summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2011-02-08 12:36:06 +0100
committerThomas Gleixner <tglx@linutronix.de>2011-02-19 12:58:17 +0100
commit6e40262ea43c4b0e3f435b3a083e4461ef921c17 (patch)
tree4548c1607f81701b77c0d63b544096cdee8ccde0 /kernel
parent2a0d6fb335d4428285dab2d254911748e6040807 (diff)
genirq: Move IRQ_MASKED to core
Keep status in sync until all users are fixed. Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/irq/chip.c28
-rw-r--r--kernel/irq/compat.h11
-rw-r--r--kernel/irq/internals.h4
-rw-r--r--kernel/irq/manage.c5
-rw-r--r--kernel/irq/migration.c2
-rw-r--r--kernel/irq/settings.h2
6 files changed, 40 insertions, 12 deletions
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index 17c87865bfb1..73b2e7e00934 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -176,6 +176,18 @@ static void irq_state_set_disabled(struct irq_desc *desc)
irq_compat_set_disabled(desc);
}
+static void irq_state_clr_masked(struct irq_desc *desc)
+{
+ desc->istate &= ~IRQS_MASKED;
+ irq_compat_clr_masked(desc);
+}
+
+static void irq_state_set_masked(struct irq_desc *desc)
+{
+ desc->istate |= IRQS_MASKED;
+ irq_compat_set_masked(desc);
+}
+
int irq_startup(struct irq_desc *desc)
{
irq_state_clr_disabled(desc);
@@ -183,7 +195,7 @@ int irq_startup(struct irq_desc *desc)
if (desc->irq_data.chip->irq_startup) {
int ret = desc->irq_data.chip->irq_startup(&desc->irq_data);
- desc->status &= ~IRQ_MASKED;
+ irq_state_clr_masked(desc);
return ret;
}
@@ -201,7 +213,7 @@ void irq_shutdown(struct irq_desc *desc)
desc->irq_data.chip->irq_disable(&desc->irq_data);
else
desc->irq_data.chip->irq_mask(&desc->irq_data);
- desc->status |= IRQ_MASKED;
+ irq_state_set_masked(desc);
}
void irq_enable(struct irq_desc *desc)
@@ -211,7 +223,7 @@ void irq_enable(struct irq_desc *desc)
desc->irq_data.chip->irq_enable(&desc->irq_data);
else
desc->irq_data.chip->irq_unmask(&desc->irq_data);
- desc->status &= ~IRQ_MASKED;
+ irq_state_clr_masked(desc);
}
void irq_disable(struct irq_desc *desc)
@@ -219,8 +231,8 @@ void irq_disable(struct irq_desc *desc)
irq_state_set_disabled(desc);
if (desc->irq_data.chip->irq_disable) {
desc->irq_data.chip->irq_disable(&desc->irq_data);
- desc->status |= IRQ_MASKED;
}
+ irq_state_set_masked(desc);
}
#ifndef CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED
@@ -352,14 +364,14 @@ static inline void mask_ack_irq(struct irq_desc *desc)
if (desc->irq_data.chip->irq_ack)
desc->irq_data.chip->irq_ack(&desc->irq_data);
}
- desc->status |= IRQ_MASKED;
+ irq_state_set_masked(desc);
}
static inline void mask_irq(struct irq_desc *desc)
{
if (desc->irq_data.chip->irq_mask) {
desc->irq_data.chip->irq_mask(&desc->irq_data);
- desc->status |= IRQ_MASKED;
+ irq_state_set_masked(desc);
}
}
@@ -367,7 +379,7 @@ static inline void unmask_irq(struct irq_desc *desc)
{
if (desc->irq_data.chip->irq_unmask) {
desc->irq_data.chip->irq_unmask(&desc->irq_data);
- desc->status &= ~IRQ_MASKED;
+ irq_state_clr_masked(desc);
}
}
@@ -583,7 +595,7 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc)
*/
if (unlikely(desc->istate & IRQS_PENDING)) {
if (!(desc->istate & IRQS_DISABLED) &&
- (desc->status & IRQ_MASKED))
+ (desc->istate & IRQS_MASKED))
unmask_irq(desc);
}
diff --git a/kernel/irq/compat.h b/kernel/irq/compat.h
index 0067a69781f4..593abecbcc44 100644
--- a/kernel/irq/compat.h
+++ b/kernel/irq/compat.h
@@ -28,6 +28,15 @@ static inline void irq_compat_clr_pending(struct irq_desc *desc)
{
desc->status &= ~IRQ_PENDING;
}
+static inline void irq_compat_set_masked(struct irq_desc *desc)
+{
+ desc->status |= IRQ_MASKED;
+}
+
+static inline void irq_compat_clr_masked(struct irq_desc *desc)
+{
+ desc->status &= ~IRQ_MASKED;
+}
#else
static inline void irq_compat_set_progress(struct irq_desc *desc) { }
static inline void irq_compat_clr_progress(struct irq_desc *desc) { }
@@ -35,5 +44,7 @@ static inline void irq_compat_set_disabled(struct irq_desc *desc) { }
static inline void irq_compat_clr_disabled(struct irq_desc *desc) { }
static inline void irq_compat_set_pending(struct irq_desc *desc) { }
static inline void irq_compat_clr_pending(struct irq_desc *desc) { }
+static inline void irq_compat_set_masked(struct irq_desc *desc) { }
+static inline void irq_compat_clr_masked(struct irq_desc *desc) { }
#endif
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h
index fdf2524437eb..3f2fcc194dcc 100644
--- a/kernel/irq/internals.h
+++ b/kernel/irq/internals.h
@@ -47,6 +47,7 @@ enum {
* IRQS_WAITING - irq is waiting
* IRQS_DISABLED - irq is disabled
* IRQS_PENDING - irq is pending and replayed later
+ * IRQS_MASKED - irq is masked
*/
enum {
IRQS_AUTODETECT = 0x00000001,
@@ -58,6 +59,7 @@ enum {
IRQS_WAITING = 0x00000080,
IRQS_DISABLED = 0x00000100,
IRQS_PENDING = 0x00000200,
+ IRQS_MASKED = 0x00000400,
};
#define irq_data_to_desc(data) container_of(data, struct irq_desc, irq_data)
@@ -142,7 +144,6 @@ static inline void print_irq_desc(unsigned int irq, struct irq_desc *desc)
}
P(IRQ_LEVEL);
- P(IRQ_MASKED);
#ifdef CONFIG_IRQ_PER_CPU
P(IRQ_PER_CPU);
#endif
@@ -156,6 +157,7 @@ static inline void print_irq_desc(unsigned int irq, struct irq_desc *desc)
PS(IRQS_WAITING);
PS(IRQS_DISABLED);
PS(IRQS_PENDING);
+ PS(IRQS_MASKED);
}
#undef P
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index ac060814a787..83fd20194e5b 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -646,8 +646,9 @@ again:
goto again;
}
- if (!(desc->istate & IRQS_DISABLED) && (desc->status & IRQ_MASKED)) {
- desc->status &= ~IRQ_MASKED;
+ if (!(desc->istate & IRQS_DISABLED) && (desc->istate & IRQS_MASKED)) {
+ irq_compat_clr_masked(desc);
+ desc->istate &= ~IRQS_MASKED;
desc->irq_data.chip->irq_unmask(&desc->irq_data);
}
raw_spin_unlock_irq(&desc->lock);
diff --git a/kernel/irq/migration.c b/kernel/irq/migration.c
index 8c68cb8555a7..6f2f98480354 100644
--- a/kernel/irq/migration.c
+++ b/kernel/irq/migration.c
@@ -69,7 +69,7 @@ void move_native_irq(int irq)
* threaded interrupt with ONESHOT set, we can end up with an
* interrupt storm.
*/
- masked = desc->status & IRQ_MASKED;
+ masked = desc->istate & IRQS_MASKED;
if (!masked)
desc->irq_data.chip->irq_mask(&desc->irq_data);
move_masked_irq(irq);
diff --git a/kernel/irq/settings.h b/kernel/irq/settings.h
index 623fcf83e7de..2cd45fd5ec8a 100644
--- a/kernel/irq/settings.h
+++ b/kernel/irq/settings.h
@@ -16,3 +16,5 @@ enum {
#define IRQ_DISABLED GOT_YOU_MORON
#undef IRQ_PENDING
#define IRQ_PENDING GOT_YOU_MORON
+#undef IRQ_MASKED
+#define IRQ_MASKED GOT_YOU_MORON
width: 0.0%;'/> -rw-r--r--Documentation/block/barrier.txt261
-rw-r--r--Documentation/block/writeback_cache_control.txt86
-rw-r--r--Documentation/cgroups/blkio-controller.txt106
-rw-r--r--Documentation/cputopology.txt23
-rw-r--r--Documentation/devices.txt6
-rw-r--r--Documentation/dynamic-debug-howto.txt22
-rw-r--r--Documentation/feature-removal-schedule.txt37
-rw-r--r--Documentation/filesystems/ocfs2.txt7
-rw-r--r--Documentation/kernel-parameters.txt32
-rw-r--r--Documentation/kprobes.txt8
-rw-r--r--Documentation/lguest/lguest.c29
-rw-r--r--Documentation/networking/bonding.txt8
-rw-r--r--Documentation/networking/can.txt12
-rw-r--r--Documentation/networking/dccp.txt29
-rw-r--r--Documentation/networking/e1000.txt373
-rw-r--r--Documentation/networking/e1000e.txt302
-rw-r--r--Documentation/networking/ip-sysctl.txt27
-rw-r--r--[-rwxr-xr-x]Documentation/networking/ixgbevf.txt40
-rw-r--r--Documentation/networking/phonet.txt56
-rw-r--r--Documentation/networking/timestamping.txt22
-rw-r--r--Documentation/pcmcia/driver-changes.txt25
-rw-r--r--Documentation/power/00-INDEX2
-rw-r--r--Documentation/power/interface.txt2
-rw-r--r--Documentation/power/opp.txt375
-rw-r--r--Documentation/power/runtime_pm.txt227
-rw-r--r--Documentation/power/s2ram.txt7
-rw-r--r--Documentation/power/swsusp.txt3
-rw-r--r--Documentation/powerpc/dts-bindings/fsl/spi.txt24
-rw-r--r--Documentation/powerpc/dts-bindings/fsl/usb.txt22
-rw-r--r--Documentation/scsi/st.txt15
-rw-r--r--Documentation/usb/proc_usb_info.txt34
-rw-r--r--Documentation/vm/page-types.c2
-rw-r--r--Documentation/workqueue.txt29
-rw-r--r--Documentation/x86/x86_64/kernel-stacks6
-rw-r--r--Kbuild1
-rw-r--r--MAINTAINERS167
-rw-r--r--Makefile22
-rw-r--r--arch/Kconfig3
-rw-r--r--arch/alpha/Kconfig1
-rw-r--r--arch/alpha/include/asm/irqflags.h67
-rw-r--r--arch/alpha/include/asm/perf_event.h5
-rw-r--r--arch/alpha/include/asm/system.h28
-rw-r--r--arch/alpha/kernel/perf_event.c128
-rw-r--r--arch/alpha/kernel/signal.c2
-rw-r--r--arch/alpha/kernel/time.c30
-rw-r--r--arch/arm/Kconfig91
-rw-r--r--arch/arm/Kconfig.debug19
-rw-r--r--arch/arm/Makefile11
-rw-r--r--arch/arm/common/gic.c14
-rw-r--r--arch/arm/common/pl330.c7
-rw-r--r--arch/arm/common/sa1111.c2
-rw-r--r--arch/arm/configs/at91sam9g20ek_defconfig1
-rw-r--r--arch/arm/configs/kirkwood_defconfig1
-rw-r--r--arch/arm/configs/mx27_defconfig15
-rw-r--r--arch/arm/configs/mx31pdk_defconfig44
-rw-r--r--arch/arm/configs/mx3_defconfig2
-rw-r--r--arch/arm/configs/mx51_defconfig9
-rw-r--r--arch/arm/configs/realview-smp_defconfig15
-rw-r--r--arch/arm/configs/realview_defconfig15
-rw-r--r--arch/arm/configs/s5p64x0_defconfig (renamed from arch/arm/configs/s5p6440_defconfig)3
-rw-r--r--arch/arm/configs/u300_defconfig37
-rw-r--r--arch/arm/include/asm/assembler.h27
-rw-r--r--arch/arm/include/asm/cacheflush.h65
-rw-r--r--arch/arm/include/asm/cachetype.h8
-rw-r--r--arch/arm/include/asm/elf.h4
-rw-r--r--arch/arm/include/asm/ftrace.h20
-rw-r--r--arch/arm/include/asm/hardware/coresight.h34
-rw-r--r--arch/arm/include/asm/hw_breakpoint.h133
-rw-r--r--arch/arm/include/asm/hw_irq.h2
-rw-r--r--arch/arm/include/asm/io.h1
-rw-r--r--arch/arm/include/asm/ioctls.h83
-rw-r--r--arch/arm/include/asm/irqflags.h145
-rw-r--r--arch/arm/include/asm/mach/arch.h9
-rw-r--r--arch/arm/include/asm/mmu_context.h29
-rw-r--r--arch/arm/include/asm/module.h31
-rw-r--r--arch/arm/include/asm/perf_event.h12
-rw-r--r--arch/arm/include/asm/pgtable.h26
-rw-r--r--arch/arm/include/asm/processor.h4
-rw-r--r--arch/arm/include/asm/ptrace.h2
-rw-r--r--arch/arm/include/asm/seccomp.h11
-rw-r--r--arch/arm/include/asm/smp_mpidr.h17
-rw-r--r--arch/arm/include/asm/smp_plat.h25
-rw-r--r--arch/arm/include/asm/system.h6
-rw-r--r--arch/arm/include/asm/thread_info.h2
-rw-r--r--arch/arm/include/asm/tlbflush.h36
-rw-r--r--arch/arm/kernel/Makefile1
-rw-r--r--arch/arm/kernel/armksyms.c2
-rw-r--r--arch/arm/kernel/asm-offsets.c2
-rw-r--r--arch/arm/kernel/debug.S35
-rw-r--r--arch/arm/kernel/entry-armv.S11
-rw-r--r--arch/arm/kernel/entry-common.S78
-rw-r--r--arch/arm/kernel/etm.c16
-rw-r--r--arch/arm/kernel/ftrace.c188
-rw-r--r--arch/arm/kernel/head-common.S305
-rw-r--r--arch/arm/kernel/head-nommu.S5
-rw-r--r--arch/arm/kernel/head.S323
-rw-r--r--arch/arm/kernel/hw_breakpoint.c849
-rw-r--r--arch/arm/kernel/irq.c10
-rw-r--r--arch/arm/kernel/kprobes-decode.c7
-rw-r--r--arch/arm/kernel/module.c68
-rw-r--r--arch/arm/kernel/perf_event.c212
-rw-r--r--arch/arm/kernel/process.c45
-rw-r--r--arch/arm/kernel/ptrace.c239
-rw-r--r--arch/arm/kernel/setup.c46
-rw-r--r--arch/arm/kernel/smp.c66
-rw-r--r--arch/arm/kernel/unwind.c2
-rw-r--r--arch/arm/kernel/vmlinux.lds.S39
-rw-r--r--arch/arm/mach-aaec2000/aaed2000.c2
-rw-r--r--arch/arm/mach-aaec2000/include/mach/debug-macro.S10
-rw-r--r--arch/arm/mach-aaec2000/include/mach/vmalloc.h2
-rw-r--r--arch/arm/mach-at91/Kconfig15
-rw-r--r--arch/arm/mach-at91/Makefile4
-rw-r--r--arch/arm/mach-at91/board-1arm.c2
-rw-r--r--arch/arm/mach-at91/board-afeb-9260v1.c2
-rw-r--r--arch/arm/mach-at91/board-at572d940hf_ek.c4
-rw-r--r--arch/arm/mach-at91/board-cam60.c2
-rw-r--r--arch/arm/mach-at91/board-cap9adk.c2
-rw-r--r--arch/arm/mach-at91/board-carmeva.c2
-rw-r--r--arch/arm/mach-at91/board-cpu9krea.c2
-rw-r--r--arch/arm/mach-at91/board-cpuat91.c2
-rw-r--r--arch/arm/mach-at91/board-csb337.c2
-rw-r--r--arch/arm/mach-at91/board-csb637.c2
-rw-r--r--arch/arm/mach-at91/board-dk.c2
-rw-r--r--arch/arm/mach-at91/board-eb9200.c2
-rw-r--r--arch/arm/mach-at91/board-ecbat91.c2
-rw-r--r--arch/arm/mach-at91/board-eco920.c2
-rw-r--r--arch/arm/mach-at91/board-ek.c2
-rw-r--r--arch/arm/mach-at91/board-flexibity.c162
-rw-r--r--arch/arm/mach-at91/board-kafa.c2
-rw-r--r--arch/arm/mach-at91/board-kb9202.c2
-rw-r--r--arch/arm/mach-at91/board-neocore926.c2
-rw-r--r--arch/arm/mach-at91/board-picotux200.c2
-rw-r--r--arch/arm/mach-at91/board-qil-a9260.c2
-rw-r--r--arch/arm/mach-at91/board-sam9-l9260.c2
-rw-r--r--arch/arm/mach-at91/board-sam9260ek.c2
-rw-r--r--arch/arm/mach-at91/board-sam9261ek.c2
-rw-r--r--arch/arm/mach-at91/board-sam9263ek.c2
-rw-r--r--arch/arm/mach-at91/board-sam9g20ek-2slot-mmc.c329
-rw-r--r--arch/arm/mach-at91/board-sam9g20ek.c74
-rw-r--r--arch/arm/mach-at91/board-sam9m10g45ek.c6
-rw-r--r--arch/arm/mach-at91/board-sam9rlek.c2
-rw-r--r--arch/arm/mach-at91/board-snapper9260.c2
-rw-r--r--arch/arm/mach-at91/board-stamp9g20.c4
-rw-r--r--arch/arm/mach-at91/board-usb-a9260.c2
-rw-r--r--arch/arm/mach-at91/board-usb-a9263.c2
-rw-r--r--arch/arm/mach-at91/board-yl-9200.c2
-rw-r--r--arch/arm/mach-at91/include/mach/at91x40.h6
-rw-r--r--arch/arm/mach-at91/include/mach/debug-macro.S8
-rw-r--r--arch/arm/mach-at91/include/mach/system.h11
-rw-r--r--arch/arm/mach-bcmring/arch.c2
-rw-r--r--arch/arm/mach-bcmring/dma.c4
-rw-r--r--arch/arm/mach-bcmring/include/mach/vmalloc.h2
-rw-r--r--arch/arm/mach-bcmring/irq.c6
-rw-r--r--arch/arm/mach-clps711x/autcpu12.c2
-rw-r--r--arch/arm/mach-clps711x/cdb89712.c2
-rw-r--r--arch/arm/mach-clps711x/ceiva.c2
-rw-r--r--arch/arm/mach-clps711x/clep7312.c2
-rw-r--r--arch/arm/mach-clps711x/edb7211-arch.c2
-rw-r--r--arch/arm/mach-clps711x/fortunet.c2
-rw-r--r--arch/arm/mach-clps711x/include/mach/debug-macro.S12
-rw-r--r--arch/arm/mach-clps711x/include/mach/vmalloc.h2
-rw-r--r--arch/arm/mach-clps711x/p720t.c2
-rw-r--r--arch/arm/mach-cns3xxx/cns3420vb.c2
-rw-r--r--arch/arm/mach-cns3xxx/include/mach/debug-macro.S10
-rw-r--r--arch/arm/mach-davinci/board-da830-evm.c2
-rw-r--r--arch/arm/mach-davinci/board-da850-evm.c2
-rw-r--r--arch/arm/mach-davinci/board-dm355-evm.c2
-rw-r--r--arch/arm/mach-davinci/board-dm355-leopard.c2
-rw-r--r--arch/arm/mach-davinci/board-dm365-evm.c2
-rw-r--r--arch/arm/mach-davinci/board-dm644x-evm.c2
-rw-r--r--arch/arm/mach-davinci/board-dm646x-evm.c4
-rw-r--r--arch/arm/mach-davinci/board-neuros-osd2.c2
-rw-r--r--arch/arm/mach-davinci/board-sffsdr.c2
-rw-r--r--arch/arm/mach-davinci/board-tnetv107x-evm.c2
-rw-r--r--arch/arm/mach-davinci/include/mach/debug-macro.S46
-rw-r--r--arch/arm/mach-dove/dove-db-setup.c2
-rw-r--r--arch/arm/mach-dove/include/mach/debug-macro.S11
-rw-r--r--arch/arm/mach-ebsa110/core.c2
-rw-r--r--arch/arm/mach-ebsa110/include/mach/debug-macro.S7
-rw-r--r--arch/arm/mach-ebsa110/include/mach/vmalloc.h2
-rw-r--r--arch/arm/mach-ep93xx/adssphere.c2
-rw-r--r--arch/arm/mach-ep93xx/dma-m2p.c2
-rw-r--r--arch/arm/mach-ep93xx/edb93xx.c16
-rw-r--r--arch/arm/mach-ep93xx/gesbc9312.c2
-rw-r--r--arch/arm/mach-ep93xx/include/mach/debug-macro.S11
-rw-r--r--arch/arm/mach-ep93xx/micro9.c8
-rw-r--r--arch/arm/mach-ep93xx/simone.c2
-rw-r--r--arch/arm/mach-ep93xx/snappercl15.c2
-rw-r--r--arch/arm/mach-ep93xx/ts72xx.c2
-rw-r--r--arch/arm/mach-footbridge/cats-hw.c2
-rw-r--r--arch/arm/mach-footbridge/ebsa285.c2
-rw-r--r--arch/arm/mach-footbridge/include/mach/debug-macro.S22
-rw-r--r--arch/arm/mach-footbridge/include/mach/vmalloc.h2
-rw-r--r--arch/arm/mach-footbridge/netwinder-hw.c2
-rw-r--r--arch/arm/mach-footbridge/personal.c2
-rw-r--r--arch/arm/mach-gemini/board-nas4220b.c2
-rw-r--r--arch/arm/mach-gemini/board-rut1xx.c2
-rw-r--r--arch/arm/mach-gemini/board-wbd111.c2
-rw-r--r--arch/arm/mach-gemini/board-wbd222.c2
-rw-r--r--arch/arm/mach-gemini/include/mach/debug-macro.S8
-rw-r--r--arch/arm/mach-h720x/h7201-eval.c2
-rw-r--r--arch/arm/mach-h720x/h7202-eval.c2
-rw-r--r--arch/arm/mach-h720x/include/mach/debug-macro.S10
-rw-r--r--arch/arm/mach-h720x/include/mach/vmalloc.h2
-rw-r--r--arch/arm/mach-imx/Kconfig15
-rw-r--r--arch/arm/mach-imx/Makefile1
-rw-r--r--arch/arm/mach-imx/clock-imx1.c2
-rw-r--r--arch/arm/mach-imx/clock-imx21.c6
-rw-r--r--arch/arm/mach-imx/clock-imx27.c48
-rw-r--r--arch/arm/mach-imx/devices-imx1.h14
-rw-r--r--arch/arm/mach-imx/devices-imx21.h36
-rw-r--r--arch/arm/mach-imx/devices-imx27.h51
-rw-r--r--arch/arm/mach-imx/devices.c56
-rw-r--r--arch/arm/mach-imx/devices.h3
-rw-r--r--arch/arm/mach-imx/eukrea_mbimx27-baseboard.c8
-rw-r--r--arch/arm/mach-imx/mach-cpuimx27.c8
-rw-r--r--arch/arm/mach-imx/mach-imx27_visstrim_m10.c261
-rw-r--r--arch/arm/mach-imx/mach-imx27lite.c10
-rw-r--r--arch/arm/mach-imx/mach-mx1ads.c8
-rw-r--r--arch/arm/mach-imx/mach-mx21ads.c4
-rw-r--r--arch/arm/mach-imx/mach-mx27_3ds.c10
-rw-r--r--arch/arm/mach-imx/mach-mx27ads.c8
-rw-r--r--arch/arm/mach-imx/mach-mxt_td60.c15
-rw-r--r--arch/arm/mach-imx/mach-pca100.c17
-rw-r--r--arch/arm/mach-imx/mach-pcm038.c10
-rw-r--r--arch/arm/mach-imx/mach-scb9328.c4
-rw-r--r--arch/arm/mach-imx/pcm970-baseboard.c4
-rw-r--r--arch/arm/mach-integrator/include/mach/debug-macro.S10
-rw-r--r--arch/arm/mach-integrator/include/mach/vmalloc.h2
-rw-r--r--arch/arm/mach-integrator/integrator_ap.c2
-rw-r--r--arch/arm/mach-integrator/integrator_cp.c2
-rw-r--r--arch/arm/mach-iop13xx/include/mach/debug-macro.S16
-rw-r--r--arch/arm/mach-iop13xx/iq81340mc.c2
-rw-r--r--arch/arm/mach-iop13xx/iq81340sc.c2
-rw-r--r--arch/arm/mach-iop13xx/msi.c8
-rw-r--r--arch/arm/mach-iop32x/em7210.c2
-rw-r--r--arch/arm/mach-iop32x/glantank.c2
-rw-r--r--arch/arm/mach-iop32x/include/mach/debug-macro.S7
-rw-r--r--arch/arm/mach-iop32x/iq31244.c4
-rw-r--r--arch/arm/mach-iop32x/iq80321.c2
-rw-r--r--arch/arm/mach-iop32x/n2100.c2
-rw-r--r--arch/arm/mach-iop33x/include/mach/debug-macro.S12
-rw-r--r--arch/arm/mach-iop33x/iq80331.c2
-rw-r--r--arch/arm/mach-iop33x/iq80332.c2
-rw-r--r--arch/arm/mach-ixp2000/enp2611.c2
-rw-r--r--arch/arm/mach-ixp2000/include/mach/debug-macro.S14
-rw-r--r--arch/arm/mach-ixp2000/ixdp2400.c2
-rw-r--r--arch/arm/mach-ixp2000/ixdp2800.c2
-rw-r--r--arch/arm/mach-ixp2000/ixdp2x01.c6
-rw-r--r--arch/arm/mach-ixp23xx/espresso.c2
-rw-r--r--arch/arm/mach-ixp23xx/include/mach/debug-macro.S11
-rw-r--r--arch/arm/mach-ixp23xx/ixdp2351.c2
-rw-r--r--arch/arm/mach-ixp23xx/roadrunner.c2
-rw-r--r--arch/arm/mach-ixp4xx/avila-setup.c4
-rw-r--r--arch/arm/mach-ixp4xx/coyote-setup.c4
-rw-r--r--arch/arm/mach-ixp4xx/dsmg600-setup.c2
-rw-r--r--arch/arm/mach-ixp4xx/fsg-setup.c2
-rw-r--r--arch/arm/mach-ixp4xx/gateway7001-setup.c2
-rw-r--r--arch/arm/mach-ixp4xx/goramo_mlr.c2
-rw-r--r--arch/arm/mach-ixp4xx/gtwx5715-setup.c2
-rw-r--r--arch/arm/mach-ixp4xx/include/mach/debug-macro.S16
-rw-r--r--arch/arm/mach-ixp4xx/ixdp425-setup.c8
-rw-r--r--arch/arm/mach-ixp4xx/nas100d-setup.c2
-rw-r--r--arch/arm/mach-ixp4xx/nslu2-setup.c2
-rw-r--r--arch/arm/mach-ixp4xx/vulcan-setup.c2
-rw-r--r--arch/arm/mach-ixp4xx/wg302v2-setup.c2
-rw-r--r--arch/arm/mach-kirkwood/Kconfig12
-rw-r--r--arch/arm/mach-kirkwood/Makefile12
-rw-r--r--arch/arm/mach-kirkwood/d2net_v2-setup.c229
-rw-r--r--arch/arm/mach-kirkwood/db88f6281-bp-setup.c2
-rw-r--r--arch/arm/mach-kirkwood/dockstar-setup.c110
-rw-r--r--arch/arm/mach-kirkwood/guruplug-setup.c2
-rw-r--r--arch/arm/mach-kirkwood/include/mach/debug-macro.S11
-rw-r--r--arch/arm/mach-kirkwood/include/mach/leds-netxbig.h55
-rw-r--r--arch/arm/mach-kirkwood/lacie_v2-common.c127
-rw-r--r--arch/arm/mach-kirkwood/lacie_v2-common.h18
-rw-r--r--arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c2
-rw-r--r--arch/arm/mach-kirkwood/netspace_v2-setup.c128
-rw-r--r--arch/arm/mach-kirkwood/netxbig_v2-setup.c273
-rw-r--r--arch/arm/mach-kirkwood/openrd-setup.c107
-rw-r--r--arch/arm/mach-kirkwood/rd88f6192-nas-setup.c2
-rw-r--r--arch/arm/mach-kirkwood/rd88f6281-setup.c2
-rw-r--r--arch/arm/mach-kirkwood/sheevaplug-setup.c4
-rw-r--r--arch/arm/mach-kirkwood/t5325-setup.c2
-rw-r--r--arch/arm/mach-kirkwood/ts219-setup.c2
-rw-r--r--arch/arm/mach-kirkwood/ts41x-setup.c2
-rw-r--r--arch/arm/mach-ks8695/board-acs5k.c2
-rw-r--r--arch/arm/mach-ks8695/board-dsm320.c2
-rw-r--r--arch/arm/mach-ks8695/board-micrel.c2
-rw-r--r--arch/arm/mach-ks8695/include/mach/debug-macro.S8
-rw-r--r--arch/arm/mach-l7200/include/mach/debug-macro.S38
-rw-r--r--arch/arm/mach-lh7a40x/arch-kev7a400.c2
-rw-r--r--arch/arm/mach-lh7a40x/arch-lpd7a40x.c4
-rw-r--r--arch/arm/mach-lh7a40x/include/mach/debug-macro.S10
-rw-r--r--arch/arm/mach-loki/include/mach/debug-macro.S11
-rw-r--r--arch/arm/mach-loki/lb88rc8480-setup.c2
-rw-r--r--arch/arm/mach-lpc32xx/include/mach/debug-macro.S8
-rw-r--r--arch/arm/mach-lpc32xx/phy3250.c9
-rw-r--r--arch/arm/mach-mmp/Kconfig7
-rw-r--r--arch/arm/mach-mmp/Makefile1
-rw-r--r--arch/arm/mach-mmp/aspenite.c94
-rw-r--r--arch/arm/mach-mmp/avengers_lite.c2
-rw-r--r--arch/arm/mach-mmp/common.c10
-rw-r--r--arch/arm/mach-mmp/flint.c6
-rw-r--r--arch/arm/mach-mmp/include/mach/cputype.h49
-rw-r--r--arch/arm/mach-mmp/include/mach/debug-macro.S11
-rw-r--r--arch/arm/mach-mmp/include/mach/irqs.h4
-rw-r--r--arch/arm/mach-mmp/include/mach/mfp-pxa168.h7
-rw-r--r--arch/arm/mach-mmp/include/mach/pxa168.h20
-rw-r--r--arch/arm/mach-mmp/include/mach/regs-apmu.h12
-rw-r--r--arch/arm/mach-mmp/include/mach/teton_bga.h27
-rw-r--r--arch/arm/mach-mmp/jasper.c7
-rw-r--r--arch/arm/mach-mmp/pxa168.c16
-rw-r--r--arch/arm/mach-mmp/tavorevb.c2
-rw-r--r--arch/arm/mach-mmp/teton_bga.c89
-rw-r--r--arch/arm/mach-mmp/ttc_dkb.c6
-rw-r--r--arch/arm/mach-msm/Kconfig55
-rw-r--r--arch/arm/mach-msm/Makefile21
-rw-r--r--arch/arm/mach-msm/board-halibut.c2
-rw-r--r--arch/arm/mach-msm/board-mahimahi.c2
-rw-r--r--arch/arm/mach-msm/board-msm7x27.c8
-rw-r--r--arch/arm/mach-msm/board-msm7x30.c28
-rw-r--r--arch/arm/mach-msm/board-msm8x60.c100
-rw-r--r--arch/arm/mach-msm/board-qsd8x50.c50
-rw-r--r--arch/arm/mach-msm/board-sapphire.c2
-rw-r--r--arch/arm/mach-msm/board-trout.c2
-rw-r--r--arch/arm/mach-msm/clock-dummy.c54
-rw-r--r--arch/arm/mach-msm/devices-msm7x30.c5
-rw-r--r--arch/arm/mach-msm/devices-msm8x60-iommu.c883
-rw-r--r--arch/arm/mach-msm/devices-qsd8x50.c5
-rw-r--r--arch/arm/mach-msm/gpio.c409
-rw-r--r--arch/arm/mach-msm/gpio_hw.h278
-rw-r--r--arch/arm/mach-msm/gpiomux-7x30.c38
-rw-r--r--arch/arm/mach-msm/gpiomux-8x50.c28
-rw-r--r--arch/arm/mach-msm/gpiomux-8x60.c19
-rw-r--r--arch/arm/mach-msm/gpiomux-v1.c33
-rw-r--r--arch/arm/mach-msm/gpiomux-v1.h67
-rw-r--r--arch/arm/mach-msm/gpiomux-v2.c25
-rw-r--r--arch/arm/mach-msm/gpiomux-v2.h61
-rw-r--r--arch/arm/mach-msm/gpiomux.c96
-rw-r--r--arch/arm/mach-msm/gpiomux.h114
-rw-r--r--arch/arm/mach-msm/include/mach/board.h2
-rw-r--r--arch/arm/mach-msm/include/mach/debug-macro.S22
-rw-r--r--arch/arm/mach-msm/include/mach/dma.h10
-rw-r--r--arch/arm/mach-msm/include/mach/entry-macro-qgic.S88
-rw-r--r--arch/arm/mach-msm/include/mach/entry-macro-vic.S37
-rw-r--r--arch/arm/mach-msm/include/mach/entry-macro.S43
-rw-r--r--arch/arm/mach-msm/include/mach/gpio.h123
-rw-r--r--arch/arm/mach-msm/include/mach/io.h1
-rw-r--r--arch/arm/mach-msm/include/mach/iommu.h103
-rw-r--r--arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h1871
-rw-r--r--arch/arm/mach-msm/include/mach/irqs-8x60.h253
-rw-r--r--arch/arm/mach-msm/include/mach/irqs.h2
-rw-r--r--arch/arm/mach-msm/include/mach/memory.h2
-rw-r--r--arch/arm/mach-msm/include/mach/msm_iomap-8x60.h101
-rw-r--r--arch/arm/mach-msm/include/mach/msm_iomap.h4
-rw-r--r--arch/arm/mach-msm/include/mach/smp.h39
-rw-r--r--arch/arm/mach-msm/include/mach/vmalloc.h2
-rw-r--r--arch/arm/mach-msm/io.c15
-rw-r--r--arch/arm/mach-msm/iommu.c597
-rw-r--r--arch/arm/mach-msm/iommu_dev.c374
-rw-r--r--arch/arm/mach-msm/last_radio_log.c3
-rw-r--r--arch/arm/mach-msm/smd_debug.c1
-rw-r--r--arch/arm/mach-msm/timer.c23
-rw-r--r--arch/arm/mach-mv78xx0/buffalo-wxl-setup.c2
-rw-r--r--arch/arm/mach-mv78xx0/db78x00-bp-setup.c2
-rw-r--r--arch/arm/mach-mv78xx0/include/mach/debug-macro.S11
-rw-r--r--arch/arm/mach-mv78xx0/rd78x00-masa-setup.c2
-rw-r--r--arch/arm/mach-mx25/Kconfig6
-rw-r--r--arch/arm/mach-mx25/clock.c34
-rw-r--r--arch/arm/mach-mx25/devices-imx25.h61
-rw-r--r--arch/arm/mach-mx25/devices.c58
-rw-r--r--arch/arm/mach-mx25/devices.h3
-rw-r--r--arch/arm/mach-mx25/eukrea_mbimxsd-baseboard.c44
-rw-r--r--arch/arm/mach-mx25/mach-cpuimx25.c21
-rw-r--r--arch/arm/mach-mx25/mach-mx25_3ds.c7
-rw-r--r--arch/arm/mach-mx3/Kconfig11
-rw-r--r--arch/arm/mach-mx3/Makefile1
-rw-r--r--arch/arm/mach-mx3/clock-imx31.c10
-rw-r--r--arch/arm/mach-mx3/clock-imx35.c28
-rw-r--r--arch/arm/mach-mx3/cpu.c47
-rw-r--r--arch/arm/mach-mx3/devices-imx31.h49
-rw-r--r--arch/arm/mach-mx3/devices-imx35.h48
-rw-r--r--arch/arm/mach-mx3/devices.c63
-rw-r--r--arch/arm/mach-mx3/devices.h4
-rw-r--r--arch/arm/mach-mx3/eukrea_mbimxsd-baseboard.c59
-rw-r--r--arch/arm/mach-mx3/mach-armadillo5x0.c2
-rw-r--r--arch/arm/mach-mx3/mach-cpuimx35.c55
-rw-r--r--arch/arm/mach-mx3/mach-kzm_arm11_01.c2
-rw-r--r--arch/arm/mach-mx3/mach-mx31_3ds.c2
-rw-r--r--arch/arm/mach-mx3/mach-mx31ads.c11
-rw-r--r--arch/arm/mach-mx3/mach-mx31lilly.c2
-rw-r--r--arch/arm/mach-mx3/mach-mx31lite.c2
-rw-r--r--arch/arm/mach-mx3/mach-mx31moboard.c2
-rw-r--r--arch/arm/mach-mx3/mach-mx35_3ds.c53
-rw-r--r--arch/arm/mach-mx3/mach-pcm037.c2
-rw-r--r--arch/arm/mach-mx3/mach-pcm037_eet.c3
-rw-r--r--arch/arm/mach-mx3/mach-pcm043.c17
-rw-r--r--arch/arm/mach-mx3/mach-qong.c2
-rw-r--r--arch/arm/mach-mx3/mm.c18
-rw-r--r--arch/arm/mach-mx5/Kconfig42
-rw-r--r--arch/arm/mach-mx5/Makefile3
-rw-r--r--arch/arm/mach-mx5/board-cpuimx51.c25
-rw-r--r--arch/arm/mach-mx5/board-cpuimx51sd.c331
-rw-r--r--arch/arm/mach-mx5/board-mx51_3ds.c44
-rw-r--r--arch/arm/mach-mx5/board-mx51_babbage.c74
-rw-r--r--arch/arm/mach-mx5/board-mx51_efikamx.c119
-rw-r--r--arch/arm/mach-mx5/clock-mx51.c391
-rw-r--r--arch/arm/mach-mx5/cpu.c19
-rw-r--r--arch/arm/mach-mx5/devices-imx51.h42
-rw-r--r--arch/arm/mach-mx5/devices.c114
-rw-r--r--arch/arm/mach-mx5/devices.h6
-rw-r--r--arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c30
-rw-r--r--arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c166
-rw-r--r--arch/arm/mach-mxc91231/magx-zn5.c2
-rw-r--r--arch/arm/mach-netx/include/mach/debug-macro.S10
-rw-r--r--arch/arm/mach-netx/include/mach/vmalloc.h2
-rw-r--r--arch/arm/mach-netx/nxdb500.c2
-rw-r--r--arch/arm/mach-netx/nxdkn.c2
-rw-r--r--arch/arm/mach-netx/nxeb500hmi.c2
-rw-r--r--arch/arm/mach-nomadik/board-nhk8815.c2
-rw-r--r--arch/arm/mach-nomadik/include/mach/debug-macro.S12
-rw-r--r--arch/arm/mach-ns9xxx/include/mach/debug-macro.S8
-rw-r--r--arch/arm/mach-nuc93x/mach-nuc932evb.c2
-rw-r--r--arch/arm/mach-omap1/board-ams-delta.c2
-rw-r--r--arch/arm/mach-omap1/board-fsample.c2
-rw-r--r--arch/arm/mach-omap1/board-generic.c2
-rw-r--r--arch/arm/mach-omap1/board-h2.c2
-rw-r--r--arch/arm/mach-omap1/board-h3.c2
-rw-r--r--arch/arm/mach-omap1/board-htcherald.c2
-rw-r--r--arch/arm/mach-omap1/board-innovator.c2
-rw-r--r--arch/arm/mach-omap1/board-nokia770.c2
-rw-r--r--arch/arm/mach-omap1/board-osk.c2
-rw-r--r--arch/arm/mach-omap1/board-palmte.c2
-rw-r--r--arch/arm/mach-omap1/board-palmtt.c2
-rw-r--r--arch/arm/mach-omap1/board-palmz71.c2
-rw-r--r--arch/arm/mach-omap1/board-perseus2.c2
-rw-r--r--arch/arm/mach-omap1/board-sx1.c2
-rw-r--r--arch/arm/mach-omap1/board-voiceblue.c2
-rw-r--r--arch/arm/mach-omap1/include/mach/debug-macro.S68
-rw-r--r--arch/arm/mach-omap1/include/mach/vmalloc.h2
-rw-r--r--arch/arm/mach-omap2/board-2430sdp.c2
-rw-r--r--arch/arm/mach-omap2/board-3430sdp.c2
-rw-r--r--arch/arm/mach-omap2/board-3630sdp.c2
-rw-r--r--arch/arm/mach-omap2/board-4430sdp.c2
-rw-r--r--arch/arm/mach-omap2/board-am3517evm.c32
-rw-r--r--arch/arm/mach-omap2/board-apollon.c2
-rw-r--r--arch/arm/mach-omap2/board-cm-t35.c2
-rw-r--r--arch/arm/mach-omap2/board-devkit8000.c2
-rw-r--r--arch/arm/mach-omap2/board-generic.c2
-rw-r--r--arch/arm/mach-omap2/board-h4.c2
-rw-r--r--arch/arm/mach-omap2/board-igep0020.c2
-rw-r--r--arch/arm/mach-omap2/board-ldp.c2
-rw-r--r--arch/arm/mach-omap2/board-n8x0.c6
-rw-r--r--arch/arm/mach-omap2/board-omap3beagle.c2
-rw-r--r--arch/arm/mach-omap2/board-omap3evm.c2
-rw-r--r--arch/arm/mach-omap2/board-omap3pandora.c4
-rw-r--r--arch/arm/mach-omap2/board-omap3stalker.c2
-rw-r--r--arch/arm/mach-omap2/board-omap3touchbook.c2
-rw-r--r--arch/arm/mach-omap2/board-omap4panda.c2
-rw-r--r--arch/arm/mach-omap2/board-overo.c2
-rw-r--r--arch/arm/mach-omap2/board-rx51-peripherals.c2
-rw-r--r--arch/arm/mach-omap2/board-rx51.c2
-rw-r--r--arch/arm/mach-omap2/board-zoom-peripherals.c54
-rw-r--r--arch/arm/mach-omap2/board-zoom2.c2
-rw-r--r--arch/arm/mach-omap2/board-zoom3.c2
-rw-r--r--arch/arm/mach-omap2/include/mach/debug-macro.S127
-rw-r--r--arch/arm/mach-omap2/include/mach/vmalloc.h2
-rw-r--r--arch/arm/mach-omap2/usb-musb.c4
-rw-r--r--arch/arm/mach-orion5x/d2net-setup.c4
-rw-r--r--arch/arm/mach-orion5x/db88f5281-setup.c2
-rw-r--r--arch/arm/mach-orion5x/dns323-setup.c2
-rw-r--r--arch/arm/mach-orion5x/edmini_v2-setup.c2
-rw-r--r--arch/arm/mach-orion5x/include/mach/debug-macro.S11
-rw-r--r--arch/arm/mach-orion5x/kurobox_pro-setup.c4
-rw-r--r--arch/arm/mach-orion5x/ls_hgl-setup.c2
-rw-r--r--arch/arm/mach-orion5x/lsmini-setup.c2
-rw-r--r--arch/arm/mach-orion5x/mss2-setup.c2
-rw-r--r--arch/arm/mach-orion5x/mv2120-setup.c2
-rw-r--r--arch/arm/mach-orion5x/net2big-setup.c2
-rw-r--r--arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c2
-rw-r--r--arch/arm/mach-orion5x/rd88f5181l-ge-setup.c2
-rw-r--r--arch/arm/mach-orion5x/rd88f5182-setup.c2
-rw-r--r--arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c2
-rw-r--r--arch/arm/mach-orion5x/terastation_pro2-setup.c2
-rw-r--r--arch/arm/mach-orion5x/ts209-setup.c2
-rw-r--r--arch/arm/mach-orion5x/ts409-setup.c2
-rw-r--r--arch/arm/mach-orion5x/ts78xx-setup.c2
-rw-r--r--arch/arm/mach-orion5x/wnr854t-setup.c2
-rw-r--r--arch/arm/mach-orion5x/wrt350n-v2-setup.c2
-rw-r--r--arch/arm/mach-pnx4008/core.c2
-rw-r--r--arch/arm/mach-pnx4008/include/mach/debug-macro.S10
-rw-r--r--arch/arm/mach-pnx4008/include/mach/vmalloc.h2
-rw-r--r--arch/arm/mach-pxa/Kconfig27
-rw-r--r--arch/arm/mach-pxa/Makefile3
-rw-r--r--arch/arm/mach-pxa/balloon3.c107
-rw-r--r--arch/arm/mach-pxa/capc7117.c2
-rw-r--r--arch/arm/mach-pxa/cm-x2xx.c6
-rw-r--r--arch/arm/mach-pxa/cm-x300.c79
-rw-r--r--arch/arm/mach-pxa/colibri-pxa270.c4
-rw-r--r--arch/arm/mach-pxa/colibri-pxa300.c2
-rw-r--r--arch/arm/mach-pxa/colibri-pxa320.c2
-rw-r--r--arch/arm/mach-pxa/corgi.c6
-rw-r--r--arch/arm/mach-pxa/cpufreq-pxa3xx.c5
-rw-r--r--arch/arm/mach-pxa/csb726.c2
-rw-r--r--arch/arm/mach-pxa/devices.c30
-rw-r--r--arch/arm/mach-pxa/devices.h1
-rw-r--r--arch/arm/mach-pxa/em-x270.c6
-rw-r--r--arch/arm/mach-pxa/eseries.c19
-rw-r--r--arch/arm/mach-pxa/ezx.c22
-rw-r--r--arch/arm/mach-pxa/generic.c6
-rw-r--r--arch/arm/mach-pxa/generic.h2
-rw-r--r--arch/arm/mach-pxa/gumstix.c2
-rw-r--r--arch/arm/mach-pxa/h5000.c2
-rw-r--r--arch/arm/mach-pxa/himalaya.c2
-rw-r--r--arch/arm/mach-pxa/hx4700.c3
-rw-r--r--arch/arm/mach-pxa/icontrol.c2
-rw-r--r--arch/arm/mach-pxa/idp.c2
-rw-r--r--arch/arm/mach-pxa/include/mach/balloon3.h2
-rw-r--r--arch/arm/mach-pxa/include/mach/debug-macro.S10
-rw-r--r--arch/arm/mach-pxa/include/mach/eseries-irq.h1
-rw-r--r--arch/arm/mach-pxa/include/mach/hx4700.h1
-rw-r--r--arch/arm/mach-pxa/include/mach/irqs.h42
-rw-r--r--arch/arm/mach-pxa/include/mach/littleton.h2
-rw-r--r--arch/arm/mach-pxa/include/mach/lpd270.h1
-rw-r--r--arch/arm/mach-pxa/include/mach/lubbock.h3
-rw-r--r--arch/arm/mach-pxa/include/mach/magician.h2
-rw-r--r--arch/arm/mach-pxa/include/mach/mainstone.h2
-rw-r--r--arch/arm/mach-pxa/include/mach/mfp-pxa930.h7
-rw-r--r--arch/arm/mach-pxa/include/mach/pcm027.h2
-rw-r--r--arch/arm/mach-pxa/include/mach/poodle.h2
-rw-r--r--arch/arm/mach-pxa/include/mach/pxa3xx-u2d.h35
-rw-r--r--arch/arm/mach-pxa/include/mach/tosa.h1
-rw-r--r--arch/arm/mach-pxa/include/mach/zeus.h2
-rw-r--r--arch/arm/mach-pxa/include/mach/zylonite.h2
-rw-r--r--arch/arm/mach-pxa/littleton.c5
-rw-r--r--arch/arm/mach-pxa/lpd270.c3
-rw-r--r--arch/arm/mach-pxa/lubbock.c5
-rw-r--r--arch/arm/mach-pxa/magician.c3
-rw-r--r--arch/arm/mach-pxa/mainstone.c5
-rw-r--r--arch/arm/mach-pxa/mioa701.c4
-rw-r--r--arch/arm/mach-pxa/mp900.c2
-rw-r--r--arch/arm/mach-pxa/palmld.c4
-rw-r--r--arch/arm/mach-pxa/palmt5.c4
-rw-r--r--arch/arm/mach-pxa/palmtc.c2
-rw-r--r--arch/arm/mach-pxa/palmte2.c2
-rw-r--r--arch/arm/mach-pxa/palmtreo.c6
-rw-r--r--arch/arm/mach-pxa/palmtx.c4
-rw-r--r--arch/arm/mach-pxa/palmz72.c4
-rw-r--r--arch/arm/mach-pxa/pcm027.c3
-rw-r--r--arch/arm/mach-pxa/poodle.c3
-rw-r--r--arch/arm/mach-pxa/pxa3xx-ulpi.c400
-rw-r--r--arch/arm/mach-pxa/pxa3xx.c19
-rw-r--r--arch/arm/mach-pxa/pxa930.c2
-rw-r--r--arch/arm/mach-pxa/raumfeld.c6
-rw-r--r--arch/arm/mach-pxa/saar.c2
-rw-r--r--arch/arm/mach-pxa/spitz.c6
-rw-r--r--arch/arm/mach-pxa/stargate2.c7
-rw-r--r--arch/arm/mach-pxa/tavorevb.c4
-rw-r--r--arch/arm/mach-pxa/tavorevb3.c135
-rw-r--r--arch/arm/mach-pxa/tosa.c3
-rw-r--r--arch/arm/mach-pxa/trizeps4.c4
-rw-r--r--arch/arm/mach-pxa/viper.c2
-rw-r--r--arch/arm/mach-pxa/vpac270.c2
-rw-r--r--arch/arm/mach-pxa/xcep.c2
-rw-r--r--arch/arm/mach-pxa/z2.c4
-rw-r--r--arch/arm/mach-pxa/zeus.c3
-rw-r--r--arch/arm/mach-pxa/zylonite.c5
-rw-r--r--arch/arm/mach-realview/core.c2
-rw-r--r--arch/arm/mach-realview/include/mach/debug-macro.S10
-rw-r--r--arch/arm/mach-realview/include/mach/smp.h10
-rw-r--r--arch/arm/mach-realview/realview_eb.c2
-rw-r--r--arch/arm/mach-realview/realview_pb1176.c2
-rw-r--r--arch/arm/mach-realview/realview_pb11mp.c2
-rw-r--r--arch/arm/mach-realview/realview_pba8.c2
-rw-r--r--arch/arm/mach-realview/realview_pbx.c2
-rw-r--r--arch/arm/mach-rpc/include/mach/debug-macro.S12
-rw-r--r--arch/arm/mach-rpc/include/mach/vmalloc.h2
-rw-r--r--arch/arm/mach-rpc/riscpc.c2
-rw-r--r--arch/arm/mach-s3c2410/include/mach/debug-macro.S11
-rw-r--r--arch/arm/mach-s3c2410/mach-amlm5900.c2
-rw-r--r--arch/arm/mach-s3c2410/mach-bast.c2
-rw-r--r--arch/arm/mach-s3c2410/mach-h1940.c2
-rw-r--r--arch/arm/mach-s3c2410/mach-n30.c4
-rw-r--r--arch/arm/mach-s3c2410/mach-otom.c2
-rw-r--r--arch/arm/mach-s3c2410/mach-qt2410.c2
-rw-r--r--arch/arm/mach-s3c2410/mach-smdk2410.c2
-rw-r--r--arch/arm/mach-s3c2410/mach-tct_hammer.c2
-rw-r--r--arch/arm/mach-s3c2410/mach-vr1000.c2
-rw-r--r--arch/arm/mach-s3c2412/mach-jive.c2
-rw-r--r--arch/arm/mach-s3c2412/mach-smdk2413.c6
-rw-r--r--arch/arm/mach-s3c2412/mach-vstms.c2
-rw-r--r--arch/arm/mach-s3c2416/mach-smdk2416.c2
-rw-r--r--arch/arm/mach-s3c2440/mach-anubis.c2
-rw-r--r--arch/arm/mach-s3c2440/mach-at2440evb.c2
-rw-r--r--arch/arm/mach-s3c2440/mach-gta02.c2
-rw-r--r--arch/arm/mach-s3c2440/mach-mini2440.c2
-rw-r--r--arch/arm/mach-s3c2440/mach-nexcoder.c2
-rw-r--r--arch/arm/mach-s3c2440/mach-osiris.c2
-rw-r--r--arch/arm/mach-s3c2440/mach-rx1950.c2
-rw-r--r--arch/arm/mach-s3c2440/mach-rx3715.c2
-rw-r--r--arch/arm/mach-s3c2440/mach-smdk2440.c2
-rw-r--r--arch/arm/mach-s3c2443/mach-smdk2443.c2
-rw-r--r--arch/arm/mach-s3c24a0/include/mach/debug-macro.S11
-rw-r--r--arch/arm/mach-s3c64xx/include/mach/debug-macro.S11
-rw-r--r--arch/arm/mach-s3c64xx/mach-anw6410.c2
-rw-r--r--arch/arm/mach-s3c64xx/mach-hmt.c2
-rw-r--r--arch/arm/mach-s3c64xx/mach-ncp.c2
-rw-r--r--arch/arm/mach-s3c64xx/mach-real6410.c2
-rw-r--r--arch/arm/mach-s3c64xx/mach-smartq.c2
-rw-r--r--arch/arm/mach-s3c64xx/mach-smartq5.c4
-rw-r--r--arch/arm/mach-s3c64xx/mach-smartq7.c4
-rw-r--r--arch/arm/mach-s3c64xx/mach-smdk6400.c2
-rw-r--r--arch/arm/mach-s3c64xx/mach-smdk6410.c2
-rw-r--r--arch/arm/mach-s5p6440/Kconfig33
-rw-r--r--arch/arm/mach-s5p6440/Makefile25
-rw-r--r--arch/arm/mach-s5p6440/clock.c846
-rw-r--r--arch/arm/mach-s5p6440/cpu.c116
-rw-r--r--arch/arm/mach-s5p6440/dev-audio.c127
-rw-r--r--arch/arm/mach-s5p6440/dev-spi.c176
-rw-r--r--arch/arm/mach-s5p6440/include/mach/debug-macro.S37
-rw-r--r--arch/arm/mach-s5p6440/include/mach/gpio.h80
-rw-r--r--arch/arm/mach-s5p6440/include/mach/io.h18
-rw-r--r--arch/arm/mach-s5p6440/include/mach/map.h86
-rw-r--r--arch/arm/mach-s5p6440/include/mach/regs-clock.h130
-rw-r--r--arch/arm/mach-s5p6440/include/mach/spi-clocks.h17
-rw-r--r--arch/arm/mach-s5p6440/include/mach/uncompress.h24
-rw-r--r--arch/arm/mach-s5p6440/init.c52
-rw-r--r--arch/arm/mach-s5p6442/cpu.c28
-rw-r--r--arch/arm/mach-s5p6442/include/mach/debug-macro.S11
-rw-r--r--arch/arm/mach-s5p6442/include/mach/map.h6
-rw-r--r--arch/arm/mach-s5p6442/mach-smdk6442.c2
-rw-r--r--arch/arm/mach-s5p64x0/Kconfig57
-rw-r--r--arch/arm/mach-s5p64x0/Makefile30
-rw-r--r--arch/arm/mach-s5p64x0/Makefile.boot (renamed from arch/arm/mach-s5p6440/Makefile.boot)0
-rw-r--r--arch/arm/mach-s5p64x0/clock-s5p6440.c626
-rw-r--r--arch/arm/mach-s5p64x0/clock-s5p6450.c655
-rw-r--r--arch/arm/mach-s5p64x0/clock.c253
-rw-r--r--arch/arm/mach-s5p64x0/cpu.c209
-rw-r--r--arch/arm/mach-s5p64x0/dev-audio.c164
-rw-r--r--arch/arm/mach-s5p64x0/dev-spi.c232
-rw-r--r--arch/arm/mach-s5p64x0/dma.c (renamed from arch/arm/mach-s5p6440/dma.c)86
-rw-r--r--arch/arm/mach-s5p64x0/gpio.c (renamed from arch/arm/mach-s5p6440/gpio.c)104
-rw-r--r--arch/arm/mach-s5p64x0/include/mach/debug-macro.S33
-rw-r--r--arch/arm/mach-s5p64x0/include/mach/dma.h (renamed from arch/arm/mach-s5p6440/include/mach/dma.h)0
-rw-r--r--arch/arm/mach-s5p64x0/include/mach/entry-macro.S (renamed from arch/arm/mach-s5p6440/include/mach/entry-macro.S)8
-rw-r--r--arch/arm/mach-s5p64x0/include/mach/gpio.h139
-rw-r--r--arch/arm/mach-s5p64x0/include/mach/hardware.h (renamed from arch/arm/mach-s5p6440/include/mach/hardware.h)8
-rw-r--r--arch/arm/mach-s5p64x0/include/mach/i2c.h17
-rw-r--r--arch/arm/mach-s5p64x0/include/mach/io.h25
-rw-r--r--arch/arm/mach-s5p64x0/include/mach/irqs.h (renamed from arch/arm/mach-s5p6440/include/mach/irqs.h)48
-rw-r--r--arch/arm/mach-s5p64x0/include/mach/map.h83
-rw-r--r--arch/arm/mach-s5p64x0/include/mach/memory.h (renamed from arch/arm/mach-s5p6440/include/mach/memory.h)12
-rw-r--r--arch/arm/mach-s5p64x0/include/mach/pwm-clock.h (renamed from arch/arm/mach-s5p6440/include/mach/pwm-clock.h)10
-rw-r--r--arch/arm/mach-s5p64x0/include/mach/regs-clock.h63
-rw-r--r--arch/arm/mach-s5p64x0/include/mach/regs-gpio.h (renamed from arch/arm/mach-s5p6440/include/mach/regs-gpio.h)28
-rw-r--r--arch/arm/mach-s5p64x0/include/mach/regs-irq.h (renamed from arch/arm/mach-s5p6440/include/mach/regs-irq.h)8
-rw-r--r--arch/arm/mach-s5p64x0/include/mach/s5p64x0-clock.h46
-rw-r--r--arch/arm/mach-s5p64x0/include/mach/spi-clocks.h20
-rw-r--r--arch/arm/mach-s5p64x0/include/mach/system.h (renamed from arch/arm/mach-s5p6440/include/mach/system.h)8
-rw-r--r--arch/arm/mach-s5p64x0/include/mach/tick.h (renamed from arch/arm/mach-s5p6440/include/mach/tick.h)13
-rw-r--r--arch/arm/mach-s5p64x0/include/mach/timex.h (renamed from arch/arm/mach-s5p6440/include/mach/timex.h)7
-rw-r--r--arch/arm/mach-s5p64x0/include/mach/uncompress.h212
-rw-r--r--arch/arm/mach-s5p64x0/include/mach/vmalloc.h (renamed from arch/arm/mach-s5p6440/include/mach/vmalloc.h)5
-rw-r--r--arch/arm/mach-s5p64x0/init.c73
-rw-r--r--arch/arm/mach-s5p64x0/mach-smdk6440.c (renamed from arch/arm/mach-s5p6440/mach-smdk6440.c)87
-rw-r--r--arch/arm/mach-s5p64x0/mach-smdk6450.c180
-rw-r--r--arch/arm/mach-s5p64x0/setup-i2c0.c (renamed from arch/arm/mach-s5p6440/setup-i2c0.c)24
-rw-r--r--arch/arm/mach-s5p64x0/setup-i2c1.c (renamed from arch/arm/mach-s5p6440/setup-i2c1.c)20
-rw-r--r--arch/arm/mach-s5pc100/cpu.c26
-rw-r--r--arch/arm/mach-s5pc100/include/mach/debug-macro.S11
-rw-r--r--arch/arm/mach-s5pc100/include/mach/map.h11
-rw-r--r--arch/arm/mach-s5pc100/mach-smdkc100.c2
-rw-r--r--arch/arm/mach-s5pv210/Kconfig9
-rw-r--r--arch/arm/mach-s5pv210/Makefile1
-rw-r--r--arch/arm/mach-s5pv210/clock.c5
-rw-r--r--arch/arm/mach-s5pv210/cpu.c23
-rw-r--r--arch/arm/mach-s5pv210/include/mach/debug-macro.S11
-rw-r--r--arch/arm/mach-s5pv210/include/mach/map.h11
-rw-r--r--arch/arm/mach-s5pv210/mach-aquila.c4
-rw-r--r--arch/arm/mach-s5pv210/mach-goni.c4
-rw-r--r--arch/arm/mach-s5pv210/mach-smdkc110.c2
-rw-r--r--arch/arm/mach-s5pv210/mach-smdkv210.c2
-rw-r--r--arch/arm/mach-s5pv310/cpu.c26
-rw-r--r--arch/arm/mach-s5pv310/include/mach/debug-macro.S11
-rw-r--r--arch/arm/mach-s5pv310/include/mach/irqs.h2
-rw-r--r--arch/arm/mach-s5pv310/include/mach/map.h7
-rw-r--r--arch/arm/mach-s5pv310/include/mach/smp.h9
-rw-r--r--arch/arm/mach-s5pv310/mach-smdkv310.c2
-rw-r--r--arch/arm/mach-s5pv310/mach-universal_c210.c2
-rw-r--r--arch/arm/mach-sa1100/assabet.c2
-rw-r--r--arch/arm/mach-sa1100/badge4.c2
-rw-r--r--arch/arm/mach-sa1100/cerf.c2
-rw-r--r--arch/arm/mach-sa1100/collie.c2
-rw-r--r--arch/arm/mach-sa1100/h3100.c2
-rw-r--r--arch/arm/mach-sa1100/h3600.c2
-rw-r--r--arch/arm/mach-sa1100/hackkit.c2
-rw-r--r--arch/arm/mach-sa1100/include/mach/debug-macro.S36
-rw-r--r--arch/arm/mach-sa1100/jornada720.c2
-rw-r--r--arch/arm/mach-sa1100/lart.c2
-rw-r--r--arch/arm/mach-sa1100/pleb.c2
-rw-r--r--arch/arm/mach-sa1100/shannon.c2
-rw-r--r--arch/arm/mach-sa1100/simpad.c2
-rw-r--r--arch/arm/mach-shark/core.c2
-rw-r--r--arch/arm/mach-shark/include/mach/debug-macro.S7
-rw-r--r--arch/arm/mach-shark/include/mach/vmalloc.h2
-rw-r--r--arch/arm/mach-shmobile/board-ap4evb.c2
-rw-r--r--arch/arm/mach-shmobile/board-g3evm.c2
-rw-r--r--arch/arm/mach-shmobile/board-g4evm.c2
-rw-r--r--arch/arm/mach-stmp378x/stmp378x_devb.c2
-rw-r--r--arch/arm/mach-stmp37xx/stmp37xx_devb.c2
-rw-r--r--arch/arm/mach-tcc8k/Kconfig11
-rw-r--r--arch/arm/mach-tcc8k/Makefile9
-rw-r--r--arch/arm/mach-tcc8k/Makefile.boot3
-rw-r--r--arch/arm/mach-tcc8k/board-tcc8000-sdk.c62
-rw-r--r--arch/arm/mach-tcc8k/clock.c567
-rw-r--r--arch/arm/mach-tcc8k/common.h15
-rw-r--r--arch/arm/mach-tcc8k/devices.c239
-rw-r--r--arch/arm/mach-tcc8k/io.c62
-rw-r--r--arch/arm/mach-tcc8k/irq.c111
-rw-r--r--arch/arm/mach-tcc8k/time.c149
-rw-r--r--arch/arm/mach-tegra/board-harmony.c2
-rw-r--r--arch/arm/mach-tegra/include/mach/debug-macro.S26
-rw-r--r--arch/arm/mach-tegra/include/mach/smp.h10
-rw-r--r--arch/arm/mach-u300/dummyspichip.c5
-rw-r--r--arch/arm/mach-u300/include/mach/debug-macro.S11
-rw-r--r--arch/arm/mach-u300/spi.c10
-rw-r--r--arch/arm/mach-u300/u300.c2
-rw-r--r--arch/arm/mach-ux500/Kconfig18
-rw-r--r--arch/arm/mach-ux500/Makefile8
-rw-r--r--arch/arm/mach-ux500/board-mop500-regulators.c101
-rw-r--r--arch/arm/mach-ux500/board-mop500-sdi.c91
-rw-r--r--arch/arm/mach-ux500/board-mop500.c44
-rw-r--r--arch/arm/mach-ux500/board-mop500.h12
-rw-r--r--arch/arm/mach-ux500/board-u5500.c2
-rw-r--r--arch/arm/mach-ux500/cpu-db5500.c88
-rw-r--r--arch/arm/mach-ux500/cpu-db8500.c82
-rw-r--r--arch/arm/mach-ux500/devices-db8500.c94
-rw-r--r--arch/arm/mach-ux500/hotplug.c75
-rw-r--r--arch/arm/mach-ux500/include/mach/db5500-regs.h14
-rw-r--r--arch/arm/mach-ux500/include/mach/db8500-regs.h2
-rw-r--r--arch/arm/mach-ux500/include/mach/debug-macro.S8
-rw-r--r--arch/arm/mach-ux500/include/mach/devices.h7
-rw-r--r--arch/arm/mach-ux500/include/mach/hardware.h23
-rw-r--r--arch/arm/mach-ux500/include/mach/irqs-db5500.h1
-rw-r--r--arch/arm/mach-ux500/include/mach/irqs.h18
-rw-r--r--arch/arm/mach-ux500/include/mach/mbox.h88
-rw-r--r--arch/arm/mach-ux500/include/mach/prcmu-regs.h91
-rw-r--r--arch/arm/mach-ux500/include/mach/prcmu.h15
-rw-r--r--arch/arm/mach-ux500/include/mach/setup.h7
-rw-r--r--arch/arm/mach-ux500/include/mach/smp.h9
-rw-r--r--arch/arm/mach-ux500/mbox.c567
-rw-r--r--arch/arm/mach-ux500/modem_irq.c139
-rw-r--r--arch/arm/mach-ux500/pins-db5500.h620
-rw-r--r--arch/arm/mach-ux500/pins-db8500.h66
-rw-r--r--arch/arm/mach-ux500/platsmp.c2
-rw-r--r--arch/arm/mach-ux500/prcmu.c231
-rw-r--r--arch/arm/mach-ux500/ste-dma40-db5500.h135
-rw-r--r--arch/arm/mach-ux500/ste-dma40-db8500.h258
-rw-r--r--arch/arm/mach-versatile/include/mach/debug-macro.S12
-rw-r--r--arch/arm/mach-versatile/include/mach/vmalloc.h2
-rw-r--r--arch/arm/mach-versatile/versatile_ab.c2
-rw-r--r--arch/arm/mach-versatile/versatile_pb.c2
-rw-r--r--arch/arm/mach-vexpress/ct-ca9x4.c6
-rw-r--r--arch/arm/mach-vexpress/include/mach/debug-macro.S10
-rw-r--r--arch/arm/mach-vexpress/include/mach/smp.h9
-rw-r--r--arch/arm/mach-vexpress/v2m.c2
-rw-r--r--arch/arm/mach-w90x900/mach-nuc910evb.c2
-rw-r--r--arch/arm/mach-w90x900/mach-nuc950evb.c2
-rw-r--r--arch/arm/mach-w90x900/mach-nuc960evb.c2
-rw-r--r--arch/arm/mm/cache-v6.S30
-rw-r--r--arch/arm/mm/cache-v7.S30
-rw-r--r--arch/arm/mm/copypage-v4mc.c2
-rw-r--r--arch/arm/mm/copypage-v6.c2
-rw-r--r--arch/arm/mm/copypage-xscale.c2
-rw-r--r--arch/arm/mm/dma-mapping.c6
-rw-r--r--arch/arm/mm/fault-armv.c8
-rw-r--r--arch/arm/mm/fault.c13
-rw-r--r--arch/arm/mm/flush.c69
-rw-r--r--arch/arm/mm/init.c41
-rw-r--r--arch/arm/mm/ioremap.c8
-rw-r--r--arch/arm/mm/mmap.c22
-rw-r--r--arch/arm/mm/mmu.c50
-rw-r--r--arch/arm/mm/proc-arm1020.S2
-rw-r--r--arch/arm/mm/proc-arm1020e.S2
-rw-r--r--arch/arm/mm/proc-arm1022.S2
-rw-r--r--arch/arm/mm/proc-arm1026.S2
-rw-r--r--arch/arm/mm/proc-arm6_7.S2
-rw-r--r--arch/arm/mm/proc-arm720.S2
-rw-r--r--arch/arm/mm/proc-arm740.S2
-rw-r--r--arch/arm/mm/proc-arm7tdmi.S2
-rw-r--r--arch/arm/mm/proc-arm920.S2
-rw-r--r--arch/arm/mm/proc-arm922.S2
-rw-r--r--arch/arm/mm/proc-arm925.S2
-rw-r--r--arch/arm/mm/proc-arm926.S2
-rw-r--r--arch/arm/mm/proc-arm940.S2
-rw-r--r--arch/arm/mm/proc-arm946.S2
-rw-r--r--arch/arm/mm/proc-arm9tdmi.S2
-rw-r--r--arch/arm/mm/proc-fa526.S2
-rw-r--r--arch/arm/mm/proc-feroceon.S2
-rw-r--r--arch/arm/mm/proc-mohawk.S2
-rw-r--r--arch/arm/mm/proc-sa110.S2
-rw-r--r--arch/arm/mm/proc-sa1100.S2
-rw-r--r--arch/arm/mm/proc-v6.S49
-rw-r--r--arch/arm/mm/proc-v7.S57
-rw-r--r--arch/arm/mm/proc-xsc3.S2
-rw-r--r--arch/arm/mm/proc-xscale.S2
-rw-r--r--arch/arm/mm/tlb-v7.S33
-rw-r--r--arch/arm/oprofile/Makefile4
-rw-r--r--arch/arm/oprofile/common.c308
-rw-r--r--arch/arm/plat-mxc/Kconfig16
-rw-r--r--arch/arm/plat-mxc/Makefile2
-rw-r--r--arch/arm/plat-mxc/audmux-v2.c9
-rw-r--r--arch/arm/plat-mxc/devices/Kconfig10
-rw-r--r--arch/arm/plat-mxc/devices/Makefile9
-rw-r--r--arch/arm/plat-mxc/devices/platform-esdhc.c71
-rw-r--r--arch/arm/plat-mxc/devices/platform-fec.c58
-rw-r--r--arch/arm/plat-mxc/devices/platform-imx-dma.c129
-rw-r--r--arch/arm/plat-mxc/devices/platform-imx-i2c.c85
-rw-r--r--arch/arm/plat-mxc/devices/platform-imx-ssi.c107
-rw-r--r--arch/arm/plat-mxc/devices/platform-imx-uart.c137
-rw-r--r--arch/arm/plat-mxc/devices/platform-mxc_nand.c85
-rw-r--r--arch/arm/plat-mxc/devices/platform-spi_imx.c89
-rw-r--r--arch/arm/plat-mxc/ehci.c4
-rw-r--r--arch/arm/plat-mxc/epit.c242
-rw-r--r--arch/arm/plat-mxc/gpio.c2
-rw-r--r--arch/arm/plat-mxc/include/mach/board-mx31ads.h33
-rw-r--r--arch/arm/plat-mxc/include/mach/common.h1
-rw-r--r--arch/arm/plat-mxc/include/mach/debug-macro.S8
-rw-r--r--arch/arm/plat-mxc/include/mach/devices-common.h112
-rw-r--r--arch/arm/plat-mxc/include/mach/esdhc.h16
-rw-r--r--arch/arm/plat-mxc/include/mach/eukrea-baseboards.h5
-rw-r--r--arch/arm/plat-mxc/include/mach/iomux-mx51.h120
-rw-r--r--arch/arm/plat-mxc/include/mach/iram.h41
-rw-r--r--arch/arm/plat-mxc/include/mach/mx21.h2
-rw-r--r--arch/arm/plat-mxc/include/mach/mx25.h17
-rw-r--r--arch/arm/plat-mxc/include/mach/mx27.h2
-rw-r--r--arch/arm/plat-mxc/include/mach/mx31.h11
-rw-r--r--arch/arm/plat-mxc/include/mach/mx35.h38
-rw-r--r--arch/arm/plat-mxc/include/mach/mx3x.h23
-rw-r--r--arch/arm/plat-mxc/include/mach/mx51.h657
-rw-r--r--arch/arm/plat-mxc/include/mach/system.h32
-rw-r--r--arch/arm/plat-mxc/include/mach/uncompress.h1
-rw-r--r--arch/arm/plat-mxc/iram_alloc.c73
-rw-r--r--arch/arm/plat-nomadik/gpio.c74
-rw-r--r--arch/arm/plat-nomadik/include/plat/gpio.h2
-rw-r--r--arch/arm/plat-nomadik/include/plat/pincfg.h36
-rw-r--r--arch/arm/plat-omap/Kconfig2
-rw-r--r--arch/arm/plat-omap/fb.c6
-rw-r--r--arch/arm/plat-omap/include/plat/smp.h12
-rw-r--r--arch/arm/plat-omap/include/plat/usb.h21
-rw-r--r--arch/arm/plat-omap/iommu-debug.c2
-rw-r--r--arch/arm/plat-omap/iommu.c1
-rw-r--r--arch/arm/plat-omap/mcbsp.c2
-rw-r--r--arch/arm/plat-pxa/include/plat/pxa27x_keypad.h (renamed from arch/arm/mach-pxa/include/mach/pxa27x_keypad.h)10
-rw-r--r--arch/arm/plat-s5p/Kconfig9
-rw-r--r--arch/arm/plat-s5p/Makefile1
-rw-r--r--arch/arm/plat-s5p/clock.c19
-rw-r--r--arch/arm/plat-s5p/cpu.c34
-rw-r--r--arch/arm/plat-s5p/dev-onenand.c (renamed from arch/arm/mach-s5pv210/dev-onenand.c)28
-rw-r--r--arch/arm/plat-s5p/dev-uart.c58
-rw-r--r--arch/arm/plat-s5p/include/plat/pll.h7
-rw-r--r--arch/arm/plat-s5p/include/plat/s5p-clock.h8
-rw-r--r--arch/arm/plat-s5p/include/plat/s5p6440.h7
-rw-r--r--arch/arm/plat-s5p/include/plat/s5p6450.h36
-rw-r--r--arch/arm/plat-samsung/adc.c1
-rw-r--r--arch/arm/plat-samsung/clock.c27
-rw-r--r--arch/arm/plat-samsung/include/plat/cpu.h2
-rw-r--r--arch/arm/plat-samsung/include/plat/devs.h7
-rw-r--r--arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h20
-rw-r--r--arch/arm/plat-samsung/include/plat/s3c64xx-spi.h5
-rw-r--r--arch/arm/plat-spear/include/plat/debug-macro.S8
-rw-r--r--arch/arm/plat-stmp3xxx/include/mach/debug-macro.S11
-rw-r--r--arch/arm/plat-tcc/Kconfig20
-rw-r--r--arch/arm/plat-tcc/Makefile3
-rw-r--r--arch/arm/plat-tcc/clock.c179
-rw-r--r--arch/arm/plat-tcc/include/mach/clkdev.h7
-rw-r--r--arch/arm/plat-tcc/include/mach/clock.h48
-rw-r--r--arch/arm/plat-tcc/include/mach/debug-macro.S32
-rw-r--r--arch/arm/plat-tcc/include/mach/entry-macro.S68
-rw-r--r--arch/arm/plat-tcc/include/mach/hardware.h43
-rw-r--r--arch/arm/plat-tcc/include/mach/io.h23
-rw-r--r--arch/arm/plat-tcc/include/mach/irqs.h83
-rw-r--r--arch/arm/plat-tcc/include/mach/memory.h18
-rw-r--r--arch/arm/plat-tcc/include/mach/system.h31
-rw-r--r--arch/arm/plat-tcc/include/mach/tcc8k-regs.h807
-rw-r--r--arch/arm/plat-tcc/include/mach/timex.h5
-rw-r--r--arch/arm/plat-tcc/include/mach/uncompress.h34
-rw-r--r--arch/arm/plat-tcc/include/mach/vmalloc.h10
-rw-r--r--arch/arm/plat-tcc/system.c25
-rw-r--r--arch/avr32/Kconfig1
-rw-r--r--arch/avr32/boards/mimc200/fram.c1
-rw-r--r--arch/avr32/include/asm/ioctls.h86
-rw-r--r--arch/avr32/include/asm/irqflags.h29
-rw-r--r--arch/avr32/kernel/module.c3
-rw-r--r--arch/blackfin/Kconfig12
-rw-r--r--arch/blackfin/Makefile3
-rw-r--r--arch/blackfin/configs/BF527-AD7160-EVAL_defconfig105
-rw-r--r--arch/blackfin/configs/BF527-TLL6527M_defconfig180
-rw-r--r--arch/blackfin/include/asm/Kbuild1
-rw-r--r--arch/blackfin/include/asm/bfin5xx_spi.h96
-rw-r--r--arch/blackfin/include/asm/bfin_can.h9
-rw-r--r--arch/blackfin/include/asm/bfin_ppi.h51
-rw-r--r--arch/blackfin/include/asm/cachectl.h20
-rw-r--r--arch/blackfin/include/asm/cdef_LPBlackfin.h9
-rw-r--r--arch/blackfin/include/asm/ipipe.h8
-rw-r--r--arch/blackfin/include/asm/irqflags.h273
-rw-r--r--arch/blackfin/include/asm/mmu_context.h8
-rw-r--r--arch/blackfin/include/asm/ptrace.h3
-rw-r--r--arch/blackfin/include/asm/serial.h1
-rw-r--r--arch/blackfin/include/asm/system.h4
-rw-r--r--arch/blackfin/include/asm/unistd.h3
-rw-r--r--arch/blackfin/kernel/bfin_gpio.c287
-rw-r--r--arch/blackfin/kernel/cplb-mpu/cplbmgr.c8
-rw-r--r--arch/blackfin/kernel/ipipe.c38
-rw-r--r--arch/blackfin/kernel/kgdb_test.c1
-rw-r--r--arch/blackfin/kernel/process.c9
-rw-r--r--arch/blackfin/kernel/ptrace.c12
-rw-r--r--arch/blackfin/kernel/sys_bfin.c15
-rw-r--r--arch/blackfin/kernel/trace.c1
-rw-r--r--arch/blackfin/mach-bf518/boards/ezbrd.c21
-rw-r--r--arch/blackfin/mach-bf518/boards/tcm-bf518.c2
-rw-r--r--arch/blackfin/mach-bf518/include/mach/cdefBF51x_base.h82
-rw-r--r--arch/blackfin/mach-bf518/include/mach/defBF51x_base.h45
-rw-r--r--arch/blackfin/mach-bf518/include/mach/pll.h63
-rw-r--r--arch/blackfin/mach-bf527/boards/Kconfig10
-rw-r--r--arch/blackfin/mach-bf527/boards/Makefile2
-rw-r--r--arch/blackfin/mach-bf527/boards/ad7160eval.c870
-rw-r--r--arch/blackfin/mach-bf527/boards/cm_bf527.c12
-rw-r--r--arch/blackfin/mach-bf527/boards/ezbrd.c6
-rw-r--r--arch/blackfin/mach-bf527/boards/ezkit.c23
-rw-r--r--arch/blackfin/mach-bf527/boards/tll6527m.c986
-rw-r--r--arch/blackfin/mach-bf527/include/mach/cdefBF52x_base.h82
-rw-r--r--arch/blackfin/mach-bf527/include/mach/defBF52x_base.h45
-rw-r--r--arch/blackfin/mach-bf527/include/mach/pll.h63
-rw-r--r--arch/blackfin/mach-bf533/boards/H8606.c10
-rw-r--r--arch/blackfin/mach-bf533/boards/blackstamp.c5
-rw-r--r--arch/blackfin/mach-bf533/boards/cm_bf533.c10
-rw-r--r--arch/blackfin/mach-bf533/boards/ezkit.c12
-rw-r--r--arch/blackfin/mach-bf533/boards/ip0x.c3
-rw-r--r--arch/blackfin/mach-bf533/boards/stamp.c20
-rw-r--r--arch/blackfin/mach-bf533/include/mach/cdefBF532.h91
-rw-r--r--arch/blackfin/mach-bf533/include/mach/defBF532.h70
-rw-r--r--arch/blackfin/mach-bf533/include/mach/fio_flag.h55
-rw-r--r--arch/blackfin/mach-bf533/include/mach/pll.h57
-rw-r--r--arch/blackfin/mach-bf537/Kconfig4
-rw-r--r--arch/blackfin/mach-bf537/boards/cm_bf537e.c10
-rw-r--r--arch/blackfin/mach-bf537/boards/cm_bf537u.c10
-rw-r--r--arch/blackfin/mach-bf537/boards/pnav10.c12
-rw-r--r--arch/blackfin/mach-bf537/boards/stamp.c597
-rw-r--r--arch/blackfin/mach-bf537/boards/tcm_bf537.c10
-rw-r--r--arch/blackfin/mach-bf537/include/mach/cdefBF534.h44
-rw-r--r--arch/blackfin/mach-bf537/include/mach/defBF534.h44
-rw-r--r--arch/blackfin/mach-bf537/include/mach/pll.h57
-rw-r--r--arch/blackfin/mach-bf538/boards/ezkit.c4
-rw-r--r--arch/blackfin/mach-bf538/include/mach/cdefBF538.h50
-rw-r--r--arch/blackfin/mach-bf538/include/mach/defBF539.h73
-rw-r--r--arch/blackfin/mach-bf538/include/mach/pll.h63
-rw-r--r--arch/blackfin/mach-bf548/boards/cm_bf548.c47
-rw-r--r--arch/blackfin/mach-bf548/boards/ezkit.c31
-rw-r--r--arch/blackfin/mach-bf548/dma.c1
-rw-r--r--arch/blackfin/mach-bf548/include/mach/cdefBF54x_base.h58
-rw-r--r--arch/blackfin/mach-bf548/include/mach/defBF54x_base.h51
-rw-r--r--arch/blackfin/mach-bf548/include/mach/pll.h69
-rw-r--r--arch/blackfin/mach-bf561/boards/acvilon.c2
-rw-r--r--arch/blackfin/mach-bf561/boards/cm_bf561.c10
-rw-r--r--arch/blackfin/mach-bf561/boards/ezkit.c68
-rw-r--r--arch/blackfin/mach-bf561/coreb.c12
-rw-r--r--arch/blackfin/mach-bf561/include/mach/blackfin.h33
-rw-r--r--arch/blackfin/mach-bf561/include/mach/cdefBF561.h126
-rw-r--r--arch/blackfin/mach-bf561/include/mach/defBF561.h94
-rw-r--r--arch/blackfin/mach-bf561/include/mach/pll.h63
-rw-r--r--arch/blackfin/mach-bf561/ints-priority.c16
-rw-r--r--arch/blackfin/mach-bf561/smp.c24
-rw-r--r--arch/blackfin/mach-common/cpufreq.c4
-rw-r--r--arch/blackfin/mach-common/dpmc_modes.S50
-rw-r--r--arch/blackfin/mach-common/entry.S113
-rw-r--r--arch/blackfin/mach-common/interrupt.S17
-rw-r--r--arch/blackfin/mach-common/ints-priority.c35
-rw-r--r--arch/blackfin/mach-common/pm.c10
-rw-r--r--arch/blackfin/mm/init.c3
-rw-r--r--arch/cris/arch-v10/drivers/ds1302.c8
-rw-r--r--arch/cris/arch-v10/drivers/gpio.c1
-rw-r--r--arch/cris/arch-v10/drivers/i2c.c1
-rw-r--r--arch/cris/arch-v10/drivers/pcf8563.c7
-rw-r--r--arch/cris/arch-v10/drivers/sync_serial.c14
-rw-r--r--arch/cris/arch-v32/drivers/cryptocop.c7
-rw-r--r--arch/cris/arch-v32/drivers/i2c.c1
-rw-r--r--arch/cris/arch-v32/drivers/mach-a3/gpio.c12
-rw-r--r--arch/cris/arch-v32/drivers/mach-fs/gpio.c12
-rw-r--r--arch/cris/arch-v32/drivers/pcf8563.c7
-rw-r--r--arch/cris/arch-v32/drivers/sync_serial.c14
-rw-r--r--arch/cris/include/arch-v10/arch/irqflags.h45
-rw-r--r--arch/cris/include/arch-v10/arch/system.h16
-rw-r--r--arch/cris/include/arch-v32/arch/irqflags.h46
-rw-r--r--arch/cris/include/arch-v32/arch/system.h22
-rw-r--r--arch/cris/include/asm/ioctls.h84
-rw-r--r--arch/cris/include/asm/irqflags.h1
-rw-r--r--arch/cris/include/asm/system.h1
-rw-r--r--arch/cris/kernel/profile.c1
-rw-r--r--arch/frv/Kconfig1
-rw-r--r--arch/frv/include/asm/ioctls.h80
-rw-r--r--arch/frv/include/asm/irqflags.h158
-rw-r--r--arch/frv/include/asm/system.h136
-rw-r--r--arch/frv/lib/Makefile2
-rw-r--r--arch/frv/lib/perf_event.c19
-rw-r--r--arch/h8300/include/asm/ioctls.h81
-rw-r--r--arch/h8300/include/asm/irqflags.h43
-rw-r--r--arch/h8300/include/asm/system.h24
-rw-r--r--arch/h8300/kernel/module.c3
-rw-r--r--arch/ia64/Kconfig12
-rw-r--r--arch/ia64/hp/sim/simserial.c12
-rw-r--r--arch/ia64/include/asm/compat.h208
-rw-r--r--arch/ia64/include/asm/hardirq.h11
-rw-r--r--arch/ia64/include/asm/ioctls.h89
-rw-r--r--arch/ia64/include/asm/iommu_table.h6
-rw-r--r--arch/ia64/include/asm/irqflags.h94
-rw-r--r--arch/ia64/include/asm/system.h80
-rw-r--r--arch/ia64/kernel/Makefile1
-rw-r--r--arch/ia64/kernel/cyclone.c2
-rw-r--r--arch/ia64/kernel/iosapic.c60
-rw-r--r--arch/ia64/kernel/irq_ia64.c5
-rw-r--r--arch/ia64/kernel/mca.c38
-rw-r--r--arch/ia64/kernel/msi_ia64.c8
-rw-r--r--arch/ia64/kernel/palinfo.c2
-rw-r--r--arch/ia64/kernel/perfmon.c12
-rw-r--r--arch/ia64/kernel/salinfo.c4
-rw-r--r--arch/ia64/kernel/setup.c4
-rw-r--r--arch/ia64/kernel/stacktrace.c39
-rw-r--r--arch/ia64/kernel/unwind.c23
-rw-r--r--arch/ia64/sn/kernel/msi_sn.c4
-rw-r--r--arch/ia64/sn/kernel/sn2/sn_hwperf.c1
-rw-r--r--arch/ia64/xen/xen_pv_ops.c5
-rw-r--r--arch/m32r/include/asm/elf.h4
-rw-r--r--arch/m32r/include/asm/ioctls.h83
-rw-r--r--arch/m32r/include/asm/irqflags.h104
-rw-r--r--arch/m32r/include/asm/system.h66
-rw-r--r--arch/m32r/kernel/.gitignore1
-rw-r--r--arch/m32r/kernel/irq.c2
-rw-r--r--arch/m32r/kernel/signal.c4
-rw-r--r--arch/m32r/platforms/m32104ut/setup.c2
-rw-r--r--arch/m32r/platforms/m32700ut/setup.c8
-rw-r--r--arch/m32r/platforms/mappi/setup.c2
-rw-r--r--arch/m32r/platforms/mappi2/setup.c2
-rw-r--r--arch/m32r/platforms/mappi3/setup.c2
-rw-r--r--arch/m32r/platforms/oaks32r/setup.c2
-rw-r--r--arch/m32r/platforms/opsput/setup.c6
-rw-r--r--arch/m32r/platforms/usrv/setup.c4
-rw-r--r--arch/m68k/Kconfig4
-rw-r--r--arch/m68k/bvme6000/rtc.c1
-rw-r--r--arch/m68k/include/asm/amigahw.h1
-rw-r--r--arch/m68k/include/asm/atomic.h210
-rw-r--r--arch/m68k/include/asm/atomic_mm.h200
-rw-r--r--arch/m68k/include/asm/atomic_no.h155
-rw-r--r--arch/m68k/include/asm/entry_mm.h3
-rw-r--r--arch/m68k/include/asm/entry_no.h2
-rw-r--r--arch/m68k/include/asm/io_mm.h43
-rw-r--r--arch/m68k/include/asm/ioctls.h80
-rw-r--r--arch/m68k/include/asm/irqflags.h76
-rw-r--r--arch/m68k/include/asm/machdep.h49
-rw-r--r--arch/m68k/include/asm/machdep_mm.h35
-rw-r--r--arch/m68k/include/asm/machdep_no.h26
-rw-r--r--arch/m68k/include/asm/page.h48
-rw-r--r--arch/m68k/include/asm/page_mm.h57
-rw-r--r--arch/m68k/include/asm/page_no.h51
-rw-r--r--arch/m68k/include/asm/string.h134
-rw-r--r--arch/m68k/include/asm/string_mm.h131
-rw-r--r--arch/m68k/include/asm/string_no.h126
-rw-r--r--arch/m68k/include/asm/system_mm.h27
-rw-r--r--arch/m68k/include/asm/system_no.h66
-rw-r--r--arch/m68k/include/asm/thread_info.h109
-rw-r--r--arch/m68k/include/asm/thread_info_mm.h71
-rw-r--r--arch/m68k/include/asm/thread_info_no.h102
-rw-r--r--arch/m68k/include/asm/traps.h275
-rw-r--r--arch/m68k/include/asm/traps_mm.h272
-rw-r--r--arch/m68k/include/asm/traps_no.h154
-rw-r--r--arch/m68k/kernel/setup.c6
-rw-r--r--arch/m68k/kernel/sys_m68k.c3
-rw-r--r--arch/m68k/kernel/time.c2
-rw-r--r--arch/m68k/mac/macboing.c6
-rw-r--r--arch/m68k/mvme16x/rtc.c1
-rw-r--r--arch/m68k/sun3/sun3ints.c2
-rw-r--r--arch/m68knommu/kernel/asm-offsets.c2
-rw-r--r--arch/m68knommu/kernel/time.c3
-rw-r--r--arch/m68knommu/platform/coldfire/entry.S4
-rw-r--r--arch/m68knommu/platform/coldfire/head.S1
-rw-r--r--arch/microblaze/include/asm/irqflags.h193
-rw-r--r--arch/microblaze/include/asm/memblock.h3
-rw-r--r--arch/microblaze/mm/init.c30
-rw-r--r--arch/mips/Kbuild4
-rw-r--r--arch/mips/Kconfig25
-rw-r--r--arch/mips/alchemy/common/platform.c28
-rw-r--r--arch/mips/alchemy/common/power.c35
-rw-r--r--arch/mips/alchemy/common/prom.c5
-rw-r--r--arch/mips/alchemy/devboards/bcsr.c1
-rw-r--r--arch/mips/ar7/irq.c1
-rw-r--r--arch/mips/bcm63xx/irq.c1
-rw-r--r--arch/mips/boot/compressed/Makefile4
-rw-r--r--arch/mips/cavium-octeon/Kconfig4
-rw-r--r--arch/mips/cavium-octeon/cpu.c2
-rw-r--r--arch/mips/cavium-octeon/executive/Makefile2
-rw-r--r--arch/mips/cavium-octeon/serial.c1
-rw-r--r--arch/mips/dec/Platform2
-rw-r--r--arch/mips/dec/setup.c1
-rw-r--r--arch/mips/include/asm/atomic.h4
-rw-r--r--arch/mips/include/asm/cop2.h2
-rw-r--r--arch/mips/include/asm/fcntl.h1
-rw-r--r--arch/mips/include/asm/gic.h1
-rw-r--r--arch/mips/include/asm/irqflags.h53
-rw-r--r--arch/mips/include/asm/mach-loongson/loongson.h1
-rw-r--r--arch/mips/include/asm/mach-tx49xx/kmalloc.h2
-rw-r--r--arch/mips/include/asm/mips-boards/maltaint.h3
-rw-r--r--arch/mips/include/asm/page.h14
-rw-r--r--arch/mips/include/asm/siginfo.h1
-rw-r--r--arch/mips/include/asm/thread_info.h3
-rw-r--r--arch/mips/include/asm/unistd.h21
-rw-r--r--arch/mips/jazz/irq.c1
-rw-r--r--arch/mips/jz4740/Platform2
-rw-r--r--arch/mips/kernel/branch.c1
-rw-r--r--arch/mips/kernel/cevt-bcm1480.c1
-rw-r--r--arch/mips/kernel/cevt-ds1287.c1
-rw-r--r--arch/mips/kernel/cevt-gt641xx.c1
-rw-r--r--arch/mips/kernel/cevt-r4k.c1
-rw-r--r--arch/mips/kernel/cevt-sb1250.c1
-rw-r--r--arch/mips/kernel/cevt-smtc.c1
-rw-r--r--arch/mips/kernel/cevt-txx9.c1
-rw-r--r--arch/mips/kernel/i8253.c1
-rw-r--r--arch/mips/kernel/i8259.c1
-rw-r--r--arch/mips/kernel/irq-gic.c7
-rw-r--r--arch/mips/kernel/irq-rm7000.c1
-rw-r--r--arch/mips/kernel/irq-rm9000.c1
-rw-r--r--arch/mips/kernel/irq_cpu.c1
-rw-r--r--arch/mips/kernel/irq_txx9.c1
-rw-r--r--arch/mips/kernel/kgdb.c2
-rw-r--r--arch/mips/kernel/kspd.c2
-rw-r--r--arch/mips/kernel/linux32.c7
-rw-r--r--arch/mips/kernel/mips-mt-fpaff.c2
-rw-r--r--arch/mips/kernel/ptrace.c4
-rw-r--r--arch/mips/kernel/rtlx.c3
-rw-r--r--arch/mips/kernel/scall32-o32.S16
-rw-r--r--arch/mips/kernel/scall64-64.S14
-rw-r--r--arch/mips/kernel/scall64-n32.S17
-rw-r--r--arch/mips/kernel/scall64-o32.S20
-rw-r--r--arch/mips/kernel/signal.c45
-rw-r--r--arch/mips/kernel/signal_n32.c5
-rw-r--r--arch/mips/kernel/smtc.c4
-rw-r--r--arch/mips/kernel/traps.c2
-rw-r--r--arch/mips/kernel/unaligned.c2
-rw-r--r--arch/mips/kernel/vpe.c3
-rw-r--r--arch/mips/mm/dma-default.c28
-rw-r--r--arch/mips/mm/sc-rm7k.c2
-rw-r--r--arch/mips/mti-malta/malta-int.c3
-rw-r--r--arch/mips/mti-malta/malta-platform.c1
-rw-r--r--arch/mips/pci/ops-tx3927.c1
-rw-r--r--arch/mips/pci/ops-tx4927.c1
-rw-r--r--arch/mips/pci/pci-rc32434.c2
-rw-r--r--arch/mips/pmc-sierra/msp71xx/msp_irq_cic.c1
-rw-r--r--arch/mips/pnx8550/common/reset.c20
-rw-r--r--arch/mips/pnx8550/common/setup.c3
-rw-r--r--arch/mips/powertv/asic/irq_asic.c1
-rw-r--r--arch/mips/rb532/serial.c1
-rw-r--r--arch/mips/sibyte/common/sb_tbprof.c1
-rw-r--r--arch/mips/sni/a20r.c1
-rw-r--r--arch/mips/sni/pcimt.c1
-rw-r--r--arch/mips/sni/pcit.c1
-rw-r--r--arch/mips/sni/rm200.c1
-rw-r--r--arch/mips/sni/time.c1
-rw-r--r--arch/mips/txx9/generic/irq_tx4927.c1
-rw-r--r--arch/mips/txx9/generic/irq_tx4938.c1
-rw-r--r--arch/mips/txx9/generic/irq_tx4939.c1
-rw-r--r--arch/mips/txx9/generic/setup.c1
-rw-r--r--arch/mips/txx9/jmr3927/irq.c1
-rw-r--r--arch/mips/txx9/rbtx4927/irq.c1
-rw-r--r--arch/mips/txx9/rbtx4938/irq.c1
-rw-r--r--arch/mips/txx9/rbtx4939/irq.c1
-rw-r--r--arch/mips/vr41xx/common/irq.c1
-rw-r--r--arch/mips/vr41xx/common/siu.c1
-rw-r--r--arch/mn10300/include/asm/ioctls.h84
-rw-r--r--arch/mn10300/include/asm/irqflags.h123
-rw-r--r--arch/mn10300/include/asm/system.h109
-rw-r--r--arch/mn10300/kernel/entry.S1
-rw-r--r--arch/mn10300/kernel/module.c3
-rw-r--r--arch/mn10300/mm/cache.c20
-rw-r--r--arch/parisc/Kconfig1
-rw-r--r--arch/parisc/include/asm/irqflags.h46
-rw-r--r--arch/parisc/include/asm/perf_event.h3
-rw-r--r--arch/parisc/include/asm/system.h19
-rw-r--r--arch/parisc/kernel/module.c3
-rw-r--r--arch/parisc/kernel/perf.c4
-rw-r--r--arch/powerpc/Kconfig1
-rw-r--r--arch/powerpc/boot/addnote.c4
-rw-r--r--arch/powerpc/boot/dts/bluestone.dts254
-rw-r--r--arch/powerpc/boot/dts/mpc8308_p1m.dts332
-rw-r--r--arch/powerpc/boot/dts/mpc8536ds.dts52
-rw-r--r--arch/powerpc/boot/dts/p1022ds.dts11
-rw-r--r--arch/powerpc/boot/dts/p4080ds.dts11
-rw-r--r--arch/powerpc/configs/44x/bluestone_defconfig68
-rw-r--r--arch/powerpc/configs/e55xx_smp_defconfig84
-rw-r--r--arch/powerpc/configs/ppc44x_defconfig9
-rw-r--r--arch/powerpc/configs/ppc64e_defconfig4
-rw-r--r--arch/powerpc/include/asm/checksum.h10
-rw-r--r--arch/powerpc/include/asm/compat.h4
-rw-r--r--arch/powerpc/include/asm/cputable.h14
-rw-r--r--arch/powerpc/include/asm/dma-mapping.h14
-rw-r--r--arch/powerpc/include/asm/elf.h2
-rw-r--r--arch/powerpc/include/asm/exception-64s.h3
-rw-r--r--arch/powerpc/include/asm/fsl_85xx_cache_sram.h48
-rw-r--r--arch/powerpc/include/asm/hw_irq.h113
-rw-r--r--arch/powerpc/include/asm/irqflags.h2
-rw-r--r--arch/powerpc/include/asm/kexec.h1
-rw-r--r--arch/powerpc/include/asm/kvm_fpu.h4
-rw-r--r--arch/powerpc/include/asm/lppaca.h29
-rw-r--r--arch/powerpc/include/asm/machdep.h3
-rw-r--r--arch/powerpc/include/asm/memblock.h7
-rw-r--r--arch/powerpc/include/asm/mmu-book3e.h15
-rw-r--r--arch/powerpc/include/asm/mmu.h12
-rw-r--r--arch/powerpc/include/asm/paca.h12
-rw-r--r--arch/powerpc/include/asm/page_64.h4
-rw-r--r--arch/powerpc/include/asm/ppc-pci.h4
-rw-r--r--arch/powerpc/include/asm/ppc_asm.h50
-rw-r--r--arch/powerpc/include/asm/processor.h4
-rw-r--r--arch/powerpc/include/asm/pte-common.h7
-rw-r--r--arch/powerpc/include/asm/rtas.h1
-rw-r--r--arch/powerpc/include/asm/systbl.h19
-rw-r--r--arch/powerpc/include/asm/system.h8
-rw-r--r--arch/powerpc/include/asm/time.h5
-rw-r--r--arch/powerpc/include/asm/unistd.h21
-rw-r--r--arch/powerpc/kernel/Makefile4
-rw-r--r--arch/powerpc/kernel/align.c4
-rw-r--r--arch/powerpc/kernel/asm-offsets.c12
-rw-r--r--arch/powerpc/kernel/cpu_setup_44x.S1
-rw-r--r--arch/powerpc/kernel/cpu_setup_fsl_booke.S15
-rw-r--r--arch/powerpc/kernel/cputable.c43
-rw-r--r--arch/powerpc/kernel/crash.c13
-rw-r--r--arch/powerpc/kernel/dma-iommu.c21
-rw-r--r--arch/powerpc/kernel/dma.c20
-rw-r--r--arch/powerpc/kernel/entry_64.S40
-rw-r--r--arch/powerpc/kernel/exceptions-64s.S4
-rw-r--r--arch/powerpc/kernel/fpu.S10
-rw-r--r--arch/powerpc/kernel/head_40x.S6
-rw-r--r--arch/powerpc/kernel/head_fsl_booke.S10
-rw-r--r--arch/powerpc/kernel/irq.c10
-rw-r--r--arch/powerpc/kernel/lparcfg.c15
-rw-r--r--arch/powerpc/kernel/machine_kexec.c24
-rw-r--r--arch/powerpc/kernel/machine_kexec_32.c4
-rw-r--r--arch/powerpc/kernel/module.c6
-rw-r--r--arch/powerpc/kernel/paca.c72
-rw-r--r--arch/powerpc/kernel/pci-common.c4
-rw-r--r--arch/powerpc/kernel/perf_callchain.c86
-rw-r--r--arch/powerpc/kernel/perf_event.c166
-rw-r--r--arch/powerpc/kernel/perf_event_fsl_emb.c148
-rw-r--r--arch/powerpc/kernel/ppc970-pmu.c2
-rw-r--r--arch/powerpc/kernel/process.c12
-rw-r--r--arch/powerpc/kernel/prom.c15
-rw-r--r--arch/powerpc/kernel/ptrace.c2
-rw-r--r--arch/powerpc/kernel/rtas.c6
-rw-r--r--arch/powerpc/kernel/rtas_flash.c3
-rw-r--r--arch/powerpc/kernel/rtasd.c1
-rw-r--r--arch/powerpc/kernel/setup_32.c4
-rw-r--r--arch/powerpc/kernel/setup_64.c2
-rw-r--r--arch/powerpc/kernel/smp.c14
-rw-r--r--arch/powerpc/kernel/time.c317
-rw-r--r--arch/powerpc/kernel/traps.c5
-rw-r--r--arch/powerpc/kernel/vdso.c6
-rw-r--r--arch/powerpc/kernel/vdso32/Makefile6
-rw-r--r--arch/powerpc/kernel/vdso64/Makefile6
-rw-r--r--arch/powerpc/kernel/vio.c10
-rw-r--r--arch/powerpc/kvm/Makefile2
-rw-r--r--arch/powerpc/kvm/book3s_paired_singles.c44
-rw-r--r--arch/powerpc/kvm/emulate.c4
-rw-r--r--arch/powerpc/kvm/fpu.S8
-rw-r--r--arch/powerpc/lib/Makefile7
-rw-r--r--arch/powerpc/lib/checksum_64.S482
-rw-r--r--arch/powerpc/lib/checksum_wrappers_64.c102
-rw-r--r--arch/powerpc/lib/copy_32.S2
-rw-r--r--arch/powerpc/lib/ldstfp.S36
-rw-r--r--arch/powerpc/lib/locks.c4
-rw-r--r--arch/powerpc/lib/sstep.c8
-rw-r--r--arch/powerpc/math-emu/Makefile2
-rw-r--r--arch/powerpc/mm/40x_mmu.c17
-rw-r--r--arch/powerpc/mm/44x_mmu.c14
-rw-r--r--arch/powerpc/mm/Makefile6
-rw-r--r--arch/powerpc/mm/fault.c6
-rw-r--r--arch/powerpc/mm/fsl_booke_mmu.c27
-rw-r--r--arch/powerpc/mm/hash_utils_64.c35
-rw-r--r--arch/powerpc/mm/init_32.c43
-rw-r--r--arch/powerpc/mm/init_64.c1
-rw-r--r--arch/powerpc/mm/mem.c94
-rw-r--r--arch/powerpc/mm/mmu_context_nohash.c6
-rw-r--r--arch/powerpc/mm/mmu_decl.h5
-rw-r--r--arch/powerpc/mm/numa.c17
-rw-r--r--arch/powerpc/mm/ppc_mmu_32.c18
-rw-r--r--arch/powerpc/mm/tlb_nohash.c72
-rw-r--r--arch/powerpc/mm/tlb_nohash_low.S2
-rw-r--r--arch/powerpc/oprofile/Makefile4
-rw-r--r--arch/powerpc/oprofile/backtrace.c2
-rw-r--r--arch/powerpc/oprofile/op_model_fsl_emb.c15
-rw-r--r--arch/powerpc/platforms/44x/Kconfig16
-rw-r--r--arch/powerpc/platforms/44x/ppc44x_simple.c1
-rw-r--r--arch/powerpc/platforms/512x/clock.c2
-rw-r--r--arch/powerpc/platforms/52xx/efika.c9
-rw-r--r--arch/powerpc/platforms/52xx/mpc52xx_common.c8
-rw-r--r--arch/powerpc/platforms/83xx/Kconfig4
-rw-r--r--arch/powerpc/platforms/83xx/mpc830x_rdb.c3
-rw-r--r--arch/powerpc/platforms/85xx/Kconfig28
-rw-r--r--arch/powerpc/platforms/85xx/Makefile2
-rw-r--r--arch/powerpc/platforms/85xx/p1022_ds.c2
-rw-r--r--arch/powerpc/platforms/85xx/p3041_ds.c64
-rw-r--r--arch/powerpc/platforms/85xx/p5020_ds.c69
-rw-r--r--arch/powerpc/platforms/85xx/smp.c83
-rw-r--r--arch/powerpc/platforms/Kconfig.cputype8
-rw-r--r--arch/powerpc/platforms/cell/axon_msi.c6
-rw-r--r--arch/powerpc/platforms/cell/ras.c4
-rw-r--r--arch/powerpc/platforms/cell/spider-pic.c4
-rw-r--r--arch/powerpc/platforms/cell/spufs/file.c18
-rw-r--r--arch/powerpc/platforms/chrp/nvram.c4
-rw-r--r--arch/powerpc/platforms/embedded6xx/wii.c2
-rw-r--r--arch/powerpc/platforms/iseries/Makefile2
-rw-r--r--arch/powerpc/platforms/iseries/dt.c4
-rw-r--r--arch/powerpc/platforms/iseries/mf.c1
-rw-r--r--arch/powerpc/platforms/iseries/smp.c2
-rw-r--r--arch/powerpc/platforms/maple/setup.c1
-rw-r--r--arch/powerpc/platforms/powermac/pfunc_core.c9
-rw-r--r--arch/powerpc/platforms/pseries/Makefile13
-rw-r--r--arch/powerpc/platforms/pseries/dlpar.c7
-rw-r--r--arch/powerpc/platforms/pseries/dtl.c224
-rw-r--r--arch/powerpc/platforms/pseries/lpar.c25
-rw-r--r--arch/powerpc/platforms/pseries/mobility.c362
-rw-r--r--arch/powerpc/platforms/pseries/pseries.h9
-rw-r--r--arch/powerpc/platforms/pseries/reconfig.c3
-rw-r--r--arch/powerpc/platforms/pseries/scanlog.c1
-rw-r--r--arch/powerpc/platforms/pseries/setup.c52
-rw-r--r--arch/powerpc/platforms/pseries/xics.c4
-rw-r--r--arch/powerpc/sysdev/Makefile5
-rw-r--r--arch/powerpc/sysdev/dart_iommu.c74
-rw-r--r--arch/powerpc/sysdev/fsl_85xx_cache_ctlr.h101
-rw-r--r--arch/powerpc/sysdev/fsl_85xx_cache_sram.c159
-rw-r--r--arch/powerpc/sysdev/fsl_85xx_l2ctlr.c231
-rw-r--r--arch/powerpc/sysdev/fsl_msi.c13
-rw-r--r--arch/powerpc/sysdev/fsl_pci.c60
-rw-r--r--arch/powerpc/sysdev/fsl_pci.h1
-rw-r--r--arch/powerpc/sysdev/fsl_rio.c65
-rw-r--r--arch/powerpc/sysdev/fsl_soc.c181
-rw-r--r--arch/powerpc/sysdev/mpc8xxx_gpio.c3
-rw-r--r--arch/powerpc/sysdev/mpic_pasemi_msi.c22
-rw-r--r--arch/powerpc/sysdev/mpic_u3msi.c18
-rw-r--r--arch/powerpc/sysdev/pmi.c2
-rw-r--r--arch/powerpc/xmon/Makefile4
-rw-r--r--arch/s390/Kconfig8
-rw-r--r--arch/s390/crypto/prng.c1
-rw-r--r--arch/s390/hypfs/hypfs_diag.c1
-rw-r--r--arch/s390/hypfs/hypfs_vm.c1
-rw-r--r--arch/s390/hypfs/inode.c1
-rw-r--r--arch/s390/include/asm/hardirq.h4
-rw-r--r--arch/s390/include/asm/ioctls.h88
-rw-r--r--arch/s390/include/asm/irqflags.h51
-rw-r--r--arch/s390/include/asm/perf_event.h3
-rw-r--r--arch/s390/include/asm/qdio.h13
-rw-r--r--arch/s390/include/asm/system.h3
-rw-r--r--arch/s390/include/asm/topology.h27
-rw-r--r--arch/s390/kernel/debug.c1
-rw-r--r--arch/s390/kernel/mem_detect.c4
-rw-r--r--arch/s390/kernel/module.c3
-rw-r--r--arch/s390/kernel/topology.c150
-rw-r--r--arch/s390/mm/init.c3
-rw-r--r--arch/s390/mm/maccess.c4
-rw-r--r--arch/score/include/asm/irqflags.h187
-rw-r--r--arch/sh/Kconfig14
-rw-r--r--arch/sh/boards/mach-landisk/gio.c1
-rw-r--r--arch/sh/include/asm/irqflags.h4
-rw-r--r--arch/sh/include/asm/memblock.h2
-rw-r--r--arch/sh/include/asm/perf_event.h7
-rw-r--r--arch/sh/include/asm/syscalls_32.h7
-rw-r--r--arch/sh/kernel/irq.c2
-rw-r--r--arch/sh/kernel/irq_32.c12
-rw-r--r--arch/sh/kernel/module.c2
-rw-r--r--arch/sh/kernel/perf_callchain.c50
-rw-r--r--arch/sh/kernel/perf_event.c159
-rw-r--r--arch/sh/mm/init.c17
-rw-r--r--arch/sh/oprofile/Makefile4
-rw-r--r--arch/sh/oprofile/common.c115
-rw-r--r--arch/sh/oprofile/op_impl.h33
-rw-r--r--arch/sparc/Kconfig3
-rw-r--r--arch/sparc/include/asm/irqflags_32.h35
-rw-r--r--arch/sparc/include/asm/irqflags_64.h29
-rw-r--r--arch/sparc/include/asm/jump_label.h32
-rw-r--r--arch/sparc/include/asm/memblock.h2
-rw-r--r--arch/sparc/include/asm/perf_event.h4
-rw-r--r--arch/sparc/kernel/Makefile2
-rw-r--r--arch/sparc/kernel/apc.c1
-rw-r--r--arch/sparc/kernel/irq_32.c13
-rw-r--r--arch/sparc/kernel/jump_label.c47
-rw-r--r--arch/sparc/kernel/mdesc.c1
-rw-r--r--arch/sparc/kernel/module.c6
-rw-r--r--arch/sparc/kernel/pci_msi.c8
-rw-r--r--arch/sparc/kernel/pcr.c8
-rw-r--r--arch/sparc/kernel/perf_event.c240
-rw-r--r--arch/sparc/mm/init_64.c46
-rw-r--r--arch/sparc/prom/p1275.c2
-rw-r--r--arch/tile/include/asm/bitops.h1
-rw-r--r--arch/tile/include/asm/irqflags.h36
-rw-r--r--arch/tile/kernel/hardwall.c1
-rw-r--r--arch/tile/kernel/irq.c4
-rw-r--r--arch/um/drivers/harddog_kern.c14
-rw-r--r--arch/um/drivers/hostaudio_kern.c26
-rw-r--r--arch/um/drivers/mconsole_kern.c1
-rw-r--r--arch/um/drivers/mmapper_kern.c1
-rw-r--r--arch/um/drivers/net_kern.c17
-rw-r--r--arch/um/drivers/random.c1
-rw-r--r--arch/um/drivers/ubd_kern.c20
-rw-r--r--arch/um/kernel/exec.c2
-rw-r--r--arch/um/kernel/irq.c6
-rw-r--r--arch/x86/Kconfig145
-rw-r--r--arch/x86/Kconfig.debug14
-rw-r--r--arch/x86/Makefile8
-rw-r--r--arch/x86/boot/compressed/misc.c29
-rw-r--r--arch/x86/ia32/ia32_aout.c22
-rw-r--r--arch/x86/include/asm/alternative.h11
-rw-r--r--arch/x86/include/asm/amd_iommu.h6
-rw-r--r--arch/x86/include/asm/amd_iommu_proto.h2
-rw-r--r--arch/x86/include/asm/amd_iommu_types.h23
-rw-r--r--arch/x86/include/asm/amd_nb.h (renamed from arch/x86/include/asm/k8.h)21
-rw-r--r--arch/x86/include/asm/apb_timer.h1
-rw-r--r--arch/x86/include/asm/apic.h4
-rw-r--r--arch/x86/include/asm/apicdef.h1
-rw-r--r--arch/x86/include/asm/bitops.h2
-rw-r--r--arch/x86/include/asm/calgary.h4
-rw-r--r--arch/x86/include/asm/calling.h52
-rw-r--r--arch/x86/include/asm/cpu.h1
-rw-r--r--arch/x86/include/asm/cpufeature.h13
-rw-r--r--arch/x86/include/asm/dwarf2.h20
-rw-r--r--arch/x86/include/asm/e820.h20
-rw-r--r--arch/x86/include/asm/efi.h2
-rw-r--r--arch/x86/include/asm/entry_arch.h23
-rw-r--r--arch/x86/include/asm/fixmap.h15
-rw-r--r--arch/x86/include/asm/gart.h20
-rw-r--r--arch/x86/include/asm/hardirq.h2
-rw-r--r--arch/x86/include/asm/hpet.h10
-rw-r--r--arch/x86/include/asm/hw_irq.h19
-rw-r--r--arch/x86/include/asm/i387.h185
-rw-r--r--arch/x86/include/asm/i8259.h2
-rw-r--r--arch/x86/include/asm/io.h2
-rw-r--r--arch/x86/include/asm/io_apic.h6
-rw-r--r--arch/x86/include/asm/iommu_table.h100
-rw-r--r--arch/x86/include/asm/irq.h12
-rw-r--r--arch/x86/include/asm/irq_remapping.h35
-rw-r--r--arch/x86/include/asm/irq_vectors.h4
-rw-r--r--arch/x86/include/asm/irqflags.h32
-rw-r--r--arch/x86/include/asm/jump_label.h37
-rw-r--r--arch/x86/include/asm/kvm_host.h24
-rw-r--r--arch/x86/include/asm/memblock.h23
-rw-r--r--arch/x86/include/asm/module.h7
-rw-r--r--arch/x86/include/asm/mrst.h10
-rw-r--r--arch/x86/include/asm/mwait.h15
-rw-r--r--arch/x86/include/asm/olpc_ofw.h4
-rw-r--r--arch/x86/include/asm/page_32_types.h4
-rw-r--r--arch/x86/include/asm/page_types.h2
-rw-r--r--arch/x86/include/asm/paravirt.h21
-rw-r--r--arch/x86/include/asm/paravirt_types.h1
-rw-r--r--arch/x86/include/asm/percpu.h14
-rw-r--r--arch/x86/include/asm/perf_event_p4.h52
-rw-r--r--arch/x86/include/asm/pgtable.h4
-rw-r--r--arch/x86/include/asm/pgtable_32.h2
-rw-r--r--arch/x86/include/asm/pgtable_64.h2
-rw-r--r--arch/x86/include/asm/processor.h29
-rw-r--r--arch/x86/include/asm/segment.h32
-rw-r--r--arch/x86/include/asm/setup.h5
-rw-r--r--arch/x86/include/asm/swiotlb.h13
-rw-r--r--arch/x86/include/asm/tlbflush.h2
-rw-r--r--arch/x86/include/asm/trampoline.h3
-rw-r--r--arch/x86/include/asm/vmi.h269
-rw-r--r--arch/x86/include/asm/vmi_time.h98
-rw-r--r--arch/x86/kernel/Makefile10
-rw-r--r--arch/x86/kernel/acpi/cstate.c13
-rw-r--r--arch/x86/kernel/acpi/sleep.c16
-rw-r--r--arch/x86/kernel/alternative.c71
-rw-r--r--arch/x86/kernel/amd_iommu.c2
-rw-r--r--arch/x86/kernel/amd_iommu_init.c139
-rw-r--r--arch/x86/kernel/amd_nb.c (renamed from arch/x86/kernel/k8.c)56
-rw-r--r--arch/x86/kernel/apb_timer.c60
-rw-r--r--arch/x86/kernel/aperture_64.c31
-rw-r--r--arch/x86/kernel/apic/apic.c91
-rw-r--r--arch/x86/kernel/apic/io_apic.c877
-rw-r--r--arch/x86/kernel/apic/nmi.c2
-rw-r--r--arch/x86/kernel/apic/numaq_32.c3
-rw-r--r--arch/x86/kernel/apic/probe_64.c3
-rw-r--r--arch/x86/kernel/apm_32.c1
-rw-r--r--arch/x86/kernel/asm-offsets_32.c4
-rw-r--r--arch/x86/kernel/check.c16
-rw-r--r--arch/x86/kernel/cpu/amd.c77
-rw-r--r--arch/x86/kernel/cpu/common.c26
-rw-r--r--arch/x86/kernel/cpu/cpu.h2
-rw-r--r--arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c18
-rw-r--r--arch/x86/kernel/cpu/intel.c7
-rw-r--r--arch/x86/kernel/cpu/intel_cacheinfo.c14
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce-severity.c1
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce.c1
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce_amd.c36
-rw-r--r--arch/x86/kernel/cpu/mcheck/therm_throt.c5
-rw-r--r--arch/x86/kernel/cpu/mtrr/cleanup.c2
-rw-r--r--arch/x86/kernel/cpu/mtrr/generic.c128
-rw-r--r--arch/x86/kernel/cpu/perf_event.c280
-rw-r--r--arch/x86/kernel/cpu/perf_event_amd.c4
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel.c8
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_ds.c13
-rw-r--r--arch/x86/kernel/cpu/perf_event_p4.c298
-rw-r--r--arch/x86/kernel/cpu/perfctr-watchdog.c9
-rw-r--r--arch/x86/kernel/cpu/scattered.c6
-rw-r--r--arch/x86/kernel/crash_dump_64.c3
-rw-r--r--arch/x86/kernel/e820.c191
-rw-r--r--arch/x86/kernel/early-quirks.c2
-rw-r--r--arch/x86/kernel/early_printk.c13
-rw-r--r--arch/x86/kernel/early_printk_mrst.c319
-rw-r--r--arch/x86/kernel/efi.c5
-rw-r--r--arch/x86/kernel/entry_32.S310
-rw-r--r--arch/x86/kernel/entry_64.S134
-rw-r--r--arch/x86/kernel/ftrace.c63
-rw-r--r--arch/x86/kernel/head.c3
-rw-r--r--arch/x86/kernel/head32.c11
-rw-r--r--arch/x86/kernel/head64.c9
-rw-r--r--arch/x86/kernel/head_32.S55
-rw-r--r--arch/x86/kernel/hpet.c69
-rw-r--r--arch/x86/kernel/i387.c58
-rw-r--r--arch/x86/kernel/i8259.c63
-rw-r--r--arch/x86/kernel/irq.c32
-rw-r--r--arch/x86/kernel/irq_32.c12
-rw-r--r--arch/x86/kernel/irq_work.c30
-rw-r--r--arch/x86/kernel/irqinit.c23
-rw-r--r--arch/x86/kernel/jump_label.c50
-rw-r--r--arch/x86/kernel/kdebugfs.c1
-rw-r--r--arch/x86/kernel/kgdb.c11
-rw-r--r--arch/x86/kernel/kprobes.c14
-rw-r--r--arch/x86/kernel/machine_kexec_64.c4
-rw-r--r--arch/x86/kernel/microcode_core.c1
-rw-r--r--arch/x86/kernel/module.c6
-rw-r--r--arch/x86/kernel/mpparse.c5
-rw-r--r--arch/x86/kernel/olpc-xo1.c140
-rw-r--r--arch/x86/kernel/olpc.c89
-rw-r--r--arch/x86/kernel/olpc_ofw.c6
-rw-r--r--arch/x86/kernel/paravirt.c1
-rw-r--r--arch/x86/kernel/pci-calgary_64.c18
-rw-r--r--arch/x86/kernel/pci-dma.c44
-rw-r--r--arch/x86/kernel/pci-gart_64.c33
-rw-r--r--arch/x86/kernel/pci-iommu_table.c89
-rw-r--r--arch/x86/kernel/pci-swiotlb.c44
-rw-r--r--arch/x86/kernel/pmtimer_64.c69
-rw-r--r--arch/x86/kernel/process_64.c2
-rw-r--r--arch/x86/kernel/quirks.c2
-rw-r--r--arch/x86/kernel/reboot.c12
-rw-r--r--arch/x86/kernel/setup.c233
-rw-r--r--arch/x86/kernel/setup_percpu.c8
-rw-r--r--arch/x86/kernel/sfi.c4
-rw-r--r--arch/x86/kernel/smpboot.c134
-rw-r--r--arch/x86/kernel/sys_i386_32.c4
-rw-r--r--arch/x86/kernel/tlb_uv.c12
-rw-r--r--arch/x86/kernel/trampoline.c26
-rw-r--r--arch/x86/kernel/traps.c36
-rw-r--r--arch/x86/kernel/tsc.c66
-rw-r--r--arch/x86/kernel/uv_irq.c55
-rw-r--r--arch/x86/kernel/visws_quirks.c140
-rw-r--r--arch/x86/kernel/vm86_32.c10
-rw-r--r--arch/x86/kernel/vmi_32.c893
-rw-r--r--arch/x86/kernel/vmiclock_32.c317
-rw-r--r--arch/x86/kernel/vmlinux.lds.S30
-rw-r--r--arch/x86/kvm/lapic.c3
-rw-r--r--arch/x86/kvm/svm.c17
-rw-r--r--arch/x86/kvm/vmx.c24
-rw-r--r--arch/x86/kvm/x86.c7
-rw-r--r--arch/x86/lguest/boot.c18
-rw-r--r--arch/x86/lib/memcpy_32.c199
-rw-r--r--arch/x86/lib/memcpy_64.S158
-rw-r--r--arch/x86/lib/memmove_64.c189
-rw-r--r--arch/x86/mm/Makefile2
-rw-r--r--arch/x86/mm/fault.c47
-rw-r--r--arch/x86/mm/init.c10
-rw-r--r--arch/x86/mm/init_32.c166
-rw-r--r--arch/x86/mm/init_64.c116
-rw-r--r--arch/x86/mm/ioremap.c5
-rw-r--r--arch/x86/mm/k8topology_64.c12
-rw-r--r--arch/x86/mm/kmemcheck/kmemcheck.c2
-rw-r--r--arch/x86/mm/kmemcheck/opcode.c2
-rw-r--r--arch/x86/mm/memblock.c348
-rw-r--r--arch/x86/mm/memtest.c7
-rw-r--r--arch/x86/mm/numa_32.c30
-rw-r--r--arch/x86/mm/numa_64.c86
-rw-r--r--arch/x86/mm/pgtable.c24
-rw-r--r--arch/x86/mm/srat_32.c3
-rw-r--r--arch/x86/mm/srat_64.c17
-rw-r--r--arch/x86/mm/tlb.c48
-rw-r--r--arch/x86/oprofile/backtrace.c70
-rw-r--r--arch/x86/oprofile/nmi_int.c10
-rw-r--r--arch/x86/oprofile/op_model_amd.c145
-rw-r--r--arch/x86/pci/olpc.c2
-rw-r--r--arch/x86/xen/debugfs.c1
-rw-r--r--arch/x86/xen/enlighten.c3
-rw-r--r--arch/x86/xen/mmu.c32
-rw-r--r--arch/x86/xen/pci-swiotlb-xen.c5
-rw-r--r--arch/x86/xen/setup.c3
-rw-r--r--arch/x86/xen/spinlock.c2
-rw-r--r--arch/x86/xen/time.c5
-rw-r--r--arch/xtensa/include/asm/irqflags.h58
-rw-r--r--arch/xtensa/include/asm/system.h33
-rw-r--r--arch/xtensa/kernel/irq.c2
-rw-r--r--block/Kconfig12
-rw-r--r--block/Makefile3
-rw-r--r--block/blk-barrier.c350
-rw-r--r--block/blk-cgroup.c804
-rw-r--r--block/blk-cgroup.h87
-rw-r--r--block/blk-core.c123
-rw-r--r--block/blk-exec.c9
-rw-r--r--block/blk-flush.c262
-rw-r--r--block/blk-integrity.c94
-rw-r--r--block/blk-lib.c39
-rw-r--r--block/blk-map.c5
-rw-r--r--block/blk-merge.c25
-rw-r--r--block/blk-settings.c32
-rw-r--r--block/blk-sysfs.c13
-rw-r--r--block/blk-throttle.c1123
-rw-r--r--block/blk.h20
-rw-r--r--block/bsg.c6
-rw-r--r--block/cfq-iosched.c39
-rw-r--r--block/cfq.h2
-rw-r--r--block/elevator.c91
-rw-r--r--block/genhd.c37
-rw-r--r--block/ioctl.c6
-rw-r--r--crypto/des_generic.c130
-rw-r--r--drivers/acpi/Kconfig2
-rw-r--r--drivers/acpi/acpi_pad.c41
-rw-r--r--drivers/acpi/acpica/aclocal.h1
-rw-r--r--drivers/acpi/acpica/exutils.c2
-rw-r--r--drivers/acpi/acpica/rsutils.c2
-rw-r--r--drivers/acpi/apei/Kconfig2
-rw-r--r--drivers/acpi/apei/apei-base.c21
-rw-r--r--drivers/acpi/apei/einj.c4
-rw-r--r--drivers/acpi/apei/erst-dbg.c19
-rw-r--r--drivers/acpi/apei/erst.c29
-rw-r--r--drivers/acpi/apei/ghes.c2
-rw-r--r--drivers/acpi/apei/hest.c11
-rw-r--r--drivers/acpi/atomicio.c2
-rw-r--r--drivers/acpi/battery.c1
-rw-r--r--drivers/acpi/blacklist.c35
-rw-r--r--drivers/acpi/bus.c18
-rw-r--r--drivers/acpi/debugfs.c1
-rw-r--r--drivers/acpi/ec_sys.c1
-rw-r--r--drivers/acpi/event.c1
-rw-r--r--drivers/acpi/fan.c2
-rw-r--r--drivers/acpi/processor_core.c7
-rw-r--r--drivers/acpi/processor_driver.c2
-rw-r--r--drivers/acpi/processor_perflib.c4
-rw-r--r--drivers/acpi/sleep.c22
-rw-r--r--drivers/acpi/sysfs.c20
-rw-r--r--drivers/acpi/video_detect.c4
-rw-r--r--drivers/amba/bus.c2
-rw-r--r--drivers/ata/Makefile2
-rw-r--r--drivers/ata/ahci.c3
-rw-r--r--drivers/ata/ahci.h4
-rw-r--r--drivers/ata/ahci_platform.c3
-rw-r--r--drivers/ata/ata_generic.c54
-rw-r--r--drivers/ata/ata_piix.c34
-rw-r--r--drivers/ata/libahci.c194
-rw-r--r--drivers/ata/libata-core.c389
-rw-r--r--drivers/ata/libata-eh.c254
-rw-r--r--drivers/ata/libata-pmp.c66
-rw-r--r--drivers/ata/libata-scsi.c204
-rw-r--r--drivers/ata/libata-sff.c16
-rw-r--r--drivers/ata/libata-transport.c774
-rw-r--r--drivers/ata/libata-transport.h18
-rw-r--r--drivers/ata/libata.h21
-rw-r--r--drivers/ata/pata_bf54x.c6
-rw-r--r--drivers/ata/pata_cmd640.c12
-rw-r--r--drivers/ata/pata_pcmcia.c104
-rw-r--r--drivers/ata/pata_pdc202xx_old.c23
-rw-r--r--drivers/ata/pata_samsung_cf.c2
-rw-r--r--drivers/ata/pata_scc.c4
-rw-r--r--drivers/ata/pata_sil680.c16
-rw-r--r--drivers/ata/pata_sl82c105.c11
-rw-r--r--drivers/ata/sata_fsl.c27
-rw-r--r--drivers/ata/sata_inic162x.c2
-rw-r--r--drivers/ata/sata_mv.c25
-rw-r--r--drivers/ata/sata_nv.c57
-rw-r--r--drivers/ata/sata_sil24.c14
-rw-r--r--drivers/ata/sata_via.c2
-rw-r--r--drivers/atm/Makefile2
-rw-r--r--drivers/atm/firestream.c4
-rw-r--r--drivers/atm/horizon.c6
-rw-r--r--drivers/atm/idt77252.c6
-rw-r--r--drivers/atm/iphase.c8
-rw-r--r--drivers/atm/iphase.h2
-rw-r--r--drivers/atm/solos-pci.c8
-rw-r--r--drivers/base/Kconfig1
-rw-r--r--drivers/base/Makefile4
-rw-r--r--drivers/base/bus.c22
-rw-r--r--drivers/base/class.c23
-rw-r--r--drivers/base/core.c208
-rw-r--r--drivers/base/memory.c94
-rw-r--r--drivers/base/node.c8
-rw-r--r--drivers/base/platform.c80
-rw-r--r--drivers/base/power/Makefile1
-rw-r--r--drivers/base/power/generic_ops.c4
-rw-r--r--drivers/base/power/main.c21
-rw-r--r--drivers/base/power/opp.c628
-rw-r--r--drivers/base/power/power.h2
-rw-r--r--drivers/base/power/runtime.c944
-rw-r--r--drivers/base/power/sysfs.c217
-rw-r--r--drivers/base/power/trace.c36
-rw-r--r--drivers/base/power/wakeup.c613
-rw-r--r--drivers/base/sys.c8
-rw-r--r--drivers/base/topology.c16
-rw-r--r--drivers/block/DAC960.c14
-rw-r--r--drivers/block/Kconfig17
-rw-r--r--drivers/block/Makefile1
-rw-r--r--drivers/block/amiflop.c79
-rw-r--r--drivers/block/aoe/aoeblk.c9
-rw-r--r--drivers/block/aoe/aoechr.c10
-rw-r--r--drivers/block/ataflop.c65
-rw-r--r--drivers/block/brd.c8
-rw-r--r--drivers/block/cciss.c878
-rw-r--r--drivers/block/cpqarray.c15
-rw-r--r--drivers/block/drbd/drbd_actlog.c41
-rw-r--r--drivers/block/drbd/drbd_bitmap.c2
-rw-r--r--drivers/block/drbd/drbd_int.h219
-rw-r--r--drivers/block/drbd/drbd_main.c604
-rw-r--r--drivers/block/drbd/drbd_nl.c270
-rw-r--r--drivers/block/drbd/drbd_proc.c34
-rw-r--r--drivers/block/drbd/drbd_receiver.c949
-rw-r--r--drivers/block/drbd/drbd_req.c165
-rw-r--r--drivers/block/drbd/drbd_req.h62
-rw-r--r--drivers/block/drbd/drbd_worker.c292
-rw-r--r--drivers/block/floppy.c82
-rw-r--r--drivers/block/loop.c132
-rw-r--r--drivers/block/nbd.c7
-rw-r--r--drivers/block/osdblk.c5
-rw-r--r--drivers/block/paride/pcd.c15
-rw-r--r--drivers/block/paride/pd.c15
-rw-r--r--drivers/block/paride/pf.c17
-rw-r--r--drivers/block/paride/pg.c8
-rw-r--r--drivers/block/paride/pt.c20
-rw-r--r--drivers/block/pktcdvd.c18
-rw-r--r--drivers/block/ps3disk.c4
-rw-r--r--drivers/block/rbd.c1841
-rw-r--r--drivers/block/rbd_types.h73
-rw-r--r--drivers/block/swim.c15
-rw-r--r--drivers/block/swim3.c15
-rw-r--r--drivers/block/ub.c17
-rw-r--r--drivers/block/viodasd.c11
-rw-r--r--drivers/block/virtio_blk.c60
-rw-r--r--drivers/block/xd.c7
-rw-r--r--drivers/block/xen-blkfront.c65
-rw-r--r--drivers/block/xsysace.c11
-rw-r--r--drivers/block/z2ram.c15
-rw-r--r--drivers/bluetooth/bluecard_cs.c12
-rw-r--r--drivers/bluetooth/bt3c_cs.c64
-rw-r--r--drivers/bluetooth/btmrvl_debugfs.c10
-rw-r--r--drivers/bluetooth/btmrvl_main.c4
-rw-r--r--drivers/bluetooth/btsdio.c8
-rw-r--r--drivers/bluetooth/btuart_cs.c62
-rw-r--r--drivers/bluetooth/btusb.c6
-rw-r--r--drivers/bluetooth/dtl1_cs.c27
-rw-r--r--drivers/bluetooth/hci_ldisc.c9
-rw-r--r--drivers/bluetooth/hci_vhci.c1
-rw-r--r--drivers/cdrom/gdrom.c15
-rw-r--r--drivers/cdrom/viocd.c15
-rw-r--r--drivers/char/Kconfig15
-rw-r--r--drivers/char/Makefile1
-rw-r--r--drivers/char/agp/Kconfig2
-rw-r--r--drivers/char/agp/amd64-agp.c39
-rw-r--r--drivers/char/agp/generic.c4
-rw-r--r--drivers/char/amiserial.c56
-rw-r--r--drivers/char/apm-emulation.c12
-rw-r--r--drivers/char/applicom.c9
-rw-r--r--drivers/char/bfin-otp.c1
-rw-r--r--drivers/char/briq_panel.c1
-rw-r--r--drivers/char/bsr.c1
-rw-r--r--drivers/char/cs5535_gpio.c3
-rw-r--r--drivers/char/cyclades.c49
-rw-r--r--drivers/char/ds1302.c16
-rw-r--r--drivers/char/ds1620.c9
-rw-r--r--drivers/char/dsp56k.c28
-rw-r--r--drivers/char/dtlk.c9
-rw-r--r--drivers/char/generic_nvram.c7
-rw-r--r--drivers/char/genrtc.c14
-rw-r--r--drivers/char/hpet.c98
-rw-r--r--drivers/char/hw_random/core.c1
-rw-r--r--drivers/char/i8k.c7
-rw-r--r--drivers/char/ip2/ip2main.c81
-rw-r--r--drivers/char/ipmi/ipmi_devintf.c15
-rw-r--r--drivers/char/ipmi/ipmi_watchdog.c9
-rw-r--r--drivers/char/istallion.c1
-rw-r--r--drivers/char/lp.c16
-rw-r--r--drivers/char/mbcs.c8
-rw-r--r--drivers/char/mem.c3
-rw-r--r--drivers/char/misc.c1
-rw-r--r--drivers/char/mmtimer.c8
-rw-r--r--drivers/char/mspec.c9
-rw-r--r--drivers/char/mwave/mwavedd.c47
-rw-r--r--drivers/char/mxser.c109
-rw-r--r--drivers/char/nozomi.c37
-rw-r--r--drivers/char/nvram.c11
-rw-r--r--drivers/char/nwbutton.c1
-rw-r--r--drivers/char/nwflash.c12
-rw-r--r--drivers/char/pc8736x_gpio.c1
-rw-r--r--drivers/char/pcmcia/cm4000_cs.c42
-rw-r--r--drivers/char/pcmcia/cm4040_cs.c47
-rw-r--r--drivers/char/pcmcia/ipwireless/main.c117
-rw-r--r--drivers/char/pcmcia/ipwireless/main.h5
-rw-r--r--drivers/char/pcmcia/ipwireless/tty.h1
-rw-r--r--drivers/char/pcmcia/synclink_cs.c106
-rw-r--r--drivers/char/ppdev.c8
-rw-r--r--drivers/char/pty.c4
-rw-r--r--drivers/char/random.c2
-rw-r--r--drivers/char/raw.c245
-rw-r--r--drivers/char/rio/rio_linux.c8
-rw-r--r--drivers/char/scx200_gpio.c1
-rw-r--r--drivers/char/snsc.c10
-rw-r--r--drivers/char/stallion.c1
-rw-r--r--drivers/char/sx.c1
-rw-r--r--drivers/char/synclink.c73
-rw-r--r--drivers/char/synclink_gt.c55
-rw-r--r--drivers/char/synclinkmp.c61
-rw-r--r--drivers/char/sysrq.c1
-rw-r--r--drivers/char/tb0219.c1
-rw-r--r--drivers/char/tlclk.c7
-rw-r--r--drivers/char/toshiba.c10
-rw-r--r--drivers/char/tpm/tpm.c22
-rw-r--r--drivers/char/tty_io.c77
-rw-r--r--drivers/char/ttyprintk.c225
-rw-r--r--drivers/char/uv_mmtimer.c1
-rw-r--r--drivers/char/vc_screen.c135
-rw-r--r--drivers/char/viotape.c12
-rw-r--r--drivers/char/virtio_console.c257
-rw-r--r--drivers/char/vt.c5
-rw-r--r--drivers/char/xilinx_hwicap/xilinx_hwicap.c7
-rw-r--r--drivers/cpuidle/governors/menu.c2
-rw-r--r--drivers/dma/coh901318.c1
-rw-r--r--drivers/dma/ioat/dma_v2.c2
-rw-r--r--drivers/dma/shdma.c3
-rw-r--r--drivers/edac/Kconfig16
-rw-r--r--drivers/edac/Makefile3
-rw-r--r--drivers/edac/amd64_edac.c17
-rw-r--r--drivers/edac/amd64_edac.h5
-rw-r--r--drivers/edac/amd64_edac_dbg.c207
-rw-r--r--drivers/edac/edac_device_sysfs.c16
-rw-r--r--drivers/edac/edac_mc_sysfs.c11
-rw-r--r--drivers/edac/edac_mce_amd.c452
-rw-r--r--drivers/edac/edac_module.c79
-rw-r--r--drivers/edac/edac_module.h1
-rw-r--r--drivers/edac/edac_pci_sysfs.c10
-rw-r--r--drivers/edac/edac_stub.c51
-rw-r--r--drivers/edac/i7core_edac.c1
-rw-r--r--drivers/edac/mce_amd.c680
-rw-r--r--drivers/edac/mce_amd.h (renamed from drivers/edac/edac_mce_amd.h)59
-rw-r--r--drivers/edac/mce_amd_inj.c171
-rw-r--r--drivers/firewire/net.c13
-rw-r--r--drivers/firewire/nosy.c1
-rw-r--r--drivers/firewire/ohci.c19
-rw-r--r--drivers/firewire/ohci.h8
-rw-r--r--drivers/firmware/Kconfig2
-rw-r--r--drivers/gpio/tc35892-gpio.c8
-rw-r--r--drivers/gpu/drm/Kconfig5
-rw-r--r--drivers/gpu/drm/drm_drv.c3
-rw-r--r--drivers/gpu/drm/drm_gem.c39
-rw-r--r--drivers/gpu/drm/drm_info.c2
-rw-r--r--drivers/gpu/drm/drm_vm.c28
-rw-r--r--drivers/gpu/drm/i810/i810_dma.c3
-rw-r--r--drivers/gpu/drm/i810/i810_drv.c1
-rw-r--r--drivers/gpu/drm/i830/i830_dma.c3
-rw-r--r--drivers/gpu/drm/i830/i830_drv.c1
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c1
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c9
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c1
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c52
-rw-r--r--drivers/gpu/drm/i915/i915_gem_evict.c45
-rw-r--r--drivers/gpu/drm/i915/intel_display.c62
-rw-r--r--drivers/gpu/drm/i915/intel_dp.c19
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h1
-rw-r--r--drivers/gpu/drm/i915/intel_fb.c4
-rw-r--r--drivers/gpu/drm/mga/mga_drv.c1
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.c1
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_gem.c6
-rw-r--r--drivers/gpu/drm/r128/r128_drv.c1
-rw-r--r--drivers/gpu/drm/radeon/evergreen.c5
-rw-r--r--drivers/gpu/drm/radeon/r100.c3
-rw-r--r--drivers/gpu/drm/radeon/r600.c7
-rw-r--r--drivers/gpu/drm/radeon/r600_blit_kms.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon.h1
-rw-r--r--drivers/gpu/drm/radeon/radeon_atombios.c27
-rw-r--r--drivers/gpu/drm/radeon/radeon_combios.c26
-rw-r--r--drivers/gpu/drm/radeon/radeon_cursor.c28
-rw-r--r--drivers/gpu/drm/radeon/radeon_display.c5
-rw-r--r--drivers/gpu/drm/radeon/radeon_drv.c1
-rw-r--r--drivers/gpu/drm/radeon/radeon_fb.c13
-rw-r--r--drivers/gpu/drm/radeon/radeon_gem.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_object.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_object.h5
-rw-r--r--drivers/gpu/drm/radeon/rs600.c1
-rw-r--r--drivers/gpu/drm/radeon/rs690.c1
-rw-r--r--drivers/gpu/drm/radeon/rv770.c2
-rw-r--r--drivers/gpu/drm/savage/savage_drv.c1
-rw-r--r--drivers/gpu/drm/sis/sis_drv.c1
-rw-r--r--drivers/gpu/drm/tdfx/tdfx_drv.c1
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo.c83
-rw-r--r--drivers/gpu/drm/via/via_drv.c1
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.c146
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.h8
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_fb.c5
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c3
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.c17
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c27
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_resource.c4
-rw-r--r--drivers/gpu/vga/vgaarb.c1
-rw-r--r--drivers/hid/hid-cando.c2
-rw-r--r--drivers/hid/hid-core.c2
-rw-r--r--drivers/hid/hid-debug.c1
-rw-r--r--drivers/hid/hid-ids.h5
-rw-r--r--drivers/hid/hid-roccat.c1
-rw-r--r--drivers/hid/hidraw.c12
-rw-r--r--drivers/hid/usbhid/hid-quirks.c1
-rw-r--r--drivers/hid/usbhid/hiddev.c1
-rw-r--r--drivers/hwmon/asus_atk0110.c1
-rw-r--r--drivers/hwmon/f71882fg.c32
-rw-r--r--drivers/hwmon/fschmd.c6
-rw-r--r--drivers/hwmon/w83793.c6
-rw-r--r--drivers/i2c/busses/i2c-cpm.c5
-rw-r--r--drivers/i2c/busses/i2c-davinci.c24
-rw-r--r--drivers/i2c/busses/i2c-ibm_iic.c3
-rw-r--r--drivers/i2c/busses/i2c-imx.c12
-rw-r--r--drivers/i2c/busses/i2c-mpc.c1
-rw-r--r--drivers/i2c/busses/i2c-octeon.c2
-rw-r--r--drivers/i2c/busses/i2c-pasemi.c2
-rw-r--r--drivers/i2c/busses/i2c-pca-isa.c12
-rw-r--r--drivers/i2c/busses/i2c-pca-platform.c11
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c4
-rw-r--r--drivers/i2c/i2c-core.c54
-rw-r--r--drivers/ide/ide-cd.c14
-rw-r--r--drivers/ide/ide-cs.c156
-rw-r--r--drivers/ide/ide-disk.c13
-rw-r--r--drivers/ide/ide-disk_ioctl.c7
-rw-r--r--drivers/ide/ide-floppy_ioctl.c7
-rw-r--r--drivers/ide/ide-gd.c10
-rw-r--r--drivers/ide/ide-io.c13
-rw-r--r--drivers/ide/ide-tape.c20
-rw-r--r--drivers/idle/i7300_idle.c1
-rw-r--r--[-rwxr-xr-x]drivers/idle/intel_idle.c39
-rw-r--r--drivers/ieee1394/eth1394.c16
-rw-r--r--drivers/infiniband/hw/ipath/ipath_diag.c4
-rw-r--r--drivers/infiniband/hw/ipath/ipath_file_ops.c3
-rw-r--r--drivers/infiniband/hw/ipath/ipath_fs.c3
-rw-r--r--drivers/infiniband/hw/mlx4/Kconfig1
-rw-r--r--drivers/infiniband/hw/nes/nes_cm.c4
-rw-r--r--drivers/infiniband/hw/nes/nes_verbs.c4
-rw-r--r--drivers/infiniband/hw/qib/qib_diag.c4
-rw-r--r--drivers/infiniband/hw/qib/qib_file_ops.c3
-rw-r--r--drivers/infiniband/hw/qib/qib_fs.c1
-rw-r--r--drivers/input/evdev.c13
-rw-r--r--drivers/input/input.c1
-rw-r--r--drivers/input/joydev.c4
-rw-r--r--drivers/input/keyboard/Kconfig2
-rw-r--r--drivers/input/keyboard/pxa27x_keypad.c12
-rw-r--r--drivers/input/misc/hp_sdc_rtc.c11
-rw-r--r--drivers/input/misc/uinput.c8
-rw-r--r--drivers/input/mousedev.c1
-rw-r--r--drivers/input/serio/hil_mlc.c6
-rw-r--r--drivers/input/serio/hp_sdc.c4
-rw-r--r--drivers/input/serio/serio_raw.c1
-rw-r--r--drivers/input/serio/serport.c1
-rw-r--r--drivers/input/tablet/wacom_sys.c23
-rw-r--r--drivers/input/tablet/wacom_wac.c4
-rw-r--r--drivers/isdn/act2000/act2000.h6
-rw-r--r--drivers/isdn/capi/capidrv.c17
-rw-r--r--drivers/isdn/capi/kcapi.c19
-rw-r--r--drivers/isdn/divert/isdn_divert.c6
-rw-r--r--drivers/isdn/gigaset/bas-gigaset.c400
-rw-r--r--drivers/isdn/gigaset/common.c26
-rw-r--r--drivers/isdn/gigaset/gigaset.h3
-rw-r--r--drivers/isdn/gigaset/i4l.c2
-rw-r--r--drivers/isdn/gigaset/isocdata.c8
-rw-r--r--drivers/isdn/hardware/avm/avm_cs.c83
-rw-r--r--drivers/isdn/hardware/eicon/debug.c2
-rw-r--r--drivers/isdn/hardware/eicon/debuglib.h2
-rw-r--r--drivers/isdn/hardware/eicon/divasmain.c2
-rw-r--r--drivers/isdn/hisax/avma1_cs.c97
-rw-r--r--drivers/isdn/hisax/config.c18
-rw-r--r--drivers/isdn/hisax/elsa_cs.c100
-rw-r--r--drivers/isdn/hisax/hfc_sx.c13
-rw-r--r--drivers/isdn/hisax/hisax.h1
-rw-r--r--drivers/isdn/hisax/sedlbauer_cs.c168
-rw-r--r--drivers/isdn/hisax/teles_cs.c98
-rw-r--r--drivers/isdn/i4l/isdn_tty.c15
-rw-r--r--drivers/isdn/mISDN/dsp_cmx.c1
-rw-r--r--drivers/isdn/mISDN/l1oip_core.c2
-rw-r--r--drivers/isdn/mISDN/stack.c7
-rw-r--r--drivers/isdn/mISDN/timerdev.c1
-rw-r--r--drivers/isdn/pcbit/edss1.c2
-rw-r--r--drivers/isdn/pcbit/edss1.h2
-rw-r--r--drivers/isdn/sc/interrupt.c18
-rw-r--r--drivers/leds/Kconfig11
-rw-r--r--drivers/leds/Makefile1
-rw-r--r--drivers/leds/leds-netxbig.c449
-rw-r--r--drivers/leds/leds-ns2.c9
-rw-r--r--drivers/lguest/lguest_user.c1
-rw-r--r--drivers/macintosh/adb.c12
-rw-r--r--drivers/macintosh/ans-lcd.c1
-rw-r--r--drivers/macintosh/smu.c6
-rw-r--r--drivers/macintosh/via-pmu-led.c4
-rw-r--r--drivers/macintosh/via-pmu.c12
-rw-r--r--drivers/md/bitmap.c9
-rw-r--r--drivers/md/dm-crypt.c2
-rw-r--r--drivers/md/dm-io.c20
-rw-r--r--drivers/md/dm-ioctl.c1
-rw-r--r--drivers/md/dm-log.c2
-rw-r--r--drivers/md/dm-raid1.c8
-rw-r--r--drivers/md/dm-region-hash.c16
-rw-r--r--drivers/md/dm-snap-persistent.c2
-rw-r--r--drivers/md/dm-snap.c8
-rw-r--r--drivers/md/dm-stripe.c2
-rw-r--r--drivers/md/dm-table.c5
-rw-r--r--drivers/md/dm.c408
-rw-r--r--drivers/md/linear.c4
-rw-r--r--drivers/md/md.c130
-rw-r--r--drivers/md/md.h23
-rw-r--r--drivers/md/multipath.c4
-rw-r--r--drivers/md/raid0.c4
-rw-r--r--drivers/md/raid1.c180
-rw-r--r--drivers/md/raid1.h2
-rw-r--r--drivers/md/raid10.c7
-rw-r--r--drivers/md/raid5.c43
-rw-r--r--drivers/md/raid5.h1
-rw-r--r--drivers/media/IR/imon.c6
-rw-r--r--drivers/media/IR/ir-keytable.c9
-rw-r--r--drivers/media/IR/ir-lirc-codec.c3
-rw-r--r--drivers/media/IR/ir-raw-event.c4
-rw-r--r--drivers/media/IR/ir-sysfs.c17
-rw-r--r--drivers/media/IR/keymaps/rc-rc6-mce.c3
-rw-r--r--drivers/media/IR/lirc_dev.c3
-rw-r--r--drivers/media/IR/mceusb.c4
-rw-r--r--drivers/media/Kconfig1
-rw-r--r--drivers/media/dvb/bt8xx/dst_ca.c10
-rw-r--r--drivers/media/dvb/dvb-core/dmxdev.c19
-rw-r--r--drivers/media/dvb/dvb-core/dvb_ca_en50221.c9
-rw-r--r--drivers/media/dvb/dvb-core/dvb_frontend.c3
-rw-r--r--drivers/media/dvb/dvb-core/dvb_net.c10
-rw-r--r--drivers/media/dvb/dvb-core/dvbdev.c18
-rw-r--r--drivers/media/dvb/dvb-usb/dib0700_core.c3
-rw-r--r--drivers/media/dvb/dvb-usb/dib0700_devices.c56
-rw-r--r--drivers/media/dvb/dvb-usb/opera1.c4
-rw-r--r--drivers/media/dvb/firewire/firedtv-ci.c1
-rw-r--r--drivers/media/dvb/frontends/dib7000p.c8
-rw-r--r--drivers/media/dvb/frontends/dib7000p.h5
-rw-r--r--drivers/media/dvb/siano/smscoreapi.c31
-rw-r--r--drivers/media/dvb/ttpci/av7110.c1
-rw-r--r--drivers/media/dvb/ttpci/av7110_av.c2
-rw-r--r--drivers/media/dvb/ttpci/av7110_ca.c1
-rw-r--r--drivers/media/dvb/ttpci/av7110_ir.c1
-rw-r--r--drivers/media/radio/si470x/radio-si470x-i2c.c2
-rw-r--r--drivers/media/video/cx231xx/Makefile1
-rw-r--r--drivers/media/video/cx231xx/cx231xx-cards.c17
-rw-r--r--drivers/media/video/cx25840/cx25840-core.c2
-rw-r--r--drivers/media/video/cx88/Kconfig2
-rw-r--r--drivers/media/video/dabusb.c18
-rw-r--r--drivers/media/video/gspca/gspca.c1
-rw-r--r--drivers/media/video/gspca/sn9c20x.c3
-rw-r--r--drivers/media/video/ivtv/ivtvfb.c2
-rw-r--r--drivers/media/video/mem2mem_testdev.c3
-rw-r--r--drivers/media/video/mt9m111.c8
-rw-r--r--drivers/media/video/mt9v022.c3
-rw-r--r--drivers/media/video/mx2_camera.c4
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-ctrl.c6
-rw-r--r--drivers/media/video/s5p-fimc/fimc-core.c94
-rw-r--r--drivers/media/video/saa7134/saa7134-cards.c10
-rw-r--r--drivers/media/video/saa7164/saa7164-buffer.c5
-rw-r--r--drivers/media/video/uvc/uvc_driver.c24
-rw-r--r--drivers/media/video/uvc/uvcvideo.h1
-rw-r--r--drivers/media/video/v4l2-compat-ioctl32.c32
-rw-r--r--drivers/media/video/videobuf-dma-contig.c6
-rw-r--r--drivers/media/video/videobuf-dma-sg.c11
-rw-r--r--drivers/memstick/core/mspro_block.c11
-rw-r--r--drivers/message/fusion/mptbase.c4
-rw-r--r--drivers/message/fusion/mptctl.c15
-rw-r--r--drivers/message/i2o/i2o_block.c15
-rw-r--r--drivers/message/i2o/i2o_config.c23
-rw-r--r--drivers/mfd/ab3100-core.c1
-rw-r--r--drivers/mfd/ab8500-spi.c5
-rw-r--r--drivers/mfd/max8925-core.c13
-rw-r--r--drivers/mfd/twl4030-irq.c4
-rw-r--r--drivers/mfd/wm831x-irq.c9
-rw-r--r--drivers/misc/Kconfig22
-rw-r--r--drivers/misc/Makefile1
-rw-r--r--drivers/misc/bh1780gli.c1
-rw-r--r--drivers/misc/hpilo.c3
-rw-r--r--drivers/misc/ibmasm/ibmasmfs.c4
-rw-r--r--drivers/misc/iwmc3200top/debugfs.c3
-rw-r--r--drivers/misc/lkdtm.c9
-rw-r--r--drivers/misc/pch_phub.c717
-rw-r--r--drivers/misc/phantom.c12
-rw-r--r--drivers/misc/sgi-gru/grufile.c1
-rw-r--r--drivers/mmc/card/block.c10
-rw-r--r--drivers/mmc/card/queue.c1
-rw-r--r--drivers/mmc/core/core.c13
-rw-r--r--drivers/mmc/core/debugfs.c1
-rw-r--r--drivers/mmc/host/mmci.c62
-rw-r--r--drivers/mmc/host/mmci.h22
-rw-r--r--drivers/mmc/host/sdricoh_cs.c5
-rw-r--r--drivers/mtd/maps/pcmciamtd.c102
-rw-r--r--drivers/mtd/mtd_blkdevs.c14
-rw-r--r--drivers/mtd/mtdchar.c15
-rw-r--r--drivers/mtd/nand/mxc_nand.c92
-rw-r--r--drivers/mtd/nand/omap2.c2
-rw-r--r--drivers/mtd/ubi/Kconfig17
-rw-r--r--drivers/mtd/ubi/Kconfig.debug29
-rw-r--r--drivers/mtd/ubi/build.c6
-rw-r--r--drivers/mtd/ubi/cdev.c1
-rw-r--r--drivers/mtd/ubi/debug.h4
-rw-r--r--drivers/mtd/ubi/eba.c10
-rw-r--r--drivers/mtd/ubi/io.c138
-rw-r--r--drivers/mtd/ubi/misc.c19
-rw-r--r--drivers/mtd/ubi/scan.c387
-rw-r--r--drivers/mtd/ubi/scan.h19
-rw-r--r--drivers/mtd/ubi/ubi.h29
-rw-r--r--drivers/mtd/ubi/vmt.c6
-rw-r--r--drivers/mtd/ubi/vtbl.c10
-rw-r--r--drivers/mtd/ubi/wl.c31
-rw-r--r--drivers/net/3c503.c8
-rw-r--r--drivers/net/3c515.c6
-rw-r--r--drivers/net/3c523.c4
-rw-r--r--drivers/net/3c527.c4
-rw-r--r--drivers/net/3c59x.c2
-rw-r--r--drivers/net/8139cp.c4
-rw-r--r--drivers/net/Kconfig60
-rw-r--r--drivers/net/Makefile3
-rw-r--r--drivers/net/acenic.c2
-rw-r--r--drivers/net/amd8111e.c20
-rw-r--r--drivers/net/amd8111e.h1
-rw-r--r--drivers/net/appletalk/Kconfig1
-rw-r--r--drivers/net/appletalk/ipddp.c10
-rw-r--r--drivers/net/appletalk/ltpc.c2
-rw-r--r--drivers/net/arm/am79c961a.c35
-rw-r--r--drivers/net/arm/am79c961a.h1
-rw-r--r--drivers/net/arm/ep93xx_eth.c39
-rw-r--r--drivers/net/arm/ether1.c34
-rw-r--r--drivers/net/arm/ether1.h1
-rw-r--r--drivers/net/arm/ether3.c33
-rw-r--r--drivers/net/arm/ether3.h1
-rw-r--r--drivers/net/atarilance.c24
-rw-r--r--drivers/net/atl1c/atl1c.h1
-rw-r--r--drivers/net/atl1c/atl1c_hw.c2
-rw-r--r--drivers/net/atl1c/atl1c_main.c10
-rw-r--r--drivers/net/atl1e/atl1e_main.c6
-rw-r--r--drivers/net/atlx/atl1.c10
-rw-r--r--drivers/net/atlx/atl2.c12
-rw-r--r--drivers/net/atp.c2
-rw-r--r--drivers/net/au1000_eth.c313
-rw-r--r--drivers/net/au1000_eth.h42
-rw-r--r--drivers/net/ax88796.c1
-rw-r--r--drivers/net/b44.c25
-rw-r--r--drivers/net/bcm63xx_enet.c62
-rw-r--r--drivers/net/bcm63xx_enet.h1
-rw-r--r--drivers/net/benet/be.h100
-rw-r--r--drivers/net/benet/be_cmds.c103
-rw-r--r--drivers/net/benet/be_cmds.h65
-rw-r--r--drivers/net/benet/be_ethtool.c177
-rw-r--r--drivers/net/benet/be_main.c644
-rw-r--r--drivers/net/bfin_mac.c11
-rw-r--r--drivers/net/bmac.c9
-rw-r--r--drivers/net/bna/Makefile11
-rw-r--r--drivers/net/bna/bfa_cee.c291
-rw-r--r--drivers/net/bna/bfa_cee.h64
-rw-r--r--drivers/net/bna/bfa_defs.h243
-rw-r--r--drivers/net/bna/bfa_defs_cna.h223
-rw-r--r--drivers/net/bna/bfa_defs_mfg_comm.h244
-rw-r--r--drivers/net/bna/bfa_defs_status.h216
-rw-r--r--drivers/net/bna/bfa_ioc.c1732
-rw-r--r--drivers/net/bna/bfa_ioc.h300
-rw-r--r--drivers/net/bna/bfa_ioc_ct.c392
-rw-r--r--drivers/net/bna/bfa_sm.h (renamed from drivers/scsi/bfa/include/cs/bfa_sm.h)51
-rw-r--r--drivers/net/bna/bfa_wc.h (renamed from drivers/scsi/bfa/include/cs/bfa_wc.h)23
-rw-r--r--drivers/net/bna/bfi.h392
-rw-r--r--drivers/net/bna/bfi_cna.h199
-rw-r--r--drivers/net/bna/bfi_ctreg.h637
-rw-r--r--drivers/net/bna/bfi_ll.h438
-rw-r--r--drivers/net/bna/bna.h550
-rw-r--r--drivers/net/bna/bna_ctrl.c3261
-rw-r--r--drivers/net/bna/bna_hw.h1490
-rw-r--r--drivers/net/bna/bna_txrx.c4172
-rw-r--r--drivers/net/bna/bna_types.h1128
-rw-r--r--drivers/net/bna/bnad.c3264
-rw-r--r--drivers/net/bna/bnad.h332
-rw-r--r--drivers/net/bna/bnad_ethtool.c1277
-rw-r--r--drivers/net/bna/cna.h (renamed from drivers/scsi/bfa/include/cs/bfa_q.h)84
-rw-r--r--drivers/net/bna/cna_fwimg.c64
-rw-r--r--drivers/net/bnx2.c253
-rw-r--r--drivers/net/bnx2.h25
-rw-r--r--drivers/net/bnx2x/bnx2x.h710
-rw-r--r--drivers/net/bnx2x/bnx2x_cmn.c1017
-rw-r--r--drivers/net/bnx2x/bnx2x_cmn.h593
-rw-r--r--drivers/net/bnx2x/bnx2x_dump.h35
-rw-r--r--drivers/net/bnx2x/bnx2x_ethtool.c432
-rw-r--r--drivers/net/bnx2x/bnx2x_fw_defs.h819
-rw-r--r--drivers/net/bnx2x/bnx2x_fw_file_hdr.h1
-rw-r--r--drivers/net/bnx2x/bnx2x_hsi.h1778
-rw-r--r--drivers/net/bnx2x/bnx2x_init.h44
-rw-r--r--drivers/net/bnx2x/bnx2x_init_ops.h366
-rw-r--r--drivers/net/bnx2x/bnx2x_link.c8871
-rw-r--r--drivers/net/bnx2x/bnx2x_link.h242
-rw-r--r--drivers/net/bnx2x/bnx2x_main.c6024
-rw-r--r--drivers/net/bnx2x/bnx2x_reg.h938
-rw-r--r--drivers/net/bnx2x/bnx2x_stats.c305
-rw-r--r--drivers/net/bnx2x/bnx2x_stats.h8
-rw-r--r--drivers/net/bonding/bond_3ad.c276
-rw-r--r--drivers/net/bonding/bond_main.c190
-rw-r--r--drivers/net/bonding/bond_sysfs.c52
-rw-r--r--drivers/net/bonding/bonding.h34
-rw-r--r--drivers/net/bsd_comp.c2
-rw-r--r--drivers/net/caif/caif_spi.c6
-rw-r--r--drivers/net/can/mcp251x.c103
-rw-r--r--drivers/net/can/mscan/mpc5xxx_can.c8
-rw-r--r--drivers/net/cassini.c6
-rw-r--r--drivers/net/chelsio/sge.c6
-rw-r--r--drivers/net/chelsio/subr.c2
-rw-r--r--drivers/net/chelsio/vsc7326.c2
-rw-r--r--drivers/net/cnic.c955
-rw-r--r--drivers/net/cnic.h118
-rw-r--r--drivers/net/cnic_defs.h456
-rw-r--r--drivers/net/cnic_if.h23
-rw-r--r--drivers/net/cpmac.c39
-rw-r--r--drivers/net/cxgb3/adapter.h3
-rw-r--r--drivers/net/cxgb3/common.h18
-rw-r--r--drivers/net/cxgb3/cxgb3_defs.h3
-rw-r--r--drivers/net/cxgb3/cxgb3_main.c29
-rw-r--r--drivers/net/cxgb3/cxgb3_offload.c11
-rw-r--r--drivers/net/cxgb3/mc5.c38
-rw-r--r--drivers/net/cxgb3/regs.h4
-rw-r--r--drivers/net/cxgb3/sge.c45
-rw-r--r--drivers/net/cxgb3/t3_hw.c204
-rw-r--r--drivers/net/cxgb4/cxgb4.h17
-rw-r--r--drivers/net/cxgb4/cxgb4_main.c168
-rw-r--r--drivers/net/cxgb4/cxgb4_uld.h6
-rw-r--r--drivers/net/cxgb4/l2t.c34
-rw-r--r--drivers/net/cxgb4/l2t.h3
-rw-r--r--drivers/net/cxgb4/sge.c19
-rw-r--r--drivers/net/cxgb4/t4_hw.c332
-rw-r--r--drivers/net/cxgb4/t4_hw.h1
-rw-r--r--drivers/net/cxgb4/t4fw_api.h5
-rw-r--r--drivers/net/cxgb4vf/cxgb4vf_main.c5
-rw-r--r--drivers/net/cxgb4vf/sge.c3
-rw-r--r--drivers/net/cxgb4vf/t4vf_common.h26
-rw-r--r--drivers/net/de620.c2
-rw-r--r--drivers/net/declance.c2
-rw-r--r--drivers/net/defxx.c66
-rw-r--r--drivers/net/dl2k.c2
-rw-r--r--drivers/net/dm9000.c2
-rw-r--r--drivers/net/dnet.c18
-rw-r--r--drivers/net/dummy.c58
-rw-r--r--drivers/net/e100.c4
-rw-r--r--drivers/net/e1000/e1000.h3
-rw-r--r--drivers/net/e1000/e1000_main.c245
-rw-r--r--drivers/net/e1000e/82571.c6
-rw-r--r--drivers/net/e1000e/defines.h2
-rw-r--r--drivers/net/e1000e/e1000.h29
-rw-r--r--drivers/net/e1000e/es2lan.c1
-rw-r--r--drivers/net/e1000e/ethtool.c23
-rw-r--r--drivers/net/e1000e/ich8lan.c2
-rw-r--r--drivers/net/e1000e/netdev.c149
-rw-r--r--drivers/net/e1000e/param.c2
-rw-r--r--drivers/net/eepro.c8
-rw-r--r--drivers/net/ehea/ehea.h2
-rw-r--r--drivers/net/ehea/ehea_main.c62
-rw-r--r--drivers/net/ehea/ehea_qmr.h1
-rw-r--r--drivers/net/enic/enic.h27
-rw-r--r--drivers/net/enic/enic_main.c415
-rw-r--r--drivers/net/enic/enic_res.c32
-rw-r--r--drivers/net/enic/enic_res.h2
-rw-r--r--drivers/net/enic/vnic_dev.c133
-rw-r--r--drivers/net/enic/vnic_dev.h19
-rw-r--r--drivers/net/enic/vnic_devcmd.h12
-rw-r--r--drivers/net/enic/vnic_enet.h2
-rw-r--r--drivers/net/enic/vnic_intr.c5
-rw-r--r--drivers/net/enic/vnic_resource.h13
-rw-r--r--drivers/net/enic/vnic_rq.c8
-rw-r--r--drivers/net/enic/vnic_rq.h6
-rw-r--r--drivers/net/enic/vnic_rss.h5
-rw-r--r--drivers/net/enic/vnic_vic.c7
-rw-r--r--drivers/net/enic/vnic_wq.c8
-rw-r--r--drivers/net/enic/vnic_wq.h4
-rw-r--r--drivers/net/epic100.c2
-rw-r--r--drivers/net/eth16i.c16
-rw-r--r--drivers/net/ethoc.c6
-rw-r--r--drivers/net/fealnx.c4
-rw-r--r--drivers/net/fec.c44
-rw-r--r--drivers/net/fec_mpc52xx.c6
-rw-r--r--drivers/net/forcedeth.c19
-rw-r--r--drivers/net/fs_enet/fs_enet-main.c3
-rw-r--r--drivers/net/fsl_pq_mdio.c4
-rw-r--r--drivers/net/gianfar.c26
-rw-r--r--drivers/net/gianfar_ethtool.c6
-rw-r--r--drivers/net/greth.c6
-rw-r--r--drivers/net/hamachi.c2
-rw-r--r--drivers/net/hamradio/6pack.c2
-rw-r--r--drivers/net/hamradio/bpqether.c2
-rw-r--r--drivers/net/hamradio/hdlcdrv.c2
-rw-r--r--drivers/net/hamradio/mkiss.c2
-rw-r--r--drivers/net/hamradio/scc.c3
-rw-r--r--drivers/net/hp.c8
-rw-r--r--drivers/net/hp100.c6
-rw-r--r--drivers/net/hydra.c13
-rw-r--r--drivers/net/ibm_newemac/core.c6
-rw-r--r--drivers/net/ibm_newemac/core.h6
-rw-r--r--drivers/net/ibmlana.c2
-rw-r--r--drivers/net/ibmveth.c999
-rw-r--r--drivers/net/ibmveth.h59
-rw-r--r--drivers/net/igb/e1000_82575.c18
-rw-r--r--drivers/net/igb/e1000_defines.h31
-rw-r--r--drivers/net/igb/e1000_hw.h2
-rw-r--r--drivers/net/igb/e1000_phy.c206
-rw-r--r--drivers/net/igb/e1000_phy.h2
-rw-r--r--drivers/net/igb/igb.h11
-rw-r--r--drivers/net/igb/igb_ethtool.c52
-rw-r--r--drivers/net/igb/igb_main.c164
-rw-r--r--drivers/net/igbvf/ethtool.c2
-rw-r--r--drivers/net/igbvf/netdev.c11
-rw-r--r--drivers/net/ioc3-eth.c2
-rw-r--r--drivers/net/ipg.c6
-rw-r--r--drivers/net/irda/donauboe.c4
-rw-r--r--drivers/net/irda/irda-usb.c10
-rw-r--r--drivers/net/irda/mcs7780.c2
-rw-r--r--drivers/net/irda/nsc-ircc.c2
-rw-r--r--drivers/net/irda/sir_dev.c4
-rw-r--r--drivers/net/irda/smsc-ircc2.c2
-rw-r--r--drivers/net/irda/stir4200.c2
-rw-r--r--drivers/net/irda/via-ircc.c3
-rw-r--r--drivers/net/irda/via-ircc.h2
-rw-r--r--drivers/net/irda/vlsi_ir.h2
-rw-r--r--drivers/net/iseries_veth.c2
-rw-r--r--drivers/net/ixgb/ixgb_ee.c32
-rw-r--r--drivers/net/ixgb/ixgb_ethtool.c2
-rw-r--r--drivers/net/ixgb/ixgb_hw.c14
-rw-r--r--drivers/net/ixgb/ixgb_main.c12
-rw-r--r--drivers/net/ixgbe/ixgbe.h39
-rw-r--r--drivers/net/ixgbe/ixgbe_82599.c234
-rw-r--r--drivers/net/ixgbe/ixgbe_common.c50
-rw-r--r--drivers/net/ixgbe/ixgbe_common.h1
-rw-r--r--drivers/net/ixgbe/ixgbe_dcb.c219
-rw-r--r--drivers/net/ixgbe/ixgbe_dcb.h18
-rw-r--r--drivers/net/ixgbe/ixgbe_dcb_82598.c67
-rw-r--r--drivers/net/ixgbe/ixgbe_dcb_82598.h15
-rw-r--r--drivers/net/ixgbe/ixgbe_dcb_82599.c69
-rw-r--r--drivers/net/ixgbe/ixgbe_dcb_82599.h18
-rw-r--r--drivers/net/ixgbe/ixgbe_ethtool.c428
-rw-r--r--drivers/net/ixgbe/ixgbe_fcoe.c13
-rw-r--r--drivers/net/ixgbe/ixgbe_fcoe.h1
-rw-r--r--drivers/net/ixgbe/ixgbe_main.c1972
-rw-r--r--drivers/net/ixgbe/ixgbe_mbx.c21
-rw-r--r--drivers/net/ixgbe/ixgbe_mbx.h5
-rw-r--r--drivers/net/ixgbe/ixgbe_sriov.c19
-rw-r--r--drivers/net/ixgbe/ixgbe_sriov.h10
-rw-r--r--drivers/net/ixgbe/ixgbe_type.h2
-rw-r--r--drivers/net/ixgbevf/ethtool.c153
-rw-r--r--drivers/net/ixgbevf/ixgbevf.h1
-rw-r--r--drivers/net/ixgbevf/ixgbevf_main.c36
-rw-r--r--drivers/net/ixgbevf/mbx.c2
-rw-r--r--drivers/net/ixgbevf/mbx.h2
-rw-r--r--drivers/net/ixgbevf/vf.c2
-rw-r--r--drivers/net/ixgbevf/vf.h2
-rw-r--r--drivers/net/jme.c167
-rw-r--r--drivers/net/jme.h6
-rw-r--r--drivers/net/ll_temac_main.c4
-rw-r--r--drivers/net/loopback.c28
-rw-r--r--drivers/net/lp486e.c2
-rw-r--r--drivers/net/mac8390.c48
-rw-r--r--drivers/net/macb.c2
-rw-r--r--drivers/net/macvlan.c4
-rw-r--r--drivers/net/macvtap.c99
-rw-r--r--drivers/net/meth.c2
-rw-r--r--drivers/net/mlx4/Makefile2
-rw-r--r--drivers/net/mlx4/alloc.c17
-rw-r--r--drivers/net/mlx4/en_ethtool.c173
-rw-r--r--drivers/net/mlx4/en_main.c24
-rw-r--r--drivers/net/mlx4/en_netdev.c31
-rw-r--r--drivers/net/mlx4/en_port.c32
-rw-r--r--drivers/net/mlx4/en_port.h14
-rw-r--r--drivers/net/mlx4/en_rx.c104
-rw-r--r--drivers/net/mlx4/en_selftest.c179
-rw-r--r--drivers/net/mlx4/en_tx.c24
-rw-r--r--drivers/net/mlx4/eq.c44
-rw-r--r--drivers/net/mlx4/fw.c15
-rw-r--r--drivers/net/mlx4/fw.h6
-rw-r--r--drivers/net/mlx4/main.c6
-rw-r--r--drivers/net/mlx4/mlx4_en.h39
-rw-r--r--drivers/net/mlx4/profile.c2
-rw-r--r--drivers/net/mv643xx_eth.c3
-rw-r--r--drivers/net/myri10ge/myri10ge.c49
-rw-r--r--drivers/net/myri_sbus.c2
-rw-r--r--drivers/net/natsemi.c2
-rw-r--r--drivers/net/netconsole.c9
-rw-r--r--drivers/net/netxen/netxen_nic.h23
-rw-r--r--drivers/net/netxen/netxen_nic_hw.c43
-rw-r--r--drivers/net/netxen/netxen_nic_init.c14
-rw-r--r--drivers/net/netxen/netxen_nic_main.c49
-rw-r--r--drivers/net/niu.c133
-rw-r--r--drivers/net/ns83820.c55
-rw-r--r--drivers/net/pasemi_mac.c2
-rw-r--r--drivers/net/pasemi_mac_ethtool.c16
-rw-r--r--drivers/net/pch_gbe/Makefile4
-rw-r--r--drivers/net/pch_gbe/pch_gbe.h659
-rw-r--r--drivers/net/pch_gbe/pch_gbe_api.c245
-rw-r--r--drivers/net/pch_gbe/pch_gbe_api.h36
-rw-r--r--drivers/net/pch_gbe/pch_gbe_ethtool.c585
-rw-r--r--drivers/net/pch_gbe/pch_gbe_main.c2477
-rw-r--r--drivers/net/pch_gbe/pch_gbe_param.c499
-rw-r--r--drivers/net/pch_gbe/pch_gbe_phy.c274
-rw-r--r--drivers/net/pch_gbe/pch_gbe_phy.h37
-rw-r--r--drivers/net/pci-skeleton.c2
-rw-r--r--drivers/net/pcmcia/3c574_cs.c123
-rw-r--r--drivers/net/pcmcia/3c589_cs.c64
-rw-r--r--drivers/net/pcmcia/axnet_cs.c274
-rw-r--r--drivers/net/pcmcia/com20020_cs.c75
-rw-r--r--drivers/net/pcmcia/fmvj18x_cs.c127
-rw-r--r--drivers/net/pcmcia/ibmtr_cs.c115
-rw-r--r--drivers/net/pcmcia/nmclan_cs.c98
-rw-r--r--drivers/net/pcmcia/pcnet_cs.c252
-rw-r--r--drivers/net/pcmcia/smc91c92_cs.c219
-rw-r--r--drivers/net/pcmcia/xirc2ps_cs.c265
-rw-r--r--drivers/net/pcnet32.c4
-rw-r--r--drivers/net/phy/Kconfig1
-rw-r--r--drivers/net/phy/bcm63xx.c2
-rw-r--r--drivers/net/phy/broadcom.c2
-rw-r--r--drivers/net/phy/cicada.c2
-rw-r--r--drivers/net/phy/davicom.c2
-rw-r--r--drivers/net/phy/et1011c.c2
-rw-r--r--drivers/net/phy/icplus.c2
-rw-r--r--drivers/net/phy/lxt.c2
-rw-r--r--drivers/net/phy/marvell.c33
-rw-r--r--drivers/net/phy/micrel.c2
-rw-r--r--drivers/net/phy/national.c2
-rw-r--r--drivers/net/phy/qsemi.c2
-rw-r--r--drivers/net/phy/realtek.c2
-rw-r--r--drivers/net/phy/smsc.c2
-rw-r--r--drivers/net/phy/ste10Xp.c2
-rw-r--r--drivers/net/phy/vitesse.c2
-rw-r--r--drivers/net/plip.c9
-rw-r--r--drivers/net/ppp_async.c2
-rw-r--r--drivers/net/ppp_generic.c49
-rw-r--r--drivers/net/pppoe.c2
-rw-r--r--drivers/net/pppox.c4
-rw-r--r--drivers/net/pptp.c726
-rw-r--r--drivers/net/ps3_gelic_net.c4
-rw-r--r--drivers/net/ps3_gelic_wireless.c6
-rw-r--r--drivers/net/pxa168_eth.c4
-rw-r--r--drivers/net/qla3xxx.c4
-rw-r--r--drivers/net/qlcnic/qlcnic.h179
-rw-r--r--drivers/net/qlcnic/qlcnic_ctx.c411
-rw-r--r--drivers/net/qlcnic/qlcnic_ethtool.c226
-rw-r--r--drivers/net/qlcnic/qlcnic_hdr.h47
-rw-r--r--drivers/net/qlcnic/qlcnic_hw.c131
-rw-r--r--drivers/net/qlcnic/qlcnic_init.c332
-rw-r--r--drivers/net/qlcnic/qlcnic_main.c1310
-rw-r--r--drivers/net/qlge/qlge_main.c36
-rw-r--r--drivers/net/r6040.c92
-rw-r--r--drivers/net/r8169.c421
-rw-r--r--drivers/net/rrunner.c2
-rw-r--r--drivers/net/s2io.c39
-rw-r--r--drivers/net/s2io.h9
-rw-r--r--drivers/net/sb1250-mac.c2
-rw-r--r--drivers/net/sc92031.c11
-rw-r--r--drivers/net/sfc/Makefile7
-rw-r--r--drivers/net/sfc/efx.c353
-rw-r--r--drivers/net/sfc/efx.h46
-rw-r--r--drivers/net/sfc/ethtool.c181
-rw-r--r--drivers/net/sfc/falcon.c136
-rw-r--r--drivers/net/sfc/falcon_boards.c203
-rw-r--r--drivers/net/sfc/falcon_gmac.c230
-rw-r--r--drivers/net/sfc/falcon_xmac.c2
-rw-r--r--drivers/net/sfc/filter.c454
-rw-r--r--drivers/net/sfc/filter.h189
-rw-r--r--drivers/net/sfc/mac.h2
-rw-r--r--drivers/net/sfc/mcdi.c4
-rw-r--r--drivers/net/sfc/mcdi.h2
-rw-r--r--drivers/net/sfc/mcdi_phy.c3
-rw-r--r--drivers/net/sfc/mdio_10g.c30
-rw-r--r--drivers/net/sfc/net_driver.h117
-rw-r--r--drivers/net/sfc/nic.c199
-rw-r--r--drivers/net/sfc/phy.h18
-rw-r--r--drivers/net/sfc/regs.h14
-rw-r--r--drivers/net/sfc/rx.c73
-rw-r--r--drivers/net/sfc/selftest.c17
-rw-r--r--drivers/net/sfc/siena.c6
-rw-r--r--drivers/net/sfc/tenxpress.c424
-rw-r--r--drivers/net/sfc/tx.c78
-rw-r--r--drivers/net/sfc/txc43128_phy.c560
-rw-r--r--drivers/net/sfc/workarounds.h9
-rw-r--r--drivers/net/sh_eth.c4
-rw-r--r--drivers/net/sis900.c8
-rw-r--r--drivers/net/skfp/cfm.c10
-rw-r--r--drivers/net/skfp/drvfbi.c16
-rw-r--r--drivers/net/skfp/ess.c46
-rw-r--r--drivers/net/skfp/fplustm.c24
-rw-r--r--drivers/net/skfp/hwmtm.c30
-rw-r--r--drivers/net/skfp/hwt.c4
-rw-r--r--drivers/net/skfp/pcmplc.c22
-rw-r--r--drivers/net/skfp/pmf.c62
-rw-r--r--drivers/net/skfp/queue.c2
-rw-r--r--drivers/net/skfp/skfddi.c116
-rw-r--r--drivers/net/skfp/smt.c78
-rw-r--r--drivers/net/skfp/smtdef.c4
-rw-r--r--drivers/net/skfp/smtinit.c2
-rw-r--r--drivers/net/skfp/srf.c2
-rw-r--r--drivers/net/skge.c23
-rw-r--r--drivers/net/sky2.c5
-rw-r--r--drivers/net/slip.c93
-rw-r--r--drivers/net/slip.h9
-rw-r--r--drivers/net/smc91x.c1
-rw-r--r--drivers/net/smsc911x.c2
-rw-r--r--drivers/net/spider_net.c4
-rw-r--r--drivers/net/starfire.c10
-rw-r--r--drivers/net/stmmac/Kconfig5
-rw-r--r--drivers/net/stmmac/common.h61
-rw-r--r--drivers/net/stmmac/dwmac100.h2
-rw-r--r--drivers/net/stmmac/dwmac1000.h4
-rw-r--r--drivers/net/stmmac/dwmac1000_core.c36
-rw-r--r--drivers/net/stmmac/dwmac1000_dma.c20
-rw-r--r--drivers/net/stmmac/dwmac100_core.c31
-rw-r--r--drivers/net/stmmac/dwmac100_dma.c20
-rw-r--r--drivers/net/stmmac/dwmac_dma.h16
-rw-r--r--drivers/net/stmmac/dwmac_lib.c22
-rw-r--r--drivers/net/stmmac/enh_desc.c6
-rw-r--r--drivers/net/stmmac/norm_desc.c21
-rw-r--r--drivers/net/stmmac/stmmac.h13
-rw-r--r--drivers/net/stmmac/stmmac_ethtool.c63
-rw-r--r--drivers/net/stmmac/stmmac_main.c216
-rw-r--r--drivers/net/stmmac/stmmac_mdio.c26
-rw-r--r--drivers/net/sun3lance.c4
-rw-r--r--drivers/net/sunbmac.c2
-rw-r--r--drivers/net/sundance.c275
-rw-r--r--drivers/net/sungem.c211
-rw-r--r--drivers/net/sungem_phy.c5
-rw-r--r--drivers/net/sunhme.c10
-rw-r--r--drivers/net/sunlance.c2
-rw-r--r--drivers/net/sunqe.c2
-rw-r--r--drivers/net/sunvnet.c50
-rw-r--r--drivers/net/tc35815.c2
-rw-r--r--drivers/net/tehuti.c34
-rw-r--r--drivers/net/tehuti.h1
-rw-r--r--drivers/net/tg3.c740
-rw-r--r--drivers/net/tg3.h75
-rw-r--r--drivers/net/tlan.c10
-rw-r--r--drivers/net/tlan.h8
-rw-r--r--drivers/net/tokenring/proteon.c2
-rw-r--r--drivers/net/tokenring/smctr.c500
-rw-r--r--drivers/net/tokenring/tms380tr.c64
-rw-r--r--drivers/net/tokenring/tmspci.c10
-rw-r--r--drivers/net/tsi108_eth.c2
-rw-r--r--drivers/net/tulip/Kconfig4
-rw-r--r--drivers/net/tulip/de2104x.c3
-rw-r--r--drivers/net/tulip/de4x5.c57
-rw-r--r--drivers/net/tulip/dmfe.c2
-rw-r--r--drivers/net/tulip/interrupt.c77
-rw-r--r--drivers/net/tulip/tulip.h3
-rw-r--r--drivers/net/tulip/tulip_core.c10
-rw-r--r--drivers/net/tulip/uli526x.c4
-rw-r--r--drivers/net/tulip/winbond-840.c2
-rw-r--r--drivers/net/tulip/xircom_cb.c15
-rw-r--r--drivers/net/typhoon.c50
-rw-r--r--drivers/net/usb/Kconfig8
-rw-r--r--drivers/net/usb/Makefile1
-rw-r--r--drivers/net/usb/cx82310_eth.c346
-rw-r--r--drivers/net/usb/hso.c44
-rw-r--r--drivers/net/usb/kaweth.c9
-rw-r--r--drivers/net/usb/sierra_net.c4
-rw-r--r--drivers/net/usb/smsc95xx.c4
-rw-r--r--drivers/net/veth.c2
-rw-r--r--drivers/net/via-velocity.c86
-rw-r--r--drivers/net/via-velocity.h16
-rw-r--r--drivers/net/virtio_net.c14
-rw-r--r--drivers/net/vmxnet3/vmxnet3_drv.c23
-rw-r--r--drivers/net/vmxnet3/vmxnet3_int.h17
-rw-r--r--drivers/net/vxge/vxge-main.c38
-rw-r--r--drivers/net/vxge/vxge-main.h1
-rw-r--r--drivers/net/wan/c101.c2
-rw-r--r--drivers/net/wan/cosa.c2
-rw-r--r--drivers/net/wan/cycx_drv.c14
-rw-r--r--drivers/net/wan/cycx_main.c6
-rw-r--r--drivers/net/wan/dlci.c42
-rw-r--r--drivers/net/wan/hdlc_cisco.c4
-rw-r--r--drivers/net/wan/lapbether.c2
-rw-r--r--drivers/net/wan/lmc/lmc_main.c6
-rw-r--r--drivers/net/wan/n2.c6
-rw-r--r--drivers/net/wan/pc300_drv.c20
-rw-r--r--drivers/net/wan/pc300_tty.c2
-rw-r--r--drivers/net/wan/pci200syn.c2
-rw-r--r--drivers/net/wan/sdla.c108
-rw-r--r--drivers/net/wan/x25_asy.c2
-rw-r--r--drivers/net/wan/z85230.c4
-rw-r--r--drivers/net/wd.c8
-rw-r--r--drivers/net/wimax/i2400m/control.c18
-rw-r--r--drivers/net/wimax/i2400m/debugfs.c2
-rw-r--r--drivers/net/wimax/i2400m/driver.c2
-rw-r--r--drivers/net/wimax/i2400m/i2400m-sdio.h1
-rw-r--r--drivers/net/wimax/i2400m/i2400m.h9
-rw-r--r--drivers/net/wimax/i2400m/rx.c28
-rw-r--r--drivers/net/wimax/i2400m/sdio-rx.c2
-rw-r--r--drivers/net/wireless/Kconfig1
-rw-r--r--drivers/net/wireless/Makefile2
-rw-r--r--drivers/net/wireless/airo.c48
-rw-r--r--drivers/net/wireless/airo_cs.c154
-rw-r--r--drivers/net/wireless/at76c50x-usb.c10
-rw-r--r--drivers/net/wireless/ath/Kconfig1
-rw-r--r--drivers/net/wireless/ath/Makefile4
-rw-r--r--drivers/net/wireless/ath/ar9170/main.c31
-rw-r--r--drivers/net/wireless/ath/ar9170/usb.c2
-rw-r--r--drivers/net/wireless/ath/ath.h56
-rw-r--r--drivers/net/wireless/ath/ath5k/ani.c47
-rw-r--r--drivers/net/wireless/ath/ath5k/ani.h5
-rw-r--r--drivers/net/wireless/ath/ath5k/ath5k.h31
-rw-r--r--drivers/net/wireless/ath/ath5k/attach.c23
-rw-r--r--drivers/net/wireless/ath/ath5k/base.c2373
-rw-r--r--drivers/net/wireless/ath/ath5k/base.h33
-rw-r--r--drivers/net/wireless/ath/ath5k/debug.c128
-rw-r--r--drivers/net/wireless/ath/ath5k/debug.h15
-rw-r--r--drivers/net/wireless/ath/ath5k/dma.c8
-rw-r--r--drivers/net/wireless/ath/ath5k/eeprom.c4
-rw-r--r--drivers/net/wireless/ath/ath5k/pcu.c297
-rw-r--r--drivers/net/wireless/ath/ath5k/phy.c26
-rw-r--r--drivers/net/wireless/ath/ath5k/qcu.c99
-rw-r--r--drivers/net/wireless/ath/ath5k/reg.h73
-rw-r--r--drivers/net/wireless/ath/ath5k/reset.c34
-rw-r--r--drivers/net/wireless/ath/ath5k/rfbuffer.h4
-rw-r--r--drivers/net/wireless/ath/ath9k/Kconfig8
-rw-r--r--drivers/net/wireless/ath/ath9k/Makefile5
-rw-r--r--drivers/net/wireless/ath/ath9k/ani.c655
-rw-r--r--drivers/net/wireless/ath/ath9k/ani.h13
-rw-r--r--drivers/net/wireless/ath/ath9k/ar5008_phy.c50
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9002_calib.c89
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9002_hw.c55
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9002_phy.c36
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9002_phy.h2
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_2p0_initvals.h1784
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_calib.c37
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_eeprom.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_hw.c164
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_mac.c5
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_phy.c20
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h86
-rw-r--r--drivers/net/wireless/ath/ath9k/beacon.c28
-rw-r--r--drivers/net/wireless/ath/ath9k/btcoex.c7
-rw-r--r--drivers/net/wireless/ath/ath9k/calib.c152
-rw-r--r--drivers/net/wireless/ath/ath9k/calib.h11
-rw-r--r--drivers/net/wireless/ath/ath9k/common.c290
-rw-r--r--drivers/net/wireless/ath/ath9k/common.h16
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.c200
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.h33
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom.h7
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom_4k.c28
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom_9287.c8
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom_def.c22
-rw-r--r--drivers/net/wireless/ath/ath9k/gpio.c40
-rw-r--r--drivers/net/wireless/ath/ath9k/hif_usb.c35
-rw-r--r--drivers/net/wireless/ath/ath9k/htc.h42
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_beacon.c9
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_gpio.c134
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_init.c74
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_main.c60
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_txrx.c6
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_hst.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_hst.h2
-rw-r--r--drivers/net/wireless/ath/ath9k/hw-ops.h22
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c418
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h116
-rw-r--r--drivers/net/wireless/ath/ath9k/init.c76
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.c13
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.h21
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c310
-rw-r--r--drivers/net/wireless/ath/ath9k/phy.h3
-rw-r--r--drivers/net/wireless/ath/ath9k/rc.c200
-rw-r--r--drivers/net/wireless/ath/ath9k/rc.h37
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c602
-rw-r--r--drivers/net/wireless/ath/ath9k/reg.h48
-rw-r--r--drivers/net/wireless/ath/ath9k/virtual.c63
-rw-r--r--drivers/net/wireless/ath/ath9k/wmi.c74
-rw-r--r--drivers/net/wireless/ath/ath9k/wmi.h7
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c184
-rw-r--r--drivers/net/wireless/ath/carl9170/Kconfig41
-rw-r--r--drivers/net/wireless/ath/carl9170/Makefile4
-rw-r--r--drivers/net/wireless/ath/carl9170/carl9170.h628
-rw-r--r--drivers/net/wireless/ath/carl9170/cmd.c188
-rw-r--r--drivers/net/wireless/ath/carl9170/cmd.h168
-rw-r--r--drivers/net/wireless/ath/carl9170/debug.c902
-rw-r--r--drivers/net/wireless/ath/carl9170/debug.h134
-rw-r--r--drivers/net/wireless/ath/carl9170/eeprom.h216
-rw-r--r--drivers/net/wireless/ath/carl9170/fw.c402
-rw-r--r--drivers/net/wireless/ath/carl9170/fwcmd.h284
-rw-r--r--drivers/net/wireless/ath/carl9170/fwdesc.h241
-rw-r--r--drivers/net/wireless/ath/carl9170/hw.h739
-rw-r--r--drivers/net/wireless/ath/carl9170/led.c190
-rw-r--r--drivers/net/wireless/ath/carl9170/mac.c604
-rw-r--r--drivers/net/wireless/ath/carl9170/main.c1891
-rw-r--r--drivers/net/wireless/ath/carl9170/phy.c1810
-rw-r--r--drivers/net/wireless/ath/carl9170/phy.h564
-rw-r--r--drivers/net/wireless/ath/carl9170/rx.c938
-rw-r--r--drivers/net/wireless/ath/carl9170/tx.c1335
-rw-r--r--drivers/net/wireless/ath/carl9170/usb.c1136
-rw-r--r--drivers/net/wireless/ath/carl9170/version.h7
-rw-r--r--drivers/net/wireless/ath/carl9170/wlan.h420
-rw-r--r--drivers/net/wireless/ath/debug.c29
-rw-r--r--drivers/net/wireless/ath/debug.h12
-rw-r--r--drivers/net/wireless/ath/hw.c59
-rw-r--r--drivers/net/wireless/ath/key.c568
-rw-r--r--drivers/net/wireless/ath/reg.h34
-rw-r--r--drivers/net/wireless/atmel_cs.c135
-rw-r--r--drivers/net/wireless/b43/Makefile2
-rw-r--r--drivers/net/wireless/b43/b43.h3
-rw-r--r--drivers/net/wireless/b43/debugfs.c1
-rw-r--r--drivers/net/wireless/b43/main.c30
-rw-r--r--drivers/net/wireless/b43/pcmcia.c24
-rw-r--r--drivers/net/wireless/b43/phy_common.c6
-rw-r--r--drivers/net/wireless/b43/phy_common.h5
-rw-r--r--drivers/net/wireless/b43/phy_n.c211
-rw-r--r--drivers/net/wireless/b43/phy_n.h218
-rw-r--r--drivers/net/wireless/b43/radio_2055.c1332
-rw-r--r--drivers/net/wireless/b43/radio_2055.h254
-rw-r--r--drivers/net/wireless/b43/radio_2056.c43
-rw-r--r--drivers/net/wireless/b43/radio_2056.h42
-rw-r--r--drivers/net/wireless/b43/tables_nphy.c1311
-rw-r--r--drivers/net/wireless/b43/tables_nphy.h59
-rw-r--r--drivers/net/wireless/b43legacy/debugfs.c1
-rw-r--r--drivers/net/wireless/b43legacy/main.c5
-rw-r--r--drivers/net/wireless/hostap/hostap_cs.c102
-rw-r--r--drivers/net/wireless/hostap/hostap_ioctl.c2
-rw-r--r--drivers/net/wireless/ipw2x00/ipw2100.c10
-rw-r--r--drivers/net/wireless/ipw2x00/ipw2200.c20
-rw-r--r--drivers/net/wireless/iwlwifi/Kconfig10
-rw-r--r--drivers/net/wireless/iwlwifi/Makefile1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-1000.c119
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-hw.h3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-rs.c8
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.c191
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.h11
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c134
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000-hw.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000.c245
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-6000-hw.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-6000.c754
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-calib.c58
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-calib.h (renamed from drivers/net/wireless/iwlwifi/iwl-calib.h)4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c515
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h7
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c454
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c157
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-ict.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-lib.c1121
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rs.c407
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rs.h21
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rx.c35
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-sta.c716
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-tt.c699
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-tt.h129
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-tx.c208
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-ucode.c118
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c890
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.h96
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-commands.h585
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c1451
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h261
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-csr.h3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debugfs.c212
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h257
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-eeprom.c393
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-eeprom.h8
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-hcmd.c13
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-helpers.h5
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-led.c6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-power.c642
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-power.h93
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-prph.h9
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-rx.c10
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-scan.c441
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.c759
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.h69
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-tx.c81
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c434
-rw-r--r--drivers/net/wireless/iwmc3200wifi/cfg80211.c7
-rw-r--r--drivers/net/wireless/iwmc3200wifi/debugfs.c4
-rw-r--r--drivers/net/wireless/iwmc3200wifi/rx.c7
-rw-r--r--drivers/net/wireless/iwmc3200wifi/sdio.c1
-rw-r--r--drivers/net/wireless/libertas/cfg.c72
-rw-r--r--drivers/net/wireless/libertas/debugfs.c2
-rw-r--r--drivers/net/wireless/libertas/decl.h13
-rw-r--r--drivers/net/wireless/libertas/if_cs.c187
-rw-r--r--drivers/net/wireless/libertas/if_sdio.c161
-rw-r--r--drivers/net/wireless/libertas/if_sdio.h4
-rw-r--r--drivers/net/wireless/libertas/if_spi.c150
-rw-r--r--drivers/net/wireless/libertas/if_spi.h5
-rw-r--r--drivers/net/wireless/libertas/if_usb.c64
-rw-r--r--drivers/net/wireless/libertas/if_usb.h1
-rw-r--r--drivers/net/wireless/libertas/main.c105
-rw-r--r--drivers/net/wireless/libertas/mesh.c2
-rw-r--r--drivers/net/wireless/libertas_tf/if_usb.c57
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c31
-rw-r--r--drivers/net/wireless/orinoco/hw.c9
-rw-r--r--drivers/net/wireless/orinoco/orinoco_cs.c137
-rw-r--r--drivers/net/wireless/orinoco/spectrum_cs.c134
-rw-r--r--drivers/net/wireless/orinoco/wext.c11
-rw-r--r--drivers/net/wireless/p54/Kconfig18
-rw-r--r--drivers/net/wireless/p54/eeprom.c25
-rw-r--r--drivers/net/wireless/p54/fwio.c6
-rw-r--r--drivers/net/wireless/p54/main.c9
-rw-r--r--drivers/net/wireless/p54/p54spi.c9
-rw-r--r--drivers/net/wireless/p54/p54spi_eeprom.h2
-rw-r--r--drivers/net/wireless/p54/p54usb.c15
-rw-r--r--drivers/net/wireless/p54/txrx.c25
-rw-r--r--drivers/net/wireless/prism54/isl_ioctl.c2
-rw-r--r--drivers/net/wireless/ray_cs.c137
-rw-r--r--drivers/net/wireless/ray_cs.h2
-rw-r--r--drivers/net/wireless/rndis_wlan.c12
-rw-r--r--drivers/net/wireless/rt2x00/rt2400pci.c149
-rw-r--r--drivers/net/wireless/rt2x00/rt2500pci.c156
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.c78
-rw-r--r--drivers/net/wireless/rt2x00/rt2800.h109
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.c625
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.h28
-rw-r--r--drivers/net/wireless/rt2x00/rt2800pci.c400
-rw-r--r--drivers/net/wireless/rt2x00/rt2800usb.c159
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h70
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00config.c24
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00crypto.c17
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00debug.c18
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c194
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00firmware.c3
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00ht.c25
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00lib.h14
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00link.c24
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mac.c6
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00pci.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.c138
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.h56
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.c320
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.h12
-rw-r--r--drivers/net/wireless/rt2x00/rt61pci.c123
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c96
-rw-r--r--drivers/net/wireless/rtl818x/rtl8180_dev.c15
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187_dev.c9
-rw-r--r--drivers/net/wireless/wl1251/Kconfig33
-rw-r--r--drivers/net/wireless/wl1251/Makefile6
-rw-r--r--drivers/net/wireless/wl1251/acx.c (renamed from drivers/net/wireless/wl12xx/wl1251_acx.c)10
-rw-r--r--drivers/net/wireless/wl1251/acx.h (renamed from drivers/net/wireless/wl12xx/wl1251_acx.h)12
-rw-r--r--drivers/net/wireless/wl1251/boot.c (renamed from drivers/net/wireless/wl12xx/wl1251_boot.c)16
-rw-r--r--drivers/net/wireless/wl1251/boot.h (renamed from drivers/net/wireless/wl12xx/wl1251_boot.h)2
-rw-r--r--drivers/net/wireless/wl1251/cmd.c (renamed from drivers/net/wireless/wl12xx/wl1251_cmd.c)12
-rw-r--r--drivers/net/wireless/wl1251/cmd.h (renamed from drivers/net/wireless/wl12xx/wl1251_cmd.h)8
-rw-r--r--drivers/net/wireless/wl1251/debugfs.c (renamed from drivers/net/wireless/wl12xx/wl1251_debugfs.c)12
-rw-r--r--drivers/net/wireless/wl1251/debugfs.h (renamed from drivers/net/wireless/wl12xx/wl1251_debugfs.h)2
-rw-r--r--drivers/net/wireless/wl1251/event.c (renamed from drivers/net/wireless/wl12xx/wl1251_event.c)41
-rw-r--r--drivers/net/wireless/wl1251/event.h (renamed from drivers/net/wireless/wl12xx/wl1251_event.h)3
-rw-r--r--drivers/net/wireless/wl1251/init.c (renamed from drivers/net/wireless/wl12xx/wl1251_init.c)10
-rw-r--r--drivers/net/wireless/wl1251/init.h (renamed from drivers/net/wireless/wl12xx/wl1251_init.h)2
-rw-r--r--drivers/net/wireless/wl1251/io.c (renamed from drivers/net/wireless/wl12xx/wl1251_io.c)6
-rw-r--r--drivers/net/wireless/wl1251/io.h (renamed from drivers/net/wireless/wl12xx/wl1251_io.h)0
-rw-r--r--drivers/net/wireless/wl1251/main.c (renamed from drivers/net/wireless/wl12xx/wl1251_main.c)75
-rw-r--r--drivers/net/wireless/wl1251/ps.c (renamed from drivers/net/wireless/wl12xx/wl1251_ps.c)10
-rw-r--r--drivers/net/wireless/wl1251/ps.h (renamed from drivers/net/wireless/wl12xx/wl1251_ps.h)10
-rw-r--r--drivers/net/wireless/wl1251/reg.h (renamed from drivers/net/wireless/wl12xx/wl1251_reg.h)2
-rw-r--r--drivers/net/wireless/wl1251/rx.c (renamed from drivers/net/wireless/wl12xx/wl1251_rx.c)12
-rw-r--r--drivers/net/wireless/wl1251/rx.h (renamed from drivers/net/wireless/wl12xx/wl1251_rx.h)2
-rw-r--r--drivers/net/wireless/wl1251/sdio.c (renamed from drivers/net/wireless/wl12xx/wl1251_sdio.c)4
-rw-r--r--drivers/net/wireless/wl1251/spi.c (renamed from drivers/net/wireless/wl12xx/wl1251_spi.c)10
-rw-r--r--drivers/net/wireless/wl1251/spi.h (renamed from drivers/net/wireless/wl12xx/wl1251_spi.h)8
-rw-r--r--drivers/net/wireless/wl1251/tx.c (renamed from drivers/net/wireless/wl12xx/wl1251_tx.c)34
-rw-r--r--drivers/net/wireless/wl1251/tx.h (renamed from drivers/net/wireless/wl12xx/wl1251_tx.h)4
-rw-r--r--drivers/net/wireless/wl1251/wl1251.h (renamed from drivers/net/wireless/wl12xx/wl1251.h)7
-rw-r--r--drivers/net/wireless/wl1251/wl12xx_80211.h156
-rw-r--r--drivers/net/wireless/wl12xx/Kconfig39
-rw-r--r--drivers/net/wireless/wl12xx/Makefile12
-rw-r--r--drivers/net/wireless/wl12xx/wl1271.h32
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_acx.c36
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_acx.h31
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_boot.c67
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_boot.h1
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_cmd.c143
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_cmd.h73
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_conf.h78
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_debugfs.c6
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_event.c15
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_init.c39
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_io.h9
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_main.c416
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_ps.c20
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_ps.h2
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_rx.c67
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_scan.c83
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_scan.h6
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_sdio.c98
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_spi.c151
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_testmode.c14
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_tx.c109
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_tx.h17
-rw-r--r--drivers/net/wireless/wl12xx/wl12xx_platform_data.c28
-rw-r--r--drivers/net/wireless/wl3501_cs.c58
-rw-r--r--drivers/net/wireless/zd1211rw/zd_chip.c5
-rw-r--r--drivers/net/xen-netfront.c14
-rw-r--r--drivers/net/xilinx_emaclite.c15
-rw-r--r--drivers/net/yellowfin.c2
-rw-r--r--drivers/oprofile/oprof.c32
-rw-r--r--drivers/oprofile/oprof.h2
-rw-r--r--drivers/oprofile/oprofile_files.c15
-rw-r--r--drivers/oprofile/oprofile_perf.c328
-rw-r--r--drivers/oprofile/oprofilefs.c57
-rw-r--r--drivers/parport/parport_cs.c76
-rw-r--r--drivers/parport/share.c2
-rw-r--r--drivers/pci/dmar.c14
-rw-r--r--drivers/pci/hotplug/cpqphp_sysfs.c13
-rw-r--r--drivers/pci/hotplug/pciehp.h2
-rw-r--r--drivers/pci/hotplug/pciehp_core.c18
-rw-r--r--drivers/pci/hotplug/pciehp_ctrl.c9
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c20
-rw-r--r--drivers/pci/hotplug/shpchp.h2
-rw-r--r--drivers/pci/hotplug/shpchp_core.c20
-rw-r--r--drivers/pci/hotplug/shpchp_ctrl.c7
-rw-r--r--drivers/pci/hotplug/shpchp_hpc.c26
-rw-r--r--drivers/pci/htirq.c22
-rw-r--r--drivers/pci/intr_remapping.c212
-rw-r--r--drivers/pci/msi.c38
-rw-r--r--drivers/pci/pcie/aer/aer_inject.c1
-rw-r--r--drivers/pci/quirks.c20
-rw-r--r--drivers/pcmcia/au1000_generic.c3
-rw-r--r--drivers/pcmcia/au1000_generic.h1
-rw-r--r--drivers/pcmcia/au1000_pb1x00.c1
-rw-r--r--drivers/pcmcia/cistpl.c1
-rw-r--r--drivers/pcmcia/cs.c3
-rw-r--r--drivers/pcmcia/cs_internal.h9
-rw-r--r--drivers/pcmcia/ds.c37
-rw-r--r--drivers/pcmcia/i82092.c1
-rw-r--r--drivers/pcmcia/i82365.c1
-rw-r--r--drivers/pcmcia/m32r_cfc.c1
-rw-r--r--drivers/pcmcia/m32r_pcc.c1
-rw-r--r--drivers/pcmcia/m8xx_pcmcia.c1
-rw-r--r--drivers/pcmcia/o2micro.h4
-rw-r--r--drivers/pcmcia/pcmcia_cis.c117
-rw-r--r--drivers/pcmcia/pcmcia_resource.c411
-rw-r--r--drivers/pcmcia/pd6729.c1
-rw-r--r--drivers/pcmcia/rsrc_iodyn.c1
-rw-r--r--drivers/pcmcia/rsrc_mgr.c1
-rw-r--r--drivers/pcmcia/rsrc_nonstatic.c1
-rw-r--r--drivers/pcmcia/sa1100_generic.c1
-rw-r--r--drivers/pcmcia/soc_common.c4
-rw-r--r--drivers/pcmcia/soc_common.h1
-rw-r--r--drivers/pcmcia/socket_sysfs.c1
-rw-r--r--drivers/pcmcia/tcic.c1
-rw-r--r--drivers/pcmcia/vrc4173_cardu.c58
-rw-r--r--drivers/pcmcia/xxs1500_ss.c1
-rw-r--r--drivers/pcmcia/yenta_socket.c1
-rw-r--r--drivers/platform/x86/intel_ips.c122
-rw-r--r--drivers/platform/x86/sony-laptop.c1
-rw-r--r--drivers/pnp/isapnp/proc.c15
-rw-r--r--drivers/regulator/ad5398.c1
-rw-r--r--drivers/regulator/core.c6
-rw-r--r--drivers/regulator/isl6271a-regulator.c2
-rw-r--r--drivers/regulator/max8649.c2
-rw-r--r--drivers/rtc/rtc-ds3232.c2
-rw-r--r--drivers/rtc/rtc-m41t80.c14
-rw-r--r--drivers/s390/block/dasd.c7
-rw-r--r--drivers/s390/block/dasd_eer.c1
-rw-r--r--drivers/s390/block/dasd_ioctl.c17
-rw-r--r--drivers/s390/block/dcssblk.c5
-rw-r--r--drivers/s390/char/fs3270.c1
-rw-r--r--drivers/s390/char/monreader.c1
-rw-r--r--drivers/s390/char/monwriter.c1
-rw-r--r--drivers/s390/char/sclp.c2
-rw-r--r--drivers/s390/char/tape_block.c13
-rw-r--r--drivers/s390/char/tape_char.c1
-rw-r--r--drivers/s390/char/vmcp.c1
-rw-r--r--drivers/s390/char/vmlogrdr.c1
-rw-r--r--drivers/s390/char/vmwatchdog.c1
-rw-r--r--drivers/s390/char/zcore.c2
-rw-r--r--drivers/s390/cio/chsc_sch.c1
-rw-r--r--drivers/s390/cio/css.c1
-rw-r--r--drivers/s390/cio/qdio.h29
-rw-r--r--drivers/s390/cio/qdio_debug.c33
-rw-r--r--drivers/s390/cio/qdio_main.c138
-rw-r--r--drivers/s390/cio/qdio_setup.c1
-rw-r--r--drivers/s390/cio/qdio_thinint.c66
-rw-r--r--drivers/s390/crypto/zcrypt_api.c3
-rw-r--r--drivers/s390/net/Kconfig2
-rw-r--r--drivers/s390/net/ctcm_mpc.c2
-rw-r--r--drivers/s390/net/qeth_core.h17
-rw-r--r--drivers/s390/net/qeth_core_main.c26
-rw-r--r--drivers/s390/net/qeth_l2_main.c175
-rw-r--r--drivers/s390/net/qeth_l3_main.c218
-rw-r--r--drivers/s390/scsi/Makefile5
-rw-r--r--drivers/s390/scsi/zfcp_aux.c126
-rw-r--r--drivers/s390/scsi/zfcp_ccw.c17
-rw-r--r--drivers/s390/scsi/zfcp_cfdc.c189
-rw-r--r--drivers/s390/scsi/zfcp_dbf.c32
-rw-r--r--drivers/s390/scsi/zfcp_dbf.h14
-rw-r--r--drivers/s390/scsi/zfcp_def.h78
-rw-r--r--drivers/s390/scsi/zfcp_erp.c631
-rw-r--r--drivers/s390/scsi/zfcp_ext.h63
-rw-r--r--drivers/s390/scsi/zfcp_fc.c2
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c609
-rw-r--r--drivers/s390/scsi/zfcp_qdio.c24
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c159
-rw-r--r--drivers/s390/scsi/zfcp_sysfs.c221
-rw-r--r--drivers/s390/scsi/zfcp_unit.c244
-rw-r--r--drivers/sbus/char/display7seg.c1
-rw-r--r--drivers/sbus/char/envctrl.c1
-rw-r--r--drivers/sbus/char/jsflash.c24
-rw-r--r--drivers/scsi/3w-9xxx.c10
-rw-r--r--drivers/scsi/3w-sas.c10
-rw-r--r--drivers/scsi/3w-xxxx.c12
-rw-r--r--drivers/scsi/Kconfig5
-rw-r--r--drivers/scsi/Makefile3
-rw-r--r--drivers/scsi/aacraid/commctrl.c2
-rw-r--r--drivers/scsi/aacraid/commsup.c2
-rw-r--r--drivers/scsi/aacraid/linit.c16
-rw-r--r--drivers/scsi/aic7xxx_old.c22
-rw-r--r--drivers/scsi/arcmsr/arcmsr_hba.c4
-rw-r--r--drivers/scsi/be2iscsi/be_cmds.c2
-rw-r--r--drivers/scsi/be2iscsi/be_iscsi.c3
-rw-r--r--drivers/scsi/be2iscsi/be_main.c2
-rw-r--r--drivers/scsi/bfa/Makefile17
-rw-r--r--drivers/scsi/bfa/bfa.h438
-rw-r--r--drivers/scsi/bfa/bfa_callback_priv.h57
-rw-r--r--drivers/scsi/bfa/bfa_cb_ioim.h (renamed from drivers/scsi/bfa/bfa_cb_ioim_macros.h)30
-rw-r--r--drivers/scsi/bfa/bfa_cee.c492
-rw-r--r--drivers/scsi/bfa/bfa_core.c1131
-rw-r--r--drivers/scsi/bfa/bfa_cs.h364
-rw-r--r--drivers/scsi/bfa/bfa_csdebug.c58
-rw-r--r--drivers/scsi/bfa/bfa_defs.h466
-rw-r--r--drivers/scsi/bfa/bfa_defs_fcs.h457
-rw-r--r--drivers/scsi/bfa/bfa_defs_svc.h1081
-rw-r--r--drivers/scsi/bfa/bfa_drv.c (renamed from drivers/scsi/bfa/bfa_module.c)41
-rw-r--r--drivers/scsi/bfa/bfa_fc.h (renamed from drivers/scsi/bfa/include/protocol/fc.h)1011
-rw-r--r--drivers/scsi/bfa/bfa_fcbuild.c (renamed from drivers/scsi/bfa/fcbuild.c)293
-rw-r--r--drivers/scsi/bfa/bfa_fcbuild.h316
-rw-r--r--drivers/scsi/bfa/bfa_fcpim.c3460
-rw-r--r--drivers/scsi/bfa/bfa_fcpim.h401
-rw-r--r--drivers/scsi/bfa/bfa_fcpim_priv.h192
-rw-r--r--drivers/scsi/bfa/bfa_fcport.c1962
-rw-r--r--drivers/scsi/bfa/bfa_fcs.c1609
-rw-r--r--drivers/scsi/bfa/bfa_fcs.h779
-rw-r--r--drivers/scsi/bfa/bfa_fcs_fcpim.c (renamed from drivers/scsi/bfa/fcpim.c)237
-rw-r--r--drivers/scsi/bfa/bfa_fcs_lport.c5411
-rw-r--r--drivers/scsi/bfa/bfa_fcs_port.c61
-rw-r--r--drivers/scsi/bfa/bfa_fcs_rport.c (renamed from drivers/scsi/bfa/rport.c)1662
-rw-r--r--drivers/scsi/bfa/bfa_fcs_uf.c99
-rw-r--r--drivers/scsi/bfa/bfa_fcxp.c774
-rw-r--r--drivers/scsi/bfa/bfa_fcxp_priv.h138
-rw-r--r--drivers/scsi/bfa/bfa_fwimg_priv.h44
-rw-r--r--drivers/scsi/bfa/bfa_hw_cb.c8
-rw-r--r--drivers/scsi/bfa/bfa_hw_ct.c11
-rw-r--r--drivers/scsi/bfa/bfa_intr.c270
-rw-r--r--drivers/scsi/bfa/bfa_intr_priv.h117
-rw-r--r--drivers/scsi/bfa/bfa_ioc.c1888
-rw-r--r--drivers/scsi/bfa/bfa_ioc.h248
-rw-r--r--drivers/scsi/bfa/bfa_ioc_cb.c124
-rw-r--r--drivers/scsi/bfa/bfa_ioc_ct.c137
-rw-r--r--drivers/scsi/bfa/bfa_iocfc.c927
-rw-r--r--drivers/scsi/bfa/bfa_iocfc.h184
-rw-r--r--drivers/scsi/bfa/bfa_iocfc_q.c44
-rw-r--r--drivers/scsi/bfa/bfa_ioim.c1364
-rw-r--r--drivers/scsi/bfa/bfa_itnim.c1088
-rw-r--r--drivers/scsi/bfa/bfa_log.c346
-rw-r--r--drivers/scsi/bfa/bfa_log_module.c537
-rw-r--r--drivers/scsi/bfa/bfa_lps.c892
-rw-r--r--drivers/scsi/bfa/bfa_lps_priv.h38
-rw-r--r--drivers/scsi/bfa/bfa_modules.h (renamed from drivers/scsi/bfa/bfa_priv.h)64
-rw-r--r--drivers/scsi/bfa/bfa_modules_priv.h43
-rw-r--r--drivers/scsi/bfa/bfa_os_inc.h144
-rw-r--r--drivers/scsi/bfa/bfa_plog.h (renamed from drivers/scsi/bfa/include/cs/bfa_plog.h)120
-rw-r--r--drivers/scsi/bfa/bfa_port.c134
-rw-r--r--drivers/scsi/bfa/bfa_port.h66
-rw-r--r--drivers/scsi/bfa/bfa_port_priv.h94
-rw-r--r--drivers/scsi/bfa/bfa_rport.c906
-rw-r--r--drivers/scsi/bfa/bfa_rport_priv.h45
-rw-r--r--drivers/scsi/bfa/bfa_sgpg.c226
-rw-r--r--drivers/scsi/bfa/bfa_sgpg_priv.h79
-rw-r--r--drivers/scsi/bfa/bfa_sm.c38
-rw-r--r--drivers/scsi/bfa/bfa_svc.c5423
-rw-r--r--drivers/scsi/bfa/bfa_svc.h657
-rw-r--r--drivers/scsi/bfa/bfa_timer.c90
-rw-r--r--drivers/scsi/bfa/bfa_trcmod_priv.h64
-rw-r--r--drivers/scsi/bfa/bfa_tskim.c690
-rw-r--r--drivers/scsi/bfa/bfa_uf.c343
-rw-r--r--drivers/scsi/bfa/bfa_uf_priv.h47
-rw-r--r--drivers/scsi/bfa/bfad.c1355
-rw-r--r--drivers/scsi/bfa/bfad_attr.c241
-rw-r--r--drivers/scsi/bfa/bfad_attr.h56
-rw-r--r--drivers/scsi/bfa/bfad_debugfs.c10
-rw-r--r--drivers/scsi/bfa/bfad_drv.h254
-rw-r--r--drivers/scsi/bfa/bfad_fwimg.c131
-rw-r--r--drivers/scsi/bfa/bfad_im.c257
-rw-r--r--drivers/scsi/bfa/bfad_im.h56
-rw-r--r--drivers/scsi/bfa/bfad_im_compat.h45
-rw-r--r--drivers/scsi/bfa/bfad_intr.c222
-rw-r--r--drivers/scsi/bfa/bfad_ipfc.h42
-rw-r--r--drivers/scsi/bfa/bfad_os.c50
-rw-r--r--drivers/scsi/bfa/bfad_tm.h59
-rw-r--r--drivers/scsi/bfa/bfad_trcmod.h52
-rw-r--r--drivers/scsi/bfa/bfi.h579
-rw-r--r--drivers/scsi/bfa/bfi_cbreg.h (renamed from drivers/scsi/bfa/include/bfi/bfi_cbreg.h)25
-rw-r--r--drivers/scsi/bfa/bfi_ctreg.h627
-rw-r--r--drivers/scsi/bfa/bfi_ms.h765
-rw-r--r--drivers/scsi/bfa/fab.c62
-rw-r--r--drivers/scsi/bfa/fabric.c1323
-rw-r--r--drivers/scsi/bfa/fcbuild.h279
-rw-r--r--drivers/scsi/bfa/fcptm.c68
-rw-r--r--drivers/scsi/bfa/fcs.h30
-rw-r--r--drivers/scsi/bfa/fcs_auth.h37
-rw-r--r--drivers/scsi/bfa/fcs_fabric.h68
-rw-r--r--drivers/scsi/bfa/fcs_fcpim.h39
-rw-r--r--drivers/scsi/bfa/fcs_fcptm.h45
-rw-r--r--drivers/scsi/bfa/fcs_fcxp.h29
-rw-r--r--drivers/scsi/bfa/fcs_lport.h118
-rw-r--r--drivers/scsi/bfa/fcs_ms.h35
-rw-r--r--drivers/scsi/bfa/fcs_port.h31
-rw-r--r--drivers/scsi/bfa/fcs_rport.h61
-rw-r--r--drivers/scsi/bfa/fcs_trcmod.h56
-rw-r--r--drivers/scsi/bfa/fcs_uf.h31
-rw-r--r--drivers/scsi/bfa/fcs_vport.h32
-rw-r--r--drivers/scsi/bfa/fdmi.c1230
-rw-r--r--drivers/scsi/bfa/include/aen/bfa_aen.h96
-rw-r--r--drivers/scsi/bfa/include/aen/bfa_aen_adapter.h31
-rw-r--r--drivers/scsi/bfa/include/aen/bfa_aen_audit.h31
-rw-r--r--drivers/scsi/bfa/include/aen/bfa_aen_ethport.h35
-rw-r--r--drivers/scsi/bfa/include/aen/bfa_aen_ioc.h45
-rw-r--r--drivers/scsi/bfa/include/aen/bfa_aen_itnim.h33
-rw-r--r--drivers/scsi/bfa/include/aen/bfa_aen_lport.h51
-rw-r--r--drivers/scsi/bfa/include/aen/bfa_aen_port.h57
-rw-r--r--drivers/scsi/bfa/include/aen/bfa_aen_rport.h37
-rw-r--r--drivers/scsi/bfa/include/bfa.h203
-rw-r--r--drivers/scsi/bfa/include/bfa_fcpim.h177
-rw-r--r--drivers/scsi/bfa/include/bfa_fcptm.h47
-rw-r--r--drivers/scsi/bfa/include/bfa_svc.h338
-rw-r--r--drivers/scsi/bfa/include/bfa_timer.h53
-rw-r--r--drivers/scsi/bfa/include/bfi/bfi.h174
-rw-r--r--drivers/scsi/bfa/include/bfi/bfi_boot.h34
-rw-r--r--drivers/scsi/bfa/include/bfi/bfi_cee.h119
-rw-r--r--drivers/scsi/bfa/include/bfi/bfi_ctreg.h640
-rw-r--r--drivers/scsi/bfa/include/bfi/bfi_fabric.h92
-rw-r--r--drivers/scsi/bfa/include/bfi/bfi_fcpim.h301
-rw-r--r--drivers/scsi/bfa/include/bfi/bfi_fcxp.h71
-rw-r--r--drivers/scsi/bfa/include/bfi/bfi_ioc.h208
-rw-r--r--drivers/scsi/bfa/include/bfi/bfi_iocfc.h179
-rw-r--r--drivers/scsi/bfa/include/bfi/bfi_lport.h89
-rw-r--r--drivers/scsi/bfa/include/bfi/bfi_lps.h104
-rw-r--r--drivers/scsi/bfa/include/bfi/bfi_pbc.h62
-rw-r--r--drivers/scsi/bfa/include/bfi/bfi_port.h115
-rw-r--r--drivers/scsi/bfa/include/bfi/bfi_pport.h118
-rw-r--r--drivers/scsi/bfa/include/bfi/bfi_rport.h104
-rw-r--r--drivers/scsi/bfa/include/bfi/bfi_uf.h52
-rw-r--r--drivers/scsi/bfa/include/cna/bfa_cna_trcmod.h40
-rw-r--r--drivers/scsi/bfa/include/cna/cee/bfa_cee.h77
-rw-r--r--drivers/scsi/bfa/include/cna/port/bfa_port.h70
-rw-r--r--drivers/scsi/bfa/include/cna/pstats/ethport_defs.h36
-rw-r--r--drivers/scsi/bfa/include/cna/pstats/phyport_defs.h218
-rw-r--r--drivers/scsi/bfa/include/cs/bfa_checksum.h60
-rw-r--r--drivers/scsi/bfa/include/cs/bfa_debug.h45
-rw-r--r--drivers/scsi/bfa/include/cs/bfa_log.h184
-rw-r--r--drivers/scsi/bfa/include/cs/bfa_perf.h34
-rw-r--r--drivers/scsi/bfa/include/cs/bfa_trc.h176
-rw-r--r--drivers/scsi/bfa/include/defs/bfa_defs_adapter.h83
-rw-r--r--drivers/scsi/bfa/include/defs/bfa_defs_aen.h83
-rw-r--r--drivers/scsi/bfa/include/defs/bfa_defs_audit.h38
-rw-r--r--drivers/scsi/bfa/include/defs/bfa_defs_auth.h134
-rw-r--r--drivers/scsi/bfa/include/defs/bfa_defs_boot.h81
-rw-r--r--drivers/scsi/bfa/include/defs/bfa_defs_cee.h157
-rw-r--r--drivers/scsi/bfa/include/defs/bfa_defs_driver.h41
-rw-r--r--drivers/scsi/bfa/include/defs/bfa_defs_ethport.h99
-rw-r--r--drivers/scsi/bfa/include/defs/bfa_defs_fcpim.h45
-rw-r--r--drivers/scsi/bfa/include/defs/bfa_defs_fcport.h88
-rw-r--r--drivers/scsi/bfa/include/defs/bfa_defs_ioc.h158
-rw-r--r--drivers/scsi/bfa/include/defs/bfa_defs_iocfc.h322
-rw-r--r--drivers/scsi/bfa/include/defs/bfa_defs_ipfc.h70
-rw-r--r--drivers/scsi/bfa/include/defs/bfa_defs_itnim.h136
-rw-r--r--drivers/scsi/bfa/include/defs/bfa_defs_led.h35
-rw-r--r--drivers/scsi/bfa/include/defs/bfa_defs_lport.h68
-rw-r--r--drivers/scsi/bfa/include/defs/bfa_defs_mfg.h144
-rw-r--r--drivers/scsi/bfa/include/defs/bfa_defs_pci.h48
-rw-r--r--drivers/scsi/bfa/include/defs/bfa_defs_pm.h33
-rw-r--r--drivers/scsi/bfa/include/defs/bfa_defs_pom.h56
-rw-r--r--drivers/scsi/bfa/include/defs/bfa_defs_port.h248
-rw-r--r--drivers/scsi/bfa/include/defs/bfa_defs_pport.h393
-rw-r--r--drivers/scsi/bfa/include/defs/bfa_defs_qos.h99
-rw-r--r--drivers/scsi/bfa/include/defs/bfa_defs_rport.h199
-rw-r--r--drivers/scsi/bfa/include/defs/bfa_defs_status.h282
-rw-r--r--drivers/scsi/bfa/include/defs/bfa_defs_tin.h118
-rw-r--r--drivers/scsi/bfa/include/defs/bfa_defs_tsensor.h43
-rw-r--r--drivers/scsi/bfa/include/defs/bfa_defs_types.h30
-rw-r--r--drivers/scsi/bfa/include/defs/bfa_defs_version.h22
-rw-r--r--drivers/scsi/bfa/include/defs/bfa_defs_vf.h74
-rw-r--r--drivers/scsi/bfa/include/defs/bfa_defs_vport.h91
-rw-r--r--drivers/scsi/bfa/include/fcb/bfa_fcb.h33
-rw-r--r--drivers/scsi/bfa/include/fcb/bfa_fcb_fcpim.h75
-rw-r--r--drivers/scsi/bfa/include/fcb/bfa_fcb_port.h113
-rw-r--r--drivers/scsi/bfa/include/fcb/bfa_fcb_rport.h80
-rw-r--r--drivers/scsi/bfa/include/fcb/bfa_fcb_vf.h47
-rw-r--r--drivers/scsi/bfa/include/fcb/bfa_fcb_vport.h48
-rw-r--r--drivers/scsi/bfa/include/fcs/bfa_fcs.h76
-rw-r--r--drivers/scsi/bfa/include/fcs/bfa_fcs_auth.h82
-rw-r--r--drivers/scsi/bfa/include/fcs/bfa_fcs_fabric.h112
-rw-r--r--drivers/scsi/bfa/include/fcs/bfa_fcs_fcpim.h132
-rw-r--r--drivers/scsi/bfa/include/fcs/bfa_fcs_fdmi.h63
-rw-r--r--drivers/scsi/bfa/include/fcs/bfa_fcs_lport.h219
-rw-r--r--drivers/scsi/bfa/include/fcs/bfa_fcs_rport.h105
-rw-r--r--drivers/scsi/bfa/include/fcs/bfa_fcs_vport.h67
-rw-r--r--drivers/scsi/bfa/include/log/bfa_log_fcs.h28
-rw-r--r--drivers/scsi/bfa/include/log/bfa_log_hal.h36
-rw-r--r--drivers/scsi/bfa/include/log/bfa_log_linux.h62
-rw-r--r--drivers/scsi/bfa/include/log/bfa_log_wdrv.h36
-rw-r--r--drivers/scsi/bfa/include/protocol/ct.h492
-rw-r--r--drivers/scsi/bfa/include/protocol/fc_sp.h224
-rw-r--r--drivers/scsi/bfa/include/protocol/fcp.h184
-rw-r--r--drivers/scsi/bfa/include/protocol/fdmi.h163
-rw-r--r--drivers/scsi/bfa/include/protocol/scsi.h1648
-rw-r--r--drivers/scsi/bfa/include/protocol/types.h42
-rw-r--r--drivers/scsi/bfa/loop.c213
-rw-r--r--drivers/scsi/bfa/lport_api.c303
-rw-r--r--drivers/scsi/bfa/lport_priv.h82
-rw-r--r--drivers/scsi/bfa/ms.c759
-rw-r--r--drivers/scsi/bfa/n2n.c105
-rw-r--r--drivers/scsi/bfa/ns.c1242
-rw-r--r--drivers/scsi/bfa/plog.c184
-rw-r--r--drivers/scsi/bfa/rport_api.c185
-rw-r--r--drivers/scsi/bfa/rport_ftrs.c379
-rw-r--r--drivers/scsi/bfa/scn.c482
-rw-r--r--drivers/scsi/bfa/vfapi.c292
-rw-r--r--drivers/scsi/bfa/vport.c903
-rw-r--r--drivers/scsi/bnx2i/57xx_iscsi_constants.h2
-rw-r--r--drivers/scsi/bnx2i/bnx2i.h4
-rw-r--r--drivers/scsi/bnx2i/bnx2i_hwi.c66
-rw-r--r--drivers/scsi/bnx2i/bnx2i_init.c62
-rw-r--r--drivers/scsi/bnx2i/bnx2i_iscsi.c15
-rw-r--r--drivers/scsi/ch.c9
-rw-r--r--drivers/scsi/cxgb3i/cxgb3i.h161
-rw-r--r--drivers/scsi/cxgb3i/cxgb3i_ddp.c773
-rw-r--r--drivers/scsi/cxgb3i/cxgb3i_ddp.h312
-rw-r--r--drivers/scsi/cxgb3i/cxgb3i_init.c132
-rw-r--r--drivers/scsi/cxgb3i/cxgb3i_iscsi.c1018
-rw-r--r--drivers/scsi/cxgb3i/cxgb3i_offload.c1944
-rw-r--r--drivers/scsi/cxgb3i/cxgb3i_offload.h243
-rw-r--r--drivers/scsi/cxgb3i/cxgb3i_pdu.c495
-rw-r--r--drivers/scsi/cxgb3i/cxgb3i_pdu.h59
-rw-r--r--drivers/scsi/cxgbi/Kconfig2
-rw-r--r--drivers/scsi/cxgbi/Makefile2
-rw-r--r--drivers/scsi/cxgbi/cxgb3i/Kbuild (renamed from drivers/scsi/cxgb3i/Kbuild)1
-rw-r--r--drivers/scsi/cxgbi/cxgb3i/Kconfig (renamed from drivers/scsi/cxgb3i/Kconfig)4
-rw-r--r--drivers/scsi/cxgbi/cxgb3i/cxgb3i.c1465
-rw-r--r--drivers/scsi/cxgbi/cxgb3i/cxgb3i.h51
-rw-r--r--drivers/scsi/cxgbi/cxgb4i/Kbuild3
-rw-r--r--drivers/scsi/cxgbi/cxgb4i/Kconfig7
-rw-r--r--drivers/scsi/cxgbi/cxgb4i/cxgb4i.c1604
-rw-r--r--drivers/scsi/cxgbi/cxgb4i/cxgb4i.h43
-rw-r--r--drivers/scsi/cxgbi/libcxgbi.c2612
-rw-r--r--drivers/scsi/cxgbi/libcxgbi.h745
-rw-r--r--drivers/scsi/device_handler/scsi_dh_alua.c65
-rw-r--r--drivers/scsi/dpt_i2o.c19
-rw-r--r--drivers/scsi/fnic/fnic_main.c15
-rw-r--r--drivers/scsi/gdth.c12
-rw-r--r--drivers/scsi/hosts.c3
-rw-r--r--drivers/scsi/ibmvscsi/ibmvfc.c91
-rw-r--r--drivers/scsi/ibmvscsi/ibmvfc.h6
-rw-r--r--drivers/scsi/ipr.c116
-rw-r--r--drivers/scsi/ipr.h17
-rw-r--r--drivers/scsi/libsas/sas_ata.c5
-rw-r--r--drivers/scsi/libsas/sas_expander.c12
-rw-r--r--drivers/scsi/libsas/sas_scsi_host.c20
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c16
-rw-r--r--drivers/scsi/lpfc/lpfc_bsg.c147
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c2
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c34
-rw-r--r--drivers/scsi/lpfc/lpfc_hw.h6
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c213
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c40
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c237
-rw-r--r--drivers/scsi/lpfc/lpfc_sli4.h2
-rw-r--r--drivers/scsi/lpfc/lpfc_version.h2
-rw-r--r--drivers/scsi/lpfc/lpfc_vport.c8
-rw-r--r--drivers/scsi/megaraid.c9
-rw-r--r--drivers/scsi/megaraid/megaraid_mm.c9
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.c759
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.h88
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.c2
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_ctl.c12
-rw-r--r--drivers/scsi/osd/osd_uld.c1
-rw-r--r--drivers/scsi/osst.c15
-rw-r--r--drivers/scsi/pcmcia/Kconfig1
-rw-r--r--drivers/scsi/pcmcia/aha152x_stub.c48
-rw-r--r--drivers/scsi/pcmcia/fdomain_stub.c24
-rw-r--r--drivers/scsi/pcmcia/nsp_cs.c182
-rw-r--r--drivers/scsi/pcmcia/qlogic_stub.c24
-rw-r--r--drivers/scsi/pcmcia/sym53c500_cs.c22
-rw-r--r--drivers/scsi/pm8001/pm8001_hwi.c6
-rw-r--r--drivers/scsi/pmcraid.c1
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c30
-rw-r--r--drivers/scsi/qla2xxx/qla_bsg.c7
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h8
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h15
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c54
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c8
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c66
-rw-r--r--drivers/scsi/qla2xxx/qla_nx.c431
-rw-r--r--drivers/scsi/qla2xxx/qla_nx.h5
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c157
-rw-r--r--drivers/scsi/qla4xxx/ql4_nx.c1
-rw-r--r--drivers/scsi/scsi.c4
-rw-r--r--drivers/scsi/scsi_debug.c125
-rw-r--r--drivers/scsi/scsi_lib.c26
-rw-r--r--drivers/scsi/scsi_scan.c2
-rw-r--r--drivers/scsi/scsi_sysfs.c2
-rw-r--r--drivers/scsi/scsi_tgt_if.c3
-rw-r--r--drivers/scsi/scsi_transport_fc.c163
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c2
-rw-r--r--drivers/scsi/sd.c108
-rw-r--r--drivers/scsi/sd.h6
-rw-r--r--drivers/scsi/sd_dif.c11
-rw-r--r--drivers/scsi/sg.c15
-rw-r--r--drivers/scsi/sr.c22
-rw-r--r--drivers/scsi/st.c27
-rw-r--r--drivers/serial/68360serial.c51
-rw-r--r--drivers/serial/8250.c69
-rw-r--r--drivers/serial/Kconfig14
-rw-r--r--drivers/serial/altera_uart.c156
-rw-r--r--drivers/serial/bfin_sport_uart.c7
-rw-r--r--drivers/serial/imx.c5
-rw-r--r--drivers/serial/ioc3_serial.c5
-rw-r--r--drivers/serial/jsm/jsm_driver.c4
-rw-r--r--drivers/serial/kgdboc.c2
-rw-r--r--drivers/serial/max3107.c34
-rw-r--r--drivers/serial/mfd.c50
-rw-r--r--drivers/serial/mrst_max3110.c359
-rw-r--r--drivers/serial/mrst_max3110.h1
-rw-r--r--drivers/serial/samsung.c2
-rw-r--r--drivers/serial/serial_core.c49
-rw-r--r--drivers/serial/serial_cs.c205
-rw-r--r--drivers/serial/uartlite.c26
-rw-r--r--drivers/spi/Kconfig46
-rw-r--r--drivers/spi/Makefile9
-rw-r--r--drivers/spi/amba-pl022.c751
-rw-r--r--drivers/spi/atmel_spi.c14
-rw-r--r--drivers/spi/dw_spi.c1
-rw-r--r--drivers/spi/omap2_mcspi.c81
-rw-r--r--drivers/spi/orion_spi.c4
-rw-r--r--drivers/spi/spi.c5
-rw-r--r--drivers/spi/spi_bfin5xx.c844
-rw-r--r--drivers/spi/spi_fsl_espi.c748
-rw-r--r--drivers/spi/spi_fsl_lib.c237
-rw-r--r--drivers/spi/spi_fsl_lib.h124
-rw-r--r--drivers/spi/spi_fsl_spi.c (renamed from drivers/spi/spi_mpc8xxx.c)562
-rw-r--r--drivers/spi/spi_gpio.c2
-rw-r--r--drivers/spi/spi_imx.c402
-rw-r--r--drivers/spi/spi_s3c64xx.c158
-rw-r--r--drivers/spi/spi_topcliff_pch.c1303
-rw-r--r--drivers/spi/spidev.c1
-rw-r--r--drivers/ssb/main.c1
-rw-r--r--drivers/ssb/pcmcia.c1
-rw-r--r--drivers/ssb/scan.c1
-rw-r--r--drivers/staging/comedi/comedi_fops.c1
-rw-r--r--drivers/staging/comedi/drivers/cb_das16_cs.c58
-rw-r--r--drivers/staging/comedi/drivers/das08_cs.c129
-rw-r--r--drivers/staging/comedi/drivers/ni_daq_700.c131
-rw-r--r--drivers/staging/comedi/drivers/ni_daq_dio24.c130
-rw-r--r--drivers/staging/comedi/drivers/ni_labpc_cs.c144
-rw-r--r--drivers/staging/comedi/drivers/ni_mio_cs.c23
-rw-r--r--drivers/staging/comedi/drivers/quatech_daqp_cs.c124
-rw-r--r--drivers/staging/crystalhd/crystalhd_lnx.c1
-rw-r--r--drivers/staging/cx25821/Kconfig1
-rw-r--r--drivers/staging/dream/camera/msm_camera.c3
-rw-r--r--drivers/staging/dream/pmem.c2
-rw-r--r--drivers/staging/dream/qdsp5/adsp_driver.c1
-rw-r--r--drivers/staging/dream/qdsp5/audio_aac.c1
-rw-r--r--drivers/staging/dream/qdsp5/audio_amrnb.c1
-rw-r--r--drivers/staging/dream/qdsp5/audio_evrc.c1
-rw-r--r--drivers/staging/dream/qdsp5/audio_in.c2
-rw-r--r--drivers/staging/dream/qdsp5/audio_mp3.c1
-rw-r--r--drivers/staging/dream/qdsp5/audio_out.c2
-rw-r--r--drivers/staging/dream/qdsp5/audio_qcelp.c1
-rw-r--r--drivers/staging/dream/qdsp5/evlog.h1
-rw-r--r--drivers/staging/dream/qdsp5/snd.c1
-rw-r--r--drivers/staging/easycap/Kconfig1
-rw-r--r--drivers/staging/frontier/alphatrack.c1
-rw-r--r--drivers/staging/frontier/tranzport.c1
-rw-r--r--drivers/staging/go7007/Kconfig1
-rw-r--r--drivers/staging/hv/blkvsc_drv.c11
-rw-r--r--drivers/staging/iio/industrialio-core.c1
-rw-r--r--drivers/staging/iio/industrialio-ring.c1
-rw-r--r--drivers/staging/lirc/lirc_imon.c3
-rw-r--r--drivers/staging/lirc/lirc_it87.c1
-rw-r--r--drivers/staging/lirc/lirc_sasem.c1
-rw-r--r--drivers/staging/lirc/lirc_serial.c1
-rw-r--r--drivers/staging/lirc/lirc_sir.c1
-rw-r--r--drivers/staging/memrar/memrar_handler.c1
-rw-r--r--drivers/staging/panel/panel.c1
-rw-r--r--drivers/staging/spectra/ffsport.c7
-rw-r--r--drivers/staging/tidspbridge/rmgr/drv_interface.c1
-rw-r--r--drivers/staging/tm6000/Kconfig2
-rw-r--r--drivers/staging/tm6000/tm6000-input.c61
-rw-r--r--drivers/staging/usbip/Kconfig2
-rw-r--r--drivers/staging/wlags49_h2/wl_cs.c77
-rw-r--r--drivers/staging/wlags49_h2/wl_internal.h1
-rw-r--r--drivers/staging/wlags49_h2/wl_main.c19
-rw-r--r--drivers/telephony/ixj.c10
-rw-r--r--drivers/telephony/ixj_pcmcia.c41
-rw-r--r--drivers/telephony/phonedev.c1
-rw-r--r--drivers/uio/uio.c164
-rw-r--r--drivers/uio/uio_pci_generic.c13
-rw-r--r--drivers/usb/Kconfig1
-rw-r--r--drivers/usb/atm/Makefile6
-rw-r--r--drivers/usb/atm/cxacru.c18
-rw-r--r--drivers/usb/c67x00/Makefile6
-rw-r--r--drivers/usb/class/cdc-acm.c2
-rw-r--r--drivers/usb/class/cdc-wdm.c3
-rw-r--r--drivers/usb/class/usblp.c1
-rw-r--r--drivers/usb/class/usbtmc.c1
-rw-r--r--drivers/usb/core/Makefile21
-rw-r--r--drivers/usb/core/devices.c11
-rw-r--r--drivers/usb/core/driver.c2
-rw-r--r--drivers/usb/core/endpoint.c2
-rw-r--r--drivers/usb/core/file.c1
-rw-r--r--drivers/usb/core/hcd-pci.c4
-rw-r--r--drivers/usb/core/hcd.c19
-rw-r--r--drivers/usb/core/hub.c41
-rw-r--r--drivers/usb/core/message.c14
-rw-r--r--drivers/usb/core/urb.c5
-rw-r--r--drivers/usb/early/Makefile2
-rw-r--r--drivers/usb/gadget/Kconfig22
-rw-r--r--drivers/usb/gadget/Makefile41
-rw-r--r--drivers/usb/gadget/amd5536udc.c15
-rw-r--r--drivers/usb/gadget/at91_udc.c11
-rw-r--r--drivers/usb/gadget/atmel_usba_udc.c10
-rw-r--r--drivers/usb/gadget/audio.c10
-rw-r--r--drivers/usb/gadget/cdc2.c10
-rw-r--r--drivers/usb/gadget/ci13xxx_udc.c18
-rw-r--r--drivers/usb/gadget/composite.c139
-rw-r--r--drivers/usb/gadget/dbgp.c19
-rw-r--r--drivers/usb/gadget/dummy_hcd.c18
-rw-r--r--drivers/usb/gadget/ether.c16
-rw-r--r--drivers/usb/gadget/f_acm.c2
-rw-r--r--drivers/usb/gadget/f_hid.c1
-rw-r--r--drivers/usb/gadget/f_loopback.c7
-rw-r--r--drivers/usb/gadget/f_mass_storage.c88
-rw-r--r--drivers/usb/gadget/f_sourcesink.c5
-rw-r--r--drivers/usb/gadget/file_storage.c128
-rw-r--r--drivers/usb/gadget/fsl_mxc_udc.c15
-rw-r--r--drivers/usb/gadget/fsl_qe_udc.c12
-rw-r--r--drivers/usb/gadget/fsl_udc_core.c10
-rw-r--r--drivers/usb/gadget/g_ffs.c91
-rw-r--r--drivers/usb/gadget/gmidi.c5
-rw-r--r--drivers/usb/gadget/goku_udc.c35
-rw-r--r--drivers/usb/gadget/hid.c10
-rw-r--r--drivers/usb/gadget/imx_udc.c9
-rw-r--r--drivers/usb/gadget/inode.c7
-rw-r--r--drivers/usb/gadget/langwell_udc.c1058
-rw-r--r--drivers/usb/gadget/langwell_udc.h15
-rw-r--r--drivers/usb/gadget/lh7a40x_udc.c10
-rw-r--r--drivers/usb/gadget/m66592-udc.c9
-rw-r--r--drivers/usb/gadget/mass_storage.c82
-rw-r--r--drivers/usb/gadget/multi.c36
-rw-r--r--drivers/usb/gadget/net2280.c10
-rw-r--r--drivers/usb/gadget/nokia.c11
-rw-r--r--drivers/usb/gadget/omap_udc.c10
-rw-r--r--drivers/usb/gadget/printer.c10
-rw-r--r--drivers/usb/gadget/pxa25x_udc.c9
-rw-r--r--drivers/usb/gadget/pxa27x_udc.c12
-rw-r--r--drivers/usb/gadget/r8a66597-udc.c14
-rw-r--r--drivers/usb/gadget/r8a66597-udc.h2
-rw-r--r--drivers/usb/gadget/rndis.c492
-rw-r--r--drivers/usb/gadget/s3c-hsotg.c9
-rw-r--r--drivers/usb/gadget/s3c2410_udc.c17
-rw-r--r--drivers/usb/gadget/serial.c11
-rw-r--r--drivers/usb/gadget/storage_common.c49
-rw-r--r--drivers/usb/gadget/webcam.c11
-rw-r--r--drivers/usb/gadget/zero.c5
-rw-r--r--drivers/usb/host/Kconfig10
-rw-r--r--drivers/usb/host/Makefile24
-rw-r--r--drivers/usb/host/ehci-dbg.c4
-rw-r--r--drivers/usb/host/ehci-fsl.c105
-rw-r--r--drivers/usb/host/ehci-fsl.h14
-rw-r--r--drivers/usb/host/ehci-hcd.c15
-rw-r--r--drivers/usb/host/ehci-mem.c2
-rw-r--r--drivers/usb/host/ehci-mxc.c13
-rw-r--r--drivers/usb/host/fsl-mph-dr-of.c308
-rw-r--r--drivers/usb/host/imx21-hcd.c284
-rw-r--r--drivers/usb/host/imx21-hcd.h8
-rw-r--r--drivers/usb/host/isp116x-hcd.c6
-rw-r--r--drivers/usb/host/isp1362-hcd.c25
-rw-r--r--drivers/usb/host/ohci-dbg.c3
-rw-r--r--drivers/usb/host/ohci-hcd.c12
-rw-r--r--drivers/usb/host/ohci-pci.c18
-rw-r--r--drivers/usb/host/ohci-pxa27x.c7
-rw-r--r--drivers/usb/host/ohci-sh.c3
-rw-r--r--drivers/usb/host/ohci-sm501.c4
-rw-r--r--drivers/usb/host/ohci.h1
-rw-r--r--drivers/usb/host/oxu210hp-hcd.c2
-rw-r--r--drivers/usb/host/pci-quirks.c18
-rw-r--r--drivers/usb/host/r8a66597.h2
-rw-r--r--drivers/usb/host/sl811_cs.c68
-rw-r--r--drivers/usb/host/uhci-q.c33
-rw-r--r--drivers/usb/host/whci/Kbuild2
-rw-r--r--drivers/usb/host/xhci-hub.c419
-rw-r--r--drivers/usb/host/xhci-mem.c5
-rw-r--r--drivers/usb/host/xhci-pci.c38
-rw-r--r--drivers/usb/host/xhci-ring.c101
-rw-r--r--drivers/usb/host/xhci.c343
-rw-r--r--drivers/usb/host/xhci.h65
-rw-r--r--drivers/usb/image/mdc800.c1
-rw-r--r--drivers/usb/misc/Kconfig13
-rw-r--r--drivers/usb/misc/Makefile45
-rw-r--r--drivers/usb/misc/adutux.c1
-rw-r--r--drivers/usb/misc/ftdi-elan.c2
-rw-r--r--drivers/usb/misc/idmouse.c1
-rw-r--r--drivers/usb/misc/iowarrior.c3
-rw-r--r--drivers/usb/misc/ldusb.c1
-rw-r--r--drivers/usb/misc/rio500.c1
-rw-r--r--drivers/usb/misc/sisusbvga/Makefile3
-rw-r--r--drivers/usb/misc/usblcd.c1
-rw-r--r--drivers/usb/misc/usbtest.c667
-rw-r--r--drivers/usb/misc/yurex.c563
-rw-r--r--drivers/usb/mon/Makefile2
-rw-r--r--drivers/usb/musb/Kconfig16
-rw-r--r--drivers/usb/musb/Makefile71
-rw-r--r--drivers/usb/musb/am35x.c524
-rw-r--r--drivers/usb/musb/blackfin.c7
-rw-r--r--drivers/usb/musb/cppi_dma.c2
-rw-r--r--drivers/usb/musb/da8xx.c469
-rw-r--r--drivers/usb/musb/davinci.c2
-rw-r--r--drivers/usb/musb/musb_core.c57
-rw-r--r--drivers/usb/musb/musb_core.h2
-rw-r--r--drivers/usb/musb/musb_debug.h11
-rw-r--r--drivers/usb/musb/musb_gadget.c132
-rw-r--r--drivers/usb/musb/musb_gadget.h2
-rw-r--r--drivers/usb/musb/musb_host.c11
-rw-r--r--drivers/usb/musb/musbhsdma.c2
-rw-r--r--drivers/usb/musb/omap2430.c1
-rw-r--r--drivers/usb/musb/tusb6010.c4
-rw-r--r--drivers/usb/otg/Kconfig14
-rw-r--r--drivers/usb/otg/Makefile8
-rw-r--r--drivers/usb/otg/langwell_otg.c2408
-rw-r--r--drivers/usb/otg/ulpi.c60
-rw-r--r--drivers/usb/serial/Kconfig9
-rw-r--r--drivers/usb/serial/Makefile10
-rw-r--r--drivers/usb/serial/ark3116.c40
-rw-r--r--drivers/usb/serial/cp210x.c2
-rw-r--r--drivers/usb/serial/ftdi_sio.c43
-rw-r--r--drivers/usb/serial/ftdi_sio_ids.h39
-rw-r--r--drivers/usb/serial/io_edgeport.c49
-rw-r--r--drivers/usb/serial/io_tables.h4
-rw-r--r--drivers/usb/serial/io_ti.c29
-rw-r--r--drivers/usb/serial/mct_u232.c7
-rw-r--r--drivers/usb/serial/mos7720.c54
-rw-r--r--drivers/usb/serial/mos7840.c53
-rw-r--r--drivers/usb/serial/opticon.c44
-rw-r--r--drivers/usb/serial/option.c30
-rw-r--r--drivers/usb/serial/qcserial.c33
-rw-r--r--drivers/usb/serial/sam-ba.c206
-rw-r--r--drivers/usb/serial/ssu100.c48
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.c37
-rw-r--r--drivers/usb/serial/usb-serial.c13
-rw-r--r--drivers/usb/serial/visor.c11
-rw-r--r--drivers/usb/storage/Kconfig13
-rw-r--r--drivers/usb/storage/Makefile35
-rw-r--r--drivers/usb/storage/scsiglue.c16
-rw-r--r--drivers/usb/storage/sddr09.c2
-rw-r--r--drivers/usb/storage/transport.c10
-rw-r--r--drivers/usb/storage/uas.c751
-rw-r--r--drivers/usb/storage/unusual_alauda.h4
-rw-r--r--drivers/usb/storage/unusual_cypress.h4
-rw-r--r--drivers/usb/storage/unusual_datafab.h20
-rw-r--r--drivers/usb/storage/unusual_devs.h580
-rw-r--r--drivers/usb/storage/unusual_freecom.h2
-rw-r--r--drivers/usb/storage/unusual_isd200.h12
-rw-r--r--drivers/usb/storage/unusual_jumpshot.h2
-rw-r--r--drivers/usb/storage/unusual_karma.h2
-rw-r--r--drivers/usb/storage/unusual_onetouch.h4
-rw-r--r--drivers/usb/storage/unusual_sddr09.h12
-rw-r--r--drivers/usb/storage/unusual_sddr55.h8
-rw-r--r--drivers/usb/storage/unusual_usbat.h8
-rw-r--r--drivers/usb/storage/usb.c30
-rw-r--r--drivers/usb/usb-skeleton.c1
-rw-r--r--drivers/usb/wusbcore/Makefile19
-rw-r--r--drivers/uwb/address.c5
-rw-r--r--drivers/uwb/wlp/wss-lc.c7
-rw-r--r--drivers/vhost/net.c19
-rw-r--r--drivers/vhost/vhost.c73
-rw-r--r--drivers/vhost/vhost.h28
-rw-r--r--drivers/video/atafb.c2
-rw-r--r--drivers/video/fbmem.c1
-rw-r--r--drivers/video/mbx/mbxdebugfs.c6
-rw-r--r--drivers/video/omap2/vram.c8
-rw-r--r--drivers/video/pxa168fb.c47
-rw-r--r--drivers/video/q40fb.c4
-rw-r--r--drivers/vlynq/vlynq.c1
-rw-r--r--drivers/watchdog/Kconfig22
-rw-r--r--drivers/watchdog/ar7_wdt.c1
-rw-r--r--drivers/watchdog/booke_wdt.c47
-rw-r--r--drivers/watchdog/cpwd.c16
-rw-r--r--drivers/watchdog/ep93xx_wdt.c1
-rw-r--r--drivers/watchdog/octeon-wdt-main.c1
-rw-r--r--drivers/watchdog/omap_wdt.c1
-rw-r--r--drivers/xen/events.c23
-rw-r--r--drivers/xen/evtchn.c1
-rw-r--r--drivers/xen/xenbus/xenbus_probe.c9
-rw-r--r--drivers/xen/xenfs/super.c1
-rw-r--r--drivers/xen/xenfs/xenbus.c1
-rw-r--r--drivers/zorro/zorro.c2
-rw-r--r--firmware/Makefile14
-rw-r--r--firmware/WHENCE15
-rw-r--r--firmware/bnx2/bnx2-mips-06-5.0.0.j6.fw.ihex5908
-rw-r--r--firmware/bnx2/bnx2-mips-06-6.0.15.fw.ihex5815
-rw-r--r--firmware/bnx2/bnx2-mips-09-5.0.0.j15.fw.ihex6081
-rw-r--r--firmware/bnx2/bnx2-mips-09-6.0.17.fw.ihex6488
-rw-r--r--firmware/bnx2/bnx2-rv2p-06-5.0.0.j3.fw.ihex424
-rw-r--r--firmware/bnx2/bnx2-rv2p-06-6.0.15.fw.ihex366
-rw-r--r--firmware/bnx2/bnx2-rv2p-09-5.0.0.j10.fw.ihex462
-rw-r--r--firmware/bnx2/bnx2-rv2p-09-6.0.17.fw.ihex392
-rw-r--r--firmware/bnx2/bnx2-rv2p-09ax-5.0.0.j10.fw.ihex499
-rw-r--r--firmware/bnx2/bnx2-rv2p-09ax-6.0.17.fw.ihex425
-rw-r--r--firmware/bnx2x-e1-5.2.13.0.fw.ihex10191
-rw-r--r--firmware/bnx2x-e1h-5.2.13.0.fw.ihex12849
-rw-r--r--firmware/bnx2x/bnx2x-e1-6.0.34.0.fw.ihex9476
-rw-r--r--firmware/bnx2x/bnx2x-e1h-6.0.34.0.fw.ihex13178
-rw-r--r--firmware/bnx2x/bnx2x-e2-6.0.34.0.fw.ihex15442
-rw-r--r--fs/Kconfig1
-rw-r--r--fs/adfs/Kconfig1
-rw-r--r--fs/adfs/super.c8
-rw-r--r--fs/affs/super.c18
-rw-r--r--fs/afs/flock.c5
-rw-r--r--fs/afs/mntpt.c1
-rw-r--r--fs/afs/super.c5
-rw-r--r--fs/autofs/Kconfig1
-rw-r--r--fs/autofs/root.c2
-rw-r--r--fs/autofs4/dev-ioctl.c1
-rw-r--r--fs/autofs4/root.c14
-rw-r--r--fs/bfs/inode.c5
-rw-r--r--fs/binfmt_aout.c4
-rw-r--r--fs/binfmt_elf.c2
-rw-r--r--fs/binfmt_misc.c3
-rw-r--r--fs/block_dev.c2
-rw-r--r--fs/btrfs/disk-io.c19
-rw-r--r--fs/btrfs/extent-tree.c3
-rw-r--r--fs/btrfs/super.c1
-rw-r--r--fs/btrfs/volumes.c4
-rw-r--r--fs/btrfs/volumes.h1
-rw-r--r--fs/buffer.c7
-rw-r--r--fs/cachefiles/daemon.c1
-rw-r--r--fs/ceph/Kconfig14
-rw-r--r--fs/ceph/Makefile11
-rw-r--r--fs/ceph/README20
-rw-r--r--fs/ceph/addr.c65
-rw-r--r--fs/ceph/caps.c81
-rw-r--r--fs/ceph/ceph_frag.c3
-rw-r--r--fs/ceph/debugfs.c406
-rw-r--r--fs/ceph/dir.c97
-rw-r--r--fs/ceph/export.c26
-rw-r--r--fs/ceph/file.c209
-rw-r--r--fs/ceph/inode.c19
-rw-r--r--fs/ceph/ioctl.c77
-rw-r--r--fs/ceph/ioctl.h4
-rw-r--r--fs/ceph/locks.c23
-rw-r--r--fs/ceph/mds_client.c129
-rw-r--r--fs/ceph/mds_client.h20
-rw-r--r--fs/ceph/mdsmap.c11
-rw-r--r--fs/ceph/pagelist.c63
-rw-r--r--fs/ceph/snap.c10
-rw-r--r--fs/ceph/strings.c (renamed from fs/ceph/ceph_strings.c)82
-rw-r--r--fs/ceph/super.c1154
-rw-r--r--fs/ceph/super.h400
-rw-r--r--fs/ceph/xattr.c18
-rw-r--r--fs/char_dev.c1
-rw-r--r--fs/cifs/README5
-rw-r--r--fs/cifs/cifs_debug.c12
-rw-r--r--fs/cifs/cifs_debug.h2
-rw-r--r--fs/cifs/cifs_dfs_ref.c24
-rw-r--r--fs/cifs/cifs_fs_sb.h13
-rw-r--r--fs/cifs/cifsacl.c46
-rw-r--r--fs/cifs/cifsencrypt.c214
-rw-r--r--fs/cifs/cifsfs.c105
-rw-r--r--fs/cifs/cifsfs.h10
-rw-r--r--fs/cifs/cifsglob.h91
-rw-r--r--fs/cifs/cifspdu.h1
-rw-r--r--fs/cifs/cifsproto.h22
-rw-r--r--fs/cifs/cifssmb.c79
-rw-r--r--fs/cifs/cn_cifs.h37
-rw-r--r--fs/cifs/connect.c534
-rw-r--r--fs/cifs/dir.c212
-rw-r--r--fs/cifs/file.c791
-rw-r--r--fs/cifs/fscache.c13
-rw-r--r--fs/cifs/inode.c239
-rw-r--r--fs/cifs/ioctl.c17
-rw-r--r--fs/cifs/link.c372
-rw-r--r--fs/cifs/misc.c32
-rw-r--r--fs/cifs/ntlmssp.h15
-rw-r--r--fs/cifs/readdir.c79
-rw-r--r--fs/cifs/sess.c167
-rw-r--r--fs/cifs/transport.c6
-rw-r--r--fs/cifs/xattr.c60
-rw-r--r--fs/coda/inode.c8
-rw-r--r--fs/coda/pioctl.c1
-rw-r--r--fs/coda/psdev.c1
-rw-r--r--fs/compat_ioctl.c70
-rw-r--r--fs/debugfs/file.c3
-rw-r--r--fs/dlm/debug_fs.c3
-rw-r--r--fs/dlm/lock.c3
-rw-r--r--fs/dlm/plock.c3
-rw-r--r--fs/dlm/user.c3
-rw-r--r--fs/ecryptfs/file.c4
-rw-r--r--fs/ecryptfs/miscdev.c1
-rw-r--r--fs/eventfd.c1
-rw-r--r--fs/eventpoll.c3
-rw-r--r--fs/exec.c40
-rw-r--r--fs/exofs/inode.c8
-rw-r--r--fs/ext2/super.c6
-rw-r--r--fs/ext3/fsync.c3
-rw-r--r--fs/ext3/super.c17
-rw-r--r--fs/ext4/fsync.c5
-rw-r--r--fs/ext4/mballoc.c2
-rw-r--r--fs/ext4/super.c19
-rw-r--r--fs/fat/fatent.c3
-rw-r--r--fs/fat/inode.c5
-rw-r--r--fs/fat/misc.c5
-rw-r--r--fs/fat/namei_msdos.c6
-rw-r--r--fs/fat/namei_vfat.c6
-rw-r--r--fs/fifo.c1
-rw-r--r--fs/freevxfs/vxfs_lookup.c14
-rw-r--r--fs/freevxfs/vxfs_super.c7
-rw-r--r--fs/fs-writeback.c19
-rw-r--r--fs/fuse/control.c4
-rw-r--r--fs/fuse/cuse.c1
-rw-r--r--fs/fuse/dev.c2
-rw-r--r--fs/gfs2/Kconfig2
-rw-r--r--fs/gfs2/aops.c24
-rw-r--r--fs/gfs2/bmap.c255
-rw-r--r--fs/gfs2/bmap.h20
-rw-r--r--fs/gfs2/dentry.c2
-rw-r--r--fs/gfs2/dir.c31
-rw-r--r--fs/gfs2/dir.h34
-rw-r--r--fs/gfs2/export.c9
-rw-r--r--fs/gfs2/file.c10
-rw-r--r--fs/gfs2/glock.c23
-rw-r--r--fs/gfs2/glock.h2
-rw-r--r--fs/gfs2/glops.c6
-rw-r--r--fs/gfs2/incore.h8
-rw-r--r--fs/gfs2/inode.c9
-rw-r--r--fs/gfs2/inode.h15
-rw-r--r--fs/gfs2/lock_dlm.c4
-rw-r--r--fs/gfs2/log.c19
-rw-r--r--fs/gfs2/main.c6
-rw-r--r--fs/gfs2/ops_fstype.c79
-rw-r--r--fs/gfs2/ops_inode.c326
-rw-r--r--fs/gfs2/quota.c16
-rw-r--r--fs/gfs2/recovery.c15
-rw-r--r--fs/gfs2/rgrp.c56
-rw-r--r--fs/gfs2/rgrp.h8
-rw-r--r--fs/gfs2/super.c26
-rw-r--r--fs/gfs2/sys.c22
-rw-r--r--fs/gfs2/trace_gfs2.h3
-rw-r--r--fs/gfs2/trans.h9
-rw-r--r--fs/gfs2/xattr.c2
-rw-r--r--fs/hfs/bfind.c4
-rw-r--r--fs/hfs/btree.c2
-rw-r--r--fs/hfs/btree.h2
-rw-r--r--fs/hfs/super.c6
-rw-r--r--fs/hfsplus/bfind.c17
-rw-r--r--fs/hfsplus/bitmap.c20
-rw-r--r--fs/hfsplus/brec.c29
-rw-r--r--fs/hfsplus/btree.c67
-rw-r--r--fs/hfsplus/catalog.c50
-rw-r--r--fs/hfsplus/dir.c201
-rw-r--r--fs/hfsplus/extents.c223
-rw-r--r--fs/hfsplus/hfsplus_fs.h85
-rw-r--r--fs/hfsplus/hfsplus_raw.h3
-rw-r--r--fs/hfsplus/inode.c185
-rw-r--r--fs/hfsplus/ioctl.c153
-rw-r--r--fs/hfsplus/options.c10
-rw-r--r--fs/hfsplus/part_tbl.c5
-rw-r--r--fs/hfsplus/super.c310
-rw-r--r--fs/hfsplus/unicode.c16
-rw-r--r--fs/hfsplus/wrapper.c40
-rw-r--r--fs/hpfs/Kconfig1
-rw-r--r--fs/hpfs/super.c8
-rw-r--r--fs/hppfs/hppfs.c1
-rw-r--r--fs/hugetlbfs/inode.c1
-rw-r--r--fs/isofs/dir.c6
-rw-r--r--fs/isofs/inode.c9
-rw-r--r--fs/isofs/isofs.h1
-rw-r--r--fs/isofs/namei.c8
-rw-r--r--fs/isofs/rock.c10
-rw-r--r--fs/jbd/commit.c32
-rw-r--r--fs/jbd2/checkpoint.c3
-rw-r--r--fs/jbd2/commit.c76
-rw-r--r--fs/jbd2/journal.c4
-rw-r--r--fs/jffs2/fs.c4
-rw-r--r--fs/jffs2/super.c9
-rw-r--r--fs/jfs/super.c23
-rw-r--r--fs/libfs.c29
-rw-r--r--fs/locks.c112
-rw-r--r--fs/logfs/dir.c1
-rw-r--r--fs/namespace.c2
-rw-r--r--fs/ncpfs/dir.c221
-rw-r--r--fs/ncpfs/file.c25
-rw-r--r--fs/ncpfs/inode.c55
-rw-r--r--fs/ncpfs/ioctl.c470
-rw-r--r--fs/ncpfs/ncplib_kernel.c101
-rw-r--r--fs/ncpfs/ncplib_kernel.h15
-rw-r--r--fs/ncpfs/ncpsign_kernel.c10
-rw-r--r--fs/ncpfs/sock.c1
-rw-r--r--fs/nfs/Kconfig1
-rw-r--r--fs/nfs/delegation.c10
-rw-r--r--fs/nfs/nfs4state.c10
-rw-r--r--fs/nfsd/Kconfig1
-rw-r--r--fs/nfsd/nfs4state.c6
-rw-r--r--fs/nfsd/nfsctl.c1
-rw-r--r--fs/nfsd/nfsfh.h2
-rw-r--r--fs/nilfs2/Makefile2
-rw-r--r--fs/nilfs2/bmap.c22
-rw-r--r--fs/nilfs2/bmap.h10
-rw-r--r--fs/nilfs2/btnode.c17
-rw-r--r--fs/nilfs2/cpfile.c72
-rw-r--r--fs/nilfs2/cpfile.h4
-rw-r--r--fs/nilfs2/dat.c92
-rw-r--r--fs/nilfs2/dat.h4
-rw-r--r--fs/nilfs2/export.h17
-rw-r--r--fs/nilfs2/gcdat.c87
-rw-r--r--fs/nilfs2/gcinode.c134
-rw-r--r--fs/nilfs2/ifile.c51
-rw-r--r--fs/nilfs2/ifile.h4
-rw-r--r--fs/nilfs2/inode.c167
-rw-r--r--fs/nilfs2/ioctl.c24
-rw-r--r--fs/nilfs2/mdt.c313
-rw-r--r--fs/nilfs2/mdt.h32
-rw-r--r--fs/nilfs2/namei.c139
-rw-r--r--fs/nilfs2/nilfs.h38
-rw-r--r--fs/nilfs2/page.c55
-rw-r--r--fs/nilfs2/page.h6
-rw-r--r--fs/nilfs2/recovery.c19
-rw-r--r--fs/nilfs2/sb.h10
-rw-r--r--fs/nilfs2/segbuf.c3
-rw-r--r--fs/nilfs2/segment.c102
-rw-r--r--fs/nilfs2/segment.h10
-rw-r--r--fs/nilfs2/sufile.c77
-rw-r--r--fs/nilfs2/sufile.h6
-rw-r--r--fs/nilfs2/super.c629
-rw-r--r--fs/nilfs2/the_nilfs.c346
-rw-r--r--fs/nilfs2/the_nilfs.h101
-rw-r--r--fs/no-block.c1
-rw-r--r--fs/notify/Kconfig2
-rw-r--r--fs/notify/fanotify/fanotify_user.c1
-rw-r--r--fs/notify/inotify/inotify_user.c1
-rw-r--r--fs/ntfs/super.c24
-rw-r--r--fs/ocfs2/aops.c9
-rw-r--r--fs/ocfs2/aops.h3
-rw-r--r--fs/ocfs2/cluster/heartbeat.c532
-rw-r--r--fs/ocfs2/cluster/heartbeat.h4
-rw-r--r--fs/ocfs2/cluster/masklog.h3
-rw-r--r--fs/ocfs2/cluster/nodemanager.c5
-rw-r--r--fs/ocfs2/cluster/ocfs2_nodemanager.h6
-rw-r--r--fs/ocfs2/cluster/tcp.c5
-rw-r--r--fs/ocfs2/dcache.c33
-rw-r--r--fs/ocfs2/dcache.h1
-rw-r--r--fs/ocfs2/dlm/dlmcommon.h29
-rw-r--r--fs/ocfs2/dlm/dlmdebug.c12
-rw-r--r--fs/ocfs2/dlm/dlmdomain.c400
-rw-r--r--fs/ocfs2/dlmfs/dlmfs.c1
-rw-r--r--fs/ocfs2/dlmglue.c8
-rw-r--r--fs/ocfs2/file.c76
-rw-r--r--fs/ocfs2/inode.c1
-rw-r--r--fs/ocfs2/inode.h12
-rw-r--r--fs/ocfs2/ioctl.c356
-rw-r--r--fs/ocfs2/journal.c9
-rw-r--r--fs/ocfs2/journal.h3
-rw-r--r--fs/ocfs2/mmap.c7
-rw-r--r--fs/ocfs2/namei.c3
-rw-r--r--fs/ocfs2/ocfs2.h63
-rw-r--r--fs/ocfs2/ocfs2_fs.h46
-rw-r--r--fs/ocfs2/ocfs2_ioctl.h95
-rw-r--r--fs/ocfs2/refcounttree.c43
-rw-r--r--fs/ocfs2/refcounttree.h7
-rw-r--r--fs/ocfs2/slot_map.c2
-rw-r--r--fs/ocfs2/stack_o2cb.c2
-rw-r--r--fs/ocfs2/stack_user.c4
-rw-r--r--fs/ocfs2/suballoc.c16
-rw-r--r--fs/ocfs2/super.c170
-rw-r--r--fs/ocfs2/symlink.c2
-rw-r--r--fs/ocfs2/sysfile.c60
-rw-r--r--fs/ocfs2/xattr.c2
-rw-r--r--fs/partitions/check.c54
-rw-r--r--fs/partitions/check.h3
-rw-r--r--fs/partitions/efi.c25
-rw-r--r--fs/pipe.c2
-rw-r--r--fs/proc/base.c12
-rw-r--r--fs/proc/proc_sysctl.c1
-rw-r--r--fs/proc/root.c1
-rw-r--r--fs/proc/task_mmu.c1
-rw-r--r--fs/qnx4/dir.c4
-rw-r--r--fs/qnx4/inode.c6
-rw-r--r--fs/qnx4/namei.c4
-rw-r--r--fs/read_write.c5
-rw-r--r--fs/reiserfs/file.c3
-rw-r--r--fs/reiserfs/ioctl.c7
-rw-r--r--fs/reiserfs/journal.c106
-rw-r--r--fs/romfs/super.c1
-rw-r--r--fs/signalfd.c1
-rw-r--r--fs/smbfs/Kconfig1
-rw-r--r--fs/smbfs/inode.c5
-rw-r--r--fs/squashfs/dir.c3
-rw-r--r--fs/squashfs/super.c5
-rw-r--r--fs/sysfs/bin.c68
-rw-r--r--fs/sysfs/group.c59
-rw-r--r--fs/timerfd.c1
-rw-r--r--fs/ubifs/commit.c4
-rw-r--r--fs/ubifs/debug.c157
-rw-r--r--fs/ubifs/debug.h4
-rw-r--r--fs/ubifs/file.c7
-rw-r--r--fs/ubifs/gc.c82
-rw-r--r--fs/ubifs/io.c20
-rw-r--r--fs/ubifs/journal.c3
-rw-r--r--fs/ubifs/key.h14
-rw-r--r--fs/ubifs/log.c6
-rw-r--r--fs/ubifs/lpt.c7
-rw-r--r--fs/ubifs/lpt_commit.c3
-rw-r--r--fs/ubifs/master.c3
-rw-r--r--fs/ubifs/misc.h9
-rw-r--r--fs/ubifs/recovery.c11
-rw-r--r--fs/ubifs/replay.c20
-rw-r--r--fs/ubifs/sb.c9
-rw-r--r--fs/ubifs/scan.c6
-rw-r--r--fs/ubifs/shrinker.c2
-rw-r--r--fs/ubifs/super.c80
-rw-r--r--fs/ubifs/tnc.c5
-rw-r--r--fs/ubifs/ubifs.h23
-rw-r--r--fs/udf/Kconfig1
-rw-r--r--fs/udf/super.c8
-rw-r--r--fs/ufs/Kconfig1
-rw-r--r--fs/ufs/super.c5
-rw-r--r--fs/xfs/linux-2.6/xfs_buf.c237
-rw-r--r--fs/xfs/linux-2.6/xfs_buf.h81
-rw-r--r--fs/xfs/linux-2.6/xfs_cred.h28
-rw-r--r--fs/xfs/linux-2.6/xfs_fs_subr.c31
-rw-r--r--fs/xfs/linux-2.6/xfs_globals.c1
-rw-r--r--fs/xfs/linux-2.6/xfs_globals.h23
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl.c19
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl32.c5
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl32.h6
-rw-r--r--fs/xfs/linux-2.6/xfs_iops.c39
-rw-r--r--fs/xfs/linux-2.6/xfs_linux.h5
-rw-r--r--fs/xfs/linux-2.6/xfs_super.c27
-rw-r--r--fs/xfs/linux-2.6/xfs_super.h1
-rw-r--r--fs/xfs/linux-2.6/xfs_sync.c432
-rw-r--r--fs/xfs/linux-2.6/xfs_sync.h4
-rw-r--r--fs/xfs/linux-2.6/xfs_trace.h5
-rw-r--r--fs/xfs/linux-2.6/xfs_version.h29
-rw-r--r--fs/xfs/quota/xfs_dquot.c164
-rw-r--r--fs/xfs/quota/xfs_qm.c221
-rw-r--r--fs/xfs/quota/xfs_qm_bhv.c2
-rw-r--r--fs/xfs/quota/xfs_qm_syscalls.c16
-rw-r--r--fs/xfs/xfs_ag.h9
-rw-r--r--fs/xfs/xfs_alloc.c4
-rw-r--r--fs/xfs/xfs_alloc_btree.c33
-rw-r--r--fs/xfs/xfs_attr.c37
-rw-r--r--fs/xfs/xfs_bmap.c44
-rw-r--r--fs/xfs/xfs_bmap.h9
-rw-r--r--fs/xfs/xfs_btree.c56
-rw-r--r--fs/xfs/xfs_btree.h14
-rw-r--r--fs/xfs/xfs_buf_item.c7
-rw-r--r--fs/xfs/xfs_da_btree.c2
-rw-r--r--fs/xfs/xfs_dinode.h5
-rw-r--r--fs/xfs/xfs_dir2_leaf.c2
-rw-r--r--fs/xfs/xfs_fs.h7
-rw-r--r--fs/xfs/xfs_fsops.c14
-rw-r--r--fs/xfs/xfs_ialloc.c2
-rw-r--r--fs/xfs/xfs_ialloc_btree.c33
-rw-r--r--fs/xfs/xfs_iget.c4
-rw-r--r--fs/xfs/xfs_inode.c17
-rw-r--r--fs/xfs/xfs_inode.h30
-rw-r--r--fs/xfs/xfs_inode_item.c9
-rw-r--r--fs/xfs/xfs_itable.c3
-rw-r--r--fs/xfs/xfs_log.c18
-rw-r--r--fs/xfs/xfs_log_cil.c244
-rw-r--r--fs/xfs/xfs_log_priv.h37
-rw-r--r--fs/xfs/xfs_log_recover.c25
-rw-r--r--fs/xfs/xfs_mount.c308
-rw-r--r--fs/xfs/xfs_mount.h9
-rw-r--r--fs/xfs/xfs_refcache.h52
-rw-r--r--fs/xfs/xfs_rename.c14
-rw-r--r--fs/xfs/xfs_rtalloc.c29
-rw-r--r--fs/xfs/xfs_sb.h10
-rw-r--r--fs/xfs/xfs_trans.c91
-rw-r--r--fs/xfs/xfs_trans.h3
-rw-r--r--fs/xfs/xfs_trans_buf.c2
-rw-r--r--fs/xfs/xfs_trans_inode.c30
-rw-r--r--fs/xfs/xfs_types.h2
-rw-r--r--fs/xfs/xfs_utils.c9
-rw-r--r--fs/xfs/xfs_utils.h3
-rw-r--r--fs/xfs/xfs_vnodeops.c65
-rw-r--r--fs/xfs/xfs_vnodeops.h6
-rw-r--r--include/acpi/acpixf.h2
-rw-r--r--include/asm-generic/atomic.h39
-rw-r--r--include/asm-generic/bitops/find.h39
-rw-r--r--include/asm-generic/cmpxchg-local.h1
-rw-r--r--include/asm-generic/fcntl.h2
-rw-r--r--include/asm-generic/hardirq.h2
-rw-r--r--include/asm-generic/io.h26
-rw-r--r--include/asm-generic/ioctls.h2
-rw-r--r--include/asm-generic/irqflags.h52
-rw-r--r--include/asm-generic/kdebug.h2
-rw-r--r--include/asm-generic/percpu.h14
-rw-r--r--include/asm-generic/pgtable.h4
-rw-r--r--include/asm-generic/system.h20
-rw-r--r--include/asm-generic/vmlinux.lds.h14
-rw-r--r--include/drm/drmP.h29
-rw-r--r--include/drm/drm_pciids.h2
-rw-r--r--include/drm/ttm/ttm_bo_api.h4
-rw-r--r--include/linux/Kbuild2
-rw-r--r--include/linux/acpi_pmtmr.h2
-rw-r--r--include/linux/altera_uart.h5
-rw-r--r--include/linux/amba/bus.h15
-rw-r--r--include/linux/amba/mmci.h2
-rw-r--r--include/linux/amba/pl022.h13
-rw-r--r--include/linux/amba/serial.h11
-rw-r--r--include/linux/ata.h46
-rw-r--r--include/linux/atmdev.h2
-rw-r--r--include/linux/bio.h15
-rw-r--r--include/linux/bitops.h45
-rw-r--r--include/linux/blk_types.h11
-rw-r--r--include/linux/blkdev.h165
-rw-r--r--include/linux/buffer_head.h2
-rw-r--r--include/linux/can/platform/mcp251x.h4
-rw-r--r--include/linux/ceph/auth.h (renamed from fs/ceph/auth.h)4
-rw-r--r--include/linux/ceph/buffer.h (renamed from fs/ceph/buffer.h)0
-rw-r--r--include/linux/ceph/ceph_debug.h (renamed from fs/ceph/ceph_debug.h)5
-rw-r--r--include/linux/ceph/ceph_frag.h (renamed from fs/ceph/ceph_frag.h)0
-rw-r--r--include/linux/ceph/ceph_fs.h (renamed from fs/ceph/ceph_fs.h)1
-rw-r--r--include/linux/ceph/ceph_hash.h (renamed from fs/ceph/ceph_hash.h)0
-rw-r--r--include/linux/ceph/debugfs.h33
-rw-r--r--include/linux/ceph/decode.h (renamed from fs/ceph/decode.h)5
-rw-r--r--include/linux/ceph/libceph.h249
-rw-r--r--include/linux/ceph/mdsmap.h (renamed from fs/ceph/mdsmap.h)0
-rw-r--r--include/linux/ceph/messenger.h (renamed from fs/ceph/messenger.h)12
-rw-r--r--include/linux/ceph/mon_client.h (renamed from fs/ceph/mon_client.h)1
-rw-r--r--include/linux/ceph/msgpool.h (renamed from fs/ceph/msgpool.h)0
-rw-r--r--include/linux/ceph/msgr.h (renamed from fs/ceph/msgr.h)0
-rw-r--r--include/linux/ceph/osd_client.h (renamed from fs/ceph/osd_client.h)67
-rw-r--r--include/linux/ceph/osdmap.h (renamed from fs/ceph/osdmap.h)4
-rw-r--r--include/linux/ceph/pagelist.h (renamed from fs/ceph/pagelist.h)23
-rw-r--r--include/linux/ceph/rados.h (renamed from fs/ceph/rados.h)0
-rw-r--r--include/linux/ceph/types.h (renamed from fs/ceph/types.h)0
-rw-r--r--include/linux/cgroup.h4
-rw-r--r--include/linux/compiler.h4
-rw-r--r--include/linux/coredump.h34
-rw-r--r--include/linux/cpuidle.h1
-rw-r--r--include/linux/cred.h2
-rw-r--r--include/linux/crush/crush.h (renamed from fs/ceph/crush/crush.h)0
-rw-r--r--include/linux/crush/hash.h (renamed from fs/ceph/crush/hash.h)0
-rw-r--r--include/linux/crush/mapper.h (renamed from fs/ceph/crush/mapper.h)0
-rw-r--r--include/linux/dccp.h6
-rw-r--r--include/linux/debug_locks.h5
-rw-r--r--include/linux/device.h7
-rw-r--r--include/linux/dlm.h4
-rw-r--r--include/linux/dmaengine.h2
-rw-r--r--include/linux/dmar.h16
-rw-r--r--include/linux/drbd.h22
-rw-r--r--include/linux/drbd_limits.h29
-rw-r--r--include/linux/drbd_nl.h6
-rw-r--r--include/linux/dynamic_debug.h41
-rw-r--r--include/linux/early_res.h23
-rw-r--r--include/linux/edac.h4
-rw-r--r--include/linux/elevator.h3
-rw-r--r--include/linux/etherdevice.h22
-rw-r--r--include/linux/ethtool.h190
-rw-r--r--include/linux/exportfs.h13
-rw-r--r--include/linux/fdtable.h6
-rw-r--r--include/linux/fs.h47
-rw-r--r--include/linux/fsl_devices.h18
-rw-r--r--include/linux/ftrace_event.h8
-rw-r--r--include/linux/genhd.h60
-rw-r--r--include/linux/hardirq.h12
-rw-r--r--include/linux/htirq.h5
-rw-r--r--include/linux/idr.h4
-rw-r--r--include/linux/ieee80211.h71
-rw-r--r--include/linux/if.h2
-rw-r--r--include/linux/if_bonding.h3
-rw-r--r--include/linux/if_ether.h2
-rw-r--r--include/linux/if_macvlan.h9
-rw-r--r--include/linux/if_pppox.h52
-rw-r--r--include/linux/if_vlan.h31
-rw-r--r--include/linux/in.h19
-rw-r--r--include/linux/in6.h4
-rw-r--r--include/linux/inetdevice.h21
-rw-r--r--include/linux/init.h13
-rw-r--r--include/linux/init_task.h14
-rw-r--r--include/linux/input.h2
-rw-r--r--include/linux/interrupt.h12
-rw-r--r--include/linux/iocontext.h2
-rw-r--r--include/linux/ip_vs.h15
-rw-r--r--include/linux/ipv6.h4
-rw-r--r--include/linux/irq.h447
-rw-r--r--include/linux/irq_work.h20
-rw-r--r--include/linux/irqdesc.h159
-rw-r--r--include/linux/irqflags.h107
-rw-r--r--include/linux/irqnr.h5
-rw-r--r--include/linux/jump_label.h74
-rw-r--r--include/linux/jump_label_ref.h44
-rw-r--r--include/linux/kdb.h51
-rw-r--r--include/linux/kernel.h23
-rw-r--r--include/linux/key.h3
-rw-r--r--include/linux/kobject.h2
-rw-r--r--include/linux/kvm_host.h2
-rw-r--r--include/linux/libata.h65
-rw-r--r--include/linux/list.h1
-rw-r--r--include/linux/lockdep.h21
-rw-r--r--include/linux/memblock.h168
-rw-r--r--include/linux/memory.h4
-rw-r--r--include/linux/mfd/tc35892.h4
-rw-r--r--include/linux/mlx4/cmd.h1
-rw-r--r--include/linux/mlx4/device.h7
-rw-r--r--include/linux/mm.h2
-rw-r--r--include/linux/mm_types.h2
-rw-r--r--include/linux/mmc/sdio_ids.h1
-rw-r--r--include/linux/module.h10
-rw-r--r--include/linux/mroute.h1
-rw-r--r--include/linux/msi.h13
-rw-r--r--include/linux/mtio.h1
-rw-r--r--include/linux/ncp_fs.h28
-rw-r--r--include/linux/ncp_fs_sb.h4
-rw-r--r--include/linux/netdevice.h120
-rw-r--r--include/linux/netfilter/nf_conntrack_common.h6
-rw-r--r--include/linux/netfilter/nf_conntrack_sip.h1
-rw-r--r--include/linux/netfilter/nfnetlink_conntrack.h11
-rw-r--r--include/linux/netfilter/x_tables.h5
-rw-r--r--include/linux/netfilter/xt_SECMARK.h12
-rw-r--r--include/linux/netfilter/xt_TPROXY.h13
-rw-r--r--include/linux/netfilter_arp/arp_tables.h68
-rw-r--r--include/linux/netfilter_bridge/Kbuild2
-rw-r--r--include/linux/netfilter_ipv4/ip_tables.h107
-rw-r--r--include/linux/netfilter_ipv6/ip6_tables.h110
-rw-r--r--include/linux/netpoll.h9
-rw-r--r--include/linux/nfs_fs.h2
-rw-r--r--include/linux/nilfs2_fs.h18
-rw-r--r--include/linux/nl80211.h210
-rw-r--r--include/linux/notifier.h10
-rw-r--r--include/linux/opp.h105
-rw-r--r--include/linux/oprofile.h7
-rw-r--r--include/linux/pci_ids.h13
-rw-r--r--include/linux/percpu-defs.h21
-rw-r--r--include/linux/percpu.h9
-rw-r--r--include/linux/perf_event.h212
-rw-r--r--include/linux/phonet.h5
-rw-r--r--include/linux/phy.h4
-rw-r--r--include/linux/pkt_cls.h1
-rw-r--r--include/linux/platform_device.h3
-rw-r--r--include/linux/pm.h38
-rw-r--r--include/linux/pm_runtime.h121
-rw-r--r--include/linux/pm_wakeup.h127
-rw-r--r--include/linux/radix-tree.h4
-rw-r--r--include/linux/rculist.h62
-rw-r--r--include/linux/rculist_nulls.h16
-rw-r--r--include/linux/rcupdate.h490
-rw-r--r--include/linux/rcutiny.h104
-rw-r--r--include/linux/rcutree.h57
-rw-r--r--include/linux/rds.h115
-rw-r--r--include/linux/resume-trace.h2
-rw-r--r--include/linux/rtnetlink.h30
-rw-r--r--include/linux/sched.h51
-rw-r--r--include/linux/security.h45
-rw-r--r--include/linux/selection.h1
-rw-r--r--include/linux/selinux.h63
-rw-r--r--include/linux/serial_8250.h8
-rw-r--r--include/linux/serial_core.h10
-rw-r--r--include/linux/skbuff.h117
-rw-r--r--include/linux/smp_lock.h7
-rw-r--r--include/linux/socket.h1
-rw-r--r--include/linux/spinlock.h1
-rw-r--r--include/linux/srcu.h34
-rw-r--r--include/linux/ssb/ssb_regs.h1
-rw-r--r--include/linux/stmmac.h6
-rw-r--r--include/linux/stop_machine.h10
-rw-r--r--include/linux/sunrpc/auth_gss.h4
-rw-r--r--include/linux/suspend.h6
-rw-r--r--include/linux/sysfs.h15
-rw-r--r--include/linux/tc_act/Kbuild1
-rw-r--r--include/linux/tc_act/tc_csum.h32
-rw-r--r--include/linux/tc_ematch/tc_em_meta.h1
-rw-r--r--include/linux/tcp.h1
-rw-r--r--include/linux/thread_info.h4
-rw-r--r--include/linux/tipc.h30
-rw-r--r--include/linux/topology.h6
-rw-r--r--include/linux/tracepoint.h5
-rw-r--r--include/linux/tty.h3
-rw-r--r--include/linux/tty_driver.h9
-rw-r--r--include/linux/types.h15
-rw-r--r--include/linux/uio_driver.h2
-rw-r--r--include/linux/usb/cdc.h79
-rw-r--r--include/linux/usb/ch9.h68
-rw-r--r--include/linux/usb/composite.h40
-rw-r--r--include/linux/usb/gadget.h20
-rw-r--r--include/linux/usb/hcd.h2
-rw-r--r--include/linux/usb/intel_mid_otg.h180
-rw-r--r--include/linux/usb/langwell_otg.h139
-rw-r--r--include/linux/usb/ncm.h114
-rw-r--r--include/linux/usb/otg.h11
-rw-r--r--include/linux/usb/serial.h2
-rw-r--r--include/linux/usb/storage.h48
-rw-r--r--include/linux/usb_usual.h43
-rw-r--r--include/linux/wait.h1
-rw-r--r--include/linux/wireless.h2
-rw-r--r--include/linux/wl12xx.h (renamed from include/linux/spi/wl12xx.h)23
-rw-r--r--include/linux/workqueue.h51
-rw-r--r--include/media/videobuf-dma-sg.h1
-rw-r--r--include/net/9p/client.h3
-rw-r--r--include/net/addrconf.h65
-rw-r--r--include/net/arp.h2
-rw-r--r--include/net/bluetooth/bluetooth.h20
-rw-r--r--include/net/bluetooth/hci.h2
-rw-r--r--include/net/bluetooth/hci_core.h2
-rw-r--r--include/net/bluetooth/l2cap.h2
-rw-r--r--include/net/bluetooth/rfcomm.h5
-rw-r--r--include/net/cfg80211.h296
-rw-r--r--include/net/cls_cgroup.h3
-rw-r--r--include/net/dst.h33
-rw-r--r--include/net/dst_ops.h37
-rw-r--r--include/net/fib_rules.h3
-rw-r--r--include/net/flow.h1
-rw-r--r--include/net/genetlink.h18
-rw-r--r--include/net/gre.h18
-rw-r--r--include/net/inet_connection_sock.h1
-rw-r--r--include/net/inet_ecn.h2
-rw-r--r--include/net/inet_hashtables.h2
-rw-r--r--include/net/ip.h6
-rw-r--r--include/net/ip_fib.h17
-rw-r--r--include/net/ip_vs.h180
-rw-r--r--include/net/ipip.h12
-rw-r--r--include/net/ipv6.h35
-rw-r--r--include/net/irda/irlan_common.h1
-rw-r--r--include/net/irda/irlan_event.h2
-rw-r--r--include/net/irda/irlap.h2
-rw-r--r--include/net/irda/irlmp.h2
-rw-r--r--include/net/irda/irttp.h2
-rw-r--r--include/net/mac80211.h195
-rw-r--r--include/net/neighbour.h47
-rw-r--r--include/net/net_namespace.h17
-rw-r--r--include/net/netfilter/ipv6/nf_defrag_ipv6.h6
-rw-r--r--include/net/netfilter/nf_conntrack.h2
-rw-r--r--include/net/netfilter/nf_conntrack_expect.h12
-rw-r--r--include/net/netfilter/nf_nat_protocol.h3
-rw-r--r--include/net/netfilter/nf_tproxy_core.h192
-rw-r--r--include/net/netfilter/xt_log.h54
-rw-r--r--include/net/netns/xfrm.h9
-rw-r--r--include/net/phonet/pep.h26
-rw-r--r--include/net/phonet/phonet.h5
-rw-r--r--include/net/phonet/pn_dev.h1
-rw-r--r--include/net/raw.h5
-rw-r--r--include/net/rtnetlink.h1
-rw-r--r--include/net/sch_generic.h5
-rw-r--r--include/net/sctp/sctp.h60
-rw-r--r--include/net/sctp/sm.h10
-rw-r--r--include/net/sctp/structs.h2
-rw-r--r--include/net/sctp/tsnmap.h2
-rw-r--r--include/net/sock.h14
-rw-r--r--include/net/tc_act/tc_csum.h15
-rw-r--r--include/net/tcp.h11
-rw-r--r--include/net/tipc/tipc.h71
-rw-r--r--include/net/tipc/tipc_msg.h10
-rw-r--r--include/net/tipc/tipc_port.h2
-rw-r--r--include/net/udp.h3
-rw-r--r--include/net/xfrm.h3
-rw-r--r--include/pcmcia/cs.h95
-rw-r--r--include/pcmcia/ds.h87
-rw-r--r--include/pcmcia/ss.h1
-rw-r--r--include/scsi/libsas.h1
-rw-r--r--include/scsi/scsi.h8
-rw-r--r--include/scsi/scsi_device.h2
-rw-r--r--include/scsi/scsi_host.h7
-rw-r--r--include/scsi/scsi_tcq.h6
-rw-r--r--include/scsi/scsi_transport_fc.h3
-rw-r--r--include/sound/core.h6
-rw-r--r--include/trace/events/irq.h26
-rw-r--r--include/trace/events/napi.h25
-rw-r--r--include/trace/events/net.h82
-rw-r--r--include/trace/events/power.h90
-rw-r--r--include/trace/events/sched.h29
-rw-r--r--include/trace/events/skb.h17
-rw-r--r--include/trace/events/workqueue.h77
-rw-r--r--init/Kconfig111
-rw-r--r--init/do_mounts.c70
-rw-r--r--init/main.c3
-rw-r--r--ipc/mqueue.c1
-rw-r--r--ipc/sem.c2
-rw-r--r--ipc/shm.c2
-rw-r--r--kernel/Makefile6
-rw-r--r--kernel/cgroup.c6
-rw-r--r--kernel/configs.c1
-rw-r--r--kernel/cpuset.c4
-rw-r--r--kernel/debug/debug_core.c139
-rw-r--r--kernel/debug/debug_core.h1
-rw-r--r--kernel/debug/kdb/kdb_debugger.c3
-rw-r--r--kernel/debug/kdb/kdb_io.c2
-rw-r--r--kernel/debug/kdb/kdb_main.c18
-rw-r--r--kernel/debug/kdb/kdb_private.h48
-rw-r--r--kernel/early_res.c590
-rw-r--r--kernel/exit.c4
-rw-r--r--kernel/futex.c66
-rw-r--r--kernel/futex_compat.c2
-rw-r--r--kernel/gcov/fs.c1
-rw-r--r--kernel/hrtimer.c13
-rw-r--r--kernel/hung_task.c4
-rw-r--r--kernel/hw_breakpoint.c75
-rw-r--r--kernel/irq/Kconfig53
-rw-r--r--kernel/irq/Makefile3
-rw-r--r--kernel/irq/autoprobe.c15
-rw-r--r--kernel/irq/chip.c378
-rw-r--r--kernel/irq/dummychip.c68
-rw-r--r--kernel/irq/handle.c341
-rw-r--r--kernel/irq/internals.h39
-rw-r--r--kernel/irq/irqdesc.c395
-rw-r--r--kernel/irq/manage.c87
-rw-r--r--kernel/irq/migration.c12
-rw-r--r--kernel/irq/numa_migrate.c120
-rw-r--r--kernel/irq/proc.c26
-rw-r--r--kernel/irq/resend.c5
-rw-r--r--kernel/irq/spurious.c8
-rw-r--r--kernel/irq_work.c164
-rw-r--r--kernel/jump_label.c429
-rw-r--r--kernel/kfifo.c2
-rw-r--r--kernel/kprobes.c27
-rw-r--r--kernel/lockdep.c51
-rw-r--r--kernel/module.c10
-rw-r--r--kernel/perf_event.c2596
-rw-r--r--kernel/pid.c3
-rw-r--r--kernel/pm_qos_params.c1
-rw-r--r--kernel/power/Kconfig17
-rw-r--r--kernel/power/hibernate.c25
-rw-r--r--kernel/power/main.c29
-rw-r--r--kernel/power/power.h10
-rw-r--r--kernel/power/process.c11
-rw-r--r--kernel/power/snapshot.c13
-rw-r--r--kernel/power/swap.c300
-rw-r--r--kernel/printk.c4
-rw-r--r--kernel/profile.c1
-rw-r--r--kernel/rcupdate.c8
-rw-r--r--kernel/rcutiny.c33
-rw-r--r--kernel/rcutiny_plugin.h582
-rw-r--r--kernel/rcutorture.c17
-rw-r--r--kernel/rcutree.c92
-rw-r--r--kernel/rcutree.h20
-rw-r--r--kernel/rcutree_plugin.h47
-rw-r--r--kernel/rcutree_trace.c12
-rw-r--r--kernel/rtmutex-tester.c6
-rw-r--r--kernel/sched.c309
-rw-r--r--kernel/sched_fair.c81
-rw-r--r--kernel/sched_features.h5
-rw-r--r--kernel/sched_rt.c40
-rw-r--r--kernel/sched_stoptask.c108
-rw-r--r--kernel/signal.c8
-rw-r--r--kernel/smp.c17
-rw-r--r--kernel/softirq.c75
-rw-r--r--kernel/srcu.c2
-rw-r--r--kernel/stop_machine.c8
-rw-r--r--kernel/sys_ni.c1
-rw-r--r--kernel/sysctl.c2
-rw-r--r--kernel/sysctl_check.c9
-rw-r--r--kernel/test_kprobes.c12
-rw-r--r--kernel/time/ntp.c14
-rw-r--r--kernel/timer.c7
-rw-r--r--kernel/trace/Kconfig7
-rw-r--r--kernel/trace/blktrace.c16
-rw-r--r--kernel/trace/ftrace.c129
-rw-r--r--kernel/trace/ring_buffer.c24
-rw-r--r--kernel/trace/trace.c2
-rw-r--r--kernel/trace/trace.h4
-rw-r--r--kernel/trace/trace_event_perf.c28
-rw-r--r--kernel/trace/trace_events.c61
-rw-r--r--kernel/trace/trace_functions_graph.c209
-rw-r--r--kernel/trace/trace_irqsoff.c152
-rw-r--r--kernel/trace/trace_kdb.c1
-rw-r--r--kernel/trace/trace_sched_wakeup.c256
-rw-r--r--kernel/trace/trace_stack.c1
-rw-r--r--kernel/trace/trace_workqueue.c10
-rw-r--r--kernel/tracepoint.c14
-rw-r--r--kernel/watchdog.c43
-rw-r--r--kernel/workqueue.c310
-rw-r--r--lib/Kconfig.debug58
-rw-r--r--lib/bug.c6
-rw-r--r--lib/dma-debug.c1
-rw-r--r--lib/dynamic_debug.c140
-rw-r--r--lib/kobject.c39
-rw-r--r--lib/list_sort.c2
-rw-r--r--lib/radix-tree.c2
-rw-r--r--lib/swiotlb.c18
-rw-r--r--mm/bootmem.c13
-rw-r--r--mm/ksm.c6
-rw-r--r--mm/memblock.c837
-rw-r--r--mm/memcontrol.c10
-rw-r--r--mm/memory-failure.c12
-rw-r--r--mm/memory.c2
-rw-r--r--mm/memory_hotplug.c2
-rw-r--r--mm/page_alloc.c90
-rw-r--r--mm/percpu.c349
-rw-r--r--mm/rmap.c8
-rw-r--r--mm/sparse-vmemmap.c11
-rw-r--r--mm/swapfile.c6
-rw-r--r--mm/vmalloc.c9
-rw-r--r--net/802/fc.c2
-rw-r--r--net/802/fddi.c12
-rw-r--r--net/802/hippi.c2
-rw-r--r--net/802/tr.c2
-rw-r--r--net/8021q/vlan.c93
-rw-r--r--net/8021q/vlan.h17
-rw-r--r--net/8021q/vlan_core.c117
-rw-r--r--net/8021q/vlan_dev.c10
-rw-r--r--net/9p/client.c55
-rw-r--r--net/9p/trans_fd.c2
-rw-r--r--net/Kconfig1
-rw-r--r--net/Makefile1
-rw-r--r--net/atm/clip.c4
-rw-r--r--net/atm/common.c2
-rw-r--r--net/atm/lec.c1
-rw-r--r--net/atm/mpc.c2
-rw-r--r--net/atm/proc.c1
-rw-r--r--net/ax25/af_ax25.c2
-rw-r--r--net/ax25/ax25_route.c4
-rw-r--r--net/bluetooth/af_bluetooth.c114
-rw-r--r--net/bluetooth/cmtp/core.c6
-rw-r--r--net/bluetooth/hci_core.c1
-rw-r--r--net/bluetooth/hci_sysfs.c21
-rw-r--r--net/bluetooth/hidp/core.c8
-rw-r--r--net/bluetooth/l2cap.c122
-rw-r--r--net/bluetooth/lib.c4
-rw-r--r--net/bluetooth/rfcomm/core.c43
-rw-r--r--net/bluetooth/rfcomm/sock.c108
-rw-r--r--net/bluetooth/rfcomm/tty.c8
-rw-r--r--net/bridge/br_device.c8
-rw-r--r--net/bridge/br_if.c29
-rw-r--r--net/bridge/br_input.c4
-rw-r--r--net/bridge/br_netfilter.c134
-rw-r--r--net/bridge/netfilter/ebt_vlan.c25
-rw-r--r--net/bridge/netfilter/ebtables.c15
-rw-r--r--net/caif/caif_dev.c24
-rw-r--r--net/caif/caif_socket.c44
-rw-r--r--net/caif/cfcnfg.c49
-rw-r--r--net/caif/cfctrl.c59
-rw-r--r--net/caif/cfdbgl.c4
-rw-r--r--net/caif/cfdgml.c11
-rw-r--r--net/caif/cffrml.c14
-rw-r--r--net/caif/cfmuxl.c14
-rw-r--r--net/caif/cfpkt_skbuff.c48
-rw-r--r--net/caif/cfrfml.c12
-rw-r--r--net/caif/cfserl.c4
-rw-r--r--net/caif/cfsrvl.c17
-rw-r--r--net/caif/cfutill.c12
-rw-r--r--net/caif/cfveil.c11
-rw-r--r--net/caif/cfvidl.c6
-rw-r--r--net/caif/chnl_net.c47
-rw-r--r--net/can/raw.c37
-rw-r--r--net/ceph/Kconfig28
-rw-r--r--net/ceph/Makefile37
-rw-r--r--net/ceph/armor.c (renamed from fs/ceph/armor.c)0
-rw-r--r--net/ceph/auth.c (renamed from fs/ceph/auth.c)10
-rw-r--r--net/ceph/auth_none.c (renamed from fs/ceph/auth_none.c)7
-rw-r--r--net/ceph/auth_none.h (renamed from fs/ceph/auth_none.h)3
-rw-r--r--net/ceph/auth_x.c (renamed from fs/ceph/auth_x.c)9
-rw-r--r--net/ceph/auth_x.h (renamed from fs/ceph/auth_x.h)3
-rw-r--r--net/ceph/auth_x_protocol.h (renamed from fs/ceph/auth_x_protocol.h)0
-rw-r--r--net/ceph/buffer.c (renamed from fs/ceph/buffer.c)9
-rw-r--r--net/ceph/ceph_common.c529
-rw-r--r--net/ceph/ceph_fs.c (renamed from fs/ceph/ceph_fs.c)5
-rw-r--r--net/ceph/ceph_hash.c (renamed from fs/ceph/ceph_hash.c)2
-rw-r--r--net/ceph/ceph_strings.c84
-rw-r--r--net/ceph/crush/crush.c (renamed from fs/ceph/crush/crush.c)2
-rw-r--r--net/ceph/crush/hash.c (renamed from fs/ceph/crush/hash.c)2
-rw-r--r--net/ceph/crush/mapper.c (renamed from fs/ceph/crush/mapper.c)4
-rw-r--r--net/ceph/crypto.c (renamed from fs/ceph/crypto.c)4
-rw-r--r--net/ceph/crypto.h (renamed from fs/ceph/crypto.h)4
-rw-r--r--net/ceph/debugfs.c267
-rw-r--r--net/ceph/messenger.c (renamed from fs/ceph/messenger.c)296
-rw-r--r--net/ceph/mon_client.c (renamed from fs/ceph/mon_client.c)73
-rw-r--r--net/ceph/msgpool.c (renamed from fs/ceph/msgpool.c)4
-rw-r--r--net/ceph/osd_client.c (renamed from fs/ceph/osd_client.c)402
-rw-r--r--net/ceph/osdmap.c (renamed from fs/ceph/osdmap.c)30
-rw-r--r--net/ceph/pagelist.c154
-rw-r--r--net/ceph/pagevec.c223
-rw-r--r--net/core/datagram.c6
-rw-r--r--net/core/dev.c605
-rw-r--r--net/core/dst.c39
-rw-r--r--net/core/ethtool.c97
-rw-r--r--net/core/fib_rules.c16
-rw-r--r--net/core/filter.c10
-rw-r--r--net/core/flow.c82
-rw-r--r--net/core/gen_estimator.c4
-rw-r--r--net/core/iovec.c6
-rw-r--r--net/core/neighbour.c486
-rw-r--r--net/core/net-sysfs.c39
-rw-r--r--net/core/net-sysfs.h4
-rw-r--r--net/core/net-traces.c1
-rw-r--r--net/core/netpoll.c6
-rw-r--r--net/core/pktgen.c12
-rw-r--r--net/core/rtnetlink.c39
-rw-r--r--net/core/skbuff.c106
-rw-r--r--net/core/sock.c9
-rw-r--r--net/core/stream.c8
-rw-r--r--net/core/utils.c15
-rw-r--r--net/dccp/ccid.h52
-rw-r--r--net/dccp/ccids/Kconfig31
-rw-r--r--net/dccp/ccids/ccid2.c289
-rw-r--r--net/dccp/ccids/ccid2.h35
-rw-r--r--net/dccp/ccids/ccid3.c256
-rw-r--r--net/dccp/ccids/ccid3.h51
-rw-r--r--net/dccp/ccids/lib/loss_interval.c2
-rw-r--r--net/dccp/ccids/lib/packet_history.c39
-rw-r--r--net/dccp/ccids/lib/packet_history.h22
-rw-r--r--net/dccp/ccids/lib/tfrc.h1
-rw-r--r--net/dccp/ccids/lib/tfrc_equation.c14
-rw-r--r--net/dccp/dccp.h46
-rw-r--r--net/dccp/feat.c10
-rw-r--r--net/dccp/feat.h1
-rw-r--r--net/dccp/input.c20
-rw-r--r--net/dccp/ipv4.c10
-rw-r--r--net/dccp/ipv6.c10
-rw-r--r--net/dccp/minisocks.c30
-rw-r--r--net/dccp/options.c31
-rw-r--r--net/dccp/output.c20
-rw-r--r--net/dccp/probe.c1
-rw-r--r--net/dccp/proto.c50
-rw-r--r--net/decnet/dn_neigh.c13
-rw-r--r--net/decnet/dn_nsp_out.c8
-rw-r--r--net/decnet/dn_route.c3
-rw-r--r--net/econet/af_econet.c6
-rw-r--r--net/ethernet/eth.c8
-rw-r--r--net/ipv4/Kconfig9
-rw-r--r--net/ipv4/Makefile1
-rw-r--r--net/ipv4/af_inet.c8
-rw-r--r--net/ipv4/arp.c245
-rw-r--r--net/ipv4/datagram.c2
-rw-r--r--net/ipv4/devinet.c11
-rw-r--r--net/ipv4/fib_frontend.c192
-rw-r--r--net/ipv4/fib_hash.c291
-rw-r--r--net/ipv4/fib_lookup.h11
-rw-r--r--net/ipv4/fib_rules.c13
-rw-r--r--net/ipv4/fib_semantics.c297
-rw-r--r--net/ipv4/fib_trie.c84
-rw-r--r--net/ipv4/gre.c151
-rw-r--r--net/ipv4/icmp.c4
-rw-r--r--net/ipv4/igmp.c36
-rw-r--r--net/ipv4/inet_diag.c2
-rw-r--r--net/ipv4/inet_hashtables.c28
-rw-r--r--net/ipv4/ip_fragment.c6
-rw-r--r--net/ipv4/ip_gre.c237
-rw-r--r--net/ipv4/ip_options.c3
-rw-r--r--net/ipv4/ip_output.c24
-rw-r--r--net/ipv4/ipip.c212
-rw-r--r--net/ipv4/ipmr.c428
-rw-r--r--net/ipv4/netfilter/Kconfig4
-rw-r--r--net/ipv4/netfilter/arp_tables.c64
-rw-r--r--net/ipv4/netfilter/arpt_mangle.c2
-rw-r--r--net/ipv4/netfilter/ip_tables.c84
-rw-r--r--net/ipv4/netfilter/ipt_CLUSTERIP.c31
-rw-r--r--net/ipv4/netfilter/ipt_LOG.c145
-rw-r--r--net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c28
-rw-r--r--net/ipv4/netfilter/nf_nat_amanda.c9
-rw-r--r--net/ipv4/netfilter/nf_nat_core.c53
-rw-r--r--net/ipv4/netfilter/nf_nat_ftp.c9
-rw-r--r--net/ipv4/netfilter/nf_nat_h323.c53
-rw-r--r--net/ipv4/netfilter/nf_nat_helper.c76
-rw-r--r--net/ipv4/netfilter/nf_nat_irc.c9
-rw-r--r--net/ipv4/netfilter/nf_nat_rule.c17
-rw-r--r--net/ipv4/netfilter/nf_nat_sip.c27
-rw-r--r--net/ipv4/protocol.c31
-rw-r--r--net/ipv4/raw.c2
-rw-r--r--net/ipv4/route.c190
-rw-r--r--net/ipv4/tcp.c11
-rw-r--r--net/ipv4/tcp_input.c55
-rw-r--r--net/ipv4/tcp_ipv4.c12
-rw-r--r--net/ipv4/tcp_minisocks.c2
-rw-r--r--net/ipv4/tcp_output.c31
-rw-r--r--net/ipv4/tcp_probe.c1
-rw-r--r--net/ipv4/tcp_timer.c60
-rw-r--r--net/ipv4/tcp_westwood.c2
-rw-r--r--net/ipv4/tunnel4.c19
-rw-r--r--net/ipv4/udp.c4
-rw-r--r--net/ipv4/xfrm4_policy.c4
-rw-r--r--net/ipv4/xfrm4_tunnel.c4
-rw-r--r--net/ipv6/addrconf.c8
-rw-r--r--net/ipv6/addrlabel.c5
-rw-r--r--net/ipv6/af_inet6.c9
-rw-r--r--net/ipv6/datagram.c19
-rw-r--r--net/ipv6/exthdrs_core.c4
-rw-r--r--net/ipv6/fib6_rules.c3
-rw-r--r--net/ipv6/ip6_fib.c9
-rw-r--r--net/ipv6/ip6_output.c6
-rw-r--r--net/ipv6/ip6_tunnel.c157
-rw-r--r--net/ipv6/ip6mr.c1
-rw-r--r--net/ipv6/ipv6_sockglue.c23
-rw-r--r--net/ipv6/ndisc.c36
-rw-r--r--net/ipv6/netfilter/Kconfig4
-rw-r--r--net/ipv6/netfilter/Makefile5
-rw-r--r--net/ipv6/netfilter/ip6_tables.c98
-rw-r--r--net/ipv6/netfilter/ip6t_LOG.c157
-rw-r--r--net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c78
-rw-r--r--net/ipv6/netfilter/nf_conntrack_reasm.c16
-rw-r--r--net/ipv6/netfilter/nf_defrag_ipv6_hooks.c131
-rw-r--r--net/ipv6/protocol.c32
-rw-r--r--net/ipv6/raw.c12
-rw-r--r--net/ipv6/reassembly.c2
-rw-r--r--net/ipv6/route.c78
-rw-r--r--net/ipv6/sit.c165
-rw-r--r--net/ipv6/tcp_ipv6.c14
-rw-r--r--net/ipv6/tunnel6.c17
-rw-r--r--net/ipv6/udp.c16
-rw-r--r--net/ipv6/xfrm6_policy.c10
-rw-r--r--net/ipv6/xfrm6_tunnel.c8
-rw-r--r--net/ipx/Kconfig1
-rw-r--r--net/irda/af_irda.c380
-rw-r--r--net/irda/discovery.c2
-rw-r--r--net/irda/ircomm/ircomm_tty.c4
-rw-r--r--net/irda/iriap.c3
-rw-r--r--net/irda/irlan/irlan_eth.c32
-rw-r--r--net/irda/irlan/irlan_event.c2
-rw-r--r--net/irda/irlmp.c2
-rw-r--r--net/irda/irlmp_frame.c2
-rw-r--r--net/irda/irnet/irnet.h2
-rw-r--r--net/irda/irnet/irnet_irda.c22
-rw-r--r--net/irda/irnet/irnet_ppp.c69
-rw-r--r--net/irda/irnet/irnet_ppp.h3
-rw-r--r--net/irda/parameters.c4
-rw-r--r--net/key/af_key.c4
-rw-r--r--net/l2tp/l2tp_eth.c1
-rw-r--r--net/l2tp/l2tp_ip.c4
-rw-r--r--net/l2tp/l2tp_ppp.c2
-rw-r--r--net/mac80211/aes_ccm.c6
-rw-r--r--net/mac80211/aes_cmac.c6
-rw-r--r--net/mac80211/agg-rx.c30
-rw-r--r--net/mac80211/agg-tx.c16
-rw-r--r--net/mac80211/cfg.c244
-rw-r--r--net/mac80211/chan.c2
-rw-r--r--net/mac80211/debugfs.c28
-rw-r--r--net/mac80211/debugfs_key.c57
-rw-r--r--net/mac80211/debugfs_netdev.c4
-rw-r--r--net/mac80211/debugfs_sta.c7
-rw-r--r--net/mac80211/driver-ops.h14
-rw-r--r--net/mac80211/driver-trace.h42
-rw-r--r--net/mac80211/ht.c47
-rw-r--r--net/mac80211/ibss.c77
-rw-r--r--net/mac80211/ieee80211_i.h133
-rw-r--r--net/mac80211/iface.c460
-rw-r--r--net/mac80211/key.c168
-rw-r--r--net/mac80211/key.h13
-rw-r--r--net/mac80211/main.c194
-rw-r--r--net/mac80211/mesh_plink.c17
-rw-r--r--net/mac80211/mlme.c173
-rw-r--r--net/mac80211/offchannel.c26
-rw-r--r--net/mac80211/pm.c2
-rw-r--r--net/mac80211/rate.c12
-rw-r--r--net/mac80211/rc80211_minstrel_debugfs.c1
-rw-r--r--net/mac80211/rc80211_minstrel_ht.c7
-rw-r--r--net/mac80211/rc80211_minstrel_ht_debugfs.c3
-rw-r--r--net/mac80211/rc80211_pid_debugfs.c3
-rw-r--r--net/mac80211/rx.c819
-rw-r--r--net/mac80211/scan.c179
-rw-r--r--net/mac80211/sta_info.c52
-rw-r--r--net/mac80211/sta_info.h24
-rw-r--r--net/mac80211/status.c18
-rw-r--r--net/mac80211/tx.c73
-rw-r--r--net/mac80211/util.c102
-rw-r--r--net/mac80211/wep.c10
-rw-r--r--net/mac80211/work.c39
-rw-r--r--net/mac80211/wpa.c34
-rw-r--r--net/netfilter/core.c8
-rw-r--r--net/netfilter/ipvs/Kconfig20
-rw-r--r--net/netfilter/ipvs/Makefile10
-rw-r--r--net/netfilter/ipvs/ip_vs_app.c6
-rw-r--r--net/netfilter/ipvs/ip_vs_conn.c286
-rw-r--r--net/netfilter/ipvs/ip_vs_core.c819
-rw-r--r--net/netfilter/ipvs/ip_vs_ctl.c392
-rw-r--r--net/netfilter/ipvs/ip_vs_ftp.c194
-rw-r--r--net/netfilter/ipvs/ip_vs_nfct.c292
-rw-r--r--net/netfilter/ipvs/ip_vs_pe.c147
-rw-r--r--net/netfilter/ipvs/ip_vs_pe_sip.c169
-rw-r--r--net/netfilter/ipvs/ip_vs_proto.c8
-rw-r--r--net/netfilter/ipvs/ip_vs_proto_ah_esp.c99
-rw-r--r--net/netfilter/ipvs/ip_vs_proto_sctp.c27
-rw-r--r--net/netfilter/ipvs/ip_vs_proto_tcp.c52
-rw-r--r--net/netfilter/ipvs/ip_vs_proto_udp.c51
-rw-r--r--net/netfilter/ipvs/ip_vs_sched.c47
-rw-r--r--net/netfilter/ipvs/ip_vs_sync.c46
-rw-r--r--net/netfilter/ipvs/ip_vs_xmit.c696
-rw-r--r--net/netfilter/nf_conntrack_core.c131
-rw-r--r--net/netfilter/nf_conntrack_ecache.c4
-rw-r--r--net/netfilter/nf_conntrack_expect.c68
-rw-r--r--net/netfilter/nf_conntrack_extend.c2
-rw-r--r--net/netfilter/nf_conntrack_netlink.c121
-rw-r--r--net/netfilter/nf_conntrack_proto.c4
-rw-r--r--net/netfilter/nf_conntrack_sip.c42
-rw-r--r--net/netfilter/nf_conntrack_standalone.c28
-rw-r--r--net/netfilter/nf_log.c2
-rw-r--r--net/netfilter/nf_queue.c2
-rw-r--r--net/netfilter/nf_tproxy_core.c35
-rw-r--r--net/netfilter/x_tables.c12
-rw-r--r--net/netfilter/xt_CT.c1
-rw-r--r--net/netfilter/xt_SECMARK.c35
-rw-r--r--net/netfilter/xt_TPROXY.c366
-rw-r--r--net/netfilter/xt_hashlimit.c15
-rw-r--r--net/netfilter/xt_ipvs.c1
-rw-r--r--net/netfilter/xt_recent.c1
-rw-r--r--net/netfilter/xt_socket.c167
-rw-r--r--net/netlink/genetlink.c14
-rw-r--r--net/nonet.c1
-rw-r--r--net/packet/af_packet.c4
-rw-r--r--net/phonet/Kconfig12
-rw-r--r--net/phonet/af_phonet.c17
-rw-r--r--net/phonet/datagram.c13
-rw-r--r--net/phonet/pep.c391
-rw-r--r--net/phonet/pn_dev.c5
-rw-r--r--net/phonet/socket.c289
-rw-r--r--net/rds/af_rds.c26
-rw-r--r--net/rds/bind.c82
-rw-r--r--net/rds/cong.c8
-rw-r--r--net/rds/connection.c159
-rw-r--r--net/rds/ib.c200
-rw-r--r--net/rds/ib.h104
-rw-r--r--net/rds/ib_cm.c184
-rw-r--r--net/rds/ib_rdma.c318
-rw-r--r--net/rds/ib_recv.c549
-rw-r--r--net/rds/ib_send.c682
-rw-r--r--net/rds/ib_stats.c2
-rw-r--r--net/rds/ib_sysctl.c19
-rw-r--r--net/rds/info.c12
-rw-r--r--net/rds/iw.c8
-rw-r--r--net/rds/iw.h15
-rw-r--r--net/rds/iw_cm.c14
-rw-r--r--net/rds/iw_rdma.c8
-rw-r--r--net/rds/iw_recv.c24
-rw-r--r--net/rds/iw_send.c93
-rw-r--r--net/rds/iw_sysctl.c6
-rw-r--r--net/rds/loop.c31
-rw-r--r--net/rds/message.c142
-rw-r--r--net/rds/page.c35
-rw-r--r--net/rds/rdma.c339
-rw-r--r--net/rds/rdma.h85
-rw-r--r--net/rds/rdma_transport.c44
-rw-r--r--net/rds/rdma_transport.h4
-rw-r--r--net/rds/rds.h192
-rw-r--r--net/rds/recv.c12
-rw-r--r--net/rds/send.c548
-rw-r--r--net/rds/stats.c6
-rw-r--r--net/rds/sysctl.c4
-rw-r--r--net/rds/tcp.c12
-rw-r--r--net/rds/tcp.h9
-rw-r--r--net/rds/tcp_connect.c2
-rw-r--r--net/rds/tcp_listen.c6
-rw-r--r--net/rds/tcp_recv.c17
-rw-r--r--net/rds/tcp_send.c68
-rw-r--r--net/rds/threads.c69
-rw-r--r--net/rds/transport.c19
-rw-r--r--net/rds/xlist.h80
-rw-r--r--net/rfkill/core.c1
-rw-r--r--net/rfkill/input.c2
-rw-r--r--net/rose/rose_link.c4
-rw-r--r--net/sched/Kconfig10
-rw-r--r--net/sched/Makefile1
-rw-r--r--net/sched/act_csum.c595
-rw-r--r--net/sched/act_ipt.c14
-rw-r--r--net/sched/cls_cgroup.c2
-rw-r--r--net/sched/cls_flow.c74
-rw-r--r--net/sched/cls_u32.c2
-rw-r--r--net/sched/em_meta.c6
-rw-r--r--net/sched/sch_api.c44
-rw-r--r--net/sched/sch_atm.c5
-rw-r--r--net/sched/sch_cbq.c12
-rw-r--r--net/sched/sch_drr.c4
-rw-r--r--net/sched/sch_dsmark.c6
-rw-r--r--net/sched/sch_fifo.c3
-rw-r--r--net/sched/sch_generic.c24
-rw-r--r--net/sched/sch_hfsc.c8
-rw-r--r--net/sched/sch_htb.c12
-rw-r--r--net/sched/sch_mq.c2
-rw-r--r--net/sched/sch_multiq.c3
-rw-r--r--net/sched/sch_netem.c3
-rw-r--r--net/sched/sch_prio.c2
-rw-r--r--net/sched/sch_sfq.c33
-rw-r--r--net/sched/sch_teql.c8
-rw-r--r--net/sctp/associola.c2
-rw-r--r--net/sctp/auth.c8
-rw-r--r--net/sctp/chunk.c2
-rw-r--r--net/sctp/inqueue.c2
-rw-r--r--net/sctp/ipv6.c4
-rw-r--r--net/sctp/objcnt.c5
-rw-r--r--net/sctp/output.c2
-rw-r--r--net/sctp/outqueue.c34
-rw-r--r--net/sctp/probe.c5
-rw-r--r--net/sctp/protocol.c19
-rw-r--r--net/sctp/sm_make_chunk.c2
-rw-r--r--net/sctp/sm_sideeffect.c21
-rw-r--r--net/sctp/sm_statefuns.c20
-rw-r--r--net/sctp/sm_statetable.c42
-rw-r--r--net/sctp/socket.c98
-rw-r--r--net/sctp/transport.c9
-rw-r--r--net/socket.c38
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c2
-rw-r--r--net/sunrpc/auth_gss/gss_generic_token.c44
-rw-r--r--net/sunrpc/auth_gss/gss_krb5_seqnum.c2
-rw-r--r--net/sunrpc/auth_gss/gss_mech_switch.c2
-rw-r--r--net/sunrpc/cache.c17
-rw-r--r--net/sunrpc/rpc_pipe.c26
-rw-r--r--net/sunrpc/sched.c2
-rw-r--r--net/tipc/addr.c7
-rw-r--r--net/tipc/bcast.c51
-rw-r--r--net/tipc/bcast.h3
-rw-r--r--net/tipc/bearer.c42
-rw-r--r--net/tipc/cluster.c21
-rw-r--r--net/tipc/cluster.h2
-rw-r--r--net/tipc/config.c148
-rw-r--r--net/tipc/config.h6
-rw-r--r--net/tipc/core.c38
-rw-r--r--net/tipc/core.h9
-rw-r--r--net/tipc/dbg.c17
-rw-r--r--net/tipc/dbg.h3
-rw-r--r--net/tipc/discover.c44
-rw-r--r--net/tipc/discover.h5
-rw-r--r--net/tipc/eth_media.c48
-rw-r--r--net/tipc/link.c188
-rw-r--r--net/tipc/link.h24
-rw-r--r--net/tipc/msg.c2
-rw-r--r--net/tipc/msg.h6
-rw-r--r--net/tipc/name_distr.c2
-rw-r--r--net/tipc/name_table.c67
-rw-r--r--net/tipc/net.c10
-rw-r--r--net/tipc/node.c73
-rw-r--r--net/tipc/node.h3
-rw-r--r--net/tipc/port.c295
-rw-r--r--net/tipc/port.h4
-rw-r--r--net/tipc/ref.c17
-rw-r--r--net/tipc/ref.h1
-rw-r--r--net/tipc/socket.c83
-rw-r--r--net/tipc/subscr.c77
-rw-r--r--net/tipc/subscr.h2
-rw-r--r--net/tipc/zone.c11
-rw-r--r--net/tipc/zone.h1
-rw-r--r--net/unix/af_unix.c10
-rw-r--r--net/wireless/core.c66
-rw-r--r--net/wireless/core.h34
-rw-r--r--net/wireless/debugfs.c2
-rw-r--r--net/wireless/ibss.c21
-rw-r--r--net/wireless/mlme.c225
-rw-r--r--net/wireless/nl80211.c2189
-rw-r--r--net/wireless/nl80211.h14
-rw-r--r--net/wireless/radiotap.c61
-rw-r--r--net/wireless/reg.c22
-rw-r--r--net/wireless/scan.c12
-rw-r--r--net/wireless/sme.c11
-rw-r--r--net/wireless/sysfs.c18
-rw-r--r--net/wireless/util.c40
-rw-r--r--net/wireless/wext-compat.c42
-rw-r--r--net/wireless/wext-core.c2
-rw-r--r--net/wireless/wext-sme.c2
-rw-r--r--net/x25/Kconfig1
-rw-r--r--net/x25/af_x25.c34
-rw-r--r--net/xfrm/xfrm_policy.c7
-rw-r--r--samples/kfifo/bytestream-example.c1
-rw-r--r--samples/kfifo/dma-example.c17
-rw-r--r--samples/kfifo/inttype-example.c1
-rw-r--r--samples/kfifo/record-example.c1
-rw-r--r--samples/tracepoints/tracepoint-sample.c1
-rw-r--r--scripts/Makefile1
-rw-r--r--scripts/Makefile.build13
-rw-r--r--scripts/Makefile.lib11
-rw-r--r--scripts/basic/Makefile2
-rw-r--r--scripts/basic/hash.c64
-rw-r--r--scripts/gcc-goto.sh5
-rw-r--r--scripts/kconfig/conf.c2
-rw-r--r--scripts/kconfig/expr.h1
-rw-r--r--scripts/kconfig/menu.c7
-rw-r--r--scripts/kconfig/symbol.c2
-rw-r--r--scripts/recordmcount.c363
-rw-r--r--scripts/recordmcount.h366
-rwxr-xr-xscripts/recordmcount.pl2
-rw-r--r--security/apparmor/.gitignore1
-rw-r--r--security/apparmor/apparmorfs.c13
-rw-r--r--security/capability.c17
-rw-r--r--security/commoncap.c5
-rw-r--r--security/inode.c1
-rw-r--r--security/security.c35
-rw-r--r--security/selinux/Makefile21
-rw-r--r--security/selinux/exports.c49
-rw-r--r--security/selinux/hooks.c28
-rw-r--r--security/selinux/include/classmap.h2
-rw-r--r--security/selinux/include/security.h23
-rw-r--r--security/selinux/selinuxfs.c195
-rw-r--r--security/selinux/ss/Makefile9
-rw-r--r--security/selinux/ss/avtab.c46
-rw-r--r--security/selinux/ss/avtab.h3
-rw-r--r--security/selinux/ss/conditional.c123
-rw-r--r--security/selinux/ss/conditional.h2
-rw-r--r--security/selinux/ss/ebitmap.c81
-rw-r--r--security/selinux/ss/ebitmap.h1
-rw-r--r--security/selinux/ss/policydb.c861
-rw-r--r--security/selinux/ss/policydb.h20
-rw-r--r--security/selinux/ss/services.c63
-rw-r--r--security/selinux/ss/status.c126
-rw-r--r--security/smack/smack_lsm.c8
-rw-r--r--security/smack/smackfs.c5
-rw-r--r--security/tomoyo/common.c17
-rw-r--r--sound/core/control.c5
-rw-r--r--sound/core/init.c11
-rw-r--r--sound/core/rawmidi.c4
-rw-r--r--sound/core/seq/oss/seq_oss.c1
-rw-r--r--sound/core/sound.c3
-rw-r--r--sound/i2c/other/ak4xxx-adda.c2
-rw-r--r--sound/oss/msnd_pinnacle.c1
-rw-r--r--sound/oss/soundcard.c4
-rw-r--r--sound/pci/hda/patch_sigmatel.c2
-rw-r--r--sound/pcmcia/pdaudiocf/pdaudiocf.c16
-rw-r--r--sound/pcmcia/pdaudiocf/pdaudiocf.h1
-rw-r--r--sound/pcmcia/vx/vxpocket.c15
-rw-r--r--sound/pcmcia/vx/vxpocket.h1
-rw-r--r--sound/soc/soc-core.c1
-rw-r--r--sound/soc/soc-dapm.c1
-rw-r--r--sound/sound_core.c1
-rw-r--r--tools/perf/Documentation/perf-annotate.txt11
-rw-r--r--tools/perf/Documentation/perf-report.txt7
-rw-r--r--tools/perf/Makefile32
-rw-r--r--tools/perf/builtin-annotate.c26
-rw-r--r--tools/perf/builtin-report.c14
-rw-r--r--tools/perf/feature-tests.mak11
-rw-r--r--tools/perf/perf.h12
-rw-r--r--tools/perf/scripts/python/bin/netdev-times-record8
-rw-r--r--tools/perf/scripts/python/bin/netdev-times-report5
-rw-r--r--tools/perf/scripts/python/netdev-times.py464
-rw-r--r--tools/perf/util/cache.h2
-rw-r--r--tools/perf/util/callchain.c98
-rw-r--r--tools/perf/util/callchain.h27
-rw-r--r--tools/perf/util/hist.c4
-rw-r--r--tools/perf/util/path.c3
-rw-r--r--tools/perf/util/sort.h2
-rw-r--r--tools/perf/util/symbol.c14
-rw-r--r--tools/perf/util/symbol.h1
-rw-r--r--tools/perf/util/trace-event-scripting.c4
-rw-r--r--tools/perf/util/ui/browser.c117
-rw-r--r--tools/perf/util/ui/browser.h9
-rw-r--r--tools/perf/util/ui/browsers/annotate.c38
-rw-r--r--tools/perf/util/ui/browsers/hists.c327
-rw-r--r--tools/perf/util/ui/browsers/map.c32
-rw-r--r--tools/perf/util/ui/util.c4
-rw-r--r--tools/perf/util/util.h13
-rw-r--r--virt/kvm/kvm_main.c3
4957 files changed, 298960 insertions, 178594 deletions
diff --git a/CREDITS b/CREDITS
index 72b487869788..41d8e63d5165 100644
--- a/CREDITS
+++ b/CREDITS
@@ -3554,12 +3554,12 @@ E: cvance@nai.com
D: portions of the Linux Security Module (LSM) framework and security modules
N: Petr Vandrovec
-E: vandrove@vc.cvut.cz
+E: petr@vandrovec.name
D: Small contributions to ncpfs
D: Matrox framebuffer driver
-S: Chudenicka 8
-S: 10200 Prague 10, Hostivar
-S: Czech Republic
+S: 21513 Conradia Ct
+S: Cupertino, CA 95014
+S: USA
N: Thibaut Varene
E: T-Bone@parisc-linux.org
diff --git a/Documentation/ABI/testing/sysfs-ata b/Documentation/ABI/testing/sysfs-ata
new file mode 100644
index 000000000000..0a932155cbba
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-ata
@@ -0,0 +1,99 @@
+What: /sys/class/ata_...
+Date: August 2008
+Contact: Gwendal Grignou<gwendal@google.com>
+Description:
+
+Provide a place in sysfs for storing the ATA topology of the system. This allows
+retrieving various information about ATA objects.
+
+Files under /sys/class/ata_port
+-------------------------------
+
+ For each port, a directory ataX is created where X is the ata_port_id of
+ the port. The device parent is the ata host device.
+
+idle_irq (read)
+
+ Number of IRQ received by the port while idle [some ata HBA only].
+
+nr_pmp_links (read)
+
+ If a SATA Port Multiplier (PM) is connected, number of link behind it.
+
+Files under /sys/class/ata_link
+-------------------------------
+
+ Behind each port, there is a ata_link. If there is a SATA PM in the
+ topology, 15 ata_link objects are created.
+
+ If a link is behind a port, the directory name is linkX, where X is
+ ata_port_id of the port.
+ If a link is behind a PM, its name is linkX.Y where X is ata_port_id
+ of the parent port and Y the PM port.
+
+hw_sata_spd_limit
+
+ Maximum speed supported by the connected SATA device.
+
+sata_spd_limit
+
+ Maximum speed imposed by libata.
+
+sata_spd
+
+ Current speed of the link [1.5, 3Gps,...].
+
+Files under /sys/class/ata_device
+---------------------------------
+
+ Behind each link, up to two ata device are created.
+ The name of the directory is devX[.Y].Z where:
+ - X is ata_port_id of the port where the device is connected,
+ - Y the port of the PM if any, and
+ - Z the device id: for PATA, there is usually 2 devices [0,1],
+ only 1 for SATA.
+
+class
+ Device class. Can be "ata" for disk, "atapi" for packet device,
+ "pmp" for PM, or "none" if no device was found behind the link.
+
+dma_mode
+
+ Transfer modes supported by the device when in DMA mode.
+ Mostly used by PATA device.
+
+pio_mode
+
+ Transfer modes supported by the device when in PIO mode.
+ Mostly used by PATA device.
+
+xfer_mode
+
+ Current transfer mode.
+
+id
+
+ Cached result of IDENTIFY command, as described in ATA8 7.16 and 7.17.
+ Only valid if the device is not a PM.
+
+gscr
+
+ Cached result of the dump of PM GSCR register.
+ Valid registers are:
+ 0: SATA_PMP_GSCR_PROD_ID,
+ 1: SATA_PMP_GSCR_REV,
+ 2: SATA_PMP_GSCR_PORT_INFO,
+ 32: SATA_PMP_GSCR_ERROR,
+ 33: SATA_PMP_GSCR_ERROR_EN,
+ 64: SATA_PMP_GSCR_FEAT,
+ 96: SATA_PMP_GSCR_FEAT_EN,
+ 130: SATA_PMP_GSCR_SII_GPIO
+ Only valid if the device is a PM.
+
+spdn_cnt
+
+ Number of time libata decided to lower the speed of link due to errors.
+
+ering
+
+ Formatted output of the error ring of the device.
diff --git a/Documentation/ABI/testing/sysfs-devices-power b/Documentation/ABI/testing/sysfs-devices-power
index 6123c523bfd7..7628cd1bc36a 100644
--- a/Documentation/ABI/testing/sysfs-devices-power
+++ b/Documentation/ABI/testing/sysfs-devices-power
@@ -77,3 +77,91 @@ Description:
devices this attribute is set to "enabled" by bus type code or
device drivers and in that cases it should be safe to leave the
default value.
+
+What: /sys/devices/.../power/wakeup_count
+Date: September 2010
+Contact: Rafael J. Wysocki <rjw@sisk.pl>
+Description:
+ The /sys/devices/.../wakeup_count attribute contains the number
+ of signaled wakeup events associated with the device. This
+ attribute is read-only. If the device is not enabled to wake up
+ the system from sleep states, this attribute is empty.
+
+What: /sys/devices/.../power/wakeup_active_count
+Date: September 2010
+Contact: Rafael J. Wysocki <rjw@sisk.pl>
+Description:
+ The /sys/devices/.../wakeup_active_count attribute contains the
+ number of times the processing of wakeup events associated with
+ the device was completed (at the kernel level). This attribute
+ is read-only. If the device is not enabled to wake up the
+ system from sleep states, this attribute is empty.
+
+What: /sys/devices/.../power/wakeup_hit_count
+Date: September 2010
+Contact: Rafael J. Wysocki <rjw@sisk.pl>
+Description:
+ The /sys/devices/.../wakeup_hit_count attribute contains the
+ number of times the processing of a wakeup event associated with
+ the device might prevent the system from entering a sleep state.
+ This attribute is read-only. If the device is not enabled to
+ wake up the system from sleep states, this attribute is empty.
+
+What: /sys/devices/.../power/wakeup_active
+Date: September 2010
+Contact: Rafael J. Wysocki <rjw@sisk.pl>
+Description:
+ The /sys/devices/.../wakeup_active attribute contains either 1,
+ or 0, depending on whether or not a wakeup event associated with
+ the device is being processed (1). This attribute is read-only.
+ If the device is not enabled to wake up the system from sleep
+ states, this attribute is empty.
+
+What: /sys/devices/.../power/wakeup_total_time_ms
+Date: September 2010
+Contact: Rafael J. Wysocki <rjw@sisk.pl>
+Description:
+ The /sys/devices/.../wakeup_total_time_ms attribute contains
+ the total time of processing wakeup events associated with the
+ device, in milliseconds. This attribute is read-only. If the
+ device is not enabled to wake up the system from sleep states,
+ this attribute is empty.
+
+What: /sys/devices/.../power/wakeup_max_time_ms
+Date: September 2010
+Contact: Rafael J. Wysocki <rjw@sisk.pl>
+Description:
+ The /sys/devices/.../wakeup_max_time_ms attribute contains
+ the maximum time of processing a single wakeup event associated
+ with the device, in milliseconds. This attribute is read-only.
+ If the device is not enabled to wake up the system from sleep
+ states, this attribute is empty.
+
+What: /sys/devices/.../power/wakeup_last_time_ms
+Date: September 2010
+Contact: Rafael J. Wysocki <rjw@sisk.pl>
+Description:
+ The /sys/devices/.../wakeup_last_time_ms attribute contains
+ the value of the monotonic clock corresponding to the time of
+ signaling the last wakeup event associated with the device, in
+ milliseconds. This attribute is read-only. If the device is
+ not enabled to wake up the system from sleep states, this
+ attribute is empty.
+
+What: /sys/devices/.../power/autosuspend_delay_ms
+Date: September 2010
+Contact: Alan Stern <stern@rowland.harvard.edu>
+Description:
+ The /sys/devices/.../power/autosuspend_delay_ms attribute
+ contains the autosuspend delay value (in milliseconds). Some
+ drivers do not want their device to suspend as soon as it
+ becomes idle at run time; they want the device to remain
+ inactive for a certain minimum period of time first. That
+ period is called the autosuspend delay. Negative values will
+ prevent the device from being suspended at run time (similar
+ to writing "on" to the power/control attribute). Values >=
+ 1000 will cause the autosuspend timer expiration to be rounded
+ up to the nearest second.
+
+ Not all drivers support this attribute. If it isn't supported,
+ attempts to read or write it will yield I/O errors.
diff --git a/Documentation/ABI/testing/sysfs-module b/Documentation/ABI/testing/sysfs-module
new file mode 100644
index 000000000000..cfcec3bffc0a
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-module
@@ -0,0 +1,12 @@
+What: /sys/module/pch_phub/drivers/.../pch_mac
+Date: August 2010
+KernelVersion: 2.6.35
+Contact: masa-korg@dsn.okisemi.com
+Description: Write/read GbE MAC address.
+
+What: /sys/module/pch_phub/drivers/.../pch_firmware
+Date: August 2010
+KernelVersion: 2.6.35
+Contact: masa-korg@dsn.okisemi.com
+Description: Write/read Option ROM data.
+
diff --git a/Documentation/ABI/testing/sysfs-power b/Documentation/ABI/testing/sysfs-power
index 2875f1f74a07..194ca446ac28 100644
--- a/Documentation/ABI/testing/sysfs-power
+++ b/Documentation/ABI/testing/sysfs-power
@@ -99,9 +99,38 @@ Description:
dmesg -s 1000000 | grep 'hash matches'
+ If you do not get any matches (or they appear to be false
+ positives), it is possible that the last PM event point
+ referred to a device created by a loadable kernel module. In
+ this case cat /sys/power/pm_trace_dev_match (see below) after
+ your system is started up and the kernel modules are loaded.
+
CAUTION: Using it will cause your machine's real-time (CMOS)
clock to be set to a random invalid time after a resume.
+What; /sys/power/pm_trace_dev_match
+Date: October 2010
+Contact: James Hogan <james@albanarts.com>
+Description:
+ The /sys/power/pm_trace_dev_match file contains the name of the
+ device associated with the last PM event point saved in the RTC
+ across reboots when pm_trace has been used. More precisely it
+ contains the list of current devices (including those
+ registered by loadable kernel modules since boot) which match
+ the device hash in the RTC at boot, with a newline after each
+ one.
+
+ The advantage of this file over the hash matches printed to the
+ kernel log (see /sys/power/pm_trace), is that it includes
+ devices created after boot by loadable kernel modules.
+
+ Due to the small hash size necessary to fit in the RTC, it is
+ possible that more than one device matches the hash, in which
+ case further investigation is required to determine which
+ device is causing the problem. Note that genuine RTC clock
+ values (such as when pm_trace has not been used), can still
+ match a device and output it's name here.
+
What: /sys/power/pm_async
Date: January 2009
Contact: Rafael J. Wysocki <rjw@sisk.pl>
diff --git a/Documentation/DocBook/80211.tmpl b/Documentation/DocBook/80211.tmpl
new file mode 100644
index 000000000000..19a1210c2530
--- /dev/null
+++ b/Documentation/DocBook/80211.tmpl
@@ -0,0 +1,495 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE set PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
+<set>
+ <setinfo>
+ <title>The 802.11 subsystems &ndash; for kernel developers</title>
+ <subtitle>
+ Explaining wireless 802.11 networking in the Linux kernel
+ </subtitle>
+
+ <copyright>
+ <year>2007-2009</year>
+ <holder>Johannes Berg</holder>
+ </copyright>
+
+ <authorgroup>
+ <author>
+ <firstname>Johannes</firstname>
+ <surname>Berg</surname>
+ <affiliation>
+ <address><email>johannes@sipsolutions.net</email></address>
+ </affiliation>
+ </author>
+ </authorgroup>
+
+ <legalnotice>
+ <para>
+ This documentation is free software; you can redistribute
+ it and/or modify it under the terms of the GNU General Public
+ License version 2 as published by the Free Software Foundation.
+ </para>
+ <para>
+ This documentation is distributed in the hope that it will be
+ useful, but WITHOUT ANY WARRANTY; without even the implied
+ warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU General Public License for more details.
+ </para>
+ <para>
+ You should have received a copy of the GNU General Public
+ License along with this documentation; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ MA 02111-1307 USA
+ </para>
+ <para>
+ For more details see the file COPYING in the source
+ distribution of Linux.
+ </para>
+ </legalnotice>
+
+ <abstract>
+ <para>
+ These books attempt to give a description of the
+ various subsystems that play a role in 802.11 wireless
+ networking in Linux. Since these books are for kernel
+ developers they attempts to document the structures
+ and functions used in the kernel as well as giving a
+ higher-level overview.
+ </para>
+ <para>
+ The reader is expected to be familiar with the 802.11
+ standard as published by the IEEE in 802.11-2007 (or
+ possibly later versions). References to this standard
+ will be given as "802.11-2007 8.1.5".
+ </para>
+ </abstract>
+ </setinfo>
+ <book id="cfg80211-developers-guide">
+ <bookinfo>
+ <title>The cfg80211 subsystem</title>
+
+ <abstract>
+!Pinclude/net/cfg80211.h Introduction
+ </abstract>
+ </bookinfo>
+ <chapter>
+ <title>Device registration</title>
+!Pinclude/net/cfg80211.h Device registration
+!Finclude/net/cfg80211.h ieee80211_band
+!Finclude/net/cfg80211.h ieee80211_channel_flags
+!Finclude/net/cfg80211.h ieee80211_channel
+!Finclude/net/cfg80211.h ieee80211_rate_flags
+!Finclude/net/cfg80211.h ieee80211_rate
+!Finclude/net/cfg80211.h ieee80211_sta_ht_cap
+!Finclude/net/cfg80211.h ieee80211_supported_band
+!Finclude/net/cfg80211.h cfg80211_signal_type
+!Finclude/net/cfg80211.h wiphy_params_flags
+!Finclude/net/cfg80211.h wiphy_flags
+!Finclude/net/cfg80211.h wiphy
+!Finclude/net/cfg80211.h wireless_dev
+!Finclude/net/cfg80211.h wiphy_new
+!Finclude/net/cfg80211.h wiphy_register
+!Finclude/net/cfg80211.h wiphy_unregister
+!Finclude/net/cfg80211.h wiphy_free
+
+!Finclude/net/cfg80211.h wiphy_name
+!Finclude/net/cfg80211.h wiphy_dev
+!Finclude/net/cfg80211.h wiphy_priv
+!Finclude/net/cfg80211.h priv_to_wiphy
+!Finclude/net/cfg80211.h set_wiphy_dev
+!Finclude/net/cfg80211.h wdev_priv
+ </chapter>
+ <chapter>
+ <title>Actions and configuration</title>
+!Pinclude/net/cfg80211.h Actions and configuration
+!Finclude/net/cfg80211.h cfg80211_ops
+!Finclude/net/cfg80211.h vif_params
+!Finclude/net/cfg80211.h key_params
+!Finclude/net/cfg80211.h survey_info_flags
+!Finclude/net/cfg80211.h survey_info
+!Finclude/net/cfg80211.h beacon_parameters
+!Finclude/net/cfg80211.h plink_actions
+!Finclude/net/cfg80211.h station_parameters
+!Finclude/net/cfg80211.h station_info_flags
+!Finclude/net/cfg80211.h rate_info_flags
+!Finclude/net/cfg80211.h rate_info
+!Finclude/net/cfg80211.h station_info
+!Finclude/net/cfg80211.h monitor_flags
+!Finclude/net/cfg80211.h mpath_info_flags
+!Finclude/net/cfg80211.h mpath_info
+!Finclude/net/cfg80211.h bss_parameters
+!Finclude/net/cfg80211.h ieee80211_txq_params
+!Finclude/net/cfg80211.h cfg80211_crypto_settings
+!Finclude/net/cfg80211.h cfg80211_auth_request
+!Finclude/net/cfg80211.h cfg80211_assoc_request
+!Finclude/net/cfg80211.h cfg80211_deauth_request
+!Finclude/net/cfg80211.h cfg80211_disassoc_request
+!Finclude/net/cfg80211.h cfg80211_ibss_params
+!Finclude/net/cfg80211.h cfg80211_connect_params
+!Finclude/net/cfg80211.h cfg80211_pmksa
+!Finclude/net/cfg80211.h cfg80211_send_rx_auth
+!Finclude/net/cfg80211.h cfg80211_send_auth_timeout
+!Finclude/net/cfg80211.h __cfg80211_auth_canceled
+!Finclude/net/cfg80211.h cfg80211_send_rx_assoc
+!Finclude/net/cfg80211.h cfg80211_send_assoc_timeout
+!Finclude/net/cfg80211.h cfg80211_send_deauth
+!Finclude/net/cfg80211.h __cfg80211_send_deauth
+!Finclude/net/cfg80211.h cfg80211_send_disassoc
+!Finclude/net/cfg80211.h __cfg80211_send_disassoc
+!Finclude/net/cfg80211.h cfg80211_ibss_joined
+!Finclude/net/cfg80211.h cfg80211_connect_result
+!Finclude/net/cfg80211.h cfg80211_roamed
+!Finclude/net/cfg80211.h cfg80211_disconnected
+!Finclude/net/cfg80211.h cfg80211_ready_on_channel
+!Finclude/net/cfg80211.h cfg80211_remain_on_channel_expired
+!Finclude/net/cfg80211.h cfg80211_new_sta
+!Finclude/net/cfg80211.h cfg80211_rx_mgmt
+!Finclude/net/cfg80211.h cfg80211_mgmt_tx_status
+!Finclude/net/cfg80211.h cfg80211_cqm_rssi_notify
+!Finclude/net/cfg80211.h cfg80211_michael_mic_failure
+ </chapter>
+ <chapter>
+ <title>Scanning and BSS list handling</title>
+!Pinclude/net/cfg80211.h Scanning and BSS list handling
+!Finclude/net/cfg80211.h cfg80211_ssid
+!Finclude/net/cfg80211.h cfg80211_scan_request
+!Finclude/net/cfg80211.h cfg80211_scan_done
+!Finclude/net/cfg80211.h cfg80211_bss
+!Finclude/net/cfg80211.h cfg80211_inform_bss_frame
+!Finclude/net/cfg80211.h cfg80211_inform_bss
+!Finclude/net/cfg80211.h cfg80211_unlink_bss
+!Finclude/net/cfg80211.h cfg80211_find_ie
+!Finclude/net/cfg80211.h ieee80211_bss_get_ie
+ </chapter>
+ <chapter>
+ <title>Utility functions</title>
+!Pinclude/net/cfg80211.h Utility functions
+!Finclude/net/cfg80211.h ieee80211_channel_to_frequency
+!Finclude/net/cfg80211.h ieee80211_frequency_to_channel
+!Finclude/net/cfg80211.h ieee80211_get_channel
+!Finclude/net/cfg80211.h ieee80211_get_response_rate
+!Finclude/net/cfg80211.h ieee80211_hdrlen
+!Finclude/net/cfg80211.h ieee80211_get_hdrlen_from_skb
+!Finclude/net/cfg80211.h ieee80211_radiotap_iterator
+ </chapter>
+ <chapter>
+ <title>Data path helpers</title>
+!Pinclude/net/cfg80211.h Data path helpers
+!Finclude/net/cfg80211.h ieee80211_data_to_8023
+!Finclude/net/cfg80211.h ieee80211_data_from_8023
+!Finclude/net/cfg80211.h ieee80211_amsdu_to_8023s
+!Finclude/net/cfg80211.h cfg80211_classify8021d
+ </chapter>
+ <chapter>
+ <title>Regulatory enforcement infrastructure</title>
+!Pinclude/net/cfg80211.h Regulatory enforcement infrastructure
+!Finclude/net/cfg80211.h regulatory_hint
+!Finclude/net/cfg80211.h wiphy_apply_custom_regulatory
+!Finclude/net/cfg80211.h freq_reg_info
+ </chapter>
+ <chapter>
+ <title>RFkill integration</title>
+!Pinclude/net/cfg80211.h RFkill integration
+!Finclude/net/cfg80211.h wiphy_rfkill_set_hw_state
+!Finclude/net/cfg80211.h wiphy_rfkill_start_polling
+!Finclude/net/cfg80211.h wiphy_rfkill_stop_polling
+ </chapter>
+ <chapter>
+ <title>Test mode</title>
+!Pinclude/net/cfg80211.h Test mode
+!Finclude/net/cfg80211.h cfg80211_testmode_alloc_reply_skb
+!Finclude/net/cfg80211.h cfg80211_testmode_reply
+!Finclude/net/cfg80211.h cfg80211_testmode_alloc_event_skb
+!Finclude/net/cfg80211.h cfg80211_testmode_event
+ </chapter>
+ </book>
+ <book id="mac80211-developers-guide">
+ <bookinfo>
+ <title>The mac80211 subsystem</title>
+ <abstract>
+!Pinclude/net/mac80211.h Introduction
+!Pinclude/net/mac80211.h Warning
+ </abstract>
+ </bookinfo>
+
+ <toc></toc>
+
+ <!--
+ Generally, this document shall be ordered by increasing complexity.
+ It is important to note that readers should be able to read only
+ the first few sections to get a working driver and only advanced
+ usage should require reading the full document.
+ -->
+
+ <part>
+ <title>The basic mac80211 driver interface</title>
+ <partintro>
+ <para>
+ You should read and understand the information contained
+ within this part of the book while implementing a driver.
+ In some chapters, advanced usage is noted, that may be
+ skipped at first.
+ </para>
+ <para>
+ This part of the book only covers station and monitor mode
+ functionality, additional information required to implement
+ the other modes is covered in the second part of the book.
+ </para>
+ </partintro>
+
+ <chapter id="basics">
+ <title>Basic hardware handling</title>
+ <para>TBD</para>
+ <para>
+ This chapter shall contain information on getting a hw
+ struct allocated and registered with mac80211.
+ </para>
+ <para>
+ Since it is required to allocate rates/modes before registering
+ a hw struct, this chapter shall also contain information on setting
+ up the rate/mode structs.
+ </para>
+ <para>
+ Additionally, some discussion about the callbacks and
+ the general programming model should be in here, including
+ the definition of ieee80211_ops which will be referred to
+ a lot.
+ </para>
+ <para>
+ Finally, a discussion of hardware capabilities should be done
+ with references to other parts of the book.
+ </para>
+ <!-- intentionally multiple !F lines to get proper order -->
+!Finclude/net/mac80211.h ieee80211_hw
+!Finclude/net/mac80211.h ieee80211_hw_flags
+!Finclude/net/mac80211.h SET_IEEE80211_DEV
+!Finclude/net/mac80211.h SET_IEEE80211_PERM_ADDR
+!Finclude/net/mac80211.h ieee80211_ops
+!Finclude/net/mac80211.h ieee80211_alloc_hw
+!Finclude/net/mac80211.h ieee80211_register_hw
+!Finclude/net/mac80211.h ieee80211_get_tx_led_name
+!Finclude/net/mac80211.h ieee80211_get_rx_led_name
+!Finclude/net/mac80211.h ieee80211_get_assoc_led_name
+!Finclude/net/mac80211.h ieee80211_get_radio_led_name
+!Finclude/net/mac80211.h ieee80211_unregister_hw
+!Finclude/net/mac80211.h ieee80211_free_hw
+ </chapter>
+
+ <chapter id="phy-handling">
+ <title>PHY configuration</title>
+ <para>TBD</para>
+ <para>
+ This chapter should describe PHY handling including
+ start/stop callbacks and the various structures used.
+ </para>
+!Finclude/net/mac80211.h ieee80211_conf
+!Finclude/net/mac80211.h ieee80211_conf_flags
+ </chapter>
+
+ <chapter id="iface-handling">
+ <title>Virtual interfaces</title>
+ <para>TBD</para>
+ <para>
+ This chapter should describe virtual interface basics
+ that are relevant to the driver (VLANs, MGMT etc are not.)
+ It should explain the use of the add_iface/remove_iface
+ callbacks as well as the interface configuration callbacks.
+ </para>
+ <para>Things related to AP mode should be discussed there.</para>
+ <para>
+ Things related to supporting multiple interfaces should be
+ in the appropriate chapter, a BIG FAT note should be here about
+ this though and the recommendation to allow only a single
+ interface in STA mode at first!
+ </para>
+!Finclude/net/mac80211.h ieee80211_vif
+ </chapter>
+
+ <chapter id="rx-tx">
+ <title>Receive and transmit processing</title>
+ <sect1>
+ <title>what should be here</title>
+ <para>TBD</para>
+ <para>
+ This should describe the receive and transmit
+ paths in mac80211/the drivers as well as
+ transmit status handling.
+ </para>
+ </sect1>
+ <sect1>
+ <title>Frame format</title>
+!Pinclude/net/mac80211.h Frame format
+ </sect1>
+ <sect1>
+ <title>Packet alignment</title>
+!Pnet/mac80211/rx.c Packet alignment
+ </sect1>
+ <sect1>
+ <title>Calling into mac80211 from interrupts</title>
+!Pinclude/net/mac80211.h Calling mac80211 from interrupts
+ </sect1>
+ <sect1>
+ <title>functions/definitions</title>
+!Finclude/net/mac80211.h ieee80211_rx_status
+!Finclude/net/mac80211.h mac80211_rx_flags
+!Finclude/net/mac80211.h ieee80211_tx_info
+!Finclude/net/mac80211.h ieee80211_rx
+!Finclude/net/mac80211.h ieee80211_rx_irqsafe
+!Finclude/net/mac80211.h ieee80211_tx_status
+!Finclude/net/mac80211.h ieee80211_tx_status_irqsafe
+!Finclude/net/mac80211.h ieee80211_rts_get
+!Finclude/net/mac80211.h ieee80211_rts_duration
+!Finclude/net/mac80211.h ieee80211_ctstoself_get
+!Finclude/net/mac80211.h ieee80211_ctstoself_duration
+!Finclude/net/mac80211.h ieee80211_generic_frame_duration
+!Finclude/net/mac80211.h ieee80211_wake_queue
+!Finclude/net/mac80211.h ieee80211_stop_queue
+!Finclude/net/mac80211.h ieee80211_wake_queues
+!Finclude/net/mac80211.h ieee80211_stop_queues
+ </sect1>
+ </chapter>
+
+ <chapter id="filters">
+ <title>Frame filtering</title>
+!Pinclude/net/mac80211.h Frame filtering
+!Finclude/net/mac80211.h ieee80211_filter_flags
+ </chapter>
+ </part>
+
+ <part id="advanced">
+ <title>Advanced driver interface</title>
+ <partintro>
+ <para>
+ Information contained within this part of the book is
+ of interest only for advanced interaction of mac80211
+ with drivers to exploit more hardware capabilities and
+ improve performance.
+ </para>
+ </partintro>
+
+ <chapter id="hardware-crypto-offload">
+ <title>Hardware crypto acceleration</title>
+!Pinclude/net/mac80211.h Hardware crypto acceleration
+ <!-- intentionally multiple !F lines to get proper order -->
+!Finclude/net/mac80211.h set_key_cmd
+!Finclude/net/mac80211.h ieee80211_key_conf
+!Finclude/net/mac80211.h ieee80211_key_flags
+ </chapter>
+
+ <chapter id="powersave">
+ <title>Powersave support</title>
+!Pinclude/net/mac80211.h Powersave support
+ </chapter>
+
+ <chapter id="beacon-filter">
+ <title>Beacon filter support</title>
+!Pinclude/net/mac80211.h Beacon filter support
+!Finclude/net/mac80211.h ieee80211_beacon_loss
+ </chapter>
+
+ <chapter id="qos">
+ <title>Multiple queues and QoS support</title>
+ <para>TBD</para>
+!Finclude/net/mac80211.h ieee80211_tx_queue_params
+ </chapter>
+
+ <chapter id="AP">
+ <title>Access point mode support</title>
+ <para>TBD</para>
+ <para>Some parts of the if_conf should be discussed here instead</para>
+ <para>
+ Insert notes about VLAN interfaces with hw crypto here or
+ in the hw crypto chapter.
+ </para>
+!Finclude/net/mac80211.h ieee80211_get_buffered_bc
+!Finclude/net/mac80211.h ieee80211_beacon_get
+ </chapter>
+
+ <chapter id="multi-iface">
+ <title>Supporting multiple virtual interfaces</title>
+ <para>TBD</para>
+ <para>
+ Note: WDS with identical MAC address should almost always be OK
+ </para>
+ <para>
+ Insert notes about having multiple virtual interfaces with
+ different MAC addresses here, note which configurations are
+ supported by mac80211, add notes about supporting hw crypto
+ with it.
+ </para>
+ </chapter>
+
+ <chapter id="hardware-scan-offload">
+ <title>Hardware scan offload</title>
+ <para>TBD</para>
+!Finclude/net/mac80211.h ieee80211_scan_completed
+ </chapter>
+ </part>
+
+ <part id="rate-control">
+ <title>Rate control interface</title>
+ <partintro>
+ <para>TBD</para>
+ <para>
+ This part of the book describes the rate control algorithm
+ interface and how it relates to mac80211 and drivers.
+ </para>
+ </partintro>
+ <chapter id="dummy">
+ <title>dummy chapter</title>
+ <para>TBD</para>
+ </chapter>
+ </part>
+
+ <part id="internal">
+ <title>Internals</title>
+ <partintro>
+ <para>TBD</para>
+ <para>
+ This part of the book describes mac80211 internals.
+ </para>
+ </partintro>
+
+ <chapter id="key-handling">
+ <title>Key handling</title>
+ <sect1>
+ <title>Key handling basics</title>
+!Pnet/mac80211/key.c Key handling basics
+ </sect1>
+ <sect1>
+ <title>MORE TBD</title>
+ <para>TBD</para>
+ </sect1>
+ </chapter>
+
+ <chapter id="rx-processing">
+ <title>Receive processing</title>
+ <para>TBD</para>
+ </chapter>
+
+ <chapter id="tx-processing">
+ <title>Transmit processing</title>
+ <para>TBD</para>
+ </chapter>
+
+ <chapter id="sta-info">
+ <title>Station info handling</title>
+ <sect1>
+ <title>Programming information</title>
+!Fnet/mac80211/sta_info.h sta_info
+!Fnet/mac80211/sta_info.h ieee80211_sta_info_flags
+ </sect1>
+ <sect1>
+ <title>STA information lifetime rules</title>
+!Pnet/mac80211/sta_info.c STA information lifetime rules
+ </sect1>
+ </chapter>
+
+ <chapter id="synchronisation">
+ <title>Synchronisation</title>
+ <para>TBD</para>
+ <para>Locking, lots of RCU</para>
+ </chapter>
+ </part>
+ </book>
+</set>
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
index 34929f24c284..8b6e00a71034 100644
--- a/Documentation/DocBook/Makefile
+++ b/Documentation/DocBook/Makefile
@@ -12,7 +12,7 @@ DOCBOOKS := z8530book.xml mcabook.xml device-drivers.xml \
kernel-api.xml filesystems.xml lsm.xml usb.xml kgdb.xml \
gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \
genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \
- mac80211.xml debugobjects.xml sh.xml regulator.xml \
+ 80211.xml debugobjects.xml sh.xml regulator.xml \
alsa-driver-api.xml writing-an-alsa-driver.xml \
tracepoint.xml media.xml drm.xml
diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl
index 910c923a9b86..2861055afd7a 100644
--- a/Documentation/DocBook/drm.tmpl
+++ b/Documentation/DocBook/drm.tmpl
@@ -136,6 +136,7 @@
#ifdef CONFIG_COMPAT
.compat_ioctl = i915_compat_ioctl,
#endif
+ .llseek = noop_llseek,
},
.pci_driver = {
.name = DRIVER_NAME,
diff --git a/Documentation/DocBook/genericirq.tmpl b/Documentation/DocBook/genericirq.tmpl
index 1448b33fd222..fb10fd08c05c 100644
--- a/Documentation/DocBook/genericirq.tmpl
+++ b/Documentation/DocBook/genericirq.tmpl
@@ -28,7 +28,7 @@
</authorgroup>
<copyright>
- <year>2005-2006</year>
+ <year>2005-2010</year>
<holder>Thomas Gleixner</holder>
</copyright>
<copyright>
@@ -100,6 +100,10 @@
<listitem><para>Edge type</para></listitem>
<listitem><para>Simple type</para></listitem>
</itemizedlist>
+ During the implementation we identified another type:
+ <itemizedlist>
+ <listitem><para>Fast EOI type</para></listitem>
+ </itemizedlist>
In the SMP world of the __do_IRQ() super-handler another type
was identified:
<itemizedlist>
@@ -153,6 +157,7 @@
is still available. This leads to a kind of duality for the time
being. Over time the new model should be used in more and more
architectures, as it enables smaller and cleaner IRQ subsystems.
+ It's deprecated for three years now and about to be removed.
</para>
</chapter>
<chapter id="bugs">
@@ -217,6 +222,7 @@
<itemizedlist>
<listitem><para>handle_level_irq</para></listitem>
<listitem><para>handle_edge_irq</para></listitem>
+ <listitem><para>handle_fasteoi_irq</para></listitem>
<listitem><para>handle_simple_irq</para></listitem>
<listitem><para>handle_percpu_irq</para></listitem>
</itemizedlist>
@@ -233,33 +239,33 @@
are used by the default flow implementations.
The following helper functions are implemented (simplified excerpt):
<programlisting>
-default_enable(irq)
+default_enable(struct irq_data *data)
{
- desc->chip->unmask(irq);
+ desc->chip->irq_unmask(data);
}
-default_disable(irq)
+default_disable(struct irq_data *data)
{
- if (!delay_disable(irq))
- desc->chip->mask(irq);
+ if (!delay_disable(data))
+ desc->chip->irq_mask(data);
}
-default_ack(irq)
+default_ack(struct irq_data *data)
{
- chip->ack(irq);
+ chip->irq_ack(data);
}
-default_mask_ack(irq)
+default_mask_ack(struct irq_data *data)
{
- if (chip->mask_ack) {
- chip->mask_ack(irq);
+ if (chip->irq_mask_ack) {
+ chip->irq_mask_ack(data);
} else {
- chip->mask(irq);
- chip->ack(irq);
+ chip->irq_mask(data);
+ chip->irq_ack(data);
}
}
-noop(irq)
+noop(struct irq_data *data))
{
}
@@ -278,12 +284,27 @@ noop(irq)
<para>
The following control flow is implemented (simplified excerpt):
<programlisting>
-desc->chip->start();
+desc->chip->irq_mask();
handle_IRQ_event(desc->action);
-desc->chip->end();
+desc->chip->irq_unmask();
</programlisting>
</para>
- </sect3>
+ </sect3>
+ <sect3 id="Default_FASTEOI_IRQ_flow_handler">
+ <title>Default Fast EOI IRQ flow handler</title>
+ <para>
+ handle_fasteoi_irq provides a generic implementation
+ for interrupts, which only need an EOI at the end of
+ the handler
+ </para>
+ <para>
+ The following control flow is implemented (simplified excerpt):
+ <programlisting>
+handle_IRQ_event(desc->action);
+desc->chip->irq_eoi();
+ </programlisting>
+ </para>
+ </sect3>
<sect3 id="Default_Edge_IRQ_flow_handler">
<title>Default Edge IRQ flow handler</title>
<para>
@@ -294,20 +315,19 @@ desc->chip->end();
The following control flow is implemented (simplified excerpt):
<programlisting>
if (desc->status &amp; running) {
- desc->chip->hold();
+ desc->chip->irq_mask();
desc->status |= pending | masked;
return;
}
-desc->chip->start();
+desc->chip->irq_ack();
desc->status |= running;
do {
if (desc->status &amp; masked)
- desc->chip->enable();
+ desc->chip->irq_unmask();
desc->status &amp;= ~pending;
handle_IRQ_event(desc->action);
} while (status &amp; pending);
desc->status &amp;= ~running;
-desc->chip->end();
</programlisting>
</para>
</sect3>
@@ -342,9 +362,9 @@ handle_IRQ_event(desc->action);
<para>
The following control flow is implemented (simplified excerpt):
<programlisting>
-desc->chip->start();
handle_IRQ_event(desc->action);
-desc->chip->end();
+if (desc->chip->irq_eoi)
+ desc->chip->irq_eoi();
</programlisting>
</para>
</sect3>
@@ -375,8 +395,7 @@ desc->chip->end();
mechanism. (It's necessary to enable CONFIG_HARDIRQS_SW_RESEND when
you want to use the delayed interrupt disable feature and your
hardware is not capable of retriggering an interrupt.)
- The delayed interrupt disable can be runtime enabled, per interrupt,
- by setting the IRQ_DELAYED_DISABLE flag in the irq_desc status field.
+ The delayed interrupt disable is not configurable.
</para>
</sect2>
</sect1>
@@ -387,13 +406,13 @@ desc->chip->end();
contains all the direct chip relevant functions, which
can be utilized by the irq flow implementations.
<itemizedlist>
- <listitem><para>ack()</para></listitem>
- <listitem><para>mask_ack() - Optional, recommended for performance</para></listitem>
- <listitem><para>mask()</para></listitem>
- <listitem><para>unmask()</para></listitem>
- <listitem><para>retrigger() - Optional</para></listitem>
- <listitem><para>set_type() - Optional</para></listitem>
- <listitem><para>set_wake() - Optional</para></listitem>
+ <listitem><para>irq_ack()</para></listitem>
+ <listitem><para>irq_mask_ack() - Optional, recommended for performance</para></listitem>
+ <listitem><para>irq_mask()</para></listitem>
+ <listitem><para>irq_unmask()</para></listitem>
+ <listitem><para>irq_retrigger() - Optional</para></listitem>
+ <listitem><para>irq_set_type() - Optional</para></listitem>
+ <listitem><para>irq_set_wake() - Optional</para></listitem>
</itemizedlist>
These primitives are strictly intended to mean what they say: ack means
ACK, masking means masking of an IRQ line, etc. It is up to the flow
@@ -458,6 +477,7 @@ desc->chip->end();
<para>
This chapter contains the autogenerated documentation of the internal functions.
</para>
+!Ikernel/irq/irqdesc.c
!Ikernel/irq/handle.c
!Ikernel/irq/chip.c
</chapter>
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl
index 6899f471fb15..6b4e07f28b69 100644
--- a/Documentation/DocBook/kernel-api.tmpl
+++ b/Documentation/DocBook/kernel-api.tmpl
@@ -257,7 +257,8 @@ X!Earch/x86/kernel/mca_32.c
!Iblock/blk-sysfs.c
!Eblock/blk-settings.c
!Eblock/blk-exec.c
-!Eblock/blk-barrier.c
+!Eblock/blk-flush.c
+!Eblock/blk-lib.c
!Eblock/blk-tag.c
!Iblock/blk-tag.c
!Eblock/blk-integrity.c
diff --git a/Documentation/DocBook/kernel-locking.tmpl b/Documentation/DocBook/kernel-locking.tmpl
index a0d479d1e1dd..f66f4df18690 100644
--- a/Documentation/DocBook/kernel-locking.tmpl
+++ b/Documentation/DocBook/kernel-locking.tmpl
@@ -1645,7 +1645,9 @@ the amount of locking which needs to be done.
all the readers who were traversing the list when we deleted the
element are finished. We use <function>call_rcu()</function> to
register a callback which will actually destroy the object once
- the readers are finished.
+ all pre-existing readers are finished. Alternatively,
+ <function>synchronize_rcu()</function> may be used to block until
+ all pre-existing are finished.
</para>
<para>
But how does Read Copy Update know when the readers are
@@ -1714,7 +1716,7 @@ the amount of locking which needs to be done.
- object_put(obj);
+ list_del_rcu(&amp;obj-&gt;list);
cache_num--;
-+ call_rcu(&amp;obj-&gt;rcu, cache_delete_rcu, obj);
++ call_rcu(&amp;obj-&gt;rcu, cache_delete_rcu);
}
/* Must be holding cache_lock */
@@ -1725,14 +1727,6 @@ the amount of locking which needs to be done.
if (++cache_num > MAX_CACHE_SIZE) {
struct object *i, *outcast = NULL;
list_for_each_entry(i, &amp;cache, list) {
-@@ -85,6 +94,7 @@
- obj-&gt;popularity = 0;
- atomic_set(&amp;obj-&gt;refcnt, 1); /* The cache holds a reference */
- spin_lock_init(&amp;obj-&gt;lock);
-+ INIT_RCU_HEAD(&amp;obj-&gt;rcu);
-
- spin_lock_irqsave(&amp;cache_lock, flags);
- __cache_add(obj);
@@ -104,12 +114,11 @@
struct object *cache_find(int id)
{
diff --git a/Documentation/DocBook/mac80211.tmpl b/Documentation/DocBook/mac80211.tmpl
deleted file mode 100644
index affb15a344a1..000000000000
--- a/Documentation/DocBook/mac80211.tmpl
+++ /dev/null
@@ -1,337 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
- "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
-
-<book id="mac80211-developers-guide">
- <bookinfo>
- <title>The mac80211 subsystem for kernel developers</title>
-
- <authorgroup>
- <author>
- <firstname>Johannes</firstname>
- <surname>Berg</surname>
- <affiliation>
- <address><email>johannes@sipsolutions.net</email></address>
- </affiliation>
- </author>
- </authorgroup>
-
- <copyright>
- <year>2007-2009</year>
- <holder>Johannes Berg</holder>
- </copyright>
-
- <legalnotice>
- <para>
- This documentation is free software; you can redistribute
- it and/or modify it under the terms of the GNU General Public
- License version 2 as published by the Free Software Foundation.
- </para>
-
- <para>
- This documentation is distributed in the hope that it will be
- useful, but WITHOUT ANY WARRANTY; without even the implied
- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the GNU General Public License for more details.
- </para>
-
- <para>
- You should have received a copy of the GNU General Public
- License along with this documentation; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- MA 02111-1307 USA
- </para>
-
- <para>
- For more details see the file COPYING in the source
- distribution of Linux.
- </para>
- </legalnotice>
-
- <abstract>
-!Pinclude/net/mac80211.h Introduction
-!Pinclude/net/mac80211.h Warning
- </abstract>
- </bookinfo>
-
- <toc></toc>
-
-<!--
-Generally, this document shall be ordered by increasing complexity.
-It is important to note that readers should be able to read only
-the first few sections to get a working driver and only advanced
-usage should require reading the full document.
--->
-
- <part>
- <title>The basic mac80211 driver interface</title>
- <partintro>
- <para>
- You should read and understand the information contained
- within this part of the book while implementing a driver.
- In some chapters, advanced usage is noted, that may be
- skipped at first.
- </para>
- <para>
- This part of the book only covers station and monitor mode
- functionality, additional information required to implement
- the other modes is covered in the second part of the book.
- </para>
- </partintro>
-
- <chapter id="basics">
- <title>Basic hardware handling</title>
- <para>TBD</para>
- <para>
- This chapter shall contain information on getting a hw
- struct allocated and registered with mac80211.
- </para>
- <para>
- Since it is required to allocate rates/modes before registering
- a hw struct, this chapter shall also contain information on setting
- up the rate/mode structs.
- </para>
- <para>
- Additionally, some discussion about the callbacks and
- the general programming model should be in here, including
- the definition of ieee80211_ops which will be referred to
- a lot.
- </para>
- <para>
- Finally, a discussion of hardware capabilities should be done
- with references to other parts of the book.
- </para>
-<!-- intentionally multiple !F lines to get proper order -->
-!Finclude/net/mac80211.h ieee80211_hw
-!Finclude/net/mac80211.h ieee80211_hw_flags
-!Finclude/net/mac80211.h SET_IEEE80211_DEV
-!Finclude/net/mac80211.h SET_IEEE80211_PERM_ADDR
-!Finclude/net/mac80211.h ieee80211_ops
-!Finclude/net/mac80211.h ieee80211_alloc_hw
-!Finclude/net/mac80211.h ieee80211_register_hw
-!Finclude/net/mac80211.h ieee80211_get_tx_led_name
-!Finclude/net/mac80211.h ieee80211_get_rx_led_name
-!Finclude/net/mac80211.h ieee80211_get_assoc_led_name
-!Finclude/net/mac80211.h ieee80211_get_radio_led_name
-!Finclude/net/mac80211.h ieee80211_unregister_hw
-!Finclude/net/mac80211.h ieee80211_free_hw
- </chapter>
-
- <chapter id="phy-handling">
- <title>PHY configuration</title>
- <para>TBD</para>
- <para>
- This chapter should describe PHY handling including
- start/stop callbacks and the various structures used.
- </para>
-!Finclude/net/mac80211.h ieee80211_conf
-!Finclude/net/mac80211.h ieee80211_conf_flags
- </chapter>
-
- <chapter id="iface-handling">
- <title>Virtual interfaces</title>
- <para>TBD</para>
- <para>
- This chapter should describe virtual interface basics
- that are relevant to the driver (VLANs, MGMT etc are not.)
- It should explain the use of the add_iface/remove_iface
- callbacks as well as the interface configuration callbacks.
- </para>
- <para>Things related to AP mode should be discussed there.</para>
- <para>
- Things related to supporting multiple interfaces should be
- in the appropriate chapter, a BIG FAT note should be here about
- this though and the recommendation to allow only a single
- interface in STA mode at first!
- </para>
-!Finclude/net/mac80211.h ieee80211_vif
- </chapter>
-
- <chapter id="rx-tx">
- <title>Receive and transmit processing</title>
- <sect1>
- <title>what should be here</title>
- <para>TBD</para>
- <para>
- This should describe the receive and transmit
- paths in mac80211/the drivers as well as
- transmit status handling.
- </para>
- </sect1>
- <sect1>
- <title>Frame format</title>
-!Pinclude/net/mac80211.h Frame format
- </sect1>
- <sect1>
- <title>Packet alignment</title>
-!Pnet/mac80211/rx.c Packet alignment
- </sect1>
- <sect1>
- <title>Calling into mac80211 from interrupts</title>
-!Pinclude/net/mac80211.h Calling mac80211 from interrupts
- </sect1>
- <sect1>
- <title>functions/definitions</title>
-!Finclude/net/mac80211.h ieee80211_rx_status
-!Finclude/net/mac80211.h mac80211_rx_flags
-!Finclude/net/mac80211.h ieee80211_tx_info
-!Finclude/net/mac80211.h ieee80211_rx
-!Finclude/net/mac80211.h ieee80211_rx_irqsafe
-!Finclude/net/mac80211.h ieee80211_tx_status
-!Finclude/net/mac80211.h ieee80211_tx_status_irqsafe
-!Finclude/net/mac80211.h ieee80211_rts_get
-!Finclude/net/mac80211.h ieee80211_rts_duration
-!Finclude/net/mac80211.h ieee80211_ctstoself_get
-!Finclude/net/mac80211.h ieee80211_ctstoself_duration
-!Finclude/net/mac80211.h ieee80211_generic_frame_duration
-!Finclude/net/mac80211.h ieee80211_wake_queue
-!Finclude/net/mac80211.h ieee80211_stop_queue
-!Finclude/net/mac80211.h ieee80211_wake_queues
-!Finclude/net/mac80211.h ieee80211_stop_queues
- </sect1>
- </chapter>
-
- <chapter id="filters">
- <title>Frame filtering</title>
-!Pinclude/net/mac80211.h Frame filtering
-!Finclude/net/mac80211.h ieee80211_filter_flags
- </chapter>
- </part>
-
- <part id="advanced">
- <title>Advanced driver interface</title>
- <partintro>
- <para>
- Information contained within this part of the book is
- of interest only for advanced interaction of mac80211
- with drivers to exploit more hardware capabilities and
- improve performance.
- </para>
- </partintro>
-
- <chapter id="hardware-crypto-offload">
- <title>Hardware crypto acceleration</title>
-!Pinclude/net/mac80211.h Hardware crypto acceleration
-<!-- intentionally multiple !F lines to get proper order -->
-!Finclude/net/mac80211.h set_key_cmd
-!Finclude/net/mac80211.h ieee80211_key_conf
-!Finclude/net/mac80211.h ieee80211_key_alg
-!Finclude/net/mac80211.h ieee80211_key_flags
- </chapter>
-
- <chapter id="powersave">
- <title>Powersave support</title>
-!Pinclude/net/mac80211.h Powersave support
- </chapter>
-
- <chapter id="beacon-filter">
- <title>Beacon filter support</title>
-!Pinclude/net/mac80211.h Beacon filter support
-!Finclude/net/mac80211.h ieee80211_beacon_loss
- </chapter>
-
- <chapter id="qos">
- <title>Multiple queues and QoS support</title>
- <para>TBD</para>
-!Finclude/net/mac80211.h ieee80211_tx_queue_params
- </chapter>
-
- <chapter id="AP">
- <title>Access point mode support</title>
- <para>TBD</para>
- <para>Some parts of the if_conf should be discussed here instead</para>
- <para>
- Insert notes about VLAN interfaces with hw crypto here or
- in the hw crypto chapter.
- </para>
-!Finclude/net/mac80211.h ieee80211_get_buffered_bc
-!Finclude/net/mac80211.h ieee80211_beacon_get
- </chapter>
-
- <chapter id="multi-iface">
- <title>Supporting multiple virtual interfaces</title>
- <para>TBD</para>
- <para>
- Note: WDS with identical MAC address should almost always be OK
- </para>
- <para>
- Insert notes about having multiple virtual interfaces with
- different MAC addresses here, note which configurations are
- supported by mac80211, add notes about supporting hw crypto
- with it.
- </para>
- </chapter>
-
- <chapter id="hardware-scan-offload">
- <title>Hardware scan offload</title>
- <para>TBD</para>
-!Finclude/net/mac80211.h ieee80211_scan_completed
- </chapter>
- </part>
-
- <part id="rate-control">
- <title>Rate control interface</title>
- <partintro>
- <para>TBD</para>
- <para>
- This part of the book describes the rate control algorithm
- interface and how it relates to mac80211 and drivers.
- </para>
- </partintro>
- <chapter id="dummy">
- <title>dummy chapter</title>
- <para>TBD</para>
- </chapter>
- </part>
-
- <part id="internal">
- <title>Internals</title>
- <partintro>
- <para>TBD</para>
- <para>
- This part of the book describes mac80211 internals.
- </para>
- </partintro>
-
- <chapter id="key-handling">
- <title>Key handling</title>
- <sect1>
- <title>Key handling basics</title>
-!Pnet/mac80211/key.c Key handling basics
- </sect1>
- <sect1>
- <title>MORE TBD</title>
- <para>TBD</para>
- </sect1>
- </chapter>
-
- <chapter id="rx-processing">
- <title>Receive processing</title>
- <para>TBD</para>
- </chapter>
-
- <chapter id="tx-processing">
- <title>Transmit processing</title>
- <para>TBD</para>
- </chapter>
-
- <chapter id="sta-info">
- <title>Station info handling</title>
- <sect1>
- <title>Programming information</title>
-!Fnet/mac80211/sta_info.h sta_info
-!Fnet/mac80211/sta_info.h ieee80211_sta_info_flags
- </sect1>
- <sect1>
- <title>STA information lifetime rules</title>
-!Pnet/mac80211/sta_info.c STA information lifetime rules
- </sect1>
- </chapter>
-
- <chapter id="synchronisation">
- <title>Synchronisation</title>
- <para>TBD</para>
- <para>Locking, lots of RCU</para>
- </chapter>
- </part>
-</book>
diff --git a/Documentation/RCU/checklist.txt b/Documentation/RCU/checklist.txt
index 790d1a812376..0c134f8afc6f 100644
--- a/Documentation/RCU/checklist.txt
+++ b/Documentation/RCU/checklist.txt
@@ -218,13 +218,22 @@ over a rather long period of time, but improvements are always welcome!
include:
a. Keeping a count of the number of data-structure elements
- used by the RCU-protected data structure, including those
- waiting for a grace period to elapse. Enforce a limit
- on this number, stalling updates as needed to allow
- previously deferred frees to complete.
-
- Alternatively, limit only the number awaiting deferred
- free rather than the total number of elements.
+ used by the RCU-protected data structure, including
+ those waiting for a grace period to elapse. Enforce a
+ limit on this number, stalling updates as needed to allow
+ previously deferred frees to complete. Alternatively,
+ limit only the number awaiting deferred free rather than
+ the total number of elements.
+
+ One way to stall the updates is to acquire the update-side
+ mutex. (Don't try this with a spinlock -- other CPUs
+ spinning on the lock could prevent the grace period
+ from ever ending.) Another way to stall the updates
+ is for the updates to use a wrapper function around
+ the memory allocator, so that this wrapper function
+ simulates OOM when there is too much memory awaiting an
+ RCU grace period. There are of course many other
+ variations on this theme.
b. Limiting update rate. For example, if updates occur only
once per hour, then no explicit rate limiting is required,
@@ -365,3 +374,26 @@ over a rather long period of time, but improvements are always welcome!
and the compiler to freely reorder code into and out of RCU
read-side critical sections. It is the responsibility of the
RCU update-side primitives to deal with this.
+
+17. Use CONFIG_PROVE_RCU, CONFIG_DEBUG_OBJECTS_RCU_HEAD, and
+ the __rcu sparse checks to validate your RCU code. These
+ can help find problems as follows:
+
+ CONFIG_PROVE_RCU: check that accesses to RCU-protected data
+ structures are carried out under the proper RCU
+ read-side critical section, while holding the right
+ combination of locks, or whatever other conditions
+ are appropriate.
+
+ CONFIG_DEBUG_OBJECTS_RCU_HEAD: check that you don't pass the
+ same object to call_rcu() (or friends) before an RCU
+ grace period has elapsed since the last time that you
+ passed that same object to call_rcu() (or friends).
+
+ __rcu sparse checks: tag the pointer to the RCU-protected data
+ structure with __rcu, and sparse will warn you if you
+ access that pointer without the services of one of the
+ variants of rcu_dereference().
+
+ These debugging aids can help you find problems that are
+ otherwise extremely difficult to spot.
diff --git a/Documentation/RCU/stallwarn.txt b/Documentation/RCU/stallwarn.txt
index 44c6dcc93d6d..862c08ef1fde 100644
--- a/Documentation/RCU/stallwarn.txt
+++ b/Documentation/RCU/stallwarn.txt
@@ -80,6 +80,24 @@ o A CPU looping with bottom halves disabled. This condition can
o For !CONFIG_PREEMPT kernels, a CPU looping anywhere in the kernel
without invoking schedule().
+o A CPU-bound real-time task in a CONFIG_PREEMPT kernel, which might
+ happen to preempt a low-priority task in the middle of an RCU
+ read-side critical section. This is especially damaging if
+ that low-priority task is not permitted to run on any other CPU,
+ in which case the next RCU grace period can never complete, which
+ will eventually cause the system to run out of memory and hang.
+ While the system is in the process of running itself out of
+ memory, you might see stall-warning messages.
+
+o A CPU-bound real-time task in a CONFIG_PREEMPT_RT kernel that
+ is running at a higher priority than the RCU softirq threads.
+ This will prevent RCU callbacks from ever being invoked,
+ and in a CONFIG_TREE_PREEMPT_RCU kernel will further prevent
+ RCU grace periods from ever completing. Either way, the
+ system will eventually run out of memory and hang. In the
+ CONFIG_TREE_PREEMPT_RCU case, you might see stall-warning
+ messages.
+
o A bug in the RCU implementation.
o A hardware failure. This is quite unlikely, but has occurred
diff --git a/Documentation/RCU/trace.txt b/Documentation/RCU/trace.txt
index efd8cc95c06b..a851118775d8 100644
--- a/Documentation/RCU/trace.txt
+++ b/Documentation/RCU/trace.txt
@@ -125,6 +125,17 @@ o "b" is the batch limit for this CPU. If more than this number
of RCU callbacks is ready to invoke, then the remainder will
be deferred.
+o "ci" is the number of RCU callbacks that have been invoked for
+ this CPU. Note that ci+ql is the number of callbacks that have
+ been registered in absence of CPU-hotplug activity.
+
+o "co" is the number of RCU callbacks that have been orphaned due to
+ this CPU going offline.
+
+o "ca" is the number of RCU callbacks that have been adopted due to
+ other CPUs going offline. Note that ci+co-ca+ql is the number of
+ RCU callbacks registered on this CPU.
+
There is also an rcu/rcudata.csv file with the same information in
comma-separated-variable spreadsheet format.
@@ -180,7 +191,7 @@ o "s" is the "signaled" state that drives force_quiescent_state()'s
o "jfq" is the number of jiffies remaining for this grace period
before force_quiescent_state() is invoked to help push things
- along. Note that CPUs in dyntick-idle mode thoughout the grace
+ along. Note that CPUs in dyntick-idle mode throughout the grace
period will not report on their own, but rather must be check by
some other CPU via force_quiescent_state().
diff --git a/Documentation/arm/00-INDEX b/Documentation/arm/00-INDEX
index 7f5fc3ba9c91..ecf7d04bca26 100644
--- a/Documentation/arm/00-INDEX
+++ b/Documentation/arm/00-INDEX
@@ -6,6 +6,8 @@ Interrupts
- ARM Interrupt subsystem documentation
IXP2000
- Release Notes for Linux on Intel's IXP2000 Network Processor
+msm
+ - MSM specific documentation
Netwinder
- Netwinder specific documentation
Porting
diff --git a/Documentation/arm/msm/gpiomux.txt b/Documentation/arm/msm/gpiomux.txt
new file mode 100644
index 000000000000..67a81620adf6
--- /dev/null
+++ b/Documentation/arm/msm/gpiomux.txt
@@ -0,0 +1,176 @@
+This document provides an overview of the msm_gpiomux interface, which
+is used to provide gpio pin multiplexing and configuration on mach-msm
+targets.
+
+History
+=======
+
+The first-generation API for gpio configuration & multiplexing on msm
+is the function gpio_tlmm_config(). This function has a few notable
+shortcomings, which led to its deprecation and replacement by gpiomux:
+
+The 'disable' parameter: Setting the second parameter to
+gpio_tlmm_config to GPIO_CFG_DISABLE tells the peripheral
+processor in charge of the subsystem to perform a look-up into a
+low-power table and apply the low-power/sleep setting for the pin.
+As the msm family evolved this became problematic. Not all pins
+have sleep settings, not all peripheral processors will accept requests
+to apply said sleep settings, and not all msm targets have their gpio
+subsystems managed by a peripheral processor. In order to get consistent
+behavior on all targets, drivers are forced to ignore this parameter,
+rendering it useless.
+
+The 'direction' flag: for all mux-settings other than raw-gpio (0),
+the output-enable bit of a gpio is hard-wired to a known
+input (usually VDD or ground). For those settings, the direction flag
+is meaningless at best, and deceptive at worst. In addition, using the
+direction flag to change output-enable (OE) directly can cause trouble in
+gpiolib, which has no visibility into gpio direction changes made
+in this way. Direction control in gpio mode should be made through gpiolib.
+
+Key Features of gpiomux
+=======================
+
+- A consistent interface across all generations of msm. Drivers can expect
+the same results on every target.
+- gpiomux plays nicely with gpiolib. Functions that should belong to gpiolib
+are left to gpiolib and not duplicated here. gpiomux is written with the
+intent that gpio_chips will call gpiomux reference-counting methods
+from their request() and free() hooks, providing full integration.
+- Tabular configuration. Instead of having to call gpio_tlmm_config
+hundreds of times, gpio configuration is placed in a single table.
+- Per-gpio sleep. Each gpio is individually reference counted, allowing only
+those lines which are in use to be put in high-power states.
+- 0 means 'do nothing': all flags are designed so that the default memset-zero
+equates to a sensible default of 'no configuration', preventing users
+from having to provide hundreds of 'no-op' configs for unused or
+unwanted lines.
+
+Usage
+=====
+
+To use gpiomux, provide configuration information for relevant gpio lines
+in the msm_gpiomux_configs table. Since a 0 equates to "unconfigured",
+only those lines to be managed by gpiomux need to be specified. Here
+is a completely fictional example:
+
+struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = {
+ [12] = {
+ .active = GPIOMUX_VALID | GPIOMUX_DRV_8MA | GPIOMUX_FUNC_1,
+ .suspended = GPIOMUX_VALID | GPIOMUX_PULL_DOWN,
+ },
+ [34] = {
+ .suspended = GPIOMUX_VALID | GPIOMUX_PULL_DOWN,
+ },
+};
+
+To indicate that a gpio is in use, call msm_gpiomux_get() to increase
+its reference count. To decrease the reference count, call msm_gpiomux_put().
+
+The effect of this configuration is as follows:
+
+When the system boots, gpios 12 and 34 will be initialized with their
+'suspended' configurations. All other gpios, which were left unconfigured,
+will not be touched.
+
+When msm_gpiomux_get() is called on gpio 12 to raise its reference count
+above 0, its active configuration will be applied. Since no other gpio
+line has a valid active configuration, msm_gpiomux_get() will have no
+effect on any other line.
+
+When msm_gpiomux_put() is called on gpio 12 or 34 to drop their reference
+count to 0, their suspended configurations will be applied.
+Since no other gpio line has a valid suspended configuration, no other
+gpio line will be effected by msm_gpiomux_put(). Since gpio 34 has no valid
+active configuration, this is effectively a no-op for gpio 34 as well,
+with one small caveat, see the section "About Output-Enable Settings".
+
+All of the GPIOMUX_VALID flags may seem like unnecessary overhead, but
+they address some important issues. As unused entries (all those
+except 12 and 34) are zero-filled, gpiomux needs a way to distinguish
+the used fields from the unused. In addition, the all-zero pattern
+is a valid configuration! Therefore, gpiomux defines an additional bit
+which is used to indicate when a field is used. This has the pleasant
+side-effect of allowing calls to msm_gpiomux_write to use '0' to indicate
+that a value should not be changed:
+
+ msm_gpiomux_write(0, GPIOMUX_VALID, 0);
+
+replaces the active configuration of gpio 0 with an all-zero configuration,
+but leaves the suspended configuration as it was.
+
+Static Configurations
+=====================
+
+To install a static configuration, which is applied at boot and does
+not change after that, install a configuration with a suspended component
+but no active component, as in the previous example:
+
+ [34] = {
+ .suspended = GPIOMUX_VALID | GPIOMUX_PULL_DOWN,
+ },
+
+The suspended setting is applied during boot, and the lack of any valid
+active setting prevents any other setting from being applied at runtime.
+If other subsystems attempting to access the line is a concern, one could
+*really* anchor the configuration down by calling msm_gpiomux_get on the
+line at initialization to move the line into active mode. With the line
+held, it will never be re-suspended, and with no valid active configuration,
+no new configurations will be applied.
+
+But then, if having other subsystems grabbing for the line is truly a concern,
+it should be reserved with gpio_request instead, which carries an implicit
+msm_gpiomux_get.
+
+gpiomux and gpiolib
+===================
+
+It is expected that msm gpio_chips will call msm_gpiomux_get() and
+msm_gpiomux_put() from their request and free hooks, like this fictional
+example:
+
+static int request(struct gpio_chip *chip, unsigned offset)
+{
+ return msm_gpiomux_get(chip->base + offset);
+}
+
+static void free(struct gpio_chip *chip, unsigned offset)
+{
+ msm_gpiomux_put(chip->base + offset);
+}
+
+ ...somewhere in a gpio_chip declaration...
+ .request = request,
+ .free = free,
+
+This provides important functionality:
+- It guarantees that a gpio line will have its 'active' config applied
+ when the line is requested, and will not be suspended while the line
+ remains requested; and
+- It guarantees that gpio-direction settings from gpiolib behave sensibly.
+ See "About Output-Enable Settings."
+
+This mechanism allows for "auto-request" of gpiomux lines via gpiolib
+when it is suitable. Drivers wishing more exact control are, of course,
+free to also use msm_gpiomux_set and msm_gpiomux_get.
+
+About Output-Enable Settings
+============================
+
+Some msm targets do not have the ability to query the current gpio
+configuration setting. This means that changes made to the output-enable
+(OE) bit by gpiolib cannot be consistently detected and preserved by gpiomux.
+Therefore, when gpiomux applies a configuration setting, any direction
+settings which may have been applied by gpiolib are lost and the default
+input settings are re-applied.
+
+For this reason, drivers should not assume that gpio direction settings
+continue to hold if they free and then re-request a gpio. This seems like
+common sense - after all, anybody could have obtained the line in the
+meantime - but it needs saying.
+
+This also means that calls to msm_gpiomux_write will reset the OE bit,
+which means that if the gpio line is held by a client of gpiolib and
+msm_gpiomux_write is called, the direction setting has been lost and
+gpiolib's internal state has been broken.
+Release gpio lines before reconfiguring them.
diff --git a/Documentation/block/00-INDEX b/Documentation/block/00-INDEX
index a406286f6f3e..d111e3b23db0 100644
--- a/Documentation/block/00-INDEX
+++ b/Documentation/block/00-INDEX
@@ -1,7 +1,5 @@
00-INDEX
- This file
-barrier.txt
- - I/O Barriers
biodoc.txt
- Notes on the Generic Block Layer Rewrite in Linux 2.5
capability.txt
@@ -16,3 +14,5 @@ stat.txt
- Block layer statistics in /sys/block/<dev>/stat
switching-sched.txt
- Switching I/O schedulers at runtime
+writeback_cache_control.txt
+ - Control of volatile write back caches
diff --git a/Documentation/block/barrier.txt b/Documentation/block/barrier.txt
deleted file mode 100644
index 2c2f24f634e4..000000000000
--- a/Documentation/block/barrier.txt
+++ /dev/null
@@ -1,261 +0,0 @@
-I/O Barriers
-============
-Tejun Heo <htejun@gmail.com>, July 22 2005
-
-I/O barrier requests are used to guarantee ordering around the barrier
-requests. Unless you're crazy enough to use disk drives for
-implementing synchronization constructs (wow, sounds interesting...),
-the ordering is meaningful only for write requests for things like
-journal checkpoints. All requests queued before a barrier request
-must be finished (made it to the physical medium) before the barrier
-request is started, and all requests queued after the barrier request
-must be started only after the barrier request is finished (again,
-made it to the physical medium).
-
-In other words, I/O barrier requests have the following two properties.
-
-1. Request ordering
-
-Requests cannot pass the barrier request. Preceding requests are
-processed before the barrier and following requests after.
-
-Depending on what features a drive supports, this can be done in one
-of the following three ways.
-
-i. For devices which have queue depth greater than 1 (TCQ devices) and
-support ordered tags, block layer can just issue the barrier as an
-ordered request and the lower level driver, controller and drive
-itself are responsible for making sure that the ordering constraint is
-met. Most modern SCSI controllers/drives should support this.
-
-NOTE: SCSI ordered tag isn't currently used due to limitation in the
- SCSI midlayer, see the following random notes section.
-
-ii. For devices which have queue depth greater than 1 but don't
-support ordered tags, block layer ensures that the requests preceding
-a barrier request finishes before issuing the barrier request. Also,
-it defers requests following the barrier until the barrier request is
-finished. Older SCSI controllers/drives and SATA drives fall in this
-category.
-
-iii. Devices which have queue depth of 1. This is a degenerate case
-of ii. Just keeping issue order suffices. Ancient SCSI
-controllers/drives and IDE drives are in this category.
-
-2. Forced flushing to physical medium
-
-Again, if you're not gonna do synchronization with disk drives (dang,
-it sounds even more appealing now!), the reason you use I/O barriers
-is mainly to protect filesystem integrity when power failure or some
-other events abruptly stop the drive from operating and possibly make
-the drive lose data in its cache. So, I/O barriers need to guarantee
-that requests actually get written to non-volatile medium in order.
-
-There are four cases,
-
-i. No write-back cache. Keeping requests ordered is enough.
-
-ii. Write-back cache but no flush operation. There's no way to
-guarantee physical-medium commit order. This kind of devices can't to
-I/O barriers.
-
-iii. Write-back cache and flush operation but no FUA (forced unit
-access). We need two cache flushes - before and after the barrier
-request.
-
-iv. Write-back cache, flush operation and FUA. We still need one
-flush to make sure requests preceding a barrier are written to medium,
-but post-barrier flush can be avoided by using FUA write on the
-barrier itself.
-
-
-How to support barrier requests in drivers
-------------------------------------------
-
-All barrier handling is done inside block layer proper. All low level
-drivers have to are implementing its prepare_flush_fn and using one
-the following two functions to indicate what barrier type it supports
-and how to prepare flush requests. Note that the term 'ordered' is
-used to indicate the whole sequence of performing barrier requests
-including draining and flushing.
-
-typedef void (prepare_flush_fn)(struct request_queue *q, struct request *rq);
-
-int blk_queue_ordered(struct request_queue *q, unsigned ordered,
- prepare_flush_fn *prepare_flush_fn);
-
-@q : the queue in question
-@ordered : the ordered mode the driver/device supports
-@prepare_flush_fn : this function should prepare @rq such that it
- flushes cache to physical medium when executed
-
-For example, SCSI disk driver's prepare_flush_fn looks like the
-following.
-
-static void sd_prepare_flush(struct request_queue *q, struct request *rq)
-{
- memset(rq->cmd, 0, sizeof(rq->cmd));
- rq->cmd_type = REQ_TYPE_BLOCK_PC;
- rq->timeout = SD_TIMEOUT;
- rq->cmd[0] = SYNCHRONIZE_CACHE;
- rq->cmd_len = 10;
-}
-
-The following seven ordered modes are supported. The following table
-shows which mode should be used depending on what features a
-device/driver supports. In the leftmost column of table,
-QUEUE_ORDERED_ prefix is omitted from the mode names to save space.
-
-The table is followed by description of each mode. Note that in the
-descriptions of QUEUE_ORDERED_DRAIN*, '=>' is used whereas '->' is
-used for QUEUE_ORDERED_TAG* descriptions. '=>' indicates that the
-preceding step must be complete before proceeding to the next step.
-'->' indicates that the next step can start as soon as the previous
-step is issued.
-
- write-back cache ordered tag flush FUA
------------------------------------------------------------------------
-NONE yes/no N/A no N/A
-DRAIN no no N/A N/A
-DRAIN_FLUSH yes no yes no
-DRAIN_FUA yes no yes yes
-TAG no yes N/A N/A
-TAG_FLUSH yes yes yes no
-TAG_FUA yes yes yes yes
-
-
-QUEUE_ORDERED_NONE
- I/O barriers are not needed and/or supported.
-
- Sequence: N/A
-
-QUEUE_ORDERED_DRAIN
- Requests are ordered by draining the request queue and cache
- flushing isn't needed.
-
- Sequence: drain => barrier
-
-QUEUE_ORDERED_DRAIN_FLUSH
- Requests are ordered by draining the request queue and both
- pre-barrier and post-barrier cache flushings are needed.
-
- Sequence: drain => preflush => barrier => postflush
-
-QUEUE_ORDERED_DRAIN_FUA
- Requests are ordered by draining the request queue and
- pre-barrier cache flushing is needed. By using FUA on barrier
- request, post-barrier flushing can be skipped.
-
- Sequence: drain => preflush => barrier
-
-QUEUE_ORDERED_TAG
- Requests are ordered by ordered tag and cache flushing isn't
- needed.
-
- Sequence: barrier
-
-QUEUE_ORDERED_TAG_FLUSH
- Requests are ordered by ordered tag and both pre-barrier and
- post-barrier cache flushings are needed.
-
- Sequence: preflush -> barrier -> postflush
-
-QUEUE_ORDERED_TAG_FUA
- Requests are ordered by ordered tag and pre-barrier cache
- flushing is needed. By using FUA on barrier request,
- post-barrier flushing can be skipped.
-
- Sequence: preflush -> barrier
-
-
-Random notes/caveats
---------------------
-
-* SCSI layer currently can't use TAG ordering even if the drive,
-controller and driver support it. The problem is that SCSI midlayer
-request dispatch function is not atomic. It releases queue lock and
-switch to SCSI host lock during issue and it's possible and likely to
-happen in time that requests change their relative positions. Once
-this problem is solved, TAG ordering can be enabled.
-
-* Currently, no matter which ordered mode is used, there can be only
-one barrier request in progress. All I/O barriers are held off by
-block layer until the previous I/O barrier is complete. This doesn't
-make any difference for DRAIN ordered devices, but, for TAG ordered
-devices with very high command latency, passing multiple I/O barriers
-to low level *might* be helpful if they are very frequent. Well, this
-certainly is a non-issue. I'm writing this just to make clear that no
-two I/O barrier is ever passed to low-level driver.
-
-* Completion order. Requests in ordered sequence are issued in order
-but not required to finish in order. Barrier implementation can
-handle out-of-order completion of ordered sequence. IOW, the requests
-MUST be processed in order but the hardware/software completion paths
-are allowed to reorder completion notifications - eg. current SCSI
-midlayer doesn't preserve completion order during error handling.
-
-* Requeueing order. Low-level drivers are free to requeue any request
-after they removed it from the request queue with
-blkdev_dequeue_request(). As barrier sequence should be kept in order
-when requeued, generic elevator code takes care of putting requests in
-order around barrier. See blk_ordered_req_seq() and
-ELEVATOR_INSERT_REQUEUE handling in __elv_add_request() for details.
-
-Note that block drivers must not requeue preceding requests while
-completing latter requests in an ordered sequence. Currently, no
-error checking is done against this.
-
-* Error handling. Currently, block layer will report error to upper
-layer if any of requests in an ordered sequence fails. Unfortunately,
-this doesn't seem to be enough. Look at the following request flow.
-QUEUE_ORDERED_TAG_FLUSH is in use.
-
- [0] [1] [2] [3] [pre] [barrier] [post] < [4] [5] [6] ... >
- still in elevator
-
-Let's say request [2], [3] are write requests to update file system
-metadata (journal or whatever) and [barrier] is used to mark that
-those updates are valid. Consider the following sequence.
-
- i. Requests [0] ~ [post] leaves the request queue and enters
- low-level driver.
- ii. After a while, unfortunately, something goes wrong and the
- drive fails [2]. Note that any of [0], [1] and [3] could have
- completed by this time, but [pre] couldn't have been finished
- as the drive must process it in order and it failed before
- processing that command.
- iii. Error handling kicks in and determines that the error is
- unrecoverable and fails [2], and resumes operation.
- iv. [pre] [barrier] [post] gets processed.
- v. *BOOM* power fails
-
-The problem here is that the barrier request is *supposed* to indicate
-that filesystem update requests [2] and [3] made it safely to the
-physical medium and, if the machine crashes after the barrier is
-written, filesystem recovery code can depend on that. Sadly, that
-isn't true in this case anymore. IOW, the success of a I/O barrier
-should also be dependent on success of some of the preceding requests,
-where only upper layer (filesystem) knows what 'some' is.
-
-This can be solved by implementing a way to tell the block layer which
-requests affect the success of the following barrier request and
-making lower lever drivers to resume operation on error only after
-block layer tells it to do so.
-
-As the probability of this happening is very low and the drive should
-be faulty, implementing the fix is probably an overkill. But, still,
-it's there.
-
-* In previous drafts of barrier implementation, there was fallback
-mechanism such that, if FUA or ordered TAG fails, less fancy ordered
-mode can be selected and the failed barrier request is retried
-automatically. The rationale for this feature was that as FUA is
-pretty new in ATA world and ordered tag was never used widely, there
-could be devices which report to support those features but choke when
-actually given such requests.
-
- This was removed for two reasons 1. it's an overkill 2. it's
-impossible to implement properly when TAG ordering is used as low
-level drivers resume after an error automatically. If it's ever
-needed adding it back and modifying low level drivers accordingly
-shouldn't be difficult.
diff --git a/Documentation/block/writeback_cache_control.txt b/Documentation/block/writeback_cache_control.txt
new file mode 100644
index 000000000000..83407d36630a
--- /dev/null
+++ b/Documentation/block/writeback_cache_control.txt
@@ -0,0 +1,86 @@
+
+Explicit volatile write back cache control
+=====================================
+
+Introduction
+------------
+
+Many storage devices, especially in the consumer market, come with volatile
+write back caches. That means the devices signal I/O completion to the
+operating system before data actually has hit the non-volatile storage. This
+behavior obviously speeds up various workloads, but it means the operating
+system needs to force data out to the non-volatile storage when it performs
+a data integrity operation like fsync, sync or an unmount.
+
+The Linux block layer provides two simple mechanisms that let filesystems
+control the caching behavior of the storage device. These mechanisms are
+a forced cache flush, and the Force Unit Access (FUA) flag for requests.
+
+
+Explicit cache flushes
+----------------------
+
+The REQ_FLUSH flag can be OR ed into the r/w flags of a bio submitted from
+the filesystem and will make sure the volatile cache of the storage device
+has been flushed before the actual I/O operation is started. This explicitly
+guarantees that previously completed write requests are on non-volatile
+storage before the flagged bio starts. In addition the REQ_FLUSH flag can be
+set on an otherwise empty bio structure, which causes only an explicit cache
+flush without any dependent I/O. It is recommend to use
+the blkdev_issue_flush() helper for a pure cache flush.
+
+
+Forced Unit Access
+-----------------
+
+The REQ_FUA flag can be OR ed into the r/w flags of a bio submitted from the
+filesystem and will make sure that I/O completion for this request is only
+signaled after the data has been committed to non-volatile storage.
+
+
+Implementation details for filesystems
+--------------------------------------
+
+Filesystems can simply set the REQ_FLUSH and REQ_FUA bits and do not have to
+worry if the underlying devices need any explicit cache flushing and how
+the Forced Unit Access is implemented. The REQ_FLUSH and REQ_FUA flags
+may both be set on a single bio.
+
+
+Implementation details for make_request_fn based block drivers
+--------------------------------------------------------------
+
+These drivers will always see the REQ_FLUSH and REQ_FUA bits as they sit
+directly below the submit_bio interface. For remapping drivers the REQ_FUA
+bits need to be propagated to underlying devices, and a global flush needs
+to be implemented for bios with the REQ_FLUSH bit set. For real device
+drivers that do not have a volatile cache the REQ_FLUSH and REQ_FUA bits
+on non-empty bios can simply be ignored, and REQ_FLUSH requests without
+data can be completed successfully without doing any work. Drivers for
+devices with volatile caches need to implement the support for these
+flags themselves without any help from the block layer.
+
+
+Implementation details for request_fn based block drivers
+--------------------------------------------------------------
+
+For devices that do not support volatile write caches there is no driver
+support required, the block layer completes empty REQ_FLUSH requests before
+entering the driver and strips off the REQ_FLUSH and REQ_FUA bits from
+requests that have a payload. For devices with volatile write caches the
+driver needs to tell the block layer that it supports flushing caches by
+doing:
+
+ blk_queue_flush(sdkp->disk->queue, REQ_FLUSH);
+
+and handle empty REQ_FLUSH requests in its prep_fn/request_fn. Note that
+REQ_FLUSH requests with a payload are automatically turned into a sequence
+of an empty REQ_FLUSH request followed by the actual write by the block
+layer. For devices that also support the FUA bit the block layer needs
+to be told to pass through the REQ_FUA bit using:
+
+ blk_queue_flush(sdkp->disk->queue, REQ_FLUSH | REQ_FUA);
+
+and the driver must handle write requests that have the REQ_FUA bit set
+in prep_fn/request_fn. If the FUA bit is not natively supported the block
+layer turns it into an empty REQ_FLUSH request after the actual write.
diff --git a/Documentation/cgroups/blkio-controller.txt b/Documentation/cgroups/blkio-controller.txt
index 6919d62591d9..d6da611f8f63 100644
--- a/Documentation/cgroups/blkio-controller.txt
+++ b/Documentation/cgroups/blkio-controller.txt
@@ -8,12 +8,17 @@ both at leaf nodes as well as at intermediate nodes in a storage hierarchy.
Plan is to use the same cgroup based management interface for blkio controller
and based on user options switch IO policies in the background.
-In the first phase, this patchset implements proportional weight time based
-division of disk policy. It is implemented in CFQ. Hence this policy takes
-effect only on leaf nodes when CFQ is being used.
+Currently two IO control policies are implemented. First one is proportional
+weight time based division of disk policy. It is implemented in CFQ. Hence
+this policy takes effect only on leaf nodes when CFQ is being used. The second
+one is throttling policy which can be used to specify upper IO rate limits
+on devices. This policy is implemented in generic block layer and can be
+used on leaf nodes as well as higher level logical devices like device mapper.
HOWTO
=====
+Proportional Weight division of bandwidth
+-----------------------------------------
You can do a very simple testing of running two dd threads in two different
cgroups. Here is what you can do.
@@ -55,6 +60,35 @@ cgroups. Here is what you can do.
group dispatched to the disk. We provide fairness in terms of disk time, so
ideally io.disk_time of cgroups should be in proportion to the weight.
+Throttling/Upper Limit policy
+-----------------------------
+- Enable Block IO controller
+ CONFIG_BLK_CGROUP=y
+
+- Enable throttling in block layer
+ CONFIG_BLK_DEV_THROTTLING=y
+
+- Mount blkio controller
+ mount -t cgroup -o blkio none /cgroup/blkio
+
+- Specify a bandwidth rate on particular device for root group. The format
+ for policy is "<major>:<minor> <byes_per_second>".
+
+ echo "8:16 1048576" > /cgroup/blkio/blkio.read_bps_device
+
+ Above will put a limit of 1MB/second on reads happening for root group
+ on device having major/minor number 8:16.
+
+- Run dd to read a file and see if rate is throttled to 1MB/s or not.
+
+ # dd if=/mnt/common/zerofile of=/dev/null bs=4K count=1024
+ # iflag=direct
+ 1024+0 records in
+ 1024+0 records out
+ 4194304 bytes (4.2 MB) copied, 4.0001 s, 1.0 MB/s
+
+ Limits for writes can be put using blkio.write_bps_device file.
+
Various user visible config options
===================================
CONFIG_BLK_CGROUP
@@ -68,8 +102,13 @@ CONFIG_CFQ_GROUP_IOSCHED
- Enables group scheduling in CFQ. Currently only 1 level of group
creation is allowed.
+CONFIG_BLK_DEV_THROTTLING
+ - Enable block device throttling support in block layer.
+
Details of cgroup files
=======================
+Proportional weight policy files
+--------------------------------
- blkio.weight
- Specifies per cgroup weight. This is default weight of the group
on all the devices until and unless overridden by per device rule.
@@ -210,6 +249,67 @@ Details of cgroup files
and minor number of the device and third field specifies the number
of times a group was dequeued from a particular device.
+Throttling/Upper limit policy files
+-----------------------------------
+- blkio.throttle.read_bps_device
+ - Specifies upper limit on READ rate from the device. IO rate is
+ specified in bytes per second. Rules are per deivce. Following is
+ the format.
+
+ echo "<major>:<minor> <rate_bytes_per_second>" > /cgrp/blkio.read_bps_device
+
+- blkio.throttle.write_bps_device
+ - Specifies upper limit on WRITE rate to the device. IO rate is
+ specified in bytes per second. Rules are per deivce. Following is
+ the format.
+
+ echo "<major>:<minor> <rate_bytes_per_second>" > /cgrp/blkio.write_bps_device
+
+- blkio.throttle.read_iops_device
+ - Specifies upper limit on READ rate from the device. IO rate is
+ specified in IO per second. Rules are per deivce. Following is
+ the format.
+
+ echo "<major>:<minor> <rate_io_per_second>" > /cgrp/blkio.read_iops_device
+
+- blkio.throttle.write_iops_device
+ - Specifies upper limit on WRITE rate to the device. IO rate is
+ specified in io per second. Rules are per deivce. Following is
+ the format.
+
+ echo "<major>:<minor> <rate_io_per_second>" > /cgrp/blkio.write_iops_device
+
+Note: If both BW and IOPS rules are specified for a device, then IO is
+ subjectd to both the constraints.
+
+- blkio.throttle.io_serviced
+ - Number of IOs (bio) completed to/from the disk by the group (as
+ seen by throttling policy). These are further divided by the type
+ of operation - read or write, sync or async. First two fields specify
+ the major and minor number of the device, third field specifies the
+ operation type and the fourth field specifies the number of IOs.
+
+ blkio.io_serviced does accounting as seen by CFQ and counts are in
+ number of requests (struct request). On the other hand,
+ blkio.throttle.io_serviced counts number of IO in terms of number
+ of bios as seen by throttling policy. These bios can later be
+ merged by elevator and total number of requests completed can be
+ lesser.
+
+- blkio.throttle.io_service_bytes
+ - Number of bytes transferred to/from the disk by the group. These
+ are further divided by the type of operation - read or write, sync
+ or async. First two fields specify the major and minor number of the
+ device, third field specifies the operation type and the fourth field
+ specifies the number of bytes.
+
+ These numbers should roughly be same as blkio.io_service_bytes as
+ updated by CFQ. The difference between two is that
+ blkio.io_service_bytes will not be updated if CFQ is not operating
+ on request queue.
+
+Common files among various policies
+-----------------------------------
- blkio.reset_stats
- Writing an int to this file will result in resetting all the stats
for that cgroup.
diff --git a/Documentation/cputopology.txt b/Documentation/cputopology.txt
index f1c5c4bccd3e..902d3151f527 100644
--- a/Documentation/cputopology.txt
+++ b/Documentation/cputopology.txt
@@ -14,25 +14,39 @@ to /proc/cpuinfo.
identifier (rather than the kernel's). The actual value is
architecture and platform dependent.
-3) /sys/devices/system/cpu/cpuX/topology/thread_siblings:
+3) /sys/devices/system/cpu/cpuX/topology/book_id:
+
+ the book ID of cpuX. Typically it is the hardware platform's
+ identifier (rather than the kernel's). The actual value is
+ architecture and platform dependent.
+
+4) /sys/devices/system/cpu/cpuX/topology/thread_siblings:
internel kernel map of cpuX's hardware threads within the same
core as cpuX
-4) /sys/devices/system/cpu/cpuX/topology/core_siblings:
+5) /sys/devices/system/cpu/cpuX/topology/core_siblings:
internal kernel map of cpuX's hardware threads within the same
physical_package_id.
+6) /sys/devices/system/cpu/cpuX/topology/book_siblings:
+
+ internal kernel map of cpuX's hardware threads within the same
+ book_id.
+
To implement it in an architecture-neutral way, a new source file,
-drivers/base/topology.c, is to export the 4 attributes.
+drivers/base/topology.c, is to export the 4 or 6 attributes. The two book
+related sysfs files will only be created if CONFIG_SCHED_BOOK is selected.
For an architecture to support this feature, it must define some of
these macros in include/asm-XXX/topology.h:
#define topology_physical_package_id(cpu)
#define topology_core_id(cpu)
+#define topology_book_id(cpu)
#define topology_thread_cpumask(cpu)
#define topology_core_cpumask(cpu)
+#define topology_book_cpumask(cpu)
The type of **_id is int.
The type of siblings is (const) struct cpumask *.
@@ -45,6 +59,9 @@ not defined by include/asm-XXX/topology.h:
3) thread_siblings: just the given CPU
4) core_siblings: just the given CPU
+For architectures that don't support books (CONFIG_SCHED_BOOK) there are no
+default definitions for topology_book_id() and topology_book_cpumask().
+
Additionally, CPU topology information is provided under
/sys/devices/system/cpu and includes these files. The internal
source for the output is in brackets ("[]").
diff --git a/Documentation/devices.txt b/Documentation/devices.txt
index d0d1df6cb5de..c58abf1ccc71 100644
--- a/Documentation/devices.txt
+++ b/Documentation/devices.txt
@@ -239,6 +239,7 @@ Your cooperation is appreciated.
0 = /dev/tty Current TTY device
1 = /dev/console System console
2 = /dev/ptmx PTY master multiplex
+ 3 = /dev/ttyprintk User messages via printk TTY device
64 = /dev/cua0 Callout device for ttyS0
...
255 = /dev/cua191 Callout device for ttyS191
@@ -2553,7 +2554,10 @@ Your cooperation is appreciated.
175 = /dev/usb/legousbtower15 16th USB Legotower device
176 = /dev/usb/usbtmc1 First USB TMC device
...
- 192 = /dev/usb/usbtmc16 16th USB TMC device
+ 191 = /dev/usb/usbtmc16 16th USB TMC device
+ 192 = /dev/usb/yurex1 First USB Yurex device
+ ...
+ 209 = /dev/usb/yurex16 16th USB Yurex device
240 = /dev/usb/dabusb0 First daubusb device
...
243 = /dev/usb/dabusb3 Fourth dabusb device
diff --git a/Documentation/dynamic-debug-howto.txt b/Documentation/dynamic-debug-howto.txt
index 674c5663d346..58ea64a96165 100644
--- a/Documentation/dynamic-debug-howto.txt
+++ b/Documentation/dynamic-debug-howto.txt
@@ -24,7 +24,7 @@ Dynamic debug has even more useful features:
read to display the complete list of known debug statements, to help guide you
Controlling dynamic debug Behaviour
-===============================
+===================================
The behaviour of pr_debug()/dev_debug()s are controlled via writing to a
control file in the 'debugfs' filesystem. Thus, you must first mount the debugfs
@@ -212,6 +212,26 @@ Note the regexp ^[-+=][scp]+$ matches a flags specification.
Note also that there is no convenient syntax to remove all
the flags at once, you need to use "-psc".
+
+Debug messages during boot process
+==================================
+
+To be able to activate debug messages during the boot process,
+even before userspace and debugfs exists, use the boot parameter:
+ddebug_query="QUERY"
+
+QUERY follows the syntax described above, but must not exceed 1023
+characters. The enablement of debug messages is done as an arch_initcall.
+Thus you can enable debug messages in all code processed after this
+arch_initcall via this boot parameter.
+On an x86 system for example ACPI enablement is a subsys_initcall and
+ddebug_query="file ec.c +p"
+will show early Embedded Controller transactions during ACPI setup if
+your machine (typically a laptop) has an Embedded Controller.
+PCI (or other devices) initialization also is a hot candidate for using
+this boot parameter for debugging purposes.
+
+
Examples
========
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 842aa9de84a6..9961f1564d22 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -386,34 +386,6 @@ Who: Tejun Heo <tj@kernel.org>
----------------------------
-What: Support for VMware's guest paravirtuliazation technique [VMI] will be
- dropped.
-When: 2.6.37 or earlier.
-Why: With the recent innovations in CPU hardware acceleration technologies
- from Intel and AMD, VMware ran a few experiments to compare these
- techniques to guest paravirtualization technique on VMware's platform.
- These hardware assisted virtualization techniques have outperformed the
- performance benefits provided by VMI in most of the workloads. VMware
- expects that these hardware features will be ubiquitous in a couple of
- years, as a result, VMware has started a phased retirement of this
- feature from the hypervisor. We will be removing this feature from the
- Kernel too. Right now we are targeting 2.6.37 but can retire earlier if
- technical reasons (read opportunity to remove major chunk of pvops)
- arise.
-
- Please note that VMI has always been an optimization and non-VMI kernels
- still work fine on VMware's platform.
- Latest versions of VMware's product which support VMI are,
- Workstation 7.0 and VSphere 4.0 on ESX side, future maintainence
- releases for these products will continue supporting VMI.
-
- For more details about VMI retirement take a look at this,
- http://blogs.vmware.com/guestosguide/2009/09/vmi-retirement.html
-
-Who: Alok N Kataria <akataria@vmware.com>
-
-----------------------------
-
What: Support for lcd_switch and display_get in asus-laptop driver
When: March 2010
Why: These two features use non-standard interfaces. There are the
@@ -564,3 +536,12 @@ Who: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
----------------------------
+What: iwlwifi disable_hw_scan module parameters
+When: 2.6.40
+Why: Hareware scan is the prefer method for iwlwifi devices for
+ scanning operation. Remove software scan support for all the
+ iwlwifi devices.
+
+Who: Wey-Yi Guy <wey-yi.w.guy@intel.com>
+
+----------------------------
diff --git a/Documentation/filesystems/ocfs2.txt b/Documentation/filesystems/ocfs2.txt
index 1f7ae144f6d8..5393e6611691 100644
--- a/Documentation/filesystems/ocfs2.txt
+++ b/Documentation/filesystems/ocfs2.txt
@@ -87,3 +87,10 @@ dir_resv_level= (*) By default, directory reservations will scale with file
reservations - users should rarely need to change this
value. If allocation reservations are turned off, this
option will have no effect.
+coherency=full (*) Disallow concurrent O_DIRECT writes, cluster inode
+ lock will be taken to force other nodes drop cache,
+ therefore full cluster coherency is guaranteed even
+ for O_DIRECT writes.
+coherency=buffered Allow concurrent O_DIRECT writes without EX lock among
+ nodes, which gains high performance at risk of getting
+ stale data on other nodes.
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 8dd7248508a9..4cd8b86e00ea 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -43,10 +43,11 @@ parameter is applicable:
AVR32 AVR32 architecture is enabled.
AX25 Appropriate AX.25 support is enabled.
BLACKFIN Blackfin architecture is enabled.
- DRM Direct Rendering Management support is enabled.
EDD BIOS Enhanced Disk Drive Services (EDD) is enabled
EFI EFI Partitioning (GPT) is enabled
EIDE EIDE/ATAPI support is enabled.
+ DRM Direct Rendering Management support is enabled.
+ DYNAMIC_DEBUG Build in debug messages and enable them at runtime
FB The frame buffer device is enabled.
GCOV GCOV profiling is enabled.
HW Appropriate hardware is enabled.
@@ -455,7 +456,7 @@ and is between 256 and 4096 characters. It is defined in the file
[ARM] imx_timer1,OSTS,netx_timer,mpu_timer2,
pxa_timer,timer3,32k_counter,timer0_1
[AVR32] avr32
- [X86-32] pit,hpet,tsc,vmi-timer;
+ [X86-32] pit,hpet,tsc;
scx200_hrt on Geode; cyclone on IBM x440
[MIPS] MIPS
[PARISC] cr16
@@ -570,6 +571,10 @@ and is between 256 and 4096 characters. It is defined in the file
Format: <port#>,<type>
See also Documentation/input/joystick-parport.txt
+ ddebug_query= [KNL,DYNAMIC_DEBUG] Enable debug messages at early boot
+ time. See Documentation/dynamic-debug-howto.txt for
+ details.
+
debug [KNL] Enable kernel debugging (events log level).
debug_locks_verbose=
@@ -2153,6 +2158,11 @@ and is between 256 and 4096 characters. It is defined in the file
Reserves a hole at the top of the kernel virtual
address space.
+ reservelow= [X86]
+ Format: nn[K]
+ Set the amount of memory to reserve for BIOS at
+ the bottom of the address space.
+
reset_devices [KNL] Force drivers to reset the underlying device
during initialization.
@@ -2165,6 +2175,11 @@ and is between 256 and 4096 characters. It is defined in the file
in <PAGE_SIZE> units (needed only for swap files).
See Documentation/power/swsusp-and-swap-files.txt
+ hibernate= [HIBERNATION]
+ noresume Don't check if there's a hibernation image
+ present during boot.
+ nocompress Don't compress/decompress hibernation images.
+
retain_initrd [RAM] Keep initrd memory after extraction
rhash_entries= [KNL,NET]
@@ -2360,6 +2375,15 @@ and is between 256 and 4096 characters. It is defined in the file
switches= [HW,M68k]
+ sysfs.deprecated=0|1 [KNL]
+ Enable/disable old style sysfs layout for old udev
+ on older distributions. When this option is enabled
+ very new udev will not work anymore. When this option
+ is disabled (or CONFIG_SYSFS_DEPRECATED not compiled)
+ in older udev will not work anymore.
+ Default depends on CONFIG_SYSFS_DEPRECATED_V2 set in
+ the kernel configuration.
+
sysrq_always_enabled
[KNL]
Ignore sysrq setting - this boot parameter will
@@ -2435,6 +2459,10 @@ and is between 256 and 4096 characters. It is defined in the file
disables clocksource verification at runtime.
Used to enable high-resolution timer mode on older
hardware, and in virtualized environment.
+ [x86] noirqtime: Do not use TSC to do irq accounting.
+ Used to run time disable IRQ_TIME_ACCOUNTING on any
+ platforms where RDTSC is slow and this accounting
+ can add overhead.
turbografx.map[2|3]= [HW,JOY]
TurboGraFX parallel port interface
diff --git a/Documentation/kprobes.txt b/Documentation/kprobes.txt
index 1762b81fcdf2..741fe66d6eca 100644
--- a/Documentation/kprobes.txt
+++ b/Documentation/kprobes.txt
@@ -542,9 +542,11 @@ Kprobes does not use mutexes or allocate memory except during
registration and unregistration.
Probe handlers are run with preemption disabled. Depending on the
-architecture, handlers may also run with interrupts disabled. In any
-case, your handler should not yield the CPU (e.g., by attempting to
-acquire a semaphore).
+architecture and optimization state, handlers may also run with
+interrupts disabled (e.g., kretprobe handlers and optimized kprobe
+handlers run without interrupt disabled on x86/x86-64). In any case,
+your handler should not yield the CPU (e.g., by attempting to acquire
+a semaphore).
Since a return probe is implemented by replacing the return
address with the trampoline's address, stack backtraces and calls
diff --git a/Documentation/lguest/lguest.c b/Documentation/lguest/lguest.c
index 8a6a8c6d4980..dc73bc54cc4e 100644
--- a/Documentation/lguest/lguest.c
+++ b/Documentation/lguest/lguest.c
@@ -1640,15 +1640,6 @@ static void blk_request(struct virtqueue *vq)
off = out->sector * 512;
/*
- * The block device implements "barriers", where the Guest indicates
- * that it wants all previous writes to occur before this write. We
- * don't have a way of asking our kernel to do a barrier, so we just
- * synchronize all the data in the file. Pretty poor, no?
- */
- if (out->type & VIRTIO_BLK_T_BARRIER)
- fdatasync(vblk->fd);
-
- /*
* In general the virtio block driver is allowed to try SCSI commands.
* It'd be nice if we supported eject, for example, but we don't.
*/
@@ -1680,6 +1671,13 @@ static void blk_request(struct virtqueue *vq)
/* Die, bad Guest, die. */
errx(1, "Write past end %llu+%u", off, ret);
}
+
+ wlen = sizeof(*in);
+ *in = (ret >= 0 ? VIRTIO_BLK_S_OK : VIRTIO_BLK_S_IOERR);
+ } else if (out->type & VIRTIO_BLK_T_FLUSH) {
+ /* Flush */
+ ret = fdatasync(vblk->fd);
+ verbose("FLUSH fdatasync: %i\n", ret);
wlen = sizeof(*in);
*in = (ret >= 0 ? VIRTIO_BLK_S_OK : VIRTIO_BLK_S_IOERR);
} else {
@@ -1703,15 +1701,6 @@ static void blk_request(struct virtqueue *vq)
}
}
- /*
- * OK, so we noted that it was pretty poor to use an fdatasync as a
- * barrier. But Christoph Hellwig points out that we need a sync
- * *afterwards* as well: "Barriers specify no reordering to the front
- * or the back." And Jens Axboe confirmed it, so here we are:
- */
- if (out->type & VIRTIO_BLK_T_BARRIER)
- fdatasync(vblk->fd);
-
/* Finished that request. */
add_used(vq, head, wlen);
}
@@ -1736,8 +1725,8 @@ static void setup_block_file(const char *filename)
vblk->fd = open_or_die(filename, O_RDWR|O_LARGEFILE);
vblk->len = lseek64(vblk->fd, 0, SEEK_END);
- /* We support barriers. */
- add_feature(dev, VIRTIO_BLK_F_BARRIER);
+ /* We support FLUSH. */
+ add_feature(dev, VIRTIO_BLK_F_FLUSH);
/* Tell Guest how many sectors this device has. */
conf.capacity = cpu_to_le64(vblk->len / 512);
diff --git a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt
index d2b62b71b617..5dc638791d97 100644
--- a/Documentation/networking/bonding.txt
+++ b/Documentation/networking/bonding.txt
@@ -765,6 +765,14 @@ xmit_hash_policy
does not exist, and the layer2 policy is the only policy. The
layer2+3 value was added for bonding version 3.2.2.
+resend_igmp
+
+ Specifies the number of IGMP membership reports to be issued after
+ a failover event. One membership report is issued immediately after
+ the failover, subsequent packets are sent in each 200ms interval.
+
+ The valid range is 0 - 255; the default value is 1. This option
+ was added for bonding version 3.7.0.
3. Configuring Bonding Devices
==============================
diff --git a/Documentation/networking/can.txt b/Documentation/networking/can.txt
index cd79735013f9..5b04b67ddca2 100644
--- a/Documentation/networking/can.txt
+++ b/Documentation/networking/can.txt
@@ -22,6 +22,7 @@ This file contains
4.1.2 RAW socket option CAN_RAW_ERR_FILTER
4.1.3 RAW socket option CAN_RAW_LOOPBACK
4.1.4 RAW socket option CAN_RAW_RECV_OWN_MSGS
+ 4.1.5 RAW socket returned message flags
4.2 Broadcast Manager protocol sockets (SOCK_DGRAM)
4.3 connected transport protocols (SOCK_SEQPACKET)
4.4 unconnected transport protocols (SOCK_DGRAM)
@@ -471,6 +472,17 @@ solution for a couple of reasons:
setsockopt(s, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS,
&recv_own_msgs, sizeof(recv_own_msgs));
+ 4.1.5 RAW socket returned message flags
+
+ When using recvmsg() call, the msg->msg_flags may contain following flags:
+
+ MSG_DONTROUTE: set when the received frame was created on the local host.
+
+ MSG_CONFIRM: set when the frame was sent via the socket it is received on.
+ This flag can be interpreted as a 'transmission confirmation' when the
+ CAN driver supports the echo of frames on driver level, see 3.2 and 6.2.
+ In order to receive such messages, CAN_RAW_RECV_OWN_MSGS must be set.
+
4.2 Broadcast Manager protocol sockets (SOCK_DGRAM)
4.3 connected transport protocols (SOCK_SEQPACKET)
4.4 unconnected transport protocols (SOCK_DGRAM)
diff --git a/Documentation/networking/dccp.txt b/Documentation/networking/dccp.txt
index a62fdf7a6bff..271d524a4c8d 100644
--- a/Documentation/networking/dccp.txt
+++ b/Documentation/networking/dccp.txt
@@ -1,18 +1,20 @@
DCCP protocol
-============
+=============
Contents
========
-
- Introduction
- Missing features
- Socket options
+- Sysctl variables
+- IOCTLs
+- Other tunables
- Notes
+
Introduction
============
-
Datagram Congestion Control Protocol (DCCP) is an unreliable, connection
oriented protocol designed to solve issues present in UDP and TCP, particularly
for real-time and multimedia (streaming) traffic.
@@ -29,9 +31,9 @@ It has a base protocol and pluggable congestion control IDs (CCIDs).
DCCP is a Proposed Standard (RFC 2026), and the homepage for DCCP as a protocol
is at http://www.ietf.org/html.charters/dccp-charter.html
+
Missing features
================
-
The Linux DCCP implementation does not currently support all the features that are
specified in RFCs 4340...42.
@@ -45,7 +47,6 @@ http://linux-net.osdl.org/index.php/DCCP_Testing#Experimental_DCCP_source_tree
Socket options
==============
-
DCCP_SOCKOPT_SERVICE sets the service. The specification mandates use of
service codes (RFC 4340, sec. 8.1.2); if this socket option is not set,
the socket will fall back to 0 (which means that no meaningful service code
@@ -112,6 +113,7 @@ DCCP_SOCKOPT_CCID_TX_INFO
On unidirectional connections it is useful to close the unused half-connection
via shutdown (SHUT_WR or SHUT_RD): this will reduce per-packet processing costs.
+
Sysctl variables
================
Several DCCP default parameters can be managed by the following sysctls
@@ -155,15 +157,30 @@ sync_ratelimit = 125 ms
sequence-invalid packets on the same socket (RFC 4340, 7.5.4). The unit
of this parameter is milliseconds; a value of 0 disables rate-limiting.
+
IOCTLS
======
FIONREAD
Works as in udp(7): returns in the `int' argument pointer the size of
the next pending datagram in bytes, or 0 when no datagram is pending.
+
+Other tunables
+==============
+Per-route rto_min support
+ CCID-2 supports the RTAX_RTO_MIN per-route setting for the minimum value
+ of the RTO timer. This setting can be modified via the 'rto_min' option
+ of iproute2; for example:
+ > ip route change 10.0.0.0/24 rto_min 250j dev wlan0
+ > ip route add 10.0.0.254/32 rto_min 800j dev wlan0
+ > ip route show dev wlan0
+ CCID-3 also supports the rto_min setting: it is used to define the lower
+ bound for the expiry of the nofeedback timer. This can be useful on LANs
+ with very low RTTs (e.g., loopback, Gbit ethernet).
+
+
Notes
=====
-
DCCP does not travel through NAT successfully at present on many boxes. This is
because the checksum covers the pseudo-header as per TCP and UDP. Linux NAT
support for DCCP has been added.
diff --git a/Documentation/networking/e1000.txt b/Documentation/networking/e1000.txt
index 2df71861e578..d9271e74e488 100644
--- a/Documentation/networking/e1000.txt
+++ b/Documentation/networking/e1000.txt
@@ -1,82 +1,35 @@
Linux* Base Driver for the Intel(R) PRO/1000 Family of Adapters
===============================================================
-September 26, 2006
-
+Intel Gigabit Linux driver.
+Copyright(c) 1999 - 2010 Intel Corporation.
Contents
========
-- In This Release
- Identifying Your Adapter
-- Building and Installation
- Command Line Parameters
- Speed and Duplex Configuration
- Additional Configurations
-- Known Issues
- Support
-
-In This Release
-===============
-
-This file describes the Linux* Base Driver for the Intel(R) PRO/1000 Family
-of Adapters. This driver includes support for Itanium(R)2-based systems.
-
-For questions related to hardware requirements, refer to the documentation
-supplied with your Intel PRO/1000 adapter. All hardware requirements listed
-apply to use with Linux.
-
-The following features are now available in supported kernels:
- - Native VLANs
- - Channel Bonding (teaming)
- - SNMP
-
-Channel Bonding documentation can be found in the Linux kernel source:
-/Documentation/networking/bonding.txt
-
-The driver information previously displayed in the /proc filesystem is not
-supported in this release. Alternatively, you can use ethtool (version 1.6
-or later), lspci, and ifconfig to obtain the same information.
-
-Instructions on updating ethtool can be found in the section "Additional
-Configurations" later in this document.
-
-NOTE: The Intel(R) 82562v 10/100 Network Connection only provides 10/100
-support.
-
-
Identifying Your Adapter
========================
For more information on how to identify your adapter, go to the Adapter &
Driver ID Guide at:
- http://support.intel.com/support/network/adapter/pro100/21397.htm
+ http://support.intel.com/support/go/network/adapter/idguide.htm
For the latest Intel network drivers for Linux, refer to the following
website. In the search field, enter your adapter name or type, or use the
networking link on the left to search for your adapter:
- http://downloadfinder.intel.com/scripts-df/support_intel.asp
-
+ http://support.intel.com/support/go/network/adapter/home.htm
Command Line Parameters
=======================
-If the driver is built as a module, the following optional parameters
-are used by entering them on the command line with the modprobe command
-using this syntax:
-
- modprobe e1000 [<option>=<VAL1>,<VAL2>,...]
-
-For example, with two PRO/1000 PCI adapters, entering:
-
- modprobe e1000 TxDescriptors=80,128
-
-loads the e1000 driver with 80 TX descriptors for the first adapter and
-128 TX descriptors for the second adapter.
-
The default value for each parameter is generally the recommended setting,
unless otherwise noted.
@@ -89,10 +42,6 @@ NOTES: For more information about the AutoNeg, Duplex, and Speed
parameters, see the application note at:
http://www.intel.com/design/network/applnots/ap450.htm
- A descriptor describes a data buffer and attributes related to
- the data buffer. This information is accessed by the hardware.
-
-
AutoNeg
-------
(Supported only on adapters with copper connections)
@@ -106,7 +55,6 @@ Duplex parameters must not be specified.
NOTE: Refer to the Speed and Duplex section of this readme for more
information on the AutoNeg parameter.
-
Duplex
------
(Supported only on adapters with copper connections)
@@ -119,7 +67,6 @@ set to auto-negotiate, the board auto-detects the correct duplex. If the
link partner is forced (either full or half), Duplex defaults to half-
duplex.
-
FlowControl
-----------
Valid Range: 0-3 (0=none, 1=Rx only, 2=Tx only, 3=Rx&Tx)
@@ -128,16 +75,16 @@ Default Value: Reads flow control settings from the EEPROM
This parameter controls the automatic generation(Tx) and response(Rx)
to Ethernet PAUSE frames.
-
InterruptThrottleRate
---------------------
(not supported on Intel(R) 82542, 82543 or 82544-based adapters)
-Valid Range: 0,1,3,100-100000 (0=off, 1=dynamic, 3=dynamic conservative)
+Valid Range: 0,1,3,4,100-100000 (0=off, 1=dynamic, 3=dynamic conservative,
+ 4=simplified balancing)
Default Value: 3
The driver can limit the amount of interrupts per second that the adapter
-will generate for incoming packets. It does this by writing a value to the
-adapter that is based on the maximum amount of interrupts that the adapter
+will generate for incoming packets. It does this by writing a value to the
+adapter that is based on the maximum amount of interrupts that the adapter
will generate per second.
Setting InterruptThrottleRate to a value greater or equal to 100
@@ -146,37 +93,43 @@ per second, even if more packets have come in. This reduces interrupt
load on the system and can lower CPU utilization under heavy load,
but will increase latency as packets are not processed as quickly.
-The default behaviour of the driver previously assumed a static
-InterruptThrottleRate value of 8000, providing a good fallback value for
-all traffic types,but lacking in small packet performance and latency.
-The hardware can handle many more small packets per second however, and
+The default behaviour of the driver previously assumed a static
+InterruptThrottleRate value of 8000, providing a good fallback value for
+all traffic types,but lacking in small packet performance and latency.
+The hardware can handle many more small packets per second however, and
for this reason an adaptive interrupt moderation algorithm was implemented.
Since 7.3.x, the driver has two adaptive modes (setting 1 or 3) in which
-it dynamically adjusts the InterruptThrottleRate value based on the traffic
+it dynamically adjusts the InterruptThrottleRate value based on the traffic
that it receives. After determining the type of incoming traffic in the last
-timeframe, it will adjust the InterruptThrottleRate to an appropriate value
+timeframe, it will adjust the InterruptThrottleRate to an appropriate value
for that traffic.
The algorithm classifies the incoming traffic every interval into
-classes. Once the class is determined, the InterruptThrottleRate value is
-adjusted to suit that traffic type the best. There are three classes defined:
+classes. Once the class is determined, the InterruptThrottleRate value is
+adjusted to suit that traffic type the best. There are three classes defined:
"Bulk traffic", for large amounts of packets of normal size; "Low latency",
for small amounts of traffic and/or a significant percentage of small
-packets; and "Lowest latency", for almost completely small packets or
+packets; and "Lowest latency", for almost completely small packets or
minimal traffic.
-In dynamic conservative mode, the InterruptThrottleRate value is set to 4000
-for traffic that falls in class "Bulk traffic". If traffic falls in the "Low
-latency" or "Lowest latency" class, the InterruptThrottleRate is increased
+In dynamic conservative mode, the InterruptThrottleRate value is set to 4000
+for traffic that falls in class "Bulk traffic". If traffic falls in the "Low
+latency" or "Lowest latency" class, the InterruptThrottleRate is increased
stepwise to 20000. This default mode is suitable for most applications.
For situations where low latency is vital such as cluster or
grid computing, the algorithm can reduce latency even more when
InterruptThrottleRate is set to mode 1. In this mode, which operates
-the same as mode 3, the InterruptThrottleRate will be increased stepwise to
+the same as mode 3, the InterruptThrottleRate will be increased stepwise to
70000 for traffic in class "Lowest latency".
+In simplified mode the interrupt rate is based on the ratio of Tx and
+Rx traffic. If the bytes per second rate is approximately equal, the
+interrupt rate will drop as low as 2000 interrupts per second. If the
+traffic is mostly transmit or mostly receive, the interrupt rate could
+be as high as 8000.
+
Setting InterruptThrottleRate to 0 turns off any interrupt moderation
and may improve small packet latency, but is generally not suitable
for bulk throughput traffic.
@@ -212,8 +165,6 @@ NOTE: When e1000 is loaded with default settings and multiple adapters
be platform-specific. If CPU utilization is not a concern, use
RX_POLLING (NAPI) and default driver settings.
-
-
RxDescriptors
-------------
Valid Range: 80-256 for 82542 and 82543-based adapters
@@ -225,15 +176,14 @@ by the driver. Increasing this value allows the driver to buffer more
incoming packets, at the expense of increased system memory utilization.
Each descriptor is 16 bytes. A receive buffer is also allocated for each
-descriptor and can be either 2048, 4096, 8192, or 16384 bytes, depending
+descriptor and can be either 2048, 4096, 8192, or 16384 bytes, depending
on the MTU setting. The maximum MTU size is 16110.
-NOTE: MTU designates the frame size. It only needs to be set for Jumbo
- Frames. Depending on the available system resources, the request
- for a higher number of receive descriptors may be denied. In this
+NOTE: MTU designates the frame size. It only needs to be set for Jumbo
+ Frames. Depending on the available system resources, the request
+ for a higher number of receive descriptors may be denied. In this
case, use a lower number.
-
RxIntDelay
----------
Valid Range: 0-65535 (0=off)
@@ -254,7 +204,6 @@ CAUTION: When setting RxIntDelay to a value other than 0, adapters may
restoring the network connection. To eliminate the potential
for the hang ensure that RxIntDelay is set to 0.
-
RxAbsIntDelay
-------------
(This parameter is supported only on 82540, 82545 and later adapters.)
@@ -268,7 +217,6 @@ packet is received within the set amount of time. Proper tuning,
along with RxIntDelay, may improve traffic throughput in specific network
conditions.
-
Speed
-----
(This parameter is supported only on adapters with copper connections.)
@@ -280,7 +228,6 @@ Speed forces the line speed to the specified value in megabits per second
partner is set to auto-negotiate, the board will auto-detect the correct
speed. Duplex should also be set when Speed is set to either 10 or 100.
-
TxDescriptors
-------------
Valid Range: 80-256 for 82542 and 82543-based adapters
@@ -295,6 +242,36 @@ NOTE: Depending on the available system resources, the request for a
higher number of transmit descriptors may be denied. In this case,
use a lower number.
+TxDescriptorStep
+----------------
+Valid Range: 1 (use every Tx Descriptor)
+ 4 (use every 4th Tx Descriptor)
+
+Default Value: 1 (use every Tx Descriptor)
+
+On certain non-Intel architectures, it has been observed that intense TX
+traffic bursts of short packets may result in an improper descriptor
+writeback. If this occurs, the driver will report a "TX Timeout" and reset
+the adapter, after which the transmit flow will restart, though data may
+have stalled for as much as 10 seconds before it resumes.
+
+The improper writeback does not occur on the first descriptor in a system
+memory cache-line, which is typically 32 bytes, or 4 descriptors long.
+
+Setting TxDescriptorStep to a value of 4 will ensure that all TX descriptors
+are aligned to the start of a system memory cache line, and so this problem
+will not occur.
+
+NOTES: Setting TxDescriptorStep to 4 effectively reduces the number of
+ TxDescriptors available for transmits to 1/4 of the normal allocation.
+ This has a possible negative performance impact, which may be
+ compensated for by allocating more descriptors using the TxDescriptors
+ module parameter.
+
+ There are other conditions which may result in "TX Timeout", which will
+ not be resolved by the use of the TxDescriptorStep parameter. As the
+ issue addressed by this parameter has never been observed on Intel
+ Architecture platforms, it should not be used on Intel platforms.
TxIntDelay
----------
@@ -307,7 +284,6 @@ efficiency if properly tuned for specific network traffic. If the
system is reporting dropped transmits, this value may be set too high
causing the driver to run out of available transmit descriptors.
-
TxAbsIntDelay
-------------
(This parameter is supported only on 82540, 82545 and later adapters.)
@@ -330,6 +306,35 @@ Default Value: 1
A value of '1' indicates that the driver should enable IP checksum
offload for received packets (both UDP and TCP) to the adapter hardware.
+Copybreak
+---------
+Valid Range: 0-xxxxxxx (0=off)
+Default Value: 256
+Usage: insmod e1000.ko copybreak=128
+
+Driver copies all packets below or equaling this size to a fresh Rx
+buffer before handing it up the stack.
+
+This parameter is different than other parameters, in that it is a
+single (not 1,1,1 etc.) parameter applied to all driver instances and
+it is also available during runtime at
+/sys/module/e1000/parameters/copybreak
+
+SmartPowerDownEnable
+--------------------
+Valid Range: 0-1
+Default Value: 0 (disabled)
+
+Allows PHY to turn off in lower power states. The user can turn off
+this parameter in supported chipsets.
+
+KumeranLockLoss
+---------------
+Valid Range: 0-1
+Default Value: 1 (enabled)
+
+This workaround skips resetting the PHY at shutdown for the initial
+silicon releases of ICH8 systems.
Speed and Duplex Configuration
==============================
@@ -385,40 +390,9 @@ If the link partner is forced to a specific speed and duplex, then this
parameter should not be used. Instead, use the Speed and Duplex parameters
previously mentioned to force the adapter to the same speed and duplex.
-
Additional Configurations
=========================
- Configuring the Driver on Different Distributions
- -------------------------------------------------
- Configuring a network driver to load properly when the system is started
- is distribution dependent. Typically, the configuration process involves
- adding an alias line to /etc/modules.conf or /etc/modprobe.conf as well
- as editing other system startup scripts and/or configuration files. Many
- popular Linux distributions ship with tools to make these changes for you.
- To learn the proper way to configure a network device for your system,
- refer to your distribution documentation. If during this process you are
- asked for the driver or module name, the name for the Linux Base Driver
- for the Intel(R) PRO/1000 Family of Adapters is e1000.
-
- As an example, if you install the e1000 driver for two PRO/1000 adapters
- (eth0 and eth1) and set the speed and duplex to 10full and 100half, add
- the following to modules.conf or or modprobe.conf:
-
- alias eth0 e1000
- alias eth1 e1000
- options e1000 Speed=10,100 Duplex=2,1
-
- Viewing Link Messages
- ---------------------
- Link messages will not be displayed to the console if the distribution is
- restricting system messages. In order to see network driver link messages
- on your console, set dmesg to eight by entering the following:
-
- dmesg -n 8
-
- NOTE: This setting is not saved across reboots.
-
Jumbo Frames
------------
Jumbo Frames support is enabled by changing the MTU to a value larger than
@@ -437,9 +411,11 @@ Additional Configurations
setting in a different location.
Notes:
-
- - To enable Jumbo Frames, increase the MTU size on the interface beyond
- 1500.
+ Degradation in throughput performance may be observed in some Jumbo frames
+ environments. If this is observed, increasing the application's socket buffer
+ size and/or increasing the /proc/sys/net/ipv4/tcp_*mem entry values may help.
+ See the specific application manual and /usr/src/linux*/Documentation/
+ networking/ip-sysctl.txt for more details.
- The maximum MTU setting for Jumbo Frames is 16110. This value coincides
with the maximum Jumbo Frames size of 16128.
@@ -447,40 +423,11 @@ Additional Configurations
- Using Jumbo Frames at 10 or 100 Mbps may result in poor performance or
loss of link.
- - Some Intel gigabit adapters that support Jumbo Frames have a frame size
- limit of 9238 bytes, with a corresponding MTU size limit of 9216 bytes.
- The adapters with this limitation are based on the Intel(R) 82571EB,
- 82572EI, 82573L and 80003ES2LAN controller. These correspond to the
- following product names:
- Intel(R) PRO/1000 PT Server Adapter
- Intel(R) PRO/1000 PT Desktop Adapter
- Intel(R) PRO/1000 PT Network Connection
- Intel(R) PRO/1000 PT Dual Port Server Adapter
- Intel(R) PRO/1000 PT Dual Port Network Connection
- Intel(R) PRO/1000 PF Server Adapter
- Intel(R) PRO/1000 PF Network Connection
- Intel(R) PRO/1000 PF Dual Port Server Adapter
- Intel(R) PRO/1000 PB Server Connection
- Intel(R) PRO/1000 PL Network Connection
- Intel(R) PRO/1000 EB Network Connection with I/O Acceleration
- Intel(R) PRO/1000 EB Backplane Connection with I/O Acceleration
- Intel(R) PRO/1000 PT Quad Port Server Adapter
-
- Adapters based on the Intel(R) 82542 and 82573V/E controller do not
support Jumbo Frames. These correspond to the following product names:
Intel(R) PRO/1000 Gigabit Server Adapter
Intel(R) PRO/1000 PM Network Connection
- - The following adapters do not support Jumbo Frames:
- Intel(R) 82562V 10/100 Network Connection
- Intel(R) 82566DM Gigabit Network Connection
- Intel(R) 82566DC Gigabit Network Connection
- Intel(R) 82566MM Gigabit Network Connection
- Intel(R) 82566MC Gigabit Network Connection
- Intel(R) 82562GT 10/100 Network Connection
- Intel(R) 82562G 10/100 Network Connection
-
-
Ethtool
-------
The driver utilizes the ethtool interface for driver configuration and
@@ -490,142 +437,14 @@ Additional Configurations
The latest release of ethtool can be found from
http://sourceforge.net/projects/gkernel.
- NOTE: Ethtool 1.6 only supports a limited set of ethtool options. Support
- for a more complete ethtool feature set can be enabled by upgrading
- ethtool to ethtool-1.8.1.
-
Enabling Wake on LAN* (WoL)
---------------------------
- WoL is configured through the Ethtool* utility. Ethtool is included with
- all versions of Red Hat after Red Hat 7.2. For other Linux distributions,
- download and install Ethtool from the following website:
- http://sourceforge.net/projects/gkernel.
-
- For instructions on enabling WoL with Ethtool, refer to the website listed
- above.
+ WoL is configured through the Ethtool* utility.
WoL will be enabled on the system during the next shut down or reboot.
For this driver version, in order to enable WoL, the e1000 driver must be
loaded when shutting down or rebooting the system.
- Wake On LAN is only supported on port A for the following devices:
- Intel(R) PRO/1000 PT Dual Port Network Connection
- Intel(R) PRO/1000 PT Dual Port Server Connection
- Intel(R) PRO/1000 PT Dual Port Server Adapter
- Intel(R) PRO/1000 PF Dual Port Server Adapter
- Intel(R) PRO/1000 PT Quad Port Server Adapter
-
- NAPI
- ----
- NAPI (Rx polling mode) is enabled in the e1000 driver.
-
- See www.cyberus.ca/~hadi/usenix-paper.tgz for more information on NAPI.
-
-
-Known Issues
-============
-
-Dropped Receive Packets on Half-duplex 10/100 Networks
-------------------------------------------------------
-If you have an Intel PCI Express adapter running at 10mbps or 100mbps, half-
-duplex, you may observe occasional dropped receive packets. There are no
-workarounds for this problem in this network configuration. The network must
-be updated to operate in full-duplex, and/or 1000mbps only.
-
-Jumbo Frames System Requirement
--------------------------------
-Memory allocation failures have been observed on Linux systems with 64 MB
-of RAM or less that are running Jumbo Frames. If you are using Jumbo
-Frames, your system may require more than the advertised minimum
-requirement of 64 MB of system memory.
-
-Performance Degradation with Jumbo Frames
------------------------------------------
-Degradation in throughput performance may be observed in some Jumbo frames
-environments. If this is observed, increasing the application's socket
-buffer size and/or increasing the /proc/sys/net/ipv4/tcp_*mem entry values
-may help. See the specific application manual and
-/usr/src/linux*/Documentation/
-networking/ip-sysctl.txt for more details.
-
-Jumbo Frames on Foundry BigIron 8000 switch
--------------------------------------------
-There is a known issue using Jumbo frames when connected to a Foundry
-BigIron 8000 switch. This is a 3rd party limitation. If you experience
-loss of packets, lower the MTU size.
-
-Allocating Rx Buffers when Using Jumbo Frames
----------------------------------------------
-Allocating Rx buffers when using Jumbo Frames on 2.6.x kernels may fail if
-the available memory is heavily fragmented. This issue may be seen with PCI-X
-adapters or with packet split disabled. This can be reduced or eliminated
-by changing the amount of available memory for receive buffer allocation, by
-increasing /proc/sys/vm/min_free_kbytes.
-
-Multiple Interfaces on Same Ethernet Broadcast Network
-------------------------------------------------------
-Due to the default ARP behavior on Linux, it is not possible to have
-one system on two IP networks in the same Ethernet broadcast domain
-(non-partitioned switch) behave as expected. All Ethernet interfaces
-will respond to IP traffic for any IP address assigned to the system.
-This results in unbalanced receive traffic.
-
-If you have multiple interfaces in a server, either turn on ARP
-filtering by entering:
-
- echo 1 > /proc/sys/net/ipv4/conf/all/arp_filter
-(this only works if your kernel's version is higher than 2.4.5),
-
-NOTE: This setting is not saved across reboots. The configuration
-change can be made permanent by adding the line:
- net.ipv4.conf.all.arp_filter = 1
-to the file /etc/sysctl.conf
-
- or,
-
-install the interfaces in separate broadcast domains (either in
-different switches or in a switch partitioned to VLANs).
-
-82541/82547 can't link or are slow to link with some link partners
------------------------------------------------------------------
-There is a known compatibility issue with 82541/82547 and some
-low-end switches where the link will not be established, or will
-be slow to establish. In particular, these switches are known to
-be incompatible with 82541/82547:
-
- Planex FXG-08TE
- I-O Data ETG-SH8
-
-To workaround this issue, the driver can be compiled with an override
-of the PHY's master/slave setting. Forcing master or forcing slave
-mode will improve time-to-link.
-
- # make CFLAGS_EXTRA=-DE1000_MASTER_SLAVE=<n>
-
-Where <n> is:
-
- 0 = Hardware default
- 1 = Master mode
- 2 = Slave mode
- 3 = Auto master/slave
-
-Disable rx flow control with ethtool
-------------------------------------
-In order to disable receive flow control using ethtool, you must turn
-off auto-negotiation on the same command line.
-
-For example:
-
- ethtool -A eth? autoneg off rx off
-
-Unplugging network cable while ethtool -p is running
-----------------------------------------------------
-In kernel versions 2.5.50 and later (including 2.6 kernel), unplugging
-the network cable while ethtool -p is running will cause the system to
-become unresponsive to keyboard commands, except for control-alt-delete.
-Restarting the system appears to be the only remedy.
-
-
Support
=======
diff --git a/Documentation/networking/e1000e.txt b/Documentation/networking/e1000e.txt
new file mode 100644
index 000000000000..6aa048badf32
--- /dev/null
+++ b/Documentation/networking/e1000e.txt
@@ -0,0 +1,302 @@
+Linux* Driver for Intel(R) Network Connection
+===============================================================
+
+Intel Gigabit Linux driver.
+Copyright(c) 1999 - 2010 Intel Corporation.
+
+Contents
+========
+
+- Identifying Your Adapter
+- Command Line Parameters
+- Additional Configurations
+- Support
+
+Identifying Your Adapter
+========================
+
+The e1000e driver supports all PCI Express Intel(R) Gigabit Network
+Connections, except those that are 82575, 82576 and 82580-based*.
+
+* NOTE: The Intel(R) PRO/1000 P Dual Port Server Adapter is supported by
+ the e1000 driver, not the e1000e driver due to the 82546 part being used
+ behind a PCI Express bridge.
+
+For more information on how to identify your adapter, go to the Adapter &
+Driver ID Guide at:
+
+ http://support.intel.com/support/go/network/adapter/idguide.htm
+
+For the latest Intel network drivers for Linux, refer to the following
+website. In the search field, enter your adapter name or type, or use the
+networking link on the left to search for your adapter:
+
+ http://support.intel.com/support/go/network/adapter/home.htm
+
+Command Line Parameters
+=======================
+
+The default value for each parameter is generally the recommended setting,
+unless otherwise noted.
+
+NOTES: For more information about the InterruptThrottleRate,
+ RxIntDelay, TxIntDelay, RxAbsIntDelay, and TxAbsIntDelay
+ parameters, see the application note at:
+ http://www.intel.com/design/network/applnots/ap450.htm
+
+InterruptThrottleRate
+---------------------
+Valid Range: 0,1,3,4,100-100000 (0=off, 1=dynamic, 3=dynamic conservative,
+ 4=simplified balancing)
+Default Value: 3
+
+The driver can limit the amount of interrupts per second that the adapter
+will generate for incoming packets. It does this by writing a value to the
+adapter that is based on the maximum amount of interrupts that the adapter
+will generate per second.
+
+Setting InterruptThrottleRate to a value greater or equal to 100
+will program the adapter to send out a maximum of that many interrupts
+per second, even if more packets have come in. This reduces interrupt
+load on the system and can lower CPU utilization under heavy load,
+but will increase latency as packets are not processed as quickly.
+
+The driver has two adaptive modes (setting 1 or 3) in which
+it dynamically adjusts the InterruptThrottleRate value based on the traffic
+that it receives. After determining the type of incoming traffic in the last
+timeframe, it will adjust the InterruptThrottleRate to an appropriate value
+for that traffic.
+
+The algorithm classifies the incoming traffic every interval into
+classes. Once the class is determined, the InterruptThrottleRate value is
+adjusted to suit that traffic type the best. There are three classes defined:
+"Bulk traffic", for large amounts of packets of normal size; "Low latency",
+for small amounts of traffic and/or a significant percentage of small
+packets; and "Lowest latency", for almost completely small packets or
+minimal traffic.
+
+In dynamic conservative mode, the InterruptThrottleRate value is set to 4000
+for traffic that falls in class "Bulk traffic". If traffic falls in the "Low
+latency" or "Lowest latency" class, the InterruptThrottleRate is increased
+stepwise to 20000. This default mode is suitable for most applications.
+
+For situations where low latency is vital such as cluster or
+grid computing, the algorithm can reduce latency even more when
+InterruptThrottleRate is set to mode 1. In this mode, which operates
+the same as mode 3, the InterruptThrottleRate will be increased stepwise to
+70000 for traffic in class "Lowest latency".
+
+In simplified mode the interrupt rate is based on the ratio of Tx and
+Rx traffic. If the bytes per second rate is approximately equal the
+interrupt rate will drop as low as 2000 interrupts per second. If the
+traffic is mostly transmit or mostly receive, the interrupt rate could
+be as high as 8000.
+
+Setting InterruptThrottleRate to 0 turns off any interrupt moderation
+and may improve small packet latency, but is generally not suitable
+for bulk throughput traffic.
+
+NOTE: InterruptThrottleRate takes precedence over the TxAbsIntDelay and
+ RxAbsIntDelay parameters. In other words, minimizing the receive
+ and/or transmit absolute delays does not force the controller to
+ generate more interrupts than what the Interrupt Throttle Rate
+ allows.
+
+NOTE: When e1000e is loaded with default settings and multiple adapters
+ are in use simultaneously, the CPU utilization may increase non-
+ linearly. In order to limit the CPU utilization without impacting
+ the overall throughput, we recommend that you load the driver as
+ follows:
+
+ modprobe e1000e InterruptThrottleRate=3000,3000,3000
+
+ This sets the InterruptThrottleRate to 3000 interrupts/sec for
+ the first, second, and third instances of the driver. The range
+ of 2000 to 3000 interrupts per second works on a majority of
+ systems and is a good starting point, but the optimal value will
+ be platform-specific. If CPU utilization is not a concern, use
+ RX_POLLING (NAPI) and default driver settings.
+
+RxIntDelay
+----------
+Valid Range: 0-65535 (0=off)
+Default Value: 0
+
+This value delays the generation of receive interrupts in units of 1.024
+microseconds. Receive interrupt reduction can improve CPU efficiency if
+properly tuned for specific network traffic. Increasing this value adds
+extra latency to frame reception and can end up decreasing the throughput
+of TCP traffic. If the system is reporting dropped receives, this value
+may be set too high, causing the driver to run out of available receive
+descriptors.
+
+CAUTION: When setting RxIntDelay to a value other than 0, adapters may
+ hang (stop transmitting) under certain network conditions. If
+ this occurs a NETDEV WATCHDOG message is logged in the system
+ event log. In addition, the controller is automatically reset,
+ restoring the network connection. To eliminate the potential
+ for the hang ensure that RxIntDelay is set to 0.
+
+RxAbsIntDelay
+-------------
+Valid Range: 0-65535 (0=off)
+Default Value: 8
+
+This value, in units of 1.024 microseconds, limits the delay in which a
+receive interrupt is generated. Useful only if RxIntDelay is non-zero,
+this value ensures that an interrupt is generated after the initial
+packet is received within the set amount of time. Proper tuning,
+along with RxIntDelay, may improve traffic throughput in specific network
+conditions.
+
+TxIntDelay
+----------
+Valid Range: 0-65535 (0=off)
+Default Value: 8
+
+This value delays the generation of transmit interrupts in units of
+1.024 microseconds. Transmit interrupt reduction can improve CPU
+efficiency if properly tuned for specific network traffic. If the
+system is reporting dropped transmits, this value may be set too high
+causing the driver to run out of available transmit descriptors.
+
+TxAbsIntDelay
+-------------
+Valid Range: 0-65535 (0=off)
+Default Value: 32
+
+This value, in units of 1.024 microseconds, limits the delay in which a
+transmit interrupt is generated. Useful only if TxIntDelay is non-zero,
+this value ensures that an interrupt is generated after the initial
+packet is sent on the wire within the set amount of time. Proper tuning,
+along with TxIntDelay, may improve traffic throughput in specific
+network conditions.
+
+Copybreak
+---------
+Valid Range: 0-xxxxxxx (0=off)
+Default Value: 256
+
+Driver copies all packets below or equaling this size to a fresh Rx
+buffer before handing it up the stack.
+
+This parameter is different than other parameters, in that it is a
+single (not 1,1,1 etc.) parameter applied to all driver instances and
+it is also available during runtime at
+/sys/module/e1000e/parameters/copybreak
+
+SmartPowerDownEnable
+--------------------
+Valid Range: 0-1
+Default Value: 0 (disabled)
+
+Allows PHY to turn off in lower power states. The user can set this parameter
+in supported chipsets.
+
+KumeranLockLoss
+---------------
+Valid Range: 0-1
+Default Value: 1 (enabled)
+
+This workaround skips resetting the PHY at shutdown for the initial
+silicon releases of ICH8 systems.
+
+IntMode
+-------
+Valid Range: 0-2 (0=legacy, 1=MSI, 2=MSI-X)
+Default Value: 2
+
+Allows changing the interrupt mode at module load time, without requiring a
+recompile. If the driver load fails to enable a specific interrupt mode, the
+driver will try other interrupt modes, from least to most compatible. The
+interrupt order is MSI-X, MSI, Legacy. If specifying MSI (IntMode=1)
+interrupts, only MSI and Legacy will be attempted.
+
+CrcStripping
+------------
+Valid Range: 0-1
+Default Value: 1 (enabled)
+
+Strip the CRC from received packets before sending up the network stack. If
+you have a machine with a BMC enabled but cannot receive IPMI traffic after
+loading or enabling the driver, try disabling this feature.
+
+WriteProtectNVM
+---------------
+Valid Range: 0-1
+Default Value: 1 (enabled)
+
+Set the hardware to ignore all write/erase cycles to the GbE region in the
+ICHx NVM (non-volatile memory). This feature can be disabled by the
+WriteProtectNVM module parameter (enabled by default) only after a hardware
+reset, but the machine must be power cycled before trying to enable writes.
+
+Note: the kernel boot option iomem=relaxed may need to be set if the kernel
+config option CONFIG_STRICT_DEVMEM=y, if the root user wants to write the
+NVM from user space via ethtool.
+
+Additional Configurations
+=========================
+
+ Jumbo Frames
+ ------------
+ Jumbo Frames support is enabled by changing the MTU to a value larger than
+ the default of 1500. Use the ifconfig command to increase the MTU size.
+ For example:
+
+ ifconfig eth<x> mtu 9000 up
+
+ This setting is not saved across reboots.
+
+ Notes:
+
+ - The maximum MTU setting for Jumbo Frames is 9216. This value coincides
+ with the maximum Jumbo Frames size of 9234 bytes.
+
+ - Using Jumbo Frames at 10 or 100 Mbps is not supported and may result in
+ poor performance or loss of link.
+
+ - Some adapters limit Jumbo Frames sized packets to a maximum of
+ 4096 bytes and some adapters do not support Jumbo Frames.
+
+
+ Ethtool
+ -------
+ The driver utilizes the ethtool interface for driver configuration and
+ diagnostics, as well as displaying statistical information. We
+ strongly recommend downloading the latest version of Ethtool at:
+
+ http://sourceforge.net/projects/gkernel.
+
+ Speed and Duplex
+ ----------------
+ Speed and Duplex are configured through the Ethtool* utility. For
+ instructions, refer to the Ethtool man page.
+
+ Enabling Wake on LAN* (WoL)
+ ---------------------------
+ WoL is configured through the Ethtool* utility. For instructions on
+ enabling WoL with Ethtool, refer to the Ethtool man page.
+
+ WoL will be enabled on the system during the next shut down or reboot.
+ For this driver version, in order to enable WoL, the e1000e driver must be
+ loaded when shutting down or rebooting the system.
+
+ In most cases Wake On LAN is only supported on port A for multiple port
+ adapters. To verify if a port supports Wake on LAN run ethtool eth<X>.
+
+
+Support
+=======
+
+For general information, go to the Intel support website at:
+
+ www.intel.com/support/
+
+or the Intel Wired Networking project hosted by Sourceforge at:
+
+ http://sourceforge.net/projects/e1000
+
+If an issue is identified with the released source code on the supported
+kernel with a supported adapter, email the specific information related
+to the issue to e1000-devel@lists.sf.net
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index f350c69b2bb4..c7165f4cb792 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -1014,6 +1014,12 @@ conf/interface/*:
accept_ra - BOOLEAN
Accept Router Advertisements; autoconfigure using them.
+ Possible values are:
+ 0 Do not accept Router Advertisements.
+ 1 Accept Router Advertisements if forwarding is disabled.
+ 2 Overrule forwarding behaviour. Accept Router Advertisements
+ even if forwarding is enabled.
+
Functional default: enabled if local forwarding is disabled.
disabled if local forwarding is enabled.
@@ -1075,7 +1081,12 @@ forwarding - BOOLEAN
Note: It is recommended to have the same setting on all
interfaces; mixed router/host scenarios are rather uncommon.
- FALSE:
+ Possible values are:
+ 0 Forwarding disabled
+ 1 Forwarding enabled
+ 2 Forwarding enabled (Hybrid Mode)
+
+ FALSE (0):
By default, Host behaviour is assumed. This means:
@@ -1085,18 +1096,24 @@ forwarding - BOOLEAN
Advertisements (and do autoconfiguration).
4. If accept_redirects is TRUE (default), accept Redirects.
- TRUE:
+ TRUE (1):
If local forwarding is enabled, Router behaviour is assumed.
This means exactly the reverse from the above:
1. IsRouter flag is set in Neighbour Advertisements.
2. Router Solicitations are not sent.
- 3. Router Advertisements are ignored.
+ 3. Router Advertisements are ignored unless accept_ra is 2.
4. Redirects are ignored.
- Default: FALSE if global forwarding is disabled (default),
- otherwise TRUE.
+ TRUE (2):
+
+ Hybrid mode. Same behaviour as TRUE, except for:
+
+ 2. Router Solicitations are being sent when necessary.
+
+ Default: 0 (disabled) if global forwarding is disabled (default),
+ otherwise 1 (enabled).
hop_limit - INTEGER
Default Hop Limit to set.
diff --git a/Documentation/networking/ixgbevf.txt b/Documentation/networking/ixgbevf.txt
index 19015de6725f..21dd5d15b6b4 100755..100644
--- a/Documentation/networking/ixgbevf.txt
+++ b/Documentation/networking/ixgbevf.txt
@@ -1,19 +1,16 @@
Linux* Base Driver for Intel(R) Network Connection
==================================================
-November 24, 2009
+Intel Gigabit Linux driver.
+Copyright(c) 1999 - 2010 Intel Corporation.
Contents
========
-- In This Release
- Identifying Your Adapter
- Known Issues/Troubleshooting
- Support
-In This Release
-===============
-
This file describes the ixgbevf Linux* Base Driver for Intel Network
Connection.
@@ -33,7 +30,7 @@ Identifying Your Adapter
For more information on how to identify your adapter, go to the Adapter &
Driver ID Guide at:
- http://support.intel.com/support/network/sb/CS-008441.htm
+ http://support.intel.com/support/go/network/adapter/idguide.htm
Known Issues/Troubleshooting
============================
@@ -57,34 +54,3 @@ or the Intel Wired Networking project hosted by Sourceforge at:
If an issue is identified with the released source code on the supported
kernel with a supported adapter, email the specific information related
to the issue to e1000-devel@lists.sf.net
-
-License
-=======
-
-Intel 10 Gigabit Linux driver.
-Copyright(c) 1999 - 2009 Intel Corporation.
-
-This program is free software; you can redistribute it and/or modify it
-under the terms and conditions of the GNU General Public License,
-version 2, as published by the Free Software Foundation.
-
-This program is distributed in the hope it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-more details.
-
-You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc.,
-51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-
-The full GNU General Public License is included in this distribution in
-the file called "COPYING".
-
-Trademarks
-==========
-
-Intel, Itanium, and Pentium are trademarks or registered trademarks of
-Intel Corporation or its subsidiaries in the United States and other
-countries.
-
-* Other names and brands may be claimed as the property of others.
diff --git a/Documentation/networking/phonet.txt b/Documentation/networking/phonet.txt
index 6e8ce09f9c73..24ad2adba6e5 100644
--- a/Documentation/networking/phonet.txt
+++ b/Documentation/networking/phonet.txt
@@ -112,6 +112,22 @@ However, connect() and getpeername() are not supported, as they did
not seem useful with Phonet usages (could be added easily).
+Resource subscription
+---------------------
+
+A Phonet datagram socket can be subscribed to any number of 8-bits
+Phonet resources, as follow:
+
+ uint32_t res = 0xXX;
+ ioctl(fd, SIOCPNADDRESOURCE, &res);
+
+Subscription is similarly cancelled using the SIOCPNDELRESOURCE I/O
+control request, or when the socket is closed.
+
+Note that no more than one socket can be subcribed to any given
+resource at a time. If not, ioctl() will return EBUSY.
+
+
Phonet Pipe protocol
--------------------
@@ -166,6 +182,46 @@ The pipe protocol provides two socket options at the SOL_PNPIPE level:
or zero if encapsulation is off.
+Phonet Pipe-controller Implementation
+-------------------------------------
+
+Phonet Pipe-controller is enabled by selecting the CONFIG_PHONET_PIPECTRLR Kconfig
+option. It is useful when communicating with those Nokia Modems which do not
+implement Pipe controller in them e.g. Nokia Slim Modem used in ST-Ericsson
+U8500 platform.
+
+The implementation is based on the Data Connection Establishment Sequence
+depicted in 'Nokia Wireless Modem API - Wireless_modem_user_guide.pdf'
+document.
+
+It allows a phonet sequenced socket (host-pep) to initiate a Pipe connection
+between itself and a remote pipe-end point (e.g. modem).
+
+The implementation adds socket options at SOL_PNPIPE level:
+
+ PNPIPE_PIPE_HANDLE
+ It accepts an integer argument for setting value of pipe handle.
+
+ PNPIPE_ENABLE accepts one integer value (int). If set to zero, the pipe
+ is disabled. If the value is non-zero, the pipe is enabled. If the pipe
+ is not (yet) connected, ENOTCONN is error is returned.
+
+The implementation also adds socket 'connect'. On calling the 'connect', pipe
+will be created between the source socket and the destination, and the pipe
+state will be set to PIPE_DISABLED.
+
+After a pipe has been created and enabled successfully, the Pipe data can be
+exchanged between the host-pep and remote-pep (modem).
+
+User-space would typically follow below sequence with Pipe controller:-
+-socket
+-bind
+-setsockopt for PNPIPE_PIPE_HANDLE
+-connect
+-setsockopt for PNPIPE_ENCAP_IP
+-setsockopt for PNPIPE_ENABLE
+
+
Authors
-------
diff --git a/Documentation/networking/timestamping.txt b/Documentation/networking/timestamping.txt
index e8c8f4f06c67..98097d8cb910 100644
--- a/Documentation/networking/timestamping.txt
+++ b/Documentation/networking/timestamping.txt
@@ -172,15 +172,19 @@ struct skb_shared_hwtstamps {
};
Time stamps for outgoing packets are to be generated as follows:
-- In hard_start_xmit(), check if skb_tx(skb)->hardware is set no-zero.
- If yes, then the driver is expected to do hardware time stamping.
+- In hard_start_xmit(), check if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)
+ is set no-zero. If yes, then the driver is expected to do hardware time
+ stamping.
- If this is possible for the skb and requested, then declare
- that the driver is doing the time stamping by setting the field
- skb_tx(skb)->in_progress non-zero. You might want to keep a pointer
- to the associated skb for the next step and not free the skb. A driver
- not supporting hardware time stamping doesn't do that. A driver must
- never touch sk_buff::tstamp! It is used to store software generated
- time stamps by the network subsystem.
+ that the driver is doing the time stamping by setting the flag
+ SKBTX_IN_PROGRESS in skb_shinfo(skb)->tx_flags , e.g. with
+
+ skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+
+ You might want to keep a pointer to the associated skb for the next step
+ and not free the skb. A driver not supporting hardware time stamping doesn't
+ do that. A driver must never touch sk_buff::tstamp! It is used to store
+ software generated time stamps by the network subsystem.
- As soon as the driver has sent the packet and/or obtained a
hardware time stamp for it, it passes the time stamp back by
calling skb_hwtstamp_tx() with the original skb, the raw
@@ -191,6 +195,6 @@ Time stamps for outgoing packets are to be generated as follows:
this would occur at a later time in the processing pipeline than other
software time stamping and therefore could lead to unexpected deltas
between time stamps.
-- If the driver did not call set skb_tx(skb)->in_progress, then
+- If the driver did not set the SKBTX_IN_PROGRESS flag (see above), then
dev_hard_start_xmit() checks whether software time stamping
is wanted as fallback and potentially generates the time stamp.
diff --git a/Documentation/pcmcia/driver-changes.txt b/Documentation/pcmcia/driver-changes.txt
index 26c0f9c00545..dd04361dd361 100644
--- a/Documentation/pcmcia/driver-changes.txt
+++ b/Documentation/pcmcia/driver-changes.txt
@@ -1,4 +1,29 @@
This file details changes in 2.6 which affect PCMCIA card driver authors:
+* pcmcia_loop_config() and autoconfiguration (as of 2.6.36)
+ If struct pcmcia_device *p_dev->config_flags is set accordingly,
+ pcmcia_loop_config() now sets up certain configuration values
+ automatically, though the driver may still override the settings
+ in the callback function. The following autoconfiguration options
+ are provided at the moment:
+ CONF_AUTO_CHECK_VCC : check for matching Vcc
+ CONF_AUTO_SET_VPP : set Vpp
+ CONF_AUTO_AUDIO : auto-enable audio line, if required
+ CONF_AUTO_SET_IO : set ioport resources (->resource[0,1])
+ CONF_AUTO_SET_IOMEM : set first iomem resource (->resource[2])
+
+* pcmcia_request_configuration -> pcmcia_enable_device (as of 2.6.36)
+ pcmcia_request_configuration() got renamed to pcmcia_enable_device(),
+ as it mirrors pcmcia_disable_device(). Configuration settings are now
+ stored in struct pcmcia_device, e.g. in the fields config_flags,
+ config_index, config_base, vpp.
+
+* pcmcia_request_window changes (as of 2.6.36)
+ Instead of win_req_t, drivers are now requested to fill out
+ struct pcmcia_device *p_dev->resource[2,3,4,5] for up to four ioport
+ ranges. After a call to pcmcia_request_window(), the regions found there
+ are reserved and may be used immediately -- until pcmcia_release_window()
+ is called.
+
* pcmcia_request_io changes (as of 2.6.36)
Instead of io_req_t, drivers are now requested to fill out
struct pcmcia_device *p_dev->resource[0,1] for up to two ioport
diff --git a/Documentation/power/00-INDEX b/Documentation/power/00-INDEX
index fb742c213c9e..45e9d4a91284 100644
--- a/Documentation/power/00-INDEX
+++ b/Documentation/power/00-INDEX
@@ -14,6 +14,8 @@ interface.txt
- Power management user interface in /sys/power
notifiers.txt
- Registering suspend notifiers in device drivers
+opp.txt
+ - Operating Performance Point library
pci.txt
- How the PCI Subsystem Does Power Management
pm_qos_interface.txt
diff --git a/Documentation/power/interface.txt b/Documentation/power/interface.txt
index e67211fe0ee2..c537834af005 100644
--- a/Documentation/power/interface.txt
+++ b/Documentation/power/interface.txt
@@ -57,7 +57,7 @@ smallest image possible. In particular, if "0" is written to this file, the
suspend image will be as small as possible.
Reading from this file will display the current image size limit, which
-is set to 500 MB by default.
+is set to 2/5 of available RAM by default.
/sys/power/pm_trace controls the code which saves the last PM event point in
the RTC across reboots, so that you can debug a machine that just hangs
diff --git a/Documentation/power/opp.txt b/Documentation/power/opp.txt
new file mode 100644
index 000000000000..44d87ad3cea9
--- /dev/null
+++ b/Documentation/power/opp.txt
@@ -0,0 +1,375 @@
+*=============*
+* OPP Library *
+*=============*
+
+(C) 2009-2010 Nishanth Menon <nm@ti.com>, Texas Instruments Incorporated
+
+Contents
+--------
+1. Introduction
+2. Initial OPP List Registration
+3. OPP Search Functions
+4. OPP Availability Control Functions
+5. OPP Data Retrieval Functions
+6. Cpufreq Table Generation
+7. Data Structures
+
+1. Introduction
+===============
+Complex SoCs of today consists of a multiple sub-modules working in conjunction.
+In an operational system executing varied use cases, not all modules in the SoC
+need to function at their highest performing frequency all the time. To
+facilitate this, sub-modules in a SoC are grouped into domains, allowing some
+domains to run at lower voltage and frequency while other domains are loaded
+more. The set of discrete tuples consisting of frequency and voltage pairs that
+the device will support per domain are called Operating Performance Points or
+OPPs.
+
+OPP library provides a set of helper functions to organize and query the OPP
+information. The library is located in drivers/base/power/opp.c and the header
+is located in include/linux/opp.h. OPP library can be enabled by enabling
+CONFIG_PM_OPP from power management menuconfig menu. OPP library depends on
+CONFIG_PM as certain SoCs such as Texas Instrument's OMAP framework allows to
+optionally boot at a certain OPP without needing cpufreq.
+
+Typical usage of the OPP library is as follows:
+(users) -> registers a set of default OPPs -> (library)
+SoC framework -> modifies on required cases certain OPPs -> OPP layer
+ -> queries to search/retrieve information ->
+
+OPP layer expects each domain to be represented by a unique device pointer. SoC
+framework registers a set of initial OPPs per device with the OPP layer. This
+list is expected to be an optimally small number typically around 5 per device.
+This initial list contains a set of OPPs that the framework expects to be safely
+enabled by default in the system.
+
+Note on OPP Availability:
+------------------------
+As the system proceeds to operate, SoC framework may choose to make certain
+OPPs available or not available on each device based on various external
+factors. Example usage: Thermal management or other exceptional situations where
+SoC framework might choose to disable a higher frequency OPP to safely continue
+operations until that OPP could be re-enabled if possible.
+
+OPP library facilitates this concept in it's implementation. The following
+operational functions operate only on available opps:
+opp_find_freq_{ceil, floor}, opp_get_voltage, opp_get_freq, opp_get_opp_count
+and opp_init_cpufreq_table
+
+opp_find_freq_exact is meant to be used to find the opp pointer which can then
+be used for opp_enable/disable functions to make an opp available as required.
+
+WARNING: Users of OPP library should refresh their availability count using
+get_opp_count if opp_enable/disable functions are invoked for a device, the
+exact mechanism to trigger these or the notification mechanism to other
+dependent subsystems such as cpufreq are left to the discretion of the SoC
+specific framework which uses the OPP library. Similar care needs to be taken
+care to refresh the cpufreq table in cases of these operations.
+
+WARNING on OPP List locking mechanism:
+-------------------------------------------------
+OPP library uses RCU for exclusivity. RCU allows the query functions to operate
+in multiple contexts and this synchronization mechanism is optimal for a read
+intensive operations on data structure as the OPP library caters to.
+
+To ensure that the data retrieved are sane, the users such as SoC framework
+should ensure that the section of code operating on OPP queries are locked
+using RCU read locks. The opp_find_freq_{exact,ceil,floor},
+opp_get_{voltage, freq, opp_count} fall into this category.
+
+opp_{add,enable,disable} are updaters which use mutex and implement it's own
+RCU locking mechanisms. opp_init_cpufreq_table acts as an updater and uses
+mutex to implment RCU updater strategy. These functions should *NOT* be called
+under RCU locks and other contexts that prevent blocking functions in RCU or
+mutex operations from working.
+
+2. Initial OPP List Registration
+================================
+The SoC implementation calls opp_add function iteratively to add OPPs per
+device. It is expected that the SoC framework will register the OPP entries
+optimally- typical numbers range to be less than 5. The list generated by
+registering the OPPs is maintained by OPP library throughout the device
+operation. The SoC framework can subsequently control the availability of the
+OPPs dynamically using the opp_enable / disable functions.
+
+opp_add - Add a new OPP for a specific domain represented by the device pointer.
+ The OPP is defined using the frequency and voltage. Once added, the OPP
+ is assumed to be available and control of it's availability can be done
+ with the opp_enable/disable functions. OPP library internally stores
+ and manages this information in the opp struct. This function may be
+ used by SoC framework to define a optimal list as per the demands of
+ SoC usage environment.
+
+ WARNING: Do not use this function in interrupt context.
+
+ Example:
+ soc_pm_init()
+ {
+ /* Do things */
+ r = opp_add(mpu_dev, 1000000, 900000);
+ if (!r) {
+ pr_err("%s: unable to register mpu opp(%d)\n", r);
+ goto no_cpufreq;
+ }
+ /* Do cpufreq things */
+ no_cpufreq:
+ /* Do remaining things */
+ }
+
+3. OPP Search Functions
+=======================
+High level framework such as cpufreq operates on frequencies. To map the
+frequency back to the corresponding OPP, OPP library provides handy functions
+to search the OPP list that OPP library internally manages. These search
+functions return the matching pointer representing the opp if a match is
+found, else returns error. These errors are expected to be handled by standard
+error checks such as IS_ERR() and appropriate actions taken by the caller.
+
+opp_find_freq_exact - Search for an OPP based on an *exact* frequency and
+ availability. This function is especially useful to enable an OPP which
+ is not available by default.
+ Example: In a case when SoC framework detects a situation where a
+ higher frequency could be made available, it can use this function to
+ find the OPP prior to call the opp_enable to actually make it available.
+ rcu_read_lock();
+ opp = opp_find_freq_exact(dev, 1000000000, false);
+ rcu_read_unlock();
+ /* dont operate on the pointer.. just do a sanity check.. */
+ if (IS_ERR(opp)) {
+ pr_err("frequency not disabled!\n");
+ /* trigger appropriate actions.. */
+ } else {
+ opp_enable(dev,1000000000);
+ }
+
+ NOTE: This is the only search function that operates on OPPs which are
+ not available.
+
+opp_find_freq_floor - Search for an available OPP which is *at most* the
+ provided frequency. This function is useful while searching for a lesser
+ match OR operating on OPP information in the order of decreasing
+ frequency.
+ Example: To find the highest opp for a device:
+ freq = ULONG_MAX;
+ rcu_read_lock();
+ opp_find_freq_floor(dev, &freq);
+ rcu_read_unlock();
+
+opp_find_freq_ceil - Search for an available OPP which is *at least* the
+ provided frequency. This function is useful while searching for a
+ higher match OR operating on OPP information in the order of increasing
+ frequency.
+ Example 1: To find the lowest opp for a device:
+ freq = 0;
+ rcu_read_lock();
+ opp_find_freq_ceil(dev, &freq);
+ rcu_read_unlock();
+ Example 2: A simplified implementation of a SoC cpufreq_driver->target:
+ soc_cpufreq_target(..)
+ {
+ /* Do stuff like policy checks etc. */
+ /* Find the best frequency match for the req */
+ rcu_read_lock();
+ opp = opp_find_freq_ceil(dev, &freq);
+ rcu_read_unlock();
+ if (!IS_ERR(opp))
+ soc_switch_to_freq_voltage(freq);
+ else
+ /* do something when we cant satisfy the req */
+ /* do other stuff */
+ }
+
+4. OPP Availability Control Functions
+=====================================
+A default OPP list registered with the OPP library may not cater to all possible
+situation. The OPP library provides a set of functions to modify the
+availability of a OPP within the OPP list. This allows SoC frameworks to have
+fine grained dynamic control of which sets of OPPs are operationally available.
+These functions are intended to *temporarily* remove an OPP in conditions such
+as thermal considerations (e.g. don't use OPPx until the temperature drops).
+
+WARNING: Do not use these functions in interrupt context.
+
+opp_enable - Make a OPP available for operation.
+ Example: Lets say that 1GHz OPP is to be made available only if the
+ SoC temperature is lower than a certain threshold. The SoC framework
+ implementation might choose to do something as follows:
+ if (cur_temp < temp_low_thresh) {
+ /* Enable 1GHz if it was disabled */
+ rcu_read_lock();
+ opp = opp_find_freq_exact(dev, 1000000000, false);
+ rcu_read_unlock();
+ /* just error check */
+ if (!IS_ERR(opp))
+ ret = opp_enable(dev, 1000000000);
+ else
+ goto try_something_else;
+ }
+
+opp_disable - Make an OPP to be not available for operation
+ Example: Lets say that 1GHz OPP is to be disabled if the temperature
+ exceeds a threshold value. The SoC framework implementation might
+ choose to do something as follows:
+ if (cur_temp > temp_high_thresh) {
+ /* Disable 1GHz if it was enabled */
+ rcu_read_lock();
+ opp = opp_find_freq_exact(dev, 1000000000, true);
+ rcu_read_unlock();
+ /* just error check */
+ if (!IS_ERR(opp))
+ ret = opp_disable(dev, 1000000000);
+ else
+ goto try_something_else;
+ }
+
+5. OPP Data Retrieval Functions
+===============================
+Since OPP library abstracts away the OPP information, a set of functions to pull
+information from the OPP structure is necessary. Once an OPP pointer is
+retrieved using the search functions, the following functions can be used by SoC
+framework to retrieve the information represented inside the OPP layer.
+
+opp_get_voltage - Retrieve the voltage represented by the opp pointer.
+ Example: At a cpufreq transition to a different frequency, SoC
+ framework requires to set the voltage represented by the OPP using
+ the regulator framework to the Power Management chip providing the
+ voltage.
+ soc_switch_to_freq_voltage(freq)
+ {
+ /* do things */
+ rcu_read_lock();
+ opp = opp_find_freq_ceil(dev, &freq);
+ v = opp_get_voltage(opp);
+ rcu_read_unlock();
+ if (v)
+ regulator_set_voltage(.., v);
+ /* do other things */
+ }
+
+opp_get_freq - Retrieve the freq represented by the opp pointer.
+ Example: Lets say the SoC framework uses a couple of helper functions
+ we could pass opp pointers instead of doing additional parameters to
+ handle quiet a bit of data parameters.
+ soc_cpufreq_target(..)
+ {
+ /* do things.. */
+ max_freq = ULONG_MAX;
+ rcu_read_lock();
+ max_opp = opp_find_freq_floor(dev,&max_freq);
+ requested_opp = opp_find_freq_ceil(dev,&freq);
+ if (!IS_ERR(max_opp) && !IS_ERR(requested_opp))
+ r = soc_test_validity(max_opp, requested_opp);
+ rcu_read_unlock();
+ /* do other things */
+ }
+ soc_test_validity(..)
+ {
+ if(opp_get_voltage(max_opp) < opp_get_voltage(requested_opp))
+ return -EINVAL;
+ if(opp_get_freq(max_opp) < opp_get_freq(requested_opp))
+ return -EINVAL;
+ /* do things.. */
+ }
+
+opp_get_opp_count - Retrieve the number of available opps for a device
+ Example: Lets say a co-processor in the SoC needs to know the available
+ frequencies in a table, the main processor can notify as following:
+ soc_notify_coproc_available_frequencies()
+ {
+ /* Do things */
+ rcu_read_lock();
+ num_available = opp_get_opp_count(dev);
+ speeds = kzalloc(sizeof(u32) * num_available, GFP_KERNEL);
+ /* populate the table in increasing order */
+ freq = 0;
+ while (!IS_ERR(opp = opp_find_freq_ceil(dev, &freq))) {
+ speeds[i] = freq;
+ freq++;
+ i++;
+ }
+ rcu_read_unlock();
+
+ soc_notify_coproc(AVAILABLE_FREQs, speeds, num_available);
+ /* Do other things */
+ }
+
+6. Cpufreq Table Generation
+===========================
+opp_init_cpufreq_table - cpufreq framework typically is initialized with
+ cpufreq_frequency_table_cpuinfo which is provided with the list of
+ frequencies that are available for operation. This function provides
+ a ready to use conversion routine to translate the OPP layer's internal
+ information about the available frequencies into a format readily
+ providable to cpufreq.
+
+ WARNING: Do not use this function in interrupt context.
+
+ Example:
+ soc_pm_init()
+ {
+ /* Do things */
+ r = opp_init_cpufreq_table(dev, &freq_table);
+ if (!r)
+ cpufreq_frequency_table_cpuinfo(policy, freq_table);
+ /* Do other things */
+ }
+
+ NOTE: This function is available only if CONFIG_CPU_FREQ is enabled in
+ addition to CONFIG_PM as power management feature is required to
+ dynamically scale voltage and frequency in a system.
+
+7. Data Structures
+==================
+Typically an SoC contains multiple voltage domains which are variable. Each
+domain is represented by a device pointer. The relationship to OPP can be
+represented as follows:
+SoC
+ |- device 1
+ | |- opp 1 (availability, freq, voltage)
+ | |- opp 2 ..
+ ... ...
+ | `- opp n ..
+ |- device 2
+ ...
+ `- device m
+
+OPP library maintains a internal list that the SoC framework populates and
+accessed by various functions as described above. However, the structures
+representing the actual OPPs and domains are internal to the OPP library itself
+to allow for suitable abstraction reusable across systems.
+
+struct opp - The internal data structure of OPP library which is used to
+ represent an OPP. In addition to the freq, voltage, availability
+ information, it also contains internal book keeping information required
+ for the OPP library to operate on. Pointer to this structure is
+ provided back to the users such as SoC framework to be used as a
+ identifier for OPP in the interactions with OPP layer.
+
+ WARNING: The struct opp pointer should not be parsed or modified by the
+ users. The defaults of for an instance is populated by opp_add, but the
+ availability of the OPP can be modified by opp_enable/disable functions.
+
+struct device - This is used to identify a domain to the OPP layer. The
+ nature of the device and it's implementation is left to the user of
+ OPP library such as the SoC framework.
+
+Overall, in a simplistic view, the data structure operations is represented as
+following:
+
+Initialization / modification:
+ +-----+ /- opp_enable
+opp_add --> | opp | <-------
+ | +-----+ \- opp_disable
+ \-------> domain_info(device)
+
+Search functions:
+ /-- opp_find_freq_ceil ---\ +-----+
+domain_info<---- opp_find_freq_exact -----> | opp |
+ \-- opp_find_freq_floor ---/ +-----+
+
+Retrieval functions:
++-----+ /- opp_get_voltage
+| opp | <---
++-----+ \- opp_get_freq
+
+domain_info <- opp_get_opp_count
diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt
index 55b859b3bc72..489e9bacd165 100644
--- a/Documentation/power/runtime_pm.txt
+++ b/Documentation/power/runtime_pm.txt
@@ -1,6 +1,7 @@
Run-time Power Management Framework for I/O Devices
(C) 2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
+(C) 2010 Alan Stern <stern@rowland.harvard.edu>
1. Introduction
@@ -157,7 +158,8 @@ rules:
to execute it, the other callbacks will not be executed for the same device.
* A request to execute ->runtime_resume() will cancel any pending or
- scheduled requests to execute the other callbacks for the same device.
+ scheduled requests to execute the other callbacks for the same device,
+ except for scheduled autosuspends.
3. Run-time PM Device Fields
@@ -165,7 +167,7 @@ The following device run-time PM fields are present in 'struct dev_pm_info', as
defined in include/linux/pm.h:
struct timer_list suspend_timer;
- - timer used for scheduling (delayed) suspend request
+ - timer used for scheduling (delayed) suspend and autosuspend requests
unsigned long timer_expires;
- timer expiration time, in jiffies (if this is different from zero, the
@@ -230,6 +232,28 @@ defined in include/linux/pm.h:
interface; it may only be modified with the help of the pm_runtime_allow()
and pm_runtime_forbid() helper functions
+ unsigned int no_callbacks;
+ - indicates that the device does not use the run-time PM callbacks (see
+ Section 8); it may be modified only by the pm_runtime_no_callbacks()
+ helper function
+
+ unsigned int use_autosuspend;
+ - indicates that the device's driver supports delayed autosuspend (see
+ Section 9); it may be modified only by the
+ pm_runtime{_dont}_use_autosuspend() helper functions
+
+ unsigned int timer_autosuspends;
+ - indicates that the PM core should attempt to carry out an autosuspend
+ when the timer expires rather than a normal suspend
+
+ int autosuspend_delay;
+ - the delay time (in milliseconds) to be used for autosuspend
+
+ unsigned long last_busy;
+ - the time (in jiffies) when the pm_runtime_mark_last_busy() helper
+ function was last called for this device; used in calculating inactivity
+ periods for autosuspend
+
All of the above fields are members of the 'power' member of 'struct device'.
4. Run-time PM Device Helper Functions
@@ -255,6 +279,12 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
error code on failure, where -EAGAIN or -EBUSY means it is safe to attempt
to suspend the device again in future
+ int pm_runtime_autosuspend(struct device *dev);
+ - same as pm_runtime_suspend() except that the autosuspend delay is taken
+ into account; if pm_runtime_autosuspend_expiration() says the delay has
+ not yet expired then an autosuspend is scheduled for the appropriate time
+ and 0 is returned
+
int pm_runtime_resume(struct device *dev);
- execute the subsystem-level resume callback for the device; returns 0 on
success, 1 if the device's run-time PM status was already 'active' or
@@ -267,6 +297,11 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
device (the request is represented by a work item in pm_wq); returns 0 on
success or error code if the request has not been queued up
+ int pm_request_autosuspend(struct device *dev);
+ - schedule the execution of the subsystem-level suspend callback for the
+ device when the autosuspend delay has expired; if the delay has already
+ expired then the work item is queued up immediately
+
int pm_schedule_suspend(struct device *dev, unsigned int delay);
- schedule the execution of the subsystem-level suspend callback for the
device in future, where 'delay' is the time to wait before queuing up a
@@ -298,12 +333,20 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
- decrement the device's usage counter
int pm_runtime_put(struct device *dev);
- - decrement the device's usage counter, run pm_request_idle(dev) and return
- its result
+ - decrement the device's usage counter; if the result is 0 then run
+ pm_request_idle(dev) and return its result
+
+ int pm_runtime_put_autosuspend(struct device *dev);
+ - decrement the device's usage counter; if the result is 0 then run
+ pm_request_autosuspend(dev) and return its result
int pm_runtime_put_sync(struct device *dev);
- - decrement the device's usage counter, run pm_runtime_idle(dev) and return
- its result
+ - decrement the device's usage counter; if the result is 0 then run
+ pm_runtime_idle(dev) and return its result
+
+ int pm_runtime_put_sync_autosuspend(struct device *dev);
+ - decrement the device's usage counter; if the result is 0 then run
+ pm_runtime_autosuspend(dev) and return its result
void pm_runtime_enable(struct device *dev);
- enable the run-time PM helper functions to run the device bus type's
@@ -349,19 +392,51 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
counter (used by the /sys/devices/.../power/control interface to
effectively prevent the device from being power managed at run time)
+ void pm_runtime_no_callbacks(struct device *dev);
+ - set the power.no_callbacks flag for the device and remove the run-time
+ PM attributes from /sys/devices/.../power (or prevent them from being
+ added when the device is registered)
+
+ void pm_runtime_mark_last_busy(struct device *dev);
+ - set the power.last_busy field to the current time
+
+ void pm_runtime_use_autosuspend(struct device *dev);
+ - set the power.use_autosuspend flag, enabling autosuspend delays
+
+ void pm_runtime_dont_use_autosuspend(struct device *dev);
+ - clear the power.use_autosuspend flag, disabling autosuspend delays
+
+ void pm_runtime_set_autosuspend_delay(struct device *dev, int delay);
+ - set the power.autosuspend_delay value to 'delay' (expressed in
+ milliseconds); if 'delay' is negative then run-time suspends are
+ prevented
+
+ unsigned long pm_runtime_autosuspend_expiration(struct device *dev);
+ - calculate the time when the current autosuspend delay period will expire,
+ based on power.last_busy and power.autosuspend_delay; if the delay time
+ is 1000 ms or larger then the expiration time is rounded up to the
+ nearest second; returns 0 if the delay period has already expired or
+ power.use_autosuspend isn't set, otherwise returns the expiration time
+ in jiffies
+
It is safe to execute the following helper functions from interrupt context:
pm_request_idle()
+pm_request_autosuspend()
pm_schedule_suspend()
pm_request_resume()
pm_runtime_get_noresume()
pm_runtime_get()
pm_runtime_put_noidle()
pm_runtime_put()
+pm_runtime_put_autosuspend()
+pm_runtime_enable()
pm_suspend_ignore_children()
pm_runtime_set_active()
pm_runtime_set_suspended()
-pm_runtime_enable()
+pm_runtime_suspended()
+pm_runtime_mark_last_busy()
+pm_runtime_autosuspend_expiration()
5. Run-time PM Initialization, Device Probing and Removal
@@ -524,3 +599,141 @@ poweroff and run-time suspend callback, and similarly for system resume, thaw,
restore, and run-time resume, can achieve this with the help of the
UNIVERSAL_DEV_PM_OPS macro defined in include/linux/pm.h (possibly setting its
last argument to NULL).
+
+8. "No-Callback" Devices
+
+Some "devices" are only logical sub-devices of their parent and cannot be
+power-managed on their own. (The prototype example is a USB interface. Entire
+USB devices can go into low-power mode or send wake-up requests, but neither is
+possible for individual interfaces.) The drivers for these devices have no
+need of run-time PM callbacks; if the callbacks did exist, ->runtime_suspend()
+and ->runtime_resume() would always return 0 without doing anything else and
+->runtime_idle() would always call pm_runtime_suspend().
+
+Subsystems can tell the PM core about these devices by calling
+pm_runtime_no_callbacks(). This should be done after the device structure is
+initialized and before it is registered (although after device registration is
+also okay). The routine will set the device's power.no_callbacks flag and
+prevent the non-debugging run-time PM sysfs attributes from being created.
+
+When power.no_callbacks is set, the PM core will not invoke the
+->runtime_idle(), ->runtime_suspend(), or ->runtime_resume() callbacks.
+Instead it will assume that suspends and resumes always succeed and that idle
+devices should be suspended.
+
+As a consequence, the PM core will never directly inform the device's subsystem
+or driver about run-time power changes. Instead, the driver for the device's
+parent must take responsibility for telling the device's driver when the
+parent's power state changes.
+
+9. Autosuspend, or automatically-delayed suspends
+
+Changing a device's power state isn't free; it requires both time and energy.
+A device should be put in a low-power state only when there's some reason to
+think it will remain in that state for a substantial time. A common heuristic
+says that a device which hasn't been used for a while is liable to remain
+unused; following this advice, drivers should not allow devices to be suspended
+at run-time until they have been inactive for some minimum period. Even when
+the heuristic ends up being non-optimal, it will still prevent devices from
+"bouncing" too rapidly between low-power and full-power states.
+
+The term "autosuspend" is an historical remnant. It doesn't mean that the
+device is automatically suspended (the subsystem or driver still has to call
+the appropriate PM routines); rather it means that run-time suspends will
+automatically be delayed until the desired period of inactivity has elapsed.
+
+Inactivity is determined based on the power.last_busy field. Drivers should
+call pm_runtime_mark_last_busy() to update this field after carrying out I/O,
+typically just before calling pm_runtime_put_autosuspend(). The desired length
+of the inactivity period is a matter of policy. Subsystems can set this length
+initially by calling pm_runtime_set_autosuspend_delay(), but after device
+registration the length should be controlled by user space, using the
+/sys/devices/.../power/autosuspend_delay_ms attribute.
+
+In order to use autosuspend, subsystems or drivers must call
+pm_runtime_use_autosuspend() (preferably before registering the device), and
+thereafter they should use the various *_autosuspend() helper functions instead
+of the non-autosuspend counterparts:
+
+ Instead of: pm_runtime_suspend use: pm_runtime_autosuspend;
+ Instead of: pm_schedule_suspend use: pm_request_autosuspend;
+ Instead of: pm_runtime_put use: pm_runtime_put_autosuspend;
+ Instead of: pm_runtime_put_sync use: pm_runtime_put_sync_autosuspend.
+
+Drivers may also continue to use the non-autosuspend helper functions; they
+will behave normally, not taking the autosuspend delay into account.
+Similarly, if the power.use_autosuspend field isn't set then the autosuspend
+helper functions will behave just like the non-autosuspend counterparts.
+
+The implementation is well suited for asynchronous use in interrupt contexts.
+However such use inevitably involves races, because the PM core can't
+synchronize ->runtime_suspend() callbacks with the arrival of I/O requests.
+This synchronization must be handled by the driver, using its private lock.
+Here is a schematic pseudo-code example:
+
+ foo_read_or_write(struct foo_priv *foo, void *data)
+ {
+ lock(&foo->private_lock);
+ add_request_to_io_queue(foo, data);
+ if (foo->num_pending_requests++ == 0)
+ pm_runtime_get(&foo->dev);
+ if (!foo->is_suspended)
+ foo_process_next_request(foo);
+ unlock(&foo->private_lock);
+ }
+
+ foo_io_completion(struct foo_priv *foo, void *req)
+ {
+ lock(&foo->private_lock);
+ if (--foo->num_pending_requests == 0) {
+ pm_runtime_mark_last_busy(&foo->dev);
+ pm_runtime_put_autosuspend(&foo->dev);
+ } else {
+ foo_process_next_request(foo);
+ }
+ unlock(&foo->private_lock);
+ /* Send req result back to the user ... */
+ }
+
+ int foo_runtime_suspend(struct device *dev)
+ {
+ struct foo_priv foo = container_of(dev, ...);
+ int ret = 0;
+
+ lock(&foo->private_lock);
+ if (foo->num_pending_requests > 0) {
+ ret = -EBUSY;
+ } else {
+ /* ... suspend the device ... */
+ foo->is_suspended = 1;
+ }
+ unlock(&foo->private_lock);
+ return ret;
+ }
+
+ int foo_runtime_resume(struct device *dev)
+ {
+ struct foo_priv foo = container_of(dev, ...);
+
+ lock(&foo->private_lock);
+ /* ... resume the device ... */
+ foo->is_suspended = 0;
+ pm_runtime_mark_last_busy(&foo->dev);
+ if (foo->num_pending_requests > 0)
+ foo_process_requests(foo);
+ unlock(&foo->private_lock);
+ return 0;
+ }
+
+The important point is that after foo_io_completion() asks for an autosuspend,
+the foo_runtime_suspend() callback may race with foo_read_or_write().
+Therefore foo_runtime_suspend() has to check whether there are any pending I/O
+requests (while holding the private lock) before allowing the suspend to
+proceed.
+
+In addition, the power.autosuspend_delay field can be changed by user space at
+any time. If a driver cares about this, it can call
+pm_runtime_autosuspend_expiration() from within the ->runtime_suspend()
+callback while holding its private lock. If the function returns a nonzero
+value then the delay has not yet expired and the callback should return
+-EAGAIN.
diff --git a/Documentation/power/s2ram.txt b/Documentation/power/s2ram.txt
index 514b94fc931e..1bdfa0443773 100644
--- a/Documentation/power/s2ram.txt
+++ b/Documentation/power/s2ram.txt
@@ -49,6 +49,13 @@ machine that doesn't boot) is:
device (lspci and /sys/devices/pci* is your friend), and see if you can
fix it, disable it, or trace into its resume function.
+ If no device matches the hash (or any matches appear to be false positives),
+ the culprit may be a device from a loadable kernel module that is not loaded
+ until after the hash is checked. You can check the hash against the current
+ devices again after more modules are loaded using sysfs:
+
+ cat /sys/power/pm_trace_dev_match
+
For example, the above happens to be the VGA device on my EVO, which I
used to run with "radeonfb" (it's an ATI Radeon mobility). It turns out
that "radeonfb" simply cannot resume that device - it tries to set the
diff --git a/Documentation/power/swsusp.txt b/Documentation/power/swsusp.txt
index 9d60ab717a7b..ea718891a665 100644
--- a/Documentation/power/swsusp.txt
+++ b/Documentation/power/swsusp.txt
@@ -66,7 +66,8 @@ swsusp saves the state of the machine into active swaps and then reboots or
powerdowns. You must explicitly specify the swap partition to resume from with
``resume='' kernel option. If signature is found it loads and restores saved
state. If the option ``noresume'' is specified as a boot parameter, it skips
-the resuming.
+the resuming. If the option ``hibernate=nocompress'' is specified as a boot
+parameter, it saves hibernation image without compression.
In the meantime while the system is suspended you should not add/remove any
of the hardware, write to the filesystems, etc.
diff --git a/Documentation/powerpc/dts-bindings/fsl/spi.txt b/Documentation/powerpc/dts-bindings/fsl/spi.txt
index 80510c018eea..777abd7399d5 100644
--- a/Documentation/powerpc/dts-bindings/fsl/spi.txt
+++ b/Documentation/powerpc/dts-bindings/fsl/spi.txt
@@ -1,7 +1,9 @@
* SPI (Serial Peripheral Interface)
Required properties:
-- cell-index : SPI controller index.
+- cell-index : QE SPI subblock index.
+ 0: QE subblock SPI1
+ 1: QE subblock SPI2
- compatible : should be "fsl,spi".
- mode : the SPI operation mode, it can be "cpu" or "cpu-qe".
- reg : Offset and length of the register set for the device
@@ -29,3 +31,23 @@ Example:
gpios = <&gpio 18 1 // device reg=<0>
&gpio 19 1>; // device reg=<1>
};
+
+
+* eSPI (Enhanced Serial Peripheral Interface)
+
+Required properties:
+- compatible : should be "fsl,mpc8536-espi".
+- reg : Offset and length of the register set for the device.
+- interrupts : should contain eSPI interrupt, the device has one interrupt.
+- fsl,espi-num-chipselects : the number of the chipselect signals.
+
+Example:
+ spi@110000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,mpc8536-espi";
+ reg = <0x110000 0x1000>;
+ interrupts = <53 0x2>;
+ interrupt-parent = <&mpic>;
+ fsl,espi-num-chipselects = <4>;
+ };
diff --git a/Documentation/powerpc/dts-bindings/fsl/usb.txt b/Documentation/powerpc/dts-bindings/fsl/usb.txt
index b00152402694..bd5723f0b67e 100644
--- a/Documentation/powerpc/dts-bindings/fsl/usb.txt
+++ b/Documentation/powerpc/dts-bindings/fsl/usb.txt
@@ -8,6 +8,7 @@ and additions :
Required properties :
- compatible : Should be "fsl-usb2-mph" for multi port host USB
controllers, or "fsl-usb2-dr" for dual role USB controllers
+ or "fsl,mpc5121-usb2-dr" for dual role USB controllers of MPC5121
- phy_type : For multi port host USB controllers, should be one of
"ulpi", or "serial". For dual role USB controllers, should be
one of "ulpi", "utmi", "utmi_wide", or "serial".
@@ -33,6 +34,12 @@ Recommended properties :
- interrupt-parent : the phandle for the interrupt controller that
services interrupts for this device.
+Optional properties :
+ - fsl,invert-drvvbus : boolean; for MPC5121 USB0 only. Indicates the
+ port power polarity of internal PHY signal DRVVBUS is inverted.
+ - fsl,invert-pwr-fault : boolean; for MPC5121 USB0 only. Indicates
+ the PWR_FAULT signal polarity is inverted.
+
Example multi port host USB controller device node :
usb@22000 {
compatible = "fsl-usb2-mph";
@@ -57,3 +64,18 @@ Example dual role USB controller device node :
dr_mode = "otg";
phy = "ulpi";
};
+
+Example dual role USB controller device node for MPC5121ADS:
+
+ usb@4000 {
+ compatible = "fsl,mpc5121-usb2-dr";
+ reg = <0x4000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupt-parent = < &ipic >;
+ interrupts = <44 0x8>;
+ dr_mode = "otg";
+ phy_type = "utmi_wide";
+ fsl,invert-drvvbus;
+ fsl,invert-pwr-fault;
+ };
diff --git a/Documentation/scsi/st.txt b/Documentation/scsi/st.txt
index 40752602c050..691ca292c24d 100644
--- a/Documentation/scsi/st.txt
+++ b/Documentation/scsi/st.txt
@@ -2,7 +2,7 @@ This file contains brief information about the SCSI tape driver.
The driver is currently maintained by Kai Mäkisara (email
Kai.Makisara@kolumbus.fi)
-Last modified: Sun Feb 24 21:59:07 2008 by kai.makisara
+Last modified: Sun Aug 29 18:25:47 2010 by kai.makisara
BASICS
@@ -85,6 +85,17 @@ writing and the last operation has been a write. Two filemarks can be
optionally written. In both cases end of data is signified by
returning zero bytes for two consecutive reads.
+Writing filemarks without the immediate bit set in the SCSI command block acts
+as a synchronization point, i.e., all remaining data form the drive buffers is
+written to tape before the command returns. This makes sure that write errors
+are caught at that point, but this takes time. In some applications, several
+consecutive files must be written fast. The MTWEOFI operation can be used to
+write the filemarks without flushing the drive buffer. Writing filemark at
+close() is always flushing the drive buffers. However, if the previous
+operation is MTWEOFI, close() does not write a filemark. This can be used if
+the program wants to close/open the tape device between files and wants to
+skip waiting.
+
If rewind, offline, bsf, or seek is done and previous tape operation was
write, a filemark is written before moving tape.
@@ -301,6 +312,8 @@ MTBSR Space backward over count records.
MTFSS Space forward over count setmarks.
MTBSS Space backward over count setmarks.
MTWEOF Write count filemarks.
+MTWEOFI Write count filemarks with immediate bit set (i.e., does not
+ wait until data is on tape)
MTWSM Write count setmarks.
MTREW Rewind tape.
MTOFFL Set device off line (often rewind plus eject).
diff --git a/Documentation/usb/proc_usb_info.txt b/Documentation/usb/proc_usb_info.txt
index fafcd4723260..afe596d5f201 100644
--- a/Documentation/usb/proc_usb_info.txt
+++ b/Documentation/usb/proc_usb_info.txt
@@ -1,12 +1,17 @@
/proc/bus/usb filesystem output
===============================
-(version 2003.05.30)
+(version 2010.09.13)
The usbfs filesystem for USB devices is traditionally mounted at
/proc/bus/usb. It provides the /proc/bus/usb/devices file, as well as
the /proc/bus/usb/BBB/DDD files.
+In many modern systems the usbfs filsystem isn't used at all. Instead
+USB device nodes are created under /dev/usb/ or someplace similar. The
+"devices" file is available in debugfs, typically as
+/sys/kernel/debug/usb/devices.
+
**NOTE**: If /proc/bus/usb appears empty, and a host controller
driver has been linked, then you need to mount the
@@ -106,8 +111,8 @@ Legend:
Topology info:
-T: Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=ddd MxCh=dd
-| | | | | | | | |__MaxChildren
+T: Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=dddd MxCh=dd
+| | | | | | | | |__MaxChildren
| | | | | | | |__Device Speed in Mbps
| | | | | | |__DeviceNumber
| | | | | |__Count of devices at this level
@@ -120,8 +125,13 @@ T: Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=ddd MxCh=dd
Speed may be:
1.5 Mbit/s for low speed USB
12 Mbit/s for full speed USB
- 480 Mbit/s for high speed USB (added for USB 2.0)
+ 480 Mbit/s for high speed USB (added for USB 2.0);
+ also used for Wireless USB, which has no fixed speed
+ 5000 Mbit/s for SuperSpeed USB (added for USB 3.0)
+ For reasons lost in the mists of time, the Port number is always
+ too low by 1. For example, a device plugged into port 4 will
+ show up with "Port=03".
Bandwidth info:
B: Alloc=ddd/ddd us (xx%), #Int=ddd, #Iso=ddd
@@ -291,7 +301,7 @@ Here's an example, from a system which has a UHCI root hub,
an external hub connected to the root hub, and a mouse and
a serial converter connected to the external hub.
-T: Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2
+T: Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2
B: Alloc= 28/900 us ( 3%), #Int= 2, #Iso= 0
D: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
P: Vendor=0000 ProdID=0000 Rev= 0.00
@@ -301,21 +311,21 @@ C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms
-T: Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 4
+T: Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 4
D: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
P: Vendor=0451 ProdID=1446 Rev= 1.00
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
E: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms
-T: Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#= 3 Spd=1.5 MxCh= 0
+T: Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#= 3 Spd=1.5 MxCh= 0
D: Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
P: Vendor=04b4 ProdID=0001 Rev= 0.00
C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=100mA
I: If#= 0 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=01 Prot=02 Driver=mouse
E: Ad=81(I) Atr=03(Int.) MxPS= 3 Ivl= 10ms
-T: Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#= 4 Spd=12 MxCh= 0
+T: Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#= 4 Spd=12 MxCh= 0
D: Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
P: Vendor=0565 ProdID=0001 Rev= 1.08
S: Manufacturer=Peracom Networks, Inc.
@@ -330,12 +340,12 @@ E: Ad=82(I) Atr=03(Int.) MxPS= 8 Ivl= 8ms
Selecting only the "T:" and "I:" lines from this (for example, by using
"procusb ti"), we have:
-T: Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2
-T: Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 4
+T: Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2
+T: Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 4
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
-T: Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#= 3 Spd=1.5 MxCh= 0
+T: Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#= 3 Spd=1.5 MxCh= 0
I: If#= 0 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=01 Prot=02 Driver=mouse
-T: Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#= 4 Spd=12 MxCh= 0
+T: Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#= 4 Spd=12 MxCh= 0
I: If#= 0 Alt= 0 #EPs= 3 Cls=00(>ifc ) Sub=00 Prot=00 Driver=serial
diff --git a/Documentation/vm/page-types.c b/Documentation/vm/page-types.c
index ccd951fa94ee..cc96ee2666f2 100644
--- a/Documentation/vm/page-types.c
+++ b/Documentation/vm/page-types.c
@@ -478,7 +478,7 @@ static void prepare_hwpoison_fd(void)
}
if (opt_unpoison && !hwpoison_forget_fd) {
- sprintf(buf, "%s/renew-pfn", hwpoison_debug_fs);
+ sprintf(buf, "%s/unpoison-pfn", hwpoison_debug_fs);
hwpoison_forget_fd = checked_open(buf, O_WRONLY);
}
}
diff --git a/Documentation/workqueue.txt b/Documentation/workqueue.txt
index e4498a2872c3..996a27d9b8db 100644
--- a/Documentation/workqueue.txt
+++ b/Documentation/workqueue.txt
@@ -196,11 +196,11 @@ resources, scheduled and executed.
suspend operations. Work items on the wq are drained and no
new work item starts execution until thawed.
- WQ_RESCUER
+ WQ_MEM_RECLAIM
All wq which might be used in the memory reclaim paths _MUST_
- have this flag set. This reserves one worker exclusively for
- the execution of this wq under memory pressure.
+ have this flag set. The wq is guaranteed to have at least one
+ execution context regardless of memory pressure.
WQ_HIGHPRI
@@ -356,11 +356,11 @@ If q1 has WQ_CPU_INTENSIVE set,
6. Guidelines
-* Do not forget to use WQ_RESCUER if a wq may process work items which
- are used during memory reclaim. Each wq with WQ_RESCUER set has one
- rescuer thread reserved for it. If there is dependency among
- multiple work items used during memory reclaim, they should be
- queued to separate wq each with WQ_RESCUER.
+* Do not forget to use WQ_MEM_RECLAIM if a wq may process work items
+ which are used during memory reclaim. Each wq with WQ_MEM_RECLAIM
+ set has an execution context reserved for it. If there is
+ dependency among multiple work items used during memory reclaim,
+ they should be queued to separate wq each with WQ_MEM_RECLAIM.
* Unless strict ordering is required, there is no need to use ST wq.
@@ -368,12 +368,13 @@ If q1 has WQ_CPU_INTENSIVE set,
recommended. In most use cases, concurrency level usually stays
well under the default limit.
-* A wq serves as a domain for forward progress guarantee (WQ_RESCUER),
- flush and work item attributes. Work items which are not involved
- in memory reclaim and don't need to be flushed as a part of a group
- of work items, and don't require any special attribute, can use one
- of the system wq. There is no difference in execution
- characteristics between using a dedicated wq and a system wq.
+* A wq serves as a domain for forward progress guarantee
+ (WQ_MEM_RECLAIM, flush and work item attributes. Work items which
+ are not involved in memory reclaim and don't need to be flushed as a
+ part of a group of work items, and don't require any special
+ attribute, can use one of the system wq. There is no difference in
+ execution characteristics between using a dedicated wq and a system
+ wq.
* Unless work items are expected to consume a huge amount of CPU
cycles, using a bound wq is usually beneficial due to the increased
diff --git a/Documentation/x86/x86_64/kernel-stacks b/Documentation/x86/x86_64/kernel-stacks
index 5ad65d51fb95..a01eec5d1d0b 100644
--- a/Documentation/x86/x86_64/kernel-stacks
+++ b/Documentation/x86/x86_64/kernel-stacks
@@ -18,9 +18,9 @@ specialized stacks contain no useful data. The main CPU stacks are:
Used for external hardware interrupts. If this is the first external
hardware interrupt (i.e. not a nested hardware interrupt) then the
kernel switches from the current task to the interrupt stack. Like
- the split thread and interrupt stacks on i386 (with CONFIG_4KSTACKS),
- this gives more room for kernel interrupt processing without having
- to increase the size of every per thread stack.
+ the split thread and interrupt stacks on i386, this gives more room
+ for kernel interrupt processing without having to increase the size
+ of every per thread stack.
The interrupt stack is also used when processing a softirq.
diff --git a/Kbuild b/Kbuild
index e3737ad72b5a..431f7ca2404c 100644
--- a/Kbuild
+++ b/Kbuild
@@ -53,6 +53,7 @@ targets += arch/$(SRCARCH)/kernel/asm-offsets.s
# Default sed regexp - multiline due to syntax constraints
define sed-y
"/^->/{s:->#\(.*\):/* \1 */:; \
+ s:^->\([^ ]*\) [\$$#]*\([-0-9]*\) \(.*\):#define \1 (\2) /* \3 */:; \
s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; \
s:->::; p;}"
endef
diff --git a/MAINTAINERS b/MAINTAINERS
index 668682d1f5fa..494e1a07366a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -157,9 +157,11 @@ S: Maintained
F: drivers/net/r8169.c
8250/16?50 (AND CLONE UARTS) SERIAL DRIVER
+M: Greg Kroah-Hartman <gregkh@suse.de>
L: linux-serial@vger.kernel.org
W: http://serial.sourceforge.net
-S: Orphan
+S: Maintained
+T: quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
F: drivers/serial/8250*
F: include/linux/serial_8250.h
@@ -962,6 +964,23 @@ W: http://www.fluff.org/ben/linux/
S: Maintained
F: arch/arm/mach-s3c6410/
+ARM/S5P ARM ARCHITECTURES
+M: Kukjin Kim <kgene.kim@samsung.com>
+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+L: linux-samsung-soc@vger.kernel.org (moderated for non-subscribers)
+S: Maintained
+F: arch/arm/mach-s5p*/
+
+ARM/SAMSUNG S5P SERIES FIMC SUPPORT
+M: Kyungmin Park <kyungmin.park@samsung.com>
+M: Sylwester Nawrocki <s.nawrocki@samsung.com>
+L: linux-arm-kernel@lists.infradead.org
+L: linux-media@vger.kernel.org
+S: Maintained
+F: arch/arm/plat-s5p/dev-fimc*
+F: arch/arm/plat-samsung/include/plat/*fimc*
+F: drivers/media/video/s5p-fimc/
+
ARM/SHMOBILE ARM ARCHITECTURE
M: Paul Mundt <lethal@linux-sh.org>
M: Magnus Damm <magnus.damm@gmail.com>
@@ -973,11 +992,23 @@ S: Supported
F: arch/arm/mach-shmobile/
F: drivers/sh/
+ARM/TELECHIPS ARM ARCHITECTURE
+M: "Hans J. Koch" <hjk@linutronix.de>
+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S: Maintained
+F: arch/arm/plat-tcc/
+F: arch/arm/mach-tcc8k/
+
ARM/TECHNOLOGIC SYSTEMS TS7250 MACHINE SUPPORT
M: Lennert Buytenhek <kernel@wantstofly.org>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
+ARM/TETON BGA MACHINE SUPPORT
+M: Mark F. Brown <mark.brown314@gmail.com>
+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S: Maintained
+
ARM/THECUS N2100 MACHINE SUPPORT
M: Lennert Buytenhek <kernel@wantstofly.org>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -1120,6 +1151,13 @@ W: http://wireless.kernel.org/en/users/Drivers/ar9170
S: Maintained
F: drivers/net/wireless/ath/ar9170/
+CARL9170 LINUX COMMUNITY WIRELESS DRIVER
+M: Christian Lamparter <chunkeey@googlemail.com>
+L: linux-wireless@vger.kernel.org
+W: http://wireless.kernel.org/en/users/Drivers/carl9170
+S: Maintained
+F: drivers/net/wireless/ath/carl9170/
+
ATK0110 HWMON DRIVER
M: Luca Tettamanti <kronos.it@gmail.com>
L: lm-sensors@lm-sensors.org
@@ -1344,16 +1382,19 @@ F: drivers/mtd/devices/block2mtd.c
BLUETOOTH DRIVERS
M: Marcel Holtmann <marcel@holtmann.org>
+M: Gustavo F. Padovan <padovan@profusion.mobi>
L: linux-bluetooth@vger.kernel.org
W: http://www.bluez.org/
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/padovan/bluetooth-2.6.git
S: Maintained
F: drivers/bluetooth/
BLUETOOTH SUBSYSTEM
M: Marcel Holtmann <marcel@holtmann.org>
+M: Gustavo F. Padovan <padovan@profusion.mobi>
L: linux-bluetooth@vger.kernel.org
W: http://www.bluez.org/
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/holtmann/bluetooth-2.6.git
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/padovan/bluetooth-2.6.git
S: Maintained
F: net/bluetooth/
F: include/net/bluetooth/
@@ -1398,6 +1439,13 @@ L: linux-scsi@vger.kernel.org
S: Supported
F: drivers/scsi/bfa/
+BROCADE BNA 10 GIGABIT ETHERNET DRIVER
+M: Rasesh Mody <rmody@brocade.com>
+M: Debashis Dutt <ddutt@brocade.com>
+L: netdev@vger.kernel.org
+S: Supported
+F: drivers/net/bna/
+
BSG (block layer generic sg v4 driver)
M: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
L: linux-scsi@vger.kernel.org
@@ -1510,6 +1558,8 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client.git
S: Supported
F: Documentation/filesystems/ceph.txt
F: fs/ceph
+F: net/ceph
+F: include/linux/ceph
CERTIFIED WIRELESS USB (WUSB) SUBSYSTEM:
M: David Vrabel <david.vrabel@csr.com>
@@ -1553,9 +1603,9 @@ S: Supported
F: scripts/checkpatch.pl
CISCO VIC ETHERNET NIC DRIVER
-M: Scott Feldman <scofeldm@cisco.com>
M: Vasanthy Kolluri <vkolluri@cisco.com>
M: Roopa Prabhu <roprabhu@cisco.com>
+M: David Wang <dwang2@cisco.com>
S: Supported
F: drivers/net/enic/
@@ -2033,14 +2083,16 @@ F: drivers/block/drbd/
F: lib/lru_cache.c
F: Documentation/blockdev/drbd/
-DRIVER CORE, KOBJECTS, AND SYSFS
+DRIVER CORE, KOBJECTS, DEBUGFS AND SYSFS
M: Greg Kroah-Hartman <gregkh@suse.de>
T: quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
S: Supported
F: Documentation/kobject.txt
F: drivers/base/
F: fs/sysfs/
+F: fs/debugfs/
F: include/linux/kobj*
+F: include/linux/debugfs.h
F: lib/kobj*
DRM DRIVERS
@@ -2528,7 +2580,7 @@ S: Supported
F: drivers/scsi/gdt*
GENERIC GPIO I2C DRIVER
-M: Haavard Skinnemoen <hskinnemoen@atmel.com>
+M: Haavard Skinnemoen <hskinnemoen@gmail.com>
S: Supported
F: drivers/i2c/busses/i2c-gpio.c
F: include/linux/i2c-gpio.h
@@ -2887,6 +2939,12 @@ M: Brian King <brking@us.ibm.com>
S: Supported
F: drivers/scsi/ipr.*
+IBM Power Virtual Ethernet Device Driver
+M: Santiago Leon <santil@linux.vnet.ibm.com>
+L: netdev@vger.kernel.org
+S: Supported
+F: drivers/net/ibmveth.*
+
IBM ServeRAID RAID DRIVER
P: Jack Hammer
M: Dave Jeffery <ipslinux@adaptec.com>
@@ -3056,16 +3114,27 @@ L: netdev@vger.kernel.org
S: Maintained
F: drivers/net/ixp2000/
-INTEL ETHERNET DRIVERS (e100/e1000/e1000e/igb/igbvf/ixgb/ixgbe)
+INTEL ETHERNET DRIVERS (e100/e1000/e1000e/igb/igbvf/ixgb/ixgbe/ixgbevf)
M: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
M: Jesse Brandeburg <jesse.brandeburg@intel.com>
M: Bruce Allan <bruce.w.allan@intel.com>
-M: Alex Duyck <alexander.h.duyck@intel.com>
+M: Carolyn Wyborny <carolyn.wyborny@intel.com>
+M: Don Skidmore <donald.c.skidmore@intel.com>
+M: Greg Rose <gregory.v.rose@intel.com>
M: PJ Waskiewicz <peter.p.waskiewicz.jr@intel.com>
+M: Alex Duyck <alexander.h.duyck@intel.com>
M: John Ronciak <john.ronciak@intel.com>
L: e1000-devel@lists.sourceforge.net
W: http://e1000.sourceforge.net/
S: Supported
+F: Documentation/networking/e100.txt
+F: Documentation/networking/e1000.txt
+F: Documentation/networking/e1000e.txt
+F: Documentation/networking/igb.txt
+F: Documentation/networking/igbvf.txt
+F: Documentation/networking/ixgb.txt
+F: Documentation/networking/ixgbe.txt
+F: Documentation/networking/ixgbevf.txt
F: drivers/net/e100.c
F: drivers/net/e1000/
F: drivers/net/e1000e/
@@ -3073,6 +3142,7 @@ F: drivers/net/igb/
F: drivers/net/igbvf/
F: drivers/net/ixgb/
F: drivers/net/ixgbe/
+F: drivers/net/ixgbevf/
INTEL PRO/WIRELESS 2100 NETWORK CONNECTION SUPPORT
L: linux-wireless@vger.kernel.org
@@ -3133,7 +3203,7 @@ F: drivers/net/ioc3-eth.c
IOC3 SERIAL DRIVER
M: Pat Gefre <pfg@sgi.com>
-L: linux-mips@linux-mips.org
+L: linux-serial@vger.kernel.org
S: Maintained
F: drivers/serial/ioc3_serial.c
@@ -3210,6 +3280,12 @@ F: drivers/net/irda/
F: include/net/irda/
F: net/irda/
+IRQ SUBSYSTEM
+M: Thomas Gleixner <tglx@linutronix.de>
+S: Maintained
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip.git irq/core
+F: kernel/irq/
+
ISAPNP
M: Jaroslav Kysela <perex@perex.cz>
S: Maintained
@@ -3302,6 +3378,12 @@ F: fs/jbd*/
F: include/linux/ext*jbd*.h
F: include/linux/jbd*.h
+JSM Neo PCI based serial card
+M: Breno Leitao <leitao@linux.vnet.ibm.com>
+L: linux-serial@vger.kernel.org
+S: Maintained
+F: drivers/serial/jsm/
+
K8TEMP HARDWARE MONITORING DRIVER
M: Rudolf Marek <r.marek@assembler.cz>
L: lm-sensors@lm-sensors.org
@@ -3781,9 +3863,8 @@ W: http://www.syskonnect.com
S: Supported
MATROX FRAMEBUFFER DRIVER
-M: Petr Vandrovec <vandrove@vc.cvut.cz>
L: linux-fbdev@vger.kernel.org
-S: Maintained
+S: Orphan
F: drivers/video/matrox/matroxfb_*
F: include/linux/matroxfb.h
@@ -3970,8 +4051,8 @@ S: Maintained
F: drivers/net/natsemi.c
NCP FILESYSTEM
-M: Petr Vandrovec <vandrove@vc.cvut.cz>
-S: Maintained
+M: Petr Vandrovec <petr@vandrovec.name>
+S: Odd Fixes
F: fs/ncpfs/
NCR DUAL 700 SCSI DRIVER (MICROCHANNEL)
@@ -4334,13 +4415,12 @@ F: Documentation/filesystems/dlmfs.txt
F: fs/ocfs2/
ORINOCO DRIVER
-M: Pavel Roskin <proski@gnu.org>
-M: David Gibson <hermes@gibson.dropbear.id.au>
L: linux-wireless@vger.kernel.org
L: orinoco-users@lists.sourceforge.net
L: orinoco-devel@lists.sourceforge.net
+W: http://linuxwireless.org/en/users/Drivers/orinoco
W: http://www.nongnu.org/orinoco/
-S: Maintained
+S: Orphan
F: drivers/net/wireless/orinoco/
OSD LIBRARY and FILESYSTEM
@@ -4528,6 +4608,14 @@ L: linux-abi-devel@lists.sourceforge.net
S: Maintained
F: include/linux/personality.h
+PHONET PROTOCOL
+M: Remi Denis-Courmont <remi.denis-courmont@nokia.com>
+S: Supported
+F: Documentation/networking/phonet.txt
+F: include/linux/phonet.h
+F: include/net/phonet/
+F: net/phonet/
+
PHRAM MTD DRIVER
M: Joern Engel <joern@lazybastard.org>
L: linux-mtd@lists.infradead.org
@@ -4777,6 +4865,15 @@ F: fs/qnx4/
F: include/linux/qnx4_fs.h
F: include/linux/qnxtypes.h
+RADOS BLOCK DEVICE (RBD)
+F: include/linux/qnxtypes.h
+M: Yehuda Sadeh <yehuda@hq.newdream.net>
+M: Sage Weil <sage@newdream.net>
+M: ceph-devel@vger.kernel.org
+S: Supported
+F: drivers/block/rbd.c
+F: drivers/block/rbd_types.h
+
RADEON FRAMEBUFFER DISPLAY DRIVER
M: Benjamin Herrenschmidt <benh@kernel.crashing.org>
L: linux-fbdev@vger.kernel.org
@@ -5002,6 +5099,12 @@ F: drivers/media/common/saa7146*
F: drivers/media/video/*7146*
F: include/media/*7146*
+SAMSUNG AUDIO (ASoC) DRIVERS
+M: Jassi Brar <jassi.brar@samsung.com>
+L: alsa-devel@alsa-project.org (moderated for non-subscribers)
+S: Supported
+F: sound/soc/s3c24xx
+
TLG2300 VIDEO4LINUX-2 DRIVER
M: Huang Shijie <shijie8@gmail.com>
M: Kang Yong <kangyong@telegent.com>
@@ -5900,6 +6003,14 @@ S: Maintained
F: Documentation/usb/acm.txt
F: drivers/usb/class/cdc-acm.*
+USB ATTACHED SCSI
+M: Matthew Wilcox <willy@linux.intel.com>
+M: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+L: linux-usb@vger.kernel.org
+L: linux-scsi@vger.kernel.org
+S: Supported
+F: drivers/usb/storage/uas.c
+
USB BLOCK DRIVER (UB ub)
M: Pete Zaitcev <zaitcev@redhat.com>
L: linux-usb@vger.kernel.org
@@ -6408,21 +6519,21 @@ S: Maintained
F: drivers/input/misc/wistron_btns.c
WL1251 WIRELESS DRIVER
-M: Kalle Valo <kalle.valo@iki.fi>
+M: Kalle Valo <kvalo@adurom.com>
L: linux-wireless@vger.kernel.org
W: http://wireless.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
S: Maintained
-F: drivers/net/wireless/wl12xx/*
-X: drivers/net/wireless/wl12xx/wl1271*
+F: drivers/net/wireless/wl1251/*
WL1271 WIRELESS DRIVER
M: Luciano Coelho <luciano.coelho@nokia.com>
L: linux-wireless@vger.kernel.org
W: http://wireless.kernel.org
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx.git
S: Maintained
F: drivers/net/wireless/wl12xx/wl1271*
+F: include/linux/wl12xx.h
WL3501 WIRELESS PCMCIA CARD DRIVER
M: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
@@ -6444,8 +6555,10 @@ F: include/linux/wm97xx.h
WOLFSON MICROELECTRONICS DRIVERS
M: Mark Brown <broonie@opensource.wolfsonmicro.com>
M: Ian Lartey <ian@opensource.wolfsonmicro.com>
+M: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
+T: git git://opensource.wolfsonmicro.com/linux-2.6-asoc
T: git git://opensource.wolfsonmicro.com/linux-2.6-audioplus
-W: http://opensource.wolfsonmicro.com/node/8
+W: http://opensource.wolfsonmicro.com/content/linux-drivers-wolfson-devices
S: Supported
F: Documentation/hwmon/wm83??
F: drivers/leds/leds-wm83*.c
@@ -6567,6 +6680,20 @@ M: "Maciej W. Rozycki" <macro@linux-mips.org>
S: Maintained
F: drivers/serial/zs.*
+GRE DEMULTIPLEXER DRIVER
+M: Dmitry Kozlov <xeb@mail.ru>
+L: netdev@vger.kernel.org
+S: Maintained
+F: net/ipv4/gre.c
+F: include/net/gre.h
+
+PPTP DRIVER
+M: Dmitry Kozlov <xeb@mail.ru>
+L: netdev@vger.kernel.org
+S: Maintained
+F: drivers/net/pptp.c
+W: http://sourceforge.net/projects/accel-pptp
+
THE REST
M: Linus Torvalds <torvalds@linux-foundation.org>
L: linux-kernel@vger.kernel.org
diff --git a/Makefile b/Makefile
index 471c49fd2f43..3e438055a92c 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 36
-EXTRAVERSION = -rc6
-NAME = Sheep on Meth
+EXTRAVERSION =
+NAME = Flesh-Eating Bats with Fangs
# *DOCUMENTATION*
# To see a list of typical targets execute "make help"
@@ -554,8 +554,15 @@ endif
ifdef CONFIG_FRAME_POINTER
KBUILD_CFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls
else
+# Some targets (ARM with Thumb2, for example), can't be built with frame
+# pointers. For those, we don't have FUNCTION_TRACER automatically
+# select FRAME_POINTER. However, FUNCTION_TRACER adds -pg, and this is
+# incompatible with -fomit-frame-pointer with current GCC, so we don't use
+# -fomit-frame-pointer with FUNCTION_TRACER.
+ifndef CONFIG_FUNCTION_TRACER
KBUILD_CFLAGS += -fomit-frame-pointer
endif
+endif
ifdef CONFIG_DEBUG_INFO
KBUILD_CFLAGS += -g
@@ -568,6 +575,12 @@ endif
ifdef CONFIG_FUNCTION_TRACER
KBUILD_CFLAGS += -pg
+ifdef CONFIG_DYNAMIC_FTRACE
+ ifdef CONFIG_HAVE_C_RECORDMCOUNT
+ BUILD_C_RECORDMCOUNT := y
+ export BUILD_C_RECORDMCOUNT
+ endif
+endif
endif
# We trigger additional mismatches with less inlining
@@ -591,6 +604,11 @@ KBUILD_CFLAGS += $(call cc-option,-fno-strict-overflow)
# conserve stack if available
KBUILD_CFLAGS += $(call cc-option,-fconserve-stack)
+# check for 'asm goto'
+ifeq ($(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-goto.sh $(CC)), y)
+ KBUILD_CFLAGS += -DCC_HAVE_ASM_GOTO
+endif
+
# Add user supplied CPPFLAGS, AFLAGS and CFLAGS as the last assignments
# But warn user when we do so
warn-assign = \
diff --git a/arch/Kconfig b/arch/Kconfig
index fe48fc7a3eba..53d7f619a1b9 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -158,4 +158,7 @@ config HAVE_PERF_EVENTS_NMI
subsystem. Also has support for calculating CPU cycle events
to determine how many clock cycles in a given period.
+config HAVE_ARCH_JUMP_LABEL
+ bool
+
source "kernel/gcov/Kconfig"
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index b9647bb66d13..d04ccd73af45 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -9,6 +9,7 @@ config ALPHA
select HAVE_IDE
select HAVE_OPROFILE
select HAVE_SYSCALL_WRAPPERS
+ select HAVE_IRQ_WORK
select HAVE_PERF_EVENTS
select HAVE_DMA_ATTRS
help
diff --git a/arch/alpha/include/asm/irqflags.h b/arch/alpha/include/asm/irqflags.h
new file mode 100644
index 000000000000..299bbc7e9d71
--- /dev/null
+++ b/arch/alpha/include/asm/irqflags.h
@@ -0,0 +1,67 @@
+#ifndef __ALPHA_IRQFLAGS_H
+#define __ALPHA_IRQFLAGS_H
+
+#include <asm/system.h>
+
+#define IPL_MIN 0
+#define IPL_SW0 1
+#define IPL_SW1 2
+#define IPL_DEV0 3
+#define IPL_DEV1 4
+#define IPL_TIMER 5
+#define IPL_PERF 6
+#define IPL_POWERFAIL 6
+#define IPL_MCHECK 7
+#define IPL_MAX 7
+
+#ifdef CONFIG_ALPHA_BROKEN_IRQ_MASK
+#undef IPL_MIN
+#define IPL_MIN __min_ipl
+extern int __min_ipl;
+#endif
+
+#define getipl() (rdps() & 7)
+#define setipl(ipl) ((void) swpipl(ipl))
+
+static inline unsigned long arch_local_save_flags(void)
+{
+ return rdps();
+}
+
+static inline void arch_local_irq_disable(void)
+{
+ setipl(IPL_MAX);
+ barrier();
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+ unsigned long flags = swpipl(IPL_MAX);
+ barrier();
+ return flags;
+}
+
+static inline void arch_local_irq_enable(void)
+{
+ barrier();
+ setipl(IPL_MIN);
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+ barrier();
+ setipl(flags);
+ barrier();
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+ return flags == IPL_MAX;
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+ return arch_irqs_disabled_flags(getipl());
+}
+
+#endif /* __ALPHA_IRQFLAGS_H */
diff --git a/arch/alpha/include/asm/perf_event.h b/arch/alpha/include/asm/perf_event.h
index 4157cd3c44a9..fe792ca818f6 100644
--- a/arch/alpha/include/asm/perf_event.h
+++ b/arch/alpha/include/asm/perf_event.h
@@ -1,11 +1,6 @@
#ifndef __ASM_ALPHA_PERF_EVENT_H
#define __ASM_ALPHA_PERF_EVENT_H
-/* Alpha only supports software events through this interface. */
-extern void set_perf_event_pending(void);
-
-#define PERF_EVENT_INDEX_OFFSET 0
-
#ifdef CONFIG_PERF_EVENTS
extern void init_hw_perf_events(void);
#else
diff --git a/arch/alpha/include/asm/system.h b/arch/alpha/include/asm/system.h
index 5aa40cca4f23..9f78e6934637 100644
--- a/arch/alpha/include/asm/system.h
+++ b/arch/alpha/include/asm/system.h
@@ -259,34 +259,6 @@ __CALL_PAL_RW2(wrperfmon, unsigned long, unsigned long, unsigned long);
__CALL_PAL_W1(wrusp, unsigned long);
__CALL_PAL_W1(wrvptptr, unsigned long);
-#define IPL_MIN 0
-#define IPL_SW0 1
-#define IPL_SW1 2
-#define IPL_DEV0 3
-#define IPL_DEV1 4
-#define IPL_TIMER 5
-#define IPL_PERF 6
-#define IPL_POWERFAIL 6
-#define IPL_MCHECK 7
-#define IPL_MAX 7
-
-#ifdef CONFIG_ALPHA_BROKEN_IRQ_MASK
-#undef IPL_MIN
-#define IPL_MIN __min_ipl
-extern int __min_ipl;
-#endif
-
-#define getipl() (rdps() & 7)
-#define setipl(ipl) ((void) swpipl(ipl))
-
-#define local_irq_disable() do { setipl(IPL_MAX); barrier(); } while(0)
-#define local_irq_enable() do { barrier(); setipl(IPL_MIN); } while(0)
-#define local_save_flags(flags) ((flags) = rdps())
-#define local_irq_save(flags) do { (flags) = swpipl(IPL_MAX); barrier(); } while(0)
-#define local_irq_restore(flags) do { barrier(); setipl(flags); barrier(); } while(0)
-
-#define irqs_disabled() (getipl() == IPL_MAX)
-
/*
* TB routines..
*/
diff --git a/arch/alpha/kernel/perf_event.c b/arch/alpha/kernel/perf_event.c
index 85d8e4f58c83..1cc49683fb69 100644
--- a/arch/alpha/kernel/perf_event.c
+++ b/arch/alpha/kernel/perf_event.c
@@ -307,7 +307,7 @@ again:
new_raw_count) != prev_raw_count)
goto again;
- delta = (new_raw_count - (prev_raw_count & alpha_pmu->pmc_count_mask[idx])) + ovf;
+ delta = (new_raw_count - (prev_raw_count & alpha_pmu->pmc_count_mask[idx])) + ovf;
/* It is possible on very rare occasions that the PMC has overflowed
* but the interrupt is yet to come. Detect and fix this situation.
@@ -402,14 +402,13 @@ static void maybe_change_configuration(struct cpu_hw_events *cpuc)
struct hw_perf_event *hwc = &pe->hw;
int idx = hwc->idx;
- if (cpuc->current_idx[j] != PMC_NO_INDEX) {
- cpuc->idx_mask |= (1<<cpuc->current_idx[j]);
- continue;
+ if (cpuc->current_idx[j] == PMC_NO_INDEX) {
+ alpha_perf_event_set_period(pe, hwc, idx);
+ cpuc->current_idx[j] = idx;
}
- alpha_perf_event_set_period(pe, hwc, idx);
- cpuc->current_idx[j] = idx;
- cpuc->idx_mask |= (1<<cpuc->current_idx[j]);
+ if (!(hwc->state & PERF_HES_STOPPED))
+ cpuc->idx_mask |= (1<<cpuc->current_idx[j]);
}
cpuc->config = cpuc->event[0]->hw.config_base;
}
@@ -420,12 +419,13 @@ static void maybe_change_configuration(struct cpu_hw_events *cpuc)
* - this function is called from outside this module via the pmu struct
* returned from perf event initialisation.
*/
-static int alpha_pmu_enable(struct perf_event *event)
+static int alpha_pmu_add(struct perf_event *event, int flags)
{
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+ struct hw_perf_event *hwc = &event->hw;
int n0;
int ret;
- unsigned long flags;
+ unsigned long irq_flags;
/*
* The Sparc code has the IRQ disable first followed by the perf
@@ -435,8 +435,8 @@ static int alpha_pmu_enable(struct perf_event *event)
* nevertheless we disable the PMCs first to enable a potential
* final PMI to occur before we disable interrupts.
*/
- perf_disable();
- local_irq_save(flags);
+ perf_pmu_disable(event->pmu);
+ local_irq_save(irq_flags);
/* Default to error to be returned */
ret = -EAGAIN;
@@ -455,8 +455,12 @@ static int alpha_pmu_enable(struct perf_event *event)
}
}
- local_irq_restore(flags);
- perf_enable();
+ hwc->state = PERF_HES_UPTODATE;
+ if (!(flags & PERF_EF_START))
+ hwc->state |= PERF_HES_STOPPED;
+
+ local_irq_restore(irq_flags);
+ perf_pmu_enable(event->pmu);
return ret;
}
@@ -467,15 +471,15 @@ static int alpha_pmu_enable(struct perf_event *event)
* - this function is called from outside this module via the pmu struct
* returned from perf event initialisation.
*/
-static void alpha_pmu_disable(struct perf_event *event)
+static void alpha_pmu_del(struct perf_event *event, int flags)
{
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
struct hw_perf_event *hwc = &event->hw;
- unsigned long flags;
+ unsigned long irq_flags;
int j;
- perf_disable();
- local_irq_save(flags);
+ perf_pmu_disable(event->pmu);
+ local_irq_save(irq_flags);
for (j = 0; j < cpuc->n_events; j++) {
if (event == cpuc->event[j]) {
@@ -501,8 +505,8 @@ static void alpha_pmu_disable(struct perf_event *event)
}
}
- local_irq_restore(flags);
- perf_enable();
+ local_irq_restore(irq_flags);
+ perf_pmu_enable(event->pmu);
}
@@ -514,13 +518,44 @@ static void alpha_pmu_read(struct perf_event *event)
}
-static void alpha_pmu_unthrottle(struct perf_event *event)
+static void alpha_pmu_stop(struct perf_event *event, int flags)
+{
+ struct hw_perf_event *hwc = &event->hw;
+ struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+
+ if (!(hwc->state & PERF_HES_STOPPED)) {
+ cpuc->idx_mask &= ~(1UL<<hwc->idx);
+ hwc->state |= PERF_HES_STOPPED;
+ }
+
+ if ((flags & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) {
+ alpha_perf_event_update(event, hwc, hwc->idx, 0);
+ hwc->state |= PERF_HES_UPTODATE;
+ }
+
+ if (cpuc->enabled)
+ wrperfmon(PERFMON_CMD_DISABLE, (1UL<<hwc->idx));
+}
+
+
+static void alpha_pmu_start(struct perf_event *event, int flags)
{
struct hw_perf_event *hwc = &event->hw;
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+ if (WARN_ON_ONCE(!(hwc->state & PERF_HES_STOPPED)))
+ return;
+
+ if (flags & PERF_EF_RELOAD) {
+ WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE));
+ alpha_perf_event_set_period(event, hwc, hwc->idx);
+ }
+
+ hwc->state = 0;
+
cpuc->idx_mask |= 1UL<<hwc->idx;
- wrperfmon(PERFMON_CMD_ENABLE, (1UL<<hwc->idx));
+ if (cpuc->enabled)
+ wrperfmon(PERFMON_CMD_ENABLE, (1UL<<hwc->idx));
}
@@ -642,39 +677,36 @@ static int __hw_perf_event_init(struct perf_event *event)
return 0;
}
-static const struct pmu pmu = {
- .enable = alpha_pmu_enable,
- .disable = alpha_pmu_disable,
- .read = alpha_pmu_read,
- .unthrottle = alpha_pmu_unthrottle,
-};
-
-
/*
* Main entry point to initialise a HW performance event.
*/
-const struct pmu *hw_perf_event_init(struct perf_event *event)
+static int alpha_pmu_event_init(struct perf_event *event)
{
int err;
+ switch (event->attr.type) {
+ case PERF_TYPE_RAW:
+ case PERF_TYPE_HARDWARE:
+ case PERF_TYPE_HW_CACHE:
+ break;
+
+ default:
+ return -ENOENT;
+ }
+
if (!alpha_pmu)
- return ERR_PTR(-ENODEV);
+ return -ENODEV;
/* Do the real initialisation work. */
err = __hw_perf_event_init(event);
- if (err)
- return ERR_PTR(err);
-
- return &pmu;
+ return err;
}
-
-
/*
* Main entry point - enable HW performance counters.
*/
-void hw_perf_enable(void)
+static void alpha_pmu_enable(struct pmu *pmu)
{
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
@@ -700,7 +732,7 @@ void hw_perf_enable(void)
* Main entry point - disable HW performance counters.
*/
-void hw_perf_disable(void)
+static void alpha_pmu_disable(struct pmu *pmu)
{
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
@@ -713,6 +745,17 @@ void hw_perf_disable(void)
wrperfmon(PERFMON_CMD_DISABLE, cpuc->idx_mask);
}
+static struct pmu pmu = {
+ .pmu_enable = alpha_pmu_enable,
+ .pmu_disable = alpha_pmu_disable,
+ .event_init = alpha_pmu_event_init,
+ .add = alpha_pmu_add,
+ .del = alpha_pmu_del,
+ .start = alpha_pmu_start,
+ .stop = alpha_pmu_stop,
+ .read = alpha_pmu_read,
+};
+
/*
* Main entry point - don't know when this is called but it
@@ -766,7 +809,7 @@ static void alpha_perf_event_irq_handler(unsigned long la_ptr,
wrperfmon(PERFMON_CMD_DISABLE, cpuc->idx_mask);
/* la_ptr is the counter that overflowed. */
- if (unlikely(la_ptr >= perf_max_events)) {
+ if (unlikely(la_ptr >= alpha_pmu->num_pmcs)) {
/* This should never occur! */
irq_err_count++;
pr_warning("PMI: silly index %ld\n", la_ptr);
@@ -807,7 +850,7 @@ static void alpha_perf_event_irq_handler(unsigned long la_ptr,
/* Interrupts coming too quickly; "throttle" the
* counter, i.e., disable it for a little while.
*/
- cpuc->idx_mask &= ~(1UL<<idx);
+ alpha_pmu_stop(event, 0);
}
}
wrperfmon(PERFMON_CMD_ENABLE, cpuc->idx_mask);
@@ -837,6 +880,7 @@ void __init init_hw_perf_events(void)
/* And set up PMU specification */
alpha_pmu = &ev67_pmu;
- perf_max_events = alpha_pmu->num_pmcs;
+
+ perf_pmu_register(&pmu);
}
diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c
index d290845aef59..6f7feb5db271 100644
--- a/arch/alpha/kernel/signal.c
+++ b/arch/alpha/kernel/signal.c
@@ -48,7 +48,7 @@ SYSCALL_DEFINE2(osf_sigprocmask, int, how, unsigned long, newmask)
sigset_t mask;
unsigned long res;
- siginitset(&mask, newmask & ~_BLOCKABLE);
+ siginitset(&mask, newmask & _BLOCKABLE);
res = sigprocmask(how, &mask, &oldmask);
if (!res) {
force_successful_syscall_return();
diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c
index 396af1799ea4..0f1d8493cfca 100644
--- a/arch/alpha/kernel/time.c
+++ b/arch/alpha/kernel/time.c
@@ -41,7 +41,7 @@
#include <linux/init.h>
#include <linux/bcd.h>
#include <linux/profile.h>
-#include <linux/perf_event.h>
+#include <linux/irq_work.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -83,25 +83,25 @@ static struct {
unsigned long est_cycle_freq;
-#ifdef CONFIG_PERF_EVENTS
+#ifdef CONFIG_IRQ_WORK
-DEFINE_PER_CPU(u8, perf_event_pending);
+DEFINE_PER_CPU(u8, irq_work_pending);
-#define set_perf_event_pending_flag() __get_cpu_var(perf_event_pending) = 1
-#define test_perf_event_pending() __get_cpu_var(perf_event_pending)
-#define clear_perf_event_pending() __get_cpu_var(perf_event_pending) = 0
+#define set_irq_work_pending_flag() __get_cpu_var(irq_work_pending) = 1
+#define test_irq_work_pending() __get_cpu_var(irq_work_pending)
+#define clear_irq_work_pending() __get_cpu_var(irq_work_pending) = 0
-void set_perf_event_pending(void)
+void set_irq_work_pending(void)
{
- set_perf_event_pending_flag();
+ set_irq_work_pending_flag();
}
-#else /* CONFIG_PERF_EVENTS */
+#else /* CONFIG_IRQ_WORK */
-#define test_perf_event_pending() 0
-#define clear_perf_event_pending()
+#define test_irq_work_pending() 0
+#define clear_irq_work_pending()
-#endif /* CONFIG_PERF_EVENTS */
+#endif /* CONFIG_IRQ_WORK */
static inline __u32 rpcc(void)
@@ -191,9 +191,9 @@ irqreturn_t timer_interrupt(int irq, void *dev)
write_sequnlock(&xtime_lock);
- if (test_perf_event_pending()) {
- clear_perf_event_pending();
- perf_event_do_pending();
+ if (test_irq_work_pending()) {
+ clear_irq_work_pending();
+ irq_work_run();
}
#ifndef CONFIG_SMP
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 88c97bc7a6f5..3849887157e7 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -19,13 +19,17 @@ config ARM
select HAVE_KPROBES if (!XIP_KERNEL)
select HAVE_KRETPROBES if (HAVE_KPROBES)
select HAVE_FUNCTION_TRACER if (!XIP_KERNEL)
+ select HAVE_FTRACE_MCOUNT_RECORD if (!XIP_KERNEL)
+ select HAVE_DYNAMIC_FTRACE if (!XIP_KERNEL)
select HAVE_GENERIC_DMA_COHERENT
select HAVE_KERNEL_GZIP
select HAVE_KERNEL_LZO
select HAVE_KERNEL_LZMA
+ select HAVE_IRQ_WORK
select HAVE_PERF_EVENTS
select PERF_USE_VMALLOC
select HAVE_REGS_AND_STACK_ACCESS_API
+ select HAVE_HW_BREAKPOINT if (PERF_EVENTS && (CPU_V6 || CPU_V7))
help
The ARM series is a line of low-power-consumption RISC chip designs
licensed by ARM Ltd and targeted at embedded applications and
@@ -145,6 +149,9 @@ config ARCH_HAS_CPUFREQ
and that the relevant menu configurations are displayed for
it.
+config ARCH_HAS_CPU_IDLE_WAIT
+ def_bool y
+
config GENERIC_HWEIGHT
bool
default y
@@ -510,6 +517,7 @@ config ARCH_MMP
select GENERIC_CLOCKEVENTS
select TICK_ONESHOT
select PLAT_PXA
+ select SPARSE_IRQ
help
Support for Marvell's PXA168/PXA910(MMP) and MMP2 processor line.
@@ -587,6 +595,7 @@ config ARCH_PXA
select GENERIC_CLOCKEVENTS
select TICK_ONESHOT
select PLAT_PXA
+ select SPARSE_IRQ
help
Support for Intel/Marvell's PXA2xx/PXA3xx processor line.
@@ -678,8 +687,8 @@ config ARCH_S3C64XX
help
Samsung S3C64XX series based systems
-config ARCH_S5P6440
- bool "Samsung S5P6440"
+config ARCH_S5P64X0
+ bool "Samsung S5P6440 S5P6450"
select CPU_V6
select GENERIC_GPIO
select HAVE_CLK
@@ -688,7 +697,8 @@ config ARCH_S5P6440
select HAVE_S3C2410_I2C
select HAVE_S3C_RTC
help
- Samsung S5P6440 CPU based systems
+ Samsung S5P64X0 CPU based systems, such as the Samsung SMDK6440,
+ SMDK6450.
config ARCH_S5P6442
bool "Samsung S5P6442"
@@ -747,6 +757,15 @@ config ARCH_SHARK
Support for the StrongARM based Digital DNARD machine, also known
as "Shark" (<http://www.shark-linux.de/shark.html>).
+config ARCH_TCC_926
+ bool "Telechips TCC ARM926-based systems"
+ select CPU_ARM926T
+ select HAVE_CLK
+ select COMMON_CLKDEV
+ select GENERIC_CLOCKEVENTS
+ help
+ Support for Telechips TCC ARM926-based systems.
+
config ARCH_LH7A40X
bool "Sharp LH7A40X"
select CPU_ARM922T
@@ -915,6 +934,8 @@ source "arch/arm/plat-s5p/Kconfig"
source "arch/arm/plat-spear/Kconfig"
+source "arch/arm/plat-tcc/Kconfig"
+
if ARCH_S3C2410
source "arch/arm/mach-s3c2400/Kconfig"
source "arch/arm/mach-s3c2410/Kconfig"
@@ -928,7 +949,7 @@ if ARCH_S3C64XX
source "arch/arm/mach-s3c64xx/Kconfig"
endif
-source "arch/arm/mach-s5p6440/Kconfig"
+source "arch/arm/mach-s5p64x0/Kconfig"
source "arch/arm/mach-s5p6442/Kconfig"
@@ -1002,7 +1023,7 @@ endif
config ARM_ERRATA_411920
bool "ARM errata: Invalidation of the Instruction Cache operation can fail"
- depends on CPU_V6 && !SMP
+ depends on CPU_V6
help
Invalidation of the Instruction Cache operation can
fail. This erratum is present in 1136 (before r1p4), 1156 and 1176.
@@ -1101,6 +1122,20 @@ config ARM_ERRATA_720789
invalidated are not, resulting in an incoherency in the system page
tables. The workaround changes the TLB flushing routines to invalidate
entries regardless of the ASID.
+
+config ARM_ERRATA_743622
+ bool "ARM errata: Faulty hazard checking in the Store Buffer may lead to data corruption"
+ depends on CPU_V7
+ help
+ This option enables the workaround for the 743622 Cortex-A9
+ (r2p0..r2p2) erratum. Under very rare conditions, a faulty
+ optimisation in the Cortex-A9 Store Buffer may lead to data
+ corruption. This workaround sets a specific bit in the diagnostic
+ register of the Cortex-A9 which disables the Store Buffer
+ optimisation, preventing the defect from occurring. This has no
+ visible impact on the overall performance or power consumption of the
+ processor.
+
endmenu
source "arch/arm/common/Kconfig"
@@ -1167,13 +1202,13 @@ source "kernel/time/Kconfig"
config SMP
bool "Symmetric Multi-Processing (EXPERIMENTAL)"
- depends on EXPERIMENTAL && (REALVIEW_EB_ARM11MP || REALVIEW_EB_A9MP ||\
- MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBX || ARCH_OMAP4 ||\
- ARCH_S5PV310 || ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS_CA9X4)
+ depends on EXPERIMENTAL
depends on GENERIC_CLOCKEVENTS
+ depends on REALVIEW_EB_ARM11MP || REALVIEW_EB_A9MP || \
+ MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBX || ARCH_OMAP4 ||\
+ ARCH_S5PV310 || ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS_CA9X4
select USE_GENERIC_SMP_HELPERS
- select HAVE_ARM_SCU if ARCH_REALVIEW || ARCH_OMAP4 || ARCH_S5PV310 ||\
- ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS_CA9X4
+ select HAVE_ARM_SCU
help
This enables support for systems with more than one CPU. If you have
a system with only one CPU, like most personal computers, say N. If
@@ -1191,6 +1226,19 @@ config SMP
If you don't know what to do here, say N.
+config SMP_ON_UP
+ bool "Allow booting SMP kernel on uniprocessor systems (EXPERIMENTAL)"
+ depends on EXPERIMENTAL
+ depends on SMP && !XIP && !THUMB2_KERNEL
+ default y
+ help
+ SMP kernels contain instructions which fail on non-SMP processors.
+ Enabling this option allows the kernel to modify itself to make
+ these instructions safe. Disabling it allows about 1K of space
+ savings.
+
+ If you don't know what to do here, say Y.
+
config HAVE_ARM_SCU
bool
depends on SMP
@@ -1241,12 +1289,9 @@ config HOTPLUG_CPU
config LOCAL_TIMERS
bool "Use local timer interrupts"
- depends on SMP && (REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || \
- REALVIEW_EB_A9MP || MACH_REALVIEW_PBX || ARCH_OMAP4 || \
- ARCH_S5PV310 || ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS_CA9X4)
+ depends on SMP
default y
- select HAVE_ARM_TWD if ARCH_REALVIEW || ARCH_OMAP4 || ARCH_S5PV310 || \
- ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS
+ select HAVE_ARM_TWD
help
Enable support for local timers on SMP platforms, rather then the
legacy IPI broadcast method. Local timers allows the system
@@ -1257,7 +1302,7 @@ source kernel/Kconfig.preempt
config HZ
int
- default 200 if ARCH_EBSA110 || ARCH_S3C2410 || ARCH_S5P6440 || \
+ default 200 if ARCH_EBSA110 || ARCH_S3C2410 || ARCH_S5P64X0 || \
ARCH_S5P6442 || ARCH_S5PV210 || ARCH_S5PV310
default OMAP_32K_TIMER_HZ if ARCH_OMAP && OMAP_32K_TIMER
default AT91_TIMER_HZ if ARCH_AT91
@@ -1463,6 +1508,20 @@ config UACCESS_WITH_MEMCPY
However, if the CPU data cache is using a write-allocate mode,
this option is unlikely to provide any performance gain.
+config SECCOMP
+ bool
+ prompt "Enable seccomp to safely compute untrusted bytecode"
+ ---help---
+ This kernel feature is useful for number crunching applications
+ that may need to compute untrusted bytecode during their
+ execution. By using pipes or other transports made available to
+ the process as file descriptors supporting the read/write
+ syscalls, it's possible to isolate those applications in
+ their own address space using seccomp. Once seccomp is
+ enabled via prctl(PR_SET_SECCOMP), it cannot be disabled
+ and the task is only allowed to execute a few safe syscalls
+ defined by each seccomp mode.
+
config CC_STACKPROTECTOR
bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)"
help
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 91344af75f39..2fd0b99afc4b 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -2,6 +2,20 @@ menu "Kernel hacking"
source "lib/Kconfig.debug"
+config STRICT_DEVMEM
+ bool "Filter access to /dev/mem"
+ depends on MMU
+ ---help---
+ If this option is disabled, you allow userspace (root) access to all
+ of memory, including kernel and userspace memory. Accidental
+ access to this is obviously disastrous, but specific access can
+ be used by people debugging the kernel.
+
+ If this option is switched on, the /dev/mem file only allows
+ userspace access to memory mapped peripherals.
+
+ If in doubt, say Y.
+
# RMK wants arm kernels compiled with frame pointers or stack unwinding.
# If you know what you are doing and are willing to live without stack
# traces, you can get a slightly smaller kernel by setting this option to
@@ -27,6 +41,11 @@ config ARM_UNWIND
the performance is not affected. Currently, this feature
only works with EABI compilers. If unsure say Y.
+config OLD_MCOUNT
+ bool
+ depends on FUNCTION_TRACER && FRAME_POINTER
+ default y
+
config DEBUG_USER
bool "Verbose user fault messages"
help
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 59c1ce858fc8..b87aed028eef 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -173,7 +173,7 @@ machine-$(CONFIG_ARCH_RPC) := rpc
machine-$(CONFIG_ARCH_S3C2410) := s3c2410 s3c2400 s3c2412 s3c2416 s3c2440 s3c2443
machine-$(CONFIG_ARCH_S3C24A0) := s3c24a0
machine-$(CONFIG_ARCH_S3C64XX) := s3c64xx
-machine-$(CONFIG_ARCH_S5P6440) := s5p6440
+machine-$(CONFIG_ARCH_S5P64X0) := s5p64x0
machine-$(CONFIG_ARCH_S5P6442) := s5p6442
machine-$(CONFIG_ARCH_S5PC100) := s5pc100
machine-$(CONFIG_ARCH_S5PV210) := s5pv210
@@ -183,6 +183,7 @@ machine-$(CONFIG_ARCH_SHARK) := shark
machine-$(CONFIG_ARCH_SHMOBILE) := shmobile
machine-$(CONFIG_ARCH_STMP378X) := stmp378x
machine-$(CONFIG_ARCH_STMP37XX) := stmp37xx
+machine-$(CONFIG_ARCH_TCC8K) := tcc8k
machine-$(CONFIG_ARCH_TEGRA) := tegra
machine-$(CONFIG_ARCH_U300) := u300
machine-$(CONFIG_ARCH_U8500) := ux500
@@ -202,6 +203,7 @@ plat-$(CONFIG_ARCH_MXC) := mxc
plat-$(CONFIG_ARCH_OMAP) := omap
plat-$(CONFIG_ARCH_S3C64XX) := samsung
plat-$(CONFIG_ARCH_STMP3XXX) := stmp3xxx
+plat-$(CONFIG_ARCH_TCC_926) := tcc
plat-$(CONFIG_PLAT_IOP) := iop
plat-$(CONFIG_PLAT_NOMADIK) := nomadik
plat-$(CONFIG_PLAT_ORION) := orion
@@ -245,13 +247,14 @@ ifeq ($(FASTFPE),$(wildcard $(FASTFPE)))
FASTFPE_OBJ :=$(FASTFPE)/
endif
-# If we have a machine-specific directory, then include it in the build.
-core-y += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
-core-y += $(machdirs) $(platdirs)
core-$(CONFIG_FPE_NWFPE) += arch/arm/nwfpe/
core-$(CONFIG_FPE_FASTFPE) += $(FASTFPE_OBJ)
core-$(CONFIG_VFP) += arch/arm/vfp/
+# If we have a machine-specific directory, then include it in the build.
+core-y += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
+core-y += $(machdirs) $(platdirs)
+
drivers-$(CONFIG_OPROFILE) += arch/arm/oprofile/
libs-y := arch/arm/lib/ $(libs-y)
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index 7dfa9a85bc0c..ada6359160eb 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -67,25 +67,11 @@ static inline unsigned int gic_irq(unsigned int irq)
/*
* Routines to acknowledge, disable and enable interrupts
- *
- * Linux assumes that when we're done with an interrupt we need to
- * unmask it, in the same way we need to unmask an interrupt when
- * we first enable it.
- *
- * The GIC has a separate notion of "end of interrupt" to re-enable
- * an interrupt after handling, in order to support hardware
- * prioritisation.
- *
- * We can make the GIC behave in the way that Linux expects by making
- * our "acknowledge" routine disable the interrupt, then mark it as
- * complete.
*/
static void gic_ack_irq(unsigned int irq)
{
- u32 mask = 1 << (irq % 32);
spin_lock(&irq_controller_lock);
- writel(mask, gic_dist_base(irq) + GIC_DIST_ENABLE_CLEAR + (gic_irq(irq) / 32) * 4);
writel(gic_irq(irq), gic_cpu_base(irq) + GIC_CPU_EOI);
spin_unlock(&irq_controller_lock);
}
diff --git a/arch/arm/common/pl330.c b/arch/arm/common/pl330.c
index 5ebbab6242a7..8f0f86db3602 100644
--- a/arch/arm/common/pl330.c
+++ b/arch/arm/common/pl330.c
@@ -146,8 +146,7 @@
#define DESIGNER 0x41
#define REVISION 0x0
#define INTEG_CFG 0x0
-#define PERIPH_ID_VAL ((PART << 0) | (DESIGNER << 12) \
- | (REVISION << 20) | (INTEG_CFG << 24))
+#define PERIPH_ID_VAL ((PART << 0) | (DESIGNER << 12))
#define PCELL_ID_VAL 0xb105f00d
@@ -1859,10 +1858,10 @@ int pl330_add(struct pl330_info *pi)
regs = pi->base;
/* Check if we can handle this DMAC */
- if (get_id(pi, PERIPH_ID) != PERIPH_ID_VAL
+ if ((get_id(pi, PERIPH_ID) & 0xfffff) != PERIPH_ID_VAL
|| get_id(pi, PCELL_ID) != PCELL_ID_VAL) {
dev_err(pi->dev, "PERIPH_ID 0x%x, PCELL_ID 0x%x !\n",
- readl(regs + PERIPH_ID), readl(regs + PCELL_ID));
+ get_id(pi, PERIPH_ID), get_id(pi, PCELL_ID));
return -EINVAL;
}
diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c
index 517d50ddbeb3..c0258a8c103b 100644
--- a/arch/arm/common/sa1111.c
+++ b/arch/arm/common/sa1111.c
@@ -678,7 +678,7 @@ out:
* %-EBUSY physical address already marked in-use.
* %0 successful.
*/
-static int
+static int __devinit
__sa1111_probe(struct device *me, struct resource *mem, int irq)
{
struct sa1111 *sachip;
diff --git a/arch/arm/configs/at91sam9g20ek_defconfig b/arch/arm/configs/at91sam9g20ek_defconfig
index f1bac70d6ce9..9e90e6d79297 100644
--- a/arch/arm/configs/at91sam9g20ek_defconfig
+++ b/arch/arm/configs/at91sam9g20ek_defconfig
@@ -13,6 +13,7 @@ CONFIG_MODULE_UNLOAD=y
CONFIG_ARCH_AT91=y
CONFIG_ARCH_AT91SAM9G20=y
CONFIG_MACH_AT91SAM9G20EK=y
+CONFIG_MACH_AT91SAM9G20EK_2MMC=y
CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
# CONFIG_ARM_THUMB is not set
CONFIG_AEABI=y
diff --git a/arch/arm/configs/kirkwood_defconfig b/arch/arm/configs/kirkwood_defconfig
index ccc9c9959b82..2f7042813765 100644
--- a/arch/arm/configs/kirkwood_defconfig
+++ b/arch/arm/configs/kirkwood_defconfig
@@ -15,6 +15,7 @@ CONFIG_MACH_MV88F6281GTW_GE=y
CONFIG_MACH_SHEEVAPLUG=y
CONFIG_MACH_ESATA_SHEEVAPLUG=y
CONFIG_MACH_GURUPLUG=y
+CONFIG_MACH_DOCKSTAR=y
CONFIG_MACH_TS219=y
CONFIG_MACH_TS41X=y
CONFIG_MACH_OPENRD_BASE=y
diff --git a/arch/arm/configs/mx27_defconfig b/arch/arm/configs/mx27_defconfig
index b2038b0e266f..813cfb366c18 100644
--- a/arch/arm/configs/mx27_defconfig
+++ b/arch/arm/configs/mx27_defconfig
@@ -21,8 +21,14 @@ CONFIG_ARCH_MX2=y
CONFIG_MACH_MX27=y
CONFIG_MACH_MX27ADS=y
CONFIG_MACH_PCM038=y
+CONFIG_MACH_CPUIMX27=y
+CONFIG_MACH_EUKREA_CPUIMX27_USESDHC2=y
+CONFIG_MACH_EUKREA_CPUIMX27_USEUART4=y
CONFIG_MACH_MX27_3DS=y
+CONFIG_MACH_IMX27_VISSTRIM_M10=y
CONFIG_MACH_IMX27LITE=y
+CONFIG_MACH_PCA100=y
+CONFIG_MACH_MXT_TD60=y
CONFIG_MXC_IRQ_PRIOR=y
CONFIG_MXC_PWM=y
CONFIG_NO_HZ=y
@@ -76,7 +82,9 @@ CONFIG_INPUT_EVDEV=y
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ADS7846=m
# CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=m
CONFIG_SERIAL_IMX=y
CONFIG_SERIAL_IMX_CONSOLE=y
# CONFIG_LEGACY_PTYS is not set
@@ -85,19 +93,20 @@ CONFIG_I2C=y
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_IMX=y
CONFIG_SPI=y
-CONFIG_SPI_BITBANG=y
+CONFIG_SPI_IMX=y
CONFIG_W1=y
CONFIG_W1_MASTER_MXC=y
CONFIG_W1_SLAVE_THERM=y
# CONFIG_HWMON is not set
CONFIG_FB=y
CONFIG_FB_IMX=y
-# CONFIG_VGA_CONSOLE is not set
CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_FONTS=y
CONFIG_FONT_8x8=y
# CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
+CONFIG_USB=m
+# CONFIG_USB_DEVICE_CLASS is not set
+CONFIG_USB_ULPI=y
CONFIG_MMC=y
CONFIG_MMC_MXC=y
CONFIG_RTC_CLASS=y
diff --git a/arch/arm/configs/mx31pdk_defconfig b/arch/arm/configs/mx31pdk_defconfig
deleted file mode 100644
index 2d29329749e4..000000000000
--- a/arch/arm/configs/mx31pdk_defconfig
+++ /dev/null
@@ -1,44 +0,0 @@
-# CONFIG_LOCALVERSION_AUTO is not set
-# CONFIG_SWAP is not set
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-# CONFIG_COMPAT_BRK is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_MXC=y
-# CONFIG_MACH_MX31ADS is not set
-CONFIG_MACH_MX31_3DS=y
-CONFIG_AEABI=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_INET_LRO is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-# CONFIG_PREVENT_FIRMWARE_BUILD is not set
-# CONFIG_FIRMWARE_IN_KERNEL is not set
-# CONFIG_BLK_DEV is not set
-# CONFIG_MISC_DEVICES is not set
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-# CONFIG_DEVKMEM is not set
-CONFIG_SERIAL_IMX=y
-CONFIG_SERIAL_IMX_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_HW_RANDOM is not set
-# CONFIG_HWMON is not set
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
-# CONFIG_DNOTIFY is not set
-# CONFIG_ENABLE_WARN_DEPRECATED is not set
-# CONFIG_ENABLE_MUST_CHECK is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-# CONFIG_CRC32 is not set
diff --git a/arch/arm/configs/mx3_defconfig b/arch/arm/configs/mx3_defconfig
index 161f907b611f..f0c339fd5d21 100644
--- a/arch/arm/configs/mx3_defconfig
+++ b/arch/arm/configs/mx3_defconfig
@@ -24,6 +24,7 @@ CONFIG_MACH_PCM043=y
CONFIG_MACH_ARMADILLO5X0=y
CONFIG_MACH_MX35_3DS=y
CONFIG_MACH_KZM_ARM11_01=y
+CONFIG_MACH_EUKREA_CPUIMX35=y
CONFIG_MXC_IRQ_PRIOR=y
CONFIG_MXC_PWM=y
CONFIG_NO_HZ=y
@@ -108,7 +109,6 @@ CONFIG_MMC=y
CONFIG_MMC_MXC=y
CONFIG_DMADEVICES=y
# CONFIG_DNOTIFY is not set
-CONFIG_INOTIFY=y
CONFIG_TMPFS=y
CONFIG_JFFS2_FS=y
CONFIG_UBIFS_FS=y
diff --git a/arch/arm/configs/mx51_defconfig b/arch/arm/configs/mx51_defconfig
index a665ecbbe2bc..163cfee7644c 100644
--- a/arch/arm/configs/mx51_defconfig
+++ b/arch/arm/configs/mx51_defconfig
@@ -15,6 +15,8 @@ CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_ARCH_MXC=y
CONFIG_ARCH_MX5=y
CONFIG_MACH_MX51_BABBAGE=y
+CONFIG_MACH_MX51_3DS=y
+CONFIG_MACH_EUKREA_CPUIMX51=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_PREEMPT_VOLUNTARY=y
@@ -69,7 +71,6 @@ CONFIG_REALTEK_PHY=y
CONFIG_NATIONAL_PHY=y
CONFIG_STE10XP=y
CONFIG_LSI_ET1011C_PHY=y
-CONFIG_FIXED_PHY=y
CONFIG_MDIO_BITBANG=y
CONFIG_MDIO_GPIO=y
CONFIG_NET_ETHERNET=y
@@ -100,7 +101,6 @@ CONFIG_I2C_ALGOPCF=m
CONFIG_I2C_ALGOPCA=m
CONFIG_GPIO_SYSFS=y
# CONFIG_HWMON is not set
-# CONFIG_VGA_CONSOLE is not set
# CONFIG_HID_SUPPORT is not set
CONFIG_USB=y
CONFIG_USB_EHCI_HCD=y
@@ -117,13 +117,11 @@ CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT2_FS_POSIX_ACL=y
CONFIG_EXT2_FS_SECURITY=y
CONFIG_EXT3_FS=y
-CONFIG_EXT3_DEFAULTS_TO_ORDERED=y
CONFIG_EXT3_FS_POSIX_ACL=y
CONFIG_EXT3_FS_SECURITY=y
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_EXT4_FS_SECURITY=y
-CONFIG_INOTIFY=y
CONFIG_QUOTA=y
CONFIG_QUOTA_NETLINK_INTERFACE=y
# CONFIG_PRINT_QUOTA_WARNING is not set
@@ -136,6 +134,7 @@ CONFIG_ZISOFS=y
CONFIG_UDF_FS=m
CONFIG_MSDOS_FS=m
CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
CONFIG_CONFIGFS_FS=m
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
@@ -151,7 +150,6 @@ CONFIG_NLS_UTF8=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_FS=y
CONFIG_DEBUG_KERNEL=y
-# CONFIG_DETECT_SOFTLOCKUP is not set
# CONFIG_SCHED_DEBUG is not set
# CONFIG_DEBUG_BUGVERBOSE is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -159,7 +157,6 @@ CONFIG_DEBUG_KERNEL=y
# CONFIG_ARM_UNWIND is not set
CONFIG_DEBUG_LL=y
CONFIG_EARLY_PRINTK=y
-CONFIG_KEYS=y
CONFIG_SECURITYFS=y
CONFIG_CRYPTO_DEFLATE=y
CONFIG_CRYPTO_LZO=y
diff --git a/arch/arm/configs/realview-smp_defconfig b/arch/arm/configs/realview-smp_defconfig
index 9312ef9f9bf4..5ca7a61f7c01 100644
--- a/arch/arm/configs/realview-smp_defconfig
+++ b/arch/arm/configs/realview-smp_defconfig
@@ -39,6 +39,7 @@ CONFIG_MTD_CFI=y
CONFIG_MTD_CFI_INTELEXT=y
CONFIG_MTD_CFI_AMDSTD=y
CONFIG_MTD_ARM_INTEGRATOR=y
+CONFIG_ARM_CHARLCD=y
CONFIG_NETDEVICES=y
CONFIG_SMSC_PHY=y
CONFIG_NET_ETHERNET=y
@@ -52,10 +53,13 @@ CONFIG_SERIAL_AMBA_PL011=y
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
CONFIG_LEGACY_PTY_COUNT=16
# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_VERSATILE=y
+CONFIG_SPI=y
+CONFIG_GPIOLIB=y
# CONFIG_HWMON is not set
CONFIG_FB=y
CONFIG_FB_ARMCLCD=y
-# CONFIG_VGA_CONSOLE is not set
CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_LOGO=y
# CONFIG_LOGO_LINUX_MONO is not set
@@ -70,7 +74,13 @@ CONFIG_SND_ARMAACI=y
# CONFIG_USB_SUPPORT is not set
CONFIG_MMC=y
CONFIG_MMC_ARMMMCI=y
-CONFIG_INOTIFY=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_DS1307=y
+CONFIG_RTC_DRV_PL031=y
CONFIG_VFAT_FS=y
CONFIG_TMPFS=y
CONFIG_CRAMFS=y
@@ -80,6 +90,7 @@ CONFIG_ROOT_NFS=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ISO8859_1=y
CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
CONFIG_DEBUG_KERNEL=y
# CONFIG_SCHED_DEBUG is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
diff --git a/arch/arm/configs/realview_defconfig b/arch/arm/configs/realview_defconfig
index fb75192ee7e5..fcaa60328051 100644
--- a/arch/arm/configs/realview_defconfig
+++ b/arch/arm/configs/realview_defconfig
@@ -38,6 +38,7 @@ CONFIG_MTD_CFI=y
CONFIG_MTD_CFI_INTELEXT=y
CONFIG_MTD_CFI_AMDSTD=y
CONFIG_MTD_ARM_INTEGRATOR=y
+CONFIG_ARM_CHARLCD=y
CONFIG_NETDEVICES=y
CONFIG_SMSC_PHY=y
CONFIG_NET_ETHERNET=y
@@ -51,10 +52,13 @@ CONFIG_SERIAL_AMBA_PL011=y
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
CONFIG_LEGACY_PTY_COUNT=16
# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_VERSATILE=y
+CONFIG_SPI=y
+CONFIG_GPIOLIB=y
# CONFIG_HWMON is not set
CONFIG_FB=y
CONFIG_FB_ARMCLCD=y
-# CONFIG_VGA_CONSOLE is not set
CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_LOGO=y
# CONFIG_LOGO_LINUX_MONO is not set
@@ -69,7 +73,13 @@ CONFIG_SND_ARMAACI=y
# CONFIG_USB_SUPPORT is not set
CONFIG_MMC=y
CONFIG_MMC_ARMMMCI=y
-CONFIG_INOTIFY=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_DS1307=y
+CONFIG_RTC_DRV_PL031=y
CONFIG_VFAT_FS=y
CONFIG_TMPFS=y
CONFIG_CRAMFS=y
@@ -79,6 +89,7 @@ CONFIG_ROOT_NFS=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ISO8859_1=y
CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
CONFIG_DEBUG_KERNEL=y
# CONFIG_SCHED_DEBUG is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
diff --git a/arch/arm/configs/s5p6440_defconfig b/arch/arm/configs/s5p64x0_defconfig
index 0b0266c6d326..2993ecd35145 100644
--- a/arch/arm/configs/s5p6440_defconfig
+++ b/arch/arm/configs/s5p64x0_defconfig
@@ -5,10 +5,11 @@ CONFIG_KALLSYMS_ALL=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_S5P6440=y
+CONFIG_ARCH_S5P64X0=y
CONFIG_S3C_BOOT_ERROR_RESET=y
CONFIG_S3C_LOWLEVEL_UART_PORT=1
CONFIG_MACH_SMDK6440=y
+CONFIG_MACH_SMDK6450=y
CONFIG_CPU_32v6K=y
CONFIG_AEABI=y
CONFIG_CMDLINE="root=/dev/ram0 rw ramdisk=8192 initrd=0x20800000,8M console=ttySAC1,115200 init=/linuxrc"
diff --git a/arch/arm/configs/u300_defconfig b/arch/arm/configs/u300_defconfig
index 46e5e0747269..c1c252cdca60 100644
--- a/arch/arm/configs/u300_defconfig
+++ b/arch/arm/configs/u300_defconfig
@@ -28,26 +28,9 @@ CONFIG_CPU_IDLE=y
CONFIG_FPE_NWFPE=y
CONFIG_PM=y
# CONFIG_SUSPEND is not set
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_INET_DIAG is not set
-# CONFIG_IPV6 is not set
-# CONFIG_WIRELESS is not set
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
# CONFIG_PREVENT_FIRMWARE_BUILD is not set
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_ECC_SMC=y
+# CONFIG_MISC_DEVICES is not set
# CONFIG_INPUT_MOUSEDEV is not set
CONFIG_INPUT_EVDEV=y
# CONFIG_KEYBOARD_ATKBD is not set
@@ -58,7 +41,6 @@ CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
CONFIG_LEGACY_PTY_COUNT=16
# CONFIG_HW_RANDOM is not set
CONFIG_I2C=y
-CONFIG_POWER_SUPPLY=y
# CONFIG_HWMON is not set
CONFIG_WATCHDOG=y
CONFIG_REGULATOR=y
@@ -66,24 +48,10 @@ CONFIG_FB=y
CONFIG_BACKLIGHT_LCD_SUPPORT=y
# CONFIG_LCD_CLASS_DEVICE is not set
CONFIG_BACKLIGHT_CLASS_DEVICE=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_SOUND=y
-CONFIG_SND=y
-# CONFIG_SND_SUPPORT_OLD_API is not set
-# CONFIG_SND_VERBOSE_PROCFS is not set
-# CONFIG_SND_DRIVERS is not set
-# CONFIG_SND_ARM is not set
-# CONFIG_SND_SPI is not set
-CONFIG_SND_SOC=y
# CONFIG_HID_SUPPORT is not set
# CONFIG_USB_SUPPORT is not set
CONFIG_MMC=y
-CONFIG_MMC_DEBUG=y
CONFIG_MMC_ARMMMCI=y
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_TRIGGERS=y
-CONFIG_LEDS_TRIGGER_BACKLIGHT=y
CONFIG_RTC_CLASS=y
# CONFIG_RTC_HCTOSYS is not set
CONFIG_RTC_DRV_COH901331=y
@@ -93,12 +61,11 @@ CONFIG_COH901318=y
CONFIG_FUSE_FS=y
CONFIG_VFAT_FS=y
CONFIG_TMPFS=y
-# CONFIG_NETWORK_FILESYSTEMS is not set
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ISO8859_1=y
CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_FS=y
CONFIG_DEBUG_KERNEL=y
-# CONFIG_DETECT_SOFTLOCKUP is not set
# CONFIG_SCHED_DEBUG is not set
CONFIG_TIMER_STATS=y
# CONFIG_DEBUG_PREEMPT is not set
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
index 6e8f05c8a1c8..062b58c029ab 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -154,16 +154,39 @@
.long 9999b,9001f; \
.popsection
+#ifdef CONFIG_SMP
+#define ALT_SMP(instr...) \
+9998: instr
+#define ALT_UP(instr...) \
+ .pushsection ".alt.smp.init", "a" ;\
+ .long 9998b ;\
+ instr ;\
+ .popsection
+#define ALT_UP_B(label) \
+ .equ up_b_offset, label - 9998b ;\
+ .pushsection ".alt.smp.init", "a" ;\
+ .long 9998b ;\
+ b . + up_b_offset ;\
+ .popsection
+#else
+#define ALT_SMP(instr...)
+#define ALT_UP(instr...) instr
+#define ALT_UP_B(label) b label
+#endif
+
/*
* SMP data memory barrier
*/
.macro smp_dmb
#ifdef CONFIG_SMP
#if __LINUX_ARM_ARCH__ >= 7
- dmb
+ ALT_SMP(dmb)
#elif __LINUX_ARM_ARCH__ == 6
- mcr p15, 0, r0, c7, c10, 5 @ dmb
+ ALT_SMP(mcr p15, 0, r0, c7, c10, 5) @ dmb
+#else
+#error Incompatible SMP platform
#endif
+ ALT_UP(nop)
#endif
.endm
diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h
index 4656a24058d2..3acd8fa25e34 100644
--- a/arch/arm/include/asm/cacheflush.h
+++ b/arch/arm/include/asm/cacheflush.h
@@ -137,10 +137,10 @@
#endif
/*
- * This flag is used to indicate that the page pointed to by a pte
- * is dirty and requires cleaning before returning it to the user.
+ * This flag is used to indicate that the page pointed to by a pte is clean
+ * and does not require cleaning before returning it to the user.
*/
-#define PG_dcache_dirty PG_arch_1
+#define PG_dcache_clean PG_arch_1
/*
* MM Cache Management
@@ -156,6 +156,12 @@
* Please note that the implementation of these, and the required
* effects are cache-type (VIVT/VIPT/PIPT) specific.
*
+ * flush_icache_all()
+ *
+ * Unconditionally clean and invalidate the entire icache.
+ * Currently only needed for cache-v6.S and cache-v7.S, see
+ * __flush_icache_all for the generic implementation.
+ *
* flush_kern_all()
*
* Unconditionally clean and invalidate the entire cache.
@@ -206,6 +212,7 @@
*/
struct cpu_cache_fns {
+ void (*flush_icache_all)(void);
void (*flush_kern_all)(void);
void (*flush_user_all)(void);
void (*flush_user_range)(unsigned long, unsigned long, unsigned int);
@@ -227,6 +234,7 @@ struct cpu_cache_fns {
extern struct cpu_cache_fns cpu_cache;
+#define __cpuc_flush_icache_all cpu_cache.flush_icache_all
#define __cpuc_flush_kern_all cpu_cache.flush_kern_all
#define __cpuc_flush_user_all cpu_cache.flush_user_all
#define __cpuc_flush_user_range cpu_cache.flush_user_range
@@ -246,6 +254,7 @@ extern struct cpu_cache_fns cpu_cache;
#else
+#define __cpuc_flush_icache_all __glue(_CACHE,_flush_icache_all)
#define __cpuc_flush_kern_all __glue(_CACHE,_flush_kern_cache_all)
#define __cpuc_flush_user_all __glue(_CACHE,_flush_user_cache_all)
#define __cpuc_flush_user_range __glue(_CACHE,_flush_user_cache_range)
@@ -253,6 +262,7 @@ extern struct cpu_cache_fns cpu_cache;
#define __cpuc_coherent_user_range __glue(_CACHE,_coherent_user_range)
#define __cpuc_flush_dcache_area __glue(_CACHE,_flush_kern_dcache_area)
+extern void __cpuc_flush_icache_all(void);
extern void __cpuc_flush_kern_all(void);
extern void __cpuc_flush_user_all(void);
extern void __cpuc_flush_user_range(unsigned long, unsigned long, unsigned int);
@@ -291,6 +301,37 @@ extern void copy_to_user_page(struct vm_area_struct *, struct page *,
/*
* Convert calls to our calling convention.
*/
+
+/* Invalidate I-cache */
+#define __flush_icache_all_generic() \
+ asm("mcr p15, 0, %0, c7, c5, 0" \
+ : : "r" (0));
+
+/* Invalidate I-cache inner shareable */
+#define __flush_icache_all_v7_smp() \
+ asm("mcr p15, 0, %0, c7, c1, 0" \
+ : : "r" (0));
+
+/*
+ * Optimized __flush_icache_all for the common cases. Note that UP ARMv7
+ * will fall through to use __flush_icache_all_generic.
+ */
+#if (defined(CONFIG_CPU_V7) && defined(CONFIG_CPU_V6)) || \
+ defined(CONFIG_SMP_ON_UP)
+#define __flush_icache_preferred __cpuc_flush_icache_all
+#elif __LINUX_ARM_ARCH__ >= 7 && defined(CONFIG_SMP)
+#define __flush_icache_preferred __flush_icache_all_v7_smp
+#elif __LINUX_ARM_ARCH__ == 6 && defined(CONFIG_ARM_ERRATA_411920)
+#define __flush_icache_preferred __cpuc_flush_icache_all
+#else
+#define __flush_icache_preferred __flush_icache_all_generic
+#endif
+
+static inline void __flush_icache_all(void)
+{
+ __flush_icache_preferred();
+}
+
#define flush_cache_all() __cpuc_flush_kern_all()
static inline void vivt_flush_cache_mm(struct mm_struct *mm)
@@ -366,21 +407,6 @@ extern void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr
#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
extern void flush_dcache_page(struct page *);
-static inline void __flush_icache_all(void)
-{
-#ifdef CONFIG_ARM_ERRATA_411920
- extern void v6_icache_inval_all(void);
- v6_icache_inval_all();
-#elif defined(CONFIG_SMP) && __LINUX_ARM_ARCH__ >= 7
- asm("mcr p15, 0, %0, c7, c1, 0 @ invalidate I-cache inner shareable\n"
- :
- : "r" (0));
-#else
- asm("mcr p15, 0, %0, c7, c5, 0 @ invalidate I-cache\n"
- :
- : "r" (0));
-#endif
-}
static inline void flush_kernel_vmap_range(void *addr, int size)
{
if ((cache_is_vivt() || cache_is_vipt_aliasing()))
@@ -405,9 +431,6 @@ static inline void flush_anon_page(struct vm_area_struct *vma,
#define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE
static inline void flush_kernel_dcache_page(struct page *page)
{
- /* highmem pages are always flushed upon kunmap already */
- if ((cache_is_vivt() || cache_is_vipt_aliasing()) && !PageHighMem(page))
- __cpuc_flush_dcache_area(page_address(page), PAGE_SIZE);
}
#define flush_dcache_mmap_lock(mapping) \
diff --git a/arch/arm/include/asm/cachetype.h b/arch/arm/include/asm/cachetype.h
index d3a4c2cb9f2f..c023db09fcc1 100644
--- a/arch/arm/include/asm/cachetype.h
+++ b/arch/arm/include/asm/cachetype.h
@@ -6,6 +6,7 @@
#define CACHEID_VIPT_ALIASING (1 << 2)
#define CACHEID_VIPT (CACHEID_VIPT_ALIASING|CACHEID_VIPT_NONALIASING)
#define CACHEID_ASID_TAGGED (1 << 3)
+#define CACHEID_VIPT_I_ALIASING (1 << 4)
extern unsigned int cacheid;
@@ -14,15 +15,18 @@ extern unsigned int cacheid;
#define cache_is_vipt_nonaliasing() cacheid_is(CACHEID_VIPT_NONALIASING)
#define cache_is_vipt_aliasing() cacheid_is(CACHEID_VIPT_ALIASING)
#define icache_is_vivt_asid_tagged() cacheid_is(CACHEID_ASID_TAGGED)
+#define icache_is_vipt_aliasing() cacheid_is(CACHEID_VIPT_I_ALIASING)
/*
* __LINUX_ARM_ARCH__ is the minimum supported CPU architecture
* Mask out support which will never be present on newer CPUs.
* - v6+ is never VIVT
- * - v7+ VIPT never aliases
+ * - v7+ VIPT never aliases on D-side
*/
#if __LINUX_ARM_ARCH__ >= 7
-#define __CACHEID_ARCH_MIN (CACHEID_VIPT_NONALIASING | CACHEID_ASID_TAGGED)
+#define __CACHEID_ARCH_MIN (CACHEID_VIPT_NONALIASING |\
+ CACHEID_ASID_TAGGED |\
+ CACHEID_VIPT_I_ALIASING)
#elif __LINUX_ARM_ARCH__ >= 6
#define __CACHEID_ARCH_MIN (~CACHEID_VIVT)
#else
diff --git a/arch/arm/include/asm/elf.h b/arch/arm/include/asm/elf.h
index 5747a8baa413..8bb66bca2e3e 100644
--- a/arch/arm/include/asm/elf.h
+++ b/arch/arm/include/asm/elf.h
@@ -127,4 +127,8 @@ struct mm_struct;
extern unsigned long arch_randomize_brk(struct mm_struct *mm);
#define arch_randomize_brk arch_randomize_brk
+extern int vectors_user_mapping(void);
+#define arch_setup_additional_pages(bprm, uses_interp) vectors_user_mapping()
+#define ARCH_HAS_SETUP_ADDITIONAL_PAGES
+
#endif
diff --git a/arch/arm/include/asm/ftrace.h b/arch/arm/include/asm/ftrace.h
index 103f7ee97313..f89515adac60 100644
--- a/arch/arm/include/asm/ftrace.h
+++ b/arch/arm/include/asm/ftrace.h
@@ -2,12 +2,30 @@
#define _ASM_ARM_FTRACE
#ifdef CONFIG_FUNCTION_TRACER
-#define MCOUNT_ADDR ((long)(mcount))
+#define MCOUNT_ADDR ((unsigned long)(__gnu_mcount_nc))
#define MCOUNT_INSN_SIZE 4 /* sizeof mcount call */
#ifndef __ASSEMBLY__
extern void mcount(void);
extern void __gnu_mcount_nc(void);
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+struct dyn_arch_ftrace {
+#ifdef CONFIG_OLD_MCOUNT
+ bool old_mcount;
+#endif
+};
+
+static inline unsigned long ftrace_call_adjust(unsigned long addr)
+{
+ /* With Thumb-2, the recorded addresses have the lsb set */
+ return addr & ~1;
+}
+
+extern void ftrace_caller_old(void);
+extern void ftrace_call_old(void);
+#endif
+
#endif
#endif
diff --git a/arch/arm/include/asm/hardware/coresight.h b/arch/arm/include/asm/hardware/coresight.h
index 212e47828c79..7ecd793b8f5a 100644
--- a/arch/arm/include/asm/hardware/coresight.h
+++ b/arch/arm/include/asm/hardware/coresight.h
@@ -21,18 +21,6 @@
#define TRACER_RUNNING BIT(TRACER_RUNNING_BIT)
#define TRACER_CYCLE_ACC BIT(TRACER_CYCLE_ACC_BIT)
-struct tracectx {
- unsigned int etb_bufsz;
- void __iomem *etb_regs;
- void __iomem *etm_regs;
- unsigned long flags;
- int ncmppairs;
- int etm_portsz;
- struct device *dev;
- struct clk *emu_clk;
- struct mutex mutex;
-};
-
#define TRACER_TIMEOUT 10000
#define etm_writel(t, v, x) \
@@ -112,10 +100,10 @@ struct tracectx {
/* ETM status register, "ETM Architecture", 3.3.2 */
#define ETMR_STATUS (0x10)
-#define ETMST_OVERFLOW (1 << 0)
-#define ETMST_PROGBIT (1 << 1)
-#define ETMST_STARTSTOP (1 << 2)
-#define ETMST_TRIGGER (1 << 3)
+#define ETMST_OVERFLOW BIT(0)
+#define ETMST_PROGBIT BIT(1)
+#define ETMST_STARTSTOP BIT(2)
+#define ETMST_TRIGGER BIT(3)
#define etm_progbit(t) (etm_readl((t), ETMR_STATUS) & ETMST_PROGBIT)
#define etm_started(t) (etm_readl((t), ETMR_STATUS) & ETMST_STARTSTOP)
@@ -123,7 +111,7 @@ struct tracectx {
#define ETMR_TRACEENCTRL2 0x1c
#define ETMR_TRACEENCTRL 0x24
-#define ETMTE_INCLEXCL (1 << 24)
+#define ETMTE_INCLEXCL BIT(24)
#define ETMR_TRACEENEVT 0x20
#define ETMCTRL_OPTS (ETMCTRL_DO_CPRT | \
ETMCTRL_DATA_DO_ADDR | \
@@ -146,12 +134,12 @@ struct tracectx {
#define ETBR_CTRL 0x20
#define ETBR_FORMATTERCTRL 0x304
#define ETBFF_ENFTC 1
-#define ETBFF_ENFCONT (1 << 1)
-#define ETBFF_FONFLIN (1 << 4)
-#define ETBFF_MANUAL_FLUSH (1 << 6)
-#define ETBFF_TRIGIN (1 << 8)
-#define ETBFF_TRIGEVT (1 << 9)
-#define ETBFF_TRIGFL (1 << 10)
+#define ETBFF_ENFCONT BIT(1)
+#define ETBFF_FONFLIN BIT(4)
+#define ETBFF_MANUAL_FLUSH BIT(6)
+#define ETBFF_TRIGIN BIT(8)
+#define ETBFF_TRIGEVT BIT(9)
+#define ETBFF_TRIGFL BIT(10)
#define etb_writel(t, v, x) \
(__raw_writel((v), (t)->etb_regs + (x)))
diff --git a/arch/arm/include/asm/hw_breakpoint.h b/arch/arm/include/asm/hw_breakpoint.h
new file mode 100644
index 000000000000..4d8ae9d67abe
--- /dev/null
+++ b/arch/arm/include/asm/hw_breakpoint.h
@@ -0,0 +1,133 @@
+#ifndef _ARM_HW_BREAKPOINT_H
+#define _ARM_HW_BREAKPOINT_H
+
+#ifdef __KERNEL__
+
+struct task_struct;
+
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+
+struct arch_hw_breakpoint_ctrl {
+ u32 __reserved : 9,
+ mismatch : 1,
+ : 9,
+ len : 8,
+ type : 2,
+ privilege : 2,
+ enabled : 1;
+};
+
+struct arch_hw_breakpoint {
+ u32 address;
+ u32 trigger;
+ struct perf_event *suspended_wp;
+ struct arch_hw_breakpoint_ctrl ctrl;
+};
+
+static inline u32 encode_ctrl_reg(struct arch_hw_breakpoint_ctrl ctrl)
+{
+ return (ctrl.mismatch << 22) | (ctrl.len << 5) | (ctrl.type << 3) |
+ (ctrl.privilege << 1) | ctrl.enabled;
+}
+
+static inline void decode_ctrl_reg(u32 reg,
+ struct arch_hw_breakpoint_ctrl *ctrl)
+{
+ ctrl->enabled = reg & 0x1;
+ reg >>= 1;
+ ctrl->privilege = reg & 0x3;
+ reg >>= 2;
+ ctrl->type = reg & 0x3;
+ reg >>= 2;
+ ctrl->len = reg & 0xff;
+ reg >>= 17;
+ ctrl->mismatch = reg & 0x1;
+}
+
+/* Debug architecture numbers. */
+#define ARM_DEBUG_ARCH_RESERVED 0 /* In case of ptrace ABI updates. */
+#define ARM_DEBUG_ARCH_V6 1
+#define ARM_DEBUG_ARCH_V6_1 2
+#define ARM_DEBUG_ARCH_V7_ECP14 3
+#define ARM_DEBUG_ARCH_V7_MM 4
+
+/* Breakpoint */
+#define ARM_BREAKPOINT_EXECUTE 0
+
+/* Watchpoints */
+#define ARM_BREAKPOINT_LOAD 1
+#define ARM_BREAKPOINT_STORE 2
+
+/* Privilege Levels */
+#define ARM_BREAKPOINT_PRIV 1
+#define ARM_BREAKPOINT_USER 2
+
+/* Lengths */
+#define ARM_BREAKPOINT_LEN_1 0x1
+#define ARM_BREAKPOINT_LEN_2 0x3
+#define ARM_BREAKPOINT_LEN_4 0xf
+#define ARM_BREAKPOINT_LEN_8 0xff
+
+/* Limits */
+#define ARM_MAX_BRP 16
+#define ARM_MAX_WRP 16
+#define ARM_MAX_HBP_SLOTS (ARM_MAX_BRP + ARM_MAX_WRP)
+
+/* DSCR method of entry bits. */
+#define ARM_DSCR_MOE(x) ((x >> 2) & 0xf)
+#define ARM_ENTRY_BREAKPOINT 0x1
+#define ARM_ENTRY_ASYNC_WATCHPOINT 0x2
+#define ARM_ENTRY_SYNC_WATCHPOINT 0xa
+
+/* DSCR monitor/halting bits. */
+#define ARM_DSCR_HDBGEN (1 << 14)
+#define ARM_DSCR_MDBGEN (1 << 15)
+
+/* opcode2 numbers for the co-processor instructions. */
+#define ARM_OP2_BVR 4
+#define ARM_OP2_BCR 5
+#define ARM_OP2_WVR 6
+#define ARM_OP2_WCR 7
+
+/* Base register numbers for the debug registers. */
+#define ARM_BASE_BVR 64
+#define ARM_BASE_BCR 80
+#define ARM_BASE_WVR 96
+#define ARM_BASE_WCR 112
+
+/* Accessor macros for the debug registers. */
+#define ARM_DBG_READ(M, OP2, VAL) do {\
+ asm volatile("mrc p14, 0, %0, c0," #M ", " #OP2 : "=r" (VAL));\
+} while (0)
+
+#define ARM_DBG_WRITE(M, OP2, VAL) do {\
+ asm volatile("mcr p14, 0, %0, c0," #M ", " #OP2 : : "r" (VAL));\
+} while (0)
+
+struct notifier_block;
+struct perf_event;
+struct pmu;
+
+extern struct pmu perf_ops_bp;
+extern int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl,
+ int *gen_len, int *gen_type);
+extern int arch_check_bp_in_kernelspace(struct perf_event *bp);
+extern int arch_validate_hwbkpt_settings(struct perf_event *bp);
+extern int hw_breakpoint_exceptions_notify(struct notifier_block *unused,
+ unsigned long val, void *data);
+
+extern u8 arch_get_debug_arch(void);
+extern u8 arch_get_max_wp_len(void);
+extern void clear_ptrace_hw_breakpoint(struct task_struct *tsk);
+
+int arch_install_hw_breakpoint(struct perf_event *bp);
+void arch_uninstall_hw_breakpoint(struct perf_event *bp);
+void hw_breakpoint_pmu_read(struct perf_event *bp);
+int hw_breakpoint_slots(int type);
+
+#else
+static inline void clear_ptrace_hw_breakpoint(struct task_struct *tsk) {}
+
+#endif /* CONFIG_HAVE_HW_BREAKPOINT */
+#endif /* __KERNEL__ */
+#endif /* _ARM_HW_BREAKPOINT_H */
diff --git a/arch/arm/include/asm/hw_irq.h b/arch/arm/include/asm/hw_irq.h
index 90831f6f5f5c..5586b7c8ef6f 100644
--- a/arch/arm/include/asm/hw_irq.h
+++ b/arch/arm/include/asm/hw_irq.h
@@ -24,4 +24,6 @@ void set_irq_flags(unsigned int irq, unsigned int flags);
#define IRQF_PROBE (1 << 1)
#define IRQF_NOAUTOEN (1 << 2)
+#define ARCH_IRQ_INIT_FLAGS (IRQ_NOREQUEST | IRQ_NOPROBE)
+
#endif
diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index 1261b1f928d9..815efa2d4e07 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -294,6 +294,7 @@ extern void pci_iounmap(struct pci_dev *dev, void __iomem *addr);
#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
extern int valid_phys_addr_range(unsigned long addr, size_t size);
extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t size);
+extern int devmem_is_allowed(unsigned long pfn);
#endif
/*
diff --git a/arch/arm/include/asm/ioctls.h b/arch/arm/include/asm/ioctls.h
index 0b30894b5482..9c9629816128 100644
--- a/arch/arm/include/asm/ioctls.h
+++ b/arch/arm/include/asm/ioctls.h
@@ -1,89 +1,8 @@
#ifndef __ASM_ARM_IOCTLS_H
#define __ASM_ARM_IOCTLS_H
-#include <asm/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS 0x5401
-#define TCSETS 0x5402
-#define TCSETSW 0x5403
-#define TCSETSF 0x5404
-#define TCGETA 0x5405
-#define TCSETA 0x5406
-#define TCSETAW 0x5407
-#define TCSETAF 0x5408
-#define TCSBRK 0x5409
-#define TCXONC 0x540A
-#define TCFLSH 0x540B
-#define TIOCEXCL 0x540C
-#define TIOCNXCL 0x540D
-#define TIOCSCTTY 0x540E
-#define TIOCGPGRP 0x540F
-#define TIOCSPGRP 0x5410
-#define TIOCOUTQ 0x5411
-#define TIOCSTI 0x5412
-#define TIOCGWINSZ 0x5413
-#define TIOCSWINSZ 0x5414
-#define TIOCMGET 0x5415
-#define TIOCMBIS 0x5416
-#define TIOCMBIC 0x5417
-#define TIOCMSET 0x5418
-#define TIOCGSOFTCAR 0x5419
-#define TIOCSSOFTCAR 0x541A
-#define FIONREAD 0x541B
-#define TIOCINQ FIONREAD
-#define TIOCLINUX 0x541C
-#define TIOCCONS 0x541D
-#define TIOCGSERIAL 0x541E
-#define TIOCSSERIAL 0x541F
-#define TIOCPKT 0x5420
-#define FIONBIO 0x5421
-#define TIOCNOTTY 0x5422
-#define TIOCSETD 0x5423
-#define TIOCGETD 0x5424
-#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
-#define TIOCSBRK 0x5427 /* BSD compatibility */
-#define TIOCCBRK 0x5428 /* BSD compatibility */
-#define TIOCGSID 0x5429 /* Return the session ID of FD */
-#define TCGETS2 _IOR('T',0x2A, struct termios2)
-#define TCSETS2 _IOW('T',0x2B, struct termios2)
-#define TCSETSW2 _IOW('T',0x2C, struct termios2)
-#define TCSETSF2 _IOW('T',0x2D, struct termios2)
-#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
-#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
-#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */
-
-#define TIOCGRS485 0x542E
-#define TIOCSRS485 0x542F
-
-#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */
-#define FIOCLEX 0x5451
-#define FIOASYNC 0x5452
-#define TIOCSERCONFIG 0x5453
-#define TIOCSERGWILD 0x5454
-#define TIOCSERSWILD 0x5455
-#define TIOCGLCKTRMIOS 0x5456
-#define TIOCSLCKTRMIOS 0x5457
-#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
-#define TIOCSERGETLSR 0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
-#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
#define FIOQSIZE 0x545E
-/* Used for packet mode */
-#define TIOCPKT_DATA 0
-#define TIOCPKT_FLUSHREAD 1
-#define TIOCPKT_FLUSHWRITE 2
-#define TIOCPKT_STOP 4
-#define TIOCPKT_START 8
-#define TIOCPKT_NOSTOP 16
-#define TIOCPKT_DOSTOP 32
-#define TIOCPKT_IOCTL 64
-
-#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
+#include <asm-generic/ioctls.h>
#endif
diff --git a/arch/arm/include/asm/irqflags.h b/arch/arm/include/asm/irqflags.h
index 6d09974e6646..1e6cca55c750 100644
--- a/arch/arm/include/asm/irqflags.h
+++ b/arch/arm/include/asm/irqflags.h
@@ -10,66 +10,85 @@
*/
#if __LINUX_ARM_ARCH__ >= 6
-#define raw_local_irq_save(x) \
- ({ \
- __asm__ __volatile__( \
- "mrs %0, cpsr @ local_irq_save\n" \
- "cpsid i" \
- : "=r" (x) : : "memory", "cc"); \
- })
+static inline unsigned long arch_local_irq_save(void)
+{
+ unsigned long flags;
+
+ asm volatile(
+ " mrs %0, cpsr @ arch_local_irq_save\n"
+ " cpsid i"
+ : "=r" (flags) : : "memory", "cc");
+ return flags;
+}
+
+static inline void arch_local_irq_enable(void)
+{
+ asm volatile(
+ " cpsie i @ arch_local_irq_enable"
+ :
+ :
+ : "memory", "cc");
+}
+
+static inline void arch_local_irq_disable(void)
+{
+ asm volatile(
+ " cpsid i @ arch_local_irq_disable"
+ :
+ :
+ : "memory", "cc");
+}
-#define raw_local_irq_enable() __asm__("cpsie i @ __sti" : : : "memory", "cc")
-#define raw_local_irq_disable() __asm__("cpsid i @ __cli" : : : "memory", "cc")
#define local_fiq_enable() __asm__("cpsie f @ __stf" : : : "memory", "cc")
#define local_fiq_disable() __asm__("cpsid f @ __clf" : : : "memory", "cc")
-
#else
/*
* Save the current interrupt enable state & disable IRQs
*/
-#define raw_local_irq_save(x) \
- ({ \
- unsigned long temp; \
- (void) (&temp == &x); \
- __asm__ __volatile__( \
- "mrs %0, cpsr @ local_irq_save\n" \
-" orr %1, %0, #128\n" \
-" msr cpsr_c, %1" \
- : "=r" (x), "=r" (temp) \
- : \
- : "memory", "cc"); \
- })
-
+static inline unsigned long arch_local_irq_save(void)
+{
+ unsigned long flags, temp;
+
+ asm volatile(
+ " mrs %0, cpsr @ arch_local_irq_save\n"
+ " orr %1, %0, #128\n"
+ " msr cpsr_c, %1"
+ : "=r" (flags), "=r" (temp)
+ :
+ : "memory", "cc");
+ return flags;
+}
+
/*
* Enable IRQs
*/
-#define raw_local_irq_enable() \
- ({ \
- unsigned long temp; \
- __asm__ __volatile__( \
- "mrs %0, cpsr @ local_irq_enable\n" \
-" bic %0, %0, #128\n" \
-" msr cpsr_c, %0" \
- : "=r" (temp) \
- : \
- : "memory", "cc"); \
- })
+static inline void arch_local_irq_enable(void)
+{
+ unsigned long temp;
+ asm volatile(
+ " mrs %0, cpsr @ arch_local_irq_enable\n"
+ " bic %0, %0, #128\n"
+ " msr cpsr_c, %0"
+ : "=r" (temp)
+ :
+ : "memory", "cc");
+}
/*
* Disable IRQs
*/
-#define raw_local_irq_disable() \
- ({ \
- unsigned long temp; \
- __asm__ __volatile__( \
- "mrs %0, cpsr @ local_irq_disable\n" \
-" orr %0, %0, #128\n" \
-" msr cpsr_c, %0" \
- : "=r" (temp) \
- : \
- : "memory", "cc"); \
- })
+static inline void arch_local_irq_disable(void)
+{
+ unsigned long temp;
+ asm volatile(
+ " mrs %0, cpsr @ arch_local_irq_disable\n"
+ " orr %0, %0, #128\n"
+ " msr cpsr_c, %0"
+ : "=r" (temp)
+ :
+ : "memory", "cc");
+}
/*
* Enable FIQs
@@ -106,27 +125,31 @@
/*
* Save the current interrupt enable state.
*/
-#define raw_local_save_flags(x) \
- ({ \
- __asm__ __volatile__( \
- "mrs %0, cpsr @ local_save_flags" \
- : "=r" (x) : : "memory", "cc"); \
- })
+static inline unsigned long arch_local_save_flags(void)
+{
+ unsigned long flags;
+ asm volatile(
+ " mrs %0, cpsr @ local_save_flags"
+ : "=r" (flags) : : "memory", "cc");
+ return flags;
+}
/*
* restore saved IRQ & FIQ state
*/
-#define raw_local_irq_restore(x) \
- __asm__ __volatile__( \
- "msr cpsr_c, %0 @ local_irq_restore\n" \
- : \
- : "r" (x) \
- : "memory", "cc")
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+ asm volatile(
+ " msr cpsr_c, %0 @ local_irq_restore"
+ :
+ : "r" (flags)
+ : "memory", "cc");
+}
-#define raw_irqs_disabled_flags(flags) \
-({ \
- (int)((flags) & PSR_I_BIT); \
-})
+static inline int arch_irqs_disabled_flags(unsigned long flags)
+{
+ return flags & PSR_I_BIT;
+}
#endif
#endif
diff --git a/arch/arm/include/asm/mach/arch.h b/arch/arm/include/asm/mach/arch.h
index 8a0dd18ba642..d97a964207fa 100644
--- a/arch/arm/include/asm/mach/arch.h
+++ b/arch/arm/include/asm/mach/arch.h
@@ -16,18 +16,15 @@ struct sys_timer;
struct machine_desc {
/*
- * Note! The first four elements are used
+ * Note! The first two elements are used
* by assembler code in head.S, head-common.S
*/
unsigned int nr; /* architecture number */
- unsigned int nr_irqs; /* number of IRQs */
- unsigned int phys_io; /* start of physical io */
- unsigned int io_pg_offst; /* byte offset for io
- * page tabe entry */
-
const char *name; /* architecture name */
unsigned long boot_params; /* tagged list */
+ unsigned int nr_irqs; /* number of IRQs */
+
unsigned int video_start; /* start of video RAM */
unsigned int video_end; /* end of video RAM */
diff --git a/arch/arm/include/asm/mmu_context.h b/arch/arm/include/asm/mmu_context.h
index a0b3cac0547c..71605d9f8e42 100644
--- a/arch/arm/include/asm/mmu_context.h
+++ b/arch/arm/include/asm/mmu_context.h
@@ -18,7 +18,6 @@
#include <asm/cacheflush.h>
#include <asm/cachetype.h>
#include <asm/proc-fns.h>
-#include <asm-generic/mm_hooks.h>
void __check_kvm_seq(struct mm_struct *mm);
@@ -134,4 +133,32 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next,
#define deactivate_mm(tsk,mm) do { } while (0)
#define activate_mm(prev,next) switch_mm(prev, next, NULL)
+/*
+ * We are inserting a "fake" vma for the user-accessible vector page so
+ * gdb and friends can get to it through ptrace and /proc/<pid>/mem.
+ * But we also want to remove it before the generic code gets to see it
+ * during process exit or the unmapping of it would cause total havoc.
+ * (the macro is used as remove_vma() is static to mm/mmap.c)
+ */
+#define arch_exit_mmap(mm) \
+do { \
+ struct vm_area_struct *high_vma = find_vma(mm, 0xffff0000); \
+ if (high_vma) { \
+ BUG_ON(high_vma->vm_next); /* it should be last */ \
+ if (high_vma->vm_prev) \
+ high_vma->vm_prev->vm_next = NULL; \
+ else \
+ mm->mmap = NULL; \
+ rb_erase(&high_vma->vm_rb, &mm->mm_rb); \
+ mm->mmap_cache = NULL; \
+ mm->map_count--; \
+ remove_vma(high_vma); \
+ } \
+} while (0)
+
+static inline void arch_dup_mmap(struct mm_struct *oldmm,
+ struct mm_struct *mm)
+{
+}
+
#endif
diff --git a/arch/arm/include/asm/module.h b/arch/arm/include/asm/module.h
index e4dfa69abb68..cbb0bc295d2b 100644
--- a/arch/arm/include/asm/module.h
+++ b/arch/arm/include/asm/module.h
@@ -7,20 +7,27 @@
struct unwind_table;
-struct mod_arch_specific
-{
#ifdef CONFIG_ARM_UNWIND
- Elf_Shdr *unw_sec_init;
- Elf_Shdr *unw_sec_devinit;
- Elf_Shdr *unw_sec_core;
- Elf_Shdr *sec_init_text;
- Elf_Shdr *sec_devinit_text;
- Elf_Shdr *sec_core_text;
- struct unwind_table *unwind_init;
- struct unwind_table *unwind_devinit;
- struct unwind_table *unwind_core;
-#endif
+struct arm_unwind_mapping {
+ Elf_Shdr *unw_sec;
+ Elf_Shdr *sec_text;
+ struct unwind_table *unwind;
+};
+enum {
+ ARM_SEC_INIT,
+ ARM_SEC_DEVINIT,
+ ARM_SEC_CORE,
+ ARM_SEC_EXIT,
+ ARM_SEC_DEVEXIT,
+ ARM_SEC_MAX,
+};
+struct mod_arch_specific {
+ struct arm_unwind_mapping map[ARM_SEC_MAX];
};
+#else
+struct mod_arch_specific {
+};
+#endif
/*
* Include the ARM architecture version.
diff --git a/arch/arm/include/asm/perf_event.h b/arch/arm/include/asm/perf_event.h
index b5799a3b7117..c4aa4e8c6af9 100644
--- a/arch/arm/include/asm/perf_event.h
+++ b/arch/arm/include/asm/perf_event.h
@@ -12,18 +12,6 @@
#ifndef __ARM_PERF_EVENT_H__
#define __ARM_PERF_EVENT_H__
-/*
- * NOP: on *most* (read: all supported) ARM platforms, the performance
- * counter interrupts are regular interrupts and not an NMI. This
- * means that when we receive the interrupt we can call
- * perf_event_do_pending() that handles all of the work with
- * interrupts disabled.
- */
-static inline void
-set_perf_event_pending(void)
-{
-}
-
/* ARM performance counters start from 1 (in the cp15 accesses) so use the
* same indexes here for consistency. */
#define PERF_EVENT_INDEX_OFFSET 1
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h
index e90b167ea848..a9672e8406a3 100644
--- a/arch/arm/include/asm/pgtable.h
+++ b/arch/arm/include/asm/pgtable.h
@@ -278,9 +278,24 @@ extern struct page *empty_zero_page;
#define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,pte,ext)
-#define set_pte_at(mm,addr,ptep,pteval) do { \
- set_pte_ext(ptep, pteval, (addr) >= TASK_SIZE ? 0 : PTE_EXT_NG); \
- } while (0)
+#if __LINUX_ARM_ARCH__ < 6
+static inline void __sync_icache_dcache(pte_t pteval)
+{
+}
+#else
+extern void __sync_icache_dcache(pte_t pteval);
+#endif
+
+static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep, pte_t pteval)
+{
+ if (addr >= TASK_SIZE)
+ set_pte_ext(ptep, pteval, 0);
+ else {
+ __sync_icache_dcache(pteval);
+ set_pte_ext(ptep, pteval, PTE_EXT_NG);
+ }
+}
/*
* The following only work if pte_present() is true.
@@ -290,8 +305,13 @@ extern struct page *empty_zero_page;
#define pte_write(pte) (pte_val(pte) & L_PTE_WRITE)
#define pte_dirty(pte) (pte_val(pte) & L_PTE_DIRTY)
#define pte_young(pte) (pte_val(pte) & L_PTE_YOUNG)
+#define pte_exec(pte) (pte_val(pte) & L_PTE_EXEC)
#define pte_special(pte) (0)
+#define pte_present_user(pte) \
+ ((pte_val(pte) & (L_PTE_PRESENT | L_PTE_USER)) == \
+ (L_PTE_PRESENT | L_PTE_USER))
+
#define PTE_BIT_FUNC(fn,op) \
static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; }
diff --git a/arch/arm/include/asm/processor.h b/arch/arm/include/asm/processor.h
index 7bed3daf83b8..67357baaeeeb 100644
--- a/arch/arm/include/asm/processor.h
+++ b/arch/arm/include/asm/processor.h
@@ -19,6 +19,7 @@
#ifdef __KERNEL__
+#include <asm/hw_breakpoint.h>
#include <asm/ptrace.h>
#include <asm/types.h>
@@ -41,6 +42,9 @@ struct debug_entry {
struct debug_info {
int nsaved;
struct debug_entry bp[2];
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+ struct perf_event *hbp[ARM_MAX_HBP_SLOTS];
+#endif
};
struct thread_struct {
diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h
index 7ce15eb15f72..783d50f32618 100644
--- a/arch/arm/include/asm/ptrace.h
+++ b/arch/arm/include/asm/ptrace.h
@@ -29,6 +29,8 @@
#define PTRACE_SETCRUNCHREGS 26
#define PTRACE_GETVFPREGS 27
#define PTRACE_SETVFPREGS 28
+#define PTRACE_GETHBPREGS 29
+#define PTRACE_SETHBPREGS 30
/*
* PSR bits
diff --git a/arch/arm/include/asm/seccomp.h b/arch/arm/include/asm/seccomp.h
new file mode 100644
index 000000000000..52b156b341f5
--- /dev/null
+++ b/arch/arm/include/asm/seccomp.h
@@ -0,0 +1,11 @@
+#ifndef _ASM_ARM_SECCOMP_H
+#define _ASM_ARM_SECCOMP_H
+
+#include <linux/unistd.h>
+
+#define __NR_seccomp_read __NR_read
+#define __NR_seccomp_write __NR_write
+#define __NR_seccomp_exit __NR_exit
+#define __NR_seccomp_sigreturn __NR_rt_sigreturn
+
+#endif /* _ASM_ARM_SECCOMP_H */
diff --git a/arch/arm/include/asm/smp_mpidr.h b/arch/arm/include/asm/smp_mpidr.h
new file mode 100644
index 000000000000..6a9307d64900
--- /dev/null
+++ b/arch/arm/include/asm/smp_mpidr.h
@@ -0,0 +1,17 @@
+#ifndef ASMARM_SMP_MIDR_H
+#define ASMARM_SMP_MIDR_H
+
+#define hard_smp_processor_id() \
+ ({ \
+ unsigned int cpunum; \
+ __asm__("\n" \
+ "1: mrc p15, 0, %0, c0, c0, 5\n" \
+ " .pushsection \".alt.smp.init\", \"a\"\n"\
+ " .long 1b\n" \
+ " mov %0, #0\n" \
+ " .popsection" \
+ : "=r" (cpunum)); \
+ cpunum &= 0x0F; \
+ })
+
+#endif
diff --git a/arch/arm/include/asm/smp_plat.h b/arch/arm/include/asm/smp_plat.h
index e6215305544a..f24c1b9e211d 100644
--- a/arch/arm/include/asm/smp_plat.h
+++ b/arch/arm/include/asm/smp_plat.h
@@ -7,15 +7,40 @@
#include <asm/cputype.h>
+/*
+ * Return true if we are running on a SMP platform
+ */
+static inline bool is_smp(void)
+{
+#ifndef CONFIG_SMP
+ return false;
+#elif defined(CONFIG_SMP_ON_UP)
+ extern unsigned int smp_on_up;
+ return !!smp_on_up;
+#else
+ return true;
+#endif
+}
+
/* all SMP configurations have the extended CPUID registers */
static inline int tlb_ops_need_broadcast(void)
{
+ if (!is_smp())
+ return 0;
+
return ((read_cpuid_ext(CPUID_EXT_MMFR3) >> 12) & 0xf) < 2;
}
+#if !defined(CONFIG_SMP) || __LINUX_ARM_ARCH__ >= 7
+#define cache_ops_need_broadcast() 0
+#else
static inline int cache_ops_need_broadcast(void)
{
+ if (!is_smp())
+ return 0;
+
return ((read_cpuid_ext(CPUID_EXT_MMFR3) >> 12) & 0xf) < 1;
}
+#endif
#endif
diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h
index 8ba1ccf82a02..1120f18a6b17 100644
--- a/arch/arm/include/asm/system.h
+++ b/arch/arm/include/asm/system.h
@@ -85,6 +85,10 @@ void hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int,
struct pt_regs *),
int sig, int code, const char *name);
+void hook_ifault_code(int nr, int (*fn)(unsigned long, unsigned int,
+ struct pt_regs *),
+ int sig, int code, const char *name);
+
#define xchg(ptr,x) \
((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
@@ -325,6 +329,8 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size
extern void disable_hlt(void);
extern void enable_hlt(void);
+void cpu_idle_wait(void);
+
#include <asm-generic/cmpxchg-local.h>
#if __LINUX_ARM_ARCH__ < 6
diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h
index 763e29fa8530..7b5cc8dae06e 100644
--- a/arch/arm/include/asm/thread_info.h
+++ b/arch/arm/include/asm/thread_info.h
@@ -144,6 +144,7 @@ extern void vfp_flush_hwstate(struct thread_info *);
#define TIF_MEMDIE 18 /* is terminating due to OOM killer */
#define TIF_FREEZE 19
#define TIF_RESTORE_SIGMASK 20
+#define TIF_SECCOMP 21
#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
@@ -153,6 +154,7 @@ extern void vfp_flush_hwstate(struct thread_info *);
#define _TIF_USING_IWMMXT (1 << TIF_USING_IWMMXT)
#define _TIF_FREEZE (1 << TIF_FREEZE)
#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK)
+#define _TIF_SECCOMP (1 << TIF_SECCOMP)
/*
* Change these and you break ASM code in entry-common.S
diff --git a/arch/arm/include/asm/tlbflush.h b/arch/arm/include/asm/tlbflush.h
index 33b546ae72d4..ce7378ea15a2 100644
--- a/arch/arm/include/asm/tlbflush.h
+++ b/arch/arm/include/asm/tlbflush.h
@@ -70,6 +70,10 @@
#undef _TLB
#undef MULTI_TLB
+#ifdef CONFIG_SMP_ON_UP
+#define MULTI_TLB 1
+#endif
+
#define v3_tlb_flags (TLB_V3_FULL | TLB_V3_PAGE)
#ifdef CONFIG_CPU_TLB_V3
@@ -185,17 +189,23 @@
# define v6wbi_always_flags (-1UL)
#endif
-#ifdef CONFIG_SMP
-#define v7wbi_tlb_flags (TLB_WB | TLB_DCLEAN | TLB_V7_IS_BTB | \
+#define v7wbi_tlb_flags_smp (TLB_WB | TLB_DCLEAN | TLB_V7_IS_BTB | \
TLB_V7_UIS_FULL | TLB_V7_UIS_PAGE | TLB_V7_UIS_ASID)
-#else
-#define v7wbi_tlb_flags (TLB_WB | TLB_DCLEAN | TLB_BTB | \
+#define v7wbi_tlb_flags_up (TLB_WB | TLB_DCLEAN | TLB_BTB | \
TLB_V6_U_FULL | TLB_V6_U_PAGE | TLB_V6_U_ASID)
-#endif
#ifdef CONFIG_CPU_TLB_V7
-# define v7wbi_possible_flags v7wbi_tlb_flags
-# define v7wbi_always_flags v7wbi_tlb_flags
+
+# ifdef CONFIG_SMP_ON_UP
+# define v7wbi_possible_flags (v7wbi_tlb_flags_smp | v7wbi_tlb_flags_up)
+# define v7wbi_always_flags (v7wbi_tlb_flags_smp & v7wbi_tlb_flags_up)
+# elif defined(CONFIG_SMP)
+# define v7wbi_possible_flags v7wbi_tlb_flags_smp
+# define v7wbi_always_flags v7wbi_tlb_flags_smp
+# else
+# define v7wbi_possible_flags v7wbi_tlb_flags_up
+# define v7wbi_always_flags v7wbi_tlb_flags_up
+# endif
# ifdef _TLB
# define MULTI_TLB 1
# else
@@ -560,12 +570,20 @@ extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
#endif
/*
- * if PG_dcache_dirty is set for the page, we need to ensure that any
+ * If PG_dcache_clean is not set for the page, we need to ensure that any
* cache entries for the kernels virtual memory range are written
- * back to the page.
+ * back to the page. On ARMv6 and later, the cache coherency is handled via
+ * the set_pte_at() function.
*/
+#if __LINUX_ARM_ARCH__ < 6
extern void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr,
pte_t *ptep);
+#else
+static inline void update_mmu_cache(struct vm_area_struct *vma,
+ unsigned long addr, pte_t *ptep)
+{
+}
+#endif
#endif
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 980b78e31328..5b9b268f4fbb 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -42,6 +42,7 @@ obj-$(CONFIG_KGDB) += kgdb.o
obj-$(CONFIG_ARM_UNWIND) += unwind.o
obj-$(CONFIG_HAVE_TCM) += tcm.o
obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
+obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o
obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o
AFLAGS_crunch-bits.o := -Wa,-mcpu=ep9312
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c
index 8214bfebfaca..e5e1e5387678 100644
--- a/arch/arm/kernel/armksyms.c
+++ b/arch/arm/kernel/armksyms.c
@@ -165,6 +165,8 @@ EXPORT_SYMBOL(_find_next_bit_be);
#endif
#ifdef CONFIG_FUNCTION_TRACER
+#ifdef CONFIG_OLD_MCOUNT
EXPORT_SYMBOL(mcount);
+#endif
EXPORT_SYMBOL(__gnu_mcount_nc);
#endif
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index 85f2a019f77b..82da66172132 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -102,8 +102,6 @@ int main(void)
DEFINE(SIZEOF_MACHINE_DESC, sizeof(struct machine_desc));
DEFINE(MACHINFO_TYPE, offsetof(struct machine_desc, nr));
DEFINE(MACHINFO_NAME, offsetof(struct machine_desc, name));
- DEFINE(MACHINFO_PHYSIO, offsetof(struct machine_desc, phys_io));
- DEFINE(MACHINFO_PGOFFIO, offsetof(struct machine_desc, io_pg_offst));
BLANK();
DEFINE(PROC_INFO_SZ, sizeof(struct proc_info_list));
DEFINE(PROCINFO_INITFUNC, offsetof(struct proc_info_list, __cpu_flush));
diff --git a/arch/arm/kernel/debug.S b/arch/arm/kernel/debug.S
index a38b4879441d..a0f07521ca8a 100644
--- a/arch/arm/kernel/debug.S
+++ b/arch/arm/kernel/debug.S
@@ -22,11 +22,11 @@
#if defined(CONFIG_DEBUG_ICEDCC)
@@ debug using ARM EmbeddedICE DCC channel
-#if defined(CONFIG_CPU_V6)
-
- .macro addruart, rx, tmp
+ .macro addruart, rp, rv
.endm
+#if defined(CONFIG_CPU_V6)
+
.macro senduart, rd, rx
mcr p14, 0, \rd, c0, c5, 0
.endm
@@ -51,9 +51,6 @@
#elif defined(CONFIG_CPU_V7)
- .macro addruart, rx, tmp
- .endm
-
.macro senduart, rd, rx
mcr p14, 0, \rd, c0, c5, 0
.endm
@@ -71,9 +68,6 @@ wait: mrc p14, 0, pc, c0, c1, 0
#elif defined(CONFIG_CPU_XSCALE)
- .macro addruart, rx, tmp
- .endm
-
.macro senduart, rd, rx
mcr p14, 0, \rd, c8, c0, 0
.endm
@@ -98,9 +92,6 @@ wait: mrc p14, 0, pc, c0, c1, 0
#else
- .macro addruart, rx, tmp
- .endm
-
.macro senduart, rd, rx
mcr p14, 0, \rd, c1, c0, 0
.endm
@@ -130,6 +121,22 @@ wait: mrc p14, 0, pc, c0, c1, 0
#include <mach/debug-macro.S>
#endif /* CONFIG_DEBUG_ICEDCC */
+#ifdef CONFIG_MMU
+ .macro addruart_current, rx, tmp1, tmp2
+ addruart \tmp1, \tmp2
+ mrc p15, 0, \rx, c1, c0
+ tst \rx, #1
+ moveq \rx, \tmp1
+ movne \rx, \tmp2
+ .endm
+
+#else /* !CONFIG_MMU */
+ .macro addruart_current, rx, tmp1, tmp2
+ addruart \rx, \tmp1
+ .endm
+
+#endif /* CONFIG_MMU */
+
/*
* Useful debugging routines
*/
@@ -164,7 +171,7 @@ ENDPROC(printhex2)
.ltorg
ENTRY(printascii)
- addruart r3, r1
+ addruart_current r3, r1, r2
b 2f
1: waituart r2, r3
senduart r1, r3
@@ -180,7 +187,7 @@ ENTRY(printascii)
ENDPROC(printascii)
ENTRY(printch)
- addruart r3, r1
+ addruart_current r3, r1, r2
mov r1, r0
mov r0, #0
b 1b
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index bb8e93a76407..c09e3573c5de 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -46,7 +46,8 @@
* this macro assumes that irqstat (r6) and base (r5) are
* preserved from get_irqnr_and_base above
*/
- test_for_ipi r0, r6, r5, lr
+ ALT_SMP(test_for_ipi r0, r6, r5, lr)
+ ALT_UP_B(9997f)
movne r0, sp
adrne lr, BSYM(1b)
bne do_IPI
@@ -57,6 +58,7 @@
adrne lr, BSYM(1b)
bne do_local_timer
#endif
+9997:
#endif
.endm
@@ -965,11 +967,8 @@ kuser_cmpxchg_fixup:
beq 1b
rsbs r0, r3, #0
/* beware -- each __kuser slot must be 8 instructions max */
-#ifdef CONFIG_SMP
- b __kuser_memory_barrier
-#else
- usr_ret lr
-#endif
+ ALT_SMP(b __kuser_memory_barrier)
+ ALT_UP(usr_ret lr)
#endif
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 7885722bdf4e..8bfa98757cd2 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -129,30 +129,58 @@ ENDPROC(ret_from_fork)
* clobber the ip register. This is OK because the ARM calling convention
* allows it to be clobbered in subroutines and doesn't use it to hold
* parameters.)
+ *
+ * When using dynamic ftrace, we patch out the mcount call by a "mov r0, r0"
+ * for the mcount case, and a "pop {lr}" for the __gnu_mcount_nc case (see
+ * arch/arm/kernel/ftrace.c).
*/
+
+#ifndef CONFIG_OLD_MCOUNT
+#if (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 4))
+#error Ftrace requires CONFIG_FRAME_POINTER=y with GCC older than 4.4.0.
+#endif
+#endif
+
#ifdef CONFIG_DYNAMIC_FTRACE
-ENTRY(mcount)
+ENTRY(__gnu_mcount_nc)
+ mov ip, lr
+ ldmia sp!, {lr}
+ mov pc, ip
+ENDPROC(__gnu_mcount_nc)
+
+ENTRY(ftrace_caller)
stmdb sp!, {r0-r3, lr}
mov r0, lr
sub r0, r0, #MCOUNT_INSN_SIZE
+ ldr r1, [sp, #20]
- .globl mcount_call
-mcount_call:
+ .global ftrace_call
+ftrace_call:
bl ftrace_stub
- ldr lr, [fp, #-4] @ restore lr
- ldmia sp!, {r0-r3, pc}
+ ldmia sp!, {r0-r3, ip, lr}
+ mov pc, ip
+ENDPROC(ftrace_caller)
-ENTRY(ftrace_caller)
+#ifdef CONFIG_OLD_MCOUNT
+ENTRY(mcount)
+ stmdb sp!, {lr}
+ ldr lr, [fp, #-4]
+ ldmia sp!, {pc}
+ENDPROC(mcount)
+
+ENTRY(ftrace_caller_old)
stmdb sp!, {r0-r3, lr}
ldr r1, [fp, #-4]
mov r0, lr
sub r0, r0, #MCOUNT_INSN_SIZE
- .globl ftrace_call
-ftrace_call:
+ .globl ftrace_call_old
+ftrace_call_old:
bl ftrace_stub
ldr lr, [fp, #-4] @ restore lr
ldmia sp!, {r0-r3, pc}
+ENDPROC(ftrace_caller_old)
+#endif
#else
@@ -160,7 +188,7 @@ ENTRY(__gnu_mcount_nc)
stmdb sp!, {r0-r3, lr}
ldr r0, =ftrace_trace_function
ldr r2, [r0]
- adr r0, ftrace_stub
+ adr r0, .Lftrace_stub
cmp r0, r2
bne gnu_trace
ldmia sp!, {r0-r3, ip, lr}
@@ -170,11 +198,19 @@ gnu_trace:
ldr r1, [sp, #20] @ lr of instrumented routine
mov r0, lr
sub r0, r0, #MCOUNT_INSN_SIZE
- mov lr, pc
+ adr lr, BSYM(1f)
mov pc, r2
+1:
ldmia sp!, {r0-r3, ip, lr}
mov pc, ip
+ENDPROC(__gnu_mcount_nc)
+#ifdef CONFIG_OLD_MCOUNT
+/*
+ * This is under an ifdef in order to force link-time errors for people trying
+ * to build with !FRAME_POINTER with a GCC which doesn't use the new-style
+ * mcount.
+ */
ENTRY(mcount)
stmdb sp!, {r0-r3, lr}
ldr r0, =ftrace_trace_function
@@ -193,12 +229,15 @@ trace:
mov pc, r2
ldr lr, [fp, #-4] @ restore lr
ldmia sp!, {r0-r3, pc}
+ENDPROC(mcount)
+#endif
#endif /* CONFIG_DYNAMIC_FTRACE */
- .globl ftrace_stub
-ftrace_stub:
+ENTRY(ftrace_stub)
+.Lftrace_stub:
mov pc, lr
+ENDPROC(ftrace_stub)
#endif /* CONFIG_FUNCTION_TRACER */
@@ -295,7 +334,6 @@ ENTRY(vector_swi)
get_thread_info tsk
adr tbl, sys_call_table @ load syscall table pointer
- ldr ip, [tsk, #TI_FLAGS] @ check for syscall tracing
#if defined(CONFIG_OABI_COMPAT)
/*
@@ -312,8 +350,20 @@ ENTRY(vector_swi)
eor scno, scno, #__NR_SYSCALL_BASE @ check OS number
#endif
+ ldr r10, [tsk, #TI_FLAGS] @ check for syscall tracing
stmdb sp!, {r4, r5} @ push fifth and sixth args
- tst ip, #_TIF_SYSCALL_TRACE @ are we tracing syscalls?
+
+#ifdef CONFIG_SECCOMP
+ tst r10, #_TIF_SECCOMP
+ beq 1f
+ mov r0, scno
+ bl __secure_computing
+ add r0, sp, #S_R0 + S_OFF @ pointer to regs
+ ldmia r0, {r0 - r3} @ have to reload r0 - r3
+1:
+#endif
+
+ tst r10, #_TIF_SYSCALL_TRACE @ are we tracing syscalls?
bne __sys_trace
cmp scno, #NR_syscalls @ check upper syscall limit
diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c
index 33c7077174db..11db62806a1a 100644
--- a/arch/arm/kernel/etm.c
+++ b/arch/arm/kernel/etm.c
@@ -30,6 +30,21 @@
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Alexander Shishkin");
+/*
+ * ETM tracer state
+ */
+struct tracectx {
+ unsigned int etb_bufsz;
+ void __iomem *etb_regs;
+ void __iomem *etm_regs;
+ unsigned long flags;
+ int ncmppairs;
+ int etm_portsz;
+ struct device *dev;
+ struct clk *emu_clk;
+ struct mutex mutex;
+};
+
static struct tracectx tracer;
static inline bool trace_isrunning(struct tracectx *t)
@@ -314,6 +329,7 @@ static const struct file_operations etb_fops = {
.read = etb_read,
.open = etb_open,
.release = etb_release,
+ .llseek = no_llseek,
};
static struct miscdevice etb_miscdev = {
diff --git a/arch/arm/kernel/ftrace.c b/arch/arm/kernel/ftrace.c
index 0298286ad4ad..971ac8c36ea7 100644
--- a/arch/arm/kernel/ftrace.c
+++ b/arch/arm/kernel/ftrace.c
@@ -2,102 +2,194 @@
* Dynamic function tracing support.
*
* Copyright (C) 2008 Abhishek Sagar <sagar.abhishek@gmail.com>
+ * Copyright (C) 2010 Rabin Vincent <rabin@rab.in>
*
* For licencing details, see COPYING.
*
* Defines low-level handling of mcount calls when the kernel
* is compiled with the -pg flag. When using dynamic ftrace, the
- * mcount call-sites get patched lazily with NOP till they are
- * enabled. All code mutation routines here take effect atomically.
+ * mcount call-sites get patched with NOP till they are enabled.
+ * All code mutation routines here are called under stop_machine().
*/
#include <linux/ftrace.h>
+#include <linux/uaccess.h>
#include <asm/cacheflush.h>
#include <asm/ftrace.h>
-#define PC_OFFSET 8
-#define BL_OPCODE 0xeb000000
-#define BL_OFFSET_MASK 0x00ffffff
+#ifdef CONFIG_THUMB2_KERNEL
+#define NOP 0xeb04f85d /* pop.w {lr} */
+#else
+#define NOP 0xe8bd4000 /* pop {lr} */
+#endif
-static unsigned long bl_insn;
-static const unsigned long NOP = 0xe1a00000; /* mov r0, r0 */
+#ifdef CONFIG_OLD_MCOUNT
+#define OLD_MCOUNT_ADDR ((unsigned long) mcount)
+#define OLD_FTRACE_ADDR ((unsigned long) ftrace_caller_old)
-unsigned char *ftrace_nop_replace(void)
+#define OLD_NOP 0xe1a00000 /* mov r0, r0 */
+
+static unsigned long ftrace_nop_replace(struct dyn_ftrace *rec)
{
- return (char *)&NOP;
+ return rec->arch.old_mcount ? OLD_NOP : NOP;
}
+static unsigned long adjust_address(struct dyn_ftrace *rec, unsigned long addr)
+{
+ if (!rec->arch.old_mcount)
+ return addr;
+
+ if (addr == MCOUNT_ADDR)
+ addr = OLD_MCOUNT_ADDR;
+ else if (addr == FTRACE_ADDR)
+ addr = OLD_FTRACE_ADDR;
+
+ return addr;
+}
+#else
+static unsigned long ftrace_nop_replace(struct dyn_ftrace *rec)
+{
+ return NOP;
+}
+
+static unsigned long adjust_address(struct dyn_ftrace *rec, unsigned long addr)
+{
+ return addr;
+}
+#endif
+
/* construct a branch (BL) instruction to addr */
-unsigned char *ftrace_call_replace(unsigned long pc, unsigned long addr)
+#ifdef CONFIG_THUMB2_KERNEL
+static unsigned long ftrace_call_replace(unsigned long pc, unsigned long addr)
{
+ unsigned long s, j1, j2, i1, i2, imm10, imm11;
+ unsigned long first, second;
long offset;
- offset = (long)addr - (long)(pc + PC_OFFSET);
+ offset = (long)addr - (long)(pc + 4);
+ if (offset < -16777216 || offset > 16777214) {
+ WARN_ON_ONCE(1);
+ return 0;
+ }
+
+ s = (offset >> 24) & 0x1;
+ i1 = (offset >> 23) & 0x1;
+ i2 = (offset >> 22) & 0x1;
+ imm10 = (offset >> 12) & 0x3ff;
+ imm11 = (offset >> 1) & 0x7ff;
+
+ j1 = (!i1) ^ s;
+ j2 = (!i2) ^ s;
+
+ first = 0xf000 | (s << 10) | imm10;
+ second = 0xd000 | (j1 << 13) | (j2 << 11) | imm11;
+
+ return (second << 16) | first;
+}
+#else
+static unsigned long ftrace_call_replace(unsigned long pc, unsigned long addr)
+{
+ long offset;
+
+ offset = (long)addr - (long)(pc + 8);
if (unlikely(offset < -33554432 || offset > 33554428)) {
/* Can't generate branches that far (from ARM ARM). Ftrace
* doesn't generate branches outside of kernel text.
*/
WARN_ON_ONCE(1);
- return NULL;
+ return 0;
}
- offset = (offset >> 2) & BL_OFFSET_MASK;
- bl_insn = BL_OPCODE | offset;
- return (unsigned char *)&bl_insn;
-}
-int ftrace_modify_code(unsigned long pc, unsigned char *old_code,
- unsigned char *new_code)
-{
- unsigned long err = 0, replaced = 0, old, new;
+ offset = (offset >> 2) & 0x00ffffff;
- old = *(unsigned long *)old_code;
- new = *(unsigned long *)new_code;
+ return 0xeb000000 | offset;
+}
+#endif
- __asm__ __volatile__ (
- "1: ldr %1, [%2] \n"
- " cmp %1, %4 \n"
- "2: streq %3, [%2] \n"
- " cmpne %1, %3 \n"
- " movne %0, #2 \n"
- "3:\n"
+static int ftrace_modify_code(unsigned long pc, unsigned long old,
+ unsigned long new)
+{
+ unsigned long replaced;
- ".pushsection .fixup, \"ax\"\n"
- "4: mov %0, #1 \n"
- " b 3b \n"
- ".popsection\n"
+ if (probe_kernel_read(&replaced, (void *)pc, MCOUNT_INSN_SIZE))
+ return -EFAULT;
- ".pushsection __ex_table, \"a\"\n"
- " .long 1b, 4b \n"
- " .long 2b, 4b \n"
- ".popsection\n"
+ if (replaced != old)
+ return -EINVAL;
- : "=r"(err), "=r"(replaced)
- : "r"(pc), "r"(new), "r"(old), "0"(err), "1"(replaced)
- : "memory");
+ if (probe_kernel_write((void *)pc, &new, MCOUNT_INSN_SIZE))
+ return -EPERM;
- if (!err && (replaced == old))
- flush_icache_range(pc, pc + MCOUNT_INSN_SIZE);
+ flush_icache_range(pc, pc + MCOUNT_INSN_SIZE);
- return err;
+ return 0;
}
int ftrace_update_ftrace_func(ftrace_func_t func)
{
- int ret;
unsigned long pc, old;
- unsigned char *new;
+ unsigned long new;
+ int ret;
pc = (unsigned long)&ftrace_call;
memcpy(&old, &ftrace_call, MCOUNT_INSN_SIZE);
new = ftrace_call_replace(pc, (unsigned long)func);
- ret = ftrace_modify_code(pc, (unsigned char *)&old, new);
+
+ ret = ftrace_modify_code(pc, old, new);
+
+#ifdef CONFIG_OLD_MCOUNT
+ if (!ret) {
+ pc = (unsigned long)&ftrace_call_old;
+ memcpy(&old, &ftrace_call_old, MCOUNT_INSN_SIZE);
+ new = ftrace_call_replace(pc, (unsigned long)func);
+
+ ret = ftrace_modify_code(pc, old, new);
+ }
+#endif
+
+ return ret;
+}
+
+int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
+{
+ unsigned long new, old;
+ unsigned long ip = rec->ip;
+
+ old = ftrace_nop_replace(rec);
+ new = ftrace_call_replace(ip, adjust_address(rec, addr));
+
+ return ftrace_modify_code(rec->ip, old, new);
+}
+
+int ftrace_make_nop(struct module *mod,
+ struct dyn_ftrace *rec, unsigned long addr)
+{
+ unsigned long ip = rec->ip;
+ unsigned long old;
+ unsigned long new;
+ int ret;
+
+ old = ftrace_call_replace(ip, adjust_address(rec, addr));
+ new = ftrace_nop_replace(rec);
+ ret = ftrace_modify_code(ip, old, new);
+
+#ifdef CONFIG_OLD_MCOUNT
+ if (ret == -EINVAL && addr == MCOUNT_ADDR) {
+ rec->arch.old_mcount = true;
+
+ old = ftrace_call_replace(ip, adjust_address(rec, addr));
+ new = ftrace_nop_replace(rec);
+ ret = ftrace_modify_code(ip, old, new);
+ }
+#endif
+
return ret;
}
-/* run from ftrace_init with irqs disabled */
int __init ftrace_dyn_arch_init(void *data)
{
- ftrace_mcount_set(data);
+ *(unsigned long *)data = 0;
+
return 0;
}
diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S
index b9505aa267c0..bbecaac1e013 100644
--- a/arch/arm/kernel/head-common.S
+++ b/arch/arm/kernel/head-common.S
@@ -15,55 +15,6 @@
#define ATAG_CORE_SIZE ((2*4 + 3*4) >> 2)
#define ATAG_CORE_SIZE_EMPTY ((2*4) >> 2)
- .align 2
- .type __switch_data, %object
-__switch_data:
- .long __mmap_switched
- .long __data_loc @ r4
- .long _data @ r5
- .long __bss_start @ r6
- .long _end @ r7
- .long processor_id @ r4
- .long __machine_arch_type @ r5
- .long __atags_pointer @ r6
- .long cr_alignment @ r7
- .long init_thread_union + THREAD_START_SP @ sp
-
-/*
- * The following fragment of code is executed with the MMU on in MMU mode,
- * and uses absolute addresses; this is not position independent.
- *
- * r0 = cp#15 control register
- * r1 = machine ID
- * r2 = atags pointer
- * r9 = processor ID
- */
-__mmap_switched:
- adr r3, __switch_data + 4
-
- ldmia r3!, {r4, r5, r6, r7}
- cmp r4, r5 @ Copy data segment if needed
-1: cmpne r5, r6
- ldrne fp, [r4], #4
- strne fp, [r5], #4
- bne 1b
-
- mov fp, #0 @ Clear BSS (and zero fp)
-1: cmp r6, r7
- strcc fp, [r6],#4
- bcc 1b
-
- ARM( ldmia r3, {r4, r5, r6, r7, sp})
- THUMB( ldmia r3, {r4, r5, r6, r7} )
- THUMB( ldr sp, [r3, #16] )
- str r9, [r4] @ Save processor ID
- str r1, [r5] @ Save machine type
- str r2, [r6] @ Save atags pointer
- bic r4, r0, #CR_A @ Clear 'A' bit
- stmia r7, {r0, r4} @ Save control register values
- b start_kernel
-ENDPROC(__mmap_switched)
-
/*
* Exception handling. Something went wrong and we can't proceed. We
* ought to tell the user, but since we don't have any guarantee that
@@ -73,21 +24,7 @@ ENDPROC(__mmap_switched)
* and hope for the best (useful if bootloader fails to pass a proper
* machine ID for example).
*/
-__error_p:
-#ifdef CONFIG_DEBUG_LL
- adr r0, str_p1
- bl printascii
- mov r0, r9
- bl printhex8
- adr r0, str_p2
- bl printascii
- b __error
-str_p1: .asciz "\nError: unrecognized/unsupported processor variant (0x"
-str_p2: .asciz ").\n"
- .align
-#endif
-ENDPROC(__error_p)
-
+ __HEAD
__error_a:
#ifdef CONFIG_DEBUG_LL
mov r4, r1 @ preserve machine ID
@@ -97,7 +34,7 @@ __error_a:
bl printhex8
adr r0, str_a2
bl printascii
- adr r3, 4f
+ adr r3, __lookup_machine_type_data
ldmia r3, {r4, r5, r6} @ get machine desc list
sub r4, r3, r4 @ get offset between virt&phys
add r5, r5, r4 @ convert virt addresses to
@@ -125,78 +62,6 @@ str_a3: .asciz "\nPlease check your kernel config and/or bootloader.\n"
.align
#endif
-__error:
-#ifdef CONFIG_ARCH_RPC
-/*
- * Turn the screen red on a error - RiscPC only.
- */
- mov r0, #0x02000000
- mov r3, #0x11
- orr r3, r3, r3, lsl #8
- orr r3, r3, r3, lsl #16
- str r3, [r0], #4
- str r3, [r0], #4
- str r3, [r0], #4
- str r3, [r0], #4
-#endif
-1: mov r0, r0
- b 1b
-ENDPROC(__error)
-
-
-/*
- * Read processor ID register (CP#15, CR0), and look up in the linker-built
- * supported processor list. Note that we can't use the absolute addresses
- * for the __proc_info lists since we aren't running with the MMU on
- * (and therefore, we are not in the correct address space). We have to
- * calculate the offset.
- *
- * r9 = cpuid
- * Returns:
- * r3, r4, r6 corrupted
- * r5 = proc_info pointer in physical address space
- * r9 = cpuid (preserved)
- */
-__lookup_processor_type:
- adr r3, 3f
- ldmia r3, {r5 - r7}
- add r3, r3, #8
- sub r3, r3, r7 @ get offset between virt&phys
- add r5, r5, r3 @ convert virt addresses to
- add r6, r6, r3 @ physical address space
-1: ldmia r5, {r3, r4} @ value, mask
- and r4, r4, r9 @ mask wanted bits
- teq r3, r4
- beq 2f
- add r5, r5, #PROC_INFO_SZ @ sizeof(proc_info_list)
- cmp r5, r6
- blo 1b
- mov r5, #0 @ unknown processor
-2: mov pc, lr
-ENDPROC(__lookup_processor_type)
-
-/*
- * This provides a C-API version of the above function.
- */
-ENTRY(lookup_processor_type)
- stmfd sp!, {r4 - r7, r9, lr}
- mov r9, r0
- bl __lookup_processor_type
- mov r0, r5
- ldmfd sp!, {r4 - r7, r9, pc}
-ENDPROC(lookup_processor_type)
-
-/*
- * Look in <asm/procinfo.h> and arch/arm/kernel/arch.[ch] for
- * more information about the __proc_info and __arch_info structures.
- */
- .align 2
-3: .long __proc_info_begin
- .long __proc_info_end
-4: .long .
- .long __arch_info_begin
- .long __arch_info_end
-
/*
* Lookup machine architecture in the linker-build list of architectures.
* Note that we can't use the absolute addresses for the __arch_info
@@ -209,7 +74,7 @@ ENDPROC(lookup_processor_type)
* r5 = mach_info pointer in physical address space
*/
__lookup_machine_type:
- adr r3, 4b
+ adr r3, __lookup_machine_type_data
ldmia r3, {r4, r5, r6}
sub r3, r3, r4 @ get offset between virt&phys
add r5, r5, r3 @ convert virt addresses to
@@ -225,15 +90,16 @@ __lookup_machine_type:
ENDPROC(__lookup_machine_type)
/*
- * This provides a C-API version of the above function.
+ * Look in arch/arm/kernel/arch.[ch] for information about the
+ * __arch_info structures.
*/
-ENTRY(lookup_machine_type)
- stmfd sp!, {r4 - r6, lr}
- mov r1, r0
- bl __lookup_machine_type
- mov r0, r5
- ldmfd sp!, {r4 - r6, pc}
-ENDPROC(lookup_machine_type)
+ .align 2
+ .type __lookup_machine_type_data, %object
+__lookup_machine_type_data:
+ .long .
+ .long __arch_info_begin
+ .long __arch_info_end
+ .size __lookup_machine_type_data, . - __lookup_machine_type_data
/* Determine validity of the r2 atags pointer. The heuristic requires
* that the pointer be aligned, in the first 16k of physical RAM and
@@ -265,3 +131,150 @@ __vet_atags:
1: mov r2, #0
mov pc, lr
ENDPROC(__vet_atags)
+
+/*
+ * The following fragment of code is executed with the MMU on in MMU mode,
+ * and uses absolute addresses; this is not position independent.
+ *
+ * r0 = cp#15 control register
+ * r1 = machine ID
+ * r2 = atags pointer
+ * r9 = processor ID
+ */
+ __INIT
+__mmap_switched:
+ adr r3, __mmap_switched_data
+
+ ldmia r3!, {r4, r5, r6, r7}
+ cmp r4, r5 @ Copy data segment if needed
+1: cmpne r5, r6
+ ldrne fp, [r4], #4
+ strne fp, [r5], #4
+ bne 1b
+
+ mov fp, #0 @ Clear BSS (and zero fp)
+1: cmp r6, r7
+ strcc fp, [r6],#4
+ bcc 1b
+
+ ARM( ldmia r3, {r4, r5, r6, r7, sp})
+ THUMB( ldmia r3, {r4, r5, r6, r7} )
+ THUMB( ldr sp, [r3, #16] )
+ str r9, [r4] @ Save processor ID
+ str r1, [r5] @ Save machine type
+ str r2, [r6] @ Save atags pointer
+ bic r4, r0, #CR_A @ Clear 'A' bit
+ stmia r7, {r0, r4} @ Save control register values
+ b start_kernel
+ENDPROC(__mmap_switched)
+
+ .align 2
+ .type __mmap_switched_data, %object
+__mmap_switched_data:
+ .long __data_loc @ r4
+ .long _sdata @ r5
+ .long __bss_start @ r6
+ .long _end @ r7
+ .long processor_id @ r4
+ .long __machine_arch_type @ r5
+ .long __atags_pointer @ r6
+ .long cr_alignment @ r7
+ .long init_thread_union + THREAD_START_SP @ sp
+ .size __mmap_switched_data, . - __mmap_switched_data
+
+/*
+ * This provides a C-API version of __lookup_machine_type
+ */
+ENTRY(lookup_machine_type)
+ stmfd sp!, {r4 - r6, lr}
+ mov r1, r0
+ bl __lookup_machine_type
+ mov r0, r5
+ ldmfd sp!, {r4 - r6, pc}
+ENDPROC(lookup_machine_type)
+
+/*
+ * This provides a C-API version of __lookup_processor_type
+ */
+ENTRY(lookup_processor_type)
+ stmfd sp!, {r4 - r6, r9, lr}
+ mov r9, r0
+ bl __lookup_processor_type
+ mov r0, r5
+ ldmfd sp!, {r4 - r6, r9, pc}
+ENDPROC(lookup_processor_type)
+
+/*
+ * Read processor ID register (CP#15, CR0), and look up in the linker-built
+ * supported processor list. Note that we can't use the absolute addresses
+ * for the __proc_info lists since we aren't running with the MMU on
+ * (and therefore, we are not in the correct address space). We have to
+ * calculate the offset.
+ *
+ * r9 = cpuid
+ * Returns:
+ * r3, r4, r6 corrupted
+ * r5 = proc_info pointer in physical address space
+ * r9 = cpuid (preserved)
+ */
+ __CPUINIT
+__lookup_processor_type:
+ adr r3, __lookup_processor_type_data
+ ldmia r3, {r4 - r6}
+ sub r3, r3, r4 @ get offset between virt&phys
+ add r5, r5, r3 @ convert virt addresses to
+ add r6, r6, r3 @ physical address space
+1: ldmia r5, {r3, r4} @ value, mask
+ and r4, r4, r9 @ mask wanted bits
+ teq r3, r4
+ beq 2f
+ add r5, r5, #PROC_INFO_SZ @ sizeof(proc_info_list)
+ cmp r5, r6
+ blo 1b
+ mov r5, #0 @ unknown processor
+2: mov pc, lr
+ENDPROC(__lookup_processor_type)
+
+/*
+ * Look in <asm/procinfo.h> for information about the __proc_info structure.
+ */
+ .align 2
+ .type __lookup_processor_type_data, %object
+__lookup_processor_type_data:
+ .long .
+ .long __proc_info_begin
+ .long __proc_info_end
+ .size __lookup_processor_type_data, . - __lookup_processor_type_data
+
+__error_p:
+#ifdef CONFIG_DEBUG_LL
+ adr r0, str_p1
+ bl printascii
+ mov r0, r9
+ bl printhex8
+ adr r0, str_p2
+ bl printascii
+ b __error
+str_p1: .asciz "\nError: unrecognized/unsupported processor variant (0x"
+str_p2: .asciz ").\n"
+ .align
+#endif
+ENDPROC(__error_p)
+
+__error:
+#ifdef CONFIG_ARCH_RPC
+/*
+ * Turn the screen red on a error - RiscPC only.
+ */
+ mov r0, #0x02000000
+ mov r3, #0x11
+ orr r3, r3, r3, lsl #8
+ orr r3, r3, r3, lsl #16
+ str r3, [r0], #4
+ str r3, [r0], #4
+ str r3, [r0], #4
+ str r3, [r0], #4
+#endif
+1: mov r0, r0
+ b 1b
+ENDPROC(__error)
diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S
index 573b803dc6bf..814ce1a73270 100644
--- a/arch/arm/kernel/head-nommu.S
+++ b/arch/arm/kernel/head-nommu.S
@@ -48,8 +48,6 @@ ENTRY(stext)
movs r8, r5 @ invalid machine (r5=0)?
beq __error_a @ yes, error 'a'
- ldr r13, __switch_data @ address to jump to after
- @ the initialization is done
adr lr, BSYM(__after_proc_init) @ return (PIC) address
ARM( add pc, r10, #PROCINFO_INITFUNC )
THUMB( add r12, r10, #PROCINFO_INITFUNC )
@@ -87,8 +85,7 @@ __after_proc_init:
mcr p15, 0, r0, c1, c0, 0 @ write control reg
#endif /* CONFIG_CPU_CP15 */
- mov r3, r13
- mov pc, r3 @ clear the BSS and jump
+ b __mmap_switched @ clear the BSS and jump
@ to start_kernel
ENDPROC(__after_proc_init)
.ltorg
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index eb62bf947212..dd6b369ac69c 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -22,6 +22,10 @@
#include <asm/thread_info.h>
#include <asm/system.h>
+#ifdef CONFIG_DEBUG_LL
+#include <mach/debug-macro.S>
+#endif
+
#if (PHYS_OFFSET & 0x001fffff)
#error "PHYS_OFFSET must be at an even 2MiB boundary!"
#endif
@@ -86,6 +90,9 @@ ENTRY(stext)
movs r8, r5 @ invalid machine (r5=0)?
beq __error_a @ yes, error 'a'
bl __vet_atags
+#ifdef CONFIG_SMP_ON_UP
+ bl __fixup_smp
+#endif
bl __create_page_tables
/*
@@ -95,113 +102,15 @@ ENTRY(stext)
* above. On return, the CPU will be ready for the MMU to be
* turned on, and r0 will hold the CPU control register value.
*/
- ldr r13, __switch_data @ address to jump to after
+ ldr r13, =__mmap_switched @ address to jump to after
@ mmu has been enabled
- adr lr, BSYM(__enable_mmu) @ return (PIC) address
+ adr lr, BSYM(1f) @ return (PIC) address
ARM( add pc, r10, #PROCINFO_INITFUNC )
THUMB( add r12, r10, #PROCINFO_INITFUNC )
THUMB( mov pc, r12 )
+1: b __enable_mmu
ENDPROC(stext)
-
-#if defined(CONFIG_SMP)
-ENTRY(secondary_startup)
- /*
- * Common entry point for secondary CPUs.
- *
- * Ensure that we're in SVC mode, and IRQs are disabled. Lookup
- * the processor type - there is no need to check the machine type
- * as it has already been validated by the primary processor.
- */
- setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9
- mrc p15, 0, r9, c0, c0 @ get processor id
- bl __lookup_processor_type
- movs r10, r5 @ invalid processor?
- moveq r0, #'p' @ yes, error 'p'
- beq __error
-
- /*
- * Use the page tables supplied from __cpu_up.
- */
- adr r4, __secondary_data
- ldmia r4, {r5, r7, r12} @ address to jump to after
- sub r4, r4, r5 @ mmu has been enabled
- ldr r4, [r7, r4] @ get secondary_data.pgdir
- adr lr, BSYM(__enable_mmu) @ return address
- mov r13, r12 @ __secondary_switched address
- ARM( add pc, r10, #PROCINFO_INITFUNC ) @ initialise processor
- @ (return control reg)
- THUMB( add r12, r10, #PROCINFO_INITFUNC )
- THUMB( mov pc, r12 )
-ENDPROC(secondary_startup)
-
- /*
- * r6 = &secondary_data
- */
-ENTRY(__secondary_switched)
- ldr sp, [r7, #4] @ get secondary_data.stack
- mov fp, #0
- b secondary_start_kernel
-ENDPROC(__secondary_switched)
-
- .type __secondary_data, %object
-__secondary_data:
- .long .
- .long secondary_data
- .long __secondary_switched
-#endif /* defined(CONFIG_SMP) */
-
-
-
-/*
- * Setup common bits before finally enabling the MMU. Essentially
- * this is just loading the page table pointer and domain access
- * registers.
- */
-__enable_mmu:
-#ifdef CONFIG_ALIGNMENT_TRAP
- orr r0, r0, #CR_A
-#else
- bic r0, r0, #CR_A
-#endif
-#ifdef CONFIG_CPU_DCACHE_DISABLE
- bic r0, r0, #CR_C
-#endif
-#ifdef CONFIG_CPU_BPREDICT_DISABLE
- bic r0, r0, #CR_Z
-#endif
-#ifdef CONFIG_CPU_ICACHE_DISABLE
- bic r0, r0, #CR_I
-#endif
- mov r5, #(domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \
- domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \
- domain_val(DOMAIN_TABLE, DOMAIN_MANAGER) | \
- domain_val(DOMAIN_IO, DOMAIN_CLIENT))
- mcr p15, 0, r5, c3, c0, 0 @ load domain access register
- mcr p15, 0, r4, c2, c0, 0 @ load page table pointer
- b __turn_mmu_on
-ENDPROC(__enable_mmu)
-
-/*
- * Enable the MMU. This completely changes the structure of the visible
- * memory space. You will not be able to trace execution through this.
- * If you have an enquiry about this, *please* check the linux-arm-kernel
- * mailing list archives BEFORE sending another post to the list.
- *
- * r0 = cp#15 control register
- * r13 = *virtual* address to jump to upon completion
- *
- * other registers depend on the function called upon completion
- */
- .align 5
-__turn_mmu_on:
- mov r0, r0
- mcr p15, 0, r0, c1, c0, 0 @ write control reg
- mrc p15, 0, r3, c0, c0, 0 @ read id reg
- mov r3, r3
- mov r3, r13
- mov pc, r3
-ENDPROC(__turn_mmu_on)
-
+ .ltorg
/*
* Setup the initial page tables. We only setup the barest
@@ -213,7 +122,7 @@ ENDPROC(__turn_mmu_on)
* r10 = procinfo
*
* Returns:
- * r0, r3, r6, r7 corrupted
+ * r0, r3, r5-r7 corrupted
* r4 = physical page table address
*/
__create_page_tables:
@@ -235,20 +144,30 @@ __create_page_tables:
ldr r7, [r10, #PROCINFO_MM_MMUFLAGS] @ mm_mmuflags
/*
- * Create identity mapping for first MB of kernel to
- * cater for the MMU enable. This identity mapping
- * will be removed by paging_init(). We use our current program
- * counter to determine corresponding section base address.
+ * Create identity mapping to cater for __enable_mmu.
+ * This identity mapping will be removed by paging_init().
*/
- mov r6, pc
- mov r6, r6, lsr #20 @ start of kernel section
- orr r3, r7, r6, lsl #20 @ flags + kernel base
- str r3, [r4, r6, lsl #2] @ identity mapping
+ adr r0, __enable_mmu_loc
+ ldmia r0, {r3, r5, r6}
+ sub r0, r0, r3 @ virt->phys offset
+ add r5, r5, r0 @ phys __enable_mmu
+ add r6, r6, r0 @ phys __enable_mmu_end
+ mov r5, r5, lsr #20
+ mov r6, r6, lsr #20
+
+1: orr r3, r7, r5, lsl #20 @ flags + kernel base
+ str r3, [r4, r5, lsl #2] @ identity mapping
+ teq r5, r6
+ addne r5, r5, #1 @ next section
+ bne 1b
/*
* Now setup the pagetables for our kernel direct
* mapped region.
*/
+ mov r3, pc
+ mov r3, r3, lsr #20
+ orr r3, r7, r3, lsl #20
add r0, r4, #(KERNEL_START & 0xff000000) >> 18
str r3, [r0, #(KERNEL_START & 0x00f00000) >> 18]!
ldr r6, =(KERNEL_END - 1)
@@ -289,24 +208,35 @@ __create_page_tables:
str r6, [r0]
#ifdef CONFIG_DEBUG_LL
- ldr r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags
+#ifndef CONFIG_DEBUG_ICEDCC
/*
* Map in IO space for serial debugging.
* This allows debug messages to be output
* via a serial console before paging_init.
*/
- ldr r3, [r8, #MACHINFO_PGOFFIO]
+ addruart r7, r3
+
+ mov r3, r3, lsr #20
+ mov r3, r3, lsl #2
+
add r0, r4, r3
rsb r3, r3, #0x4000 @ PTRS_PER_PGD*sizeof(long)
cmp r3, #0x0800 @ limit to 512MB
movhi r3, #0x0800
add r6, r0, r3
- ldr r3, [r8, #MACHINFO_PHYSIO]
- orr r3, r3, r7
+ mov r3, r7, lsr #20
+ ldr r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags
+ orr r3, r7, r3, lsl #20
1: str r3, [r0], #4
add r3, r3, #1 << 20
teq r0, r6
bne 1b
+
+#else /* CONFIG_DEBUG_ICEDCC */
+ /* we don't need any serial debugging mappings for ICEDCC */
+ ldr r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags
+#endif /* !CONFIG_DEBUG_ICEDCC */
+
#if defined(CONFIG_ARCH_NETWINDER) || defined(CONFIG_ARCH_CATS)
/*
* If we're using the NetWinder or CATS, we also need to map
@@ -332,5 +262,168 @@ __create_page_tables:
mov pc, lr
ENDPROC(__create_page_tables)
.ltorg
+__enable_mmu_loc:
+ .long .
+ .long __enable_mmu
+ .long __enable_mmu_end
+
+#if defined(CONFIG_SMP)
+ __CPUINIT
+ENTRY(secondary_startup)
+ /*
+ * Common entry point for secondary CPUs.
+ *
+ * Ensure that we're in SVC mode, and IRQs are disabled. Lookup
+ * the processor type - there is no need to check the machine type
+ * as it has already been validated by the primary processor.
+ */
+ setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9
+ mrc p15, 0, r9, c0, c0 @ get processor id
+ bl __lookup_processor_type
+ movs r10, r5 @ invalid processor?
+ moveq r0, #'p' @ yes, error 'p'
+ beq __error_p
+
+ /*
+ * Use the page tables supplied from __cpu_up.
+ */
+ adr r4, __secondary_data
+ ldmia r4, {r5, r7, r12} @ address to jump to after
+ sub r4, r4, r5 @ mmu has been enabled
+ ldr r4, [r7, r4] @ get secondary_data.pgdir
+ adr lr, BSYM(__enable_mmu) @ return address
+ mov r13, r12 @ __secondary_switched address
+ ARM( add pc, r10, #PROCINFO_INITFUNC ) @ initialise processor
+ @ (return control reg)
+ THUMB( add r12, r10, #PROCINFO_INITFUNC )
+ THUMB( mov pc, r12 )
+ENDPROC(secondary_startup)
+
+ /*
+ * r6 = &secondary_data
+ */
+ENTRY(__secondary_switched)
+ ldr sp, [r7, #4] @ get secondary_data.stack
+ mov fp, #0
+ b secondary_start_kernel
+ENDPROC(__secondary_switched)
+
+ .type __secondary_data, %object
+__secondary_data:
+ .long .
+ .long secondary_data
+ .long __secondary_switched
+#endif /* defined(CONFIG_SMP) */
+
+
+
+/*
+ * Setup common bits before finally enabling the MMU. Essentially
+ * this is just loading the page table pointer and domain access
+ * registers.
+ *
+ * r0 = cp#15 control register
+ * r1 = machine ID
+ * r2 = atags pointer
+ * r4 = page table pointer
+ * r9 = processor ID
+ * r13 = *virtual* address to jump to upon completion
+ */
+__enable_mmu:
+#ifdef CONFIG_ALIGNMENT_TRAP
+ orr r0, r0, #CR_A
+#else
+ bic r0, r0, #CR_A
+#endif
+#ifdef CONFIG_CPU_DCACHE_DISABLE
+ bic r0, r0, #CR_C
+#endif
+#ifdef CONFIG_CPU_BPREDICT_DISABLE
+ bic r0, r0, #CR_Z
+#endif
+#ifdef CONFIG_CPU_ICACHE_DISABLE
+ bic r0, r0, #CR_I
+#endif
+ mov r5, #(domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \
+ domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \
+ domain_val(DOMAIN_TABLE, DOMAIN_MANAGER) | \
+ domain_val(DOMAIN_IO, DOMAIN_CLIENT))
+ mcr p15, 0, r5, c3, c0, 0 @ load domain access register
+ mcr p15, 0, r4, c2, c0, 0 @ load page table pointer
+ b __turn_mmu_on
+ENDPROC(__enable_mmu)
+
+/*
+ * Enable the MMU. This completely changes the structure of the visible
+ * memory space. You will not be able to trace execution through this.
+ * If you have an enquiry about this, *please* check the linux-arm-kernel
+ * mailing list archives BEFORE sending another post to the list.
+ *
+ * r0 = cp#15 control register
+ * r1 = machine ID
+ * r2 = atags pointer
+ * r9 = processor ID
+ * r13 = *virtual* address to jump to upon completion
+ *
+ * other registers depend on the function called upon completion
+ */
+ .align 5
+__turn_mmu_on:
+ mov r0, r0
+ mcr p15, 0, r0, c1, c0, 0 @ write control reg
+ mrc p15, 0, r3, c0, c0, 0 @ read id reg
+ mov r3, r3
+ mov r3, r13
+ mov pc, r3
+__enable_mmu_end:
+ENDPROC(__turn_mmu_on)
+
+
+#ifdef CONFIG_SMP_ON_UP
+__fixup_smp:
+ mov r7, #0x00070000
+ orr r6, r7, #0xff000000 @ mask 0xff070000
+ orr r7, r7, #0x41000000 @ val 0x41070000
+ and r0, r9, r6
+ teq r0, r7 @ ARM CPU and ARMv6/v7?
+ bne __fixup_smp_on_up @ no, assume UP
+
+ orr r6, r6, #0x0000ff00
+ orr r6, r6, #0x000000f0 @ mask 0xff07fff0
+ orr r7, r7, #0x0000b000
+ orr r7, r7, #0x00000020 @ val 0x4107b020
+ and r0, r9, r6
+ teq r0, r7 @ ARM 11MPCore?
+ moveq pc, lr @ yes, assume SMP
+
+ mrc p15, 0, r0, c0, c0, 5 @ read MPIDR
+ tst r0, #1 << 31
+ movne pc, lr @ bit 31 => SMP
+
+__fixup_smp_on_up:
+ adr r0, 1f
+ ldmia r0, {r3, r6, r7}
+ sub r3, r0, r3
+ add r6, r6, r3
+ add r7, r7, r3
+2: cmp r6, r7
+ ldmia r6!, {r0, r4}
+ strlo r4, [r0, r3]
+ blo 2b
+ mov pc, lr
+ENDPROC(__fixup_smp)
+
+1: .word .
+ .word __smpalt_begin
+ .word __smpalt_end
+
+ .pushsection .data
+ .globl smp_on_up
+smp_on_up:
+ ALT_SMP(.long 1)
+ ALT_UP(.long 0)
+ .popsection
+
+#endif
#include "head-common.S"
diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c
new file mode 100644
index 000000000000..54593b0c241b
--- /dev/null
+++ b/arch/arm/kernel/hw_breakpoint.c
@@ -0,0 +1,849 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) 2009, 2010 ARM Limited
+ *
+ * Author: Will Deacon <will.deacon@arm.com>
+ */
+
+/*
+ * HW_breakpoint: a unified kernel/user-space hardware breakpoint facility,
+ * using the CPU's debug registers.
+ */
+#define pr_fmt(fmt) "hw-breakpoint: " fmt
+
+#include <linux/errno.h>
+#include <linux/perf_event.h>
+#include <linux/hw_breakpoint.h>
+#include <linux/smp.h>
+
+#include <asm/cacheflush.h>
+#include <asm/cputype.h>
+#include <asm/current.h>
+#include <asm/hw_breakpoint.h>
+#include <asm/kdebug.h>
+#include <asm/system.h>
+#include <asm/traps.h>
+
+/* Breakpoint currently in use for each BRP. */
+static DEFINE_PER_CPU(struct perf_event *, bp_on_reg[ARM_MAX_BRP]);
+
+/* Watchpoint currently in use for each WRP. */
+static DEFINE_PER_CPU(struct perf_event *, wp_on_reg[ARM_MAX_WRP]);
+
+/* Number of BRP/WRP registers on this CPU. */
+static int core_num_brps;
+static int core_num_wrps;
+
+/* Debug architecture version. */
+static u8 debug_arch;
+
+/* Maximum supported watchpoint length. */
+static u8 max_watchpoint_len;
+
+/* Determine number of BRP registers available. */
+static int get_num_brps(void)
+{
+ u32 didr;
+ ARM_DBG_READ(c0, 0, didr);
+ return ((didr >> 24) & 0xf) + 1;
+}
+
+/* Determine number of WRP registers available. */
+static int get_num_wrps(void)
+{
+ /*
+ * FIXME: When a watchpoint fires, the only way to work out which
+ * watchpoint it was is by disassembling the faulting instruction
+ * and working out the address of the memory access.
+ *
+ * Furthermore, we can only do this if the watchpoint was precise
+ * since imprecise watchpoints prevent us from calculating register
+ * based addresses.
+ *
+ * For the time being, we only report 1 watchpoint register so we
+ * always know which watchpoint fired. In the future we can either
+ * add a disassembler and address generation emulator, or we can
+ * insert a check to see if the DFAR is set on watchpoint exception
+ * entry [the ARM ARM states that the DFAR is UNKNOWN, but
+ * experience shows that it is set on some implementations].
+ */
+
+#if 0
+ u32 didr, wrps;
+ ARM_DBG_READ(c0, 0, didr);
+ return ((didr >> 28) & 0xf) + 1;
+#endif
+
+ return 1;
+}
+
+int hw_breakpoint_slots(int type)
+{
+ /*
+ * We can be called early, so don't rely on
+ * our static variables being initialised.
+ */
+ switch (type) {
+ case TYPE_INST:
+ return get_num_brps();
+ case TYPE_DATA:
+ return get_num_wrps();
+ default:
+ pr_warning("unknown slot type: %d\n", type);
+ return 0;
+ }
+}
+
+/* Determine debug architecture. */
+static u8 get_debug_arch(void)
+{
+ u32 didr;
+
+ /* Do we implement the extended CPUID interface? */
+ if (((read_cpuid_id() >> 16) & 0xf) != 0xf) {
+ pr_warning("CPUID feature registers not supported. "
+ "Assuming v6 debug is present.\n");
+ return ARM_DEBUG_ARCH_V6;
+ }
+
+ ARM_DBG_READ(c0, 0, didr);
+ return (didr >> 16) & 0xf;
+}
+
+/* Does this core support mismatch breakpoints? */
+static int core_has_mismatch_bps(void)
+{
+ return debug_arch >= ARM_DEBUG_ARCH_V7_ECP14 && core_num_brps > 1;
+}
+
+u8 arch_get_debug_arch(void)
+{
+ return debug_arch;
+}
+
+#define READ_WB_REG_CASE(OP2, M, VAL) \
+ case ((OP2 << 4) + M): \
+ ARM_DBG_READ(c ## M, OP2, VAL); \
+ break
+
+#define WRITE_WB_REG_CASE(OP2, M, VAL) \
+ case ((OP2 << 4) + M): \
+ ARM_DBG_WRITE(c ## M, OP2, VAL);\
+ break
+
+#define GEN_READ_WB_REG_CASES(OP2, VAL) \
+ READ_WB_REG_CASE(OP2, 0, VAL); \
+ READ_WB_REG_CASE(OP2, 1, VAL); \
+ READ_WB_REG_CASE(OP2, 2, VAL); \
+ READ_WB_REG_CASE(OP2, 3, VAL); \
+ READ_WB_REG_CASE(OP2, 4, VAL); \
+ READ_WB_REG_CASE(OP2, 5, VAL); \
+ READ_WB_REG_CASE(OP2, 6, VAL); \
+ READ_WB_REG_CASE(OP2, 7, VAL); \
+ READ_WB_REG_CASE(OP2, 8, VAL); \
+ READ_WB_REG_CASE(OP2, 9, VAL); \
+ READ_WB_REG_CASE(OP2, 10, VAL); \
+ READ_WB_REG_CASE(OP2, 11, VAL); \
+ READ_WB_REG_CASE(OP2, 12, VAL); \
+ READ_WB_REG_CASE(OP2, 13, VAL); \
+ READ_WB_REG_CASE(OP2, 14, VAL); \
+ READ_WB_REG_CASE(OP2, 15, VAL)
+
+#define GEN_WRITE_WB_REG_CASES(OP2, VAL) \
+ WRITE_WB_REG_CASE(OP2, 0, VAL); \
+ WRITE_WB_REG_CASE(OP2, 1, VAL); \
+ WRITE_WB_REG_CASE(OP2, 2, VAL); \
+ WRITE_WB_REG_CASE(OP2, 3, VAL); \
+ WRITE_WB_REG_CASE(OP2, 4, VAL); \
+ WRITE_WB_REG_CASE(OP2, 5, VAL); \
+ WRITE_WB_REG_CASE(OP2, 6, VAL); \
+ WRITE_WB_REG_CASE(OP2, 7, VAL); \
+ WRITE_WB_REG_CASE(OP2, 8, VAL); \
+ WRITE_WB_REG_CASE(OP2, 9, VAL); \
+ WRITE_WB_REG_CASE(OP2, 10, VAL); \
+ WRITE_WB_REG_CASE(OP2, 11, VAL); \
+ WRITE_WB_REG_CASE(OP2, 12, VAL); \
+ WRITE_WB_REG_CASE(OP2, 13, VAL); \
+ WRITE_WB_REG_CASE(OP2, 14, VAL); \
+ WRITE_WB_REG_CASE(OP2, 15, VAL)
+
+static u32 read_wb_reg(int n)
+{
+ u32 val = 0;
+
+ switch (n) {
+ GEN_READ_WB_REG_CASES(ARM_OP2_BVR, val);
+ GEN_READ_WB_REG_CASES(ARM_OP2_BCR, val);
+ GEN_READ_WB_REG_CASES(ARM_OP2_WVR, val);
+ GEN_READ_WB_REG_CASES(ARM_OP2_WCR, val);
+ default:
+ pr_warning("attempt to read from unknown breakpoint "
+ "register %d\n", n);
+ }
+
+ return val;
+}
+
+static void write_wb_reg(int n, u32 val)
+{
+ switch (n) {
+ GEN_WRITE_WB_REG_CASES(ARM_OP2_BVR, val);
+ GEN_WRITE_WB_REG_CASES(ARM_OP2_BCR, val);
+ GEN_WRITE_WB_REG_CASES(ARM_OP2_WVR, val);
+ GEN_WRITE_WB_REG_CASES(ARM_OP2_WCR, val);
+ default:
+ pr_warning("attempt to write to unknown breakpoint "
+ "register %d\n", n);
+ }
+ isb();
+}
+
+/*
+ * In order to access the breakpoint/watchpoint control registers,
+ * we must be running in debug monitor mode. Unfortunately, we can
+ * be put into halting debug mode at any time by an external debugger
+ * but there is nothing we can do to prevent that.
+ */
+static int enable_monitor_mode(void)
+{
+ u32 dscr;
+ int ret = 0;
+
+ ARM_DBG_READ(c1, 0, dscr);
+
+ /* Ensure that halting mode is disabled. */
+ if (WARN_ONCE(dscr & ARM_DSCR_HDBGEN, "halting debug mode enabled."
+ "Unable to access hardware resources.")) {
+ ret = -EPERM;
+ goto out;
+ }
+
+ /* Write to the corresponding DSCR. */
+ switch (debug_arch) {
+ case ARM_DEBUG_ARCH_V6:
+ case ARM_DEBUG_ARCH_V6_1:
+ ARM_DBG_WRITE(c1, 0, (dscr | ARM_DSCR_MDBGEN));
+ break;
+ case ARM_DEBUG_ARCH_V7_ECP14:
+ ARM_DBG_WRITE(c2, 2, (dscr | ARM_DSCR_MDBGEN));
+ break;
+ default:
+ ret = -ENODEV;
+ goto out;
+ }
+
+ /* Check that the write made it through. */
+ ARM_DBG_READ(c1, 0, dscr);
+ if (WARN_ONCE(!(dscr & ARM_DSCR_MDBGEN),
+ "failed to enable monitor mode.")) {
+ ret = -EPERM;
+ }
+
+out:
+ return ret;
+}
+
+/*
+ * Check if 8-bit byte-address select is available.
+ * This clobbers WRP 0.
+ */
+static u8 get_max_wp_len(void)
+{
+ u32 ctrl_reg;
+ struct arch_hw_breakpoint_ctrl ctrl;
+ u8 size = 4;
+
+ if (debug_arch < ARM_DEBUG_ARCH_V7_ECP14)
+ goto out;
+
+ if (enable_monitor_mode())
+ goto out;
+
+ memset(&ctrl, 0, sizeof(ctrl));
+ ctrl.len = ARM_BREAKPOINT_LEN_8;
+ ctrl_reg = encode_ctrl_reg(ctrl);
+
+ write_wb_reg(ARM_BASE_WVR, 0);
+ write_wb_reg(ARM_BASE_WCR, ctrl_reg);
+ if ((read_wb_reg(ARM_BASE_WCR) & ctrl_reg) == ctrl_reg)
+ size = 8;
+
+out:
+ return size;
+}
+
+u8 arch_get_max_wp_len(void)
+{
+ return max_watchpoint_len;
+}
+
+/*
+ * Handler for reactivating a suspended watchpoint when the single
+ * step `mismatch' breakpoint is triggered.
+ */
+static void wp_single_step_handler(struct perf_event *bp, int unused,
+ struct perf_sample_data *data,
+ struct pt_regs *regs)
+{
+ perf_event_enable(counter_arch_bp(bp)->suspended_wp);
+ unregister_hw_breakpoint(bp);
+}
+
+static int bp_is_single_step(struct perf_event *bp)
+{
+ return bp->overflow_handler == wp_single_step_handler;
+}
+
+/*
+ * Install a perf counter breakpoint.
+ */
+int arch_install_hw_breakpoint(struct perf_event *bp)
+{
+ struct arch_hw_breakpoint *info = counter_arch_bp(bp);
+ struct perf_event **slot, **slots;
+ int i, max_slots, ctrl_base, val_base, ret = 0;
+
+ /* Ensure that we are in monitor mode and halting mode is disabled. */
+ ret = enable_monitor_mode();
+ if (ret)
+ goto out;
+
+ if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) {
+ /* Breakpoint */
+ ctrl_base = ARM_BASE_BCR;
+ val_base = ARM_BASE_BVR;
+ slots = __get_cpu_var(bp_on_reg);
+ max_slots = core_num_brps - 1;
+
+ if (bp_is_single_step(bp)) {
+ info->ctrl.mismatch = 1;
+ i = max_slots;
+ slots[i] = bp;
+ goto setup;
+ }
+ } else {
+ /* Watchpoint */
+ ctrl_base = ARM_BASE_WCR;
+ val_base = ARM_BASE_WVR;
+ slots = __get_cpu_var(wp_on_reg);
+ max_slots = core_num_wrps;
+ }
+
+ for (i = 0; i < max_slots; ++i) {
+ slot = &slots[i];
+
+ if (!*slot) {
+ *slot = bp;
+ break;
+ }
+ }
+
+ if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot")) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+setup:
+ /* Setup the address register. */
+ write_wb_reg(val_base + i, info->address);
+
+ /* Setup the control register. */
+ write_wb_reg(ctrl_base + i, encode_ctrl_reg(info->ctrl) | 0x1);
+
+out:
+ return ret;
+}
+
+void arch_uninstall_hw_breakpoint(struct perf_event *bp)
+{
+ struct arch_hw_breakpoint *info = counter_arch_bp(bp);
+ struct perf_event **slot, **slots;
+ int i, max_slots, base;
+
+ if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) {
+ /* Breakpoint */
+ base = ARM_BASE_BCR;
+ slots = __get_cpu_var(bp_on_reg);
+ max_slots = core_num_brps - 1;
+
+ if (bp_is_single_step(bp)) {
+ i = max_slots;
+ slots[i] = NULL;
+ goto reset;
+ }
+ } else {
+ /* Watchpoint */
+ base = ARM_BASE_WCR;
+ slots = __get_cpu_var(wp_on_reg);
+ max_slots = core_num_wrps;
+ }
+
+ /* Remove the breakpoint. */
+ for (i = 0; i < max_slots; ++i) {
+ slot = &slots[i];
+
+ if (*slot == bp) {
+ *slot = NULL;
+ break;
+ }
+ }
+
+ if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot"))
+ return;
+
+reset:
+ /* Reset the control register. */
+ write_wb_reg(base + i, 0);
+}
+
+static int get_hbp_len(u8 hbp_len)
+{
+ unsigned int len_in_bytes = 0;
+
+ switch (hbp_len) {
+ case ARM_BREAKPOINT_LEN_1:
+ len_in_bytes = 1;
+ break;
+ case ARM_BREAKPOINT_LEN_2:
+ len_in_bytes = 2;
+ break;
+ case ARM_BREAKPOINT_LEN_4:
+ len_in_bytes = 4;
+ break;
+ case ARM_BREAKPOINT_LEN_8:
+ len_in_bytes = 8;
+ break;
+ }
+
+ return len_in_bytes;
+}
+
+/*
+ * Check whether bp virtual address is in kernel space.
+ */
+int arch_check_bp_in_kernelspace(struct perf_event *bp)
+{
+ unsigned int len;
+ unsigned long va;
+ struct arch_hw_breakpoint *info = counter_arch_bp(bp);
+
+ va = info->address;
+ len = get_hbp_len(info->ctrl.len);
+
+ return (va >= TASK_SIZE) && ((va + len - 1) >= TASK_SIZE);
+}
+
+/*
+ * Extract generic type and length encodings from an arch_hw_breakpoint_ctrl.
+ * Hopefully this will disappear when ptrace can bypass the conversion
+ * to generic breakpoint descriptions.
+ */
+int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl,
+ int *gen_len, int *gen_type)
+{
+ /* Type */
+ switch (ctrl.type) {
+ case ARM_BREAKPOINT_EXECUTE:
+ *gen_type = HW_BREAKPOINT_X;
+ break;
+ case ARM_BREAKPOINT_LOAD:
+ *gen_type = HW_BREAKPOINT_R;
+ break;
+ case ARM_BREAKPOINT_STORE:
+ *gen_type = HW_BREAKPOINT_W;
+ break;
+ case ARM_BREAKPOINT_LOAD | ARM_BREAKPOINT_STORE:
+ *gen_type = HW_BREAKPOINT_RW;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Len */
+ switch (ctrl.len) {
+ case ARM_BREAKPOINT_LEN_1:
+ *gen_len = HW_BREAKPOINT_LEN_1;
+ break;
+ case ARM_BREAKPOINT_LEN_2:
+ *gen_len = HW_BREAKPOINT_LEN_2;
+ break;
+ case ARM_BREAKPOINT_LEN_4:
+ *gen_len = HW_BREAKPOINT_LEN_4;
+ break;
+ case ARM_BREAKPOINT_LEN_8:
+ *gen_len = HW_BREAKPOINT_LEN_8;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/*
+ * Construct an arch_hw_breakpoint from a perf_event.
+ */
+static int arch_build_bp_info(struct perf_event *bp)
+{
+ struct arch_hw_breakpoint *info = counter_arch_bp(bp);
+
+ /* Type */
+ switch (bp->attr.bp_type) {
+ case HW_BREAKPOINT_X:
+ info->ctrl.type = ARM_BREAKPOINT_EXECUTE;
+ break;
+ case HW_BREAKPOINT_R:
+ info->ctrl.type = ARM_BREAKPOINT_LOAD;
+ break;
+ case HW_BREAKPOINT_W:
+ info->ctrl.type = ARM_BREAKPOINT_STORE;
+ break;
+ case HW_BREAKPOINT_RW:
+ info->ctrl.type = ARM_BREAKPOINT_LOAD | ARM_BREAKPOINT_STORE;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Len */
+ switch (bp->attr.bp_len) {
+ case HW_BREAKPOINT_LEN_1:
+ info->ctrl.len = ARM_BREAKPOINT_LEN_1;
+ break;
+ case HW_BREAKPOINT_LEN_2:
+ info->ctrl.len = ARM_BREAKPOINT_LEN_2;
+ break;
+ case HW_BREAKPOINT_LEN_4:
+ info->ctrl.len = ARM_BREAKPOINT_LEN_4;
+ break;
+ case HW_BREAKPOINT_LEN_8:
+ info->ctrl.len = ARM_BREAKPOINT_LEN_8;
+ if ((info->ctrl.type != ARM_BREAKPOINT_EXECUTE)
+ && max_watchpoint_len >= 8)
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Address */
+ info->address = bp->attr.bp_addr;
+
+ /* Privilege */
+ info->ctrl.privilege = ARM_BREAKPOINT_USER;
+ if (arch_check_bp_in_kernelspace(bp) && !bp_is_single_step(bp))
+ info->ctrl.privilege |= ARM_BREAKPOINT_PRIV;
+
+ /* Enabled? */
+ info->ctrl.enabled = !bp->attr.disabled;
+
+ /* Mismatch */
+ info->ctrl.mismatch = 0;
+
+ return 0;
+}
+
+/*
+ * Validate the arch-specific HW Breakpoint register settings.
+ */
+int arch_validate_hwbkpt_settings(struct perf_event *bp)
+{
+ struct arch_hw_breakpoint *info = counter_arch_bp(bp);
+ int ret = 0;
+ u32 bytelen, max_len, offset, alignment_mask = 0x3;
+
+ /* Build the arch_hw_breakpoint. */
+ ret = arch_build_bp_info(bp);
+ if (ret)
+ goto out;
+
+ /* Check address alignment. */
+ if (info->ctrl.len == ARM_BREAKPOINT_LEN_8)
+ alignment_mask = 0x7;
+ if (info->address & alignment_mask) {
+ /*
+ * Try to fix the alignment. This may result in a length
+ * that is too large, so we must check for that.
+ */
+ bytelen = get_hbp_len(info->ctrl.len);
+ max_len = info->ctrl.type == ARM_BREAKPOINT_EXECUTE ? 4 :
+ max_watchpoint_len;
+
+ if (max_len >= 8)
+ offset = info->address & 0x7;
+ else
+ offset = info->address & 0x3;
+
+ if (bytelen > (1 << ((max_len - (offset + 1)) >> 1))) {
+ ret = -EFBIG;
+ goto out;
+ }
+
+ info->ctrl.len <<= offset;
+ info->address &= ~offset;
+
+ pr_debug("breakpoint alignment fixup: length = 0x%x, "
+ "address = 0x%x\n", info->ctrl.len, info->address);
+ }
+
+ /*
+ * Currently we rely on an overflow handler to take
+ * care of single-stepping the breakpoint when it fires.
+ * In the case of userspace breakpoints on a core with V7 debug,
+ * we can use the mismatch feature as a poor-man's hardware single-step.
+ */
+ if (WARN_ONCE(!bp->overflow_handler &&
+ (arch_check_bp_in_kernelspace(bp) || !core_has_mismatch_bps()),
+ "overflow handler required but none found")) {
+ ret = -EINVAL;
+ goto out;
+ }
+out:
+ return ret;
+}
+
+static void update_mismatch_flag(int idx, int flag)
+{
+ struct perf_event *bp = __get_cpu_var(bp_on_reg[idx]);
+ struct arch_hw_breakpoint *info;
+
+ if (bp == NULL)
+ return;
+
+ info = counter_arch_bp(bp);
+
+ /* Update the mismatch field to enter/exit `single-step' mode */
+ if (!bp->overflow_handler && info->ctrl.mismatch != flag) {
+ info->ctrl.mismatch = flag;
+ write_wb_reg(ARM_BASE_BCR + idx, encode_ctrl_reg(info->ctrl) | 0x1);
+ }
+}
+
+static void watchpoint_handler(unsigned long unknown, struct pt_regs *regs)
+{
+ int i;
+ struct perf_event *bp, **slots = __get_cpu_var(wp_on_reg);
+ struct arch_hw_breakpoint *info;
+ struct perf_event_attr attr;
+
+ /* Without a disassembler, we can only handle 1 watchpoint. */
+ BUG_ON(core_num_wrps > 1);
+
+ hw_breakpoint_init(&attr);
+ attr.bp_addr = regs->ARM_pc & ~0x3;
+ attr.bp_len = HW_BREAKPOINT_LEN_4;
+ attr.bp_type = HW_BREAKPOINT_X;
+
+ for (i = 0; i < core_num_wrps; ++i) {
+ rcu_read_lock();
+
+ if (slots[i] == NULL) {
+ rcu_read_unlock();
+ continue;
+ }
+
+ /*
+ * The DFAR is an unknown value. Since we only allow a
+ * single watchpoint, we can set the trigger to the lowest
+ * possible faulting address.
+ */
+ info = counter_arch_bp(slots[i]);
+ info->trigger = slots[i]->attr.bp_addr;
+ pr_debug("watchpoint fired: address = 0x%x\n", info->trigger);
+ perf_bp_event(slots[i], regs);
+
+ /*
+ * If no overflow handler is present, insert a temporary
+ * mismatch breakpoint so we can single-step over the
+ * watchpoint trigger.
+ */
+ if (!slots[i]->overflow_handler) {
+ bp = register_user_hw_breakpoint(&attr,
+ wp_single_step_handler,
+ current);
+ counter_arch_bp(bp)->suspended_wp = slots[i];
+ perf_event_disable(slots[i]);
+ }
+
+ rcu_read_unlock();
+ }
+}
+
+static void breakpoint_handler(unsigned long unknown, struct pt_regs *regs)
+{
+ int i;
+ int mismatch;
+ u32 ctrl_reg, val, addr;
+ struct perf_event *bp, **slots = __get_cpu_var(bp_on_reg);
+ struct arch_hw_breakpoint *info;
+ struct arch_hw_breakpoint_ctrl ctrl;
+
+ /* The exception entry code places the amended lr in the PC. */
+ addr = regs->ARM_pc;
+
+ for (i = 0; i < core_num_brps; ++i) {
+ rcu_read_lock();
+
+ bp = slots[i];
+
+ if (bp == NULL) {
+ rcu_read_unlock();
+ continue;
+ }
+
+ mismatch = 0;
+
+ /* Check if the breakpoint value matches. */
+ val = read_wb_reg(ARM_BASE_BVR + i);
+ if (val != (addr & ~0x3))
+ goto unlock;
+
+ /* Possible match, check the byte address select to confirm. */
+ ctrl_reg = read_wb_reg(ARM_BASE_BCR + i);
+ decode_ctrl_reg(ctrl_reg, &ctrl);
+ if ((1 << (addr & 0x3)) & ctrl.len) {
+ mismatch = 1;
+ info = counter_arch_bp(bp);
+ info->trigger = addr;
+ }
+
+unlock:
+ if ((mismatch && !info->ctrl.mismatch) || bp_is_single_step(bp)) {
+ pr_debug("breakpoint fired: address = 0x%x\n", addr);
+ perf_bp_event(bp, regs);
+ }
+
+ update_mismatch_flag(i, mismatch);
+ rcu_read_unlock();
+ }
+}
+
+/*
+ * Called from either the Data Abort Handler [watchpoint] or the
+ * Prefetch Abort Handler [breakpoint].
+ */
+static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr,
+ struct pt_regs *regs)
+{
+ int ret = 1; /* Unhandled fault. */
+ u32 dscr;
+
+ /* We only handle watchpoints and hardware breakpoints. */
+ ARM_DBG_READ(c1, 0, dscr);
+
+ /* Perform perf callbacks. */
+ switch (ARM_DSCR_MOE(dscr)) {
+ case ARM_ENTRY_BREAKPOINT:
+ breakpoint_handler(addr, regs);
+ break;
+ case ARM_ENTRY_ASYNC_WATCHPOINT:
+ WARN_ON("Asynchronous watchpoint exception taken. "
+ "Debugging results may be unreliable");
+ case ARM_ENTRY_SYNC_WATCHPOINT:
+ watchpoint_handler(addr, regs);
+ break;
+ default:
+ goto out;
+ }
+
+ ret = 0;
+out:
+ return ret;
+}
+
+/*
+ * One-time initialisation.
+ */
+static void __init reset_ctrl_regs(void *unused)
+{
+ int i;
+
+ if (enable_monitor_mode())
+ return;
+
+ for (i = 0; i < core_num_brps; ++i) {
+ write_wb_reg(ARM_BASE_BCR + i, 0UL);
+ write_wb_reg(ARM_BASE_BVR + i, 0UL);
+ }
+
+ for (i = 0; i < core_num_wrps; ++i) {
+ write_wb_reg(ARM_BASE_WCR + i, 0UL);
+ write_wb_reg(ARM_BASE_WVR + i, 0UL);
+ }
+}
+
+static int __init arch_hw_breakpoint_init(void)
+{
+ int ret = 0;
+ u32 dscr;
+
+ debug_arch = get_debug_arch();
+
+ if (debug_arch > ARM_DEBUG_ARCH_V7_ECP14) {
+ pr_info("debug architecture 0x%x unsupported.\n", debug_arch);
+ ret = -ENODEV;
+ goto out;
+ }
+
+ /* Determine how many BRPs/WRPs are available. */
+ core_num_brps = get_num_brps();
+ core_num_wrps = get_num_wrps();
+
+ pr_info("found %d breakpoint and %d watchpoint registers.\n",
+ core_num_brps, core_num_wrps);
+
+ if (core_has_mismatch_bps())
+ pr_info("1 breakpoint reserved for watchpoint single-step.\n");
+
+ ARM_DBG_READ(c1, 0, dscr);
+ if (dscr & ARM_DSCR_HDBGEN) {
+ pr_warning("halting debug mode enabled. Assuming maximum "
+ "watchpoint size of 4 bytes.");
+ } else {
+ /* Work out the maximum supported watchpoint length. */
+ max_watchpoint_len = get_max_wp_len();
+ pr_info("maximum watchpoint size is %u bytes.\n",
+ max_watchpoint_len);
+
+ /*
+ * Reset the breakpoint resources. We assume that a halting
+ * debugger will leave the world in a nice state for us.
+ */
+ smp_call_function(reset_ctrl_regs, NULL, 1);
+ reset_ctrl_regs(NULL);
+ }
+
+ /* Register debug fault handler. */
+ hook_fault_code(2, hw_breakpoint_pending, SIGTRAP, TRAP_HWBKPT,
+ "watchpoint debug exception");
+ hook_ifault_code(2, hw_breakpoint_pending, SIGTRAP, TRAP_HWBKPT,
+ "breakpoint debug exception");
+
+out:
+ return ret;
+}
+arch_initcall(arch_hw_breakpoint_init);
+
+void hw_breakpoint_pmu_read(struct perf_event *bp)
+{
+}
+
+/*
+ * Dummy function to register with die_notifier.
+ */
+int hw_breakpoint_exceptions_notify(struct notifier_block *unused,
+ unsigned long val, void *data)
+{
+ return NOTIFY_DONE;
+}
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index c0d5c3b3a760..36ad3be4692a 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -154,14 +154,6 @@ void set_irq_flags(unsigned int irq, unsigned int iflags)
void __init init_IRQ(void)
{
- struct irq_desc *desc;
- int irq;
-
- for (irq = 0; irq < nr_irqs; irq++) {
- desc = irq_to_desc_alloc_node(irq, 0);
- desc->status |= IRQ_NOREQUEST | IRQ_NOPROBE;
- }
-
init_arch_irq();
}
@@ -169,7 +161,7 @@ void __init init_IRQ(void)
int __init arch_probe_nr_irqs(void)
{
nr_irqs = arch_nr_irqs ? arch_nr_irqs : NR_IRQS;
- return 0;
+ return nr_irqs;
}
#endif
diff --git a/arch/arm/kernel/kprobes-decode.c b/arch/arm/kernel/kprobes-decode.c
index 8bccbfa693ff..2c1f0050c9c4 100644
--- a/arch/arm/kernel/kprobes-decode.c
+++ b/arch/arm/kernel/kprobes-decode.c
@@ -1162,11 +1162,12 @@ space_cccc_001x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
{
/*
* MSR : cccc 0011 0x10 xxxx xxxx xxxx xxxx xxxx
- * Undef : cccc 0011 0x00 xxxx xxxx xxxx xxxx xxxx
+ * Undef : cccc 0011 0100 xxxx xxxx xxxx xxxx xxxx
* ALU op with S bit and Rd == 15 :
* cccc 001x xxx1 xxxx 1111 xxxx xxxx xxxx
*/
- if ((insn & 0x0f900000) == 0x03200000 || /* MSR & Undef */
+ if ((insn & 0x0fb00000) == 0x03200000 || /* MSR */
+ (insn & 0x0ff00000) == 0x03400000 || /* Undef */
(insn & 0x0e10f000) == 0x0210f000) /* ALU s-bit, R15 */
return INSN_REJECTED;
@@ -1177,7 +1178,7 @@ space_cccc_001x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
* *S (bit 20) updates condition codes
* ADC/SBC/RSC reads the C flag
*/
- insn &= 0xfff00fff; /* Rn = r0, Rd = r0 */
+ insn &= 0xffff0fff; /* Rd = r0 */
asi->insn[0] = insn;
asi->insn_handler = (insn & (1 << 20)) ? /* S-bit */
emulate_alu_imm_rwflags : emulate_alu_imm_rflags;
diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c
index 6b4605893f1e..d9bd786ce23d 100644
--- a/arch/arm/kernel/module.c
+++ b/arch/arm/kernel/module.c
@@ -69,20 +69,31 @@ int module_frob_arch_sections(Elf_Ehdr *hdr,
{
#ifdef CONFIG_ARM_UNWIND
Elf_Shdr *s, *sechdrs_end = sechdrs + hdr->e_shnum;
+ struct arm_unwind_mapping *maps = mod->arch.map;
for (s = sechdrs; s < sechdrs_end; s++) {
- if (strcmp(".ARM.exidx.init.text", secstrings + s->sh_name) == 0)
- mod->arch.unw_sec_init = s;
- else if (strcmp(".ARM.exidx.devinit.text", secstrings + s->sh_name) == 0)
- mod->arch.unw_sec_devinit = s;
- else if (strcmp(".ARM.exidx", secstrings + s->sh_name) == 0)
- mod->arch.unw_sec_core = s;
- else if (strcmp(".init.text", secstrings + s->sh_name) == 0)
- mod->arch.sec_init_text = s;
- else if (strcmp(".devinit.text", secstrings + s->sh_name) == 0)
- mod->arch.sec_devinit_text = s;
- else if (strcmp(".text", secstrings + s->sh_name) == 0)
- mod->arch.sec_core_text = s;
+ char const *secname = secstrings + s->sh_name;
+
+ if (strcmp(".ARM.exidx.init.text", secname) == 0)
+ maps[ARM_SEC_INIT].unw_sec = s;
+ else if (strcmp(".ARM.exidx.devinit.text", secname) == 0)
+ maps[ARM_SEC_DEVINIT].unw_sec = s;
+ else if (strcmp(".ARM.exidx", secname) == 0)
+ maps[ARM_SEC_CORE].unw_sec = s;
+ else if (strcmp(".ARM.exidx.exit.text", secname) == 0)
+ maps[ARM_SEC_EXIT].unw_sec = s;
+ else if (strcmp(".ARM.exidx.devexit.text", secname) == 0)
+ maps[ARM_SEC_DEVEXIT].unw_sec = s;
+ else if (strcmp(".init.text", secname) == 0)
+ maps[ARM_SEC_INIT].sec_text = s;
+ else if (strcmp(".devinit.text", secname) == 0)
+ maps[ARM_SEC_DEVINIT].sec_text = s;
+ else if (strcmp(".text", secname) == 0)
+ maps[ARM_SEC_CORE].sec_text = s;
+ else if (strcmp(".exit.text", secname) == 0)
+ maps[ARM_SEC_EXIT].sec_text = s;
+ else if (strcmp(".devexit.text", secname) == 0)
+ maps[ARM_SEC_DEVEXIT].sec_text = s;
}
#endif
return 0;
@@ -292,31 +303,22 @@ apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
#ifdef CONFIG_ARM_UNWIND
static void register_unwind_tables(struct module *mod)
{
- if (mod->arch.unw_sec_init && mod->arch.sec_init_text)
- mod->arch.unwind_init =
- unwind_table_add(mod->arch.unw_sec_init->sh_addr,
- mod->arch.unw_sec_init->sh_size,
- mod->arch.sec_init_text->sh_addr,
- mod->arch.sec_init_text->sh_size);
- if (mod->arch.unw_sec_devinit && mod->arch.sec_devinit_text)
- mod->arch.unwind_devinit =
- unwind_table_add(mod->arch.unw_sec_devinit->sh_addr,
- mod->arch.unw_sec_devinit->sh_size,
- mod->arch.sec_devinit_text->sh_addr,
- mod->arch.sec_devinit_text->sh_size);
- if (mod->arch.unw_sec_core && mod->arch.sec_core_text)
- mod->arch.unwind_core =
- unwind_table_add(mod->arch.unw_sec_core->sh_addr,
- mod->arch.unw_sec_core->sh_size,
- mod->arch.sec_core_text->sh_addr,
- mod->arch.sec_core_text->sh_size);
+ int i;
+ for (i = 0; i < ARM_SEC_MAX; ++i) {
+ struct arm_unwind_mapping *map = &mod->arch.map[i];
+ if (map->unw_sec && map->sec_text)
+ map->unwind = unwind_table_add(map->unw_sec->sh_addr,
+ map->unw_sec->sh_size,
+ map->sec_text->sh_addr,
+ map->sec_text->sh_size);
+ }
}
static void unregister_unwind_tables(struct module *mod)
{
- unwind_table_del(mod->arch.unwind_init);
- unwind_table_del(mod->arch.unwind_devinit);
- unwind_table_del(mod->arch.unwind_core);
+ int i = ARM_SEC_MAX;
+ while (--i >= 0)
+ unwind_table_del(mod->arch.map[i].unwind);
}
#else
static inline void register_unwind_tables(struct module *mod) { }
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index ecbb0288e5dd..49643b1467e6 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -123,6 +123,12 @@ armpmu_get_max_events(void)
}
EXPORT_SYMBOL_GPL(armpmu_get_max_events);
+int perf_num_counters(void)
+{
+ return armpmu_get_max_events();
+}
+EXPORT_SYMBOL_GPL(perf_num_counters);
+
#define HW_OP_UNSUPPORTED 0xFFFF
#define C(_x) \
@@ -221,46 +227,56 @@ again:
}
static void
-armpmu_disable(struct perf_event *event)
+armpmu_read(struct perf_event *event)
{
- struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
struct hw_perf_event *hwc = &event->hw;
- int idx = hwc->idx;
-
- WARN_ON(idx < 0);
-
- clear_bit(idx, cpuc->active_mask);
- armpmu->disable(hwc, idx);
-
- barrier();
- armpmu_event_update(event, hwc, idx);
- cpuc->events[idx] = NULL;
- clear_bit(idx, cpuc->used_mask);
+ /* Don't read disabled counters! */
+ if (hwc->idx < 0)
+ return;
- perf_event_update_userpage(event);
+ armpmu_event_update(event, hwc, hwc->idx);
}
static void
-armpmu_read(struct perf_event *event)
+armpmu_stop(struct perf_event *event, int flags)
{
struct hw_perf_event *hwc = &event->hw;
- /* Don't read disabled counters! */
- if (hwc->idx < 0)
+ if (!armpmu)
return;
- armpmu_event_update(event, hwc, hwc->idx);
+ /*
+ * ARM pmu always has to update the counter, so ignore
+ * PERF_EF_UPDATE, see comments in armpmu_start().
+ */
+ if (!(hwc->state & PERF_HES_STOPPED)) {
+ armpmu->disable(hwc, hwc->idx);
+ barrier(); /* why? */
+ armpmu_event_update(event, hwc, hwc->idx);
+ hwc->state |= PERF_HES_STOPPED | PERF_HES_UPTODATE;
+ }
}
static void
-armpmu_unthrottle(struct perf_event *event)
+armpmu_start(struct perf_event *event, int flags)
{
struct hw_perf_event *hwc = &event->hw;
+ if (!armpmu)
+ return;
+
+ /*
+ * ARM pmu always has to reprogram the period, so ignore
+ * PERF_EF_RELOAD, see the comment below.
+ */
+ if (flags & PERF_EF_RELOAD)
+ WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE));
+
+ hwc->state = 0;
/*
* Set the period again. Some counters can't be stopped, so when we
- * were throttled we simply disabled the IRQ source and the counter
+ * were stopped we simply disabled the IRQ source and the counter
* may have been left counting. If we don't do this step then we may
* get an interrupt too soon or *way* too late if the overflow has
* happened since disabling.
@@ -269,14 +285,33 @@ armpmu_unthrottle(struct perf_event *event)
armpmu->enable(hwc, hwc->idx);
}
+static void
+armpmu_del(struct perf_event *event, int flags)
+{
+ struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+ struct hw_perf_event *hwc = &event->hw;
+ int idx = hwc->idx;
+
+ WARN_ON(idx < 0);
+
+ clear_bit(idx, cpuc->active_mask);
+ armpmu_stop(event, PERF_EF_UPDATE);
+ cpuc->events[idx] = NULL;
+ clear_bit(idx, cpuc->used_mask);
+
+ perf_event_update_userpage(event);
+}
+
static int
-armpmu_enable(struct perf_event *event)
+armpmu_add(struct perf_event *event, int flags)
{
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
struct hw_perf_event *hwc = &event->hw;
int idx;
int err = 0;
+ perf_pmu_disable(event->pmu);
+
/* If we don't have a space for the counter then finish early. */
idx = armpmu->get_event_idx(cpuc, hwc);
if (idx < 0) {
@@ -293,25 +328,19 @@ armpmu_enable(struct perf_event *event)
cpuc->events[idx] = event;
set_bit(idx, cpuc->active_mask);
- /* Set the period for the event. */
- armpmu_event_set_period(event, hwc, idx);
-
- /* Enable the event. */
- armpmu->enable(hwc, idx);
+ hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE;
+ if (flags & PERF_EF_START)
+ armpmu_start(event, PERF_EF_RELOAD);
/* Propagate our changes to the userspace mapping. */
perf_event_update_userpage(event);
out:
+ perf_pmu_enable(event->pmu);
return err;
}
-static struct pmu pmu = {
- .enable = armpmu_enable,
- .disable = armpmu_disable,
- .unthrottle = armpmu_unthrottle,
- .read = armpmu_read,
-};
+static struct pmu pmu;
static int
validate_event(struct cpu_hw_events *cpuc,
@@ -491,20 +520,29 @@ __hw_perf_event_init(struct perf_event *event)
return err;
}
-const struct pmu *
-hw_perf_event_init(struct perf_event *event)
+static int armpmu_event_init(struct perf_event *event)
{
int err = 0;
+ switch (event->attr.type) {
+ case PERF_TYPE_RAW:
+ case PERF_TYPE_HARDWARE:
+ case PERF_TYPE_HW_CACHE:
+ break;
+
+ default:
+ return -ENOENT;
+ }
+
if (!armpmu)
- return ERR_PTR(-ENODEV);
+ return -ENODEV;
event->destroy = hw_perf_event_destroy;
if (!atomic_inc_not_zero(&active_events)) {
- if (atomic_read(&active_events) > perf_max_events) {
+ if (atomic_read(&active_events) > armpmu->num_events) {
atomic_dec(&active_events);
- return ERR_PTR(-ENOSPC);
+ return -ENOSPC;
}
mutex_lock(&pmu_reserve_mutex);
@@ -518,17 +556,16 @@ hw_perf_event_init(struct perf_event *event)
}
if (err)
- return ERR_PTR(err);
+ return err;
err = __hw_perf_event_init(event);
if (err)
hw_perf_event_destroy(event);
- return err ? ERR_PTR(err) : &pmu;
+ return err;
}
-void
-hw_perf_enable(void)
+static void armpmu_enable(struct pmu *pmu)
{
/* Enable all of the perf events on hardware. */
int idx;
@@ -549,13 +586,23 @@ hw_perf_enable(void)
armpmu->start();
}
-void
-hw_perf_disable(void)
+static void armpmu_disable(struct pmu *pmu)
{
if (armpmu)
armpmu->stop();
}
+static struct pmu pmu = {
+ .pmu_enable = armpmu_enable,
+ .pmu_disable = armpmu_disable,
+ .event_init = armpmu_event_init,
+ .add = armpmu_add,
+ .del = armpmu_del,
+ .start = armpmu_start,
+ .stop = armpmu_stop,
+ .read = armpmu_read,
+};
+
/*
* ARMv6 Performance counter handling code.
*
@@ -1045,7 +1092,7 @@ armv6pmu_handle_irq(int irq_num,
* platforms that can have the PMU interrupts raised as an NMI, this
* will not work.
*/
- perf_event_do_pending();
+ irq_work_run();
return IRQ_HANDLED;
}
@@ -2021,7 +2068,7 @@ static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev)
* platforms that can have the PMU interrupts raised as an NMI, this
* will not work.
*/
- perf_event_do_pending();
+ irq_work_run();
return IRQ_HANDLED;
}
@@ -2389,7 +2436,7 @@ xscale1pmu_handle_irq(int irq_num, void *dev)
armpmu->disable(hwc, idx);
}
- perf_event_do_pending();
+ irq_work_run();
/*
* Re-enable the PMU.
@@ -2716,7 +2763,7 @@ xscale2pmu_handle_irq(int irq_num, void *dev)
armpmu->disable(hwc, idx);
}
- perf_event_do_pending();
+ irq_work_run();
/*
* Re-enable the PMU.
@@ -2933,14 +2980,12 @@ init_hw_perf_events(void)
armpmu = &armv6pmu;
memcpy(armpmu_perf_cache_map, armv6_perf_cache_map,
sizeof(armv6_perf_cache_map));
- perf_max_events = armv6pmu.num_events;
break;
case 0xB020: /* ARM11mpcore */
armpmu = &armv6mpcore_pmu;
memcpy(armpmu_perf_cache_map,
armv6mpcore_perf_cache_map,
sizeof(armv6mpcore_perf_cache_map));
- perf_max_events = armv6mpcore_pmu.num_events;
break;
case 0xC080: /* Cortex-A8 */
armv7pmu.id = ARM_PERF_PMU_ID_CA8;
@@ -2952,7 +2997,6 @@ init_hw_perf_events(void)
/* Reset PMNC and read the nb of CNTx counters
supported */
armv7pmu.num_events = armv7_reset_read_pmnc();
- perf_max_events = armv7pmu.num_events;
break;
case 0xC090: /* Cortex-A9 */
armv7pmu.id = ARM_PERF_PMU_ID_CA9;
@@ -2964,7 +3008,6 @@ init_hw_perf_events(void)
/* Reset PMNC and read the nb of CNTx counters
supported */
armv7pmu.num_events = armv7_reset_read_pmnc();
- perf_max_events = armv7pmu.num_events;
break;
}
/* Intel CPUs [xscale]. */
@@ -2975,13 +3018,11 @@ init_hw_perf_events(void)
armpmu = &xscale1pmu;
memcpy(armpmu_perf_cache_map, xscale_perf_cache_map,
sizeof(xscale_perf_cache_map));
- perf_max_events = xscale1pmu.num_events;
break;
case 2:
armpmu = &xscale2pmu;
memcpy(armpmu_perf_cache_map, xscale_perf_cache_map,
sizeof(xscale_perf_cache_map));
- perf_max_events = xscale2pmu.num_events;
break;
}
}
@@ -2991,9 +3032,10 @@ init_hw_perf_events(void)
arm_pmu_names[armpmu->id], armpmu->num_events);
} else {
pr_info("no hardware support available\n");
- perf_max_events = -1;
}
+ perf_pmu_register(&pmu);
+
return 0;
}
arch_initcall(init_hw_perf_events);
@@ -3001,13 +3043,6 @@ arch_initcall(init_hw_perf_events);
/*
* Callchain handling code.
*/
-static inline void
-callchain_store(struct perf_callchain_entry *entry,
- u64 ip)
-{
- if (entry->nr < PERF_MAX_STACK_DEPTH)
- entry->ip[entry->nr++] = ip;
-}
/*
* The registers we're interested in are at the end of the variable
@@ -3039,7 +3074,7 @@ user_backtrace(struct frame_tail *tail,
if (__copy_from_user_inatomic(&buftail, tail, sizeof(buftail)))
return NULL;
- callchain_store(entry, buftail.lr);
+ perf_callchain_store(entry, buftail.lr);
/*
* Frame pointers should strictly progress back up the stack
@@ -3051,16 +3086,11 @@ user_backtrace(struct frame_tail *tail,
return buftail.fp - 1;
}
-static void
-perf_callchain_user(struct pt_regs *regs,
- struct perf_callchain_entry *entry)
+void
+perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
{
struct frame_tail *tail;
- callchain_store(entry, PERF_CONTEXT_USER);
-
- if (!user_mode(regs))
- regs = task_pt_regs(current);
tail = (struct frame_tail *)regs->ARM_fp - 1;
@@ -3078,56 +3108,18 @@ callchain_trace(struct stackframe *fr,
void *data)
{
struct perf_callchain_entry *entry = data;
- callchain_store(entry, fr->pc);
+ perf_callchain_store(entry, fr->pc);
return 0;
}
-static void
-perf_callchain_kernel(struct pt_regs *regs,
- struct perf_callchain_entry *entry)
+void
+perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs)
{
struct stackframe fr;
- callchain_store(entry, PERF_CONTEXT_KERNEL);
fr.fp = regs->ARM_fp;
fr.sp = regs->ARM_sp;
fr.lr = regs->ARM_lr;
fr.pc = regs->ARM_pc;
walk_stackframe(&fr, callchain_trace, entry);
}
-
-static void
-perf_do_callchain(struct pt_regs *regs,
- struct perf_callchain_entry *entry)
-{
- int is_user;
-
- if (!regs)
- return;
-
- is_user = user_mode(regs);
-
- if (!current || !current->pid)
- return;
-
- if (is_user && current->state != TASK_RUNNING)
- return;
-
- if (!is_user)
- perf_callchain_kernel(regs, entry);
-
- if (current->mm)
- perf_callchain_user(regs, entry);
-}
-
-static DEFINE_PER_CPU(struct perf_callchain_entry, pmc_irq_entry);
-
-struct perf_callchain_entry *
-perf_callchain(struct pt_regs *regs)
-{
- struct perf_callchain_entry *entry = &__get_cpu_var(pmc_irq_entry);
-
- entry->nr = 0;
- perf_do_callchain(regs, entry);
- return entry;
-}
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 401e38be1f78..e76fcaadce03 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -29,6 +29,7 @@
#include <linux/utsname.h>
#include <linux/uaccess.h>
#include <linux/random.h>
+#include <linux/hw_breakpoint.h>
#include <asm/cacheflush.h>
#include <asm/leds.h>
@@ -135,6 +136,25 @@ EXPORT_SYMBOL(pm_power_off);
void (*arm_pm_restart)(char str, const char *cmd) = arm_machine_restart;
EXPORT_SYMBOL_GPL(arm_pm_restart);
+static void do_nothing(void *unused)
+{
+}
+
+/*
+ * cpu_idle_wait - Used to ensure that all the CPUs discard old value of
+ * pm_idle and update to new pm_idle value. Required while changing pm_idle
+ * handler on SMP systems.
+ *
+ * Caller must have changed pm_idle to the new value before the call. Old
+ * pm_idle value will not be used by any CPU after the return of this function.
+ */
+void cpu_idle_wait(void)
+{
+ smp_mb();
+ /* kick all the CPUs so that they exit out of pm_idle */
+ smp_call_function(do_nothing, NULL, 1);
+}
+EXPORT_SYMBOL_GPL(cpu_idle_wait);
/*
* This is our default idle handler. We need to disable
@@ -317,6 +337,8 @@ void flush_thread(void)
struct thread_info *thread = current_thread_info();
struct task_struct *tsk = current;
+ flush_ptrace_hw_breakpoint(tsk);
+
memset(thread->used_cp, 0, sizeof(thread->used_cp));
memset(&tsk->thread.debug, 0, sizeof(struct debug_info));
memset(&thread->fpstate, 0, sizeof(union fp_state));
@@ -345,6 +367,8 @@ copy_thread(unsigned long clone_flags, unsigned long stack_start,
thread->cpu_context.sp = (unsigned long)childregs;
thread->cpu_context.pc = (unsigned long)ret_from_fork;
+ clear_ptrace_hw_breakpoint(p);
+
if (clone_flags & CLONE_SETTLS)
thread->tp_value = regs->ARM_r3;
@@ -458,3 +482,24 @@ unsigned long arch_randomize_brk(struct mm_struct *mm)
unsigned long range_end = mm->brk + 0x02000000;
return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
}
+
+/*
+ * The vectors page is always readable from user space for the
+ * atomic helpers and the signal restart code. Let's declare a mapping
+ * for it so it is visible through ptrace and /proc/<pid>/mem.
+ */
+
+int vectors_user_mapping(void)
+{
+ struct mm_struct *mm = current->mm;
+ return install_special_mapping(mm, 0xffff0000, PAGE_SIZE,
+ VM_READ | VM_EXEC |
+ VM_MAYREAD | VM_MAYEXEC |
+ VM_ALWAYSDUMP | VM_RESERVED,
+ NULL);
+}
+
+const char *arch_vma_name(struct vm_area_struct *vma)
+{
+ return (vma->vm_start == 0xffff0000) ? "[vectors]" : NULL;
+}
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index f99d489822d5..e0cb6370ed14 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -19,6 +19,8 @@
#include <linux/init.h>
#include <linux/signal.h>
#include <linux/uaccess.h>
+#include <linux/perf_event.h>
+#include <linux/hw_breakpoint.h>
#include <asm/pgtable.h>
#include <asm/system.h>
@@ -847,6 +849,232 @@ static int ptrace_setvfpregs(struct task_struct *tsk, void __user *data)
}
#endif
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+/*
+ * Convert a virtual register number into an index for a thread_info
+ * breakpoint array. Breakpoints are identified using positive numbers
+ * whilst watchpoints are negative. The registers are laid out as pairs
+ * of (address, control), each pair mapping to a unique hw_breakpoint struct.
+ * Register 0 is reserved for describing resource information.
+ */
+static int ptrace_hbp_num_to_idx(long num)
+{
+ if (num < 0)
+ num = (ARM_MAX_BRP << 1) - num;
+ return (num - 1) >> 1;
+}
+
+/*
+ * Returns the virtual register number for the address of the
+ * breakpoint at index idx.
+ */
+static long ptrace_hbp_idx_to_num(int idx)
+{
+ long mid = ARM_MAX_BRP << 1;
+ long num = (idx << 1) + 1;
+ return num > mid ? mid - num : num;
+}
+
+/*
+ * Handle hitting a HW-breakpoint.
+ */
+static void ptrace_hbptriggered(struct perf_event *bp, int unused,
+ struct perf_sample_data *data,
+ struct pt_regs *regs)
+{
+ struct arch_hw_breakpoint *bkpt = counter_arch_bp(bp);
+ long num;
+ int i;
+ siginfo_t info;
+
+ for (i = 0; i < ARM_MAX_HBP_SLOTS; ++i)
+ if (current->thread.debug.hbp[i] == bp)
+ break;
+
+ num = (i == ARM_MAX_HBP_SLOTS) ? 0 : ptrace_hbp_idx_to_num(i);
+
+ info.si_signo = SIGTRAP;
+ info.si_errno = (int)num;
+ info.si_code = TRAP_HWBKPT;
+ info.si_addr = (void __user *)(bkpt->trigger);
+
+ force_sig_info(SIGTRAP, &info, current);
+}
+
+/*
+ * Set ptrace breakpoint pointers to zero for this task.
+ * This is required in order to prevent child processes from unregistering
+ * breakpoints held by their parent.
+ */
+void clear_ptrace_hw_breakpoint(struct task_struct *tsk)
+{
+ memset(tsk->thread.debug.hbp, 0, sizeof(tsk->thread.debug.hbp));
+}
+
+/*
+ * Unregister breakpoints from this task and reset the pointers in
+ * the thread_struct.
+ */
+void flush_ptrace_hw_breakpoint(struct task_struct *tsk)
+{
+ int i;
+ struct thread_struct *t = &tsk->thread;
+
+ for (i = 0; i < ARM_MAX_HBP_SLOTS; i++) {
+ if (t->debug.hbp[i]) {
+ unregister_hw_breakpoint(t->debug.hbp[i]);
+ t->debug.hbp[i] = NULL;
+ }
+ }
+}
+
+static u32 ptrace_get_hbp_resource_info(void)
+{
+ u8 num_brps, num_wrps, debug_arch, wp_len;
+ u32 reg = 0;
+
+ num_brps = hw_breakpoint_slots(TYPE_INST);
+ num_wrps = hw_breakpoint_slots(TYPE_DATA);
+ debug_arch = arch_get_debug_arch();
+ wp_len = arch_get_max_wp_len();
+
+ reg |= debug_arch;
+ reg <<= 8;
+ reg |= wp_len;
+ reg <<= 8;
+ reg |= num_wrps;
+ reg <<= 8;
+ reg |= num_brps;
+
+ return reg;
+}
+
+static struct perf_event *ptrace_hbp_create(struct task_struct *tsk, int type)
+{
+ struct perf_event_attr attr;
+
+ ptrace_breakpoint_init(&attr);
+
+ /* Initialise fields to sane defaults. */
+ attr.bp_addr = 0;
+ attr.bp_len = HW_BREAKPOINT_LEN_4;
+ attr.bp_type = type;
+ attr.disabled = 1;
+
+ return register_user_hw_breakpoint(&attr, ptrace_hbptriggered, tsk);
+}
+
+static int ptrace_gethbpregs(struct task_struct *tsk, long num,
+ unsigned long __user *data)
+{
+ u32 reg;
+ int idx, ret = 0;
+ struct perf_event *bp;
+ struct arch_hw_breakpoint_ctrl arch_ctrl;
+
+ if (num == 0) {
+ reg = ptrace_get_hbp_resource_info();
+ } else {
+ idx = ptrace_hbp_num_to_idx(num);
+ if (idx < 0 || idx >= ARM_MAX_HBP_SLOTS) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ bp = tsk->thread.debug.hbp[idx];
+ if (!bp) {
+ reg = 0;
+ goto put;
+ }
+
+ arch_ctrl = counter_arch_bp(bp)->ctrl;
+
+ /*
+ * Fix up the len because we may have adjusted it
+ * to compensate for an unaligned address.
+ */
+ while (!(arch_ctrl.len & 0x1))
+ arch_ctrl.len >>= 1;
+
+ if (idx & 0x1)
+ reg = encode_ctrl_reg(arch_ctrl);
+ else
+ reg = bp->attr.bp_addr;
+ }
+
+put:
+ if (put_user(reg, data))
+ ret = -EFAULT;
+
+out:
+ return ret;
+}
+
+static int ptrace_sethbpregs(struct task_struct *tsk, long num,
+ unsigned long __user *data)
+{
+ int idx, gen_len, gen_type, implied_type, ret = 0;
+ u32 user_val;
+ struct perf_event *bp;
+ struct arch_hw_breakpoint_ctrl ctrl;
+ struct perf_event_attr attr;
+
+ if (num == 0)
+ goto out;
+ else if (num < 0)
+ implied_type = HW_BREAKPOINT_RW;
+ else
+ implied_type = HW_BREAKPOINT_X;
+
+ idx = ptrace_hbp_num_to_idx(num);
+ if (idx < 0 || idx >= ARM_MAX_HBP_SLOTS) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (get_user(user_val, data)) {
+ ret = -EFAULT;
+ goto out;
+ }
+
+ bp = tsk->thread.debug.hbp[idx];
+ if (!bp) {
+ bp = ptrace_hbp_create(tsk, implied_type);
+ if (IS_ERR(bp)) {
+ ret = PTR_ERR(bp);
+ goto out;
+ }
+ tsk->thread.debug.hbp[idx] = bp;
+ }
+
+ attr = bp->attr;
+
+ if (num & 0x1) {
+ /* Address */
+ attr.bp_addr = user_val;
+ } else {
+ /* Control */
+ decode_ctrl_reg(user_val, &ctrl);
+ ret = arch_bp_generic_fields(ctrl, &gen_len, &gen_type);
+ if (ret)
+ goto out;
+
+ if ((gen_type & implied_type) != gen_type) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ attr.bp_len = gen_len;
+ attr.bp_type = gen_type;
+ attr.disabled = !ctrl.enabled;
+ }
+
+ ret = modify_user_hw_breakpoint(bp, &attr);
+out:
+ return ret;
+}
+#endif
+
long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{
int ret;
@@ -916,6 +1144,17 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break;
#endif
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+ case PTRACE_GETHBPREGS:
+ ret = ptrace_gethbpregs(child, addr,
+ (unsigned long __user *)data);
+ break;
+ case PTRACE_SETHBPREGS:
+ ret = ptrace_sethbpregs(child, addr,
+ (unsigned long __user *)data);
+ break;
+#endif
+
default:
ret = ptrace_request(child, request, addr, data);
break;
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index d5231ae7355a..336f14e0e5c2 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -36,6 +36,7 @@
#include <asm/procinfo.h>
#include <asm/sections.h>
#include <asm/setup.h>
+#include <asm/smp_plat.h>
#include <asm/mach-types.h>
#include <asm/cacheflush.h>
#include <asm/cachetype.h>
@@ -238,6 +239,35 @@ int cpu_architecture(void)
return cpu_arch;
}
+static int cpu_has_aliasing_icache(unsigned int arch)
+{
+ int aliasing_icache;
+ unsigned int id_reg, num_sets, line_size;
+
+ /* arch specifies the register format */
+ switch (arch) {
+ case CPU_ARCH_ARMv7:
+ asm("mcr p15, 2, %0, c0, c0, 0 @ set CSSELR"
+ : /* No output operands */
+ : "r" (1));
+ isb();
+ asm("mrc p15, 1, %0, c0, c0, 0 @ read CCSIDR"
+ : "=r" (id_reg));
+ line_size = 4 << ((id_reg & 0x7) + 2);
+ num_sets = ((id_reg >> 13) & 0x7fff) + 1;
+ aliasing_icache = (line_size * num_sets) > PAGE_SIZE;
+ break;
+ case CPU_ARCH_ARMv6:
+ aliasing_icache = read_cpuid_cachetype() & (1 << 11);
+ break;
+ default:
+ /* I-cache aliases will be handled by D-cache aliasing code */
+ aliasing_icache = 0;
+ }
+
+ return aliasing_icache;
+}
+
static void __init cacheid_init(void)
{
unsigned int cachetype = read_cpuid_cachetype();
@@ -249,10 +279,15 @@ static void __init cacheid_init(void)
cacheid = CACHEID_VIPT_NONALIASING;
if ((cachetype & (3 << 14)) == 1 << 14)
cacheid |= CACHEID_ASID_TAGGED;
- } else if (cachetype & (1 << 23))
+ else if (cpu_has_aliasing_icache(CPU_ARCH_ARMv7))
+ cacheid |= CACHEID_VIPT_I_ALIASING;
+ } else if (cachetype & (1 << 23)) {
cacheid = CACHEID_VIPT_ALIASING;
- else
+ } else {
cacheid = CACHEID_VIPT_NONALIASING;
+ if (cpu_has_aliasing_icache(CPU_ARCH_ARMv6))
+ cacheid |= CACHEID_VIPT_I_ALIASING;
+ }
} else {
cacheid = CACHEID_VIVT;
}
@@ -263,7 +298,7 @@ static void __init cacheid_init(void)
cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown",
cache_is_vivt() ? "VIVT" :
icache_is_vivt_asid_tagged() ? "VIVT ASID tagged" :
- cache_is_vipt_aliasing() ? "VIPT aliasing" :
+ icache_is_vipt_aliasing() ? "VIPT aliasing" :
cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown");
}
@@ -490,7 +525,7 @@ request_standard_resources(struct meminfo *mi, struct machine_desc *mdesc)
kernel_code.start = virt_to_phys(_text);
kernel_code.end = virt_to_phys(_etext - 1);
- kernel_data.start = virt_to_phys(_data);
+ kernel_data.start = virt_to_phys(_sdata);
kernel_data.end = virt_to_phys(_end - 1);
for (i = 0; i < mi->nr_banks; i++) {
@@ -825,7 +860,8 @@ void __init setup_arch(char **cmdline_p)
request_standard_resources(&meminfo, mdesc);
#ifdef CONFIG_SMP
- smp_init_cpus();
+ if (is_smp())
+ smp_init_cpus();
#endif
reserve_crashkernel();
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 40dc74f2b27f..8c1959590252 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -33,6 +33,7 @@
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
#include <asm/processor.h>
+#include <asm/sections.h>
#include <asm/tlbflush.h>
#include <asm/ptrace.h>
#include <asm/localtimer.h>
@@ -67,12 +68,47 @@ enum ipi_msg_type {
IPI_CPU_STOP,
};
+static inline void identity_mapping_add(pgd_t *pgd, unsigned long start,
+ unsigned long end)
+{
+ unsigned long addr, prot;
+ pmd_t *pmd;
+
+ prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE;
+ if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale())
+ prot |= PMD_BIT4;
+
+ for (addr = start & PGDIR_MASK; addr < end;) {
+ pmd = pmd_offset(pgd + pgd_index(addr), addr);
+ pmd[0] = __pmd(addr | prot);
+ addr += SECTION_SIZE;
+ pmd[1] = __pmd(addr | prot);
+ addr += SECTION_SIZE;
+ flush_pmd_entry(pmd);
+ outer_clean_range(__pa(pmd), __pa(pmd + 1));
+ }
+}
+
+static inline void identity_mapping_del(pgd_t *pgd, unsigned long start,
+ unsigned long end)
+{
+ unsigned long addr;
+ pmd_t *pmd;
+
+ for (addr = start & PGDIR_MASK; addr < end; addr += PGDIR_SIZE) {
+ pmd = pmd_offset(pgd + pgd_index(addr), addr);
+ pmd[0] = __pmd(0);
+ pmd[1] = __pmd(0);
+ clean_pmd_entry(pmd);
+ outer_clean_range(__pa(pmd), __pa(pmd + 1));
+ }
+}
+
int __cpuinit __cpu_up(unsigned int cpu)
{
struct cpuinfo_arm *ci = &per_cpu(cpu_data, cpu);
struct task_struct *idle = ci->idle;
pgd_t *pgd;
- pmd_t *pmd;
int ret;
/*
@@ -101,11 +137,16 @@ int __cpuinit __cpu_up(unsigned int cpu)
* a 1:1 mapping for the physical address of the kernel.
*/
pgd = pgd_alloc(&init_mm);
- pmd = pmd_offset(pgd + pgd_index(PHYS_OFFSET), PHYS_OFFSET);
- *pmd = __pmd((PHYS_OFFSET & PGDIR_MASK) |
- PMD_TYPE_SECT | PMD_SECT_AP_WRITE);
- flush_pmd_entry(pmd);
- outer_clean_range(__pa(pmd), __pa(pmd + 1));
+ if (!pgd)
+ return -ENOMEM;
+
+ if (PHYS_OFFSET != PAGE_OFFSET) {
+#ifndef CONFIG_HOTPLUG_CPU
+ identity_mapping_add(pgd, __pa(__init_begin), __pa(__init_end));
+#endif
+ identity_mapping_add(pgd, __pa(_stext), __pa(_etext));
+ identity_mapping_add(pgd, __pa(_sdata), __pa(_edata));
+ }
/*
* We need to tell the secondary core where to find
@@ -143,8 +184,14 @@ int __cpuinit __cpu_up(unsigned int cpu)
secondary_data.stack = NULL;
secondary_data.pgdir = 0;
- *pmd = __pmd(0);
- clean_pmd_entry(pmd);
+ if (PHYS_OFFSET != PAGE_OFFSET) {
+#ifndef CONFIG_HOTPLUG_CPU
+ identity_mapping_del(pgd, __pa(__init_begin), __pa(__init_end));
+#endif
+ identity_mapping_del(pgd, __pa(_stext), __pa(_etext));
+ identity_mapping_del(pgd, __pa(_sdata), __pa(_edata));
+ }
+
pgd_free(&init_mm, pgd);
if (ret) {
@@ -567,7 +614,8 @@ void smp_send_stop(void)
{
cpumask_t mask = cpu_online_map;
cpu_clear(smp_processor_id(), mask);
- send_ipi_message(&mask, IPI_CPU_STOP);
+ if (!cpus_empty(mask))
+ send_ipi_message(&mask, IPI_CPU_STOP);
}
/*
diff --git a/arch/arm/kernel/unwind.c b/arch/arm/kernel/unwind.c
index dd81a918c106..2a161765f6d5 100644
--- a/arch/arm/kernel/unwind.c
+++ b/arch/arm/kernel/unwind.c
@@ -146,6 +146,8 @@ static struct unwind_idx *unwind_find_idx(unsigned long addr)
addr < table->end_addr) {
idx = search_index(addr, table->start,
table->stop - 1);
+ /* Move-to-front to exploit common traces */
+ list_move(&table->list, &unwind_tables);
break;
}
}
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index b16c07914b55..1953e3d21abf 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -8,6 +8,19 @@
#include <asm/memory.h>
#include <asm/page.h>
+#define PROC_INFO \
+ VMLINUX_SYMBOL(__proc_info_begin) = .; \
+ *(.proc.info.init) \
+ VMLINUX_SYMBOL(__proc_info_end) = .;
+
+#ifdef CONFIG_HOTPLUG_CPU
+#define ARM_CPU_DISCARD(x)
+#define ARM_CPU_KEEP(x) x
+#else
+#define ARM_CPU_DISCARD(x) x
+#define ARM_CPU_KEEP(x)
+#endif
+
OUTPUT_ARCH(arm)
ENTRY(stext)
@@ -31,15 +44,18 @@ SECTIONS
HEAD_TEXT
INIT_TEXT
_einittext = .;
- __proc_info_begin = .;
- *(.proc.info.init)
- __proc_info_end = .;
+ ARM_CPU_DISCARD(PROC_INFO)
__arch_info_begin = .;
*(.arch.info.init)
__arch_info_end = .;
__tagtable_begin = .;
*(.taglist.init)
__tagtable_end = .;
+#ifdef CONFIG_SMP_ON_UP
+ __smpalt_begin = .;
+ *(.alt.smp.init)
+ __smpalt_end = .;
+#endif
INIT_SETUP(16)
@@ -68,10 +84,8 @@ SECTIONS
/DISCARD/ : {
*(.ARM.exidx.exit.text)
*(.ARM.extab.exit.text)
-#ifndef CONFIG_HOTPLUG_CPU
- *(.ARM.exidx.cpuexit.text)
- *(.ARM.extab.cpuexit.text)
-#endif
+ ARM_CPU_DISCARD(*(.ARM.exidx.cpuexit.text))
+ ARM_CPU_DISCARD(*(.ARM.extab.cpuexit.text))
#ifndef CONFIG_HOTPLUG
*(.ARM.exidx.devexit.text)
*(.ARM.extab.devexit.text)
@@ -100,12 +114,11 @@ SECTIONS
*(.glue_7)
*(.glue_7t)
*(.got) /* Global offset table */
+ ARM_CPU_KEEP(PROC_INFO)
}
RO_DATA(PAGE_SIZE)
- _etext = .; /* End of text and rodata section */
-
#ifdef CONFIG_ARM_UNWIND
/*
* Stack unwinding tables
@@ -123,6 +136,8 @@ SECTIONS
}
#endif
+ _etext = .; /* End of text and rodata section */
+
#ifdef CONFIG_XIP_KERNEL
__data_loc = ALIGN(4); /* location in binary */
. = PAGE_OFFSET + TEXT_OFFSET;
@@ -237,6 +252,12 @@ SECTIONS
/* Default discards */
DISCARDS
+
+#ifndef CONFIG_SMP_ON_UP
+ /DISCARD/ : {
+ *(.alt.smp.init)
+ }
+#endif
}
/*
diff --git a/arch/arm/mach-aaec2000/aaed2000.c b/arch/arm/mach-aaec2000/aaed2000.c
index 81a3ecc0d104..0eb3e3e5b2d1 100644
--- a/arch/arm/mach-aaec2000/aaed2000.c
+++ b/arch/arm/mach-aaec2000/aaed2000.c
@@ -95,8 +95,6 @@ static void __init aaed2000_map_io(void)
MACHINE_START(AAED2000, "Agilent AAED-2000 Development Platform")
/* Maintainer: Nicolas Bellido Y Ortega */
- .phys_io = PIO_BASE,
- .io_pg_offst = ((VIO_BASE) >> 18) & 0xfffc,
.map_io = aaed2000_map_io,
.init_irq = aaed2000_init_irq,
.timer = &aaec2000_timer,
diff --git a/arch/arm/mach-aaec2000/include/mach/debug-macro.S b/arch/arm/mach-aaec2000/include/mach/debug-macro.S
index a9cac368bfe6..bc7ad5561c4c 100644
--- a/arch/arm/mach-aaec2000/include/mach/debug-macro.S
+++ b/arch/arm/mach-aaec2000/include/mach/debug-macro.S
@@ -10,12 +10,10 @@
*/
#include "hardware.h"
- .macro addruart, rx, tmp
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ MMU enabled?
- moveq \rx, #0x80000000 @ physical
- movne \rx, #io_p2v(0x80000000) @ virtual
- orr \rx, \rx, #0x00000800
+ .macro addruart, rp, rv
+ mov \rp, 0x00000800
+ orr \rv, \rp, #io_p2v(0x80000000) @ virtual
+ orr \rp, \rp, #0x80000000 @ physical
.endm
.macro senduart,rd,rx
diff --git a/arch/arm/mach-aaec2000/include/mach/vmalloc.h b/arch/arm/mach-aaec2000/include/mach/vmalloc.h
index 551f68f666bf..cff4e0a996ce 100644
--- a/arch/arm/mach-aaec2000/include/mach/vmalloc.h
+++ b/arch/arm/mach-aaec2000/include/mach/vmalloc.h
@@ -11,6 +11,6 @@
#ifndef __ASM_ARCH_VMALLOC_H
#define __ASM_ARCH_VMALLOC_H
-#define VMALLOC_END (PAGE_OFFSET + 0x10000000)
+#define VMALLOC_END 0xd0000000
#endif /* __ASM_ARCH_VMALLOC_H */
diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
index 939bccd70569..851e8139ef9d 100644
--- a/arch/arm/mach-at91/Kconfig
+++ b/arch/arm/mach-at91/Kconfig
@@ -33,6 +33,7 @@ config ARCH_AT91SAM9260
select HAVE_AT91_USART3
select HAVE_AT91_USART4
select HAVE_AT91_USART5
+ select HAVE_NET_MACB
config ARCH_AT91SAM9261
bool "AT91SAM9261"
@@ -51,6 +52,7 @@ config ARCH_AT91SAM9263
select CPU_ARM926T
select GENERIC_CLOCKEVENTS
select HAVE_FB_ATMEL
+ select HAVE_NET_MACB
config ARCH_AT91SAM9RL
bool "AT91SAM9RL"
@@ -66,6 +68,7 @@ config ARCH_AT91SAM9G20
select HAVE_AT91_USART3
select HAVE_AT91_USART4
select HAVE_AT91_USART5
+ select HAVE_NET_MACB
config ARCH_AT91SAM9G45
bool "AT91SAM9G45"
@@ -73,6 +76,7 @@ config ARCH_AT91SAM9G45
select GENERIC_CLOCKEVENTS
select HAVE_AT91_USART3
select HAVE_FB_ATMEL
+ select HAVE_NET_MACB
config ARCH_AT91CAP9
bool "AT91CAP9"
@@ -248,6 +252,12 @@ config MACH_CPU9260
Select this if you are using a Eukrea Electromatique's
CPU9260 Board <http://www.eukrea.com/>
+config MACH_FLEXIBITY
+ bool "Flexibity Connect board"
+ help
+ Select this if you are using Flexibity Connect board
+ <http://www.flexibity.com>
+
endif
# ----------------------------------------------------------
@@ -338,6 +348,7 @@ config MACH_AT91SAM9G20EK
that embeds only one SD/MMC slot.
config MACH_AT91SAM9G20EK_2MMC
+ depends on MACH_AT91SAM9G20EK
bool "Atmel AT91SAM9G20-EK Evaluation Kit with 2 SD/MMC Slots"
select HAVE_NAND_ATMEL_BUSWIDTH_16
help
@@ -383,8 +394,8 @@ if ARCH_AT91SAM9G45
comment "AT91SAM9G45 Board Type"
-config MACH_AT91SAM9G45EKES
- bool "Atmel AT91SAM9G45-EKES Evaluation Kit"
+config MACH_AT91SAM9M10G45EK
+ bool "Atmel AT91SAM9M10G45-EK Evaluation Kits"
select HAVE_NAND_ATMEL_BUSWIDTH_16
help
Select this if you are using Atmel's AT91SAM9G45-EKES Evaluation Kit.
diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile
index ca2ac003f41f..412b3a471a4b 100644
--- a/arch/arm/mach-at91/Makefile
+++ b/arch/arm/mach-at91/Makefile
@@ -46,6 +46,7 @@ obj-$(CONFIG_MACH_USB_A9260) += board-usb-a9260.o
obj-$(CONFIG_MACH_QIL_A9260) += board-qil-a9260.o
obj-$(CONFIG_MACH_AFEB9260) += board-afeb-9260v1.o
obj-$(CONFIG_MACH_CPU9260) += board-cpu9krea.o
+obj-$(CONFIG_MACH_FLEXIBITY) += board-flexibity.o
# AT91SAM9261 board-specific support
obj-$(CONFIG_MACH_AT91SAM9261EK) += board-sam9261ek.o
@@ -61,7 +62,6 @@ obj-$(CONFIG_MACH_AT91SAM9RLEK) += board-sam9rlek.o
# AT91SAM9G20 board-specific support
obj-$(CONFIG_MACH_AT91SAM9G20EK) += board-sam9g20ek.o
-obj-$(CONFIG_MACH_AT91SAM9G20EK_2MMC) += board-sam9g20ek-2slot-mmc.o
obj-$(CONFIG_MACH_CPU9G20) += board-cpu9krea.o
obj-$(CONFIG_MACH_STAMP9G20) += board-stamp9g20.o
obj-$(CONFIG_MACH_PORTUXG20) += board-stamp9g20.o
@@ -70,7 +70,7 @@ obj-$(CONFIG_MACH_PORTUXG20) += board-stamp9g20.o
obj-$(CONFIG_MACH_SNAPPER_9260) += board-snapper9260.o
# AT91SAM9G45 board-specific support
-obj-$(CONFIG_MACH_AT91SAM9G45EKES) += board-sam9m10g45ek.o
+obj-$(CONFIG_MACH_AT91SAM9M10G45EK) += board-sam9m10g45ek.o
# AT91CAP9 board-specific support
obj-$(CONFIG_MACH_AT91CAP9ADK) += board-cap9adk.o
diff --git a/arch/arm/mach-at91/board-1arm.c b/arch/arm/mach-at91/board-1arm.c
index 9b27d167bff0..46bdc82d3fbf 100644
--- a/arch/arm/mach-at91/board-1arm.c
+++ b/arch/arm/mach-at91/board-1arm.c
@@ -92,8 +92,6 @@ static void __init onearm_board_init(void)
MACHINE_START(ONEARM, "Ajeco 1ARM single board computer")
/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
- .phys_io = AT91_BASE_SYS,
- .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
.boot_params = AT91_SDRAM_BASE + 0x100,
.timer = &at91rm9200_timer,
.map_io = onearm_map_io,
diff --git a/arch/arm/mach-at91/board-afeb-9260v1.c b/arch/arm/mach-at91/board-afeb-9260v1.c
index 50667bed7cc9..cba7f7771fee 100644
--- a/arch/arm/mach-at91/board-afeb-9260v1.c
+++ b/arch/arm/mach-at91/board-afeb-9260v1.c
@@ -218,8 +218,6 @@ static void __init afeb9260_board_init(void)
MACHINE_START(AFEB9260, "Custom afeb9260 board")
/* Maintainer: Sergey Lapin <slapin@ossfans.org> */
- .phys_io = AT91_BASE_SYS,
- .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
.boot_params = AT91_SDRAM_BASE + 0x100,
.timer = &at91sam926x_timer,
.map_io = afeb9260_map_io,
diff --git a/arch/arm/mach-at91/board-at572d940hf_ek.c b/arch/arm/mach-at91/board-at572d940hf_ek.c
index 5daff277f53e..3929f1c9e4e5 100644
--- a/arch/arm/mach-at91/board-at572d940hf_ek.c
+++ b/arch/arm/mach-at91/board-at572d940hf_ek.c
@@ -216,7 +216,7 @@ static struct atmel_nand_data __initdata eb_nand_data = {
/* .rdy_pin = AT91_PIN_PC16, */
.enable_pin = AT91_PIN_PA15,
.partition_info = nand_partitions,
-#if defined(CONFIG_MTD_NAND_AT91_BUSWIDTH_16)
+#if defined(CONFIG_MTD_NAND_ATMEL_BUSWIDTH_16)
.bus_width_16 = 1,
#else
.bus_width_16 = 0,
@@ -318,8 +318,6 @@ static void __init eb_board_init(void)
MACHINE_START(AT572D940HFEB, "Atmel AT91D940HF-EB")
/* Maintainer: Atmel <costa.antonior@gmail.com> */
- .phys_io = AT91_BASE_SYS,
- .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
.boot_params = AT91_SDRAM_BASE + 0x100,
.timer = &at91sam926x_timer,
.map_io = eb_map_io,
diff --git a/arch/arm/mach-at91/board-cam60.c b/arch/arm/mach-at91/board-cam60.c
index 44eb9f764938..b54e3e6fceb6 100644
--- a/arch/arm/mach-at91/board-cam60.c
+++ b/arch/arm/mach-at91/board-cam60.c
@@ -198,8 +198,6 @@ static void __init cam60_board_init(void)
MACHINE_START(CAM60, "KwikByte CAM60")
/* Maintainer: KwikByte */
- .phys_io = AT91_BASE_SYS,
- .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
.boot_params = AT91_SDRAM_BASE + 0x100,
.timer = &at91sam926x_timer,
.map_io = cam60_map_io,
diff --git a/arch/arm/mach-at91/board-cap9adk.c b/arch/arm/mach-at91/board-cap9adk.c
index d6940870e403..e7274440ead9 100644
--- a/arch/arm/mach-at91/board-cap9adk.c
+++ b/arch/arm/mach-at91/board-cap9adk.c
@@ -399,8 +399,6 @@ static void __init cap9adk_board_init(void)
MACHINE_START(AT91CAP9ADK, "Atmel AT91CAP9A-DK")
/* Maintainer: Stelian Pop <stelian.pop@leadtechdesign.com> */
- .phys_io = AT91_BASE_SYS,
- .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
.boot_params = AT91_SDRAM_BASE + 0x100,
.timer = &at91sam926x_timer,
.map_io = cap9adk_map_io,
diff --git a/arch/arm/mach-at91/board-carmeva.c b/arch/arm/mach-at91/board-carmeva.c
index db1f9544d2e0..2e74a19874d1 100644
--- a/arch/arm/mach-at91/board-carmeva.c
+++ b/arch/arm/mach-at91/board-carmeva.c
@@ -162,8 +162,6 @@ static void __init carmeva_board_init(void)
MACHINE_START(CARMEVA, "Carmeva")
/* Maintainer: Conitec Datasystems */
- .phys_io = AT91_BASE_SYS,
- .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
.boot_params = AT91_SDRAM_BASE + 0x100,
.timer = &at91rm9200_timer,
.map_io = carmeva_map_io,
diff --git a/arch/arm/mach-at91/board-cpu9krea.c b/arch/arm/mach-at91/board-cpu9krea.c
index 4bc2e9f6ebb5..3838594578f3 100644
--- a/arch/arm/mach-at91/board-cpu9krea.c
+++ b/arch/arm/mach-at91/board-cpu9krea.c
@@ -375,8 +375,6 @@ MACHINE_START(CPUAT9260, "Eukrea CPU9260")
MACHINE_START(CPUAT9G20, "Eukrea CPU9G20")
#endif
/* Maintainer: Eric Benard - EUKREA Electromatique */
- .phys_io = AT91_BASE_SYS,
- .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
.boot_params = AT91_SDRAM_BASE + 0x100,
.timer = &at91sam926x_timer,
.map_io = cpu9krea_map_io,
diff --git a/arch/arm/mach-at91/board-cpuat91.c b/arch/arm/mach-at91/board-cpuat91.c
index a28d99656190..2f4dd8cdd484 100644
--- a/arch/arm/mach-at91/board-cpuat91.c
+++ b/arch/arm/mach-at91/board-cpuat91.c
@@ -175,8 +175,6 @@ static void __init cpuat91_board_init(void)
MACHINE_START(CPUAT91, "Eukrea")
/* Maintainer: Eric Benard - EUKREA Electromatique */
- .phys_io = AT91_BASE_SYS,
- .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
.boot_params = AT91_SDRAM_BASE + 0x100,
.timer = &at91rm9200_timer,
.map_io = cpuat91_map_io,
diff --git a/arch/arm/mach-at91/board-csb337.c b/arch/arm/mach-at91/board-csb337.c
index fea2529ebcf9..464839dc39bd 100644
--- a/arch/arm/mach-at91/board-csb337.c
+++ b/arch/arm/mach-at91/board-csb337.c
@@ -257,8 +257,6 @@ static void __init csb337_board_init(void)
MACHINE_START(CSB337, "Cogent CSB337")
/* Maintainer: Bill Gatliff */
- .phys_io = AT91_BASE_SYS,
- .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
.boot_params = AT91_SDRAM_BASE + 0x100,
.timer = &at91rm9200_timer,
.map_io = csb337_map_io,
diff --git a/arch/arm/mach-at91/board-csb637.c b/arch/arm/mach-at91/board-csb637.c
index cfa3f04b2205..431688c61412 100644
--- a/arch/arm/mach-at91/board-csb637.c
+++ b/arch/arm/mach-at91/board-csb637.c
@@ -138,8 +138,6 @@ static void __init csb637_board_init(void)
MACHINE_START(CSB637, "Cogent CSB637")
/* Maintainer: Bill Gatliff */
- .phys_io = AT91_BASE_SYS,
- .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
.boot_params = AT91_SDRAM_BASE + 0x100,
.timer = &at91rm9200_timer,
.map_io = csb637_map_io,
diff --git a/arch/arm/mach-at91/board-dk.c b/arch/arm/mach-at91/board-dk.c
index 0fd0f5bc77ea..e14f0e165680 100644
--- a/arch/arm/mach-at91/board-dk.c
+++ b/arch/arm/mach-at91/board-dk.c
@@ -225,8 +225,6 @@ static void __init dk_board_init(void)
MACHINE_START(AT91RM9200DK, "Atmel AT91RM9200-DK")
/* Maintainer: SAN People/Atmel */
- .phys_io = AT91_BASE_SYS,
- .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
.boot_params = AT91_SDRAM_BASE + 0x100,
.timer = &at91rm9200_timer,
.map_io = dk_map_io,
diff --git a/arch/arm/mach-at91/board-eb9200.c b/arch/arm/mach-at91/board-eb9200.c
index 528656761ff7..6cf6566ae346 100644
--- a/arch/arm/mach-at91/board-eb9200.c
+++ b/arch/arm/mach-at91/board-eb9200.c
@@ -120,8 +120,6 @@ static void __init eb9200_board_init(void)
}
MACHINE_START(ATEB9200, "Embest ATEB9200")
- .phys_io = AT91_BASE_SYS,
- .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
.boot_params = AT91_SDRAM_BASE + 0x100,
.timer = &at91rm9200_timer,
.map_io = eb9200_map_io,
diff --git a/arch/arm/mach-at91/board-ecbat91.c b/arch/arm/mach-at91/board-ecbat91.c
index 1d69908617f0..7b58c948a957 100644
--- a/arch/arm/mach-at91/board-ecbat91.c
+++ b/arch/arm/mach-at91/board-ecbat91.c
@@ -168,8 +168,6 @@ static void __init ecb_at91board_init(void)
MACHINE_START(ECBAT91, "emQbit's ECB_AT91")
/* Maintainer: emQbit.com */
- .phys_io = AT91_BASE_SYS,
- .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
.boot_params = AT91_SDRAM_BASE + 0x100,
.timer = &at91rm9200_timer,
.map_io = ecb_at91map_io,
diff --git a/arch/arm/mach-at91/board-eco920.c b/arch/arm/mach-at91/board-eco920.c
index 295a96609e71..a158a0ce458f 100644
--- a/arch/arm/mach-at91/board-eco920.c
+++ b/arch/arm/mach-at91/board-eco920.c
@@ -148,8 +148,6 @@ static void __init eco920_board_init(void)
MACHINE_START(ECO920, "eco920")
/* Maintainer: Sascha Hauer */
- .phys_io = AT91_BASE_SYS,
- .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
.boot_params = AT91_SDRAM_BASE + 0x100,
.timer = &at91rm9200_timer,
.map_io = eco920_map_io,
diff --git a/arch/arm/mach-at91/board-ek.c b/arch/arm/mach-at91/board-ek.c
index 4cdfaac8e590..56e92c4bbc2a 100644
--- a/arch/arm/mach-at91/board-ek.c
+++ b/arch/arm/mach-at91/board-ek.c
@@ -191,8 +191,6 @@ static void __init ek_board_init(void)
MACHINE_START(AT91RM9200EK, "Atmel AT91RM9200-EK")
/* Maintainer: SAN People/Atmel */
- .phys_io = AT91_BASE_SYS,
- .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
.boot_params = AT91_SDRAM_BASE + 0x100,
.timer = &at91rm9200_timer,
.map_io = ek_map_io,
diff --git a/arch/arm/mach-at91/board-flexibity.c b/arch/arm/mach-at91/board-flexibity.c
new file mode 100644
index 000000000000..c8a62dc8fa65
--- /dev/null
+++ b/arch/arm/mach-at91/board-flexibity.c
@@ -0,0 +1,162 @@
+/*
+ * linux/arch/arm/mach-at91/board-flexibity.c
+ *
+ * Copyright (C) 2010 Flexibity
+ * Copyright (C) 2005 SAN People
+ * Copyright (C) 2006 Atmel
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/input.h>
+#include <linux/gpio.h>
+
+#include <asm/mach-types.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/board.h>
+
+#include "generic.h"
+
+static void __init flexibity_map_io(void)
+{
+ /* Initialize processor: 18.432 MHz crystal */
+ at91sam9260_initialize(18432000);
+
+ /* DBGU on ttyS0. (Rx & Tx only) */
+ at91_register_uart(0, 0, 0);
+
+ /* set serial console to ttyS0 (ie, DBGU) */
+ at91_set_serial_console(0);
+}
+
+static void __init flexibity_init_irq(void)
+{
+ at91sam9260_init_interrupts(NULL);
+}
+
+/* USB Host port */
+static struct at91_usbh_data __initdata flexibity_usbh_data = {
+ .ports = 2,
+};
+
+/* USB Device port */
+static struct at91_udc_data __initdata flexibity_udc_data = {
+ .vbus_pin = AT91_PIN_PC5,
+ .pullup_pin = 0, /* pull-up driven by UDC */
+};
+
+/* SPI devices */
+static struct spi_board_info flexibity_spi_devices[] = {
+ { /* DataFlash chip */
+ .modalias = "mtd_dataflash",
+ .chip_select = 1,
+ .max_speed_hz = 15 * 1000 * 1000,
+ .bus_num = 0,
+ },
+};
+
+/* MCI (SD/MMC) */
+static struct at91_mmc_data __initdata flexibity_mmc_data = {
+ .slot_b = 0,
+ .wire4 = 1,
+ .det_pin = AT91_PIN_PC9,
+ .wp_pin = AT91_PIN_PC4,
+};
+
+/* LEDs */
+static struct gpio_led flexibity_leds[] = {
+ {
+ .name = "usb1:green",
+ .gpio = AT91_PIN_PA12,
+ .active_low = 1,
+ .default_trigger = "default-on",
+ },
+ {
+ .name = "usb1:red",
+ .gpio = AT91_PIN_PA13,
+ .active_low = 1,
+ .default_trigger = "default-on",
+ },
+ {
+ .name = "usb2:green",
+ .gpio = AT91_PIN_PB26,
+ .active_low = 1,
+ .default_trigger = "default-on",
+ },
+ {
+ .name = "usb2:red",
+ .gpio = AT91_PIN_PB27,
+ .active_low = 1,
+ .default_trigger = "default-on",
+ },
+ {
+ .name = "usb3:green",
+ .gpio = AT91_PIN_PC8,
+ .active_low = 1,
+ .default_trigger = "default-on",
+ },
+ {
+ .name = "usb3:red",
+ .gpio = AT91_PIN_PC6,
+ .active_low = 1,
+ .default_trigger = "default-on",
+ },
+ {
+ .name = "usb4:green",
+ .gpio = AT91_PIN_PB4,
+ .active_low = 1,
+ .default_trigger = "default-on",
+ },
+ {
+ .name = "usb4:red",
+ .gpio = AT91_PIN_PB5,
+ .active_low = 1,
+ .default_trigger = "default-on",
+ }
+};
+
+static void __init flexibity_board_init(void)
+{
+ /* Serial */
+ at91_add_device_serial();
+ /* USB Host */
+ at91_add_device_usbh(&flexibity_usbh_data);
+ /* USB Device */
+ at91_add_device_udc(&flexibity_udc_data);
+ /* SPI */
+ at91_add_device_spi(flexibity_spi_devices,
+ ARRAY_SIZE(flexibity_spi_devices));
+ /* MMC */
+ at91_add_device_mmc(0, &flexibity_mmc_data);
+ /* LEDs */
+ at91_gpio_leds(flexibity_leds, ARRAY_SIZE(flexibity_leds));
+}
+
+MACHINE_START(FLEXIBITY, "Flexibity Connect")
+ /* Maintainer: Maxim Osipov */
+ .boot_params = AT91_SDRAM_BASE + 0x100,
+ .timer = &at91sam926x_timer,
+ .map_io = flexibity_map_io,
+ .init_irq = flexibity_init_irq,
+ .init_machine = flexibity_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91/board-kafa.c b/arch/arm/mach-at91/board-kafa.c
index a87956c0a74f..c0ce79d431a0 100644
--- a/arch/arm/mach-at91/board-kafa.c
+++ b/arch/arm/mach-at91/board-kafa.c
@@ -99,8 +99,6 @@ static void __init kafa_board_init(void)
MACHINE_START(KAFA, "Sperry-Sun KAFA")
/* Maintainer: Sergei Sharonov */
- .phys_io = AT91_BASE_SYS,
- .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
.boot_params = AT91_SDRAM_BASE + 0x100,
.timer = &at91rm9200_timer,
.map_io = kafa_map_io,
diff --git a/arch/arm/mach-at91/board-kb9202.c b/arch/arm/mach-at91/board-kb9202.c
index fe9b9913fa3c..a13d2063faff 100644
--- a/arch/arm/mach-at91/board-kb9202.c
+++ b/arch/arm/mach-at91/board-kb9202.c
@@ -136,8 +136,6 @@ static void __init kb9202_board_init(void)
MACHINE_START(KB9200, "KB920x")
/* Maintainer: KwikByte, Inc. */
- .phys_io = AT91_BASE_SYS,
- .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
.boot_params = AT91_SDRAM_BASE + 0x100,
.timer = &at91rm9200_timer,
.map_io = kb9202_map_io,
diff --git a/arch/arm/mach-at91/board-neocore926.c b/arch/arm/mach-at91/board-neocore926.c
index 7c1e382330fb..fe5f1d47e6e2 100644
--- a/arch/arm/mach-at91/board-neocore926.c
+++ b/arch/arm/mach-at91/board-neocore926.c
@@ -387,8 +387,6 @@ static void __init neocore926_board_init(void)
MACHINE_START(NEOCORE926, "ADENEO NEOCORE 926")
/* Maintainer: ADENEO */
- .phys_io = AT91_BASE_SYS,
- .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
.boot_params = AT91_SDRAM_BASE + 0x100,
.timer = &at91sam926x_timer,
.map_io = neocore926_map_io,
diff --git a/arch/arm/mach-at91/board-picotux200.c b/arch/arm/mach-at91/board-picotux200.c
index 859727e7ea30..9d833bbc592d 100644
--- a/arch/arm/mach-at91/board-picotux200.c
+++ b/arch/arm/mach-at91/board-picotux200.c
@@ -156,8 +156,6 @@ static void __init picotux200_board_init(void)
MACHINE_START(PICOTUX2XX, "picotux 200")
/* Maintainer: Kleinhenz Elektronik GmbH */
- .phys_io = AT91_BASE_SYS,
- .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
.boot_params = AT91_SDRAM_BASE + 0x100,
.timer = &at91rm9200_timer,
.map_io = picotux200_map_io,
diff --git a/arch/arm/mach-at91/board-qil-a9260.c b/arch/arm/mach-at91/board-qil-a9260.c
index 664938e8f661..69d15a875b66 100644
--- a/arch/arm/mach-at91/board-qil-a9260.c
+++ b/arch/arm/mach-at91/board-qil-a9260.c
@@ -268,8 +268,6 @@ static void __init ek_board_init(void)
MACHINE_START(QIL_A9260, "CALAO QIL_A9260")
/* Maintainer: calao-systems */
- .phys_io = AT91_BASE_SYS,
- .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
.boot_params = AT91_SDRAM_BASE + 0x100,
.timer = &at91sam926x_timer,
.map_io = ek_map_io,
diff --git a/arch/arm/mach-at91/board-sam9-l9260.c b/arch/arm/mach-at91/board-sam9-l9260.c
index b48346977534..25a26beaa728 100644
--- a/arch/arm/mach-at91/board-sam9-l9260.c
+++ b/arch/arm/mach-at91/board-sam9-l9260.c
@@ -212,8 +212,6 @@ static void __init ek_board_init(void)
MACHINE_START(SAM9_L9260, "Olimex SAM9-L9260")
/* Maintainer: Olimex */
- .phys_io = AT91_BASE_SYS,
- .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
.boot_params = AT91_SDRAM_BASE + 0x100,
.timer = &at91sam926x_timer,
.map_io = ek_map_io,
diff --git a/arch/arm/mach-at91/board-sam9260ek.c b/arch/arm/mach-at91/board-sam9260ek.c
index ba9d501b5c50..de1816e0e1d9 100644
--- a/arch/arm/mach-at91/board-sam9260ek.c
+++ b/arch/arm/mach-at91/board-sam9260ek.c
@@ -356,8 +356,6 @@ static void __init ek_board_init(void)
MACHINE_START(AT91SAM9260EK, "Atmel AT91SAM9260-EK")
/* Maintainer: Atmel */
- .phys_io = AT91_BASE_SYS,
- .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
.boot_params = AT91_SDRAM_BASE + 0x100,
.timer = &at91sam926x_timer,
.map_io = ek_map_io,
diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c
index 65eb0943194f..14acc901e24c 100644
--- a/arch/arm/mach-at91/board-sam9261ek.c
+++ b/arch/arm/mach-at91/board-sam9261ek.c
@@ -623,8 +623,6 @@ MACHINE_START(AT91SAM9261EK, "Atmel AT91SAM9261-EK")
MACHINE_START(AT91SAM9G10EK, "Atmel AT91SAM9G10-EK")
#endif
/* Maintainer: Atmel */
- .phys_io = AT91_BASE_SYS,
- .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
.boot_params = AT91_SDRAM_BASE + 0x100,
.timer = &at91sam926x_timer,
.map_io = ek_map_io,
diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
index 2d867fb0630f..bfe490df58be 100644
--- a/arch/arm/mach-at91/board-sam9263ek.c
+++ b/arch/arm/mach-at91/board-sam9263ek.c
@@ -454,8 +454,6 @@ static void __init ek_board_init(void)
MACHINE_START(AT91SAM9263EK, "Atmel AT91SAM9263-EK")
/* Maintainer: Atmel */
- .phys_io = AT91_BASE_SYS,
- .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
.boot_params = AT91_SDRAM_BASE + 0x100,
.timer = &at91sam926x_timer,
.map_io = ek_map_io,
diff --git a/arch/arm/mach-at91/board-sam9g20ek-2slot-mmc.c b/arch/arm/mach-at91/board-sam9g20ek-2slot-mmc.c
deleted file mode 100644
index c49f5c003ee1..000000000000
--- a/arch/arm/mach-at91/board-sam9g20ek-2slot-mmc.c
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- * Copyright (C) 2005 SAN People
- * Copyright (C) 2008 Atmel
- * Copyright (C) 2009 Rob Emanuele
- *
- * 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/at73c213.h>
-#include <linux/clk.h>
-#include <linux/regulator/machine.h>
-#include <linux/regulator/fixed.h>
-#include <linux/regulator/consumer.h>
-
-#include <mach/hardware.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/board.h>
-#include <mach/gpio.h>
-#include <mach/at91sam9_smc.h>
-
-#include "sam9_smc.h"
-#include "generic.h"
-
-
-static void __init ek_map_io(void)
-{
- /* Initialize processor: 18.432 MHz crystal */
- at91sam9260_initialize(18432000);
-
- /* DGBU on ttyS0. (Rx & Tx only) */
- at91_register_uart(0, 0, 0);
-
- /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
- at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
- | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
- | ATMEL_UART_RI);
-
- /* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */
- at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
-
- /* set serial console to ttyS0 (ie, DBGU) */
- at91_set_serial_console(0);
-}
-
-static void __init ek_init_irq(void)
-{
- at91sam9260_init_interrupts(NULL);
-}
-
-
-/*
- * USB Host port
- */
-static struct at91_usbh_data __initdata ek_usbh_data = {
- .ports = 2,
-};
-
-/*
- * USB Device port
- */
-static struct at91_udc_data __initdata ek_udc_data = {
- .vbus_pin = AT91_PIN_PC5,
- .pullup_pin = 0, /* pull-up driven by UDC */
-};
-
-
-/*
- * SPI devices.
- */
-static struct spi_board_info ek_spi_devices[] = {
-#if !(defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_AT91))
- { /* DataFlash chip */
- .modalias = "mtd_dataflash",
- .chip_select = 1,
- .max_speed_hz = 15 * 1000 * 1000,
- .bus_num = 0,
- },
-#if defined(CONFIG_MTD_AT91_DATAFLASH_CARD)
- { /* DataFlash card */
- .modalias = "mtd_dataflash",
- .chip_select = 0,
- .max_speed_hz = 15 * 1000 * 1000,
- .bus_num = 0,
- },
-#endif
-#endif
-};
-
-
-/*
- * MACB Ethernet device
- */
-static struct at91_eth_data __initdata ek_macb_data = {
- .phy_irq_pin = AT91_PIN_PB0,
- .is_rmii = 1,
-};
-
-
-/*
- * NAND flash
- */
-static struct mtd_partition __initdata ek_nand_partition[] = {
- {
- .name = "Bootstrap",
- .offset = 0,
- .size = 4 * SZ_1M,
- },
- {
- .name = "Partition 1",
- .offset = MTDPART_OFS_NXTBLK,
- .size = 60 * SZ_1M,
- },
- {
- .name = "Partition 2",
- .offset = MTDPART_OFS_NXTBLK,
- .size = MTDPART_SIZ_FULL,
- },
-};
-
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
- *num_partitions = ARRAY_SIZE(ek_nand_partition);
- return ek_nand_partition;
-}
-
-/* det_pin is not connected */
-static struct atmel_nand_data __initdata ek_nand_data = {
- .ale = 21,
- .cle = 22,
- .rdy_pin = AT91_PIN_PC13,
- .enable_pin = AT91_PIN_PC14,
- .partition_info = nand_partitions,
-#if defined(CONFIG_MTD_NAND_ATMEL_BUSWIDTH_16)
- .bus_width_16 = 1,
-#else
- .bus_width_16 = 0,
-#endif
-};
-
-static struct sam9_smc_config __initdata ek_nand_smc_config = {
- .ncs_read_setup = 0,
- .nrd_setup = 2,
- .ncs_write_setup = 0,
- .nwe_setup = 2,
-
- .ncs_read_pulse = 4,
- .nrd_pulse = 4,
- .ncs_write_pulse = 4,
- .nwe_pulse = 4,
-
- .read_cycle = 7,
- .write_cycle = 7,
-
- .mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE,
- .tdf_cycles = 3,
-};
-
-static void __init ek_add_device_nand(void)
-{
- /* setup bus-width (8 or 16) */
- if (ek_nand_data.bus_width_16)
- ek_nand_smc_config.mode |= AT91_SMC_DBW_16;
- else
- ek_nand_smc_config.mode |= AT91_SMC_DBW_8;
-
- /* configure chip-select 3 (NAND) */
- sam9_smc_configure(3, &ek_nand_smc_config);
-
- at91_add_device_nand(&ek_nand_data);
-}
-
-
-/*
- * MCI (SD/MMC)
- * wp_pin is not connected
- */
-#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
-static struct mci_platform_data __initdata ek_mmc_data = {
- .slot[0] = {
- .bus_width = 4,
- .detect_pin = AT91_PIN_PC2,
- .wp_pin = -ENODEV,
- },
- .slot[1] = {
- .bus_width = 4,
- .detect_pin = AT91_PIN_PC9,
- .wp_pin = -ENODEV,
- },
-
-};
-#else
-static struct at91_mmc_data __initdata ek_mmc_data = {
- .slot_b = 1, /* Only one slot so use slot B */
- .wire4 = 1,
- .det_pin = AT91_PIN_PC9,
-};
-#endif
-
-/*
- * LEDs
- */
-static struct gpio_led ek_leds[] = {
- { /* "bottom" led, green, userled1 to be defined */
- .name = "ds5",
- .gpio = AT91_PIN_PB8,
- .active_low = 1,
- .default_trigger = "none",
- },
- { /* "power" led, yellow */
- .name = "ds1",
- .gpio = AT91_PIN_PB9,
- .default_trigger = "heartbeat",
- }
-};
-
-#if defined(CONFIG_REGULATOR_FIXED_VOLTAGE) || defined(CONFIG_REGULATOR_FIXED_VOLTAGE_MODULE)
-static struct regulator_consumer_supply ek_audio_consumer_supplies[] = {
- REGULATOR_SUPPLY("AVDD", "0-001b"),
- REGULATOR_SUPPLY("HPVDD", "0-001b"),
- REGULATOR_SUPPLY("DBVDD", "0-001b"),
- REGULATOR_SUPPLY("DCVDD", "0-001b"),
-};
-
-static struct regulator_init_data ek_avdd_reg_init_data = {
- .constraints = {
- .name = "3V3",
- .valid_ops_mask = REGULATOR_CHANGE_STATUS,
- },
- .consumer_supplies = ek_audio_consumer_supplies,
- .num_consumer_supplies = ARRAY_SIZE(ek_audio_consumer_supplies),
-};
-
-static struct fixed_voltage_config ek_vdd_pdata = {
- .supply_name = "board-3V3",
- .microvolts = 3300000,
- .gpio = -EINVAL,
- .enabled_at_boot = 0,
- .init_data = &ek_avdd_reg_init_data,
-};
-static struct platform_device ek_voltage_regulator = {
- .name = "reg-fixed-voltage",
- .id = -1,
- .num_resources = 0,
- .dev = {
- .platform_data = &ek_vdd_pdata,
- },
-};
-static void __init ek_add_regulators(void)
-{
- platform_device_register(&ek_voltage_regulator);
-}
-#else
-static void __init ek_add_regulators(void) {}
-#endif
-
-static struct i2c_board_info __initdata ek_i2c_devices[] = {
- {
- I2C_BOARD_INFO("24c512", 0x50),
- },
-};
-
-
-static void __init ek_board_init(void)
-{
- /* Serial */
- at91_add_device_serial();
- /* USB Host */
- at91_add_device_usbh(&ek_usbh_data);
- /* USB Device */
- at91_add_device_udc(&ek_udc_data);
- /* SPI */
- at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
- /* NAND */
- ek_add_device_nand();
- /* Ethernet */
- at91_add_device_eth(&ek_macb_data);
- /* Regulators */
- ek_add_regulators();
- /* MMC */
-#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
- at91_add_device_mci(0, &ek_mmc_data);
-#else
- at91_add_device_mmc(0, &ek_mmc_data);
-#endif
- /* I2C */
- at91_add_device_i2c(ek_i2c_devices, ARRAY_SIZE(ek_i2c_devices));
- /* LEDs */
- at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
- /* PCK0 provides MCLK to the WM8731 */
- at91_set_B_periph(AT91_PIN_PC1, 0);
- /* SSC (for WM8731) */
- at91_add_device_ssc(AT91SAM9260_ID_SSC, ATMEL_SSC_TX);
-}
-
-MACHINE_START(AT91SAM9G20EK_2MMC, "Atmel AT91SAM9G20-EK 2 MMC Slot Mod")
- /* Maintainer: Rob Emanuele */
- .phys_io = AT91_BASE_SYS,
- .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
- .boot_params = AT91_SDRAM_BASE + 0x100,
- .timer = &at91sam926x_timer,
- .map_io = ek_map_io,
- .init_irq = ek_init_irq,
- .init_machine = ek_board_init,
-MACHINE_END
diff --git a/arch/arm/mach-at91/board-sam9g20ek.c b/arch/arm/mach-at91/board-sam9g20ek.c
index 6ea9808b8868..ca8198b3c168 100644
--- a/arch/arm/mach-at91/board-sam9g20ek.c
+++ b/arch/arm/mach-at91/board-sam9g20ek.c
@@ -47,6 +47,18 @@
#include "sam9_smc.h"
#include "generic.h"
+/*
+ * board revision encoding
+ * bit 0:
+ * 0 => 1 sd/mmc slot
+ * 1 => 2 sd/mmc slots connectors (board from revision C)
+ */
+#define HAVE_2MMC (1 << 0)
+static int inline ek_have_2mmc(void)
+{
+ return machine_is_at91sam9g20ek_2mmc() || (system_rev & HAVE_2MMC);
+}
+
static void __init ek_map_io(void)
{
@@ -94,7 +106,7 @@ static struct at91_udc_data __initdata ek_udc_data = {
* SPI devices.
*/
static struct spi_board_info ek_spi_devices[] = {
-#if !defined(CONFIG_MMC_AT91)
+#if !(defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_AT91))
{ /* DataFlash chip */
.modalias = "mtd_dataflash",
.chip_select = 1,
@@ -121,6 +133,13 @@ static struct at91_eth_data __initdata ek_macb_data = {
.is_rmii = 1,
};
+static void __init ek_add_device_macb(void)
+{
+ if (ek_have_2mmc())
+ ek_macb_data.phy_irq_pin = AT91_PIN_PB0;
+
+ at91_add_device_eth(&ek_macb_data);
+}
/*
* NAND flash
@@ -198,13 +217,36 @@ static void __init ek_add_device_nand(void)
/*
* MCI (SD/MMC)
- * det_pin, wp_pin and vcc_pin are not connected
+ * wp_pin and vcc_pin are not connected
*/
+#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
+static struct mci_platform_data __initdata ek_mmc_data = {
+ .slot[1] = {
+ .bus_width = 4,
+ .detect_pin = AT91_PIN_PC9,
+ },
+
+};
+#else
static struct at91_mmc_data __initdata ek_mmc_data = {
- .slot_b = 1,
+ .slot_b = 1, /* Only one slot so use slot B */
.wire4 = 1,
+ .det_pin = AT91_PIN_PC9,
};
+#endif
+static void __init ek_add_device_mmc(void)
+{
+#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
+ if (ek_have_2mmc()) {
+ ek_mmc_data.slot[0].bus_width = 4;
+ ek_mmc_data.slot[0].detect_pin = AT91_PIN_PC2;
+ }
+ at91_add_device_mci(0, &ek_mmc_data);
+#else
+ at91_add_device_mmc(0, &ek_mmc_data);
+#endif
+}
/*
* LEDs
@@ -223,6 +265,15 @@ static struct gpio_led ek_leds[] = {
}
};
+static void __init ek_add_device_gpio_leds(void)
+{
+ if (ek_have_2mmc()) {
+ ek_leds[0].gpio = AT91_PIN_PB8;
+ ek_leds[1].gpio = AT91_PIN_PB9;
+ }
+
+ at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
+}
/*
* GPIO Buttons
@@ -336,15 +387,15 @@ static void __init ek_board_init(void)
/* NAND */
ek_add_device_nand();
/* Ethernet */
- at91_add_device_eth(&ek_macb_data);
+ ek_add_device_macb();
/* Regulators */
ek_add_regulators();
/* MMC */
- at91_add_device_mmc(0, &ek_mmc_data);
+ ek_add_device_mmc();
/* I2C */
at91_add_device_i2c(ek_i2c_devices, ARRAY_SIZE(ek_i2c_devices));
/* LEDs */
- at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
+ ek_add_device_gpio_leds();
/* Push Buttons */
ek_add_device_buttons();
/* PCK0 provides MCLK to the WM8731 */
@@ -355,8 +406,15 @@ static void __init ek_board_init(void)
MACHINE_START(AT91SAM9G20EK, "Atmel AT91SAM9G20-EK")
/* Maintainer: Atmel */
- .phys_io = AT91_BASE_SYS,
- .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+ .boot_params = AT91_SDRAM_BASE + 0x100,
+ .timer = &at91sam926x_timer,
+ .map_io = ek_map_io,
+ .init_irq = ek_init_irq,
+ .init_machine = ek_board_init,
+MACHINE_END
+
+MACHINE_START(AT91SAM9G20EK_2MMC, "Atmel AT91SAM9G20-EK 2 MMC Slot Mod")
+ /* Maintainer: Atmel */
.boot_params = AT91_SDRAM_BASE + 0x100,
.timer = &at91sam926x_timer,
.map_io = ek_map_io,
diff --git a/arch/arm/mach-at91/board-sam9m10g45ek.c b/arch/arm/mach-at91/board-sam9m10g45ek.c
index ee800595594d..7913984f6de9 100644
--- a/arch/arm/mach-at91/board-sam9m10g45ek.c
+++ b/arch/arm/mach-at91/board-sam9m10g45ek.c
@@ -135,7 +135,7 @@ static struct atmel_nand_data __initdata ek_nand_data = {
.rdy_pin = AT91_PIN_PC8,
.enable_pin = AT91_PIN_PC14,
.partition_info = nand_partitions,
-#if defined(CONFIG_MTD_NAND_AT91_BUSWIDTH_16)
+#if defined(CONFIG_MTD_NAND_ATMEL_BUSWIDTH_16)
.bus_width_16 = 1,
#else
.bus_width_16 = 0,
@@ -399,10 +399,8 @@ static void __init ek_board_init(void)
at91_pwm_leds(ek_pwm_led, ARRAY_SIZE(ek_pwm_led));
}
-MACHINE_START(AT91SAM9G45EKES, "Atmel AT91SAM9G45-EKES")
+MACHINE_START(AT91SAM9M10G45EK, "Atmel AT91SAM9M10G45-EK")
/* Maintainer: Atmel */
- .phys_io = AT91_BASE_SYS,
- .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
.boot_params = AT91_SDRAM_BASE + 0x100,
.timer = &at91sam926x_timer,
.map_io = ek_map_io,
diff --git a/arch/arm/mach-at91/board-sam9rlek.c b/arch/arm/mach-at91/board-sam9rlek.c
index 7ac20f3a2067..3bf3408e94c1 100644
--- a/arch/arm/mach-at91/board-sam9rlek.c
+++ b/arch/arm/mach-at91/board-sam9rlek.c
@@ -329,8 +329,6 @@ static void __init ek_board_init(void)
MACHINE_START(AT91SAM9RLEK, "Atmel AT91SAM9RL-EK")
/* Maintainer: Atmel */
- .phys_io = AT91_BASE_SYS,
- .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
.boot_params = AT91_SDRAM_BASE + 0x100,
.timer = &at91sam926x_timer,
.map_io = ek_map_io,
diff --git a/arch/arm/mach-at91/board-snapper9260.c b/arch/arm/mach-at91/board-snapper9260.c
index 2c08ae4ad3a1..0a99b3cedd7a 100644
--- a/arch/arm/mach-at91/board-snapper9260.c
+++ b/arch/arm/mach-at91/board-snapper9260.c
@@ -177,8 +177,6 @@ static void __init snapper9260_board_init(void)
}
MACHINE_START(SNAPPER_9260, "Bluewater Systems Snapper 9260/9G20 module")
- .phys_io = AT91_BASE_SYS,
- .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
.boot_params = AT91_SDRAM_BASE + 0x100,
.timer = &at91sam926x_timer,
.map_io = snapper9260_map_io,
diff --git a/arch/arm/mach-at91/board-stamp9g20.c b/arch/arm/mach-at91/board-stamp9g20.c
index 87958274290f..5206eef4a67e 100644
--- a/arch/arm/mach-at91/board-stamp9g20.c
+++ b/arch/arm/mach-at91/board-stamp9g20.c
@@ -294,8 +294,6 @@ static void __init stamp9g20_board_init(void)
MACHINE_START(PORTUXG20, "taskit PortuxG20")
/* Maintainer: taskit GmbH */
- .phys_io = AT91_BASE_SYS,
- .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
.boot_params = AT91_SDRAM_BASE + 0x100,
.timer = &at91sam926x_timer,
.map_io = portuxg20_map_io,
@@ -305,8 +303,6 @@ MACHINE_END
MACHINE_START(STAMP9G20, "taskit Stamp9G20")
/* Maintainer: taskit GmbH */
- .phys_io = AT91_BASE_SYS,
- .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
.boot_params = AT91_SDRAM_BASE + 0x100,
.timer = &at91sam926x_timer,
.map_io = stamp9g20_map_io,
diff --git a/arch/arm/mach-at91/board-usb-a9260.c b/arch/arm/mach-at91/board-usb-a9260.c
index 905d6ef76807..07784baeae84 100644
--- a/arch/arm/mach-at91/board-usb-a9260.c
+++ b/arch/arm/mach-at91/board-usb-a9260.c
@@ -228,8 +228,6 @@ static void __init ek_board_init(void)
MACHINE_START(USB_A9260, "CALAO USB_A9260")
/* Maintainer: calao-systems */
- .phys_io = AT91_BASE_SYS,
- .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
.boot_params = AT91_SDRAM_BASE + 0x100,
.timer = &at91sam926x_timer,
.map_io = ek_map_io,
diff --git a/arch/arm/mach-at91/board-usb-a9263.c b/arch/arm/mach-at91/board-usb-a9263.c
index b6a3480383e5..b614508931fd 100644
--- a/arch/arm/mach-at91/board-usb-a9263.c
+++ b/arch/arm/mach-at91/board-usb-a9263.c
@@ -244,8 +244,6 @@ static void __init ek_board_init(void)
MACHINE_START(USB_A9263, "CALAO USB_A9263")
/* Maintainer: calao-systems */
- .phys_io = AT91_BASE_SYS,
- .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
.boot_params = AT91_SDRAM_BASE + 0x100,
.timer = &at91sam926x_timer,
.map_io = ek_map_io,
diff --git a/arch/arm/mach-at91/board-yl-9200.c b/arch/arm/mach-at91/board-yl-9200.c
index e22bf051f835..89df00a9d2f7 100644
--- a/arch/arm/mach-at91/board-yl-9200.c
+++ b/arch/arm/mach-at91/board-yl-9200.c
@@ -594,8 +594,6 @@ static void __init yl9200_board_init(void)
MACHINE_START(YL9200, "uCdragon YL-9200")
/* Maintainer: S.Birtles */
- .phys_io = AT91_BASE_SYS,
- .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
.boot_params = AT91_SDRAM_BASE + 0x100,
.timer = &at91rm9200_timer,
.map_io = yl9200_map_io,
diff --git a/arch/arm/mach-at91/include/mach/at91x40.h b/arch/arm/mach-at91/include/mach/at91x40.h
index d34cdb8abdca..063ac44a0204 100644
--- a/arch/arm/mach-at91/include/mach/at91x40.h
+++ b/arch/arm/mach-at91/include/mach/at91x40.h
@@ -52,4 +52,10 @@
#define AT91_DBGU_CIDR (AT91_SF + 0) /* CIDR in PS segment */
#define AT91_DBGU_EXID (AT91_SF + 4) /* EXID in PS segment */
+/*
+ * Support defines for the simple Power Controller module.
+ */
+#define AT91_PS_CR (AT91_PS + 0) /* PS Control register */
+#define AT91_PS_CR_CPU (1 << 0) /* CPU clock disable bit */
+
#endif /* AT91X40_H */
diff --git a/arch/arm/mach-at91/include/mach/debug-macro.S b/arch/arm/mach-at91/include/mach/debug-macro.S
index 9e750a1c1b5a..0f959faf74a9 100644
--- a/arch/arm/mach-at91/include/mach/debug-macro.S
+++ b/arch/arm/mach-at91/include/mach/debug-macro.S
@@ -14,11 +14,9 @@
#include <mach/hardware.h>
#include <mach/at91_dbgu.h>
- .macro addruart, rx, tmp
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ MMU enabled?
- ldreq \rx, =(AT91_BASE_SYS + AT91_DBGU) @ System peripherals (phys address)
- ldrne \rx, =(AT91_VA_BASE_SYS + AT91_DBGU) @ System peripherals (virt address)
+ .macro addruart, rp, rv
+ ldr \rp, =(AT91_BASE_SYS + AT91_DBGU) @ System peripherals (phys address)
+ ldr \rv, =(AT91_VA_BASE_SYS + AT91_DBGU) @ System peripherals (virt address)
.endm
.macro senduart,rd,rx
diff --git a/arch/arm/mach-at91/include/mach/system.h b/arch/arm/mach-at91/include/mach/system.h
index c80e090b3670..36af14bc13bb 100644
--- a/arch/arm/mach-at91/include/mach/system.h
+++ b/arch/arm/mach-at91/include/mach/system.h
@@ -28,17 +28,20 @@
static inline void arch_idle(void)
{
-#ifndef CONFIG_DEBUG_KERNEL
/*
* Disable the processor clock. The processor will be automatically
* re-enabled by an interrupt or by a reset.
*/
- at91_sys_write(AT91_PMC_SCDR, AT91_PMC_PCK);
+#ifdef AT91_PS
+ at91_sys_write(AT91_PS_CR, AT91_PS_CR_CPU);
#else
+ at91_sys_write(AT91_PMC_SCDR, AT91_PMC_PCK);
+#endif
+#ifndef CONFIG_CPU_ARM920T
/*
* Set the processor (CP15) into 'Wait for Interrupt' mode.
- * Unlike disabling the processor clock via the PMC (above)
- * this allows the processor to be woken via JTAG.
+ * Post-RM9200 processors need this in conjunction with the above
+ * to save power when idle.
*/
cpu_do_idle();
#endif
diff --git a/arch/arm/mach-bcmring/arch.c b/arch/arm/mach-bcmring/arch.c
index 2f139196d63d..73eb066d2329 100644
--- a/arch/arm/mach-bcmring/arch.c
+++ b/arch/arm/mach-bcmring/arch.c
@@ -167,8 +167,6 @@ static void __init bcmring_fixup(struct machine_desc *desc,
MACHINE_START(BCMRING, "BCMRING")
/* Maintainer: Broadcom Corporation */
- .phys_io = MM_IO_START,
- .io_pg_offst = (MM_IO_BASE >> 18) & 0xfffc,
.fixup = bcmring_fixup,
.map_io = bcmring_map_io,
.init_irq = bcmring_init_irq,
diff --git a/arch/arm/mach-bcmring/dma.c b/arch/arm/mach-bcmring/dma.c
index 29c0a911df26..77eb35c89cd0 100644
--- a/arch/arm/mach-bcmring/dma.c
+++ b/arch/arm/mach-bcmring/dma.c
@@ -691,7 +691,7 @@ int dma_init(void)
memset(&gDMA, 0, sizeof(gDMA));
- init_MUTEX_LOCKED(&gDMA.lock);
+ sema_init(&gDMA.lock, 0);
init_waitqueue_head(&gDMA.freeChannelQ);
/* Initialize the Hardware */
@@ -1574,7 +1574,7 @@ int dma_init_mem_map(DMA_MemMap_t *memMap)
{
memset(memMap, 0, sizeof(*memMap));
- init_MUTEX(&memMap->lock);
+ sema_init(&memMap->lock, 1);
return 0;
}
diff --git a/arch/arm/mach-bcmring/include/mach/vmalloc.h b/arch/arm/mach-bcmring/include/mach/vmalloc.h
index 35e2ead8395c..3db3a09fd398 100644
--- a/arch/arm/mach-bcmring/include/mach/vmalloc.h
+++ b/arch/arm/mach-bcmring/include/mach/vmalloc.h
@@ -22,4 +22,4 @@
* 0xe0000000 to 0xefffffff. This gives us 256 MB of vm space and handles
* larger physical memory designs better.
*/
-#define VMALLOC_END (PAGE_OFFSET + 0x30000000)
+#define VMALLOC_END 0xf0000000
diff --git a/arch/arm/mach-bcmring/irq.c b/arch/arm/mach-bcmring/irq.c
index dc1c4939b0ce..e3152631eb37 100644
--- a/arch/arm/mach-bcmring/irq.c
+++ b/arch/arm/mach-bcmring/irq.c
@@ -67,21 +67,21 @@ static void bcmring_unmask_irq2(unsigned int irq)
}
static struct irq_chip bcmring_irq0_chip = {
- .typename = "ARM-INTC0",
+ .name = "ARM-INTC0",
.ack = bcmring_mask_irq0,
.mask = bcmring_mask_irq0, /* mask a specific interrupt, blocking its delivery. */
.unmask = bcmring_unmask_irq0, /* unmaks an interrupt */
};
static struct irq_chip bcmring_irq1_chip = {
- .typename = "ARM-INTC1",
+ .name = "ARM-INTC1",
.ack = bcmring_mask_irq1,
.mask = bcmring_mask_irq1,
.unmask = bcmring_unmask_irq1,
};
static struct irq_chip bcmring_irq2_chip = {
- .typename = "ARM-SINTC",
+ .name = "ARM-SINTC",
.ack = bcmring_mask_irq2,
.mask = bcmring_mask_irq2,
.unmask = bcmring_unmask_irq2,
diff --git a/arch/arm/mach-clps711x/autcpu12.c b/arch/arm/mach-clps711x/autcpu12.c
index 5f18eccdc725..4a74b2c959bd 100644
--- a/arch/arm/mach-clps711x/autcpu12.c
+++ b/arch/arm/mach-clps711x/autcpu12.c
@@ -64,8 +64,6 @@ void __init autcpu12_map_io(void)
MACHINE_START(AUTCPU12, "autronix autcpu12")
/* Maintainer: Thomas Gleixner */
- .phys_io = 0x80000000,
- .io_pg_offst = ((0xff000000) >> 18) & 0xfffc,
.boot_params = 0xc0020000,
.map_io = autcpu12_map_io,
.init_irq = clps711x_init_irq,
diff --git a/arch/arm/mach-clps711x/cdb89712.c b/arch/arm/mach-clps711x/cdb89712.c
index 71a80b5b8ad6..5a1689d48793 100644
--- a/arch/arm/mach-clps711x/cdb89712.c
+++ b/arch/arm/mach-clps711x/cdb89712.c
@@ -55,8 +55,6 @@ static void __init cdb89712_map_io(void)
MACHINE_START(CDB89712, "Cirrus-CDB89712")
/* Maintainer: Ray Lehtiniemi */
- .phys_io = 0x80000000,
- .io_pg_offst = ((0xff000000) >> 18) & 0xfffc,
.boot_params = 0xc0000100,
.map_io = cdb89712_map_io,
.init_irq = clps711x_init_irq,
diff --git a/arch/arm/mach-clps711x/ceiva.c b/arch/arm/mach-clps711x/ceiva.c
index 8ada20184978..16481cf3e931 100644
--- a/arch/arm/mach-clps711x/ceiva.c
+++ b/arch/arm/mach-clps711x/ceiva.c
@@ -56,8 +56,6 @@ static void __init ceiva_map_io(void)
MACHINE_START(CEIVA, "CEIVA/Polaroid Photo MAX Digital Picture Frame")
/* Maintainer: Rob Scott */
- .phys_io = 0x80000000,
- .io_pg_offst = ((0xff000000) >> 18) & 0xfffc,
.boot_params = 0xc0000100,
.map_io = ceiva_map_io,
.init_irq = clps711x_init_irq,
diff --git a/arch/arm/mach-clps711x/clep7312.c b/arch/arm/mach-clps711x/clep7312.c
index 3c3bf45039ff..67b5abb4a60a 100644
--- a/arch/arm/mach-clps711x/clep7312.c
+++ b/arch/arm/mach-clps711x/clep7312.c
@@ -37,8 +37,6 @@ fixup_clep7312(struct machine_desc *desc, struct tag *tags,
MACHINE_START(CLEP7212, "Cirrus Logic 7212/7312")
/* Maintainer: Nobody */
- .phys_io = 0x80000000,
- .io_pg_offst = ((0xff000000) >> 18) & 0xfffc,
.boot_params = 0xc0000100,
.fixup = fixup_clep7312,
.map_io = clps711x_map_io,
diff --git a/arch/arm/mach-clps711x/edb7211-arch.c b/arch/arm/mach-clps711x/edb7211-arch.c
index 4a7a2322979a..98ca5b2e940d 100644
--- a/arch/arm/mach-clps711x/edb7211-arch.c
+++ b/arch/arm/mach-clps711x/edb7211-arch.c
@@ -57,8 +57,6 @@ fixup_edb7211(struct machine_desc *desc, struct tag *tags,
MACHINE_START(EDB7211, "CL-EDB7211 (EP7211 eval board)")
/* Maintainer: Jon McClintock */
- .phys_io = 0x80000000,
- .io_pg_offst = ((0xff000000) >> 18) & 0xfffc,
.boot_params = 0xc0020100, /* 0xc0000000 - 0xc001ffff can be video RAM */
.fixup = fixup_edb7211,
.map_io = edb7211_map_io,
diff --git a/arch/arm/mach-clps711x/fortunet.c b/arch/arm/mach-clps711x/fortunet.c
index a696099aa4f8..b1cb479e71e9 100644
--- a/arch/arm/mach-clps711x/fortunet.c
+++ b/arch/arm/mach-clps711x/fortunet.c
@@ -75,8 +75,6 @@ fortunet_fixup(struct machine_desc *desc, struct tag *tags,
MACHINE_START(FORTUNET, "ARM-FortuNet")
/* Maintainer: FortuNet Inc. */
- .phys_io = 0x80000000,
- .io_pg_offst = ((0xf0000000) >> 18) & 0xfffc,
.boot_params = 0x00000000,
.fixup = fortunet_fixup,
.map_io = clps711x_map_io,
diff --git a/arch/arm/mach-clps711x/include/mach/debug-macro.S b/arch/arm/mach-clps711x/include/mach/debug-macro.S
index 072cc6b61ba3..507c6873b7ee 100644
--- a/arch/arm/mach-clps711x/include/mach/debug-macro.S
+++ b/arch/arm/mach-clps711x/include/mach/debug-macro.S
@@ -14,16 +14,14 @@
#include <mach/hardware.h>
#include <asm/hardware/clps7111.h>
- .macro addruart, rx, tmp
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ MMU enabled?
- moveq \rx, #CLPS7111_PHYS_BASE
- movne \rx, #CLPS7111_VIRT_BASE
+ .macro addruart, rp, rv
#ifndef CONFIG_DEBUG_CLPS711X_UART2
- add \rx, \rx, #0x0000 @ UART1
+ mov \rp, #0x0000 @ UART1
#else
- add \rx, \rx, #0x1000 @ UART2
+ mov \rp, #0x1000 @ UART2
#endif
+ orr \rv, \rp, #CLPS7111_VIRT_BASE
+ orr \rp, \rp, #CLPS7111_PHYS_BASE
.endm
.macro senduart,rd,rx
diff --git a/arch/arm/mach-clps711x/include/mach/vmalloc.h b/arch/arm/mach-clps711x/include/mach/vmalloc.h
index ea6cc7beff28..30b3a287ed88 100644
--- a/arch/arm/mach-clps711x/include/mach/vmalloc.h
+++ b/arch/arm/mach-clps711x/include/mach/vmalloc.h
@@ -17,4 +17,4 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#define VMALLOC_END (PAGE_OFFSET + 0x10000000)
+#define VMALLOC_END 0xd0000000
diff --git a/arch/arm/mach-clps711x/p720t.c b/arch/arm/mach-clps711x/p720t.c
index 0d94a30fd6fc..cefbce0480b9 100644
--- a/arch/arm/mach-clps711x/p720t.c
+++ b/arch/arm/mach-clps711x/p720t.c
@@ -89,8 +89,6 @@ static void __init p720t_map_io(void)
MACHINE_START(P720T, "ARM-Prospector720T")
/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
- .phys_io = 0x80000000,
- .io_pg_offst = ((0xff000000) >> 18) & 0xfffc,
.boot_params = 0xc0000100,
.fixup = fixup_p720t,
.map_io = p720t_map_io,
diff --git a/arch/arm/mach-cns3xxx/cns3420vb.c b/arch/arm/mach-cns3xxx/cns3420vb.c
index 9df8391fd78a..90fe9ab8591d 100644
--- a/arch/arm/mach-cns3xxx/cns3420vb.c
+++ b/arch/arm/mach-cns3xxx/cns3420vb.c
@@ -142,8 +142,6 @@ static void __init cns3420_map_io(void)
}
MACHINE_START(CNS3420VB, "Cavium Networks CNS3420 Validation Board")
- .phys_io = CNS3XXX_UART0_BASE,
- .io_pg_offst = (CNS3XXX_UART0_BASE_VIRT >> 18) & 0xfffc,
.boot_params = 0x00000100,
.map_io = cns3420_map_io,
.init_irq = cns3xxx_init_irq,
diff --git a/arch/arm/mach-cns3xxx/include/mach/debug-macro.S b/arch/arm/mach-cns3xxx/include/mach/debug-macro.S
index d16ce7eb00e9..56d828634db5 100644
--- a/arch/arm/mach-cns3xxx/include/mach/debug-macro.S
+++ b/arch/arm/mach-cns3xxx/include/mach/debug-macro.S
@@ -10,12 +10,10 @@
* published by the Free Software Foundation.
*/
- .macro addruart,rx
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ MMU enabled?
- moveq \rx, #0x10000000
- movne \rx, #0xf0000000 @ virtual base
- orr \rx, \rx, #0x00009000
+ .macro addruart,rp,rv
+ mov \rp, #0x00009000
+ orr \rv, \rp, #0xf0000000 @ virtual base
+ orr \rp, \rp, #0x10000000
.endm
#include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c
index c3994f341e49..7f3cdbfc0fbb 100644
--- a/arch/arm/mach-davinci/board-da830-evm.c
+++ b/arch/arm/mach-davinci/board-da830-evm.c
@@ -597,8 +597,6 @@ static void __init da830_evm_map_io(void)
}
MACHINE_START(DAVINCI_DA830_EVM, "DaVinci DA830/OMAP-L137 EVM")
- .phys_io = IO_PHYS,
- .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc,
.boot_params = (DA8XX_DDR_BASE + 0x100),
.map_io = da830_evm_map_io,
.init_irq = cp_intc_init,
diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
index fdc2cc500fc6..b26f5cbfce3e 100644
--- a/arch/arm/mach-davinci/board-da850-evm.c
+++ b/arch/arm/mach-davinci/board-da850-evm.c
@@ -817,8 +817,6 @@ static void __init da850_evm_map_io(void)
}
MACHINE_START(DAVINCI_DA850_EVM, "DaVinci DA850/OMAP-L138 EVM")
- .phys_io = IO_PHYS,
- .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc,
.boot_params = (DA8XX_DDR_BASE + 0x100),
.map_io = da850_evm_map_io,
.init_irq = cp_intc_init,
diff --git a/arch/arm/mach-davinci/board-dm355-evm.c b/arch/arm/mach-davinci/board-dm355-evm.c
index a3191015efee..6e7cad13352c 100644
--- a/arch/arm/mach-davinci/board-dm355-evm.c
+++ b/arch/arm/mach-davinci/board-dm355-evm.c
@@ -351,8 +351,6 @@ static __init void dm355_evm_init(void)
}
MACHINE_START(DAVINCI_DM355_EVM, "DaVinci DM355 EVM")
- .phys_io = IO_PHYS,
- .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc,
.boot_params = (0x80000100),
.map_io = dm355_evm_map_io,
.init_irq = davinci_irq_init,
diff --git a/arch/arm/mach-davinci/board-dm355-leopard.c b/arch/arm/mach-davinci/board-dm355-leopard.c
index f1d8132cf0c3..543f9911b281 100644
--- a/arch/arm/mach-davinci/board-dm355-leopard.c
+++ b/arch/arm/mach-davinci/board-dm355-leopard.c
@@ -270,8 +270,6 @@ static __init void dm355_leopard_init(void)
}
MACHINE_START(DM355_LEOPARD, "DaVinci DM355 leopard")
- .phys_io = IO_PHYS,
- .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc,
.boot_params = (0x80000100),
.map_io = dm355_leopard_map_io,
.init_irq = davinci_irq_init,
diff --git a/arch/arm/mach-davinci/board-dm365-evm.c b/arch/arm/mach-davinci/board-dm365-evm.c
index 84acef1d0b3d..944a0cbaf5cb 100644
--- a/arch/arm/mach-davinci/board-dm365-evm.c
+++ b/arch/arm/mach-davinci/board-dm365-evm.c
@@ -613,8 +613,6 @@ static __init void dm365_evm_init(void)
}
MACHINE_START(DAVINCI_DM365_EVM, "DaVinci DM365 EVM")
- .phys_io = IO_PHYS,
- .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc,
.boot_params = (0x80000100),
.map_io = dm365_evm_map_io,
.init_irq = davinci_irq_init,
diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c
index 34c8b418cd72..d59fba15ba8d 100644
--- a/arch/arm/mach-davinci/board-dm644x-evm.c
+++ b/arch/arm/mach-davinci/board-dm644x-evm.c
@@ -706,8 +706,6 @@ static __init void davinci_evm_init(void)
MACHINE_START(DAVINCI_EVM, "DaVinci DM644x EVM")
/* Maintainer: MontaVista Software <source@mvista.com> */
- .phys_io = IO_PHYS,
- .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc,
.boot_params = (DAVINCI_DDR_BASE + 0x100),
.map_io = davinci_evm_map_io,
.init_irq = davinci_irq_init,
diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c
index 4502f346b2b0..6890488fb92b 100644
--- a/arch/arm/mach-davinci/board-dm646x-evm.c
+++ b/arch/arm/mach-davinci/board-dm646x-evm.c
@@ -786,8 +786,6 @@ void __init dm646x_board_setup_refclk(struct clk *clk)
}
MACHINE_START(DAVINCI_DM6467_EVM, "DaVinci DM646x EVM")
- .phys_io = IO_PHYS,
- .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc,
.boot_params = (0x80000100),
.map_io = davinci_map_io,
.init_irq = davinci_irq_init,
@@ -796,8 +794,6 @@ MACHINE_START(DAVINCI_DM6467_EVM, "DaVinci DM646x EVM")
MACHINE_END
MACHINE_START(DAVINCI_DM6467TEVM, "DaVinci DM6467T EVM")
- .phys_io = IO_PHYS,
- .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc,
.boot_params = (0x80000100),
.map_io = davinci_map_io,
.init_irq = davinci_irq_init,
diff --git a/arch/arm/mach-davinci/board-neuros-osd2.c b/arch/arm/mach-davinci/board-neuros-osd2.c
index 4c30e929bbf9..a4def889275c 100644
--- a/arch/arm/mach-davinci/board-neuros-osd2.c
+++ b/arch/arm/mach-davinci/board-neuros-osd2.c
@@ -275,8 +275,6 @@ static __init void davinci_ntosd2_init(void)
MACHINE_START(NEUROS_OSD2, "Neuros OSD2")
/* Maintainer: Neuros Technologies <neuros@groups.google.com> */
- .phys_io = IO_PHYS,
- .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc,
.boot_params = (DAVINCI_DDR_BASE + 0x100),
.map_io = davinci_ntosd2_map_io,
.init_irq = davinci_irq_init,
diff --git a/arch/arm/mach-davinci/board-sffsdr.c b/arch/arm/mach-davinci/board-sffsdr.c
index 23e664a1a802..9bdf8aafcc84 100644
--- a/arch/arm/mach-davinci/board-sffsdr.c
+++ b/arch/arm/mach-davinci/board-sffsdr.c
@@ -154,8 +154,6 @@ static __init void davinci_sffsdr_init(void)
MACHINE_START(SFFSDR, "Lyrtech SFFSDR")
/* Maintainer: Hugo Villeneuve hugo.villeneuve@lyrtech.com */
- .phys_io = IO_PHYS,
- .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc,
.boot_params = (DAVINCI_DDR_BASE + 0x100),
.map_io = davinci_sffsdr_map_io,
.init_irq = davinci_irq_init,
diff --git a/arch/arm/mach-davinci/board-tnetv107x-evm.c b/arch/arm/mach-davinci/board-tnetv107x-evm.c
index fe2a9d9c8bb7..b4de35b78904 100644
--- a/arch/arm/mach-davinci/board-tnetv107x-evm.c
+++ b/arch/arm/mach-davinci/board-tnetv107x-evm.c
@@ -164,8 +164,6 @@ console_initcall(tnetv107x_evm_console_init);
#endif
MACHINE_START(TNETV107X, "TNETV107X EVM")
- .phys_io = TNETV107X_IO_BASE,
- .io_pg_offst = (TNETV107X_IO_VIRT >> 18) & 0xfffc,
.boot_params = (TNETV107X_DDR_BASE + 0x100),
.map_io = tnetv107x_init,
.init_irq = cp_intc_init,
diff --git a/arch/arm/mach-davinci/include/mach/debug-macro.S b/arch/arm/mach-davinci/include/mach/debug-macro.S
index f761dfdb8689..9f1befc5ac38 100644
--- a/arch/arm/mach-davinci/include/mach/debug-macro.S
+++ b/arch/arm/mach-davinci/include/mach/debug-macro.S
@@ -29,35 +29,39 @@ davinci_uart_phys: .word 0
davinci_uart_virt: .word 0
.popsection
- .macro addruart, rx, tmp
+ .macro addruart, rp, rv
/* Use davinci_uart_phys/virt if already configured */
-10: mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ MMU enabled?
- ldreq \rx, =__virt_to_phys(davinci_uart_phys)
- ldrne \rx, =davinci_uart_virt
- ldr \rx, [\rx]
- cmp \rx, #0 @ is port configured?
+10: mrc p15, 0, \rp, c1, c0
+ tst \rp, #1 @ MMU enabled?
+ ldreq \rp, =__virt_to_phys(davinci_uart_phys)
+ ldrne \rp, =davinci_uart_phys
+ add \rv, \rp, #4 @ davinci_uart_virt
+ ldr \rp, [\rp, #0]
+ ldr \rv, [\rv, #0]
+ cmp \rp, #0 @ is port configured?
+ cmpne \rv, #0
bne 99f @ already configured
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ MMU enabled?
+ /* Check the debug UART address set in uncompress.h */
+ mrc p15, 0, \rp, c1, c0
+ tst \rp, #1 @ MMU enabled?
/* Copy uart phys address from decompressor uart info */
- ldreq \tmp, =__virt_to_phys(davinci_uart_phys)
- ldrne \tmp, =davinci_uart_phys
- ldreq \rx, =DAVINCI_UART_INFO
- ldrne \rx, =__phys_to_virt(DAVINCI_UART_INFO)
- ldr \rx, [\rx, #0]
- str \rx, [\tmp]
+ ldreq \rv, =__virt_to_phys(davinci_uart_phys)
+ ldrne \rv, =davinci_uart_phys
+ ldreq \rp, =DAVINCI_UART_INFO
+ ldrne \rp, =__phys_to_virt(DAVINCI_UART_INFO)
+ ldr \rp, [\rp, #0]
+ str \rp, [\rv]
/* Copy uart virt address from decompressor uart info */
- ldreq \tmp, =__virt_to_phys(davinci_uart_virt)
- ldrne \tmp, =davinci_uart_virt
- ldreq \rx, =DAVINCI_UART_INFO
- ldrne \rx, =__phys_to_virt(DAVINCI_UART_INFO)
- ldr \rx, [\rx, #4]
- str \rx, [\tmp]
+ ldreq \rv, =__virt_to_phys(davinci_uart_virt)
+ ldrne \rv, =davinci_uart_virt
+ ldreq \rp, =DAVINCI_UART_INFO
+ ldrne \rp, =__phys_to_virt(DAVINCI_UART_INFO)
+ ldr \rp, [\rp, #4]
+ str \rp, [\rv]
b 10b
99:
diff --git a/arch/arm/mach-dove/dove-db-setup.c b/arch/arm/mach-dove/dove-db-setup.c
index bef70460fbc6..95925aa76dd9 100644
--- a/arch/arm/mach-dove/dove-db-setup.c
+++ b/arch/arm/mach-dove/dove-db-setup.c
@@ -94,8 +94,6 @@ static void __init dove_db_init(void)
}
MACHINE_START(DOVE_DB, "Marvell DB-MV88AP510-BP Development Board")
- .phys_io = DOVE_SB_REGS_PHYS_BASE,
- .io_pg_offst = ((DOVE_SB_REGS_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = 0x00000100,
.init_machine = dove_db_init,
.map_io = dove_map_io,
diff --git a/arch/arm/mach-dove/include/mach/debug-macro.S b/arch/arm/mach-dove/include/mach/debug-macro.S
index 1521d13f1d14..da8bf2bad3b1 100644
--- a/arch/arm/mach-dove/include/mach/debug-macro.S
+++ b/arch/arm/mach-dove/include/mach/debug-macro.S
@@ -8,12 +8,11 @@
#include <mach/bridge-regs.h>
- .macro addruart, rx, tmp
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ MMU enabled?
- ldreq \rx, =DOVE_SB_REGS_PHYS_BASE
- ldrne \rx, =DOVE_SB_REGS_VIRT_BASE
- orr \rx, \rx, #0x00012000
+ .macro addruart, rp, rv
+ ldr \rp, =DOVE_SB_REGS_PHYS_BASE
+ ldr \rv, =DOVE_SB_REGS_VIRT_BASE
+ orr \rp, \rp, #0x00012000
+ orr \rv, \rv, #0x00012000
.endm
#define UART_SHIFT 2
diff --git a/arch/arm/mach-ebsa110/core.c b/arch/arm/mach-ebsa110/core.c
index c7bc7fbb11a6..5df4099fc14f 100644
--- a/arch/arm/mach-ebsa110/core.c
+++ b/arch/arm/mach-ebsa110/core.c
@@ -280,8 +280,6 @@ arch_initcall(ebsa110_init);
MACHINE_START(EBSA110, "EBSA110")
/* Maintainer: Russell King */
- .phys_io = 0xe0000000,
- .io_pg_offst = ((0xe0000000) >> 18) & 0xfffc,
.boot_params = 0x00000400,
.reserve_lp0 = 1,
.reserve_lp2 = 1,
diff --git a/arch/arm/mach-ebsa110/include/mach/debug-macro.S b/arch/arm/mach-ebsa110/include/mach/debug-macro.S
index ebbd89f0e6c0..7ef5690fd08c 100644
--- a/arch/arm/mach-ebsa110/include/mach/debug-macro.S
+++ b/arch/arm/mach-ebsa110/include/mach/debug-macro.S
@@ -11,9 +11,10 @@
*
**/
- .macro addruart, rx, tmp
- mov \rx, #0xf0000000
- orr \rx, \rx, #0x00000be0
+ .macro addruart, rp, rv
+ mov \rp, #0xf0000000
+ orr \rp, \rp, #0x00000be0
+ mov \rp, \rv
.endm
#define UART_SHIFT 2
diff --git a/arch/arm/mach-ebsa110/include/mach/vmalloc.h b/arch/arm/mach-ebsa110/include/mach/vmalloc.h
index 9b44c19e95ec..60bde56fba4c 100644
--- a/arch/arm/mach-ebsa110/include/mach/vmalloc.h
+++ b/arch/arm/mach-ebsa110/include/mach/vmalloc.h
@@ -7,4 +7,4 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-#define VMALLOC_END (PAGE_OFFSET + 0x1f000000)
+#define VMALLOC_END 0xdf000000
diff --git a/arch/arm/mach-ep93xx/adssphere.c b/arch/arm/mach-ep93xx/adssphere.c
index f744f676783f..61b98ce4b673 100644
--- a/arch/arm/mach-ep93xx/adssphere.c
+++ b/arch/arm/mach-ep93xx/adssphere.c
@@ -33,8 +33,6 @@ static void __init adssphere_init_machine(void)
MACHINE_START(ADSSPHERE, "ADS Sphere board")
/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
- .phys_io = EP93XX_APB_PHYS_BASE,
- .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
.map_io = ep93xx_map_io,
.init_irq = ep93xx_init_irq,
diff --git a/arch/arm/mach-ep93xx/dma-m2p.c b/arch/arm/mach-ep93xx/dma-m2p.c
index 8904ca4e2e24..a696d354b1f8 100644
--- a/arch/arm/mach-ep93xx/dma-m2p.c
+++ b/arch/arm/mach-ep93xx/dma-m2p.c
@@ -276,7 +276,7 @@ static void channel_disable(struct m2p_channel *ch)
v &= ~(M2P_CONTROL_STALL_IRQ_EN | M2P_CONTROL_NFB_IRQ_EN);
m2p_set_control(ch, v);
- while (m2p_channel_state(ch) == STATE_ON)
+ while (m2p_channel_state(ch) >= STATE_ON)
cpu_relax();
m2p_set_control(ch, 0x0);
diff --git a/arch/arm/mach-ep93xx/edb93xx.c b/arch/arm/mach-ep93xx/edb93xx.c
index c2ce9034ba87..4b0431652131 100644
--- a/arch/arm/mach-ep93xx/edb93xx.c
+++ b/arch/arm/mach-ep93xx/edb93xx.c
@@ -124,8 +124,6 @@ static void __init edb93xx_init_machine(void)
#ifdef CONFIG_MACH_EDB9301
MACHINE_START(EDB9301, "Cirrus Logic EDB9301 Evaluation Board")
/* Maintainer: H Hartley Sweeten <hsweeten@visionengravers.com> */
- .phys_io = EP93XX_APB_PHYS_BASE,
- .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
.map_io = ep93xx_map_io,
.init_irq = ep93xx_init_irq,
@@ -137,8 +135,6 @@ MACHINE_END
#ifdef CONFIG_MACH_EDB9302
MACHINE_START(EDB9302, "Cirrus Logic EDB9302 Evaluation Board")
/* Maintainer: George Kashperko <george@chas.com.ua> */
- .phys_io = EP93XX_APB_PHYS_BASE,
- .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
.map_io = ep93xx_map_io,
.init_irq = ep93xx_init_irq,
@@ -150,8 +146,6 @@ MACHINE_END
#ifdef CONFIG_MACH_EDB9302A
MACHINE_START(EDB9302A, "Cirrus Logic EDB9302A Evaluation Board")
/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
- .phys_io = EP93XX_APB_PHYS_BASE,
- .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = EP93XX_SDCE0_PHYS_BASE + 0x100,
.map_io = ep93xx_map_io,
.init_irq = ep93xx_init_irq,
@@ -163,8 +157,6 @@ MACHINE_END
#ifdef CONFIG_MACH_EDB9307
MACHINE_START(EDB9307, "Cirrus Logic EDB9307 Evaluation Board")
/* Maintainer: Herbert Valerio Riedel <hvr@gnu.org> */
- .phys_io = EP93XX_APB_PHYS_BASE,
- .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
.map_io = ep93xx_map_io,
.init_irq = ep93xx_init_irq,
@@ -176,8 +168,6 @@ MACHINE_END
#ifdef CONFIG_MACH_EDB9307A
MACHINE_START(EDB9307A, "Cirrus Logic EDB9307A Evaluation Board")
/* Maintainer: H Hartley Sweeten <hsweeten@visionengravers.com> */
- .phys_io = EP93XX_APB_PHYS_BASE,
- .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = EP93XX_SDCE0_PHYS_BASE + 0x100,
.map_io = ep93xx_map_io,
.init_irq = ep93xx_init_irq,
@@ -189,8 +179,6 @@ MACHINE_END
#ifdef CONFIG_MACH_EDB9312
MACHINE_START(EDB9312, "Cirrus Logic EDB9312 Evaluation Board")
/* Maintainer: Toufeeq Hussain <toufeeq_hussain@infosys.com> */
- .phys_io = EP93XX_APB_PHYS_BASE,
- .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
.map_io = ep93xx_map_io,
.init_irq = ep93xx_init_irq,
@@ -202,8 +190,6 @@ MACHINE_END
#ifdef CONFIG_MACH_EDB9315
MACHINE_START(EDB9315, "Cirrus Logic EDB9315 Evaluation Board")
/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
- .phys_io = EP93XX_APB_PHYS_BASE,
- .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
.map_io = ep93xx_map_io,
.init_irq = ep93xx_init_irq,
@@ -215,8 +201,6 @@ MACHINE_END
#ifdef CONFIG_MACH_EDB9315A
MACHINE_START(EDB9315A, "Cirrus Logic EDB9315A Evaluation Board")
/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
- .phys_io = EP93XX_APB_PHYS_BASE,
- .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = EP93XX_SDCE0_PHYS_BASE + 0x100,
.map_io = ep93xx_map_io,
.init_irq = ep93xx_init_irq,
diff --git a/arch/arm/mach-ep93xx/gesbc9312.c b/arch/arm/mach-ep93xx/gesbc9312.c
index d97168c0ba33..9bd3152bff9a 100644
--- a/arch/arm/mach-ep93xx/gesbc9312.c
+++ b/arch/arm/mach-ep93xx/gesbc9312.c
@@ -33,8 +33,6 @@ static void __init gesbc9312_init_machine(void)
MACHINE_START(GESBC9312, "Glomation GESBC-9312-sx")
/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
- .phys_io = EP93XX_APB_PHYS_BASE,
- .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
.map_io = ep93xx_map_io,
.init_irq = ep93xx_init_irq,
diff --git a/arch/arm/mach-ep93xx/include/mach/debug-macro.S b/arch/arm/mach-ep93xx/include/mach/debug-macro.S
index 5cd22444e223..b25bc9076367 100644
--- a/arch/arm/mach-ep93xx/include/mach/debug-macro.S
+++ b/arch/arm/mach-ep93xx/include/mach/debug-macro.S
@@ -11,12 +11,11 @@
*/
#include <mach/ep93xx-regs.h>
- .macro addruart, rx, tmp
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ MMU enabled?
- ldreq \rx, =EP93XX_APB_PHYS_BASE @ Physical base
- ldrne \rx, =EP93XX_APB_VIRT_BASE @ virtual base
- orr \rx, \rx, #0x000c0000
+ .macro addruart, rp, rv
+ ldr \rp, =EP93XX_APB_PHYS_BASE @ Physical base
+ ldr \rv, =EP93XX_APB_VIRT_BASE @ virtual base
+ orr \rp, \rp, #0x000c0000
+ orr \rv, \rv, #0x000c0000
.endm
#include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/mach-ep93xx/micro9.c b/arch/arm/mach-ep93xx/micro9.c
index 2ba776320a82..7adea6258efe 100644
--- a/arch/arm/mach-ep93xx/micro9.c
+++ b/arch/arm/mach-ep93xx/micro9.c
@@ -77,8 +77,6 @@ static void __init micro9_init_machine(void)
#ifdef CONFIG_MACH_MICRO9H
MACHINE_START(MICRO9, "Contec Micro9-High")
/* Maintainer: Hubert Feurstein <hubert.feurstein@contec.at> */
- .phys_io = EP93XX_APB_PHYS_BASE,
- .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
.map_io = ep93xx_map_io,
.init_irq = ep93xx_init_irq,
@@ -90,8 +88,6 @@ MACHINE_END
#ifdef CONFIG_MACH_MICRO9M
MACHINE_START(MICRO9M, "Contec Micro9-Mid")
/* Maintainer: Hubert Feurstein <hubert.feurstein@contec.at> */
- .phys_io = EP93XX_APB_PHYS_BASE,
- .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = EP93XX_SDCE3_PHYS_BASE_ASYNC + 0x100,
.map_io = ep93xx_map_io,
.init_irq = ep93xx_init_irq,
@@ -103,8 +99,6 @@ MACHINE_END
#ifdef CONFIG_MACH_MICRO9L
MACHINE_START(MICRO9L, "Contec Micro9-Lite")
/* Maintainer: Hubert Feurstein <hubert.feurstein@contec.at> */
- .phys_io = EP93XX_APB_PHYS_BASE,
- .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
.map_io = ep93xx_map_io,
.init_irq = ep93xx_init_irq,
@@ -116,8 +110,6 @@ MACHINE_END
#ifdef CONFIG_MACH_MICRO9S
MACHINE_START(MICRO9S, "Contec Micro9-Slim")
/* Maintainer: Hubert Feurstein <hubert.feurstein@contec.at> */
- .phys_io = EP93XX_APB_PHYS_BASE,
- .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = EP93XX_SDCE3_PHYS_BASE_ASYNC + 0x100,
.map_io = ep93xx_map_io,
.init_irq = ep93xx_init_irq,
diff --git a/arch/arm/mach-ep93xx/simone.c b/arch/arm/mach-ep93xx/simone.c
index 5dded5884133..f22ce8db7947 100644
--- a/arch/arm/mach-ep93xx/simone.c
+++ b/arch/arm/mach-ep93xx/simone.c
@@ -65,8 +65,6 @@ static void __init simone_init_machine(void)
MACHINE_START(SIM_ONE, "Simplemachines Sim.One Board")
/* Maintainer: Ryan Mallon <ryan@bluewatersys.com> */
- .phys_io = EP93XX_APB_PHYS_BASE,
- .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = EP93XX_SDCE0_PHYS_BASE + 0x100,
.map_io = ep93xx_map_io,
.init_irq = ep93xx_init_irq,
diff --git a/arch/arm/mach-ep93xx/snappercl15.c b/arch/arm/mach-ep93xx/snappercl15.c
index a12c89301297..ac601fe2b448 100644
--- a/arch/arm/mach-ep93xx/snappercl15.c
+++ b/arch/arm/mach-ep93xx/snappercl15.c
@@ -163,8 +163,6 @@ static void __init snappercl15_init_machine(void)
MACHINE_START(SNAPPER_CL15, "Bluewater Systems Snapper CL15")
/* Maintainer: Ryan Mallon <ryan@bluewatersys.com> */
- .phys_io = EP93XX_APB_PHYS_BASE,
- .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = EP93XX_SDCE0_PHYS_BASE + 0x100,
.map_io = ep93xx_map_io,
.init_irq = ep93xx_init_irq,
diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
index 93aeab8af705..c2d2cf40ead9 100644
--- a/arch/arm/mach-ep93xx/ts72xx.c
+++ b/arch/arm/mach-ep93xx/ts72xx.c
@@ -257,8 +257,6 @@ static void __init ts72xx_init_machine(void)
MACHINE_START(TS72XX, "Technologic Systems TS-72xx SBC")
/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
- .phys_io = EP93XX_APB_PHYS_BASE,
- .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
.map_io = ts72xx_map_io,
.init_irq = ep93xx_init_irq,
diff --git a/arch/arm/mach-footbridge/cats-hw.c b/arch/arm/mach-footbridge/cats-hw.c
index 1b996b26d2e0..5b1a8db779be 100644
--- a/arch/arm/mach-footbridge/cats-hw.c
+++ b/arch/arm/mach-footbridge/cats-hw.c
@@ -86,8 +86,6 @@ fixup_cats(struct machine_desc *desc, struct tag *tags,
MACHINE_START(CATS, "Chalice-CATS")
/* Maintainer: Philip Blundell */
- .phys_io = DC21285_ARMCSR_BASE,
- .io_pg_offst = ((0xfe000000) >> 18) & 0xfffc,
.boot_params = 0x00000100,
.soft_reboot = 1,
.fixup = fixup_cats,
diff --git a/arch/arm/mach-footbridge/ebsa285.c b/arch/arm/mach-footbridge/ebsa285.c
index 30040fd588cc..2ef69ff44ba8 100644
--- a/arch/arm/mach-footbridge/ebsa285.c
+++ b/arch/arm/mach-footbridge/ebsa285.c
@@ -15,8 +15,6 @@
MACHINE_START(EBSA285, "EBSA285")
/* Maintainer: Russell King */
- .phys_io = DC21285_ARMCSR_BASE,
- .io_pg_offst = ((0xfe000000) >> 18) & 0xfffc,
.boot_params = 0x00000100,
.video_start = 0x000a0000,
.video_end = 0x000bffff,
diff --git a/arch/arm/mach-footbridge/include/mach/debug-macro.S b/arch/arm/mach-footbridge/include/mach/debug-macro.S
index 60dda1318f22..3c9e0c40c679 100644
--- a/arch/arm/mach-footbridge/include/mach/debug-macro.S
+++ b/arch/arm/mach-footbridge/include/mach/debug-macro.S
@@ -15,12 +15,10 @@
#ifndef CONFIG_DEBUG_DC21285_PORT
/* For NetWinder debugging */
- .macro addruart, rx, tmp
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ MMU enabled?
- moveq \rx, #0x7c000000 @ physical
- movne \rx, #0xff000000 @ virtual
- orr \rx, \rx, #0x000003f8
+ .macro addruart, rp, rv
+ mov \rp, #0x000003f8
+ orr \rv, \rp, #0x7c000000 @ physical
+ orr \rp, \rp, #0xff000000 @ virtual
.endm
#define UART_SHIFT 0
@@ -32,14 +30,14 @@
.equ dc21285_high, ARMCSR_BASE & 0xff000000
.equ dc21285_low, ARMCSR_BASE & 0x00ffffff
- .macro addruart, rx, tmp
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ MMU enabled?
- moveq \rx, #0x42000000
- movne \rx, #dc21285_high
+ .macro addruart, rp, rv
.if dc21285_low
- orrne \rx, \rx, #dc21285_low
+ mov \rp, #dc21285_low
+ .else
+ mov \rp, #0
.endif
+ orr \rv, \rp, #0x42000000
+ orr \rp, \rp, #dc21285_high
.endm
.macro senduart,rd,rx
diff --git a/arch/arm/mach-footbridge/include/mach/vmalloc.h b/arch/arm/mach-footbridge/include/mach/vmalloc.h
index d0958d860a3c..0ffbb7c85e59 100644
--- a/arch/arm/mach-footbridge/include/mach/vmalloc.h
+++ b/arch/arm/mach-footbridge/include/mach/vmalloc.h
@@ -7,4 +7,4 @@
*/
-#define VMALLOC_END (PAGE_OFFSET + 0x30000000)
+#define VMALLOC_END 0xf0000000
diff --git a/arch/arm/mach-footbridge/netwinder-hw.c b/arch/arm/mach-footbridge/netwinder-hw.c
index ac7ffa6fc413..06e514f372d0 100644
--- a/arch/arm/mach-footbridge/netwinder-hw.c
+++ b/arch/arm/mach-footbridge/netwinder-hw.c
@@ -648,8 +648,6 @@ fixup_netwinder(struct machine_desc *desc, struct tag *tags,
MACHINE_START(NETWINDER, "Rebel-NetWinder")
/* Maintainer: Russell King/Rebel.com */
- .phys_io = DC21285_ARMCSR_BASE,
- .io_pg_offst = ((0xfe000000) >> 18) & 0xfffc,
.boot_params = 0x00000100,
.video_start = 0x000a0000,
.video_end = 0x000bffff,
diff --git a/arch/arm/mach-footbridge/personal.c b/arch/arm/mach-footbridge/personal.c
index e2c9f0690b16..3285e91ca8c1 100644
--- a/arch/arm/mach-footbridge/personal.c
+++ b/arch/arm/mach-footbridge/personal.c
@@ -15,8 +15,6 @@
MACHINE_START(PERSONAL_SERVER, "Compaq-PersonalServer")
/* Maintainer: Jamey Hicks / George France */
- .phys_io = DC21285_ARMCSR_BASE,
- .io_pg_offst = ((0xfe000000) >> 18) & 0xfffc,
.boot_params = 0x00000100,
.map_io = footbridge_map_io,
.init_irq = footbridge_init_irq,
diff --git a/arch/arm/mach-gemini/board-nas4220b.c b/arch/arm/mach-gemini/board-nas4220b.c
index 01f1d6daab44..2ba096de0034 100644
--- a/arch/arm/mach-gemini/board-nas4220b.c
+++ b/arch/arm/mach-gemini/board-nas4220b.c
@@ -101,8 +101,6 @@ static void __init ib4220b_init(void)
}
MACHINE_START(NAS4220B, "Raidsonic NAS IB-4220-B")
- .phys_io = 0x7fffc000,
- .io_pg_offst = ((0xffffc000) >> 18) & 0xfffc,
.boot_params = 0x100,
.map_io = gemini_map_io,
.init_irq = gemini_init_irq,
diff --git a/arch/arm/mach-gemini/board-rut1xx.c b/arch/arm/mach-gemini/board-rut1xx.c
index e0de968e32a6..a9a0d8b01942 100644
--- a/arch/arm/mach-gemini/board-rut1xx.c
+++ b/arch/arm/mach-gemini/board-rut1xx.c
@@ -85,8 +85,6 @@ static void __init rut1xx_init(void)
}
MACHINE_START(RUT100, "Teltonika RUT100")
- .phys_io = 0x7fffc000,
- .io_pg_offst = ((0xffffc000) >> 18) & 0xfffc,
.boot_params = 0x100,
.map_io = gemini_map_io,
.init_irq = gemini_init_irq,
diff --git a/arch/arm/mach-gemini/board-wbd111.c b/arch/arm/mach-gemini/board-wbd111.c
index 36538c15b3c4..8b88d50d4337 100644
--- a/arch/arm/mach-gemini/board-wbd111.c
+++ b/arch/arm/mach-gemini/board-wbd111.c
@@ -133,8 +133,6 @@ static void __init wbd111_init(void)
}
MACHINE_START(WBD111, "Wiliboard WBD-111")
- .phys_io = 0x7fffc000,
- .io_pg_offst = ((0xffffc000) >> 18) & 0xfffc,
.boot_params = 0x100,
.map_io = gemini_map_io,
.init_irq = gemini_init_irq,
diff --git a/arch/arm/mach-gemini/board-wbd222.c b/arch/arm/mach-gemini/board-wbd222.c
index ece8b4c65110..1eebcecd1c33 100644
--- a/arch/arm/mach-gemini/board-wbd222.c
+++ b/arch/arm/mach-gemini/board-wbd222.c
@@ -133,8 +133,6 @@ static void __init wbd222_init(void)
}
MACHINE_START(WBD222, "Wiliboard WBD-222")
- .phys_io = 0x7fffc000,
- .io_pg_offst = ((0xffffc000) >> 18) & 0xfffc,
.boot_params = 0x100,
.map_io = gemini_map_io,
.init_irq = gemini_init_irq,
diff --git a/arch/arm/mach-gemini/include/mach/debug-macro.S b/arch/arm/mach-gemini/include/mach/debug-macro.S
index ad477047069d..f40e006d296e 100644
--- a/arch/arm/mach-gemini/include/mach/debug-macro.S
+++ b/arch/arm/mach-gemini/include/mach/debug-macro.S
@@ -11,11 +11,9 @@
*/
#include <mach/hardware.h>
- .macro addruart, rx, tmp
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ MMU enabled?
- ldreq \rx, =GEMINI_UART_BASE @ physical
- ldrne \rx, =IO_ADDRESS(GEMINI_UART_BASE) @ virtual
+ .macro addruart, rp, rv
+ ldr \rp, =GEMINI_UART_BASE @ physical
+ ldr \rv, =IO_ADDRESS(GEMINI_UART_BASE) @ virtual
.endm
#define UART_SHIFT 2
diff --git a/arch/arm/mach-h720x/h7201-eval.c b/arch/arm/mach-h720x/h7201-eval.c
index 78be457dc324..79f0b896e446 100644
--- a/arch/arm/mach-h720x/h7201-eval.c
+++ b/arch/arm/mach-h720x/h7201-eval.c
@@ -30,8 +30,6 @@
MACHINE_START(H7201, "Hynix GMS30C7201")
/* Maintainer: Robert Schwebel, Pengutronix */
- .phys_io = 0x80000000,
- .io_pg_offst = ((0xf0000000) >> 18) & 0xfffc,
.boot_params = 0xc0001000,
.map_io = h720x_map_io,
.init_irq = h720x_init_irq,
diff --git a/arch/arm/mach-h720x/h7202-eval.c b/arch/arm/mach-h720x/h7202-eval.c
index 8c0ba99d683f..cc28b1efe047 100644
--- a/arch/arm/mach-h720x/h7202-eval.c
+++ b/arch/arm/mach-h720x/h7202-eval.c
@@ -72,8 +72,6 @@ static void __init init_eval_h7202(void)
MACHINE_START(H7202, "Hynix HMS30C7202")
/* Maintainer: Robert Schwebel, Pengutronix */
- .phys_io = 0x80000000,
- .io_pg_offst = ((0xf0000000) >> 18) & 0xfffc,
.boot_params = 0x40000100,
.map_io = h720x_map_io,
.init_irq = h7202_init_irq,
diff --git a/arch/arm/mach-h720x/include/mach/debug-macro.S b/arch/arm/mach-h720x/include/mach/debug-macro.S
index 27cafd12f033..c2093e835720 100644
--- a/arch/arm/mach-h720x/include/mach/debug-macro.S
+++ b/arch/arm/mach-h720x/include/mach/debug-macro.S
@@ -16,12 +16,10 @@
.equ io_virt, IO_VIRT
.equ io_phys, IO_PHYS
- .macro addruart, rx, tmp
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ MMU enabled?
- moveq \rx, #io_phys @ physical base address
- movne \rx, #io_virt @ virtual address
- add \rx, \rx, #0x00020000 @ UART1
+ .macro addruart, rp, rv
+ mov \rp, #0x00020000 @ UART1
+ add \rv, \rp, #io_virt @ virtual address
+ add \rp, \rp, #io_phys @ physical base address
.endm
.macro senduart,rd,rx
diff --git a/arch/arm/mach-h720x/include/mach/vmalloc.h b/arch/arm/mach-h720x/include/mach/vmalloc.h
index ff1460d6841b..a45915b88756 100644
--- a/arch/arm/mach-h720x/include/mach/vmalloc.h
+++ b/arch/arm/mach-h720x/include/mach/vmalloc.h
@@ -5,6 +5,6 @@
#ifndef __ARCH_ARM_VMALLOC_H
#define __ARCH_ARM_VMALLOC_H
-#define VMALLOC_END (PAGE_OFFSET + 0x10000000)
+#define VMALLOC_END 0xd0000000
#endif
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index c5c0369bb481..197f9e241cff 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -122,6 +122,7 @@ config MACH_CPUIMX27
select IMX_HAVE_PLATFORM_IMX_I2C
select IMX_HAVE_PLATFORM_IMX_UART
select IMX_HAVE_PLATFORM_MXC_NAND
+ select MXC_ULPI if USB_ULPI
help
Include support for Eukrea CPUIMX27 platform. This includes
specific configurations for the module and its peripherals.
@@ -146,8 +147,8 @@ choice
default MACH_EUKREA_MBIMX27_BASEBOARD
config MACH_EUKREA_MBIMX27_BASEBOARD
- prompt "Eukrea MBIMX27 development board"
- bool
+ bool "Eukrea MBIMX27 development board"
+ select IMX_HAVE_PLATFORM_IMX_SSI
select IMX_HAVE_PLATFORM_IMX_UART
select IMX_HAVE_PLATFORM_SPI_IMX
help
@@ -163,6 +164,15 @@ config MACH_MX27_3DS
Include support for MX27PDK platform. This includes specific
configurations for the board and its peripherals.
+config MACH_IMX27_VISSTRIM_M10
+ bool "Vista Silicon i.MX27 Visstrim_m10"
+ select IMX_HAVE_PLATFORM_IMX_I2C
+ select IMX_HAVE_PLATFORM_IMX_UART
+ help
+ Include support for Visstrim_m10 platform and its different variants.
+ This includes specific configurations for the board and its
+ peripherals.
+
config MACH_IMX27LITE
bool "LogicPD MX27 LITEKIT platform"
select IMX_HAVE_PLATFORM_IMX_UART
@@ -173,6 +183,7 @@ config MACH_IMX27LITE
config MACH_PCA100
bool "Phytec phyCARD-s (pca100)"
select IMX_HAVE_PLATFORM_IMX_I2C
+ select IMX_HAVE_PLATFORM_IMX_SSI
select IMX_HAVE_PLATFORM_IMX_UART
select IMX_HAVE_PLATFORM_MXC_NAND
select IMX_HAVE_PLATFORM_SPI_IMX
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index 46a9fdfbbd15..5582692bb176 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -27,6 +27,7 @@ obj-$(CONFIG_MACH_PCM038) += mach-pcm038.o
obj-$(CONFIG_MACH_PCM970_BASEBOARD) += pcm970-baseboard.o
obj-$(CONFIG_MACH_MX27_3DS) += mach-mx27_3ds.o
obj-$(CONFIG_MACH_IMX27LITE) += mach-imx27lite.o
+obj-$(CONFIG_MACH_IMX27_VISSTRIM_M10) += mach-imx27_visstrim_m10.o
obj-$(CONFIG_MACH_CPUIMX27) += mach-cpuimx27.o
obj-$(CONFIG_MACH_EUKREA_MBIMX27_BASEBOARD) += eukrea_mbimx27-baseboard.o
obj-$(CONFIG_MACH_PCA100) += mach-pca100.o
diff --git a/arch/arm/mach-imx/clock-imx1.c b/arch/arm/mach-imx/clock-imx1.c
index c05096c38301..daca30b2d5b1 100644
--- a/arch/arm/mach-imx/clock-imx1.c
+++ b/arch/arm/mach-imx/clock-imx1.c
@@ -592,7 +592,7 @@ static struct clk_lookup lookups[] __initdata = {
_REGISTER_CLOCK("imx-uart.1", NULL, uart_clk)
_REGISTER_CLOCK("imx-uart.2", NULL, uart_clk)
_REGISTER_CLOCK("imx-i2c.0", NULL, i2c_clk)
- _REGISTER_CLOCK("spi_imx.0", NULL, spi_clk)
+ _REGISTER_CLOCK("imx1-cspi.0", NULL, spi_clk)
_REGISTER_CLOCK("imx-mmc.0", NULL, sdhc_clk)
_REGISTER_CLOCK("imx-fb.0", NULL, lcdc_clk)
_REGISTER_CLOCK(NULL, "mshc", mshc_clk)
diff --git a/arch/arm/mach-imx/clock-imx21.c b/arch/arm/mach-imx/clock-imx21.c
index bb419ef4d133..cf15ea516a72 100644
--- a/arch/arm/mach-imx/clock-imx21.c
+++ b/arch/arm/mach-imx/clock-imx21.c
@@ -1172,9 +1172,9 @@ static struct clk_lookup lookups[] = {
_REGISTER_CLOCK(NULL, "pwm", pwm_clk[0])
_REGISTER_CLOCK(NULL, "sdhc1", sdhc_clk[0])
_REGISTER_CLOCK(NULL, "sdhc2", sdhc_clk[1])
- _REGISTER_CLOCK(NULL, "cspi1", cspi_clk[0])
- _REGISTER_CLOCK(NULL, "cspi2", cspi_clk[1])
- _REGISTER_CLOCK(NULL, "cspi3", cspi_clk[2])
+ _REGISTER_CLOCK("imx21-cspi.0", NULL, cspi_clk[0])
+ _REGISTER_CLOCK("imx21-cspi.1", NULL, cspi_clk[1])
+ _REGISTER_CLOCK("imx21-cspi.2", NULL, cspi_clk[2])
_REGISTER_CLOCK("imx-fb.0", NULL, lcdc_clk[0])
_REGISTER_CLOCK(NULL, "csi", csi_clk[0])
_REGISTER_CLOCK("imx21-hcd.0", NULL, usb_clk[0])
diff --git a/arch/arm/mach-imx/clock-imx27.c b/arch/arm/mach-imx/clock-imx27.c
index 5a1aa15c8a16..98a25bada783 100644
--- a/arch/arm/mach-imx/clock-imx27.c
+++ b/arch/arm/mach-imx/clock-imx27.c
@@ -594,27 +594,27 @@ DEFINE_CLOCK(uart2_clk1, 0, PCCR1, 30, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(uart1_clk1, 0, PCCR1, 31, NULL, NULL, &ipg_clk);
/* Clocks we cannot directly gate, but drivers need their rates */
-DEFINE_CLOCK(cspi1_clk, 0, 0, 0, NULL, &cspi1_clk1, &per2_clk);
-DEFINE_CLOCK(cspi2_clk, 1, 0, 0, NULL, &cspi2_clk1, &per2_clk);
-DEFINE_CLOCK(cspi3_clk, 2, 0, 0, NULL, &cspi13_clk1, &per2_clk);
-DEFINE_CLOCK(sdhc1_clk, 0, 0, 0, NULL, &sdhc1_clk1, &per2_clk);
-DEFINE_CLOCK(sdhc2_clk, 1, 0, 0, NULL, &sdhc2_clk1, &per2_clk);
-DEFINE_CLOCK(sdhc3_clk, 2, 0, 0, NULL, &sdhc3_clk1, &per2_clk);
-DEFINE_CLOCK(pwm_clk, 0, 0, 0, NULL, &pwm_clk1, &per1_clk);
-DEFINE_CLOCK(gpt1_clk, 0, 0, 0, NULL, &gpt1_clk1, &per1_clk);
-DEFINE_CLOCK(gpt2_clk, 1, 0, 0, NULL, &gpt2_clk1, &per1_clk);
-DEFINE_CLOCK(gpt3_clk, 2, 0, 0, NULL, &gpt3_clk1, &per1_clk);
-DEFINE_CLOCK(gpt4_clk, 3, 0, 0, NULL, &gpt4_clk1, &per1_clk);
-DEFINE_CLOCK(gpt5_clk, 4, 0, 0, NULL, &gpt5_clk1, &per1_clk);
-DEFINE_CLOCK(gpt6_clk, 5, 0, 0, NULL, &gpt6_clk1, &per1_clk);
-DEFINE_CLOCK(uart1_clk, 0, 0, 0, NULL, &uart1_clk1, &per1_clk);
-DEFINE_CLOCK(uart2_clk, 1, 0, 0, NULL, &uart2_clk1, &per1_clk);
-DEFINE_CLOCK(uart3_clk, 2, 0, 0, NULL, &uart3_clk1, &per1_clk);
-DEFINE_CLOCK(uart4_clk, 3, 0, 0, NULL, &uart4_clk1, &per1_clk);
-DEFINE_CLOCK(uart5_clk, 4, 0, 0, NULL, &uart5_clk1, &per1_clk);
-DEFINE_CLOCK(uart6_clk, 5, 0, 0, NULL, &uart6_clk1, &per1_clk);
-DEFINE_CLOCK1(lcdc_clk, 0, 0, 0, parent, &lcdc_clk1, &per3_clk);
-DEFINE_CLOCK1(csi_clk, 0, 0, 0, parent, &csi_clk1, &per4_clk);
+DEFINE_CLOCK(cspi1_clk, 0, NULL, 0, NULL, &cspi1_clk1, &per2_clk);
+DEFINE_CLOCK(cspi2_clk, 1, NULL, 0, NULL, &cspi2_clk1, &per2_clk);
+DEFINE_CLOCK(cspi3_clk, 2, NULL, 0, NULL, &cspi13_clk1, &per2_clk);
+DEFINE_CLOCK(sdhc1_clk, 0, NULL, 0, NULL, &sdhc1_clk1, &per2_clk);
+DEFINE_CLOCK(sdhc2_clk, 1, NULL, 0, NULL, &sdhc2_clk1, &per2_clk);
+DEFINE_CLOCK(sdhc3_clk, 2, NULL, 0, NULL, &sdhc3_clk1, &per2_clk);
+DEFINE_CLOCK(pwm_clk, 0, NULL, 0, NULL, &pwm_clk1, &per1_clk);
+DEFINE_CLOCK(gpt1_clk, 0, NULL, 0, NULL, &gpt1_clk1, &per1_clk);
+DEFINE_CLOCK(gpt2_clk, 1, NULL, 0, NULL, &gpt2_clk1, &per1_clk);
+DEFINE_CLOCK(gpt3_clk, 2, NULL, 0, NULL, &gpt3_clk1, &per1_clk);
+DEFINE_CLOCK(gpt4_clk, 3, NULL, 0, NULL, &gpt4_clk1, &per1_clk);
+DEFINE_CLOCK(gpt5_clk, 4, NULL, 0, NULL, &gpt5_clk1, &per1_clk);
+DEFINE_CLOCK(gpt6_clk, 5, NULL, 0, NULL, &gpt6_clk1, &per1_clk);
+DEFINE_CLOCK(uart1_clk, 0, NULL, 0, NULL, &uart1_clk1, &per1_clk);
+DEFINE_CLOCK(uart2_clk, 1, NULL, 0, NULL, &uart2_clk1, &per1_clk);
+DEFINE_CLOCK(uart3_clk, 2, NULL, 0, NULL, &uart3_clk1, &per1_clk);
+DEFINE_CLOCK(uart4_clk, 3, NULL, 0, NULL, &uart4_clk1, &per1_clk);
+DEFINE_CLOCK(uart5_clk, 4, NULL, 0, NULL, &uart5_clk1, &per1_clk);
+DEFINE_CLOCK(uart6_clk, 5, NULL, 0, NULL, &uart6_clk1, &per1_clk);
+DEFINE_CLOCK1(lcdc_clk, 0, NULL, 0, parent, &lcdc_clk1, &per3_clk);
+DEFINE_CLOCK1(csi_clk, 0, NULL, 0, parent, &csi_clk1, &per4_clk);
#define _REGISTER_CLOCK(d, n, c) \
{ \
@@ -640,9 +640,9 @@ static struct clk_lookup lookups[] = {
_REGISTER_CLOCK("mxc-mmc.0", NULL, sdhc1_clk)
_REGISTER_CLOCK("mxc-mmc.1", NULL, sdhc2_clk)
_REGISTER_CLOCK("mxc-mmc.2", NULL, sdhc3_clk)
- _REGISTER_CLOCK("spi_imx.0", NULL, cspi1_clk)
- _REGISTER_CLOCK("spi_imx.1", NULL, cspi2_clk)
- _REGISTER_CLOCK("spi_imx.2", NULL, cspi3_clk)
+ _REGISTER_CLOCK("imx27-cspi.0", NULL, cspi1_clk)
+ _REGISTER_CLOCK("imx27-cspi.1", NULL, cspi2_clk)
+ _REGISTER_CLOCK("imx27-cspi.2", NULL, cspi3_clk)
_REGISTER_CLOCK("imx-fb.0", NULL, lcdc_clk)
_REGISTER_CLOCK("mx2-camera.0", NULL, csi_clk)
_REGISTER_CLOCK("fsl-usb2-udc", "usb", usb_clk)
diff --git a/arch/arm/mach-imx/devices-imx1.h b/arch/arm/mach-imx/devices-imx1.h
index a8d94f078196..81979486218e 100644
--- a/arch/arm/mach-imx/devices-imx1.h
+++ b/arch/arm/mach-imx/devices-imx1.h
@@ -9,10 +9,12 @@
#include <mach/mx1.h>
#include <mach/devices-common.h>
-#define imx1_add_i2c_imx(pdata) \
- imx_add_imx_i2c(0, MX1_I2C_BASE_ADDR, SZ_4K, MX1_INT_I2C, pdata)
+extern const struct imx_imx_i2c_data imx1_imx_i2c_data __initconst;
+#define imx1_add_imx_i2c(pdata) \
+ imx_add_imx_i2c(&imx1_imx_i2c_data, pdata)
-#define imx1_add_imx_uart0(pdata) \
- imx_add_imx_uart_3irq(0, MX1_UART1_BASE_ADDR, 0xd0, MX1_INT_UART1RX, MX1_INT_UART1TX, MX1_INT_UART1RTS, pdata)
-#define imx1_add_imx_uart1(pdata) \
- imx_add_imx_uart_3irq(0, MX1_UART2_BASE_ADDR, 0xd0, MX1_INT_UART2RX, MX1_INT_UART2TX, MX1_INT_UART2RTS, pdata)
+extern const struct imx_imx_uart_3irq_data imx1_imx_uart_data[] __initconst;
+#define imx1_add_imx_uart(id, pdata) \
+ imx_add_imx_uart_3irq(&imx1_imx_uart_data[id], pdata)
+#define imx1_add_imx_uart0(pdata) imx1_add_imx_uart(0, pdata)
+#define imx1_add_imx_uart1(pdata) imx1_add_imx_uart(1, pdata)
diff --git a/arch/arm/mach-imx/devices-imx21.h b/arch/arm/mach-imx/devices-imx21.h
index 42788e99d127..d189039749b0 100644
--- a/arch/arm/mach-imx/devices-imx21.h
+++ b/arch/arm/mach-imx/devices-imx21.h
@@ -9,22 +9,28 @@
#include <mach/mx21.h>
#include <mach/devices-common.h>
-#define imx21_add_i2c_imx(pdata) \
- imx_add_imx_i2c(0, MX2x_I2C_BASE_ADDR, SZ_4K, MX2x_INT_I2C, pdata)
+extern const struct imx_imx_i2c_data imx21_imx_i2c_data __initconst;
+#define imx21_add_imx_i2c(pdata) \
+ imx_add_imx_i2c(&imx21_imx_i2c_data, pdata)
-#define imx21_add_imx_uart0(pdata) \
- imx_add_imx_uart_1irq(0, MX21_UART1_BASE_ADDR, SZ_4K, MX21_INT_UART1, pdata)
-#define imx21_add_imx_uart1(pdata) \
- imx_add_imx_uart_1irq(1, MX21_UART2_BASE_ADDR, SZ_4K, MX21_INT_UART2, pdata)
-#define imx21_add_imx_uart2(pdata) \
- imx_add_imx_uart_1irq(2, MX21_UART3_BASE_ADDR, SZ_4K, MX21_INT_UART3, pdata)
-#define imx21_add_imx_uart3(pdata) \
- imx_add_imx_uart_1irq(3, MX21_UART4_BASE_ADDR, SZ_4K, MX21_INT_UART4, pdata)
+extern const struct imx_imx_ssi_data imx21_imx_ssi_data[] __initconst;
+#define imx21_add_imx_ssi(id, pdata) \
+ imx_add_imx_ssi(&imx21_imx_ssi_data[id], pdata)
+extern const struct imx_imx_uart_1irq_data imx21_imx_uart_data[] __initconst;
+#define imx21_add_imx_uart(id, pdata) \
+ imx_add_imx_uart_1irq(&imx21_imx_uart_data[id], pdata)
+#define imx21_add_imx_uart0(pdata) imx21_add_imx_uart(0, pdata)
+#define imx21_add_imx_uart1(pdata) imx21_add_imx_uart(1, pdata)
+#define imx21_add_imx_uart2(pdata) imx21_add_imx_uart(2, pdata)
+#define imx21_add_imx_uart3(pdata) imx21_add_imx_uart(3, pdata)
+
+extern const struct imx_mxc_nand_data imx21_mxc_nand_data __initconst;
#define imx21_add_mxc_nand(pdata) \
- imx_add_mxc_nand_v1(MX21_NFC_BASE_ADDR, MX21_INT_NANDFC, pdata)
+ imx_add_mxc_nand(&imx21_mxc_nand_data, pdata)
-#define imx21_add_spi_imx0(pdata) \
- imx_add_spi_imx(0, MX21_CSPI1_BASE_ADDR, SZ_4K, MX21_INT_CSPI1, pdata)
-#define imx21_add_spi_imx1(pdata) \
- imx_add_spi_imx(1, MX21_CSPI2_BASE_ADDR, SZ_4K, MX21_INT_CSPI2, pdata)
+extern const struct imx_spi_imx_data imx21_cspi_data[] __initconst;
+#define imx21_add_cspi(id, pdata) \
+ imx_add_spi_imx(&imx21_cspi_data[id], pdata)
+#define imx21_add_spi_imx0(pdata) imx21_add_cspi(0, pdata)
+#define imx21_add_spi_imx1(pdata) imx21_add_cspi(1, pdata)
diff --git a/arch/arm/mach-imx/devices-imx27.h b/arch/arm/mach-imx/devices-imx27.h
index 65e7bb7ec2e8..7011690364f2 100644
--- a/arch/arm/mach-imx/devices-imx27.h
+++ b/arch/arm/mach-imx/devices-imx27.h
@@ -9,30 +9,35 @@
#include <mach/mx27.h>
#include <mach/devices-common.h>
-#define imx27_add_i2c_imx0(pdata) \
- imx_add_imx_i2c(0, MX27_I2C1_BASE_ADDR, SZ_4K, MX27_INT_I2C1, pdata)
-#define imx27_add_i2c_imx1(pdata) \
- imx_add_imx_i2c(1, MX27_I2C2_BASE_ADDR, SZ_4K, MX27_INT_I2C2, pdata)
+extern const struct imx_fec_data imx27_fec_data __initconst;
+#define imx27_add_fec(pdata) \
+ imx_add_fec(&imx27_fec_data, pdata)
-#define imx27_add_imx_uart0(pdata) \
- imx_add_imx_uart_1irq(0, MX27_UART1_BASE_ADDR, SZ_4K, MX27_INT_UART1, pdata)
-#define imx27_add_imx_uart1(pdata) \
- imx_add_imx_uart_1irq(1, MX27_UART2_BASE_ADDR, SZ_4K, MX27_INT_UART2, pdata)
-#define imx27_add_imx_uart2(pdata) \
- imx_add_imx_uart_1irq(2, MX27_UART3_BASE_ADDR, SZ_4K, MX27_INT_UART3, pdata)
-#define imx27_add_imx_uart3(pdata) \
- imx_add_imx_uart_1irq(3, MX27_UART4_BASE_ADDR, SZ_4K, MX27_INT_UART4, pdata)
-#define imx27_add_imx_uart4(pdata) \
- imx_add_imx_uart_1irq(4, MX27_UART5_BASE_ADDR, SZ_4K, MX27_INT_UART5, pdata)
-#define imx27_add_imx_uart5(pdata) \
- imx_add_imx_uart_1irq(5, MX27_UART6_BASE_ADDR, SZ_4K, MX27_INT_UART6, pdata)
+extern const struct imx_imx_i2c_data imx27_imx_i2c_data[] __initconst;
+#define imx27_add_imx_i2c(id, pdata) \
+ imx_add_imx_i2c(&imx27_imx_i2c_data[id], pdata)
+extern const struct imx_imx_ssi_data imx27_imx_ssi_data[] __initconst;
+#define imx27_add_imx_ssi(id, pdata) \
+ imx_add_imx_ssi(&imx27_imx_ssi_data[id], pdata)
+
+extern const struct imx_imx_uart_1irq_data imx27_imx_uart_data[] __initconst;
+#define imx27_add_imx_uart(id, pdata) \
+ imx_add_imx_uart_1irq(&imx27_imx_uart_data[id], pdata)
+#define imx27_add_imx_uart0(pdata) imx27_add_imx_uart(0, pdata)
+#define imx27_add_imx_uart1(pdata) imx27_add_imx_uart(1, pdata)
+#define imx27_add_imx_uart2(pdata) imx27_add_imx_uart(2, pdata)
+#define imx27_add_imx_uart3(pdata) imx27_add_imx_uart(3, pdata)
+#define imx27_add_imx_uart4(pdata) imx27_add_imx_uart(4, pdata)
+#define imx27_add_imx_uart5(pdata) imx27_add_imx_uart(5, pdata)
+
+extern const struct imx_mxc_nand_data imx27_mxc_nand_data __initconst;
#define imx27_add_mxc_nand(pdata) \
- imx_add_mxc_nand_v1(MX27_NFC_BASE_ADDR, MX27_INT_NANDFC, pdata)
+ imx_add_mxc_nand(&imx27_mxc_nand_data, pdata)
-#define imx27_add_spi_imx0(pdata) \
- imx_add_spi_imx(0, MX27_CSPI1_BASE_ADDR, SZ_4K, MX27_INT_CSPI1, pdata)
-#define imx27_add_spi_imx1(pdata) \
- imx_add_spi_imx(1, MX27_CSPI2_BASE_ADDR, SZ_4K, MX27_INT_CSPI2, pdata)
-#define imx27_add_spi_imx2(pdata) \
- imx_add_spi_imx(2, MX27_CSPI3_BASE_ADDR, SZ_4K, MX27_INT_CSPI3, pdata)
+extern const struct imx_spi_imx_data imx27_cspi_data[] __initconst;
+#define imx27_add_cspi(id, pdata) \
+ imx_add_spi_imx(&imx27_cspi_data[id], pdata)
+#define imx27_add_spi_imx0(pdata) imx27_add_cspi(0, pdata)
+#define imx27_add_spi_imx1(pdata) imx27_add_cspi(1, pdata)
+#define imx27_add_spi_imx2(pdata) imx27_add_cspi(2, pdata)
diff --git a/arch/arm/mach-imx/devices.c b/arch/arm/mach-imx/devices.c
index 9c271a752b84..fba5047de8b1 100644
--- a/arch/arm/mach-imx/devices.c
+++ b/arch/arm/mach-imx/devices.c
@@ -314,27 +314,6 @@ struct platform_device mxc_fb_device = {
},
};
-#ifdef CONFIG_MACH_MX27
-static struct resource mxc_fec_resources[] = {
- {
- .start = MX27_FEC_BASE_ADDR,
- .end = MX27_FEC_BASE_ADDR + SZ_4K - 1,
- .flags = IORESOURCE_MEM,
- }, {
- .start = MX27_INT_FEC,
- .end = MX27_INT_FEC,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-struct platform_device mxc_fec_device = {
- .name = "fec",
- .id = 0,
- .num_resources = ARRAY_SIZE(mxc_fec_resources),
- .resource = mxc_fec_resources,
-};
-#endif
-
static struct resource mxc_pwm_resources[] = {
{
.start = MX2x_PWM_BASE_ADDR,
@@ -480,41 +459,6 @@ struct platform_device mxc_usbh2 = {
};
#endif
-#define DEFINE_IMX_SSI_DMARES(_name, ssin, suffix) \
- { \
- .name = _name, \
- .start = MX2x_DMA_REQ_SSI ## ssin ## _ ## suffix, \
- .end = MX2x_DMA_REQ_SSI ## ssin ## _ ## suffix, \
- .flags = IORESOURCE_DMA, \
- }
-
-#define DEFINE_IMX_SSI_DEVICE(n, ssin, baseaddr, irq) \
- static struct resource imx_ssi_resources ## n[] = { \
- { \
- .start = MX2x_SSI ## ssin ## _BASE_ADDR, \
- .end = MX2x_SSI ## ssin ## _BASE_ADDR + 0x6f, \
- .flags = IORESOURCE_MEM, \
- }, { \
- .start = MX2x_INT_SSI1, \
- .end = MX2x_INT_SSI1, \
- .flags = IORESOURCE_IRQ, \
- }, \
- DEFINE_IMX_SSI_DMARES("tx0", ssin, TX0), \
- DEFINE_IMX_SSI_DMARES("rx0", ssin, RX0), \
- DEFINE_IMX_SSI_DMARES("tx1", ssin, TX1), \
- DEFINE_IMX_SSI_DMARES("rx1", ssin, RX1), \
- }; \
- \
- struct platform_device imx_ssi_device ## n = { \
- .name = "imx-ssi", \
- .id = n, \
- .num_resources = ARRAY_SIZE(imx_ssi_resources ## n), \
- .resource = imx_ssi_resources ## n, \
- }
-
-DEFINE_IMX_SSI_DEVICE(0, 1, MX2x_SSI1_BASE_ADDR, MX2x_INT_SSI1);
-DEFINE_IMX_SSI_DEVICE(1, 2, MX2x_SSI1_BASE_ADDR, MX2x_INT_SSI1);
-
/* GPIO port description */
#define DEFINE_MXC_GPIO_PORT_IRQ(SOC, n, _irq) \
{ \
diff --git a/arch/arm/mach-imx/devices.h b/arch/arm/mach-imx/devices.h
index efd4527506a5..807f02a031c9 100644
--- a/arch/arm/mach-imx/devices.h
+++ b/arch/arm/mach-imx/devices.h
@@ -16,7 +16,6 @@ extern struct platform_device mxc_gpt5;
extern struct platform_device mxc_wdt;
extern struct platform_device mxc_w1_master_device;
extern struct platform_device mxc_fb_device;
-extern struct platform_device mxc_fec_device;
extern struct platform_device mxc_pwm_device;
extern struct platform_device mxc_sdhc_device0;
extern struct platform_device mxc_sdhc_device1;
@@ -26,7 +25,5 @@ extern struct platform_device mxc_otg_host;
extern struct platform_device mxc_usbh1;
extern struct platform_device mxc_usbh2;
extern struct platform_device mx21_usbhc_device;
-extern struct platform_device imx_ssi_device0;
-extern struct platform_device imx_ssi_device1;
extern struct platform_device imx_kpp_device;
#endif
diff --git a/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c b/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c
index 4edc5f439201..026263c665ca 100644
--- a/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c
+++ b/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c
@@ -36,13 +36,12 @@
#include <mach/hardware.h>
#include <mach/mmc.h>
#include <mach/spi.h>
-#include <mach/ssi.h>
#include <mach/audmux.h>
#include "devices-imx27.h"
#include "devices.h"
-static int eukrea_mbimx27_pins[] = {
+static const int eukrea_mbimx27_pins[] __initconst = {
/* UART2 */
PE3_PF_UART2_CTS,
PE4_PF_UART2_RTS,
@@ -311,7 +310,8 @@ static struct imxmmc_platform_data sdhc_pdata = {
.dat3_card_detect = 1,
};
-struct imx_ssi_platform_data eukrea_mbimx27_ssi_pdata = {
+static const
+struct imx_ssi_platform_data eukrea_mbimx27_ssi_pdata __initconst = {
.flags = IMX_SSI_DMA | IMX_SSI_USE_I2S_SLAVE,
};
@@ -357,7 +357,7 @@ void __init eukrea_mbimx27_baseboard_init(void)
i2c_register_board_info(0, eukrea_mbimx27_i2c_devices,
ARRAY_SIZE(eukrea_mbimx27_i2c_devices));
- mxc_register_device(&imx_ssi_device0, &eukrea_mbimx27_ssi_pdata);
+ imx27_add_imx_ssi(0, &eukrea_mbimx27_ssi_pdata);
#if defined(CONFIG_TOUCHSCREEN_ADS7846) \
|| defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
diff --git a/arch/arm/mach-imx/mach-cpuimx27.c b/arch/arm/mach-imx/mach-cpuimx27.c
index 339150ab0ea5..745ee60fb068 100644
--- a/arch/arm/mach-imx/mach-cpuimx27.c
+++ b/arch/arm/mach-imx/mach-cpuimx27.c
@@ -46,7 +46,7 @@
#include "devices-imx27.h"
#include "devices.h"
-static int eukrea_cpuimx27_pins[] = {
+static const int eukrea_cpuimx27_pins[] __initconst = {
/* UART1 */
PE12_PF_UART1_TXD,
PE13_PF_UART1_RXD,
@@ -157,7 +157,6 @@ cpuimx27_nand_board_info __initconst = {
static struct platform_device *platform_devices[] __initdata = {
&eukrea_cpuimx27_nor_mtd_device,
- &mxc_fec_device,
&mxc_wdt,
&mxc_w1_master_device,
};
@@ -259,8 +258,9 @@ static void __init eukrea_cpuimx27_init(void)
i2c_register_board_info(0, eukrea_cpuimx27_i2c_devices,
ARRAY_SIZE(eukrea_cpuimx27_i2c_devices));
- imx27_add_i2c_imx1(&cpuimx27_i2c1_data);
+ imx27_add_imx_i2c(0, &cpuimx27_i2c1_data);
+ imx27_add_fec(NULL);
platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
#if defined(CONFIG_MACH_EUKREA_CPUIMX27_USESDHC2)
@@ -307,8 +307,6 @@ static struct sys_timer eukrea_cpuimx27_timer = {
};
MACHINE_START(CPUIMX27, "EUKREA CPUIMX27")
- .phys_io = MX27_AIPI_BASE_ADDR,
- .io_pg_offst = ((MX27_AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc,
.boot_params = MX27_PHYS_OFFSET + 0x100,
.map_io = mx27_map_io,
.init_irq = mx27_init_irq,
diff --git a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
new file mode 100644
index 000000000000..59716fab586d
--- /dev/null
+++ b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
@@ -0,0 +1,261 @@
+/*
+ * mach-imx27_visstrim_m10.c
+ *
+ * Copyright 2010 Javier Martin <javier.martin@vista-silicon.com>
+ *
+ * Based on mach-pcm038.c, mach-pca100.c, mach-mx27ads.c and others.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/i2c.h>
+#include <linux/i2c/pca953x.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
+#include <linux/gpio.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/common.h>
+#include <mach/mmc.h>
+#include <mach/iomux.h>
+#include <mach/mxc_ehci.h>
+
+#include "devices-imx27.h"
+#include "devices.h"
+
+#define OTG_PHY_CS_GPIO (GPIO_PORTF + 17)
+#define SDHC1_IRQ IRQ_GPIOB(25)
+
+static const int visstrim_m10_pins[] __initconst = {
+ /* UART1 (console) */
+ PE12_PF_UART1_TXD,
+ PE13_PF_UART1_RXD,
+ PE14_PF_UART1_CTS,
+ PE15_PF_UART1_RTS,
+ /* FEC */
+ PD0_AIN_FEC_TXD0,
+ PD1_AIN_FEC_TXD1,
+ PD2_AIN_FEC_TXD2,
+ PD3_AIN_FEC_TXD3,
+ PD4_AOUT_FEC_RX_ER,
+ PD5_AOUT_FEC_RXD1,
+ PD6_AOUT_FEC_RXD2,
+ PD7_AOUT_FEC_RXD3,
+ PD8_AF_FEC_MDIO,
+ PD9_AIN_FEC_MDC,
+ PD10_AOUT_FEC_CRS,
+ PD11_AOUT_FEC_TX_CLK,
+ PD12_AOUT_FEC_RXD0,
+ PD13_AOUT_FEC_RX_DV,
+ PD14_AOUT_FEC_RX_CLK,
+ PD15_AOUT_FEC_COL,
+ PD16_AIN_FEC_TX_ER,
+ PF23_AIN_FEC_TX_EN,
+ /* SDHC1 */
+ PE18_PF_SD1_D0,
+ PE19_PF_SD1_D1,
+ PE20_PF_SD1_D2,
+ PE21_PF_SD1_D3,
+ PE22_PF_SD1_CMD,
+ PE23_PF_SD1_CLK,
+ /* Both I2Cs */
+ PD17_PF_I2C_DATA,
+ PD18_PF_I2C_CLK,
+ PC5_PF_I2C2_SDA,
+ PC6_PF_I2C2_SCL,
+ /* USB OTG */
+ OTG_PHY_CS_GPIO | GPIO_GPIO | GPIO_OUT,
+ PC9_PF_USBOTG_DATA0,
+ PC11_PF_USBOTG_DATA1,
+ PC10_PF_USBOTG_DATA2,
+ PC13_PF_USBOTG_DATA3,
+ PC12_PF_USBOTG_DATA4,
+ PC7_PF_USBOTG_DATA5,
+ PC8_PF_USBOTG_DATA6,
+ PE25_PF_USBOTG_DATA7,
+ PE24_PF_USBOTG_CLK,
+ PE2_PF_USBOTG_DIR,
+ PE0_PF_USBOTG_NXT,
+ PE1_PF_USBOTG_STP,
+ PB23_PF_USB_PWR,
+ PB24_PF_USB_OC,
+};
+
+/* GPIOs used as events for applications */
+static struct gpio_keys_button visstrim_gpio_keys[] = {
+ {
+ .type = EV_KEY,
+ .code = KEY_RESTART,
+ .gpio = (GPIO_PORTC + 15),
+ .desc = "Default config",
+ .active_low = 0,
+ .wakeup = 1,
+ },
+ {
+ .type = EV_KEY,
+ .code = KEY_RECORD,
+ .gpio = (GPIO_PORTF + 14),
+ .desc = "Record",
+ .active_low = 0,
+ .wakeup = 1,
+ },
+ {
+ .type = EV_KEY,
+ .code = KEY_STOP,
+ .gpio = (GPIO_PORTF + 13),
+ .desc = "Stop",
+ .active_low = 0,
+ .wakeup = 1,
+ }
+};
+
+static struct gpio_keys_platform_data visstrim_gpio_keys_platform_data = {
+ .buttons = visstrim_gpio_keys,
+ .nbuttons = ARRAY_SIZE(visstrim_gpio_keys),
+};
+
+static struct platform_device visstrim_gpio_keys_device = {
+ .name = "gpio-keys",
+ .id = -1,
+ .dev = {
+ .platform_data = &visstrim_gpio_keys_platform_data,
+ },
+};
+
+/* Visstrim_SM10 has a microSD slot connected to sdhc1 */
+static int visstrim_m10_sdhc1_init(struct device *dev,
+ irq_handler_t detect_irq, void *data)
+{
+ int ret;
+
+ ret = request_irq(SDHC1_IRQ, detect_irq, IRQF_TRIGGER_FALLING,
+ "mmc-detect", data);
+ return ret;
+}
+
+static void visstrim_m10_sdhc1_exit(struct device *dev, void *data)
+{
+ free_irq(SDHC1_IRQ, data);
+}
+
+static struct imxmmc_platform_data visstrim_m10_sdhc_pdata = {
+ .init = visstrim_m10_sdhc1_init,
+ .exit = visstrim_m10_sdhc1_exit,
+};
+
+/* Visstrim_SM10 NOR flash */
+static struct physmap_flash_data visstrim_m10_flash_data = {
+ .width = 2,
+};
+
+static struct resource visstrim_m10_flash_resource = {
+ .start = 0xc0000000,
+ .end = 0xc0000000 + SZ_64M - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device visstrim_m10_nor_mtd_device = {
+ .name = "physmap-flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &visstrim_m10_flash_data,
+ },
+ .num_resources = 1,
+ .resource = &visstrim_m10_flash_resource,
+};
+
+static struct platform_device *platform_devices[] __initdata = {
+ &visstrim_gpio_keys_device,
+ &visstrim_m10_nor_mtd_device,
+};
+
+/* Visstrim_M10 uses UART0 as console */
+static const struct imxuart_platform_data uart_pdata __initconst = {
+ .flags = IMXUART_HAVE_RTSCTS,
+};
+
+/* I2C */
+static const struct imxi2c_platform_data visstrim_m10_i2c_data __initconst = {
+ .bitrate = 100000,
+};
+
+static struct pca953x_platform_data visstrim_m10_pca9555_pdata = {
+ .gpio_base = 240, /* After MX27 internal GPIOs */
+ .invert = 0,
+};
+
+static struct i2c_board_info visstrim_m10_i2c_devices[] = {
+ {
+ I2C_BOARD_INFO("pca9555", 0x20),
+ .platform_data = &visstrim_m10_pca9555_pdata,
+ },
+};
+
+/* USB OTG */
+static int otg_phy_init(struct platform_device *pdev)
+{
+ gpio_set_value(OTG_PHY_CS_GPIO, 0);
+ return 0;
+}
+
+static struct mxc_usbh_platform_data visstrim_m10_usbotg_pdata = {
+ .init = otg_phy_init,
+ .portsc = MXC_EHCI_MODE_ULPI | MXC_EHCI_UTMI_8BIT,
+ .flags = MXC_EHCI_POWER_PINS_ENABLED,
+};
+
+static void __init visstrim_m10_board_init(void)
+{
+ int ret;
+
+ ret = mxc_gpio_setup_multiple_pins(visstrim_m10_pins,
+ ARRAY_SIZE(visstrim_m10_pins), "VISSTRIM_M10");
+ if (ret)
+ pr_err("Failed to setup pins (%d)\n", ret);
+
+ imx27_add_imx_uart0(&uart_pdata);
+
+ i2c_register_board_info(0, visstrim_m10_i2c_devices,
+ ARRAY_SIZE(visstrim_m10_i2c_devices));
+ imx27_add_imx_i2c(0, &visstrim_m10_i2c_data);
+ imx27_add_imx_i2c(1, &visstrim_m10_i2c_data);
+ mxc_register_device(&mxc_sdhc_device0, &visstrim_m10_sdhc_pdata);
+ mxc_register_device(&mxc_otg_host, &visstrim_m10_usbotg_pdata);
+ imx27_add_fec(NULL);
+ platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+}
+
+static void __init visstrim_m10_timer_init(void)
+{
+ mx27_clocks_init((unsigned long)25000000);
+}
+
+static struct sys_timer visstrim_m10_timer = {
+ .init = visstrim_m10_timer_init,
+};
+
+MACHINE_START(IMX27_VISSTRIM_M10, "Vista Silicon Visstrim_M10")
+ .boot_params = MX27_PHYS_OFFSET + 0x100,
+ .map_io = mx27_map_io,
+ .init_irq = mx27_init_irq,
+ .init_machine = visstrim_m10_board_init,
+ .timer = &visstrim_m10_timer,
+MACHINE_END
diff --git a/arch/arm/mach-imx/mach-imx27lite.c b/arch/arm/mach-imx/mach-imx27lite.c
index 22a2b5d91213..bbdbc75127d3 100644
--- a/arch/arm/mach-imx/mach-imx27lite.c
+++ b/arch/arm/mach-imx/mach-imx27lite.c
@@ -27,7 +27,7 @@
#include "devices-imx27.h"
#include "devices.h"
-static unsigned int mx27lite_pins[] = {
+static const int mx27lite_pins[] __initconst = {
/* UART1 */
PE12_PF_UART1_TXD,
PE13_PF_UART1_RXD,
@@ -58,16 +58,12 @@ static const struct imxuart_platform_data uart_pdata __initconst = {
.flags = IMXUART_HAVE_RTSCTS,
};
-static struct platform_device *platform_devices[] __initdata = {
- &mxc_fec_device,
-};
-
static void __init mx27lite_init(void)
{
mxc_gpio_setup_multiple_pins(mx27lite_pins, ARRAY_SIZE(mx27lite_pins),
"imx27lite");
imx27_add_imx_uart0(&uart_pdata);
- platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+ imx27_add_fec(NULL);
}
static void __init mx27lite_timer_init(void)
@@ -80,8 +76,6 @@ static struct sys_timer mx27lite_timer = {
};
MACHINE_START(IMX27LITE, "LogicPD i.MX27LITE")
- .phys_io = MX27_AIPI_BASE_ADDR,
- .io_pg_offst = ((MX27_AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc,
.boot_params = MX27_PHYS_OFFSET + 0x100,
.map_io = mx27_map_io,
.init_irq = mx27_init_irq,
diff --git a/arch/arm/mach-imx/mach-mx1ads.c b/arch/arm/mach-imx/mach-mx1ads.c
index 77a760cfadc0..6187ce9ba7d5 100644
--- a/arch/arm/mach-imx/mach-mx1ads.c
+++ b/arch/arm/mach-imx/mach-mx1ads.c
@@ -32,7 +32,7 @@
#include "devices-imx1.h"
#include "devices.h"
-static int mx1ads_pins[] = {
+static const int mx1ads_pins[] __initconst = {
/* UART1 */
PC9_PF_UART1_CTS,
PC10_PF_UART1_RTS,
@@ -131,7 +131,7 @@ static void __init mx1ads_init(void)
i2c_register_board_info(0, mx1ads_i2c_devices,
ARRAY_SIZE(mx1ads_i2c_devices));
- imx1_add_i2c_imx(&mx1ads_i2c_data);
+ imx1_add_imx_i2c(&mx1ads_i2c_data);
}
static void __init mx1ads_timer_init(void)
@@ -145,8 +145,6 @@ struct sys_timer mx1ads_timer = {
MACHINE_START(MX1ADS, "Freescale MX1ADS")
/* Maintainer: Sascha Hauer, Pengutronix */
- .phys_io = MX1_IO_BASE_ADDR,
- .io_pg_offst = (MX1_IO_BASE_ADDR_VIRT >> 18) & 0xfffc,
.boot_params = MX1_PHYS_OFFSET + 0x100,
.map_io = mx1_map_io,
.init_irq = mx1_init_irq,
@@ -155,8 +153,6 @@ MACHINE_START(MX1ADS, "Freescale MX1ADS")
MACHINE_END
MACHINE_START(MXLADS, "Freescale MXLADS")
- .phys_io = MX1_IO_BASE_ADDR,
- .io_pg_offst = (MX1_IO_BASE_ADDR_VIRT >> 18) & 0xfffc,
.boot_params = MX1_PHYS_OFFSET + 0x100,
.map_io = mx1_map_io,
.init_irq = mx1_init_irq,
diff --git a/arch/arm/mach-imx/mach-mx21ads.c b/arch/arm/mach-imx/mach-mx21ads.c
index 96d7f8189f32..e1282e9f50ff 100644
--- a/arch/arm/mach-imx/mach-mx21ads.c
+++ b/arch/arm/mach-imx/mach-mx21ads.c
@@ -67,7 +67,7 @@
#define MX21ADS_IO_LED4_ON 0x4000
#define MX21ADS_IO_LED3_ON 0x8000
-static unsigned int mx21ads_pins[] = {
+static const int mx21ads_pins[] __initconst = {
/* CS8900A */
(GPIO_PORTE | GPIO_GPIO | GPIO_IN | 11),
@@ -314,8 +314,6 @@ static struct sys_timer mx21ads_timer = {
MACHINE_START(MX21ADS, "Freescale i.MX21ADS")
/* maintainer: Freescale Semiconductor, Inc. */
- .phys_io = MX21_AIPI_BASE_ADDR,
- .io_pg_offst = ((MX21_AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc,
.boot_params = MX21_PHYS_OFFSET + 0x100,
.map_io = mx21ads_map_io,
.init_irq = mx21_init_irq,
diff --git a/arch/arm/mach-imx/mach-mx27_3ds.c b/arch/arm/mach-imx/mach-mx27_3ds.c
index e66ffaa1c26c..b8bbd31aa850 100644
--- a/arch/arm/mach-imx/mach-mx27_3ds.c
+++ b/arch/arm/mach-imx/mach-mx27_3ds.c
@@ -33,7 +33,7 @@
#include "devices-imx27.h"
#include "devices.h"
-static unsigned int mx27pdk_pins[] = {
+static const int mx27pdk_pins[] __initconst = {
/* UART1 */
PE12_PF_UART1_TXD,
PE13_PF_UART1_RXD,
@@ -64,10 +64,6 @@ static const struct imxuart_platform_data uart_pdata __initconst = {
.flags = IMXUART_HAVE_RTSCTS,
};
-static struct platform_device *platform_devices[] __initdata = {
- &mxc_fec_device,
-};
-
/*
* Matrix keyboard
*/
@@ -94,7 +90,7 @@ static void __init mx27pdk_init(void)
mxc_gpio_setup_multiple_pins(mx27pdk_pins, ARRAY_SIZE(mx27pdk_pins),
"mx27pdk");
imx27_add_imx_uart0(&uart_pdata);
- platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+ imx27_add_fec(NULL);
mxc_register_device(&imx_kpp_device, &mx27_3ds_keymap_data);
}
@@ -109,8 +105,6 @@ static struct sys_timer mx27pdk_timer = {
MACHINE_START(MX27_3DS, "Freescale MX27PDK")
/* maintainer: Freescale Semiconductor, Inc. */
- .phys_io = MX27_AIPI_BASE_ADDR,
- .io_pg_offst = ((MX27_AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc,
.boot_params = MX27_PHYS_OFFSET + 0x100,
.map_io = mx27_map_io,
.init_irq = mx27_init_irq,
diff --git a/arch/arm/mach-imx/mach-mx27ads.c b/arch/arm/mach-imx/mach-mx27ads.c
index 9c77da98a10e..a1e4bc573afc 100644
--- a/arch/arm/mach-imx/mach-mx27ads.c
+++ b/arch/arm/mach-imx/mach-mx27ads.c
@@ -66,7 +66,7 @@
/* to determine the correct external crystal reference */
#define CKIH_27MHZ_BIT_SET (1 << 3)
-static unsigned int mx27ads_pins[] = {
+static const int mx27ads_pins[] __initconst = {
/* UART0 */
PE12_PF_UART1_TXD,
PE13_PF_UART1_RXD,
@@ -284,7 +284,6 @@ static struct imxmmc_platform_data sdhc2_pdata = {
static struct platform_device *platform_devices[] __initdata = {
&mx27ads_nor_mtd_device,
- &mxc_fec_device,
&mxc_w1_master_device,
};
@@ -308,11 +307,12 @@ static void __init mx27ads_board_init(void)
/* only the i2c master 1 is used on this CPU card */
i2c_register_board_info(1, mx27ads_i2c_devices,
ARRAY_SIZE(mx27ads_i2c_devices));
- imx27_add_i2c_imx1(&mx27ads_i2c1_data);
+ imx27_add_imx_i2c(1, &mx27ads_i2c1_data);
mxc_register_device(&mxc_fb_device, &mx27ads_fb_data);
mxc_register_device(&mxc_sdhc_device0, &sdhc1_pdata);
mxc_register_device(&mxc_sdhc_device1, &sdhc2_pdata);
+ imx27_add_fec(NULL);
platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
}
@@ -347,8 +347,6 @@ static void __init mx27ads_map_io(void)
MACHINE_START(MX27ADS, "Freescale i.MX27ADS")
/* maintainer: Freescale Semiconductor, Inc. */
- .phys_io = MX27_AIPI_BASE_ADDR,
- .io_pg_offst = ((MX27_AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc,
.boot_params = MX27_PHYS_OFFSET + 0x100,
.map_io = mx27ads_map_io,
.init_irq = mx27_init_irq,
diff --git a/arch/arm/mach-imx/mach-mxt_td60.c b/arch/arm/mach-imx/mach-mxt_td60.c
index a3a1e452d4c5..38d3a4ae17c7 100644
--- a/arch/arm/mach-imx/mach-mxt_td60.c
+++ b/arch/arm/mach-imx/mach-mxt_td60.c
@@ -37,7 +37,7 @@
#include "devices-imx27.h"
#include "devices.h"
-static unsigned int mxt_td60_pins[] __initdata = {
+static const int mxt_td60_pins[] __initconst = {
/* UART0 */
PE12_PF_UART1_TXD,
PE13_PF_UART1_RXD,
@@ -231,10 +231,6 @@ static struct imxmmc_platform_data sdhc1_pdata = {
.exit = mxt_td60_sdhc1_exit,
};
-static struct platform_device *platform_devices[] __initdata = {
- &mxc_fec_device,
-};
-
static const struct imxuart_platform_data uart_pdata __initconst = {
.flags = IMXUART_HAVE_RTSCTS,
};
@@ -255,12 +251,11 @@ static void __init mxt_td60_board_init(void)
i2c_register_board_info(1, mxt_td60_i2c2_devices,
ARRAY_SIZE(mxt_td60_i2c2_devices));
- imx27_add_i2c_imx0(&mxt_td60_i2c0_data);
- imx27_add_i2c_imx1(&mxt_td60_i2c1_data);
+ imx27_add_imx_i2c(0, &mxt_td60_i2c0_data);
+ imx27_add_imx_i2c(1, &mxt_td60_i2c1_data);
mxc_register_device(&mxc_fb_device, &mxt_td60_fb_data);
mxc_register_device(&mxc_sdhc_device0, &sdhc1_pdata);
-
- platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+ imx27_add_fec(NULL);
}
static void __init mxt_td60_timer_init(void)
@@ -274,8 +269,6 @@ static struct sys_timer mxt_td60_timer = {
MACHINE_START(MXT_TD60, "Maxtrack i-MXT TD60")
/* maintainer: Maxtrack Industrial */
- .phys_io = MX27_AIPI_BASE_ADDR,
- .io_pg_offst = ((MX27_AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc,
.boot_params = MX27_PHYS_OFFSET + 0x100,
.map_io = mx27_map_io,
.init_irq = mx27_init_irq,
diff --git a/arch/arm/mach-imx/mach-pca100.c b/arch/arm/mach-imx/mach-pca100.c
index 23c9e1f37b9c..8c720d44602a 100644
--- a/arch/arm/mach-imx/mach-pca100.c
+++ b/arch/arm/mach-imx/mach-pca100.c
@@ -38,7 +38,6 @@
#include <mach/iomux-mx27.h>
#include <asm/mach/time.h>
#include <mach/audmux.h>
-#include <mach/ssi.h>
#include <mach/mxc_nand.h>
#include <mach/irqs.h>
#include <mach/mmc.h>
@@ -55,7 +54,7 @@
#define SPI1_SS1 (GPIO_PORTD + 27)
#define SD2_CD (GPIO_PORTC + 29)
-static int pca100_pins[] = {
+static const int pca100_pins[] __initconst = {
/* UART1 */
PE12_PF_UART1_TXD,
PE13_PF_UART1_RXD,
@@ -174,7 +173,6 @@ pca100_nand_board_info __initconst = {
static struct platform_device *platform_devices[] __initdata = {
&mxc_w1_master_device,
- &mxc_fec_device,
&mxc_wdt,
};
@@ -193,11 +191,9 @@ static struct i2c_board_info pca100_i2c_devices[] = {
I2C_BOARD_INFO("at24", 0x52), /* E0=0, E1=1, E2=0 */
.platform_data = &board_eeprom,
}, {
- I2C_BOARD_INFO("rtc-pcf8563", 0x51),
- .type = "pcf8563"
+ I2C_BOARD_INFO("pcf8563", 0x51),
}, {
I2C_BOARD_INFO("lm75", 0x4a),
- .type = "lm75"
}
};
@@ -252,7 +248,7 @@ static void pca100_ac97_cold_reset(struct snd_ac97 *ac97)
msleep(2);
}
-static struct imx_ssi_platform_data pca100_ssi_pdata = {
+static const struct imx_ssi_platform_data pca100_ssi_pdata __initconst = {
.ac97_reset = pca100_ac97_cold_reset,
.ac97_warm_reset = pca100_ac97_warm_reset,
.flags = IMX_SSI_USE_AC97,
@@ -389,7 +385,7 @@ static void __init pca100_init(void)
if (ret)
printk(KERN_ERR "pca100: Failed to setup pins (%d)\n", ret);
- mxc_register_device(&imx_ssi_device0, &pca100_ssi_pdata);
+ imx27_add_imx_ssi(0, &pca100_ssi_pdata);
imx27_add_imx_uart0(&uart_pdata);
@@ -401,7 +397,7 @@ static void __init pca100_init(void)
i2c_register_board_info(1, pca100_i2c_devices,
ARRAY_SIZE(pca100_i2c_devices));
- imx27_add_i2c_imx1(&pca100_i2c1_data);
+ imx27_add_imx_i2c(1, &pca100_i2c1_data);
#if defined(CONFIG_SPI_IMX) || defined(CONFIG_SPI_IMX_MODULE)
mxc_gpio_mode(GPIO_PORTD | 28 | GPIO_GPIO | GPIO_IN);
@@ -436,6 +432,7 @@ static void __init pca100_init(void)
mxc_register_device(&mxc_fb_device, &pca100_fb_data);
+ imx27_add_fec(NULL);
platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
}
@@ -449,8 +446,6 @@ static struct sys_timer pca100_timer = {
};
MACHINE_START(PCA100, "phyCARD-i.MX27")
- .phys_io = MX27_AIPI_BASE_ADDR,
- .io_pg_offst = ((MX27_AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc,
.boot_params = MX27_PHYS_OFFSET + 0x100,
.map_io = mx27_map_io,
.init_irq = mx27_init_irq,
diff --git a/arch/arm/mach-imx/mach-pcm038.c b/arch/arm/mach-imx/mach-pcm038.c
index 9212e8f37001..49a97ce07426 100644
--- a/arch/arm/mach-imx/mach-pcm038.c
+++ b/arch/arm/mach-imx/mach-pcm038.c
@@ -43,7 +43,7 @@
#include "devices-imx27.h"
#include "devices.h"
-static int pcm038_pins[] = {
+static const int pcm038_pins[] __initconst = {
/* UART1 */
PE12_PF_UART1_TXD,
PE13_PF_UART1_RXD,
@@ -173,7 +173,6 @@ pcm038_nand_board_info __initconst = {
static struct platform_device *platform_devices[] __initdata = {
&pcm038_nor_mtd_device,
&mxc_w1_master_device,
- &mxc_fec_device,
&pcm038_sram_mtd_device,
&mxc_wdt,
};
@@ -257,7 +256,7 @@ static struct regulator_init_data cam_data = {
.consumer_supplies = cam_consumers,
};
-struct mc13783_regulator_init_data pcm038_regulators[] = {
+static struct mc13783_regulator_init_data pcm038_regulators[] = {
{
.id = MC13783_REGU_VCAM,
.init_data = &cam_data,
@@ -309,7 +308,7 @@ static void __init pcm038_init(void)
i2c_register_board_info(1, pcm038_i2c_devices,
ARRAY_SIZE(pcm038_i2c_devices));
- imx27_add_i2c_imx1(&pcm038_i2c1_data);
+ imx27_add_imx_i2c(1, &pcm038_i2c1_data);
/* PE18 for user-LED D40 */
mxc_gpio_mode(GPIO_PORTE | 18 | GPIO_GPIO | GPIO_OUT);
@@ -325,6 +324,7 @@ static void __init pcm038_init(void)
mxc_register_device(&mxc_usbh2, &usbh2_pdata);
+ imx27_add_fec(NULL);
platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
#ifdef CONFIG_MACH_PCM970_BASEBOARD
@@ -342,8 +342,6 @@ static struct sys_timer pcm038_timer = {
};
MACHINE_START(PCM038, "phyCORE-i.MX27")
- .phys_io = MX27_AIPI_BASE_ADDR,
- .io_pg_offst = ((MX27_AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc,
.boot_params = MX27_PHYS_OFFSET + 0x100,
.map_io = mx27_map_io,
.init_irq = mx27_init_irq,
diff --git a/arch/arm/mach-imx/mach-scb9328.c b/arch/arm/mach-imx/mach-scb9328.c
index 88bf0d1e26e6..1fbdd3faa7ab 100644
--- a/arch/arm/mach-imx/mach-scb9328.c
+++ b/arch/arm/mach-imx/mach-scb9328.c
@@ -95,7 +95,7 @@ static struct platform_device dm9000x_device = {
}
};
-static int mxc_uart1_pins[] = {
+static const int mxc_uart1_pins[] = {
PC9_PF_UART1_CTS,
PC10_PF_UART1_RTS,
PC11_PF_UART1_TXD,
@@ -147,8 +147,6 @@ static struct sys_timer scb9328_timer = {
MACHINE_START(SCB9328, "Synertronixx scb9328")
/* Sascha Hauer */
- .phys_io = 0x00200000,
- .io_pg_offst = ((0xe0200000) >> 18) & 0xfffc,
.boot_params = 0x08000100,
.map_io = mx1_map_io,
.init_irq = mx1_init_irq,
diff --git a/arch/arm/mach-imx/pcm970-baseboard.c b/arch/arm/mach-imx/pcm970-baseboard.c
index f490a406d57e..9110d9cca7a2 100644
--- a/arch/arm/mach-imx/pcm970-baseboard.c
+++ b/arch/arm/mach-imx/pcm970-baseboard.c
@@ -31,7 +31,7 @@
#include "devices.h"
-static int pcm970_pins[] = {
+static const int pcm970_pins[] __initconst = {
/* SDHC */
PB4_PF_SD2_D0,
PB5_PF_SD2_D1,
@@ -200,7 +200,7 @@ static struct resource pcm970_sja1000_resources[] = {
},
};
-struct sja1000_platform_data pcm970_sja1000_platform_data = {
+static struct sja1000_platform_data pcm970_sja1000_platform_data = {
.osc_freq = 16000000,
.ocr = OCR_TX1_PULLDOWN | OCR_TX0_PUSHPULL,
.cdr = CDR_CBP,
diff --git a/arch/arm/mach-integrator/include/mach/debug-macro.S b/arch/arm/mach-integrator/include/mach/debug-macro.S
index 87a6888ae011..a1f598fd3a56 100644
--- a/arch/arm/mach-integrator/include/mach/debug-macro.S
+++ b/arch/arm/mach-integrator/include/mach/debug-macro.S
@@ -11,12 +11,10 @@
*
*/
- .macro addruart, rx, tmp
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ MMU enabled?
- moveq \rx, #0x16000000 @ physical base address
- movne \rx, #0xf0000000 @ virtual base
- addne \rx, \rx, #0x16000000 >> 4
+ .macro addruart, rp, rv
+ mov \rp, #0x16000000 @ physical base address
+ mov \rv, #0xf0000000 @ virtual base
+ add \rv, \rv, #0x16000000 >> 4
.endm
#include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/mach-integrator/include/mach/vmalloc.h b/arch/arm/mach-integrator/include/mach/vmalloc.h
index e87ab0b37bdd..e056e7cf5645 100644
--- a/arch/arm/mach-integrator/include/mach/vmalloc.h
+++ b/arch/arm/mach-integrator/include/mach/vmalloc.h
@@ -17,4 +17,4 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#define VMALLOC_END (PAGE_OFFSET + 0x10000000)
+#define VMALLOC_END 0xd0000000
diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c
index 6ab5a03ab9d8..548208f11179 100644
--- a/arch/arm/mach-integrator/integrator_ap.c
+++ b/arch/arm/mach-integrator/integrator_ap.c
@@ -500,8 +500,6 @@ static struct sys_timer ap_timer = {
MACHINE_START(INTEGRATOR, "ARM-Integrator")
/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
- .phys_io = 0x16000000,
- .io_pg_offst = ((0xf1600000) >> 18) & 0xfffc,
.boot_params = 0x00000100,
.map_io = ap_map_io,
.reserve = integrator_reserve,
diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c
index 05db40e3c4f7..6258c90d020c 100644
--- a/arch/arm/mach-integrator/integrator_cp.c
+++ b/arch/arm/mach-integrator/integrator_cp.c
@@ -599,8 +599,6 @@ static struct sys_timer cp_timer = {
MACHINE_START(CINTEGRATOR, "ARM-IntegratorCP")
/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
- .phys_io = 0x16000000,
- .io_pg_offst = ((0xf1600000) >> 18) & 0xfffc,
.boot_params = 0x00000100,
.map_io = intcp_map_io,
.reserve = integrator_reserve,
diff --git a/arch/arm/mach-iop13xx/include/mach/debug-macro.S b/arch/arm/mach-iop13xx/include/mach/debug-macro.S
index c9d6ba46963d..e664466d51bf 100644
--- a/arch/arm/mach-iop13xx/include/mach/debug-macro.S
+++ b/arch/arm/mach-iop13xx/include/mach/debug-macro.S
@@ -11,15 +11,13 @@
* published by the Free Software Foundation.
*/
- .macro addruart, rx, tmp
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ mmu enabled?
- moveq \rx, #0xff000000 @ physical
- orreq \rx, \rx, #0x00d80000
- movne \rx, #0xfe000000 @ virtual
- orrne \rx, \rx, #0x00e80000
- orr \rx, \rx, #0x00002300
- orr \rx, \rx, #0x00000040
+ .macro addruart, rp, rv
+ mov \rp, #0x00002300
+ orr \rp, \rp, #0x00000040
+ orr \rv, \rp, #0xfe000000 @ virtual
+ orr \rv, \rv, #0x00e80000
+ orr \rp, \rp, #0xff000000 @ physical
+ orr \rp, \rp, #0x00d80000
.endm
#define UART_SHIFT 2
diff --git a/arch/arm/mach-iop13xx/iq81340mc.c b/arch/arm/mach-iop13xx/iq81340mc.c
index f91f3154577d..9b5a63f5d07d 100644
--- a/arch/arm/mach-iop13xx/iq81340mc.c
+++ b/arch/arm/mach-iop13xx/iq81340mc.c
@@ -91,8 +91,6 @@ static struct sys_timer iq81340mc_timer = {
MACHINE_START(IQ81340MC, "Intel IQ81340MC")
/* Maintainer: Dan Williams <dan.j.williams@intel.com> */
- .phys_io = IOP13XX_PMMR_PHYS_MEM_BASE,
- .io_pg_offst = (IOP13XX_PMMR_VIRT_MEM_BASE >> 18) & 0xfffc,
.boot_params = 0x00000100,
.map_io = iop13xx_map_io,
.init_irq = iop13xx_init_irq,
diff --git a/arch/arm/mach-iop13xx/iq81340sc.c b/arch/arm/mach-iop13xx/iq81340sc.c
index ddb7a3435de9..df3492a9c280 100644
--- a/arch/arm/mach-iop13xx/iq81340sc.c
+++ b/arch/arm/mach-iop13xx/iq81340sc.c
@@ -93,8 +93,6 @@ static struct sys_timer iq81340sc_timer = {
MACHINE_START(IQ81340SC, "Intel IQ81340SC")
/* Maintainer: Dan Williams <dan.j.williams@intel.com> */
- .phys_io = IOP13XX_PMMR_PHYS_MEM_BASE,
- .io_pg_offst = (IOP13XX_PMMR_VIRT_MEM_BASE >> 18) & 0xfffc,
.boot_params = 0x00000100,
.map_io = iop13xx_map_io,
.init_irq = iop13xx_init_irq,
diff --git a/arch/arm/mach-iop13xx/msi.c b/arch/arm/mach-iop13xx/msi.c
index f34b0ed80630..7149fcc16c8a 100644
--- a/arch/arm/mach-iop13xx/msi.c
+++ b/arch/arm/mach-iop13xx/msi.c
@@ -164,10 +164,10 @@ static void iop13xx_msi_nop(unsigned int irq)
static struct irq_chip iop13xx_msi_chip = {
.name = "PCI-MSI",
.ack = iop13xx_msi_nop,
- .enable = unmask_msi_irq,
- .disable = mask_msi_irq,
- .mask = mask_msi_irq,
- .unmask = unmask_msi_irq,
+ .irq_enable = unmask_msi_irq,
+ .irq_disable = mask_msi_irq,
+ .irq_mask = mask_msi_irq,
+ .irq_unmask = unmask_msi_irq,
};
int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
diff --git a/arch/arm/mach-iop32x/em7210.c b/arch/arm/mach-iop32x/em7210.c
index 2bef9b6e1cc9..779f924af302 100644
--- a/arch/arm/mach-iop32x/em7210.c
+++ b/arch/arm/mach-iop32x/em7210.c
@@ -203,8 +203,6 @@ static void __init em7210_init_machine(void)
}
MACHINE_START(EM7210, "Lanner EM7210")
- .phys_io = IQ31244_UART,
- .io_pg_offst = ((IQ31244_UART) >> 18) & 0xfffc,
.boot_params = 0xa0000100,
.map_io = em7210_map_io,
.init_irq = iop32x_init_irq,
diff --git a/arch/arm/mach-iop32x/glantank.c b/arch/arm/mach-iop32x/glantank.c
index 10384fc37cb2..c6b6f9c5650d 100644
--- a/arch/arm/mach-iop32x/glantank.c
+++ b/arch/arm/mach-iop32x/glantank.c
@@ -207,8 +207,6 @@ static void __init glantank_init_machine(void)
MACHINE_START(GLANTANK, "GLAN Tank")
/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
- .phys_io = GLANTANK_UART,
- .io_pg_offst = ((GLANTANK_UART) >> 18) & 0xfffc,
.boot_params = 0xa0000100,
.map_io = glantank_map_io,
.init_irq = iop32x_init_irq,
diff --git a/arch/arm/mach-iop32x/include/mach/debug-macro.S b/arch/arm/mach-iop32x/include/mach/debug-macro.S
index 736afe1edd1f..ff9e76c09f35 100644
--- a/arch/arm/mach-iop32x/include/mach/debug-macro.S
+++ b/arch/arm/mach-iop32x/include/mach/debug-macro.S
@@ -11,9 +11,10 @@
* published by the Free Software Foundation.
*/
- .macro addruart, rx, tmp
- mov \rx, #0xfe000000 @ physical as well as virtual
- orr \rx, \rx, #0x00800000 @ location of the UART
+ .macro addruart, rp, rv
+ mov \rp, #0xfe000000 @ physical as well as virtual
+ orr \rp, \rp, #0x00800000 @ location of the UART
+ mov \rv, \rp
.endm
#define UART_SHIFT 0
diff --git a/arch/arm/mach-iop32x/iq31244.c b/arch/arm/mach-iop32x/iq31244.c
index d6ac85ff109d..fde962c057f0 100644
--- a/arch/arm/mach-iop32x/iq31244.c
+++ b/arch/arm/mach-iop32x/iq31244.c
@@ -313,8 +313,6 @@ __setup("force_ep80219", force_ep80219_setup);
MACHINE_START(IQ31244, "Intel IQ31244")
/* Maintainer: Intel Corp. */
- .phys_io = IQ31244_UART,
- .io_pg_offst = ((IQ31244_UART) >> 18) & 0xfffc,
.boot_params = 0xa0000100,
.map_io = iq31244_map_io,
.init_irq = iop32x_init_irq,
@@ -329,8 +327,6 @@ MACHINE_END
*/
MACHINE_START(EP80219, "Intel EP80219")
/* Maintainer: Intel Corp. */
- .phys_io = IQ31244_UART,
- .io_pg_offst = ((IQ31244_UART) >> 18) & 0xfffc,
.boot_params = 0xa0000100,
.map_io = iq31244_map_io,
.init_irq = iop32x_init_irq,
diff --git a/arch/arm/mach-iop32x/iq80321.c b/arch/arm/mach-iop32x/iq80321.c
index c6a0e4ee9d91..3a95950e8737 100644
--- a/arch/arm/mach-iop32x/iq80321.c
+++ b/arch/arm/mach-iop32x/iq80321.c
@@ -186,8 +186,6 @@ static void __init iq80321_init_machine(void)
MACHINE_START(IQ80321, "Intel IQ80321")
/* Maintainer: Intel Corp. */
- .phys_io = IQ80321_UART,
- .io_pg_offst = ((IQ80321_UART) >> 18) & 0xfffc,
.boot_params = 0xa0000100,
.map_io = iq80321_map_io,
.init_irq = iop32x_init_irq,
diff --git a/arch/arm/mach-iop32x/n2100.c b/arch/arm/mach-iop32x/n2100.c
index f108a31afc2b..626aa375915d 100644
--- a/arch/arm/mach-iop32x/n2100.c
+++ b/arch/arm/mach-iop32x/n2100.c
@@ -327,8 +327,6 @@ static void __init n2100_init_machine(void)
MACHINE_START(N2100, "Thecus N2100")
/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
- .phys_io = N2100_UART,
- .io_pg_offst = ((N2100_UART) >> 18) & 0xfffc,
.boot_params = 0xa0000100,
.map_io = n2100_map_io,
.init_irq = iop32x_init_irq,
diff --git a/arch/arm/mach-iop33x/include/mach/debug-macro.S b/arch/arm/mach-iop33x/include/mach/debug-macro.S
index addb2da78422..40c500dd1fac 100644
--- a/arch/arm/mach-iop33x/include/mach/debug-macro.S
+++ b/arch/arm/mach-iop33x/include/mach/debug-macro.S
@@ -11,13 +11,11 @@
* published by the Free Software Foundation.
*/
- .macro addruart, rx, tmp
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ mmu enabled?
- moveq \rx, #0xff000000 @ physical
- movne \rx, #0xfe000000 @ virtual
- orr \rx, \rx, #0x00ff0000
- orr \rx, \rx, #0x0000f700
+ .macro addruart, rp, rv
+ mov \rp, #0x00ff0000
+ orr \rp, \rp, #0x0000f700
+ orr \rv, #0xfe000000 @ virtual
+ orr \rp, #0xff000000 @ physical
.endm
#define UART_SHIFT 2
diff --git a/arch/arm/mach-iop33x/iq80331.c b/arch/arm/mach-iop33x/iq80331.c
index c6ff5523b380..c565f8d1e3a4 100644
--- a/arch/arm/mach-iop33x/iq80331.c
+++ b/arch/arm/mach-iop33x/iq80331.c
@@ -141,8 +141,6 @@ static void __init iq80331_init_machine(void)
MACHINE_START(IQ80331, "Intel IQ80331")
/* Maintainer: Intel Corp. */
- .phys_io = 0xfefff000,
- .io_pg_offst = ((0xfffff000) >> 18) & 0xfffc,
.boot_params = 0x00000100,
.map_io = iop3xx_map_io,
.init_irq = iop33x_init_irq,
diff --git a/arch/arm/mach-iop33x/iq80332.c b/arch/arm/mach-iop33x/iq80332.c
index fbf551409394..36a9efb254c2 100644
--- a/arch/arm/mach-iop33x/iq80332.c
+++ b/arch/arm/mach-iop33x/iq80332.c
@@ -141,8 +141,6 @@ static void __init iq80332_init_machine(void)
MACHINE_START(IQ80332, "Intel IQ80332")
/* Maintainer: Intel Corp. */
- .phys_io = 0xfefff000,
- .io_pg_offst = ((0xfffff000) >> 18) & 0xfffc,
.boot_params = 0x00000100,
.map_io = iop3xx_map_io,
.init_irq = iop33x_init_irq,
diff --git a/arch/arm/mach-ixp2000/enp2611.c b/arch/arm/mach-ixp2000/enp2611.c
index 1a557e0d055b..88663ab1d2ad 100644
--- a/arch/arm/mach-ixp2000/enp2611.c
+++ b/arch/arm/mach-ixp2000/enp2611.c
@@ -253,8 +253,6 @@ static void __init enp2611_init_machine(void)
MACHINE_START(ENP2611, "Radisys ENP-2611 PCI network processor board")
/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
- .phys_io = IXP2000_UART_PHYS_BASE,
- .io_pg_offst = ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = 0x00000100,
.map_io = enp2611_map_io,
.init_irq = ixp2000_init_irq,
diff --git a/arch/arm/mach-ixp2000/include/mach/debug-macro.S b/arch/arm/mach-ixp2000/include/mach/debug-macro.S
index 6a827681680f..0ef533b20972 100644
--- a/arch/arm/mach-ixp2000/include/mach/debug-macro.S
+++ b/arch/arm/mach-ixp2000/include/mach/debug-macro.S
@@ -11,16 +11,14 @@
*
*/
- .macro addruart, rx, tmp
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ MMU enabled?
- moveq \rx, #0xc0000000 @ Physical base
- movne \rx, #0xfe000000 @ virtual base
- orrne \rx, \rx, #0x00f00000
- orr \rx, \rx, #0x00030000
+ .macro addruart, rp, rv
+ mov \rp, #0x00030000
#ifdef __ARMEB__
- orr \rx, \rx, #0x00000003
+ orr \rp, \rp, #0x00000003
#endif
+ orr \rv, \rp, #0xfe000000 @ virtual base
+ orr \rv, \rv, #0x00f00000
+ orr \rp, \rp, #0xc0000000 @ Physical base
.endm
#define UART_SHIFT 2
diff --git a/arch/arm/mach-ixp2000/ixdp2400.c b/arch/arm/mach-ixp2000/ixdp2400.c
index 55e5c69352ad..dfffc1e817fa 100644
--- a/arch/arm/mach-ixp2000/ixdp2400.c
+++ b/arch/arm/mach-ixp2000/ixdp2400.c
@@ -170,8 +170,6 @@ void __init ixdp2400_init_irq(void)
MACHINE_START(IXDP2400, "Intel IXDP2400 Development Platform")
/* Maintainer: MontaVista Software, Inc. */
- .phys_io = IXP2000_UART_PHYS_BASE,
- .io_pg_offst = ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = 0x00000100,
.map_io = ixdp2x00_map_io,
.init_irq = ixdp2400_init_irq,
diff --git a/arch/arm/mach-ixp2000/ixdp2800.c b/arch/arm/mach-ixp2000/ixdp2800.c
index 237b61a85e9a..cd4c9bcff2b5 100644
--- a/arch/arm/mach-ixp2000/ixdp2800.c
+++ b/arch/arm/mach-ixp2000/ixdp2800.c
@@ -285,8 +285,6 @@ void __init ixdp2800_init_irq(void)
MACHINE_START(IXDP2800, "Intel IXDP2800 Development Platform")
/* Maintainer: MontaVista Software, Inc. */
- .phys_io = IXP2000_UART_PHYS_BASE,
- .io_pg_offst = ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = 0x00000100,
.map_io = ixdp2x00_map_io,
.init_irq = ixdp2800_init_irq,
diff --git a/arch/arm/mach-ixp2000/ixdp2x01.c b/arch/arm/mach-ixp2000/ixdp2x01.c
index 0369ec4242a6..6c121bdbe311 100644
--- a/arch/arm/mach-ixp2000/ixdp2x01.c
+++ b/arch/arm/mach-ixp2000/ixdp2x01.c
@@ -416,8 +416,6 @@ static void __init ixdp2x01_init_machine(void)
#ifdef CONFIG_ARCH_IXDP2401
MACHINE_START(IXDP2401, "Intel IXDP2401 Development Platform")
/* Maintainer: MontaVista Software, Inc. */
- .phys_io = IXP2000_UART_PHYS_BASE,
- .io_pg_offst = ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = 0x00000100,
.map_io = ixdp2x01_map_io,
.init_irq = ixdp2x01_init_irq,
@@ -429,8 +427,6 @@ MACHINE_END
#ifdef CONFIG_ARCH_IXDP2801
MACHINE_START(IXDP2801, "Intel IXDP2801 Development Platform")
/* Maintainer: MontaVista Software, Inc. */
- .phys_io = IXP2000_UART_PHYS_BASE,
- .io_pg_offst = ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = 0x00000100,
.map_io = ixdp2x01_map_io,
.init_irq = ixdp2x01_init_irq,
@@ -444,8 +440,6 @@ MACHINE_END
*/
MACHINE_START(IXDP28X5, "Intel IXDP2805/2855 Development Platform")
/* Maintainer: MontaVista Software, Inc. */
- .phys_io = IXP2000_UART_PHYS_BASE,
- .io_pg_offst = ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = 0x00000100,
.map_io = ixdp2x01_map_io,
.init_irq = ixdp2x01_init_irq,
diff --git a/arch/arm/mach-ixp23xx/espresso.c b/arch/arm/mach-ixp23xx/espresso.c
index 1c06bfc5a7ef..e25e5fe183ba 100644
--- a/arch/arm/mach-ixp23xx/espresso.c
+++ b/arch/arm/mach-ixp23xx/espresso.c
@@ -85,8 +85,6 @@ static void __init espresso_init(void)
MACHINE_START(ESPRESSO, "IP Fabrics Double Espresso")
/* Maintainer: Lennert Buytenhek */
- .phys_io = IXP23XX_PERIPHERAL_PHYS,
- .io_pg_offst = ((IXP23XX_PERIPHERAL_VIRT >> 18)) & 0xfffc,
.map_io = ixp23xx_map_io,
.init_irq = ixp23xx_init_irq,
.timer = &ixp23xx_timer,
diff --git a/arch/arm/mach-ixp23xx/include/mach/debug-macro.S b/arch/arm/mach-ixp23xx/include/mach/debug-macro.S
index a82e375465e2..f7c6eef7fa22 100644
--- a/arch/arm/mach-ixp23xx/include/mach/debug-macro.S
+++ b/arch/arm/mach-ixp23xx/include/mach/debug-macro.S
@@ -12,13 +12,12 @@
*/
#include <mach/ixp23xx.h>
- .macro addruart, rx, tmp
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ mmu enabled?
- ldreq \rx, =IXP23XX_PERIPHERAL_PHYS @ physical
- ldrne \rx, =IXP23XX_PERIPHERAL_VIRT @ virtual
+ .macro addruart, rp, rv
+ ldr \rp, =IXP23XX_PERIPHERAL_PHYS @ physical
+ ldr \rv, =IXP23XX_PERIPHERAL_VIRT @ virtual
#ifdef __ARMEB__
- orr \rx, \rx, #0x00000003
+ orr \rp, \rp, #0x00000003
+ orr \rv, \rv, #0x00000003
#endif
.endm
diff --git a/arch/arm/mach-ixp23xx/ixdp2351.c b/arch/arm/mach-ixp23xx/ixdp2351.c
index f1b124a709ab..664e39c2a903 100644
--- a/arch/arm/mach-ixp23xx/ixdp2351.c
+++ b/arch/arm/mach-ixp23xx/ixdp2351.c
@@ -328,8 +328,6 @@ static void __init ixdp2351_init(void)
MACHINE_START(IXDP2351, "Intel IXDP2351 Development Platform")
/* Maintainer: MontaVista Software, Inc. */
- .phys_io = IXP23XX_PERIPHERAL_PHYS,
- .io_pg_offst = ((IXP23XX_PERIPHERAL_VIRT >> 18)) & 0xfffc,
.map_io = ixdp2351_map_io,
.init_irq = ixdp2351_init_irq,
.timer = &ixp23xx_timer,
diff --git a/arch/arm/mach-ixp23xx/roadrunner.c b/arch/arm/mach-ixp23xx/roadrunner.c
index 6d38d769761c..76c61ba73218 100644
--- a/arch/arm/mach-ixp23xx/roadrunner.c
+++ b/arch/arm/mach-ixp23xx/roadrunner.c
@@ -171,8 +171,6 @@ static void __init roadrunner_init(void)
MACHINE_START(ROADRUNNER, "ADI Engineering RoadRunner Development Platform")
/* Maintainer: Deepak Saxena */
- .phys_io = IXP23XX_PERIPHERAL_PHYS,
- .io_pg_offst = ((IXP23XX_PERIPHERAL_VIRT >> 18)) & 0xfffc,
.map_io = ixp23xx_map_io,
.init_irq = ixp23xx_init_irq,
.timer = &ixp23xx_timer,
diff --git a/arch/arm/mach-ixp4xx/avila-setup.c b/arch/arm/mach-ixp4xx/avila-setup.c
index d8bc86d76f1d..73745ff102d5 100644
--- a/arch/arm/mach-ixp4xx/avila-setup.c
+++ b/arch/arm/mach-ixp4xx/avila-setup.c
@@ -164,8 +164,6 @@ static void __init avila_init(void)
MACHINE_START(AVILA, "Gateworks Avila Network Platform")
/* Maintainer: Deepak Saxena <dsaxena@plexity.net> */
- .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
- .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
.map_io = ixp4xx_map_io,
.init_irq = ixp4xx_init_irq,
.timer = &ixp4xx_timer,
@@ -181,8 +179,6 @@ MACHINE_END
#ifdef CONFIG_MACH_LOFT
MACHINE_START(LOFT, "Giant Shoulder Inc Loft board")
/* Maintainer: Tom Billman <kernel@giantshoulderinc.com> */
- .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
- .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
.map_io = ixp4xx_map_io,
.init_irq = ixp4xx_init_irq,
.timer = &ixp4xx_timer,
diff --git a/arch/arm/mach-ixp4xx/coyote-setup.c b/arch/arm/mach-ixp4xx/coyote-setup.c
index 31a47f6a8939..355e3de38733 100644
--- a/arch/arm/mach-ixp4xx/coyote-setup.c
+++ b/arch/arm/mach-ixp4xx/coyote-setup.c
@@ -109,8 +109,6 @@ static void __init coyote_init(void)
#ifdef CONFIG_ARCH_ADI_COYOTE
MACHINE_START(ADI_COYOTE, "ADI Engineering Coyote")
/* Maintainer: MontaVista Software, Inc. */
- .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
- .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
.map_io = ixp4xx_map_io,
.init_irq = ixp4xx_init_irq,
.timer = &ixp4xx_timer,
@@ -126,8 +124,6 @@ MACHINE_END
#ifdef CONFIG_MACH_IXDPG425
MACHINE_START(IXDPG425, "Intel IXDPG425")
/* Maintainer: MontaVista Software, Inc. */
- .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
- .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
.map_io = ixp4xx_map_io,
.init_irq = ixp4xx_init_irq,
.timer = &ixp4xx_timer,
diff --git a/arch/arm/mach-ixp4xx/dsmg600-setup.c b/arch/arm/mach-ixp4xx/dsmg600-setup.c
index 7c1fa54a6145..d398229cfaa5 100644
--- a/arch/arm/mach-ixp4xx/dsmg600-setup.c
+++ b/arch/arm/mach-ixp4xx/dsmg600-setup.c
@@ -279,8 +279,6 @@ static void __init dsmg600_init(void)
MACHINE_START(DSMG600, "D-Link DSM-G600 RevA")
/* Maintainer: www.nslu2-linux.org */
- .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
- .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xFFFC,
.boot_params = 0x00000100,
.map_io = ixp4xx_map_io,
.init_irq = ixp4xx_init_irq,
diff --git a/arch/arm/mach-ixp4xx/fsg-setup.c b/arch/arm/mach-ixp4xx/fsg-setup.c
index e7f4befba422..727ee39ce11c 100644
--- a/arch/arm/mach-ixp4xx/fsg-setup.c
+++ b/arch/arm/mach-ixp4xx/fsg-setup.c
@@ -270,8 +270,6 @@ static void __init fsg_init(void)
MACHINE_START(FSG, "Freecom FSG-3")
/* Maintainer: www.nslu2-linux.org */
- .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
- .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
.map_io = ixp4xx_map_io,
.init_irq = ixp4xx_init_irq,
.timer = &ixp4xx_timer,
diff --git a/arch/arm/mach-ixp4xx/gateway7001-setup.c b/arch/arm/mach-ixp4xx/gateway7001-setup.c
index 2583b2a13174..9dc0b4eaa65a 100644
--- a/arch/arm/mach-ixp4xx/gateway7001-setup.c
+++ b/arch/arm/mach-ixp4xx/gateway7001-setup.c
@@ -96,8 +96,6 @@ static void __init gateway7001_init(void)
#ifdef CONFIG_MACH_GATEWAY7001
MACHINE_START(GATEWAY7001, "Gateway 7001 AP")
/* Maintainer: Imre Kaloz <kaloz@openwrt.org> */
- .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
- .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
.map_io = ixp4xx_map_io,
.init_irq = ixp4xx_init_irq,
.timer = &ixp4xx_timer,
diff --git a/arch/arm/mach-ixp4xx/goramo_mlr.c b/arch/arm/mach-ixp4xx/goramo_mlr.c
index 1c28048209c1..d0e4861ac03d 100644
--- a/arch/arm/mach-ixp4xx/goramo_mlr.c
+++ b/arch/arm/mach-ixp4xx/goramo_mlr.c
@@ -496,8 +496,6 @@ subsys_initcall(gmlr_pci_init);
MACHINE_START(GORAMO_MLR, "MultiLink")
/* Maintainer: Krzysztof Halasa */
- .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
- .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xFFFC,
.map_io = ixp4xx_map_io,
.init_irq = ixp4xx_init_irq,
.timer = &ixp4xx_timer,
diff --git a/arch/arm/mach-ixp4xx/gtwx5715-setup.c b/arch/arm/mach-ixp4xx/gtwx5715-setup.c
index c67586b79400..77abead36227 100644
--- a/arch/arm/mach-ixp4xx/gtwx5715-setup.c
+++ b/arch/arm/mach-ixp4xx/gtwx5715-setup.c
@@ -164,8 +164,6 @@ static void __init gtwx5715_init(void)
MACHINE_START(GTWX5715, "Gemtek GTWX5715 (Linksys WRV54G)")
/* Maintainer: George Joseph */
- .phys_io = IXP4XX_UART2_BASE_PHYS,
- .io_pg_offst = ((IXP4XX_UART2_BASE_VIRT) >> 18) & 0xfffc,
.map_io = ixp4xx_map_io,
.init_irq = ixp4xx_init_irq,
.timer = &ixp4xx_timer,
diff --git a/arch/arm/mach-ixp4xx/include/mach/debug-macro.S b/arch/arm/mach-ixp4xx/include/mach/debug-macro.S
index 3fc66d6d00a0..b974a49c0aff 100644
--- a/arch/arm/mach-ixp4xx/include/mach/debug-macro.S
+++ b/arch/arm/mach-ixp4xx/include/mach/debug-macro.S
@@ -10,16 +10,16 @@
* published by the Free Software Foundation.
*/
- .macro addruart, rx, tmp
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ MMU enabled?
- moveq \rx, #0xc8000000
- movne \rx, #0xff000000
- orrne \rx, \rx, #0x00b00000
+ .macro addruart, rp, rv
#ifdef __ARMEB__
- add \rx,\rx,#3 @ Uart regs are at off set of 3 if
- @ byte writes used - Big Endian.
+ mov \rp, #3 @ Uart regs are at off set of 3 if
+ @ byte writes used - Big Endian.
+#else
+ mov \rp, #0
#endif
+ orr \rv, \rp, #0xff000000 @ virtual
+ orr \rv, \rv, #0x00b00000
+ orr \rp, \rp, #0xc8000000 @ physical
.endm
#define UART_SHIFT 2
diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c
index ea9ee4ed0a3e..140783386785 100644
--- a/arch/arm/mach-ixp4xx/ixdp425-setup.c
+++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c
@@ -257,8 +257,6 @@ static void __init ixdp425_init(void)
#ifdef CONFIG_ARCH_IXDP425
MACHINE_START(IXDP425, "Intel IXDP425 Development Platform")
/* Maintainer: MontaVista Software, Inc. */
- .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
- .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
.map_io = ixp4xx_map_io,
.init_irq = ixp4xx_init_irq,
.timer = &ixp4xx_timer,
@@ -270,8 +268,6 @@ MACHINE_END
#ifdef CONFIG_MACH_IXDP465
MACHINE_START(IXDP465, "Intel IXDP465 Development Platform")
/* Maintainer: MontaVista Software, Inc. */
- .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
- .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
.map_io = ixp4xx_map_io,
.init_irq = ixp4xx_init_irq,
.timer = &ixp4xx_timer,
@@ -283,8 +279,6 @@ MACHINE_END
#ifdef CONFIG_ARCH_PRPMC1100
MACHINE_START(IXCDP1100, "Intel IXCDP1100 Development Platform")
/* Maintainer: MontaVista Software, Inc. */
- .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
- .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
.map_io = ixp4xx_map_io,
.init_irq = ixp4xx_init_irq,
.timer = &ixp4xx_timer,
@@ -296,8 +290,6 @@ MACHINE_END
#ifdef CONFIG_MACH_KIXRP435
MACHINE_START(KIXRP435, "Intel KIXRP435 Reference Platform")
/* Maintainer: MontaVista Software, Inc. */
- .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
- .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
.map_io = ixp4xx_map_io,
.init_irq = ixp4xx_init_irq,
.timer = &ixp4xx_timer,
diff --git a/arch/arm/mach-ixp4xx/nas100d-setup.c b/arch/arm/mach-ixp4xx/nas100d-setup.c
index e3ee880aa1e6..f18fee748878 100644
--- a/arch/arm/mach-ixp4xx/nas100d-setup.c
+++ b/arch/arm/mach-ixp4xx/nas100d-setup.c
@@ -314,8 +314,6 @@ static void __init nas100d_init(void)
MACHINE_START(NAS100D, "Iomega NAS 100d")
/* Maintainer: www.nslu2-linux.org */
- .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
- .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xFFFC,
.boot_params = 0x00000100,
.map_io = ixp4xx_map_io,
.init_irq = ixp4xx_init_irq,
diff --git a/arch/arm/mach-ixp4xx/nslu2-setup.c b/arch/arm/mach-ixp4xx/nslu2-setup.c
index c14e0034be4b..f79b62eb7614 100644
--- a/arch/arm/mach-ixp4xx/nslu2-setup.c
+++ b/arch/arm/mach-ixp4xx/nslu2-setup.c
@@ -300,8 +300,6 @@ static void __init nslu2_init(void)
MACHINE_START(NSLU2, "Linksys NSLU2")
/* Maintainer: www.nslu2-linux.org */
- .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
- .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xFFFC,
.boot_params = 0x00000100,
.map_io = ixp4xx_map_io,
.init_irq = ixp4xx_init_irq,
diff --git a/arch/arm/mach-ixp4xx/vulcan-setup.c b/arch/arm/mach-ixp4xx/vulcan-setup.c
index 465cc5cce687..4e72cfdd3c46 100644
--- a/arch/arm/mach-ixp4xx/vulcan-setup.c
+++ b/arch/arm/mach-ixp4xx/vulcan-setup.c
@@ -236,8 +236,6 @@ static void __init vulcan_init(void)
MACHINE_START(ARCOM_VULCAN, "Arcom/Eurotech Vulcan")
/* Maintainer: Marc Zyngier <maz@misterjones.org> */
- .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
- .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
.map_io = ixp4xx_map_io,
.init_irq = ixp4xx_init_irq,
.timer = &ixp4xx_timer,
diff --git a/arch/arm/mach-ixp4xx/wg302v2-setup.c b/arch/arm/mach-ixp4xx/wg302v2-setup.c
index 4dd74863daa9..5d148c7bc4fb 100644
--- a/arch/arm/mach-ixp4xx/wg302v2-setup.c
+++ b/arch/arm/mach-ixp4xx/wg302v2-setup.c
@@ -97,8 +97,6 @@ static void __init wg302v2_init(void)
#ifdef CONFIG_MACH_WG302V2
MACHINE_START(WG302V2, "Netgear WG302 v2 / WAG302 v2")
/* Maintainer: Imre Kaloz <kaloz@openwrt.org> */
- .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
- .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
.map_io = ixp4xx_map_io,
.init_irq = ixp4xx_init_irq,
.timer = &ixp4xx_timer,
diff --git a/arch/arm/mach-kirkwood/Kconfig b/arch/arm/mach-kirkwood/Kconfig
index cc25501b57fa..34106335c728 100644
--- a/arch/arm/mach-kirkwood/Kconfig
+++ b/arch/arm/mach-kirkwood/Kconfig
@@ -58,6 +58,12 @@ config MACH_TS41X
QNAP TS-410, TS-410U, TS-419P and TS-419U Turbo NAS
devices.
+config MACH_DOCKSTAR
+ bool "Seagate FreeAgent DockStar"
+ help
+ Say 'Y' here if you want your kernel to support the
+ Seagate FreeAgent DockStar.
+
config MACH_OPENRD
bool
@@ -100,6 +106,12 @@ config MACH_NETSPACE_MAX_V2
Say 'Y' here if you want your kernel to support the
LaCie Network Space Max v2 NAS.
+config MACH_D2NET_V2
+ bool "LaCie d2 Network v2 NAS Board"
+ help
+ Say 'Y' here if you want your kernel to support the
+ LaCie d2 Network v2 NAS.
+
config MACH_NET2BIG_V2
bool "LaCie 2Big Network v2 NAS Board"
help
diff --git a/arch/arm/mach-kirkwood/Makefile b/arch/arm/mach-kirkwood/Makefile
index 295d7baa6ae1..5dcaa81a2ec3 100644
--- a/arch/arm/mach-kirkwood/Makefile
+++ b/arch/arm/mach-kirkwood/Makefile
@@ -7,14 +7,16 @@ obj-$(CONFIG_MACH_MV88F6281GTW_GE) += mv88f6281gtw_ge-setup.o
obj-$(CONFIG_MACH_SHEEVAPLUG) += sheevaplug-setup.o
obj-$(CONFIG_MACH_ESATA_SHEEVAPLUG) += sheevaplug-setup.o
obj-$(CONFIG_MACH_GURUPLUG) += guruplug-setup.o
+obj-$(CONFIG_MACH_DOCKSTAR) += dockstar-setup.o
obj-$(CONFIG_MACH_TS219) += ts219-setup.o tsx1x-common.o
obj-$(CONFIG_MACH_TS41X) += ts41x-setup.o tsx1x-common.o
obj-$(CONFIG_MACH_OPENRD) += openrd-setup.o
-obj-$(CONFIG_MACH_NETSPACE_V2) += netspace_v2-setup.o
-obj-$(CONFIG_MACH_INETSPACE_V2) += netspace_v2-setup.o
-obj-$(CONFIG_MACH_NETSPACE_MAX_V2) += netspace_v2-setup.o
-obj-$(CONFIG_MACH_NET2BIG_V2) += netxbig_v2-setup.o
-obj-$(CONFIG_MACH_NET5BIG_V2) += netxbig_v2-setup.o
+obj-$(CONFIG_MACH_NETSPACE_V2) += netspace_v2-setup.o lacie_v2-common.o
+obj-$(CONFIG_MACH_INETSPACE_V2) += netspace_v2-setup.o lacie_v2-common.o
+obj-$(CONFIG_MACH_NETSPACE_MAX_V2) += netspace_v2-setup.o lacie_v2-common.o
+obj-$(CONFIG_MACH_D2NET_V2) += d2net_v2-setup.o lacie_v2-common.o
+obj-$(CONFIG_MACH_NET2BIG_V2) += netxbig_v2-setup.o lacie_v2-common.o
+obj-$(CONFIG_MACH_NET5BIG_V2) += netxbig_v2-setup.o lacie_v2-common.o
obj-$(CONFIG_MACH_T5325) += t5325-setup.o
obj-$(CONFIG_CPU_IDLE) += cpuidle.o
diff --git a/arch/arm/mach-kirkwood/d2net_v2-setup.c b/arch/arm/mach-kirkwood/d2net_v2-setup.c
new file mode 100644
index 000000000000..4aa86e4a152c
--- /dev/null
+++ b/arch/arm/mach-kirkwood/d2net_v2-setup.c
@@ -0,0 +1,229 @@
+/*
+ * arch/arm/mach-kirkwood/d2net_v2-setup.c
+ *
+ * LaCie d2 Network Space v2 Board Setup
+ *
+ * Copyright (C) 2010 Simon Guinot <sguinot@lacie.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/ata_platform.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/input.h>
+#include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+#include <linux/leds.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <mach/kirkwood.h>
+#include <mach/leds-ns2.h>
+#include "common.h"
+#include "mpp.h"
+#include "lacie_v2-common.h"
+
+/*****************************************************************************
+ * Ethernet
+ ****************************************************************************/
+
+static struct mv643xx_eth_platform_data d2net_v2_ge00_data = {
+ .phy_addr = MV643XX_ETH_PHY_ADDR(8),
+};
+
+/*****************************************************************************
+ * SATA
+ ****************************************************************************/
+
+static struct mv_sata_platform_data d2net_v2_sata_data = {
+ .n_ports = 2,
+};
+
+/*****************************************************************************
+ * GPIO keys
+ ****************************************************************************/
+
+#define D2NET_V2_GPIO_PUSH_BUTTON 34
+#define D2NET_V2_GPIO_POWER_SWITCH_ON 13
+#define D2NET_V2_GPIO_POWER_SWITCH_OFF 15
+
+#define D2NET_V2_SWITCH_POWER_ON 0x1
+#define D2NET_V2_SWITCH_POWER_OFF 0x2
+
+static struct gpio_keys_button d2net_v2_buttons[] = {
+ [0] = {
+ .type = EV_SW,
+ .code = D2NET_V2_SWITCH_POWER_ON,
+ .gpio = D2NET_V2_GPIO_POWER_SWITCH_ON,
+ .desc = "Back power switch (on|auto)",
+ .active_low = 0,
+ },
+ [1] = {
+ .type = EV_SW,
+ .code = D2NET_V2_SWITCH_POWER_OFF,
+ .gpio = D2NET_V2_GPIO_POWER_SWITCH_OFF,
+ .desc = "Back power switch (auto|off)",
+ .active_low = 0,
+ },
+ [2] = {
+ .code = KEY_POWER,
+ .gpio = D2NET_V2_GPIO_PUSH_BUTTON,
+ .desc = "Front Push Button",
+ .active_low = 1,
+ },
+};
+
+static struct gpio_keys_platform_data d2net_v2_button_data = {
+ .buttons = d2net_v2_buttons,
+ .nbuttons = ARRAY_SIZE(d2net_v2_buttons),
+};
+
+static struct platform_device d2net_v2_gpio_buttons = {
+ .name = "gpio-keys",
+ .id = -1,
+ .dev = {
+ .platform_data = &d2net_v2_button_data,
+ },
+};
+
+/*****************************************************************************
+ * GPIO LEDs
+ ****************************************************************************/
+
+#define D2NET_V2_GPIO_RED_LED 12
+
+static struct gpio_led d2net_v2_gpio_led_pins[] = {
+ {
+ .name = "d2net_v2:red:fail",
+ .gpio = D2NET_V2_GPIO_RED_LED,
+ },
+};
+
+static struct gpio_led_platform_data d2net_v2_gpio_leds_data = {
+ .num_leds = ARRAY_SIZE(d2net_v2_gpio_led_pins),
+ .leds = d2net_v2_gpio_led_pins,
+};
+
+static struct platform_device d2net_v2_gpio_leds = {
+ .name = "leds-gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = &d2net_v2_gpio_leds_data,
+ },
+};
+
+/*****************************************************************************
+ * Dual-GPIO CPLD LEDs
+ ****************************************************************************/
+
+#define D2NET_V2_GPIO_BLUE_LED_SLOW 29
+#define D2NET_V2_GPIO_BLUE_LED_CMD 30
+
+static struct ns2_led d2net_v2_led_pins[] = {
+ {
+ .name = "d2net_v2:blue:sata",
+ .cmd = D2NET_V2_GPIO_BLUE_LED_CMD,
+ .slow = D2NET_V2_GPIO_BLUE_LED_SLOW,
+ },
+};
+
+static struct ns2_led_platform_data d2net_v2_leds_data = {
+ .num_leds = ARRAY_SIZE(d2net_v2_led_pins),
+ .leds = d2net_v2_led_pins,
+};
+
+static struct platform_device d2net_v2_leds = {
+ .name = "leds-ns2",
+ .id = -1,
+ .dev = {
+ .platform_data = &d2net_v2_leds_data,
+ },
+};
+
+/*****************************************************************************
+ * General Setup
+ ****************************************************************************/
+
+static unsigned int d2net_v2_mpp_config[] __initdata = {
+ MPP0_SPI_SCn,
+ MPP1_SPI_MOSI,
+ MPP2_SPI_SCK,
+ MPP3_SPI_MISO,
+ MPP6_SYSRST_OUTn,
+ MPP7_GPO, /* Request power-off */
+ MPP8_TW0_SDA,
+ MPP9_TW0_SCK,
+ MPP10_UART0_TXD,
+ MPP11_UART0_RXD,
+ MPP12_GPO, /* Red led */
+ MPP13_GPIO, /* Rear power switch (on|auto) */
+ MPP14_GPIO, /* USB fuse */
+ MPP15_GPIO, /* Rear power switch (auto|off) */
+ MPP16_GPIO, /* SATA 0 power */
+ MPP21_SATA0_ACTn,
+ MPP24_GPIO, /* USB mode select */
+ MPP26_GPIO, /* USB device vbus */
+ MPP28_GPIO, /* USB enable host vbus */
+ MPP29_GPIO, /* Blue led (slow register) */
+ MPP30_GPIO, /* Blue led (command register) */
+ MPP34_GPIO, /* Power button (1 = Released, 0 = Pushed) */
+ MPP35_GPIO, /* Inhibit power-off */
+ 0
+};
+
+#define D2NET_V2_GPIO_POWER_OFF 7
+
+static void d2net_v2_power_off(void)
+{
+ gpio_set_value(D2NET_V2_GPIO_POWER_OFF, 1);
+}
+
+static void __init d2net_v2_init(void)
+{
+ /*
+ * Basic setup. Needs to be called early.
+ */
+ kirkwood_init();
+ kirkwood_mpp_conf(d2net_v2_mpp_config);
+
+ lacie_v2_hdd_power_init(1);
+
+ kirkwood_ehci_init();
+ kirkwood_ge00_init(&d2net_v2_ge00_data);
+ kirkwood_sata_init(&d2net_v2_sata_data);
+ kirkwood_uart0_init();
+ lacie_v2_register_flash();
+ lacie_v2_register_i2c_devices();
+
+ platform_device_register(&d2net_v2_leds);
+ platform_device_register(&d2net_v2_gpio_leds);
+ platform_device_register(&d2net_v2_gpio_buttons);
+
+ if (gpio_request(D2NET_V2_GPIO_POWER_OFF, "power-off") == 0 &&
+ gpio_direction_output(D2NET_V2_GPIO_POWER_OFF, 0) == 0)
+ pm_power_off = d2net_v2_power_off;
+ else
+ pr_err("d2net_v2: failed to configure power-off GPIO\n");
+}
+
+MACHINE_START(D2NET_V2, "LaCie d2 Network v2")
+ .boot_params = 0x00000100,
+ .init_machine = d2net_v2_init,
+ .map_io = kirkwood_map_io,
+ .init_irq = kirkwood_init_irq,
+ .timer = &lacie_v2_timer,
+MACHINE_END
diff --git a/arch/arm/mach-kirkwood/db88f6281-bp-setup.c b/arch/arm/mach-kirkwood/db88f6281-bp-setup.c
index 16f6691e7c68..9ea71182d31a 100644
--- a/arch/arm/mach-kirkwood/db88f6281-bp-setup.c
+++ b/arch/arm/mach-kirkwood/db88f6281-bp-setup.c
@@ -97,8 +97,6 @@ subsys_initcall(db88f6281_pci_init);
MACHINE_START(DB88F6281_BP, "Marvell DB-88F6281-BP Development Board")
/* Maintainer: Saeed Bishara <saeed@marvell.com> */
- .phys_io = KIRKWOOD_REGS_PHYS_BASE,
- .io_pg_offst = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = 0x00000100,
.init_machine = db88f6281_init,
.map_io = kirkwood_map_io,
diff --git a/arch/arm/mach-kirkwood/dockstar-setup.c b/arch/arm/mach-kirkwood/dockstar-setup.c
new file mode 100644
index 000000000000..433ea368c060
--- /dev/null
+++ b/arch/arm/mach-kirkwood/dockstar-setup.c
@@ -0,0 +1,110 @@
+/*
+ * arch/arm/mach-kirkwood/dockstar-setup.c
+ *
+ * Seagate FreeAgent DockStar Setup
+ *
+ * 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 <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/ata_platform.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <mach/kirkwood.h>
+#include <plat/mvsdio.h>
+#include "common.h"
+#include "mpp.h"
+
+static struct mtd_partition dockstar_nand_parts[] = {
+ {
+ .name = "u-boot",
+ .offset = 0,
+ .size = SZ_1M
+ }, {
+ .name = "uImage",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = SZ_4M
+ }, {
+ .name = "root",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = MTDPART_SIZ_FULL
+ },
+};
+
+static struct mv643xx_eth_platform_data dockstar_ge00_data = {
+ .phy_addr = MV643XX_ETH_PHY_ADDR(0),
+};
+
+static struct gpio_led dockstar_led_pins[] = {
+ {
+ .name = "dockstar:green:health",
+ .default_trigger = "default-on",
+ .gpio = 46,
+ .active_low = 1,
+ },
+ {
+ .name = "dockstar:orange:misc",
+ .default_trigger = "none",
+ .gpio = 47,
+ .active_low = 1,
+ },
+};
+
+static struct gpio_led_platform_data dockstar_led_data = {
+ .leds = dockstar_led_pins,
+ .num_leds = ARRAY_SIZE(dockstar_led_pins),
+};
+
+static struct platform_device dockstar_leds = {
+ .name = "leds-gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = &dockstar_led_data,
+ }
+};
+
+static unsigned int dockstar_mpp_config[] __initdata = {
+ MPP29_GPIO, /* USB Power Enable */
+ MPP46_GPIO, /* LED green */
+ MPP47_GPIO, /* LED orange */
+ 0
+};
+
+static void __init dockstar_init(void)
+{
+ /*
+ * Basic setup. Needs to be called early.
+ */
+ kirkwood_init();
+
+ /* setup gpio pin select */
+ kirkwood_mpp_conf(dockstar_mpp_config);
+
+ kirkwood_uart0_init();
+ kirkwood_nand_init(ARRAY_AND_SIZE(dockstar_nand_parts), 25);
+
+ if (gpio_request(29, "USB Power Enable") != 0 ||
+ gpio_direction_output(29, 1) != 0)
+ printk(KERN_ERR "can't set up GPIO 29 (USB Power Enable)\n");
+ kirkwood_ehci_init();
+
+ kirkwood_ge00_init(&dockstar_ge00_data);
+
+ platform_device_register(&dockstar_leds);
+}
+
+MACHINE_START(DOCKSTAR, "Seagate FreeAgent DockStar")
+ .boot_params = 0x00000100,
+ .init_machine = dockstar_init,
+ .map_io = kirkwood_map_io,
+ .init_irq = kirkwood_init_irq,
+ .timer = &kirkwood_timer,
+MACHINE_END
diff --git a/arch/arm/mach-kirkwood/guruplug-setup.c b/arch/arm/mach-kirkwood/guruplug-setup.c
index 54d07c89d4ff..8f47dc0a2fef 100644
--- a/arch/arm/mach-kirkwood/guruplug-setup.c
+++ b/arch/arm/mach-kirkwood/guruplug-setup.c
@@ -121,8 +121,6 @@ static void __init guruplug_init(void)
MACHINE_START(GURUPLUG, "Marvell GuruPlug Reference Board")
/* Maintainer: Siddarth Gore <gores@marvell.com> */
- .phys_io = KIRKWOOD_REGS_PHYS_BASE,
- .io_pg_offst = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = 0x00000100,
.init_machine = guruplug_init,
.map_io = kirkwood_map_io,
diff --git a/arch/arm/mach-kirkwood/include/mach/debug-macro.S b/arch/arm/mach-kirkwood/include/mach/debug-macro.S
index d0606774dea7..db06ae437d08 100644
--- a/arch/arm/mach-kirkwood/include/mach/debug-macro.S
+++ b/arch/arm/mach-kirkwood/include/mach/debug-macro.S
@@ -8,12 +8,11 @@
#include <mach/bridge-regs.h>
- .macro addruart, rx, tmp
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ MMU enabled?
- ldreq \rx, =KIRKWOOD_REGS_PHYS_BASE
- ldrne \rx, =KIRKWOOD_REGS_VIRT_BASE
- orr \rx, \rx, #0x00012000
+ .macro addruart, rp, rv
+ ldr \rp, =KIRKWOOD_REGS_PHYS_BASE
+ ldr \rv, =KIRKWOOD_REGS_VIRT_BASE
+ orr \rp, \rp, #0x00012000
+ orr \rv, \rv, #0x00012000
.endm
#define UART_SHIFT 2
diff --git a/arch/arm/mach-kirkwood/include/mach/leds-netxbig.h b/arch/arm/mach-kirkwood/include/mach/leds-netxbig.h
new file mode 100644
index 000000000000..24b536ebdf13
--- /dev/null
+++ b/arch/arm/mach-kirkwood/include/mach/leds-netxbig.h
@@ -0,0 +1,55 @@
+/*
+ * arch/arm/mach-kirkwood/include/mach/leds-netxbig.h
+ *
+ * Platform data structure for netxbig LED driver
+ *
+ * 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.
+ */
+
+#ifndef __MACH_LEDS_NETXBIG_H
+#define __MACH_LEDS_NETXBIG_H
+
+struct netxbig_gpio_ext {
+ unsigned *addr;
+ int num_addr;
+ unsigned *data;
+ int num_data;
+ unsigned enable;
+};
+
+enum netxbig_led_mode {
+ NETXBIG_LED_OFF,
+ NETXBIG_LED_ON,
+ NETXBIG_LED_SATA,
+ NETXBIG_LED_TIMER1,
+ NETXBIG_LED_TIMER2,
+ NETXBIG_LED_MODE_NUM,
+};
+
+#define NETXBIG_LED_INVALID_MODE NETXBIG_LED_MODE_NUM
+
+struct netxbig_led_timer {
+ unsigned long delay_on;
+ unsigned long delay_off;
+ enum netxbig_led_mode mode;
+};
+
+struct netxbig_led {
+ const char *name;
+ const char *default_trigger;
+ int mode_addr;
+ int *mode_val;
+ int bright_addr;
+};
+
+struct netxbig_led_platform_data {
+ struct netxbig_gpio_ext *gpio_ext;
+ struct netxbig_led_timer *timer;
+ int num_timer;
+ struct netxbig_led *leds;
+ int num_leds;
+};
+
+#endif /* __MACH_LEDS_NETXBIG_H */
diff --git a/arch/arm/mach-kirkwood/lacie_v2-common.c b/arch/arm/mach-kirkwood/lacie_v2-common.c
new file mode 100644
index 000000000000..d3ea1b6c8a02
--- /dev/null
+++ b/arch/arm/mach-kirkwood/lacie_v2-common.c
@@ -0,0 +1,127 @@
+/*
+ * arch/arm/mach-kirkwood/lacie_v2-common.c
+ *
+ * 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 <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mtd/physmap.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
+#include <linux/i2c.h>
+#include <linux/i2c/at24.h>
+#include <linux/gpio.h>
+#include <asm/mach/time.h>
+#include <mach/kirkwood.h>
+#include <mach/irqs.h>
+#include <plat/time.h>
+#include "common.h"
+
+/*****************************************************************************
+ * 512KB SPI Flash on Boot Device (MACRONIX MX25L4005)
+ ****************************************************************************/
+
+static struct mtd_partition lacie_v2_flash_parts[] = {
+ {
+ .name = "u-boot",
+ .size = MTDPART_SIZ_FULL,
+ .offset = 0,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+};
+
+static const struct flash_platform_data lacie_v2_flash = {
+ .type = "mx25l4005a",
+ .name = "spi_flash",
+ .parts = lacie_v2_flash_parts,
+ .nr_parts = ARRAY_SIZE(lacie_v2_flash_parts),
+};
+
+static struct spi_board_info __initdata lacie_v2_spi_slave_info[] = {
+ {
+ .modalias = "m25p80",
+ .platform_data = &lacie_v2_flash,
+ .irq = -1,
+ .max_speed_hz = 20000000,
+ .bus_num = 0,
+ .chip_select = 0,
+ },
+};
+
+void __init lacie_v2_register_flash(void)
+{
+ spi_register_board_info(lacie_v2_spi_slave_info,
+ ARRAY_SIZE(lacie_v2_spi_slave_info));
+ kirkwood_spi_init();
+}
+
+/*****************************************************************************
+ * I2C devices
+ ****************************************************************************/
+
+static struct at24_platform_data at24c04 = {
+ .byte_len = SZ_4K / 8,
+ .page_size = 16,
+};
+
+/*
+ * i2c addr | chip | description
+ * 0x50 | HT24LC04 | eeprom (512B)
+ */
+
+static struct i2c_board_info __initdata lacie_v2_i2c_info[] = {
+ {
+ I2C_BOARD_INFO("24c04", 0x50),
+ .platform_data = &at24c04,
+ }
+};
+
+void __init lacie_v2_register_i2c_devices(void)
+{
+ kirkwood_i2c_init();
+ i2c_register_board_info(0, lacie_v2_i2c_info,
+ ARRAY_SIZE(lacie_v2_i2c_info));
+}
+
+/*****************************************************************************
+ * Hard Disk power
+ ****************************************************************************/
+
+static int __initdata lacie_v2_gpio_hdd_power[] = { 16, 17, 41, 42, 43 };
+
+void __init lacie_v2_hdd_power_init(int hdd_num)
+{
+ int i;
+ int err;
+
+ /* Power up all hard disks. */
+ for (i = 0; i < hdd_num; i++) {
+ err = gpio_request(lacie_v2_gpio_hdd_power[i], NULL);
+ if (err == 0) {
+ err = gpio_direction_output(
+ lacie_v2_gpio_hdd_power[i], 1);
+ /* Free the HDD power GPIOs. This allow user-space to
+ * configure them via the gpiolib sysfs interface. */
+ gpio_free(lacie_v2_gpio_hdd_power[i]);
+ }
+ if (err)
+ pr_err("Failed to power up HDD%d\n", i + 1);
+ }
+}
+
+/*****************************************************************************
+ * Timer
+ ****************************************************************************/
+
+static void lacie_v2_timer_init(void)
+{
+ kirkwood_tclk = 166666667;
+ orion_time_init(IRQ_KIRKWOOD_BRIDGE, kirkwood_tclk);
+}
+
+struct sys_timer lacie_v2_timer = {
+ .init = lacie_v2_timer_init,
+};
diff --git a/arch/arm/mach-kirkwood/lacie_v2-common.h b/arch/arm/mach-kirkwood/lacie_v2-common.h
new file mode 100644
index 000000000000..af521315b87b
--- /dev/null
+++ b/arch/arm/mach-kirkwood/lacie_v2-common.h
@@ -0,0 +1,18 @@
+/*
+ * arch/arm/mach-kirkwood/lacie_v2-common.h
+ *
+ * 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.
+ */
+
+#ifndef __ARCH_KIRKWOOD_LACIE_V2_COMMON_H
+#define __ARCH_KIRKWOOD_LACIE_V2_COMMON_H
+
+void lacie_v2_register_flash(void);
+void lacie_v2_register_i2c_devices(void);
+void lacie_v2_hdd_power_init(int hdd_num);
+
+extern struct sys_timer lacie_v2_timer;
+
+#endif
diff --git a/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c b/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c
index c6b92b42eb4e..1e5266f57e2a 100644
--- a/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c
+++ b/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c
@@ -163,8 +163,6 @@ subsys_initcall(mv88f6281gtw_ge_pci_init);
MACHINE_START(MV88F6281GTW_GE, "Marvell 88F6281 GTW GE Board")
/* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */
- .phys_io = KIRKWOOD_REGS_PHYS_BASE,
- .io_pg_offst = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = 0x00000100,
.init_machine = mv88f6281gtw_ge_init,
.map_io = kirkwood_map_io,
diff --git a/arch/arm/mach-kirkwood/netspace_v2-setup.c b/arch/arm/mach-kirkwood/netspace_v2-setup.c
index d26bf324738b..5e286441b8f4 100644
--- a/arch/arm/mach-kirkwood/netspace_v2-setup.c
+++ b/arch/arm/mach-kirkwood/netspace_v2-setup.c
@@ -24,56 +24,19 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
-#include <linux/mtd/physmap.h>
-#include <linux/spi/flash.h>
-#include <linux/spi/spi.h>
#include <linux/ata_platform.h>
#include <linux/mv643xx_eth.h>
-#include <linux/i2c.h>
-#include <linux/i2c/at24.h>
#include <linux/input.h>
#include <linux/gpio.h>
#include <linux/gpio_keys.h>
#include <linux/leds.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
#include <mach/kirkwood.h>
#include <mach/leds-ns2.h>
-#include <plat/time.h>
#include "common.h"
#include "mpp.h"
-
-/*****************************************************************************
- * 512KB SPI Flash on Boot Device (MACRONIX MX25L4005)
- ****************************************************************************/
-
-static struct mtd_partition netspace_v2_flash_parts[] = {
- {
- .name = "u-boot",
- .size = MTDPART_SIZ_FULL,
- .offset = 0,
- .mask_flags = MTD_WRITEABLE, /* force read-only */
- },
-};
-
-static const struct flash_platform_data netspace_v2_flash = {
- .type = "mx25l4005a",
- .name = "spi_flash",
- .parts = netspace_v2_flash_parts,
- .nr_parts = ARRAY_SIZE(netspace_v2_flash_parts),
-};
-
-static struct spi_board_info __initdata netspace_v2_spi_slave_info[] = {
- {
- .modalias = "m25p80",
- .platform_data = &netspace_v2_flash,
- .irq = -1,
- .max_speed_hz = 20000000,
- .bus_num = 0,
- .chip_select = 0,
- },
-};
+#include "lacie_v2-common.h"
/*****************************************************************************
* Ethernet
@@ -84,27 +47,6 @@ static struct mv643xx_eth_platform_data netspace_v2_ge00_data = {
};
/*****************************************************************************
- * I2C devices
- ****************************************************************************/
-
-static struct at24_platform_data at24c04 = {
- .byte_len = SZ_4K / 8,
- .page_size = 16,
-};
-
-/*
- * i2c addr | chip | description
- * 0x50 | HT24LC04 | eeprom (512B)
- */
-
-static struct i2c_board_info __initdata netspace_v2_i2c_info[] = {
- {
- I2C_BOARD_INFO("24c04", 0x50),
- .platform_data = &at24c04,
- }
-};
-
-/*****************************************************************************
* SATA
****************************************************************************/
@@ -112,35 +54,6 @@ static struct mv_sata_platform_data netspace_v2_sata_data = {
.n_ports = 2,
};
-#define NETSPACE_V2_GPIO_SATA0_POWER 16
-#define NETSPACE_V2_GPIO_SATA1_POWER 17
-
-static void __init netspace_v2_sata_power_init(void)
-{
- int err;
-
- err = gpio_request(NETSPACE_V2_GPIO_SATA0_POWER, "SATA0 power");
- if (err == 0) {
- err = gpio_direction_output(NETSPACE_V2_GPIO_SATA0_POWER, 1);
- if (err)
- gpio_free(NETSPACE_V2_GPIO_SATA0_POWER);
- }
- if (err)
- pr_err("netspace_v2: failed to setup SATA0 power\n");
-
- if (machine_is_netspace_max_v2()) {
- err = gpio_request(NETSPACE_V2_GPIO_SATA1_POWER, "SATA1 power");
- if (err == 0) {
- err = gpio_direction_output(
- NETSPACE_V2_GPIO_SATA1_POWER, 1);
- if (err)
- gpio_free(NETSPACE_V2_GPIO_SATA1_POWER);
- }
- if (err)
- pr_err("netspace_v2: failed to setup SATA1 power\n");
- }
-}
-
/*****************************************************************************
* GPIO keys
****************************************************************************/
@@ -224,20 +137,6 @@ static struct platform_device netspace_v2_leds = {
};
/*****************************************************************************
- * Timer
- ****************************************************************************/
-
-static void netspace_v2_timer_init(void)
-{
- kirkwood_tclk = 166666667;
- orion_time_init(IRQ_KIRKWOOD_BRIDGE, kirkwood_tclk);
-}
-
-struct sys_timer netspace_v2_timer = {
- .init = netspace_v2_timer_init,
-};
-
-/*****************************************************************************
* General Setup
****************************************************************************/
@@ -291,18 +190,17 @@ static void __init netspace_v2_init(void)
kirkwood_init();
kirkwood_mpp_conf(netspace_v2_mpp_config);
- netspace_v2_sata_power_init();
+ if (machine_is_netspace_max_v2())
+ lacie_v2_hdd_power_init(2);
+ else
+ lacie_v2_hdd_power_init(1);
kirkwood_ehci_init();
kirkwood_ge00_init(&netspace_v2_ge00_data);
kirkwood_sata_init(&netspace_v2_sata_data);
kirkwood_uart0_init();
- spi_register_board_info(netspace_v2_spi_slave_info,
- ARRAY_SIZE(netspace_v2_spi_slave_info));
- kirkwood_spi_init();
- kirkwood_i2c_init();
- i2c_register_board_info(0, netspace_v2_i2c_info,
- ARRAY_SIZE(netspace_v2_i2c_info));
+ lacie_v2_register_flash();
+ lacie_v2_register_i2c_devices();
platform_device_register(&netspace_v2_leds);
platform_device_register(&netspace_v2_gpio_leds);
@@ -317,36 +215,30 @@ static void __init netspace_v2_init(void)
#ifdef CONFIG_MACH_NETSPACE_V2
MACHINE_START(NETSPACE_V2, "LaCie Network Space v2")
- .phys_io = KIRKWOOD_REGS_PHYS_BASE,
- .io_pg_offst = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = 0x00000100,
.init_machine = netspace_v2_init,
.map_io = kirkwood_map_io,
.init_irq = kirkwood_init_irq,
- .timer = &netspace_v2_timer,
+ .timer = &lacie_v2_timer,
MACHINE_END
#endif
#ifdef CONFIG_MACH_INETSPACE_V2
MACHINE_START(INETSPACE_V2, "LaCie Internet Space v2")
- .phys_io = KIRKWOOD_REGS_PHYS_BASE,
- .io_pg_offst = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = 0x00000100,
.init_machine = netspace_v2_init,
.map_io = kirkwood_map_io,
.init_irq = kirkwood_init_irq,
- .timer = &netspace_v2_timer,
+ .timer = &lacie_v2_timer,
MACHINE_END
#endif
#ifdef CONFIG_MACH_NETSPACE_MAX_V2
MACHINE_START(NETSPACE_MAX_V2, "LaCie Network Space Max v2")
- .phys_io = KIRKWOOD_REGS_PHYS_BASE,
- .io_pg_offst = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = 0x00000100,
.init_machine = netspace_v2_init,
.map_io = kirkwood_map_io,
.init_irq = kirkwood_init_irq,
- .timer = &netspace_v2_timer,
+ .timer = &lacie_v2_timer,
MACHINE_END
#endif
diff --git a/arch/arm/mach-kirkwood/netxbig_v2-setup.c b/arch/arm/mach-kirkwood/netxbig_v2-setup.c
index 2bd14c5079de..a1b45d501aef 100644
--- a/arch/arm/mach-kirkwood/netxbig_v2-setup.c
+++ b/arch/arm/mach-kirkwood/netxbig_v2-setup.c
@@ -23,55 +23,19 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
-#include <linux/mtd/physmap.h>
-#include <linux/spi/flash.h>
-#include <linux/spi/spi.h>
#include <linux/ata_platform.h>
#include <linux/mv643xx_eth.h>
-#include <linux/i2c.h>
-#include <linux/i2c/at24.h>
#include <linux/input.h>
#include <linux/gpio.h>
#include <linux/gpio_keys.h>
#include <linux/leds.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
#include <mach/kirkwood.h>
-#include <plat/time.h>
+#include <mach/leds-netxbig.h>
#include "common.h"
#include "mpp.h"
-
-/*****************************************************************************
- * 512KB SPI Flash on Boot Device (MACRONIX MX25L4005)
- ****************************************************************************/
-
-static struct mtd_partition netxbig_v2_flash_parts[] = {
- {
- .name = "u-boot",
- .size = MTDPART_SIZ_FULL,
- .offset = 0,
- .mask_flags = MTD_WRITEABLE, /* force read-only */
- },
-};
-
-static const struct flash_platform_data netxbig_v2_flash = {
- .type = "mx25l4005a",
- .name = "spi_flash",
- .parts = netxbig_v2_flash_parts,
- .nr_parts = ARRAY_SIZE(netxbig_v2_flash_parts),
-};
-
-static struct spi_board_info __initdata netxbig_v2_spi_slave_info[] = {
- {
- .modalias = "m25p80",
- .platform_data = &netxbig_v2_flash,
- .irq = -1,
- .max_speed_hz = 20000000,
- .bus_num = 0,
- .chip_select = 0,
- },
-};
+#include "lacie_v2-common.h"
/*****************************************************************************
* Ethernet
@@ -86,27 +50,6 @@ static struct mv643xx_eth_platform_data netxbig_v2_ge01_data = {
};
/*****************************************************************************
- * I2C devices
- ****************************************************************************/
-
-static struct at24_platform_data at24c04 = {
- .byte_len = SZ_4K / 8,
- .page_size = 16,
-};
-
-/*
- * i2c addr | chip | description
- * 0x50 | HT24LC04 | eeprom (512B)
- */
-
-static struct i2c_board_info __initdata netxbig_v2_i2c_info[] = {
- {
- I2C_BOARD_INFO("24c04", 0x50),
- .platform_data = &at24c04,
- }
-};
-
-/*****************************************************************************
* SATA
****************************************************************************/
@@ -114,34 +57,6 @@ static struct mv_sata_platform_data netxbig_v2_sata_data = {
.n_ports = 2,
};
-static int __initdata netxbig_v2_gpio_hdd_power[] = { 16, 17, 41, 42, 43 };
-
-static void __init netxbig_v2_sata_power_init(void)
-{
- int i;
- int err;
- int hdd_nb;
-
- if (machine_is_net2big_v2())
- hdd_nb = 2;
- else
- hdd_nb = 5;
-
- /* Power up all hard disks. */
- for (i = 0; i < hdd_nb; i++) {
- err = gpio_request(netxbig_v2_gpio_hdd_power[i], NULL);
- if (err == 0) {
- err = gpio_direction_output(
- netxbig_v2_gpio_hdd_power[i], 1);
- /* Free the HDD power GPIOs. This allow user-space to
- * configure them via the gpiolib sysfs interface. */
- gpio_free(netxbig_v2_gpio_hdd_power[i]);
- }
- if (err)
- pr_err("netxbig_v2: failed to power up HDD%d\n", i + 1);
- }
-}
-
/*****************************************************************************
* GPIO keys
****************************************************************************/
@@ -190,7 +105,7 @@ static struct platform_device netxbig_v2_gpio_buttons = {
};
/*****************************************************************************
- * GPIO LEDs
+ * GPIO extension LEDs
****************************************************************************/
/*
@@ -200,19 +115,32 @@ static struct platform_device netxbig_v2_gpio_buttons = {
* - address register : bit [0-2] -> GPIO [47-49]
* - data register : bit [0-2] -> GPIO [44-46]
* - enable register : GPIO 29
- *
+ */
+
+static int netxbig_v2_gpio_ext_addr[] = { 47, 48, 49 };
+static int netxbig_v2_gpio_ext_data[] = { 44, 45, 46 };
+
+static struct netxbig_gpio_ext netxbig_v2_gpio_ext = {
+ .addr = netxbig_v2_gpio_ext_addr,
+ .num_addr = ARRAY_SIZE(netxbig_v2_gpio_ext_addr),
+ .data = netxbig_v2_gpio_ext_data,
+ .num_data = ARRAY_SIZE(netxbig_v2_gpio_ext_data),
+ .enable = 29,
+};
+
+/*
* Address register selection:
*
* addr | register
* ----------------------------
* 0 | front LED
* 1 | front LED brightness
- * 2 | HDD LED brightness
- * 3 | HDD1 LED
- * 4 | HDD2 LED
- * 5 | HDD3 LED
- * 6 | HDD4 LED
- * 7 | HDD5 LED
+ * 2 | SATA LED brightness
+ * 3 | SATA0 LED
+ * 4 | SATA1 LED
+ * 5 | SATA2 LED
+ * 6 | SATA3 LED
+ * 7 | SATA4 LED
*
* Data register configuration:
*
@@ -233,30 +161,107 @@ static struct platform_device netxbig_v2_gpio_buttons = {
* 6 | blink blue on=1 sec and red on=1 sec
* 7 | blink blue on=0.5 sec and blue off=2.5 sec
*
- * data | HDD LED mode
+ * data | SATA LED mode
* -------------------------------------------------
- * 0 | fix blue on
+ * 0 | fix off
* 1 | SATA activity blink
* 2 | fix red on
* 3 | blink blue on=1 sec and blue off=1 sec
* 4 | blink red on=1 sec and red off=1 sec
* 5 | blink blue on=2.5 sec and red on=0.5 sec
* 6 | blink blue on=1 sec and red on=1 sec
- * 7 | blink blue on=0.5 sec and blue off=2.5 sec
+ * 7 | fix blue on
*/
-/*****************************************************************************
- * Timer
- ****************************************************************************/
+static int netxbig_v2_red_mled[NETXBIG_LED_MODE_NUM] = {
+ [NETXBIG_LED_OFF] = 0,
+ [NETXBIG_LED_ON] = 2,
+ [NETXBIG_LED_SATA] = NETXBIG_LED_INVALID_MODE,
+ [NETXBIG_LED_TIMER1] = 4,
+ [NETXBIG_LED_TIMER2] = NETXBIG_LED_INVALID_MODE,
+};
-static void netxbig_v2_timer_init(void)
-{
- kirkwood_tclk = 166666667;
- orion_time_init(IRQ_KIRKWOOD_BRIDGE, kirkwood_tclk);
-}
+static int netxbig_v2_blue_pwr_mled[NETXBIG_LED_MODE_NUM] = {
+ [NETXBIG_LED_OFF] = 0,
+ [NETXBIG_LED_ON] = 1,
+ [NETXBIG_LED_SATA] = NETXBIG_LED_INVALID_MODE,
+ [NETXBIG_LED_TIMER1] = 3,
+ [NETXBIG_LED_TIMER2] = 7,
+};
+
+static int netxbig_v2_blue_sata_mled[NETXBIG_LED_MODE_NUM] = {
+ [NETXBIG_LED_OFF] = 0,
+ [NETXBIG_LED_ON] = 7,
+ [NETXBIG_LED_SATA] = 1,
+ [NETXBIG_LED_TIMER1] = 3,
+ [NETXBIG_LED_TIMER2] = NETXBIG_LED_INVALID_MODE,
+};
+
+static struct netxbig_led_timer netxbig_v2_led_timer[] = {
+ [0] = {
+ .delay_on = 500,
+ .delay_off = 500,
+ .mode = NETXBIG_LED_TIMER1,
+ },
+ [1] = {
+ .delay_on = 500,
+ .delay_off = 1000,
+ .mode = NETXBIG_LED_TIMER2,
+ },
+};
+
+#define NETXBIG_LED(_name, maddr, mval, baddr) \
+ { .name = _name, \
+ .mode_addr = maddr, \
+ .mode_val = mval, \
+ .bright_addr = baddr }
+
+static struct netxbig_led net2big_v2_leds_ctrl[] = {
+ NETXBIG_LED("net2big-v2:blue:power", 0, netxbig_v2_blue_pwr_mled, 1),
+ NETXBIG_LED("net2big-v2:red:power", 0, netxbig_v2_red_mled, 1),
+ NETXBIG_LED("net2big-v2:blue:sata0", 3, netxbig_v2_blue_sata_mled, 2),
+ NETXBIG_LED("net2big-v2:red:sata0", 3, netxbig_v2_red_mled, 2),
+ NETXBIG_LED("net2big-v2:blue:sata1", 4, netxbig_v2_blue_sata_mled, 2),
+ NETXBIG_LED("net2big-v2:red:sata1", 4, netxbig_v2_red_mled, 2),
+};
+
+static struct netxbig_led_platform_data net2big_v2_leds_data = {
+ .gpio_ext = &netxbig_v2_gpio_ext,
+ .timer = netxbig_v2_led_timer,
+ .num_timer = ARRAY_SIZE(netxbig_v2_led_timer),
+ .leds = net2big_v2_leds_ctrl,
+ .num_leds = ARRAY_SIZE(net2big_v2_leds_ctrl),
+};
+
+static struct netxbig_led net5big_v2_leds_ctrl[] = {
+ NETXBIG_LED("net5big-v2:blue:power", 0, netxbig_v2_blue_pwr_mled, 1),
+ NETXBIG_LED("net5big-v2:red:power", 0, netxbig_v2_red_mled, 1),
+ NETXBIG_LED("net5big-v2:blue:sata0", 3, netxbig_v2_blue_sata_mled, 2),
+ NETXBIG_LED("net5big-v2:red:sata0", 3, netxbig_v2_red_mled, 2),
+ NETXBIG_LED("net5big-v2:blue:sata1", 4, netxbig_v2_blue_sata_mled, 2),
+ NETXBIG_LED("net5big-v2:red:sata1", 4, netxbig_v2_red_mled, 2),
+ NETXBIG_LED("net5big-v2:blue:sata2", 5, netxbig_v2_blue_sata_mled, 2),
+ NETXBIG_LED("net5big-v2:red:sata2", 5, netxbig_v2_red_mled, 2),
+ NETXBIG_LED("net5big-v2:blue:sata3", 6, netxbig_v2_blue_sata_mled, 2),
+ NETXBIG_LED("net5big-v2:red:sata3", 6, netxbig_v2_red_mled, 2),
+ NETXBIG_LED("net5big-v2:blue:sata4", 7, netxbig_v2_blue_sata_mled, 2),
+ NETXBIG_LED("net5big-v2:red:sata5", 7, netxbig_v2_red_mled, 2),
+};
-struct sys_timer netxbig_v2_timer = {
- .init = netxbig_v2_timer_init,
+static struct netxbig_led_platform_data net5big_v2_leds_data = {
+ .gpio_ext = &netxbig_v2_gpio_ext,
+ .timer = netxbig_v2_led_timer,
+ .num_timer = ARRAY_SIZE(netxbig_v2_led_timer),
+ .leds = net5big_v2_leds_ctrl,
+ .num_leds = ARRAY_SIZE(net5big_v2_leds_ctrl),
+};
+
+static struct platform_device netxbig_v2_leds = {
+ .name = "leds-netxbig",
+ .id = -1,
+ .dev = {
+ .platform_data = &net2big_v2_leds_data,
+ },
};
/*****************************************************************************
@@ -284,18 +289,18 @@ static unsigned int net2big_v2_mpp_config[] __initdata = {
MPP24_GPIO, /* USB mode select */
MPP26_GPIO, /* USB device vbus */
MPP28_GPIO, /* USB enable host vbus */
- MPP29_GPIO, /* CPLD extension ALE */
+ MPP29_GPIO, /* GPIO extension ALE */
MPP34_GPIO, /* Rear Push button */
MPP35_GPIO, /* Inhibit switch power-off */
MPP36_GPIO, /* SATA HDD1 presence */
MPP37_GPIO, /* SATA HDD2 presence */
MPP40_GPIO, /* eSATA presence */
- MPP44_GPIO, /* CPLD extension (data 0) */
- MPP45_GPIO, /* CPLD extension (data 1) */
- MPP46_GPIO, /* CPLD extension (data 2) */
- MPP47_GPIO, /* CPLD extension (addr 0) */
- MPP48_GPIO, /* CPLD extension (addr 1) */
- MPP49_GPIO, /* CPLD extension (addr 2) */
+ MPP44_GPIO, /* GPIO extension (data 0) */
+ MPP45_GPIO, /* GPIO extension (data 1) */
+ MPP46_GPIO, /* GPIO extension (data 2) */
+ MPP47_GPIO, /* GPIO extension (addr 0) */
+ MPP48_GPIO, /* GPIO extension (addr 1) */
+ MPP49_GPIO, /* GPIO extension (addr 2) */
0
};
@@ -324,7 +329,7 @@ static unsigned int net5big_v2_mpp_config[] __initdata = {
MPP26_GE1_RXD2,
MPP27_GE1_RXD3,
MPP28_GPIO, /* USB enable host vbus */
- MPP29_GPIO, /* CPLD extension ALE */
+ MPP29_GPIO, /* GPIO extension ALE */
MPP30_GE1_RXCTL,
MPP31_GE1_RXCLK,
MPP32_GE1_TCLKOUT,
@@ -339,12 +344,12 @@ static unsigned int net5big_v2_mpp_config[] __initdata = {
MPP41_GPIO, /* SATA HDD3 power */
MPP42_GPIO, /* SATA HDD4 power */
MPP43_GPIO, /* SATA HDD5 power */
- MPP44_GPIO, /* CPLD extension (data 0) */
- MPP45_GPIO, /* CPLD extension (data 1) */
- MPP46_GPIO, /* CPLD extension (data 2) */
- MPP47_GPIO, /* CPLD extension (addr 0) */
- MPP48_GPIO, /* CPLD extension (addr 1) */
- MPP49_GPIO, /* CPLD extension (addr 2) */
+ MPP44_GPIO, /* GPIO extension (data 0) */
+ MPP45_GPIO, /* GPIO extension (data 1) */
+ MPP46_GPIO, /* GPIO extension (data 2) */
+ MPP47_GPIO, /* GPIO extension (addr 0) */
+ MPP48_GPIO, /* GPIO extension (addr 1) */
+ MPP49_GPIO, /* GPIO extension (addr 2) */
0
};
@@ -366,7 +371,10 @@ static void __init netxbig_v2_init(void)
else
kirkwood_mpp_conf(net5big_v2_mpp_config);
- netxbig_v2_sata_power_init();
+ if (machine_is_net2big_v2())
+ lacie_v2_hdd_power_init(2);
+ else
+ lacie_v2_hdd_power_init(5);
kirkwood_ehci_init();
kirkwood_ge00_init(&netxbig_v2_ge00_data);
@@ -374,13 +382,12 @@ static void __init netxbig_v2_init(void)
kirkwood_ge01_init(&netxbig_v2_ge01_data);
kirkwood_sata_init(&netxbig_v2_sata_data);
kirkwood_uart0_init();
- spi_register_board_info(netxbig_v2_spi_slave_info,
- ARRAY_SIZE(netxbig_v2_spi_slave_info));
- kirkwood_spi_init();
- kirkwood_i2c_init();
- i2c_register_board_info(0, netxbig_v2_i2c_info,
- ARRAY_SIZE(netxbig_v2_i2c_info));
+ lacie_v2_register_flash();
+ lacie_v2_register_i2c_devices();
+ if (machine_is_net5big_v2())
+ netxbig_v2_leds.dev.platform_data = &net5big_v2_leds_data;
+ platform_device_register(&netxbig_v2_leds);
platform_device_register(&netxbig_v2_gpio_buttons);
if (gpio_request(NETXBIG_V2_GPIO_POWER_OFF, "power-off") == 0 &&
@@ -392,24 +399,20 @@ static void __init netxbig_v2_init(void)
#ifdef CONFIG_MACH_NET2BIG_V2
MACHINE_START(NET2BIG_V2, "LaCie 2Big Network v2")
- .phys_io = KIRKWOOD_REGS_PHYS_BASE,
- .io_pg_offst = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = 0x00000100,
.init_machine = netxbig_v2_init,
.map_io = kirkwood_map_io,
.init_irq = kirkwood_init_irq,
- .timer = &netxbig_v2_timer,
+ .timer = &lacie_v2_timer,
MACHINE_END
#endif
#ifdef CONFIG_MACH_NET5BIG_V2
MACHINE_START(NET5BIG_V2, "LaCie 5Big Network v2")
- .phys_io = KIRKWOOD_REGS_PHYS_BASE,
- .io_pg_offst = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = 0x00000100,
.init_machine = netxbig_v2_init,
.map_io = kirkwood_map_io,
.init_irq = kirkwood_init_irq,
- .timer = &netxbig_v2_timer,
+ .timer = &lacie_v2_timer,
MACHINE_END
#endif
diff --git a/arch/arm/mach-kirkwood/openrd-setup.c b/arch/arm/mach-kirkwood/openrd-setup.c
index fd06be618815..c9d77fad10ab 100644
--- a/arch/arm/mach-kirkwood/openrd-setup.c
+++ b/arch/arm/mach-kirkwood/openrd-setup.c
@@ -16,6 +16,7 @@
#include <linux/ata_platform.h>
#include <linux/mv643xx_eth.h>
#include <linux/i2c.h>
+#include <linux/gpio.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <mach/kirkwood.h>
@@ -57,7 +58,22 @@ static struct mvsdio_platform_data openrd_mvsdio_data = {
};
static unsigned int openrd_mpp_config[] __initdata = {
+ MPP12_SD_CLK,
+ MPP13_SD_CMD,
+ MPP14_SD_D0,
+ MPP15_SD_D1,
+ MPP16_SD_D2,
+ MPP17_SD_D3,
+ MPP28_GPIO,
MPP29_GPIO,
+ MPP34_GPIO,
+ 0
+};
+
+/* Configure MPP for UART1 */
+static unsigned int openrd_uart1_mpp_config[] __initdata = {
+ MPP13_UART1_TXD,
+ MPP14_UART1_RXD,
0
};
@@ -67,6 +83,68 @@ static struct i2c_board_info i2c_board_info[] __initdata = {
},
};
+static int __initdata uart1;
+
+static int __init sd_uart_selection(char *str)
+{
+ uart1 = -EINVAL;
+
+ /* Default is SD. Change if required, for UART */
+ if (!str)
+ return 0;
+
+ if (!strncmp(str, "232", 3)) {
+ uart1 = 232;
+ } else if (!strncmp(str, "485", 3)) {
+ /* OpenRD-Base doesn't have RS485. Treat is as an
+ * unknown argument & just have default setting -
+ * which is SD */
+ if (machine_is_openrd_base()) {
+ uart1 = -ENODEV;
+ return 1;
+ }
+
+ uart1 = 485;
+ }
+ return 1;
+}
+/* Parse boot_command_line string kw_openrd_init_uart1=232/485 */
+__setup("kw_openrd_init_uart1=", sd_uart_selection);
+
+static int __init uart1_mpp_config(void)
+{
+ kirkwood_mpp_conf(openrd_uart1_mpp_config);
+
+ if (gpio_request(34, "SD_UART1_SEL")) {
+ printk(KERN_ERR "GPIO request failed for SD/UART1 selection"
+ ", gpio: 34\n");
+ return -EIO;
+ }
+
+ if (gpio_request(28, "RS232_RS485_SEL")) {
+ printk(KERN_ERR "GPIO request failed for RS232/RS485 selection"
+ ", gpio# 28\n");
+ gpio_free(34);
+ return -EIO;
+ }
+
+ /* Select UART1
+ * Pin # 34: 0 => UART1, 1 => SD */
+ gpio_direction_output(34, 0);
+
+ /* Select RS232 OR RS485
+ * Pin # 28: 0 => RS232, 1 => RS485 */
+ if (uart1 == 232)
+ gpio_direction_output(28, 0);
+ else
+ gpio_direction_output(28, 1);
+
+ gpio_free(34);
+ gpio_free(28);
+
+ return 0;
+}
+
static void __init openrd_init(void)
{
/*
@@ -90,7 +168,6 @@ static void __init openrd_init(void)
kirkwood_ge01_init(&openrd_ge01_data);
kirkwood_sata_init(&openrd_sata_data);
- kirkwood_sdio_init(&openrd_mvsdio_data);
kirkwood_i2c_init();
@@ -99,6 +176,28 @@ static void __init openrd_init(void)
ARRAY_SIZE(i2c_board_info));
kirkwood_audio_init();
}
+
+ if (uart1 <= 0) {
+ if (uart1 < 0)
+ printk(KERN_ERR "Invalid kernel parameter to select "
+ "UART1. Defaulting to SD. ERROR CODE: %d\n",
+ uart1);
+
+ /* Select SD
+ * Pin # 34: 0 => UART1, 1 => SD */
+ if (gpio_request(34, "SD_UART1_SEL")) {
+ printk(KERN_ERR "GPIO request failed for SD/UART1 "
+ "selection, gpio: 34\n");
+ } else {
+
+ gpio_direction_output(34, 1);
+ gpio_free(34);
+ kirkwood_sdio_init(&openrd_mvsdio_data);
+ }
+ } else {
+ if (!uart1_mpp_config())
+ kirkwood_uart1_init();
+ }
}
static int __init openrd_pci_init(void)
@@ -115,8 +214,6 @@ subsys_initcall(openrd_pci_init);
#ifdef CONFIG_MACH_OPENRD_BASE
MACHINE_START(OPENRD_BASE, "Marvell OpenRD Base Board")
/* Maintainer: Dhaval Vasa <dhaval.vasa@einfochips.com> */
- .phys_io = KIRKWOOD_REGS_PHYS_BASE,
- .io_pg_offst = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = 0x00000100,
.init_machine = openrd_init,
.map_io = kirkwood_map_io,
@@ -128,8 +225,6 @@ MACHINE_END
#ifdef CONFIG_MACH_OPENRD_CLIENT
MACHINE_START(OPENRD_CLIENT, "Marvell OpenRD Client Board")
/* Maintainer: Dhaval Vasa <dhaval.vasa@einfochips.com> */
- .phys_io = KIRKWOOD_REGS_PHYS_BASE,
- .io_pg_offst = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = 0x00000100,
.init_machine = openrd_init,
.map_io = kirkwood_map_io,
@@ -141,8 +236,6 @@ MACHINE_END
#ifdef CONFIG_MACH_OPENRD_ULTIMATE
MACHINE_START(OPENRD_ULTIMATE, "Marvell OpenRD Ultimate Board")
/* Maintainer: Dhaval Vasa <dhaval.vasa@einfochips.com> */
- .phys_io = KIRKWOOD_REGS_PHYS_BASE,
- .io_pg_offst = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = 0x00000100,
.init_machine = openrd_init,
.map_io = kirkwood_map_io,
diff --git a/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c b/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c
index c34718c2cfe5..0049614cd324 100644
--- a/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c
+++ b/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c
@@ -79,8 +79,6 @@ subsys_initcall(rd88f6192_pci_init);
MACHINE_START(RD88F6192_NAS, "Marvell RD-88F6192-NAS Development Board")
/* Maintainer: Saeed Bishara <saeed@marvell.com> */
- .phys_io = KIRKWOOD_REGS_PHYS_BASE,
- .io_pg_offst = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = 0x00000100,
.init_machine = rd88f6192_init,
.map_io = kirkwood_map_io,
diff --git a/arch/arm/mach-kirkwood/rd88f6281-setup.c b/arch/arm/mach-kirkwood/rd88f6281-setup.c
index 3d1477135e12..0998a08cf42d 100644
--- a/arch/arm/mach-kirkwood/rd88f6281-setup.c
+++ b/arch/arm/mach-kirkwood/rd88f6281-setup.c
@@ -115,8 +115,6 @@ subsys_initcall(rd88f6281_pci_init);
MACHINE_START(RD88F6281, "Marvell RD-88F6281 Reference Board")
/* Maintainer: Saeed Bishara <saeed@marvell.com> */
- .phys_io = KIRKWOOD_REGS_PHYS_BASE,
- .io_pg_offst = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = 0x00000100,
.init_machine = rd88f6281_init,
.map_io = kirkwood_map_io,
diff --git a/arch/arm/mach-kirkwood/sheevaplug-setup.c b/arch/arm/mach-kirkwood/sheevaplug-setup.c
index a00879d34d54..d2eec35dfe0f 100644
--- a/arch/arm/mach-kirkwood/sheevaplug-setup.c
+++ b/arch/arm/mach-kirkwood/sheevaplug-setup.c
@@ -131,8 +131,6 @@ static void __init sheevaplug_init(void)
#ifdef CONFIG_MACH_SHEEVAPLUG
MACHINE_START(SHEEVAPLUG, "Marvell SheevaPlug Reference Board")
/* Maintainer: shadi Ammouri <shadi@marvell.com> */
- .phys_io = KIRKWOOD_REGS_PHYS_BASE,
- .io_pg_offst = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = 0x00000100,
.init_machine = sheevaplug_init,
.map_io = kirkwood_map_io,
@@ -143,8 +141,6 @@ MACHINE_END
#ifdef CONFIG_MACH_ESATA_SHEEVAPLUG
MACHINE_START(ESATA_SHEEVAPLUG, "Marvell eSATA SheevaPlug Reference Board")
- .phys_io = KIRKWOOD_REGS_PHYS_BASE,
- .io_pg_offst = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = 0x00000100,
.init_machine = sheevaplug_init,
.map_io = kirkwood_map_io,
diff --git a/arch/arm/mach-kirkwood/t5325-setup.c b/arch/arm/mach-kirkwood/t5325-setup.c
index d01bf89cedbe..ce50e61aac9f 100644
--- a/arch/arm/mach-kirkwood/t5325-setup.c
+++ b/arch/arm/mach-kirkwood/t5325-setup.c
@@ -184,8 +184,6 @@ subsys_initcall(hp_t5325_pci_init);
MACHINE_START(T5325, "HP t5325 Thin Client")
/* Maintainer: Martin Michlmayr <tbm@cyrius.com> */
- .phys_io = KIRKWOOD_REGS_PHYS_BASE,
- .io_pg_offst = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = 0x00000100,
.init_machine = hp_t5325_init,
.map_io = kirkwood_map_io,
diff --git a/arch/arm/mach-kirkwood/ts219-setup.c b/arch/arm/mach-kirkwood/ts219-setup.c
index a5bd7fde04a9..6710bd7773b8 100644
--- a/arch/arm/mach-kirkwood/ts219-setup.c
+++ b/arch/arm/mach-kirkwood/ts219-setup.c
@@ -120,8 +120,6 @@ subsys_initcall(ts219_pci_init);
MACHINE_START(TS219, "QNAP TS-119/TS-219")
/* Maintainer: Martin Michlmayr <tbm@cyrius.com> */
- .phys_io = KIRKWOOD_REGS_PHYS_BASE,
- .io_pg_offst = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = 0x00000100,
.init_machine = qnap_ts219_init,
.map_io = kirkwood_map_io,
diff --git a/arch/arm/mach-kirkwood/ts41x-setup.c b/arch/arm/mach-kirkwood/ts41x-setup.c
index 2e14afef07a2..8be09a0ce4ac 100644
--- a/arch/arm/mach-kirkwood/ts41x-setup.c
+++ b/arch/arm/mach-kirkwood/ts41x-setup.c
@@ -149,8 +149,6 @@ subsys_initcall(ts41x_pci_init);
MACHINE_START(TS41X, "QNAP TS-41x")
/* Maintainer: Martin Michlmayr <tbm@cyrius.com> */
- .phys_io = KIRKWOOD_REGS_PHYS_BASE,
- .io_pg_offst = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = 0x00000100,
.init_machine = qnap_ts41x_init,
.map_io = kirkwood_map_io,
diff --git a/arch/arm/mach-ks8695/board-acs5k.c b/arch/arm/mach-ks8695/board-acs5k.c
index 9e3e5a640ad2..3ca4f8e6f54f 100644
--- a/arch/arm/mach-ks8695/board-acs5k.c
+++ b/arch/arm/mach-ks8695/board-acs5k.c
@@ -223,8 +223,6 @@ static void __init acs5k_init(void)
MACHINE_START(ACS5K, "Brivo Systems LLC ACS-5000 Master board")
/* Maintainer: Simtec Electronics. */
- .phys_io = KS8695_IO_PA,
- .io_pg_offst = (KS8695_IO_VA >> 18) & 0xfffc,
.boot_params = KS8695_SDRAM_PA + 0x100,
.map_io = ks8695_map_io,
.init_irq = ks8695_init_irq,
diff --git a/arch/arm/mach-ks8695/board-dsm320.c b/arch/arm/mach-ks8695/board-dsm320.c
index 521ff0789f39..ada92b6bed24 100644
--- a/arch/arm/mach-ks8695/board-dsm320.c
+++ b/arch/arm/mach-ks8695/board-dsm320.c
@@ -121,8 +121,6 @@ static void __init dsm320_init(void)
MACHINE_START(DSM320, "D-Link DSM-320 Wireless Media Player")
/* Maintainer: Simtec Electronics. */
- .phys_io = KS8695_IO_PA,
- .io_pg_offst = (KS8695_IO_VA >> 18) & 0xfffc,
.boot_params = KS8695_SDRAM_PA + 0x100,
.map_io = ks8695_map_io,
.init_irq = ks8695_init_irq,
diff --git a/arch/arm/mach-ks8695/board-micrel.c b/arch/arm/mach-ks8695/board-micrel.c
index 8ceaf5ac6e2c..c7ad09bd6ea2 100644
--- a/arch/arm/mach-ks8695/board-micrel.c
+++ b/arch/arm/mach-ks8695/board-micrel.c
@@ -53,8 +53,6 @@ static void __init micrel_init(void)
MACHINE_START(KS8695, "KS8695 Centaur Development Board")
/* Maintainer: Micrel Semiconductor Inc. */
- .phys_io = KS8695_IO_PA,
- .io_pg_offst = (KS8695_IO_VA >> 18) & 0xfffc,
.boot_params = KS8695_SDRAM_PA + 0x100,
.map_io = ks8695_map_io,
.init_irq = ks8695_init_irq,
diff --git a/arch/arm/mach-ks8695/include/mach/debug-macro.S b/arch/arm/mach-ks8695/include/mach/debug-macro.S
index cf2095da2372..bf516adf1925 100644
--- a/arch/arm/mach-ks8695/include/mach/debug-macro.S
+++ b/arch/arm/mach-ks8695/include/mach/debug-macro.S
@@ -14,11 +14,9 @@
#include <mach/hardware.h>
#include <mach/regs-uart.h>
- .macro addruart, rx, tmp
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ MMU enabled?
- ldreq \rx, =KS8695_UART_PA @ physical base address
- ldrne \rx, =KS8695_UART_VA @ virtual base address
+ .macro addruart, rp, rv
+ ldr \rp, =KS8695_UART_PA @ physical base address
+ ldr \rv, =KS8695_UART_VA @ virtual base address
.endm
.macro senduart, rd, rx
diff --git a/arch/arm/mach-l7200/include/mach/debug-macro.S b/arch/arm/mach-l7200/include/mach/debug-macro.S
new file mode 100644
index 000000000000..b0a2db77d392
--- /dev/null
+++ b/arch/arm/mach-l7200/include/mach/debug-macro.S
@@ -0,0 +1,38 @@
+/* arch/arm/mach-l7200/include/mach/debug-macro.S
+ *
+ * Debugging macro include header
+ *
+ * Copyright (C) 1994-1999 Russell King
+ * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+*/
+
+ .equ io_virt, IO_BASE
+ .equ io_phys, IO_START
+
+ .macro addruart, rp, rv
+ mov \rp, #0x00044000 @ UART1
+@ mov \rp, #0x00045000 @ UART2
+ add \rv, \rp, #io_virt @ virtual address
+ add \rp, \rp, #io_phys @ physical base address
+ .endm
+
+ .macro senduart,rd,rx
+ str \rd, [\rx, #0x0] @ UARTDR
+ .endm
+
+ .macro waituart,rd,rx
+1001: ldr \rd, [\rx, #0x18] @ UARTFLG
+ tst \rd, #1 << 5 @ UARTFLGUTXFF - 1 when full
+ bne 1001b
+ .endm
+
+ .macro busyuart,rd,rx
+1001: ldr \rd, [\rx, #0x18] @ UARTFLG
+ tst \rd, #1 << 3 @ UARTFLGUBUSY - 1 when busy
+ bne 1001b
+ .endm
diff --git a/arch/arm/mach-lh7a40x/arch-kev7a400.c b/arch/arm/mach-lh7a40x/arch-kev7a400.c
index 3d7bd50b9095..9088c16662e8 100644
--- a/arch/arm/mach-lh7a40x/arch-kev7a400.c
+++ b/arch/arm/mach-lh7a40x/arch-kev7a400.c
@@ -111,8 +111,6 @@ void __init lh7a40x_init_board_irq (void)
MACHINE_START (KEV7A400, "Sharp KEV7a400")
/* Maintainer: Marc Singer */
- .phys_io = 0x80000000,
- .io_pg_offst = ((io_p2v (0x80000000))>>18) & 0xfffc,
.boot_params = 0xc0000100,
.map_io = kev7a400_map_io,
.init_irq = lh7a400_init_irq,
diff --git a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
index cb15e5d32120..7315a569aea1 100644
--- a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
+++ b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
@@ -398,8 +398,6 @@ lpd7a40x_map_io(void)
MACHINE_START (LPD7A400, "Logic Product Development LPD7A400-10")
/* Maintainer: Marc Singer */
- .phys_io = 0x80000000,
- .io_pg_offst = ((io_p2v (0x80000000))>>18) & 0xfffc,
.boot_params = 0xc0000100,
.map_io = lpd7a40x_map_io,
.init_irq = lh7a400_init_irq,
@@ -413,8 +411,6 @@ MACHINE_END
MACHINE_START (LPD7A404, "Logic Product Development LPD7A404-10")
/* Maintainer: Marc Singer */
- .phys_io = 0x80000000,
- .io_pg_offst = ((io_p2v (0x80000000))>>18) & 0xfffc,
.boot_params = 0xc0000100,
.map_io = lpd7a40x_map_io,
.init_irq = lh7a404_init_irq,
diff --git a/arch/arm/mach-lh7a40x/include/mach/debug-macro.S b/arch/arm/mach-lh7a40x/include/mach/debug-macro.S
index c0dcbbba22ba..cff33625276f 100644
--- a/arch/arm/mach-lh7a40x/include/mach/debug-macro.S
+++ b/arch/arm/mach-lh7a40x/include/mach/debug-macro.S
@@ -14,12 +14,10 @@
@ It is not known if this will be appropriate for every 40x
@ board.
- .macro addruart, rx, tmp
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ MMU enabled?
- mov \rx, #0x00000700 @ offset from base
- orreq \rx, \rx, #0x80000000 @ physical base
- orrne \rx, \rx, #0xf8000000 @ virtual base
+ .macro addruart, rp, rv
+ mov \rp, #0x00000700 @ offset from base
+ orr \rv, \rp, #0xf8000000 @ virtual base
+ orr \rp, \rp, #0x80000000 @ physical base
.endm
.macro senduart,rd,rx
diff --git a/arch/arm/mach-loki/include/mach/debug-macro.S b/arch/arm/mach-loki/include/mach/debug-macro.S
index 3136c913a92c..cc90d99ac76c 100644
--- a/arch/arm/mach-loki/include/mach/debug-macro.S
+++ b/arch/arm/mach-loki/include/mach/debug-macro.S
@@ -8,12 +8,11 @@
#include <mach/loki.h>
- .macro addruart, rx, tmp
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ MMU enabled?
- ldreq \rx, =LOKI_REGS_PHYS_BASE
- ldrne \rx, =LOKI_REGS_VIRT_BASE
- orr \rx, \rx, #0x00012000
+ .macro addruart, rp, rv
+ ldr \rp, =LOKI_REGS_PHYS_BASE
+ ldr \rv, =LOKI_REGS_VIRT_BASE
+ orr \rp, \rp, #0x00012000
+ orr \rv, \rv, #0x00012000
.endm
#define UART_SHIFT 2
diff --git a/arch/arm/mach-loki/lb88rc8480-setup.c b/arch/arm/mach-loki/lb88rc8480-setup.c
index 85f9c1296aa0..a1e75e7fc500 100644
--- a/arch/arm/mach-loki/lb88rc8480-setup.c
+++ b/arch/arm/mach-loki/lb88rc8480-setup.c
@@ -90,8 +90,6 @@ static void __init lb88rc8480_init(void)
MACHINE_START(LB88RC8480, "Marvell LB88RC8480 Development Board")
/* Maintainer: Ke Wei <kewei@marvell.com> */
- .phys_io = LOKI_REGS_PHYS_BASE,
- .io_pg_offst = ((LOKI_REGS_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = 0x00000100,
.init_machine = lb88rc8480_init,
.map_io = loki_map_io,
diff --git a/arch/arm/mach-lpc32xx/include/mach/debug-macro.S b/arch/arm/mach-lpc32xx/include/mach/debug-macro.S
index 621744d6b152..629e744aeb9e 100644
--- a/arch/arm/mach-lpc32xx/include/mach/debug-macro.S
+++ b/arch/arm/mach-lpc32xx/include/mach/debug-macro.S
@@ -20,11 +20,9 @@
* Debug output is hardcoded to standard UART 5
*/
- .macro addruart,rx, tmp
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ MMU enabled?
- ldreq \rx, =0x40090000
- ldrne \rx, =0xF4090000
+ .macro addruart, rp, rv
+ ldreq \rp, =0x40090000
+ ldrne \rv, =0xF4090000
.endm
#define UART_SHIFT 2
diff --git a/arch/arm/mach-lpc32xx/phy3250.c b/arch/arm/mach-lpc32xx/phy3250.c
index bc9a42da2145..7993b096778e 100644
--- a/arch/arm/mach-lpc32xx/phy3250.c
+++ b/arch/arm/mach-lpc32xx/phy3250.c
@@ -172,18 +172,12 @@ static void phy3250_spi_cs_set(u32 control)
}
static struct pl022_config_chip spi0_chip_info = {
- .lbm = LOOPBACK_DISABLED,
.com_mode = INTERRUPT_TRANSFER,
.iface = SSP_INTERFACE_MOTOROLA_SPI,
.hierarchy = SSP_MASTER,
.slave_tx_disable = 0,
- .endian_tx = SSP_TX_LSB,
- .endian_rx = SSP_RX_LSB,
- .data_size = SSP_DATA_BITS_8,
.rx_lev_trig = SSP_RX_4_OR_MORE_ELEM,
.tx_lev_trig = SSP_TX_4_OR_MORE_EMPTY_LOC,
- .clk_phase = SSP_CLK_FIRST_EDGE,
- .clk_pol = SSP_CLK_POL_IDLE_LOW,
.ctrl_len = SSP_BITS_8,
.wait_state = SSP_MWIRE_WAIT_ZERO,
.duplex = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX,
@@ -239,6 +233,7 @@ static int __init phy3250_spi_board_register(void)
.max_speed_hz = 5000000,
.bus_num = 0,
.chip_select = 0,
+ .mode = SPI_MODE_0,
.platform_data = &eeprom,
.controller_data = &spi0_chip_info,
},
@@ -387,8 +382,6 @@ arch_initcall(lpc32xx_display_uid);
MACHINE_START(PHY3250, "Phytec 3250 board with the LPC3250 Microcontroller")
/* Maintainer: Kevin Wells, NXP Semiconductors */
- .phys_io = LPC32XX_UART5_BASE,
- .io_pg_offst = ((IO_ADDRESS(LPC32XX_UART5_BASE))>>18) & 0xfffc,
.boot_params = 0x80000100,
.map_io = lpc32xx_map_io,
.init_irq = lpc32xx_init_irq,
diff --git a/arch/arm/mach-mmp/Kconfig b/arch/arm/mach-mmp/Kconfig
index 6ab843eaa35b..0711d3b620ad 100644
--- a/arch/arm/mach-mmp/Kconfig
+++ b/arch/arm/mach-mmp/Kconfig
@@ -57,6 +57,13 @@ config MACH_MARVELL_JASPER
PXA910-based development board. Since MMP2 is compatible to
ARMv6 architecture.
+config MACH_TETON_BGA
+ bool "Marvell's PXA168 Teton BGA Development Board"
+ select CPU_PXA168
+ help
+ Say 'Y' here if you want to support the Marvell PXA168-based
+ Teton BGA Development Board.
+
endmenu
config CPU_PXA168
diff --git a/arch/arm/mach-mmp/Makefile b/arch/arm/mach-mmp/Makefile
index 8b66d06739c4..751cdbf733c8 100644
--- a/arch/arm/mach-mmp/Makefile
+++ b/arch/arm/mach-mmp/Makefile
@@ -17,3 +17,4 @@ obj-$(CONFIG_MACH_TAVOREVB) += tavorevb.o
obj-$(CONFIG_MACH_TTC_DKB) += ttc_dkb.o
obj-$(CONFIG_MACH_FLINT) += flint.o
obj-$(CONFIG_MACH_MARVELL_JASPER) += jasper.o
+obj-$(CONFIG_MACH_TETON_BGA) += teton_bga.o
diff --git a/arch/arm/mach-mmp/aspenite.c b/arch/arm/mach-mmp/aspenite.c
index 0629394a5fb9..06b5fa853c93 100644
--- a/arch/arm/mach-mmp/aspenite.c
+++ b/arch/arm/mach-mmp/aspenite.c
@@ -16,6 +16,7 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/nand.h>
+#include <linux/interrupt.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -23,6 +24,9 @@
#include <mach/mfp-pxa168.h>
#include <mach/pxa168.h>
#include <mach/gpio.h>
+#include <video/pxa168fb.h>
+#include <linux/input.h>
+#include <plat/pxa27x_keypad.h>
#include "common.h"
@@ -66,6 +70,43 @@ static unsigned long common_pin_config[] __initdata = {
GPIO115_I2S_BCLK,
GPIO116_I2S_RXD,
GPIO117_I2S_TXD,
+
+ /* LCD */
+ GPIO56_LCD_FCLK_RD,
+ GPIO57_LCD_LCLK_A0,
+ GPIO58_LCD_PCLK_WR,
+ GPIO59_LCD_DENA_BIAS,
+ GPIO60_LCD_DD0,
+ GPIO61_LCD_DD1,
+ GPIO62_LCD_DD2,
+ GPIO63_LCD_DD3,
+ GPIO64_LCD_DD4,
+ GPIO65_LCD_DD5,
+ GPIO66_LCD_DD6,
+ GPIO67_LCD_DD7,
+ GPIO68_LCD_DD8,
+ GPIO69_LCD_DD9,
+ GPIO70_LCD_DD10,
+ GPIO71_LCD_DD11,
+ GPIO72_LCD_DD12,
+ GPIO73_LCD_DD13,
+ GPIO74_LCD_DD14,
+ GPIO75_LCD_DD15,
+ GPIO76_LCD_DD16,
+ GPIO77_LCD_DD17,
+ GPIO78_LCD_DD18,
+ GPIO79_LCD_DD19,
+ GPIO80_LCD_DD20,
+ GPIO81_LCD_DD21,
+ GPIO82_LCD_DD22,
+ GPIO83_LCD_DD23,
+
+ /* Keypad */
+ GPIO109_KP_MKIN1,
+ GPIO110_KP_MKIN0,
+ GPIO111_KP_MKOUT7,
+ GPIO112_KP_MKOUT6,
+ GPIO121_KP_MKIN4,
};
static struct smc91x_platdata smc91x_info = {
@@ -134,6 +175,51 @@ static struct i2c_board_info aspenite_i2c_info[] __initdata = {
{ I2C_BOARD_INFO("wm8753", 0x1b), },
};
+static struct fb_videomode video_modes[] = {
+ [0] = {
+ .pixclock = 30120,
+ .refresh = 60,
+ .xres = 800,
+ .yres = 480,
+ .hsync_len = 1,
+ .left_margin = 215,
+ .right_margin = 40,
+ .vsync_len = 1,
+ .upper_margin = 34,
+ .lower_margin = 10,
+ .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT,
+ },
+};
+
+struct pxa168fb_mach_info aspenite_lcd_info = {
+ .id = "Graphic Frame",
+ .modes = video_modes,
+ .num_modes = ARRAY_SIZE(video_modes),
+ .pix_fmt = PIX_FMT_RGB565,
+ .io_pin_allocation_mode = PIN_MODE_DUMB_24,
+ .dumb_mode = DUMB_MODE_RGB888,
+ .active = 1,
+ .panel_rbswap = 0,
+ .invert_pixclock = 0,
+};
+
+static unsigned int aspenite_matrix_key_map[] = {
+ KEY(0, 6, KEY_UP), /* SW 4 */
+ KEY(0, 7, KEY_DOWN), /* SW 5 */
+ KEY(1, 6, KEY_LEFT), /* SW 6 */
+ KEY(1, 7, KEY_RIGHT), /* SW 7 */
+ KEY(4, 6, KEY_ENTER), /* SW 8 */
+ KEY(4, 7, KEY_ESC), /* SW 9 */
+};
+
+static struct pxa27x_keypad_platform_data aspenite_keypad_info __initdata = {
+ .matrix_key_rows = 5,
+ .matrix_key_cols = 8,
+ .matrix_key_map = aspenite_matrix_key_map,
+ .matrix_key_map_size = ARRAY_SIZE(aspenite_matrix_key_map),
+ .debounce_interval = 30,
+};
+
static void __init common_init(void)
{
mfp_config(ARRAY_AND_SIZE(common_pin_config));
@@ -143,24 +229,24 @@ static void __init common_init(void)
pxa168_add_twsi(1, NULL, ARRAY_AND_SIZE(aspenite_i2c_info));
pxa168_add_ssp(1);
pxa168_add_nand(&aspenite_nand_info);
+ pxa168_add_fb(&aspenite_lcd_info);
+ pxa168_add_keypad(&aspenite_keypad_info);
/* off-chip devices */
platform_device_register(&smc91x_device);
}
MACHINE_START(ASPENITE, "PXA168-based Aspenite Development Platform")
- .phys_io = APB_PHYS_BASE,
- .io_pg_offst = (APB_VIRT_BASE >> 18) & 0xfffc,
.map_io = mmp_map_io,
+ .nr_irqs = IRQ_BOARD_START,
.init_irq = pxa168_init_irq,
.timer = &pxa168_timer,
.init_machine = common_init,
MACHINE_END
MACHINE_START(ZYLONITE2, "PXA168-based Zylonite2 Development Platform")
- .phys_io = APB_PHYS_BASE,
- .io_pg_offst = (APB_VIRT_BASE >> 18) & 0xfffc,
.map_io = mmp_map_io,
+ .nr_irqs = IRQ_BOARD_START,
.init_irq = pxa168_init_irq,
.timer = &pxa168_timer,
.init_machine = common_init,
diff --git a/arch/arm/mach-mmp/avengers_lite.c b/arch/arm/mach-mmp/avengers_lite.c
index 69bcba11f53f..39f0878d64a0 100644
--- a/arch/arm/mach-mmp/avengers_lite.c
+++ b/arch/arm/mach-mmp/avengers_lite.c
@@ -41,8 +41,6 @@ static void __init avengers_lite_init(void)
}
MACHINE_START(AVENGERS_LITE, "PXA168 Avengers lite Development Platform")
- .phys_io = APB_PHYS_BASE,
- .io_pg_offst = (APB_VIRT_BASE >> 18) & 0xfffc,
.map_io = mmp_map_io,
.init_irq = pxa168_init_irq,
.timer = &pxa168_timer,
diff --git a/arch/arm/mach-mmp/common.c b/arch/arm/mach-mmp/common.c
index 3b29fa7e9b08..0ec0ca80bb3e 100644
--- a/arch/arm/mach-mmp/common.c
+++ b/arch/arm/mach-mmp/common.c
@@ -10,13 +10,20 @@
#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/module.h>
#include <asm/page.h>
#include <asm/mach/map.h>
#include <mach/addr-map.h>
+#include <mach/cputype.h>
#include "common.h"
+#define MMP_CHIPID (AXI_VIRT_BASE + 0x82c00)
+
+unsigned int mmp_chip_id;
+EXPORT_SYMBOL(mmp_chip_id);
+
static struct map_desc standard_io_desc[] __initdata = {
{
.pfn = __phys_to_pfn(APB_PHYS_BASE),
@@ -34,4 +41,7 @@ static struct map_desc standard_io_desc[] __initdata = {
void __init mmp_map_io(void)
{
iotable_init(standard_io_desc, ARRAY_SIZE(standard_io_desc));
+
+ /* this is early, initialize mmp_chip_id here */
+ mmp_chip_id = __raw_readl(MMP_CHIPID);
}
diff --git a/arch/arm/mach-mmp/flint.c b/arch/arm/mach-mmp/flint.c
index e4312d238eae..bdeb6db4d49a 100644
--- a/arch/arm/mach-mmp/flint.c
+++ b/arch/arm/mach-mmp/flint.c
@@ -16,6 +16,7 @@
#include <linux/smc91x.h>
#include <linux/io.h>
#include <linux/gpio.h>
+#include <linux/interrupt.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -25,6 +26,8 @@
#include "common.h"
+#define FLINT_NR_IRQS (IRQ_BOARD_START + 48)
+
static unsigned long flint_pin_config[] __initdata = {
/* UART1 */
GPIO45_UART1_RXD,
@@ -113,9 +116,8 @@ static void __init flint_init(void)
}
MACHINE_START(FLINT, "Flint Development Platform")
- .phys_io = APB_PHYS_BASE,
- .io_pg_offst = (APB_VIRT_BASE >> 18) & 0xfffc,
.map_io = mmp_map_io,
+ .nr_irqs = FLINT_NR_IRQS,
.init_irq = mmp2_init_irq,
.timer = &mmp2_timer,
.init_machine = flint_init,
diff --git a/arch/arm/mach-mmp/include/mach/cputype.h b/arch/arm/mach-mmp/include/mach/cputype.h
index 83b18721d933..f43a68b213f1 100644
--- a/arch/arm/mach-mmp/include/mach/cputype.h
+++ b/arch/arm/mach-mmp/include/mach/cputype.h
@@ -4,36 +4,51 @@
#include <asm/cputype.h>
/*
- * CPU Stepping OLD_ID CPU_ID CHIP_ID
+ * CPU Stepping CPU_ID CHIP_ID
*
- * PXA168 A0 0x41159263 0x56158400 0x00A0A333
- * PXA910 Y0 0x41159262 0x56158000 0x00F0C910
- * MMP2 Z0 0x560f5811
+ * PXA168 S0 0x56158400 0x0000C910
+ * PXA168 A0 0x56158400 0x00A0A168
+ * PXA910 Y1 0x56158400 0x00F2C920
+ * PXA910 A0 0x56158400 0x00F2C910
+ * PXA910 A1 0x56158400 0x00A0C910
+ * PXA920 Y0 0x56158400 0x00F2C920
+ * PXA920 A0 0x56158400 0x00A0C920
+ * PXA920 A1 0x56158400 0x00A1C920
+ * MMP2 Z0 0x560f5811 0x00F00410
+ * MMP2 Z1 0x560f5811 0x00E00410
+ * MMP2 A0 0x560f5811 0x00A0A610
*/
+extern unsigned int mmp_chip_id;
+
#ifdef CONFIG_CPU_PXA168
-# define __cpu_is_pxa168(id) \
- ({ unsigned int _id = ((id) >> 8) & 0xff; _id == 0x84; })
+static inline int cpu_is_pxa168(void)
+{
+ return (((read_cpuid_id() >> 8) & 0xff) == 0x84) &&
+ ((mmp_chip_id & 0xfff) == 0x168);
+}
#else
-# define __cpu_is_pxa168(id) (0)
+#define cpu_is_pxa168() (0)
#endif
+/* cpu_is_pxa910() is shared on both pxa910 and pxa920 */
#ifdef CONFIG_CPU_PXA910
-# define __cpu_is_pxa910(id) \
- ({ unsigned int _id = ((id) >> 8) & 0xff; _id == 0x80; })
+static inline int cpu_is_pxa910(void)
+{
+ return (((read_cpuid_id() >> 8) & 0xff) == 0x84) &&
+ (((mmp_chip_id & 0xfff) == 0x910) ||
+ ((mmp_chip_id & 0xfff) == 0x920));
+}
#else
-# define __cpu_is_pxa910(id) (0)
+#define cpu_is_pxa910() (0)
#endif
#ifdef CONFIG_CPU_MMP2
-# define __cpu_is_mmp2(id) \
- ({ unsigned int _id = ((id) >> 8) & 0xff; _id == 0x58; })
+static inline int cpu_is_mmp2(void)
+{
+ return (((cpu_readid_id() >> 8) & 0xff) == 0x58);
#else
-# define __cpu_is_mmp2(id) (0)
+#define cpu_is_mmp2() (0)
#endif
-#define cpu_is_pxa168() ({ __cpu_is_pxa168(read_cpuid_id()); })
-#define cpu_is_pxa910() ({ __cpu_is_pxa910(read_cpuid_id()); })
-#define cpu_is_mmp2() ({ __cpu_is_mmp2(read_cpuid_id()); })
-
#endif /* __ASM_MACH_CPUTYPE_H */
diff --git a/arch/arm/mach-mmp/include/mach/debug-macro.S b/arch/arm/mach-mmp/include/mach/debug-macro.S
index 76deff238e1c..7e2ebd3efc7c 100644
--- a/arch/arm/mach-mmp/include/mach/debug-macro.S
+++ b/arch/arm/mach-mmp/include/mach/debug-macro.S
@@ -11,12 +11,11 @@
#include <mach/addr-map.h>
- .macro addruart, rx, tmp
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ MMU enabled?
- ldreq \rx, =APB_PHYS_BASE @ physical
- ldrne \rx, =APB_VIRT_BASE @ virtual
- orr \rx, \rx, #0x00017000
+ .macro addruart, rp, rv
+ ldr \rp, =APB_PHYS_BASE @ physical
+ ldr \rv, =APB_VIRT_BASE @ virtual
+ orr \rp, \rp, #0x00017000
+ orr \rv, \rv, #0x00017000
.endm
#define UART_SHIFT 2
diff --git a/arch/arm/mach-mmp/include/mach/irqs.h b/arch/arm/mach-mmp/include/mach/irqs.h
index b379cdec4d38..a09d328e2ddd 100644
--- a/arch/arm/mach-mmp/include/mach/irqs.h
+++ b/arch/arm/mach-mmp/include/mach/irqs.h
@@ -222,10 +222,8 @@
#define IRQ_GPIO_NUM 192
#define IRQ_GPIO(x) (IRQ_GPIO_START + (x))
-/* Board IRQ - 64 by default, increase if not enough */
#define IRQ_BOARD_START (IRQ_GPIO_START + IRQ_GPIO_NUM)
-#define IRQ_BOARD_END (IRQ_BOARD_START + 64)
-#define NR_IRQS (IRQ_BOARD_END)
+#define NR_IRQS (IRQ_BOARD_START)
#endif /* __ASM_MACH_IRQS_H */
diff --git a/arch/arm/mach-mmp/include/mach/mfp-pxa168.h b/arch/arm/mach-mmp/include/mach/mfp-pxa168.h
index ded43c455ec3..4621067c7720 100644
--- a/arch/arm/mach-mmp/include/mach/mfp-pxa168.h
+++ b/arch/arm/mach-mmp/include/mach/mfp-pxa168.h
@@ -289,4 +289,11 @@
#define GPIO86_PWM1_OUT MFP_CFG(GPIO86, AF2)
#define GPIO86_PWM2_OUT MFP_CFG(GPIO86, AF3)
+/* Keypad */
+#define GPIO109_KP_MKIN1 MFP_CFG(GPIO109, AF7)
+#define GPIO110_KP_MKIN0 MFP_CFG(GPIO110, AF7)
+#define GPIO111_KP_MKOUT7 MFP_CFG(GPIO111, AF7)
+#define GPIO112_KP_MKOUT6 MFP_CFG(GPIO112, AF7)
+#define GPIO121_KP_MKIN4 MFP_CFG(GPIO121, AF7)
+
#endif /* __ASM_MACH_MFP_PXA168_H */
diff --git a/arch/arm/mach-mmp/include/mach/pxa168.h b/arch/arm/mach-mmp/include/mach/pxa168.h
index 27e1bc758623..1801e4206232 100644
--- a/arch/arm/mach-mmp/include/mach/pxa168.h
+++ b/arch/arm/mach-mmp/include/mach/pxa168.h
@@ -5,11 +5,15 @@ struct sys_timer;
extern struct sys_timer pxa168_timer;
extern void __init pxa168_init_irq(void);
+extern void pxa168_clear_keypad_wakeup(void);
#include <linux/i2c.h>
#include <mach/devices.h>
#include <plat/i2c.h>
#include <plat/pxa3xx_nand.h>
+#include <video/pxa168fb.h>
+#include <plat/pxa27x_keypad.h>
+#include <mach/cputype.h>
extern struct pxa_device_desc pxa168_device_uart1;
extern struct pxa_device_desc pxa168_device_uart2;
@@ -25,6 +29,8 @@ extern struct pxa_device_desc pxa168_device_ssp3;
extern struct pxa_device_desc pxa168_device_ssp4;
extern struct pxa_device_desc pxa168_device_ssp5;
extern struct pxa_device_desc pxa168_device_nand;
+extern struct pxa_device_desc pxa168_device_fb;
+extern struct pxa_device_desc pxa168_device_keypad;
static inline int pxa168_add_uart(int id)
{
@@ -97,4 +103,18 @@ static inline int pxa168_add_nand(struct pxa3xx_nand_platform_data *info)
{
return pxa_register_device(&pxa168_device_nand, info, sizeof(*info));
}
+
+static inline int pxa168_add_fb(struct pxa168fb_mach_info *mi)
+{
+ return pxa_register_device(&pxa168_device_fb, mi, sizeof(*mi));
+}
+
+static inline int pxa168_add_keypad(struct pxa27x_keypad_platform_data *data)
+{
+ if (cpu_is_pxa168())
+ data->clear_wakeup_event = pxa168_clear_keypad_wakeup;
+
+ return pxa_register_device(&pxa168_device_keypad, data, sizeof(*data));
+}
+
#endif /* __ASM_MACH_PXA168_H */
diff --git a/arch/arm/mach-mmp/include/mach/regs-apmu.h b/arch/arm/mach-mmp/include/mach/regs-apmu.h
index 919030514120..ac4702357a6e 100644
--- a/arch/arm/mach-mmp/include/mach/regs-apmu.h
+++ b/arch/arm/mach-mmp/include/mach/regs-apmu.h
@@ -33,4 +33,16 @@
#define APMU_FNRST_DIS (1 << 1)
#define APMU_AXIRST_DIS (1 << 0)
+/* Wake Clear Register */
+#define APMU_WAKE_CLR APMU_REG(0x07c)
+
+#define APMU_PXA168_KP_WAKE_CLR (1 << 7)
+#define APMU_PXA168_CFI_WAKE_CLR (1 << 6)
+#define APMU_PXA168_XD_WAKE_CLR (1 << 5)
+#define APMU_PXA168_MSP_WAKE_CLR (1 << 4)
+#define APMU_PXA168_SD4_WAKE_CLR (1 << 3)
+#define APMU_PXA168_SD3_WAKE_CLR (1 << 2)
+#define APMU_PXA168_SD2_WAKE_CLR (1 << 1)
+#define APMU_PXA168_SD1_WAKE_CLR (1 << 0)
+
#endif /* __ASM_MACH_REGS_APMU_H */
diff --git a/arch/arm/mach-mmp/include/mach/teton_bga.h b/arch/arm/mach-mmp/include/mach/teton_bga.h
new file mode 100644
index 000000000000..61a539b2cc98
--- /dev/null
+++ b/arch/arm/mach-mmp/include/mach/teton_bga.h
@@ -0,0 +1,27 @@
+/*
+ * linux/arch/arm/mach-mmp/include/mach/teton_bga.h
+ *
+ * Support for the Marvell PXA168 Teton BGA Development Platform.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * publishhed by the Free Software Foundation.
+ */
+#ifndef __ASM_MACH_TETON_BGA_H
+#define __ASM_MACH_TETON_BGA_H
+
+/* GPIOs */
+#define MMC_PWENA_GPIO 27
+#define USBHPENB_GPIO 55
+#define RTC_INT_GPIO 78
+#define LCD_VBLK_EN_GPIO 79
+#define LCD_DVDD_EN_GPIO 80
+#define RST_WIFI_GPIO 81
+#define CF_PWEN_GPIO 82
+#define USB_OC_GPIO 83
+#define PWM_GPIO 84
+#define USBHPENA_GPIO 85
+#define TS_INT_GPIO 86
+#define CIR_GPIO 108
+
+#endif /* __ASM_MACH_TETON_BGA_H */
diff --git a/arch/arm/mach-mmp/jasper.c b/arch/arm/mach-mmp/jasper.c
index 80c3e7ab1e17..2a684fa50773 100644
--- a/arch/arm/mach-mmp/jasper.c
+++ b/arch/arm/mach-mmp/jasper.c
@@ -18,16 +18,18 @@
#include <linux/regulator/machine.h>
#include <linux/regulator/max8649.h>
#include <linux/mfd/max8925.h>
+#include <linux/interrupt.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <mach/addr-map.h>
#include <mach/mfp-mmp2.h>
#include <mach/mmp2.h>
-#include <mach/irqs.h>
#include "common.h"
+#define JASPER_NR_IRQS (IRQ_BOARD_START + 48)
+
static unsigned long jasper_pin_config[] __initdata = {
/* UART1 */
GPIO29_UART1_RXD,
@@ -134,9 +136,8 @@ static void __init jasper_init(void)
}
MACHINE_START(MARVELL_JASPER, "Jasper Development Platform")
- .phys_io = APB_PHYS_BASE,
- .io_pg_offst = (APB_VIRT_BASE >> 18) & 0xfffc,
.map_io = mmp_map_io,
+ .nr_irqs = JASPER_NR_IRQS,
.init_irq = mmp2_init_irq,
.timer = &mmp2_timer,
.init_machine = jasper_init,
diff --git a/arch/arm/mach-mmp/pxa168.c b/arch/arm/mach-mmp/pxa168.c
index 652ae660634c..72b4e7631583 100644
--- a/arch/arm/mach-mmp/pxa168.c
+++ b/arch/arm/mach-mmp/pxa168.c
@@ -77,8 +77,10 @@ static APBC_CLK(ssp2, PXA168_SSP2, 4, 0);
static APBC_CLK(ssp3, PXA168_SSP3, 4, 0);
static APBC_CLK(ssp4, PXA168_SSP4, 4, 0);
static APBC_CLK(ssp5, PXA168_SSP5, 4, 0);
+static APBC_CLK(keypad, PXA168_KPC, 0, 32000);
static APMU_CLK(nand, NAND, 0x01db, 208000000);
+static APMU_CLK(lcd, LCD, 0x7f, 312000000);
/* device and clock bindings */
static struct clk_lookup pxa168_clkregs[] = {
@@ -96,6 +98,8 @@ static struct clk_lookup pxa168_clkregs[] = {
INIT_CLKREG(&clk_ssp4, "pxa168-ssp.3", NULL),
INIT_CLKREG(&clk_ssp5, "pxa168-ssp.4", NULL),
INIT_CLKREG(&clk_nand, "pxa3xx-nand", NULL),
+ INIT_CLKREG(&clk_lcd, "pxa168-fb", NULL),
+ INIT_CLKREG(&clk_keypad, "pxa27x-keypad", NULL),
};
static int __init pxa168_init(void)
@@ -132,6 +136,16 @@ struct sys_timer pxa168_timer = {
.init = pxa168_timer_init,
};
+void pxa168_clear_keypad_wakeup(void)
+{
+ uint32_t val;
+ uint32_t mask = APMU_PXA168_KP_WAKE_CLR;
+
+ /* wake event clear is needed in order to clear keypad interrupt */
+ val = __raw_readl(APMU_WAKE_CLR);
+ __raw_writel(val | mask, APMU_WAKE_CLR);
+}
+
/* on-chip devices */
PXA168_DEVICE(uart1, "pxa2xx-uart", 0, UART1, 0xd4017000, 0x30, 21, 22);
PXA168_DEVICE(uart2, "pxa2xx-uart", 1, UART2, 0xd4018000, 0x30, 23, 24);
@@ -147,3 +161,5 @@ PXA168_DEVICE(ssp2, "pxa168-ssp", 1, SSP2, 0xd401c000, 0x40, 54, 55);
PXA168_DEVICE(ssp3, "pxa168-ssp", 2, SSP3, 0xd401f000, 0x40, 56, 57);
PXA168_DEVICE(ssp4, "pxa168-ssp", 3, SSP4, 0xd4020000, 0x40, 58, 59);
PXA168_DEVICE(ssp5, "pxa168-ssp", 4, SSP5, 0xd4021000, 0x40, 60, 61);
+PXA168_DEVICE(fb, "pxa168-fb", -1, LCD, 0xd420b000, 0x1c8);
+PXA168_DEVICE(keypad, "pxa27x-keypad", -1, KEYPAD, 0xd4012000, 0x4c);
diff --git a/arch/arm/mach-mmp/tavorevb.c b/arch/arm/mach-mmp/tavorevb.c
index e81db7428215..c296b75c4453 100644
--- a/arch/arm/mach-mmp/tavorevb.c
+++ b/arch/arm/mach-mmp/tavorevb.c
@@ -99,8 +99,6 @@ static void __init tavorevb_init(void)
}
MACHINE_START(TAVOREVB, "PXA910 Evaluation Board (aka TavorEVB)")
- .phys_io = APB_PHYS_BASE,
- .io_pg_offst = (APB_VIRT_BASE >> 18) & 0xfffc,
.map_io = mmp_map_io,
.init_irq = pxa910_init_irq,
.timer = &pxa910_timer,
diff --git a/arch/arm/mach-mmp/teton_bga.c b/arch/arm/mach-mmp/teton_bga.c
new file mode 100644
index 000000000000..bbe4727b96cc
--- /dev/null
+++ b/arch/arm/mach-mmp/teton_bga.c
@@ -0,0 +1,89 @@
+/*
+ * linux/arch/arm/mach-mmp/teton_bga.c
+ *
+ * Support for the Marvell PXA168 Teton BGA Development Platform.
+ *
+ * Author: Mark F. Brown <mark.brown314@gmail.com>
+ *
+ * This code is based on aspenite.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * publishhed by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/input.h>
+#include <plat/pxa27x_keypad.h>
+#include <linux/i2c.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <mach/addr-map.h>
+#include <mach/mfp-pxa168.h>
+#include <mach/pxa168.h>
+#include <mach/teton_bga.h>
+
+#include "common.h"
+
+static unsigned long teton_bga_pin_config[] __initdata = {
+ /* UART1 */
+ GPIO107_UART1_TXD,
+ GPIO108_UART1_RXD,
+
+ /* Keypad */
+ GPIO109_KP_MKIN1,
+ GPIO110_KP_MKIN0,
+ GPIO111_KP_MKOUT7,
+ GPIO112_KP_MKOUT6,
+
+ /* I2C Bus */
+ GPIO105_CI2C_SDA,
+ GPIO106_CI2C_SCL,
+
+ /* RTC */
+ GPIO78_GPIO,
+};
+
+static unsigned int teton_bga_matrix_key_map[] = {
+ KEY(0, 6, KEY_ESC),
+ KEY(0, 7, KEY_ENTER),
+ KEY(1, 6, KEY_LEFT),
+ KEY(1, 7, KEY_RIGHT),
+};
+
+static struct pxa27x_keypad_platform_data teton_bga_keypad_info __initdata = {
+ .matrix_key_rows = 2,
+ .matrix_key_cols = 8,
+ .matrix_key_map = teton_bga_matrix_key_map,
+ .matrix_key_map_size = ARRAY_SIZE(teton_bga_matrix_key_map),
+ .debounce_interval = 30,
+};
+
+static struct i2c_board_info teton_bga_i2c_info[] __initdata = {
+ {
+ I2C_BOARD_INFO("ds1337", 0x68),
+ .irq = gpio_to_irq(RTC_INT_GPIO)
+ },
+};
+
+static void __init teton_bga_init(void)
+{
+ mfp_config(ARRAY_AND_SIZE(teton_bga_pin_config));
+
+ /* on-chip devices */
+ pxa168_add_uart(1);
+ pxa168_add_keypad(&teton_bga_keypad_info);
+ pxa168_add_twsi(0, NULL, ARRAY_AND_SIZE(teton_bga_i2c_info));
+}
+
+MACHINE_START(TETON_BGA, "PXA168-based Teton BGA Development Platform")
+ .map_io = mmp_map_io,
+ .nr_irqs = IRQ_BOARD_START,
+ .init_irq = pxa168_init_irq,
+ .timer = &pxa168_timer,
+ .init_machine = teton_bga_init,
+MACHINE_END
diff --git a/arch/arm/mach-mmp/ttc_dkb.c b/arch/arm/mach-mmp/ttc_dkb.c
index ee65e05f0cf1..e411039ea59e 100644
--- a/arch/arm/mach-mmp/ttc_dkb.c
+++ b/arch/arm/mach-mmp/ttc_dkb.c
@@ -14,6 +14,7 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/onenand.h>
+#include <linux/interrupt.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -24,6 +25,8 @@
#include "common.h"
+#define TTCDKB_NR_IRQS (IRQ_BOARD_START + 24)
+
static unsigned long ttc_dkb_pin_config[] __initdata = {
/* UART2 */
GPIO47_UART2_RXD,
@@ -122,9 +125,8 @@ static void __init ttc_dkb_init(void)
}
MACHINE_START(TTC_DKB, "PXA910-based TTC_DKB Development Platform")
- .phys_io = APB_PHYS_BASE,
- .io_pg_offst = (APB_VIRT_BASE >> 18) & 0xfffc,
.map_io = mmp_map_io,
+ .nr_irqs = TTCDKB_NR_IRQS,
.init_irq = pxa910_init_irq,
.timer = &pxa910_timer,
.init_machine = ttc_dkb_init,
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 47264a76eeb3..3115a29dec4e 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -10,6 +10,8 @@ config ARCH_MSM7X00A
select MSM_SMD
select MSM_SMD_PKG3
select CPU_V6
+ select MSM_PROC_COMM
+ select HAS_MSM_DEBUG_UART_PHYS
config ARCH_MSM7X30
bool "MSM7x30"
@@ -18,6 +20,9 @@ config ARCH_MSM7X30
select MSM_VIC
select CPU_V7
select MSM_REMOTE_SPINLOCK_DEKKERS
+ select MSM_GPIOMUX
+ select MSM_PROC_COMM
+ select HAS_MSM_DEBUG_UART_PHYS
config ARCH_QSD8X50
bool "QSD8X50"
@@ -26,6 +31,19 @@ config ARCH_QSD8X50
select MSM_VIC
select CPU_V7
select MSM_REMOTE_SPINLOCK_LDREX
+ select MSM_GPIOMUX
+ select MSM_PROC_COMM
+ select HAS_MSM_DEBUG_UART_PHYS
+
+config ARCH_MSM8X60
+ bool "MSM8X60"
+ select ARM_GIC
+ select CPU_V7
+ select MSM_V2_TLMM
+ select MSM_GPIOMUX
+ select MACH_MSM8X60_SURF if (!MACH_MSM8X60_RUMI3 && !MACH_MSM8X60_SIM \
+ && !MACH_MSM8X60_FFA)
+
endchoice
config MSM_SOC_REV_A
@@ -36,6 +54,9 @@ config ARCH_MSM_ARM11
config ARCH_MSM_SCORPION
bool
+config HAS_MSM_DEBUG_UART_PHYS
+ bool
+
config MSM_VIC
bool
@@ -74,6 +95,30 @@ config MACH_QSD8X50A_ST1_5
help
Support for the Qualcomm ST1.5.
+config MACH_MSM8X60_RUMI3
+ depends on ARCH_MSM8X60
+ bool "MSM8x60 RUMI3"
+ help
+ Support for the Qualcomm MSM8x60 RUMI3 emulator.
+
+config MACH_MSM8X60_SURF
+ depends on ARCH_MSM8X60
+ bool "MSM8x60 SURF"
+ help
+ Support for the Qualcomm MSM8x60 SURF eval board.
+
+config MACH_MSM8X60_SIM
+ depends on ARCH_MSM8X60
+ bool "MSM8x60 Simulator"
+ help
+ Support for the Qualcomm MSM8x60 simulator.
+
+config MACH_MSM8X60_FFA
+ depends on ARCH_MSM8X60
+ bool "MSM8x60 FFA"
+ help
+ Support for the Qualcomm MSM8x60 FFA eval board.
+
endmenu
config MSM_DEBUG_UART
@@ -82,6 +127,7 @@ config MSM_DEBUG_UART
default 2 if MSM_DEBUG_UART2
default 3 if MSM_DEBUG_UART3
+if HAS_MSM_DEBUG_UART_PHYS
choice
prompt "Debug UART"
@@ -99,11 +145,20 @@ choice
config MSM_DEBUG_UART3
bool "UART3"
endchoice
+endif
config MSM_SMD_PKG3
bool
+config MSM_PROC_COMM
+ bool
+
config MSM_SMD
bool
+config MSM_GPIOMUX
+ bool
+
+config MSM_V2_TLMM
+ bool
endif
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 704610648a25..b5a7b07a44f5 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -1,16 +1,20 @@
-obj-y += proc_comm.o
-obj-y += io.o idle.o timer.o dma.o
-obj-y += vreg.o
+obj-y += io.o idle.o timer.o
+ifndef CONFIG_ARCH_MSM8X60
obj-y += acpuclock-arm11.o
-obj-y += clock.o clock-pcom.o
-obj-y += gpio.o
+obj-y += dma.o
+endif
ifdef CONFIG_MSM_VIC
obj-y += irq-vic.o
else
+ifndef CONFIG_ARCH_MSM8X60
obj-y += irq.o
endif
+endif
+obj-$(CONFIG_ARCH_MSM8X60) += clock-dummy.o iommu.o iommu_dev.o devices-msm8x60-iommu.o
+obj-$(CONFIG_MSM_PROC_COMM) += proc_comm.o clock-pcom.o vreg.o
+obj-$(CONFIG_MSM_PROC_COMM) += clock.o
obj-$(CONFIG_ARCH_QSD8X50) += sirc.o
obj-$(CONFIG_MSM_SMD) += smd.o smd_debug.o
obj-$(CONFIG_MSM_SMD) += last_radio_log.o
@@ -19,4 +23,11 @@ obj-$(CONFIG_MACH_TROUT) += board-trout.o board-trout-gpio.o board-trout-mmc.o d
obj-$(CONFIG_MACH_HALIBUT) += board-halibut.o devices-msm7x00.o
obj-$(CONFIG_ARCH_MSM7X30) += board-msm7x30.o devices-msm7x30.o
obj-$(CONFIG_ARCH_QSD8X50) += board-qsd8x50.o devices-qsd8x50.o
+obj-$(CONFIG_ARCH_MSM8X60) += board-msm8x60.o
+obj-$(CONFIG_ARCH_MSM7X30) += gpiomux-7x30.o gpiomux-v1.o gpiomux.o
+obj-$(CONFIG_ARCH_QSD8X50) += gpiomux-8x50.o gpiomux-v1.o gpiomux.o
+obj-$(CONFIG_ARCH_MSM8X60) += gpiomux-8x60.o gpiomux-v2.o gpiomux.o
+ifndef CONFIG_MSM_V2_TLMM
+obj-y += gpio.o
+endif
diff --git a/arch/arm/mach-msm/board-halibut.c b/arch/arm/mach-msm/board-halibut.c
index 7bd72e8f127e..59edecbe126c 100644
--- a/arch/arm/mach-msm/board-halibut.c
+++ b/arch/arm/mach-msm/board-halibut.c
@@ -95,8 +95,6 @@ static void __init halibut_map_io(void)
MACHINE_START(HALIBUT, "Halibut Board (QCT SURF7200A)")
#ifdef CONFIG_MSM_DEBUG_UART
- .phys_io = MSM_DEBUG_UART_PHYS,
- .io_pg_offst = ((MSM_DEBUG_UART_BASE) >> 18) & 0xfffc,
#endif
.boot_params = 0x10000100,
.fixup = halibut_fixup,
diff --git a/arch/arm/mach-msm/board-mahimahi.c b/arch/arm/mach-msm/board-mahimahi.c
index bcbefdfe7b5e..ef3ebf2f763b 100644
--- a/arch/arm/mach-msm/board-mahimahi.c
+++ b/arch/arm/mach-msm/board-mahimahi.c
@@ -75,8 +75,6 @@ extern struct sys_timer msm_timer;
MACHINE_START(MAHIMAHI, "mahimahi")
#ifdef CONFIG_MSM_DEBUG_UART
- .phys_io = MSM_DEBUG_UART_PHYS,
- .io_pg_offst = ((MSM_DEBUG_UART_BASE) >> 18) & 0xfffc,
#endif
.boot_params = 0x20000100,
.fixup = mahimahi_fixup,
diff --git a/arch/arm/mach-msm/board-msm7x27.c b/arch/arm/mach-msm/board-msm7x27.c
index db9381b85bf0..e7a76eff57d9 100644
--- a/arch/arm/mach-msm/board-msm7x27.c
+++ b/arch/arm/mach-msm/board-msm7x27.c
@@ -131,8 +131,6 @@ static void __init msm7x2x_map_io(void)
MACHINE_START(MSM7X27_SURF, "QCT MSM7x27 SURF")
#ifdef CONFIG_MSM_DEBUG_UART
- .phys_io = MSM_DEBUG_UART_PHYS,
- .io_pg_offst = ((MSM_DEBUG_UART_BASE) >> 18) & 0xfffc,
#endif
.boot_params = PHYS_OFFSET + 0x100,
.map_io = msm7x2x_map_io,
@@ -143,8 +141,6 @@ MACHINE_END
MACHINE_START(MSM7X27_FFA, "QCT MSM7x27 FFA")
#ifdef CONFIG_MSM_DEBUG_UART
- .phys_io = MSM_DEBUG_UART_PHYS,
- .io_pg_offst = ((MSM_DEBUG_UART_BASE) >> 18) & 0xfffc,
#endif
.boot_params = PHYS_OFFSET + 0x100,
.map_io = msm7x2x_map_io,
@@ -155,8 +151,6 @@ MACHINE_END
MACHINE_START(MSM7X25_SURF, "QCT MSM7x25 SURF")
#ifdef CONFIG_MSM_DEBUG_UART
- .phys_io = MSM_DEBUG_UART_PHYS,
- .io_pg_offst = ((MSM_DEBUG_UART_BASE) >> 18) & 0xfffc,
#endif
.boot_params = PHYS_OFFSET + 0x100,
.map_io = msm7x2x_map_io,
@@ -167,8 +161,6 @@ MACHINE_END
MACHINE_START(MSM7X25_FFA, "QCT MSM7x25 FFA")
#ifdef CONFIG_MSM_DEBUG_UART
- .phys_io = MSM_DEBUG_UART_PHYS,
- .io_pg_offst = ((MSM_DEBUG_UART_BASE) >> 18) & 0xfffc,
#endif
.boot_params = PHYS_OFFSET + 0x100,
.map_io = msm7x2x_map_io,
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index e32981928c77..05241df3f9b6 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -39,27 +39,11 @@
extern struct sys_timer msm_timer;
-#ifdef CONFIG_SERIAL_MSM_CONSOLE
-static struct msm_gpio uart2_config_data[] = {
- { GPIO_CFG(49, 2, GPIO_OUTPUT, GPIO_PULL_DOWN, GPIO_2MA), "UART2_RFR"},
- { GPIO_CFG(50, 2, GPIO_INPUT, GPIO_PULL_DOWN, GPIO_2MA), "UART2_CTS"},
- { GPIO_CFG(51, 2, GPIO_INPUT, GPIO_PULL_DOWN, GPIO_2MA), "UART2_Rx"},
- { GPIO_CFG(52, 2, GPIO_OUTPUT, GPIO_PULL_DOWN, GPIO_2MA), "UART2_Tx"},
-};
-
-static void msm7x30_init_uart2(void)
-{
- msm_gpios_request_enable(uart2_config_data,
- ARRAY_SIZE(uart2_config_data));
-
-}
-#endif
-
static struct platform_device *devices[] __initdata = {
#if defined(CONFIG_SERIAL_MSM) || defined(CONFIG_MSM_SERIAL_DEBUGGER)
&msm_device_uart2,
#endif
-
+ &msm_device_smd,
};
static void __init msm7x30_init_irq(void)
@@ -70,10 +54,6 @@ static void __init msm7x30_init_irq(void)
static void __init msm7x30_init(void)
{
platform_add_devices(devices, ARRAY_SIZE(devices));
-#ifdef CONFIG_SERIAL_MSM_CONSOLE
- msm7x30_init_uart2();
-#endif
-
}
static void __init msm7x30_map_io(void)
@@ -84,8 +64,6 @@ static void __init msm7x30_map_io(void)
MACHINE_START(MSM7X30_SURF, "QCT MSM7X30 SURF")
#ifdef CONFIG_MSM_DEBUG_UART
- .phys_io = MSM_DEBUG_UART_PHYS,
- .io_pg_offst = ((MSM_DEBUG_UART_BASE) >> 18) & 0xfffc,
#endif
.boot_params = PHYS_OFFSET + 0x100,
.map_io = msm7x30_map_io,
@@ -96,8 +74,6 @@ MACHINE_END
MACHINE_START(MSM7X30_FFA, "QCT MSM7X30 FFA")
#ifdef CONFIG_MSM_DEBUG_UART
- .phys_io = MSM_DEBUG_UART_PHYS,
- .io_pg_offst = ((MSM_DEBUG_UART_BASE) >> 18) & 0xfffc,
#endif
.boot_params = PHYS_OFFSET + 0x100,
.map_io = msm7x30_map_io,
@@ -108,8 +84,6 @@ MACHINE_END
MACHINE_START(MSM7X30_FLUID, "QCT MSM7X30 FLUID")
#ifdef CONFIG_MSM_DEBUG_UART
- .phys_io = MSM_DEBUG_UART_PHYS,
- .io_pg_offst = ((MSM_DEBUG_UART_BASE) >> 18) & 0xfffc,
#endif
.boot_params = PHYS_OFFSET + 0x100,
.map_io = msm7x30_map_io,
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
new file mode 100644
index 000000000000..7486a681cc71
--- /dev/null
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -0,0 +1,100 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/hardware/gic.h>
+
+#include <mach/board.h>
+#include <mach/msm_iomap.h>
+
+void __iomem *gic_cpu_base_addr;
+
+unsigned long clk_get_max_axi_khz(void)
+{
+ return 0;
+}
+
+static void __init msm8x60_map_io(void)
+{
+ msm_map_msm8x60_io();
+}
+
+static void __init msm8x60_init_irq(void)
+{
+ unsigned int i;
+
+ gic_dist_init(0, MSM_QGIC_DIST_BASE, GIC_PPI_START);
+ gic_cpu_base_addr = (void *)MSM_QGIC_CPU_BASE;
+ gic_cpu_init(0, MSM_QGIC_CPU_BASE);
+
+ /* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */
+ writel(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4);
+
+ /* RUMI does not adhere to GIC spec by enabling STIs by default.
+ * Enable/clear is supposed to be RO for STIs, but is RW on RUMI.
+ */
+ if (!machine_is_msm8x60_sim())
+ writel(0x0000FFFF, MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_SET);
+
+ /* FIXME: Not installing AVS_SVICINT and AVS_SVICINTSWDONE yet
+ * as they are configured as level, which does not play nice with
+ * handle_percpu_irq.
+ */
+ for (i = GIC_PPI_START; i < GIC_SPI_START; i++) {
+ if (i != AVS_SVICINT && i != AVS_SVICINTSWDONE)
+ set_irq_handler(i, handle_percpu_irq);
+ }
+}
+
+static void __init msm8x60_init(void)
+{
+}
+
+MACHINE_START(MSM8X60_RUMI3, "QCT MSM8X60 RUMI3")
+ .map_io = msm8x60_map_io,
+ .init_irq = msm8x60_init_irq,
+ .init_machine = msm8x60_init,
+ .timer = &msm_timer,
+MACHINE_END
+
+MACHINE_START(MSM8X60_SURF, "QCT MSM8X60 SURF")
+ .map_io = msm8x60_map_io,
+ .init_irq = msm8x60_init_irq,
+ .init_machine = msm8x60_init,
+ .timer = &msm_timer,
+MACHINE_END
+
+MACHINE_START(MSM8X60_SIM, "QCT MSM8X60 SIMULATOR")
+ .map_io = msm8x60_map_io,
+ .init_irq = msm8x60_init_irq,
+ .init_machine = msm8x60_init,
+ .timer = &msm_timer,
+MACHINE_END
+
+MACHINE_START(MSM8X60_FFA, "QCT MSM8X60 FFA")
+ .map_io = msm8x60_map_io,
+ .init_irq = msm8x60_init_irq,
+ .init_machine = msm8x60_init,
+ .timer = &msm_timer,
+MACHINE_END
diff --git a/arch/arm/mach-msm/board-qsd8x50.c b/arch/arm/mach-msm/board-qsd8x50.c
index e3cc80792d6c..ed2af4ad97ed 100644
--- a/arch/arm/mach-msm/board-qsd8x50.c
+++ b/arch/arm/mach-msm/board-qsd8x50.c
@@ -35,20 +35,49 @@
extern struct sys_timer msm_timer;
-static struct msm_gpio uart3_config_data[] = {
- { GPIO_CFG(86, 1, GPIO_INPUT, GPIO_PULL_DOWN, GPIO_2MA), "UART2_Rx"},
- { GPIO_CFG(87, 1, GPIO_OUTPUT, GPIO_PULL_DOWN, GPIO_2MA), "UART2_Tx"},
+static const resource_size_t qsd8x50_surf_smc91x_base __initdata = 0x70000300;
+static const unsigned qsd8x50_surf_smc91x_gpio __initdata = 156;
+
+/* Leave smc91x resources empty here, as we'll fill them in
+ * at run-time: they vary from board to board, and the true
+ * configuration won't be known until boot.
+ */
+static struct resource smc91x_resources[] __initdata = {
+ [0] = {
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .flags = IORESOURCE_IRQ,
+ },
};
-static struct platform_device *devices[] __initdata = {
- &msm_device_uart3,
+static struct platform_device smc91x_device __initdata = {
+ .name = "smc91x",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(smc91x_resources),
+ .resource = smc91x_resources,
};
-static void msm8x50_init_uart3(void)
+static int __init msm_init_smc91x(void)
{
- msm_gpios_request_enable(uart3_config_data,
- ARRAY_SIZE(uart3_config_data));
+ if (machine_is_qsd8x50_surf()) {
+ smc91x_resources[0].start = qsd8x50_surf_smc91x_base;
+ smc91x_resources[0].end = qsd8x50_surf_smc91x_base + 0xff;
+ smc91x_resources[1].start =
+ gpio_to_irq(qsd8x50_surf_smc91x_gpio);
+ smc91x_resources[1].end =
+ gpio_to_irq(qsd8x50_surf_smc91x_gpio);
+ platform_device_register(&smc91x_device);
+ }
+
+ return 0;
}
+module_init(msm_init_smc91x);
+
+static struct platform_device *devices[] __initdata = {
+ &msm_device_uart3,
+ &msm_device_smd,
+};
static void __init qsd8x50_map_io(void)
{
@@ -64,14 +93,11 @@ static void __init qsd8x50_init_irq(void)
static void __init qsd8x50_init(void)
{
- msm8x50_init_uart3();
platform_add_devices(devices, ARRAY_SIZE(devices));
}
MACHINE_START(QSD8X50_SURF, "QCT QSD8X50 SURF")
#ifdef CONFIG_MSM_DEBUG_UART
- .phys_io = MSM_DEBUG_UART_PHYS,
- .io_pg_offst = ((MSM_DEBUG_UART_BASE) >> 18) & 0xfffc,
#endif
.boot_params = PHYS_OFFSET + 0x100,
.map_io = qsd8x50_map_io,
@@ -82,8 +108,6 @@ MACHINE_END
MACHINE_START(QSD8X50A_ST1_5, "QCT QSD8X50A ST1.5")
#ifdef CONFIG_MSM_DEBUG_UART
- .phys_io = MSM_DEBUG_UART_PHYS,
- .io_pg_offst = ((MSM_DEBUG_UART_BASE) >> 18) & 0xfffc,
#endif
.boot_params = PHYS_OFFSET + 0x100,
.map_io = qsd8x50_map_io,
diff --git a/arch/arm/mach-msm/board-sapphire.c b/arch/arm/mach-msm/board-sapphire.c
index 2bc1b9d5623e..8919ffb17196 100644
--- a/arch/arm/mach-msm/board-sapphire.c
+++ b/arch/arm/mach-msm/board-sapphire.c
@@ -106,8 +106,6 @@ static void __init sapphire_map_io(void)
MACHINE_START(SAPPHIRE, "sapphire")
/* Maintainer: Brian Swetland <swetland@google.com> */
#ifdef CONFIG_MSM_DEBUG_UART
- .phys_io = MSM_DEBUG_UART_PHYS,
- .io_pg_offst = ((MSM_DEBUG_UART_BASE) >> 18) & 0xfffc,
#endif
.boot_params = PHYS_OFFSET + 0x100,
.fixup = sapphire_fixup,
diff --git a/arch/arm/mach-msm/board-trout.c b/arch/arm/mach-msm/board-trout.c
index 469e0be3499d..73f146066542 100644
--- a/arch/arm/mach-msm/board-trout.c
+++ b/arch/arm/mach-msm/board-trout.c
@@ -93,8 +93,6 @@ static void __init trout_map_io(void)
MACHINE_START(TROUT, "HTC Dream")
#ifdef CONFIG_MSM_DEBUG_UART
- .phys_io = MSM_DEBUG_UART_PHYS,
- .io_pg_offst = ((MSM_DEBUG_UART_BASE) >> 18) & 0xfffc,
#endif
.boot_params = 0x10000100,
.fixup = trout_fixup,
diff --git a/arch/arm/mach-msm/clock-dummy.c b/arch/arm/mach-msm/clock-dummy.c
new file mode 100644
index 000000000000..1250d22082ee
--- /dev/null
+++ b/arch/arm/mach-msm/clock-dummy.c
@@ -0,0 +1,54 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/module.h>
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+ return ERR_PTR(-ENOENT);
+}
+EXPORT_SYMBOL(clk_get);
+
+int clk_enable(struct clk *clk)
+{
+ return -ENOENT;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+ return 0;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ return -ENOENT;
+}
+EXPORT_SYMBOL(clk_set_rate);
+
+void clk_put(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_put);
diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c
index b449e8ad2904..7fcf2e3b7698 100644
--- a/arch/arm/mach-msm/devices-msm7x30.c
+++ b/arch/arm/mach-msm/devices-msm7x30.c
@@ -51,6 +51,11 @@ struct platform_device msm_device_uart2 = {
.resource = resources_uart2,
};
+struct platform_device msm_device_smd = {
+ .name = "msm_smd",
+ .id = -1,
+};
+
struct clk msm_clocks_7x30[] = {
CLK_PCOM("adm_clk", ADM_CLK, NULL, 0),
CLK_PCOM("adsp_clk", ADSP_CLK, NULL, 0),
diff --git a/arch/arm/mach-msm/devices-msm8x60-iommu.c b/arch/arm/mach-msm/devices-msm8x60-iommu.c
new file mode 100644
index 000000000000..89b9d4437e92
--- /dev/null
+++ b/arch/arm/mach-msm/devices-msm8x60-iommu.c
@@ -0,0 +1,883 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/bootmem.h>
+
+#include <mach/msm_iomap-8x60.h>
+#include <mach/irqs-8x60.h>
+#include <mach/iommu.h>
+
+static struct resource msm_iommu_jpegd_resources[] = {
+ {
+ .start = MSM_IOMMU_JPEGD_PHYS,
+ .end = MSM_IOMMU_JPEGD_PHYS + MSM_IOMMU_JPEGD_SIZE - 1,
+ .name = "physbase",
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "nonsecure_irq",
+ .start = SMMU_JPEGD_CB_SC_NON_SECURE_IRQ,
+ .end = SMMU_JPEGD_CB_SC_NON_SECURE_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "secure_irq",
+ .start = SMMU_JPEGD_CB_SC_SECURE_IRQ,
+ .end = SMMU_JPEGD_CB_SC_SECURE_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource msm_iommu_vpe_resources[] = {
+ {
+ .start = MSM_IOMMU_VPE_PHYS,
+ .end = MSM_IOMMU_VPE_PHYS + MSM_IOMMU_VPE_SIZE - 1,
+ .name = "physbase",
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "nonsecure_irq",
+ .start = SMMU_VPE_CB_SC_NON_SECURE_IRQ,
+ .end = SMMU_VPE_CB_SC_NON_SECURE_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "secure_irq",
+ .start = SMMU_VPE_CB_SC_SECURE_IRQ,
+ .end = SMMU_VPE_CB_SC_SECURE_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource msm_iommu_mdp0_resources[] = {
+ {
+ .start = MSM_IOMMU_MDP0_PHYS,
+ .end = MSM_IOMMU_MDP0_PHYS + MSM_IOMMU_MDP0_SIZE - 1,
+ .name = "physbase",
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "nonsecure_irq",
+ .start = SMMU_MDP0_CB_SC_NON_SECURE_IRQ,
+ .end = SMMU_MDP0_CB_SC_NON_SECURE_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "secure_irq",
+ .start = SMMU_MDP0_CB_SC_SECURE_IRQ,
+ .end = SMMU_MDP0_CB_SC_SECURE_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource msm_iommu_mdp1_resources[] = {
+ {
+ .start = MSM_IOMMU_MDP1_PHYS,
+ .end = MSM_IOMMU_MDP1_PHYS + MSM_IOMMU_MDP1_SIZE - 1,
+ .name = "physbase",
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "nonsecure_irq",
+ .start = SMMU_MDP1_CB_SC_NON_SECURE_IRQ,
+ .end = SMMU_MDP1_CB_SC_NON_SECURE_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "secure_irq",
+ .start = SMMU_MDP1_CB_SC_SECURE_IRQ,
+ .end = SMMU_MDP1_CB_SC_SECURE_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource msm_iommu_rot_resources[] = {
+ {
+ .start = MSM_IOMMU_ROT_PHYS,
+ .end = MSM_IOMMU_ROT_PHYS + MSM_IOMMU_ROT_SIZE - 1,
+ .name = "physbase",
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "nonsecure_irq",
+ .start = SMMU_ROT_CB_SC_NON_SECURE_IRQ,
+ .end = SMMU_ROT_CB_SC_NON_SECURE_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "secure_irq",
+ .start = SMMU_ROT_CB_SC_SECURE_IRQ,
+ .end = SMMU_ROT_CB_SC_SECURE_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource msm_iommu_ijpeg_resources[] = {
+ {
+ .start = MSM_IOMMU_IJPEG_PHYS,
+ .end = MSM_IOMMU_IJPEG_PHYS + MSM_IOMMU_IJPEG_SIZE - 1,
+ .name = "physbase",
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "nonsecure_irq",
+ .start = SMMU_IJPEG_CB_SC_NON_SECURE_IRQ,
+ .end = SMMU_IJPEG_CB_SC_NON_SECURE_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "secure_irq",
+ .start = SMMU_IJPEG_CB_SC_SECURE_IRQ,
+ .end = SMMU_IJPEG_CB_SC_SECURE_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource msm_iommu_vfe_resources[] = {
+ {
+ .start = MSM_IOMMU_VFE_PHYS,
+ .end = MSM_IOMMU_VFE_PHYS + MSM_IOMMU_VFE_SIZE - 1,
+ .name = "physbase",
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "nonsecure_irq",
+ .start = SMMU_VFE_CB_SC_NON_SECURE_IRQ,
+ .end = SMMU_VFE_CB_SC_NON_SECURE_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "secure_irq",
+ .start = SMMU_VFE_CB_SC_SECURE_IRQ,
+ .end = SMMU_VFE_CB_SC_SECURE_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource msm_iommu_vcodec_a_resources[] = {
+ {
+ .start = MSM_IOMMU_VCODEC_A_PHYS,
+ .end = MSM_IOMMU_VCODEC_A_PHYS + MSM_IOMMU_VCODEC_A_SIZE - 1,
+ .name = "physbase",
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "nonsecure_irq",
+ .start = SMMU_VCODEC_A_CB_SC_NON_SECURE_IRQ,
+ .end = SMMU_VCODEC_A_CB_SC_NON_SECURE_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "secure_irq",
+ .start = SMMU_VCODEC_A_CB_SC_SECURE_IRQ,
+ .end = SMMU_VCODEC_A_CB_SC_SECURE_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource msm_iommu_vcodec_b_resources[] = {
+ {
+ .start = MSM_IOMMU_VCODEC_B_PHYS,
+ .end = MSM_IOMMU_VCODEC_B_PHYS + MSM_IOMMU_VCODEC_B_SIZE - 1,
+ .name = "physbase",
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "nonsecure_irq",
+ .start = SMMU_VCODEC_B_CB_SC_NON_SECURE_IRQ,
+ .end = SMMU_VCODEC_B_CB_SC_NON_SECURE_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "secure_irq",
+ .start = SMMU_VCODEC_B_CB_SC_SECURE_IRQ,
+ .end = SMMU_VCODEC_B_CB_SC_SECURE_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource msm_iommu_gfx3d_resources[] = {
+ {
+ .start = MSM_IOMMU_GFX3D_PHYS,
+ .end = MSM_IOMMU_GFX3D_PHYS + MSM_IOMMU_GFX3D_SIZE - 1,
+ .name = "physbase",
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "nonsecure_irq",
+ .start = SMMU_GFX3D_CB_SC_NON_SECURE_IRQ,
+ .end = SMMU_GFX3D_CB_SC_NON_SECURE_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "secure_irq",
+ .start = SMMU_GFX3D_CB_SC_SECURE_IRQ,
+ .end = SMMU_GFX3D_CB_SC_SECURE_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource msm_iommu_gfx2d0_resources[] = {
+ {
+ .start = MSM_IOMMU_GFX2D0_PHYS,
+ .end = MSM_IOMMU_GFX2D0_PHYS + MSM_IOMMU_GFX2D0_SIZE - 1,
+ .name = "physbase",
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "nonsecure_irq",
+ .start = SMMU_GFX2D0_CB_SC_NON_SECURE_IRQ,
+ .end = SMMU_GFX2D0_CB_SC_NON_SECURE_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "secure_irq",
+ .start = SMMU_GFX2D0_CB_SC_SECURE_IRQ,
+ .end = SMMU_GFX2D0_CB_SC_SECURE_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device msm_root_iommu_dev = {
+ .name = "msm_iommu",
+ .id = -1,
+};
+
+static struct msm_iommu_dev jpegd_smmu = {
+ .name = "jpegd",
+ .clk_rate = -1
+};
+
+static struct msm_iommu_dev vpe_smmu = {
+ .name = "vpe"
+};
+
+static struct msm_iommu_dev mdp0_smmu = {
+ .name = "mdp0"
+};
+
+static struct msm_iommu_dev mdp1_smmu = {
+ .name = "mdp1"
+};
+
+static struct msm_iommu_dev rot_smmu = {
+ .name = "rot"
+};
+
+static struct msm_iommu_dev ijpeg_smmu = {
+ .name = "ijpeg"
+};
+
+static struct msm_iommu_dev vfe_smmu = {
+ .name = "vfe",
+ .clk_rate = -1
+};
+
+static struct msm_iommu_dev vcodec_a_smmu = {
+ .name = "vcodec_a"
+};
+
+static struct msm_iommu_dev vcodec_b_smmu = {
+ .name = "vcodec_b"
+};
+
+static struct msm_iommu_dev gfx3d_smmu = {
+ .name = "gfx3d",
+ .clk_rate = 27000000
+};
+
+static struct msm_iommu_dev gfx2d0_smmu = {
+ .name = "gfx2d0",
+ .clk_rate = 27000000
+};
+
+static struct platform_device msm_device_smmu_jpegd = {
+ .name = "msm_iommu",
+ .id = 0,
+ .dev = {
+ .parent = &msm_root_iommu_dev.dev,
+ },
+ .num_resources = ARRAY_SIZE(msm_iommu_jpegd_resources),
+ .resource = msm_iommu_jpegd_resources,
+};
+
+static struct platform_device msm_device_smmu_vpe = {
+ .name = "msm_iommu",
+ .id = 1,
+ .dev = {
+ .parent = &msm_root_iommu_dev.dev,
+ },
+ .num_resources = ARRAY_SIZE(msm_iommu_vpe_resources),
+ .resource = msm_iommu_vpe_resources,
+};
+
+static struct platform_device msm_device_smmu_mdp0 = {
+ .name = "msm_iommu",
+ .id = 2,
+ .dev = {
+ .parent = &msm_root_iommu_dev.dev,
+ },
+ .num_resources = ARRAY_SIZE(msm_iommu_mdp0_resources),
+ .resource = msm_iommu_mdp0_resources,
+};
+
+static struct platform_device msm_device_smmu_mdp1 = {
+ .name = "msm_iommu",
+ .id = 3,
+ .dev = {
+ .parent = &msm_root_iommu_dev.dev,
+ },
+ .num_resources = ARRAY_SIZE(msm_iommu_mdp1_resources),
+ .resource = msm_iommu_mdp1_resources,
+};
+
+static struct platform_device msm_device_smmu_rot = {
+ .name = "msm_iommu",
+ .id = 4,
+ .dev = {
+ .parent = &msm_root_iommu_dev.dev,
+ },
+ .num_resources = ARRAY_SIZE(msm_iommu_rot_resources),
+ .resource = msm_iommu_rot_resources,
+};
+
+static struct platform_device msm_device_smmu_ijpeg = {
+ .name = "msm_iommu",
+ .id = 5,
+ .dev = {
+ .parent = &msm_root_iommu_dev.dev,
+ },
+ .num_resources = ARRAY_SIZE(msm_iommu_ijpeg_resources),
+ .resource = msm_iommu_ijpeg_resources,
+};
+
+static struct platform_device msm_device_smmu_vfe = {
+ .name = "msm_iommu",
+ .id = 6,
+ .dev = {
+ .parent = &msm_root_iommu_dev.dev,
+ },
+ .num_resources = ARRAY_SIZE(msm_iommu_vfe_resources),
+ .resource = msm_iommu_vfe_resources,
+};
+
+static struct platform_device msm_device_smmu_vcodec_a = {
+ .name = "msm_iommu",
+ .id = 7,
+ .dev = {
+ .parent = &msm_root_iommu_dev.dev,
+ },
+ .num_resources = ARRAY_SIZE(msm_iommu_vcodec_a_resources),
+ .resource = msm_iommu_vcodec_a_resources,
+};
+
+static struct platform_device msm_device_smmu_vcodec_b = {
+ .name = "msm_iommu",
+ .id = 8,
+ .dev = {
+ .parent = &msm_root_iommu_dev.dev,
+ },
+ .num_resources = ARRAY_SIZE(msm_iommu_vcodec_b_resources),
+ .resource = msm_iommu_vcodec_b_resources,
+};
+
+static struct platform_device msm_device_smmu_gfx3d = {
+ .name = "msm_iommu",
+ .id = 9,
+ .dev = {
+ .parent = &msm_root_iommu_dev.dev,
+ },
+ .num_resources = ARRAY_SIZE(msm_iommu_gfx3d_resources),
+ .resource = msm_iommu_gfx3d_resources,
+};
+
+static struct platform_device msm_device_smmu_gfx2d0 = {
+ .name = "msm_iommu",
+ .id = 10,
+ .dev = {
+ .parent = &msm_root_iommu_dev.dev,
+ },
+ .num_resources = ARRAY_SIZE(msm_iommu_gfx2d0_resources),
+ .resource = msm_iommu_gfx2d0_resources,
+};
+
+static struct msm_iommu_ctx_dev jpegd_src_ctx = {
+ .name = "jpegd_src",
+ .num = 0,
+ .mids = {0, -1}
+};
+
+static struct msm_iommu_ctx_dev jpegd_dst_ctx = {
+ .name = "jpegd_dst",
+ .num = 1,
+ .mids = {1, -1}
+};
+
+static struct msm_iommu_ctx_dev vpe_src_ctx = {
+ .name = "vpe_src",
+ .num = 0,
+ .mids = {0, -1}
+};
+
+static struct msm_iommu_ctx_dev vpe_dst_ctx = {
+ .name = "vpe_dst",
+ .num = 1,
+ .mids = {1, -1}
+};
+
+static struct msm_iommu_ctx_dev mdp_vg1_ctx = {
+ .name = "mdp_vg1",
+ .num = 0,
+ .mids = {0, 2, -1}
+};
+
+static struct msm_iommu_ctx_dev mdp_rgb1_ctx = {
+ .name = "mdp_rgb1",
+ .num = 1,
+ .mids = {1, 3, 4, 5, 6, 7, 8, 9, 10, -1}
+};
+
+static struct msm_iommu_ctx_dev mdp_vg2_ctx = {
+ .name = "mdp_vg2",
+ .num = 0,
+ .mids = {0, 2, -1}
+};
+
+static struct msm_iommu_ctx_dev mdp_rgb2_ctx = {
+ .name = "mdp_rgb2",
+ .num = 1,
+ .mids = {1, 3, 4, 5, 6, 7, 8, 9, 10, -1}
+};
+
+static struct msm_iommu_ctx_dev rot_src_ctx = {
+ .name = "rot_src",
+ .num = 0,
+ .mids = {0, -1}
+};
+
+static struct msm_iommu_ctx_dev rot_dst_ctx = {
+ .name = "rot_dst",
+ .num = 1,
+ .mids = {1, -1}
+};
+
+static struct msm_iommu_ctx_dev ijpeg_src_ctx = {
+ .name = "ijpeg_src",
+ .num = 0,
+ .mids = {0, -1}
+};
+
+static struct msm_iommu_ctx_dev ijpeg_dst_ctx = {
+ .name = "ijpeg_dst",
+ .num = 1,
+ .mids = {1, -1}
+};
+
+static struct msm_iommu_ctx_dev vfe_imgwr_ctx = {
+ .name = "vfe_imgwr",
+ .num = 0,
+ .mids = {2, 3, 4, 5, 6, 7, 8, -1}
+};
+
+static struct msm_iommu_ctx_dev vfe_misc_ctx = {
+ .name = "vfe_misc",
+ .num = 1,
+ .mids = {0, 1, 9, -1}
+};
+
+static struct msm_iommu_ctx_dev vcodec_a_stream_ctx = {
+ .name = "vcodec_a_stream",
+ .num = 0,
+ .mids = {2, 5, -1}
+};
+
+static struct msm_iommu_ctx_dev vcodec_a_mm1_ctx = {
+ .name = "vcodec_a_mm1",
+ .num = 1,
+ .mids = {0, 1, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -1}
+};
+
+static struct msm_iommu_ctx_dev vcodec_b_mm2_ctx = {
+ .name = "vcodec_b_mm2",
+ .num = 0,
+ .mids = {0, 1, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -1}
+};
+
+static struct msm_iommu_ctx_dev gfx3d_rbpa_ctx = {
+ .name = "gfx3d_rbpa",
+ .num = 0,
+ .mids = {-1}
+};
+
+static struct msm_iommu_ctx_dev gfx3d_cpvgttc_ctx = {
+ .name = "gfx3d_cpvgttc",
+ .num = 1,
+ .mids = {0, 1, 2, 3, 4, 5, 6, 7, -1}
+};
+
+static struct msm_iommu_ctx_dev gfx3d_smmu_ctx = {
+ .name = "gfx3d_smmu",
+ .num = 2,
+ .mids = {8, 9, 10, 11, 12, -1}
+};
+
+static struct msm_iommu_ctx_dev gfx2d0_pixv1_ctx = {
+ .name = "gfx2d0_pixv1_smmu",
+ .num = 0,
+ .mids = {0, 3, 4, -1}
+};
+
+static struct msm_iommu_ctx_dev gfx2d0_texv3_ctx = {
+ .name = "gfx2d0_texv3_smmu",
+ .num = 1,
+ .mids = {1, 6, 7, -1}
+};
+
+static struct platform_device msm_device_jpegd_src_ctx = {
+ .name = "msm_iommu_ctx",
+ .id = 0,
+ .dev = {
+ .parent = &msm_device_smmu_jpegd.dev,
+ },
+};
+
+static struct platform_device msm_device_jpegd_dst_ctx = {
+ .name = "msm_iommu_ctx",
+ .id = 1,
+ .dev = {
+ .parent = &msm_device_smmu_jpegd.dev,
+ },
+};
+
+static struct platform_device msm_device_vpe_src_ctx = {
+ .name = "msm_iommu_ctx",
+ .id = 2,
+ .dev = {
+ .parent = &msm_device_smmu_vpe.dev,
+ },
+};
+
+static struct platform_device msm_device_vpe_dst_ctx = {
+ .name = "msm_iommu_ctx",
+ .id = 3,
+ .dev = {
+ .parent = &msm_device_smmu_vpe.dev,
+ },
+};
+
+static struct platform_device msm_device_mdp_vg1_ctx = {
+ .name = "msm_iommu_ctx",
+ .id = 4,
+ .dev = {
+ .parent = &msm_device_smmu_mdp0.dev,
+ },
+};
+
+static struct platform_device msm_device_mdp_rgb1_ctx = {
+ .name = "msm_iommu_ctx",
+ .id = 5,
+ .dev = {
+ .parent = &msm_device_smmu_mdp0.dev,
+ },
+};
+
+static struct platform_device msm_device_mdp_vg2_ctx = {
+ .name = "msm_iommu_ctx",
+ .id = 6,
+ .dev = {
+ .parent = &msm_device_smmu_mdp1.dev,
+ },
+};
+
+static struct platform_device msm_device_mdp_rgb2_ctx = {
+ .name = "msm_iommu_ctx",
+ .id = 7,
+ .dev = {
+ .parent = &msm_device_smmu_mdp1.dev,
+ },
+};
+
+static struct platform_device msm_device_rot_src_ctx = {
+ .name = "msm_iommu_ctx",
+ .id = 8,
+ .dev = {
+ .parent = &msm_device_smmu_rot.dev,
+ },
+};
+
+static struct platform_device msm_device_rot_dst_ctx = {
+ .name = "msm_iommu_ctx",
+ .id = 9,
+ .dev = {
+ .parent = &msm_device_smmu_rot.dev,
+ },
+};
+
+static struct platform_device msm_device_ijpeg_src_ctx = {
+ .name = "msm_iommu_ctx",
+ .id = 10,
+ .dev = {
+ .parent = &msm_device_smmu_ijpeg.dev,
+ },
+};
+
+static struct platform_device msm_device_ijpeg_dst_ctx = {
+ .name = "msm_iommu_ctx",
+ .id = 11,
+ .dev = {
+ .parent = &msm_device_smmu_ijpeg.dev,
+ },
+};
+
+static struct platform_device msm_device_vfe_imgwr_ctx = {
+ .name = "msm_iommu_ctx",
+ .id = 12,
+ .dev = {
+ .parent = &msm_device_smmu_vfe.dev,
+ },
+};
+
+static struct platform_device msm_device_vfe_misc_ctx = {
+ .name = "msm_iommu_ctx",
+ .id = 13,
+ .dev = {
+ .parent = &msm_device_smmu_vfe.dev,
+ },
+};
+
+static struct platform_device msm_device_vcodec_a_stream_ctx = {
+ .name = "msm_iommu_ctx",
+ .id = 14,
+ .dev = {
+ .parent = &msm_device_smmu_vcodec_a.dev,
+ },
+};
+
+static struct platform_device msm_device_vcodec_a_mm1_ctx = {
+ .name = "msm_iommu_ctx",
+ .id = 15,
+ .dev = {
+ .parent = &msm_device_smmu_vcodec_a.dev,
+ },
+};
+
+static struct platform_device msm_device_vcodec_b_mm2_ctx = {
+ .name = "msm_iommu_ctx",
+ .id = 16,
+ .dev = {
+ .parent = &msm_device_smmu_vcodec_b.dev,
+ },
+};
+
+static struct platform_device msm_device_gfx3d_rbpa_ctx = {
+ .name = "msm_iommu_ctx",
+ .id = 17,
+ .dev = {
+ .parent = &msm_device_smmu_gfx3d.dev,
+ },
+};
+
+static struct platform_device msm_device_gfx3d_cpvgttc_ctx = {
+ .name = "msm_iommu_ctx",
+ .id = 18,
+ .dev = {
+ .parent = &msm_device_smmu_gfx3d.dev,
+ },
+};
+
+static struct platform_device msm_device_gfx3d_smmu_ctx = {
+ .name = "msm_iommu_ctx",
+ .id = 19,
+ .dev = {
+ .parent = &msm_device_smmu_gfx3d.dev,
+ },
+};
+
+static struct platform_device msm_device_gfx2d0_pixv1_ctx = {
+ .name = "msm_iommu_ctx",
+ .id = 20,
+ .dev = {
+ .parent = &msm_device_smmu_gfx2d0.dev,
+ },
+};
+
+static struct platform_device msm_device_gfx2d0_texv3_ctx = {
+ .name = "msm_iommu_ctx",
+ .id = 21,
+ .dev = {
+ .parent = &msm_device_smmu_gfx2d0.dev,
+ },
+};
+
+static struct platform_device *msm_iommu_devs[] = {
+ &msm_device_smmu_jpegd,
+ &msm_device_smmu_vpe,
+ &msm_device_smmu_mdp0,
+ &msm_device_smmu_mdp1,
+ &msm_device_smmu_rot,
+ &msm_device_smmu_ijpeg,
+ &msm_device_smmu_vfe,
+ &msm_device_smmu_vcodec_a,
+ &msm_device_smmu_vcodec_b,
+ &msm_device_smmu_gfx3d,
+ &msm_device_smmu_gfx2d0,
+};
+
+static struct msm_iommu_dev *msm_iommu_data[] = {
+ &jpegd_smmu,
+ &vpe_smmu,
+ &mdp0_smmu,
+ &mdp1_smmu,
+ &rot_smmu,
+ &ijpeg_smmu,
+ &vfe_smmu,
+ &vcodec_a_smmu,
+ &vcodec_b_smmu,
+ &gfx3d_smmu,
+ &gfx2d0_smmu,
+};
+
+static struct platform_device *msm_iommu_ctx_devs[] = {
+ &msm_device_jpegd_src_ctx,
+ &msm_device_jpegd_dst_ctx,
+ &msm_device_vpe_src_ctx,
+ &msm_device_vpe_dst_ctx,
+ &msm_device_mdp_vg1_ctx,
+ &msm_device_mdp_rgb1_ctx,
+ &msm_device_mdp_vg2_ctx,
+ &msm_device_mdp_rgb2_ctx,
+ &msm_device_rot_src_ctx,
+ &msm_device_rot_dst_ctx,
+ &msm_device_ijpeg_src_ctx,
+ &msm_device_ijpeg_dst_ctx,
+ &msm_device_vfe_imgwr_ctx,
+ &msm_device_vfe_misc_ctx,
+ &msm_device_vcodec_a_stream_ctx,
+ &msm_device_vcodec_a_mm1_ctx,
+ &msm_device_vcodec_b_mm2_ctx,
+ &msm_device_gfx3d_rbpa_ctx,
+ &msm_device_gfx3d_cpvgttc_ctx,
+ &msm_device_gfx3d_smmu_ctx,
+ &msm_device_gfx2d0_pixv1_ctx,
+ &msm_device_gfx2d0_texv3_ctx,
+};
+
+static struct msm_iommu_ctx_dev *msm_iommu_ctx_data[] = {
+ &jpegd_src_ctx,
+ &jpegd_dst_ctx,
+ &vpe_src_ctx,
+ &vpe_dst_ctx,
+ &mdp_vg1_ctx,
+ &mdp_rgb1_ctx,
+ &mdp_vg2_ctx,
+ &mdp_rgb2_ctx,
+ &rot_src_ctx,
+ &rot_dst_ctx,
+ &ijpeg_src_ctx,
+ &ijpeg_dst_ctx,
+ &vfe_imgwr_ctx,
+ &vfe_misc_ctx,
+ &vcodec_a_stream_ctx,
+ &vcodec_a_mm1_ctx,
+ &vcodec_b_mm2_ctx,
+ &gfx3d_rbpa_ctx,
+ &gfx3d_cpvgttc_ctx,
+ &gfx3d_smmu_ctx,
+ &gfx2d0_pixv1_ctx,
+ &gfx2d0_texv3_ctx,
+};
+
+static int msm8x60_iommu_init(void)
+{
+ int ret, i;
+
+ ret = platform_device_register(&msm_root_iommu_dev);
+ if (ret != 0) {
+ pr_err("Failed to register root IOMMU device!\n");
+ goto failure;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(msm_iommu_devs); i++) {
+ ret = platform_device_add_data(msm_iommu_devs[i],
+ msm_iommu_data[i],
+ sizeof(struct msm_iommu_dev));
+ if (ret != 0) {
+ pr_err("platform_device_add_data failed, "
+ "i = %d\n", i);
+ goto failure_unwind;
+ }
+
+ ret = platform_device_register(msm_iommu_devs[i]);
+
+ if (ret != 0) {
+ pr_err("platform_device_register smmu failed, "
+ "i = %d\n", i);
+ goto failure_unwind;
+ }
+ }
+
+ for (i = 0; i < ARRAY_SIZE(msm_iommu_ctx_devs); i++) {
+ ret = platform_device_add_data(msm_iommu_ctx_devs[i],
+ msm_iommu_ctx_data[i],
+ sizeof(*msm_iommu_ctx_devs[i]));
+ if (ret != 0) {
+ pr_err("platform_device_add_data smmu failed, "
+ "i = %d\n", i);
+ goto failure_unwind2;
+ }
+
+ ret = platform_device_register(msm_iommu_ctx_devs[i]);
+ if (ret != 0) {
+ pr_err("platform_device_register ctx failed, "
+ "i = %d\n", i);
+ goto failure_unwind2;
+ }
+ }
+ return 0;
+
+failure_unwind2:
+ while (--i >= 0)
+ platform_device_unregister(msm_iommu_ctx_devs[i]);
+failure_unwind:
+ while (--i >= 0)
+ platform_device_unregister(msm_iommu_devs[i]);
+
+ platform_device_unregister(&msm_root_iommu_dev);
+failure:
+ return ret;
+}
+
+static void msm8x60_iommu_exit(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(msm_iommu_ctx_devs); i++)
+ platform_device_unregister(msm_iommu_ctx_devs[i]);
+
+ for (i = 0; i < ARRAY_SIZE(msm_iommu_devs); ++i)
+ platform_device_unregister(msm_iommu_devs[i]);
+
+ platform_device_unregister(&msm_root_iommu_dev);
+}
+
+subsys_initcall(msm8x60_iommu_init);
+module_exit(msm8x60_iommu_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Stepan Moskovchenko <stepanm@codeaurora.org>");
diff --git a/arch/arm/mach-msm/devices-qsd8x50.c b/arch/arm/mach-msm/devices-qsd8x50.c
index 4d4a50785e34..6fe67c5d1ae0 100644
--- a/arch/arm/mach-msm/devices-qsd8x50.c
+++ b/arch/arm/mach-msm/devices-qsd8x50.c
@@ -48,6 +48,11 @@ struct platform_device msm_device_uart3 = {
.resource = resources_uart3,
};
+struct platform_device msm_device_smd = {
+ .name = "msm_smd",
+ .id = -1,
+};
+
struct clk msm_clocks_8x50[] = {
CLK_PCOM("adm_clk", ADM_CLK, NULL, 0),
CLK_PCOM("ebi1_clk", EBI1_CLK, NULL, CLK_MIN),
diff --git a/arch/arm/mach-msm/gpio.c b/arch/arm/mach-msm/gpio.c
index bc32c845c7b0..33051b509e88 100644
--- a/arch/arm/mach-msm/gpio.c
+++ b/arch/arm/mach-msm/gpio.c
@@ -1,7 +1,7 @@
/* linux/arch/arm/mach-msm/gpio.c
*
* Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -14,72 +14,363 @@
*
*/
+#include <linux/bitops.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
#include <linux/module.h>
-#include <mach/gpio.h>
-#include "proc_comm.h"
-
-int gpio_tlmm_config(unsigned config, unsigned disable)
-{
- return msm_proc_comm(PCOM_RPC_GPIO_TLMM_CONFIG_EX, &config, &disable);
-}
-EXPORT_SYMBOL(gpio_tlmm_config);
-
-int msm_gpios_enable(const struct msm_gpio *table, int size)
-{
- int rc;
- int i;
- const struct msm_gpio *g;
- for (i = 0; i < size; i++) {
- g = table + i;
- rc = gpio_tlmm_config(g->gpio_cfg, GPIO_ENABLE);
- if (rc) {
- pr_err("gpio_tlmm_config(0x%08x, GPIO_ENABLE)"
- " <%s> failed: %d\n",
- g->gpio_cfg, g->label ?: "?", rc);
- pr_err("pin %d func %d dir %d pull %d drvstr %d\n",
- GPIO_PIN(g->gpio_cfg), GPIO_FUNC(g->gpio_cfg),
- GPIO_DIR(g->gpio_cfg), GPIO_PULL(g->gpio_cfg),
- GPIO_DRVSTR(g->gpio_cfg));
- goto err;
- }
+#include "gpio_hw.h"
+#include "gpiomux.h"
+
+#define FIRST_GPIO_IRQ MSM_GPIO_TO_INT(0)
+
+#define MSM_GPIO_BANK(bank, first, last) \
+ { \
+ .regs = { \
+ .out = MSM_GPIO_OUT_##bank, \
+ .in = MSM_GPIO_IN_##bank, \
+ .int_status = MSM_GPIO_INT_STATUS_##bank, \
+ .int_clear = MSM_GPIO_INT_CLEAR_##bank, \
+ .int_en = MSM_GPIO_INT_EN_##bank, \
+ .int_edge = MSM_GPIO_INT_EDGE_##bank, \
+ .int_pos = MSM_GPIO_INT_POS_##bank, \
+ .oe = MSM_GPIO_OE_##bank, \
+ }, \
+ .chip = { \
+ .base = (first), \
+ .ngpio = (last) - (first) + 1, \
+ .get = msm_gpio_get, \
+ .set = msm_gpio_set, \
+ .direction_input = msm_gpio_direction_input, \
+ .direction_output = msm_gpio_direction_output, \
+ .to_irq = msm_gpio_to_irq, \
+ .request = msm_gpio_request, \
+ .free = msm_gpio_free, \
+ } \
}
+
+#define MSM_GPIO_BROKEN_INT_CLEAR 1
+
+struct msm_gpio_regs {
+ void __iomem *out;
+ void __iomem *in;
+ void __iomem *int_status;
+ void __iomem *int_clear;
+ void __iomem *int_en;
+ void __iomem *int_edge;
+ void __iomem *int_pos;
+ void __iomem *oe;
+};
+
+struct msm_gpio_chip {
+ spinlock_t lock;
+ struct gpio_chip chip;
+ struct msm_gpio_regs regs;
+#if MSM_GPIO_BROKEN_INT_CLEAR
+ unsigned int_status_copy;
+#endif
+ unsigned int both_edge_detect;
+ unsigned int int_enable[2]; /* 0: awake, 1: sleep */
+};
+
+static int msm_gpio_write(struct msm_gpio_chip *msm_chip,
+ unsigned offset, unsigned on)
+{
+ unsigned mask = BIT(offset);
+ unsigned val;
+
+ val = readl(msm_chip->regs.out);
+ if (on)
+ writel(val | mask, msm_chip->regs.out);
+ else
+ writel(val & ~mask, msm_chip->regs.out);
return 0;
-err:
- msm_gpios_disable(table, i);
- return rc;
-}
-EXPORT_SYMBOL(msm_gpios_enable);
-
-void msm_gpios_disable(const struct msm_gpio *table, int size)
-{
- int rc;
- int i;
- const struct msm_gpio *g;
- for (i = size-1; i >= 0; i--) {
- g = table + i;
- rc = gpio_tlmm_config(g->gpio_cfg, GPIO_DISABLE);
- if (rc) {
- pr_err("gpio_tlmm_config(0x%08x, GPIO_DISABLE)"
- " <%s> failed: %d\n",
- g->gpio_cfg, g->label ?: "?", rc);
- pr_err("pin %d func %d dir %d pull %d drvstr %d\n",
- GPIO_PIN(g->gpio_cfg), GPIO_FUNC(g->gpio_cfg),
- GPIO_DIR(g->gpio_cfg), GPIO_PULL(g->gpio_cfg),
- GPIO_DRVSTR(g->gpio_cfg));
- }
+}
+
+static void msm_gpio_update_both_edge_detect(struct msm_gpio_chip *msm_chip)
+{
+ int loop_limit = 100;
+ unsigned pol, val, val2, intstat;
+ do {
+ val = readl(msm_chip->regs.in);
+ pol = readl(msm_chip->regs.int_pos);
+ pol = (pol & ~msm_chip->both_edge_detect) |
+ (~val & msm_chip->both_edge_detect);
+ writel(pol, msm_chip->regs.int_pos);
+ intstat = readl(msm_chip->regs.int_status);
+ val2 = readl(msm_chip->regs.in);
+ if (((val ^ val2) & msm_chip->both_edge_detect & ~intstat) == 0)
+ return;
+ } while (loop_limit-- > 0);
+ printk(KERN_ERR "msm_gpio_update_both_edge_detect, "
+ "failed to reach stable state %x != %x\n", val, val2);
+}
+
+static int msm_gpio_clear_detect_status(struct msm_gpio_chip *msm_chip,
+ unsigned offset)
+{
+ unsigned bit = BIT(offset);
+
+#if MSM_GPIO_BROKEN_INT_CLEAR
+ /* Save interrupts that already triggered before we loose them. */
+ /* Any interrupt that triggers between the read of int_status */
+ /* and the write to int_clear will still be lost though. */
+ msm_chip->int_status_copy |= readl(msm_chip->regs.int_status);
+ msm_chip->int_status_copy &= ~bit;
+#endif
+ writel(bit, msm_chip->regs.int_clear);
+ msm_gpio_update_both_edge_detect(msm_chip);
+ return 0;
+}
+
+static int msm_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+ struct msm_gpio_chip *msm_chip;
+ unsigned long irq_flags;
+
+ msm_chip = container_of(chip, struct msm_gpio_chip, chip);
+ spin_lock_irqsave(&msm_chip->lock, irq_flags);
+ writel(readl(msm_chip->regs.oe) & ~BIT(offset), msm_chip->regs.oe);
+ spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
+ return 0;
+}
+
+static int
+msm_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value)
+{
+ struct msm_gpio_chip *msm_chip;
+ unsigned long irq_flags;
+
+ msm_chip = container_of(chip, struct msm_gpio_chip, chip);
+ spin_lock_irqsave(&msm_chip->lock, irq_flags);
+ msm_gpio_write(msm_chip, offset, value);
+ writel(readl(msm_chip->regs.oe) | BIT(offset), msm_chip->regs.oe);
+ spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
+ return 0;
+}
+
+static int msm_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+ struct msm_gpio_chip *msm_chip;
+
+ msm_chip = container_of(chip, struct msm_gpio_chip, chip);
+ return (readl(msm_chip->regs.in) & (1U << offset)) ? 1 : 0;
+}
+
+static void msm_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+ struct msm_gpio_chip *msm_chip;
+ unsigned long irq_flags;
+
+ msm_chip = container_of(chip, struct msm_gpio_chip, chip);
+ spin_lock_irqsave(&msm_chip->lock, irq_flags);
+ msm_gpio_write(msm_chip, offset, value);
+ spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
+}
+
+static int msm_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+ return MSM_GPIO_TO_INT(chip->base + offset);
+}
+
+#ifdef CONFIG_MSM_GPIOMUX
+static int msm_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+ return msm_gpiomux_get(chip->base + offset);
+}
+
+static void msm_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+ msm_gpiomux_put(chip->base + offset);
+}
+#else
+#define msm_gpio_request NULL
+#define msm_gpio_free NULL
+#endif
+
+struct msm_gpio_chip msm_gpio_chips[] = {
+#if defined(CONFIG_ARCH_MSM7X00A)
+ MSM_GPIO_BANK(0, 0, 15),
+ MSM_GPIO_BANK(1, 16, 42),
+ MSM_GPIO_BANK(2, 43, 67),
+ MSM_GPIO_BANK(3, 68, 94),
+ MSM_GPIO_BANK(4, 95, 106),
+ MSM_GPIO_BANK(5, 107, 121),
+#elif defined(CONFIG_ARCH_MSM7X25) || defined(CONFIG_ARCH_MSM7X27)
+ MSM_GPIO_BANK(0, 0, 15),
+ MSM_GPIO_BANK(1, 16, 42),
+ MSM_GPIO_BANK(2, 43, 67),
+ MSM_GPIO_BANK(3, 68, 94),
+ MSM_GPIO_BANK(4, 95, 106),
+ MSM_GPIO_BANK(5, 107, 132),
+#elif defined(CONFIG_ARCH_MSM7X30)
+ MSM_GPIO_BANK(0, 0, 15),
+ MSM_GPIO_BANK(1, 16, 43),
+ MSM_GPIO_BANK(2, 44, 67),
+ MSM_GPIO_BANK(3, 68, 94),
+ MSM_GPIO_BANK(4, 95, 106),
+ MSM_GPIO_BANK(5, 107, 133),
+ MSM_GPIO_BANK(6, 134, 150),
+ MSM_GPIO_BANK(7, 151, 181),
+#elif defined(CONFIG_ARCH_QSD8X50)
+ MSM_GPIO_BANK(0, 0, 15),
+ MSM_GPIO_BANK(1, 16, 42),
+ MSM_GPIO_BANK(2, 43, 67),
+ MSM_GPIO_BANK(3, 68, 94),
+ MSM_GPIO_BANK(4, 95, 103),
+ MSM_GPIO_BANK(5, 104, 121),
+ MSM_GPIO_BANK(6, 122, 152),
+ MSM_GPIO_BANK(7, 153, 164),
+#endif
+};
+
+static void msm_gpio_irq_ack(unsigned int irq)
+{
+ unsigned long irq_flags;
+ struct msm_gpio_chip *msm_chip = get_irq_chip_data(irq);
+ spin_lock_irqsave(&msm_chip->lock, irq_flags);
+ msm_gpio_clear_detect_status(msm_chip,
+ irq - gpio_to_irq(msm_chip->chip.base));
+ spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
+}
+
+static void msm_gpio_irq_mask(unsigned int irq)
+{
+ unsigned long irq_flags;
+ struct msm_gpio_chip *msm_chip = get_irq_chip_data(irq);
+ unsigned offset = irq - gpio_to_irq(msm_chip->chip.base);
+
+ spin_lock_irqsave(&msm_chip->lock, irq_flags);
+ /* level triggered interrupts are also latched */
+ if (!(readl(msm_chip->regs.int_edge) & BIT(offset)))
+ msm_gpio_clear_detect_status(msm_chip, offset);
+ msm_chip->int_enable[0] &= ~BIT(offset);
+ writel(msm_chip->int_enable[0], msm_chip->regs.int_en);
+ spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
+}
+
+static void msm_gpio_irq_unmask(unsigned int irq)
+{
+ unsigned long irq_flags;
+ struct msm_gpio_chip *msm_chip = get_irq_chip_data(irq);
+ unsigned offset = irq - gpio_to_irq(msm_chip->chip.base);
+
+ spin_lock_irqsave(&msm_chip->lock, irq_flags);
+ /* level triggered interrupts are also latched */
+ if (!(readl(msm_chip->regs.int_edge) & BIT(offset)))
+ msm_gpio_clear_detect_status(msm_chip, offset);
+ msm_chip->int_enable[0] |= BIT(offset);
+ writel(msm_chip->int_enable[0], msm_chip->regs.int_en);
+ spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
+}
+
+static int msm_gpio_irq_set_wake(unsigned int irq, unsigned int on)
+{
+ unsigned long irq_flags;
+ struct msm_gpio_chip *msm_chip = get_irq_chip_data(irq);
+ unsigned offset = irq - gpio_to_irq(msm_chip->chip.base);
+
+ spin_lock_irqsave(&msm_chip->lock, irq_flags);
+
+ if (on)
+ msm_chip->int_enable[1] |= BIT(offset);
+ else
+ msm_chip->int_enable[1] &= ~BIT(offset);
+
+ spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
+ return 0;
+}
+
+static int msm_gpio_irq_set_type(unsigned int irq, unsigned int flow_type)
+{
+ unsigned long irq_flags;
+ struct msm_gpio_chip *msm_chip = get_irq_chip_data(irq);
+ unsigned offset = irq - gpio_to_irq(msm_chip->chip.base);
+ unsigned val, mask = BIT(offset);
+
+ spin_lock_irqsave(&msm_chip->lock, irq_flags);
+ val = readl(msm_chip->regs.int_edge);
+ if (flow_type & IRQ_TYPE_EDGE_BOTH) {
+ writel(val | mask, msm_chip->regs.int_edge);
+ irq_desc[irq].handle_irq = handle_edge_irq;
+ } else {
+ writel(val & ~mask, msm_chip->regs.int_edge);
+ irq_desc[irq].handle_irq = handle_level_irq;
+ }
+ if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) {
+ msm_chip->both_edge_detect |= mask;
+ msm_gpio_update_both_edge_detect(msm_chip);
+ } else {
+ msm_chip->both_edge_detect &= ~mask;
+ val = readl(msm_chip->regs.int_pos);
+ if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_HIGH))
+ writel(val | mask, msm_chip->regs.int_pos);
+ else
+ writel(val & ~mask, msm_chip->regs.int_pos);
}
+ spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
+ return 0;
}
-EXPORT_SYMBOL(msm_gpios_disable);
-int msm_gpios_request_enable(const struct msm_gpio *table, int size)
+static void msm_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
{
- int rc = msm_gpios_enable(table, size);
- return rc;
+ int i, j, mask;
+ unsigned val;
+
+ for (i = 0; i < ARRAY_SIZE(msm_gpio_chips); i++) {
+ struct msm_gpio_chip *msm_chip = &msm_gpio_chips[i];
+ val = readl(msm_chip->regs.int_status);
+ val &= msm_chip->int_enable[0];
+ while (val) {
+ mask = val & -val;
+ j = fls(mask) - 1;
+ /* printk("%s %08x %08x bit %d gpio %d irq %d\n",
+ __func__, v, m, j, msm_chip->chip.start + j,
+ FIRST_GPIO_IRQ + msm_chip->chip.start + j); */
+ val &= ~mask;
+ generic_handle_irq(FIRST_GPIO_IRQ +
+ msm_chip->chip.base + j);
+ }
+ }
+ desc->chip->ack(irq);
}
-EXPORT_SYMBOL(msm_gpios_request_enable);
-void msm_gpios_disable_free(const struct msm_gpio *table, int size)
+static struct irq_chip msm_gpio_irq_chip = {
+ .name = "msmgpio",
+ .ack = msm_gpio_irq_ack,
+ .mask = msm_gpio_irq_mask,
+ .unmask = msm_gpio_irq_unmask,
+ .set_wake = msm_gpio_irq_set_wake,
+ .set_type = msm_gpio_irq_set_type,
+};
+
+static int __init msm_init_gpio(void)
{
- msm_gpios_disable(table, size);
+ int i, j = 0;
+
+ for (i = FIRST_GPIO_IRQ; i < FIRST_GPIO_IRQ + NR_GPIO_IRQS; i++) {
+ if (i - FIRST_GPIO_IRQ >=
+ msm_gpio_chips[j].chip.base +
+ msm_gpio_chips[j].chip.ngpio)
+ j++;
+ set_irq_chip_data(i, &msm_gpio_chips[j]);
+ set_irq_chip(i, &msm_gpio_irq_chip);
+ set_irq_handler(i, handle_edge_irq);
+ set_irq_flags(i, IRQF_VALID);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(msm_gpio_chips); i++) {
+ spin_lock_init(&msm_gpio_chips[i].lock);
+ writel(0, msm_gpio_chips[i].regs.int_en);
+ gpiochip_add(&msm_gpio_chips[i].chip);
+ }
+
+ set_irq_chained_handler(INT_GPIO_GROUP1, msm_gpio_irq_handler);
+ set_irq_chained_handler(INT_GPIO_GROUP2, msm_gpio_irq_handler);
+ set_irq_wake(INT_GPIO_GROUP1, 1);
+ set_irq_wake(INT_GPIO_GROUP2, 2);
+ return 0;
}
-EXPORT_SYMBOL(msm_gpios_disable_free);
+
+postcore_initcall(msm_init_gpio);
diff --git a/arch/arm/mach-msm/gpio_hw.h b/arch/arm/mach-msm/gpio_hw.h
new file mode 100644
index 000000000000..6b5066038baa
--- /dev/null
+++ b/arch/arm/mach-msm/gpio_hw.h
@@ -0,0 +1,278 @@
+/* arch/arm/mach-msm/gpio_hw.h
+ *
+ * Copyright (C) 2007 Google, Inc.
+ * Author: Brian Swetland <swetland@google.com>
+ * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __ARCH_ARM_MACH_MSM_GPIO_HW_H
+#define __ARCH_ARM_MACH_MSM_GPIO_HW_H
+
+#include <mach/msm_iomap.h>
+
+/* see 80-VA736-2 Rev C pp 695-751
+**
+** These are actually the *shadow* gpio registers, since the
+** real ones (which allow full access) are only available to the
+** ARM9 side of the world.
+**
+** Since the _BASE need to be page-aligned when we're mapping them
+** to virtual addresses, adjust for the additional offset in these
+** macros.
+*/
+
+#if defined(CONFIG_ARCH_MSM7X30)
+#define MSM_GPIO1_REG(off) (MSM_GPIO1_BASE + (off))
+#define MSM_GPIO2_REG(off) (MSM_GPIO2_BASE + 0x400 + (off))
+#else
+#define MSM_GPIO1_REG(off) (MSM_GPIO1_BASE + 0x800 + (off))
+#define MSM_GPIO2_REG(off) (MSM_GPIO2_BASE + 0xC00 + (off))
+#endif
+
+#if defined(CONFIG_ARCH_MSM7X00A) || defined(CONFIG_ARCH_MSM7X25) ||\
+ defined(CONFIG_ARCH_MSM7X27)
+
+/* output value */
+#define MSM_GPIO_OUT_0 MSM_GPIO1_REG(0x00) /* gpio 15-0 */
+#define MSM_GPIO_OUT_1 MSM_GPIO2_REG(0x00) /* gpio 42-16 */
+#define MSM_GPIO_OUT_2 MSM_GPIO1_REG(0x04) /* gpio 67-43 */
+#define MSM_GPIO_OUT_3 MSM_GPIO1_REG(0x08) /* gpio 94-68 */
+#define MSM_GPIO_OUT_4 MSM_GPIO1_REG(0x0C) /* gpio 106-95 */
+#define MSM_GPIO_OUT_5 MSM_GPIO1_REG(0x50) /* gpio 107-121 */
+
+/* same pin map as above, output enable */
+#define MSM_GPIO_OE_0 MSM_GPIO1_REG(0x10)
+#define MSM_GPIO_OE_1 MSM_GPIO2_REG(0x08)
+#define MSM_GPIO_OE_2 MSM_GPIO1_REG(0x14)
+#define MSM_GPIO_OE_3 MSM_GPIO1_REG(0x18)
+#define MSM_GPIO_OE_4 MSM_GPIO1_REG(0x1C)
+#define MSM_GPIO_OE_5 MSM_GPIO1_REG(0x54)
+
+/* same pin map as above, input read */
+#define MSM_GPIO_IN_0 MSM_GPIO1_REG(0x34)
+#define MSM_GPIO_IN_1 MSM_GPIO2_REG(0x20)
+#define MSM_GPIO_IN_2 MSM_GPIO1_REG(0x38)
+#define MSM_GPIO_IN_3 MSM_GPIO1_REG(0x3C)
+#define MSM_GPIO_IN_4 MSM_GPIO1_REG(0x40)
+#define MSM_GPIO_IN_5 MSM_GPIO1_REG(0x44)
+
+/* same pin map as above, 1=edge 0=level interrup */
+#define MSM_GPIO_INT_EDGE_0 MSM_GPIO1_REG(0x60)
+#define MSM_GPIO_INT_EDGE_1 MSM_GPIO2_REG(0x50)
+#define MSM_GPIO_INT_EDGE_2 MSM_GPIO1_REG(0x64)
+#define MSM_GPIO_INT_EDGE_3 MSM_GPIO1_REG(0x68)
+#define MSM_GPIO_INT_EDGE_4 MSM_GPIO1_REG(0x6C)
+#define MSM_GPIO_INT_EDGE_5 MSM_GPIO1_REG(0xC0)
+
+/* same pin map as above, 1=positive 0=negative */
+#define MSM_GPIO_INT_POS_0 MSM_GPIO1_REG(0x70)
+#define MSM_GPIO_INT_POS_1 MSM_GPIO2_REG(0x58)
+#define MSM_GPIO_INT_POS_2 MSM_GPIO1_REG(0x74)
+#define MSM_GPIO_INT_POS_3 MSM_GPIO1_REG(0x78)
+#define MSM_GPIO_INT_POS_4 MSM_GPIO1_REG(0x7C)
+#define MSM_GPIO_INT_POS_5 MSM_GPIO1_REG(0xBC)
+
+/* same pin map as above, interrupt enable */
+#define MSM_GPIO_INT_EN_0 MSM_GPIO1_REG(0x80)
+#define MSM_GPIO_INT_EN_1 MSM_GPIO2_REG(0x60)
+#define MSM_GPIO_INT_EN_2 MSM_GPIO1_REG(0x84)
+#define MSM_GPIO_INT_EN_3 MSM_GPIO1_REG(0x88)
+#define MSM_GPIO_INT_EN_4 MSM_GPIO1_REG(0x8C)
+#define MSM_GPIO_INT_EN_5 MSM_GPIO1_REG(0xB8)
+
+/* same pin map as above, write 1 to clear interrupt */
+#define MSM_GPIO_INT_CLEAR_0 MSM_GPIO1_REG(0x90)
+#define MSM_GPIO_INT_CLEAR_1 MSM_GPIO2_REG(0x68)
+#define MSM_GPIO_INT_CLEAR_2 MSM_GPIO1_REG(0x94)
+#define MSM_GPIO_INT_CLEAR_3 MSM_GPIO1_REG(0x98)
+#define MSM_GPIO_INT_CLEAR_4 MSM_GPIO1_REG(0x9C)
+#define MSM_GPIO_INT_CLEAR_5 MSM_GPIO1_REG(0xB4)
+
+/* same pin map as above, 1=interrupt pending */
+#define MSM_GPIO_INT_STATUS_0 MSM_GPIO1_REG(0xA0)
+#define MSM_GPIO_INT_STATUS_1 MSM_GPIO2_REG(0x70)
+#define MSM_GPIO_INT_STATUS_2 MSM_GPIO1_REG(0xA4)
+#define MSM_GPIO_INT_STATUS_3 MSM_GPIO1_REG(0xA8)
+#define MSM_GPIO_INT_STATUS_4 MSM_GPIO1_REG(0xAC)
+#define MSM_GPIO_INT_STATUS_5 MSM_GPIO1_REG(0xB0)
+
+#endif
+
+#if defined(CONFIG_ARCH_QSD8X50)
+/* output value */
+#define MSM_GPIO_OUT_0 MSM_GPIO1_REG(0x00) /* gpio 15-0 */
+#define MSM_GPIO_OUT_1 MSM_GPIO2_REG(0x00) /* gpio 42-16 */
+#define MSM_GPIO_OUT_2 MSM_GPIO1_REG(0x04) /* gpio 67-43 */
+#define MSM_GPIO_OUT_3 MSM_GPIO1_REG(0x08) /* gpio 94-68 */
+#define MSM_GPIO_OUT_4 MSM_GPIO1_REG(0x0C) /* gpio 103-95 */
+#define MSM_GPIO_OUT_5 MSM_GPIO1_REG(0x10) /* gpio 121-104 */
+#define MSM_GPIO_OUT_6 MSM_GPIO1_REG(0x14) /* gpio 152-122 */
+#define MSM_GPIO_OUT_7 MSM_GPIO1_REG(0x18) /* gpio 164-153 */
+
+/* same pin map as above, output enable */
+#define MSM_GPIO_OE_0 MSM_GPIO1_REG(0x20)
+#define MSM_GPIO_OE_1 MSM_GPIO2_REG(0x08)
+#define MSM_GPIO_OE_2 MSM_GPIO1_REG(0x24)
+#define MSM_GPIO_OE_3 MSM_GPIO1_REG(0x28)
+#define MSM_GPIO_OE_4 MSM_GPIO1_REG(0x2C)
+#define MSM_GPIO_OE_5 MSM_GPIO1_REG(0x30)
+#define MSM_GPIO_OE_6 MSM_GPIO1_REG(0x34)
+#define MSM_GPIO_OE_7 MSM_GPIO1_REG(0x38)
+
+/* same pin map as above, input read */
+#define MSM_GPIO_IN_0 MSM_GPIO1_REG(0x50)
+#define MSM_GPIO_IN_1 MSM_GPIO2_REG(0x20)
+#define MSM_GPIO_IN_2 MSM_GPIO1_REG(0x54)
+#define MSM_GPIO_IN_3 MSM_GPIO1_REG(0x58)
+#define MSM_GPIO_IN_4 MSM_GPIO1_REG(0x5C)
+#define MSM_GPIO_IN_5 MSM_GPIO1_REG(0x60)
+#define MSM_GPIO_IN_6 MSM_GPIO1_REG(0x64)
+#define MSM_GPIO_IN_7 MSM_GPIO1_REG(0x68)
+
+/* same pin map as above, 1=edge 0=level interrup */
+#define MSM_GPIO_INT_EDGE_0 MSM_GPIO1_REG(0x70)
+#define MSM_GPIO_INT_EDGE_1 MSM_GPIO2_REG(0x50)
+#define MSM_GPIO_INT_EDGE_2 MSM_GPIO1_REG(0x74)
+#define MSM_GPIO_INT_EDGE_3 MSM_GPIO1_REG(0x78)
+#define MSM_GPIO_INT_EDGE_4 MSM_GPIO1_REG(0x7C)
+#define MSM_GPIO_INT_EDGE_5 MSM_GPIO1_REG(0x80)
+#define MSM_GPIO_INT_EDGE_6 MSM_GPIO1_REG(0x84)
+#define MSM_GPIO_INT_EDGE_7 MSM_GPIO1_REG(0x88)
+
+/* same pin map as above, 1=positive 0=negative */
+#define MSM_GPIO_INT_POS_0 MSM_GPIO1_REG(0x90)
+#define MSM_GPIO_INT_POS_1 MSM_GPIO2_REG(0x58)
+#define MSM_GPIO_INT_POS_2 MSM_GPIO1_REG(0x94)
+#define MSM_GPIO_INT_POS_3 MSM_GPIO1_REG(0x98)
+#define MSM_GPIO_INT_POS_4 MSM_GPIO1_REG(0x9C)
+#define MSM_GPIO_INT_POS_5 MSM_GPIO1_REG(0xA0)
+#define MSM_GPIO_INT_POS_6 MSM_GPIO1_REG(0xA4)
+#define MSM_GPIO_INT_POS_7 MSM_GPIO1_REG(0xA8)
+
+/* same pin map as above, interrupt enable */
+#define MSM_GPIO_INT_EN_0 MSM_GPIO1_REG(0xB0)
+#define MSM_GPIO_INT_EN_1 MSM_GPIO2_REG(0x60)
+#define MSM_GPIO_INT_EN_2 MSM_GPIO1_REG(0xB4)
+#define MSM_GPIO_INT_EN_3 MSM_GPIO1_REG(0xB8)
+#define MSM_GPIO_INT_EN_4 MSM_GPIO1_REG(0xBC)
+#define MSM_GPIO_INT_EN_5 MSM_GPIO1_REG(0xC0)
+#define MSM_GPIO_INT_EN_6 MSM_GPIO1_REG(0xC4)
+#define MSM_GPIO_INT_EN_7 MSM_GPIO1_REG(0xC8)
+
+/* same pin map as above, write 1 to clear interrupt */
+#define MSM_GPIO_INT_CLEAR_0 MSM_GPIO1_REG(0xD0)
+#define MSM_GPIO_INT_CLEAR_1 MSM_GPIO2_REG(0x68)
+#define MSM_GPIO_INT_CLEAR_2 MSM_GPIO1_REG(0xD4)
+#define MSM_GPIO_INT_CLEAR_3 MSM_GPIO1_REG(0xD8)
+#define MSM_GPIO_INT_CLEAR_4 MSM_GPIO1_REG(0xDC)
+#define MSM_GPIO_INT_CLEAR_5 MSM_GPIO1_REG(0xE0)
+#define MSM_GPIO_INT_CLEAR_6 MSM_GPIO1_REG(0xE4)
+#define MSM_GPIO_INT_CLEAR_7 MSM_GPIO1_REG(0xE8)
+
+/* same pin map as above, 1=interrupt pending */
+#define MSM_GPIO_INT_STATUS_0 MSM_GPIO1_REG(0xF0)
+#define MSM_GPIO_INT_STATUS_1 MSM_GPIO2_REG(0x70)
+#define MSM_GPIO_INT_STATUS_2 MSM_GPIO1_REG(0xF4)
+#define MSM_GPIO_INT_STATUS_3 MSM_GPIO1_REG(0xF8)
+#define MSM_GPIO_INT_STATUS_4 MSM_GPIO1_REG(0xFC)
+#define MSM_GPIO_INT_STATUS_5 MSM_GPIO1_REG(0x100)
+#define MSM_GPIO_INT_STATUS_6 MSM_GPIO1_REG(0x104)
+#define MSM_GPIO_INT_STATUS_7 MSM_GPIO1_REG(0x108)
+
+#endif
+
+#if defined(CONFIG_ARCH_MSM7X30)
+
+/* output value */
+#define MSM_GPIO_OUT_0 MSM_GPIO1_REG(0x00) /* gpio 15-0 */
+#define MSM_GPIO_OUT_1 MSM_GPIO2_REG(0x00) /* gpio 43-16 */
+#define MSM_GPIO_OUT_2 MSM_GPIO1_REG(0x04) /* gpio 67-44 */
+#define MSM_GPIO_OUT_3 MSM_GPIO1_REG(0x08) /* gpio 94-68 */
+#define MSM_GPIO_OUT_4 MSM_GPIO1_REG(0x0C) /* gpio 106-95 */
+#define MSM_GPIO_OUT_5 MSM_GPIO1_REG(0x50) /* gpio 133-107 */
+#define MSM_GPIO_OUT_6 MSM_GPIO1_REG(0xC4) /* gpio 150-134 */
+#define MSM_GPIO_OUT_7 MSM_GPIO1_REG(0x214) /* gpio 181-151 */
+
+/* same pin map as above, output enable */
+#define MSM_GPIO_OE_0 MSM_GPIO1_REG(0x10)
+#define MSM_GPIO_OE_1 MSM_GPIO2_REG(0x08)
+#define MSM_GPIO_OE_2 MSM_GPIO1_REG(0x14)
+#define MSM_GPIO_OE_3 MSM_GPIO1_REG(0x18)
+#define MSM_GPIO_OE_4 MSM_GPIO1_REG(0x1C)
+#define MSM_GPIO_OE_5 MSM_GPIO1_REG(0x54)
+#define MSM_GPIO_OE_6 MSM_GPIO1_REG(0xC8)
+#define MSM_GPIO_OE_7 MSM_GPIO1_REG(0x218)
+
+/* same pin map as above, input read */
+#define MSM_GPIO_IN_0 MSM_GPIO1_REG(0x34)
+#define MSM_GPIO_IN_1 MSM_GPIO2_REG(0x20)
+#define MSM_GPIO_IN_2 MSM_GPIO1_REG(0x38)
+#define MSM_GPIO_IN_3 MSM_GPIO1_REG(0x3C)
+#define MSM_GPIO_IN_4 MSM_GPIO1_REG(0x40)
+#define MSM_GPIO_IN_5 MSM_GPIO1_REG(0x44)
+#define MSM_GPIO_IN_6 MSM_GPIO1_REG(0xCC)
+#define MSM_GPIO_IN_7 MSM_GPIO1_REG(0x21C)
+
+/* same pin map as above, 1=edge 0=level interrup */
+#define MSM_GPIO_INT_EDGE_0 MSM_GPIO1_REG(0x60)
+#define MSM_GPIO_INT_EDGE_1 MSM_GPIO2_REG(0x50)
+#define MSM_GPIO_INT_EDGE_2 MSM_GPIO1_REG(0x64)
+#define MSM_GPIO_INT_EDGE_3 MSM_GPIO1_REG(0x68)
+#define MSM_GPIO_INT_EDGE_4 MSM_GPIO1_REG(0x6C)
+#define MSM_GPIO_INT_EDGE_5 MSM_GPIO1_REG(0xC0)
+#define MSM_GPIO_INT_EDGE_6 MSM_GPIO1_REG(0xD0)
+#define MSM_GPIO_INT_EDGE_7 MSM_GPIO1_REG(0x240)
+
+/* same pin map as above, 1=positive 0=negative */
+#define MSM_GPIO_INT_POS_0 MSM_GPIO1_REG(0x70)
+#define MSM_GPIO_INT_POS_1 MSM_GPIO2_REG(0x58)
+#define MSM_GPIO_INT_POS_2 MSM_GPIO1_REG(0x74)
+#define MSM_GPIO_INT_POS_3 MSM_GPIO1_REG(0x78)
+#define MSM_GPIO_INT_POS_4 MSM_GPIO1_REG(0x7C)
+#define MSM_GPIO_INT_POS_5 MSM_GPIO1_REG(0xBC)
+#define MSM_GPIO_INT_POS_6 MSM_GPIO1_REG(0xD4)
+#define MSM_GPIO_INT_POS_7 MSM_GPIO1_REG(0x228)
+
+/* same pin map as above, interrupt enable */
+#define MSM_GPIO_INT_EN_0 MSM_GPIO1_REG(0x80)
+#define MSM_GPIO_INT_EN_1 MSM_GPIO2_REG(0x60)
+#define MSM_GPIO_INT_EN_2 MSM_GPIO1_REG(0x84)
+#define MSM_GPIO_INT_EN_3 MSM_GPIO1_REG(0x88)
+#define MSM_GPIO_INT_EN_4 MSM_GPIO1_REG(0x8C)
+#define MSM_GPIO_INT_EN_5 MSM_GPIO1_REG(0xB8)
+#define MSM_GPIO_INT_EN_6 MSM_GPIO1_REG(0xD8)
+#define MSM_GPIO_INT_EN_7 MSM_GPIO1_REG(0x22C)
+
+/* same pin map as above, write 1 to clear interrupt */
+#define MSM_GPIO_INT_CLEAR_0 MSM_GPIO1_REG(0x90)
+#define MSM_GPIO_INT_CLEAR_1 MSM_GPIO2_REG(0x68)
+#define MSM_GPIO_INT_CLEAR_2 MSM_GPIO1_REG(0x94)
+#define MSM_GPIO_INT_CLEAR_3 MSM_GPIO1_REG(0x98)
+#define MSM_GPIO_INT_CLEAR_4 MSM_GPIO1_REG(0x9C)
+#define MSM_GPIO_INT_CLEAR_5 MSM_GPIO1_REG(0xB4)
+#define MSM_GPIO_INT_CLEAR_6 MSM_GPIO1_REG(0xDC)
+#define MSM_GPIO_INT_CLEAR_7 MSM_GPIO1_REG(0x230)
+
+/* same pin map as above, 1=interrupt pending */
+#define MSM_GPIO_INT_STATUS_0 MSM_GPIO1_REG(0xA0)
+#define MSM_GPIO_INT_STATUS_1 MSM_GPIO2_REG(0x70)
+#define MSM_GPIO_INT_STATUS_2 MSM_GPIO1_REG(0xA4)
+#define MSM_GPIO_INT_STATUS_3 MSM_GPIO1_REG(0xA8)
+#define MSM_GPIO_INT_STATUS_4 MSM_GPIO1_REG(0xAC)
+#define MSM_GPIO_INT_STATUS_5 MSM_GPIO1_REG(0xB0)
+#define MSM_GPIO_INT_STATUS_6 MSM_GPIO1_REG(0xE0)
+#define MSM_GPIO_INT_STATUS_7 MSM_GPIO1_REG(0x234)
+
+#endif
+
+#endif
diff --git a/arch/arm/mach-msm/gpiomux-7x30.c b/arch/arm/mach-msm/gpiomux-7x30.c
new file mode 100644
index 000000000000..6ce41c5241a5
--- /dev/null
+++ b/arch/arm/mach-msm/gpiomux-7x30.c
@@ -0,0 +1,38 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+#include "gpiomux.h"
+
+struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = {
+#ifdef CONFIG_SERIAL_MSM_CONSOLE
+ [49] = { /* UART2 RFR */
+ .suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
+ GPIOMUX_FUNC_2 | GPIOMUX_VALID,
+ },
+ [50] = { /* UART2 CTS */
+ .suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
+ GPIOMUX_FUNC_2 | GPIOMUX_VALID,
+ },
+ [51] = { /* UART2 RX */
+ .suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
+ GPIOMUX_FUNC_2 | GPIOMUX_VALID,
+ },
+ [52] = { /* UART2 TX */
+ .suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
+ GPIOMUX_FUNC_2 | GPIOMUX_VALID,
+ },
+#endif
+};
diff --git a/arch/arm/mach-msm/gpiomux-8x50.c b/arch/arm/mach-msm/gpiomux-8x50.c
new file mode 100644
index 000000000000..4406e0f4ae95
--- /dev/null
+++ b/arch/arm/mach-msm/gpiomux-8x50.c
@@ -0,0 +1,28 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+#include "gpiomux.h"
+
+struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = {
+ [86] = { /* UART3 RX */
+ .suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
+ GPIOMUX_FUNC_1 | GPIOMUX_VALID,
+ },
+ [87] = { /* UART3 TX */
+ .suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
+ GPIOMUX_FUNC_1 | GPIOMUX_VALID,
+ },
+};
diff --git a/arch/arm/mach-msm/gpiomux-8x60.c b/arch/arm/mach-msm/gpiomux-8x60.c
new file mode 100644
index 000000000000..7b380b31bd0e
--- /dev/null
+++ b/arch/arm/mach-msm/gpiomux-8x60.c
@@ -0,0 +1,19 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+#include "gpiomux.h"
+
+struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = {};
diff --git a/arch/arm/mach-msm/gpiomux-v1.c b/arch/arm/mach-msm/gpiomux-v1.c
new file mode 100644
index 000000000000..27de2abd7144
--- /dev/null
+++ b/arch/arm/mach-msm/gpiomux-v1.c
@@ -0,0 +1,33 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+#include <linux/kernel.h>
+#include "gpiomux.h"
+#include "proc_comm.h"
+
+void __msm_gpiomux_write(unsigned gpio, gpiomux_config_t val)
+{
+ unsigned tlmm_config = (val & ~GPIOMUX_CTL_MASK) |
+ ((gpio & 0x3ff) << 4);
+ unsigned tlmm_disable = 0;
+ int rc;
+
+ rc = msm_proc_comm(PCOM_RPC_GPIO_TLMM_CONFIG_EX,
+ &tlmm_config, &tlmm_disable);
+ if (rc)
+ pr_err("%s: unexpected proc_comm failure %d: %08x %08x\n",
+ __func__, rc, tlmm_config, tlmm_disable);
+}
diff --git a/arch/arm/mach-msm/gpiomux-v1.h b/arch/arm/mach-msm/gpiomux-v1.h
new file mode 100644
index 000000000000..71d86feba450
--- /dev/null
+++ b/arch/arm/mach-msm/gpiomux-v1.h
@@ -0,0 +1,67 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+#ifndef __ARCH_ARM_MACH_MSM_GPIOMUX_V1_H
+#define __ARCH_ARM_MACH_MSM_GPIOMUX_V1_H
+
+#if defined(CONFIG_ARCH_MSM7X30)
+#define GPIOMUX_NGPIOS 182
+#elif defined(CONFIG_ARCH_QSD8X50)
+#define GPIOMUX_NGPIOS 165
+#else
+#define GPIOMUX_NGPIOS 133
+#endif
+
+typedef u32 gpiomux_config_t;
+
+enum {
+ GPIOMUX_DRV_2MA = 0UL << 17,
+ GPIOMUX_DRV_4MA = 1UL << 17,
+ GPIOMUX_DRV_6MA = 2UL << 17,
+ GPIOMUX_DRV_8MA = 3UL << 17,
+ GPIOMUX_DRV_10MA = 4UL << 17,
+ GPIOMUX_DRV_12MA = 5UL << 17,
+ GPIOMUX_DRV_14MA = 6UL << 17,
+ GPIOMUX_DRV_16MA = 7UL << 17,
+};
+
+enum {
+ GPIOMUX_FUNC_GPIO = 0UL,
+ GPIOMUX_FUNC_1 = 1UL,
+ GPIOMUX_FUNC_2 = 2UL,
+ GPIOMUX_FUNC_3 = 3UL,
+ GPIOMUX_FUNC_4 = 4UL,
+ GPIOMUX_FUNC_5 = 5UL,
+ GPIOMUX_FUNC_6 = 6UL,
+ GPIOMUX_FUNC_7 = 7UL,
+ GPIOMUX_FUNC_8 = 8UL,
+ GPIOMUX_FUNC_9 = 9UL,
+ GPIOMUX_FUNC_A = 10UL,
+ GPIOMUX_FUNC_B = 11UL,
+ GPIOMUX_FUNC_C = 12UL,
+ GPIOMUX_FUNC_D = 13UL,
+ GPIOMUX_FUNC_E = 14UL,
+ GPIOMUX_FUNC_F = 15UL,
+};
+
+enum {
+ GPIOMUX_PULL_NONE = 0UL << 15,
+ GPIOMUX_PULL_DOWN = 1UL << 15,
+ GPIOMUX_PULL_KEEPER = 2UL << 15,
+ GPIOMUX_PULL_UP = 3UL << 15,
+};
+
+#endif
diff --git a/arch/arm/mach-msm/gpiomux-v2.c b/arch/arm/mach-msm/gpiomux-v2.c
new file mode 100644
index 000000000000..273396d2b127
--- /dev/null
+++ b/arch/arm/mach-msm/gpiomux-v2.c
@@ -0,0 +1,25 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+#include <linux/io.h>
+#include <mach/msm_iomap.h>
+#include "gpiomux.h"
+
+void __msm_gpiomux_write(unsigned gpio, gpiomux_config_t val)
+{
+ writel(val & ~GPIOMUX_CTL_MASK,
+ MSM_TLMM_BASE + 0x1000 + (0x10 * gpio));
+}
diff --git a/arch/arm/mach-msm/gpiomux-v2.h b/arch/arm/mach-msm/gpiomux-v2.h
new file mode 100644
index 000000000000..3bf10e7f0381
--- /dev/null
+++ b/arch/arm/mach-msm/gpiomux-v2.h
@@ -0,0 +1,61 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+#ifndef __ARCH_ARM_MACH_MSM_GPIOMUX_V2_H
+#define __ARCH_ARM_MACH_MSM_GPIOMUX_V2_H
+
+#define GPIOMUX_NGPIOS 173
+
+typedef u16 gpiomux_config_t;
+
+enum {
+ GPIOMUX_DRV_2MA = 0UL << 6,
+ GPIOMUX_DRV_4MA = 1UL << 6,
+ GPIOMUX_DRV_6MA = 2UL << 6,
+ GPIOMUX_DRV_8MA = 3UL << 6,
+ GPIOMUX_DRV_10MA = 4UL << 6,
+ GPIOMUX_DRV_12MA = 5UL << 6,
+ GPIOMUX_DRV_14MA = 6UL << 6,
+ GPIOMUX_DRV_16MA = 7UL << 6,
+};
+
+enum {
+ GPIOMUX_FUNC_GPIO = 0UL << 2,
+ GPIOMUX_FUNC_1 = 1UL << 2,
+ GPIOMUX_FUNC_2 = 2UL << 2,
+ GPIOMUX_FUNC_3 = 3UL << 2,
+ GPIOMUX_FUNC_4 = 4UL << 2,
+ GPIOMUX_FUNC_5 = 5UL << 2,
+ GPIOMUX_FUNC_6 = 6UL << 2,
+ GPIOMUX_FUNC_7 = 7UL << 2,
+ GPIOMUX_FUNC_8 = 8UL << 2,
+ GPIOMUX_FUNC_9 = 9UL << 2,
+ GPIOMUX_FUNC_A = 10UL << 2,
+ GPIOMUX_FUNC_B = 11UL << 2,
+ GPIOMUX_FUNC_C = 12UL << 2,
+ GPIOMUX_FUNC_D = 13UL << 2,
+ GPIOMUX_FUNC_E = 14UL << 2,
+ GPIOMUX_FUNC_F = 15UL << 2,
+};
+
+enum {
+ GPIOMUX_PULL_NONE = 0UL,
+ GPIOMUX_PULL_DOWN = 1UL,
+ GPIOMUX_PULL_KEEPER = 2UL,
+ GPIOMUX_PULL_UP = 3UL,
+};
+
+#endif
diff --git a/arch/arm/mach-msm/gpiomux.c b/arch/arm/mach-msm/gpiomux.c
new file mode 100644
index 000000000000..53af21abd155
--- /dev/null
+++ b/arch/arm/mach-msm/gpiomux.c
@@ -0,0 +1,96 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include "gpiomux.h"
+
+static DEFINE_SPINLOCK(gpiomux_lock);
+
+int msm_gpiomux_write(unsigned gpio,
+ gpiomux_config_t active,
+ gpiomux_config_t suspended)
+{
+ struct msm_gpiomux_config *cfg = msm_gpiomux_configs + gpio;
+ unsigned long irq_flags;
+ gpiomux_config_t setting;
+
+ if (gpio >= GPIOMUX_NGPIOS)
+ return -EINVAL;
+
+ spin_lock_irqsave(&gpiomux_lock, irq_flags);
+
+ if (active & GPIOMUX_VALID)
+ cfg->active = active;
+
+ if (suspended & GPIOMUX_VALID)
+ cfg->suspended = suspended;
+
+ setting = cfg->ref ? active : suspended;
+ if (setting & GPIOMUX_VALID)
+ __msm_gpiomux_write(gpio, setting);
+
+ spin_unlock_irqrestore(&gpiomux_lock, irq_flags);
+ return 0;
+}
+EXPORT_SYMBOL(msm_gpiomux_write);
+
+int msm_gpiomux_get(unsigned gpio)
+{
+ struct msm_gpiomux_config *cfg = msm_gpiomux_configs + gpio;
+ unsigned long irq_flags;
+
+ if (gpio >= GPIOMUX_NGPIOS)
+ return -EINVAL;
+
+ spin_lock_irqsave(&gpiomux_lock, irq_flags);
+ if (cfg->ref++ == 0 && cfg->active & GPIOMUX_VALID)
+ __msm_gpiomux_write(gpio, cfg->active);
+ spin_unlock_irqrestore(&gpiomux_lock, irq_flags);
+ return 0;
+}
+EXPORT_SYMBOL(msm_gpiomux_get);
+
+int msm_gpiomux_put(unsigned gpio)
+{
+ struct msm_gpiomux_config *cfg = msm_gpiomux_configs + gpio;
+ unsigned long irq_flags;
+
+ if (gpio >= GPIOMUX_NGPIOS)
+ return -EINVAL;
+
+ spin_lock_irqsave(&gpiomux_lock, irq_flags);
+ BUG_ON(cfg->ref == 0);
+ if (--cfg->ref == 0 && cfg->suspended & GPIOMUX_VALID)
+ __msm_gpiomux_write(gpio, cfg->suspended);
+ spin_unlock_irqrestore(&gpiomux_lock, irq_flags);
+ return 0;
+}
+EXPORT_SYMBOL(msm_gpiomux_put);
+
+static int __init gpiomux_init(void)
+{
+ unsigned n;
+
+ for (n = 0; n < GPIOMUX_NGPIOS; ++n) {
+ msm_gpiomux_configs[n].ref = 0;
+ if (!(msm_gpiomux_configs[n].suspended & GPIOMUX_VALID))
+ continue;
+ __msm_gpiomux_write(n, msm_gpiomux_configs[n].suspended);
+ }
+ return 0;
+}
+postcore_initcall(gpiomux_init);
diff --git a/arch/arm/mach-msm/gpiomux.h b/arch/arm/mach-msm/gpiomux.h
new file mode 100644
index 000000000000..b178d9cb742f
--- /dev/null
+++ b/arch/arm/mach-msm/gpiomux.h
@@ -0,0 +1,114 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+#ifndef __ARCH_ARM_MACH_MSM_GPIOMUX_H
+#define __ARCH_ARM_MACH_MSM_GPIOMUX_H
+
+#include <linux/bitops.h>
+#include <linux/errno.h>
+
+#if defined(CONFIG_MSM_V2_TLMM)
+#include "gpiomux-v2.h"
+#else
+#include "gpiomux-v1.h"
+#endif
+
+/**
+ * struct msm_gpiomux_config: gpiomux settings for one gpio line.
+ *
+ * A complete gpiomux config is the bitwise-or of a drive-strength,
+ * function, and pull. For functions other than GPIO, the OE
+ * is hard-wired according to the function. For GPIO mode,
+ * OE is controlled by gpiolib.
+ *
+ * Available settings differ by target; see the gpiomux header
+ * specific to your target arch for available configurations.
+ *
+ * @active: The configuration to be installed when the line is
+ * active, or its reference count is > 0.
+ * @suspended: The configuration to be installed when the line
+ * is suspended, or its reference count is 0.
+ * @ref: The reference count of the line. For internal use of
+ * the gpiomux framework only.
+ */
+struct msm_gpiomux_config {
+ gpiomux_config_t active;
+ gpiomux_config_t suspended;
+ unsigned ref;
+};
+
+/**
+ * @GPIOMUX_VALID: If set, the config field contains 'good data'.
+ * The absence of this bit will prevent the gpiomux
+ * system from applying the configuration under all
+ * circumstances.
+ */
+enum {
+ GPIOMUX_VALID = BIT(sizeof(gpiomux_config_t) * BITS_PER_BYTE - 1),
+ GPIOMUX_CTL_MASK = GPIOMUX_VALID,
+};
+
+#ifdef CONFIG_MSM_GPIOMUX
+
+/* Each architecture must provide its own instance of this table.
+ * To avoid having gpiomux manage any given gpio, one or both of
+ * the entries can avoid setting GPIOMUX_VALID - the absence
+ * of that flag will prevent the configuration from being applied
+ * during state transitions.
+ */
+extern struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS];
+
+/* Increment a gpio's reference count, possibly activating the line. */
+int __must_check msm_gpiomux_get(unsigned gpio);
+
+/* Decrement a gpio's reference count, possibly suspending the line. */
+int msm_gpiomux_put(unsigned gpio);
+
+/* Install a new configuration to the gpio line. To avoid overwriting
+ * a configuration, leave the VALID bit out.
+ */
+int msm_gpiomux_write(unsigned gpio,
+ gpiomux_config_t active,
+ gpiomux_config_t suspended);
+
+/* Architecture-internal function for use by the framework only.
+ * This function can assume the following:
+ * - the gpio value has passed a bounds-check
+ * - the gpiomux spinlock has been obtained
+ *
+ * This function is not for public consumption. External users
+ * should use msm_gpiomux_write.
+ */
+void __msm_gpiomux_write(unsigned gpio, gpiomux_config_t val);
+#else
+static inline int __must_check msm_gpiomux_get(unsigned gpio)
+{
+ return -ENOSYS;
+}
+
+static inline int msm_gpiomux_put(unsigned gpio)
+{
+ return -ENOSYS;
+}
+
+static inline int msm_gpiomux_write(unsigned gpio,
+ gpiomux_config_t active,
+ gpiomux_config_t suspended)
+{
+ return -ENOSYS;
+}
+#endif
+#endif
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index 5a79bcf50413..6abf4a6eadc1 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -33,6 +33,8 @@ struct msm_acpu_clock_platform_data
struct clk;
+extern struct sys_timer msm_timer;
+
/* common init routines for use by arch/arm/mach-msm/board-*.c */
void __init msm_add_devices(void);
diff --git a/arch/arm/mach-msm/include/mach/debug-macro.S b/arch/arm/mach-msm/include/mach/debug-macro.S
index 528750f307e9..fbd5d90dcc8c 100644
--- a/arch/arm/mach-msm/include/mach/debug-macro.S
+++ b/arch/arm/mach-msm/include/mach/debug-macro.S
@@ -19,13 +19,10 @@
#include <mach/hardware.h>
#include <mach/msm_iomap.h>
-#ifdef CONFIG_MSM_DEBUG_UART
- .macro addruart, rx, tmp
- @ see if the MMU is enabled and select appropriate base address
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1
- ldreq \rx, =MSM_DEBUG_UART_PHYS
- ldrne \rx, =MSM_DEBUG_UART_BASE
+#ifdef CONFIG_HAS_MSM_DEBUG_UART_PHYS
+ .macro addruart, rp, rv
+ ldr \rp, =MSM_DEBUG_UART_PHYS
+ ldr \rv, =MSM_DEBUG_UART_BASE
.endm
.macro senduart,rd,rx
@@ -39,16 +36,7 @@
tst \rd, #0x04
beq 1001b
.endm
-#else
- .macro addruart, rx, tmp
- .endm
-
- .macro senduart,rd,rx
- .endm
-
- .macro waituart,rd,rx
- .endm
-#endif
.macro busyuart,rd,rx
.endm
+#endif
diff --git a/arch/arm/mach-msm/include/mach/dma.h b/arch/arm/mach-msm/include/mach/dma.h
index 00f9bbfadbe6..05583f569524 100644
--- a/arch/arm/mach-msm/include/mach/dma.h
+++ b/arch/arm/mach-msm/include/mach/dma.h
@@ -32,10 +32,18 @@ struct msm_dmov_cmd {
void *data;
};
+#ifndef CONFIG_ARCH_MSM8X60
void msm_dmov_enqueue_cmd(unsigned id, struct msm_dmov_cmd *cmd);
void msm_dmov_stop_cmd(unsigned id, struct msm_dmov_cmd *cmd, int graceful);
int msm_dmov_exec_cmd(unsigned id, unsigned int cmdptr);
-
+#else
+static inline
+void msm_dmov_enqueue_cmd(unsigned id, struct msm_dmov_cmd *cmd) { }
+static inline
+void msm_dmov_stop_cmd(unsigned id, struct msm_dmov_cmd *cmd, int graceful) { }
+static inline
+int msm_dmov_exec_cmd(unsigned id, unsigned int cmdptr) { return -EIO; }
+#endif
#define DMOV_SD0(off, ch) (MSM_DMOV_BASE + 0x0000 + (off) + ((ch) << 2))
diff --git a/arch/arm/mach-msm/include/mach/entry-macro-qgic.S b/arch/arm/mach-msm/include/mach/entry-macro-qgic.S
new file mode 100644
index 000000000000..4dc99aa65d07
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/entry-macro-qgic.S
@@ -0,0 +1,88 @@
+/*
+ * Low-level IRQ helper macros
+ *
+ * Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * 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 <mach/hardware.h>
+#include <asm/hardware/gic.h>
+
+ .macro disable_fiq
+ .endm
+
+ .macro get_irqnr_preamble, base, tmp
+ ldr \base, =gic_cpu_base_addr
+ ldr \base, [\base]
+ .endm
+
+ .macro arch_ret_to_user, tmp1, tmp2
+ .endm
+
+ /*
+ * The interrupt numbering scheme is defined in the
+ * interrupt controller spec. To wit:
+ *
+ * Migrated the code from ARM MP port to be more consistant
+ * with interrupt processing , the following still holds true
+ * however, all interrupts are treated the same regardless of
+ * if they are local IPI or PPI
+ *
+ * Interrupts 0-15 are IPI
+ * 16-31 are PPI
+ * (16-18 are the timers)
+ * 32-1020 are global
+ * 1021-1022 are reserved
+ * 1023 is "spurious" (no interrupt)
+ *
+ * A simple read from the controller will tell us the number of the
+ * highest priority enabled interrupt. We then just need to check
+ * whether it is in the valid range for an IRQ (0-1020 inclusive).
+ *
+ * Base ARM code assumes that the local (private) peripheral interrupts
+ * are not valid, we treat them differently, in that the privates are
+ * handled like normal shared interrupts with the exception that only
+ * one processor can register the interrupt and the handler must be
+ * the same for all processors.
+ */
+
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
+
+ ldr \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 =srcCPU,
+ 9-0 =int # */
+
+ bic \irqnr, \irqstat, #0x1c00 @mask src
+ cmp \irqnr, #15
+ ldr \tmp, =1021
+ cmpcc \irqnr, \irqnr
+ cmpne \irqnr, \tmp
+ cmpcs \irqnr, \irqnr
+
+ .endm
+
+ /* We assume that irqstat (the raw value of the IRQ acknowledge
+ * register) is preserved from the macro above.
+ * If there is an IPI, we immediately signal end of interrupt on the
+ * controller, since this requires the original irqstat value which
+ * we won't easily be able to recreate later.
+ */
+ .macro test_for_ipi, irqnr, irqstat, base, tmp
+ bic \irqnr, \irqstat, #0x1c00
+ cmp \irqnr, #16
+ strcc \irqstat, [\base, #GIC_CPU_EOI]
+ cmpcs \irqnr, \irqnr
+ .endm
+
+ /* As above, this assumes that irqstat and base are preserved.. */
+
+ .macro test_for_ltirq, irqnr, irqstat, base, tmp
+ bic \irqnr, \irqstat, #0x1c00
+ mov \tmp, #0
+ cmp \irqnr, #16
+ moveq \tmp, #1
+ streq \irqstat, [\base, #GIC_CPU_EOI]
+ cmp \tmp, #0
+ .endm
diff --git a/arch/arm/mach-msm/include/mach/entry-macro-vic.S b/arch/arm/mach-msm/include/mach/entry-macro-vic.S
new file mode 100644
index 000000000000..70563ed11b36
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/entry-macro-vic.S
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2007 Google, Inc.
+ * Author: Brian Swetland <swetland@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <mach/msm_iomap.h>
+
+ .macro disable_fiq
+ .endm
+
+ .macro get_irqnr_preamble, base, tmp
+ @ enable imprecise aborts
+ cpsie a
+ mov \base, #MSM_VIC_BASE
+ .endm
+
+ .macro arch_ret_to_user, tmp1, tmp2
+ .endm
+
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
+ @ 0xD0 has irq# or old irq# if the irq has been handled
+ @ 0xD4 has irq# or -1 if none pending *but* if you just
+ @ read 0xD4 you never get the first irq for some reason
+ ldr \irqnr, [\base, #0xD0]
+ ldr \irqnr, [\base, #0xD4]
+ cmp \irqnr, #0xffffffff
+ .endm
diff --git a/arch/arm/mach-msm/include/mach/entry-macro.S b/arch/arm/mach-msm/include/mach/entry-macro.S
index d2259486bcb1..b16f082eeb6f 100644
--- a/arch/arm/mach-msm/include/mach/entry-macro.S
+++ b/arch/arm/mach-msm/include/mach/entry-macro.S
@@ -1,38 +1,23 @@
-/* arch/arm/mach-msm7200/include/mach/entry-macro.S
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
*
- * Copyright (C) 2007 Google, Inc.
- * Author: Brian Swetland <swetland@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
*/
-#include <mach/msm_iomap.h>
-
- .macro disable_fiq
- .endm
-
- .macro get_irqnr_preamble, base, tmp
- @ enable imprecise aborts
- cpsie a
- mov \base, #MSM_VIC_BASE
- .endm
-
- .macro arch_ret_to_user, tmp1, tmp2
- .endm
-
- .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
- @ 0xD0 has irq# or old irq# if the irq has been handled
- @ 0xD4 has irq# or -1 if none pending *but* if you just
- @ read 0xD4 you never get the first irq for some reason
- ldr \irqnr, [\base, #0xD0]
- ldr \irqnr, [\base, #0xD4]
- cmp \irqnr, #0xffffffff
- .endm
+#if defined(CONFIG_ARM_GIC)
+#include <mach/entry-macro-qgic.S>
+#else
+#include <mach/entry-macro-vic.S>
+#endif
diff --git a/arch/arm/mach-msm/include/mach/gpio.h b/arch/arm/mach-msm/include/mach/gpio.h
index 83e47c0d5c2e..36ad50d3bfaa 100644
--- a/arch/arm/mach-msm/include/mach/gpio.h
+++ b/arch/arm/mach-msm/include/mach/gpio.h
@@ -23,127 +23,4 @@
#define gpio_cansleep __gpio_cansleep
#define gpio_to_irq __gpio_to_irq
-/**
- * struct msm_gpio - GPIO pin description
- * @gpio_cfg - configuration bitmap, as per gpio_tlmm_config()
- * @label - textual label
- *
- * Usually, GPIO's are operated by sets.
- * This struct accumulate all GPIO information in single source
- * and facilitete group operations provided by msm_gpios_xxx()
- */
-struct msm_gpio {
- u32 gpio_cfg;
- const char *label;
-};
-
-/**
- * msm_gpios_request_enable() - request and enable set of GPIOs
- *
- * Request and configure set of GPIO's
- * In case of error, all operations rolled back.
- * Return error code.
- *
- * @table: GPIO table
- * @size: number of entries in @table
- */
-int msm_gpios_request_enable(const struct msm_gpio *table, int size);
-
-/**
- * msm_gpios_disable_free() - disable and free set of GPIOs
- *
- * @table: GPIO table
- * @size: number of entries in @table
- */
-void msm_gpios_disable_free(const struct msm_gpio *table, int size);
-
-/**
- * msm_gpios_request() - request set of GPIOs
- * In case of error, all operations rolled back.
- * Return error code.
- *
- * @table: GPIO table
- * @size: number of entries in @table
- */
-int msm_gpios_request(const struct msm_gpio *table, int size);
-
-/**
- * msm_gpios_free() - free set of GPIOs
- *
- * @table: GPIO table
- * @size: number of entries in @table
- */
-void msm_gpios_free(const struct msm_gpio *table, int size);
-
-/**
- * msm_gpios_enable() - enable set of GPIOs
- * In case of error, all operations rolled back.
- * Return error code.
- *
- * @table: GPIO table
- * @size: number of entries in @table
- */
-int msm_gpios_enable(const struct msm_gpio *table, int size);
-
-/**
- * msm_gpios_disable() - disable set of GPIOs
- *
- * @table: GPIO table
- * @size: number of entries in @table
- */
-void msm_gpios_disable(const struct msm_gpio *table, int size);
-
-/* GPIO TLMM (Top Level Multiplexing) Definitions */
-
-/* GPIO TLMM: Function -- GPIO specific */
-
-/* GPIO TLMM: Direction */
-enum {
- GPIO_INPUT,
- GPIO_OUTPUT,
-};
-
-/* GPIO TLMM: Pullup/Pulldown */
-enum {
- GPIO_NO_PULL,
- GPIO_PULL_DOWN,
- GPIO_KEEPER,
- GPIO_PULL_UP,
-};
-
-/* GPIO TLMM: Drive Strength */
-enum {
- GPIO_2MA,
- GPIO_4MA,
- GPIO_6MA,
- GPIO_8MA,
- GPIO_10MA,
- GPIO_12MA,
- GPIO_14MA,
- GPIO_16MA,
-};
-
-enum {
- GPIO_ENABLE,
- GPIO_DISABLE,
-};
-
-#define GPIO_CFG(gpio, func, dir, pull, drvstr) \
- ((((gpio) & 0x3FF) << 4) | \
- ((func) & 0xf) | \
- (((dir) & 0x1) << 14) | \
- (((pull) & 0x3) << 15) | \
- (((drvstr) & 0xF) << 17))
-
-/**
- * extract GPIO pin from bit-field used for gpio_tlmm_config
- */
-#define GPIO_PIN(gpio_cfg) (((gpio_cfg) >> 4) & 0x3ff)
-#define GPIO_FUNC(gpio_cfg) (((gpio_cfg) >> 0) & 0xf)
-#define GPIO_DIR(gpio_cfg) (((gpio_cfg) >> 14) & 0x1)
-#define GPIO_PULL(gpio_cfg) (((gpio_cfg) >> 15) & 0x3)
-#define GPIO_DRVSTR(gpio_cfg) (((gpio_cfg) >> 17) & 0xf)
-
-int gpio_tlmm_config(unsigned config, unsigned disable);
-
#endif /* __ASM_ARCH_MSM_GPIO_H */
diff --git a/arch/arm/mach-msm/include/mach/io.h b/arch/arm/mach-msm/include/mach/io.h
index c35b29f9ac0f..7386e732baad 100644
--- a/arch/arm/mach-msm/include/mach/io.h
+++ b/arch/arm/mach-msm/include/mach/io.h
@@ -28,6 +28,7 @@ void __iomem *__msm_ioremap(unsigned long phys_addr, size_t size, unsigned int m
void msm_map_qsd8x50_io(void);
void msm_map_msm7x30_io(void);
+void msm_map_msm8x60_io(void);
extern unsigned int msm_shared_ram_phys;
diff --git a/arch/arm/mach-msm/include/mach/iommu.h b/arch/arm/mach-msm/include/mach/iommu.h
new file mode 100644
index 000000000000..218ef5732a24
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/iommu.h
@@ -0,0 +1,103 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef MSM_IOMMU_H
+#define MSM_IOMMU_H
+
+#include <linux/interrupt.h>
+
+/* Maximum number of Machine IDs that we are allowing to be mapped to the same
+ * context bank. The number of MIDs mapped to the same CB does not affect
+ * performance, but there is a practical limit on how many distinct MIDs may
+ * be present. These mappings are typically determined at design time and are
+ * not expected to change at run time.
+ */
+#define MAX_NUM_MIDS 16
+
+/**
+ * struct msm_iommu_dev - a single IOMMU hardware instance
+ * name Human-readable name given to this IOMMU HW instance
+ * clk_rate Rate to set for this IOMMU's clock, if applicable to this
+ * particular IOMMU. 0 means don't set a rate.
+ * -1 means it is an AXI clock with no valid rate
+ *
+ */
+struct msm_iommu_dev {
+ const char *name;
+ int clk_rate;
+};
+
+/**
+ * struct msm_iommu_ctx_dev - an IOMMU context bank instance
+ * name Human-readable name given to this context bank
+ * num Index of this context bank within the hardware
+ * mids List of Machine IDs that are to be mapped into this context
+ * bank, terminated by -1. The MID is a set of signals on the
+ * AXI bus that identifies the function associated with a specific
+ * memory request. (See ARM spec).
+ */
+struct msm_iommu_ctx_dev {
+ const char *name;
+ int num;
+ int mids[MAX_NUM_MIDS];
+};
+
+
+/**
+ * struct msm_iommu_drvdata - A single IOMMU hardware instance
+ * @base: IOMMU config port base address (VA)
+ * @irq: Interrupt number
+ *
+ * A msm_iommu_drvdata holds the global driver data about a single piece
+ * of an IOMMU hardware instance.
+ */
+struct msm_iommu_drvdata {
+ void __iomem *base;
+ int irq;
+};
+
+/**
+ * struct msm_iommu_ctx_drvdata - an IOMMU context bank instance
+ * @num: Hardware context number of this context
+ * @pdev: Platform device associated wit this HW instance
+ * @attached_elm: List element for domains to track which devices are
+ * attached to them
+ *
+ * A msm_iommu_ctx_drvdata holds the driver data for a single context bank
+ * within each IOMMU hardware instance
+ */
+struct msm_iommu_ctx_drvdata {
+ int num;
+ struct platform_device *pdev;
+ struct list_head attached_elm;
+};
+
+/*
+ * Look up an IOMMU context device by its context name. NULL if none found.
+ * Useful for testing and drivers that do not yet fully have IOMMU stuff in
+ * their platform devices.
+ */
+struct device *msm_iommu_get_ctx(const char *ctx_name);
+
+/*
+ * Interrupt handler for the IOMMU context fault interrupt. Hooking the
+ * interrupt is not supported in the API yet, but this will print an error
+ * message and dump useful IOMMU registers.
+ */
+irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id);
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h b/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h
new file mode 100644
index 000000000000..f9386d3a2f77
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h
@@ -0,0 +1,1871 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef __ARCH_ARM_MACH_MSM_IOMMU_HW_8XXX_H
+#define __ARCH_ARM_MACH_MSM_IOMMU_HW_8XXX_H
+
+#define CTX_SHIFT 12
+
+#define GET_GLOBAL_REG(reg, base) (readl((base) + (reg)))
+#define GET_CTX_REG(reg, base, ctx) \
+ (readl((base) + (reg) + ((ctx) << CTX_SHIFT)))
+
+#define SET_GLOBAL_REG(reg, base, val) writel((val), ((base) + (reg)))
+
+#define SET_CTX_REG(reg, base, ctx, val) \
+ writel((val), ((base) + (reg) + ((ctx) << CTX_SHIFT)))
+
+/* Wrappers for numbered registers */
+#define SET_GLOBAL_REG_N(b, n, r, v) SET_GLOBAL_REG(b, ((r) + (n << 2)), (v))
+#define GET_GLOBAL_REG_N(b, n, r) GET_GLOBAL_REG(b, ((r) + (n << 2)))
+
+/* Field wrappers */
+#define GET_GLOBAL_FIELD(b, r, F) GET_FIELD(((b) + (r)), F##_MASK, F##_SHIFT)
+#define GET_CONTEXT_FIELD(b, c, r, F) \
+ GET_FIELD(((b) + (r) + ((c) << CTX_SHIFT)), F##_MASK, F##_SHIFT)
+
+#define SET_GLOBAL_FIELD(b, r, F, v) \
+ SET_FIELD(((b) + (r)), F##_MASK, F##_SHIFT, (v))
+#define SET_CONTEXT_FIELD(b, c, r, F, v) \
+ SET_FIELD(((b) + (r) + ((c) << CTX_SHIFT)), F##_MASK, F##_SHIFT, (v))
+
+#define GET_FIELD(addr, mask, shift) ((readl(addr) >> (shift)) & (mask))
+
+#define SET_FIELD(addr, mask, shift, v) \
+do { \
+ int t = readl(addr); \
+ writel((t & ~((mask) << (shift))) + (((v) & (mask)) << (shift)), addr);\
+} while (0)
+
+
+#define NUM_FL_PTE 4096
+#define NUM_SL_PTE 256
+
+/* First-level page table bits */
+#define FL_BASE_MASK 0xFFFFFC00
+#define FL_TYPE_TABLE (1 << 0)
+#define FL_TYPE_SECT (2 << 0)
+#define FL_SUPERSECTION (1 << 18)
+#define FL_AP_WRITE (1 << 10)
+#define FL_AP_READ (1 << 11)
+#define FL_SHARED (1 << 16)
+#define FL_OFFSET(va) (((va) & 0xFFF00000) >> 20)
+
+/* Second-level page table bits */
+#define SL_BASE_MASK_LARGE 0xFFFF0000
+#define SL_BASE_MASK_SMALL 0xFFFFF000
+#define SL_TYPE_LARGE (1 << 0)
+#define SL_TYPE_SMALL (2 << 0)
+#define SL_AP0 (1 << 4)
+#define SL_AP1 (2 << 4)
+#define SL_SHARED (1 << 10)
+#define SL_OFFSET(va) (((va) & 0xFF000) >> 12)
+
+/* Global register setters / getters */
+#define SET_M2VCBR_N(b, N, v) SET_GLOBAL_REG_N(M2VCBR_N, N, (b), (v))
+#define SET_CBACR_N(b, N, v) SET_GLOBAL_REG_N(CBACR_N, N, (b), (v))
+#define SET_TLBRSW(b, v) SET_GLOBAL_REG(TLBRSW, (b), (v))
+#define SET_TLBTR0(b, v) SET_GLOBAL_REG(TLBTR0, (b), (v))
+#define SET_TLBTR1(b, v) SET_GLOBAL_REG(TLBTR1, (b), (v))
+#define SET_TLBTR2(b, v) SET_GLOBAL_REG(TLBTR2, (b), (v))
+#define SET_TESTBUSCR(b, v) SET_GLOBAL_REG(TESTBUSCR, (b), (v))
+#define SET_GLOBAL_TLBIALL(b, v) SET_GLOBAL_REG(GLOBAL_TLBIALL, (b), (v))
+#define SET_TLBIVMID(b, v) SET_GLOBAL_REG(TLBIVMID, (b), (v))
+#define SET_CR(b, v) SET_GLOBAL_REG(CR, (b), (v))
+#define SET_EAR(b, v) SET_GLOBAL_REG(EAR, (b), (v))
+#define SET_ESR(b, v) SET_GLOBAL_REG(ESR, (b), (v))
+#define SET_ESRRESTORE(b, v) SET_GLOBAL_REG(ESRRESTORE, (b), (v))
+#define SET_ESYNR0(b, v) SET_GLOBAL_REG(ESYNR0, (b), (v))
+#define SET_ESYNR1(b, v) SET_GLOBAL_REG(ESYNR1, (b), (v))
+#define SET_RPU_ACR(b, v) SET_GLOBAL_REG(RPU_ACR, (b), (v))
+
+#define GET_M2VCBR_N(b, N) GET_GLOBAL_REG_N(M2VCBR_N, N, (b))
+#define GET_CBACR_N(b, N) GET_GLOBAL_REG_N(CBACR_N, N, (b))
+#define GET_TLBTR0(b) GET_GLOBAL_REG(TLBTR0, (b))
+#define GET_TLBTR1(b) GET_GLOBAL_REG(TLBTR1, (b))
+#define GET_TLBTR2(b) GET_GLOBAL_REG(TLBTR2, (b))
+#define GET_TESTBUSCR(b) GET_GLOBAL_REG(TESTBUSCR, (b))
+#define GET_GLOBAL_TLBIALL(b) GET_GLOBAL_REG(GLOBAL_TLBIALL, (b))
+#define GET_TLBIVMID(b) GET_GLOBAL_REG(TLBIVMID, (b))
+#define GET_CR(b) GET_GLOBAL_REG(CR, (b))
+#define GET_EAR(b) GET_GLOBAL_REG(EAR, (b))
+#define GET_ESR(b) GET_GLOBAL_REG(ESR, (b))
+#define GET_ESRRESTORE(b) GET_GLOBAL_REG(ESRRESTORE, (b))
+#define GET_ESYNR0(b) GET_GLOBAL_REG(ESYNR0, (b))
+#define GET_ESYNR1(b) GET_GLOBAL_REG(ESYNR1, (b))
+#define GET_REV(b) GET_GLOBAL_REG(REV, (b))
+#define GET_IDR(b) GET_GLOBAL_REG(IDR, (b))
+#define GET_RPU_ACR(b) GET_GLOBAL_REG(RPU_ACR, (b))
+
+
+/* Context register setters/getters */
+#define SET_SCTLR(b, c, v) SET_CTX_REG(SCTLR, (b), (c), (v))
+#define SET_ACTLR(b, c, v) SET_CTX_REG(ACTLR, (b), (c), (v))
+#define SET_CONTEXTIDR(b, c, v) SET_CTX_REG(CONTEXTIDR, (b), (c), (v))
+#define SET_TTBR0(b, c, v) SET_CTX_REG(TTBR0, (b), (c), (v))
+#define SET_TTBR1(b, c, v) SET_CTX_REG(TTBR1, (b), (c), (v))
+#define SET_TTBCR(b, c, v) SET_CTX_REG(TTBCR, (b), (c), (v))
+#define SET_PAR(b, c, v) SET_CTX_REG(PAR, (b), (c), (v))
+#define SET_FSR(b, c, v) SET_CTX_REG(FSR, (b), (c), (v))
+#define SET_FSRRESTORE(b, c, v) SET_CTX_REG(FSRRESTORE, (b), (c), (v))
+#define SET_FAR(b, c, v) SET_CTX_REG(FAR, (b), (c), (v))
+#define SET_FSYNR0(b, c, v) SET_CTX_REG(FSYNR0, (b), (c), (v))
+#define SET_FSYNR1(b, c, v) SET_CTX_REG(FSYNR1, (b), (c), (v))
+#define SET_PRRR(b, c, v) SET_CTX_REG(PRRR, (b), (c), (v))
+#define SET_NMRR(b, c, v) SET_CTX_REG(NMRR, (b), (c), (v))
+#define SET_TLBLKCR(b, c, v) SET_CTX_REG(TLBLCKR, (b), (c), (v))
+#define SET_V2PSR(b, c, v) SET_CTX_REG(V2PSR, (b), (c), (v))
+#define SET_TLBFLPTER(b, c, v) SET_CTX_REG(TLBFLPTER, (b), (c), (v))
+#define SET_TLBSLPTER(b, c, v) SET_CTX_REG(TLBSLPTER, (b), (c), (v))
+#define SET_BFBCR(b, c, v) SET_CTX_REG(BFBCR, (b), (c), (v))
+#define SET_CTX_TLBIALL(b, c, v) SET_CTX_REG(CTX_TLBIALL, (b), (c), (v))
+#define SET_TLBIASID(b, c, v) SET_CTX_REG(TLBIASID, (b), (c), (v))
+#define SET_TLBIVA(b, c, v) SET_CTX_REG(TLBIVA, (b), (c), (v))
+#define SET_TLBIVAA(b, c, v) SET_CTX_REG(TLBIVAA, (b), (c), (v))
+#define SET_V2PPR(b, c, v) SET_CTX_REG(V2PPR, (b), (c), (v))
+#define SET_V2PPW(b, c, v) SET_CTX_REG(V2PPW, (b), (c), (v))
+#define SET_V2PUR(b, c, v) SET_CTX_REG(V2PUR, (b), (c), (v))
+#define SET_V2PUW(b, c, v) SET_CTX_REG(V2PUW, (b), (c), (v))
+#define SET_RESUME(b, c, v) SET_CTX_REG(RESUME, (b), (c), (v))
+
+#define GET_SCTLR(b, c) GET_CTX_REG(SCTLR, (b), (c))
+#define GET_ACTLR(b, c) GET_CTX_REG(ACTLR, (b), (c))
+#define GET_CONTEXTIDR(b, c) GET_CTX_REG(CONTEXTIDR, (b), (c))
+#define GET_TTBR0(b, c) GET_CTX_REG(TTBR0, (b), (c))
+#define GET_TTBR1(b, c) GET_CTX_REG(TTBR1, (b), (c))
+#define GET_TTBCR(b, c) GET_CTX_REG(TTBCR, (b), (c))
+#define GET_PAR(b, c) GET_CTX_REG(PAR, (b), (c))
+#define GET_FSR(b, c) GET_CTX_REG(FSR, (b), (c))
+#define GET_FSRRESTORE(b, c) GET_CTX_REG(FSRRESTORE, (b), (c))
+#define GET_FAR(b, c) GET_CTX_REG(FAR, (b), (c))
+#define GET_FSYNR0(b, c) GET_CTX_REG(FSYNR0, (b), (c))
+#define GET_FSYNR1(b, c) GET_CTX_REG(FSYNR1, (b), (c))
+#define GET_PRRR(b, c) GET_CTX_REG(PRRR, (b), (c))
+#define GET_NMRR(b, c) GET_CTX_REG(NMRR, (b), (c))
+#define GET_TLBLCKR(b, c) GET_CTX_REG(TLBLCKR, (b), (c))
+#define GET_V2PSR(b, c) GET_CTX_REG(V2PSR, (b), (c))
+#define GET_TLBFLPTER(b, c) GET_CTX_REG(TLBFLPTER, (b), (c))
+#define GET_TLBSLPTER(b, c) GET_CTX_REG(TLBSLPTER, (b), (c))
+#define GET_BFBCR(b, c) GET_CTX_REG(BFBCR, (b), (c))
+#define GET_CTX_TLBIALL(b, c) GET_CTX_REG(CTX_TLBIALL, (b), (c))
+#define GET_TLBIASID(b, c) GET_CTX_REG(TLBIASID, (b), (c))
+#define GET_TLBIVA(b, c) GET_CTX_REG(TLBIVA, (b), (c))
+#define GET_TLBIVAA(b, c) GET_CTX_REG(TLBIVAA, (b), (c))
+#define GET_V2PPR(b, c) GET_CTX_REG(V2PPR, (b), (c))
+#define GET_V2PPW(b, c) GET_CTX_REG(V2PPW, (b), (c))
+#define GET_V2PUR(b, c) GET_CTX_REG(V2PUR, (b), (c))
+#define GET_V2PUW(b, c) GET_CTX_REG(V2PUW, (b), (c))
+#define GET_RESUME(b, c) GET_CTX_REG(RESUME, (b), (c))
+
+
+/* Global field setters / getters */
+/* Global Field Setters: */
+/* CBACR_N */
+#define SET_RWVMID(b, n, v) SET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), RWVMID, v)
+#define SET_RWE(b, n, v) SET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), RWE, v)
+#define SET_RWGE(b, n, v) SET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), RWGE, v)
+#define SET_CBVMID(b, n, v) SET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), CBVMID, v)
+#define SET_IRPTNDX(b, n, v) SET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), IRPTNDX, v)
+
+
+/* M2VCBR_N */
+#define SET_VMID(b, n, v) SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), VMID, v)
+#define SET_CBNDX(b, n, v) SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), CBNDX, v)
+#define SET_BYPASSD(b, n, v) SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BYPASSD, v)
+#define SET_BPRCOSH(b, n, v) SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPRCOSH, v)
+#define SET_BPRCISH(b, n, v) SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPRCISH, v)
+#define SET_BPRCNSH(b, n, v) SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPRCNSH, v)
+#define SET_BPSHCFG(b, n, v) SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPSHCFG, v)
+#define SET_NSCFG(b, n, v) SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), NSCFG, v)
+#define SET_BPMTCFG(b, n, v) SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPMTCFG, v)
+#define SET_BPMEMTYPE(b, n, v) \
+ SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPMEMTYPE, v)
+
+
+/* CR */
+#define SET_RPUE(b, v) SET_GLOBAL_FIELD(b, CR, RPUE, v)
+#define SET_RPUERE(b, v) SET_GLOBAL_FIELD(b, CR, RPUERE, v)
+#define SET_RPUEIE(b, v) SET_GLOBAL_FIELD(b, CR, RPUEIE, v)
+#define SET_DCDEE(b, v) SET_GLOBAL_FIELD(b, CR, DCDEE, v)
+#define SET_CLIENTPD(b, v) SET_GLOBAL_FIELD(b, CR, CLIENTPD, v)
+#define SET_STALLD(b, v) SET_GLOBAL_FIELD(b, CR, STALLD, v)
+#define SET_TLBLKCRWE(b, v) SET_GLOBAL_FIELD(b, CR, TLBLKCRWE, v)
+#define SET_CR_TLBIALLCFG(b, v) SET_GLOBAL_FIELD(b, CR, CR_TLBIALLCFG, v)
+#define SET_TLBIVMIDCFG(b, v) SET_GLOBAL_FIELD(b, CR, TLBIVMIDCFG, v)
+#define SET_CR_HUME(b, v) SET_GLOBAL_FIELD(b, CR, CR_HUME, v)
+
+
+/* ESR */
+#define SET_CFG(b, v) SET_GLOBAL_FIELD(b, ESR, CFG, v)
+#define SET_BYPASS(b, v) SET_GLOBAL_FIELD(b, ESR, BYPASS, v)
+#define SET_ESR_MULTI(b, v) SET_GLOBAL_FIELD(b, ESR, ESR_MULTI, v)
+
+
+/* ESYNR0 */
+#define SET_ESYNR0_AMID(b, v) SET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_AMID, v)
+#define SET_ESYNR0_APID(b, v) SET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_APID, v)
+#define SET_ESYNR0_ABID(b, v) SET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_ABID, v)
+#define SET_ESYNR0_AVMID(b, v) SET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_AVMID, v)
+#define SET_ESYNR0_ATID(b, v) SET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_ATID, v)
+
+
+/* ESYNR1 */
+#define SET_ESYNR1_AMEMTYPE(b, v) \
+ SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AMEMTYPE, v)
+#define SET_ESYNR1_ASHARED(b, v) SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ASHARED, v)
+#define SET_ESYNR1_AINNERSHARED(b, v) \
+ SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AINNERSHARED, v)
+#define SET_ESYNR1_APRIV(b, v) SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_APRIV, v)
+#define SET_ESYNR1_APROTNS(b, v) SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_APROTNS, v)
+#define SET_ESYNR1_AINST(b, v) SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AINST, v)
+#define SET_ESYNR1_AWRITE(b, v) SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AWRITE, v)
+#define SET_ESYNR1_ABURST(b, v) SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ABURST, v)
+#define SET_ESYNR1_ALEN(b, v) SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ALEN, v)
+#define SET_ESYNR1_ASIZE(b, v) SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ASIZE, v)
+#define SET_ESYNR1_ALOCK(b, v) SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ALOCK, v)
+#define SET_ESYNR1_AOOO(b, v) SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AOOO, v)
+#define SET_ESYNR1_AFULL(b, v) SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AFULL, v)
+#define SET_ESYNR1_AC(b, v) SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AC, v)
+#define SET_ESYNR1_DCD(b, v) SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_DCD, v)
+
+
+/* TESTBUSCR */
+#define SET_TBE(b, v) SET_GLOBAL_FIELD(b, TESTBUSCR, TBE, v)
+#define SET_SPDMBE(b, v) SET_GLOBAL_FIELD(b, TESTBUSCR, SPDMBE, v)
+#define SET_WGSEL(b, v) SET_GLOBAL_FIELD(b, TESTBUSCR, WGSEL, v)
+#define SET_TBLSEL(b, v) SET_GLOBAL_FIELD(b, TESTBUSCR, TBLSEL, v)
+#define SET_TBHSEL(b, v) SET_GLOBAL_FIELD(b, TESTBUSCR, TBHSEL, v)
+#define SET_SPDM0SEL(b, v) SET_GLOBAL_FIELD(b, TESTBUSCR, SPDM0SEL, v)
+#define SET_SPDM1SEL(b, v) SET_GLOBAL_FIELD(b, TESTBUSCR, SPDM1SEL, v)
+#define SET_SPDM2SEL(b, v) SET_GLOBAL_FIELD(b, TESTBUSCR, SPDM2SEL, v)
+#define SET_SPDM3SEL(b, v) SET_GLOBAL_FIELD(b, TESTBUSCR, SPDM3SEL, v)
+
+
+/* TLBIVMID */
+#define SET_TLBIVMID_VMID(b, v) SET_GLOBAL_FIELD(b, TLBIVMID, TLBIVMID_VMID, v)
+
+
+/* TLBRSW */
+#define SET_TLBRSW_INDEX(b, v) SET_GLOBAL_FIELD(b, TLBRSW, TLBRSW_INDEX, v)
+#define SET_TLBBFBS(b, v) SET_GLOBAL_FIELD(b, TLBRSW, TLBBFBS, v)
+
+
+/* TLBTR0 */
+#define SET_PR(b, v) SET_GLOBAL_FIELD(b, TLBTR0, PR, v)
+#define SET_PW(b, v) SET_GLOBAL_FIELD(b, TLBTR0, PW, v)
+#define SET_UR(b, v) SET_GLOBAL_FIELD(b, TLBTR0, UR, v)
+#define SET_UW(b, v) SET_GLOBAL_FIELD(b, TLBTR0, UW, v)
+#define SET_XN(b, v) SET_GLOBAL_FIELD(b, TLBTR0, XN, v)
+#define SET_NSDESC(b, v) SET_GLOBAL_FIELD(b, TLBTR0, NSDESC, v)
+#define SET_ISH(b, v) SET_GLOBAL_FIELD(b, TLBTR0, ISH, v)
+#define SET_SH(b, v) SET_GLOBAL_FIELD(b, TLBTR0, SH, v)
+#define SET_MT(b, v) SET_GLOBAL_FIELD(b, TLBTR0, MT, v)
+#define SET_DPSIZR(b, v) SET_GLOBAL_FIELD(b, TLBTR0, DPSIZR, v)
+#define SET_DPSIZC(b, v) SET_GLOBAL_FIELD(b, TLBTR0, DPSIZC, v)
+
+
+/* TLBTR1 */
+#define SET_TLBTR1_VMID(b, v) SET_GLOBAL_FIELD(b, TLBTR1, TLBTR1_VMID, v)
+#define SET_TLBTR1_PA(b, v) SET_GLOBAL_FIELD(b, TLBTR1, TLBTR1_PA, v)
+
+
+/* TLBTR2 */
+#define SET_TLBTR2_ASID(b, v) SET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_ASID, v)
+#define SET_TLBTR2_V(b, v) SET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_V, v)
+#define SET_TLBTR2_NSTID(b, v) SET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_NSTID, v)
+#define SET_TLBTR2_NV(b, v) SET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_NV, v)
+#define SET_TLBTR2_VA(b, v) SET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_VA, v)
+
+
+/* Global Field Getters */
+/* CBACR_N */
+#define GET_RWVMID(b, n) GET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), RWVMID)
+#define GET_RWE(b, n) GET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), RWE)
+#define GET_RWGE(b, n) GET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), RWGE)
+#define GET_CBVMID(b, n) GET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), CBVMID)
+#define GET_IRPTNDX(b, n) GET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), IRPTNDX)
+
+
+/* M2VCBR_N */
+#define GET_VMID(b, n) GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), VMID)
+#define GET_CBNDX(b, n) GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), CBNDX)
+#define GET_BYPASSD(b, n) GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BYPASSD)
+#define GET_BPRCOSH(b, n) GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPRCOSH)
+#define GET_BPRCISH(b, n) GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPRCISH)
+#define GET_BPRCNSH(b, n) GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPRCNSH)
+#define GET_BPSHCFG(b, n) GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPSHCFG)
+#define GET_NSCFG(b, n) GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), NSCFG)
+#define GET_BPMTCFG(b, n) GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPMTCFG)
+#define GET_BPMEMTYPE(b, n) GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPMEMTYPE)
+
+
+/* CR */
+#define GET_RPUE(b) GET_GLOBAL_FIELD(b, CR, RPUE)
+#define GET_RPUERE(b) GET_GLOBAL_FIELD(b, CR, RPUERE)
+#define GET_RPUEIE(b) GET_GLOBAL_FIELD(b, CR, RPUEIE)
+#define GET_DCDEE(b) GET_GLOBAL_FIELD(b, CR, DCDEE)
+#define GET_CLIENTPD(b) GET_GLOBAL_FIELD(b, CR, CLIENTPD)
+#define GET_STALLD(b) GET_GLOBAL_FIELD(b, CR, STALLD)
+#define GET_TLBLKCRWE(b) GET_GLOBAL_FIELD(b, CR, TLBLKCRWE)
+#define GET_CR_TLBIALLCFG(b) GET_GLOBAL_FIELD(b, CR, CR_TLBIALLCFG)
+#define GET_TLBIVMIDCFG(b) GET_GLOBAL_FIELD(b, CR, TLBIVMIDCFG)
+#define GET_CR_HUME(b) GET_GLOBAL_FIELD(b, CR, CR_HUME)
+
+
+/* ESR */
+#define GET_CFG(b) GET_GLOBAL_FIELD(b, ESR, CFG)
+#define GET_BYPASS(b) GET_GLOBAL_FIELD(b, ESR, BYPASS)
+#define GET_ESR_MULTI(b) GET_GLOBAL_FIELD(b, ESR, ESR_MULTI)
+
+
+/* ESYNR0 */
+#define GET_ESYNR0_AMID(b) GET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_AMID)
+#define GET_ESYNR0_APID(b) GET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_APID)
+#define GET_ESYNR0_ABID(b) GET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_ABID)
+#define GET_ESYNR0_AVMID(b) GET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_AVMID)
+#define GET_ESYNR0_ATID(b) GET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_ATID)
+
+
+/* ESYNR1 */
+#define GET_ESYNR1_AMEMTYPE(b) GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AMEMTYPE)
+#define GET_ESYNR1_ASHARED(b) GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ASHARED)
+#define GET_ESYNR1_AINNERSHARED(b) \
+ GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AINNERSHARED)
+#define GET_ESYNR1_APRIV(b) GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_APRIV)
+#define GET_ESYNR1_APROTNS(b) GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_APROTNS)
+#define GET_ESYNR1_AINST(b) GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AINST)
+#define GET_ESYNR1_AWRITE(b) GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AWRITE)
+#define GET_ESYNR1_ABURST(b) GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ABURST)
+#define GET_ESYNR1_ALEN(b) GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ALEN)
+#define GET_ESYNR1_ASIZE(b) GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ASIZE)
+#define GET_ESYNR1_ALOCK(b) GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ALOCK)
+#define GET_ESYNR1_AOOO(b) GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AOOO)
+#define GET_ESYNR1_AFULL(b) GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AFULL)
+#define GET_ESYNR1_AC(b) GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AC)
+#define GET_ESYNR1_DCD(b) GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_DCD)
+
+
+/* IDR */
+#define GET_NM2VCBMT(b) GET_GLOBAL_FIELD(b, IDR, NM2VCBMT)
+#define GET_HTW(b) GET_GLOBAL_FIELD(b, IDR, HTW)
+#define GET_HUM(b) GET_GLOBAL_FIELD(b, IDR, HUM)
+#define GET_TLBSIZE(b) GET_GLOBAL_FIELD(b, IDR, TLBSIZE)
+#define GET_NCB(b) GET_GLOBAL_FIELD(b, IDR, NCB)
+#define GET_NIRPT(b) GET_GLOBAL_FIELD(b, IDR, NIRPT)
+
+
+/* REV */
+#define GET_MAJOR(b) GET_GLOBAL_FIELD(b, REV, MAJOR)
+#define GET_MINOR(b) GET_GLOBAL_FIELD(b, REV, MINOR)
+
+
+/* TESTBUSCR */
+#define GET_TBE(b) GET_GLOBAL_FIELD(b, TESTBUSCR, TBE)
+#define GET_SPDMBE(b) GET_GLOBAL_FIELD(b, TESTBUSCR, SPDMBE)
+#define GET_WGSEL(b) GET_GLOBAL_FIELD(b, TESTBUSCR, WGSEL)
+#define GET_TBLSEL(b) GET_GLOBAL_FIELD(b, TESTBUSCR, TBLSEL)
+#define GET_TBHSEL(b) GET_GLOBAL_FIELD(b, TESTBUSCR, TBHSEL)
+#define GET_SPDM0SEL(b) GET_GLOBAL_FIELD(b, TESTBUSCR, SPDM0SEL)
+#define GET_SPDM1SEL(b) GET_GLOBAL_FIELD(b, TESTBUSCR, SPDM1SEL)
+#define GET_SPDM2SEL(b) GET_GLOBAL_FIELD(b, TESTBUSCR, SPDM2SEL)
+#define GET_SPDM3SEL(b) GET_GLOBAL_FIELD(b, TESTBUSCR, SPDM3SEL)
+
+
+/* TLBIVMID */
+#define GET_TLBIVMID_VMID(b) GET_GLOBAL_FIELD(b, TLBIVMID, TLBIVMID_VMID)
+
+
+/* TLBTR0 */
+#define GET_PR(b) GET_GLOBAL_FIELD(b, TLBTR0, PR)
+#define GET_PW(b) GET_GLOBAL_FIELD(b, TLBTR0, PW)
+#define GET_UR(b) GET_GLOBAL_FIELD(b, TLBTR0, UR)
+#define GET_UW(b) GET_GLOBAL_FIELD(b, TLBTR0, UW)
+#define GET_XN(b) GET_GLOBAL_FIELD(b, TLBTR0, XN)
+#define GET_NSDESC(b) GET_GLOBAL_FIELD(b, TLBTR0, NSDESC)
+#define GET_ISH(b) GET_GLOBAL_FIELD(b, TLBTR0, ISH)
+#define GET_SH(b) GET_GLOBAL_FIELD(b, TLBTR0, SH)
+#define GET_MT(b) GET_GLOBAL_FIELD(b, TLBTR0, MT)
+#define GET_DPSIZR(b) GET_GLOBAL_FIELD(b, TLBTR0, DPSIZR)
+#define GET_DPSIZC(b) GET_GLOBAL_FIELD(b, TLBTR0, DPSIZC)
+
+
+/* TLBTR1 */
+#define GET_TLBTR1_VMID(b) GET_GLOBAL_FIELD(b, TLBTR1, TLBTR1_VMID)
+#define GET_TLBTR1_PA(b) GET_GLOBAL_FIELD(b, TLBTR1, TLBTR1_PA)
+
+
+/* TLBTR2 */
+#define GET_TLBTR2_ASID(b) GET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_ASID)
+#define GET_TLBTR2_V(b) GET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_V)
+#define GET_TLBTR2_NSTID(b) GET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_NSTID)
+#define GET_TLBTR2_NV(b) GET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_NV)
+#define GET_TLBTR2_VA(b) GET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_VA)
+
+
+/* Context Register setters / getters */
+/* Context Register setters */
+/* ACTLR */
+#define SET_CFERE(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, CFERE, v)
+#define SET_CFEIE(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, CFEIE, v)
+#define SET_PTSHCFG(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, PTSHCFG, v)
+#define SET_RCOSH(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, RCOSH, v)
+#define SET_RCISH(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, RCISH, v)
+#define SET_RCNSH(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, RCNSH, v)
+#define SET_PRIVCFG(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, PRIVCFG, v)
+#define SET_DNA(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, DNA, v)
+#define SET_DNLV2PA(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, DNLV2PA, v)
+#define SET_TLBMCFG(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, TLBMCFG, v)
+#define SET_CFCFG(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, CFCFG, v)
+#define SET_TIPCF(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, TIPCF, v)
+#define SET_V2PCFG(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, V2PCFG, v)
+#define SET_HUME(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, HUME, v)
+#define SET_PTMTCFG(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, PTMTCFG, v)
+#define SET_PTMEMTYPE(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, PTMEMTYPE, v)
+
+
+/* BFBCR */
+#define SET_BFBDFE(b, c, v) SET_CONTEXT_FIELD(b, c, BFBCR, BFBDFE, v)
+#define SET_BFBSFE(b, c, v) SET_CONTEXT_FIELD(b, c, BFBCR, BFBSFE, v)
+#define SET_SFVS(b, c, v) SET_CONTEXT_FIELD(b, c, BFBCR, SFVS, v)
+#define SET_FLVIC(b, c, v) SET_CONTEXT_FIELD(b, c, BFBCR, FLVIC, v)
+#define SET_SLVIC(b, c, v) SET_CONTEXT_FIELD(b, c, BFBCR, SLVIC, v)
+
+
+/* CONTEXTIDR */
+#define SET_CONTEXTIDR_ASID(b, c, v) \
+ SET_CONTEXT_FIELD(b, c, CONTEXTIDR, CONTEXTIDR_ASID, v)
+#define SET_CONTEXTIDR_PROCID(b, c, v) \
+ SET_CONTEXT_FIELD(b, c, CONTEXTIDR, PROCID, v)
+
+
+/* FSR */
+#define SET_TF(b, c, v) SET_CONTEXT_FIELD(b, c, FSR, TF, v)
+#define SET_AFF(b, c, v) SET_CONTEXT_FIELD(b, c, FSR, AFF, v)
+#define SET_APF(b, c, v) SET_CONTEXT_FIELD(b, c, FSR, APF, v)
+#define SET_TLBMF(b, c, v) SET_CONTEXT_FIELD(b, c, FSR, TLBMF, v)
+#define SET_HTWDEEF(b, c, v) SET_CONTEXT_FIELD(b, c, FSR, HTWDEEF, v)
+#define SET_HTWSEEF(b, c, v) SET_CONTEXT_FIELD(b, c, FSR, HTWSEEF, v)
+#define SET_MHF(b, c, v) SET_CONTEXT_FIELD(b, c, FSR, MHF, v)
+#define SET_SL(b, c, v) SET_CONTEXT_FIELD(b, c, FSR, SL, v)
+#define SET_SS(b, c, v) SET_CONTEXT_FIELD(b, c, FSR, SS, v)
+#define SET_MULTI(b, c, v) SET_CONTEXT_FIELD(b, c, FSR, MULTI, v)
+
+
+/* FSYNR0 */
+#define SET_AMID(b, c, v) SET_CONTEXT_FIELD(b, c, FSYNR0, AMID, v)
+#define SET_APID(b, c, v) SET_CONTEXT_FIELD(b, c, FSYNR0, APID, v)
+#define SET_ABID(b, c, v) SET_CONTEXT_FIELD(b, c, FSYNR0, ABID, v)
+#define SET_ATID(b, c, v) SET_CONTEXT_FIELD(b, c, FSYNR0, ATID, v)
+
+
+/* FSYNR1 */
+#define SET_AMEMTYPE(b, c, v) SET_CONTEXT_FIELD(b, c, FSYNR1, AMEMTYPE, v)
+#define SET_ASHARED(b, c, v) SET_CONTEXT_FIELD(b, c, FSYNR1, ASHARED, v)
+#define SET_AINNERSHARED(b, c, v) \
+ SET_CONTEXT_FIELD(b, c, FSYNR1, AINNERSHARED, v)
+#define SET_APRIV(b, c, v) SET_CONTEXT_FIELD(b, c, FSYNR1, APRIV, v)
+#define SET_APROTNS(b, c, v) SET_CONTEXT_FIELD(b, c, FSYNR1, APROTNS, v)
+#define SET_AINST(b, c, v) SET_CONTEXT_FIELD(b, c, FSYNR1, AINST, v)
+#define SET_AWRITE(b, c, v) SET_CONTEXT_FIELD(b, c, FSYNR1, AWRITE, v)
+#define SET_ABURST(b, c, v) SET_CONTEXT_FIELD(b, c, FSYNR1, ABURST, v)
+#define SET_ALEN(b, c, v) SET_CONTEXT_FIELD(b, c, FSYNR1, ALEN, v)
+#define SET_FSYNR1_ASIZE(b, c, v) \
+ SET_CONTEXT_FIELD(b, c, FSYNR1, FSYNR1_ASIZE, v)
+#define SET_ALOCK(b, c, v) SET_CONTEXT_FIELD(b, c, FSYNR1, ALOCK, v)
+#define SET_AFULL(b, c, v) SET_CONTEXT_FIELD(b, c, FSYNR1, AFULL, v)
+
+
+/* NMRR */
+#define SET_ICPC0(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, ICPC0, v)
+#define SET_ICPC1(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, ICPC1, v)
+#define SET_ICPC2(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, ICPC2, v)
+#define SET_ICPC3(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, ICPC3, v)
+#define SET_ICPC4(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, ICPC4, v)
+#define SET_ICPC5(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, ICPC5, v)
+#define SET_ICPC6(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, ICPC6, v)
+#define SET_ICPC7(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, ICPC7, v)
+#define SET_OCPC0(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, OCPC0, v)
+#define SET_OCPC1(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, OCPC1, v)
+#define SET_OCPC2(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, OCPC2, v)
+#define SET_OCPC3(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, OCPC3, v)
+#define SET_OCPC4(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, OCPC4, v)
+#define SET_OCPC5(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, OCPC5, v)
+#define SET_OCPC6(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, OCPC6, v)
+#define SET_OCPC7(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, OCPC7, v)
+
+
+/* PAR */
+#define SET_FAULT(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, FAULT, v)
+
+#define SET_FAULT_TF(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, FAULT_TF, v)
+#define SET_FAULT_AFF(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, FAULT_AFF, v)
+#define SET_FAULT_APF(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, FAULT_APF, v)
+#define SET_FAULT_TLBMF(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, FAULT_TLBMF, v)
+#define SET_FAULT_HTWDEEF(b, c, v) \
+ SET_CONTEXT_FIELD(b, c, PAR, FAULT_HTWDEEF, v)
+#define SET_FAULT_HTWSEEF(b, c, v) \
+ SET_CONTEXT_FIELD(b, c, PAR, FAULT_HTWSEEF, v)
+#define SET_FAULT_MHF(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, FAULT_MHF, v)
+#define SET_FAULT_SL(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, FAULT_SL, v)
+#define SET_FAULT_SS(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, FAULT_SS, v)
+
+#define SET_NOFAULT_SS(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, NOFAULT_SS, v)
+#define SET_NOFAULT_MT(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, NOFAULT_MT, v)
+#define SET_NOFAULT_SH(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, NOFAULT_SH, v)
+#define SET_NOFAULT_NS(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, NOFAULT_NS, v)
+#define SET_NOFAULT_NOS(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, NOFAULT_NOS, v)
+#define SET_NPFAULT_PA(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, NPFAULT_PA, v)
+
+
+/* PRRR */
+#define SET_MTC0(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, MTC0, v)
+#define SET_MTC1(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, MTC1, v)
+#define SET_MTC2(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, MTC2, v)
+#define SET_MTC3(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, MTC3, v)
+#define SET_MTC4(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, MTC4, v)
+#define SET_MTC5(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, MTC5, v)
+#define SET_MTC6(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, MTC6, v)
+#define SET_MTC7(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, MTC7, v)
+#define SET_SHDSH0(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, SHDSH0, v)
+#define SET_SHDSH1(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, SHDSH1, v)
+#define SET_SHNMSH0(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, SHNMSH0, v)
+#define SET_SHNMSH1(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, SHNMSH1, v)
+#define SET_NOS0(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, NOS0, v)
+#define SET_NOS1(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, NOS1, v)
+#define SET_NOS2(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, NOS2, v)
+#define SET_NOS3(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, NOS3, v)
+#define SET_NOS4(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, NOS4, v)
+#define SET_NOS5(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, NOS5, v)
+#define SET_NOS6(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, NOS6, v)
+#define SET_NOS7(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, NOS7, v)
+
+
+/* RESUME */
+#define SET_TNR(b, c, v) SET_CONTEXT_FIELD(b, c, RESUME, TNR, v)
+
+
+/* SCTLR */
+#define SET_M(b, c, v) SET_CONTEXT_FIELD(b, c, SCTLR, M, v)
+#define SET_TRE(b, c, v) SET_CONTEXT_FIELD(b, c, SCTLR, TRE, v)
+#define SET_AFE(b, c, v) SET_CONTEXT_FIELD(b, c, SCTLR, AFE, v)
+#define SET_HAF(b, c, v) SET_CONTEXT_FIELD(b, c, SCTLR, HAF, v)
+#define SET_BE(b, c, v) SET_CONTEXT_FIELD(b, c, SCTLR, BE, v)
+#define SET_AFFD(b, c, v) SET_CONTEXT_FIELD(b, c, SCTLR, AFFD, v)
+
+
+/* TLBLKCR */
+#define SET_LKE(b, c, v) SET_CONTEXT_FIELD(b, c, TLBLKCR, LKE, v)
+#define SET_TLBLKCR_TLBIALLCFG(b, c, v) \
+ SET_CONTEXT_FIELD(b, c, TLBLKCR, TLBLCKR_TLBIALLCFG, v)
+#define SET_TLBIASIDCFG(b, c, v) \
+ SET_CONTEXT_FIELD(b, c, TLBLKCR, TLBIASIDCFG, v)
+#define SET_TLBIVAACFG(b, c, v) SET_CONTEXT_FIELD(b, c, TLBLKCR, TLBIVAACFG, v)
+#define SET_FLOOR(b, c, v) SET_CONTEXT_FIELD(b, c, TLBLKCR, FLOOR, v)
+#define SET_VICTIM(b, c, v) SET_CONTEXT_FIELD(b, c, TLBLKCR, VICTIM, v)
+
+
+/* TTBCR */
+#define SET_N(b, c, v) SET_CONTEXT_FIELD(b, c, TTBCR, N, v)
+#define SET_PD0(b, c, v) SET_CONTEXT_FIELD(b, c, TTBCR, PD0, v)
+#define SET_PD1(b, c, v) SET_CONTEXT_FIELD(b, c, TTBCR, PD1, v)
+
+
+/* TTBR0 */
+#define SET_TTBR0_IRGNH(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_IRGNH, v)
+#define SET_TTBR0_SH(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_SH, v)
+#define SET_TTBR0_ORGN(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_ORGN, v)
+#define SET_TTBR0_NOS(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_NOS, v)
+#define SET_TTBR0_IRGNL(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_IRGNL, v)
+#define SET_TTBR0_PA(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_PA, v)
+
+
+/* TTBR1 */
+#define SET_TTBR1_IRGNH(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_IRGNH, v)
+#define SET_TTBR1_SH(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_SH, v)
+#define SET_TTBR1_ORGN(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_ORGN, v)
+#define SET_TTBR1_NOS(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_NOS, v)
+#define SET_TTBR1_IRGNL(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_IRGNL, v)
+#define SET_TTBR1_PA(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_PA, v)
+
+
+/* V2PSR */
+#define SET_HIT(b, c, v) SET_CONTEXT_FIELD(b, c, V2PSR, HIT, v)
+#define SET_INDEX(b, c, v) SET_CONTEXT_FIELD(b, c, V2PSR, INDEX, v)
+
+
+/* V2Pxx UW UR PW PR */
+#define SET_V2PUW_INDEX(b, c, v) SET_CONTEXT_FIELD(b, c, V2PUW, V2Pxx_INDEX, v)
+#define SET_V2PUW_VA(b, c, v) SET_CONTEXT_FIELD(b, c, V2PUW, V2Pxx_VA, v)
+
+#define SET_V2PUR_INDEX(b, c, v) SET_CONTEXT_FIELD(b, c, V2PUR, V2Pxx_INDEX, v)
+#define SET_V2PUR_VA(b, c, v) SET_CONTEXT_FIELD(b, c, V2PUR, V2Pxx_VA, v)
+
+#define SET_V2PPW_INDEX(b, c, v) SET_CONTEXT_FIELD(b, c, V2PPW, V2Pxx_INDEX, v)
+#define SET_V2PPW_VA(b, c, v) SET_CONTEXT_FIELD(b, c, V2PPW, V2Pxx_VA, v)
+
+#define SET_V2PPR_INDEX(b, c, v) SET_CONTEXT_FIELD(b, c, V2PPR, V2Pxx_INDEX, v)
+#define SET_V2PPR_VA(b, c, v) SET_CONTEXT_FIELD(b, c, V2PPR, V2Pxx_VA, v)
+
+
+/* Context Register getters */
+/* ACTLR */
+#define GET_CFERE(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, CFERE)
+#define GET_CFEIE(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, CFEIE)
+#define GET_PTSHCFG(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, PTSHCFG)
+#define GET_RCOSH(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, RCOSH)
+#define GET_RCISH(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, RCISH)
+#define GET_RCNSH(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, RCNSH)
+#define GET_PRIVCFG(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, PRIVCFG)
+#define GET_DNA(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, DNA)
+#define GET_DNLV2PA(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, DNLV2PA)
+#define GET_TLBMCFG(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, TLBMCFG)
+#define GET_CFCFG(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, CFCFG)
+#define GET_TIPCF(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, TIPCF)
+#define GET_V2PCFG(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, V2PCFG)
+#define GET_HUME(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, HUME)
+#define GET_PTMTCFG(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, PTMTCFG)
+#define GET_PTMEMTYPE(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, PTMEMTYPE)
+
+/* BFBCR */
+#define GET_BFBDFE(b, c) GET_CONTEXT_FIELD(b, c, BFBCR, BFBDFE)
+#define GET_BFBSFE(b, c) GET_CONTEXT_FIELD(b, c, BFBCR, BFBSFE)
+#define GET_SFVS(b, c) GET_CONTEXT_FIELD(b, c, BFBCR, SFVS)
+#define GET_FLVIC(b, c) GET_CONTEXT_FIELD(b, c, BFBCR, FLVIC)
+#define GET_SLVIC(b, c) GET_CONTEXT_FIELD(b, c, BFBCR, SLVIC)
+
+
+/* CONTEXTIDR */
+#define GET_CONTEXTIDR_ASID(b, c) \
+ GET_CONTEXT_FIELD(b, c, CONTEXTIDR, CONTEXTIDR_ASID)
+#define GET_CONTEXTIDR_PROCID(b, c) GET_CONTEXT_FIELD(b, c, CONTEXTIDR, PROCID)
+
+
+/* FSR */
+#define GET_TF(b, c) GET_CONTEXT_FIELD(b, c, FSR, TF)
+#define GET_AFF(b, c) GET_CONTEXT_FIELD(b, c, FSR, AFF)
+#define GET_APF(b, c) GET_CONTEXT_FIELD(b, c, FSR, APF)
+#define GET_TLBMF(b, c) GET_CONTEXT_FIELD(b, c, FSR, TLBMF)
+#define GET_HTWDEEF(b, c) GET_CONTEXT_FIELD(b, c, FSR, HTWDEEF)
+#define GET_HTWSEEF(b, c) GET_CONTEXT_FIELD(b, c, FSR, HTWSEEF)
+#define GET_MHF(b, c) GET_CONTEXT_FIELD(b, c, FSR, MHF)
+#define GET_SL(b, c) GET_CONTEXT_FIELD(b, c, FSR, SL)
+#define GET_SS(b, c) GET_CONTEXT_FIELD(b, c, FSR, SS)
+#define GET_MULTI(b, c) GET_CONTEXT_FIELD(b, c, FSR, MULTI)
+
+
+/* FSYNR0 */
+#define GET_AMID(b, c) GET_CONTEXT_FIELD(b, c, FSYNR0, AMID)
+#define GET_APID(b, c) GET_CONTEXT_FIELD(b, c, FSYNR0, APID)
+#define GET_ABID(b, c) GET_CONTEXT_FIELD(b, c, FSYNR0, ABID)
+#define GET_ATID(b, c) GET_CONTEXT_FIELD(b, c, FSYNR0, ATID)
+
+
+/* FSYNR1 */
+#define GET_AMEMTYPE(b, c) GET_CONTEXT_FIELD(b, c, FSYNR1, AMEMTYPE)
+#define GET_ASHARED(b, c) GET_CONTEXT_FIELD(b, c, FSYNR1, ASHARED)
+#define GET_AINNERSHARED(b, c) GET_CONTEXT_FIELD(b, c, FSYNR1, AINNERSHARED)
+#define GET_APRIV(b, c) GET_CONTEXT_FIELD(b, c, FSYNR1, APRIV)
+#define GET_APROTNS(b, c) GET_CONTEXT_FIELD(b, c, FSYNR1, APROTNS)
+#define GET_AINST(b, c) GET_CONTEXT_FIELD(b, c, FSYNR1, AINST)
+#define GET_AWRITE(b, c) GET_CONTEXT_FIELD(b, c, FSYNR1, AWRITE)
+#define GET_ABURST(b, c) GET_CONTEXT_FIELD(b, c, FSYNR1, ABURST)
+#define GET_ALEN(b, c) GET_CONTEXT_FIELD(b, c, FSYNR1, ALEN)
+#define GET_FSYNR1_ASIZE(b, c) GET_CONTEXT_FIELD(b, c, FSYNR1, FSYNR1_ASIZE)
+#define GET_ALOCK(b, c) GET_CONTEXT_FIELD(b, c, FSYNR1, ALOCK)
+#define GET_AFULL(b, c) GET_CONTEXT_FIELD(b, c, FSYNR1, AFULL)
+
+
+/* NMRR */
+#define GET_ICPC0(b, c) GET_CONTEXT_FIELD(b, c, NMRR, ICPC0)
+#define GET_ICPC1(b, c) GET_CONTEXT_FIELD(b, c, NMRR, ICPC1)
+#define GET_ICPC2(b, c) GET_CONTEXT_FIELD(b, c, NMRR, ICPC2)
+#define GET_ICPC3(b, c) GET_CONTEXT_FIELD(b, c, NMRR, ICPC3)
+#define GET_ICPC4(b, c) GET_CONTEXT_FIELD(b, c, NMRR, ICPC4)
+#define GET_ICPC5(b, c) GET_CONTEXT_FIELD(b, c, NMRR, ICPC5)
+#define GET_ICPC6(b, c) GET_CONTEXT_FIELD(b, c, NMRR, ICPC6)
+#define GET_ICPC7(b, c) GET_CONTEXT_FIELD(b, c, NMRR, ICPC7)
+#define GET_OCPC0(b, c) GET_CONTEXT_FIELD(b, c, NMRR, OCPC0)
+#define GET_OCPC1(b, c) GET_CONTEXT_FIELD(b, c, NMRR, OCPC1)
+#define GET_OCPC2(b, c) GET_CONTEXT_FIELD(b, c, NMRR, OCPC2)
+#define GET_OCPC3(b, c) GET_CONTEXT_FIELD(b, c, NMRR, OCPC3)
+#define GET_OCPC4(b, c) GET_CONTEXT_FIELD(b, c, NMRR, OCPC4)
+#define GET_OCPC5(b, c) GET_CONTEXT_FIELD(b, c, NMRR, OCPC5)
+#define GET_OCPC6(b, c) GET_CONTEXT_FIELD(b, c, NMRR, OCPC6)
+#define GET_OCPC7(b, c) GET_CONTEXT_FIELD(b, c, NMRR, OCPC7)
+
+
+/* PAR */
+#define GET_FAULT(b, c) GET_CONTEXT_FIELD(b, c, PAR, FAULT)
+
+#define GET_FAULT_TF(b, c) GET_CONTEXT_FIELD(b, c, PAR, FAULT_TF)
+#define GET_FAULT_AFF(b, c) GET_CONTEXT_FIELD(b, c, PAR, FAULT_AFF)
+#define GET_FAULT_APF(b, c) GET_CONTEXT_FIELD(b, c, PAR, FAULT_APF)
+#define GET_FAULT_TLBMF(b, c) GET_CONTEXT_FIELD(b, c, PAR, FAULT_TLBMF)
+#define GET_FAULT_HTWDEEF(b, c) GET_CONTEXT_FIELD(b, c, PAR, FAULT_HTWDEEF)
+#define GET_FAULT_HTWSEEF(b, c) GET_CONTEXT_FIELD(b, c, PAR, FAULT_HTWSEEF)
+#define GET_FAULT_MHF(b, c) GET_CONTEXT_FIELD(b, c, PAR, FAULT_MHF)
+#define GET_FAULT_SL(b, c) GET_CONTEXT_FIELD(b, c, PAR, FAULT_SL)
+#define GET_FAULT_SS(b, c) GET_CONTEXT_FIELD(b, c, PAR, FAULT_SS)
+
+#define GET_NOFAULT_SS(b, c) GET_CONTEXT_FIELD(b, c, PAR, PAR_NOFAULT_SS)
+#define GET_NOFAULT_MT(b, c) GET_CONTEXT_FIELD(b, c, PAR, PAR_NOFAULT_MT)
+#define GET_NOFAULT_SH(b, c) GET_CONTEXT_FIELD(b, c, PAR, PAR_NOFAULT_SH)
+#define GET_NOFAULT_NS(b, c) GET_CONTEXT_FIELD(b, c, PAR, PAR_NOFAULT_NS)
+#define GET_NOFAULT_NOS(b, c) GET_CONTEXT_FIELD(b, c, PAR, PAR_NOFAULT_NOS)
+#define GET_NPFAULT_PA(b, c) GET_CONTEXT_FIELD(b, c, PAR, PAR_NPFAULT_PA)
+
+
+/* PRRR */
+#define GET_MTC0(b, c) GET_CONTEXT_FIELD(b, c, PRRR, MTC0)
+#define GET_MTC1(b, c) GET_CONTEXT_FIELD(b, c, PRRR, MTC1)
+#define GET_MTC2(b, c) GET_CONTEXT_FIELD(b, c, PRRR, MTC2)
+#define GET_MTC3(b, c) GET_CONTEXT_FIELD(b, c, PRRR, MTC3)
+#define GET_MTC4(b, c) GET_CONTEXT_FIELD(b, c, PRRR, MTC4)
+#define GET_MTC5(b, c) GET_CONTEXT_FIELD(b, c, PRRR, MTC5)
+#define GET_MTC6(b, c) GET_CONTEXT_FIELD(b, c, PRRR, MTC6)
+#define GET_MTC7(b, c) GET_CONTEXT_FIELD(b, c, PRRR, MTC7)
+#define GET_SHDSH0(b, c) GET_CONTEXT_FIELD(b, c, PRRR, SHDSH0)
+#define GET_SHDSH1(b, c) GET_CONTEXT_FIELD(b, c, PRRR, SHDSH1)
+#define GET_SHNMSH0(b, c) GET_CONTEXT_FIELD(b, c, PRRR, SHNMSH0)
+#define GET_SHNMSH1(b, c) GET_CONTEXT_FIELD(b, c, PRRR, SHNMSH1)
+#define GET_NOS0(b, c) GET_CONTEXT_FIELD(b, c, PRRR, NOS0)
+#define GET_NOS1(b, c) GET_CONTEXT_FIELD(b, c, PRRR, NOS1)
+#define GET_NOS2(b, c) GET_CONTEXT_FIELD(b, c, PRRR, NOS2)
+#define GET_NOS3(b, c) GET_CONTEXT_FIELD(b, c, PRRR, NOS3)
+#define GET_NOS4(b, c) GET_CONTEXT_FIELD(b, c, PRRR, NOS4)
+#define GET_NOS5(b, c) GET_CONTEXT_FIELD(b, c, PRRR, NOS5)
+#define GET_NOS6(b, c) GET_CONTEXT_FIELD(b, c, PRRR, NOS6)
+#define GET_NOS7(b, c) GET_CONTEXT_FIELD(b, c, PRRR, NOS7)
+
+
+/* RESUME */
+#define GET_TNR(b, c) GET_CONTEXT_FIELD(b, c, RESUME, TNR)
+
+
+/* SCTLR */
+#define GET_M(b, c) GET_CONTEXT_FIELD(b, c, SCTLR, M)
+#define GET_TRE(b, c) GET_CONTEXT_FIELD(b, c, SCTLR, TRE)
+#define GET_AFE(b, c) GET_CONTEXT_FIELD(b, c, SCTLR, AFE)
+#define GET_HAF(b, c) GET_CONTEXT_FIELD(b, c, SCTLR, HAF)
+#define GET_BE(b, c) GET_CONTEXT_FIELD(b, c, SCTLR, BE)
+#define GET_AFFD(b, c) GET_CONTEXT_FIELD(b, c, SCTLR, AFFD)
+
+
+/* TLBLKCR */
+#define GET_LKE(b, c) GET_CONTEXT_FIELD(b, c, TLBLKCR, LKE)
+#define GET_TLBLCKR_TLBIALLCFG(b, c) \
+ GET_CONTEXT_FIELD(b, c, TLBLKCR, TLBLCKR_TLBIALLCFG)
+#define GET_TLBIASIDCFG(b, c) GET_CONTEXT_FIELD(b, c, TLBLKCR, TLBIASIDCFG)
+#define GET_TLBIVAACFG(b, c) GET_CONTEXT_FIELD(b, c, TLBLKCR, TLBIVAACFG)
+#define GET_FLOOR(b, c) GET_CONTEXT_FIELD(b, c, TLBLKCR, FLOOR)
+#define GET_VICTIM(b, c) GET_CONTEXT_FIELD(b, c, TLBLKCR, VICTIM)
+
+
+/* TTBCR */
+#define GET_N(b, c) GET_CONTEXT_FIELD(b, c, TTBCR, N)
+#define GET_PD0(b, c) GET_CONTEXT_FIELD(b, c, TTBCR, PD0)
+#define GET_PD1(b, c) GET_CONTEXT_FIELD(b, c, TTBCR, PD1)
+
+
+/* TTBR0 */
+#define GET_TTBR0_IRGNH(b, c) GET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_IRGNH)
+#define GET_TTBR0_SH(b, c) GET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_SH)
+#define GET_TTBR0_ORGN(b, c) GET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_ORGN)
+#define GET_TTBR0_NOS(b, c) GET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_NOS)
+#define GET_TTBR0_IRGNL(b, c) GET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_IRGNL)
+#define GET_TTBR0_PA(b, c) GET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_PA)
+
+
+/* TTBR1 */
+#define GET_TTBR1_IRGNH(b, c) GET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_IRGNH)
+#define GET_TTBR1_SH(b, c) GET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_SH)
+#define GET_TTBR1_ORGN(b, c) GET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_ORGN)
+#define GET_TTBR1_NOS(b, c) GET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_NOS)
+#define GET_TTBR1_IRGNL(b, c) GET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_IRGNL)
+#define GET_TTBR1_PA(b, c) GET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_PA)
+
+
+/* V2PSR */
+#define GET_HIT(b, c) GET_CONTEXT_FIELD(b, c, V2PSR, HIT)
+#define GET_INDEX(b, c) GET_CONTEXT_FIELD(b, c, V2PSR, INDEX)
+
+
+/* V2Pxx UW UR PW PR */
+#define GET_V2PUW_INDEX(b, c) GET_CONTEXT_FIELD(b, c, V2PUW, V2Pxx_INDEX)
+#define GET_V2PUW_VA(b, c) GET_CONTEXT_FIELD(b, c, V2PUW, V2Pxx_VA)
+
+#define GET_V2PUR_INDEX(b, c) GET_CONTEXT_FIELD(b, c, V2PUR, V2Pxx_INDEX)
+#define GET_V2PUR_VA(b, c) GET_CONTEXT_FIELD(b, c, V2PUR, V2Pxx_VA)
+
+#define GET_V2PPW_INDEX(b, c) GET_CONTEXT_FIELD(b, c, V2PPW, V2Pxx_INDEX)
+#define GET_V2PPW_VA(b, c) GET_CONTEXT_FIELD(b, c, V2PPW, V2Pxx_VA)
+
+#define GET_V2PPR_INDEX(b, c) GET_CONTEXT_FIELD(b, c, V2PPR, V2Pxx_INDEX)
+#define GET_V2PPR_VA(b, c) GET_CONTEXT_FIELD(b, c, V2PPR, V2Pxx_VA)
+
+
+/* Global Registers */
+#define M2VCBR_N (0xFF000)
+#define CBACR_N (0xFF800)
+#define TLBRSW (0xFFE00)
+#define TLBTR0 (0xFFE80)
+#define TLBTR1 (0xFFE84)
+#define TLBTR2 (0xFFE88)
+#define TESTBUSCR (0xFFE8C)
+#define GLOBAL_TLBIALL (0xFFF00)
+#define TLBIVMID (0xFFF04)
+#define CR (0xFFF80)
+#define EAR (0xFFF84)
+#define ESR (0xFFF88)
+#define ESRRESTORE (0xFFF8C)
+#define ESYNR0 (0xFFF90)
+#define ESYNR1 (0xFFF94)
+#define REV (0xFFFF4)
+#define IDR (0xFFFF8)
+#define RPU_ACR (0xFFFFC)
+
+
+/* Context Bank Registers */
+#define SCTLR (0x000)
+#define ACTLR (0x004)
+#define CONTEXTIDR (0x008)
+#define TTBR0 (0x010)
+#define TTBR1 (0x014)
+#define TTBCR (0x018)
+#define PAR (0x01C)
+#define FSR (0x020)
+#define FSRRESTORE (0x024)
+#define FAR (0x028)
+#define FSYNR0 (0x02C)
+#define FSYNR1 (0x030)
+#define PRRR (0x034)
+#define NMRR (0x038)
+#define TLBLCKR (0x03C)
+#define V2PSR (0x040)
+#define TLBFLPTER (0x044)
+#define TLBSLPTER (0x048)
+#define BFBCR (0x04C)
+#define CTX_TLBIALL (0x800)
+#define TLBIASID (0x804)
+#define TLBIVA (0x808)
+#define TLBIVAA (0x80C)
+#define V2PPR (0x810)
+#define V2PPW (0x814)
+#define V2PUR (0x818)
+#define V2PUW (0x81C)
+#define RESUME (0x820)
+
+
+/* Global Register Fields */
+/* CBACRn */
+#define RWVMID (RWVMID_MASK << RWVMID_SHIFT)
+#define RWE (RWE_MASK << RWE_SHIFT)
+#define RWGE (RWGE_MASK << RWGE_SHIFT)
+#define CBVMID (CBVMID_MASK << CBVMID_SHIFT)
+#define IRPTNDX (IRPTNDX_MASK << IRPTNDX_SHIFT)
+
+
+/* CR */
+#define RPUE (RPUE_MASK << RPUE_SHIFT)
+#define RPUERE (RPUERE_MASK << RPUERE_SHIFT)
+#define RPUEIE (RPUEIE_MASK << RPUEIE_SHIFT)
+#define DCDEE (DCDEE_MASK << DCDEE_SHIFT)
+#define CLIENTPD (CLIENTPD_MASK << CLIENTPD_SHIFT)
+#define STALLD (STALLD_MASK << STALLD_SHIFT)
+#define TLBLKCRWE (TLBLKCRWE_MASK << TLBLKCRWE_SHIFT)
+#define CR_TLBIALLCFG (CR_TLBIALLCFG_MASK << CR_TLBIALLCFG_SHIFT)
+#define TLBIVMIDCFG (TLBIVMIDCFG_MASK << TLBIVMIDCFG_SHIFT)
+#define CR_HUME (CR_HUME_MASK << CR_HUME_SHIFT)
+
+
+/* ESR */
+#define CFG (CFG_MASK << CFG_SHIFT)
+#define BYPASS (BYPASS_MASK << BYPASS_SHIFT)
+#define ESR_MULTI (ESR_MULTI_MASK << ESR_MULTI_SHIFT)
+
+
+/* ESYNR0 */
+#define ESYNR0_AMID (ESYNR0_AMID_MASK << ESYNR0_AMID_SHIFT)
+#define ESYNR0_APID (ESYNR0_APID_MASK << ESYNR0_APID_SHIFT)
+#define ESYNR0_ABID (ESYNR0_ABID_MASK << ESYNR0_ABID_SHIFT)
+#define ESYNR0_AVMID (ESYNR0_AVMID_MASK << ESYNR0_AVMID_SHIFT)
+#define ESYNR0_ATID (ESYNR0_ATID_MASK << ESYNR0_ATID_SHIFT)
+
+
+/* ESYNR1 */
+#define ESYNR1_AMEMTYPE (ESYNR1_AMEMTYPE_MASK << ESYNR1_AMEMTYPE_SHIFT)
+#define ESYNR1_ASHARED (ESYNR1_ASHARED_MASK << ESYNR1_ASHARED_SHIFT)
+#define ESYNR1_AINNERSHARED (ESYNR1_AINNERSHARED_MASK<< \
+ ESYNR1_AINNERSHARED_SHIFT)
+#define ESYNR1_APRIV (ESYNR1_APRIV_MASK << ESYNR1_APRIV_SHIFT)
+#define ESYNR1_APROTNS (ESYNR1_APROTNS_MASK << ESYNR1_APROTNS_SHIFT)
+#define ESYNR1_AINST (ESYNR1_AINST_MASK << ESYNR1_AINST_SHIFT)
+#define ESYNR1_AWRITE (ESYNR1_AWRITE_MASK << ESYNR1_AWRITE_SHIFT)
+#define ESYNR1_ABURST (ESYNR1_ABURST_MASK << ESYNR1_ABURST_SHIFT)
+#define ESYNR1_ALEN (ESYNR1_ALEN_MASK << ESYNR1_ALEN_SHIFT)
+#define ESYNR1_ASIZE (ESYNR1_ASIZE_MASK << ESYNR1_ASIZE_SHIFT)
+#define ESYNR1_ALOCK (ESYNR1_ALOCK_MASK << ESYNR1_ALOCK_SHIFT)
+#define ESYNR1_AOOO (ESYNR1_AOOO_MASK << ESYNR1_AOOO_SHIFT)
+#define ESYNR1_AFULL (ESYNR1_AFULL_MASK << ESYNR1_AFULL_SHIFT)
+#define ESYNR1_AC (ESYNR1_AC_MASK << ESYNR1_AC_SHIFT)
+#define ESYNR1_DCD (ESYNR1_DCD_MASK << ESYNR1_DCD_SHIFT)
+
+
+/* IDR */
+#define NM2VCBMT (NM2VCBMT_MASK << NM2VCBMT_SHIFT)
+#define HTW (HTW_MASK << HTW_SHIFT)
+#define HUM (HUM_MASK << HUM_SHIFT)
+#define TLBSIZE (TLBSIZE_MASK << TLBSIZE_SHIFT)
+#define NCB (NCB_MASK << NCB_SHIFT)
+#define NIRPT (NIRPT_MASK << NIRPT_SHIFT)
+
+
+/* M2VCBRn */
+#define VMID (VMID_MASK << VMID_SHIFT)
+#define CBNDX (CBNDX_MASK << CBNDX_SHIFT)
+#define BYPASSD (BYPASSD_MASK << BYPASSD_SHIFT)
+#define BPRCOSH (BPRCOSH_MASK << BPRCOSH_SHIFT)
+#define BPRCISH (BPRCISH_MASK << BPRCISH_SHIFT)
+#define BPRCNSH (BPRCNSH_MASK << BPRCNSH_SHIFT)
+#define BPSHCFG (BPSHCFG_MASK << BPSHCFG_SHIFT)
+#define NSCFG (NSCFG_MASK << NSCFG_SHIFT)
+#define BPMTCFG (BPMTCFG_MASK << BPMTCFG_SHIFT)
+#define BPMEMTYPE (BPMEMTYPE_MASK << BPMEMTYPE_SHIFT)
+
+
+/* REV */
+#define IDR_MINOR (MINOR_MASK << MINOR_SHIFT)
+#define IDR_MAJOR (MAJOR_MASK << MAJOR_SHIFT)
+
+
+/* TESTBUSCR */
+#define TBE (TBE_MASK << TBE_SHIFT)
+#define SPDMBE (SPDMBE_MASK << SPDMBE_SHIFT)
+#define WGSEL (WGSEL_MASK << WGSEL_SHIFT)
+#define TBLSEL (TBLSEL_MASK << TBLSEL_SHIFT)
+#define TBHSEL (TBHSEL_MASK << TBHSEL_SHIFT)
+#define SPDM0SEL (SPDM0SEL_MASK << SPDM0SEL_SHIFT)
+#define SPDM1SEL (SPDM1SEL_MASK << SPDM1SEL_SHIFT)
+#define SPDM2SEL (SPDM2SEL_MASK << SPDM2SEL_SHIFT)
+#define SPDM3SEL (SPDM3SEL_MASK << SPDM3SEL_SHIFT)
+
+
+/* TLBIVMID */
+#define TLBIVMID_VMID (TLBIVMID_VMID_MASK << TLBIVMID_VMID_SHIFT)
+
+
+/* TLBRSW */
+#define TLBRSW_INDEX (TLBRSW_INDEX_MASK << TLBRSW_INDEX_SHIFT)
+#define TLBBFBS (TLBBFBS_MASK << TLBBFBS_SHIFT)
+
+
+/* TLBTR0 */
+#define PR (PR_MASK << PR_SHIFT)
+#define PW (PW_MASK << PW_SHIFT)
+#define UR (UR_MASK << UR_SHIFT)
+#define UW (UW_MASK << UW_SHIFT)
+#define XN (XN_MASK << XN_SHIFT)
+#define NSDESC (NSDESC_MASK << NSDESC_SHIFT)
+#define ISH (ISH_MASK << ISH_SHIFT)
+#define SH (SH_MASK << SH_SHIFT)
+#define MT (MT_MASK << MT_SHIFT)
+#define DPSIZR (DPSIZR_MASK << DPSIZR_SHIFT)
+#define DPSIZC (DPSIZC_MASK << DPSIZC_SHIFT)
+
+
+/* TLBTR1 */
+#define TLBTR1_VMID (TLBTR1_VMID_MASK << TLBTR1_VMID_SHIFT)
+#define TLBTR1_PA (TLBTR1_PA_MASK << TLBTR1_PA_SHIFT)
+
+
+/* TLBTR2 */
+#define TLBTR2_ASID (TLBTR2_ASID_MASK << TLBTR2_ASID_SHIFT)
+#define TLBTR2_V (TLBTR2_V_MASK << TLBTR2_V_SHIFT)
+#define TLBTR2_NSTID (TLBTR2_NSTID_MASK << TLBTR2_NSTID_SHIFT)
+#define TLBTR2_NV (TLBTR2_NV_MASK << TLBTR2_NV_SHIFT)
+#define TLBTR2_VA (TLBTR2_VA_MASK << TLBTR2_VA_SHIFT)
+
+
+/* Context Register Fields */
+/* ACTLR */
+#define CFERE (CFERE_MASK << CFERE_SHIFT)
+#define CFEIE (CFEIE_MASK << CFEIE_SHIFT)
+#define PTSHCFG (PTSHCFG_MASK << PTSHCFG_SHIFT)
+#define RCOSH (RCOSH_MASK << RCOSH_SHIFT)
+#define RCISH (RCISH_MASK << RCISH_SHIFT)
+#define RCNSH (RCNSH_MASK << RCNSH_SHIFT)
+#define PRIVCFG (PRIVCFG_MASK << PRIVCFG_SHIFT)
+#define DNA (DNA_MASK << DNA_SHIFT)
+#define DNLV2PA (DNLV2PA_MASK << DNLV2PA_SHIFT)
+#define TLBMCFG (TLBMCFG_MASK << TLBMCFG_SHIFT)
+#define CFCFG (CFCFG_MASK << CFCFG_SHIFT)
+#define TIPCF (TIPCF_MASK << TIPCF_SHIFT)
+#define V2PCFG (V2PCFG_MASK << V2PCFG_SHIFT)
+#define HUME (HUME_MASK << HUME_SHIFT)
+#define PTMTCFG (PTMTCFG_MASK << PTMTCFG_SHIFT)
+#define PTMEMTYPE (PTMEMTYPE_MASK << PTMEMTYPE_SHIFT)
+
+
+/* BFBCR */
+#define BFBDFE (BFBDFE_MASK << BFBDFE_SHIFT)
+#define BFBSFE (BFBSFE_MASK << BFBSFE_SHIFT)
+#define SFVS (SFVS_MASK << SFVS_SHIFT)
+#define FLVIC (FLVIC_MASK << FLVIC_SHIFT)
+#define SLVIC (SLVIC_MASK << SLVIC_SHIFT)
+
+
+/* CONTEXTIDR */
+#define CONTEXTIDR_ASID (CONTEXTIDR_ASID_MASK << CONTEXTIDR_ASID_SHIFT)
+#define PROCID (PROCID_MASK << PROCID_SHIFT)
+
+
+/* FSR */
+#define TF (TF_MASK << TF_SHIFT)
+#define AFF (AFF_MASK << AFF_SHIFT)
+#define APF (APF_MASK << APF_SHIFT)
+#define TLBMF (TLBMF_MASK << TLBMF_SHIFT)
+#define HTWDEEF (HTWDEEF_MASK << HTWDEEF_SHIFT)
+#define HTWSEEF (HTWSEEF_MASK << HTWSEEF_SHIFT)
+#define MHF (MHF_MASK << MHF_SHIFT)
+#define SL (SL_MASK << SL_SHIFT)
+#define SS (SS_MASK << SS_SHIFT)
+#define MULTI (MULTI_MASK << MULTI_SHIFT)
+
+
+/* FSYNR0 */
+#define AMID (AMID_MASK << AMID_SHIFT)
+#define APID (APID_MASK << APID_SHIFT)
+#define ABID (ABID_MASK << ABID_SHIFT)
+#define ATID (ATID_MASK << ATID_SHIFT)
+
+
+/* FSYNR1 */
+#define AMEMTYPE (AMEMTYPE_MASK << AMEMTYPE_SHIFT)
+#define ASHARED (ASHARED_MASK << ASHARED_SHIFT)
+#define AINNERSHARED (AINNERSHARED_MASK << AINNERSHARED_SHIFT)
+#define APRIV (APRIV_MASK << APRIV_SHIFT)
+#define APROTNS (APROTNS_MASK << APROTNS_SHIFT)
+#define AINST (AINST_MASK << AINST_SHIFT)
+#define AWRITE (AWRITE_MASK << AWRITE_SHIFT)
+#define ABURST (ABURST_MASK << ABURST_SHIFT)
+#define ALEN (ALEN_MASK << ALEN_SHIFT)
+#define FSYNR1_ASIZE (FSYNR1_ASIZE_MASK << FSYNR1_ASIZE_SHIFT)
+#define ALOCK (ALOCK_MASK << ALOCK_SHIFT)
+#define AFULL (AFULL_MASK << AFULL_SHIFT)
+
+
+/* NMRR */
+#define ICPC0 (ICPC0_MASK << ICPC0_SHIFT)
+#define ICPC1 (ICPC1_MASK << ICPC1_SHIFT)
+#define ICPC2 (ICPC2_MASK << ICPC2_SHIFT)
+#define ICPC3 (ICPC3_MASK << ICPC3_SHIFT)
+#define ICPC4 (ICPC4_MASK << ICPC4_SHIFT)
+#define ICPC5 (ICPC5_MASK << ICPC5_SHIFT)
+#define ICPC6 (ICPC6_MASK << ICPC6_SHIFT)
+#define ICPC7 (ICPC7_MASK << ICPC7_SHIFT)
+#define OCPC0 (OCPC0_MASK << OCPC0_SHIFT)
+#define OCPC1 (OCPC1_MASK << OCPC1_SHIFT)
+#define OCPC2 (OCPC2_MASK << OCPC2_SHIFT)
+#define OCPC3 (OCPC3_MASK << OCPC3_SHIFT)
+#define OCPC4 (OCPC4_MASK << OCPC4_SHIFT)
+#define OCPC5 (OCPC5_MASK << OCPC5_SHIFT)
+#define OCPC6 (OCPC6_MASK << OCPC6_SHIFT)
+#define OCPC7 (OCPC7_MASK << OCPC7_SHIFT)
+
+
+/* PAR */
+#define FAULT (FAULT_MASK << FAULT_SHIFT)
+/* If a fault is present, these are the
+same as the fault fields in the FAR */
+#define FAULT_TF (FAULT_TF_MASK << FAULT_TF_SHIFT)
+#define FAULT_AFF (FAULT_AFF_MASK << FAULT_AFF_SHIFT)
+#define FAULT_APF (FAULT_APF_MASK << FAULT_APF_SHIFT)
+#define FAULT_TLBMF (FAULT_TLBMF_MASK << FAULT_TLBMF_SHIFT)
+#define FAULT_HTWDEEF (FAULT_HTWDEEF_MASK << FAULT_HTWDEEF_SHIFT)
+#define FAULT_HTWSEEF (FAULT_HTWSEEF_MASK << FAULT_HTWSEEF_SHIFT)
+#define FAULT_MHF (FAULT_MHF_MASK << FAULT_MHF_SHIFT)
+#define FAULT_SL (FAULT_SL_MASK << FAULT_SL_SHIFT)
+#define FAULT_SS (FAULT_SS_MASK << FAULT_SS_SHIFT)
+
+/* If NO fault is present, the following fields are in effect */
+/* (FAULT remains as before) */
+#define PAR_NOFAULT_SS (PAR_NOFAULT_SS_MASK << PAR_NOFAULT_SS_SHIFT)
+#define PAR_NOFAULT_MT (PAR_NOFAULT_MT_MASK << PAR_NOFAULT_MT_SHIFT)
+#define PAR_NOFAULT_SH (PAR_NOFAULT_SH_MASK << PAR_NOFAULT_SH_SHIFT)
+#define PAR_NOFAULT_NS (PAR_NOFAULT_NS_MASK << PAR_NOFAULT_NS_SHIFT)
+#define PAR_NOFAULT_NOS (PAR_NOFAULT_NOS_MASK << PAR_NOFAULT_NOS_SHIFT)
+#define PAR_NPFAULT_PA (PAR_NPFAULT_PA_MASK << PAR_NPFAULT_PA_SHIFT)
+
+
+/* PRRR */
+#define MTC0 (MTC0_MASK << MTC0_SHIFT)
+#define MTC1 (MTC1_MASK << MTC1_SHIFT)
+#define MTC2 (MTC2_MASK << MTC2_SHIFT)
+#define MTC3 (MTC3_MASK << MTC3_SHIFT)
+#define MTC4 (MTC4_MASK << MTC4_SHIFT)
+#define MTC5 (MTC5_MASK << MTC5_SHIFT)
+#define MTC6 (MTC6_MASK << MTC6_SHIFT)
+#define MTC7 (MTC7_MASK << MTC7_SHIFT)
+#define SHDSH0 (SHDSH0_MASK << SHDSH0_SHIFT)
+#define SHDSH1 (SHDSH1_MASK << SHDSH1_SHIFT)
+#define SHNMSH0 (SHNMSH0_MASK << SHNMSH0_SHIFT)
+#define SHNMSH1 (SHNMSH1_MASK << SHNMSH1_SHIFT)
+#define NOS0 (NOS0_MASK << NOS0_SHIFT)
+#define NOS1 (NOS1_MASK << NOS1_SHIFT)
+#define NOS2 (NOS2_MASK << NOS2_SHIFT)
+#define NOS3 (NOS3_MASK << NOS3_SHIFT)
+#define NOS4 (NOS4_MASK << NOS4_SHIFT)
+#define NOS5 (NOS5_MASK << NOS5_SHIFT)
+#define NOS6 (NOS6_MASK << NOS6_SHIFT)
+#define NOS7 (NOS7_MASK << NOS7_SHIFT)
+
+
+/* RESUME */
+#define TNR (TNR_MASK << TNR_SHIFT)
+
+
+/* SCTLR */
+#define M (M_MASK << M_SHIFT)
+#define TRE (TRE_MASK << TRE_SHIFT)
+#define AFE (AFE_MASK << AFE_SHIFT)
+#define HAF (HAF_MASK << HAF_SHIFT)
+#define BE (BE_MASK << BE_SHIFT)
+#define AFFD (AFFD_MASK << AFFD_SHIFT)
+
+
+/* TLBIASID */
+#define TLBIASID_ASID (TLBIASID_ASID_MASK << TLBIASID_ASID_SHIFT)
+
+
+/* TLBIVA */
+#define TLBIVA_ASID (TLBIVA_ASID_MASK << TLBIVA_ASID_SHIFT)
+#define TLBIVA_VA (TLBIVA_VA_MASK << TLBIVA_VA_SHIFT)
+
+
+/* TLBIVAA */
+#define TLBIVAA_VA (TLBIVAA_VA_MASK << TLBIVAA_VA_SHIFT)
+
+
+/* TLBLCKR */
+#define LKE (LKE_MASK << LKE_SHIFT)
+#define TLBLCKR_TLBIALLCFG (TLBLCKR_TLBIALLCFG_MASK<<TLBLCKR_TLBIALLCFG_SHIFT)
+#define TLBIASIDCFG (TLBIASIDCFG_MASK << TLBIASIDCFG_SHIFT)
+#define TLBIVAACFG (TLBIVAACFG_MASK << TLBIVAACFG_SHIFT)
+#define FLOOR (FLOOR_MASK << FLOOR_SHIFT)
+#define VICTIM (VICTIM_MASK << VICTIM_SHIFT)
+
+
+/* TTBCR */
+#define N (N_MASK << N_SHIFT)
+#define PD0 (PD0_MASK << PD0_SHIFT)
+#define PD1 (PD1_MASK << PD1_SHIFT)
+
+
+/* TTBR0 */
+#define TTBR0_IRGNH (TTBR0_IRGNH_MASK << TTBR0_IRGNH_SHIFT)
+#define TTBR0_SH (TTBR0_SH_MASK << TTBR0_SH_SHIFT)
+#define TTBR0_ORGN (TTBR0_ORGN_MASK << TTBR0_ORGN_SHIFT)
+#define TTBR0_NOS (TTBR0_NOS_MASK << TTBR0_NOS_SHIFT)
+#define TTBR0_IRGNL (TTBR0_IRGNL_MASK << TTBR0_IRGNL_SHIFT)
+#define TTBR0_PA (TTBR0_PA_MASK << TTBR0_PA_SHIFT)
+
+
+/* TTBR1 */
+#define TTBR1_IRGNH (TTBR1_IRGNH_MASK << TTBR1_IRGNH_SHIFT)
+#define TTBR1_SH (TTBR1_SH_MASK << TTBR1_SH_SHIFT)
+#define TTBR1_ORGN (TTBR1_ORGN_MASK << TTBR1_ORGN_SHIFT)
+#define TTBR1_NOS (TTBR1_NOS_MASK << TTBR1_NOS_SHIFT)
+#define TTBR1_IRGNL (TTBR1_IRGNL_MASK << TTBR1_IRGNL_SHIFT)
+#define TTBR1_PA (TTBR1_PA_MASK << TTBR1_PA_SHIFT)
+
+
+/* V2PSR */
+#define HIT (HIT_MASK << HIT_SHIFT)
+#define INDEX (INDEX_MASK << INDEX_SHIFT)
+
+
+/* V2Pxx */
+#define V2Pxx_INDEX (V2Pxx_INDEX_MASK << V2Pxx_INDEX_SHIFT)
+#define V2Pxx_VA (V2Pxx_VA_MASK << V2Pxx_VA_SHIFT)
+
+
+/* Global Register Masks */
+/* CBACRn */
+#define RWVMID_MASK 0x1F
+#define RWE_MASK 0x01
+#define RWGE_MASK 0x01
+#define CBVMID_MASK 0x1F
+#define IRPTNDX_MASK 0xFF
+
+
+/* CR */
+#define RPUE_MASK 0x01
+#define RPUERE_MASK 0x01
+#define RPUEIE_MASK 0x01
+#define DCDEE_MASK 0x01
+#define CLIENTPD_MASK 0x01
+#define STALLD_MASK 0x01
+#define TLBLKCRWE_MASK 0x01
+#define CR_TLBIALLCFG_MASK 0x01
+#define TLBIVMIDCFG_MASK 0x01
+#define CR_HUME_MASK 0x01
+
+
+/* ESR */
+#define CFG_MASK 0x01
+#define BYPASS_MASK 0x01
+#define ESR_MULTI_MASK 0x01
+
+
+/* ESYNR0 */
+#define ESYNR0_AMID_MASK 0xFF
+#define ESYNR0_APID_MASK 0x1F
+#define ESYNR0_ABID_MASK 0x07
+#define ESYNR0_AVMID_MASK 0x1F
+#define ESYNR0_ATID_MASK 0xFF
+
+
+/* ESYNR1 */
+#define ESYNR1_AMEMTYPE_MASK 0x07
+#define ESYNR1_ASHARED_MASK 0x01
+#define ESYNR1_AINNERSHARED_MASK 0x01
+#define ESYNR1_APRIV_MASK 0x01
+#define ESYNR1_APROTNS_MASK 0x01
+#define ESYNR1_AINST_MASK 0x01
+#define ESYNR1_AWRITE_MASK 0x01
+#define ESYNR1_ABURST_MASK 0x01
+#define ESYNR1_ALEN_MASK 0x0F
+#define ESYNR1_ASIZE_MASK 0x01
+#define ESYNR1_ALOCK_MASK 0x03
+#define ESYNR1_AOOO_MASK 0x01
+#define ESYNR1_AFULL_MASK 0x01
+#define ESYNR1_AC_MASK 0x01
+#define ESYNR1_DCD_MASK 0x01
+
+
+/* IDR */
+#define NM2VCBMT_MASK 0x1FF
+#define HTW_MASK 0x01
+#define HUM_MASK 0x01
+#define TLBSIZE_MASK 0x0F
+#define NCB_MASK 0xFF
+#define NIRPT_MASK 0xFF
+
+
+/* M2VCBRn */
+#define VMID_MASK 0x1F
+#define CBNDX_MASK 0xFF
+#define BYPASSD_MASK 0x01
+#define BPRCOSH_MASK 0x01
+#define BPRCISH_MASK 0x01
+#define BPRCNSH_MASK 0x01
+#define BPSHCFG_MASK 0x03
+#define NSCFG_MASK 0x03
+#define BPMTCFG_MASK 0x01
+#define BPMEMTYPE_MASK 0x07
+
+
+/* REV */
+#define MINOR_MASK 0x0F
+#define MAJOR_MASK 0x0F
+
+
+/* TESTBUSCR */
+#define TBE_MASK 0x01
+#define SPDMBE_MASK 0x01
+#define WGSEL_MASK 0x03
+#define TBLSEL_MASK 0x03
+#define TBHSEL_MASK 0x03
+#define SPDM0SEL_MASK 0x0F
+#define SPDM1SEL_MASK 0x0F
+#define SPDM2SEL_MASK 0x0F
+#define SPDM3SEL_MASK 0x0F
+
+
+/* TLBIMID */
+#define TLBIVMID_VMID_MASK 0x1F
+
+
+/* TLBRSW */
+#define TLBRSW_INDEX_MASK 0xFF
+#define TLBBFBS_MASK 0x03
+
+
+/* TLBTR0 */
+#define PR_MASK 0x01
+#define PW_MASK 0x01
+#define UR_MASK 0x01
+#define UW_MASK 0x01
+#define XN_MASK 0x01
+#define NSDESC_MASK 0x01
+#define ISH_MASK 0x01
+#define SH_MASK 0x01
+#define MT_MASK 0x07
+#define DPSIZR_MASK 0x07
+#define DPSIZC_MASK 0x07
+
+
+/* TLBTR1 */
+#define TLBTR1_VMID_MASK 0x1F
+#define TLBTR1_PA_MASK 0x000FFFFF
+
+
+/* TLBTR2 */
+#define TLBTR2_ASID_MASK 0xFF
+#define TLBTR2_V_MASK 0x01
+#define TLBTR2_NSTID_MASK 0x01
+#define TLBTR2_NV_MASK 0x01
+#define TLBTR2_VA_MASK 0x000FFFFF
+
+
+/* Global Register Shifts */
+/* CBACRn */
+#define RWVMID_SHIFT 0
+#define RWE_SHIFT 8
+#define RWGE_SHIFT 9
+#define CBVMID_SHIFT 16
+#define IRPTNDX_SHIFT 24
+
+
+/* CR */
+#define RPUE_SHIFT 0
+#define RPUERE_SHIFT 1
+#define RPUEIE_SHIFT 2
+#define DCDEE_SHIFT 3
+#define CLIENTPD_SHIFT 4
+#define STALLD_SHIFT 5
+#define TLBLKCRWE_SHIFT 6
+#define CR_TLBIALLCFG_SHIFT 7
+#define TLBIVMIDCFG_SHIFT 8
+#define CR_HUME_SHIFT 9
+
+
+/* ESR */
+#define CFG_SHIFT 0
+#define BYPASS_SHIFT 1
+#define ESR_MULTI_SHIFT 31
+
+
+/* ESYNR0 */
+#define ESYNR0_AMID_SHIFT 0
+#define ESYNR0_APID_SHIFT 8
+#define ESYNR0_ABID_SHIFT 13
+#define ESYNR0_AVMID_SHIFT 16
+#define ESYNR0_ATID_SHIFT 24
+
+
+/* ESYNR1 */
+#define ESYNR1_AMEMTYPE_SHIFT 0
+#define ESYNR1_ASHARED_SHIFT 3
+#define ESYNR1_AINNERSHARED_SHIFT 4
+#define ESYNR1_APRIV_SHIFT 5
+#define ESYNR1_APROTNS_SHIFT 6
+#define ESYNR1_AINST_SHIFT 7
+#define ESYNR1_AWRITE_SHIFT 8
+#define ESYNR1_ABURST_SHIFT 10
+#define ESYNR1_ALEN_SHIFT 12
+#define ESYNR1_ASIZE_SHIFT 16
+#define ESYNR1_ALOCK_SHIFT 20
+#define ESYNR1_AOOO_SHIFT 22
+#define ESYNR1_AFULL_SHIFT 24
+#define ESYNR1_AC_SHIFT 30
+#define ESYNR1_DCD_SHIFT 31
+
+
+/* IDR */
+#define NM2VCBMT_SHIFT 0
+#define HTW_SHIFT 9
+#define HUM_SHIFT 10
+#define TLBSIZE_SHIFT 12
+#define NCB_SHIFT 16
+#define NIRPT_SHIFT 24
+
+
+/* M2VCBRn */
+#define VMID_SHIFT 0
+#define CBNDX_SHIFT 8
+#define BYPASSD_SHIFT 16
+#define BPRCOSH_SHIFT 17
+#define BPRCISH_SHIFT 18
+#define BPRCNSH_SHIFT 19
+#define BPSHCFG_SHIFT 20
+#define NSCFG_SHIFT 22
+#define BPMTCFG_SHIFT 24
+#define BPMEMTYPE_SHIFT 25
+
+
+/* REV */
+#define MINOR_SHIFT 0
+#define MAJOR_SHIFT 4
+
+
+/* TESTBUSCR */
+#define TBE_SHIFT 0
+#define SPDMBE_SHIFT 1
+#define WGSEL_SHIFT 8
+#define TBLSEL_SHIFT 12
+#define TBHSEL_SHIFT 14
+#define SPDM0SEL_SHIFT 16
+#define SPDM1SEL_SHIFT 20
+#define SPDM2SEL_SHIFT 24
+#define SPDM3SEL_SHIFT 28
+
+
+/* TLBIMID */
+#define TLBIVMID_VMID_SHIFT 0
+
+
+/* TLBRSW */
+#define TLBRSW_INDEX_SHIFT 0
+#define TLBBFBS_SHIFT 8
+
+
+/* TLBTR0 */
+#define PR_SHIFT 0
+#define PW_SHIFT 1
+#define UR_SHIFT 2
+#define UW_SHIFT 3
+#define XN_SHIFT 4
+#define NSDESC_SHIFT 6
+#define ISH_SHIFT 7
+#define SH_SHIFT 8
+#define MT_SHIFT 9
+#define DPSIZR_SHIFT 16
+#define DPSIZC_SHIFT 20
+
+
+/* TLBTR1 */
+#define TLBTR1_VMID_SHIFT 0
+#define TLBTR1_PA_SHIFT 12
+
+
+/* TLBTR2 */
+#define TLBTR2_ASID_SHIFT 0
+#define TLBTR2_V_SHIFT 8
+#define TLBTR2_NSTID_SHIFT 9
+#define TLBTR2_NV_SHIFT 10
+#define TLBTR2_VA_SHIFT 12
+
+
+/* Context Register Masks */
+/* ACTLR */
+#define CFERE_MASK 0x01
+#define CFEIE_MASK 0x01
+#define PTSHCFG_MASK 0x03
+#define RCOSH_MASK 0x01
+#define RCISH_MASK 0x01
+#define RCNSH_MASK 0x01
+#define PRIVCFG_MASK 0x03
+#define DNA_MASK 0x01
+#define DNLV2PA_MASK 0x01
+#define TLBMCFG_MASK 0x03
+#define CFCFG_MASK 0x01
+#define TIPCF_MASK 0x01
+#define V2PCFG_MASK 0x03
+#define HUME_MASK 0x01
+#define PTMTCFG_MASK 0x01
+#define PTMEMTYPE_MASK 0x07
+
+
+/* BFBCR */
+#define BFBDFE_MASK 0x01
+#define BFBSFE_MASK 0x01
+#define SFVS_MASK 0x01
+#define FLVIC_MASK 0x0F
+#define SLVIC_MASK 0x0F
+
+
+/* CONTEXTIDR */
+#define CONTEXTIDR_ASID_MASK 0xFF
+#define PROCID_MASK 0x00FFFFFF
+
+
+/* FSR */
+#define TF_MASK 0x01
+#define AFF_MASK 0x01
+#define APF_MASK 0x01
+#define TLBMF_MASK 0x01
+#define HTWDEEF_MASK 0x01
+#define HTWSEEF_MASK 0x01
+#define MHF_MASK 0x01
+#define SL_MASK 0x01
+#define SS_MASK 0x01
+#define MULTI_MASK 0x01
+
+
+/* FSYNR0 */
+#define AMID_MASK 0xFF
+#define APID_MASK 0x1F
+#define ABID_MASK 0x07
+#define ATID_MASK 0xFF
+
+
+/* FSYNR1 */
+#define AMEMTYPE_MASK 0x07
+#define ASHARED_MASK 0x01
+#define AINNERSHARED_MASK 0x01
+#define APRIV_MASK 0x01
+#define APROTNS_MASK 0x01
+#define AINST_MASK 0x01
+#define AWRITE_MASK 0x01
+#define ABURST_MASK 0x01
+#define ALEN_MASK 0x0F
+#define FSYNR1_ASIZE_MASK 0x07
+#define ALOCK_MASK 0x03
+#define AFULL_MASK 0x01
+
+
+/* NMRR */
+#define ICPC0_MASK 0x03
+#define ICPC1_MASK 0x03
+#define ICPC2_MASK 0x03
+#define ICPC3_MASK 0x03
+#define ICPC4_MASK 0x03
+#define ICPC5_MASK 0x03
+#define ICPC6_MASK 0x03
+#define ICPC7_MASK 0x03
+#define OCPC0_MASK 0x03
+#define OCPC1_MASK 0x03
+#define OCPC2_MASK 0x03
+#define OCPC3_MASK 0x03
+#define OCPC4_MASK 0x03
+#define OCPC5_MASK 0x03
+#define OCPC6_MASK 0x03
+#define OCPC7_MASK 0x03
+
+
+/* PAR */
+#define FAULT_MASK 0x01
+/* If a fault is present, these are the
+same as the fault fields in the FAR */
+#define FAULT_TF_MASK 0x01
+#define FAULT_AFF_MASK 0x01
+#define FAULT_APF_MASK 0x01
+#define FAULT_TLBMF_MASK 0x01
+#define FAULT_HTWDEEF_MASK 0x01
+#define FAULT_HTWSEEF_MASK 0x01
+#define FAULT_MHF_MASK 0x01
+#define FAULT_SL_MASK 0x01
+#define FAULT_SS_MASK 0x01
+
+/* If NO fault is present, the following
+ * fields are in effect
+ * (FAULT remains as before) */
+#define PAR_NOFAULT_SS_MASK 0x01
+#define PAR_NOFAULT_MT_MASK 0x07
+#define PAR_NOFAULT_SH_MASK 0x01
+#define PAR_NOFAULT_NS_MASK 0x01
+#define PAR_NOFAULT_NOS_MASK 0x01
+#define PAR_NPFAULT_PA_MASK 0x000FFFFF
+
+
+/* PRRR */
+#define MTC0_MASK 0x03
+#define MTC1_MASK 0x03
+#define MTC2_MASK 0x03
+#define MTC3_MASK 0x03
+#define MTC4_MASK 0x03
+#define MTC5_MASK 0x03
+#define MTC6_MASK 0x03
+#define MTC7_MASK 0x03
+#define SHDSH0_MASK 0x01
+#define SHDSH1_MASK 0x01
+#define SHNMSH0_MASK 0x01
+#define SHNMSH1_MASK 0x01
+#define NOS0_MASK 0x01
+#define NOS1_MASK 0x01
+#define NOS2_MASK 0x01
+#define NOS3_MASK 0x01
+#define NOS4_MASK 0x01
+#define NOS5_MASK 0x01
+#define NOS6_MASK 0x01
+#define NOS7_MASK 0x01
+
+
+/* RESUME */
+#define TNR_MASK 0x01
+
+
+/* SCTLR */
+#define M_MASK 0x01
+#define TRE_MASK 0x01
+#define AFE_MASK 0x01
+#define HAF_MASK 0x01
+#define BE_MASK 0x01
+#define AFFD_MASK 0x01
+
+
+/* TLBIASID */
+#define TLBIASID_ASID_MASK 0xFF
+
+
+/* TLBIVA */
+#define TLBIVA_ASID_MASK 0xFF
+#define TLBIVA_VA_MASK 0x000FFFFF
+
+
+/* TLBIVAA */
+#define TLBIVAA_VA_MASK 0x000FFFFF
+
+
+/* TLBLCKR */
+#define LKE_MASK 0x01
+#define TLBLCKR_TLBIALLCFG_MASK 0x01
+#define TLBIASIDCFG_MASK 0x01
+#define TLBIVAACFG_MASK 0x01
+#define FLOOR_MASK 0xFF
+#define VICTIM_MASK 0xFF
+
+
+/* TTBCR */
+#define N_MASK 0x07
+#define PD0_MASK 0x01
+#define PD1_MASK 0x01
+
+
+/* TTBR0 */
+#define TTBR0_IRGNH_MASK 0x01
+#define TTBR0_SH_MASK 0x01
+#define TTBR0_ORGN_MASK 0x03
+#define TTBR0_NOS_MASK 0x01
+#define TTBR0_IRGNL_MASK 0x01
+#define TTBR0_PA_MASK 0x0003FFFF
+
+
+/* TTBR1 */
+#define TTBR1_IRGNH_MASK 0x01
+#define TTBR1_SH_MASK 0x01
+#define TTBR1_ORGN_MASK 0x03
+#define TTBR1_NOS_MASK 0x01
+#define TTBR1_IRGNL_MASK 0x01
+#define TTBR1_PA_MASK 0x0003FFFF
+
+
+/* V2PSR */
+#define HIT_MASK 0x01
+#define INDEX_MASK 0xFF
+
+
+/* V2Pxx */
+#define V2Pxx_INDEX_MASK 0xFF
+#define V2Pxx_VA_MASK 0x000FFFFF
+
+
+/* Context Register Shifts */
+/* ACTLR */
+#define CFERE_SHIFT 0
+#define CFEIE_SHIFT 1
+#define PTSHCFG_SHIFT 2
+#define RCOSH_SHIFT 4
+#define RCISH_SHIFT 5
+#define RCNSH_SHIFT 6
+#define PRIVCFG_SHIFT 8
+#define DNA_SHIFT 10
+#define DNLV2PA_SHIFT 11
+#define TLBMCFG_SHIFT 12
+#define CFCFG_SHIFT 14
+#define TIPCF_SHIFT 15
+#define V2PCFG_SHIFT 16
+#define HUME_SHIFT 18
+#define PTMTCFG_SHIFT 20
+#define PTMEMTYPE_SHIFT 21
+
+
+/* BFBCR */
+#define BFBDFE_SHIFT 0
+#define BFBSFE_SHIFT 1
+#define SFVS_SHIFT 2
+#define FLVIC_SHIFT 4
+#define SLVIC_SHIFT 8
+
+
+/* CONTEXTIDR */
+#define CONTEXTIDR_ASID_SHIFT 0
+#define PROCID_SHIFT 8
+
+
+/* FSR */
+#define TF_SHIFT 1
+#define AFF_SHIFT 2
+#define APF_SHIFT 3
+#define TLBMF_SHIFT 4
+#define HTWDEEF_SHIFT 5
+#define HTWSEEF_SHIFT 6
+#define MHF_SHIFT 7
+#define SL_SHIFT 16
+#define SS_SHIFT 30
+#define MULTI_SHIFT 31
+
+
+/* FSYNR0 */
+#define AMID_SHIFT 0
+#define APID_SHIFT 8
+#define ABID_SHIFT 13
+#define ATID_SHIFT 24
+
+
+/* FSYNR1 */
+#define AMEMTYPE_SHIFT 0
+#define ASHARED_SHIFT 3
+#define AINNERSHARED_SHIFT 4
+#define APRIV_SHIFT 5
+#define APROTNS_SHIFT 6
+#define AINST_SHIFT 7
+#define AWRITE_SHIFT 8
+#define ABURST_SHIFT 10
+#define ALEN_SHIFT 12
+#define FSYNR1_ASIZE_SHIFT 16
+#define ALOCK_SHIFT 20
+#define AFULL_SHIFT 24
+
+
+/* NMRR */
+#define ICPC0_SHIFT 0
+#define ICPC1_SHIFT 2
+#define ICPC2_SHIFT 4
+#define ICPC3_SHIFT 6
+#define ICPC4_SHIFT 8
+#define ICPC5_SHIFT 10
+#define ICPC6_SHIFT 12
+#define ICPC7_SHIFT 14
+#define OCPC0_SHIFT 16
+#define OCPC1_SHIFT 18
+#define OCPC2_SHIFT 20
+#define OCPC3_SHIFT 22
+#define OCPC4_SHIFT 24
+#define OCPC5_SHIFT 26
+#define OCPC6_SHIFT 28
+#define OCPC7_SHIFT 30
+
+
+/* PAR */
+#define FAULT_SHIFT 0
+/* If a fault is present, these are the
+same as the fault fields in the FAR */
+#define FAULT_TF_SHIFT 1
+#define FAULT_AFF_SHIFT 2
+#define FAULT_APF_SHIFT 3
+#define FAULT_TLBMF_SHIFT 4
+#define FAULT_HTWDEEF_SHIFT 5
+#define FAULT_HTWSEEF_SHIFT 6
+#define FAULT_MHF_SHIFT 7
+#define FAULT_SL_SHIFT 16
+#define FAULT_SS_SHIFT 30
+
+/* If NO fault is present, the following
+ * fields are in effect
+ * (FAULT remains as before) */
+#define PAR_NOFAULT_SS_SHIFT 1
+#define PAR_NOFAULT_MT_SHIFT 4
+#define PAR_NOFAULT_SH_SHIFT 7
+#define PAR_NOFAULT_NS_SHIFT 9
+#define PAR_NOFAULT_NOS_SHIFT 10
+#define PAR_NPFAULT_PA_SHIFT 12
+
+
+/* PRRR */
+#define MTC0_SHIFT 0
+#define MTC1_SHIFT 2
+#define MTC2_SHIFT 4
+#define MTC3_SHIFT 6
+#define MTC4_SHIFT 8
+#define MTC5_SHIFT 10
+#define MTC6_SHIFT 12
+#define MTC7_SHIFT 14
+#define SHDSH0_SHIFT 16
+#define SHDSH1_SHIFT 17
+#define SHNMSH0_SHIFT 18
+#define SHNMSH1_SHIFT 19
+#define NOS0_SHIFT 24
+#define NOS1_SHIFT 25
+#define NOS2_SHIFT 26
+#define NOS3_SHIFT 27
+#define NOS4_SHIFT 28
+#define NOS5_SHIFT 29
+#define NOS6_SHIFT 30
+#define NOS7_SHIFT 31
+
+
+/* RESUME */
+#define TNR_SHIFT 0
+
+
+/* SCTLR */
+#define M_SHIFT 0
+#define TRE_SHIFT 1
+#define AFE_SHIFT 2
+#define HAF_SHIFT 3
+#define BE_SHIFT 4
+#define AFFD_SHIFT 5
+
+
+/* TLBIASID */
+#define TLBIASID_ASID_SHIFT 0
+
+
+/* TLBIVA */
+#define TLBIVA_ASID_SHIFT 0
+#define TLBIVA_VA_SHIFT 12
+
+
+/* TLBIVAA */
+#define TLBIVAA_VA_SHIFT 12
+
+
+/* TLBLCKR */
+#define LKE_SHIFT 0
+#define TLBLCKR_TLBIALLCFG_SHIFT 1
+#define TLBIASIDCFG_SHIFT 2
+#define TLBIVAACFG_SHIFT 3
+#define FLOOR_SHIFT 8
+#define VICTIM_SHIFT 8
+
+
+/* TTBCR */
+#define N_SHIFT 3
+#define PD0_SHIFT 4
+#define PD1_SHIFT 5
+
+
+/* TTBR0 */
+#define TTBR0_IRGNH_SHIFT 0
+#define TTBR0_SH_SHIFT 1
+#define TTBR0_ORGN_SHIFT 3
+#define TTBR0_NOS_SHIFT 5
+#define TTBR0_IRGNL_SHIFT 6
+#define TTBR0_PA_SHIFT 14
+
+
+/* TTBR1 */
+#define TTBR1_IRGNH_SHIFT 0
+#define TTBR1_SH_SHIFT 1
+#define TTBR1_ORGN_SHIFT 3
+#define TTBR1_NOS_SHIFT 5
+#define TTBR1_IRGNL_SHIFT 6
+#define TTBR1_PA_SHIFT 14
+
+
+/* V2PSR */
+#define HIT_SHIFT 0
+#define INDEX_SHIFT 8
+
+
+/* V2Pxx */
+#define V2Pxx_INDEX_SHIFT 0
+#define V2Pxx_VA_SHIFT 12
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/irqs-8x60.h b/arch/arm/mach-msm/include/mach/irqs-8x60.h
new file mode 100644
index 000000000000..36074cfc9ad2
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/irqs-8x60.h
@@ -0,0 +1,253 @@
+/* Copyright (c) 2010 Code Aurora Forum. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __ASM_ARCH_MSM_IRQS_8X60_H
+#define __ASM_ARCH_MSM_IRQS_8X60_H
+
+/* MSM ACPU Interrupt Numbers */
+
+/* 0-15: STI/SGI (software triggered/generated interrupts)
+ * 16-31: PPI (private peripheral interrupts)
+ * 32+: SPI (shared peripheral interrupts)
+ */
+
+#define GIC_PPI_START 16
+#define GIC_SPI_START 32
+
+#define INT_DEBUG_TIMER_EXP (GIC_PPI_START + 0)
+#define INT_GP_TIMER_EXP (GIC_PPI_START + 1)
+#define INT_GP_TIMER2_EXP (GIC_PPI_START + 2)
+#define WDT0_ACCSCSSNBARK_INT (GIC_PPI_START + 3)
+#define WDT1_ACCSCSSNBARK_INT (GIC_PPI_START + 4)
+#define AVS_SVICINT (GIC_PPI_START + 5)
+#define AVS_SVICINTSWDONE (GIC_PPI_START + 6)
+#define CPU_DBGCPUXCOMMRXFULL (GIC_PPI_START + 7)
+#define CPU_DBGCPUXCOMMTXEMPTY (GIC_PPI_START + 8)
+#define CPU_SICCPUXPERFMONIRPTREQ (GIC_PPI_START + 9)
+#define SC_AVSCPUXDOWN (GIC_PPI_START + 10)
+#define SC_AVSCPUXUP (GIC_PPI_START + 11)
+#define SC_SICCPUXACGIRPTREQ (GIC_PPI_START + 12)
+/* PPI 13 to 15 are unused */
+
+
+#define SC_SICMPUIRPTREQ (GIC_SPI_START + 0)
+#define SC_SICL2IRPTREQ (GIC_SPI_START + 1)
+#define SC_SICL2ACGIRPTREQ (GIC_SPI_START + 2)
+#define NC (GIC_SPI_START + 3)
+#define TLMM_SCSS_DIR_CONN_IRQ_0 (GIC_SPI_START + 4)
+#define TLMM_SCSS_DIR_CONN_IRQ_1 (GIC_SPI_START + 5)
+#define TLMM_SCSS_DIR_CONN_IRQ_2 (GIC_SPI_START + 6)
+#define TLMM_SCSS_DIR_CONN_IRQ_3 (GIC_SPI_START + 7)
+#define TLMM_SCSS_DIR_CONN_IRQ_4 (GIC_SPI_START + 8)
+#define TLMM_SCSS_DIR_CONN_IRQ_5 (GIC_SPI_START + 9)
+#define TLMM_SCSS_DIR_CONN_IRQ_6 (GIC_SPI_START + 10)
+#define TLMM_SCSS_DIR_CONN_IRQ_7 (GIC_SPI_START + 11)
+#define TLMM_SCSS_DIR_CONN_IRQ_8 (GIC_SPI_START + 12)
+#define TLMM_SCSS_DIR_CONN_IRQ_9 (GIC_SPI_START + 13)
+#define PM8058_SEC_IRQ_N (GIC_SPI_START + 14)
+#define PM8901_SEC_IRQ_N (GIC_SPI_START + 15)
+#define TLMM_SCSS_SUMMARY_IRQ (GIC_SPI_START + 16)
+#define SPDM_RT_1_IRQ (GIC_SPI_START + 17)
+#define SPDM_DIAG_IRQ (GIC_SPI_START + 18)
+#define RPM_SCSS_CPU0_GP_HIGH_IRQ (GIC_SPI_START + 19)
+#define RPM_SCSS_CPU0_GP_MEDIUM_IRQ (GIC_SPI_START + 20)
+#define RPM_SCSS_CPU0_GP_LOW_IRQ (GIC_SPI_START + 21)
+#define RPM_SCSS_CPU0_WAKE_UP_IRQ (GIC_SPI_START + 22)
+#define RPM_SCSS_CPU1_GP_HIGH_IRQ (GIC_SPI_START + 23)
+#define RPM_SCSS_CPU1_GP_MEDIUM_IRQ (GIC_SPI_START + 24)
+#define RPM_SCSS_CPU1_GP_LOW_IRQ (GIC_SPI_START + 25)
+#define RPM_SCSS_CPU1_WAKE_UP_IRQ (GIC_SPI_START + 26)
+#define SSBI2_2_SC_CPU0_SECURE_INT (GIC_SPI_START + 27)
+#define SSBI2_2_SC_CPU0_NON_SECURE_INT (GIC_SPI_START + 28)
+#define SSBI2_1_SC_CPU0_SECURE_INT (GIC_SPI_START + 29)
+#define SSBI2_1_SC_CPU0_NON_SECURE_INT (GIC_SPI_START + 30)
+#define MSMC_SC_SEC_CE_IRQ (GIC_SPI_START + 31)
+#define MSMC_SC_PRI_CE_IRQ (GIC_SPI_START + 32)
+#define MARM_FIQ (GIC_SPI_START + 33)
+#define MARM_IRQ (GIC_SPI_START + 34)
+#define MARM_L2CC_IRQ (GIC_SPI_START + 35)
+#define MARM_WDOG_EXPIRED (GIC_SPI_START + 36)
+#define MARM_SCSS_GP_IRQ_0 (GIC_SPI_START + 37)
+#define MARM_SCSS_GP_IRQ_1 (GIC_SPI_START + 38)
+#define MARM_SCSS_GP_IRQ_2 (GIC_SPI_START + 39)
+#define MARM_SCSS_GP_IRQ_3 (GIC_SPI_START + 40)
+#define MARM_SCSS_GP_IRQ_4 (GIC_SPI_START + 41)
+#define MARM_SCSS_GP_IRQ_5 (GIC_SPI_START + 42)
+#define MARM_SCSS_GP_IRQ_6 (GIC_SPI_START + 43)
+#define MARM_SCSS_GP_IRQ_7 (GIC_SPI_START + 44)
+#define MARM_SCSS_GP_IRQ_8 (GIC_SPI_START + 45)
+#define MARM_SCSS_GP_IRQ_9 (GIC_SPI_START + 46)
+#define VPE_IRQ (GIC_SPI_START + 47)
+#define VFE_IRQ (GIC_SPI_START + 48)
+#define VCODEC_IRQ (GIC_SPI_START + 49)
+#define TV_ENC_IRQ (GIC_SPI_START + 50)
+#define SMMU_VPE_CB_SC_SECURE_IRQ (GIC_SPI_START + 51)
+#define SMMU_VPE_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 52)
+#define SMMU_VFE_CB_SC_SECURE_IRQ (GIC_SPI_START + 53)
+#define SMMU_VFE_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 54)
+#define SMMU_VCODEC_B_CB_SC_SECURE_IRQ (GIC_SPI_START + 55)
+#define SMMU_VCODEC_B_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 56)
+#define SMMU_VCODEC_A_CB_SC_SECURE_IRQ (GIC_SPI_START + 57)
+#define SMMU_VCODEC_A_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 58)
+#define SMMU_ROT_CB_SC_SECURE_IRQ (GIC_SPI_START + 59)
+#define SMMU_ROT_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 60)
+#define SMMU_MDP1_CB_SC_SECURE_IRQ (GIC_SPI_START + 61)
+#define SMMU_MDP1_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 62)
+#define SMMU_MDP0_CB_SC_SECURE_IRQ (GIC_SPI_START + 63)
+#define SMMU_MDP0_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 64)
+#define SMMU_JPEGD_CB_SC_SECURE_IRQ (GIC_SPI_START + 65)
+#define SMMU_JPEGD_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 66)
+#define SMMU_IJPEG_CB_SC_SECURE_IRQ (GIC_SPI_START + 67)
+#define SMMU_IJPEG_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 68)
+#define SMMU_GFX3D_CB_SC_SECURE_IRQ (GIC_SPI_START + 69)
+#define SMMU_GFX3D_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 70)
+#define SMMU_GFX2D0_CB_SC_SECURE_IRQ (GIC_SPI_START + 71)
+#define SMMU_GFX2D0_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 72)
+#define ROT_IRQ (GIC_SPI_START + 73)
+#define MMSS_FABRIC_IRQ (GIC_SPI_START + 74)
+#define MDP_IRQ (GIC_SPI_START + 75)
+#define JPEGD_IRQ (GIC_SPI_START + 76)
+#define JPEG_IRQ (GIC_SPI_START + 77)
+#define MMSS_IMEM_IRQ (GIC_SPI_START + 78)
+#define HDMI_IRQ (GIC_SPI_START + 79)
+#define GFX3D_IRQ (GIC_SPI_START + 80)
+#define GFX2D0_IRQ (GIC_SPI_START + 81)
+#define DSI_IRQ (GIC_SPI_START + 82)
+#define CSI_1_IRQ (GIC_SPI_START + 83)
+#define CSI_0_IRQ (GIC_SPI_START + 84)
+#define LPASS_SCSS_AUDIO_IF_OUT0_IRQ (GIC_SPI_START + 85)
+#define LPASS_SCSS_MIDI_IRQ (GIC_SPI_START + 86)
+#define LPASS_Q6SS_WDOG_EXPIRED (GIC_SPI_START + 87)
+#define LPASS_SCSS_GP_LOW_IRQ (GIC_SPI_START + 88)
+#define LPASS_SCSS_GP_MEDIUM_IRQ (GIC_SPI_START + 89)
+#define LPASS_SCSS_GP_HIGH_IRQ (GIC_SPI_START + 90)
+#define TOP_IMEM_IRQ (GIC_SPI_START + 91)
+#define FABRIC_SYS_IRQ (GIC_SPI_START + 92)
+#define FABRIC_APPS_IRQ (GIC_SPI_START + 93)
+#define USB1_HS_BAM_IRQ (GIC_SPI_START + 94)
+#define SDC4_BAM_IRQ (GIC_SPI_START + 95)
+#define SDC3_BAM_IRQ (GIC_SPI_START + 96)
+#define SDC2_BAM_IRQ (GIC_SPI_START + 97)
+#define SDC1_BAM_IRQ (GIC_SPI_START + 98)
+#define FABRIC_SPS_IRQ (GIC_SPI_START + 99)
+#define USB1_HS_IRQ (GIC_SPI_START + 100)
+#define SDC4_IRQ_0 (GIC_SPI_START + 101)
+#define SDC3_IRQ_0 (GIC_SPI_START + 102)
+#define SDC2_IRQ_0 (GIC_SPI_START + 103)
+#define SDC1_IRQ_0 (GIC_SPI_START + 104)
+#define SPS_BAM_DMA_IRQ (GIC_SPI_START + 105)
+#define SPS_SEC_VIOL_IRQ (GIC_SPI_START + 106)
+#define SPS_MTI_0 (GIC_SPI_START + 107)
+#define SPS_MTI_1 (GIC_SPI_START + 108)
+#define SPS_MTI_2 (GIC_SPI_START + 109)
+#define SPS_MTI_3 (GIC_SPI_START + 110)
+#define SPS_MTI_4 (GIC_SPI_START + 111)
+#define SPS_MTI_5 (GIC_SPI_START + 112)
+#define SPS_MTI_6 (GIC_SPI_START + 113)
+#define SPS_MTI_7 (GIC_SPI_START + 114)
+#define SPS_MTI_8 (GIC_SPI_START + 115)
+#define SPS_MTI_9 (GIC_SPI_START + 116)
+#define SPS_MTI_10 (GIC_SPI_START + 117)
+#define SPS_MTI_11 (GIC_SPI_START + 118)
+#define SPS_MTI_12 (GIC_SPI_START + 119)
+#define SPS_MTI_13 (GIC_SPI_START + 120)
+#define SPS_MTI_14 (GIC_SPI_START + 121)
+#define SPS_MTI_15 (GIC_SPI_START + 122)
+#define SPS_MTI_16 (GIC_SPI_START + 123)
+#define SPS_MTI_17 (GIC_SPI_START + 124)
+#define SPS_MTI_18 (GIC_SPI_START + 125)
+#define SPS_MTI_19 (GIC_SPI_START + 126)
+#define SPS_MTI_20 (GIC_SPI_START + 127)
+#define SPS_MTI_21 (GIC_SPI_START + 128)
+#define SPS_MTI_22 (GIC_SPI_START + 129)
+#define SPS_MTI_23 (GIC_SPI_START + 130)
+#define SPS_MTI_24 (GIC_SPI_START + 131)
+#define SPS_MTI_25 (GIC_SPI_START + 132)
+#define SPS_MTI_26 (GIC_SPI_START + 133)
+#define SPS_MTI_27 (GIC_SPI_START + 134)
+#define SPS_MTI_28 (GIC_SPI_START + 135)
+#define SPS_MTI_29 (GIC_SPI_START + 136)
+#define SPS_MTI_30 (GIC_SPI_START + 137)
+#define SPS_MTI_31 (GIC_SPI_START + 138)
+#define UXMC_EBI2_WR_ER_DONE_IRQ (GIC_SPI_START + 139)
+#define UXMC_EBI2_OP_DONE_IRQ (GIC_SPI_START + 140)
+#define USB2_IRQ (GIC_SPI_START + 141)
+#define USB1_IRQ (GIC_SPI_START + 142)
+#define TSSC_SSBI_IRQ (GIC_SPI_START + 143)
+#define TSSC_SAMPLE_IRQ (GIC_SPI_START + 144)
+#define TSSC_PENUP_IRQ (GIC_SPI_START + 145)
+#define INT_UART1DM_IRQ (GIC_SPI_START + 146)
+#define GSBI1_QUP_IRQ (GIC_SPI_START + 147)
+#define INT_UART2DM_IRQ (GIC_SPI_START + 148)
+#define GSBI2_QUP_IRQ (GIC_SPI_START + 149)
+#define INT_UART3DM_IRQ (GIC_SPI_START + 150)
+#define GSBI3_QUP_IRQ (GIC_SPI_START + 151)
+#define INT_UART4DM_IRQ (GIC_SPI_START + 152)
+#define GSBI4_QUP_IRQ (GIC_SPI_START + 153)
+#define INT_UART5DM_IRQ (GIC_SPI_START + 154)
+#define GSBI5_QUP_IRQ (GIC_SPI_START + 155)
+#define INT_UART6DM_IRQ (GIC_SPI_START + 156)
+#define GSBI6_QUP_IRQ (GIC_SPI_START + 157)
+#define INT_UART7DM_IRQ (GIC_SPI_START + 158)
+#define GSBI7_QUP_IRQ (GIC_SPI_START + 159)
+#define INT_UART8DM_IRQ (GIC_SPI_START + 160)
+#define GSBI8_QUP_IRQ (GIC_SPI_START + 161)
+#define TSIF_TSPP_IRQ (GIC_SPI_START + 162)
+#define TSIF_BAM_IRQ (GIC_SPI_START + 163)
+#define TSIF2_IRQ (GIC_SPI_START + 164)
+#define TSIF1_IRQ (GIC_SPI_START + 165)
+#define INT_ADM1_MASTER (GIC_SPI_START + 166)
+#define INT_ADM1_AARM (GIC_SPI_START + 167)
+#define INT_ADM1_SD2 (GIC_SPI_START + 168)
+#define INT_ADM1_SD3 (GIC_SPI_START + 169)
+#define INT_ADM0_MASTER (GIC_SPI_START + 170)
+#define INT_ADM0_AARM (GIC_SPI_START + 171)
+#define INT_ADM0_SD2 (GIC_SPI_START + 172)
+#define INT_ADM0_SD3 (GIC_SPI_START + 173)
+#define CC_SCSS_WDT1CPU1BITEEXPIRED (GIC_SPI_START + 174)
+#define CC_SCSS_WDT1CPU0BITEEXPIRED (GIC_SPI_START + 175)
+#define CC_SCSS_WDT0CPU1BITEEXPIRED (GIC_SPI_START + 176)
+#define CC_SCSS_WDT0CPU0BITEEXPIRED (GIC_SPI_START + 177)
+#define TSENS_UPPER_LOWER_INT (GIC_SPI_START + 178)
+#define SSBI2_2_SC_CPU1_SECURE_INT (GIC_SPI_START + 179)
+#define SSBI2_2_SC_CPU1_NON_SECURE_INT (GIC_SPI_START + 180)
+#define SSBI2_1_SC_CPU1_SECURE_INT (GIC_SPI_START + 181)
+#define SSBI2_1_SC_CPU1_NON_SECURE_INT (GIC_SPI_START + 182)
+#define XPU_SUMMARY_IRQ (GIC_SPI_START + 183)
+#define BUS_EXCEPTION_SUMMARY_IRQ (GIC_SPI_START + 184)
+#define HSDDRX_SMICH0_IRQ (GIC_SPI_START + 185)
+#define HSDDRX_EBI1_IRQ (GIC_SPI_START + 186)
+#define SDC5_BAM_IRQ (GIC_SPI_START + 187)
+#define SDC5_IRQ_0 (GIC_SPI_START + 188)
+#define INT_UART9DM_IRQ (GIC_SPI_START + 189)
+#define GSBI9_QUP_IRQ (GIC_SPI_START + 190)
+#define INT_UART10DM_IRQ (GIC_SPI_START + 191)
+#define GSBI10_QUP_IRQ (GIC_SPI_START + 192)
+#define INT_UART11DM_IRQ (GIC_SPI_START + 193)
+#define GSBI11_QUP_IRQ (GIC_SPI_START + 194)
+#define INT_UART12DM_IRQ (GIC_SPI_START + 195)
+#define GSBI12_QUP_IRQ (GIC_SPI_START + 196)
+/*SPI 197 to 216 arent used in 8x60*/
+#define SMPSS_SPARE_1 (GIC_SPI_START + 217)
+#define SMPSS_SPARE_2 (GIC_SPI_START + 218)
+#define SMPSS_SPARE_3 (GIC_SPI_START + 219)
+#define SMPSS_SPARE_4 (GIC_SPI_START + 220)
+#define SMPSS_SPARE_5 (GIC_SPI_START + 221)
+#define SMPSS_SPARE_6 (GIC_SPI_START + 222)
+#define SMPSS_SPARE_7 (GIC_SPI_START + 223)
+
+#define NR_GPIO_IRQS 173
+#define NR_MSM_IRQS 256
+#define NR_BOARD_IRQS 0
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/irqs.h b/arch/arm/mach-msm/include/mach/irqs.h
index 164d355c96ea..8679a4564744 100644
--- a/arch/arm/mach-msm/include/mach/irqs.h
+++ b/arch/arm/mach-msm/include/mach/irqs.h
@@ -24,6 +24,8 @@
#elif defined(CONFIG_ARCH_QSD8X50)
#include "irqs-8x50.h"
#include "sirc.h"
+#elif defined(CONFIG_ARCH_MSM8X60)
+#include "irqs-8x60.h"
#elif defined(CONFIG_ARCH_MSM_ARM11)
#include "irqs-7x00.h"
#else
diff --git a/arch/arm/mach-msm/include/mach/memory.h b/arch/arm/mach-msm/include/mach/memory.h
index 50c7847e6002..070e17d237f1 100644
--- a/arch/arm/mach-msm/include/mach/memory.h
+++ b/arch/arm/mach-msm/include/mach/memory.h
@@ -23,6 +23,8 @@
#define PHYS_OFFSET UL(0x20000000)
#elif defined(CONFIG_ARCH_MSM7X30)
#define PHYS_OFFSET UL(0x00200000)
+#elif defined(CONFIG_ARCH_MSM8X60)
+#define PHYS_OFFSET UL(0x40200000)
#else
#define PHYS_OFFSET UL(0x10000000)
#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h b/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h
new file mode 100644
index 000000000000..45bab50e3ee6
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2007 Google, Inc.
+ * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ * Author: Brian Swetland <swetland@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ *
+ * The MSM peripherals are spread all over across 768MB of physical
+ * space, which makes just having a simple IO_ADDRESS macro to slide
+ * them into the right virtual location rough. Instead, we will
+ * provide a master phys->virt mapping for peripherals here.
+ *
+ */
+
+#ifndef __ASM_ARCH_MSM_IOMAP_8X60_H
+#define __ASM_ARCH_MSM_IOMAP_8X60_H
+
+/* Physical base address and size of peripherals.
+ * Ordered by the virtual base addresses they will be mapped at.
+ *
+ * MSM_VIC_BASE must be an value that can be loaded via a "mov"
+ * instruction, otherwise entry-macro.S will not compile.
+ *
+ * If you add or remove entries here, you'll want to edit the
+ * msm_io_desc array in arch/arm/mach-msm/io.c to reflect your
+ * changes.
+ *
+ */
+
+#define MSM_QGIC_DIST_BASE IOMEM(0xF0000000)
+#define MSM_QGIC_DIST_PHYS 0x02080000
+#define MSM_QGIC_DIST_SIZE SZ_4K
+
+#define MSM_QGIC_CPU_BASE IOMEM(0xF0001000)
+#define MSM_QGIC_CPU_PHYS 0x02081000
+#define MSM_QGIC_CPU_SIZE SZ_4K
+
+#define MSM_ACC_BASE IOMEM(0xF0002000)
+#define MSM_ACC_PHYS 0x02001000
+#define MSM_ACC_SIZE SZ_4K
+
+#define MSM_GCC_BASE IOMEM(0xF0003000)
+#define MSM_GCC_PHYS 0x02082000
+#define MSM_GCC_SIZE SZ_4K
+
+#define MSM_TLMM_BASE IOMEM(0xF0004000)
+#define MSM_TLMM_PHYS 0x00800000
+#define MSM_TLMM_SIZE SZ_16K
+
+#define MSM_SHARED_RAM_BASE IOMEM(0xF0100000)
+#define MSM_SHARED_RAM_SIZE SZ_1M
+
+#define MSM_TMR_BASE IOMEM(0xF0200000)
+#define MSM_TMR_PHYS 0x02000000
+#define MSM_TMR_SIZE (SZ_1M)
+
+#define MSM_GPT_BASE (MSM_TMR_BASE + 0x4)
+#define MSM_DGT_BASE (MSM_TMR_BASE + 0x24)
+
+#define MSM_IOMMU_JPEGD_PHYS 0x07300000
+#define MSM_IOMMU_JPEGD_SIZE SZ_1M
+
+#define MSM_IOMMU_VPE_PHYS 0x07400000
+#define MSM_IOMMU_VPE_SIZE SZ_1M
+
+#define MSM_IOMMU_MDP0_PHYS 0x07500000
+#define MSM_IOMMU_MDP0_SIZE SZ_1M
+
+#define MSM_IOMMU_MDP1_PHYS 0x07600000
+#define MSM_IOMMU_MDP1_SIZE SZ_1M
+
+#define MSM_IOMMU_ROT_PHYS 0x07700000
+#define MSM_IOMMU_ROT_SIZE SZ_1M
+
+#define MSM_IOMMU_IJPEG_PHYS 0x07800000
+#define MSM_IOMMU_IJPEG_SIZE SZ_1M
+
+#define MSM_IOMMU_VFE_PHYS 0x07900000
+#define MSM_IOMMU_VFE_SIZE SZ_1M
+
+#define MSM_IOMMU_VCODEC_A_PHYS 0x07A00000
+#define MSM_IOMMU_VCODEC_A_SIZE SZ_1M
+
+#define MSM_IOMMU_VCODEC_B_PHYS 0x07B00000
+#define MSM_IOMMU_VCODEC_B_SIZE SZ_1M
+
+#define MSM_IOMMU_GFX3D_PHYS 0x07C00000
+#define MSM_IOMMU_GFX3D_SIZE SZ_1M
+
+#define MSM_IOMMU_GFX2D0_PHYS 0x07D00000
+#define MSM_IOMMU_GFX2D0_SIZE SZ_1M
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap.h b/arch/arm/mach-msm/include/mach/msm_iomap.h
index e6b1821cc4ea..8e24dd812139 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap.h
@@ -47,8 +47,12 @@
#include "msm_iomap-7x30.h"
#elif defined(CONFIG_ARCH_QSD8X50)
#include "msm_iomap-8x50.h"
+#elif defined(CONFIG_ARCH_MSM8X60)
+#include "msm_iomap-8x60.h"
#else
#include "msm_iomap-7x00.h"
#endif
+
+
#endif
diff --git a/arch/arm/mach-msm/include/mach/smp.h b/arch/arm/mach-msm/include/mach/smp.h
new file mode 100644
index 000000000000..3ff7bf5e679e
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/smp.h
@@ -0,0 +1,39 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Code Aurora nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __ASM_ARCH_MSM_SMP_H
+#define __ASM_ARCH_MSM_SMP_H
+
+#include <asm/hardware/gic.h>
+
+static inline void smp_cross_call(const struct cpumask *mask)
+{
+ gic_raise_softirq(mask, 1);
+}
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/vmalloc.h b/arch/arm/mach-msm/include/mach/vmalloc.h
index 05f81fd8623c..31a32ad062dc 100644
--- a/arch/arm/mach-msm/include/mach/vmalloc.h
+++ b/arch/arm/mach-msm/include/mach/vmalloc.h
@@ -16,7 +16,7 @@
#ifndef __ASM_ARCH_MSM_VMALLOC_H
#define __ASM_ARCH_MSM_VMALLOC_H
-#define VMALLOC_END (PAGE_OFFSET + 0x10000000)
+#define VMALLOC_END 0xd0000000
#endif
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index 1c05060b5f3b..d36b61074146 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -100,6 +100,21 @@ void __init msm_map_qsd8x50_io(void)
}
#endif /* CONFIG_ARCH_QSD8X50 */
+#ifdef CONFIG_ARCH_MSM8X60
+static struct map_desc msm8x60_io_desc[] __initdata = {
+ MSM_DEVICE(QGIC_DIST),
+ MSM_DEVICE(QGIC_CPU),
+ MSM_DEVICE(TMR),
+ MSM_DEVICE(ACC),
+ MSM_DEVICE(GCC),
+};
+
+void __init msm_map_msm8x60_io(void)
+{
+ iotable_init(msm8x60_io_desc, ARRAY_SIZE(msm8x60_io_desc));
+}
+#endif /* CONFIG_ARCH_MSM8X60 */
+
#ifdef CONFIG_ARCH_MSM7X30
static struct map_desc msm7x30_io_desc[] __initdata = {
MSM_DEVICE(VIC),
diff --git a/arch/arm/mach-msm/iommu.c b/arch/arm/mach-msm/iommu.c
new file mode 100644
index 000000000000..f71747db3bee
--- /dev/null
+++ b/arch/arm/mach-msm/iommu.c
@@ -0,0 +1,597 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/iommu.h>
+
+#include <asm/cacheflush.h>
+#include <asm/sizes.h>
+
+#include <mach/iommu_hw-8xxx.h>
+#include <mach/iommu.h>
+
+DEFINE_SPINLOCK(msm_iommu_lock);
+
+struct msm_priv {
+ unsigned long *pgtable;
+ struct list_head list_attached;
+};
+
+static void __flush_iotlb(struct iommu_domain *domain)
+{
+ struct msm_priv *priv = domain->priv;
+ struct msm_iommu_drvdata *iommu_drvdata;
+ struct msm_iommu_ctx_drvdata *ctx_drvdata;
+
+#ifndef CONFIG_IOMMU_PGTABLES_L2
+ unsigned long *fl_table = priv->pgtable;
+ int i;
+
+ dmac_flush_range(fl_table, fl_table + SZ_16K);
+
+ for (i = 0; i < NUM_FL_PTE; i++)
+ if ((fl_table[i] & 0x03) == FL_TYPE_TABLE) {
+ void *sl_table = __va(fl_table[i] & FL_BASE_MASK);
+ dmac_flush_range(sl_table, sl_table + SZ_4K);
+ }
+#endif
+
+ list_for_each_entry(ctx_drvdata, &priv->list_attached, attached_elm) {
+ if (!ctx_drvdata->pdev || !ctx_drvdata->pdev->dev.parent)
+ BUG();
+
+ iommu_drvdata = dev_get_drvdata(ctx_drvdata->pdev->dev.parent);
+ SET_CTX_TLBIALL(iommu_drvdata->base, ctx_drvdata->num, 0);
+ }
+}
+
+static void __reset_context(void __iomem *base, int ctx)
+{
+ SET_BPRCOSH(base, ctx, 0);
+ SET_BPRCISH(base, ctx, 0);
+ SET_BPRCNSH(base, ctx, 0);
+ SET_BPSHCFG(base, ctx, 0);
+ SET_BPMTCFG(base, ctx, 0);
+ SET_ACTLR(base, ctx, 0);
+ SET_SCTLR(base, ctx, 0);
+ SET_FSRRESTORE(base, ctx, 0);
+ SET_TTBR0(base, ctx, 0);
+ SET_TTBR1(base, ctx, 0);
+ SET_TTBCR(base, ctx, 0);
+ SET_BFBCR(base, ctx, 0);
+ SET_PAR(base, ctx, 0);
+ SET_FAR(base, ctx, 0);
+ SET_CTX_TLBIALL(base, ctx, 0);
+ SET_TLBFLPTER(base, ctx, 0);
+ SET_TLBSLPTER(base, ctx, 0);
+ SET_TLBLKCR(base, ctx, 0);
+ SET_PRRR(base, ctx, 0);
+ SET_NMRR(base, ctx, 0);
+ SET_CONTEXTIDR(base, ctx, 0);
+}
+
+static void __program_context(void __iomem *base, int ctx, phys_addr_t pgtable)
+{
+ __reset_context(base, ctx);
+
+ /* Set up HTW mode */
+ /* TLB miss configuration: perform HTW on miss */
+ SET_TLBMCFG(base, ctx, 0x3);
+
+ /* V2P configuration: HTW for access */
+ SET_V2PCFG(base, ctx, 0x3);
+
+ SET_TTBCR(base, ctx, 0);
+ SET_TTBR0_PA(base, ctx, (pgtable >> 14));
+
+ /* Invalidate the TLB for this context */
+ SET_CTX_TLBIALL(base, ctx, 0);
+
+ /* Set interrupt number to "secure" interrupt */
+ SET_IRPTNDX(base, ctx, 0);
+
+ /* Enable context fault interrupt */
+ SET_CFEIE(base, ctx, 1);
+
+ /* Stall access on a context fault and let the handler deal with it */
+ SET_CFCFG(base, ctx, 1);
+
+ /* Redirect all cacheable requests to L2 slave port. */
+ SET_RCISH(base, ctx, 1);
+ SET_RCOSH(base, ctx, 1);
+ SET_RCNSH(base, ctx, 1);
+
+ /* Turn on TEX Remap */
+ SET_TRE(base, ctx, 1);
+
+ /* Do not configure PRRR / NMRR on the IOMMU for now. We will assume
+ * TEX class 0 for everything until attributes are properly worked out
+ */
+ SET_PRRR(base, ctx, 0);
+ SET_NMRR(base, ctx, 0);
+
+ /* Turn on BFB prefetch */
+ SET_BFBDFE(base, ctx, 1);
+
+#ifdef CONFIG_IOMMU_PGTABLES_L2
+ /* Configure page tables as inner-cacheable and shareable to reduce
+ * the TLB miss penalty.
+ */
+ SET_TTBR0_SH(base, ctx, 1);
+ SET_TTBR1_SH(base, ctx, 1);
+
+ SET_TTBR0_NOS(base, ctx, 1);
+ SET_TTBR1_NOS(base, ctx, 1);
+
+ SET_TTBR0_IRGNH(base, ctx, 0); /* WB, WA */
+ SET_TTBR0_IRGNL(base, ctx, 1);
+
+ SET_TTBR1_IRGNH(base, ctx, 0); /* WB, WA */
+ SET_TTBR1_IRGNL(base, ctx, 1);
+
+ SET_TTBR0_ORGN(base, ctx, 1); /* WB, WA */
+ SET_TTBR1_ORGN(base, ctx, 1); /* WB, WA */
+#endif
+
+ /* Enable the MMU */
+ SET_M(base, ctx, 1);
+}
+
+static int msm_iommu_domain_init(struct iommu_domain *domain)
+{
+ struct msm_priv *priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+
+ if (!priv)
+ goto fail_nomem;
+
+ INIT_LIST_HEAD(&priv->list_attached);
+ priv->pgtable = (unsigned long *)__get_free_pages(GFP_KERNEL,
+ get_order(SZ_16K));
+
+ if (!priv->pgtable)
+ goto fail_nomem;
+
+ memset(priv->pgtable, 0, SZ_16K);
+ domain->priv = priv;
+ return 0;
+
+fail_nomem:
+ kfree(priv);
+ return -ENOMEM;
+}
+
+static void msm_iommu_domain_destroy(struct iommu_domain *domain)
+{
+ struct msm_priv *priv;
+ unsigned long flags;
+ unsigned long *fl_table;
+ int i;
+
+ spin_lock_irqsave(&msm_iommu_lock, flags);
+ priv = domain->priv;
+ domain->priv = NULL;
+
+ if (priv) {
+ fl_table = priv->pgtable;
+
+ for (i = 0; i < NUM_FL_PTE; i++)
+ if ((fl_table[i] & 0x03) == FL_TYPE_TABLE)
+ free_page((unsigned long) __va(((fl_table[i]) &
+ FL_BASE_MASK)));
+
+ free_pages((unsigned long)priv->pgtable, get_order(SZ_16K));
+ priv->pgtable = NULL;
+ }
+
+ kfree(priv);
+ spin_unlock_irqrestore(&msm_iommu_lock, flags);
+}
+
+static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
+{
+ struct msm_priv *priv;
+ struct msm_iommu_ctx_dev *ctx_dev;
+ struct msm_iommu_drvdata *iommu_drvdata;
+ struct msm_iommu_ctx_drvdata *ctx_drvdata;
+ struct msm_iommu_ctx_drvdata *tmp_drvdata;
+ int ret = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&msm_iommu_lock, flags);
+
+ priv = domain->priv;
+
+ if (!priv || !dev) {
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ iommu_drvdata = dev_get_drvdata(dev->parent);
+ ctx_drvdata = dev_get_drvdata(dev);
+ ctx_dev = dev->platform_data;
+
+ if (!iommu_drvdata || !ctx_drvdata || !ctx_dev) {
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ list_for_each_entry(tmp_drvdata, &priv->list_attached, attached_elm)
+ if (tmp_drvdata == ctx_drvdata) {
+ ret = -EBUSY;
+ goto fail;
+ }
+
+ __program_context(iommu_drvdata->base, ctx_dev->num,
+ __pa(priv->pgtable));
+
+ list_add(&(ctx_drvdata->attached_elm), &priv->list_attached);
+ __flush_iotlb(domain);
+
+fail:
+ spin_unlock_irqrestore(&msm_iommu_lock, flags);
+ return ret;
+}
+
+static void msm_iommu_detach_dev(struct iommu_domain *domain,
+ struct device *dev)
+{
+ struct msm_priv *priv;
+ struct msm_iommu_ctx_dev *ctx_dev;
+ struct msm_iommu_drvdata *iommu_drvdata;
+ struct msm_iommu_ctx_drvdata *ctx_drvdata;
+ unsigned long flags;
+
+ spin_lock_irqsave(&msm_iommu_lock, flags);
+ priv = domain->priv;
+
+ if (!priv || !dev)
+ goto fail;
+
+ iommu_drvdata = dev_get_drvdata(dev->parent);
+ ctx_drvdata = dev_get_drvdata(dev);
+ ctx_dev = dev->platform_data;
+
+ if (!iommu_drvdata || !ctx_drvdata || !ctx_dev)
+ goto fail;
+
+ __flush_iotlb(domain);
+ __reset_context(iommu_drvdata->base, ctx_dev->num);
+ list_del_init(&ctx_drvdata->attached_elm);
+
+fail:
+ spin_unlock_irqrestore(&msm_iommu_lock, flags);
+}
+
+static int msm_iommu_map(struct iommu_domain *domain, unsigned long va,
+ phys_addr_t pa, int order, int prot)
+{
+ struct msm_priv *priv;
+ unsigned long flags;
+ unsigned long *fl_table;
+ unsigned long *fl_pte;
+ unsigned long fl_offset;
+ unsigned long *sl_table;
+ unsigned long *sl_pte;
+ unsigned long sl_offset;
+ size_t len = 0x1000UL << order;
+ int ret = 0;
+
+ spin_lock_irqsave(&msm_iommu_lock, flags);
+ priv = domain->priv;
+
+ if (!priv) {
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ fl_table = priv->pgtable;
+
+ if (len != SZ_16M && len != SZ_1M &&
+ len != SZ_64K && len != SZ_4K) {
+ pr_debug("Bad size: %d\n", len);
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ if (!fl_table) {
+ pr_debug("Null page table\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ fl_offset = FL_OFFSET(va); /* Upper 12 bits */
+ fl_pte = fl_table + fl_offset; /* int pointers, 4 bytes */
+
+ if (len == SZ_16M) {
+ int i = 0;
+ for (i = 0; i < 16; i++)
+ *(fl_pte+i) = (pa & 0xFF000000) | FL_SUPERSECTION |
+ FL_AP_READ | FL_AP_WRITE | FL_TYPE_SECT |
+ FL_SHARED;
+ }
+
+ if (len == SZ_1M)
+ *fl_pte = (pa & 0xFFF00000) | FL_AP_READ | FL_AP_WRITE |
+ FL_TYPE_SECT | FL_SHARED;
+
+ /* Need a 2nd level table */
+ if ((len == SZ_4K || len == SZ_64K) && (*fl_pte) == 0) {
+ unsigned long *sl;
+ sl = (unsigned long *) __get_free_pages(GFP_KERNEL,
+ get_order(SZ_4K));
+
+ if (!sl) {
+ pr_debug("Could not allocate second level table\n");
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ memset(sl, 0, SZ_4K);
+ *fl_pte = ((((int)__pa(sl)) & FL_BASE_MASK) | FL_TYPE_TABLE);
+ }
+
+ sl_table = (unsigned long *) __va(((*fl_pte) & FL_BASE_MASK));
+ sl_offset = SL_OFFSET(va);
+ sl_pte = sl_table + sl_offset;
+
+
+ if (len == SZ_4K)
+ *sl_pte = (pa & SL_BASE_MASK_SMALL) | SL_AP0 | SL_AP1 |
+ SL_SHARED | SL_TYPE_SMALL;
+
+ if (len == SZ_64K) {
+ int i;
+
+ for (i = 0; i < 16; i++)
+ *(sl_pte+i) = (pa & SL_BASE_MASK_LARGE) | SL_AP0 |
+ SL_AP1 | SL_SHARED | SL_TYPE_LARGE;
+ }
+
+ __flush_iotlb(domain);
+fail:
+ spin_unlock_irqrestore(&msm_iommu_lock, flags);
+ return ret;
+}
+
+static int msm_iommu_unmap(struct iommu_domain *domain, unsigned long va,
+ int order)
+{
+ struct msm_priv *priv;
+ unsigned long flags;
+ unsigned long *fl_table;
+ unsigned long *fl_pte;
+ unsigned long fl_offset;
+ unsigned long *sl_table;
+ unsigned long *sl_pte;
+ unsigned long sl_offset;
+ size_t len = 0x1000UL << order;
+ int i, ret = 0;
+
+ spin_lock_irqsave(&msm_iommu_lock, flags);
+
+ priv = domain->priv;
+
+ if (!priv) {
+ ret = -ENODEV;
+ goto fail;
+ }
+
+ fl_table = priv->pgtable;
+
+ if (len != SZ_16M && len != SZ_1M &&
+ len != SZ_64K && len != SZ_4K) {
+ pr_debug("Bad length: %d\n", len);
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ if (!fl_table) {
+ pr_debug("Null page table\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ fl_offset = FL_OFFSET(va); /* Upper 12 bits */
+ fl_pte = fl_table + fl_offset; /* int pointers, 4 bytes */
+
+ if (*fl_pte == 0) {
+ pr_debug("First level PTE is 0\n");
+ ret = -ENODEV;
+ goto fail;
+ }
+
+ /* Unmap supersection */
+ if (len == SZ_16M)
+ for (i = 0; i < 16; i++)
+ *(fl_pte+i) = 0;
+
+ if (len == SZ_1M)
+ *fl_pte = 0;
+
+ sl_table = (unsigned long *) __va(((*fl_pte) & FL_BASE_MASK));
+ sl_offset = SL_OFFSET(va);
+ sl_pte = sl_table + sl_offset;
+
+ if (len == SZ_64K) {
+ for (i = 0; i < 16; i++)
+ *(sl_pte+i) = 0;
+ }
+
+ if (len == SZ_4K)
+ *sl_pte = 0;
+
+ if (len == SZ_4K || len == SZ_64K) {
+ int used = 0;
+
+ for (i = 0; i < NUM_SL_PTE; i++)
+ if (sl_table[i])
+ used = 1;
+ if (!used) {
+ free_page((unsigned long)sl_table);
+ *fl_pte = 0;
+ }
+ }
+
+ __flush_iotlb(domain);
+fail:
+ spin_unlock_irqrestore(&msm_iommu_lock, flags);
+ return ret;
+}
+
+static phys_addr_t msm_iommu_iova_to_phys(struct iommu_domain *domain,
+ unsigned long va)
+{
+ struct msm_priv *priv;
+ struct msm_iommu_drvdata *iommu_drvdata;
+ struct msm_iommu_ctx_drvdata *ctx_drvdata;
+ unsigned int par;
+ unsigned long flags;
+ void __iomem *base;
+ phys_addr_t ret = 0;
+ int ctx;
+
+ spin_lock_irqsave(&msm_iommu_lock, flags);
+
+ priv = domain->priv;
+ if (list_empty(&priv->list_attached))
+ goto fail;
+
+ ctx_drvdata = list_entry(priv->list_attached.next,
+ struct msm_iommu_ctx_drvdata, attached_elm);
+ iommu_drvdata = dev_get_drvdata(ctx_drvdata->pdev->dev.parent);
+
+ base = iommu_drvdata->base;
+ ctx = ctx_drvdata->num;
+
+ /* Invalidate context TLB */
+ SET_CTX_TLBIALL(base, ctx, 0);
+ SET_V2PPR_VA(base, ctx, va >> V2Pxx_VA_SHIFT);
+
+ if (GET_FAULT(base, ctx))
+ goto fail;
+
+ par = GET_PAR(base, ctx);
+
+ /* We are dealing with a supersection */
+ if (GET_NOFAULT_SS(base, ctx))
+ ret = (par & 0xFF000000) | (va & 0x00FFFFFF);
+ else /* Upper 20 bits from PAR, lower 12 from VA */
+ ret = (par & 0xFFFFF000) | (va & 0x00000FFF);
+
+fail:
+ spin_unlock_irqrestore(&msm_iommu_lock, flags);
+ return ret;
+}
+
+static int msm_iommu_domain_has_cap(struct iommu_domain *domain,
+ unsigned long cap)
+{
+ return 0;
+}
+
+static void print_ctx_regs(void __iomem *base, int ctx)
+{
+ unsigned int fsr = GET_FSR(base, ctx);
+ pr_err("FAR = %08x PAR = %08x\n",
+ GET_FAR(base, ctx), GET_PAR(base, ctx));
+ pr_err("FSR = %08x [%s%s%s%s%s%s%s%s%s%s]\n", fsr,
+ (fsr & 0x02) ? "TF " : "",
+ (fsr & 0x04) ? "AFF " : "",
+ (fsr & 0x08) ? "APF " : "",
+ (fsr & 0x10) ? "TLBMF " : "",
+ (fsr & 0x20) ? "HTWDEEF " : "",
+ (fsr & 0x40) ? "HTWSEEF " : "",
+ (fsr & 0x80) ? "MHF " : "",
+ (fsr & 0x10000) ? "SL " : "",
+ (fsr & 0x40000000) ? "SS " : "",
+ (fsr & 0x80000000) ? "MULTI " : "");
+
+ pr_err("FSYNR0 = %08x FSYNR1 = %08x\n",
+ GET_FSYNR0(base, ctx), GET_FSYNR1(base, ctx));
+ pr_err("TTBR0 = %08x TTBR1 = %08x\n",
+ GET_TTBR0(base, ctx), GET_TTBR1(base, ctx));
+ pr_err("SCTLR = %08x ACTLR = %08x\n",
+ GET_SCTLR(base, ctx), GET_ACTLR(base, ctx));
+ pr_err("PRRR = %08x NMRR = %08x\n",
+ GET_PRRR(base, ctx), GET_NMRR(base, ctx));
+}
+
+irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id)
+{
+ struct msm_iommu_drvdata *drvdata = dev_id;
+ void __iomem *base;
+ unsigned int fsr = 0;
+ int ncb = 0, i = 0;
+
+ spin_lock(&msm_iommu_lock);
+
+ if (!drvdata) {
+ pr_err("Invalid device ID in context interrupt handler\n");
+ goto fail;
+ }
+
+ base = drvdata->base;
+
+ pr_err("===== WOAH! =====\n");
+ pr_err("Unexpected IOMMU page fault!\n");
+ pr_err("base = %08x\n", (unsigned int) base);
+
+ ncb = GET_NCB(base)+1;
+ for (i = 0; i < ncb; i++) {
+ fsr = GET_FSR(base, i);
+ if (fsr) {
+ pr_err("Fault occurred in context %d.\n", i);
+ pr_err("Interesting registers:\n");
+ print_ctx_regs(base, i);
+ SET_FSR(base, i, 0x4000000F);
+ }
+ }
+fail:
+ spin_unlock(&msm_iommu_lock);
+ return 0;
+}
+
+static struct iommu_ops msm_iommu_ops = {
+ .domain_init = msm_iommu_domain_init,
+ .domain_destroy = msm_iommu_domain_destroy,
+ .attach_dev = msm_iommu_attach_dev,
+ .detach_dev = msm_iommu_detach_dev,
+ .map = msm_iommu_map,
+ .unmap = msm_iommu_unmap,
+ .iova_to_phys = msm_iommu_iova_to_phys,
+ .domain_has_cap = msm_iommu_domain_has_cap
+};
+
+static int msm_iommu_init(void)
+{
+ register_iommu(&msm_iommu_ops);
+ return 0;
+}
+
+subsys_initcall(msm_iommu_init);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Stepan Moskovchenko <stepanm@codeaurora.org>");
diff --git a/arch/arm/mach-msm/iommu_dev.c b/arch/arm/mach-msm/iommu_dev.c
new file mode 100644
index 000000000000..c33ae786c41f
--- /dev/null
+++ b/arch/arm/mach-msm/iommu_dev.c
@@ -0,0 +1,374 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/iommu.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+
+#include <mach/iommu_hw-8xxx.h>
+#include <mach/iommu.h>
+
+struct iommu_ctx_iter_data {
+ /* input */
+ const char *name;
+
+ /* output */
+ struct device *dev;
+};
+
+static struct platform_device *msm_iommu_root_dev;
+
+static int each_iommu_ctx(struct device *dev, void *data)
+{
+ struct iommu_ctx_iter_data *res = data;
+ struct msm_iommu_ctx_dev *c = dev->platform_data;
+
+ if (!res || !c || !c->name || !res->name)
+ return -EINVAL;
+
+ if (!strcmp(res->name, c->name)) {
+ res->dev = dev;
+ return 1;
+ }
+ return 0;
+}
+
+static int each_iommu(struct device *dev, void *data)
+{
+ return device_for_each_child(dev, data, each_iommu_ctx);
+}
+
+struct device *msm_iommu_get_ctx(const char *ctx_name)
+{
+ struct iommu_ctx_iter_data r;
+ int found;
+
+ if (!msm_iommu_root_dev) {
+ pr_err("No root IOMMU device.\n");
+ goto fail;
+ }
+
+ r.name = ctx_name;
+ found = device_for_each_child(&msm_iommu_root_dev->dev, &r, each_iommu);
+
+ if (!found) {
+ pr_err("Could not find context <%s>\n", ctx_name);
+ goto fail;
+ }
+
+ return r.dev;
+fail:
+ return NULL;
+}
+EXPORT_SYMBOL(msm_iommu_get_ctx);
+
+static void msm_iommu_reset(void __iomem *base)
+{
+ int ctx, ncb;
+
+ SET_RPUE(base, 0);
+ SET_RPUEIE(base, 0);
+ SET_ESRRESTORE(base, 0);
+ SET_TBE(base, 0);
+ SET_CR(base, 0);
+ SET_SPDMBE(base, 0);
+ SET_TESTBUSCR(base, 0);
+ SET_TLBRSW(base, 0);
+ SET_GLOBAL_TLBIALL(base, 0);
+ SET_RPU_ACR(base, 0);
+ SET_TLBLKCRWE(base, 1);
+ ncb = GET_NCB(base)+1;
+
+ for (ctx = 0; ctx < ncb; ctx++) {
+ SET_BPRCOSH(base, ctx, 0);
+ SET_BPRCISH(base, ctx, 0);
+ SET_BPRCNSH(base, ctx, 0);
+ SET_BPSHCFG(base, ctx, 0);
+ SET_BPMTCFG(base, ctx, 0);
+ SET_ACTLR(base, ctx, 0);
+ SET_SCTLR(base, ctx, 0);
+ SET_FSRRESTORE(base, ctx, 0);
+ SET_TTBR0(base, ctx, 0);
+ SET_TTBR1(base, ctx, 0);
+ SET_TTBCR(base, ctx, 0);
+ SET_BFBCR(base, ctx, 0);
+ SET_PAR(base, ctx, 0);
+ SET_FAR(base, ctx, 0);
+ SET_CTX_TLBIALL(base, ctx, 0);
+ SET_TLBFLPTER(base, ctx, 0);
+ SET_TLBSLPTER(base, ctx, 0);
+ SET_TLBLKCR(base, ctx, 0);
+ SET_PRRR(base, ctx, 0);
+ SET_NMRR(base, ctx, 0);
+ SET_CONTEXTIDR(base, ctx, 0);
+ }
+}
+
+static int msm_iommu_probe(struct platform_device *pdev)
+{
+ struct resource *r;
+ struct clk *iommu_clk;
+ struct msm_iommu_drvdata *drvdata;
+ struct msm_iommu_dev *iommu_dev = pdev->dev.platform_data;
+ void __iomem *regs_base;
+ resource_size_t len;
+ int ret = 0, ncb, nm2v, irq;
+
+ if (pdev->id != -1) {
+ drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
+
+ if (!drvdata) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ if (!iommu_dev) {
+ ret = -ENODEV;
+ goto fail;
+ }
+
+ if (iommu_dev->clk_rate != 0) {
+ iommu_clk = clk_get(&pdev->dev, "iommu_clk");
+
+ if (IS_ERR(iommu_clk)) {
+ ret = -ENODEV;
+ goto fail;
+ }
+
+ if (iommu_dev->clk_rate > 0) {
+ ret = clk_set_rate(iommu_clk,
+ iommu_dev->clk_rate);
+ if (ret) {
+ clk_put(iommu_clk);
+ goto fail;
+ }
+ }
+
+ ret = clk_enable(iommu_clk);
+ if (ret) {
+ clk_put(iommu_clk);
+ goto fail;
+ }
+ clk_put(iommu_clk);
+ }
+
+ r = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "physbase");
+ if (!r) {
+ ret = -ENODEV;
+ goto fail;
+ }
+
+ len = r->end - r->start + 1;
+
+ r = request_mem_region(r->start, len, r->name);
+ if (!r) {
+ pr_err("Could not request memory region: "
+ "start=%p, len=%d\n", (void *) r->start, len);
+ ret = -EBUSY;
+ goto fail;
+ }
+
+ regs_base = ioremap(r->start, len);
+
+ if (!regs_base) {
+ pr_err("Could not ioremap: start=%p, len=%d\n",
+ (void *) r->start, len);
+ ret = -EBUSY;
+ goto fail;
+ }
+
+ irq = platform_get_irq_byname(pdev, "secure_irq");
+ if (irq < 0) {
+ ret = -ENODEV;
+ goto fail;
+ }
+
+ mb();
+
+ if (GET_IDR(regs_base) == 0) {
+ pr_err("Invalid IDR value detected\n");
+ ret = -ENODEV;
+ goto fail;
+ }
+
+ ret = request_irq(irq, msm_iommu_fault_handler, 0,
+ "msm_iommu_secure_irpt_handler", drvdata);
+ if (ret) {
+ pr_err("Request IRQ %d failed with ret=%d\n", irq, ret);
+ goto fail;
+ }
+
+ msm_iommu_reset(regs_base);
+ drvdata->base = regs_base;
+ drvdata->irq = irq;
+
+ nm2v = GET_NM2VCBMT((unsigned long) regs_base);
+ ncb = GET_NCB((unsigned long) regs_base);
+
+ pr_info("device %s mapped at %p, irq %d with %d ctx banks\n",
+ iommu_dev->name, regs_base, irq, ncb+1);
+
+ platform_set_drvdata(pdev, drvdata);
+ } else
+ msm_iommu_root_dev = pdev;
+
+ return 0;
+
+fail:
+ kfree(drvdata);
+ return ret;
+}
+
+static int msm_iommu_remove(struct platform_device *pdev)
+{
+ struct msm_iommu_drvdata *drv = NULL;
+
+ drv = platform_get_drvdata(pdev);
+ if (drv) {
+ memset(drv, 0, sizeof(struct msm_iommu_drvdata));
+ kfree(drv);
+ platform_set_drvdata(pdev, NULL);
+ }
+ return 0;
+}
+
+static int msm_iommu_ctx_probe(struct platform_device *pdev)
+{
+ struct msm_iommu_ctx_dev *c = pdev->dev.platform_data;
+ struct msm_iommu_drvdata *drvdata;
+ struct msm_iommu_ctx_drvdata *ctx_drvdata = NULL;
+ int i, ret = 0;
+ if (!c || !pdev->dev.parent) {
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ drvdata = dev_get_drvdata(pdev->dev.parent);
+
+ if (!drvdata) {
+ ret = -ENODEV;
+ goto fail;
+ }
+
+ ctx_drvdata = kzalloc(sizeof(*ctx_drvdata), GFP_KERNEL);
+ if (!ctx_drvdata) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+ ctx_drvdata->num = c->num;
+ ctx_drvdata->pdev = pdev;
+
+ INIT_LIST_HEAD(&ctx_drvdata->attached_elm);
+ platform_set_drvdata(pdev, ctx_drvdata);
+
+ /* Program the M2V tables for this context */
+ for (i = 0; i < MAX_NUM_MIDS; i++) {
+ int mid = c->mids[i];
+ if (mid == -1)
+ break;
+
+ SET_M2VCBR_N(drvdata->base, mid, 0);
+ SET_CBACR_N(drvdata->base, c->num, 0);
+
+ /* Set VMID = MID */
+ SET_VMID(drvdata->base, mid, mid);
+
+ /* Set the context number for that MID to this context */
+ SET_CBNDX(drvdata->base, mid, c->num);
+
+ /* Set MID associated with this context bank */
+ SET_CBVMID(drvdata->base, c->num, mid);
+
+ /* Set security bit override to be Non-secure */
+ SET_NSCFG(drvdata->base, mid, 3);
+ }
+
+ pr_info("context device %s with bank index %d\n", c->name, c->num);
+
+ return 0;
+fail:
+ kfree(ctx_drvdata);
+ return ret;
+}
+
+static int msm_iommu_ctx_remove(struct platform_device *pdev)
+{
+ struct msm_iommu_ctx_drvdata *drv = NULL;
+ drv = platform_get_drvdata(pdev);
+ if (drv) {
+ memset(drv, 0, sizeof(struct msm_iommu_ctx_drvdata));
+ kfree(drv);
+ platform_set_drvdata(pdev, NULL);
+ }
+ return 0;
+}
+
+static struct platform_driver msm_iommu_driver = {
+ .driver = {
+ .name = "msm_iommu",
+ },
+ .probe = msm_iommu_probe,
+ .remove = msm_iommu_remove,
+};
+
+static struct platform_driver msm_iommu_ctx_driver = {
+ .driver = {
+ .name = "msm_iommu_ctx",
+ },
+ .probe = msm_iommu_ctx_probe,
+ .remove = msm_iommu_ctx_remove,
+};
+
+static int msm_iommu_driver_init(void)
+{
+ int ret;
+ ret = platform_driver_register(&msm_iommu_driver);
+ if (ret != 0) {
+ pr_err("Failed to register IOMMU driver\n");
+ goto error;
+ }
+
+ ret = platform_driver_register(&msm_iommu_ctx_driver);
+ if (ret != 0) {
+ pr_err("Failed to register IOMMU context driver\n");
+ goto error;
+ }
+
+error:
+ return ret;
+}
+
+static void msm_iommu_driver_exit(void)
+{
+ platform_driver_unregister(&msm_iommu_ctx_driver);
+ platform_driver_unregister(&msm_iommu_driver);
+}
+
+subsys_initcall(msm_iommu_driver_init);
+module_exit(msm_iommu_driver_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Stepan Moskovchenko <stepanm@codeaurora.org>");
diff --git a/arch/arm/mach-msm/last_radio_log.c b/arch/arm/mach-msm/last_radio_log.c
index b64ba5a98686..1e243f46a969 100644
--- a/arch/arm/mach-msm/last_radio_log.c
+++ b/arch/arm/mach-msm/last_radio_log.c
@@ -48,7 +48,8 @@ static ssize_t last_radio_log_read(struct file *file, char __user *buf,
}
static struct file_operations last_radio_log_fops = {
- .read = last_radio_log_read
+ .read = last_radio_log_read,
+ .llseek = default_llseek,
};
void msm_init_last_radio_log(struct module *owner)
diff --git a/arch/arm/mach-msm/smd_debug.c b/arch/arm/mach-msm/smd_debug.c
index 3b2dd717b788..f91c3b7bc655 100644
--- a/arch/arm/mach-msm/smd_debug.c
+++ b/arch/arm/mach-msm/smd_debug.c
@@ -212,6 +212,7 @@ static int debug_open(struct inode *inode, struct file *file)
static const struct file_operations debug_ops = {
.read = debug_read,
.open = debug_open,
+ .llseek = default_llseek,
};
static void debug_create(const char *name, mode_t mode,
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c
index dec5ca622d7d..7689848ec680 100644
--- a/arch/arm/mach-msm/timer.c
+++ b/arch/arm/mach-msm/timer.c
@@ -28,7 +28,6 @@
#ifndef MSM_DGT_BASE
#define MSM_DGT_BASE (MSM_GPT_BASE + 0x10)
#endif
-#define MSM_DGT_SHIFT (5)
#define TIMER_MATCH_VAL 0x0000
#define TIMER_COUNT_VAL 0x0004
@@ -36,12 +35,28 @@
#define TIMER_ENABLE_CLR_ON_MATCH_EN 2
#define TIMER_ENABLE_EN 1
#define TIMER_CLEAR 0x000C
-
+#define DGT_CLK_CTL 0x0034
+enum {
+ DGT_CLK_CTL_DIV_1 = 0,
+ DGT_CLK_CTL_DIV_2 = 1,
+ DGT_CLK_CTL_DIV_3 = 2,
+ DGT_CLK_CTL_DIV_4 = 3,
+};
#define CSR_PROTECTION 0x0020
#define CSR_PROTECTION_EN 1
#define GPT_HZ 32768
+
+#if defined(CONFIG_ARCH_QSD8X50)
+#define DGT_HZ (19200000 / 4) /* 19.2 MHz / 4 by default */
+#define MSM_DGT_SHIFT (0)
+#elif defined(CONFIG_ARCH_MSM7X30) || defined(CONFIG_ARCH_MSM8X60)
+#define DGT_HZ (24576000 / 4) /* 24.576 MHz (LPXO) / 4 by default */
+#define MSM_DGT_SHIFT (0)
+#else
#define DGT_HZ 19200000 /* 19.2 MHz or 600 KHz after shift */
+#define MSM_DGT_SHIFT (5)
+#endif
struct msm_clock {
struct clock_event_device clockevent;
@@ -170,6 +185,10 @@ static void __init msm_timer_init(void)
int i;
int res;
+#ifdef CONFIG_ARCH_MSM8X60
+ writel(DGT_CLK_CTL_DIV_4, MSM_TMR_BASE + DGT_CLK_CTL);
+#endif
+
for (i = 0; i < ARRAY_SIZE(msm_clocks); i++) {
struct msm_clock *clock = &msm_clocks[i];
struct clock_event_device *ce = &clock->clockevent;
diff --git a/arch/arm/mach-mv78xx0/buffalo-wxl-setup.c b/arch/arm/mach-mv78xx0/buffalo-wxl-setup.c
index 61e5e583603b..29e390e89ff4 100644
--- a/arch/arm/mach-mv78xx0/buffalo-wxl-setup.c
+++ b/arch/arm/mach-mv78xx0/buffalo-wxl-setup.c
@@ -145,8 +145,6 @@ subsys_initcall(wxl_pci_init);
MACHINE_START(TERASTATION_WXL, "Buffalo Nas WXL")
/* Maintainer: Sebastien Requiem <sebastien@requiem.fr> */
- .phys_io = MV78XX0_REGS_PHYS_BASE,
- .io_pg_offst = ((MV78XX0_REGS_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = 0x00000100,
.init_machine = wxl_init,
.map_io = mv78xx0_map_io,
diff --git a/arch/arm/mach-mv78xx0/db78x00-bp-setup.c b/arch/arm/mach-mv78xx0/db78x00-bp-setup.c
index efdabe04c69e..207c95e403b9 100644
--- a/arch/arm/mach-mv78xx0/db78x00-bp-setup.c
+++ b/arch/arm/mach-mv78xx0/db78x00-bp-setup.c
@@ -93,8 +93,6 @@ subsys_initcall(db78x00_pci_init);
MACHINE_START(DB78X00_BP, "Marvell DB-78x00-BP Development Board")
/* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */
- .phys_io = MV78XX0_REGS_PHYS_BASE,
- .io_pg_offst = ((MV78XX0_REGS_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = 0x00000100,
.init_machine = db78x00_init,
.map_io = mv78xx0_map_io,
diff --git a/arch/arm/mach-mv78xx0/include/mach/debug-macro.S b/arch/arm/mach-mv78xx0/include/mach/debug-macro.S
index cd81689c4621..04891428e48b 100644
--- a/arch/arm/mach-mv78xx0/include/mach/debug-macro.S
+++ b/arch/arm/mach-mv78xx0/include/mach/debug-macro.S
@@ -8,12 +8,11 @@
#include <mach/mv78xx0.h>
- .macro addruart, rx, tmp
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ MMU enabled?
- ldreq \rx, =MV78XX0_REGS_PHYS_BASE
- ldrne \rx, =MV78XX0_REGS_VIRT_BASE
- orr \rx, \rx, #0x00012000
+ .macro addruart, rp, rv
+ ldr \rp, =MV78XX0_REGS_PHYS_BASE
+ ldr \rv, =MV78XX0_REGS_VIRT_BASE
+ orr \rp, \rp, #0x00012000
+ orr \rv, \rv, #0x00012000
.endm
#define UART_SHIFT 2
diff --git a/arch/arm/mach-mv78xx0/rd78x00-masa-setup.c b/arch/arm/mach-mv78xx0/rd78x00-masa-setup.c
index e136b7a03355..3511ad4d973b 100644
--- a/arch/arm/mach-mv78xx0/rd78x00-masa-setup.c
+++ b/arch/arm/mach-mv78xx0/rd78x00-masa-setup.c
@@ -78,8 +78,6 @@ subsys_initcall(rd78x00_pci_init);
MACHINE_START(RD78X00_MASA, "Marvell RD-78x00-MASA Development Board")
/* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */
- .phys_io = MV78XX0_REGS_PHYS_BASE,
- .io_pg_offst = ((MV78XX0_REGS_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = 0x00000100,
.init_machine = rd78x00_masa_init,
.map_io = mv78xx0_map_io,
diff --git a/arch/arm/mach-mx25/Kconfig b/arch/arm/mach-mx25/Kconfig
index c71a7bc19284..aa57e35ce3cd 100644
--- a/arch/arm/mach-mx25/Kconfig
+++ b/arch/arm/mach-mx25/Kconfig
@@ -12,6 +12,8 @@ config MACH_EUKREA_CPUIMX25
select IMX_HAVE_PLATFORM_IMX_I2C
select IMX_HAVE_PLATFORM_IMX_UART
select IMX_HAVE_PLATFORM_MXC_NAND
+ select IMX_HAVE_PLATFORM_FLEXCAN
+ select IMX_HAVE_PLATFORM_ESDHC
select MXC_ULPI if USB_ULPI
choice
@@ -20,8 +22,8 @@ choice
default MACH_EUKREA_MBIMXSD25_BASEBOARD
config MACH_EUKREA_MBIMXSD25_BASEBOARD
- prompt "Eukrea MBIMXSD development board"
- bool
+ bool "Eukrea MBIMXSD development board"
+ select IMX_HAVE_PLATFORM_IMX_SSI
help
This adds board specific devices that can be found on Eukrea's
MBIMXSD evaluation board.
diff --git a/arch/arm/mach-mx25/clock.c b/arch/arm/mach-mx25/clock.c
index 40c7cc41cee3..9e4a5578c2fb 100644
--- a/arch/arm/mach-mx25/clock.c
+++ b/arch/arm/mach-mx25/clock.c
@@ -72,7 +72,7 @@ unsigned long get_rate_arm(struct clk *clk)
unsigned long rate = get_rate_mpll();
if (cctl & (1 << 14))
- rate = (rate * 3) >> 1;
+ rate = (rate * 3) >> 2;
return rate / ((cctl >> 30) + 1);
}
@@ -99,7 +99,7 @@ static unsigned long get_rate_per(int per)
if (readl(CRM_BASE + 0x64) & (1 << per))
fref = get_rate_upll();
else
- fref = get_rate_ipg(NULL);
+ fref = get_rate_ahb(NULL);
return fref / (val + 1);
}
@@ -139,6 +139,16 @@ static unsigned long get_rate_lcdc(struct clk *clk)
return get_rate_per(7);
}
+static unsigned long get_rate_esdhc1(struct clk *clk)
+{
+ return get_rate_per(3);
+}
+
+static unsigned long get_rate_esdhc2(struct clk *clk)
+{
+ return get_rate_per(4);
+}
+
static unsigned long get_rate_csi(struct clk *clk)
{
return get_rate_per(0);
@@ -213,6 +223,12 @@ DEFINE_CLOCK(ssi2_per_clk, 0, CCM_CGCR0, 14, get_rate_ipg, NULL, NULL);
DEFINE_CLOCK(cspi1_clk, 0, CCM_CGCR1, 5, get_rate_ipg, NULL, NULL);
DEFINE_CLOCK(cspi2_clk, 0, CCM_CGCR1, 6, get_rate_ipg, NULL, NULL);
DEFINE_CLOCK(cspi3_clk, 0, CCM_CGCR1, 7, get_rate_ipg, NULL, NULL);
+DEFINE_CLOCK(esdhc1_ahb_clk, 0, CCM_CGCR0, 21, get_rate_esdhc1, NULL, NULL);
+DEFINE_CLOCK(esdhc1_per_clk, 0, CCM_CGCR0, 3, get_rate_esdhc1, NULL,
+ &esdhc1_ahb_clk);
+DEFINE_CLOCK(esdhc2_ahb_clk, 0, CCM_CGCR0, 22, get_rate_esdhc2, NULL, NULL);
+DEFINE_CLOCK(esdhc2_per_clk, 0, CCM_CGCR0, 4, get_rate_esdhc2, NULL,
+ &esdhc2_ahb_clk);
DEFINE_CLOCK(fec_ahb_clk, 0, CCM_CGCR0, 23, NULL, NULL, NULL);
DEFINE_CLOCK(lcdc_ahb_clk, 0, CCM_CGCR0, 24, NULL, NULL, NULL);
DEFINE_CLOCK(lcdc_per_clk, 0, CCM_CGCR0, 7, NULL, NULL, &lcdc_ahb_clk);
@@ -238,10 +254,14 @@ DEFINE_CLOCK(lcdc_clk, 0, CCM_CGCR1, 29, get_rate_lcdc, NULL, &lcdc_per_clk);
DEFINE_CLOCK(wdt_clk, 0, CCM_CGCR2, 19, get_rate_ipg, NULL, NULL);
DEFINE_CLOCK(ssi1_clk, 0, CCM_CGCR2, 11, get_rate_ssi1, NULL, &ssi1_per_clk);
DEFINE_CLOCK(ssi2_clk, 1, CCM_CGCR2, 12, get_rate_ssi2, NULL, &ssi2_per_clk);
+DEFINE_CLOCK(esdhc1_clk, 0, CCM_CGCR1, 13, get_rate_esdhc1, NULL,
+ &esdhc1_per_clk);
+DEFINE_CLOCK(esdhc2_clk, 1, CCM_CGCR1, 14, get_rate_esdhc2, NULL,
+ &esdhc2_per_clk);
DEFINE_CLOCK(audmux_clk, 0, CCM_CGCR1, 0, NULL, NULL, NULL);
DEFINE_CLOCK(csi_clk, 0, CCM_CGCR1, 4, get_rate_csi, NULL, &csi_per_clk);
DEFINE_CLOCK(can1_clk, 0, CCM_CGCR1, 2, get_rate_ipg, NULL, NULL);
-DEFINE_CLOCK(can2_clk, 0, CCM_CGCR1, 3, get_rate_ipg, NULL, NULL);
+DEFINE_CLOCK(can2_clk, 1, CCM_CGCR1, 3, get_rate_ipg, NULL, NULL);
#define _REGISTER_CLOCK(d, n, c) \
{ \
@@ -261,9 +281,9 @@ static struct clk_lookup lookups[] = {
_REGISTER_CLOCK("mxc-ehci.2", "usb", usbotg_clk)
_REGISTER_CLOCK("fsl-usb2-udc", "usb", usbotg_clk)
_REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk)
- _REGISTER_CLOCK("spi_imx.0", NULL, cspi1_clk)
- _REGISTER_CLOCK("spi_imx.1", NULL, cspi2_clk)
- _REGISTER_CLOCK("spi_imx.2", NULL, cspi3_clk)
+ _REGISTER_CLOCK("imx25-cspi.0", NULL, cspi1_clk)
+ _REGISTER_CLOCK("imx25-cspi.1", NULL, cspi2_clk)
+ _REGISTER_CLOCK("imx25-cspi.2", NULL, cspi3_clk)
_REGISTER_CLOCK("mxc_pwm.0", NULL, pwm1_clk)
_REGISTER_CLOCK("mxc_pwm.1", NULL, pwm2_clk)
_REGISTER_CLOCK("mxc_pwm.2", NULL, pwm3_clk)
@@ -279,6 +299,8 @@ static struct clk_lookup lookups[] = {
_REGISTER_CLOCK("imx-wdt.0", NULL, wdt_clk)
_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
+ _REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)
+ _REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_clk)
_REGISTER_CLOCK("mx2-camera.0", NULL, csi_clk)
_REGISTER_CLOCK(NULL, "audmux", audmux_clk)
_REGISTER_CLOCK("flexcan.0", NULL, can1_clk)
diff --git a/arch/arm/mach-mx25/devices-imx25.h b/arch/arm/mach-mx25/devices-imx25.h
index d86a7c3ca8b0..93afa10b13cf 100644
--- a/arch/arm/mach-mx25/devices-imx25.h
+++ b/arch/arm/mach-mx25/devices-imx25.h
@@ -9,35 +9,46 @@
#include <mach/mx25.h>
#include <mach/devices-common.h>
+extern const struct imx_fec_data imx25_fec_data __initconst;
+#define imx25_add_fec(pdata) \
+ imx_add_fec(&imx25_fec_data, pdata)
+
#define imx25_add_flexcan0(pdata) \
imx_add_flexcan(0, MX25_CAN1_BASE_ADDR, SZ_16K, MX25_INT_CAN1, pdata)
#define imx25_add_flexcan1(pdata) \
imx_add_flexcan(1, MX25_CAN2_BASE_ADDR, SZ_16K, MX25_INT_CAN2, pdata)
-#define imx25_add_imx_i2c0(pdata) \
- imx_add_imx_i2c(0, MX25_I2C1_BASE_ADDR, SZ_16K, MX25_INT_I2C1, pdata)
-#define imx25_add_imx_i2c1(pdata) \
- imx_add_imx_i2c(1, MX25_I2C2_BASE_ADDR, SZ_16K, MX25_INT_I2C2, pdata)
-#define imx25_add_imx_i2c2(pdata) \
- imx_add_imx_i2c(2, MX25_I2C3_BASE_ADDR, SZ_16K, MX25_INT_I2C3, pdata)
-
-#define imx25_add_imx_uart0(pdata) \
- imx_add_imx_uart_1irq(0, MX25_UART1_BASE_ADDR, SZ_16K, MX25_INT_UART1, pdata)
-#define imx25_add_imx_uart1(pdata) \
- imx_add_imx_uart_1irq(1, MX25_UART2_BASE_ADDR, SZ_16K, MX25_INT_UART2, pdata)
-#define imx25_add_imx_uart2(pdata) \
- imx_add_imx_uart_1irq(2, MX25_UART3_BASE_ADDR, SZ_16K, MX25_INT_UART3, pdata)
-#define imx25_add_imx_uart3(pdata) \
- imx_add_imx_uart_1irq(3, MX25_UART4_BASE_ADDR, SZ_16K, MX25_INT_UART4, pdata)
-#define imx25_add_imx_uart4(pdata) \
- imx_add_imx_uart_1irq(4, MX25_UART5_BASE_ADDR, SZ_16K, MX25_INT_UART5, pdata)
+extern const struct imx_imx_i2c_data imx25_imx_i2c_data[] __initconst;
+#define imx25_add_imx_i2c(id, pdata) \
+ imx_add_imx_i2c(&imx25_imx_i2c_data[id], pdata)
+#define imx25_add_imx_i2c0(pdata) imx25_add_imx_i2c(0, pdata)
+#define imx25_add_imx_i2c1(pdata) imx25_add_imx_i2c(1, pdata)
+#define imx25_add_imx_i2c2(pdata) imx25_add_imx_i2c(2, pdata)
+
+extern const struct imx_imx_ssi_data imx25_imx_ssi_data[] __initconst;
+#define imx25_add_imx_ssi(id, pdata) \
+ imx_add_imx_ssi(&imx25_imx_ssi_data[id], pdata)
+
+extern const struct imx_imx_uart_1irq_data imx25_imx_uart_data[] __initconst;
+#define imx25_add_imx_uart(id, pdata) \
+ imx_add_imx_uart_1irq(&imx25_imx_uart_data[id], pdata)
+#define imx25_add_imx_uart0(pdata) imx25_add_imx_uart(0, pdata)
+#define imx25_add_imx_uart1(pdata) imx25_add_imx_uart(1, pdata)
+#define imx25_add_imx_uart2(pdata) imx25_add_imx_uart(2, pdata)
+#define imx25_add_imx_uart3(pdata) imx25_add_imx_uart(3, pdata)
+#define imx25_add_imx_uart4(pdata) imx25_add_imx_uart(4, pdata)
+extern const struct imx_mxc_nand_data imx25_mxc_nand_data __initconst;
#define imx25_add_mxc_nand(pdata) \
- imx_add_mxc_nand_v21(MX25_NFC_BASE_ADDR, MX25_INT_NANDFC, pdata)
-
-#define imx25_add_spi_imx0(pdata) \
- imx_add_spi_imx(0, MX25_CSPI1_BASE_ADDR, SZ_16K, MX25_INT_CSPI1, pdata)
-#define imx25_add_spi_imx1(pdata) \
- imx_add_spi_imx(1, MX25_CSPI2_BASE_ADDR, SZ_16K, MX25_INT_CSPI2, pdata)
-#define imx25_add_spi_imx2(pdata) \
- imx_add_spi_imx(2, MX25_CSPI3_BASE_ADDR, SZ_16K, MX25_INT_CSPI3, pdata)
+ imx_add_mxc_nand(&imx25_mxc_nand_data, pdata)
+
+extern const struct imx_spi_imx_data imx25_spi_imx_data[] __initconst;
+#define imx25_add_spi_imx(id, pdata) \
+ imx_add_spi_imx(&imx25_spi_imx_data[id], pdata)
+#define imx25_add_spi_imx0(pdata) imx25_add_spi_imx(0, pdata)
+#define imx25_add_spi_imx1(pdata) imx25_add_spi_imx(1, pdata)
+#define imx25_add_spi_imx2(pdata) imx25_add_spi_imx(2, pdata)
+
+extern const struct imx_esdhc_imx_data imx25_esdhc_data[] __initconst;
+#define imx25_add_esdhc(id, pdata) \
+ imx_add_esdhc(&imx25_esdhc_data[id], pdata)
diff --git a/arch/arm/mach-mx25/devices.c b/arch/arm/mach-mx25/devices.c
index 3468eb15b236..1d0eb3e85941 100644
--- a/arch/arm/mach-mx25/devices.c
+++ b/arch/arm/mach-mx25/devices.c
@@ -208,26 +208,6 @@ int __init imx25_register_gpios(void)
return mxc_gpio_init(imx_gpio_ports, ARRAY_SIZE(imx_gpio_ports));
}
-static struct resource mx25_fec_resources[] = {
- {
- .start = MX25_FEC_BASE_ADDR,
- .end = MX25_FEC_BASE_ADDR + 0xfff,
- .flags = IORESOURCE_MEM,
- },
- {
- .start = MX25_INT_FEC,
- .end = MX25_INT_FEC,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-struct platform_device mx25_fec_device = {
- .name = "fec",
- .id = 0,
- .num_resources = ARRAY_SIZE(mx25_fec_resources),
- .resource = mx25_fec_resources,
-};
-
static struct resource mx25_rtc_resources[] = {
{
.start = MX25_DRYICE_BASE_ADDR,
@@ -305,44 +285,6 @@ struct platform_device mx25_kpp_device = {
.resource = mx25_kpp_resources,
};
-static struct resource imx_ssi_resources0[] = {
- {
- .start = MX25_SSI1_BASE_ADDR,
- .end = MX25_SSI1_BASE_ADDR + 0x3fff,
- .flags = IORESOURCE_MEM,
- }, {
- .start = MX25_INT_SSI1,
- .end = MX25_INT_SSI1,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct resource imx_ssi_resources1[] = {
- {
- .start = MX25_SSI2_BASE_ADDR,
- .end = MX25_SSI2_BASE_ADDR + 0x3fff,
- .flags = IORESOURCE_MEM
- }, {
- .start = MX25_INT_SSI2,
- .end = MX25_INT_SSI2,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-struct platform_device imx_ssi_device0 = {
- .name = "imx-ssi",
- .id = 0,
- .num_resources = ARRAY_SIZE(imx_ssi_resources0),
- .resource = imx_ssi_resources0,
-};
-
-struct platform_device imx_ssi_device1 = {
- .name = "imx-ssi",
- .id = 1,
- .num_resources = ARRAY_SIZE(imx_ssi_resources1),
- .resource = imx_ssi_resources1,
-};
-
static struct resource mx25_csi_resources[] = {
{
.start = MX25_CSI_BASE_ADDR,
diff --git a/arch/arm/mach-mx25/devices.h b/arch/arm/mach-mx25/devices.h
index 4aceb68e35a7..7b70a43c3a4b 100644
--- a/arch/arm/mach-mx25/devices.h
+++ b/arch/arm/mach-mx25/devices.h
@@ -6,11 +6,8 @@ extern struct platform_device mxc_pwm_device1;
extern struct platform_device mxc_pwm_device2;
extern struct platform_device mxc_pwm_device3;
extern struct platform_device mxc_keypad_device;
-extern struct platform_device mx25_fec_device;
extern struct platform_device mx25_rtc_device;
extern struct platform_device mx25_fb_device;
extern struct platform_device mxc_wdt;
extern struct platform_device mx25_kpp_device;
-extern struct platform_device imx_ssi_device0;
-extern struct platform_device imx_ssi_device1;
extern struct platform_device mx25_csi_device;
diff --git a/arch/arm/mach-mx25/eukrea_mbimxsd-baseboard.c b/arch/arm/mach-mx25/eukrea_mbimxsd-baseboard.c
index 4aaadc753d3e..e765ac5d9a08 100644
--- a/arch/arm/mach-mx25/eukrea_mbimxsd-baseboard.c
+++ b/arch/arm/mach-mx25/eukrea_mbimxsd-baseboard.c
@@ -34,7 +34,6 @@
#include <mach/mx25.h>
#include <mach/imx-uart.h>
#include <mach/imxfb.h>
-#include <mach/ssi.h>
#include <mach/audmux.h>
#include "devices-imx25.h"
@@ -90,6 +89,9 @@ static struct pad_desc eukrea_mbimxsd_pads[] = {
MX25_PAD_KPP_COL2__AUD5_TXC,
MX25_PAD_KPP_COL1__AUD5_RXD,
MX25_PAD_KPP_COL0__AUD5_TXD,
+ /* CAN */
+ MX25_PAD_GPIO_D__CAN2_RX,
+ MX25_PAD_GPIO_C__CAN2_TX,
};
#define GPIO_LED1 83
@@ -114,6 +116,38 @@ static struct imx_fb_videomode eukrea_mximxsd_modes[] = {
},
.bpp = 16,
.pcr = 0xCAD08B80,
+ }, {
+ .mode = {
+ .name = "DVI-VGA",
+ .refresh = 60,
+ .xres = 640,
+ .yres = 480,
+ .pixclock = 32000,
+ .hsync_len = 7,
+ .left_margin = 100,
+ .right_margin = 100,
+ .vsync_len = 7,
+ .upper_margin = 7,
+ .lower_margin = 100,
+ },
+ .pcr = 0xFA208B80,
+ .bpp = 16,
+ }, {
+ .mode = {
+ .name = "DVI-SVGA",
+ .refresh = 60,
+ .xres = 800,
+ .yres = 600,
+ .pixclock = 25000,
+ .hsync_len = 7,
+ .left_margin = 75,
+ .right_margin = 75,
+ .vsync_len = 7,
+ .upper_margin = 7,
+ .lower_margin = 75,
+ },
+ .pcr = 0xFA208B80,
+ .bpp = 16,
},
};
@@ -205,7 +239,8 @@ static struct i2c_board_info eukrea_mbimxsd_i2c_devices[] = {
},
};
-struct imx_ssi_platform_data eukrea_mbimxsd_ssi_pdata = {
+static const
+struct imx_ssi_platform_data eukrea_mbimxsd_ssi_pdata __initconst = {
.flags = IMX_SSI_SYN | IMX_SSI_NET | IMX_SSI_USE_I2S_SLAVE,
};
@@ -239,7 +274,10 @@ void __init eukrea_mbimxsd25_baseboard_init(void)
imx25_add_imx_uart1(&uart_pdata);
mxc_register_device(&mx25_fb_device, &eukrea_mximxsd_fb_pdata);
- mxc_register_device(&imx_ssi_device0, &eukrea_mbimxsd_ssi_pdata);
+ imx25_add_imx_ssi(0, &eukrea_mbimxsd_ssi_pdata);
+
+ imx25_add_flexcan1(NULL);
+ imx25_add_esdhc(0, NULL);
gpio_request(GPIO_LED1, "LED1");
gpio_direction_output(GPIO_LED1, 1);
diff --git a/arch/arm/mach-mx25/mach-cpuimx25.c b/arch/arm/mach-mx25/mach-cpuimx25.c
index e064bb3d6919..f6f9ad60c25e 100644
--- a/arch/arm/mach-mx25/mach-cpuimx25.c
+++ b/arch/arm/mach-mx25/mach-cpuimx25.c
@@ -23,7 +23,6 @@
#include <linux/clk.h>
#include <linux/irq.h>
#include <linux/gpio.h>
-#include <linux/fec.h>
#include <linux/platform_device.h>
#include <linux/usb/otg.h>
#include <linux/usb/ulpi.h>
@@ -41,7 +40,6 @@
#include <mach/mxc_nand.h>
#include <mach/imxfb.h>
#include <mach/mxc_ehci.h>
-#include <mach/ulpi.h>
#include <mach/iomux-mx25.h>
#include "devices-imx25.h"
@@ -67,7 +65,7 @@ static struct pad_desc eukrea_cpuimx25_pads[] = {
MX25_PAD_I2C1_DAT__I2C1_DAT,
};
-static struct fec_platform_data mx25_fec_pdata = {
+static const struct fec_platform_data mx25_fec_pdata __initconst = {
.phy = PHY_INTERFACE_MODE_RMII,
};
@@ -129,24 +127,19 @@ static void __init eukrea_cpuimx25_init(void)
imx25_add_imx_uart0(&uart_pdata);
imx25_add_mxc_nand(&eukrea_cpuimx25_nand_board_info);
mxc_register_device(&mx25_rtc_device, NULL);
- mxc_register_device(&mx25_fec_device, &mx25_fec_pdata);
+ imx25_add_fec(&mx25_fec_pdata);
i2c_register_board_info(0, eukrea_cpuimx25_i2c_devices,
ARRAY_SIZE(eukrea_cpuimx25_i2c_devices));
imx25_add_imx_i2c0(&eukrea_cpuimx25_i2c0_data);
-#if defined(CONFIG_USB_ULPI)
- if (otg_mode_host) {
- otg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
- ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
-
+ if (otg_mode_host)
mxc_register_device(&mxc_otg, &otg_pdata);
- }
- mxc_register_device(&mxc_usbh2, &usbh2_pdata);
-#endif
- if (!otg_mode_host)
+ else
mxc_register_device(&otg_udc_device, &otg_device_pdata);
+ mxc_register_device(&mxc_usbh2, &usbh2_pdata);
+
#ifdef CONFIG_MACH_EUKREA_MBIMXSD25_BASEBOARD
eukrea_mbimxsd25_baseboard_init();
#endif
@@ -163,8 +156,6 @@ static struct sys_timer eukrea_cpuimx25_timer = {
MACHINE_START(EUKREA_CPUIMX25, "Eukrea CPUIMX25")
/* Maintainer: Eukrea Electromatique */
- .phys_io = MX25_AIPS1_BASE_ADDR,
- .io_pg_offst = ((MX25_AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
.boot_params = MX25_PHYS_OFFSET + 0x100,
.map_io = mx25_map_io,
.init_irq = mx25_init_irq,
diff --git a/arch/arm/mach-mx25/mach-mx25_3ds.c b/arch/arm/mach-mx25/mach-mx25_3ds.c
index 62bc21f11a71..80805107a73e 100644
--- a/arch/arm/mach-mx25/mach-mx25_3ds.c
+++ b/arch/arm/mach-mx25/mach-mx25_3ds.c
@@ -28,7 +28,6 @@
#include <linux/clk.h>
#include <linux/irq.h>
#include <linux/gpio.h>
-#include <linux/fec.h>
#include <linux/platform_device.h>
#include <linux/input/matrix_keypad.h>
@@ -99,7 +98,7 @@ static struct pad_desc mx25pdk_pads[] = {
MX25_PAD_KPP_COL3__KPP_COL3,
};
-static struct fec_platform_data mx25_fec_pdata = {
+static const struct fec_platform_data mx25_fec_pdata __initconst = {
.phy = PHY_INTERFACE_MODE_RMII,
};
@@ -192,7 +191,7 @@ static void __init mx25pdk_init(void)
mxc_register_device(&mxc_wdt, NULL);
mx25pdk_fec_reset();
- mxc_register_device(&mx25_fec_device, &mx25_fec_pdata);
+ imx25_add_fec(&mx25_fec_pdata);
mxc_register_device(&mx25_kpp_device, &mx25pdk_keymap_data);
}
@@ -207,8 +206,6 @@ static struct sys_timer mx25pdk_timer = {
MACHINE_START(MX25_3DS, "Freescale MX25PDK (3DS)")
/* Maintainer: Freescale Semiconductor, Inc. */
- .phys_io = MX25_AIPS1_BASE_ADDR,
- .io_pg_offst = ((MX25_AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
.boot_params = MX25_PHYS_OFFSET + 0x100,
.map_io = mx25_map_io,
.init_irq = mx25_init_irq,
diff --git a/arch/arm/mach-mx3/Kconfig b/arch/arm/mach-mx3/Kconfig
index 85beece802aa..096fd33f8ab9 100644
--- a/arch/arm/mach-mx3/Kconfig
+++ b/arch/arm/mach-mx3/Kconfig
@@ -9,6 +9,7 @@ config ARCH_MX35
bool
select ARCH_MXC_IOMUX_V3
select ARCH_MXC_AUDMUX_V2
+ select HAVE_EPIT
comment "MX3 platforms:"
@@ -16,6 +17,7 @@ config MACH_MX31ADS
bool "Support MX31ADS platforms"
select ARCH_MX31
select IMX_HAVE_PLATFORM_IMX_I2C
+ select IMX_HAVE_PLATFORM_IMX_SSI
select IMX_HAVE_PLATFORM_IMX_UART
default y
help
@@ -117,9 +119,11 @@ config MACH_PCM043
bool "Support Phytec pcm043 (i.MX35) platforms"
select ARCH_MX35
select IMX_HAVE_PLATFORM_IMX_I2C
+ select IMX_HAVE_PLATFORM_IMX_SSI
select IMX_HAVE_PLATFORM_IMX_UART
select IMX_HAVE_PLATFORM_MXC_NAND
select IMX_HAVE_PLATFORM_FLEXCAN
+ select IMX_HAVE_PLATFORM_ESDHC
select MXC_ULPI if USB_ULPI
help
Include support for Phytec pcm043 platform. This includes
@@ -140,6 +144,7 @@ config MACH_MX35_3DS
bool "Support MX35PDK platform"
select ARCH_MX35
select IMX_HAVE_PLATFORM_IMX_UART
+ select IMX_HAVE_PLATFORM_MXC_NAND
default n
help
Include support for MX35PDK platform. This includes specific
@@ -159,6 +164,8 @@ config MACH_EUKREA_CPUIMX35
select IMX_HAVE_PLATFORM_IMX_UART
select IMX_HAVE_PLATFORM_IMX_I2C
select IMX_HAVE_PLATFORM_MXC_NAND
+ select IMX_HAVE_PLATFORM_FLEXCAN
+ select IMX_HAVE_PLATFORM_ESDHC
select MXC_ULPI if USB_ULPI
help
Include support for Eukrea CPUIMX35 platform. This includes
@@ -170,8 +177,8 @@ choice
default MACH_EUKREA_MBIMXSD35_BASEBOARD
config MACH_EUKREA_MBIMXSD35_BASEBOARD
- prompt "Eukrea MBIMXSD development board"
- bool
+ bool "Eukrea MBIMXSD development board"
+ select IMX_HAVE_PLATFORM_IMX_SSI
help
This adds board specific devices that can be found on Eukrea's
MBIMXSD evaluation board.
diff --git a/arch/arm/mach-mx3/Makefile b/arch/arm/mach-mx3/Makefile
index 2bd7beceb991..8a182d0a3fcf 100644
--- a/arch/arm/mach-mx3/Makefile
+++ b/arch/arm/mach-mx3/Makefile
@@ -7,7 +7,6 @@
obj-y := mm.o devices.o cpu.o
CFLAGS_mm.o = -DIMX_NEEDS_DEPRECATED_SYMBOLS
CFLAGS_devices.o = -DIMX_NEEDS_DEPRECATED_SYMBOLS
-CFLAGS_cpu.o = -DIMX_NEEDS_DEPRECATED_SYMBOLS
obj-$(CONFIG_ARCH_MX31) += clock-imx31.o iomux-imx31.o
obj-$(CONFIG_ARCH_MX35) += clock-imx35.o
obj-$(CONFIG_MACH_MX31ADS) += mach-mx31ads.o
diff --git a/arch/arm/mach-mx3/clock-imx31.c b/arch/arm/mach-mx3/clock-imx31.c
index 9a9eb6de6127..109e98f323e0 100644
--- a/arch/arm/mach-mx3/clock-imx31.c
+++ b/arch/arm/mach-mx3/clock-imx31.c
@@ -477,7 +477,7 @@ DEFINE_CLOCK(epit1_clk, 0, MXC_CCM_CGR0, 6, NULL, NULL, &perclk_clk);
DEFINE_CLOCK(epit2_clk, 1, MXC_CCM_CGR0, 8, NULL, NULL, &perclk_clk);
DEFINE_CLOCK(iim_clk, 0, MXC_CCM_CGR0, 10, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(ata_clk, 0, MXC_CCM_CGR0, 12, NULL, NULL, &ipg_clk);
-DEFINE_CLOCK(sdma_clk1, 0, MXC_CCM_CGR0, 14, NULL, &sdma_clk1, &ahb_clk);
+DEFINE_CLOCK(sdma_clk1, 0, MXC_CCM_CGR0, 14, NULL, NULL, &ahb_clk);
DEFINE_CLOCK(cspi3_clk, 2, MXC_CCM_CGR0, 16, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(rng_clk, 0, MXC_CCM_CGR0, 18, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(uart1_clk, 0, MXC_CCM_CGR0, 20, NULL, NULL, &perclk_clk);
@@ -525,9 +525,9 @@ DEFINE_CLOCK(ipg_clk, 0, NULL, 0, ipg_get_rate, NULL, &ahb_clk);
static struct clk_lookup lookups[] = {
_REGISTER_CLOCK(NULL, "emi", emi_clk)
- _REGISTER_CLOCK("spi_imx.0", NULL, cspi1_clk)
- _REGISTER_CLOCK("spi_imx.1", NULL, cspi2_clk)
- _REGISTER_CLOCK("spi_imx.2", NULL, cspi3_clk)
+ _REGISTER_CLOCK("imx31-cspi.0", NULL, cspi1_clk)
+ _REGISTER_CLOCK("imx31-cspi.1", NULL, cspi2_clk)
+ _REGISTER_CLOCK("imx31-cspi.2", NULL, cspi3_clk)
_REGISTER_CLOCK(NULL, "gpt", gpt_clk)
_REGISTER_CLOCK(NULL, "pwm", pwm_clk)
_REGISTER_CLOCK("imx-wdt.0", NULL, wdog_clk)
@@ -564,7 +564,7 @@ static struct clk_lookup lookups[] = {
_REGISTER_CLOCK(NULL, "ata", ata_clk)
_REGISTER_CLOCK(NULL, "rtic", rtic_clk)
_REGISTER_CLOCK(NULL, "rng", rng_clk)
- _REGISTER_CLOCK(NULL, "sdma_ahb", sdma_clk1)
+ _REGISTER_CLOCK("imx-sdma", NULL, sdma_clk1)
_REGISTER_CLOCK(NULL, "sdma_ipg", sdma_clk2)
_REGISTER_CLOCK(NULL, "mstick", mstick1_clk)
_REGISTER_CLOCK(NULL, "mstick", mstick2_clk)
diff --git a/arch/arm/mach-mx3/clock-imx35.c b/arch/arm/mach-mx3/clock-imx35.c
index 7a62e744a8b0..61e4a318980a 100644
--- a/arch/arm/mach-mx3/clock-imx35.c
+++ b/arch/arm/mach-mx3/clock-imx35.c
@@ -364,8 +364,8 @@ DEFINE_CLOCK(cspi2_clk, 1, CCM_CGR0, 12, get_rate_ipg, NULL);
DEFINE_CLOCK(ect_clk, 0, CCM_CGR0, 14, get_rate_ipg, NULL);
DEFINE_CLOCK(edio_clk, 0, CCM_CGR0, 16, NULL, NULL);
DEFINE_CLOCK(emi_clk, 0, CCM_CGR0, 18, get_rate_ipg, NULL);
-DEFINE_CLOCK(epit1_clk, 0, CCM_CGR0, 20, get_rate_ipg_per, NULL);
-DEFINE_CLOCK(epit2_clk, 1, CCM_CGR0, 22, get_rate_ipg_per, NULL);
+DEFINE_CLOCK(epit1_clk, 0, CCM_CGR0, 20, get_rate_ipg, NULL);
+DEFINE_CLOCK(epit2_clk, 1, CCM_CGR0, 22, get_rate_ipg, NULL);
DEFINE_CLOCK(esai_clk, 0, CCM_CGR0, 24, NULL, NULL);
DEFINE_CLOCK(esdhc1_clk, 0, CCM_CGR0, 26, get_rate_sdhc, NULL);
DEFINE_CLOCK(esdhc2_clk, 1, CCM_CGR0, 28, get_rate_sdhc, NULL);
@@ -451,17 +451,17 @@ static struct clk_lookup lookups[] = {
_REGISTER_CLOCK(NULL, "ata", ata_clk)
_REGISTER_CLOCK("flexcan.0", NULL, can1_clk)
_REGISTER_CLOCK("flexcan.1", NULL, can2_clk)
- _REGISTER_CLOCK("spi_imx.0", NULL, cspi1_clk)
- _REGISTER_CLOCK("spi_imx.1", NULL, cspi2_clk)
+ _REGISTER_CLOCK("imx35-cspi.0", NULL, cspi1_clk)
+ _REGISTER_CLOCK("imx35-cspi.1", NULL, cspi2_clk)
_REGISTER_CLOCK(NULL, "ect", ect_clk)
_REGISTER_CLOCK(NULL, "edio", edio_clk)
_REGISTER_CLOCK(NULL, "emi", emi_clk)
- _REGISTER_CLOCK(NULL, "epit", epit1_clk)
- _REGISTER_CLOCK(NULL, "epit", epit2_clk)
+ _REGISTER_CLOCK("imx-epit.0", NULL, epit1_clk)
+ _REGISTER_CLOCK("imx-epit.1", NULL, epit2_clk)
_REGISTER_CLOCK(NULL, "esai", esai_clk)
- _REGISTER_CLOCK(NULL, "sdhc", esdhc1_clk)
- _REGISTER_CLOCK(NULL, "sdhc", esdhc2_clk)
- _REGISTER_CLOCK(NULL, "sdhc", esdhc3_clk)
+ _REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)
+ _REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_clk)
+ _REGISTER_CLOCK("sdhci-esdhc-imx.2", NULL, esdhc3_clk)
_REGISTER_CLOCK("fec.0", NULL, fec_clk)
_REGISTER_CLOCK(NULL, "gpio", gpio1_clk)
_REGISTER_CLOCK(NULL, "gpio", gpio2_clk)
@@ -482,7 +482,7 @@ static struct clk_lookup lookups[] = {
_REGISTER_CLOCK(NULL, "rtc", rtc_clk)
_REGISTER_CLOCK(NULL, "rtic", rtic_clk)
_REGISTER_CLOCK(NULL, "scc", scc_clk)
- _REGISTER_CLOCK(NULL, "sdma", sdma_clk)
+ _REGISTER_CLOCK("imx-sdma", NULL, sdma_clk)
_REGISTER_CLOCK(NULL, "spba", spba_clk)
_REGISTER_CLOCK(NULL, "spdif", spdif_clk)
_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
@@ -535,8 +535,16 @@ int __init mx35_clocks_init()
__raw_writel(cgr2, CCM_BASE + CCM_CGR2);
__raw_writel(cgr3, CCM_BASE + CCM_CGR3);
+ clk_enable(&iim_clk);
+ mx35_read_cpu_rev();
+
+#ifdef CONFIG_MXC_USE_EPIT
+ epit_timer_init(&epit1_clk,
+ MX35_IO_ADDRESS(MX35_EPIT1_BASE_ADDR), MX35_INT_EPIT1);
+#else
mxc_timer_init(&gpt_clk,
MX35_IO_ADDRESS(MX35_GPT1_BASE_ADDR), MX35_INT_GPT);
+#endif
return 0;
}
diff --git a/arch/arm/mach-mx3/cpu.c b/arch/arm/mach-mx3/cpu.c
index 861afe0fe3ad..d00a75457812 100644
--- a/arch/arm/mach-mx3/cpu.c
+++ b/arch/arm/mach-mx3/cpu.c
@@ -25,15 +25,15 @@ struct mx3_cpu_type {
};
static struct mx3_cpu_type mx31_cpu_type[] __initdata = {
- { .srev = 0x00, .name = "i.MX31(L)", .v = "1.0", .rev = CHIP_REV_1_0 },
- { .srev = 0x10, .name = "i.MX31", .v = "1.1", .rev = CHIP_REV_1_1 },
- { .srev = 0x11, .name = "i.MX31L", .v = "1.1", .rev = CHIP_REV_1_1 },
- { .srev = 0x12, .name = "i.MX31", .v = "1.15", .rev = CHIP_REV_1_1 },
- { .srev = 0x13, .name = "i.MX31L", .v = "1.15", .rev = CHIP_REV_1_1 },
- { .srev = 0x14, .name = "i.MX31", .v = "1.2", .rev = CHIP_REV_1_2 },
- { .srev = 0x15, .name = "i.MX31L", .v = "1.2", .rev = CHIP_REV_1_2 },
- { .srev = 0x28, .name = "i.MX31", .v = "2.0", .rev = CHIP_REV_2_0 },
- { .srev = 0x29, .name = "i.MX31L", .v = "2.0", .rev = CHIP_REV_2_0 },
+ { .srev = 0x00, .name = "i.MX31(L)", .v = "1.0", .rev = MX3x_CHIP_REV_1_0 },
+ { .srev = 0x10, .name = "i.MX31", .v = "1.1", .rev = MX3x_CHIP_REV_1_1 },
+ { .srev = 0x11, .name = "i.MX31L", .v = "1.1", .rev = MX3x_CHIP_REV_1_1 },
+ { .srev = 0x12, .name = "i.MX31", .v = "1.15", .rev = MX3x_CHIP_REV_1_1 },
+ { .srev = 0x13, .name = "i.MX31L", .v = "1.15", .rev = MX3x_CHIP_REV_1_1 },
+ { .srev = 0x14, .name = "i.MX31", .v = "1.2", .rev = MX3x_CHIP_REV_1_2 },
+ { .srev = 0x15, .name = "i.MX31L", .v = "1.2", .rev = MX3x_CHIP_REV_1_2 },
+ { .srev = 0x28, .name = "i.MX31", .v = "2.0", .rev = MX3x_CHIP_REV_2_0 },
+ { .srev = 0x29, .name = "i.MX31L", .v = "2.0", .rev = MX3x_CHIP_REV_2_0 },
};
void __init mx31_read_cpu_rev(void)
@@ -41,7 +41,7 @@ void __init mx31_read_cpu_rev(void)
u32 i, srev;
/* read SREV register from IIM module */
- srev = __raw_readl(IO_ADDRESS(IIM_BASE_ADDR + MXC_IIMSREV));
+ srev = __raw_readl(MX31_IO_ADDRESS(MX31_IIM_BASE_ADDR + MXC_IIMSREV));
for (i = 0; i < ARRAY_SIZE(mx31_cpu_type); i++)
if (srev == mx31_cpu_type[i].srev) {
@@ -55,3 +55,30 @@ void __init mx31_read_cpu_rev(void)
printk(KERN_WARNING "Unknown CPU identifier. srev = %02x\n", srev);
}
+
+unsigned int mx35_cpu_rev;
+EXPORT_SYMBOL(mx35_cpu_rev);
+
+void __init mx35_read_cpu_rev(void)
+{
+ u32 rev;
+ char *srev = "unknown";
+
+ rev = __raw_readl(MX35_IO_ADDRESS(MX35_IIM_BASE_ADDR + MXC_IIMSREV));
+ switch (rev) {
+ case 0x00:
+ mx35_cpu_rev = MX3x_CHIP_REV_1_0;
+ srev = "1.0";
+ break;
+ case 0x10:
+ mx35_cpu_rev = MX3x_CHIP_REV_2_0;
+ srev = "2.0";
+ break;
+ case 0x11:
+ mx35_cpu_rev = MX3x_CHIP_REV_2_1;
+ srev = "2.1";
+ break;
+ }
+
+ printk(KERN_INFO "CPU identified as i.MX35, silicon rev %s\n", srev);
+}
diff --git a/arch/arm/mach-mx3/devices-imx31.h b/arch/arm/mach-mx3/devices-imx31.h
index 3b1a44a20585..de9598590eba 100644
--- a/arch/arm/mach-mx3/devices-imx31.h
+++ b/arch/arm/mach-mx3/devices-imx31.h
@@ -9,30 +9,33 @@
#include <mach/mx31.h>
#include <mach/devices-common.h>
-#define imx31_add_imx_i2c0(pdata) \
- imx_add_imx_i2c(0, MX31_I2C1_BASE_ADDR, SZ_4K, MX31_INT_I2C1, pdata)
-#define imx31_add_imx_i2c1(pdata) \
- imx_add_imx_i2c(1, MX31_I2C2_BASE_ADDR, SZ_4K, MX31_INT_I2C2, pdata)
-#define imx31_add_imx_i2c2(pdata) \
- imx_add_imx_i2c(2, MX31_I2C3_BASE_ADDR, SZ_4K, MX31_INT_I2C3, pdata)
+extern const struct imx_imx_i2c_data imx31_imx_i2c_data[] __initconst;
+#define imx31_add_imx_i2c(id, pdata) \
+ imx_add_imx_i2c(&imx31_imx_i2c_data[id], pdata)
+#define imx31_add_imx_i2c0(pdata) imx31_add_imx_i2c(0, pdata)
+#define imx31_add_imx_i2c1(pdata) imx31_add_imx_i2c(1, pdata)
+#define imx31_add_imx_i2c2(pdata) imx31_add_imx_i2c(2, pdata)
-#define imx31_add_imx_uart0(pdata) \
- imx_add_imx_uart_1irq(0, MX31_UART1_BASE_ADDR, SZ_16K, MX31_INT_UART1, pdata)
-#define imx31_add_imx_uart1(pdata) \
- imx_add_imx_uart_1irq(1, MX31_UART2_BASE_ADDR, SZ_16K, MX31_INT_UART2, pdata)
-#define imx31_add_imx_uart2(pdata) \
- imx_add_imx_uart_1irq(2, MX31_UART3_BASE_ADDR, SZ_16K, MX31_INT_UART3, pdata)
-#define imx31_add_imx_uart3(pdata) \
- imx_add_imx_uart_1irq(3, MX31_UART4_BASE_ADDR, SZ_16K, MX31_INT_UART4, pdata)
-#define imx31_add_imx_uart4(pdata) \
- imx_add_imx_uart_1irq(4, MX31_UART5_BASE_ADDR, SZ_16K, MX31_INT_UART5, pdata)
+extern const struct imx_imx_ssi_data imx31_imx_ssi_data[] __initconst;
+#define imx31_add_imx_ssi(id, pdata) \
+ imx_add_imx_ssi(&imx31_imx_ssi_data[id], pdata)
+extern const struct imx_imx_uart_1irq_data imx31_imx_uart_data[] __initconst;
+#define imx31_add_imx_uart(id, pdata) \
+ imx_add_imx_uart_1irq(&imx31_imx_uart_data[id], pdata)
+#define imx31_add_imx_uart0(pdata) imx31_add_imx_uart(0, pdata)
+#define imx31_add_imx_uart1(pdata) imx31_add_imx_uart(1, pdata)
+#define imx31_add_imx_uart2(pdata) imx31_add_imx_uart(2, pdata)
+#define imx31_add_imx_uart3(pdata) imx31_add_imx_uart(3, pdata)
+#define imx31_add_imx_uart4(pdata) imx31_add_imx_uart(4, pdata)
+
+extern const struct imx_mxc_nand_data imx31_mxc_nand_data __initconst;
#define imx31_add_mxc_nand(pdata) \
- imx_add_mxc_nand_v1(MX31_NFC_BASE_ADDR, MX31_INT_NANDFC, pdata)
+ imx_add_mxc_nand(&imx31_mxc_nand_data, pdata)
-#define imx31_add_spi_imx0(pdata) \
- imx_add_spi_imx(0, MX31_CSPI1_BASE_ADDR, SZ_4K, MX31_INT_CSPI1, pdata)
-#define imx31_add_spi_imx1(pdata) \
- imx_add_spi_imx(1, MX31_CSPI2_BASE_ADDR, SZ_4K, MX31_INT_CSPI2, pdata)
-#define imx31_add_spi_imx2(pdata) \
- imx_add_spi_imx(2, MX31_CSPI3_BASE_ADDR, SZ_4K, MX31_INT_CSPI3, pdata)
+extern const struct imx_spi_imx_data imx31_cspi_data[] __initconst;
+#define imx31_add_cspi(id, pdata) \
+ imx_add_spi_imx(&imx31_cspi_data[id], pdata)
+#define imx31_add_spi_imx0(pdata) imx31_add_cspi(0, pdata)
+#define imx31_add_spi_imx1(pdata) imx31_add_cspi(1, pdata)
+#define imx31_add_spi_imx2(pdata) imx31_add_cspi(2, pdata)
diff --git a/arch/arm/mach-mx3/devices-imx35.h b/arch/arm/mach-mx3/devices-imx35.h
index f6a431a4c3d2..5eb917b638d0 100644
--- a/arch/arm/mach-mx3/devices-imx35.h
+++ b/arch/arm/mach-mx3/devices-imx35.h
@@ -9,29 +9,43 @@
#include <mach/mx35.h>
#include <mach/devices-common.h>
+extern const struct imx_fec_data imx35_fec_data __initconst;
+#define imx35_add_fec(pdata) \
+ imx_add_fec(&imx35_fec_data, pdata)
+
#define imx35_add_flexcan0(pdata) \
imx_add_flexcan(0, MX35_CAN1_BASE_ADDR, SZ_16K, MX35_INT_CAN1, pdata)
#define imx35_add_flexcan1(pdata) \
imx_add_flexcan(1, MX35_CAN2_BASE_ADDR, SZ_16K, MX35_INT_CAN2, pdata)
-#define imx35_add_imx_i2c0(pdata) \
- imx_add_imx_i2c(0, MX35_I2C1_BASE_ADDR, SZ_4K, MX35_INT_I2C1, pdata)
-#define imx35_add_imx_i2c1(pdata) \
- imx_add_imx_i2c(1, MX35_I2C2_BASE_ADDR, SZ_4K, MX35_INT_I2C2, pdata)
-#define imx35_add_imx_i2c2(pdata) \
- imx_add_imx_i2c(2, MX35_I2C3_BASE_ADDR, SZ_4K, MX35_INT_I2C3, pdata)
+extern const struct imx_imx_i2c_data imx35_imx_i2c_data[] __initconst;
+#define imx35_add_imx_i2c(id, pdata) \
+ imx_add_imx_i2c(&imx35_imx_i2c_data[id], pdata)
+#define imx35_add_imx_i2c0(pdata) imx35_add_imx_i2c(0, pdata)
+#define imx35_add_imx_i2c1(pdata) imx35_add_imx_i2c(1, pdata)
+#define imx35_add_imx_i2c2(pdata) imx35_add_imx_i2c(2, pdata)
+
+extern const struct imx_imx_ssi_data imx35_imx_ssi_data[] __initconst;
+#define imx35_add_imx_ssi(id, pdata) \
+ imx_add_imx_ssi(&imx35_imx_ssi_data[id], pdata)
-#define imx35_add_imx_uart0(pdata) \
- imx_add_imx_uart_1irq(0, MX35_UART1_BASE_ADDR, SZ_16K, MX35_INT_UART1, pdata)
-#define imx35_add_imx_uart1(pdata) \
- imx_add_imx_uart_1irq(1, MX35_UART2_BASE_ADDR, SZ_16K, MX35_INT_UART2, pdata)
-#define imx35_add_imx_uart2(pdata) \
- imx_add_imx_uart_1irq(2, MX35_UART3_BASE_ADDR, SZ_16K, MX35_INT_UART3, pdata)
+extern const struct imx_imx_uart_1irq_data imx35_imx_uart_data[] __initconst;
+#define imx35_add_imx_uart(id, pdata) \
+ imx_add_imx_uart_1irq(&imx35_imx_uart_data[id], pdata)
+#define imx35_add_imx_uart0(pdata) imx35_add_imx_uart(0, pdata)
+#define imx35_add_imx_uart1(pdata) imx35_add_imx_uart(1, pdata)
+#define imx35_add_imx_uart2(pdata) imx35_add_imx_uart(2, pdata)
+extern const struct imx_mxc_nand_data imx35_mxc_nand_data __initconst;
#define imx35_add_mxc_nand(pdata) \
- imx_add_mxc_nand_v21(MX35_NFC_BASE_ADDR, MX35_INT_NANDFC, pdata)
+ imx_add_mxc_nand(&imx35_mxc_nand_data, pdata)
+
+extern const struct imx_spi_imx_data imx35_cspi_data[] __initconst;
+#define imx35_add_cspi(id, pdata) \
+ imx_add_spi_imx(&imx35_cspi_data[id], pdata)
+#define imx35_add_spi_imx0(pdata) imx35_add_cspi(0, pdata)
+#define imx35_add_spi_imx1(pdata) imx35_add_cspi(1, pdata)
-#define imx35_add_spi_imx0(pdata) \
- imx_add_spi_imx(0, MX35_CSPI1_BASE_ADDR, SZ_4K, MX35_INT_CSPI1, pdata)
-#define imx35_add_spi_imx1(pdata) \
- imx_add_spi_imx(1, MX35_CSPI2_BASE_ADDR, SZ_4K, MX35_INT_CSPI2, pdata)
+extern const struct imx_esdhc_imx_data imx35_esdhc_data[] __initconst;
+#define imx35_add_esdhc(id, pdata) \
+ imx_add_esdhc(&imx35_esdhc_data[id], pdata)
diff --git a/arch/arm/mach-mx3/devices.c b/arch/arm/mach-mx3/devices.c
index a4fd1a26fc91..f4dff11aaee7 100644
--- a/arch/arm/mach-mx3/devices.c
+++ b/arch/arm/mach-mx3/devices.c
@@ -281,65 +281,6 @@ struct platform_device mxc_usbh2 = {
.num_resources = ARRAY_SIZE(mxc_usbh2_resources),
};
-#if defined(CONFIG_ARCH_MX35)
-static struct resource mxc_fec_resources[] = {
- {
- .start = MXC_FEC_BASE_ADDR,
- .end = MXC_FEC_BASE_ADDR + 0xfff,
- .flags = IORESOURCE_MEM,
- }, {
- .start = MXC_INT_FEC,
- .end = MXC_INT_FEC,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-struct platform_device mxc_fec_device = {
- .name = "fec",
- .id = 0,
- .num_resources = ARRAY_SIZE(mxc_fec_resources),
- .resource = mxc_fec_resources,
-};
-#endif
-
-static struct resource imx_ssi_resources0[] = {
- {
- .start = SSI1_BASE_ADDR,
- .end = SSI1_BASE_ADDR + 0xfff,
- .flags = IORESOURCE_MEM,
- }, {
- .start = MX31_INT_SSI1,
- .end = MX31_INT_SSI1,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct resource imx_ssi_resources1[] = {
- {
- .start = SSI2_BASE_ADDR,
- .end = SSI2_BASE_ADDR + 0xfff,
- .flags = IORESOURCE_MEM
- }, {
- .start = MX31_INT_SSI2,
- .end = MX31_INT_SSI2,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-struct platform_device imx_ssi_device0 = {
- .name = "imx-ssi",
- .id = 0,
- .num_resources = ARRAY_SIZE(imx_ssi_resources0),
- .resource = imx_ssi_resources0,
-};
-
-struct platform_device imx_ssi_device1 = {
- .name = "imx-ssi",
- .id = 1,
- .num_resources = ARRAY_SIZE(imx_ssi_resources1),
- .resource = imx_ssi_resources1,
-};
-
static struct resource imx_wdt_resources[] = {
{
.flags = IORESOURCE_MEM,
@@ -410,10 +351,6 @@ static int __init mx3_devices_init(void)
mxc_usbh1_resources[0].end = MX35_OTG_BASE_ADDR + 0x5ff;
mxc_usbh1_resources[1].start = MXC_INT_USBHS;
mxc_usbh1_resources[1].end = MXC_INT_USBHS;
- imx_ssi_resources0[1].start = MX35_INT_SSI1;
- imx_ssi_resources0[1].end = MX35_INT_SSI1;
- imx_ssi_resources1[1].start = MX35_INT_SSI2;
- imx_ssi_resources1[1].end = MX35_INT_SSI2;
imx_wdt_resources[0].start = MX35_WDOG_BASE_ADDR;
imx_wdt_resources[0].end = MX35_WDOG_BASE_ADDR + 0x3fff;
}
diff --git a/arch/arm/mach-mx3/devices.h b/arch/arm/mach-mx3/devices.h
index e5535234839f..585f814473d5 100644
--- a/arch/arm/mach-mx3/devices.h
+++ b/arch/arm/mach-mx3/devices.h
@@ -2,7 +2,6 @@ extern struct platform_device mxc_w1_master_device;
extern struct platform_device mx3_ipu;
extern struct platform_device mx3_fb;
extern struct platform_device mx3_camera;
-extern struct platform_device mxc_fec_device;
extern struct platform_device mxcsdhc_device0;
extern struct platform_device mxcsdhc_device1;
extern struct platform_device mxc_otg_udc_device;
@@ -10,9 +9,6 @@ extern struct platform_device mxc_otg_host;
extern struct platform_device mxc_usbh1;
extern struct platform_device mxc_usbh2;
extern struct platform_device mxc_rnga_device;
-extern struct platform_device imx_ssi_device0;
-extern struct platform_device imx_ssi_device1;
-extern struct platform_device imx_ssi_device1;
extern struct platform_device imx_wdt_device0;
extern struct platform_device imx_rtc_device0;
extern struct platform_device imx_kpp_device;
diff --git a/arch/arm/mach-mx3/eukrea_mbimxsd-baseboard.c b/arch/arm/mach-mx3/eukrea_mbimxsd-baseboard.c
index f8f15e3ac7a0..1abc10d52922 100644
--- a/arch/arm/mach-mx3/eukrea_mbimxsd-baseboard.c
+++ b/arch/arm/mach-mx3/eukrea_mbimxsd-baseboard.c
@@ -43,14 +43,13 @@
#include <mach/ipu.h>
#include <mach/mx3fb.h>
#include <mach/audmux.h>
-#include <mach/ssi.h>
#include "devices-imx35.h"
#include "devices.h"
static const struct fb_videomode fb_modedb[] = {
{
- .name = "CMO_QVGA",
+ .name = "CMO-QVGA",
.refresh = 60,
.xres = 320,
.yres = 240,
@@ -65,6 +64,40 @@ static const struct fb_videomode fb_modedb[] = {
.vmode = FB_VMODE_NONINTERLACED,
.flag = 0,
},
+ {
+ .name = "DVI-VGA",
+ .refresh = 60,
+ .xres = 640,
+ .yres = 480,
+ .pixclock = 32000,
+ .left_margin = 100,
+ .right_margin = 100,
+ .upper_margin = 7,
+ .lower_margin = 100,
+ .hsync_len = 7,
+ .vsync_len = 7,
+ .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT |
+ FB_SYNC_OE_ACT_HIGH | FB_SYNC_CLK_INVERT,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,
+ },
+ {
+ .name = "DVI-SVGA",
+ .refresh = 60,
+ .xres = 800,
+ .yres = 600,
+ .pixclock = 25000,
+ .left_margin = 75,
+ .right_margin = 75,
+ .upper_margin = 7,
+ .lower_margin = 75,
+ .hsync_len = 7,
+ .vsync_len = 7,
+ .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT |
+ FB_SYNC_OE_ACT_HIGH | FB_SYNC_CLK_INVERT,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,
+ },
};
static struct ipu_platform_data mx3_ipu_data = {
@@ -73,7 +106,7 @@ static struct ipu_platform_data mx3_ipu_data = {
static struct mx3fb_platform_data mx3fb_pdata = {
.dma_dev = &mx3_ipu.dev,
- .name = "CMO_QVGA",
+ .name = "CMO-QVGA",
.mode = fb_modedb,
.num_modes = ARRAY_SIZE(fb_modedb),
};
@@ -120,6 +153,16 @@ static struct pad_desc eukrea_mbimxsd_pads[] = {
MX35_PAD_STXD4__AUDMUX_AUD4_TXD,
MX35_PAD_SRXD4__AUDMUX_AUD4_RXD,
MX35_PAD_SCK4__AUDMUX_AUD4_TXC,
+ /* CAN2 */
+ MX35_PAD_TX5_RX0__CAN2_TXCAN,
+ MX35_PAD_TX4_RX1__CAN2_RXCAN,
+ /* SDCARD */
+ MX35_PAD_SD1_CMD__ESDHC1_CMD,
+ MX35_PAD_SD1_CLK__ESDHC1_CLK,
+ MX35_PAD_SD1_DATA0__ESDHC1_DAT0,
+ MX35_PAD_SD1_DATA1__ESDHC1_DAT1,
+ MX35_PAD_SD1_DATA2__ESDHC1_DAT2,
+ MX35_PAD_SD1_DATA3__ESDHC1_DAT3,
};
#define GPIO_LED1 (2 * 32 + 29)
@@ -206,7 +249,8 @@ static struct i2c_board_info eukrea_mbimxsd_i2c_devices[] = {
},
};
-struct imx_ssi_platform_data eukrea_mbimxsd_ssi_pdata = {
+static const
+struct imx_ssi_platform_data eukrea_mbimxsd_ssi_pdata __initconst = {
.flags = IMX_SSI_SYN | IMX_SSI_NET | IMX_SSI_USE_I2S_SLAVE,
};
@@ -242,7 +286,10 @@ void __init eukrea_mbimxsd35_baseboard_init(void)
mxc_register_device(&mx3_ipu, &mx3_ipu_data);
mxc_register_device(&mx3_fb, &mx3fb_pdata);
- mxc_register_device(&imx_ssi_device0, &eukrea_mbimxsd_ssi_pdata);
+ imx35_add_imx_ssi(0, &eukrea_mbimxsd_ssi_pdata);
+
+ imx35_add_flexcan1(NULL);
+ imx35_add_esdhc(0, NULL);
gpio_request(GPIO_LED1, "LED1");
gpio_direction_output(GPIO_LED1, 1);
@@ -254,7 +301,7 @@ void __init eukrea_mbimxsd35_baseboard_init(void)
gpio_request(GPIO_LCDPWR, "LCDPWR");
gpio_direction_output(GPIO_LCDPWR, 1);
- gpio_free(GPIO_SWITCH1);
+ gpio_free(GPIO_LCDPWR);
i2c_register_board_info(0, eukrea_mbimxsd_i2c_devices,
ARRAY_SIZE(eukrea_mbimxsd_i2c_devices));
diff --git a/arch/arm/mach-mx3/mach-armadillo5x0.c b/arch/arm/mach-mx3/mach-armadillo5x0.c
index 68879c996a55..aaa30fe18f85 100644
--- a/arch/arm/mach-mx3/mach-armadillo5x0.c
+++ b/arch/arm/mach-mx3/mach-armadillo5x0.c
@@ -571,8 +571,6 @@ static struct sys_timer armadillo5x0_timer = {
MACHINE_START(ARMADILLO5X0, "Armadillo-500")
/* Maintainer: Alberto Panizzo */
- .phys_io = MX31_AIPS1_BASE_ADDR,
- .io_pg_offst = (MX31_AIPS1_BASE_ADDR_VIRT >> 18) & 0xfffc,
.boot_params = MX3x_PHYS_OFFSET + 0x100,
.map_io = mx31_map_io,
.init_irq = mx31_init_irq,
diff --git a/arch/arm/mach-mx3/mach-cpuimx35.c b/arch/arm/mach-mx3/mach-cpuimx35.c
index 2a4f8b781ba4..9fde873f5889 100644
--- a/arch/arm/mach-mx3/mach-cpuimx35.c
+++ b/arch/arm/mach-mx3/mach-cpuimx35.c
@@ -31,6 +31,7 @@
#include <linux/usb/otg.h>
#include <linux/usb/ulpi.h>
#include <linux/fsl_devices.h>
+#include <linux/i2c-gpio.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -43,7 +44,6 @@
#include <mach/iomux-mx35.h>
#include <mach/mxc_nand.h>
#include <mach/mxc_ehci.h>
-#include <mach/ulpi.h>
#include "devices-imx35.h"
#include "devices.h"
@@ -53,39 +53,16 @@ static const struct imxuart_platform_data uart_pdata __initconst = {
};
static const struct imxi2c_platform_data
-eukrea_cpuimx35_i2c0_data __initconst = {
- .bitrate = 50000,
+ eukrea_cpuimx35_i2c0_data __initconst = {
+ .bitrate = 100000,
};
-#define TSC2007_IRQGPIO (2 * 32 + 2)
-static int ts_get_pendown_state(void)
-{
- int val = 0;
- gpio_free(TSC2007_IRQGPIO);
- gpio_request(TSC2007_IRQGPIO, NULL);
- gpio_direction_input(TSC2007_IRQGPIO);
-
- val = gpio_get_value(TSC2007_IRQGPIO);
-
- gpio_free(TSC2007_IRQGPIO);
- gpio_request(TSC2007_IRQGPIO, NULL);
-
- return val ? 0 : 1;
-}
-
-static int ts_init(void)
-{
- gpio_request(TSC2007_IRQGPIO, NULL);
- return 0;
-}
-
static struct tsc2007_platform_data tsc2007_info = {
.model = 2007,
.x_plate_ohms = 180,
- .get_pendown_state = ts_get_pendown_state,
- .init_platform_hw = ts_init,
};
+#define TSC2007_IRQGPIO (2 * 32 + 2)
static struct i2c_board_info eukrea_cpuimx35_i2c_devices[] = {
{
I2C_BOARD_INFO("pcf8563", 0x51),
@@ -98,7 +75,6 @@ static struct i2c_board_info eukrea_cpuimx35_i2c_devices[] = {
};
static struct platform_device *devices[] __initdata = {
- &mxc_fec_device,
&imx_wdt_device0,
};
@@ -135,18 +111,18 @@ static struct pad_desc eukrea_cpuimx35_pads[] = {
};
static const struct mxc_nand_platform_data
-eukrea_cpuimx35_nand_board_info __initconst = {
+ eukrea_cpuimx35_nand_board_info __initconst = {
.width = 1,
.hw_ecc = 1,
.flash_bbt = 1,
};
-static struct mxc_usbh_platform_data otg_pdata = {
+static struct mxc_usbh_platform_data __maybe_unused otg_pdata = {
.portsc = MXC_EHCI_MODE_UTMI,
.flags = MXC_EHCI_INTERFACE_DIFF_UNI,
};
-static struct mxc_usbh_platform_data usbh1_pdata = {
+static struct mxc_usbh_platform_data __maybe_unused usbh1_pdata = {
.portsc = MXC_EHCI_MODE_SERIAL,
.flags = MXC_EHCI_INTERFACE_SINGLE_UNI | MXC_EHCI_INTERNAL_PHY |
MXC_EHCI_IPPUE_DOWN,
@@ -155,6 +131,7 @@ static struct mxc_usbh_platform_data usbh1_pdata = {
static struct fsl_usb2_platform_data otg_device_pdata = {
.operating_mode = FSL_USB2_DR_DEVICE,
.phy_mode = FSL_USB2_PHY_UTMI,
+ .workaround = FLS_USB2_WORKAROUND_ENGCM09152,
};
static int otg_mode_host;
@@ -180,6 +157,7 @@ static void __init mxc_board_init(void)
mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx35_pads,
ARRAY_SIZE(eukrea_cpuimx35_pads));
+ imx35_add_fec(NULL);
platform_add_devices(devices, ARRAY_SIZE(devices));
imx35_add_imx_uart0(&uart_pdata);
@@ -189,18 +167,13 @@ static void __init mxc_board_init(void)
ARRAY_SIZE(eukrea_cpuimx35_i2c_devices));
imx35_add_imx_i2c0(&eukrea_cpuimx35_i2c0_data);
-#if defined(CONFIG_USB_ULPI)
- if (otg_mode_host) {
- otg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
- ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
-
+ if (otg_mode_host)
mxc_register_device(&mxc_otg_host, &otg_pdata);
- }
- mxc_register_device(&mxc_usbh1, &usbh1_pdata);
-#endif
- if (!otg_mode_host)
+ else
mxc_register_device(&mxc_otg_udc_device, &otg_device_pdata);
+ mxc_register_device(&mxc_usbh1, &usbh1_pdata);
+
#ifdef CONFIG_MACH_EUKREA_MBIMXSD35_BASEBOARD
eukrea_mbimxsd35_baseboard_init();
#endif
@@ -217,8 +190,6 @@ struct sys_timer eukrea_cpuimx35_timer = {
MACHINE_START(EUKREA_CPUIMX35, "Eukrea CPUIMX35")
/* Maintainer: Eukrea Electromatique */
- .phys_io = MX35_AIPS1_BASE_ADDR,
- .io_pg_offst = ((MX35_AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
.boot_params = MX3x_PHYS_OFFSET + 0x100,
.map_io = mx35_map_io,
.init_irq = mx35_init_irq,
diff --git a/arch/arm/mach-mx3/mach-kzm_arm11_01.c b/arch/arm/mach-mx3/mach-kzm_arm11_01.c
index 5b23e416d6c7..042cd5655e17 100644
--- a/arch/arm/mach-mx3/mach-kzm_arm11_01.c
+++ b/arch/arm/mach-mx3/mach-kzm_arm11_01.c
@@ -274,8 +274,6 @@ static struct sys_timer kzm_timer = {
* initialize __mach_desc_KZM_ARM11_01 data structure.
*/
MACHINE_START(KZM_ARM11_01, "Kyoto Microcomputer Co., Ltd. KZM-ARM11-01")
- .phys_io = MX31_AIPS1_BASE_ADDR,
- .io_pg_offst = (MX31_AIPS1_BASE_ADDR_VIRT >> 18) & 0xfffc,
.boot_params = MX3x_PHYS_OFFSET + 0x100,
.map_io = kzm_map_io,
.init_irq = mx31_init_irq,
diff --git a/arch/arm/mach-mx3/mach-mx31_3ds.c b/arch/arm/mach-mx3/mach-mx31_3ds.c
index 6fe69e124d30..5c1d0e86c91e 100644
--- a/arch/arm/mach-mx3/mach-mx31_3ds.c
+++ b/arch/arm/mach-mx3/mach-mx31_3ds.c
@@ -301,8 +301,6 @@ static struct sys_timer mx31_3ds_timer = {
*/
MACHINE_START(MX31_3DS, "Freescale MX31PDK (3DS)")
/* Maintainer: Freescale Semiconductor, Inc. */
- .phys_io = MX31_AIPS1_BASE_ADDR,
- .io_pg_offst = (MX31_AIPS1_BASE_ADDR_VIRT >> 18) & 0xfffc,
.boot_params = MX3x_PHYS_OFFSET + 0x100,
.map_io = mx31_3ds_map_io,
.init_irq = mx31_init_irq,
diff --git a/arch/arm/mach-mx3/mach-mx31ads.c b/arch/arm/mach-mx3/mach-mx31ads.c
index 94b3e7c42404..b993b9bf6179 100644
--- a/arch/arm/mach-mx3/mach-mx31ads.c
+++ b/arch/arm/mach-mx3/mach-mx31ads.c
@@ -22,13 +22,13 @@
#include <linux/i2c.h>
#include <linux/irq.h>
-#include <mach/hardware.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/time.h>
#include <asm/memory.h>
#include <asm/mach/map.h>
#include <mach/common.h>
+#include <mach/board-mx31ads.h>
#include <mach/iomux-mx3.h>
#ifdef CONFIG_MACH_MX31ADS_WM1133_EV1
@@ -40,10 +40,6 @@
#include "devices-imx31.h"
#include "devices.h"
-/* Base address of PBC controller */
-#define PBC_BASE_ADDRESS MX31_CS4_BASE_ADDR_VIRT
-/* Offsets for the PBC Controller register */
-
/* PBC Board interrupt status register */
#define PBC_INTSTATUS 0x000016
@@ -67,7 +63,6 @@
#define PBC_INTMASK_CLEAR_REG (PBC_INTMASK_CLEAR + PBC_BASE_ADDRESS)
#define EXPIO_PARENT_INT IOMUX_TO_IRQ(MX31_PIN_GPIO1_4)
-#define MXC_EXP_IO_BASE (MXC_BOARD_IRQ_START)
#define MXC_IRQ_TO_EXPIO(irq) ((irq) - MXC_EXP_IO_BASE)
#define EXPIO_INT_XUART_INTA (MXC_EXP_IO_BASE + 10)
@@ -517,7 +512,7 @@ static unsigned int ssi_pins[] = {
static void mxc_init_audio(void)
{
- mxc_register_device(&imx_ssi_device0, NULL);
+ imx31_add_imx_ssi(0, NULL);
mxc_iomux_setup_multiple_pins(ssi_pins, ARRAY_SIZE(ssi_pins), "ssi");
}
@@ -574,8 +569,6 @@ static struct sys_timer mx31ads_timer = {
*/
MACHINE_START(MX31ADS, "Freescale MX31ADS")
/* Maintainer: Freescale Semiconductor, Inc. */
- .phys_io = MX31_AIPS1_BASE_ADDR,
- .io_pg_offst = (MX31_AIPS1_BASE_ADDR_VIRT >> 18) & 0xfffc,
.boot_params = MX3x_PHYS_OFFSET + 0x100,
.map_io = mx31ads_map_io,
.init_irq = mx31ads_init_irq,
diff --git a/arch/arm/mach-mx3/mach-mx31lilly.c b/arch/arm/mach-mx3/mach-mx31lilly.c
index 7c37daabb757..42f47faa6fd6 100644
--- a/arch/arm/mach-mx3/mach-mx31lilly.c
+++ b/arch/arm/mach-mx3/mach-mx31lilly.c
@@ -348,8 +348,6 @@ static struct sys_timer mx31lilly_timer = {
};
MACHINE_START(LILLY1131, "INCO startec LILLY-1131")
- .phys_io = MX31_AIPS1_BASE_ADDR,
- .io_pg_offst = (MX31_AIPS1_BASE_ADDR_VIRT >> 18) & 0xfffc,
.boot_params = MX3x_PHYS_OFFSET + 0x100,
.map_io = mx31_map_io,
.init_irq = mx31_init_irq,
diff --git a/arch/arm/mach-mx3/mach-mx31lite.c b/arch/arm/mach-mx3/mach-mx31lite.c
index f66a9576d8c2..b93895814cdf 100644
--- a/arch/arm/mach-mx3/mach-mx31lite.c
+++ b/arch/arm/mach-mx3/mach-mx31lite.c
@@ -282,8 +282,6 @@ struct sys_timer mx31lite_timer = {
MACHINE_START(MX31LITE, "LogicPD i.MX31 SOM")
/* Maintainer: Freescale Semiconductor, Inc. */
- .phys_io = MX31_AIPS1_BASE_ADDR,
- .io_pg_offst = (MX31_AIPS1_BASE_ADDR_VIRT >> 18) & 0xfffc,
.boot_params = MX3x_PHYS_OFFSET + 0x100,
.map_io = mx31lite_map_io,
.init_irq = mx31_init_irq,
diff --git a/arch/arm/mach-mx3/mach-mx31moboard.c b/arch/arm/mach-mx3/mach-mx31moboard.c
index 7a075e8bf2d4..eb5f426df224 100644
--- a/arch/arm/mach-mx3/mach-mx31moboard.c
+++ b/arch/arm/mach-mx3/mach-mx31moboard.c
@@ -560,8 +560,6 @@ struct sys_timer mx31moboard_timer = {
MACHINE_START(MX31MOBOARD, "EPFL Mobots mx31moboard")
/* Maintainer: Valentin Longchamp, EPFL Mobots group */
- .phys_io = MX31_AIPS1_BASE_ADDR,
- .io_pg_offst = (MX31_AIPS1_BASE_ADDR_VIRT >> 18) & 0xfffc,
.boot_params = MX3x_PHYS_OFFSET + 0x100,
.map_io = mx31_map_io,
.init_irq = mx31_init_irq,
diff --git a/arch/arm/mach-mx3/mach-mx35_3ds.c b/arch/arm/mach-mx3/mach-mx35_3ds.c
index 1c30d7212f17..05f628d90725 100644
--- a/arch/arm/mach-mx3/mach-mx35_3ds.c
+++ b/arch/arm/mach-mx3/mach-mx35_3ds.c
@@ -1,5 +1,6 @@
/*
* Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2009 Marc Kleine-Budde, Pengutronix
*
* Author: Fabio Estevam <fabio.estevam@freescale.com>
*
@@ -27,6 +28,8 @@
#include <linux/gpio.h>
#include <linux/fsl_devices.h>
+#include <linux/mtd/physmap.h>
+
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/time.h>
@@ -35,6 +38,7 @@
#include <mach/hardware.h>
#include <mach/common.h>
#include <mach/iomux-mx35.h>
+#include <mach/mxc_ehci.h>
#include "devices-imx35.h"
#include "devices.h"
@@ -43,8 +47,34 @@ static const struct imxuart_platform_data uart_pdata __initconst = {
.flags = IMXUART_HAVE_RTSCTS,
};
+static struct physmap_flash_data mx35pdk_flash_data = {
+ .width = 2,
+};
+
+static struct resource mx35pdk_flash_resource = {
+ .start = MX35_CS0_BASE_ADDR,
+ .end = MX35_CS0_BASE_ADDR + SZ_64M - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device mx35pdk_flash = {
+ .name = "physmap-flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &mx35pdk_flash_data,
+ },
+ .resource = &mx35pdk_flash_resource,
+ .num_resources = 1,
+};
+
+static const struct mxc_nand_platform_data mx35pdk_nand_board_info __initconst = {
+ .width = 1,
+ .hw_ecc = 1,
+ .flash_bbt = 1,
+};
+
static struct platform_device *devices[] __initdata = {
- &mxc_fec_device,
+ &mx35pdk_flash,
};
static struct pad_desc mx35pdk_pads[] = {
@@ -75,14 +105,24 @@ static struct pad_desc mx35pdk_pads[] = {
/* USBOTG */
MX35_PAD_USBOTG_PWR__USB_TOP_USBOTG_PWR,
MX35_PAD_USBOTG_OC__USB_TOP_USBOTG_OC,
+ /* USBH1 */
+ MX35_PAD_I2C2_CLK__USB_TOP_USBH2_PWR,
+ MX35_PAD_I2C2_DAT__USB_TOP_USBH2_OC,
};
/* OTG config */
-static struct fsl_usb2_platform_data usb_pdata = {
+static struct fsl_usb2_platform_data usb_otg_pdata = {
.operating_mode = FSL_USB2_DR_DEVICE,
.phy_mode = FSL_USB2_PHY_UTMI_WIDE,
};
+/* USB HOST config */
+static struct mxc_usbh_platform_data usb_host_pdata = {
+ .portsc = MXC_EHCI_MODE_SERIAL,
+ .flags = MXC_EHCI_INTERFACE_SINGLE_UNI |
+ MXC_EHCI_INTERNAL_PHY,
+};
+
/*
* Board specific initialization.
*/
@@ -90,11 +130,16 @@ static void __init mxc_board_init(void)
{
mxc_iomux_v3_setup_multiple_pads(mx35pdk_pads, ARRAY_SIZE(mx35pdk_pads));
+ imx35_add_fec(NULL);
platform_add_devices(devices, ARRAY_SIZE(devices));
imx35_add_imx_uart0(&uart_pdata);
- mxc_register_device(&mxc_otg_udc_device, &usb_pdata);
+ mxc_register_device(&mxc_otg_udc_device, &usb_otg_pdata);
+
+ mxc_register_device(&mxc_usbh1, &usb_host_pdata);
+
+ imx35_add_mxc_nand(&mx35pdk_nand_board_info);
}
static void __init mx35pdk_timer_init(void)
@@ -108,8 +153,6 @@ struct sys_timer mx35pdk_timer = {
MACHINE_START(MX35_3DS, "Freescale MX35PDK")
/* Maintainer: Freescale Semiconductor, Inc */
- .phys_io = MX35_AIPS1_BASE_ADDR,
- .io_pg_offst = ((MX35_AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
.boot_params = MX3x_PHYS_OFFSET + 0x100,
.map_io = mx35_map_io,
.init_irq = mx35_init_irq,
diff --git a/arch/arm/mach-mx3/mach-pcm037.c b/arch/arm/mach-mx3/mach-pcm037.c
index 214de11b20b9..86e86c1300d5 100644
--- a/arch/arm/mach-mx3/mach-pcm037.c
+++ b/arch/arm/mach-mx3/mach-pcm037.c
@@ -680,8 +680,6 @@ struct sys_timer pcm037_timer = {
MACHINE_START(PCM037, "Phytec Phycore pcm037")
/* Maintainer: Pengutronix */
- .phys_io = MX31_AIPS1_BASE_ADDR,
- .io_pg_offst = (MX31_AIPS1_BASE_ADDR_VIRT >> 18) & 0xfffc,
.boot_params = MX3x_PHYS_OFFSET + 0x100,
.map_io = mx31_map_io,
.init_irq = mx31_init_irq,
diff --git a/arch/arm/mach-mx3/mach-pcm037_eet.c b/arch/arm/mach-mx3/mach-pcm037_eet.c
index c8b98218efee..99e0894e07db 100644
--- a/arch/arm/mach-mx3/mach-pcm037_eet.c
+++ b/arch/arm/mach-mx3/mach-pcm037_eet.c
@@ -19,6 +19,7 @@
#include "pcm037.h"
#include "devices.h"
+#include "devices-imx31.h"
static unsigned int pcm037_eet_pins[] = {
/* Reserve and hardwire GPIO 57 high - S6E63D6 chipselect */
@@ -181,7 +182,7 @@ static int eet_init_devices(void)
/* SPI */
spi_register_board_info(pcm037_spi_dev, ARRAY_SIZE(pcm037_spi_dev));
#if defined(CONFIG_SPI_IMX) || defined(CONFIG_SPI_IMX_MODULE)
- imx35_add_spi_imx0(&pcm037_spi1_pdata);
+ imx31_add_spi_imx0(&pcm037_spi1_pdata);
#endif
platform_device_register(&pcm037_gpio_keys_device);
diff --git a/arch/arm/mach-mx3/mach-pcm043.c b/arch/arm/mach-mx3/mach-pcm043.c
index 28886f0e62f9..4e1de87995d4 100644
--- a/arch/arm/mach-mx3/mach-pcm043.c
+++ b/arch/arm/mach-mx3/mach-pcm043.c
@@ -42,7 +42,6 @@
#include <mach/mxc_ehci.h>
#include <mach/ulpi.h>
#include <mach/audmux.h>
-#include <mach/ssi.h>
#include "devices-imx35.h"
#include "devices.h"
@@ -141,7 +140,6 @@ static struct i2c_board_info pcm043_i2c_devices[] = {
static struct platform_device *devices[] __initdata = {
&pcm043_flash,
- &mxc_fec_device,
&imx_wdt_device0,
};
@@ -217,6 +215,13 @@ static struct pad_desc pcm043_pads[] = {
/* CAN2 */
MX35_PAD_TX5_RX0__CAN2_TXCAN,
MX35_PAD_TX4_RX1__CAN2_RXCAN,
+ /* esdhc */
+ MX35_PAD_SD1_CMD__ESDHC1_CMD,
+ MX35_PAD_SD1_CLK__ESDHC1_CLK,
+ MX35_PAD_SD1_DATA0__ESDHC1_DAT0,
+ MX35_PAD_SD1_DATA1__ESDHC1_DAT1,
+ MX35_PAD_SD1_DATA2__ESDHC1_DAT2,
+ MX35_PAD_SD1_DATA3__ESDHC1_DAT3,
};
#define AC97_GPIO_TXFS (1 * 32 + 31)
@@ -293,7 +298,7 @@ err1:
mdelay(1);
}
-static struct imx_ssi_platform_data pcm043_ssi_pdata = {
+static const struct imx_ssi_platform_data pcm043_ssi_pdata __initconst = {
.ac97_reset = pcm043_ac97_cold_reset,
.ac97_warm_reset = pcm043_ac97_warm_reset,
.flags = IMX_SSI_USE_AC97,
@@ -357,11 +362,12 @@ static void __init mxc_board_init(void)
MXC_AUDMUX_V2_PTCR_TCLKDIR, /* clock is output */
MXC_AUDMUX_V2_PDCR_RXDSEL(3));
+ imx35_add_fec(NULL);
platform_add_devices(devices, ARRAY_SIZE(devices));
imx35_add_imx_uart0(&uart_pdata);
imx35_add_mxc_nand(&pcm037_nand_board_info);
- mxc_register_device(&imx_ssi_device0, &pcm043_ssi_pdata);
+ imx35_add_imx_ssi(0, &pcm043_ssi_pdata);
imx35_add_imx_uart1(&uart_pdata);
@@ -389,6 +395,7 @@ static void __init mxc_board_init(void)
mxc_register_device(&mxc_otg_udc_device, &otg_device_pdata);
imx35_add_flexcan1(NULL);
+ imx35_add_esdhc(0, NULL);
}
static void __init pcm043_timer_init(void)
@@ -402,8 +409,6 @@ struct sys_timer pcm043_timer = {
MACHINE_START(PCM043, "Phytec Phycore pcm043")
/* Maintainer: Pengutronix */
- .phys_io = MX35_AIPS1_BASE_ADDR,
- .io_pg_offst = ((MX35_AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
.boot_params = MX3x_PHYS_OFFSET + 0x100,
.map_io = mx35_map_io,
.init_irq = mx35_init_irq,
diff --git a/arch/arm/mach-mx3/mach-qong.c b/arch/arm/mach-mx3/mach-qong.c
index c8c380eef74c..fd1050c40964 100644
--- a/arch/arm/mach-mx3/mach-qong.c
+++ b/arch/arm/mach-mx3/mach-qong.c
@@ -270,8 +270,6 @@ static struct sys_timer qong_timer = {
MACHINE_START(QONG, "Dave/DENX QongEVB-LITE")
/* Maintainer: DENX Software Engineering GmbH */
- .phys_io = MX31_AIPS1_BASE_ADDR,
- .io_pg_offst = (MX31_AIPS1_BASE_ADDR_VIRT >> 18) & 0xfffc,
.boot_params = MX3x_PHYS_OFFSET + 0x100,
.map_io = mx31_map_io,
.init_irq = mx31_init_irq,
diff --git a/arch/arm/mach-mx3/mm.c b/arch/arm/mach-mx3/mm.c
index 20e48c0195c4..b4ffc531a82c 100644
--- a/arch/arm/mach-mx3/mm.c
+++ b/arch/arm/mach-mx3/mm.c
@@ -110,6 +110,24 @@ void __init mx35_init_irq(void)
static int mxc_init_l2x0(void)
{
void __iomem *l2x0_base;
+ void __iomem *clkctl_base;
+/*
+ * First of all, we must repair broken chip settings. There are some
+ * i.MX35 CPUs in the wild, comming with bogus L2 cache settings. These
+ * misconfigured CPUs will run amok immediately when the L2 cache gets enabled.
+ * Workaraound is to setup the correct register setting prior enabling the
+ * L2 cache. This should not hurt already working CPUs, as they are using the
+ * same value
+ */
+#define L2_MEM_VAL 0x10
+
+ clkctl_base = ioremap(MX35_CLKCTL_BASE_ADDR, 4096);
+ if (clkctl_base != NULL) {
+ writel(0x00000515, clkctl_base + L2_MEM_VAL);
+ iounmap(clkctl_base);
+ } else {
+ pr_err("L2 cache: Cannot fix timing. Trying to continue without\n");
+ }
l2x0_base = ioremap(L2CC_BASE_ADDR, 4096);
if (IS_ERR(l2x0_base)) {
diff --git a/arch/arm/mach-mx5/Kconfig b/arch/arm/mach-mx5/Kconfig
index 0848db5dd364..a2df9ac37996 100644
--- a/arch/arm/mach-mx5/Kconfig
+++ b/arch/arm/mach-mx5/Kconfig
@@ -5,11 +5,14 @@ config ARCH_MX51
default y
select MXC_TZIC
select ARCH_MXC_IOMUX_V3
+ select ARCH_MXC_AUDMUX_V2
comment "MX5 platforms:"
config MACH_MX51_BABBAGE
bool "Support MX51 BABBAGE platforms"
+ select IMX_HAVE_PLATFORM_IMX_I2C
+ select IMX_HAVE_PLATFORM_IMX_UART
help
Include support for MX51 Babbage platform, also known as MX51EVK in
u-boot. This includes specific configurations for the board and its
@@ -17,6 +20,8 @@ config MACH_MX51_BABBAGE
config MACH_MX51_3DS
bool "Support MX51PDK (3DS)"
+ select IMX_HAVE_PLATFORM_IMX_UART
+ select IMX_HAVE_PLATFORM_SPI_IMX
select MXC_DEBUG_BOARD
help
Include support for MX51PDK (3DS) platform. This includes specific
@@ -24,6 +29,10 @@ config MACH_MX51_3DS
config MACH_EUKREA_CPUIMX51
bool "Support Eukrea CPUIMX51 module"
+ select IMX_HAVE_PLATFORM_IMX_I2C
+ select IMX_HAVE_PLATFORM_IMX_UART
+ select IMX_HAVE_PLATFORM_MXC_NAND
+ select IMX_HAVE_PLATFORM_SPI_IMX
help
Include support for Eukrea CPUIMX51 platform. This includes
specific configurations for the module and its peripherals.
@@ -36,10 +45,43 @@ choice
config MACH_EUKREA_MBIMX51_BASEBOARD
prompt "Eukrea MBIMX51 development board"
bool
+ select IMX_HAVE_PLATFORM_ESDHC
help
This adds board specific devices that can be found on Eukrea's
MBIMX51 evaluation board.
endchoice
+config MACH_EUKREA_CPUIMX51SD
+ bool "Support Eukrea CPUIMX51SD module"
+ select IMX_HAVE_PLATFORM_IMX_I2C
+ select IMX_HAVE_PLATFORM_SPI_IMX
+ select IMX_HAVE_PLATFORM_IMX_UART
+ select IMX_HAVE_PLATFORM_MXC_NAND
+ help
+ Include support for Eukrea CPUIMX51SD platform. This includes
+ specific configurations for the module and its peripherals.
+
+choice
+ prompt "Baseboard"
+ depends on MACH_EUKREA_CPUIMX51SD
+ default MACH_EUKREA_MBIMXSD51_BASEBOARD
+
+config MACH_EUKREA_MBIMXSD51_BASEBOARD
+ prompt "Eukrea MBIMXSD development board"
+ bool
+ select IMX_HAVE_PLATFORM_ESDHC
+ help
+ This adds board specific devices that can be found on Eukrea's
+ MBIMXSD evaluation board.
+
+endchoice
+
+config MACH_MX51_EFIKAMX
+ bool "Support MX51 Genesi Efika MX nettop"
+ select IMX_HAVE_PLATFORM_IMX_UART
+ help
+ Include support for Genesi Efika MX nettop. This includes specific
+ configurations for the board and its peripherals.
+
endif
diff --git a/arch/arm/mach-mx5/Makefile b/arch/arm/mach-mx5/Makefile
index 86c66e7f52f3..1769c161a60d 100644
--- a/arch/arm/mach-mx5/Makefile
+++ b/arch/arm/mach-mx5/Makefile
@@ -9,3 +9,6 @@ obj-$(CONFIG_MACH_MX51_BABBAGE) += board-mx51_babbage.o
obj-$(CONFIG_MACH_MX51_3DS) += board-mx51_3ds.o
obj-$(CONFIG_MACH_EUKREA_CPUIMX51) += board-cpuimx51.o
obj-$(CONFIG_MACH_EUKREA_MBIMX51_BASEBOARD) += eukrea_mbimx51-baseboard.o
+obj-$(CONFIG_MACH_EUKREA_CPUIMX51SD) += board-cpuimx51sd.o
+obj-$(CONFIG_MACH_EUKREA_MBIMXSD51_BASEBOARD) += eukrea_mbimxsd-baseboard.o
+obj-$(CONFIG_MACH_MX51_EFIKAMX) += board-mx51_efikamx.o
diff --git a/arch/arm/mach-mx5/board-cpuimx51.c b/arch/arm/mach-mx5/board-cpuimx51.c
index 623607a20f57..6a9792fd0a76 100644
--- a/arch/arm/mach-mx5/board-cpuimx51.c
+++ b/arch/arm/mach-mx5/board-cpuimx51.c
@@ -28,9 +28,7 @@
#include <mach/eukrea-baseboards.h>
#include <mach/common.h>
#include <mach/hardware.h>
-#include <mach/imx-uart.h>
#include <mach/iomux-mx51.h>
-#include <mach/i2c.h>
#include <mach/mxc_ehci.h>
#include <asm/irq.h>
@@ -39,6 +37,7 @@
#include <asm/mach/arch.h>
#include <asm/mach/time.h>
+#include "devices-imx51.h"
#include "devices.h"
#define CPUIMX51_USBH1_STP (0*32 + 27)
@@ -109,7 +108,6 @@ static struct platform_device serial_device = {
#endif
static struct platform_device *devices[] __initdata = {
- &mxc_fec_device,
#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
&serial_device,
#endif
@@ -148,11 +146,19 @@ static struct pad_desc eukrea_cpuimx51_pads[] = {
MX51_PAD_USBH1_STP__USBH1_STP,
};
-static struct imxuart_platform_data uart_pdata = {
+static const struct mxc_nand_platform_data
+ eukrea_cpuimx51_nand_board_info __initconst = {
+ .width = 1,
+ .hw_ecc = 1,
+ .flash_bbt = 1,
+};
+
+static const struct imxuart_platform_data uart_pdata __initconst = {
.flags = IMXUART_HAVE_RTSCTS,
};
-static struct imxi2c_platform_data eukrea_cpuimx51_i2c_data = {
+static const
+struct imxi2c_platform_data eukrea_cpuimx51_i2c_data __initconst = {
.bitrate = 100000,
};
@@ -239,7 +245,9 @@ static void __init eukrea_cpuimx51_init(void)
mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx51_pads,
ARRAY_SIZE(eukrea_cpuimx51_pads));
- mxc_register_device(&mxc_uart_device0, &uart_pdata);
+ imx51_add_imx_uart(0, &uart_pdata);
+ imx51_add_mxc_nand(&eukrea_cpuimx51_nand_board_info);
+
gpio_request(CPUIMX51_QUARTA_GPIO, "quarta_irq");
gpio_direction_input(CPUIMX51_QUARTA_GPIO);
gpio_free(CPUIMX51_QUARTA_GPIO);
@@ -253,9 +261,10 @@ static void __init eukrea_cpuimx51_init(void)
gpio_direction_input(CPUIMX51_QUARTD_GPIO);
gpio_free(CPUIMX51_QUARTD_GPIO);
+ imx51_add_fec(NULL);
platform_add_devices(devices, ARRAY_SIZE(devices));
- mxc_register_device(&mxc_i2c_device1, &eukrea_cpuimx51_i2c_data);
+ imx51_add_imx_i2c(1, &eukrea_cpuimx51_i2c_data);
i2c_register_board_info(1, eukrea_cpuimx51_i2c_devices,
ARRAY_SIZE(eukrea_cpuimx51_i2c_devices));
@@ -283,8 +292,6 @@ static struct sys_timer mxc_timer = {
MACHINE_START(EUKREA_CPUIMX51, "Eukrea CPUIMX51 Module")
/* Maintainer: Eric Bénard <eric@eukrea.com> */
- .phys_io = MX51_AIPS1_BASE_ADDR,
- .io_pg_offst = ((MX51_AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
.boot_params = PHYS_OFFSET + 0x100,
.map_io = mx51_map_io,
.init_irq = mx51_init_irq,
diff --git a/arch/arm/mach-mx5/board-cpuimx51sd.c b/arch/arm/mach-mx5/board-cpuimx51sd.c
new file mode 100644
index 000000000000..4b3a6119c5fb
--- /dev/null
+++ b/arch/arm/mach-mx5/board-cpuimx51sd.c
@@ -0,0 +1,331 @@
+/*
+ *
+ * Copyright (C) 2010 Eric Bénard <eric@eukrea.com>
+ *
+ * based on board-mx51_babbage.c which is
+ * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/i2c/tsc2007.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/fsl_devices.h>
+#include <linux/i2c-gpio.h>
+#include <linux/spi/spi.h>
+#include <linux/can/platform/mcp251x.h>
+
+#include <mach/eukrea-baseboards.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx51.h>
+#include <mach/mxc_ehci.h>
+
+#include <asm/irq.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "devices-imx51.h"
+#include "devices.h"
+
+#define USBH1_RST (1*32 + 28)
+#define ETH_RST (1*32 + 31)
+#define TSC2007_IRQGPIO (2*32 + 12)
+#define CAN_IRQGPIO (0*32 + 1)
+#define CAN_RST (3*32 + 15)
+#define CAN_NCS (3*32 + 24)
+#define CAN_RXOBF (0*32 + 4)
+#define CAN_RX1BF (0*32 + 6)
+#define CAN_TXORTS (0*32 + 7)
+#define CAN_TX1RTS (0*32 + 8)
+#define CAN_TX2RTS (0*32 + 9)
+#define I2C_SCL (3*32 + 16)
+#define I2C_SDA (3*32 + 17)
+
+/* USB_CTRL_1 */
+#define MX51_USB_CTRL_1_OFFSET 0x10
+#define MX51_USB_CTRL_UH1_EXT_CLK_EN (1 << 25)
+
+#define MX51_USB_PLLDIV_12_MHZ 0x00
+#define MX51_USB_PLL_DIV_19_2_MHZ 0x01
+#define MX51_USB_PLL_DIV_24_MHZ 0x02
+
+#define CPUIMX51SD_GPIO_3_12 IOMUX_PAD(0x57C, 0x194, 3, 0x0, 0, \
+ MX51_PAD_CTRL_1 | PAD_CTL_PUS_22K_UP)
+
+static struct pad_desc eukrea_cpuimx51sd_pads[] = {
+ /* UART1 */
+ MX51_PAD_UART1_RXD__UART1_RXD,
+ MX51_PAD_UART1_TXD__UART1_TXD,
+ MX51_PAD_UART1_RTS__UART1_RTS,
+ MX51_PAD_UART1_CTS__UART1_CTS,
+
+ /* USB HOST1 */
+ MX51_PAD_USBH1_CLK__USBH1_CLK,
+ MX51_PAD_USBH1_DIR__USBH1_DIR,
+ MX51_PAD_USBH1_NXT__USBH1_NXT,
+ MX51_PAD_USBH1_DATA0__USBH1_DATA0,
+ MX51_PAD_USBH1_DATA1__USBH1_DATA1,
+ MX51_PAD_USBH1_DATA2__USBH1_DATA2,
+ MX51_PAD_USBH1_DATA3__USBH1_DATA3,
+ MX51_PAD_USBH1_DATA4__USBH1_DATA4,
+ MX51_PAD_USBH1_DATA5__USBH1_DATA5,
+ MX51_PAD_USBH1_DATA6__USBH1_DATA6,
+ MX51_PAD_USBH1_DATA7__USBH1_DATA7,
+ MX51_PAD_USBH1_STP__USBH1_STP,
+ MX51_PAD_EIM_CS3__GPIO_2_28, /* PHY nRESET */
+
+ /* FEC */
+ MX51_PAD_EIM_DTACK__GPIO_2_31, /* PHY nRESET */
+
+ /* HSI2C */
+ MX51_PAD_I2C1_CLK__GPIO_4_16,
+ MX51_PAD_I2C1_DAT__GPIO_4_17,
+
+ /* CAN */
+ MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI,
+ MX51_PAD_CSPI1_MISO__ECSPI1_MISO,
+ MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK,
+ MX51_PAD_CSPI1_SS0__GPIO_4_24, /* nCS */
+ MX51_PAD_CSI2_PIXCLK__GPIO_4_15, /* nReset */
+ MX51_PAD_GPIO_1_1__GPIO_1_1, /* IRQ */
+ MX51_PAD_GPIO_1_4__GPIO_1_4, /* Control signals */
+ MX51_PAD_GPIO_1_6__GPIO_1_6,
+ MX51_PAD_GPIO_1_7__GPIO_1_7,
+ MX51_PAD_GPIO_1_8__GPIO_1_8,
+ MX51_PAD_GPIO_1_9__GPIO_1_9,
+
+ /* Touchscreen */
+ CPUIMX51SD_GPIO_3_12, /* IRQ */
+};
+
+static const struct imxuart_platform_data uart_pdata __initconst = {
+ .flags = IMXUART_HAVE_RTSCTS,
+};
+
+static int ts_get_pendown_state(void)
+{
+ return gpio_get_value(TSC2007_IRQGPIO) ? 0 : 1;
+}
+
+static struct tsc2007_platform_data tsc2007_info = {
+ .model = 2007,
+ .x_plate_ohms = 180,
+ .get_pendown_state = ts_get_pendown_state,
+};
+
+static struct i2c_board_info eukrea_cpuimx51sd_i2c_devices[] = {
+ {
+ I2C_BOARD_INFO("pcf8563", 0x51),
+ }, {
+ I2C_BOARD_INFO("tsc2007", 0x49),
+ .type = "tsc2007",
+ .platform_data = &tsc2007_info,
+ .irq = gpio_to_irq(TSC2007_IRQGPIO),
+ },
+};
+
+static const struct mxc_nand_platform_data
+ eukrea_cpuimx51sd_nand_board_info __initconst = {
+ .width = 1,
+ .hw_ecc = 1,
+ .flash_bbt = 1,
+};
+
+/* This function is board specific as the bit mask for the plldiv will also
+be different for other Freescale SoCs, thus a common bitmask is not
+possible and cannot get place in /plat-mxc/ehci.c.*/
+static int initialize_otg_port(struct platform_device *pdev)
+{
+ u32 v;
+ void __iomem *usb_base;
+ void __iomem *usbother_base;
+
+ usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+ usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
+
+ /* Set the PHY clock to 19.2MHz */
+ v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
+ v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK;
+ v |= MX51_USB_PLL_DIV_19_2_MHZ;
+ __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
+ iounmap(usb_base);
+ return 0;
+}
+
+static int initialize_usbh1_port(struct platform_device *pdev)
+{
+ u32 v;
+ void __iomem *usb_base;
+ void __iomem *usbother_base;
+
+ usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+ usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
+
+ /* The clock for the USBH1 ULPI port will come from the PHY. */
+ v = __raw_readl(usbother_base + MX51_USB_CTRL_1_OFFSET);
+ __raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN,
+ usbother_base + MX51_USB_CTRL_1_OFFSET);
+ iounmap(usb_base);
+ return 0;
+}
+
+static struct mxc_usbh_platform_data dr_utmi_config = {
+ .init = initialize_otg_port,
+ .portsc = MXC_EHCI_UTMI_16BIT,
+ .flags = MXC_EHCI_INTERNAL_PHY,
+};
+
+static struct fsl_usb2_platform_data usb_pdata = {
+ .operating_mode = FSL_USB2_DR_DEVICE,
+ .phy_mode = FSL_USB2_PHY_UTMI_WIDE,
+};
+
+static struct mxc_usbh_platform_data usbh1_config = {
+ .init = initialize_usbh1_port,
+ .portsc = MXC_EHCI_MODE_ULPI,
+ .flags = (MXC_EHCI_POWER_PINS_ENABLED | MXC_EHCI_ITC_NO_THRESHOLD),
+};
+
+static int otg_mode_host;
+
+static int __init eukrea_cpuimx51sd_otg_mode(char *options)
+{
+ if (!strcmp(options, "host"))
+ otg_mode_host = 1;
+ else if (!strcmp(options, "device"))
+ otg_mode_host = 0;
+ else
+ pr_info("otg_mode neither \"host\" nor \"device\". "
+ "Defaulting to device\n");
+ return 0;
+}
+__setup("otg_mode=", eukrea_cpuimx51sd_otg_mode);
+
+static struct i2c_gpio_platform_data pdata = {
+ .sda_pin = I2C_SDA,
+ .sda_is_open_drain = 0,
+ .scl_pin = I2C_SCL,
+ .scl_is_open_drain = 0,
+ .udelay = 2,
+};
+
+static struct platform_device hsi2c_gpio_device = {
+ .name = "i2c-gpio",
+ .id = 0,
+ .dev.platform_data = &pdata,
+};
+
+static struct mcp251x_platform_data mcp251x_info = {
+ .oscillator_frequency = 24E6,
+};
+
+static struct spi_board_info cpuimx51sd_spi_device[] = {
+ {
+ .modalias = "mcp2515",
+ .max_speed_hz = 6500000,
+ .bus_num = 0,
+ .mode = SPI_MODE_0,
+ .chip_select = 0,
+ .platform_data = &mcp251x_info,
+ .irq = gpio_to_irq(0 * 32 + 1)
+ },
+};
+
+static int cpuimx51sd_spi1_cs[] = {
+ CAN_NCS,
+};
+
+static const struct spi_imx_master cpuimx51sd_ecspi1_pdata __initconst = {
+ .chipselect = cpuimx51sd_spi1_cs,
+ .num_chipselect = ARRAY_SIZE(cpuimx51sd_spi1_cs),
+};
+
+static struct platform_device *platform_devices[] __initdata = {
+ &hsi2c_gpio_device,
+};
+
+static void __init eukrea_cpuimx51sd_init(void)
+{
+ mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx51sd_pads,
+ ARRAY_SIZE(eukrea_cpuimx51sd_pads));
+
+ imx51_add_imx_uart(0, &uart_pdata);
+ imx51_add_mxc_nand(&eukrea_cpuimx51sd_nand_board_info);
+
+ gpio_request(ETH_RST, "eth_rst");
+ gpio_set_value(ETH_RST, 1);
+ imx51_add_fec(NULL);
+
+ gpio_request(CAN_IRQGPIO, "can_irq");
+ gpio_direction_input(CAN_IRQGPIO);
+ gpio_free(CAN_IRQGPIO);
+ gpio_request(CAN_NCS, "can_ncs");
+ gpio_direction_output(CAN_NCS, 1);
+ gpio_free(CAN_NCS);
+ gpio_request(CAN_RST, "can_rst");
+ gpio_direction_output(CAN_RST, 0);
+ msleep(20);
+ gpio_set_value(CAN_RST, 1);
+ imx51_add_ecspi(0, &cpuimx51sd_ecspi1_pdata);
+ spi_register_board_info(cpuimx51sd_spi_device,
+ ARRAY_SIZE(cpuimx51sd_spi_device));
+
+ gpio_request(TSC2007_IRQGPIO, "tsc2007_irq");
+ gpio_direction_input(TSC2007_IRQGPIO);
+ gpio_free(TSC2007_IRQGPIO);
+
+ i2c_register_board_info(0, eukrea_cpuimx51sd_i2c_devices,
+ ARRAY_SIZE(eukrea_cpuimx51sd_i2c_devices));
+ platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+
+ if (otg_mode_host)
+ mxc_register_device(&mxc_usbdr_host_device, &dr_utmi_config);
+ else {
+ initialize_otg_port(NULL);
+ mxc_register_device(&mxc_usbdr_udc_device, &usb_pdata);
+ }
+
+ gpio_request(USBH1_RST, "usb_rst");
+ gpio_direction_output(USBH1_RST, 0);
+ msleep(20);
+ gpio_set_value(USBH1_RST, 1);
+ mxc_register_device(&mxc_usbh1_device, &usbh1_config);
+
+#ifdef CONFIG_MACH_EUKREA_MBIMXSD51_BASEBOARD
+ eukrea_mbimxsd51_baseboard_init();
+#endif
+}
+
+static void __init eukrea_cpuimx51sd_timer_init(void)
+{
+ mx51_clocks_init(32768, 24000000, 22579200, 0);
+}
+
+static struct sys_timer mxc_timer = {
+ .init = eukrea_cpuimx51sd_timer_init,
+};
+
+MACHINE_START(EUKREA_CPUIMX51SD, "Eukrea CPUIMX51SD")
+ /* Maintainer: Eric Bénard <eric@eukrea.com> */
+ .boot_params = PHYS_OFFSET + 0x100,
+ .map_io = mx51_map_io,
+ .init_irq = mx51_init_irq,
+ .init_machine = eukrea_cpuimx51sd_init,
+ .timer = &mxc_timer,
+MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx51_3ds.c b/arch/arm/mach-mx5/board-mx51_3ds.c
index f95c2fd94667..79ce8dcf3cda 100644
--- a/arch/arm/mach-mx5/board-mx51_3ds.c
+++ b/arch/arm/mach-mx5/board-mx51_3ds.c
@@ -13,6 +13,7 @@
#include <linux/irq.h>
#include <linux/platform_device.h>
#include <linux/input/matrix_keypad.h>
+#include <linux/spi/spi.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -21,12 +22,13 @@
#include <mach/hardware.h>
#include <mach/common.h>
#include <mach/iomux-mx51.h>
-#include <mach/imx-uart.h>
#include <mach/3ds_debugboard.h>
+#include "devices-imx51.h"
#include "devices.h"
#define EXPIO_PARENT_INT (MXC_INTERNAL_IRQS + GPIO_PORTA + 6)
+#define MX51_3DS_ECSPI2_CS (GPIO_PORTC + 28)
static struct pad_desc mx51_3ds_pads[] = {
/* UART1 */
@@ -61,19 +63,25 @@ static struct pad_desc mx51_3ds_pads[] = {
MX51_PAD_KEY_COL3__KEY_COL3,
MX51_PAD_KEY_COL4__KEY_COL4,
MX51_PAD_KEY_COL5__KEY_COL5,
+
+ /* eCSPI2 */
+ MX51_PAD_NANDF_RB2__ECSPI2_SCLK,
+ MX51_PAD_NANDF_RB3__ECSPI2_MISO,
+ MX51_PAD_NANDF_D15__ECSPI2_MOSI,
+ MX51_PAD_NANDF_D12__GPIO_3_28,
};
/* Serial ports */
#if defined(CONFIG_SERIAL_IMX) || defined(CONFIG_SERIAL_IMX_MODULE)
-static struct imxuart_platform_data uart_pdata = {
+static const struct imxuart_platform_data uart_pdata __initconst = {
.flags = IMXUART_HAVE_RTSCTS,
};
static inline void mxc_init_imx_uart(void)
{
- mxc_register_device(&mxc_uart_device0, &uart_pdata);
- mxc_register_device(&mxc_uart_device1, &uart_pdata);
- mxc_register_device(&mxc_uart_device2, &uart_pdata);
+ imx51_add_imx_uart(0, &uart_pdata);
+ imx51_add_imx_uart(1, &uart_pdata);
+ imx51_add_imx_uart(2, &uart_pdata);
}
#else /* !SERIAL_IMX */
static inline void mxc_init_imx_uart(void)
@@ -127,6 +135,26 @@ static inline void mxc_init_keypad(void)
}
#endif
+static int mx51_3ds_spi2_cs[] = {
+ MXC_SPI_CS(0),
+ MX51_3DS_ECSPI2_CS,
+};
+
+static const struct spi_imx_master mx51_3ds_ecspi2_pdata __initconst = {
+ .chipselect = mx51_3ds_spi2_cs,
+ .num_chipselect = ARRAY_SIZE(mx51_3ds_spi2_cs),
+};
+
+static struct spi_board_info mx51_3ds_spi_nor_device[] = {
+ {
+ .modalias = "m25p80",
+ .max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 1,
+ .chip_select = 1,
+ .mode = SPI_MODE_0,
+ .platform_data = NULL,},
+};
+
/*
* Board specific initialization.
*/
@@ -136,6 +164,10 @@ static void __init mxc_board_init(void)
ARRAY_SIZE(mx51_3ds_pads));
mxc_init_imx_uart();
+ imx51_add_ecspi(1, &mx51_3ds_ecspi2_pdata);
+ spi_register_board_info(mx51_3ds_spi_nor_device,
+ ARRAY_SIZE(mx51_3ds_spi_nor_device));
+
if (mxc_expio_init(MX51_CS5_BASE_ADDR, EXPIO_PARENT_INT))
printk(KERN_WARNING "Init of the debugboard failed, all "
"devices on the board are unusable.\n");
@@ -154,8 +186,6 @@ static struct sys_timer mxc_timer = {
MACHINE_START(MX51_3DS, "Freescale MX51 3-Stack Board")
/* Maintainer: Freescale Semiconductor, Inc. */
- .phys_io = MX51_AIPS1_BASE_ADDR,
- .io_pg_offst = ((MX51_AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
.boot_params = PHYS_OFFSET + 0x100,
.map_io = mx51_map_io,
.init_irq = mx51_init_irq,
diff --git a/arch/arm/mach-mx5/board-mx51_babbage.c b/arch/arm/mach-mx5/board-mx51_babbage.c
index 6e384d92e625..0821fe9b3b27 100644
--- a/arch/arm/mach-mx5/board-mx51_babbage.c
+++ b/arch/arm/mach-mx5/board-mx51_babbage.c
@@ -17,12 +17,11 @@
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/fsl_devices.h>
+#include <linux/fec.h>
#include <mach/common.h>
#include <mach/hardware.h>
-#include <mach/imx-uart.h>
#include <mach/iomux-mx51.h>
-#include <mach/i2c.h>
#include <mach/mxc_ehci.h>
#include <asm/irq.h>
@@ -31,11 +30,13 @@
#include <asm/mach/arch.h>
#include <asm/mach/time.h>
+#include "devices-imx51.h"
#include "devices.h"
#define BABBAGE_USB_HUB_RESET (0*32 + 7) /* GPIO_1_7 */
#define BABBAGE_USBH1_STP (0*32 + 27) /* GPIO_1_27 */
-#define BABBAGE_PHY_RESET (1*32 +5) /* GPIO_2_5 */
+#define BABBAGE_PHY_RESET (1*32 + 5) /* GPIO_2_5 */
+#define BABBAGE_FEC_PHY_RESET (1*32 + 14) /* GPIO_2_14 */
/* USB_CTRL_1 */
#define MX51_USB_CTRL_1_OFFSET 0x10
@@ -45,10 +46,6 @@
#define MX51_USB_PLL_DIV_19_2_MHZ 0x01
#define MX51_USB_PLL_DIV_24_MHZ 0x02
-static struct platform_device *devices[] __initdata = {
- &mxc_fec_device,
-};
-
static struct pad_desc mx51babbage_pads[] = {
/* UART1 */
MX51_PAD_UART1_RXD__UART1_RXD,
@@ -93,19 +90,41 @@ static struct pad_desc mx51babbage_pads[] = {
/* USB HUB reset line*/
MX51_PAD_GPIO_1_7__GPIO_1_7,
+
+ /* FEC */
+ MX51_PAD_EIM_EB2__FEC_MDIO,
+ MX51_PAD_EIM_EB3__FEC_RDAT1,
+ MX51_PAD_EIM_CS2__FEC_RDAT2,
+ MX51_PAD_EIM_CS3__FEC_RDAT3,
+ MX51_PAD_EIM_CS4__FEC_RX_ER,
+ MX51_PAD_EIM_CS5__FEC_CRS,
+ MX51_PAD_NANDF_RB2__FEC_COL,
+ MX51_PAD_NANDF_RB3__FEC_RXCLK,
+ MX51_PAD_NANDF_RB6__FEC_RDAT0,
+ MX51_PAD_NANDF_RB7__FEC_TDAT0,
+ MX51_PAD_NANDF_CS2__FEC_TX_ER,
+ MX51_PAD_NANDF_CS3__FEC_MDC,
+ MX51_PAD_NANDF_CS4__FEC_TDAT1,
+ MX51_PAD_NANDF_CS5__FEC_TDAT2,
+ MX51_PAD_NANDF_CS6__FEC_TDAT3,
+ MX51_PAD_NANDF_CS7__FEC_TX_EN,
+ MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK,
+
+ /* FEC PHY reset line */
+ MX51_PAD_EIM_A20__GPIO_2_14,
};
/* Serial ports */
#if defined(CONFIG_SERIAL_IMX) || defined(CONFIG_SERIAL_IMX_MODULE)
-static struct imxuart_platform_data uart_pdata = {
+static const struct imxuart_platform_data uart_pdata __initconst = {
.flags = IMXUART_HAVE_RTSCTS,
};
static inline void mxc_init_imx_uart(void)
{
- mxc_register_device(&mxc_uart_device0, &uart_pdata);
- mxc_register_device(&mxc_uart_device1, &uart_pdata);
- mxc_register_device(&mxc_uart_device2, &uart_pdata);
+ imx51_add_imx_uart(0, &uart_pdata);
+ imx51_add_imx_uart(1, &uart_pdata);
+ imx51_add_imx_uart(2, &uart_pdata);
}
#else /* !SERIAL_IMX */
static inline void mxc_init_imx_uart(void)
@@ -113,7 +132,7 @@ static inline void mxc_init_imx_uart(void)
}
#endif /* SERIAL_IMX */
-static struct imxi2c_platform_data babbage_i2c_data = {
+static const struct imxi2c_platform_data babbage_i2c_data __initconst = {
.bitrate = 100000,
};
@@ -171,6 +190,22 @@ static inline void babbage_usbhub_reset(void)
gpio_set_value(BABBAGE_USB_HUB_RESET, 1);
}
+static inline void babbage_fec_reset(void)
+{
+ int ret;
+
+ /* reset FEC PHY */
+ ret = gpio_request(BABBAGE_FEC_PHY_RESET, "fec-phy-reset");
+ if (ret) {
+ printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret);
+ return;
+ }
+ gpio_direction_output(BABBAGE_FEC_PHY_RESET, 0);
+ gpio_set_value(BABBAGE_FEC_PHY_RESET, 0);
+ msleep(1);
+ gpio_set_value(BABBAGE_FEC_PHY_RESET, 1);
+}
+
/* This function is board specific as the bit mask for the plldiv will also
be different for other Freescale SoCs, thus a common bitmask is not
possible and cannot get place in /plat-mxc/ehci.c.*/
@@ -178,7 +213,7 @@ static int initialize_otg_port(struct platform_device *pdev)
{
u32 v;
void __iomem *usb_base;
- u32 usbother_base;
+ void __iomem *usbother_base;
usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
@@ -196,7 +231,7 @@ static int initialize_usbh1_port(struct platform_device *pdev)
{
u32 v;
void __iomem *usb_base;
- u32 usbother_base;
+ void __iomem *usbother_base;
usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
@@ -250,10 +285,11 @@ static void __init mxc_board_init(void)
mxc_iomux_v3_setup_multiple_pads(mx51babbage_pads,
ARRAY_SIZE(mx51babbage_pads));
mxc_init_imx_uart();
- platform_add_devices(devices, ARRAY_SIZE(devices));
+ babbage_fec_reset();
+ imx51_add_fec(NULL);
- mxc_register_device(&mxc_i2c_device0, &babbage_i2c_data);
- mxc_register_device(&mxc_i2c_device1, &babbage_i2c_data);
+ imx51_add_imx_i2c(0, &babbage_i2c_data);
+ imx51_add_imx_i2c(1, &babbage_i2c_data);
mxc_register_device(&mxc_hsi2c_device, &babbage_hsi2c_data);
if (otg_mode_host)
@@ -281,9 +317,7 @@ static struct sys_timer mxc_timer = {
MACHINE_START(MX51_BABBAGE, "Freescale MX51 Babbage Board")
/* Maintainer: Amit Kucheria <amit.kucheria@canonical.com> */
- .phys_io = MX51_AIPS1_BASE_ADDR,
- .io_pg_offst = ((MX51_AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
- .boot_params = PHYS_OFFSET + 0x100,
+ .boot_params = MX51_PHYS_OFFSET + 0x100,
.map_io = mx51_map_io,
.init_irq = mx51_init_irq,
.init_machine = mxc_board_init,
diff --git a/arch/arm/mach-mx5/board-mx51_efikamx.c b/arch/arm/mach-mx5/board-mx51_efikamx.c
new file mode 100644
index 000000000000..6e623bda3ee7
--- /dev/null
+++ b/arch/arm/mach-mx5/board-mx51_efikamx.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2010 Linaro Limited
+ *
+ * based on code from the following
+ * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2009-2010 Pegatron Corporation. All Rights Reserved.
+ * Copyright 2009-2010 Genesi USA, Inc. All Rights Reserved.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/fsl_devices.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx51.h>
+#include <mach/i2c.h>
+#include <mach/mxc_ehci.h>
+
+#include <asm/irq.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "devices-imx51.h"
+#include "devices.h"
+
+#define MX51_USB_PLL_DIV_24_MHZ 0x01
+
+static struct pad_desc mx51efikamx_pads[] = {
+ /* UART1 */
+ MX51_PAD_UART1_RXD__UART1_RXD,
+ MX51_PAD_UART1_TXD__UART1_TXD,
+ MX51_PAD_UART1_RTS__UART1_RTS,
+ MX51_PAD_UART1_CTS__UART1_CTS,
+};
+
+/* Serial ports */
+#if defined(CONFIG_SERIAL_IMX) || defined(CONFIG_SERIAL_IMX_MODULE)
+static const struct imxuart_platform_data uart_pdata = {
+ .flags = IMXUART_HAVE_RTSCTS,
+};
+
+static inline void mxc_init_imx_uart(void)
+{
+ imx51_add_imx_uart(0, &uart_pdata);
+ imx51_add_imx_uart(1, &uart_pdata);
+ imx51_add_imx_uart(2, &uart_pdata);
+}
+#else /* !SERIAL_IMX */
+static inline void mxc_init_imx_uart(void)
+{
+}
+#endif /* SERIAL_IMX */
+
+/* This function is board specific as the bit mask for the plldiv will also
+ * be different for other Freescale SoCs, thus a common bitmask is not
+ * possible and cannot get place in /plat-mxc/ehci.c.
+ */
+static int initialize_otg_port(struct platform_device *pdev)
+{
+ u32 v;
+ void __iomem *usb_base;
+ void __iomem *usbother_base;
+ usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+ usbother_base = (void __iomem *)(usb_base + MX5_USBOTHER_REGS_OFFSET);
+
+ /* Set the PHY clock to 19.2MHz */
+ v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
+ v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK;
+ v |= MX51_USB_PLL_DIV_24_MHZ;
+ __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
+ iounmap(usb_base);
+ return 0;
+}
+
+static struct mxc_usbh_platform_data dr_utmi_config = {
+ .init = initialize_otg_port,
+ .portsc = MXC_EHCI_UTMI_16BIT,
+ .flags = MXC_EHCI_INTERNAL_PHY,
+};
+
+static void __init mxc_board_init(void)
+{
+ mxc_iomux_v3_setup_multiple_pads(mx51efikamx_pads,
+ ARRAY_SIZE(mx51efikamx_pads));
+ mxc_register_device(&mxc_usbdr_host_device, &dr_utmi_config);
+ mxc_init_imx_uart();
+}
+
+static void __init mx51_efikamx_timer_init(void)
+{
+ mx51_clocks_init(32768, 24000000, 22579200, 24576000);
+}
+
+static struct sys_timer mxc_timer = {
+ .init = mx51_efikamx_timer_init,
+};
+
+MACHINE_START(MX51_EFIKAMX, "Genesi EfikaMX nettop")
+ /* Maintainer: Amit Kucheria <amit.kucheria@linaro.org> */
+ .boot_params = MX51_PHYS_OFFSET + 0x100,
+ .map_io = mx51_map_io,
+ .init_irq = mx51_init_irq,
+ .init_machine = mxc_board_init,
+ .timer = &mxc_timer,
+MACHINE_END
diff --git a/arch/arm/mach-mx5/clock-mx51.c b/arch/arm/mach-mx5/clock-mx51.c
index 57c10a9926cc..f2aae92cf0e2 100644
--- a/arch/arm/mach-mx5/clock-mx51.c
+++ b/arch/arm/mach-mx5/clock-mx51.c
@@ -41,34 +41,66 @@ static struct clk usboh3_clk;
#define MAX_DPLL_WAIT_TRIES 1000 /* 1000 * udelay(1) = 1ms */
-static int _clk_ccgr_enable(struct clk *clk)
+/* calculate best pre and post dividers to get the required divider */
+static void __calc_pre_post_dividers(u32 div, u32 *pre, u32 *post,
+ u32 max_pre, u32 max_post)
{
- u32 reg;
+ if (div >= max_pre * max_post) {
+ *pre = max_pre;
+ *post = max_post;
+ } else if (div >= max_pre) {
+ u32 min_pre, temp_pre, old_err, err;
+ min_pre = DIV_ROUND_UP(div, max_post);
+ old_err = max_pre;
+ for (temp_pre = max_pre; temp_pre >= min_pre; temp_pre--) {
+ err = div % temp_pre;
+ if (err == 0) {
+ *pre = temp_pre;
+ break;
+ }
+ err = temp_pre - err;
+ if (err < old_err) {
+ old_err = err;
+ *pre = temp_pre;
+ }
+ }
+ *post = DIV_ROUND_UP(div, *pre);
+ } else {
+ *pre = div;
+ *post = 1;
+ }
+}
+
+static void _clk_ccgr_setclk(struct clk *clk, unsigned mode)
+{
+ u32 reg = __raw_readl(clk->enable_reg);
+
+ reg &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift);
+ reg |= mode << clk->enable_shift;
- reg = __raw_readl(clk->enable_reg);
- reg |= MXC_CCM_CCGRx_MOD_ON << clk->enable_shift;
__raw_writel(reg, clk->enable_reg);
+}
+static int _clk_ccgr_enable(struct clk *clk)
+{
+ _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_ON);
return 0;
}
static void _clk_ccgr_disable(struct clk *clk)
{
- u32 reg;
- reg = __raw_readl(clk->enable_reg);
- reg &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift);
- __raw_writel(reg, clk->enable_reg);
+ _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_OFF);
+}
+static int _clk_ccgr_enable_inrun(struct clk *clk)
+{
+ _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_IDLE);
+ return 0;
}
static void _clk_ccgr_disable_inwait(struct clk *clk)
{
- u32 reg;
-
- reg = __raw_readl(clk->enable_reg);
- reg &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift);
- reg |= MXC_CCM_CCGRx_MOD_IDLE << clk->enable_shift;
- __raw_writel(reg, clk->enable_reg);
+ _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_IDLE);
}
/*
@@ -542,60 +574,60 @@ static int _clk_ipg_per_set_parent(struct clk *clk, struct clk *parent)
return 0;
}
-static unsigned long clk_uart_get_rate(struct clk *clk)
-{
- u32 reg, prediv, podf;
- unsigned long parent_rate;
+#define clk_nfc_set_parent NULL
- parent_rate = clk_get_rate(clk->parent);
-
- reg = __raw_readl(MXC_CCM_CSCDR1);
- prediv = ((reg & MXC_CCM_CSCDR1_UART_CLK_PRED_MASK) >>
- MXC_CCM_CSCDR1_UART_CLK_PRED_OFFSET) + 1;
- podf = ((reg & MXC_CCM_CSCDR1_UART_CLK_PODF_MASK) >>
- MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET) + 1;
+static unsigned long clk_nfc_get_rate(struct clk *clk)
+{
+ unsigned long rate;
+ u32 reg, div;
- return parent_rate / (prediv * podf);
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ div = ((reg & MXC_CCM_CBCDR_NFC_PODF_MASK) >>
+ MXC_CCM_CBCDR_NFC_PODF_OFFSET) + 1;
+ rate = clk_get_rate(clk->parent) / div;
+ WARN_ON(rate == 0);
+ return rate;
}
-static int _clk_uart_set_parent(struct clk *clk, struct clk *parent)
+static unsigned long clk_nfc_round_rate(struct clk *clk,
+ unsigned long rate)
{
- u32 reg, mux;
+ u32 div;
+ unsigned long parent_rate = clk_get_rate(clk->parent);
- mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk,
- &lp_apm_clk);
- reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_UART_CLK_SEL_MASK;
- reg |= mux << MXC_CCM_CSCMR1_UART_CLK_SEL_OFFSET;
- __raw_writel(reg, MXC_CCM_CSCMR1);
+ if (!rate)
+ return -EINVAL;
- return 0;
-}
+ div = parent_rate / rate;
-static unsigned long clk_usboh3_get_rate(struct clk *clk)
-{
- u32 reg, prediv, podf;
- unsigned long parent_rate;
+ if (parent_rate % rate)
+ div++;
- parent_rate = clk_get_rate(clk->parent);
+ if (div > 8)
+ return -EINVAL;
- reg = __raw_readl(MXC_CCM_CSCDR1);
- prediv = ((reg & MXC_CCM_CSCDR1_USBOH3_CLK_PRED_MASK) >>
- MXC_CCM_CSCDR1_USBOH3_CLK_PRED_OFFSET) + 1;
- podf = ((reg & MXC_CCM_CSCDR1_USBOH3_CLK_PODF_MASK) >>
- MXC_CCM_CSCDR1_USBOH3_CLK_PODF_OFFSET) + 1;
+ return parent_rate / div;
- return parent_rate / (prediv * podf);
}
-static int _clk_usboh3_set_parent(struct clk *clk, struct clk *parent)
+static int clk_nfc_set_rate(struct clk *clk, unsigned long rate)
{
- u32 reg, mux;
+ u32 reg, div;
+
+ div = clk_get_rate(clk->parent) / rate;
+ if (div == 0)
+ div++;
+ if (((clk_get_rate(clk->parent) / div) != rate) || (div > 8))
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ reg &= ~MXC_CCM_CBCDR_NFC_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CBCDR_NFC_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CBCDR);
- mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk,
- &lp_apm_clk);
- reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_USBOH3_CLK_SEL_MASK;
- reg |= mux << MXC_CCM_CSCMR1_USBOH3_CLK_SEL_OFFSET;
- __raw_writel(reg, MXC_CCM_CSCMR1);
+ while (__raw_readl(MXC_CCM_CDHIPR) &
+ MXC_CCM_CDHIPR_NFC_IPG_INT_MEM_PODF_BUSY){
+ }
return 0;
}
@@ -620,6 +652,17 @@ static unsigned long get_ckih2_reference_clock_rate(struct clk *clk)
return ckih2_reference;
}
+static unsigned long clk_emi_slow_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ div = ((reg & MXC_CCM_CBCDR_EMI_PODF_MASK) >>
+ MXC_CCM_CBCDR_EMI_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / div;
+}
+
/* External high frequency clock */
static struct clk ckih_clk = {
.get_rate = get_high_reference_clock_rate,
@@ -715,18 +758,6 @@ static struct clk ipg_perclk = {
.set_parent = _clk_ipg_per_set_parent,
};
-static struct clk uart_root_clk = {
- .parent = &pll2_sw_clk,
- .get_rate = clk_uart_get_rate,
- .set_parent = _clk_uart_set_parent,
-};
-
-static struct clk usboh3_clk = {
- .parent = &pll2_sw_clk,
- .get_rate = clk_usboh3_get_rate,
- .set_parent = _clk_usboh3_set_parent,
-};
-
static struct clk ahb_max_clk = {
.parent = &ahb_clk,
.enable_reg = MXC_CCM_CCGR0,
@@ -762,45 +793,183 @@ static struct clk kpp_clk = {
.id = 0,
};
-#define DEFINE_CLOCK(name, i, er, es, gr, sr, p, s) \
+static struct clk emi_slow_clk = {
+ .parent = &pll2_sw_clk,
+ .enable_reg = MXC_CCM_CCGR5,
+ .enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
+ .enable = _clk_ccgr_enable,
+ .disable = _clk_ccgr_disable_inwait,
+ .get_rate = clk_emi_slow_get_rate,
+};
+
+#define DEFINE_CLOCK_CCGR(name, i, er, es, pfx, p, s) \
static struct clk name = { \
.id = i, \
.enable_reg = er, \
.enable_shift = es, \
- .get_rate = gr, \
- .set_rate = sr, \
+ .get_rate = pfx##_get_rate, \
+ .set_rate = pfx##_set_rate, \
+ .round_rate = pfx##_round_rate, \
+ .set_parent = pfx##_set_parent, \
.enable = _clk_ccgr_enable, \
.disable = _clk_ccgr_disable, \
.parent = p, \
.secondary = s, \
}
-/* DEFINE_CLOCK(name, id, enable_reg, enable_shift,
- get_rate, set_rate, parent, secondary); */
+#define DEFINE_CLOCK_MAX(name, i, er, es, pfx, p, s) \
+ static struct clk name = { \
+ .id = i, \
+ .enable_reg = er, \
+ .enable_shift = es, \
+ .get_rate = pfx##_get_rate, \
+ .set_rate = pfx##_set_rate, \
+ .set_parent = pfx##_set_parent, \
+ .enable = _clk_max_enable, \
+ .disable = _clk_max_disable, \
+ .parent = p, \
+ .secondary = s, \
+ }
+
+#define CLK_GET_RATE(name, nr, bitsname) \
+static unsigned long clk_##name##_get_rate(struct clk *clk) \
+{ \
+ u32 reg, pred, podf; \
+ \
+ reg = __raw_readl(MXC_CCM_CSCDR##nr); \
+ pred = (reg & MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK) \
+ >> MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET; \
+ podf = (reg & MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK) \
+ >> MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET; \
+ \
+ return DIV_ROUND_CLOSEST(clk_get_rate(clk->parent), \
+ (pred + 1) * (podf + 1)); \
+}
+
+#define CLK_SET_PARENT(name, nr, bitsname) \
+static int clk_##name##_set_parent(struct clk *clk, struct clk *parent) \
+{ \
+ u32 reg, mux; \
+ \
+ mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, \
+ &pll3_sw_clk, &lp_apm_clk); \
+ reg = __raw_readl(MXC_CCM_CSCMR##nr) & \
+ ~MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_MASK; \
+ reg |= mux << MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_OFFSET; \
+ __raw_writel(reg, MXC_CCM_CSCMR##nr); \
+ \
+ return 0; \
+}
+
+#define CLK_SET_RATE(name, nr, bitsname) \
+static int clk_##name##_set_rate(struct clk *clk, unsigned long rate) \
+{ \
+ u32 reg, div, parent_rate; \
+ u32 pre = 0, post = 0; \
+ \
+ parent_rate = clk_get_rate(clk->parent); \
+ div = parent_rate / rate; \
+ \
+ if ((parent_rate / div) != rate) \
+ return -EINVAL; \
+ \
+ __calc_pre_post_dividers(div, &pre, &post, \
+ (MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK >> \
+ MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET) + 1, \
+ (MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK >> \
+ MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET) + 1);\
+ \
+ /* Set sdhc1 clock divider */ \
+ reg = __raw_readl(MXC_CCM_CSCDR##nr) & \
+ ~(MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK \
+ | MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK); \
+ reg |= (post - 1) << \
+ MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET; \
+ reg |= (pre - 1) << \
+ MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET; \
+ __raw_writel(reg, MXC_CCM_CSCDR##nr); \
+ \
+ return 0; \
+}
+
+/* UART */
+CLK_GET_RATE(uart, 1, UART)
+CLK_SET_PARENT(uart, 1, UART)
+
+static struct clk uart_root_clk = {
+ .parent = &pll2_sw_clk,
+ .get_rate = clk_uart_get_rate,
+ .set_parent = clk_uart_set_parent,
+};
+
+/* USBOH3 */
+CLK_GET_RATE(usboh3, 1, USBOH3)
+CLK_SET_PARENT(usboh3, 1, USBOH3)
+
+static struct clk usboh3_clk = {
+ .parent = &pll2_sw_clk,
+ .get_rate = clk_usboh3_get_rate,
+ .set_parent = clk_usboh3_set_parent,
+};
+
+/* eCSPI */
+CLK_GET_RATE(ecspi, 2, CSPI)
+CLK_SET_PARENT(ecspi, 1, CSPI)
+
+static struct clk ecspi_main_clk = {
+ .parent = &pll3_sw_clk,
+ .get_rate = clk_ecspi_get_rate,
+ .set_parent = clk_ecspi_set_parent,
+};
+
+/* eSDHC */
+CLK_GET_RATE(esdhc1, 1, ESDHC1_MSHC1)
+CLK_SET_PARENT(esdhc1, 1, ESDHC1_MSHC1)
+CLK_SET_RATE(esdhc1, 1, ESDHC1_MSHC1)
+
+CLK_GET_RATE(esdhc2, 1, ESDHC2_MSHC2)
+CLK_SET_PARENT(esdhc2, 1, ESDHC2_MSHC2)
+CLK_SET_RATE(esdhc2, 1, ESDHC2_MSHC2)
+
+#define DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, e, d, p, s) \
+ static struct clk name = { \
+ .id = i, \
+ .enable_reg = er, \
+ .enable_shift = es, \
+ .get_rate = gr, \
+ .set_rate = sr, \
+ .enable = e, \
+ .disable = d, \
+ .parent = p, \
+ .secondary = s, \
+ }
+
+#define DEFINE_CLOCK(name, i, er, es, gr, sr, p, s) \
+ DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, _clk_ccgr_enable, _clk_ccgr_disable, p, s)
/* Shared peripheral bus arbiter */
DEFINE_CLOCK(spba_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG0_OFFSET,
NULL, NULL, &ipg_clk, NULL);
/* UART */
-DEFINE_CLOCK(uart1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG4_OFFSET,
- NULL, NULL, &uart_root_clk, NULL);
-DEFINE_CLOCK(uart2_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG6_OFFSET,
- NULL, NULL, &uart_root_clk, NULL);
-DEFINE_CLOCK(uart3_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG8_OFFSET,
- NULL, NULL, &uart_root_clk, NULL);
DEFINE_CLOCK(uart1_ipg_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG3_OFFSET,
NULL, NULL, &ipg_clk, &aips_tz1_clk);
DEFINE_CLOCK(uart2_ipg_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG5_OFFSET,
NULL, NULL, &ipg_clk, &aips_tz1_clk);
DEFINE_CLOCK(uart3_ipg_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG7_OFFSET,
NULL, NULL, &ipg_clk, &spba_clk);
+DEFINE_CLOCK(uart1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG4_OFFSET,
+ NULL, NULL, &uart_root_clk, &uart1_ipg_clk);
+DEFINE_CLOCK(uart2_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG6_OFFSET,
+ NULL, NULL, &uart_root_clk, &uart2_ipg_clk);
+DEFINE_CLOCK(uart3_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG8_OFFSET,
+ NULL, NULL, &uart_root_clk, &uart3_ipg_clk);
/* GPT */
-DEFINE_CLOCK(gpt_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG9_OFFSET,
- NULL, NULL, &ipg_clk, NULL);
DEFINE_CLOCK(gpt_ipg_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG10_OFFSET,
NULL, NULL, &ipg_clk, NULL);
+DEFINE_CLOCK(gpt_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG9_OFFSET,
+ NULL, NULL, &ipg_clk, &gpt_ipg_clk);
/* I2C */
DEFINE_CLOCK(i2c1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG9_OFFSET,
@@ -814,6 +983,52 @@ DEFINE_CLOCK(hsi2c_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG11_OFFSET,
DEFINE_CLOCK(fec_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG12_OFFSET,
NULL, NULL, &ipg_clk, NULL);
+/* NFC */
+DEFINE_CLOCK_CCGR(nfc_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG10_OFFSET,
+ clk_nfc, &emi_slow_clk, NULL);
+
+/* SSI */
+DEFINE_CLOCK(ssi1_ipg_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG8_OFFSET,
+ NULL, NULL, &ipg_clk, NULL);
+DEFINE_CLOCK(ssi1_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG9_OFFSET,
+ NULL, NULL, &pll3_sw_clk, &ssi1_ipg_clk);
+DEFINE_CLOCK(ssi2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG10_OFFSET,
+ NULL, NULL, &ipg_clk, NULL);
+DEFINE_CLOCK(ssi2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG11_OFFSET,
+ NULL, NULL, &pll3_sw_clk, &ssi2_ipg_clk);
+
+/* eCSPI */
+DEFINE_CLOCK_FULL(ecspi1_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG9_OFFSET,
+ NULL, NULL, _clk_ccgr_enable_inrun, _clk_ccgr_disable,
+ &ipg_clk, &spba_clk);
+DEFINE_CLOCK(ecspi1_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG10_OFFSET,
+ NULL, NULL, &ecspi_main_clk, &ecspi1_ipg_clk);
+DEFINE_CLOCK_FULL(ecspi2_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG11_OFFSET,
+ NULL, NULL, _clk_ccgr_enable_inrun, _clk_ccgr_disable,
+ &ipg_clk, &aips_tz2_clk);
+DEFINE_CLOCK(ecspi2_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG12_OFFSET,
+ NULL, NULL, &ecspi_main_clk, &ecspi2_ipg_clk);
+
+/* CSPI */
+DEFINE_CLOCK(cspi_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG9_OFFSET,
+ NULL, NULL, &ipg_clk, &aips_tz2_clk);
+DEFINE_CLOCK(cspi_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG13_OFFSET,
+ NULL, NULL, &ipg_clk, &cspi_ipg_clk);
+
+/* SDMA */
+DEFINE_CLOCK(sdma_clk, 1, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG15_OFFSET,
+ NULL, NULL, &ahb_clk, NULL);
+
+/* eSDHC */
+DEFINE_CLOCK_FULL(esdhc1_ipg_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG0_OFFSET,
+ NULL, NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
+DEFINE_CLOCK_MAX(esdhc1_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG1_OFFSET,
+ clk_esdhc1, &pll2_sw_clk, &esdhc1_ipg_clk);
+DEFINE_CLOCK_FULL(esdhc2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG2_OFFSET,
+ NULL, NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
+DEFINE_CLOCK_MAX(esdhc2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG3_OFFSET,
+ clk_esdhc2, &pll2_sw_clk, &esdhc2_ipg_clk);
+
#define _REGISTER_CLOCK(d, n, c) \
{ \
.dev_id = d, \
@@ -837,6 +1052,18 @@ static struct clk_lookup lookups[] = {
_REGISTER_CLOCK("fsl-usb2-udc", "usb", usboh3_clk)
_REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", ahb_clk)
_REGISTER_CLOCK("imx-keypad.0", NULL, kpp_clk)
+ _REGISTER_CLOCK("mxc_nand", NULL, nfc_clk)
+ _REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
+ _REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
+ _REGISTER_CLOCK("imx-sdma", NULL, sdma_clk)
+ _REGISTER_CLOCK(NULL, "ckih", ckih_clk)
+ _REGISTER_CLOCK(NULL, "ckih2", ckih2_clk)
+ _REGISTER_CLOCK(NULL, "gpt_32k", gpt_32k_clk)
+ _REGISTER_CLOCK("imx51-ecspi.0", NULL, ecspi1_clk)
+ _REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk)
+ _REGISTER_CLOCK("imx51-cspi.0", NULL, cspi_clk)
+ _REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)
+ _REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_clk)
};
static void clk_tree_init(void)
@@ -880,6 +1107,14 @@ int __init mx51_clocks_init(unsigned long ckil, unsigned long osc,
/* set the usboh3_clk parent to pll2_sw_clk */
clk_set_parent(&usboh3_clk, &pll2_sw_clk);
+ /* Set SDHC parents to be PLL2 */
+ clk_set_parent(&esdhc1_clk, &pll2_sw_clk);
+ clk_set_parent(&esdhc2_clk, &pll2_sw_clk);
+
+ /* set SDHC root clock as 166.25MHZ*/
+ clk_set_rate(&esdhc1_clk, 166250000);
+ clk_set_rate(&esdhc2_clk, 166250000);
+
/* System timer */
mxc_timer_init(&gpt_clk, MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR),
MX51_MXC_INT_GPT);
diff --git a/arch/arm/mach-mx5/cpu.c b/arch/arm/mach-mx5/cpu.c
index 2d37785e3857..eaacb6e9b5d0 100644
--- a/arch/arm/mach-mx5/cpu.c
+++ b/arch/arm/mach-mx5/cpu.c
@@ -70,6 +70,25 @@ int mx51_revision(void)
}
EXPORT_SYMBOL(mx51_revision);
+#ifdef CONFIG_NEON
+
+/*
+ * All versions of the silicon before Rev. 3 have broken NEON implementations.
+ * Dependent on link order - so the assumption is that vfp_init is called
+ * before us.
+ */
+static int __init mx51_neon_fixup(void)
+{
+ if (mx51_revision() < MX51_CHIP_REV_3_0 && (elf_hwcap & HWCAP_NEON)) {
+ elf_hwcap &= ~HWCAP_NEON;
+ pr_info("Turning off NEON support, detected broken NEON implementation\n");
+ }
+ return 0;
+}
+
+late_initcall(mx51_neon_fixup);
+#endif
+
static int __init post_cpu_init(void)
{
unsigned int reg;
diff --git a/arch/arm/mach-mx5/devices-imx51.h b/arch/arm/mach-mx5/devices-imx51.h
new file mode 100644
index 000000000000..5cc910e60538
--- /dev/null
+++ b/arch/arm/mach-mx5/devices-imx51.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include <mach/mx51.h>
+#include <mach/devices-common.h>
+
+extern const struct imx_fec_data imx51_fec_data __initconst;
+#define imx51_add_fec(pdata) \
+ imx_add_fec(&imx51_fec_data, pdata)
+
+extern const struct imx_imx_i2c_data imx51_imx_i2c_data[] __initconst;
+#define imx51_add_imx_i2c(id, pdata) \
+ imx_add_imx_i2c(&imx51_imx_i2c_data[id], pdata)
+
+extern const struct imx_imx_ssi_data imx51_imx_ssi_data[] __initconst;
+#define imx51_add_imx_ssi(id, pdata) \
+ imx_add_imx_ssi(&imx51_imx_ssi_data[id], pdata)
+
+extern const struct imx_imx_uart_1irq_data imx51_imx_uart_data[] __initconst;
+#define imx51_add_imx_uart(id, pdata) \
+ imx_add_imx_uart_1irq(&imx51_imx_uart_data[id], pdata)
+
+extern const struct imx_mxc_nand_data imx51_mxc_nand_data __initconst;
+#define imx51_add_mxc_nand(pdata) \
+ imx_add_mxc_nand(&imx51_mxc_nand_data, pdata)
+
+extern const struct imx_spi_imx_data imx51_cspi_data __initconst;
+#define imx51_add_cspi(pdata) \
+ imx_add_spi_imx(&imx51_cspi_data, pdata)
+
+extern const struct imx_spi_imx_data imx51_ecspi_data[] __initconst;
+#define imx51_add_ecspi(id, pdata) \
+ imx_add_spi_imx(&imx51_ecspi_data[id], pdata)
+
+extern const struct imx_esdhc_imx_data imx51_esdhc_data[] __initconst;
+#define imx51_add_esdhc(id, pdata) \
+ imx_add_esdhc(&imx51_esdhc_data[id], pdata)
diff --git a/arch/arm/mach-mx5/devices.c b/arch/arm/mach-mx5/devices.c
index 1920ff4963b2..4c7be87a7c9d 100644
--- a/arch/arm/mach-mx5/devices.c
+++ b/arch/arm/mach-mx5/devices.c
@@ -17,120 +17,6 @@
#include <mach/imx-uart.h>
#include <mach/irqs.h>
-static struct resource uart0[] = {
- {
- .start = MX51_UART1_BASE_ADDR,
- .end = MX51_UART1_BASE_ADDR + 0xfff,
- .flags = IORESOURCE_MEM,
- }, {
- .start = MX51_MXC_INT_UART1,
- .end = MX51_MXC_INT_UART1,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-struct platform_device mxc_uart_device0 = {
- .name = "imx-uart",
- .id = 0,
- .resource = uart0,
- .num_resources = ARRAY_SIZE(uart0),
-};
-
-static struct resource uart1[] = {
- {
- .start = MX51_UART2_BASE_ADDR,
- .end = MX51_UART2_BASE_ADDR + 0xfff,
- .flags = IORESOURCE_MEM,
- }, {
- .start = MX51_MXC_INT_UART2,
- .end = MX51_MXC_INT_UART2,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-struct platform_device mxc_uart_device1 = {
- .name = "imx-uart",
- .id = 1,
- .resource = uart1,
- .num_resources = ARRAY_SIZE(uart1),
-};
-
-static struct resource uart2[] = {
- {
- .start = MX51_UART3_BASE_ADDR,
- .end = MX51_UART3_BASE_ADDR + 0xfff,
- .flags = IORESOURCE_MEM,
- }, {
- .start = MX51_MXC_INT_UART3,
- .end = MX51_MXC_INT_UART3,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-struct platform_device mxc_uart_device2 = {
- .name = "imx-uart",
- .id = 2,
- .resource = uart2,
- .num_resources = ARRAY_SIZE(uart2),
-};
-
-static struct resource mxc_fec_resources[] = {
- {
- .start = MX51_MXC_FEC_BASE_ADDR,
- .end = MX51_MXC_FEC_BASE_ADDR + 0xfff,
- .flags = IORESOURCE_MEM,
- }, {
- .start = MX51_MXC_INT_FEC,
- .end = MX51_MXC_INT_FEC,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-struct platform_device mxc_fec_device = {
- .name = "fec",
- .id = 0,
- .num_resources = ARRAY_SIZE(mxc_fec_resources),
- .resource = mxc_fec_resources,
-};
-
-static struct resource mxc_i2c0_resources[] = {
- {
- .start = MX51_I2C1_BASE_ADDR,
- .end = MX51_I2C1_BASE_ADDR + SZ_4K - 1,
- .flags = IORESOURCE_MEM,
- }, {
- .start = MX51_MXC_INT_I2C1,
- .end = MX51_MXC_INT_I2C1,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-struct platform_device mxc_i2c_device0 = {
- .name = "imx-i2c",
- .id = 0,
- .num_resources = ARRAY_SIZE(mxc_i2c0_resources),
- .resource = mxc_i2c0_resources,
-};
-
-static struct resource mxc_i2c1_resources[] = {
- {
- .start = MX51_I2C2_BASE_ADDR,
- .end = MX51_I2C2_BASE_ADDR + SZ_4K - 1,
- .flags = IORESOURCE_MEM,
- }, {
- .start = MX51_MXC_INT_I2C2,
- .end = MX51_MXC_INT_I2C2,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-struct platform_device mxc_i2c_device1 = {
- .name = "imx-i2c",
- .id = 1,
- .num_resources = ARRAY_SIZE(mxc_i2c1_resources),
- .resource = mxc_i2c1_resources,
-};
-
static struct resource mxc_hsi2c_resources[] = {
{
.start = MX51_HSI2C_DMA_BASE_ADDR,
diff --git a/arch/arm/mach-mx5/devices.h b/arch/arm/mach-mx5/devices.h
index e509cfaad1d4..af1d07c0bbc1 100644
--- a/arch/arm/mach-mx5/devices.h
+++ b/arch/arm/mach-mx5/devices.h
@@ -1,12 +1,6 @@
-extern struct platform_device mxc_uart_device0;
-extern struct platform_device mxc_uart_device1;
-extern struct platform_device mxc_uart_device2;
-extern struct platform_device mxc_fec_device;
extern struct platform_device mxc_usbdr_host_device;
extern struct platform_device mxc_usbh1_device;
extern struct platform_device mxc_usbdr_udc_device;
extern struct platform_device mxc_wdt;
-extern struct platform_device mxc_i2c_device0;
-extern struct platform_device mxc_i2c_device1;
extern struct platform_device mxc_hsi2c_device;
extern struct platform_device mxc_keypad_device;
diff --git a/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c b/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c
index ffa93d1d6ef8..a2e6e8c39d25 100644
--- a/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c
+++ b/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c
@@ -30,6 +30,7 @@
#include <asm/mach/arch.h>
+#include "devices-imx51.h"
#include "devices.h"
#define MBIMX51_TSC2007_GPIO (2*32 + 30)
@@ -112,9 +113,25 @@ static struct pad_desc mbimx51_pads[] = {
MX51_PAD_KEY_COL1__KEY_COL1,
MX51_PAD_KEY_COL2__KEY_COL2,
MX51_PAD_KEY_COL3__KEY_COL3,
+
+ /* SD 1 */
+ MX51_PAD_SD1_CMD__SD1_CMD,
+ MX51_PAD_SD1_CLK__SD1_CLK,
+ MX51_PAD_SD1_DATA0__SD1_DATA0,
+ MX51_PAD_SD1_DATA1__SD1_DATA1,
+ MX51_PAD_SD1_DATA2__SD1_DATA2,
+ MX51_PAD_SD1_DATA3__SD1_DATA3,
+
+ /* SD 2 */
+ MX51_PAD_SD2_CMD__SD2_CMD,
+ MX51_PAD_SD2_CLK__SD2_CLK,
+ MX51_PAD_SD2_DATA0__SD2_DATA0,
+ MX51_PAD_SD2_DATA1__SD2_DATA1,
+ MX51_PAD_SD2_DATA2__SD2_DATA2,
+ MX51_PAD_SD2_DATA3__SD2_DATA3,
};
-static struct imxuart_platform_data uart_pdata = {
+static const struct imxuart_platform_data uart_pdata __initconst = {
.flags = IMXUART_HAVE_RTSCTS,
};
@@ -158,9 +175,11 @@ struct tsc2007_platform_data tsc2007_data = {
static struct i2c_board_info mbimx51_i2c_devices[] = {
{
- I2C_BOARD_INFO("tsc2007", 0x48),
+ I2C_BOARD_INFO("tsc2007", 0x49),
.irq = MBIMX51_TSC2007_IRQ,
.platform_data = &tsc2007_data,
+ }, {
+ I2C_BOARD_INFO("tlv320aic23", 0x1a),
},
};
@@ -172,8 +191,8 @@ void __init eukrea_mbimx51_baseboard_init(void)
mxc_iomux_v3_setup_multiple_pads(mbimx51_pads,
ARRAY_SIZE(mbimx51_pads));
- mxc_register_device(&mxc_uart_device1, NULL);
- mxc_register_device(&mxc_uart_device2, &uart_pdata);
+ imx51_add_imx_uart(1, NULL);
+ imx51_add_imx_uart(2, &uart_pdata);
gpio_request(MBIMX51_LED0, "LED0");
gpio_direction_output(MBIMX51_LED0, 1);
@@ -197,4 +216,7 @@ void __init eukrea_mbimx51_baseboard_init(void)
set_irq_type(MBIMX51_TSC2007_IRQ, IRQF_TRIGGER_FALLING);
i2c_register_board_info(1, mbimx51_i2c_devices,
ARRAY_SIZE(mbimx51_i2c_devices));
+
+ imx51_add_esdhc(0, NULL);
+ imx51_add_esdhc(1, NULL);
}
diff --git a/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c b/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c
new file mode 100644
index 000000000000..2b48f5190830
--- /dev/null
+++ b/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2010 Eric Benard - eric@eukrea.com
+ *
+ * Based on pcm970-baseboard.c which is :
+ * Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de)
+ *
+ * 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.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/leds.h>
+#include <linux/platform_device.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
+#include <linux/i2c.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <asm/mach/map.h>
+
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/imx-uart.h>
+#include <mach/iomux-mx51.h>
+#include <mach/audmux.h>
+
+#include "devices-imx51.h"
+#include "devices.h"
+
+#define MBIMXSD_GPIO_3_31 IOMUX_PAD(0x554, 0x16C, 3, 0x0, 0, \
+ MX51_PAD_CTRL_1 | PAD_CTL_PUS_22K_UP)
+
+static struct pad_desc eukrea_mbimxsd_pads[] = {
+ /* LED */
+ MX51_PAD_NANDF_D10__GPIO_3_30,
+ /* SWITCH */
+ MBIMXSD_GPIO_3_31,
+ /* UART2 */
+ MX51_PAD_UART2_RXD__UART2_RXD,
+ MX51_PAD_UART2_TXD__UART2_TXD,
+ /* UART 3 */
+ MX51_PAD_UART3_RXD__UART3_RXD,
+ MX51_PAD_UART3_TXD__UART3_TXD,
+ MX51_PAD_KEY_COL4__UART3_RTS,
+ MX51_PAD_KEY_COL5__UART3_CTS,
+ /* SD */
+ MX51_PAD_SD1_CMD__SD1_CMD,
+ MX51_PAD_SD1_CLK__SD1_CLK,
+ MX51_PAD_SD1_DATA0__SD1_DATA0,
+ MX51_PAD_SD1_DATA1__SD1_DATA1,
+ MX51_PAD_SD1_DATA2__SD1_DATA2,
+ MX51_PAD_SD1_DATA3__SD1_DATA3,
+};
+
+#define GPIO_LED1 (2 * 32 + 30)
+#define GPIO_SWITCH1 (2 * 32 + 31)
+
+static struct gpio_led eukrea_mbimxsd_leds[] = {
+ {
+ .name = "led1",
+ .default_trigger = "heartbeat",
+ .active_low = 1,
+ .gpio = GPIO_LED1,
+ },
+};
+
+static struct gpio_led_platform_data eukrea_mbimxsd_led_info = {
+ .leds = eukrea_mbimxsd_leds,
+ .num_leds = ARRAY_SIZE(eukrea_mbimxsd_leds),
+};
+
+static struct platform_device eukrea_mbimxsd_leds_gpio = {
+ .name = "leds-gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = &eukrea_mbimxsd_led_info,
+ },
+};
+
+static struct gpio_keys_button eukrea_mbimxsd_gpio_buttons[] = {
+ {
+ .gpio = GPIO_SWITCH1,
+ .code = BTN_0,
+ .desc = "BP1",
+ .active_low = 1,
+ .wakeup = 1,
+ },
+};
+
+static struct gpio_keys_platform_data eukrea_mbimxsd_button_data = {
+ .buttons = eukrea_mbimxsd_gpio_buttons,
+ .nbuttons = ARRAY_SIZE(eukrea_mbimxsd_gpio_buttons),
+};
+
+static struct platform_device eukrea_mbimxsd_button_device = {
+ .name = "gpio-keys",
+ .id = -1,
+ .num_resources = 0,
+ .dev = {
+ .platform_data = &eukrea_mbimxsd_button_data,
+ }
+};
+
+static struct platform_device *platform_devices[] __initdata = {
+ &eukrea_mbimxsd_leds_gpio,
+ &eukrea_mbimxsd_button_device,
+};
+
+static const struct imxuart_platform_data uart_pdata __initconst = {
+ .flags = IMXUART_HAVE_RTSCTS,
+};
+
+static struct i2c_board_info eukrea_mbimxsd_i2c_devices[] = {
+ {
+ I2C_BOARD_INFO("tlv320aic23", 0x1a),
+ },
+};
+
+/*
+ * system init for baseboard usage. Will be called by cpuimx51sd init.
+ *
+ * Add platform devices present on this baseboard and init
+ * them from CPU side as far as required to use them later on
+ */
+void __init eukrea_mbimxsd51_baseboard_init(void)
+{
+ if (mxc_iomux_v3_setup_multiple_pads(eukrea_mbimxsd_pads,
+ ARRAY_SIZE(eukrea_mbimxsd_pads)))
+ printk(KERN_ERR "error setting mbimxsd pads !\n");
+
+ imx51_add_imx_uart(1, NULL);
+ imx51_add_imx_uart(2, &uart_pdata);
+
+ imx51_add_esdhc(0, NULL);
+
+ gpio_request(GPIO_LED1, "LED1");
+ gpio_direction_output(GPIO_LED1, 1);
+ gpio_free(GPIO_LED1);
+
+ gpio_request(GPIO_SWITCH1, "SWITCH1");
+ gpio_direction_input(GPIO_SWITCH1);
+ gpio_free(GPIO_SWITCH1);
+
+ i2c_register_board_info(0, eukrea_mbimxsd_i2c_devices,
+ ARRAY_SIZE(eukrea_mbimxsd_i2c_devices));
+
+ platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+}
diff --git a/arch/arm/mach-mxc91231/magx-zn5.c b/arch/arm/mach-mxc91231/magx-zn5.c
index 69816ba82930..395d83be8c98 100644
--- a/arch/arm/mach-mxc91231/magx-zn5.c
+++ b/arch/arm/mach-mxc91231/magx-zn5.c
@@ -53,8 +53,6 @@ struct sys_timer zn5_timer = {
};
MACHINE_START(MAGX_ZN5, "Motorola Zn5")
- .phys_io = MXC91231_AIPS1_BASE_ADDR,
- .io_pg_offst = ((MXC91231_AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
.boot_params = MXC91231_PHYS_OFFSET + 0x100,
.map_io = mxc91231_map_io,
.init_irq = mxc91231_init_irq,
diff --git a/arch/arm/mach-netx/include/mach/debug-macro.S b/arch/arm/mach-netx/include/mach/debug-macro.S
index e96339e71d88..56a915228180 100644
--- a/arch/arm/mach-netx/include/mach/debug-macro.S
+++ b/arch/arm/mach-netx/include/mach/debug-macro.S
@@ -13,12 +13,10 @@
#include "hardware.h"
- .macro addruart, rx, tmp
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ MMU enabled?
- moveq \rx, #0x00100000 @ physical
- movne \rx, #io_p2v(0x00100000) @ virtual
- orr \rx, \rx, #0x00000a00
+ .macro addruart, rp, rv
+ mov \rp, #0x00000a00
+ orr \rv, \rp, #io_p2v(0x00100000) @ virtual
+ orr \rp, \rp, #0x00100000 @ physical
.endm
.macro senduart,rd,rx
diff --git a/arch/arm/mach-netx/include/mach/vmalloc.h b/arch/arm/mach-netx/include/mach/vmalloc.h
index 25d5cc676e0f..7cca3574308f 100644
--- a/arch/arm/mach-netx/include/mach/vmalloc.h
+++ b/arch/arm/mach-netx/include/mach/vmalloc.h
@@ -16,4 +16,4 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#define VMALLOC_END (PAGE_OFFSET + 0x10000000)
+#define VMALLOC_END 0xd0000000
diff --git a/arch/arm/mach-netx/nxdb500.c b/arch/arm/mach-netx/nxdb500.c
index c9b174bc8ccf..ca8b203a3c99 100644
--- a/arch/arm/mach-netx/nxdb500.c
+++ b/arch/arm/mach-netx/nxdb500.c
@@ -200,8 +200,6 @@ static void __init nxdb500_init(void)
}
MACHINE_START(NXDB500, "Hilscher nxdb500")
- .phys_io = 0x00100000,
- .io_pg_offst = (io_p2v(0x00100000) >> 18) & 0xfffc,
.boot_params = 0x80000100,
.map_io = netx_map_io,
.init_irq = netx_init_irq,
diff --git a/arch/arm/mach-netx/nxdkn.c b/arch/arm/mach-netx/nxdkn.c
index 15b54c62d60f..d775cbe07278 100644
--- a/arch/arm/mach-netx/nxdkn.c
+++ b/arch/arm/mach-netx/nxdkn.c
@@ -93,8 +93,6 @@ static void __init nxdkn_init(void)
}
MACHINE_START(NXDKN, "Hilscher nxdkn")
- .phys_io = 0x00100000,
- .io_pg_offst = (io_p2v(0x00100000) >> 18) & 0xfffc,
.boot_params = 0x80000100,
.map_io = netx_map_io,
.init_irq = netx_init_irq,
diff --git a/arch/arm/mach-netx/nxeb500hmi.c b/arch/arm/mach-netx/nxeb500hmi.c
index 1061c01ff679..de369cd1dcbe 100644
--- a/arch/arm/mach-netx/nxeb500hmi.c
+++ b/arch/arm/mach-netx/nxeb500hmi.c
@@ -177,8 +177,6 @@ static void __init nxeb500hmi_init(void)
}
MACHINE_START(NXEB500HMI, "Hilscher nxeb500hmi")
- .phys_io = 0x00100000,
- .io_pg_offst = (io_p2v(0x00100000) >> 18) & 0xfffc,
.boot_params = 0x80000100,
.map_io = netx_map_io,
.init_irq = netx_init_irq,
diff --git a/arch/arm/mach-nomadik/board-nhk8815.c b/arch/arm/mach-nomadik/board-nhk8815.c
index 841d459ad59d..139930350d93 100644
--- a/arch/arm/mach-nomadik/board-nhk8815.c
+++ b/arch/arm/mach-nomadik/board-nhk8815.c
@@ -276,8 +276,6 @@ static void __init nhk8815_platform_init(void)
MACHINE_START(NOMADIK, "NHK8815")
/* Maintainer: ST MicroElectronics */
- .phys_io = NOMADIK_UART0_BASE,
- .io_pg_offst = (IO_ADDRESS(NOMADIK_UART0_BASE) >> 18) & 0xfffc,
.boot_params = 0x100,
.map_io = cpu8815_map_io,
.init_irq = cpu8815_init_irq,
diff --git a/arch/arm/mach-nomadik/include/mach/debug-macro.S b/arch/arm/mach-nomadik/include/mach/debug-macro.S
index 4f92acfba954..e7151b4b8889 100644
--- a/arch/arm/mach-nomadik/include/mach/debug-macro.S
+++ b/arch/arm/mach-nomadik/include/mach/debug-macro.S
@@ -10,13 +10,11 @@
*
*/
- .macro addruart, rx, tmp
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ MMU enabled?
- moveq \rx, #0x10000000 @ physical base address
- movne \rx, #0xf0000000 @ virtual base
- add \rx, \rx, #0x00100000
- add \rx, \rx, #0x000fb000
+ .macro addruart, rp, rv
+ mov \rp, #0x00100000
+ add \rp, \rp, #0x000fb000
+ add \rv, \rp, #0xf0000000 @ virtual base
+ add \rp, \rp, #0x10000000 @ physical base address
.endm
#include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/mach-ns9xxx/include/mach/debug-macro.S b/arch/arm/mach-ns9xxx/include/mach/debug-macro.S
index 5c934bdb7158..5a2acbdc3d67 100644
--- a/arch/arm/mach-ns9xxx/include/mach/debug-macro.S
+++ b/arch/arm/mach-ns9xxx/include/mach/debug-macro.S
@@ -12,11 +12,9 @@
#include <mach/regs-board-a9m9750dev.h>
- .macro addruart, rx, tmp
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1
- ldreq \rx, =NS9XXX_CSxSTAT_PHYS(0)
- ldrne \rx, =io_p2v(NS9XXX_CSxSTAT_PHYS(0))
+ .macro addruart, rp, rv
+ ldr \rp, =NS9XXX_CSxSTAT_PHYS(0)
+ ldr \rv, =io_p2v(NS9XXX_CSxSTAT_PHYS(0))
.endm
#define UART_SHIFT 2
diff --git a/arch/arm/mach-nuc93x/mach-nuc932evb.c b/arch/arm/mach-nuc93x/mach-nuc932evb.c
index 9f79266f08e2..d70257042480 100644
--- a/arch/arm/mach-nuc93x/mach-nuc932evb.c
+++ b/arch/arm/mach-nuc93x/mach-nuc932evb.c
@@ -35,8 +35,6 @@ static void __init nuc932evb_init(void)
MACHINE_START(NUC932EVB, "NUC932EVB")
/* Maintainer: Wan ZongShun */
- .phys_io = NUC93X_PA_UART,
- .io_pg_offst = (((u32)NUC93X_VA_UART) >> 18) & 0xfffc,
.boot_params = 0,
.map_io = nuc932evb_map_io,
.init_irq = nuc93x_init_irq,
diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c
index 41992ab71961..73c86392fcd3 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -297,8 +297,6 @@ static void __init ams_delta_map_io(void)
MACHINE_START(AMS_DELTA, "Amstrad E3 (Delta)")
/* Maintainer: Jonathan McDowell <noodles@earth.li> */
- .phys_io = 0xfff00000,
- .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
.boot_params = 0x10000100,
.map_io = ams_delta_map_io,
.reserve = omap_reserve,
diff --git a/arch/arm/mach-omap1/board-fsample.c b/arch/arm/mach-omap1/board-fsample.c
index 180ce79e5eac..149fdd32e127 100644
--- a/arch/arm/mach-omap1/board-fsample.c
+++ b/arch/arm/mach-omap1/board-fsample.c
@@ -386,8 +386,6 @@ static void __init omap_fsample_map_io(void)
MACHINE_START(OMAP_FSAMPLE, "OMAP730 F-Sample")
/* Maintainer: Brian Swetland <swetland@google.com> */
- .phys_io = 0xfff00000,
- .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
.boot_params = 0x10000100,
.map_io = omap_fsample_map_io,
.reserve = omap_reserve,
diff --git a/arch/arm/mach-omap1/board-generic.c b/arch/arm/mach-omap1/board-generic.c
index 93b9ab8fc3be..23f4ab9e2651 100644
--- a/arch/arm/mach-omap1/board-generic.c
+++ b/arch/arm/mach-omap1/board-generic.c
@@ -94,8 +94,6 @@ static void __init omap_generic_map_io(void)
MACHINE_START(OMAP_GENERIC, "Generic OMAP1510/1610/1710")
/* Maintainer: Tony Lindgren <tony@atomide.com> */
- .phys_io = 0xfff00000,
- .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
.boot_params = 0x10000100,
.map_io = omap_generic_map_io,
.reserve = omap_reserve,
diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c
index d2cda58bcc48..197adb49dc5a 100644
--- a/arch/arm/mach-omap1/board-h2.c
+++ b/arch/arm/mach-omap1/board-h2.c
@@ -458,8 +458,6 @@ static void __init h2_map_io(void)
MACHINE_START(OMAP_H2, "TI-H2")
/* Maintainer: Imre Deak <imre.deak@nokia.com> */
- .phys_io = 0xfff00000,
- .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
.boot_params = 0x10000100,
.map_io = h2_map_io,
.reserve = omap_reserve,
diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c
index c2ef4ff846c7..9126e3e37b4a 100644
--- a/arch/arm/mach-omap1/board-h3.c
+++ b/arch/arm/mach-omap1/board-h3.c
@@ -446,8 +446,6 @@ static void __init h3_map_io(void)
MACHINE_START(OMAP_H3, "TI OMAP1710 H3 board")
/* Maintainer: Texas Instruments, Inc. */
- .phys_io = 0xfff00000,
- .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
.boot_params = 0x10000100,
.map_io = h3_map_io,
.reserve = omap_reserve,
diff --git a/arch/arm/mach-omap1/board-htcherald.c b/arch/arm/mach-omap1/board-htcherald.c
index 311899ff5ffc..86afb2952225 100644
--- a/arch/arm/mach-omap1/board-htcherald.c
+++ b/arch/arm/mach-omap1/board-htcherald.c
@@ -300,8 +300,6 @@ static void __init htcherald_init_irq(void)
MACHINE_START(HERALD, "HTC Herald")
/* Maintainer: Cory Maccarrone <darkstar6262@gmail.com> */
/* Maintainer: wing-linux.sourceforge.net */
- .phys_io = 0xfff00000,
- .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
.boot_params = 0x10000100,
.map_io = htcherald_map_io,
.reserve = omap_reserve,
diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c
index 3daf87ad2576..dc2b86fd66c1 100644
--- a/arch/arm/mach-omap1/board-innovator.c
+++ b/arch/arm/mach-omap1/board-innovator.c
@@ -459,8 +459,6 @@ static void __init innovator_map_io(void)
MACHINE_START(OMAP_INNOVATOR, "TI-Innovator")
/* Maintainer: MontaVista Software, Inc. */
- .phys_io = 0xfff00000,
- .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
.boot_params = 0x10000100,
.map_io = innovator_map_io,
.reserve = omap_reserve,
diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c
index 51a4539aecf5..aa8375b2a0a3 100644
--- a/arch/arm/mach-omap1/board-nokia770.c
+++ b/arch/arm/mach-omap1/board-nokia770.c
@@ -262,8 +262,6 @@ static void __init omap_nokia770_map_io(void)
}
MACHINE_START(NOKIA770, "Nokia 770")
- .phys_io = 0xfff00000,
- .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
.boot_params = 0x10000100,
.map_io = omap_nokia770_map_io,
.reserve = omap_reserve,
diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c
index 679740cc1e90..e9dd79149a8e 100644
--- a/arch/arm/mach-omap1/board-osk.c
+++ b/arch/arm/mach-omap1/board-osk.c
@@ -580,8 +580,6 @@ static void __init osk_map_io(void)
MACHINE_START(OMAP_OSK, "TI-OSK")
/* Maintainer: Dirk Behme <dirk.behme@de.bosch.com> */
- .phys_io = 0xfff00000,
- .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
.boot_params = 0x10000100,
.map_io = osk_map_io,
.reserve = omap_reserve,
diff --git a/arch/arm/mach-omap1/board-palmte.c b/arch/arm/mach-omap1/board-palmte.c
index 782bb257a85d..f32738b1eb6b 100644
--- a/arch/arm/mach-omap1/board-palmte.c
+++ b/arch/arm/mach-omap1/board-palmte.c
@@ -285,8 +285,6 @@ static void __init omap_palmte_map_io(void)
}
MACHINE_START(OMAP_PALMTE, "OMAP310 based Palm Tungsten E")
- .phys_io = 0xfff00000,
- .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
.boot_params = 0x10000100,
.map_io = omap_palmte_map_io,
.reserve = omap_reserve,
diff --git a/arch/arm/mach-omap1/board-palmtt.c b/arch/arm/mach-omap1/board-palmtt.c
index 0b35ef54a64f..ed1400a67f75 100644
--- a/arch/arm/mach-omap1/board-palmtt.c
+++ b/arch/arm/mach-omap1/board-palmtt.c
@@ -317,8 +317,6 @@ static void __init omap_palmtt_map_io(void)
}
MACHINE_START(OMAP_PALMTT, "OMAP1510 based Palm Tungsten|T")
- .phys_io = 0xfff00000,
- .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
.boot_params = 0x10000100,
.map_io = omap_palmtt_map_io,
.reserve = omap_reserve,
diff --git a/arch/arm/mach-omap1/board-palmz71.c b/arch/arm/mach-omap1/board-palmz71.c
index 66362903b6e2..d7a245cef9a4 100644
--- a/arch/arm/mach-omap1/board-palmz71.c
+++ b/arch/arm/mach-omap1/board-palmz71.c
@@ -338,8 +338,6 @@ omap_palmz71_map_io(void)
}
MACHINE_START(OMAP_PALMZ71, "OMAP310 based Palm Zire71")
- .phys_io = 0xfff00000,
- .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
.boot_params = 0x10000100,
.map_io = omap_palmz71_map_io,
.reserve = omap_reserve,
diff --git a/arch/arm/mach-omap1/board-perseus2.c b/arch/arm/mach-omap1/board-perseus2.c
index 34ab354758b0..a8d16a255c18 100644
--- a/arch/arm/mach-omap1/board-perseus2.c
+++ b/arch/arm/mach-omap1/board-perseus2.c
@@ -347,8 +347,6 @@ static void __init omap_perseus2_map_io(void)
MACHINE_START(OMAP_PERSEUS2, "OMAP730 Perseus2")
/* Maintainer: Kevin Hilman <kjh@hilman.org> */
- .phys_io = 0xfff00000,
- .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
.boot_params = 0x10000100,
.map_io = omap_perseus2_map_io,
.reserve = omap_reserve,
diff --git a/arch/arm/mach-omap1/board-sx1.c b/arch/arm/mach-omap1/board-sx1.c
index 2eb148b8de93..d25f59e5a773 100644
--- a/arch/arm/mach-omap1/board-sx1.c
+++ b/arch/arm/mach-omap1/board-sx1.c
@@ -419,8 +419,6 @@ static void __init omap_sx1_map_io(void)
}
MACHINE_START(SX1, "OMAP310 based Siemens SX1")
- .phys_io = 0xfff00000,
- .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
.boot_params = 0x10000100,
.map_io = omap_sx1_map_io,
.reserve = omap_reserve,
diff --git a/arch/arm/mach-omap1/board-voiceblue.c b/arch/arm/mach-omap1/board-voiceblue.c
index 6b3cf14bc757..f5992c239bcd 100644
--- a/arch/arm/mach-omap1/board-voiceblue.c
+++ b/arch/arm/mach-omap1/board-voiceblue.c
@@ -283,8 +283,6 @@ EXPORT_SYMBOL(voiceblue_wdt_ping);
MACHINE_START(VOICEBLUE, "VoiceBlue OMAP5910")
/* Maintainer: Ladislav Michl <michl@2n.cz> */
- .phys_io = 0xfff00000,
- .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
.boot_params = 0x10000100,
.map_io = voiceblue_map_io,
.reserve = omap_reserve,
diff --git a/arch/arm/mach-omap1/include/mach/debug-macro.S b/arch/arm/mach-omap1/include/mach/debug-macro.S
index 671408eb4ab4..6a0fa0462365 100644
--- a/arch/arm/mach-omap1/include/mach/debug-macro.S
+++ b/arch/arm/mach-omap1/include/mach/debug-macro.S
@@ -28,56 +28,58 @@ omap_uart_virt: .word 0x0
* the desired UART phys and virt addresses temporarily into
* the omap_uart_phys and omap_uart_virt above.
*/
- .macro addruart, rx, tmp
+ .macro addruart, rp, rv
/* Use omap_uart_phys/virt if already configured */
-9: mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ MMU enabled?
- ldreq \rx, =__virt_to_phys(omap_uart_phys) @ physical base address
- ldrne \rx, =omap_uart_virt @ virtual base
- ldr \rx, [\rx, #0]
- cmp \rx, #0 @ is port configured?
+9: mrc p15, 0, \rp, c1, c0
+ tst \rp, #1 @ MMU enabled?
+ ldreq \rp, =__virt_to_phys(omap_uart_phys) @ MMU not enabled
+ ldrne \rp, =omap_uart_phys @ MMU enabled
+ add \rv, \rp, #4 @ omap_uart_virt
+ ldr \rp, [\rp, #0]
+ ldr \rv, [\rv, #0]
+ cmp \rp, #0 @ is port configured?
+ cmpne \rv, #0
bne 99f @ already configured
/* Check the debug UART configuration set in uncompress.h */
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ MMU enabled?
- ldreq \rx, =OMAP_UART_INFO
- ldrne \rx, =__phys_to_virt(OMAP_UART_INFO)
- ldr \rx, [\rx, #0]
+ mrc p15, 0, \rp, c1, c0
+ tst \rp, #1 @ MMU enabled?
+ ldreq \rp, =OMAP_UART_INFO @ MMU not enabled
+ ldrne \rp, =__phys_to_virt(OMAP_UART_INFO) @ MMU enabled
+ ldr \rp, [\rp, #0]
/* Select the UART to use based on the UART1 scratchpad value */
-10: cmp \rx, #0 @ no port configured?
+10: cmp \rp, #0 @ no port configured?
beq 11f @ if none, try to use UART1
- cmp \rx, #OMAP1UART1
+ cmp \rp, #OMAP1UART1
beq 11f @ configure OMAP1UART1
- cmp \rx, #OMAP1UART2
+ cmp \rp, #OMAP1UART2
beq 12f @ configure OMAP1UART2
- cmp \rx, #OMAP1UART3
+ cmp \rp, #OMAP1UART3
beq 13f @ configure OMAP2UART3
/* Configure the UART offset from the phys/virt base */
-11: mov \rx, #0x00fb0000 @ OMAP1UART1
+11: mov \rp, #0x00fb0000 @ OMAP1UART1
b 98f
-12: mov \rx, #0x00fb0000 @ OMAP1UART1
- orr \rx, \rx, #0x00000800 @ OMAP1UART2
+12: mov \rp, #0x00fb0000 @ OMAP1UART1
+ orr \rp, \rp, #0x00000800 @ OMAP1UART2
b 98f
-13: mov \rx, #0x00fb0000 @ OMAP1UART1
- orr \rx, \rx, #0x00000800 @ OMAP1UART2
- orr \rx, \rx, #0x00009000 @ OMAP1UART3
+13: mov \rp, #0x00fb0000 @ OMAP1UART1
+ orr \rp, \rp, #0x00000800 @ OMAP1UART2
+ orr \rp, \rp, #0x00009000 @ OMAP1UART3
/* Store both phys and virt address for the uart */
-98: add \rx, \rx, #0xff000000 @ phys base
- mrc p15, 0, \tmp, c1, c0
- tst \tmp, #1 @ MMU enabled?
- ldreq \tmp, =__virt_to_phys(omap_uart_phys)
- ldrne \tmp, =omap_uart_phys
- str \rx, [\tmp, #0]
- sub \rx, \rx, #0xff000000 @ phys base
- add \rx, \rx, #0xfe000000 @ virt base
- ldreq \tmp, =__virt_to_phys(omap_uart_virt)
- ldrne \tmp, =omap_uart_virt
- str \rx, [\tmp, #0]
+98: add \rp, \rp, #0xff000000 @ phys base
+ mrc p15, 0, \rv, c1, c0
+ tst \rv, #1 @ MMU enabled?
+ ldreq \rv, =__virt_to_phys(omap_uart_phys) @ MMU not enabled
+ ldrne \rv, =omap_uart_phys @ MMU enabled
+ str \rp, [\rv, #0]
+ sub \rp, \rp, #0xff000000 @ phys base
+ add \rp, \rp, #0xfe000000 @ virt base
+ add \rv, \rv, #4 @ omap_uart_lsr
+ str \rp, [\rv, #0]
b 9b
99:
.endm
diff --git a/arch/arm/mach-omap1/include/mach/vmalloc.h b/arch/arm/mach-omap1/include/mach/vmalloc.h
index 1b2af14df151..b001f67d695b 100644
--- a/arch/arm/mach-omap1/include/mach/vmalloc.h
+++ b/arch/arm/mach-omap1/include/mach/vmalloc.h
@@ -17,4 +17,4 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#define VMALLOC_END (PAGE_OFFSET + 0x18000000)
+#define VMALLOC_END 0xd8000000
diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c
index 8538e4131d27..b857ce484510 100644
--- a/arch/arm/mach-omap2/board-2430sdp.c
+++ b/arch/arm/mach-omap2/board-2430sdp.c
@@ -253,8 +253,6 @@ static void __init omap_2430sdp_map_io(void)
MACHINE_START(OMAP_2430SDP, "OMAP2430 sdp2430 board")
/* Maintainer: Syed Khasim - Texas Instruments Inc */
- .phys_io = 0x48000000,
- .io_pg_offst = ((0xfa000000) >> 18) & 0xfffc,
.boot_params = 0x80000100,
.map_io = omap_2430sdp_map_io,
.reserve = omap_reserve,
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index 67b95b5f1a2f..a5b095cf2adc 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -817,8 +817,6 @@ static void __init omap_3430sdp_init(void)
MACHINE_START(OMAP_3430SDP, "OMAP3430 3430SDP board")
/* Maintainer: Syed Khasim - Texas Instruments Inc */
- .phys_io = 0x48000000,
- .io_pg_offst = ((0xfa000000) >> 18) & 0xfffc,
.boot_params = 0x80000100,
.map_io = omap3_map_io,
.reserve = omap_reserve,
diff --git a/arch/arm/mach-omap2/board-3630sdp.c b/arch/arm/mach-omap2/board-3630sdp.c
index b359c3f7bb39..fd27ac0860b0 100644
--- a/arch/arm/mach-omap2/board-3630sdp.c
+++ b/arch/arm/mach-omap2/board-3630sdp.c
@@ -217,8 +217,6 @@ static void __init omap_sdp_init(void)
}
MACHINE_START(OMAP_3630SDP, "OMAP 3630SDP board")
- .phys_io = 0x48000000,
- .io_pg_offst = ((0xfa000000) >> 18) & 0xfffc,
.boot_params = 0x80000100,
.map_io = omap3_map_io,
.reserve = omap_reserve,
diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c
index 9447644774c2..0b6a65f3a10a 100644
--- a/arch/arm/mach-omap2/board-4430sdp.c
+++ b/arch/arm/mach-omap2/board-4430sdp.c
@@ -458,8 +458,6 @@ static void __init omap_4430sdp_map_io(void)
MACHINE_START(OMAP_4430SDP, "OMAP4430 4430SDP board")
/* Maintainer: Santosh Shilimkar - Texas Instruments Inc */
- .phys_io = 0x48000000,
- .io_pg_offst = ((0xfa000000) >> 18) & 0xfffc,
.boot_params = 0x80000100,
.map_io = omap_4430sdp_map_io,
.reserve = omap_reserve,
diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c
index 4d0f58592864..d547036aff3f 100644
--- a/arch/arm/mach-omap2/board-am3517evm.c
+++ b/arch/arm/mach-omap2/board-am3517evm.c
@@ -375,6 +375,31 @@ static void __init am3517_evm_init_irq(void)
omap_gpio_init();
}
+static struct omap_musb_board_data musb_board_data = {
+ .interface_type = MUSB_INTERFACE_ULPI,
+ .mode = MUSB_OTG,
+ .power = 500,
+};
+
+static __init void am3517_evm_musb_init(void)
+{
+ u32 devconf2;
+
+ /*
+ * Set up USB clock/mode in the DEVCONF2 register.
+ */
+ devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
+
+ /* USB2.0 PHY reference clock is 13 MHz */
+ devconf2 &= ~(CONF2_REFFREQ | CONF2_OTGMODE | CONF2_PHY_GPIOMODE);
+ devconf2 |= CONF2_REFFREQ_13MHZ | CONF2_SESENDEN | CONF2_VBDTCTEN
+ | CONF2_DATPOL;
+
+ omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
+
+ usb_musb_init(&musb_board_data);
+}
+
static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
.port_mode[0] = EHCI_HCD_OMAP_MODE_PHY,
#if defined(CONFIG_PANEL_SHARP_LQ043T1DG01) || \
@@ -393,6 +418,8 @@ static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
#ifdef CONFIG_OMAP_MUX
static struct omap_board_mux board_mux[] __initdata = {
+ /* USB OTG DRVVBUS offset = 0x212 */
+ OMAP3_MUX(SAD2D_MCAD23, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLDOWN),
{ .reg_offset = OMAP_MUX_TERMINATOR },
};
#else
@@ -459,11 +486,12 @@ static void __init am3517_evm_init(void)
ARRAY_SIZE(am3517evm_i2c1_boardinfo));
/*Ethernet*/
am3517_evm_ethernet_init(&am3517_evm_emac_pdata);
+
+ /* MUSB */
+ am3517_evm_musb_init();
}
MACHINE_START(OMAP3517EVM, "OMAP3517/AM3517 EVM")
- .phys_io = 0x48000000,
- .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc,
.boot_params = 0x80000100,
.map_io = omap3_map_io,
.reserve = omap_reserve,
diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c
index c6421a72514a..68f07f5f441a 100644
--- a/arch/arm/mach-omap2/board-apollon.c
+++ b/arch/arm/mach-omap2/board-apollon.c
@@ -356,8 +356,6 @@ static void __init omap_apollon_map_io(void)
MACHINE_START(OMAP_APOLLON, "OMAP24xx Apollon")
/* Maintainer: Kyungmin Park <kyungmin.park@samsung.com> */
- .phys_io = 0x48000000,
- .io_pg_offst = ((0xfa000000) >> 18) & 0xfffc,
.boot_params = 0x80000100,
.map_io = omap_apollon_map_io,
.reserve = omap_reserve,
diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
index e10bc109415c..934d9380c372 100644
--- a/arch/arm/mach-omap2/board-cm-t35.c
+++ b/arch/arm/mach-omap2/board-cm-t35.c
@@ -809,8 +809,6 @@ static void __init cm_t35_init(void)
}
MACHINE_START(CM_T35, "Compulab CM-T35")
- .phys_io = 0x48000000,
- .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc,
.boot_params = 0x80000100,
.map_io = omap3_map_io,
.reserve = omap_reserve,
diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c
index a07086d6a0b2..2205c20a4cdb 100644
--- a/arch/arm/mach-omap2/board-devkit8000.c
+++ b/arch/arm/mach-omap2/board-devkit8000.c
@@ -800,8 +800,6 @@ static void __init devkit8000_init(void)
}
MACHINE_START(DEVKIT8000, "OMAP3 Devkit8000")
- .phys_io = 0x48000000,
- .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc,
.boot_params = 0x80000100,
.map_io = omap3_map_io,
.reserve = omap_reserve,
diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c
index 3482b99e8c86..69064b1c6a75 100644
--- a/arch/arm/mach-omap2/board-generic.c
+++ b/arch/arm/mach-omap2/board-generic.c
@@ -54,8 +54,6 @@ static void __init omap_generic_map_io(void)
MACHINE_START(OMAP_GENERIC, "Generic OMAP24xx")
/* Maintainer: Paul Mundt <paul.mundt@nokia.com> */
- .phys_io = 0x48000000,
- .io_pg_offst = ((0xfa000000) >> 18) & 0xfffc,
.boot_params = 0x80000100,
.map_io = omap_generic_map_io,
.reserve = omap_reserve,
diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c
index e09bd686389f..cc39fc866524 100644
--- a/arch/arm/mach-omap2/board-h4.c
+++ b/arch/arm/mach-omap2/board-h4.c
@@ -376,8 +376,6 @@ static void __init omap_h4_map_io(void)
MACHINE_START(OMAP_H4, "OMAP2420 H4 board")
/* Maintainer: Paul Mundt <paul.mundt@nokia.com> */
- .phys_io = 0x48000000,
- .io_pg_offst = ((0xfa000000) >> 18) & 0xfffc,
.boot_params = 0x80000100,
.map_io = omap_h4_map_io,
.reserve = omap_reserve,
diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c
index 175f04339761..b62a68ba069b 100644
--- a/arch/arm/mach-omap2/board-igep0020.c
+++ b/arch/arm/mach-omap2/board-igep0020.c
@@ -533,8 +533,6 @@ static void __init igep2_init(void)
}
MACHINE_START(IGEP0020, "IGEP v2 board")
- .phys_io = 0x48000000,
- .io_pg_offst = ((0xfa000000) >> 18) & 0xfffc,
.boot_params = 0x80000100,
.map_io = omap3_map_io,
.reserve = omap_reserve,
diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
index 00d9b13b01c5..f28fd77bceb3 100644
--- a/arch/arm/mach-omap2/board-ldp.c
+++ b/arch/arm/mach-omap2/board-ldp.c
@@ -442,8 +442,6 @@ static void __init omap_ldp_init(void)
}
MACHINE_START(OMAP_LDP, "OMAP LDP board")
- .phys_io = 0x48000000,
- .io_pg_offst = ((0xfa000000) >> 18) & 0xfffc,
.boot_params = 0x80000100,
.map_io = omap3_map_io,
.reserve = omap_reserve,
diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c
index a3e2b49aa39f..3f7966873507 100644
--- a/arch/arm/mach-omap2/board-n8x0.c
+++ b/arch/arm/mach-omap2/board-n8x0.c
@@ -674,8 +674,6 @@ static void __init n8x0_init_machine(void)
}
MACHINE_START(NOKIA_N800, "Nokia N800")
- .phys_io = 0x48000000,
- .io_pg_offst = ((0xfa000000) >> 18) & 0xfffc,
.boot_params = 0x80000100,
.map_io = n8x0_map_io,
.reserve = omap_reserve,
@@ -685,8 +683,6 @@ MACHINE_START(NOKIA_N800, "Nokia N800")
MACHINE_END
MACHINE_START(NOKIA_N810, "Nokia N810")
- .phys_io = 0x48000000,
- .io_pg_offst = ((0xfa000000) >> 18) & 0xfffc,
.boot_params = 0x80000100,
.map_io = n8x0_map_io,
.reserve = omap_reserve,
@@ -696,8 +692,6 @@ MACHINE_START(NOKIA_N810, "Nokia N810")
MACHINE_END
MACHINE_START(NOKIA_N810_WIMAX, "Nokia N810 WiMAX")
- .phys_io = 0x48000000,
- .io_pg_offst = ((0xfa000000) >> 18) & 0xfffc,
.boot_params = 0x80000100,
.map_io = n8x0_map_io,
.reserve = omap_reserve,
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 87969c7df652..9d9f5b881ee8 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -487,8 +487,6 @@ static void __init omap3_beagle_init(void)
MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board")
/* Maintainer: Syed Mohammed Khasim - http://beagleboard.org */
- .phys_io = 0x48000000,
- .io_pg_offst = ((0xfa000000) >> 18) & 0xfffc,
.boot_params = 0x80000100,
.map_io = omap3_map_io,
.reserve = omap_reserve,
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index f76d9c0a47a1..8936e4fba334 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -714,8 +714,6 @@ static void __init omap3_evm_init(void)
MACHINE_START(OMAP3EVM, "OMAP3 EVM")
/* Maintainer: Syed Mohammed Khasim - Texas Instruments */
- .phys_io = 0x48000000,
- .io_pg_offst = ((0xfa000000) >> 18) & 0xfffc,
.boot_params = 0x80000100,
.map_io = omap3_map_io,
.reserve = omap_reserve,
diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c
index dd3af2be13be..41d6f549070c 100644
--- a/arch/arm/mach-omap2/board-omap3pandora.c
+++ b/arch/arm/mach-omap2/board-omap3pandora.c
@@ -25,7 +25,7 @@
#include <linux/spi/ads7846.h>
#include <linux/regulator/machine.h>
#include <linux/i2c/twl.h>
-#include <linux/spi/wl12xx.h>
+#include <linux/wl12xx.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/nand.h>
#include <linux/leds.h>
@@ -717,8 +717,6 @@ static void __init omap3pandora_init(void)
}
MACHINE_START(OMAP3_PANDORA, "Pandora Handheld Console")
- .phys_io = 0x48000000,
- .io_pg_offst = ((0xfa000000) >> 18) & 0xfffc,
.boot_params = 0x80000100,
.map_io = omap3_map_io,
.reserve = omap_reserve,
diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c
index bcd01d278c65..bc5ac83bd4cf 100644
--- a/arch/arm/mach-omap2/board-omap3stalker.c
+++ b/arch/arm/mach-omap2/board-omap3stalker.c
@@ -654,8 +654,6 @@ static void __init omap3_stalker_init(void)
MACHINE_START(SBC3530, "OMAP3 STALKER")
/* Maintainer: Jason Lam -lzg@ema-tech.com */
- .phys_io = 0x48000000,
- .io_pg_offst = ((0xfa000000) >> 18) & 0xfffc,
.boot_params = 0x80000100,
.map_io = omap3_map_io,
.init_irq = omap3_stalker_init_irq,
diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c
index 663c62d271e8..0e99ce584dbf 100644
--- a/arch/arm/mach-omap2/board-omap3touchbook.c
+++ b/arch/arm/mach-omap2/board-omap3touchbook.c
@@ -538,8 +538,6 @@ static void __init omap3_touchbook_init(void)
MACHINE_START(TOUCHBOOK, "OMAP3 touchbook Board")
/* Maintainer: Gregoire Gentil - http://www.alwaysinnovating.com */
- .phys_io = 0x48000000,
- .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc,
.boot_params = 0x80000100,
.map_io = omap3_map_io,
.reserve = omap_reserve,
diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
index c03d1d56db56..db69bcadf4c7 100644
--- a/arch/arm/mach-omap2/board-omap4panda.c
+++ b/arch/arm/mach-omap2/board-omap4panda.c
@@ -294,8 +294,6 @@ static void __init omap4_panda_map_io(void)
MACHINE_START(OMAP4_PANDA, "OMAP4 Panda board")
/* Maintainer: David Anders - Texas Instruments Inc */
- .phys_io = 0x48000000,
- .io_pg_offst = ((0xfa000000) >> 18) & 0xfffc,
.boot_params = 0x80000100,
.map_io = omap4_panda_map_io,
.init_irq = omap4_panda_init_irq,
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index 4c4843618350..5e528ca015a1 100644
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -501,8 +501,6 @@ static void __init overo_init(void)
}
MACHINE_START(OVERO, "Gumstix Overo")
- .phys_io = 0x48000000,
- .io_pg_offst = ((0xfa000000) >> 18) & 0xfffc,
.boot_params = 0x80000100,
.map_io = omap3_map_io,
.reserve = omap_reserve,
diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c
index 9a5eb87425fc..ce28a851dcd3 100644
--- a/arch/arm/mach-omap2/board-rx51-peripherals.c
+++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
@@ -14,7 +14,7 @@
#include <linux/input.h>
#include <linux/input/matrix_keypad.h>
#include <linux/spi/spi.h>
-#include <linux/spi/wl12xx.h>
+#include <linux/wl12xx.h>
#include <linux/i2c.h>
#include <linux/i2c/twl.h>
#include <linux/clk.h>
diff --git a/arch/arm/mach-omap2/board-rx51.c b/arch/arm/mach-omap2/board-rx51.c
index a58e8cb1a7fc..36f2cf4efd57 100644
--- a/arch/arm/mach-omap2/board-rx51.c
+++ b/arch/arm/mach-omap2/board-rx51.c
@@ -150,8 +150,6 @@ static void __init rx51_map_io(void)
MACHINE_START(NOKIA_RX51, "Nokia RX-51 board")
/* Maintainer: Lauri Leukkunen <lauri.leukkunen@nokia.com> */
- .phys_io = 0x48000000,
- .io_pg_offst = ((0xfa000000) >> 18) & 0xfffc,
.boot_params = 0x80000100,
.map_io = rx51_map_io,
.reserve = omap_reserve,
diff --git a/arch/arm/mach-omap2/board-zoom-peripherals.c b/arch/arm/mach-omap2/board-zoom-peripherals.c
index 6b3984964cc5..189a6d1600b2 100644
--- a/arch/arm/mach-omap2/board-zoom-peripherals.c
+++ b/arch/arm/mach-omap2/board-zoom-peripherals.c
@@ -16,6 +16,8 @@
#include <linux/gpio.h>
#include <linux/i2c/twl.h>
#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
+#include <linux/wl12xx.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -27,6 +29,9 @@
#include "mux.h"
#include "hsmmc.h"
+#define OMAP_ZOOM_WLAN_PMENA_GPIO (101)
+#define OMAP_ZOOM_WLAN_IRQ_GPIO (162)
+
/* Zoom2 has Qwerty keyboard*/
static int board_keymap[] = {
KEY(0, 0, KEY_E),
@@ -106,6 +111,11 @@ static struct regulator_consumer_supply zoom_vmmc2_supply = {
.supply = "vmmc",
};
+static struct regulator_consumer_supply zoom_vmmc3_supply = {
+ .supply = "vmmc",
+ .dev_name = "mmci-omap-hs.2",
+};
+
/* VMMC1 for OMAP VDD_MMC1 (i/o) and MMC1 card */
static struct regulator_init_data zoom_vmmc1 = {
.constraints = {
@@ -151,6 +161,38 @@ static struct regulator_init_data zoom_vsim = {
.consumer_supplies = &zoom_vsim_supply,
};
+static struct regulator_init_data zoom_vmmc3 = {
+ .constraints = {
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = 1,
+ .consumer_supplies = &zoom_vmmc3_supply,
+};
+
+static struct fixed_voltage_config zoom_vwlan = {
+ .supply_name = "vwl1271",
+ .microvolts = 1800000, /* 1.8V */
+ .gpio = OMAP_ZOOM_WLAN_PMENA_GPIO,
+ .startup_delay = 70000, /* 70msec */
+ .enable_high = 1,
+ .enabled_at_boot = 0,
+ .init_data = &zoom_vmmc3,
+};
+
+static struct platform_device omap_vwlan_device = {
+ .name = "reg-fixed-voltage",
+ .id = 1,
+ .dev = {
+ .platform_data = &zoom_vwlan,
+ },
+};
+
+struct wl12xx_platform_data omap_zoom_wlan_data __initdata = {
+ .irq = OMAP_GPIO_IRQ(OMAP_ZOOM_WLAN_IRQ_GPIO),
+ /* ZOOM ref clock is 26 MHz */
+ .board_ref_clock = 1,
+};
+
static struct omap2_hsmmc_info mmc[] __initdata = {
{
.name = "external",
@@ -168,6 +210,14 @@ static struct omap2_hsmmc_info mmc[] __initdata = {
.nonremovable = true,
.power_saving = true,
},
+ {
+ .name = "wl1271",
+ .mmc = 3,
+ .caps = MMC_CAP_4_BIT_DATA,
+ .gpio_wp = -EINVAL,
+ .gpio_cd = -EINVAL,
+ .nonremovable = true,
+ },
{} /* Terminator */
};
@@ -279,7 +329,11 @@ static void enable_board_wakeup_source(void)
void __init zoom_peripherals_init(void)
{
+ if (wl12xx_set_platform_data(&omap_zoom_wlan_data))
+ pr_err("error setting wl12xx data\n");
+
omap_i2c_init();
+ platform_device_register(&omap_vwlan_device);
usb_musb_init(&musb_board_data);
enable_board_wakeup_source();
}
diff --git a/arch/arm/mach-omap2/board-zoom2.c b/arch/arm/mach-omap2/board-zoom2.c
index 3ad9ecf7f5e2..24bbd0def64f 100644
--- a/arch/arm/mach-omap2/board-zoom2.c
+++ b/arch/arm/mach-omap2/board-zoom2.c
@@ -141,8 +141,6 @@ static void __init omap_zoom2_init(void)
}
MACHINE_START(OMAP_ZOOM2, "OMAP Zoom2 board")
- .phys_io = ZOOM_UART_BASE,
- .io_pg_offst = (ZOOM_UART_VIRT >> 18) & 0xfffc,
.boot_params = 0x80000100,
.map_io = omap3_map_io,
.reserve = omap_reserve,
diff --git a/arch/arm/mach-omap2/board-zoom3.c b/arch/arm/mach-omap2/board-zoom3.c
index 6ca0b8341615..b2bb3ff971ac 100644
--- a/arch/arm/mach-omap2/board-zoom3.c
+++ b/arch/arm/mach-omap2/board-zoom3.c
@@ -123,8 +123,6 @@ static void __init omap_zoom_init(void)
}
MACHINE_START(OMAP_ZOOM3, "OMAP Zoom3 board")
- .phys_io = ZOOM_UART_BASE,
- .io_pg_offst = (ZOOM_UART_VIRT >> 18) & 0xfffc,
.boot_params = 0x80000100,
.map_io = omap3_map_io,
.reserve = omap_reserve,
diff --git a/arch/arm/mach-omap2/include/mach/debug-macro.S b/arch/arm/mach-omap2/include/mach/debug-macro.S
index 09331bbbda52..6a4d4136002e 100644
--- a/arch/arm/mach-omap2/include/mach/debug-macro.S
+++ b/arch/arm/mach-omap2/include/mach/debug-macro.S
@@ -31,95 +31,94 @@ omap_uart_lsr: .word 0
* the desired UART phys and virt addresses temporarily into
* the omap_uart_phys and omap_uart_virt above.
*/
- .macro addruart, rx, tmp
+ .macro addruart, rp, rv
/* Use omap_uart_phys/virt if already configured */
-10: mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ MMU enabled?
- ldreq \rx, =__virt_to_phys(omap_uart_phys) @ physical base address
- ldrne \rx, =omap_uart_virt @ virtual base address
- ldr \rx, [\rx, #0]
- cmp \rx, #0 @ is port configured?
+10: mrc p15, 0, \rp, c1, c0
+ tst \rp, #1 @ MMU enabled?
+ ldreq \rp, =__virt_to_phys(omap_uart_phys) @ MMU not enabled
+ ldrne \rp, =omap_uart_phys @ MMU enabled
+ add \rv, \rp, #4 @ omap_uart_virt
+ ldr \rp, [\rp, #0]
+ ldr \rv, [\rv, #0]
+ cmp \rp, #0 @ is port configured?
+ cmpne \rv, #0
bne 99f @ already configured
/* Check the debug UART configuration set in uncompress.h */
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ MMU enabled?
- ldreq \rx, =OMAP_UART_INFO
- ldrne \rx, =__phys_to_virt(OMAP_UART_INFO)
- ldr \rx, [\rx, #0]
+ mrc p15, 0, \rp, c1, c0
+ tst \rp, #1 @ MMU enabled?
+ ldreq \rp, =OMAP_UART_INFO @ MMU not enabled
+ ldrne \rp, =__phys_to_virt(OMAP_UART_INFO) @ MMU enabled
+ ldr \rp, [\rp, #0]
/* Select the UART to use based on the UART1 scratchpad value */
- cmp \rx, #0 @ no port configured?
+ cmp \rp, #0 @ no port configured?
beq 21f @ if none, try to use UART1
- cmp \rx, #OMAP2UART1 @ OMAP2/3/4UART1
+ cmp \rp, #OMAP2UART1 @ OMAP2/3/4UART1
beq 21f @ configure OMAP2/3/4UART1
- cmp \rx, #OMAP2UART2 @ OMAP2/3/4UART2
+ cmp \rp, #OMAP2UART2 @ OMAP2/3/4UART2
beq 22f @ configure OMAP2/3/4UART2
- cmp \rx, #OMAP2UART3 @ only on 24xx
+ cmp \rp, #OMAP2UART3 @ only on 24xx
beq 23f @ configure OMAP2UART3
- cmp \rx, #OMAP3UART3 @ only on 34xx
+ cmp \rp, #OMAP3UART3 @ only on 34xx
beq 33f @ configure OMAP3UART3
- cmp \rx, #OMAP4UART3 @ only on 44xx
+ cmp \rp, #OMAP4UART3 @ only on 44xx
beq 43f @ configure OMAP4UART3
- cmp \rx, #OMAP3UART4 @ only on 36xx
+ cmp \rp, #OMAP3UART4 @ only on 36xx
beq 34f @ configure OMAP3UART4
- cmp \rx, #OMAP4UART4 @ only on 44xx
+ cmp \rp, #OMAP4UART4 @ only on 44xx
beq 44f @ configure OMAP4UART4
- cmp \rx, #ZOOM_UART @ only on zoom2/3
+ cmp \rp, #ZOOM_UART @ only on zoom2/3
beq 95f @ configure ZOOM_UART
/* Configure the UART offset from the phys/virt base */
-21: mov \rx, #UART_OFFSET(OMAP2_UART1_BASE) @ omap2/3/4
+21: mov \rp, #UART_OFFSET(OMAP2_UART1_BASE) @ omap2/3/4
b 98f
-22: mov \rx, #UART_OFFSET(OMAP2_UART2_BASE) @ omap2/3/4
+22: mov \rp, #UART_OFFSET(OMAP2_UART2_BASE) @ omap2/3/4
b 98f
-23: mov \rx, #UART_OFFSET(OMAP2_UART3_BASE)
+23: mov \rp, #UART_OFFSET(OMAP2_UART3_BASE)
b 98f
-33: mov \rx, #UART_OFFSET(OMAP3_UART1_BASE)
- add \rx, \rx, #0x00fb0000
- add \rx, \rx, #0x00006000 @ OMAP3_UART3_BASE
+33: mov \rp, #UART_OFFSET(OMAP3_UART1_BASE)
+ add \rp, \rp, #0x00fb0000
+ add \rp, \rp, #0x00006000 @ OMAP3_UART3_BASE
b 98f
-34: mov \rx, #UART_OFFSET(OMAP3_UART1_BASE)
- add \rx, \rx, #0x00fb0000
- add \rx, \rx, #0x00028000 @ OMAP3_UART4_BASE
+34: mov \rp, #UART_OFFSET(OMAP3_UART1_BASE)
+ add \rp, \rp, #0x00fb0000
+ add \rp, \rp, #0x00028000 @ OMAP3_UART4_BASE
b 98f
-43: mov \rx, #UART_OFFSET(OMAP4_UART3_BASE)
+43: mov \rp, #UART_OFFSET(OMAP4_UART3_BASE)
b 98f
-44: mov \rx, #UART_OFFSET(OMAP4_UART4_BASE)
+44: mov \rp, #UART_OFFSET(OMAP4_UART4_BASE)
b 98f
-95: ldr \rx, =ZOOM_UART_BASE
- mrc p15, 0, \tmp, c1, c0
- tst \tmp, #1 @ MMU enabled?
- ldreq \tmp, =__virt_to_phys(omap_uart_phys)
- ldrne \tmp, =omap_uart_phys
- str \rx, [\tmp, #0]
- ldr \rx, =ZOOM_UART_VIRT
- ldreq \tmp, =__virt_to_phys(omap_uart_virt)
- ldrne \tmp, =omap_uart_virt
- str \rx, [\tmp, #0]
- mov \rx, #(UART_LSR << ZOOM_PORT_SHIFT)
- ldreq \tmp, =__virt_to_phys(omap_uart_lsr)
- ldrne \tmp, =omap_uart_lsr
- str \rx, [\tmp, #0]
+95: ldr \rp, =ZOOM_UART_BASE
+ mrc p15, 0, \rv, c1, c0
+ tst \rv, #1 @ MMU enabled?
+ ldreq \rv, =__virt_to_phys(omap_uart_phys) @ MMU not enabled
+ ldrne \rv, =omap_uart_phys @ MMU enabled
+ str \rp, [\rv, #0]
+ ldr \rp, =ZOOM_UART_VIRT
+ add \rv, \rv, #4 @ omap_uart_virt
+ str \rp, [\rv, #0]
+ mov \rp, #(UART_LSR << ZOOM_PORT_SHIFT)
+ add \rv, \rv, #4 @ omap_uart_lsr
+ str \rp, [\rv, #0]
b 10b
/* Store both phys and virt address for the uart */
-98: add \rx, \rx, #0x48000000 @ phys base
- mrc p15, 0, \tmp, c1, c0
- tst \tmp, #1 @ MMU enabled?
- ldreq \tmp, =__virt_to_phys(omap_uart_phys)
- ldrne \tmp, =omap_uart_phys
- str \rx, [\tmp, #0]
- sub \rx, \rx, #0x48000000 @ phys base
- add \rx, \rx, #0xfa000000 @ virt base
- ldreq \tmp, =__virt_to_phys(omap_uart_virt)
- ldrne \tmp, =omap_uart_virt
- str \rx, [\tmp, #0]
- mov \rx, #(UART_LSR << OMAP_PORT_SHIFT)
- ldreq \tmp, =__virt_to_phys(omap_uart_lsr)
- ldrne \tmp, =omap_uart_lsr
- str \rx, [\tmp, #0]
+98: add \rp, \rp, #0x48000000 @ phys base
+ mrc p15, 0, \rv, c1, c0
+ tst \rv, #1 @ MMU enabled?
+ ldreq \rv, =__virt_to_phys(omap_uart_phys) @ MMU not enabled
+ ldrne \rv, =omap_uart_phys @ MMU enabled
+ str \rp, [\rv, #0]
+ sub \rp, \rp, #0x48000000 @ phys base
+ add \rp, \rp, #0xfa000000 @ virt base
+ add \rv, \rv, #4 @ omap_uart_virt
+ str \rp, [\rv, #0]
+ mov \rp, #(UART_LSR << OMAP_PORT_SHIFT)
+ add \rv, \rv, #4 @ omap_uart_lsr
+ str \rp, [\rv, #0]
b 10b
99:
@@ -131,9 +130,9 @@ omap_uart_lsr: .word 0
.macro busyuart,rd,rx
1001: mrc p15, 0, \rd, c1, c0
- tst \rd, #1 @ MMU enabled?
- ldreq \rd, =__virt_to_phys(omap_uart_lsr)
- ldrne \rd, =omap_uart_lsr
+ tst \rd, #1 @ MMU enabled?
+ ldreq \rd, =__virt_to_phys(omap_uart_lsr) @ MMU not enabled
+ ldrne \rd, =omap_uart_lsr @ MMU enabled
ldr \rd, [\rd, #0]
ldrb \rd, [\rx, \rd]
and \rd, \rd, #(UART_LSR_TEMT | UART_LSR_THRE)
diff --git a/arch/arm/mach-omap2/include/mach/vmalloc.h b/arch/arm/mach-omap2/include/mach/vmalloc.h
index 9ce9b6e8ad23..4da31e997efe 100644
--- a/arch/arm/mach-omap2/include/mach/vmalloc.h
+++ b/arch/arm/mach-omap2/include/mach/vmalloc.h
@@ -17,4 +17,4 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#define VMALLOC_END (PAGE_OFFSET + 0x38000000)
+#define VMALLOC_END 0xf8000000
diff --git a/arch/arm/mach-omap2/usb-musb.c b/arch/arm/mach-omap2/usb-musb.c
index 33a5cde1c227..72605584bfff 100644
--- a/arch/arm/mach-omap2/usb-musb.c
+++ b/arch/arm/mach-omap2/usb-musb.c
@@ -28,6 +28,7 @@
#include <mach/hardware.h>
#include <mach/irqs.h>
+#include <mach/am35xx.h>
#include <plat/usb.h>
#ifdef CONFIG_USB_MUSB_SOC
@@ -89,6 +90,9 @@ void __init usb_musb_init(struct omap_musb_board_data *board_data)
{
if (cpu_is_omap243x()) {
musb_resources[0].start = OMAP243X_HS_BASE;
+ } else if (cpu_is_omap3517() || cpu_is_omap3505()) {
+ musb_resources[0].start = AM35XX_IPSS_USBOTGSS_BASE;
+ musb_resources[1].start = INT_35XX_USBOTG_IRQ;
} else if (cpu_is_omap34xx()) {
musb_resources[0].start = OMAP34XX_HSUSB_OTG_BASE;
} else if (cpu_is_omap44xx()) {
diff --git a/arch/arm/mach-orion5x/d2net-setup.c b/arch/arm/mach-orion5x/d2net-setup.c
index 7130904ad999..b1c451f5ee27 100644
--- a/arch/arm/mach-orion5x/d2net-setup.c
+++ b/arch/arm/mach-orion5x/d2net-setup.c
@@ -336,8 +336,6 @@ static void __init d2net_init(void)
#ifdef CONFIG_MACH_D2NET
MACHINE_START(D2NET, "LaCie d2 Network")
- .phys_io = ORION5X_REGS_PHYS_BASE,
- .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
.boot_params = 0x00000100,
.init_machine = d2net_init,
.map_io = orion5x_map_io,
@@ -349,8 +347,6 @@ MACHINE_END
#ifdef CONFIG_MACH_BIGDISK
MACHINE_START(BIGDISK, "LaCie Big Disk Network")
- .phys_io = ORION5X_REGS_PHYS_BASE,
- .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
.boot_params = 0x00000100,
.init_machine = d2net_init,
.map_io = orion5x_map_io,
diff --git a/arch/arm/mach-orion5x/db88f5281-setup.c b/arch/arm/mach-orion5x/db88f5281-setup.c
index d318bea2af91..df1083f5b6eb 100644
--- a/arch/arm/mach-orion5x/db88f5281-setup.c
+++ b/arch/arm/mach-orion5x/db88f5281-setup.c
@@ -358,8 +358,6 @@ static void __init db88f5281_init(void)
MACHINE_START(DB88F5281, "Marvell Orion-2 Development Board")
/* Maintainer: Tzachi Perelstein <tzachi@marvell.com> */
- .phys_io = ORION5X_REGS_PHYS_BASE,
- .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = 0x00000100,
.init_machine = db88f5281_init,
.map_io = orion5x_map_io,
diff --git a/arch/arm/mach-orion5x/dns323-setup.c b/arch/arm/mach-orion5x/dns323-setup.c
index a47100d46a4e..3a7bc0e36982 100644
--- a/arch/arm/mach-orion5x/dns323-setup.c
+++ b/arch/arm/mach-orion5x/dns323-setup.c
@@ -730,8 +730,6 @@ static void __init dns323_init(void)
/* Warning: D-Link uses a wrong mach-type (=526) in their bootloader */
MACHINE_START(DNS323, "D-Link DNS-323")
/* Maintainer: Herbert Valerio Riedel <hvr@gnu.org> */
- .phys_io = ORION5X_REGS_PHYS_BASE,
- .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
.boot_params = 0x00000100,
.init_machine = dns323_init,
.map_io = orion5x_map_io,
diff --git a/arch/arm/mach-orion5x/edmini_v2-setup.c b/arch/arm/mach-orion5x/edmini_v2-setup.c
index b24ee0c2cd61..ba98459f44b0 100644
--- a/arch/arm/mach-orion5x/edmini_v2-setup.c
+++ b/arch/arm/mach-orion5x/edmini_v2-setup.c
@@ -251,8 +251,6 @@ static void __init edmini_v2_init(void)
/* Warning: LaCie use a wrong mach-type (0x20e=526) in their bootloader. */
MACHINE_START(EDMINI_V2, "LaCie Ethernet Disk mini V2")
/* Maintainer: Christopher Moore <moore@free.fr> */
- .phys_io = ORION5X_REGS_PHYS_BASE,
- .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
.boot_params = 0x00000100,
.init_machine = edmini_v2_init,
.map_io = orion5x_map_io,
diff --git a/arch/arm/mach-orion5x/include/mach/debug-macro.S b/arch/arm/mach-orion5x/include/mach/debug-macro.S
index 91e0e39bb23f..5e3bf5b68aec 100644
--- a/arch/arm/mach-orion5x/include/mach/debug-macro.S
+++ b/arch/arm/mach-orion5x/include/mach/debug-macro.S
@@ -10,12 +10,11 @@
#include <mach/orion5x.h>
- .macro addruart, rx, tmp
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ MMU enabled?
- ldreq \rx, =ORION5X_REGS_PHYS_BASE
- ldrne \rx, =ORION5X_REGS_VIRT_BASE
- orr \rx, \rx, #0x00012000
+ .macro addruart, rp, rv
+ ldr \rp, =ORION5X_REGS_PHYS_BASE
+ ldr \rv, =ORION5X_REGS_VIRT_BASE
+ orr \rp, \rp, #0x00012000
+ orr \rv, \rv, #0x00012000
.endm
#define UART_SHIFT 2
diff --git a/arch/arm/mach-orion5x/kurobox_pro-setup.c b/arch/arm/mach-orion5x/kurobox_pro-setup.c
index dfbb68df7b09..4be9aa08de69 100644
--- a/arch/arm/mach-orion5x/kurobox_pro-setup.c
+++ b/arch/arm/mach-orion5x/kurobox_pro-setup.c
@@ -379,8 +379,6 @@ static void __init kurobox_pro_init(void)
#ifdef CONFIG_MACH_KUROBOX_PRO
MACHINE_START(KUROBOX_PRO, "Buffalo/Revogear Kurobox Pro")
/* Maintainer: Ronen Shitrit <rshitrit@marvell.com> */
- .phys_io = ORION5X_REGS_PHYS_BASE,
- .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
.boot_params = 0x00000100,
.init_machine = kurobox_pro_init,
.map_io = orion5x_map_io,
@@ -393,8 +391,6 @@ MACHINE_END
#ifdef CONFIG_MACH_LINKSTATION_PRO
MACHINE_START(LINKSTATION_PRO, "Buffalo Linkstation Pro/Live")
/* Maintainer: Byron Bradley <byron.bbradley@gmail.com> */
- .phys_io = ORION5X_REGS_PHYS_BASE,
- .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
.boot_params = 0x00000100,
.init_machine = kurobox_pro_init,
.map_io = orion5x_map_io,
diff --git a/arch/arm/mach-orion5x/ls_hgl-setup.c b/arch/arm/mach-orion5x/ls_hgl-setup.c
index 8e569be6e2c7..437364b7168e 100644
--- a/arch/arm/mach-orion5x/ls_hgl-setup.c
+++ b/arch/arm/mach-orion5x/ls_hgl-setup.c
@@ -265,8 +265,6 @@ static void __init ls_hgl_init(void)
MACHINE_START(LINKSTATION_LS_HGL, "Buffalo Linkstation LS-HGL")
/* Maintainer: Zhu Qingsen <zhuqs@cn.fujistu.com> */
- .phys_io = ORION5X_REGS_PHYS_BASE,
- .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
.boot_params = 0x00000100,
.init_machine = ls_hgl_init,
.map_io = orion5x_map_io,
diff --git a/arch/arm/mach-orion5x/lsmini-setup.c b/arch/arm/mach-orion5x/lsmini-setup.c
index c704f056de1e..ab9b0cf0a90b 100644
--- a/arch/arm/mach-orion5x/lsmini-setup.c
+++ b/arch/arm/mach-orion5x/lsmini-setup.c
@@ -267,8 +267,6 @@ static void __init lsmini_init(void)
#ifdef CONFIG_MACH_LINKSTATION_MINI
MACHINE_START(LINKSTATION_MINI, "Buffalo Linkstation Mini")
/* Maintainer: Alexey Kopytko <alexey@kopytko.ru> */
- .phys_io = ORION5X_REGS_PHYS_BASE,
- .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
.boot_params = 0x00000100,
.init_machine = lsmini_init,
.map_io = orion5x_map_io,
diff --git a/arch/arm/mach-orion5x/mss2-setup.c b/arch/arm/mach-orion5x/mss2-setup.c
index 61c086b66723..2f0e16cd7e81 100644
--- a/arch/arm/mach-orion5x/mss2-setup.c
+++ b/arch/arm/mach-orion5x/mss2-setup.c
@@ -261,8 +261,6 @@ static void __init mss2_init(void)
MACHINE_START(MSS2, "Maxtor Shared Storage II")
/* Maintainer: Sylver Bruneau <sylver.bruneau@googlemail.com> */
- .phys_io = ORION5X_REGS_PHYS_BASE,
- .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
.boot_params = 0x00000100,
.init_machine = mss2_init,
.map_io = orion5x_map_io,
diff --git a/arch/arm/mach-orion5x/mv2120-setup.c b/arch/arm/mach-orion5x/mv2120-setup.c
index 97c9ccb2ac60..b3d90f25de9f 100644
--- a/arch/arm/mach-orion5x/mv2120-setup.c
+++ b/arch/arm/mach-orion5x/mv2120-setup.c
@@ -229,8 +229,6 @@ static void __init mv2120_init(void)
/* Warning: HP uses a wrong mach-type (=526) in their bootloader */
MACHINE_START(MV2120, "HP Media Vault mv2120")
/* Maintainer: Martin Michlmayr <tbm@cyrius.com> */
- .phys_io = ORION5X_REGS_PHYS_BASE,
- .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
.boot_params = 0x00000100,
.init_machine = mv2120_init,
.map_io = orion5x_map_io,
diff --git a/arch/arm/mach-orion5x/net2big-setup.c b/arch/arm/mach-orion5x/net2big-setup.c
index 7bd6283476f9..d6665b31665f 100644
--- a/arch/arm/mach-orion5x/net2big-setup.c
+++ b/arch/arm/mach-orion5x/net2big-setup.c
@@ -419,8 +419,6 @@ static void __init net2big_init(void)
/* Warning: LaCie use a wrong mach-type (0x20e=526) in their bootloader. */
MACHINE_START(NET2BIG, "LaCie 2Big Network")
- .phys_io = ORION5X_REGS_PHYS_BASE,
- .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
.boot_params = 0x00000100,
.init_machine = net2big_init,
.map_io = orion5x_map_io,
diff --git a/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c b/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c
index 9c1ca41730ba..f4c26fd731f4 100644
--- a/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c
+++ b/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c
@@ -169,8 +169,6 @@ subsys_initcall(rd88f5181l_fxo_pci_init);
MACHINE_START(RD88F5181L_FXO, "Marvell Orion-VoIP FXO Reference Design")
/* Maintainer: Nicolas Pitre <nico@marvell.com> */
- .phys_io = ORION5X_REGS_PHYS_BASE,
- .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
.boot_params = 0x00000100,
.init_machine = rd88f5181l_fxo_init,
.map_io = orion5x_map_io,
diff --git a/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c b/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c
index ee1399ff0ced..b5942909bab0 100644
--- a/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c
+++ b/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c
@@ -181,8 +181,6 @@ subsys_initcall(rd88f5181l_ge_pci_init);
MACHINE_START(RD88F5181L_GE, "Marvell Orion-VoIP GE Reference Design")
/* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */
- .phys_io = ORION5X_REGS_PHYS_BASE,
- .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
.boot_params = 0x00000100,
.init_machine = rd88f5181l_ge_init,
.map_io = orion5x_map_io,
diff --git a/arch/arm/mach-orion5x/rd88f5182-setup.c b/arch/arm/mach-orion5x/rd88f5182-setup.c
index a04f9e4b633a..165ed87029b2 100644
--- a/arch/arm/mach-orion5x/rd88f5182-setup.c
+++ b/arch/arm/mach-orion5x/rd88f5182-setup.c
@@ -305,8 +305,6 @@ static void __init rd88f5182_init(void)
MACHINE_START(RD88F5182, "Marvell Orion-NAS Reference Design")
/* Maintainer: Ronen Shitrit <rshitrit@marvell.com> */
- .phys_io = ORION5X_REGS_PHYS_BASE,
- .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
.boot_params = 0x00000100,
.init_machine = rd88f5182_init,
.map_io = orion5x_map_io,
diff --git a/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c b/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c
index 7737cf9a8f50..02ff45f3e2e3 100644
--- a/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c
+++ b/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c
@@ -123,8 +123,6 @@ subsys_initcall(rd88f6183ap_ge_pci_init);
MACHINE_START(RD88F6183AP_GE, "Marvell Orion-1-90 AP GE Reference Design")
/* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */
- .phys_io = ORION5X_REGS_PHYS_BASE,
- .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
.boot_params = 0x00000100,
.init_machine = rd88f6183ap_ge_init,
.map_io = orion5x_map_io,
diff --git a/arch/arm/mach-orion5x/terastation_pro2-setup.c b/arch/arm/mach-orion5x/terastation_pro2-setup.c
index 0b101d7d41c2..4403fae5ab0e 100644
--- a/arch/arm/mach-orion5x/terastation_pro2-setup.c
+++ b/arch/arm/mach-orion5x/terastation_pro2-setup.c
@@ -358,8 +358,6 @@ static void __init tsp2_init(void)
MACHINE_START(TERASTATION_PRO2, "Buffalo Terastation Pro II/Live")
/* Maintainer: Sylver Bruneau <sylver.bruneau@googlemail.com> */
- .phys_io = ORION5X_REGS_PHYS_BASE,
- .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
.boot_params = 0x00000100,
.init_machine = tsp2_init,
.map_io = orion5x_map_io,
diff --git a/arch/arm/mach-orion5x/ts209-setup.c b/arch/arm/mach-orion5x/ts209-setup.c
index 9d6890514199..1e196129d763 100644
--- a/arch/arm/mach-orion5x/ts209-setup.c
+++ b/arch/arm/mach-orion5x/ts209-setup.c
@@ -322,8 +322,6 @@ static void __init qnap_ts209_init(void)
MACHINE_START(TS209, "QNAP TS-109/TS-209")
/* Maintainer: Byron Bradley <byron.bbradley@gmail.com> */
- .phys_io = ORION5X_REGS_PHYS_BASE,
- .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
.boot_params = 0x00000100,
.init_machine = qnap_ts209_init,
.map_io = orion5x_map_io,
diff --git a/arch/arm/mach-orion5x/ts409-setup.c b/arch/arm/mach-orion5x/ts409-setup.c
index d85588ac7ef8..428af2046e36 100644
--- a/arch/arm/mach-orion5x/ts409-setup.c
+++ b/arch/arm/mach-orion5x/ts409-setup.c
@@ -311,8 +311,6 @@ static void __init qnap_ts409_init(void)
MACHINE_START(TS409, "QNAP TS-409")
/* Maintainer: Sylver Bruneau <sylver.bruneau@gmail.com> */
- .phys_io = ORION5X_REGS_PHYS_BASE,
- .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
.boot_params = 0x00000100,
.init_machine = qnap_ts409_init,
.map_io = orion5x_map_io,
diff --git a/arch/arm/mach-orion5x/ts78xx-setup.c b/arch/arm/mach-orion5x/ts78xx-setup.c
index 696b1a97f9e2..16f1bd5324be 100644
--- a/arch/arm/mach-orion5x/ts78xx-setup.c
+++ b/arch/arm/mach-orion5x/ts78xx-setup.c
@@ -550,8 +550,6 @@ static void __init ts78xx_init(void)
MACHINE_START(TS78XX, "Technologic Systems TS-78xx SBC")
/* Maintainer: Alexander Clouter <alex@digriz.org.uk> */
- .phys_io = ORION5X_REGS_PHYS_BASE,
- .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
.boot_params = 0x00000100,
.init_machine = ts78xx_init,
.map_io = ts78xx_map_io,
diff --git a/arch/arm/mach-orion5x/wnr854t-setup.c b/arch/arm/mach-orion5x/wnr854t-setup.c
index 69208217b220..7994d6ec08a8 100644
--- a/arch/arm/mach-orion5x/wnr854t-setup.c
+++ b/arch/arm/mach-orion5x/wnr854t-setup.c
@@ -172,8 +172,6 @@ subsys_initcall(wnr854t_pci_init);
MACHINE_START(WNR854T, "Netgear WNR854T")
/* Maintainer: Imre Kaloz <kaloz@openwrt.org> */
- .phys_io = ORION5X_REGS_PHYS_BASE,
- .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
.boot_params = 0x00000100,
.init_machine = wnr854t_init,
.map_io = orion5x_map_io,
diff --git a/arch/arm/mach-orion5x/wrt350n-v2-setup.c b/arch/arm/mach-orion5x/wrt350n-v2-setup.c
index f9f222ebb7ed..a5989b7eb53e 100644
--- a/arch/arm/mach-orion5x/wrt350n-v2-setup.c
+++ b/arch/arm/mach-orion5x/wrt350n-v2-setup.c
@@ -260,8 +260,6 @@ subsys_initcall(wrt350n_v2_pci_init);
MACHINE_START(WRT350N_V2, "Linksys WRT350N v2")
/* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */
- .phys_io = ORION5X_REGS_PHYS_BASE,
- .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
.boot_params = 0x00000100,
.init_machine = wrt350n_v2_init,
.map_io = orion5x_map_io,
diff --git a/arch/arm/mach-pnx4008/core.c b/arch/arm/mach-pnx4008/core.c
index 45734bb880a8..63399755f199 100644
--- a/arch/arm/mach-pnx4008/core.c
+++ b/arch/arm/mach-pnx4008/core.c
@@ -264,8 +264,6 @@ extern struct sys_timer pnx4008_timer;
MACHINE_START(PNX4008, "Philips PNX4008")
/* Maintainer: MontaVista Software Inc. */
- .phys_io = 0x40090000,
- .io_pg_offst = (0xf4090000 >> 18) & 0xfffc,
.boot_params = 0x80000100,
.map_io = pnx4008_map_io,
.init_irq = pnx4008_init_irq,
diff --git a/arch/arm/mach-pnx4008/include/mach/debug-macro.S b/arch/arm/mach-pnx4008/include/mach/debug-macro.S
index 6ca8bd30bf46..931afebaf064 100644
--- a/arch/arm/mach-pnx4008/include/mach/debug-macro.S
+++ b/arch/arm/mach-pnx4008/include/mach/debug-macro.S
@@ -11,12 +11,10 @@
*
*/
- .macro addruart, rx, tmp
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ MMU enabled?
- mov \rx, #0x00090000
- addeq \rx, \rx, #0x40000000
- addne \rx, \rx, #0xf4000000
+ .macro addruart, rp, rv
+ mov \rp, #0x00090000
+ add \rv, \rp, #0xf4000000 @ virtual
+ add \rp, \rp, #0x40000000 @ physical
.endm
#define UART_SHIFT 2
diff --git a/arch/arm/mach-pnx4008/include/mach/vmalloc.h b/arch/arm/mach-pnx4008/include/mach/vmalloc.h
index 2ad398378aed..31b65ee07b0b 100644
--- a/arch/arm/mach-pnx4008/include/mach/vmalloc.h
+++ b/arch/arm/mach-pnx4008/include/mach/vmalloc.h
@@ -17,4 +17,4 @@
* The vmalloc() routines leaves a hole of 4kB between each vmalloced
* area for the same reason. ;)
*/
-#define VMALLOC_END (PAGE_OFFSET + 0x10000000)
+#define VMALLOC_END 0xd0000000
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 7aefb9074852..dd235ecc9d6c 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -8,19 +8,16 @@ config ARCH_LUBBOCK
bool "Intel DBPXA250 Development Platform (aka Lubbock)"
select PXA25x
select SA1111
- select PXA_HAVE_BOARD_IRQS
config MACH_MAINSTONE
bool "Intel HCDDBBVA0 Development Platform (aka Mainstone)"
select PXA27x
select HAVE_PWM
- select PXA_HAVE_BOARD_IRQS
config MACH_ZYLONITE
bool
select PXA3xx
select HAVE_PWM
- select PXA_HAVE_BOARD_IRQS
config MACH_ZYLONITE300
bool "PXA3xx Development Platform (aka Zylonite) PXA300/310"
@@ -44,6 +41,10 @@ config MACH_TAVOREVB
select PXA3xx
select CPU_PXA930
+config MACH_TAVOREVB3
+ bool "PXA95x Development Platform (aka TavorEVB III)"
+ select CPU_PXA950
+
config MACH_SAAR
bool "PXA930 Handheld Platform (aka SAAR)"
select PXA3xx
@@ -61,7 +62,6 @@ config ARCH_VIPER
select ISA
select I2C_GPIO
select HAVE_PWM
- select PXA_HAVE_BOARD_IRQS
select PXA_HAVE_ISA_IRQS
select ARCOM_PCMCIA
@@ -69,7 +69,6 @@ config MACH_ARCOM_ZEUS
bool "Arcom/Eurotech ZEUS SBC"
select PXA27x
select ISA
- select PXA_HAVE_BOARD_IRQS
select PXA_HAVE_ISA_IRQS
select ARCOM_PCMCIA
@@ -77,7 +76,6 @@ config MACH_BALLOON3
bool "Balloon 3 board"
select PXA27x
select IWMMXT
- select PXA_HAVE_BOARD_IRQS
config MACH_CSB726
bool "Enable Cogent CSB726 System On a Module"
@@ -140,13 +138,11 @@ config MACH_INTELMOTE2
bool "Intel Mote 2 Platform"
select PXA27x
select IWMMXT
- select PXA_HAVE_BOARD_IRQS
config MACH_STARGATE2
bool "Intel Stargate 2 Platform"
select PXA27x
select IWMMXT
- select PXA_HAVE_BOARD_IRQS
config MACH_XCEP
bool "Iskratel Electronics XCEP"
@@ -206,13 +202,11 @@ config MACH_LOGICPD_PXA270
bool "LogicPD PXA270 Card Engine Development Platform"
select PXA27x
select HAVE_PWM
- select PXA_HAVE_BOARD_IRQS
config MACH_PCM027
bool "Phytec phyCORE-PXA270 CPU module (PCM-027)"
select PXA27x
select IWMMXT
- select PXA_HAVE_BOARD_IRQS
config MACH_PCM990_BASEBOARD
bool "PHYTEC PCM-990 development board"
@@ -247,7 +241,6 @@ config MACH_COLIBRI_PXA270_INCOME
depends on MACH_COLIBRI
select PXA27x
select HAVE_PWM
- select PXA_HAVE_BOARD_IRQS
config MACH_COLIBRI300
bool "Toradex Colibri PXA300/310"
@@ -274,7 +267,6 @@ config MACH_H4700
select PXA27x
select IWMMXT
select HAVE_PWM
- select PXA_HAVE_BOARD_IRQS
config MACH_H5000
bool "HP iPAQ h5000"
@@ -289,7 +281,6 @@ config MACH_MAGICIAN
select PXA27x
select IWMMXT
select HAVE_PWM
- select PXA_HAVE_BOARD_IRQS
config MACH_MIOA701
bool "Mitac Mio A701 Support"
@@ -307,7 +298,6 @@ config PXA_EZX
select PXA27x
select IWMMXT
select HAVE_PWM
- select PXA_HAVE_BOARD_IRQS
config MACH_EZX_A780
bool "Motorola EZX A780"
@@ -478,7 +468,6 @@ config MACH_POODLE
depends on PXA_SHARPSL
select PXA25x
select SHARP_LOCOMO
- select PXA_HAVE_BOARD_IRQS
config MACH_CORGI
bool "Enable Sharp SL-C700 (Corgi) Support"
@@ -523,7 +512,6 @@ config MACH_TOSA
bool "Enable Sharp SL-6000x (Tosa) Support"
depends on PXA_SHARPSL
select PXA25x
- select PXA_HAVE_BOARD_IRQS
config TOSA_BT
tristate "Control the state of built-in bluetooth chip on Sharp SL-6000"
@@ -552,7 +540,6 @@ config MACH_ICONTROL
config ARCH_PXA_ESERIES
bool "PXA based Toshiba e-series PDAs"
select PXA25x
- select PXA_HAVE_BOARD_IRQS
config MACH_E330
bool "Toshiba e330"
@@ -606,7 +593,6 @@ config MACH_ZIPIT2
bool "Zipit Z2 Handheld"
select PXA27x
select HAVE_PWM
- select PXA_HAVE_BOARD_IRQS
endmenu
@@ -643,6 +629,7 @@ config CPU_PXA300
config CPU_PXA310
bool
select CPU_PXA300
+ select PXA310_ULPI if USB_ULPI
help
PXA310 (codename Monahans-LV)
@@ -692,10 +679,10 @@ config SHARPSL_PM_MAX1111
select HWMON
select SENSORS_MAX1111
-config PXA_HAVE_BOARD_IRQS
+config PXA_HAVE_ISA_IRQS
bool
-config PXA_HAVE_ISA_IRQS
+config PXA310_ULPI
bool
endif
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index 85c7fb324dbb..e2f89c2c6f49 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -18,7 +18,7 @@ endif
# SoC-specific code
obj-$(CONFIG_PXA25x) += mfp-pxa2xx.o pxa2xx.o pxa25x.o
obj-$(CONFIG_PXA27x) += mfp-pxa2xx.o pxa2xx.o pxa27x.o
-obj-$(CONFIG_PXA3xx) += mfp-pxa3xx.o pxa3xx.o smemc.o
+obj-$(CONFIG_PXA3xx) += mfp-pxa3xx.o pxa3xx.o smemc.o pxa3xx-ulpi.o
obj-$(CONFIG_CPU_PXA300) += pxa300.o
obj-$(CONFIG_CPU_PXA320) += pxa320.o
obj-$(CONFIG_CPU_PXA930) += pxa930.o
@@ -32,6 +32,7 @@ obj-$(CONFIG_MACH_ZYLONITE300) += zylonite.o zylonite_pxa300.o
obj-$(CONFIG_MACH_ZYLONITE320) += zylonite.o zylonite_pxa320.o
obj-$(CONFIG_MACH_LITTLETON) += littleton.o
obj-$(CONFIG_MACH_TAVOREVB) += tavorevb.o
+obj-$(CONFIG_MACH_TAVOREVB3) += tavorevb3.o
obj-$(CONFIG_MACH_SAAR) += saar.o
# 3rd Party Dev Platforms
diff --git a/arch/arm/mach-pxa/balloon3.c b/arch/arm/mach-pxa/balloon3.c
index 9041340fee1d..21e188901935 100644
--- a/arch/arm/mach-pxa/balloon3.c
+++ b/arch/arm/mach-pxa/balloon3.c
@@ -68,42 +68,6 @@ static unsigned long balloon3_pin_config[] __initdata = {
/* Reset, configured as GPIO wakeup source */
GPIO1_GPIO | WAKEUP_ON_EDGE_BOTH,
-
- /* LEDs */
- GPIO9_GPIO, /* NAND activity LED */
- GPIO10_GPIO, /* Heartbeat LED */
-
- /* AC97 */
- GPIO28_AC97_BITCLK,
- GPIO29_AC97_SDATA_IN_0,
- GPIO30_AC97_SDATA_OUT,
- GPIO31_AC97_SYNC,
- GPIO113_AC97_nRESET,
- GPIO95_GPIO,
-
- /* MMC */
- GPIO32_MMC_CLK,
- GPIO92_MMC_DAT_0,
- GPIO109_MMC_DAT_1,
- GPIO110_MMC_DAT_2,
- GPIO111_MMC_DAT_3,
- GPIO112_MMC_CMD,
-
- /* USB Host */
- GPIO88_USBH1_PWR,
- GPIO89_USBH1_PEN,
-
- /* PC Card */
- GPIO48_nPOE,
- GPIO49_nPWE,
- GPIO50_nPIOR,
- GPIO51_nPIOW,
- GPIO85_nPCE_1,
- GPIO54_nPCE_2,
- GPIO79_PSKTSEL,
- GPIO55_nPREG,
- GPIO56_nPWAIT,
- GPIO57_nIOIS16,
};
/******************************************************************************
@@ -132,6 +96,34 @@ int __init parse_balloon3_features(char *arg)
early_param("balloon3_features", parse_balloon3_features);
/******************************************************************************
+ * Compact Flash slot
+ ******************************************************************************/
+#if defined(CONFIG_PCMCIA_PXA2XX) || defined(CONFIG_PCMCIA_PXA2XX_MODULE)
+static unsigned long balloon3_cf_pin_config[] __initdata = {
+ GPIO48_nPOE,
+ GPIO49_nPWE,
+ GPIO50_nPIOR,
+ GPIO51_nPIOW,
+ GPIO85_nPCE_1,
+ GPIO54_nPCE_2,
+ GPIO79_PSKTSEL,
+ GPIO55_nPREG,
+ GPIO56_nPWAIT,
+ GPIO57_nIOIS16,
+};
+
+static void __init balloon3_cf_init(void)
+{
+ if (!balloon3_has(BALLOON3_FEATURE_CF))
+ return;
+
+ pxa2xx_mfp_config(ARRAY_AND_SIZE(balloon3_cf_pin_config));
+}
+#else
+static inline void balloon3_cf_init(void) {}
+#endif
+
+/******************************************************************************
* NOR Flash
******************************************************************************/
#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
@@ -179,6 +171,15 @@ static inline void balloon3_nor_init(void) {}
******************************************************************************/
#if defined(CONFIG_TOUCHSCREEN_UCB1400) || \
defined(CONFIG_TOUCHSCREEN_UCB1400_MODULE)
+static unsigned long balloon3_ac97_pin_config[] __initdata = {
+ GPIO28_AC97_BITCLK,
+ GPIO29_AC97_SDATA_IN_0,
+ GPIO30_AC97_SDATA_OUT,
+ GPIO31_AC97_SYNC,
+ GPIO113_AC97_nRESET,
+ GPIO95_GPIO,
+};
+
static struct ucb1400_pdata vpac270_ucb1400_pdata = {
.irq = IRQ_GPIO(BALLOON3_GPIO_CODEC_IRQ),
};
@@ -197,6 +198,7 @@ static void __init balloon3_ts_init(void)
if (!balloon3_has(BALLOON3_FEATURE_AUDIO))
return;
+ pxa2xx_mfp_config(ARRAY_AND_SIZE(balloon3_ac97_pin_config));
pxa_set_ac97_info(NULL);
platform_device_register(&balloon3_ucb1400_device);
}
@@ -208,6 +210,11 @@ static inline void balloon3_ts_init(void) {}
* Framebuffer
******************************************************************************/
#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
+static unsigned long balloon3_lcd_pin_config[] __initdata = {
+ GPIOxx_LCD_TFT_16BPP,
+ GPIO99_GPIO,
+};
+
static struct pxafb_mode_info balloon3_lcd_modes[] = {
{
.pixclock = 38000,
@@ -242,6 +249,8 @@ static void __init balloon3_lcd_init(void)
if (!balloon3_has(BALLOON3_FEATURE_TOPPOLY))
return;
+ pxa2xx_mfp_config(ARRAY_AND_SIZE(balloon3_lcd_pin_config));
+
ret = gpio_request(BALLOON3_GPIO_RUN_BACKLIGHT, "BKL-ON");
if (ret) {
pr_err("Requesting BKL-ON GPIO failed!\n");
@@ -271,6 +280,15 @@ static inline void balloon3_lcd_init(void) {}
* SD/MMC card controller
******************************************************************************/
#if defined(CONFIG_MMC_PXA) || defined(CONFIG_MMC_PXA_MODULE)
+static unsigned long balloon3_mmc_pin_config[] __initdata = {
+ GPIO32_MMC_CLK,
+ GPIO92_MMC_DAT_0,
+ GPIO109_MMC_DAT_1,
+ GPIO110_MMC_DAT_2,
+ GPIO111_MMC_DAT_3,
+ GPIO112_MMC_CMD,
+};
+
static struct pxamci_platform_data balloon3_mci_platform_data = {
.ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34,
.gpio_card_detect = -1,
@@ -281,6 +299,7 @@ static struct pxamci_platform_data balloon3_mci_platform_data = {
static void __init balloon3_mmc_init(void)
{
+ pxa2xx_mfp_config(ARRAY_AND_SIZE(balloon3_mmc_pin_config));
pxa_set_mci_info(&balloon3_mci_platform_data);
}
#else
@@ -339,6 +358,11 @@ static inline void balloon3_irda_init(void) {}
* USB Host
******************************************************************************/
#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+static unsigned long balloon3_uhc_pin_config[] __initdata = {
+ GPIO88_USBH1_PWR,
+ GPIO89_USBH1_PEN,
+};
+
static struct pxaohci_platform_data balloon3_ohci_info = {
.port_mode = PMM_PERPORT_MODE,
.flags = ENABLE_PORT_ALL | POWER_CONTROL_LOW | POWER_SENSE_LOW,
@@ -348,6 +372,7 @@ static void __init balloon3_uhc_init(void)
{
if (!balloon3_has(BALLOON3_FEATURE_OHCI))
return;
+ pxa2xx_mfp_config(ARRAY_AND_SIZE(balloon3_uhc_pin_config));
pxa_set_ohci_info(&balloon3_ohci_info);
}
#else
@@ -358,6 +383,11 @@ static inline void balloon3_uhc_init(void) {}
* LEDs
******************************************************************************/
#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
+static unsigned long balloon3_led_pin_config[] __initdata = {
+ GPIO9_GPIO, /* NAND activity LED */
+ GPIO10_GPIO, /* Heartbeat LED */
+};
+
struct gpio_led balloon3_gpio_leds[] = {
{
.name = "balloon3:green:idle",
@@ -436,6 +466,7 @@ static struct platform_device balloon3_pcf_leds = {
static void __init balloon3_leds_init(void)
{
+ pxa2xx_mfp_config(ARRAY_AND_SIZE(balloon3_led_pin_config));
platform_device_register(&balloon3_leds);
platform_device_register(&balloon3_pcf_leds);
}
@@ -757,6 +788,7 @@ static void __init balloon3_init(void)
balloon3_ts_init();
balloon3_udc_init();
balloon3_uhc_init();
+ balloon3_cf_init();
}
static struct map_desc balloon3_io_desc[] __initdata = {
@@ -776,9 +808,8 @@ static void __init balloon3_map_io(void)
MACHINE_START(BALLOON3, "Balloon3")
/* Maintainer: Nick Bane. */
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.map_io = balloon3_map_io,
+ .nr_irqs = BALLOON3_NR_IRQS,
.init_irq = balloon3_init_irq,
.timer = &pxa_timer,
.init_machine = balloon3_init,
diff --git a/arch/arm/mach-pxa/capc7117.c b/arch/arm/mach-pxa/capc7117.c
index aae544631a8b..4bd7a3cda48c 100644
--- a/arch/arm/mach-pxa/capc7117.c
+++ b/arch/arm/mach-pxa/capc7117.c
@@ -148,9 +148,7 @@ static void __init capc7117_init(void)
MACHINE_START(CAPC7117,
"Embedian CAPC-7117 evaluation kit based on the MXM-8x10 CoM")
- .phys_io = 0x40000000,
.boot_params = 0xa0000100,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.map_io = pxa_map_io,
.init_irq = pxa3xx_init_irq,
.timer = &pxa_timer,
diff --git a/arch/arm/mach-pxa/cm-x2xx.c b/arch/arm/mach-pxa/cm-x2xx.c
index bff6e78f033d..ac5598ce9724 100644
--- a/arch/arm/mach-pxa/cm-x2xx.c
+++ b/arch/arm/mach-pxa/cm-x2xx.c
@@ -33,6 +33,9 @@
extern void cmx255_init(void);
extern void cmx270_init(void);
+/* reserve IRQs for IT8152 */
+#define CMX2XX_NR_IRQS (IRQ_BOARD_START + 40)
+
/* virtual addresses for statically mapped regions */
#define CMX2XX_VIRT_BASE (0xe8000000)
#define CMX2XX_IT8152_VIRT (CMX2XX_VIRT_BASE)
@@ -511,9 +514,8 @@ static void __init cmx2xx_map_io(void)
MACHINE_START(ARMCORE, "Compulab CM-X2XX")
.boot_params = 0xa0000100,
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.map_io = cmx2xx_map_io,
+ .nr_irqs = CMX2XX_NR_IRQS,
.init_irq = cmx2xx_init_irq,
.timer = &pxa_timer,
.init_machine = cmx2xx_init,
diff --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c
index c70e6c2f4e7c..922b1075b9de 100644
--- a/arch/arm/mach-pxa/cm-x300.c
+++ b/arch/arm/mach-pxa/cm-x300.c
@@ -19,6 +19,7 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
+#include <linux/clk.h>
#include <linux/gpio.h>
#include <linux/dm9000.h>
@@ -50,6 +51,7 @@
#include <plat/i2c.h>
#include <plat/pxa3xx_nand.h>
#include <mach/audio.h>
+#include <mach/pxa3xx-u2d.h>
#include <asm/mach/map.h>
@@ -68,6 +70,8 @@
#define GPIO97_RTC_RD (97)
#define GPIO98_RTC_IO (98)
+#define GPIO_ULPI_PHY_RST (127)
+
static mfp_cfg_t cm_x3xx_mfp_cfg[] __initdata = {
/* LCD */
GPIO54_LCD_LDD_0,
@@ -472,6 +476,78 @@ static void __init cm_x300_init_mmc(void)
static inline void cm_x300_init_mmc(void) {}
#endif
+#if defined(CONFIG_PXA310_ULPI)
+static struct clk *pout_clk;
+
+static int cm_x300_ulpi_phy_reset(void)
+{
+ int err;
+
+ /* reset the PHY */
+ err = gpio_request(GPIO_ULPI_PHY_RST, "ulpi reset");
+ if (err) {
+ pr_err("%s: failed to request ULPI reset GPIO: %d\n",
+ __func__, err);
+ return err;
+ }
+
+ gpio_direction_output(GPIO_ULPI_PHY_RST, 0);
+ msleep(10);
+ gpio_set_value(GPIO_ULPI_PHY_RST, 1);
+ msleep(10);
+
+ gpio_free(GPIO_ULPI_PHY_RST);
+
+ return 0;
+}
+
+static inline int cm_x300_u2d_init(struct device *dev)
+{
+ int err = 0;
+
+ if (cpu_is_pxa310()) {
+ /* CLK_POUT is connected to the ULPI PHY */
+ pout_clk = clk_get(NULL, "CLK_POUT");
+ if (IS_ERR(pout_clk)) {
+ err = PTR_ERR(pout_clk);
+ pr_err("%s: failed to get CLK_POUT: %d\n",
+ __func__, err);
+ return err;
+ }
+ clk_enable(pout_clk);
+
+ err = cm_x300_ulpi_phy_reset();
+ if (err) {
+ clk_disable(pout_clk);
+ clk_put(pout_clk);
+ }
+ }
+
+ return err;
+}
+
+static void cm_x300_u2d_exit(struct device *dev)
+{
+ if (cpu_is_pxa310()) {
+ clk_disable(pout_clk);
+ clk_put(pout_clk);
+ }
+}
+
+static struct pxa3xx_u2d_platform_data cm_x300_u2d_platform_data = {
+ .ulpi_mode = ULPI_SER_6PIN,
+ .init = cm_x300_u2d_init,
+ .exit = cm_x300_u2d_exit,
+};
+
+static void cm_x300_init_u2d(void)
+{
+ pxa3xx_set_u2d_info(&cm_x300_u2d_platform_data);
+}
+#else
+static inline void cm_x300_init_u2d(void) {}
+#endif
+
#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
static int cm_x300_ohci_init(struct device *dev)
{
@@ -754,6 +830,7 @@ static void __init cm_x300_init(void)
cm_x300_init_da9030();
cm_x300_init_dm9000();
cm_x300_init_lcd();
+ cm_x300_init_u2d();
cm_x300_init_ohci();
cm_x300_init_mmc();
cm_x300_init_nand();
@@ -779,9 +856,7 @@ static void __init cm_x300_fixup(struct machine_desc *mdesc, struct tag *tags,
}
MACHINE_START(CM_X300, "CM-X300 module")
- .phys_io = 0x40000000,
.boot_params = 0xa0000100,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.map_io = pxa_map_io,
.init_irq = pxa3xx_init_irq,
.timer = &pxa_timer,
diff --git a/arch/arm/mach-pxa/colibri-pxa270.c b/arch/arm/mach-pxa/colibri-pxa270.c
index 98673ac6efd0..bc045100ec15 100644
--- a/arch/arm/mach-pxa/colibri-pxa270.c
+++ b/arch/arm/mach-pxa/colibri-pxa270.c
@@ -207,8 +207,6 @@ static void __init colibri_pxa270_income_init(void)
}
MACHINE_START(COLIBRI, "Toradex Colibri PXA270")
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.boot_params = COLIBRI_SDRAM_BASE + 0x100,
.init_machine = colibri_pxa270_init,
.map_io = pxa_map_io,
@@ -217,8 +215,6 @@ MACHINE_START(COLIBRI, "Toradex Colibri PXA270")
MACHINE_END
MACHINE_START(INCOME, "Income s.r.o. SH-Dmaster PXA270 SBC")
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.boot_params = 0xa0000100,
.init_machine = colibri_pxa270_income_init,
.map_io = pxa_map_io,
diff --git a/arch/arm/mach-pxa/colibri-pxa300.c b/arch/arm/mach-pxa/colibri-pxa300.c
index 40b6ac2de876..a70b256591e6 100644
--- a/arch/arm/mach-pxa/colibri-pxa300.c
+++ b/arch/arm/mach-pxa/colibri-pxa300.c
@@ -186,8 +186,6 @@ void __init colibri_pxa300_init(void)
}
MACHINE_START(COLIBRI300, "Toradex Colibri PXA300")
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.boot_params = COLIBRI_SDRAM_BASE + 0x100,
.init_machine = colibri_pxa300_init,
.map_io = pxa_map_io,
diff --git a/arch/arm/mach-pxa/colibri-pxa320.c b/arch/arm/mach-pxa/colibri-pxa320.c
index 99e850d84710..ca5f29e2e9cd 100644
--- a/arch/arm/mach-pxa/colibri-pxa320.c
+++ b/arch/arm/mach-pxa/colibri-pxa320.c
@@ -255,8 +255,6 @@ void __init colibri_pxa320_init(void)
}
MACHINE_START(COLIBRI320, "Toradex Colibri PXA320")
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.boot_params = COLIBRI_SDRAM_BASE + 0x100,
.init_machine = colibri_pxa320_init,
.map_io = pxa_map_io,
diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c
index 3fb0fc099080..821229acabe6 100644
--- a/arch/arm/mach-pxa/corgi.c
+++ b/arch/arm/mach-pxa/corgi.c
@@ -720,8 +720,6 @@ static void __init fixup_corgi(struct machine_desc *desc,
#ifdef CONFIG_MACH_CORGI
MACHINE_START(CORGI, "SHARP Corgi")
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.fixup = fixup_corgi,
.map_io = pxa_map_io,
.init_irq = pxa25x_init_irq,
@@ -732,8 +730,6 @@ MACHINE_END
#ifdef CONFIG_MACH_SHEPHERD
MACHINE_START(SHEPHERD, "SHARP Shepherd")
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.fixup = fixup_corgi,
.map_io = pxa_map_io,
.init_irq = pxa25x_init_irq,
@@ -744,8 +740,6 @@ MACHINE_END
#ifdef CONFIG_MACH_HUSKY
MACHINE_START(HUSKY, "SHARP Husky")
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.fixup = fixup_corgi,
.map_io = pxa_map_io,
.init_irq = pxa25x_init_irq,
diff --git a/arch/arm/mach-pxa/cpufreq-pxa3xx.c b/arch/arm/mach-pxa/cpufreq-pxa3xx.c
index 0a0d0fe99220..88fbec05ec50 100644
--- a/arch/arm/mach-pxa/cpufreq-pxa3xx.c
+++ b/arch/arm/mach-pxa/cpufreq-pxa3xx.c
@@ -159,7 +159,7 @@ static int pxa3xx_cpufreq_verify(struct cpufreq_policy *policy)
static unsigned int pxa3xx_cpufreq_get(unsigned int cpu)
{
- return get_clk_frequency_khz(0);
+ return pxa3xx_get_clk_frequency_khz(0);
}
static int pxa3xx_cpufreq_set(struct cpufreq_policy *policy,
@@ -212,7 +212,8 @@ static int pxa3xx_cpufreq_init(struct cpufreq_policy *policy)
policy->cpuinfo.min_freq = 104000;
policy->cpuinfo.max_freq = (cpu_is_pxa320()) ? 806000 : 624000;
policy->cpuinfo.transition_latency = 1000; /* FIXME: 1 ms, assumed */
- policy->cur = policy->min = policy->max = get_clk_frequency_khz(0);
+ policy->max = pxa3xx_get_clk_frequency_khz(0);
+ policy->cur = policy->min = policy->max;
if (cpu_is_pxa300() || cpu_is_pxa310())
ret = setup_freqs_table(policy, ARRAY_AND_SIZE(pxa300_freqs));
diff --git a/arch/arm/mach-pxa/csb726.c b/arch/arm/mach-pxa/csb726.c
index 91fd4fea6a54..57cacaff194d 100644
--- a/arch/arm/mach-pxa/csb726.c
+++ b/arch/arm/mach-pxa/csb726.c
@@ -272,9 +272,7 @@ static void __init csb726_init(void)
}
MACHINE_START(CSB726, "Cogent CSB726")
- .phys_io = 0x40000000,
.boot_params = 0xa0000100,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.map_io = pxa_map_io,
.init_irq = pxa27x_init_irq,
.init_machine = csb726_init,
diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c
index 65447dc736c2..08b410343870 100644
--- a/arch/arm/mach-pxa/devices.c
+++ b/arch/arm/mach-pxa/devices.c
@@ -6,11 +6,12 @@
#include <asm/pmu.h>
#include <mach/udc.h>
+#include <mach/pxa3xx-u2d.h>
#include <mach/pxafb.h>
#include <mach/mmc.h>
#include <mach/irda.h>
#include <mach/ohci.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
#include <mach/pxa2xx_spi.h>
#include <mach/camera.h>
#include <mach/audio.h>
@@ -134,6 +135,33 @@ struct platform_device pxa27x_device_udc = {
}
};
+#ifdef CONFIG_PXA3xx
+static struct resource pxa3xx_u2d_resources[] = {
+ [0] = {
+ .start = 0x54100000,
+ .end = 0x54100fff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_USB2,
+ .end = IRQ_USB2,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device pxa3xx_device_u2d = {
+ .name = "pxa3xx-u2d",
+ .id = -1,
+ .resource = pxa3xx_u2d_resources,
+ .num_resources = ARRAY_SIZE(pxa3xx_u2d_resources),
+};
+
+void __init pxa3xx_set_u2d_info(struct pxa3xx_u2d_platform_data *info)
+{
+ pxa_register_device(&pxa3xx_device_u2d, info);
+}
+#endif /* CONFIG_PXA3xx */
+
static struct resource pxafb_resources[] = {
[0] = {
.start = 0x44000000,
diff --git a/arch/arm/mach-pxa/devices.h b/arch/arm/mach-pxa/devices.h
index 50353ea49ba4..715e8bd02e24 100644
--- a/arch/arm/mach-pxa/devices.h
+++ b/arch/arm/mach-pxa/devices.h
@@ -4,6 +4,7 @@ extern struct platform_device pxa3xx_device_mci2;
extern struct platform_device pxa3xx_device_mci3;
extern struct platform_device pxa25x_device_udc;
extern struct platform_device pxa27x_device_udc;
+extern struct platform_device pxa3xx_device_u2d;
extern struct platform_device pxa_device_fb;
extern struct platform_device pxa_device_ffuart;
extern struct platform_device pxa_device_btuart;
diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c
index 0517c17978f3..ab48bb81b570 100644
--- a/arch/arm/mach-pxa/em-x270.c
+++ b/arch/arm/mach-pxa/em-x270.c
@@ -43,7 +43,7 @@
#include <mach/pxafb.h>
#include <mach/ohci.h>
#include <mach/mmc.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
#include <plat/i2c.h>
#include <mach/camera.h>
#include <mach/pxa2xx_spi.h>
@@ -1301,8 +1301,6 @@ static void __init em_x270_init(void)
MACHINE_START(EM_X270, "Compulab EM-X270")
.boot_params = 0xa0000100,
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.map_io = pxa_map_io,
.init_irq = pxa27x_init_irq,
.timer = &pxa_timer,
@@ -1311,8 +1309,6 @@ MACHINE_END
MACHINE_START(EXEDA, "Compulab eXeda")
.boot_params = 0xa0000100,
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.map_io = pxa_map_io,
.init_irq = pxa27x_init_irq,
.timer = &pxa_timer,
diff --git a/arch/arm/mach-pxa/eseries.c b/arch/arm/mach-pxa/eseries.c
index 349212a1cbd3..b25690ccadc4 100644
--- a/arch/arm/mach-pxa/eseries.c
+++ b/arch/arm/mach-pxa/eseries.c
@@ -29,6 +29,7 @@
#include <mach/pxa25x.h>
#include <mach/eseries-gpio.h>
+#include <mach/eseries-irq.h>
#include <mach/audio.h>
#include <mach/pxafb.h>
#include <mach/udc.h>
@@ -179,10 +180,9 @@ static void __init e330_init(void)
MACHINE_START(E330, "Toshiba e330")
/* Maintainer: Ian Molton (spyro@f2s.com) */
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.boot_params = 0xa0000100,
.map_io = pxa_map_io,
+ .nr_irqs = ESERIES_NR_IRQS,
.init_irq = pxa25x_init_irq,
.fixup = eseries_fixup,
.init_machine = e330_init,
@@ -229,10 +229,9 @@ static void __init e350_init(void)
MACHINE_START(E350, "Toshiba e350")
/* Maintainer: Ian Molton (spyro@f2s.com) */
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.boot_params = 0xa0000100,
.map_io = pxa_map_io,
+ .nr_irqs = ESERIES_NR_IRQS,
.init_irq = pxa25x_init_irq,
.fixup = eseries_fixup,
.init_machine = e350_init,
@@ -352,10 +351,9 @@ static void __init e400_init(void)
MACHINE_START(E400, "Toshiba e400")
/* Maintainer: Ian Molton (spyro@f2s.com) */
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.boot_params = 0xa0000100,
.map_io = pxa_map_io,
+ .nr_irqs = ESERIES_NR_IRQS,
.init_irq = pxa25x_init_irq,
.fixup = eseries_fixup,
.init_machine = e400_init,
@@ -541,10 +539,9 @@ static void __init e740_init(void)
MACHINE_START(E740, "Toshiba e740")
/* Maintainer: Ian Molton (spyro@f2s.com) */
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.boot_params = 0xa0000100,
.map_io = pxa_map_io,
+ .nr_irqs = ESERIES_NR_IRQS,
.init_irq = pxa25x_init_irq,
.fixup = eseries_fixup,
.init_machine = e740_init,
@@ -733,10 +730,9 @@ static void __init e750_init(void)
MACHINE_START(E750, "Toshiba e750")
/* Maintainer: Ian Molton (spyro@f2s.com) */
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.boot_params = 0xa0000100,
.map_io = pxa_map_io,
+ .nr_irqs = ESERIES_NR_IRQS,
.init_irq = pxa25x_init_irq,
.fixup = eseries_fixup,
.init_machine = e750_init,
@@ -929,10 +925,9 @@ static void __init e800_init(void)
MACHINE_START(E800, "Toshiba e800")
/* Maintainer: Ian Molton (spyro@f2s.com) */
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.boot_params = 0xa0000100,
.map_io = pxa_map_io,
+ .nr_irqs = ESERIES_NR_IRQS,
.init_irq = pxa25x_init_irq,
.fixup = eseries_fixup,
.init_machine = e800_init,
diff --git a/arch/arm/mach-pxa/ezx.c b/arch/arm/mach-pxa/ezx.c
index 626c82b13970..80a9352d43f3 100644
--- a/arch/arm/mach-pxa/ezx.c
+++ b/arch/arm/mach-pxa/ezx.c
@@ -32,12 +32,14 @@
#include <mach/ohci.h>
#include <plat/i2c.h>
#include <mach/hardware.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
#include <mach/camera.h>
#include "devices.h"
#include "generic.h"
+#define EZX_NR_IRQS (IRQ_BOARD_START + 24)
+
#define GPIO12_A780_FLIP_LID 12
#define GPIO15_A1200_FLIP_LID 15
#define GPIO15_A910_FLIP_LID 15
@@ -796,10 +798,9 @@ static void __init a780_init(void)
}
MACHINE_START(EZX_A780, "Motorola EZX A780")
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.boot_params = 0xa0000100,
.map_io = pxa_map_io,
+ .nr_irqs = EZX_NR_IRQS,
.init_irq = pxa27x_init_irq,
.timer = &pxa_timer,
.init_machine = a780_init,
@@ -862,10 +863,9 @@ static void __init e680_init(void)
}
MACHINE_START(EZX_E680, "Motorola EZX E680")
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.boot_params = 0xa0000100,
.map_io = pxa_map_io,
+ .nr_irqs = EZX_NR_IRQS,
.init_irq = pxa27x_init_irq,
.timer = &pxa_timer,
.init_machine = e680_init,
@@ -928,10 +928,9 @@ static void __init a1200_init(void)
}
MACHINE_START(EZX_A1200, "Motorola EZX A1200")
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.boot_params = 0xa0000100,
.map_io = pxa_map_io,
+ .nr_irqs = EZX_NR_IRQS,
.init_irq = pxa27x_init_irq,
.timer = &pxa_timer,
.init_machine = a1200_init,
@@ -1120,10 +1119,9 @@ static void __init a910_init(void)
}
MACHINE_START(EZX_A910, "Motorola EZX A910")
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.boot_params = 0xa0000100,
.map_io = pxa_map_io,
+ .nr_irqs = EZX_NR_IRQS,
.init_irq = pxa27x_init_irq,
.timer = &pxa_timer,
.init_machine = a910_init,
@@ -1186,10 +1184,9 @@ static void __init e6_init(void)
}
MACHINE_START(EZX_E6, "Motorola EZX E6")
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.boot_params = 0xa0000100,
.map_io = pxa_map_io,
+ .nr_irqs = EZX_NR_IRQS,
.init_irq = pxa27x_init_irq,
.timer = &pxa_timer,
.init_machine = e6_init,
@@ -1226,10 +1223,9 @@ static void __init e2_init(void)
}
MACHINE_START(EZX_E2, "Motorola EZX E2")
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.boot_params = 0xa0000100,
.map_io = pxa_map_io,
+ .nr_irqs = EZX_NR_IRQS,
.init_irq = pxa27x_init_irq,
.timer = &pxa_timer,
.init_machine = e2_init,
diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c
index baabb3ce088e..6451e9c3a93f 100644
--- a/arch/arm/mach-pxa/generic.c
+++ b/arch/arm/mach-pxa/generic.c
@@ -66,8 +66,7 @@ unsigned int get_clk_frequency_khz(int info)
return pxa25x_get_clk_frequency_khz(info);
else if (cpu_is_pxa27x())
return pxa27x_get_clk_frequency_khz(info);
- else
- return pxa3xx_get_clk_frequency_khz(info);
+ return 0;
}
EXPORT_SYMBOL(get_clk_frequency_khz);
@@ -80,8 +79,7 @@ unsigned int get_memclk_frequency_10khz(void)
return pxa25x_get_memclk_frequency_10khz();
else if (cpu_is_pxa27x())
return pxa27x_get_memclk_frequency_10khz();
- else
- return pxa3xx_get_memclk_frequency_10khz();
+ return 0;
}
EXPORT_SYMBOL(get_memclk_frequency_10khz);
diff --git a/arch/arm/mach-pxa/generic.h b/arch/arm/mach-pxa/generic.h
index c6305c5b8a72..4b1ad2769ed7 100644
--- a/arch/arm/mach-pxa/generic.h
+++ b/arch/arm/mach-pxa/generic.h
@@ -54,11 +54,9 @@ static inline void pxa2xx_clear_reset_status(unsigned int mask) {}
#ifdef CONFIG_PXA3xx
extern unsigned pxa3xx_get_clk_frequency_khz(int);
-extern unsigned pxa3xx_get_memclk_frequency_10khz(void);
extern void pxa3xx_clear_reset_status(unsigned int);
#else
#define pxa3xx_get_clk_frequency_khz(x) (0)
-#define pxa3xx_get_memclk_frequency_10khz() (0)
static inline void pxa3xx_clear_reset_status(unsigned int mask) {}
#endif
diff --git a/arch/arm/mach-pxa/gumstix.c b/arch/arm/mach-pxa/gumstix.c
index 96c345129135..1e2a9a13aec1 100644
--- a/arch/arm/mach-pxa/gumstix.c
+++ b/arch/arm/mach-pxa/gumstix.c
@@ -224,9 +224,7 @@ static void __init gumstix_init(void)
}
MACHINE_START(GUMSTIX, "Gumstix")
- .phys_io = 0x40000000,
.boot_params = 0xa0000100, /* match u-boot bi_boot_params */
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.map_io = pxa_map_io,
.init_irq = pxa25x_init_irq,
.timer = &pxa_timer,
diff --git a/arch/arm/mach-pxa/h5000.c b/arch/arm/mach-pxa/h5000.c
index c1cab0871c99..7057a1f46db4 100644
--- a/arch/arm/mach-pxa/h5000.c
+++ b/arch/arm/mach-pxa/h5000.c
@@ -201,8 +201,6 @@ static void __init h5000_init(void)
}
MACHINE_START(H5400, "HP iPAQ H5000")
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.boot_params = 0xa0000100,
.map_io = pxa_map_io,
.init_irq = pxa25x_init_irq,
diff --git a/arch/arm/mach-pxa/himalaya.c b/arch/arm/mach-pxa/himalaya.c
index f9a2e4b0f090..01b7f07ebad2 100644
--- a/arch/arm/mach-pxa/himalaya.c
+++ b/arch/arm/mach-pxa/himalaya.c
@@ -159,8 +159,6 @@ static void __init himalaya_init(void)
MACHINE_START(HIMALAYA, "HTC Himalaya")
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.boot_params = 0xa0000100,
.map_io = pxa_map_io,
.init_irq = pxa25x_init_irq,
diff --git a/arch/arm/mach-pxa/hx4700.c b/arch/arm/mach-pxa/hx4700.c
index 848c861dd23f..76d93a25bab6 100644
--- a/arch/arm/mach-pxa/hx4700.c
+++ b/arch/arm/mach-pxa/hx4700.c
@@ -870,10 +870,9 @@ static void __init hx4700_init(void)
}
MACHINE_START(H4700, "HP iPAQ HX4700")
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.boot_params = 0xa0000100,
.map_io = pxa_map_io,
+ .nr_irqs = HX4700_NR_IRQS,
.init_irq = pxa27x_init_irq,
.init_machine = hx4700_init,
.timer = &pxa_timer,
diff --git a/arch/arm/mach-pxa/icontrol.c b/arch/arm/mach-pxa/icontrol.c
index 5ccb0ceff6c4..d51ee3d25e70 100644
--- a/arch/arm/mach-pxa/icontrol.c
+++ b/arch/arm/mach-pxa/icontrol.c
@@ -191,9 +191,7 @@ static void __init icontrol_init(void)
}
MACHINE_START(ICONTROL, "iControl/SafeTcam boards using Embedian MXM-8x10 CoM")
- .phys_io = 0x40000000,
.boot_params = 0xa0000100,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.map_io = pxa_map_io,
.init_irq = pxa3xx_init_irq,
.timer = &pxa_timer,
diff --git a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c
index bc78c4dc0c66..e773dceeabc6 100644
--- a/arch/arm/mach-pxa/idp.c
+++ b/arch/arm/mach-pxa/idp.c
@@ -194,8 +194,6 @@ static void __init idp_map_io(void)
MACHINE_START(PXA_IDP, "Vibren PXA255 IDP")
/* Maintainer: Vibren Technologies */
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.map_io = idp_map_io,
.init_irq = pxa25x_init_irq,
.timer = &pxa_timer,
diff --git a/arch/arm/mach-pxa/include/mach/balloon3.h b/arch/arm/mach-pxa/include/mach/balloon3.h
index eec92e6fd7cf..561562b4360b 100644
--- a/arch/arm/mach-pxa/include/mach/balloon3.h
+++ b/arch/arm/mach-pxa/include/mach/balloon3.h
@@ -174,6 +174,8 @@ enum balloon3_features {
#define BALLOON3_CODEC_IRQ IRQ_GPIO(BALLOON3_GPIO_CODEC_IRQ)
#define BALLOON3_S0_CD_IRQ IRQ_GPIO(BALLOON3_GPIO_S0_CD)
+#define BALLOON3_NR_IRQS (IRQ_BOARD_START + 4)
+
extern int balloon3_has(enum balloon3_features feature);
#endif
diff --git a/arch/arm/mach-pxa/include/mach/debug-macro.S b/arch/arm/mach-pxa/include/mach/debug-macro.S
index 01cf81393fe2..7d5c75125d65 100644
--- a/arch/arm/mach-pxa/include/mach/debug-macro.S
+++ b/arch/arm/mach-pxa/include/mach/debug-macro.S
@@ -13,12 +13,10 @@
#include "hardware.h"
- .macro addruart, rx, tmp
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ MMU enabled?
- moveq \rx, #0x40000000 @ physical
- movne \rx, #io_p2v(0x40000000) @ virtual
- orr \rx, \rx, #0x00100000
+ .macro addruart, rp, rv
+ mov \rp, #0x00100000
+ orr \rv, \rp, #io_p2v(0x40000000) @ virtual
+ orr \rp, \rp, #0x40000000 @ physical
.endm
#define UART_SHIFT 2
diff --git a/arch/arm/mach-pxa/include/mach/eseries-irq.h b/arch/arm/mach-pxa/include/mach/eseries-irq.h
index f2a93d5e31d3..de292b269c63 100644
--- a/arch/arm/mach-pxa/include/mach/eseries-irq.h
+++ b/arch/arm/mach-pxa/include/mach/eseries-irq.h
@@ -25,3 +25,4 @@
#define TMIO_SD_IRQ IRQ_TMIO(1)
#define TMIO_USB_IRQ IRQ_TMIO(2)
+#define ESERIES_NR_IRQS (IRQ_BOARD_START + 16)
diff --git a/arch/arm/mach-pxa/include/mach/hx4700.h b/arch/arm/mach-pxa/include/mach/hx4700.h
index 9eaeed1f87f1..37408449ec25 100644
--- a/arch/arm/mach-pxa/include/mach/hx4700.h
+++ b/arch/arm/mach-pxa/include/mach/hx4700.h
@@ -17,6 +17,7 @@
#define HX4700_ASIC3_GPIO_BASE NR_BUILTIN_GPIO
#define HX4700_EGPIO_BASE (HX4700_ASIC3_GPIO_BASE + ASIC3_NUM_GPIOS)
+#define HX4700_NR_IRQS (IRQ_BOARD_START + 70)
/*
* PXA GPIOs
diff --git a/arch/arm/mach-pxa/include/mach/irqs.h b/arch/arm/mach-pxa/include/mach/irqs.h
index ffc8314520f2..d372caa75dc7 100644
--- a/arch/arm/mach-pxa/include/mach/irqs.h
+++ b/arch/arm/mach-pxa/include/mach/irqs.h
@@ -117,48 +117,12 @@
/*
* The following interrupts are for board specific purposes. Since
* the kernel can only run on one machine at a time, we can re-use
- * these. There will be 16 IRQs by default. If it is not enough,
- * IRQ_BOARD_END is allowed be customized for each board, but keep
- * the numbers within sensible limits and in descending order, so
- * when multiple config options are selected, the maximum will be
- * used.
+ * these.
+ * By default, no board IRQ is reserved. It should be finished in
+ * custom board since sparse IRQ is already enabled.
*/
#define IRQ_BOARD_START (PXA_GPIO_IRQ_BASE + PXA_GPIO_IRQ_NUM)
-#if defined(CONFIG_MACH_H4700)
-#define IRQ_BOARD_END (IRQ_BOARD_START + 70)
-#elif defined(CONFIG_MACH_ZYLONITE)
-#define IRQ_BOARD_END (IRQ_BOARD_START + 32)
-#elif defined(CONFIG_PXA_EZX)
-#define IRQ_BOARD_END (IRQ_BOARD_START + 23)
-#else
-#define IRQ_BOARD_END (IRQ_BOARD_START + 16)
-#endif
-
-/*
- * Figure out the MAX IRQ number.
- *
- * If we have an SA1111, the max IRQ is S1_BVD1_STSCHG+1.
- * If we have an LoCoMo, the max IRQ is IRQ_LOCOMO_SPI_TEND+1
- * Otherwise, we have the standard IRQs only.
- */
-#ifdef CONFIG_SA1111
-#define NR_IRQS (IRQ_BOARD_END + 55)
-#elif defined(CONFIG_PXA_HAVE_BOARD_IRQS)
-#define NR_IRQS (IRQ_BOARD_END)
-#else
#define NR_IRQS (IRQ_BOARD_START)
-#endif
-
-/* add IT8152 IRQs beyond BOARD_END */
-#ifdef CONFIG_PCI_HOST_ITE8152
-#define IT8152_LAST_IRQ (IRQ_BOARD_END + 40)
-
-#if NR_IRQS < (IT8152_LAST_IRQ+1)
-#undef NR_IRQS
-#define NR_IRQS (IT8152_LAST_IRQ+1)
-#endif
-
-#endif /* CONFIG_PCI_HOST_ITE8152 */
#endif /* __ASM_MACH_IRQS_H */
diff --git a/arch/arm/mach-pxa/include/mach/littleton.h b/arch/arm/mach-pxa/include/mach/littleton.h
index 6c9b21c51322..2a5726c15e0e 100644
--- a/arch/arm/mach-pxa/include/mach/littleton.h
+++ b/arch/arm/mach-pxa/include/mach/littleton.h
@@ -10,4 +10,6 @@
#define EXT0_GPIO_BASE (NR_BUILTIN_GPIO)
#define EXT0_GPIO(x) (EXT0_GPIO_BASE + (x))
+#define LITTLETON_NR_IRQS (IRQ_BOARD_START + 8)
+
#endif /* __ASM_ARCH_LITTLETON_H */
diff --git a/arch/arm/mach-pxa/include/mach/lpd270.h b/arch/arm/mach-pxa/include/mach/lpd270.h
index 0e6440c81683..cd070092b6eb 100644
--- a/arch/arm/mach-pxa/include/mach/lpd270.h
+++ b/arch/arm/mach-pxa/include/mach/lpd270.h
@@ -38,5 +38,6 @@
#define LPD270_USBC_IRQ LPD270_IRQ(2)
#define LPD270_ETHERNET_IRQ LPD270_IRQ(3)
#define LPD270_AC97_IRQ LPD270_IRQ(4)
+#define LPD270_NR_IRQS (IRQ_BOARD_START + 5)
#endif
diff --git a/arch/arm/mach-pxa/include/mach/lubbock.h b/arch/arm/mach-pxa/include/mach/lubbock.h
index a0d4247f08fc..2a086e8373eb 100644
--- a/arch/arm/mach-pxa/include/mach/lubbock.h
+++ b/arch/arm/mach-pxa/include/mach/lubbock.h
@@ -45,6 +45,9 @@
#define LUBBOCK_USB_DISC_IRQ LUBBOCK_IRQ(6) /* usb disconnect */
#define LUBBOCK_LAST_IRQ LUBBOCK_IRQ(6)
+#define LUBBOCK_SA1111_IRQ_BASE (IRQ_BOARD_START + 16)
+#define LUBBOCK_NR_IRQS (IRQ_BOARD_START + 16 + 55)
+
#ifndef __ASSEMBLY__
extern void lubbock_set_misc_wr(unsigned int mask, unsigned int set);
#endif
diff --git a/arch/arm/mach-pxa/include/mach/magician.h b/arch/arm/mach-pxa/include/mach/magician.h
index 20ef37d4a9a7..0a2efcf7947c 100644
--- a/arch/arm/mach-pxa/include/mach/magician.h
+++ b/arch/arm/mach-pxa/include/mach/magician.h
@@ -71,6 +71,8 @@
#define IRQ_MAGICIAN_BT (IRQ_BOARD_START + 2)
#define IRQ_MAGICIAN_VBUS (IRQ_BOARD_START + 3)
+#define MAGICIAN_NR_IRQS (IRQ_BOARD_START + 8)
+
/*
* CPLD EGPIOs
*/
diff --git a/arch/arm/mach-pxa/include/mach/mainstone.h b/arch/arm/mach-pxa/include/mach/mainstone.h
index 86e623abd64d..4c2d11cd824d 100644
--- a/arch/arm/mach-pxa/include/mach/mainstone.h
+++ b/arch/arm/mach-pxa/include/mach/mainstone.h
@@ -134,4 +134,6 @@
#define MAINSTONE_S1_STSCHG_IRQ MAINSTONE_IRQ(14)
#define MAINSTONE_S1_IRQ MAINSTONE_IRQ(15)
+#define MAINSTONE_NR_IRQS (IRQ_BOARD_START + 16)
+
#endif
diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa930.h b/arch/arm/mach-pxa/include/mach/mfp-pxa930.h
index 0d119d3b9221..04f7c97044f3 100644
--- a/arch/arm/mach-pxa/include/mach/mfp-pxa930.h
+++ b/arch/arm/mach-pxa/include/mach/mfp-pxa930.h
@@ -69,6 +69,7 @@
#define nBE0_GPIO_60 MFP_CFG(nBE0, AF0)
#define nBE1_GPIO_61 MFP_CFG(nBE1, AF0)
#define RDY_GPIO_62 MFP_CFG(RDY, AF0)
+#define PMIC_INT_GPIO83 MFP_CFG_LPM(PMIC_INT, AF0, PULL_HIGH)
/* Chip Select */
#define DF_nCS0_nCS2 MFP_CFG_LPM(DF_nCS0, AF3, PULL_HIGH)
@@ -92,6 +93,9 @@
#define GPIO63_CI2C_SCL MFP_CFG_LPM(GPIO63, AF4, PULL_HIGH)
#define GPIO64_CI2C_SDA MFP_CFG_LPM(GPIO64, AF4, PULL_HIGH)
+#define GPIO73_CI2C_SCL MFP_CFG_LPM(GPIO73, AF1, PULL_HIGH)
+#define GPIO74_CI2C_SDA MFP_CFG_LPM(GPIO74, AF1, PULL_HIGH)
+
#define GPIO77_CI2C_SCL MFP_CFG_LPM(GPIO77, AF2, PULL_HIGH)
#define GPIO78_CI2C_SDA MFP_CFG_LPM(GPIO78, AF2, PULL_HIGH)
@@ -345,6 +349,9 @@
#define GPIO69_UART1_CTS MFP_CFG(GPIO69, AF2)
#define GPIO70_UART1_RTS MFP_CFG(GPIO70, AF2)
+#define GPIO53_UART1_TXD MFP_CFG(GPIO53, AF2)
+#define GPIO54_UART1_RXD MFP_CFG(GPIO54, AF2)
+
/* UART2 - BTUART */
#define GPIO91_UART2_RXD MFP_CFG(GPIO91, AF1)
#define GPIO92_UART2_TXD MFP_CFG(GPIO92, AF1)
diff --git a/arch/arm/mach-pxa/include/mach/pcm027.h b/arch/arm/mach-pxa/include/mach/pcm027.h
index 04083263167e..4bac588478a8 100644
--- a/arch/arm/mach-pxa/include/mach/pcm027.h
+++ b/arch/arm/mach-pxa/include/mach/pcm027.h
@@ -30,6 +30,8 @@
#define PCM027_MMCDET_IRQ PCM027_IRQ(2)
#define PCM027_PM_5V_IRQ PCM027_IRQ(3)
+#define PCM027_NR_IRQS (IRQ_BOARD_START + 32)
+
/* I2C RTC */
#define PCM027_RTC_IRQ_GPIO 0
#define PCM027_RTC_IRQ IRQ_GPIO(PCM027_RTC_IRQ_GPIO)
diff --git a/arch/arm/mach-pxa/include/mach/poodle.h b/arch/arm/mach-pxa/include/mach/poodle.h
index 0b3e6d051c64..83d1cfd00fc9 100644
--- a/arch/arm/mach-pxa/include/mach/poodle.h
+++ b/arch/arm/mach-pxa/include/mach/poodle.h
@@ -85,6 +85,8 @@
#define POODLE_LOCOMO_GPIO_232VCC_ON LOCOMO_GPIO(12)
#define POODLE_LOCOMO_GPIO_JK_B LOCOMO_GPIO(13)
+#define POODLE_NR_IRQS (IRQ_BOARD_START + 4) /* 4 for LoCoMo */
+
extern struct platform_device poodle_locomo_device;
#endif /* __ASM_ARCH_POODLE_H */
diff --git a/arch/arm/mach-pxa/include/mach/pxa3xx-u2d.h b/arch/arm/mach-pxa/include/mach/pxa3xx-u2d.h
new file mode 100644
index 000000000000..9d82cb65ea56
--- /dev/null
+++ b/arch/arm/mach-pxa/include/mach/pxa3xx-u2d.h
@@ -0,0 +1,35 @@
+/*
+ * PXA3xx U2D header
+ *
+ * Copyright (C) 2010 CompuLab Ltd.
+ *
+ * Igor Grinberg <grinberg@compulab.co.il>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __PXA310_U2D__
+#define __PXA310_U2D__
+
+#include <linux/usb/ulpi.h>
+
+struct pxa3xx_u2d_platform_data {
+
+#define ULPI_SER_6PIN (1 << 0)
+#define ULPI_SER_3PIN (1 << 1)
+ unsigned int ulpi_mode;
+
+ int (*init)(struct device *);
+ void (*exit)(struct device *);
+};
+
+
+/* Start PXA3xx U2D host */
+int pxa3xx_u2d_start_hc(struct usb_bus *host);
+/* Stop PXA3xx U2D host */
+void pxa3xx_u2d_stop_hc(struct usb_bus *host);
+
+extern void pxa3xx_set_u2d_info(struct pxa3xx_u2d_platform_data *info);
+
+#endif /* __PXA310_U2D__ */
diff --git a/arch/arm/mach-pxa/include/mach/tosa.h b/arch/arm/mach-pxa/include/mach/tosa.h
index 1bbd1f2e4beb..1272c4b56ceb 100644
--- a/arch/arm/mach-pxa/include/mach/tosa.h
+++ b/arch/arm/mach-pxa/include/mach/tosa.h
@@ -20,6 +20,7 @@
/* Jacket Scoop */
#define TOSA_SCOOP_PHYS (PXA_CS5_PHYS + 0x00800000)
+#define TOSA_NR_IRQS (IRQ_BOARD_START + TC6393XB_NR_IRQS)
/*
* SCOOP2 internal GPIOs
*/
diff --git a/arch/arm/mach-pxa/include/mach/zeus.h b/arch/arm/mach-pxa/include/mach/zeus.h
index 6e119976003e..faa408ab7ad7 100644
--- a/arch/arm/mach-pxa/include/mach/zeus.h
+++ b/arch/arm/mach-pxa/include/mach/zeus.h
@@ -15,6 +15,8 @@
#ifndef _MACH_ZEUS_H
#define _MACH_ZEUS_H
+#define ZEUS_NR_IRQS (IRQ_BOARD_START + 48)
+
/* Physical addresses */
#define ZEUS_FLASH_PHYS PXA_CS0_PHYS
#define ZEUS_ETH0_PHYS PXA_CS1_PHYS
diff --git a/arch/arm/mach-pxa/include/mach/zylonite.h b/arch/arm/mach-pxa/include/mach/zylonite.h
index 9edf645368d6..ea24998b923c 100644
--- a/arch/arm/mach-pxa/include/mach/zylonite.h
+++ b/arch/arm/mach-pxa/include/mach/zylonite.h
@@ -5,6 +5,8 @@
#define EXT_GPIO(x) (128 + (x))
+#define ZYLONITE_NR_IRQS (IRQ_BOARD_START + 32)
+
/* the following variables are processor specific and initialized
* by the corresponding zylonite_pxa3xx_init()
*/
diff --git a/arch/arm/mach-pxa/littleton.c b/arch/arm/mach-pxa/littleton.c
index 9b9046185b00..41aa89e35772 100644
--- a/arch/arm/mach-pxa/littleton.c
+++ b/arch/arm/mach-pxa/littleton.c
@@ -43,7 +43,7 @@
#include <mach/pxafb.h>
#include <mach/mmc.h>
#include <mach/pxa2xx_spi.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
#include <mach/littleton.h>
#include <plat/i2c.h>
#include <plat/pxa3xx_nand.h>
@@ -437,10 +437,9 @@ static void __init littleton_init(void)
}
MACHINE_START(LITTLETON, "Marvell Form Factor Development Platform (aka Littleton)")
- .phys_io = 0x40000000,
.boot_params = 0xa0000100,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.map_io = pxa_map_io,
+ .nr_irqs = LITTLETON_NR_IRQS,
.init_irq = pxa3xx_init_irq,
.timer = &pxa_timer,
.init_machine = littleton_init,
diff --git a/arch/arm/mach-pxa/lpd270.c b/arch/arm/mach-pxa/lpd270.c
index d279507fc748..623af0232a54 100644
--- a/arch/arm/mach-pxa/lpd270.c
+++ b/arch/arm/mach-pxa/lpd270.c
@@ -505,10 +505,9 @@ static void __init lpd270_map_io(void)
MACHINE_START(LOGICPD_PXA270, "LogicPD PXA270 Card Engine")
/* Maintainer: Peter Barada */
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.boot_params = 0xa0000100,
.map_io = lpd270_map_io,
+ .nr_irqs = LPD270_NR_IRQS,
.init_irq = lpd270_init_irq,
.timer = &pxa_timer,
.init_machine = lpd270_init,
diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
index 330c3282856e..1499493cd070 100644
--- a/arch/arm/mach-pxa/lubbock.c
+++ b/arch/arm/mach-pxa/lubbock.c
@@ -229,7 +229,7 @@ static struct resource sa1111_resources[] = {
};
static struct sa1111_platform_data sa1111_info = {
- .irq_base = IRQ_BOARD_END,
+ .irq_base = LUBBOCK_SA1111_IRQ_BASE,
};
static struct platform_device sa1111_device = {
@@ -557,9 +557,8 @@ static void __init lubbock_map_io(void)
MACHINE_START(LUBBOCK, "Intel DBPXA250 Development Platform (aka Lubbock)")
/* Maintainer: MontaVista Software Inc. */
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.map_io = lubbock_map_io,
+ .nr_irqs = LUBBOCK_NR_IRQS,
.init_irq = lubbock_init_irq,
.timer = &pxa_timer,
.init_machine = lubbock_init,
diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c
index e81dd0c8e40d..90663760307a 100644
--- a/arch/arm/mach-pxa/magician.c
+++ b/arch/arm/mach-pxa/magician.c
@@ -764,10 +764,9 @@ static void __init magician_init(void)
MACHINE_START(MAGICIAN, "HTC Magician")
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.boot_params = 0xa0000100,
.map_io = pxa_map_io,
+ .nr_irqs = MAGICIAN_NR_IRQS,
.init_irq = pxa27x_init_irq,
.init_machine = magician_init,
.timer = &pxa_timer,
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
index 5543c64da9ef..a980a5c93e49 100644
--- a/arch/arm/mach-pxa/mainstone.c
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -50,7 +50,7 @@
#include <mach/mmc.h>
#include <mach/irda.h>
#include <mach/ohci.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
#include "generic.h"
#include "devices.h"
@@ -624,10 +624,9 @@ static void __init mainstone_map_io(void)
MACHINE_START(MAINSTONE, "Intel HCDDBBVA0 Development Platform (aka Mainstone)")
/* Maintainer: MontaVista Software Inc. */
- .phys_io = 0x40000000,
.boot_params = 0xa0000100, /* BLOB boot parameter setting */
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.map_io = mainstone_map_io,
+ .nr_irqs = MAINSTONE_NR_IRQS,
.init_irq = mainstone_init_irq,
.timer = &pxa_timer,
.init_machine = mainstone_init,
diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c
index dc66942ef9ab..0c31fabfc7fd 100644
--- a/arch/arm/mach-pxa/mioa701.c
+++ b/arch/arm/mach-pxa/mioa701.c
@@ -45,7 +45,7 @@
#include <mach/pxa27x.h>
#include <mach/regs-rtc.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
#include <mach/pxafb.h>
#include <mach/mmc.h>
#include <mach/udc.h>
@@ -819,8 +819,6 @@ static void mioa701_machine_exit(void)
}
MACHINE_START(MIOA701, "MIO A701")
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.boot_params = 0xa0000100,
.map_io = &pxa_map_io,
.init_irq = &pxa27x_init_irq,
diff --git a/arch/arm/mach-pxa/mp900.c b/arch/arm/mach-pxa/mp900.c
index 6d4503927a76..116167aaba68 100644
--- a/arch/arm/mach-pxa/mp900.c
+++ b/arch/arm/mach-pxa/mp900.c
@@ -92,9 +92,7 @@ static void __init mp900c_init(void)
/* Maintainer - Michael Petchkovsky <mkpetch@internode.on.net> */
MACHINE_START(NEC_MP900, "MobilePro900/C")
- .phys_io = 0x40000000,
.boot_params = 0xa0220100,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.timer = &pxa_timer,
.map_io = pxa_map_io,
.init_irq = pxa25x_init_irq,
diff --git a/arch/arm/mach-pxa/palmld.c b/arch/arm/mach-pxa/palmld.c
index 91038eeafe44..ce092c521e6d 100644
--- a/arch/arm/mach-pxa/palmld.c
+++ b/arch/arm/mach-pxa/palmld.c
@@ -39,7 +39,7 @@
#include <mach/mmc.h>
#include <mach/pxafb.h>
#include <mach/irda.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
#include <mach/palmasoc.h>
#include <mach/palm27x.h>
@@ -343,8 +343,6 @@ static void __init palmld_init(void)
}
MACHINE_START(PALMLD, "Palm LifeDrive")
- .phys_io = PALMLD_PHYS_IO_START,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.boot_params = 0xa0000100,
.map_io = palmld_map_io,
.init_irq = pxa27x_init_irq,
diff --git a/arch/arm/mach-pxa/palmt5.c b/arch/arm/mach-pxa/palmt5.c
index 1c281995f658..862da812cd10 100644
--- a/arch/arm/mach-pxa/palmt5.c
+++ b/arch/arm/mach-pxa/palmt5.c
@@ -39,7 +39,7 @@
#include <mach/mmc.h>
#include <mach/pxafb.h>
#include <mach/irda.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
#include <mach/udc.h>
#include <mach/palmasoc.h>
#include <mach/palm27x.h>
@@ -202,8 +202,6 @@ static void __init palmt5_init(void)
}
MACHINE_START(PALMT5, "Palm Tungsten|T5")
- .phys_io = PALMT5_PHYS_IO_START,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.boot_params = 0xa0000100,
.map_io = pxa_map_io,
.reserve = palmt5_reserve,
diff --git a/arch/arm/mach-pxa/palmtc.c b/arch/arm/mach-pxa/palmtc.c
index ce1104d1bc17..2131d5860919 100644
--- a/arch/arm/mach-pxa/palmtc.c
+++ b/arch/arm/mach-pxa/palmtc.c
@@ -412,9 +412,7 @@ static void __init palmtc_init(void)
};
MACHINE_START(PALMTC, "Palm Tungsten|C")
- .phys_io = 0x40000000,
.boot_params = 0xa0000100,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.map_io = pxa_map_io,
.init_irq = pxa25x_init_irq,
.timer = &pxa_timer,
diff --git a/arch/arm/mach-pxa/palmte2.c b/arch/arm/mach-pxa/palmte2.c
index 93c11a0438d5..a9dae7bc35d9 100644
--- a/arch/arm/mach-pxa/palmte2.c
+++ b/arch/arm/mach-pxa/palmte2.c
@@ -373,8 +373,6 @@ static void __init palmte2_init(void)
}
MACHINE_START(PALMTE2, "Palm Tungsten|E2")
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.boot_params = 0xa0000100,
.map_io = pxa_map_io,
.init_irq = pxa25x_init_irq,
diff --git a/arch/arm/mach-pxa/palmtreo.c b/arch/arm/mach-pxa/palmtreo.c
index 52defd5e42e5..00e2d7ba84ed 100644
--- a/arch/arm/mach-pxa/palmtreo.c
+++ b/arch/arm/mach-pxa/palmtreo.c
@@ -39,7 +39,7 @@
#include <mach/mmc.h>
#include <mach/pxafb.h>
#include <mach/irda.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
#include <mach/udc.h>
#include <mach/ohci.h>
#include <mach/pxa2xx-regs.h>
@@ -441,8 +441,6 @@ static void __init centro_init(void)
}
MACHINE_START(TREO680, "Palm Treo 680")
- .phys_io = TREO_PHYS_IO_START,
- .io_pg_offst = io_p2v(0x40000000),
.boot_params = 0xa0000100,
.map_io = pxa_map_io,
.reserve = treo_reserve,
@@ -452,8 +450,6 @@ MACHINE_START(TREO680, "Palm Treo 680")
MACHINE_END
MACHINE_START(CENTRO, "Palm Centro 685")
- .phys_io = TREO_PHYS_IO_START,
- .io_pg_offst = io_p2v(0x40000000),
.boot_params = 0xa0000100,
.map_io = pxa_map_io,
.reserve = treo_reserve,
diff --git a/arch/arm/mach-pxa/palmtx.c b/arch/arm/mach-pxa/palmtx.c
index 144dc2b6911f..d2060a1d1d68 100644
--- a/arch/arm/mach-pxa/palmtx.c
+++ b/arch/arm/mach-pxa/palmtx.c
@@ -43,7 +43,7 @@
#include <mach/mmc.h>
#include <mach/pxafb.h>
#include <mach/irda.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
#include <mach/udc.h>
#include <mach/palmasoc.h>
#include <mach/palm27x.h>
@@ -363,8 +363,6 @@ static void __init palmtx_init(void)
}
MACHINE_START(PALMTX, "Palm T|X")
- .phys_io = PALMTX_PHYS_IO_START,
- .io_pg_offst = io_p2v(0x40000000),
.boot_params = 0xa0000100,
.map_io = palmtx_map_io,
.init_irq = pxa27x_init_irq,
diff --git a/arch/arm/mach-pxa/palmz72.c b/arch/arm/mach-pxa/palmz72.c
index 87e4b1044e0b..af6203fbca9c 100644
--- a/arch/arm/mach-pxa/palmz72.c
+++ b/arch/arm/mach-pxa/palmz72.c
@@ -41,7 +41,7 @@
#include <mach/mmc.h>
#include <mach/pxafb.h>
#include <mach/irda.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
#include <mach/udc.h>
#include <mach/palmasoc.h>
#include <mach/palm27x.h>
@@ -279,8 +279,6 @@ static void __init palmz72_init(void)
}
MACHINE_START(PALMZ72, "Palm Zire72")
- .phys_io = 0x40000000,
- .io_pg_offst = io_p2v(0x40000000),
.boot_params = 0xa0000100,
.map_io = pxa_map_io,
.init_irq = pxa27x_init_irq,
diff --git a/arch/arm/mach-pxa/pcm027.c b/arch/arm/mach-pxa/pcm027.c
index 2190af066470..c77e8f30a439 100644
--- a/arch/arm/mach-pxa/pcm027.c
+++ b/arch/arm/mach-pxa/pcm027.c
@@ -259,9 +259,8 @@ static void __init pcm027_map_io(void)
MACHINE_START(PCM027, "Phytec Messtechnik GmbH phyCORE-PXA270")
/* Maintainer: Pengutronix */
.boot_params = 0xa0000100,
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.map_io = pcm027_map_io,
+ .nr_irqs = PCM027_NR_IRQS,
.init_irq = pxa27x_init_irq,
.timer = &pxa_timer,
.init_machine = pcm027_init,
diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
index 55e8fcde0141..93a191c889df 100644
--- a/arch/arm/mach-pxa/poodle.c
+++ b/arch/arm/mach-pxa/poodle.c
@@ -465,10 +465,9 @@ static void __init fixup_poodle(struct machine_desc *desc,
}
MACHINE_START(POODLE, "SHARP Poodle")
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.fixup = fixup_poodle,
.map_io = pxa_map_io,
+ .nr_irqs = POODLE_NR_IRQS, /* 4 for LoCoMo */
.init_irq = pxa25x_init_irq,
.timer = &pxa_timer,
.init_machine = poodle_init,
diff --git a/arch/arm/mach-pxa/pxa3xx-ulpi.c b/arch/arm/mach-pxa/pxa3xx-ulpi.c
new file mode 100644
index 000000000000..ce7168b233e2
--- /dev/null
+++ b/arch/arm/mach-pxa/pxa3xx-ulpi.c
@@ -0,0 +1,400 @@
+/*
+ * linux/arch/arm/mach-pxa/pxa3xx-ulpi.c
+ *
+ * code specific to pxa3xx aka Monahans
+ *
+ * Copyright (C) 2010 CompuLab Ltd.
+ *
+ * 2010-13-07: Igor Grinberg <grinberg@compulab.co.il>
+ * initial version: pxa310 USB Host mode support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/usb.h>
+#include <linux/usb/otg.h>
+
+#include <mach/hardware.h>
+#include <mach/regs-u2d.h>
+#include <mach/pxa3xx-u2d.h>
+
+struct pxa3xx_u2d_ulpi {
+ struct clk *clk;
+ void __iomem *mmio_base;
+
+ struct otg_transceiver *otg;
+ unsigned int ulpi_mode;
+};
+
+static struct pxa3xx_u2d_ulpi *u2d;
+
+static inline u32 u2d_readl(u32 reg)
+{
+ return __raw_readl(u2d->mmio_base + reg);
+}
+
+static inline void u2d_writel(u32 reg, u32 val)
+{
+ __raw_writel(val, u2d->mmio_base + reg);
+}
+
+#if defined(CONFIG_PXA310_ULPI)
+enum u2d_ulpi_phy_mode {
+ SYNCH = 0,
+ CARKIT = (1 << 0),
+ SER_3PIN = (1 << 1),
+ SER_6PIN = (1 << 2),
+ LOWPOWER = (1 << 3),
+};
+
+static inline enum u2d_ulpi_phy_mode pxa310_ulpi_get_phymode(void)
+{
+ return (u2d_readl(U2DOTGUSR) >> 28) & 0xF;
+}
+
+static int pxa310_ulpi_poll(void)
+{
+ int timeout = 50000;
+
+ while (timeout--) {
+ if (!(u2d_readl(U2DOTGUCR) & U2DOTGUCR_RUN))
+ return 0;
+
+ cpu_relax();
+ }
+
+ pr_warning("%s: ULPI access timed out!\n", __func__);
+
+ return -ETIMEDOUT;
+}
+
+static int pxa310_ulpi_read(struct otg_transceiver *otg, u32 reg)
+{
+ int err;
+
+ if (pxa310_ulpi_get_phymode() != SYNCH) {
+ pr_warning("%s: PHY is not in SYNCH mode!\n", __func__);
+ return -EBUSY;
+ }
+
+ u2d_writel(U2DOTGUCR, U2DOTGUCR_RUN | U2DOTGUCR_RNW | (reg << 16));
+ msleep(5);
+
+ err = pxa310_ulpi_poll();
+ if (err)
+ return err;
+
+ return u2d_readl(U2DOTGUCR) & U2DOTGUCR_RDATA;
+}
+
+static int pxa310_ulpi_write(struct otg_transceiver *otg, u32 val, u32 reg)
+{
+ if (pxa310_ulpi_get_phymode() != SYNCH) {
+ pr_warning("%s: PHY is not in SYNCH mode!\n", __func__);
+ return -EBUSY;
+ }
+
+ u2d_writel(U2DOTGUCR, U2DOTGUCR_RUN | (reg << 16) | (val << 8));
+ msleep(5);
+
+ return pxa310_ulpi_poll();
+}
+
+struct otg_io_access_ops pxa310_ulpi_access_ops = {
+ .read = pxa310_ulpi_read,
+ .write = pxa310_ulpi_write,
+};
+
+static void pxa310_otg_transceiver_rtsm(void)
+{
+ u32 u2dotgcr;
+
+ /* put PHY to sync mode */
+ u2dotgcr = u2d_readl(U2DOTGCR);
+ u2dotgcr |= U2DOTGCR_RTSM | U2DOTGCR_UTMID;
+ u2d_writel(U2DOTGCR, u2dotgcr);
+ msleep(10);
+
+ /* setup OTG sync mode */
+ u2dotgcr = u2d_readl(U2DOTGCR);
+ u2dotgcr |= U2DOTGCR_ULAF;
+ u2dotgcr &= ~(U2DOTGCR_SMAF | U2DOTGCR_CKAF);
+ u2d_writel(U2DOTGCR, u2dotgcr);
+}
+
+static int pxa310_start_otg_host_transcvr(struct usb_bus *host)
+{
+ int err;
+
+ pxa310_otg_transceiver_rtsm();
+
+ err = otg_init(u2d->otg);
+ if (err) {
+ pr_err("OTG transceiver init failed");
+ return err;
+ }
+
+ err = otg_set_vbus(u2d->otg, 1);
+ if (err) {
+ pr_err("OTG transceiver VBUS set failed");
+ return err;
+ }
+
+ err = otg_set_host(u2d->otg, host);
+ if (err)
+ pr_err("OTG transceiver Host mode set failed");
+
+ return err;
+}
+
+static int pxa310_start_otg_hc(struct usb_bus *host)
+{
+ u32 u2dotgcr;
+ int err;
+
+ /* disable USB device controller */
+ u2d_writel(U2DCR, u2d_readl(U2DCR) & ~U2DCR_UDE);
+ u2d_writel(U2DOTGCR, u2d_readl(U2DOTGCR) | U2DOTGCR_UTMID);
+ u2d_writel(U2DOTGICR, u2d_readl(U2DOTGICR) & ~0x37F7F);
+
+ err = pxa310_start_otg_host_transcvr(host);
+ if (err)
+ return err;
+
+ /* set xceiver mode */
+ if (u2d->ulpi_mode & ULPI_IC_6PIN_SERIAL)
+ u2d_writel(U2DP3CR, u2d_readl(U2DP3CR) & ~U2DP3CR_P2SS);
+ else if (u2d->ulpi_mode & ULPI_IC_3PIN_SERIAL)
+ u2d_writel(U2DP3CR, u2d_readl(U2DP3CR) | U2DP3CR_P2SS);
+
+ /* start OTG host controller */
+ u2dotgcr = u2d_readl(U2DOTGCR) | U2DOTGCR_SMAF;
+ u2d_writel(U2DOTGCR, u2dotgcr & ~(U2DOTGCR_ULAF | U2DOTGCR_CKAF));
+
+ return 0;
+}
+
+static void pxa310_stop_otg_hc(void)
+{
+ pxa310_otg_transceiver_rtsm();
+
+ otg_set_host(u2d->otg, NULL);
+ otg_set_vbus(u2d->otg, 0);
+ otg_shutdown(u2d->otg);
+}
+
+static void pxa310_u2d_setup_otg_hc(void)
+{
+ u32 u2dotgcr;
+
+ u2dotgcr = u2d_readl(U2DOTGCR);
+ u2dotgcr |= U2DOTGCR_ULAF | U2DOTGCR_UTMID;
+ u2dotgcr &= ~(U2DOTGCR_SMAF | U2DOTGCR_CKAF);
+ u2d_writel(U2DOTGCR, u2dotgcr);
+ msleep(5);
+ u2d_writel(U2DOTGCR, u2dotgcr | U2DOTGCR_ULE);
+ msleep(5);
+ u2d_writel(U2DOTGICR, u2d_readl(U2DOTGICR) & ~0x37F7F);
+}
+
+static int pxa310_otg_init(struct pxa3xx_u2d_platform_data *pdata)
+{
+ unsigned int ulpi_mode = ULPI_OTG_DRVVBUS;
+
+ if (pdata) {
+ if (pdata->ulpi_mode & ULPI_SER_6PIN)
+ ulpi_mode |= ULPI_IC_6PIN_SERIAL;
+ else if (pdata->ulpi_mode & ULPI_SER_3PIN)
+ ulpi_mode |= ULPI_IC_3PIN_SERIAL;
+ }
+
+ u2d->ulpi_mode = ulpi_mode;
+
+ u2d->otg = otg_ulpi_create(&pxa310_ulpi_access_ops, ulpi_mode);
+ if (!u2d->otg)
+ return -ENOMEM;
+
+ u2d->otg->io_priv = u2d->mmio_base;
+
+ return 0;
+}
+
+static void pxa310_otg_exit(void)
+{
+ kfree(u2d->otg);
+}
+#else
+static inline void pxa310_u2d_setup_otg_hc(void) {}
+static inline int pxa310_start_otg_hc(struct usb_bus *host)
+{
+ return 0;
+}
+static inline void pxa310_stop_otg_hc(void) {}
+static inline int pxa310_otg_init(struct pxa3xx_u2d_platform_data *pdata)
+{
+ return 0;
+}
+static inline void pxa310_otg_exit(void) {}
+#endif /* CONFIG_PXA310_ULPI */
+
+int pxa3xx_u2d_start_hc(struct usb_bus *host)
+{
+ int err = 0;
+
+ /* In case the PXA3xx ULPI isn't used, do nothing. */
+ if (!u2d)
+ return 0;
+
+ clk_enable(u2d->clk);
+
+ if (cpu_is_pxa310()) {
+ pxa310_u2d_setup_otg_hc();
+ err = pxa310_start_otg_hc(host);
+ }
+
+ return err;
+}
+
+void pxa3xx_u2d_stop_hc(struct usb_bus *host)
+{
+ /* In case the PXA3xx ULPI isn't used, do nothing. */
+ if (!u2d)
+ return;
+
+ if (cpu_is_pxa310())
+ pxa310_stop_otg_hc();
+
+ clk_disable(u2d->clk);
+}
+
+static int pxa3xx_u2d_probe(struct platform_device *pdev)
+{
+ struct pxa3xx_u2d_platform_data *pdata = pdev->dev.platform_data;
+ struct resource *r;
+ int err;
+
+ u2d = kzalloc(sizeof(struct pxa3xx_u2d_ulpi), GFP_KERNEL);
+ if (!u2d) {
+ dev_err(&pdev->dev, "failed to allocate memory\n");
+ return -ENOMEM;
+ }
+
+ u2d->clk = clk_get(&pdev->dev, NULL);
+ if (IS_ERR(u2d->clk)) {
+ dev_err(&pdev->dev, "failed to get u2d clock\n");
+ err = PTR_ERR(u2d->clk);
+ goto err_free_mem;
+ }
+
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!r) {
+ dev_err(&pdev->dev, "no IO memory resource defined\n");
+ err = -ENODEV;
+ goto err_put_clk;
+ }
+
+ r = request_mem_region(r->start, resource_size(r), pdev->name);
+ if (!r) {
+ dev_err(&pdev->dev, "failed to request memory resource\n");
+ err = -EBUSY;
+ goto err_put_clk;
+ }
+
+ u2d->mmio_base = ioremap(r->start, resource_size(r));
+ if (!u2d->mmio_base) {
+ dev_err(&pdev->dev, "ioremap() failed\n");
+ err = -ENODEV;
+ goto err_free_res;
+ }
+
+ if (pdata->init) {
+ err = pdata->init(&pdev->dev);
+ if (err)
+ goto err_free_io;
+ }
+
+ /* Only PXA310 U2D has OTG functionality */
+ if (cpu_is_pxa310()) {
+ err = pxa310_otg_init(pdata);
+ if (err)
+ goto err_free_plat;
+ }
+
+ platform_set_drvdata(pdev, &u2d);
+
+ return 0;
+
+err_free_plat:
+ if (pdata->exit)
+ pdata->exit(&pdev->dev);
+err_free_io:
+ iounmap(u2d->mmio_base);
+err_free_res:
+ release_mem_region(r->start, resource_size(r));
+err_put_clk:
+ clk_put(u2d->clk);
+err_free_mem:
+ kfree(u2d);
+ return err;
+}
+
+static int pxa3xx_u2d_remove(struct platform_device *pdev)
+{
+ struct pxa3xx_u2d_platform_data *pdata = pdev->dev.platform_data;
+ struct resource *r;
+
+ if (cpu_is_pxa310()) {
+ pxa310_stop_otg_hc();
+ pxa310_otg_exit();
+ }
+
+ if (pdata->exit)
+ pdata->exit(&pdev->dev);
+
+ platform_set_drvdata(pdev, NULL);
+ iounmap(u2d->mmio_base);
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ release_mem_region(r->start, resource_size(r));
+
+ clk_put(u2d->clk);
+
+ kfree(u2d);
+
+ return 0;
+}
+
+static struct platform_driver pxa3xx_u2d_ulpi_driver = {
+ .driver = {
+ .name = "pxa3xx-u2d",
+ .owner = THIS_MODULE,
+ },
+ .probe = pxa3xx_u2d_probe,
+ .remove = pxa3xx_u2d_remove,
+};
+
+static int pxa3xx_u2d_ulpi_init(void)
+{
+ return platform_driver_register(&pxa3xx_u2d_ulpi_driver);
+}
+module_init(pxa3xx_u2d_ulpi_init);
+
+static void __exit pxa3xx_u2d_ulpi_exit(void)
+{
+ platform_driver_unregister(&pxa3xx_u2d_ulpi_driver);
+}
+module_exit(pxa3xx_u2d_ulpi_exit);
+
+MODULE_DESCRIPTION("PXA3xx U2D ULPI driver");
+MODULE_AUTHOR("Igor Grinberg");
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index fa0014847c71..c85c3a7abd31 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -98,23 +98,6 @@ unsigned int pxa3xx_get_clk_frequency_khz(int info)
return CLK / 1000;
}
-/*
- * Return the current static memory controller clock frequency
- * in units of 10kHz
- */
-unsigned int pxa3xx_get_memclk_frequency_10khz(void)
-{
- unsigned long acsr;
- unsigned int smcfs, clk = 0;
-
- acsr = ACSR;
-
- smcfs = (acsr >> 23) & 0x7;
- clk = (acsr & ACCR_D0CS) ? RO_CLK : smcfs_mult[smcfs] * BASE_CLK;
-
- return (clk / 10000);
-}
-
void pxa3xx_clear_reset_status(unsigned int mask)
{
/* RESET_STATUS_* has a 1:1 mapping with ARSR */
@@ -265,7 +248,7 @@ static struct clk_lookup pxa3xx_clkregs[] = {
INIT_CLKREG(&clk_pxa3xx_i2c, "pxa2xx-i2c.0", NULL),
INIT_CLKREG(&clk_pxa3xx_udc, "pxa27x-udc", NULL),
INIT_CLKREG(&clk_pxa3xx_usbh, "pxa27x-ohci", NULL),
- INIT_CLKREG(&clk_pxa3xx_u2d, NULL, "U2DCLK"),
+ INIT_CLKREG(&clk_pxa3xx_u2d, "pxa3xx-u2d", NULL),
INIT_CLKREG(&clk_pxa3xx_keypad, "pxa27x-keypad", NULL),
INIT_CLKREG(&clk_pxa3xx_ssp1, "pxa27x-ssp.0", NULL),
INIT_CLKREG(&clk_pxa3xx_ssp2, "pxa27x-ssp.1", NULL),
diff --git a/arch/arm/mach-pxa/pxa930.c b/arch/arm/mach-pxa/pxa930.c
index 064292008288..7d29dd3af79d 100644
--- a/arch/arm/mach-pxa/pxa930.c
+++ b/arch/arm/mach-pxa/pxa930.c
@@ -192,7 +192,7 @@ static struct mfp_addr_map pxa935_mfp_addr_map[] __initdata = {
static int __init pxa930_init(void)
{
- if (cpu_is_pxa930() || cpu_is_pxa935()) {
+ if (cpu_is_pxa930() || cpu_is_pxa935() || cpu_is_pxa950()) {
mfp_init_base(io_p2v(MFPR_BASE));
mfp_init_addr(pxa930_mfp_addr_map);
}
diff --git a/arch/arm/mach-pxa/raumfeld.c b/arch/arm/mach-pxa/raumfeld.c
index 67e04f4e07c1..4121d03ea2c3 100644
--- a/arch/arm/mach-pxa/raumfeld.c
+++ b/arch/arm/mach-pxa/raumfeld.c
@@ -1083,8 +1083,6 @@ static void __init raumfeld_speaker_init(void)
#ifdef CONFIG_MACH_RAUMFELD_RC
MACHINE_START(RAUMFELD_RC, "Raumfeld Controller")
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.boot_params = RAUMFELD_SDRAM_BASE + 0x100,
.init_machine = raumfeld_controller_init,
.map_io = pxa_map_io,
@@ -1095,8 +1093,6 @@ MACHINE_END
#ifdef CONFIG_MACH_RAUMFELD_CONNECTOR
MACHINE_START(RAUMFELD_CONNECTOR, "Raumfeld Connector")
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.boot_params = RAUMFELD_SDRAM_BASE + 0x100,
.init_machine = raumfeld_connector_init,
.map_io = pxa_map_io,
@@ -1107,8 +1103,6 @@ MACHINE_END
#ifdef CONFIG_MACH_RAUMFELD_SPEAKER
MACHINE_START(RAUMFELD_SPEAKER, "Raumfeld Speaker")
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.boot_params = RAUMFELD_SDRAM_BASE + 0x100,
.init_machine = raumfeld_speaker_init,
.map_io = pxa_map_io,
diff --git a/arch/arm/mach-pxa/saar.c b/arch/arm/mach-pxa/saar.c
index 115b6f234bdd..4b521e045d75 100644
--- a/arch/arm/mach-pxa/saar.c
+++ b/arch/arm/mach-pxa/saar.c
@@ -596,9 +596,7 @@ static void __init saar_init(void)
MACHINE_START(SAAR, "PXA930 Handheld Platform (aka SAAR)")
/* Maintainer: Eric Miao <eric.miao@marvell.com> */
- .phys_io = 0x40000000,
.boot_params = 0xa0000100,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.map_io = pxa_map_io,
.init_irq = pxa3xx_init_irq,
.timer = &pxa_timer,
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
index 1cd99cb87bb1..f736119f1ebf 100644
--- a/arch/arm/mach-pxa/spitz.c
+++ b/arch/arm/mach-pxa/spitz.c
@@ -979,8 +979,6 @@ static void __init spitz_fixup(struct machine_desc *desc,
#ifdef CONFIG_MACH_SPITZ
MACHINE_START(SPITZ, "SHARP Spitz")
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.fixup = spitz_fixup,
.map_io = pxa_map_io,
.init_irq = pxa27x_init_irq,
@@ -991,8 +989,6 @@ MACHINE_END
#ifdef CONFIG_MACH_BORZOI
MACHINE_START(BORZOI, "SHARP Borzoi")
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.fixup = spitz_fixup,
.map_io = pxa_map_io,
.init_irq = pxa27x_init_irq,
@@ -1003,8 +999,6 @@ MACHINE_END
#ifdef CONFIG_MACH_AKITA
MACHINE_START(AKITA, "SHARP Akita")
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.fixup = spitz_fixup,
.map_io = pxa_map_io,
.init_irq = pxa27x_init_irq,
diff --git a/arch/arm/mach-pxa/stargate2.c b/arch/arm/mach-pxa/stargate2.c
index a654d1e6b38a..738adc1773fd 100644
--- a/arch/arm/mach-pxa/stargate2.c
+++ b/arch/arm/mach-pxa/stargate2.c
@@ -56,6 +56,8 @@
#include "devices.h"
#include "generic.h"
+#define STARGATE_NR_IRQS (IRQ_BOARD_START + 8)
+
/* Bluetooth */
#define SG2_BT_RESET 81
@@ -996,8 +998,6 @@ static void __init stargate2_init(void)
#ifdef CONFIG_MACH_INTELMOTE2
MACHINE_START(INTELMOTE2, "IMOTE 2")
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.map_io = pxa_map_io,
.init_irq = pxa27x_init_irq,
.timer = &pxa_timer,
@@ -1008,9 +1008,8 @@ MACHINE_END
#ifdef CONFIG_MACH_STARGATE2
MACHINE_START(STARGATE2, "Stargate 2")
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.map_io = pxa_map_io,
+ .nr_irqs = STARGATE_NR_IRQS,
.init_irq = pxa27x_init_irq,
.timer = &pxa_timer,
.init_machine = stargate2_init,
diff --git a/arch/arm/mach-pxa/tavorevb.c b/arch/arm/mach-pxa/tavorevb.c
index f02dcb5b4e97..2ea7545273ad 100644
--- a/arch/arm/mach-pxa/tavorevb.c
+++ b/arch/arm/mach-pxa/tavorevb.c
@@ -25,7 +25,7 @@
#include <mach/pxa930.h>
#include <mach/pxafb.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
#include "devices.h"
#include "generic.h"
@@ -489,9 +489,7 @@ static void __init tavorevb_init(void)
MACHINE_START(TAVOREVB, "PXA930 Evaluation Board (aka TavorEVB)")
/* Maintainer: Eric Miao <eric.miao@marvell.com> */
- .phys_io = 0x40000000,
.boot_params = 0xa0000100,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.map_io = pxa_map_io,
.init_irq = pxa3xx_init_irq,
.timer = &pxa_timer,
diff --git a/arch/arm/mach-pxa/tavorevb3.c b/arch/arm/mach-pxa/tavorevb3.c
new file mode 100644
index 000000000000..dc3011697bbf
--- /dev/null
+++ b/arch/arm/mach-pxa/tavorevb3.c
@@ -0,0 +1,135 @@
+/*
+ * linux/arch/arm/mach-pxa/tavorevb3.c
+ *
+ * Support for the Marvell EVB3 Development Platform.
+ *
+ * Copyright: (C) Copyright 2008-2010 Marvell International Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * publishhed by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/mfd/88pm860x.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include <mach/pxa930.h>
+
+#include <plat/i2c.h>
+
+#include "devices.h"
+#include "generic.h"
+
+#define TAVOREVB3_NR_IRQS (IRQ_BOARD_START + 24)
+
+static mfp_cfg_t evb3_mfp_cfg[] __initdata = {
+ /* UART */
+ GPIO53_UART1_TXD,
+ GPIO54_UART1_RXD,
+
+ /* PMIC */
+ PMIC_INT_GPIO83,
+};
+
+#if defined(CONFIG_I2C_PXA) || defined(CONFIG_I2C_PXA_MODULE)
+static struct pm860x_touch_pdata evb3_touch = {
+ .gpadc_prebias = 1,
+ .slot_cycle = 1,
+ .tsi_prebias = 6,
+ .pen_prebias = 16,
+ .pen_prechg = 2,
+ .res_x = 300,
+};
+
+static struct pm860x_backlight_pdata evb3_backlight[] = {
+ {
+ .id = PM8606_ID_BACKLIGHT,
+ .iset = PM8606_WLED_CURRENT(24),
+ .flags = PM8606_BACKLIGHT1,
+ },
+ {},
+};
+
+static struct pm860x_led_pdata evb3_led[] = {
+ {
+ .id = PM8606_ID_LED,
+ .iset = PM8606_LED_CURRENT(12),
+ .flags = PM8606_LED1_RED,
+ }, {
+ .id = PM8606_ID_LED,
+ .iset = PM8606_LED_CURRENT(12),
+ .flags = PM8606_LED1_GREEN,
+ }, {
+ .id = PM8606_ID_LED,
+ .iset = PM8606_LED_CURRENT(12),
+ .flags = PM8606_LED1_BLUE,
+ }, {
+ .id = PM8606_ID_LED,
+ .iset = PM8606_LED_CURRENT(12),
+ .flags = PM8606_LED2_RED,
+ }, {
+ .id = PM8606_ID_LED,
+ .iset = PM8606_LED_CURRENT(12),
+ .flags = PM8606_LED2_GREEN,
+ }, {
+ .id = PM8606_ID_LED,
+ .iset = PM8606_LED_CURRENT(12),
+ .flags = PM8606_LED2_BLUE,
+ },
+};
+
+static struct pm860x_platform_data evb3_pm8607_info = {
+ .touch = &evb3_touch,
+ .backlight = &evb3_backlight[0],
+ .led = &evb3_led[0],
+ .companion_addr = 0x10,
+ .irq_mode = 0,
+ .irq_base = IRQ_BOARD_START,
+
+ .i2c_port = GI2C_PORT,
+};
+
+static struct i2c_board_info evb3_i2c_info[] = {
+ {
+ .type = "88PM860x",
+ .addr = 0x34,
+ .platform_data = &evb3_pm8607_info,
+ .irq = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO83)),
+ },
+};
+
+static void __init evb3_init_i2c(void)
+{
+ pxa_set_i2c_info(NULL);
+ i2c_register_board_info(0, ARRAY_AND_SIZE(evb3_i2c_info));
+}
+#else
+static inline void evb3_init_i2c(void) {}
+#endif
+
+static void __init evb3_init(void)
+{
+ /* initialize MFP configurations */
+ pxa3xx_mfp_config(ARRAY_AND_SIZE(evb3_mfp_cfg));
+
+ pxa_set_ffuart_info(NULL);
+
+ evb3_init_i2c();
+}
+
+MACHINE_START(TAVOREVB3, "PXA950 Evaluation Board (aka TavorEVB3)")
+ .boot_params = 0xa0000100,
+ .map_io = pxa_map_io,
+ .nr_irqs = TAVOREVB3_NR_IRQS,
+ .init_irq = pxa3xx_init_irq,
+ .timer = &pxa_timer,
+ .init_machine = evb3_init,
+MACHINE_END
diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c
index 83cc3a18c2e9..0ee1df49606d 100644
--- a/arch/arm/mach-pxa/tosa.c
+++ b/arch/arm/mach-pxa/tosa.c
@@ -952,10 +952,9 @@ static void __init fixup_tosa(struct machine_desc *desc,
}
MACHINE_START(TOSA, "SHARP Tosa")
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.fixup = fixup_tosa,
.map_io = pxa_map_io,
+ .nr_irqs = TOSA_NR_IRQS,
.init_irq = pxa25x_init_irq,
.init_machine = tosa_init,
.timer = &pxa_timer,
diff --git a/arch/arm/mach-pxa/trizeps4.c b/arch/arm/mach-pxa/trizeps4.c
index 0acff172ef22..565d062f51d5 100644
--- a/arch/arm/mach-pxa/trizeps4.c
+++ b/arch/arm/mach-pxa/trizeps4.c
@@ -555,8 +555,6 @@ static void __init trizeps4_map_io(void)
MACHINE_START(TRIZEPS4, "Keith und Koep Trizeps IV module")
/* MAINTAINER("Jürgen Schindele") */
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.boot_params = TRIZEPS4_SDRAM_BASE + 0x100,
.init_machine = trizeps4_init,
.map_io = trizeps4_map_io,
@@ -566,8 +564,6 @@ MACHINE_END
MACHINE_START(TRIZEPS4WL, "Keith und Koep Trizeps IV-WL module")
/* MAINTAINER("Jürgen Schindele") */
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.boot_params = TRIZEPS4_SDRAM_BASE + 0x100,
.init_machine = trizeps4_init,
.map_io = trizeps4_map_io,
diff --git a/arch/arm/mach-pxa/viper.c b/arch/arm/mach-pxa/viper.c
index e90114a7e246..438fc9a5ed59 100644
--- a/arch/arm/mach-pxa/viper.c
+++ b/arch/arm/mach-pxa/viper.c
@@ -992,8 +992,6 @@ static void __init viper_map_io(void)
MACHINE_START(VIPER, "Arcom/Eurotech VIPER SBC")
/* Maintainer: Marc Zyngier <maz@misterjones.org> */
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.boot_params = 0xa0000100,
.map_io = viper_map_io,
.init_irq = viper_init_irq,
diff --git a/arch/arm/mach-pxa/vpac270.c b/arch/arm/mach-pxa/vpac270.c
index 37d6173bbb66..f45ac0961778 100644
--- a/arch/arm/mach-pxa/vpac270.c
+++ b/arch/arm/mach-pxa/vpac270.c
@@ -718,8 +718,6 @@ static void __init vpac270_init(void)
}
MACHINE_START(VPAC270, "Voipac PXA270")
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.boot_params = 0xa0000100,
.map_io = pxa_map_io,
.init_irq = pxa27x_init_irq,
diff --git a/arch/arm/mach-pxa/xcep.c b/arch/arm/mach-pxa/xcep.c
index d3b4e3f2e033..3260ce73d327 100644
--- a/arch/arm/mach-pxa/xcep.c
+++ b/arch/arm/mach-pxa/xcep.c
@@ -181,8 +181,6 @@ static void __init xcep_init(void)
}
MACHINE_START(XCEP, "Iskratel XCEP")
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.boot_params = 0xa0000100,
.init_machine = xcep_init,
.map_io = pxa_map_io,
diff --git a/arch/arm/mach-pxa/z2.c b/arch/arm/mach-pxa/z2.c
index f0d02288b4ca..fefde9848d82 100644
--- a/arch/arm/mach-pxa/z2.c
+++ b/arch/arm/mach-pxa/z2.c
@@ -37,7 +37,7 @@
#include <mach/z2.h>
#include <mach/pxafb.h>
#include <mach/mmc.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
#include <mach/pxa2xx_spi.h>
#include <plat/i2c.h>
@@ -703,9 +703,7 @@ static void __init z2_init(void)
}
MACHINE_START(ZIPIT2, "Zipit Z2")
- .phys_io = 0x40000000,
.boot_params = 0xa0000100,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.map_io = pxa_map_io,
.init_irq = pxa27x_init_irq,
.timer = &pxa_timer,
diff --git a/arch/arm/mach-pxa/zeus.c b/arch/arm/mach-pxa/zeus.c
index 03b9cb910e08..dea46a2d089b 100644
--- a/arch/arm/mach-pxa/zeus.c
+++ b/arch/arm/mach-pxa/zeus.c
@@ -900,10 +900,9 @@ static void __init zeus_map_io(void)
MACHINE_START(ARCOM_ZEUS, "Arcom/Eurotech ZEUS")
/* Maintainer: Marc Zyngier <maz@misterjones.org> */
- .phys_io = 0x40000000,
- .io_pg_offst = ((io_p2v(0x40000000) >> 18) & 0xfffc),
.boot_params = 0xa0000100,
.map_io = zeus_map_io,
+ .nr_irqs = ZEUS_NR_IRQS,
.init_irq = zeus_init_irq,
.timer = &pxa_timer,
.init_machine = zeus_init,
diff --git a/arch/arm/mach-pxa/zylonite.c b/arch/arm/mach-pxa/zylonite.c
index c479cbecf784..f25fb6245bd7 100644
--- a/arch/arm/mach-pxa/zylonite.c
+++ b/arch/arm/mach-pxa/zylonite.c
@@ -30,7 +30,7 @@
#include <mach/zylonite.h>
#include <mach/mmc.h>
#include <mach/ohci.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
#include <plat/pxa3xx_nand.h>
#include "devices.h"
@@ -411,10 +411,9 @@ static void __init zylonite_init(void)
}
MACHINE_START(ZYLONITE, "PXA3xx Platform Development Kit (aka Zylonite)")
- .phys_io = 0x40000000,
.boot_params = 0xa0000100,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.map_io = pxa_map_io,
+ .nr_irqs = ZYLONITE_NR_IRQS,
.init_irq = pxa3xx_init_irq,
.timer = &pxa_timer,
.init_machine = zylonite_init,
diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c
index 2fa38df28414..07c08151dfe6 100644
--- a/arch/arm/mach-realview/core.c
+++ b/arch/arm/mach-realview/core.c
@@ -259,6 +259,7 @@ struct mmci_platform_data realview_mmc0_plat_data = {
.status = realview_mmc_status,
.gpio_wp = 17,
.gpio_cd = 16,
+ .cd_invert = true,
};
struct mmci_platform_data realview_mmc1_plat_data = {
@@ -266,6 +267,7 @@ struct mmci_platform_data realview_mmc1_plat_data = {
.status = realview_mmc_status,
.gpio_wp = 19,
.gpio_cd = 18,
+ .cd_invert = true,
};
/*
diff --git a/arch/arm/mach-realview/include/mach/debug-macro.S b/arch/arm/mach-realview/include/mach/debug-macro.S
index 86622289b74e..90b687cbe04e 100644
--- a/arch/arm/mach-realview/include/mach/debug-macro.S
+++ b/arch/arm/mach-realview/include/mach/debug-macro.S
@@ -33,12 +33,10 @@
#error "Unknown RealView platform"
#endif
- .macro addruart, rx, tmp
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ MMU enabled?
- moveq \rx, #0x10000000
- movne \rx, #0xfb000000 @ virtual base
- orr \rx, \rx, #DEBUG_LL_UART_OFFSET
+ .macro addruart, rp, rv
+ mov \rp, #DEBUG_LL_UART_OFFSET
+ orr \rv, \rp, #0xfb000000 @ virtual base
+ orr \rp, \rp, #0x10000000 @ physical base
.endm
#include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/mach-realview/include/mach/smp.h b/arch/arm/mach-realview/include/mach/smp.h
index dd53892d44a7..d3cd265cb058 100644
--- a/arch/arm/mach-realview/include/mach/smp.h
+++ b/arch/arm/mach-realview/include/mach/smp.h
@@ -1,16 +1,8 @@
#ifndef ASMARM_ARCH_SMP_H
#define ASMARM_ARCH_SMP_H
-
#include <asm/hardware/gic.h>
-
-#define hard_smp_processor_id() \
- ({ \
- unsigned int cpunum; \
- __asm__("mrc p15, 0, %0, c0, c0, 5" \
- : "=r" (cpunum)); \
- cpunum &= 0x0F; \
- })
+#include <asm/smp_mpidr.h>
/*
* We use IRQ1 as the IPI
diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c
index 991c1f8390e2..f2697106f809 100644
--- a/arch/arm/mach-realview/realview_eb.c
+++ b/arch/arm/mach-realview/realview_eb.c
@@ -486,8 +486,6 @@ static void __init realview_eb_init(void)
MACHINE_START(REALVIEW_EB, "ARM-RealView EB")
/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
- .phys_io = REALVIEW_EB_UART0_BASE & SECTION_MASK,
- .io_pg_offst = (IO_ADDRESS(REALVIEW_EB_UART0_BASE) >> 18) & 0xfffc,
.boot_params = PHYS_OFFSET + 0x00000100,
.fixup = realview_fixup,
.map_io = realview_eb_map_io,
diff --git a/arch/arm/mach-realview/realview_pb1176.c b/arch/arm/mach-realview/realview_pb1176.c
index d2be12eb829e..a4125619d71b 100644
--- a/arch/arm/mach-realview/realview_pb1176.c
+++ b/arch/arm/mach-realview/realview_pb1176.c
@@ -378,8 +378,6 @@ static void __init realview_pb1176_init(void)
MACHINE_START(REALVIEW_PB1176, "ARM-RealView PB1176")
/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
- .phys_io = REALVIEW_PB1176_UART0_BASE & SECTION_MASK,
- .io_pg_offst = (IO_ADDRESS(REALVIEW_PB1176_UART0_BASE) >> 18) & 0xfffc,
.boot_params = PHYS_OFFSET + 0x00000100,
.fixup = realview_pb1176_fixup,
.map_io = realview_pb1176_map_io,
diff --git a/arch/arm/mach-realview/realview_pb11mp.c b/arch/arm/mach-realview/realview_pb11mp.c
index d591bc00b86e..117b95b2ca15 100644
--- a/arch/arm/mach-realview/realview_pb11mp.c
+++ b/arch/arm/mach-realview/realview_pb11mp.c
@@ -381,8 +381,6 @@ static void __init realview_pb11mp_init(void)
MACHINE_START(REALVIEW_PB11MP, "ARM-RealView PB11MPCore")
/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
- .phys_io = REALVIEW_PB11MP_UART0_BASE & SECTION_MASK,
- .io_pg_offst = (IO_ADDRESS(REALVIEW_PB11MP_UART0_BASE) >> 18) & 0xfffc,
.boot_params = PHYS_OFFSET + 0x00000100,
.fixup = realview_fixup,
.map_io = realview_pb11mp_map_io,
diff --git a/arch/arm/mach-realview/realview_pba8.c b/arch/arm/mach-realview/realview_pba8.c
index 6c37621217bc..929b8dc12e81 100644
--- a/arch/arm/mach-realview/realview_pba8.c
+++ b/arch/arm/mach-realview/realview_pba8.c
@@ -331,8 +331,6 @@ static void __init realview_pba8_init(void)
MACHINE_START(REALVIEW_PBA8, "ARM-RealView PB-A8")
/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
- .phys_io = REALVIEW_PBA8_UART0_BASE & SECTION_MASK,
- .io_pg_offst = (IO_ADDRESS(REALVIEW_PBA8_UART0_BASE) >> 18) & 0xfffc,
.boot_params = PHYS_OFFSET + 0x00000100,
.fixup = realview_fixup,
.map_io = realview_pba8_map_io,
diff --git a/arch/arm/mach-realview/realview_pbx.c b/arch/arm/mach-realview/realview_pbx.c
index 9428eff0b116..b9f9e20031a7 100644
--- a/arch/arm/mach-realview/realview_pbx.c
+++ b/arch/arm/mach-realview/realview_pbx.c
@@ -417,8 +417,6 @@ static void __init realview_pbx_init(void)
MACHINE_START(REALVIEW_PBX, "ARM-RealView PBX")
/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
- .phys_io = REALVIEW_PBX_UART0_BASE & SECTION_MASK,
- .io_pg_offst = (IO_ADDRESS(REALVIEW_PBX_UART0_BASE) >> 18) & 0xfffc,
.boot_params = PHYS_OFFSET + 0x00000100,
.fixup = realview_pbx_fixup,
.map_io = realview_pbx_map_io,
diff --git a/arch/arm/mach-rpc/include/mach/debug-macro.S b/arch/arm/mach-rpc/include/mach/debug-macro.S
index 6fc8d66395dc..85effffdc2b2 100644
--- a/arch/arm/mach-rpc/include/mach/debug-macro.S
+++ b/arch/arm/mach-rpc/include/mach/debug-macro.S
@@ -11,13 +11,11 @@
*
*/
- .macro addruart, rx, tmp
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ MMU enabled?
- moveq \rx, #0x03000000
- movne \rx, #0xe0000000
- orr \rx, \rx, #0x00010000
- orr \rx, \rx, #0x00000fe0
+ .macro addruart, rp, rv
+ mov \rp, #0x00010000
+ orr \rp, \rp, #0x00000fe0
+ orr \rv, \rp, #0xe0000000 @ virtual
+ orr \rp, \rp, #0x03000000 @ physical
.endm
#define UART_SHIFT 2
diff --git a/arch/arm/mach-rpc/include/mach/vmalloc.h b/arch/arm/mach-rpc/include/mach/vmalloc.h
index 9a96fd69e705..3bcd86fadb81 100644
--- a/arch/arm/mach-rpc/include/mach/vmalloc.h
+++ b/arch/arm/mach-rpc/include/mach/vmalloc.h
@@ -7,4 +7,4 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-#define VMALLOC_END (PAGE_OFFSET + 0x1c000000)
+#define VMALLOC_END 0xdc000000
diff --git a/arch/arm/mach-rpc/riscpc.c b/arch/arm/mach-rpc/riscpc.c
index c7fc01e9d1f6..580b3c73d2c7 100644
--- a/arch/arm/mach-rpc/riscpc.c
+++ b/arch/arm/mach-rpc/riscpc.c
@@ -218,8 +218,6 @@ extern struct sys_timer ioc_timer;
MACHINE_START(RISCPC, "Acorn-RiscPC")
/* Maintainer: Russell King */
- .phys_io = 0x03000000,
- .io_pg_offst = ((0xe0000000) >> 18) & 0xfffc,
.boot_params = 0x10000100,
.reserve_lp0 = 1,
.reserve_lp1 = 1,
diff --git a/arch/arm/mach-s3c2410/include/mach/debug-macro.S b/arch/arm/mach-s3c2410/include/mach/debug-macro.S
index 0eef78b4a6ed..5882deaa56be 100644
--- a/arch/arm/mach-s3c2410/include/mach/debug-macro.S
+++ b/arch/arm/mach-s3c2410/include/mach/debug-macro.S
@@ -19,13 +19,12 @@
#define S3C2410_UART1_OFF (0x4000)
#define SHIFT_2440TXF (14-9)
- .macro addruart, rx, tmp
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1
- ldreq \rx, = S3C24XX_PA_UART
- ldrne \rx, = S3C24XX_VA_UART
+ .macro addruart, rp, rv
+ ldr \rp, = S3C24XX_PA_UART
+ ldr \rv, = S3C24XX_VA_UART
#if CONFIG_DEBUG_S3C_UART != 0
- add \rx, \rx, #(S3C2410_UART1_OFF * CONFIG_DEBUG_S3C_UART)
+ add \rp, \rp, #(S3C2410_UART1_OFF * CONFIG_DEBUG_S3C_UART)
+ add \rv, \rv, #(S3C2410_UART1_OFF * CONFIG_DEBUG_S3C_UART)
#endif
.endm
diff --git a/arch/arm/mach-s3c2410/mach-amlm5900.c b/arch/arm/mach-s3c2410/mach-amlm5900.c
index 34fc05a4244b..44440cbd7620 100644
--- a/arch/arm/mach-s3c2410/mach-amlm5900.c
+++ b/arch/arm/mach-s3c2410/mach-amlm5900.c
@@ -241,8 +241,6 @@ static void __init amlm5900_init(void)
}
MACHINE_START(AML_M5900, "AML_M5900")
- .phys_io = S3C2410_PA_UART,
- .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.map_io = amlm5900_map_io,
.init_irq = s3c24xx_init_irq,
diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c
index c1f90f6fab42..2970ea9f7c2b 100644
--- a/arch/arm/mach-s3c2410/mach-bast.c
+++ b/arch/arm/mach-s3c2410/mach-bast.c
@@ -664,8 +664,6 @@ static void __init bast_init(void)
MACHINE_START(BAST, "Simtec-BAST")
/* Maintainer: Ben Dooks <ben@simtec.co.uk> */
- .phys_io = S3C2410_PA_UART,
- .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.map_io = bast_map_io,
.init_irq = s3c24xx_init_irq,
diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c
index 3ba3bab139d0..98c5c9e81ee9 100644
--- a/arch/arm/mach-s3c2410/mach-h1940.c
+++ b/arch/arm/mach-s3c2410/mach-h1940.c
@@ -350,8 +350,6 @@ static void __init h1940_init(void)
MACHINE_START(H1940, "IPAQ-H1940")
/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
- .phys_io = S3C2410_PA_UART,
- .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.map_io = h1940_map_io,
.reserve = h1940_reserve,
diff --git a/arch/arm/mach-s3c2410/mach-n30.c b/arch/arm/mach-s3c2410/mach-n30.c
index 41f299d983eb..271b9aa6d40a 100644
--- a/arch/arm/mach-s3c2410/mach-n30.c
+++ b/arch/arm/mach-s3c2410/mach-n30.c
@@ -605,8 +605,6 @@ MACHINE_START(N30, "Acer-N30")
/* Maintainer: Christer Weinigel <christer@weinigel.se>,
Ben Dooks <ben-linux@fluff.org>
*/
- .phys_io = S3C2410_PA_UART,
- .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.timer = &s3c24xx_timer,
.init_machine = n30_init,
@@ -617,8 +615,6 @@ MACHINE_END
MACHINE_START(N35, "Acer-N35")
/* Maintainer: Christer Weinigel <christer@weinigel.se>
*/
- .phys_io = S3C2410_PA_UART,
- .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.timer = &s3c24xx_timer,
.init_machine = n30_init,
diff --git a/arch/arm/mach-s3c2410/mach-otom.c b/arch/arm/mach-s3c2410/mach-otom.c
index d8c7f2efc1a7..0aa16cd5acbc 100644
--- a/arch/arm/mach-s3c2410/mach-otom.c
+++ b/arch/arm/mach-s3c2410/mach-otom.c
@@ -116,8 +116,6 @@ static void __init otom11_init(void)
MACHINE_START(OTOM, "Nex Vision - Otom 1.1")
/* Maintainer: Guillaume GOURAT <guillaume.gourat@nexvision.tv> */
- .phys_io = S3C2410_PA_UART,
- .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.map_io = otom11_map_io,
.init_machine = otom11_init,
diff --git a/arch/arm/mach-s3c2410/mach-qt2410.c b/arch/arm/mach-s3c2410/mach-qt2410.c
index d0e87b6e2e0f..e8f49feef28c 100644
--- a/arch/arm/mach-s3c2410/mach-qt2410.c
+++ b/arch/arm/mach-s3c2410/mach-qt2410.c
@@ -362,8 +362,6 @@ static void __init qt2410_machine_init(void)
}
MACHINE_START(QT2410, "QT2410")
- .phys_io = S3C2410_PA_UART,
- .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.map_io = qt2410_map_io,
.init_irq = s3c24xx_init_irq,
diff --git a/arch/arm/mach-s3c2410/mach-smdk2410.c b/arch/arm/mach-s3c2410/mach-smdk2410.c
index 452223042201..e17f03387aba 100644
--- a/arch/arm/mach-s3c2410/mach-smdk2410.c
+++ b/arch/arm/mach-s3c2410/mach-smdk2410.c
@@ -111,8 +111,6 @@ static void __init smdk2410_init(void)
MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switch
* to SMDK2410 */
/* Maintainer: Jonas Dietsche */
- .phys_io = S3C2410_PA_UART,
- .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.map_io = smdk2410_map_io,
.init_irq = s3c24xx_init_irq,
diff --git a/arch/arm/mach-s3c2410/mach-tct_hammer.c b/arch/arm/mach-s3c2410/mach-tct_hammer.c
index 929164a8e9b1..a15d0621c22f 100644
--- a/arch/arm/mach-s3c2410/mach-tct_hammer.c
+++ b/arch/arm/mach-s3c2410/mach-tct_hammer.c
@@ -152,8 +152,6 @@ static void __init tct_hammer_init(void)
}
MACHINE_START(TCT_HAMMER, "TCT_HAMMER")
- .phys_io = S3C2410_PA_UART,
- .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.map_io = tct_hammer_map_io,
.init_irq = s3c24xx_init_irq,
diff --git a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c
index d540d79dd264..6ccce5a761b4 100644
--- a/arch/arm/mach-s3c2410/mach-vr1000.c
+++ b/arch/arm/mach-s3c2410/mach-vr1000.c
@@ -400,8 +400,6 @@ static void __init vr1000_init(void)
MACHINE_START(VR1000, "Thorcom-VR1000")
/* Maintainer: Ben Dooks <ben@simtec.co.uk> */
- .phys_io = S3C2410_PA_UART,
- .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.map_io = vr1000_map_io,
.init_machine = vr1000_init,
diff --git a/arch/arm/mach-s3c2412/mach-jive.c b/arch/arm/mach-s3c2412/mach-jive.c
index 478f4b4606c2..923e01bdf017 100644
--- a/arch/arm/mach-s3c2412/mach-jive.c
+++ b/arch/arm/mach-s3c2412/mach-jive.c
@@ -675,8 +675,6 @@ static void __init jive_machine_init(void)
MACHINE_START(JIVE, "JIVE")
/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
- .phys_io = S3C2410_PA_UART,
- .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.init_irq = s3c24xx_init_irq,
diff --git a/arch/arm/mach-s3c2412/mach-smdk2413.c b/arch/arm/mach-s3c2412/mach-smdk2413.c
index 054c9f92232a..8e5758bdd666 100644
--- a/arch/arm/mach-s3c2412/mach-smdk2413.c
+++ b/arch/arm/mach-s3c2412/mach-smdk2413.c
@@ -150,8 +150,6 @@ static void __init smdk2413_machine_init(void)
MACHINE_START(S3C2413, "S3C2413")
/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
- .phys_io = S3C2410_PA_UART,
- .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.fixup = smdk2413_fixup,
@@ -163,8 +161,6 @@ MACHINE_END
MACHINE_START(SMDK2412, "SMDK2412")
/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
- .phys_io = S3C2410_PA_UART,
- .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.fixup = smdk2413_fixup,
@@ -176,8 +172,6 @@ MACHINE_END
MACHINE_START(SMDK2413, "SMDK2413")
/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
- .phys_io = S3C2410_PA_UART,
- .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.fixup = smdk2413_fixup,
diff --git a/arch/arm/mach-s3c2412/mach-vstms.c b/arch/arm/mach-s3c2412/mach-vstms.c
index f291ac25d312..83544ebe20ac 100644
--- a/arch/arm/mach-s3c2412/mach-vstms.c
+++ b/arch/arm/mach-s3c2412/mach-vstms.c
@@ -156,8 +156,6 @@ static void __init vstms_init(void)
}
MACHINE_START(VSTMS, "VSTMS")
- .phys_io = S3C2410_PA_UART,
- .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.fixup = vstms_fixup,
diff --git a/arch/arm/mach-s3c2416/mach-smdk2416.c b/arch/arm/mach-s3c2416/mach-smdk2416.c
index 5fc3f67ef265..7fc366476d7e 100644
--- a/arch/arm/mach-s3c2416/mach-smdk2416.c
+++ b/arch/arm/mach-s3c2416/mach-smdk2416.c
@@ -195,8 +195,6 @@ static void __init smdk2416_machine_init(void)
MACHINE_START(SMDK2416, "SMDK2416")
/* Maintainer: Yauhen Kharuzhy <jekhor@gmail.com> */
- .phys_io = S3C2410_PA_UART,
- .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.init_irq = s3c24xx_init_irq,
diff --git a/arch/arm/mach-s3c2440/mach-anubis.c b/arch/arm/mach-s3c2440/mach-anubis.c
index b73f78a9da5c..d7086788b1ff 100644
--- a/arch/arm/mach-s3c2440/mach-anubis.c
+++ b/arch/arm/mach-s3c2440/mach-anubis.c
@@ -498,8 +498,6 @@ static void __init anubis_init(void)
MACHINE_START(ANUBIS, "Simtec-Anubis")
/* Maintainer: Ben Dooks <ben@simtec.co.uk> */
- .phys_io = S3C2410_PA_UART,
- .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.map_io = anubis_map_io,
.init_machine = anubis_init,
diff --git a/arch/arm/mach-s3c2440/mach-at2440evb.c b/arch/arm/mach-s3c2440/mach-at2440evb.c
index 84725791e6bf..e3810c86a5e6 100644
--- a/arch/arm/mach-s3c2440/mach-at2440evb.c
+++ b/arch/arm/mach-s3c2440/mach-at2440evb.c
@@ -233,8 +233,6 @@ static void __init at2440evb_init(void)
MACHINE_START(AT2440EVB, "AT2440EVB")
- .phys_io = S3C2410_PA_UART,
- .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.map_io = at2440evb_map_io,
.init_machine = at2440evb_init,
diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c
index deaabe86741d..9f2c14ec7181 100644
--- a/arch/arm/mach-s3c2440/mach-gta02.c
+++ b/arch/arm/mach-s3c2440/mach-gta02.c
@@ -572,8 +572,6 @@ static void __init gta02_machine_init(void)
MACHINE_START(NEO1973_GTA02, "GTA02")
/* Maintainer: Nelson Castillo <arhuaco@freaks-unidos.net> */
- .phys_io = S3C2410_PA_UART,
- .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.map_io = gta02_map_io,
.init_irq = s3c24xx_init_irq,
diff --git a/arch/arm/mach-s3c2440/mach-mini2440.c b/arch/arm/mach-s3c2440/mach-mini2440.c
index a76bcda210ad..f62bb4c793bd 100644
--- a/arch/arm/mach-s3c2440/mach-mini2440.c
+++ b/arch/arm/mach-s3c2440/mach-mini2440.c
@@ -691,8 +691,6 @@ static void __init mini2440_init(void)
MACHINE_START(MINI2440, "MINI2440")
/* Maintainer: Michel Pollet <buserror@gmail.com> */
- .phys_io = S3C2410_PA_UART,
- .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.map_io = mini2440_map_io,
.init_machine = mini2440_init,
diff --git a/arch/arm/mach-s3c2440/mach-nexcoder.c b/arch/arm/mach-s3c2440/mach-nexcoder.c
index 3ff62de45fde..37dd306fb7dc 100644
--- a/arch/arm/mach-s3c2440/mach-nexcoder.c
+++ b/arch/arm/mach-s3c2440/mach-nexcoder.c
@@ -151,8 +151,6 @@ static void __init nexcoder_init(void)
MACHINE_START(NEXCODER_2440, "NexVision - Nexcoder 2440")
/* Maintainer: Guillaume GOURAT <guillaume.gourat@nexvision.tv> */
- .phys_io = S3C2410_PA_UART,
- .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.map_io = nexcoder_map_io,
.init_machine = nexcoder_init,
diff --git a/arch/arm/mach-s3c2440/mach-osiris.c b/arch/arm/mach-s3c2440/mach-osiris.c
index 319458da71a0..14dc67897757 100644
--- a/arch/arm/mach-s3c2440/mach-osiris.c
+++ b/arch/arm/mach-s3c2440/mach-osiris.c
@@ -455,8 +455,6 @@ static void __init osiris_init(void)
MACHINE_START(OSIRIS, "Simtec-OSIRIS")
/* Maintainer: Ben Dooks <ben@simtec.co.uk> */
- .phys_io = S3C2410_PA_UART,
- .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.map_io = osiris_map_io,
.init_irq = s3c24xx_init_irq,
diff --git a/arch/arm/mach-s3c2440/mach-rx1950.c b/arch/arm/mach-s3c2440/mach-rx1950.c
index 142d1f921176..32019bd9db3b 100644
--- a/arch/arm/mach-s3c2440/mach-rx1950.c
+++ b/arch/arm/mach-s3c2440/mach-rx1950.c
@@ -580,8 +580,6 @@ static void __init rx1950_reserve(void)
MACHINE_START(RX1950, "HP iPAQ RX1950")
/* Maintainers: Vasily Khoruzhick */
- .phys_io = S3C2410_PA_UART,
- .io_pg_offst = (((u32) S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.map_io = rx1950_map_io,
.reserve = rx1950_reserve,
diff --git a/arch/arm/mach-s3c2440/mach-rx3715.c b/arch/arm/mach-s3c2440/mach-rx3715.c
index 6bb44f75a9ce..1472b1a5b2fb 100644
--- a/arch/arm/mach-s3c2440/mach-rx3715.c
+++ b/arch/arm/mach-s3c2440/mach-rx3715.c
@@ -218,8 +218,6 @@ static void __init rx3715_init_machine(void)
MACHINE_START(RX3715, "IPAQ-RX3715")
/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
- .phys_io = S3C2410_PA_UART,
- .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.map_io = rx3715_map_io,
.reserve = rx3715_reserve,
diff --git a/arch/arm/mach-s3c2440/mach-smdk2440.c b/arch/arm/mach-s3c2440/mach-smdk2440.c
index df83276d85ae..eedfe0f11643 100644
--- a/arch/arm/mach-s3c2440/mach-smdk2440.c
+++ b/arch/arm/mach-s3c2440/mach-smdk2440.c
@@ -175,8 +175,6 @@ static void __init smdk2440_machine_init(void)
MACHINE_START(S3C2440, "SMDK2440")
/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
- .phys_io = S3C2410_PA_UART,
- .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.init_irq = s3c24xx_init_irq,
diff --git a/arch/arm/mach-s3c2443/mach-smdk2443.c b/arch/arm/mach-s3c2443/mach-smdk2443.c
index 4c863d3a52f4..4337f0a9960d 100644
--- a/arch/arm/mach-s3c2443/mach-smdk2443.c
+++ b/arch/arm/mach-s3c2443/mach-smdk2443.c
@@ -132,8 +132,6 @@ static void __init smdk2443_machine_init(void)
MACHINE_START(SMDK2443, "SMDK2443")
/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
- .phys_io = S3C2410_PA_UART,
- .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.init_irq = s3c24xx_init_irq,
diff --git a/arch/arm/mach-s3c24a0/include/mach/debug-macro.S b/arch/arm/mach-s3c24a0/include/mach/debug-macro.S
index 239476b81f3b..0c5a73805560 100644
--- a/arch/arm/mach-s3c24a0/include/mach/debug-macro.S
+++ b/arch/arm/mach-s3c24a0/include/mach/debug-macro.S
@@ -10,13 +10,12 @@
#include <mach/map.h>
#include <plat/regs-serial.h>
- .macro addruart, rx, tmp
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1
- ldreq \rx, = S3C24XX_PA_UART
- ldrne \rx, = S3C24XX_VA_UART
+ .macro addruart, rp, rv
+ ldr \rp, = S3C24XX_PA_UART
+ ldr \rv, = S3C24XX_VA_UART
#if CONFIG_DEBUG_S3C_UART != 0
- add \rx, \rx, #(S3C2410_UART1_OFF * CONFIG_DEBUG_S3C_UART)
+ add \rp, \rp, #(S3C2410_UART1_OFF * CONFIG_DEBUG_S3C_UART)
+ add \rv, \rv, #(S3C2410_UART1_OFF * CONFIG_DEBUG_S3C_UART)
#endif
.endm
diff --git a/arch/arm/mach-s3c64xx/include/mach/debug-macro.S b/arch/arm/mach-s3c64xx/include/mach/debug-macro.S
index f9ab5d26052a..a29e70550c70 100644
--- a/arch/arm/mach-s3c64xx/include/mach/debug-macro.S
+++ b/arch/arm/mach-s3c64xx/include/mach/debug-macro.S
@@ -21,13 +21,12 @@
* aligned and add in the offset when we load the value here.
*/
- .macro addruart, rx, rtmp
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1
- ldreq \rx, = S3C_PA_UART
- ldrne \rx, = (S3C_VA_UART + S3C_PA_UART & 0xfffff)
+ .macro addruart, rp, rv
+ ldr \rp, = S3C_PA_UART
+ ldr \rv, = (S3C_VA_UART + S3C_PA_UART & 0xfffff)
#if CONFIG_DEBUG_S3C_UART != 0
- add \rx, \rx, #(0x400 * CONFIG_DEBUG_S3C_UART)
+ add \rp, \rp, #(0x400 * CONFIG_DEBUG_S3C_UART)
+ add \rv, \rv, #(0x400 * CONFIG_DEBUG_S3C_UART)
#endif
.endm
diff --git a/arch/arm/mach-s3c64xx/mach-anw6410.c b/arch/arm/mach-s3c64xx/mach-anw6410.c
index 742dc87bd9c1..a53cf149476e 100644
--- a/arch/arm/mach-s3c64xx/mach-anw6410.c
+++ b/arch/arm/mach-s3c64xx/mach-anw6410.c
@@ -233,8 +233,6 @@ static void __init anw6410_machine_init(void)
MACHINE_START(ANW6410, "A&W6410")
/* Maintainer: Kwangwoo Lee <kwangwoo.lee@gmail.com> */
- .phys_io = S3C_PA_UART & 0xfff00000,
- .io_pg_offst = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C64XX_PA_SDRAM + 0x100,
.init_irq = s3c6410_init_irq,
diff --git a/arch/arm/mach-s3c64xx/mach-hmt.c b/arch/arm/mach-s3c64xx/mach-hmt.c
index fba90229f0df..b2639582caca 100644
--- a/arch/arm/mach-s3c64xx/mach-hmt.c
+++ b/arch/arm/mach-s3c64xx/mach-hmt.c
@@ -265,8 +265,6 @@ static void __init hmt_machine_init(void)
MACHINE_START(HMT, "Airgoo-HMT")
/* Maintainer: Peter Korsgaard <jacmet@sunsite.dk> */
- .phys_io = S3C_PA_UART & 0xfff00000,
- .io_pg_offst = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C64XX_PA_SDRAM + 0x100,
.init_irq = s3c6410_init_irq,
.map_io = hmt_map_io,
diff --git a/arch/arm/mach-s3c64xx/mach-ncp.c b/arch/arm/mach-s3c64xx/mach-ncp.c
index bf65747ea68e..c4986498cd12 100644
--- a/arch/arm/mach-s3c64xx/mach-ncp.c
+++ b/arch/arm/mach-s3c64xx/mach-ncp.c
@@ -97,8 +97,6 @@ static void __init ncp_machine_init(void)
MACHINE_START(NCP, "NCP")
/* Maintainer: Samsung Electronics */
- .phys_io = S3C_PA_UART & 0xfff00000,
- .io_pg_offst = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C64XX_PA_SDRAM + 0x100,
.init_irq = s3c6410_init_irq,
.map_io = ncp_map_io,
diff --git a/arch/arm/mach-s3c64xx/mach-real6410.c b/arch/arm/mach-s3c64xx/mach-real6410.c
index e130379ba0e8..4b4475da8ec6 100644
--- a/arch/arm/mach-s3c64xx/mach-real6410.c
+++ b/arch/arm/mach-s3c64xx/mach-real6410.c
@@ -141,8 +141,6 @@ static void __init real6410_machine_init(void)
MACHINE_START(REAL6410, "REAL6410")
/* Maintainer: Darius Augulis <augulis.darius@gmail.com> */
- .phys_io = S3C_PA_UART & 0xfff00000,
- .io_pg_offst = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C64XX_PA_SDRAM + 0x100,
.init_irq = s3c6410_init_irq,
diff --git a/arch/arm/mach-s3c64xx/mach-smartq.c b/arch/arm/mach-s3c64xx/mach-smartq.c
index 3a9639bc3d9b..cb1ebeb08763 100644
--- a/arch/arm/mach-s3c64xx/mach-smartq.c
+++ b/arch/arm/mach-s3c64xx/mach-smartq.c
@@ -136,7 +136,7 @@ static struct platform_device smartq_usb_otg_vbus_dev = {
.dev.platform_data = &smartq_usb_otg_vbus_pdata,
};
-static int __init smartq_bl_init(struct device *dev)
+static int smartq_bl_init(struct device *dev)
{
s3c_gpio_cfgpin(S3C64XX_GPF(15), S3C_GPIO_SFN(2));
diff --git a/arch/arm/mach-s3c64xx/mach-smartq5.c b/arch/arm/mach-s3c64xx/mach-smartq5.c
index a4d59b076e3d..3a3e5acde523 100644
--- a/arch/arm/mach-s3c64xx/mach-smartq5.c
+++ b/arch/arm/mach-s3c64xx/mach-smartq5.c
@@ -32,7 +32,7 @@
#include "mach-smartq.h"
-static struct gpio_led smartq5_leds[] __initdata = {
+static struct gpio_led smartq5_leds[] = {
{
.name = "smartq5:green",
.active_low = 1,
@@ -146,8 +146,6 @@ static void __init smartq5_machine_init(void)
MACHINE_START(SMARTQ5, "SmartQ 5")
/* Maintainer: Maurus Cuelenaere <mcuelenaere AT gmail DOT com> */
- .phys_io = S3C_PA_UART & 0xfff00000,
- .io_pg_offst = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C64XX_PA_SDRAM + 0x100,
.init_irq = s3c6410_init_irq,
.map_io = smartq_map_io,
diff --git a/arch/arm/mach-s3c64xx/mach-smartq7.c b/arch/arm/mach-s3c64xx/mach-smartq7.c
index e50a7d781732..e65375877d53 100644
--- a/arch/arm/mach-s3c64xx/mach-smartq7.c
+++ b/arch/arm/mach-s3c64xx/mach-smartq7.c
@@ -32,7 +32,7 @@
#include "mach-smartq.h"
-static struct gpio_led smartq7_leds[] __initdata = {
+static struct gpio_led smartq7_leds[] = {
{
.name = "smartq7:red",
.active_low = 1,
@@ -162,8 +162,6 @@ static void __init smartq7_machine_init(void)
MACHINE_START(SMARTQ7, "SmartQ 7")
/* Maintainer: Maurus Cuelenaere <mcuelenaere AT gmail DOT com> */
- .phys_io = S3C_PA_UART & 0xfff00000,
- .io_pg_offst = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C64XX_PA_SDRAM + 0x100,
.init_irq = s3c6410_init_irq,
.map_io = smartq_map_io,
diff --git a/arch/arm/mach-s3c64xx/mach-smdk6400.c b/arch/arm/mach-s3c64xx/mach-smdk6400.c
index 59916676d8d2..3cca642f1e6d 100644
--- a/arch/arm/mach-s3c64xx/mach-smdk6400.c
+++ b/arch/arm/mach-s3c64xx/mach-smdk6400.c
@@ -85,8 +85,6 @@ static void __init smdk6400_machine_init(void)
MACHINE_START(SMDK6400, "SMDK6400")
/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
- .phys_io = S3C_PA_UART & 0xfff00000,
- .io_pg_offst = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C64XX_PA_SDRAM + 0x100,
.init_irq = s3c6400_init_irq,
diff --git a/arch/arm/mach-s3c64xx/mach-smdk6410.c b/arch/arm/mach-s3c64xx/mach-smdk6410.c
index d498219fff1b..ec8865c03a19 100644
--- a/arch/arm/mach-s3c64xx/mach-smdk6410.c
+++ b/arch/arm/mach-s3c64xx/mach-smdk6410.c
@@ -704,8 +704,6 @@ static void __init smdk6410_machine_init(void)
MACHINE_START(SMDK6410, "SMDK6410")
/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
- .phys_io = S3C_PA_UART & 0xfff00000,
- .io_pg_offst = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C64XX_PA_SDRAM + 0x100,
.init_irq = s3c6410_init_irq,
diff --git a/arch/arm/mach-s5p6440/Kconfig b/arch/arm/mach-s5p6440/Kconfig
deleted file mode 100644
index 6a4af7f57584..000000000000
--- a/arch/arm/mach-s5p6440/Kconfig
+++ /dev/null
@@ -1,33 +0,0 @@
-# arch/arm/mach-s5p6440/Kconfig
-#
-# Copyright (c) 2009 Samsung Electronics Co., Ltd.
-# http://www.samsung.com/
-#
-# Licensed under GPLv2
-
-if ARCH_S5P6440
-
-config CPU_S5P6440
- bool
- select S3C_PL330_DMA
- help
- Enable S5P6440 CPU support
-
-config S5P6440_SETUP_I2C1
- bool
- help
- Common setup code for i2c bus 1.
-
-config MACH_SMDK6440
- bool "SMDK6440"
- select CPU_S5P6440
- select S3C_DEV_I2C1
- select S3C_DEV_RTC
- select S3C_DEV_WDT
- select SAMSUNG_DEV_ADC
- select SAMSUNG_DEV_TS
- select S5P6440_SETUP_I2C1
- help
- Machine support for the Samsung SMDK6440
-
-endif
diff --git a/arch/arm/mach-s5p6440/Makefile b/arch/arm/mach-s5p6440/Makefile
deleted file mode 100644
index c3fe4d3662a9..000000000000
--- a/arch/arm/mach-s5p6440/Makefile
+++ /dev/null
@@ -1,25 +0,0 @@
-# arch/arm/mach-s5p6440/Makefile
-#
-# Copyright (c) 2009 Samsung Electronics Co., Ltd.
-# http://www.samsung.com/
-#
-# Licensed under GPLv2
-
-obj-y :=
-obj-m :=
-obj-n :=
-obj- :=
-
-# Core support for S5P6440 system
-
-obj-$(CONFIG_CPU_S5P6440) += cpu.o init.o clock.o gpio.o dma.o
-obj-$(CONFIG_CPU_S5P6440) += setup-i2c0.o
-
-# machine support
-
-obj-$(CONFIG_MACH_SMDK6440) += mach-smdk6440.o
-
-# device support
-obj-y += dev-audio.o
-obj-$(CONFIG_S3C64XX_DEV_SPI) += dev-spi.o
-obj-$(CONFIG_S5P6440_SETUP_I2C1) += setup-i2c1.o
diff --git a/arch/arm/mach-s5p6440/clock.c b/arch/arm/mach-s5p6440/clock.c
deleted file mode 100644
index ca6e48dce777..000000000000
--- a/arch/arm/mach-s5p6440/clock.c
+++ /dev/null
@@ -1,846 +0,0 @@
-/* linux/arch/arm/mach-s5p6440/clock.c
- *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * S5P6440 - Clock support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/sysdev.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <mach/map.h>
-
-#include <plat/cpu-freq.h>
-#include <mach/regs-clock.h>
-#include <plat/clock.h>
-#include <plat/cpu.h>
-#include <plat/clock-clksrc.h>
-#include <plat/s5p-clock.h>
-#include <plat/pll.h>
-#include <plat/s5p6440.h>
-
-/* APLL Mux output clock */
-static struct clksrc_clk clk_mout_apll = {
- .clk = {
- .name = "mout_apll",
- .id = -1,
- },
- .sources = &clk_src_apll,
- .reg_src = { .reg = S5P_CLK_SRC0, .shift = 0, .size = 1 },
-};
-
-static int s5p6440_epll_enable(struct clk *clk, int enable)
-{
- unsigned int ctrlbit = clk->ctrlbit;
- unsigned int epll_con = __raw_readl(S5P_EPLL_CON) & ~ctrlbit;
-
- if (enable)
- __raw_writel(epll_con | ctrlbit, S5P_EPLL_CON);
- else
- __raw_writel(epll_con, S5P_EPLL_CON);
-
- return 0;
-}
-
-static unsigned long s5p6440_epll_get_rate(struct clk *clk)
-{
- return clk->rate;
-}
-
-static u32 epll_div[][5] = {
- { 36000000, 0, 48, 1, 4 },
- { 48000000, 0, 32, 1, 3 },
- { 60000000, 0, 40, 1, 3 },
- { 72000000, 0, 48, 1, 3 },
- { 84000000, 0, 28, 1, 2 },
- { 96000000, 0, 32, 1, 2 },
- { 32768000, 45264, 43, 1, 4 },
- { 45158000, 6903, 30, 1, 3 },
- { 49152000, 50332, 32, 1, 3 },
- { 67738000, 10398, 45, 1, 3 },
- { 73728000, 9961, 49, 1, 3 }
-};
-
-static int s5p6440_epll_set_rate(struct clk *clk, unsigned long rate)
-{
- unsigned int epll_con, epll_con_k;
- unsigned int i;
-
- if (clk->rate == rate) /* Return if nothing changed */
- return 0;
-
- epll_con = __raw_readl(S5P_EPLL_CON);
- epll_con_k = __raw_readl(S5P_EPLL_CON_K);
-
- epll_con_k &= ~(PLL90XX_KDIV_MASK);
- epll_con &= ~(PLL90XX_MDIV_MASK | PLL90XX_PDIV_MASK | PLL90XX_SDIV_MASK);
-
- for (i = 0; i < ARRAY_SIZE(epll_div); i++) {
- if (epll_div[i][0] == rate) {
- epll_con_k |= (epll_div[i][1] << PLL90XX_KDIV_SHIFT);
- epll_con |= (epll_div[i][2] << PLL90XX_MDIV_SHIFT) |
- (epll_div[i][3] << PLL90XX_PDIV_SHIFT) |
- (epll_div[i][4] << PLL90XX_SDIV_SHIFT);
- break;
- }
- }
-
- if (i == ARRAY_SIZE(epll_div)) {
- printk(KERN_ERR "%s: Invalid Clock EPLL Frequency\n", __func__);
- return -EINVAL;
- }
-
- __raw_writel(epll_con, S5P_EPLL_CON);
- __raw_writel(epll_con_k, S5P_EPLL_CON_K);
-
- clk->rate = rate;
-
- return 0;
-}
-
-static struct clk_ops s5p6440_epll_ops = {
- .get_rate = s5p6440_epll_get_rate,
- .set_rate = s5p6440_epll_set_rate,
-};
-
-static struct clksrc_clk clk_mout_epll = {
- .clk = {
- .name = "mout_epll",
- .id = -1,
- },
- .sources = &clk_src_epll,
- .reg_src = { .reg = S5P_CLK_SRC0, .shift = 2, .size = 1 },
-};
-
-static struct clksrc_clk clk_mout_mpll = {
- .clk = {
- .name = "mout_mpll",
- .id = -1,
- },
- .sources = &clk_src_mpll,
- .reg_src = { .reg = S5P_CLK_SRC0, .shift = 1, .size = 1 },
-};
-
-enum perf_level {
- L0 = 532*1000,
- L1 = 266*1000,
- L2 = 133*1000,
-};
-
-static const u32 clock_table[][3] = {
- /*{ARM_CLK, DIVarm, DIVhclk}*/
- {L0 * 1000, (0 << ARM_DIV_RATIO_SHIFT), (3 << S5P_CLKDIV0_HCLK_SHIFT)},
- {L1 * 1000, (1 << ARM_DIV_RATIO_SHIFT), (1 << S5P_CLKDIV0_HCLK_SHIFT)},
- {L2 * 1000, (3 << ARM_DIV_RATIO_SHIFT), (0 << S5P_CLKDIV0_HCLK_SHIFT)},
-};
-
-static unsigned long s5p6440_armclk_get_rate(struct clk *clk)
-{
- unsigned long rate = clk_get_rate(clk->parent);
- u32 clkdiv;
-
- /* divisor mask starts at bit0, so no need to shift */
- clkdiv = __raw_readl(ARM_CLK_DIV) & ARM_DIV_MASK;
-
- return rate / (clkdiv + 1);
-}
-
-static unsigned long s5p6440_armclk_round_rate(struct clk *clk,
- unsigned long rate)
-{
- u32 iter;
-
- for (iter = 1 ; iter < ARRAY_SIZE(clock_table) ; iter++) {
- if (rate > clock_table[iter][0])
- return clock_table[iter-1][0];
- }
-
- return clock_table[ARRAY_SIZE(clock_table) - 1][0];
-}
-
-static int s5p6440_armclk_set_rate(struct clk *clk, unsigned long rate)
-{
- u32 round_tmp;
- u32 iter;
- u32 clk_div0_tmp;
- u32 cur_rate = clk->ops->get_rate(clk);
- unsigned long flags;
-
- round_tmp = clk->ops->round_rate(clk, rate);
- if (round_tmp == cur_rate)
- return 0;
-
-
- for (iter = 0 ; iter < ARRAY_SIZE(clock_table) ; iter++) {
- if (round_tmp == clock_table[iter][0])
- break;
- }
-
- if (iter >= ARRAY_SIZE(clock_table))
- iter = ARRAY_SIZE(clock_table) - 1;
-
- local_irq_save(flags);
- if (cur_rate > round_tmp) {
- /* Frequency Down */
- clk_div0_tmp = __raw_readl(ARM_CLK_DIV) & ~(ARM_DIV_MASK);
- clk_div0_tmp |= clock_table[iter][1];
- __raw_writel(clk_div0_tmp, ARM_CLK_DIV);
-
- clk_div0_tmp = __raw_readl(ARM_CLK_DIV) &
- ~(S5P_CLKDIV0_HCLK_MASK);
- clk_div0_tmp |= clock_table[iter][2];
- __raw_writel(clk_div0_tmp, ARM_CLK_DIV);
-
-
- } else {
- /* Frequency Up */
- clk_div0_tmp = __raw_readl(ARM_CLK_DIV) &
- ~(S5P_CLKDIV0_HCLK_MASK);
- clk_div0_tmp |= clock_table[iter][2];
- __raw_writel(clk_div0_tmp, ARM_CLK_DIV);
-
- clk_div0_tmp = __raw_readl(ARM_CLK_DIV) & ~(ARM_DIV_MASK);
- clk_div0_tmp |= clock_table[iter][1];
- __raw_writel(clk_div0_tmp, ARM_CLK_DIV);
- }
- local_irq_restore(flags);
-
- clk->rate = clock_table[iter][0];
-
- return 0;
-}
-
-static struct clk_ops s5p6440_clkarm_ops = {
- .get_rate = s5p6440_armclk_get_rate,
- .set_rate = s5p6440_armclk_set_rate,
- .round_rate = s5p6440_armclk_round_rate,
-};
-
-static struct clksrc_clk clk_armclk = {
- .clk = {
- .name = "armclk",
- .id = 1,
- .parent = &clk_mout_apll.clk,
- .ops = &s5p6440_clkarm_ops,
- },
- .reg_div = { .reg = S5P_CLK_DIV0, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk clk_dout_mpll = {
- .clk = {
- .name = "dout_mpll",
- .id = -1,
- .parent = &clk_mout_mpll.clk,
- },
- .reg_div = { .reg = S5P_CLK_DIV0, .shift = 4, .size = 1 },
-};
-
-static struct clksrc_clk clk_hclk = {
- .clk = {
- .name = "clk_hclk",
- .id = -1,
- .parent = &clk_armclk.clk,
- },
- .reg_div = { .reg = S5P_CLK_DIV0, .shift = 8, .size = 4 },
-};
-
-static struct clksrc_clk clk_pclk = {
- .clk = {
- .name = "clk_pclk",
- .id = -1,
- .parent = &clk_hclk.clk,
- },
- .reg_div = { .reg = S5P_CLK_DIV0, .shift = 12, .size = 4 },
-};
-
-static struct clk *clkset_hclklow_list[] = {
- &clk_mout_apll.clk,
- &clk_mout_mpll.clk,
-};
-
-static struct clksrc_sources clkset_hclklow = {
- .sources = clkset_hclklow_list,
- .nr_sources = ARRAY_SIZE(clkset_hclklow_list),
-};
-
-static struct clksrc_clk clk_hclk_low = {
- .clk = {
- .name = "hclk_low",
- .id = -1,
- },
- .sources = &clkset_hclklow,
- .reg_src = { .reg = S5P_SYS_OTHERS, .shift = 6, .size = 1 },
- .reg_div = { .reg = S5P_CLK_DIV3, .shift = 8, .size = 4 },
-};
-
-static struct clksrc_clk clk_pclk_low = {
- .clk = {
- .name = "pclk_low",
- .id = -1,
- .parent = &clk_hclk_low.clk,
- },
- .reg_div = { .reg = S5P_CLK_DIV3, .shift = 12, .size = 4 },
-};
-
-int s5p6440_clk48m_ctrl(struct clk *clk, int enable)
-{
- unsigned long flags;
- u32 val;
-
- /* can't rely on clock lock, this register has other usages */
- local_irq_save(flags);
-
- val = __raw_readl(S5P_OTHERS);
- if (enable)
- val |= S5P_OTHERS_USB_SIG_MASK;
- else
- val &= ~S5P_OTHERS_USB_SIG_MASK;
-
- __raw_writel(val, S5P_OTHERS);
-
- local_irq_restore(flags);
-
- return 0;
-}
-
-static int s5p6440_pclk_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(S5P_CLK_GATE_PCLK, clk, enable);
-}
-
-static int s5p6440_hclk0_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(S5P_CLK_GATE_HCLK0, clk, enable);
-}
-
-static int s5p6440_hclk1_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(S5P_CLK_GATE_HCLK1, clk, enable);
-}
-
-static int s5p6440_sclk_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(S5P_CLK_GATE_SCLK0, clk, enable);
-}
-
-static int s5p6440_sclk1_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(S5P_CLK_GATE_SCLK1, clk, enable);
-}
-
-static int s5p6440_mem_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(S5P_CLK_GATE_MEM0, clk, enable);
-}
-
-/*
- * The following clocks will be disabled during clock initialization. It is
- * recommended to keep the following clocks disabled until the driver requests
- * for enabling the clock.
- */
-static struct clk init_clocks_disable[] = {
- {
- .name = "nand",
- .id = -1,
- .parent = &clk_hclk.clk,
- .enable = s5p6440_mem_ctrl,
- .ctrlbit = S5P_CLKCON_MEM0_HCLK_NFCON,
- }, {
- .name = "adc",
- .id = -1,
- .parent = &clk_pclk_low.clk,
- .enable = s5p6440_pclk_ctrl,
- .ctrlbit = S5P_CLKCON_PCLK_TSADC,
- }, {
- .name = "i2c",
- .id = -1,
- .parent = &clk_pclk_low.clk,
- .enable = s5p6440_pclk_ctrl,
- .ctrlbit = S5P_CLKCON_PCLK_IIC0,
- }, {
- .name = "i2s_v40",
- .id = 0,
- .parent = &clk_pclk_low.clk,
- .enable = s5p6440_pclk_ctrl,
- .ctrlbit = S5P_CLKCON_PCLK_IIS2,
- }, {
- .name = "spi",
- .id = 0,
- .parent = &clk_pclk_low.clk,
- .enable = s5p6440_pclk_ctrl,
- .ctrlbit = S5P_CLKCON_PCLK_SPI0,
- }, {
- .name = "spi",
- .id = 1,
- .parent = &clk_pclk_low.clk,
- .enable = s5p6440_pclk_ctrl,
- .ctrlbit = S5P_CLKCON_PCLK_SPI1,
- }, {
- .name = "sclk_spi_48",
- .id = 0,
- .parent = &clk_48m,
- .enable = s5p6440_sclk_ctrl,
- .ctrlbit = S5P_CLKCON_SCLK0_SPI0_48,
- }, {
- .name = "sclk_spi_48",
- .id = 1,
- .parent = &clk_48m,
- .enable = s5p6440_sclk_ctrl,
- .ctrlbit = S5P_CLKCON_SCLK0_SPI1_48,
- }, {
- .name = "mmc_48m",
- .id = 0,
- .parent = &clk_48m,
- .enable = s5p6440_sclk_ctrl,
- .ctrlbit = S5P_CLKCON_SCLK0_MMC0_48,
- }, {
- .name = "mmc_48m",
- .id = 1,
- .parent = &clk_48m,
- .enable = s5p6440_sclk_ctrl,
- .ctrlbit = S5P_CLKCON_SCLK0_MMC1_48,
- }, {
- .name = "mmc_48m",
- .id = 2,
- .parent = &clk_48m,
- .enable = s5p6440_sclk_ctrl,
- .ctrlbit = S5P_CLKCON_SCLK0_MMC2_48,
- }, {
- .name = "otg",
- .id = -1,
- .parent = &clk_hclk_low.clk,
- .enable = s5p6440_hclk0_ctrl,
- .ctrlbit = S5P_CLKCON_HCLK0_USB
- }, {
- .name = "post",
- .id = -1,
- .parent = &clk_hclk_low.clk,
- .enable = s5p6440_hclk0_ctrl,
- .ctrlbit = S5P_CLKCON_HCLK0_POST0
- }, {
- .name = "lcd",
- .id = -1,
- .parent = &clk_hclk_low.clk,
- .enable = s5p6440_hclk1_ctrl,
- .ctrlbit = S5P_CLKCON_HCLK1_DISPCON,
- }, {
- .name = "hsmmc",
- .id = 0,
- .parent = &clk_hclk_low.clk,
- .enable = s5p6440_hclk0_ctrl,
- .ctrlbit = S5P_CLKCON_HCLK0_HSMMC0,
- }, {
- .name = "hsmmc",
- .id = 1,
- .parent = &clk_hclk_low.clk,
- .enable = s5p6440_hclk0_ctrl,
- .ctrlbit = S5P_CLKCON_HCLK0_HSMMC1,
- }, {
- .name = "hsmmc",
- .id = 2,
- .parent = &clk_hclk_low.clk,
- .enable = s5p6440_hclk0_ctrl,
- .ctrlbit = S5P_CLKCON_HCLK0_HSMMC2,
- }, {
- .name = "rtc",
- .id = -1,
- .parent = &clk_pclk_low.clk,
- .enable = s5p6440_pclk_ctrl,
- .ctrlbit = S5P_CLKCON_PCLK_RTC,
- }, {
- .name = "watchdog",
- .id = -1,
- .parent = &clk_pclk_low.clk,
- .enable = s5p6440_pclk_ctrl,
- .ctrlbit = S5P_CLKCON_PCLK_WDT,
- }, {
- .name = "timers",
- .id = -1,
- .parent = &clk_pclk_low.clk,
- .enable = s5p6440_pclk_ctrl,
- .ctrlbit = S5P_CLKCON_PCLK_PWM,
- }, {
- .name = "hclk_fimgvg",
- .id = -1,
- .parent = &clk_hclk.clk,
- .enable = s5p6440_hclk1_ctrl,
- .ctrlbit = (1 << 2),
- }, {
- .name = "tsi",
- .id = -1,
- .parent = &clk_hclk_low.clk,
- .enable = s5p6440_hclk1_ctrl,
- .ctrlbit = (1 << 0),
- }, {
- .name = "pclk_fimgvg",
- .id = -1,
- .parent = &clk_pclk.clk,
- .enable = s5p6440_pclk_ctrl,
- .ctrlbit = (1 << 31),
- }, {
- .name = "dmc0",
- .id = -1,
- .parent = &clk_pclk.clk,
- .enable = s5p6440_pclk_ctrl,
- .ctrlbit = (1 << 30),
- }, {
- .name = "etm",
- .id = -1,
- .parent = &clk_pclk.clk,
- .enable = s5p6440_pclk_ctrl,
- .ctrlbit = (1 << 29),
- }, {
- .name = "dsim",
- .id = -1,
- .parent = &clk_pclk_low.clk,
- .enable = s5p6440_pclk_ctrl,
- .ctrlbit = (1 << 28),
- }, {
- .name = "gps",
- .id = -1,
- .parent = &clk_pclk_low.clk,
- .enable = s5p6440_pclk_ctrl,
- .ctrlbit = (1 << 25),
- }, {
- .name = "pcm",
- .id = -1,
- .parent = &clk_pclk_low.clk,
- .enable = s5p6440_pclk_ctrl,
- .ctrlbit = (1 << 8),
- }, {
- .name = "irom",
- .id = -1,
- .parent = &clk_hclk.clk,
- .enable = s5p6440_hclk0_ctrl,
- .ctrlbit = (1 << 25),
- }, {
- .name = "dma",
- .id = -1,
- .parent = &clk_hclk_low.clk,
- .enable = s5p6440_hclk0_ctrl,
- .ctrlbit = (1 << 12),
- }, {
- .name = "2d",
- .id = -1,
- .parent = &clk_hclk.clk,
- .enable = s5p6440_hclk0_ctrl,
- .ctrlbit = (1 << 8),
- },
-};
-
-/*
- * The following clocks will be enabled during clock initialization.
- */
-static struct clk init_clocks[] = {
- {
- .name = "gpio",
- .id = -1,
- .parent = &clk_pclk_low.clk,
- .enable = s5p6440_pclk_ctrl,
- .ctrlbit = S5P_CLKCON_PCLK_GPIO,
- }, {
- .name = "uart",
- .id = 0,
- .parent = &clk_pclk_low.clk,
- .enable = s5p6440_pclk_ctrl,
- .ctrlbit = S5P_CLKCON_PCLK_UART0,
- }, {
- .name = "uart",
- .id = 1,
- .parent = &clk_pclk_low.clk,
- .enable = s5p6440_pclk_ctrl,
- .ctrlbit = S5P_CLKCON_PCLK_UART1,
- }, {
- .name = "uart",
- .id = 2,
- .parent = &clk_pclk_low.clk,
- .enable = s5p6440_pclk_ctrl,
- .ctrlbit = S5P_CLKCON_PCLK_UART2,
- }, {
- .name = "uart",
- .id = 3,
- .parent = &clk_pclk_low.clk,
- .enable = s5p6440_pclk_ctrl,
- .ctrlbit = S5P_CLKCON_PCLK_UART3,
- }, {
- .name = "mem",
- .id = -1,
- .parent = &clk_hclk.clk,
- .enable = s5p6440_hclk0_ctrl,
- .ctrlbit = (1 << 21),
- }, {
- .name = "intc",
- .id = -1,
- .parent = &clk_hclk.clk,
- .enable = s5p6440_hclk0_ctrl,
- .ctrlbit = (1 << 1),
- },
-};
-
-static struct clk clk_iis_cd_v40 = {
- .name = "iis_cdclk_v40",
- .id = -1,
-};
-
-static struct clk clk_pcm_cd = {
- .name = "pcm_cdclk",
- .id = -1,
-};
-
-static struct clk *clkset_group1_list[] = {
- &clk_mout_epll.clk,
- &clk_dout_mpll.clk,
- &clk_fin_epll,
-};
-
-static struct clksrc_sources clkset_group1 = {
- .sources = clkset_group1_list,
- .nr_sources = ARRAY_SIZE(clkset_group1_list),
-};
-
-static struct clk *clkset_uart_list[] = {
- &clk_mout_epll.clk,
- &clk_dout_mpll.clk,
-};
-
-static struct clksrc_sources clkset_uart = {
- .sources = clkset_uart_list,
- .nr_sources = ARRAY_SIZE(clkset_uart_list),
-};
-
-static struct clk *clkset_audio_list[] = {
- &clk_mout_epll.clk,
- &clk_dout_mpll.clk,
- &clk_fin_epll,
- &clk_iis_cd_v40,
- &clk_pcm_cd,
-};
-
-static struct clksrc_sources clkset_audio = {
- .sources = clkset_audio_list,
- .nr_sources = ARRAY_SIZE(clkset_audio_list),
-};
-
-static struct clksrc_clk clksrcs[] = {
- {
- .clk = {
- .name = "mmc_bus",
- .id = 0,
- .ctrlbit = S5P_CLKCON_SCLK0_MMC0,
- .enable = s5p6440_sclk_ctrl,
- },
- .sources = &clkset_group1,
- .reg_src = { .reg = S5P_CLK_SRC0, .shift = 18, .size = 2 },
- .reg_div = { .reg = S5P_CLK_DIV1, .shift = 0, .size = 4 },
- }, {
- .clk = {
- .name = "mmc_bus",
- .id = 1,
- .ctrlbit = S5P_CLKCON_SCLK0_MMC1,
- .enable = s5p6440_sclk_ctrl,
- },
- .sources = &clkset_group1,
- .reg_src = { .reg = S5P_CLK_SRC0, .shift = 20, .size = 2 },
- .reg_div = { .reg = S5P_CLK_DIV1, .shift = 4, .size = 4 },
- }, {
- .clk = {
- .name = "mmc_bus",
- .id = 2,
- .ctrlbit = S5P_CLKCON_SCLK0_MMC2,
- .enable = s5p6440_sclk_ctrl,
- },
- .sources = &clkset_group1,
- .reg_src = { .reg = S5P_CLK_SRC0, .shift = 22, .size = 2 },
- .reg_div = { .reg = S5P_CLK_DIV1, .shift = 8, .size = 4 },
- }, {
- .clk = {
- .name = "uclk1",
- .id = -1,
- .ctrlbit = S5P_CLKCON_SCLK0_UART,
- .enable = s5p6440_sclk_ctrl,
- },
- .sources = &clkset_uart,
- .reg_src = { .reg = S5P_CLK_SRC0, .shift = 13, .size = 1 },
- .reg_div = { .reg = S5P_CLK_DIV2, .shift = 16, .size = 4 },
- }, {
- .clk = {
- .name = "spi_epll",
- .id = 0,
- .ctrlbit = S5P_CLKCON_SCLK0_SPI0,
- .enable = s5p6440_sclk_ctrl,
- },
- .sources = &clkset_group1,
- .reg_src = { .reg = S5P_CLK_SRC0, .shift = 14, .size = 2 },
- .reg_div = { .reg = S5P_CLK_DIV2, .shift = 0, .size = 4 },
- }, {
- .clk = {
- .name = "spi_epll",
- .id = 1,
- .ctrlbit = S5P_CLKCON_SCLK0_SPI1,
- .enable = s5p6440_sclk_ctrl,
- },
- .sources = &clkset_group1,
- .reg_src = { .reg = S5P_CLK_SRC0, .shift = 16, .size = 2 },
- .reg_div = { .reg = S5P_CLK_DIV2, .shift = 4, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_post",
- .id = -1,
- .ctrlbit = (1 << 10),
- .enable = s5p6440_sclk_ctrl,
- },
- .sources = &clkset_group1,
- .reg_src = { .reg = S5P_CLK_SRC0, .shift = 26, .size = 2 },
- .reg_div = { .reg = S5P_CLK_DIV1, .shift = 12, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_dispcon",
- .id = -1,
- .ctrlbit = (1 << 1),
- .enable = s5p6440_sclk1_ctrl,
- },
- .sources = &clkset_group1,
- .reg_src = { .reg = S5P_CLK_SRC1, .shift = 4, .size = 2 },
- .reg_div = { .reg = S5P_CLK_DIV3, .shift = 0, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_fimgvg",
- .id = -1,
- .ctrlbit = (1 << 2),
- .enable = s5p6440_sclk1_ctrl,
- },
- .sources = &clkset_group1,
- .reg_src = { .reg = S5P_CLK_SRC1, .shift = 8, .size = 2 },
- .reg_div = { .reg = S5P_CLK_DIV3, .shift = 4, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_audio2",
- .id = -1,
- .ctrlbit = (1 << 11),
- .enable = s5p6440_sclk_ctrl,
- },
- .sources = &clkset_audio,
- .reg_src = { .reg = S5P_CLK_SRC1, .shift = 0, .size = 3 },
- .reg_div = { .reg = S5P_CLK_DIV2, .shift = 24, .size = 4 },
- },
-};
-
-/* Clock initialisation code */
-static struct clksrc_clk *sysclks[] = {
- &clk_mout_apll,
- &clk_mout_epll,
- &clk_mout_mpll,
- &clk_dout_mpll,
- &clk_armclk,
- &clk_hclk,
- &clk_pclk,
- &clk_hclk_low,
- &clk_pclk_low,
-};
-
-void __init_or_cpufreq s5p6440_setup_clocks(void)
-{
- struct clk *xtal_clk;
- unsigned long xtal;
- unsigned long fclk;
- unsigned long hclk;
- unsigned long hclk_low;
- unsigned long pclk;
- unsigned long pclk_low;
- unsigned long epll;
- unsigned long apll;
- unsigned long mpll;
- unsigned int ptr;
-
- /* Set S5P6440 functions for clk_fout_epll */
- clk_fout_epll.enable = s5p6440_epll_enable;
- clk_fout_epll.ops = &s5p6440_epll_ops;
-
- clk_48m.enable = s5p6440_clk48m_ctrl;
-
- xtal_clk = clk_get(NULL, "ext_xtal");
- BUG_ON(IS_ERR(xtal_clk));
-
- xtal = clk_get_rate(xtal_clk);
- clk_put(xtal_clk);
-
- epll = s5p_get_pll90xx(xtal, __raw_readl(S5P_EPLL_CON),
- __raw_readl(S5P_EPLL_CON_K));
- mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON), pll_4502);
- apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON), pll_4502);
-
- clk_fout_mpll.rate = mpll;
- clk_fout_epll.rate = epll;
- clk_fout_apll.rate = apll;
-
- printk(KERN_INFO "S5P6440: PLL settings, A=%ld.%ldMHz, M=%ld.%ldMHz," \
- " E=%ld.%ldMHz\n",
- print_mhz(apll), print_mhz(mpll), print_mhz(epll));
-
- fclk = clk_get_rate(&clk_armclk.clk);
- hclk = clk_get_rate(&clk_hclk.clk);
- pclk = clk_get_rate(&clk_pclk.clk);
- hclk_low = clk_get_rate(&clk_hclk_low.clk);
- pclk_low = clk_get_rate(&clk_pclk_low.clk);
-
- printk(KERN_INFO "S5P6440: HCLK=%ld.%ldMHz, HCLK_LOW=%ld.%ldMHz," \
- " PCLK=%ld.%ldMHz, PCLK_LOW=%ld.%ldMHz\n",
- print_mhz(hclk), print_mhz(hclk_low),
- print_mhz(pclk), print_mhz(pclk_low));
-
- clk_f.rate = fclk;
- clk_h.rate = hclk;
- clk_p.rate = pclk;
-
- for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
- s3c_set_clksrc(&clksrcs[ptr], true);
-}
-
-static struct clk *clks[] __initdata = {
- &clk_ext,
- &clk_iis_cd_v40,
- &clk_pcm_cd,
-};
-
-void __init s5p6440_register_clocks(void)
-{
- struct clk *clkp;
- int ret;
- int ptr;
-
- ret = s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
- if (ret > 0)
- printk(KERN_ERR "Failed to register %u clocks\n", ret);
-
- for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
- s3c_register_clksrc(sysclks[ptr], 1);
-
- s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
- s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
-
- clkp = init_clocks_disable;
- for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
-
- ret = s3c24xx_register_clock(clkp);
- if (ret < 0) {
- printk(KERN_ERR "Failed to register clock %s (%d)\n",
- clkp->name, ret);
- }
- (clkp->enable)(clkp, 0);
- }
-
- s3c_pwmclk_init();
-}
diff --git a/arch/arm/mach-s5p6440/cpu.c b/arch/arm/mach-s5p6440/cpu.c
deleted file mode 100644
index 526f33adb31d..000000000000
--- a/arch/arm/mach-s5p6440/cpu.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/* linux/arch/arm/mach-s5p6440/cpu.c
- *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/sysdev.h>
-#include <linux/serial_core.h>
-#include <linux/platform_device.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <asm/proc-fns.h>
-
-#include <mach/hardware.h>
-#include <mach/map.h>
-#include <asm/irq.h>
-
-#include <plat/regs-serial.h>
-#include <mach/regs-clock.h>
-
-#include <plat/cpu.h>
-#include <plat/devs.h>
-#include <plat/clock.h>
-#include <plat/s5p6440.h>
-#include <plat/adc-core.h>
-
-static void s5p6440_idle(void)
-{
- unsigned long val;
-
- if (!need_resched()) {
- val = __raw_readl(S5P_PWR_CFG);
- val &= ~(0x3<<5);
- val |= (0x1<<5);
- __raw_writel(val, S5P_PWR_CFG);
-
- cpu_do_idle();
- }
- local_irq_enable();
-}
-
-/* s5p6440_map_io
- *
- * register the standard cpu IO areas
-*/
-
-void __init s5p6440_map_io(void)
-{
- /* initialize any device information early */
- s3c_adc_setname("s3c64xx-adc");
-}
-
-void __init s5p6440_init_clocks(int xtal)
-{
- printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
-
- s3c24xx_register_baseclocks(xtal);
- s5p_register_clocks(xtal);
- s5p6440_register_clocks();
- s5p6440_setup_clocks();
-}
-
-void __init s5p6440_init_irq(void)
-{
- /* S5P6440 supports only 2 VIC */
- u32 vic[2];
-
- /*
- * VIC0 is missing IRQ_VIC0[3, 4, 8, 10, (12-22)]
- * VIC1 is missing IRQ VIC1[1, 3, 4, 10, 11, 12, 14, 15, 22]
- */
- vic[0] = 0xff800ae7;
- vic[1] = 0xffbf23e5;
-
- s5p_init_irq(vic, ARRAY_SIZE(vic));
-}
-
-struct sysdev_class s5p6440_sysclass = {
- .name = "s5p6440-core",
-};
-
-static struct sys_device s5p6440_sysdev = {
- .cls = &s5p6440_sysclass,
-};
-
-static int __init s5p6440_core_init(void)
-{
- return sysdev_class_register(&s5p6440_sysclass);
-}
-
-core_initcall(s5p6440_core_init);
-
-int __init s5p6440_init(void)
-{
- printk(KERN_INFO "S5P6440: Initializing architecture\n");
-
- /* set idle function */
- pm_idle = s5p6440_idle;
-
- return sysdev_register(&s5p6440_sysdev);
-}
diff --git a/arch/arm/mach-s5p6440/dev-audio.c b/arch/arm/mach-s5p6440/dev-audio.c
deleted file mode 100644
index 3ca0d2b8275d..000000000000
--- a/arch/arm/mach-s5p6440/dev-audio.c
+++ /dev/null
@@ -1,127 +0,0 @@
-/* linux/arch/arm/mach-s5p6440/dev-audio.c
- *
- * Copyright (c) 2010 Samsung Electronics Co. Ltd
- * Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <linux/gpio.h>
-
-#include <plat/gpio-cfg.h>
-#include <plat/audio.h>
-
-#include <mach/map.h>
-#include <mach/dma.h>
-#include <mach/irqs.h>
-
-static int s5p6440_cfg_i2s(struct platform_device *pdev)
-{
- /* configure GPIO for i2s port */
- switch (pdev->id) {
- case -1:
- s3c_gpio_cfgpin(S5P6440_GPR(4), S3C_GPIO_SFN(5));
- s3c_gpio_cfgpin(S5P6440_GPR(5), S3C_GPIO_SFN(5));
- s3c_gpio_cfgpin(S5P6440_GPR(6), S3C_GPIO_SFN(5));
- s3c_gpio_cfgpin(S5P6440_GPR(7), S3C_GPIO_SFN(5));
- s3c_gpio_cfgpin(S5P6440_GPR(8), S3C_GPIO_SFN(5));
- s3c_gpio_cfgpin(S5P6440_GPR(13), S3C_GPIO_SFN(5));
- s3c_gpio_cfgpin(S5P6440_GPR(14), S3C_GPIO_SFN(5));
- break;
-
- default:
- printk(KERN_ERR "Invalid Device %d\n", pdev->id);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static struct s3c_audio_pdata s3c_i2s_pdata = {
- .cfg_gpio = s5p6440_cfg_i2s,
-};
-
-static struct resource s5p6440_iis0_resource[] = {
- [0] = {
- .start = S5P6440_PA_I2S,
- .end = S5P6440_PA_I2S + 0x100 - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = DMACH_I2S0_TX,
- .end = DMACH_I2S0_TX,
- .flags = IORESOURCE_DMA,
- },
- [2] = {
- .start = DMACH_I2S0_RX,
- .end = DMACH_I2S0_RX,
- .flags = IORESOURCE_DMA,
- },
-};
-
-struct platform_device s5p6440_device_iis = {
- .name = "s3c64xx-iis-v4",
- .id = -1,
- .num_resources = ARRAY_SIZE(s5p6440_iis0_resource),
- .resource = s5p6440_iis0_resource,
- .dev = {
- .platform_data = &s3c_i2s_pdata,
- },
-};
-
-/* PCM Controller platform_devices */
-
-static int s5p6440_pcm_cfg_gpio(struct platform_device *pdev)
-{
- switch (pdev->id) {
- case 0:
- s3c_gpio_cfgpin(S5P6440_GPR(7), S3C_GPIO_SFN(2));
- s3c_gpio_cfgpin(S5P6440_GPR(13), S3C_GPIO_SFN(2));
- s3c_gpio_cfgpin(S5P6440_GPR(14), S3C_GPIO_SFN(2));
- s3c_gpio_cfgpin(S5P6440_GPR(8), S3C_GPIO_SFN(2));
- s3c_gpio_cfgpin(S5P6440_GPR(6), S3C_GPIO_SFN(2));
- break;
-
- default:
- printk(KERN_DEBUG "Invalid PCM Controller number!");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static struct s3c_audio_pdata s3c_pcm_pdata = {
- .cfg_gpio = s5p6440_pcm_cfg_gpio,
-};
-
-static struct resource s5p6440_pcm0_resource[] = {
- [0] = {
- .start = S5P6440_PA_PCM,
- .end = S5P6440_PA_PCM + 0x100 - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = DMACH_PCM0_TX,
- .end = DMACH_PCM0_TX,
- .flags = IORESOURCE_DMA,
- },
- [2] = {
- .start = DMACH_PCM0_RX,
- .end = DMACH_PCM0_RX,
- .flags = IORESOURCE_DMA,
- },
-};
-
-struct platform_device s5p6440_device_pcm = {
- .name = "samsung-pcm",
- .id = 0,
- .num_resources = ARRAY_SIZE(s5p6440_pcm0_resource),
- .resource = s5p6440_pcm0_resource,
- .dev = {
- .platform_data = &s3c_pcm_pdata,
- },
-};
diff --git a/arch/arm/mach-s5p6440/dev-spi.c b/arch/arm/mach-s5p6440/dev-spi.c
deleted file mode 100644
index 510af44d180c..000000000000
--- a/arch/arm/mach-s5p6440/dev-spi.c
+++ /dev/null
@@ -1,176 +0,0 @@
-/* linux/arch/arm/mach-s5p6440/dev-spi.c
- *
- * Copyright (C) 2010 Samsung Electronics Co. Ltd.
- * Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <linux/gpio.h>
-
-#include <mach/dma.h>
-#include <mach/map.h>
-#include <mach/irqs.h>
-#include <mach/spi-clocks.h>
-
-#include <plat/s3c64xx-spi.h>
-#include <plat/gpio-cfg.h>
-
-static char *spi_src_clks[] = {
- [S5P6440_SPI_SRCCLK_PCLK] = "pclk",
- [S5P6440_SPI_SRCCLK_SCLK] = "spi_epll",
-};
-
-/* SPI Controller platform_devices */
-
-/* Since we emulate multi-cs capability, we do not touch the CS.
- * The emulated CS is toggled by board specific mechanism, as it can
- * be either some immediate GPIO or some signal out of some other
- * chip in between ... or some yet another way.
- * We simply do not assume anything about CS.
- */
-static int s5p6440_spi_cfg_gpio(struct platform_device *pdev)
-{
- switch (pdev->id) {
- case 0:
- s3c_gpio_cfgpin(S5P6440_GPC(0), S3C_GPIO_SFN(2));
- s3c_gpio_cfgpin(S5P6440_GPC(1), S3C_GPIO_SFN(2));
- s3c_gpio_cfgpin(S5P6440_GPC(2), S3C_GPIO_SFN(2));
- s3c_gpio_setpull(S5P6440_GPC(0), S3C_GPIO_PULL_UP);
- s3c_gpio_setpull(S5P6440_GPC(1), S3C_GPIO_PULL_UP);
- s3c_gpio_setpull(S5P6440_GPC(2), S3C_GPIO_PULL_UP);
- break;
-
- case 1:
- s3c_gpio_cfgpin(S5P6440_GPC(4), S3C_GPIO_SFN(2));
- s3c_gpio_cfgpin(S5P6440_GPC(5), S3C_GPIO_SFN(2));
- s3c_gpio_cfgpin(S5P6440_GPC(6), S3C_GPIO_SFN(2));
- s3c_gpio_setpull(S5P6440_GPC(4), S3C_GPIO_PULL_UP);
- s3c_gpio_setpull(S5P6440_GPC(5), S3C_GPIO_PULL_UP);
- s3c_gpio_setpull(S5P6440_GPC(6), S3C_GPIO_PULL_UP);
- break;
-
- default:
- dev_err(&pdev->dev, "Invalid SPI Controller number!");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static struct resource s5p6440_spi0_resource[] = {
- [0] = {
- .start = S5P6440_PA_SPI0,
- .end = S5P6440_PA_SPI0 + 0x100 - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = DMACH_SPI0_TX,
- .end = DMACH_SPI0_TX,
- .flags = IORESOURCE_DMA,
- },
- [2] = {
- .start = DMACH_SPI0_RX,
- .end = DMACH_SPI0_RX,
- .flags = IORESOURCE_DMA,
- },
- [3] = {
- .start = IRQ_SPI0,
- .end = IRQ_SPI0,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct s3c64xx_spi_info s5p6440_spi0_pdata = {
- .cfg_gpio = s5p6440_spi_cfg_gpio,
- .fifo_lvl_mask = 0x1ff,
- .rx_lvl_offset = 15,
-};
-
-static u64 spi_dmamask = DMA_BIT_MASK(32);
-
-struct platform_device s5p6440_device_spi0 = {
- .name = "s3c64xx-spi",
- .id = 0,
- .num_resources = ARRAY_SIZE(s5p6440_spi0_resource),
- .resource = s5p6440_spi0_resource,
- .dev = {
- .dma_mask = &spi_dmamask,
- .coherent_dma_mask = DMA_BIT_MASK(32),
- .platform_data = &s5p6440_spi0_pdata,
- },
-};
-
-static struct resource s5p6440_spi1_resource[] = {
- [0] = {
- .start = S5P6440_PA_SPI1,
- .end = S5P6440_PA_SPI1 + 0x100 - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = DMACH_SPI1_TX,
- .end = DMACH_SPI1_TX,
- .flags = IORESOURCE_DMA,
- },
- [2] = {
- .start = DMACH_SPI1_RX,
- .end = DMACH_SPI1_RX,
- .flags = IORESOURCE_DMA,
- },
- [3] = {
- .start = IRQ_SPI1,
- .end = IRQ_SPI1,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct s3c64xx_spi_info s5p6440_spi1_pdata = {
- .cfg_gpio = s5p6440_spi_cfg_gpio,
- .fifo_lvl_mask = 0x7f,
- .rx_lvl_offset = 15,
-};
-
-struct platform_device s5p6440_device_spi1 = {
- .name = "s3c64xx-spi",
- .id = 1,
- .num_resources = ARRAY_SIZE(s5p6440_spi1_resource),
- .resource = s5p6440_spi1_resource,
- .dev = {
- .dma_mask = &spi_dmamask,
- .coherent_dma_mask = DMA_BIT_MASK(32),
- .platform_data = &s5p6440_spi1_pdata,
- },
-};
-
-void __init s5p6440_spi_set_info(int cntrlr, int src_clk_nr, int num_cs)
-{
- struct s3c64xx_spi_info *pd;
-
- /* Reject invalid configuration */
- if (!num_cs || src_clk_nr < 0
- || src_clk_nr > S5P6440_SPI_SRCCLK_SCLK) {
- printk(KERN_ERR "%s: Invalid SPI configuration\n", __func__);
- return;
- }
-
- switch (cntrlr) {
- case 0:
- pd = &s5p6440_spi0_pdata;
- break;
- case 1:
- pd = &s5p6440_spi1_pdata;
- break;
- default:
- printk(KERN_ERR "%s: Invalid SPI controller(%d)\n",
- __func__, cntrlr);
- return;
- }
-
- pd->num_cs = num_cs;
- pd->src_clk_nr = src_clk_nr;
- pd->src_clk_name = spi_src_clks[src_clk_nr];
-}
diff --git a/arch/arm/mach-s5p6440/include/mach/debug-macro.S b/arch/arm/mach-s5p6440/include/mach/debug-macro.S
deleted file mode 100644
index 1347d7f99079..000000000000
--- a/arch/arm/mach-s5p6440/include/mach/debug-macro.S
+++ /dev/null
@@ -1,37 +0,0 @@
-/* linux/arch/arm/mach-s5p6440/include/mach/debug-macro.S
- *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-/* pull in the relevant register and map files. */
-
-#include <mach/map.h>
-#include <plat/regs-serial.h>
-
- /* note, for the boot process to work we have to keep the UART
- * virtual address aligned to an 1MiB boundary for the L1
- * mapping the head code makes. We keep the UART virtual address
- * aligned and add in the offset when we load the value here.
- */
-
- .macro addruart, rx, rtmp
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1
- ldreq \rx, = S3C_PA_UART
- ldrne \rx, = S3C_VA_UART
-#if CONFIG_DEBUG_S3C_UART != 0
- add \rx, \rx, #(0x400 * CONFIG_DEBUG_S3C_UART)
-#endif
- .endm
-
-/* include the reset of the code which will do the work, we're only
- * compiling for a single cpu processor type so the default of s3c2440
- * will be fine with us.
- */
-
-#include <plat/debug-macro.S>
diff --git a/arch/arm/mach-s5p6440/include/mach/gpio.h b/arch/arm/mach-s5p6440/include/mach/gpio.h
deleted file mode 100644
index 21783834f2a2..000000000000
--- a/arch/arm/mach-s5p6440/include/mach/gpio.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/* linux/arch/arm/mach-s5p6440/include/mach/gpio.h
- *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * S5P6440 - GPIO lib support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_GPIO_H
-#define __ASM_ARCH_GPIO_H __FILE__
-
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-#define gpio_cansleep __gpio_cansleep
-#define gpio_to_irq __gpio_to_irq
-
-/* GPIO bank sizes */
-#define S5P6440_GPIO_A_NR (6)
-#define S5P6440_GPIO_B_NR (7)
-#define S5P6440_GPIO_C_NR (8)
-#define S5P6440_GPIO_F_NR (2)
-#define S5P6440_GPIO_G_NR (7)
-#define S5P6440_GPIO_H_NR (10)
-#define S5P6440_GPIO_I_NR (16)
-#define S5P6440_GPIO_J_NR (12)
-#define S5P6440_GPIO_N_NR (16)
-#define S5P6440_GPIO_P_NR (8)
-#define S5P6440_GPIO_R_NR (15)
-
-/* GPIO bank numbers */
-
-/* CONFIG_S3C_GPIO_SPACE allows the user to select extra
- * space for debugging purposes so that any accidental
- * change from one gpio bank to another can be caught.
-*/
-#define S5P6440_GPIO_NEXT(__gpio) \
- ((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 1)
-
-enum s5p_gpio_number {
- S5P6440_GPIO_A_START = 0,
- S5P6440_GPIO_B_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_A),
- S5P6440_GPIO_C_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_B),
- S5P6440_GPIO_F_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_C),
- S5P6440_GPIO_G_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_F),
- S5P6440_GPIO_H_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_G),
- S5P6440_GPIO_I_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_H),
- S5P6440_GPIO_J_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_I),
- S5P6440_GPIO_N_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_J),
- S5P6440_GPIO_P_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_N),
- S5P6440_GPIO_R_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_P),
-};
-
-/* S5P6440 GPIO number definitions. */
-#define S5P6440_GPA(_nr) (S5P6440_GPIO_A_START + (_nr))
-#define S5P6440_GPB(_nr) (S5P6440_GPIO_B_START + (_nr))
-#define S5P6440_GPC(_nr) (S5P6440_GPIO_C_START + (_nr))
-#define S5P6440_GPF(_nr) (S5P6440_GPIO_F_START + (_nr))
-#define S5P6440_GPG(_nr) (S5P6440_GPIO_G_START + (_nr))
-#define S5P6440_GPH(_nr) (S5P6440_GPIO_H_START + (_nr))
-#define S5P6440_GPI(_nr) (S5P6440_GPIO_I_START + (_nr))
-#define S5P6440_GPJ(_nr) (S5P6440_GPIO_J_START + (_nr))
-#define S5P6440_GPN(_nr) (S5P6440_GPIO_N_START + (_nr))
-#define S5P6440_GPP(_nr) (S5P6440_GPIO_P_START + (_nr))
-#define S5P6440_GPR(_nr) (S5P6440_GPIO_R_START + (_nr))
-
-/* the end of the S5P6440 specific gpios */
-#define S5P6440_GPIO_END (S5P6440_GPR(S5P6440_GPIO_R_NR) + 1)
-#define S3C_GPIO_END S5P6440_GPIO_END
-
-/* define the number of gpios we need to the one after the GPR() range */
-#define ARCH_NR_GPIOS (S5P6440_GPR(S5P6440_GPIO_R_NR) + \
- CONFIG_SAMSUNG_GPIO_EXTRA + 1)
-
-#include <asm-generic/gpio.h>
-
-#endif /* __ASM_ARCH_GPIO_H */
diff --git a/arch/arm/mach-s5p6440/include/mach/io.h b/arch/arm/mach-s5p6440/include/mach/io.h
deleted file mode 100644
index fa2d69cb1ad7..000000000000
--- a/arch/arm/mach-s5p6440/include/mach/io.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* arch/arm/mach-s5p6440/include/mach/io.h
- *
- * Copyright 2008 Simtec Electronics
- * Ben Dooks <ben-linux@fluff.org>
- *
- * Default IO routines for S3C64XX based
- */
-
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-/* No current ISA/PCI bus support. */
-#define __io(a) __typesafe_io(a)
-#define __mem_pci(a) (a)
-
-#define IO_SPACE_LIMIT (0xFFFFFFFF)
-
-#endif
diff --git a/arch/arm/mach-s5p6440/include/mach/map.h b/arch/arm/mach-s5p6440/include/mach/map.h
deleted file mode 100644
index 6cc5cbc88ffb..000000000000
--- a/arch/arm/mach-s5p6440/include/mach/map.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/* linux/arch/arm/mach-s5p6440/include/mach/map.h
- *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * S5P6440 - Memory map definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_MAP_H
-#define __ASM_ARCH_MAP_H __FILE__
-
-#include <plat/map-base.h>
-#include <plat/map-s5p.h>
-
-#define S5P6440_PA_CHIPID (0xE0000000)
-#define S5P_PA_CHIPID S5P6440_PA_CHIPID
-
-#define S5P6440_PA_SYSCON (0xE0100000)
-#define S5P6440_PA_CLK (S5P6440_PA_SYSCON + 0x0)
-#define S5P_PA_SYSCON S5P6440_PA_SYSCON
-
-#define S5P6440_PA_GPIO (0xE0308000)
-#define S5P_PA_GPIO S5P6440_PA_GPIO
-
-#define S5P6440_PA_VIC0 (0xE4000000)
-#define S5P_PA_VIC0 S5P6440_PA_VIC0
-
-#define S5P6440_PA_PDMA 0xE9000000
-
-#define S5P6440_PA_VIC1 (0xE4100000)
-#define S5P_PA_VIC1 S5P6440_PA_VIC1
-
-#define S5P6440_PA_TIMER (0xEA000000)
-#define S5P_PA_TIMER S5P6440_PA_TIMER
-
-#define S5P6440_PA_RTC (0xEA100000)
-
-#define S5P6440_PA_WDT (0xEA200000)
-#define S5P_PA_WDT S5P6440_PA_WDT
-
-#define S5P6440_PA_UART (0xEC000000)
-
-#define S5P_PA_UART0 (S5P6440_PA_UART + 0x0)
-#define S5P_PA_UART1 (S5P6440_PA_UART + 0x400)
-#define S5P_PA_UART2 (S5P6440_PA_UART + 0x800)
-#define S5P_PA_UART3 (S5P6440_PA_UART + 0xC00)
-
-#define S5P_SZ_UART SZ_256
-
-#define S5P6440_PA_IIC0 (0xEC104000)
-#define S5P6440_PA_IIC1 (0xEC20F000)
-
-#define S5P6440_PA_SPI0 0xEC400000
-#define S5P6440_PA_SPI1 0xEC500000
-
-#define S5P6440_PA_HSOTG (0xED100000)
-
-#define S5P6440_PA_HSMMC0 (0xED800000)
-#define S5P6440_PA_HSMMC1 (0xED900000)
-#define S5P6440_PA_HSMMC2 (0xEDA00000)
-
-#define S5P6440_PA_SDRAM (0x20000000)
-#define S5P_PA_SDRAM S5P6440_PA_SDRAM
-
-/* I2S */
-#define S5P6440_PA_I2S 0xF2000000
-
-/* PCM */
-#define S5P6440_PA_PCM 0xF2100000
-
-#define S5P6440_PA_ADC (0xF3000000)
-
-/* compatibiltiy defines. */
-#define S3C_PA_UART S5P6440_PA_UART
-#define S3C_PA_IIC S5P6440_PA_IIC0
-#define S3C_PA_RTC S5P6440_PA_RTC
-#define S3C_PA_IIC1 S5P6440_PA_IIC1
-#define S3C_PA_WDT S5P6440_PA_WDT
-
-#define SAMSUNG_PA_ADC S5P6440_PA_ADC
-
-#endif /* __ASM_ARCH_MAP_H */
diff --git a/arch/arm/mach-s5p6440/include/mach/regs-clock.h b/arch/arm/mach-s5p6440/include/mach/regs-clock.h
deleted file mode 100644
index c783ecc9f193..000000000000
--- a/arch/arm/mach-s5p6440/include/mach/regs-clock.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/* linux/arch/arm/mach-s5p6440/include/mach/regs-clock.h
- *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * S5P6440 - Clock register definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_REGS_CLOCK_H
-#define __ASM_ARCH_REGS_CLOCK_H __FILE__
-
-#include <mach/map.h>
-
-#define S5P_CLKREG(x) (S3C_VA_SYS + (x))
-
-#define S5P_APLL_LOCK S5P_CLKREG(0x00)
-#define S5P_MPLL_LOCK S5P_CLKREG(0x04)
-#define S5P_EPLL_LOCK S5P_CLKREG(0x08)
-#define S5P_APLL_CON S5P_CLKREG(0x0C)
-#define S5P_MPLL_CON S5P_CLKREG(0x10)
-#define S5P_EPLL_CON S5P_CLKREG(0x14)
-#define S5P_EPLL_CON_K S5P_CLKREG(0x18)
-#define S5P_CLK_SRC0 S5P_CLKREG(0x1C)
-#define S5P_CLK_DIV0 S5P_CLKREG(0x20)
-#define S5P_CLK_DIV1 S5P_CLKREG(0x24)
-#define S5P_CLK_DIV2 S5P_CLKREG(0x28)
-#define S5P_CLK_OUT S5P_CLKREG(0x2C)
-#define S5P_CLK_GATE_HCLK0 S5P_CLKREG(0x30)
-#define S5P_CLK_GATE_PCLK S5P_CLKREG(0x34)
-#define S5P_CLK_GATE_SCLK0 S5P_CLKREG(0x38)
-#define S5P_CLK_GATE_MEM0 S5P_CLKREG(0x3C)
-#define S5P_CLK_DIV3 S5P_CLKREG(0x40)
-#define S5P_CLK_GATE_HCLK1 S5P_CLKREG(0x44)
-#define S5P_CLK_GATE_SCLK1 S5P_CLKREG(0x48)
-#define S5P_AHB_CON0 S5P_CLKREG(0x100)
-#define S5P_CLK_SRC1 S5P_CLKREG(0x10C)
-#define S5P_SWRESET S5P_CLKREG(0x114)
-#define S5P_SYS_ID S5P_CLKREG(0x118)
-#define S5P_SYS_OTHERS S5P_CLKREG(0x11C)
-#define S5P_MEM_CFG_STAT S5P_CLKREG(0x12C)
-#define S5P_PWR_CFG S5P_CLKREG(0x804)
-#define S5P_EINT_WAKEUP_MASK S5P_CLKREG(0x808)
-#define S5P_NORMAL_CFG S5P_CLKREG(0x810)
-#define S5P_STOP_CFG S5P_CLKREG(0x814)
-#define S5P_SLEEP_CFG S5P_CLKREG(0x818)
-#define S5P_OSC_FREQ S5P_CLKREG(0x820)
-#define S5P_OSC_STABLE S5P_CLKREG(0x824)
-#define S5P_PWR_STABLE S5P_CLKREG(0x828)
-#define S5P_MTC_STABLE S5P_CLKREG(0x830)
-#define S5P_OTHERS S5P_CLKREG(0x900)
-#define S5P_RST_STAT S5P_CLKREG(0x904)
-#define S5P_WAKEUP_STAT S5P_CLKREG(0x908)
-#define S5P_SLPEN S5P_CLKREG(0x930)
-#define S5P_INFORM0 S5P_CLKREG(0xA00)
-#define S5P_INFORM1 S5P_CLKREG(0xA04)
-#define S5P_INFORM2 S5P_CLKREG(0xA08)
-#define S5P_INFORM3 S5P_CLKREG(0xA0C)
-
-/* CLKDIV0 */
-#define S5P_CLKDIV0_PCLK_MASK (0xf << 12)
-#define S5P_CLKDIV0_PCLK_SHIFT (12)
-#define S5P_CLKDIV0_HCLK_MASK (0xf << 8)
-#define S5P_CLKDIV0_HCLK_SHIFT (8)
-#define S5P_CLKDIV0_MPLL_MASK (0x1 << 4)
-#define S5P_CLKDIV0_ARM_MASK (0xf << 0)
-#define S5P_CLKDIV0_ARM_SHIFT (0)
-
-/* CLKDIV3 */
-#define S5P_CLKDIV3_PCLK_LOW_MASK (0xf << 12)
-#define S5P_CLKDIV3_PCLK_LOW_SHIFT (12)
-#define S5P_CLKDIV3_HCLK_LOW_MASK (0xf << 8)
-#define S5P_CLKDIV3_HCLK_LOW_SHIFT (8)
-
-/* HCLK0 GATE Registers */
-#define S5P_CLKCON_HCLK0_USB (1<<20)
-#define S5P_CLKCON_HCLK0_HSMMC2 (1<<19)
-#define S5P_CLKCON_HCLK0_HSMMC1 (1<<18)
-#define S5P_CLKCON_HCLK0_HSMMC0 (1<<17)
-#define S5P_CLKCON_HCLK0_POST0 (1<<5)
-
-/* HCLK1 GATE Registers */
-#define S5P_CLKCON_HCLK1_DISPCON (1<<1)
-
-/* PCLK GATE Registers */
-#define S5P_CLKCON_PCLK_IIS2 (1<<26)
-#define S5P_CLKCON_PCLK_SPI1 (1<<22)
-#define S5P_CLKCON_PCLK_SPI0 (1<<21)
-#define S5P_CLKCON_PCLK_GPIO (1<<18)
-#define S5P_CLKCON_PCLK_IIC0 (1<<17)
-#define S5P_CLKCON_PCLK_TSADC (1<<12)
-#define S5P_CLKCON_PCLK_PWM (1<<7)
-#define S5P_CLKCON_PCLK_RTC (1<<6)
-#define S5P_CLKCON_PCLK_WDT (1<<5)
-#define S5P_CLKCON_PCLK_UART3 (1<<4)
-#define S5P_CLKCON_PCLK_UART2 (1<<3)
-#define S5P_CLKCON_PCLK_UART1 (1<<2)
-#define S5P_CLKCON_PCLK_UART0 (1<<1)
-
-/* SCLK0 GATE Registers */
-#define S5P_CLKCON_SCLK0_MMC2_48 (1<<29)
-#define S5P_CLKCON_SCLK0_MMC1_48 (1<<28)
-#define S5P_CLKCON_SCLK0_MMC0_48 (1<<27)
-#define S5P_CLKCON_SCLK0_MMC2 (1<<26)
-#define S5P_CLKCON_SCLK0_MMC1 (1<<25)
-#define S5P_CLKCON_SCLK0_MMC0 (1<<24)
-#define S5P_CLKCON_SCLK0_SPI1_48 (1<<23)
-#define S5P_CLKCON_SCLK0_SPI0_48 (1<<22)
-#define S5P_CLKCON_SCLK0_SPI1 (1<<21)
-#define S5P_CLKCON_SCLK0_SPI0 (1<<20)
-#define S5P_CLKCON_SCLK0_UART (1<<5)
-
-/* SCLK1 GATE Registers */
-
-/* MEM0 GATE Registers */
-#define S5P_CLKCON_MEM0_HCLK_NFCON (1<<2)
-
-/*OTHERS Resgister */
-#define S5P_OTHERS_USB_SIG_MASK (1<<16)
-#define S5P_OTHERS_HCLK_LOW_SEL_MPLL (1<<6)
-
-/* Compatibility defines */
-#define ARM_CLK_DIV S5P_CLK_DIV0
-#define ARM_DIV_RATIO_SHIFT 0
-#define ARM_DIV_MASK (0xf << ARM_DIV_RATIO_SHIFT)
-
-#endif /* __ASM_ARCH_REGS_CLOCK_H */
diff --git a/arch/arm/mach-s5p6440/include/mach/spi-clocks.h b/arch/arm/mach-s5p6440/include/mach/spi-clocks.h
deleted file mode 100644
index 5fbca50d1cfb..000000000000
--- a/arch/arm/mach-s5p6440/include/mach/spi-clocks.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* linux/arch/arm/mach-s5p6440/include/mach/spi-clocks.h
- *
- * Copyright (C) 2010 Samsung Electronics Co. Ltd.
- * Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __S5P6440_PLAT_SPI_CLKS_H
-#define __S5P6440_PLAT_SPI_CLKS_H __FILE__
-
-#define S5P6440_SPI_SRCCLK_PCLK 0
-#define S5P6440_SPI_SRCCLK_SCLK 1
-
-#endif /* __S5P6440_PLAT_SPI_CLKS_H */
diff --git a/arch/arm/mach-s5p6440/include/mach/uncompress.h b/arch/arm/mach-s5p6440/include/mach/uncompress.h
deleted file mode 100644
index 7c1f600d65c0..000000000000
--- a/arch/arm/mach-s5p6440/include/mach/uncompress.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* linux/arch/arm/mach-s5p6440/include/mach/uncompress.h
- *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * S5P6440 - uncompress code
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_UNCOMPRESS_H
-#define __ASM_ARCH_UNCOMPRESS_H
-
-#include <mach/map.h>
-#include <plat/uncompress.h>
-
-static void arch_detect_cpu(void)
-{
- /* we do not need to do any cpu detection here at the moment. */
-}
-
-#endif /* __ASM_ARCH_UNCOMPRESS_H */
diff --git a/arch/arm/mach-s5p6440/init.c b/arch/arm/mach-s5p6440/init.c
deleted file mode 100644
index a1f3727e4021..000000000000
--- a/arch/arm/mach-s5p6440/init.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/* linux/arch/arm/mach-s5p6440/init.c
- *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * S5P6440 - Init support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/serial_core.h>
-
-#include <plat/cpu.h>
-#include <plat/devs.h>
-#include <plat/s5p6440.h>
-#include <plat/regs-serial.h>
-
-static struct s3c24xx_uart_clksrc s5p6440_serial_clocks[] = {
- [0] = {
- .name = "pclk_low",
- .divisor = 1,
- .min_baud = 0,
- .max_baud = 0,
- },
- [1] = {
- .name = "uclk1",
- .divisor = 1,
- .min_baud = 0,
- .max_baud = 0,
- },
-};
-
-/* uart registration process */
-void __init s5p6440_common_init_uarts(struct s3c2410_uartcfg *cfg, int no)
-{
- struct s3c2410_uartcfg *tcfg = cfg;
- u32 ucnt;
-
- for (ucnt = 0; ucnt < no; ucnt++, tcfg++) {
- if (!tcfg->clocks) {
- tcfg->clocks = s5p6440_serial_clocks;
- tcfg->clocks_size = ARRAY_SIZE(s5p6440_serial_clocks);
- }
- }
-
- s3c24xx_init_uartdevs("s3c6400-uart", s5p_uart_resources, cfg, no);
-}
diff --git a/arch/arm/mach-s5p6442/cpu.c b/arch/arm/mach-s5p6442/cpu.c
index a48fb553fd01..842af86bda6d 100644
--- a/arch/arm/mach-s5p6442/cpu.c
+++ b/arch/arm/mach-s5p6442/cpu.c
@@ -1,7 +1,7 @@
/* linux/arch/arm/mach-s5p6442/cpu.c
*
* Copyright (c) 2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
+ * http://www.samsung.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -19,6 +19,7 @@
#include <linux/sysdev.h>
#include <linux/serial_core.h>
#include <linux/platform_device.h>
+#include <linux/sched.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
@@ -47,10 +48,30 @@ static struct map_desc s5p6442_iodesc[] __initdata = {
.length = SZ_16K,
.type = MT_DEVICE,
}, {
+ .virtual = (unsigned long)S5P_VA_GPIO,
+ .pfn = __phys_to_pfn(S5P6442_PA_GPIO),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = (unsigned long)VA_VIC0,
+ .pfn = __phys_to_pfn(S5P6442_PA_VIC0),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = (unsigned long)VA_VIC1,
+ .pfn = __phys_to_pfn(S5P6442_PA_VIC1),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ }, {
.virtual = (unsigned long)VA_VIC2,
.pfn = __phys_to_pfn(S5P6442_PA_VIC2),
.length = SZ_16K,
.type = MT_DEVICE,
+ }, {
+ .virtual = (unsigned long)S3C_VA_UART,
+ .pfn = __phys_to_pfn(S3C_PA_UART),
+ .length = SZ_512K,
+ .type = MT_DEVICE,
}
};
@@ -62,10 +83,11 @@ static void s5p6442_idle(void)
local_irq_enable();
}
-/* s5p6442_map_io
+/*
+ * s5p6442_map_io
*
* register the standard cpu IO areas
-*/
+ */
void __init s5p6442_map_io(void)
{
diff --git a/arch/arm/mach-s5p6442/include/mach/debug-macro.S b/arch/arm/mach-s5p6442/include/mach/debug-macro.S
index bb6536147ffb..e2213205d780 100644
--- a/arch/arm/mach-s5p6442/include/mach/debug-macro.S
+++ b/arch/arm/mach-s5p6442/include/mach/debug-macro.S
@@ -15,13 +15,12 @@
#include <mach/map.h>
#include <plat/regs-serial.h>
- .macro addruart, rx, rtmp
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1
- ldreq \rx, = S3C_PA_UART
- ldrne \rx, = S3C_VA_UART
+ .macro addruart, rp, rv
+ ldr \rp, = S3C_PA_UART
+ ldr \rv, = S3C_VA_UART
#if CONFIG_DEBUG_S3C_UART != 0
- add \rx, \rx, #(0x400 * CONFIG_DEBUG_S3C_UART)
+ add \rp, \rp, #(0x400 * CONFIG_DEBUG_S3C_UART)
+ add \rv, \rv, #(0x400 * CONFIG_DEBUG_S3C_UART)
#endif
.endm
diff --git a/arch/arm/mach-s5p6442/include/mach/map.h b/arch/arm/mach-s5p6442/include/mach/map.h
index 281d256faafb..31fb2e68d527 100644
--- a/arch/arm/mach-s5p6442/include/mach/map.h
+++ b/arch/arm/mach-s5p6442/include/mach/map.h
@@ -23,16 +23,10 @@
#define S5P_PA_SYSCON S5P6442_PA_SYSCON
#define S5P6442_PA_GPIO (0xE0200000)
-#define S5P_PA_GPIO S5P6442_PA_GPIO
#define S5P6442_PA_VIC0 (0xE4000000)
-#define S5P_PA_VIC0 S5P6442_PA_VIC0
-
#define S5P6442_PA_VIC1 (0xE4100000)
-#define S5P_PA_VIC1 S5P6442_PA_VIC1
-
#define S5P6442_PA_VIC2 (0xE4200000)
-#define S5P_PA_VIC2 S5P6442_PA_VIC2
#define S5P6442_PA_MDMA 0xE8000000
#define S5P6442_PA_PDMA 0xE9000000
diff --git a/arch/arm/mach-s5p6442/mach-smdk6442.c b/arch/arm/mach-s5p6442/mach-smdk6442.c
index 8d8d04272f85..819fd80d00af 100644
--- a/arch/arm/mach-s5p6442/mach-smdk6442.c
+++ b/arch/arm/mach-s5p6442/mach-smdk6442.c
@@ -83,8 +83,6 @@ static void __init smdk6442_machine_init(void)
MACHINE_START(SMDK6442, "SMDK6442")
/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
- .phys_io = S3C_PA_UART & 0xfff00000,
- .io_pg_offst = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
.boot_params = S5P_PA_SDRAM + 0x100,
.init_irq = s5p6442_init_irq,
.map_io = smdk6442_map_io,
diff --git a/arch/arm/mach-s5p64x0/Kconfig b/arch/arm/mach-s5p64x0/Kconfig
new file mode 100644
index 000000000000..fbcae9352022
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/Kconfig
@@ -0,0 +1,57 @@
+# arch/arm/mach-s5p64x0/Kconfig
+#
+# Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+# http://www.samsung.com/
+#
+# Licensed under GPLv2
+
+if ARCH_S5P64X0
+
+config CPU_S5P6440
+ bool
+ select PLAT_S5P
+ select S3C_PL330_DMA
+ help
+ Enable S5P6440 CPU support
+
+config CPU_S5P6450
+ bool
+ select PLAT_S5P
+ select S3C_PL330_DMA
+ help
+ Enable S5P6450 CPU support
+
+config S5P64X0_SETUP_I2C1
+ bool
+ help
+ Common setup code for i2c bus 1.
+
+# machine support
+
+config MACH_SMDK6440
+ bool "SMDK6440"
+ select CPU_S5P6440
+ select S3C_DEV_I2C1
+ select S3C_DEV_RTC
+ select S3C_DEV_WDT
+ select S3C64XX_DEV_SPI
+ select SAMSUNG_DEV_ADC
+ select SAMSUNG_DEV_TS
+ select S5P64X0_SETUP_I2C1
+ help
+ Machine support for the Samsung SMDK6440
+
+config MACH_SMDK6450
+ bool "SMDK6450"
+ select CPU_S5P6450
+ select S3C_DEV_I2C1
+ select S3C_DEV_RTC
+ select S3C_DEV_WDT
+ select S3C64XX_DEV_SPI
+ select SAMSUNG_DEV_ADC
+ select SAMSUNG_DEV_TS
+ select S5P64X0_SETUP_I2C1
+ help
+ Machine support for the Samsung SMDK6450
+
+endif
diff --git a/arch/arm/mach-s5p64x0/Makefile b/arch/arm/mach-s5p64x0/Makefile
new file mode 100644
index 000000000000..2655829e6bf8
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/Makefile
@@ -0,0 +1,30 @@
+# arch/arm/mach-s5p64x0/Makefile
+#
+# Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+# http://www.samsung.com
+#
+# Licensed under GPLv2
+
+obj-y :=
+obj-m :=
+obj-n :=
+obj- :=
+
+# Core support for S5P64X0 system
+
+obj-$(CONFIG_ARCH_S5P64X0) += cpu.o init.o clock.o dma.o
+obj-$(CONFIG_ARCH_S5P64X0) += setup-i2c0.o
+obj-$(CONFIG_CPU_S5P6440) += clock-s5p6440.o gpio.o
+obj-$(CONFIG_CPU_S5P6450) += clock-s5p6450.o
+
+# machine support
+
+obj-$(CONFIG_MACH_SMDK6440) += mach-smdk6440.o
+obj-$(CONFIG_MACH_SMDK6450) += mach-smdk6450.o
+
+# device support
+
+obj-y += dev-audio.o
+obj-$(CONFIG_S3C64XX_DEV_SPI) += dev-spi.o
+
+obj-$(CONFIG_S5P64X0_SETUP_I2C1) += setup-i2c1.o
diff --git a/arch/arm/mach-s5p6440/Makefile.boot b/arch/arm/mach-s5p64x0/Makefile.boot
index ff90aa13bd67..ff90aa13bd67 100644
--- a/arch/arm/mach-s5p6440/Makefile.boot
+++ b/arch/arm/mach-s5p64x0/Makefile.boot
diff --git a/arch/arm/mach-s5p64x0/clock-s5p6440.c b/arch/arm/mach-s5p64x0/clock-s5p6440.c
new file mode 100644
index 000000000000..f93dcd8b4d6a
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/clock-s5p6440.c
@@ -0,0 +1,626 @@
+/* linux/arch/arm/mach-s5p64x0/clock-s5p6440.c
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * S5P6440 - Clock support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/sysdev.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#include <mach/s5p64x0-clock.h>
+
+#include <plat/cpu-freq.h>
+#include <plat/clock.h>
+#include <plat/cpu.h>
+#include <plat/pll.h>
+#include <plat/s5p-clock.h>
+#include <plat/clock-clksrc.h>
+#include <plat/s5p6440.h>
+
+static u32 epll_div[][5] = {
+ { 36000000, 0, 48, 1, 4 },
+ { 48000000, 0, 32, 1, 3 },
+ { 60000000, 0, 40, 1, 3 },
+ { 72000000, 0, 48, 1, 3 },
+ { 84000000, 0, 28, 1, 2 },
+ { 96000000, 0, 32, 1, 2 },
+ { 32768000, 45264, 43, 1, 4 },
+ { 45158000, 6903, 30, 1, 3 },
+ { 49152000, 50332, 32, 1, 3 },
+ { 67738000, 10398, 45, 1, 3 },
+ { 73728000, 9961, 49, 1, 3 }
+};
+
+static int s5p6440_epll_set_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned int epll_con, epll_con_k;
+ unsigned int i;
+
+ if (clk->rate == rate) /* Return if nothing changed */
+ return 0;
+
+ epll_con = __raw_readl(S5P64X0_EPLL_CON);
+ epll_con_k = __raw_readl(S5P64X0_EPLL_CON_K);
+
+ epll_con_k &= ~(PLL90XX_KDIV_MASK);
+ epll_con &= ~(PLL90XX_MDIV_MASK | PLL90XX_PDIV_MASK | PLL90XX_SDIV_MASK);
+
+ for (i = 0; i < ARRAY_SIZE(epll_div); i++) {
+ if (epll_div[i][0] == rate) {
+ epll_con_k |= (epll_div[i][1] << PLL90XX_KDIV_SHIFT);
+ epll_con |= (epll_div[i][2] << PLL90XX_MDIV_SHIFT) |
+ (epll_div[i][3] << PLL90XX_PDIV_SHIFT) |
+ (epll_div[i][4] << PLL90XX_SDIV_SHIFT);
+ break;
+ }
+ }
+
+ if (i == ARRAY_SIZE(epll_div)) {
+ printk(KERN_ERR "%s: Invalid Clock EPLL Frequency\n", __func__);
+ return -EINVAL;
+ }
+
+ __raw_writel(epll_con, S5P64X0_EPLL_CON);
+ __raw_writel(epll_con_k, S5P64X0_EPLL_CON_K);
+
+ clk->rate = rate;
+
+ return 0;
+}
+
+static struct clk_ops s5p6440_epll_ops = {
+ .get_rate = s5p64x0_epll_get_rate,
+ .set_rate = s5p6440_epll_set_rate,
+};
+
+static struct clksrc_clk clk_hclk = {
+ .clk = {
+ .name = "clk_hclk",
+ .id = -1,
+ .parent = &clk_armclk.clk,
+ },
+ .reg_div = { .reg = S5P64X0_CLK_DIV0, .shift = 8, .size = 4 },
+};
+
+static struct clksrc_clk clk_pclk = {
+ .clk = {
+ .name = "clk_pclk",
+ .id = -1,
+ .parent = &clk_hclk.clk,
+ },
+ .reg_div = { .reg = S5P64X0_CLK_DIV0, .shift = 12, .size = 4 },
+};
+static struct clksrc_clk clk_hclk_low = {
+ .clk = {
+ .name = "clk_hclk_low",
+ .id = -1,
+ },
+ .sources = &clkset_hclk_low,
+ .reg_src = { .reg = S5P64X0_SYS_OTHERS, .shift = 6, .size = 1 },
+ .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 8, .size = 4 },
+};
+
+static struct clksrc_clk clk_pclk_low = {
+ .clk = {
+ .name = "clk_pclk_low",
+ .id = -1,
+ .parent = &clk_hclk_low.clk,
+ },
+ .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 12, .size = 4 },
+};
+
+/*
+ * The following clocks will be disabled during clock initialization. It is
+ * recommended to keep the following clocks disabled until the driver requests
+ * for enabling the clock.
+ */
+static struct clk init_clocks_disable[] = {
+ {
+ .name = "nand",
+ .id = -1,
+ .parent = &clk_hclk.clk,
+ .enable = s5p64x0_mem_ctrl,
+ .ctrlbit = (1 << 2),
+ }, {
+ .name = "post",
+ .id = -1,
+ .parent = &clk_hclk_low.clk,
+ .enable = s5p64x0_hclk0_ctrl,
+ .ctrlbit = (1 << 5)
+ }, {
+ .name = "2d",
+ .id = -1,
+ .parent = &clk_hclk.clk,
+ .enable = s5p64x0_hclk0_ctrl,
+ .ctrlbit = (1 << 8),
+ }, {
+ .name = "hsmmc",
+ .id = 0,
+ .parent = &clk_hclk_low.clk,
+ .enable = s5p64x0_hclk0_ctrl,
+ .ctrlbit = (1 << 17),
+ }, {
+ .name = "hsmmc",
+ .id = 1,
+ .parent = &clk_hclk_low.clk,
+ .enable = s5p64x0_hclk0_ctrl,
+ .ctrlbit = (1 << 18),
+ }, {
+ .name = "hsmmc",
+ .id = 2,
+ .parent = &clk_hclk_low.clk,
+ .enable = s5p64x0_hclk0_ctrl,
+ .ctrlbit = (1 << 19),
+ }, {
+ .name = "otg",
+ .id = -1,
+ .parent = &clk_hclk_low.clk,
+ .enable = s5p64x0_hclk0_ctrl,
+ .ctrlbit = (1 << 20)
+ }, {
+ .name = "irom",
+ .id = -1,
+ .parent = &clk_hclk.clk,
+ .enable = s5p64x0_hclk0_ctrl,
+ .ctrlbit = (1 << 25),
+ }, {
+ .name = "lcd",
+ .id = -1,
+ .parent = &clk_hclk_low.clk,
+ .enable = s5p64x0_hclk1_ctrl,
+ .ctrlbit = (1 << 1),
+ }, {
+ .name = "hclk_fimgvg",
+ .id = -1,
+ .parent = &clk_hclk.clk,
+ .enable = s5p64x0_hclk1_ctrl,
+ .ctrlbit = (1 << 2),
+ }, {
+ .name = "tsi",
+ .id = -1,
+ .parent = &clk_hclk_low.clk,
+ .enable = s5p64x0_hclk1_ctrl,
+ .ctrlbit = (1 << 0),
+ }, {
+ .name = "watchdog",
+ .id = -1,
+ .parent = &clk_pclk_low.clk,
+ .enable = s5p64x0_pclk_ctrl,
+ .ctrlbit = (1 << 5),
+ }, {
+ .name = "rtc",
+ .id = -1,
+ .parent = &clk_pclk_low.clk,
+ .enable = s5p64x0_pclk_ctrl,
+ .ctrlbit = (1 << 6),
+ }, {
+ .name = "timers",
+ .id = -1,
+ .parent = &clk_pclk_low.clk,
+ .enable = s5p64x0_pclk_ctrl,
+ .ctrlbit = (1 << 7),
+ }, {
+ .name = "pcm",
+ .id = -1,
+ .parent = &clk_pclk_low.clk,
+ .enable = s5p64x0_pclk_ctrl,
+ .ctrlbit = (1 << 8),
+ }, {
+ .name = "adc",
+ .id = -1,
+ .parent = &clk_pclk_low.clk,
+ .enable = s5p64x0_pclk_ctrl,
+ .ctrlbit = (1 << 12),
+ }, {
+ .name = "i2c",
+ .id = -1,
+ .parent = &clk_pclk_low.clk,
+ .enable = s5p64x0_pclk_ctrl,
+ .ctrlbit = (1 << 17),
+ }, {
+ .name = "spi",
+ .id = 0,
+ .parent = &clk_pclk_low.clk,
+ .enable = s5p64x0_pclk_ctrl,
+ .ctrlbit = (1 << 21),
+ }, {
+ .name = "spi",
+ .id = 1,
+ .parent = &clk_pclk_low.clk,
+ .enable = s5p64x0_pclk_ctrl,
+ .ctrlbit = (1 << 22),
+ }, {
+ .name = "gps",
+ .id = -1,
+ .parent = &clk_pclk_low.clk,
+ .enable = s5p64x0_pclk_ctrl,
+ .ctrlbit = (1 << 25),
+ }, {
+ .name = "i2s_v40",
+ .id = 0,
+ .parent = &clk_pclk_low.clk,
+ .enable = s5p64x0_pclk_ctrl,
+ .ctrlbit = (1 << 26),
+ }, {
+ .name = "dsim",
+ .id = -1,
+ .parent = &clk_pclk_low.clk,
+ .enable = s5p64x0_pclk_ctrl,
+ .ctrlbit = (1 << 28),
+ }, {
+ .name = "etm",
+ .id = -1,
+ .parent = &clk_pclk.clk,
+ .enable = s5p64x0_pclk_ctrl,
+ .ctrlbit = (1 << 29),
+ }, {
+ .name = "dmc0",
+ .id = -1,
+ .parent = &clk_pclk.clk,
+ .enable = s5p64x0_pclk_ctrl,
+ .ctrlbit = (1 << 30),
+ }, {
+ .name = "pclk_fimgvg",
+ .id = -1,
+ .parent = &clk_pclk.clk,
+ .enable = s5p64x0_pclk_ctrl,
+ .ctrlbit = (1 << 31),
+ }, {
+ .name = "sclk_spi_48",
+ .id = 0,
+ .parent = &clk_48m,
+ .enable = s5p64x0_sclk_ctrl,
+ .ctrlbit = (1 << 22),
+ }, {
+ .name = "sclk_spi_48",
+ .id = 1,
+ .parent = &clk_48m,
+ .enable = s5p64x0_sclk_ctrl,
+ .ctrlbit = (1 << 23),
+ }, {
+ .name = "mmc_48m",
+ .id = 0,
+ .parent = &clk_48m,
+ .enable = s5p64x0_sclk_ctrl,
+ .ctrlbit = (1 << 27),
+ }, {
+ .name = "mmc_48m",
+ .id = 1,
+ .parent = &clk_48m,
+ .enable = s5p64x0_sclk_ctrl,
+ .ctrlbit = (1 << 28),
+ }, {
+ .name = "mmc_48m",
+ .id = 2,
+ .parent = &clk_48m,
+ .enable = s5p64x0_sclk_ctrl,
+ .ctrlbit = (1 << 29),
+ },
+};
+
+/*
+ * The following clocks will be enabled during clock initialization.
+ */
+static struct clk init_clocks[] = {
+ {
+ .name = "intc",
+ .id = -1,
+ .parent = &clk_hclk.clk,
+ .enable = s5p64x0_hclk0_ctrl,
+ .ctrlbit = (1 << 1),
+ }, {
+ .name = "mem",
+ .id = -1,
+ .parent = &clk_hclk.clk,
+ .enable = s5p64x0_hclk0_ctrl,
+ .ctrlbit = (1 << 21),
+ }, {
+ .name = "dma",
+ .id = -1,
+ .parent = &clk_hclk_low.clk,
+ .enable = s5p64x0_hclk0_ctrl,
+ .ctrlbit = (1 << 12),
+ }, {
+ .name = "uart",
+ .id = 0,
+ .parent = &clk_pclk_low.clk,
+ .enable = s5p64x0_pclk_ctrl,
+ .ctrlbit = (1 << 1),
+ }, {
+ .name = "uart",
+ .id = 1,
+ .parent = &clk_pclk_low.clk,
+ .enable = s5p64x0_pclk_ctrl,
+ .ctrlbit = (1 << 2),
+ }, {
+ .name = "uart",
+ .id = 2,
+ .parent = &clk_pclk_low.clk,
+ .enable = s5p64x0_pclk_ctrl,
+ .ctrlbit = (1 << 3),
+ }, {
+ .name = "uart",
+ .id = 3,
+ .parent = &clk_pclk_low.clk,
+ .enable = s5p64x0_pclk_ctrl,
+ .ctrlbit = (1 << 4),
+ }, {
+ .name = "gpio",
+ .id = -1,
+ .parent = &clk_pclk_low.clk,
+ .enable = s5p64x0_pclk_ctrl,
+ .ctrlbit = (1 << 18),
+ },
+};
+
+static struct clk clk_iis_cd_v40 = {
+ .name = "iis_cdclk_v40",
+ .id = -1,
+};
+
+static struct clk clk_pcm_cd = {
+ .name = "pcm_cdclk",
+ .id = -1,
+};
+
+static struct clk *clkset_group1_list[] = {
+ &clk_mout_epll.clk,
+ &clk_dout_mpll.clk,
+ &clk_fin_epll,
+};
+
+static struct clksrc_sources clkset_group1 = {
+ .sources = clkset_group1_list,
+ .nr_sources = ARRAY_SIZE(clkset_group1_list),
+};
+
+static struct clk *clkset_uart_list[] = {
+ &clk_mout_epll.clk,
+ &clk_dout_mpll.clk,
+};
+
+static struct clksrc_sources clkset_uart = {
+ .sources = clkset_uart_list,
+ .nr_sources = ARRAY_SIZE(clkset_uart_list),
+};
+
+static struct clk *clkset_audio_list[] = {
+ &clk_mout_epll.clk,
+ &clk_dout_mpll.clk,
+ &clk_fin_epll,
+ &clk_iis_cd_v40,
+ &clk_pcm_cd,
+};
+
+static struct clksrc_sources clkset_audio = {
+ .sources = clkset_audio_list,
+ .nr_sources = ARRAY_SIZE(clkset_audio_list),
+};
+
+static struct clksrc_clk clksrcs[] = {
+ {
+ .clk = {
+ .name = "mmc_bus",
+ .id = 0,
+ .ctrlbit = (1 << 24),
+ .enable = s5p64x0_sclk_ctrl,
+ },
+ .sources = &clkset_group1,
+ .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 18, .size = 2 },
+ .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 0, .size = 4 },
+ }, {
+ .clk = {
+ .name = "mmc_bus",
+ .id = 1,
+ .ctrlbit = (1 << 25),
+ .enable = s5p64x0_sclk_ctrl,
+ },
+ .sources = &clkset_group1,
+ .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 20, .size = 2 },
+ .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 4, .size = 4 },
+ }, {
+ .clk = {
+ .name = "mmc_bus",
+ .id = 2,
+ .ctrlbit = (1 << 26),
+ .enable = s5p64x0_sclk_ctrl,
+ },
+ .sources = &clkset_group1,
+ .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 22, .size = 2 },
+ .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 8, .size = 4 },
+ }, {
+ .clk = {
+ .name = "uclk1",
+ .id = -1,
+ .ctrlbit = (1 << 5),
+ .enable = s5p64x0_sclk_ctrl,
+ },
+ .sources = &clkset_uart,
+ .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 13, .size = 1 },
+ .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 16, .size = 4 },
+ }, {
+ .clk = {
+ .name = "sclk_spi",
+ .id = 0,
+ .ctrlbit = (1 << 20),
+ .enable = s5p64x0_sclk_ctrl,
+ },
+ .sources = &clkset_group1,
+ .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 14, .size = 2 },
+ .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 0, .size = 4 },
+ }, {
+ .clk = {
+ .name = "sclk_spi",
+ .id = 1,
+ .ctrlbit = (1 << 21),
+ .enable = s5p64x0_sclk_ctrl,
+ },
+ .sources = &clkset_group1,
+ .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 16, .size = 2 },
+ .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 4, .size = 4 },
+ }, {
+ .clk = {
+ .name = "sclk_post",
+ .id = -1,
+ .ctrlbit = (1 << 10),
+ .enable = s5p64x0_sclk_ctrl,
+ },
+ .sources = &clkset_group1,
+ .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 26, .size = 2 },
+ .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 12, .size = 4 },
+ }, {
+ .clk = {
+ .name = "sclk_dispcon",
+ .id = -1,
+ .ctrlbit = (1 << 1),
+ .enable = s5p64x0_sclk1_ctrl,
+ },
+ .sources = &clkset_group1,
+ .reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 4, .size = 2 },
+ .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 0, .size = 4 },
+ }, {
+ .clk = {
+ .name = "sclk_fimgvg",
+ .id = -1,
+ .ctrlbit = (1 << 2),
+ .enable = s5p64x0_sclk1_ctrl,
+ },
+ .sources = &clkset_group1,
+ .reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 8, .size = 2 },
+ .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 4, .size = 4 },
+ }, {
+ .clk = {
+ .name = "sclk_audio2",
+ .id = -1,
+ .ctrlbit = (1 << 11),
+ .enable = s5p64x0_sclk_ctrl,
+ },
+ .sources = &clkset_audio,
+ .reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 0, .size = 3 },
+ .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 24, .size = 4 },
+ },
+};
+
+/* Clock initialization code */
+static struct clksrc_clk *sysclks[] = {
+ &clk_mout_apll,
+ &clk_mout_epll,
+ &clk_mout_mpll,
+ &clk_dout_mpll,
+ &clk_armclk,
+ &clk_hclk,
+ &clk_pclk,
+ &clk_hclk_low,
+ &clk_pclk_low,
+};
+
+void __init_or_cpufreq s5p6440_setup_clocks(void)
+{
+ struct clk *xtal_clk;
+
+ unsigned long xtal;
+ unsigned long fclk;
+ unsigned long hclk;
+ unsigned long hclk_low;
+ unsigned long pclk;
+ unsigned long pclk_low;
+
+ unsigned long apll;
+ unsigned long mpll;
+ unsigned long epll;
+ unsigned int ptr;
+
+ /* Set S5P6440 functions for clk_fout_epll */
+
+ clk_fout_epll.enable = s5p64x0_epll_enable;
+ clk_fout_epll.ops = &s5p6440_epll_ops;
+
+ clk_48m.enable = s5p64x0_clk48m_ctrl;
+
+ xtal_clk = clk_get(NULL, "ext_xtal");
+ BUG_ON(IS_ERR(xtal_clk));
+
+ xtal = clk_get_rate(xtal_clk);
+ clk_put(xtal_clk);
+
+ apll = s5p_get_pll45xx(xtal, __raw_readl(S5P64X0_APLL_CON), pll_4502);
+ mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P64X0_MPLL_CON), pll_4502);
+ epll = s5p_get_pll90xx(xtal, __raw_readl(S5P64X0_EPLL_CON),
+ __raw_readl(S5P64X0_EPLL_CON_K));
+
+ clk_fout_apll.rate = apll;
+ clk_fout_mpll.rate = mpll;
+ clk_fout_epll.rate = epll;
+
+ printk(KERN_INFO "S5P6440: PLL settings, A=%ld.%ldMHz, M=%ld.%ldMHz," \
+ " E=%ld.%ldMHz\n",
+ print_mhz(apll), print_mhz(mpll), print_mhz(epll));
+
+ fclk = clk_get_rate(&clk_armclk.clk);
+ hclk = clk_get_rate(&clk_hclk.clk);
+ pclk = clk_get_rate(&clk_pclk.clk);
+ hclk_low = clk_get_rate(&clk_hclk_low.clk);
+ pclk_low = clk_get_rate(&clk_pclk_low.clk);
+
+ printk(KERN_INFO "S5P6440: HCLK=%ld.%ldMHz, HCLK_LOW=%ld.%ldMHz," \
+ " PCLK=%ld.%ldMHz, PCLK_LOW=%ld.%ldMHz\n",
+ print_mhz(hclk), print_mhz(hclk_low),
+ print_mhz(pclk), print_mhz(pclk_low));
+
+ clk_f.rate = fclk;
+ clk_h.rate = hclk;
+ clk_p.rate = pclk;
+
+ for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
+ s3c_set_clksrc(&clksrcs[ptr], true);
+}
+
+static struct clk *clks[] __initdata = {
+ &clk_ext,
+ &clk_iis_cd_v40,
+ &clk_pcm_cd,
+};
+
+void __init s5p6440_register_clocks(void)
+{
+ struct clk *clkp;
+ int ret;
+ int ptr;
+
+ s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
+
+ for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
+ s3c_register_clksrc(sysclks[ptr], 1);
+
+ s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
+ s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
+
+ clkp = init_clocks_disable;
+ for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
+
+ ret = s3c24xx_register_clock(clkp);
+ if (ret < 0) {
+ printk(KERN_ERR "Failed to register clock %s (%d)\n",
+ clkp->name, ret);
+ }
+ (clkp->enable)(clkp, 0);
+ }
+
+ s3c_pwmclk_init();
+}
diff --git a/arch/arm/mach-s5p64x0/clock-s5p6450.c b/arch/arm/mach-s5p64x0/clock-s5p6450.c
new file mode 100644
index 000000000000..f9afb05b217c
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/clock-s5p6450.c
@@ -0,0 +1,655 @@
+/* linux/arch/arm/mach-s5p64x0/clock-s5p6450.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * S5P6450 - Clock support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/sysdev.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#include <mach/s5p64x0-clock.h>
+
+#include <plat/cpu-freq.h>
+#include <plat/clock.h>
+#include <plat/cpu.h>
+#include <plat/pll.h>
+#include <plat/s5p-clock.h>
+#include <plat/clock-clksrc.h>
+#include <plat/s5p6450.h>
+
+static struct clksrc_clk clk_mout_dpll = {
+ .clk = {
+ .name = "mout_dpll",
+ .id = -1,
+ },
+ .sources = &clk_src_dpll,
+ .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 5, .size = 1 },
+};
+
+static u32 epll_div[][5] = {
+ { 133000000, 27307, 55, 2, 2 },
+ { 100000000, 43691, 41, 2, 2 },
+ { 480000000, 0, 80, 2, 0 },
+};
+
+static int s5p6450_epll_set_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned int epll_con, epll_con_k;
+ unsigned int i;
+
+ if (clk->rate == rate) /* Return if nothing changed */
+ return 0;
+
+ epll_con = __raw_readl(S5P64X0_EPLL_CON);
+ epll_con_k = __raw_readl(S5P64X0_EPLL_CON_K);
+
+ epll_con_k &= ~(PLL90XX_KDIV_MASK);
+ epll_con &= ~(PLL90XX_MDIV_MASK | PLL90XX_PDIV_MASK | PLL90XX_SDIV_MASK);
+
+ for (i = 0; i < ARRAY_SIZE(epll_div); i++) {
+ if (epll_div[i][0] == rate) {
+ epll_con_k |= (epll_div[i][1] << PLL90XX_KDIV_SHIFT);
+ epll_con |= (epll_div[i][2] << PLL90XX_MDIV_SHIFT) |
+ (epll_div[i][3] << PLL90XX_PDIV_SHIFT) |
+ (epll_div[i][4] << PLL90XX_SDIV_SHIFT);
+ break;
+ }
+ }
+
+ if (i == ARRAY_SIZE(epll_div)) {
+ printk(KERN_ERR "%s: Invalid Clock EPLL Frequency\n", __func__);
+ return -EINVAL;
+ }
+
+ __raw_writel(epll_con, S5P64X0_EPLL_CON);
+ __raw_writel(epll_con_k, S5P64X0_EPLL_CON_K);
+
+ clk->rate = rate;
+
+ return 0;
+}
+
+static struct clk_ops s5p6450_epll_ops = {
+ .get_rate = s5p64x0_epll_get_rate,
+ .set_rate = s5p6450_epll_set_rate,
+};
+
+static struct clksrc_clk clk_dout_epll = {
+ .clk = {
+ .name = "dout_epll",
+ .id = -1,
+ .parent = &clk_mout_epll.clk,
+ },
+ .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 24, .size = 4 },
+};
+
+static struct clksrc_clk clk_mout_hclk_sel = {
+ .clk = {
+ .name = "mout_hclk_sel",
+ .id = -1,
+ },
+ .sources = &clkset_hclk_low,
+ .reg_src = { .reg = S5P64X0_OTHERS, .shift = 15, .size = 1 },
+};
+
+static struct clk *clkset_hclk_list[] = {
+ &clk_mout_hclk_sel.clk,
+ &clk_armclk.clk,
+};
+
+static struct clksrc_sources clkset_hclk = {
+ .sources = clkset_hclk_list,
+ .nr_sources = ARRAY_SIZE(clkset_hclk_list),
+};
+
+static struct clksrc_clk clk_hclk = {
+ .clk = {
+ .name = "clk_hclk",
+ .id = -1,
+ },
+ .sources = &clkset_hclk,
+ .reg_src = { .reg = S5P64X0_OTHERS, .shift = 14, .size = 1 },
+ .reg_div = { .reg = S5P64X0_CLK_DIV0, .shift = 8, .size = 4 },
+};
+
+static struct clksrc_clk clk_pclk = {
+ .clk = {
+ .name = "clk_pclk",
+ .id = -1,
+ .parent = &clk_hclk.clk,
+ },
+ .reg_div = { .reg = S5P64X0_CLK_DIV0, .shift = 12, .size = 4 },
+};
+static struct clksrc_clk clk_dout_pwm_ratio0 = {
+ .clk = {
+ .name = "clk_dout_pwm_ratio0",
+ .id = -1,
+ .parent = &clk_mout_hclk_sel.clk,
+ },
+ .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 16, .size = 4 },
+};
+
+static struct clksrc_clk clk_pclk_to_wdt_pwm = {
+ .clk = {
+ .name = "clk_pclk_to_wdt_pwm",
+ .id = -1,
+ .parent = &clk_dout_pwm_ratio0.clk,
+ },
+ .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 20, .size = 4 },
+};
+
+static struct clksrc_clk clk_hclk_low = {
+ .clk = {
+ .name = "clk_hclk_low",
+ .id = -1,
+ },
+ .sources = &clkset_hclk_low,
+ .reg_src = { .reg = S5P64X0_OTHERS, .shift = 6, .size = 1 },
+ .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 8, .size = 4 },
+};
+
+static struct clksrc_clk clk_pclk_low = {
+ .clk = {
+ .name = "clk_pclk_low",
+ .id = -1,
+ .parent = &clk_hclk_low.clk,
+ },
+ .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 12, .size = 4 },
+};
+
+/*
+ * The following clocks will be disabled during clock initialization. It is
+ * recommended to keep the following clocks disabled until the driver requests
+ * for enabling the clock.
+ */
+static struct clk init_clocks_disable[] = {
+ {
+ .name = "usbhost",
+ .id = -1,
+ .parent = &clk_hclk_low.clk,
+ .enable = s5p64x0_hclk0_ctrl,
+ .ctrlbit = (1 << 3),
+ }, {
+ .name = "hsmmc",
+ .id = 0,
+ .parent = &clk_hclk_low.clk,
+ .enable = s5p64x0_hclk0_ctrl,
+ .ctrlbit = (1 << 17),
+ }, {
+ .name = "hsmmc",
+ .id = 1,
+ .parent = &clk_hclk_low.clk,
+ .enable = s5p64x0_hclk0_ctrl,
+ .ctrlbit = (1 << 18),
+ }, {
+ .name = "hsmmc",
+ .id = 2,
+ .parent = &clk_hclk_low.clk,
+ .enable = s5p64x0_hclk0_ctrl,
+ .ctrlbit = (1 << 19),
+ }, {
+ .name = "usbotg",
+ .id = -1,
+ .parent = &clk_hclk_low.clk,
+ .enable = s5p64x0_hclk0_ctrl,
+ .ctrlbit = (1 << 20),
+ }, {
+ .name = "lcd",
+ .id = -1,
+ .parent = &clk_h,
+ .enable = s5p64x0_hclk1_ctrl,
+ .ctrlbit = (1 << 1),
+ }, {
+ .name = "watchdog",
+ .id = -1,
+ .parent = &clk_pclk_low.clk,
+ .enable = s5p64x0_pclk_ctrl,
+ .ctrlbit = (1 << 5),
+ }, {
+ .name = "adc",
+ .id = -1,
+ .parent = &clk_pclk_low.clk,
+ .enable = s5p64x0_pclk_ctrl,
+ .ctrlbit = (1 << 12),
+ }, {
+ .name = "i2c",
+ .id = 0,
+ .parent = &clk_pclk_low.clk,
+ .enable = s5p64x0_pclk_ctrl,
+ .ctrlbit = (1 << 17),
+ }, {
+ .name = "spi",
+ .id = 0,
+ .parent = &clk_pclk_low.clk,
+ .enable = s5p64x0_pclk_ctrl,
+ .ctrlbit = (1 << 21),
+ }, {
+ .name = "spi",
+ .id = 1,
+ .parent = &clk_pclk_low.clk,
+ .enable = s5p64x0_pclk_ctrl,
+ .ctrlbit = (1 << 22),
+ }, {
+ .name = "iis",
+ .id = -1,
+ .parent = &clk_pclk_low.clk,
+ .enable = s5p64x0_pclk_ctrl,
+ .ctrlbit = (1 << 26),
+ }, {
+ .name = "i2c",
+ .id = 1,
+ .parent = &clk_pclk_low.clk,
+ .enable = s5p64x0_pclk_ctrl,
+ .ctrlbit = (1 << 27),
+ }, {
+ .name = "dmc0",
+ .id = -1,
+ .parent = &clk_pclk.clk,
+ .enable = s5p64x0_pclk_ctrl,
+ .ctrlbit = (1 << 30),
+ }
+};
+
+/*
+ * The following clocks will be enabled during clock initialization.
+ */
+static struct clk init_clocks[] = {
+ {
+ .name = "intc",
+ .id = -1,
+ .parent = &clk_hclk.clk,
+ .enable = s5p64x0_hclk0_ctrl,
+ .ctrlbit = (1 << 1),
+ }, {
+ .name = "mem",
+ .id = -1,
+ .parent = &clk_hclk.clk,
+ .enable = s5p64x0_hclk0_ctrl,
+ .ctrlbit = (1 << 21),
+ }, {
+ .name = "dma",
+ .id = -1,
+ .parent = &clk_hclk_low.clk,
+ .enable = s5p64x0_hclk0_ctrl,
+ .ctrlbit = (1 << 12),
+ }, {
+ .name = "uart",
+ .id = 0,
+ .parent = &clk_pclk_low.clk,
+ .enable = s5p64x0_pclk_ctrl,
+ .ctrlbit = (1 << 1),
+ }, {
+ .name = "uart",
+ .id = 1,
+ .parent = &clk_pclk_low.clk,
+ .enable = s5p64x0_pclk_ctrl,
+ .ctrlbit = (1 << 2),
+ }, {
+ .name = "uart",
+ .id = 2,
+ .parent = &clk_pclk_low.clk,
+ .enable = s5p64x0_pclk_ctrl,
+ .ctrlbit = (1 << 3),
+ }, {
+ .name = "uart",
+ .id = 3,
+ .parent = &clk_pclk_low.clk,
+ .enable = s5p64x0_pclk_ctrl,
+ .ctrlbit = (1 << 4),
+ }, {
+ .name = "timers",
+ .id = -1,
+ .parent = &clk_pclk_to_wdt_pwm.clk,
+ .enable = s5p64x0_pclk_ctrl,
+ .ctrlbit = (1 << 7),
+ }, {
+ .name = "gpio",
+ .id = -1,
+ .parent = &clk_pclk_low.clk,
+ .enable = s5p64x0_pclk_ctrl,
+ .ctrlbit = (1 << 18),
+ },
+};
+
+static struct clk *clkset_uart_list[] = {
+ &clk_dout_epll.clk,
+ &clk_dout_mpll.clk,
+};
+
+static struct clksrc_sources clkset_uart = {
+ .sources = clkset_uart_list,
+ .nr_sources = ARRAY_SIZE(clkset_uart_list),
+};
+
+static struct clk *clkset_mali_list[] = {
+ &clk_mout_epll.clk,
+ &clk_mout_apll.clk,
+ &clk_mout_mpll.clk,
+};
+
+static struct clksrc_sources clkset_mali = {
+ .sources = clkset_mali_list,
+ .nr_sources = ARRAY_SIZE(clkset_mali_list),
+};
+
+static struct clk *clkset_group2_list[] = {
+ &clk_dout_epll.clk,
+ &clk_dout_mpll.clk,
+ &clk_ext_xtal_mux,
+};
+
+static struct clksrc_sources clkset_group2 = {
+ .sources = clkset_group2_list,
+ .nr_sources = ARRAY_SIZE(clkset_group2_list),
+};
+
+static struct clk *clkset_dispcon_list[] = {
+ &clk_dout_epll.clk,
+ &clk_dout_mpll.clk,
+ &clk_ext_xtal_mux,
+ &clk_mout_dpll.clk,
+};
+
+static struct clksrc_sources clkset_dispcon = {
+ .sources = clkset_dispcon_list,
+ .nr_sources = ARRAY_SIZE(clkset_dispcon_list),
+};
+
+static struct clk *clkset_hsmmc44_list[] = {
+ &clk_dout_epll.clk,
+ &clk_dout_mpll.clk,
+ &clk_ext_xtal_mux,
+ &s5p_clk_27m,
+ &clk_48m,
+};
+
+static struct clksrc_sources clkset_hsmmc44 = {
+ .sources = clkset_hsmmc44_list,
+ .nr_sources = ARRAY_SIZE(clkset_hsmmc44_list),
+};
+
+static struct clk *clkset_sclk_audio0_list[] = {
+ [0] = &clk_dout_epll.clk,
+ [1] = &clk_dout_mpll.clk,
+ [2] = &clk_ext_xtal_mux,
+ [3] = NULL,
+ [4] = NULL,
+};
+
+static struct clksrc_sources clkset_sclk_audio0 = {
+ .sources = clkset_sclk_audio0_list,
+ .nr_sources = ARRAY_SIZE(clkset_sclk_audio0_list),
+};
+
+static struct clksrc_clk clk_sclk_audio0 = {
+ .clk = {
+ .name = "audio-bus",
+ .id = -1,
+ .enable = s5p64x0_sclk_ctrl,
+ .ctrlbit = (1 << 8),
+ .parent = &clk_dout_epll.clk,
+ },
+ .sources = &clkset_sclk_audio0,
+ .reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 10, .size = 3 },
+ .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 8, .size = 4 },
+};
+
+static struct clksrc_clk clksrcs[] = {
+ {
+ .clk = {
+ .name = "sclk_mmc",
+ .id = 0,
+ .ctrlbit = (1 << 24),
+ .enable = s5p64x0_sclk_ctrl,
+ },
+ .sources = &clkset_group2,
+ .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 18, .size = 2 },
+ .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 0, .size = 4 },
+ }, {
+ .clk = {
+ .name = "sclk_mmc",
+ .id = 1,
+ .ctrlbit = (1 << 25),
+ .enable = s5p64x0_sclk_ctrl,
+ },
+ .sources = &clkset_group2,
+ .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 20, .size = 2 },
+ .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 4, .size = 4 },
+ }, {
+ .clk = {
+ .name = "sclk_mmc",
+ .id = 2,
+ .ctrlbit = (1 << 26),
+ .enable = s5p64x0_sclk_ctrl,
+ },
+ .sources = &clkset_group2,
+ .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 22, .size = 2 },
+ .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 8, .size = 4 },
+ }, {
+ .clk = {
+ .name = "uclk1",
+ .id = -1,
+ .ctrlbit = (1 << 5),
+ .enable = s5p64x0_sclk_ctrl,
+ },
+ .sources = &clkset_uart,
+ .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 13, .size = 1 },
+ .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 16, .size = 4 },
+ }, {
+ .clk = {
+ .name = "sclk_spi",
+ .id = 0,
+ .ctrlbit = (1 << 20),
+ .enable = s5p64x0_sclk_ctrl,
+ },
+ .sources = &clkset_group2,
+ .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 14, .size = 2 },
+ .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 0, .size = 4 },
+ }, {
+ .clk = {
+ .name = "sclk_spi",
+ .id = 1,
+ .ctrlbit = (1 << 21),
+ .enable = s5p64x0_sclk_ctrl,
+ },
+ .sources = &clkset_group2,
+ .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 16, .size = 2 },
+ .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 4, .size = 4 },
+ }, {
+ .clk = {
+ .name = "sclk_fimc",
+ .id = -1,
+ .ctrlbit = (1 << 10),
+ .enable = s5p64x0_sclk_ctrl,
+ },
+ .sources = &clkset_group2,
+ .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 26, .size = 2 },
+ .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 12, .size = 4 },
+ }, {
+ .clk = {
+ .name = "aclk_mali",
+ .id = -1,
+ .ctrlbit = (1 << 2),
+ .enable = s5p64x0_sclk1_ctrl,
+ },
+ .sources = &clkset_mali,
+ .reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 8, .size = 2 },
+ .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 4, .size = 4 },
+ }, {
+ .clk = {
+ .name = "sclk_2d",
+ .id = -1,
+ .ctrlbit = (1 << 12),
+ .enable = s5p64x0_sclk_ctrl,
+ },
+ .sources = &clkset_mali,
+ .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 30, .size = 2 },
+ .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 20, .size = 4 },
+ }, {
+ .clk = {
+ .name = "sclk_usi",
+ .id = -1,
+ .ctrlbit = (1 << 7),
+ .enable = s5p64x0_sclk_ctrl,
+ },
+ .sources = &clkset_group2,
+ .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 10, .size = 2 },
+ .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 16, .size = 4 },
+ }, {
+ .clk = {
+ .name = "sclk_camif",
+ .id = -1,
+ .ctrlbit = (1 << 6),
+ .enable = s5p64x0_sclk_ctrl,
+ },
+ .sources = &clkset_group2,
+ .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 28, .size = 2 },
+ .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 20, .size = 4 },
+ }, {
+ .clk = {
+ .name = "sclk_dispcon",
+ .id = -1,
+ .ctrlbit = (1 << 1),
+ .enable = s5p64x0_sclk1_ctrl,
+ },
+ .sources = &clkset_dispcon,
+ .reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 4, .size = 2 },
+ .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 0, .size = 4 },
+ }, {
+ .clk = {
+ .name = "sclk_hsmmc44",
+ .id = -1,
+ .ctrlbit = (1 << 30),
+ .enable = s5p64x0_sclk_ctrl,
+ },
+ .sources = &clkset_hsmmc44,
+ .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 6, .size = 3 },
+ .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 28, .size = 4 },
+ },
+};
+
+/* Clock initialization code */
+static struct clksrc_clk *sysclks[] = {
+ &clk_mout_apll,
+ &clk_mout_epll,
+ &clk_dout_epll,
+ &clk_mout_mpll,
+ &clk_dout_mpll,
+ &clk_armclk,
+ &clk_mout_hclk_sel,
+ &clk_dout_pwm_ratio0,
+ &clk_pclk_to_wdt_pwm,
+ &clk_hclk,
+ &clk_pclk,
+ &clk_hclk_low,
+ &clk_pclk_low,
+ &clk_sclk_audio0,
+};
+
+void __init_or_cpufreq s5p6450_setup_clocks(void)
+{
+ struct clk *xtal_clk;
+
+ unsigned long xtal;
+ unsigned long fclk;
+ unsigned long hclk;
+ unsigned long hclk_low;
+ unsigned long pclk;
+ unsigned long pclk_low;
+
+ unsigned long apll;
+ unsigned long mpll;
+ unsigned long epll;
+ unsigned long dpll;
+ unsigned int ptr;
+
+ /* Set S5P6450 functions for clk_fout_epll */
+
+ clk_fout_epll.enable = s5p64x0_epll_enable;
+ clk_fout_epll.ops = &s5p6450_epll_ops;
+
+ clk_48m.enable = s5p64x0_clk48m_ctrl;
+
+ xtal_clk = clk_get(NULL, "ext_xtal");
+ BUG_ON(IS_ERR(xtal_clk));
+
+ xtal = clk_get_rate(xtal_clk);
+ clk_put(xtal_clk);
+
+ apll = s5p_get_pll45xx(xtal, __raw_readl(S5P64X0_APLL_CON), pll_4502);
+ mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P64X0_MPLL_CON), pll_4502);
+ epll = s5p_get_pll90xx(xtal, __raw_readl(S5P64X0_EPLL_CON),
+ __raw_readl(S5P64X0_EPLL_CON_K));
+ dpll = s5p_get_pll46xx(xtal, __raw_readl(S5P6450_DPLL_CON),
+ __raw_readl(S5P6450_DPLL_CON_K), pll_4650c);
+
+ clk_fout_apll.rate = apll;
+ clk_fout_mpll.rate = mpll;
+ clk_fout_epll.rate = epll;
+ clk_fout_dpll.rate = dpll;
+
+ printk(KERN_INFO "S5P6450: PLL settings, A=%ld.%ldMHz, M=%ld.%ldMHz," \
+ " E=%ld.%ldMHz, D=%ld.%ldMHz\n",
+ print_mhz(apll), print_mhz(mpll), print_mhz(epll),
+ print_mhz(dpll));
+
+ fclk = clk_get_rate(&clk_armclk.clk);
+ hclk = clk_get_rate(&clk_hclk.clk);
+ pclk = clk_get_rate(&clk_pclk.clk);
+ hclk_low = clk_get_rate(&clk_hclk_low.clk);
+ pclk_low = clk_get_rate(&clk_pclk_low.clk);
+
+ printk(KERN_INFO "S5P6450: HCLK=%ld.%ldMHz, HCLK_LOW=%ld.%ldMHz," \
+ " PCLK=%ld.%ldMHz, PCLK_LOW=%ld.%ldMHz\n",
+ print_mhz(hclk), print_mhz(hclk_low),
+ print_mhz(pclk), print_mhz(pclk_low));
+
+ clk_f.rate = fclk;
+ clk_h.rate = hclk;
+ clk_p.rate = pclk;
+
+ for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
+ s3c_set_clksrc(&clksrcs[ptr], true);
+}
+
+void __init s5p6450_register_clocks(void)
+{
+ struct clk *clkp;
+ int ret;
+ int ptr;
+
+ for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
+ s3c_register_clksrc(sysclks[ptr], 1);
+
+ s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
+ s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
+
+ clkp = init_clocks_disable;
+ for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
+
+ ret = s3c24xx_register_clock(clkp);
+ if (ret < 0) {
+ printk(KERN_ERR "Failed to register clock %s (%d)\n",
+ clkp->name, ret);
+ }
+ (clkp->enable)(clkp, 0);
+ }
+
+ s3c_pwmclk_init();
+}
diff --git a/arch/arm/mach-s5p64x0/clock.c b/arch/arm/mach-s5p64x0/clock.c
new file mode 100644
index 000000000000..523ba8039ac2
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/clock.c
@@ -0,0 +1,253 @@
+/* linux/arch/arm/mach-s5p64x0/clock.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * S5P64X0 - Clock support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/sysdev.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+
+#include <plat/cpu-freq.h>
+#include <plat/clock.h>
+#include <plat/cpu.h>
+#include <plat/pll.h>
+#include <plat/s5p-clock.h>
+#include <plat/clock-clksrc.h>
+#include <plat/s5p6440.h>
+#include <plat/s5p6450.h>
+
+struct clksrc_clk clk_mout_apll = {
+ .clk = {
+ .name = "mout_apll",
+ .id = -1,
+ },
+ .sources = &clk_src_apll,
+ .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 0, .size = 1 },
+};
+
+struct clksrc_clk clk_mout_mpll = {
+ .clk = {
+ .name = "mout_mpll",
+ .id = -1,
+ },
+ .sources = &clk_src_mpll,
+ .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 1, .size = 1 },
+};
+
+struct clksrc_clk clk_mout_epll = {
+ .clk = {
+ .name = "mout_epll",
+ .id = -1,
+ },
+ .sources = &clk_src_epll,
+ .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 2, .size = 1 },
+};
+
+enum perf_level {
+ L0 = 532*1000,
+ L1 = 266*1000,
+ L2 = 133*1000,
+};
+
+static const u32 clock_table[][3] = {
+ /*{ARM_CLK, DIVarm, DIVhclk}*/
+ {L0 * 1000, (0 << ARM_DIV_RATIO_SHIFT), (3 << S5P64X0_CLKDIV0_HCLK_SHIFT)},
+ {L1 * 1000, (1 << ARM_DIV_RATIO_SHIFT), (1 << S5P64X0_CLKDIV0_HCLK_SHIFT)},
+ {L2 * 1000, (3 << ARM_DIV_RATIO_SHIFT), (0 << S5P64X0_CLKDIV0_HCLK_SHIFT)},
+};
+
+int s5p64x0_epll_enable(struct clk *clk, int enable)
+{
+ unsigned int ctrlbit = clk->ctrlbit;
+ unsigned int epll_con = __raw_readl(S5P64X0_EPLL_CON) & ~ctrlbit;
+
+ if (enable)
+ __raw_writel(epll_con | ctrlbit, S5P64X0_EPLL_CON);
+ else
+ __raw_writel(epll_con, S5P64X0_EPLL_CON);
+
+ return 0;
+}
+
+unsigned long s5p64x0_epll_get_rate(struct clk *clk)
+{
+ return clk->rate;
+}
+
+unsigned long s5p64x0_armclk_get_rate(struct clk *clk)
+{
+ unsigned long rate = clk_get_rate(clk->parent);
+ u32 clkdiv;
+
+ /* divisor mask starts at bit0, so no need to shift */
+ clkdiv = __raw_readl(ARM_CLK_DIV) & ARM_DIV_MASK;
+
+ return rate / (clkdiv + 1);
+}
+
+unsigned long s5p64x0_armclk_round_rate(struct clk *clk, unsigned long rate)
+{
+ u32 iter;
+
+ for (iter = 1 ; iter < ARRAY_SIZE(clock_table) ; iter++) {
+ if (rate > clock_table[iter][0])
+ return clock_table[iter-1][0];
+ }
+
+ return clock_table[ARRAY_SIZE(clock_table) - 1][0];
+}
+
+int s5p64x0_armclk_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 round_tmp;
+ u32 iter;
+ u32 clk_div0_tmp;
+ u32 cur_rate = clk->ops->get_rate(clk);
+ unsigned long flags;
+
+ round_tmp = clk->ops->round_rate(clk, rate);
+ if (round_tmp == cur_rate)
+ return 0;
+
+
+ for (iter = 0 ; iter < ARRAY_SIZE(clock_table) ; iter++) {
+ if (round_tmp == clock_table[iter][0])
+ break;
+ }
+
+ if (iter >= ARRAY_SIZE(clock_table))
+ iter = ARRAY_SIZE(clock_table) - 1;
+
+ local_irq_save(flags);
+ if (cur_rate > round_tmp) {
+ /* Frequency Down */
+ clk_div0_tmp = __raw_readl(ARM_CLK_DIV) & ~(ARM_DIV_MASK);
+ clk_div0_tmp |= clock_table[iter][1];
+ __raw_writel(clk_div0_tmp, ARM_CLK_DIV);
+
+ clk_div0_tmp = __raw_readl(ARM_CLK_DIV) &
+ ~(S5P64X0_CLKDIV0_HCLK_MASK);
+ clk_div0_tmp |= clock_table[iter][2];
+ __raw_writel(clk_div0_tmp, ARM_CLK_DIV);
+
+
+ } else {
+ /* Frequency Up */
+ clk_div0_tmp = __raw_readl(ARM_CLK_DIV) &
+ ~(S5P64X0_CLKDIV0_HCLK_MASK);
+ clk_div0_tmp |= clock_table[iter][2];
+ __raw_writel(clk_div0_tmp, ARM_CLK_DIV);
+
+ clk_div0_tmp = __raw_readl(ARM_CLK_DIV) & ~(ARM_DIV_MASK);
+ clk_div0_tmp |= clock_table[iter][1];
+ __raw_writel(clk_div0_tmp, ARM_CLK_DIV);
+ }
+ local_irq_restore(flags);
+
+ clk->rate = clock_table[iter][0];
+
+ return 0;
+}
+
+struct clk_ops s5p64x0_clkarm_ops = {
+ .get_rate = s5p64x0_armclk_get_rate,
+ .set_rate = s5p64x0_armclk_set_rate,
+ .round_rate = s5p64x0_armclk_round_rate,
+};
+
+struct clksrc_clk clk_armclk = {
+ .clk = {
+ .name = "armclk",
+ .id = 1,
+ .parent = &clk_mout_apll.clk,
+ .ops = &s5p64x0_clkarm_ops,
+ },
+ .reg_div = { .reg = S5P64X0_CLK_DIV0, .shift = 0, .size = 4 },
+};
+
+struct clksrc_clk clk_dout_mpll = {
+ .clk = {
+ .name = "dout_mpll",
+ .id = -1,
+ .parent = &clk_mout_mpll.clk,
+ },
+ .reg_div = { .reg = S5P64X0_CLK_DIV0, .shift = 4, .size = 1 },
+};
+
+struct clk *clkset_hclk_low_list[] = {
+ &clk_mout_apll.clk,
+ &clk_mout_mpll.clk,
+};
+
+struct clksrc_sources clkset_hclk_low = {
+ .sources = clkset_hclk_low_list,
+ .nr_sources = ARRAY_SIZE(clkset_hclk_low_list),
+};
+
+int s5p64x0_pclk_ctrl(struct clk *clk, int enable)
+{
+ return s5p_gatectrl(S5P64X0_CLK_GATE_PCLK, clk, enable);
+}
+
+int s5p64x0_hclk0_ctrl(struct clk *clk, int enable)
+{
+ return s5p_gatectrl(S5P64X0_CLK_GATE_HCLK0, clk, enable);
+}
+
+int s5p64x0_hclk1_ctrl(struct clk *clk, int enable)
+{
+ return s5p_gatectrl(S5P64X0_CLK_GATE_HCLK1, clk, enable);
+}
+
+int s5p64x0_sclk_ctrl(struct clk *clk, int enable)
+{
+ return s5p_gatectrl(S5P64X0_CLK_GATE_SCLK0, clk, enable);
+}
+
+int s5p64x0_sclk1_ctrl(struct clk *clk, int enable)
+{
+ return s5p_gatectrl(S5P64X0_CLK_GATE_SCLK1, clk, enable);
+}
+
+int s5p64x0_mem_ctrl(struct clk *clk, int enable)
+{
+ return s5p_gatectrl(S5P64X0_CLK_GATE_MEM0, clk, enable);
+}
+
+int s5p64x0_clk48m_ctrl(struct clk *clk, int enable)
+{
+ unsigned long flags;
+ u32 val;
+
+ /* can't rely on clock lock, this register has other usages */
+ local_irq_save(flags);
+
+ val = __raw_readl(S5P64X0_OTHERS);
+ if (enable)
+ val |= S5P64X0_OTHERS_USB_SIG_MASK;
+ else
+ val &= ~S5P64X0_OTHERS_USB_SIG_MASK;
+
+ __raw_writel(val, S5P64X0_OTHERS);
+
+ local_irq_restore(flags);
+
+ return 0;
+}
diff --git a/arch/arm/mach-s5p64x0/cpu.c b/arch/arm/mach-s5p64x0/cpu.c
new file mode 100644
index 000000000000..b8d02eb4cf30
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/cpu.c
@@ -0,0 +1,209 @@
+/* linux/arch/arm/mach-s5p64x0/cpu.c
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/sysdev.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+#include <asm/proc-fns.h>
+#include <asm/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+
+#include <plat/regs-serial.h>
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/clock.h>
+#include <plat/s5p6440.h>
+#include <plat/s5p6450.h>
+#include <plat/adc-core.h>
+
+/* Initial IO mappings */
+
+static struct map_desc s5p64x0_iodesc[] __initdata = {
+ {
+ .virtual = (unsigned long)S5P_VA_GPIO,
+ .pfn = __phys_to_pfn(S5P64X0_PA_GPIO),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = (unsigned long)VA_VIC0,
+ .pfn = __phys_to_pfn(S5P64X0_PA_VIC0),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = (unsigned long)VA_VIC1,
+ .pfn = __phys_to_pfn(S5P64X0_PA_VIC1),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ },
+};
+
+static struct map_desc s5p6440_iodesc[] __initdata = {
+ {
+ .virtual = (unsigned long)S3C_VA_UART,
+ .pfn = __phys_to_pfn(S5P6440_PA_UART(0)),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ },
+};
+
+static struct map_desc s5p6450_iodesc[] __initdata = {
+ {
+ .virtual = (unsigned long)S3C_VA_UART,
+ .pfn = __phys_to_pfn(S5P6450_PA_UART(0)),
+ .length = SZ_512K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = (unsigned long)S3C_VA_UART + SZ_512K,
+ .pfn = __phys_to_pfn(S5P6450_PA_UART(5)),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ },
+};
+
+static void s5p64x0_idle(void)
+{
+ unsigned long val;
+
+ if (!need_resched()) {
+ val = __raw_readl(S5P64X0_PWR_CFG);
+ val &= ~(0x3 << 5);
+ val |= (0x1 << 5);
+ __raw_writel(val, S5P64X0_PWR_CFG);
+
+ cpu_do_idle();
+ }
+ local_irq_enable();
+}
+
+/*
+ * s5p64x0_map_io
+ *
+ * register the standard CPU IO areas
+ */
+
+void __init s5p6440_map_io(void)
+{
+ /* initialize any device information early */
+ s3c_adc_setname("s3c64xx-adc");
+
+ iotable_init(s5p64x0_iodesc, ARRAY_SIZE(s5p64x0_iodesc));
+ iotable_init(s5p6440_iodesc, ARRAY_SIZE(s5p6440_iodesc));
+}
+
+void __init s5p6450_map_io(void)
+{
+ /* initialize any device information early */
+ s3c_adc_setname("s3c64xx-adc");
+
+ iotable_init(s5p64x0_iodesc, ARRAY_SIZE(s5p64x0_iodesc));
+ iotable_init(s5p6450_iodesc, ARRAY_SIZE(s5p6440_iodesc));
+}
+
+/*
+ * s5p64x0_init_clocks
+ *
+ * register and setup the CPU clocks
+ */
+
+void __init s5p6440_init_clocks(int xtal)
+{
+ printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
+
+ s3c24xx_register_baseclocks(xtal);
+ s5p_register_clocks(xtal);
+ s5p6440_register_clocks();
+ s5p6440_setup_clocks();
+}
+
+void __init s5p6450_init_clocks(int xtal)
+{
+ printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
+
+ s3c24xx_register_baseclocks(xtal);
+ s5p_register_clocks(xtal);
+ s5p6450_register_clocks();
+ s5p6450_setup_clocks();
+}
+
+/*
+ * s5p64x0_init_irq
+ *
+ * register the CPU interrupts
+ */
+
+void __init s5p6440_init_irq(void)
+{
+ /* S5P6440 supports 2 VIC */
+ u32 vic[2];
+
+ /*
+ * VIC0 is missing IRQ_VIC0[3, 4, 8, 10, (12-22)]
+ * VIC1 is missing IRQ VIC1[1, 3, 4, 10, 11, 12, 14, 15, 22]
+ */
+ vic[0] = 0xff800ae7;
+ vic[1] = 0xffbf23e5;
+
+ s5p_init_irq(vic, ARRAY_SIZE(vic));
+}
+
+void __init s5p6450_init_irq(void)
+{
+ /* S5P6450 supports only 2 VIC */
+ u32 vic[2];
+
+ /*
+ * VIC0 is missing IRQ_VIC0[(13-15), (21-22)]
+ * VIC1 is missing IRQ VIC1[12, 14, 23]
+ */
+ vic[0] = 0xff9f1fff;
+ vic[1] = 0xff7fafff;
+
+ s5p_init_irq(vic, ARRAY_SIZE(vic));
+}
+
+struct sysdev_class s5p64x0_sysclass = {
+ .name = "s5p64x0-core",
+};
+
+static struct sys_device s5p64x0_sysdev = {
+ .cls = &s5p64x0_sysclass,
+};
+
+static int __init s5p64x0_core_init(void)
+{
+ return sysdev_class_register(&s5p64x0_sysclass);
+}
+core_initcall(s5p64x0_core_init);
+
+int __init s5p64x0_init(void)
+{
+ printk(KERN_INFO "S5P64X0(S5P6440/S5P6450): Initializing architecture\n");
+
+ /* set idle function */
+ pm_idle = s5p64x0_idle;
+
+ return sysdev_register(&s5p64x0_sysdev);
+}
diff --git a/arch/arm/mach-s5p64x0/dev-audio.c b/arch/arm/mach-s5p64x0/dev-audio.c
new file mode 100644
index 000000000000..fa097bd68ca4
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/dev-audio.c
@@ -0,0 +1,164 @@
+/* linux/arch/arm/mach-s5p64x0/dev-audio.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co. Ltd
+ * Jaswinder Singh <jassi.brar@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/gpio.h>
+
+#include <plat/gpio-cfg.h>
+#include <plat/audio.h>
+
+#include <mach/map.h>
+#include <mach/dma.h>
+#include <mach/irqs.h>
+
+static int s5p6440_cfg_i2s(struct platform_device *pdev)
+{
+ /* configure GPIO for i2s port */
+ switch (pdev->id) {
+ case -1:
+ s3c_gpio_cfgpin(S5P6440_GPR(4), S3C_GPIO_SFN(5));
+ s3c_gpio_cfgpin(S5P6440_GPR(5), S3C_GPIO_SFN(5));
+ s3c_gpio_cfgpin(S5P6440_GPR(6), S3C_GPIO_SFN(5));
+ s3c_gpio_cfgpin(S5P6440_GPR(7), S3C_GPIO_SFN(5));
+ s3c_gpio_cfgpin(S5P6440_GPR(8), S3C_GPIO_SFN(5));
+ s3c_gpio_cfgpin(S5P6440_GPR(13), S3C_GPIO_SFN(5));
+ s3c_gpio_cfgpin(S5P6440_GPR(14), S3C_GPIO_SFN(5));
+ break;
+
+ default:
+ printk(KERN_ERR "Invalid Device %d\n", pdev->id);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int s5p6450_cfg_i2s(struct platform_device *pdev)
+{
+ /* configure GPIO for i2s port */
+ switch (pdev->id) {
+ case -1:
+ s3c_gpio_cfgpin(S5P6450_GPB(4), S3C_GPIO_SFN(5));
+ s3c_gpio_cfgpin(S5P6450_GPR(4), S3C_GPIO_SFN(5));
+ s3c_gpio_cfgpin(S5P6450_GPR(5), S3C_GPIO_SFN(5));
+ s3c_gpio_cfgpin(S5P6450_GPR(6), S3C_GPIO_SFN(5));
+ s3c_gpio_cfgpin(S5P6450_GPR(7), S3C_GPIO_SFN(5));
+ s3c_gpio_cfgpin(S5P6450_GPR(8), S3C_GPIO_SFN(5));
+ s3c_gpio_cfgpin(S5P6450_GPR(13), S3C_GPIO_SFN(5));
+ s3c_gpio_cfgpin(S5P6450_GPR(14), S3C_GPIO_SFN(5));
+ break;
+
+ default:
+ printk(KERN_ERR "Invalid Device %d\n", pdev->id);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static struct s3c_audio_pdata s5p6440_i2s_pdata = {
+ .cfg_gpio = s5p6440_cfg_i2s,
+};
+
+static struct s3c_audio_pdata s5p6450_i2s_pdata = {
+ .cfg_gpio = s5p6450_cfg_i2s,
+};
+
+static struct resource s5p64x0_iis0_resource[] = {
+ [0] = {
+ .start = S5P64X0_PA_I2S,
+ .end = S5P64X0_PA_I2S + 0x100 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = DMACH_I2S0_TX,
+ .end = DMACH_I2S0_TX,
+ .flags = IORESOURCE_DMA,
+ },
+ [2] = {
+ .start = DMACH_I2S0_RX,
+ .end = DMACH_I2S0_RX,
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+struct platform_device s5p6440_device_iis = {
+ .name = "s3c64xx-iis-v4",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s5p64x0_iis0_resource),
+ .resource = s5p64x0_iis0_resource,
+ .dev = {
+ .platform_data = &s5p6440_i2s_pdata,
+ },
+};
+
+struct platform_device s5p6450_device_iis0 = {
+ .name = "s3c64xx-iis-v4",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s5p64x0_iis0_resource),
+ .resource = s5p64x0_iis0_resource,
+ .dev = {
+ .platform_data = &s5p6450_i2s_pdata,
+ },
+};
+
+/* PCM Controller platform_devices */
+
+static int s5p6440_pcm_cfg_gpio(struct platform_device *pdev)
+{
+ switch (pdev->id) {
+ case 0:
+ s3c_gpio_cfgpin(S5P6440_GPR(7), S3C_GPIO_SFN(2));
+ s3c_gpio_cfgpin(S5P6440_GPR(13), S3C_GPIO_SFN(2));
+ s3c_gpio_cfgpin(S5P6440_GPR(14), S3C_GPIO_SFN(2));
+ s3c_gpio_cfgpin(S5P6440_GPR(8), S3C_GPIO_SFN(2));
+ s3c_gpio_cfgpin(S5P6440_GPR(6), S3C_GPIO_SFN(2));
+ break;
+
+ default:
+ printk(KERN_DEBUG "Invalid PCM Controller number!");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static struct s3c_audio_pdata s5p6440_pcm_pdata = {
+ .cfg_gpio = s5p6440_pcm_cfg_gpio,
+};
+
+static struct resource s5p6440_pcm0_resource[] = {
+ [0] = {
+ .start = S5P64X0_PA_PCM,
+ .end = S5P64X0_PA_PCM + 0x100 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = DMACH_PCM0_TX,
+ .end = DMACH_PCM0_TX,
+ .flags = IORESOURCE_DMA,
+ },
+ [2] = {
+ .start = DMACH_PCM0_RX,
+ .end = DMACH_PCM0_RX,
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+struct platform_device s5p6440_device_pcm = {
+ .name = "samsung-pcm",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(s5p6440_pcm0_resource),
+ .resource = s5p6440_pcm0_resource,
+ .dev = {
+ .platform_data = &s5p6440_pcm_pdata,
+ },
+};
diff --git a/arch/arm/mach-s5p64x0/dev-spi.c b/arch/arm/mach-s5p64x0/dev-spi.c
new file mode 100644
index 000000000000..5b69ec4c8af3
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/dev-spi.c
@@ -0,0 +1,232 @@
+/* linux/arch/arm/mach-s5p64x0/dev-spi.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Copyright (C) 2010 Samsung Electronics Co. Ltd.
+ * Jaswinder Singh <jassi.brar@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/gpio.h>
+
+#include <mach/dma.h>
+#include <mach/map.h>
+#include <mach/irqs.h>
+#include <mach/regs-clock.h>
+#include <mach/spi-clocks.h>
+
+#include <plat/s3c64xx-spi.h>
+#include <plat/gpio-cfg.h>
+
+static char *s5p64x0_spi_src_clks[] = {
+ [S5P64X0_SPI_SRCCLK_PCLK] = "pclk",
+ [S5P64X0_SPI_SRCCLK_SCLK] = "sclk_spi",
+};
+
+/* SPI Controller platform_devices */
+
+/* Since we emulate multi-cs capability, we do not touch the CS.
+ * The emulated CS is toggled by board specific mechanism, as it can
+ * be either some immediate GPIO or some signal out of some other
+ * chip in between ... or some yet another way.
+ * We simply do not assume anything about CS.
+ */
+static int s5p6440_spi_cfg_gpio(struct platform_device *pdev)
+{
+ switch (pdev->id) {
+ case 0:
+ s3c_gpio_cfgpin(S5P6440_GPC(0), S3C_GPIO_SFN(2));
+ s3c_gpio_cfgpin(S5P6440_GPC(1), S3C_GPIO_SFN(2));
+ s3c_gpio_cfgpin(S5P6440_GPC(2), S3C_GPIO_SFN(2));
+ s3c_gpio_setpull(S5P6440_GPC(0), S3C_GPIO_PULL_UP);
+ s3c_gpio_setpull(S5P6440_GPC(1), S3C_GPIO_PULL_UP);
+ s3c_gpio_setpull(S5P6440_GPC(2), S3C_GPIO_PULL_UP);
+ break;
+
+ case 1:
+ s3c_gpio_cfgpin(S5P6440_GPC(4), S3C_GPIO_SFN(2));
+ s3c_gpio_cfgpin(S5P6440_GPC(5), S3C_GPIO_SFN(2));
+ s3c_gpio_cfgpin(S5P6440_GPC(6), S3C_GPIO_SFN(2));
+ s3c_gpio_setpull(S5P6440_GPC(4), S3C_GPIO_PULL_UP);
+ s3c_gpio_setpull(S5P6440_GPC(5), S3C_GPIO_PULL_UP);
+ s3c_gpio_setpull(S5P6440_GPC(6), S3C_GPIO_PULL_UP);
+ break;
+
+ default:
+ dev_err(&pdev->dev, "Invalid SPI Controller number!");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int s5p6450_spi_cfg_gpio(struct platform_device *pdev)
+{
+ switch (pdev->id) {
+ case 0:
+ s3c_gpio_cfgpin(S5P6450_GPC(0), S3C_GPIO_SFN(2));
+ s3c_gpio_cfgpin(S5P6450_GPC(1), S3C_GPIO_SFN(2));
+ s3c_gpio_cfgpin(S5P6450_GPC(2), S3C_GPIO_SFN(2));
+ s3c_gpio_setpull(S5P6450_GPC(0), S3C_GPIO_PULL_UP);
+ s3c_gpio_setpull(S5P6450_GPC(1), S3C_GPIO_PULL_UP);
+ s3c_gpio_setpull(S5P6450_GPC(2), S3C_GPIO_PULL_UP);
+ break;
+
+ case 1:
+ s3c_gpio_cfgpin(S5P6450_GPC(4), S3C_GPIO_SFN(2));
+ s3c_gpio_cfgpin(S5P6450_GPC(5), S3C_GPIO_SFN(2));
+ s3c_gpio_cfgpin(S5P6450_GPC(6), S3C_GPIO_SFN(2));
+ s3c_gpio_setpull(S5P6450_GPC(4), S3C_GPIO_PULL_UP);
+ s3c_gpio_setpull(S5P6450_GPC(5), S3C_GPIO_PULL_UP);
+ s3c_gpio_setpull(S5P6450_GPC(6), S3C_GPIO_PULL_UP);
+ break;
+
+ default:
+ dev_err(&pdev->dev, "Invalid SPI Controller number!");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static struct resource s5p64x0_spi0_resource[] = {
+ [0] = {
+ .start = S5P64X0_PA_SPI0,
+ .end = S5P64X0_PA_SPI0 + 0x100 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = DMACH_SPI0_TX,
+ .end = DMACH_SPI0_TX,
+ .flags = IORESOURCE_DMA,
+ },
+ [2] = {
+ .start = DMACH_SPI0_RX,
+ .end = DMACH_SPI0_RX,
+ .flags = IORESOURCE_DMA,
+ },
+ [3] = {
+ .start = IRQ_SPI0,
+ .end = IRQ_SPI0,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct s3c64xx_spi_info s5p6440_spi0_pdata = {
+ .cfg_gpio = s5p6440_spi_cfg_gpio,
+ .fifo_lvl_mask = 0x1ff,
+ .rx_lvl_offset = 15,
+};
+
+static struct s3c64xx_spi_info s5p6450_spi0_pdata = {
+ .cfg_gpio = s5p6450_spi_cfg_gpio,
+ .fifo_lvl_mask = 0x1ff,
+ .rx_lvl_offset = 15,
+};
+
+static u64 spi_dmamask = DMA_BIT_MASK(32);
+
+struct platform_device s5p64x0_device_spi0 = {
+ .name = "s3c64xx-spi",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(s5p64x0_spi0_resource),
+ .resource = s5p64x0_spi0_resource,
+ .dev = {
+ .dma_mask = &spi_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+
+static struct resource s5p64x0_spi1_resource[] = {
+ [0] = {
+ .start = S5P64X0_PA_SPI1,
+ .end = S5P64X0_PA_SPI1 + 0x100 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = DMACH_SPI1_TX,
+ .end = DMACH_SPI1_TX,
+ .flags = IORESOURCE_DMA,
+ },
+ [2] = {
+ .start = DMACH_SPI1_RX,
+ .end = DMACH_SPI1_RX,
+ .flags = IORESOURCE_DMA,
+ },
+ [3] = {
+ .start = IRQ_SPI1,
+ .end = IRQ_SPI1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct s3c64xx_spi_info s5p6440_spi1_pdata = {
+ .cfg_gpio = s5p6440_spi_cfg_gpio,
+ .fifo_lvl_mask = 0x7f,
+ .rx_lvl_offset = 15,
+};
+
+static struct s3c64xx_spi_info s5p6450_spi1_pdata = {
+ .cfg_gpio = s5p6450_spi_cfg_gpio,
+ .fifo_lvl_mask = 0x7f,
+ .rx_lvl_offset = 15,
+};
+
+struct platform_device s5p64x0_device_spi1 = {
+ .name = "s3c64xx-spi",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(s5p64x0_spi1_resource),
+ .resource = s5p64x0_spi1_resource,
+ .dev = {
+ .dma_mask = &spi_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+
+void __init s5p64x0_spi_set_info(int cntrlr, int src_clk_nr, int num_cs)
+{
+ unsigned int id;
+ struct s3c64xx_spi_info *pd;
+
+ id = __raw_readl(S5P64X0_SYS_ID) & 0xFF000;
+
+ /* Reject invalid configuration */
+ if (!num_cs || src_clk_nr < 0
+ || src_clk_nr > S5P64X0_SPI_SRCCLK_SCLK) {
+ printk(KERN_ERR "%s: Invalid SPI configuration\n", __func__);
+ return;
+ }
+
+ switch (cntrlr) {
+ case 0:
+ if (id == 0x50000)
+ pd = &s5p6450_spi0_pdata;
+ else
+ pd = &s5p6440_spi0_pdata;
+
+ s5p64x0_device_spi0.dev.platform_data = pd;
+ break;
+ case 1:
+ if (id == 0x50000)
+ pd = &s5p6450_spi1_pdata;
+ else
+ pd = &s5p6440_spi1_pdata;
+
+ s5p64x0_device_spi1.dev.platform_data = pd;
+ break;
+ default:
+ printk(KERN_ERR "%s: Invalid SPI controller(%d)\n",
+ __func__, cntrlr);
+ return;
+ }
+
+ pd->num_cs = num_cs;
+ pd->src_clk_nr = src_clk_nr;
+ pd->src_clk_name = s5p64x0_spi_src_clks[src_clk_nr];
+}
diff --git a/arch/arm/mach-s5p6440/dma.c b/arch/arm/mach-s5p64x0/dma.c
index 07606ad57519..29a8c2410049 100644
--- a/arch/arm/mach-s5p6440/dma.c
+++ b/arch/arm/mach-s5p64x0/dma.c
@@ -1,4 +1,8 @@
-/*
+/* linux/arch/arm/mach-s5p64x0/dma.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
* Copyright (C) 2010 Samsung Electronics Co. Ltd.
* Jaswinder Singh <jassi.brar@samsung.com>
*
@@ -15,26 +19,25 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
+*/
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
-#include <plat/devs.h>
-#include <plat/irqs.h>
-
#include <mach/map.h>
#include <mach/irqs.h>
+#include <mach/regs-clock.h>
+#include <plat/devs.h>
#include <plat/s3c-pl330-pdata.h>
static u64 dma_dmamask = DMA_BIT_MASK(32);
-static struct resource s5p6440_pdma_resource[] = {
+static struct resource s5p64x0_pdma_resource[] = {
[0] = {
- .start = S5P6440_PA_PDMA,
- .end = S5P6440_PA_PDMA + SZ_4K,
- .flags = IORESOURCE_MEM,
+ .start = S5P64X0_PA_PDMA,
+ .end = S5P64X0_PA_PDMA + SZ_4K,
+ .flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_DMA0,
@@ -80,26 +83,67 @@ static struct s3c_pl330_platdata s5p6440_pdma_pdata = {
},
};
-static struct platform_device s5p6440_device_pdma = {
+static struct s3c_pl330_platdata s5p6450_pdma_pdata = {
+ .peri = {
+ [0] = DMACH_UART0_RX,
+ [1] = DMACH_UART0_TX,
+ [2] = DMACH_UART1_RX,
+ [3] = DMACH_UART1_TX,
+ [4] = DMACH_UART2_RX,
+ [5] = DMACH_UART2_TX,
+ [6] = DMACH_UART3_RX,
+ [7] = DMACH_UART3_TX,
+ [8] = DMACH_UART4_RX,
+ [9] = DMACH_UART4_TX,
+ [10] = DMACH_PCM0_TX,
+ [11] = DMACH_PCM0_RX,
+ [12] = DMACH_I2S0_TX,
+ [13] = DMACH_I2S0_RX,
+ [14] = DMACH_SPI0_TX,
+ [15] = DMACH_SPI0_RX,
+ [16] = DMACH_PCM1_TX,
+ [17] = DMACH_PCM1_RX,
+ [18] = DMACH_PCM2_TX,
+ [19] = DMACH_PCM2_RX,
+ [20] = DMACH_SPI1_TX,
+ [21] = DMACH_SPI1_RX,
+ [22] = DMACH_USI_TX,
+ [23] = DMACH_USI_RX,
+ [24] = DMACH_MAX,
+ [25] = DMACH_I2S1_TX,
+ [26] = DMACH_I2S1_RX,
+ [27] = DMACH_I2S2_TX,
+ [28] = DMACH_I2S2_RX,
+ [29] = DMACH_PWM,
+ [30] = DMACH_UART5_RX,
+ [31] = DMACH_UART5_TX,
+ },
+};
+
+static struct platform_device s5p64x0_device_pdma = {
.name = "s3c-pl330",
- .id = 1,
- .num_resources = ARRAY_SIZE(s5p6440_pdma_resource),
- .resource = s5p6440_pdma_resource,
+ .id = 0,
+ .num_resources = ARRAY_SIZE(s5p64x0_pdma_resource),
+ .resource = s5p64x0_pdma_resource,
.dev = {
.dma_mask = &dma_dmamask,
.coherent_dma_mask = DMA_BIT_MASK(32),
- .platform_data = &s5p6440_pdma_pdata,
},
};
-static struct platform_device *s5p6440_dmacs[] __initdata = {
- &s5p6440_device_pdma,
-};
-
-static int __init s5p6440_dma_init(void)
+static int __init s5p64x0_dma_init(void)
{
- platform_add_devices(s5p6440_dmacs, ARRAY_SIZE(s5p6440_dmacs));
+ unsigned int id;
+
+ id = __raw_readl(S5P64X0_SYS_ID) & 0xFF000;
+
+ if (id == 0x50000)
+ s5p64x0_device_pdma.dev.platform_data = &s5p6450_pdma_pdata;
+ else
+ s5p64x0_device_pdma.dev.platform_data = &s5p6440_pdma_pdata;
+
+ platform_device_register(&s5p64x0_device_pdma);
return 0;
}
-arch_initcall(s5p6440_dma_init);
+arch_initcall(s5p64x0_dma_init);
diff --git a/arch/arm/mach-s5p6440/gpio.c b/arch/arm/mach-s5p64x0/gpio.c
index 8bf6e0ce51c9..39159dd5a29a 100644
--- a/arch/arm/mach-s5p6440/gpio.c
+++ b/arch/arm/mach-s5p64x0/gpio.c
@@ -1,14 +1,14 @@
-/* arch/arm/mach-s5p6440/gpio.c
+/* linux/arch/arm/mach-s5p64x0/gpio.c
*
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
*
- * S5P6440 - GPIOlib support
+ * S5P64X0 - GPIOlib support
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- */
+*/
#include <linux/kernel.h>
#include <linux/irq.h>
@@ -22,26 +22,29 @@
#include <plat/gpio-cfg.h>
#include <plat/gpio-cfg-helpers.h>
-/* GPIO bank summary:
-*
-* Bank GPIOs Style SlpCon ExtInt Group
-* A 6 4Bit Yes 1
-* B 7 4Bit Yes 1
-* C 8 4Bit Yes 2
-* F 2 2Bit Yes 4 [1]
-* G 7 4Bit Yes 5
-* H 10 4Bit[2] Yes 6
-* I 16 2Bit Yes None
-* J 12 2Bit Yes None
-* N 16 2Bit No IRQ_EINT
-* P 8 2Bit Yes 8
-* R 15 4Bit[2] Yes 8
-*
-* [1] BANKF pins 14,15 do not form part of the external interrupt sources
-* [2] BANK has two control registers, GPxCON0 and GPxCON1
-*/
+/* To be implemented S5P6450 GPIO */
+
+/*
+ * S5P6440 GPIO bank summary:
+ *
+ * Bank GPIOs Style SlpCon ExtInt Group
+ * A 6 4Bit Yes 1
+ * B 7 4Bit Yes 1
+ * C 8 4Bit Yes 2
+ * F 2 2Bit Yes 4 [1]
+ * G 7 4Bit Yes 5
+ * H 10 4Bit[2] Yes 6
+ * I 16 2Bit Yes None
+ * J 12 2Bit Yes None
+ * N 16 2Bit No IRQ_EINT
+ * P 8 2Bit Yes 8
+ * R 15 4Bit[2] Yes 8
+ *
+ * [1] BANKF pins 14,15 do not form part of the external interrupt sources
+ * [2] BANK has two control registers, GPxCON0 and GPxCON1
+ */
-static int s5p6440_gpiolib_rbank_4bit2_input(struct gpio_chip *chip,
+static int s5p64x0_gpiolib_rbank_4bit2_input(struct gpio_chip *chip,
unsigned int offset)
{
struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
@@ -77,7 +80,7 @@ static int s5p6440_gpiolib_rbank_4bit2_input(struct gpio_chip *chip,
return 0;
}
-static int s5p6440_gpiolib_rbank_4bit2_output(struct gpio_chip *chip,
+static int s5p64x0_gpiolib_rbank_4bit2_output(struct gpio_chip *chip,
unsigned int offset, int value)
{
struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
@@ -124,12 +127,11 @@ static int s5p6440_gpiolib_rbank_4bit2_output(struct gpio_chip *chip,
return 0;
}
-int s5p6440_gpio_setcfg_4bit_rbank(struct s3c_gpio_chip *chip,
+int s5p64x0_gpio_setcfg_4bit_rbank(struct s3c_gpio_chip *chip,
unsigned int off, unsigned int cfg)
{
void __iomem *reg = chip->base;
unsigned int shift;
- unsigned long flags;
u32 con;
switch (off) {
@@ -155,26 +157,22 @@ int s5p6440_gpio_setcfg_4bit_rbank(struct s3c_gpio_chip *chip,
cfg <<= shift;
}
- s3c_gpio_lock(chip, flags);
-
con = __raw_readl(reg);
con &= ~(0xf << shift);
con |= cfg;
__raw_writel(con, reg);
- s3c_gpio_unlock(chip, flags);
-
return 0;
}
-static struct s3c_gpio_cfg s5p6440_gpio_cfgs[] = {
+static struct s3c_gpio_cfg s5p64x0_gpio_cfgs[] = {
{
.cfg_eint = 0,
}, {
.cfg_eint = 7,
}, {
.cfg_eint = 3,
- .set_config = s5p6440_gpio_setcfg_4bit_rbank,
+ .set_config = s5p64x0_gpio_setcfg_4bit_rbank,
}, {
.cfg_eint = 0,
.set_config = s3c_gpio_setcfg_s3c24xx,
@@ -193,7 +191,7 @@ static struct s3c_gpio_cfg s5p6440_gpio_cfgs[] = {
static struct s3c_gpio_chip s5p6440_gpio_4bit[] = {
{
.base = S5P6440_GPA_BASE,
- .config = &s5p6440_gpio_cfgs[1],
+ .config = &s5p64x0_gpio_cfgs[1],
.chip = {
.base = S5P6440_GPA(0),
.ngpio = S5P6440_GPIO_A_NR,
@@ -201,7 +199,7 @@ static struct s3c_gpio_chip s5p6440_gpio_4bit[] = {
},
}, {
.base = S5P6440_GPB_BASE,
- .config = &s5p6440_gpio_cfgs[1],
+ .config = &s5p64x0_gpio_cfgs[1],
.chip = {
.base = S5P6440_GPB(0),
.ngpio = S5P6440_GPIO_B_NR,
@@ -209,7 +207,7 @@ static struct s3c_gpio_chip s5p6440_gpio_4bit[] = {
},
}, {
.base = S5P6440_GPC_BASE,
- .config = &s5p6440_gpio_cfgs[1],
+ .config = &s5p64x0_gpio_cfgs[1],
.chip = {
.base = S5P6440_GPC(0),
.ngpio = S5P6440_GPIO_C_NR,
@@ -217,7 +215,7 @@ static struct s3c_gpio_chip s5p6440_gpio_4bit[] = {
},
}, {
.base = S5P6440_GPG_BASE,
- .config = &s5p6440_gpio_cfgs[1],
+ .config = &s5p64x0_gpio_cfgs[1],
.chip = {
.base = S5P6440_GPG(0),
.ngpio = S5P6440_GPIO_G_NR,
@@ -229,7 +227,7 @@ static struct s3c_gpio_chip s5p6440_gpio_4bit[] = {
static struct s3c_gpio_chip s5p6440_gpio_4bit2[] = {
{
.base = S5P6440_GPH_BASE + 0x4,
- .config = &s5p6440_gpio_cfgs[1],
+ .config = &s5p64x0_gpio_cfgs[1],
.chip = {
.base = S5P6440_GPH(0),
.ngpio = S5P6440_GPIO_H_NR,
@@ -238,10 +236,10 @@ static struct s3c_gpio_chip s5p6440_gpio_4bit2[] = {
},
};
-static struct s3c_gpio_chip gpio_rbank_4bit2[] = {
+static struct s3c_gpio_chip s5p6440_gpio_rbank_4bit2[] = {
{
.base = S5P6440_GPR_BASE + 0x4,
- .config = &s5p6440_gpio_cfgs[2],
+ .config = &s5p64x0_gpio_cfgs[2],
.chip = {
.base = S5P6440_GPR(0),
.ngpio = S5P6440_GPIO_R_NR,
@@ -253,7 +251,7 @@ static struct s3c_gpio_chip gpio_rbank_4bit2[] = {
static struct s3c_gpio_chip s5p6440_gpio_2bit[] = {
{
.base = S5P6440_GPF_BASE,
- .config = &s5p6440_gpio_cfgs[5],
+ .config = &s5p64x0_gpio_cfgs[5],
.chip = {
.base = S5P6440_GPF(0),
.ngpio = S5P6440_GPIO_F_NR,
@@ -261,7 +259,7 @@ static struct s3c_gpio_chip s5p6440_gpio_2bit[] = {
},
}, {
.base = S5P6440_GPI_BASE,
- .config = &s5p6440_gpio_cfgs[3],
+ .config = &s5p64x0_gpio_cfgs[3],
.chip = {
.base = S5P6440_GPI(0),
.ngpio = S5P6440_GPIO_I_NR,
@@ -269,7 +267,7 @@ static struct s3c_gpio_chip s5p6440_gpio_2bit[] = {
},
}, {
.base = S5P6440_GPJ_BASE,
- .config = &s5p6440_gpio_cfgs[3],
+ .config = &s5p64x0_gpio_cfgs[3],
.chip = {
.base = S5P6440_GPJ(0),
.ngpio = S5P6440_GPIO_J_NR,
@@ -277,7 +275,7 @@ static struct s3c_gpio_chip s5p6440_gpio_2bit[] = {
},
}, {
.base = S5P6440_GPN_BASE,
- .config = &s5p6440_gpio_cfgs[4],
+ .config = &s5p64x0_gpio_cfgs[4],
.chip = {
.base = S5P6440_GPN(0),
.ngpio = S5P6440_GPIO_N_NR,
@@ -285,7 +283,7 @@ static struct s3c_gpio_chip s5p6440_gpio_2bit[] = {
},
}, {
.base = S5P6440_GPP_BASE,
- .config = &s5p6440_gpio_cfgs[5],
+ .config = &s5p64x0_gpio_cfgs[5],
.chip = {
.base = S5P6440_GPP(0),
.ngpio = S5P6440_GPIO_P_NR,
@@ -294,7 +292,7 @@ static struct s3c_gpio_chip s5p6440_gpio_2bit[] = {
},
};
-void __init s5p6440_gpiolib_set_cfg(struct s3c_gpio_cfg *chipcfg, int nr_chips)
+void __init s5p64x0_gpiolib_set_cfg(struct s3c_gpio_cfg *chipcfg, int nr_chips)
{
for (; nr_chips > 0; nr_chips--, chipcfg++) {
if (!chipcfg->set_config)
@@ -308,13 +306,13 @@ void __init s5p6440_gpiolib_set_cfg(struct s3c_gpio_cfg *chipcfg, int nr_chips)
}
}
-static void __init s5p6440_gpio_add_rbank_4bit2(struct s3c_gpio_chip *chip,
+static void __init s5p64x0_gpio_add_rbank_4bit2(struct s3c_gpio_chip *chip,
int nr_chips)
{
for (; nr_chips > 0; nr_chips--, chip++) {
- chip->chip.direction_input = s5p6440_gpiolib_rbank_4bit2_input;
+ chip->chip.direction_input = s5p64x0_gpiolib_rbank_4bit2_input;
chip->chip.direction_output =
- s5p6440_gpiolib_rbank_4bit2_output;
+ s5p64x0_gpiolib_rbank_4bit2_output;
s3c_gpiolib_add(chip);
}
}
@@ -324,8 +322,8 @@ static int __init s5p6440_gpiolib_init(void)
struct s3c_gpio_chip *chips = s5p6440_gpio_2bit;
int nr_chips = ARRAY_SIZE(s5p6440_gpio_2bit);
- s5p6440_gpiolib_set_cfg(s5p6440_gpio_cfgs,
- ARRAY_SIZE(s5p6440_gpio_cfgs));
+ s5p64x0_gpiolib_set_cfg(s5p64x0_gpio_cfgs,
+ ARRAY_SIZE(s5p64x0_gpio_cfgs));
for (; nr_chips > 0; nr_chips--, chips++)
s3c_gpiolib_add(chips);
@@ -336,8 +334,8 @@ static int __init s5p6440_gpiolib_init(void)
samsung_gpiolib_add_4bit2_chips(s5p6440_gpio_4bit2,
ARRAY_SIZE(s5p6440_gpio_4bit2));
- s5p6440_gpio_add_rbank_4bit2(gpio_rbank_4bit2,
- ARRAY_SIZE(gpio_rbank_4bit2));
+ s5p64x0_gpio_add_rbank_4bit2(s5p6440_gpio_rbank_4bit2,
+ ARRAY_SIZE(s5p6440_gpio_rbank_4bit2));
return 0;
}
diff --git a/arch/arm/mach-s5p64x0/include/mach/debug-macro.S b/arch/arm/mach-s5p64x0/include/mach/debug-macro.S
new file mode 100644
index 000000000000..79b04e6a6f8e
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/include/mach/debug-macro.S
@@ -0,0 +1,33 @@
+/* linux/arch/arm/mach-s5p64x0/include/mach/debug-macro.S
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/* pull in the relevant register and map files. */
+
+#include <plat/map-base.h>
+#include <plat/map-s5p.h>
+
+#include <plat/regs-serial.h>
+
+ .macro addruart, rp, rv
+ mov \rp, #0xE0000000
+ orr \rp, \rp, #0x00100000
+ ldr \rp, [\rp, #0x118 ]
+ and \rp, \rp, #0xff000
+ teq \rp, #0x50000 @@ S5P6450
+ ldreq \rp, =0xEC800000
+ movne \rp, #0xEC000000 @@ S5P6440
+ ldrne \rv, = S3C_VA_UART
+#if CONFIG_DEBUG_S3C_UART != 0
+ add \rp, \rp, #(0x400 * CONFIG_DEBUG_S3C_UART)
+ add \rv, \rv, #(0x400 * CONFIG_DEBUG_S3C_UART)
+#endif
+ .endm
+
+#include <plat/debug-macro.S>
diff --git a/arch/arm/mach-s5p6440/include/mach/dma.h b/arch/arm/mach-s5p64x0/include/mach/dma.h
index 81209eb1409b..81209eb1409b 100644
--- a/arch/arm/mach-s5p6440/include/mach/dma.h
+++ b/arch/arm/mach-s5p64x0/include/mach/dma.h
diff --git a/arch/arm/mach-s5p6440/include/mach/entry-macro.S b/arch/arm/mach-s5p64x0/include/mach/entry-macro.S
index e65f1b967262..10b62b4f8211 100644
--- a/arch/arm/mach-s5p6440/include/mach/entry-macro.S
+++ b/arch/arm/mach-s5p64x0/include/mach/entry-macro.S
@@ -1,9 +1,9 @@
-/* linux/arch/arm/mach-s5p6440/include/mach/entry-macro.S
+/* linux/arch/arm/mach-s5p64x0/include/mach/entry-macro.S
*
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
*
- * Low-level IRQ helper macros for the Samsung S5P6440
+ * Low-level IRQ helper macros for the Samsung S5P64X0
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
diff --git a/arch/arm/mach-s5p64x0/include/mach/gpio.h b/arch/arm/mach-s5p64x0/include/mach/gpio.h
new file mode 100644
index 000000000000..5486c8f01f1d
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/include/mach/gpio.h
@@ -0,0 +1,139 @@
+/* linux/arch/arm/mach-s5p64x0/include/mach/gpio.h
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * S5P64X0 - GPIO lib support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_GPIO_H
+#define __ASM_ARCH_GPIO_H __FILE__
+
+#define gpio_get_value __gpio_get_value
+#define gpio_set_value __gpio_set_value
+#define gpio_cansleep __gpio_cansleep
+#define gpio_to_irq __gpio_to_irq
+
+/* GPIO bank sizes */
+
+#define S5P6440_GPIO_A_NR (6)
+#define S5P6440_GPIO_B_NR (7)
+#define S5P6440_GPIO_C_NR (8)
+#define S5P6440_GPIO_F_NR (2)
+#define S5P6440_GPIO_G_NR (7)
+#define S5P6440_GPIO_H_NR (10)
+#define S5P6440_GPIO_I_NR (16)
+#define S5P6440_GPIO_J_NR (12)
+#define S5P6440_GPIO_N_NR (16)
+#define S5P6440_GPIO_P_NR (8)
+#define S5P6440_GPIO_R_NR (15)
+
+#define S5P6450_GPIO_A_NR (6)
+#define S5P6450_GPIO_B_NR (7)
+#define S5P6450_GPIO_C_NR (8)
+#define S5P6450_GPIO_D_NR (8)
+#define S5P6450_GPIO_F_NR (2)
+#define S5P6450_GPIO_G_NR (14)
+#define S5P6450_GPIO_H_NR (10)
+#define S5P6450_GPIO_I_NR (16)
+#define S5P6450_GPIO_J_NR (12)
+#define S5P6450_GPIO_K_NR (5)
+#define S5P6450_GPIO_N_NR (16)
+#define S5P6450_GPIO_P_NR (11)
+#define S5P6450_GPIO_Q_NR (14)
+#define S5P6450_GPIO_R_NR (15)
+#define S5P6450_GPIO_S_NR (8)
+
+/* GPIO bank numbers */
+
+/* CONFIG_S3C_GPIO_SPACE allows the user to select extra
+ * space for debugging purposes so that any accidental
+ * change from one gpio bank to another can be caught.
+*/
+
+#define S5P64X0_GPIO_NEXT(__gpio) \
+ ((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 1)
+
+enum s5p6440_gpio_number {
+ S5P6440_GPIO_A_START = 0,
+ S5P6440_GPIO_B_START = S5P64X0_GPIO_NEXT(S5P6440_GPIO_A),
+ S5P6440_GPIO_C_START = S5P64X0_GPIO_NEXT(S5P6440_GPIO_B),
+ S5P6440_GPIO_F_START = S5P64X0_GPIO_NEXT(S5P6440_GPIO_C),
+ S5P6440_GPIO_G_START = S5P64X0_GPIO_NEXT(S5P6440_GPIO_F),
+ S5P6440_GPIO_H_START = S5P64X0_GPIO_NEXT(S5P6440_GPIO_G),
+ S5P6440_GPIO_I_START = S5P64X0_GPIO_NEXT(S5P6440_GPIO_H),
+ S5P6440_GPIO_J_START = S5P64X0_GPIO_NEXT(S5P6440_GPIO_I),
+ S5P6440_GPIO_N_START = S5P64X0_GPIO_NEXT(S5P6440_GPIO_J),
+ S5P6440_GPIO_P_START = S5P64X0_GPIO_NEXT(S5P6440_GPIO_N),
+ S5P6440_GPIO_R_START = S5P64X0_GPIO_NEXT(S5P6440_GPIO_P),
+};
+
+enum s5p6450_gpio_number {
+ S5P6450_GPIO_A_START = 0,
+ S5P6450_GPIO_B_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_A),
+ S5P6450_GPIO_C_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_B),
+ S5P6450_GPIO_D_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_C),
+ S5P6450_GPIO_F_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_D),
+ S5P6450_GPIO_G_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_F),
+ S5P6450_GPIO_H_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_G),
+ S5P6450_GPIO_I_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_H),
+ S5P6450_GPIO_J_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_I),
+ S5P6450_GPIO_K_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_J),
+ S5P6450_GPIO_N_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_K),
+ S5P6450_GPIO_P_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_N),
+ S5P6450_GPIO_Q_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_P),
+ S5P6450_GPIO_R_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_Q),
+ S5P6450_GPIO_S_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_R),
+};
+
+/* GPIO number definitions */
+
+#define S5P6440_GPA(_nr) (S5P6440_GPIO_A_START + (_nr))
+#define S5P6440_GPB(_nr) (S5P6440_GPIO_B_START + (_nr))
+#define S5P6440_GPC(_nr) (S5P6440_GPIO_C_START + (_nr))
+#define S5P6440_GPF(_nr) (S5P6440_GPIO_F_START + (_nr))
+#define S5P6440_GPG(_nr) (S5P6440_GPIO_G_START + (_nr))
+#define S5P6440_GPH(_nr) (S5P6440_GPIO_H_START + (_nr))
+#define S5P6440_GPI(_nr) (S5P6440_GPIO_I_START + (_nr))
+#define S5P6440_GPJ(_nr) (S5P6440_GPIO_J_START + (_nr))
+#define S5P6440_GPN(_nr) (S5P6440_GPIO_N_START + (_nr))
+#define S5P6440_GPP(_nr) (S5P6440_GPIO_P_START + (_nr))
+#define S5P6440_GPR(_nr) (S5P6440_GPIO_R_START + (_nr))
+
+#define S5P6450_GPA(_nr) (S5P6450_GPIO_A_START + (_nr))
+#define S5P6450_GPB(_nr) (S5P6450_GPIO_B_START + (_nr))
+#define S5P6450_GPC(_nr) (S5P6450_GPIO_C_START + (_nr))
+#define S5P6450_GPD(_nr) (S5P6450_GPIO_D_START + (_nr))
+#define S5P6450_GPF(_nr) (S5P6450_GPIO_F_START + (_nr))
+#define S5P6450_GPG(_nr) (S5P6450_GPIO_G_START + (_nr))
+#define S5P6450_GPH(_nr) (S5P6450_GPIO_H_START + (_nr))
+#define S5P6450_GPI(_nr) (S5P6450_GPIO_I_START + (_nr))
+#define S5P6450_GPJ(_nr) (S5P6450_GPIO_J_START + (_nr))
+#define S5P6450_GPK(_nr) (S5P6450_GPIO_K_START + (_nr))
+#define S5P6450_GPN(_nr) (S5P6450_GPIO_N_START + (_nr))
+#define S5P6450_GPP(_nr) (S5P6450_GPIO_P_START + (_nr))
+#define S5P6450_GPQ(_nr) (S5P6450_GPIO_Q_START + (_nr))
+#define S5P6450_GPR(_nr) (S5P6450_GPIO_R_START + (_nr))
+#define S5P6450_GPS(_nr) (S5P6450_GPIO_S_START + (_nr))
+
+/* the end of the S5P64X0 specific gpios */
+
+#define S5P6440_GPIO_END (S5P6440_GPR(S5P6440_GPIO_R_NR) + 1)
+#define S5P6450_GPIO_END (S5P6450_GPS(S5P6450_GPIO_S_NR) + 1)
+
+#define S5P64X0_GPIO_END (S5P6440_GPIO_END > S5P6450_GPIO_END ? \
+ S5P6440_GPIO_END : S5P6450_GPIO_END)
+
+#define S3C_GPIO_END S5P64X0_GPIO_END
+
+/* define the number of gpios we need to the one after the last GPIO range */
+
+#define ARCH_NR_GPIOS (S5P64X0_GPIO_END + CONFIG_SAMSUNG_GPIO_EXTRA)
+
+#include <asm-generic/gpio.h>
+
+#endif /* __ASM_ARCH_GPIO_H */
diff --git a/arch/arm/mach-s5p6440/include/mach/hardware.h b/arch/arm/mach-s5p64x0/include/mach/hardware.h
index be8b26e875db..d3e87996dd9a 100644
--- a/arch/arm/mach-s5p6440/include/mach/hardware.h
+++ b/arch/arm/mach-s5p64x0/include/mach/hardware.h
@@ -1,9 +1,9 @@
-/* linux/arch/arm/mach-s5p6440/include/mach/hardware.h
+/* linux/arch/arm/mach-s5p64x0/include/mach/hardware.h
*
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
*
- * S5P6440 - Hardware support
+ * S5P64X0 - Hardware support
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
diff --git a/arch/arm/mach-s5p64x0/include/mach/i2c.h b/arch/arm/mach-s5p64x0/include/mach/i2c.h
new file mode 100644
index 000000000000..887d25209e8e
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/include/mach/i2c.h
@@ -0,0 +1,17 @@
+/* linux/arch/arm/mach-s5p64x0/include/mach/i2c.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * S5P64X0 I2C configuration
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+extern void s5p6440_i2c0_cfg_gpio(struct platform_device *dev);
+extern void s5p6440_i2c1_cfg_gpio(struct platform_device *dev);
+
+extern void s5p6450_i2c0_cfg_gpio(struct platform_device *dev);
+extern void s5p6450_i2c1_cfg_gpio(struct platform_device *dev);
diff --git a/arch/arm/mach-s5p64x0/include/mach/io.h b/arch/arm/mach-s5p64x0/include/mach/io.h
new file mode 100644
index 000000000000..a3e095c02fb5
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/include/mach/io.h
@@ -0,0 +1,25 @@
+/* linux/arch/arm/mach-s5p64x0/include/mach/io.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Copyright 2008 Simtec Electronics
+ * Ben Dooks <ben-linux@fluff.org>
+ *
+ * Default IO routines for S5P64X0 based
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+/* No current ISA/PCI bus support. */
+#define __io(a) __typesafe_io(a)
+#define __mem_pci(a) (a)
+
+#define IO_SPACE_LIMIT (0xFFFFFFFF)
+
+#endif
diff --git a/arch/arm/mach-s5p6440/include/mach/irqs.h b/arch/arm/mach-s5p64x0/include/mach/irqs.h
index 16a761270de1..513abffc7604 100644
--- a/arch/arm/mach-s5p6440/include/mach/irqs.h
+++ b/arch/arm/mach-s5p64x0/include/mach/irqs.h
@@ -1,17 +1,17 @@
-/* linux/arch/arm/mach-s5p6440/include/mach/irqs.h
+/* linux/arch/arm/mach-s5p64x0/include/mach/irqs.h
*
- * Copyright 2009 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
+ * Copyright 2009-2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
*
- * S5P6440 - IRQ definitions
+ * S5P64X0 - IRQ definitions
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-#ifndef __ASM_ARCH_S5P_IRQS_H
-#define __ASM_ARCH_S5P_IRQS_H __FILE__
+#ifndef __ASM_ARCH_IRQS_H
+#define __ASM_ARCH_IRQS_H __FILE__
#include <plat/irqs.h>
@@ -20,10 +20,12 @@
#define IRQ_EINT0_3 S5P_IRQ_VIC0(0)
#define IRQ_EINT4_11 S5P_IRQ_VIC0(1)
#define IRQ_RTC_TIC S5P_IRQ_VIC0(2)
+#define IRQ_IIS1 S5P_IRQ_VIC0(3) /* for only S5P6450 */
+#define IRQ_IIS2 S5P_IRQ_VIC0(4) /* for only S5P6450 */
#define IRQ_IIC1 S5P_IRQ_VIC0(5)
#define IRQ_I2SV40 S5P_IRQ_VIC0(6)
-#define IRQ_GPS S5P_IRQ_VIC0(7)
-#define IRQ_POST0 S5P_IRQ_VIC0(9)
+#define IRQ_GPS S5P_IRQ_VIC0(7) /* for only S5P6450 */
+
#define IRQ_2D S5P_IRQ_VIC0(11)
#define IRQ_TIMER0_VIC S5P_IRQ_VIC0(23)
#define IRQ_TIMER1_VIC S5P_IRQ_VIC0(24)
@@ -39,22 +41,26 @@
#define IRQ_EINT12_15 S5P_IRQ_VIC1(0)
#define IRQ_PCM0 S5P_IRQ_VIC1(2)
+#define IRQ_PCM1 S5P_IRQ_VIC1(3) /* for only S5P6450 */
+#define IRQ_PCM2 S5P_IRQ_VIC1(4) /* for only S5P6450 */
#define IRQ_UART0 S5P_IRQ_VIC1(5)
#define IRQ_UART1 S5P_IRQ_VIC1(6)
#define IRQ_UART2 S5P_IRQ_VIC1(7)
#define IRQ_UART3 S5P_IRQ_VIC1(8)
#define IRQ_DMA0 S5P_IRQ_VIC1(9)
+#define IRQ_UART4 S5P_IRQ_VIC1(10) /* S5P6450 */
+#define IRQ_UART5 S5P_IRQ_VIC1(11) /* S5P6450 */
#define IRQ_NFC S5P_IRQ_VIC1(13)
+#define IRQ_USI S5P_IRQ_VIC1(15) /* S5P6450 */
#define IRQ_SPI0 S5P_IRQ_VIC1(16)
#define IRQ_SPI1 S5P_IRQ_VIC1(17)
+#define IRQ_HSMMC2 S5P_IRQ_VIC1(17) /* Shared */
#define IRQ_IIC S5P_IRQ_VIC1(18)
#define IRQ_DISPCON3 S5P_IRQ_VIC1(19)
-#define IRQ_FIMGVG S5P_IRQ_VIC1(20)
#define IRQ_EINT_GROUPS S5P_IRQ_VIC1(21)
-#define IRQ_PMU S5P_IRQ_VIC1(23)
+#define IRQ_PMU S5P_IRQ_VIC1(23) /* S5P6440 */
#define IRQ_HSMMC0 S5P_IRQ_VIC1(24)
#define IRQ_HSMMC1 S5P_IRQ_VIC1(25)
-#define IRQ_HSMMC2 IRQ_SPI1 /* shared with SPI1 */
#define IRQ_OTG S5P_IRQ_VIC1(26)
#define IRQ_DSI S5P_IRQ_VIC1(27)
#define IRQ_RTC_ALARM S5P_IRQ_VIC1(28)
@@ -63,6 +69,24 @@
#define IRQ_TC IRQ_PENDN
#define IRQ_ADC S5P_IRQ_VIC1(31)
+/* UART interrupts, S5P6450 has 5 UARTs */
+#define IRQ_S5P_UART_BASE4 (96)
+#define IRQ_S5P_UART_BASE5 (100)
+
+#define IRQ_S5P_UART_RX4 (IRQ_S5P_UART_BASE4 + UART_IRQ_RXD)
+#define IRQ_S5P_UART_TX4 (IRQ_S5P_UART_BASE4 + UART_IRQ_TXD)
+#define IRQ_S5P_UART_ERR4 (IRQ_S5P_UART_BASE4 + UART_IRQ_ERR)
+
+#define IRQ_S5P_UART_RX5 (IRQ_S5P_UART_BASE5 + UART_IRQ_RXD)
+#define IRQ_S5P_UART_TX5 (IRQ_S5P_UART_BASE5 + UART_IRQ_TXD)
+#define IRQ_S5P_UART_ERR5 (IRQ_S5P_UART_BASE5 + UART_IRQ_ERR)
+
+/* S3C compatibilty defines */
+#define IRQ_S3CUART_RX4 IRQ_S5P_UART_RX4
+#define IRQ_S3CUART_RX5 IRQ_S5P_UART_RX5
+
+/* S5P6450 EINT feature will be added */
+
/*
* Since the IRQ_EINT(x) are a linear mapping on s5p6440 we just defined
* them as an IRQ_EINT(x) macro from S5P_IRQ_EINT_BASE which we place
@@ -115,4 +139,4 @@
#define NR_IRQS (IRQ_EINT_GROUP8_BASE + IRQ_EINT_GROUP8_NR + 1)
-#endif /* __ASM_ARCH_S5P_IRQS_H */
+#endif /* __ASM_ARCH_IRQS_H */
diff --git a/arch/arm/mach-s5p64x0/include/mach/map.h b/arch/arm/mach-s5p64x0/include/mach/map.h
new file mode 100644
index 000000000000..31e534156e06
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/include/mach/map.h
@@ -0,0 +1,83 @@
+/* linux/arch/arm/mach-s5p64x0/include/mach/map.h
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * S5P64X0 - Memory map definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_MAP_H
+#define __ASM_ARCH_MAP_H __FILE__
+
+#include <plat/map-base.h>
+#include <plat/map-s5p.h>
+
+#define S5P64X0_PA_SDRAM (0x20000000)
+
+#define S5P64X0_PA_CHIPID (0xE0000000)
+#define S5P_PA_CHIPID S5P64X0_PA_CHIPID
+
+#define S5P64X0_PA_SYSCON (0xE0100000)
+#define S5P_PA_SYSCON S5P64X0_PA_SYSCON
+
+#define S5P64X0_PA_GPIO (0xE0308000)
+
+#define S5P64X0_PA_VIC0 (0xE4000000)
+#define S5P64X0_PA_VIC1 (0xE4100000)
+
+#define S5P64X0_PA_PDMA (0xE9000000)
+
+#define S5P64X0_PA_TIMER (0xEA000000)
+#define S5P_PA_TIMER S5P64X0_PA_TIMER
+
+#define S5P64X0_PA_RTC (0xEA100000)
+
+#define S5P64X0_PA_WDT (0xEA200000)
+
+#define S5P6440_PA_UART(x) (0xEC000000 + ((x) * S3C_UART_OFFSET))
+#define S5P6450_PA_UART(x) ((x < 5) ? (0xEC800000 + ((x) * S3C_UART_OFFSET)) : (0xEC000000))
+
+#define S5P_PA_UART0 S5P6450_PA_UART(0)
+#define S5P_PA_UART1 S5P6450_PA_UART(1)
+#define S5P_PA_UART2 S5P6450_PA_UART(2)
+#define S5P_PA_UART3 S5P6450_PA_UART(3)
+#define S5P_PA_UART4 S5P6450_PA_UART(4)
+#define S5P_PA_UART5 S5P6450_PA_UART(5)
+
+#define S5P_SZ_UART SZ_256
+
+#define S5P6440_PA_IIC0 (0xEC104000)
+#define S5P6440_PA_IIC1 (0xEC20F000)
+#define S5P6450_PA_IIC0 (0xEC100000)
+#define S5P6450_PA_IIC1 (0xEC200000)
+
+#define S5P64X0_PA_SPI0 (0xEC400000)
+#define S5P64X0_PA_SPI1 (0xEC500000)
+
+#define S5P64X0_PA_HSOTG (0xED100000)
+
+#define S5P64X0_PA_HSMMC(x) (0xED800000 + ((x) * 0x100000))
+
+#define S5P64X0_PA_I2S (0xF2000000)
+
+#define S5P64X0_PA_PCM (0xF2100000)
+
+#define S5P64X0_PA_ADC (0xF3000000)
+
+/* compatibiltiy defines. */
+
+#define S3C_PA_HSMMC0 S5P64X0_PA_HSMMC(0)
+#define S3C_PA_HSMMC1 S5P64X0_PA_HSMMC(1)
+#define S3C_PA_HSMMC2 S5P64X0_PA_HSMMC(2)
+#define S3C_PA_IIC S5P6440_PA_IIC0
+#define S3C_PA_IIC1 S5P6440_PA_IIC1
+#define S3C_PA_RTC S5P64X0_PA_RTC
+#define S3C_PA_WDT S5P64X0_PA_WDT
+
+#define SAMSUNG_PA_ADC S5P64X0_PA_ADC
+
+#endif /* __ASM_ARCH_MAP_H */
diff --git a/arch/arm/mach-s5p6440/include/mach/memory.h b/arch/arm/mach-s5p64x0/include/mach/memory.h
index d62910c71b56..1b036b0a24ce 100644
--- a/arch/arm/mach-s5p6440/include/mach/memory.h
+++ b/arch/arm/mach-s5p64x0/include/mach/memory.h
@@ -1,9 +1,9 @@
-/* linux/arch/arm/mach-s5p6440/include/mach/memory.h
+/* linux/arch/arm/mach-s5p64x0/include/mach/memory.h
*
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
*
- * S5P6440 - Memory definitions
+ * S5P64X0 - Memory definitions
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -11,9 +11,9 @@
*/
#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H __FILE__
-#define PHYS_OFFSET UL(0x20000000)
+#define PHYS_OFFSET UL(0x20000000)
#define CONSISTENT_DMA_SIZE SZ_8M
#endif /* __ASM_ARCH_MEMORY_H */
diff --git a/arch/arm/mach-s5p6440/include/mach/pwm-clock.h b/arch/arm/mach-s5p64x0/include/mach/pwm-clock.h
index 6a2a02fdf12a..19fff8b701c0 100644
--- a/arch/arm/mach-s5p6440/include/mach/pwm-clock.h
+++ b/arch/arm/mach-s5p64x0/include/mach/pwm-clock.h
@@ -1,16 +1,14 @@
-/* linux/arch/arm/mach-s5p6440/include/mach/pwm-clock.h
+/* linux/arch/arm/mach-s5p64x0/include/mach/pwm-clock.h
*
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
*
* Copyright 2008 Openmoko, Inc.
* Copyright 2008 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
* http://armlinux.simtec.co.uk/
*
- * Based on arch/arm/mach-s3c64xx/include/mach/pwm-clock.h
- *
- * S5P6440 - pwm clock and timer support
+ * S5P64X0 - pwm clock and timer support
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
diff --git a/arch/arm/mach-s5p64x0/include/mach/regs-clock.h b/arch/arm/mach-s5p64x0/include/mach/regs-clock.h
new file mode 100644
index 000000000000..58e1bc813804
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/include/mach/regs-clock.h
@@ -0,0 +1,63 @@
+/* linux/arch/arm/mach-s5p64x0/include/mach/regs-clock.h
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * S5P64X0 - Clock register definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_REGS_CLOCK_H
+#define __ASM_ARCH_REGS_CLOCK_H __FILE__
+
+#include <mach/map.h>
+
+#define S5P_CLKREG(x) (S3C_VA_SYS + (x))
+
+#define S5P64X0_APLL_CON S5P_CLKREG(0x0C)
+#define S5P64X0_MPLL_CON S5P_CLKREG(0x10)
+#define S5P64X0_EPLL_CON S5P_CLKREG(0x14)
+#define S5P64X0_EPLL_CON_K S5P_CLKREG(0x18)
+
+#define S5P64X0_CLK_SRC0 S5P_CLKREG(0x1C)
+
+#define S5P64X0_CLK_DIV0 S5P_CLKREG(0x20)
+#define S5P64X0_CLK_DIV1 S5P_CLKREG(0x24)
+#define S5P64X0_CLK_DIV2 S5P_CLKREG(0x28)
+
+#define S5P64X0_CLK_GATE_HCLK0 S5P_CLKREG(0x30)
+#define S5P64X0_CLK_GATE_PCLK S5P_CLKREG(0x34)
+#define S5P64X0_CLK_GATE_SCLK0 S5P_CLKREG(0x38)
+#define S5P64X0_CLK_GATE_MEM0 S5P_CLKREG(0x3C)
+
+#define S5P64X0_CLK_DIV3 S5P_CLKREG(0x40)
+
+#define S5P64X0_CLK_GATE_HCLK1 S5P_CLKREG(0x44)
+#define S5P64X0_CLK_GATE_SCLK1 S5P_CLKREG(0x48)
+
+#define S5P6450_DPLL_CON S5P_CLKREG(0x50)
+#define S5P6450_DPLL_CON_K S5P_CLKREG(0x54)
+
+#define S5P64X0_CLK_SRC1 S5P_CLKREG(0x10C)
+
+#define S5P64X0_SYS_ID S5P_CLKREG(0x118)
+#define S5P64X0_SYS_OTHERS S5P_CLKREG(0x11C)
+
+#define S5P64X0_PWR_CFG S5P_CLKREG(0x804)
+#define S5P64X0_OTHERS S5P_CLKREG(0x900)
+
+#define S5P64X0_CLKDIV0_HCLK_SHIFT (8)
+#define S5P64X0_CLKDIV0_HCLK_MASK (0xF << S5P64X0_CLKDIV0_HCLK_SHIFT)
+
+#define S5P64X0_OTHERS_USB_SIG_MASK (1 << 16)
+
+/* Compatibility defines */
+
+#define ARM_CLK_DIV S5P64X0_CLK_DIV0
+#define ARM_DIV_RATIO_SHIFT 0
+#define ARM_DIV_MASK (0xF << ARM_DIV_RATIO_SHIFT)
+
+#endif /* __ASM_ARCH_REGS_CLOCK_H */
diff --git a/arch/arm/mach-s5p6440/include/mach/regs-gpio.h b/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h
index 82ff753913da..85f448e20a8b 100644
--- a/arch/arm/mach-s5p6440/include/mach/regs-gpio.h
+++ b/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h
@@ -1,21 +1,24 @@
-/* linux/arch/arm/mach-s5p6440/include/mach/regs-gpio.h
+/* linux/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h
*
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
*
- * S5P6440 - GPIO register definitions
+ * S5P64X0 - GPIO register definitions
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- */
+*/
#ifndef __ASM_ARCH_REGS_GPIO_H
#define __ASM_ARCH_REGS_GPIO_H __FILE__
#include <mach/map.h>
+/* Will be implemented S5P6442 GPIOlib */
+
/* Base addresses for each of the banks */
+
#define S5P6440_GPA_BASE (S5P_VA_GPIO + 0x0000)
#define S5P6440_GPB_BASE (S5P_VA_GPIO + 0x0020)
#define S5P6440_GPC_BASE (S5P_VA_GPIO + 0x0040)
@@ -27,6 +30,7 @@
#define S5P6440_GPN_BASE (S5P_VA_GPIO + 0x0830)
#define S5P6440_GPP_BASE (S5P_VA_GPIO + 0x0160)
#define S5P6440_GPR_BASE (S5P_VA_GPIO + 0x0290)
+
#define S5P6440_EINT0CON0 (S5P_VA_GPIO + 0x900)
#define S5P6440_EINT0FLTCON0 (S5P_VA_GPIO + 0x910)
#define S5P6440_EINT0FLTCON1 (S5P_VA_GPIO + 0x914)
@@ -34,19 +38,23 @@
#define S5P6440_EINT0PEND (S5P_VA_GPIO + 0x924)
/* for LCD */
+
#define S5P6440_SPCON_LCD_SEL_RGB (1 << 0)
#define S5P6440_SPCON_LCD_SEL_MASK (3 << 0)
-/* These set of macros are not really useful for the
- * GPF/GPI/GPJ/GPN/GPP,
- * useful for others set of GPIO's (4 bit)
+/*
+ * These set of macros are not really useful for the
+ * GPF/GPI/GPJ/GPN/GPP, useful for others set of GPIO's (4 bit)
*/
+
#define S5P6440_GPIO_CONMASK(__gpio) (0xf << ((__gpio) * 4))
#define S5P6440_GPIO_INPUT(__gpio) (0x0 << ((__gpio) * 4))
#define S5P6440_GPIO_OUTPUT(__gpio) (0x1 << ((__gpio) * 4))
-/* Use these macros for GPF/GPI/GPJ/GPN/GPP set of GPIO (2 bit)
- * */
+/*
+ * Use these macros for GPF/GPI/GPJ/GPN/GPP set of GPIO (2 bit)
+ */
+
#define S5P6440_GPIO2_CONMASK(__gpio) (0x3 << ((__gpio) * 2))
#define S5P6440_GPIO2_INPUT(__gpio) (0x0 << ((__gpio) * 2))
#define S5P6440_GPIO2_OUTPUT(__gpio) (0x1 << ((__gpio) * 2))
diff --git a/arch/arm/mach-s5p6440/include/mach/regs-irq.h b/arch/arm/mach-s5p64x0/include/mach/regs-irq.h
index a961f4beeb0c..4aaebdace55f 100644
--- a/arch/arm/mach-s5p6440/include/mach/regs-irq.h
+++ b/arch/arm/mach-s5p64x0/include/mach/regs-irq.h
@@ -1,9 +1,9 @@
-/* linux/arch/arm/mach-s5p6440/include/mach/regs-irq.h
+/* linux/arch/arm/mach-s5p64x0/include/mach/regs-irq.h
*
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
*
- * S5P6440 - IRQ register definitions
+ * S5P64X0 - IRQ register definitions
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
diff --git a/arch/arm/mach-s5p64x0/include/mach/s5p64x0-clock.h b/arch/arm/mach-s5p64x0/include/mach/s5p64x0-clock.h
new file mode 100644
index 000000000000..ff85b4b6e8d9
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/include/mach/s5p64x0-clock.h
@@ -0,0 +1,46 @@
+/* linux/arch/arm/mach-s5p64x0/include/mach/s5p64x0-clock.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Header file for s5p64x0 clock support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_CLOCK_H
+#define __ASM_ARCH_CLOCK_H __FILE__
+
+#include <linux/clk.h>
+
+extern struct clksrc_clk clk_mout_apll;
+extern struct clksrc_clk clk_mout_mpll;
+extern struct clksrc_clk clk_mout_epll;
+
+extern int s5p64x0_epll_enable(struct clk *clk, int enable);
+extern unsigned long s5p64x0_epll_get_rate(struct clk *clk);
+
+extern unsigned long s5p64x0_armclk_get_rate(struct clk *clk);
+extern unsigned long s5p64x0_armclk_round_rate(struct clk *clk, unsigned long rate);
+extern int s5p64x0_armclk_set_rate(struct clk *clk, unsigned long rate);
+
+extern struct clk_ops s5p64x0_clkarm_ops;
+
+extern struct clksrc_clk clk_armclk;
+extern struct clksrc_clk clk_dout_mpll;
+
+extern struct clk *clkset_hclk_low_list[];
+extern struct clksrc_sources clkset_hclk_low;
+
+extern int s5p64x0_pclk_ctrl(struct clk *clk, int enable);
+extern int s5p64x0_hclk0_ctrl(struct clk *clk, int enable);
+extern int s5p64x0_hclk1_ctrl(struct clk *clk, int enable);
+extern int s5p64x0_sclk_ctrl(struct clk *clk, int enable);
+extern int s5p64x0_sclk1_ctrl(struct clk *clk, int enable);
+extern int s5p64x0_mem_ctrl(struct clk *clk, int enable);
+
+extern int s5p64x0_clk48m_ctrl(struct clk *clk, int enable);
+
+#endif /* __ASM_ARCH_CLOCK_H */
diff --git a/arch/arm/mach-s5p64x0/include/mach/spi-clocks.h b/arch/arm/mach-s5p64x0/include/mach/spi-clocks.h
new file mode 100644
index 000000000000..170a20a9643a
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/include/mach/spi-clocks.h
@@ -0,0 +1,20 @@
+/* linux/arch/arm/mach-s5p64x0/include/mach/spi-clocks.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Copyright (C) 2010 Samsung Electronics Co. Ltd.
+ * Jaswinder Singh <jassi.brar@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_SPI_CLKS_H
+#define __ASM_ARCH_SPI_CLKS_H __FILE__
+
+#define S5P64X0_SPI_SRCCLK_PCLK 0
+#define S5P64X0_SPI_SRCCLK_SCLK 1
+
+#endif /* __ASM_ARCH_SPI_CLKS_H */
diff --git a/arch/arm/mach-s5p6440/include/mach/system.h b/arch/arm/mach-s5p64x0/include/mach/system.h
index a359ee3fa510..60f57532c970 100644
--- a/arch/arm/mach-s5p6440/include/mach/system.h
+++ b/arch/arm/mach-s5p64x0/include/mach/system.h
@@ -1,9 +1,9 @@
-/* linux/arch/arm/mach-s5p6440/include/mach/system.h
+/* linux/arch/arm/mach-s5p64x0/include/mach/system.h
*
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
*
- * S5P6440 - system support header
+ * S5P64X0 - system support header
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
diff --git a/arch/arm/mach-s5p6440/include/mach/tick.h b/arch/arm/mach-s5p64x0/include/mach/tick.h
index 2f25c7f07970..00aa7f1d8e51 100644
--- a/arch/arm/mach-s5p6440/include/mach/tick.h
+++ b/arch/arm/mach-s5p64x0/include/mach/tick.h
@@ -1,9 +1,14 @@
-/* linux/arch/arm/mach-s5p6440/include/mach/tick.h
+/* linux/arch/arm/mach-s5p64x0/include/mach/tick.h
*
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
*
- * S5P6440 - Timer tick support definitions
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ * http://armlinux.simtec.co.uk/
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * S5P64X0 - Timer tick support definitions
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
diff --git a/arch/arm/mach-s5p6440/include/mach/timex.h b/arch/arm/mach-s5p64x0/include/mach/timex.h
index fb2e8cd40829..4b91faa195a8 100644
--- a/arch/arm/mach-s5p6440/include/mach/timex.h
+++ b/arch/arm/mach-s5p64x0/include/mach/timex.h
@@ -1,9 +1,12 @@
-/* arch/arm/mach-s3c64xx/include/mach/timex.h
+/* linux/arch/arm/mach-s5p64x0/include/mach/timex.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
*
* Copyright (c) 2003-2005 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
- * S3C6400 - time parameters
+ * S5P64X0 - time parameters
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
diff --git a/arch/arm/mach-s5p64x0/include/mach/uncompress.h b/arch/arm/mach-s5p64x0/include/mach/uncompress.h
new file mode 100644
index 000000000000..c65b229aab23
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/include/mach/uncompress.h
@@ -0,0 +1,212 @@
+/* linux/arch/arm/mach-s5p64x0/include/mach/uncompress.h
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * S5P64X0 - uncompress code
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_UNCOMPRESS_H
+#define __ASM_ARCH_UNCOMPRESS_H
+
+#include <mach/map.h>
+
+/*
+ * cannot use commonly <plat/uncompress.h>
+ * because uart base of S5P6440 and S5P6450 is different
+ */
+
+typedef unsigned int upf_t; /* cannot include linux/serial_core.h */
+
+/* uart setup */
+
+static unsigned int fifo_mask;
+static unsigned int fifo_max;
+
+/* forward declerations */
+
+static void arch_detect_cpu(void);
+
+/* defines for UART registers */
+
+#include <plat/regs-serial.h>
+#include <plat/regs-watchdog.h>
+
+/* working in physical space... */
+#undef S3C2410_WDOGREG
+#define S3C2410_WDOGREG(x) ((S3C24XX_PA_WATCHDOG + (x)))
+
+/* how many bytes we allow into the FIFO at a time in FIFO mode */
+#define FIFO_MAX (14)
+
+static unsigned long uart_base;
+
+static __inline__ void get_uart_base(void)
+{
+ unsigned int chipid;
+
+ chipid = *(const volatile unsigned int __force *) 0xE0100118;
+
+ uart_base = S3C_UART_OFFSET * CONFIG_S3C_LOWLEVEL_UART_PORT;
+
+ if ((chipid & 0xff000) == 0x50000)
+ uart_base += 0xEC800000;
+ else
+ uart_base += 0xEC000000;
+}
+
+static __inline__ void uart_wr(unsigned int reg, unsigned int val)
+{
+ volatile unsigned int *ptr;
+
+ get_uart_base();
+ ptr = (volatile unsigned int *)(reg + uart_base);
+ *ptr = val;
+}
+
+static __inline__ unsigned int uart_rd(unsigned int reg)
+{
+ volatile unsigned int *ptr;
+
+ get_uart_base();
+ ptr = (volatile unsigned int *)(reg + uart_base);
+ return *ptr;
+}
+
+/*
+ * we can deal with the case the UARTs are being run
+ * in FIFO mode, so that we don't hold up our execution
+ * waiting for tx to happen...
+ */
+
+static void putc(int ch)
+{
+ if (uart_rd(S3C2410_UFCON) & S3C2410_UFCON_FIFOMODE) {
+ int level;
+
+ while (1) {
+ level = uart_rd(S3C2410_UFSTAT);
+ level &= fifo_mask;
+
+ if (level < fifo_max)
+ break;
+ }
+
+ } else {
+ /* not using fifos */
+
+ while ((uart_rd(S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE) != S3C2410_UTRSTAT_TXE)
+ barrier();
+ }
+
+ /* write byte to transmission register */
+ uart_wr(S3C2410_UTXH, ch);
+}
+
+static inline void flush(void)
+{
+}
+
+#define __raw_writel(d, ad) \
+ do { \
+ *((volatile unsigned int __force *)(ad)) = (d); \
+ } while (0)
+
+/*
+ * CONFIG_S3C_BOOT_WATCHDOG
+ *
+ * Simple boot-time watchdog setup, to reboot the system if there is
+ * any problem with the boot process
+ */
+
+#ifdef CONFIG_S3C_BOOT_WATCHDOG
+
+#define WDOG_COUNT (0xff00)
+
+static inline void arch_decomp_wdog(void)
+{
+ __raw_writel(WDOG_COUNT, S3C2410_WTCNT);
+}
+
+static void arch_decomp_wdog_start(void)
+{
+ __raw_writel(WDOG_COUNT, S3C2410_WTDAT);
+ __raw_writel(WDOG_COUNT, S3C2410_WTCNT);
+ __raw_writel(S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV128 | S3C2410_WTCON_RSTEN | S3C2410_WTCON_PRESCALE(0x80), S3C2410_WTCON);
+}
+
+#else
+#define arch_decomp_wdog_start()
+#define arch_decomp_wdog()
+#endif
+
+#ifdef CONFIG_S3C_BOOT_ERROR_RESET
+
+static void arch_decomp_error(const char *x)
+{
+ putstr("\n\n");
+ putstr(x);
+ putstr("\n\n -- System resetting\n");
+
+ __raw_writel(0x4000, S3C2410_WTDAT);
+ __raw_writel(0x4000, S3C2410_WTCNT);
+ __raw_writel(S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV128 | S3C2410_WTCON_RSTEN | S3C2410_WTCON_PRESCALE(0x40), S3C2410_WTCON);
+
+ while(1);
+}
+
+#define arch_error arch_decomp_error
+#endif
+
+#ifdef CONFIG_S3C_BOOT_UART_FORCE_FIFO
+static inline void arch_enable_uart_fifo(void)
+{
+ u32 fifocon = uart_rd(S3C2410_UFCON);
+
+ if (!(fifocon & S3C2410_UFCON_FIFOMODE)) {
+ fifocon |= S3C2410_UFCON_RESETBOTH;
+ uart_wr(S3C2410_UFCON, fifocon);
+
+ /* wait for fifo reset to complete */
+ while (1) {
+ fifocon = uart_rd(S3C2410_UFCON);
+ if (!(fifocon & S3C2410_UFCON_RESETBOTH))
+ break;
+ }
+ }
+}
+#else
+#define arch_enable_uart_fifo() do { } while(0)
+#endif
+
+static void arch_decomp_setup(void)
+{
+ /*
+ * we may need to setup the uart(s) here if we are not running
+ * on an BAST... the BAST will have left the uarts configured
+ * after calling linux.
+ */
+
+ arch_detect_cpu();
+ arch_decomp_wdog_start();
+
+ /*
+ * Enable the UART FIFOs if they where not enabled and our
+ * configuration says we should turn them on.
+ */
+
+ arch_enable_uart_fifo();
+}
+
+
+
+static void arch_detect_cpu(void)
+{
+ /* we do not need to do any cpu detection here at the moment. */
+}
+
+#endif /* __ASM_ARCH_UNCOMPRESS_H */
diff --git a/arch/arm/mach-s5p6440/include/mach/vmalloc.h b/arch/arm/mach-s5p64x0/include/mach/vmalloc.h
index e3f0eebf5205..97a9df38f1cf 100644
--- a/arch/arm/mach-s5p6440/include/mach/vmalloc.h
+++ b/arch/arm/mach-s5p64x0/include/mach/vmalloc.h
@@ -1,4 +1,7 @@
-/* arch/arm/mach-s5p6440/include/mach/vmalloc.h
+/* linux/arch/arm/mach-s5p64x0/include/mach/vmalloc.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
*
* Copyright 2010 Ben Dooks <ben-linux@fluff.org>
*
diff --git a/arch/arm/mach-s5p64x0/init.c b/arch/arm/mach-s5p64x0/init.c
new file mode 100644
index 000000000000..79833caf8165
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/init.c
@@ -0,0 +1,73 @@
+/* linux/arch/arm/mach-s5p64x0/init.c
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * S5P64X0 - Init support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/serial_core.h>
+
+#include <mach/map.h>
+
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/s5p6440.h>
+#include <plat/s5p6450.h>
+#include <plat/regs-serial.h>
+
+static struct s3c24xx_uart_clksrc s5p64x0_serial_clocks[] = {
+ [0] = {
+ .name = "pclk_low",
+ .divisor = 1,
+ .min_baud = 0,
+ .max_baud = 0,
+ },
+ [1] = {
+ .name = "uclk1",
+ .divisor = 1,
+ .min_baud = 0,
+ .max_baud = 0,
+ },
+};
+
+/* uart registration process */
+
+void __init s5p64x0_common_init_uarts(struct s3c2410_uartcfg *cfg, int no)
+{
+ struct s3c2410_uartcfg *tcfg = cfg;
+ u32 ucnt;
+
+ for (ucnt = 0; ucnt < no; ucnt++, tcfg++) {
+ if (!tcfg->clocks) {
+ tcfg->clocks = s5p64x0_serial_clocks;
+ tcfg->clocks_size = ARRAY_SIZE(s5p64x0_serial_clocks);
+ }
+ }
+}
+
+void __init s5p6440_init_uarts(struct s3c2410_uartcfg *cfg, int no)
+{
+ int uart;
+
+ for (uart = 0; uart < no; uart++) {
+ s5p_uart_resources[uart].resources->start = S5P6440_PA_UART(uart);
+ s5p_uart_resources[uart].resources->end = S5P6440_PA_UART(uart) + S5P_SZ_UART;
+ }
+
+ s5p64x0_common_init_uarts(cfg, no);
+ s3c24xx_init_uartdevs("s3c6400-uart", s5p_uart_resources, cfg, no);
+}
+
+void __init s5p6450_init_uarts(struct s3c2410_uartcfg *cfg, int no)
+{
+ s5p64x0_common_init_uarts(cfg, no);
+ s3c24xx_init_uartdevs("s3c6400-uart", s5p_uart_resources, cfg, no);
+}
diff --git a/arch/arm/mach-s5p6440/mach-smdk6440.c b/arch/arm/mach-s5p64x0/mach-smdk6440.c
index 9202aaac3b56..87c3f03c618c 100644
--- a/arch/arm/mach-s5p6440/mach-smdk6440.c
+++ b/arch/arm/mach-s5p64x0/mach-smdk6440.c
@@ -1,7 +1,7 @@
-/* linux/arch/arm/mach-s5p6440/mach-smdk6440.c
+/* linux/arch/arm/mach-s5p64x0/mach-smdk6440.c
*
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -21,21 +21,22 @@
#include <linux/io.h>
#include <linux/module.h>
#include <linux/clk.h>
+#include <linux/gpio.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
#include <mach/hardware.h>
#include <mach/map.h>
-
-#include <asm/irq.h>
-#include <asm/mach-types.h>
+#include <mach/regs-clock.h>
+#include <mach/i2c.h>
#include <plat/regs-serial.h>
-
+#include <plat/gpio-cfg.h>
#include <plat/s5p6440.h>
#include <plat/clock.h>
-#include <mach/regs-clock.h>
#include <plat/devs.h>
#include <plat/cpu.h>
#include <plat/iic.h>
@@ -58,43 +59,60 @@
static struct s3c2410_uartcfg smdk6440_uartcfgs[] __initdata = {
[0] = {
- .hwport = 0,
- .flags = 0,
- .ucon = SMDK6440_UCON_DEFAULT,
- .ulcon = SMDK6440_ULCON_DEFAULT,
- .ufcon = SMDK6440_UFCON_DEFAULT,
+ .hwport = 0,
+ .flags = 0,
+ .ucon = SMDK6440_UCON_DEFAULT,
+ .ulcon = SMDK6440_ULCON_DEFAULT,
+ .ufcon = SMDK6440_UFCON_DEFAULT,
},
[1] = {
- .hwport = 1,
- .flags = 0,
- .ucon = SMDK6440_UCON_DEFAULT,
- .ulcon = SMDK6440_ULCON_DEFAULT,
- .ufcon = SMDK6440_UFCON_DEFAULT,
+ .hwport = 1,
+ .flags = 0,
+ .ucon = SMDK6440_UCON_DEFAULT,
+ .ulcon = SMDK6440_ULCON_DEFAULT,
+ .ufcon = SMDK6440_UFCON_DEFAULT,
},
[2] = {
- .hwport = 2,
- .flags = 0,
- .ucon = SMDK6440_UCON_DEFAULT,
- .ulcon = SMDK6440_ULCON_DEFAULT,
- .ufcon = SMDK6440_UFCON_DEFAULT,
+ .hwport = 2,
+ .flags = 0,
+ .ucon = SMDK6440_UCON_DEFAULT,
+ .ulcon = SMDK6440_ULCON_DEFAULT,
+ .ufcon = SMDK6440_UFCON_DEFAULT,
},
[3] = {
- .hwport = 3,
- .flags = 0,
- .ucon = SMDK6440_UCON_DEFAULT,
- .ulcon = SMDK6440_ULCON_DEFAULT,
- .ufcon = SMDK6440_UFCON_DEFAULT,
+ .hwport = 3,
+ .flags = 0,
+ .ucon = SMDK6440_UCON_DEFAULT,
+ .ulcon = SMDK6440_ULCON_DEFAULT,
+ .ufcon = SMDK6440_UFCON_DEFAULT,
},
};
static struct platform_device *smdk6440_devices[] __initdata = {
- &s5p6440_device_iis,
&s3c_device_adc,
&s3c_device_rtc,
&s3c_device_i2c0,
&s3c_device_i2c1,
&s3c_device_ts,
&s3c_device_wdt,
+ &s5p6440_device_iis,
+};
+
+static struct s3c2410_platform_i2c s5p6440_i2c0_data __initdata = {
+ .flags = 0,
+ .slave_addr = 0x10,
+ .frequency = 100*1000,
+ .sda_delay = 100,
+ .cfg_gpio = s5p6440_i2c0_cfg_gpio,
+};
+
+static struct s3c2410_platform_i2c s5p6440_i2c1_data __initdata = {
+ .flags = 0,
+ .bus_num = 1,
+ .slave_addr = 0x10,
+ .frequency = 100*1000,
+ .sda_delay = 100,
+ .cfg_gpio = s5p6440_i2c1_cfg_gpio,
};
static struct i2c_board_info smdk6440_i2c_devs0[] __initdata = {
@@ -113,7 +131,7 @@ static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
static void __init smdk6440_map_io(void)
{
- s5p_init_io(NULL, 0, S5P_SYS_ID);
+ s5p_init_io(NULL, 0, S5P64X0_SYS_ID);
s3c24xx_init_clocks(12000000);
s3c24xx_init_uarts(smdk6440_uartcfgs, ARRAY_SIZE(smdk6440_uartcfgs));
}
@@ -122,9 +140,8 @@ static void __init smdk6440_machine_init(void)
{
s3c24xx_ts_set_platdata(&s3c_ts_platform);
- /* I2C */
- s3c_i2c0_set_platdata(NULL);
- s3c_i2c1_set_platdata(NULL);
+ s3c_i2c0_set_platdata(&s5p6440_i2c0_data);
+ s3c_i2c1_set_platdata(&s5p6440_i2c1_data);
i2c_register_board_info(0, smdk6440_i2c_devs0,
ARRAY_SIZE(smdk6440_i2c_devs0));
i2c_register_board_info(1, smdk6440_i2c_devs1,
@@ -135,9 +152,7 @@ static void __init smdk6440_machine_init(void)
MACHINE_START(SMDK6440, "SMDK6440")
/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
- .phys_io = S3C_PA_UART & 0xfff00000,
- .io_pg_offst = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
- .boot_params = S5P_PA_SDRAM + 0x100,
+ .boot_params = S5P64X0_PA_SDRAM + 0x100,
.init_irq = s5p6440_init_irq,
.map_io = smdk6440_map_io,
diff --git a/arch/arm/mach-s5p64x0/mach-smdk6450.c b/arch/arm/mach-s5p64x0/mach-smdk6450.c
new file mode 100644
index 000000000000..d609f5af2b98
--- /dev/null
+++ b/arch/arm/mach-s5p64x0/mach-smdk6450.c
@@ -0,0 +1,180 @@
+/* linux/arch/arm/mach-s5p64x0/mach-smdk6450.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/gpio.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+#include <mach/hardware.h>
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#include <mach/i2c.h>
+
+#include <plat/regs-serial.h>
+#include <plat/gpio-cfg.h>
+#include <plat/s5p6450.h>
+#include <plat/clock.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+#include <plat/iic.h>
+#include <plat/pll.h>
+#include <plat/adc.h>
+#include <plat/ts.h>
+
+#define SMDK6450_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
+ S3C2410_UCON_RXILEVEL | \
+ S3C2410_UCON_TXIRQMODE | \
+ S3C2410_UCON_RXIRQMODE | \
+ S3C2410_UCON_RXFIFO_TOI | \
+ S3C2443_UCON_RXERR_IRQEN)
+
+#define SMDK6450_ULCON_DEFAULT S3C2410_LCON_CS8
+
+#define SMDK6450_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | \
+ S3C2440_UFCON_TXTRIG16 | \
+ S3C2410_UFCON_RXTRIG8)
+
+static struct s3c2410_uartcfg smdk6450_uartcfgs[] __initdata = {
+ [0] = {
+ .hwport = 0,
+ .flags = 0,
+ .ucon = SMDK6450_UCON_DEFAULT,
+ .ulcon = SMDK6450_ULCON_DEFAULT,
+ .ufcon = SMDK6450_UFCON_DEFAULT,
+ },
+ [1] = {
+ .hwport = 1,
+ .flags = 0,
+ .ucon = SMDK6450_UCON_DEFAULT,
+ .ulcon = SMDK6450_ULCON_DEFAULT,
+ .ufcon = SMDK6450_UFCON_DEFAULT,
+ },
+ [2] = {
+ .hwport = 2,
+ .flags = 0,
+ .ucon = SMDK6450_UCON_DEFAULT,
+ .ulcon = SMDK6450_ULCON_DEFAULT,
+ .ufcon = SMDK6450_UFCON_DEFAULT,
+ },
+ [3] = {
+ .hwport = 3,
+ .flags = 0,
+ .ucon = SMDK6450_UCON_DEFAULT,
+ .ulcon = SMDK6450_ULCON_DEFAULT,
+ .ufcon = SMDK6450_UFCON_DEFAULT,
+ },
+#if CONFIG_SERIAL_SAMSUNG_UARTS > 4
+ [4] = {
+ .hwport = 4,
+ .flags = 0,
+ .ucon = SMDK6450_UCON_DEFAULT,
+ .ulcon = SMDK6450_ULCON_DEFAULT,
+ .ufcon = SMDK6450_UFCON_DEFAULT,
+ },
+#endif
+#if CONFIG_SERIAL_SAMSUNG_UARTS > 5
+ [5] = {
+ .hwport = 5,
+ .flags = 0,
+ .ucon = SMDK6450_UCON_DEFAULT,
+ .ulcon = SMDK6450_ULCON_DEFAULT,
+ .ufcon = SMDK6450_UFCON_DEFAULT,
+ },
+#endif
+};
+
+static struct platform_device *smdk6450_devices[] __initdata = {
+ &s3c_device_adc,
+ &s3c_device_rtc,
+ &s3c_device_i2c0,
+ &s3c_device_i2c1,
+ &s3c_device_ts,
+ &s3c_device_wdt,
+ &s5p6450_device_iis0,
+ /* s5p6450_device_spi0 will be added */
+};
+
+static struct s3c2410_platform_i2c s5p6450_i2c0_data __initdata = {
+ .flags = 0,
+ .slave_addr = 0x10,
+ .frequency = 100*1000,
+ .sda_delay = 100,
+ .cfg_gpio = s5p6450_i2c0_cfg_gpio,
+};
+
+static struct s3c2410_platform_i2c s5p6450_i2c1_data __initdata = {
+ .flags = 0,
+ .bus_num = 1,
+ .slave_addr = 0x10,
+ .frequency = 100*1000,
+ .sda_delay = 100,
+ .cfg_gpio = s5p6450_i2c1_cfg_gpio,
+};
+
+static struct i2c_board_info smdk6450_i2c_devs0[] __initdata = {
+ { I2C_BOARD_INFO("24c08", 0x50), }, /* Samsung KS24C080C EEPROM */
+};
+
+static struct i2c_board_info smdk6450_i2c_devs1[] __initdata = {
+ { I2C_BOARD_INFO("24c128", 0x57), },/* Samsung S524AD0XD1 EEPROM */
+};
+
+static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
+ .delay = 10000,
+ .presc = 49,
+ .oversampling_shift = 2,
+};
+
+static void __init smdk6450_map_io(void)
+{
+ s5p_init_io(NULL, 0, S5P64X0_SYS_ID);
+ s3c24xx_init_clocks(19200000);
+ s3c24xx_init_uarts(smdk6450_uartcfgs, ARRAY_SIZE(smdk6450_uartcfgs));
+}
+
+static void __init smdk6450_machine_init(void)
+{
+ s3c24xx_ts_set_platdata(&s3c_ts_platform);
+
+ s3c_i2c0_set_platdata(&s5p6450_i2c0_data);
+ s3c_i2c1_set_platdata(&s5p6450_i2c1_data);
+ i2c_register_board_info(0, smdk6450_i2c_devs0,
+ ARRAY_SIZE(smdk6450_i2c_devs0));
+ i2c_register_board_info(1, smdk6450_i2c_devs1,
+ ARRAY_SIZE(smdk6450_i2c_devs1));
+
+ platform_add_devices(smdk6450_devices, ARRAY_SIZE(smdk6450_devices));
+}
+
+MACHINE_START(SMDK6450, "SMDK6450")
+ /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
+ .boot_params = S5P64X0_PA_SDRAM + 0x100,
+
+ .init_irq = s5p6450_init_irq,
+ .map_io = smdk6450_map_io,
+ .init_machine = smdk6450_machine_init,
+ .timer = &s3c24xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-s5p6440/setup-i2c0.c b/arch/arm/mach-s5p64x0/setup-i2c0.c
index 2c99d14f7ac7..dc4cc65a5019 100644
--- a/arch/arm/mach-s5p6440/setup-i2c0.c
+++ b/arch/arm/mach-s5p64x0/setup-i2c0.c
@@ -1,11 +1,11 @@
-/* linux/arch/arm/mach-s5p6440/setup-i2c0.c
+/* linux/arch/arm/mach-s5p64x0/setup-i2c0.c
*
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
*
* I2C0 GPIO configuration.
*
- * Based on plat-s3c64xx/setup-i2c0.c
+ * Based on plat-s3c64x0/setup-i2c0.c
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -14,17 +14,29 @@
#include <linux/kernel.h>
#include <linux/types.h>
+#include <linux/gpio.h>
struct platform_device; /* don't need the contents */
-#include <linux/gpio.h>
#include <plat/gpio-cfg.h>
#include <plat/iic.h>
-void s3c_i2c0_cfg_gpio(struct platform_device *dev)
+#include <mach/i2c.h>
+
+void s5p6440_i2c0_cfg_gpio(struct platform_device *dev)
{
s3c_gpio_cfgpin(S5P6440_GPB(5), S3C_GPIO_SFN(2));
s3c_gpio_setpull(S5P6440_GPB(5), S3C_GPIO_PULL_UP);
s3c_gpio_cfgpin(S5P6440_GPB(6), S3C_GPIO_SFN(2));
s3c_gpio_setpull(S5P6440_GPB(6), S3C_GPIO_PULL_UP);
}
+
+void s5p6450_i2c0_cfg_gpio(struct platform_device *dev)
+{
+ s3c_gpio_cfgpin(S5P6450_GPB(5), S3C_GPIO_SFN(2));
+ s3c_gpio_setpull(S5P6450_GPB(5), S3C_GPIO_PULL_UP);
+ s3c_gpio_cfgpin(S5P6450_GPB(6), S3C_GPIO_SFN(2));
+ s3c_gpio_setpull(S5P6450_GPB(6), S3C_GPIO_PULL_UP);
+}
+
+void s3c_i2c0_cfg_gpio(struct platform_device *dev) { }
diff --git a/arch/arm/mach-s5p6440/setup-i2c1.c b/arch/arm/mach-s5p64x0/setup-i2c1.c
index 9a1537f786e0..2edd7912f8e4 100644
--- a/arch/arm/mach-s5p6440/setup-i2c1.c
+++ b/arch/arm/mach-s5p64x0/setup-i2c1.c
@@ -1,7 +1,7 @@
-/* linux/arch/arm/mach-s5p6440/setup-i2c1.c
+/* linux/arch/arm/mach-s5p64xx/setup-i2c1.c
*
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
*
* I2C1 GPIO configuration.
*
@@ -21,10 +21,22 @@ struct platform_device; /* don't need the contents */
#include <plat/gpio-cfg.h>
#include <plat/iic.h>
-void s3c_i2c1_cfg_gpio(struct platform_device *dev)
+#include <mach/i2c.h>
+
+void s5p6440_i2c1_cfg_gpio(struct platform_device *dev)
{
s3c_gpio_cfgpin(S5P6440_GPR(9), S3C_GPIO_SFN(6));
s3c_gpio_setpull(S5P6440_GPR(9), S3C_GPIO_PULL_UP);
s3c_gpio_cfgpin(S5P6440_GPR(10), S3C_GPIO_SFN(6));
s3c_gpio_setpull(S5P6440_GPR(10), S3C_GPIO_PULL_UP);
}
+
+void s5p6450_i2c1_cfg_gpio(struct platform_device *dev)
+{
+ s3c_gpio_cfgpin(S5P6450_GPR(9), S3C_GPIO_SFN(6));
+ s3c_gpio_setpull(S5P6450_GPR(9), S3C_GPIO_PULL_UP);
+ s3c_gpio_cfgpin(S5P6450_GPR(10), S3C_GPIO_SFN(6));
+ s3c_gpio_setpull(S5P6450_GPR(10), S3C_GPIO_PULL_UP);
+}
+
+void s3c_i2c1_cfg_gpio(struct platform_device *dev) { }
diff --git a/arch/arm/mach-s5pc100/cpu.c b/arch/arm/mach-s5pc100/cpu.c
index 251c92ac5b22..fd2708e7d8a9 100644
--- a/arch/arm/mach-s5pc100/cpu.c
+++ b/arch/arm/mach-s5pc100/cpu.c
@@ -1,5 +1,8 @@
/* linux/arch/arm/mach-s5pc100/cpu.c
*
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
* Copyright 2009 Samsung Electronics Co.
* Byungho Min <bhmin@samsung.com>
*
@@ -21,6 +24,7 @@
#include <linux/sysdev.h>
#include <linux/serial_core.h>
#include <linux/platform_device.h>
+#include <linux/sched.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
@@ -56,11 +60,31 @@ static struct map_desc s5pc100_iodesc[] __initdata = {
.length = SZ_16K,
.type = MT_DEVICE,
}, {
+ .virtual = (unsigned long)S5P_VA_GPIO,
+ .pfn = __phys_to_pfn(S5PC100_PA_GPIO),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = (unsigned long)VA_VIC0,
+ .pfn = __phys_to_pfn(S5PC100_PA_VIC0),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = (unsigned long)VA_VIC1,
+ .pfn = __phys_to_pfn(S5PC100_PA_VIC1),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ }, {
.virtual = (unsigned long)VA_VIC2,
- .pfn = __phys_to_pfn(S5P_PA_VIC2),
+ .pfn = __phys_to_pfn(S5PC100_PA_VIC2),
.length = SZ_16K,
.type = MT_DEVICE,
}, {
+ .virtual = (unsigned long)S3C_VA_UART,
+ .pfn = __phys_to_pfn(S3C_PA_UART),
+ .length = SZ_512K,
+ .type = MT_DEVICE,
+ }, {
.virtual = (unsigned long)S5PC100_VA_OTHERS,
.pfn = __phys_to_pfn(S5PC100_PA_OTHERS),
.length = SZ_4K,
diff --git a/arch/arm/mach-s5pc100/include/mach/debug-macro.S b/arch/arm/mach-s5pc100/include/mach/debug-macro.S
index 70e02e91ee3c..b2ba95ddf8e0 100644
--- a/arch/arm/mach-s5pc100/include/mach/debug-macro.S
+++ b/arch/arm/mach-s5pc100/include/mach/debug-macro.S
@@ -22,13 +22,12 @@
* aligned and add in the offset when we load the value here.
*/
- .macro addruart, rx, rtmp
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1
- ldreq \rx, = S3C_PA_UART
- ldrne \rx, = S3C_VA_UART
+ .macro addruart, rp, rv
+ ldr \rp, = S3C_PA_UART
+ ldr \rv, = S3C_VA_UART
#if CONFIG_DEBUG_S3C_UART != 0
- add \rx, \rx, #(0x400 * CONFIG_DEBUG_S3C_UART)
+ add \rp, \rp, #(0x400 * CONFIG_DEBUG_S3C_UART)
+ add \rv, \rv, #(0x400 * CONFIG_DEBUG_S3C_UART)
#endif
.endm
diff --git a/arch/arm/mach-s5pc100/include/mach/map.h b/arch/arm/mach-s5pc100/include/mach/map.h
index 01b9134feff0..8751ef4a6804 100644
--- a/arch/arm/mach-s5pc100/include/mach/map.h
+++ b/arch/arm/mach-s5pc100/include/mach/map.h
@@ -44,19 +44,16 @@
#define S5PC100_PA_OTHERS (0xE0200000)
#define S5PC100_VA_OTHERS (S3C_VA_SYS + 0x10000)
-#define S5P_PA_GPIO (0xE0300000)
+#define S5PC100_PA_GPIO (0xE0300000)
#define S5PC1XX_VA_GPIO S3C_ADDR(0x00500000)
/* Interrupt */
-#define S5PC100_PA_VIC (0xE4000000)
+#define S5PC100_PA_VIC0 (0xE4000000)
+#define S5PC100_PA_VIC1 (0xE4100000)
+#define S5PC100_PA_VIC2 (0xE4200000)
#define S5PC100_VA_VIC S3C_VA_IRQ
-#define S5PC100_PA_VIC_OFFSET 0x100000
#define S5PC100_VA_VIC_OFFSET 0x10000
-#define S5PC1XX_PA_VIC(x) (S5PC100_PA_VIC + ((x) * S5PC100_PA_VIC_OFFSET))
#define S5PC1XX_VA_VIC(x) (S5PC100_VA_VIC + ((x) * S5PC100_VA_VIC_OFFSET))
-#define S5P_PA_VIC0 S5PC1XX_PA_VIC(0)
-#define S5P_PA_VIC1 S5PC1XX_PA_VIC(1)
-#define S5P_PA_VIC2 S5PC1XX_PA_VIC(2)
#define S5PC100_PA_ONENAND (0xE7100000)
diff --git a/arch/arm/mach-s5pc100/mach-smdkc100.c b/arch/arm/mach-s5pc100/mach-smdkc100.c
index 020c3f98f81f..880fb075092c 100644
--- a/arch/arm/mach-s5pc100/mach-smdkc100.c
+++ b/arch/arm/mach-s5pc100/mach-smdkc100.c
@@ -235,8 +235,6 @@ static void __init smdkc100_machine_init(void)
MACHINE_START(SMDKC100, "SMDKC100")
/* Maintainer: Byungho Min <bhmin@samsung.com> */
- .phys_io = S3C_PA_UART & 0xfff00000,
- .io_pg_offst = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
.boot_params = S5P_PA_SDRAM + 0x100,
.init_irq = s5pc100_init_irq,
.map_io = smdkc100_map_io,
diff --git a/arch/arm/mach-s5pv210/Kconfig b/arch/arm/mach-s5pv210/Kconfig
index d3a38955c741..5315fec3db86 100644
--- a/arch/arm/mach-s5pv210/Kconfig
+++ b/arch/arm/mach-s5pv210/Kconfig
@@ -53,11 +53,6 @@ config S5PV210_SETUP_SDHCI_GPIO
help
Common setup code for SDHCI gpio.
-config S5PC110_DEV_ONENAND
- bool
- help
- Compile in platform device definition for OneNAND1 controller
-
menu "S5PC110 Machines"
config MACH_AQUILA
@@ -71,7 +66,7 @@ config MACH_AQUILA
select S3C_DEV_HSMMC
select S3C_DEV_HSMMC1
select S3C_DEV_HSMMC2
- select S5PC110_DEV_ONENAND
+ select S5P_DEV_ONENAND
select S5PV210_SETUP_FB_24BPP
select S5PV210_SETUP_SDHCI
help
@@ -88,7 +83,7 @@ config MACH_GONI
select S3C_DEV_HSMMC
select S3C_DEV_HSMMC1
select S3C_DEV_HSMMC2
- select S5PC110_DEV_ONENAND
+ select S5P_DEV_ONENAND
select S5PV210_SETUP_FB_24BPP
select S5PV210_SETUP_SDHCI
help
diff --git a/arch/arm/mach-s5pv210/Makefile b/arch/arm/mach-s5pv210/Makefile
index 05048c5aa4c6..704548912408 100644
--- a/arch/arm/mach-s5pv210/Makefile
+++ b/arch/arm/mach-s5pv210/Makefile
@@ -26,7 +26,6 @@ obj-$(CONFIG_MACH_GONI) += mach-goni.o
obj-y += dev-audio.o
obj-$(CONFIG_S3C64XX_DEV_SPI) += dev-spi.o
-obj-$(CONFIG_S5PC110_DEV_ONENAND) += dev-onenand.o
obj-$(CONFIG_S5PV210_SETUP_FB_24BPP) += setup-fb-24bpp.o
obj-$(CONFIG_S5PV210_SETUP_I2C1) += setup-i2c1.o
diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c
index cfecd70657cb..d562670e1b0b 100644
--- a/arch/arm/mach-s5pv210/clock.c
+++ b/arch/arm/mach-s5pv210/clock.c
@@ -173,11 +173,6 @@ static int s5pv210_clk_ip3_ctrl(struct clk *clk, int enable)
return s5p_gatectrl(S5P_CLKGATE_IP3, clk, enable);
}
-static int s5pv210_clk_ip4_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(S5P_CLKGATE_IP4, clk, enable);
-}
-
static int s5pv210_clk_mask0_ctrl(struct clk *clk, int enable)
{
return s5p_gatectrl(S5P_CLK_SRC_MASK0, clk, enable);
diff --git a/arch/arm/mach-s5pv210/cpu.c b/arch/arm/mach-s5pv210/cpu.c
index 77f456c91ad3..2f16bfc0a116 100644
--- a/arch/arm/mach-s5pv210/cpu.c
+++ b/arch/arm/mach-s5pv210/cpu.c
@@ -1,7 +1,7 @@
/* linux/arch/arm/mach-s5pv210/cpu.c
*
* Copyright (c) 2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
+ * http://www.samsung.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -19,6 +19,7 @@
#include <linux/io.h>
#include <linux/sysdev.h>
#include <linux/platform_device.h>
+#include <linux/sched.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
@@ -50,6 +51,21 @@ static struct map_desc s5pv210_iodesc[] __initdata = {
.length = SZ_4K,
.type = MT_DEVICE,
}, {
+ .virtual = (unsigned long)S5P_VA_GPIO,
+ .pfn = __phys_to_pfn(S5PV210_PA_GPIO),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = (unsigned long)VA_VIC0,
+ .pfn = __phys_to_pfn(S5PV210_PA_VIC0),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = (unsigned long)VA_VIC1,
+ .pfn = __phys_to_pfn(S5PV210_PA_VIC1),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ }, {
.virtual = (unsigned long)VA_VIC2,
.pfn = __phys_to_pfn(S5PV210_PA_VIC2),
.length = SZ_16K,
@@ -60,6 +76,11 @@ static struct map_desc s5pv210_iodesc[] __initdata = {
.length = SZ_16K,
.type = MT_DEVICE,
}, {
+ .virtual = (unsigned long)S3C_VA_UART,
+ .pfn = __phys_to_pfn(S3C_PA_UART),
+ .length = SZ_512K,
+ .type = MT_DEVICE,
+ }, {
.virtual = (unsigned long)S5P_VA_SROMC,
.pfn = __phys_to_pfn(S5PV210_PA_SROMC),
.length = SZ_4K,
diff --git a/arch/arm/mach-s5pv210/include/mach/debug-macro.S b/arch/arm/mach-s5pv210/include/mach/debug-macro.S
index 7872f5c3dfc2..169fe654a59e 100644
--- a/arch/arm/mach-s5pv210/include/mach/debug-macro.S
+++ b/arch/arm/mach-s5pv210/include/mach/debug-macro.S
@@ -21,13 +21,12 @@
* aligned and add in the offset when we load the value here.
*/
- .macro addruart, rx, tmp
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1
- ldreq \rx, = S3C_PA_UART
- ldrne \rx, = S3C_VA_UART
+ .macro addruart, rp, rv
+ ldr \rp, = S3C_PA_UART
+ ldr \rv, = S3C_VA_UART
#if CONFIG_DEBUG_S3C_UART != 0
- add \rx, \rx, #(0x400 * CONFIG_DEBUG_S3C_UART)
+ add \rp, \rp, #(0x400 * CONFIG_DEBUG_S3C_UART)
+ add \rv, \rv, #(0x400 * CONFIG_DEBUG_S3C_UART)
#endif
.endm
diff --git a/arch/arm/mach-s5pv210/include/mach/map.h b/arch/arm/mach-s5pv210/include/mach/map.h
index dd4fb6bf14b5..bd9afd52466a 100644
--- a/arch/arm/mach-s5pv210/include/mach/map.h
+++ b/arch/arm/mach-s5pv210/include/mach/map.h
@@ -17,7 +17,10 @@
#include <plat/map-s5p.h>
#define S5PC110_PA_ONENAND (0xB0000000)
+#define S5P_PA_ONENAND S5PC110_PA_ONENAND
+
#define S5PC110_PA_ONENAND_DMA (0xB0600000)
+#define S5P_PA_ONENAND_DMA S5PC110_PA_ONENAND_DMA
#define S5PV210_PA_CHIPID (0xE0000000)
#define S5P_PA_CHIPID S5PV210_PA_CHIPID
@@ -26,7 +29,6 @@
#define S5P_PA_SYSCON S5PV210_PA_SYSCON
#define S5PV210_PA_GPIO (0xE0200000)
-#define S5P_PA_GPIO S5PV210_PA_GPIO
/* SPI */
#define S5PV210_PA_SPI0 0xE1300000
@@ -72,16 +74,9 @@
#define S5PV210_PA_HSMMC(x) (0xEB000000 + ((x) * 0x100000))
#define S5PV210_PA_VIC0 (0xF2000000)
-#define S5P_PA_VIC0 S5PV210_PA_VIC0
-
#define S5PV210_PA_VIC1 (0xF2100000)
-#define S5P_PA_VIC1 S5PV210_PA_VIC1
-
#define S5PV210_PA_VIC2 (0xF2200000)
-#define S5P_PA_VIC2 S5PV210_PA_VIC2
-
#define S5PV210_PA_VIC3 (0xF2300000)
-#define S5P_PA_VIC3 S5PV210_PA_VIC3
#define S5PV210_PA_SDRAM (0x20000000)
#define S5P_PA_SDRAM S5PV210_PA_SDRAM
diff --git a/arch/arm/mach-s5pv210/mach-aquila.c b/arch/arm/mach-s5pv210/mach-aquila.c
index 0dda8012d6b2..00883087363c 100644
--- a/arch/arm/mach-s5pv210/mach-aquila.c
+++ b/arch/arm/mach-s5pv210/mach-aquila.c
@@ -477,7 +477,7 @@ static struct platform_device *aquila_devices[] __initdata = {
&aquila_i2c_gpio_pmic,
&aquila_device_gpiokeys,
&s3c_device_fb,
- &s5pc110_device_onenand,
+ &s5p_device_onenand,
&s3c_device_hsmmc0,
&s3c_device_hsmmc1,
&s3c_device_hsmmc2,
@@ -516,8 +516,6 @@ MACHINE_START(AQUILA, "Aquila")
/* Maintainers:
Marek Szyprowski <m.szyprowski@samsung.com>
Kyungmin Park <kyungmin.park@samsung.com> */
- .phys_io = S3C_PA_UART & 0xfff00000,
- .io_pg_offst = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
.boot_params = S5P_PA_SDRAM + 0x100,
.init_irq = s5pv210_init_irq,
.map_io = aquila_map_io,
diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c
index 53754d7d364e..d9ecf57fc2a5 100644
--- a/arch/arm/mach-s5pv210/mach-goni.c
+++ b/arch/arm/mach-s5pv210/mach-goni.c
@@ -456,7 +456,7 @@ static void goni_setup_sdhci(void)
static struct platform_device *goni_devices[] __initdata = {
&s3c_device_fb,
- &s5pc110_device_onenand,
+ &s5p_device_onenand,
&goni_i2c_gpio_pmic,
&goni_device_gpiokeys,
&s5p_device_fimc0,
@@ -491,8 +491,6 @@ static void __init goni_machine_init(void)
MACHINE_START(GONI, "GONI")
/* Maintainers: Kyungmin Park <kyungmin.park@samsung.com> */
- .phys_io = S3C_PA_UART & 0xfff00000,
- .io_pg_offst = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
.boot_params = S5P_PA_SDRAM + 0x100,
.init_irq = s5pv210_init_irq,
.map_io = goni_map_io,
diff --git a/arch/arm/mach-s5pv210/mach-smdkc110.c b/arch/arm/mach-s5pv210/mach-smdkc110.c
index 8211bb87c54b..cea9bca79d88 100644
--- a/arch/arm/mach-s5pv210/mach-smdkc110.c
+++ b/arch/arm/mach-s5pv210/mach-smdkc110.c
@@ -127,8 +127,6 @@ static void __init smdkc110_machine_init(void)
MACHINE_START(SMDKC110, "SMDKC110")
/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
- .phys_io = S3C_PA_UART & 0xfff00000,
- .io_pg_offst = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
.boot_params = S5P_PA_SDRAM + 0x100,
.init_irq = s5pv210_init_irq,
.map_io = smdkc110_map_io,
diff --git a/arch/arm/mach-s5pv210/mach-smdkv210.c b/arch/arm/mach-s5pv210/mach-smdkv210.c
index fbbc0a3c3738..83189ae9da9a 100644
--- a/arch/arm/mach-s5pv210/mach-smdkv210.c
+++ b/arch/arm/mach-s5pv210/mach-smdkv210.c
@@ -165,8 +165,6 @@ static void __init smdkv210_machine_init(void)
MACHINE_START(SMDKV210, "SMDKV210")
/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
- .phys_io = S3C_PA_UART & 0xfff00000,
- .io_pg_offst = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
.boot_params = S5P_PA_SDRAM + 0x100,
.init_irq = s5pv210_init_irq,
.map_io = smdkv210_map_io,
diff --git a/arch/arm/mach-s5pv310/cpu.c b/arch/arm/mach-s5pv310/cpu.c
index e5b261a99ab2..4add39853ff9 100644
--- a/arch/arm/mach-s5pv310/cpu.c
+++ b/arch/arm/mach-s5pv310/cpu.c
@@ -31,9 +31,14 @@ extern void combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq);
/* Initial IO mappings */
static struct map_desc s5pv310_iodesc[] __initdata = {
{
- .virtual = (unsigned long)S5P_VA_COREPERI_BASE,
- .pfn = __phys_to_pfn(S5PV310_PA_COREPERI),
- .length = SZ_8K,
+ .virtual = (unsigned long)S5P_VA_SYSRAM,
+ .pfn = __phys_to_pfn(S5PV310_PA_SYSRAM),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = (unsigned long)S5P_VA_CMU,
+ .pfn = __phys_to_pfn(S5PV310_PA_CMU),
+ .length = SZ_128K,
.type = MT_DEVICE,
}, {
.virtual = (unsigned long)S5P_VA_COMBINER_BASE,
@@ -41,19 +46,24 @@ static struct map_desc s5pv310_iodesc[] __initdata = {
.length = SZ_4K,
.type = MT_DEVICE,
}, {
+ .virtual = (unsigned long)S5P_VA_COREPERI_BASE,
+ .pfn = __phys_to_pfn(S5PV310_PA_COREPERI),
+ .length = SZ_8K,
+ .type = MT_DEVICE,
+ }, {
.virtual = (unsigned long)S5P_VA_L2CC,
.pfn = __phys_to_pfn(S5PV310_PA_L2CC),
.length = SZ_4K,
.type = MT_DEVICE,
}, {
- .virtual = (unsigned long)S5P_VA_SYSRAM,
- .pfn = __phys_to_pfn(S5PV310_PA_SYSRAM),
+ .virtual = (unsigned long)S5P_VA_GPIO,
+ .pfn = __phys_to_pfn(S5PV310_PA_GPIO1),
.length = SZ_4K,
.type = MT_DEVICE,
}, {
- .virtual = (unsigned long)S5P_VA_CMU,
- .pfn = __phys_to_pfn(S5PV310_PA_CMU),
- .length = SZ_128K,
+ .virtual = (unsigned long)S3C_VA_UART,
+ .pfn = __phys_to_pfn(S3C_PA_UART),
+ .length = SZ_512K,
.type = MT_DEVICE,
},
};
diff --git a/arch/arm/mach-s5pv310/include/mach/debug-macro.S b/arch/arm/mach-s5pv310/include/mach/debug-macro.S
index 6fb3893486be..b0d920c474d3 100644
--- a/arch/arm/mach-s5pv310/include/mach/debug-macro.S
+++ b/arch/arm/mach-s5pv310/include/mach/debug-macro.S
@@ -20,13 +20,12 @@
* aligned and add in the offset when we load the value here.
*/
- .macro addruart, rx, tmp
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1
- ldreq \rx, = S3C_PA_UART
- ldrne \rx, = S3C_VA_UART
+ .macro addruart, rp, rv
+ ldreq \rp, = S3C_PA_UART
+ ldrne \rv, = S3C_VA_UART
#if CONFIG_DEBUG_S3C_UART != 0
- add \rx, \rx, #(0x10000 * CONFIG_DEBUG_S3C_UART)
+ add \rp, \rp, #(0x10000 * CONFIG_DEBUG_S3C_UART)
+ add \rv, \rv, #(0x10000 * CONFIG_DEBUG_S3C_UART)
#endif
.endm
diff --git a/arch/arm/mach-s5pv310/include/mach/irqs.h b/arch/arm/mach-s5pv310/include/mach/irqs.h
index 4cdedda6e652..471fc3bb199a 100644
--- a/arch/arm/mach-s5pv310/include/mach/irqs.h
+++ b/arch/arm/mach-s5pv310/include/mach/irqs.h
@@ -68,6 +68,8 @@
#define IRQ_IIC COMBINER_IRQ(27, 0)
+#define IRQ_ONENAND_AUDI COMBINER_IRQ(34, 0)
+
/* Set the default NR_IRQS */
#define NR_IRQS COMBINER_IRQ(MAX_COMBINER_NR, 0)
diff --git a/arch/arm/mach-s5pv310/include/mach/map.h b/arch/arm/mach-s5pv310/include/mach/map.h
index 213e1101a3b3..aff6d23624bb 100644
--- a/arch/arm/mach-s5pv310/include/mach/map.h
+++ b/arch/arm/mach-s5pv310/include/mach/map.h
@@ -25,6 +25,12 @@
#define S5PV310_PA_SYSRAM (0x02025000)
+#define S5PC210_PA_ONENAND (0x0C000000)
+#define S5P_PA_ONENAND S5PC210_PA_ONENAND
+
+#define S5PC210_PA_ONENAND_DMA (0x0C600000)
+#define S5P_PA_ONENAND_DMA S5PC210_PA_ONENAND_DMA
+
#define S5PV310_PA_CHIPID (0x10000000)
#define S5P_PA_CHIPID S5PV310_PA_CHIPID
@@ -46,7 +52,6 @@
#define S5PV310_PA_GPIO1 (0x11400000)
#define S5PV310_PA_GPIO2 (0x11000000)
#define S5PV310_PA_GPIO3 (0x03860000)
-#define S5P_PA_GPIO S5PV310_PA_GPIO1
#define S5PV310_PA_HSMMC(x) (0x12510000 + ((x) * 0x10000))
diff --git a/arch/arm/mach-s5pv310/include/mach/smp.h b/arch/arm/mach-s5pv310/include/mach/smp.h
index 990f3ba88a1f..b7ec252384f4 100644
--- a/arch/arm/mach-s5pv310/include/mach/smp.h
+++ b/arch/arm/mach-s5pv310/include/mach/smp.h
@@ -7,17 +7,10 @@
#define ASM_ARCH_SMP_H __FILE__
#include <asm/hardware/gic.h>
+#include <asm/smp_mpidr.h>
extern void __iomem *gic_cpu_base_addr;
-#define hard_smp_processor_id() \
- ({ \
- unsigned int cpunum; \
- __asm__("mrc p15, 0, %0, c0, c0, 5" \
- : "=r" (cpunum)); \
- cpunum &= 0x03; \
- })
-
/*
* We use IRQ1 as the IPI
*/
diff --git a/arch/arm/mach-s5pv310/mach-smdkv310.c b/arch/arm/mach-s5pv310/mach-smdkv310.c
index 0d6ab77709d2..46215a14b3bb 100644
--- a/arch/arm/mach-s5pv310/mach-smdkv310.c
+++ b/arch/arm/mach-s5pv310/mach-smdkv310.c
@@ -82,8 +82,6 @@ static void __init smdkv310_machine_init(void)
MACHINE_START(SMDKV310, "SMDKV310")
/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
/* Maintainer: Changhwan Youn <chaos.youn@samsung.com> */
- .phys_io = S3C_PA_UART & 0xfff00000,
- .io_pg_offst = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
.boot_params = S5P_PA_SDRAM + 0x100,
.init_irq = s5pv310_init_irq,
.map_io = smdkv310_map_io,
diff --git a/arch/arm/mach-s5pv310/mach-universal_c210.c b/arch/arm/mach-s5pv310/mach-universal_c210.c
index 2388cb947936..d7c2ec770f88 100644
--- a/arch/arm/mach-s5pv310/mach-universal_c210.c
+++ b/arch/arm/mach-s5pv310/mach-universal_c210.c
@@ -76,8 +76,6 @@ static void __init universal_machine_init(void)
MACHINE_START(UNIVERSAL_C210, "UNIVERSAL_C210")
/* Maintainer: Kyungmin Park <kyungmin.park@samsung.com> */
- .phys_io = S3C_PA_UART & 0xfff00000,
- .io_pg_offst = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
.boot_params = S5P_PA_SDRAM + 0x100,
.init_irq = s5pv310_init_irq,
.map_io = universal_map_io,
diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c
index 169e5b87dbff..5778274a8260 100644
--- a/arch/arm/mach-sa1100/assabet.c
+++ b/arch/arm/mach-sa1100/assabet.c
@@ -447,8 +447,6 @@ static void __init assabet_map_io(void)
MACHINE_START(ASSABET, "Intel-Assabet")
- .phys_io = 0x80000000,
- .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc,
.boot_params = 0xc0000100,
.fixup = fixup_assabet,
.map_io = assabet_map_io,
diff --git a/arch/arm/mach-sa1100/badge4.c b/arch/arm/mach-sa1100/badge4.c
index 259cb2c15fff..4f19ff868b00 100644
--- a/arch/arm/mach-sa1100/badge4.c
+++ b/arch/arm/mach-sa1100/badge4.c
@@ -302,8 +302,6 @@ static void __init badge4_map_io(void)
}
MACHINE_START(BADGE4, "Hewlett-Packard Laboratories BadgePAD 4")
- .phys_io = 0x80000000,
- .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc,
.boot_params = 0xc0000100,
.map_io = badge4_map_io,
.init_irq = sa1100_init_irq,
diff --git a/arch/arm/mach-sa1100/cerf.c b/arch/arm/mach-sa1100/cerf.c
index bc950ef418af..98d780608c7e 100644
--- a/arch/arm/mach-sa1100/cerf.c
+++ b/arch/arm/mach-sa1100/cerf.c
@@ -135,8 +135,6 @@ static void __init cerf_init(void)
MACHINE_START(CERF, "Intrinsyc CerfBoard/CerfCube")
/* Maintainer: support@intrinsyc.com */
- .phys_io = 0x80000000,
- .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc,
.map_io = cerf_map_io,
.init_irq = cerf_init_irq,
.timer = &sa1100_timer,
diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c
index 16e682d5dbb7..d43c5ef58eb6 100644
--- a/arch/arm/mach-sa1100/collie.c
+++ b/arch/arm/mach-sa1100/collie.c
@@ -379,8 +379,6 @@ static void __init collie_map_io(void)
}
MACHINE_START(COLLIE, "Sharp-Collie")
- .phys_io = 0x80000000,
- .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc,
.map_io = collie_map_io,
.init_irq = sa1100_init_irq,
.timer = &sa1100_timer,
diff --git a/arch/arm/mach-sa1100/h3100.c b/arch/arm/mach-sa1100/h3100.c
index 0c7cea0dc013..03d7376cf8a0 100644
--- a/arch/arm/mach-sa1100/h3100.c
+++ b/arch/arm/mach-sa1100/h3100.c
@@ -84,8 +84,6 @@ static void __init h3100_mach_init(void)
}
MACHINE_START(H3100, "Compaq iPAQ H3100")
- .phys_io = 0x80000000,
- .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc,
.boot_params = 0xc0000100,
.map_io = h3100_map_io,
.init_irq = sa1100_init_irq,
diff --git a/arch/arm/mach-sa1100/h3600.c b/arch/arm/mach-sa1100/h3600.c
index af3b71459f8d..965f64a836f8 100644
--- a/arch/arm/mach-sa1100/h3600.c
+++ b/arch/arm/mach-sa1100/h3600.c
@@ -125,8 +125,6 @@ static void __init h3600_mach_init(void)
}
MACHINE_START(H3600, "Compaq iPAQ H3600")
- .phys_io = 0x80000000,
- .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc,
.boot_params = 0xc0000100,
.map_io = h3600_map_io,
.init_irq = sa1100_init_irq,
diff --git a/arch/arm/mach-sa1100/hackkit.c b/arch/arm/mach-sa1100/hackkit.c
index 51568dfc8e97..db5e434a17db 100644
--- a/arch/arm/mach-sa1100/hackkit.c
+++ b/arch/arm/mach-sa1100/hackkit.c
@@ -195,8 +195,6 @@ static void __init hackkit_init(void)
*/
MACHINE_START(HACKKIT, "HackKit Cpu Board")
- .phys_io = 0x80000000,
- .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc,
.boot_params = 0xc0000100,
.map_io = hackkit_map_io,
.init_irq = sa1100_init_irq,
diff --git a/arch/arm/mach-sa1100/include/mach/debug-macro.S b/arch/arm/mach-sa1100/include/mach/debug-macro.S
index 336adccea542..0cd0fc9635b6 100644
--- a/arch/arm/mach-sa1100/include/mach/debug-macro.S
+++ b/arch/arm/mach-sa1100/include/mach/debug-macro.S
@@ -12,33 +12,37 @@
*/
#include <mach/hardware.h>
- .macro addruart, rx, tmp
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ MMU enabled?
- moveq \rx, #0x80000000 @ physical base address
- movne \rx, #0xf8000000 @ virtual address
+ .macro addruart, rp, rv
+ mrc p15, 0, \rp, c1, c0
+ tst \rp, #1 @ MMU enabled?
+ moveq \rp, #0x80000000 @ physical base address
+ movne \rp, #0xf8000000 @ virtual address
@ We probe for the active serial port here, coherently with
@ the comment in arch/arm/mach-sa1100/include/mach/uncompress.h.
@ We assume r1 can be clobbered.
@ see if Ser3 is active
- add \rx, \rx, #0x00050000
- ldr r1, [\rx, #UTCR3]
- tst r1, #UTCR3_TXE
+ add \rp, \rp, #0x00050000
+ ldr \rv, [\rp, #UTCR3]
+ tst \rv, #UTCR3_TXE
@ if Ser3 is inactive, then try Ser1
- addeq \rx, \rx, #(0x00010000 - 0x00050000)
- ldreq r1, [\rx, #UTCR3]
- tsteq r1, #UTCR3_TXE
+ addeq \rp, \rp, #(0x00010000 - 0x00050000)
+ ldreq \rv, [\rp, #UTCR3]
+ tsteq \rv, #UTCR3_TXE
@ if Ser1 is inactive, then try Ser2
- addeq \rx, \rx, #(0x00030000 - 0x00010000)
- ldreq r1, [\rx, #UTCR3]
- tsteq r1, #UTCR3_TXE
+ addeq \rp, \rp, #(0x00030000 - 0x00010000)
+ ldreq \rv, [\rp, #UTCR3]
+ tsteq \rv, #UTCR3_TXE
+
+ @ clear top bits, and generate both phys and virt addresses
+ lsl \rp, \rp, #8
+ lsr \rp, \rp, #8
+ orr \rv, \rp, #0xf8000000 @ virtual
+ orr \rp, \rp, #0x80000000 @ physical
- @ if all ports are inactive, then there is nothing we can do
- moveq pc, lr
.endm
.macro senduart,rd,rx
diff --git a/arch/arm/mach-sa1100/jornada720.c b/arch/arm/mach-sa1100/jornada720.c
index d3ec620618f1..491ac9f20fb4 100644
--- a/arch/arm/mach-sa1100/jornada720.c
+++ b/arch/arm/mach-sa1100/jornada720.c
@@ -364,8 +364,6 @@ static void __init jornada720_mach_init(void)
MACHINE_START(JORNADA720, "HP Jornada 720")
/* Maintainer: Kristoffer Ericson <Kristoffer.Ericson@gmail.com> */
- .phys_io = 0x80000000,
- .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc,
.boot_params = 0xc0000100,
.map_io = jornada720_map_io,
.init_irq = sa1100_init_irq,
diff --git a/arch/arm/mach-sa1100/lart.c b/arch/arm/mach-sa1100/lart.c
index 68069d6dc07a..7b9556b59057 100644
--- a/arch/arm/mach-sa1100/lart.c
+++ b/arch/arm/mach-sa1100/lart.c
@@ -61,8 +61,6 @@ static void __init lart_map_io(void)
}
MACHINE_START(LART, "LART")
- .phys_io = 0x80000000,
- .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc,
.boot_params = 0xc0000100,
.map_io = lart_map_io,
.init_irq = sa1100_init_irq,
diff --git a/arch/arm/mach-sa1100/pleb.c b/arch/arm/mach-sa1100/pleb.c
index 1ccd6018d3a3..42b80400c100 100644
--- a/arch/arm/mach-sa1100/pleb.c
+++ b/arch/arm/mach-sa1100/pleb.c
@@ -146,8 +146,6 @@ static void __init pleb_map_io(void)
}
MACHINE_START(PLEB, "PLEB")
- .phys_io = 0x80000000,
- .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc,
.map_io = pleb_map_io,
.init_irq = sa1100_init_irq,
.timer = &sa1100_timer,
diff --git a/arch/arm/mach-sa1100/shannon.c b/arch/arm/mach-sa1100/shannon.c
index 85e82bb73d7e..7917b2405579 100644
--- a/arch/arm/mach-sa1100/shannon.c
+++ b/arch/arm/mach-sa1100/shannon.c
@@ -82,8 +82,6 @@ static void __init shannon_map_io(void)
}
MACHINE_START(SHANNON, "Shannon (AKA: Tuxscreen)")
- .phys_io = 0x80000000,
- .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc,
.boot_params = 0xc0000100,
.map_io = shannon_map_io,
.init_irq = sa1100_init_irq,
diff --git a/arch/arm/mach-sa1100/simpad.c b/arch/arm/mach-sa1100/simpad.c
index 49cfd64663ac..27692d0ffbe8 100644
--- a/arch/arm/mach-sa1100/simpad.c
+++ b/arch/arm/mach-sa1100/simpad.c
@@ -228,8 +228,6 @@ arch_initcall(simpad_init);
MACHINE_START(SIMPAD, "Simpad")
/* Maintainer: Holger Freyther */
- .phys_io = 0x80000000,
- .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc,
.boot_params = 0xc0000100,
.map_io = simpad_map_io,
.init_irq = sa1100_init_irq,
diff --git a/arch/arm/mach-shark/core.c b/arch/arm/mach-shark/core.c
index 358d875ace14..5cf7f94c1f31 100644
--- a/arch/arm/mach-shark/core.c
+++ b/arch/arm/mach-shark/core.c
@@ -152,8 +152,6 @@ static struct sys_timer shark_timer = {
MACHINE_START(SHARK, "Shark")
/* Maintainer: Alexander Schulz */
- .phys_io = 0x40000000,
- .io_pg_offst = ((0xe0000000) >> 18) & 0xfffc,
.boot_params = 0x08003000,
.map_io = shark_map_io,
.init_irq = shark_init_irq,
diff --git a/arch/arm/mach-shark/include/mach/debug-macro.S b/arch/arm/mach-shark/include/mach/debug-macro.S
index 5ea24d4d1ba6..a473f55dc71f 100644
--- a/arch/arm/mach-shark/include/mach/debug-macro.S
+++ b/arch/arm/mach-shark/include/mach/debug-macro.S
@@ -11,9 +11,10 @@
*
*/
- .macro addruart, rx, tmp
- mov \rx, #0xe0000000
- orr \rx, \rx, #0x000003f8
+ .macro addruart, rp, rv
+ mov \rp, #0xe0000000
+ orr \rp, \rp, #0x000003f8
+ mov \rv, \rp
.endm
.macro senduart,rd,rx
diff --git a/arch/arm/mach-shark/include/mach/vmalloc.h b/arch/arm/mach-shark/include/mach/vmalloc.h
index f6c6837c5451..8e845b6a7cb5 100644
--- a/arch/arm/mach-shark/include/mach/vmalloc.h
+++ b/arch/arm/mach-shark/include/mach/vmalloc.h
@@ -1,4 +1,4 @@
/*
* arch/arm/mach-shark/include/mach/vmalloc.h
*/
-#define VMALLOC_END (PAGE_OFFSET + 0x10000000)
+#define VMALLOC_END 0xd0000000
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c
index 95935c83c306..14923989ea05 100644
--- a/arch/arm/mach-shmobile/board-ap4evb.c
+++ b/arch/arm/mach-shmobile/board-ap4evb.c
@@ -1105,8 +1105,6 @@ static struct sys_timer ap4evb_timer = {
};
MACHINE_START(AP4EVB, "ap4evb")
- .phys_io = 0xe6000000,
- .io_pg_offst = ((0xe6000000) >> 18) & 0xfffc,
.map_io = ap4evb_map_io,
.init_irq = sh7372_init_irq,
.init_machine = ap4evb_init,
diff --git a/arch/arm/mach-shmobile/board-g3evm.c b/arch/arm/mach-shmobile/board-g3evm.c
index a5525901e91f..3b83d6320bec 100644
--- a/arch/arm/mach-shmobile/board-g3evm.c
+++ b/arch/arm/mach-shmobile/board-g3evm.c
@@ -365,8 +365,6 @@ static struct sys_timer g3evm_timer = {
};
MACHINE_START(G3EVM, "g3evm")
- .phys_io = 0xe6000000,
- .io_pg_offst = ((0xe6000000) >> 18) & 0xfffc,
.map_io = g3evm_map_io,
.init_irq = sh7367_init_irq,
.init_machine = g3evm_init,
diff --git a/arch/arm/mach-shmobile/board-g4evm.c b/arch/arm/mach-shmobile/board-g4evm.c
index 2c3ff6f7f34c..5b3b582ef3f2 100644
--- a/arch/arm/mach-shmobile/board-g4evm.c
+++ b/arch/arm/mach-shmobile/board-g4evm.c
@@ -392,8 +392,6 @@ static struct sys_timer g4evm_timer = {
};
MACHINE_START(G4EVM, "g4evm")
- .phys_io = 0xe6000000,
- .io_pg_offst = ((0xe6000000) >> 18) & 0xfffc,
.map_io = g4evm_map_io,
.init_irq = sh7377_init_irq,
.init_machine = g4evm_init,
diff --git a/arch/arm/mach-stmp378x/stmp378x_devb.c b/arch/arm/mach-stmp378x/stmp378x_devb.c
index 90d8fe6f10fe..06158848afd9 100644
--- a/arch/arm/mach-stmp378x/stmp378x_devb.c
+++ b/arch/arm/mach-stmp378x/stmp378x_devb.c
@@ -324,8 +324,6 @@ static void __init stmp378x_devb_init(void)
}
MACHINE_START(STMP378X, "STMP378X")
- .phys_io = 0x80000000,
- .io_pg_offst = ((0xf0000000) >> 18) & 0xfffc,
.boot_params = 0x40000100,
.map_io = stmp378x_map_io,
.init_irq = stmp378x_init_irq,
diff --git a/arch/arm/mach-stmp37xx/stmp37xx_devb.c b/arch/arm/mach-stmp37xx/stmp37xx_devb.c
index 394f21ab59e6..311d8552d362 100644
--- a/arch/arm/mach-stmp37xx/stmp37xx_devb.c
+++ b/arch/arm/mach-stmp37xx/stmp37xx_devb.c
@@ -91,8 +91,6 @@ static void __init stmp37xx_devb_init(void)
}
MACHINE_START(STMP37XX, "STMP37XX")
- .phys_io = 0x80000000,
- .io_pg_offst = ((0xf0000000) >> 18) & 0xfffc,
.boot_params = 0x40000100,
.map_io = stmp37xx_map_io,
.init_irq = stmp37xx_init_irq,
diff --git a/arch/arm/mach-tcc8k/Kconfig b/arch/arm/mach-tcc8k/Kconfig
new file mode 100644
index 000000000000..ad86415d1577
--- /dev/null
+++ b/arch/arm/mach-tcc8k/Kconfig
@@ -0,0 +1,11 @@
+if ARCH_TCC8K
+
+comment "TCC8000 systems:"
+
+config MACH_TCC8000_SDK
+ bool "Telechips TCC8000-SDK development kit"
+ default y
+ help
+ Support for the Telechips TCC8000-SDK board.
+
+endif
diff --git a/arch/arm/mach-tcc8k/Makefile b/arch/arm/mach-tcc8k/Makefile
new file mode 100644
index 000000000000..9bacf31e49ba
--- /dev/null
+++ b/arch/arm/mach-tcc8k/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for TCC8K boards and common files.
+#
+
+# Common support
+obj-y += clock.o irq.o time.o io.o devices.o
+
+# Board specific support
+obj-$(CONFIG_MACH_TCC8000_SDK) += board-tcc8000-sdk.o
diff --git a/arch/arm/mach-tcc8k/Makefile.boot b/arch/arm/mach-tcc8k/Makefile.boot
new file mode 100644
index 000000000000..f135c9deae10
--- /dev/null
+++ b/arch/arm/mach-tcc8k/Makefile.boot
@@ -0,0 +1,3 @@
+ zreladdr-y := 0x20008000
+params_phys-y := 0x20000100
+initrd_phys-y := 0x20800000
diff --git a/arch/arm/mach-tcc8k/board-tcc8000-sdk.c b/arch/arm/mach-tcc8k/board-tcc8000-sdk.c
new file mode 100644
index 000000000000..7991415e666b
--- /dev/null
+++ b/arch/arm/mach-tcc8k/board-tcc8000-sdk.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2009 Hans J. Koch <hjk@linutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach-types.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/time.h>
+
+#include <mach/clock.h>
+
+#include "common.h"
+
+#define XI_FREQUENCY 12000000
+#define XTI_FREQUENCY 32768
+
+#ifdef CONFIG_MTD_NAND_TCC
+/* NAND */
+static struct tcc_nand_platform_data tcc8k_sdk_nand_data = {
+ .width = 1,
+ .hw_ecc = 0,
+};
+#endif
+
+static void __init tcc8k_init(void)
+{
+#ifdef CONFIG_MTD_NAND_TCC
+ tcc_nand_device.dev.platform_data = &tcc8k_sdk_nand_data;
+ platform_device_register(&tcc_nand_device);
+#endif
+}
+
+static void __init tcc8k_init_timer(void)
+{
+ tcc_clocks_init(XI_FREQUENCY, XTI_FREQUENCY);
+}
+
+static struct sys_timer tcc8k_timer = {
+ .init = tcc8k_init_timer,
+};
+
+static void __init tcc8k_map_io(void)
+{
+ tcc8k_map_common_io();
+}
+
+MACHINE_START(TCC8000_SDK, "Telechips TCC8000-SDK Demo Board")
+ .boot_params = PHYS_OFFSET + 0x00000100,
+ .map_io = tcc8k_map_io,
+ .init_irq = tcc8k_init_irq,
+ .init_machine = tcc8k_init,
+ .timer = &tcc8k_timer,
+MACHINE_END
diff --git a/arch/arm/mach-tcc8k/clock.c b/arch/arm/mach-tcc8k/clock.c
new file mode 100644
index 000000000000..ba32a15127ab
--- /dev/null
+++ b/arch/arm/mach-tcc8k/clock.c
@@ -0,0 +1,567 @@
+/*
+ * Lowlevel clock handling for Telechips TCC8xxx SoCs
+ *
+ * Copyright (C) 2010 by Hans J. Koch <hjk@linutronix.de>
+ *
+ * Licensed under the terms of the GPL v2
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+
+#include <asm/clkdev.h>
+
+#include <mach/clock.h>
+#include <mach/irqs.h>
+#include <mach/tcc8k-regs.h>
+
+#include "common.h"
+
+#define BCLKCTR0 (CKC_BASE + BCLKCTR0_OFFS)
+#define BCLKCTR1 (CKC_BASE + BCLKCTR1_OFFS)
+
+#define ACLKREF (CKC_BASE + ACLKREF_OFFS)
+#define ACLKUART0 (CKC_BASE + ACLKUART0_OFFS)
+#define ACLKUART1 (CKC_BASE + ACLKUART1_OFFS)
+#define ACLKUART2 (CKC_BASE + ACLKUART2_OFFS)
+#define ACLKUART3 (CKC_BASE + ACLKUART3_OFFS)
+#define ACLKUART4 (CKC_BASE + ACLKUART4_OFFS)
+#define ACLKI2C (CKC_BASE + ACLKI2C_OFFS)
+#define ACLKADC (CKC_BASE + ACLKADC_OFFS)
+#define ACLKUSBH (CKC_BASE + ACLKUSBH_OFFS)
+#define ACLKLCD (CKC_BASE + ACLKLCD_OFFS)
+#define ACLKSDH0 (CKC_BASE + ACLKSDH0_OFFS)
+#define ACLKSDH1 (CKC_BASE + ACLKSDH1_OFFS)
+#define ACLKSPI0 (CKC_BASE + ACLKSPI0_OFFS)
+#define ACLKSPI1 (CKC_BASE + ACLKSPI1_OFFS)
+#define ACLKSPDIF (CKC_BASE + ACLKSPDIF_OFFS)
+#define ACLKC3DEC (CKC_BASE + ACLKC3DEC_OFFS)
+#define ACLKCAN0 (CKC_BASE + ACLKCAN0_OFFS)
+#define ACLKCAN1 (CKC_BASE + ACLKCAN1_OFFS)
+#define ACLKGSB0 (CKC_BASE + ACLKGSB0_OFFS)
+#define ACLKGSB1 (CKC_BASE + ACLKGSB1_OFFS)
+#define ACLKGSB2 (CKC_BASE + ACLKGSB2_OFFS)
+#define ACLKGSB3 (CKC_BASE + ACLKGSB3_OFFS)
+#define ACLKUSBH (CKC_BASE + ACLKUSBH_OFFS)
+#define ACLKTCT (CKC_BASE + ACLKTCT_OFFS)
+#define ACLKTCX (CKC_BASE + ACLKTCX_OFFS)
+#define ACLKTCZ (CKC_BASE + ACLKTCZ_OFFS)
+
+/* Crystal frequencies */
+static unsigned long xi_rate, xti_rate;
+
+static void __iomem *pll_cfg_addr(int pll)
+{
+ switch (pll) {
+ case 0: return (CKC_BASE + PLL0CFG_OFFS);
+ case 1: return (CKC_BASE + PLL1CFG_OFFS);
+ case 2: return (CKC_BASE + PLL2CFG_OFFS);
+ default:
+ BUG();
+ }
+}
+
+static int pll_enable(int pll, int enable)
+{
+ u32 reg;
+ void __iomem *addr = pll_cfg_addr(pll);
+
+ reg = __raw_readl(addr);
+ if (enable)
+ reg &= ~PLLxCFG_PD;
+ else
+ reg |= PLLxCFG_PD;
+
+ __raw_writel(reg, addr);
+ return 0;
+}
+
+static int xi_enable(int enable)
+{
+ u32 reg;
+
+ reg = __raw_readl(CKC_BASE + CLKCTRL_OFFS);
+ if (enable)
+ reg |= CLKCTRL_XE;
+ else
+ reg &= ~CLKCTRL_XE;
+
+ __raw_writel(reg, CKC_BASE + CLKCTRL_OFFS);
+ return 0;
+}
+
+static int root_clk_enable(enum root_clks src)
+{
+ switch (src) {
+ case CLK_SRC_PLL0: return pll_enable(0, 1);
+ case CLK_SRC_PLL1: return pll_enable(1, 1);
+ case CLK_SRC_PLL2: return pll_enable(2, 1);
+ case CLK_SRC_XI: return xi_enable(1);
+ default:
+ BUG();
+ }
+ return 0;
+}
+
+static int root_clk_disable(enum root_clks root_src)
+{
+ switch (root_src) {
+ case CLK_SRC_PLL0: return pll_enable(0, 0);
+ case CLK_SRC_PLL1: return pll_enable(1, 0);
+ case CLK_SRC_PLL2: return pll_enable(2, 0);
+ case CLK_SRC_XI: return xi_enable(0);
+ default:
+ BUG();
+ }
+ return 0;
+}
+
+static int enable_clk(struct clk *clk)
+{
+ u32 reg;
+
+ if (clk->root_id != CLK_SRC_NOROOT)
+ return root_clk_enable(clk->root_id);
+
+ if (clk->aclkreg) {
+ reg = __raw_readl(clk->aclkreg);
+ reg |= ACLK_EN;
+ __raw_writel(reg, clk->aclkreg);
+ }
+ if (clk->bclkctr) {
+ reg = __raw_readl(clk->bclkctr);
+ reg |= 1 << clk->bclk_shift;
+ __raw_writel(reg, clk->bclkctr);
+ }
+ return 0;
+}
+
+static void disable_clk(struct clk *clk)
+{
+ u32 reg;
+
+ if (clk->root_id != CLK_SRC_NOROOT) {
+ root_clk_disable(clk->root_id);
+ return;
+ }
+
+ if (clk->bclkctr) {
+ reg = __raw_readl(clk->bclkctr);
+ reg &= ~(1 << clk->bclk_shift);
+ __raw_writel(reg, clk->bclkctr);
+ }
+ if (clk->aclkreg) {
+ reg = __raw_readl(clk->aclkreg);
+ reg &= ~ACLK_EN;
+ __raw_writel(reg, clk->aclkreg);
+ }
+}
+
+static unsigned long get_rate_pll(int pll)
+{
+ u32 reg;
+ unsigned long s, m, p;
+ void __iomem *addr = pll_cfg_addr(pll);
+
+ reg = __raw_readl(addr);
+ s = (reg >> 16) & 0x07;
+ m = (reg >> 8) & 0xff;
+ p = reg & 0x3f;
+
+ return (m * xi_rate) / (p * (1 << s));
+}
+
+static unsigned long get_rate_pll_div(int pll)
+{
+ u32 reg;
+ unsigned long div = 0;
+ void __iomem *addr;
+
+ switch (pll) {
+ case 0:
+ addr = CKC_BASE + CLKDIVC0_OFFS;
+ reg = __raw_readl(addr);
+ if (reg & CLKDIVC0_P0E)
+ div = (reg >> 24) & 0x3f;
+ break;
+ case 1:
+ addr = CKC_BASE + CLKDIVC0_OFFS;
+ reg = __raw_readl(addr);
+ if (reg & CLKDIVC0_P1E)
+ div = (reg >> 16) & 0x3f;
+ break;
+ case 2:
+ addr = CKC_BASE + CLKDIVC1_OFFS;
+ reg = __raw_readl(addr);
+ if (reg & CLKDIVC1_P2E)
+ div = __raw_readl(addr) & 0x3f;
+ break;
+ }
+ return get_rate_pll(pll) / (div + 1);
+}
+
+static unsigned long get_rate_xi_div(void)
+{
+ unsigned long div = 0;
+ u32 reg = __raw_readl(CKC_BASE + CLKDIVC0_OFFS);
+
+ if (reg & CLKDIVC0_XE)
+ div = (reg >> 8) & 0x3f;
+
+ return xi_rate / (div + 1);
+}
+
+static unsigned long get_rate_xti_div(void)
+{
+ unsigned long div = 0;
+ u32 reg = __raw_readl(CKC_BASE + CLKDIVC0_OFFS);
+
+ if (reg & CLKDIVC0_XTE)
+ div = reg & 0x3f;
+
+ return xti_rate / (div + 1);
+}
+
+static unsigned long root_clk_get_rate(enum root_clks src)
+{
+ switch (src) {
+ case CLK_SRC_PLL0: return get_rate_pll(0);
+ case CLK_SRC_PLL1: return get_rate_pll(1);
+ case CLK_SRC_PLL2: return get_rate_pll(2);
+ case CLK_SRC_PLL0DIV: return get_rate_pll_div(0);
+ case CLK_SRC_PLL1DIV: return get_rate_pll_div(1);
+ case CLK_SRC_PLL2DIV: return get_rate_pll_div(2);
+ case CLK_SRC_XI: return xi_rate;
+ case CLK_SRC_XTI: return xti_rate;
+ case CLK_SRC_XIDIV: return get_rate_xi_div();
+ case CLK_SRC_XTIDIV: return get_rate_xti_div();
+ default: return 0;
+ }
+}
+
+static unsigned long aclk_get_rate(struct clk *clk)
+{
+ u32 reg;
+ unsigned long div;
+ unsigned int src;
+
+ reg = __raw_readl(clk->aclkreg);
+ div = reg & 0x0fff;
+ src = (reg >> ACLK_SEL_SHIFT) & CLK_SRC_MASK;
+ return root_clk_get_rate(src) / (div + 1);
+}
+
+static unsigned long aclk_best_div(struct clk *clk, unsigned long rate)
+{
+ unsigned long div, src, freq, r1, r2;
+
+ src = __raw_readl(clk->aclkreg) >> ACLK_SEL_SHIFT;
+ src &= CLK_SRC_MASK;
+ freq = root_clk_get_rate(src);
+ div = freq / rate + 1;
+ r1 = freq / div;
+ r2 = freq / (div + 1);
+ if (r2 >= rate)
+ return div + 1;
+ if ((rate - r2) < (r1 - rate))
+ return div + 1;
+
+ return div;
+}
+
+static unsigned long aclk_round_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned int src;
+
+ src = __raw_readl(clk->aclkreg) >> ACLK_SEL_SHIFT;
+ src &= CLK_SRC_MASK;
+
+ return root_clk_get_rate(src) / aclk_best_div(clk, rate);
+}
+
+static int aclk_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg;
+
+ reg = __raw_readl(clk->aclkreg) & ~ACLK_DIV_MASK;
+ reg |= aclk_best_div(clk, rate);
+ return 0;
+}
+
+static unsigned long get_rate_sys(struct clk *clk)
+{
+ unsigned int src;
+
+ src = __raw_readl(CKC_BASE + CLKCTRL_OFFS) & CLK_SRC_MASK;
+ return root_clk_get_rate(src);
+}
+
+static unsigned long get_rate_bus(struct clk *clk)
+{
+ unsigned int div;
+
+ div = (__raw_readl(CKC_BASE + CLKCTRL_OFFS) >> 4) & 0xff;
+ return get_rate_sys(clk) / (div + 1);
+}
+
+static unsigned long get_rate_cpu(struct clk *clk)
+{
+ unsigned int reg, div, fsys, fbus;
+
+ fbus = get_rate_bus(clk);
+ reg = __raw_readl(CKC_BASE + CLKCTRL_OFFS);
+ if (reg & (1 << 29))
+ return fbus;
+ fsys = get_rate_sys(clk);
+ div = (reg >> 16) & 0x0f;
+ return fbus + ((fsys - fbus) * (div + 1)) / 16;
+}
+
+static unsigned long get_rate_root(struct clk *clk)
+{
+ return root_clk_get_rate(clk->root_id);
+}
+
+static int aclk_set_parent(struct clk *clock, struct clk *parent)
+{
+ u32 reg;
+
+ if (clock->parent == parent)
+ return 0;
+
+ clock->parent = parent;
+
+ if (!parent)
+ return 0;
+
+ if (parent->root_id == CLK_SRC_NOROOT)
+ return 0;
+ reg = __raw_readl(clock->aclkreg);
+ reg &= ~ACLK_SEL_MASK;
+ reg |= (parent->root_id << ACLK_SEL_SHIFT) & ACLK_SEL_MASK;
+ __raw_writel(reg, clock->aclkreg);
+
+ return 0;
+}
+
+#define DEFINE_ROOT_CLOCK(name, ri, p) \
+ static struct clk name = { \
+ .root_id = ri, \
+ .get_rate = get_rate_root, \
+ .enable = enable_clk, \
+ .disable = disable_clk, \
+ .parent = p, \
+ };
+
+#define DEFINE_SPECIAL_CLOCK(name, gr, p) \
+ static struct clk name = { \
+ .root_id = CLK_SRC_NOROOT, \
+ .get_rate = gr, \
+ .parent = p, \
+ };
+
+#define DEFINE_ACLOCK(name, bc, bs, ar) \
+ static struct clk name = { \
+ .root_id = CLK_SRC_NOROOT, \
+ .bclkctr = bc, \
+ .bclk_shift = bs, \
+ .aclkreg = ar, \
+ .get_rate = aclk_get_rate, \
+ .set_rate = aclk_set_rate, \
+ .round_rate = aclk_round_rate, \
+ .enable = enable_clk, \
+ .disable = disable_clk, \
+ .set_parent = aclk_set_parent, \
+ };
+
+#define DEFINE_BCLOCK(name, bc, bs, gr, p) \
+ static struct clk name = { \
+ .root_id = CLK_SRC_NOROOT, \
+ .bclkctr = bc, \
+ .bclk_shift = bs, \
+ .get_rate = gr, \
+ .enable = enable_clk, \
+ .disable = disable_clk, \
+ .parent = p, \
+ };
+
+DEFINE_ROOT_CLOCK(xi, CLK_SRC_XI, NULL)
+DEFINE_ROOT_CLOCK(xti, CLK_SRC_XTI, NULL)
+DEFINE_ROOT_CLOCK(xidiv, CLK_SRC_XIDIV, &xi)
+DEFINE_ROOT_CLOCK(xtidiv, CLK_SRC_XTIDIV, &xti)
+DEFINE_ROOT_CLOCK(pll0, CLK_SRC_PLL0, &xi)
+DEFINE_ROOT_CLOCK(pll1, CLK_SRC_PLL1, &xi)
+DEFINE_ROOT_CLOCK(pll2, CLK_SRC_PLL2, &xi)
+DEFINE_ROOT_CLOCK(pll0div, CLK_SRC_PLL0DIV, &pll0)
+DEFINE_ROOT_CLOCK(pll1div, CLK_SRC_PLL1DIV, &pll1)
+DEFINE_ROOT_CLOCK(pll2div, CLK_SRC_PLL2DIV, &pll2)
+
+/* The following 3 clocks are special and are initialized explicitly later */
+DEFINE_SPECIAL_CLOCK(sys, get_rate_sys, NULL)
+DEFINE_SPECIAL_CLOCK(bus, get_rate_bus, &sys)
+DEFINE_SPECIAL_CLOCK(cpu, get_rate_cpu, &sys)
+
+DEFINE_ACLOCK(tct, NULL, 0, ACLKTCT)
+DEFINE_ACLOCK(tcx, NULL, 0, ACLKTCX)
+DEFINE_ACLOCK(tcz, NULL, 0, ACLKTCZ)
+DEFINE_ACLOCK(ref, NULL, 0, ACLKREF)
+DEFINE_ACLOCK(uart0, BCLKCTR0, 5, ACLKUART0)
+DEFINE_ACLOCK(uart1, BCLKCTR0, 23, ACLKUART1)
+DEFINE_ACLOCK(uart2, BCLKCTR0, 6, ACLKUART2)
+DEFINE_ACLOCK(uart3, BCLKCTR0, 8, ACLKUART3)
+DEFINE_ACLOCK(uart4, BCLKCTR1, 6, ACLKUART4)
+DEFINE_ACLOCK(i2c, BCLKCTR0, 7, ACLKI2C)
+DEFINE_ACLOCK(adc, BCLKCTR0, 10, ACLKADC)
+DEFINE_ACLOCK(usbh0, BCLKCTR0, 11, ACLKUSBH)
+DEFINE_ACLOCK(lcd, BCLKCTR0, 13, ACLKLCD)
+DEFINE_ACLOCK(sd0, BCLKCTR0, 17, ACLKSDH0)
+DEFINE_ACLOCK(sd1, BCLKCTR1, 5, ACLKSDH1)
+DEFINE_ACLOCK(spi0, BCLKCTR0, 24, ACLKSPI0)
+DEFINE_ACLOCK(spi1, BCLKCTR0, 30, ACLKSPI1)
+DEFINE_ACLOCK(spdif, BCLKCTR1, 2, ACLKSPDIF)
+DEFINE_ACLOCK(c3dec, BCLKCTR1, 9, ACLKC3DEC)
+DEFINE_ACLOCK(can0, BCLKCTR1, 10, ACLKCAN0)
+DEFINE_ACLOCK(can1, BCLKCTR1, 11, ACLKCAN1)
+DEFINE_ACLOCK(gsb0, BCLKCTR1, 13, ACLKGSB0)
+DEFINE_ACLOCK(gsb1, BCLKCTR1, 14, ACLKGSB1)
+DEFINE_ACLOCK(gsb2, BCLKCTR1, 15, ACLKGSB2)
+DEFINE_ACLOCK(gsb3, BCLKCTR1, 16, ACLKGSB3)
+DEFINE_ACLOCK(usbh1, BCLKCTR1, 20, ACLKUSBH)
+
+DEFINE_BCLOCK(dai0, BCLKCTR0, 0, NULL, NULL)
+DEFINE_BCLOCK(pic, BCLKCTR0, 1, NULL, NULL)
+DEFINE_BCLOCK(tc, BCLKCTR0, 2, NULL, NULL)
+DEFINE_BCLOCK(gpio, BCLKCTR0, 3, NULL, NULL)
+DEFINE_BCLOCK(usbd, BCLKCTR0, 4, NULL, NULL)
+DEFINE_BCLOCK(ecc, BCLKCTR0, 9, NULL, NULL)
+DEFINE_BCLOCK(gdma0, BCLKCTR0, 12, NULL, NULL)
+DEFINE_BCLOCK(rtc, BCLKCTR0, 15, NULL, NULL)
+DEFINE_BCLOCK(nfc, BCLKCTR0, 16, NULL, NULL)
+DEFINE_BCLOCK(g2d, BCLKCTR0, 18, NULL, NULL)
+DEFINE_BCLOCK(gdma1, BCLKCTR0, 22, NULL, NULL)
+DEFINE_BCLOCK(mscl, BCLKCTR0, 25, NULL, NULL)
+DEFINE_BCLOCK(bdma, BCLKCTR1, 0, NULL, NULL)
+DEFINE_BCLOCK(adma0, BCLKCTR1, 1, NULL, NULL)
+DEFINE_BCLOCK(scfg, BCLKCTR1, 3, NULL, NULL)
+DEFINE_BCLOCK(cid, BCLKCTR1, 4, NULL, NULL)
+DEFINE_BCLOCK(dai1, BCLKCTR1, 7, NULL, NULL)
+DEFINE_BCLOCK(adma1, BCLKCTR1, 8, NULL, NULL)
+DEFINE_BCLOCK(gps, BCLKCTR1, 12, NULL, NULL)
+DEFINE_BCLOCK(gdma2, BCLKCTR1, 17, NULL, NULL)
+DEFINE_BCLOCK(gdma3, BCLKCTR1, 18, NULL, NULL)
+DEFINE_BCLOCK(ddrc, BCLKCTR1, 19, NULL, NULL)
+
+#define _REGISTER_CLOCK(d, n, c) \
+ { \
+ .dev_id = d, \
+ .con_id = n, \
+ .clk = &c, \
+ },
+
+static struct clk_lookup lookups[] = {
+ _REGISTER_CLOCK(NULL, "bus", bus)
+ _REGISTER_CLOCK(NULL, "cpu", cpu)
+ _REGISTER_CLOCK(NULL, "tct", tct)
+ _REGISTER_CLOCK(NULL, "tcx", tcx)
+ _REGISTER_CLOCK(NULL, "tcz", tcz)
+ _REGISTER_CLOCK(NULL, "ref", ref)
+ _REGISTER_CLOCK(NULL, "dai0", dai0)
+ _REGISTER_CLOCK(NULL, "pic", pic)
+ _REGISTER_CLOCK(NULL, "tc", tc)
+ _REGISTER_CLOCK(NULL, "gpio", gpio)
+ _REGISTER_CLOCK(NULL, "usbd", usbd)
+ _REGISTER_CLOCK("tcc-uart.0", NULL, uart0)
+ _REGISTER_CLOCK("tcc-uart.2", NULL, uart2)
+ _REGISTER_CLOCK("tcc-i2c", NULL, i2c)
+ _REGISTER_CLOCK("tcc-uart.3", NULL, uart3)
+ _REGISTER_CLOCK(NULL, "ecc", ecc)
+ _REGISTER_CLOCK(NULL, "adc", adc)
+ _REGISTER_CLOCK("tcc-usbh.0", "usb", usbh0)
+ _REGISTER_CLOCK(NULL, "gdma0", gdma0)
+ _REGISTER_CLOCK(NULL, "lcd", lcd)
+ _REGISTER_CLOCK(NULL, "rtc", rtc)
+ _REGISTER_CLOCK(NULL, "nfc", nfc)
+ _REGISTER_CLOCK("tcc-mmc.0", NULL, sd0)
+ _REGISTER_CLOCK(NULL, "g2d", g2d)
+ _REGISTER_CLOCK(NULL, "gdma1", gdma1)
+ _REGISTER_CLOCK("tcc-uart.1", NULL, uart1)
+ _REGISTER_CLOCK("tcc-spi.0", NULL, spi0)
+ _REGISTER_CLOCK(NULL, "mscl", mscl)
+ _REGISTER_CLOCK("tcc-spi.1", NULL, spi1)
+ _REGISTER_CLOCK(NULL, "bdma", bdma)
+ _REGISTER_CLOCK(NULL, "adma0", adma0)
+ _REGISTER_CLOCK(NULL, "spdif", spdif)
+ _REGISTER_CLOCK(NULL, "scfg", scfg)
+ _REGISTER_CLOCK(NULL, "cid", cid)
+ _REGISTER_CLOCK("tcc-mmc.1", NULL, sd1)
+ _REGISTER_CLOCK("tcc-uart.4", NULL, uart4)
+ _REGISTER_CLOCK(NULL, "dai1", dai1)
+ _REGISTER_CLOCK(NULL, "adma1", adma1)
+ _REGISTER_CLOCK(NULL, "c3dec", c3dec)
+ _REGISTER_CLOCK("tcc-can.0", NULL, can0)
+ _REGISTER_CLOCK("tcc-can.1", NULL, can1)
+ _REGISTER_CLOCK(NULL, "gps", gps)
+ _REGISTER_CLOCK("tcc-gsb.0", NULL, gsb0)
+ _REGISTER_CLOCK("tcc-gsb.1", NULL, gsb1)
+ _REGISTER_CLOCK("tcc-gsb.2", NULL, gsb2)
+ _REGISTER_CLOCK("tcc-gsb.3", NULL, gsb3)
+ _REGISTER_CLOCK(NULL, "gdma2", gdma2)
+ _REGISTER_CLOCK(NULL, "gdma3", gdma3)
+ _REGISTER_CLOCK(NULL, "ddrc", ddrc)
+ _REGISTER_CLOCK("tcc-usbh.1", "usb", usbh1)
+};
+
+static struct clk *root_clk_by_index(enum root_clks src)
+{
+ switch (src) {
+ case CLK_SRC_PLL0: return &pll0;
+ case CLK_SRC_PLL1: return &pll1;
+ case CLK_SRC_PLL2: return &pll2;
+ case CLK_SRC_PLL0DIV: return &pll0div;
+ case CLK_SRC_PLL1DIV: return &pll1div;
+ case CLK_SRC_PLL2DIV: return &pll2div;
+ case CLK_SRC_XI: return &xi;
+ case CLK_SRC_XTI: return &xti;
+ case CLK_SRC_XIDIV: return &xidiv;
+ case CLK_SRC_XTIDIV: return &xtidiv;
+ default: return NULL;
+ }
+}
+
+static void find_aclk_parent(struct clk *clk)
+{
+ unsigned int src;
+ struct clk *clock;
+
+ if (!clk->aclkreg)
+ return;
+
+ src = __raw_readl(clk->aclkreg) >> ACLK_SEL_SHIFT;
+ src &= CLK_SRC_MASK;
+
+ clock = root_clk_by_index(src);
+ if (!clock)
+ return;
+
+ clk->parent = clock;
+ clk->set_parent = aclk_set_parent;
+}
+
+void __init tcc_clocks_init(unsigned long xi_freq, unsigned long xti_freq)
+{
+ int i;
+
+ xi_rate = xi_freq;
+ xti_rate = xti_freq;
+
+ /* fixup parents and add the clock */
+ for (i = 0; i < ARRAY_SIZE(lookups); i++) {
+ find_aclk_parent(lookups[i].clk);
+ clkdev_add(&lookups[i]);
+ }
+ tcc8k_timer_init(&tcz, (void __iomem *)TIMER_BASE, INT_TC32);
+}
diff --git a/arch/arm/mach-tcc8k/common.h b/arch/arm/mach-tcc8k/common.h
new file mode 100644
index 000000000000..705690add395
--- /dev/null
+++ b/arch/arm/mach-tcc8k/common.h
@@ -0,0 +1,15 @@
+#ifndef MACH_TCC8K_COMMON_H
+#define MACH_TCC8K_COMMON_H
+
+#include <linux/platform_device.h>
+
+extern struct platform_device tcc_nand_device;
+
+struct clk;
+
+extern void tcc_clocks_init(unsigned long xi_freq, unsigned long xti_freq);
+extern void tcc8k_timer_init(struct clk *clock, void __iomem *base, int irq);
+extern void tcc8k_init_irq(void);
+extern void tcc8k_map_common_io(void);
+
+#endif
diff --git a/arch/arm/mach-tcc8k/devices.c b/arch/arm/mach-tcc8k/devices.c
new file mode 100644
index 000000000000..6722ad7c2836
--- /dev/null
+++ b/arch/arm/mach-tcc8k/devices.c
@@ -0,0 +1,239 @@
+/*
+ * linux/arch/arm/mach-tcc8k/devices.c
+ *
+ * Copyright (C) Telechips, Inc.
+ * Copyright (C) 2009 Hans J. Koch <hjk@linutronix.de>
+ *
+ * Licensed under the terms of GPL v2.
+ *
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include <asm/mach/map.h>
+
+#include <mach/tcc8k-regs.h>
+#include <mach/irqs.h>
+
+#include "common.h"
+
+static u64 tcc8k_dmamask = DMA_BIT_MASK(32);
+
+#ifdef CONFIG_MTD_NAND_TCC
+/* NAND controller */
+static struct resource tcc_nand_resources[] = {
+ {
+ .start = (resource_size_t)NFC_BASE,
+ .end = (resource_size_t)NFC_BASE + 0x7f,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = INT_NFC,
+ .end = INT_NFC,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device tcc_nand_device = {
+ .name = "tcc_nand",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(tcc_nand_resources),
+ .resource = tcc_nand_resources,
+};
+#endif
+
+#ifdef CONFIG_MMC_TCC8K
+/* MMC controller */
+static struct resource tcc8k_mmc0_resource[] = {
+ {
+ .start = INT_SD0,
+ .end = INT_SD0,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource tcc8k_mmc1_resource[] = {
+ {
+ .start = INT_SD1,
+ .end = INT_SD1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device tcc8k_mmc0_device = {
+ .name = "tcc-mmc",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(tcc8k_mmc0_resource),
+ .resource = tcc8k_mmc0_resource,
+ .dev = {
+ .dma_mask = &tcc8k_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ }
+};
+
+struct platform_device tcc8k_mmc1_device = {
+ .name = "tcc-mmc",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(tcc8k_mmc1_resource),
+ .resource = tcc8k_mmc1_resource,
+ .dev = {
+ .dma_mask = &tcc8k_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ }
+};
+
+static inline void tcc8k_init_mmc(void)
+{
+ u32 reg = __raw_readl(GPIOPS_BASE + GPIOPS_FS1_OFFS);
+
+ reg |= GPIOPS_FS1_SDH0_BITS | GPIOPS_FS1_SDH1_BITS;
+ __raw_writel(reg, GPIOPS_BASE + GPIOPS_FS1_OFFS);
+
+ platform_device_register(&tcc8k_mmc0_device);
+ platform_device_register(&tcc8k_mmc1_device);
+}
+#else
+static inline void tcc8k_init_mmc(void) { }
+#endif
+
+#ifdef CONFIG_USB_OHCI_HCD
+static int tcc8k_ohci_init(struct device *dev)
+{
+ u32 reg;
+
+ /* Use GPIO PK19 as VBUS control output */
+ reg = __raw_readl(GPIOPK_BASE + GPIOPK_FS0_OFFS);
+ reg &= ~(1 << 19);
+ __raw_writel(reg, GPIOPK_BASE + GPIOPK_FS0_OFFS);
+ reg = __raw_readl(GPIOPK_BASE + GPIOPK_FS1_OFFS);
+ reg &= ~(1 << 19);
+ __raw_writel(reg, GPIOPK_BASE + GPIOPK_FS1_OFFS);
+
+ reg = __raw_readl(GPIOPK_BASE + GPIOPK_DOE_OFFS);
+ reg |= (1 << 19);
+ __raw_writel(reg, GPIOPK_BASE + GPIOPK_DOE_OFFS);
+ /* Turn on VBUS */
+ reg = __raw_readl(GPIOPK_BASE + GPIOPK_DAT_OFFS);
+ reg |= (1 << 19);
+ __raw_writel(reg, GPIOPK_BASE + GPIOPK_DAT_OFFS);
+
+ return 0;
+}
+
+static struct resource tcc8k_ohci0_resources[] = {
+ [0] = {
+ .start = (resource_size_t)USBH0_BASE,
+ .end = (resource_size_t)USBH0_BASE + 0x5c,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = INT_USBH0,
+ .end = INT_USBH0,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct resource tcc8k_ohci1_resources[] = {
+ [0] = {
+ .start = (resource_size_t)USBH1_BASE,
+ .end = (resource_size_t)USBH1_BASE + 0x5c,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = INT_USBH1,
+ .end = INT_USBH1,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct tccohci_platform_data tcc8k_ohci0_platform_data = {
+ .controller = 0,
+ .port_mode = PMM_PERPORT_MODE,
+ .init = tcc8k_ohci_init,
+};
+
+static struct tccohci_platform_data tcc8k_ohci1_platform_data = {
+ .controller = 1,
+ .port_mode = PMM_PERPORT_MODE,
+ .init = tcc8k_ohci_init,
+};
+
+static struct platform_device ohci0_device = {
+ .name = "tcc-ohci",
+ .id = 0,
+ .dev = {
+ .dma_mask = &tcc8k_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &tcc8k_ohci0_platform_data,
+ },
+ .num_resources = ARRAY_SIZE(tcc8k_ohci0_resources),
+ .resource = tcc8k_ohci0_resources,
+};
+
+static struct platform_device ohci1_device = {
+ .name = "tcc-ohci",
+ .id = 1,
+ .dev = {
+ .dma_mask = &tcc8k_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &tcc8k_ohci1_platform_data,
+ },
+ .num_resources = ARRAY_SIZE(tcc8k_ohci1_resources),
+ .resource = tcc8k_ohci1_resources,
+};
+
+static void __init tcc8k_init_usbhost(void)
+{
+ platform_device_register(&ohci0_device);
+ platform_device_register(&ohci1_device);
+}
+#else
+static void __init tcc8k_init_usbhost(void) { }
+#endif
+
+/* USB device controller*/
+#ifdef CONFIG_USB_GADGET_TCC8K
+static struct resource udc_resources[] = {
+ [0] = {
+ .start = INT_USBD,
+ .end = INT_USBD,
+ .flags = IORESOURCE_IRQ,
+ },
+ [1] = {
+ .start = INT_UDMA,
+ .end = INT_UDMA,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tcc8k_udc_device = {
+ .name = "tcc-udc",
+ .id = 0,
+ .resource = udc_resources,
+ .num_resources = ARRAY_SIZE(udc_resources),
+ .dev = {
+ .dma_mask = &tcc8k_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+
+static void __init tcc8k_init_usb_gadget(void)
+{
+ platform_device_register(&tcc8k_udc_device);
+}
+#else
+static void __init tcc8k_init_usb_gadget(void) { }
+#endif /* CONFIG_USB_GADGET_TCC83X */
+
+static int __init tcc8k_init_devices(void)
+{
+ tcc8k_init_mmc();
+ tcc8k_init_usbhost();
+ tcc8k_init_usb_gadget();
+ return 0;
+}
+
+arch_initcall(tcc8k_init_devices);
diff --git a/arch/arm/mach-tcc8k/io.c b/arch/arm/mach-tcc8k/io.c
new file mode 100644
index 000000000000..9b39d7fa658f
--- /dev/null
+++ b/arch/arm/mach-tcc8k/io.c
@@ -0,0 +1,62 @@
+/*
+ * linux/arch/arm/mach-tcc8k/io.c
+ *
+ * (C) 2009 Hans J. Koch <hjk@linutronix.de>
+ *
+ * derived from TCC83xx io.c
+ * Copyright (C) Telechips, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+
+#include <asm/mach/map.h>
+
+#include <mach/tcc8k-regs.h>
+
+/*
+ * The machine specific code may provide the extra mapping besides the
+ * default mapping provided here.
+ */
+static struct map_desc tcc8k_io_desc[] __initdata = {
+ {
+ .virtual = (unsigned long)CS1_BASE_VIRT,
+ .pfn = __phys_to_pfn(CS1_BASE),
+ .length = CS1_SIZE,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = (unsigned long)AHB_PERI_BASE_VIRT,
+ .pfn = __phys_to_pfn(AHB_PERI_BASE),
+ .length = AHB_PERI_SIZE,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = (unsigned long)APB0_PERI_BASE_VIRT,
+ .pfn = __phys_to_pfn(APB0_PERI_BASE),
+ .length = APB0_PERI_SIZE,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = (unsigned long)APB1_PERI_BASE_VIRT,
+ .pfn = __phys_to_pfn(APB1_PERI_BASE),
+ .length = APB1_PERI_SIZE,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = (unsigned long)EXT_MEM_CTRL_BASE_VIRT,
+ .pfn = __phys_to_pfn(EXT_MEM_CTRL_BASE),
+ .length = EXT_MEM_CTRL_SIZE,
+ .type = MT_DEVICE,
+ },
+};
+
+/*
+ * Maps common IO regions for tcc8k.
+ *
+ */
+void __init tcc8k_map_common_io(void)
+{
+ iotable_init(tcc8k_io_desc, ARRAY_SIZE(tcc8k_io_desc));
+}
diff --git a/arch/arm/mach-tcc8k/irq.c b/arch/arm/mach-tcc8k/irq.c
new file mode 100644
index 000000000000..34575c4963f0
--- /dev/null
+++ b/arch/arm/mach-tcc8k/irq.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) Telechips, Inc.
+ * Copyright (C) 2009-2010 Hans J. Koch <hjk@linutronix.de>
+ *
+ * Licensed under the terms of the GNU GPL version 2.
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+
+#include <asm/irq.h>
+#include <asm/mach/irq.h>
+
+#include <mach/tcc8k-regs.h>
+#include <mach/irqs.h>
+
+#include "common.h"
+
+/* Disable IRQ */
+static void tcc8000_mask_ack_irq0(unsigned int irq)
+{
+ PIC0_IEN &= ~(1 << irq);
+ PIC0_CREQ |= (1 << irq);
+}
+
+static void tcc8000_mask_ack_irq1(unsigned int irq)
+{
+ PIC1_IEN &= ~(1 << (irq - 32));
+ PIC1_CREQ |= (1 << (irq - 32));
+}
+
+static void tcc8000_mask_irq0(unsigned int irq)
+{
+ PIC0_IEN &= ~(1 << irq);
+}
+
+static void tcc8000_mask_irq1(unsigned int irq)
+{
+ PIC1_IEN &= ~(1 << (irq - 32));
+}
+
+static void tcc8000_ack_irq0(unsigned int irq)
+{
+ PIC0_CREQ |= (1 << irq);
+}
+
+static void tcc8000_ack_irq1(unsigned int irq)
+{
+ PIC1_CREQ |= (1 << (irq - 32));
+}
+
+/* Enable IRQ */
+static void tcc8000_unmask_irq0(unsigned int irq)
+{
+ PIC0_IEN |= (1 << irq);
+ PIC0_INTOEN |= (1 << irq);
+}
+
+static void tcc8000_unmask_irq1(unsigned int irq)
+{
+ PIC1_IEN |= (1 << (irq - 32));
+ PIC1_INTOEN |= (1 << (irq - 32));
+}
+
+static struct irq_chip tcc8000_irq_chip0 = {
+ .name = "tcc_irq0",
+ .mask = tcc8000_mask_irq0,
+ .ack = tcc8000_ack_irq0,
+ .mask_ack = tcc8000_mask_ack_irq0,
+ .unmask = tcc8000_unmask_irq0,
+};
+
+static struct irq_chip tcc8000_irq_chip1 = {
+ .name = "tcc_irq1",
+ .mask = tcc8000_mask_irq1,
+ .ack = tcc8000_ack_irq1,
+ .mask_ack = tcc8000_mask_ack_irq1,
+ .unmask = tcc8000_unmask_irq1,
+};
+
+void __init tcc8k_init_irq(void)
+{
+ int irqno;
+
+ /* Mask and clear all interrupts */
+ PIC0_IEN = 0x00000000;
+ PIC0_CREQ = 0xffffffff;
+ PIC1_IEN = 0x00000000;
+ PIC1_CREQ = 0xffffffff;
+
+ PIC0_MEN0 = 0x00000003;
+ PIC1_MEN1 = 0x00000003;
+ PIC1_MEN = 0x00000003;
+
+ /* let all IRQs be level triggered */
+ PIC0_TMODE = 0xffffffff;
+ PIC1_TMODE = 0xffffffff;
+ /* all IRQs are IRQs (not FIQs) */
+ PIC0_IRQSEL = 0xffffffff;
+ PIC1_IRQSEL = 0xffffffff;
+
+ for (irqno = 0; irqno < NR_IRQS; irqno++) {
+ if (irqno < 32)
+ set_irq_chip(irqno, &tcc8000_irq_chip0);
+ else
+ set_irq_chip(irqno, &tcc8000_irq_chip1);
+ set_irq_handler(irqno, handle_level_irq);
+ set_irq_flags(irqno, IRQF_VALID);
+ }
+}
diff --git a/arch/arm/mach-tcc8k/time.c b/arch/arm/mach-tcc8k/time.c
new file mode 100644
index 000000000000..78d06008841d
--- /dev/null
+++ b/arch/arm/mach-tcc8k/time.c
@@ -0,0 +1,149 @@
+/*
+ * TCC8000 system timer setup
+ *
+ * (C) 2009 Hans J. Koch <hjk@linutronix.de>
+ *
+ * Licensed under the terms of the GPL version 2.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+
+#include <asm/mach/time.h>
+
+#include <mach/tcc8k-regs.h>
+#include <mach/irqs.h>
+
+#include "common.h"
+
+static void __iomem *timer_base;
+
+static cycle_t tcc_get_cycles(struct clocksource *cs)
+{
+ return __raw_readl(timer_base + TC32MCNT_OFFS);
+}
+
+static struct clocksource clocksource_tcc = {
+ .name = "tcc_tc32",
+ .rating = 200,
+ .read = tcc_get_cycles,
+ .mask = CLOCKSOURCE_MASK(32),
+ .shift = 28,
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static int tcc_set_next_event(unsigned long evt,
+ struct clock_event_device *unused)
+{
+ unsigned long reg = __raw_readl(timer_base + TC32MCNT_OFFS);
+
+ __raw_writel(reg + evt, timer_base + TC32CMP0_OFFS);
+ return 0;
+}
+
+static void tcc_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt)
+{
+ unsigned long tc32irq;
+
+ switch (mode) {
+ case CLOCK_EVT_MODE_ONESHOT:
+ tc32irq = __raw_readl(timer_base + TC32IRQ_OFFS);
+ tc32irq |= TC32IRQ_IRQEN0;
+ __raw_writel(tc32irq, timer_base + TC32IRQ_OFFS);
+ break;
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ case CLOCK_EVT_MODE_UNUSED:
+ tc32irq = __raw_readl(timer_base + TC32IRQ_OFFS);
+ tc32irq &= ~TC32IRQ_IRQEN0;
+ __raw_writel(tc32irq, timer_base + TC32IRQ_OFFS);
+ break;
+ case CLOCK_EVT_MODE_PERIODIC:
+ case CLOCK_EVT_MODE_RESUME:
+ break;
+ }
+}
+
+static irqreturn_t tcc8k_timer_interrupt(int irq, void *dev_id)
+{
+ struct clock_event_device *evt = dev_id;
+
+ /* Acknowledge TC32 interrupt by reading TC32IRQ */
+ __raw_readl(timer_base + TC32IRQ_OFFS);
+
+ evt->event_handler(evt);
+
+ return IRQ_HANDLED;
+}
+
+static struct clock_event_device clockevent_tcc = {
+ .name = "tcc_timer1",
+ .features = CLOCK_EVT_FEAT_ONESHOT,
+ .shift = 32,
+ .set_mode = tcc_set_mode,
+ .set_next_event = tcc_set_next_event,
+ .rating = 200,
+};
+
+static struct irqaction tcc8k_timer_irq = {
+ .name = "TC32_timer",
+ .flags = IRQF_DISABLED | IRQF_TIMER,
+ .handler = tcc8k_timer_interrupt,
+ .dev_id = &clockevent_tcc,
+};
+
+static int __init tcc_clockevent_init(struct clk *clock)
+{
+ unsigned int c = clk_get_rate(clock);
+
+ clocksource_tcc.mult = clocksource_hz2mult(c,
+ clocksource_tcc.shift);
+ clocksource_register(&clocksource_tcc);
+
+ clockevent_tcc.mult = div_sc(c, NSEC_PER_SEC,
+ clockevent_tcc.shift);
+ clockevent_tcc.max_delta_ns =
+ clockevent_delta2ns(0xfffffffe, &clockevent_tcc);
+ clockevent_tcc.min_delta_ns =
+ clockevent_delta2ns(0xff, &clockevent_tcc);
+
+ clockevent_tcc.cpumask = cpumask_of(0);
+
+ clockevents_register_device(&clockevent_tcc);
+
+ return 0;
+}
+
+void __init tcc8k_timer_init(struct clk *clock, void __iomem *base, int irq)
+{
+ u32 reg;
+
+ timer_base = base;
+ tcc8k_timer_irq.irq = irq;
+
+ /* Enable clocks */
+ clk_enable(clock);
+
+ /* Initialize 32-bit timer */
+ reg = __raw_readl(timer_base + TC32EN_OFFS);
+ reg &= ~TC32EN_ENABLE; /* Disable timer */
+ __raw_writel(reg, timer_base + TC32EN_OFFS);
+ /* Free running timer, counting from 0 to 0xffffffff */
+ __raw_writel(0, timer_base + TC32EN_OFFS);
+ __raw_writel(0, timer_base + TC32LDV_OFFS);
+ reg = __raw_readl(timer_base + TC32IRQ_OFFS);
+ reg |= TC32IRQ_IRQEN0; /* irq at match with CMP0 */
+ __raw_writel(reg, timer_base + TC32IRQ_OFFS);
+
+ __raw_writel(TC32EN_ENABLE, timer_base + TC32EN_OFFS);
+
+ tcc_clockevent_init(clock);
+ setup_irq(irq, &tcc8k_timer_irq);
+}
diff --git a/arch/arm/mach-tegra/board-harmony.c b/arch/arm/mach-tegra/board-harmony.c
index 9e305de56be9..b9dbdb1289d0 100644
--- a/arch/arm/mach-tegra/board-harmony.c
+++ b/arch/arm/mach-tegra/board-harmony.c
@@ -115,8 +115,6 @@ static void __init tegra_harmony_init(void)
MACHINE_START(HARMONY, "harmony")
.boot_params = 0x00000100,
- .phys_io = IO_APB_PHYS,
- .io_pg_offst = ((IO_APB_VIRT) >> 18) & 0xfffc,
.fixup = tegra_harmony_fixup,
.init_irq = tegra_init_irq,
.init_machine = tegra_harmony_init,
diff --git a/arch/arm/mach-tegra/include/mach/debug-macro.S b/arch/arm/mach-tegra/include/mach/debug-macro.S
index 55a39564b43c..8ea3bffb4e00 100644
--- a/arch/arm/mach-tegra/include/mach/debug-macro.S
+++ b/arch/arm/mach-tegra/include/mach/debug-macro.S
@@ -20,24 +20,28 @@
#include <mach/io.h>
- .macro addruart,rx, tmp
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ MMU enabled?
- ldreq \rx, =IO_APB_PHYS @ physical
- ldrne \rx, =IO_APB_VIRT @ virtual
+ .macro addruart, rp, rv
+ ldreq \rp, =IO_APB_PHYS @ physical
+ ldrne \rv, =IO_APB_VIRT @ virtual
#if defined(CONFIG_TEGRA_DEBUG_UART_NONE)
#error "A debug UART must be selected in the kernel config to use DEBUG_LL"
#elif defined(CONFIG_TEGRA_DEBUG_UARTA)
- orr \rx, \rx, #0x6000
+ orr \rp, \rp, #0x6000
+ orr \rv, \rv, #0x6000
#elif defined(CONFIG_TEGRA_DEBUG_UARTB)
- ldr \tmp, =0x6040
- orr \rx, \rx, \tmp
+ orr \rp, \rp, #0x6000
+ orr \rp, \rp, #0x40
+ orr \rv, \rv, #0x6000
+ orr \rv, \rv, #0x40
#elif defined(CONFIG_TEGRA_DEBUG_UARTC)
- orr \rx, \rx, #0x6200
+ orr \rp, \rp, #0x6200
+ orr \rv, \rv, #0x6200
#elif defined(CONFIG_TEGRA_DEBUG_UARTD)
- orr \rx, \rx, #0x6300
+ orr \rp, \rp, #0x6300
+ orr \rv, \rv, #0x6300
#elif defined(CONFIG_TEGRA_DEBUG_UARTE)
- orr \rx, \rx, #0x6400
+ orr \rp, \rp, #0x6400
+ orr \rv, \rv, #0x6400
#endif
.endm
diff --git a/arch/arm/mach-tegra/include/mach/smp.h b/arch/arm/mach-tegra/include/mach/smp.h
index 8b42dab79a70..e4a34a35a544 100644
--- a/arch/arm/mach-tegra/include/mach/smp.h
+++ b/arch/arm/mach-tegra/include/mach/smp.h
@@ -1,16 +1,8 @@
#ifndef ASMARM_ARCH_SMP_H
#define ASMARM_ARCH_SMP_H
-
#include <asm/hardware/gic.h>
-
-#define hard_smp_processor_id() \
- ({ \
- unsigned int cpunum; \
- __asm__("mrc p15, 0, %0, c0, c0, 5" \
- : "=r" (cpunum)); \
- cpunum &= 0x0F; \
- })
+#include <asm/smp_mpidr.h>
/*
* We use IRQ1 as the IPI
diff --git a/arch/arm/mach-u300/dummyspichip.c b/arch/arm/mach-u300/dummyspichip.c
index 5f55012b7c9e..03f793612594 100644
--- a/arch/arm/mach-u300/dummyspichip.c
+++ b/arch/arm/mach-u300/dummyspichip.c
@@ -46,7 +46,6 @@ static ssize_t dummy_looptest(struct device *dev,
* struct, this is just used here to alter the behaviour of the chip
* in order to perform tests.
*/
- struct pl022_config_chip *chip_info = spi->controller_data;
int status;
u8 txbuf[14] = {0xDE, 0xAD, 0xBE, 0xEF, 0x2B, 0xAD,
0xCA, 0xFE, 0xBA, 0xBE, 0xB1, 0x05,
@@ -72,7 +71,7 @@ static ssize_t dummy_looptest(struct device *dev,
* Force chip to 8 bit mode
* WARNING: NEVER DO THIS IN REAL DRIVER CODE, THIS SHOULD BE STATIC!
*/
- chip_info->data_size = SSP_DATA_BITS_8;
+ spi->bits_per_word = 8;
/* You should NOT DO THIS EITHER */
spi->master->setup(spi);
@@ -159,7 +158,7 @@ static ssize_t dummy_looptest(struct device *dev,
* Force chip to 16 bit mode
* WARNING: NEVER DO THIS IN REAL DRIVER CODE, THIS SHOULD BE STATIC!
*/
- chip_info->data_size = SSP_DATA_BITS_16;
+ spi->bits_per_word = 16;
/* You should NOT DO THIS EITHER */
spi->master->setup(spi);
diff --git a/arch/arm/mach-u300/include/mach/debug-macro.S b/arch/arm/mach-u300/include/mach/debug-macro.S
index 92c12420256f..df715707bead 100644
--- a/arch/arm/mach-u300/include/mach/debug-macro.S
+++ b/arch/arm/mach-u300/include/mach/debug-macro.S
@@ -10,13 +10,12 @@
*/
#include <mach/hardware.h>
- .macro addruart, rx, tmp
+ .macro addruart, rp, rv
/* If we move the address using MMU, use this. */
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ MMU enabled?
- ldreq \rx, = U300_SLOW_PER_PHYS_BASE @ MMU off, physical address
- ldrne \rx, = U300_SLOW_PER_VIRT_BASE @ MMU on, virtual address
- orr \rx, \rx, #0x00003000
+ ldr \rp, = U300_SLOW_PER_PHYS_BASE @ MMU off, physical address
+ ldr \rv, = U300_SLOW_PER_VIRT_BASE @ MMU on, virtual address
+ orr \rp, \rp, #0x00003000
+ orr \rv, \rv, #0x00003000
.endm
#include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/mach-u300/spi.c b/arch/arm/mach-u300/spi.c
index f0e887bea30e..edb2c0d255c2 100644
--- a/arch/arm/mach-u300/spi.c
+++ b/arch/arm/mach-u300/spi.c
@@ -30,8 +30,6 @@ static void select_dummy_chip(u32 chipselect)
}
struct pl022_config_chip dummy_chip_info = {
- /* Nominally this is LOOPBACK_DISABLED, but this is our dummy chip! */
- .lbm = LOOPBACK_ENABLED,
/*
* available POLLING_TRANSFER and INTERRUPT_TRANSFER,
* DMA_TRANSFER does not work
@@ -42,14 +40,8 @@ struct pl022_config_chip dummy_chip_info = {
.hierarchy = SSP_MASTER,
/* 0 = drive TX even as slave, 1 = do not drive TX as slave */
.slave_tx_disable = 0,
- /* LSB first */
- .endian_tx = SSP_TX_LSB,
- .endian_rx = SSP_RX_LSB,
- .data_size = SSP_DATA_BITS_8, /* used to be 12 in some default */
.rx_lev_trig = SSP_RX_1_OR_MORE_ELEM,
.tx_lev_trig = SSP_TX_1_OR_MORE_EMPTY_LOC,
- .clk_phase = SSP_CLK_SECOND_EDGE,
- .clk_pol = SSP_CLK_POL_IDLE_LOW,
.ctrl_len = SSP_BITS_12,
.wait_state = SSP_MWIRE_WAIT_ZERO,
.duplex = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX,
@@ -75,7 +67,7 @@ static struct spi_board_info u300_spi_devices[] = {
.bus_num = 0, /* Only one bus on this chip */
.chip_select = 0,
/* Means SPI_CS_HIGH, change if e.g low CS */
- .mode = 0,
+ .mode = SPI_MODE_1 | SPI_LSB_FIRST | SPI_LOOP,
},
#endif
};
diff --git a/arch/arm/mach-u300/u300.c b/arch/arm/mach-u300/u300.c
index bfcda9820888..07c35a846424 100644
--- a/arch/arm/mach-u300/u300.c
+++ b/arch/arm/mach-u300/u300.c
@@ -61,8 +61,6 @@ static void __init u300_init_machine(void)
MACHINE_START(U300, MACH_U300_STRING)
/* Maintainer: Linus Walleij <linus.walleij@stericsson.com> */
- .phys_io = U300_AHB_PER_PHYS_BASE,
- .io_pg_offst = ((U300_AHB_PER_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = BOOT_PARAMS_OFFSET,
.map_io = u300_map_io,
.reserve = u300_reserve,
diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig
index 6625e5bbf4d6..2dd44a0b4615 100644
--- a/arch/arm/mach-ux500/Kconfig
+++ b/arch/arm/mach-ux500/Kconfig
@@ -21,9 +21,7 @@ config MACH_U8500_MOP
bool "U8500 Development platform"
select UX500_SOC_DB8500
help
- Include support for mop500 development platform
- based on U8500 architecture. The platform is based
- on early drop silicon version of 8500.
+ Include support for the mop500 development platform.
config MACH_U5500
bool "U5500 Development platform"
@@ -39,4 +37,18 @@ config UX500_DEBUG_UART
Choose the UART on which kernel low-level debug messages should be
output.
+config U5500_MODEM_IRQ
+ bool "Modem IRQ support"
+ depends on MACH_U5500
+ default y
+ help
+ Add support for handling IRQ:s from modem side
+
+config U5500_MBOX
+ bool "Mailbox support"
+ depends on MACH_U5500 && U5500_MODEM_IRQ
+ default y
+ help
+ Add support for U5500 mailbox communication with modem side
+
endif
diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile
index 4556aea9c3c5..9e27a84433cb 100644
--- a/arch/arm/mach-ux500/Makefile
+++ b/arch/arm/mach-ux500/Makefile
@@ -4,8 +4,12 @@
obj-y := clock.o cpu.o devices.o
obj-$(CONFIG_UX500_SOC_DB5500) += cpu-db5500.o devices-db5500.o
-obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o
-obj-$(CONFIG_MACH_U8500_MOP) += board-mop500.o
+obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o prcmu.o
+obj-$(CONFIG_MACH_U8500_MOP) += board-mop500.o board-mop500-sdi.o
obj-$(CONFIG_MACH_U5500) += board-u5500.o
obj-$(CONFIG_SMP) += platsmp.o headsmp.o
+obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
+obj-$(CONFIG_REGULATOR_AB8500) += board-mop500-regulators.o
+obj-$(CONFIG_U5500_MODEM_IRQ) += modem_irq.o
+obj-$(CONFIG_U5500_MBOX) += mbox.o
diff --git a/arch/arm/mach-ux500/board-mop500-regulators.c b/arch/arm/mach-ux500/board-mop500-regulators.c
new file mode 100644
index 000000000000..1187f1fc2e53
--- /dev/null
+++ b/arch/arm/mach-ux500/board-mop500-regulators.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License v2
+ *
+ * Author: Sundar Iyer <sundar.iyer@stericsson.com>
+ *
+ * MOP500 board specific initialization for regulators
+ */
+#include <linux/kernel.h>
+#include <linux/regulator/machine.h>
+
+/* supplies to the display/camera */
+static struct regulator_init_data ab8500_vaux1_regulator = {
+ .constraints = {
+ .name = "V-DISPLAY",
+ .min_uV = 2500000,
+ .max_uV = 2900000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE|
+ REGULATOR_CHANGE_STATUS,
+ },
+};
+
+/* supplies to the on-board eMMC */
+static struct regulator_init_data ab8500_vaux2_regulator = {
+ .constraints = {
+ .name = "V-eMMC1",
+ .min_uV = 1100000,
+ .max_uV = 3300000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE|
+ REGULATOR_CHANGE_STATUS,
+ },
+};
+
+/* supply for VAUX3, supplies to SDcard slots */
+static struct regulator_init_data ab8500_vaux3_regulator = {
+ .constraints = {
+ .name = "V-MMC-SD",
+ .min_uV = 1100000,
+ .max_uV = 3300000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE|
+ REGULATOR_CHANGE_STATUS,
+ },
+};
+
+/* supply for tvout, gpadc, TVOUT LDO */
+static struct regulator_init_data ab8500_vtvout_init = {
+ .constraints = {
+ .name = "V-TVOUT",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+};
+
+/* supply for ab8500-vaudio, VAUDIO LDO */
+static struct regulator_init_data ab8500_vaudio_init = {
+ .constraints = {
+ .name = "V-AUD",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+};
+
+/* supply for v-anamic1 VAMic1-LDO */
+static struct regulator_init_data ab8500_vamic1_init = {
+ .constraints = {
+ .name = "V-AMIC1",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+};
+
+/* supply for v-amic2, VAMIC2 LDO, reuse constants for AMIC1 */
+static struct regulator_init_data ab8500_vamic2_init = {
+ .constraints = {
+ .name = "V-AMIC2",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+};
+
+/* supply for v-dmic, VDMIC LDO */
+static struct regulator_init_data ab8500_vdmic_init = {
+ .constraints = {
+ .name = "V-DMIC",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+};
+
+/* supply for v-intcore12, VINTCORE12 LDO */
+static struct regulator_init_data ab8500_vintcore_init = {
+ .constraints = {
+ .name = "V-INTCORE",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+};
+
+/* supply for U8500 CSI/DSI, VANA LDO */
+static struct regulator_init_data ab8500_vana_init = {
+ .constraints = {
+ .name = "V-CSI/DSI",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+};
+
diff --git a/arch/arm/mach-ux500/board-mop500-sdi.c b/arch/arm/mach-ux500/board-mop500-sdi.c
new file mode 100644
index 000000000000..bac995665b58
--- /dev/null
+++ b/arch/arm/mach-ux500/board-mop500-sdi.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Hanumath Prasad <hanumath.prasad@stericsson.com>
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/mmci.h>
+#include <linux/mmc/host.h>
+#include <linux/platform_device.h>
+
+#include <plat/pincfg.h>
+#include <mach/devices.h>
+#include <mach/hardware.h>
+
+#include "pins-db8500.h"
+#include "board-mop500.h"
+
+static pin_cfg_t mop500_sdi_pins[] = {
+ /* SDI4 (on-board eMMC) */
+ GPIO197_MC4_DAT3,
+ GPIO198_MC4_DAT2,
+ GPIO199_MC4_DAT1,
+ GPIO200_MC4_DAT0,
+ GPIO201_MC4_CMD,
+ GPIO202_MC4_FBCLK,
+ GPIO203_MC4_CLK,
+ GPIO204_MC4_DAT7,
+ GPIO205_MC4_DAT6,
+ GPIO206_MC4_DAT5,
+ GPIO207_MC4_DAT4,
+};
+
+static pin_cfg_t mop500_sdi2_pins[] = {
+ /* SDI2 (POP eMMC) */
+ GPIO128_MC2_CLK,
+ GPIO129_MC2_CMD,
+ GPIO130_MC2_FBCLK,
+ GPIO131_MC2_DAT0,
+ GPIO132_MC2_DAT1,
+ GPIO133_MC2_DAT2,
+ GPIO134_MC2_DAT3,
+ GPIO135_MC2_DAT4,
+ GPIO136_MC2_DAT5,
+ GPIO137_MC2_DAT6,
+ GPIO138_MC2_DAT7,
+};
+
+/*
+ * SDI 2 (POP eMMC, not on DB8500ed)
+ */
+
+static struct mmci_platform_data mop500_sdi2_data = {
+ .ocr_mask = MMC_VDD_165_195,
+ .f_max = 100000000,
+ .capabilities = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
+ .gpio_cd = -1,
+ .gpio_wp = -1,
+};
+
+/*
+ * SDI 4 (on-board eMMC)
+ */
+
+static struct mmci_platform_data mop500_sdi4_data = {
+ .ocr_mask = MMC_VDD_29_30,
+ .f_max = 100000000,
+ .capabilities = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA |
+ MMC_CAP_MMC_HIGHSPEED,
+ .gpio_cd = -1,
+ .gpio_wp = -1,
+};
+
+void mop500_sdi_init(void)
+{
+ nmk_config_pins(mop500_sdi_pins, ARRAY_SIZE(mop500_sdi_pins));
+
+ u8500_sdi2_device.dev.platform_data = &mop500_sdi2_data;
+ u8500_sdi4_device.dev.platform_data = &mop500_sdi4_data;
+
+ if (!cpu_is_u8500ed()) {
+ nmk_config_pins(mop500_sdi2_pins, ARRAY_SIZE(mop500_sdi2_pins));
+ amba_device_register(&u8500_sdi2_device, &iomem_resource);
+ }
+
+ /* On-board eMMC */
+ amba_device_register(&u8500_sdi4_device, &iomem_resource);
+}
diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c
index 0e8fd135a57d..fcb587f825cc 100644
--- a/arch/arm/mach-ux500/board-mop500.c
+++ b/arch/arm/mach-ux500/board-mop500.c
@@ -28,8 +28,10 @@
#include <mach/hardware.h>
#include <mach/setup.h>
#include <mach/devices.h>
+#include <mach/irqs.h>
#include "pins-db8500.h"
+#include "board-mop500.h"
static pin_cfg_t mop500_pins[] = {
/* SSP0 */
@@ -55,19 +57,13 @@ static void ab4500_spi_cs_control(u32 command)
}
struct pl022_config_chip ab4500_chip_info = {
- .lbm = LOOPBACK_DISABLED,
.com_mode = INTERRUPT_TRANSFER,
.iface = SSP_INTERFACE_MOTOROLA_SPI,
/* we can act as master only */
.hierarchy = SSP_MASTER,
.slave_tx_disable = 0,
- .endian_rx = SSP_RX_MSB,
- .endian_tx = SSP_TX_MSB,
- .data_size = SSP_DATA_BITS_24,
.rx_lev_trig = SSP_RX_1_OR_MORE_ELEM,
.tx_lev_trig = SSP_TX_1_OR_MORE_EMPTY_LOC,
- .clk_phase = SSP_CLK_SECOND_EDGE,
- .clk_pol = SSP_CLK_POL_IDLE_HIGH,
.cs_control = ab4500_spi_cs_control,
};
@@ -75,15 +71,33 @@ static struct ab8500_platform_data ab8500_platdata = {
.irq_base = MOP500_AB8500_IRQ_BASE,
};
-static struct spi_board_info u8500_spi_devices[] = {
+static struct resource ab8500_resources[] = {
+ [0] = {
+ .start = IRQ_AB8500,
+ .end = IRQ_AB8500,
+ .flags = IORESOURCE_IRQ
+ }
+};
+
+struct platform_device ab8500_device = {
+ .name = "ab8500-i2c",
+ .id = 0,
+ .dev = {
+ .platform_data = &ab8500_platdata,
+ },
+ .num_resources = 1,
+ .resource = ab8500_resources,
+};
+
+static struct spi_board_info ab8500_spi_devices[] = {
{
- .modalias = "ab8500",
+ .modalias = "ab8500-spi",
.controller_data = &ab4500_chip_info,
.platform_data = &ab8500_platdata,
.max_speed_hz = 12000000,
.bus_num = 0,
.chip_select = 0,
- .mode = SPI_MODE_0,
+ .mode = SPI_MODE_3,
.irq = IRQ_DB8500_AB8500,
},
};
@@ -163,14 +177,18 @@ static void __init u8500_init_machine(void)
platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs));
- spi_register_board_info(u8500_spi_devices,
- ARRAY_SIZE(u8500_spi_devices));
+ mop500_sdi_init();
+
+ /* If HW is early drop (ED) or V1.0 then use SPI to access AB8500 */
+ if (cpu_is_u8500ed() || cpu_is_u8500v10())
+ spi_register_board_info(ab8500_spi_devices,
+ ARRAY_SIZE(ab8500_spi_devices));
+ else /* If HW is v.1.1 or later use I2C to access AB8500 */
+ platform_device_register(&ab8500_device);
}
MACHINE_START(U8500, "ST-Ericsson MOP500 platform")
/* Maintainer: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com> */
- .phys_io = U8500_UART2_BASE,
- .io_pg_offst = (IO_ADDRESS(U8500_UART2_BASE) >> 18) & 0xfffc,
.boot_params = 0x100,
.map_io = u8500_map_io,
.init_irq = ux500_init_irq,
diff --git a/arch/arm/mach-ux500/board-mop500.h b/arch/arm/mach-ux500/board-mop500.h
new file mode 100644
index 000000000000..2d240322fa6f
--- /dev/null
+++ b/arch/arm/mach-ux500/board-mop500.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef __BOARD_MOP500_H
+#define __BOARD_MOP500_H
+
+extern void mop500_sdi_init(void);
+
+#endif
diff --git a/arch/arm/mach-ux500/board-u5500.c b/arch/arm/mach-ux500/board-u5500.c
index 4430e69cf538..1ca094a45e71 100644
--- a/arch/arm/mach-ux500/board-u5500.c
+++ b/arch/arm/mach-ux500/board-u5500.c
@@ -31,8 +31,6 @@ static void __init u5500_init_machine(void)
}
MACHINE_START(U8500, "ST-Ericsson U5500 Platform")
- .phys_io = UX500_UART0_BASE,
- .io_pg_offst = (IO_ADDRESS(UX500_UART0_BASE) >> 18) & 0xfffc,
.boot_params = 0x00000100,
.map_io = u5500_map_io,
.init_irq = ux500_init_irq,
diff --git a/arch/arm/mach-ux500/cpu-db5500.c b/arch/arm/mach-ux500/cpu-db5500.c
index e9278f6d67aa..2f87075e9d6f 100644
--- a/arch/arm/mach-ux500/cpu-db5500.c
+++ b/arch/arm/mach-ux500/cpu-db5500.c
@@ -14,6 +14,7 @@
#include <mach/hardware.h>
#include <mach/devices.h>
#include <mach/setup.h>
+#include <mach/irqs.h>
static struct map_desc u5500_io_desc[] __initdata = {
__IO_DEV_DESC(U5500_GPIO0_BASE, SZ_4K),
@@ -24,6 +25,90 @@ static struct map_desc u5500_io_desc[] __initdata = {
__IO_DEV_DESC(U5500_PRCMU_BASE, SZ_4K),
};
+static struct resource mbox0_resources[] = {
+ {
+ .name = "mbox_peer",
+ .start = U5500_MBOX0_PEER_START,
+ .end = U5500_MBOX0_PEER_END,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "mbox_local",
+ .start = U5500_MBOX0_LOCAL_START,
+ .end = U5500_MBOX0_LOCAL_END,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "mbox_irq",
+ .start = MBOX_PAIR0_VIRT_IRQ,
+ .end = MBOX_PAIR0_VIRT_IRQ,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct resource mbox1_resources[] = {
+ {
+ .name = "mbox_peer",
+ .start = U5500_MBOX1_PEER_START,
+ .end = U5500_MBOX1_PEER_END,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "mbox_local",
+ .start = U5500_MBOX1_LOCAL_START,
+ .end = U5500_MBOX1_LOCAL_END,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "mbox_irq",
+ .start = MBOX_PAIR1_VIRT_IRQ,
+ .end = MBOX_PAIR1_VIRT_IRQ,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct resource mbox2_resources[] = {
+ {
+ .name = "mbox_peer",
+ .start = U5500_MBOX2_PEER_START,
+ .end = U5500_MBOX2_PEER_END,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "mbox_local",
+ .start = U5500_MBOX2_LOCAL_START,
+ .end = U5500_MBOX2_LOCAL_END,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "mbox_irq",
+ .start = MBOX_PAIR2_VIRT_IRQ,
+ .end = MBOX_PAIR2_VIRT_IRQ,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct platform_device mbox0_device = {
+ .id = 0,
+ .name = "mbox",
+ .resource = mbox0_resources,
+ .num_resources = ARRAY_SIZE(mbox0_resources),
+};
+
+static struct platform_device mbox1_device = {
+ .id = 1,
+ .name = "mbox",
+ .resource = mbox1_resources,
+ .num_resources = ARRAY_SIZE(mbox1_resources),
+};
+
+static struct platform_device mbox2_device = {
+ .id = 2,
+ .name = "mbox",
+ .resource = mbox2_resources,
+ .num_resources = ARRAY_SIZE(mbox2_resources),
+};
+
static struct platform_device *u5500_platform_devs[] __initdata = {
&u5500_gpio_devs[0],
&u5500_gpio_devs[1],
@@ -33,6 +118,9 @@ static struct platform_device *u5500_platform_devs[] __initdata = {
&u5500_gpio_devs[5],
&u5500_gpio_devs[6],
&u5500_gpio_devs[7],
+ &mbox0_device,
+ &mbox1_device,
+ &mbox2_device,
};
void __init u5500_map_io(void)
diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c
index f21c444edd99..4acab7544b3c 100644
--- a/arch/arm/mach-ux500/cpu-db8500.c
+++ b/arch/arm/mach-ux500/cpu-db8500.c
@@ -38,10 +38,12 @@ static struct platform_device *platform_devs[] __initdata = {
/* minimum static i/o mapping required to boot U8500 platforms */
static struct map_desc u8500_io_desc[] __initdata = {
__IO_DEV_DESC(U8500_PRCMU_BASE, SZ_4K),
+ __IO_DEV_DESC(U8500_PRCMU_TCDM_BASE, SZ_4K),
__IO_DEV_DESC(U8500_GPIO0_BASE, SZ_4K),
__IO_DEV_DESC(U8500_GPIO1_BASE, SZ_4K),
__IO_DEV_DESC(U8500_GPIO2_BASE, SZ_4K),
__IO_DEV_DESC(U8500_GPIO3_BASE, SZ_4K),
+ __MEM_DEV_DESC(U8500_BOOT_ROM_BASE, SZ_1M),
};
static struct map_desc u8500ed_io_desc[] __initdata = {
@@ -53,6 +55,69 @@ static struct map_desc u8500v1_io_desc[] __initdata = {
__IO_DEV_DESC(U8500_MTU0_BASE, SZ_4K),
};
+/*
+ * Functions to differentiate between later ASICs
+ * We look into the end of the ROM to locate the hardcoded ASIC ID.
+ * This is only needed to differentiate between minor revisions and
+ * process variants of an ASIC, the major revisions are encoded in
+ * the cpuid.
+ */
+#define U8500_ASIC_ID_LOC_ED_V1 (U8500_BOOT_ROM_BASE + 0x1FFF4)
+#define U8500_ASIC_ID_LOC_V2 (U8500_BOOT_ROM_BASE + 0x1DBF4)
+#define U8500_ASIC_REV_ED 0x01
+#define U8500_ASIC_REV_V10 0xA0
+#define U8500_ASIC_REV_V11 0xA1
+#define U8500_ASIC_REV_V20 0xB0
+
+/**
+ * struct db8500_asic_id - fields of the ASIC ID
+ * @process: the manufacturing process, 0x40 is 40 nm
+ * 0x00 is "standard"
+ * @partnumber: hithereto 0x8500 for DB8500
+ * @revision: version code in the series
+ * This field definion is not formally defined but makes
+ * sense.
+ */
+struct db8500_asic_id {
+ u8 process;
+ u16 partnumber;
+ u8 revision;
+};
+
+/* This isn't going to change at runtime */
+static struct db8500_asic_id db8500_id;
+
+static void __init get_db8500_asic_id(void)
+{
+ u32 asicid;
+
+ if (cpu_is_u8500v1() || cpu_is_u8500ed())
+ asicid = readl(__io_address(U8500_ASIC_ID_LOC_ED_V1));
+ else if (cpu_is_u8500v2())
+ asicid = readl(__io_address(U8500_ASIC_ID_LOC_V2));
+ else
+ BUG();
+
+ db8500_id.process = (asicid >> 24);
+ db8500_id.partnumber = (asicid >> 16) & 0xFFFFU;
+ db8500_id.revision = asicid & 0xFFU;
+}
+
+bool cpu_is_u8500v10(void)
+{
+ return (db8500_id.revision == U8500_ASIC_REV_V10);
+}
+
+bool cpu_is_u8500v11(void)
+{
+ return (db8500_id.revision == U8500_ASIC_REV_V11);
+}
+
+bool cpu_is_u8500v20(void)
+{
+ return (db8500_id.revision == U8500_ASIC_REV_V20);
+}
+
void __init u8500_map_io(void)
{
ux500_map_io();
@@ -63,6 +128,9 @@ void __init u8500_map_io(void)
iotable_init(u8500ed_io_desc, ARRAY_SIZE(u8500ed_io_desc));
else
iotable_init(u8500v1_io_desc, ARRAY_SIZE(u8500v1_io_desc));
+
+ /* Read out the ASIC ID as early as we can */
+ get_db8500_asic_id();
}
/*
@@ -70,6 +138,20 @@ void __init u8500_map_io(void)
*/
void __init u8500_init_devices(void)
{
+ /* Display some ASIC boilerplate */
+ pr_info("DB8500: process: %02x, revision ID: 0x%02x\n",
+ db8500_id.process, db8500_id.revision);
+ if (cpu_is_u8500ed())
+ pr_info("DB8500: Early Drop (ED)\n");
+ else if (cpu_is_u8500v10())
+ pr_info("DB8500: version 1.0\n");
+ else if (cpu_is_u8500v11())
+ pr_info("DB8500: version 1.1\n");
+ else if (cpu_is_u8500v20())
+ pr_info("DB8500: version 2.0\n");
+ else
+ pr_warning("ASIC: UNKNOWN SILICON VERSION!\n");
+
ux500_init_devices();
if (cpu_is_u8500ed())
diff --git a/arch/arm/mach-ux500/devices-db8500.c b/arch/arm/mach-ux500/devices-db8500.c
index 9280d2561111..40032fecbc16 100644
--- a/arch/arm/mach-ux500/devices-db8500.c
+++ b/arch/arm/mach-ux500/devices-db8500.c
@@ -110,6 +110,82 @@ struct platform_device u8500_i2c4_device = {
.num_resources = ARRAY_SIZE(u8500_i2c4_resources),
};
+/*
+ * SD/MMC
+ */
+
+struct amba_device u8500_sdi0_device = {
+ .dev = {
+ .init_name = "sdi0",
+ },
+ .res = {
+ .start = U8500_SDI0_BASE,
+ .end = U8500_SDI0_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ .irq = {IRQ_DB8500_SDMMC0, NO_IRQ},
+};
+
+struct amba_device u8500_sdi1_device = {
+ .dev = {
+ .init_name = "sdi1",
+ },
+ .res = {
+ .start = U8500_SDI1_BASE,
+ .end = U8500_SDI1_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ .irq = {IRQ_DB8500_SDMMC1, NO_IRQ},
+};
+
+struct amba_device u8500_sdi2_device = {
+ .dev = {
+ .init_name = "sdi2",
+ },
+ .res = {
+ .start = U8500_SDI2_BASE,
+ .end = U8500_SDI2_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ .irq = {IRQ_DB8500_SDMMC2, NO_IRQ},
+};
+
+struct amba_device u8500_sdi3_device = {
+ .dev = {
+ .init_name = "sdi3",
+ },
+ .res = {
+ .start = U8500_SDI3_BASE,
+ .end = U8500_SDI3_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ .irq = {IRQ_DB8500_SDMMC3, NO_IRQ},
+};
+
+struct amba_device u8500_sdi4_device = {
+ .dev = {
+ .init_name = "sdi4",
+ },
+ .res = {
+ .start = U8500_SDI4_BASE,
+ .end = U8500_SDI4_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ .irq = {IRQ_DB8500_SDMMC4, NO_IRQ},
+};
+
+struct amba_device u8500_sdi5_device = {
+ .dev = {
+ .init_name = "sdi5",
+ },
+ .res = {
+ .start = U8500_SDI5_BASE,
+ .end = U8500_SDI5_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ .irq = {IRQ_DB8500_SDMMC5, NO_IRQ},
+};
+
static struct resource dma40_resources[] = {
[0] = {
.start = U8500_DMA_BASE,
@@ -170,23 +246,23 @@ struct stedma40_chan_cfg dma40_memcpy_conf_log = {
* Mapping between destination event lines and physical device address.
* The event line is tied to a device and therefor the address is constant.
*/
-static const dma_addr_t dma40_tx_map[STEDMA40_NR_DEV];
+static const dma_addr_t dma40_tx_map[DB8500_DMA_NR_DEV];
/* Mapping between source event lines and physical device address */
-static const dma_addr_t dma40_rx_map[STEDMA40_NR_DEV];
+static const dma_addr_t dma40_rx_map[DB8500_DMA_NR_DEV];
/* Reserved event lines for memcpy only */
static int dma40_memcpy_event[] = {
- STEDMA40_MEMCPY_TX_0,
- STEDMA40_MEMCPY_TX_1,
- STEDMA40_MEMCPY_TX_2,
- STEDMA40_MEMCPY_TX_3,
- STEDMA40_MEMCPY_TX_4,
- STEDMA40_MEMCPY_TX_5,
+ DB8500_DMA_MEMCPY_TX_0,
+ DB8500_DMA_MEMCPY_TX_1,
+ DB8500_DMA_MEMCPY_TX_2,
+ DB8500_DMA_MEMCPY_TX_3,
+ DB8500_DMA_MEMCPY_TX_4,
+ DB8500_DMA_MEMCPY_TX_5,
};
static struct stedma40_platform_data dma40_plat_data = {
- .dev_len = STEDMA40_NR_DEV,
+ .dev_len = DB8500_DMA_NR_DEV,
.dev_rx = dma40_rx_map,
.dev_tx = dma40_tx_map,
.memcpy = dma40_memcpy_event,
diff --git a/arch/arm/mach-ux500/hotplug.c b/arch/arm/mach-ux500/hotplug.c
new file mode 100644
index 000000000000..b782a03024be
--- /dev/null
+++ b/arch/arm/mach-ux500/hotplug.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) STMicroelectronics 2009
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License v2
+ * Based on ARM realview platform
+ *
+ * Author: Sundar Iyer <sundar.iyer@stericsson.com>
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/smp.h>
+#include <linux/completion.h>
+
+#include <asm/cacheflush.h>
+
+extern volatile int pen_release;
+
+static DECLARE_COMPLETION(cpu_killed);
+
+static inline void platform_do_lowpower(unsigned int cpu)
+{
+ flush_cache_all();
+
+ /* we put the platform to just WFI */
+ for (;;) {
+ __asm__ __volatile__("dsb\n\t" "wfi\n\t"
+ : : : "memory");
+ if (pen_release == cpu) {
+ /*
+ * OK, proper wakeup, we're done
+ */
+ break;
+ }
+ }
+}
+
+int platform_cpu_kill(unsigned int cpu)
+{
+ return wait_for_completion_timeout(&cpu_killed, 5000);
+}
+
+/*
+ * platform-specific code to shutdown a CPU
+ *
+ * Called with IRQs disabled
+ */
+void platform_cpu_die(unsigned int cpu)
+{
+#ifdef DEBUG
+ unsigned int this_cpu = hard_smp_processor_id();
+
+ if (cpu != this_cpu) {
+ printk(KERN_CRIT "Eek! platform_cpu_die running on %u, should be %u\n",
+ this_cpu, cpu);
+ BUG();
+ }
+#endif
+
+ printk(KERN_NOTICE "CPU%u: shutdown\n", cpu);
+ complete(&cpu_killed);
+
+ /* directly enter low power state, skipping secure registers */
+ platform_do_lowpower(cpu);
+}
+
+int platform_cpu_disable(unsigned int cpu)
+{
+ /*
+ * we don't allow CPU 0 to be shutdown (it is still too special
+ * e.g. clock tick interrupts)
+ */
+ return cpu == 0 ? -EPERM : 0;
+}
diff --git a/arch/arm/mach-ux500/include/mach/db5500-regs.h b/arch/arm/mach-ux500/include/mach/db5500-regs.h
index 545c80fc8024..3eafc0e24ba5 100644
--- a/arch/arm/mach-ux500/include/mach/db5500-regs.h
+++ b/arch/arm/mach-ux500/include/mach/db5500-regs.h
@@ -100,4 +100,18 @@
#define U5500_GPIOBANK6_BASE (U5500_GPIO4_BASE + 0x80)
#define U5500_GPIOBANK7_BASE (U5500_GPIO4_BASE + 0x100)
+#define U5500_MBOX_BASE (U5500_MODEM_BASE + 0xFFD1000)
+#define U5500_MBOX0_PEER_START (U5500_MBOX_BASE + 0x40)
+#define U5500_MBOX0_PEER_END (U5500_MBOX_BASE + 0x5F)
+#define U5500_MBOX0_LOCAL_START (U5500_MBOX_BASE + 0x60)
+#define U5500_MBOX0_LOCAL_END (U5500_MBOX_BASE + 0x7F)
+#define U5500_MBOX1_PEER_START (U5500_MBOX_BASE + 0x80)
+#define U5500_MBOX1_PEER_END (U5500_MBOX_BASE + 0x9F)
+#define U5500_MBOX1_LOCAL_START (U5500_MBOX_BASE + 0xA0)
+#define U5500_MBOX1_LOCAL_END (U5500_MBOX_BASE + 0xBF)
+#define U5500_MBOX2_PEER_START (U5500_MBOX_BASE + 0x00)
+#define U5500_MBOX2_PEER_END (U5500_MBOX_BASE + 0x1F)
+#define U5500_MBOX2_LOCAL_START (U5500_MBOX_BASE + 0x20)
+#define U5500_MBOX2_LOCAL_END (U5500_MBOX_BASE + 0x3F)
+
#endif
diff --git a/arch/arm/mach-ux500/include/mach/db8500-regs.h b/arch/arm/mach-ux500/include/mach/db8500-regs.h
index f000218210c9..f07d0986409d 100644
--- a/arch/arm/mach-ux500/include/mach/db8500-regs.h
+++ b/arch/arm/mach-ux500/include/mach/db8500-regs.h
@@ -30,8 +30,6 @@
#define U8500_ICN_BASE 0x81000000
#define U8500_BOOT_ROM_BASE 0x90000000
-/* ASIC ID is at 0xff4 offset within this region */
-#define U8500_ASIC_ID_BASE 0x9001F000
#define U8500_PER6_BASE 0xa03c0000
#define U8500_PER5_BASE 0xa03e0000
diff --git a/arch/arm/mach-ux500/include/mach/debug-macro.S b/arch/arm/mach-ux500/include/mach/debug-macro.S
index c5203b7ea552..be7c0f14e310 100644
--- a/arch/arm/mach-ux500/include/mach/debug-macro.S
+++ b/arch/arm/mach-ux500/include/mach/debug-macro.S
@@ -18,11 +18,9 @@
#define UX500_UART(n) __UX500_UART(n)
#define UART_BASE UX500_UART(CONFIG_UX500_DEBUG_UART)
- .macro addruart, rx, tmp
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ MMU enabled?
- ldreq \rx, =UART_BASE @ no, physical address
- ldrne \rx, =IO_ADDRESS(UART_BASE) @ yes, virtual address
+ .macro addruart, rp, rv
+ ldr \rp, =UART_BASE @ no, physical address
+ ldr \rv, =IO_ADDRESS(UART_BASE) @ yes, virtual address
.endm
#include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/mach-ux500/include/mach/devices.h b/arch/arm/mach-ux500/include/mach/devices.h
index c2b2f2574947..33a120c2e82e 100644
--- a/arch/arm/mach-ux500/include/mach/devices.h
+++ b/arch/arm/mach-ux500/include/mach/devices.h
@@ -27,6 +27,13 @@ extern struct platform_device u8500_i2c0_device;
extern struct platform_device u8500_i2c4_device;
extern struct platform_device u8500_dma40_device;
+extern struct amba_device u8500_sdi0_device;
+extern struct amba_device u8500_sdi1_device;
+extern struct amba_device u8500_sdi2_device;
+extern struct amba_device u8500_sdi3_device;
+extern struct amba_device u8500_sdi4_device;
+extern struct amba_device u8500_sdi5_device;
+
void dma40_u8500ed_fixup(void);
#endif
diff --git a/arch/arm/mach-ux500/include/mach/hardware.h b/arch/arm/mach-ux500/include/mach/hardware.h
index 8656379a8309..32e883a8f2a2 100644
--- a/arch/arm/mach-ux500/include/mach/hardware.h
+++ b/arch/arm/mach-ux500/include/mach/hardware.h
@@ -104,16 +104,35 @@ static inline bool cpu_is_u8500(void)
#endif
}
+#define CPUID_DB8500ED 0x410fc090
+#define CPUID_DB8500V1 0x411fc091
+#define CPUID_DB8500V2 0x412fc091
+
static inline bool cpu_is_u8500ed(void)
{
- return cpu_is_u8500() && (read_cpuid_id() & 15) == 0;
+ return cpu_is_u8500() && (read_cpuid_id() == CPUID_DB8500ED);
}
static inline bool cpu_is_u8500v1(void)
{
- return cpu_is_u8500() && (read_cpuid_id() & 15) == 1;
+ return cpu_is_u8500() && (read_cpuid_id() == CPUID_DB8500V1);
+}
+
+static inline bool cpu_is_u8500v2(void)
+{
+ return cpu_is_u8500() && (read_cpuid_id() == CPUID_DB8500V2);
}
+#ifdef CONFIG_UX500_SOC_DB8500
+bool cpu_is_u8500v10(void);
+bool cpu_is_u8500v11(void);
+bool cpu_is_u8500v20(void);
+#else
+static inline bool cpu_is_u8500v10(void) { return false; }
+static inline bool cpu_is_u8500v11(void) { return false; }
+static inline bool cpu_is_u8500v20(void) { return false; }
+#endif
+
static inline bool cpu_is_u5500(void)
{
#ifdef CONFIG_UX500_SOC_DB5500
diff --git a/arch/arm/mach-ux500/include/mach/irqs-db5500.h b/arch/arm/mach-ux500/include/mach/irqs-db5500.h
index 6fbfe5e2065a..bfa123dbec3b 100644
--- a/arch/arm/mach-ux500/include/mach/irqs-db5500.h
+++ b/arch/arm/mach-ux500/include/mach/irqs-db5500.h
@@ -61,6 +61,7 @@
#define IRQ_DB5500_SDMMC0 (IRQ_SHPI_START + 60)
#define IRQ_DB5500_HSEM (IRQ_SHPI_START + 61)
#define IRQ_DB5500_SBAG (IRQ_SHPI_START + 63)
+#define IRQ_DB5500_MODEM (IRQ_SHPI_START + 65)
#define IRQ_DB5500_SPI1 (IRQ_SHPI_START + 96)
#define IRQ_DB5500_MSP2 (IRQ_SHPI_START + 98)
#define IRQ_DB5500_SRPTIMER (IRQ_SHPI_START + 101)
diff --git a/arch/arm/mach-ux500/include/mach/irqs.h b/arch/arm/mach-ux500/include/mach/irqs.h
index 10385bdc2b77..693aa57de88d 100644
--- a/arch/arm/mach-ux500/include/mach/irqs.h
+++ b/arch/arm/mach-ux500/include/mach/irqs.h
@@ -40,7 +40,8 @@
#define IRQ_HSIR_CH1_OVRRUN (IRQ_SHPI_START + 33)
#define IRQ_HSIR_CH2_OVRRUN (IRQ_SHPI_START + 34)
#define IRQ_HSIR_CH3_OVRRUN (IRQ_SHPI_START + 35)
-#define IRQ_AB4500 (IRQ_SHPI_START + 40)
+#define IRQ_AB8500 (IRQ_SHPI_START + 40)
+#define IRQ_PRCMU (IRQ_SHPI_START + 47)
#define IRQ_DISP (IRQ_SHPI_START + 48)
#define IRQ_SiPI3 (IRQ_SHPI_START + 49)
#define IRQ_I2C4 (IRQ_SHPI_START + 51)
@@ -83,6 +84,19 @@
#include <mach/irqs-board-mop500.h>
#endif
-#define NR_IRQS IRQ_BOARD_END
+/*
+ * After the board specific IRQ:s we reserve a range of IRQ:s in which virtual
+ * IRQ:s representing modem IRQ:s can be allocated
+ */
+#define IRQ_MODEM_EVENTS_BASE (IRQ_BOARD_END + 1)
+#define IRQ_MODEM_EVENTS_NBR 72
+#define IRQ_MODEM_EVENTS_END (IRQ_MODEM_EVENTS_BASE + IRQ_MODEM_EVENTS_NBR)
+
+/* List of virtual IRQ:s that are allocated from the range above */
+#define MBOX_PAIR0_VIRT_IRQ (IRQ_MODEM_EVENTS_BASE + 43)
+#define MBOX_PAIR1_VIRT_IRQ (IRQ_MODEM_EVENTS_BASE + 45)
+#define MBOX_PAIR2_VIRT_IRQ (IRQ_MODEM_EVENTS_BASE + 41)
+
+#define NR_IRQS IRQ_MODEM_EVENTS_END
#endif /* ASM_ARCH_IRQS_H */
diff --git a/arch/arm/mach-ux500/include/mach/mbox.h b/arch/arm/mach-ux500/include/mach/mbox.h
new file mode 100644
index 000000000000..7f9da4d2fbda
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/mbox.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Stefan Nilsson <stefan.xk.nilsson@stericsson.com> for ST-Ericsson.
+ * Author: Martin Persson <martin.persson@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#ifndef __INC_STE_MBOX_H
+#define __INC_STE_MBOX_H
+
+#define MBOX_BUF_SIZE 16
+#define MBOX_NAME_SIZE 8
+
+/**
+ * mbox_recv_cb_t - Definition of the mailbox callback.
+ * @mbox_msg: The mailbox message.
+ * @priv: The clients private data as specified in the call to mbox_setup.
+ *
+ * This function will be called upon reception of new mailbox messages.
+ */
+typedef void mbox_recv_cb_t (u32 mbox_msg, void *priv);
+
+/**
+ * struct mbox - Mailbox instance struct
+ * @list: Linked list head.
+ * @pdev: Pointer to device struct.
+ * @cb: Callback function. Will be called
+ * when new data is received.
+ * @client_data: Clients private data. Will be sent back
+ * in the callback function.
+ * @virtbase_peer: Virtual address for outgoing mailbox.
+ * @virtbase_local: Virtual address for incoming mailbox.
+ * @buffer: Then internal queue for outgoing messages.
+ * @name: Name of this mailbox.
+ * @buffer_available: Completion variable to achieve "blocking send".
+ * This variable will be signaled when there is
+ * internal buffer space available.
+ * @client_blocked: To keep track if any client is currently
+ * blocked.
+ * @lock: Spinlock to protect this mailbox instance.
+ * @write_index: Index in internal buffer to write to.
+ * @read_index: Index in internal buffer to read from.
+ * @allocated: Indicates whether this particular mailbox
+ * id has been allocated by someone.
+ */
+struct mbox {
+ struct list_head list;
+ struct platform_device *pdev;
+ mbox_recv_cb_t *cb;
+ void *client_data;
+ void __iomem *virtbase_peer;
+ void __iomem *virtbase_local;
+ u32 buffer[MBOX_BUF_SIZE];
+ char name[MBOX_NAME_SIZE];
+ struct completion buffer_available;
+ u8 client_blocked;
+ spinlock_t lock;
+ u8 write_index;
+ u8 read_index;
+ bool allocated;
+};
+
+/**
+ * mbox_setup - Set up a mailbox and return its instance.
+ * @mbox_id: The ID number of the mailbox. 0 or 1 for modem CPU,
+ * 2 for modem DSP.
+ * @mbox_cb: Pointer to the callback function to be called when a new message
+ * is received.
+ * @priv: Client user data which will be returned in the callback.
+ *
+ * Returns a mailbox instance to be specified in subsequent calls to mbox_send.
+ */
+struct mbox *mbox_setup(u8 mbox_id, mbox_recv_cb_t *mbox_cb, void *priv);
+
+/**
+ * mbox_send - Send a mailbox message.
+ * @mbox: Mailbox instance (returned by mbox_setup)
+ * @mbox_msg: The mailbox message to send.
+ * @block: Specifies whether this call will block until send is possible,
+ * or return an error if the mailbox buffer is full.
+ *
+ * Returns 0 on success or a negative error code on error. -ENOMEM indicates
+ * that the internal buffer is full and you have to try again later (or
+ * specify "block" in order to block until send is possible).
+ */
+int mbox_send(struct mbox *mbox, u32 mbox_msg, bool block);
+
+#endif /*INC_STE_MBOX_H*/
diff --git a/arch/arm/mach-ux500/include/mach/prcmu-regs.h b/arch/arm/mach-ux500/include/mach/prcmu-regs.h
new file mode 100644
index 000000000000..8885f39a6421
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/prcmu-regs.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2009 ST-Ericsson SA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ */
+#ifndef __MACH_PRCMU_REGS_H
+#define __MACH_PRCMU_REGS_H
+
+#include <mach/hardware.h>
+
+#define _PRCMU_BASE IO_ADDRESS(U8500_PRCMU_BASE)
+
+#define PRCM_ARM_PLLDIVPS (_PRCMU_BASE + 0x118)
+#define PRCM_ARM_CHGCLKREQ (_PRCMU_BASE + 0x114)
+#define PRCM_PLLARM_ENABLE (_PRCMU_BASE + 0x98)
+#define PRCM_ARMCLKFIX_MGT (_PRCMU_BASE + 0x0)
+#define PRCM_A9_RESETN_CLR (_PRCMU_BASE + 0x1f4)
+#define PRCM_A9_RESETN_SET (_PRCMU_BASE + 0x1f0)
+#define PRCM_ARM_LS_CLAMP (_PRCMU_BASE + 0x30c)
+#define PRCM_SRAM_A9 (_PRCMU_BASE + 0x308)
+
+/* ARM WFI Standby signal register */
+#define PRCM_ARM_WFI_STANDBY (_PRCMU_BASE + 0x130)
+#define PRCMU_IOCR (_PRCMU_BASE + 0x310)
+
+/* CPU mailbox registers */
+#define PRCM_MBOX_CPU_VAL (_PRCMU_BASE + 0x0fc)
+#define PRCM_MBOX_CPU_SET (_PRCMU_BASE + 0x100)
+#define PRCM_MBOX_CPU_CLR (_PRCMU_BASE + 0x104)
+
+/* Dual A9 core interrupt management unit registers */
+#define PRCM_A9_MASK_REQ (_PRCMU_BASE + 0x328)
+#define PRCM_A9_MASK_ACK (_PRCMU_BASE + 0x32c)
+#define PRCM_ARMITMSK31TO0 (_PRCMU_BASE + 0x11c)
+#define PRCM_ARMITMSK63TO32 (_PRCMU_BASE + 0x120)
+#define PRCM_ARMITMSK95TO64 (_PRCMU_BASE + 0x124)
+#define PRCM_ARMITMSK127TO96 (_PRCMU_BASE + 0x128)
+#define PRCM_POWER_STATE_VAL (_PRCMU_BASE + 0x25C)
+#define PRCM_ARMITVAL31TO0 (_PRCMU_BASE + 0x260)
+#define PRCM_ARMITVAL63TO32 (_PRCMU_BASE + 0x264)
+#define PRCM_ARMITVAL95TO64 (_PRCMU_BASE + 0x268)
+#define PRCM_ARMITVAL127TO96 (_PRCMU_BASE + 0x26C)
+
+#define PRCM_HOSTACCESS_REQ (_PRCMU_BASE + 0x334)
+#define ARM_WAKEUP_MODEM 0x1
+
+#define PRCM_ARM_IT1_CLEAR (_PRCMU_BASE + 0x48C)
+#define PRCM_ARM_IT1_VAL (_PRCMU_BASE + 0x494)
+#define PRCM_HOLD_EVT (_PRCMU_BASE + 0x174)
+
+#define PRCM_ITSTATUS0 (_PRCMU_BASE + 0x148)
+#define PRCM_ITSTATUS1 (_PRCMU_BASE + 0x150)
+#define PRCM_ITSTATUS2 (_PRCMU_BASE + 0x158)
+#define PRCM_ITSTATUS3 (_PRCMU_BASE + 0x160)
+#define PRCM_ITSTATUS4 (_PRCMU_BASE + 0x168)
+#define PRCM_ITSTATUS5 (_PRCMU_BASE + 0x484)
+#define PRCM_ITCLEAR5 (_PRCMU_BASE + 0x488)
+#define PRCM_ARMIT_MASKXP70_IT (_PRCMU_BASE + 0x1018)
+
+/* System reset register */
+#define PRCM_APE_SOFTRST (_PRCMU_BASE + 0x228)
+
+/* Level shifter and clamp control registers */
+#define PRCM_MMIP_LS_CLAMP_SET (_PRCMU_BASE + 0x420)
+#define PRCM_MMIP_LS_CLAMP_CLR (_PRCMU_BASE + 0x424)
+
+/* PRCMU clock/PLL/reset registers */
+#define PRCM_PLLDSI_FREQ (_PRCMU_BASE + 0x500)
+#define PRCM_PLLDSI_ENABLE (_PRCMU_BASE + 0x504)
+#define PRCM_LCDCLK_MGT (_PRCMU_BASE + 0x044)
+#define PRCM_MCDECLK_MGT (_PRCMU_BASE + 0x064)
+#define PRCM_HDMICLK_MGT (_PRCMU_BASE + 0x058)
+#define PRCM_TVCLK_MGT (_PRCMU_BASE + 0x07c)
+#define PRCM_DSI_PLLOUT_SEL (_PRCMU_BASE + 0x530)
+#define PRCM_DSITVCLK_DIV (_PRCMU_BASE + 0x52C)
+#define PRCM_APE_RESETN_SET (_PRCMU_BASE + 0x1E4)
+#define PRCM_APE_RESETN_CLR (_PRCMU_BASE + 0x1E8)
+
+/* ePOD and memory power signal control registers */
+#define PRCM_EPOD_C_SET (_PRCMU_BASE + 0x410)
+#define PRCM_SRAM_LS_SLEEP (_PRCMU_BASE + 0x304)
+
+/* Debug power control unit registers */
+#define PRCM_POWER_STATE_SET (_PRCMU_BASE + 0x254)
+
+/* Miscellaneous unit registers */
+#define PRCM_DSI_SW_RESET (_PRCMU_BASE + 0x324)
+
+#endif /* __MACH_PRCMU__REGS_H */
diff --git a/arch/arm/mach-ux500/include/mach/prcmu.h b/arch/arm/mach-ux500/include/mach/prcmu.h
new file mode 100644
index 000000000000..549843ff6dbe
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/prcmu.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) STMicroelectronics 2009
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License v2
+ *
+ * PRCMU f/w APIs
+ */
+#ifndef __MACH_PRCMU_H
+#define __MACH_PRCMU_H
+
+int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size);
+int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size);
+
+#endif /* __MACH_PRCMU_H */
diff --git a/arch/arm/mach-ux500/include/mach/setup.h b/arch/arm/mach-ux500/include/mach/setup.h
index e978dbd9e210..54bbe648bf58 100644
--- a/arch/arm/mach-ux500/include/mach/setup.h
+++ b/arch/arm/mach-ux500/include/mach/setup.h
@@ -38,4 +38,11 @@ extern struct sys_timer ux500_timer;
.type = MT_DEVICE, \
}
+#define __MEM_DEV_DESC(x, sz) { \
+ .virtual = IO_ADDRESS(x), \
+ .pfn = __phys_to_pfn(x), \
+ .length = sz, \
+ .type = MT_MEMORY, \
+}
+
#endif /* __ASM_ARCH_SETUP_H */
diff --git a/arch/arm/mach-ux500/include/mach/smp.h b/arch/arm/mach-ux500/include/mach/smp.h
index b59f7bc9725d..197e8417375e 100644
--- a/arch/arm/mach-ux500/include/mach/smp.h
+++ b/arch/arm/mach-ux500/include/mach/smp.h
@@ -10,18 +10,11 @@
#define ASMARM_ARCH_SMP_H
#include <asm/hardware/gic.h>
+#include <asm/smp_mpidr.h>
/* This is required to wakeup the secondary core */
extern void u8500_secondary_startup(void);
-#define hard_smp_processor_id() \
- ({ \
- unsigned int cpunum; \
- __asm__("mrc p15, 0, %0, c0, c0, 5" \
- : "=r" (cpunum)); \
- cpunum &= 0x0F; \
- })
-
/*
* We use IRQ1 as the IPI
*/
diff --git a/arch/arm/mach-ux500/mbox.c b/arch/arm/mach-ux500/mbox.c
new file mode 100644
index 000000000000..63435389c544
--- /dev/null
+++ b/arch/arm/mach-ux500/mbox.c
@@ -0,0 +1,567 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Stefan Nilsson <stefan.xk.nilsson@stericsson.com> for ST-Ericsson.
+ * Author: Martin Persson <martin.persson@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+/*
+ * Mailbox nomenclature:
+ *
+ * APE MODEM
+ * mbox pairX
+ * ..........................
+ * . .
+ * . peer .
+ * . send ---- .
+ * . --> | | .
+ * . | | .
+ * . ---- .
+ * . .
+ * . local .
+ * . rec ---- .
+ * . | | <-- .
+ * . | | .
+ * . ---- .
+ * .........................
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/completion.h>
+#include <mach/mbox.h>
+
+#define MBOX_NAME "mbox"
+
+#define MBOX_FIFO_DATA 0x000
+#define MBOX_FIFO_ADD 0x004
+#define MBOX_FIFO_REMOVE 0x008
+#define MBOX_FIFO_THRES_FREE 0x00C
+#define MBOX_FIFO_THRES_OCCUP 0x010
+#define MBOX_FIFO_STATUS 0x014
+
+#define MBOX_DISABLE_IRQ 0x4
+#define MBOX_ENABLE_IRQ 0x0
+#define MBOX_LATCH 1
+
+/* Global list of all mailboxes */
+static struct list_head mboxs = LIST_HEAD_INIT(mboxs);
+
+static struct mbox *get_mbox_with_id(u8 id)
+{
+ u8 i;
+ struct list_head *pos = &mboxs;
+ for (i = 0; i <= id; i++)
+ pos = pos->next;
+
+ return (struct mbox *) list_entry(pos, struct mbox, list);
+}
+
+int mbox_send(struct mbox *mbox, u32 mbox_msg, bool block)
+{
+ int res = 0;
+
+ spin_lock(&mbox->lock);
+
+ dev_dbg(&(mbox->pdev->dev),
+ "About to buffer 0x%X to mailbox 0x%X."
+ " ri = %d, wi = %d\n",
+ mbox_msg, (u32)mbox, mbox->read_index,
+ mbox->write_index);
+
+ /* Check if write buffer is full */
+ while (((mbox->write_index + 1) % MBOX_BUF_SIZE) == mbox->read_index) {
+ if (!block) {
+ dev_dbg(&(mbox->pdev->dev),
+ "Buffer full in non-blocking call! "
+ "Returning -ENOMEM!\n");
+ res = -ENOMEM;
+ goto exit;
+ }
+ spin_unlock(&mbox->lock);
+ dev_dbg(&(mbox->pdev->dev),
+ "Buffer full in blocking call! Sleeping...\n");
+ mbox->client_blocked = 1;
+ wait_for_completion(&mbox->buffer_available);
+ dev_dbg(&(mbox->pdev->dev),
+ "Blocking send was woken up! Trying again...\n");
+ spin_lock(&mbox->lock);
+ }
+
+ mbox->buffer[mbox->write_index] = mbox_msg;
+ mbox->write_index = (mbox->write_index + 1) % MBOX_BUF_SIZE;
+
+ /*
+ * Indicate that we want an IRQ as soon as there is a slot
+ * in the FIFO
+ */
+ writel(MBOX_ENABLE_IRQ, mbox->virtbase_peer + MBOX_FIFO_THRES_FREE);
+
+exit:
+ spin_unlock(&mbox->lock);
+ return res;
+}
+EXPORT_SYMBOL(mbox_send);
+
+#if defined(CONFIG_DEBUG_FS)
+/*
+ * Expected input: <value> <nbr sends>
+ * Example: "echo 0xdeadbeef 4 > mbox-node" sends 0xdeadbeef 4 times
+ */
+static ssize_t mbox_write_fifo(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ unsigned long mbox_mess;
+ unsigned long nbr_sends;
+ unsigned long i;
+ char int_buf[16];
+ char *token;
+ char *val;
+
+ struct mbox *mbox = (struct mbox *) dev->platform_data;
+
+ strncpy((char *) &int_buf, buf, sizeof(int_buf));
+ token = (char *) &int_buf;
+
+ /* Parse message */
+ val = strsep(&token, " ");
+ if ((val == NULL) || (strict_strtoul(val, 16, &mbox_mess) != 0))
+ mbox_mess = 0xDEADBEEF;
+
+ val = strsep(&token, " ");
+ if ((val == NULL) || (strict_strtoul(val, 10, &nbr_sends) != 0))
+ nbr_sends = 1;
+
+ dev_dbg(dev, "Will write 0x%lX %ld times using data struct at 0x%X\n",
+ mbox_mess, nbr_sends, (u32) mbox);
+
+ for (i = 0; i < nbr_sends; i++)
+ mbox_send(mbox, mbox_mess, true);
+
+ return count;
+}
+
+static ssize_t mbox_read_fifo(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ int mbox_value;
+ struct mbox *mbox = (struct mbox *) dev->platform_data;
+
+ if ((readl(mbox->virtbase_local + MBOX_FIFO_STATUS) & 0x7) <= 0)
+ return sprintf(buf, "Mailbox is empty\n");
+
+ mbox_value = readl(mbox->virtbase_local + MBOX_FIFO_DATA);
+ writel(MBOX_LATCH, (mbox->virtbase_local + MBOX_FIFO_REMOVE));
+
+ return sprintf(buf, "0x%X\n", mbox_value);
+}
+
+static DEVICE_ATTR(fifo, S_IWUGO | S_IRUGO, mbox_read_fifo, mbox_write_fifo);
+
+static int mbox_show(struct seq_file *s, void *data)
+{
+ struct list_head *pos;
+ u8 mbox_index = 0;
+
+ list_for_each(pos, &mboxs) {
+ struct mbox *m =
+ (struct mbox *) list_entry(pos, struct mbox, list);
+ if (m == NULL) {
+ seq_printf(s,
+ "Unable to retrieve mailbox %d\n",
+ mbox_index);
+ continue;
+ }
+
+ spin_lock(&m->lock);
+ if ((m->virtbase_peer == NULL) || (m->virtbase_local == NULL)) {
+ seq_printf(s, "MAILBOX %d not setup or corrupt\n",
+ mbox_index);
+ spin_unlock(&m->lock);
+ continue;
+ }
+
+ seq_printf(s,
+ "===========================\n"
+ " MAILBOX %d\n"
+ " PEER MAILBOX DUMP\n"
+ "---------------------------\n"
+ "FIFO: 0x%X (%d)\n"
+ "Free Threshold: 0x%.2X (%d)\n"
+ "Occupied Threshold: 0x%.2X (%d)\n"
+ "Status: 0x%.2X (%d)\n"
+ " Free spaces (ot): %d (%d)\n"
+ " Occup spaces (ot): %d (%d)\n"
+ "===========================\n"
+ " LOCAL MAILBOX DUMP\n"
+ "---------------------------\n"
+ "FIFO: 0x%.X (%d)\n"
+ "Free Threshold: 0x%.2X (%d)\n"
+ "Occupied Threshold: 0x%.2X (%d)\n"
+ "Status: 0x%.2X (%d)\n"
+ " Free spaces (ot): %d (%d)\n"
+ " Occup spaces (ot): %d (%d)\n"
+ "===========================\n"
+ "write_index: %d\n"
+ "read_index : %d\n"
+ "===========================\n"
+ "\n",
+ mbox_index,
+ readl(m->virtbase_peer + MBOX_FIFO_DATA),
+ readl(m->virtbase_peer + MBOX_FIFO_DATA),
+ readl(m->virtbase_peer + MBOX_FIFO_THRES_FREE),
+ readl(m->virtbase_peer + MBOX_FIFO_THRES_FREE),
+ readl(m->virtbase_peer + MBOX_FIFO_THRES_OCCUP),
+ readl(m->virtbase_peer + MBOX_FIFO_THRES_OCCUP),
+ readl(m->virtbase_peer + MBOX_FIFO_STATUS),
+ readl(m->virtbase_peer + MBOX_FIFO_STATUS),
+ (readl(m->virtbase_peer + MBOX_FIFO_STATUS) >> 4) & 0x7,
+ (readl(m->virtbase_peer + MBOX_FIFO_STATUS) >> 7) & 0x1,
+ (readl(m->virtbase_peer + MBOX_FIFO_STATUS) >> 0) & 0x7,
+ (readl(m->virtbase_peer + MBOX_FIFO_STATUS) >> 3) & 0x1,
+ readl(m->virtbase_local + MBOX_FIFO_DATA),
+ readl(m->virtbase_local + MBOX_FIFO_DATA),
+ readl(m->virtbase_local + MBOX_FIFO_THRES_FREE),
+ readl(m->virtbase_local + MBOX_FIFO_THRES_FREE),
+ readl(m->virtbase_local + MBOX_FIFO_THRES_OCCUP),
+ readl(m->virtbase_local + MBOX_FIFO_THRES_OCCUP),
+ readl(m->virtbase_local + MBOX_FIFO_STATUS),
+ readl(m->virtbase_local + MBOX_FIFO_STATUS),
+ (readl(m->virtbase_local + MBOX_FIFO_STATUS) >> 4) & 0x7,
+ (readl(m->virtbase_local + MBOX_FIFO_STATUS) >> 7) & 0x1,
+ (readl(m->virtbase_local + MBOX_FIFO_STATUS) >> 0) & 0x7,
+ (readl(m->virtbase_local + MBOX_FIFO_STATUS) >> 3) & 0x1,
+ m->write_index, m->read_index);
+ mbox_index++;
+ spin_unlock(&m->lock);
+ }
+
+ return 0;
+}
+
+static int mbox_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, mbox_show, NULL);
+}
+
+static const struct file_operations mbox_operations = {
+ .owner = THIS_MODULE,
+ .open = mbox_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+#endif
+
+static irqreturn_t mbox_irq(int irq, void *arg)
+{
+ u32 mbox_value;
+ int nbr_occup;
+ int nbr_free;
+ struct mbox *mbox = (struct mbox *) arg;
+
+ spin_lock(&mbox->lock);
+
+ dev_dbg(&(mbox->pdev->dev),
+ "mbox IRQ [%d] received. ri = %d, wi = %d\n",
+ irq, mbox->read_index, mbox->write_index);
+
+ /*
+ * Check if we have any outgoing messages, and if there is space for
+ * them in the FIFO.
+ */
+ if (mbox->read_index != mbox->write_index) {
+ /*
+ * Check by reading FREE for LOCAL since that indicates
+ * OCCUP for PEER
+ */
+ nbr_free = (readl(mbox->virtbase_local + MBOX_FIFO_STATUS)
+ >> 4) & 0x7;
+ dev_dbg(&(mbox->pdev->dev),
+ "Status indicates %d empty spaces in the FIFO!\n",
+ nbr_free);
+
+ while ((nbr_free > 0) &&
+ (mbox->read_index != mbox->write_index)) {
+ /* Write the message and latch it into the FIFO */
+ writel(mbox->buffer[mbox->read_index],
+ (mbox->virtbase_peer + MBOX_FIFO_DATA));
+ writel(MBOX_LATCH,
+ (mbox->virtbase_peer + MBOX_FIFO_ADD));
+ dev_dbg(&(mbox->pdev->dev),
+ "Wrote message 0x%X to addr 0x%X\n",
+ mbox->buffer[mbox->read_index],
+ (u32) (mbox->virtbase_peer + MBOX_FIFO_DATA));
+
+ nbr_free--;
+ mbox->read_index =
+ (mbox->read_index + 1) % MBOX_BUF_SIZE;
+ }
+
+ /*
+ * Check if we still want IRQ:s when there is free
+ * space to send
+ */
+ if (mbox->read_index != mbox->write_index) {
+ dev_dbg(&(mbox->pdev->dev),
+ "Still have messages to send, but FIFO full. "
+ "Request IRQ again!\n");
+ writel(MBOX_ENABLE_IRQ,
+ mbox->virtbase_peer + MBOX_FIFO_THRES_FREE);
+ } else {
+ dev_dbg(&(mbox->pdev->dev),
+ "No more messages to send. "
+ "Do not request IRQ again!\n");
+ writel(MBOX_DISABLE_IRQ,
+ mbox->virtbase_peer + MBOX_FIFO_THRES_FREE);
+ }
+
+ /*
+ * Check if we can signal any blocked clients that it is OK to
+ * start buffering again
+ */
+ if (mbox->client_blocked &&
+ (((mbox->write_index + 1) % MBOX_BUF_SIZE)
+ != mbox->read_index)) {
+ dev_dbg(&(mbox->pdev->dev),
+ "Waking up blocked client\n");
+ complete(&mbox->buffer_available);
+ mbox->client_blocked = 0;
+ }
+ }
+
+ /* Check if we have any incoming messages */
+ nbr_occup = readl(mbox->virtbase_local + MBOX_FIFO_STATUS) & 0x7;
+ if (nbr_occup == 0)
+ goto exit;
+
+ if (mbox->cb == NULL) {
+ dev_dbg(&(mbox->pdev->dev), "No receive callback registered, "
+ "leaving %d incoming messages in fifo!\n", nbr_occup);
+ goto exit;
+ }
+
+ /* Read and acknowledge the message */
+ mbox_value = readl(mbox->virtbase_local + MBOX_FIFO_DATA);
+ writel(MBOX_LATCH, (mbox->virtbase_local + MBOX_FIFO_REMOVE));
+
+ /* Notify consumer of new mailbox message */
+ dev_dbg(&(mbox->pdev->dev), "Calling callback for message 0x%X!\n",
+ mbox_value);
+ mbox->cb(mbox_value, mbox->client_data);
+
+exit:
+ dev_dbg(&(mbox->pdev->dev), "Exit mbox IRQ. ri = %d, wi = %d\n",
+ mbox->read_index, mbox->write_index);
+ spin_unlock(&mbox->lock);
+
+ return IRQ_HANDLED;
+}
+
+/* Setup is executed once for each mbox pair */
+struct mbox *mbox_setup(u8 mbox_id, mbox_recv_cb_t *mbox_cb, void *priv)
+{
+ struct resource *resource;
+ int irq;
+ int res;
+ struct mbox *mbox;
+
+ mbox = get_mbox_with_id(mbox_id);
+ if (mbox == NULL) {
+ dev_err(&(mbox->pdev->dev), "Incorrect mailbox id: %d!\n",
+ mbox_id);
+ goto exit;
+ }
+
+ /*
+ * Check if mailbox has been allocated to someone else,
+ * otherwise allocate it
+ */
+ if (mbox->allocated) {
+ dev_err(&(mbox->pdev->dev), "Mailbox number %d is busy!\n",
+ mbox_id);
+ mbox = NULL;
+ goto exit;
+ }
+ mbox->allocated = true;
+
+ dev_dbg(&(mbox->pdev->dev), "Initiating mailbox number %d: 0x%X...\n",
+ mbox_id, (u32)mbox);
+
+ mbox->client_data = priv;
+ mbox->cb = mbox_cb;
+
+ /* Get addr for peer mailbox and ioremap it */
+ resource = platform_get_resource_byname(mbox->pdev,
+ IORESOURCE_MEM,
+ "mbox_peer");
+ if (resource == NULL) {
+ dev_err(&(mbox->pdev->dev),
+ "Unable to retrieve mbox peer resource\n");
+ mbox = NULL;
+ goto exit;
+ }
+ dev_dbg(&(mbox->pdev->dev),
+ "Resource name: %s start: 0x%X, end: 0x%X\n",
+ resource->name, resource->start, resource->end);
+ mbox->virtbase_peer =
+ ioremap(resource->start, resource->end - resource->start);
+ if (!mbox->virtbase_peer) {
+ dev_err(&(mbox->pdev->dev), "Unable to ioremap peer mbox\n");
+ mbox = NULL;
+ goto exit;
+ }
+ dev_dbg(&(mbox->pdev->dev),
+ "ioremapped peer physical: (0x%X-0x%X) to virtual: 0x%X\n",
+ resource->start, resource->end, (u32) mbox->virtbase_peer);
+
+ /* Get addr for local mailbox and ioremap it */
+ resource = platform_get_resource_byname(mbox->pdev,
+ IORESOURCE_MEM,
+ "mbox_local");
+ if (resource == NULL) {
+ dev_err(&(mbox->pdev->dev),
+ "Unable to retrieve mbox local resource\n");
+ mbox = NULL;
+ goto exit;
+ }
+ dev_dbg(&(mbox->pdev->dev),
+ "Resource name: %s start: 0x%X, end: 0x%X\n",
+ resource->name, resource->start, resource->end);
+ mbox->virtbase_local =
+ ioremap(resource->start, resource->end - resource->start);
+ if (!mbox->virtbase_local) {
+ dev_err(&(mbox->pdev->dev), "Unable to ioremap local mbox\n");
+ mbox = NULL;
+ goto exit;
+ }
+ dev_dbg(&(mbox->pdev->dev),
+ "ioremapped local physical: (0x%X-0x%X) to virtual: 0x%X\n",
+ resource->start, resource->end, (u32) mbox->virtbase_peer);
+
+ init_completion(&mbox->buffer_available);
+ mbox->client_blocked = 0;
+
+ /* Get IRQ for mailbox and allocate it */
+ irq = platform_get_irq_byname(mbox->pdev, "mbox_irq");
+ if (irq < 0) {
+ dev_err(&(mbox->pdev->dev),
+ "Unable to retrieve mbox irq resource\n");
+ mbox = NULL;
+ goto exit;
+ }
+
+ dev_dbg(&(mbox->pdev->dev), "Allocating irq %d...\n", irq);
+ res = request_irq(irq, mbox_irq, 0, mbox->name, (void *) mbox);
+ if (res < 0) {
+ dev_err(&(mbox->pdev->dev),
+ "Unable to allocate mbox irq %d\n", irq);
+ mbox = NULL;
+ goto exit;
+ }
+
+ /* Set up mailbox to not launch IRQ on free space in mailbox */
+ writel(MBOX_DISABLE_IRQ, mbox->virtbase_peer + MBOX_FIFO_THRES_FREE);
+
+ /*
+ * Set up mailbox to launch IRQ on new message if we have
+ * a callback set. If not, do not raise IRQ, but keep message
+ * in FIFO for manual retrieval
+ */
+ if (mbox_cb != NULL)
+ writel(MBOX_ENABLE_IRQ,
+ mbox->virtbase_local + MBOX_FIFO_THRES_OCCUP);
+ else
+ writel(MBOX_DISABLE_IRQ,
+ mbox->virtbase_local + MBOX_FIFO_THRES_OCCUP);
+
+#if defined(CONFIG_DEBUG_FS)
+ res = device_create_file(&(mbox->pdev->dev), &dev_attr_fifo);
+ if (res != 0)
+ dev_warn(&(mbox->pdev->dev),
+ "Unable to create mbox sysfs entry");
+
+ (void) debugfs_create_file("mbox", S_IFREG | S_IRUGO, NULL,
+ NULL, &mbox_operations);
+#endif
+
+ dev_info(&(mbox->pdev->dev),
+ "Mailbox driver with index %d initated!\n", mbox_id);
+
+exit:
+ return mbox;
+}
+EXPORT_SYMBOL(mbox_setup);
+
+
+int __init mbox_probe(struct platform_device *pdev)
+{
+ struct mbox local_mbox;
+ struct mbox *mbox;
+ int res = 0;
+ dev_dbg(&(pdev->dev), "Probing mailbox (pdev = 0x%X)...\n", (u32) pdev);
+
+ memset(&local_mbox, 0x0, sizeof(struct mbox));
+
+ /* Associate our mbox data with the platform device */
+ res = platform_device_add_data(pdev,
+ (void *) &local_mbox,
+ sizeof(struct mbox));
+ if (res != 0) {
+ dev_err(&(pdev->dev),
+ "Unable to allocate driver platform data!\n");
+ goto exit;
+ }
+
+ mbox = (struct mbox *) pdev->dev.platform_data;
+ mbox->pdev = pdev;
+ mbox->write_index = 0;
+ mbox->read_index = 0;
+
+ INIT_LIST_HEAD(&(mbox->list));
+ list_add_tail(&(mbox->list), &mboxs);
+
+ sprintf(mbox->name, "%s", MBOX_NAME);
+ spin_lock_init(&mbox->lock);
+
+ dev_info(&(pdev->dev), "Mailbox driver loaded\n");
+
+exit:
+ return res;
+}
+
+static struct platform_driver mbox_driver = {
+ .driver = {
+ .name = MBOX_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init mbox_init(void)
+{
+ return platform_driver_probe(&mbox_driver, mbox_probe);
+}
+
+module_init(mbox_init);
+
+void __exit mbox_exit(void)
+{
+ platform_driver_unregister(&mbox_driver);
+}
+
+module_exit(mbox_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("MBOX driver");
diff --git a/arch/arm/mach-ux500/modem_irq.c b/arch/arm/mach-ux500/modem_irq.c
new file mode 100644
index 000000000000..3187f8871169
--- /dev/null
+++ b/arch/arm/mach-ux500/modem_irq.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Stefan Nilsson <stefan.xk.nilsson@stericsson.com> for ST-Ericsson.
+ * Author: Martin Persson <martin.persson@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+#define MODEM_INTCON_BASE_ADDR 0xBFFD3000
+#define MODEM_INTCON_SIZE 0xFFF
+
+#define DEST_IRQ41_OFFSET 0x2A4
+#define DEST_IRQ43_OFFSET 0x2AC
+#define DEST_IRQ45_OFFSET 0x2B4
+
+#define PRIO_IRQ41_OFFSET 0x6A4
+#define PRIO_IRQ43_OFFSET 0x6AC
+#define PRIO_IRQ45_OFFSET 0x6B4
+
+#define ALLOW_IRQ_OFFSET 0x104
+
+#define MODEM_INTCON_CPU_NBR 0x1
+#define MODEM_INTCON_PRIO_HIGH 0x0
+
+#define MODEM_INTCON_ALLOW_IRQ41 0x0200
+#define MODEM_INTCON_ALLOW_IRQ43 0x0800
+#define MODEM_INTCON_ALLOW_IRQ45 0x2000
+
+#define MODEM_IRQ_REG_OFFSET 0x4
+
+struct modem_irq {
+ void __iomem *modem_intcon_base;
+};
+
+
+static void setup_modem_intcon(void __iomem *modem_intcon_base)
+{
+ /* IC_DESTINATION_BASE_ARRAY - Which CPU to receive the IRQ */
+ writel(MODEM_INTCON_CPU_NBR, modem_intcon_base + DEST_IRQ41_OFFSET);
+ writel(MODEM_INTCON_CPU_NBR, modem_intcon_base + DEST_IRQ43_OFFSET);
+ writel(MODEM_INTCON_CPU_NBR, modem_intcon_base + DEST_IRQ45_OFFSET);
+
+ /* IC_PRIORITY_BASE_ARRAY - IRQ priority in modem IRQ controller */
+ writel(MODEM_INTCON_PRIO_HIGH, modem_intcon_base + PRIO_IRQ41_OFFSET);
+ writel(MODEM_INTCON_PRIO_HIGH, modem_intcon_base + PRIO_IRQ43_OFFSET);
+ writel(MODEM_INTCON_PRIO_HIGH, modem_intcon_base + PRIO_IRQ45_OFFSET);
+
+ /* IC_ALLOW_ARRAY - IRQ enable */
+ writel(MODEM_INTCON_ALLOW_IRQ41 |
+ MODEM_INTCON_ALLOW_IRQ43 |
+ MODEM_INTCON_ALLOW_IRQ45,
+ modem_intcon_base + ALLOW_IRQ_OFFSET);
+}
+
+static irqreturn_t modem_cpu_irq_handler(int irq, void *data)
+{
+ int real_irq;
+ int virt_irq;
+ struct modem_irq *mi = (struct modem_irq *)data;
+
+ /* Read modem side IRQ number from modem IRQ controller */
+ real_irq = readl(mi->modem_intcon_base + MODEM_IRQ_REG_OFFSET) & 0xFF;
+ virt_irq = IRQ_MODEM_EVENTS_BASE + real_irq;
+
+ pr_debug("modem_irq: Worker read addr 0x%X and got value 0x%X "
+ "which will be 0x%X (%d) which translates to "
+ "virtual IRQ 0x%X (%d)!\n",
+ (u32)mi->modem_intcon_base + MODEM_IRQ_REG_OFFSET,
+ real_irq,
+ real_irq & 0xFF,
+ real_irq & 0xFF,
+ virt_irq,
+ virt_irq);
+
+ if (virt_irq != 0)
+ generic_handle_irq(virt_irq);
+
+ pr_debug("modem_irq: Done handling virtual IRQ %d!\n", virt_irq);
+
+ return IRQ_HANDLED;
+}
+
+static void create_virtual_irq(int irq, struct irq_chip *modem_irq_chip)
+{
+ set_irq_chip(irq, modem_irq_chip);
+ set_irq_handler(irq, handle_simple_irq);
+ set_irq_flags(irq, IRQF_VALID);
+
+ pr_debug("modem_irq: Created virtual IRQ %d\n", irq);
+}
+
+static int modem_irq_init(void)
+{
+ int err;
+ static struct irq_chip modem_irq_chip;
+ struct modem_irq *mi;
+
+ pr_info("modem_irq: Set up IRQ handler for incoming modem IRQ %d\n",
+ IRQ_DB5500_MODEM);
+
+ mi = kmalloc(sizeof(struct modem_irq), GFP_KERNEL);
+ if (!mi) {
+ pr_err("modem_irq: Could not allocate device\n");
+ return -ENOMEM;
+ }
+
+ mi->modem_intcon_base =
+ ioremap(MODEM_INTCON_BASE_ADDR, MODEM_INTCON_SIZE);
+ pr_debug("modem_irq: ioremapped modem_intcon_base from "
+ "phy 0x%x to virt 0x%x\n", MODEM_INTCON_BASE_ADDR,
+ (u32)mi->modem_intcon_base);
+
+ setup_modem_intcon(mi->modem_intcon_base);
+
+ modem_irq_chip = dummy_irq_chip;
+ modem_irq_chip.name = "modem_irq";
+
+ /* Create the virtual IRQ:s needed */
+ create_virtual_irq(MBOX_PAIR0_VIRT_IRQ, &modem_irq_chip);
+ create_virtual_irq(MBOX_PAIR1_VIRT_IRQ, &modem_irq_chip);
+ create_virtual_irq(MBOX_PAIR2_VIRT_IRQ, &modem_irq_chip);
+
+ err = request_threaded_irq(IRQ_DB5500_MODEM, NULL,
+ modem_cpu_irq_handler, IRQF_ONESHOT,
+ "modem_irq", mi);
+ if (err)
+ pr_err("modem_irq: Could not register IRQ %d\n",
+ IRQ_DB5500_MODEM);
+
+ return 0;
+}
+
+arch_initcall(modem_irq_init);
diff --git a/arch/arm/mach-ux500/pins-db5500.h b/arch/arm/mach-ux500/pins-db5500.h
new file mode 100644
index 000000000000..bf50c21fe69d
--- /dev/null
+++ b/arch/arm/mach-ux500/pins-db5500.h
@@ -0,0 +1,620 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License terms: GNU General Public License, version 2
+ * Author: Rabin Vincent <rabin.vincent@stericsson.com>
+ */
+
+#ifndef __MACH_DB5500_PINS_H
+#define __MACH_DB5500_PINS_H
+
+#define GPIO0_GPIO PIN_CFG(0, GPIO)
+#define GPIO0_SM_CS3n PIN_CFG(0, ALT_A)
+
+#define GPIO1_GPIO PIN_CFG(1, GPIO)
+#define GPIO1_SM_A3 PIN_CFG(1, ALT_A)
+
+#define GPIO2_GPIO PIN_CFG(2, GPIO)
+#define GPIO2_SM_A4 PIN_CFG(2, ALT_A)
+#define GPIO2_SM_AVD PIN_CFG(2, ALT_B)
+
+#define GPIO3_GPIO PIN_CFG(3, GPIO)
+#define GPIO3_I2C1_SCL PIN_CFG(3, ALT_A)
+
+#define GPIO4_GPIO PIN_CFG(4, GPIO)
+#define GPIO4_I2C1_SDA PIN_CFG(4, ALT_A)
+
+#define GPIO5_GPIO PIN_CFG(5, GPIO)
+#define GPIO5_MC0_DAT0 PIN_CFG(5, ALT_A)
+#define GPIO5_SM_ADQ8 PIN_CFG(5, ALT_B)
+
+#define GPIO6_GPIO PIN_CFG(6, GPIO)
+#define GPIO6_MC0_DAT1 PIN_CFG(6, ALT_A)
+#define GPIO6_SM_ADQ0 PIN_CFG(6, ALT_B)
+
+#define GPIO7_GPIO PIN_CFG(7, GPIO)
+#define GPIO7_MC0_DAT2 PIN_CFG(7, ALT_A)
+#define GPIO7_SM_ADQ9 PIN_CFG(7, ALT_B)
+
+#define GPIO8_GPIO PIN_CFG(8, GPIO)
+#define GPIO8_MC0_DAT3 PIN_CFG(8, ALT_A)
+#define GPIO8_SM_ADQ1 PIN_CFG(8, ALT_B)
+
+#define GPIO9_GPIO PIN_CFG(9, GPIO)
+#define GPIO9_MC0_DAT4 PIN_CFG(9, ALT_A)
+#define GPIO9_SM_ADQ10 PIN_CFG(9, ALT_B)
+
+#define GPIO10_GPIO PIN_CFG(10, GPIO)
+#define GPIO10_MC0_DAT5 PIN_CFG(10, ALT_A)
+#define GPIO10_SM_ADQ2 PIN_CFG(10, ALT_B)
+
+#define GPIO11_GPIO PIN_CFG(11, GPIO)
+#define GPIO11_MC0_DAT6 PIN_CFG(11, ALT_A)
+#define GPIO11_SM_ADQ11 PIN_CFG(11, ALT_B)
+
+#define GPIO12_GPIO PIN_CFG(12, GPIO)
+#define GPIO12_MC0_DAT7 PIN_CFG(12, ALT_A)
+#define GPIO12_SM_ADQ3 PIN_CFG(12, ALT_B)
+
+#define GPIO13_GPIO PIN_CFG(13, GPIO)
+#define GPIO13_MC0_CMD PIN_CFG(13, ALT_A)
+#define GPIO13_SM_BUSY0n PIN_CFG(13, ALT_B)
+#define GPIO13_SM_WAIT0n PIN_CFG(13, ALT_C)
+
+#define GPIO14_GPIO PIN_CFG(14, GPIO)
+#define GPIO14_MC0_CLK PIN_CFG(14, ALT_A)
+#define GPIO14_SM_CS1n PIN_CFG(14, ALT_B)
+#define GPIO14_SM_CKO PIN_CFG(14, ALT_C)
+
+#define GPIO15_GPIO PIN_CFG(15, GPIO)
+#define GPIO15_SM_A5 PIN_CFG(15, ALT_A)
+#define GPIO15_SM_CLE PIN_CFG(15, ALT_B)
+
+#define GPIO16_GPIO PIN_CFG(16, GPIO)
+#define GPIO16_MC2_CMD PIN_CFG(16, ALT_A)
+#define GPIO16_SM_OEn PIN_CFG(16, ALT_B)
+
+#define GPIO17_GPIO PIN_CFG(17, GPIO)
+#define GPIO17_MC2_CLK PIN_CFG(17, ALT_A)
+#define GPIO17_SM_WEn PIN_CFG(17, ALT_B)
+
+#define GPIO18_GPIO PIN_CFG(18, GPIO)
+#define GPIO18_SM_A6 PIN_CFG(18, ALT_A)
+#define GPIO18_SM_ALE PIN_CFG(18, ALT_B)
+#define GPIO18_SM_AVDn PIN_CFG(18, ALT_C)
+
+#define GPIO19_GPIO PIN_CFG(19, GPIO)
+#define GPIO19_MC2_DAT1 PIN_CFG(19, ALT_A)
+#define GPIO19_SM_ADQ4 PIN_CFG(19, ALT_B)
+
+#define GPIO20_GPIO PIN_CFG(20, GPIO)
+#define GPIO20_MC2_DAT3 PIN_CFG(20, ALT_A)
+#define GPIO20_SM_ADQ5 PIN_CFG(20, ALT_B)
+
+#define GPIO21_GPIO PIN_CFG(21, GPIO)
+#define GPIO21_MC2_DAT5 PIN_CFG(21, ALT_A)
+#define GPIO21_SM_ADQ6 PIN_CFG(21, ALT_B)
+
+#define GPIO22_GPIO PIN_CFG(22, GPIO)
+#define GPIO22_MC2_DAT7 PIN_CFG(22, ALT_A)
+#define GPIO22_SM_ADQ7 PIN_CFG(22, ALT_B)
+
+#define GPIO23_GPIO PIN_CFG(23, GPIO)
+#define GPIO23_MC2_DAT0 PIN_CFG(23, ALT_A)
+#define GPIO23_SM_ADQ12 PIN_CFG(23, ALT_B)
+#define GPIO23_MC0_DAT1 PIN_CFG(23, ALT_C)
+
+#define GPIO24_GPIO PIN_CFG(24, GPIO)
+#define GPIO24_MC2_DAT2 PIN_CFG(24, ALT_A)
+#define GPIO24_SM_ADQ13 PIN_CFG(24, ALT_B)
+#define GPIO24_MC0_DAT3 PIN_CFG(24, ALT_C)
+
+#define GPIO25_GPIO PIN_CFG(25, GPIO)
+#define GPIO25_MC2_DAT4 PIN_CFG(25, ALT_A)
+#define GPIO25_SM_ADQ14 PIN_CFG(25, ALT_B)
+#define GPIO25_MC0_CMD PIN_CFG(25, ALT_C)
+
+#define GPIO26_GPIO PIN_CFG(26, GPIO)
+#define GPIO26_MC2_DAT6 PIN_CFG(26, ALT_A)
+#define GPIO26_SM_ADQ15 PIN_CFG(26, ALT_B)
+
+#define GPIO27_GPIO PIN_CFG(27, GPIO)
+#define GPIO27_SM_CS0n PIN_CFG(27, ALT_A)
+#define GPIO27_SM_PS0n PIN_CFG(27, ALT_B)
+
+#define GPIO28_GPIO PIN_CFG(28, GPIO)
+#define GPIO28_U0_TXD PIN_CFG(28, ALT_A)
+#define GPIO28_SM_A0 PIN_CFG(28, ALT_B)
+
+#define GPIO29_GPIO PIN_CFG(29, GPIO)
+#define GPIO29_U0_RXD PIN_CFG(29, ALT_A)
+#define GPIO29_SM_A1 PIN_CFG(29, ALT_B)
+#define GPIO29_PWM_0 PIN_CFG(29, ALT_C)
+
+#define GPIO30_GPIO PIN_CFG(30, GPIO)
+#define GPIO30_MC0_DAT5 PIN_CFG(30, ALT_A)
+#define GPIO30_SM_A2 PIN_CFG(30, ALT_B)
+#define GPIO30_PWM_1 PIN_CFG(30, ALT_C)
+
+#define GPIO31_GPIO PIN_CFG(31, GPIO)
+#define GPIO31_MC0_DAT7 PIN_CFG(31, ALT_A)
+#define GPIO31_SM_CS2n PIN_CFG(31, ALT_B)
+#define GPIO31_PWM_2 PIN_CFG(31, ALT_C)
+
+#define GPIO32_GPIO PIN_CFG(32, GPIO)
+#define GPIO32_MSP0_TCK PIN_CFG(32, ALT_A)
+#define GPIO32_ACCI2S0_SCK PIN_CFG(32, ALT_B)
+
+#define GPIO33_GPIO PIN_CFG(33, GPIO)
+#define GPIO33_MSP0_TFS PIN_CFG(33, ALT_A)
+#define GPIO33_ACCI2S0_WS PIN_CFG(33, ALT_B)
+
+#define GPIO34_GPIO PIN_CFG(34, GPIO)
+#define GPIO34_MSP0_TXD PIN_CFG(34, ALT_A)
+#define GPIO34_ACCI2S0_DLD PIN_CFG(34, ALT_B)
+
+#define GPIO35_GPIO PIN_CFG(35, GPIO)
+#define GPIO35_MSP0_RXD PIN_CFG(35, ALT_A)
+#define GPIO35_ACCI2S0_ULD PIN_CFG(35, ALT_B)
+
+#define GPIO64_GPIO PIN_CFG(64, GPIO)
+#define GPIO64_USB_DAT0 PIN_CFG(64, ALT_A)
+#define GPIO64_U0_TXD PIN_CFG(64, ALT_B)
+
+#define GPIO65_GPIO PIN_CFG(65, GPIO)
+#define GPIO65_USB_DAT1 PIN_CFG(65, ALT_A)
+#define GPIO65_U0_RXD PIN_CFG(65, ALT_B)
+
+#define GPIO66_GPIO PIN_CFG(66, GPIO)
+#define GPIO66_USB_DAT2 PIN_CFG(66, ALT_A)
+
+#define GPIO67_GPIO PIN_CFG(67, GPIO)
+#define GPIO67_USB_DAT3 PIN_CFG(67, ALT_A)
+
+#define GPIO68_GPIO PIN_CFG(68, GPIO)
+#define GPIO68_USB_DAT4 PIN_CFG(68, ALT_A)
+
+#define GPIO69_GPIO PIN_CFG(69, GPIO)
+#define GPIO69_USB_DAT5 PIN_CFG(69, ALT_A)
+
+#define GPIO70_GPIO PIN_CFG(70, GPIO)
+#define GPIO70_USB_DAT6 PIN_CFG(70, ALT_A)
+
+#define GPIO71_GPIO PIN_CFG(71, GPIO)
+#define GPIO71_USB_DAT7 PIN_CFG(71, ALT_A)
+
+#define GPIO72_GPIO PIN_CFG(72, GPIO)
+#define GPIO72_USB_STP PIN_CFG(72, ALT_A)
+
+#define GPIO73_GPIO PIN_CFG(73, GPIO)
+#define GPIO73_USB_DIR PIN_CFG(73, ALT_A)
+
+#define GPIO74_GPIO PIN_CFG(74, GPIO)
+#define GPIO74_USB_NXT PIN_CFG(74, ALT_A)
+
+#define GPIO75_GPIO PIN_CFG(75, GPIO)
+#define GPIO75_USB_XCLK PIN_CFG(75, ALT_A)
+
+#define GPIO76_GPIO PIN_CFG(76, GPIO)
+
+#define GPIO77_GPIO PIN_CFG(77, GPIO)
+#define GPIO77_ACCTX_ON PIN_CFG(77, ALT_A)
+
+#define GPIO78_GPIO PIN_CFG(78, GPIO)
+#define GPIO78_IRQn PIN_CFG(78, ALT_A)
+
+#define GPIO79_GPIO PIN_CFG(79, GPIO)
+#define GPIO79_ACCSIM_Clk PIN_CFG(79, ALT_A)
+
+#define GPIO80_GPIO PIN_CFG(80, GPIO)
+#define GPIO80_ACCSIM_Da PIN_CFG(80, ALT_A)
+
+#define GPIO81_GPIO PIN_CFG(81, GPIO)
+#define GPIO81_ACCSIM_Reset PIN_CFG(81, ALT_A)
+
+#define GPIO82_GPIO PIN_CFG(82, GPIO)
+#define GPIO82_ACCSIM_DDir PIN_CFG(82, ALT_A)
+
+#define GPIO96_GPIO PIN_CFG(96, GPIO)
+#define GPIO96_MSP1_TCK PIN_CFG(96, ALT_A)
+#define GPIO96_PRCMU_DEBUG3 PIN_CFG(96, ALT_B)
+#define GPIO96_PRCMU_DEBUG7 PIN_CFG(96, ALT_C)
+
+#define GPIO97_GPIO PIN_CFG(97, GPIO)
+#define GPIO97_MSP1_TFS PIN_CFG(97, ALT_A)
+#define GPIO97_PRCMU_DEBUG2 PIN_CFG(97, ALT_B)
+#define GPIO97_PRCMU_DEBUG6 PIN_CFG(97, ALT_C)
+
+#define GPIO98_GPIO PIN_CFG(98, GPIO)
+#define GPIO98_MSP1_TXD PIN_CFG(98, ALT_A)
+#define GPIO98_PRCMU_DEBUG1 PIN_CFG(98, ALT_B)
+#define GPIO98_PRCMU_DEBUG5 PIN_CFG(98, ALT_C)
+
+#define GPIO99_GPIO PIN_CFG(99, GPIO)
+#define GPIO99_MSP1_RXD PIN_CFG(99, ALT_A)
+#define GPIO99_PRCMU_DEBUG0 PIN_CFG(99, ALT_B)
+#define GPIO99_PRCMU_DEBUG4 PIN_CFG(99, ALT_C)
+
+#define GPIO100_GPIO PIN_CFG(100, GPIO)
+#define GPIO100_I2C0_SCL PIN_CFG(100, ALT_A)
+
+#define GPIO101_GPIO PIN_CFG(101, GPIO)
+#define GPIO101_I2C0_SDA PIN_CFG(101, ALT_A)
+
+#define GPIO128_GPIO PIN_CFG(128, GPIO)
+#define GPIO128_KP_I0 PIN_CFG(128, ALT_A)
+#define GPIO128_BUSMON_D0 PIN_CFG(128, ALT_B)
+
+#define GPIO129_GPIO PIN_CFG(129, GPIO)
+#define GPIO129_KP_O0 PIN_CFG(129, ALT_A)
+#define GPIO129_BUSMON_D1 PIN_CFG(129, ALT_B)
+
+#define GPIO130_GPIO PIN_CFG(130, GPIO)
+#define GPIO130_KP_I1 PIN_CFG(130, ALT_A)
+#define GPIO130_BUSMON_D2 PIN_CFG(130, ALT_B)
+
+#define GPIO131_GPIO PIN_CFG(131, GPIO)
+#define GPIO131_KP_O1 PIN_CFG(131, ALT_A)
+#define GPIO131_BUSMON_D3 PIN_CFG(131, ALT_B)
+
+#define GPIO132_GPIO PIN_CFG(132, GPIO)
+#define GPIO132_KP_I2 PIN_CFG(132, ALT_A)
+#define GPIO132_ETM_D15 PIN_CFG(132, ALT_B)
+#define GPIO132_STMAPE_CLK PIN_CFG(132, ALT_C)
+
+#define GPIO133_GPIO PIN_CFG(133, GPIO)
+#define GPIO133_KP_O2 PIN_CFG(133, ALT_A)
+#define GPIO133_ETM_D14 PIN_CFG(133, ALT_B)
+#define GPIO133_U0_RXD PIN_CFG(133, ALT_C)
+
+#define GPIO134_GPIO PIN_CFG(134, GPIO)
+#define GPIO134_KP_I3 PIN_CFG(134, ALT_A)
+#define GPIO134_ETM_D13 PIN_CFG(134, ALT_B)
+#define GPIO134_STMAPE_DAT0 PIN_CFG(134, ALT_C)
+
+#define GPIO135_GPIO PIN_CFG(135, GPIO)
+#define GPIO135_KP_O3 PIN_CFG(135, ALT_A)
+#define GPIO135_ETM_D12 PIN_CFG(135, ALT_B)
+#define GPIO135_STMAPE_DAT1 PIN_CFG(135, ALT_C)
+
+#define GPIO136_GPIO PIN_CFG(136, GPIO)
+#define GPIO136_KP_I4 PIN_CFG(136, ALT_A)
+#define GPIO136_ETM_D11 PIN_CFG(136, ALT_B)
+#define GPIO136_STMAPE_DAT2 PIN_CFG(136, ALT_C)
+
+#define GPIO137_GPIO PIN_CFG(137, GPIO)
+#define GPIO137_KP_O4 PIN_CFG(137, ALT_A)
+#define GPIO137_ETM_D10 PIN_CFG(137, ALT_B)
+#define GPIO137_STMAPE_DAT3 PIN_CFG(137, ALT_C)
+
+#define GPIO138_GPIO PIN_CFG(138, GPIO)
+#define GPIO138_KP_I5 PIN_CFG(138, ALT_A)
+#define GPIO138_ETM_D9 PIN_CFG(138, ALT_B)
+#define GPIO138_U0_TXD PIN_CFG(138, ALT_C)
+
+#define GPIO139_GPIO PIN_CFG(139, GPIO)
+#define GPIO139_KP_O5 PIN_CFG(139, ALT_A)
+#define GPIO139_ETM_D8 PIN_CFG(139, ALT_B)
+#define GPIO139_BUSMON_D11 PIN_CFG(139, ALT_C)
+
+#define GPIO140_GPIO PIN_CFG(140, GPIO)
+#define GPIO140_KP_I6 PIN_CFG(140, ALT_A)
+#define GPIO140_ETM_D7 PIN_CFG(140, ALT_B)
+#define GPIO140_STMAPE_CLK PIN_CFG(140, ALT_C)
+
+#define GPIO141_GPIO PIN_CFG(141, GPIO)
+#define GPIO141_KP_O6 PIN_CFG(141, ALT_A)
+#define GPIO141_ETM_D6 PIN_CFG(141, ALT_B)
+#define GPIO141_U0_RXD PIN_CFG(141, ALT_C)
+
+#define GPIO142_GPIO PIN_CFG(142, GPIO)
+#define GPIO142_KP_I7 PIN_CFG(142, ALT_A)
+#define GPIO142_ETM_D5 PIN_CFG(142, ALT_B)
+#define GPIO142_STMAPE_DAT0 PIN_CFG(142, ALT_C)
+
+#define GPIO143_GPIO PIN_CFG(143, GPIO)
+#define GPIO143_KP_O7 PIN_CFG(143, ALT_A)
+#define GPIO143_ETM_D4 PIN_CFG(143, ALT_B)
+#define GPIO143_STMAPE_DAT1 PIN_CFG(143, ALT_C)
+
+#define GPIO144_GPIO PIN_CFG(144, GPIO)
+#define GPIO144_I2C3_SCL PIN_CFG(144, ALT_A)
+#define GPIO144_ETM_D3 PIN_CFG(144, ALT_B)
+#define GPIO144_STMAPE_DAT2 PIN_CFG(144, ALT_C)
+
+#define GPIO145_GPIO PIN_CFG(145, GPIO)
+#define GPIO145_I2C3_SDA PIN_CFG(145, ALT_A)
+#define GPIO145_ETM_D2 PIN_CFG(145, ALT_B)
+#define GPIO145_STMAPE_DAT3 PIN_CFG(145, ALT_C)
+
+#define GPIO146_GPIO PIN_CFG(146, GPIO)
+#define GPIO146_PWM_0 PIN_CFG(146, ALT_A)
+#define GPIO146_ETM_D1 PIN_CFG(146, ALT_B)
+
+#define GPIO147_GPIO PIN_CFG(147, GPIO)
+#define GPIO147_PWM_1 PIN_CFG(147, ALT_A)
+#define GPIO147_ETM_D0 PIN_CFG(147, ALT_B)
+
+#define GPIO148_GPIO PIN_CFG(148, GPIO)
+#define GPIO148_PWM_2 PIN_CFG(148, ALT_A)
+#define GPIO148_ETM_CLK PIN_CFG(148, ALT_B)
+
+#define GPIO160_GPIO PIN_CFG(160, GPIO)
+#define GPIO160_CLKOUT_REQn PIN_CFG(160, ALT_A)
+
+#define GPIO161_GPIO PIN_CFG(161, GPIO)
+#define GPIO161_CLKOUT_0 PIN_CFG(161, ALT_A)
+
+#define GPIO162_GPIO PIN_CFG(162, GPIO)
+#define GPIO162_CLKOUT_1 PIN_CFG(162, ALT_A)
+
+#define GPIO163_GPIO PIN_CFG(163, GPIO)
+
+#define GPIO164_GPIO PIN_CFG(164, GPIO)
+#define GPIO164_GPS_START PIN_CFG(164, ALT_A)
+
+#define GPIO165_GPIO PIN_CFG(165, GPIO)
+#define GPIO165_SPI1_CS2n PIN_CFG(165, ALT_A)
+#define GPIO165_U3_RXD PIN_CFG(165, ALT_B)
+#define GPIO165_BUSMON_D20 PIN_CFG(165, ALT_C)
+
+#define GPIO166_GPIO PIN_CFG(166, GPIO)
+#define GPIO166_SPI1_CS1n PIN_CFG(166, ALT_A)
+#define GPIO166_U3_TXD PIN_CFG(166, ALT_B)
+#define GPIO166_BUSMON_D21 PIN_CFG(166, ALT_C)
+
+#define GPIO167_GPIO PIN_CFG(167, GPIO)
+#define GPIO167_SPI1_CS0n PIN_CFG(167, ALT_A)
+#define GPIO167_U3_RTSn PIN_CFG(167, ALT_B)
+#define GPIO167_BUSMON_D22 PIN_CFG(167, ALT_C)
+
+#define GPIO168_GPIO PIN_CFG(168, GPIO)
+#define GPIO168_SPI1_RXD PIN_CFG(168, ALT_A)
+#define GPIO168_U3_CTSn PIN_CFG(168, ALT_B)
+#define GPIO168_BUSMON_D23 PIN_CFG(168, ALT_C)
+
+#define GPIO169_GPIO PIN_CFG(169, GPIO)
+#define GPIO169_SPI1_TXD PIN_CFG(169, ALT_A)
+#define GPIO169_DDR_RC PIN_CFG(169, ALT_B)
+#define GPIO169_BUSMON_D24 PIN_CFG(169, ALT_C)
+
+#define GPIO170_GPIO PIN_CFG(170, GPIO)
+#define GPIO170_SPI1_CLK PIN_CFG(170, ALT_A)
+
+#define GPIO171_GPIO PIN_CFG(171, GPIO)
+#define GPIO171_MC3_DAT0 PIN_CFG(171, ALT_A)
+#define GPIO171_SPI3_RXD PIN_CFG(171, ALT_B)
+#define GPIO171_BUSMON_D25 PIN_CFG(171, ALT_C)
+
+#define GPIO172_GPIO PIN_CFG(172, GPIO)
+#define GPIO172_MC3_DAT1 PIN_CFG(172, ALT_A)
+#define GPIO172_SPI3_CS1n PIN_CFG(172, ALT_B)
+#define GPIO172_BUSMON_D26 PIN_CFG(172, ALT_C)
+
+#define GPIO173_GPIO PIN_CFG(173, GPIO)
+#define GPIO173_MC3_DAT2 PIN_CFG(173, ALT_A)
+#define GPIO173_SPI3_CS2n PIN_CFG(173, ALT_B)
+#define GPIO173_BUSMON_D27 PIN_CFG(173, ALT_C)
+
+#define GPIO174_GPIO PIN_CFG(174, GPIO)
+#define GPIO174_MC3_DAT3 PIN_CFG(174, ALT_A)
+#define GPIO174_SPI3_CS0n PIN_CFG(174, ALT_B)
+#define GPIO174_BUSMON_D28 PIN_CFG(174, ALT_C)
+
+#define GPIO175_GPIO PIN_CFG(175, GPIO)
+#define GPIO175_MC3_CMD PIN_CFG(175, ALT_A)
+#define GPIO175_SPI3_TXD PIN_CFG(175, ALT_B)
+#define GPIO175_BUSMON_D29 PIN_CFG(175, ALT_C)
+
+#define GPIO176_GPIO PIN_CFG(176, GPIO)
+#define GPIO176_MC3_CLK PIN_CFG(176, ALT_A)
+#define GPIO176_SPI3_CLK PIN_CFG(176, ALT_B)
+
+#define GPIO177_GPIO PIN_CFG(177, GPIO)
+#define GPIO177_U2_RXD PIN_CFG(177, ALT_A)
+#define GPIO177_I2C3_SCL PIN_CFG(177, ALT_B)
+#define GPIO177_BUSMON_D30 PIN_CFG(177, ALT_C)
+
+#define GPIO178_GPIO PIN_CFG(178, GPIO)
+#define GPIO178_U2_TXD PIN_CFG(178, ALT_A)
+#define GPIO178_I2C3_SDA PIN_CFG(178, ALT_B)
+#define GPIO178_BUSMON_D31 PIN_CFG(178, ALT_C)
+
+#define GPIO179_GPIO PIN_CFG(179, GPIO)
+#define GPIO179_U2_CTSn PIN_CFG(179, ALT_A)
+#define GPIO179_U3_RXD PIN_CFG(179, ALT_B)
+#define GPIO179_BUSMON_D32 PIN_CFG(179, ALT_C)
+
+#define GPIO180_GPIO PIN_CFG(180, GPIO)
+#define GPIO180_U2_RTSn PIN_CFG(180, ALT_A)
+#define GPIO180_U3_TXD PIN_CFG(180, ALT_B)
+#define GPIO180_BUSMON_D33 PIN_CFG(180, ALT_C)
+
+#define GPIO185_GPIO PIN_CFG(185, GPIO)
+#define GPIO185_SPI3_CS2n PIN_CFG(185, ALT_A)
+#define GPIO185_MC4_DAT0 PIN_CFG(185, ALT_B)
+
+#define GPIO186_GPIO PIN_CFG(186, GPIO)
+#define GPIO186_SPI3_CS1n PIN_CFG(186, ALT_A)
+#define GPIO186_MC4_DAT1 PIN_CFG(186, ALT_B)
+
+#define GPIO187_GPIO PIN_CFG(187, GPIO)
+#define GPIO187_SPI3_CS0n PIN_CFG(187, ALT_A)
+#define GPIO187_MC4_DAT2 PIN_CFG(187, ALT_B)
+
+#define GPIO188_GPIO PIN_CFG(188, GPIO)
+#define GPIO188_SPI3_RXD PIN_CFG(188, ALT_A)
+#define GPIO188_MC4_DAT3 PIN_CFG(188, ALT_B)
+
+#define GPIO189_GPIO PIN_CFG(189, GPIO)
+#define GPIO189_SPI3_TXD PIN_CFG(189, ALT_A)
+#define GPIO189_MC4_CMD PIN_CFG(189, ALT_B)
+
+#define GPIO190_GPIO PIN_CFG(190, GPIO)
+#define GPIO190_SPI3_CLK PIN_CFG(190, ALT_A)
+#define GPIO190_MC4_CLK PIN_CFG(190, ALT_B)
+
+#define GPIO191_GPIO PIN_CFG(191, GPIO)
+#define GPIO191_MC1_DAT0 PIN_CFG(191, ALT_A)
+#define GPIO191_MC4_DAT4 PIN_CFG(191, ALT_B)
+#define GPIO191_STMAPE_DAT0 PIN_CFG(191, ALT_C)
+
+#define GPIO192_GPIO PIN_CFG(192, GPIO)
+#define GPIO192_MC1_DAT1 PIN_CFG(192, ALT_A)
+#define GPIO192_MC4_DAT5 PIN_CFG(192, ALT_B)
+#define GPIO192_STMAPE_DAT1 PIN_CFG(192, ALT_C)
+
+#define GPIO193_GPIO PIN_CFG(193, GPIO)
+#define GPIO193_MC1_DAT2 PIN_CFG(193, ALT_A)
+#define GPIO193_MC4_DAT6 PIN_CFG(193, ALT_B)
+#define GPIO193_STMAPE_DAT2 PIN_CFG(193, ALT_C)
+
+#define GPIO194_GPIO PIN_CFG(194, GPIO)
+#define GPIO194_MC1_DAT3 PIN_CFG(194, ALT_A)
+#define GPIO194_MC4_DAT7 PIN_CFG(194, ALT_B)
+#define GPIO194_STMAPE_DAT3 PIN_CFG(194, ALT_C)
+
+#define GPIO195_GPIO PIN_CFG(195, GPIO)
+#define GPIO195_MC1_CLK PIN_CFG(195, ALT_A)
+#define GPIO195_STMAPE_CLK PIN_CFG(195, ALT_B)
+#define GPIO195_BUSMON_CLK PIN_CFG(195, ALT_C)
+
+#define GPIO196_GPIO PIN_CFG(196, GPIO)
+#define GPIO196_MC1_CMD PIN_CFG(196, ALT_A)
+#define GPIO196_U0_RXD PIN_CFG(196, ALT_B)
+#define GPIO196_BUSMON_D38 PIN_CFG(196, ALT_C)
+
+#define GPIO197_GPIO PIN_CFG(197, GPIO)
+#define GPIO197_MC1_CMDDIR PIN_CFG(197, ALT_A)
+#define GPIO197_BUSMON_D39 PIN_CFG(197, ALT_B)
+
+#define GPIO198_GPIO PIN_CFG(198, GPIO)
+#define GPIO198_MC1_FBCLK PIN_CFG(198, ALT_A)
+
+#define GPIO199_GPIO PIN_CFG(199, GPIO)
+#define GPIO199_MC1_DAT0DIR PIN_CFG(199, ALT_A)
+#define GPIO199_BUSMON_D40 PIN_CFG(199, ALT_B)
+
+#define GPIO200_GPIO PIN_CFG(200, GPIO)
+#define GPIO200_U1_TXD PIN_CFG(200, ALT_A)
+#define GPIO200_ACCU0_RTSn PIN_CFG(200, ALT_B)
+
+#define GPIO201_GPIO PIN_CFG(201, GPIO)
+#define GPIO201_U1_RXD PIN_CFG(201, ALT_A)
+#define GPIO201_ACCU0_CTSn PIN_CFG(201, ALT_B)
+
+#define GPIO202_GPIO PIN_CFG(202, GPIO)
+#define GPIO202_U1_CTSn PIN_CFG(202, ALT_A)
+#define GPIO202_ACCU0_RXD PIN_CFG(202, ALT_B)
+
+#define GPIO203_GPIO PIN_CFG(203, GPIO)
+#define GPIO203_U1_RTSn PIN_CFG(203, ALT_A)
+#define GPIO203_ACCU0_TXD PIN_CFG(203, ALT_B)
+
+#define GPIO204_GPIO PIN_CFG(204, GPIO)
+#define GPIO204_SPI0_CS2n PIN_CFG(204, ALT_A)
+#define GPIO204_ACCGPIO_000 PIN_CFG(204, ALT_B)
+#define GPIO204_LCD_VSI1 PIN_CFG(204, ALT_C)
+
+#define GPIO205_GPIO PIN_CFG(205, GPIO)
+#define GPIO205_SPI0_CS1n PIN_CFG(205, ALT_A)
+#define GPIO205_ACCGPIO_001 PIN_CFG(205, ALT_B)
+#define GPIO205_LCD_D3 PIN_CFG(205, ALT_C)
+
+#define GPIO206_GPIO PIN_CFG(206, GPIO)
+#define GPIO206_SPI0_CS0n PIN_CFG(206, ALT_A)
+#define GPIO206_ACCGPIO_002 PIN_CFG(206, ALT_B)
+#define GPIO206_LCD_D2 PIN_CFG(206, ALT_C)
+
+#define GPIO207_GPIO PIN_CFG(207, GPIO)
+#define GPIO207_SPI0_RXD PIN_CFG(207, ALT_A)
+#define GPIO207_ACCGPIO_003 PIN_CFG(207, ALT_B)
+#define GPIO207_LCD_D1 PIN_CFG(207, ALT_C)
+
+#define GPIO208_GPIO PIN_CFG(208, GPIO)
+#define GPIO208_SPI0_TXD PIN_CFG(208, ALT_A)
+#define GPIO208_ACCGPIO_004 PIN_CFG(208, ALT_B)
+#define GPIO208_LCD_D0 PIN_CFG(208, ALT_C)
+
+#define GPIO209_GPIO PIN_CFG(209, GPIO)
+#define GPIO209_SPI0_CLK PIN_CFG(209, ALT_A)
+#define GPIO209_ACCGPIO_005 PIN_CFG(209, ALT_B)
+#define GPIO209_LCD_CLK PIN_CFG(209, ALT_C)
+
+#define GPIO210_GPIO PIN_CFG(210, GPIO)
+#define GPIO210_LCD_VSO PIN_CFG(210, ALT_A)
+#define GPIO210_PRCMU_PWRCTRL1 PIN_CFG(210, ALT_B)
+
+#define GPIO211_GPIO PIN_CFG(211, GPIO)
+#define GPIO211_LCD_VSI0 PIN_CFG(211, ALT_A)
+#define GPIO211_PRCMU_PWRCTRL2 PIN_CFG(211, ALT_B)
+
+#define GPIO212_GPIO PIN_CFG(212, GPIO)
+#define GPIO212_SPI2_CS2n PIN_CFG(212, ALT_A)
+#define GPIO212_LCD_HSO PIN_CFG(212, ALT_B)
+
+#define GPIO213_GPIO PIN_CFG(213, GPIO)
+#define GPIO213_SPI2_CS1n PIN_CFG(213, ALT_A)
+#define GPIO213_LCD_DE PIN_CFG(213, ALT_B)
+#define GPIO213_BUSMON_D16 PIN_CFG(213, ALT_C)
+
+#define GPIO214_GPIO PIN_CFG(214, GPIO)
+#define GPIO214_SPI2_CS0n PIN_CFG(214, ALT_A)
+#define GPIO214_LCD_D7 PIN_CFG(214, ALT_B)
+#define GPIO214_BUSMON_D17 PIN_CFG(214, ALT_C)
+
+#define GPIO215_GPIO PIN_CFG(215, GPIO)
+#define GPIO215_SPI2_RXD PIN_CFG(215, ALT_A)
+#define GPIO215_LCD_D6 PIN_CFG(215, ALT_B)
+#define GPIO215_BUSMON_D18 PIN_CFG(215, ALT_C)
+
+#define GPIO216_GPIO PIN_CFG(216, GPIO)
+#define GPIO216_SPI2_CLK PIN_CFG(216, ALT_A)
+#define GPIO216_LCD_D5 PIN_CFG(216, ALT_B)
+
+#define GPIO217_GPIO PIN_CFG(217, GPIO)
+#define GPIO217_SPI2_TXD PIN_CFG(217, ALT_A)
+#define GPIO217_LCD_D4 PIN_CFG(217, ALT_B)
+#define GPIO217_BUSMON_D19 PIN_CFG(217, ALT_C)
+
+#define GPIO218_GPIO PIN_CFG(218, GPIO)
+#define GPIO218_I2C2_SCL PIN_CFG(218, ALT_A)
+#define GPIO218_LCD_VSO PIN_CFG(218, ALT_B)
+
+#define GPIO219_GPIO PIN_CFG(219, GPIO)
+#define GPIO219_I2C2_SDA PIN_CFG(219, ALT_A)
+#define GPIO219_LCD_D3 PIN_CFG(219, ALT_B)
+
+#define GPIO220_GPIO PIN_CFG(220, GPIO)
+#define GPIO220_MSP2_TCK PIN_CFG(220, ALT_A)
+#define GPIO220_LCD_D2 PIN_CFG(220, ALT_B)
+
+#define GPIO221_GPIO PIN_CFG(221, GPIO)
+#define GPIO221_MSP2_TFS PIN_CFG(221, ALT_A)
+#define GPIO221_LCD_D1 PIN_CFG(221, ALT_B)
+
+#define GPIO222_GPIO PIN_CFG(222, GPIO)
+#define GPIO222_MSP2_TXD PIN_CFG(222, ALT_A)
+#define GPIO222_LCD_D0 PIN_CFG(222, ALT_B)
+
+#define GPIO223_GPIO PIN_CFG(223, GPIO)
+#define GPIO223_MSP2_RXD PIN_CFG(223, ALT_A)
+#define GPIO223_LCD_CLK PIN_CFG(223, ALT_B)
+
+#define GPIO224_GPIO PIN_CFG(224, GPIO)
+#define GPIO224_PRCMU_PWRCTRL0 PIN_CFG(224, ALT_A)
+#define GPIO224_LCD_VSI1 PIN_CFG(224, ALT_B)
+
+#define GPIO225_GPIO PIN_CFG(225, GPIO)
+#define GPIO225_PRCMU_PWRCTRL1 PIN_CFG(225, ALT_A)
+#define GPIO225_IRDA_RXD PIN_CFG(225, ALT_B)
+
+#define GPIO226_GPIO PIN_CFG(226, GPIO)
+#define GPIO226_PRCMU_PWRCTRL2 PIN_CFG(226, ALT_A)
+#define GPIO226_IRRC_DAT PIN_CFG(226, ALT_B)
+
+#define GPIO227_GPIO PIN_CFG(227, GPIO)
+#define GPIO227_IRRC_DAT PIN_CFG(227, ALT_A)
+#define GPIO227_IRDA_TXD PIN_CFG(227, ALT_B)
+
+#endif
diff --git a/arch/arm/mach-ux500/pins-db8500.h b/arch/arm/mach-ux500/pins-db8500.h
index 9055d5d3233c..66f8761cc823 100644
--- a/arch/arm/mach-ux500/pins-db8500.h
+++ b/arch/arm/mach-ux500/pins-db8500.h
@@ -96,57 +96,57 @@
#define GPIO17_SLIM0_CLK PIN_CFG(17, ALT_C)
#define GPIO18_GPIO PIN_CFG(18, GPIO)
-#define GPIO18_MC0_CMDDIR PIN_CFG(18, ALT_A)
+#define GPIO18_MC0_CMDDIR PIN_CFG_PULL(18, ALT_A, UP)
#define GPIO18_U2_RXD PIN_CFG(18, ALT_B)
#define GPIO18_MS_IEP PIN_CFG(18, ALT_C)
#define GPIO19_GPIO PIN_CFG(19, GPIO)
-#define GPIO19_MC0_DAT0DIR PIN_CFG(19, ALT_A)
+#define GPIO19_MC0_DAT0DIR PIN_CFG_PULL(19, ALT_A, UP)
#define GPIO19_U2_TXD PIN_CFG(19, ALT_B)
#define GPIO19_MS_DAT0DIR PIN_CFG(19, ALT_C)
#define GPIO20_GPIO PIN_CFG(20, GPIO)
-#define GPIO20_MC0_DAT2DIR PIN_CFG(20, ALT_A)
+#define GPIO20_MC0_DAT2DIR PIN_CFG_PULL(20, ALT_A, UP)
#define GPIO20_UARTMOD_TXD PIN_CFG(20, ALT_B)
#define GPIO20_IP_TRIGOUT PIN_CFG(20, ALT_C)
#define GPIO21_GPIO PIN_CFG(21, GPIO)
-#define GPIO21_MC0_DAT31DIR PIN_CFG(21, ALT_A)
+#define GPIO21_MC0_DAT31DIR PIN_CFG_PULL(21, ALT_A, UP)
#define GPIO21_MSP0_SCK PIN_CFG(21, ALT_B)
#define GPIO21_MS_DAT31DIR PIN_CFG(21, ALT_C)
#define GPIO22_GPIO PIN_CFG(22, GPIO)
-#define GPIO22_MC0_FBCLK PIN_CFG(22, ALT_A)
+#define GPIO22_MC0_FBCLK PIN_CFG_PULL(22, ALT_A, UP)
#define GPIO22_UARTMOD_RXD PIN_CFG(22, ALT_B)
#define GPIO22_MS_FBCLK PIN_CFG(22, ALT_C)
#define GPIO23_GPIO PIN_CFG(23, GPIO)
-#define GPIO23_MC0_CLK PIN_CFG(23, ALT_A)
+#define GPIO23_MC0_CLK PIN_CFG_PULL(23, ALT_A, UP)
#define GPIO23_STMMOD_CLK PIN_CFG(23, ALT_B)
#define GPIO23_MS_CLK PIN_CFG(23, ALT_C)
#define GPIO24_GPIO PIN_CFG(24, GPIO)
-#define GPIO24_MC0_CMD PIN_CFG(24, ALT_A)
+#define GPIO24_MC0_CMD PIN_CFG_PULL(24, ALT_A, UP)
#define GPIO24_UARTMOD_RXD PIN_CFG(24, ALT_B)
#define GPIO24_MS_BS PIN_CFG(24, ALT_C)
#define GPIO25_GPIO PIN_CFG(25, GPIO)
-#define GPIO25_MC0_DAT0 PIN_CFG(25, ALT_A)
+#define GPIO25_MC0_DAT0 PIN_CFG_PULL(25, ALT_A, UP)
#define GPIO25_STMMOD_DAT0 PIN_CFG(25, ALT_B)
#define GPIO25_MS_DAT0 PIN_CFG(25, ALT_C)
#define GPIO26_GPIO PIN_CFG(26, GPIO)
-#define GPIO26_MC0_DAT1 PIN_CFG(26, ALT_A)
+#define GPIO26_MC0_DAT1 PIN_CFG_PULL(26, ALT_A, UP)
#define GPIO26_STMMOD_DAT1 PIN_CFG(26, ALT_B)
#define GPIO26_MS_DAT1 PIN_CFG(26, ALT_C)
#define GPIO27_GPIO PIN_CFG(27, GPIO)
-#define GPIO27_MC0_DAT2 PIN_CFG(27, ALT_A)
+#define GPIO27_MC0_DAT2 PIN_CFG_PULL(27, ALT_A, UP)
#define GPIO27_STMMOD_DAT2 PIN_CFG(27, ALT_B)
#define GPIO27_MS_DAT2 PIN_CFG(27, ALT_C)
#define GPIO28_GPIO PIN_CFG(28, GPIO)
-#define GPIO28_MC0_DAT3 PIN_CFG(28, ALT_A)
+#define GPIO28_MC0_DAT3 PIN_CFG_PULL(28, ALT_A, UP)
#define GPIO28_STMMOD_DAT3 PIN_CFG(28, ALT_B)
#define GPIO28_MS_DAT3 PIN_CFG(28, ALT_C)
@@ -357,48 +357,48 @@
#define GPIO97_MC5_DAT7 PIN_CFG(97, ALT_C)
#define GPIO128_GPIO PIN_CFG(128, GPIO)
-#define GPIO128_MC2_CLK PIN_CFG(128, ALT_A)
+#define GPIO128_MC2_CLK PIN_CFG_PULL(128, ALT_A, UP)
#define GPIO128_SM_CKO PIN_CFG(128, ALT_B)
#define GPIO129_GPIO PIN_CFG(129, GPIO)
-#define GPIO129_MC2_CMD PIN_CFG(129, ALT_A)
+#define GPIO129_MC2_CMD PIN_CFG_PULL(129, ALT_A, UP)
#define GPIO129_SM_WAIT0n PIN_CFG(129, ALT_B)
#define GPIO130_GPIO PIN_CFG(130, GPIO)
-#define GPIO130_MC2_FBCLK PIN_CFG(130, ALT_A)
+#define GPIO130_MC2_FBCLK PIN_CFG_PULL(130, ALT_A, UP)
#define GPIO130_SM_FBCLK PIN_CFG(130, ALT_B)
#define GPIO130_MC2_RSTN PIN_CFG(130, ALT_C)
#define GPIO131_GPIO PIN_CFG(131, GPIO)
-#define GPIO131_MC2_DAT0 PIN_CFG(131, ALT_A)
+#define GPIO131_MC2_DAT0 PIN_CFG_PULL(131, ALT_A, UP)
#define GPIO131_SM_ADQ8 PIN_CFG(131, ALT_B)
#define GPIO132_GPIO PIN_CFG(132, GPIO)
-#define GPIO132_MC2_DAT1 PIN_CFG(132, ALT_A)
+#define GPIO132_MC2_DAT1 PIN_CFG_PULL(132, ALT_A, UP)
#define GPIO132_SM_ADQ9 PIN_CFG(132, ALT_B)
#define GPIO133_GPIO PIN_CFG(133, GPIO)
-#define GPIO133_MC2_DAT2 PIN_CFG(133, ALT_A)
+#define GPIO133_MC2_DAT2 PIN_CFG_PULL(133, ALT_A, UP)
#define GPIO133_SM_ADQ10 PIN_CFG(133, ALT_B)
#define GPIO134_GPIO PIN_CFG(134, GPIO)
-#define GPIO134_MC2_DAT3 PIN_CFG(134, ALT_A)
+#define GPIO134_MC2_DAT3 PIN_CFG_PULL(134, ALT_A, UP)
#define GPIO134_SM_ADQ11 PIN_CFG(134, ALT_B)
#define GPIO135_GPIO PIN_CFG(135, GPIO)
-#define GPIO135_MC2_DAT4 PIN_CFG(135, ALT_A)
+#define GPIO135_MC2_DAT4 PIN_CFG_PULL(135, ALT_A, UP)
#define GPIO135_SM_ADQ12 PIN_CFG(135, ALT_B)
#define GPIO136_GPIO PIN_CFG(136, GPIO)
-#define GPIO136_MC2_DAT5 PIN_CFG(136, ALT_A)
+#define GPIO136_MC2_DAT5 PIN_CFG_PULL(136, ALT_A, UP)
#define GPIO136_SM_ADQ13 PIN_CFG(136, ALT_B)
#define GPIO137_GPIO PIN_CFG(137, GPIO)
-#define GPIO137_MC2_DAT6 PIN_CFG(137, ALT_A)
+#define GPIO137_MC2_DAT6 PIN_CFG_PULL(137, ALT_A, UP)
#define GPIO137_SM_ADQ14 PIN_CFG(137, ALT_B)
#define GPIO138_GPIO PIN_CFG(138, GPIO)
-#define GPIO138_MC2_DAT7 PIN_CFG(138, ALT_A)
+#define GPIO138_MC2_DAT7 PIN_CFG_PULL(138, ALT_A, UP)
#define GPIO138_SM_ADQ15 PIN_CFG(138, ALT_B)
#define GPIO139_GPIO PIN_CFG(139, GPIO)
@@ -569,39 +569,39 @@
#define GPIO196_MSP2_RXD PIN_CFG(196, ALT_A)
#define GPIO197_GPIO PIN_CFG(197, GPIO)
-#define GPIO197_MC4_DAT3 PIN_CFG(197, ALT_A)
+#define GPIO197_MC4_DAT3 PIN_CFG_PULL(197, ALT_A, UP)
#define GPIO198_GPIO PIN_CFG(198, GPIO)
-#define GPIO198_MC4_DAT2 PIN_CFG(198, ALT_A)
+#define GPIO198_MC4_DAT2 PIN_CFG_PULL(198, ALT_A, UP)
#define GPIO199_GPIO PIN_CFG(199, GPIO)
-#define GPIO199_MC4_DAT1 PIN_CFG(199, ALT_A)
+#define GPIO199_MC4_DAT1 PIN_CFG_PULL(199, ALT_A, UP)
#define GPIO200_GPIO PIN_CFG(200, GPIO)
-#define GPIO200_MC4_DAT0 PIN_CFG(200, ALT_A)
+#define GPIO200_MC4_DAT0 PIN_CFG_PULL(200, ALT_A, UP)
#define GPIO201_GPIO PIN_CFG(201, GPIO)
-#define GPIO201_MC4_CMD PIN_CFG(201, ALT_A)
+#define GPIO201_MC4_CMD PIN_CFG_PULL(201, ALT_A, UP)
#define GPIO202_GPIO PIN_CFG(202, GPIO)
-#define GPIO202_MC4_FBCLK PIN_CFG(202, ALT_A)
+#define GPIO202_MC4_FBCLK PIN_CFG_PULL(202, ALT_A, UP)
#define GPIO202_PWL PIN_CFG(202, ALT_B)
#define GPIO202_MC4_RSTN PIN_CFG(202, ALT_C)
#define GPIO203_GPIO PIN_CFG(203, GPIO)
-#define GPIO203_MC4_CLK PIN_CFG(203, ALT_A)
+#define GPIO203_MC4_CLK PIN_CFG_PULL(203, ALT_A, UP)
#define GPIO204_GPIO PIN_CFG(204, GPIO)
-#define GPIO204_MC4_DAT7 PIN_CFG(204, ALT_A)
+#define GPIO204_MC4_DAT7 PIN_CFG_PULL(204, ALT_A, UP)
#define GPIO205_GPIO PIN_CFG(205, GPIO)
-#define GPIO205_MC4_DAT6 PIN_CFG(205, ALT_A)
+#define GPIO205_MC4_DAT6 PIN_CFG_PULL(205, ALT_A, UP)
#define GPIO206_GPIO PIN_CFG(206, GPIO)
-#define GPIO206_MC4_DAT5 PIN_CFG(206, ALT_A)
+#define GPIO206_MC4_DAT5 PIN_CFG_PULL(206, ALT_A, UP)
#define GPIO207_GPIO PIN_CFG(207, GPIO)
-#define GPIO207_MC4_DAT4 PIN_CFG(207, ALT_A)
+#define GPIO207_MC4_DAT4 PIN_CFG_PULL(207, ALT_A, UP)
#define GPIO208_GPIO PIN_CFG(208, GPIO)
#define GPIO208_MC1_CLK PIN_CFG(208, ALT_A)
diff --git a/arch/arm/mach-ux500/platsmp.c b/arch/arm/mach-ux500/platsmp.c
index 438ef16aec90..9e4c678de785 100644
--- a/arch/arm/mach-ux500/platsmp.c
+++ b/arch/arm/mach-ux500/platsmp.c
@@ -78,6 +78,8 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
__cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
outer_clean_range(__pa(&pen_release), __pa(&pen_release) + 1);
+ smp_cross_call(cpumask_of(cpu));
+
timeout = jiffies + (1 * HZ);
while (time_before(jiffies, timeout)) {
if (pen_release == -1)
diff --git a/arch/arm/mach-ux500/prcmu.c b/arch/arm/mach-ux500/prcmu.c
new file mode 100644
index 000000000000..293274d1342a
--- /dev/null
+++ b/arch/arm/mach-ux500/prcmu.c
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) ST Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License v2
+ * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com>
+ *
+ * U8500 PRCMU driver.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/mutex.h>
+#include <linux/completion.h>
+#include <linux/jiffies.h>
+#include <linux/bitops.h>
+#include <linux/interrupt.h>
+
+#include <mach/hardware.h>
+#include <mach/prcmu-regs.h>
+
+#define PRCMU_TCDM_BASE __io_address(U8500_PRCMU_TCDM_BASE)
+
+#define REQ_MB5 (PRCMU_TCDM_BASE + 0xE44)
+#define ACK_MB5 (PRCMU_TCDM_BASE + 0xDF4)
+
+#define REQ_MB5_I2C_SLAVE_OP (REQ_MB5)
+#define REQ_MB5_I2C_HW_BITS (REQ_MB5 + 1)
+#define REQ_MB5_I2C_REG (REQ_MB5 + 2)
+#define REQ_MB5_I2C_VAL (REQ_MB5 + 3)
+
+#define ACK_MB5_I2C_STATUS (ACK_MB5 + 1)
+#define ACK_MB5_I2C_VAL (ACK_MB5 + 3)
+
+#define I2C_WRITE(slave) ((slave) << 1)
+#define I2C_READ(slave) (((slave) << 1) | BIT(0))
+#define I2C_STOP_EN BIT(3)
+
+enum ack_mb5_status {
+ I2C_WR_OK = 0x01,
+ I2C_RD_OK = 0x02,
+};
+
+#define MBOX_BIT BIT
+#define NUM_MBOX 8
+
+static struct {
+ struct mutex lock;
+ struct completion work;
+ bool failed;
+ struct {
+ u8 status;
+ u8 value;
+ } ack;
+} mb5_transfer;
+
+/**
+ * prcmu_abb_read() - Read register value(s) from the ABB.
+ * @slave: The I2C slave address.
+ * @reg: The (start) register address.
+ * @value: The read out value(s).
+ * @size: The number of registers to read.
+ *
+ * Reads register value(s) from the ABB.
+ * @size has to be 1 for the current firmware version.
+ */
+int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
+{
+ int r;
+
+ if (size != 1)
+ return -EINVAL;
+
+ r = mutex_lock_interruptible(&mb5_transfer.lock);
+ if (r)
+ return r;
+
+ while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
+ cpu_relax();
+
+ writeb(I2C_READ(slave), REQ_MB5_I2C_SLAVE_OP);
+ writeb(I2C_STOP_EN, REQ_MB5_I2C_HW_BITS);
+ writeb(reg, REQ_MB5_I2C_REG);
+
+ writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET);
+ if (!wait_for_completion_timeout(&mb5_transfer.work,
+ msecs_to_jiffies(500))) {
+ pr_err("prcmu: prcmu_abb_read timed out.\n");
+ r = -EIO;
+ goto unlock_and_return;
+ }
+ r = ((mb5_transfer.ack.status == I2C_RD_OK) ? 0 : -EIO);
+ if (!r)
+ *value = mb5_transfer.ack.value;
+
+unlock_and_return:
+ mutex_unlock(&mb5_transfer.lock);
+ return r;
+}
+EXPORT_SYMBOL(prcmu_abb_read);
+
+/**
+ * prcmu_abb_write() - Write register value(s) to the ABB.
+ * @slave: The I2C slave address.
+ * @reg: The (start) register address.
+ * @value: The value(s) to write.
+ * @size: The number of registers to write.
+ *
+ * Reads register value(s) from the ABB.
+ * @size has to be 1 for the current firmware version.
+ */
+int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
+{
+ int r;
+
+ if (size != 1)
+ return -EINVAL;
+
+ r = mutex_lock_interruptible(&mb5_transfer.lock);
+ if (r)
+ return r;
+
+
+ while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
+ cpu_relax();
+
+ writeb(I2C_WRITE(slave), REQ_MB5_I2C_SLAVE_OP);
+ writeb(I2C_STOP_EN, REQ_MB5_I2C_HW_BITS);
+ writeb(reg, REQ_MB5_I2C_REG);
+ writeb(*value, REQ_MB5_I2C_VAL);
+
+ writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET);
+ if (!wait_for_completion_timeout(&mb5_transfer.work,
+ msecs_to_jiffies(500))) {
+ pr_err("prcmu: prcmu_abb_write timed out.\n");
+ r = -EIO;
+ goto unlock_and_return;
+ }
+ r = ((mb5_transfer.ack.status == I2C_WR_OK) ? 0 : -EIO);
+
+unlock_and_return:
+ mutex_unlock(&mb5_transfer.lock);
+ return r;
+}
+EXPORT_SYMBOL(prcmu_abb_write);
+
+static void read_mailbox_0(void)
+{
+ writel(MBOX_BIT(0), PRCM_ARM_IT1_CLEAR);
+}
+
+static void read_mailbox_1(void)
+{
+ writel(MBOX_BIT(1), PRCM_ARM_IT1_CLEAR);
+}
+
+static void read_mailbox_2(void)
+{
+ writel(MBOX_BIT(2), PRCM_ARM_IT1_CLEAR);
+}
+
+static void read_mailbox_3(void)
+{
+ writel(MBOX_BIT(3), PRCM_ARM_IT1_CLEAR);
+}
+
+static void read_mailbox_4(void)
+{
+ writel(MBOX_BIT(4), PRCM_ARM_IT1_CLEAR);
+}
+
+static void read_mailbox_5(void)
+{
+ mb5_transfer.ack.status = readb(ACK_MB5_I2C_STATUS);
+ mb5_transfer.ack.value = readb(ACK_MB5_I2C_VAL);
+ complete(&mb5_transfer.work);
+ writel(MBOX_BIT(5), PRCM_ARM_IT1_CLEAR);
+}
+
+static void read_mailbox_6(void)
+{
+ writel(MBOX_BIT(6), PRCM_ARM_IT1_CLEAR);
+}
+
+static void read_mailbox_7(void)
+{
+ writel(MBOX_BIT(7), PRCM_ARM_IT1_CLEAR);
+}
+
+static void (* const read_mailbox[NUM_MBOX])(void) = {
+ read_mailbox_0,
+ read_mailbox_1,
+ read_mailbox_2,
+ read_mailbox_3,
+ read_mailbox_4,
+ read_mailbox_5,
+ read_mailbox_6,
+ read_mailbox_7
+};
+
+static irqreturn_t prcmu_irq_handler(int irq, void *data)
+{
+ u32 bits;
+ u8 n;
+
+ bits = (readl(PRCM_ARM_IT1_VAL) & (MBOX_BIT(NUM_MBOX) - 1));
+ if (unlikely(!bits))
+ return IRQ_NONE;
+
+ for (n = 0; bits; n++) {
+ if (bits & MBOX_BIT(n)) {
+ bits -= MBOX_BIT(n);
+ read_mailbox[n]();
+ }
+ }
+ return IRQ_HANDLED;
+}
+
+static int __init prcmu_init(void)
+{
+ mutex_init(&mb5_transfer.lock);
+ init_completion(&mb5_transfer.work);
+
+ /* Clean up the mailbox interrupts after pre-kernel code. */
+ writel((MBOX_BIT(NUM_MBOX) - 1), PRCM_ARM_IT1_CLEAR);
+
+ return request_irq(IRQ_PRCMU, prcmu_irq_handler, 0, "prcmu", NULL);
+}
+
+arch_initcall(prcmu_init);
diff --git a/arch/arm/mach-ux500/ste-dma40-db5500.h b/arch/arm/mach-ux500/ste-dma40-db5500.h
new file mode 100644
index 000000000000..cb2110c32858
--- /dev/null
+++ b/arch/arm/mach-ux500/ste-dma40-db5500.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
+ * License terms: GNU General Public License (GPL) version 2
+ *
+ * DB5500-SoC-specific configuration for DMA40
+ */
+
+#ifndef STE_DMA40_DB5500_H
+#define STE_DMA40_DB5500_H
+
+#define DB5500_DMA_NR_DEV 64
+
+enum dma_src_dev_type {
+ DB5500_DMA_DEV0_SPI0_RX = 0,
+ DB5500_DMA_DEV1_SPI1_RX = 1,
+ DB5500_DMA_DEV2_SPI2_RX = 2,
+ DB5500_DMA_DEV3_SPI3_RX = 3,
+ DB5500_DMA_DEV4_USB_OTG_IEP_1_9 = 4,
+ DB5500_DMA_DEV5_USB_OTG_IEP_2_10 = 5,
+ DB5500_DMA_DEV6_USB_OTG_IEP_3_11 = 6,
+ DB5500_DMA_DEV7_IRDA_RFS = 7,
+ DB5500_DMA_DEV8_IRDA_FIFO_RX = 8,
+ DB5500_DMA_DEV9_MSP0_RX = 9,
+ DB5500_DMA_DEV10_MSP1_RX = 10,
+ DB5500_DMA_DEV11_MSP2_RX = 11,
+ DB5500_DMA_DEV12_UART0_RX = 12,
+ DB5500_DMA_DEV13_UART1_RX = 13,
+ DB5500_DMA_DEV14_UART2_RX = 14,
+ DB5500_DMA_DEV15_UART3_RX = 15,
+ DB5500_DMA_DEV16_USB_OTG_IEP_8 = 16,
+ DB5500_DMA_DEV17_USB_OTG_IEP_1_9 = 17,
+ DB5500_DMA_DEV18_USB_OTG_IEP_2_10 = 18,
+ DB5500_DMA_DEV19_USB_OTG_IEP_3_11 = 19,
+ DB5500_DMA_DEV20_USB_OTG_IEP_4_12 = 20,
+ DB5500_DMA_DEV21_USB_OTG_IEP_5_13 = 21,
+ DB5500_DMA_DEV22_USB_OTG_IEP_6_14 = 22,
+ DB5500_DMA_DEV23_USB_OTG_IEP_7_15 = 23,
+ DB5500_DMA_DEV24_SDMMC0_RX = 24,
+ DB5500_DMA_DEV25_SDMMC1_RX = 25,
+ DB5500_DMA_DEV26_SDMMC2_RX = 26,
+ DB5500_DMA_DEV27_SDMMC3_RX = 27,
+ DB5500_DMA_DEV28_SDMMC4_RX = 28,
+ /* 29 - 32 not used */
+ DB5500_DMA_DEV33_SDMMC0_RX = 33,
+ DB5500_DMA_DEV34_SDMMC1_RX = 34,
+ DB5500_DMA_DEV35_SDMMC2_RX = 35,
+ DB5500_DMA_DEV36_SDMMC3_RX = 36,
+ DB5500_DMA_DEV37_SDMMC4_RX = 37,
+ DB5500_DMA_DEV38_USB_OTG_IEP_8 = 38,
+ DB5500_DMA_DEV39_USB_OTG_IEP_1_9 = 39,
+ DB5500_DMA_DEV40_USB_OTG_IEP_2_10 = 40,
+ DB5500_DMA_DEV41_USB_OTG_IEP_3_11 = 41,
+ DB5500_DMA_DEV42_USB_OTG_IEP_4_12 = 42,
+ DB5500_DMA_DEV43_USB_OTG_IEP_5_13 = 43,
+ DB5500_DMA_DEV44_USB_OTG_IEP_6_14 = 44,
+ DB5500_DMA_DEV45_USB_OTG_IEP_7_15 = 45,
+ /* 46 not used */
+ DB5500_DMA_DEV47_MCDE_RX = 47,
+ DB5500_DMA_DEV48_CRYPTO1_RX = 48,
+ /* 49, 50 not used */
+ DB5500_DMA_DEV49_I2C1_RX = 51,
+ DB5500_DMA_DEV50_I2C3_RX = 52,
+ DB5500_DMA_DEV51_I2C2_RX = 53,
+ /* 54 - 60 not used */
+ DB5500_DMA_DEV61_CRYPTO0_RX = 61,
+ /* 62, 63 not used */
+};
+
+enum dma_dest_dev_type {
+ DB5500_DMA_DEV0_SPI0_TX = 0,
+ DB5500_DMA_DEV1_SPI1_TX = 1,
+ DB5500_DMA_DEV2_SPI2_TX = 2,
+ DB5500_DMA_DEV3_SPI3_TX = 3,
+ DB5500_DMA_DEV4_USB_OTG_OEP_1_9 = 4,
+ DB5500_DMA_DEV5_USB_OTG_OEP_2_10 = 5,
+ DB5500_DMA_DEV6_USB_OTG_OEP_3_11 = 6,
+ DB5500_DMA_DEV7_IRRC_TX = 7,
+ DB5500_DMA_DEV8_IRDA_FIFO_TX = 8,
+ DB5500_DMA_DEV9_MSP0_TX = 9,
+ DB5500_DMA_DEV10_MSP1_TX = 10,
+ DB5500_DMA_DEV11_MSP2_TX = 11,
+ DB5500_DMA_DEV12_UART0_TX = 12,
+ DB5500_DMA_DEV13_UART1_TX = 13,
+ DB5500_DMA_DEV14_UART2_TX = 14,
+ DB5500_DMA_DEV15_UART3_TX = 15,
+ DB5500_DMA_DEV16_USB_OTG_OEP_8 = 16,
+ DB5500_DMA_DEV17_USB_OTG_OEP_1_9 = 17,
+ DB5500_DMA_DEV18_USB_OTG_OEP_2_10 = 18,
+ DB5500_DMA_DEV19_USB_OTG_OEP_3_11 = 19,
+ DB5500_DMA_DEV20_USB_OTG_OEP_4_12 = 20,
+ DB5500_DMA_DEV21_USB_OTG_OEP_5_13 = 21,
+ DB5500_DMA_DEV22_USB_OTG_OEP_6_14 = 22,
+ DB5500_DMA_DEV23_USB_OTG_OEP_7_15 = 23,
+ DB5500_DMA_DEV24_SDMMC0_TX = 24,
+ DB5500_DMA_DEV25_SDMMC1_TX = 25,
+ DB5500_DMA_DEV26_SDMMC2_TX = 26,
+ DB5500_DMA_DEV27_SDMMC3_TX = 27,
+ DB5500_DMA_DEV28_SDMMC4_TX = 28,
+ /* 29 - 31 not used */
+ DB5500_DMA_DEV32_FSMC_TX = 32,
+ DB5500_DMA_DEV33_SDMMC0_TX = 33,
+ DB5500_DMA_DEV34_SDMMC1_TX = 34,
+ DB5500_DMA_DEV35_SDMMC2_TX = 35,
+ DB5500_DMA_DEV36_SDMMC3_TX = 36,
+ DB5500_DMA_DEV37_SDMMC4_TX = 37,
+ DB5500_DMA_DEV38_USB_OTG_OEP_8 = 38,
+ DB5500_DMA_DEV39_USB_OTG_OEP_1_9 = 39,
+ DB5500_DMA_DEV40_USB_OTG_OEP_2_10 = 40,
+ DB5500_DMA_DEV41_USB_OTG_OEP_3_11 = 41,
+ DB5500_DMA_DEV42_USB_OTG_OEP_4_12 = 42,
+ DB5500_DMA_DEV43_USB_OTG_OEP_5_13 = 43,
+ DB5500_DMA_DEV44_USB_OTG_OEP_6_14 = 44,
+ DB5500_DMA_DEV45_USB_OTG_OEP_7_15 = 45,
+ /* 46 not used */
+ DB5500_DMA_DEV47_STM_TX = 47,
+ DB5500_DMA_DEV48_CRYPTO1_TX = 48,
+ DB5500_DMA_DEV49_CRYPTO1_TX_HASH1_TX = 49,
+ DB5500_DMA_DEV50_HASH1_TX = 50,
+ DB5500_DMA_DEV51_I2C1_TX = 51,
+ DB5500_DMA_DEV52_I2C3_TX = 52,
+ DB5500_DMA_DEV53_I2C2_TX = 53,
+ /* 54, 55 not used */
+ DB5500_DMA_MEMCPY_TX_1 = 56,
+ DB5500_DMA_MEMCPY_TX_2 = 57,
+ DB5500_DMA_MEMCPY_TX_3 = 58,
+ DB5500_DMA_MEMCPY_TX_4 = 59,
+ DB5500_DMA_MEMCPY_TX_5 = 60,
+ DB5500_DMA_DEV61_CRYPTO0_TX = 61,
+ DB5500_DMA_DEV62_CRYPTO0_TX_HASH0_TX = 62,
+ DB5500_DMA_DEV63_HASH0_TX = 63,
+};
+
+#endif
diff --git a/arch/arm/mach-ux500/ste-dma40-db8500.h b/arch/arm/mach-ux500/ste-dma40-db8500.h
index 9d9d3797b3b0..a616419bea76 100644
--- a/arch/arm/mach-ux500/ste-dma40-db8500.h
+++ b/arch/arm/mach-ux500/ste-dma40-db8500.h
@@ -10,145 +10,135 @@
#ifndef STE_DMA40_DB8500_H
#define STE_DMA40_DB8500_H
-#define STEDMA40_NR_DEV 64
+#define DB8500_DMA_NR_DEV 64
enum dma_src_dev_type {
- STEDMA40_DEV_SPI0_RX = 0,
- STEDMA40_DEV_SD_MMC0_RX = 1,
- STEDMA40_DEV_SD_MMC1_RX = 2,
- STEDMA40_DEV_SD_MMC2_RX = 3,
- STEDMA40_DEV_I2C1_RX = 4,
- STEDMA40_DEV_I2C3_RX = 5,
- STEDMA40_DEV_I2C2_RX = 6,
- STEDMA40_DEV_I2C4_RX = 7, /* Only on V1 */
- STEDMA40_DEV_SSP0_RX = 8,
- STEDMA40_DEV_SSP1_RX = 9,
- STEDMA40_DEV_MCDE_RX = 10,
- STEDMA40_DEV_UART2_RX = 11,
- STEDMA40_DEV_UART1_RX = 12,
- STEDMA40_DEV_UART0_RX = 13,
- STEDMA40_DEV_MSP2_RX = 14,
- STEDMA40_DEV_I2C0_RX = 15,
- STEDMA40_DEV_USB_OTG_IEP_8 = 16,
- STEDMA40_DEV_USB_OTG_IEP_1_9 = 17,
- STEDMA40_DEV_USB_OTG_IEP_2_10 = 18,
- STEDMA40_DEV_USB_OTG_IEP_3_11 = 19,
- STEDMA40_DEV_SLIM0_CH0_RX_HSI_RX_CH0 = 20,
- STEDMA40_DEV_SLIM0_CH1_RX_HSI_RX_CH1 = 21,
- STEDMA40_DEV_SLIM0_CH2_RX_HSI_RX_CH2 = 22,
- STEDMA40_DEV_SLIM0_CH3_RX_HSI_RX_CH3 = 23,
- STEDMA40_DEV_SRC_SXA0_RX_TX = 24,
- STEDMA40_DEV_SRC_SXA1_RX_TX = 25,
- STEDMA40_DEV_SRC_SXA2_RX_TX = 26,
- STEDMA40_DEV_SRC_SXA3_RX_TX = 27,
- STEDMA40_DEV_SD_MM2_RX = 28,
- STEDMA40_DEV_SD_MM0_RX = 29,
- STEDMA40_DEV_MSP1_RX = 30,
- /*
- * This channel is either SlimBus or MSP,
- * never both at the same time.
- */
- STEDMA40_SLIM0_CH0_RX = 31,
- STEDMA40_DEV_MSP0_RX = 31,
- STEDMA40_DEV_SD_MM1_RX = 32,
- STEDMA40_DEV_SPI2_RX = 33,
- STEDMA40_DEV_I2C3_RX2 = 34,
- STEDMA40_DEV_SPI1_RX = 35,
- STEDMA40_DEV_USB_OTG_IEP_4_12 = 36,
- STEDMA40_DEV_USB_OTG_IEP_5_13 = 37,
- STEDMA40_DEV_USB_OTG_IEP_6_14 = 38,
- STEDMA40_DEV_USB_OTG_IEP_7_15 = 39,
- STEDMA40_DEV_SPI3_RX = 40,
- STEDMA40_DEV_SD_MM3_RX = 41,
- STEDMA40_DEV_SD_MM4_RX = 42,
- STEDMA40_DEV_SD_MM5_RX = 43,
- STEDMA40_DEV_SRC_SXA4_RX_TX = 44,
- STEDMA40_DEV_SRC_SXA5_RX_TX = 45,
- STEDMA40_DEV_SRC_SXA6_RX_TX = 46,
- STEDMA40_DEV_SRC_SXA7_RX_TX = 47,
- STEDMA40_DEV_CAC1_RX = 48,
- /* RX channels 49 and 50 are unused */
- STEDMA40_DEV_MSHC_RX = 51,
- STEDMA40_DEV_SLIM1_CH0_RX_HSI_RX_CH4 = 52,
- STEDMA40_DEV_SLIM1_CH1_RX_HSI_RX_CH5 = 53,
- STEDMA40_DEV_SLIM1_CH2_RX_HSI_RX_CH6 = 54,
- STEDMA40_DEV_SLIM1_CH3_RX_HSI_RX_CH7 = 55,
- /* RX channels 56 thru 60 are unused */
- STEDMA40_DEV_CAC0_RX = 61,
- /* RX channels 62 and 63 are unused */
+ DB8500_DMA_DEV0_SPI0_RX = 0,
+ DB8500_DMA_DEV1_SD_MMC0_RX = 1,
+ DB8500_DMA_DEV2_SD_MMC1_RX = 2,
+ DB8500_DMA_DEV3_SD_MMC2_RX = 3,
+ DB8500_DMA_DEV4_I2C1_RX = 4,
+ DB8500_DMA_DEV5_I2C3_RX = 5,
+ DB8500_DMA_DEV6_I2C2_RX = 6,
+ DB8500_DMA_DEV7_I2C4_RX = 7, /* Only on V1 and later */
+ DB8500_DMA_DEV8_SSP0_RX = 8,
+ DB8500_DMA_DEV9_SSP1_RX = 9,
+ DB8500_DMA_DEV10_MCDE_RX = 10,
+ DB8500_DMA_DEV11_UART2_RX = 11,
+ DB8500_DMA_DEV12_UART1_RX = 12,
+ DB8500_DMA_DEV13_UART0_RX = 13,
+ DB8500_DMA_DEV14_MSP2_RX = 14,
+ DB8500_DMA_DEV15_I2C0_RX = 15,
+ DB8500_DMA_DEV16_USB_OTG_IEP_7_15 = 16,
+ DB8500_DMA_DEV17_USB_OTG_IEP_6_14 = 17,
+ DB8500_DMA_DEV18_USB_OTG_IEP_5_13 = 18,
+ DB8500_DMA_DEV19_USB_OTG_IEP_4_12 = 19,
+ DB8500_DMA_DEV20_SLIM0_CH0_RX_HSI_RX_CH0 = 20,
+ DB8500_DMA_DEV21_SLIM0_CH1_RX_HSI_RX_CH1 = 21,
+ DB8500_DMA_DEV22_SLIM0_CH2_RX_HSI_RX_CH2 = 22,
+ DB8500_DMA_DEV23_SLIM0_CH3_RX_HSI_RX_CH3 = 23,
+ DB8500_DMA_DEV24_SRC_SXA0_RX_TX = 24,
+ DB8500_DMA_DEV25_SRC_SXA1_RX_TX = 25,
+ DB8500_DMA_DEV26_SRC_SXA2_RX_TX = 26,
+ DB8500_DMA_DEV27_SRC_SXA3_RX_TX = 27,
+ DB8500_DMA_DEV28_SD_MM2_RX = 28,
+ DB8500_DMA_DEV29_SD_MM0_RX = 29,
+ DB8500_DMA_DEV30_MSP1_RX = 30,
+ /* On DB8500v2, MSP3 RX replaces MSP1 RX */
+ DB8500_DMA_DEV30_MSP3_RX = 30,
+ DB8500_DMA_DEV31_MSP0_RX_SLIM0_CH0_RX = 31,
+ DB8500_DMA_DEV32_SD_MM1_RX = 32,
+ DB8500_DMA_DEV33_SPI2_RX = 33,
+ DB8500_DMA_DEV34_I2C3_RX2 = 34,
+ DB8500_DMA_DEV35_SPI1_RX = 35,
+ DB8500_DMA_DEV36_USB_OTG_IEP_3_11 = 36,
+ DB8500_DMA_DEV37_USB_OTG_IEP_2_10 = 37,
+ DB8500_DMA_DEV38_USB_OTG_IEP_1_9 = 38,
+ DB8500_DMA_DEV39_USB_OTG_IEP_8 = 39,
+ DB8500_DMA_DEV40_SPI3_RX = 40,
+ DB8500_DMA_DEV41_SD_MM3_RX = 41,
+ DB8500_DMA_DEV42_SD_MM4_RX = 42,
+ DB8500_DMA_DEV43_SD_MM5_RX = 43,
+ DB8500_DMA_DEV44_SRC_SXA4_RX_TX = 44,
+ DB8500_DMA_DEV45_SRC_SXA5_RX_TX = 45,
+ DB8500_DMA_DEV46_SLIM0_CH8_RX_SRC_SXA6_RX_TX = 46,
+ DB8500_DMA_DEV47_SLIM0_CH9_RX_SRC_SXA7_RX_TX = 47,
+ DB8500_DMA_DEV48_CAC1_RX = 48,
+ /* 49, 50 and 51 are not used */
+ DB8500_DMA_DEV52_SLIM0_CH4_RX_HSI_RX_CH4 = 52,
+ DB8500_DMA_DEV53_SLIM0_CH5_RX_HSI_RX_CH5 = 53,
+ DB8500_DMA_DEV54_SLIM0_CH6_RX_HSI_RX_CH6 = 54,
+ DB8500_DMA_DEV55_SLIM0_CH7_RX_HSI_RX_CH7 = 55,
+ /* 56, 57, 58, 59 and 60 are not used */
+ DB8500_DMA_DEV61_CAC0_RX = 61,
+ /* 62 and 63 are not used */
};
enum dma_dest_dev_type {
- STEDMA40_DEV_SPI0_TX = 0,
- STEDMA40_DEV_SD_MMC0_TX = 1,
- STEDMA40_DEV_SD_MMC1_TX = 2,
- STEDMA40_DEV_SD_MMC2_TX = 3,
- STEDMA40_DEV_I2C1_TX = 4,
- STEDMA40_DEV_I2C3_TX = 5,
- STEDMA40_DEV_I2C2_TX = 6,
- STEDMA50_DEV_I2C4_TX = 7, /* Only on V1 */
- STEDMA40_DEV_SSP0_TX = 8,
- STEDMA40_DEV_SSP1_TX = 9,
- /* TX channel 10 is unused */
- STEDMA40_DEV_UART2_TX = 11,
- STEDMA40_DEV_UART1_TX = 12,
- STEDMA40_DEV_UART0_TX= 13,
- STEDMA40_DEV_MSP2_TX = 14,
- STEDMA40_DEV_I2C0_TX = 15,
- STEDMA40_DEV_USB_OTG_OEP_8 = 16,
- STEDMA40_DEV_USB_OTG_OEP_1_9 = 17,
- STEDMA40_DEV_USB_OTG_OEP_2_10= 18,
- STEDMA40_DEV_USB_OTG_OEP_3_11 = 19,
- STEDMA40_DEV_SLIM0_CH0_TX_HSI_TX_CH0 = 20,
- STEDMA40_DEV_SLIM0_CH1_TX_HSI_TX_CH1 = 21,
- STEDMA40_DEV_SLIM0_CH2_TX_HSI_TX_CH2 = 22,
- STEDMA40_DEV_SLIM0_CH3_TX_HSI_TX_CH3 = 23,
- STEDMA40_DEV_DST_SXA0_RX_TX = 24,
- STEDMA40_DEV_DST_SXA1_RX_TX = 25,
- STEDMA40_DEV_DST_SXA2_RX_TX = 26,
- STEDMA40_DEV_DST_SXA3_RX_TX = 27,
- STEDMA40_DEV_SD_MM2_TX = 28,
- STEDMA40_DEV_SD_MM0_TX = 29,
- STEDMA40_DEV_MSP1_TX = 30,
- /*
- * This channel is either SlimBus or MSP,
- * never both at the same time.
- */
- STEDMA40_SLIM0_CH0_TX = 31,
- STEDMA40_DEV_MSP0_TX = 31,
- STEDMA40_DEV_SD_MM1_TX = 32,
- STEDMA40_DEV_SPI2_TX = 33,
- /* Secondary I2C3 channel */
- STEDMA40_DEV_I2C3_TX2 = 34,
- STEDMA40_DEV_SPI1_TX = 35,
- STEDMA40_DEV_USB_OTG_OEP_4_12 = 36,
- STEDMA40_DEV_USB_OTG_OEP_5_13 = 37,
- STEDMA40_DEV_USB_OTG_OEP_6_14 = 38,
- STEDMA40_DEV_USB_OTG_OEP_7_15 = 39,
- STEDMA40_DEV_SPI3_TX = 40,
- STEDMA40_DEV_SD_MM3_TX = 41,
- STEDMA40_DEV_SD_MM4_TX = 42,
- STEDMA40_DEV_SD_MM5_TX = 43,
- STEDMA40_DEV_DST_SXA4_RX_TX = 44,
- STEDMA40_DEV_DST_SXA5_RX_TX = 45,
- STEDMA40_DEV_DST_SXA6_RX_TX = 46,
- STEDMA40_DEV_DST_SXA7_RX_TX = 47,
- STEDMA40_DEV_CAC1_TX = 48,
- STEDMA40_DEV_CAC1_TX_HAC1_TX = 49,
- STEDMA40_DEV_HAC1_TX = 50,
- STEDMA40_MEMCPY_TX_0 = 51,
- STEDMA40_DEV_SLIM1_CH0_TX_HSI_TX_CH4 = 52,
- STEDMA40_DEV_SLIM1_CH1_TX_HSI_TX_CH5 = 53,
- STEDMA40_DEV_SLIM1_CH2_TX_HSI_TX_CH6 = 54,
- STEDMA40_DEV_SLIM1_CH3_TX_HSI_TX_CH7 = 55,
- STEDMA40_MEMCPY_TX_1 = 56,
- STEDMA40_MEMCPY_TX_2 = 57,
- STEDMA40_MEMCPY_TX_3 = 58,
- STEDMA40_MEMCPY_TX_4 = 59,
- STEDMA40_MEMCPY_TX_5 = 60,
- STEDMA40_DEV_CAC0_TX = 61,
- STEDMA40_DEV_CAC0_TX_HAC0_TX = 62,
- STEDMA40_DEV_HAC0_TX = 63,
+ DB8500_DMA_DEV0_SPI0_TX = 0,
+ DB8500_DMA_DEV1_SD_MMC0_TX = 1,
+ DB8500_DMA_DEV2_SD_MMC1_TX = 2,
+ DB8500_DMA_DEV3_SD_MMC2_TX = 3,
+ DB8500_DMA_DEV4_I2C1_TX = 4,
+ DB8500_DMA_DEV5_I2C3_TX = 5,
+ DB8500_DMA_DEV6_I2C2_TX = 6,
+ DB8500_DMA_DEV7_I2C4_TX = 7, /* Only on V1 and later */
+ DB8500_DMA_DEV8_SSP0_TX = 8,
+ DB8500_DMA_DEV9_SSP1_TX = 9,
+ /* 10 is not used*/
+ DB8500_DMA_DEV11_UART2_TX = 11,
+ DB8500_DMA_DEV12_UART1_TX = 12,
+ DB8500_DMA_DEV13_UART0_TX = 13,
+ DB8500_DMA_DEV14_MSP2_TX = 14,
+ DB8500_DMA_DEV15_I2C0_TX = 15,
+ DB8500_DMA_DEV16_USB_OTG_OEP_7_15 = 16,
+ DB8500_DMA_DEV17_USB_OTG_OEP_6_14 = 17,
+ DB8500_DMA_DEV18_USB_OTG_OEP_5_13 = 18,
+ DB8500_DMA_DEV19_USB_OTG_OEP_4_12 = 19,
+ DB8500_DMA_DEV20_SLIM0_CH0_TX_HSI_TX_CH0 = 20,
+ DB8500_DMA_DEV21_SLIM0_CH1_TX_HSI_TX_CH1 = 21,
+ DB8500_DMA_DEV22_SLIM0_CH2_TX_HSI_TX_CH2 = 22,
+ DB8500_DMA_DEV23_SLIM0_CH3_TX_HSI_TX_CH3 = 23,
+ DB8500_DMA_DEV24_DST_SXA0_RX_TX = 24,
+ DB8500_DMA_DEV25_DST_SXA1_RX_TX = 25,
+ DB8500_DMA_DEV26_DST_SXA2_RX_TX = 26,
+ DB8500_DMA_DEV27_DST_SXA3_RX_TX = 27,
+ DB8500_DMA_DEV28_SD_MM2_TX = 28,
+ DB8500_DMA_DEV29_SD_MM0_TX = 29,
+ DB8500_DMA_DEV30_MSP1_TX = 30,
+ DB8500_DMA_DEV31_MSP0_TX_SLIM0_CH0_TX = 31,
+ DB8500_DMA_DEV32_SD_MM1_TX = 32,
+ DB8500_DMA_DEV33_SPI2_TX = 33,
+ DB8500_DMA_DEV34_I2C3_TX2 = 34,
+ DB8500_DMA_DEV35_SPI1_TX = 35,
+ DB8500_DMA_DEV36_USB_OTG_OEP_3_11 = 36,
+ DB8500_DMA_DEV37_USB_OTG_OEP_2_10 = 37,
+ DB8500_DMA_DEV38_USB_OTG_OEP_1_9 = 38,
+ DB8500_DMA_DEV39_USB_OTG_OEP_8 = 39,
+ DB8500_DMA_DEV40_SPI3_TX = 40,
+ DB8500_DMA_DEV41_SD_MM3_TX = 41,
+ DB8500_DMA_DEV42_SD_MM4_TX = 42,
+ DB8500_DMA_DEV43_SD_MM5_TX = 43,
+ DB8500_DMA_DEV44_DST_SXA4_RX_TX = 44,
+ DB8500_DMA_DEV45_DST_SXA5_RX_TX = 45,
+ DB8500_DMA_DEV46_SLIM0_CH8_TX_DST_SXA6_RX_TX = 46,
+ DB8500_DMA_DEV47_SLIM0_CH9_TX_DST_SXA7_RX_TX = 47,
+ DB8500_DMA_DEV48_CAC1_TX = 48,
+ DB8500_DMA_DEV49_CAC1_TX_HAC1_TX = 49,
+ DB8500_DMA_DEV50_HAC1_TX = 50,
+ DB8500_DMA_MEMCPY_TX_0 = 51,
+ DB8500_DMA_DEV52_SLIM1_CH4_TX_HSI_TX_CH4 = 52,
+ DB8500_DMA_DEV53_SLIM1_CH5_TX_HSI_TX_CH5 = 53,
+ DB8500_DMA_DEV54_SLIM1_CH6_TX_HSI_TX_CH6 = 54,
+ DB8500_DMA_DEV55_SLIM1_CH7_TX_HSI_TX_CH7 = 55,
+ DB8500_DMA_MEMCPY_TX_1 = 56,
+ DB8500_DMA_MEMCPY_TX_2 = 57,
+ DB8500_DMA_MEMCPY_TX_3 = 58,
+ DB8500_DMA_MEMCPY_TX_4 = 59,
+ DB8500_DMA_MEMCPY_TX_5 = 60,
+ DB8500_DMA_DEV61_CAC0_TX = 61,
+ DB8500_DMA_DEV62_CAC0_TX_HAC0_TX = 62,
+ DB8500_DMA_DEV63_HAC0_TX = 63,
};
#endif
diff --git a/arch/arm/mach-versatile/include/mach/debug-macro.S b/arch/arm/mach-versatile/include/mach/debug-macro.S
index 6fea7199c626..eb2cf7dc5c44 100644
--- a/arch/arm/mach-versatile/include/mach/debug-macro.S
+++ b/arch/arm/mach-versatile/include/mach/debug-macro.S
@@ -11,13 +11,11 @@
*
*/
- .macro addruart, rx, tmp
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ MMU enabled?
- moveq \rx, #0x10000000
- movne \rx, #0xf1000000 @ virtual base
- orr \rx, \rx, #0x001F0000
- orr \rx, \rx, #0x00001000
+ .macro addruart, rp, rv
+ mov \rp, #0x001F0000
+ orr \rp, \rp, #0x00001000
+ orr \rv, \rp, #0xf1000000 @ virtual base
+ orr \rp, \rp, #0x10000000 @ physical base
.endm
#include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/mach-versatile/include/mach/vmalloc.h b/arch/arm/mach-versatile/include/mach/vmalloc.h
index 427e3612db5d..ebd8a2543d3b 100644
--- a/arch/arm/mach-versatile/include/mach/vmalloc.h
+++ b/arch/arm/mach-versatile/include/mach/vmalloc.h
@@ -18,4 +18,4 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#define VMALLOC_END (PAGE_OFFSET + 0x18000000)
+#define VMALLOC_END 0xd8000000
diff --git a/arch/arm/mach-versatile/versatile_ab.c b/arch/arm/mach-versatile/versatile_ab.c
index bb8ec7724f79..aa9730fb13bf 100644
--- a/arch/arm/mach-versatile/versatile_ab.c
+++ b/arch/arm/mach-versatile/versatile_ab.c
@@ -35,8 +35,6 @@
MACHINE_START(VERSATILE_AB, "ARM-Versatile AB")
/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
- .phys_io = 0x101f1000,
- .io_pg_offst = ((0xf11f1000) >> 18) & 0xfffc,
.boot_params = 0x00000100,
.map_io = versatile_map_io,
.init_irq = versatile_init_irq,
diff --git a/arch/arm/mach-versatile/versatile_pb.c b/arch/arm/mach-versatile/versatile_pb.c
index 239cd30fc4f5..bf469642a3f8 100644
--- a/arch/arm/mach-versatile/versatile_pb.c
+++ b/arch/arm/mach-versatile/versatile_pb.c
@@ -108,8 +108,6 @@ static void __init versatile_pb_init(void)
MACHINE_START(VERSATILE_PB, "ARM-Versatile PB")
/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
- .phys_io = 0x101f1000,
- .io_pg_offst = ((0xf11f1000) >> 18) & 0xfffc,
.boot_params = 0x00000100,
.map_io = versatile_map_io,
.init_irq = versatile_init_irq,
diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c
index efb127022d42..c2e405a9e025 100644
--- a/arch/arm/mach-vexpress/ct-ca9x4.c
+++ b/arch/arm/mach-vexpress/ct-ca9x4.c
@@ -68,7 +68,7 @@ static void __init ct_ca9x4_init_irq(void)
}
#if 0
-static void ct_ca9x4_timer_init(void)
+static void __init ct_ca9x4_timer_init(void)
{
writel(0, MMIO_P2V(CT_CA9X4_TIMER0) + TIMER_CTRL);
writel(0, MMIO_P2V(CT_CA9X4_TIMER1) + TIMER_CTRL);
@@ -222,7 +222,7 @@ static struct platform_device pmu_device = {
.resource = pmu_resources,
};
-static void ct_ca9x4_init(void)
+static void __init ct_ca9x4_init(void)
{
int i;
@@ -245,8 +245,6 @@ static void ct_ca9x4_init(void)
}
MACHINE_START(VEXPRESS, "ARM-Versatile Express CA9x4")
- .phys_io = V2M_UART0 & SECTION_MASK,
- .io_pg_offst = (__MMIO_P2V(V2M_UART0) >> 18) & 0xfffc,
.boot_params = PHYS_OFFSET + 0x00000100,
.map_io = ct_ca9x4_map_io,
.init_irq = ct_ca9x4_init_irq,
diff --git a/arch/arm/mach-vexpress/include/mach/debug-macro.S b/arch/arm/mach-vexpress/include/mach/debug-macro.S
index 5167e2aceeba..050d65e02a42 100644
--- a/arch/arm/mach-vexpress/include/mach/debug-macro.S
+++ b/arch/arm/mach-vexpress/include/mach/debug-macro.S
@@ -12,12 +12,10 @@
#define DEBUG_LL_UART_OFFSET 0x00009000
- .macro addruart,rx,tmp
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ MMU enabled?
- moveq \rx, #0x10000000
- movne \rx, #0xf8000000 @ virtual base
- orr \rx, \rx, #DEBUG_LL_UART_OFFSET
+ .macro addruart,rp,rv
+ mov \rp, #DEBUG_LL_UART_OFFSET
+ orr \rv, \rp, #0xf8000000 @ virtual base
+ orr \rp, \rp, #0x10000000 @ physical base
.endm
#include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/mach-vexpress/include/mach/smp.h b/arch/arm/mach-vexpress/include/mach/smp.h
index 72a9621ed087..5a6da4fd247e 100644
--- a/arch/arm/mach-vexpress/include/mach/smp.h
+++ b/arch/arm/mach-vexpress/include/mach/smp.h
@@ -2,14 +2,7 @@
#define __MACH_SMP_H
#include <asm/hardware/gic.h>
-
-#define hard_smp_processor_id() \
- ({ \
- unsigned int cpunum; \
- __asm__("mrc p15, 0, %0, c0, c0, 5" \
- : "=r" (cpunum)); \
- cpunum &= 0x0F; \
- })
+#include <asm/smp_mpidr.h>
/*
* We use IRQ1 as the IPI
diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c
index 817f0ad38a0b..7eaa232180a5 100644
--- a/arch/arm/mach-vexpress/v2m.c
+++ b/arch/arm/mach-vexpress/v2m.c
@@ -48,7 +48,7 @@ void __init v2m_map_io(struct map_desc *tile, size_t num)
}
-static void v2m_timer_init(void)
+static void __init v2m_timer_init(void)
{
writel(0, MMIO_P2V(V2M_TIMER0) + TIMER_CTRL);
writel(0, MMIO_P2V(V2M_TIMER1) + TIMER_CTRL);
diff --git a/arch/arm/mach-w90x900/mach-nuc910evb.c b/arch/arm/mach-w90x900/mach-nuc910evb.c
index ec05bda946f3..30fccde94fb8 100644
--- a/arch/arm/mach-w90x900/mach-nuc910evb.c
+++ b/arch/arm/mach-w90x900/mach-nuc910evb.c
@@ -34,8 +34,6 @@ static void __init nuc910evb_init(void)
MACHINE_START(W90P910EVB, "W90P910EVB")
/* Maintainer: Wan ZongShun */
- .phys_io = W90X900_PA_UART,
- .io_pg_offst = (((u32)W90X900_VA_UART) >> 18) & 0xfffc,
.boot_params = 0,
.map_io = nuc910evb_map_io,
.init_irq = nuc900_init_irq,
diff --git a/arch/arm/mach-w90x900/mach-nuc950evb.c b/arch/arm/mach-w90x900/mach-nuc950evb.c
index 04d295f89eb0..590c99b96dc1 100644
--- a/arch/arm/mach-w90x900/mach-nuc950evb.c
+++ b/arch/arm/mach-w90x900/mach-nuc950evb.c
@@ -37,8 +37,6 @@ static void __init nuc950evb_init(void)
MACHINE_START(W90P950EVB, "W90P950EVB")
/* Maintainer: Wan ZongShun */
- .phys_io = W90X900_PA_UART,
- .io_pg_offst = (((u32)W90X900_VA_UART) >> 18) & 0xfffc,
.boot_params = 0,
.map_io = nuc950evb_map_io,
.init_irq = nuc900_init_irq,
diff --git a/arch/arm/mach-w90x900/mach-nuc960evb.c b/arch/arm/mach-w90x900/mach-nuc960evb.c
index e3a46f19f2bc..e09c645d61b6 100644
--- a/arch/arm/mach-w90x900/mach-nuc960evb.c
+++ b/arch/arm/mach-w90x900/mach-nuc960evb.c
@@ -34,8 +34,6 @@ static void __init nuc960evb_init(void)
MACHINE_START(W90N960EVB, "W90N960EVB")
/* Maintainer: Wan ZongShun */
- .phys_io = W90X900_PA_UART,
- .io_pg_offst = (((u32)W90X900_VA_UART) >> 18) & 0xfffc,
.boot_params = 0,
.map_io = nuc960evb_map_io,
.init_irq = nuc900_init_irq,
diff --git a/arch/arm/mm/cache-v6.S b/arch/arm/mm/cache-v6.S
index 86aa689ef1aa..99fa688dfadd 100644
--- a/arch/arm/mm/cache-v6.S
+++ b/arch/arm/mm/cache-v6.S
@@ -21,18 +21,22 @@
#define D_CACHE_LINE_SIZE 32
#define BTB_FLUSH_SIZE 8
-#ifdef CONFIG_ARM_ERRATA_411920
/*
- * Invalidate the entire I cache (this code is a workaround for the ARM1136
- * erratum 411920 - Invalidate Instruction Cache operation can fail. This
- * erratum is present in 1136, 1156 and 1176. It does not affect the MPCore.
+ * v6_flush_icache_all()
+ *
+ * Flush the whole I-cache.
*
- * Registers:
- * r0 - set to 0
- * r1 - corrupted
+ * ARM1136 erratum 411920 - Invalidate Instruction Cache operation can fail.
+ * This erratum is present in 1136, 1156 and 1176. It does not affect the
+ * MPCore.
+ *
+ * Registers:
+ * r0 - set to 0
+ * r1 - corrupted
*/
-ENTRY(v6_icache_inval_all)
+ENTRY(v6_flush_icache_all)
mov r0, #0
+#ifdef CONFIG_ARM_ERRATA_411920
mrs r1, cpsr
cpsid ifa @ disable interrupts
mcr p15, 0, r0, c7, c5, 0 @ invalidate entire I-cache
@@ -43,8 +47,11 @@ ENTRY(v6_icache_inval_all)
.rept 11 @ ARM Ltd recommends at least
nop @ 11 NOPs
.endr
- mov pc, lr
+#else
+ mcr p15, 0, r0, c7, c5, 0 @ invalidate I-cache
#endif
+ mov pc, lr
+ENDPROC(v6_flush_icache_all)
/*
* v6_flush_cache_all()
@@ -60,7 +67,7 @@ ENTRY(v6_flush_kern_cache_all)
#ifndef CONFIG_ARM_ERRATA_411920
mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate
#else
- b v6_icache_inval_all
+ b v6_flush_icache_all
#endif
#else
mcr p15, 0, r0, c7, c15, 0 @ Cache clean+invalidate
@@ -138,7 +145,7 @@ ENTRY(v6_coherent_user_range)
#ifndef CONFIG_ARM_ERRATA_411920
mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate
#else
- b v6_icache_inval_all
+ b v6_flush_icache_all
#endif
#else
mcr p15, 0, r0, c7, c5, 6 @ invalidate BTB
@@ -312,6 +319,7 @@ ENDPROC(v6_dma_unmap_area)
.type v6_cache_fns, #object
ENTRY(v6_cache_fns)
+ .long v6_flush_icache_all
.long v6_flush_kern_cache_all
.long v6_flush_user_cache_all
.long v6_flush_user_cache_range
diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S
index 37c8157e116e..a3ebf7a4f49b 100644
--- a/arch/arm/mm/cache-v7.S
+++ b/arch/arm/mm/cache-v7.S
@@ -18,6 +18,21 @@
#include "proc-macros.S"
/*
+ * v7_flush_icache_all()
+ *
+ * Flush the whole I-cache.
+ *
+ * Registers:
+ * r0 - set to 0
+ */
+ENTRY(v7_flush_icache_all)
+ mov r0, #0
+ ALT_SMP(mcr p15, 0, r0, c7, c1, 0) @ invalidate I-cache inner shareable
+ ALT_UP(mcr p15, 0, r0, c7, c5, 0) @ I+BTB cache invalidate
+ mov pc, lr
+ENDPROC(v7_flush_icache_all)
+
+/*
* v7_flush_dcache_all()
*
* Flush the whole D-cache.
@@ -91,11 +106,8 @@ ENTRY(v7_flush_kern_cache_all)
THUMB( stmfd sp!, {r4-r7, r9-r11, lr} )
bl v7_flush_dcache_all
mov r0, #0
-#ifdef CONFIG_SMP
- mcr p15, 0, r0, c7, c1, 0 @ invalidate I-cache inner shareable
-#else
- mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate
-#endif
+ ALT_SMP(mcr p15, 0, r0, c7, c1, 0) @ invalidate I-cache inner shareable
+ ALT_UP(mcr p15, 0, r0, c7, c5, 0) @ I+BTB cache invalidate
ARM( ldmfd sp!, {r4-r5, r7, r9-r11, lr} )
THUMB( ldmfd sp!, {r4-r7, r9-r11, lr} )
mov pc, lr
@@ -171,11 +183,8 @@ ENTRY(v7_coherent_user_range)
cmp r0, r1
blo 1b
mov r0, #0
-#ifdef CONFIG_SMP
- mcr p15, 0, r0, c7, c1, 6 @ invalidate BTB Inner Shareable
-#else
- mcr p15, 0, r0, c7, c5, 6 @ invalidate BTB
-#endif
+ ALT_SMP(mcr p15, 0, r0, c7, c1, 6) @ invalidate BTB Inner Shareable
+ ALT_UP(mcr p15, 0, r0, c7, c5, 6) @ invalidate BTB
dsb
isb
mov pc, lr
@@ -309,6 +318,7 @@ ENDPROC(v7_dma_unmap_area)
.type v7_cache_fns, #object
ENTRY(v7_cache_fns)
+ .long v7_flush_icache_all
.long v7_flush_kern_cache_all
.long v7_flush_user_cache_all
.long v7_flush_user_cache_range
diff --git a/arch/arm/mm/copypage-v4mc.c b/arch/arm/mm/copypage-v4mc.c
index 598c51ad5071..b8061519ce77 100644
--- a/arch/arm/mm/copypage-v4mc.c
+++ b/arch/arm/mm/copypage-v4mc.c
@@ -73,7 +73,7 @@ void v4_mc_copy_user_highpage(struct page *to, struct page *from,
{
void *kto = kmap_atomic(to, KM_USER1);
- if (test_and_clear_bit(PG_dcache_dirty, &from->flags))
+ if (!test_and_set_bit(PG_dcache_clean, &from->flags))
__flush_dcache_page(page_mapping(from), from);
spin_lock(&minicache_lock);
diff --git a/arch/arm/mm/copypage-v6.c b/arch/arm/mm/copypage-v6.c
index f55fa1044f72..bdba6c65c901 100644
--- a/arch/arm/mm/copypage-v6.c
+++ b/arch/arm/mm/copypage-v6.c
@@ -79,7 +79,7 @@ static void v6_copy_user_highpage_aliasing(struct page *to,
unsigned int offset = CACHE_COLOUR(vaddr);
unsigned long kfrom, kto;
- if (test_and_clear_bit(PG_dcache_dirty, &from->flags))
+ if (!test_and_set_bit(PG_dcache_clean, &from->flags))
__flush_dcache_page(page_mapping(from), from);
/* FIXME: not highmem safe */
diff --git a/arch/arm/mm/copypage-xscale.c b/arch/arm/mm/copypage-xscale.c
index 9920c0ae2096..649bbcd325bf 100644
--- a/arch/arm/mm/copypage-xscale.c
+++ b/arch/arm/mm/copypage-xscale.c
@@ -95,7 +95,7 @@ void xscale_mc_copy_user_highpage(struct page *to, struct page *from,
{
void *kto = kmap_atomic(to, KM_USER1);
- if (test_and_clear_bit(PG_dcache_dirty, &from->flags))
+ if (!test_and_set_bit(PG_dcache_clean, &from->flags))
__flush_dcache_page(page_mapping(from), from);
spin_lock(&minicache_lock);
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 4bc43e535d3b..e4dd0646e859 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -523,6 +523,12 @@ void ___dma_page_dev_to_cpu(struct page *page, unsigned long off,
outer_inv_range(paddr, paddr + size);
dma_cache_maint_page(page, off, size, dir, dmac_unmap_area);
+
+ /*
+ * Mark the D-cache clean for this page to avoid extra flushing.
+ */
+ if (dir != DMA_TO_DEVICE && off == 0 && size >= PAGE_SIZE)
+ set_bit(PG_dcache_clean, &page->flags);
}
EXPORT_SYMBOL(___dma_page_dev_to_cpu);
diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c
index 9b906dec1ca1..8440d952ba6d 100644
--- a/arch/arm/mm/fault-armv.c
+++ b/arch/arm/mm/fault-armv.c
@@ -28,6 +28,7 @@
static unsigned long shared_pte_mask = L_PTE_MT_BUFFERABLE;
+#if __LINUX_ARM_ARCH__ < 6
/*
* We take the easy way out of this problem - we make the
* PTE uncacheable. However, we leave the write buffer on.
@@ -141,7 +142,7 @@ make_coherent(struct address_space *mapping, struct vm_area_struct *vma,
* a page table, or changing an existing PTE. Basically, there are two
* things that we need to take care of:
*
- * 1. If PG_dcache_dirty is set for the page, we need to ensure
+ * 1. If PG_dcache_clean is not set for the page, we need to ensure
* that any cache entries for the kernels virtual memory
* range are written back to the page.
* 2. If we have multiple shared mappings of the same space in
@@ -168,10 +169,8 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr,
return;
mapping = page_mapping(page);
-#ifndef CONFIG_SMP
- if (test_and_clear_bit(PG_dcache_dirty, &page->flags))
+ if (!test_and_set_bit(PG_dcache_clean, &page->flags))
__flush_dcache_page(mapping, page);
-#endif
if (mapping) {
if (cache_is_vivt())
make_coherent(mapping, vma, addr, ptep, pfn);
@@ -179,6 +178,7 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr,
__flush_icache_all();
}
}
+#endif /* __LINUX_ARM_ARCH__ < 6 */
/*
* Check whether the write buffer has physical address aliasing
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index 23b0b03af5ea..1e21e125fe3a 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -581,6 +581,19 @@ static struct fsr_info ifsr_info[] = {
{ do_bad, SIGBUS, 0, "unknown 31" },
};
+void __init
+hook_ifault_code(int nr, int (*fn)(unsigned long, unsigned int, struct pt_regs *),
+ int sig, int code, const char *name)
+{
+ if (nr < 0 || nr >= ARRAY_SIZE(ifsr_info))
+ BUG();
+
+ ifsr_info[nr].fn = fn;
+ ifsr_info[nr].sig = sig;
+ ifsr_info[nr].code = code;
+ ifsr_info[nr].name = name;
+}
+
asmlinkage void __exception
do_PrefetchAbort(unsigned long addr, unsigned int ifsr, struct pt_regs *regs)
{
diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c
index c6844cb9b508..391ffae75098 100644
--- a/arch/arm/mm/flush.c
+++ b/arch/arm/mm/flush.c
@@ -17,6 +17,7 @@
#include <asm/smp_plat.h>
#include <asm/system.h>
#include <asm/tlbflush.h>
+#include <asm/smp_plat.h>
#include "mm.h"
@@ -39,6 +40,18 @@ static void flush_pfn_alias(unsigned long pfn, unsigned long vaddr)
: "cc");
}
+static void flush_icache_alias(unsigned long pfn, unsigned long vaddr, unsigned long len)
+{
+ unsigned long colour = CACHE_COLOUR(vaddr);
+ unsigned long offset = vaddr & (PAGE_SIZE - 1);
+ unsigned long to;
+
+ set_pte_ext(TOP_PTE(ALIAS_FLUSH_START) + colour, pfn_pte(pfn, PAGE_KERNEL), 0);
+ to = ALIAS_FLUSH_START + (colour << PAGE_SHIFT) + offset;
+ flush_tlb_kernel_page(to);
+ flush_icache_range(to, to + len);
+}
+
void flush_cache_mm(struct mm_struct *mm)
{
if (cache_is_vivt()) {
@@ -89,16 +102,16 @@ void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsig
if (vma->vm_flags & VM_EXEC && icache_is_vivt_asid_tagged())
__flush_icache_all();
}
+
#else
-#define flush_pfn_alias(pfn,vaddr) do { } while (0)
+#define flush_pfn_alias(pfn,vaddr) do { } while (0)
+#define flush_icache_alias(pfn,vaddr,len) do { } while (0)
#endif
-#ifdef CONFIG_SMP
static void flush_ptrace_access_other(void *args)
{
__flush_icache_all();
}
-#endif
static
void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
@@ -118,15 +131,16 @@ void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
return;
}
- /* VIPT non-aliasing cache */
+ /* VIPT non-aliasing D-cache */
if (vma->vm_flags & VM_EXEC) {
unsigned long addr = (unsigned long)kaddr;
- __cpuc_coherent_kern_range(addr, addr + len);
-#ifdef CONFIG_SMP
+ if (icache_is_vipt_aliasing())
+ flush_icache_alias(page_to_pfn(page), uaddr, len);
+ else
+ __cpuc_coherent_kern_range(addr, addr + len);
if (cache_ops_need_broadcast())
smp_call_function(flush_ptrace_access_other,
NULL, 1);
-#endif
}
}
@@ -215,6 +229,36 @@ static void __flush_dcache_aliases(struct address_space *mapping, struct page *p
flush_dcache_mmap_unlock(mapping);
}
+#if __LINUX_ARM_ARCH__ >= 6
+void __sync_icache_dcache(pte_t pteval)
+{
+ unsigned long pfn;
+ struct page *page;
+ struct address_space *mapping;
+
+ if (!pte_present_user(pteval))
+ return;
+ if (cache_is_vipt_nonaliasing() && !pte_exec(pteval))
+ /* only flush non-aliasing VIPT caches for exec mappings */
+ return;
+ pfn = pte_pfn(pteval);
+ if (!pfn_valid(pfn))
+ return;
+
+ page = pfn_to_page(pfn);
+ if (cache_is_vipt_aliasing())
+ mapping = page_mapping(page);
+ else
+ mapping = NULL;
+
+ if (!test_and_set_bit(PG_dcache_clean, &page->flags))
+ __flush_dcache_page(mapping, page);
+ /* pte_exec() already checked above for non-aliasing VIPT cache */
+ if (cache_is_vipt_nonaliasing() || pte_exec(pteval))
+ __flush_icache_all();
+}
+#endif
+
/*
* Ensure cache coherency between kernel mapping and userspace mapping
* of this page.
@@ -246,17 +290,16 @@ void flush_dcache_page(struct page *page)
mapping = page_mapping(page);
-#ifndef CONFIG_SMP
- if (!PageHighMem(page) && mapping && !mapping_mapped(mapping))
- set_bit(PG_dcache_dirty, &page->flags);
- else
-#endif
- {
+ if (!cache_ops_need_broadcast() &&
+ mapping && !mapping_mapped(mapping))
+ clear_bit(PG_dcache_clean, &page->flags);
+ else {
__flush_dcache_page(mapping, page);
if (mapping && cache_is_vivt())
__flush_dcache_aliases(mapping, page);
else if (mapping)
__flush_icache_all();
+ set_bit(PG_dcache_clean, &page->flags);
}
}
EXPORT_SYMBOL(flush_dcache_page);
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 7185b00650fe..7fd9b5eb177f 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -150,6 +150,7 @@ static void __init find_limits(struct meminfo *mi,
static void __init arm_bootmem_init(struct meminfo *mi,
unsigned long start_pfn, unsigned long end_pfn)
{
+ struct memblock_region *reg;
unsigned int boot_pages;
phys_addr_t bitmap;
pg_data_t *pgdat;
@@ -180,13 +181,13 @@ static void __init arm_bootmem_init(struct meminfo *mi,
/*
* Reserve the memblock reserved regions in bootmem.
*/
- for (i = 0; i < memblock.reserved.cnt; i++) {
- phys_addr_t start = memblock_start_pfn(&memblock.reserved, i);
- if (start >= start_pfn &&
- memblock_end_pfn(&memblock.reserved, i) <= end_pfn)
+ for_each_memblock(reserved, reg) {
+ phys_addr_t start = memblock_region_reserved_base_pfn(reg);
+ phys_addr_t end = memblock_region_reserved_end_pfn(reg);
+ if (start >= start_pfn && end <= end_pfn)
reserve_bootmem_node(pgdat, __pfn_to_phys(start),
- memblock_size_bytes(&memblock.reserved, i),
- BOOTMEM_DEFAULT);
+ (end - start) << PAGE_SHIFT,
+ BOOTMEM_DEFAULT);
}
}
@@ -237,20 +238,7 @@ static void __init arm_bootmem_free(struct meminfo *mi, unsigned long min,
#ifndef CONFIG_SPARSEMEM
int pfn_valid(unsigned long pfn)
{
- struct memblock_region *mem = &memblock.memory;
- unsigned int left = 0, right = mem->cnt;
-
- do {
- unsigned int mid = (right + left) / 2;
-
- if (pfn < memblock_start_pfn(mem, mid))
- right = mid;
- else if (pfn >= memblock_end_pfn(mem, mid))
- left = mid + 1;
- else
- return 1;
- } while (left < right);
- return 0;
+ return memblock_is_memory(pfn << PAGE_SHIFT);
}
EXPORT_SYMBOL(pfn_valid);
@@ -260,10 +248,11 @@ static void arm_memory_present(void)
#else
static void arm_memory_present(void)
{
- int i;
- for (i = 0; i < memblock.memory.cnt; i++)
- memory_present(0, memblock_start_pfn(&memblock.memory, i),
- memblock_end_pfn(&memblock.memory, i));
+ struct memblock_region *reg;
+
+ for_each_memblock(memory, reg)
+ memory_present(0, memblock_region_memory_base_pfn(reg),
+ memblock_region_memory_end_pfn(reg));
}
#endif
@@ -277,7 +266,7 @@ void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc)
/* Register the kernel text, kernel data and initrd with memblock. */
#ifdef CONFIG_XIP_KERNEL
- memblock_reserve(__pa(_data), _end - _data);
+ memblock_reserve(__pa(_sdata), _end - _sdata);
#else
memblock_reserve(__pa(_stext), _end - _stext);
#endif
@@ -545,7 +534,7 @@ void __init mem_init(void)
MLK_ROUNDUP(__init_begin, __init_end),
MLK_ROUNDUP(_text, _etext),
- MLK_ROUNDUP(_data, _edata));
+ MLK_ROUNDUP(_sdata, _edata));
#undef MLK
#undef MLM
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
index ab506272b2d3..17e7b0b57e49 100644
--- a/arch/arm/mm/ioremap.c
+++ b/arch/arm/mm/ioremap.c
@@ -204,8 +204,12 @@ void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn,
/*
* Don't allow RAM to be mapped - this causes problems with ARMv6+
*/
- if (WARN_ON(pfn_valid(pfn)))
- return NULL;
+ if (pfn_valid(pfn)) {
+ printk(KERN_WARNING "BUG: Your driver calls ioremap() on system memory. This leads\n"
+ KERN_WARNING "to architecturally unpredictable behaviour on ARMv6+, and ioremap()\n"
+ KERN_WARNING "will fail in the next kernel release. Please fix your driver.\n");
+ WARN_ON(1);
+ }
type = get_mem_type(mtype);
if (!type)
diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c
index 4f5b39687df5..b0a98305055c 100644
--- a/arch/arm/mm/mmap.c
+++ b/arch/arm/mm/mmap.c
@@ -144,3 +144,25 @@ int valid_mmap_phys_addr_range(unsigned long pfn, size_t size)
{
return !(pfn + (size >> PAGE_SHIFT) > 0x00100000);
}
+
+#ifdef CONFIG_STRICT_DEVMEM
+
+#include <linux/ioport.h>
+
+/*
+ * devmem_is_allowed() checks to see if /dev/mem access to a certain
+ * address is valid. The argument is a physical page number.
+ * We mimic x86 here by disallowing access to system RAM as well as
+ * device-exclusive MMIO regions. This effectively disable read()/write()
+ * on /dev/mem.
+ */
+int devmem_is_allowed(unsigned long pfn)
+{
+ if (iomem_is_exclusive(pfn << PAGE_SHIFT))
+ return 0;
+ if (!page_is_ram(pfn))
+ return 1;
+ return 0;
+}
+
+#endif
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 6a3a2d0cd6db..c32f731d56d3 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -248,7 +248,7 @@ static struct mem_type mem_types[] = {
},
[MT_MEMORY] = {
.prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
- L_PTE_USER | L_PTE_EXEC,
+ L_PTE_WRITE | L_PTE_EXEC,
.prot_l1 = PMD_TYPE_TABLE,
.prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE,
.domain = DOMAIN_KERNEL,
@@ -259,7 +259,7 @@ static struct mem_type mem_types[] = {
},
[MT_MEMORY_NONCACHED] = {
.prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
- L_PTE_USER | L_PTE_EXEC | L_PTE_MT_BUFFERABLE,
+ L_PTE_WRITE | L_PTE_EXEC | L_PTE_MT_BUFFERABLE,
.prot_l1 = PMD_TYPE_TABLE,
.prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE,
.domain = DOMAIN_KERNEL,
@@ -310,9 +310,8 @@ static void __init build_mem_type_table(void)
cachepolicy = CPOLICY_WRITEBACK;
ecc_mask = 0;
}
-#ifdef CONFIG_SMP
- cachepolicy = CPOLICY_WRITEALLOC;
-#endif
+ if (is_smp())
+ cachepolicy = CPOLICY_WRITEALLOC;
/*
* Strip out features not present on earlier architectures.
@@ -406,13 +405,11 @@ static void __init build_mem_type_table(void)
cp = &cache_policies[cachepolicy];
vecs_pgprot = kern_pgprot = user_pgprot = cp->pte;
-#ifndef CONFIG_SMP
/*
* Only use write-through for non-SMP systems
*/
- if (cpu_arch >= CPU_ARCH_ARMv5 && cachepolicy > CPOLICY_WRITETHROUGH)
+ if (!is_smp() && cpu_arch >= CPU_ARCH_ARMv5 && cachepolicy > CPOLICY_WRITETHROUGH)
vecs_pgprot = cache_policies[CPOLICY_WRITETHROUGH].pte;
-#endif
/*
* Enable CPU-specific coherency if supported.
@@ -436,22 +433,23 @@ static void __init build_mem_type_table(void)
mem_types[MT_MINICLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
-#ifdef CONFIG_SMP
- /*
- * Mark memory with the "shared" attribute for SMP systems
- */
- user_pgprot |= L_PTE_SHARED;
- kern_pgprot |= L_PTE_SHARED;
- vecs_pgprot |= L_PTE_SHARED;
- mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_S;
- mem_types[MT_DEVICE_WC].prot_pte |= L_PTE_SHARED;
- mem_types[MT_DEVICE_CACHED].prot_sect |= PMD_SECT_S;
- mem_types[MT_DEVICE_CACHED].prot_pte |= L_PTE_SHARED;
- mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S;
- mem_types[MT_MEMORY].prot_pte |= L_PTE_SHARED;
- mem_types[MT_MEMORY_NONCACHED].prot_sect |= PMD_SECT_S;
- mem_types[MT_MEMORY_NONCACHED].prot_pte |= L_PTE_SHARED;
-#endif
+ if (is_smp()) {
+ /*
+ * Mark memory with the "shared" attribute
+ * for SMP systems
+ */
+ user_pgprot |= L_PTE_SHARED;
+ kern_pgprot |= L_PTE_SHARED;
+ vecs_pgprot |= L_PTE_SHARED;
+ mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_S;
+ mem_types[MT_DEVICE_WC].prot_pte |= L_PTE_SHARED;
+ mem_types[MT_DEVICE_CACHED].prot_sect |= PMD_SECT_S;
+ mem_types[MT_DEVICE_CACHED].prot_pte |= L_PTE_SHARED;
+ mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S;
+ mem_types[MT_MEMORY].prot_pte |= L_PTE_SHARED;
+ mem_types[MT_MEMORY_NONCACHED].prot_sect |= PMD_SECT_S;
+ mem_types[MT_MEMORY_NONCACHED].prot_pte |= L_PTE_SHARED;
+ }
}
/*
@@ -829,8 +827,7 @@ static void __init sanity_check_meminfo(void)
* rather difficult.
*/
reason = "with VIPT aliasing cache";
-#ifdef CONFIG_SMP
- } else if (tlb_ops_need_broadcast()) {
+ } else if (is_smp() && tlb_ops_need_broadcast()) {
/*
* kmap_high needs to occasionally flush TLB entries,
* however, if the TLB entries need to be broadcast
@@ -840,7 +837,6 @@ static void __init sanity_check_meminfo(void)
* (must not be called with irqs off)
*/
reason = "without hardware TLB ops broadcasting";
-#endif
}
if (reason) {
printk(KERN_CRIT "HIGHMEM is not supported %s, ignoring high memory\n",
diff --git a/arch/arm/mm/proc-arm1020.S b/arch/arm/mm/proc-arm1020.S
index 203a4e944d9e..a6f5f8475b96 100644
--- a/arch/arm/mm/proc-arm1020.S
+++ b/arch/arm/mm/proc-arm1020.S
@@ -430,7 +430,7 @@ ENTRY(cpu_arm1020_set_pte_ext)
#endif /* CONFIG_MMU */
mov pc, lr
- __INIT
+ __CPUINIT
.type __arm1020_setup, #function
__arm1020_setup:
diff --git a/arch/arm/mm/proc-arm1020e.S b/arch/arm/mm/proc-arm1020e.S
index 1a511e765909..afc06b9c3133 100644
--- a/arch/arm/mm/proc-arm1020e.S
+++ b/arch/arm/mm/proc-arm1020e.S
@@ -412,7 +412,7 @@ ENTRY(cpu_arm1020e_set_pte_ext)
#endif /* CONFIG_MMU */
mov pc, lr
- __INIT
+ __CPUINIT
.type __arm1020e_setup, #function
__arm1020e_setup:
diff --git a/arch/arm/mm/proc-arm1022.S b/arch/arm/mm/proc-arm1022.S
index 1ffa4eb9c34f..8915e0ba3fe5 100644
--- a/arch/arm/mm/proc-arm1022.S
+++ b/arch/arm/mm/proc-arm1022.S
@@ -394,7 +394,7 @@ ENTRY(cpu_arm1022_set_pte_ext)
#endif /* CONFIG_MMU */
mov pc, lr
- __INIT
+ __CPUINIT
.type __arm1022_setup, #function
__arm1022_setup:
diff --git a/arch/arm/mm/proc-arm1026.S b/arch/arm/mm/proc-arm1026.S
index 5697c34b95b0..ff446c5d476f 100644
--- a/arch/arm/mm/proc-arm1026.S
+++ b/arch/arm/mm/proc-arm1026.S
@@ -384,7 +384,7 @@ ENTRY(cpu_arm1026_set_pte_ext)
mov pc, lr
- __INIT
+ __CPUINIT
.type __arm1026_setup, #function
__arm1026_setup:
diff --git a/arch/arm/mm/proc-arm6_7.S b/arch/arm/mm/proc-arm6_7.S
index 64e0b327c7c5..6a7be1863edd 100644
--- a/arch/arm/mm/proc-arm6_7.S
+++ b/arch/arm/mm/proc-arm6_7.S
@@ -238,7 +238,7 @@ ENTRY(cpu_arm7_reset)
mcr p15, 0, r1, c1, c0, 0 @ turn off MMU etc
mov pc, r0
- __INIT
+ __CPUINIT
.type __arm6_setup, #function
__arm6_setup: mov r0, #0
diff --git a/arch/arm/mm/proc-arm720.S b/arch/arm/mm/proc-arm720.S
index 9d96824134fc..c285395f44b2 100644
--- a/arch/arm/mm/proc-arm720.S
+++ b/arch/arm/mm/proc-arm720.S
@@ -113,7 +113,7 @@ ENTRY(cpu_arm720_reset)
mcr p15, 0, ip, c1, c0, 0 @ ctrl register
mov pc, r0
- __INIT
+ __CPUINIT
.type __arm710_setup, #function
__arm710_setup:
diff --git a/arch/arm/mm/proc-arm740.S b/arch/arm/mm/proc-arm740.S
index 6c1a9ab059ae..38b27dcba727 100644
--- a/arch/arm/mm/proc-arm740.S
+++ b/arch/arm/mm/proc-arm740.S
@@ -55,7 +55,7 @@ ENTRY(cpu_arm740_reset)
mcr p15, 0, ip, c1, c0, 0 @ ctrl register
mov pc, r0
- __INIT
+ __CPUINIT
.type __arm740_setup, #function
__arm740_setup:
diff --git a/arch/arm/mm/proc-arm7tdmi.S b/arch/arm/mm/proc-arm7tdmi.S
index 6a850dbba22e..0c9786de20af 100644
--- a/arch/arm/mm/proc-arm7tdmi.S
+++ b/arch/arm/mm/proc-arm7tdmi.S
@@ -46,7 +46,7 @@ ENTRY(cpu_arm7tdmi_proc_fin)
ENTRY(cpu_arm7tdmi_reset)
mov pc, r0
- __INIT
+ __CPUINIT
.type __arm7tdmi_setup, #function
__arm7tdmi_setup:
diff --git a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S
index 86f80aa56216..fecf570939f3 100644
--- a/arch/arm/mm/proc-arm920.S
+++ b/arch/arm/mm/proc-arm920.S
@@ -375,7 +375,7 @@ ENTRY(cpu_arm920_set_pte_ext)
#endif
mov pc, lr
- __INIT
+ __CPUINIT
.type __arm920_setup, #function
__arm920_setup:
diff --git a/arch/arm/mm/proc-arm922.S b/arch/arm/mm/proc-arm922.S
index f76ce9b62883..e3cbf87c9480 100644
--- a/arch/arm/mm/proc-arm922.S
+++ b/arch/arm/mm/proc-arm922.S
@@ -379,7 +379,7 @@ ENTRY(cpu_arm922_set_pte_ext)
#endif /* CONFIG_MMU */
mov pc, lr
- __INIT
+ __CPUINIT
.type __arm922_setup, #function
__arm922_setup:
diff --git a/arch/arm/mm/proc-arm925.S b/arch/arm/mm/proc-arm925.S
index 657bd3f7c153..572424c867b5 100644
--- a/arch/arm/mm/proc-arm925.S
+++ b/arch/arm/mm/proc-arm925.S
@@ -428,7 +428,7 @@ ENTRY(cpu_arm925_set_pte_ext)
#endif /* CONFIG_MMU */
mov pc, lr
- __INIT
+ __CPUINIT
.type __arm925_setup, #function
__arm925_setup:
diff --git a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S
index 73f1f3c68910..63d168b4ebe6 100644
--- a/arch/arm/mm/proc-arm926.S
+++ b/arch/arm/mm/proc-arm926.S
@@ -389,7 +389,7 @@ ENTRY(cpu_arm926_set_pte_ext)
#endif
mov pc, lr
- __INIT
+ __CPUINIT
.type __arm926_setup, #function
__arm926_setup:
diff --git a/arch/arm/mm/proc-arm940.S b/arch/arm/mm/proc-arm940.S
index fffb061a45a5..f6a62822418e 100644
--- a/arch/arm/mm/proc-arm940.S
+++ b/arch/arm/mm/proc-arm940.S
@@ -264,7 +264,7 @@ ENTRY(arm940_cache_fns)
.long arm940_dma_unmap_area
.long arm940_dma_flush_range
- __INIT
+ __CPUINIT
.type __arm940_setup, #function
__arm940_setup:
diff --git a/arch/arm/mm/proc-arm946.S b/arch/arm/mm/proc-arm946.S
index 249a6053760a..ea2e7f2eb95b 100644
--- a/arch/arm/mm/proc-arm946.S
+++ b/arch/arm/mm/proc-arm946.S
@@ -317,7 +317,7 @@ ENTRY(cpu_arm946_dcache_clean_area)
mcr p15, 0, r0, c7, c10, 4 @ drain WB
mov pc, lr
- __INIT
+ __CPUINIT
.type __arm946_setup, #function
__arm946_setup:
diff --git a/arch/arm/mm/proc-arm9tdmi.S b/arch/arm/mm/proc-arm9tdmi.S
index db475667fac2..db67e3134d7a 100644
--- a/arch/arm/mm/proc-arm9tdmi.S
+++ b/arch/arm/mm/proc-arm9tdmi.S
@@ -46,7 +46,7 @@ ENTRY(cpu_arm9tdmi_proc_fin)
ENTRY(cpu_arm9tdmi_reset)
mov pc, r0
- __INIT
+ __CPUINIT
.type __arm9tdmi_setup, #function
__arm9tdmi_setup:
diff --git a/arch/arm/mm/proc-fa526.S b/arch/arm/mm/proc-fa526.S
index 7803fdf70029..7c9ad621f0e6 100644
--- a/arch/arm/mm/proc-fa526.S
+++ b/arch/arm/mm/proc-fa526.S
@@ -134,7 +134,7 @@ ENTRY(cpu_fa526_set_pte_ext)
#endif
mov pc, lr
- __INIT
+ __CPUINIT
.type __fa526_setup, #function
__fa526_setup:
diff --git a/arch/arm/mm/proc-feroceon.S b/arch/arm/mm/proc-feroceon.S
index b304d0104a4e..578da69200cf 100644
--- a/arch/arm/mm/proc-feroceon.S
+++ b/arch/arm/mm/proc-feroceon.S
@@ -494,7 +494,7 @@ ENTRY(cpu_feroceon_set_pte_ext)
#endif
mov pc, lr
- __INIT
+ __CPUINIT
.type __feroceon_setup, #function
__feroceon_setup:
diff --git a/arch/arm/mm/proc-mohawk.S b/arch/arm/mm/proc-mohawk.S
index 5f6892fcc167..4458ee6aa713 100644
--- a/arch/arm/mm/proc-mohawk.S
+++ b/arch/arm/mm/proc-mohawk.S
@@ -338,7 +338,7 @@ ENTRY(cpu_mohawk_set_pte_ext)
mcr p15, 0, r0, c7, c10, 4 @ drain WB
mov pc, lr
- __INIT
+ __CPUINIT
.type __mohawk_setup, #function
__mohawk_setup:
diff --git a/arch/arm/mm/proc-sa110.S b/arch/arm/mm/proc-sa110.S
index a201eb04b5e1..5aa8d59c2e85 100644
--- a/arch/arm/mm/proc-sa110.S
+++ b/arch/arm/mm/proc-sa110.S
@@ -156,7 +156,7 @@ ENTRY(cpu_sa110_set_pte_ext)
#endif
mov pc, lr
- __INIT
+ __CPUINIT
.type __sa110_setup, #function
__sa110_setup:
diff --git a/arch/arm/mm/proc-sa1100.S b/arch/arm/mm/proc-sa1100.S
index 7ddc4805bf97..2ac4e6f10713 100644
--- a/arch/arm/mm/proc-sa1100.S
+++ b/arch/arm/mm/proc-sa1100.S
@@ -169,7 +169,7 @@ ENTRY(cpu_sa1100_set_pte_ext)
#endif
mov pc, lr
- __INIT
+ __CPUINIT
.type __sa1100_setup, #function
__sa1100_setup:
diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S
index 22aac8515196..59a7e1ffe7bc 100644
--- a/arch/arm/mm/proc-v6.S
+++ b/arch/arm/mm/proc-v6.S
@@ -30,13 +30,10 @@
#define TTB_RGN_WT (2 << 3)
#define TTB_RGN_WB (3 << 3)
-#ifndef CONFIG_SMP
-#define TTB_FLAGS TTB_RGN_WBWA
-#define PMD_FLAGS PMD_SECT_WB
-#else
-#define TTB_FLAGS TTB_RGN_WBWA|TTB_S
-#define PMD_FLAGS PMD_SECT_WBWA|PMD_SECT_S
-#endif
+#define TTB_FLAGS_UP TTB_RGN_WBWA
+#define PMD_FLAGS_UP PMD_SECT_WB
+#define TTB_FLAGS_SMP TTB_RGN_WBWA|TTB_S
+#define PMD_FLAGS_SMP PMD_SECT_WBWA|PMD_SECT_S
ENTRY(cpu_v6_proc_init)
mov pc, lr
@@ -97,7 +94,8 @@ ENTRY(cpu_v6_switch_mm)
#ifdef CONFIG_MMU
mov r2, #0
ldr r1, [r1, #MM_CONTEXT_ID] @ get mm->context.id
- orr r0, r0, #TTB_FLAGS
+ ALT_SMP(orr r0, r0, #TTB_FLAGS_SMP)
+ ALT_UP(orr r0, r0, #TTB_FLAGS_UP)
mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB
mcr p15, 0, r2, c7, c10, 4 @ drain write buffer
mcr p15, 0, r0, c2, c0, 0 @ set TTB 0
@@ -137,7 +135,7 @@ cpu_pj4_name:
.align
- __INIT
+ __CPUINIT
/*
* __v6_setup
@@ -156,9 +154,11 @@ cpu_pj4_name:
*/
__v6_setup:
#ifdef CONFIG_SMP
- mrc p15, 0, r0, c1, c0, 1 @ Enable SMP/nAMP mode
+ ALT_SMP(mrc p15, 0, r0, c1, c0, 1) @ Enable SMP/nAMP mode
+ ALT_UP(nop)
orr r0, r0, #0x20
- mcr p15, 0, r0, c1, c0, 1
+ ALT_SMP(mcr p15, 0, r0, c1, c0, 1)
+ ALT_UP(nop)
#endif
mov r0, #0
@@ -169,7 +169,8 @@ __v6_setup:
#ifdef CONFIG_MMU
mcr p15, 0, r0, c8, c7, 0 @ invalidate I + D TLBs
mcr p15, 0, r0, c2, c0, 2 @ TTB control register
- orr r4, r4, #TTB_FLAGS
+ ALT_SMP(orr r4, r4, #TTB_FLAGS_SMP)
+ ALT_UP(orr r4, r4, #TTB_FLAGS_UP)
mcr p15, 0, r4, c2, c0, 1 @ load TTB1
#endif /* CONFIG_MMU */
adr r5, v6_crval
@@ -192,6 +193,8 @@ __v6_setup:
v6_crval:
crval clear=0x01e0fb7f, mmuset=0x00c0387d, ucset=0x00c0187c
+ __INITDATA
+
.type v6_processor_functions, #object
ENTRY(v6_processor_functions)
.word v6_early_abort
@@ -205,6 +208,8 @@ ENTRY(v6_processor_functions)
.word cpu_v6_set_pte_ext
.size v6_processor_functions, . - v6_processor_functions
+ .section ".rodata"
+
.type cpu_arch_name, #object
cpu_arch_name:
.asciz "armv6"
@@ -225,10 +230,16 @@ cpu_elf_name:
__v6_proc_info:
.long 0x0007b000
.long 0x0007f000
- .long PMD_TYPE_SECT | \
+ ALT_SMP(.long \
+ PMD_TYPE_SECT | \
PMD_SECT_AP_WRITE | \
PMD_SECT_AP_READ | \
- PMD_FLAGS
+ PMD_FLAGS_SMP)
+ ALT_UP(.long \
+ PMD_TYPE_SECT | \
+ PMD_SECT_AP_WRITE | \
+ PMD_SECT_AP_READ | \
+ PMD_FLAGS_UP)
.long PMD_TYPE_SECT | \
PMD_SECT_XN | \
PMD_SECT_AP_WRITE | \
@@ -249,10 +260,16 @@ __v6_proc_info:
__pj4_v6_proc_info:
.long 0x560f5810
.long 0xff0ffff0
- .long PMD_TYPE_SECT | \
+ ALT_SMP(.long \
+ PMD_TYPE_SECT | \
+ PMD_SECT_AP_WRITE | \
+ PMD_SECT_AP_READ | \
+ PMD_FLAGS_SMP)
+ ALT_UP(.long \
+ PMD_TYPE_SECT | \
PMD_SECT_AP_WRITE | \
PMD_SECT_AP_READ | \
- PMD_FLAGS
+ PMD_FLAGS_UP)
.long PMD_TYPE_SECT | \
PMD_SECT_XN | \
PMD_SECT_AP_WRITE | \
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index 7563ff0141bd..53cbe2225153 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -30,15 +30,13 @@
#define TTB_IRGN_WT ((1 << 0) | (0 << 6))
#define TTB_IRGN_WB ((1 << 0) | (1 << 6))
-#ifndef CONFIG_SMP
/* PTWs cacheable, inner WB not shareable, outer WB not shareable */
-#define TTB_FLAGS TTB_IRGN_WB|TTB_RGN_OC_WB
-#define PMD_FLAGS PMD_SECT_WB
-#else
+#define TTB_FLAGS_UP TTB_IRGN_WB|TTB_RGN_OC_WB
+#define PMD_FLAGS_UP PMD_SECT_WB
+
/* PTWs cacheable, inner WBWA shareable, outer WBWA not shareable */
-#define TTB_FLAGS TTB_IRGN_WBWA|TTB_S|TTB_NOS|TTB_RGN_OC_WBWA
-#define PMD_FLAGS PMD_SECT_WBWA|PMD_SECT_S
-#endif
+#define TTB_FLAGS_SMP TTB_IRGN_WBWA|TTB_S|TTB_NOS|TTB_RGN_OC_WBWA
+#define PMD_FLAGS_SMP PMD_SECT_WBWA|PMD_SECT_S
ENTRY(cpu_v7_proc_init)
mov pc, lr
@@ -105,7 +103,8 @@ ENTRY(cpu_v7_switch_mm)
#ifdef CONFIG_MMU
mov r2, #0
ldr r1, [r1, #MM_CONTEXT_ID] @ get mm->context.id
- orr r0, r0, #TTB_FLAGS
+ ALT_SMP(orr r0, r0, #TTB_FLAGS_SMP)
+ ALT_UP(orr r0, r0, #TTB_FLAGS_UP)
#ifdef CONFIG_ARM_ERRATA_430973
mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB
#endif
@@ -169,7 +168,7 @@ cpu_v7_name:
.ascii "ARMv7 Processor"
.align
- __INIT
+ __CPUINIT
/*
* __v7_setup
@@ -188,7 +187,8 @@ cpu_v7_name:
*/
__v7_ca9mp_setup:
#ifdef CONFIG_SMP
- mrc p15, 0, r0, c1, c0, 1
+ ALT_SMP(mrc p15, 0, r0, c1, c0, 1)
+ ALT_UP(mov r0, #(1 << 6)) @ fake it for UP
tst r0, #(1 << 6) @ SMP/nAMP mode enabled?
orreq r0, r0, #(1 << 6) | (1 << 0) @ Enable SMP/nAMP mode and
mcreq p15, 0, r0, c1, c0, 1 @ TLB ops broadcasting
@@ -253,6 +253,14 @@ __v7_setup:
orreq r10, r10, #1 << 22 @ set bit #22
mcreq p15, 0, r10, c15, c0, 1 @ write diagnostic register
#endif
+#ifdef CONFIG_ARM_ERRATA_743622
+ teq r6, #0x20 @ present in r2p0
+ teqne r6, #0x21 @ present in r2p1
+ teqne r6, #0x22 @ present in r2p2
+ mrceq p15, 0, r10, c15, c0, 1 @ read diagnostic register
+ orreq r10, r10, #1 << 6 @ set bit #6
+ mcreq p15, 0, r10, c15, c0, 1 @ write diagnostic register
+#endif
3: mov r10, #0
#ifdef HARVARD_CACHE
@@ -262,7 +270,8 @@ __v7_setup:
#ifdef CONFIG_MMU
mcr p15, 0, r10, c8, c7, 0 @ invalidate I + D TLBs
mcr p15, 0, r10, c2, c0, 2 @ TTB control register
- orr r4, r4, #TTB_FLAGS
+ ALT_SMP(orr r4, r4, #TTB_FLAGS_SMP)
+ ALT_UP(orr r4, r4, #TTB_FLAGS_UP)
mcr p15, 0, r4, c2, c0, 1 @ load TTB1
mov r10, #0x1f @ domains 0, 1 = manager
mcr p15, 0, r10, c3, c0, 0 @ load domain access register
@@ -324,6 +333,8 @@ v7_crval:
__v7_setup_stack:
.space 4 * 11 @ 11 registers
+ __INITDATA
+
.type v7_processor_functions, #object
ENTRY(v7_processor_functions)
.word v7_early_abort
@@ -337,6 +348,8 @@ ENTRY(v7_processor_functions)
.word cpu_v7_set_pte_ext
.size v7_processor_functions, . - v7_processor_functions
+ .section ".rodata"
+
.type cpu_arch_name, #object
cpu_arch_name:
.asciz "armv7"
@@ -354,10 +367,16 @@ cpu_elf_name:
__v7_ca9mp_proc_info:
.long 0x410fc090 @ Required ID value
.long 0xff0ffff0 @ Mask for ID
- .long PMD_TYPE_SECT | \
+ ALT_SMP(.long \
+ PMD_TYPE_SECT | \
+ PMD_SECT_AP_WRITE | \
+ PMD_SECT_AP_READ | \
+ PMD_FLAGS_SMP)
+ ALT_UP(.long \
+ PMD_TYPE_SECT | \
PMD_SECT_AP_WRITE | \
PMD_SECT_AP_READ | \
- PMD_FLAGS
+ PMD_FLAGS_UP)
.long PMD_TYPE_SECT | \
PMD_SECT_XN | \
PMD_SECT_AP_WRITE | \
@@ -365,7 +384,7 @@ __v7_ca9mp_proc_info:
b __v7_ca9mp_setup
.long cpu_arch_name
.long cpu_elf_name
- .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
+ .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_TLS
.long cpu_v7_name
.long v7_processor_functions
.long v7wbi_tlb_fns
@@ -380,10 +399,16 @@ __v7_ca9mp_proc_info:
__v7_proc_info:
.long 0x000f0000 @ Required ID value
.long 0x000f0000 @ Mask for ID
- .long PMD_TYPE_SECT | \
+ ALT_SMP(.long \
+ PMD_TYPE_SECT | \
+ PMD_SECT_AP_WRITE | \
+ PMD_SECT_AP_READ | \
+ PMD_FLAGS_SMP)
+ ALT_UP(.long \
+ PMD_TYPE_SECT | \
PMD_SECT_AP_WRITE | \
PMD_SECT_AP_READ | \
- PMD_FLAGS
+ PMD_FLAGS_UP)
.long PMD_TYPE_SECT | \
PMD_SECT_XN | \
PMD_SECT_AP_WRITE | \
diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S
index 361a51e49030..cad07e403044 100644
--- a/arch/arm/mm/proc-xsc3.S
+++ b/arch/arm/mm/proc-xsc3.S
@@ -404,7 +404,7 @@ ENTRY(cpu_xsc3_set_pte_ext)
.align
- __INIT
+ __CPUINIT
.type __xsc3_setup, #function
__xsc3_setup:
diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S
index 14075979bcba..cb245edb2c2b 100644
--- a/arch/arm/mm/proc-xscale.S
+++ b/arch/arm/mm/proc-xscale.S
@@ -506,7 +506,7 @@ ENTRY(cpu_xscale_set_pte_ext)
.align
- __INIT
+ __CPUINIT
.type __xscale_setup, #function
__xscale_setup:
diff --git a/arch/arm/mm/tlb-v7.S b/arch/arm/mm/tlb-v7.S
index f3f288a9546d..53cd5b454673 100644
--- a/arch/arm/mm/tlb-v7.S
+++ b/arch/arm/mm/tlb-v7.S
@@ -13,6 +13,7 @@
*/
#include <linux/init.h>
#include <linux/linkage.h>
+#include <asm/assembler.h>
#include <asm/asm-offsets.h>
#include <asm/page.h>
#include <asm/tlbflush.h>
@@ -41,20 +42,15 @@ ENTRY(v7wbi_flush_user_tlb_range)
orr r0, r3, r0, lsl #PAGE_SHIFT @ Create initial MVA
mov r1, r1, lsl #PAGE_SHIFT
1:
-#ifdef CONFIG_SMP
- mcr p15, 0, r0, c8, c3, 1 @ TLB invalidate U MVA (shareable)
-#else
- mcr p15, 0, r0, c8, c7, 1 @ TLB invalidate U MVA
-#endif
+ ALT_SMP(mcr p15, 0, r0, c8, c3, 1) @ TLB invalidate U MVA (shareable)
+ ALT_UP(mcr p15, 0, r0, c8, c7, 1) @ TLB invalidate U MVA
+
add r0, r0, #PAGE_SZ
cmp r0, r1
blo 1b
mov ip, #0
-#ifdef CONFIG_SMP
- mcr p15, 0, ip, c7, c1, 6 @ flush BTAC/BTB Inner Shareable
-#else
- mcr p15, 0, ip, c7, c5, 6 @ flush BTAC/BTB
-#endif
+ ALT_SMP(mcr p15, 0, ip, c7, c1, 6) @ flush BTAC/BTB Inner Shareable
+ ALT_UP(mcr p15, 0, ip, c7, c5, 6) @ flush BTAC/BTB
dsb
mov pc, lr
ENDPROC(v7wbi_flush_user_tlb_range)
@@ -74,20 +70,14 @@ ENTRY(v7wbi_flush_kern_tlb_range)
mov r0, r0, lsl #PAGE_SHIFT
mov r1, r1, lsl #PAGE_SHIFT
1:
-#ifdef CONFIG_SMP
- mcr p15, 0, r0, c8, c3, 1 @ TLB invalidate U MVA (shareable)
-#else
- mcr p15, 0, r0, c8, c7, 1 @ TLB invalidate U MVA
-#endif
+ ALT_SMP(mcr p15, 0, r0, c8, c3, 1) @ TLB invalidate U MVA (shareable)
+ ALT_UP(mcr p15, 0, r0, c8, c7, 1) @ TLB invalidate U MVA
add r0, r0, #PAGE_SZ
cmp r0, r1
blo 1b
mov r2, #0
-#ifdef CONFIG_SMP
- mcr p15, 0, r2, c7, c1, 6 @ flush BTAC/BTB Inner Shareable
-#else
- mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB
-#endif
+ ALT_SMP(mcr p15, 0, r2, c7, c1, 6) @ flush BTAC/BTB Inner Shareable
+ ALT_UP(mcr p15, 0, r2, c7, c5, 6) @ flush BTAC/BTB
dsb
isb
mov pc, lr
@@ -99,5 +89,6 @@ ENDPROC(v7wbi_flush_kern_tlb_range)
ENTRY(v7wbi_tlb_fns)
.long v7wbi_flush_user_tlb_range
.long v7wbi_flush_kern_tlb_range
- .long v7wbi_tlb_flags
+ ALT_SMP(.long v7wbi_tlb_flags_smp)
+ ALT_UP(.long v7wbi_tlb_flags_up)
.size v7wbi_tlb_fns, . - v7wbi_tlb_fns
diff --git a/arch/arm/oprofile/Makefile b/arch/arm/oprofile/Makefile
index e666eafed152..b2215c61cdf0 100644
--- a/arch/arm/oprofile/Makefile
+++ b/arch/arm/oprofile/Makefile
@@ -6,4 +6,8 @@ DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \
oprofilefs.o oprofile_stats.o \
timer_int.o )
+ifeq ($(CONFIG_HW_PERF_EVENTS),y)
+DRIVER_OBJS += $(addprefix ../../../drivers/oprofile/, oprofile_perf.o)
+endif
+
oprofile-y := $(DRIVER_OBJS) common.o
diff --git a/arch/arm/oprofile/common.c b/arch/arm/oprofile/common.c
index 0691176899ff..8aa974491dfc 100644
--- a/arch/arm/oprofile/common.c
+++ b/arch/arm/oprofile/common.c
@@ -25,138 +25,10 @@
#include <asm/ptrace.h>
#ifdef CONFIG_HW_PERF_EVENTS
-/*
- * Per performance monitor configuration as set via oprofilefs.
- */
-struct op_counter_config {
- unsigned long count;
- unsigned long enabled;
- unsigned long event;
- unsigned long unit_mask;
- unsigned long kernel;
- unsigned long user;
- struct perf_event_attr attr;
-};
-
-static int op_arm_enabled;
-static DEFINE_MUTEX(op_arm_mutex);
-
-static struct op_counter_config *counter_config;
-static struct perf_event **perf_events[nr_cpumask_bits];
-static int perf_num_counters;
-
-/*
- * Overflow callback for oprofile.
- */
-static void op_overflow_handler(struct perf_event *event, int unused,
- struct perf_sample_data *data, struct pt_regs *regs)
-{
- int id;
- u32 cpu = smp_processor_id();
-
- for (id = 0; id < perf_num_counters; ++id)
- if (perf_events[cpu][id] == event)
- break;
-
- if (id != perf_num_counters)
- oprofile_add_sample(regs, id);
- else
- pr_warning("oprofile: ignoring spurious overflow "
- "on cpu %u\n", cpu);
-}
-
-/*
- * Called by op_arm_setup to create perf attributes to mirror the oprofile
- * settings in counter_config. Attributes are created as `pinned' events and
- * so are permanently scheduled on the PMU.
- */
-static void op_perf_setup(void)
-{
- int i;
- u32 size = sizeof(struct perf_event_attr);
- struct perf_event_attr *attr;
-
- for (i = 0; i < perf_num_counters; ++i) {
- attr = &counter_config[i].attr;
- memset(attr, 0, size);
- attr->type = PERF_TYPE_RAW;
- attr->size = size;
- attr->config = counter_config[i].event;
- attr->sample_period = counter_config[i].count;
- attr->pinned = 1;
- }
-}
-
-static int op_create_counter(int cpu, int event)
-{
- int ret = 0;
- struct perf_event *pevent;
-
- if (!counter_config[event].enabled || (perf_events[cpu][event] != NULL))
- return ret;
-
- pevent = perf_event_create_kernel_counter(&counter_config[event].attr,
- cpu, -1,
- op_overflow_handler);
-
- if (IS_ERR(pevent)) {
- ret = PTR_ERR(pevent);
- } else if (pevent->state != PERF_EVENT_STATE_ACTIVE) {
- pr_warning("oprofile: failed to enable event %d "
- "on CPU %d\n", event, cpu);
- ret = -EBUSY;
- } else {
- perf_events[cpu][event] = pevent;
- }
-
- return ret;
-}
-
-static void op_destroy_counter(int cpu, int event)
-{
- struct perf_event *pevent = perf_events[cpu][event];
-
- if (pevent) {
- perf_event_release_kernel(pevent);
- perf_events[cpu][event] = NULL;
- }
-}
-
-/*
- * Called by op_arm_start to create active perf events based on the
- * perviously configured attributes.
- */
-static int op_perf_start(void)
-{
- int cpu, event, ret = 0;
-
- for_each_online_cpu(cpu) {
- for (event = 0; event < perf_num_counters; ++event) {
- ret = op_create_counter(cpu, event);
- if (ret)
- goto out;
- }
- }
-
-out:
- return ret;
-}
-
-/*
- * Called by op_arm_stop at the end of a profiling run.
- */
-static void op_perf_stop(void)
+char *op_name_from_perf_id(void)
{
- int cpu, event;
+ enum arm_perf_pmu_ids id = armpmu_get_pmu_id();
- for_each_online_cpu(cpu)
- for (event = 0; event < perf_num_counters; ++event)
- op_destroy_counter(cpu, event);
-}
-
-
-static char *op_name_from_perf_id(enum arm_perf_pmu_ids id)
-{
switch (id) {
case ARM_PERF_PMU_ID_XSCALE1:
return "arm/xscale1";
@@ -175,116 +47,6 @@ static char *op_name_from_perf_id(enum arm_perf_pmu_ids id)
}
}
-static int op_arm_create_files(struct super_block *sb, struct dentry *root)
-{
- unsigned int i;
-
- for (i = 0; i < perf_num_counters; i++) {
- struct dentry *dir;
- char buf[4];
-
- snprintf(buf, sizeof buf, "%d", i);
- dir = oprofilefs_mkdir(sb, root, buf);
- oprofilefs_create_ulong(sb, dir, "enabled", &counter_config[i].enabled);
- oprofilefs_create_ulong(sb, dir, "event", &counter_config[i].event);
- oprofilefs_create_ulong(sb, dir, "count", &counter_config[i].count);
- oprofilefs_create_ulong(sb, dir, "unit_mask", &counter_config[i].unit_mask);
- oprofilefs_create_ulong(sb, dir, "kernel", &counter_config[i].kernel);
- oprofilefs_create_ulong(sb, dir, "user", &counter_config[i].user);
- }
-
- return 0;
-}
-
-static int op_arm_setup(void)
-{
- spin_lock(&oprofilefs_lock);
- op_perf_setup();
- spin_unlock(&oprofilefs_lock);
- return 0;
-}
-
-static int op_arm_start(void)
-{
- int ret = -EBUSY;
-
- mutex_lock(&op_arm_mutex);
- if (!op_arm_enabled) {
- ret = 0;
- op_perf_start();
- op_arm_enabled = 1;
- }
- mutex_unlock(&op_arm_mutex);
- return ret;
-}
-
-static void op_arm_stop(void)
-{
- mutex_lock(&op_arm_mutex);
- if (op_arm_enabled)
- op_perf_stop();
- op_arm_enabled = 0;
- mutex_unlock(&op_arm_mutex);
-}
-
-#ifdef CONFIG_PM
-static int op_arm_suspend(struct platform_device *dev, pm_message_t state)
-{
- mutex_lock(&op_arm_mutex);
- if (op_arm_enabled)
- op_perf_stop();
- mutex_unlock(&op_arm_mutex);
- return 0;
-}
-
-static int op_arm_resume(struct platform_device *dev)
-{
- mutex_lock(&op_arm_mutex);
- if (op_arm_enabled && op_perf_start())
- op_arm_enabled = 0;
- mutex_unlock(&op_arm_mutex);
- return 0;
-}
-
-static struct platform_driver oprofile_driver = {
- .driver = {
- .name = "arm-oprofile",
- },
- .resume = op_arm_resume,
- .suspend = op_arm_suspend,
-};
-
-static struct platform_device *oprofile_pdev;
-
-static int __init init_driverfs(void)
-{
- int ret;
-
- ret = platform_driver_register(&oprofile_driver);
- if (ret)
- goto out;
-
- oprofile_pdev = platform_device_register_simple(
- oprofile_driver.driver.name, 0, NULL, 0);
- if (IS_ERR(oprofile_pdev)) {
- ret = PTR_ERR(oprofile_pdev);
- platform_driver_unregister(&oprofile_driver);
- }
-
-out:
- return ret;
-}
-
-static void exit_driverfs(void)
-{
- platform_device_unregister(oprofile_pdev);
- platform_driver_unregister(&oprofile_driver);
-}
-#else
-static int __init init_driverfs(void) { return 0; }
-#define exit_driverfs() do { } while (0)
-#endif /* CONFIG_PM */
-
static int report_trace(struct stackframe *frame, void *d)
{
unsigned int *depth = d;
@@ -349,72 +111,14 @@ static void arm_backtrace(struct pt_regs * const regs, unsigned int depth)
int __init oprofile_arch_init(struct oprofile_operations *ops)
{
- int cpu, ret = 0;
-
- perf_num_counters = armpmu_get_max_events();
-
- counter_config = kcalloc(perf_num_counters,
- sizeof(struct op_counter_config), GFP_KERNEL);
-
- if (!counter_config) {
- pr_info("oprofile: failed to allocate %d "
- "counters\n", perf_num_counters);
- return -ENOMEM;
- }
-
- ret = init_driverfs();
- if (ret) {
- kfree(counter_config);
- return ret;
- }
-
- for_each_possible_cpu(cpu) {
- perf_events[cpu] = kcalloc(perf_num_counters,
- sizeof(struct perf_event *), GFP_KERNEL);
- if (!perf_events[cpu]) {
- pr_info("oprofile: failed to allocate %d perf events "
- "for cpu %d\n", perf_num_counters, cpu);
- while (--cpu >= 0)
- kfree(perf_events[cpu]);
- return -ENOMEM;
- }
- }
-
ops->backtrace = arm_backtrace;
- ops->create_files = op_arm_create_files;
- ops->setup = op_arm_setup;
- ops->start = op_arm_start;
- ops->stop = op_arm_stop;
- ops->shutdown = op_arm_stop;
- ops->cpu_type = op_name_from_perf_id(armpmu_get_pmu_id());
-
- if (!ops->cpu_type)
- ret = -ENODEV;
- else
- pr_info("oprofile: using %s\n", ops->cpu_type);
- return ret;
+ return oprofile_perf_init(ops);
}
-void oprofile_arch_exit(void)
+void __exit oprofile_arch_exit(void)
{
- int cpu, id;
- struct perf_event *event;
-
- if (*perf_events) {
- exit_driverfs();
- for_each_possible_cpu(cpu) {
- for (id = 0; id < perf_num_counters; ++id) {
- event = perf_events[cpu][id];
- if (event != NULL)
- perf_event_release_kernel(event);
- }
- kfree(perf_events[cpu]);
- }
- }
-
- if (counter_config)
- kfree(counter_config);
+ oprofile_perf_exit();
}
#else
int __init oprofile_arch_init(struct oprofile_operations *ops)
@@ -422,5 +126,5 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
pr_info("oprofile: hardware counters not available\n");
return -ENODEV;
}
-void oprofile_arch_exit(void) {}
+void __exit oprofile_arch_exit(void) {}
#endif /* CONFIG_HW_PERF_EVENTS */
diff --git a/arch/arm/plat-mxc/Kconfig b/arch/arm/plat-mxc/Kconfig
index 6785db4179b8..64e3a64520e0 100644
--- a/arch/arm/plat-mxc/Kconfig
+++ b/arch/arm/plat-mxc/Kconfig
@@ -92,6 +92,18 @@ config MXC_DEBUG_BOARD
data/address de-multiplexing and decode, signal level shift,
interrupt control and various board functions.
+config HAVE_EPIT
+ bool
+
+config MXC_USE_EPIT
+ bool "Use EPIT instead of GPT"
+ depends on HAVE_EPIT
+ help
+ Use EPIT as the system timer on systems that have it. Normally you
+ don't have a reason to do so as the EPIT has the same features and
+ uses the same clocks as the GPT. Anyway, on some systems the GPT
+ may be in use for other purposes.
+
config MXC_ULPI
bool
@@ -110,4 +122,8 @@ config ARCH_MXC_AUDMUX_V1
config ARCH_MXC_AUDMUX_V2
bool
+config IRAM_ALLOC
+ bool
+ select GENERIC_ALLOCATOR
+
endif
diff --git a/arch/arm/plat-mxc/Makefile b/arch/arm/plat-mxc/Makefile
index 78d405ed8616..06875b4dd70f 100644
--- a/arch/arm/plat-mxc/Makefile
+++ b/arch/arm/plat-mxc/Makefile
@@ -10,9 +10,11 @@ obj-$(CONFIG_MXC_TZIC) += tzic.o
obj-$(CONFIG_IMX_HAVE_IOMUX_V1) += iomux-v1.o
obj-$(CONFIG_ARCH_MXC_IOMUX_V3) += iomux-v3.o
+obj-$(CONFIG_IRAM_ALLOC) += iram_alloc.o
obj-$(CONFIG_MXC_PWM) += pwm.o
obj-$(CONFIG_USB_EHCI_MXC) += ehci.o
obj-$(CONFIG_MXC_ULPI) += ulpi.o
+obj-$(CONFIG_MXC_USE_EPIT) += epit.o
obj-$(CONFIG_ARCH_MXC_AUDMUX_V1) += audmux-v1.o
obj-$(CONFIG_ARCH_MXC_AUDMUX_V2) += audmux-v2.o
obj-$(CONFIG_MXC_DEBUG_BOARD) += 3ds_debugboard.o
diff --git a/arch/arm/plat-mxc/audmux-v2.c b/arch/arm/plat-mxc/audmux-v2.c
index f9e7cdbd0005..0be1ac7f421b 100644
--- a/arch/arm/plat-mxc/audmux-v2.c
+++ b/arch/arm/plat-mxc/audmux-v2.c
@@ -137,6 +137,7 @@ static ssize_t audmux_read_file(struct file *file, char __user *user_buf,
static const struct file_operations audmux_debugfs_fops = {
.open = audmux_open_file,
.read = audmux_read_file,
+ .llseek = default_llseek,
};
static void audmux_debugfs_init(void)
@@ -186,7 +187,13 @@ EXPORT_SYMBOL_GPL(mxc_audmux_v2_configure_port);
static int mxc_audmux_v2_init(void)
{
int ret;
-
+#if defined(CONFIG_ARCH_MX5)
+ if (cpu_is_mx51()) {
+ audmux_base = MX51_IO_ADDRESS(MX51_AUDMUX_BASE_ADDR);
+ ret = 0;
+ return ret;
+ }
+#endif
#if defined(CONFIG_ARCH_MX3)
if (cpu_is_mx31())
audmux_base = MX31_IO_ADDRESS(MX31_AUDMUX_BASE_ADDR);
diff --git a/arch/arm/plat-mxc/devices/Kconfig b/arch/arm/plat-mxc/devices/Kconfig
index 9ab784b776f9..404799487f17 100644
--- a/arch/arm/plat-mxc/devices/Kconfig
+++ b/arch/arm/plat-mxc/devices/Kconfig
@@ -1,3 +1,10 @@
+config IMX_HAVE_PLATFORM_ESDHC
+ bool
+
+config IMX_HAVE_PLATFORM_FEC
+ bool
+ default y if ARCH_MX25 || SOC_IMX27 || ARCH_MX35 || ARCH_MX51
+
config IMX_HAVE_PLATFORM_FLEXCAN
select HAVE_CAN_FLEXCAN
bool
@@ -5,6 +12,9 @@ config IMX_HAVE_PLATFORM_FLEXCAN
config IMX_HAVE_PLATFORM_IMX_I2C
bool
+config IMX_HAVE_PLATFORM_IMX_SSI
+ bool
+
config IMX_HAVE_PLATFORM_IMX_UART
bool
diff --git a/arch/arm/plat-mxc/devices/Makefile b/arch/arm/plat-mxc/devices/Makefile
index 347da5161f7e..0a3c1f089413 100644
--- a/arch/arm/plat-mxc/devices/Makefile
+++ b/arch/arm/plat-mxc/devices/Makefile
@@ -1,8 +1,9 @@
-ifdef CONFIG_CAN_FLEXCAN
-# the ifdef can be removed once the flexcan driver has been merged
-obj-$(CONFIG_IMX_HAVE_PLATFORM_FLEXCAN) += platform-flexcan.o
-endif
+obj-$(CONFIG_IMX_HAVE_PLATFORM_ESDHC) += platform-esdhc.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_FEC) += platform-fec.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_FLEXCAN) += platform-flexcan.o
+obj-y += platform-imx-dma.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_I2C) += platform-imx-i2c.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_SSI) += platform-imx-ssi.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_UART) += platform-imx-uart.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_NAND) += platform-mxc_nand.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_SPI_IMX) += platform-spi_imx.o
diff --git a/arch/arm/plat-mxc/devices/platform-esdhc.c b/arch/arm/plat-mxc/devices/platform-esdhc.c
new file mode 100644
index 000000000000..2605bfa0dfb0
--- /dev/null
+++ b/arch/arm/plat-mxc/devices/platform-esdhc.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2010 Pengutronix, Wolfram Sang <w.sang@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+
+#include <mach/hardware.h>
+#include <mach/devices-common.h>
+#include <mach/esdhc.h>
+
+#define imx_esdhc_imx_data_entry_single(soc, _id, hwid) \
+ { \
+ .id = _id, \
+ .iobase = soc ## _ESDHC ## hwid ## _BASE_ADDR, \
+ .irq = soc ## _INT_ESDHC ## hwid, \
+ }
+
+#define imx_esdhc_imx_data_entry(soc, id, hwid) \
+ [id] = imx_esdhc_imx_data_entry_single(soc, id, hwid)
+
+#ifdef CONFIG_ARCH_MX25
+const struct imx_esdhc_imx_data imx25_esdhc_data[] __initconst = {
+#define imx25_esdhc_data_entry(_id, _hwid) \
+ imx_esdhc_imx_data_entry(MX25, _id, _hwid)
+ imx25_esdhc_data_entry(0, 1),
+ imx25_esdhc_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_ARCH_MX25 */
+
+#ifdef CONFIG_ARCH_MX35
+const struct imx_esdhc_imx_data imx35_esdhc_data[] __initconst = {
+#define imx35_esdhc_data_entry(_id, _hwid) \
+ imx_esdhc_imx_data_entry(MX35, _id, _hwid)
+ imx35_esdhc_data_entry(0, 1),
+ imx35_esdhc_data_entry(1, 2),
+ imx35_esdhc_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_ARCH_MX35 */
+
+#ifdef CONFIG_ARCH_MX51
+const struct imx_esdhc_imx_data imx51_esdhc_data[] __initconst = {
+#define imx51_esdhc_data_entry(_id, _hwid) \
+ imx_esdhc_imx_data_entry(MX51, _id, _hwid)
+ imx51_esdhc_data_entry(0, 1),
+ imx51_esdhc_data_entry(1, 2),
+ imx51_esdhc_data_entry(2, 3),
+ imx51_esdhc_data_entry(3, 4),
+};
+#endif /* ifdef CONFIG_ARCH_MX51 */
+
+struct platform_device *__init imx_add_esdhc(
+ const struct imx_esdhc_imx_data *data,
+ const struct esdhc_platform_data *pdata)
+{
+ struct resource res[] = {
+ {
+ .start = data->iobase,
+ .end = data->iobase + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = data->irq,
+ .end = data->irq,
+ .flags = IORESOURCE_IRQ,
+ },
+ };
+
+ return imx_add_platform_device("sdhci-esdhc-imx", data->id, res,
+ ARRAY_SIZE(res), pdata, sizeof(*pdata));
+}
diff --git a/arch/arm/plat-mxc/devices/platform-fec.c b/arch/arm/plat-mxc/devices/platform-fec.c
new file mode 100644
index 000000000000..11d087f4e219
--- /dev/null
+++ b/arch/arm/plat-mxc/devices/platform-fec.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include <asm/sizes.h>
+#include <mach/hardware.h>
+#include <mach/devices-common.h>
+
+#define imx_fec_data_entry_single(soc) \
+ { \
+ .iobase = soc ## _FEC_BASE_ADDR, \
+ .irq = soc ## _INT_FEC, \
+ }
+
+#ifdef CONFIG_ARCH_MX25
+const struct imx_fec_data imx25_fec_data __initconst =
+ imx_fec_data_entry_single(MX25);
+#endif /* ifdef CONFIG_ARCH_MX25 */
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_fec_data imx27_fec_data __initconst =
+ imx_fec_data_entry_single(MX27);
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+#ifdef CONFIG_ARCH_MX35
+const struct imx_fec_data imx35_fec_data __initconst =
+ imx_fec_data_entry_single(MX35);
+#endif
+
+#ifdef CONFIG_ARCH_MX51
+const struct imx_fec_data imx51_fec_data __initconst =
+ imx_fec_data_entry_single(MX51);
+#endif
+
+struct platform_device *__init imx_add_fec(
+ const struct imx_fec_data *data,
+ const struct fec_platform_data *pdata)
+{
+ struct resource res[] = {
+ {
+ .start = data->iobase,
+ .end = data->iobase + SZ_4K,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = data->irq,
+ .end = data->irq,
+ .flags = IORESOURCE_IRQ,
+ },
+ };
+
+ return imx_add_platform_device("fec", 0 /* -1? */,
+ res, ARRAY_SIZE(res),
+ pdata, sizeof(*pdata));
+}
diff --git a/arch/arm/plat-mxc/devices/platform-imx-dma.c b/arch/arm/plat-mxc/devices/platform-imx-dma.c
new file mode 100644
index 000000000000..02d989018059
--- /dev/null
+++ b/arch/arm/plat-mxc/devices/platform-imx-dma.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include <linux/compiler.h>
+#include <linux/err.h>
+#include <linux/init.h>
+
+#include <mach/hardware.h>
+#include <mach/devices-common.h>
+#ifdef SDMA_IS_MERGED
+#include <mach/sdma.h>
+#else
+struct sdma_platform_data {
+ int sdma_version;
+ char *cpu_name;
+ int to_version;
+};
+#endif
+
+struct imx_imx_sdma_data {
+ resource_size_t iobase;
+ resource_size_t irq;
+ struct sdma_platform_data pdata;
+};
+
+#define imx_imx_sdma_data_entry_single(soc, _sdma_version, _cpu_name, _to_version)\
+ { \
+ .iobase = soc ## _SDMA ## _BASE_ADDR, \
+ .irq = soc ## _INT_SDMA, \
+ .pdata = { \
+ .sdma_version = _sdma_version, \
+ .cpu_name = _cpu_name, \
+ .to_version = _to_version, \
+ }, \
+ }
+
+#ifdef CONFIG_ARCH_MX25
+const struct imx_imx_sdma_data imx25_imx_sdma_data __initconst =
+ imx_imx_sdma_data_entry_single(MX25, 1, "imx25", 0);
+#endif /* ifdef CONFIG_ARCH_MX25 */
+
+#ifdef CONFIG_ARCH_MX31
+struct imx_imx_sdma_data imx31_imx_sdma_data __initdata =
+ imx_imx_sdma_data_entry_single(MX31, 1, "imx31", 0);
+#endif /* ifdef CONFIG_ARCH_MX31 */
+
+#ifdef CONFIG_ARCH_MX35
+struct imx_imx_sdma_data imx35_imx_sdma_data __initdata =
+ imx_imx_sdma_data_entry_single(MX35, 2, "imx35", 0);
+#endif /* ifdef CONFIG_ARCH_MX35 */
+
+#ifdef CONFIG_ARCH_MX51
+const struct imx_imx_sdma_data imx51_imx_sdma_data __initconst =
+ imx_imx_sdma_data_entry_single(MX51, 2, "imx51", 0);
+#endif /* ifdef CONFIG_ARCH_MX51 */
+
+static struct platform_device __init __maybe_unused *imx_add_imx_sdma(
+ const struct imx_imx_sdma_data *data)
+{
+ struct resource res[] = {
+ {
+ .start = data->iobase,
+ .end = data->iobase + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = data->irq,
+ .end = data->irq,
+ .flags = IORESOURCE_IRQ,
+ },
+ };
+
+ return imx_add_platform_device("imx-sdma", -1,
+ res, ARRAY_SIZE(res),
+ &data->pdata, sizeof(data->pdata));
+}
+
+static struct platform_device __init __maybe_unused *imx_add_imx_dma(void)
+{
+ return imx_add_platform_device("imx-dma", -1, NULL, 0, NULL, 0);
+}
+
+static int __init imxXX_add_imx_dma(void)
+{
+ struct platform_device *ret;
+
+#if defined(CONFIG_SOC_IMX21) || defined(CONFIG_SOC_IMX27)
+ if (cpu_is_mx21() || cpu_is_mx27())
+ ret = imx_add_imx_dma();
+ else
+#endif
+
+#if defined(CONFIG_ARCH_MX25)
+ if (cpu_is_mx25())
+ ret = imx_add_imx_sdma(&imx25_imx_sdma_data);
+ else
+#endif
+
+#if defined(CONFIG_ARCH_MX31)
+ if (cpu_is_mx31()) {
+ imx31_imx_sdma_data.pdata.to_version = mx31_revision() >> 4;
+ ret = imx_add_imx_sdma(&imx31_imx_sdma_data);
+ } else
+#endif
+
+#if defined(CONFIG_ARCH_MX35)
+ if (cpu_is_mx35()) {
+ imx35_imx_sdma_data.pdata.to_version = mx35_revision() >> 4;
+ ret = imx_add_imx_sdma(&imx35_imx_sdma_data);
+ } else
+#endif
+
+#if defined(CONFIG_ARCH_MX51)
+ if (cpu_is_mx51())
+ ret = imx_add_imx_sdma(&imx51_imx_sdma_data);
+ else
+#endif
+ ret = ERR_PTR(-ENODEV);
+
+ if (IS_ERR(ret))
+ return PTR_ERR(ret);
+
+ return 0;
+}
+arch_initcall(imxXX_add_imx_dma);
diff --git a/arch/arm/plat-mxc/devices/platform-imx-i2c.c b/arch/arm/plat-mxc/devices/platform-imx-i2c.c
index d0af9f7d8aed..679588453aad 100644
--- a/arch/arm/plat-mxc/devices/platform-imx-i2c.c
+++ b/arch/arm/plat-mxc/devices/platform-imx-i2c.c
@@ -6,24 +6,95 @@
* the terms of the GNU General Public License version 2 as published by the
* Free Software Foundation.
*/
+#include <mach/hardware.h>
#include <mach/devices-common.h>
-struct platform_device *__init imx_add_imx_i2c(int id,
- resource_size_t iobase, resource_size_t iosize, int irq,
+#define imx_imx_i2c_data_entry_single(soc, _id, _hwid, _size) \
+ { \
+ .id = _id, \
+ .iobase = soc ## _I2C ## _hwid ## _BASE_ADDR, \
+ .iosize = _size, \
+ .irq = soc ## _INT_I2C ## _hwid, \
+ }
+
+#define imx_imx_i2c_data_entry(soc, _id, _hwid, _size) \
+ [_id] = imx_imx_i2c_data_entry_single(soc, _id, _hwid, _size)
+
+#ifdef CONFIG_SOC_IMX1
+const struct imx_imx_i2c_data imx1_imx_i2c_data __initconst =
+ imx_imx_i2c_data_entry_single(MX1, 0, , SZ_4K);
+#endif /* ifdef CONFIG_SOC_IMX1 */
+
+#ifdef CONFIG_SOC_IMX21
+const struct imx_imx_i2c_data imx21_imx_i2c_data __initconst =
+ imx_imx_i2c_data_entry_single(MX21, 0, , SZ_4K);
+#endif /* ifdef CONFIG_SOC_IMX21 */
+
+#ifdef CONFIG_ARCH_MX25
+const struct imx_imx_i2c_data imx25_imx_i2c_data[] __initconst = {
+#define imx25_imx_i2c_data_entry(_id, _hwid) \
+ imx_imx_i2c_data_entry(MX25, _id, _hwid, SZ_16K)
+ imx25_imx_i2c_data_entry(0, 1),
+ imx25_imx_i2c_data_entry(1, 2),
+ imx25_imx_i2c_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_ARCH_MX25 */
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_imx_i2c_data imx27_imx_i2c_data[] __initconst = {
+#define imx27_imx_i2c_data_entry(_id, _hwid) \
+ imx_imx_i2c_data_entry(MX27, _id, _hwid, SZ_4K)
+ imx27_imx_i2c_data_entry(0, 1),
+ imx27_imx_i2c_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+#ifdef CONFIG_ARCH_MX31
+const struct imx_imx_i2c_data imx31_imx_i2c_data[] __initconst = {
+#define imx31_imx_i2c_data_entry(_id, _hwid) \
+ imx_imx_i2c_data_entry(MX31, _id, _hwid, SZ_4K)
+ imx31_imx_i2c_data_entry(0, 1),
+ imx31_imx_i2c_data_entry(1, 2),
+ imx31_imx_i2c_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_ARCH_MX31 */
+
+#ifdef CONFIG_ARCH_MX35
+const struct imx_imx_i2c_data imx35_imx_i2c_data[] __initconst = {
+#define imx35_imx_i2c_data_entry(_id, _hwid) \
+ imx_imx_i2c_data_entry(MX35, _id, _hwid, SZ_4K)
+ imx35_imx_i2c_data_entry(0, 1),
+ imx35_imx_i2c_data_entry(1, 2),
+ imx35_imx_i2c_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_ARCH_MX35 */
+
+#ifdef CONFIG_ARCH_MX51
+const struct imx_imx_i2c_data imx51_imx_i2c_data[] __initconst = {
+#define imx51_imx_i2c_data_entry(_id, _hwid) \
+ imx_imx_i2c_data_entry(MX51, _id, _hwid, SZ_4K)
+ imx51_imx_i2c_data_entry(0, 1),
+ imx51_imx_i2c_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_ARCH_MX51 */
+
+struct platform_device *__init imx_add_imx_i2c(
+ const struct imx_imx_i2c_data *data,
const struct imxi2c_platform_data *pdata)
{
struct resource res[] = {
{
- .start = iobase,
- .end = iobase + iosize - 1,
+ .start = data->iobase,
+ .end = data->iobase + data->iosize - 1,
.flags = IORESOURCE_MEM,
}, {
- .start = irq,
- .end = irq,
+ .start = data->irq,
+ .end = data->irq,
.flags = IORESOURCE_IRQ,
},
};
- return imx_add_platform_device("imx-i2c", id, res, ARRAY_SIZE(res),
+ return imx_add_platform_device("imx-i2c", data->id,
+ res, ARRAY_SIZE(res),
pdata, sizeof(*pdata));
}
diff --git a/arch/arm/plat-mxc/devices/platform-imx-ssi.c b/arch/arm/plat-mxc/devices/platform-imx-ssi.c
new file mode 100644
index 000000000000..38a7a0b8f2f1
--- /dev/null
+++ b/arch/arm/plat-mxc/devices/platform-imx-ssi.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include <mach/hardware.h>
+#include <mach/devices-common.h>
+
+#define imx_imx_ssi_data_entry(soc, _id, _hwid, _size) \
+ [_id] = { \
+ .id = _id, \
+ .iobase = soc ## _SSI ## _hwid ## _BASE_ADDR, \
+ .iosize = _size, \
+ .irq = soc ## _INT_SSI ## _hwid, \
+ .dmatx0 = soc ## _DMA_REQ_SSI ## _hwid ## _TX0, \
+ .dmarx0 = soc ## _DMA_REQ_SSI ## _hwid ## _RX0, \
+ .dmatx1 = soc ## _DMA_REQ_SSI ## _hwid ## _TX1, \
+ .dmarx1 = soc ## _DMA_REQ_SSI ## _hwid ## _RX1, \
+ }
+
+#ifdef CONFIG_SOC_IMX21
+const struct imx_imx_ssi_data imx21_imx_ssi_data[] __initconst = {
+#define imx21_imx_ssi_data_entry(_id, _hwid) \
+ imx_imx_ssi_data_entry(MX21, _id, _hwid, SZ_4K)
+ imx21_imx_ssi_data_entry(0, 1),
+ imx21_imx_ssi_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_SOC_IMX21 */
+
+#ifdef CONFIG_ARCH_MX25
+const struct imx_imx_ssi_data imx25_imx_ssi_data[] __initconst = {
+#define imx25_imx_ssi_data_entry(_id, _hwid) \
+ imx_imx_ssi_data_entry(MX25, _id, _hwid, SZ_4K)
+ imx25_imx_ssi_data_entry(0, 1),
+ imx25_imx_ssi_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_ARCH_MX25 */
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_imx_ssi_data imx27_imx_ssi_data[] __initconst = {
+#define imx27_imx_ssi_data_entry(_id, _hwid) \
+ imx_imx_ssi_data_entry(MX27, _id, _hwid, SZ_4K)
+ imx27_imx_ssi_data_entry(0, 1),
+ imx27_imx_ssi_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+#ifdef CONFIG_ARCH_MX31
+const struct imx_imx_ssi_data imx31_imx_ssi_data[] __initconst = {
+#define imx31_imx_ssi_data_entry(_id, _hwid) \
+ imx_imx_ssi_data_entry(MX31, _id, _hwid, SZ_4K)
+ imx31_imx_ssi_data_entry(0, 1),
+ imx31_imx_ssi_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_ARCH_MX31 */
+
+#ifdef CONFIG_ARCH_MX35
+const struct imx_imx_ssi_data imx35_imx_ssi_data[] __initconst = {
+#define imx35_imx_ssi_data_entry(_id, _hwid) \
+ imx_imx_ssi_data_entry(MX35, _id, _hwid, SZ_4K)
+ imx35_imx_ssi_data_entry(0, 1),
+ imx35_imx_ssi_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_ARCH_MX35 */
+
+#ifdef CONFIG_ARCH_MX51
+const struct imx_imx_ssi_data imx51_imx_ssi_data[] __initconst = {
+#define imx51_imx_ssi_data_entry(_id, _hwid) \
+ imx_imx_ssi_data_entry(MX51, _id, _hwid, SZ_4K)
+ imx51_imx_ssi_data_entry(0, 1),
+ imx51_imx_ssi_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_ARCH_MX51 */
+
+struct platform_device *__init imx_add_imx_ssi(
+ const struct imx_imx_ssi_data *data,
+ const struct imx_ssi_platform_data *pdata)
+{
+ struct resource res[] = {
+ {
+ .start = data->iobase,
+ .end = data->iobase + data->iosize - 1,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = data->irq,
+ .end = data->irq,
+ .flags = IORESOURCE_IRQ,
+ },
+#define DMARES(_name) { \
+ .name = #_name, \
+ .start = data->dma ## _name, \
+ .end = data->dma ## _name, \
+ .flags = IORESOURCE_DMA, \
+}
+ DMARES(tx0),
+ DMARES(rx0),
+ DMARES(tx1),
+ DMARES(rx1),
+ };
+
+ return imx_add_platform_device("imx-ssi", data->id,
+ res, ARRAY_SIZE(res),
+ pdata, sizeof(*pdata));
+}
diff --git a/arch/arm/plat-mxc/devices/platform-imx-uart.c b/arch/arm/plat-mxc/devices/platform-imx-uart.c
index fa3dff1433e8..2039640adf27 100644
--- a/arch/arm/plat-mxc/devices/platform-imx-uart.c
+++ b/arch/arm/plat-mxc/devices/platform-imx-uart.c
@@ -6,55 +6,148 @@
* the terms of the GNU General Public License version 2 as published by the
* Free Software Foundation.
*/
+#include <mach/hardware.h>
#include <mach/devices-common.h>
-struct platform_device *__init imx_add_imx_uart_3irq(int id,
- resource_size_t iobase, resource_size_t iosize,
- resource_size_t irqrx, resource_size_t irqtx,
- resource_size_t irqrts,
+#define imx_imx_uart_3irq_data_entry(soc, _id, _hwid, _size) \
+ [_id] = { \
+ .id = _id, \
+ .iobase = soc ## _UART ## _hwid ## _BASE_ADDR, \
+ .iosize = _size, \
+ .irqrx = soc ## _INT_UART ## _hwid ## RX, \
+ .irqtx = soc ## _INT_UART ## _hwid ## TX, \
+ .irqrts = soc ## _INT_UART ## _hwid ## RTS, \
+ }
+
+#define imx_imx_uart_1irq_data_entry(soc, _id, _hwid, _size) \
+ [_id] = { \
+ .id = _id, \
+ .iobase = soc ## _UART ## _hwid ## _BASE_ADDR, \
+ .iosize = _size, \
+ .irq = soc ## _INT_UART ## _hwid, \
+ }
+
+#ifdef CONFIG_SOC_IMX1
+const struct imx_imx_uart_3irq_data imx1_imx_uart_data[] __initconst = {
+#define imx1_imx_uart_data_entry(_id, _hwid) \
+ imx_imx_uart_3irq_data_entry(MX1, _id, _hwid, 0xd0)
+ imx1_imx_uart_data_entry(0, 1),
+ imx1_imx_uart_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_SOC_IMX1 */
+
+#ifdef CONFIG_SOC_IMX21
+const struct imx_imx_uart_1irq_data imx21_imx_uart_data[] __initconst = {
+#define imx21_imx_uart_data_entry(_id, _hwid) \
+ imx_imx_uart_1irq_data_entry(MX21, _id, _hwid, SZ_4K)
+ imx21_imx_uart_data_entry(0, 1),
+ imx21_imx_uart_data_entry(1, 2),
+ imx21_imx_uart_data_entry(2, 3),
+ imx21_imx_uart_data_entry(3, 4),
+};
+#endif
+
+#ifdef CONFIG_ARCH_MX25
+const struct imx_imx_uart_1irq_data imx25_imx_uart_data[] __initconst = {
+#define imx25_imx_uart_data_entry(_id, _hwid) \
+ imx_imx_uart_1irq_data_entry(MX25, _id, _hwid, SZ_16K)
+ imx25_imx_uart_data_entry(0, 1),
+ imx25_imx_uart_data_entry(1, 2),
+ imx25_imx_uart_data_entry(2, 3),
+ imx25_imx_uart_data_entry(3, 4),
+ imx25_imx_uart_data_entry(4, 5),
+};
+#endif /* ifdef CONFIG_ARCH_MX25 */
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_imx_uart_1irq_data imx27_imx_uart_data[] __initconst = {
+#define imx27_imx_uart_data_entry(_id, _hwid) \
+ imx_imx_uart_1irq_data_entry(MX27, _id, _hwid, SZ_4K)
+ imx27_imx_uart_data_entry(0, 1),
+ imx27_imx_uart_data_entry(1, 2),
+ imx27_imx_uart_data_entry(2, 3),
+ imx27_imx_uart_data_entry(3, 4),
+ imx27_imx_uart_data_entry(4, 5),
+ imx27_imx_uart_data_entry(5, 6),
+};
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+#ifdef CONFIG_ARCH_MX31
+const struct imx_imx_uart_1irq_data imx31_imx_uart_data[] __initconst = {
+#define imx31_imx_uart_data_entry(_id, _hwid) \
+ imx_imx_uart_1irq_data_entry(MX31, _id, _hwid, SZ_4K)
+ imx31_imx_uart_data_entry(0, 1),
+ imx31_imx_uart_data_entry(1, 2),
+ imx31_imx_uart_data_entry(2, 3),
+ imx31_imx_uart_data_entry(3, 4),
+ imx31_imx_uart_data_entry(4, 5),
+};
+#endif /* ifdef CONFIG_ARCH_MX31 */
+
+#ifdef CONFIG_ARCH_MX35
+const struct imx_imx_uart_1irq_data imx35_imx_uart_data[] __initconst = {
+#define imx35_imx_uart_data_entry(_id, _hwid) \
+ imx_imx_uart_1irq_data_entry(MX31, _id, _hwid, SZ_16K)
+ imx35_imx_uart_data_entry(0, 1),
+ imx35_imx_uart_data_entry(1, 2),
+ imx35_imx_uart_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_ARCH_MX35 */
+
+#ifdef CONFIG_ARCH_MX51
+const struct imx_imx_uart_1irq_data imx51_imx_uart_data[] __initconst = {
+#define imx51_imx_uart_data_entry(_id, _hwid) \
+ imx_imx_uart_1irq_data_entry(MX51, _id, _hwid, SZ_4K)
+ imx51_imx_uart_data_entry(0, 1),
+ imx51_imx_uart_data_entry(1, 2),
+ imx51_imx_uart_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_ARCH_MX51 */
+
+struct platform_device *__init imx_add_imx_uart_3irq(
+ const struct imx_imx_uart_3irq_data *data,
const struct imxuart_platform_data *pdata)
{
struct resource res[] = {
{
- .start = iobase,
- .end = iobase + iosize - 1,
+ .start = data->iobase,
+ .end = data->iobase + data->iosize - 1,
.flags = IORESOURCE_MEM,
}, {
- .start = irqrx,
- .end = irqrx,
+ .start = data->irqrx,
+ .end = data->irqrx,
.flags = IORESOURCE_IRQ,
}, {
- .start = irqtx,
- .end = irqtx,
+ .start = data->irqtx,
+ .end = data->irqtx,
.flags = IORESOURCE_IRQ,
}, {
- .start = irqrts,
- .end = irqrx,
+ .start = data->irqrts,
+ .end = data->irqrx,
.flags = IORESOURCE_IRQ,
},
};
- return imx_add_platform_device("imx-uart", id, res, ARRAY_SIZE(res),
- pdata, sizeof(*pdata));
+ return imx_add_platform_device("imx-uart", data->id, res,
+ ARRAY_SIZE(res), pdata, sizeof(*pdata));
}
-struct platform_device *__init imx_add_imx_uart_1irq(int id,
- resource_size_t iobase, resource_size_t iosize,
- resource_size_t irq,
+struct platform_device *__init imx_add_imx_uart_1irq(
+ const struct imx_imx_uart_1irq_data *data,
const struct imxuart_platform_data *pdata)
{
struct resource res[] = {
{
- .start = iobase,
- .end = iobase + iosize - 1,
+ .start = data->iobase,
+ .end = data->iobase + data->iosize - 1,
.flags = IORESOURCE_MEM,
}, {
- .start = irq,
- .end = irq,
+ .start = data->irq,
+ .end = data->irq,
.flags = IORESOURCE_IRQ,
},
};
- return imx_add_platform_device("imx-uart", id, res, ARRAY_SIZE(res),
+ return imx_add_platform_device("imx-uart", data->id, res, ARRAY_SIZE(res),
pdata, sizeof(*pdata));
}
diff --git a/arch/arm/plat-mxc/devices/platform-mxc_nand.c b/arch/arm/plat-mxc/devices/platform-mxc_nand.c
index 1c286418d123..3fdcc32e3d67 100644
--- a/arch/arm/plat-mxc/devices/platform-mxc_nand.c
+++ b/arch/arm/plat-mxc/devices/platform-mxc_nand.c
@@ -7,38 +7,77 @@
* Free Software Foundation.
*/
#include <asm/sizes.h>
+#include <mach/hardware.h>
#include <mach/devices-common.h>
-static struct platform_device *__init imx_add_mxc_nand(resource_size_t iobase,
- int irq, const struct mxc_nand_platform_data *pdata,
- resource_size_t iosize)
+#define imx_mxc_nand_data_entry_single(soc, _size) \
+ { \
+ .iobase = soc ## _NFC_BASE_ADDR, \
+ .iosize = _size, \
+ .irq = soc ## _INT_NFC \
+ }
+
+#define imx_mxc_nandv3_data_entry_single(soc, _size) \
+ { \
+ .id = -1, \
+ .iobase = soc ## _NFC_BASE_ADDR, \
+ .iosize = _size, \
+ .axibase = soc ## _NFC_AXI_BASE_ADDR, \
+ .irq = soc ## _INT_NFC \
+ }
+
+#ifdef CONFIG_SOC_IMX21
+const struct imx_mxc_nand_data imx21_mxc_nand_data __initconst =
+ imx_mxc_nand_data_entry_single(MX21, SZ_4K);
+#endif /* ifdef CONFIG_SOC_IMX21 */
+
+#ifdef CONFIG_ARCH_MX25
+const struct imx_mxc_nand_data imx25_mxc_nand_data __initconst =
+ imx_mxc_nand_data_entry_single(MX25, SZ_8K);
+#endif /* ifdef CONFIG_ARCH_MX25 */
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_mxc_nand_data imx27_mxc_nand_data __initconst =
+ imx_mxc_nand_data_entry_single(MX27, SZ_4K);
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+#ifdef CONFIG_ARCH_MX31
+const struct imx_mxc_nand_data imx31_mxc_nand_data __initconst =
+ imx_mxc_nand_data_entry_single(MX31, SZ_4K);
+#endif
+
+#ifdef CONFIG_ARCH_MX35
+const struct imx_mxc_nand_data imx35_mxc_nand_data __initconst =
+ imx_mxc_nand_data_entry_single(MX35, SZ_8K);
+#endif
+
+#ifdef CONFIG_ARCH_MX51
+const struct imx_mxc_nand_data imx51_mxc_nand_data __initconst =
+ imx_mxc_nandv3_data_entry_single(MX51, SZ_16K);
+#endif
+
+struct platform_device *__init imx_add_mxc_nand(
+ const struct imx_mxc_nand_data *data,
+ const struct mxc_nand_platform_data *pdata)
{
- static int id = 0;
-
+ /* AXI has to come first, that's how the mxc_nand driver expect it */
struct resource res[] = {
{
- .start = iobase,
- .end = iobase + iosize - 1,
+ .start = data->axibase,
+ .end = data->axibase + SZ_16K - 1,
.flags = IORESOURCE_MEM,
}, {
- .start = irq,
- .end = irq,
+ .start = data->iobase,
+ .end = data->iobase + data->iosize - 1,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = data->irq,
+ .end = data->irq,
.flags = IORESOURCE_IRQ,
},
};
-
- return imx_add_platform_device("mxc_nand", id++, res, ARRAY_SIZE(res),
+ return imx_add_platform_device("mxc_nand", data->id,
+ res + !data->axibase,
+ ARRAY_SIZE(res) - !data->axibase,
pdata, sizeof(*pdata));
}
-
-struct platform_device *__init imx_add_mxc_nand_v1(resource_size_t iobase,
- int irq, const struct mxc_nand_platform_data *pdata)
-{
- return imx_add_mxc_nand(iobase, irq, pdata, SZ_4K);
-}
-
-struct platform_device *__init imx_add_mxc_nand_v21(resource_size_t iobase,
- int irq, const struct mxc_nand_platform_data *pdata)
-{
- return imx_add_mxc_nand(iobase, irq, pdata, SZ_8K);
-}
diff --git a/arch/arm/plat-mxc/devices/platform-spi_imx.c b/arch/arm/plat-mxc/devices/platform-spi_imx.c
index 2831a6d3eb4b..e48340ec331e 100644
--- a/arch/arm/plat-mxc/devices/platform-spi_imx.c
+++ b/arch/arm/plat-mxc/devices/platform-spi_imx.c
@@ -6,25 +6,96 @@
* the terms of the GNU General Public License version 2 as published by the
* Free Software Foundation.
*/
-#include <asm/sizes.h>
+#include <mach/hardware.h>
#include <mach/devices-common.h>
-struct platform_device *__init imx_add_spi_imx(int id,
- resource_size_t iobase, resource_size_t iosize, int irq,
+#define imx_spi_imx_data_entry_single(soc, type, _devid, _id, hwid, _size) \
+ { \
+ .devid = _devid, \
+ .id = _id, \
+ .iobase = soc ## _ ## type ## hwid ## _BASE_ADDR, \
+ .iosize = _size, \
+ .irq = soc ## _INT_ ## type ## hwid, \
+ }
+
+#define imx_spi_imx_data_entry(soc, type, devid, id, hwid, size) \
+ [id] = imx_spi_imx_data_entry_single(soc, type, devid, id, hwid, size)
+
+#ifdef CONFIG_SOC_IMX21
+const struct imx_spi_imx_data imx21_cspi_data[] __initconst = {
+#define imx21_cspi_data_entry(_id, _hwid) \
+ imx_spi_imx_data_entry(MX21, CSPI, "imx21-cspi", _id, _hwid, SZ_4K)
+ imx21_cspi_data_entry(0, 1),
+ imx21_cspi_data_entry(1, 2),
+#endif
+
+#ifdef CONFIG_ARCH_MX25
+const struct imx_spi_imx_data imx25_cspi_data[] __initconst = {
+#define imx25_cspi_data_entry(_id, _hwid) \
+ imx_spi_imx_data_entry(MX25, CSPI, "imx25-cspi", _id, _hwid, SZ_16K)
+ imx25_cspi_data_entry(0, 1),
+ imx25_cspi_data_entry(1, 2),
+ imx25_cspi_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_ARCH_MX25 */
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_spi_imx_data imx27_cspi_data[] __initconst = {
+#define imx27_cspi_data_entry(_id, _hwid) \
+ imx_spi_imx_data_entry(MX27, CSPI, "imx27-cspi", _id, _hwid, SZ_4K)
+ imx27_cspi_data_entry(0, 1),
+ imx27_cspi_data_entry(1, 2),
+ imx27_cspi_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+#ifdef CONFIG_ARCH_MX31
+const struct imx_spi_imx_data imx31_cspi_data[] __initconst = {
+#define imx31_cspi_data_entry(_id, _hwid) \
+ imx_spi_imx_data_entry(MX31, CSPI, "imx31-cspi", _id, _hwid, SZ_4K)
+ imx31_cspi_data_entry(0, 1),
+ imx31_cspi_data_entry(1, 2),
+ imx31_cspi_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_ARCH_MX31 */
+
+#ifdef CONFIG_ARCH_MX35
+const struct imx_spi_imx_data imx35_cspi_data[] __initconst = {
+#define imx35_cspi_data_entry(_id, _hwid) \
+ imx_spi_imx_data_entry(MX35, CSPI, "imx35-cspi", _id, _hwid, SZ_4K)
+ imx35_cspi_data_entry(0, 1),
+ imx35_cspi_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_ARCH_MX35 */
+
+#ifdef CONFIG_ARCH_MX51
+const struct imx_spi_imx_data imx51_cspi_data __initconst =
+ imx_spi_imx_data_entry_single(MX51, CSPI, "imx51-cspi", 0, , SZ_4K);
+
+const struct imx_spi_imx_data imx51_ecspi_data[] __initconst = {
+#define imx51_ecspi_data_entry(_id, _hwid) \
+ imx_spi_imx_data_entry(MX51, ECSPI, "imx51-ecspi", _id, _hwid, SZ_4K)
+ imx51_ecspi_data_entry(0, 1),
+ imx51_ecspi_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_ARCH_MX51 */
+
+struct platform_device *__init imx_add_spi_imx(
+ const struct imx_spi_imx_data *data,
const struct spi_imx_master *pdata)
{
struct resource res[] = {
{
- .start = iobase,
- .end = iobase + iosize - 1,
+ .start = data->iobase,
+ .end = data->iobase + data->iosize - 1,
.flags = IORESOURCE_MEM,
}, {
- .start = irq,
- .end = irq,
+ .start = data->irq,
+ .end = data->irq,
.flags = IORESOURCE_IRQ,
},
};
- return imx_add_platform_device("spi_imx", id, res, ARRAY_SIZE(res),
- pdata, sizeof(*pdata));
+ return imx_add_platform_device(data->devid, data->id,
+ res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
}
diff --git a/arch/arm/plat-mxc/ehci.c b/arch/arm/plat-mxc/ehci.c
index 35a064ff02ba..9915607683de 100644
--- a/arch/arm/plat-mxc/ehci.c
+++ b/arch/arm/plat-mxc/ehci.c
@@ -249,8 +249,8 @@ int mxc_initialize_usb_hw(int port, unsigned int flags)
#ifdef CONFIG_ARCH_MX51
if (cpu_is_mx51()) {
void __iomem *usb_base;
- u32 usbotg_base;
- u32 usbother_base;
+ void __iomem *usbotg_base;
+ void __iomem *usbother_base;
int ret = 0;
usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
diff --git a/arch/arm/plat-mxc/epit.c b/arch/arm/plat-mxc/epit.c
new file mode 100644
index 000000000000..ee9582f4972e
--- /dev/null
+++ b/arch/arm/plat-mxc/epit.c
@@ -0,0 +1,242 @@
+/*
+ * linux/arch/arm/plat-mxc/epit.c
+ *
+ * Copyright (C) 2010 Sascha Hauer <s.hauer@pengutronix.de>
+ *
+ * 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.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#define EPITCR 0x00
+#define EPITSR 0x04
+#define EPITLR 0x08
+#define EPITCMPR 0x0c
+#define EPITCNR 0x10
+
+#define EPITCR_EN (1 << 0)
+#define EPITCR_ENMOD (1 << 1)
+#define EPITCR_OCIEN (1 << 2)
+#define EPITCR_RLD (1 << 3)
+#define EPITCR_PRESC(x) (((x) & 0xfff) << 4)
+#define EPITCR_SWR (1 << 16)
+#define EPITCR_IOVW (1 << 17)
+#define EPITCR_DBGEN (1 << 18)
+#define EPITCR_WAITEN (1 << 19)
+#define EPITCR_RES (1 << 20)
+#define EPITCR_STOPEN (1 << 21)
+#define EPITCR_OM_DISCON (0 << 22)
+#define EPITCR_OM_TOGGLE (1 << 22)
+#define EPITCR_OM_CLEAR (2 << 22)
+#define EPITCR_OM_SET (3 << 22)
+#define EPITCR_CLKSRC_OFF (0 << 24)
+#define EPITCR_CLKSRC_PERIPHERAL (1 << 24)
+#define EPITCR_CLKSRC_REF_HIGH (1 << 24)
+#define EPITCR_CLKSRC_REF_LOW (3 << 24)
+
+#define EPITSR_OCIF (1 << 0)
+
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/clockchips.h>
+#include <linux/clk.h>
+
+#include <mach/hardware.h>
+#include <asm/mach/time.h>
+#include <mach/common.h>
+
+static struct clock_event_device clockevent_epit;
+static enum clock_event_mode clockevent_mode = CLOCK_EVT_MODE_UNUSED;
+
+static void __iomem *timer_base;
+
+static inline void epit_irq_disable(void)
+{
+ u32 val;
+
+ val = __raw_readl(timer_base + EPITCR);
+ val &= ~EPITCR_OCIEN;
+ __raw_writel(val, timer_base + EPITCR);
+}
+
+static inline void epit_irq_enable(void)
+{
+ u32 val;
+
+ val = __raw_readl(timer_base + EPITCR);
+ val |= EPITCR_OCIEN;
+ __raw_writel(val, timer_base + EPITCR);
+}
+
+static void epit_irq_acknowledge(void)
+{
+ __raw_writel(EPITSR_OCIF, timer_base + EPITSR);
+}
+
+static cycle_t epit_read(struct clocksource *cs)
+{
+ return 0 - __raw_readl(timer_base + EPITCNR);
+}
+
+static struct clocksource clocksource_epit = {
+ .name = "epit",
+ .rating = 200,
+ .read = epit_read,
+ .mask = CLOCKSOURCE_MASK(32),
+ .shift = 20,
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static int __init epit_clocksource_init(struct clk *timer_clk)
+{
+ unsigned int c = clk_get_rate(timer_clk);
+
+ clocksource_epit.mult = clocksource_hz2mult(c,
+ clocksource_epit.shift);
+ clocksource_register(&clocksource_epit);
+
+ return 0;
+}
+
+/* clock event */
+
+static int epit_set_next_event(unsigned long evt,
+ struct clock_event_device *unused)
+{
+ unsigned long tcmp;
+
+ tcmp = __raw_readl(timer_base + EPITCNR);
+
+ __raw_writel(tcmp - evt, timer_base + EPITCMPR);
+
+ return 0;
+}
+
+static void epit_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt)
+{
+ unsigned long flags;
+
+ /*
+ * The timer interrupt generation is disabled at least
+ * for enough time to call epit_set_next_event()
+ */
+ local_irq_save(flags);
+
+ /* Disable interrupt in GPT module */
+ epit_irq_disable();
+
+ if (mode != clockevent_mode) {
+ /* Set event time into far-far future */
+
+ /* Clear pending interrupt */
+ epit_irq_acknowledge();
+ }
+
+ /* Remember timer mode */
+ clockevent_mode = mode;
+ local_irq_restore(flags);
+
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ printk(KERN_ERR "epit_set_mode: Periodic mode is not "
+ "supported for i.MX EPIT\n");
+ break;
+ case CLOCK_EVT_MODE_ONESHOT:
+ /*
+ * Do not put overhead of interrupt enable/disable into
+ * epit_set_next_event(), the core has about 4 minutes
+ * to call epit_set_next_event() or shutdown clock after
+ * mode switching
+ */
+ local_irq_save(flags);
+ epit_irq_enable();
+ local_irq_restore(flags);
+ break;
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ case CLOCK_EVT_MODE_UNUSED:
+ case CLOCK_EVT_MODE_RESUME:
+ /* Left event sources disabled, no more interrupts appear */
+ break;
+ }
+}
+
+/*
+ * IRQ handler for the timer
+ */
+static irqreturn_t epit_timer_interrupt(int irq, void *dev_id)
+{
+ struct clock_event_device *evt = &clockevent_epit;
+
+ epit_irq_acknowledge();
+
+ evt->event_handler(evt);
+
+ return IRQ_HANDLED;
+}
+
+static struct irqaction epit_timer_irq = {
+ .name = "i.MX EPIT Timer Tick",
+ .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+ .handler = epit_timer_interrupt,
+};
+
+static struct clock_event_device clockevent_epit = {
+ .name = "epit",
+ .features = CLOCK_EVT_FEAT_ONESHOT,
+ .shift = 32,
+ .set_mode = epit_set_mode,
+ .set_next_event = epit_set_next_event,
+ .rating = 200,
+};
+
+static int __init epit_clockevent_init(struct clk *timer_clk)
+{
+ unsigned int c = clk_get_rate(timer_clk);
+
+ clockevent_epit.mult = div_sc(c, NSEC_PER_SEC,
+ clockevent_epit.shift);
+ clockevent_epit.max_delta_ns =
+ clockevent_delta2ns(0xfffffffe, &clockevent_epit);
+ clockevent_epit.min_delta_ns =
+ clockevent_delta2ns(0x800, &clockevent_epit);
+
+ clockevent_epit.cpumask = cpumask_of(0);
+
+ clockevents_register_device(&clockevent_epit);
+
+ return 0;
+}
+
+void __init epit_timer_init(struct clk *timer_clk, void __iomem *base, int irq)
+{
+ clk_enable(timer_clk);
+
+ timer_base = base;
+
+ /*
+ * Initialise to a known state (all timers off, and timing reset)
+ */
+ __raw_writel(0x0, timer_base + EPITCR);
+
+ __raw_writel(0xffffffff, timer_base + EPITLR);
+ __raw_writel(EPITCR_EN | EPITCR_CLKSRC_REF_HIGH | EPITCR_WAITEN,
+ timer_base + EPITCR);
+
+ /* init and register the timer to the framework */
+ epit_clocksource_init(timer_clk);
+ epit_clockevent_init(timer_clk);
+
+ /* Make irqs happen */
+ setup_irq(irq, &epit_timer_irq);
+}
diff --git a/arch/arm/plat-mxc/gpio.c b/arch/arm/plat-mxc/gpio.c
index 57ec4a896a5d..9d38da077edb 100644
--- a/arch/arm/plat-mxc/gpio.c
+++ b/arch/arm/plat-mxc/gpio.c
@@ -235,7 +235,7 @@ static void mxc_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
unsigned long flags;
spin_lock_irqsave(&port->lock, flags);
- l = (__raw_readl(reg) & (~(1 << offset))) | (value << offset);
+ l = (__raw_readl(reg) & (~(1 << offset))) | (!!value << offset);
__raw_writel(l, reg);
spin_unlock_irqrestore(&port->lock, flags);
}
diff --git a/arch/arm/plat-mxc/include/mach/board-mx31ads.h b/arch/arm/plat-mxc/include/mach/board-mx31ads.h
new file mode 100644
index 000000000000..94b60dd47137
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/board-mx31ads.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_MXC_BOARD_MX31ADS_H__
+#define __ASM_ARCH_MXC_BOARD_MX31ADS_H__
+
+#include <mach/hardware.h>
+
+/*
+ * These symbols are used by drivers/net/cs89x0.c.
+ * This is ugly as hell, but we have to provide them until
+ * someone fixed the driver.
+ */
+
+/* Base address of PBC controller */
+#define PBC_BASE_ADDRESS MX31_CS4_BASE_ADDR_VIRT
+/* Offsets for the PBC Controller register */
+
+/* Ethernet Controller IO base address */
+#define PBC_CS8900A_IOBASE 0x020000
+
+#define MXC_EXP_IO_BASE (MXC_BOARD_IRQ_START)
+
+#define EXPIO_INT_ENET_INT (MXC_EXP_IO_BASE + 8)
+
+#endif /* __ASM_ARCH_MXC_BOARD_MX31ADS_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/common.h b/arch/arm/plat-mxc/include/mach/common.h
index 2941472582d2..7a1e1f89ff09 100644
--- a/arch/arm/plat-mxc/include/mach/common.h
+++ b/arch/arm/plat-mxc/include/mach/common.h
@@ -32,6 +32,7 @@ extern void mx31_init_irq(void);
extern void mx35_init_irq(void);
extern void mx51_init_irq(void);
extern void mxc91231_init_irq(void);
+extern void epit_timer_init(struct clk *timer_clk, void __iomem *base, int irq);
extern void mxc_timer_init(struct clk *timer_clk, void __iomem *, int);
extern int mx1_clocks_init(unsigned long fref);
extern int mx21_clocks_init(unsigned long lref, unsigned long fref);
diff --git a/arch/arm/plat-mxc/include/mach/debug-macro.S b/arch/arm/plat-mxc/include/mach/debug-macro.S
index 25606409aabc..d56213fb901b 100644
--- a/arch/arm/plat-mxc/include/mach/debug-macro.S
+++ b/arch/arm/plat-mxc/include/mach/debug-macro.S
@@ -62,11 +62,9 @@
#define UART_PADDR MXC91231_UART2_BASE_ADDR
#define UART_VADDR MXC91231_IO_ADDRESS(MXC91231_UART2_BASE_ADDR)
#endif
- .macro addruart, rx, tmp
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ MMU enabled?
- ldreq \rx, =UART_PADDR @ physical
- ldrne \rx, =UART_VADDR @ virtual
+ .macro addruart, rp, rv
+ ldr \rp, =UART_PADDR @ physical
+ ldr \rv, =UART_VADDR @ virtual
.endm
.macro senduart,rd,rx
diff --git a/arch/arm/plat-mxc/include/mach/devices-common.h b/arch/arm/plat-mxc/include/mach/devices-common.h
index c5f68c587309..86d7575a564d 100644
--- a/arch/arm/plat-mxc/include/mach/devices-common.h
+++ b/arch/arm/plat-mxc/include/mach/devices-common.h
@@ -14,47 +14,105 @@ struct platform_device *imx_add_platform_device(const char *name, int id,
const struct resource *res, unsigned int num_resources,
const void *data, size_t size_data);
-#if defined (CONFIG_CAN_FLEXCAN) || defined (CONFIG_CAN_FLEXCAN_MODULE)
+#include <linux/fec.h>
+struct imx_fec_data {
+ resource_size_t iobase;
+ resource_size_t irq;
+};
+struct platform_device *__init imx_add_fec(
+ const struct imx_fec_data *data,
+ const struct fec_platform_data *pdata);
+
#include <linux/can/platform/flexcan.h>
struct platform_device *__init imx_add_flexcan(int id,
resource_size_t iobase, resource_size_t iosize,
resource_size_t irq,
const struct flexcan_platform_data *pdata);
-#else
-/* the ifdef can be removed once the flexcan driver has been merged */
-struct flexcan_platform_data;
-static inline struct platform_device *__init imx_add_flexcan(int id,
- resource_size_t iobase, resource_size_t iosize,
- resource_size_t irq,
- const struct flexcan_platform_data *pdata)
-{
- return NULL;
-}
-#endif
#include <mach/i2c.h>
-struct platform_device *__init imx_add_imx_i2c(int id,
- resource_size_t iobase, resource_size_t iosize, int irq,
+struct imx_imx_i2c_data {
+ int id;
+ resource_size_t iobase;
+ resource_size_t iosize;
+ resource_size_t irq;
+};
+struct platform_device *__init imx_add_imx_i2c(
+ const struct imx_imx_i2c_data *data,
const struct imxi2c_platform_data *pdata);
+#include <mach/ssi.h>
+struct imx_imx_ssi_data {
+ int id;
+ resource_size_t iobase;
+ resource_size_t iosize;
+ resource_size_t irq;
+ resource_size_t dmatx0;
+ resource_size_t dmarx0;
+ resource_size_t dmatx1;
+ resource_size_t dmarx1;
+};
+struct platform_device *__init imx_add_imx_ssi(
+ const struct imx_imx_ssi_data *data,
+ const struct imx_ssi_platform_data *pdata);
+
#include <mach/imx-uart.h>
-struct platform_device *__init imx_add_imx_uart_3irq(int id,
- resource_size_t iobase, resource_size_t iosize,
- resource_size_t irqrx, resource_size_t irqtx,
- resource_size_t irqrts,
+struct imx_imx_uart_3irq_data {
+ int id;
+ resource_size_t iobase;
+ resource_size_t iosize;
+ resource_size_t irqrx;
+ resource_size_t irqtx;
+ resource_size_t irqrts;
+};
+struct platform_device *__init imx_add_imx_uart_3irq(
+ const struct imx_imx_uart_3irq_data *data,
const struct imxuart_platform_data *pdata);
-struct platform_device *__init imx_add_imx_uart_1irq(int id,
- resource_size_t iobase, resource_size_t iosize,
- resource_size_t irq,
+
+struct imx_imx_uart_1irq_data {
+ int id;
+ resource_size_t iobase;
+ resource_size_t iosize;
+ resource_size_t irq;
+};
+struct platform_device *__init imx_add_imx_uart_1irq(
+ const struct imx_imx_uart_1irq_data *data,
const struct imxuart_platform_data *pdata);
#include <mach/mxc_nand.h>
-struct platform_device *__init imx_add_mxc_nand_v1(resource_size_t iobase,
- int irq, const struct mxc_nand_platform_data *pdata);
-struct platform_device *__init imx_add_mxc_nand_v21(resource_size_t iobase,
- int irq, const struct mxc_nand_platform_data *pdata);
+struct imx_mxc_nand_data {
+ /*
+ * id is traditionally 0, but -1 is more appropriate. We use -1 for new
+ * machines but don't change existing devices as the nand device usually
+ * appears in the kernel command line to pass its partitioning.
+ */
+ int id;
+ resource_size_t iobase;
+ resource_size_t iosize;
+ resource_size_t axibase;
+ resource_size_t irq;
+};
+struct platform_device *__init imx_add_mxc_nand(
+ const struct imx_mxc_nand_data *data,
+ const struct mxc_nand_platform_data *pdata);
#include <mach/spi.h>
-struct platform_device *__init imx_add_spi_imx(int id,
- resource_size_t iobase, resource_size_t iosize, int irq,
+struct imx_spi_imx_data {
+ const char *devid;
+ int id;
+ resource_size_t iobase;
+ resource_size_t iosize;
+ int irq;
+};
+struct platform_device *__init imx_add_spi_imx(
+ const struct imx_spi_imx_data *data,
const struct spi_imx_master *pdata);
+
+#include <mach/esdhc.h>
+struct imx_esdhc_imx_data {
+ int id;
+ resource_size_t iobase;
+ resource_size_t irq;
+};
+struct platform_device *__init imx_add_esdhc(
+ const struct imx_esdhc_imx_data *data,
+ const struct esdhc_platform_data *pdata);
diff --git a/arch/arm/plat-mxc/include/mach/esdhc.h b/arch/arm/plat-mxc/include/mach/esdhc.h
new file mode 100644
index 000000000000..a48a9aaa56b1
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/esdhc.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2010 Wolfram Sang <w.sang@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#ifndef __ASM_ARCH_IMX_ESDHC_H
+#define __ASM_ARCH_IMX_ESDHC_H
+
+struct esdhc_platform_data {
+ unsigned int wp_gpio; /* write protect pin */
+};
+#endif /* __ASM_ARCH_IMX_ESDHC_H */
diff --git a/arch/arm/plat-mxc/include/mach/eukrea-baseboards.h b/arch/arm/plat-mxc/include/mach/eukrea-baseboards.h
index 656acb45d434..a21d3313f994 100644
--- a/arch/arm/plat-mxc/include/mach/eukrea-baseboards.h
+++ b/arch/arm/plat-mxc/include/mach/eukrea-baseboards.h
@@ -28,19 +28,22 @@
* its own devices, it calls baseboard's init function.
* TODO: Add your own baseboard init function and call it from
* inside eukrea_cpuimx25_init() eukrea_cpuimx27_init()
- * eukrea_cpuimx35_init() or eukrea_cpuimx51_init().
+ * eukrea_cpuimx35_init() eukrea_cpuimx51_init()
+ * or eukrea_cpuimx51sd_init().
*
* This example here is for the development board. Refer
* mach-mx25/eukrea_mbimxsd-baseboard.c for cpuimx25
* mach-imx/eukrea_mbimx27-baseboard.c for cpuimx27
* mach-mx3/eukrea_mbimxsd-baseboard.c for cpuimx35
* mach-mx5/eukrea_mbimx51-baseboard.c for cpuimx51
+ * mach-mx5/eukrea_mbimxsd-baseboard.c for cpuimx51sd
*/
extern void eukrea_mbimxsd25_baseboard_init(void);
extern void eukrea_mbimx27_baseboard_init(void);
extern void eukrea_mbimxsd35_baseboard_init(void);
extern void eukrea_mbimx51_baseboard_init(void);
+extern void eukrea_mbimxsd51_baseboard_init(void);
#endif
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx51.h b/arch/arm/plat-mxc/include/mach/iomux-mx51.h
index 21bfa46785bb..e46b1c2836d4 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-mx51.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-mx51.h
@@ -45,6 +45,18 @@ typedef enum iomux_config {
PAD_CTL_PKE | PAD_CTL_HYS)
#define MX51_GPIO_PAD_CTRL (PAD_CTL_DSE_HIGH | PAD_CTL_PKE | \
PAD_CTL_SRE_FAST)
+#define MX51_ECSPI_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_PKE | PAD_CTL_DSE_HIGH | \
+ PAD_CTL_SRE_FAST)
+#define MX51_SDHCI_PAD_CTRL (PAD_CTL_DSE_HIGH | PAD_CTL_PUS_47K_UP | \
+ PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_SRE_FAST | \
+ PAD_CTL_DVS)
+
+#define MX51_PAD_CTRL_1 (PAD_CTL_SRE_FAST | PAD_CTL_DSE_HIGH | \
+ PAD_CTL_PUE | PAD_CTL_PKE | PAD_CTL_HYS)
+#define MX51_PAD_CTRL_2 (PAD_CTL_HYS | PAD_CTL_PKE)
+#define MX51_PAD_CTRL_3 (PAD_CTL_PKE | PAD_CTL_PUS_100K_UP)
+#define MX51_PAD_CTRL_4 (PAD_CTL_DVS | PAD_CTL_HYS | PAD_CTL_PKE)
+#define MX51_PAD_CTRL_5 (PAD_CTL_DVS | PAD_CTL_DSE_HIGH)
/*
* The naming convention for the pad modes is MX51_PAD_<padname>__<padmode>
@@ -106,14 +118,20 @@ typedef enum iomux_config {
#define MX51_PAD_EIM_EB0__EIM_EB0 IOMUX_PAD(0x460, 0x0cc, 0, 0x0, 0, NO_PAD_CTRL)
#define MX51_PAD_EIM_EB1__EIM_EB1 IOMUX_PAD(0x464, 0x0d0, 0, 0x0, 0, NO_PAD_CTRL)
#define MX51_PAD_EIM_EB2__GPIO_2_22 IOMUX_PAD(0x468, 0x0d4, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB2__FEC_MDIO IOMUX_PAD(0x468, 0x0d4, 3, 0x0, 0, MX51_PAD_CTRL_1 | PAD_CTL_PUS_22K_UP)
#define MX51_PAD_EIM_EB3__GPIO_2_23 IOMUX_PAD(0x46c, 0x0d8, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB3__FEC_RDAT1 IOMUX_PAD(0x46c, 0x0d8, 3, 0x0, 0, MX51_PAD_CTRL_2)
#define MX51_PAD_EIM_OE__GPIO_2_24 IOMUX_PAD(0x470, 0x0dc, 1, 0x0, 0, NO_PAD_CTRL)
#define MX51_PAD_EIM_CS0__GPIO_2_25 IOMUX_PAD(0x474, 0x0e0, 1, 0x0, 0, NO_PAD_CTRL)
#define MX51_PAD_EIM_CS1__GPIO_2_26 IOMUX_PAD(0x478, 0x0e4, 1, 0x0, 0, NO_PAD_CTRL)
#define MX51_PAD_EIM_CS2__GPIO_2_27 IOMUX_PAD(0x47c, 0x0e8, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS2__FEC_RDAT2 IOMUX_PAD(0x47c, 0x0e8, 3, 0x0, 0, MX51_PAD_CTRL_2)
#define MX51_PAD_EIM_CS3__GPIO_2_28 IOMUX_PAD(0x480, 0x0ec, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS3__FEC_RDAT3 IOMUX_PAD(0x480, 0x0ec, 3, 0x0, 0, MX51_PAD_CTRL_2)
#define MX51_PAD_EIM_CS4__GPIO_2_29 IOMUX_PAD(0x484, 0x0f0, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS4__FEC_RX_ER IOMUX_PAD(0x484, 0x0f0, 3, 0x0, 0, MX51_PAD_CTRL_2)
#define MX51_PAD_EIM_CS5__GPIO_2_30 IOMUX_PAD(0x488, 0x0f4, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS5__FEC_CRS IOMUX_PAD(0x488, 0x0f4, 3, 0x0, 0, MX51_PAD_CTRL_2)
#define MX51_PAD_EIM_DTACK__GPIO_2_31 IOMUX_PAD(0x48c, 0x0f8, 1, 0x0, 0, NO_PAD_CTRL)
#define MX51_PAD_EIM_LBA__GPIO_3_1 IOMUX_PAD(0x494, 0x0FC, 1, 0x0, 0, NO_PAD_CTRL)
#define MX51_PAD_EIM_CRE__GPIO_3_2 IOMUX_PAD(0x4A0, 0x100, 1, 0x0, 0, NO_PAD_CTRL)
@@ -126,18 +144,32 @@ typedef enum iomux_config {
#define MX51_PAD_NANDF_RB0__GPIO_3_8 IOMUX_PAD(0x4F8, 0x11C, 3, 0x0, 0, NO_PAD_CTRL)
#define MX51_PAD_NANDF_RB1__GPIO_3_9 IOMUX_PAD(0x4FC, 0x120, 3, 0x0, 0, NO_PAD_CTRL)
#define MX51_PAD_NANDF_RB2__GPIO_3_10 IOMUX_PAD(0x500, 0x124, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB2__ECSPI2_SCLK IOMUX_PAD(0x500, 0x124, 2, 0x0, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB2__FEC_COL IOMUX_PAD(0x500, 0x124, 1, 0x0, 0, MX51_PAD_CTRL_2)
#define MX51_PAD_NANDF_RB3__GPIO_3_11 IOMUX_PAD(0x504, 0x128, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB3__ECSPI2_MISO IOMUX_PAD(0x504, 0x128, 2, 0x0, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB3__FEC_RXCLK IOMUX_PAD(0x504, 0x128, 1, 0x0, 0, MX51_PAD_CTRL_2)
+#define MX51_PAD_NANDF_RB6__FEC_RDAT0 IOMUX_PAD(0x5DC, 0x134, 1, 0x0, 0, MX51_PAD_CTRL_4)
+#define MX51_PAD_NANDF_RB7__FEC_TDAT0 IOMUX_PAD(0x5E0, 0x138, 1, 0x0, 0, MX51_PAD_CTRL_5)
#define MX51_PAD_GPIO_NAND__GPIO_3_12 IOMUX_PAD(0x514, 0x12C, 3, 0x0, 0, NO_PAD_CTRL)
#define MX51_PAD_NANDF_CS0__GPIO_3_16 IOMUX_PAD(0x518, 0x130, 3, 0x0, 0, NO_PAD_CTRL)
#define MX51_PAD_NANDF_CS1__GPIO_3_17 IOMUX_PAD(0x51C, 0x134, 3, 0x0, 0, NO_PAD_CTRL)
#define MX51_PAD_NANDF_CS2__GPIO_3_18 IOMUX_PAD(0x520, 0x138, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS2__FEC_TX_ER IOMUX_PAD(0x520, 0x138, 2, 0x0, 0, MX51_PAD_CTRL_5)
#define MX51_PAD_NANDF_CS3__GPIO_3_19 IOMUX_PAD(0x524, 0x13C, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS3__FEC_MDC IOMUX_PAD(0x524, 0x13C, 2, 0x0, 0, MX51_PAD_CTRL_5)
#define MX51_PAD_NANDF_CS4__GPIO_3_20 IOMUX_PAD(0x528, 0x140, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS4__FEC_TDAT1 IOMUX_PAD(0x528, 0x140, 2, 0x0, 0, MX51_PAD_CTRL_5)
#define MX51_PAD_NANDF_CS5__GPIO_3_21 IOMUX_PAD(0x52C, 0x144, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS5__FEC_TDAT2 IOMUX_PAD(0x52C, 0x144, 2, 0x0, 0, MX51_PAD_CTRL_5)
#define MX51_PAD_NANDF_CS6__GPIO_3_22 IOMUX_PAD(0x530, 0x148, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS6__FEC_TDAT3 IOMUX_PAD(0x530, 0x148, 2, 0x0, 0, MX51_PAD_CTRL_5)
#define MX51_PAD_NANDF_CS7__GPIO_3_23 IOMUX_PAD(0x534, 0x14C, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS7__FEC_TX_EN IOMUX_PAD(0x534, 0x14C, 1, 0x0, 0, MX51_PAD_CTRL_5)
#define MX51_PAD_NANDF_RDY_INT__GPIO_3_24 IOMUX_PAD(0x538, 0x150, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK IOMUX_PAD(0x538, 0x150, 1, 0x0, 0, MX51_PAD_CTRL_4)
#define MX51_PAD_NANDF_D15__GPIO_3_25 IOMUX_PAD(0x53C, 0x154, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D15__ECSPI2_MOSI IOMUX_PAD(0x53C, 0x154, 2, 0x0, 0, MX51_ECSPI_PAD_CTRL)
#define MX51_PAD_NANDF_D14__GPIO_3_26 IOMUX_PAD(0x540, 0x158, 3, 0x0, 0, NO_PAD_CTRL)
#define MX51_PAD_NANDF_D13__GPIO_3_27 IOMUX_PAD(0x544, 0x15C, 3, 0x0, 0, NO_PAD_CTRL)
#define MX51_PAD_NANDF_D12__GPIO_3_28 IOMUX_PAD(0x548, 0x160, 3, 0x0, 0, NO_PAD_CTRL)
@@ -185,15 +217,25 @@ typedef enum iomux_config {
#define MX51_PAD_I2C1_CLK__HSI2C_CLK IOMUX_PAD(0x5E8, 0x1F8, 0, 0x0, 0, NO_PAD_CTRL)
#define MX51_PAD_I2C1_DAT__GPIO_4_17 IOMUX_PAD(0x5EC, 0x1FC, 3, 0x0, 0, NO_PAD_CTRL)
#define MX51_PAD_I2C1_DAT__HSI2C_DAT IOMUX_PAD(0x5EC, 0x1FC, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_TXD__AUD3_BB_TXD IOMUX_PAD(0x5F0, 0x200, IOMUX_CONFIG_SION, 0x0, 0, NO_PAD_CTRL)
#define MX51_PAD_AUD3_BB_TXD__GPIO_4_18 IOMUX_PAD(0x5F0, 0x200, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_RXD__AUD3_BB_RXD IOMUX_PAD(0x5F4, 0x204, IOMUX_CONFIG_SION, 0x0, 0, NO_PAD_CTRL)
#define MX51_PAD_AUD3_BB_RXD__GPIO_4_19 IOMUX_PAD(0x5F4, 0x204, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_CK__AUD3_BB_CK IOMUX_PAD(0x5F8, 0x208, IOMUX_CONFIG_SION, 0x0, 0, NO_PAD_CTRL)
#define MX51_PAD_AUD3_BB_CK__GPIO_4_20 IOMUX_PAD(0x5F8, 0x208, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_FS__AUD3_BB_FS IOMUX_PAD(0x5FC, 0x20C, IOMUX_CONFIG_SION, 0x0, 0, NO_PAD_CTRL)
#define MX51_PAD_AUD3_BB_FS__GPIO_4_21 IOMUX_PAD(0x5FC, 0x20C, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI IOMUX_PAD(0x600, 0x210, 0, 0x0, 0, MX51_ECSPI_PAD_CTRL)
#define MX51_PAD_CSPI1_MOSI__GPIO_4_22 IOMUX_PAD(0x600, 0x210, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSPI1_MISO__ECSPI1_MISO IOMUX_PAD(0x604, 0x214, 0, 0x0, 0, MX51_ECSPI_PAD_CTRL)
#define MX51_PAD_CSPI1_MISO__GPIO_4_23 IOMUX_PAD(0x604, 0x214, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSPI1_SS0__ECSPI1_SS0 IOMUX_PAD(0x608, 0x218, 0, 0x0, 0, MX51_ECSPI_PAD_CTRL)
#define MX51_PAD_CSPI1_SS0__GPIO_4_24 IOMUX_PAD(0x608, 0x218, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSPI1_SS1__ECSPI1_SS1 IOMUX_PAD(0x60C, 0x21C, 0, 0x0, 0, MX51_ECSPI_PAD_CTRL)
#define MX51_PAD_CSPI1_SS1__GPIO_4_25 IOMUX_PAD(0x60C, 0x21C, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSPI1_RDY__ECSPI1_RDY IOMUX_PAD(0x610, 0x220, 0, 0x0, 0, MX51_ECSPI_PAD_CTRL)
#define MX51_PAD_CSPI1_RDY__GPIO_4_26 IOMUX_PAD(0x610, 0x220, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK IOMUX_PAD(0x614, 0x224, 0, 0x0, 0, MX51_ECSPI_PAD_CTRL)
#define MX51_PAD_CSPI1_SCLK__GPIO_4_27 IOMUX_PAD(0x614, 0x224, 3, 0x0, 0, NO_PAD_CTRL)
#define MX51_PAD_UART1_RXD__UART1_RXD IOMUX_PAD(0x618, 0x228, 0, 0x9e4, 0, MX51_UART1_PAD_CTRL | PAD_CTL_SRE_FAST)
#define MX51_PAD_UART1_TXD__UART1_TXD IOMUX_PAD(0x61C, 0x22C, 0, 0x0, 0, MX51_UART1_PAD_CTRL | PAD_CTL_SRE_FAST)
@@ -236,14 +278,14 @@ typedef enum iomux_config {
#define MX51_PAD_USBH1_DATA6__USBH1_DATA6 IOMUX_PAD(0x6A0, 0x2A0, 0, 0x0, 0, MX51_USBH1_PAD_CTRL)
#define MX51_PAD_USBH1_DATA7__USBH1_DATA7 IOMUX_PAD(0x6A4, 0x2A4, 0, 0x0, 0, MX51_USBH1_PAD_CTRL)
#define MX51_PAD_DI1_PIN11__GPIO_3_0 IOMUX_PAD(0x6A8, 0x2A8, 4, 0x0, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_PIN12__GPIO_3_1 IOMUX_PAD(0x6AC, 0x2AC, 4, 0x0, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_PIN13__GPIO_3_2 IOMUX_PAD(0x6B0, 0x2B0, 4, 0x0, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_D0_CS__GPIO_3_3 IOMUX_PAD(0x6B4, 0x2B4, 4, 0x0, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_D1_CS__GPIO_3_4 IOMUX_PAD(0x6B8, 0x2B8, 4, 0x0, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_DIN__GPIO_3_5 IOMUX_PAD(0x6BC, 0x2BC, 4, 0x0, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_DIO__GPIO_3_6 IOMUX_PAD(0x6C0, 0x2C0, 4, 0x0, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_CLK__GPIO_3_7 IOMUX_PAD(0x6C4, 0x2C4, 4, 0x0, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_RS__GPIO_3_8 IOMUX_PAD(0x6C8, 0x2C8, 4, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_PIN12__GPIO_3_1 IOMUX_PAD(0x6AC, 0x2AC, 4, 0x978, 1, NO_PAD_CTRL)
+#define MX51_PAD_DI1_PIN13__GPIO_3_2 IOMUX_PAD(0x6B0, 0x2B0, 4, 0x97c, 1, NO_PAD_CTRL)
+#define MX51_PAD_DI1_D0_CS__GPIO_3_3 IOMUX_PAD(0x6B4, 0x2B4, 4, 0x980, 1, NO_PAD_CTRL)
+#define MX51_PAD_DI1_D1_CS__GPIO_3_4 IOMUX_PAD(0x6B8, 0x2B8, 4, 0x984, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_DIN__GPIO_3_5 IOMUX_PAD(0x6BC, 0x2BC, 4, 0x988, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_DIO__GPIO_3_6 IOMUX_PAD(0x6C0, 0x2C0, 4, 0x98c, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_CLK__GPIO_3_7 IOMUX_PAD(0x6C4, 0x2C4, 4, 0x990, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_RS__GPIO_3_8 IOMUX_PAD(0x6C8, 0x2C8, 4, 0x994, 1, NO_PAD_CTRL)
#define MX51_PAD_DISP1_DAT0__DISP1_DAT0 IOMUX_PAD(0x6CC, 0x2CC, 0, 0x0, 0, NO_PAD_CTRL)
#define MX51_PAD_DISP1_DAT1__DISP1_DAT1 IOMUX_PAD(0x6D0, 0x2D0, 0, 0x0, 0, NO_PAD_CTRL)
#define MX51_PAD_DISP1_DAT2__DISP1_DAT2 IOMUX_PAD(0x6D4, 0x2D4, 0, 0x0, 0, NO_PAD_CTRL)
@@ -294,32 +336,50 @@ typedef enum iomux_config {
#define MX51_PAD_DISP2_DAT13__DISP2_DAT13 IOMUX_PAD(0x790, 0x388, 0, 0x0, 0, NO_PAD_CTRL)
#define MX51_PAD_DISP2_DAT14__DISP2_DAT14 IOMUX_PAD(0x794, 0x38C, 0, 0x0, 0, NO_PAD_CTRL)
#define MX51_PAD_DISP2_DAT15__DISP2_DAT15 IOMUX_PAD(0x798, 0x390, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX51_PAD_SD1_CMD__SD1_CMD IOMUX_PAD(0x79C, 0x394, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX51_PAD_SD1_CLK__SD1_CLK IOMUX_PAD(0x7A0, 0x398, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX51_PAD_SD1_DATA0__SD1_DATA0 IOMUX_PAD(0x7A4, 0x39C, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX51_PAD_SD1_DATA1__SD1_DATA1 IOMUX_PAD(0x7A8, 0x3A0, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX51_PAD_SD1_DATA2__SD1_DATA2 IOMUX_PAD(0x7AC, 0x3A4, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX51_PAD_SD1_DATA3__SD1_DATA3 IOMUX_PAD(0x7B0, 0x3A8, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO_1_0__GPIO_1_0 IOMUX_PAD(0x7B4, 0x3AC, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO_1_1__GPIO_1_1 IOMUX_PAD(0x7B8, 0x3B0, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_CMD__SD2_CMD IOMUX_PAD(0x7BC, 0x3B4, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_CLK__SD2_CLK IOMUX_PAD(0x7C0, 0x3B8, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_DATA0__SD2_DATA0 IOMUX_PAD(0x7C4, 0x3BC, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_DATA1__SD2_DATA1 IOMUX_PAD(0x7C8, 0x3C0, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_DATA2__SD2_DATA2 IOMUX_PAD(0x7CC, 0x3C4, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_DATA3__SD2_DATA3 IOMUX_PAD(0x7D0, 0x3C8, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO_1_2__GPIO_1_2 IOMUX_PAD(0x7D4, 0x3CC, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD1_CMD__SD1_CMD IOMUX_PAD(0x79C, 0x394, IOMUX_CONFIG_SION, 0x0, 0, \
+ MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD1_CMD__AUD5_RXFS IOMUX_PAD(0x79C, 0x394, 1, 0x8e0, 1, NO_PAD_CTRL)
+#define MX51_PAD_SD1_CLK__SD1_CLK IOMUX_PAD(0x7A0, 0x398, IOMUX_CONFIG_SION, 0x0, 0, \
+ MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
+#define MX51_PAD_SD1_CLK__AUD5_RXC IOMUX_PAD(0x7A0, 0x398, 1, 0x8dc, 1, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA0__SD1_DATA0 IOMUX_PAD(0x7A4, 0x39C, IOMUX_CONFIG_SION, 0x0, 0, \
+ MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD1_DATA0__AUD5_TXD IOMUX_PAD(0x7A4, 0x39C, 1, 0x8d8, 2, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA1__SD1_DATA1 IOMUX_PAD(0x7A8, 0x3A0, IOMUX_CONFIG_SION, 0x0, 0, \
+ MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD1_DATA1__AUD5_RXD IOMUX_PAD(0x7A8, 0x3A0, 1, 0x8d4, 2, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA2__SD1_DATA2 IOMUX_PAD(0x7AC, 0x3A4, IOMUX_CONFIG_SION, 0x0, 0, \
+ MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD1_DATA2__AUD5_TXC IOMUX_PAD(0x7AC, 0x3A4, 1, 0x8e4, 2, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA3__SD1_DATA3 IOMUX_PAD(0x7B0, 0x3A8, IOMUX_CONFIG_SION, 0x0, 0, \
+ MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD1_DATA3__AUD5_TXFS IOMUX_PAD(0x7B0, 0x3A8, 1, 0x8e8, 2, NO_PAD_CTRL)
+#define MX51_PAD_SD2_CMD__SD2_CMD IOMUX_PAD(0x7BC, 0x3B4, IOMUX_CONFIG_SION, 0x0, 1, \
+ MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD2_CLK__SD2_CLK IOMUX_PAD(0x7C0, 0x3B8, IOMUX_CONFIG_SION, 0x0, 0, \
+ MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
+#define MX51_PAD_SD2_DATA0__SD2_DATA0 IOMUX_PAD(0x7C4, 0x3BC, IOMUX_CONFIG_SION, 0x0, 0, \
+ MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD2_DATA1__SD2_DATA1 IOMUX_PAD(0x7C8, 0x3C0, IOMUX_CONFIG_SION, 0x0, 0, \
+ MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD2_DATA2__SD2_DATA2 IOMUX_PAD(0x7CC, 0x3C4, IOMUX_CONFIG_SION, 0x0, 0, \
+ MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD2_DATA3__SD2_DATA3 IOMUX_PAD(0x7D0, 0x3C8, IOMUX_CONFIG_SION, 0x0, 0, \
+ MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_GPIO_1_0__GPIO_1_0 IOMUX_PAD(0x7B4, 0x3AC, 1, 0x0, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_1__GPIO_1_1 IOMUX_PAD(0x7B8, 0x3B0, 1, 0x0, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_2__GPIO_1_2 IOMUX_PAD(0x7D4, 0x3CC, 1, 0x0, 0, MX51_GPIO_PAD_CTRL)
#define MX51_PAD_GPIO_1_2__I2C2_SCL IOMUX_PAD(0x7D4, 0x3CC, (2 | IOMUX_CONFIG_SION), \
0x9b8, 3, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_GPIO_1_3__GPIO_1_3 IOMUX_PAD(0x7D8, 0x3D0, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_3__GPIO_1_3 IOMUX_PAD(0x7D8, 0x3D0, 1, 0x0, 0, MX51_GPIO_PAD_CTRL)
#define MX51_PAD_GPIO_1_3__I2C2_SDA IOMUX_PAD(0x7D8, 0x3D0, (2 | IOMUX_CONFIG_SION), \
0x9bc, 3, MX51_I2C_PAD_CTRL)
#define MX51_PAD_PMIC_INT_REQ__PMIC_INT_REQ IOMUX_PAD(0x7FC, 0x3D4, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO_1_4__GPIO_1_4 IOMUX_PAD(0x804, 0x3D8, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO_1_5__GPIO_1_5 IOMUX_PAD(0x808, 0x3DC, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO_1_6__GPIO_1_6 IOMUX_PAD(0x80C, 0x3E0, 0, 0x0, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO_1_7__GPIO_1_7 IOMUX_PAD(0x810, 0x3E4, 0, 0x0, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO_1_8__GPIO_1_8 IOMUX_PAD(0x814, 0x3E8, 0, 0x0, 1, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO_1_9__GPIO_1_9 IOMUX_PAD(0x818, 0x3EC, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_4__GPIO_1_4 IOMUX_PAD(0x804, 0x3D8, 1, 0x0, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_5__GPIO_1_5 IOMUX_PAD(0x808, 0x3DC, 1, 0x0, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_6__GPIO_1_6 IOMUX_PAD(0x80C, 0x3E0, 1, 0x0, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_7__GPIO_1_7 IOMUX_PAD(0x810, 0x3E4, 1, 0x0, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_8__GPIO_1_8 IOMUX_PAD(0x814, 0x3E8, 1, 0x0, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_9__GPIO_1_9 IOMUX_PAD(0x818, 0x3EC, 1, 0x0, 0, MX51_GPIO_PAD_CTRL)
#endif /* __MACH_IOMUX_MX51_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/iram.h b/arch/arm/plat-mxc/include/mach/iram.h
new file mode 100644
index 000000000000..022690c33702
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/iram.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+#include <linux/errno.h>
+
+#ifdef CONFIG_IRAM_ALLOC
+
+int __init iram_init(unsigned long base, unsigned long size);
+void __iomem *iram_alloc(unsigned int size, unsigned long *dma_addr);
+void iram_free(unsigned long dma_addr, unsigned int size);
+
+#else
+
+static inline int __init iram_init(unsigned long base, unsigned long size)
+{
+ return -ENOMEM;
+}
+
+static inline void __iomem *iram_alloc(unsigned int size, unsigned long *dma_addr)
+{
+ return NULL;
+}
+
+static inline void iram_free(unsigned long base, unsigned long size) {}
+
+#endif
diff --git a/arch/arm/plat-mxc/include/mach/mx21.h b/arch/arm/plat-mxc/include/mach/mx21.h
index ed98b9c9f389..8bc59720b6e4 100644
--- a/arch/arm/plat-mxc/include/mach/mx21.h
+++ b/arch/arm/plat-mxc/include/mach/mx21.h
@@ -120,7 +120,7 @@
#define MX21_INT_GPT1 26
#define MX21_INT_WDOG 27
#define MX21_INT_PCMCIA 28
-#define MX21_INT_NANDFC 29
+#define MX21_INT_NFC 29
#define MX21_INT_BMI 30
#define MX21_INT_CSI 31
#define MX21_INT_DMACH0 32
diff --git a/arch/arm/plat-mxc/include/mach/mx25.h b/arch/arm/plat-mxc/include/mach/mx25.h
index 4a6f800990f8..cf46a45b0d4e 100644
--- a/arch/arm/plat-mxc/include/mach/mx25.h
+++ b/arch/arm/plat-mxc/include/mach/mx25.h
@@ -50,8 +50,11 @@
#define MX25_SSI1_BASE_ADDR 0x50034000
#define MX25_NFC_BASE_ADDR 0xbb000000
#define MX25_DRYICE_BASE_ADDR 0x53ffc000
+#define MX25_ESDHC1_BASE_ADDR 0x53fb4000
+#define MX25_ESDHC2_BASE_ADDR 0x53fb8000
#define MX25_LCDC_BASE_ADDR 0x53fbc000
#define MX25_KPP_BASE_ADDR 0x43fa8000
+#define MX25_SDMA_BASE_ADDR 0x53fd4000
#define MX25_OTG_BASE_ADDR 0x53ff4000
#define MX25_CSI_BASE_ADDR 0x53ff8000
@@ -59,6 +62,8 @@
#define MX25_INT_I2C1 3
#define MX25_INT_I2C2 4
#define MX25_INT_UART4 5
+#define MX25_INT_ESDHC2 8
+#define MX25_INT_ESDHC1 9
#define MX25_INT_I2C3 10
#define MX25_INT_SSI2 11
#define MX25_INT_SSI1 12
@@ -69,7 +74,8 @@
#define MX25_INT_KPP 24
#define MX25_INT_DRYICE 25
#define MX25_INT_UART2 32
-#define MX25_INT_NANDFC 33
+#define MX25_INT_NFC 33
+#define MX25_INT_SDMA 34
#define MX25_INT_LCDC 39
#define MX25_INT_UART5 40
#define MX25_INT_CAN1 43
@@ -77,4 +83,13 @@
#define MX25_INT_UART1 45
#define MX25_INT_FEC 57
+#define MX25_DMA_REQ_SSI2_RX1 22
+#define MX25_DMA_REQ_SSI2_TX1 23
+#define MX25_DMA_REQ_SSI2_RX0 24
+#define MX25_DMA_REQ_SSI2_TX0 25
+#define MX25_DMA_REQ_SSI1_RX1 26
+#define MX25_DMA_REQ_SSI1_TX1 27
+#define MX25_DMA_REQ_SSI1_RX0 28
+#define MX25_DMA_REQ_SSI1_TX0 29
+
#endif /* ifndef __MACH_MX25_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/mx27.h b/arch/arm/plat-mxc/include/mach/mx27.h
index a8ab2e02a8ca..2237ba2e5351 100644
--- a/arch/arm/plat-mxc/include/mach/mx27.h
+++ b/arch/arm/plat-mxc/include/mach/mx27.h
@@ -167,7 +167,7 @@ static inline void mx27_setup_weimcs(size_t cs,
#define MX27_INT_GPT1 26
#define MX27_INT_WDOG 27
#define MX27_INT_PCMCIA 28
-#define MX27_INT_NANDFC 29
+#define MX27_INT_NFC 29
#define MX27_INT_ATA 30
#define MX27_INT_CSI 31
#define MX27_INT_DMACH0 32
diff --git a/arch/arm/plat-mxc/include/mach/mx31.h b/arch/arm/plat-mxc/include/mach/mx31.h
index afee3ab9d62e..03e2afabc9fc 100644
--- a/arch/arm/plat-mxc/include/mach/mx31.h
+++ b/arch/arm/plat-mxc/include/mach/mx31.h
@@ -168,7 +168,7 @@ static inline void mx31_setup_weimcs(size_t cs,
#define MX31_INT_POWER_FAIL 30
#define MX31_INT_CCM_DVFS 31
#define MX31_INT_UART2 32
-#define MX31_INT_NANDFC 33
+#define MX31_INT_NFC 33
#define MX31_INT_SDMA 34
#define MX31_INT_USB1 35
#define MX31_INT_USB2 36
@@ -197,6 +197,15 @@ static inline void mx31_setup_weimcs(size_t cs,
#define MX31_INT_EXT_WDOG 62
#define MX31_INT_EXT_TV 63
+#define MX31_DMA_REQ_SSI2_RX1 22
+#define MX31_DMA_REQ_SSI2_TX1 23
+#define MX31_DMA_REQ_SSI2_RX0 24
+#define MX31_DMA_REQ_SSI2_TX0 25
+#define MX31_DMA_REQ_SSI1_RX1 26
+#define MX31_DMA_REQ_SSI1_TX1 27
+#define MX31_DMA_REQ_SSI1_RX0 28
+#define MX31_DMA_REQ_SSI1_TX0 29
+
#define MX31_PROD_SIGNATURE 0x1 /* For MX31 */
/* silicon revisions specific to i.MX31 */
diff --git a/arch/arm/plat-mxc/include/mach/mx35.h b/arch/arm/plat-mxc/include/mach/mx35.h
index af3038c12e39..ff905cb32458 100644
--- a/arch/arm/plat-mxc/include/mach/mx35.h
+++ b/arch/arm/plat-mxc/include/mach/mx35.h
@@ -1,5 +1,6 @@
#ifndef __MACH_MX35_H__
#define __MACH_MX35_H__
+
/*
* IRAM
*/
@@ -52,6 +53,9 @@
#define MX35_GPIO3_BASE_ADDR (MX35_AIPS2_BASE_ADDR + 0xa4000)
#define MX35_SCC_BASE_ADDR (MX35_AIPS2_BASE_ADDR + 0xac000)
#define MX35_RNGA_BASE_ADDR (MX35_AIPS2_BASE_ADDR + 0xb0000)
+#define MX35_ESDHC1_BASE_ADDR (MX35_AIPS2_BASE_ADDR + 0xb4000)
+#define MX35_ESDHC2_BASE_ADDR (MX35_AIPS2_BASE_ADDR + 0xb8000)
+#define MX35_ESDHC3_BASE_ADDR (MX35_AIPS2_BASE_ADDR + 0xbc000)
#define MX35_IPU_CTRL_BASE_ADDR (MX35_AIPS2_BASE_ADDR + 0xc0000)
#define MX35_AUDMUX_BASE_ADDR (MX35_AIPS2_BASE_ADDR + 0xc4000)
#define MX35_GPIO1_BASE_ADDR (MX35_AIPS2_BASE_ADDR + 0xcc000)
@@ -63,6 +67,8 @@
#define MX35_CAN1_BASE_ADDR (MX35_AIPS2_BASE_ADDR + 0xe4000)
#define MX35_CAN2_BASE_ADDR (MX35_AIPS2_BASE_ADDR + 0xe8000)
#define MX35_RTIC_BASE_ADDR (MX35_AIPS2_BASE_ADDR + 0xec000)
+#define MX35_IIM_BASE_ADDR (MX35_AIPS2_BASE_ADDR + 0xf0000)
+
#define MX35_OTG_BASE_ADDR 0x53ff4000
#define MX35_ROMP_BASE_ADDR 0x60000000
@@ -122,9 +128,9 @@
#define MX35_INT_I2C3 3
#define MX35_INT_I2C2 4
#define MX35_INT_RTIC 6
-#define MX35_INT_MMC_SDHC1 7
-#define MX35_INT_MMC_SDHC2 8
-#define MX35_INT_MMC_SDHC3 9
+#define MX35_INT_ESDHC1 7
+#define MX35_INT_ESDHC2 8
+#define MX35_INT_ESDHC3 9
#define MX35_INT_I2C1 10
#define MX35_INT_SSI1 11
#define MX35_INT_SSI2 12
@@ -145,7 +151,7 @@
#define MX35_INT_GPT 29
#define MX35_INT_POWER_FAIL 30
#define MX35_INT_UART2 32
-#define MX35_INT_NANDFC 33
+#define MX35_INT_NFC 33
#define MX35_INT_SDMA 34
#define MX35_INT_USBHS 35
#define MX35_INT_USBOTG 37
@@ -173,22 +179,18 @@
#define MX35_INT_EXT_WDOG 62
#define MX35_INT_EXT_TV 63
+#define MX35_DMA_REQ_SSI2_RX1 22
+#define MX35_DMA_REQ_SSI2_TX1 23
+#define MX35_DMA_REQ_SSI2_RX0 24
+#define MX35_DMA_REQ_SSI2_TX0 25
+#define MX35_DMA_REQ_SSI1_RX1 26
+#define MX35_DMA_REQ_SSI1_TX1 27
+#define MX35_DMA_REQ_SSI1_RX0 28
+#define MX35_DMA_REQ_SSI1_TX0 29
+
#define MX35_PROD_SIGNATURE 0x1 /* For MX31 */
-/* silicon revisions specific to i.MX31 */
-#define MX35_CHIP_REV_1_0 0x10
-#define MX35_CHIP_REV_1_1 0x11
-#define MX35_CHIP_REV_1_2 0x12
-#define MX35_CHIP_REV_1_3 0x13
-#define MX35_CHIP_REV_2_0 0x20
-#define MX35_CHIP_REV_2_1 0x21
-#define MX35_CHIP_REV_2_2 0x22
-#define MX35_CHIP_REV_2_3 0x23
-#define MX35_CHIP_REV_3_0 0x30
-#define MX35_CHIP_REV_3_1 0x31
-#define MX35_CHIP_REV_3_2 0x32
-
-#define MX35_SYSTEM_REV_MIN MX35_CHIP_REV_1_0
+#define MX35_SYSTEM_REV_MIN MX3x_CHIP_REV_1_0
#define MX35_SYSTEM_REV_NUM 3
#ifdef IMX_NEEDS_DEPRECATED_SYMBOLS
diff --git a/arch/arm/plat-mxc/include/mach/mx3x.h b/arch/arm/plat-mxc/include/mach/mx3x.h
index 7a356de385f5..d1bd26d7b8a6 100644
--- a/arch/arm/plat-mxc/include/mach/mx3x.h
+++ b/arch/arm/plat-mxc/include/mach/mx3x.h
@@ -240,7 +240,7 @@
#define MX3x_PROD_SIGNATURE 0x1 /* For MX31 */
-/* silicon revisions specific to i.MX31 */
+/* silicon revisions specific to i.MX31 and i.MX35 */
#define MX3x_CHIP_REV_1_0 0x10
#define MX3x_CHIP_REV_1_1 0x11
#define MX3x_CHIP_REV_1_2 0x12
@@ -267,6 +267,14 @@ static inline int mx31_revision(void)
{
return mx31_cpu_rev;
}
+
+extern unsigned int mx35_cpu_rev;
+extern void mx35_read_cpu_rev(void);
+
+static inline int mx35_revision(void)
+{
+ return mx35_cpu_rev;
+}
#endif
#ifdef IMX_NEEDS_DEPRECATED_SYMBOLS
@@ -389,19 +397,6 @@ static inline int mx31_revision(void)
#define MXC_INT_EXT_WDOG MX3x_INT_EXT_WDOG
#define MXC_INT_EXT_TV MX3x_INT_EXT_TV
#define PROD_SIGNATURE MX3x_PROD_SIGNATURE
-#define CHIP_REV_1_0 MX3x_CHIP_REV_1_0
-#define CHIP_REV_1_1 MX3x_CHIP_REV_1_1
-#define CHIP_REV_1_2 MX3x_CHIP_REV_1_2
-#define CHIP_REV_1_3 MX3x_CHIP_REV_1_3
-#define CHIP_REV_2_0 MX3x_CHIP_REV_2_0
-#define CHIP_REV_2_1 MX3x_CHIP_REV_2_1
-#define CHIP_REV_2_2 MX3x_CHIP_REV_2_2
-#define CHIP_REV_2_3 MX3x_CHIP_REV_2_3
-#define CHIP_REV_3_0 MX3x_CHIP_REV_3_0
-#define CHIP_REV_3_1 MX3x_CHIP_REV_3_1
-#define CHIP_REV_3_2 MX3x_CHIP_REV_3_2
-#define SYSTEM_REV_MIN MX3x_SYSTEM_REV_MIN
-#define SYSTEM_REV_NUM MX3x_SYSTEM_REV_NUM
#endif
#endif /* ifndef __MACH_MX3x_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/mx51.h b/arch/arm/plat-mxc/include/mach/mx51.h
index 5aad344d5651..2af7a1056fc1 100644
--- a/arch/arm/plat-mxc/include/mach/mx51.h
+++ b/arch/arm/plat-mxc/include/mach/mx51.h
@@ -1,5 +1,5 @@
-#ifndef __ASM_ARCH_MXC_MX51_H__
-#define __ASM_ARCH_MXC_MX51_H__
+#ifndef __MACH_MX51_H__
+#define __MACH_MX51_H__
/*
* MX51 memory map:
@@ -7,24 +7,23 @@
*
* Virt Phys Size What
* ---------------------------------------------------------------------------
- * FA3E0000 1FFE0000 128K IRAM (SCCv2 RAM)
+ * fa3e0000 1ffe0000 128K IRAM (SCCv2 RAM)
* 30000000 256M GPU
* 40000000 512M IPU
- * FA200000 60000000 1M DEBUG
- * FB100000 70000000 1M SPBA 0
- * FB000000 73F00000 1M AIPS 1
- * FB200000 83F00000 1M AIPS 2
- * 8FFFC000 16K TZIC (interrupt controller)
+ * fa200000 60000000 1M DEBUG
+ * fb100000 70000000 1M SPBA 0
+ * fb000000 73f00000 1M AIPS 1
+ * fb200000 83f00000 1M AIPS 2
+ * 8fffc000 16K TZIC (interrupt controller)
* 90000000 256M CSD0 SDRAM/DDR
- * A0000000 256M CSD1 SDRAM/DDR
- * B0000000 128M CS0 Flash
- * B8000000 128M CS1 Flash
- * C0000000 128M CS2 Flash
- * C8000000 64M CS3 Flash
- * CC000000 32M CS4 SRAM
- * CE000000 32M CS5 SRAM
- * CFFF0000 64K NFC (NAND Flash AXI)
- *
+ * a0000000 256M CSD1 SDRAM/DDR
+ * b0000000 128M CS0 Flash
+ * b8000000 128M CS1 Flash
+ * c0000000 128M CS2 Flash
+ * c8000000 64M CS3 Flash
+ * cc000000 32M CS4 SRAM
+ * ce000000 32M CS5 SRAM
+ * cfff0000 64K NFC (NAND Flash AXI)
*/
/*
@@ -36,65 +35,151 @@
/*
* IRAM
*/
-#define MX51_IRAM_BASE_ADDR 0x1FFE0000 /* internal ram */
-#define MX51_IRAM_BASE_ADDR_VIRT 0xFA3E0000
+#define MX51_IRAM_BASE_ADDR 0x1ffe0000 /* internal ram */
+#define MX51_IRAM_BASE_ADDR_VIRT 0xfa3e0000
#define MX51_IRAM_PARTITIONS 16
-#define MX51_IRAM_PARTITIONS_TO1 12
#define MX51_IRAM_SIZE (MX51_IRAM_PARTITIONS * SZ_8K) /* 128KB */
+#define MX51_GPU_BASE_ADDR 0x20000000
+#define MX51_GPU_CTRL_BASE_ADDR 0x30000000
+#define MX51_IPU_CTRL_BASE_ADDR 0x40000000
+
+#define MX51_DEBUG_BASE_ADDR 0x60000000
+#define MX51_DEBUG_BASE_ADDR_VIRT 0xfa200000
+#define MX51_DEBUG_SIZE SZ_1M
+
+#define MX51_ETB_BASE_ADDR (MX51_DEBUG_BASE_ADDR + 0x01000)
+#define MX51_ETM_BASE_ADDR (MX51_DEBUG_BASE_ADDR + 0x02000)
+#define MX51_TPIU_BASE_ADDR (MX51_DEBUG_BASE_ADDR + 0x03000)
+#define MX51_CTI0_BASE_ADDR (MX51_DEBUG_BASE_ADDR + 0x04000)
+#define MX51_CTI1_BASE_ADDR (MX51_DEBUG_BASE_ADDR + 0x05000)
+#define MX51_CTI2_BASE_ADDR (MX51_DEBUG_BASE_ADDR + 0x06000)
+#define MX51_CTI3_BASE_ADDR (MX51_DEBUG_BASE_ADDR + 0x07000)
+#define MX51_CORTEX_DBG_BASE_ADDR (MX51_DEBUG_BASE_ADDR + 0x08000)
+
/*
- * NFC
+ * SPBA global module enabled #0
*/
-#define MX51_NFC_AXI_BASE_ADDR 0xCFFF0000 /* NAND flash AXI */
-#define MX51_NFC_AXI_SIZE SZ_64K
+#define MX51_SPBA0_BASE_ADDR 0x70000000
+#define MX51_SPBA0_BASE_ADDR_VIRT 0xfb100000
+#define MX51_SPBA0_SIZE SZ_1M
+
+#define MX51_ESDHC1_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x04000)
+#define MX51_ESDHC2_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x08000)
+#define MX51_UART3_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x0c000)
+#define MX51_ECSPI1_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x10000)
+#define MX51_SSI2_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x14000)
+#define MX51_ESDHC3_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x20000)
+#define MX51_ESDHC4_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x24000)
+#define MX51_SPDIF_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x28000)
+#define MX51_ATA_DMA_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x30000)
+#define MX51_SLIM_DMA_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x34000)
+#define MX51_HSI2C_DMA_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x38000)
+#define MX51_SPBA_CTRL_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x3c000)
/*
- * Graphics Memory of GPU
+ * AIPS 1
*/
-#define MX51_GPU_BASE_ADDR 0x20000000
-#define MX51_GPU2D_BASE_ADDR 0xD0000000
+#define MX51_AIPS1_BASE_ADDR 0x73f00000
+#define MX51_AIPS1_BASE_ADDR_VIRT 0xfb000000
+#define MX51_AIPS1_SIZE SZ_1M
+
+#define MX51_OTG_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0x80000)
+#define MX51_GPIO1_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0x84000)
+#define MX51_GPIO2_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0x88000)
+#define MX51_GPIO3_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0x8c000)
+#define MX51_GPIO4_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0x90000)
+#define MX51_KPP_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0x94000)
+#define MX51_WDOG_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0x98000)
+#define MX51_WDOG2_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0x9c000)
+#define MX51_GPT1_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0xa0000)
+#define MX51_SRTC_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0xa4000)
+#define MX51_IOMUXC_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0xa8000)
+#define MX51_EPIT1_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0xac000)
+#define MX51_EPIT2_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0xb0000)
+#define MX51_PWM1_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0xb4000)
+#define MX51_PWM2_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0xb8000)
+#define MX51_UART1_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0xbc000)
+#define MX51_UART2_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0xc0000)
+#define MX51_SRC_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0xd0000)
+#define MX51_CCM_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0xd4000)
+#define MX51_GPC_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0xd8000)
-#define MX51_TZIC_BASE_ADDR_TO1 0x8FFFC000
-#define MX51_TZIC_BASE_ADDR 0xE0000000
+/*
+ * AIPS 2
+ */
+#define MX51_AIPS2_BASE_ADDR 0x83f00000
+#define MX51_AIPS2_BASE_ADDR_VIRT 0xfb200000
+#define MX51_AIPS2_SIZE SZ_1M
-#define MX51_DEBUG_BASE_ADDR 0x60000000
-#define MX51_DEBUG_BASE_ADDR_VIRT 0xFA200000
-#define MX51_DEBUG_SIZE SZ_1M
-#define MX51_ETB_BASE_ADDR (MX51_DEBUG_BASE_ADDR + 0x00001000)
-#define MX51_ETM_BASE_ADDR (MX51_DEBUG_BASE_ADDR + 0x00002000)
-#define MX51_TPIU_BASE_ADDR (MX51_DEBUG_BASE_ADDR + 0x00003000)
-#define MX51_CTI0_BASE_ADDR (MX51_DEBUG_BASE_ADDR + 0x00004000)
-#define MX51_CTI1_BASE_ADDR (MX51_DEBUG_BASE_ADDR + 0x00005000)
-#define MX51_CTI2_BASE_ADDR (MX51_DEBUG_BASE_ADDR + 0x00006000)
-#define MX51_CTI3_BASE_ADDR (MX51_DEBUG_BASE_ADDR + 0x00007000)
-#define MX51_CORTEX_DBG_BASE_ADDR (MX51_DEBUG_BASE_ADDR + 0x00008000)
+#define MX51_PLL1_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0x80000)
+#define MX51_PLL2_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0x84000)
+#define MX51_PLL3_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0x88000)
+#define MX51_AHBMAX_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0x94000)
+#define MX51_IIM_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0x98000)
+#define MX51_CSU_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0x9c000)
+#define MX51_ARM_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xa0000)
+#define MX51_OWIRE_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xa4000)
+#define MX51_FIRI_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xa8000)
+#define MX51_ECSPI2_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xac000)
+#define MX51_SDMA_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xb0000)
+#define MX51_SCC_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xb4000)
+#define MX51_ROMCP_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xb8000)
+#define MX51_RTIC_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xbc000)
+#define MX51_CSPI_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xc0000)
+#define MX51_I2C2_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xc4000)
+#define MX51_I2C1_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xc8000)
+#define MX51_SSI1_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xcc000)
+#define MX51_AUDMUX_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xd0000)
+#define MX51_M4IF_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xd8000)
+#define MX51_ESDCTL_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xd9000)
+#define MX51_WEIM_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xda000)
+#define MX51_NFC_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xdb000)
+#define MX51_EMI_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xdbf00)
+#define MX51_MIPI_HSC_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xdc000)
+#define MX51_ATA_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xe0000)
+#define MX51_SIM_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xe4000)
+#define MX51_SSI3BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xe8000)
+#define MX51_FEC_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xec000)
+#define MX51_TVE_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xf0000)
+#define MX51_VPU_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xf4000)
+#define MX51_SAHARA_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xf8000)
+
+#define MX51_CSD0_BASE_ADDR 0x90000000
+#define MX51_CSD1_BASE_ADDR 0xa0000000
+#define MX51_CS0_BASE_ADDR 0xb0000000
+#define MX51_CS1_BASE_ADDR 0xb8000000
+#define MX51_CS2_BASE_ADDR 0xc0000000
+#define MX51_CS3_BASE_ADDR 0xc8000000
+#define MX51_CS4_BASE_ADDR 0xcc000000
+#define MX51_CS5_BASE_ADDR 0xce000000
/*
- * SPBA global module enabled #0
+ * NFC
*/
-#define MX51_SPBA0_BASE_ADDR 0x70000000
-#define MX51_SPBA0_BASE_ADDR_VIRT 0xFB100000
-#define MX51_SPBA0_SIZE SZ_1M
+#define MX51_NFC_AXI_BASE_ADDR 0xcfff0000 /* NAND flash AXI */
+#define MX51_NFC_AXI_SIZE SZ_64K
+
+#define MX51_GPU2D_BASE_ADDR 0xd0000000
+#define MX51_TZIC_BASE_ADDR 0xe0000000
-#define MX51_MMC_SDHC1_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x00004000)
-#define MX51_MMC_SDHC2_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x00008000)
-#define MX51_UART3_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x0000C000)
-#define MX51_CSPI1_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x00010000)
-#define MX51_SSI2_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x00014000)
-#define MX51_MMC_SDHC3_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x00020000)
-#define MX51_MMC_SDHC4_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x00024000)
-#define MX51_SPDIF_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x00028000)
-#define MX51_ATA_DMA_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x00030000)
-#define MX51_SLIM_DMA_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x00034000)
-#define MX51_HSI2C_DMA_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x00038000)
-#define MX51_SPBA_CTRL_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x0003C000)
+#define MX51_IO_ADDRESS(x) ( \
+ IMX_IO_ADDRESS(x, MX51_IRAM) ?: \
+ IMX_IO_ADDRESS(x, MX51_DEBUG) ?: \
+ IMX_IO_ADDRESS(x, MX51_SPBA0) ?: \
+ IMX_IO_ADDRESS(x, MX51_AIPS1) ?: \
+ IMX_IO_ADDRESS(x, MX51_AIPS2))
+
+/* This is currently used in <mach/debug-macro.S>, but should go away */
+#define MX51_AIPS1_IO_ADDRESS(x) \
+ (((x) - MX51_AIPS1_BASE_ADDR) + MX51_AIPS1_BASE_ADDR_VIRT)
/*
* defines for SPBA modules
*/
#define MX51_SPBA_SDHC1 0x04
#define MX51_SPBA_SDHC2 0x08
-#define MX51_SPBA_UART3 0x0C
+#define MX51_SPBA_UART3 0x0c
#define MX51_SPBA_CSPI1 0x10
#define MX51_SPBA_SSI2 0x14
#define MX51_SPBA_SDHC3 0x20
@@ -103,35 +188,7 @@
#define MX51_SPBA_ATA 0x30
#define MX51_SPBA_SLIM 0x34
#define MX51_SPBA_HSI2C 0x38
-#define MX51_SPBA_CTRL 0x3C
-
-/*
- * AIPS 1
- */
-#define MX51_AIPS1_BASE_ADDR 0x73F00000
-#define MX51_AIPS1_BASE_ADDR_VIRT 0xFB000000
-#define MX51_AIPS1_SIZE SZ_1M
-
-#define MX51_OTG_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0x00080000)
-#define MX51_GPIO1_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0x00084000)
-#define MX51_GPIO2_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0x00088000)
-#define MX51_GPIO3_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0x0008C000)
-#define MX51_GPIO4_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0x00090000)
-#define MX51_KPP_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0x00094000)
-#define MX51_WDOG_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0x00098000)
-#define MX51_WDOG2_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0x0009C000)
-#define MX51_GPT1_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0x000A0000)
-#define MX51_SRTC_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0x000A4000)
-#define MX51_IOMUXC_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0x000A8000)
-#define MX51_EPIT1_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0x000AC000)
-#define MX51_EPIT2_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0x000B0000)
-#define MX51_PWM1_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0x000B4000)
-#define MX51_PWM2_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0x000B8000)
-#define MX51_UART1_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0x000BC000)
-#define MX51_UART2_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0x000C0000)
-#define MX51_SRC_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0x000D0000)
-#define MX51_CCM_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0x000D4000)
-#define MX51_GPC_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0x000D8000)
+#define MX51_SPBA_CTRL 0x3c
/*
* Defines for modules using static and dynamic DMA channels
@@ -164,282 +221,186 @@
#define MX51_MXC_DMA_CHANNEL_ATA_TX MXC_DMA_DYNAMIC_CHANNEL
#define MX51_MXC_DMA_CHANNEL_MEMORY MXC_DMA_DYNAMIC_CHANNEL
-/*
- * AIPS 2
- */
-#define MX51_AIPS2_BASE_ADDR 0x83F00000
-#define MX51_AIPS2_BASE_ADDR_VIRT 0xFB200000
-#define MX51_AIPS2_SIZE SZ_1M
-
-#define MX51_PLL1_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0x00080000)
-#define MX51_PLL2_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0x00084000)
-#define MX51_PLL3_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0x00088000)
-#define MX51_AHBMAX_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0x00094000)
-#define MX51_IIM_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0x00098000)
-#define MX51_CSU_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0x0009C000)
-#define MX51_ARM_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0x000A0000)
-#define MX51_OWIRE_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0x000A4000)
-#define MX51_FIRI_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0x000A8000)
-#define MX51_CSPI2_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0x000AC000)
-#define MX51_SDMA_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0x000B0000)
-#define MX51_SCC_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0x000B4000)
-#define MX51_ROMCP_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0x000B8000)
-#define MX51_RTIC_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0x000BC000)
-#define MX51_CSPI3_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0x000C0000)
-#define MX51_I2C2_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0x000C4000)
-#define MX51_I2C1_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0x000C8000)
-#define MX51_SSI1_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0x000CC000)
-#define MX51_AUDMUX_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0x000D0000)
-#define MX51_M4IF_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0x000D8000)
-#define MX51_ESDCTL_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0x000D9000)
-#define MX51_WEIM_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0x000DA000)
-#define MX51_NFC_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0x000DB000)
-#define MX51_EMI_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0x000DBF00)
-#define MX51_MIPI_HSC_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0x000DC000)
-#define MX51_ATA_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0x000E0000)
-#define MX51_SIM_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0x000E4000)
-#define MX51_SSI3BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0x000E8000)
-#define MX51_MXC_FEC_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0x000EC000)
-#define MX51_TVE_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0x000F0000)
-#define MX51_VPU_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0x000F4000)
-#define MX51_SAHARA_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0x000F8000)
-
-/*
- * Memory regions and CS
- */
-#define MX51_GPU_CTRL_BASE_ADDR 0x30000000
-#define MX51_IPU_CTRL_BASE_ADDR 0x40000000
-#define MX51_CSD0_BASE_ADDR 0x90000000
-#define MX51_CSD1_BASE_ADDR 0xA0000000
-#define MX51_CS0_BASE_ADDR 0xB0000000
-#define MX51_CS1_BASE_ADDR 0xB8000000
-#define MX51_CS2_BASE_ADDR 0xC0000000
-#define MX51_CS3_BASE_ADDR 0xC8000000
-#define MX51_CS4_BASE_ADDR 0xCC000000
-#define MX51_CS5_BASE_ADDR 0xCE000000
-
-/* Does given address belongs to the specified memory region? */
-#define ADDRESS_IN_REGION(addr, start, size) \
- (((addr) >= (start)) && ((addr) < (start)+(size)))
-
-/* Does given address belongs to the specified named `module'? */
-#define MX51_IS_MODULE(addr, module) \
- ADDRESS_IN_REGION(addr, MX51_ ## module ## _BASE_ADDR, \
- MX51_ ## module ## _SIZE)
-/*
- * This macro defines the physical to virtual address mapping for all the
- * peripheral modules. It is used by passing in the physical address as x
- * and returning the virtual address. If the physical address is not mapped,
- * it returns 0xDEADBEEF
- */
-
-#define MX51_IO_ADDRESS(x) \
- (void __iomem *) \
- (MX51_IS_MODULE(x, IRAM) ? MX51_IRAM_IO_ADDRESS(x) : \
- MX51_IS_MODULE(x, DEBUG) ? MX51_DEBUG_IO_ADDRESS(x) : \
- MX51_IS_MODULE(x, SPBA0) ? MX51_SPBA0_IO_ADDRESS(x) : \
- MX51_IS_MODULE(x, AIPS1) ? MX51_AIPS1_IO_ADDRESS(x) : \
- MX51_IS_MODULE(x, AIPS2) ? MX51_AIPS2_IO_ADDRESS(x) : \
- 0xDEADBEEF)
-
-/*
- * define the address mapping macros: in physical address order
- */
-#define MX51_IRAM_IO_ADDRESS(x) \
- (((x) - MX51_IRAM_BASE_ADDR) + MX51_IRAM_BASE_ADDR_VIRT)
-
-#define MX51_DEBUG_IO_ADDRESS(x) \
- (((x) - MX51_DEBUG_BASE_ADDR) + MX51_DEBUG_BASE_ADDR_VIRT)
-
-#define MX51_SPBA0_IO_ADDRESS(x) \
- (((x) - MX51_SPBA0_BASE_ADDR) + MX51_SPBA0_BASE_ADDR_VIRT)
-
-#define MX51_AIPS1_IO_ADDRESS(x) \
- (((x) - MX51_AIPS1_BASE_ADDR) + MX51_AIPS1_BASE_ADDR_VIRT)
-
-#define MX51_AIPS2_IO_ADDRESS(x) \
- (((x) - MX51_AIPS2_BASE_ADDR) + MX51_AIPS2_BASE_ADDR_VIRT)
-
#define MX51_IS_MEM_DEVICE_NONSHARED(x) 0
/*
* DMA request assignments
*/
-#define MX51_DMA_REQ_SSI3_TX1 47
-#define MX51_DMA_REQ_SSI3_RX1 46
-#define MX51_DMA_REQ_SPDIF 45
-#define MX51_DMA_REQ_UART3_TX 44
-#define MX51_DMA_REQ_UART3_RX 43
-#define MX51_DMA_REQ_SLIM_B_TX 42
-#define MX51_DMA_REQ_SDHC4 41
-#define MX51_DMA_REQ_SDHC3 40
-#define MX51_DMA_REQ_CSPI_TX 39
-#define MX51_DMA_REQ_CSPI_RX 38
-#define MX51_DMA_REQ_SSI3_TX2 37
-#define MX51_DMA_REQ_IPU 36
-#define MX51_DMA_REQ_SSI3_RX2 35
-#define MX51_DMA_REQ_EPIT2 34
-#define MX51_DMA_REQ_CTI2_1 33
-#define MX51_DMA_REQ_EMI_WR 32
-#define MX51_DMA_REQ_CTI2_0 31
-#define MX51_DMA_REQ_EMI_RD 30
-#define MX51_DMA_REQ_SSI1_TX1 29
-#define MX51_DMA_REQ_SSI1_RX1 28
-#define MX51_DMA_REQ_SSI1_TX2 27
-#define MX51_DMA_REQ_SSI1_RX2 26
-#define MX51_DMA_REQ_SSI2_TX1 25
-#define MX51_DMA_REQ_SSI2_RX1 24
-#define MX51_DMA_REQ_SSI2_TX2 23
-#define MX51_DMA_REQ_SSI2_RX2 22
-#define MX51_DMA_REQ_SDHC2 21
-#define MX51_DMA_REQ_SDHC1 20
-#define MX51_DMA_REQ_UART1_TX 19
-#define MX51_DMA_REQ_UART1_RX 18
-#define MX51_DMA_REQ_UART2_TX 17
-#define MX51_DMA_REQ_UART2_RX 16
-#define MX51_DMA_REQ_GPU 15
-#define MX51_DMA_REQ_EXTREQ1 14
-#define MX51_DMA_REQ_FIRI_TX 13
-#define MX51_DMA_REQ_FIRI_RX 12
-#define MX51_DMA_REQ_HS_I2C_RX 11
-#define MX51_DMA_REQ_HS_I2C_TX 10
-#define MX51_DMA_REQ_CSPI2_TX 9
-#define MX51_DMA_REQ_CSPI2_RX 8
-#define MX51_DMA_REQ_CSPI1_TX 7
-#define MX51_DMA_REQ_CSPI1_RX 6
-#define MX51_DMA_REQ_SLIM_B 5
-#define MX51_DMA_REQ_ATA_TX_END 4
-#define MX51_DMA_REQ_ATA_TX 3
-#define MX51_DMA_REQ_ATA_RX 2
-#define MX51_DMA_REQ_GPC 1
-#define MX51_DMA_REQ_VPU 0
+#define MX51_DMA_REQ_VPU 0
+#define MX51_DMA_REQ_GPC 1
+#define MX51_DMA_REQ_ATA_RX 2
+#define MX51_DMA_REQ_ATA_TX 3
+#define MX51_DMA_REQ_ATA_TX_END 4
+#define MX51_DMA_REQ_SLIM_B 5
+#define MX51_DMA_REQ_CSPI1_RX 6
+#define MX51_DMA_REQ_CSPI1_TX 7
+#define MX51_DMA_REQ_CSPI2_RX 8
+#define MX51_DMA_REQ_CSPI2_TX 9
+#define MX51_DMA_REQ_HS_I2C_TX 10
+#define MX51_DMA_REQ_HS_I2C_RX 11
+#define MX51_DMA_REQ_FIRI_RX 12
+#define MX51_DMA_REQ_FIRI_TX 13
+#define MX51_DMA_REQ_EXTREQ1 14
+#define MX51_DMA_REQ_GPU 15
+#define MX51_DMA_REQ_UART2_RX 16
+#define MX51_DMA_REQ_UART2_TX 17
+#define MX51_DMA_REQ_UART1_RX 18
+#define MX51_DMA_REQ_UART1_TX 19
+#define MX51_DMA_REQ_SDHC1 20
+#define MX51_DMA_REQ_SDHC2 21
+#define MX51_DMA_REQ_SSI2_RX1 22
+#define MX51_DMA_REQ_SSI2_TX1 23
+#define MX51_DMA_REQ_SSI2_RX0 24
+#define MX51_DMA_REQ_SSI2_TX0 25
+#define MX51_DMA_REQ_SSI1_RX1 26
+#define MX51_DMA_REQ_SSI1_TX1 27
+#define MX51_DMA_REQ_SSI1_RX0 28
+#define MX51_DMA_REQ_SSI1_TX0 29
+#define MX51_DMA_REQ_EMI_RD 30
+#define MX51_DMA_REQ_CTI2_0 31
+#define MX51_DMA_REQ_EMI_WR 32
+#define MX51_DMA_REQ_CTI2_1 33
+#define MX51_DMA_REQ_EPIT2 34
+#define MX51_DMA_REQ_SSI3_RX2 35
+#define MX51_DMA_REQ_IPU 36
+#define MX51_DMA_REQ_SSI3_TX2 37
+#define MX51_DMA_REQ_CSPI_RX 38
+#define MX51_DMA_REQ_CSPI_TX 39
+#define MX51_DMA_REQ_SDHC3 40
+#define MX51_DMA_REQ_SDHC4 41
+#define MX51_DMA_REQ_SLIM_B_TX 42
+#define MX51_DMA_REQ_UART3_RX 43
+#define MX51_DMA_REQ_UART3_TX 44
+#define MX51_DMA_REQ_SPDIF 45
+#define MX51_DMA_REQ_SSI3_RX1 46
+#define MX51_DMA_REQ_SSI3_TX1 47
/*
* Interrupt numbers
*/
-#define MX51_MXC_INT_BASE 0
-#define MX51_MXC_INT_RESV0 0
-#define MX51_MXC_INT_MMC_SDHC1 1
-#define MX51_MXC_INT_MMC_SDHC2 2
-#define MX51_MXC_INT_MMC_SDHC3 3
-#define MX51_MXC_INT_MMC_SDHC4 4
-#define MX51_MXC_INT_RESV5 5
-#define MX51_MXC_INT_SDMA 6
-#define MX51_MXC_INT_IOMUX 7
-#define MX51_MXC_INT_NFC 8
-#define MX51_MXC_INT_VPU 9
-#define MX51_MXC_INT_IPU_ERR 10
-#define MX51_MXC_INT_IPU_SYN 11
-#define MX51_MXC_INT_GPU 12
-#define MX51_MXC_INT_RESV13 13
-#define MX51_MXC_INT_USB_H1 14
-#define MX51_MXC_INT_EMI 15
-#define MX51_MXC_INT_USB_H2 16
-#define MX51_MXC_INT_USB_H3 17
-#define MX51_MXC_INT_USB_OTG 18
-#define MX51_MXC_INT_SAHARA_H0 19
-#define MX51_MXC_INT_SAHARA_H1 20
-#define MX51_MXC_INT_SCC_SMN 21
-#define MX51_MXC_INT_SCC_STZ 22
-#define MX51_MXC_INT_SCC_SCM 23
-#define MX51_MXC_INT_SRTC_NTZ 24
-#define MX51_MXC_INT_SRTC_TZ 25
-#define MX51_MXC_INT_RTIC 26
-#define MX51_MXC_INT_CSU 27
-#define MX51_MXC_INT_SLIM_B 28
-#define MX51_MXC_INT_SSI1 29
-#define MX51_MXC_INT_SSI2 30
-#define MX51_MXC_INT_UART1 31
-#define MX51_MXC_INT_UART2 32
-#define MX51_MXC_INT_UART3 33
-#define MX51_MXC_INT_RESV34 34
-#define MX51_MXC_INT_RESV35 35
-#define MX51_MXC_INT_CSPI1 36
-#define MX51_MXC_INT_CSPI2 37
-#define MX51_MXC_INT_CSPI 38
-#define MX51_MXC_INT_GPT 39
-#define MX51_MXC_INT_EPIT1 40
-#define MX51_MXC_INT_EPIT2 41
-#define MX51_MXC_INT_GPIO1_INT7 42
-#define MX51_MXC_INT_GPIO1_INT6 43
-#define MX51_MXC_INT_GPIO1_INT5 44
-#define MX51_MXC_INT_GPIO1_INT4 45
-#define MX51_MXC_INT_GPIO1_INT3 46
-#define MX51_MXC_INT_GPIO1_INT2 47
-#define MX51_MXC_INT_GPIO1_INT1 48
-#define MX51_MXC_INT_GPIO1_INT0 49
-#define MX51_MXC_INT_GPIO1_LOW 50
-#define MX51_MXC_INT_GPIO1_HIGH 51
-#define MX51_MXC_INT_GPIO2_LOW 52
-#define MX51_MXC_INT_GPIO2_HIGH 53
-#define MX51_MXC_INT_GPIO3_LOW 54
-#define MX51_MXC_INT_GPIO3_HIGH 55
-#define MX51_MXC_INT_GPIO4_LOW 56
-#define MX51_MXC_INT_GPIO4_HIGH 57
-#define MX51_MXC_INT_WDOG1 58
-#define MX51_MXC_INT_WDOG2 59
-#define MX51_MXC_INT_KPP 60
-#define MX51_MXC_INT_PWM1 61
-#define MX51_MXC_INT_I2C1 62
-#define MX51_MXC_INT_I2C2 63
-#define MX51_MXC_INT_HS_I2C 64
-#define MX51_MXC_INT_RESV65 65
-#define MX51_MXC_INT_RESV66 66
-#define MX51_MXC_INT_SIM_IPB 67
-#define MX51_MXC_INT_SIM_DAT 68
-#define MX51_MXC_INT_IIM 69
-#define MX51_MXC_INT_ATA 70
-#define MX51_MXC_INT_CCM1 71
-#define MX51_MXC_INT_CCM2 72
-#define MX51_MXC_INT_GPC1 73
-#define MX51_MXC_INT_GPC2 74
-#define MX51_MXC_INT_SRC 75
-#define MX51_MXC_INT_NM 76
-#define MX51_MXC_INT_PMU 77
-#define MX51_MXC_INT_CTI_IRQ 78
-#define MX51_MXC_INT_CTI1_TG0 79
-#define MX51_MXC_INT_CTI1_TG1 80
-#define MX51_MXC_INT_MCG_ERR 81
-#define MX51_MXC_INT_MCG_TMR 82
-#define MX51_MXC_INT_MCG_FUNC 83
-#define MX51_MXC_INT_GPU2_IRQ 84
-#define MX51_MXC_INT_GPU2_BUSY 85
-#define MX51_MXC_INT_RESV86 86
-#define MX51_MXC_INT_FEC 87
-#define MX51_MXC_INT_OWIRE 88
-#define MX51_MXC_INT_CTI1_TG2 89
-#define MX51_MXC_INT_SJC 90
-#define MX51_MXC_INT_SPDIF 91
-#define MX51_MXC_INT_TVE 92
-#define MX51_MXC_INT_FIRI 93
-#define MX51_MXC_INT_PWM2 94
-#define MX51_MXC_INT_SLIM_EXP 95
-#define MX51_MXC_INT_SSI3 96
-#define MX51_MXC_INT_EMI_BOOT 97
-#define MX51_MXC_INT_CTI1_TG3 98
-#define MX51_MXC_INT_SMC_RX 99
-#define MX51_MXC_INT_VPU_IDLE 100
-#define MX51_MXC_INT_EMI_NFC 101
-#define MX51_MXC_INT_GPU_IDLE 102
+#define MX51_MXC_INT_BASE 0
+#define MX51_MXC_INT_RESV0 0
+#define MX51_INT_ESDHC1 1
+#define MX51_INT_ESDHC2 2
+#define MX51_INT_ESDHC3 3
+#define MX51_INT_ESDHC4 4
+#define MX51_MXC_INT_RESV5 5
+#define MX51_INT_SDMA 6
+#define MX51_MXC_INT_IOMUX 7
+#define MX51_INT_NFC 8
+#define MX51_MXC_INT_VPU 9
+#define MX51_MXC_INT_IPU_ERR 10
+#define MX51_MXC_INT_IPU_SYN 11
+#define MX51_MXC_INT_GPU 12
+#define MX51_MXC_INT_RESV13 13
+#define MX51_MXC_INT_USB_H1 14
+#define MX51_MXC_INT_EMI 15
+#define MX51_MXC_INT_USB_H2 16
+#define MX51_MXC_INT_USB_H3 17
+#define MX51_MXC_INT_USB_OTG 18
+#define MX51_MXC_INT_SAHARA_H0 19
+#define MX51_MXC_INT_SAHARA_H1 20
+#define MX51_MXC_INT_SCC_SMN 21
+#define MX51_MXC_INT_SCC_STZ 22
+#define MX51_MXC_INT_SCC_SCM 23
+#define MX51_MXC_INT_SRTC_NTZ 24
+#define MX51_MXC_INT_SRTC_TZ 25
+#define MX51_MXC_INT_RTIC 26
+#define MX51_MXC_INT_CSU 27
+#define MX51_MXC_INT_SLIM_B 28
+#define MX51_INT_SSI1 29
+#define MX51_INT_SSI2 30
+#define MX51_INT_UART1 31
+#define MX51_INT_UART2 32
+#define MX51_INT_UART3 33
+#define MX51_MXC_INT_RESV34 34
+#define MX51_MXC_INT_RESV35 35
+#define MX51_INT_ECSPI1 36
+#define MX51_INT_ECSPI2 37
+#define MX51_INT_CSPI 38
+#define MX51_MXC_INT_GPT 39
+#define MX51_MXC_INT_EPIT1 40
+#define MX51_MXC_INT_EPIT2 41
+#define MX51_MXC_INT_GPIO1_INT7 42
+#define MX51_MXC_INT_GPIO1_INT6 43
+#define MX51_MXC_INT_GPIO1_INT5 44
+#define MX51_MXC_INT_GPIO1_INT4 45
+#define MX51_MXC_INT_GPIO1_INT3 46
+#define MX51_MXC_INT_GPIO1_INT2 47
+#define MX51_MXC_INT_GPIO1_INT1 48
+#define MX51_MXC_INT_GPIO1_INT0 49
+#define MX51_MXC_INT_GPIO1_LOW 50
+#define MX51_MXC_INT_GPIO1_HIGH 51
+#define MX51_MXC_INT_GPIO2_LOW 52
+#define MX51_MXC_INT_GPIO2_HIGH 53
+#define MX51_MXC_INT_GPIO3_LOW 54
+#define MX51_MXC_INT_GPIO3_HIGH 55
+#define MX51_MXC_INT_GPIO4_LOW 56
+#define MX51_MXC_INT_GPIO4_HIGH 57
+#define MX51_MXC_INT_WDOG1 58
+#define MX51_MXC_INT_WDOG2 59
+#define MX51_MXC_INT_KPP 60
+#define MX51_MXC_INT_PWM1 61
+#define MX51_INT_I2C1 62
+#define MX51_INT_I2C2 63
+#define MX51_MXC_INT_HS_I2C 64
+#define MX51_MXC_INT_RESV65 65
+#define MX51_MXC_INT_RESV66 66
+#define MX51_MXC_INT_SIM_IPB 67
+#define MX51_MXC_INT_SIM_DAT 68
+#define MX51_MXC_INT_IIM 69
+#define MX51_MXC_INT_ATA 70
+#define MX51_MXC_INT_CCM1 71
+#define MX51_MXC_INT_CCM2 72
+#define MX51_MXC_INT_GPC1 73
+#define MX51_MXC_INT_GPC2 74
+#define MX51_MXC_INT_SRC 75
+#define MX51_MXC_INT_NM 76
+#define MX51_MXC_INT_PMU 77
+#define MX51_MXC_INT_CTI_IRQ 78
+#define MX51_MXC_INT_CTI1_TG0 79
+#define MX51_MXC_INT_CTI1_TG1 80
+#define MX51_MXC_INT_MCG_ERR 81
+#define MX51_MXC_INT_MCG_TMR 82
+#define MX51_MXC_INT_MCG_FUNC 83
+#define MX51_MXC_INT_GPU2_IRQ 84
+#define MX51_MXC_INT_GPU2_BUSY 85
+#define MX51_MXC_INT_RESV86 86
+#define MX51_INT_FEC 87
+#define MX51_MXC_INT_OWIRE 88
+#define MX51_MXC_INT_CTI1_TG2 89
+#define MX51_MXC_INT_SJC 90
+#define MX51_MXC_INT_SPDIF 91
+#define MX51_MXC_INT_TVE 92
+#define MX51_MXC_INT_FIRI 93
+#define MX51_MXC_INT_PWM2 94
+#define MX51_MXC_INT_SLIM_EXP 95
+#define MX51_MXC_INT_SSI3 96
+#define MX51_MXC_INT_EMI_BOOT 97
+#define MX51_MXC_INT_CTI1_TG3 98
+#define MX51_MXC_INT_SMC_RX 99
+#define MX51_MXC_INT_VPU_IDLE 100
+#define MX51_MXC_INT_EMI_NFC 101
+#define MX51_MXC_INT_GPU_IDLE 102
/* silicon revisions specific to i.MX51 */
-#define MX51_CHIP_REV_1_0 0x10
-#define MX51_CHIP_REV_1_1 0x11
-#define MX51_CHIP_REV_1_2 0x12
-#define MX51_CHIP_REV_1_3 0x13
-#define MX51_CHIP_REV_2_0 0x20
-#define MX51_CHIP_REV_2_1 0x21
-#define MX51_CHIP_REV_2_2 0x22
-#define MX51_CHIP_REV_2_3 0x23
-#define MX51_CHIP_REV_3_0 0x30
-#define MX51_CHIP_REV_3_1 0x31
-#define MX51_CHIP_REV_3_2 0x32
-
-/* Mandatory defines used globally */
+#define MX51_CHIP_REV_1_0 0x10
+#define MX51_CHIP_REV_1_1 0x11
+#define MX51_CHIP_REV_1_2 0x12
+#define MX51_CHIP_REV_1_3 0x13
+#define MX51_CHIP_REV_2_0 0x20
+#define MX51_CHIP_REV_2_1 0x21
+#define MX51_CHIP_REV_2_2 0x22
+#define MX51_CHIP_REV_2_3 0x23
+#define MX51_CHIP_REV_3_0 0x30
+#define MX51_CHIP_REV_3_1 0x31
+#define MX51_CHIP_REV_3_2 0x32
#if !defined(__ASSEMBLY__) && !defined(__MXC_BOOT_UNCOMPRESS)
-
extern int mx51_revision(void);
#endif
-#endif /* __ASM_ARCH_MXC_MX51_H__ */
+/* tape-out 1 defines */
+#define MX51_TZIC_BASE_ADDR_TO1 0x8fffc000
+
+#endif /* ifndef __MACH_MX51_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/system.h b/arch/arm/plat-mxc/include/mach/system.h
index 4acd1143a9bd..95be51bfe9a9 100644
--- a/arch/arm/plat-mxc/include/mach/system.h
+++ b/arch/arm/plat-mxc/include/mach/system.h
@@ -1,7 +1,7 @@
/*
* Copyright (C) 1999 ARM Limited
* Copyright (C) 2000 Deep Blue Solutions Ltd
- * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2004-2008 Freescale Semiconductor, Inc. All Rights Reserved.
*
* 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
@@ -28,8 +28,34 @@ static inline void arch_idle(void)
mxc91231_prepare_idle();
}
#endif
-
- cpu_do_idle();
+ /* fix i.MX31 errata TLSbo65953 and i.MX35 errata ENGcm09472 */
+ if (cpu_is_mx31() || cpu_is_mx35()) {
+ unsigned long reg = 0;
+ __asm__ __volatile__(
+ /* disable I and D cache */
+ "mrc p15, 0, %0, c1, c0, 0\n"
+ "bic %0, %0, #0x00001000\n"
+ "bic %0, %0, #0x00000004\n"
+ "mcr p15, 0, %0, c1, c0, 0\n"
+ /* invalidate I cache */
+ "mov %0, #0\n"
+ "mcr p15, 0, %0, c7, c5, 0\n"
+ /* clear and invalidate D cache */
+ "mov %0, #0\n"
+ "mcr p15, 0, %0, c7, c14, 0\n"
+ /* WFI */
+ "mov %0, #0\n"
+ "mcr p15, 0, %0, c7, c0, 4\n"
+ "nop\n" "nop\n" "nop\n" "nop\n"
+ "nop\n" "nop\n" "nop\n"
+ /* enable I and D cache */
+ "mrc p15, 0, %0, c1, c0, 0\n"
+ "orr %0, %0, #0x00001000\n"
+ "orr %0, %0, #0x00000004\n"
+ "mcr p15, 0, %0, c1, c0, 0\n"
+ : "=r" (reg));
+ } else
+ cpu_do_idle();
}
void arch_reset(char mode, const char *cmd);
diff --git a/arch/arm/plat-mxc/include/mach/uncompress.h b/arch/arm/plat-mxc/include/mach/uncompress.h
index d9bd37e4667a..9dd9c2085aad 100644
--- a/arch/arm/plat-mxc/include/mach/uncompress.h
+++ b/arch/arm/plat-mxc/include/mach/uncompress.h
@@ -99,6 +99,7 @@ static __inline__ void __arch_decomp_setup(unsigned long arch_id)
uart_base = MX3X_UART2_BASE_ADDR;
break;
case MACH_TYPE_MX51_BABBAGE:
+ case MACH_TYPE_EUKREA_CPUIMX51SD:
uart_base = MX51_UART1_BASE_ADDR;
break;
default:
diff --git a/arch/arm/plat-mxc/iram_alloc.c b/arch/arm/plat-mxc/iram_alloc.c
new file mode 100644
index 000000000000..074c3869626a
--- /dev/null
+++ b/arch/arm/plat-mxc/iram_alloc.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/genalloc.h>
+#include <mach/iram.h>
+
+static unsigned long iram_phys_base;
+static void __iomem *iram_virt_base;
+static struct gen_pool *iram_pool;
+
+static inline void __iomem *iram_phys_to_virt(unsigned long p)
+{
+ return iram_virt_base + (p - iram_phys_base);
+}
+
+void __iomem *iram_alloc(unsigned int size, unsigned long *dma_addr)
+{
+ if (!iram_pool)
+ return NULL;
+
+ *dma_addr = gen_pool_alloc(iram_pool, size);
+ pr_debug("iram alloc - %dB@0x%lX\n", size, *dma_addr);
+ if (!*dma_addr)
+ return NULL;
+ return iram_phys_to_virt(*dma_addr);
+}
+EXPORT_SYMBOL(iram_alloc);
+
+void iram_free(unsigned long addr, unsigned int size)
+{
+ if (!iram_pool)
+ return;
+
+ gen_pool_free(iram_pool, addr, size);
+}
+EXPORT_SYMBOL(iram_free);
+
+int __init iram_init(unsigned long base, unsigned long size)
+{
+ iram_phys_base = base;
+
+ iram_pool = gen_pool_create(PAGE_SHIFT, -1);
+ if (!iram_pool)
+ return -ENOMEM;
+
+ gen_pool_add(iram_pool, base, size, -1);
+ iram_virt_base = ioremap(iram_phys_base, size);
+ if (!iram_virt_base)
+ return -EIO;
+
+ pr_debug("i.MX IRAM pool: %ld KB@0x%p\n", size / 1024, iram_virt_base);
+ return 0;
+}
diff --git a/arch/arm/plat-nomadik/gpio.c b/arch/arm/plat-nomadik/gpio.c
index 977c8f9a07a2..85e6fd212a41 100644
--- a/arch/arm/plat-nomadik/gpio.c
+++ b/arch/arm/plat-nomadik/gpio.c
@@ -102,6 +102,22 @@ static void __nmk_gpio_make_input(struct nmk_gpio_chip *nmk_chip,
writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRC);
}
+static void __nmk_gpio_set_output(struct nmk_gpio_chip *nmk_chip,
+ unsigned offset, int val)
+{
+ if (val)
+ writel(1 << offset, nmk_chip->addr + NMK_GPIO_DATS);
+ else
+ writel(1 << offset, nmk_chip->addr + NMK_GPIO_DATC);
+}
+
+static void __nmk_gpio_make_output(struct nmk_gpio_chip *nmk_chip,
+ unsigned offset, int val)
+{
+ writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRS);
+ __nmk_gpio_set_output(nmk_chip, offset, val);
+}
+
static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset,
pin_cfg_t cfg)
{
@@ -118,20 +134,29 @@ static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset,
[3] /* illegal */ = "??"
};
static const char *slpmnames[] = {
- [NMK_GPIO_SLPM_INPUT] = "input",
- [NMK_GPIO_SLPM_NOCHANGE] = "no-change",
+ [NMK_GPIO_SLPM_INPUT] = "input/wakeup",
+ [NMK_GPIO_SLPM_NOCHANGE] = "no-change/no-wakeup",
};
int pin = PIN_NUM(cfg);
int pull = PIN_PULL(cfg);
int af = PIN_ALT(cfg);
int slpm = PIN_SLPM(cfg);
+ int output = PIN_DIR(cfg);
+ int val = PIN_VAL(cfg);
- dev_dbg(nmk_chip->chip.dev, "pin %d: af %s, pull %s, slpm %s\n",
- pin, afnames[af], pullnames[pull], slpmnames[slpm]);
+ dev_dbg(nmk_chip->chip.dev, "pin %d: af %s, pull %s, slpm %s (%s%s)\n",
+ pin, afnames[af], pullnames[pull], slpmnames[slpm],
+ output ? "output " : "input",
+ output ? (val ? "high" : "low") : "");
+
+ if (output)
+ __nmk_gpio_make_output(nmk_chip, offset, val);
+ else {
+ __nmk_gpio_make_input(nmk_chip, offset);
+ __nmk_gpio_set_pull(nmk_chip, offset, pull);
+ }
- __nmk_gpio_make_input(nmk_chip, offset);
- __nmk_gpio_set_pull(nmk_chip, offset, pull);
__nmk_gpio_set_slpm(nmk_chip, offset, slpm);
__nmk_gpio_set_mode(nmk_chip, offset, af);
}
@@ -200,6 +225,10 @@ EXPORT_SYMBOL(nmk_config_pins);
* changed to an input (with pullup/down enabled) in sleep and deep sleep. If
* @mode is NMK_GPIO_SLPM_NOCHANGE, the pin remains in the state it was
* configured even when in sleep and deep sleep.
+ *
+ * On DB8500v2 onwards, this setting loses the previous meaning and instead
+ * indicates if wakeup detection is enabled on the pin. Note that
+ * enable_irq_wake() will automatically enable wakeup detection.
*/
int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode)
{
@@ -367,7 +396,27 @@ static void nmk_gpio_irq_unmask(unsigned int irq)
static int nmk_gpio_irq_set_wake(unsigned int irq, unsigned int on)
{
- return nmk_gpio_irq_modify(irq, WAKE, on);
+ struct nmk_gpio_chip *nmk_chip;
+ unsigned long flags;
+ int gpio;
+
+ gpio = NOMADIK_IRQ_TO_GPIO(irq);
+ nmk_chip = get_irq_chip_data(irq);
+ if (!nmk_chip)
+ return -EINVAL;
+
+ spin_lock_irqsave(&nmk_chip->lock, flags);
+#ifdef CONFIG_ARCH_U8500
+ if (cpu_is_u8500v2()) {
+ __nmk_gpio_set_slpm(nmk_chip, gpio,
+ on ? NMK_GPIO_SLPM_WAKEUP_ENABLE
+ : NMK_GPIO_SLPM_WAKEUP_DISABLE);
+ }
+#endif
+ __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, on);
+ spin_unlock_irqrestore(&nmk_chip->lock, flags);
+
+ return 0;
}
static int nmk_gpio_irq_set_type(unsigned int irq, unsigned int type)
@@ -495,12 +544,8 @@ static void nmk_gpio_set_output(struct gpio_chip *chip, unsigned offset,
{
struct nmk_gpio_chip *nmk_chip =
container_of(chip, struct nmk_gpio_chip, chip);
- u32 bit = 1 << offset;
- if (val)
- writel(bit, nmk_chip->addr + NMK_GPIO_DATS);
- else
- writel(bit, nmk_chip->addr + NMK_GPIO_DATC);
+ __nmk_gpio_set_output(nmk_chip, offset, val);
}
static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned offset,
@@ -509,8 +554,7 @@ static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned offset,
struct nmk_gpio_chip *nmk_chip =
container_of(chip, struct nmk_gpio_chip, chip);
- writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRS);
- nmk_gpio_set_output(chip, offset, val);
+ __nmk_gpio_make_output(nmk_chip, offset, val);
return 0;
}
@@ -534,7 +578,7 @@ static struct gpio_chip nmk_gpio_template = {
.can_sleep = 0,
};
-static int __init nmk_gpio_probe(struct platform_device *dev)
+static int __devinit nmk_gpio_probe(struct platform_device *dev)
{
struct nmk_gpio_platform_data *pdata = dev->dev.platform_data;
struct nmk_gpio_chip *nmk_chip;
diff --git a/arch/arm/plat-nomadik/include/plat/gpio.h b/arch/arm/plat-nomadik/include/plat/gpio.h
index aba355101f49..67b113d639d8 100644
--- a/arch/arm/plat-nomadik/include/plat/gpio.h
+++ b/arch/arm/plat-nomadik/include/plat/gpio.h
@@ -65,7 +65,9 @@ enum nmk_gpio_pull {
/* Sleep mode */
enum nmk_gpio_slpm {
NMK_GPIO_SLPM_INPUT,
+ NMK_GPIO_SLPM_WAKEUP_ENABLE = NMK_GPIO_SLPM_INPUT,
NMK_GPIO_SLPM_NOCHANGE,
+ NMK_GPIO_SLPM_WAKEUP_DISABLE = NMK_GPIO_SLPM_NOCHANGE,
};
extern int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode);
diff --git a/arch/arm/plat-nomadik/include/plat/pincfg.h b/arch/arm/plat-nomadik/include/plat/pincfg.h
index 7eed11c1038d..8c5ae3f2acf8 100644
--- a/arch/arm/plat-nomadik/include/plat/pincfg.h
+++ b/arch/arm/plat-nomadik/include/plat/pincfg.h
@@ -19,12 +19,16 @@
* bit 9..10 - Alternate Function Selection
* bit 11..12 - Pull up/down state
* bit 13 - Sleep mode behaviour
+ * bit 14 - (sleep mode) Direction
+ * bit 15 - (sleep mode) Value (if output)
*
* to facilitate the definition, the following macros are provided
*
* PIN_CFG_DEFAULT - default config (0):
* pull up/down = disabled
- * sleep mode = input
+ * sleep mode = input/wakeup
+ * (sleep mode) direction = input
+ * (sleep mode) value = low
*
* PIN_CFG - default config with alternate function
* PIN_CFG_PULL - default config with alternate function and pull up/down
@@ -53,8 +57,36 @@ typedef unsigned long pin_cfg_t;
#define PIN_SLPM_SHIFT 13
#define PIN_SLPM_MASK (0x1 << PIN_SLPM_SHIFT)
#define PIN_SLPM(x) (((x) & PIN_SLPM_MASK) >> PIN_SLPM_SHIFT)
-#define PIN_SLPM_INPUT (NMK_GPIO_SLPM_INPUT << PIN_SLPM_SHIFT)
+#define PIN_SLPM_MAKE_INPUT (NMK_GPIO_SLPM_INPUT << PIN_SLPM_SHIFT)
#define PIN_SLPM_NOCHANGE (NMK_GPIO_SLPM_NOCHANGE << PIN_SLPM_SHIFT)
+/* These two replace the above in DB8500v2+ */
+#define PIN_SLPM_WAKEUP_ENABLE (NMK_GPIO_SLPM_WAKEUP_ENABLE << PIN_SLPM_SHIFT)
+#define PIN_SLPM_WAKEUP_DISABLE (NMK_GPIO_SLPM_WAKEUP_DISABLE << PIN_SLPM_SHIFT)
+
+#define PIN_DIR_SHIFT 14
+#define PIN_DIR_MASK (0x1 << PIN_DIR_SHIFT)
+#define PIN_DIR(x) (((x) & PIN_DIR_MASK) >> PIN_DIR_SHIFT)
+#define PIN_DIR_INPUT (0 << PIN_DIR_SHIFT)
+#define PIN_DIR_OUTPUT (1 << PIN_DIR_SHIFT)
+
+#define PIN_VAL_SHIFT 15
+#define PIN_VAL_MASK (0x1 << PIN_VAL_SHIFT)
+#define PIN_VAL(x) (((x) & PIN_VAL_MASK) >> PIN_VAL_SHIFT)
+#define PIN_VAL_LOW (0 << PIN_VAL_SHIFT)
+#define PIN_VAL_HIGH (1 << PIN_VAL_SHIFT)
+
+/* Shortcuts. Use these instead of separate DIR and VAL. */
+#define PIN_INPUT PIN_DIR_INPUT
+#define PIN_OUTPUT_LOW (PIN_DIR_OUTPUT | PIN_VAL_LOW)
+#define PIN_OUTPUT_HIGH (PIN_DIR_OUTPUT | PIN_VAL_HIGH)
+
+/*
+ * These are the same as the ones above, but should make more sense to the
+ * reader when seen along with a setting a pin to AF mode.
+ */
+#define PIN_SLPM_INPUT PIN_INPUT
+#define PIN_SLPM_OUTPUT_LOW PIN_OUTPUT_LOW
+#define PIN_SLPM_OUTPUT_HIGH PIN_OUTPUT_HIGH
#define PIN_CFG_DEFAULT (PIN_PULL_NONE | PIN_SLPM_INPUT)
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index e39a417a368d..a92cb499313f 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -33,7 +33,7 @@ config OMAP_DEBUG_DEVICES
config OMAP_DEBUG_LEDS
bool
depends on OMAP_DEBUG_DEVICES
- default y if LEDS
+ default y if LEDS_CLASS
config OMAP_RESET_CLOCKS
bool "Reset unused clocks during boot"
diff --git a/arch/arm/plat-omap/fb.c b/arch/arm/plat-omap/fb.c
index 0054b9501a53..71934817e172 100644
--- a/arch/arm/plat-omap/fb.c
+++ b/arch/arm/plat-omap/fb.c
@@ -173,11 +173,7 @@ static int check_fbmem_region(int region_idx, struct omapfb_mem_region *rg,
static int valid_sdram(unsigned long addr, unsigned long size)
{
- struct memblock_property res;
-
- res.base = addr;
- res.size = size;
- return !memblock_find(&res) && res.base == addr && res.size == size;
+ return memblock_is_region_memory(addr, size);
}
static int reserve_sdram(unsigned long addr, unsigned long size)
diff --git a/arch/arm/plat-omap/include/plat/smp.h b/arch/arm/plat-omap/include/plat/smp.h
index 5177a9c5a25a..ecd6a488c497 100644
--- a/arch/arm/plat-omap/include/plat/smp.h
+++ b/arch/arm/plat-omap/include/plat/smp.h
@@ -18,6 +18,7 @@
#define OMAP_ARCH_SMP_H
#include <asm/hardware/gic.h>
+#include <asm/smp_mpidr.h>
/* Needed for secondary core boot */
extern void omap_secondary_startup(void);
@@ -33,15 +34,4 @@ static inline void smp_cross_call(const struct cpumask *mask)
gic_raise_softirq(mask, 1);
}
-/*
- * Read MPIDR: Multiprocessor affinity register
- */
-#define hard_smp_processor_id() \
- ({ \
- unsigned int cpunum; \
- __asm__("mrc p15, 0, %0, c0, c0, 5" \
- : "=r" (cpunum)); \
- cpunum &= 0x0F; \
- })
-
#endif
diff --git a/arch/arm/plat-omap/include/plat/usb.h b/arch/arm/plat-omap/include/plat/usb.h
index 2a9427c8cc48..9feddacfe850 100644
--- a/arch/arm/plat-omap/include/plat/usb.h
+++ b/arch/arm/plat-omap/include/plat/usb.h
@@ -218,6 +218,27 @@ static inline omap2_usbfs_init(struct omap_usb_config *pdata)
# define USBT2TLL5PI (1 << 17)
# define USB0PUENACTLOI (1 << 16)
# define USBSTANDBYCTRL (1 << 15)
+/* AM35x */
+/* USB 2.0 PHY Control */
+#define CONF2_PHY_GPIOMODE (1 << 23)
+#define CONF2_OTGMODE (3 << 14)
+#define CONF2_NO_OVERRIDE (0 << 14)
+#define CONF2_FORCE_HOST (1 << 14)
+#define CONF2_FORCE_DEVICE (2 << 14)
+#define CONF2_FORCE_HOST_VBUS_LOW (3 << 14)
+#define CONF2_SESENDEN (1 << 13)
+#define CONF2_VBDTCTEN (1 << 12)
+#define CONF2_REFFREQ_24MHZ (2 << 8)
+#define CONF2_REFFREQ_26MHZ (7 << 8)
+#define CONF2_REFFREQ_13MHZ (6 << 8)
+#define CONF2_REFFREQ (0xf << 8)
+#define CONF2_PHYCLKGD (1 << 7)
+#define CONF2_VBUSSENSE (1 << 6)
+#define CONF2_PHY_PLLON (1 << 5)
+#define CONF2_RESET (1 << 4)
+#define CONF2_PHYPWRDN (1 << 3)
+#define CONF2_OTGPWRDN (1 << 2)
+#define CONF2_DATPOL (1 << 1)
#if defined(CONFIG_ARCH_OMAP1) && defined(CONFIG_USB)
u32 omap1_usb0_init(unsigned nwires, unsigned is_device);
diff --git a/arch/arm/plat-omap/iommu-debug.c b/arch/arm/plat-omap/iommu-debug.c
index e6c0d536899c..f07cf2f08e09 100644
--- a/arch/arm/plat-omap/iommu-debug.c
+++ b/arch/arm/plat-omap/iommu-debug.c
@@ -328,12 +328,14 @@ static int debug_open_generic(struct inode *inode, struct file *file)
.open = debug_open_generic, \
.read = debug_read_##name, \
.write = debug_write_##name, \
+ .llseek = generic_file_llseek, \
};
#define DEBUG_FOPS_RO(name) \
static const struct file_operations debug_##name##_fops = { \
.open = debug_open_generic, \
.read = debug_read_##name, \
+ .llseek = generic_file_llseek, \
};
DEBUG_FOPS_RO(ver);
diff --git a/arch/arm/plat-omap/iommu.c b/arch/arm/plat-omap/iommu.c
index a202a2ce6e3d..6cd151b31bc5 100644
--- a/arch/arm/plat-omap/iommu.c
+++ b/arch/arm/plat-omap/iommu.c
@@ -320,6 +320,7 @@ void flush_iotlb_page(struct iommu *obj, u32 da)
if ((start <= da) && (da < start + bytes)) {
dev_dbg(obj->dev, "%s: %08x<=%08x(%x)\n",
__func__, start, da, bytes);
+ iotlb_load_cr(obj, &cr);
iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY);
}
}
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c
index e31496e35b0f..0c8612fd8312 100644
--- a/arch/arm/plat-omap/mcbsp.c
+++ b/arch/arm/plat-omap/mcbsp.c
@@ -156,7 +156,7 @@ static irqreturn_t omap_mcbsp_rx_irq_handler(int irq, void *dev_id)
/* Writing zero to RSYNC_ERR clears the IRQ */
MCBSP_WRITE(mcbsp_rx, SPCR1, MCBSP_READ_CACHE(mcbsp_rx, SPCR1));
} else {
- complete(&mcbsp_rx->tx_irq_completion);
+ complete(&mcbsp_rx->rx_irq_completion);
}
return IRQ_HANDLED;
diff --git a/arch/arm/mach-pxa/include/mach/pxa27x_keypad.h b/arch/arm/plat-pxa/include/plat/pxa27x_keypad.h
index 7b4eadc6df3a..abcc36eb1242 100644
--- a/arch/arm/mach-pxa/include/mach/pxa27x_keypad.h
+++ b/arch/arm/plat-pxa/include/plat/pxa27x_keypad.h
@@ -25,6 +25,13 @@
*
* 4. matrix key and direct key will use the same debounce_interval by
* default, which should be sufficient in most cases
+ *
+ * pxa168 keypad platform specific parameter
+ *
+ * NOTE:
+ * clear_wakeup_event callback is a workaround required to clear the
+ * keypad interrupt. The keypad wake must be cleared in addition to
+ * reading the MI/DI bits in the KPC register.
*/
struct pxa27x_keypad_platform_data {
@@ -52,6 +59,9 @@ struct pxa27x_keypad_platform_data {
/* key debounce interval */
unsigned int debounce_interval;
+
+ /* clear wakeup event requirement for pxa168 */
+ void (*clear_wakeup_event)(void);
};
extern void pxa_set_keypad_info(struct pxa27x_keypad_platform_data *info);
diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig
index c6a855db2fb6..25960966af7c 100644
--- a/arch/arm/plat-s5p/Kconfig
+++ b/arch/arm/plat-s5p/Kconfig
@@ -7,7 +7,7 @@
config PLAT_S5P
bool
- depends on (ARCH_S5P6440 || ARCH_S5P6442 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_S5PV310)
+ depends on (ARCH_S5P64X0 || ARCH_S5P6442 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_S5PV310)
default y
select ARM_VIC if !ARCH_S5PV310
select ARM_GIC if ARCH_S5PV310
@@ -30,7 +30,7 @@ config S5P_EXT_INT
bool
help
Use the external interrupts (other than GPIO interrupts.)
- Note: Do not choose this for S5P6440.
+ Note: Do not choose this for S5P6440 and S5P6450.
config S5P_DEV_FIMC0
bool
@@ -46,3 +46,8 @@ config S5P_DEV_FIMC2
bool
help
Compile in platform device definitions for FIMC controller 2
+
+config S5P_DEV_ONENAND
+ bool
+ help
+ Compile in platform device definition for OneNAND controller
diff --git a/arch/arm/plat-s5p/Makefile b/arch/arm/plat-s5p/Makefile
index b2e029673950..f3e917e27da8 100644
--- a/arch/arm/plat-s5p/Makefile
+++ b/arch/arm/plat-s5p/Makefile
@@ -24,3 +24,4 @@ obj-$(CONFIG_S5P_EXT_INT) += irq-eint.o
obj-$(CONFIG_S5P_DEV_FIMC0) += dev-fimc0.o
obj-$(CONFIG_S5P_DEV_FIMC1) += dev-fimc1.o
obj-$(CONFIG_S5P_DEV_FIMC2) += dev-fimc2.o
+obj-$(CONFIG_S5P_DEV_ONENAND) += dev-onenand.o
diff --git a/arch/arm/plat-s5p/clock.c b/arch/arm/plat-s5p/clock.c
index b5e255265f20..8aaf4e6b60c3 100644
--- a/arch/arm/plat-s5p/clock.c
+++ b/arch/arm/plat-s5p/clock.c
@@ -74,6 +74,13 @@ struct clk clk_fout_epll = {
.ctrlbit = (1 << 31),
};
+/* DPLL clock output */
+struct clk clk_fout_dpll = {
+ .name = "fout_dpll",
+ .id = -1,
+ .ctrlbit = (1 << 31),
+};
+
/* VPLL clock output */
struct clk clk_fout_vpll = {
.name = "fout_vpll",
@@ -122,6 +129,17 @@ struct clksrc_sources clk_src_epll = {
.nr_sources = ARRAY_SIZE(clk_src_epll_list),
};
+/* Possible clock sources for DPLL Mux */
+static struct clk *clk_src_dpll_list[] = {
+ [0] = &clk_fin_dpll,
+ [1] = &clk_fout_dpll,
+};
+
+struct clksrc_sources clk_src_dpll = {
+ .sources = clk_src_dpll_list,
+ .nr_sources = ARRAY_SIZE(clk_src_dpll_list),
+};
+
struct clk clk_vpll = {
.name = "vpll",
.id = -1,
@@ -145,6 +163,7 @@ static struct clk *s5p_clks[] __initdata = {
&clk_fout_apll,
&clk_fout_mpll,
&clk_fout_epll,
+ &clk_fout_dpll,
&clk_fout_vpll,
&clk_arm,
&clk_vpll,
diff --git a/arch/arm/plat-s5p/cpu.c b/arch/arm/plat-s5p/cpu.c
index b07a078fd284..74f7f5a5446c 100644
--- a/arch/arm/plat-s5p/cpu.c
+++ b/arch/arm/plat-s5p/cpu.c
@@ -19,6 +19,7 @@
#include <plat/cpu.h>
#include <plat/s5p6440.h>
#include <plat/s5p6442.h>
+#include <plat/s5p6450.h>
#include <plat/s5pc100.h>
#include <plat/s5pv210.h>
#include <plat/s5pv310.h>
@@ -27,6 +28,7 @@
static const char name_s5p6440[] = "S5P6440";
static const char name_s5p6442[] = "S5P6442";
+static const char name_s5p6450[] = "S5P6450";
static const char name_s5pc100[] = "S5PC100";
static const char name_s5pv210[] = "S5PV210/S5PC110";
static const char name_s5pv310[] = "S5PV310";
@@ -38,7 +40,7 @@ static struct cpu_table cpu_ids[] __initdata = {
.map_io = s5p6440_map_io,
.init_clocks = s5p6440_init_clocks,
.init_uarts = s5p6440_init_uarts,
- .init = s5p6440_init,
+ .init = s5p64x0_init,
.name = name_s5p6440,
}, {
.idcode = 0x36442000,
@@ -49,6 +51,14 @@ static struct cpu_table cpu_ids[] __initdata = {
.init = s5p6442_init,
.name = name_s5p6442,
}, {
+ .idcode = 0x36450000,
+ .idmask = 0xffffff00,
+ .map_io = s5p6450_map_io,
+ .init_clocks = s5p6450_init_clocks,
+ .init_uarts = s5p6450_init_uarts,
+ .init = s5p64x0_init,
+ .name = name_s5p6450,
+ }, {
.idcode = 0x43100000,
.idmask = 0xfffff000,
.map_io = s5pc100_map_io,
@@ -89,33 +99,11 @@ static struct map_desc s5p_iodesc[] __initdata = {
.length = SZ_64K,
.type = MT_DEVICE,
}, {
- .virtual = (unsigned long)S3C_VA_UART,
- .pfn = __phys_to_pfn(S3C_PA_UART),
- .length = SZ_512K,
- .type = MT_DEVICE,
-#ifdef CONFIG_ARM_VIC
- }, {
- .virtual = (unsigned long)VA_VIC0,
- .pfn = __phys_to_pfn(S5P_PA_VIC0),
- .length = SZ_16K,
- .type = MT_DEVICE,
- }, {
- .virtual = (unsigned long)VA_VIC1,
- .pfn = __phys_to_pfn(S5P_PA_VIC1),
- .length = SZ_16K,
- .type = MT_DEVICE,
-#endif
- }, {
.virtual = (unsigned long)S3C_VA_TIMER,
.pfn = __phys_to_pfn(S5P_PA_TIMER),
.length = SZ_16K,
.type = MT_DEVICE,
}, {
- .virtual = (unsigned long)S5P_VA_GPIO,
- .pfn = __phys_to_pfn(S5P_PA_GPIO),
- .length = SZ_4K,
- .type = MT_DEVICE,
- }, {
.virtual = (unsigned long)S3C_VA_WATCHDOG,
.pfn = __phys_to_pfn(S3C_PA_WDT),
.length = SZ_4K,
diff --git a/arch/arm/mach-s5pv210/dev-onenand.c b/arch/arm/plat-s5p/dev-onenand.c
index f8ede33ee82b..6db926202caa 100644
--- a/arch/arm/mach-s5pv210/dev-onenand.c
+++ b/arch/arm/plat-s5p/dev-onenand.c
@@ -1,10 +1,12 @@
-/*
- * linux/arch/arm/mach-s5pv210/dev-onenand.c
+/* linux/arch/arm/plat-s5p/dev-onenand.c
+ *
+ * Copyright 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
*
* Copyright (c) 2008-2010 Samsung Electronics
* Kyungmin Park <kyungmin.park@samsung.com>
*
- * S5PC110 series device definition for OneNAND devices
+ * S5P series device definition for OneNAND devices
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -19,15 +21,15 @@
#include <mach/irqs.h>
#include <mach/map.h>
-static struct resource s5pc110_onenand_resources[] = {
+static struct resource s5p_onenand_resources[] = {
[0] = {
- .start = S5PC110_PA_ONENAND,
- .end = S5PC110_PA_ONENAND + SZ_128K - 1,
+ .start = S5P_PA_ONENAND,
+ .end = S5P_PA_ONENAND + SZ_128K - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = S5PC110_PA_ONENAND_DMA,
- .end = S5PC110_PA_ONENAND_DMA + SZ_8K - 1,
+ .start = S5P_PA_ONENAND_DMA,
+ .end = S5P_PA_ONENAND_DMA + SZ_8K - 1,
.flags = IORESOURCE_MEM,
},
[2] = {
@@ -37,19 +39,19 @@ static struct resource s5pc110_onenand_resources[] = {
},
};
-struct platform_device s5pc110_device_onenand = {
+struct platform_device s5p_device_onenand = {
.name = "s5pc110-onenand",
.id = -1,
- .num_resources = ARRAY_SIZE(s5pc110_onenand_resources),
- .resource = s5pc110_onenand_resources,
+ .num_resources = ARRAY_SIZE(s5p_onenand_resources),
+ .resource = s5p_onenand_resources,
};
-void s5pc110_onenand_set_platdata(struct onenand_platform_data *pdata)
+void s5p_onenand_set_platdata(struct onenand_platform_data *pdata)
{
struct onenand_platform_data *pd;
pd = kmemdup(pdata, sizeof(struct onenand_platform_data), GFP_KERNEL);
if (!pd)
printk(KERN_ERR "%s: no memory for platform data\n", __func__);
- s5pc110_device_onenand.dev.platform_data = pd;
+ s5p_device_onenand.dev.platform_data = pd;
}
diff --git a/arch/arm/plat-s5p/dev-uart.c b/arch/arm/plat-s5p/dev-uart.c
index a89331ef4ae1..6a7342886171 100644
--- a/arch/arm/plat-s5p/dev-uart.c
+++ b/arch/arm/plat-s5p/dev-uart.c
@@ -119,6 +119,56 @@ static struct resource s5p_uart3_resource[] = {
#endif
};
+static struct resource s5p_uart4_resource[] = {
+#if CONFIG_SERIAL_SAMSUNG_UARTS > 4
+ [0] = {
+ .start = S5P_PA_UART4,
+ .end = S5P_PA_UART4 + S5P_SZ_UART,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_S5P_UART_RX4,
+ .end = IRQ_S5P_UART_RX4,
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ .start = IRQ_S5P_UART_TX4,
+ .end = IRQ_S5P_UART_TX4,
+ .flags = IORESOURCE_IRQ,
+ },
+ [3] = {
+ .start = IRQ_S5P_UART_ERR4,
+ .end = IRQ_S5P_UART_ERR4,
+ .flags = IORESOURCE_IRQ,
+ },
+#endif
+};
+
+static struct resource s5p_uart5_resource[] = {
+#if CONFIG_SERIAL_SAMSUNG_UARTS > 5
+ [0] = {
+ .start = S5P_PA_UART5,
+ .end = S5P_PA_UART5 + S5P_SZ_UART,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_S5P_UART_RX5,
+ .end = IRQ_S5P_UART_RX5,
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ .start = IRQ_S5P_UART_TX5,
+ .end = IRQ_S5P_UART_TX5,
+ .flags = IORESOURCE_IRQ,
+ },
+ [3] = {
+ .start = IRQ_S5P_UART_ERR5,
+ .end = IRQ_S5P_UART_ERR5,
+ .flags = IORESOURCE_IRQ,
+ },
+#endif
+};
+
struct s3c24xx_uart_resources s5p_uart_resources[] __initdata = {
[0] = {
.resources = s5p_uart0_resource,
@@ -136,4 +186,12 @@ struct s3c24xx_uart_resources s5p_uart_resources[] __initdata = {
.resources = s5p_uart3_resource,
.nr_resources = ARRAY_SIZE(s5p_uart3_resource),
},
+ [4] = {
+ .resources = s5p_uart4_resource,
+ .nr_resources = ARRAY_SIZE(s5p_uart4_resource),
+ },
+ [5] = {
+ .resources = s5p_uart5_resource,
+ .nr_resources = ARRAY_SIZE(s5p_uart5_resource),
+ },
};
diff --git a/arch/arm/plat-s5p/include/plat/pll.h b/arch/arm/plat-s5p/include/plat/pll.h
index 4e8fe08cb70d..bf28fadee7ae 100644
--- a/arch/arm/plat-s5p/include/plat/pll.h
+++ b/arch/arm/plat-s5p/include/plat/pll.h
@@ -47,6 +47,7 @@ static inline unsigned long s5p_get_pll45xx(unsigned long baseclk, u32 pll_con,
}
#define PLL46XX_KDIV_MASK (0xFFFF)
+#define PLL4650C_KDIV_MASK (0xFFF)
#define PLL46XX_MDIV_MASK (0x1FF)
#define PLL46XX_PDIV_MASK (0x3F)
#define PLL46XX_SDIV_MASK (0x7)
@@ -57,6 +58,7 @@ static inline unsigned long s5p_get_pll45xx(unsigned long baseclk, u32 pll_con,
enum pll46xx_type_t {
pll_4600,
pll_4650,
+ pll_4650c,
};
static inline unsigned long s5p_get_pll46xx(unsigned long baseclk,
@@ -72,6 +74,11 @@ static inline unsigned long s5p_get_pll46xx(unsigned long baseclk,
sdiv = (pll_con0 >> PLL46XX_SDIV_SHIFT) & PLL46XX_SDIV_MASK;
kdiv = pll_con1 & PLL46XX_KDIV_MASK;
+ if (pll_type == pll_4650c)
+ kdiv = pll_con1 & PLL4650C_KDIV_MASK;
+ else
+ kdiv = pll_con1 & PLL46XX_KDIV_MASK;
+
tmp = baseclk;
if (pll_type == pll_4600) {
diff --git a/arch/arm/plat-s5p/include/plat/s5p-clock.h b/arch/arm/plat-s5p/include/plat/s5p-clock.h
index 09418b1101fe..17036c898409 100644
--- a/arch/arm/plat-s5p/include/plat/s5p-clock.h
+++ b/arch/arm/plat-s5p/include/plat/s5p-clock.h
@@ -1,7 +1,7 @@
/* linux/arch/arm/plat-s5p/include/plat/s5p-clock.h
*
- * Copyright 2009 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
*
* Header file for s5p clock support
*
@@ -20,6 +20,7 @@
#define clk_fin_apll clk_ext_xtal_mux
#define clk_fin_mpll clk_ext_xtal_mux
#define clk_fin_epll clk_ext_xtal_mux
+#define clk_fin_dpll clk_ext_xtal_mux
#define clk_fin_vpll clk_ext_xtal_mux
#define clk_fin_hpll clk_ext_xtal_mux
@@ -30,6 +31,7 @@ extern struct clk s5p_clk_27m;
extern struct clk clk_fout_apll;
extern struct clk clk_fout_mpll;
extern struct clk clk_fout_epll;
+extern struct clk clk_fout_dpll;
extern struct clk clk_fout_vpll;
extern struct clk clk_arm;
extern struct clk clk_vpll;
@@ -37,8 +39,8 @@ extern struct clk clk_vpll;
extern struct clksrc_sources clk_src_apll;
extern struct clksrc_sources clk_src_mpll;
extern struct clksrc_sources clk_src_epll;
+extern struct clksrc_sources clk_src_dpll;
-extern int s5p6440_clk48m_ctrl(struct clk *clk, int enable);
extern int s5p_gatectrl(void __iomem *reg, struct clk *clk, int enable);
#endif /* __ASM_PLAT_S5P_CLOCK_H */
diff --git a/arch/arm/plat-s5p/include/plat/s5p6440.h b/arch/arm/plat-s5p/include/plat/s5p6440.h
index a4cd75afeb3b..528585d2cafc 100644
--- a/arch/arm/plat-s5p/include/plat/s5p6440.h
+++ b/arch/arm/plat-s5p/include/plat/s5p6440.h
@@ -12,24 +12,23 @@
/* Common init code for S5P6440 related SoCs */
-extern void s5p6440_common_init_uarts(struct s3c2410_uartcfg *cfg, int no);
extern void s5p6440_register_clocks(void);
extern void s5p6440_setup_clocks(void);
#ifdef CONFIG_CPU_S5P6440
-extern int s5p6440_init(void);
+extern int s5p64x0_init(void);
extern void s5p6440_init_irq(void);
extern void s5p6440_map_io(void);
extern void s5p6440_init_clocks(int xtal);
-#define s5p6440_init_uarts s5p6440_common_init_uarts
+extern void s5p6440_init_uarts(struct s3c2410_uartcfg *cfg, int no);
#else
#define s5p6440_init_clocks NULL
#define s5p6440_init_uarts NULL
#define s5p6440_map_io NULL
-#define s5p6440_init NULL
+#define s5p64x0_init NULL
#endif
/* S5P6440 timer */
diff --git a/arch/arm/plat-s5p/include/plat/s5p6450.h b/arch/arm/plat-s5p/include/plat/s5p6450.h
new file mode 100644
index 000000000000..640a41c26be3
--- /dev/null
+++ b/arch/arm/plat-s5p/include/plat/s5p6450.h
@@ -0,0 +1,36 @@
+/* arch/arm/plat-s5p/include/plat/s5p6450.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Header file for s5p6450 cpu support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/* Common init code for S5P6450 related SoCs */
+
+extern void s5p6450_register_clocks(void);
+extern void s5p6450_setup_clocks(void);
+
+#ifdef CONFIG_CPU_S5P6450
+
+extern int s5p64x0_init(void);
+extern void s5p6450_init_irq(void);
+extern void s5p6450_map_io(void);
+extern void s5p6450_init_clocks(int xtal);
+
+extern void s5p6450_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+#else
+#define s5p6450_init_clocks NULL
+#define s5p6450_init_uarts NULL
+#define s5p6450_map_io NULL
+#define s5p64x0_init NULL
+#endif
+
+/* S5P6450 timer */
+
+extern struct sys_timer s5p6450_timer;
diff --git a/arch/arm/plat-samsung/adc.c b/arch/arm/plat-samsung/adc.c
index 04d9521ddc9f..e8f2be2d67f2 100644
--- a/arch/arm/plat-samsung/adc.c
+++ b/arch/arm/plat-samsung/adc.c
@@ -435,7 +435,6 @@ static int s3c_adc_suspend(struct platform_device *pdev, pm_message_t state)
static int s3c_adc_resume(struct platform_device *pdev)
{
struct adc_device *adc = platform_get_drvdata(pdev);
- unsigned long flags;
clk_enable(adc->clk);
enable_irq(adc->irq);
diff --git a/arch/arm/plat-samsung/clock.c b/arch/arm/plat-samsung/clock.c
index 90a20512d68d..e8d20b0bc50e 100644
--- a/arch/arm/plat-samsung/clock.c
+++ b/arch/arm/plat-samsung/clock.c
@@ -48,6 +48,9 @@
#include <plat/clock.h>
#include <plat/cpu.h>
+#include <linux/serial_core.h>
+#include <plat/regs-serial.h> /* for s3c24xx_uart_devs */
+
/* clock information */
static LIST_HEAD(clocks);
@@ -65,6 +68,28 @@ static int clk_null_enable(struct clk *clk, int enable)
return 0;
}
+static int dev_is_s3c_uart(struct device *dev)
+{
+ struct platform_device **pdev = s3c24xx_uart_devs;
+ int i;
+ for (i = 0; i < ARRAY_SIZE(s3c24xx_uart_devs); i++, pdev++)
+ if (*pdev && dev == &(*pdev)->dev)
+ return 1;
+ return 0;
+}
+
+/*
+ * Serial drivers call get_clock() very early, before platform bus
+ * has been set up, this requires a special check to let them get
+ * a proper clock
+ */
+
+static int dev_is_platform_device(struct device *dev)
+{
+ return dev->bus == &platform_bus_type ||
+ (dev->bus == NULL && dev_is_s3c_uart(dev));
+}
+
/* Clock API calls */
struct clk *clk_get(struct device *dev, const char *id)
@@ -73,7 +98,7 @@ struct clk *clk_get(struct device *dev, const char *id)
struct clk *clk = ERR_PTR(-ENOENT);
int idno;
- if (dev == NULL || dev->bus != &platform_bus_type)
+ if (dev == NULL || !dev_is_platform_device(dev))
idno = -1;
else
idno = to_platform_device(dev)->id;
diff --git a/arch/arm/plat-samsung/include/plat/cpu.h b/arch/arm/plat-samsung/include/plat/cpu.h
index 6412933d6fbb..9addb3dfb4bc 100644
--- a/arch/arm/plat-samsung/include/plat/cpu.h
+++ b/arch/arm/plat-samsung/include/plat/cpu.h
@@ -79,7 +79,7 @@ extern struct sysdev_class s3c2442_sysclass;
extern struct sysdev_class s3c2443_sysclass;
extern struct sysdev_class s3c6410_sysclass;
extern struct sysdev_class s3c64xx_sysclass;
-extern struct sysdev_class s5p6440_sysclass;
+extern struct sysdev_class s5p64x0_sysclass;
extern struct sysdev_class s5p6442_sysclass;
extern struct sysdev_class s5pv210_sysclass;
diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h
index 85f6f23a510f..7d448e138792 100644
--- a/arch/arm/plat-samsung/include/plat/devs.h
+++ b/arch/arm/plat-samsung/include/plat/devs.h
@@ -67,13 +67,15 @@ extern struct platform_device s5pv210_device_spi0;
extern struct platform_device s5pv210_device_spi1;
extern struct platform_device s5p6440_device_spi0;
extern struct platform_device s5p6440_device_spi1;
+extern struct platform_device s5p6450_device_spi0;
+extern struct platform_device s5p6450_device_spi1;
extern struct platform_device s3c_device_hwmon;
extern struct platform_device s3c_device_nand;
extern struct platform_device s3c_device_onenand;
extern struct platform_device s3c64xx_device_onenand1;
-extern struct platform_device s5pc110_device_onenand;
+extern struct platform_device s5p_device_onenand;
extern struct platform_device s3c_device_usbgadget;
extern struct platform_device s3c_device_usb_hsotg;
@@ -95,6 +97,9 @@ extern struct platform_device s5p6442_device_spi;
extern struct platform_device s5p6440_device_pcm;
extern struct platform_device s5p6440_device_iis;
+extern struct platform_device s5p6450_device_iis0;
+extern struct platform_device s5p6450_device_pcm0;
+
extern struct platform_device s5pc100_device_ac97;
extern struct platform_device s5pc100_device_pcm0;
extern struct platform_device s5pc100_device_pcm1;
diff --git a/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h b/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h
index 5fe6721b57f7..810744213120 100644
--- a/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h
+++ b/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h
@@ -32,6 +32,12 @@ enum dma_ch {
DMACH_UART2_TX,
DMACH_UART3_RX,
DMACH_UART3_TX,
+ DMACH_UART4_RX,
+ DMACH_UART4_TX,
+ DMACH_UART5_RX,
+ DMACH_UART5_TX,
+ DMACH_USI_RX,
+ DMACH_USI_TX,
DMACH_IRDA,
DMACH_I2S0_RX,
DMACH_I2S0_TX,
@@ -64,6 +70,20 @@ enum dma_ch {
DMACH_MSM_REQ2,
DMACH_MSM_REQ1,
DMACH_MSM_REQ0,
+ DMACH_SLIMBUS0_RX,
+ DMACH_SLIMBUS0_TX,
+ DMACH_SLIMBUS0AUX_RX,
+ DMACH_SLIMBUS0AUX_TX,
+ DMACH_SLIMBUS1_RX,
+ DMACH_SLIMBUS1_TX,
+ DMACH_SLIMBUS2_RX,
+ DMACH_SLIMBUS2_TX,
+ DMACH_SLIMBUS3_RX,
+ DMACH_SLIMBUS3_TX,
+ DMACH_SLIMBUS4_RX,
+ DMACH_SLIMBUS4_TX,
+ DMACH_SLIMBUS5_RX,
+ DMACH_SLIMBUS5_TX,
/* END Marker, also used to denote a reserved channel */
DMACH_MAX,
};
diff --git a/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h b/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h
index e5aba8f95b79..ff1a561b326e 100644
--- a/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h
+++ b/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h
@@ -32,6 +32,8 @@ struct s3c64xx_spi_csinfo {
* struct s3c64xx_spi_info - SPI Controller defining structure
* @src_clk_nr: Clock source index for the CLK_CFG[SPI_CLKSEL] field.
* @src_clk_name: Platform name of the corresponding clock.
+ * @clk_from_cmu: If the SPI clock/prescalar control block is present
+ * by the platform's clock-management-unit and not in SPI controller.
* @num_cs: Number of CS this controller emulates.
* @cfg_gpio: Configure pins for this SPI controller.
* @fifo_lvl_mask: All tx fifo_lvl fields start at offset-6
@@ -41,6 +43,7 @@ struct s3c64xx_spi_csinfo {
struct s3c64xx_spi_info {
int src_clk_nr;
char *src_clk_name;
+ bool clk_from_cmu;
int num_cs;
@@ -65,7 +68,7 @@ struct s3c64xx_spi_info {
extern void s3c64xx_spi_set_info(int cntrlr, int src_clk_nr, int num_cs);
extern void s5pc100_spi_set_info(int cntrlr, int src_clk_nr, int num_cs);
extern void s5pv210_spi_set_info(int cntrlr, int src_clk_nr, int num_cs);
-extern void s5p6440_spi_set_info(int cntrlr, int src_clk_nr, int num_cs);
+extern void s5p64x0_spi_set_info(int cntrlr, int src_clk_nr, int num_cs);
extern void s5p6442_spi_set_info(int cntrlr, int src_clk_nr, int num_cs);
#endif /* __S3C64XX_PLAT_SPI_H */
diff --git a/arch/arm/plat-spear/include/plat/debug-macro.S b/arch/arm/plat-spear/include/plat/debug-macro.S
index 37fa593884ee..e91270e4f640 100644
--- a/arch/arm/plat-spear/include/plat/debug-macro.S
+++ b/arch/arm/plat-spear/include/plat/debug-macro.S
@@ -14,11 +14,9 @@
#include <linux/amba/serial.h>
#include <mach/spear.h>
- .macro addruart, rx
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ MMU enabled?
- moveq \rx, #SPEAR_DBG_UART_BASE @ Physical base
- movne \rx, #VA_SPEAR_DBG_UART_BASE @ Virtual base
+ .macro addruart, rp, rv
+ mov \rp, #SPEAR_DBG_UART_BASE @ Physical base
+ mov \rv, #VA_SPEAR_DBG_UART_BASE @ Virtual base
.endm
.macro senduart, rd, rx
diff --git a/arch/arm/plat-stmp3xxx/include/mach/debug-macro.S b/arch/arm/plat-stmp3xxx/include/mach/debug-macro.S
index 1b9348bf0e49..d3a0985c9681 100644
--- a/arch/arm/plat-stmp3xxx/include/mach/debug-macro.S
+++ b/arch/arm/plat-stmp3xxx/include/mach/debug-macro.S
@@ -16,13 +16,10 @@
* http://www.gnu.org/copyleft/gpl.html
*/
- .macro addruart, rx, tmp
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ MMU enabled?
- moveq \rx, #0x80000000 @ physical base address
- addeq \rx, \rx, #0x00070000
- movne \rx, #0xf0000000 @ virtual base
- addne \rx, \rx, #0x00070000
+ .macro addruart, rp, rv
+ mov \rp, #0x00070000
+ add \rv, \rp, #0xf0000000 @ virtual base
+ add \rp, \rp, #0x80000000 @ physical base
.endm
.macro senduart,rd,rx
diff --git a/arch/arm/plat-tcc/Kconfig b/arch/arm/plat-tcc/Kconfig
new file mode 100644
index 000000000000..1bf499570f42
--- /dev/null
+++ b/arch/arm/plat-tcc/Kconfig
@@ -0,0 +1,20 @@
+if ARCH_TCC_926
+
+menu "Telechips ARM926-based CPUs"
+
+choice
+ prompt "Telechips CPU type:"
+ default ARCH_TCC8K
+
+config ARCH_TCC8K
+ bool TCC8000
+ select USB_ARCH_HAS_OHCI
+ help
+ Support for Telechips TCC8000 systems
+
+endchoice
+
+source "arch/arm/mach-tcc8k/Kconfig"
+
+endmenu
+endif
diff --git a/arch/arm/plat-tcc/Makefile b/arch/arm/plat-tcc/Makefile
new file mode 100644
index 000000000000..eceabc869b8f
--- /dev/null
+++ b/arch/arm/plat-tcc/Makefile
@@ -0,0 +1,3 @@
+# "Telechips Platform Common Modules"
+
+obj-y := clock.o system.o
diff --git a/arch/arm/plat-tcc/clock.c b/arch/arm/plat-tcc/clock.c
new file mode 100644
index 000000000000..f3ced10d5271
--- /dev/null
+++ b/arch/arm/plat-tcc/clock.c
@@ -0,0 +1,179 @@
+/*
+ * Clock framework for Telechips SoCs
+ * Based on arch/arm/plat-mxc/clock.c
+ *
+ * Copyright (C) 2004 - 2005 Nokia corporation
+ * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
+ * Modified for omap shared clock framework by Tony Lindgren <tony@atomide.com>
+ * Copyright 2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
+ * Copyright 2010 Hans J. Koch, hjk@linutronix.de
+ *
+ * Licensed under the terms of the GPL v2.
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/string.h>
+
+#include <mach/clock.h>
+#include <mach/hardware.h>
+
+static DEFINE_MUTEX(clocks_mutex);
+
+/*-------------------------------------------------------------------------
+ * Standard clock functions defined in include/linux/clk.h
+ *-------------------------------------------------------------------------*/
+
+static void __clk_disable(struct clk *clk)
+{
+ BUG_ON(clk->refcount == 0);
+
+ if (!(--clk->refcount) && clk->disable) {
+ /* Unconditionally disable the clock in hardware */
+ clk->disable(clk);
+ /* recursively disable parents */
+ if (clk->parent)
+ __clk_disable(clk->parent);
+ }
+}
+
+static int __clk_enable(struct clk *clk)
+{
+ int ret = 0;
+
+ if (clk->refcount++ == 0 && clk->enable) {
+ if (clk->parent)
+ ret = __clk_enable(clk->parent);
+ if (ret)
+ return ret;
+ else
+ return clk->enable(clk);
+ }
+
+ return 0;
+}
+
+/* This function increments the reference count on the clock and enables the
+ * clock if not already enabled. The parent clock tree is recursively enabled
+ */
+int clk_enable(struct clk *clk)
+{
+ int ret = 0;
+
+ if (!clk)
+ return -EINVAL;
+
+ mutex_lock(&clocks_mutex);
+ ret = __clk_enable(clk);
+ mutex_unlock(&clocks_mutex);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(clk_enable);
+
+/* This function decrements the reference count on the clock and disables
+ * the clock when reference count is 0. The parent clock tree is
+ * recursively disabled
+ */
+void clk_disable(struct clk *clk)
+{
+ if (!clk)
+ return;
+
+ mutex_lock(&clocks_mutex);
+ __clk_disable(clk);
+ mutex_unlock(&clocks_mutex);
+}
+EXPORT_SYMBOL_GPL(clk_disable);
+
+/* Retrieve the *current* clock rate. If the clock itself
+ * does not provide a special calculation routine, ask
+ * its parent and so on, until one is able to return
+ * a valid clock rate
+ */
+unsigned long clk_get_rate(struct clk *clk)
+{
+ if (!clk)
+ return 0UL;
+
+ if (clk->get_rate)
+ return clk->get_rate(clk);
+
+ return clk_get_rate(clk->parent);
+}
+EXPORT_SYMBOL_GPL(clk_get_rate);
+
+/* Round the requested clock rate to the nearest supported
+ * rate that is less than or equal to the requested rate.
+ * This is dependent on the clock's current parent.
+ */
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+ if (!clk)
+ return 0;
+ if (!clk->round_rate)
+ return 0;
+
+ return clk->round_rate(clk, rate);
+}
+EXPORT_SYMBOL_GPL(clk_round_rate);
+
+/* Set the clock to the requested clock rate. The rate must
+ * match a supported rate exactly based on what clk_round_rate returns
+ */
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ int ret = -EINVAL;
+
+ if (!clk)
+ return ret;
+ if (!clk->set_rate || !rate)
+ return ret;
+
+ mutex_lock(&clocks_mutex);
+ ret = clk->set_rate(clk, rate);
+ mutex_unlock(&clocks_mutex);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(clk_set_rate);
+
+/* Set the clock's parent to another clock source */
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+ struct clk *old;
+ int ret = -EINVAL;
+
+ if (!clk)
+ return ret;
+ if (!clk->set_parent || !parent)
+ return ret;
+
+ mutex_lock(&clocks_mutex);
+ old = clk->parent;
+ if (clk->refcount)
+ __clk_enable(parent);
+ ret = clk->set_parent(clk, parent);
+ if (ret)
+ old = parent;
+ if (clk->refcount)
+ __clk_disable(old);
+ mutex_unlock(&clocks_mutex);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(clk_set_parent);
+
+/* Retrieve the clock's parent clock source */
+struct clk *clk_get_parent(struct clk *clk)
+{
+ if (!clk)
+ return NULL;
+
+ return clk->parent;
+}
+EXPORT_SYMBOL_GPL(clk_get_parent);
diff --git a/arch/arm/plat-tcc/include/mach/clkdev.h b/arch/arm/plat-tcc/include/mach/clkdev.h
new file mode 100644
index 000000000000..04b37a89801c
--- /dev/null
+++ b/arch/arm/plat-tcc/include/mach/clkdev.h
@@ -0,0 +1,7 @@
+#ifndef __ASM_MACH_CLKDEV_H
+#define __ASM_MACH_CLKDEV_H
+
+#define __clk_get(clk) ({ 1; })
+#define __clk_put(clk) do { } while (0)
+
+#endif
diff --git a/arch/arm/plat-tcc/include/mach/clock.h b/arch/arm/plat-tcc/include/mach/clock.h
new file mode 100644
index 000000000000..a12f58ad71a8
--- /dev/null
+++ b/arch/arm/plat-tcc/include/mach/clock.h
@@ -0,0 +1,48 @@
+/*
+ * Low level clock header file for Telechips TCC architecture
+ * (C) 2010 Hans J. Koch <hjk@linutronix.de>
+ *
+ * Licensed under the GPL v2.
+ */
+
+#ifndef __ASM_ARCH_TCC_CLOCK_H__
+#define __ASM_ARCH_TCC_CLOCK_H__
+
+#ifndef __ASSEMBLY__
+
+struct clk {
+ struct clk *parent;
+ /* id number of a root clock, 0 for normal clocks */
+ int root_id;
+ /* Reference count of clock enable/disable */
+ int refcount;
+ /* Address of associated BCLKCTRx register. Must be set. */
+ void __iomem *bclkctr;
+ /* Bit position for BCLKCTRx. Must be set. */
+ int bclk_shift;
+ /* Address of ACLKxxx register, if any. */
+ void __iomem *aclkreg;
+ /* get the current clock rate (always a fresh value) */
+ unsigned long (*get_rate) (struct clk *);
+ /* Function ptr to set the clock to a new rate. The rate must match a
+ supported rate returned from round_rate. Leave blank if clock is not
+ programmable */
+ int (*set_rate) (struct clk *, unsigned long);
+ /* Function ptr to round the requested clock rate to the nearest
+ supported rate that is less than or equal to the requested rate. */
+ unsigned long (*round_rate) (struct clk *, unsigned long);
+ /* Function ptr to enable the clock. Leave blank if clock can not
+ be gated. */
+ int (*enable) (struct clk *);
+ /* Function ptr to disable the clock. Leave blank if clock can not
+ be gated. */
+ void (*disable) (struct clk *);
+ /* Function ptr to set the parent clock of the clock. */
+ int (*set_parent) (struct clk *, struct clk *);
+};
+
+int clk_register(struct clk *clk);
+void clk_unregister(struct clk *clk);
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ASM_ARCH_MXC_CLOCK_H__ */
diff --git a/arch/arm/plat-tcc/include/mach/debug-macro.S b/arch/arm/plat-tcc/include/mach/debug-macro.S
new file mode 100644
index 000000000000..7662f736e42b
--- /dev/null
+++ b/arch/arm/plat-tcc/include/mach/debug-macro.S
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 1994-1999 Russell King
+ * Copyright (C) 2008-2009 Telechips
+ * Copyright (C) 2009 Hans J. Koch <hjk@linutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+ .macro addruart, rp, rv
+ moveq \rp, #0x90000000 @ physical base address
+ movne \rv, #0xF1000000 @ virtual base
+ orr \rp, \rp, #0x00007000 @ UART0
+ orr \rv, \rv, #0x00007000 @ UART0
+ .endm
+
+ .macro senduart,rd,rx
+ strb \rd, [\rx, #0x44]
+ .endm
+
+ .macro waituart,rd,rx
+ .endm
+
+ .macro busyuart,rd,rx
+1001:
+ ldr \rd, [\rx, #0x14]
+ tst \rd, #0x20
+
+ beq 1001b
+ .endm
diff --git a/arch/arm/plat-tcc/include/mach/entry-macro.S b/arch/arm/plat-tcc/include/mach/entry-macro.S
new file mode 100644
index 000000000000..748f401e4b6d
--- /dev/null
+++ b/arch/arm/plat-tcc/include/mach/entry-macro.S
@@ -0,0 +1,68 @@
+/*
+ * include/asm-arm/arch-tcc83x/entry-macro.S
+ *
+ * Author : <linux@telechips.com>
+ * Created: June 10, 2008
+ * Description: Low-level IRQ helper macros for Telechips-based platforms
+ *
+ * Copyright (C) 2008-2009 Telechips
+ *
+ * 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 <mach/hardware.h>
+#include <mach/irqs.h>
+
+ .macro disable_fiq
+ .endm
+
+ .macro get_irqnr_preamble, base, tmp
+ .endm
+
+ .macro arch_ret_to_user, tmp1, tmp2
+ .endm
+
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
+
+ ldr \base, =0xF2003000 @ base address of PIC registers
+
+ @@ read MREQ register of PIC0
+
+ mov \irqnr, #0
+ ldr \irqstat, [\base, #0x00000014 ] @ lower 32 interrupts
+ cmp \irqstat, #0
+ bne 1001f
+
+ @@ read MREQ register of PIC1
+
+ ldr \irqstat, [\base, #0x00000094] @ upper 32 interrupts
+ cmp \irqstat, #0
+ beq 1002f
+ mov \irqnr, #0x20
+
+1001:
+ movs \tmp, \irqstat, lsl #16
+ movne \irqstat, \tmp
+ addeq \irqnr, \irqnr, #16
+
+ movs \tmp, \irqstat, lsl #8
+ movne \irqstat, \tmp
+ addeq \irqnr, \irqnr, #8
+
+ movs \tmp, \irqstat, lsl #4
+ movne \irqstat, \tmp
+ addeq \irqnr, \irqnr, #4
+
+ movs \tmp, \irqstat, lsl #2
+ movne \irqstat, \tmp
+ addeq \irqnr, \irqnr, #2
+
+ movs \tmp, \irqstat, lsl #1
+ addeq \irqnr, \irqnr, #1
+ orrs \base, \base, #1
+1002:
+ @@ exit here, Z flag unset if IRQ
+
+ .endm
diff --git a/arch/arm/plat-tcc/include/mach/hardware.h b/arch/arm/plat-tcc/include/mach/hardware.h
new file mode 100644
index 000000000000..e70d126ccaf3
--- /dev/null
+++ b/arch/arm/plat-tcc/include/mach/hardware.h
@@ -0,0 +1,43 @@
+/*
+ * Author: RidgeRun, Inc. Greg Lonnon <glonnon@ridgerun.com>
+ * Reorganized for Linux-2.6 by Tony Lindgren <tony@atomide.com>
+ * and Dirk Behme <dirk.behme@de.bosch.com>
+ * Rewritten by: <linux@telechips.com>
+ * Description: Hardware definitions for TCC8300 processors and boards
+ *
+ * Copyright (C) 2001 RidgeRun, Inc.
+ * Copyright (C) 2008-2009 Telechips
+ *
+ * Modifications for mainline (C) 2009 Hans J. Koch <hjk@linutronix.de>
+ *
+ * Licensed under the terms of the GNU Pulic License version 2.
+ */
+
+#ifndef __ASM_ARCH_TCC_HARDWARE_H
+#define __ASM_ARCH_TCC_HARDWARE_H
+
+#include <asm/sizes.h>
+#ifndef __ASSEMBLER__
+#include <asm/types.h>
+#endif
+#include <mach/io.h>
+
+/*
+ * ----------------------------------------------------------------------------
+ * Clocks
+ * ----------------------------------------------------------------------------
+ */
+#define CLKGEN_REG_BASE 0xfffece00
+#define ARM_CKCTL (CLKGEN_REG_BASE + 0x0)
+#define ARM_IDLECT1 (CLKGEN_REG_BASE + 0x4)
+#define ARM_IDLECT2 (CLKGEN_REG_BASE + 0x8)
+#define ARM_EWUPCT (CLKGEN_REG_BASE + 0xC)
+#define ARM_RSTCT1 (CLKGEN_REG_BASE + 0x10)
+#define ARM_RSTCT2 (CLKGEN_REG_BASE + 0x14)
+#define ARM_SYSST (CLKGEN_REG_BASE + 0x18)
+#define ARM_IDLECT3 (CLKGEN_REG_BASE + 0x24)
+
+/* DPLL control registers */
+#define DPLL_CTL 0xfffecf00
+
+#endif /* __ASM_ARCH_TCC_HARDWARE_H */
diff --git a/arch/arm/plat-tcc/include/mach/io.h b/arch/arm/plat-tcc/include/mach/io.h
new file mode 100644
index 000000000000..3e911d3ea0f1
--- /dev/null
+++ b/arch/arm/plat-tcc/include/mach/io.h
@@ -0,0 +1,23 @@
+/*
+ * IO definitions for TCC8000 processors and boards
+ *
+ * Copyright (C) 1997-1999 Russell King
+ * Copyright (C) 2008-2009 Telechips
+ * Copyright (C) 2010 Hans J. Koch <hjk@linutronix.de>
+ *
+ * Licensed under the terms of the GNU Public License version 2.
+ */
+
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+/*
+ * We don't actually have real ISA nor PCI buses, but there is so many
+ * drivers out there that might just work if we fake them...
+ */
+#define __io(a) __typesafe_io(a)
+#define __mem_pci(a) (a)
+
+#endif
diff --git a/arch/arm/plat-tcc/include/mach/irqs.h b/arch/arm/plat-tcc/include/mach/irqs.h
new file mode 100644
index 000000000000..da863894d498
--- /dev/null
+++ b/arch/arm/plat-tcc/include/mach/irqs.h
@@ -0,0 +1,83 @@
+/*
+ * IRQ definitions for TCC8xxx
+ *
+ * Copyright (C) 2008-2009 Telechips
+ * Copyright (C) 2009 Hans J. Koch <hjk@linutronix.de>
+ *
+ * Licensed under the terms of the GPL v2.
+ *
+ */
+
+#ifndef __ASM_ARCH_TCC_IRQS_H
+#define __ASM_ARCH_TCC_IRQS_H
+
+#define NR_IRQS 64
+
+/* PIC0 interrupts */
+#define INT_ADMA1 0
+#define INT_BDMA 1
+#define INT_ADMA0 2
+#define INT_GDMA1 3
+#define INT_I2S0RX 4
+#define INT_I2S0TX 5
+#define INT_TC 6
+#define INT_UART0 7
+#define INT_USBD 8
+#define INT_SPI0TX 9
+#define INT_UDMA 10
+#define INT_LIRQ 11
+#define INT_GDMA2 12
+#define INT_GDMA0 13
+#define INT_TC32 14
+#define INT_LCD 15
+#define INT_ADC 16
+#define INT_I2C 17
+#define INT_RTCP 18
+#define INT_RTCA 19
+#define INT_NFC 20
+#define INT_SD0 21
+#define INT_GSB0 22
+#define INT_PK 23
+#define INT_USBH0 24
+#define INT_USBH1 25
+#define INT_G2D 26
+#define INT_ECC 27
+#define INT_SPI0RX 28
+#define INT_UART1 29
+#define INT_MSCL 30
+#define INT_GSB1 31
+/* PIC1 interrupts */
+#define INT_E0 32
+#define INT_E1 33
+#define INT_E2 34
+#define INT_E3 35
+#define INT_E4 36
+#define INT_E5 37
+#define INT_E6 38
+#define INT_E7 39
+#define INT_UART2 40
+#define INT_UART3 41
+#define INT_SPI1TX 42
+#define INT_SPI1RX 43
+#define INT_GSB2 44
+#define INT_SPDIF 45
+#define INT_CDIF 46
+#define INT_VBON 47
+#define INT_VBOFF 48
+#define INT_SD1 49
+#define INT_UART4 50
+#define INT_GDMA3 51
+#define INT_I2S1RX 52
+#define INT_I2S1TX 53
+#define INT_CAN0 54
+#define INT_CAN1 55
+#define INT_GSB3 56
+#define INT_KRST 57
+#define INT_UNUSED 58
+#define INT_SD0D3 59
+#define INT_SD1D3 60
+#define INT_GPS0 61
+#define INT_GPS1 62
+#define INT_GPS2 63
+
+#endif /* ASM_ARCH_TCC_IRQS_H */
diff --git a/arch/arm/plat-tcc/include/mach/memory.h b/arch/arm/plat-tcc/include/mach/memory.h
new file mode 100644
index 000000000000..cd91ba8a670b
--- /dev/null
+++ b/arch/arm/plat-tcc/include/mach/memory.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 1999 ARM Limited
+ * Copyright (C) 2000 RidgeRun, Inc.
+ * Copyright (C) 2008-2009 Telechips
+ * Copyright (C) 2010 Hans J. Koch <hjk@linutronix.de>
+ *
+ * Licensed under the terms of the GPL v2.
+ */
+
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+/*
+ * Physical DRAM offset.
+ */
+#define PHYS_OFFSET UL(0x20000000)
+
+#endif
diff --git a/arch/arm/plat-tcc/include/mach/system.h b/arch/arm/plat-tcc/include/mach/system.h
new file mode 100644
index 000000000000..909e6035d843
--- /dev/null
+++ b/arch/arm/plat-tcc/include/mach/system.h
@@ -0,0 +1,31 @@
+/*
+ * Author: <linux@telechips.com>
+ * Created: June 10, 2008
+ * Description: LINUX SYSTEM FUNCTIONS for TCC83x
+ *
+ * Copyright (C) 2008-2009 Telechips
+ *
+ * Licensed under the terms of the GPL v2.
+ *
+ */
+
+#ifndef __ASM_ARCH_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H
+#include <linux/clk.h>
+
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+
+extern void plat_tcc_reboot(void);
+
+static inline void arch_idle(void)
+{
+ cpu_do_idle();
+}
+
+static inline void arch_reset(char mode, const char *cmd)
+{
+ plat_tcc_reboot();
+}
+
+#endif
diff --git a/arch/arm/plat-tcc/include/mach/tcc8k-regs.h b/arch/arm/plat-tcc/include/mach/tcc8k-regs.h
new file mode 100644
index 000000000000..1d9428295332
--- /dev/null
+++ b/arch/arm/plat-tcc/include/mach/tcc8k-regs.h
@@ -0,0 +1,807 @@
+/*
+ * Telechips TCC8000 register definitions
+ *
+ * (C) 2009 Hans J. Koch <hjk@linutronix.de>
+ *
+ * Licensed under the terms of the GPLv2.
+ */
+
+#ifndef TCC8K_REGS_H
+#define TCC8K_REGS_H
+
+#include <linux/types.h>
+
+#define EXT_SDRAM_BASE 0x20000000
+#define INT_SRAM_BASE 0x30000000
+#define INT_SRAM_SIZE SZ_32K
+#define CS0_BASE 0x40000000
+#define CS1_BASE 0x50000000
+#define CS1_SIZE SZ_64K
+#define CS2_BASE 0x60000000
+#define CS3_BASE 0x70000000
+#define AHB_PERI_BASE 0x80000000
+#define AHB_PERI_SIZE SZ_64K
+#define APB0_PERI_BASE 0x90000000
+#define APB0_PERI_SIZE SZ_128K
+#define APB1_PERI_BASE 0x98000000
+#define APB1_PERI_SIZE SZ_128K
+#define DATA_TCM_BASE 0xa0000000
+#define DATA_TCM_SIZE SZ_8K
+#define EXT_MEM_CTRL_BASE 0xf0000000
+#define EXT_MEM_CTRL_SIZE SZ_4K
+
+#define CS1_BASE_VIRT (void __iomem *)0xf7000000
+#define AHB_PERI_BASE_VIRT (void __iomem *)0xf4000000
+#define APB0_PERI_BASE_VIRT (void __iomem *)0xf1000000
+#define APB1_PERI_BASE_VIRT (void __iomem *)0xf2000000
+#define EXT_MEM_CTRL_BASE_VIRT (void __iomem *)0xf3000000
+#define INT_SRAM_BASE_VIRT (void __iomem *)0xf5000000
+#define DATA_TCM_BASE_VIRT (void __iomem *)0xf6000000
+
+#define __REG(x) (*((volatile u32 *)(x)))
+
+/* USB Device Controller Registers */
+#define UDC_BASE (AHB_PERI_BASE_VIRT + 0x8000)
+#define UDC_BASE_PHYS (AHB_PERI_BASE + 0x8000)
+
+#define UDC_IR_OFFS 0x00
+#define UDC_EIR_OFFS 0x04
+#define UDC_EIER_OFFS 0x08
+#define UDC_FAR_OFFS 0x0c
+#define UDC_FNR_OFFS 0x10
+#define UDC_EDR_OFFS 0x14
+#define UDC_RT_OFFS 0x18
+#define UDC_SSR_OFFS 0x1c
+#define UDC_SCR_OFFS 0x20
+#define UDC_EP0SR_OFFS 0x24
+#define UDC_EP0CR_OFFS 0x28
+
+#define UDC_ESR_OFFS 0x2c
+#define UDC_ECR_OFFS 0x30
+#define UDC_BRCR_OFFS 0x34
+#define UDC_BWCR_OFFS 0x38
+#define UDC_MPR_OFFS 0x3c
+#define UDC_DCR_OFFS 0x40
+#define UDC_DTCR_OFFS 0x44
+#define UDC_DFCR_OFFS 0x48
+#define UDC_DTTCR1_OFFS 0x4c
+#define UDC_DTTCR2_OFFS 0x50
+#define UDC_ESR2_OFFS 0x54
+
+#define UDC_SCR2_OFFS 0x58
+#define UDC_EP0BUF_OFFS 0x60
+#define UDC_EP1BUF_OFFS 0x64
+#define UDC_EP2BUF_OFFS 0x68
+#define UDC_EP3BUF_OFFS 0x6c
+#define UDC_PLICR_OFFS 0xa0
+#define UDC_PCR_OFFS 0xa4
+
+#define UDC_UPCR0_OFFS 0xc8
+#define UDC_UPCR1_OFFS 0xcc
+#define UDC_UPCR2_OFFS 0xd0
+#define UDC_UPCR3_OFFS 0xd4
+
+/* Bits in UDC_EIR */
+#define UDC_EIR_EP0I (1 << 0)
+#define UDC_EIR_EP1I (1 << 1)
+#define UDC_EIR_EP2I (1 << 2)
+#define UDC_EIR_EP3I (1 << 3)
+#define UDC_EIR_EPI_MASK 0x0f
+
+/* Bits in UDC_EIER */
+#define UDC_EIER_EP0IE (1 << 0)
+#define UDC_EIER_EP1IE (1 << 1)
+#define UDC_EIER_EP2IE (1 << 2)
+#define UDC_EIER_EP3IE (1 << 3)
+
+/* Bits in UDC_FNR */
+#define UDC_FNR_FN_MASK 0x7ff
+#define UDC_FNR_SM (1 << 13)
+#define UDC_FNR_FTL (1 << 14)
+
+/* Bits in UDC_SSR */
+#define UDC_SSR_HFRES (1 << 0)
+#define UDC_SSR_HFSUSP (1 << 1)
+#define UDC_SSR_HFRM (1 << 2)
+#define UDC_SSR_SDE (1 << 3)
+#define UDC_SSR_HSP (1 << 4)
+#define UDC_SSR_DM (1 << 5)
+#define UDC_SSR_DP (1 << 6)
+#define UDC_SSR_TBM (1 << 7)
+#define UDC_SSR_VBON (1 << 8)
+#define UDC_SSR_VBOFF (1 << 9)
+#define UDC_SSR_EOERR (1 << 10)
+#define UDC_SSR_DCERR (1 << 11)
+#define UDC_SSR_TCERR (1 << 12)
+#define UDC_SSR_BSERR (1 << 13)
+#define UDC_SSR_TMERR (1 << 14)
+#define UDC_SSR_BAERR (1 << 15)
+
+/* Bits in UDC_SCR */
+#define UDC_SCR_HRESE (1 << 0)
+#define UDC_SCR_HSSPE (1 << 1)
+#define UDC_SCR_RRDE (1 << 5)
+#define UDC_SCR_SPDEN (1 << 6)
+#define UDC_SCR_DIEN (1 << 12)
+
+/* Bits in UDC_EP0SR */
+#define UDC_EP0SR_RSR (1 << 0)
+#define UDC_EP0SR_TST (1 << 1)
+#define UDC_EP0SR_SHT (1 << 4)
+#define UDC_EP0SR_LWO (1 << 6)
+
+/* Bits in UDC_EP0CR */
+#define UDC_EP0CR_ESS (1 << 1)
+
+/* Bits in UDC_ESR */
+#define UDC_ESR_RPS (1 << 0)
+#define UDC_ESR_TPS (1 << 1)
+#define UDC_ESR_LWO (1 << 4)
+#define UDC_ESR_FFS (1 << 6)
+
+/* Bits in UDC_ECR */
+#define UDC_ECR_ESS (1 << 1)
+#define UDC_ECR_CDP (1 << 2)
+
+#define UDC_ECR_FLUSH (1 << 6)
+#define UDC_ECR_DUEN (1 << 7)
+
+/* Bits in UDC_UPCR0 */
+#define UDC_UPCR0_VBD (1 << 1)
+#define UDC_UPCR0_VBDS (1 << 6)
+#define UDC_UPCR0_RCD_12 (0x0 << 9)
+#define UDC_UPCR0_RCD_24 (0x1 << 9)
+#define UDC_UPCR0_RCD_48 (0x2 << 9)
+#define UDC_UPCR0_RCS_EXT (0x1 << 11)
+#define UDC_UPCR0_RCS_XTAL (0x0 << 11)
+
+/* Bits in UDC_UPCR1 */
+#define UDC_UPCR1_CDT(x) ((x) << 0)
+#define UDC_UPCR1_OTGT(x) ((x) << 3)
+#define UDC_UPCR1_SQRXT(x) ((x) << 8)
+#define UDC_UPCR1_TXFSLST(x) ((x) << 12)
+
+/* Bits in UDC_UPCR2 */
+#define UDC_UPCR2_TP (1 << 0)
+#define UDC_UPCR2_TXRT(x) ((x) << 2)
+#define UDC_UPCR2_TXVRT(x) ((x) << 5)
+#define UDC_UPCR2_OPMODE(x) ((x) << 9)
+#define UDC_UPCR2_XCVRSEL(x) ((x) << 12)
+#define UDC_UPCR2_TM (1 << 14)
+
+/* USB Host Controller registers */
+#define USBH0_BASE (AHB_PERI_BASE_VIRT + 0xb000)
+#define USBH1_BASE (AHB_PERI_BASE_VIRT + 0xb800)
+
+#define OHCI_INT_ENABLE_OFFS 0x10
+
+#define RH_DESCRIPTOR_A_OFFS 0x48
+#define RH_DESCRIPTOR_B_OFFS 0x4c
+
+#define USBHTCFG0_OFFS 0x100
+#define USBHHCFG0_OFFS 0x104
+#define USBHHCFG1_OFFS 0x104
+
+/* DMA controller registers */
+#define DMAC0_BASE (AHB_PERI_BASE + 0x4000)
+#define DMAC1_BASE (AHB_PERI_BASE + 0xa000)
+#define DMAC2_BASE (AHB_PERI_BASE + 0x4800)
+#define DMAC3_BASE (AHB_PERI_BASE + 0xa800)
+
+#define DMAC_CH_OFFSET(ch) (ch * 0x30)
+
+#define ST_SADR_OFFS 0x00
+#define SPARAM_OFFS 0x04
+#define C_SADR_OFFS 0x0c
+#define ST_DADR_OFFS 0x10
+#define DPARAM_OFFS 0x14
+#define C_DADR_OFFS 0x1c
+#define HCOUNT_OFFS 0x20
+#define CHCTRL_OFFS 0x24
+#define RPTCTRL_OFFS 0x28
+#define EXTREQ_A_OFFS 0x2c
+
+/* Bits in CHCTRL register */
+#define CHCTRL_EN (1 << 0)
+
+#define CHCTRL_IEN (1 << 2)
+#define CHCTRL_FLAG (1 << 3)
+#define CHCTRL_WSIZE8 (0 << 4)
+#define CHCTRL_WSIZE16 (1 << 4)
+#define CHCTRL_WSIZE32 (2 << 4)
+
+#define CHCTRL_BSIZE1 (0 << 6)
+#define CHCTRL_BSIZE2 (1 << 6)
+#define CHCTRL_BSIZE4 (2 << 6)
+#define CHCTRL_BSIZE8 (3 << 6)
+
+#define CHCTRL_TYPE_SINGLE_E (0 << 8)
+#define CHCTRL_TYPE_HW (1 << 8)
+#define CHCTRL_TYPE_SW (2 << 8)
+#define CHCTRL_TYPE_SINGLE_L (3 << 8)
+
+#define CHCTRL_BST (1 << 10)
+
+/* Use DMA controller 0, channel 2 for USB */
+#define USB_DMA_BASE (DMAC0_BASE + DMAC_CH_OFFSET(2))
+
+/* NAND flash controller registers */
+#define NFC_BASE (AHB_PERI_BASE_VIRT + 0xd000)
+#define NFC_BASE_PHYS (AHB_PERI_BASE + 0xd000)
+
+#define NFC_CMD_OFFS 0x00
+#define NFC_LADDR_OFFS 0x04
+#define NFC_BADDR_OFFS 0x08
+#define NFC_SADDR_OFFS 0x0c
+#define NFC_WDATA_OFFS 0x10
+#define NFC_LDATA_OFFS 0x20
+#define NFC_SDATA_OFFS 0x40
+#define NFC_CTRL_OFFS 0x50
+#define NFC_PSTART_OFFS 0x54
+#define NFC_RSTART_OFFS 0x58
+#define NFC_DSIZE_OFFS 0x5c
+#define NFC_IREQ_OFFS 0x60
+#define NFC_RST_OFFS 0x64
+#define NFC_CTRL1_OFFS 0x68
+#define NFC_MDATA_OFFS 0x70
+
+#define NFC_WDATA_PHYS_ADDR (NFC_BASE_PHYS + NFC_WDATA_OFFS)
+
+/* Bits in NFC_CTRL */
+#define NFC_CTRL_BHLD_MASK (0xf << 0)
+#define NFC_CTRL_BPW_MASK (0xf << 4)
+#define NFC_CTRL_BSTP_MASK (0xf << 8)
+#define NFC_CTRL_CADDR_MASK (0x7 << 12)
+#define NFC_CTRL_CADDR_1 (0x0 << 12)
+#define NFC_CTRL_CADDR_2 (0x1 << 12)
+#define NFC_CTRL_CADDR_3 (0x2 << 12)
+#define NFC_CTRL_CADDR_4 (0x3 << 12)
+#define NFC_CTRL_CADDR_5 (0x4 << 12)
+#define NFC_CTRL_MSK (1 << 15)
+#define NFC_CTRL_PSIZE256 (0 << 16)
+#define NFC_CTRL_PSIZE512 (1 << 16)
+#define NFC_CTRL_PSIZE1024 (2 << 16)
+#define NFC_CTRL_PSIZE2048 (3 << 16)
+#define NFC_CTRL_PSIZE4096 (4 << 16)
+#define NFC_CTRL_PSIZE_MASK (7 << 16)
+#define NFC_CTRL_BSIZE1 (0 << 19)
+#define NFC_CTRL_BSIZE2 (1 << 19)
+#define NFC_CTRL_BSIZE4 (2 << 19)
+#define NFC_CTRL_BSIZE8 (3 << 19)
+#define NFC_CTRL_BSIZE_MASK (3 << 19)
+#define NFC_CTRL_RDY (1 << 21)
+#define NFC_CTRL_CS0SEL (1 << 22)
+#define NFC_CTRL_CS1SEL (1 << 23)
+#define NFC_CTRL_CS2SEL (1 << 24)
+#define NFC_CTRL_CS3SEL (1 << 25)
+#define NFC_CTRL_CSMASK (0xf << 22)
+#define NFC_CTRL_BW (1 << 26)
+#define NFC_CTRL_FS (1 << 27)
+#define NFC_CTRL_DEN (1 << 28)
+#define NFC_CTRL_READ_IEN (1 << 29)
+#define NFC_CTRL_PROG_IEN (1 << 30)
+#define NFC_CTRL_RDY_IEN (1 << 31)
+
+/* Bits in NFC_IREQ */
+#define NFC_IREQ_IRQ0 (1 << 0)
+#define NFC_IREQ_IRQ1 (1 << 1)
+#define NFC_IREQ_IRQ2 (1 << 2)
+
+#define NFC_IREQ_FLAG0 (1 << 4)
+#define NFC_IREQ_FLAG1 (1 << 5)
+#define NFC_IREQ_FLAG2 (1 << 6)
+
+/* MMC controller registers */
+#define MMC0_BASE (AHB_PERI_BASE_VIRT + 0xe000)
+#define MMC1_BASE (AHB_PERI_BASE_VIRT + 0xe800)
+
+/* UART base addresses */
+
+#define UART0_BASE (APB0_PERI_BASE_VIRT + 0x07000)
+#define UART0_BASE_PHYS (APB0_PERI_BASE + 0x07000)
+#define UART1_BASE (APB0_PERI_BASE_VIRT + 0x08000)
+#define UART1_BASE_PHYS (APB0_PERI_BASE + 0x08000)
+#define UART2_BASE (APB0_PERI_BASE_VIRT + 0x09000)
+#define UART2_BASE_PHYS (APB0_PERI_BASE + 0x09000)
+#define UART3_BASE (APB0_PERI_BASE_VIRT + 0x0a000)
+#define UART3_BASE_PHYS (APB0_PERI_BASE + 0x0a000)
+#define UART4_BASE (APB0_PERI_BASE_VIRT + 0x15000)
+#define UART4_BASE_PHYS (APB0_PERI_BASE + 0x15000)
+
+#define UART_BASE UART0_BASE
+#define UART_BASE_PHYS UART0_BASE_PHYS
+
+/* ECC controller */
+#define ECC_CTR_BASE (APB0_PERI_BASE_VIRT + 0xd000)
+
+#define ECC_CTRL_OFFS 0x00
+#define ECC_BASE_OFFS 0x04
+#define ECC_MASK_OFFS 0x08
+#define ECC_CLEAR_OFFS 0x0c
+#define ECC4_0_OFFS 0x10
+#define ECC4_1_OFFS 0x14
+
+#define ECC_EADDR0_OFFS 0x50
+
+#define ECC_ERRNUM_OFFS 0x90
+#define ECC_IREQ_OFFS 0x94
+
+/* Bits in ECC_CTRL */
+#define ECC_CTRL_ECC4_DIEN (1 << 28)
+#define ECC_CTRL_ECC8_DIEN (1 << 29)
+#define ECC_CTRL_ECC12_DIEN (1 << 30)
+#define ECC_CTRL_ECC_DISABLE 0x0
+#define ECC_CTRL_ECC_SLC_ENC 0x8
+#define ECC_CTRL_ECC_SLC_DEC 0x9
+#define ECC_CTRL_ECC4_ENC 0xa
+#define ECC_CTRL_ECC4_DEC 0xb
+#define ECC_CTRL_ECC8_ENC 0xc
+#define ECC_CTRL_ECC8_DEC 0xd
+#define ECC_CTRL_ECC12_ENC 0xe
+#define ECC_CTRL_ECC12_DEC 0xf
+
+/* Bits in ECC_IREQ */
+#define ECC_IREQ_E4DI (1 << 4)
+
+#define ECC_IREQ_E4DF (1 << 20)
+#define ECC_IREQ_E4EF (1 << 21)
+
+/* Interrupt controller */
+
+#define PIC0_BASE (APB1_PERI_BASE_VIRT + 0x3000)
+#define PIC0_BASE_PHYS (APB1_PERI_BASE + 0x3000)
+
+#define PIC0_IEN_OFFS 0x00
+#define PIC0_CREQ_OFFS 0x04
+#define PIC0_IREQ_OFFS 0x08
+#define PIC0_IRQSEL_OFFS 0x0c
+#define PIC0_SRC_OFFS 0x10
+#define PIC0_MREQ_OFFS 0x14
+#define PIC0_TSTREQ_OFFS 0x18
+#define PIC0_POL_OFFS 0x1c
+#define PIC0_IRQ_OFFS 0x20
+#define PIC0_FIQ_OFFS 0x24
+#define PIC0_MIRQ_OFFS 0x28
+#define PIC0_MFIQ_OFFS 0x2c
+#define PIC0_TMODE_OFFS 0x30
+#define PIC0_SYNC_OFFS 0x34
+#define PIC0_WKUP_OFFS 0x38
+#define PIC0_TMODEA_OFFS 0x3c
+#define PIC0_INTOEN_OFFS 0x40
+#define PIC0_MEN0_OFFS 0x44
+#define PIC0_MEN_OFFS 0x48
+
+#define PIC0_IEN __REG(PIC0_BASE + PIC0_IEN_OFFS)
+#define PIC0_IEN_PHYS __REG(PIC0_BASE_PHYS + PIC0_IEN_OFFS)
+#define PIC0_CREQ __REG(PIC0_BASE + PIC0_CREQ_OFFS)
+#define PIC0_CREQ_PHYS __REG(PIC0_BASE_PHYS + PIC0_CREQ_OFFS)
+#define PIC0_IREQ __REG(PIC0_BASE + PIC0_IREQ_OFFS)
+#define PIC0_IRQSEL __REG(PIC0_BASE + PIC0_IRQSEL_OFFS)
+#define PIC0_IRQSEL_PHYS __REG(PIC0_BASE_PHYS + PIC0_IRQSEL_OFFS)
+#define PIC0_SRC __REG(PIC0_BASE + PIC0_SRC_OFFS)
+#define PIC0_MREQ __REG(PIC0_BASE + PIC0_MREQ_OFFS)
+#define PIC0_TSTREQ __REG(PIC0_BASE + PIC0_TSTREQ_OFFS)
+#define PIC0_POL __REG(PIC0_BASE + PIC0_POL_OFFS)
+#define PIC0_IRQ __REG(PIC0_BASE + PIC0_IRQ_OFFS)
+#define PIC0_FIQ __REG(PIC0_BASE + PIC0_FIQ_OFFS)
+#define PIC0_MIRQ __REG(PIC0_BASE + PIC0_MIRQ_OFFS)
+#define PIC0_MFIQ __REG(PIC0_BASE + PIC0_MFIQ_OFFS)
+#define PIC0_TMODE __REG(PIC0_BASE + PIC0_TMODE_OFFS)
+#define PIC0_TMODE_PHYS __REG(PIC0_BASE_PHYS + PIC0_TMODE_OFFS)
+#define PIC0_SYNC __REG(PIC0_BASE + PIC0_SYNC_OFFS)
+#define PIC0_WKUP __REG(PIC0_BASE + PIC0_WKUP_OFFS)
+#define PIC0_TMODEA __REG(PIC0_BASE + PIC0_TMODEA_OFFS)
+#define PIC0_INTOEN __REG(PIC0_BASE + PIC0_INTOEN_OFFS)
+#define PIC0_MEN0 __REG(PIC0_BASE + PIC0_MEN0_OFFS)
+#define PIC0_MEN __REG(PIC0_BASE + PIC0_MEN_OFFS)
+
+#define PIC1_BASE (APB1_PERI_BASE_VIRT + 0x3080)
+
+#define PIC1_IEN_OFFS 0x00
+#define PIC1_CREQ_OFFS 0x04
+#define PIC1_IREQ_OFFS 0x08
+#define PIC1_IRQSEL_OFFS 0x0c
+#define PIC1_SRC_OFFS 0x10
+#define PIC1_MREQ_OFFS 0x14
+#define PIC1_TSTREQ_OFFS 0x18
+#define PIC1_POL_OFFS 0x1c
+#define PIC1_IRQ_OFFS 0x20
+#define PIC1_FIQ_OFFS 0x24
+#define PIC1_MIRQ_OFFS 0x28
+#define PIC1_MFIQ_OFFS 0x2c
+#define PIC1_TMODE_OFFS 0x30
+#define PIC1_SYNC_OFFS 0x34
+#define PIC1_WKUP_OFFS 0x38
+#define PIC1_TMODEA_OFFS 0x3c
+#define PIC1_INTOEN_OFFS 0x40
+#define PIC1_MEN1_OFFS 0x44
+#define PIC1_MEN_OFFS 0x48
+
+#define PIC1_IEN __REG(PIC1_BASE + PIC1_IEN_OFFS)
+#define PIC1_CREQ __REG(PIC1_BASE + PIC1_CREQ_OFFS)
+#define PIC1_IREQ __REG(PIC1_BASE + PIC1_IREQ_OFFS)
+#define PIC1_IRQSEL __REG(PIC1_BASE + PIC1_IRQSEL_OFFS)
+#define PIC1_SRC __REG(PIC1_BASE + PIC1_SRC_OFFS)
+#define PIC1_MREQ __REG(PIC1_BASE + PIC1_MREQ_OFFS)
+#define PIC1_TSTREQ __REG(PIC1_BASE + PIC1_TSTREQ_OFFS)
+#define PIC1_POL __REG(PIC1_BASE + PIC1_POL_OFFS)
+#define PIC1_IRQ __REG(PIC1_BASE + PIC1_IRQ_OFFS)
+#define PIC1_FIQ __REG(PIC1_BASE + PIC1_FIQ_OFFS)
+#define PIC1_MIRQ __REG(PIC1_BASE + PIC1_MIRQ_OFFS)
+#define PIC1_MFIQ __REG(PIC1_BASE + PIC1_MFIQ_OFFS)
+#define PIC1_TMODE __REG(PIC1_BASE + PIC1_TMODE_OFFS)
+#define PIC1_SYNC __REG(PIC1_BASE + PIC1_SYNC_OFFS)
+#define PIC1_WKUP __REG(PIC1_BASE + PIC1_WKUP_OFFS)
+#define PIC1_TMODEA __REG(PIC1_BASE + PIC1_TMODEA_OFFS)
+#define PIC1_INTOEN __REG(PIC1_BASE + PIC1_INTOEN_OFFS)
+#define PIC1_MEN1 __REG(PIC1_BASE + PIC1_MEN1_OFFS)
+#define PIC1_MEN __REG(PIC1_BASE + PIC1_MEN_OFFS)
+
+/* Timer registers */
+#define TIMER_BASE (APB1_PERI_BASE_VIRT + 0x4000)
+#define TIMER_BASE_PHYS (APB1_PERI_BASE + 0x4000)
+
+#define TWDCFG_OFFS 0x70
+
+#define TC32EN_OFFS 0x80
+#define TC32LDV_OFFS 0x84
+#define TC32CMP0_OFFS 0x88
+#define TC32CMP1_OFFS 0x8c
+#define TC32PCNT_OFFS 0x90
+#define TC32MCNT_OFFS 0x94
+#define TC32IRQ_OFFS 0x98
+
+/* Bits in TC32EN */
+#define TC32EN_PRESCALE_MASK 0x00ffffff
+#define TC32EN_ENABLE (1 << 24)
+#define TC32EN_LOADZERO (1 << 25)
+#define TC32EN_STOPMODE (1 << 26)
+#define TC32EN_LDM0 (1 << 28)
+#define TC32EN_LDM1 (1 << 29)
+
+/* Bits in TC32IRQ */
+#define TC32IRQ_MSTAT_MASK 0x0000001f
+#define TC32IRQ_RSTAT_MASK (0x1f << 8)
+#define TC32IRQ_IRQEN0 (1 << 16)
+#define TC32IRQ_IRQEN1 (1 << 17)
+#define TC32IRQ_IRQEN2 (1 << 18)
+#define TC32IRQ_IRQEN3 (1 << 19)
+#define TC32IRQ_IRQEN4 (1 << 20)
+#define TC32IRQ_RSYNC (1 << 30)
+#define TC32IRQ_IRQCLR (1 << 31)
+
+/* GPIO registers */
+#define GPIOPD_BASE (APB1_PERI_BASE_VIRT + 0x5000)
+
+#define GPIOPD_DAT_OFFS 0x00
+#define GPIOPD_DOE_OFFS 0x04
+#define GPIOPD_FS0_OFFS 0x08
+#define GPIOPD_FS1_OFFS 0x0c
+#define GPIOPD_FS2_OFFS 0x10
+#define GPIOPD_RPU_OFFS 0x30
+#define GPIOPD_RPD_OFFS 0x34
+#define GPIOPD_DV0_OFFS 0x38
+#define GPIOPD_DV1_OFFS 0x3c
+
+#define GPIOPS_BASE (APB1_PERI_BASE_VIRT + 0x5000)
+
+#define GPIOPS_DAT_OFFS 0x40
+#define GPIOPS_DOE_OFFS 0x44
+#define GPIOPS_FS0_OFFS 0x48
+#define GPIOPS_FS1_OFFS 0x4c
+#define GPIOPS_FS2_OFFS 0x50
+#define GPIOPS_FS3_OFFS 0x54
+#define GPIOPS_RPU_OFFS 0x70
+#define GPIOPS_RPD_OFFS 0x74
+#define GPIOPS_DV0_OFFS 0x78
+#define GPIOPS_DV1_OFFS 0x7c
+
+#define GPIOPS_FS1_SDH0_BITS 0x000000ff
+#define GPIOPS_FS1_SDH1_BITS 0x0000ff00
+
+#define GPIOPU_BASE (APB1_PERI_BASE_VIRT + 0x5000)
+
+#define GPIOPU_DAT_OFFS 0x80
+#define GPIOPU_DOE_OFFS 0x84
+#define GPIOPU_FS0_OFFS 0x88
+#define GPIOPU_FS1_OFFS 0x8c
+#define GPIOPU_FS2_OFFS 0x90
+#define GPIOPU_RPU_OFFS 0xb0
+#define GPIOPU_RPD_OFFS 0xb4
+#define GPIOPU_DV0_OFFS 0xb8
+#define GPIOPU_DV1_OFFS 0xbc
+
+#define GPIOPU_FS0_TXD0 (1 << 0)
+#define GPIOPU_FS0_RXD0 (1 << 1)
+#define GPIOPU_FS0_CTS0 (1 << 2)
+#define GPIOPU_FS0_RTS0 (1 << 3)
+#define GPIOPU_FS0_TXD1 (1 << 4)
+#define GPIOPU_FS0_RXD1 (1 << 5)
+#define GPIOPU_FS0_CTS1 (1 << 6)
+#define GPIOPU_FS0_RTS1 (1 << 7)
+#define GPIOPU_FS0_TXD2 (1 << 8)
+#define GPIOPU_FS0_RXD2 (1 << 9)
+#define GPIOPU_FS0_CTS2 (1 << 10)
+#define GPIOPU_FS0_RTS2 (1 << 11)
+#define GPIOPU_FS0_TXD3 (1 << 12)
+#define GPIOPU_FS0_RXD3 (1 << 13)
+#define GPIOPU_FS0_CTS3 (1 << 14)
+#define GPIOPU_FS0_RTS3 (1 << 15)
+#define GPIOPU_FS0_TXD4 (1 << 16)
+#define GPIOPU_FS0_RXD4 (1 << 17)
+#define GPIOPU_FS0_CTS4 (1 << 18)
+#define GPIOPU_FS0_RTS4 (1 << 19)
+
+#define GPIOFC_BASE (APB1_PERI_BASE_VIRT + 0x5000)
+
+#define GPIOFC_DAT_OFFS 0xc0
+#define GPIOFC_DOE_OFFS 0xc4
+#define GPIOFC_FS0_OFFS 0xc8
+#define GPIOFC_FS1_OFFS 0xcc
+#define GPIOFC_FS2_OFFS 0xd0
+#define GPIOFC_FS3_OFFS 0xd4
+#define GPIOFC_RPU_OFFS 0xf0
+#define GPIOFC_RPD_OFFS 0xf4
+#define GPIOFC_DV0_OFFS 0xf8
+#define GPIOFC_DV1_OFFS 0xfc
+
+#define GPIOFD_BASE (APB1_PERI_BASE_VIRT + 0x5000)
+
+#define GPIOFD_DAT_OFFS 0x100
+#define GPIOFD_DOE_OFFS 0x104
+#define GPIOFD_FS0_OFFS 0x108
+#define GPIOFD_FS1_OFFS 0x10c
+#define GPIOFD_FS2_OFFS 0x110
+#define GPIOFD_RPU_OFFS 0x130
+#define GPIOFD_RPD_OFFS 0x134
+#define GPIOFD_DV0_OFFS 0x138
+#define GPIOFD_DV1_OFFS 0x13c
+
+#define GPIOLC_BASE (APB1_PERI_BASE_VIRT + 0x5000)
+
+#define GPIOLC_DAT_OFFS 0x140
+#define GPIOLC_DOE_OFFS 0x144
+#define GPIOLC_FS0_OFFS 0x148
+#define GPIOLC_FS1_OFFS 0x14c
+#define GPIOLC_RPU_OFFS 0x170
+#define GPIOLC_RPD_OFFS 0x174
+#define GPIOLC_DV0_OFFS 0x178
+#define GPIOLC_DV1_OFFS 0x17c
+
+#define GPIOLD_BASE (APB1_PERI_BASE_VIRT + 0x5000)
+
+#define GPIOLD_DAT_OFFS 0x180
+#define GPIOLD_DOE_OFFS 0x184
+#define GPIOLD_FS0_OFFS 0x188
+#define GPIOLD_FS1_OFFS 0x18c
+#define GPIOLD_FS2_OFFS 0x190
+#define GPIOLD_RPU_OFFS 0x1b0
+#define GPIOLD_RPD_OFFS 0x1b4
+#define GPIOLD_DV0_OFFS 0x1b8
+#define GPIOLD_DV1_OFFS 0x1bc
+
+#define GPIOAD_BASE (APB1_PERI_BASE_VIRT + 0x5000)
+
+#define GPIOAD_DAT_OFFS 0x1c0
+#define GPIOAD_DOE_OFFS 0x1c4
+#define GPIOAD_FS0_OFFS 0x1c8
+#define GPIOAD_RPU_OFFS 0x1f0
+#define GPIOAD_RPD_OFFS 0x1f4
+#define GPIOAD_DV0_OFFS 0x1f8
+#define GPIOAD_DV1_OFFS 0x1fc
+
+#define GPIOXC_BASE (APB1_PERI_BASE_VIRT + 0x5000)
+
+#define GPIOXC_DAT_OFFS 0x200
+#define GPIOXC_DOE_OFFS 0x204
+#define GPIOXC_FS0_OFFS 0x208
+#define GPIOXC_RPU_OFFS 0x230
+#define GPIOXC_RPD_OFFS 0x234
+#define GPIOXC_DV0_OFFS 0x238
+#define GPIOXC_DV1_OFFS 0x23c
+
+#define GPIOXC_FS0 __REG(GPIOXC_BASE + GPIOXC_FS0_OFFS)
+
+#define GPIOXC_FS0_CS0 (1 << 26)
+#define GPIOXC_FS0_CS1 (1 << 27)
+
+#define GPIOXD_BASE (APB1_PERI_BASE_VIRT + 0x5000)
+
+#define GPIOXD_DAT_OFFS 0x240
+#define GPIOXD_FS0_OFFS 0x248
+#define GPIOXD_RPU_OFFS 0x270
+#define GPIOXD_RPD_OFFS 0x274
+#define GPIOXD_DV0_OFFS 0x278
+#define GPIOXD_DV1_OFFS 0x27c
+
+#define GPIOPK_BASE (APB1_PERI_BASE_VIRT + 0x1c000)
+
+#define GPIOPK_RST_OFFS 0x008
+#define GPIOPK_DAT_OFFS 0x100
+#define GPIOPK_DOE_OFFS 0x104
+#define GPIOPK_FS0_OFFS 0x108
+#define GPIOPK_FS1_OFFS 0x10c
+#define GPIOPK_FS2_OFFS 0x110
+#define GPIOPK_IRQST_OFFS 0x210
+#define GPIOPK_IRQEN_OFFS 0x214
+#define GPIOPK_IRQPOL_OFFS 0x218
+#define GPIOPK_IRQTM0_OFFS 0x21c
+#define GPIOPK_IRQTM1_OFFS 0x220
+#define GPIOPK_CTL_OFFS 0x22c
+
+#define PMGPIO_BASE (APB1_PERI_BASE_VIRT + 0x10000)
+#define BACKUP_RAM_BASE PMGPIO_BASE
+
+#define PMGPIO_DAT_OFFS 0x800
+#define PMGPIO_DOE_OFFS 0x804
+#define PMGPIO_FS0_OFFS 0x808
+#define PMGPIO_RPU_OFFS 0x810
+#define PMGPIO_RPD_OFFS 0x814
+#define PMGPIO_DV0_OFFS 0x818
+#define PMGPIO_DV1_OFFS 0x81c
+#define PMGPIO_EE0_OFFS 0x820
+#define PMGPIO_EE1_OFFS 0x824
+#define PMGPIO_CTL_OFFS 0x828
+#define PMGPIO_DI_OFFS 0x82c
+#define PMGPIO_STR_OFFS 0x830
+#define PMGPIO_STF_OFFS 0x834
+#define PMGPIO_POL_OFFS 0x838
+#define PMGPIO_APB_OFFS 0x800
+
+/* Clock controller registers */
+#define CKC_BASE ((void __iomem *)(APB1_PERI_BASE_VIRT + 0x6000))
+
+#define CLKCTRL_OFFS 0x00
+#define PLL0CFG_OFFS 0x04
+#define PLL1CFG_OFFS 0x08
+#define CLKDIVC0_OFFS 0x0c
+
+#define BCLKCTR0_OFFS 0x14
+#define SWRESET0_OFFS 0x18
+
+#define BCLKCTR1_OFFS 0x60
+#define SWRESET1_OFFS 0x64
+#define PWDCTL_OFFS 0x68
+#define PLL2CFG_OFFS 0x6c
+#define CLKDIVC1_OFFS 0x70
+
+#define ACLKREF_OFFS 0x80
+#define ACLKI2C_OFFS 0x84
+#define ACLKSPI0_OFFS 0x88
+#define ACLKSPI1_OFFS 0x8c
+#define ACLKUART0_OFFS 0x90
+#define ACLKUART1_OFFS 0x94
+#define ACLKUART2_OFFS 0x98
+#define ACLKUART3_OFFS 0x9c
+#define ACLKUART4_OFFS 0xa0
+#define ACLKTCT_OFFS 0xa4
+#define ACLKTCX_OFFS 0xa8
+#define ACLKTCZ_OFFS 0xac
+#define ACLKADC_OFFS 0xb0
+#define ACLKDAI0_OFFS 0xb4
+#define ACLKDAI1_OFFS 0xb8
+#define ACLKLCD_OFFS 0xbc
+#define ACLKSPDIF_OFFS 0xc0
+#define ACLKUSBH_OFFS 0xc4
+#define ACLKSDH0_OFFS 0xc8
+#define ACLKSDH1_OFFS 0xcc
+#define ACLKC3DEC_OFFS 0xd0
+#define ACLKEXT_OFFS 0xd4
+#define ACLKCAN0_OFFS 0xd8
+#define ACLKCAN1_OFFS 0xdc
+#define ACLKGSB0_OFFS 0xe0
+#define ACLKGSB1_OFFS 0xe4
+#define ACLKGSB2_OFFS 0xe8
+#define ACLKGSB3_OFFS 0xec
+
+#define PLLxCFG_PD (1 << 31)
+
+/* CLKCTRL bits */
+#define CLKCTRL_XE (1 << 31)
+
+/* CLKDIVCx bits */
+#define CLKDIVC0_XTE (1 << 7)
+#define CLKDIVC0_XE (1 << 15)
+#define CLKDIVC0_P1E (1 << 23)
+#define CLKDIVC0_P0E (1 << 31)
+
+#define CLKDIVC1_P2E (1 << 7)
+
+/* BCLKCTR0 clock bits */
+#define BCLKCTR0_USBD (1 << 4)
+#define BCLKCTR0_ECC (1 << 9)
+#define BCLKCTR0_USBH0 (1 << 11)
+#define BCLKCTR0_NFC (1 << 16)
+
+/* BCLKCTR1 clock bits */
+#define BCLKCTR1_USBH1 (1 << 20)
+
+/* SWRESET0 bits */
+#define SWRESET0_USBD (1 << 4)
+#define SWRESET0_USBH0 (1 << 11)
+
+/* SWRESET1 bits */
+#define SWRESET1_USBH1 (1 << 20)
+
+/* System clock sources.
+ * Note: These are the clock sources that serve as parents for
+ * all other clocks. They have no parents themselves.
+ *
+ * These values are used for struct clk->root_id. All clocks
+ * that are not system clock sources have this value set to
+ * CLK_SRC_NOROOT.
+ * The values for system clocks start with CLK_SRC_PLL0 == 0
+ * because this gives us exactly the values needed for the lower
+ * 4 bits of ACLK_* registers. Therefore, CLK_SRC_NOROOT is
+ * defined as -1 to not disturb the order.
+ */
+enum root_clks {
+ CLK_SRC_NOROOT = -1,
+ CLK_SRC_PLL0 = 0,
+ CLK_SRC_PLL1,
+ CLK_SRC_PLL0DIV,
+ CLK_SRC_PLL1DIV,
+ CLK_SRC_XI,
+ CLK_SRC_XIDIV,
+ CLK_SRC_XTI,
+ CLK_SRC_XTIDIV,
+ CLK_SRC_PLL2,
+ CLK_SRC_PLL2DIV,
+ CLK_SRC_PK0,
+ CLK_SRC_PK1,
+ CLK_SRC_PK2,
+ CLK_SRC_PK3,
+ CLK_SRC_PK4,
+ CLK_SRC_48MHZ
+};
+
+#define CLK_SRC_MASK 0xf
+
+/* Bits in ACLK* registers */
+#define ACLK_EN (1 << 28)
+#define ACLK_SEL_SHIFT 24
+#define ACLK_SEL_MASK 0x0f000000
+#define ACLK_DIV_MASK 0x00000fff
+
+/* System configuration registers */
+
+#define SCFG_BASE (APB1_PERI_BASE_VIRT + 0x13000)
+
+#define BMI_OFFS 0x00
+#define AHBCON0_OFFS 0x04
+#define APBPWE_OFFS 0x08
+#define DTCMWAIT_OFFS 0x0c
+#define ECCSEL_OFFS 0x10
+#define AHBCON1_OFFS 0x14
+#define SDHCFG_OFFS 0x18
+#define REMAP_OFFS 0x20
+#define LCDSIAE_OFFS 0x24
+#define XMCCFG_OFFS 0xe0
+#define IMCCFG_OFFS 0xe4
+
+/* Values for ECCSEL */
+#define ECCSEL_EXTMEM 0x0
+#define ECCSEL_DTCM 0x1
+#define ECCSEL_INT_SRAM 0x2
+#define ECCSEL_AHB 0x3
+
+/* Bits in XMCCFG */
+#define XMCCFG_NFCE (1 << 1)
+#define XMCCFG_FDXD (1 << 2)
+
+/* External memory controller registers */
+
+#define EMC_BASE EXT_MEM_CTRL_BASE
+
+#define SDCFG_OFFS 0x00
+#define SDFSM_OFFS 0x04
+#define MCFG_OFFS 0x08
+
+#define CSCFG0_OFFS 0x10
+#define CSCFG1_OFFS 0x14
+#define CSCFG2_OFFS 0x18
+#define CSCFG3_OFFS 0x1c
+
+#define MCFG_SDEN (1 << 4)
+
+#endif /* TCC8K_REGS_H */
diff --git a/arch/arm/plat-tcc/include/mach/timex.h b/arch/arm/plat-tcc/include/mach/timex.h
new file mode 100644
index 000000000000..057acbe651d9
--- /dev/null
+++ b/arch/arm/plat-tcc/include/mach/timex.h
@@ -0,0 +1,5 @@
+/*
+ * A definition needed by arch core code.
+ *
+ */
+#define CLOCK_TICK_RATE (HZ * 100000UL)
diff --git a/arch/arm/plat-tcc/include/mach/uncompress.h b/arch/arm/plat-tcc/include/mach/uncompress.h
new file mode 100644
index 000000000000..7a3e33a27a30
--- /dev/null
+++ b/arch/arm/plat-tcc/include/mach/uncompress.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2009 Hans J. Koch <hjk@linutronix.de>
+ *
+ * This file is licensed under the terms of the GPL version 2.
+ */
+
+#include <linux/serial_reg.h>
+#include <linux/types.h>
+
+#include <mach/tcc8k-regs.h>
+
+unsigned int system_rev;
+
+#define ID_MASK 0x7fff
+
+static void putc(int c)
+{
+ u32 *uart_lsr = (u32 *)(UART_BASE_PHYS + (UART_LSR << 2));
+ u32 *uart_tx = (u32 *)(UART_BASE_PHYS + (UART_TX << 2));
+
+ while (!(*uart_lsr & UART_LSR_THRE))
+ barrier();
+ *uart_tx = c;
+}
+
+static inline void flush(void)
+{
+}
+
+/*
+ * nothing to do
+ */
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
diff --git a/arch/arm/plat-tcc/include/mach/vmalloc.h b/arch/arm/plat-tcc/include/mach/vmalloc.h
new file mode 100644
index 000000000000..99414d9c2b94
--- /dev/null
+++ b/arch/arm/plat-tcc/include/mach/vmalloc.h
@@ -0,0 +1,10 @@
+/*
+ * Author: <linux@telechips.com>
+ * Created: June 10, 2008
+ *
+ * Copyright (C) 2000 Russell King.
+ * Copyright (C) 2008-2009 Telechips
+ *
+ * Licensed under the terms of the GPL v2.
+ */
+#define VMALLOC_END 0xf0000000UL
diff --git a/arch/arm/plat-tcc/system.c b/arch/arm/plat-tcc/system.c
new file mode 100644
index 000000000000..cc208fae3e7a
--- /dev/null
+++ b/arch/arm/plat-tcc/system.c
@@ -0,0 +1,25 @@
+/*
+ * System functions for Telechips TCCxxxx SoCs
+ *
+ * Copyright (C) Hans J. Koch <hjk@linutronix.de>
+ *
+ * Licensed under the terms of the GPL v2.
+ *
+ */
+
+#include <linux/io.h>
+
+#include <mach/tcc8k-regs.h>
+
+/* System reboot */
+void plat_tcc_reboot(void)
+{
+ /* Make sure clocks are on */
+ __raw_writel(0xffffffff, CKC_BASE + BCLKCTR0_OFFS);
+
+ /* Enable watchdog reset */
+ __raw_writel(0x49, TIMER_BASE + TWDCFG_OFFS);
+ /* Wait for reset */
+ while(1)
+ ;
+}
diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig
index f51572772e21..9ac87255a03a 100644
--- a/arch/avr32/Kconfig
+++ b/arch/avr32/Kconfig
@@ -90,6 +90,7 @@ config PLATFORM_AT32AP
select ARCH_REQUIRE_GPIOLIB
select GENERIC_ALLOCATOR
select HAVE_FB_ATMEL
+ select HAVE_NET_MACB
#
# CPU types
diff --git a/arch/avr32/boards/mimc200/fram.c b/arch/avr32/boards/mimc200/fram.c
index 54fbd95cee9b..9764a1a1073e 100644
--- a/arch/avr32/boards/mimc200/fram.c
+++ b/arch/avr32/boards/mimc200/fram.c
@@ -41,6 +41,7 @@ static int fram_mmap(struct file *filp, struct vm_area_struct *vma)
static const struct file_operations fram_fops = {
.owner = THIS_MODULE,
.mmap = fram_mmap,
+ .llseek = noop_llseek,
};
#define FRAM_MINOR 0
diff --git a/arch/avr32/include/asm/ioctls.h b/arch/avr32/include/asm/ioctls.h
index b7dd324b46a9..909cf66feaf5 100644
--- a/arch/avr32/include/asm/ioctls.h
+++ b/arch/avr32/include/asm/ioctls.h
@@ -1,90 +1,6 @@
#ifndef __ASM_AVR32_IOCTLS_H
#define __ASM_AVR32_IOCTLS_H
-#include <asm/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS 0x5401
-#define TCSETS 0x5402 /* Clashes with SNDCTL_TMR_START sound ioctl */
-#define TCSETSW 0x5403
-#define TCSETSF 0x5404
-#define TCGETA 0x5405
-#define TCSETA 0x5406
-#define TCSETAW 0x5407
-#define TCSETAF 0x5408
-#define TCSBRK 0x5409
-#define TCXONC 0x540A
-#define TCFLSH 0x540B
-#define TIOCEXCL 0x540C
-#define TIOCNXCL 0x540D
-#define TIOCSCTTY 0x540E
-#define TIOCGPGRP 0x540F
-#define TIOCSPGRP 0x5410
-#define TIOCOUTQ 0x5411
-#define TIOCSTI 0x5412
-#define TIOCGWINSZ 0x5413
-#define TIOCSWINSZ 0x5414
-#define TIOCMGET 0x5415
-#define TIOCMBIS 0x5416
-#define TIOCMBIC 0x5417
-#define TIOCMSET 0x5418
-#define TIOCGSOFTCAR 0x5419
-#define TIOCSSOFTCAR 0x541A
-#define FIONREAD 0x541B
-#define TIOCINQ FIONREAD
-#define TIOCLINUX 0x541C
-#define TIOCCONS 0x541D
-#define TIOCGSERIAL 0x541E
-#define TIOCSSERIAL 0x541F
-#define TIOCPKT 0x5420
-#define FIONBIO 0x5421
-#define TIOCNOTTY 0x5422
-#define TIOCSETD 0x5423
-#define TIOCGETD 0x5424
-#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
-/* #define TIOCTTYGSTRUCT 0x5426 - Former debugging-only ioctl */
-#define TIOCSBRK 0x5427 /* BSD compatibility */
-#define TIOCCBRK 0x5428 /* BSD compatibility */
-#define TIOCGSID 0x5429 /* Return the session ID of FD */
-#define TCGETS2 _IOR('T',0x2A, struct termios2)
-#define TCSETS2 _IOW('T',0x2B, struct termios2)
-#define TCSETSW2 _IOW('T',0x2C, struct termios2)
-#define TCSETSF2 _IOW('T',0x2D, struct termios2)
-#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
-#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
-#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */
-
-#define TIOCGRS485 0x542E
-#define TIOCSRS485 0x542F
-
-#define FIONCLEX 0x5450
-#define FIOCLEX 0x5451
-#define FIOASYNC 0x5452
-#define TIOCSERCONFIG 0x5453
-#define TIOCSERGWILD 0x5454
-#define TIOCSERSWILD 0x5455
-#define TIOCGLCKTRMIOS 0x5456
-#define TIOCSLCKTRMIOS 0x5457
-#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
-#define TIOCSERGETLSR 0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
-#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
-#define FIOQSIZE 0x5460
-
-/* Used for packet mode */
-#define TIOCPKT_DATA 0
-#define TIOCPKT_FLUSHREAD 1
-#define TIOCPKT_FLUSHWRITE 2
-#define TIOCPKT_STOP 4
-#define TIOCPKT_START 8
-#define TIOCPKT_NOSTOP 16
-#define TIOCPKT_DOSTOP 32
-#define TIOCPKT_IOCTL 64
-
-#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
+#include <asm-generic/ioctls.h>
#endif /* __ASM_AVR32_IOCTLS_H */
diff --git a/arch/avr32/include/asm/irqflags.h b/arch/avr32/include/asm/irqflags.h
index 93570daac38a..006e9487372d 100644
--- a/arch/avr32/include/asm/irqflags.h
+++ b/arch/avr32/include/asm/irqflags.h
@@ -8,16 +8,14 @@
#ifndef __ASM_AVR32_IRQFLAGS_H
#define __ASM_AVR32_IRQFLAGS_H
+#include <linux/types.h>
#include <asm/sysreg.h>
-static inline unsigned long __raw_local_save_flags(void)
+static inline unsigned long arch_local_save_flags(void)
{
return sysreg_read(SR);
}
-#define raw_local_save_flags(x) \
- do { (x) = __raw_local_save_flags(); } while (0)
-
/*
* This will restore ALL status register flags, not only the interrupt
* mask flag.
@@ -25,44 +23,39 @@ static inline unsigned long __raw_local_save_flags(void)
* The empty asm statement informs the compiler of this fact while
* also serving as a barrier.
*/
-static inline void raw_local_irq_restore(unsigned long flags)
+static inline void arch_local_irq_restore(unsigned long flags)
{
sysreg_write(SR, flags);
asm volatile("" : : : "memory", "cc");
}
-static inline void raw_local_irq_disable(void)
+static inline void arch_local_irq_disable(void)
{
asm volatile("ssrf %0" : : "n"(SYSREG_GM_OFFSET) : "memory");
}
-static inline void raw_local_irq_enable(void)
+static inline void arch_local_irq_enable(void)
{
asm volatile("csrf %0" : : "n"(SYSREG_GM_OFFSET) : "memory");
}
-static inline int raw_irqs_disabled_flags(unsigned long flags)
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
{
return (flags & SYSREG_BIT(GM)) != 0;
}
-static inline int raw_irqs_disabled(void)
+static inline bool arch_irqs_disabled(void)
{
- unsigned long flags = __raw_local_save_flags();
-
- return raw_irqs_disabled_flags(flags);
+ return arch_irqs_disabled_flags(arch_local_save_flags());
}
-static inline unsigned long __raw_local_irq_save(void)
+static inline unsigned long arch_local_irq_save(void)
{
- unsigned long flags = __raw_local_save_flags();
+ unsigned long flags = arch_local_save_flags();
- raw_local_irq_disable();
+ arch_local_irq_disable();
return flags;
}
-#define raw_local_irq_save(flags) \
- do { (flags) = __raw_local_irq_save(); } while (0)
-
#endif /* __ASM_AVR32_IRQFLAGS_H */
diff --git a/arch/avr32/kernel/module.c b/arch/avr32/kernel/module.c
index 98f94d041d9c..a727f54d64d6 100644
--- a/arch/avr32/kernel/module.c
+++ b/arch/avr32/kernel/module.c
@@ -314,10 +314,9 @@ int module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
vfree(module->arch.syminfo);
module->arch.syminfo = NULL;
- return module_bug_finalize(hdr, sechdrs, module);
+ return 0;
}
void module_arch_cleanup(struct module *module)
{
- module_bug_cleanup(module);
}
diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig
index 5a3152b75cdb..d9a1cb7ec30a 100644
--- a/arch/blackfin/Kconfig
+++ b/arch/blackfin/Kconfig
@@ -300,7 +300,7 @@ config BF_REV_0_1
config BF_REV_0_2
bool "0.2"
- depends on (BF52x || BF537 || BF536 || BF534 || (BF54x && !BF54xM))
+ depends on (BF51x || BF52x || BF537 || BF536 || BF534 || (BF54x && !BF54xM))
config BF_REV_0_3
bool "0.3"
@@ -356,7 +356,7 @@ config MEM_MT48LC8M32B2B5_7
config MEM_MT48LC32M16A2TG_75
bool
- depends on (BFIN527_EZKIT || BFIN527_EZKIT_V2 || BFIN532_IP0X || BLACKSTAMP)
+ depends on (BFIN527_EZKIT || BFIN527_EZKIT_V2 || BFIN532_IP0X || BLACKSTAMP || BFIN527_AD7160EVAL)
default y
config MEM_MT48H32M16LFCJ_75
@@ -426,6 +426,7 @@ config CLKIN_HZ
default "25000000" # most people use this
default "27000000" if BFIN533_EZKIT
default "30000000" if BFIN561_EZKIT
+ default "24000000" if BFIN527_AD7160EVAL
help
The frequency of CLKIN crystal oscillator on the board in Hz.
Warning: This value should match the crystal on the board. Otherwise,
@@ -463,6 +464,7 @@ config VCO_MULT
default "20" if (BFIN537_BLUETECHNIX_CM_E || BFIN537_BLUETECHNIX_CM_U || BFIN527_BLUETECHNIX_CM || BFIN561_BLUETECHNIX_CM)
default "20" if BFIN561_EZKIT
default "16" if (H8606_HVSISTEMAS || BLACKSTAMP || BFIN526_EZBRD || BFIN518F_EZBRD)
+ default "25" if BFIN527_AD7160EVAL
help
This controls the frequency of the on-chip PLL. This can be between 1 and 64.
PLL Frequency = (Crystal Frequency) * (this setting)
@@ -926,6 +928,12 @@ config ROMKERNEL
endchoice
+# Common code uses "ROMKERNEL" or "XIP_KERNEL", so define both
+config XIP_KERNEL
+ bool
+ default y
+ depends on ROMKERNEL
+
source "mm/Kconfig"
config BFIN_GPTIMERS
diff --git a/arch/blackfin/Makefile b/arch/blackfin/Makefile
index 3e65b0ffe084..46738d49b7c8 100644
--- a/arch/blackfin/Makefile
+++ b/arch/blackfin/Makefile
@@ -101,9 +101,8 @@ KBUILD_CFLAGS += -mcpu=$(cpu-y)-$(rev-y)
KBUILD_AFLAGS += -mcpu=$(cpu-y)-$(rev-y)
# - we utilize the silicon rev from the toolchain, so move it over to the checkflags
-# - the l1_text attribute is Blackfin specific, so fake it out as used to kill warnings
CHECKFLAGS_SILICON = $(shell echo "" | $(CPP) $(KBUILD_CFLAGS) -dD - 2>/dev/null | awk '$$2 == "__SILICON_REVISION__" { print $$3 }')
-CHECKFLAGS += -D__SILICON_REVISION__=$(CHECKFLAGS_SILICON) -Dl1_text=__used__
+CHECKFLAGS += -D__SILICON_REVISION__=$(CHECKFLAGS_SILICON) -D__bfin__
head-y := arch/$(ARCH)/kernel/init_task.o
diff --git a/arch/blackfin/configs/BF527-AD7160-EVAL_defconfig b/arch/blackfin/configs/BF527-AD7160-EVAL_defconfig
new file mode 100644
index 000000000000..08c55f6b8b7a
--- /dev/null
+++ b/arch/blackfin/configs/BF527-AD7160-EVAL_defconfig
@@ -0,0 +1,105 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_SYSVIPC=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_EMBEDDED=y
+# CONFIG_ELF_CORE is not set
+# CONFIG_AIO is not set
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_PREEMPT=y
+CONFIG_BF527=y
+CONFIG_BF_REV_0_2=y
+CONFIG_IRQ_TWI=7
+CONFIG_IRQ_PORTH_INTA=7
+CONFIG_IRQ_PORTH_INTB=7
+CONFIG_BFIN527_AD7160EVAL=y
+CONFIG_BF527_SPORT0_PORTF=y
+CONFIG_BF527_UART1_PORTG=y
+CONFIG_IRQ_USB_INT0=11
+CONFIG_IRQ_USB_INT1=11
+CONFIG_IRQ_USB_INT2=11
+CONFIG_IRQ_USB_DMA=11
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="bootargs=root=/dev/mtdblock0 rw clkin_hz=24000000 earlyprintk=serial,uart0,57600 console=tty0 console=ttyBF0,57600"
+CONFIG_CLKIN_HZ=24000000
+CONFIG_HZ_300=y
+# CONFIG_CYCLES_CLOCKSOURCE is not set
+CONFIG_IP_CHECKSUM_L1=y
+CONFIG_SYSCALL_TAB_L1=y
+CONFIG_CPLB_SWITCH_TAB_L1=y
+CONFIG_BFIN_GPTIMERS=y
+CONFIG_C_CDPRIO=y
+CONFIG_BANK_1=0x5554
+CONFIG_BANK_3=0xFFC0
+CONFIG_BINFMT_FLAT=y
+CONFIG_BINFMT_ZFLAT=y
+CONFIG_NET=y
+CONFIG_UNIX=y
+# CONFIG_WIRELESS is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+# CONFIG_MISC_DEVICES is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_AD7160=y
+CONFIG_TOUCHSCREEN_AD7160_FW=y
+# CONFIG_SERIO is not set
+# CONFIG_BFIN_DMA_INTERFACE is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_BFIN=y
+CONFIG_SERIAL_BFIN_CONSOLE=y
+CONFIG_SERIAL_BFIN_UART0=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_BFIN_OTP is not set
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+# CONFIG_I2C_HELPER_AUTO is not set
+CONFIG_I2C_ALGOBIT=y
+CONFIG_I2C_BLACKFIN_TWI=y
+CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=400
+CONFIG_SPI=y
+CONFIG_SPI_BFIN=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+# CONFIG_HWMON is not set
+CONFIG_FB=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+# CONFIG_LOGO_BLACKFIN_VGA16 is not set
+# CONFIG_HID_SUPPORT is not set
+CONFIG_USB_MUSB_HDRC=y
+CONFIG_USB_GADGET_MUSB_HDRC=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_VBUS_DRAW=500
+CONFIG_USB_G_SERIAL=y
+CONFIG_MMC=y
+CONFIG_MMC_SPI=y
+CONFIG_EXT2_FS=y
+# CONFIG_DNOTIFY is not set
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
+CONFIG_EARLY_PRINTK=y
+CONFIG_CPLB_INFO=y
+CONFIG_SECURITY=y
+CONFIG_CRC_CCITT=m
diff --git a/arch/blackfin/configs/BF527-TLL6527M_defconfig b/arch/blackfin/configs/BF527-TLL6527M_defconfig
new file mode 100644
index 000000000000..92ded5edc86c
--- /dev/null
+++ b/arch/blackfin/configs/BF527-TLL6527M_defconfig
@@ -0,0 +1,180 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCALVERSION="DEV_0-1_pre2010"
+CONFIG_SYSVIPC=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_EMBEDDED=y
+# CONFIG_SYSCTL_SYSCALL is not set
+# CONFIG_ELF_CORE is not set
+# CONFIG_FUTEX is not set
+# CONFIG_SIGNALFD is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_EVENTFD is not set
+# CONFIG_AIO is not set
+CONFIG_SLAB=y
+CONFIG_MMAP_ALLOW_UNINITIALIZED=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+CONFIG_BF527=y
+CONFIG_BF_REV_0_2=y
+CONFIG_BFIN527_TLL6527M=y
+CONFIG_BF527_UART1_PORTG=y
+CONFIG_IRQ_USB_INT0=11
+CONFIG_IRQ_USB_INT1=11
+CONFIG_IRQ_USB_INT2=11
+CONFIG_IRQ_USB_DMA=11
+CONFIG_BOOT_LOAD=0x400000
+# CONFIG_CYCLES_CLOCKSOURCE is not set
+# CONFIG_SCHEDULE_L1 is not set
+# CONFIG_MEMSET_L1 is not set
+# CONFIG_MEMCPY_L1 is not set
+# CONFIG_SYS_BFIN_SPINLOCK_L1 is not set
+CONFIG_NOMMU_INITIAL_TRIM_EXCESS=0
+CONFIG_BFIN_GPTIMERS=y
+CONFIG_DMA_UNCACHED_2M=y
+CONFIG_C_CDPRIO=y
+CONFIG_BANK_0=0xFFC2
+CONFIG_BANK_1=0xFFC2
+CONFIG_BANK_2=0xFFC2
+CONFIG_BANK_3=0xFFC2
+CONFIG_BINFMT_FLAT=y
+CONFIG_BINFMT_ZFLAT=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_IPV6 is not set
+CONFIG_IRDA=m
+CONFIG_IRLAN=m
+CONFIG_IRCOMM=m
+CONFIG_IRTTY_SIR=m
+CONFIG_BFIN_SIR=m
+CONFIG_BFIN_SIR0=y
+# CONFIG_WIRELESS is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_FW_LOADER is not set
+CONFIG_MTD=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_RAM=y
+CONFIG_MTD_ROM=y
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_GPIO_ADDR=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+CONFIG_BLK_DEV_SR=m
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_NET_ETHERNET=y
+CONFIG_BFIN_MAC=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_AD7879=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_AD714X=y
+CONFIG_INPUT_ADXL34X=y
+# CONFIG_SERIO is not set
+CONFIG_BFIN_PPI=m
+CONFIG_BFIN_SIMPLE_TIMER=m
+CONFIG_BFIN_SPORT=m
+# CONFIG_CONSOLE_TRANSLATIONS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_BFIN_JTAG_COMM=m
+CONFIG_SERIAL_BFIN=y
+CONFIG_SERIAL_BFIN_CONSOLE=y
+CONFIG_SERIAL_BFIN_UART1=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_HELPER_AUTO is not set
+CONFIG_I2C_SMBUS=y
+CONFIG_I2C_BLACKFIN_TWI=y
+CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=100
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_BFIN_WDT=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_VIDEO_DEV=y
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+CONFIG_VIDEO_BLACKFIN_CAM=m
+CONFIG_OV9655=y
+CONFIG_FB=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+CONFIG_FONT_6x11=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+# CONFIG_LOGO_BLACKFIN_VGA16 is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_SOC=y
+CONFIG_SND_BF5XX_I2S=y
+CONFIG_SND_BF5XX_SOC_SSM2602=y
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_MMC=m
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_BFIN=y
+CONFIG_EXT2_FS=y
+# CONFIG_DNOTIFY is not set
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_UDF_FS=m
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_JFFS2_FS=y
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_UTF8=m
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_SHIRQ=y
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_FTRACE is not set
+CONFIG_DEBUG_MMRS=y
+CONFIG_DEBUG_HWERR=y
+CONFIG_EXACT_HWERR=y
+CONFIG_DEBUG_DOUBLEFAULT=y
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_CPLB_INFO=y
+CONFIG_SECURITY=y
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRC7=m
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index d9eb29e2555c..9e7c5379d3ff 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -1,4 +1,5 @@
include include/asm-generic/Kbuild.asm
header-y += bfin_sport.h
+header-y += cachectl.h
header-y += fixed_code.h
diff --git a/arch/blackfin/include/asm/bfin5xx_spi.h b/arch/blackfin/include/asm/bfin5xx_spi.h
index ed4f8c6db0cd..0b5136e334b5 100644
--- a/arch/blackfin/include/asm/bfin5xx_spi.h
+++ b/arch/blackfin/include/asm/bfin5xx_spi.h
@@ -11,26 +11,17 @@
#define MIN_SPI_BAUD_VAL 2
-#define SPI_READ 0
-#define SPI_WRITE 1
-
-#define SPI_CTRL_OFF 0x0
-#define SPI_FLAG_OFF 0x4
-#define SPI_STAT_OFF 0x8
-#define SPI_TXBUFF_OFF 0xc
-#define SPI_RXBUFF_OFF 0x10
-#define SPI_BAUD_OFF 0x14
-#define SPI_SHAW_OFF 0x18
-
-
#define BIT_CTL_ENABLE 0x4000
#define BIT_CTL_OPENDRAIN 0x2000
#define BIT_CTL_MASTER 0x1000
-#define BIT_CTL_POLAR 0x0800
-#define BIT_CTL_PHASE 0x0400
-#define BIT_CTL_BITORDER 0x0200
+#define BIT_CTL_CPOL 0x0800
+#define BIT_CTL_CPHA 0x0400
+#define BIT_CTL_LSBF 0x0200
#define BIT_CTL_WORDSIZE 0x0100
-#define BIT_CTL_MISOENABLE 0x0020
+#define BIT_CTL_EMISO 0x0020
+#define BIT_CTL_PSSE 0x0010
+#define BIT_CTL_GM 0x0008
+#define BIT_CTL_SZ 0x0004
#define BIT_CTL_RXMOD 0x0000
#define BIT_CTL_TXMOD 0x0001
#define BIT_CTL_TIMOD_DMA_TX 0x0003
@@ -50,61 +41,26 @@
#define BIT_STU_SENDOVER 0x0001
#define BIT_STU_RECVFULL 0x0020
-#define CFG_SPI_ENABLE 1
-#define CFG_SPI_DISABLE 0
-
-#define CFG_SPI_OUTENABLE 1
-#define CFG_SPI_OUTDISABLE 0
-
-#define CFG_SPI_ACTLOW 1
-#define CFG_SPI_ACTHIGH 0
-
-#define CFG_SPI_PHASESTART 1
-#define CFG_SPI_PHASEMID 0
-
-#define CFG_SPI_MASTER 1
-#define CFG_SPI_SLAVE 0
-
-#define CFG_SPI_SENELAST 0
-#define CFG_SPI_SENDZERO 1
-
-#define CFG_SPI_RCVFLUSH 1
-#define CFG_SPI_RCVDISCARD 0
-
-#define CFG_SPI_LSBFIRST 1
-#define CFG_SPI_MSBFIRST 0
-
-#define CFG_SPI_WORDSIZE16 1
-#define CFG_SPI_WORDSIZE8 0
-
-#define CFG_SPI_MISOENABLE 1
-#define CFG_SPI_MISODISABLE 0
-
-#define CFG_SPI_READ 0x00
-#define CFG_SPI_WRITE 0x01
-#define CFG_SPI_DMAREAD 0x02
-#define CFG_SPI_DMAWRITE 0x03
-
-#define CFG_SPI_CSCLEARALL 0
-#define CFG_SPI_CHIPSEL1 1
-#define CFG_SPI_CHIPSEL2 2
-#define CFG_SPI_CHIPSEL3 3
-#define CFG_SPI_CHIPSEL4 4
-#define CFG_SPI_CHIPSEL5 5
-#define CFG_SPI_CHIPSEL6 6
-#define CFG_SPI_CHIPSEL7 7
+/*
+ * All Blackfin system MMRs are padded to 32bits even if the register
+ * itself is only 16bits. So use a helper macro to streamline this.
+ */
+#define __BFP(m) u16 m; u16 __pad_##m
-#define CFG_SPI_CS1VALUE 1
-#define CFG_SPI_CS2VALUE 2
-#define CFG_SPI_CS3VALUE 3
-#define CFG_SPI_CS4VALUE 4
-#define CFG_SPI_CS5VALUE 5
-#define CFG_SPI_CS6VALUE 6
-#define CFG_SPI_CS7VALUE 7
+/*
+ * bfin spi registers layout
+ */
+struct bfin_spi_regs {
+ __BFP(ctl);
+ __BFP(flg);
+ __BFP(stat);
+ __BFP(tdbr);
+ __BFP(rdbr);
+ __BFP(baud);
+ __BFP(shadow);
+};
-#define CMD_SPI_SET_BAUDRATE 2
-#define CMD_SPI_GET_SYSTEMCLOCK 25
-#define CMD_SPI_SET_WRITECONTINUOUS 26
+#define MAX_CTRL_CS 8 /* cs in spi controller */
/* device.platform_data for SSP controller devices */
struct bfin5xx_spi_master {
@@ -120,9 +76,7 @@ struct bfin5xx_spi_chip {
u16 ctl_reg;
u8 enable_dma;
u8 bits_per_word;
- u8 cs_change_per_word;
u16 cs_chg_udelay; /* Some devices require 16-bit delays */
- u32 cs_gpio;
/* Value to send if no TX value is supplied, usually 0x0 or 0xFFFF */
u16 idle_tx_val;
u8 pio_interrupt; /* Enable spi data irq */
diff --git a/arch/blackfin/include/asm/bfin_can.h b/arch/blackfin/include/asm/bfin_can.h
index eec0076a385b..b1492e0bcabb 100644
--- a/arch/blackfin/include/asm/bfin_can.h
+++ b/arch/blackfin/include/asm/bfin_can.h
@@ -34,6 +34,7 @@ struct bfin_can_mask_regs {
};
struct bfin_can_channel_regs {
+ /* data[0,2,4,6] -> data{0,1,2,3} while data[1,3,5,7] is padding */
u16 data[8];
__BFP(dlc);
__BFP(tsv);
@@ -83,16 +84,18 @@ struct bfin_can_regs {
__BFP(gif); /* offset 0x9c */
__BFP(control); /* offset 0xa0 */
__BFP(intr); /* offset 0xa4 */
- u32 __pad3[1];
+ __BFP(version); /* offset 0xa8 */
__BFP(mbtd); /* offset 0xac */
__BFP(ewr); /* offset 0xb0 */
__BFP(esr); /* offset 0xb4 */
- u32 __pad4[2];
+ u32 __pad3[2];
__BFP(ucreg); /* offset 0xc0 */
__BFP(uccnt); /* offset 0xc4 */
__BFP(ucrc); /* offset 0xc8 */
__BFP(uccnf); /* offset 0xcc */
- u32 __pad5[12];
+ u32 __pad4[1];
+ __BFP(version2); /* offset 0xd4 */
+ u32 __pad5[10];
/*
* channel(mailbox) mask and message registers
diff --git a/arch/blackfin/include/asm/bfin_ppi.h b/arch/blackfin/include/asm/bfin_ppi.h
new file mode 100644
index 000000000000..003900886f97
--- /dev/null
+++ b/arch/blackfin/include/asm/bfin_ppi.h
@@ -0,0 +1,51 @@
+/*
+ * bfin_ppi.h - interface to Blackfin PPIs
+ *
+ * Copyright 2005-2010 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef __ASM_BFIN_PPI_H__
+#define __ASM_BFIN_PPI_H__
+
+#include <linux/types.h>
+
+/*
+ * All Blackfin system MMRs are padded to 32bits even if the register
+ * itself is only 16bits. So use a helper macro to streamline this.
+ */
+#define __BFP(m) u16 m; u16 __pad_##m
+
+/*
+ * bfin ppi registers layout
+ */
+struct bfin_ppi_regs {
+ __BFP(control);
+ __BFP(status);
+ __BFP(count);
+ __BFP(delay);
+ __BFP(frame);
+};
+
+/*
+ * bfin eppi registers layout
+ */
+struct bfin_eppi_regs {
+ __BFP(status);
+ __BFP(hcount);
+ __BFP(hdelay);
+ __BFP(vcount);
+ __BFP(vdelay);
+ __BFP(frame);
+ __BFP(line);
+ __BFP(clkdiv);
+ u32 control;
+ u32 fs1w_hbl;
+ u32 fs1p_avpl;
+ u32 fs2w_lvb;
+ u32 fs2p_lavf;
+ u32 clip;
+};
+
+#endif
diff --git a/arch/blackfin/include/asm/cachectl.h b/arch/blackfin/include/asm/cachectl.h
new file mode 100644
index 000000000000..03255df6c1ea
--- /dev/null
+++ b/arch/blackfin/include/asm/cachectl.h
@@ -0,0 +1,20 @@
+/*
+ * based on the mips/cachectl.h
+ *
+ * Copyright 2010 Analog Devices Inc.
+ * Copyright (C) 1994, 1995, 1996 by Ralf Baechle
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef _ASM_CACHECTL
+#define _ASM_CACHECTL
+
+/*
+ * Options for cacheflush system call
+ */
+#define ICACHE (1<<0) /* flush instruction cache */
+#define DCACHE (1<<1) /* writeback and flush data cache */
+#define BCACHE (ICACHE|DCACHE) /* flush both caches */
+
+#endif /* _ASM_CACHECTL */
diff --git a/arch/blackfin/include/asm/cdef_LPBlackfin.h b/arch/blackfin/include/asm/cdef_LPBlackfin.h
index 6c39d94b44d0..a1f6817687e8 100644
--- a/arch/blackfin/include/asm/cdef_LPBlackfin.h
+++ b/arch/blackfin/include/asm/cdef_LPBlackfin.h
@@ -172,16 +172,19 @@
#define bfin_write_ICPLB_DATA14(val) bfin_write32(ICPLB_DATA14,val)
#define bfin_read_ICPLB_DATA15() bfin_read32(ICPLB_DATA15)
#define bfin_write_ICPLB_DATA15(val) bfin_write32(ICPLB_DATA15,val)
-#define bfin_read_ITEST_COMMAND() bfin_read32(ITEST_COMMAND)
#define bfin_write_ITEST_COMMAND(val) bfin_write32(ITEST_COMMAND,val)
#if 0
#define ITEST_INDEX 0xFFE01304 /* Instruction Test Index Register */
#endif
-#define bfin_read_ITEST_DATA0() bfin_read32(ITEST_DATA0)
#define bfin_write_ITEST_DATA0(val) bfin_write32(ITEST_DATA0,val)
-#define bfin_read_ITEST_DATA1() bfin_read32(ITEST_DATA1)
#define bfin_write_ITEST_DATA1(val) bfin_write32(ITEST_DATA1,val)
+#if ANOMALY_05000481
+#define bfin_read_ITEST_COMMAND() bfin_read32(ITEST_COMMAND)
+#define bfin_read_ITEST_DATA0() bfin_read32(ITEST_DATA0)
+#define bfin_read_ITEST_DATA1() bfin_read32(ITEST_DATA1)
+#endif
+
/* Event/Interrupt Registers*/
#define bfin_read_EVT0() bfin_read32(EVT0)
diff --git a/arch/blackfin/include/asm/ipipe.h b/arch/blackfin/include/asm/ipipe.h
index d3b40449ca0e..40f94a704c02 100644
--- a/arch/blackfin/include/asm/ipipe.h
+++ b/arch/blackfin/include/asm/ipipe.h
@@ -49,7 +49,7 @@
#define prepare_arch_switch(next) \
do { \
ipipe_schedule_notify(current, next); \
- local_irq_disable_hw(); \
+ hard_local_irq_disable(); \
} while (0)
#define task_hijacked(p) \
@@ -57,7 +57,7 @@ do { \
int __x__ = __ipipe_root_domain_p; \
__clear_bit(IPIPE_SYNC_FLAG, &ipipe_root_cpudom_var(status)); \
if (__x__) \
- local_irq_enable_hw(); \
+ hard_local_irq_enable(); \
!__x__; \
})
@@ -167,7 +167,7 @@ static inline unsigned long __ipipe_ffnz(unsigned long ul)
#define __ipipe_run_isr(ipd, irq) \
do { \
if (!__ipipe_pipeline_head_p(ipd)) \
- local_irq_enable_hw(); \
+ hard_local_irq_enable(); \
if (ipd == ipipe_root_domain) { \
if (unlikely(ipipe_virtual_irq_p(irq))) { \
irq_enter(); \
@@ -183,7 +183,7 @@ static inline unsigned long __ipipe_ffnz(unsigned long ul)
__ipipe_run_irqtail(); \
__set_bit(IPIPE_SYNC_FLAG, &ipipe_cpudom_var(ipd, status)); \
} \
- local_irq_disable_hw(); \
+ hard_local_irq_disable(); \
} while (0)
#define __ipipe_syscall_watched_p(p, sc) \
diff --git a/arch/blackfin/include/asm/irqflags.h b/arch/blackfin/include/asm/irqflags.h
index 813a1af3e865..41c4d70544ef 100644
--- a/arch/blackfin/include/asm/irqflags.h
+++ b/arch/blackfin/include/asm/irqflags.h
@@ -8,6 +8,8 @@
#ifndef __ASM_BFIN_IRQFLAGS_H__
#define __ASM_BFIN_IRQFLAGS_H__
+#include <mach/blackfin.h>
+
#ifdef CONFIG_SMP
# include <asm/pda.h>
# include <asm/processor.h>
@@ -31,54 +33,108 @@ static inline unsigned long bfin_cli(void)
return flags;
}
-#ifdef CONFIG_IPIPE
-
-#include <linux/compiler.h>
-#include <linux/ipipe_base.h>
-#include <linux/ipipe_trace.h>
-
#ifdef CONFIG_DEBUG_HWERR
# define bfin_no_irqs 0x3f
#else
# define bfin_no_irqs 0x1f
#endif
-#define raw_local_irq_disable() \
- do { \
- ipipe_check_context(ipipe_root_domain); \
- __ipipe_stall_root(); \
- barrier(); \
- } while (0)
+/*****************************************************************************/
+/*
+ * Hard, untraced CPU interrupt flag manipulation and access.
+ */
+static inline void __hard_local_irq_disable(void)
+{
+ bfin_cli();
+}
+
+static inline void __hard_local_irq_enable(void)
+{
+ bfin_sti(bfin_irq_flags);
+}
+
+static inline unsigned long hard_local_save_flags(void)
+{
+ return bfin_read_IMASK();
+}
-#define raw_local_irq_enable() \
- do { \
- barrier(); \
- ipipe_check_context(ipipe_root_domain); \
- __ipipe_unstall_root(); \
- } while (0)
+static inline unsigned long __hard_local_irq_save(void)
+{
+ unsigned long flags;
+ flags = bfin_cli();
+#ifdef CONFIG_DEBUG_HWERR
+ bfin_sti(0x3f);
+#endif
+ return flags;
+}
+
+static inline int hard_irqs_disabled_flags(unsigned long flags)
+{
+ return (flags & ~0x3f) == 0;
+}
+
+static inline int hard_irqs_disabled(void)
+{
+ unsigned long flags = hard_local_save_flags();
+ return hard_irqs_disabled_flags(flags);
+}
+
+static inline void __hard_local_irq_restore(unsigned long flags)
+{
+ if (!hard_irqs_disabled_flags(flags))
+ __hard_local_irq_enable();
+}
+
+/*****************************************************************************/
+/*
+ * Interrupt pipe handling.
+ */
+#ifdef CONFIG_IPIPE
+
+#include <linux/compiler.h>
+#include <linux/ipipe_base.h>
+#include <linux/ipipe_trace.h>
+
+/*
+ * Interrupt pipe interface to linux/irqflags.h.
+ */
+static inline void arch_local_irq_disable(void)
+{
+ ipipe_check_context(ipipe_root_domain);
+ __ipipe_stall_root();
+ barrier();
+}
-#define raw_local_save_flags_ptr(x) \
- do { \
- *(x) = __ipipe_test_root() ? bfin_no_irqs : bfin_irq_flags; \
- } while (0)
+static inline void arch_local_irq_enable(void)
+{
+ barrier();
+ ipipe_check_context(ipipe_root_domain);
+ __ipipe_unstall_root();
+}
-#define raw_local_save_flags(x) raw_local_save_flags_ptr(&(x))
+static inline unsigned long arch_local_save_flags(void)
+{
+ return __ipipe_test_root() ? bfin_no_irqs : bfin_irq_flags;
+}
-#define raw_irqs_disabled_flags(x) ((x) == bfin_no_irqs)
+static inline int arch_irqs_disabled_flags(unsigned long flags)
+{
+ return flags == bfin_no_irqs;
+}
-#define raw_local_irq_save_ptr(x) \
- do { \
- *(x) = __ipipe_test_and_stall_root() ? bfin_no_irqs : bfin_irq_flags; \
- barrier(); \
- } while (0)
+static inline void arch_local_irq_save_ptr(unsigned long *_flags)
+{
+ x = __ipipe_test_and_stall_root() ? bfin_no_irqs : bfin_irq_flags;
+ barrier();
+}
-#define raw_local_irq_save(x) \
- do { \
- ipipe_check_context(ipipe_root_domain); \
- raw_local_irq_save_ptr(&(x)); \
- } while (0)
+static inline unsigned long arch_local_irq_save(void)
+{
+ ipipe_check_context(ipipe_root_domain);
+ return __hard_local_irq_save();
+}
-static inline unsigned long raw_mangle_irq_bits(int virt, unsigned long real)
+static inline unsigned long arch_mangle_irq_bits(int virt, unsigned long real)
{
/*
* Merge virtual and real interrupt mask bits into a single
@@ -87,130 +143,79 @@ static inline unsigned long raw_mangle_irq_bits(int virt, unsigned long real)
return (real & ~(1 << 31)) | ((virt != 0) << 31);
}
-static inline int raw_demangle_irq_bits(unsigned long *x)
+static inline int arch_demangle_irq_bits(unsigned long *x)
{
int virt = (*x & (1 << 31)) != 0;
*x &= ~(1L << 31);
return virt;
}
-static inline void local_irq_disable_hw_notrace(void)
+/*
+ * Interface to various arch routines that may be traced.
+ */
+#ifdef CONFIG_IPIPE_TRACE_IRQSOFF
+static inline void hard_local_irq_disable(void)
{
- bfin_cli();
+ if (!hard_irqs_disabled()) {
+ __hard_local_irq_disable();
+ ipipe_trace_begin(0x80000000);
+ }
}
-static inline void local_irq_enable_hw_notrace(void)
+static inline void hard_local_irq_enable(void)
{
- bfin_sti(bfin_irq_flags);
+ if (hard_irqs_disabled()) {
+ ipipe_trace_end(0x80000000);
+ __hard_local_irq_enable();
+ }
}
-#define local_save_flags_hw(flags) \
- do { \
- (flags) = bfin_read_IMASK(); \
- } while (0)
-
-#define irqs_disabled_flags_hw(flags) (((flags) & ~0x3f) == 0)
-
-#define irqs_disabled_hw() \
- ({ \
- unsigned long flags; \
- local_save_flags_hw(flags); \
- irqs_disabled_flags_hw(flags); \
- })
-
-static inline void local_irq_save_ptr_hw(unsigned long *flags)
+static inline unsigned long hard_local_irq_save(void)
{
- *flags = bfin_cli();
-#ifdef CONFIG_DEBUG_HWERR
- bfin_sti(0x3f);
-#endif
+ unsigned long flags = hard_local_save_flags();
+ if (!hard_irqs_disabled_flags(flags)) {
+ __hard_local_irq_disable();
+ ipipe_trace_begin(0x80000001);
+ }
+ return flags;
}
-#define local_irq_save_hw_notrace(flags) \
- do { \
- local_irq_save_ptr_hw(&(flags)); \
- } while (0)
-
-static inline void local_irq_restore_hw_notrace(unsigned long flags)
+static inline void hard_local_irq_restore(unsigned long flags)
{
- if (!irqs_disabled_flags_hw(flags))
- local_irq_enable_hw_notrace();
+ if (!hard_irqs_disabled_flags(flags)) {
+ ipipe_trace_end(0x80000001);
+ __hard_local_irq_enable();
+ }
}
-#ifdef CONFIG_IPIPE_TRACE_IRQSOFF
-# define local_irq_disable_hw() \
- do { \
- if (!irqs_disabled_hw()) { \
- local_irq_disable_hw_notrace(); \
- ipipe_trace_begin(0x80000000); \
- } \
- } while (0)
-# define local_irq_enable_hw() \
- do { \
- if (irqs_disabled_hw()) { \
- ipipe_trace_end(0x80000000); \
- local_irq_enable_hw_notrace(); \
- } \
- } while (0)
-# define local_irq_save_hw(flags) \
- do { \
- local_save_flags_hw(flags); \
- if (!irqs_disabled_flags_hw(flags)) { \
- local_irq_disable_hw_notrace(); \
- ipipe_trace_begin(0x80000001); \
- } \
- } while (0)
-# define local_irq_restore_hw(flags) \
- do { \
- if (!irqs_disabled_flags_hw(flags)) { \
- ipipe_trace_end(0x80000001); \
- local_irq_enable_hw_notrace(); \
- } \
- } while (0)
#else /* !CONFIG_IPIPE_TRACE_IRQSOFF */
-# define local_irq_disable_hw() local_irq_disable_hw_notrace()
-# define local_irq_enable_hw() local_irq_enable_hw_notrace()
-# define local_irq_save_hw(flags) local_irq_save_hw_notrace(flags)
-# define local_irq_restore_hw(flags) local_irq_restore_hw_notrace(flags)
+# define hard_local_irq_disable() __hard_local_irq_disable()
+# define hard_local_irq_enable() __hard_local_irq_enable()
+# define hard_local_irq_save() __hard_local_irq_save()
+# define hard_local_irq_restore(flags) __hard_local_irq_restore(flags)
#endif /* !CONFIG_IPIPE_TRACE_IRQSOFF */
#else /* CONFIG_IPIPE */
-static inline void raw_local_irq_disable(void)
-{
- bfin_cli();
-}
-static inline void raw_local_irq_enable(void)
-{
- bfin_sti(bfin_irq_flags);
-}
-
-#define raw_local_save_flags(flags) do { (flags) = bfin_read_IMASK(); } while (0)
-
-#define raw_irqs_disabled_flags(flags) (((flags) & ~0x3f) == 0)
+/*
+ * Direct interface to linux/irqflags.h.
+ */
+#define arch_local_save_flags() hard_local_save_flags()
+#define arch_local_irq_save(flags) __hard_local_irq_save()
+#define arch_local_irq_restore(flags) __hard_local_irq_restore(flags)
+#define arch_local_irq_enable() __hard_local_irq_enable()
+#define arch_local_irq_disable() __hard_local_irq_disable()
+#define arch_irqs_disabled_flags(flags) hard_irqs_disabled_flags(flags)
+#define arch_irqs_disabled() hard_irqs_disabled()
-static inline unsigned long __raw_local_irq_save(void)
-{
- unsigned long flags = bfin_cli();
-#ifdef CONFIG_DEBUG_HWERR
- bfin_sti(0x3f);
-#endif
- return flags;
-}
-#define raw_local_irq_save(flags) do { (flags) = __raw_local_irq_save(); } while (0)
+/*
+ * Interface to various arch routines that may be traced.
+ */
+#define hard_local_irq_save() __hard_local_irq_save()
+#define hard_local_irq_restore(flags) __hard_local_irq_restore(flags)
+#define hard_local_irq_enable() __hard_local_irq_enable()
+#define hard_local_irq_disable() __hard_local_irq_disable()
-#define local_irq_save_hw(flags) raw_local_irq_save(flags)
-#define local_irq_restore_hw(flags) raw_local_irq_restore(flags)
-#define local_irq_enable_hw() raw_local_irq_enable()
-#define local_irq_disable_hw() raw_local_irq_disable()
-#define irqs_disabled_hw() irqs_disabled()
#endif /* !CONFIG_IPIPE */
-
-static inline void raw_local_irq_restore(unsigned long flags)
-{
- if (!raw_irqs_disabled_flags(flags))
- raw_local_irq_enable();
-}
-
#endif
diff --git a/arch/blackfin/include/asm/mmu_context.h b/arch/blackfin/include/asm/mmu_context.h
index e1a9b4624f91..3828c70e7a2e 100644
--- a/arch/blackfin/include/asm/mmu_context.h
+++ b/arch/blackfin/include/asm/mmu_context.h
@@ -97,8 +97,8 @@ static inline void __switch_mm(struct mm_struct *prev_mm, struct mm_struct *next
}
#ifdef CONFIG_IPIPE
-#define lock_mm_switch(flags) local_irq_save_hw_cond(flags)
-#define unlock_mm_switch(flags) local_irq_restore_hw_cond(flags)
+#define lock_mm_switch(flags) flags = hard_local_irq_save_cond()
+#define unlock_mm_switch(flags) hard_local_irq_restore_cond(flags)
#else
#define lock_mm_switch(flags) do { (void)(flags); } while (0)
#define unlock_mm_switch(flags) do { (void)(flags); } while (0)
@@ -205,9 +205,9 @@ static inline void destroy_context(struct mm_struct *mm)
}
#define ipipe_mm_switch_protect(flags) \
- local_irq_save_hw_cond(flags)
+ flags = hard_local_irq_save_cond()
#define ipipe_mm_switch_unprotect(flags) \
- local_irq_restore_hw_cond(flags)
+ hard_local_irq_restore_cond(flags)
#endif
diff --git a/arch/blackfin/include/asm/ptrace.h b/arch/blackfin/include/asm/ptrace.h
index aaa1c6c2bc19..832d7c009a2c 100644
--- a/arch/blackfin/include/asm/ptrace.h
+++ b/arch/blackfin/include/asm/ptrace.h
@@ -113,6 +113,9 @@ extern void user_disable_single_step(struct task_struct *child);
/* common code demands this function */
#define ptrace_disable(child) user_disable_single_step(child)
+extern int is_user_addr_valid(struct task_struct *child,
+ unsigned long start, unsigned long len);
+
/*
* Get the address of the live pt_regs for the specified task.
* These are saved onto the top kernel stack when the process
diff --git a/arch/blackfin/include/asm/serial.h b/arch/blackfin/include/asm/serial.h
index 94a4a12e3bf2..a0cb0caff152 100644
--- a/arch/blackfin/include/asm/serial.h
+++ b/arch/blackfin/include/asm/serial.h
@@ -1,2 +1 @@
#include <asm-generic/serial.h>
-#define SERIAL_EXTRA_IRQ_FLAGS IRQF_TRIGGER_HIGH
diff --git a/arch/blackfin/include/asm/system.h b/arch/blackfin/include/asm/system.h
index dde19b1d25f5..19e2c7c3e63a 100644
--- a/arch/blackfin/include/asm/system.h
+++ b/arch/blackfin/include/asm/system.h
@@ -117,7 +117,7 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
unsigned long tmp = 0;
unsigned long flags;
- local_irq_save_hw(flags);
+ flags = hard_local_irq_save();
switch (size) {
case 1:
@@ -139,7 +139,7 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
: "=&d" (tmp) : "d" (x), "m" (*__xg(ptr)) : "memory");
break;
}
- local_irq_restore_hw(flags);
+ hard_local_irq_restore(flags);
return tmp;
}
diff --git a/arch/blackfin/include/asm/unistd.h b/arch/blackfin/include/asm/unistd.h
index 14fcd254b185..928ae975b87e 100644
--- a/arch/blackfin/include/asm/unistd.h
+++ b/arch/blackfin/include/asm/unistd.h
@@ -392,8 +392,9 @@
#define __NR_fanotify_init 371
#define __NR_fanotify_mark 372
#define __NR_prlimit64 373
+#define __NR_cacheflush 374
-#define __NR_syscall 374
+#define __NR_syscall 375
#define NR_syscalls __NR_syscall
/* Old optional stuff no one actually uses */
diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c
index dc07ed08b37f..170cf90735ba 100644
--- a/arch/blackfin/kernel/bfin_gpio.c
+++ b/arch/blackfin/kernel/bfin_gpio.c
@@ -1,7 +1,7 @@
/*
* GPIO Abstraction Layer
*
- * Copyright 2006-2009 Analog Devices Inc.
+ * Copyright 2006-2010 Analog Devices Inc.
*
* Licensed under the GPL-2 or later
*/
@@ -215,82 +215,91 @@ static void port_setup(unsigned gpio, unsigned short usage)
}
#ifdef BF537_FAMILY
-static struct {
- unsigned short res;
- unsigned short offset;
-} port_mux_lut[] = {
- {.res = P_PPI0_D13, .offset = 11},
- {.res = P_PPI0_D14, .offset = 11},
- {.res = P_PPI0_D15, .offset = 11},
- {.res = P_SPORT1_TFS, .offset = 11},
- {.res = P_SPORT1_TSCLK, .offset = 11},
- {.res = P_SPORT1_DTPRI, .offset = 11},
- {.res = P_PPI0_D10, .offset = 10},
- {.res = P_PPI0_D11, .offset = 10},
- {.res = P_PPI0_D12, .offset = 10},
- {.res = P_SPORT1_RSCLK, .offset = 10},
- {.res = P_SPORT1_RFS, .offset = 10},
- {.res = P_SPORT1_DRPRI, .offset = 10},
- {.res = P_PPI0_D8, .offset = 9},
- {.res = P_PPI0_D9, .offset = 9},
- {.res = P_SPORT1_DRSEC, .offset = 9},
- {.res = P_SPORT1_DTSEC, .offset = 9},
- {.res = P_TMR2, .offset = 8},
- {.res = P_PPI0_FS3, .offset = 8},
- {.res = P_TMR3, .offset = 7},
- {.res = P_SPI0_SSEL4, .offset = 7},
- {.res = P_TMR4, .offset = 6},
- {.res = P_SPI0_SSEL5, .offset = 6},
- {.res = P_TMR5, .offset = 5},
- {.res = P_SPI0_SSEL6, .offset = 5},
- {.res = P_UART1_RX, .offset = 4},
- {.res = P_UART1_TX, .offset = 4},
- {.res = P_TMR6, .offset = 4},
- {.res = P_TMR7, .offset = 4},
- {.res = P_UART0_RX, .offset = 3},
- {.res = P_UART0_TX, .offset = 3},
- {.res = P_DMAR0, .offset = 3},
- {.res = P_DMAR1, .offset = 3},
- {.res = P_SPORT0_DTSEC, .offset = 1},
- {.res = P_SPORT0_DRSEC, .offset = 1},
- {.res = P_CAN0_RX, .offset = 1},
- {.res = P_CAN0_TX, .offset = 1},
- {.res = P_SPI0_SSEL7, .offset = 1},
- {.res = P_SPORT0_TFS, .offset = 0},
- {.res = P_SPORT0_DTPRI, .offset = 0},
- {.res = P_SPI0_SSEL2, .offset = 0},
- {.res = P_SPI0_SSEL3, .offset = 0},
+static const s8 port_mux[] = {
+ [GPIO_PF0] = 3,
+ [GPIO_PF1] = 3,
+ [GPIO_PF2] = 4,
+ [GPIO_PF3] = 4,
+ [GPIO_PF4] = 5,
+ [GPIO_PF5] = 6,
+ [GPIO_PF6] = 7,
+ [GPIO_PF7] = 8,
+ [GPIO_PF8 ... GPIO_PF15] = -1,
+ [GPIO_PG0 ... GPIO_PG7] = -1,
+ [GPIO_PG8] = 9,
+ [GPIO_PG9] = 9,
+ [GPIO_PG10] = 10,
+ [GPIO_PG11] = 10,
+ [GPIO_PG12] = 10,
+ [GPIO_PG13] = 11,
+ [GPIO_PG14] = 11,
+ [GPIO_PG15] = 11,
+ [GPIO_PH0 ... GPIO_PH15] = -1,
+ [PORT_PJ0 ... PORT_PJ3] = -1,
+ [PORT_PJ4] = 1,
+ [PORT_PJ5] = 1,
+ [PORT_PJ6 ... PORT_PJ9] = -1,
+ [PORT_PJ10] = 0,
+ [PORT_PJ11] = 0,
};
-static void portmux_setup(unsigned short per)
+static int portmux_group_check(unsigned short per)
{
- u16 y, offset, muxreg;
+ u16 ident = P_IDENT(per);
u16 function = P_FUNCT2MUX(per);
+ s8 offset = port_mux[ident];
+ u16 m, pmux, pfunc;
- for (y = 0; y < ARRAY_SIZE(port_mux_lut); y++) {
- if (port_mux_lut[y].res == per) {
-
- /* SET PORTMUX REG */
-
- offset = port_mux_lut[y].offset;
- muxreg = bfin_read_PORT_MUX();
+ if (offset < 0)
+ return 0;
- if (offset != 1)
- muxreg &= ~(1 << offset);
- else
- muxreg &= ~(3 << 1);
+ pmux = bfin_read_PORT_MUX();
+ for (m = 0; m < ARRAY_SIZE(port_mux); ++m) {
+ if (m == ident)
+ continue;
+ if (port_mux[m] != offset)
+ continue;
+ if (!is_reserved(peri, m, 1))
+ continue;
- muxreg |= (function << offset);
- bfin_write_PORT_MUX(muxreg);
+ if (offset == 1)
+ pfunc = (pmux >> offset) & 3;
+ else
+ pfunc = (pmux >> offset) & 1;
+ if (pfunc != function) {
+ pr_err("pin group conflict! request pin %d func %d conflict with pin %d func %d\n",
+ ident, function, m, pfunc);
+ return -EINVAL;
}
}
+
+ return 0;
+}
+
+static void portmux_setup(unsigned short per)
+{
+ u16 ident = P_IDENT(per);
+ u16 function = P_FUNCT2MUX(per);
+ s8 offset = port_mux[ident];
+ u16 pmux;
+
+ if (offset == -1)
+ return;
+
+ pmux = bfin_read_PORT_MUX();
+ if (offset != 1)
+ pmux &= ~(1 << offset);
+ else
+ pmux &= ~(3 << 1);
+ pmux |= (function << offset);
+ bfin_write_PORT_MUX(pmux);
}
#elif defined(CONFIG_BF54x)
inline void portmux_setup(unsigned short per)
{
- u32 pmux;
u16 ident = P_IDENT(per);
u16 function = P_FUNCT2MUX(per);
+ u32 pmux;
pmux = gpio_array[gpio_bank(ident)]->port_mux;
@@ -302,20 +311,54 @@ inline void portmux_setup(unsigned short per)
inline u16 get_portmux(unsigned short per)
{
- u32 pmux;
u16 ident = P_IDENT(per);
-
- pmux = gpio_array[gpio_bank(ident)]->port_mux;
-
+ u32 pmux = gpio_array[gpio_bank(ident)]->port_mux;
return (pmux >> (2 * gpio_sub_n(ident)) & 0x3);
}
+static int portmux_group_check(unsigned short per)
+{
+ return 0;
+}
#elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x)
+static int portmux_group_check(unsigned short per)
+{
+ u16 ident = P_IDENT(per);
+ u16 function = P_FUNCT2MUX(per);
+ u8 offset = pmux_offset[gpio_bank(ident)][gpio_sub_n(ident)];
+ u16 pin, gpiopin, pfunc;
+
+ for (pin = 0; pin < GPIO_BANKSIZE; ++pin) {
+ if (offset != pmux_offset[gpio_bank(ident)][pin])
+ continue;
+
+ gpiopin = gpio_bank(ident) * GPIO_BANKSIZE + pin;
+ if (gpiopin == ident)
+ continue;
+ if (!is_reserved(peri, gpiopin, 1))
+ continue;
+
+ pfunc = *port_mux[gpio_bank(ident)];
+ pfunc = (pfunc >> offset) & 3;
+ if (pfunc != function) {
+ pr_err("pin group conflict! request pin %d func %d conflict with pin %d func %d\n",
+ ident, function, gpiopin, pfunc);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
inline void portmux_setup(unsigned short per)
{
- u16 pmux, ident = P_IDENT(per), function = P_FUNCT2MUX(per);
+ u16 ident = P_IDENT(per);
+ u16 function = P_FUNCT2MUX(per);
u8 offset = pmux_offset[gpio_bank(ident)][gpio_sub_n(ident)];
+ u16 pmux;
pmux = *port_mux[gpio_bank(ident)];
+ if (((pmux >> offset) & 3) == function)
+ return;
pmux &= ~(3 << offset);
pmux |= (function & 3) << offset;
*port_mux[gpio_bank(ident)] = pmux;
@@ -323,6 +366,10 @@ inline void portmux_setup(unsigned short per)
}
#else
# define portmux_setup(...) do { } while (0)
+static int portmux_group_check(unsigned short per)
+{
+ return 0;
+}
#endif
#ifndef CONFIG_BF54x
@@ -349,13 +396,13 @@ inline void portmux_setup(unsigned short per)
void set_gpio_ ## name(unsigned gpio, unsigned short arg) \
{ \
unsigned long flags; \
- local_irq_save_hw(flags); \
+ flags = hard_local_irq_save(); \
if (arg) \
gpio_array[gpio_bank(gpio)]->name |= gpio_bit(gpio); \
else \
gpio_array[gpio_bank(gpio)]->name &= ~gpio_bit(gpio); \
AWA_DUMMY_READ(name); \
- local_irq_restore_hw(flags); \
+ hard_local_irq_restore(flags); \
} \
EXPORT_SYMBOL(set_gpio_ ## name);
@@ -371,14 +418,14 @@ void set_gpio_ ## name(unsigned gpio, unsigned short arg) \
{ \
unsigned long flags; \
if (ANOMALY_05000311 || ANOMALY_05000323) \
- local_irq_save_hw(flags); \
+ flags = hard_local_irq_save(); \
if (arg) \
gpio_array[gpio_bank(gpio)]->name ## _set = gpio_bit(gpio); \
else \
gpio_array[gpio_bank(gpio)]->name ## _clear = gpio_bit(gpio); \
if (ANOMALY_05000311 || ANOMALY_05000323) { \
AWA_DUMMY_READ(name); \
- local_irq_restore_hw(flags); \
+ hard_local_irq_restore(flags); \
} \
} \
EXPORT_SYMBOL(set_gpio_ ## name);
@@ -391,11 +438,11 @@ void set_gpio_toggle(unsigned gpio)
{
unsigned long flags;
if (ANOMALY_05000311 || ANOMALY_05000323)
- local_irq_save_hw(flags);
+ flags = hard_local_irq_save();
gpio_array[gpio_bank(gpio)]->toggle = gpio_bit(gpio);
if (ANOMALY_05000311 || ANOMALY_05000323) {
AWA_DUMMY_READ(toggle);
- local_irq_restore_hw(flags);
+ hard_local_irq_restore(flags);
}
}
EXPORT_SYMBOL(set_gpio_toggle);
@@ -408,11 +455,11 @@ void set_gpiop_ ## name(unsigned gpio, unsigned short arg) \
{ \
unsigned long flags; \
if (ANOMALY_05000311 || ANOMALY_05000323) \
- local_irq_save_hw(flags); \
+ flags = hard_local_irq_save(); \
gpio_array[gpio_bank(gpio)]->name = arg; \
if (ANOMALY_05000311 || ANOMALY_05000323) { \
AWA_DUMMY_READ(name); \
- local_irq_restore_hw(flags); \
+ hard_local_irq_restore(flags); \
} \
} \
EXPORT_SYMBOL(set_gpiop_ ## name);
@@ -433,11 +480,11 @@ unsigned short get_gpio_ ## name(unsigned gpio) \
unsigned long flags; \
unsigned short ret; \
if (ANOMALY_05000311 || ANOMALY_05000323) \
- local_irq_save_hw(flags); \
+ flags = hard_local_irq_save(); \
ret = 0x01 & (gpio_array[gpio_bank(gpio)]->name >> gpio_sub_n(gpio)); \
if (ANOMALY_05000311 || ANOMALY_05000323) { \
AWA_DUMMY_READ(name); \
- local_irq_restore_hw(flags); \
+ hard_local_irq_restore(flags); \
} \
return ret; \
} \
@@ -460,11 +507,11 @@ unsigned short get_gpiop_ ## name(unsigned gpio) \
unsigned long flags; \
unsigned short ret; \
if (ANOMALY_05000311 || ANOMALY_05000323) \
- local_irq_save_hw(flags); \
+ flags = hard_local_irq_save(); \
ret = (gpio_array[gpio_bank(gpio)]->name); \
if (ANOMALY_05000311 || ANOMALY_05000323) { \
AWA_DUMMY_READ(name); \
- local_irq_restore_hw(flags); \
+ hard_local_irq_restore(flags); \
} \
return ret; \
} \
@@ -525,14 +572,14 @@ int gpio_pm_wakeup_ctrl(unsigned gpio, unsigned ctrl)
if (check_gpio(gpio) < 0)
return -EINVAL;
- local_irq_save_hw(flags);
+ flags = hard_local_irq_save();
if (ctrl)
reserve(wakeup, gpio);
else
unreserve(wakeup, gpio);
set_gpio_maskb(gpio, ctrl);
- local_irq_restore_hw(flags);
+ hard_local_irq_restore(flags);
return 0;
}
@@ -690,7 +737,7 @@ int peripheral_request(unsigned short per, const char *label)
BUG_ON(ident >= MAX_RESOURCES);
- local_irq_save_hw(flags);
+ flags = hard_local_irq_save();
/* If a pin can be muxed as either GPIO or peripheral, make
* sure it is not already a GPIO pin when we request it.
@@ -701,7 +748,7 @@ int peripheral_request(unsigned short per, const char *label)
printk(KERN_ERR
"%s: Peripheral %d is already reserved as GPIO by %s !\n",
__func__, ident, get_label(ident));
- local_irq_restore_hw(flags);
+ hard_local_irq_restore(flags);
return -EBUSY;
}
@@ -730,18 +777,22 @@ int peripheral_request(unsigned short per, const char *label)
printk(KERN_ERR
"%s: Peripheral %d function %d is already reserved by %s !\n",
__func__, ident, P_FUNCT2MUX(per), get_label(ident));
- local_irq_restore_hw(flags);
+ hard_local_irq_restore(flags);
return -EBUSY;
}
}
+ if (unlikely(portmux_group_check(per))) {
+ hard_local_irq_restore(flags);
+ return -EBUSY;
+ }
anyway:
reserve(peri, ident);
portmux_setup(per);
port_setup(ident, PERIPHERAL_USAGE);
- local_irq_restore_hw(flags);
+ hard_local_irq_restore(flags);
set_label(ident, label);
return 0;
@@ -780,10 +831,10 @@ void peripheral_free(unsigned short per)
if (!(per & P_DEFINED))
return;
- local_irq_save_hw(flags);
+ flags = hard_local_irq_save();
if (unlikely(!is_reserved(peri, ident, 0))) {
- local_irq_restore_hw(flags);
+ hard_local_irq_restore(flags);
return;
}
@@ -794,7 +845,7 @@ void peripheral_free(unsigned short per)
set_label(ident, "free");
- local_irq_restore_hw(flags);
+ hard_local_irq_restore(flags);
}
EXPORT_SYMBOL(peripheral_free);
@@ -828,7 +879,7 @@ int bfin_gpio_request(unsigned gpio, const char *label)
if (check_gpio(gpio) < 0)
return -EINVAL;
- local_irq_save_hw(flags);
+ flags = hard_local_irq_save();
/*
* Allow that the identical GPIO can
@@ -837,7 +888,7 @@ int bfin_gpio_request(unsigned gpio, const char *label)
*/
if (cmp_label(gpio, label) == 0) {
- local_irq_restore_hw(flags);
+ hard_local_irq_restore(flags);
return 0;
}
@@ -846,7 +897,7 @@ int bfin_gpio_request(unsigned gpio, const char *label)
dump_stack();
printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved by %s !\n",
gpio, get_label(gpio));
- local_irq_restore_hw(flags);
+ hard_local_irq_restore(flags);
return -EBUSY;
}
if (unlikely(is_reserved(peri, gpio, 1))) {
@@ -855,7 +906,7 @@ int bfin_gpio_request(unsigned gpio, const char *label)
printk(KERN_ERR
"bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",
gpio, get_label(gpio));
- local_irq_restore_hw(flags);
+ hard_local_irq_restore(flags);
return -EBUSY;
}
if (unlikely(is_reserved(gpio_irq, gpio, 1))) {
@@ -871,7 +922,7 @@ int bfin_gpio_request(unsigned gpio, const char *label)
reserve(gpio, gpio);
set_label(gpio, label);
- local_irq_restore_hw(flags);
+ hard_local_irq_restore(flags);
port_setup(gpio, GPIO_USAGE);
@@ -888,13 +939,13 @@ void bfin_gpio_free(unsigned gpio)
might_sleep();
- local_irq_save_hw(flags);
+ flags = hard_local_irq_save();
if (unlikely(!is_reserved(gpio, gpio, 0))) {
if (system_state == SYSTEM_BOOTING)
dump_stack();
gpio_error(gpio);
- local_irq_restore_hw(flags);
+ hard_local_irq_restore(flags);
return;
}
@@ -902,7 +953,7 @@ void bfin_gpio_free(unsigned gpio)
set_label(gpio, "free");
- local_irq_restore_hw(flags);
+ hard_local_irq_restore(flags);
}
EXPORT_SYMBOL(bfin_gpio_free);
@@ -913,7 +964,7 @@ int bfin_special_gpio_request(unsigned gpio, const char *label)
{
unsigned long flags;
- local_irq_save_hw(flags);
+ flags = hard_local_irq_save();
/*
* Allow that the identical GPIO can
@@ -922,19 +973,19 @@ int bfin_special_gpio_request(unsigned gpio, const char *label)
*/
if (cmp_label(gpio, label) == 0) {
- local_irq_restore_hw(flags);
+ hard_local_irq_restore(flags);
return 0;
}
if (unlikely(is_reserved(special_gpio, gpio, 1))) {
- local_irq_restore_hw(flags);
+ hard_local_irq_restore(flags);
printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved by %s !\n",
gpio, get_label(gpio));
return -EBUSY;
}
if (unlikely(is_reserved(peri, gpio, 1))) {
- local_irq_restore_hw(flags);
+ hard_local_irq_restore(flags);
printk(KERN_ERR
"bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",
gpio, get_label(gpio));
@@ -946,7 +997,7 @@ int bfin_special_gpio_request(unsigned gpio, const char *label)
reserve(peri, gpio);
set_label(gpio, label);
- local_irq_restore_hw(flags);
+ hard_local_irq_restore(flags);
port_setup(gpio, GPIO_USAGE);
return 0;
@@ -959,18 +1010,18 @@ void bfin_special_gpio_free(unsigned gpio)
might_sleep();
- local_irq_save_hw(flags);
+ flags = hard_local_irq_save();
if (unlikely(!is_reserved(special_gpio, gpio, 0))) {
gpio_error(gpio);
- local_irq_restore_hw(flags);
+ hard_local_irq_restore(flags);
return;
}
unreserve(special_gpio, gpio);
unreserve(peri, gpio);
set_label(gpio, "free");
- local_irq_restore_hw(flags);
+ hard_local_irq_restore(flags);
}
EXPORT_SYMBOL(bfin_special_gpio_free);
#endif
@@ -983,7 +1034,7 @@ int bfin_gpio_irq_request(unsigned gpio, const char *label)
if (check_gpio(gpio) < 0)
return -EINVAL;
- local_irq_save_hw(flags);
+ flags = hard_local_irq_save();
if (unlikely(is_reserved(peri, gpio, 1))) {
if (system_state == SYSTEM_BOOTING)
@@ -991,7 +1042,7 @@ int bfin_gpio_irq_request(unsigned gpio, const char *label)
printk(KERN_ERR
"bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",
gpio, get_label(gpio));
- local_irq_restore_hw(flags);
+ hard_local_irq_restore(flags);
return -EBUSY;
}
if (unlikely(is_reserved(gpio, gpio, 1)))
@@ -1002,7 +1053,7 @@ int bfin_gpio_irq_request(unsigned gpio, const char *label)
reserve(gpio_irq, gpio);
set_label(gpio, label);
- local_irq_restore_hw(flags);
+ hard_local_irq_restore(flags);
port_setup(gpio, GPIO_USAGE);
@@ -1016,13 +1067,13 @@ void bfin_gpio_irq_free(unsigned gpio)
if (check_gpio(gpio) < 0)
return;
- local_irq_save_hw(flags);
+ flags = hard_local_irq_save();
if (unlikely(!is_reserved(gpio_irq, gpio, 0))) {
if (system_state == SYSTEM_BOOTING)
dump_stack();
gpio_error(gpio);
- local_irq_restore_hw(flags);
+ hard_local_irq_restore(flags);
return;
}
@@ -1030,7 +1081,7 @@ void bfin_gpio_irq_free(unsigned gpio)
set_label(gpio, "free");
- local_irq_restore_hw(flags);
+ hard_local_irq_restore(flags);
}
static inline void __bfin_gpio_direction_input(unsigned gpio)
@@ -1052,10 +1103,10 @@ int bfin_gpio_direction_input(unsigned gpio)
return -EINVAL;
}
- local_irq_save_hw(flags);
+ flags = hard_local_irq_save();
__bfin_gpio_direction_input(gpio);
AWA_DUMMY_READ(inen);
- local_irq_restore_hw(flags);
+ hard_local_irq_restore(flags);
return 0;
}
@@ -1070,9 +1121,9 @@ void bfin_gpio_irq_prepare(unsigned gpio)
port_setup(gpio, GPIO_USAGE);
#ifdef CONFIG_BF54x
- local_irq_save_hw(flags);
+ flags = hard_local_irq_save();
__bfin_gpio_direction_input(gpio);
- local_irq_restore_hw(flags);
+ hard_local_irq_restore(flags);
#endif
}
@@ -1094,7 +1145,7 @@ int bfin_gpio_direction_output(unsigned gpio, int value)
return -EINVAL;
}
- local_irq_save_hw(flags);
+ flags = hard_local_irq_save();
gpio_array[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio);
gpio_set_value(gpio, value);
@@ -1105,7 +1156,7 @@ int bfin_gpio_direction_output(unsigned gpio, int value)
#endif
AWA_DUMMY_READ(dir);
- local_irq_restore_hw(flags);
+ hard_local_irq_restore(flags);
return 0;
}
@@ -1120,11 +1171,11 @@ int bfin_gpio_get_value(unsigned gpio)
if (unlikely(get_gpio_edge(gpio))) {
int ret;
- local_irq_save_hw(flags);
+ flags = hard_local_irq_save();
set_gpio_edge(gpio, 0);
ret = get_gpio_data(gpio);
set_gpio_edge(gpio, 1);
- local_irq_restore_hw(flags);
+ hard_local_irq_restore(flags);
return ret;
} else
return get_gpio_data(gpio);
diff --git a/arch/blackfin/kernel/cplb-mpu/cplbmgr.c b/arch/blackfin/kernel/cplb-mpu/cplbmgr.c
index 87b25b1b30ed..8de92299b3ee 100644
--- a/arch/blackfin/kernel/cplb-mpu/cplbmgr.c
+++ b/arch/blackfin/kernel/cplb-mpu/cplbmgr.c
@@ -318,7 +318,7 @@ void flush_switched_cplbs(unsigned int cpu)
nr_cplb_flush[cpu]++;
- local_irq_save_hw(flags);
+ flags = hard_local_irq_save();
_disable_icplb();
for (i = first_switched_icplb; i < MAX_CPLBS; i++) {
icplb_tbl[cpu][i].data = 0;
@@ -332,7 +332,7 @@ void flush_switched_cplbs(unsigned int cpu)
bfin_write32(DCPLB_DATA0 + i * 4, 0);
}
_enable_dcplb();
- local_irq_restore_hw(flags);
+ hard_local_irq_restore(flags);
}
@@ -348,7 +348,7 @@ void set_mask_dcplbs(unsigned long *masks, unsigned int cpu)
return;
}
- local_irq_save_hw(flags);
+ flags = hard_local_irq_save();
current_rwx_mask[cpu] = masks;
if (L2_LENGTH && addr >= L2_START && addr < L2_START + L2_LENGTH) {
@@ -373,5 +373,5 @@ void set_mask_dcplbs(unsigned long *masks, unsigned int cpu)
addr += PAGE_SIZE;
}
_enable_dcplb();
- local_irq_restore_hw(flags);
+ hard_local_irq_restore(flags);
}
diff --git a/arch/blackfin/kernel/ipipe.c b/arch/blackfin/kernel/ipipe.c
index 1a496cd71ba2..3b1da4aff2a1 100644
--- a/arch/blackfin/kernel/ipipe.c
+++ b/arch/blackfin/kernel/ipipe.c
@@ -219,10 +219,10 @@ int __ipipe_syscall_root(struct pt_regs *regs)
ret = __ipipe_dispatch_event(IPIPE_EVENT_SYSCALL, regs);
- local_irq_save_hw(flags);
+ flags = hard_local_irq_save();
if (!__ipipe_root_domain_p) {
- local_irq_restore_hw(flags);
+ hard_local_irq_restore(flags);
return 1;
}
@@ -230,7 +230,7 @@ int __ipipe_syscall_root(struct pt_regs *regs)
if ((p->irqpend_himask & IPIPE_IRQMASK_VIRT) != 0)
__ipipe_sync_pipeline(IPIPE_IRQMASK_VIRT);
- local_irq_restore_hw(flags);
+ hard_local_irq_restore(flags);
return -ret;
}
@@ -239,14 +239,14 @@ unsigned long ipipe_critical_enter(void (*syncfn) (void))
{
unsigned long flags;
- local_irq_save_hw(flags);
+ flags = hard_local_irq_save();
return flags;
}
void ipipe_critical_exit(unsigned long flags)
{
- local_irq_restore_hw(flags);
+ hard_local_irq_restore(flags);
}
static void __ipipe_no_irqtail(void)
@@ -279,9 +279,9 @@ int ipipe_trigger_irq(unsigned irq)
return -EINVAL;
#endif
- local_irq_save_hw(flags);
+ flags = hard_local_irq_save();
__ipipe_handle_irq(irq, NULL);
- local_irq_restore_hw(flags);
+ hard_local_irq_restore(flags);
return 1;
}
@@ -293,7 +293,7 @@ asmlinkage void __ipipe_sync_root(void)
BUG_ON(irqs_disabled());
- local_irq_save_hw(flags);
+ flags = hard_local_irq_save();
if (irq_tail_hook)
irq_tail_hook();
@@ -303,7 +303,7 @@ asmlinkage void __ipipe_sync_root(void)
if (ipipe_root_cpudom_var(irqpend_himask) != 0)
__ipipe_sync_pipeline(IPIPE_IRQMASK_ANY);
- local_irq_restore_hw(flags);
+ hard_local_irq_restore(flags);
}
void ___ipipe_sync_pipeline(unsigned long syncmask)
@@ -344,10 +344,10 @@ void __ipipe_stall_root(void)
{
unsigned long *p, flags;
- local_irq_save_hw(flags);
+ flags = hard_local_irq_save();
p = &__ipipe_root_status;
__set_bit(IPIPE_STALL_FLAG, p);
- local_irq_restore_hw(flags);
+ hard_local_irq_restore(flags);
}
EXPORT_SYMBOL(__ipipe_stall_root);
@@ -356,10 +356,10 @@ unsigned long __ipipe_test_and_stall_root(void)
unsigned long *p, flags;
int x;
- local_irq_save_hw(flags);
+ flags = hard_local_irq_save();
p = &__ipipe_root_status;
x = __test_and_set_bit(IPIPE_STALL_FLAG, p);
- local_irq_restore_hw(flags);
+ hard_local_irq_restore(flags);
return x;
}
@@ -371,10 +371,10 @@ unsigned long __ipipe_test_root(void)
unsigned long flags;
int x;
- local_irq_save_hw_smp(flags);
+ flags = hard_local_irq_save_smp();
p = &__ipipe_root_status;
x = test_bit(IPIPE_STALL_FLAG, p);
- local_irq_restore_hw_smp(flags);
+ hard_local_irq_restore_smp(flags);
return x;
}
@@ -384,10 +384,10 @@ void __ipipe_lock_root(void)
{
unsigned long *p, flags;
- local_irq_save_hw(flags);
+ flags = hard_local_irq_save();
p = &__ipipe_root_status;
__set_bit(IPIPE_SYNCDEFER_FLAG, p);
- local_irq_restore_hw(flags);
+ hard_local_irq_restore(flags);
}
EXPORT_SYMBOL(__ipipe_lock_root);
@@ -395,9 +395,9 @@ void __ipipe_unlock_root(void)
{
unsigned long *p, flags;
- local_irq_save_hw(flags);
+ flags = hard_local_irq_save();
p = &__ipipe_root_status;
__clear_bit(IPIPE_SYNCDEFER_FLAG, p);
- local_irq_restore_hw(flags);
+ hard_local_irq_restore(flags);
}
EXPORT_SYMBOL(__ipipe_unlock_root);
diff --git a/arch/blackfin/kernel/kgdb_test.c b/arch/blackfin/kernel/kgdb_test.c
index 9a4b07594389..08c0236acf3c 100644
--- a/arch/blackfin/kernel/kgdb_test.c
+++ b/arch/blackfin/kernel/kgdb_test.c
@@ -88,6 +88,7 @@ static const struct file_operations kgdb_test_proc_fops = {
.owner = THIS_MODULE,
.read = kgdb_test_proc_read,
.write = kgdb_test_proc_write,
+ .llseek = noop_llseek,
};
static int __init kgdbtest_init(void)
diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c
index 01f98cb964d2..cd0c090ebc54 100644
--- a/arch/blackfin/kernel/process.c
+++ b/arch/blackfin/kernel/process.c
@@ -65,11 +65,11 @@ static void default_idle(void)
#ifdef CONFIG_IPIPE
ipipe_suspend_domain();
#endif
- local_irq_disable_hw();
+ hard_local_irq_disable();
if (!need_resched())
idle_with_irq_disabled();
- local_irq_enable_hw();
+ hard_local_irq_enable();
}
/*
@@ -493,6 +493,11 @@ int _access_ok(unsigned long addr, unsigned long size)
return 1;
#endif
+#ifndef CONFIG_EXCEPTION_L1_SCRATCH
+ if (in_mem_const(addr, size, (unsigned long)l1_stack_base, l1_stack_len))
+ return 1;
+#endif
+
aret = in_async(addr, size);
if (aret < 2)
return aret;
diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c
index 6ec77685df52..b35839354130 100644
--- a/arch/blackfin/kernel/ptrace.c
+++ b/arch/blackfin/kernel/ptrace.c
@@ -27,6 +27,7 @@
#include <asm/fixed_code.h>
#include <asm/cacheflush.h>
#include <asm/mem_map.h>
+#include <asm/mmu_context.h>
/*
* does not yet catch signals sent when the child dies.
@@ -113,8 +114,8 @@ put_reg(struct task_struct *task, long regno, unsigned long data)
/*
* check that an address falls within the bounds of the target process's memory mappings
*/
-static inline int is_user_addr_valid(struct task_struct *child,
- unsigned long start, unsigned long len)
+int
+is_user_addr_valid(struct task_struct *child, unsigned long start, unsigned long len)
{
struct vm_area_struct *vma;
struct sram_list_struct *sraml;
@@ -135,6 +136,13 @@ static inline int is_user_addr_valid(struct task_struct *child,
if (start >= FIXED_CODE_START && start + len < FIXED_CODE_END)
return 0;
+#ifdef CONFIG_APP_STACK_L1
+ if (child->mm->context.l1_stack_save)
+ if (start >= (unsigned long)l1_stack_base &&
+ start + len < (unsigned long)l1_stack_base + l1_stack_len)
+ return 0;
+#endif
+
return -EIO;
}
diff --git a/arch/blackfin/kernel/sys_bfin.c b/arch/blackfin/kernel/sys_bfin.c
index bdc1e2f0da32..89448ed7065d 100644
--- a/arch/blackfin/kernel/sys_bfin.c
+++ b/arch/blackfin/kernel/sys_bfin.c
@@ -21,6 +21,8 @@
#include <asm/cacheflush.h>
#include <asm/dma.h>
+#include <asm/cachectl.h>
+#include <asm/ptrace.h>
asmlinkage void *sys_sram_alloc(size_t size, unsigned long flags)
{
@@ -70,3 +72,16 @@ asmlinkage int sys_bfin_spinlock(int *p)
return ret;
}
+
+SYSCALL_DEFINE3(cacheflush, unsigned long, addr, unsigned long, len, int, op)
+{
+ if (is_user_addr_valid(current, addr, len) != 0)
+ return -EINVAL;
+
+ if (op & DCACHE)
+ blackfin_dcache_flush_range(addr, addr + len);
+ if (op & ICACHE)
+ blackfin_icache_flush_range(addr, addr + len);
+
+ return 0;
+}
diff --git a/arch/blackfin/kernel/trace.c b/arch/blackfin/kernel/trace.c
index 59fcdf6b0138..05b550891ce5 100644
--- a/arch/blackfin/kernel/trace.c
+++ b/arch/blackfin/kernel/trace.c
@@ -15,6 +15,7 @@
#include <linux/kallsyms.h>
#include <linux/err.h>
#include <linux/fs.h>
+#include <linux/irq.h>
#include <asm/dma.h>
#include <asm/trace.h>
#include <asm/fixed_code.h>
diff --git a/arch/blackfin/mach-bf518/boards/ezbrd.c b/arch/blackfin/mach-bf518/boards/ezbrd.c
index 44d6d5299022..f95e6096719b 100644
--- a/arch/blackfin/mach-bf518/boards/ezbrd.c
+++ b/arch/blackfin/mach-bf518/boards/ezbrd.c
@@ -312,7 +312,7 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
/* SPI (0) */
static struct bfin5xx_spi_master bfin_spi0_info = {
- .num_chipselect = 5,
+ .num_chipselect = 6,
.enable_dma = 1, /* master has the ability to do dma transfer */
.pin_req = {P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0},
};
@@ -347,7 +347,7 @@ static struct platform_device bfin_spi0_device = {
/* SPI (1) */
static struct bfin5xx_spi_master bfin_spi1_info = {
- .num_chipselect = 5,
+ .num_chipselect = 6,
.enable_dma = 1, /* master has the ability to do dma transfer */
.pin_req = {P_SPI1_SCK, P_SPI1_MISO, P_SPI1_MOSI, 0},
};
@@ -525,6 +525,14 @@ static struct platform_device bfin_sir1_device = {
#endif
#endif
+#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE)
+static struct platform_device bfin_i2s = {
+ .name = "bfin-i2s",
+ .id = CONFIG_SND_BF5XX_SPORT_NUM,
+ /* TODO: add platform data here */
+};
+#endif
+
#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
static struct resource bfin_twi0_resource[] = {
[0] = {
@@ -559,6 +567,11 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
.irq = IRQ_PF8,
},
#endif
+#if defined(CONFIG_SND_SOC_SSM2602) || defined(CONFIG_SND_SOC_SSM2602_MODULE)
+ {
+ I2C_BOARD_INFO("ssm2602", 0x1b),
+ },
+#endif
};
#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
@@ -736,6 +749,10 @@ static struct platform_device *stamp_devices[] __initdata = {
&i2c_bfin_twi_device,
#endif
+#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE)
+ &bfin_i2s,
+#endif
+
#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
#ifdef CONFIG_SERIAL_BFIN_SPORT0_UART
&bfin_sport0_uart_device,
diff --git a/arch/blackfin/mach-bf518/boards/tcm-bf518.c b/arch/blackfin/mach-bf518/boards/tcm-bf518.c
index 9b72e5cb21fe..bead810a6546 100644
--- a/arch/blackfin/mach-bf518/boards/tcm-bf518.c
+++ b/arch/blackfin/mach-bf518/boards/tcm-bf518.c
@@ -291,7 +291,7 @@ static struct platform_device bfin_spi0_device = {
/* SPI (1) */
static struct bfin5xx_spi_master bfin_spi1_info = {
- .num_chipselect = 5,
+ .num_chipselect = 6,
.enable_dma = 1, /* master has the ability to do dma transfer */
.pin_req = {P_SPI1_SCK, P_SPI1_MISO, P_SPI1_MOSI, 0},
};
diff --git a/arch/blackfin/mach-bf518/include/mach/cdefBF51x_base.h b/arch/blackfin/mach-bf518/include/mach/cdefBF51x_base.h
index e548e9d1d6fa..e16969f24ffd 100644
--- a/arch/blackfin/mach-bf518/include/mach/cdefBF51x_base.h
+++ b/arch/blackfin/mach-bf518/include/mach/cdefBF51x_base.h
@@ -262,14 +262,14 @@
#define bfin_write_SPORT0_TX(val) bfin_write32(SPORT0_TX, val)
#define bfin_read_SPORT0_RX() bfin_read32(SPORT0_RX)
#define bfin_write_SPORT0_RX(val) bfin_write32(SPORT0_RX, val)
-#define bfin_read_SPORT0_TX32() bfin_read32(SPORT0_TX32)
-#define bfin_write_SPORT0_TX32(val) bfin_write32(SPORT0_TX32, val)
-#define bfin_read_SPORT0_RX32() bfin_read32(SPORT0_RX32)
-#define bfin_write_SPORT0_RX32(val) bfin_write32(SPORT0_RX32, val)
-#define bfin_read_SPORT0_TX16() bfin_read16(SPORT0_TX16)
-#define bfin_write_SPORT0_TX16(val) bfin_write16(SPORT0_TX16, val)
-#define bfin_read_SPORT0_RX16() bfin_read16(SPORT0_RX16)
-#define bfin_write_SPORT0_RX16(val) bfin_write16(SPORT0_RX16, val)
+#define bfin_read_SPORT0_TX32() bfin_read32(SPORT0_TX)
+#define bfin_write_SPORT0_TX32(val) bfin_write32(SPORT0_TX, val)
+#define bfin_read_SPORT0_RX32() bfin_read32(SPORT0_RX)
+#define bfin_write_SPORT0_RX32(val) bfin_write32(SPORT0_RX, val)
+#define bfin_read_SPORT0_TX16() bfin_read16(SPORT0_TX)
+#define bfin_write_SPORT0_TX16(val) bfin_write16(SPORT0_TX, val)
+#define bfin_read_SPORT0_RX16() bfin_read16(SPORT0_RX)
+#define bfin_write_SPORT0_RX16(val) bfin_write16(SPORT0_RX, val)
#define bfin_read_SPORT0_RCR1() bfin_read16(SPORT0_RCR1)
#define bfin_write_SPORT0_RCR1(val) bfin_write16(SPORT0_RCR1, val)
#define bfin_read_SPORT0_RCR2() bfin_read16(SPORT0_RCR2)
@@ -317,14 +317,14 @@
#define bfin_write_SPORT1_TX(val) bfin_write32(SPORT1_TX, val)
#define bfin_read_SPORT1_RX() bfin_read32(SPORT1_RX)
#define bfin_write_SPORT1_RX(val) bfin_write32(SPORT1_RX, val)
-#define bfin_read_SPORT1_TX32() bfin_read32(SPORT1_TX32)
-#define bfin_write_SPORT1_TX32(val) bfin_write32(SPORT1_TX32, val)
-#define bfin_read_SPORT1_RX32() bfin_read32(SPORT1_RX32)
-#define bfin_write_SPORT1_RX32(val) bfin_write32(SPORT1_RX32, val)
-#define bfin_read_SPORT1_TX16() bfin_read16(SPORT1_TX16)
-#define bfin_write_SPORT1_TX16(val) bfin_write16(SPORT1_TX16, val)
-#define bfin_read_SPORT1_RX16() bfin_read16(SPORT1_RX16)
-#define bfin_write_SPORT1_RX16(val) bfin_write16(SPORT1_RX16, val)
+#define bfin_read_SPORT1_TX32() bfin_read32(SPORT1_TX)
+#define bfin_write_SPORT1_TX32(val) bfin_write32(SPORT1_TX, val)
+#define bfin_read_SPORT1_RX32() bfin_read32(SPORT1_RX)
+#define bfin_write_SPORT1_RX32(val) bfin_write32(SPORT1_RX, val)
+#define bfin_read_SPORT1_TX16() bfin_read16(SPORT1_TX)
+#define bfin_write_SPORT1_TX16(val) bfin_write16(SPORT1_TX, val)
+#define bfin_read_SPORT1_RX16() bfin_read16(SPORT1_RX)
+#define bfin_write_SPORT1_RX16(val) bfin_write16(SPORT1_RX, val)
#define bfin_read_SPORT1_RCR1() bfin_read16(SPORT1_RCR1)
#define bfin_write_SPORT1_RCR1(val) bfin_write16(SPORT1_RCR1, val)
#define bfin_read_SPORT1_RCR2() bfin_read16(SPORT1_RCR2)
@@ -1058,54 +1058,4 @@
/* These need to be last due to the cdef/linux inter-dependencies */
#include <asm/irq.h>
-/* Writing to PLL_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_PLL_CTL(unsigned int val)
-{
- unsigned long flags, iwr0, iwr1;
-
- if (val == bfin_read_PLL_CTL())
- return;
-
- local_irq_save_hw(flags);
- /* Enable the PLL Wakeup bit in SIC IWR */
- iwr0 = bfin_read32(SIC_IWR0);
- iwr1 = bfin_read32(SIC_IWR1);
- /* Only allow PPL Wakeup) */
- bfin_write32(SIC_IWR0, IWR_ENABLE(0));
- bfin_write32(SIC_IWR1, 0);
-
- bfin_write16(PLL_CTL, val);
- SSYNC();
- asm("IDLE;");
-
- bfin_write32(SIC_IWR0, iwr0);
- bfin_write32(SIC_IWR1, iwr1);
- local_irq_restore_hw(flags);
-}
-
-/* Writing to VR_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_VR_CTL(unsigned int val)
-{
- unsigned long flags, iwr0, iwr1;
-
- if (val == bfin_read_VR_CTL())
- return;
-
- local_irq_save_hw(flags);
- /* Enable the PLL Wakeup bit in SIC IWR */
- iwr0 = bfin_read32(SIC_IWR0);
- iwr1 = bfin_read32(SIC_IWR1);
- /* Only allow PPL Wakeup) */
- bfin_write32(SIC_IWR0, IWR_ENABLE(0));
- bfin_write32(SIC_IWR1, 0);
-
- bfin_write16(VR_CTL, val);
- SSYNC();
- asm("IDLE;");
-
- bfin_write32(SIC_IWR0, iwr0);
- bfin_write32(SIC_IWR1, iwr1);
- local_irq_restore_hw(flags);
-}
-
#endif /* _CDEF_BF52X_H */
diff --git a/arch/blackfin/mach-bf518/include/mach/defBF51x_base.h b/arch/blackfin/mach-bf518/include/mach/defBF51x_base.h
index 037a51fd8e93..5f84913dcd91 100644
--- a/arch/blackfin/mach-bf518/include/mach/defBF51x_base.h
+++ b/arch/blackfin/mach-bf518/include/mach/defBF51x_base.h
@@ -748,51 +748,6 @@
#define FFE 0x20 /* Force Framing Error On Transmit */
-/* *********** SERIAL PERIPHERAL INTERFACE (SPI) MASKS ****************************/
-/* SPI_CTL Masks */
-#define TIMOD 0x0003 /* Transfer Initiate Mode */
-#define RDBR_CORE 0x0000 /* RDBR Read Initiates, IRQ When RDBR Full */
-#define TDBR_CORE 0x0001 /* TDBR Write Initiates, IRQ When TDBR Empty */
-#define RDBR_DMA 0x0002 /* DMA Read, DMA Until FIFO Empty */
-#define TDBR_DMA 0x0003 /* DMA Write, DMA Until FIFO Full */
-#define SZ 0x0004 /* Send Zero (When TDBR Empty, Send Zero/Last*) */
-#define GM 0x0008 /* Get More (When RDBR Full, Overwrite/Discard*) */
-#define PSSE 0x0010 /* Slave-Select Input Enable */
-#define EMISO 0x0020 /* Enable MISO As Output */
-#define SIZE 0x0100 /* Size of Words (16/8* Bits) */
-#define LSBF 0x0200 /* LSB First */
-#define CPHA 0x0400 /* Clock Phase */
-#define CPOL 0x0800 /* Clock Polarity */
-#define MSTR 0x1000 /* Master/Slave* */
-#define WOM 0x2000 /* Write Open Drain Master */
-#define SPE 0x4000 /* SPI Enable */
-
-/* SPI_FLG Masks */
-#define FLS1 0x0002 /* Enables SPI_FLOUT1 as SPI Slave-Select Output */
-#define FLS2 0x0004 /* Enables SPI_FLOUT2 as SPI Slave-Select Output */
-#define FLS3 0x0008 /* Enables SPI_FLOUT3 as SPI Slave-Select Output */
-#define FLS4 0x0010 /* Enables SPI_FLOUT4 as SPI Slave-Select Output */
-#define FLS5 0x0020 /* Enables SPI_FLOUT5 as SPI Slave-Select Output */
-#define FLS6 0x0040 /* Enables SPI_FLOUT6 as SPI Slave-Select Output */
-#define FLS7 0x0080 /* Enables SPI_FLOUT7 as SPI Slave-Select Output */
-#define FLG1 0xFDFF /* Activates SPI_FLOUT1 */
-#define FLG2 0xFBFF /* Activates SPI_FLOUT2 */
-#define FLG3 0xF7FF /* Activates SPI_FLOUT3 */
-#define FLG4 0xEFFF /* Activates SPI_FLOUT4 */
-#define FLG5 0xDFFF /* Activates SPI_FLOUT5 */
-#define FLG6 0xBFFF /* Activates SPI_FLOUT6 */
-#define FLG7 0x7FFF /* Activates SPI_FLOUT7 */
-
-/* SPI_STAT Masks */
-#define SPIF 0x0001 /* SPI Finished (Single-Word Transfer Complete) */
-#define MODF 0x0002 /* Mode Fault Error (Another Device Tried To Become Master) */
-#define TXE 0x0004 /* Transmission Error (Data Sent With No New Data In TDBR) */
-#define TXS 0x0008 /* SPI_TDBR Data Buffer Status (Full/Empty*) */
-#define RBSY 0x0010 /* Receive Error (Data Received With RDBR Full) */
-#define RXS 0x0020 /* SPI_RDBR Data Buffer Status (Full/Empty*) */
-#define TXCOL 0x0040 /* Transmit Collision Error (Corrupt Data May Have Been Sent) */
-
-
/* **************** GENERAL PURPOSE TIMER MASKS **********************/
/* TIMER_ENABLE Masks */
#define TIMEN0 0x0001 /* Enable Timer 0 */
diff --git a/arch/blackfin/mach-bf518/include/mach/pll.h b/arch/blackfin/mach-bf518/include/mach/pll.h
new file mode 100644
index 000000000000..d5502988896b
--- /dev/null
+++ b/arch/blackfin/mach-bf518/include/mach/pll.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later
+ */
+
+#ifndef _MACH_PLL_H
+#define _MACH_PLL_H
+
+#include <asm/blackfin.h>
+#include <asm/irqflags.h>
+
+/* Writing to PLL_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_PLL_CTL(unsigned int val)
+{
+ unsigned long flags, iwr0, iwr1;
+
+ if (val == bfin_read_PLL_CTL())
+ return;
+
+ flags = hard_local_irq_save();
+ /* Enable the PLL Wakeup bit in SIC IWR */
+ iwr0 = bfin_read32(SIC_IWR0);
+ iwr1 = bfin_read32(SIC_IWR1);
+ /* Only allow PPL Wakeup) */
+ bfin_write32(SIC_IWR0, IWR_ENABLE(0));
+ bfin_write32(SIC_IWR1, 0);
+
+ bfin_write16(PLL_CTL, val);
+ SSYNC();
+ asm("IDLE;");
+
+ bfin_write32(SIC_IWR0, iwr0);
+ bfin_write32(SIC_IWR1, iwr1);
+ hard_local_irq_restore(flags);
+}
+
+/* Writing to VR_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_VR_CTL(unsigned int val)
+{
+ unsigned long flags, iwr0, iwr1;
+
+ if (val == bfin_read_VR_CTL())
+ return;
+
+ flags = hard_local_irq_save();
+ /* Enable the PLL Wakeup bit in SIC IWR */
+ iwr0 = bfin_read32(SIC_IWR0);
+ iwr1 = bfin_read32(SIC_IWR1);
+ /* Only allow PPL Wakeup) */
+ bfin_write32(SIC_IWR0, IWR_ENABLE(0));
+ bfin_write32(SIC_IWR1, 0);
+
+ bfin_write16(VR_CTL, val);
+ SSYNC();
+ asm("IDLE;");
+
+ bfin_write32(SIC_IWR0, iwr0);
+ bfin_write32(SIC_IWR1, iwr1);
+ hard_local_irq_restore(flags);
+}
+
+#endif /* _MACH_PLL_H */
diff --git a/arch/blackfin/mach-bf527/boards/Kconfig b/arch/blackfin/mach-bf527/boards/Kconfig
index b14c28810a44..1cc2667c10f1 100644
--- a/arch/blackfin/mach-bf527/boards/Kconfig
+++ b/arch/blackfin/mach-bf527/boards/Kconfig
@@ -24,4 +24,14 @@ config BFIN526_EZBRD
help
BF526-EZBRD/EZKIT Lite board support.
+config BFIN527_AD7160EVAL
+ bool "BF527-AD7160-EVAL"
+ help
+ BF527-AD7160-EVAL board support.
+
+config BFIN527_TLL6527M
+ bool "The Learning Labs TLL6527M"
+ help
+ TLL6527M V1.0 platform support
+
endchoice
diff --git a/arch/blackfin/mach-bf527/boards/Makefile b/arch/blackfin/mach-bf527/boards/Makefile
index 51a5817c4a90..1d67da9f05ac 100644
--- a/arch/blackfin/mach-bf527/boards/Makefile
+++ b/arch/blackfin/mach-bf527/boards/Makefile
@@ -6,3 +6,5 @@ obj-$(CONFIG_BFIN527_EZKIT) += ezkit.o
obj-$(CONFIG_BFIN527_EZKIT_V2) += ezkit.o
obj-$(CONFIG_BFIN527_BLUETECHNIX_CM) += cm_bf527.o
obj-$(CONFIG_BFIN526_EZBRD) += ezbrd.o
+obj-$(CONFIG_BFIN527_AD7160EVAL) += ad7160eval.o
+obj-$(CONFIG_BFIN527_TLL6527M) += tll6527m.o
diff --git a/arch/blackfin/mach-bf527/boards/ad7160eval.c b/arch/blackfin/mach-bf527/boards/ad7160eval.c
new file mode 100644
index 000000000000..fc767ac76381
--- /dev/null
+++ b/arch/blackfin/mach-bf527/boards/ad7160eval.c
@@ -0,0 +1,870 @@
+/*
+ * Copyright 2004-20010 Analog Devices Inc.
+ * 2005 National ICT Australia (NICTA)
+ * Aidan Williams <aidan@nicta.com.au>
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#include <linux/i2c.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/usb/musb.h>
+#include <linux/leds.h>
+#include <linux/input.h>
+#include <asm/dma.h>
+#include <asm/bfin5xx_spi.h>
+#include <asm/reboot.h>
+#include <asm/nand.h>
+#include <asm/portmux.h>
+#include <asm/dpmc.h>
+
+
+/*
+ * Name the Board for the /proc/cpuinfo
+ */
+const char bfin_board_name[] = "ADI BF527-AD7160EVAL";
+
+/*
+ * Driver needs to know address, irq and flag pin.
+ */
+
+#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE)
+static struct resource musb_resources[] = {
+ [0] = {
+ .start = 0xffc03800,
+ .end = 0xffc03cff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = { /* general IRQ */
+ .start = IRQ_USB_INT0,
+ .end = IRQ_USB_INT0,
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+ },
+ [2] = { /* DMA IRQ */
+ .start = IRQ_USB_DMA,
+ .end = IRQ_USB_DMA,
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+ },
+};
+
+static struct musb_hdrc_config musb_config = {
+ .multipoint = 0,
+ .dyn_fifo = 0,
+ .soft_con = 1,
+ .dma = 1,
+ .num_eps = 8,
+ .dma_channels = 8,
+ .gpio_vrsel = GPIO_PG13,
+ /* Some custom boards need to be active low, just set it to "0"
+ * if it is the case.
+ */
+ .gpio_vrsel_active = 1,
+};
+
+static struct musb_hdrc_platform_data musb_plat = {
+#if defined(CONFIG_USB_MUSB_OTG)
+ .mode = MUSB_OTG,
+#elif defined(CONFIG_USB_MUSB_HDRC_HCD)
+ .mode = MUSB_HOST,
+#elif defined(CONFIG_USB_GADGET_MUSB_HDRC)
+ .mode = MUSB_PERIPHERAL,
+#endif
+ .config = &musb_config,
+};
+
+static u64 musb_dmamask = ~(u32)0;
+
+static struct platform_device musb_device = {
+ .name = "musb_hdrc",
+ .id = 0,
+ .dev = {
+ .dma_mask = &musb_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ .platform_data = &musb_plat,
+ },
+ .num_resources = ARRAY_SIZE(musb_resources),
+ .resource = musb_resources,
+};
+#endif
+
+#if defined(CONFIG_FB_BFIN_RA158Z) || defined(CONFIG_FB_BFIN_RA158Z_MODULE)
+static struct resource bf52x_ra158z_resources[] = {
+ {
+ .start = IRQ_PPI_ERROR,
+ .end = IRQ_PPI_ERROR,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device bf52x_ra158z_device = {
+ .name = "bfin-ra158z",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(bf52x_ra158z_resources),
+ .resource = bf52x_ra158z_resources,
+};
+#endif
+
+#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
+static struct mtd_partition ad7160eval_partitions[] = {
+ {
+ .name = "bootloader(nor)",
+ .size = 0x40000,
+ .offset = 0,
+ }, {
+ .name = "linux kernel(nor)",
+ .size = 0x1C0000,
+ .offset = MTDPART_OFS_APPEND,
+ }, {
+ .name = "file system(nor)",
+ .size = MTDPART_SIZ_FULL,
+ .offset = MTDPART_OFS_APPEND,
+ }
+};
+
+static struct physmap_flash_data ad7160eval_flash_data = {
+ .width = 2,
+ .parts = ad7160eval_partitions,
+ .nr_parts = ARRAY_SIZE(ad7160eval_partitions),
+};
+
+static struct resource ad7160eval_flash_resource = {
+ .start = 0x20000000,
+ .end = 0x203fffff,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device ad7160eval_flash_device = {
+ .name = "physmap-flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &ad7160eval_flash_data,
+ },
+ .num_resources = 1,
+ .resource = &ad7160eval_flash_resource,
+};
+#endif
+
+#if defined(CONFIG_MTD_NAND_BF5XX) || defined(CONFIG_MTD_NAND_BF5XX_MODULE)
+static struct mtd_partition partition_info[] = {
+ {
+ .name = "linux kernel(nand)",
+ .offset = 0,
+ .size = 4 * 1024 * 1024,
+ },
+ {
+ .name = "file system(nand)",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ },
+};
+
+static struct bf5xx_nand_platform bf5xx_nand_platform = {
+ .data_width = NFC_NWIDTH_8,
+ .partitions = partition_info,
+ .nr_partitions = ARRAY_SIZE(partition_info),
+ .rd_dly = 3,
+ .wr_dly = 3,
+};
+
+static struct resource bf5xx_nand_resources[] = {
+ {
+ .start = NFC_CTL,
+ .end = NFC_DATA_RD + 2,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = CH_NFC,
+ .end = CH_NFC,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device bf5xx_nand_device = {
+ .name = "bf5xx-nand",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bf5xx_nand_resources),
+ .resource = bf5xx_nand_resources,
+ .dev = {
+ .platform_data = &bf5xx_nand_platform,
+ },
+};
+#endif
+
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+static struct platform_device rtc_device = {
+ .name = "rtc-bfin",
+ .id = -1,
+};
+#endif
+
+#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+#include <linux/bfin_mac.h>
+static const unsigned short bfin_mac_peripherals[] = P_RMII0;
+
+static struct bfin_phydev_platform_data bfin_phydev_data[] = {
+ {
+ .addr = 1,
+ .irq = IRQ_MAC_PHYINT,
+ },
+};
+
+static struct bfin_mii_bus_platform_data bfin_mii_bus_data = {
+ .phydev_number = 1,
+ .phydev_data = bfin_phydev_data,
+ .phy_mode = PHY_INTERFACE_MODE_RMII,
+ .mac_peripherals = bfin_mac_peripherals,
+};
+
+static struct platform_device bfin_mii_bus = {
+ .name = "bfin_mii_bus",
+ .dev = {
+ .platform_data = &bfin_mii_bus_data,
+ }
+};
+
+static struct platform_device bfin_mac_device = {
+ .name = "bfin_mac",
+ .dev = {
+ .platform_data = &bfin_mii_bus,
+ }
+};
+#endif
+
+
+#if defined(CONFIG_MTD_M25P80) \
+ || defined(CONFIG_MTD_M25P80_MODULE)
+static struct mtd_partition bfin_spi_flash_partitions[] = {
+ {
+ .name = "bootloader(spi)",
+ .size = 0x00040000,
+ .offset = 0,
+ .mask_flags = MTD_CAP_ROM
+ }, {
+ .name = "linux kernel(spi)",
+ .size = MTDPART_SIZ_FULL,
+ .offset = MTDPART_OFS_APPEND,
+ }
+};
+
+static struct flash_platform_data bfin_spi_flash_data = {
+ .name = "m25p80",
+ .parts = bfin_spi_flash_partitions,
+ .nr_parts = ARRAY_SIZE(bfin_spi_flash_partitions),
+ .type = "m25p16",
+};
+
+/* SPI flash chip (m25p64) */
+static struct bfin5xx_spi_chip spi_flash_chip_info = {
+ .enable_dma = 0, /* use dma transfer with this chip*/
+ .bits_per_word = 8,
+};
+#endif
+
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
+ || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
+static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
+ .enable_dma = 0,
+ .bits_per_word = 16,
+};
+#endif
+
+#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
+static struct bfin5xx_spi_chip mmc_spi_chip_info = {
+ .enable_dma = 0,
+ .bits_per_word = 8,
+};
+#endif
+
+#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
+static struct bfin5xx_spi_chip spidev_chip_info = {
+ .enable_dma = 0,
+ .bits_per_word = 8,
+};
+#endif
+
+#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE)
+static struct platform_device bfin_i2s = {
+ .name = "bfin-i2s",
+ .id = CONFIG_SND_BF5XX_SPORT_NUM,
+ /* TODO: add platform data here */
+};
+#endif
+
+#if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE)
+static struct platform_device bfin_tdm = {
+ .name = "bfin-tdm",
+ .id = CONFIG_SND_BF5XX_SPORT_NUM,
+ /* TODO: add platform data here */
+};
+#endif
+
+static struct spi_board_info bfin_spi_board_info[] __initdata = {
+#if defined(CONFIG_MTD_M25P80) \
+ || defined(CONFIG_MTD_M25P80_MODULE)
+ {
+ /* the modalias must be the same as spi device driver name */
+ .modalias = "m25p80", /* Name of spi_driver for this device */
+ .max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0, /* Framework bus number */
+ .chip_select = 1, /* Framework chip select. On STAMP537 it is SPISSEL1*/
+ .platform_data = &bfin_spi_flash_data,
+ .controller_data = &spi_flash_chip_info,
+ .mode = SPI_MODE_3,
+ },
+#endif
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
+ || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
+ {
+ .modalias = "ad183x",
+ .max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 4,
+ .controller_data = &ad1836_spi_chip_info,
+ },
+#endif
+#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
+ {
+ .modalias = "mmc_spi",
+ .max_speed_hz = 30000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = GPIO_PH3 + MAX_CTRL_CS,
+ .controller_data = &mmc_spi_chip_info,
+ .mode = SPI_MODE_3,
+ },
+#endif
+#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
+ {
+ .modalias = "spidev",
+ .max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 1,
+ .controller_data = &spidev_chip_info,
+ },
+#endif
+};
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+/* SPI controller data */
+static struct bfin5xx_spi_master bfin_spi0_info = {
+ .num_chipselect = MAX_CTRL_CS + MAX_BLACKFIN_GPIOS,
+ .enable_dma = 1, /* master has the ability to do dma transfer */
+ .pin_req = {P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0},
+};
+
+/* SPI (0) */
+static struct resource bfin_spi0_resource[] = {
+ [0] = {
+ .start = SPI0_REGBASE,
+ .end = SPI0_REGBASE + 0xFF,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = CH_SPI,
+ .end = CH_SPI,
+ .flags = IORESOURCE_DMA,
+ },
+ [2] = {
+ .start = IRQ_SPI,
+ .end = IRQ_SPI,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device bfin_spi0_device = {
+ .name = "bfin-spi",
+ .id = 0, /* Bus number */
+ .num_resources = ARRAY_SIZE(bfin_spi0_resource),
+ .resource = bfin_spi0_resource,
+ .dev = {
+ .platform_data = &bfin_spi0_info, /* Passed to driver */
+ },
+};
+#endif /* spi master and devices */
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+#ifdef CONFIG_SERIAL_BFIN_UART0
+static struct resource bfin_uart0_resources[] = {
+ {
+ .start = UART0_THR,
+ .end = UART0_GCTL+2,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_UART0_RX,
+ .end = IRQ_UART0_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = IRQ_UART0_ERROR,
+ .end = IRQ_UART0_ERROR,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART0_TX,
+ .end = CH_UART0_TX,
+ .flags = IORESOURCE_DMA,
+ },
+ {
+ .start = CH_UART0_RX,
+ .end = CH_UART0_RX,
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+unsigned short bfin_uart0_peripherals[] = {
+ P_UART0_TX, P_UART0_RX, 0
+};
+
+static struct platform_device bfin_uart0_device = {
+ .name = "bfin-uart",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bfin_uart0_resources),
+ .resource = bfin_uart0_resources,
+ .dev = {
+ .platform_data = &bfin_uart0_peripherals, /* Passed to driver */
+ },
+};
+#endif
+#ifdef CONFIG_SERIAL_BFIN_UART1
+static struct resource bfin_uart1_resources[] = {
+ {
+ .start = UART1_THR,
+ .end = UART1_GCTL+2,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_UART1_RX,
+ .end = IRQ_UART1_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = IRQ_UART1_ERROR,
+ .end = IRQ_UART1_ERROR,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART1_TX,
+ .end = CH_UART1_TX,
+ .flags = IORESOURCE_DMA,
+ },
+ {
+ .start = CH_UART1_RX,
+ .end = CH_UART1_RX,
+ .flags = IORESOURCE_DMA,
+ },
+#ifdef CONFIG_BFIN_UART1_CTSRTS
+ { /* CTS pin */
+ .start = GPIO_PF9,
+ .end = GPIO_PF9,
+ .flags = IORESOURCE_IO,
+ },
+ { /* RTS pin */
+ .start = GPIO_PF10,
+ .end = GPIO_PF10,
+ .flags = IORESOURCE_IO,
+ },
+#endif
+};
+
+unsigned short bfin_uart1_peripherals[] = {
+ P_UART1_TX, P_UART1_RX, 0
+};
+
+static struct platform_device bfin_uart1_device = {
+ .name = "bfin-uart",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(bfin_uart1_resources),
+ .resource = bfin_uart1_resources,
+ .dev = {
+ .platform_data = &bfin_uart1_peripherals, /* Passed to driver */
+ },
+};
+#endif
+#endif
+
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+#ifdef CONFIG_BFIN_SIR0
+static struct resource bfin_sir0_resources[] = {
+ {
+ .start = 0xFFC00400,
+ .end = 0xFFC004FF,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_UART0_RX,
+ .end = IRQ_UART0_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART0_RX,
+ .end = CH_UART0_RX+1,
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+static struct platform_device bfin_sir0_device = {
+ .name = "bfin_sir",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bfin_sir0_resources),
+ .resource = bfin_sir0_resources,
+};
+#endif
+#ifdef CONFIG_BFIN_SIR1
+static struct resource bfin_sir1_resources[] = {
+ {
+ .start = 0xFFC02000,
+ .end = 0xFFC020FF,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_UART1_RX,
+ .end = IRQ_UART1_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART1_RX,
+ .end = CH_UART1_RX+1,
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+static struct platform_device bfin_sir1_device = {
+ .name = "bfin_sir",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(bfin_sir1_resources),
+ .resource = bfin_sir1_resources,
+};
+#endif
+#endif
+
+#if defined(CONFIG_TOUCHSCREEN_AD7160) || defined(CONFIG_TOUCHSCREEN_AD7160_MODULE)
+#include <linux/input/ad7160.h>
+static const struct ad7160_platform_data bfin_ad7160_ts_info = {
+ .sensor_x_res = 854,
+ .sensor_y_res = 480,
+ .pressure = 100,
+ .filter_coef = 3,
+ .coord_pref = AD7160_ORIG_TOP_LEFT,
+ .first_touch_window = 5,
+ .move_window = 3,
+ .event_cabs = AD7160_EMIT_ABS_MT_TRACKING_ID |
+ AD7160_EMIT_ABS_MT_PRESSURE |
+ AD7160_TRACKING_ID_ASCENDING,
+ .finger_act_ctrl = 0x64,
+ .haptic_effect1_ctrl = AD7160_HAPTIC_SLOT_A(60) |
+ AD7160_HAPTIC_SLOT_A_LVL_HIGH |
+ AD7160_HAPTIC_SLOT_B(60) |
+ AD7160_HAPTIC_SLOT_B_LVL_LOW,
+
+ .haptic_effect2_ctrl = AD7160_HAPTIC_SLOT_A(20) |
+ AD7160_HAPTIC_SLOT_A_LVL_HIGH |
+ AD7160_HAPTIC_SLOT_B(80) |
+ AD7160_HAPTIC_SLOT_B_LVL_LOW |
+ AD7160_HAPTIC_SLOT_C(120) |
+ AD7160_HAPTIC_SLOT_C_LVL_HIGH |
+ AD7160_HAPTIC_SLOT_D(30) |
+ AD7160_HAPTIC_SLOT_D_LVL_LOW,
+};
+#endif
+
+#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+static struct resource bfin_twi0_resource[] = {
+ [0] = {
+ .start = TWI0_REGBASE,
+ .end = TWI0_REGBASE,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_TWI,
+ .end = IRQ_TWI,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device i2c_bfin_twi_device = {
+ .name = "i2c-bfin-twi",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bfin_twi0_resource),
+ .resource = bfin_twi0_resource,
+};
+#endif
+
+static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
+#if defined(CONFIG_TOUCHSCREEN_AD7160) || defined(CONFIG_TOUCHSCREEN_AD7160_MODULE)
+ {
+ I2C_BOARD_INFO("ad7160", 0x33),
+ .irq = IRQ_PH1,
+ .platform_data = (void *)&bfin_ad7160_ts_info,
+ },
+#endif
+};
+
+#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
+#ifdef CONFIG_SERIAL_BFIN_SPORT0_UART
+static struct resource bfin_sport0_uart_resources[] = {
+ {
+ .start = SPORT0_TCR1,
+ .end = SPORT0_MRCS3+4,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_SPORT0_RX,
+ .end = IRQ_SPORT0_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = IRQ_SPORT0_ERROR,
+ .end = IRQ_SPORT0_ERROR,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+unsigned short bfin_sport0_peripherals[] = {
+ P_SPORT0_TFS, P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
+ P_SPORT0_DRPRI, P_SPORT0_RSCLK, P_SPORT0_DRSEC, P_SPORT0_DTSEC, 0
+};
+
+static struct platform_device bfin_sport0_uart_device = {
+ .name = "bfin-sport-uart",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bfin_sport0_uart_resources),
+ .resource = bfin_sport0_uart_resources,
+ .dev = {
+ .platform_data = &bfin_sport0_peripherals, /* Passed to driver */
+ },
+};
+#endif
+#ifdef CONFIG_SERIAL_BFIN_SPORT1_UART
+static struct resource bfin_sport1_uart_resources[] = {
+ {
+ .start = SPORT1_TCR1,
+ .end = SPORT1_MRCS3+4,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_SPORT1_RX,
+ .end = IRQ_SPORT1_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = IRQ_SPORT1_ERROR,
+ .end = IRQ_SPORT1_ERROR,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+unsigned short bfin_sport1_peripherals[] = {
+ P_SPORT1_TFS, P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS,
+ P_SPORT1_DRPRI, P_SPORT1_RSCLK, P_SPORT1_DRSEC, P_SPORT1_DTSEC, 0
+};
+
+static struct platform_device bfin_sport1_uart_device = {
+ .name = "bfin-sport-uart",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(bfin_sport1_uart_resources),
+ .resource = bfin_sport1_uart_resources,
+ .dev = {
+ .platform_data = &bfin_sport1_peripherals, /* Passed to driver */
+ },
+};
+#endif
+#endif
+
+#if defined(CONFIG_INPUT_BFIN_ROTARY) || defined(CONFIG_INPUT_BFIN_ROTARY_MODULE)
+#include <asm/bfin_rotary.h>
+
+static struct bfin_rotary_platform_data bfin_rotary_data = {
+ /*.rotary_up_key = KEY_UP,*/
+ /*.rotary_down_key = KEY_DOWN,*/
+ .rotary_rel_code = REL_WHEEL,
+ .rotary_button_key = KEY_ENTER,
+ .debounce = 10, /* 0..17 */
+ .mode = ROT_QUAD_ENC | ROT_DEBE,
+};
+
+static struct resource bfin_rotary_resources[] = {
+ {
+ .start = IRQ_CNT,
+ .end = IRQ_CNT,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device bfin_rotary_device = {
+ .name = "bfin-rotary",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(bfin_rotary_resources),
+ .resource = bfin_rotary_resources,
+ .dev = {
+ .platform_data = &bfin_rotary_data,
+ },
+};
+#endif
+
+static const unsigned int cclk_vlev_datasheet[] = {
+ VRPAIR(VLEV_100, 400000000),
+ VRPAIR(VLEV_105, 426000000),
+ VRPAIR(VLEV_110, 500000000),
+ VRPAIR(VLEV_115, 533000000),
+ VRPAIR(VLEV_120, 600000000),
+};
+
+static struct bfin_dpmc_platform_data bfin_dmpc_vreg_data = {
+ .tuple_tab = cclk_vlev_datasheet,
+ .tabsize = ARRAY_SIZE(cclk_vlev_datasheet),
+ .vr_settling_time = 25 /* us */,
+};
+
+static struct platform_device bfin_dpmc = {
+ .name = "bfin dpmc",
+ .dev = {
+ .platform_data = &bfin_dmpc_vreg_data,
+ },
+};
+
+static struct platform_device *stamp_devices[] __initdata = {
+
+ &bfin_dpmc,
+
+#if defined(CONFIG_MTD_NAND_BF5XX) || defined(CONFIG_MTD_NAND_BF5XX_MODULE)
+ &bf5xx_nand_device,
+#endif
+
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+ &rtc_device,
+#endif
+
+#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE)
+ &musb_device,
+#endif
+
+#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+ &bfin_mii_bus,
+ &bfin_mac_device,
+#endif
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+ &bfin_spi0_device,
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+#ifdef CONFIG_SERIAL_BFIN_UART0
+ &bfin_uart0_device,
+#endif
+#ifdef CONFIG_SERIAL_BFIN_UART1
+ &bfin_uart1_device,
+#endif
+#endif
+
+#if defined(CONFIG_FB_BFIN_RA158Z) || defined(CONFIG_FB_BFIN_RA158Z_MODULE)
+ &bf52x_ra158z_device,
+#endif
+
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+#ifdef CONFIG_BFIN_SIR0
+ &bfin_sir0_device,
+#endif
+#ifdef CONFIG_BFIN_SIR1
+ &bfin_sir1_device,
+#endif
+#endif
+
+#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+ &i2c_bfin_twi_device,
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
+#ifdef CONFIG_SERIAL_BFIN_SPORT0_UART
+ &bfin_sport0_uart_device,
+#endif
+#ifdef CONFIG_SERIAL_BFIN_SPORT1_UART
+ &bfin_sport1_uart_device,
+#endif
+#endif
+
+#if defined(CONFIG_INPUT_BFIN_ROTARY) || defined(CONFIG_INPUT_BFIN_ROTARY_MODULE)
+ &bfin_rotary_device,
+#endif
+
+#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
+ &ad7160eval_flash_device,
+#endif
+
+#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE)
+ &bfin_i2s,
+#endif
+
+#if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE)
+ &bfin_tdm,
+#endif
+};
+
+static int __init ad7160eval_init(void)
+{
+ printk(KERN_INFO "%s(): registering device resources\n", __func__);
+ i2c_register_board_info(0, bfin_i2c_board_info,
+ ARRAY_SIZE(bfin_i2c_board_info));
+ platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
+ spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
+ return 0;
+}
+
+arch_initcall(ad7160eval_init);
+
+static struct platform_device *ad7160eval_early_devices[] __initdata = {
+#if defined(CONFIG_SERIAL_BFIN_CONSOLE) || defined(CONFIG_EARLY_PRINTK)
+#ifdef CONFIG_SERIAL_BFIN_UART0
+ &bfin_uart0_device,
+#endif
+#ifdef CONFIG_SERIAL_BFIN_UART1
+ &bfin_uart1_device,
+#endif
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN_SPORT_CONSOLE)
+#ifdef CONFIG_SERIAL_BFIN_SPORT0_UART
+ &bfin_sport0_uart_device,
+#endif
+#ifdef CONFIG_SERIAL_BFIN_SPORT1_UART
+ &bfin_sport1_uart_device,
+#endif
+#endif
+};
+
+void __init native_machine_early_platform_add_devices(void)
+{
+ printk(KERN_INFO "register early platform devices\n");
+ early_platform_add_devices(ad7160eval_early_devices,
+ ARRAY_SIZE(ad7160eval_early_devices));
+}
+
+void native_machine_restart(char *cmd)
+{
+ /* workaround reboot hang when booting from SPI */
+ if ((bfin_read_SYSCR() & 0x7) == 0x3)
+ bfin_reset_boot_spi_cs(P_DEFAULT_BOOT_SPI_CS);
+}
+
+void bfin_get_ether_addr(char *addr)
+{
+ /* the MAC is stored in OTP memory page 0xDF */
+ u32 ret;
+ u64 otp_mac;
+ u32 (*otp_read)(u32 page, u32 flags, u64 *page_content) = (void *)0xEF00001A;
+
+ ret = otp_read(0xDF, 0x00, &otp_mac);
+ if (!(ret & 0x1)) {
+ char *otp_mac_p = (char *)&otp_mac;
+ for (ret = 0; ret < 6; ++ret)
+ addr[ret] = otp_mac_p[5 - ret];
+ }
+}
+EXPORT_SYMBOL(bfin_get_ether_addr);
diff --git a/arch/blackfin/mach-bf527/boards/cm_bf527.c b/arch/blackfin/mach-bf527/boards/cm_bf527.c
index 645ba5c8077b..38037c7e125a 100644
--- a/arch/blackfin/mach-bf527/boards/cm_bf527.c
+++ b/arch/blackfin/mach-bf527/boards/cm_bf527.c
@@ -342,8 +342,8 @@ static struct bfin5xx_spi_chip spi_adc_chip_info = {
};
#endif
-#if defined(CONFIG_SND_BLACKFIN_AD183X) \
- || defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
+ || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
.enable_dma = 0,
.bits_per_word = 16,
@@ -420,13 +420,13 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
},
#endif
-#if defined(CONFIG_SND_BLACKFIN_AD183X) \
- || defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
+ || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
{
- .modalias = "ad1836",
+ .modalias = "ad183x",
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
- .chip_select = CONFIG_SND_BLACKFIN_SPI_PFBIT,
+ .chip_select = 4,
.controller_data = &ad1836_spi_chip_info,
},
#endif
diff --git a/arch/blackfin/mach-bf527/boards/ezbrd.c b/arch/blackfin/mach-bf527/boards/ezbrd.c
index c975fe88eba3..6cc64a1e78b9 100644
--- a/arch/blackfin/mach-bf527/boards/ezbrd.c
+++ b/arch/blackfin/mach-bf527/boards/ezbrd.c
@@ -137,8 +137,12 @@ static struct platform_device ezbrd_flash_device = {
#if defined(CONFIG_MTD_NAND_BF5XX) || defined(CONFIG_MTD_NAND_BF5XX_MODULE)
static struct mtd_partition partition_info[] = {
{
- .name = "linux kernel(nand)",
+ .name = "bootloader(nand)",
.offset = 0,
+ .size = 0x40000,
+ }, {
+ .name = "linux kernel(nand)",
+ .offset = MTDPART_OFS_APPEND,
.size = 4 * 1024 * 1024,
},
{
diff --git a/arch/blackfin/mach-bf527/boards/ezkit.c b/arch/blackfin/mach-bf527/boards/ezkit.c
index 87b41e994ba3..07c132dc4125 100644
--- a/arch/blackfin/mach-bf527/boards/ezkit.c
+++ b/arch/blackfin/mach-bf527/boards/ezkit.c
@@ -222,8 +222,12 @@ static struct platform_device ezkit_flash_device = {
#if defined(CONFIG_MTD_NAND_BF5XX) || defined(CONFIG_MTD_NAND_BF5XX_MODULE)
static struct mtd_partition partition_info[] = {
{
- .name = "linux kernel(nand)",
+ .name = "bootloader(nand)",
.offset = 0,
+ .size = 0x40000,
+ }, {
+ .name = "linux kernel(nand)",
+ .offset = MTDPART_OFS_APPEND,
.size = 4 * 1024 * 1024,
},
{
@@ -431,8 +435,8 @@ static struct bfin5xx_spi_chip spi_adc_chip_info = {
};
#endif
-#if defined(CONFIG_SND_BLACKFIN_AD183X) \
- || defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
+ || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
.enable_dma = 0,
.bits_per_word = 16,
@@ -547,13 +551,13 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
},
#endif
-#if defined(CONFIG_SND_BLACKFIN_AD183X) \
- || defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
+ || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
{
- .modalias = "ad1836",
+ .modalias = "ad183x",
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
- .chip_select = CONFIG_SND_BLACKFIN_SPI_PFBIT,
+ .chip_select = 4,
.controller_data = &ad1836_spi_chip_info,
},
#endif
@@ -929,6 +933,11 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
I2C_BOARD_INFO("ssm2602", 0x1b),
},
#endif
+#if defined(CONFIG_BFIN_TWI_LCD) || defined(CONFIG_BFIN_TWI_LCD_MODULE)
+ {
+ I2C_BOARD_INFO("ad5252", 0x2f),
+ },
+#endif
};
#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
diff --git a/arch/blackfin/mach-bf527/boards/tll6527m.c b/arch/blackfin/mach-bf527/boards/tll6527m.c
new file mode 100644
index 000000000000..ae4130e97c01
--- /dev/null
+++ b/arch/blackfin/mach-bf527/boards/tll6527m.c
@@ -0,0 +1,986 @@
+/* File: arch/blackfin/mach-bf527/boards/tll6527m.c
+ * Based on: arch/blackfin/mach-bf527/boards/ezkit.c
+ * Author: Ashish Gupta
+ *
+ * Copyright: 2010 - The Learning Labs Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#include <linux/i2c.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/usb/musb.h>
+#include <linux/leds.h>
+#include <linux/input.h>
+#include <asm/dma.h>
+#include <asm/bfin5xx_spi.h>
+#include <asm/reboot.h>
+#include <asm/nand.h>
+#include <asm/portmux.h>
+#include <asm/dpmc.h>
+
+#if defined(CONFIG_TOUCHSCREEN_AD7879) \
+ || defined(CONFIG_TOUCHSCREEN_AD7879_MODULE)
+#include <linux/spi/ad7879.h>
+#define LCD_BACKLIGHT_GPIO 0x40
+/* TLL6527M uses TLL7UIQ35 / ADI LCD EZ Extender. AD7879 AUX GPIO is used for
+ * LCD Backlight Enable
+ */
+#endif
+
+/*
+ * Name the Board for the /proc/cpuinfo
+ */
+const char bfin_board_name[] = "TLL6527M";
+/*
+ * Driver needs to know address, irq and flag pin.
+ */
+
+#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE)
+static struct resource musb_resources[] = {
+ [0] = {
+ .start = 0xffc03800,
+ .end = 0xffc03cff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = { /* general IRQ */
+ .start = IRQ_USB_INT0,
+ .end = IRQ_USB_INT0,
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+ },
+ [2] = { /* DMA IRQ */
+ .start = IRQ_USB_DMA,
+ .end = IRQ_USB_DMA,
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+ },
+};
+
+static struct musb_hdrc_config musb_config = {
+ .multipoint = 0,
+ .dyn_fifo = 0,
+ .soft_con = 1,
+ .dma = 1,
+ .num_eps = 8,
+ .dma_channels = 8,
+ /*.gpio_vrsel = GPIO_PG13,*/
+ /* Some custom boards need to be active low, just set it to "0"
+ * if it is the case.
+ */
+ .gpio_vrsel_active = 1,
+};
+
+static struct musb_hdrc_platform_data musb_plat = {
+#if defined(CONFIG_USB_MUSB_OTG)
+ .mode = MUSB_OTG,
+#elif defined(CONFIG_USB_MUSB_HDRC_HCD)
+ .mode = MUSB_HOST,
+#elif defined(CONFIG_USB_GADGET_MUSB_HDRC)
+ .mode = MUSB_PERIPHERAL,
+#endif
+ .config = &musb_config,
+};
+
+static u64 musb_dmamask = ~(u32)0;
+
+static struct platform_device musb_device = {
+ .name = "musb_hdrc",
+ .id = 0,
+ .dev = {
+ .dma_mask = &musb_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ .platform_data = &musb_plat,
+ },
+ .num_resources = ARRAY_SIZE(musb_resources),
+ .resource = musb_resources,
+};
+#endif
+
+#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
+#include <asm/bfin-lq035q1.h>
+
+static struct bfin_lq035q1fb_disp_info bfin_lq035q1_data = {
+ .mode = LQ035_NORM | LQ035_RGB | LQ035_RL | LQ035_TB,
+ .ppi_mode = USE_RGB565_16_BIT_PPI,
+ .use_bl = 1,
+ .gpio_bl = LCD_BACKLIGHT_GPIO,
+};
+
+static struct resource bfin_lq035q1_resources[] = {
+ {
+ .start = IRQ_PPI_ERROR,
+ .end = IRQ_PPI_ERROR,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device bfin_lq035q1_device = {
+ .name = "bfin-lq035q1",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(bfin_lq035q1_resources),
+ .resource = bfin_lq035q1_resources,
+ .dev = {
+ .platform_data = &bfin_lq035q1_data,
+ },
+};
+#endif
+
+#if defined(CONFIG_MTD_GPIO_ADDR) || defined(CONFIG_MTD_GPIO_ADDR_MODULE)
+static struct mtd_partition tll6527m_partitions[] = {
+ {
+ .name = "bootloader(nor)",
+ .size = 0xA0000,
+ .offset = 0,
+ }, {
+ .name = "linux kernel(nor)",
+ .size = 0xD00000,
+ .offset = MTDPART_OFS_APPEND,
+ }, {
+ .name = "file system(nor)",
+ .size = MTDPART_SIZ_FULL,
+ .offset = MTDPART_OFS_APPEND,
+ }
+};
+
+static struct physmap_flash_data tll6527m_flash_data = {
+ .width = 2,
+ .parts = tll6527m_partitions,
+ .nr_parts = ARRAY_SIZE(tll6527m_partitions),
+};
+
+static unsigned tll6527m_flash_gpios[] = { GPIO_PG11, GPIO_PH11, GPIO_PH12 };
+
+static struct resource tll6527m_flash_resource[] = {
+ {
+ .name = "cfi_probe",
+ .start = 0x20000000,
+ .end = 0x201fffff,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = (unsigned long)tll6527m_flash_gpios,
+ .end = ARRAY_SIZE(tll6527m_flash_gpios),
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct platform_device tll6527m_flash_device = {
+ .name = "gpio-addr-flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &tll6527m_flash_data,
+ },
+ .num_resources = ARRAY_SIZE(tll6527m_flash_resource),
+ .resource = tll6527m_flash_resource,
+};
+#endif
+
+#if defined(CONFIG_GPIO_DECODER) || defined(CONFIG_GPIO_DECODER_MODULE)
+/* An SN74LVC138A 3:8 decoder chip has been used to generate 7 augmented
+ * outputs used as SPI CS lines for all SPI SLAVE devices on TLL6527v1-0.
+ * EXP_GPIO_SPISEL_BASE is the base number for the expanded outputs being
+ * used as SPI CS lines, this should be > MAX_BLACKFIN_GPIOS
+ */
+#include <linux/gpio-decoder.h>
+#define EXP_GPIO_SPISEL_BASE 0x64
+static unsigned gpio_addr_inputs[] = {
+ GPIO_PG1, GPIO_PH9, GPIO_PH10
+};
+
+static struct gpio_decoder_platfrom_data spi_decoded_cs = {
+ .base = EXP_GPIO_SPISEL_BASE,
+ .input_addrs = gpio_addr_inputs,
+ .nr_input_addrs = ARRAY_SIZE(gpio_addr_inputs),
+ .default_output = 0,
+/* .default_output = (1 << ARRAY_SIZE(gpio_addr_inputs)) - 1 */
+};
+
+static struct platform_device spi_decoded_gpio = {
+ .name = "gpio-decoder",
+ .id = 0,
+ .dev = {
+ .platform_data = &spi_decoded_cs,
+ },
+};
+
+#else
+#define EXP_GPIO_SPISEL_BASE 0x0
+
+#endif
+
+#if defined(CONFIG_INPUT_ADXL34X) || defined(CONFIG_INPUT_ADXL34X_MODULE)
+#include <linux/input/adxl34x.h>
+static const struct adxl34x_platform_data adxl345_info = {
+ .x_axis_offset = 0,
+ .y_axis_offset = 0,
+ .z_axis_offset = 0,
+ .tap_threshold = 0x31,
+ .tap_duration = 0x10,
+ .tap_latency = 0x60,
+ .tap_window = 0xF0,
+ .tap_axis_control = ADXL_TAP_X_EN | ADXL_TAP_Y_EN | ADXL_TAP_Z_EN,
+ .act_axis_control = 0xFF,
+ .activity_threshold = 5,
+ .inactivity_threshold = 2,
+ .inactivity_time = 2,
+ .free_fall_threshold = 0x7,
+ .free_fall_time = 0x20,
+ .data_rate = 0x8,
+ .data_range = ADXL_FULL_RES,
+
+ .ev_type = EV_ABS,
+ .ev_code_x = ABS_X, /* EV_REL */
+ .ev_code_y = ABS_Y, /* EV_REL */
+ .ev_code_z = ABS_Z, /* EV_REL */
+
+ .ev_code_tap = {BTN_TOUCH, BTN_TOUCH, BTN_TOUCH}, /* EV_KEY x,y,z */
+
+/* .ev_code_ff = KEY_F,*/ /* EV_KEY */
+ .ev_code_act_inactivity = KEY_A, /* EV_KEY */
+ .use_int2 = 1,
+ .power_mode = ADXL_AUTO_SLEEP | ADXL_LINK,
+ .fifo_mode = ADXL_FIFO_STREAM,
+};
+#endif
+
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+static struct platform_device rtc_device = {
+ .name = "rtc-bfin",
+ .id = -1,
+};
+#endif
+
+#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+static struct platform_device bfin_mii_bus = {
+ .name = "bfin_mii_bus",
+};
+
+static struct platform_device bfin_mac_device = {
+ .name = "bfin_mac",
+ .dev.platform_data = &bfin_mii_bus,
+};
+#endif
+
+#if defined(CONFIG_MTD_M25P80) \
+ || defined(CONFIG_MTD_M25P80_MODULE)
+static struct mtd_partition bfin_spi_flash_partitions[] = {
+ {
+ .name = "bootloader(spi)",
+ .size = 0x00040000,
+ .offset = 0,
+ .mask_flags = MTD_CAP_ROM
+ }, {
+ .name = "linux kernel(spi)",
+ .size = MTDPART_SIZ_FULL,
+ .offset = MTDPART_OFS_APPEND,
+ }
+};
+
+static struct flash_platform_data bfin_spi_flash_data = {
+ .name = "m25p80",
+ .parts = bfin_spi_flash_partitions,
+ .nr_parts = ARRAY_SIZE(bfin_spi_flash_partitions),
+ .type = "m25p16",
+};
+
+/* SPI flash chip (m25p64) */
+static struct bfin5xx_spi_chip spi_flash_chip_info = {
+ .enable_dma = 0, /* use dma transfer with this chip*/
+ .bits_per_word = 8,
+};
+#endif
+
+#if defined(CONFIG_BFIN_SPI_ADC) \
+ || defined(CONFIG_BFIN_SPI_ADC_MODULE)
+/* SPI ADC chip */
+static struct bfin5xx_spi_chip spi_adc_chip_info = {
+ .enable_dma = 0, /* use dma transfer with this chip*/
+/*
+ * tll6527m V1.0 does not support native spi slave selects
+ * hence DMA mode will not be useful since the ADC needs
+ * CS to toggle for each sample and cs_change_per_word
+ * seems to be removed from spi_bfin5xx.c
+ */
+ .bits_per_word = 16,
+};
+#endif
+
+#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
+static struct bfin5xx_spi_chip mmc_spi_chip_info = {
+ .enable_dma = 0,
+ .bits_per_word = 8,
+};
+#endif
+
+#if defined(CONFIG_TOUCHSCREEN_AD7879) \
+ || defined(CONFIG_TOUCHSCREEN_AD7879_MODULE)
+static const struct ad7879_platform_data bfin_ad7879_ts_info = {
+ .model = 7879, /* Model = AD7879 */
+ .x_plate_ohms = 620, /* 620 Ohm from the touch datasheet */
+ .pressure_max = 10000,
+ .pressure_min = 0,
+ .first_conversion_delay = 3,
+ /* wait 512us before do a first conversion */
+ .acquisition_time = 1, /* 4us acquisition time per sample */
+ .median = 2, /* do 8 measurements */
+ .averaging = 1,
+ /* take the average of 4 middle samples */
+ .pen_down_acc_interval = 255, /* 9.4 ms */
+ .gpio_export = 1, /* configure AUX as GPIO output*/
+ .gpio_base = LCD_BACKLIGHT_GPIO,
+};
+#endif
+
+#if defined(CONFIG_TOUCHSCREEN_AD7879_SPI) \
+ || defined(CONFIG_TOUCHSCREEN_AD7879_SPI_MODULE)
+static struct bfin5xx_spi_chip spi_ad7879_chip_info = {
+ .enable_dma = 0,
+ .bits_per_word = 16,
+};
+#endif
+
+#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
+static struct bfin5xx_spi_chip spidev_chip_info = {
+ .enable_dma = 0,
+ .bits_per_word = 8,
+};
+#endif
+
+#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE)
+static struct platform_device bfin_i2s = {
+ .name = "bfin-i2s",
+ .id = CONFIG_SND_BF5XX_SPORT_NUM,
+ /* TODO: add platform data here */
+};
+#endif
+
+#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
+static struct bfin5xx_spi_chip lq035q1_spi_chip_info = {
+ .enable_dma = 0,
+ .bits_per_word = 8,
+};
+#endif
+
+#if defined(CONFIG_GPIO_MCP23S08) || defined(CONFIG_GPIO_MCP23S08_MODULE)
+static struct bfin5xx_spi_chip spi_mcp23s08_sys_chip_info = {
+ .enable_dma = 0,
+ .bits_per_word = 8,
+};
+
+static struct bfin5xx_spi_chip spi_mcp23s08_usr_chip_info = {
+ .enable_dma = 0,
+ .bits_per_word = 8,
+};
+
+#include <linux/spi/mcp23s08.h>
+static const struct mcp23s08_platform_data bfin_mcp23s08_sys_gpio_info = {
+ .chip[0].is_present = true,
+ .base = 0x30,
+};
+static const struct mcp23s08_platform_data bfin_mcp23s08_usr_gpio_info = {
+ .chip[2].is_present = true,
+ .base = 0x38,
+};
+#endif
+
+static struct spi_board_info bfin_spi_board_info[] __initdata = {
+#if defined(CONFIG_MTD_M25P80) \
+ || defined(CONFIG_MTD_M25P80_MODULE)
+ {
+ /* the modalias must be the same as spi device driver name */
+ .modalias = "m25p80", /* Name of spi_driver for this device */
+ .max_speed_hz = 25000000,
+ /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0, /* Framework bus number */
+ .chip_select = EXP_GPIO_SPISEL_BASE + 0x04 + MAX_CTRL_CS,
+ /* Can be connected to TLL6527M GPIO connector */
+ /* Either SPI_ADC or M25P80 FLASH can be installed at a time */
+ .platform_data = &bfin_spi_flash_data,
+ .controller_data = &spi_flash_chip_info,
+ .mode = SPI_MODE_3,
+ },
+#endif
+
+#if defined(CONFIG_BFIN_SPI_ADC)
+ || defined(CONFIG_BFIN_SPI_ADC_MODULE)
+ {
+ .modalias = "bfin_spi_adc",
+ /* Name of spi_driver for this device */
+ .max_speed_hz = 10000000,
+ /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0, /* Framework bus number */
+ .chip_select = EXP_GPIO_SPISEL_BASE + 0x04 + MAX_CTRL_CS,
+ /* Framework chip select. */
+ .platform_data = NULL, /* No spi_driver specific config */
+ .controller_data = &spi_adc_chip_info,
+ .mode = SPI_MODE_0,
+ },
+#endif
+
+#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
+ {
+ .modalias = "mmc_spi",
+/*
+ * TLL6527M V1.0 does not support SD Card at SPI Clock > 10 MHz due to
+ * SPI buffer limitations
+ */
+ .max_speed_hz = 10000000,
+ /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = EXP_GPIO_SPISEL_BASE + 0x05 + MAX_CTRL_CS,
+ .controller_data = &mmc_spi_chip_info,
+ .mode = SPI_MODE_0,
+ },
+#endif
+#if defined(CONFIG_TOUCHSCREEN_AD7879_SPI) \
+ || defined(CONFIG_TOUCHSCREEN_AD7879_SPI_MODULE)
+ {
+ .modalias = "ad7879",
+ .platform_data = &bfin_ad7879_ts_info,
+ .irq = IRQ_PH14,
+ .max_speed_hz = 5000000,
+ /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = EXP_GPIO_SPISEL_BASE + 0x07 + MAX_CTRL_CS,
+ .controller_data = &spi_ad7879_chip_info,
+ .mode = SPI_CPHA | SPI_CPOL,
+ },
+#endif
+#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
+ {
+ .modalias = "spidev",
+ .max_speed_hz = 10000000,
+ /* TLL6527Mv1-0 supports max spi clock (SCK) speed = 10 MHz */
+ .bus_num = 0,
+ .chip_select = EXP_GPIO_SPISEL_BASE + 0x03 + MAX_CTRL_CS,
+ .mode = SPI_CPHA | SPI_CPOL,
+ .controller_data = &spidev_chip_info,
+ },
+#endif
+#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
+ {
+ .modalias = "bfin-lq035q1-spi",
+ .max_speed_hz = 20000000,
+ .bus_num = 0,
+ .chip_select = EXP_GPIO_SPISEL_BASE + 0x06 + MAX_CTRL_CS,
+ .controller_data = &lq035q1_spi_chip_info,
+ .mode = SPI_CPHA | SPI_CPOL,
+ },
+#endif
+#if defined(CONFIG_GPIO_MCP23S08) || defined(CONFIG_GPIO_MCP23S08_MODULE)
+ {
+ .modalias = "mcp23s08",
+ .platform_data = &bfin_mcp23s08_sys_gpio_info,
+ .max_speed_hz = 5000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = EXP_GPIO_SPISEL_BASE + 0x01 + MAX_CTRL_CS,
+ .controller_data = &spi_mcp23s08_sys_chip_info,
+ .mode = SPI_CPHA | SPI_CPOL,
+ },
+ {
+ .modalias = "mcp23s08",
+ .platform_data = &bfin_mcp23s08_usr_gpio_info,
+ .max_speed_hz = 5000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = EXP_GPIO_SPISEL_BASE + 0x02 + MAX_CTRL_CS,
+ .controller_data = &spi_mcp23s08_usr_chip_info,
+ .mode = SPI_CPHA | SPI_CPOL,
+ },
+#endif
+};
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+/* SPI controller data */
+static struct bfin5xx_spi_master bfin_spi0_info = {
+ .num_chipselect = EXP_GPIO_SPISEL_BASE + 8 + MAX_CTRL_CS,
+ /* EXP_GPIO_SPISEL_BASE will be > MAX_BLACKFIN_GPIOS */
+ .enable_dma = 1, /* master has the ability to do dma transfer */
+ .pin_req = {P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0},
+};
+
+/* SPI (0) */
+static struct resource bfin_spi0_resource[] = {
+ [0] = {
+ .start = SPI0_REGBASE,
+ .end = SPI0_REGBASE + 0xFF,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = CH_SPI,
+ .end = CH_SPI,
+ .flags = IORESOURCE_DMA,
+ },
+ [2] = {
+ .start = IRQ_SPI,
+ .end = IRQ_SPI,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device bfin_spi0_device = {
+ .name = "bfin-spi",
+ .id = 0, /* Bus number */
+ .num_resources = ARRAY_SIZE(bfin_spi0_resource),
+ .resource = bfin_spi0_resource,
+ .dev = {
+ .platform_data = &bfin_spi0_info, /* Passed to driver */
+ },
+};
+#endif /* spi master and devices */
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+#ifdef CONFIG_SERIAL_BFIN_UART0
+static struct resource bfin_uart0_resources[] = {
+ {
+ .start = UART0_THR,
+ .end = UART0_GCTL+2,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_UART0_RX,
+ .end = IRQ_UART0_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = IRQ_UART0_ERROR,
+ .end = IRQ_UART0_ERROR,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART0_TX,
+ .end = CH_UART0_TX,
+ .flags = IORESOURCE_DMA,
+ },
+ {
+ .start = CH_UART0_RX,
+ .end = CH_UART0_RX,
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+unsigned short bfin_uart0_peripherals[] = {
+ P_UART0_TX, P_UART0_RX, 0
+};
+
+static struct platform_device bfin_uart0_device = {
+ .name = "bfin-uart",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bfin_uart0_resources),
+ .resource = bfin_uart0_resources,
+ .dev = {
+ .platform_data = &bfin_uart0_peripherals,
+ /* Passed to driver */
+ },
+};
+#endif
+#ifdef CONFIG_SERIAL_BFIN_UART1
+static struct resource bfin_uart1_resources[] = {
+ {
+ .start = UART1_THR,
+ .end = UART1_GCTL+2,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_UART1_RX,
+ .end = IRQ_UART1_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = IRQ_UART1_ERROR,
+ .end = IRQ_UART1_ERROR,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART1_TX,
+ .end = CH_UART1_TX,
+ .flags = IORESOURCE_DMA,
+ },
+ {
+ .start = CH_UART1_RX,
+ .end = CH_UART1_RX,
+ .flags = IORESOURCE_DMA,
+ },
+#ifdef CONFIG_BFIN_UART1_CTSRTS
+ { /* CTS pin */
+ .start = GPIO_PF9,
+ .end = GPIO_PF9,
+ .flags = IORESOURCE_IO,
+ },
+ { /* RTS pin */
+ .start = GPIO_PF10,
+ .end = GPIO_PF10,
+ .flags = IORESOURCE_IO,
+ },
+#endif
+};
+
+unsigned short bfin_uart1_peripherals[] = {
+ P_UART1_TX, P_UART1_RX, 0
+};
+
+static struct platform_device bfin_uart1_device = {
+ .name = "bfin-uart",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(bfin_uart1_resources),
+ .resource = bfin_uart1_resources,
+ .dev = {
+ .platform_data = &bfin_uart1_peripherals,
+ /* Passed to driver */
+ },
+};
+#endif
+#endif
+
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+#ifdef CONFIG_BFIN_SIR0
+static struct resource bfin_sir0_resources[] = {
+ {
+ .start = 0xFFC00400,
+ .end = 0xFFC004FF,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_UART0_RX,
+ .end = IRQ_UART0_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART0_RX,
+ .end = CH_UART0_RX+1,
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+static struct platform_device bfin_sir0_device = {
+ .name = "bfin_sir",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bfin_sir0_resources),
+ .resource = bfin_sir0_resources,
+};
+#endif
+#ifdef CONFIG_BFIN_SIR1
+static struct resource bfin_sir1_resources[] = {
+ {
+ .start = 0xFFC02000,
+ .end = 0xFFC020FF,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_UART1_RX,
+ .end = IRQ_UART1_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART1_RX,
+ .end = CH_UART1_RX+1,
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+static struct platform_device bfin_sir1_device = {
+ .name = "bfin_sir",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(bfin_sir1_resources),
+ .resource = bfin_sir1_resources,
+};
+#endif
+#endif
+
+#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+static struct resource bfin_twi0_resource[] = {
+ [0] = {
+ .start = TWI0_REGBASE,
+ .end = TWI0_REGBASE,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_TWI,
+ .end = IRQ_TWI,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device i2c_bfin_twi_device = {
+ .name = "i2c-bfin-twi",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bfin_twi0_resource),
+ .resource = bfin_twi0_resource,
+};
+#endif
+
+static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
+#if defined(CONFIG_BFIN_TWI_LCD) || defined(CONFIG_BFIN_TWI_LCD_MODULE)
+ {
+ I2C_BOARD_INFO("pcf8574_lcd", 0x22),
+ },
+#endif
+
+#if defined(CONFIG_FB_BFIN_7393) || defined(CONFIG_FB_BFIN_7393_MODULE)
+ {
+ I2C_BOARD_INFO("bfin-adv7393", 0x2B),
+ },
+#endif
+#if defined(CONFIG_TOUCHSCREEN_AD7879_I2C) \
+ || defined(CONFIG_TOUCHSCREEN_AD7879_I2C_MODULE)
+ {
+ I2C_BOARD_INFO("ad7879", 0x2C),
+ .irq = IRQ_PH14,
+ .platform_data = (void *)&bfin_ad7879_ts_info,
+ },
+#endif
+#if defined(CONFIG_SND_SOC_SSM2602) || defined(CONFIG_SND_SOC_SSM2602_MODULE)
+ {
+ I2C_BOARD_INFO("ssm2602", 0x1b),
+ },
+#endif
+ {
+ I2C_BOARD_INFO("adm1192", 0x2e),
+ },
+
+ {
+ I2C_BOARD_INFO("ltc3576", 0x09),
+ },
+#if defined(CONFIG_INPUT_ADXL34X_I2C) \
+ || defined(CONFIG_INPUT_ADXL34X_I2C_MODULE)
+ {
+ I2C_BOARD_INFO("adxl34x", 0x53),
+ .irq = IRQ_PH13,
+ .platform_data = (void *)&adxl345_info,
+ },
+#endif
+};
+
+#if defined(CONFIG_SERIAL_BFIN_SPORT) \
+ || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
+#ifdef CONFIG_SERIAL_BFIN_SPORT0_UART
+static struct resource bfin_sport0_uart_resources[] = {
+ {
+ .start = SPORT0_TCR1,
+ .end = SPORT0_MRCS3+4,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_SPORT0_RX,
+ .end = IRQ_SPORT0_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = IRQ_SPORT0_ERROR,
+ .end = IRQ_SPORT0_ERROR,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+unsigned short bfin_sport0_peripherals[] = {
+ P_SPORT0_TFS, P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
+ P_SPORT0_DRPRI, P_SPORT0_RSCLK, P_SPORT0_DRSEC, P_SPORT0_DTSEC, 0
+};
+
+static struct platform_device bfin_sport0_uart_device = {
+ .name = "bfin-sport-uart",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bfin_sport0_uart_resources),
+ .resource = bfin_sport0_uart_resources,
+ .dev = {
+ .platform_data = &bfin_sport0_peripherals,
+ /* Passed to driver */
+ },
+};
+#endif
+#ifdef CONFIG_SERIAL_BFIN_SPORT1_UART
+static struct resource bfin_sport1_uart_resources[] = {
+ {
+ .start = SPORT1_TCR1,
+ .end = SPORT1_MRCS3+4,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_SPORT1_RX,
+ .end = IRQ_SPORT1_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = IRQ_SPORT1_ERROR,
+ .end = IRQ_SPORT1_ERROR,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+unsigned short bfin_sport1_peripherals[] = {
+ P_SPORT1_TFS, P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS,
+ P_SPORT1_DRPRI, P_SPORT1_RSCLK, P_SPORT1_DRSEC, P_SPORT1_DTSEC, 0
+};
+
+static struct platform_device bfin_sport1_uart_device = {
+ .name = "bfin-sport-uart",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(bfin_sport1_uart_resources),
+ .resource = bfin_sport1_uart_resources,
+ .dev = {
+ .platform_data = &bfin_sport1_peripherals,
+ /* Passed to driver */
+ },
+};
+#endif
+#endif
+
+static const unsigned int cclk_vlev_datasheet[] = {
+ VRPAIR(VLEV_100, 400000000),
+ VRPAIR(VLEV_105, 426000000),
+ VRPAIR(VLEV_110, 500000000),
+ VRPAIR(VLEV_115, 533000000),
+ VRPAIR(VLEV_120, 600000000),
+};
+
+static struct bfin_dpmc_platform_data bfin_dmpc_vreg_data = {
+ .tuple_tab = cclk_vlev_datasheet,
+ .tabsize = ARRAY_SIZE(cclk_vlev_datasheet),
+ .vr_settling_time = 25 /* us */,
+};
+
+static struct platform_device bfin_dpmc = {
+ .name = "bfin dpmc",
+ .dev = {
+ .platform_data = &bfin_dmpc_vreg_data,
+ },
+};
+
+static struct platform_device *tll6527m_devices[] __initdata = {
+
+ &bfin_dpmc,
+
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+ &rtc_device,
+#endif
+
+#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE)
+ &musb_device,
+#endif
+
+#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+ &bfin_mii_bus,
+ &bfin_mac_device,
+#endif
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+ &bfin_spi0_device,
+#endif
+
+#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
+ &bfin_lq035q1_device,
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+#ifdef CONFIG_SERIAL_BFIN_UART0
+ &bfin_uart0_device,
+#endif
+#ifdef CONFIG_SERIAL_BFIN_UART1
+ &bfin_uart1_device,
+#endif
+#endif
+
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+#ifdef CONFIG_BFIN_SIR0
+ &bfin_sir0_device,
+#endif
+#ifdef CONFIG_BFIN_SIR1
+ &bfin_sir1_device,
+#endif
+#endif
+
+#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+ &i2c_bfin_twi_device,
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN_SPORT) \
+ || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
+#ifdef CONFIG_SERIAL_BFIN_SPORT0_UART
+ &bfin_sport0_uart_device,
+#endif
+#ifdef CONFIG_SERIAL_BFIN_SPORT1_UART
+ &bfin_sport1_uart_device,
+#endif
+#endif
+
+#if defined(CONFIG_MTD_GPIO_ADDR) || defined(CONFIG_MTD_GPIO_ADDR_MODULE)
+ &tll6527m_flash_device,
+#endif
+
+#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE)
+ &bfin_i2s,
+#endif
+
+#if defined(CONFIG_GPIO_DECODER) || defined(CONFIG_GPIO_DECODER_MODULE)
+ &spi_decoded_gpio,
+#endif
+};
+
+static int __init tll6527m_init(void)
+{
+ printk(KERN_INFO "%s(): registering device resources\n", __func__);
+ i2c_register_board_info(0, bfin_i2c_board_info,
+ ARRAY_SIZE(bfin_i2c_board_info));
+ platform_add_devices(tll6527m_devices, ARRAY_SIZE(tll6527m_devices));
+ spi_register_board_info(bfin_spi_board_info,
+ ARRAY_SIZE(bfin_spi_board_info));
+ return 0;
+}
+
+arch_initcall(tll6527m_init);
+
+static struct platform_device *tll6527m_early_devices[] __initdata = {
+#if defined(CONFIG_SERIAL_BFIN_CONSOLE) || defined(CONFIG_EARLY_PRINTK)
+#ifdef CONFIG_SERIAL_BFIN_UART0
+ &bfin_uart0_device,
+#endif
+#ifdef CONFIG_SERIAL_BFIN_UART1
+ &bfin_uart1_device,
+#endif
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN_SPORT_CONSOLE)
+#ifdef CONFIG_SERIAL_BFIN_SPORT0_UART
+ &bfin_sport0_uart_device,
+#endif
+#ifdef CONFIG_SERIAL_BFIN_SPORT1_UART
+ &bfin_sport1_uart_device,
+#endif
+#endif
+};
+
+void __init native_machine_early_platform_add_devices(void)
+{
+ printk(KERN_INFO "register early platform devices\n");
+ early_platform_add_devices(tll6527m_early_devices,
+ ARRAY_SIZE(tll6527m_early_devices));
+}
+
+void native_machine_restart(char *cmd)
+{
+ /* workaround reboot hang when booting from SPI */
+ if ((bfin_read_SYSCR() & 0x7) == 0x3)
+ bfin_reset_boot_spi_cs(P_DEFAULT_BOOT_SPI_CS);
+}
+
+void bfin_get_ether_addr(char *addr)
+{
+ /* the MAC is stored in OTP memory page 0xDF */
+ u32 ret;
+ u64 otp_mac;
+ u32 (*otp_read)(u32 page, u32 flags,
+ u64 *page_content) = (void *)0xEF00001A;
+
+ ret = otp_read(0xDF, 0x00, &otp_mac);
+ if (!(ret & 0x1)) {
+ char *otp_mac_p = (char *)&otp_mac;
+ for (ret = 0; ret < 6; ++ret)
+ addr[ret] = otp_mac_p[5 - ret];
+ }
+}
+EXPORT_SYMBOL(bfin_get_ether_addr);
diff --git a/arch/blackfin/mach-bf527/include/mach/cdefBF52x_base.h b/arch/blackfin/mach-bf527/include/mach/cdefBF52x_base.h
index 12f2ad45314e..3048b52bf46a 100644
--- a/arch/blackfin/mach-bf527/include/mach/cdefBF52x_base.h
+++ b/arch/blackfin/mach-bf527/include/mach/cdefBF52x_base.h
@@ -279,14 +279,14 @@
#define bfin_write_SPORT0_TX(val) bfin_write32(SPORT0_TX, val)
#define bfin_read_SPORT0_RX() bfin_read32(SPORT0_RX)
#define bfin_write_SPORT0_RX(val) bfin_write32(SPORT0_RX, val)
-#define bfin_read_SPORT0_TX32() bfin_read32(SPORT0_TX32)
-#define bfin_write_SPORT0_TX32(val) bfin_write32(SPORT0_TX32, val)
-#define bfin_read_SPORT0_RX32() bfin_read32(SPORT0_RX32)
-#define bfin_write_SPORT0_RX32(val) bfin_write32(SPORT0_RX32, val)
-#define bfin_read_SPORT0_TX16() bfin_read16(SPORT0_TX16)
-#define bfin_write_SPORT0_TX16(val) bfin_write16(SPORT0_TX16, val)
-#define bfin_read_SPORT0_RX16() bfin_read16(SPORT0_RX16)
-#define bfin_write_SPORT0_RX16(val) bfin_write16(SPORT0_RX16, val)
+#define bfin_read_SPORT0_TX32() bfin_read32(SPORT0_TX)
+#define bfin_write_SPORT0_TX32(val) bfin_write32(SPORT0_TX, val)
+#define bfin_read_SPORT0_RX32() bfin_read32(SPORT0_RX)
+#define bfin_write_SPORT0_RX32(val) bfin_write32(SPORT0_RX, val)
+#define bfin_read_SPORT0_TX16() bfin_read16(SPORT0_TX)
+#define bfin_write_SPORT0_TX16(val) bfin_write16(SPORT0_TX, val)
+#define bfin_read_SPORT0_RX16() bfin_read16(SPORT0_RX)
+#define bfin_write_SPORT0_RX16(val) bfin_write16(SPORT0_RX, val)
#define bfin_read_SPORT0_RCR1() bfin_read16(SPORT0_RCR1)
#define bfin_write_SPORT0_RCR1(val) bfin_write16(SPORT0_RCR1, val)
#define bfin_read_SPORT0_RCR2() bfin_read16(SPORT0_RCR2)
@@ -334,14 +334,14 @@
#define bfin_write_SPORT1_TX(val) bfin_write32(SPORT1_TX, val)
#define bfin_read_SPORT1_RX() bfin_read32(SPORT1_RX)
#define bfin_write_SPORT1_RX(val) bfin_write32(SPORT1_RX, val)
-#define bfin_read_SPORT1_TX32() bfin_read32(SPORT1_TX32)
-#define bfin_write_SPORT1_TX32(val) bfin_write32(SPORT1_TX32, val)
-#define bfin_read_SPORT1_RX32() bfin_read32(SPORT1_RX32)
-#define bfin_write_SPORT1_RX32(val) bfin_write32(SPORT1_RX32, val)
-#define bfin_read_SPORT1_TX16() bfin_read16(SPORT1_TX16)
-#define bfin_write_SPORT1_TX16(val) bfin_write16(SPORT1_TX16, val)
-#define bfin_read_SPORT1_RX16() bfin_read16(SPORT1_RX16)
-#define bfin_write_SPORT1_RX16(val) bfin_write16(SPORT1_RX16, val)
+#define bfin_read_SPORT1_TX32() bfin_read32(SPORT1_TX)
+#define bfin_write_SPORT1_TX32(val) bfin_write32(SPORT1_TX, val)
+#define bfin_read_SPORT1_RX32() bfin_read32(SPORT1_RX)
+#define bfin_write_SPORT1_RX32(val) bfin_write32(SPORT1_RX, val)
+#define bfin_read_SPORT1_TX16() bfin_read16(SPORT1_TX)
+#define bfin_write_SPORT1_TX16(val) bfin_write16(SPORT1_TX, val)
+#define bfin_read_SPORT1_RX16() bfin_read16(SPORT1_RX)
+#define bfin_write_SPORT1_RX16(val) bfin_write16(SPORT1_RX, val)
#define bfin_read_SPORT1_RCR1() bfin_read16(SPORT1_RCR1)
#define bfin_write_SPORT1_RCR1(val) bfin_write16(SPORT1_RCR1, val)
#define bfin_read_SPORT1_RCR2() bfin_read16(SPORT1_RCR2)
@@ -1110,54 +1110,4 @@
/* These need to be last due to the cdef/linux inter-dependencies */
#include <asm/irq.h>
-/* Writing to PLL_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_PLL_CTL(unsigned int val)
-{
- unsigned long flags, iwr0, iwr1;
-
- if (val == bfin_read_PLL_CTL())
- return;
-
- local_irq_save_hw(flags);
- /* Enable the PLL Wakeup bit in SIC IWR */
- iwr0 = bfin_read32(SIC_IWR0);
- iwr1 = bfin_read32(SIC_IWR1);
- /* Only allow PPL Wakeup) */
- bfin_write32(SIC_IWR0, IWR_ENABLE(0));
- bfin_write32(SIC_IWR1, 0);
-
- bfin_write16(PLL_CTL, val);
- SSYNC();
- asm("IDLE;");
-
- bfin_write32(SIC_IWR0, iwr0);
- bfin_write32(SIC_IWR1, iwr1);
- local_irq_restore_hw(flags);
-}
-
-/* Writing to VR_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_VR_CTL(unsigned int val)
-{
- unsigned long flags, iwr0, iwr1;
-
- if (val == bfin_read_VR_CTL())
- return;
-
- local_irq_save_hw(flags);
- /* Enable the PLL Wakeup bit in SIC IWR */
- iwr0 = bfin_read32(SIC_IWR0);
- iwr1 = bfin_read32(SIC_IWR1);
- /* Only allow PPL Wakeup) */
- bfin_write32(SIC_IWR0, IWR_ENABLE(0));
- bfin_write32(SIC_IWR1, 0);
-
- bfin_write16(VR_CTL, val);
- SSYNC();
- asm("IDLE;");
-
- bfin_write32(SIC_IWR0, iwr0);
- bfin_write32(SIC_IWR1, iwr1);
- local_irq_restore_hw(flags);
-}
-
#endif /* _CDEF_BF52X_H */
diff --git a/arch/blackfin/mach-bf527/include/mach/defBF52x_base.h b/arch/blackfin/mach-bf527/include/mach/defBF52x_base.h
index 3e000756aacd..09475034c6a1 100644
--- a/arch/blackfin/mach-bf527/include/mach/defBF52x_base.h
+++ b/arch/blackfin/mach-bf527/include/mach/defBF52x_base.h
@@ -749,51 +749,6 @@
#define FFE 0x20 /* Force Framing Error On Transmit */
-/* *********** SERIAL PERIPHERAL INTERFACE (SPI) MASKS ****************************/
-/* SPI_CTL Masks */
-#define TIMOD 0x0003 /* Transfer Initiate Mode */
-#define RDBR_CORE 0x0000 /* RDBR Read Initiates, IRQ When RDBR Full */
-#define TDBR_CORE 0x0001 /* TDBR Write Initiates, IRQ When TDBR Empty */
-#define RDBR_DMA 0x0002 /* DMA Read, DMA Until FIFO Empty */
-#define TDBR_DMA 0x0003 /* DMA Write, DMA Until FIFO Full */
-#define SZ 0x0004 /* Send Zero (When TDBR Empty, Send Zero/Last*) */
-#define GM 0x0008 /* Get More (When RDBR Full, Overwrite/Discard*) */
-#define PSSE 0x0010 /* Slave-Select Input Enable */
-#define EMISO 0x0020 /* Enable MISO As Output */
-#define SIZE 0x0100 /* Size of Words (16/8* Bits) */
-#define LSBF 0x0200 /* LSB First */
-#define CPHA 0x0400 /* Clock Phase */
-#define CPOL 0x0800 /* Clock Polarity */
-#define MSTR 0x1000 /* Master/Slave* */
-#define WOM 0x2000 /* Write Open Drain Master */
-#define SPE 0x4000 /* SPI Enable */
-
-/* SPI_FLG Masks */
-#define FLS1 0x0002 /* Enables SPI_FLOUT1 as SPI Slave-Select Output */
-#define FLS2 0x0004 /* Enables SPI_FLOUT2 as SPI Slave-Select Output */
-#define FLS3 0x0008 /* Enables SPI_FLOUT3 as SPI Slave-Select Output */
-#define FLS4 0x0010 /* Enables SPI_FLOUT4 as SPI Slave-Select Output */
-#define FLS5 0x0020 /* Enables SPI_FLOUT5 as SPI Slave-Select Output */
-#define FLS6 0x0040 /* Enables SPI_FLOUT6 as SPI Slave-Select Output */
-#define FLS7 0x0080 /* Enables SPI_FLOUT7 as SPI Slave-Select Output */
-#define FLG1 0xFDFF /* Activates SPI_FLOUT1 */
-#define FLG2 0xFBFF /* Activates SPI_FLOUT2 */
-#define FLG3 0xF7FF /* Activates SPI_FLOUT3 */
-#define FLG4 0xEFFF /* Activates SPI_FLOUT4 */
-#define FLG5 0xDFFF /* Activates SPI_FLOUT5 */
-#define FLG6 0xBFFF /* Activates SPI_FLOUT6 */
-#define FLG7 0x7FFF /* Activates SPI_FLOUT7 */
-
-/* SPI_STAT Masks */
-#define SPIF 0x0001 /* SPI Finished (Single-Word Transfer Complete) */
-#define MODF 0x0002 /* Mode Fault Error (Another Device Tried To Become Master) */
-#define TXE 0x0004 /* Transmission Error (Data Sent With No New Data In TDBR) */
-#define TXS 0x0008 /* SPI_TDBR Data Buffer Status (Full/Empty*) */
-#define RBSY 0x0010 /* Receive Error (Data Received With RDBR Full) */
-#define RXS 0x0020 /* SPI_RDBR Data Buffer Status (Full/Empty*) */
-#define TXCOL 0x0040 /* Transmit Collision Error (Corrupt Data May Have Been Sent) */
-
-
/* **************** GENERAL PURPOSE TIMER MASKS **********************/
/* TIMER_ENABLE Masks */
#define TIMEN0 0x0001 /* Enable Timer 0 */
diff --git a/arch/blackfin/mach-bf527/include/mach/pll.h b/arch/blackfin/mach-bf527/include/mach/pll.h
new file mode 100644
index 000000000000..24f1d7c02325
--- /dev/null
+++ b/arch/blackfin/mach-bf527/include/mach/pll.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2007-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later
+ */
+
+#ifndef _MACH_PLL_H
+#define _MACH_PLL_H
+
+#include <asm/blackfin.h>
+#include <asm/irqflags.h>
+
+/* Writing to PLL_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_PLL_CTL(unsigned int val)
+{
+ unsigned long flags, iwr0, iwr1;
+
+ if (val == bfin_read_PLL_CTL())
+ return;
+
+ flags = hard_local_irq_save();
+ /* Enable the PLL Wakeup bit in SIC IWR */
+ iwr0 = bfin_read32(SIC_IWR0);
+ iwr1 = bfin_read32(SIC_IWR1);
+ /* Only allow PPL Wakeup) */
+ bfin_write32(SIC_IWR0, IWR_ENABLE(0));
+ bfin_write32(SIC_IWR1, 0);
+
+ bfin_write16(PLL_CTL, val);
+ SSYNC();
+ asm("IDLE;");
+
+ bfin_write32(SIC_IWR0, iwr0);
+ bfin_write32(SIC_IWR1, iwr1);
+ hard_local_irq_restore(flags);
+}
+
+/* Writing to VR_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_VR_CTL(unsigned int val)
+{
+ unsigned long flags, iwr0, iwr1;
+
+ if (val == bfin_read_VR_CTL())
+ return;
+
+ flags = hard_local_irq_save();
+ /* Enable the PLL Wakeup bit in SIC IWR */
+ iwr0 = bfin_read32(SIC_IWR0);
+ iwr1 = bfin_read32(SIC_IWR1);
+ /* Only allow PPL Wakeup) */
+ bfin_write32(SIC_IWR0, IWR_ENABLE(0));
+ bfin_write32(SIC_IWR1, 0);
+
+ bfin_write16(VR_CTL, val);
+ SSYNC();
+ asm("IDLE;");
+
+ bfin_write32(SIC_IWR0, iwr0);
+ bfin_write32(SIC_IWR1, iwr1);
+ hard_local_irq_restore(flags);
+}
+
+#endif /* _MACH_PLL_H */
diff --git a/arch/blackfin/mach-bf533/boards/H8606.c b/arch/blackfin/mach-bf533/boards/H8606.c
index 175371af0692..2ce7b16faee1 100644
--- a/arch/blackfin/mach-bf533/boards/H8606.c
+++ b/arch/blackfin/mach-bf533/boards/H8606.c
@@ -171,7 +171,7 @@ static struct bfin5xx_spi_chip spi_adc_chip_info = {
};
#endif
-#if defined(CONFIG_SND_BLACKFIN_AD183X) || defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
.enable_dma = 0,
.bits_per_word = 16,
@@ -206,12 +206,12 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
},
#endif
-#if defined(CONFIG_SND_BLACKFIN_AD183X) || defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
{
- .modalias = "ad1836",
+ .modalias = "ad183x",
.max_speed_hz = 16,
.bus_num = 1,
- .chip_select = CONFIG_SND_BLACKFIN_SPI_PFBIT,
+ .chip_select = 4,
.controller_data = &ad1836_spi_chip_info,
},
#endif
@@ -347,6 +347,7 @@ static struct plat_serial8250_port serial8250_platform_data [] = {
.membase = (void *)0x20200000,
.mapbase = 0x20200000,
.irq = IRQ_PF8,
+ .irqflags = IRQF_TRIGGER_HIGH,
.flags = UPF_BOOT_AUTOCONF | UART_CONFIG_TYPE,
.iotype = UPIO_MEM,
.regshift = 1,
@@ -355,6 +356,7 @@ static struct plat_serial8250_port serial8250_platform_data [] = {
.membase = (void *)0x20200010,
.mapbase = 0x20200010,
.irq = IRQ_PF8,
+ .irqflags = IRQF_TRIGGER_HIGH,
.flags = UPF_BOOT_AUTOCONF | UART_CONFIG_TYPE,
.iotype = UPIO_MEM,
.regshift = 1,
diff --git a/arch/blackfin/mach-bf533/boards/blackstamp.c b/arch/blackfin/mach-bf533/boards/blackstamp.c
index 842b4fa76ea9..20c102285bef 100644
--- a/arch/blackfin/mach-bf533/boards/blackstamp.c
+++ b/arch/blackfin/mach-bf533/boards/blackstamp.c
@@ -25,6 +25,7 @@
#include <asm/bfin5xx_spi.h>
#include <asm/portmux.h>
#include <asm/dpmc.h>
+#include <mach/fio_flag.h>
/*
* Name the Board for the /proc/cpuinfo
@@ -367,8 +368,8 @@ static struct platform_device bfin_device_gpiokeys = {
#include <linux/i2c-gpio.h>
static struct i2c_gpio_platform_data i2c_gpio_data = {
- .sda_pin = 8,
- .scl_pin = 9,
+ .sda_pin = GPIO_PF8,
+ .scl_pin = GPIO_PF9,
.sda_is_open_drain = 0,
.scl_is_open_drain = 0,
.udelay = 40,
diff --git a/arch/blackfin/mach-bf533/boards/cm_bf533.c b/arch/blackfin/mach-bf533/boards/cm_bf533.c
index fdcde61906dc..adbe62a81e25 100644
--- a/arch/blackfin/mach-bf533/boards/cm_bf533.c
+++ b/arch/blackfin/mach-bf533/boards/cm_bf533.c
@@ -71,7 +71,7 @@ static struct bfin5xx_spi_chip spi_adc_chip_info = {
};
#endif
-#if defined(CONFIG_SND_BLACKFIN_AD183X) || defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
.enable_dma = 0,
.bits_per_word = 16,
@@ -110,12 +110,12 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
},
#endif
-#if defined(CONFIG_SND_BLACKFIN_AD183X) || defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
{
- .modalias = "ad1836",
+ .modalias = "ad183x",
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
- .chip_select = CONFIG_SND_BLACKFIN_SPI_PFBIT,
+ .chip_select = 4,
.controller_data = &ad1836_spi_chip_info,
},
#endif
@@ -400,7 +400,7 @@ static struct resource isp1362_hcd_resources[] = {
}, {
.start = IRQ_PF4,
.end = IRQ_PF4,
- .flags = IORESOURCE_IRQ,
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
},
};
diff --git a/arch/blackfin/mach-bf533/boards/ezkit.c b/arch/blackfin/mach-bf533/boards/ezkit.c
index 739773cb7fc6..a1cb8e7c1010 100644
--- a/arch/blackfin/mach-bf533/boards/ezkit.c
+++ b/arch/blackfin/mach-bf533/boards/ezkit.c
@@ -222,7 +222,7 @@ static struct bfin5xx_spi_chip spi_adc_chip_info = {
};
#endif
-#if defined(CONFIG_SND_BLACKFIN_AD183X) || defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
.enable_dma = 0,
.bits_per_word = 16,
@@ -261,12 +261,12 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
},
#endif
-#if defined(CONFIG_SND_BLACKFIN_AD183X) || defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
{
- .modalias = "ad1836",
+ .modalias = "ad183x",
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
- .chip_select = CONFIG_SND_BLACKFIN_SPI_PFBIT,
+ .chip_select = 4,
.controller_data = &ad1836_spi_chip_info,
},
#endif
@@ -422,8 +422,8 @@ static struct platform_device bfin_device_gpiokeys = {
#include <linux/i2c-gpio.h>
static struct i2c_gpio_platform_data i2c_gpio_data = {
- .sda_pin = 1,
- .scl_pin = 0,
+ .sda_pin = GPIO_PF1,
+ .scl_pin = GPIO_PF0,
.sda_is_open_drain = 0,
.scl_is_open_drain = 0,
.udelay = 40,
diff --git a/arch/blackfin/mach-bf533/boards/ip0x.c b/arch/blackfin/mach-bf533/boards/ip0x.c
index 7349970db978..5ba4b02a12eb 100644
--- a/arch/blackfin/mach-bf533/boards/ip0x.c
+++ b/arch/blackfin/mach-bf533/boards/ip0x.c
@@ -22,6 +22,7 @@
#include <asm/dma.h>
#include <asm/bfin5xx_spi.h>
#include <asm/portmux.h>
+#include <mach/fio_flag.h>
/*
* Name the Board for the /proc/cpuinfo
@@ -231,7 +232,7 @@ static struct resource isp1362_hcd_resources[] = {
},{
.start = IRQ_PF11,
.end = IRQ_PF11,
- .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
},
};
diff --git a/arch/blackfin/mach-bf533/boards/stamp.c b/arch/blackfin/mach-bf533/boards/stamp.c
index c457eaa60239..b3b1cdea2703 100644
--- a/arch/blackfin/mach-bf533/boards/stamp.c
+++ b/arch/blackfin/mach-bf533/boards/stamp.c
@@ -24,6 +24,7 @@
#include <asm/reboot.h>
#include <asm/portmux.h>
#include <asm/dpmc.h>
+#include <mach/fio_flag.h>
/*
* Name the Board for the /proc/cpuinfo
@@ -184,7 +185,7 @@ static struct bfin5xx_spi_chip spi_adc_chip_info = {
};
#endif
-#if defined(CONFIG_SND_BLACKFIN_AD183X) || defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
.enable_dma = 0,
.bits_per_word = 16,
@@ -251,13 +252,15 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
},
#endif
-#if defined(CONFIG_SND_BLACKFIN_AD183X) || defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
{
- .modalias = "ad1836",
+ .modalias = "ad183x",
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
- .chip_select = CONFIG_SND_BLACKFIN_SPI_PFBIT,
+ .chip_select = 4,
+ .platform_data = "ad1836", /* only includes chip name for the moment */
.controller_data = &ad1836_spi_chip_info,
+ .mode = SPI_MODE_3,
},
#endif
@@ -494,8 +497,8 @@ static struct platform_device bfin_device_gpiokeys = {
#include <linux/i2c-gpio.h>
static struct i2c_gpio_platform_data i2c_gpio_data = {
- .sda_pin = 2,
- .scl_pin = 3,
+ .sda_pin = GPIO_PF2,
+ .scl_pin = GPIO_PF3,
.sda_is_open_drain = 0,
.scl_is_open_drain = 0,
.udelay = 40,
@@ -533,6 +536,11 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
I2C_BOARD_INFO("bfin-adv7393", 0x2B),
},
#endif
+#if defined(CONFIG_BFIN_TWI_LCD) || defined(CONFIG_BFIN_TWI_LCD_MODULE)
+ {
+ I2C_BOARD_INFO("ad5252", 0x2f),
+ },
+#endif
};
static const unsigned int cclk_vlev_datasheet[] =
diff --git a/arch/blackfin/mach-bf533/include/mach/cdefBF532.h b/arch/blackfin/mach-bf533/include/mach/cdefBF532.h
index feb2392c43ea..401e524f5321 100644
--- a/arch/blackfin/mach-bf533/include/mach/cdefBF532.h
+++ b/arch/blackfin/mach-bf533/include/mach/cdefBF532.h
@@ -7,11 +7,6 @@
#ifndef _CDEF_BF532_H
#define _CDEF_BF532_H
-#include <asm/blackfin.h>
-
-/*include all Core registers and bit definitions*/
-#include "defBF532.h"
-
/*include core specific register pointer definitions*/
#include <asm/cdef_LPBlackfin.h>
@@ -655,90 +650,4 @@
/* These need to be last due to the cdef/linux inter-dependencies */
#include <asm/irq.h>
-#if ANOMALY_05000311
-#define BFIN_WRITE_FIO_FLAG(name) \
-static inline void bfin_write_FIO_FLAG_##name(unsigned short val) \
-{ \
- unsigned long flags; \
- local_irq_save_hw(flags); \
- bfin_write16(FIO_FLAG_##name, val); \
- bfin_read_CHIPID(); \
- local_irq_restore_hw(flags); \
-}
-BFIN_WRITE_FIO_FLAG(D)
-BFIN_WRITE_FIO_FLAG(C)
-BFIN_WRITE_FIO_FLAG(S)
-BFIN_WRITE_FIO_FLAG(T)
-
-#define BFIN_READ_FIO_FLAG(name) \
-static inline u16 bfin_read_FIO_FLAG_##name(void) \
-{ \
- unsigned long flags; \
- u16 ret; \
- local_irq_save_hw(flags); \
- ret = bfin_read16(FIO_FLAG_##name); \
- bfin_read_CHIPID(); \
- local_irq_restore_hw(flags); \
- return ret; \
-}
-BFIN_READ_FIO_FLAG(D)
-BFIN_READ_FIO_FLAG(C)
-BFIN_READ_FIO_FLAG(S)
-BFIN_READ_FIO_FLAG(T)
-
-#else
-#define bfin_write_FIO_FLAG_D(val) bfin_write16(FIO_FLAG_D, val)
-#define bfin_write_FIO_FLAG_C(val) bfin_write16(FIO_FLAG_C, val)
-#define bfin_write_FIO_FLAG_S(val) bfin_write16(FIO_FLAG_S, val)
-#define bfin_write_FIO_FLAG_T(val) bfin_write16(FIO_FLAG_T, val)
-#define bfin_read_FIO_FLAG_T() bfin_read16(FIO_FLAG_T)
-#define bfin_read_FIO_FLAG_C() bfin_read16(FIO_FLAG_C)
-#define bfin_read_FIO_FLAG_S() bfin_read16(FIO_FLAG_S)
-#define bfin_read_FIO_FLAG_D() bfin_read16(FIO_FLAG_D)
-#endif
-
-/* Writing to PLL_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_PLL_CTL(unsigned int val)
-{
- unsigned long flags, iwr;
-
- if (val == bfin_read_PLL_CTL())
- return;
-
- local_irq_save_hw(flags);
- /* Enable the PLL Wakeup bit in SIC IWR */
- iwr = bfin_read32(SIC_IWR);
- /* Only allow PPL Wakeup) */
- bfin_write32(SIC_IWR, IWR_ENABLE(0));
-
- bfin_write16(PLL_CTL, val);
- SSYNC();
- asm("IDLE;");
-
- bfin_write32(SIC_IWR, iwr);
- local_irq_restore_hw(flags);
-}
-
-/* Writing to VR_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_VR_CTL(unsigned int val)
-{
- unsigned long flags, iwr;
-
- if (val == bfin_read_VR_CTL())
- return;
-
- local_irq_save_hw(flags);
- /* Enable the PLL Wakeup bit in SIC IWR */
- iwr = bfin_read32(SIC_IWR);
- /* Only allow PPL Wakeup) */
- bfin_write32(SIC_IWR, IWR_ENABLE(0));
-
- bfin_write16(VR_CTL, val);
- SSYNC();
- asm("IDLE;");
-
- bfin_write32(SIC_IWR, iwr);
- local_irq_restore_hw(flags);
-}
-
#endif /* _CDEF_BF532_H */
diff --git a/arch/blackfin/mach-bf533/include/mach/defBF532.h b/arch/blackfin/mach-bf533/include/mach/defBF532.h
index 04acf1ed10f9..3adb0b44e597 100644
--- a/arch/blackfin/mach-bf533/include/mach/defBF532.h
+++ b/arch/blackfin/mach-bf533/include/mach/defBF532.h
@@ -681,76 +681,6 @@
#define PF14_P 14
#define PF15_P 15
-/* *********** SERIAL PERIPHERAL INTERFACE (SPI) MASKS **************** */
-
-/* SPI_CTL Masks */
-#define TIMOD 0x00000003 /* Transfer initiation mode and interrupt generation */
-#define RDBR_CORE 0x0000 /* RDBR Read Initiates, IRQ When RDBR Full */
-#define TDBR_CORE 0x0001 /* TDBR Write Initiates, IRQ When TDBR Empty */
-#define RDBR_DMA 0x0002 /* DMA Read, DMA Until FIFO Empty */
-#define TDBR_DMA 0x0003 /* DMA Write, DMA Until FIFO Full */
-#define SZ 0x00000004 /* Send Zero (=0) or last (=1) word when TDBR empty. */
-#define GM 0x00000008 /* When RDBR full, get more (=1) data or discard (=0) incoming Data */
-#define PSSE 0x00000010 /* Enable (=1) Slave-Select input for Master. */
-#define EMISO 0x00000020 /* Enable (=1) MISO pin as an output. */
-#define SIZE 0x00000100 /* Word length (0 => 8 bits, 1 => 16 bits) */
-#define LSBF 0x00000200 /* Data format (0 => MSB sent/received first 1 => LSB sent/received first) */
-#define CPHA 0x00000400 /* Clock phase (0 => SPICLK starts toggling in middle of xfer, 1 => SPICLK toggles at the beginning of xfer. */
-#define CPOL 0x00000800 /* Clock polarity (0 => active-high, 1 => active-low) */
-#define MSTR 0x00001000 /* Configures SPI as master (=1) or slave (=0) */
-#define WOM 0x00002000 /* Open drain (=1) data output enable (for MOSI and MISO) */
-#define SPE 0x00004000 /* SPI module enable (=1), disable (=0) */
-
-/* SPI_FLG Masks */
-#define FLS1 0x00000002 /* Enables (=1) SPI_FLOUT1 as flag output for SPI Slave-select */
-#define FLS2 0x00000004 /* Enables (=1) SPI_FLOUT2 as flag output for SPI Slave-select */
-#define FLS3 0x00000008 /* Enables (=1) SPI_FLOUT3 as flag output for SPI Slave-select */
-#define FLS4 0x00000010 /* Enables (=1) SPI_FLOUT4 as flag output for SPI Slave-select */
-#define FLS5 0x00000020 /* Enables (=1) SPI_FLOUT5 as flag output for SPI Slave-select */
-#define FLS6 0x00000040 /* Enables (=1) SPI_FLOUT6 as flag output for SPI Slave-select */
-#define FLS7 0x00000080 /* Enables (=1) SPI_FLOUT7 as flag output for SPI Slave-select */
-#define FLG1 0x00000200 /* Activates (=0) SPI_FLOUT1 as flag output for SPI Slave-select */
-#define FLG2 0x00000400 /* Activates (=0) SPI_FLOUT2 as flag output for SPI Slave-select */
-#define FLG3 0x00000800 /* Activates (=0) SPI_FLOUT3 as flag output for SPI Slave-select */
-#define FLG4 0x00001000 /* Activates (=0) SPI_FLOUT4 as flag output for SPI Slave-select */
-#define FLG5 0x00002000 /* Activates (=0) SPI_FLOUT5 as flag output for SPI Slave-select */
-#define FLG6 0x00004000 /* Activates (=0) SPI_FLOUT6 as flag output for SPI Slave-select */
-#define FLG7 0x00008000 /* Activates (=0) SPI_FLOUT7 as flag output for SPI Slave-select */
-
-/* SPI_FLG Bit Positions */
-#define FLS1_P 0x00000001 /* Enables (=1) SPI_FLOUT1 as flag output for SPI Slave-select */
-#define FLS2_P 0x00000002 /* Enables (=1) SPI_FLOUT2 as flag output for SPI Slave-select */
-#define FLS3_P 0x00000003 /* Enables (=1) SPI_FLOUT3 as flag output for SPI Slave-select */
-#define FLS4_P 0x00000004 /* Enables (=1) SPI_FLOUT4 as flag output for SPI Slave-select */
-#define FLS5_P 0x00000005 /* Enables (=1) SPI_FLOUT5 as flag output for SPI Slave-select */
-#define FLS6_P 0x00000006 /* Enables (=1) SPI_FLOUT6 as flag output for SPI Slave-select */
-#define FLS7_P 0x00000007 /* Enables (=1) SPI_FLOUT7 as flag output for SPI Slave-select */
-#define FLG1_P 0x00000009 /* Activates (=0) SPI_FLOUT1 as flag output for SPI Slave-select */
-#define FLG2_P 0x0000000A /* Activates (=0) SPI_FLOUT2 as flag output for SPI Slave-select */
-#define FLG3_P 0x0000000B /* Activates (=0) SPI_FLOUT3 as flag output for SPI Slave-select */
-#define FLG4_P 0x0000000C /* Activates (=0) SPI_FLOUT4 as flag output for SPI Slave-select */
-#define FLG5_P 0x0000000D /* Activates (=0) SPI_FLOUT5 as flag output for SPI Slave-select */
-#define FLG6_P 0x0000000E /* Activates (=0) SPI_FLOUT6 as flag output for SPI Slave-select */
-#define FLG7_P 0x0000000F /* Activates (=0) SPI_FLOUT7 as flag output for SPI Slave-select */
-
-/* SPI_STAT Masks */
-#define SPIF 0x00000001 /* Set (=1) when SPI single-word transfer complete */
-#define MODF 0x00000002 /* Set (=1) in a master device when some other device tries to become master */
-#define TXE 0x00000004 /* Set (=1) when transmission occurs with no new data in SPI_TDBR */
-#define TXS 0x00000008 /* SPI_TDBR Data Buffer Status (0=Empty, 1=Full) */
-#define RBSY 0x00000010 /* Set (=1) when data is received with RDBR full */
-#define RXS 0x00000020 /* SPI_RDBR Data Buffer Status (0=Empty, 1=Full) */
-#define TXCOL 0x00000040 /* When set (=1), corrupt data may have been transmitted */
-
-/* SPIx_FLG Masks */
-#define FLG1E 0xFDFF /* Activates SPI_FLOUT1 */
-#define FLG2E 0xFBFF /* Activates SPI_FLOUT2 */
-#define FLG3E 0xF7FF /* Activates SPI_FLOUT3 */
-#define FLG4E 0xEFFF /* Activates SPI_FLOUT4 */
-#define FLG5E 0xDFFF /* Activates SPI_FLOUT5 */
-#define FLG6E 0xBFFF /* Activates SPI_FLOUT6 */
-#define FLG7E 0x7FFF /* Activates SPI_FLOUT7 */
-
/* ********************* ASYNCHRONOUS MEMORY CONTROLLER MASKS ************* */
/* AMGCTL Masks */
diff --git a/arch/blackfin/mach-bf533/include/mach/fio_flag.h b/arch/blackfin/mach-bf533/include/mach/fio_flag.h
new file mode 100644
index 000000000000..d0bfba0b083b
--- /dev/null
+++ b/arch/blackfin/mach-bf533/include/mach/fio_flag.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2005-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later
+ */
+
+#ifndef _MACH_FIO_FLAG_H
+#define _MACH_FIO_FLAG_H
+
+#include <asm/blackfin.h>
+#include <asm/irqflags.h>
+
+#if ANOMALY_05000311
+#define BFIN_WRITE_FIO_FLAG(name) \
+static inline void bfin_write_FIO_FLAG_##name(unsigned short val) \
+{ \
+ unsigned long flags; \
+ flags = hard_local_irq_save(); \
+ bfin_write16(FIO_FLAG_##name, val); \
+ bfin_read_CHIPID(); \
+ hard_local_irq_restore(flags); \
+}
+BFIN_WRITE_FIO_FLAG(D)
+BFIN_WRITE_FIO_FLAG(C)
+BFIN_WRITE_FIO_FLAG(S)
+BFIN_WRITE_FIO_FLAG(T)
+
+#define BFIN_READ_FIO_FLAG(name) \
+static inline u16 bfin_read_FIO_FLAG_##name(void) \
+{ \
+ unsigned long flags; \
+ u16 ret; \
+ flags = hard_local_irq_save(); \
+ ret = bfin_read16(FIO_FLAG_##name); \
+ bfin_read_CHIPID(); \
+ hard_local_irq_restore(flags); \
+ return ret; \
+}
+BFIN_READ_FIO_FLAG(D)
+BFIN_READ_FIO_FLAG(C)
+BFIN_READ_FIO_FLAG(S)
+BFIN_READ_FIO_FLAG(T)
+
+#else
+#define bfin_write_FIO_FLAG_D(val) bfin_write16(FIO_FLAG_D, val)
+#define bfin_write_FIO_FLAG_C(val) bfin_write16(FIO_FLAG_C, val)
+#define bfin_write_FIO_FLAG_S(val) bfin_write16(FIO_FLAG_S, val)
+#define bfin_write_FIO_FLAG_T(val) bfin_write16(FIO_FLAG_T, val)
+#define bfin_read_FIO_FLAG_T() bfin_read16(FIO_FLAG_T)
+#define bfin_read_FIO_FLAG_C() bfin_read16(FIO_FLAG_C)
+#define bfin_read_FIO_FLAG_S() bfin_read16(FIO_FLAG_S)
+#define bfin_read_FIO_FLAG_D() bfin_read16(FIO_FLAG_D)
+#endif
+
+#endif /* _MACH_FIO_FLAG_H */
diff --git a/arch/blackfin/mach-bf533/include/mach/pll.h b/arch/blackfin/mach-bf533/include/mach/pll.h
new file mode 100644
index 000000000000..169c106d0edb
--- /dev/null
+++ b/arch/blackfin/mach-bf533/include/mach/pll.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2005-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later
+ */
+
+#ifndef _MACH_PLL_H
+#define _MACH_PLL_H
+
+#include <asm/blackfin.h>
+#include <asm/irqflags.h>
+
+/* Writing to PLL_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_PLL_CTL(unsigned int val)
+{
+ unsigned long flags, iwr;
+
+ if (val == bfin_read_PLL_CTL())
+ return;
+
+ flags = hard_local_irq_save();
+ /* Enable the PLL Wakeup bit in SIC IWR */
+ iwr = bfin_read32(SIC_IWR);
+ /* Only allow PPL Wakeup) */
+ bfin_write32(SIC_IWR, IWR_ENABLE(0));
+
+ bfin_write16(PLL_CTL, val);
+ SSYNC();
+ asm("IDLE;");
+
+ bfin_write32(SIC_IWR, iwr);
+ hard_local_irq_restore(flags);
+}
+
+/* Writing to VR_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_VR_CTL(unsigned int val)
+{
+ unsigned long flags, iwr;
+
+ if (val == bfin_read_VR_CTL())
+ return;
+
+ flags = hard_local_irq_save();
+ /* Enable the PLL Wakeup bit in SIC IWR */
+ iwr = bfin_read32(SIC_IWR);
+ /* Only allow PPL Wakeup) */
+ bfin_write32(SIC_IWR, IWR_ENABLE(0));
+
+ bfin_write16(VR_CTL, val);
+ SSYNC();
+ asm("IDLE;");
+
+ bfin_write32(SIC_IWR, iwr);
+ hard_local_irq_restore(flags);
+}
+
+#endif /* _MACH_PLL_H */
diff --git a/arch/blackfin/mach-bf537/Kconfig b/arch/blackfin/mach-bf537/Kconfig
index d81224f9d723..08b2b343ccec 100644
--- a/arch/blackfin/mach-bf537/Kconfig
+++ b/arch/blackfin/mach-bf537/Kconfig
@@ -14,8 +14,8 @@ config IRQ_DMA_ERROR
int "IRQ_DMA_ERROR Generic"
default 7
config IRQ_ERROR
- int "IRQ_ERROR: CAN MAC SPORT0 SPORT1 SPI UART0 UART1"
- default 7
+ int "IRQ_ERROR: PPI CAN MAC SPORT0 SPORT1 SPI UART0 UART1"
+ default 11
config IRQ_RTC
int "IRQ_RTC"
default 8
diff --git a/arch/blackfin/mach-bf537/boards/cm_bf537e.c b/arch/blackfin/mach-bf537/boards/cm_bf537e.c
index d35fc5fe4c2b..e2e7be40ef44 100644
--- a/arch/blackfin/mach-bf537/boards/cm_bf537e.c
+++ b/arch/blackfin/mach-bf537/boards/cm_bf537e.c
@@ -73,7 +73,7 @@ static struct bfin5xx_spi_chip spi_adc_chip_info = {
};
#endif
-#if defined(CONFIG_SND_BLACKFIN_AD183X) || defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
.enable_dma = 0,
.bits_per_word = 16,
@@ -112,12 +112,12 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
},
#endif
-#if defined(CONFIG_SND_BLACKFIN_AD183X) || defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
{
- .modalias = "ad1836",
+ .modalias = "ad183x",
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
- .chip_select = CONFIG_SND_BLACKFIN_SPI_PFBIT,
+ .chip_select = 4,
.controller_data = &ad1836_spi_chip_info,
},
#endif
@@ -229,7 +229,7 @@ static struct resource isp1362_hcd_resources[] = {
}, {
.start = IRQ_PG15,
.end = IRQ_PG15,
- .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
},
};
diff --git a/arch/blackfin/mach-bf537/boards/cm_bf537u.c b/arch/blackfin/mach-bf537/boards/cm_bf537u.c
index d464ad5b72b2..752c833f7ca8 100644
--- a/arch/blackfin/mach-bf537/boards/cm_bf537u.c
+++ b/arch/blackfin/mach-bf537/boards/cm_bf537u.c
@@ -74,7 +74,7 @@ static struct bfin5xx_spi_chip spi_adc_chip_info = {
};
#endif
-#if defined(CONFIG_SND_BLACKFIN_AD183X) || defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
.enable_dma = 0,
.bits_per_word = 16,
@@ -113,12 +113,12 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
},
#endif
-#if defined(CONFIG_SND_BLACKFIN_AD183X) || defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
{
- .modalias = "ad1836",
+ .modalias = "ad183x",
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
- .chip_select = CONFIG_SND_BLACKFIN_SPI_PFBIT,
+ .chip_select = 4,
.controller_data = &ad1836_spi_chip_info,
},
#endif
@@ -230,7 +230,7 @@ static struct resource isp1362_hcd_resources[] = {
}, {
.start = IRQ_PG15,
.end = IRQ_PG15,
- .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
},
};
diff --git a/arch/blackfin/mach-bf537/boards/pnav10.c b/arch/blackfin/mach-bf537/boards/pnav10.c
index 812e8f991601..6b03808800a6 100644
--- a/arch/blackfin/mach-bf537/boards/pnav10.c
+++ b/arch/blackfin/mach-bf537/boards/pnav10.c
@@ -175,8 +175,8 @@ static struct bfin5xx_spi_chip spi_adc_chip_info = {
};
#endif
-#if defined(CONFIG_SND_BLACKFIN_AD183X) \
- || defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
+ || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
.enable_dma = 0,
.bits_per_word = 16,
@@ -238,13 +238,13 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
},
#endif
-#if defined(CONFIG_SND_BLACKFIN_AD183X) \
- || defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
+ || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
{
- .modalias = "ad1836",
+ .modalias = "ad183x",
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
- .chip_select = CONFIG_SND_BLACKFIN_SPI_PFBIT,
+ .chip_select = 4,
.controller_data = &ad1836_spi_chip_info,
},
#endif
diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c
index 68a27bccc7d4..c9e0e85629bf 100644
--- a/arch/blackfin/mach-bf537/boards/stamp.c
+++ b/arch/blackfin/mach-bf537/boards/stamp.c
@@ -35,12 +35,10 @@
#include <asm/reboot.h>
#include <asm/portmux.h>
#include <asm/dpmc.h>
-#ifdef CONFIG_REGULATOR_ADP_SWITCH
-#include <linux/regulator/adp_switch.h>
-#endif
-#ifdef CONFIG_REGULATOR_AD5398
-#include <linux/regulator/ad5398.h>
+#ifdef CONFIG_REGULATOR_FIXED_VOLTAGE
+#include <linux/regulator/fixed.h>
#endif
+#include <linux/regulator/machine.h>
#include <linux/regulator/consumer.h>
#include <linux/regulator/userspace-consumer.h>
@@ -264,7 +262,7 @@ static struct resource isp1362_hcd_resources[] = {
}, {
.start = IRQ_PF3,
.end = IRQ_PF3,
- .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
},
};
@@ -418,7 +416,7 @@ static struct platform_nand_data bfin_plat_nand_data = {
static struct resource bfin_plat_nand_resources = {
.start = 0x20212000,
.end = 0x20212000 + (1 << MAX(BFIN_NAND_PLAT_CLE, BFIN_NAND_PLAT_ALE)),
- .flags = IORESOURCE_IO,
+ .flags = IORESOURCE_MEM,
};
static struct platform_device bfin_async_nand_device = {
@@ -545,6 +543,14 @@ static struct bfin5xx_spi_chip ad1938_spi_chip_info = {
};
#endif
+#if defined(CONFIG_SND_BF5XX_SOC_ADAV80X) \
+ || defined(CONFIG_SND_BF5XX_SOC_ADAV80X_MODULE)
+static struct bfin5xx_spi_chip adav801_spi_chip_info = {
+ .enable_dma = 0,
+ .bits_per_word = 8,
+};
+#endif
+
#if defined(CONFIG_INPUT_AD714X_SPI) || defined(CONFIG_INPUT_AD714X_SPI_MODULE)
#include <linux/input/ad714x.h>
static struct bfin5xx_spi_chip ad7147_spi_chip_info = {
@@ -693,6 +699,65 @@ static struct bfin5xx_spi_chip ad2s1210_spi_chip_info = {
};
#endif
+#if defined(CONFIG_AD7314) || defined(CONFIG_AD7314_MODULE)
+static struct bfin5xx_spi_chip ad7314_spi_chip_info = {
+ .enable_dma = 0,
+ .bits_per_word = 16,
+};
+#endif
+
+#if defined(CONFIG_AD7816) || defined(CONFIG_AD7816_MODULE)
+static unsigned short ad7816_platform_data[] = {
+ GPIO_PF4, /* rdwr_pin */
+ GPIO_PF5, /* convert_pin */
+ GPIO_PF7, /* busy_pin */
+ 0,
+};
+
+static struct bfin5xx_spi_chip ad7816_spi_chip_info = {
+ .enable_dma = 0,
+ .bits_per_word = 8,
+};
+#endif
+
+#if defined(CONFIG_ADT7310) || defined(CONFIG_ADT7310_MODULE)
+static unsigned long adt7310_platform_data[3] = {
+/* INT bound temperature alarm event. line 1 */
+ IRQ_PG4, IRQF_TRIGGER_LOW,
+/* CT bound temperature alarm event irq_flags. line 0 */
+ IRQF_TRIGGER_LOW,
+};
+
+static struct bfin5xx_spi_chip adt7310_spi_chip_info = {
+ .enable_dma = 0,
+ .bits_per_word = 8,
+};
+#endif
+
+#if defined(CONFIG_AD7298) || defined(CONFIG_AD7298_MODULE)
+static unsigned short ad7298_platform_data[] = {
+ GPIO_PF7, /* busy_pin */
+ 0,
+};
+
+static struct bfin5xx_spi_chip ad7298_spi_chip_info = {
+ .enable_dma = 0,
+ .bits_per_word = 16,
+};
+#endif
+
+#if defined(CONFIG_ADT7316_SPI) || defined(CONFIG_ADT7316_SPI_MODULE)
+static unsigned long adt7316_spi_data[2] = {
+ IRQF_TRIGGER_LOW, /* interrupt flags */
+ GPIO_PF7, /* ldac_pin, 0 means DAC/LDAC registers control DAC update */
+};
+
+static struct bfin5xx_spi_chip adt7316_spi_chip_info = {
+ .enable_dma = 0,
+ .bits_per_word = 8,
+};
+#endif
+
#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
#define MMC_SPI_CARD_DETECT_INT IRQ_PF5
@@ -824,14 +889,12 @@ static struct bfin5xx_spi_chip lq035q1_spi_chip_info = {
static struct bfin5xx_spi_chip enc28j60_spi_chip_info = {
.enable_dma = 1,
.bits_per_word = 8,
- .cs_gpio = GPIO_PF10,
};
#endif
#if defined(CONFIG_ADF702X) || defined(CONFIG_ADF702X_MODULE)
static struct bfin5xx_spi_chip adf7021_spi_chip_info = {
.bits_per_word = 16,
- .cs_gpio = GPIO_PF10,
};
#include <linux/spi/adf702x.h>
@@ -938,6 +1001,13 @@ static struct bfin5xx_spi_chip spi_adxl34x_chip_info = {
};
#endif
+#if defined(CONFIG_AD7476) || defined(CONFIG_AD7476_MODULE)
+static struct bfin5xx_spi_chip spi_ad7476_chip_info = {
+ .enable_dma = 0, /* use dma transfer with this chip*/
+ .bits_per_word = 8,
+};
+#endif
+
static struct spi_board_info bfin_spi_board_info[] __initdata = {
#if defined(CONFIG_MTD_M25P80) \
|| defined(CONFIG_MTD_M25P80_MODULE)
@@ -982,7 +1052,7 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.modalias = "ad183x",
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
- .chip_select = 4,/* CONFIG_SND_BLACKFIN_SPI_PFBIT */
+ .chip_select = 4,
.platform_data = "ad1836", /* only includes chip name for the moment */
.controller_data = &ad1836_spi_chip_info,
.mode = SPI_MODE_3,
@@ -1000,6 +1070,17 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
},
#endif
+#if defined(CONFIG_SND_BF5XX_SOC_ADAV80X) || defined(CONFIG_SND_BF5XX_SOC_ADAV80X_MODULE)
+ {
+ .modalias = "adav80x",
+ .max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 1,
+ .controller_data = &adav801_spi_chip_info,
+ .mode = SPI_MODE_3,
+ },
+#endif
+
#if defined(CONFIG_INPUT_AD714X_SPI) || defined(CONFIG_INPUT_AD714X_SPI_MODULE)
{
.modalias = "ad714x_captouch",
@@ -1018,6 +1099,7 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.modalias = "ad2s90",
.bus_num = 0,
.chip_select = 3, /* change it for your board */
+ .mode = SPI_MODE_3,
.platform_data = NULL,
.controller_data = &ad2s90_spi_chip_info,
},
@@ -1044,6 +1126,67 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
},
#endif
+#if defined(CONFIG_AD7314) || defined(CONFIG_AD7314_MODULE)
+ {
+ .modalias = "ad7314",
+ .max_speed_hz = 1000000,
+ .bus_num = 0,
+ .chip_select = 4, /* CS, change it for your board */
+ .controller_data = &ad7314_spi_chip_info,
+ .mode = SPI_MODE_1,
+ },
+#endif
+
+#if defined(CONFIG_AD7816) || defined(CONFIG_AD7816_MODULE)
+ {
+ .modalias = "ad7818",
+ .max_speed_hz = 1000000,
+ .bus_num = 0,
+ .chip_select = 4, /* CS, change it for your board */
+ .platform_data = ad7816_platform_data,
+ .controller_data = &ad7816_spi_chip_info,
+ .mode = SPI_MODE_3,
+ },
+#endif
+
+#if defined(CONFIG_ADT7310) || defined(CONFIG_ADT7310_MODULE)
+ {
+ .modalias = "adt7310",
+ .max_speed_hz = 1000000,
+ .irq = IRQ_PG5, /* CT alarm event. Line 0 */
+ .bus_num = 0,
+ .chip_select = 4, /* CS, change it for your board */
+ .platform_data = adt7310_platform_data,
+ .controller_data = &adt7310_spi_chip_info,
+ .mode = SPI_MODE_3,
+ },
+#endif
+
+#if defined(CONFIG_AD7298) || defined(CONFIG_AD7298_MODULE)
+ {
+ .modalias = "ad7298",
+ .max_speed_hz = 1000000,
+ .bus_num = 0,
+ .chip_select = 4, /* CS, change it for your board */
+ .platform_data = ad7298_platform_data,
+ .controller_data = &ad7298_spi_chip_info,
+ .mode = SPI_MODE_3,
+ },
+#endif
+
+#if defined(CONFIG_ADT7316_SPI) || defined(CONFIG_ADT7316_SPI_MODULE)
+ {
+ .modalias = "adt7316",
+ .max_speed_hz = 1000000,
+ .irq = IRQ_PG5, /* interrupt line */
+ .bus_num = 0,
+ .chip_select = 4, /* CS, change it for your board */
+ .platform_data = adt7316_spi_data,
+ .controller_data = &adt7316_spi_chip_info,
+ .mode = SPI_MODE_3,
+ },
+#endif
+
#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
{
.modalias = "mmc_spi",
@@ -1103,7 +1246,7 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.max_speed_hz = 20000000, /* max spi clock (SCK) speed in HZ */
.irq = IRQ_PF6,
.bus_num = 0,
- .chip_select = 0, /* GPIO controlled SSEL */
+ .chip_select = GPIO_PF10 + MAX_CTRL_CS, /* GPIO controlled SSEL */
.controller_data = &enc28j60_spi_chip_info,
.mode = SPI_MODE_0,
},
@@ -1125,7 +1268,7 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.modalias = "adf702x",
.max_speed_hz = 16000000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
- .chip_select = 0, /* GPIO controlled SSEL */
+ .chip_select = GPIO_PF10 + MAX_CTRL_CS, /* GPIO controlled SSEL */
.controller_data = &adf7021_spi_chip_info,
.platform_data = &adf7021_platform_data,
.mode = SPI_MODE_0,
@@ -1143,12 +1286,239 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.mode = SPI_MODE_0,
},
#endif
+#if defined(CONFIG_AD7476) \
+ || defined(CONFIG_AD7476_MODULE)
+ {
+ .modalias = "ad7476", /* Name of spi_driver for this device */
+ .max_speed_hz = 6250000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0, /* Framework bus number */
+ .chip_select = 1, /* Framework chip select. */
+ .platform_data = NULL, /* No spi_driver specific config */
+ .controller_data = &spi_ad7476_chip_info,
+ .mode = SPI_MODE_3,
+ },
+#endif
+#if defined(CONFIG_ADE7753) \
+ || defined(CONFIG_ADE7753_MODULE)
+ {
+ .modalias = "ade7753",
+ .max_speed_hz = 1000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 1, /* CS, change it for your board */
+ .platform_data = NULL, /* No spi_driver specific config */
+ .mode = SPI_MODE_1,
+ },
+#endif
+#if defined(CONFIG_ADE7754) \
+ || defined(CONFIG_ADE7754_MODULE)
+ {
+ .modalias = "ade7754",
+ .max_speed_hz = 1000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 1, /* CS, change it for your board */
+ .platform_data = NULL, /* No spi_driver specific config */
+ .mode = SPI_MODE_1,
+ },
+#endif
+#if defined(CONFIG_ADE7758) \
+ || defined(CONFIG_ADE7758_MODULE)
+ {
+ .modalias = "ade7758",
+ .max_speed_hz = 1000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 1, /* CS, change it for your board */
+ .platform_data = NULL, /* No spi_driver specific config */
+ .mode = SPI_MODE_1,
+ },
+#endif
+#if defined(CONFIG_ADE7759) \
+ || defined(CONFIG_ADE7759_MODULE)
+ {
+ .modalias = "ade7759",
+ .max_speed_hz = 1000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 1, /* CS, change it for your board */
+ .platform_data = NULL, /* No spi_driver specific config */
+ .mode = SPI_MODE_1,
+ },
+#endif
+#if defined(CONFIG_ADE7854_SPI) \
+ || defined(CONFIG_ADE7854_SPI_MODULE)
+ {
+ .modalias = "ade7854",
+ .max_speed_hz = 1000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 1, /* CS, change it for your board */
+ .platform_data = NULL, /* No spi_driver specific config */
+ .mode = SPI_MODE_3,
+ },
+#endif
+#if defined(CONFIG_ADIS16060) \
+ || defined(CONFIG_ADIS16060_MODULE)
+ {
+ .modalias = "adis16060_r",
+ .max_speed_hz = 2900000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = MAX_CTRL_CS + 1, /* CS for read, change it for your board */
+ .platform_data = NULL, /* No spi_driver specific config */
+ .mode = SPI_MODE_0,
+ },
+ {
+ .modalias = "adis16060_w",
+ .max_speed_hz = 2900000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 2, /* CS for write, change it for your board */
+ .platform_data = NULL, /* No spi_driver specific config */
+ .mode = SPI_MODE_1,
+ },
+#endif
+#if defined(CONFIG_ADIS16130) \
+ || defined(CONFIG_ADIS16130_MODULE)
+ {
+ .modalias = "adis16130",
+ .max_speed_hz = 1000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 1, /* CS for read, change it for your board */
+ .platform_data = NULL, /* No spi_driver specific config */
+ .mode = SPI_MODE_3,
+ },
+#endif
+#if defined(CONFIG_ADIS16201) \
+ || defined(CONFIG_ADIS16201_MODULE)
+ {
+ .modalias = "adis16201",
+ .max_speed_hz = 1000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 5, /* CS, change it for your board */
+ .platform_data = NULL, /* No spi_driver specific config */
+ .mode = SPI_MODE_3,
+ .irq = IRQ_PF4,
+ },
+#endif
+#if defined(CONFIG_ADIS16203) \
+ || defined(CONFIG_ADIS16203_MODULE)
+ {
+ .modalias = "adis16203",
+ .max_speed_hz = 1000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 5, /* CS, change it for your board */
+ .platform_data = NULL, /* No spi_driver specific config */
+ .mode = SPI_MODE_3,
+ .irq = IRQ_PF4,
+ },
+#endif
+#if defined(CONFIG_ADIS16204) \
+ || defined(CONFIG_ADIS16204_MODULE)
+ {
+ .modalias = "adis16204",
+ .max_speed_hz = 1000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 5, /* CS, change it for your board */
+ .platform_data = NULL, /* No spi_driver specific config */
+ .mode = SPI_MODE_3,
+ .irq = IRQ_PF4,
+ },
+#endif
+#if defined(CONFIG_ADIS16209) \
+ || defined(CONFIG_ADIS16209_MODULE)
+ {
+ .modalias = "adis16209",
+ .max_speed_hz = 1000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 5, /* CS, change it for your board */
+ .platform_data = NULL, /* No spi_driver specific config */
+ .mode = SPI_MODE_3,
+ .irq = IRQ_PF4,
+ },
+#endif
+#if defined(CONFIG_ADIS16220) \
+ || defined(CONFIG_ADIS16220_MODULE)
+ {
+ .modalias = "adis16220",
+ .max_speed_hz = 2000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 5, /* CS, change it for your board */
+ .platform_data = NULL, /* No spi_driver specific config */
+ .mode = SPI_MODE_3,
+ .irq = IRQ_PF4,
+ },
+#endif
+#if defined(CONFIG_ADIS16240) \
+ || defined(CONFIG_ADIS16240_MODULE)
+ {
+ .modalias = "adis16240",
+ .max_speed_hz = 1500000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 5, /* CS, change it for your board */
+ .platform_data = NULL, /* No spi_driver specific config */
+ .mode = SPI_MODE_3,
+ .irq = IRQ_PF4,
+ },
+#endif
+#if defined(CONFIG_ADIS16260) \
+ || defined(CONFIG_ADIS16260_MODULE)
+ {
+ .modalias = "adis16260",
+ .max_speed_hz = 1500000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 5, /* CS, change it for your board */
+ .platform_data = NULL, /* No spi_driver specific config */
+ .mode = SPI_MODE_3,
+ .irq = IRQ_PF4,
+ },
+#endif
+#if defined(CONFIG_ADIS16261) \
+ || defined(CONFIG_ADIS16261_MODULE)
+ {
+ .modalias = "adis16261",
+ .max_speed_hz = 2500000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 1, /* CS, change it for your board */
+ .platform_data = NULL, /* No spi_driver specific config */
+ .mode = SPI_MODE_3,
+ },
+#endif
+#if defined(CONFIG_ADIS16300) \
+ || defined(CONFIG_ADIS16300_MODULE)
+ {
+ .modalias = "adis16300",
+ .max_speed_hz = 1000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 5, /* CS, change it for your board */
+ .platform_data = NULL, /* No spi_driver specific config */
+ .mode = SPI_MODE_3,
+ .irq = IRQ_PF4,
+ },
+#endif
+#if defined(CONFIG_ADIS16350) \
+ || defined(CONFIG_ADIS16350_MODULE)
+ {
+ .modalias = "adis16364",
+ .max_speed_hz = 1000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 5, /* CS, change it for your board */
+ .platform_data = NULL, /* No spi_driver specific config */
+ .mode = SPI_MODE_3,
+ .irq = IRQ_PF4,
+ },
+#endif
+#if defined(CONFIG_ADIS16400) \
+ || defined(CONFIG_ADIS16400_MODULE)
+ {
+ .modalias = "adis16400",
+ .max_speed_hz = 1000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 1, /* CS, change it for your board */
+ .platform_data = NULL, /* No spi_driver specific config */
+ .mode = SPI_MODE_3,
+ },
+#endif
};
#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
/* SPI controller data */
static struct bfin5xx_spi_master bfin_spi0_info = {
- .num_chipselect = 8,
+ .num_chipselect = MAX_CTRL_CS + MAX_BLACKFIN_GPIOS,
.enable_dma = 1, /* master has the ability to do dma transfer */
.pin_req = {P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0},
};
@@ -1773,12 +2143,6 @@ static struct regulator_init_data ad5398_regulator_data = {
.consumer_supplies = &ad5398_consumer,
};
-static struct ad5398_platform_data ad5398_i2c_platform_data = {
- .current_bits = 10,
- .current_offset = 4,
- .regulator_data = &ad5398_regulator_data,
-};
-
#if defined(CONFIG_REGULATOR_VIRTUAL_CONSUMER) || \
defined(CONFIG_REGULATOR_VIRTUAL_CONSUMER_MODULE)
static struct platform_device ad5398_virt_consumer_device = {
@@ -1811,7 +2175,34 @@ static struct platform_device ad5398_userspace_consumer_device = {
#endif
#endif
+#if defined(CONFIG_ADT7410) || defined(CONFIG_ADT7410_MODULE)
+/* INT bound temperature alarm event. line 1 */
+static unsigned long adt7410_platform_data[2] = {
+ IRQ_PG4, IRQF_TRIGGER_LOW,
+};
+#endif
+
+#if defined(CONFIG_ADT7316_I2C) || defined(CONFIG_ADT7316_I2C_MODULE)
+/* INT bound temperature alarm event. line 1 */
+static unsigned long adt7316_i2c_data[2] = {
+ IRQF_TRIGGER_LOW, /* interrupt flags */
+ GPIO_PF4, /* ldac_pin, 0 means DAC/LDAC registers control DAC update */
+};
+#endif
+
static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
+#if defined(CONFIG_SND_BF5XX_SOC_AD193X) || defined(CONFIG_SND_BF5XX_SOC_AD193X_MODULE)
+ {
+ I2C_BOARD_INFO("ad1937", 0x04),
+ },
+#endif
+
+#if defined(CONFIG_SND_BF5XX_SOC_ADAV80X) || defined(CONFIG_SND_BF5XX_SOC_ADAV80X_MODULE)
+ {
+ I2C_BOARD_INFO("adav803", 0x10),
+ },
+#endif
+
#if defined(CONFIG_INPUT_AD714X_I2C) || defined(CONFIG_INPUT_AD714X_I2C_MODULE)
{
I2C_BOARD_INFO("ad7142_captouch", 0x2C),
@@ -1843,12 +2234,7 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
{
I2C_BOARD_INFO("ad7414", 0x9),
.irq = IRQ_PG5,
- /*
- * platform_data pointer is borrwoed by the driver to
- * store custimer defined IRQ ALART level mode.
- * only IRQF_TRIGGER_HIGH and IRQF_TRIGGER_LOW are valid.
- */
- .platform_data = (void *)IRQF_TRIGGER_LOW,
+ .irq_flags = IRQF_TRIGGER_LOW,
},
#endif
@@ -1856,12 +2242,56 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
{
I2C_BOARD_INFO("ad7417", 0xb),
.irq = IRQ_PG5,
- /*
- * platform_data pointer is borrwoed by the driver to
- * store custimer defined IRQ ALART level mode.
- * only IRQF_TRIGGER_HIGH and IRQF_TRIGGER_LOW are valid.
- */
- .platform_data = (void *)IRQF_TRIGGER_LOW,
+ .irq_flags = IRQF_TRIGGER_LOW,
+ .platform_data = (void *)GPIO_PF4,
+ },
+#endif
+
+#if defined(CONFIG_ADE7854_I2C) || defined(CONFIG_ADE7854_I2C_MODULE)
+ {
+ I2C_BOARD_INFO("ade7854", 0x38),
+ },
+#endif
+
+#if defined(CONFIG_ADT75) || defined(CONFIG_ADT75_MODULE)
+ {
+ I2C_BOARD_INFO("adt75", 0x9),
+ .irq = IRQ_PG5,
+ .irq_flags = IRQF_TRIGGER_LOW,
+ },
+#endif
+
+#if defined(CONFIG_ADT7408) || defined(CONFIG_ADT7408_MODULE)
+ {
+ I2C_BOARD_INFO("adt7408", 0x18),
+ .irq = IRQ_PG5,
+ .irq_flags = IRQF_TRIGGER_LOW,
+ },
+#endif
+
+#if defined(CONFIG_ADT7410) || defined(CONFIG_ADT7410_MODULE)
+ {
+ I2C_BOARD_INFO("adt7410", 0x48),
+ /* CT critical temperature event. line 0 */
+ .irq = IRQ_PG5,
+ .irq_flags = IRQF_TRIGGER_LOW,
+ .platform_data = (void *)&adt7410_platform_data,
+ },
+#endif
+
+#if defined(CONFIG_AD7291) || defined(CONFIG_AD7291_MODULE)
+ {
+ I2C_BOARD_INFO("ad7291", 0x20),
+ .irq = IRQ_PG5,
+ .irq_flags = IRQF_TRIGGER_LOW,
+ },
+#endif
+
+#if defined(CONFIG_ADT7316_I2C) || defined(CONFIG_ADT7316_I2C_MODULE)
+ {
+ I2C_BOARD_INFO("adt7316", 0x48),
+ .irq = IRQ_PG6,
+ .platform_data = (void *)&adt7316_i2c_data,
},
#endif
@@ -1917,7 +2347,7 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
#endif
#if defined(CONFIG_FB_BF537_LQ035) || defined(CONFIG_FB_BF537_LQ035_MODULE)
{
- I2C_BOARD_INFO("bf537-lq035-ad5280", 0x2C),
+ I2C_BOARD_INFO("bf537-lq035-ad5280", 0x2F),
},
#endif
#if defined(CONFIG_BACKLIGHT_ADP8870) || defined(CONFIG_BACKLIGHT_ADP8870_MODULE)
@@ -1954,7 +2384,7 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
#if defined(CONFIG_REGULATOR_AD5398) || defined(CONFIG_REGULATOR_AD5398_MODULE)
{
I2C_BOARD_INFO("ad5398", 0xC),
- .platform_data = (void *)&ad5398_i2c_platform_data,
+ .platform_data = (void *)&ad5398_regulator_data,
},
#endif
#if defined(CONFIG_BACKLIGHT_ADP8860) || defined(CONFIG_BACKLIGHT_ADP8860_MODULE)
@@ -1963,6 +2393,16 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
.platform_data = (void *)&adp8860_pdata,
},
#endif
+#if defined(CONFIG_SND_SOC_ADAU1373) || defined(CONFIG_SND_SOC_ADAU1373_MODULE)
+ {
+ I2C_BOARD_INFO("adau1373", 0x1A),
+ },
+#endif
+#if defined(CONFIG_BFIN_TWI_LCD) || defined(CONFIG_BFIN_TWI_LCD_MODULE)
+ {
+ I2C_BOARD_INFO("ad5252", 0x2e),
+ },
+#endif
};
#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
@@ -2147,50 +2587,38 @@ static struct platform_device bfin_ac97 = {
};
#endif
-#if defined(CONFIG_REGULATOR_ADP_SWITCH) || defined(CONFIG_REGULATOR_ADP_SWITCH_MODULE)
-#define REGULATOR_ADP122 "adp122"
-#define REGULATOR_ADP150 "adp150"
+#if defined(CONFIG_REGULATOR_FIXED_VOLTAGE) || defined(CONFIG_REGULATOR_FIXED_VOLTAGE_MODULE)
+#define REGULATOR_ADP122 "adp122"
+#define REGULATOR_ADP122_UV 2500000
static struct regulator_consumer_supply adp122_consumers = {
.supply = REGULATOR_ADP122,
};
-static struct regulator_consumer_supply adp150_consumers = {
- .supply = REGULATOR_ADP150,
-};
-
-static struct regulator_init_data adp_switch_regulator_data[] = {
- {
- .constraints = {
- .name = REGULATOR_ADP122,
- .valid_ops_mask = REGULATOR_CHANGE_STATUS,
- .min_uA = 0,
- .max_uA = 300000,
- },
- .num_consumer_supplies = 1, /* only 1 */
- .consumer_supplies = &adp122_consumers,
- .driver_data = (void *)GPIO_PF2, /* gpio port only */
- },
- {
- .constraints = {
- .name = REGULATOR_ADP150,
- .valid_ops_mask = REGULATOR_CHANGE_STATUS,
- .min_uA = 0,
- .max_uA = 150000,
- },
- .num_consumer_supplies = 1, /* only 1 */
- .consumer_supplies = &adp150_consumers,
- .driver_data = (void *)GPIO_PF3, /* gpio port only */
+static struct regulator_init_data adp_switch_regulator_data = {
+ .constraints = {
+ .name = REGULATOR_ADP122,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .min_uV = REGULATOR_ADP122_UV,
+ .max_uV = REGULATOR_ADP122_UV,
+ .min_uA = 0,
+ .max_uA = 300000,
},
+ .num_consumer_supplies = 1, /* only 1 */
+ .consumer_supplies = &adp122_consumers,
};
-static struct adp_switch_platform_data adp_switch_pdata = {
- .regulator_num = ARRAY_SIZE(adp_switch_regulator_data),
- .regulator_data = adp_switch_regulator_data,
+static struct fixed_voltage_config adp_switch_pdata = {
+ .supply_name = REGULATOR_ADP122,
+ .microvolts = REGULATOR_ADP122_UV,
+ .gpio = GPIO_PF2,
+ .enable_high = 1,
+ .enabled_at_boot = 0,
+ .init_data = &adp_switch_regulator_data,
};
static struct platform_device adp_switch_device = {
- .name = "adp_switch",
+ .name = "reg-fixed-voltage",
.id = 0,
.dev = {
.platform_data = &adp_switch_pdata,
@@ -2216,27 +2644,26 @@ static struct platform_device adp122_userspace_consumer_device = {
.platform_data = &adp122_userspace_comsumer_data,
},
};
+#endif
+#endif
-static struct regulator_bulk_data adp150_bulk_data = {
- .supply = REGULATOR_ADP150,
-};
+#if defined(CONFIG_IIO_GPIO_TRIGGER) || \
+ defined(CONFIG_IIO_GPIO_TRIGGER_MODULE)
-static struct regulator_userspace_consumer_data adp150_userspace_comsumer_data = {
- .name = REGULATOR_ADP150,
- .num_supplies = 1,
- .supplies = &adp150_bulk_data,
+static struct resource iio_gpio_trigger_resources[] = {
+ [0] = {
+ .start = IRQ_PF5,
+ .end = IRQ_PF5,
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
+ },
};
-static struct platform_device adp150_userspace_consumer_device = {
- .name = "reg-userspace-consumer",
- .id = 1,
- .dev = {
- .platform_data = &adp150_userspace_comsumer_data,
- },
+static struct platform_device iio_gpio_trigger = {
+ .name = "iio_gpio_trigger",
+ .num_resources = ARRAY_SIZE(iio_gpio_trigger_resources),
+ .resource = iio_gpio_trigger_resources,
};
#endif
-#endif
-
static struct platform_device *stamp_devices[] __initdata = {
@@ -2369,14 +2796,18 @@ static struct platform_device *stamp_devices[] __initdata = {
#endif
#endif
-#if defined(CONFIG_REGULATOR_ADP_SWITCH) || defined(CONFIG_REGULATOR_ADP_SWITCH_MODULE)
+#if defined(CONFIG_REGULATOR_FIXED_VOLTAGE) || defined(CONFIG_REGULATOR_FIXED_VOLTAGE_MODULE)
&adp_switch_device,
#if defined(CONFIG_REGULATOR_USERSPACE_CONSUMER) || \
defined(CONFIG_REGULATOR_USERSPACE_CONSUMER_MODULE)
&adp122_userspace_consumer_device,
- &adp150_userspace_consumer_device,
#endif
#endif
+
+#if defined(CONFIG_IIO_GPIO_TRIGGER) || \
+ defined(CONFIG_IIO_GPIO_TRIGGER_MODULE)
+ &iio_gpio_trigger,
+#endif
};
static int __init stamp_init(void)
diff --git a/arch/blackfin/mach-bf537/boards/tcm_bf537.c b/arch/blackfin/mach-bf537/boards/tcm_bf537.c
index 4f0a2e72ce4c..a4d62b5fc7ba 100644
--- a/arch/blackfin/mach-bf537/boards/tcm_bf537.c
+++ b/arch/blackfin/mach-bf537/boards/tcm_bf537.c
@@ -74,7 +74,7 @@ static struct bfin5xx_spi_chip spi_adc_chip_info = {
};
#endif
-#if defined(CONFIG_SND_BLACKFIN_AD183X) || defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
.enable_dma = 0,
.bits_per_word = 16,
@@ -113,12 +113,12 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
},
#endif
-#if defined(CONFIG_SND_BLACKFIN_AD183X) || defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
{
- .modalias = "ad1836",
+ .modalias = "ad183x",
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
- .chip_select = CONFIG_SND_BLACKFIN_SPI_PFBIT,
+ .chip_select = 4,
.controller_data = &ad1836_spi_chip_info,
},
#endif
@@ -230,7 +230,7 @@ static struct resource isp1362_hcd_resources[] = {
}, {
.start = IRQ_PG15,
.end = IRQ_PG15,
- .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
},
};
diff --git a/arch/blackfin/mach-bf537/include/mach/cdefBF534.h b/arch/blackfin/mach-bf537/include/mach/cdefBF534.h
index 91825c9bd226..fbeb35e14135 100644
--- a/arch/blackfin/mach-bf537/include/mach/cdefBF534.h
+++ b/arch/blackfin/mach-bf537/include/mach/cdefBF534.h
@@ -1750,48 +1750,4 @@
/* These need to be last due to the cdef/linux inter-dependencies */
#include <asm/irq.h>
-/* Writing to PLL_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_PLL_CTL(unsigned int val)
-{
- unsigned long flags, iwr;
-
- if (val == bfin_read_PLL_CTL())
- return;
-
- local_irq_save_hw(flags);
- /* Enable the PLL Wakeup bit in SIC IWR */
- iwr = bfin_read32(SIC_IWR);
- /* Only allow PPL Wakeup) */
- bfin_write32(SIC_IWR, IWR_ENABLE(0));
-
- bfin_write16(PLL_CTL, val);
- SSYNC();
- asm("IDLE;");
-
- bfin_write32(SIC_IWR, iwr);
- local_irq_restore_hw(flags);
-}
-
-/* Writing to VR_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_VR_CTL(unsigned int val)
-{
- unsigned long flags, iwr;
-
- if (val == bfin_read_VR_CTL())
- return;
-
- local_irq_save_hw(flags);
- /* Enable the PLL Wakeup bit in SIC IWR */
- iwr = bfin_read32(SIC_IWR);
- /* Only allow PPL Wakeup) */
- bfin_write32(SIC_IWR, IWR_ENABLE(0));
-
- bfin_write16(VR_CTL, val);
- SSYNC();
- asm("IDLE;");
-
- bfin_write32(SIC_IWR, iwr);
- local_irq_restore_hw(flags);
-}
-
#endif /* _CDEF_BF534_H */
diff --git a/arch/blackfin/mach-bf537/include/mach/defBF534.h b/arch/blackfin/mach-bf537/include/mach/defBF534.h
index 6f56907a18c0..0323e6bacdae 100644
--- a/arch/blackfin/mach-bf537/include/mach/defBF534.h
+++ b/arch/blackfin/mach-bf537/include/mach/defBF534.h
@@ -1071,50 +1071,6 @@
#define FPE 0x10 /* Force Parity Error On Transmit */
#define FFE 0x20 /* Force Framing Error On Transmit */
-/* *********** SERIAL PERIPHERAL INTERFACE (SPI) MASKS ****************************/
-/* SPI_CTL Masks */
-#define TIMOD 0x0003 /* Transfer Initiate Mode */
-#define RDBR_CORE 0x0000 /* RDBR Read Initiates, IRQ When RDBR Full */
-#define TDBR_CORE 0x0001 /* TDBR Write Initiates, IRQ When TDBR Empty */
-#define RDBR_DMA 0x0002 /* DMA Read, DMA Until FIFO Empty */
-#define TDBR_DMA 0x0003 /* DMA Write, DMA Until FIFO Full */
-#define SZ 0x0004 /* Send Zero (When TDBR Empty, Send Zero/Last*) */
-#define GM 0x0008 /* Get More (When RDBR Full, Overwrite/Discard*) */
-#define PSSE 0x0010 /* Slave-Select Input Enable */
-#define EMISO 0x0020 /* Enable MISO As Output */
-#define SIZE 0x0100 /* Size of Words (16/8* Bits) */
-#define LSBF 0x0200 /* LSB First */
-#define CPHA 0x0400 /* Clock Phase */
-#define CPOL 0x0800 /* Clock Polarity */
-#define MSTR 0x1000 /* Master/Slave* */
-#define WOM 0x2000 /* Write Open Drain Master */
-#define SPE 0x4000 /* SPI Enable */
-
-/* SPI_FLG Masks */
-#define FLS1 0x0002 /* Enables SPI_FLOUT1 as SPI Slave-Select Output */
-#define FLS2 0x0004 /* Enables SPI_FLOUT2 as SPI Slave-Select Output */
-#define FLS3 0x0008 /* Enables SPI_FLOUT3 as SPI Slave-Select Output */
-#define FLS4 0x0010 /* Enables SPI_FLOUT4 as SPI Slave-Select Output */
-#define FLS5 0x0020 /* Enables SPI_FLOUT5 as SPI Slave-Select Output */
-#define FLS6 0x0040 /* Enables SPI_FLOUT6 as SPI Slave-Select Output */
-#define FLS7 0x0080 /* Enables SPI_FLOUT7 as SPI Slave-Select Output */
-#define FLG1 0xFDFF /* Activates SPI_FLOUT1 */
-#define FLG2 0xFBFF /* Activates SPI_FLOUT2 */
-#define FLG3 0xF7FF /* Activates SPI_FLOUT3 */
-#define FLG4 0xEFFF /* Activates SPI_FLOUT4 */
-#define FLG5 0xDFFF /* Activates SPI_FLOUT5 */
-#define FLG6 0xBFFF /* Activates SPI_FLOUT6 */
-#define FLG7 0x7FFF /* Activates SPI_FLOUT7 */
-
-/* SPI_STAT Masks */
-#define SPIF 0x0001 /* SPI Finished (Single-Word Transfer Complete) */
-#define MODF 0x0002 /* Mode Fault Error (Another Device Tried To Become Master) */
-#define TXE 0x0004 /* Transmission Error (Data Sent With No New Data In TDBR) */
-#define TXS 0x0008 /* SPI_TDBR Data Buffer Status (Full/Empty*) */
-#define RBSY 0x0010 /* Receive Error (Data Received With RDBR Full) */
-#define RXS 0x0020 /* SPI_RDBR Data Buffer Status (Full/Empty*) */
-#define TXCOL 0x0040 /* Transmit Collision Error (Corrupt Data May Have Been Sent) */
-
/* **************** GENERAL PURPOSE TIMER MASKS **********************/
/* TIMER_ENABLE Masks */
#define TIMEN0 0x0001 /* Enable Timer 0 */
diff --git a/arch/blackfin/mach-bf537/include/mach/pll.h b/arch/blackfin/mach-bf537/include/mach/pll.h
new file mode 100644
index 000000000000..169c106d0edb
--- /dev/null
+++ b/arch/blackfin/mach-bf537/include/mach/pll.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2005-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later
+ */
+
+#ifndef _MACH_PLL_H
+#define _MACH_PLL_H
+
+#include <asm/blackfin.h>
+#include <asm/irqflags.h>
+
+/* Writing to PLL_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_PLL_CTL(unsigned int val)
+{
+ unsigned long flags, iwr;
+
+ if (val == bfin_read_PLL_CTL())
+ return;
+
+ flags = hard_local_irq_save();
+ /* Enable the PLL Wakeup bit in SIC IWR */
+ iwr = bfin_read32(SIC_IWR);
+ /* Only allow PPL Wakeup) */
+ bfin_write32(SIC_IWR, IWR_ENABLE(0));
+
+ bfin_write16(PLL_CTL, val);
+ SSYNC();
+ asm("IDLE;");
+
+ bfin_write32(SIC_IWR, iwr);
+ hard_local_irq_restore(flags);
+}
+
+/* Writing to VR_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_VR_CTL(unsigned int val)
+{
+ unsigned long flags, iwr;
+
+ if (val == bfin_read_VR_CTL())
+ return;
+
+ flags = hard_local_irq_save();
+ /* Enable the PLL Wakeup bit in SIC IWR */
+ iwr = bfin_read32(SIC_IWR);
+ /* Only allow PPL Wakeup) */
+ bfin_write32(SIC_IWR, IWR_ENABLE(0));
+
+ bfin_write16(VR_CTL, val);
+ SSYNC();
+ asm("IDLE;");
+
+ bfin_write32(SIC_IWR, iwr);
+ hard_local_irq_restore(flags);
+}
+
+#endif /* _MACH_PLL_H */
diff --git a/arch/blackfin/mach-bf538/boards/ezkit.c b/arch/blackfin/mach-bf538/boards/ezkit.c
index 1a1f65855b03..c6fb0a52f849 100644
--- a/arch/blackfin/mach-bf538/boards/ezkit.c
+++ b/arch/blackfin/mach-bf538/boards/ezkit.c
@@ -695,7 +695,7 @@ static struct platform_device bf538_spi_master0 = {
};
static struct bfin5xx_spi_master bf538_spi_master_info1 = {
- .num_chipselect = 8,
+ .num_chipselect = 2,
.enable_dma = 1, /* master has the ability to do dma transfer */
.pin_req = {P_SPI1_SCK, P_SPI1_MISO, P_SPI1_MOSI, 0},
};
@@ -711,7 +711,7 @@ static struct platform_device bf538_spi_master1 = {
};
static struct bfin5xx_spi_master bf538_spi_master_info2 = {
- .num_chipselect = 8,
+ .num_chipselect = 2,
.enable_dma = 1, /* master has the ability to do dma transfer */
.pin_req = {P_SPI2_SCK, P_SPI2_MISO, P_SPI2_MOSI, 0},
};
diff --git a/arch/blackfin/mach-bf538/include/mach/cdefBF538.h b/arch/blackfin/mach-bf538/include/mach/cdefBF538.h
index 66aa722cf6c8..085b06b8c0a5 100644
--- a/arch/blackfin/mach-bf538/include/mach/cdefBF538.h
+++ b/arch/blackfin/mach-bf538/include/mach/cdefBF538.h
@@ -2027,54 +2027,4 @@
/* These need to be last due to the cdef/linux inter-dependencies */
#include <asm/irq.h>
-/* Writing to PLL_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_PLL_CTL(unsigned int val)
-{
- unsigned long flags, iwr0, iwr1;
-
- if (val == bfin_read_PLL_CTL())
- return;
-
- local_irq_save_hw(flags);
- /* Enable the PLL Wakeup bit in SIC IWR */
- iwr0 = bfin_read32(SIC_IWR0);
- iwr1 = bfin_read32(SIC_IWR1);
- /* Only allow PPL Wakeup) */
- bfin_write32(SIC_IWR0, IWR_ENABLE(0));
- bfin_write32(SIC_IWR1, 0);
-
- bfin_write16(PLL_CTL, val);
- SSYNC();
- asm("IDLE;");
-
- bfin_write32(SIC_IWR0, iwr0);
- bfin_write32(SIC_IWR1, iwr1);
- local_irq_restore_hw(flags);
-}
-
-/* Writing to VR_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_VR_CTL(unsigned int val)
-{
- unsigned long flags, iwr0, iwr1;
-
- if (val == bfin_read_VR_CTL())
- return;
-
- local_irq_save_hw(flags);
- /* Enable the PLL Wakeup bit in SIC IWR */
- iwr0 = bfin_read32(SIC_IWR0);
- iwr1 = bfin_read32(SIC_IWR1);
- /* Only allow PPL Wakeup) */
- bfin_write32(SIC_IWR0, IWR_ENABLE(0));
- bfin_write32(SIC_IWR1, 0);
-
- bfin_write16(VR_CTL, val);
- SSYNC();
- asm("IDLE;");
-
- bfin_write32(SIC_IWR0, iwr0);
- bfin_write32(SIC_IWR1, iwr1);
- local_irq_restore_hw(flags);
-}
-
#endif
diff --git a/arch/blackfin/mach-bf538/include/mach/defBF539.h b/arch/blackfin/mach-bf538/include/mach/defBF539.h
index fe43062b4975..7a8ac5f44204 100644
--- a/arch/blackfin/mach-bf538/include/mach/defBF539.h
+++ b/arch/blackfin/mach-bf538/include/mach/defBF539.h
@@ -32,6 +32,7 @@
/* System Interrupt Controller (0xFFC00100 - 0xFFC001FF) */
#define SWRST 0xFFC00100 /* Software Reset Register (16-bit) */
#define SYSCR 0xFFC00104 /* System Configuration registe */
+#define SIC_RVECT 0xFFC00108
#define SIC_IMASK0 0xFFC0010C /* Interrupt Mask Register */
#define SIC_IAR0 0xFFC00110 /* Interrupt Assignment Register 0 */
#define SIC_IAR1 0xFFC00114 /* Interrupt Assignment Register 1 */
@@ -1894,78 +1895,6 @@
#define PE14_P 0xE
#define PE15_P 0xF
-
-/* *********** SERIAL PERIPHERAL INTERFACE (SPI) MASKS **************** */
-/* SPIx_CTL Masks */
-#define TIMOD 0x0003 /* Transfer Initiate Mode */
-#define RDBR_CORE 0x0000 /* RDBR Read Initiates, IRQ When RDBR Full */
-#define TDBR_CORE 0x0001 /* TDBR Write Initiates, IRQ When TDBR Empty */
-#define RDBR_DMA 0x0002 /* DMA Read, DMA Until FIFO Empty */
-#define TDBR_DMA 0x0003 /* DMA Write, DMA Until FIFO Full */
-#define SZ 0x0004 /* Send Zero (When TDBR Empty, Send Zero/Last*) */
-#define GM 0x0008 /* Get More (When RDBR Full, Overwrite/Discard*) */
-#define PSSE 0x0010 /* Slave-Select Input Enable */
-#define EMISO 0x0020 /* Enable MISO As Output */
-#define SIZE 0x0100 /* Size of Words (16/8* Bits) */
-#define LSBF 0x0200 /* LSB First */
-#define CPHA 0x0400 /* Clock Phase */
-#define CPOL 0x0800 /* Clock Polarity */
-#define MSTR 0x1000 /* Master/Slave* */
-#define WOM 0x2000 /* Write Open Drain Master */
-#define SPE 0x4000 /* SPI Enable */
-
-/* SPIx_FLG Masks */
-#define FLS1 0x0002 /* Enables (=1) SPI_FLOUT1 as flag output for SPI Slave-select */
-#define FLS2 0x0004 /* Enables (=1) SPI_FLOUT2 as flag output for SPI Slave-select */
-#define FLS3 0x0008 /* Enables (=1) SPI_FLOUT3 as flag output for SPI Slave-select */
-#define FLS4 0x0010 /* Enables (=1) SPI_FLOUT4 as flag output for SPI Slave-select */
-#define FLS5 0x0020 /* Enables (=1) SPI_FLOUT5 as flag output for SPI Slave-select */
-#define FLS6 0x0040 /* Enables (=1) SPI_FLOUT6 as flag output for SPI Slave-select */
-#define FLS7 0x0080 /* Enables (=1) SPI_FLOUT7 as flag output for SPI Slave-select */
-
-#define FLG1 0x0200 /* Activates (=0) SPI_FLOUT1 as flag output for SPI Slave-select */
-#define FLG2 0x0400 /* Activates (=0) SPI_FLOUT2 as flag output for SPI Slave-select */
-#define FLG3 0x0800 /* Activates (=0) SPI_FLOUT3 as flag output for SPI Slave-select */
-#define FLG4 0x1000 /* Activates (=0) SPI_FLOUT4 as flag output for SPI Slave-select */
-#define FLG5 0x2000 /* Activates (=0) SPI_FLOUT5 as flag output for SPI Slave-select */
-#define FLG6 0x4000 /* Activates (=0) SPI_FLOUT6 as flag output for SPI Slave-select */
-#define FLG7 0x8000 /* Activates (=0) SPI_FLOUT7 as flag output for SPI Slave-select */
-
-/* SPIx_FLG Bit Positions */
-#define FLS1_P 0x0001 /* Enables (=1) SPI_FLOUT1 as flag output for SPI Slave-select */
-#define FLS2_P 0x0002 /* Enables (=1) SPI_FLOUT2 as flag output for SPI Slave-select */
-#define FLS3_P 0x0003 /* Enables (=1) SPI_FLOUT3 as flag output for SPI Slave-select */
-#define FLS4_P 0x0004 /* Enables (=1) SPI_FLOUT4 as flag output for SPI Slave-select */
-#define FLS5_P 0x0005 /* Enables (=1) SPI_FLOUT5 as flag output for SPI Slave-select */
-#define FLS6_P 0x0006 /* Enables (=1) SPI_FLOUT6 as flag output for SPI Slave-select */
-#define FLS7_P 0x0007 /* Enables (=1) SPI_FLOUT7 as flag output for SPI Slave-select */
-#define FLG1_P 0x0009 /* Activates (=0) SPI_FLOUT1 as flag output for SPI Slave-select */
-#define FLG2_P 0x000A /* Activates (=0) SPI_FLOUT2 as flag output for SPI Slave-select */
-#define FLG3_P 0x000B /* Activates (=0) SPI_FLOUT3 as flag output for SPI Slave-select */
-#define FLG4_P 0x000C /* Activates (=0) SPI_FLOUT4 as flag output for SPI Slave-select */
-#define FLG5_P 0x000D /* Activates (=0) SPI_FLOUT5 as flag output for SPI Slave-select */
-#define FLG6_P 0x000E /* Activates (=0) SPI_FLOUT6 as flag output for SPI Slave-select */
-#define FLG7_P 0x000F /* Activates (=0) SPI_FLOUT7 as flag output for SPI Slave-select */
-
-/* SPIx_STAT Masks */
-#define SPIF 0x0001 /* Set (=1) when SPI single-word transfer complete */
-#define MODF 0x0002 /* Set (=1) in a master device when some other device tries to become master */
-#define TXE 0x0004 /* Set (=1) when transmission occurs with no new data in SPI_TDBR */
-#define TXS 0x0008 /* SPI_TDBR Data Buffer Status (0=Empty, 1=Full) */
-#define RBSY 0x0010 /* Set (=1) when data is received with RDBR full */
-#define RXS 0x0020 /* SPI_RDBR Data Buffer Status (0=Empty, 1=Full) */
-#define TXCOL 0x0040 /* When set (=1), corrupt data may have been transmitted */
-
-/* SPIx_FLG Masks */
-#define FLG1E 0xFDFF /* Activates SPI_FLOUT1 */
-#define FLG2E 0xFBFF /* Activates SPI_FLOUT2 */
-#define FLG3E 0xF7FF /* Activates SPI_FLOUT3 */
-#define FLG4E 0xEFFF /* Activates SPI_FLOUT4 */
-#define FLG5E 0xDFFF /* Activates SPI_FLOUT5 */
-#define FLG6E 0xBFFF /* Activates SPI_FLOUT6 */
-#define FLG7E 0x7FFF /* Activates SPI_FLOUT7 */
-
-
/* ********************* ASYNCHRONOUS MEMORY CONTROLLER MASKS ************* */
/* EBIU_AMGCTL Masks */
#define AMCKEN 0x0001 /* Enable CLKOUT */
diff --git a/arch/blackfin/mach-bf538/include/mach/pll.h b/arch/blackfin/mach-bf538/include/mach/pll.h
new file mode 100644
index 000000000000..b30bbcd412a7
--- /dev/null
+++ b/arch/blackfin/mach-bf538/include/mach/pll.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2008-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef _MACH_PLL_H
+#define _MACH_PLL_H
+
+#include <asm/blackfin.h>
+#include <asm/irqflags.h>
+
+/* Writing to PLL_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_PLL_CTL(unsigned int val)
+{
+ unsigned long flags, iwr0, iwr1;
+
+ if (val == bfin_read_PLL_CTL())
+ return;
+
+ flags = hard_local_irq_save();
+ /* Enable the PLL Wakeup bit in SIC IWR */
+ iwr0 = bfin_read32(SIC_IWR0);
+ iwr1 = bfin_read32(SIC_IWR1);
+ /* Only allow PPL Wakeup) */
+ bfin_write32(SIC_IWR0, IWR_ENABLE(0));
+ bfin_write32(SIC_IWR1, 0);
+
+ bfin_write16(PLL_CTL, val);
+ SSYNC();
+ asm("IDLE;");
+
+ bfin_write32(SIC_IWR0, iwr0);
+ bfin_write32(SIC_IWR1, iwr1);
+ hard_local_irq_restore(flags);
+}
+
+/* Writing to VR_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_VR_CTL(unsigned int val)
+{
+ unsigned long flags, iwr0, iwr1;
+
+ if (val == bfin_read_VR_CTL())
+ return;
+
+ flags = hard_local_irq_save();
+ /* Enable the PLL Wakeup bit in SIC IWR */
+ iwr0 = bfin_read32(SIC_IWR0);
+ iwr1 = bfin_read32(SIC_IWR1);
+ /* Only allow PPL Wakeup) */
+ bfin_write32(SIC_IWR0, IWR_ENABLE(0));
+ bfin_write32(SIC_IWR1, 0);
+
+ bfin_write16(VR_CTL, val);
+ SSYNC();
+ asm("IDLE;");
+
+ bfin_write32(SIC_IWR0, iwr0);
+ bfin_write32(SIC_IWR1, iwr1);
+ hard_local_irq_restore(flags);
+}
+
+#endif /* _MACH_PLL_H */
diff --git a/arch/blackfin/mach-bf548/boards/cm_bf548.c b/arch/blackfin/mach-bf548/boards/cm_bf548.c
index 0c38eec9ade1..f0c0eef95ba8 100644
--- a/arch/blackfin/mach-bf548/boards/cm_bf548.c
+++ b/arch/blackfin/mach-bf548/boards/cm_bf548.c
@@ -753,6 +753,44 @@ static struct platform_device bf54x_sdh_device = {
};
#endif
+#if defined(CONFIG_CAN_BFIN) || defined(CONFIG_CAN_BFIN_MODULE)
+unsigned short bfin_can_peripherals[] = {
+ P_CAN0_RX, P_CAN0_TX, 0
+};
+
+static struct resource bfin_can_resources[] = {
+ {
+ .start = 0xFFC02A00,
+ .end = 0xFFC02FFF,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_CAN0_RX,
+ .end = IRQ_CAN0_RX,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = IRQ_CAN0_TX,
+ .end = IRQ_CAN0_TX,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = IRQ_CAN0_ERROR,
+ .end = IRQ_CAN0_ERROR,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device bfin_can_device = {
+ .name = "bfin_can",
+ .num_resources = ARRAY_SIZE(bfin_can_resources),
+ .resource = bfin_can_resources,
+ .dev = {
+ .platform_data = &bfin_can_peripherals, /* Passed to driver */
+ },
+};
+#endif
+
#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
static struct mtd_partition para_partitions[] = {
{
@@ -928,7 +966,7 @@ static struct resource bfin_spi1_resource[] = {
/* SPI controller data */
static struct bfin5xx_spi_master bf54x_spi_master_info0 = {
- .num_chipselect = 3,
+ .num_chipselect = 4,
.enable_dma = 1, /* master has the ability to do dma transfer */
.pin_req = {P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0},
};
@@ -944,7 +982,7 @@ static struct platform_device bf54x_spi_master0 = {
};
static struct bfin5xx_spi_master bf54x_spi_master_info1 = {
- .num_chipselect = 3,
+ .num_chipselect = 4,
.enable_dma = 1, /* master has the ability to do dma transfer */
.pin_req = {P_SPI1_SCK, P_SPI1_MISO, P_SPI1_MOSI, 0},
};
@@ -1152,6 +1190,11 @@ static struct platform_device *cm_bf548_devices[] __initdata = {
#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
&para_flash_device,
#endif
+
+#if defined(CONFIG_CAN_BFIN) || defined(CONFIG_CAN_BFIN_MODULE)
+ &bfin_can_device,
+#endif
+
};
static int __init cm_bf548_init(void)
diff --git a/arch/blackfin/mach-bf548/boards/ezkit.c b/arch/blackfin/mach-bf548/boards/ezkit.c
index 56682a36e42d..216e26999af9 100644
--- a/arch/blackfin/mach-bf548/boards/ezkit.c
+++ b/arch/blackfin/mach-bf548/boards/ezkit.c
@@ -837,8 +837,12 @@ static struct platform_device bfin_atapi_device = {
#if defined(CONFIG_MTD_NAND_BF5XX) || defined(CONFIG_MTD_NAND_BF5XX_MODULE)
static struct mtd_partition partition_info[] = {
{
- .name = "linux kernel(nand)",
+ .name = "bootloader(nand)",
.offset = 0,
+ .size = 0x80000,
+ }, {
+ .name = "linux kernel(nand)",
+ .offset = MTDPART_OFS_APPEND,
.size = 4 * 1024 * 1024,
},
{
@@ -901,7 +905,7 @@ static struct platform_device bf54x_sdh_device = {
static struct mtd_partition ezkit_partitions[] = {
{
.name = "bootloader(nor)",
- .size = 0x40000,
+ .size = 0x80000,
.offset = 0,
}, {
.name = "linux kernel(nor)",
@@ -943,7 +947,7 @@ static struct platform_device ezkit_flash_device = {
static struct mtd_partition bfin_spi_flash_partitions[] = {
{
.name = "bootloader(spi)",
- .size = 0x00040000,
+ .size = 0x00080000,
.offset = 0,
.mask_flags = MTD_CAP_ROM
}, {
@@ -966,8 +970,8 @@ static struct bfin5xx_spi_chip spi_flash_chip_info = {
};
#endif
-#if defined(CONFIG_SND_BLACKFIN_AD183X) \
- || defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
+ || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
.enable_dma = 0,
.bits_per_word = 16,
@@ -1023,13 +1027,13 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.mode = SPI_MODE_3,
},
#endif
-#if defined(CONFIG_SND_BLACKFIN_AD183X) \
- || defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
+ || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
{
- .modalias = "ad1836",
+ .modalias = "ad183x",
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 1,
- .chip_select = CONFIG_SND_BLACKFIN_SPI_PFBIT,
+ .chip_select = 4,
.controller_data = &ad1836_spi_chip_info,
},
#endif
@@ -1107,7 +1111,7 @@ static struct resource bfin_spi1_resource[] = {
/* SPI controller data */
static struct bfin5xx_spi_master bf54x_spi_master_info0 = {
- .num_chipselect = 3,
+ .num_chipselect = 4,
.enable_dma = 1, /* master has the ability to do dma transfer */
.pin_req = {P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0},
};
@@ -1123,7 +1127,7 @@ static struct platform_device bf54x_spi_master0 = {
};
static struct bfin5xx_spi_master bf54x_spi_master_info1 = {
- .num_chipselect = 3,
+ .num_chipselect = 4,
.enable_dma = 1, /* master has the ability to do dma transfer */
.pin_req = {P_SPI1_SCK, P_SPI1_MISO, P_SPI1_MOSI, 0},
};
@@ -1206,6 +1210,11 @@ static struct i2c_board_info __initdata bfin_i2c_board_info1[] = {
.platform_data = (void *)&adxl34x_info,
},
#endif
+#if defined(CONFIG_BFIN_TWI_LCD) || defined(CONFIG_BFIN_TWI_LCD_MODULE)
+ {
+ I2C_BOARD_INFO("ad5252", 0x2f),
+ },
+#endif
};
#endif
diff --git a/arch/blackfin/mach-bf548/dma.c b/arch/blackfin/mach-bf548/dma.c
index 039a6d9d38f3..888b9cc0b822 100644
--- a/arch/blackfin/mach-bf548/dma.c
+++ b/arch/blackfin/mach-bf548/dma.c
@@ -63,6 +63,7 @@ int channel2irq(unsigned int channel)
break;
case CH_SPORT1_TX:
ret_irq = IRQ_SPORT1_TX;
+ break;
case CH_SPI0:
ret_irq = IRQ_SPI0;
break;
diff --git a/arch/blackfin/mach-bf548/include/mach/cdefBF54x_base.h b/arch/blackfin/mach-bf548/include/mach/cdefBF54x_base.h
index ea3ec4ea9e2b..deaf5d6542d5 100644
--- a/arch/blackfin/mach-bf548/include/mach/cdefBF54x_base.h
+++ b/arch/blackfin/mach-bf548/include/mach/cdefBF54x_base.h
@@ -40,6 +40,8 @@
/* SIC Registers */
+#define bfin_read_SIC_RVECT() bfin_read32(SIC_RVECT)
+#define bfin_write_SIC_RVECT(val) bfin_write32(SIC_RVECT, val)
#define bfin_read_SIC_IMASK0() bfin_read32(SIC_IMASK0)
#define bfin_write_SIC_IMASK0(val) bfin_write32(SIC_IMASK0, val)
#define bfin_read_SIC_IMASK1() bfin_read32(SIC_IMASK1)
@@ -2648,61 +2650,5 @@
/* These need to be last due to the cdef/linux inter-dependencies */
#include <asm/irq.h>
-/* Writing to PLL_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_PLL_CTL(unsigned int val)
-{
- unsigned long flags, iwr0, iwr1, iwr2;
-
- if (val == bfin_read_PLL_CTL())
- return;
-
- local_irq_save_hw(flags);
- /* Enable the PLL Wakeup bit in SIC IWR */
- iwr0 = bfin_read32(SIC_IWR0);
- iwr1 = bfin_read32(SIC_IWR1);
- iwr2 = bfin_read32(SIC_IWR2);
- /* Only allow PPL Wakeup) */
- bfin_write32(SIC_IWR0, IWR_ENABLE(0));
- bfin_write32(SIC_IWR1, 0);
- bfin_write32(SIC_IWR2, 0);
-
- bfin_write16(PLL_CTL, val);
- SSYNC();
- asm("IDLE;");
-
- bfin_write32(SIC_IWR0, iwr0);
- bfin_write32(SIC_IWR1, iwr1);
- bfin_write32(SIC_IWR2, iwr2);
- local_irq_restore_hw(flags);
-}
-
-/* Writing to VR_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_VR_CTL(unsigned int val)
-{
- unsigned long flags, iwr0, iwr1, iwr2;
-
- if (val == bfin_read_VR_CTL())
- return;
-
- local_irq_save_hw(flags);
- /* Enable the PLL Wakeup bit in SIC IWR */
- iwr0 = bfin_read32(SIC_IWR0);
- iwr1 = bfin_read32(SIC_IWR1);
- iwr2 = bfin_read32(SIC_IWR2);
- /* Only allow PPL Wakeup) */
- bfin_write32(SIC_IWR0, IWR_ENABLE(0));
- bfin_write32(SIC_IWR1, 0);
- bfin_write32(SIC_IWR2, 0);
-
- bfin_write16(VR_CTL, val);
- SSYNC();
- asm("IDLE;");
-
- bfin_write32(SIC_IWR0, iwr0);
- bfin_write32(SIC_IWR1, iwr1);
- bfin_write32(SIC_IWR2, iwr2);
- local_irq_restore_hw(flags);
-}
-
#endif /* _CDEF_BF54X_H */
diff --git a/arch/blackfin/mach-bf548/include/mach/defBF54x_base.h b/arch/blackfin/mach-bf548/include/mach/defBF54x_base.h
index 7866197f5485..78f91103f175 100644
--- a/arch/blackfin/mach-bf548/include/mach/defBF54x_base.h
+++ b/arch/blackfin/mach-bf548/include/mach/defBF54x_base.h
@@ -35,6 +35,7 @@
/* SIC Registers */
+#define SIC_RVECT 0xffc00108
#define SIC_IMASK0 0xffc0010c /* System Interrupt Mask Register 0 */
#define SIC_IMASK1 0xffc00110 /* System Interrupt Mask Register 1 */
#define SIC_IMASK2 0xffc00114 /* System Interrupt Mask Register 2 */
@@ -2061,56 +2062,6 @@
#define LOW_EVEN 0xff0000 /* Lower Limit for Even Bytes (Luma) */
#define HIGH_EVEN 0xff000000 /* Upper Limit for Even Bytes (Luma) */
-/* Bit masks for SPIx_BAUD */
-
-#define SPI_BAUD 0xffff /* Baud Rate */
-
-/* Bit masks for SPIx_CTL */
-
-#define SPE 0x4000 /* SPI Enable */
-#define WOM 0x2000 /* Write Open Drain Master */
-#define MSTR 0x1000 /* Master Mode */
-#define CPOL 0x800 /* Clock Polarity */
-#define CPHA 0x400 /* Clock Phase */
-#define LSBF 0x200 /* LSB First */
-#define SIZE 0x100 /* Size of Words */
-#define EMISO 0x20 /* Enable MISO Output */
-#define PSSE 0x10 /* Slave-Select Enable */
-#define GM 0x8 /* Get More Data */
-#define SZ 0x4 /* Send Zero */
-#define TIMOD 0x3 /* Transfer Initiation Mode */
-
-/* Bit masks for SPIx_FLG */
-
-#define FLS1 0x2 /* Slave Select Enable 1 */
-#define FLS2 0x4 /* Slave Select Enable 2 */
-#define FLS3 0x8 /* Slave Select Enable 3 */
-#define FLG1 0x200 /* Slave Select Value 1 */
-#define FLG2 0x400 /* Slave Select Value 2 */
-#define FLG3 0x800 /* Slave Select Value 3 */
-
-/* Bit masks for SPIx_STAT */
-
-#define TXCOL 0x40 /* Transmit Collision Error */
-#define RXS 0x20 /* RDBR Data Buffer Status */
-#define RBSY 0x10 /* Receive Error */
-#define TXS 0x8 /* TDBR Data Buffer Status */
-#define TXE 0x4 /* Transmission Error */
-#define MODF 0x2 /* Mode Fault Error */
-#define SPIF 0x1 /* SPI Finished */
-
-/* Bit masks for SPIx_TDBR */
-
-#define TDBR 0xffff /* Transmit Data Buffer */
-
-/* Bit masks for SPIx_RDBR */
-
-#define RDBR 0xffff /* Receive Data Buffer */
-
-/* Bit masks for SPIx_SHADOW */
-
-#define SHADOW 0xffff /* RDBR Shadow */
-
/* ************************************************ */
/* The TWI bit masks fields are from the ADSP-BF538 */
/* and they have not been verified as the final */
diff --git a/arch/blackfin/mach-bf548/include/mach/pll.h b/arch/blackfin/mach-bf548/include/mach/pll.h
new file mode 100644
index 000000000000..7865a090d333
--- /dev/null
+++ b/arch/blackfin/mach-bf548/include/mach/pll.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2007-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef _MACH_PLL_H
+#define _MACH_PLL_H
+
+#include <asm/blackfin.h>
+#include <asm/irqflags.h>
+
+/* Writing to PLL_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_PLL_CTL(unsigned int val)
+{
+ unsigned long flags, iwr0, iwr1, iwr2;
+
+ if (val == bfin_read_PLL_CTL())
+ return;
+
+ flags = hard_local_irq_save();
+ /* Enable the PLL Wakeup bit in SIC IWR */
+ iwr0 = bfin_read32(SIC_IWR0);
+ iwr1 = bfin_read32(SIC_IWR1);
+ iwr2 = bfin_read32(SIC_IWR2);
+ /* Only allow PPL Wakeup) */
+ bfin_write32(SIC_IWR0, IWR_ENABLE(0));
+ bfin_write32(SIC_IWR1, 0);
+ bfin_write32(SIC_IWR2, 0);
+
+ bfin_write16(PLL_CTL, val);
+ SSYNC();
+ asm("IDLE;");
+
+ bfin_write32(SIC_IWR0, iwr0);
+ bfin_write32(SIC_IWR1, iwr1);
+ bfin_write32(SIC_IWR2, iwr2);
+ hard_local_irq_restore(flags);
+}
+
+/* Writing to VR_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_VR_CTL(unsigned int val)
+{
+ unsigned long flags, iwr0, iwr1, iwr2;
+
+ if (val == bfin_read_VR_CTL())
+ return;
+
+ flags = hard_local_irq_save();
+ /* Enable the PLL Wakeup bit in SIC IWR */
+ iwr0 = bfin_read32(SIC_IWR0);
+ iwr1 = bfin_read32(SIC_IWR1);
+ iwr2 = bfin_read32(SIC_IWR2);
+ /* Only allow PPL Wakeup) */
+ bfin_write32(SIC_IWR0, IWR_ENABLE(0));
+ bfin_write32(SIC_IWR1, 0);
+ bfin_write32(SIC_IWR2, 0);
+
+ bfin_write16(VR_CTL, val);
+ SSYNC();
+ asm("IDLE;");
+
+ bfin_write32(SIC_IWR0, iwr0);
+ bfin_write32(SIC_IWR1, iwr1);
+ bfin_write32(SIC_IWR2, iwr2);
+ hard_local_irq_restore(flags);
+}
+
+#endif /* _MACH_PLL_H */
diff --git a/arch/blackfin/mach-bf561/boards/acvilon.c b/arch/blackfin/mach-bf561/boards/acvilon.c
index 35b6d124c1e3..0b1c20f14fe0 100644
--- a/arch/blackfin/mach-bf561/boards/acvilon.c
+++ b/arch/blackfin/mach-bf561/boards/acvilon.c
@@ -302,7 +302,7 @@ static struct platform_nand_data bfin_plat_nand_data = {
static struct resource bfin_plat_nand_resources = {
.start = 0x24000000,
.end = 0x24000000 + (1 << MAX(BFIN_NAND_PLAT_CLE, BFIN_NAND_PLAT_ALE)),
- .flags = IORESOURCE_IO,
+ .flags = IORESOURCE_MEM,
};
static struct platform_device bfin_async_nand_device = {
diff --git a/arch/blackfin/mach-bf561/boards/cm_bf561.c b/arch/blackfin/mach-bf561/boards/cm_bf561.c
index e127aedc1d7f..087b6b05cc73 100644
--- a/arch/blackfin/mach-bf561/boards/cm_bf561.c
+++ b/arch/blackfin/mach-bf561/boards/cm_bf561.c
@@ -72,7 +72,7 @@ static struct bfin5xx_spi_chip spi_adc_chip_info = {
};
#endif
-#if defined(CONFIG_SND_BLACKFIN_AD183X) || defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
.enable_dma = 0,
.bits_per_word = 16,
@@ -111,12 +111,12 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
},
#endif
-#if defined(CONFIG_SND_BLACKFIN_AD183X) || defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
{
- .modalias = "ad1836",
+ .modalias = "ad183x",
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
- .chip_select = CONFIG_SND_BLACKFIN_SPI_PFBIT,
+ .chip_select = 4,
.controller_data = &ad1836_spi_chip_info,
},
#endif
@@ -278,7 +278,7 @@ static struct resource isp1362_hcd_resources[] = {
}, {
.start = IRQ_PF47,
.end = IRQ_PF47,
- .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
},
};
diff --git a/arch/blackfin/mach-bf561/boards/ezkit.c b/arch/blackfin/mach-bf561/boards/ezkit.c
index 9b93e2f95791..ab7a487975fd 100644
--- a/arch/blackfin/mach-bf561/boards/ezkit.c
+++ b/arch/blackfin/mach-bf561/boards/ezkit.c
@@ -14,6 +14,7 @@
#include <linux/spi/spi.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
+#include <linux/delay.h>
#include <asm/dma.h>
#include <asm/bfin5xx_spi.h>
#include <asm/portmux.h>
@@ -74,7 +75,7 @@ static struct resource isp1362_hcd_resources[] = {
}, {
.start = IRQ_PF8,
.end = IRQ_PF8,
- .flags = IORESOURCE_IRQ,
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
},
};
@@ -274,8 +275,8 @@ static struct platform_device ezkit_flash_device = {
};
#endif
-#if defined(CONFIG_SND_BLACKFIN_AD183X) \
- || defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
+ || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
.enable_dma = 0,
.bits_per_word = 16,
@@ -328,14 +329,16 @@ static struct platform_device bfin_spi0_device = {
#endif
static struct spi_board_info bfin_spi_board_info[] __initdata = {
-#if defined(CONFIG_SND_BLACKFIN_AD183X) \
- || defined(CONFIG_SND_BLACKFIN_AD183X_MODULE)
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) \
+ || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
{
- .modalias = "ad1836",
+ .modalias = "ad183x",
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
- .chip_select = CONFIG_SND_BLACKFIN_SPI_PFBIT,
+ .chip_select = 4,
+ .platform_data = "ad1836", /* only includes chip name for the moment */
.controller_data = &ad1836_spi_chip_info,
+ .mode = SPI_MODE_3,
},
#endif
#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
@@ -377,8 +380,8 @@ static struct platform_device bfin_device_gpiokeys = {
#include <linux/i2c-gpio.h>
static struct i2c_gpio_platform_data i2c_gpio_data = {
- .sda_pin = 1,
- .scl_pin = 0,
+ .sda_pin = GPIO_PF1,
+ .scl_pin = GPIO_PF0,
.sda_is_open_drain = 0,
.scl_is_open_drain = 0,
.udelay = 40,
@@ -420,6 +423,30 @@ static struct platform_device bfin_dpmc = {
},
};
+#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE)
+static struct platform_device bfin_i2s = {
+ .name = "bfin-i2s",
+ .id = CONFIG_SND_BF5XX_SPORT_NUM,
+ /* TODO: add platform data here */
+};
+#endif
+
+#if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE)
+static struct platform_device bfin_tdm = {
+ .name = "bfin-tdm",
+ .id = CONFIG_SND_BF5XX_SPORT_NUM,
+ /* TODO: add platform data here */
+};
+#endif
+
+#if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE)
+static struct platform_device bfin_ac97 = {
+ .name = "bfin-ac97",
+ .id = CONFIG_SND_BF5XX_SPORT_NUM,
+ /* TODO: add platform data here */
+};
+#endif
+
static struct platform_device *ezkit_devices[] __initdata = {
&bfin_dpmc,
@@ -467,6 +494,18 @@ static struct platform_device *ezkit_devices[] __initdata = {
#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
&ezkit_flash_device,
#endif
+
+#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE)
+ &bfin_i2s,
+#endif
+
+#if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE)
+ &bfin_tdm,
+#endif
+
+#if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE)
+ &bfin_ac97,
+#endif
};
static int __init ezkit_init(void)
@@ -484,6 +523,17 @@ static int __init ezkit_init(void)
SSYNC();
#endif
+#if defined(CONFIG_SND_BF5XX_SOC_AD183X) || defined(CONFIG_SND_BF5XX_SOC_AD183X_MODULE)
+ bfin_write_FIO0_DIR(bfin_read_FIO0_DIR() | (1 << 15));
+ bfin_write_FIO0_FLAG_S(1 << 15);
+ SSYNC();
+ /*
+ * This initialization lasts for approximately 4500 MCLKs.
+ * MCLK = 12.288MHz
+ */
+ udelay(400);
+#endif
+
spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
return 0;
}
diff --git a/arch/blackfin/mach-bf561/coreb.c b/arch/blackfin/mach-bf561/coreb.c
index deb2271d09a3..78ecb50bafc8 100644
--- a/arch/blackfin/mach-bf561/coreb.c
+++ b/arch/blackfin/mach-bf561/coreb.c
@@ -18,9 +18,9 @@
#include <linux/miscdevice.h>
#include <linux/module.h>
-#define CMD_COREB_START 2
-#define CMD_COREB_STOP 3
-#define CMD_COREB_RESET 4
+#define CMD_COREB_START _IO('b', 0)
+#define CMD_COREB_STOP _IO('b', 1)
+#define CMD_COREB_RESET _IO('b', 2)
static long
coreb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
@@ -29,10 +29,10 @@ coreb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
switch (cmd) {
case CMD_COREB_START:
- bfin_write_SICA_SYSCR(bfin_read_SICA_SYSCR() & ~0x0020);
+ bfin_write_SYSCR(bfin_read_SYSCR() & ~0x0020);
break;
case CMD_COREB_STOP:
- bfin_write_SICA_SYSCR(bfin_read_SICA_SYSCR() | 0x0020);
+ bfin_write_SYSCR(bfin_read_SYSCR() | 0x0020);
bfin_write_SICB_SYSCR(bfin_read_SICB_SYSCR() | 0x0080);
break;
case CMD_COREB_RESET:
@@ -51,6 +51,7 @@ coreb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
static const struct file_operations coreb_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = coreb_ioctl,
+ .llseek = noop_llseek,
};
static struct miscdevice coreb_dev = {
@@ -73,3 +74,4 @@ module_exit(bf561_coreb_exit);
MODULE_AUTHOR("Bas Vermeulen <bvermeul@blackstar.xs4all.nl>");
MODULE_DESCRIPTION("BF561 Core B Support");
+MODULE_LICENSE("GPL");
diff --git a/arch/blackfin/mach-bf561/include/mach/blackfin.h b/arch/blackfin/mach-bf561/include/mach/blackfin.h
index 67d6bdcd3fa8..6c7dc58c018c 100644
--- a/arch/blackfin/mach-bf561/include/mach/blackfin.h
+++ b/arch/blackfin/mach-bf561/include/mach/blackfin.h
@@ -24,29 +24,16 @@
#define bfin_read_FIO_INEN() bfin_read_FIO0_INEN()
#define bfin_write_FIO_INEN(val) bfin_write_FIO0_INEN(val)
-#define SIC_IWR0 SICA_IWR0
-#define SIC_IWR1 SICA_IWR1
-#define SIC_IAR0 SICA_IAR0
-#define bfin_write_SIC_IMASK0 bfin_write_SICA_IMASK0
-#define bfin_write_SIC_IMASK1 bfin_write_SICA_IMASK1
-#define bfin_write_SIC_IWR0 bfin_write_SICA_IWR0
-#define bfin_write_SIC_IWR1 bfin_write_SICA_IWR1
-
-#define bfin_read_SIC_IMASK0 bfin_read_SICA_IMASK0
-#define bfin_read_SIC_IMASK1 bfin_read_SICA_IMASK1
-#define bfin_read_SIC_IWR0 bfin_read_SICA_IWR0
-#define bfin_read_SIC_IWR1 bfin_read_SICA_IWR1
-#define bfin_read_SIC_ISR0 bfin_read_SICA_ISR0
-#define bfin_read_SIC_ISR1 bfin_read_SICA_ISR1
-
-#define bfin_read_SIC_IMASK(x) bfin_read32(SICA_IMASK0 + (x << 2))
-#define bfin_write_SIC_IMASK(x, val) bfin_write32((SICA_IMASK0 + (x << 2)), val)
-#define bfin_read_SICB_IMASK(x) bfin_read32(SICB_IMASK0 + (x << 2))
-#define bfin_write_SICB_IMASK(x, val) bfin_write32((SICB_IMASK0 + (x << 2)), val)
-#define bfin_read_SIC_ISR(x) bfin_read32(SICA_ISR0 + (x << 2))
-#define bfin_write_SIC_ISR(x, val) bfin_write32((SICA_ISR0 + (x << 2)), val)
-#define bfin_read_SICB_ISR(x) bfin_read32(SICB_ISR0 + (x << 2))
-#define bfin_write_SICB_ISR(x, val) bfin_write32((SICB_ISR0 + (x << 2)), val)
+/* Weird muxer funcs which pick SIC regs from IMASK base */
+#define __SIC_MUX(base, x) ((base) + ((x) << 2))
+#define bfin_read_SIC_IMASK(x) bfin_read32(__SIC_MUX(SIC_IMASK0, x))
+#define bfin_write_SIC_IMASK(x, val) bfin_write32(__SIC_MUX(SIC_IMASK0, x), val)
+#define bfin_read_SICB_IMASK(x) bfin_read32(__SIC_MUX(SICB_IMASK0, x))
+#define bfin_write_SICB_IMASK(x, val) bfin_write32(__SIC_MUX(SICB_IMASK0, x), val)
+#define bfin_read_SIC_ISR(x) bfin_read32(__SIC_MUX(SIC_ISR0, x))
+#define bfin_write_SIC_ISR(x, val) bfin_write32(__SIC_MUX(SIC_ISR0, x), val)
+#define bfin_read_SICB_ISR(x) bfin_read32(__SIC_MUX(SICB_ISR0, x))
+#define bfin_write_SICB_ISR(x, val) bfin_write32(__SIC_MUX(SICB_ISR0, x), val)
#define BFIN_UART_NR_PORTS 1
diff --git a/arch/blackfin/mach-bf561/include/mach/cdefBF561.h b/arch/blackfin/mach-bf561/include/mach/cdefBF561.h
index 81ecdb71c6af..2bab99152495 100644
--- a/arch/blackfin/mach-bf561/include/mach/cdefBF561.h
+++ b/arch/blackfin/mach-bf561/include/mach/cdefBF561.h
@@ -30,49 +30,41 @@
#define bfin_write_PLL_LOCKCNT(val) bfin_write16(PLL_LOCKCNT,val)
#define bfin_read_CHIPID() bfin_read32(CHIPID)
-/* For MMR's that are reserved on Core B, set up defines to better integrate with other ports */
-#define bfin_read_SWRST() bfin_read_SICA_SWRST()
-#define bfin_write_SWRST(val) bfin_write_SICA_SWRST(val)
-#define bfin_read_SYSCR() bfin_read_SICA_SYSCR()
-#define bfin_write_SYSCR(val) bfin_write_SICA_SYSCR(val)
-
/* System Reset and Interrupt Controller registers for core A (0xFFC0 0100-0xFFC0 01FF) */
-#define bfin_read_SICA_SWRST() bfin_read16(SICA_SWRST)
-#define bfin_write_SICA_SWRST(val) bfin_write16(SICA_SWRST,val)
-#define bfin_read_SICA_SYSCR() bfin_read16(SICA_SYSCR)
-#define bfin_write_SICA_SYSCR(val) bfin_write16(SICA_SYSCR,val)
-#define bfin_read_SICA_RVECT() bfin_read16(SICA_RVECT)
-#define bfin_write_SICA_RVECT(val) bfin_write16(SICA_RVECT,val)
-#define bfin_read_SICA_IMASK() bfin_read32(SICA_IMASK)
-#define bfin_write_SICA_IMASK(val) bfin_write32(SICA_IMASK,val)
-#define bfin_read_SICA_IMASK0() bfin_read32(SICA_IMASK0)
-#define bfin_write_SICA_IMASK0(val) bfin_write32(SICA_IMASK0,val)
-#define bfin_read_SICA_IMASK1() bfin_read32(SICA_IMASK1)
-#define bfin_write_SICA_IMASK1(val) bfin_write32(SICA_IMASK1,val)
-#define bfin_read_SICA_IAR0() bfin_read32(SICA_IAR0)
-#define bfin_write_SICA_IAR0(val) bfin_write32(SICA_IAR0,val)
-#define bfin_read_SICA_IAR1() bfin_read32(SICA_IAR1)
-#define bfin_write_SICA_IAR1(val) bfin_write32(SICA_IAR1,val)
-#define bfin_read_SICA_IAR2() bfin_read32(SICA_IAR2)
-#define bfin_write_SICA_IAR2(val) bfin_write32(SICA_IAR2,val)
-#define bfin_read_SICA_IAR3() bfin_read32(SICA_IAR3)
-#define bfin_write_SICA_IAR3(val) bfin_write32(SICA_IAR3,val)
-#define bfin_read_SICA_IAR4() bfin_read32(SICA_IAR4)
-#define bfin_write_SICA_IAR4(val) bfin_write32(SICA_IAR4,val)
-#define bfin_read_SICA_IAR5() bfin_read32(SICA_IAR5)
-#define bfin_write_SICA_IAR5(val) bfin_write32(SICA_IAR5,val)
-#define bfin_read_SICA_IAR6() bfin_read32(SICA_IAR6)
-#define bfin_write_SICA_IAR6(val) bfin_write32(SICA_IAR6,val)
-#define bfin_read_SICA_IAR7() bfin_read32(SICA_IAR7)
-#define bfin_write_SICA_IAR7(val) bfin_write32(SICA_IAR7,val)
-#define bfin_read_SICA_ISR0() bfin_read32(SICA_ISR0)
-#define bfin_write_SICA_ISR0(val) bfin_write32(SICA_ISR0,val)
-#define bfin_read_SICA_ISR1() bfin_read32(SICA_ISR1)
-#define bfin_write_SICA_ISR1(val) bfin_write32(SICA_ISR1,val)
-#define bfin_read_SICA_IWR0() bfin_read32(SICA_IWR0)
-#define bfin_write_SICA_IWR0(val) bfin_write32(SICA_IWR0,val)
-#define bfin_read_SICA_IWR1() bfin_read32(SICA_IWR1)
-#define bfin_write_SICA_IWR1(val) bfin_write32(SICA_IWR1,val)
+#define bfin_read_SWRST() bfin_read16(SWRST)
+#define bfin_write_SWRST(val) bfin_write16(SWRST,val)
+#define bfin_read_SYSCR() bfin_read16(SYSCR)
+#define bfin_write_SYSCR(val) bfin_write16(SYSCR,val)
+#define bfin_read_SIC_RVECT() bfin_read16(SIC_RVECT)
+#define bfin_write_SIC_RVECT(val) bfin_write16(SIC_RVECT,val)
+#define bfin_read_SIC_IMASK0() bfin_read32(SIC_IMASK0)
+#define bfin_write_SIC_IMASK0(val) bfin_write32(SIC_IMASK0,val)
+#define bfin_read_SIC_IMASK1() bfin_read32(SIC_IMASK1)
+#define bfin_write_SIC_IMASK1(val) bfin_write32(SIC_IMASK1,val)
+#define bfin_read_SIC_IAR0() bfin_read32(SIC_IAR0)
+#define bfin_write_SIC_IAR0(val) bfin_write32(SIC_IAR0,val)
+#define bfin_read_SIC_IAR1() bfin_read32(SIC_IAR1)
+#define bfin_write_SIC_IAR1(val) bfin_write32(SIC_IAR1,val)
+#define bfin_read_SIC_IAR2() bfin_read32(SIC_IAR2)
+#define bfin_write_SIC_IAR2(val) bfin_write32(SIC_IAR2,val)
+#define bfin_read_SIC_IAR3() bfin_read32(SIC_IAR3)
+#define bfin_write_SIC_IAR3(val) bfin_write32(SIC_IAR3,val)
+#define bfin_read_SIC_IAR4() bfin_read32(SIC_IAR4)
+#define bfin_write_SIC_IAR4(val) bfin_write32(SIC_IAR4,val)
+#define bfin_read_SIC_IAR5() bfin_read32(SIC_IAR5)
+#define bfin_write_SIC_IAR5(val) bfin_write32(SIC_IAR5,val)
+#define bfin_read_SIC_IAR6() bfin_read32(SIC_IAR6)
+#define bfin_write_SIC_IAR6(val) bfin_write32(SIC_IAR6,val)
+#define bfin_read_SIC_IAR7() bfin_read32(SIC_IAR7)
+#define bfin_write_SIC_IAR7(val) bfin_write32(SIC_IAR7,val)
+#define bfin_read_SIC_ISR0() bfin_read32(SIC_ISR0)
+#define bfin_write_SIC_ISR0(val) bfin_write32(SIC_ISR0,val)
+#define bfin_read_SIC_ISR1() bfin_read32(SIC_ISR1)
+#define bfin_write_SIC_ISR1(val) bfin_write32(SIC_ISR1,val)
+#define bfin_read_SIC_IWR0() bfin_read32(SIC_IWR0)
+#define bfin_write_SIC_IWR0(val) bfin_write32(SIC_IWR0,val)
+#define bfin_read_SIC_IWR1() bfin_read32(SIC_IWR1)
+#define bfin_write_SIC_IWR1(val) bfin_write32(SIC_IWR1,val)
/* System Reset and Interrupt Controller registers for Core B (0xFFC0 1100-0xFFC0 11FF) */
#define bfin_read_SICB_SWRST() bfin_read16(SICB_SWRST)
@@ -1534,54 +1526,4 @@
/* These need to be last due to the cdef/linux inter-dependencies */
#include <asm/irq.h>
-/* Writing to PLL_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_PLL_CTL(unsigned int val)
-{
- unsigned long flags, iwr0, iwr1;
-
- if (val == bfin_read_PLL_CTL())
- return;
-
- local_irq_save_hw(flags);
- /* Enable the PLL Wakeup bit in SIC IWR */
- iwr0 = bfin_read32(SICA_IWR0);
- iwr1 = bfin_read32(SICA_IWR1);
- /* Only allow PPL Wakeup) */
- bfin_write32(SICA_IWR0, IWR_ENABLE(0));
- bfin_write32(SICA_IWR1, 0);
-
- bfin_write16(PLL_CTL, val);
- SSYNC();
- asm("IDLE;");
-
- bfin_write32(SICA_IWR0, iwr0);
- bfin_write32(SICA_IWR1, iwr1);
- local_irq_restore_hw(flags);
-}
-
-/* Writing to VR_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_VR_CTL(unsigned int val)
-{
- unsigned long flags, iwr0, iwr1;
-
- if (val == bfin_read_VR_CTL())
- return;
-
- local_irq_save_hw(flags);
- /* Enable the PLL Wakeup bit in SIC IWR */
- iwr0 = bfin_read32(SICA_IWR0);
- iwr1 = bfin_read32(SICA_IWR1);
- /* Only allow PPL Wakeup) */
- bfin_write32(SICA_IWR0, IWR_ENABLE(0));
- bfin_write32(SICA_IWR1, 0);
-
- bfin_write16(VR_CTL, val);
- SSYNC();
- asm("IDLE;");
-
- bfin_write32(SICA_IWR0, iwr0);
- bfin_write32(SICA_IWR1, iwr1);
- local_irq_restore_hw(flags);
-}
-
#endif /* _CDEF_BF561_H */
diff --git a/arch/blackfin/mach-bf561/include/mach/defBF561.h b/arch/blackfin/mach-bf561/include/mach/defBF561.h
index 2674f0097576..79e048d452e0 100644
--- a/arch/blackfin/mach-bf561/include/mach/defBF561.h
+++ b/arch/blackfin/mach-bf561/include/mach/defBF561.h
@@ -28,32 +28,29 @@
#define CHIPID 0xFFC00014 /* Chip ID Register */
/* For MMR's that are reserved on Core B, set up defines to better integrate with other ports */
-#define SWRST SICA_SWRST
-#define SYSCR SICA_SYSCR
#define DOUBLE_FAULT (DOUBLE_FAULT_B|DOUBLE_FAULT_A)
#define RESET_DOUBLE (SWRST_DBL_FAULT_B|SWRST_DBL_FAULT_A)
#define RESET_WDOG (SWRST_WDT_B|SWRST_WDT_A)
#define RESET_SOFTWARE (SWRST_OCCURRED)
/* System Reset and Interrupt Controller registers for core A (0xFFC0 0100-0xFFC0 01FF) */
-#define SICA_SWRST 0xFFC00100 /* Software Reset register */
-#define SICA_SYSCR 0xFFC00104 /* System Reset Configuration register */
-#define SICA_RVECT 0xFFC00108 /* SIC Reset Vector Address Register */
-#define SICA_IMASK 0xFFC0010C /* SIC Interrupt Mask register 0 - hack to fix old tests */
-#define SICA_IMASK0 0xFFC0010C /* SIC Interrupt Mask register 0 */
-#define SICA_IMASK1 0xFFC00110 /* SIC Interrupt Mask register 1 */
-#define SICA_IAR0 0xFFC00124 /* SIC Interrupt Assignment Register 0 */
-#define SICA_IAR1 0xFFC00128 /* SIC Interrupt Assignment Register 1 */
-#define SICA_IAR2 0xFFC0012C /* SIC Interrupt Assignment Register 2 */
-#define SICA_IAR3 0xFFC00130 /* SIC Interrupt Assignment Register 3 */
-#define SICA_IAR4 0xFFC00134 /* SIC Interrupt Assignment Register 4 */
-#define SICA_IAR5 0xFFC00138 /* SIC Interrupt Assignment Register 5 */
-#define SICA_IAR6 0xFFC0013C /* SIC Interrupt Assignment Register 6 */
-#define SICA_IAR7 0xFFC00140 /* SIC Interrupt Assignment Register 7 */
-#define SICA_ISR0 0xFFC00114 /* SIC Interrupt Status register 0 */
-#define SICA_ISR1 0xFFC00118 /* SIC Interrupt Status register 1 */
-#define SICA_IWR0 0xFFC0011C /* SIC Interrupt Wakeup-Enable register 0 */
-#define SICA_IWR1 0xFFC00120 /* SIC Interrupt Wakeup-Enable register 1 */
+#define SWRST 0xFFC00100 /* Software Reset register */
+#define SYSCR 0xFFC00104 /* System Reset Configuration register */
+#define SIC_RVECT 0xFFC00108 /* SIC Reset Vector Address Register */
+#define SIC_IMASK0 0xFFC0010C /* SIC Interrupt Mask register 0 */
+#define SIC_IMASK1 0xFFC00110 /* SIC Interrupt Mask register 1 */
+#define SIC_IAR0 0xFFC00124 /* SIC Interrupt Assignment Register 0 */
+#define SIC_IAR1 0xFFC00128 /* SIC Interrupt Assignment Register 1 */
+#define SIC_IAR2 0xFFC0012C /* SIC Interrupt Assignment Register 2 */
+#define SIC_IAR3 0xFFC00130 /* SIC Interrupt Assignment Register 3 */
+#define SIC_IAR4 0xFFC00134 /* SIC Interrupt Assignment Register 4 */
+#define SIC_IAR5 0xFFC00138 /* SIC Interrupt Assignment Register 5 */
+#define SIC_IAR6 0xFFC0013C /* SIC Interrupt Assignment Register 6 */
+#define SIC_IAR7 0xFFC00140 /* SIC Interrupt Assignment Register 7 */
+#define SIC_ISR0 0xFFC00114 /* SIC Interrupt Status register 0 */
+#define SIC_ISR1 0xFFC00118 /* SIC Interrupt Status register 1 */
+#define SIC_IWR0 0xFFC0011C /* SIC Interrupt Wakeup-Enable register 0 */
+#define SIC_IWR1 0xFFC00120 /* SIC Interrupt Wakeup-Enable register 1 */
/* System Reset and Interrupt Controller registers for Core B (0xFFC0 1100-0xFFC0 11FF) */
#define SICB_SWRST 0xFFC01100 /* reserved */
@@ -1271,63 +1268,6 @@
#define PF14_P 14
#define PF15_P 15
-/* *********** SERIAL PERIPHERAL INTERFACE (SPI) MASKS **************** */
-
-/* SPI_CTL Masks */
-#define TIMOD 0x00000003 /* Transfer initiation mode and interrupt generation */
-#define SZ 0x00000004 /* Send Zero (=0) or last (=1) word when TDBR empty. */
-#define GM 0x00000008 /* When RDBR full, get more (=1) data or discard (=0) incoming Data */
-#define PSSE 0x00000010 /* Enable (=1) Slave-Select input for Master. */
-#define EMISO 0x00000020 /* Enable (=1) MISO pin as an output. */
-#define SIZE 0x00000100 /* Word length (0 => 8 bits, 1 => 16 bits) */
-#define LSBF 0x00000200 /* Data format (0 => MSB sent/received first 1 => LSB sent/received first) */
-#define CPHA 0x00000400 /* Clock phase (0 => SPICLK starts toggling in middle of xfer, 1 => SPICLK toggles at the beginning of xfer. */
-#define CPOL 0x00000800 /* Clock polarity (0 => active-high, 1 => active-low) */
-#define MSTR 0x00001000 /* Configures SPI as master (=1) or slave (=0) */
-#define WOM 0x00002000 /* Open drain (=1) data output enable (for MOSI and MISO) */
-#define SPE 0x00004000 /* SPI module enable (=1), disable (=0) */
-
-/* SPI_FLG Masks */
-#define FLS1 0x00000002 /* Enables (=1) SPI_FLOUT1 as flag output for SPI Slave-select */
-#define FLS2 0x00000004 /* Enables (=1) SPI_FLOUT2 as flag output for SPI Slave-select */
-#define FLS3 0x00000008 /* Enables (=1) SPI_FLOUT3 as flag output for SPI Slave-select */
-#define FLS4 0x00000010 /* Enables (=1) SPI_FLOUT4 as flag output for SPI Slave-select */
-#define FLS5 0x00000020 /* Enables (=1) SPI_FLOUT5 as flag output for SPI Slave-select */
-#define FLS6 0x00000040 /* Enables (=1) SPI_FLOUT6 as flag output for SPI Slave-select */
-#define FLS7 0x00000080 /* Enables (=1) SPI_FLOUT7 as flag output for SPI Slave-select */
-#define FLG1 0x00000200 /* Activates (=0) SPI_FLOUT1 as flag output for SPI Slave-select */
-#define FLG2 0x00000400 /* Activates (=0) SPI_FLOUT2 as flag output for SPI Slave-select */
-#define FLG3 0x00000800 /* Activates (=0) SPI_FLOUT3 as flag output for SPI Slave-select */
-#define FLG4 0x00001000 /* Activates (=0) SPI_FLOUT4 as flag output for SPI Slave-select */
-#define FLG5 0x00002000 /* Activates (=0) SPI_FLOUT5 as flag output for SPI Slave-select */
-#define FLG6 0x00004000 /* Activates (=0) SPI_FLOUT6 as flag output for SPI Slave-select */
-#define FLG7 0x00008000 /* Activates (=0) SPI_FLOUT7 as flag output for SPI Slave-select */
-
-/* SPI_FLG Bit Positions */
-#define FLS1_P 0x00000001 /* Enables (=1) SPI_FLOUT1 as flag output for SPI Slave-select */
-#define FLS2_P 0x00000002 /* Enables (=1) SPI_FLOUT2 as flag output for SPI Slave-select */
-#define FLS3_P 0x00000003 /* Enables (=1) SPI_FLOUT3 as flag output for SPI Slave-select */
-#define FLS4_P 0x00000004 /* Enables (=1) SPI_FLOUT4 as flag output for SPI Slave-select */
-#define FLS5_P 0x00000005 /* Enables (=1) SPI_FLOUT5 as flag output for SPI Slave-select */
-#define FLS6_P 0x00000006 /* Enables (=1) SPI_FLOUT6 as flag output for SPI Slave-select */
-#define FLS7_P 0x00000007 /* Enables (=1) SPI_FLOUT7 as flag output for SPI Slave-select */
-#define FLG1_P 0x00000009 /* Activates (=0) SPI_FLOUT1 as flag output for SPI Slave-select */
-#define FLG2_P 0x0000000A /* Activates (=0) SPI_FLOUT2 as flag output for SPI Slave-select */
-#define FLG3_P 0x0000000B /* Activates (=0) SPI_FLOUT3 as flag output for SPI Slave-select */
-#define FLG4_P 0x0000000C /* Activates (=0) SPI_FLOUT4 as flag output for SPI Slave-select */
-#define FLG5_P 0x0000000D /* Activates (=0) SPI_FLOUT5 as flag output for SPI Slave-select */
-#define FLG6_P 0x0000000E /* Activates (=0) SPI_FLOUT6 as flag output for SPI Slave-select */
-#define FLG7_P 0x0000000F /* Activates (=0) SPI_FLOUT7 as flag output for SPI Slave-select */
-
-/* SPI_STAT Masks */
-#define SPIF 0x00000001 /* Set (=1) when SPI single-word transfer complete */
-#define MODF 0x00000002 /* Set (=1) in a master device when some other device tries to become master */
-#define TXE 0x00000004 /* Set (=1) when transmission occurs with no new data in SPI_TDBR */
-#define TXS 0x00000008 /* SPI_TDBR Data Buffer Status (0=Empty, 1=Full) */
-#define RBSY 0x00000010 /* Set (=1) when data is received with RDBR full */
-#define RXS 0x00000020 /* SPI_RDBR Data Buffer Status (0=Empty, 1=Full) */
-#define TXCOL 0x00000040 /* When set (=1), corrupt data may have been transmitted */
-
/* ********************* ASYNCHRONOUS MEMORY CONTROLLER MASKS ************* */
/* AMGCTL Masks */
diff --git a/arch/blackfin/mach-bf561/include/mach/pll.h b/arch/blackfin/mach-bf561/include/mach/pll.h
new file mode 100644
index 000000000000..f2b1fbdb8e72
--- /dev/null
+++ b/arch/blackfin/mach-bf561/include/mach/pll.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2005-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef _MACH_PLL_H
+#define _MACH_PLL_H
+
+#include <asm/blackfin.h>
+#include <asm/irqflags.h>
+
+/* Writing to PLL_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_PLL_CTL(unsigned int val)
+{
+ unsigned long flags, iwr0, iwr1;
+
+ if (val == bfin_read_PLL_CTL())
+ return;
+
+ flags = hard_local_irq_save();
+ /* Enable the PLL Wakeup bit in SIC IWR */
+ iwr0 = bfin_read32(SICA_IWR0);
+ iwr1 = bfin_read32(SICA_IWR1);
+ /* Only allow PPL Wakeup) */
+ bfin_write32(SICA_IWR0, IWR_ENABLE(0));
+ bfin_write32(SICA_IWR1, 0);
+
+ bfin_write16(PLL_CTL, val);
+ SSYNC();
+ asm("IDLE;");
+
+ bfin_write32(SICA_IWR0, iwr0);
+ bfin_write32(SICA_IWR1, iwr1);
+ hard_local_irq_restore(flags);
+}
+
+/* Writing to VR_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_VR_CTL(unsigned int val)
+{
+ unsigned long flags, iwr0, iwr1;
+
+ if (val == bfin_read_VR_CTL())
+ return;
+
+ flags = hard_local_irq_save();
+ /* Enable the PLL Wakeup bit in SIC IWR */
+ iwr0 = bfin_read32(SICA_IWR0);
+ iwr1 = bfin_read32(SICA_IWR1);
+ /* Only allow PPL Wakeup) */
+ bfin_write32(SICA_IWR0, IWR_ENABLE(0));
+ bfin_write32(SICA_IWR1, 0);
+
+ bfin_write16(VR_CTL, val);
+ SSYNC();
+ asm("IDLE;");
+
+ bfin_write32(SICA_IWR0, iwr0);
+ bfin_write32(SICA_IWR1, iwr1);
+ hard_local_irq_restore(flags);
+}
+
+#endif /* _MACH_PLL_H */
diff --git a/arch/blackfin/mach-bf561/ints-priority.c b/arch/blackfin/mach-bf561/ints-priority.c
index b4424172ad9e..7ee9262fe132 100644
--- a/arch/blackfin/mach-bf561/ints-priority.c
+++ b/arch/blackfin/mach-bf561/ints-priority.c
@@ -13,7 +13,7 @@
void __init program_IAR(void)
{
/* Program the IAR0 Register with the configured priority */
- bfin_write_SICA_IAR0(((CONFIG_IRQ_PLL_WAKEUP - 7) << IRQ_PLL_WAKEUP_POS) |
+ bfin_write_SIC_IAR0(((CONFIG_IRQ_PLL_WAKEUP - 7) << IRQ_PLL_WAKEUP_POS) |
((CONFIG_IRQ_DMA1_ERROR - 7) << IRQ_DMA1_ERROR_POS) |
((CONFIG_IRQ_DMA2_ERROR - 7) << IRQ_DMA2_ERROR_POS) |
((CONFIG_IRQ_IMDMA_ERROR - 7) << IRQ_IMDMA_ERROR_POS) |
@@ -22,7 +22,7 @@ void __init program_IAR(void)
((CONFIG_IRQ_SPORT0_ERROR - 7) << IRQ_SPORT0_ERROR_POS) |
((CONFIG_IRQ_SPORT1_ERROR - 7) << IRQ_SPORT1_ERROR_POS));
- bfin_write_SICA_IAR1(((CONFIG_IRQ_SPI_ERROR - 7) << IRQ_SPI_ERROR_POS) |
+ bfin_write_SIC_IAR1(((CONFIG_IRQ_SPI_ERROR - 7) << IRQ_SPI_ERROR_POS) |
((CONFIG_IRQ_UART_ERROR - 7) << IRQ_UART_ERROR_POS) |
((CONFIG_IRQ_RESERVED_ERROR - 7) << IRQ_RESERVED_ERROR_POS) |
((CONFIG_IRQ_DMA1_0 - 7) << IRQ_DMA1_0_POS) |
@@ -31,7 +31,7 @@ void __init program_IAR(void)
((CONFIG_IRQ_DMA1_3 - 7) << IRQ_DMA1_3_POS) |
((CONFIG_IRQ_DMA1_4 - 7) << IRQ_DMA1_4_POS));
- bfin_write_SICA_IAR2(((CONFIG_IRQ_DMA1_5 - 7) << IRQ_DMA1_5_POS) |
+ bfin_write_SIC_IAR2(((CONFIG_IRQ_DMA1_5 - 7) << IRQ_DMA1_5_POS) |
((CONFIG_IRQ_DMA1_6 - 7) << IRQ_DMA1_6_POS) |
((CONFIG_IRQ_DMA1_7 - 7) << IRQ_DMA1_7_POS) |
((CONFIG_IRQ_DMA1_8 - 7) << IRQ_DMA1_8_POS) |
@@ -40,7 +40,7 @@ void __init program_IAR(void)
((CONFIG_IRQ_DMA1_11 - 7) << IRQ_DMA1_11_POS) |
((CONFIG_IRQ_DMA2_0 - 7) << IRQ_DMA2_0_POS));
- bfin_write_SICA_IAR3(((CONFIG_IRQ_DMA2_1 - 7) << IRQ_DMA2_1_POS) |
+ bfin_write_SIC_IAR3(((CONFIG_IRQ_DMA2_1 - 7) << IRQ_DMA2_1_POS) |
((CONFIG_IRQ_DMA2_2 - 7) << IRQ_DMA2_2_POS) |
((CONFIG_IRQ_DMA2_3 - 7) << IRQ_DMA2_3_POS) |
((CONFIG_IRQ_DMA2_4 - 7) << IRQ_DMA2_4_POS) |
@@ -49,7 +49,7 @@ void __init program_IAR(void)
((CONFIG_IRQ_DMA2_7 - 7) << IRQ_DMA2_7_POS) |
((CONFIG_IRQ_DMA2_8 - 7) << IRQ_DMA2_8_POS));
- bfin_write_SICA_IAR4(((CONFIG_IRQ_DMA2_9 - 7) << IRQ_DMA2_9_POS) |
+ bfin_write_SIC_IAR4(((CONFIG_IRQ_DMA2_9 - 7) << IRQ_DMA2_9_POS) |
((CONFIG_IRQ_DMA2_10 - 7) << IRQ_DMA2_10_POS) |
((CONFIG_IRQ_DMA2_11 - 7) << IRQ_DMA2_11_POS) |
((CONFIG_IRQ_TIMER0 - 7) << IRQ_TIMER0_POS) |
@@ -58,7 +58,7 @@ void __init program_IAR(void)
((CONFIG_IRQ_TIMER3 - 7) << IRQ_TIMER3_POS) |
((CONFIG_IRQ_TIMER4 - 7) << IRQ_TIMER4_POS));
- bfin_write_SICA_IAR5(((CONFIG_IRQ_TIMER5 - 7) << IRQ_TIMER5_POS) |
+ bfin_write_SIC_IAR5(((CONFIG_IRQ_TIMER5 - 7) << IRQ_TIMER5_POS) |
((CONFIG_IRQ_TIMER6 - 7) << IRQ_TIMER6_POS) |
((CONFIG_IRQ_TIMER7 - 7) << IRQ_TIMER7_POS) |
((CONFIG_IRQ_TIMER8 - 7) << IRQ_TIMER8_POS) |
@@ -67,7 +67,7 @@ void __init program_IAR(void)
((CONFIG_IRQ_TIMER11 - 7) << IRQ_TIMER11_POS) |
((CONFIG_IRQ_PROG0_INTA - 7) << IRQ_PROG0_INTA_POS));
- bfin_write_SICA_IAR6(((CONFIG_IRQ_PROG0_INTB - 7) << IRQ_PROG0_INTB_POS) |
+ bfin_write_SIC_IAR6(((CONFIG_IRQ_PROG0_INTB - 7) << IRQ_PROG0_INTB_POS) |
((CONFIG_IRQ_PROG1_INTA - 7) << IRQ_PROG1_INTA_POS) |
((CONFIG_IRQ_PROG1_INTB - 7) << IRQ_PROG1_INTB_POS) |
((CONFIG_IRQ_PROG2_INTA - 7) << IRQ_PROG2_INTA_POS) |
@@ -76,7 +76,7 @@ void __init program_IAR(void)
((CONFIG_IRQ_DMA1_WRRD1 - 7) << IRQ_DMA1_WRRD1_POS) |
((CONFIG_IRQ_DMA2_WRRD0 - 7) << IRQ_DMA2_WRRD0_POS));
- bfin_write_SICA_IAR7(((CONFIG_IRQ_DMA2_WRRD1 - 7) << IRQ_DMA2_WRRD1_POS) |
+ bfin_write_SIC_IAR7(((CONFIG_IRQ_DMA2_WRRD1 - 7) << IRQ_DMA2_WRRD1_POS) |
((CONFIG_IRQ_IMDMA_WRRD0 - 7) << IRQ_IMDMA_WRRD0_POS) |
((CONFIG_IRQ_IMDMA_WRRD1 - 7) << IRQ_IMDMA_WRRD1_POS) |
((CONFIG_IRQ_WDTIMER - 7) << IRQ_WDTIMER_POS) |
diff --git a/arch/blackfin/mach-bf561/smp.c b/arch/blackfin/mach-bf561/smp.c
index 3b9a4bf7dacc..f540ed1257d6 100644
--- a/arch/blackfin/mach-bf561/smp.c
+++ b/arch/blackfin/mach-bf561/smp.c
@@ -52,19 +52,19 @@ int __init setup_profiling_timer(unsigned int multiplier) /* not supported */
void __cpuinit platform_secondary_init(unsigned int cpu)
{
/* Clone setup for peripheral interrupt sources from CoreA. */
- bfin_write_SICB_IMASK0(bfin_read_SICA_IMASK0());
- bfin_write_SICB_IMASK1(bfin_read_SICA_IMASK1());
+ bfin_write_SICB_IMASK0(bfin_read_SIC_IMASK0());
+ bfin_write_SICB_IMASK1(bfin_read_SIC_IMASK1());
SSYNC();
/* Clone setup for IARs from CoreA. */
- bfin_write_SICB_IAR0(bfin_read_SICA_IAR0());
- bfin_write_SICB_IAR1(bfin_read_SICA_IAR1());
- bfin_write_SICB_IAR2(bfin_read_SICA_IAR2());
- bfin_write_SICB_IAR3(bfin_read_SICA_IAR3());
- bfin_write_SICB_IAR4(bfin_read_SICA_IAR4());
- bfin_write_SICB_IAR5(bfin_read_SICA_IAR5());
- bfin_write_SICB_IAR6(bfin_read_SICA_IAR6());
- bfin_write_SICB_IAR7(bfin_read_SICA_IAR7());
+ bfin_write_SICB_IAR0(bfin_read_SIC_IAR0());
+ bfin_write_SICB_IAR1(bfin_read_SIC_IAR1());
+ bfin_write_SICB_IAR2(bfin_read_SIC_IAR2());
+ bfin_write_SICB_IAR3(bfin_read_SIC_IAR3());
+ bfin_write_SICB_IAR4(bfin_read_SIC_IAR4());
+ bfin_write_SICB_IAR5(bfin_read_SIC_IAR5());
+ bfin_write_SICB_IAR6(bfin_read_SIC_IAR6());
+ bfin_write_SICB_IAR7(bfin_read_SIC_IAR7());
bfin_write_SICB_IWR0(IWR_DISABLE_ALL);
bfin_write_SICB_IWR1(IWR_DISABLE_ALL);
SSYNC();
@@ -86,12 +86,12 @@ int __cpuinit platform_boot_secondary(unsigned int cpu, struct task_struct *idle
spin_lock(&boot_lock);
- if ((bfin_read_SICA_SYSCR() & COREB_SRAM_INIT) == 0) {
+ if ((bfin_read_SIC_SYSCR() & COREB_SRAM_INIT) == 0) {
/* CoreB already running, sending ipi to wakeup it */
platform_send_ipi_cpu(cpu, IRQ_SUPPLE_0);
} else {
/* Kick CoreB, which should start execution from CORE_SRAM_BASE. */
- bfin_write_SICA_SYSCR(bfin_read_SICA_SYSCR() & ~COREB_SRAM_INIT);
+ bfin_write_SIC_SYSCR(bfin_read_SIC_SYSCR() & ~COREB_SRAM_INIT);
SSYNC();
}
diff --git a/arch/blackfin/mach-common/cpufreq.c b/arch/blackfin/mach-common/cpufreq.c
index 4391d03dc845..f4cf11d362e1 100644
--- a/arch/blackfin/mach-common/cpufreq.c
+++ b/arch/blackfin/mach-common/cpufreq.c
@@ -134,7 +134,7 @@ static int bfin_target(struct cpufreq_policy *poli,
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
if (cpu == CPUFREQ_CPU) {
- local_irq_save_hw(flags);
+ flags = hard_local_irq_save();
plldiv = (bfin_read_PLL_DIV() & SSEL) |
dpm_state_table[index].csel;
bfin_write_PLL_DIV(plldiv);
@@ -155,7 +155,7 @@ static int bfin_target(struct cpufreq_policy *poli,
loops_per_jiffy = cpufreq_scale(lpj_ref,
lpj_ref_freq, freqs.new);
}
- local_irq_restore_hw(flags);
+ hard_local_irq_restore(flags);
}
/* TODO: just test case for cycles clock source, remove later */
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
diff --git a/arch/blackfin/mach-common/dpmc_modes.S b/arch/blackfin/mach-common/dpmc_modes.S
index 5969d86836a5..9cfdd49a3127 100644
--- a/arch/blackfin/mach-common/dpmc_modes.S
+++ b/arch/blackfin/mach-common/dpmc_modes.S
@@ -292,13 +292,7 @@ ENTRY(_do_hibernate)
#ifdef SIC_IMASK
PM_SYS_PUSH(SIC_IMASK)
#endif
-#ifdef SICA_IMASK0
- PM_SYS_PUSH(SICA_IMASK0)
-#endif
-#ifdef SICA_IMASK1
- PM_SYS_PUSH(SICA_IMASK1)
-#endif
-#ifdef SIC_IAR2
+#ifdef SIC_IAR0
PM_SYS_PUSH(SIC_IAR0)
PM_SYS_PUSH(SIC_IAR1)
PM_SYS_PUSH(SIC_IAR2)
@@ -321,17 +315,6 @@ ENTRY(_do_hibernate)
PM_SYS_PUSH(SIC_IAR11)
#endif
-#ifdef SICA_IAR0
- PM_SYS_PUSH(SICA_IAR0)
- PM_SYS_PUSH(SICA_IAR1)
- PM_SYS_PUSH(SICA_IAR2)
- PM_SYS_PUSH(SICA_IAR3)
- PM_SYS_PUSH(SICA_IAR4)
- PM_SYS_PUSH(SICA_IAR5)
- PM_SYS_PUSH(SICA_IAR6)
- PM_SYS_PUSH(SICA_IAR7)
-#endif
-
#ifdef SIC_IWR
PM_SYS_PUSH(SIC_IWR)
#endif
@@ -344,12 +327,6 @@ ENTRY(_do_hibernate)
#ifdef SIC_IWR2
PM_SYS_PUSH(SIC_IWR2)
#endif
-#ifdef SICA_IWR0
- PM_SYS_PUSH(SICA_IWR0)
-#endif
-#ifdef SICA_IWR1
- PM_SYS_PUSH(SICA_IWR1)
-#endif
#ifdef PINT0_ASSIGN
PM_SYS_PUSH(PINT0_MASK_SET)
@@ -750,12 +727,6 @@ ENTRY(_do_hibernate)
PM_SYS_POP(PINT0_MASK_SET)
#endif
-#ifdef SICA_IWR1
- PM_SYS_POP(SICA_IWR1)
-#endif
-#ifdef SICA_IWR0
- PM_SYS_POP(SICA_IWR0)
-#endif
#ifdef SIC_IWR2
PM_SYS_POP(SIC_IWR2)
#endif
@@ -769,17 +740,6 @@ ENTRY(_do_hibernate)
PM_SYS_POP(SIC_IWR)
#endif
-#ifdef SICA_IAR0
- PM_SYS_POP(SICA_IAR7)
- PM_SYS_POP(SICA_IAR6)
- PM_SYS_POP(SICA_IAR5)
- PM_SYS_POP(SICA_IAR4)
- PM_SYS_POP(SICA_IAR3)
- PM_SYS_POP(SICA_IAR2)
- PM_SYS_POP(SICA_IAR1)
- PM_SYS_POP(SICA_IAR0)
-#endif
-
#ifdef SIC_IAR8
PM_SYS_POP(SIC_IAR11)
PM_SYS_POP(SIC_IAR10)
@@ -797,17 +757,11 @@ ENTRY(_do_hibernate)
#ifdef SIC_IAR3
PM_SYS_POP(SIC_IAR3)
#endif
-#ifdef SIC_IAR2
+#ifdef SIC_IAR0
PM_SYS_POP(SIC_IAR2)
PM_SYS_POP(SIC_IAR1)
PM_SYS_POP(SIC_IAR0)
#endif
-#ifdef SICA_IMASK1
- PM_SYS_POP(SICA_IMASK1)
-#endif
-#ifdef SICA_IMASK0
- PM_SYS_POP(SICA_IMASK0)
-#endif
#ifdef SIC_IMASK
PM_SYS_POP(SIC_IMASK)
#endif
diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S
index af1bffa21dc1..2ca915ee181f 100644
--- a/arch/blackfin/mach-common/entry.S
+++ b/arch/blackfin/mach-common/entry.S
@@ -889,6 +889,66 @@ ENTRY(_ret_from_exception)
rts;
ENDPROC(_ret_from_exception)
+#if defined(CONFIG_PREEMPT)
+
+ENTRY(_up_to_irq14)
+#if ANOMALY_05000281 || ANOMALY_05000461
+ r0.l = lo(SAFE_USER_INSTRUCTION);
+ r0.h = hi(SAFE_USER_INSTRUCTION);
+ reti = r0;
+#endif
+
+#ifdef CONFIG_DEBUG_HWERR
+ /* enable irq14 & hwerr interrupt, until we transition to _evt_evt14 */
+ r0 = (EVT_IVG14 | EVT_IVHW | EVT_IRPTEN | EVT_EVX | EVT_NMI | EVT_RST | EVT_EMU);
+#else
+ /* Only enable irq14 interrupt, until we transition to _evt_evt14 */
+ r0 = (EVT_IVG14 | EVT_IRPTEN | EVT_EVX | EVT_NMI | EVT_RST | EVT_EMU);
+#endif
+ sti r0;
+
+ p0.l = lo(EVT14);
+ p0.h = hi(EVT14);
+ p1.l = _evt_up_evt14;
+ p1.h = _evt_up_evt14;
+ [p0] = p1;
+ csync;
+
+ raise 14;
+1:
+ jump 1b;
+ENDPROC(_up_to_irq14)
+
+ENTRY(_evt_up_evt14)
+#ifdef CONFIG_DEBUG_HWERR
+ r0 = (EVT_IVHW | EVT_IRPTEN | EVT_EVX | EVT_NMI | EVT_RST | EVT_EMU);
+ sti r0;
+#else
+ cli r0;
+#endif
+#ifdef CONFIG_TRACE_IRQFLAGS
+ [--sp] = rets;
+ sp += -12;
+ call _trace_hardirqs_off;
+ sp += 12;
+ rets = [sp++];
+#endif
+ [--sp] = RETI;
+ SP += 4;
+
+ /* restore normal evt14 */
+ p0.l = lo(EVT14);
+ p0.h = hi(EVT14);
+ p1.l = _evt_evt14;
+ p1.h = _evt_evt14;
+ [p0] = p1;
+ csync;
+
+ rts;
+ENDPROC(_evt_up_evt14)
+
+#endif
+
#ifdef CONFIG_IPIPE
_resume_kernel_from_int:
@@ -902,8 +962,54 @@ _resume_kernel_from_int:
( r7:4, p5:3 ) = [sp++];
rets = [sp++];
rts
+#elif defined(CONFIG_PREEMPT)
+
+_resume_kernel_from_int:
+ /* check preempt_count */
+ r7 = sp;
+ r4.l = lo(ALIGN_PAGE_MASK);
+ r4.h = hi(ALIGN_PAGE_MASK);
+ r7 = r7 & r4;
+ p5 = r7;
+ r7 = [p5 + TI_PREEMPT];
+ cc = r7 == 0x0;
+ if !cc jump .Lreturn_to_kernel;
+.Lneed_schedule:
+ r7 = [p5 + TI_FLAGS];
+ r4.l = lo(_TIF_WORK_MASK);
+ r4.h = hi(_TIF_WORK_MASK);
+ r7 = r7 & r4;
+ cc = BITTST(r7, TIF_NEED_RESCHED);
+ if !cc jump .Lreturn_to_kernel;
+ /*
+ * let schedule done at level 15, otherwise sheduled process will run
+ * at high level and block low level interrupt
+ */
+ r6 = reti; /* save reti */
+ r5.l = .Lkernel_schedule;
+ r5.h = .Lkernel_schedule;
+ reti = r5;
+ rti;
+.Lkernel_schedule:
+ [--sp] = rets;
+ sp += -12;
+ pseudo_long_call _preempt_schedule_irq, p4;
+ sp += 12;
+ rets = [sp++];
+
+ [--sp] = rets;
+ sp += -12;
+ /* up to irq14 so that reti after restore_all can return to irq15(kernel) */
+ pseudo_long_call _up_to_irq14, p4;
+ sp += 12;
+ rets = [sp++];
+
+ reti = r6; /* restore reti so that origin process can return to interrupted point */
+
+ jump .Lneed_schedule;
#else
-#define _resume_kernel_from_int 2f
+
+#define _resume_kernel_from_int .Lreturn_to_kernel
#endif
ENTRY(_return_from_int)
@@ -913,7 +1019,7 @@ ENTRY(_return_from_int)
p2.h = hi(ILAT);
r0 = [p2];
cc = bittst (r0, EVT_IVG15_P);
- if cc jump 2f;
+ if cc jump .Lreturn_to_kernel;
/* if not return to user mode, get out */
p2.l = lo(IPEND);
@@ -945,7 +1051,7 @@ ENTRY(_return_from_int)
STI r0;
raise 15; /* raise evt15 to do signal or reschedule */
rti;
-2:
+.Lreturn_to_kernel:
rts;
ENDPROC(_return_from_int)
@@ -1631,6 +1737,7 @@ ENTRY(_sys_call_table)
.long _sys_fanotify_init
.long _sys_fanotify_mark
.long _sys_prlimit64
+ .long _sys_cacheflush
.rept NR_syscalls-(.-_sys_call_table)/4
.long _sys_ni_syscall
diff --git a/arch/blackfin/mach-common/interrupt.S b/arch/blackfin/mach-common/interrupt.S
index cee62cf4acd4..2df37db3b49b 100644
--- a/arch/blackfin/mach-common/interrupt.S
+++ b/arch/blackfin/mach-common/interrupt.S
@@ -116,7 +116,24 @@ __common_int_entry:
cc = r0 == 0;
if cc jump .Lcommon_restore_context;
#else /* CONFIG_IPIPE */
+
+#ifdef CONFIG_PREEMPT
+ r7 = sp;
+ r4.l = lo(ALIGN_PAGE_MASK);
+ r4.h = hi(ALIGN_PAGE_MASK);
+ r7 = r7 & r4;
+ p5 = r7;
+ r7 = [p5 + TI_PREEMPT]; /* get preempt count */
+ r7 += 1; /* increment it */
+ [p5 + TI_PREEMPT] = r7;
+#endif
pseudo_long_call _do_irq, p2;
+
+#ifdef CONFIG_PREEMPT
+ r7 += -1;
+ [p5 + TI_PREEMPT] = r7; /* restore preempt count */
+#endif
+
SP += 12;
#endif /* CONFIG_IPIPE */
pseudo_long_call _return_from_int, p2;
diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c
index 1c8c4c7245c3..da7e3c63746b 100644
--- a/arch/blackfin/mach-common/ints-priority.c
+++ b/arch/blackfin/mach-common/ints-priority.c
@@ -132,8 +132,8 @@ static void bfin_ack_noop(unsigned int irq)
static void bfin_core_mask_irq(unsigned int irq)
{
bfin_irq_flags &= ~(1 << irq);
- if (!irqs_disabled_hw())
- local_irq_enable_hw();
+ if (!hard_irqs_disabled())
+ hard_local_irq_enable();
}
static void bfin_core_unmask_irq(unsigned int irq)
@@ -148,8 +148,8 @@ static void bfin_core_unmask_irq(unsigned int irq)
* local_irq_enable just does "STI bfin_irq_flags", so it's exactly
* what we need.
*/
- if (!irqs_disabled_hw())
- local_irq_enable_hw();
+ if (!hard_irqs_disabled())
+ hard_local_irq_enable();
return;
}
@@ -158,12 +158,12 @@ static void bfin_internal_mask_irq(unsigned int irq)
unsigned long flags;
#ifdef CONFIG_BF53x
- local_irq_save_hw(flags);
+ flags = hard_local_irq_save();
bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() &
~(1 << SIC_SYSIRQ(irq)));
#else
unsigned mask_bank, mask_bit;
- local_irq_save_hw(flags);
+ flags = hard_local_irq_save();
mask_bank = SIC_SYSIRQ(irq) / 32;
mask_bit = SIC_SYSIRQ(irq) % 32;
bfin_write_SIC_IMASK(mask_bank, bfin_read_SIC_IMASK(mask_bank) &
@@ -173,7 +173,7 @@ static void bfin_internal_mask_irq(unsigned int irq)
~(1 << mask_bit));
#endif
#endif
- local_irq_restore_hw(flags);
+ hard_local_irq_restore(flags);
}
#ifdef CONFIG_SMP
@@ -186,12 +186,12 @@ static void bfin_internal_unmask_irq(unsigned int irq)
unsigned long flags;
#ifdef CONFIG_BF53x
- local_irq_save_hw(flags);
+ flags = hard_local_irq_save();
bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() |
(1 << SIC_SYSIRQ(irq)));
#else
unsigned mask_bank, mask_bit;
- local_irq_save_hw(flags);
+ flags = hard_local_irq_save();
mask_bank = SIC_SYSIRQ(irq) / 32;
mask_bit = SIC_SYSIRQ(irq) % 32;
#ifdef CONFIG_SMP
@@ -207,7 +207,7 @@ static void bfin_internal_unmask_irq(unsigned int irq)
(1 << mask_bit));
#endif
#endif
- local_irq_restore_hw(flags);
+ hard_local_irq_restore(flags);
}
#ifdef CONFIG_SMP
@@ -264,7 +264,7 @@ int bfin_internal_set_wake(unsigned int irq, unsigned int state)
break;
}
- local_irq_save_hw(flags);
+ flags = hard_local_irq_save();
if (state) {
bfin_sic_iwr[bank] |= (1 << bit);
@@ -275,7 +275,7 @@ int bfin_internal_set_wake(unsigned int irq, unsigned int state)
vr_wakeup &= ~wakeup;
}
- local_irq_restore_hw(flags);
+ hard_local_irq_restore(flags);
return 0;
}
@@ -511,7 +511,7 @@ static void bfin_demux_mac_status_irq(unsigned int int_err_irq,
int i, irq = 0;
u32 status = bfin_read_EMAC_SYSTAT();
- for (i = 0; i < (IRQ_MAC_STMDONE - IRQ_MAC_PHYINT); i++)
+ for (i = 0; i <= (IRQ_MAC_STMDONE - IRQ_MAC_PHYINT); i++)
if (status & (1L << i)) {
irq = IRQ_MAC_PHYINT + i;
break;
@@ -529,8 +529,9 @@ static void bfin_demux_mac_status_irq(unsigned int int_err_irq,
} else
printk(KERN_ERR
"%s : %s : LINE %d :\nIRQ ?: MAC ERROR"
- " INTERRUPT ASSERTED BUT NO SOURCE FOUND\n",
- __func__, __FILE__, __LINE__);
+ " INTERRUPT ASSERTED BUT NO SOURCE FOUND"
+ "(EMAC_SYSTAT=0x%X)\n",
+ __func__, __FILE__, __LINE__, status);
}
#endif
@@ -1298,7 +1299,7 @@ void do_irq(int vec, struct pt_regs *fp)
} else {
struct ivgx *ivg = ivg7_13[vec - IVG7].ifirst;
struct ivgx *ivg_stop = ivg7_13[vec - IVG7].istop;
-#if defined(SIC_ISR0) || defined(SICA_ISR0)
+#if defined(SIC_ISR0)
unsigned long sic_status[3];
if (smp_processor_id()) {
@@ -1378,7 +1379,7 @@ asmlinkage int __ipipe_grab_irq(int vec, struct pt_regs *regs)
if (likely(vec == EVT_IVTMR_P))
irq = IRQ_CORETMR;
else {
-#if defined(SIC_ISR0) || defined(SICA_ISR0)
+#if defined(SIC_ISR0)
unsigned long sic_status[3];
sic_status[0] = bfin_read_SIC_ISR0() & bfin_read_SIC_IMASK0();
diff --git a/arch/blackfin/mach-common/pm.c b/arch/blackfin/mach-common/pm.c
index 09c1fb410748..80884b136a0c 100644
--- a/arch/blackfin/mach-common/pm.c
+++ b/arch/blackfin/mach-common/pm.c
@@ -25,7 +25,7 @@ void bfin_pm_suspend_standby_enter(void)
{
unsigned long flags;
- local_irq_save_hw(flags);
+ flags = hard_local_irq_save();
bfin_pm_standby_setup();
#ifdef CONFIG_PM_BFIN_SLEEP_DEEPER
@@ -56,7 +56,7 @@ void bfin_pm_suspend_standby_enter(void)
bfin_write_SIC_IWR(IWR_DISABLE_ALL);
#endif
- local_irq_restore_hw(flags);
+ hard_local_irq_restore(flags);
}
int bf53x_suspend_l1_mem(unsigned char *memptr)
@@ -149,12 +149,12 @@ int bfin_pm_suspend_mem_enter(void)
wakeup |= GPWE;
#endif
- local_irq_save_hw(flags);
+ flags = hard_local_irq_save();
ret = blackfin_dma_suspend();
if (ret) {
- local_irq_restore_hw(flags);
+ hard_local_irq_restore(flags);
kfree(memptr);
return ret;
}
@@ -178,7 +178,7 @@ int bfin_pm_suspend_mem_enter(void)
bfin_gpio_pm_hibernate_restore();
blackfin_dma_resume();
- local_irq_restore_hw(flags);
+ hard_local_irq_restore(flags);
kfree(memptr);
return 0;
diff --git a/arch/blackfin/mm/init.c b/arch/blackfin/mm/init.c
index bb4e8fff4b55..f8435cd36c7c 100644
--- a/arch/blackfin/mm/init.c
+++ b/arch/blackfin/mm/init.c
@@ -158,5 +158,8 @@ void __init_refok free_initmem(void)
free_init_pages("unused kernel memory",
(unsigned long)(&__init_begin),
(unsigned long)(&__init_end));
+
+ if (memory_start == (unsigned long)(&__init_end))
+ memory_start = (unsigned long)(&__init_begin);
#endif
}
diff --git a/arch/cris/arch-v10/drivers/ds1302.c b/arch/cris/arch-v10/drivers/ds1302.c
index 884275629ef7..3d655dcc65da 100644
--- a/arch/cris/arch-v10/drivers/ds1302.c
+++ b/arch/cris/arch-v10/drivers/ds1302.c
@@ -19,7 +19,7 @@
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/delay.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/bcd.h>
#include <linux/capability.h>
@@ -34,6 +34,7 @@
#define RTC_MAJOR_NR 121 /* local major, change later */
+static DEFINE_MUTEX(ds1302_mutex);
static const char ds1302_name[] = "ds1302";
/* The DS1302 might be connected to different bits on different products.
@@ -357,9 +358,9 @@ static long rtc_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned lon
{
int ret;
- lock_kernel();
+ mutex_lock(&ds1302_mutex);
ret = rtc_ioctl(file, cmd, arg);
- unlock_kernel();
+ mutex_unlock(&ds1302_mutex);
return ret;
}
@@ -387,6 +388,7 @@ print_rtc_status(void)
static const struct file_operations rtc_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = rtc_unlocked_ioctl,
+ .llseek = noop_llseek,
};
/* Probe for the chip by writing something to its RAM and try reading it back. */
diff --git a/arch/cris/arch-v10/drivers/gpio.c b/arch/cris/arch-v10/drivers/gpio.c
index a07b6d25b0c7..a276f0811731 100644
--- a/arch/cris/arch-v10/drivers/gpio.c
+++ b/arch/cris/arch-v10/drivers/gpio.c
@@ -745,6 +745,7 @@ static const struct file_operations gpio_fops = {
.write = gpio_write,
.open = gpio_open,
.release = gpio_release,
+ .llseek = noop_llseek,
};
static void ioif_watcher(const unsigned int gpio_in_available,
diff --git a/arch/cris/arch-v10/drivers/i2c.c b/arch/cris/arch-v10/drivers/i2c.c
index 77a941813819..c413539d4205 100644
--- a/arch/cris/arch-v10/drivers/i2c.c
+++ b/arch/cris/arch-v10/drivers/i2c.c
@@ -617,6 +617,7 @@ static const struct file_operations i2c_fops = {
.unlocked_ioctl = i2c_ioctl,
.open = i2c_open,
.release = i2c_release,
+ .llseek = noop_llseek,
};
int __init
diff --git a/arch/cris/arch-v10/drivers/pcf8563.c b/arch/cris/arch-v10/drivers/pcf8563.c
index 7dcb1f85f42b..ea69faba9b62 100644
--- a/arch/cris/arch-v10/drivers/pcf8563.c
+++ b/arch/cris/arch-v10/drivers/pcf8563.c
@@ -27,7 +27,6 @@
#include <linux/delay.h>
#include <linux/bcd.h>
#include <linux/mutex.h>
-#include <linux/smp_lock.h>
#include <asm/uaccess.h>
#include <asm/system.h>
@@ -49,6 +48,7 @@
#define rtc_read(x) i2c_readreg(RTC_I2C_READ, x)
#define rtc_write(x,y) i2c_writereg(RTC_I2C_WRITE, x, y)
+static DEFINE_MUTEX(pcf8563_mutex);
static DEFINE_MUTEX(rtc_lock); /* Protect state etc */
static const unsigned char days_in_month[] =
@@ -64,6 +64,7 @@ static int voltage_low;
static const struct file_operations pcf8563_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = pcf8563_unlocked_ioctl,
+ .llseek = noop_llseek,
};
unsigned char
@@ -343,9 +344,9 @@ static long pcf8563_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned
{
int ret;
- lock_kernel();
+ mutex_lock(&pcf8563_mutex);
return pcf8563_ioctl(filp, cmd, arg);
- unlock_kernel();
+ mutex_unlock(&pcf8563_mutex);
return ret;
}
diff --git a/arch/cris/arch-v10/drivers/sync_serial.c b/arch/cris/arch-v10/drivers/sync_serial.c
index ee2dd4323daf..399dc1ec8e6f 100644
--- a/arch/cris/arch-v10/drivers/sync_serial.c
+++ b/arch/cris/arch-v10/drivers/sync_serial.c
@@ -20,7 +20,7 @@
#include <linux/interrupt.h>
#include <linux/poll.h>
#include <linux/init.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/timer.h>
#include <asm/irq.h>
#include <asm/dma.h>
@@ -149,6 +149,7 @@ struct sync_port {
};
+static DEFINE_MUTEX(sync_serial_mutex);
static int etrax_sync_serial_init(void);
static void initialize_port(int portnbr);
static inline int sync_data_avail(struct sync_port *port);
@@ -250,7 +251,8 @@ static const struct file_operations sync_serial_fops = {
.poll = sync_serial_poll,
.unlocked_ioctl = sync_serial_ioctl,
.open = sync_serial_open,
- .release = sync_serial_release
+ .release = sync_serial_release,
+ .llseek = noop_llseek,
};
static int __init etrax_sync_serial_init(void)
@@ -445,7 +447,7 @@ static int sync_serial_open(struct inode *inode, struct file *file)
int mode;
int err = -EBUSY;
- lock_kernel();
+ mutex_lock(&sync_serial_mutex);
DEBUG(printk(KERN_DEBUG "Open sync serial port %d\n", dev));
if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled) {
@@ -626,7 +628,7 @@ static int sync_serial_open(struct inode *inode, struct file *file)
ret = 0;
out:
- unlock_kernel();
+ mutex_unlock(&sync_serial_mutex);
return ret;
}
@@ -961,9 +963,9 @@ static long sync_serial_ioctl(struct file *file,
{
long ret;
- lock_kernel();
+ mutex_lock(&sync_serial_mutex);
ret = sync_serial_ioctl_unlocked(file, cmd, arg);
- unlock_kernel();
+ mutex_unlock(&sync_serial_mutex);
return ret;
}
diff --git a/arch/cris/arch-v32/drivers/cryptocop.c b/arch/cris/arch-v32/drivers/cryptocop.c
index b07646a30509..c03bc3bc30c2 100644
--- a/arch/cris/arch-v32/drivers/cryptocop.c
+++ b/arch/cris/arch-v32/drivers/cryptocop.c
@@ -281,7 +281,8 @@ const struct file_operations cryptocop_fops = {
.owner = THIS_MODULE,
.open = cryptocop_open,
.release = cryptocop_release,
- .unlocked_ioctl = cryptocop_ioctl
+ .unlocked_ioctl = cryptocop_ioctl,
+ .llseek = noop_llseek,
};
@@ -3139,9 +3140,9 @@ cryptocop_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
struct inode *inode = file->f_path.dentry->d_inode;
long ret;
- lock_kernel();
+ mutex_lock(&cryptocop_mutex);
ret = cryptocop_ioctl_unlocked(inode, filp, cmd, arg);
- unlock_kernel();
+ mutex_unlock(&cryptocop_mutex);
return ret;
}
diff --git a/arch/cris/arch-v32/drivers/i2c.c b/arch/cris/arch-v32/drivers/i2c.c
index 5a3e900c9a78..ddb23996f11a 100644
--- a/arch/cris/arch-v32/drivers/i2c.c
+++ b/arch/cris/arch-v32/drivers/i2c.c
@@ -698,6 +698,7 @@ static const struct file_operations i2c_fops = {
.unlocked_ioctl = i2c_ioctl,
.open = i2c_open,
.release = i2c_release,
+ .llseek = noop_llseek,
};
static int __init i2c_init(void)
diff --git a/arch/cris/arch-v32/drivers/mach-a3/gpio.c b/arch/cris/arch-v32/drivers/mach-a3/gpio.c
index 2dcd27adbad4..c845831e2225 100644
--- a/arch/cris/arch-v32/drivers/mach-a3/gpio.c
+++ b/arch/cris/arch-v32/drivers/mach-a3/gpio.c
@@ -23,7 +23,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <asm/etraxgpio.h>
#include <hwregs/reg_map.h>
@@ -66,6 +66,7 @@ static int dp_cnt;
#define DP(x)
#endif
+static DEFINE_MUTEX(gpio_mutex);
static char gpio_name[] = "etrax gpio";
#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
@@ -391,7 +392,7 @@ static int gpio_open(struct inode *inode, struct file *filp)
if (!priv)
return -ENOMEM;
- lock_kernel();
+ mutex_lock(&gpio_mutex);
memset(priv, 0, sizeof(*priv));
priv->minor = p;
@@ -414,7 +415,7 @@ static int gpio_open(struct inode *inode, struct file *filp)
spin_unlock_irq(&gpio_lock);
}
- unlock_kernel();
+ mutex_unlock(&gpio_mutex);
return 0;
}
@@ -667,9 +668,9 @@ static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
long ret;
- lock_kernel();
+ mutex_lock(&gpio_mutex);
ret = gpio_ioctl_unlocked(file, cmd, arg);
- unlock_kernel();
+ mutex_unlock(&gpio_mutex);
return ret;
}
@@ -893,6 +894,7 @@ static const struct file_operations gpio_fops = {
.write = gpio_write,
.open = gpio_open,
.release = gpio_release,
+ .llseek = noop_llseek,
};
#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
diff --git a/arch/cris/arch-v32/drivers/mach-fs/gpio.c b/arch/cris/arch-v32/drivers/mach-fs/gpio.c
index 5ec8a7d4e7d7..ee90d2659be7 100644
--- a/arch/cris/arch-v32/drivers/mach-fs/gpio.c
+++ b/arch/cris/arch-v32/drivers/mach-fs/gpio.c
@@ -22,7 +22,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <asm/etraxgpio.h>
#include <hwregs/reg_map.h>
@@ -64,6 +64,7 @@ static int dp_cnt;
#define DP(x)
#endif
+static DEFINE_MUTEX(gpio_mutex);
static char gpio_name[] = "etrax gpio";
#if 0
@@ -429,7 +430,7 @@ gpio_open(struct inode *inode, struct file *filp)
if (!priv)
return -ENOMEM;
- lock_kernel();
+ mutex_lock(&gpio_mutex);
memset(priv, 0, sizeof(*priv));
priv->minor = p;
@@ -450,7 +451,7 @@ gpio_open(struct inode *inode, struct file *filp)
alarmlist = priv;
spin_unlock_irq(&alarm_lock);
- unlock_kernel();
+ mutex_unlock(&gpio_mutex);
return 0;
}
@@ -708,9 +709,9 @@ static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
long ret;
- lock_kernel();
+ mutex_lock(&gpio_mutex);
ret = gpio_ioctl_unlocked(file, cmd, arg);
- unlock_kernel();
+ mutex_unlock(&gpio_mutex);
return ret;
}
@@ -870,6 +871,7 @@ static const struct file_operations gpio_fops = {
.write = gpio_write,
.open = gpio_open,
.release = gpio_release,
+ .llseek = noop_llseek,
};
#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
diff --git a/arch/cris/arch-v32/drivers/pcf8563.c b/arch/cris/arch-v32/drivers/pcf8563.c
index bef6eb53b153..b6e4fc0aad42 100644
--- a/arch/cris/arch-v32/drivers/pcf8563.c
+++ b/arch/cris/arch-v32/drivers/pcf8563.c
@@ -24,7 +24,6 @@
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/ioctl.h>
-#include <linux/smp_lock.h>
#include <linux/delay.h>
#include <linux/bcd.h>
#include <linux/mutex.h>
@@ -45,6 +44,7 @@
#define rtc_read(x) i2c_readreg(RTC_I2C_READ, x)
#define rtc_write(x,y) i2c_writereg(RTC_I2C_WRITE, x, y)
+static DEFINE_MUTEX(pcf8563_mutex);
static DEFINE_MUTEX(rtc_lock); /* Protect state etc */
static const unsigned char days_in_month[] =
@@ -60,6 +60,7 @@ static int voltage_low;
static const struct file_operations pcf8563_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = pcf8563_unlocked_ioctl,
+ .llseek = noop_llseek,
};
unsigned char
@@ -339,9 +340,9 @@ static long pcf8563_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned
{
int ret;
- lock_kernel();
+ mutex_lock(&pcf8563_mutex);
return pcf8563_ioctl(filp, cmd, arg);
- unlock_kernel();
+ mutex_unlock(&pcf8563_mutex);
return ret;
}
diff --git a/arch/cris/arch-v32/drivers/sync_serial.c b/arch/cris/arch-v32/drivers/sync_serial.c
index ca248f3adb80..c8637a9195ea 100644
--- a/arch/cris/arch-v32/drivers/sync_serial.c
+++ b/arch/cris/arch-v32/drivers/sync_serial.c
@@ -13,7 +13,7 @@
#include <linux/errno.h>
#include <linux/major.h>
#include <linux/sched.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/interrupt.h>
#include <linux/poll.h>
#include <linux/init.h>
@@ -145,6 +145,7 @@ typedef struct sync_port
spinlock_t lock;
} sync_port;
+static DEFINE_MUTEX(sync_serial_mutex);
static int etrax_sync_serial_init(void);
static void initialize_port(int portnbr);
static inline int sync_data_avail(struct sync_port *port);
@@ -247,7 +248,8 @@ static const struct file_operations sync_serial_fops = {
.poll = sync_serial_poll,
.unlocked_ioctl = sync_serial_ioctl,
.open = sync_serial_open,
- .release = sync_serial_release
+ .release = sync_serial_release,
+ .llseek = noop_llseek,
};
static int __init etrax_sync_serial_init(void)
@@ -434,7 +436,7 @@ static int sync_serial_open(struct inode *inode, struct file *file)
reg_dma_rw_cfg cfg = {.en = regk_dma_yes};
reg_dma_rw_intr_mask intr_mask = {.data = regk_dma_yes};
- lock_kernel();
+ mutex_lock(&sync_serial_mutex);
DEBUG(printk(KERN_DEBUG "Open sync serial port %d\n", dev));
if (dev < 0 || dev >= NBR_PORTS || !ports[dev].enabled)
@@ -583,7 +585,7 @@ static int sync_serial_open(struct inode *inode, struct file *file)
port->busy++;
ret = 0;
out:
- unlock_kernel();
+ mutex_unlock(&sync_serial_mutex);
return ret;
}
@@ -966,9 +968,9 @@ static long sync_serial_ioctl(struct file *file,
{
long ret;
- lock_kernel();
+ mutex_lock(&sync_serial_mutex);
ret = sync_serial_ioctl_unlocked(file, cmd, arg);
- unlock_kernel();
+ mutex_unlock(&sync_serial_mutex);
return ret;
}
diff --git a/arch/cris/include/arch-v10/arch/irqflags.h b/arch/cris/include/arch-v10/arch/irqflags.h
new file mode 100644
index 000000000000..75ef18991240
--- /dev/null
+++ b/arch/cris/include/arch-v10/arch/irqflags.h
@@ -0,0 +1,45 @@
+#ifndef __ASM_CRIS_ARCH_IRQFLAGS_H
+#define __ASM_CRIS_ARCH_IRQFLAGS_H
+
+#include <linux/types.h>
+
+static inline unsigned long arch_local_save_flags(void)
+{
+ unsigned long flags;
+ asm volatile("move $ccr,%0" : "=rm" (flags) : : "memory");
+ return flags;
+}
+
+static inline void arch_local_irq_disable(void)
+{
+ asm volatile("di" : : : "memory");
+}
+
+static inline void arch_local_irq_enable(void)
+{
+ asm volatile("ei" : : : "memory");
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+ unsigned long flags = arch_local_save_flags();
+ arch_local_irq_disable();
+ return flags;
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+ asm volatile("move %0,$ccr" : : "rm" (flags) : "memory");
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+ return !(flags & (1 << 5));
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+ return arch_irqs_disabled_flags(arch_local_save_flags());
+}
+
+#endif /* __ASM_CRIS_ARCH_IRQFLAGS_H */
diff --git a/arch/cris/include/arch-v10/arch/system.h b/arch/cris/include/arch-v10/arch/system.h
index 4a9cd36c9e16..935fde34aa15 100644
--- a/arch/cris/include/arch-v10/arch/system.h
+++ b/arch/cris/include/arch-v10/arch/system.h
@@ -44,20 +44,4 @@ static inline unsigned long _get_base(char * addr)
struct __xchg_dummy { unsigned long a[100]; };
#define __xg(x) ((struct __xchg_dummy *)(x))
-/* interrupt control.. */
-#define local_save_flags(x) __asm__ __volatile__ ("move $ccr,%0" : "=rm" (x) : : "memory");
-#define local_irq_restore(x) __asm__ __volatile__ ("move %0,$ccr" : : "rm" (x) : "memory");
-#define local_irq_disable() __asm__ __volatile__ ( "di" : : :"memory");
-#define local_irq_enable() __asm__ __volatile__ ( "ei" : : :"memory");
-
-#define irqs_disabled() \
-({ \
- unsigned long flags; \
- local_save_flags(flags); \
- !(flags & (1<<5)); \
-})
-
-/* For spinlocks etc */
-#define local_irq_save(x) __asm__ __volatile__ ("move $ccr,%0\n\tdi" : "=rm" (x) : : "memory");
-
#endif
diff --git a/arch/cris/include/arch-v32/arch/irqflags.h b/arch/cris/include/arch-v32/arch/irqflags.h
new file mode 100644
index 000000000000..041851f8ec6f
--- /dev/null
+++ b/arch/cris/include/arch-v32/arch/irqflags.h
@@ -0,0 +1,46 @@
+#ifndef __ASM_CRIS_ARCH_IRQFLAGS_H
+#define __ASM_CRIS_ARCH_IRQFLAGS_H
+
+#include <linux/types.h>
+#include <arch/ptrace.h>
+
+static inline unsigned long arch_local_save_flags(void)
+{
+ unsigned long flags;
+ asm volatile("move $ccs,%0" : "=rm" (flags) : : "memory");
+ return flags;
+}
+
+static inline void arch_local_irq_disable(void)
+{
+ asm volatile("di" : : : "memory");
+}
+
+static inline void arch_local_irq_enable(void)
+{
+ asm volatile("ei" : : : "memory");
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+ unsigned long flags = arch_local_save_flags();
+ arch_local_irq_disable();
+ return flags;
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+ asm volatile("move %0,$ccs" : : "rm" (flags) : "memory");
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+ return !(flags & (1 << I_CCS_BITNR));
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+ return arch_irqs_disabled_flags(arch_local_save_flags());
+}
+
+#endif /* __ASM_CRIS_ARCH_IRQFLAGS_H */
diff --git a/arch/cris/include/arch-v32/arch/system.h b/arch/cris/include/arch-v32/arch/system.h
index 6ca90f1f110a..76cea99eaa60 100644
--- a/arch/cris/include/arch-v32/arch/system.h
+++ b/arch/cris/include/arch-v32/arch/system.h
@@ -44,26 +44,4 @@ static inline unsigned long rdsp(void)
struct __xchg_dummy { unsigned long a[100]; };
#define __xg(x) ((struct __xchg_dummy *)(x))
-/* Used for interrupt control. */
-#define local_save_flags(x) \
- __asm__ __volatile__ ("move $ccs, %0" : "=rm" (x) : : "memory");
-
-#define local_irq_restore(x) \
- __asm__ __volatile__ ("move %0, $ccs" : : "rm" (x) : "memory");
-
-#define local_irq_disable() __asm__ __volatile__ ("di" : : : "memory");
-#define local_irq_enable() __asm__ __volatile__ ("ei" : : : "memory");
-
-#define irqs_disabled() \
-({ \
- unsigned long flags; \
- \
- local_save_flags(flags);\
- !(flags & (1 << I_CCS_BITNR)); \
-})
-
-/* Used for spinlocks, etc. */
-#define local_irq_save(x) \
- __asm__ __volatile__ ("move $ccs, %0\n\tdi" : "=rm" (x) : : "memory");
-
#endif /* _ASM_CRIS_ARCH_SYSTEM_H */
diff --git a/arch/cris/include/asm/ioctls.h b/arch/cris/include/asm/ioctls.h
index c9129ed37443..488fbb3f5e84 100644
--- a/arch/cris/include/asm/ioctls.h
+++ b/arch/cris/include/asm/ioctls.h
@@ -1,93 +1,11 @@
#ifndef __ARCH_CRIS_IOCTLS_H__
#define __ARCH_CRIS_IOCTLS_H__
-/* verbatim copy of asm-i386/ioctls.h */
-
-#include <asm/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS 0x5401
-#define TCSETS 0x5402
-#define TCSETSW 0x5403
-#define TCSETSF 0x5404
-#define TCGETA 0x5405
-#define TCSETA 0x5406
-#define TCSETAW 0x5407
-#define TCSETAF 0x5408
-#define TCSBRK 0x5409
-#define TCXONC 0x540A
-#define TCFLSH 0x540B
-#define TIOCEXCL 0x540C
-#define TIOCNXCL 0x540D
-#define TIOCSCTTY 0x540E
-#define TIOCGPGRP 0x540F
-#define TIOCSPGRP 0x5410
-#define TIOCOUTQ 0x5411
-#define TIOCSTI 0x5412
-#define TIOCGWINSZ 0x5413
-#define TIOCSWINSZ 0x5414
-#define TIOCMGET 0x5415
-#define TIOCMBIS 0x5416
-#define TIOCMBIC 0x5417
-#define TIOCMSET 0x5418
-#define TIOCGSOFTCAR 0x5419
-#define TIOCSSOFTCAR 0x541A
-#define FIONREAD 0x541B
-#define TIOCINQ FIONREAD
-#define TIOCLINUX 0x541C
-#define TIOCCONS 0x541D
-#define TIOCGSERIAL 0x541E
-#define TIOCSSERIAL 0x541F
-#define TIOCPKT 0x5420
-#define FIONBIO 0x5421
-#define TIOCNOTTY 0x5422
-#define TIOCSETD 0x5423
-#define TIOCGETD 0x5424
-#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
-#define TIOCSBRK 0x5427 /* BSD compatibility */
-#define TIOCCBRK 0x5428 /* BSD compatibility */
-#define TIOCGSID 0x5429 /* Return the session ID of FD */
-#define TCGETS2 _IOR('T',0x2A, struct termios2)
-#define TCSETS2 _IOW('T',0x2B, struct termios2)
-#define TCSETSW2 _IOW('T',0x2C, struct termios2)
-#define TCSETSF2 _IOW('T',0x2D, struct termios2)
-#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
-#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
-#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */
-
-#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */
-#define FIOCLEX 0x5451
-#define FIOASYNC 0x5452
-#define TIOCSERCONFIG 0x5453
-#define TIOCSERGWILD 0x5454
-#define TIOCSERSWILD 0x5455
-#define TIOCGLCKTRMIOS 0x5456
-#define TIOCSLCKTRMIOS 0x5457
#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
-#define TIOCSERGETLSR 0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
-#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
-#define FIOQSIZE 0x5460
-
#define TIOCSERSETRS485 0x5461 /* enable rs-485 (deprecated) */
#define TIOCSERWRRS485 0x5462 /* write rs-485 */
#define TIOCSRS485 0x5463 /* enable rs-485 */
-#define TIOCGRS485 0x542E /* get rs-485 */
-
-/* Used for packet mode */
-#define TIOCPKT_DATA 0
-#define TIOCPKT_FLUSHREAD 1
-#define TIOCPKT_FLUSHWRITE 2
-#define TIOCPKT_STOP 4
-#define TIOCPKT_START 8
-#define TIOCPKT_NOSTOP 16
-#define TIOCPKT_DOSTOP 32
-#define TIOCPKT_IOCTL 64
-#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
+#include <asm-generic/ioctls.h>
#endif
diff --git a/arch/cris/include/asm/irqflags.h b/arch/cris/include/asm/irqflags.h
new file mode 100644
index 000000000000..943ba5ca6d2c
--- /dev/null
+++ b/arch/cris/include/asm/irqflags.h
@@ -0,0 +1 @@
+#include <arch/irqflags.h>
diff --git a/arch/cris/include/asm/system.h b/arch/cris/include/asm/system.h
index 8657b084a922..ea10592f7d75 100644
--- a/arch/cris/include/asm/system.h
+++ b/arch/cris/include/asm/system.h
@@ -1,6 +1,7 @@
#ifndef __ASM_CRIS_SYSTEM_H
#define __ASM_CRIS_SYSTEM_H
+#include <linux/irqflags.h>
#include <arch/system.h>
/* the switch_to macro calls resume, an asm function in entry.S which does the actual
diff --git a/arch/cris/kernel/profile.c b/arch/cris/kernel/profile.c
index 195ec5fa0dd2..b82e08615d1b 100644
--- a/arch/cris/kernel/profile.c
+++ b/arch/cris/kernel/profile.c
@@ -59,6 +59,7 @@ write_cris_profile(struct file *file, const char __user *buf,
static const struct file_operations cris_proc_profile_operations = {
.read = read_cris_profile,
.write = write_cris_profile,
+ .llseek = default_llseek,
};
static int __init init_cris_profile(void)
diff --git a/arch/frv/Kconfig b/arch/frv/Kconfig
index 16399bd24993..0f2417df6323 100644
--- a/arch/frv/Kconfig
+++ b/arch/frv/Kconfig
@@ -7,6 +7,7 @@ config FRV
default y
select HAVE_IDE
select HAVE_ARCH_TRACEHOOK
+ select HAVE_IRQ_WORK
select HAVE_PERF_EVENTS
config ZONE_DMA
diff --git a/arch/frv/include/asm/ioctls.h b/arch/frv/include/asm/ioctls.h
index a993e3759ccf..2f9fb436ec3c 100644
--- a/arch/frv/include/asm/ioctls.h
+++ b/arch/frv/include/asm/ioctls.h
@@ -1,88 +1,10 @@
#ifndef __ASM_IOCTLS_H__
#define __ASM_IOCTLS_H__
-#include <asm/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS 0x5401
-#define TCSETS 0x5402
-#define TCSETSW 0x5403
-#define TCSETSF 0x5404
-#define TCGETA 0x5405
-#define TCSETA 0x5406
-#define TCSETAW 0x5407
-#define TCSETAF 0x5408
-#define TCSBRK 0x5409
-#define TCXONC 0x540A
-#define TCFLSH 0x540B
-#define TIOCEXCL 0x540C
-#define TIOCNXCL 0x540D
-#define TIOCSCTTY 0x540E
-#define TIOCGPGRP 0x540F
-#define TIOCSPGRP 0x5410
-#define TIOCOUTQ 0x5411
-#define TIOCSTI 0x5412
-#define TIOCGWINSZ 0x5413
-#define TIOCSWINSZ 0x5414
-#define TIOCMGET 0x5415
-#define TIOCMBIS 0x5416
-#define TIOCMBIC 0x5417
-#define TIOCMSET 0x5418
-#define TIOCGSOFTCAR 0x5419
-#define TIOCSSOFTCAR 0x541A
-#define FIONREAD 0x541B
-#define TIOCINQ FIONREAD
-#define TIOCLINUX 0x541C
-#define TIOCCONS 0x541D
-#define TIOCGSERIAL 0x541E
-#define TIOCSSERIAL 0x541F
-#define TIOCPKT 0x5420
-#define FIONBIO 0x5421
-#define TIOCNOTTY 0x5422
-#define TIOCSETD 0x5423
-#define TIOCGETD 0x5424
-#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
#define TIOCTTYGSTRUCT 0x5426 /* For debugging only */
-#define TIOCSBRK 0x5427 /* BSD compatibility */
-#define TIOCCBRK 0x5428 /* BSD compatibility */
-#define TIOCGSID 0x5429 /* Return the session ID of FD */
-#define TCGETS2 _IOR('T',0x2A, struct termios2)
-#define TCSETS2 _IOW('T',0x2B, struct termios2)
-#define TCSETSW2 _IOW('T',0x2C, struct termios2)
-#define TCSETSF2 _IOW('T',0x2D, struct termios2)
-#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
-#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
-#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */
-
-#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */
-#define FIOCLEX 0x5451
-#define FIOASYNC 0x5452
-#define TIOCSERCONFIG 0x5453
-#define TIOCSERGWILD 0x5454
-#define TIOCSERSWILD 0x5455
-#define TIOCGLCKTRMIOS 0x5456
-#define TIOCSLCKTRMIOS 0x5457
-#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
-#define TIOCSERGETLSR 0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
-#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
#define FIOQSIZE 0x545E
-/* Used for packet mode */
-#define TIOCPKT_DATA 0
-#define TIOCPKT_FLUSHREAD 1
-#define TIOCPKT_FLUSHWRITE 2
-#define TIOCPKT_STOP 4
-#define TIOCPKT_START 8
-#define TIOCPKT_NOSTOP 16
-#define TIOCPKT_DOSTOP 32
-#define TIOCPKT_IOCTL 64
-
-#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
+#include <asm-generic/ioctls.h>
#endif /* __ASM_IOCTLS_H__ */
diff --git a/arch/frv/include/asm/irqflags.h b/arch/frv/include/asm/irqflags.h
new file mode 100644
index 000000000000..82f0b5363f42
--- /dev/null
+++ b/arch/frv/include/asm/irqflags.h
@@ -0,0 +1,158 @@
+/* FR-V interrupt handling
+ *
+ * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#ifndef _ASM_IRQFLAGS_H
+#define _ASM_IRQFLAGS_H
+
+/*
+ * interrupt flag manipulation
+ * - use virtual interrupt management since touching the PSR is slow
+ * - ICC2.Z: T if interrupts virtually disabled
+ * - ICC2.C: F if interrupts really disabled
+ * - if Z==1 upon interrupt:
+ * - C is set to 0
+ * - interrupts are really disabled
+ * - entry.S returns immediately
+ * - uses TIHI (TRAP if Z==0 && C==0) #2 to really reenable interrupts
+ * - if taken, the trap:
+ * - sets ICC2.C
+ * - enables interrupts
+ */
+static inline void arch_local_irq_disable(void)
+{
+ /* set Z flag, but don't change the C flag */
+ asm volatile(" andcc gr0,gr0,gr0,icc2 \n"
+ :
+ :
+ : "memory", "icc2"
+ );
+}
+
+static inline void arch_local_irq_enable(void)
+{
+ /* clear Z flag and then test the C flag */
+ asm volatile(" oricc gr0,#1,gr0,icc2 \n"
+ " tihi icc2,gr0,#2 \n"
+ :
+ :
+ : "memory", "icc2"
+ );
+}
+
+static inline unsigned long arch_local_save_flags(void)
+{
+ unsigned long flags;
+
+ asm volatile("movsg ccr,%0"
+ : "=r"(flags)
+ :
+ : "memory");
+
+ /* shift ICC2.Z to bit 0 */
+ flags >>= 26;
+
+ /* make flags 1 if interrupts disabled, 0 otherwise */
+ return flags & 1UL;
+
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+ unsigned long flags = arch_local_save_flags();
+ arch_local_irq_disable();
+ return flags;
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+ /* load the Z flag by turning 1 if disabled into 0 if disabled
+ * and thus setting the Z flag but not the C flag */
+ asm volatile(" xoricc %0,#1,gr0,icc2 \n"
+ /* then trap if Z=0 and C=0 */
+ " tihi icc2,gr0,#2 \n"
+ :
+ : "r"(flags)
+ : "memory", "icc2"
+ );
+
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+ return flags;
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+ return arch_irqs_disabled_flags(arch_local_save_flags());
+}
+
+/*
+ * real interrupt flag manipulation
+ */
+#define __arch_local_irq_disable() \
+do { \
+ unsigned long psr; \
+ asm volatile(" movsg psr,%0 \n" \
+ " andi %0,%2,%0 \n" \
+ " ori %0,%1,%0 \n" \
+ " movgs %0,psr \n" \
+ : "=r"(psr) \
+ : "i" (PSR_PIL_14), "i" (~PSR_PIL) \
+ : "memory"); \
+} while (0)
+
+#define __arch_local_irq_enable() \
+do { \
+ unsigned long psr; \
+ asm volatile(" movsg psr,%0 \n" \
+ " andi %0,%1,%0 \n" \
+ " movgs %0,psr \n" \
+ : "=r"(psr) \
+ : "i" (~PSR_PIL) \
+ : "memory"); \
+} while (0)
+
+#define __arch_local_save_flags(flags) \
+do { \
+ typecheck(unsigned long, flags); \
+ asm("movsg psr,%0" \
+ : "=r"(flags) \
+ : \
+ : "memory"); \
+} while (0)
+
+#define __arch_local_irq_save(flags) \
+do { \
+ unsigned long npsr; \
+ typecheck(unsigned long, flags); \
+ asm volatile(" movsg psr,%0 \n" \
+ " andi %0,%3,%1 \n" \
+ " ori %1,%2,%1 \n" \
+ " movgs %1,psr \n" \
+ : "=r"(flags), "=r"(npsr) \
+ : "i" (PSR_PIL_14), "i" (~PSR_PIL) \
+ : "memory"); \
+} while (0)
+
+#define __arch_local_irq_restore(flags) \
+do { \
+ typecheck(unsigned long, flags); \
+ asm volatile(" movgs %0,psr \n" \
+ : \
+ : "r" (flags) \
+ : "memory"); \
+} while (0)
+
+#define __arch_irqs_disabled() \
+ ((__get_PSR() & PSR_PIL) >= PSR_PIL_14)
+
+#endif /* _ASM_IRQFLAGS_H */
diff --git a/arch/frv/include/asm/system.h b/arch/frv/include/asm/system.h
index efd22d9077ac..0a6d8d9ca45b 100644
--- a/arch/frv/include/asm/system.h
+++ b/arch/frv/include/asm/system.h
@@ -37,142 +37,6 @@ do { \
} while(0)
/*
- * interrupt flag manipulation
- * - use virtual interrupt management since touching the PSR is slow
- * - ICC2.Z: T if interrupts virtually disabled
- * - ICC2.C: F if interrupts really disabled
- * - if Z==1 upon interrupt:
- * - C is set to 0
- * - interrupts are really disabled
- * - entry.S returns immediately
- * - uses TIHI (TRAP if Z==0 && C==0) #2 to really reenable interrupts
- * - if taken, the trap:
- * - sets ICC2.C
- * - enables interrupts
- */
-#define local_irq_disable() \
-do { \
- /* set Z flag, but don't change the C flag */ \
- asm volatile(" andcc gr0,gr0,gr0,icc2 \n" \
- : \
- : \
- : "memory", "icc2" \
- ); \
-} while(0)
-
-#define local_irq_enable() \
-do { \
- /* clear Z flag and then test the C flag */ \
- asm volatile(" oricc gr0,#1,gr0,icc2 \n" \
- " tihi icc2,gr0,#2 \n" \
- : \
- : \
- : "memory", "icc2" \
- ); \
-} while(0)
-
-#define local_save_flags(flags) \
-do { \
- typecheck(unsigned long, flags); \
- asm volatile("movsg ccr,%0" \
- : "=r"(flags) \
- : \
- : "memory"); \
- \
- /* shift ICC2.Z to bit 0 */ \
- flags >>= 26; \
- \
- /* make flags 1 if interrupts disabled, 0 otherwise */ \
- flags &= 1UL; \
-} while(0)
-
-#define irqs_disabled() \
- ({unsigned long flags; local_save_flags(flags); !!flags; })
-
-#define local_irq_save(flags) \
-do { \
- typecheck(unsigned long, flags); \
- local_save_flags(flags); \
- local_irq_disable(); \
-} while(0)
-
-#define local_irq_restore(flags) \
-do { \
- typecheck(unsigned long, flags); \
- \
- /* load the Z flag by turning 1 if disabled into 0 if disabled \
- * and thus setting the Z flag but not the C flag */ \
- asm volatile(" xoricc %0,#1,gr0,icc2 \n" \
- /* then test Z=0 and C=0 */ \
- " tihi icc2,gr0,#2 \n" \
- : \
- : "r"(flags) \
- : "memory", "icc2" \
- ); \
- \
-} while(0)
-
-/*
- * real interrupt flag manipulation
- */
-#define __local_irq_disable() \
-do { \
- unsigned long psr; \
- asm volatile(" movsg psr,%0 \n" \
- " andi %0,%2,%0 \n" \
- " ori %0,%1,%0 \n" \
- " movgs %0,psr \n" \
- : "=r"(psr) \
- : "i" (PSR_PIL_14), "i" (~PSR_PIL) \
- : "memory"); \
-} while(0)
-
-#define __local_irq_enable() \
-do { \
- unsigned long psr; \
- asm volatile(" movsg psr,%0 \n" \
- " andi %0,%1,%0 \n" \
- " movgs %0,psr \n" \
- : "=r"(psr) \
- : "i" (~PSR_PIL) \
- : "memory"); \
-} while(0)
-
-#define __local_save_flags(flags) \
-do { \
- typecheck(unsigned long, flags); \
- asm("movsg psr,%0" \
- : "=r"(flags) \
- : \
- : "memory"); \
-} while(0)
-
-#define __local_irq_save(flags) \
-do { \
- unsigned long npsr; \
- typecheck(unsigned long, flags); \
- asm volatile(" movsg psr,%0 \n" \
- " andi %0,%3,%1 \n" \
- " ori %1,%2,%1 \n" \
- " movgs %1,psr \n" \
- : "=r"(flags), "=r"(npsr) \
- : "i" (PSR_PIL_14), "i" (~PSR_PIL) \
- : "memory"); \
-} while(0)
-
-#define __local_irq_restore(flags) \
-do { \
- typecheck(unsigned long, flags); \
- asm volatile(" movgs %0,psr \n" \
- : \
- : "r" (flags) \
- : "memory"); \
-} while(0)
-
-#define __irqs_disabled() \
- ((__get_PSR() & PSR_PIL) >= PSR_PIL_14)
-
-/*
* Force strict CPU ordering.
*/
#define nop() asm volatile ("nop"::)
diff --git a/arch/frv/lib/Makefile b/arch/frv/lib/Makefile
index f4709756d0d9..4ff2fb1e6b16 100644
--- a/arch/frv/lib/Makefile
+++ b/arch/frv/lib/Makefile
@@ -5,4 +5,4 @@
lib-y := \
__ashldi3.o __lshrdi3.o __muldi3.o __ashrdi3.o __negdi2.o __ucmpdi2.o \
checksum.o memcpy.o memset.o atomic-ops.o atomic64-ops.o \
- outsl_ns.o outsl_sw.o insl_ns.o insl_sw.o cache.o perf_event.o
+ outsl_ns.o outsl_sw.o insl_ns.o insl_sw.o cache.o
diff --git a/arch/frv/lib/perf_event.c b/arch/frv/lib/perf_event.c
deleted file mode 100644
index 9ac5acfd2e91..000000000000
--- a/arch/frv/lib/perf_event.c
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Performance event handling
- *
- * Copyright (C) 2009 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public Licence
- * as published by the Free Software Foundation; either version
- * 2 of the Licence, or (at your option) any later version.
- */
-
-#include <linux/perf_event.h>
-
-/*
- * mark the performance event as pending
- */
-void set_perf_event_pending(void)
-{
-}
diff --git a/arch/h8300/include/asm/ioctls.h b/arch/h8300/include/asm/ioctls.h
index b6b249f9f308..30eaed2facdb 100644
--- a/arch/h8300/include/asm/ioctls.h
+++ b/arch/h8300/include/asm/ioctls.h
@@ -1,87 +1,8 @@
#ifndef __ARCH_H8300_IOCTLS_H__
#define __ARCH_H8300_IOCTLS_H__
-#include <asm/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS 0x5401
-#define TCSETS 0x5402
-#define TCSETSW 0x5403
-#define TCSETSF 0x5404
-#define TCGETA 0x5405
-#define TCSETA 0x5406
-#define TCSETAW 0x5407
-#define TCSETAF 0x5408
-#define TCSBRK 0x5409
-#define TCXONC 0x540A
-#define TCFLSH 0x540B
-#define TIOCEXCL 0x540C
-#define TIOCNXCL 0x540D
-#define TIOCSCTTY 0x540E
-#define TIOCGPGRP 0x540F
-#define TIOCSPGRP 0x5410
-#define TIOCOUTQ 0x5411
-#define TIOCSTI 0x5412
-#define TIOCGWINSZ 0x5413
-#define TIOCSWINSZ 0x5414
-#define TIOCMGET 0x5415
-#define TIOCMBIS 0x5416
-#define TIOCMBIC 0x5417
-#define TIOCMSET 0x5418
-#define TIOCGSOFTCAR 0x5419
-#define TIOCSSOFTCAR 0x541A
-#define FIONREAD 0x541B
-#define TIOCINQ FIONREAD
-#define TIOCLINUX 0x541C
-#define TIOCCONS 0x541D
-#define TIOCGSERIAL 0x541E
-#define TIOCSSERIAL 0x541F
-#define TIOCPKT 0x5420
-#define FIONBIO 0x5421
-#define TIOCNOTTY 0x5422
-#define TIOCSETD 0x5423
-#define TIOCGETD 0x5424
-#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
-#define TIOCTTYGSTRUCT 0x5426 /* For debugging only */
-#define TIOCSBRK 0x5427 /* BSD compatibility */
-#define TIOCCBRK 0x5428 /* BSD compatibility */
-#define TIOCGSID 0x5429 /* Return the session ID of FD */
-#define TCGETS2 _IOR('T',0x2A, struct termios2)
-#define TCSETS2 _IOW('T',0x2B, struct termios2)
-#define TCSETSW2 _IOW('T',0x2C, struct termios2)
-#define TCSETSF2 _IOW('T',0x2D, struct termios2)
-#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
-#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
-#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */
-
-#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */
-#define FIOCLEX 0x5451
-#define FIOASYNC 0x5452
-#define TIOCSERCONFIG 0x5453
-#define TIOCSERGWILD 0x5454
-#define TIOCSERSWILD 0x5455
-#define TIOCGLCKTRMIOS 0x5456
-#define TIOCSLCKTRMIOS 0x5457
-#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
-#define TIOCSERGETLSR 0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
-#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
#define FIOQSIZE 0x545E
-/* Used for packet mode */
-#define TIOCPKT_DATA 0
-#define TIOCPKT_FLUSHREAD 1
-#define TIOCPKT_FLUSHWRITE 2
-#define TIOCPKT_STOP 4
-#define TIOCPKT_START 8
-#define TIOCPKT_NOSTOP 16
-#define TIOCPKT_DOSTOP 32
-#define TIOCPKT_IOCTL 64
-
-#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
+#include <asm-generic/ioctls.h>
#endif /* __ARCH_H8300_IOCTLS_H__ */
diff --git a/arch/h8300/include/asm/irqflags.h b/arch/h8300/include/asm/irqflags.h
new file mode 100644
index 000000000000..9617cd57aebd
--- /dev/null
+++ b/arch/h8300/include/asm/irqflags.h
@@ -0,0 +1,43 @@
+#ifndef _H8300_IRQFLAGS_H
+#define _H8300_IRQFLAGS_H
+
+static inline unsigned long arch_local_save_flags(void)
+{
+ unsigned long flags;
+ asm volatile ("stc ccr,%w0" : "=r" (flags));
+ return flags;
+}
+
+static inline void arch_local_irq_disable(void)
+{
+ asm volatile ("orc #0x80,ccr" : : : "memory");
+}
+
+static inline void arch_local_irq_enable(void)
+{
+ asm volatile ("andc #0x7f,ccr" : : : "memory");
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+ unsigned long flags = arch_local_save_flags();
+ arch_local_irq_disable();
+ return flags;
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+ asm volatile ("ldc %w0,ccr" : : "r" (flags) : "memory");
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+ return (flags & 0x80) == 0x80;
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+ return arch_irqs_disabled_flags(arch_local_save_flags());
+}
+
+#endif /* _H8300_IRQFLAGS_H */
diff --git a/arch/h8300/include/asm/system.h b/arch/h8300/include/asm/system.h
index 16bf1560ff68..2c2382e50d93 100644
--- a/arch/h8300/include/asm/system.h
+++ b/arch/h8300/include/asm/system.h
@@ -2,6 +2,7 @@
#define _H8300_SYSTEM_H
#include <linux/linkage.h>
+#include <linux/irqflags.h>
struct pt_regs;
@@ -51,31 +52,8 @@ asmlinkage void resume(void);
(last) = _last; \
}
-#define __sti() asm volatile ("andc #0x7f,ccr")
-#define __cli() asm volatile ("orc #0x80,ccr")
-
-#define __save_flags(x) \
- asm volatile ("stc ccr,%w0":"=r" (x))
-
-#define __restore_flags(x) \
- asm volatile ("ldc %w0,ccr": :"r" (x))
-
-#define irqs_disabled() \
-({ \
- unsigned char flags; \
- __save_flags(flags); \
- ((flags & 0x80) == 0x80); \
-})
-
#define iret() __asm__ __volatile__ ("rte": : :"memory", "sp", "cc")
-/* For spinlocks etc */
-#define local_irq_disable() __cli()
-#define local_irq_enable() __sti()
-#define local_irq_save(x) ({ __save_flags(x); local_irq_disable(); })
-#define local_irq_restore(x) __restore_flags(x)
-#define local_save_flags(x) __save_flags(x)
-
/*
* Force strict CPU ordering.
* Not really required on H8...
diff --git a/arch/h8300/kernel/module.c b/arch/h8300/kernel/module.c
index 0865e291c20d..db4953dc4e1b 100644
--- a/arch/h8300/kernel/module.c
+++ b/arch/h8300/kernel/module.c
@@ -112,10 +112,9 @@ int module_finalize(const Elf_Ehdr *hdr,
const Elf_Shdr *sechdrs,
struct module *me)
{
- return module_bug_finalize(hdr, sechdrs, me);
+ return 0;
}
void module_arch_cleanup(struct module *mod)
{
- module_bug_cleanup(mod);
}
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index ba22849ee3ec..7c82fa1fc911 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -53,6 +53,9 @@ config MMU
bool
default y
+config ARCH_DMA_ADDR_T_64BIT
+ def_bool y
+
config NEED_DMA_MAP_STATE
def_bool y
@@ -62,6 +65,9 @@ config NEED_SG_DMA_LENGTH
config SWIOTLB
bool
+config STACKTRACE_SUPPORT
+ def_bool y
+
config GENERIC_LOCKBREAK
def_bool n
@@ -683,8 +689,10 @@ source "lib/Kconfig"
# Use the generic interrupt handling code in kernel/irq/:
#
config GENERIC_HARDIRQS
- bool
- default y
+ def_bool y
+
+config GENERIC_HARDIRQS_NO__DO_IRQ
+ def_bool y
config GENERIC_IRQ_PROBE
bool
diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c
index 1e8d71ad93ef..13633da0d3de 100644
--- a/arch/ia64/hp/sim/simserial.c
+++ b/arch/ia64/hp/sim/simserial.c
@@ -395,7 +395,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
{
if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
(cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
- (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
+ (cmd != TIOCMIWAIT)) {
if (tty->flags & (1 << TTY_IO_ERROR))
return -EIO;
}
@@ -433,16 +433,6 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
case TIOCMIWAIT:
printk(KERN_INFO "rs_ioctl: TIOCMIWAIT: called\n");
return 0;
- /*
- * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
- * Return: write counters to the user passed counter struct
- * NB: both 1->0 and 0->1 transitions are counted except for
- * RI where only 0->1 is counted.
- */
- case TIOCGICOUNT:
- printk(KERN_INFO "rs_ioctl: TIOCGICOUNT called\n");
- return 0;
-
case TIOCSERGWILD:
case TIOCSERSWILD:
/* "setserial -W" is called in Debian boot */
diff --git a/arch/ia64/include/asm/compat.h b/arch/ia64/include/asm/compat.h
deleted file mode 100644
index 9301a2821615..000000000000
--- a/arch/ia64/include/asm/compat.h
+++ /dev/null
@@ -1,208 +0,0 @@
-#ifndef _ASM_IA64_COMPAT_H
-#define _ASM_IA64_COMPAT_H
-/*
- * Architecture specific compatibility types
- */
-#include <linux/types.h>
-
-#define COMPAT_USER_HZ 100
-#define COMPAT_UTS_MACHINE "i686\0\0\0"
-
-typedef u32 compat_size_t;
-typedef s32 compat_ssize_t;
-typedef s32 compat_time_t;
-typedef s32 compat_clock_t;
-typedef s32 compat_key_t;
-typedef s32 compat_pid_t;
-typedef u16 __compat_uid_t;
-typedef u16 __compat_gid_t;
-typedef u32 __compat_uid32_t;
-typedef u32 __compat_gid32_t;
-typedef u16 compat_mode_t;
-typedef u32 compat_ino_t;
-typedef u16 compat_dev_t;
-typedef s32 compat_off_t;
-typedef s64 compat_loff_t;
-typedef u16 compat_nlink_t;
-typedef u16 compat_ipc_pid_t;
-typedef s32 compat_daddr_t;
-typedef u32 compat_caddr_t;
-typedef __kernel_fsid_t compat_fsid_t;
-typedef s32 compat_timer_t;
-
-typedef s32 compat_int_t;
-typedef s32 compat_long_t;
-typedef s64 __attribute__((aligned(4))) compat_s64;
-typedef u32 compat_uint_t;
-typedef u32 compat_ulong_t;
-typedef u64 __attribute__((aligned(4))) compat_u64;
-
-struct compat_timespec {
- compat_time_t tv_sec;
- s32 tv_nsec;
-};
-
-struct compat_timeval {
- compat_time_t tv_sec;
- s32 tv_usec;
-};
-
-struct compat_stat {
- compat_dev_t st_dev;
- u16 __pad1;
- compat_ino_t st_ino;
- compat_mode_t st_mode;
- compat_nlink_t st_nlink;
- __compat_uid_t st_uid;
- __compat_gid_t st_gid;
- compat_dev_t st_rdev;
- u16 __pad2;
- u32 st_size;
- u32 st_blksize;
- u32 st_blocks;
- u32 st_atime;
- u32 st_atime_nsec;
- u32 st_mtime;
- u32 st_mtime_nsec;
- u32 st_ctime;
- u32 st_ctime_nsec;
- u32 __unused4;
- u32 __unused5;
-};
-
-struct compat_flock {
- short l_type;
- short l_whence;
- compat_off_t l_start;
- compat_off_t l_len;
- compat_pid_t l_pid;
-};
-
-#define F_GETLK64 12
-#define F_SETLK64 13
-#define F_SETLKW64 14
-
-/*
- * IA32 uses 4 byte alignment for 64 bit quantities,
- * so we need to pack this structure.
- */
-struct compat_flock64 {
- short l_type;
- short l_whence;
- compat_loff_t l_start;
- compat_loff_t l_len;
- compat_pid_t l_pid;
-} __attribute__((packed));
-
-struct compat_statfs {
- int f_type;
- int f_bsize;
- int f_blocks;
- int f_bfree;
- int f_bavail;
- int f_files;
- int f_ffree;
- compat_fsid_t f_fsid;
- int f_namelen; /* SunOS ignores this field. */
- int f_frsize;
- int f_spare[5];
-};
-
-#define COMPAT_RLIM_OLD_INFINITY 0x7fffffff
-#define COMPAT_RLIM_INFINITY 0xffffffff
-
-typedef u32 compat_old_sigset_t; /* at least 32 bits */
-
-#define _COMPAT_NSIG 64
-#define _COMPAT_NSIG_BPW 32
-
-typedef u32 compat_sigset_word;
-
-#define COMPAT_OFF_T_MAX 0x7fffffff
-#define COMPAT_LOFF_T_MAX 0x7fffffffffffffffL
-
-struct compat_ipc64_perm {
- compat_key_t key;
- __compat_uid32_t uid;
- __compat_gid32_t gid;
- __compat_uid32_t cuid;
- __compat_gid32_t cgid;
- unsigned short mode;
- unsigned short __pad1;
- unsigned short seq;
- unsigned short __pad2;
- compat_ulong_t unused1;
- compat_ulong_t unused2;
-};
-
-struct compat_semid64_ds {
- struct compat_ipc64_perm sem_perm;
- compat_time_t sem_otime;
- compat_ulong_t __unused1;
- compat_time_t sem_ctime;
- compat_ulong_t __unused2;
- compat_ulong_t sem_nsems;
- compat_ulong_t __unused3;
- compat_ulong_t __unused4;
-};
-
-struct compat_msqid64_ds {
- struct compat_ipc64_perm msg_perm;
- compat_time_t msg_stime;
- compat_ulong_t __unused1;
- compat_time_t msg_rtime;
- compat_ulong_t __unused2;
- compat_time_t msg_ctime;
- compat_ulong_t __unused3;
- compat_ulong_t msg_cbytes;
- compat_ulong_t msg_qnum;
- compat_ulong_t msg_qbytes;
- compat_pid_t msg_lspid;
- compat_pid_t msg_lrpid;
- compat_ulong_t __unused4;
- compat_ulong_t __unused5;
-};
-
-struct compat_shmid64_ds {
- struct compat_ipc64_perm shm_perm;
- compat_size_t shm_segsz;
- compat_time_t shm_atime;
- compat_ulong_t __unused1;
- compat_time_t shm_dtime;
- compat_ulong_t __unused2;
- compat_time_t shm_ctime;
- compat_ulong_t __unused3;
- compat_pid_t shm_cpid;
- compat_pid_t shm_lpid;
- compat_ulong_t shm_nattch;
- compat_ulong_t __unused4;
- compat_ulong_t __unused5;
-};
-
-/*
- * A pointer passed in from user mode. This should not be used for syscall parameters,
- * just declare them as pointers because the syscall entry code will have appropriately
- * converted them already.
- */
-typedef u32 compat_uptr_t;
-
-static inline void __user *
-compat_ptr (compat_uptr_t uptr)
-{
- return (void __user *) (unsigned long) uptr;
-}
-
-static inline compat_uptr_t
-ptr_to_compat(void __user *uptr)
-{
- return (u32)(unsigned long)uptr;
-}
-
-static __inline__ void __user *
-arch_compat_alloc_user_space (long len)
-{
- struct pt_regs *regs = task_pt_regs(current);
- return (void __user *) (((regs->r12 & 0xffffffff) & -16) - len);
-}
-
-#endif /* _ASM_IA64_COMPAT_H */
diff --git a/arch/ia64/include/asm/hardirq.h b/arch/ia64/include/asm/hardirq.h
index d514cd9edb49..8fb7d33a661f 100644
--- a/arch/ia64/include/asm/hardirq.h
+++ b/arch/ia64/include/asm/hardirq.h
@@ -6,12 +6,6 @@
* David Mosberger-Tang <davidm@hpl.hp.com>
*/
-
-#include <linux/threads.h>
-#include <linux/irq.h>
-
-#include <asm/processor.h>
-
/*
* No irq_cpustat_t for IA-64. The data is held in the per-CPU data structure.
*/
@@ -20,6 +14,11 @@
#define local_softirq_pending() (local_cpu_data->softirq_pending)
+#include <linux/threads.h>
+#include <linux/irq.h>
+
+#include <asm/processor.h>
+
extern void __iomem *ipi_base_addr;
void ack_bad_irq(unsigned int irq);
diff --git a/arch/ia64/include/asm/ioctls.h b/arch/ia64/include/asm/ioctls.h
index b79c385114ef..f3aab5512e98 100644
--- a/arch/ia64/include/asm/ioctls.h
+++ b/arch/ia64/include/asm/ioctls.h
@@ -1,93 +1,6 @@
#ifndef _ASM_IA64_IOCTLS_H
#define _ASM_IA64_IOCTLS_H
-/*
- * Based on <asm-i386/ioctls.h>
- *
- * Modified 1998, 1999, 2002
- * David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
- */
-
-#include <asm/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS 0x5401
-#define TCSETS 0x5402 /* Clashes with SNDCTL_TMR_START sound ioctl */
-#define TCSETSW 0x5403
-#define TCSETSF 0x5404
-#define TCGETA 0x5405
-#define TCSETA 0x5406
-#define TCSETAW 0x5407
-#define TCSETAF 0x5408
-#define TCSBRK 0x5409
-#define TCXONC 0x540A
-#define TCFLSH 0x540B
-#define TIOCEXCL 0x540C
-#define TIOCNXCL 0x540D
-#define TIOCSCTTY 0x540E
-#define TIOCGPGRP 0x540F
-#define TIOCSPGRP 0x5410
-#define TIOCOUTQ 0x5411
-#define TIOCSTI 0x5412
-#define TIOCGWINSZ 0x5413
-#define TIOCSWINSZ 0x5414
-#define TIOCMGET 0x5415
-#define TIOCMBIS 0x5416
-#define TIOCMBIC 0x5417
-#define TIOCMSET 0x5418
-#define TIOCGSOFTCAR 0x5419
-#define TIOCSSOFTCAR 0x541A
-#define FIONREAD 0x541B
-#define TIOCINQ FIONREAD
-#define TIOCLINUX 0x541C
-#define TIOCCONS 0x541D
-#define TIOCGSERIAL 0x541E
-#define TIOCSSERIAL 0x541F
-#define TIOCPKT 0x5420
-#define FIONBIO 0x5421
-#define TIOCNOTTY 0x5422
-#define TIOCSETD 0x5423
-#define TIOCGETD 0x5424
-#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
-#define TIOCSBRK 0x5427 /* BSD compatibility */
-#define TIOCCBRK 0x5428 /* BSD compatibility */
-#define TIOCGSID 0x5429 /* Return the session ID of FD */
-#define TCGETS2 _IOR('T',0x2A, struct termios2)
-#define TCSETS2 _IOW('T',0x2B, struct termios2)
-#define TCSETSW2 _IOW('T',0x2C, struct termios2)
-#define TCSETSF2 _IOW('T',0x2D, struct termios2)
-#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
-#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
-#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */
-
-#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */
-#define FIOCLEX 0x5451
-#define FIOASYNC 0x5452
-#define TIOCSERCONFIG 0x5453
-#define TIOCSERGWILD 0x5454
-#define TIOCSERSWILD 0x5455
-#define TIOCGLCKTRMIOS 0x5456
-#define TIOCSLCKTRMIOS 0x5457
-#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
-#define TIOCSERGETLSR 0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
-#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
-#define FIOQSIZE 0x5460
-
-/* Used for packet mode */
-#define TIOCPKT_DATA 0
-#define TIOCPKT_FLUSHREAD 1
-#define TIOCPKT_FLUSHWRITE 2
-#define TIOCPKT_STOP 4
-#define TIOCPKT_START 8
-#define TIOCPKT_NOSTOP 16
-#define TIOCPKT_DOSTOP 32
-#define TIOCPKT_IOCTL 64
-
-#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
+#include <asm-generic/ioctls.h>
#endif /* _ASM_IA64_IOCTLS_H */
diff --git a/arch/ia64/include/asm/iommu_table.h b/arch/ia64/include/asm/iommu_table.h
new file mode 100644
index 000000000000..92c8d36ae5ae
--- /dev/null
+++ b/arch/ia64/include/asm/iommu_table.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_IA64_IOMMU_TABLE_H
+#define _ASM_IA64_IOMMU_TABLE_H
+
+#define IOMMU_INIT_POST(_detect)
+
+#endif /* _ASM_IA64_IOMMU_TABLE_H */
diff --git a/arch/ia64/include/asm/irqflags.h b/arch/ia64/include/asm/irqflags.h
new file mode 100644
index 000000000000..f82d6be2ecd2
--- /dev/null
+++ b/arch/ia64/include/asm/irqflags.h
@@ -0,0 +1,94 @@
+/*
+ * IRQ flags defines.
+ *
+ * Copyright (C) 1998-2003 Hewlett-Packard Co
+ * David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com>
+ * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
+ */
+
+#ifndef _ASM_IA64_IRQFLAGS_H
+#define _ASM_IA64_IRQFLAGS_H
+
+#ifdef CONFIG_IA64_DEBUG_IRQ
+extern unsigned long last_cli_ip;
+static inline void arch_maybe_save_ip(unsigned long flags)
+{
+ if (flags & IA64_PSR_I)
+ last_cli_ip = ia64_getreg(_IA64_REG_IP);
+}
+#else
+#define arch_maybe_save_ip(flags) do {} while (0)
+#endif
+
+/*
+ * - clearing psr.i is implicitly serialized (visible by next insn)
+ * - setting psr.i requires data serialization
+ * - we need a stop-bit before reading PSR because we sometimes
+ * write a floating-point register right before reading the PSR
+ * and that writes to PSR.mfl
+ */
+
+static inline unsigned long arch_local_save_flags(void)
+{
+ ia64_stop();
+#ifdef CONFIG_PARAVIRT
+ return ia64_get_psr_i();
+#else
+ return ia64_getreg(_IA64_REG_PSR);
+#endif
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+ unsigned long flags = arch_local_save_flags();
+
+ ia64_stop();
+ ia64_rsm(IA64_PSR_I);
+ arch_maybe_save_ip(flags);
+ return flags;
+}
+
+static inline void arch_local_irq_disable(void)
+{
+#ifdef CONFIG_IA64_DEBUG_IRQ
+ arch_local_irq_save();
+#else
+ ia64_stop();
+ ia64_rsm(IA64_PSR_I);
+#endif
+}
+
+static inline void arch_local_irq_enable(void)
+{
+ ia64_stop();
+ ia64_ssm(IA64_PSR_I);
+ ia64_srlz_d();
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+#ifdef CONFIG_IA64_DEBUG_IRQ
+ unsigned long old_psr = arch_local_save_flags();
+#endif
+ ia64_intrin_local_irq_restore(flags & IA64_PSR_I);
+ arch_maybe_save_ip(old_psr & ~flags);
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+ return (flags & IA64_PSR_I) == 0;
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+ return arch_irqs_disabled_flags(arch_local_save_flags());
+}
+
+static inline void arch_safe_halt(void)
+{
+ ia64_pal_halt_light(); /* PAL_HALT_LIGHT */
+}
+
+
+#endif /* _ASM_IA64_IRQFLAGS_H */
diff --git a/arch/ia64/include/asm/system.h b/arch/ia64/include/asm/system.h
index 9f342a574ce8..6cca30705d50 100644
--- a/arch/ia64/include/asm/system.h
+++ b/arch/ia64/include/asm/system.h
@@ -107,87 +107,11 @@ extern struct ia64_boot_param {
*/
#define set_mb(var, value) do { (var) = (value); mb(); } while (0)
-#define safe_halt() ia64_pal_halt_light() /* PAL_HALT_LIGHT */
-
/*
* The group barrier in front of the rsm & ssm are necessary to ensure
* that none of the previous instructions in the same group are
* affected by the rsm/ssm.
*/
-/* For spinlocks etc */
-
-/*
- * - clearing psr.i is implicitly serialized (visible by next insn)
- * - setting psr.i requires data serialization
- * - we need a stop-bit before reading PSR because we sometimes
- * write a floating-point register right before reading the PSR
- * and that writes to PSR.mfl
- */
-#ifdef CONFIG_PARAVIRT
-#define __local_save_flags() ia64_get_psr_i()
-#else
-#define __local_save_flags() ia64_getreg(_IA64_REG_PSR)
-#endif
-
-#define __local_irq_save(x) \
-do { \
- ia64_stop(); \
- (x) = __local_save_flags(); \
- ia64_stop(); \
- ia64_rsm(IA64_PSR_I); \
-} while (0)
-
-#define __local_irq_disable() \
-do { \
- ia64_stop(); \
- ia64_rsm(IA64_PSR_I); \
-} while (0)
-
-#define __local_irq_restore(x) ia64_intrin_local_irq_restore((x) & IA64_PSR_I)
-
-#ifdef CONFIG_IA64_DEBUG_IRQ
-
- extern unsigned long last_cli_ip;
-
-# define __save_ip() last_cli_ip = ia64_getreg(_IA64_REG_IP)
-
-# define local_irq_save(x) \
-do { \
- unsigned long __psr; \
- \
- __local_irq_save(__psr); \
- if (__psr & IA64_PSR_I) \
- __save_ip(); \
- (x) = __psr; \
-} while (0)
-
-# define local_irq_disable() do { unsigned long __x; local_irq_save(__x); } while (0)
-
-# define local_irq_restore(x) \
-do { \
- unsigned long __old_psr, __psr = (x); \
- \
- local_save_flags(__old_psr); \
- __local_irq_restore(__psr); \
- if ((__old_psr & IA64_PSR_I) && !(__psr & IA64_PSR_I)) \
- __save_ip(); \
-} while (0)
-
-#else /* !CONFIG_IA64_DEBUG_IRQ */
-# define local_irq_save(x) __local_irq_save(x)
-# define local_irq_disable() __local_irq_disable()
-# define local_irq_restore(x) __local_irq_restore(x)
-#endif /* !CONFIG_IA64_DEBUG_IRQ */
-
-#define local_irq_enable() ({ ia64_stop(); ia64_ssm(IA64_PSR_I); ia64_srlz_d(); })
-#define local_save_flags(flags) ({ ia64_stop(); (flags) = __local_save_flags(); })
-
-#define irqs_disabled() \
-({ \
- unsigned long __ia64_id_flags; \
- local_save_flags(__ia64_id_flags); \
- (__ia64_id_flags & IA64_PSR_I) == 0; \
-})
#ifdef __KERNEL__
@@ -272,10 +196,6 @@ void cpu_idle_wait(void);
void default_idle(void);
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING
-extern void account_system_vtime(struct task_struct *);
-#endif
-
#endif /* __KERNEL__ */
#endif /* __ASSEMBLY__ */
diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile
index db10b1e378b0..395c2f216dd8 100644
--- a/arch/ia64/kernel/Makefile
+++ b/arch/ia64/kernel/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_AUDIT) += audit.o
obj-$(CONFIG_PCI_MSI) += msi_ia64.o
mca_recovery-y += mca_drv.o mca_drv_asm.o
obj-$(CONFIG_IA64_MC_ERR_INJECT)+= err_inject.o
+obj-$(CONFIG_STACKTRACE) += stacktrace.o
obj-$(CONFIG_PARAVIRT) += paravirt.o paravirtentry.o \
paravirt_patch.o
diff --git a/arch/ia64/kernel/cyclone.c b/arch/ia64/kernel/cyclone.c
index 71e35864d2e2..d52f1f78eff2 100644
--- a/arch/ia64/kernel/cyclone.c
+++ b/arch/ia64/kernel/cyclone.c
@@ -59,13 +59,13 @@ int __init init_cyclone_clock(void)
return -ENODEV;
}
base = readq(reg);
+ iounmap(reg);
if(!base){
printk(KERN_ERR "Summit chipset: Could not find valid CBAR"
" value.\n");
use_cyclone = 0;
return -ENODEV;
}
- iounmap(reg);
/* setup PMCC */
offset = (base + CYCLONE_PMCC_OFFSET);
diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c
index 7ded76658d2d..22c38404f539 100644
--- a/arch/ia64/kernel/iosapic.c
+++ b/arch/ia64/kernel/iosapic.c
@@ -108,10 +108,6 @@
#define DBG(fmt...)
#endif
-#define NR_PREALLOCATE_RTE_ENTRIES \
- (PAGE_SIZE / sizeof(struct iosapic_rte_info))
-#define RTE_PREALLOCATED (1)
-
static DEFINE_SPINLOCK(iosapic_lock);
/*
@@ -136,7 +132,6 @@ struct iosapic_rte_info {
struct list_head rte_list; /* RTEs sharing the same vector */
char rte_index; /* IOSAPIC RTE index */
int refcnt; /* reference counter */
- unsigned int flags; /* flags */
struct iosapic *iosapic;
} ____cacheline_aligned;
@@ -155,9 +150,6 @@ static struct iosapic_intr_info {
static unsigned char pcat_compat __devinitdata; /* 8259 compatibility flag */
-static int iosapic_kmalloc_ok;
-static LIST_HEAD(free_rte_list);
-
static inline void
iosapic_write(struct iosapic *iosapic, unsigned int reg, u32 val)
{
@@ -394,7 +386,7 @@ iosapic_startup_level_irq (unsigned int irq)
}
static void
-iosapic_end_level_irq (unsigned int irq)
+iosapic_unmask_level_irq (unsigned int irq)
{
ia64_vector vec = irq_to_vector(irq);
struct iosapic_rte_info *rte;
@@ -404,7 +396,8 @@ iosapic_end_level_irq (unsigned int irq)
if (unlikely(irq_desc[irq].status & IRQ_MOVE_PENDING)) {
do_unmask_irq = 1;
mask_irq(irq);
- }
+ } else
+ unmask_irq(irq);
list_for_each_entry(rte, &iosapic_intr_info[irq].rtes, rte_list)
iosapic_eoi(rte->iosapic->addr, vec);
@@ -427,9 +420,8 @@ static struct irq_chip irq_type_iosapic_level = {
.enable = iosapic_enable_level_irq,
.disable = iosapic_disable_level_irq,
.ack = iosapic_ack_level_irq,
- .end = iosapic_end_level_irq,
.mask = mask_irq,
- .unmask = unmask_irq,
+ .unmask = iosapic_unmask_level_irq,
.set_affinity = iosapic_set_affinity
};
@@ -552,37 +544,6 @@ iosapic_reassign_vector (int irq)
}
}
-static struct iosapic_rte_info * __init_refok iosapic_alloc_rte (void)
-{
- int i;
- struct iosapic_rte_info *rte;
- int preallocated = 0;
-
- if (!iosapic_kmalloc_ok && list_empty(&free_rte_list)) {
- rte = alloc_bootmem(sizeof(struct iosapic_rte_info) *
- NR_PREALLOCATE_RTE_ENTRIES);
- for (i = 0; i < NR_PREALLOCATE_RTE_ENTRIES; i++, rte++)
- list_add(&rte->rte_list, &free_rte_list);
- }
-
- if (!list_empty(&free_rte_list)) {
- rte = list_entry(free_rte_list.next, struct iosapic_rte_info,
- rte_list);
- list_del(&rte->rte_list);
- preallocated++;
- } else {
- rte = kmalloc(sizeof(struct iosapic_rte_info), GFP_ATOMIC);
- if (!rte)
- return NULL;
- }
-
- memset(rte, 0, sizeof(struct iosapic_rte_info));
- if (preallocated)
- rte->flags |= RTE_PREALLOCATED;
-
- return rte;
-}
-
static inline int irq_is_shared (int irq)
{
return (iosapic_intr_info[irq].count > 1);
@@ -615,7 +576,7 @@ register_intr (unsigned int gsi, int irq, unsigned char delivery,
rte = find_rte(irq, gsi);
if (!rte) {
- rte = iosapic_alloc_rte();
+ rte = kzalloc(sizeof (*rte), GFP_ATOMIC);
if (!rte) {
printk(KERN_WARNING "%s: cannot allocate memory\n",
__func__);
@@ -658,6 +619,10 @@ register_intr (unsigned int gsi, int irq, unsigned char delivery,
idesc->chip->name, irq_type->name);
idesc->chip = irq_type;
}
+ if (trigger == IOSAPIC_EDGE)
+ __set_irq_handler_unlocked(irq, handle_edge_irq);
+ else
+ __set_irq_handler_unlocked(irq, handle_level_irq);
return 0;
}
@@ -1161,10 +1126,3 @@ map_iosapic_to_node(unsigned int gsi_base, int node)
return;
}
#endif
-
-static int __init iosapic_enable_kmalloc (void)
-{
- iosapic_kmalloc_ok = 1;
- return 0;
-}
-core_initcall (iosapic_enable_kmalloc);
diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c
index f14c35f9b03a..9a26015c3e50 100644
--- a/arch/ia64/kernel/irq_ia64.c
+++ b/arch/ia64/kernel/irq_ia64.c
@@ -30,6 +30,7 @@
#include <linux/bitops.h>
#include <linux/irq.h>
#include <linux/ratelimit.h>
+#include <linux/acpi.h>
#include <asm/delay.h>
#include <asm/intrinsics.h>
@@ -635,6 +636,7 @@ ia64_native_register_percpu_irq (ia64_vector vec, struct irqaction *action)
desc->chip = &irq_type_ia64_lsapic;
if (action)
setup_irq(irq, action);
+ set_irq_handler(irq, handle_percpu_irq);
}
void __init
@@ -650,6 +652,9 @@ ia64_native_register_ipi(void)
void __init
init_IRQ (void)
{
+#ifdef CONFIG_ACPI
+ acpi_boot_init();
+#endif
ia64_register_ipi();
register_percpu_irq(IA64_SPURIOUS_INT_VECTOR, NULL);
#ifdef CONFIG_SMP
diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
index a0220dc5ff42..1753f6a30d55 100644
--- a/arch/ia64/kernel/mca.c
+++ b/arch/ia64/kernel/mca.c
@@ -2055,25 +2055,6 @@ ia64_mca_init(void)
IA64_MCA_DEBUG("%s: registered OS INIT handler with SAL\n", __func__);
- /*
- * Configure the CMCI/P vector and handler. Interrupts for CMC are
- * per-processor, so AP CMC interrupts are setup in smp_callin() (smpboot.c).
- */
- register_percpu_irq(IA64_CMC_VECTOR, &cmci_irqaction);
- register_percpu_irq(IA64_CMCP_VECTOR, &cmcp_irqaction);
- ia64_mca_cmc_vector_setup(); /* Setup vector on BSP */
-
- /* Setup the MCA rendezvous interrupt vector */
- register_percpu_irq(IA64_MCA_RENDEZ_VECTOR, &mca_rdzv_irqaction);
-
- /* Setup the MCA wakeup interrupt vector */
- register_percpu_irq(IA64_MCA_WAKEUP_VECTOR, &mca_wkup_irqaction);
-
-#ifdef CONFIG_ACPI
- /* Setup the CPEI/P handler */
- register_percpu_irq(IA64_CPEP_VECTOR, &mca_cpep_irqaction);
-#endif
-
/* Initialize the areas set aside by the OS to buffer the
* platform/processor error states for MCA/INIT/CMC
* handling.
@@ -2103,6 +2084,25 @@ ia64_mca_late_init(void)
if (!mca_init)
return 0;
+ /*
+ * Configure the CMCI/P vector and handler. Interrupts for CMC are
+ * per-processor, so AP CMC interrupts are setup in smp_callin() (smpboot.c).
+ */
+ register_percpu_irq(IA64_CMC_VECTOR, &cmci_irqaction);
+ register_percpu_irq(IA64_CMCP_VECTOR, &cmcp_irqaction);
+ ia64_mca_cmc_vector_setup(); /* Setup vector on BSP */
+
+ /* Setup the MCA rendezvous interrupt vector */
+ register_percpu_irq(IA64_MCA_RENDEZ_VECTOR, &mca_rdzv_irqaction);
+
+ /* Setup the MCA wakeup interrupt vector */
+ register_percpu_irq(IA64_MCA_WAKEUP_VECTOR, &mca_wkup_irqaction);
+
+#ifdef CONFIG_ACPI
+ /* Setup the CPEI/P handler */
+ register_percpu_irq(IA64_CPEP_VECTOR, &mca_cpep_irqaction);
+#endif
+
register_hotcpu_notifier(&mca_cpu_notifier);
/* Setup the CMCI/P vector and handler */
diff --git a/arch/ia64/kernel/msi_ia64.c b/arch/ia64/kernel/msi_ia64.c
index 4a746ea838ff..00b19a416eab 100644
--- a/arch/ia64/kernel/msi_ia64.c
+++ b/arch/ia64/kernel/msi_ia64.c
@@ -104,8 +104,8 @@ static int ia64_msi_retrigger_irq(unsigned int irq)
*/
static struct irq_chip ia64_msi_chip = {
.name = "PCI-MSI",
- .mask = mask_msi_irq,
- .unmask = unmask_msi_irq,
+ .irq_mask = mask_msi_irq,
+ .irq_unmask = unmask_msi_irq,
.ack = ia64_ack_msi_irq,
#ifdef CONFIG_SMP
.set_affinity = ia64_set_msi_irq_affinity,
@@ -160,8 +160,8 @@ static int dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
static struct irq_chip dmar_msi_type = {
.name = "DMAR_MSI",
- .unmask = dmar_msi_unmask,
- .mask = dmar_msi_mask,
+ .irq_unmask = dmar_msi_unmask,
+ .irq_mask = dmar_msi_mask,
.ack = ia64_ack_msi_irq,
#ifdef CONFIG_SMP
.set_affinity = dmar_msi_set_affinity,
diff --git a/arch/ia64/kernel/palinfo.c b/arch/ia64/kernel/palinfo.c
index fdf6f9d013e5..77597e5ea60a 100644
--- a/arch/ia64/kernel/palinfo.c
+++ b/arch/ia64/kernel/palinfo.c
@@ -434,7 +434,7 @@ register_info(char *page)
unsigned long phys_stacked;
pal_hints_u_t hints;
unsigned long iregs, dregs;
- char *info_type[]={
+ static const char * const info_type[] = {
"Implemented AR(s)",
"AR(s) with read side-effects",
"Implemented CR(s)",
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index cce050e85c73..6b1852f7f972 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -1573,7 +1573,7 @@ pfm_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
return -EINVAL;
}
- ctx = (pfm_context_t *)filp->private_data;
+ ctx = filp->private_data;
if (ctx == NULL) {
printk(KERN_ERR "perfmon: pfm_read: NULL ctx [%d]\n", task_pid_nr(current));
return -EINVAL;
@@ -1673,7 +1673,7 @@ pfm_poll(struct file *filp, poll_table * wait)
return 0;
}
- ctx = (pfm_context_t *)filp->private_data;
+ ctx = filp->private_data;
if (ctx == NULL) {
printk(KERN_ERR "perfmon: pfm_poll: NULL ctx [%d]\n", task_pid_nr(current));
return 0;
@@ -1733,7 +1733,7 @@ pfm_fasync(int fd, struct file *filp, int on)
return -EBADF;
}
- ctx = (pfm_context_t *)filp->private_data;
+ ctx = filp->private_data;
if (ctx == NULL) {
printk(KERN_ERR "perfmon: pfm_fasync NULL ctx [%d]\n", task_pid_nr(current));
return -EBADF;
@@ -1841,7 +1841,7 @@ pfm_flush(struct file *filp, fl_owner_t id)
return -EBADF;
}
- ctx = (pfm_context_t *)filp->private_data;
+ ctx = filp->private_data;
if (ctx == NULL) {
printk(KERN_ERR "perfmon: pfm_flush: NULL ctx [%d]\n", task_pid_nr(current));
return -EBADF;
@@ -1984,7 +1984,7 @@ pfm_close(struct inode *inode, struct file *filp)
return -EBADF;
}
- ctx = (pfm_context_t *)filp->private_data;
+ ctx = filp->private_data;
if (ctx == NULL) {
printk(KERN_ERR "perfmon: pfm_close: NULL ctx [%d]\n", task_pid_nr(current));
return -EBADF;
@@ -4907,7 +4907,7 @@ restart_args:
goto error_args;
}
- ctx = (pfm_context_t *)file->private_data;
+ ctx = file->private_data;
if (unlikely(ctx == NULL)) {
DPRINT(("no context for fd %d\n", fd));
goto error_args;
diff --git a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c
index aa8b5fa1a8de..79802e540e53 100644
--- a/arch/ia64/kernel/salinfo.c
+++ b/arch/ia64/kernel/salinfo.c
@@ -354,6 +354,7 @@ retry:
static const struct file_operations salinfo_event_fops = {
.open = salinfo_event_open,
.read = salinfo_event_read,
+ .llseek = noop_llseek,
};
static int
@@ -571,6 +572,7 @@ static const struct file_operations salinfo_data_fops = {
.release = salinfo_log_release,
.read = salinfo_log_read,
.write = salinfo_log_write,
+ .llseek = default_llseek,
};
static int __cpuinit
@@ -642,7 +644,7 @@ salinfo_init(void)
for (i = 0; i < ARRAY_SIZE(salinfo_log_name); i++) {
data = salinfo_data + i;
data->type = i;
- init_MUTEX(&data->mutex);
+ sema_init(&data->mutex, 1);
dir = proc_mkdir(salinfo_log_name[i], salinfo_dir);
if (!dir)
continue;
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index 8fb958abf8d0..911cf9749700 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -594,10 +594,6 @@ setup_arch (char **cmdline_p)
cpu_init(); /* initialize the bootstrap CPU */
mmu_context_init(); /* initialize context_id bitmap */
-#ifdef CONFIG_ACPI
- acpi_boot_init();
-#endif
-
paravirt_banner();
paravirt_arch_setup_console(cmdline_p);
diff --git a/arch/ia64/kernel/stacktrace.c b/arch/ia64/kernel/stacktrace.c
new file mode 100644
index 000000000000..5af2783a87f4
--- /dev/null
+++ b/arch/ia64/kernel/stacktrace.c
@@ -0,0 +1,39 @@
+/*
+ * arch/ia64/kernel/stacktrace.c
+ *
+ * Stack trace management functions
+ *
+ */
+#include <linux/sched.h>
+#include <linux/stacktrace.h>
+#include <linux/module.h>
+
+static void
+ia64_do_save_stack(struct unw_frame_info *info, void *arg)
+{
+ struct stack_trace *trace = arg;
+ unsigned long ip;
+ int skip = trace->skip;
+
+ trace->nr_entries = 0;
+ do {
+ unw_get_ip(info, &ip);
+ if (ip == 0)
+ break;
+ if (skip == 0) {
+ trace->entries[trace->nr_entries++] = ip;
+ if (trace->nr_entries == trace->max_entries)
+ break;
+ } else
+ skip--;
+ } while (unw_unwind(info) >= 0);
+}
+
+/*
+ * Save stack-backtrace addresses into a stack_trace buffer.
+ */
+void save_stack_trace(struct stack_trace *trace)
+{
+ unw_init_running(ia64_do_save_stack, trace);
+}
+EXPORT_SYMBOL(save_stack_trace);
diff --git a/arch/ia64/kernel/unwind.c b/arch/ia64/kernel/unwind.c
index b6c0e63a0bf6..fed6afa2e8a9 100644
--- a/arch/ia64/kernel/unwind.c
+++ b/arch/ia64/kernel/unwind.c
@@ -1204,10 +1204,10 @@ desc_spill_sprel_p (unsigned char qp, unw_word t, unsigned char abreg, unw_word
static inline unw_hash_index_t
hash (unsigned long ip)
{
-# define hashmagic 0x9e3779b97f4a7c16UL /* based on (sqrt(5)/2-1)*2^64 */
+ /* magic number = ((sqrt(5)-1)/2)*2^64 */
+ static const unsigned long hashmagic = 0x9e3779b97f4a7c16UL;
- return (ip >> 4)*hashmagic >> (64 - UNW_LOG_HASH_SIZE);
-#undef hashmagic
+ return (ip >> 4) * hashmagic >> (64 - UNW_LOG_HASH_SIZE);
}
static inline long
@@ -1531,7 +1531,7 @@ build_script (struct unw_frame_info *info)
struct unw_labeled_state *ls, *next;
unsigned long ip = info->ip;
struct unw_state_record sr;
- struct unw_table *table;
+ struct unw_table *table, *prev;
struct unw_reg_info *r;
struct unw_insn insn;
u8 *dp, *desc_end;
@@ -1560,11 +1560,26 @@ build_script (struct unw_frame_info *info)
STAT(parse_start = ia64_get_itc());
+ prev = NULL;
for (table = unw.tables; table; table = table->next) {
if (ip >= table->start && ip < table->end) {
+ /*
+ * Leave the kernel unwind table at the very front,
+ * lest moving it breaks some assumption elsewhere.
+ * Otherwise, move the matching table to the second
+ * position in the list so that traversals can benefit
+ * from commonality in backtrace paths.
+ */
+ if (prev && prev != unw.tables) {
+ /* unw is safe - we're already spinlocked */
+ prev->next = table->next;
+ table->next = unw.tables->next;
+ unw.tables->next = table;
+ }
e = lookup(table, ip - table->segment_base);
break;
}
+ prev = table;
}
if (!e) {
/* no info, return default unwinder (leaf proc, no mem stack, no saved regs) */
diff --git a/arch/ia64/sn/kernel/msi_sn.c b/arch/ia64/sn/kernel/msi_sn.c
index 0c72dd463831..a5e500f02853 100644
--- a/arch/ia64/sn/kernel/msi_sn.c
+++ b/arch/ia64/sn/kernel/msi_sn.c
@@ -228,8 +228,8 @@ static int sn_msi_retrigger_irq(unsigned int irq)
static struct irq_chip sn_msi_chip = {
.name = "PCI-MSI",
- .mask = mask_msi_irq,
- .unmask = unmask_msi_irq,
+ .irq_mask = mask_msi_irq,
+ .irq_unmask = unmask_msi_irq,
.ack = sn_ack_msi_irq,
#ifdef CONFIG_SMP
.set_affinity = sn_set_msi_irq_affinity,
diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
index fa1eceed0d23..30862c0358cd 100644
--- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c
+++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
@@ -860,6 +860,7 @@ error:
static const struct file_operations sn_hwperf_fops = {
.unlocked_ioctl = sn_hwperf_ioctl,
+ .llseek = noop_llseek,
};
static struct miscdevice sn_hwperf_dev = {
diff --git a/arch/ia64/xen/xen_pv_ops.c b/arch/ia64/xen/xen_pv_ops.c
index 8adc6a14272a..3e8d350fdf39 100644
--- a/arch/ia64/xen/xen_pv_ops.c
+++ b/arch/ia64/xen/xen_pv_ops.c
@@ -1136,7 +1136,6 @@ __initconst = {
static void __init
xen_patch_branch(unsigned long tag, unsigned long type)
{
- const unsigned long nelem =
- sizeof(xen_branch_target) / sizeof(xen_branch_target[0]);
- __paravirt_patch_apply_branch(tag, type, xen_branch_target, nelem);
+ __paravirt_patch_apply_branch(tag, type, xen_branch_target,
+ ARRAY_SIZE(xen_branch_target));
}
diff --git a/arch/m32r/include/asm/elf.h b/arch/m32r/include/asm/elf.h
index 2f85412ef730..b8da7d0574d2 100644
--- a/arch/m32r/include/asm/elf.h
+++ b/arch/m32r/include/asm/elf.h
@@ -82,9 +82,9 @@ typedef elf_fpreg_t elf_fpregset_t;
* These are used to set parameters in the core dumps.
*/
#define ELF_CLASS ELFCLASS32
-#if defined(__LITTLE_ENDIAN)
+#if defined(__LITTLE_ENDIAN__)
#define ELF_DATA ELFDATA2LSB
-#elif defined(__BIG_ENDIAN)
+#elif defined(__BIG_ENDIAN__)
#define ELF_DATA ELFDATA2MSB
#else
#error no endian defined
diff --git a/arch/m32r/include/asm/ioctls.h b/arch/m32r/include/asm/ioctls.h
index 66288063a4c0..349bf87bfbd0 100644
--- a/arch/m32r/include/asm/ioctls.h
+++ b/arch/m32r/include/asm/ioctls.h
@@ -1,87 +1,6 @@
#ifndef __ARCH_M32R_IOCTLS_H__
#define __ARCH_M32R_IOCTLS_H__
-#include <asm/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS 0x5401
-#define TCSETS 0x5402 /* Clashes with SNDCTL_TMR_START sound ioctl */
-#define TCSETSW 0x5403
-#define TCSETSF 0x5404
-#define TCGETA 0x5405
-#define TCSETA 0x5406
-#define TCSETAW 0x5407
-#define TCSETAF 0x5408
-#define TCSBRK 0x5409
-#define TCXONC 0x540A
-#define TCFLSH 0x540B
-#define TIOCEXCL 0x540C
-#define TIOCNXCL 0x540D
-#define TIOCSCTTY 0x540E
-#define TIOCGPGRP 0x540F
-#define TIOCSPGRP 0x5410
-#define TIOCOUTQ 0x5411
-#define TIOCSTI 0x5412
-#define TIOCGWINSZ 0x5413
-#define TIOCSWINSZ 0x5414
-#define TIOCMGET 0x5415
-#define TIOCMBIS 0x5416
-#define TIOCMBIC 0x5417
-#define TIOCMSET 0x5418
-#define TIOCGSOFTCAR 0x5419
-#define TIOCSSOFTCAR 0x541A
-#define FIONREAD 0x541B
-#define TIOCINQ FIONREAD
-#define TIOCLINUX 0x541C
-#define TIOCCONS 0x541D
-#define TIOCGSERIAL 0x541E
-#define TIOCSSERIAL 0x541F
-#define TIOCPKT 0x5420
-#define FIONBIO 0x5421
-#define TIOCNOTTY 0x5422
-#define TIOCSETD 0x5423
-#define TIOCGETD 0x5424
-#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
-/* #define TIOCTTYGSTRUCT 0x5426 - Former debugging-only ioctl */
-#define TIOCSBRK 0x5427 /* BSD compatibility */
-#define TIOCCBRK 0x5428 /* BSD compatibility */
-#define TIOCGSID 0x5429 /* Return the session ID of FD */
-#define TCGETS2 _IOR('T',0x2A, struct termios2)
-#define TCSETS2 _IOW('T',0x2B, struct termios2)
-#define TCSETSW2 _IOW('T',0x2C, struct termios2)
-#define TCSETSF2 _IOW('T',0x2D, struct termios2)
-#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
-#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
-#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */
-
-#define FIONCLEX 0x5450
-#define FIOCLEX 0x5451
-#define FIOASYNC 0x5452
-#define TIOCSERCONFIG 0x5453
-#define TIOCSERGWILD 0x5454
-#define TIOCSERSWILD 0x5455
-#define TIOCGLCKTRMIOS 0x5456
-#define TIOCSLCKTRMIOS 0x5457
-#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
-#define TIOCSERGETLSR 0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
-#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
-#define FIOQSIZE 0x5460
-
-/* Used for packet mode */
-#define TIOCPKT_DATA 0
-#define TIOCPKT_FLUSHREAD 1
-#define TIOCPKT_FLUSHWRITE 2
-#define TIOCPKT_STOP 4
-#define TIOCPKT_START 8
-#define TIOCPKT_NOSTOP 16
-#define TIOCPKT_DOSTOP 32
-#define TIOCPKT_IOCTL 64
-
-#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
+#include <asm-generic/ioctls.h>
#endif /* __ARCH_M32R_IOCTLS_H__ */
diff --git a/arch/m32r/include/asm/irqflags.h b/arch/m32r/include/asm/irqflags.h
new file mode 100644
index 000000000000..1f92d29982ae
--- /dev/null
+++ b/arch/m32r/include/asm/irqflags.h
@@ -0,0 +1,104 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 Hiroyuki Kondo, Hirokazu Takata, and Hitoshi Yamamoto
+ * Copyright (C) 2004, 2006 Hirokazu Takata <takata at linux-m32r.org>
+ */
+
+#ifndef _ASM_M32R_IRQFLAGS_H
+#define _ASM_M32R_IRQFLAGS_H
+
+#include <linux/types.h>
+
+static inline unsigned long arch_local_save_flags(void)
+{
+ unsigned long flags;
+ asm volatile("mvfc %0,psw" : "=r"(flags));
+ return flags;
+}
+
+static inline void arch_local_irq_disable(void)
+{
+#if !defined(CONFIG_CHIP_M32102) && !defined(CONFIG_CHIP_M32104)
+ asm volatile (
+ "clrpsw #0x40 -> nop"
+ : : : "memory");
+#else
+ unsigned long tmpreg0, tmpreg1;
+ asm volatile (
+ "ld24 %0, #0 ; Use 32-bit insn. \n\t"
+ "mvfc %1, psw ; No interrupt can be accepted here. \n\t"
+ "mvtc %0, psw \n\t"
+ "and3 %0, %1, #0xffbf \n\t"
+ "mvtc %0, psw \n\t"
+ : "=&r" (tmpreg0), "=&r" (tmpreg1)
+ :
+ : "cbit", "memory");
+#endif
+}
+
+static inline void arch_local_irq_enable(void)
+{
+#if !defined(CONFIG_CHIP_M32102) && !defined(CONFIG_CHIP_M32104)
+ asm volatile (
+ "setpsw #0x40 -> nop"
+ : : : "memory");
+#else
+ unsigned long tmpreg;
+ asm volatile (
+ "mvfc %0, psw; \n\t"
+ "or3 %0, %0, #0x0040; \n\t"
+ "mvtc %0, psw; \n\t"
+ : "=&r" (tmpreg)
+ :
+ : "cbit", "memory");
+#endif
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+ unsigned long flags;
+
+#if !(defined(CONFIG_CHIP_M32102) || defined(CONFIG_CHIP_M32104))
+ asm volatile (
+ "mvfc %0, psw; \n\t"
+ "clrpsw #0x40 -> nop; \n\t"
+ : "=r" (flags)
+ :
+ : "memory");
+#else
+ unsigned long tmpreg;
+ asm volatile (
+ "ld24 %1, #0 \n\t"
+ "mvfc %0, psw \n\t"
+ "mvtc %1, psw \n\t"
+ "and3 %1, %0, #0xffbf \n\t"
+ "mvtc %1, psw \n\t"
+ : "=r" (flags), "=&r" (tmpreg)
+ :
+ : "cbit", "memory");
+#endif
+ return flags;
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+ asm volatile("mvtc %0,psw"
+ :
+ : "r" (flags)
+ : "cbit", "memory");
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+ return !(flags & 0x40);
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+ return arch_irqs_disabled_flags(arch_local_save_flags());
+}
+
+#endif /* _ASM_M32R_IRQFLAGS_H */
diff --git a/arch/m32r/include/asm/system.h b/arch/m32r/include/asm/system.h
index c980f5ba8de7..13c46794ccb1 100644
--- a/arch/m32r/include/asm/system.h
+++ b/arch/m32r/include/asm/system.h
@@ -11,6 +11,7 @@
*/
#include <linux/compiler.h>
+#include <linux/irqflags.h>
#include <asm/assembler.h>
#ifdef __KERNEL__
@@ -54,71 +55,6 @@
); \
} while(0)
-/* Interrupt Control */
-#if !defined(CONFIG_CHIP_M32102) && !defined(CONFIG_CHIP_M32104)
-#define local_irq_enable() \
- __asm__ __volatile__ ("setpsw #0x40 -> nop": : :"memory")
-#define local_irq_disable() \
- __asm__ __volatile__ ("clrpsw #0x40 -> nop": : :"memory")
-#else /* CONFIG_CHIP_M32102 || CONFIG_CHIP_M32104 */
-static inline void local_irq_enable(void)
-{
- unsigned long tmpreg;
- __asm__ __volatile__(
- "mvfc %0, psw; \n\t"
- "or3 %0, %0, #0x0040; \n\t"
- "mvtc %0, psw; \n\t"
- : "=&r" (tmpreg) : : "cbit", "memory");
-}
-
-static inline void local_irq_disable(void)
-{
- unsigned long tmpreg0, tmpreg1;
- __asm__ __volatile__(
- "ld24 %0, #0 ; Use 32-bit insn. \n\t"
- "mvfc %1, psw ; No interrupt can be accepted here. \n\t"
- "mvtc %0, psw \n\t"
- "and3 %0, %1, #0xffbf \n\t"
- "mvtc %0, psw \n\t"
- : "=&r" (tmpreg0), "=&r" (tmpreg1) : : "cbit", "memory");
-}
-#endif /* CONFIG_CHIP_M32102 || CONFIG_CHIP_M32104 */
-
-#define local_save_flags(x) \
- __asm__ __volatile__("mvfc %0,psw" : "=r"(x) : /* no input */)
-
-#define local_irq_restore(x) \
- __asm__ __volatile__("mvtc %0,psw" : /* no outputs */ \
- : "r" (x) : "cbit", "memory")
-
-#if !(defined(CONFIG_CHIP_M32102) || defined(CONFIG_CHIP_M32104))
-#define local_irq_save(x) \
- __asm__ __volatile__( \
- "mvfc %0, psw; \n\t" \
- "clrpsw #0x40 -> nop; \n\t" \
- : "=r" (x) : /* no input */ : "memory")
-#else /* CONFIG_CHIP_M32102 || CONFIG_CHIP_M32104 */
-#define local_irq_save(x) \
- ({ \
- unsigned long tmpreg; \
- __asm__ __volatile__( \
- "ld24 %1, #0 \n\t" \
- "mvfc %0, psw \n\t" \
- "mvtc %1, psw \n\t" \
- "and3 %1, %0, #0xffbf \n\t" \
- "mvtc %1, psw \n\t" \
- : "=r" (x), "=&r" (tmpreg) \
- : : "cbit", "memory"); \
- })
-#endif /* CONFIG_CHIP_M32102 || CONFIG_CHIP_M32104 */
-
-#define irqs_disabled() \
- ({ \
- unsigned long flags; \
- local_save_flags(flags); \
- !(flags & 0x40); \
- })
-
#define nop() __asm__ __volatile__ ("nop" : : )
#define xchg(ptr, x) \
diff --git a/arch/m32r/kernel/.gitignore b/arch/m32r/kernel/.gitignore
new file mode 100644
index 000000000000..c5f676c3c224
--- /dev/null
+++ b/arch/m32r/kernel/.gitignore
@@ -0,0 +1 @@
+vmlinux.lds
diff --git a/arch/m32r/kernel/irq.c b/arch/m32r/kernel/irq.c
index 3c71f776872c..7db26f1f082d 100644
--- a/arch/m32r/kernel/irq.c
+++ b/arch/m32r/kernel/irq.c
@@ -51,7 +51,7 @@ int show_interrupts(struct seq_file *p, void *v)
for_each_online_cpu(j)
seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
#endif
- seq_printf(p, " %14s", irq_desc[i].chip->typename);
+ seq_printf(p, " %14s", irq_desc[i].chip->name);
seq_printf(p, " %s", action->name);
for (action=action->next; action; action = action->next)
diff --git a/arch/m32r/kernel/signal.c b/arch/m32r/kernel/signal.c
index 7bbe38645ed5..a08697f0886d 100644
--- a/arch/m32r/kernel/signal.c
+++ b/arch/m32r/kernel/signal.c
@@ -28,6 +28,8 @@
#define DEBUG_SIG 0
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
asmlinkage int
sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
unsigned long r2, unsigned long r3, unsigned long r4,
@@ -254,7 +256,7 @@ give_sigsegv:
static int prev_insn(struct pt_regs *regs)
{
u16 inst;
- if (get_user(&inst, (u16 __user *)(regs->bpc - 2)))
+ if (get_user(inst, (u16 __user *)(regs->bpc - 2)))
return -EFAULT;
if ((inst & 0xfff0) == 0x10f0) /* trap ? */
regs->bpc -= 2;
diff --git a/arch/m32r/platforms/m32104ut/setup.c b/arch/m32r/platforms/m32104ut/setup.c
index 922fdfdadeaa..402a59d7219b 100644
--- a/arch/m32r/platforms/m32104ut/setup.c
+++ b/arch/m32r/platforms/m32104ut/setup.c
@@ -65,7 +65,7 @@ static void shutdown_m32104ut_irq(unsigned int irq)
static struct irq_chip m32104ut_irq_type =
{
- .typename = "M32104UT-IRQ",
+ .name = "M32104UT-IRQ",
.startup = startup_m32104ut_irq,
.shutdown = shutdown_m32104ut_irq,
.enable = enable_m32104ut_irq,
diff --git a/arch/m32r/platforms/m32700ut/setup.c b/arch/m32r/platforms/m32700ut/setup.c
index 9c1bc7487c1e..80b1a026795a 100644
--- a/arch/m32r/platforms/m32700ut/setup.c
+++ b/arch/m32r/platforms/m32700ut/setup.c
@@ -71,7 +71,7 @@ static void shutdown_m32700ut_irq(unsigned int irq)
static struct irq_chip m32700ut_irq_type =
{
- .typename = "M32700UT-IRQ",
+ .name = "M32700UT-IRQ",
.startup = startup_m32700ut_irq,
.shutdown = shutdown_m32700ut_irq,
.enable = enable_m32700ut_irq,
@@ -148,7 +148,7 @@ static void shutdown_m32700ut_pld_irq(unsigned int irq)
static struct irq_chip m32700ut_pld_irq_type =
{
- .typename = "M32700UT-PLD-IRQ",
+ .name = "M32700UT-PLD-IRQ",
.startup = startup_m32700ut_pld_irq,
.shutdown = shutdown_m32700ut_pld_irq,
.enable = enable_m32700ut_pld_irq,
@@ -217,7 +217,7 @@ static void shutdown_m32700ut_lanpld_irq(unsigned int irq)
static struct irq_chip m32700ut_lanpld_irq_type =
{
- .typename = "M32700UT-PLD-LAN-IRQ",
+ .name = "M32700UT-PLD-LAN-IRQ",
.startup = startup_m32700ut_lanpld_irq,
.shutdown = shutdown_m32700ut_lanpld_irq,
.enable = enable_m32700ut_lanpld_irq,
@@ -286,7 +286,7 @@ static void shutdown_m32700ut_lcdpld_irq(unsigned int irq)
static struct irq_chip m32700ut_lcdpld_irq_type =
{
- .typename = "M32700UT-PLD-LCD-IRQ",
+ .name = "M32700UT-PLD-LCD-IRQ",
.startup = startup_m32700ut_lcdpld_irq,
.shutdown = shutdown_m32700ut_lcdpld_irq,
.enable = enable_m32700ut_lcdpld_irq,
diff --git a/arch/m32r/platforms/mappi/setup.c b/arch/m32r/platforms/mappi/setup.c
index fb4b17799b66..ea00c84d6b1b 100644
--- a/arch/m32r/platforms/mappi/setup.c
+++ b/arch/m32r/platforms/mappi/setup.c
@@ -65,7 +65,7 @@ static void shutdown_mappi_irq(unsigned int irq)
static struct irq_chip mappi_irq_type =
{
- .typename = "MAPPI-IRQ",
+ .name = "MAPPI-IRQ",
.startup = startup_mappi_irq,
.shutdown = shutdown_mappi_irq,
.enable = enable_mappi_irq,
diff --git a/arch/m32r/platforms/mappi2/setup.c b/arch/m32r/platforms/mappi2/setup.c
index 6a65eda0a056..c049376d0270 100644
--- a/arch/m32r/platforms/mappi2/setup.c
+++ b/arch/m32r/platforms/mappi2/setup.c
@@ -72,7 +72,7 @@ static void shutdown_mappi2_irq(unsigned int irq)
static struct irq_chip mappi2_irq_type =
{
- .typename = "MAPPI2-IRQ",
+ .name = "MAPPI2-IRQ",
.startup = startup_mappi2_irq,
.shutdown = shutdown_mappi2_irq,
.enable = enable_mappi2_irq,
diff --git a/arch/m32r/platforms/mappi3/setup.c b/arch/m32r/platforms/mappi3/setup.c
index 9c337aeac94b..882de25c6e8c 100644
--- a/arch/m32r/platforms/mappi3/setup.c
+++ b/arch/m32r/platforms/mappi3/setup.c
@@ -72,7 +72,7 @@ static void shutdown_mappi3_irq(unsigned int irq)
static struct irq_chip mappi3_irq_type =
{
- .typename = "MAPPI3-IRQ",
+ .name = "MAPPI3-IRQ",
.startup = startup_mappi3_irq,
.shutdown = shutdown_mappi3_irq,
.enable = enable_mappi3_irq,
diff --git a/arch/m32r/platforms/oaks32r/setup.c b/arch/m32r/platforms/oaks32r/setup.c
index ed865741c38d..d11d93bf74f5 100644
--- a/arch/m32r/platforms/oaks32r/setup.c
+++ b/arch/m32r/platforms/oaks32r/setup.c
@@ -63,7 +63,7 @@ static void shutdown_oaks32r_irq(unsigned int irq)
static struct irq_chip oaks32r_irq_type =
{
- .typename = "OAKS32R-IRQ",
+ .name = "OAKS32R-IRQ",
.startup = startup_oaks32r_irq,
.shutdown = shutdown_oaks32r_irq,
.enable = enable_oaks32r_irq,
diff --git a/arch/m32r/platforms/opsput/setup.c b/arch/m32r/platforms/opsput/setup.c
index 80d680657019..5f3402a2fbaf 100644
--- a/arch/m32r/platforms/opsput/setup.c
+++ b/arch/m32r/platforms/opsput/setup.c
@@ -72,7 +72,7 @@ static void shutdown_opsput_irq(unsigned int irq)
static struct irq_chip opsput_irq_type =
{
- .typename = "OPSPUT-IRQ",
+ .name = "OPSPUT-IRQ",
.startup = startup_opsput_irq,
.shutdown = shutdown_opsput_irq,
.enable = enable_opsput_irq,
@@ -149,7 +149,7 @@ static void shutdown_opsput_pld_irq(unsigned int irq)
static struct irq_chip opsput_pld_irq_type =
{
- .typename = "OPSPUT-PLD-IRQ",
+ .name = "OPSPUT-PLD-IRQ",
.startup = startup_opsput_pld_irq,
.shutdown = shutdown_opsput_pld_irq,
.enable = enable_opsput_pld_irq,
@@ -218,7 +218,7 @@ static void shutdown_opsput_lanpld_irq(unsigned int irq)
static struct irq_chip opsput_lanpld_irq_type =
{
- .typename = "OPSPUT-PLD-LAN-IRQ",
+ .name = "OPSPUT-PLD-LAN-IRQ",
.startup = startup_opsput_lanpld_irq,
.shutdown = shutdown_opsput_lanpld_irq,
.enable = enable_opsput_lanpld_irq,
diff --git a/arch/m32r/platforms/usrv/setup.c b/arch/m32r/platforms/usrv/setup.c
index 757302660af8..1beac7a51ed4 100644
--- a/arch/m32r/platforms/usrv/setup.c
+++ b/arch/m32r/platforms/usrv/setup.c
@@ -63,7 +63,7 @@ static void shutdown_mappi_irq(unsigned int irq)
static struct irq_chip mappi_irq_type =
{
- .typename = "M32700-IRQ",
+ .name = "M32700-IRQ",
.startup = startup_mappi_irq,
.shutdown = shutdown_mappi_irq,
.enable = enable_mappi_irq,
@@ -136,7 +136,7 @@ static void shutdown_m32700ut_pld_irq(unsigned int irq)
static struct irq_chip m32700ut_pld_irq_type =
{
- .typename = "USRV-PLD-IRQ",
+ .name = "USRV-PLD-IRQ",
.startup = startup_m32700ut_pld_irq,
.shutdown = shutdown_m32700ut_pld_irq,
.enable = enable_m32700ut_pld_irq,
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index 8030e2481d97..77bb0d6baa62 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -434,7 +434,7 @@ config PROC_HARDWARE
config ISA
bool
- depends on Q40 || AMIGA_PCMCIA || GG2
+ depends on Q40 || AMIGA_PCMCIA
default y
help
Find out whether you have ISA slots on your motherboard. ISA is the
@@ -445,7 +445,7 @@ config ISA
config GENERIC_ISA_DMA
bool
- depends on Q40 || AMIGA_PCMCIA || GG2
+ depends on Q40 || AMIGA_PCMCIA
default y
config ZONE_DMA
diff --git a/arch/m68k/bvme6000/rtc.c b/arch/m68k/bvme6000/rtc.c
index cb8617bb194b..1c4d4c7bf4d4 100644
--- a/arch/m68k/bvme6000/rtc.c
+++ b/arch/m68k/bvme6000/rtc.c
@@ -155,6 +155,7 @@ static const struct file_operations rtc_fops = {
.unlocked_ioctl = rtc_ioctl,
.open = rtc_open,
.release = rtc_release,
+ .llseek = noop_llseek,
};
static struct miscdevice rtc_dev = {
diff --git a/arch/m68k/include/asm/amigahw.h b/arch/m68k/include/asm/amigahw.h
index 5ca5dd951a4a..7a19b5686a4a 100644
--- a/arch/m68k/include/asm/amigahw.h
+++ b/arch/m68k/include/asm/amigahw.h
@@ -102,7 +102,6 @@ struct amiga_hw_present {
AMIGAHW_DECLARE(ALICE_NTSC); /* NTSC Alice (8374) */
AMIGAHW_DECLARE(MAGIC_REKICK); /* A3000 Magic Hard Rekick */
AMIGAHW_DECLARE(PCMCIA); /* PCMCIA Slot */
- AMIGAHW_DECLARE(GG2_ISA); /* GG2 Zorro2ISA Bridge */
AMIGAHW_DECLARE(ZORRO); /* Zorro AutoConfig */
AMIGAHW_DECLARE(ZORRO3); /* Zorro III */
};
diff --git a/arch/m68k/include/asm/atomic.h b/arch/m68k/include/asm/atomic.h
index eab36dcacf6c..03ae3d14cd4a 100644
--- a/arch/m68k/include/asm/atomic.h
+++ b/arch/m68k/include/asm/atomic.h
@@ -1,7 +1,211 @@
-#ifdef __uClinux__
-#include "atomic_no.h"
+#ifndef __ARCH_M68K_ATOMIC__
+#define __ARCH_M68K_ATOMIC__
+
+#include <linux/types.h>
+#include <asm/system.h>
+
+/*
+ * Atomic operations that C can't guarantee us. Useful for
+ * resource counting etc..
+ */
+
+/*
+ * We do not have SMP m68k systems, so we don't have to deal with that.
+ */
+
+#define ATOMIC_INIT(i) { (i) }
+
+#define atomic_read(v) (*(volatile int *)&(v)->counter)
+#define atomic_set(v, i) (((v)->counter) = i)
+
+/*
+ * The ColdFire parts cannot do some immediate to memory operations,
+ * so for them we do not specify the "i" asm constraint.
+ */
+#ifdef CONFIG_COLDFIRE
+#define ASM_DI "d"
#else
-#include "atomic_mm.h"
+#define ASM_DI "di"
#endif
+static inline void atomic_add(int i, atomic_t *v)
+{
+ __asm__ __volatile__("addl %1,%0" : "+m" (*v) : ASM_DI (i));
+}
+
+static inline void atomic_sub(int i, atomic_t *v)
+{
+ __asm__ __volatile__("subl %1,%0" : "+m" (*v) : ASM_DI (i));
+}
+
+static inline void atomic_inc(atomic_t *v)
+{
+ __asm__ __volatile__("addql #1,%0" : "+m" (*v));
+}
+
+static inline void atomic_dec(atomic_t *v)
+{
+ __asm__ __volatile__("subql #1,%0" : "+m" (*v));
+}
+
+static inline int atomic_dec_and_test(atomic_t *v)
+{
+ char c;
+ __asm__ __volatile__("subql #1,%1; seq %0" : "=d" (c), "+m" (*v));
+ return c != 0;
+}
+
+static inline int atomic_inc_and_test(atomic_t *v)
+{
+ char c;
+ __asm__ __volatile__("addql #1,%1; seq %0" : "=d" (c), "+m" (*v));
+ return c != 0;
+}
+
+#ifdef CONFIG_RMW_INSNS
+
+static inline int atomic_add_return(int i, atomic_t *v)
+{
+ int t, tmp;
+
+ __asm__ __volatile__(
+ "1: movel %2,%1\n"
+ " addl %3,%1\n"
+ " casl %2,%1,%0\n"
+ " jne 1b"
+ : "+m" (*v), "=&d" (t), "=&d" (tmp)
+ : "g" (i), "2" (atomic_read(v)));
+ return t;
+}
+
+static inline int atomic_sub_return(int i, atomic_t *v)
+{
+ int t, tmp;
+
+ __asm__ __volatile__(
+ "1: movel %2,%1\n"
+ " subl %3,%1\n"
+ " casl %2,%1,%0\n"
+ " jne 1b"
+ : "+m" (*v), "=&d" (t), "=&d" (tmp)
+ : "g" (i), "2" (atomic_read(v)));
+ return t;
+}
+
+#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
+#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
+
+#else /* !CONFIG_RMW_INSNS */
+
+static inline int atomic_add_return(int i, atomic_t * v)
+{
+ unsigned long flags;
+ int t;
+
+ local_irq_save(flags);
+ t = atomic_read(v);
+ t += i;
+ atomic_set(v, t);
+ local_irq_restore(flags);
+
+ return t;
+}
+
+static inline int atomic_sub_return(int i, atomic_t * v)
+{
+ unsigned long flags;
+ int t;
+
+ local_irq_save(flags);
+ t = atomic_read(v);
+ t -= i;
+ atomic_set(v, t);
+ local_irq_restore(flags);
+
+ return t;
+}
+
+static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
+{
+ unsigned long flags;
+ int prev;
+
+ local_irq_save(flags);
+ prev = atomic_read(v);
+ if (prev == old)
+ atomic_set(v, new);
+ local_irq_restore(flags);
+ return prev;
+}
+
+static inline int atomic_xchg(atomic_t *v, int new)
+{
+ unsigned long flags;
+ int prev;
+
+ local_irq_save(flags);
+ prev = atomic_read(v);
+ atomic_set(v, new);
+ local_irq_restore(flags);
+ return prev;
+}
+
+#endif /* !CONFIG_RMW_INSNS */
+
+#define atomic_dec_return(v) atomic_sub_return(1, (v))
+#define atomic_inc_return(v) atomic_add_return(1, (v))
+
+static inline int atomic_sub_and_test(int i, atomic_t *v)
+{
+ char c;
+ __asm__ __volatile__("subl %2,%1; seq %0"
+ : "=d" (c), "+m" (*v)
+ : ASM_DI (i));
+ return c != 0;
+}
+
+static inline int atomic_add_negative(int i, atomic_t *v)
+{
+ char c;
+ __asm__ __volatile__("addl %2,%1; smi %0"
+ : "=d" (c), "+m" (*v)
+ : "id" (i));
+ return c != 0;
+}
+
+static inline void atomic_clear_mask(unsigned long mask, unsigned long *v)
+{
+ __asm__ __volatile__("andl %1,%0" : "+m" (*v) : "id" (~(mask)));
+}
+
+static inline void atomic_set_mask(unsigned long mask, unsigned long *v)
+{
+ __asm__ __volatile__("orl %1,%0" : "+m" (*v) : "id" (mask));
+}
+
+static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+{
+ int c, old;
+ c = atomic_read(v);
+ for (;;) {
+ if (unlikely(c == (u)))
+ break;
+ old = atomic_cmpxchg((v), c, c + (a));
+ if (likely(old == c))
+ break;
+ c = old;
+ }
+ return c != (u);
+}
+
+#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
+
+/* Atomic operations are already serializing */
+#define smp_mb__before_atomic_dec() barrier()
+#define smp_mb__after_atomic_dec() barrier()
+#define smp_mb__before_atomic_inc() barrier()
+#define smp_mb__after_atomic_inc() barrier()
+
+#include <asm-generic/atomic-long.h>
#include <asm-generic/atomic64.h>
+#endif /* __ARCH_M68K_ATOMIC __ */
diff --git a/arch/m68k/include/asm/atomic_mm.h b/arch/m68k/include/asm/atomic_mm.h
deleted file mode 100644
index 6a223b3f7e74..000000000000
--- a/arch/m68k/include/asm/atomic_mm.h
+++ /dev/null
@@ -1,200 +0,0 @@
-#ifndef __ARCH_M68K_ATOMIC__
-#define __ARCH_M68K_ATOMIC__
-
-#include <linux/types.h>
-#include <asm/system.h>
-
-/*
- * Atomic operations that C can't guarantee us. Useful for
- * resource counting etc..
- */
-
-/*
- * We do not have SMP m68k systems, so we don't have to deal with that.
- */
-
-#define ATOMIC_INIT(i) { (i) }
-
-#define atomic_read(v) (*(volatile int *)&(v)->counter)
-#define atomic_set(v, i) (((v)->counter) = i)
-
-static inline void atomic_add(int i, atomic_t *v)
-{
- __asm__ __volatile__("addl %1,%0" : "+m" (*v) : "id" (i));
-}
-
-static inline void atomic_sub(int i, atomic_t *v)
-{
- __asm__ __volatile__("subl %1,%0" : "+m" (*v) : "id" (i));
-}
-
-static inline void atomic_inc(atomic_t *v)
-{
- __asm__ __volatile__("addql #1,%0" : "+m" (*v));
-}
-
-static inline void atomic_dec(atomic_t *v)
-{
- __asm__ __volatile__("subql #1,%0" : "+m" (*v));
-}
-
-static inline int atomic_dec_and_test(atomic_t *v)
-{
- char c;
- __asm__ __volatile__("subql #1,%1; seq %0" : "=d" (c), "+m" (*v));
- return c != 0;
-}
-
-static inline int atomic_inc_and_test(atomic_t *v)
-{
- char c;
- __asm__ __volatile__("addql #1,%1; seq %0" : "=d" (c), "+m" (*v));
- return c != 0;
-}
-
-#ifdef CONFIG_RMW_INSNS
-
-static inline int atomic_add_return(int i, atomic_t *v)
-{
- int t, tmp;
-
- __asm__ __volatile__(
- "1: movel %2,%1\n"
- " addl %3,%1\n"
- " casl %2,%1,%0\n"
- " jne 1b"
- : "+m" (*v), "=&d" (t), "=&d" (tmp)
- : "g" (i), "2" (atomic_read(v)));
- return t;
-}
-
-static inline int atomic_sub_return(int i, atomic_t *v)
-{
- int t, tmp;
-
- __asm__ __volatile__(
- "1: movel %2,%1\n"
- " subl %3,%1\n"
- " casl %2,%1,%0\n"
- " jne 1b"
- : "+m" (*v), "=&d" (t), "=&d" (tmp)
- : "g" (i), "2" (atomic_read(v)));
- return t;
-}
-
-#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
-#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
-
-#else /* !CONFIG_RMW_INSNS */
-
-static inline int atomic_add_return(int i, atomic_t * v)
-{
- unsigned long flags;
- int t;
-
- local_irq_save(flags);
- t = atomic_read(v);
- t += i;
- atomic_set(v, t);
- local_irq_restore(flags);
-
- return t;
-}
-
-static inline int atomic_sub_return(int i, atomic_t * v)
-{
- unsigned long flags;
- int t;
-
- local_irq_save(flags);
- t = atomic_read(v);
- t -= i;
- atomic_set(v, t);
- local_irq_restore(flags);
-
- return t;
-}
-
-static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
-{
- unsigned long flags;
- int prev;
-
- local_irq_save(flags);
- prev = atomic_read(v);
- if (prev == old)
- atomic_set(v, new);
- local_irq_restore(flags);
- return prev;
-}
-
-static inline int atomic_xchg(atomic_t *v, int new)
-{
- unsigned long flags;
- int prev;
-
- local_irq_save(flags);
- prev = atomic_read(v);
- atomic_set(v, new);
- local_irq_restore(flags);
- return prev;
-}
-
-#endif /* !CONFIG_RMW_INSNS */
-
-#define atomic_dec_return(v) atomic_sub_return(1, (v))
-#define atomic_inc_return(v) atomic_add_return(1, (v))
-
-static inline int atomic_sub_and_test(int i, atomic_t *v)
-{
- char c;
- __asm__ __volatile__("subl %2,%1; seq %0"
- : "=d" (c), "+m" (*v)
- : "id" (i));
- return c != 0;
-}
-
-static inline int atomic_add_negative(int i, atomic_t *v)
-{
- char c;
- __asm__ __volatile__("addl %2,%1; smi %0"
- : "=d" (c), "+m" (*v)
- : "id" (i));
- return c != 0;
-}
-
-static inline void atomic_clear_mask(unsigned long mask, unsigned long *v)
-{
- __asm__ __volatile__("andl %1,%0" : "+m" (*v) : "id" (~(mask)));
-}
-
-static inline void atomic_set_mask(unsigned long mask, unsigned long *v)
-{
- __asm__ __volatile__("orl %1,%0" : "+m" (*v) : "id" (mask));
-}
-
-static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
-{
- int c, old;
- c = atomic_read(v);
- for (;;) {
- if (unlikely(c == (u)))
- break;
- old = atomic_cmpxchg((v), c, c + (a));
- if (likely(old == c))
- break;
- c = old;
- }
- return c != (u);
-}
-
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
-
-/* Atomic operations are already serializing */
-#define smp_mb__before_atomic_dec() barrier()
-#define smp_mb__after_atomic_dec() barrier()
-#define smp_mb__before_atomic_inc() barrier()
-#define smp_mb__after_atomic_inc() barrier()
-
-#include <asm-generic/atomic-long.h>
-#endif /* __ARCH_M68K_ATOMIC __ */
diff --git a/arch/m68k/include/asm/atomic_no.h b/arch/m68k/include/asm/atomic_no.h
deleted file mode 100644
index 289310c63a8a..000000000000
--- a/arch/m68k/include/asm/atomic_no.h
+++ /dev/null
@@ -1,155 +0,0 @@
-#ifndef __ARCH_M68KNOMMU_ATOMIC__
-#define __ARCH_M68KNOMMU_ATOMIC__
-
-#include <linux/types.h>
-#include <asm/system.h>
-
-/*
- * Atomic operations that C can't guarantee us. Useful for
- * resource counting etc..
- */
-
-/*
- * We do not have SMP m68k systems, so we don't have to deal with that.
- */
-
-#define ATOMIC_INIT(i) { (i) }
-
-#define atomic_read(v) (*(volatile int *)&(v)->counter)
-#define atomic_set(v, i) (((v)->counter) = i)
-
-static __inline__ void atomic_add(int i, atomic_t *v)
-{
-#ifdef CONFIG_COLDFIRE
- __asm__ __volatile__("addl %1,%0" : "+m" (*v) : "d" (i));
-#else
- __asm__ __volatile__("addl %1,%0" : "+m" (*v) : "di" (i));
-#endif
-}
-
-static __inline__ void atomic_sub(int i, atomic_t *v)
-{
-#ifdef CONFIG_COLDFIRE
- __asm__ __volatile__("subl %1,%0" : "+m" (*v) : "d" (i));
-#else
- __asm__ __volatile__("subl %1,%0" : "+m" (*v) : "di" (i));
-#endif
-}
-
-static __inline__ int atomic_sub_and_test(int i, atomic_t * v)
-{
- char c;
-#ifdef CONFIG_COLDFIRE
- __asm__ __volatile__("subl %2,%1; seq %0"
- : "=d" (c), "+m" (*v)
- : "d" (i));
-#else
- __asm__ __volatile__("subl %2,%1; seq %0"
- : "=d" (c), "+m" (*v)
- : "di" (i));
-#endif
- return c != 0;
-}
-
-static __inline__ void atomic_inc(volatile atomic_t *v)
-{
- __asm__ __volatile__("addql #1,%0" : "+m" (*v));
-}
-
-/*
- * atomic_inc_and_test - increment and test
- * @v: pointer of type atomic_t
- *
- * Atomically increments @v by 1
- * and returns true if the result is zero, or false for all
- * other cases.
- */
-
-static __inline__ int atomic_inc_and_test(volatile atomic_t *v)
-{
- char c;
- __asm__ __volatile__("addql #1,%1; seq %0" : "=d" (c), "+m" (*v));
- return c != 0;
-}
-
-static __inline__ void atomic_dec(volatile atomic_t *v)
-{
- __asm__ __volatile__("subql #1,%0" : "+m" (*v));
-}
-
-static __inline__ int atomic_dec_and_test(volatile atomic_t *v)
-{
- char c;
- __asm__ __volatile__("subql #1,%1; seq %0" : "=d" (c), "+m" (*v));
- return c != 0;
-}
-
-static __inline__ void atomic_clear_mask(unsigned long mask, unsigned long *v)
-{
- __asm__ __volatile__("andl %1,%0" : "+m" (*v) : "id" (~(mask)));
-}
-
-static __inline__ void atomic_set_mask(unsigned long mask, unsigned long *v)
-{
- __asm__ __volatile__("orl %1,%0" : "+m" (*v) : "id" (mask));
-}
-
-/* Atomic operations are already serializing */
-#define smp_mb__before_atomic_dec() barrier()
-#define smp_mb__after_atomic_dec() barrier()
-#define smp_mb__before_atomic_inc() barrier()
-#define smp_mb__after_atomic_inc() barrier()
-
-static inline int atomic_add_return(int i, atomic_t * v)
-{
- unsigned long temp, flags;
-
- local_irq_save(flags);
- temp = *(long *)v;
- temp += i;
- *(long *)v = temp;
- local_irq_restore(flags);
-
- return temp;
-}
-
-#define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0)
-
-static inline int atomic_sub_return(int i, atomic_t * v)
-{
- unsigned long temp, flags;
-
- local_irq_save(flags);
- temp = *(long *)v;
- temp -= i;
- *(long *)v = temp;
- local_irq_restore(flags);
-
- return temp;
-}
-
-#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
-#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
-
-static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
-{
- int c, old;
- c = atomic_read(v);
- for (;;) {
- if (unlikely(c == (u)))
- break;
- old = atomic_cmpxchg((v), c, c + (a));
- if (likely(old == c))
- break;
- c = old;
- }
- return c != (u);
-}
-
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
-
-#define atomic_dec_return(v) atomic_sub_return(1,(v))
-#define atomic_inc_return(v) atomic_add_return(1,(v))
-
-#include <asm-generic/atomic-long.h>
-#endif /* __ARCH_M68KNOMMU_ATOMIC __ */
diff --git a/arch/m68k/include/asm/entry_mm.h b/arch/m68k/include/asm/entry_mm.h
index 474125886218..e41fea399bfe 100644
--- a/arch/m68k/include/asm/entry_mm.h
+++ b/arch/m68k/include/asm/entry_mm.h
@@ -3,6 +3,9 @@
#include <asm/setup.h>
#include <asm/page.h>
+#ifdef __ASSEMBLY__
+#include <asm/thread_info.h>
+#endif
/*
* Stack layout in 'ret_from_exception':
diff --git a/arch/m68k/include/asm/entry_no.h b/arch/m68k/include/asm/entry_no.h
index 907ed03d792f..80e41492aa2a 100644
--- a/arch/m68k/include/asm/entry_no.h
+++ b/arch/m68k/include/asm/entry_no.h
@@ -28,7 +28,7 @@
* M68K COLDFIRE
*/
-#define ALLOWINT 0xf8ff
+#define ALLOWINT (~0x700)
#ifdef __ASSEMBLY__
diff --git a/arch/m68k/include/asm/io_mm.h b/arch/m68k/include/asm/io_mm.h
index 9e673e3bd434..0fb3468000e7 100644
--- a/arch/m68k/include/asm/io_mm.h
+++ b/arch/m68k/include/asm/io_mm.h
@@ -49,23 +49,6 @@
#define MULTI_ISA 0
#endif /* Q40 */
-/* GG-II Zorro to ISA bridge */
-#ifdef CONFIG_GG2
-
-extern unsigned long gg2_isa_base;
-#define GG2_ISA_IO_B(ioaddr) (gg2_isa_base+1+((unsigned long)(ioaddr)*4))
-#define GG2_ISA_IO_W(ioaddr) (gg2_isa_base+ ((unsigned long)(ioaddr)*4))
-#define GG2_ISA_MEM_B(madr) (gg2_isa_base+1+(((unsigned long)(madr)*4) & 0xfffff))
-#define GG2_ISA_MEM_W(madr) (gg2_isa_base+ (((unsigned long)(madr)*4) & 0xfffff))
-
-#ifndef MULTI_ISA
-#define MULTI_ISA 0
-#else
-#undef MULTI_ISA
-#define MULTI_ISA 1
-#endif
-#endif /* GG2 */
-
#ifdef CONFIG_AMIGA_PCMCIA
#include <asm/amigayle.h>
@@ -89,8 +72,7 @@ extern unsigned long gg2_isa_base;
#endif
#define ISA_TYPE_Q40 (1)
-#define ISA_TYPE_GG2 (2)
-#define ISA_TYPE_AG (3)
+#define ISA_TYPE_AG (2)
#if defined(CONFIG_Q40) && !defined(MULTI_ISA)
#define ISA_TYPE ISA_TYPE_Q40
@@ -100,10 +82,6 @@ extern unsigned long gg2_isa_base;
#define ISA_TYPE ISA_TYPE_AG
#define ISA_SEX 1
#endif
-#if defined(CONFIG_GG2) && !defined(MULTI_ISA)
-#define ISA_TYPE ISA_TYPE_GG2
-#define ISA_SEX 0
-#endif
#ifdef MULTI_ISA
extern int isa_type;
@@ -125,9 +103,6 @@ static inline u8 __iomem *isa_itb(unsigned long addr)
#ifdef CONFIG_Q40
case ISA_TYPE_Q40: return (u8 __iomem *)Q40_ISA_IO_B(addr);
#endif
-#ifdef CONFIG_GG2
- case ISA_TYPE_GG2: return (u8 __iomem *)GG2_ISA_IO_B(addr);
-#endif
#ifdef CONFIG_AMIGA_PCMCIA
case ISA_TYPE_AG: return (u8 __iomem *)AG_ISA_IO_B(addr);
#endif
@@ -141,9 +116,6 @@ static inline u16 __iomem *isa_itw(unsigned long addr)
#ifdef CONFIG_Q40
case ISA_TYPE_Q40: return (u16 __iomem *)Q40_ISA_IO_W(addr);
#endif
-#ifdef CONFIG_GG2
- case ISA_TYPE_GG2: return (u16 __iomem *)GG2_ISA_IO_W(addr);
-#endif
#ifdef CONFIG_AMIGA_PCMCIA
case ISA_TYPE_AG: return (u16 __iomem *)AG_ISA_IO_W(addr);
#endif
@@ -167,9 +139,6 @@ static inline u8 __iomem *isa_mtb(unsigned long addr)
#ifdef CONFIG_Q40
case ISA_TYPE_Q40: return (u8 __iomem *)Q40_ISA_MEM_B(addr);
#endif
-#ifdef CONFIG_GG2
- case ISA_TYPE_GG2: return (u8 __iomem *)GG2_ISA_MEM_B(addr);
-#endif
#ifdef CONFIG_AMIGA_PCMCIA
case ISA_TYPE_AG: return (u8 __iomem *)addr;
#endif
@@ -183,9 +152,6 @@ static inline u16 __iomem *isa_mtw(unsigned long addr)
#ifdef CONFIG_Q40
case ISA_TYPE_Q40: return (u16 __iomem *)Q40_ISA_MEM_W(addr);
#endif
-#ifdef CONFIG_GG2
- case ISA_TYPE_GG2: return (u16 __iomem *)GG2_ISA_MEM_W(addr);
-#endif
#ifdef CONFIG_AMIGA_PCMCIA
case ISA_TYPE_AG: return (u16 __iomem *)addr;
#endif
@@ -217,9 +183,6 @@ static inline void isa_delay(void)
#ifdef CONFIG_Q40
case ISA_TYPE_Q40: isa_outb(0,0x80); break;
#endif
-#ifdef CONFIG_GG2
- case ISA_TYPE_GG2: break;
-#endif
#ifdef CONFIG_AMIGA_PCMCIA
case ISA_TYPE_AG: break;
#endif
@@ -287,9 +250,13 @@ static inline void isa_delay(void)
#define outb(val,port) ((void)0)
#define outb_p(val,port) ((void)0)
#define inw(port) 0xffff
+#define inw_p(port) 0xffff
#define outw(val,port) ((void)0)
+#define outw_p(val,port) ((void)0)
#define inl(port) 0xffffffffUL
+#define inl_p(port) 0xffffffffUL
#define outl(val,port) ((void)0)
+#define outl_p(val,port) ((void)0)
#define insb(port,buf,nr) ((void)0)
#define outsb(port,buf,nr) ((void)0)
diff --git a/arch/m68k/include/asm/ioctls.h b/arch/m68k/include/asm/ioctls.h
index 91a57d665460..1332bb4ca5b0 100644
--- a/arch/m68k/include/asm/ioctls.h
+++ b/arch/m68k/include/asm/ioctls.h
@@ -1,86 +1,8 @@
#ifndef __ARCH_M68K_IOCTLS_H__
#define __ARCH_M68K_IOCTLS_H__
-#include <asm/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS 0x5401
-#define TCSETS 0x5402
-#define TCSETSW 0x5403
-#define TCSETSF 0x5404
-#define TCGETA 0x5405
-#define TCSETA 0x5406
-#define TCSETAW 0x5407
-#define TCSETAF 0x5408
-#define TCSBRK 0x5409
-#define TCXONC 0x540A
-#define TCFLSH 0x540B
-#define TIOCEXCL 0x540C
-#define TIOCNXCL 0x540D
-#define TIOCSCTTY 0x540E
-#define TIOCGPGRP 0x540F
-#define TIOCSPGRP 0x5410
-#define TIOCOUTQ 0x5411
-#define TIOCSTI 0x5412
-#define TIOCGWINSZ 0x5413
-#define TIOCSWINSZ 0x5414
-#define TIOCMGET 0x5415
-#define TIOCMBIS 0x5416
-#define TIOCMBIC 0x5417
-#define TIOCMSET 0x5418
-#define TIOCGSOFTCAR 0x5419
-#define TIOCSSOFTCAR 0x541A
-#define FIONREAD 0x541B
-#define TIOCINQ FIONREAD
-#define TIOCLINUX 0x541C
-#define TIOCCONS 0x541D
-#define TIOCGSERIAL 0x541E
-#define TIOCSSERIAL 0x541F
-#define TIOCPKT 0x5420
-#define FIONBIO 0x5421
-#define TIOCNOTTY 0x5422
-#define TIOCSETD 0x5423
-#define TIOCGETD 0x5424
-#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
-#define TIOCSBRK 0x5427 /* BSD compatibility */
-#define TIOCCBRK 0x5428 /* BSD compatibility */
-#define TIOCGSID 0x5429 /* Return the session ID of FD */
-#define TCGETS2 _IOR('T',0x2A, struct termios2)
-#define TCSETS2 _IOW('T',0x2B, struct termios2)
-#define TCSETSW2 _IOW('T',0x2C, struct termios2)
-#define TCSETSF2 _IOW('T',0x2D, struct termios2)
-#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
-#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
-#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */
-
-#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */
-#define FIOCLEX 0x5451
-#define FIOASYNC 0x5452
-#define TIOCSERCONFIG 0x5453
-#define TIOCSERGWILD 0x5454
-#define TIOCSERSWILD 0x5455
-#define TIOCGLCKTRMIOS 0x5456
-#define TIOCSLCKTRMIOS 0x5457
-#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
-#define TIOCSERGETLSR 0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
-#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
#define FIOQSIZE 0x545E
-/* Used for packet mode */
-#define TIOCPKT_DATA 0
-#define TIOCPKT_FLUSHREAD 1
-#define TIOCPKT_FLUSHWRITE 2
-#define TIOCPKT_STOP 4
-#define TIOCPKT_START 8
-#define TIOCPKT_NOSTOP 16
-#define TIOCPKT_DOSTOP 32
-#define TIOCPKT_IOCTL 64
-
-#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
+#include <asm-generic/ioctls.h>
#endif /* __ARCH_M68K_IOCTLS_H__ */
diff --git a/arch/m68k/include/asm/irqflags.h b/arch/m68k/include/asm/irqflags.h
new file mode 100644
index 000000000000..4a5b284a1550
--- /dev/null
+++ b/arch/m68k/include/asm/irqflags.h
@@ -0,0 +1,76 @@
+#ifndef _M68K_IRQFLAGS_H
+#define _M68K_IRQFLAGS_H
+
+#include <linux/types.h>
+#include <linux/hardirq.h>
+#include <linux/preempt.h>
+#include <asm/thread_info.h>
+#include <asm/entry.h>
+
+static inline unsigned long arch_local_save_flags(void)
+{
+ unsigned long flags;
+ asm volatile ("movew %%sr,%0" : "=d" (flags) : : "memory");
+ return flags;
+}
+
+static inline void arch_local_irq_disable(void)
+{
+#ifdef CONFIG_COLDFIRE
+ asm volatile (
+ "move %/sr,%%d0 \n\t"
+ "ori.l #0x0700,%%d0 \n\t"
+ "move %%d0,%/sr \n"
+ : /* no outputs */
+ :
+ : "cc", "%d0", "memory");
+#else
+ asm volatile ("oriw #0x0700,%%sr" : : : "memory");
+#endif
+}
+
+static inline void arch_local_irq_enable(void)
+{
+#if defined(CONFIG_COLDFIRE)
+ asm volatile (
+ "move %/sr,%%d0 \n\t"
+ "andi.l #0xf8ff,%%d0 \n\t"
+ "move %%d0,%/sr \n"
+ : /* no outputs */
+ :
+ : "cc", "%d0", "memory");
+#else
+# if defined(CONFIG_MMU)
+ if (MACH_IS_Q40 || !hardirq_count())
+# endif
+ asm volatile (
+ "andiw %0,%%sr"
+ :
+ : "i" (ALLOWINT)
+ : "memory");
+#endif
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+ unsigned long flags = arch_local_save_flags();
+ arch_local_irq_disable();
+ return flags;
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+ asm volatile ("movew %0,%%sr" : : "d" (flags) : "memory");
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+ return (flags & ~ALLOWINT) != 0;
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+ return arch_irqs_disabled_flags(arch_local_save_flags());
+}
+
+#endif /* _M68K_IRQFLAGS_H */
diff --git a/arch/m68k/include/asm/machdep.h b/arch/m68k/include/asm/machdep.h
index fc24b6fc5508..789f3b2de0e9 100644
--- a/arch/m68k/include/asm/machdep.h
+++ b/arch/m68k/include/asm/machdep.h
@@ -1,5 +1,44 @@
-#ifdef __uClinux__
-#include "machdep_no.h"
-#else
-#include "machdep_mm.h"
-#endif
+#ifndef _M68K_MACHDEP_H
+#define _M68K_MACHDEP_H
+
+#include <linux/seq_file.h>
+#include <linux/interrupt.h>
+
+struct pt_regs;
+struct mktime;
+struct rtc_time;
+struct rtc_pll_info;
+struct buffer_head;
+
+extern void (*mach_sched_init) (irq_handler_t handler);
+/* machine dependent irq functions */
+extern void (*mach_init_IRQ) (void);
+extern void (*mach_get_model) (char *model);
+extern void (*mach_get_hardware_list) (struct seq_file *m);
+/* machine dependent timer functions */
+extern unsigned long (*mach_gettimeoffset)(void);
+extern int (*mach_hwclk)(int, struct rtc_time*);
+extern unsigned int (*mach_get_ss)(void);
+extern int (*mach_get_rtc_pll)(struct rtc_pll_info *);
+extern int (*mach_set_rtc_pll)(struct rtc_pll_info *);
+extern int (*mach_set_clock_mmss)(unsigned long);
+extern void (*mach_gettod)(int *year, int *mon, int *day, int *hour,
+ int *min, int *sec);
+extern void (*mach_reset)( void );
+extern void (*mach_halt)( void );
+extern void (*mach_power_off)( void );
+extern unsigned long (*mach_hd_init) (unsigned long, unsigned long);
+extern void (*mach_hd_setup)(char *, int *);
+extern long mach_max_dma_address;
+extern void (*mach_heartbeat) (int);
+extern void (*mach_l2_flush) (int);
+extern void (*mach_beep) (unsigned int, unsigned int);
+
+/* Hardware clock functions */
+extern void hw_timer_init(void);
+extern unsigned long hw_timer_offset(void);
+extern irqreturn_t arch_timer_interrupt(int irq, void *dummy);
+
+extern void config_BSP(char *command, int len);
+
+#endif /* _M68K_MACHDEP_H */
diff --git a/arch/m68k/include/asm/machdep_mm.h b/arch/m68k/include/asm/machdep_mm.h
deleted file mode 100644
index 5637dcef314e..000000000000
--- a/arch/m68k/include/asm/machdep_mm.h
+++ /dev/null
@@ -1,35 +0,0 @@
-#ifndef _M68K_MACHDEP_H
-#define _M68K_MACHDEP_H
-
-#include <linux/seq_file.h>
-#include <linux/interrupt.h>
-
-struct pt_regs;
-struct mktime;
-struct rtc_time;
-struct rtc_pll_info;
-struct buffer_head;
-
-extern void (*mach_sched_init) (irq_handler_t handler);
-/* machine dependent irq functions */
-extern void (*mach_init_IRQ) (void);
-extern void (*mach_get_model) (char *model);
-extern void (*mach_get_hardware_list) (struct seq_file *m);
-/* machine dependent timer functions */
-extern unsigned long (*mach_gettimeoffset)(void);
-extern int (*mach_hwclk)(int, struct rtc_time*);
-extern unsigned int (*mach_get_ss)(void);
-extern int (*mach_get_rtc_pll)(struct rtc_pll_info *);
-extern int (*mach_set_rtc_pll)(struct rtc_pll_info *);
-extern int (*mach_set_clock_mmss)(unsigned long);
-extern void (*mach_reset)( void );
-extern void (*mach_halt)( void );
-extern void (*mach_power_off)( void );
-extern unsigned long (*mach_hd_init) (unsigned long, unsigned long);
-extern void (*mach_hd_setup)(char *, int *);
-extern long mach_max_dma_address;
-extern void (*mach_heartbeat) (int);
-extern void (*mach_l2_flush) (int);
-extern void (*mach_beep) (unsigned int, unsigned int);
-
-#endif /* _M68K_MACHDEP_H */
diff --git a/arch/m68k/include/asm/machdep_no.h b/arch/m68k/include/asm/machdep_no.h
deleted file mode 100644
index de9f47a51cc2..000000000000
--- a/arch/m68k/include/asm/machdep_no.h
+++ /dev/null
@@ -1,26 +0,0 @@
-#ifndef _M68KNOMMU_MACHDEP_H
-#define _M68KNOMMU_MACHDEP_H
-
-#include <linux/interrupt.h>
-
-/* Hardware clock functions */
-extern void hw_timer_init(void);
-extern unsigned long hw_timer_offset(void);
-
-extern irqreturn_t arch_timer_interrupt(int irq, void *dummy);
-
-/* Machine dependent time handling */
-extern void (*mach_gettod)(int *year, int *mon, int *day, int *hour,
- int *min, int *sec);
-extern int (*mach_set_clock_mmss)(unsigned long);
-
-/* machine dependent power off functions */
-extern void (*mach_reset)( void );
-extern void (*mach_halt)( void );
-extern void (*mach_power_off)( void );
-
-extern void config_BSP(char *command, int len);
-
-extern void do_IRQ(int irq, struct pt_regs *fp);
-
-#endif /* _M68KNOMMU_MACHDEP_H */
diff --git a/arch/m68k/include/asm/page.h b/arch/m68k/include/asm/page.h
index f2b4480cc98a..dfebb7c1e379 100644
--- a/arch/m68k/include/asm/page.h
+++ b/arch/m68k/include/asm/page.h
@@ -1,5 +1,49 @@
-#ifdef __uClinux__
-#include "page_no.h"
+#ifndef _M68K_PAGE_H
+#define _M68K_PAGE_H
+
+#include <linux/const.h>
+#include <asm/setup.h>
+#include <asm/page_offset.h>
+
+/* PAGE_SHIFT determines the page size */
+#ifndef CONFIG_SUN3
+#define PAGE_SHIFT (12)
#else
+#define PAGE_SHIFT (13)
+#endif
+#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT)
+#define PAGE_MASK (~(PAGE_SIZE-1))
+#define PAGE_OFFSET (PAGE_OFFSET_RAW)
+
+#ifndef __ASSEMBLY__
+
+/*
+ * These are used to make use of C type-checking..
+ */
+typedef struct { unsigned long pte; } pte_t;
+typedef struct { unsigned long pmd[16]; } pmd_t;
+typedef struct { unsigned long pgd; } pgd_t;
+typedef struct { unsigned long pgprot; } pgprot_t;
+typedef struct page *pgtable_t;
+
+#define pte_val(x) ((x).pte)
+#define pmd_val(x) ((&x)->pmd[0])
+#define pgd_val(x) ((x).pgd)
+#define pgprot_val(x) ((x).pgprot)
+
+#define __pte(x) ((pte_t) { (x) } )
+#define __pmd(x) ((pmd_t) { (x) } )
+#define __pgd(x) ((pgd_t) { (x) } )
+#define __pgprot(x) ((pgprot_t) { (x) } )
+
+#endif /* !__ASSEMBLY__ */
+
+#ifdef CONFIG_MMU
#include "page_mm.h"
+#else
+#include "page_no.h"
#endif
+
+#include <asm-generic/getorder.h>
+
+#endif /* _M68K_PAGE_H */
diff --git a/arch/m68k/include/asm/page_mm.h b/arch/m68k/include/asm/page_mm.h
index d009f3ea39ab..31d5570d6567 100644
--- a/arch/m68k/include/asm/page_mm.h
+++ b/arch/m68k/include/asm/page_mm.h
@@ -1,29 +1,9 @@
-#ifndef _M68K_PAGE_H
-#define _M68K_PAGE_H
-
-#include <linux/const.h>
-
-/* PAGE_SHIFT determines the page size */
-#ifndef CONFIG_SUN3
-#define PAGE_SHIFT (12)
-#else
-#define PAGE_SHIFT (13)
-#endif
-#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT)
-#define PAGE_MASK (~(PAGE_SIZE-1))
-
-#include <asm/setup.h>
-
-#if PAGE_SHIFT < 13
-#define THREAD_SIZE (8192)
-#else
-#define THREAD_SIZE PAGE_SIZE
-#endif
+#ifndef _M68K_PAGE_MM_H
+#define _M68K_PAGE_MM_H
#ifndef __ASSEMBLY__
#include <linux/compiler.h>
-
#include <asm/module.h>
#define get_user_page(vaddr) __get_free_page(GFP_KERNEL)
@@ -84,33 +64,6 @@ static inline void clear_page(void *page)
flush_dcache_page(page); \
} while (0)
-/*
- * These are used to make use of C type-checking..
- */
-typedef struct { unsigned long pte; } pte_t;
-typedef struct { unsigned long pmd[16]; } pmd_t;
-typedef struct { unsigned long pgd; } pgd_t;
-typedef struct { unsigned long pgprot; } pgprot_t;
-typedef struct page *pgtable_t;
-
-#define pte_val(x) ((x).pte)
-#define pmd_val(x) ((&x)->pmd[0])
-#define pgd_val(x) ((x).pgd)
-#define pgprot_val(x) ((x).pgprot)
-
-#define __pte(x) ((pte_t) { (x) } )
-#define __pmd(x) ((pmd_t) { (x) } )
-#define __pgd(x) ((pgd_t) { (x) } )
-#define __pgprot(x) ((pgprot_t) { (x) } )
-
-#endif /* !__ASSEMBLY__ */
-
-#include <asm/page_offset.h>
-
-#define PAGE_OFFSET (PAGE_OFFSET_RAW)
-
-#ifndef __ASSEMBLY__
-
extern unsigned long m68k_memoffset;
#ifndef CONFIG_SUN3
@@ -127,7 +80,7 @@ static inline unsigned long ___pa(void *vaddr)
: "0" (vaddr), "i" (m68k_fixup_memoffset));
return paddr;
}
-#define __pa(vaddr) ___pa((void *)(vaddr))
+#define __pa(vaddr) ___pa((void *)(long)(vaddr))
static inline void *__va(unsigned long paddr)
{
void *vaddr;
@@ -223,6 +176,4 @@ static inline __attribute_const__ int __virt_to_node_shift(void)
#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
-#include <asm-generic/getorder.h>
-
-#endif /* _M68K_PAGE_H */
+#endif /* _M68K_PAGE_MM_H */
diff --git a/arch/m68k/include/asm/page_no.h b/arch/m68k/include/asm/page_no.h
index 8029a33e03c3..90595721185f 100644
--- a/arch/m68k/include/asm/page_no.h
+++ b/arch/m68k/include/asm/page_no.h
@@ -1,18 +1,11 @@
-#ifndef _M68KNOMMU_PAGE_H
-#define _M68KNOMMU_PAGE_H
-
-#include <linux/const.h>
-
-/* PAGE_SHIFT determines the page size */
-
-#define PAGE_SHIFT (12)
-#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT)
-#define PAGE_MASK (~(PAGE_SIZE-1))
-
-#include <asm/setup.h>
+#ifndef _M68K_PAGE_NO_H
+#define _M68K_PAGE_NO_H
#ifndef __ASSEMBLY__
+extern unsigned long memory_start;
+extern unsigned long memory_end;
+
#define get_user_page(vaddr) __get_free_page(GFP_KERNEL)
#define free_user_page(page, addr) free_page(addr)
@@ -26,36 +19,6 @@
alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
#define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
-/*
- * These are used to make use of C type-checking..
- */
-typedef struct { unsigned long pte; } pte_t;
-typedef struct { unsigned long pmd[16]; } pmd_t;
-typedef struct { unsigned long pgd; } pgd_t;
-typedef struct { unsigned long pgprot; } pgprot_t;
-typedef struct page *pgtable_t;
-
-#define pte_val(x) ((x).pte)
-#define pmd_val(x) ((&x)->pmd[0])
-#define pgd_val(x) ((x).pgd)
-#define pgprot_val(x) ((x).pgprot)
-
-#define __pte(x) ((pte_t) { (x) } )
-#define __pmd(x) ((pmd_t) { (x) } )
-#define __pgd(x) ((pgd_t) { (x) } )
-#define __pgprot(x) ((pgprot_t) { (x) } )
-
-extern unsigned long memory_start;
-extern unsigned long memory_end;
-
-#endif /* !__ASSEMBLY__ */
-
-#include <asm/page_offset.h>
-
-#define PAGE_OFFSET (PAGE_OFFSET_RAW)
-
-#ifndef __ASSEMBLY__
-
#define __pa(vaddr) ((unsigned long)(vaddr))
#define __va(paddr) ((void *)(paddr))
@@ -74,6 +37,4 @@ extern unsigned long memory_end;
#endif /* __ASSEMBLY__ */
-#include <asm-generic/getorder.h>
-
-#endif /* _M68KNOMMU_PAGE_H */
+#endif /* _M68K_PAGE_NO_H */
diff --git a/arch/m68k/include/asm/string.h b/arch/m68k/include/asm/string.h
index 2c356f90f171..2936dda938d7 100644
--- a/arch/m68k/include/asm/string.h
+++ b/arch/m68k/include/asm/string.h
@@ -1,5 +1,133 @@
-#ifdef __uClinux__
-#include "string_no.h"
+#ifndef _M68K_STRING_H_
+#define _M68K_STRING_H_
+
+#include <linux/types.h>
+#include <linux/compiler.h>
+
+static inline size_t __kernel_strlen(const char *s)
+{
+ const char *sc;
+
+ for (sc = s; *sc++; )
+ ;
+ return sc - s - 1;
+}
+
+static inline char *__kernel_strcpy(char *dest, const char *src)
+{
+ char *xdest = dest;
+
+ asm volatile ("\n"
+ "1: move.b (%1)+,(%0)+\n"
+ " jne 1b"
+ : "+a" (dest), "+a" (src)
+ : : "memory");
+ return xdest;
+}
+
+#ifndef __IN_STRING_C
+
+#define __HAVE_ARCH_STRLEN
+#define strlen(s) (__builtin_constant_p(s) ? \
+ __builtin_strlen(s) : \
+ __kernel_strlen(s))
+
+#define __HAVE_ARCH_STRNLEN
+static inline size_t strnlen(const char *s, size_t count)
+{
+ const char *sc = s;
+
+ asm volatile ("\n"
+ "1: subq.l #1,%1\n"
+ " jcs 2f\n"
+ " tst.b (%0)+\n"
+ " jne 1b\n"
+ " subq.l #1,%0\n"
+ "2:"
+ : "+a" (sc), "+d" (count));
+ return sc - s;
+}
+
+#define __HAVE_ARCH_STRCPY
+#if __GNUC__ >= 4
+#define strcpy(d, s) (__builtin_constant_p(s) && \
+ __builtin_strlen(s) <= 32 ? \
+ __builtin_strcpy(d, s) : \
+ __kernel_strcpy(d, s))
#else
-#include "string_mm.h"
+#define strcpy(d, s) __kernel_strcpy(d, s)
#endif
+
+#define __HAVE_ARCH_STRNCPY
+static inline char *strncpy(char *dest, const char *src, size_t n)
+{
+ char *xdest = dest;
+
+ asm volatile ("\n"
+ " jra 2f\n"
+ "1: move.b (%1),(%0)+\n"
+ " jeq 2f\n"
+ " addq.l #1,%1\n"
+ "2: subq.l #1,%2\n"
+ " jcc 1b\n"
+ : "+a" (dest), "+a" (src), "+d" (n)
+ : : "memory");
+ return xdest;
+}
+
+#define __HAVE_ARCH_STRCAT
+#define strcat(d, s) ({ \
+ char *__d = (d); \
+ strcpy(__d + strlen(__d), (s)); \
+})
+
+#define __HAVE_ARCH_STRCHR
+static inline char *strchr(const char *s, int c)
+{
+ char sc, ch = c;
+
+ for (; (sc = *s++) != ch; ) {
+ if (!sc)
+ return NULL;
+ }
+ return (char *)s - 1;
+}
+
+#ifndef CONFIG_COLDFIRE
+#define __HAVE_ARCH_STRCMP
+static inline int strcmp(const char *cs, const char *ct)
+{
+ char res;
+
+ asm ("\n"
+ "1: move.b (%0)+,%2\n" /* get *cs */
+ " cmp.b (%1)+,%2\n" /* compare a byte */
+ " jne 2f\n" /* not equal, break out */
+ " tst.b %2\n" /* at end of cs? */
+ " jne 1b\n" /* no, keep going */
+ " jra 3f\n" /* strings are equal */
+ "2: sub.b -(%1),%2\n" /* *cs - *ct */
+ "3:"
+ : "+a" (cs), "+a" (ct), "=d" (res));
+ return res;
+}
+
+#define __HAVE_ARCH_MEMMOVE
+extern void *memmove(void *, const void *, __kernel_size_t);
+
+#define __HAVE_ARCH_MEMCMP
+extern int memcmp(const void *, const void *, __kernel_size_t);
+#define memcmp(d, s, n) __builtin_memcmp(d, s, n)
+#endif /* CONFIG_COLDFIRE */
+
+#define __HAVE_ARCH_MEMSET
+extern void *memset(void *, int, __kernel_size_t);
+#define memset(d, c, n) __builtin_memset(d, c, n)
+
+#define __HAVE_ARCH_MEMCPY
+extern void *memcpy(void *, const void *, __kernel_size_t);
+#define memcpy(d, s, n) __builtin_memcpy(d, s, n)
+
+#endif
+
+#endif /* _M68K_STRING_H_ */
diff --git a/arch/m68k/include/asm/string_mm.h b/arch/m68k/include/asm/string_mm.h
deleted file mode 100644
index 2eb7df1e0f5d..000000000000
--- a/arch/m68k/include/asm/string_mm.h
+++ /dev/null
@@ -1,131 +0,0 @@
-#ifndef _M68K_STRING_H_
-#define _M68K_STRING_H_
-
-#include <linux/types.h>
-#include <linux/compiler.h>
-
-static inline size_t __kernel_strlen(const char *s)
-{
- const char *sc;
-
- for (sc = s; *sc++; )
- ;
- return sc - s - 1;
-}
-
-static inline char *__kernel_strcpy(char *dest, const char *src)
-{
- char *xdest = dest;
-
- asm volatile ("\n"
- "1: move.b (%1)+,(%0)+\n"
- " jne 1b"
- : "+a" (dest), "+a" (src)
- : : "memory");
- return xdest;
-}
-
-#ifndef __IN_STRING_C
-
-#define __HAVE_ARCH_STRLEN
-#define strlen(s) (__builtin_constant_p(s) ? \
- __builtin_strlen(s) : \
- __kernel_strlen(s))
-
-#define __HAVE_ARCH_STRNLEN
-static inline size_t strnlen(const char *s, size_t count)
-{
- const char *sc = s;
-
- asm volatile ("\n"
- "1: subq.l #1,%1\n"
- " jcs 2f\n"
- " tst.b (%0)+\n"
- " jne 1b\n"
- " subq.l #1,%0\n"
- "2:"
- : "+a" (sc), "+d" (count));
- return sc - s;
-}
-
-#define __HAVE_ARCH_STRCPY
-#if __GNUC__ >= 4
-#define strcpy(d, s) (__builtin_constant_p(s) && \
- __builtin_strlen(s) <= 32 ? \
- __builtin_strcpy(d, s) : \
- __kernel_strcpy(d, s))
-#else
-#define strcpy(d, s) __kernel_strcpy(d, s)
-#endif
-
-#define __HAVE_ARCH_STRNCPY
-static inline char *strncpy(char *dest, const char *src, size_t n)
-{
- char *xdest = dest;
-
- asm volatile ("\n"
- " jra 2f\n"
- "1: move.b (%1),(%0)+\n"
- " jeq 2f\n"
- " addq.l #1,%1\n"
- "2: subq.l #1,%2\n"
- " jcc 1b\n"
- : "+a" (dest), "+a" (src), "+d" (n)
- : : "memory");
- return xdest;
-}
-
-#define __HAVE_ARCH_STRCAT
-#define strcat(d, s) ({ \
- char *__d = (d); \
- strcpy(__d + strlen(__d), (s)); \
-})
-
-#define __HAVE_ARCH_STRCHR
-static inline char *strchr(const char *s, int c)
-{
- char sc, ch = c;
-
- for (; (sc = *s++) != ch; ) {
- if (!sc)
- return NULL;
- }
- return (char *)s - 1;
-}
-
-#define __HAVE_ARCH_STRCMP
-static inline int strcmp(const char *cs, const char *ct)
-{
- char res;
-
- asm ("\n"
- "1: move.b (%0)+,%2\n" /* get *cs */
- " cmp.b (%1)+,%2\n" /* compare a byte */
- " jne 2f\n" /* not equal, break out */
- " tst.b %2\n" /* at end of cs? */
- " jne 1b\n" /* no, keep going */
- " jra 3f\n" /* strings are equal */
- "2: sub.b -(%1),%2\n" /* *cs - *ct */
- "3:"
- : "+a" (cs), "+a" (ct), "=d" (res));
- return res;
-}
-
-#define __HAVE_ARCH_MEMSET
-extern void *memset(void *, int, __kernel_size_t);
-#define memset(d, c, n) __builtin_memset(d, c, n)
-
-#define __HAVE_ARCH_MEMCPY
-extern void *memcpy(void *, const void *, __kernel_size_t);
-#define memcpy(d, s, n) __builtin_memcpy(d, s, n)
-
-#define __HAVE_ARCH_MEMMOVE
-extern void *memmove(void *, const void *, __kernel_size_t);
-
-#define __HAVE_ARCH_MEMCMP
-extern int memcmp(const void *, const void *, __kernel_size_t);
-#define memcmp(d, s, n) __builtin_memcmp(d, s, n)
-
-#endif
-
-#endif /* _M68K_STRING_H_ */
diff --git a/arch/m68k/include/asm/string_no.h b/arch/m68k/include/asm/string_no.h
deleted file mode 100644
index af09e17000fc..000000000000
--- a/arch/m68k/include/asm/string_no.h
+++ /dev/null
@@ -1,126 +0,0 @@
-#ifndef _M68KNOMMU_STRING_H_
-#define _M68KNOMMU_STRING_H_
-
-#ifdef __KERNEL__ /* only set these up for kernel code */
-
-#include <asm/setup.h>
-#include <asm/page.h>
-
-#define __HAVE_ARCH_STRCPY
-static inline char * strcpy(char * dest,const char *src)
-{
- char *xdest = dest;
-
- __asm__ __volatile__
- ("1:\tmoveb %1@+,%0@+\n\t"
- "jne 1b"
- : "=a" (dest), "=a" (src)
- : "0" (dest), "1" (src) : "memory");
- return xdest;
-}
-
-#define __HAVE_ARCH_STRNCPY
-static inline char * strncpy(char *dest, const char *src, size_t n)
-{
- char *xdest = dest;
-
- if (n == 0)
- return xdest;
-
- __asm__ __volatile__
- ("1:\tmoveb %1@+,%0@+\n\t"
- "jeq 2f\n\t"
- "subql #1,%2\n\t"
- "jne 1b\n\t"
- "2:"
- : "=a" (dest), "=a" (src), "=d" (n)
- : "0" (dest), "1" (src), "2" (n)
- : "memory");
- return xdest;
-}
-
-
-#ifndef CONFIG_COLDFIRE
-
-#define __HAVE_ARCH_STRCMP
-static inline int strcmp(const char * cs,const char * ct)
-{
- char __res;
-
- __asm__
- ("1:\tmoveb %0@+,%2\n\t" /* get *cs */
- "cmpb %1@+,%2\n\t" /* compare a byte */
- "jne 2f\n\t" /* not equal, break out */
- "tstb %2\n\t" /* at end of cs? */
- "jne 1b\n\t" /* no, keep going */
- "jra 3f\n\t" /* strings are equal */
- "2:\tsubb %1@-,%2\n\t" /* *cs - *ct */
- "3:"
- : "=a" (cs), "=a" (ct), "=d" (__res)
- : "0" (cs), "1" (ct));
-
- return __res;
-}
-
-#define __HAVE_ARCH_STRNCMP
-static inline int strncmp(const char * cs,const char * ct,size_t count)
-{
- char __res;
-
- if (!count)
- return 0;
- __asm__
- ("1:\tmovb %0@+,%3\n\t" /* get *cs */
- "cmpb %1@+,%3\n\t" /* compare a byte */
- "jne 3f\n\t" /* not equal, break out */
- "tstb %3\n\t" /* at end of cs? */
- "jeq 4f\n\t" /* yes, all done */
- "subql #1,%2\n\t" /* no, adjust count */
- "jne 1b\n\t" /* more to do, keep going */
- "2:\tmoveq #0,%3\n\t" /* strings are equal */
- "jra 4f\n\t"
- "3:\tsubb %1@-,%3\n\t" /* *cs - *ct */
- "4:"
- : "=a" (cs), "=a" (ct), "=d" (count), "=d" (__res)
- : "0" (cs), "1" (ct), "2" (count));
- return __res;
-}
-
-#endif /* CONFIG_COLDFIRE */
-
-#define __HAVE_ARCH_MEMSET
-extern void * memset(void * s, int c, size_t count);
-
-#define __HAVE_ARCH_MEMCPY
-extern void * memcpy(void *d, const void *s, size_t count);
-
-#else /* KERNEL */
-
-/*
- * let user libraries deal with these,
- * IMHO the kernel has no place defining these functions for user apps
- */
-
-#define __HAVE_ARCH_STRCPY 1
-#define __HAVE_ARCH_STRNCPY 1
-#define __HAVE_ARCH_STRCAT 1
-#define __HAVE_ARCH_STRNCAT 1
-#define __HAVE_ARCH_STRCMP 1
-#define __HAVE_ARCH_STRNCMP 1
-#define __HAVE_ARCH_STRNICMP 1
-#define __HAVE_ARCH_STRCHR 1
-#define __HAVE_ARCH_STRRCHR 1
-#define __HAVE_ARCH_STRSTR 1
-#define __HAVE_ARCH_STRLEN 1
-#define __HAVE_ARCH_STRNLEN 1
-#define __HAVE_ARCH_MEMSET 1
-#define __HAVE_ARCH_MEMCPY 1
-#define __HAVE_ARCH_MEMMOVE 1
-#define __HAVE_ARCH_MEMSCAN 1
-#define __HAVE_ARCH_MEMCMP 1
-#define __HAVE_ARCH_MEMCHR 1
-#define __HAVE_ARCH_STRTOK 1
-
-#endif /* KERNEL */
-
-#endif /* _M68K_STRING_H_ */
diff --git a/arch/m68k/include/asm/system_mm.h b/arch/m68k/include/asm/system_mm.h
index dbb6515ffd5b..47b01f4726bc 100644
--- a/arch/m68k/include/asm/system_mm.h
+++ b/arch/m68k/include/asm/system_mm.h
@@ -3,6 +3,7 @@
#include <linux/linkage.h>
#include <linux/kernel.h>
+#include <linux/irqflags.h>
#include <asm/segment.h>
#include <asm/entry.h>
@@ -62,30 +63,6 @@ asmlinkage void resume(void);
#define smp_wmb() barrier()
#define smp_read_barrier_depends() ((void)0)
-/* interrupt control.. */
-#if 0
-#define local_irq_enable() asm volatile ("andiw %0,%%sr": : "i" (ALLOWINT) : "memory")
-#else
-#include <linux/hardirq.h>
-#define local_irq_enable() ({ \
- if (MACH_IS_Q40 || !hardirq_count()) \
- asm volatile ("andiw %0,%%sr": : "i" (ALLOWINT) : "memory"); \
-})
-#endif
-#define local_irq_disable() asm volatile ("oriw #0x0700,%%sr": : : "memory")
-#define local_save_flags(x) asm volatile ("movew %%sr,%0":"=d" (x) : : "memory")
-#define local_irq_restore(x) asm volatile ("movew %0,%%sr": :"d" (x) : "memory")
-
-static inline int irqs_disabled(void)
-{
- unsigned long flags;
- local_save_flags(flags);
- return flags & ~ALLOWINT;
-}
-
-/* For spinlocks etc */
-#define local_irq_save(x) ({ local_save_flags(x); local_irq_disable(); })
-
#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
struct __xchg_dummy { unsigned long a[100]; };
@@ -205,9 +182,7 @@ static inline unsigned long __cmpxchg(volatile void *p, unsigned long old,
((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
(unsigned long)(n), sizeof(*(ptr))))
-#ifndef CONFIG_SMP
#include <asm-generic/cmpxchg.h>
-#endif
#endif
diff --git a/arch/m68k/include/asm/system_no.h b/arch/m68k/include/asm/system_no.h
index 3c0718d74398..6fe9f93bc3ff 100644
--- a/arch/m68k/include/asm/system_no.h
+++ b/arch/m68k/include/asm/system_no.h
@@ -2,6 +2,7 @@
#define _M68KNOMMU_SYSTEM_H
#include <linux/linkage.h>
+#include <linux/irqflags.h>
#include <asm/segment.h>
#include <asm/entry.h>
@@ -46,54 +47,6 @@ asmlinkage void resume(void);
(last) = _last; \
}
-#ifdef CONFIG_COLDFIRE
-#define local_irq_enable() __asm__ __volatile__ ( \
- "move %/sr,%%d0\n\t" \
- "andi.l #0xf8ff,%%d0\n\t" \
- "move %%d0,%/sr\n" \
- : /* no outputs */ \
- : \
- : "cc", "%d0", "memory")
-#define local_irq_disable() __asm__ __volatile__ ( \
- "move %/sr,%%d0\n\t" \
- "ori.l #0x0700,%%d0\n\t" \
- "move %%d0,%/sr\n" \
- : /* no outputs */ \
- : \
- : "cc", "%d0", "memory")
-/* For spinlocks etc */
-#define local_irq_save(x) __asm__ __volatile__ ( \
- "movew %%sr,%0\n\t" \
- "movew #0x0700,%%d0\n\t" \
- "or.l %0,%%d0\n\t" \
- "movew %%d0,%/sr" \
- : "=d" (x) \
- : \
- : "cc", "%d0", "memory")
-#else
-
-/* portable version */ /* FIXME - see entry.h*/
-#define ALLOWINT 0xf8ff
-
-#define local_irq_enable() asm volatile ("andiw %0,%%sr": : "i" (ALLOWINT) : "memory")
-#define local_irq_disable() asm volatile ("oriw #0x0700,%%sr": : : "memory")
-#endif
-
-#define local_save_flags(x) asm volatile ("movew %%sr,%0":"=d" (x) : : "memory")
-#define local_irq_restore(x) asm volatile ("movew %0,%%sr": :"d" (x) : "memory")
-
-/* For spinlocks etc */
-#ifndef local_irq_save
-#define local_irq_save(x) do { local_save_flags(x); local_irq_disable(); } while (0)
-#endif
-
-#define irqs_disabled() \
-({ \
- unsigned long flags; \
- local_save_flags(flags); \
- ((flags & 0x0700) == 0x0700); \
-})
-
#define iret() __asm__ __volatile__ ("rte": : :"memory", "sp", "cc")
/*
@@ -106,17 +59,10 @@ asmlinkage void resume(void);
#define wmb() asm volatile ("" : : :"memory")
#define set_mb(var, value) ({ (var) = (value); wmb(); })
-#ifdef CONFIG_SMP
-#define smp_mb() mb()
-#define smp_rmb() rmb()
-#define smp_wmb() wmb()
-#define smp_read_barrier_depends() read_barrier_depends()
-#else
#define smp_mb() barrier()
#define smp_rmb() barrier()
#define smp_wmb() barrier()
#define smp_read_barrier_depends() do { } while(0)
-#endif
#define read_barrier_depends() ((void)0)
@@ -199,19 +145,9 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz
(unsigned long)(n), sizeof(*(ptr))))
#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
-#ifndef CONFIG_SMP
#include <asm-generic/cmpxchg.h>
-#endif
#define arch_align_stack(x) (x)
-static inline int irqs_disabled_flags(unsigned long flags)
-{
- if (flags & 0x0700)
- return 0;
- else
- return 1;
-}
-
#endif /* _M68KNOMMU_SYSTEM_H */
diff --git a/arch/m68k/include/asm/thread_info.h b/arch/m68k/include/asm/thread_info.h
index f31a3f42b7b3..1da5d53a00eb 100644
--- a/arch/m68k/include/asm/thread_info.h
+++ b/arch/m68k/include/asm/thread_info.h
@@ -1,5 +1,108 @@
-#ifdef __uClinux__
-#include "thread_info_no.h"
+#ifndef _ASM_M68K_THREAD_INFO_H
+#define _ASM_M68K_THREAD_INFO_H
+
+#include <asm/types.h>
+#include <asm/page.h>
+
+/*
+ * On machines with 4k pages we default to an 8k thread size, though we
+ * allow a 4k with config option. Any other machine page size then
+ * the thread size must match the page size (which is 8k and larger here).
+ */
+#if PAGE_SHIFT < 13
+#ifdef CONFIG_4KSTACKS
+#define THREAD_SIZE 4096
#else
-#include "thread_info_mm.h"
+#define THREAD_SIZE 8192
#endif
+#else
+#define THREAD_SIZE PAGE_SIZE
+#endif
+#define THREAD_SIZE_ORDER ((THREAD_SIZE / PAGE_SIZE) - 1)
+
+#ifndef __ASSEMBLY__
+
+struct thread_info {
+ struct task_struct *task; /* main task structure */
+ unsigned long flags;
+ struct exec_domain *exec_domain; /* execution domain */
+ int preempt_count; /* 0 => preemptable, <0 => BUG */
+ __u32 cpu; /* should always be 0 on m68k */
+ unsigned long tp_value; /* thread pointer */
+ struct restart_block restart_block;
+};
+#endif /* __ASSEMBLY__ */
+
+#define PREEMPT_ACTIVE 0x4000000
+
+#define INIT_THREAD_INFO(tsk) \
+{ \
+ .task = &tsk, \
+ .exec_domain = &default_exec_domain, \
+ .preempt_count = INIT_PREEMPT_COUNT, \
+ .restart_block = { \
+ .fn = do_no_restart_syscall, \
+ }, \
+}
+
+#define init_stack (init_thread_union.stack)
+
+#ifdef CONFIG_MMU
+
+#ifndef __ASSEMBLY__
+#include <asm/current.h>
+#endif
+
+#ifdef ASM_OFFSETS_C
+#define task_thread_info(tsk) ((struct thread_info *) NULL)
+#else
+#include <asm/asm-offsets.h>
+#define task_thread_info(tsk) ((struct thread_info *)((char *)tsk+TASK_TINFO))
+#endif
+
+#define init_thread_info (init_task.thread.info)
+#define task_stack_page(tsk) ((tsk)->stack)
+#define current_thread_info() task_thread_info(current)
+
+#define __HAVE_THREAD_FUNCTIONS
+
+#define setup_thread_stack(p, org) ({ \
+ *(struct task_struct **)(p)->stack = (p); \
+ task_thread_info(p)->task = (p); \
+})
+
+#define end_of_stack(p) ((unsigned long *)(p)->stack + 1)
+
+#else /* !CONFIG_MMU */
+
+#ifndef __ASSEMBLY__
+/* how to get the thread information struct from C */
+static inline struct thread_info *current_thread_info(void)
+{
+ struct thread_info *ti;
+ __asm__(
+ "move.l %%sp, %0 \n\t"
+ "and.l %1, %0"
+ : "=&d"(ti)
+ : "di" (~(THREAD_SIZE-1))
+ );
+ return ti;
+}
+#endif
+
+#define init_thread_info (init_thread_union.thread_info)
+
+#endif /* CONFIG_MMU */
+
+/* entry.S relies on these definitions!
+ * bits 0-7 are tested at every exception exit
+ * bits 8-15 are also tested at syscall exit
+ */
+#define TIF_SIGPENDING 6 /* signal pending */
+#define TIF_NEED_RESCHED 7 /* rescheduling necessary */
+#define TIF_DELAYED_TRACE 14 /* single step a syscall */
+#define TIF_SYSCALL_TRACE 15 /* syscall trace active */
+#define TIF_MEMDIE 16 /* is terminating due to OOM killer */
+#define TIF_FREEZE 17 /* thread is freezing for suspend */
+
+#endif /* _ASM_M68K_THREAD_INFO_H */
diff --git a/arch/m68k/include/asm/thread_info_mm.h b/arch/m68k/include/asm/thread_info_mm.h
deleted file mode 100644
index 3bf31dc51b12..000000000000
--- a/arch/m68k/include/asm/thread_info_mm.h
+++ /dev/null
@@ -1,71 +0,0 @@
-#ifndef _ASM_M68K_THREAD_INFO_H
-#define _ASM_M68K_THREAD_INFO_H
-
-#ifndef ASM_OFFSETS_C
-#include <asm/asm-offsets.h>
-#endif
-#include <asm/types.h>
-#include <asm/page.h>
-
-#ifndef __ASSEMBLY__
-#include <asm/current.h>
-
-struct thread_info {
- struct task_struct *task; /* main task structure */
- unsigned long flags;
- struct exec_domain *exec_domain; /* execution domain */
- int preempt_count; /* 0 => preemptable, <0 => BUG */
- __u32 cpu; /* should always be 0 on m68k */
- unsigned long tp_value; /* thread pointer */
- struct restart_block restart_block;
-};
-#endif /* __ASSEMBLY__ */
-
-#define PREEMPT_ACTIVE 0x4000000
-
-#define INIT_THREAD_INFO(tsk) \
-{ \
- .task = &tsk, \
- .exec_domain = &default_exec_domain, \
- .preempt_count = INIT_PREEMPT_COUNT, \
- .restart_block = { \
- .fn = do_no_restart_syscall, \
- }, \
-}
-
-/* THREAD_SIZE should be 8k, so handle differently for 4k and 8k machines */
-#define THREAD_SIZE_ORDER (13 - PAGE_SHIFT)
-
-#define init_thread_info (init_task.thread.info)
-#define init_stack (init_thread_union.stack)
-
-#ifdef ASM_OFFSETS_C
-#define task_thread_info(tsk) ((struct thread_info *) NULL)
-#else
-#define task_thread_info(tsk) ((struct thread_info *)((char *)tsk+TASK_TINFO))
-#endif
-
-#define task_stack_page(tsk) ((tsk)->stack)
-#define current_thread_info() task_thread_info(current)
-
-#define __HAVE_THREAD_FUNCTIONS
-
-#define setup_thread_stack(p, org) ({ \
- *(struct task_struct **)(p)->stack = (p); \
- task_thread_info(p)->task = (p); \
-})
-
-#define end_of_stack(p) ((unsigned long *)(p)->stack + 1)
-
-/* entry.S relies on these definitions!
- * bits 0-7 are tested at every exception exit
- * bits 8-15 are also tested at syscall exit
- */
-#define TIF_SIGPENDING 6 /* signal pending */
-#define TIF_NEED_RESCHED 7 /* rescheduling necessary */
-#define TIF_DELAYED_TRACE 14 /* single step a syscall */
-#define TIF_SYSCALL_TRACE 15 /* syscall trace active */
-#define TIF_MEMDIE 16 /* is terminating due to OOM killer */
-#define TIF_FREEZE 17 /* thread is freezing for suspend */
-
-#endif /* _ASM_M68K_THREAD_INFO_H */
diff --git a/arch/m68k/include/asm/thread_info_no.h b/arch/m68k/include/asm/thread_info_no.h
deleted file mode 100644
index 51f354b672e6..000000000000
--- a/arch/m68k/include/asm/thread_info_no.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/* thread_info.h: m68knommu low-level thread information
- * adapted from the i386 and PPC versions by Greg Ungerer (gerg@snapgear.com)
- *
- * Copyright (C) 2002 David Howells (dhowells@redhat.com)
- * - Incorporating suggestions made by Linus Torvalds and Dave Miller
- */
-
-#ifndef _ASM_THREAD_INFO_H
-#define _ASM_THREAD_INFO_H
-
-#include <asm/page.h>
-
-#ifdef __KERNEL__
-
-/*
- * Size of kernel stack for each process. This must be a power of 2...
- */
-#ifdef CONFIG_4KSTACKS
-#define THREAD_SIZE_ORDER (0)
-#else
-#define THREAD_SIZE_ORDER (1)
-#endif
-
-/*
- * for asm files, THREAD_SIZE is now generated by asm-offsets.c
- */
-#define THREAD_SIZE (PAGE_SIZE<<THREAD_SIZE_ORDER)
-
-#ifndef __ASSEMBLY__
-
-/*
- * low level task data.
- */
-struct thread_info {
- struct task_struct *task; /* main task structure */
- struct exec_domain *exec_domain; /* execution domain */
- unsigned long flags; /* low level flags */
- int cpu; /* cpu we're on */
- int preempt_count; /* 0 => preemptable, <0 => BUG */
- unsigned long tp_value; /* thread pointer */
- struct restart_block restart_block;
-};
-
-/*
- * macros/functions for gaining access to the thread information structure
- */
-#define INIT_THREAD_INFO(tsk) \
-{ \
- .task = &tsk, \
- .exec_domain = &default_exec_domain, \
- .flags = 0, \
- .cpu = 0, \
- .preempt_count = INIT_PREEMPT_COUNT, \
- .restart_block = { \
- .fn = do_no_restart_syscall, \
- }, \
-}
-
-#define init_thread_info (init_thread_union.thread_info)
-#define init_stack (init_thread_union.stack)
-
-
-/* how to get the thread information struct from C */
-static inline struct thread_info *current_thread_info(void)
-{
- struct thread_info *ti;
- __asm__(
- "move.l %%sp, %0 \n\t"
- "and.l %1, %0"
- : "=&d"(ti)
- : "di" (~(THREAD_SIZE-1))
- );
- return ti;
-}
-
-#endif /* __ASSEMBLY__ */
-
-#define PREEMPT_ACTIVE 0x4000000
-
-/*
- * thread information flag bit numbers
- */
-#define TIF_SYSCALL_TRACE 0 /* syscall trace active */
-#define TIF_SIGPENDING 1 /* signal pending */
-#define TIF_NEED_RESCHED 2 /* rescheduling necessary */
-#define TIF_POLLING_NRFLAG 3 /* true if poll_idle() is polling
- TIF_NEED_RESCHED */
-#define TIF_MEMDIE 4 /* is terminating due to OOM killer */
-#define TIF_FREEZE 16 /* is freezing for suspend */
-
-/* as above, but as bit values */
-#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
-#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
-#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
-#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
-#define _TIF_FREEZE (1<<TIF_FREEZE)
-
-#define _TIF_WORK_MASK 0x0000FFFE /* work to do on interrupt/exception return */
-
-#endif /* __KERNEL__ */
-
-#endif /* _ASM_THREAD_INFO_H */
diff --git a/arch/m68k/include/asm/traps.h b/arch/m68k/include/asm/traps.h
index 3011ec0f5365..0bffb17d5db7 100644
--- a/arch/m68k/include/asm/traps.h
+++ b/arch/m68k/include/asm/traps.h
@@ -1,5 +1,272 @@
-#ifdef __uClinux__
-#include "traps_no.h"
-#else
-#include "traps_mm.h"
+/*
+ * linux/include/asm/traps.h
+ *
+ * Copyright (C) 1993 Hamish Macdonald
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _M68K_TRAPS_H
+#define _M68K_TRAPS_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/linkage.h>
+#include <asm/ptrace.h>
+
+typedef void (*e_vector)(void);
+extern e_vector vectors[];
+
+asmlinkage void auto_inthandler(void);
+asmlinkage void user_inthandler(void);
+asmlinkage void bad_inthandler(void);
+extern void init_vectors(void);
+
#endif
+
+#define VEC_RESETSP (0)
+#define VEC_RESETPC (1)
+#define VEC_BUSERR (2)
+#define VEC_ADDRERR (3)
+#define VEC_ILLEGAL (4)
+#define VEC_ZERODIV (5)
+#define VEC_CHK (6)
+#define VEC_TRAP (7)
+#define VEC_PRIV (8)
+#define VEC_TRACE (9)
+#define VEC_LINE10 (10)
+#define VEC_LINE11 (11)
+#define VEC_RESV12 (12)
+#define VEC_COPROC (13)
+#define VEC_FORMAT (14)
+#define VEC_UNINT (15)
+#define VEC_RESV16 (16)
+#define VEC_RESV17 (17)
+#define VEC_RESV18 (18)
+#define VEC_RESV19 (19)
+#define VEC_RESV20 (20)
+#define VEC_RESV21 (21)
+#define VEC_RESV22 (22)
+#define VEC_RESV23 (23)
+#define VEC_SPUR (24)
+#define VEC_INT1 (25)
+#define VEC_INT2 (26)
+#define VEC_INT3 (27)
+#define VEC_INT4 (28)
+#define VEC_INT5 (29)
+#define VEC_INT6 (30)
+#define VEC_INT7 (31)
+#define VEC_SYS (32)
+#define VEC_TRAP1 (33)
+#define VEC_TRAP2 (34)
+#define VEC_TRAP3 (35)
+#define VEC_TRAP4 (36)
+#define VEC_TRAP5 (37)
+#define VEC_TRAP6 (38)
+#define VEC_TRAP7 (39)
+#define VEC_TRAP8 (40)
+#define VEC_TRAP9 (41)
+#define VEC_TRAP10 (42)
+#define VEC_TRAP11 (43)
+#define VEC_TRAP12 (44)
+#define VEC_TRAP13 (45)
+#define VEC_TRAP14 (46)
+#define VEC_TRAP15 (47)
+#define VEC_FPBRUC (48)
+#define VEC_FPIR (49)
+#define VEC_FPDIVZ (50)
+#define VEC_FPUNDER (51)
+#define VEC_FPOE (52)
+#define VEC_FPOVER (53)
+#define VEC_FPNAN (54)
+#define VEC_FPUNSUP (55)
+#define VEC_MMUCFG (56)
+#define VEC_MMUILL (57)
+#define VEC_MMUACC (58)
+#define VEC_RESV59 (59)
+#define VEC_UNIMPEA (60)
+#define VEC_UNIMPII (61)
+#define VEC_RESV62 (62)
+#define VEC_RESV63 (63)
+#define VEC_USER (64)
+
+#define VECOFF(vec) ((vec)<<2)
+
+#ifndef __ASSEMBLY__
+
+/* Status register bits */
+#define PS_T (0x8000)
+#define PS_S (0x2000)
+#define PS_M (0x1000)
+#define PS_C (0x0001)
+
+/* bits for 68020/68030 special status word */
+
+#define FC (0x8000)
+#define FB (0x4000)
+#define RC (0x2000)
+#define RB (0x1000)
+#define DF (0x0100)
+#define RM (0x0080)
+#define RW (0x0040)
+#define SZ (0x0030)
+#define DFC (0x0007)
+
+/* bits for 68030 MMU status register (mmusr,psr) */
+
+#define MMU_B (0x8000) /* bus error */
+#define MMU_L (0x4000) /* limit violation */
+#define MMU_S (0x2000) /* supervisor violation */
+#define MMU_WP (0x0800) /* write-protected */
+#define MMU_I (0x0400) /* invalid descriptor */
+#define MMU_M (0x0200) /* ATC entry modified */
+#define MMU_T (0x0040) /* transparent translation */
+#define MMU_NUM (0x0007) /* number of levels traversed */
+
+
+/* bits for 68040 special status word */
+#define CP_040 (0x8000)
+#define CU_040 (0x4000)
+#define CT_040 (0x2000)
+#define CM_040 (0x1000)
+#define MA_040 (0x0800)
+#define ATC_040 (0x0400)
+#define LK_040 (0x0200)
+#define RW_040 (0x0100)
+#define SIZ_040 (0x0060)
+#define TT_040 (0x0018)
+#define TM_040 (0x0007)
+
+/* bits for 68040 write back status word */
+#define WBV_040 (0x80)
+#define WBSIZ_040 (0x60)
+#define WBBYT_040 (0x20)
+#define WBWRD_040 (0x40)
+#define WBLNG_040 (0x00)
+#define WBTT_040 (0x18)
+#define WBTM_040 (0x07)
+
+/* bus access size codes */
+#define BA_SIZE_BYTE (0x20)
+#define BA_SIZE_WORD (0x40)
+#define BA_SIZE_LONG (0x00)
+#define BA_SIZE_LINE (0x60)
+
+/* bus access transfer type codes */
+#define BA_TT_MOVE16 (0x08)
+
+/* bits for 68040 MMU status register (mmusr) */
+#define MMU_B_040 (0x0800)
+#define MMU_G_040 (0x0400)
+#define MMU_S_040 (0x0080)
+#define MMU_CM_040 (0x0060)
+#define MMU_M_040 (0x0010)
+#define MMU_WP_040 (0x0004)
+#define MMU_T_040 (0x0002)
+#define MMU_R_040 (0x0001)
+
+/* bits in the 68060 fault status long word (FSLW) */
+#define MMU060_MA (0x08000000) /* misaligned */
+#define MMU060_LK (0x02000000) /* locked transfer */
+#define MMU060_RW (0x01800000) /* read/write */
+# define MMU060_RW_W (0x00800000) /* write */
+# define MMU060_RW_R (0x01000000) /* read */
+# define MMU060_RW_RMW (0x01800000) /* read/modify/write */
+# define MMU060_W (0x00800000) /* general write, includes rmw */
+#define MMU060_SIZ (0x00600000) /* transfer size */
+#define MMU060_TT (0x00180000) /* transfer type (TT) bits */
+#define MMU060_TM (0x00070000) /* transfer modifier (TM) bits */
+#define MMU060_IO (0x00008000) /* instruction or operand */
+#define MMU060_PBE (0x00004000) /* push buffer bus error */
+#define MMU060_SBE (0x00002000) /* store buffer bus error */
+#define MMU060_PTA (0x00001000) /* pointer A fault */
+#define MMU060_PTB (0x00000800) /* pointer B fault */
+#define MMU060_IL (0x00000400) /* double indirect descr fault */
+#define MMU060_PF (0x00000200) /* page fault (invalid descr) */
+#define MMU060_SP (0x00000100) /* supervisor protection */
+#define MMU060_WP (0x00000080) /* write protection */
+#define MMU060_TWE (0x00000040) /* bus error on table search */
+#define MMU060_RE (0x00000020) /* bus error on read */
+#define MMU060_WE (0x00000010) /* bus error on write */
+#define MMU060_TTR (0x00000008) /* error caused by TTR translation */
+#define MMU060_BPE (0x00000004) /* branch prediction error */
+#define MMU060_SEE (0x00000001) /* software emulated error */
+
+/* cases of missing or invalid descriptors */
+#define MMU060_DESC_ERR (MMU060_PTA | MMU060_PTB | \
+ MMU060_IL | MMU060_PF)
+/* bits that indicate real errors */
+#define MMU060_ERR_BITS (MMU060_PBE | MMU060_SBE | MMU060_DESC_ERR | MMU060_SP | \
+ MMU060_WP | MMU060_TWE | MMU060_RE | MMU060_WE)
+
+/* structure for stack frames */
+
+struct frame {
+ struct pt_regs ptregs;
+ union {
+ struct {
+ unsigned long iaddr; /* instruction address */
+ } fmt2;
+ struct {
+ unsigned long effaddr; /* effective address */
+ } fmt3;
+ struct {
+ unsigned long effaddr; /* effective address */
+ unsigned long pc; /* pc of faulted instr */
+ } fmt4;
+ struct {
+ unsigned long effaddr; /* effective address */
+ unsigned short ssw; /* special status word */
+ unsigned short wb3s; /* write back 3 status */
+ unsigned short wb2s; /* write back 2 status */
+ unsigned short wb1s; /* write back 1 status */
+ unsigned long faddr; /* fault address */
+ unsigned long wb3a; /* write back 3 address */
+ unsigned long wb3d; /* write back 3 data */
+ unsigned long wb2a; /* write back 2 address */
+ unsigned long wb2d; /* write back 2 data */
+ unsigned long wb1a; /* write back 1 address */
+ unsigned long wb1dpd0; /* write back 1 data/push data 0*/
+ unsigned long pd1; /* push data 1*/
+ unsigned long pd2; /* push data 2*/
+ unsigned long pd3; /* push data 3*/
+ } fmt7;
+ struct {
+ unsigned long iaddr; /* instruction address */
+ unsigned short int1[4]; /* internal registers */
+ } fmt9;
+ struct {
+ unsigned short int1;
+ unsigned short ssw; /* special status word */
+ unsigned short isc; /* instruction stage c */
+ unsigned short isb; /* instruction stage b */
+ unsigned long daddr; /* data cycle fault address */
+ unsigned short int2[2];
+ unsigned long dobuf; /* data cycle output buffer */
+ unsigned short int3[2];
+ } fmta;
+ struct {
+ unsigned short int1;
+ unsigned short ssw; /* special status word */
+ unsigned short isc; /* instruction stage c */
+ unsigned short isb; /* instruction stage b */
+ unsigned long daddr; /* data cycle fault address */
+ unsigned short int2[2];
+ unsigned long dobuf; /* data cycle output buffer */
+ unsigned short int3[4];
+ unsigned long baddr; /* stage B address */
+ unsigned short int4[2];
+ unsigned long dibuf; /* data cycle input buffer */
+ unsigned short int5[3];
+ unsigned ver : 4; /* stack frame version # */
+ unsigned int6:12;
+ unsigned short int7[18];
+ } fmtb;
+ } un;
+};
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _M68K_TRAPS_H */
diff --git a/arch/m68k/include/asm/traps_mm.h b/arch/m68k/include/asm/traps_mm.h
deleted file mode 100644
index 8caef25624c7..000000000000
--- a/arch/m68k/include/asm/traps_mm.h
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
- * linux/include/asm/traps.h
- *
- * Copyright (C) 1993 Hamish Macdonald
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-#ifndef _M68K_TRAPS_H
-#define _M68K_TRAPS_H
-
-#ifndef __ASSEMBLY__
-
-#include <linux/linkage.h>
-#include <asm/ptrace.h>
-
-typedef void (*e_vector)(void);
-
-asmlinkage void auto_inthandler(void);
-asmlinkage void user_inthandler(void);
-asmlinkage void bad_inthandler(void);
-
-extern e_vector vectors[];
-
-#endif
-
-#define VEC_RESETSP (0)
-#define VEC_RESETPC (1)
-#define VEC_BUSERR (2)
-#define VEC_ADDRERR (3)
-#define VEC_ILLEGAL (4)
-#define VEC_ZERODIV (5)
-#define VEC_CHK (6)
-#define VEC_TRAP (7)
-#define VEC_PRIV (8)
-#define VEC_TRACE (9)
-#define VEC_LINE10 (10)
-#define VEC_LINE11 (11)
-#define VEC_RESV12 (12)
-#define VEC_COPROC (13)
-#define VEC_FORMAT (14)
-#define VEC_UNINT (15)
-#define VEC_RESV16 (16)
-#define VEC_RESV17 (17)
-#define VEC_RESV18 (18)
-#define VEC_RESV19 (19)
-#define VEC_RESV20 (20)
-#define VEC_RESV21 (21)
-#define VEC_RESV22 (22)
-#define VEC_RESV23 (23)
-#define VEC_SPUR (24)
-#define VEC_INT1 (25)
-#define VEC_INT2 (26)
-#define VEC_INT3 (27)
-#define VEC_INT4 (28)
-#define VEC_INT5 (29)
-#define VEC_INT6 (30)
-#define VEC_INT7 (31)
-#define VEC_SYS (32)
-#define VEC_TRAP1 (33)
-#define VEC_TRAP2 (34)
-#define VEC_TRAP3 (35)
-#define VEC_TRAP4 (36)
-#define VEC_TRAP5 (37)
-#define VEC_TRAP6 (38)
-#define VEC_TRAP7 (39)
-#define VEC_TRAP8 (40)
-#define VEC_TRAP9 (41)
-#define VEC_TRAP10 (42)
-#define VEC_TRAP11 (43)
-#define VEC_TRAP12 (44)
-#define VEC_TRAP13 (45)
-#define VEC_TRAP14 (46)
-#define VEC_TRAP15 (47)
-#define VEC_FPBRUC (48)
-#define VEC_FPIR (49)
-#define VEC_FPDIVZ (50)
-#define VEC_FPUNDER (51)
-#define VEC_FPOE (52)
-#define VEC_FPOVER (53)
-#define VEC_FPNAN (54)
-#define VEC_FPUNSUP (55)
-#define VEC_MMUCFG (56)
-#define VEC_MMUILL (57)
-#define VEC_MMUACC (58)
-#define VEC_RESV59 (59)
-#define VEC_UNIMPEA (60)
-#define VEC_UNIMPII (61)
-#define VEC_RESV62 (62)
-#define VEC_RESV63 (63)
-#define VEC_USER (64)
-
-#define VECOFF(vec) ((vec)<<2)
-
-#ifndef __ASSEMBLY__
-
-/* Status register bits */
-#define PS_T (0x8000)
-#define PS_S (0x2000)
-#define PS_M (0x1000)
-#define PS_C (0x0001)
-
-/* bits for 68020/68030 special status word */
-
-#define FC (0x8000)
-#define FB (0x4000)
-#define RC (0x2000)
-#define RB (0x1000)
-#define DF (0x0100)
-#define RM (0x0080)
-#define RW (0x0040)
-#define SZ (0x0030)
-#define DFC (0x0007)
-
-/* bits for 68030 MMU status register (mmusr,psr) */
-
-#define MMU_B (0x8000) /* bus error */
-#define MMU_L (0x4000) /* limit violation */
-#define MMU_S (0x2000) /* supervisor violation */
-#define MMU_WP (0x0800) /* write-protected */
-#define MMU_I (0x0400) /* invalid descriptor */
-#define MMU_M (0x0200) /* ATC entry modified */
-#define MMU_T (0x0040) /* transparent translation */
-#define MMU_NUM (0x0007) /* number of levels traversed */
-
-
-/* bits for 68040 special status word */
-#define CP_040 (0x8000)
-#define CU_040 (0x4000)
-#define CT_040 (0x2000)
-#define CM_040 (0x1000)
-#define MA_040 (0x0800)
-#define ATC_040 (0x0400)
-#define LK_040 (0x0200)
-#define RW_040 (0x0100)
-#define SIZ_040 (0x0060)
-#define TT_040 (0x0018)
-#define TM_040 (0x0007)
-
-/* bits for 68040 write back status word */
-#define WBV_040 (0x80)
-#define WBSIZ_040 (0x60)
-#define WBBYT_040 (0x20)
-#define WBWRD_040 (0x40)
-#define WBLNG_040 (0x00)
-#define WBTT_040 (0x18)
-#define WBTM_040 (0x07)
-
-/* bus access size codes */
-#define BA_SIZE_BYTE (0x20)
-#define BA_SIZE_WORD (0x40)
-#define BA_SIZE_LONG (0x00)
-#define BA_SIZE_LINE (0x60)
-
-/* bus access transfer type codes */
-#define BA_TT_MOVE16 (0x08)
-
-/* bits for 68040 MMU status register (mmusr) */
-#define MMU_B_040 (0x0800)
-#define MMU_G_040 (0x0400)
-#define MMU_S_040 (0x0080)
-#define MMU_CM_040 (0x0060)
-#define MMU_M_040 (0x0010)
-#define MMU_WP_040 (0x0004)
-#define MMU_T_040 (0x0002)
-#define MMU_R_040 (0x0001)
-
-/* bits in the 68060 fault status long word (FSLW) */
-#define MMU060_MA (0x08000000) /* misaligned */
-#define MMU060_LK (0x02000000) /* locked transfer */
-#define MMU060_RW (0x01800000) /* read/write */
-# define MMU060_RW_W (0x00800000) /* write */
-# define MMU060_RW_R (0x01000000) /* read */
-# define MMU060_RW_RMW (0x01800000) /* read/modify/write */
-# define MMU060_W (0x00800000) /* general write, includes rmw */
-#define MMU060_SIZ (0x00600000) /* transfer size */
-#define MMU060_TT (0x00180000) /* transfer type (TT) bits */
-#define MMU060_TM (0x00070000) /* transfer modifier (TM) bits */
-#define MMU060_IO (0x00008000) /* instruction or operand */
-#define MMU060_PBE (0x00004000) /* push buffer bus error */
-#define MMU060_SBE (0x00002000) /* store buffer bus error */
-#define MMU060_PTA (0x00001000) /* pointer A fault */
-#define MMU060_PTB (0x00000800) /* pointer B fault */
-#define MMU060_IL (0x00000400) /* double indirect descr fault */
-#define MMU060_PF (0x00000200) /* page fault (invalid descr) */
-#define MMU060_SP (0x00000100) /* supervisor protection */
-#define MMU060_WP (0x00000080) /* write protection */
-#define MMU060_TWE (0x00000040) /* bus error on table search */
-#define MMU060_RE (0x00000020) /* bus error on read */
-#define MMU060_WE (0x00000010) /* bus error on write */
-#define MMU060_TTR (0x00000008) /* error caused by TTR translation */
-#define MMU060_BPE (0x00000004) /* branch prediction error */
-#define MMU060_SEE (0x00000001) /* software emulated error */
-
-/* cases of missing or invalid descriptors */
-#define MMU060_DESC_ERR (MMU060_PTA | MMU060_PTB | \
- MMU060_IL | MMU060_PF)
-/* bits that indicate real errors */
-#define MMU060_ERR_BITS (MMU060_PBE | MMU060_SBE | MMU060_DESC_ERR | MMU060_SP | \
- MMU060_WP | MMU060_TWE | MMU060_RE | MMU060_WE)
-
-/* structure for stack frames */
-
-struct frame {
- struct pt_regs ptregs;
- union {
- struct {
- unsigned long iaddr; /* instruction address */
- } fmt2;
- struct {
- unsigned long effaddr; /* effective address */
- } fmt3;
- struct {
- unsigned long effaddr; /* effective address */
- unsigned long pc; /* pc of faulted instr */
- } fmt4;
- struct {
- unsigned long effaddr; /* effective address */
- unsigned short ssw; /* special status word */
- unsigned short wb3s; /* write back 3 status */
- unsigned short wb2s; /* write back 2 status */
- unsigned short wb1s; /* write back 1 status */
- unsigned long faddr; /* fault address */
- unsigned long wb3a; /* write back 3 address */
- unsigned long wb3d; /* write back 3 data */
- unsigned long wb2a; /* write back 2 address */
- unsigned long wb2d; /* write back 2 data */
- unsigned long wb1a; /* write back 1 address */
- unsigned long wb1dpd0; /* write back 1 data/push data 0*/
- unsigned long pd1; /* push data 1*/
- unsigned long pd2; /* push data 2*/
- unsigned long pd3; /* push data 3*/
- } fmt7;
- struct {
- unsigned long iaddr; /* instruction address */
- unsigned short int1[4]; /* internal registers */
- } fmt9;
- struct {
- unsigned short int1;
- unsigned short ssw; /* special status word */
- unsigned short isc; /* instruction stage c */
- unsigned short isb; /* instruction stage b */
- unsigned long daddr; /* data cycle fault address */
- unsigned short int2[2];
- unsigned long dobuf; /* data cycle output buffer */
- unsigned short int3[2];
- } fmta;
- struct {
- unsigned short int1;
- unsigned short ssw; /* special status word */
- unsigned short isc; /* instruction stage c */
- unsigned short isb; /* instruction stage b */
- unsigned long daddr; /* data cycle fault address */
- unsigned short int2[2];
- unsigned long dobuf; /* data cycle output buffer */
- unsigned short int3[4];
- unsigned long baddr; /* stage B address */
- unsigned short int4[2];
- unsigned long dibuf; /* data cycle input buffer */
- unsigned short int5[3];
- unsigned ver : 4; /* stack frame version # */
- unsigned int6:12;
- unsigned short int7[18];
- } fmtb;
- } un;
-};
-
-#endif /* __ASSEMBLY__ */
-
-#endif /* _M68K_TRAPS_H */
diff --git a/arch/m68k/include/asm/traps_no.h b/arch/m68k/include/asm/traps_no.h
deleted file mode 100644
index d0671e5f8e29..000000000000
--- a/arch/m68k/include/asm/traps_no.h
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * linux/include/asm/traps.h
- *
- * Copyright (C) 1993 Hamish Macdonald
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-#ifndef _M68KNOMMU_TRAPS_H
-#define _M68KNOMMU_TRAPS_H
-
-#ifndef __ASSEMBLY__
-
-typedef void (*e_vector)(void);
-
-extern e_vector vectors[];
-extern void init_vectors(void);
-extern void enable_vector(unsigned int irq);
-extern void disable_vector(unsigned int irq);
-extern void ack_vector(unsigned int irq);
-
-#endif
-
-#define VEC_BUSERR (2)
-#define VEC_ADDRERR (3)
-#define VEC_ILLEGAL (4)
-#define VEC_ZERODIV (5)
-#define VEC_CHK (6)
-#define VEC_TRAP (7)
-#define VEC_PRIV (8)
-#define VEC_TRACE (9)
-#define VEC_LINE10 (10)
-#define VEC_LINE11 (11)
-#define VEC_RESV1 (12)
-#define VEC_COPROC (13)
-#define VEC_FORMAT (14)
-#define VEC_UNINT (15)
-#define VEC_SPUR (24)
-#define VEC_INT1 (25)
-#define VEC_INT2 (26)
-#define VEC_INT3 (27)
-#define VEC_INT4 (28)
-#define VEC_INT5 (29)
-#define VEC_INT6 (30)
-#define VEC_INT7 (31)
-#define VEC_SYS (32)
-#define VEC_TRAP1 (33)
-#define VEC_TRAP2 (34)
-#define VEC_TRAP3 (35)
-#define VEC_TRAP4 (36)
-#define VEC_TRAP5 (37)
-#define VEC_TRAP6 (38)
-#define VEC_TRAP7 (39)
-#define VEC_TRAP8 (40)
-#define VEC_TRAP9 (41)
-#define VEC_TRAP10 (42)
-#define VEC_TRAP11 (43)
-#define VEC_TRAP12 (44)
-#define VEC_TRAP13 (45)
-#define VEC_TRAP14 (46)
-#define VEC_TRAP15 (47)
-#define VEC_FPBRUC (48)
-#define VEC_FPIR (49)
-#define VEC_FPDIVZ (50)
-#define VEC_FPUNDER (51)
-#define VEC_FPOE (52)
-#define VEC_FPOVER (53)
-#define VEC_FPNAN (54)
-#define VEC_FPUNSUP (55)
-#define VEC_UNIMPEA (60)
-#define VEC_UNIMPII (61)
-#define VEC_USER (64)
-
-#define VECOFF(vec) ((vec)<<2)
-
-#ifndef __ASSEMBLY__
-
-/* Status register bits */
-#define PS_T (0x8000)
-#define PS_S (0x2000)
-#define PS_M (0x1000)
-#define PS_C (0x0001)
-
-/* structure for stack frames */
-
-struct frame {
- struct pt_regs ptregs;
- union {
- struct {
- unsigned long iaddr; /* instruction address */
- } fmt2;
- struct {
- unsigned long effaddr; /* effective address */
- } fmt3;
- struct {
- unsigned long effaddr; /* effective address */
- unsigned long pc; /* pc of faulted instr */
- } fmt4;
- struct {
- unsigned long effaddr; /* effective address */
- unsigned short ssw; /* special status word */
- unsigned short wb3s; /* write back 3 status */
- unsigned short wb2s; /* write back 2 status */
- unsigned short wb1s; /* write back 1 status */
- unsigned long faddr; /* fault address */
- unsigned long wb3a; /* write back 3 address */
- unsigned long wb3d; /* write back 3 data */
- unsigned long wb2a; /* write back 2 address */
- unsigned long wb2d; /* write back 2 data */
- unsigned long wb1a; /* write back 1 address */
- unsigned long wb1dpd0; /* write back 1 data/push data 0*/
- unsigned long pd1; /* push data 1*/
- unsigned long pd2; /* push data 2*/
- unsigned long pd3; /* push data 3*/
- } fmt7;
- struct {
- unsigned long iaddr; /* instruction address */
- unsigned short int1[4]; /* internal registers */
- } fmt9;
- struct {
- unsigned short int1;
- unsigned short ssw; /* special status word */
- unsigned short isc; /* instruction stage c */
- unsigned short isb; /* instruction stage b */
- unsigned long daddr; /* data cycle fault address */
- unsigned short int2[2];
- unsigned long dobuf; /* data cycle output buffer */
- unsigned short int3[2];
- } fmta;
- struct {
- unsigned short int1;
- unsigned short ssw; /* special status word */
- unsigned short isc; /* instruction stage c */
- unsigned short isb; /* instruction stage b */
- unsigned long daddr; /* data cycle fault address */
- unsigned short int2[2];
- unsigned long dobuf; /* data cycle output buffer */
- unsigned short int3[4];
- unsigned long baddr; /* stage B address */
- unsigned short int4[2];
- unsigned long dibuf; /* data cycle input buffer */
- unsigned short int5[3];
- unsigned ver : 4; /* stack frame version # */
- unsigned int6:12;
- unsigned short int7[18];
- } fmtb;
- } un;
-};
-
-#endif /* __ASSEMBLY__ */
-
-#endif /* _M68KNOMMU_TRAPS_H */
diff --git a/arch/m68k/kernel/setup.c b/arch/m68k/kernel/setup.c
index 303730afb1c9..b3963ab3d149 100644
--- a/arch/m68k/kernel/setup.c
+++ b/arch/m68k/kernel/setup.c
@@ -359,12 +359,6 @@ void __init setup_arch(char **cmdline_p)
isa_type = ISA_TYPE_Q40;
isa_sex = 0;
}
-#ifdef CONFIG_GG2
- if (MACH_IS_AMIGA && AMIGAHW_PRESENT(GG2_ISA)) {
- isa_type = ISA_TYPE_GG2;
- isa_sex = 0;
- }
-#endif
#ifdef CONFIG_AMIGA_PCMCIA
if (MACH_IS_AMIGA && AMIGAHW_PRESENT(PCMCIA)) {
isa_type = ISA_TYPE_AG;
diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c
index 2f431ece7b5f..3db2e7f902aa 100644
--- a/arch/m68k/kernel/sys_m68k.c
+++ b/arch/m68k/kernel/sys_m68k.c
@@ -12,7 +12,6 @@
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/smp.h>
-#include <linux/smp_lock.h>
#include <linux/sem.h>
#include <linux/msg.h>
#include <linux/shm.h>
@@ -377,7 +376,6 @@ sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
struct vm_area_struct *vma;
int ret = -EINVAL;
- lock_kernel();
if (scope < FLUSH_SCOPE_LINE || scope > FLUSH_SCOPE_ALL ||
cache & ~FLUSH_CACHE_BOTH)
goto out;
@@ -446,7 +444,6 @@ sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
}
}
out:
- unlock_kernel();
return ret;
}
diff --git a/arch/m68k/kernel/time.c b/arch/m68k/kernel/time.c
index 4926b3856c15..06438dac08ff 100644
--- a/arch/m68k/kernel/time.c
+++ b/arch/m68k/kernel/time.c
@@ -42,9 +42,7 @@ static inline int set_rtc_mmss(unsigned long nowtime)
static irqreturn_t timer_interrupt(int irq, void *dummy)
{
do_timer(1);
-#ifndef CONFIG_SMP
update_process_times(user_mode(get_irq_regs()));
-#endif
profile_tick(CPU_PROFILING);
#ifdef CONFIG_HEARTBEAT
diff --git a/arch/m68k/mac/macboing.c b/arch/m68k/mac/macboing.c
index 8f0640847ad2..05285d08e547 100644
--- a/arch/m68k/mac/macboing.c
+++ b/arch/m68k/mac/macboing.c
@@ -162,7 +162,7 @@ static void mac_init_asc( void )
void mac_mksound( unsigned int freq, unsigned int length )
{
__u32 cfreq = ( freq << 5 ) / 468;
- __u32 flags;
+ unsigned long flags;
int i;
if ( mac_special_bell == NULL )
@@ -224,7 +224,7 @@ static void mac_nosound( unsigned long ignored )
*/
static void mac_quadra_start_bell( unsigned int freq, unsigned int length, unsigned int volume )
{
- __u32 flags;
+ unsigned long flags;
/* if the bell is already ringing, ring longer */
if ( mac_bell_duration > 0 )
@@ -271,7 +271,7 @@ static void mac_quadra_start_bell( unsigned int freq, unsigned int length, unsig
static void mac_quadra_ring_bell( unsigned long ignored )
{
int i, count = mac_asc_samplespersec / HZ;
- __u32 flags;
+ unsigned long flags;
/*
* we neither want a sound buffer overflow nor underflow, so we need to match
diff --git a/arch/m68k/mvme16x/rtc.c b/arch/m68k/mvme16x/rtc.c
index 11ac6f63967a..39c79ebcd18a 100644
--- a/arch/m68k/mvme16x/rtc.c
+++ b/arch/m68k/mvme16x/rtc.c
@@ -144,6 +144,7 @@ static const struct file_operations rtc_fops = {
.unlocked_ioctl = rtc_ioctl,
.open = rtc_open,
.release = rtc_release,
+ .llseek = noop_llseek,
};
static struct miscdevice rtc_dev=
diff --git a/arch/m68k/sun3/sun3ints.c b/arch/m68k/sun3/sun3ints.c
index ad90393a3361..2d9e21bd313a 100644
--- a/arch/m68k/sun3/sun3ints.c
+++ b/arch/m68k/sun3/sun3ints.c
@@ -67,9 +67,7 @@ static irqreturn_t sun3_int5(int irq, void *dev_id)
intersil_clear();
#endif
do_timer(1);
-#ifndef CONFIG_SMP
update_process_times(user_mode(get_irq_regs()));
-#endif
if (!(kstat_cpu(0).irqs[irq] % 20))
sun3_leds(led_pattern[(kstat_cpu(0).irqs[irq] % 160) / 20]);
return IRQ_HANDLED;
diff --git a/arch/m68knommu/kernel/asm-offsets.c b/arch/m68knommu/kernel/asm-offsets.c
index 9a8876f715d8..24335022fa2c 100644
--- a/arch/m68knommu/kernel/asm-offsets.c
+++ b/arch/m68knommu/kernel/asm-offsets.c
@@ -74,8 +74,6 @@ int main(void)
DEFINE(PT_PTRACED, PT_PTRACED);
- DEFINE(THREAD_SIZE, THREAD_SIZE);
-
/* Offsets in thread_info structure */
DEFINE(TI_TASK, offsetof(struct thread_info, task));
DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain));
diff --git a/arch/m68knommu/kernel/time.c b/arch/m68knommu/kernel/time.c
index a90acf5b0cde..7089dd9d843b 100644
--- a/arch/m68knommu/kernel/time.c
+++ b/arch/m68knommu/kernel/time.c
@@ -50,9 +50,8 @@ irqreturn_t arch_timer_interrupt(int irq, void *dummy)
write_sequnlock(&xtime_lock);
-#ifndef CONFIG_SMP
update_process_times(user_mode(get_irq_regs()));
-#endif
+
return(IRQ_HANDLED);
}
#endif
diff --git a/arch/m68knommu/platform/coldfire/entry.S b/arch/m68knommu/platform/coldfire/entry.S
index dd7d591f70ea..cd79d7e92ce6 100644
--- a/arch/m68knommu/platform/coldfire/entry.S
+++ b/arch/m68knommu/platform/coldfire/entry.S
@@ -112,7 +112,7 @@ ret_from_exception:
andl #-THREAD_SIZE,%d1 /* at base of kernel stack */
movel %d1,%a0
movel %a0@(TI_FLAGS),%d1 /* get thread_info->flags */
- andl #_TIF_NEED_RESCHED,%d1
+ andl #(1<<TIF_NEED_RESCHED),%d1
jeq Lkernel_return
movel %a0@(TI_PREEMPTCOUNT),%d1
@@ -136,7 +136,7 @@ Luser_return:
andl #-THREAD_SIZE,%d1 /* at base of kernel stack */
movel %d1,%a0
movel %a0@(TI_FLAGS),%d1 /* get thread_info->flags */
- andl #_TIF_WORK_MASK,%d1
+ andl #0xefff,%d1
jne Lwork_to_do /* still work to do */
Lreturn:
diff --git a/arch/m68knommu/platform/coldfire/head.S b/arch/m68knommu/platform/coldfire/head.S
index 4b91aa24eb00..0b2d7c7adf79 100644
--- a/arch/m68knommu/platform/coldfire/head.S
+++ b/arch/m68knommu/platform/coldfire/head.S
@@ -15,6 +15,7 @@
#include <asm/coldfire.h>
#include <asm/mcfcache.h>
#include <asm/mcfsim.h>
+#include <asm/thread_info.h>
/*****************************************************************************/
diff --git a/arch/microblaze/include/asm/irqflags.h b/arch/microblaze/include/asm/irqflags.h
index 2c38c6d80176..5fd31905775d 100644
--- a/arch/microblaze/include/asm/irqflags.h
+++ b/arch/microblaze/include/asm/irqflags.h
@@ -9,103 +9,114 @@
#ifndef _ASM_MICROBLAZE_IRQFLAGS_H
#define _ASM_MICROBLAZE_IRQFLAGS_H
-#include <linux/irqflags.h>
+#include <linux/types.h>
#include <asm/registers.h>
-# if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR
-
-# define raw_local_irq_save(flags) \
- do { \
- asm volatile (" msrclr %0, %1; \
- nop;" \
- : "=r"(flags) \
- : "i"(MSR_IE) \
- : "memory"); \
- } while (0)
-
-# define raw_local_irq_disable() \
- do { \
- asm volatile (" msrclr r0, %0; \
- nop;" \
- : \
- : "i"(MSR_IE) \
- : "memory"); \
- } while (0)
-
-# define raw_local_irq_enable() \
- do { \
- asm volatile (" msrset r0, %0; \
- nop;" \
- : \
- : "i"(MSR_IE) \
- : "memory"); \
- } while (0)
-
-# else /* CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR == 0 */
-
-# define raw_local_irq_save(flags) \
- do { \
- register unsigned tmp; \
- asm volatile (" mfs %0, rmsr; \
- nop; \
- andi %1, %0, %2; \
- mts rmsr, %1; \
- nop;" \
- : "=r"(flags), "=r" (tmp) \
- : "i"(~MSR_IE) \
- : "memory"); \
- } while (0)
-
-# define raw_local_irq_disable() \
- do { \
- register unsigned tmp; \
- asm volatile (" mfs %0, rmsr; \
- nop; \
- andi %0, %0, %1; \
- mts rmsr, %0; \
- nop;" \
- : "=r"(tmp) \
- : "i"(~MSR_IE) \
- : "memory"); \
- } while (0)
-
-# define raw_local_irq_enable() \
- do { \
- register unsigned tmp; \
- asm volatile (" mfs %0, rmsr; \
- nop; \
- ori %0, %0, %1; \
- mts rmsr, %0; \
- nop;" \
- : "=r"(tmp) \
- : "i"(MSR_IE) \
- : "memory"); \
- } while (0)
-
-# endif /* CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR */
-
-#define raw_local_irq_restore(flags) \
- do { \
- asm volatile (" mts rmsr, %0; \
- nop;" \
- : \
- : "r"(flags) \
- : "memory"); \
- } while (0)
-
-static inline unsigned long get_msr(void)
+#ifdef CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR
+
+static inline unsigned long arch_local_irq_save(void)
+{
+ unsigned long flags;
+ asm volatile(" msrclr %0, %1 \n"
+ " nop \n"
+ : "=r"(flags)
+ : "i"(MSR_IE)
+ : "memory");
+ return flags;
+}
+
+static inline void arch_local_irq_disable(void)
+{
+ /* this uses r0 without declaring it - is that correct? */
+ asm volatile(" msrclr r0, %0 \n"
+ " nop \n"
+ :
+ : "i"(MSR_IE)
+ : "memory");
+}
+
+static inline void arch_local_irq_enable(void)
+{
+ /* this uses r0 without declaring it - is that correct? */
+ asm volatile(" msrset r0, %0 \n"
+ " nop \n"
+ :
+ : "i"(MSR_IE)
+ : "memory");
+}
+
+#else /* !CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR */
+
+static inline unsigned long arch_local_irq_save(void)
+{
+ unsigned long flags, tmp;
+ asm volatile (" mfs %0, rmsr \n"
+ " nop \n"
+ " andi %1, %0, %2 \n"
+ " mts rmsr, %1 \n"
+ " nop \n"
+ : "=r"(flags), "=r"(tmp)
+ : "i"(~MSR_IE)
+ : "memory");
+ return flags;
+}
+
+static inline void arch_local_irq_disable(void)
+{
+ unsigned long tmp;
+ asm volatile(" mfs %0, rmsr \n"
+ " nop \n"
+ " andi %0, %0, %1 \n"
+ " mts rmsr, %0 \n"
+ " nop \n"
+ : "=r"(tmp)
+ : "i"(~MSR_IE)
+ : "memory");
+}
+
+static inline void arch_local_irq_enable(void)
+{
+ unsigned long tmp;
+ asm volatile(" mfs %0, rmsr \n"
+ " nop \n"
+ " ori %0, %0, %1 \n"
+ " mts rmsr, %0 \n"
+ " nop \n"
+ : "=r"(tmp)
+ : "i"(MSR_IE)
+ : "memory");
+}
+
+#endif /* CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR */
+
+static inline unsigned long arch_local_save_flags(void)
{
unsigned long flags;
- asm volatile (" mfs %0, rmsr; \
- nop;" \
- : "=r"(flags) \
- : \
- : "memory"); \
+ asm volatile(" mfs %0, rmsr \n"
+ " nop \n"
+ : "=r"(flags)
+ :
+ : "memory");
return flags;
}
-#define raw_local_save_flags(flags) ((flags) = get_msr())
-#define raw_irqs_disabled() ((get_msr() & MSR_IE) == 0)
-#define raw_irqs_disabled_flags(flags) ((flags & MSR_IE) == 0)
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+ asm volatile(" mts rmsr, %0 \n"
+ " nop \n"
+ :
+ : "r"(flags)
+ : "memory");
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+ return (flags & MSR_IE) == 0;
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+ return arch_irqs_disabled_flags(arch_local_save_flags());
+}
#endif /* _ASM_MICROBLAZE_IRQFLAGS_H */
diff --git a/arch/microblaze/include/asm/memblock.h b/arch/microblaze/include/asm/memblock.h
index f9c2fa331d2a..20a8e257c77f 100644
--- a/arch/microblaze/include/asm/memblock.h
+++ b/arch/microblaze/include/asm/memblock.h
@@ -9,9 +9,6 @@
#ifndef _ASM_MICROBLAZE_MEMBLOCK_H
#define _ASM_MICROBLAZE_MEMBLOCK_H
-/* MEMBLOCK limit is OFF */
-#define MEMBLOCK_REAL_LIMIT 0xFFFFFFFF
-
#endif /* _ASM_MICROBLAZE_MEMBLOCK_H */
diff --git a/arch/microblaze/mm/init.c b/arch/microblaze/mm/init.c
index 65eb00419d19..c8437866d3b7 100644
--- a/arch/microblaze/mm/init.c
+++ b/arch/microblaze/mm/init.c
@@ -70,16 +70,16 @@ static void __init paging_init(void)
void __init setup_memory(void)
{
- int i;
unsigned long map_size;
+ struct memblock_region *reg;
+
#ifndef CONFIG_MMU
u32 kernel_align_start, kernel_align_size;
/* Find main memory where is the kernel */
- for (i = 0; i < memblock.memory.cnt; i++) {
- memory_start = (u32) memblock.memory.region[i].base;
- memory_end = (u32) memblock.memory.region[i].base
- + (u32) memblock.memory.region[i].size;
+ for_each_memblock(memory, reg) {
+ memory_start = (u32)reg->base;
+ memory_end = (u32) reg->base + reg->size;
if ((memory_start <= (u32)_text) &&
((u32)_text <= memory_end)) {
memory_size = memory_end - memory_start;
@@ -142,12 +142,10 @@ void __init setup_memory(void)
free_bootmem(memory_start, memory_size);
/* reserve allocate blocks */
- for (i = 0; i < memblock.reserved.cnt; i++) {
- pr_debug("reserved %d - 0x%08x-0x%08x\n", i,
- (u32) memblock.reserved.region[i].base,
- (u32) memblock_size_bytes(&memblock.reserved, i));
- reserve_bootmem(memblock.reserved.region[i].base,
- memblock_size_bytes(&memblock.reserved, i) - 1, BOOTMEM_DEFAULT);
+ for_each_memblock(reserved, reg) {
+ pr_debug("reserved - 0x%08x-0x%08x\n",
+ (u32) reg->base, (u32) reg->size);
+ reserve_bootmem(reg->base, reg->size, BOOTMEM_DEFAULT);
}
#ifdef CONFIG_MMU
init_bootmem_done = 1;
@@ -230,7 +228,7 @@ static void mm_cmdline_setup(void)
if (maxmem && memory_size > maxmem) {
memory_size = maxmem;
memory_end = memory_start + memory_size;
- memblock.memory.region[0].size = memory_size;
+ memblock.memory.regions[0].size = memory_size;
}
}
}
@@ -273,14 +271,14 @@ asmlinkage void __init mmu_init(void)
machine_restart(NULL);
}
- if ((u32) memblock.memory.region[0].size < 0x1000000) {
+ if ((u32) memblock.memory.regions[0].size < 0x1000000) {
printk(KERN_EMERG "Memory must be greater than 16MB\n");
machine_restart(NULL);
}
/* Find main memory where the kernel is */
- memory_start = (u32) memblock.memory.region[0].base;
- memory_end = (u32) memblock.memory.region[0].base +
- (u32) memblock.memory.region[0].size;
+ memory_start = (u32) memblock.memory.regions[0].base;
+ memory_end = (u32) memblock.memory.regions[0].base +
+ (u32) memblock.memory.regions[0].size;
memory_size = memory_end - memory_start;
mm_cmdline_setup(); /* FIXME parse args from command line - not used */
diff --git a/arch/mips/Kbuild b/arch/mips/Kbuild
index e322d65f33a4..7dd65cfae837 100644
--- a/arch/mips/Kbuild
+++ b/arch/mips/Kbuild
@@ -7,6 +7,10 @@ subdir-ccflags-y := -Werror
include arch/mips/Kbuild.platforms
obj-y := $(platform-y)
+# make clean traverses $(obj-) without having included .config, so
+# everything ends up here
+obj- := $(platform-)
+
# mips object files
# The object files are linked as core-y files would be linked
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 3ad59dde4852..4c9f402295dd 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -13,6 +13,7 @@ config MIPS
select HAVE_KPROBES
select HAVE_KRETPROBES
select RTC_LIB if !MACH_LOONGSON
+ select GENERIC_ATOMIC64 if !64BIT
mainmenu "Linux/MIPS Kernel Configuration"
@@ -880,11 +881,15 @@ config NO_IOPORT
config GENERIC_ISA_DMA
bool
select ZONE_DMA if GENERIC_ISA_DMA_SUPPORT_BROKEN=n
+ select ISA_DMA_API
config GENERIC_ISA_DMA_SUPPORT_BROKEN
bool
select GENERIC_ISA_DMA
+config ISA_DMA_API
+ bool
+
config GENERIC_GPIO
bool
@@ -1646,8 +1651,16 @@ config MIPS_MT_SMP
select SYS_SUPPORTS_SMP
select SMP_UP
help
- This is a kernel model which is also known a VSMP or lately
- has been marketesed into SMVP.
+ This is a kernel model which is known a VSMP but lately has been
+ marketesed into SMVP.
+ Virtual SMP uses the processor's VPEs to implement virtual
+ processors. In currently available configuration of the 34K processor
+ this allows for a dual processor. Both processors will share the same
+ primary caches; each will obtain the half of the TLB for it's own
+ exclusive use. For a layman this model can be described as similar to
+ what Intel calls Hyperthreading.
+
+ For further information see http://www.linux-mips.org/wiki/34K#VSMP
config MIPS_MT_SMTC
bool "SMTC: Use all TCs on all VPEs for SMP"
@@ -1664,6 +1677,14 @@ config MIPS_MT_SMTC
help
This is a kernel model which is known a SMTC or lately has been
marketesed into SMVP.
+ is presenting the available TC's of the core as processors to Linux.
+ On currently available 34K processors this means a Linux system will
+ see up to 5 processors. The implementation of the SMTC kernel differs
+ significantly from VSMP and cannot efficiently coexist in the same
+ kernel binary so the choice between VSMP and SMTC is a compile time
+ decision.
+
+ For further information see http://www.linux-mips.org/wiki/34K#SMTC
endchoice
diff --git a/arch/mips/alchemy/common/platform.c b/arch/mips/alchemy/common/platform.c
index 1dc55ee2681b..3691630931d6 100644
--- a/arch/mips/alchemy/common/platform.c
+++ b/arch/mips/alchemy/common/platform.c
@@ -24,6 +24,33 @@
#include <prom.h>
+static void alchemy_8250_pm(struct uart_port *port, unsigned int state,
+ unsigned int old_state)
+{
+ switch (state) {
+ case 0:
+ if ((__raw_readl(port->membase + UART_MOD_CNTRL) & 3) != 3) {
+ /* power-on sequence as suggested in the databooks */
+ __raw_writel(0, port->membase + UART_MOD_CNTRL);
+ wmb();
+ __raw_writel(1, port->membase + UART_MOD_CNTRL);
+ wmb();
+ }
+ __raw_writel(3, port->membase + UART_MOD_CNTRL); /* full on */
+ wmb();
+ serial8250_do_pm(port, state, old_state);
+ break;
+ case 3: /* power off */
+ serial8250_do_pm(port, state, old_state);
+ __raw_writel(0, port->membase + UART_MOD_CNTRL);
+ wmb();
+ break;
+ default:
+ serial8250_do_pm(port, state, old_state);
+ break;
+ }
+}
+
#define PORT(_base, _irq) \
{ \
.mapbase = _base, \
@@ -33,6 +60,7 @@
.flags = UPF_SKIP_TEST | UPF_IOREMAP | \
UPF_FIXED_TYPE, \
.type = PORT_16550A, \
+ .pm = alchemy_8250_pm, \
}
static struct plat_serial8250_port au1x00_uart_data[] = {
diff --git a/arch/mips/alchemy/common/power.c b/arch/mips/alchemy/common/power.c
index 5ef06a164a82..e5916a516e58 100644
--- a/arch/mips/alchemy/common/power.c
+++ b/arch/mips/alchemy/common/power.c
@@ -49,11 +49,6 @@
* We only have to save/restore registers that aren't otherwise
* done as part of a driver pm_* function.
*/
-static unsigned int sleep_uart0_inten;
-static unsigned int sleep_uart0_fifoctl;
-static unsigned int sleep_uart0_linectl;
-static unsigned int sleep_uart0_clkdiv;
-static unsigned int sleep_uart0_enable;
static unsigned int sleep_usb[2];
static unsigned int sleep_sys_clocks[5];
static unsigned int sleep_sys_pinfunc;
@@ -62,22 +57,6 @@ static unsigned int sleep_static_memctlr[4][3];
static void save_core_regs(void)
{
- extern void save_au1xxx_intctl(void);
- extern void pm_eth0_shutdown(void);
-
- /*
- * Do the serial ports.....these really should be a pm_*
- * registered function by the driver......but of course the
- * standard serial driver doesn't understand our Au1xxx
- * unique registers.
- */
- sleep_uart0_inten = au_readl(UART0_ADDR + UART_IER);
- sleep_uart0_fifoctl = au_readl(UART0_ADDR + UART_FCR);
- sleep_uart0_linectl = au_readl(UART0_ADDR + UART_LCR);
- sleep_uart0_clkdiv = au_readl(UART0_ADDR + UART_CLK);
- sleep_uart0_enable = au_readl(UART0_ADDR + UART_MOD_CNTRL);
- au_sync();
-
#ifndef CONFIG_SOC_AU1200
/* Shutdown USB host/device. */
sleep_usb[0] = au_readl(USB_HOST_CONFIG);
@@ -175,20 +154,6 @@ static void restore_core_regs(void)
au_writel(sleep_static_memctlr[3][0], MEM_STCFG3);
au_writel(sleep_static_memctlr[3][1], MEM_STTIME3);
au_writel(sleep_static_memctlr[3][2], MEM_STADDR3);
-
- /*
- * Enable the UART if it was enabled before sleep.
- * I guess I should define module control bits........
- */
- if (sleep_uart0_enable & 0x02) {
- au_writel(0, UART0_ADDR + UART_MOD_CNTRL); au_sync();
- au_writel(1, UART0_ADDR + UART_MOD_CNTRL); au_sync();
- au_writel(3, UART0_ADDR + UART_MOD_CNTRL); au_sync();
- au_writel(sleep_uart0_inten, UART0_ADDR + UART_IER); au_sync();
- au_writel(sleep_uart0_fifoctl, UART0_ADDR + UART_FCR); au_sync();
- au_writel(sleep_uart0_linectl, UART0_ADDR + UART_LCR); au_sync();
- au_writel(sleep_uart0_clkdiv, UART0_ADDR + UART_CLK); au_sync();
- }
}
void au_sleep(void)
diff --git a/arch/mips/alchemy/common/prom.c b/arch/mips/alchemy/common/prom.c
index c29511b11d44..534021059629 100644
--- a/arch/mips/alchemy/common/prom.c
+++ b/arch/mips/alchemy/common/prom.c
@@ -43,7 +43,7 @@ int prom_argc;
char **prom_argv;
char **prom_envp;
-void prom_init_cmdline(void)
+void __init prom_init_cmdline(void)
{
int i;
@@ -104,7 +104,7 @@ static inline void str2eaddr(unsigned char *ea, unsigned char *str)
}
}
-int prom_get_ethernet_addr(char *ethernet_addr)
+int __init prom_get_ethernet_addr(char *ethernet_addr)
{
char *ethaddr_str;
@@ -123,7 +123,6 @@ int prom_get_ethernet_addr(char *ethernet_addr)
return 0;
}
-EXPORT_SYMBOL(prom_get_ethernet_addr);
void __init prom_free_prom_memory(void)
{
diff --git a/arch/mips/alchemy/devboards/bcsr.c b/arch/mips/alchemy/devboards/bcsr.c
index 3bc4fd2155d7..c52af8821da0 100644
--- a/arch/mips/alchemy/devboards/bcsr.c
+++ b/arch/mips/alchemy/devboards/bcsr.c
@@ -10,6 +10,7 @@
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/spinlock.h>
+#include <linux/irq.h>
#include <asm/addrspace.h>
#include <asm/io.h>
#include <asm/mach-db1x00/bcsr.h>
diff --git a/arch/mips/ar7/irq.c b/arch/mips/ar7/irq.c
index c781556c44e4..4ec2642c568f 100644
--- a/arch/mips/ar7/irq.c
+++ b/arch/mips/ar7/irq.c
@@ -19,6 +19,7 @@
#include <linux/interrupt.h>
#include <linux/io.h>
+#include <linux/irq.h>
#include <asm/irq_cpu.h>
#include <asm/mipsregs.h>
diff --git a/arch/mips/bcm63xx/irq.c b/arch/mips/bcm63xx/irq.c
index a0c5cd18c192..3be87f2422f0 100644
--- a/arch/mips/bcm63xx/irq.c
+++ b/arch/mips/bcm63xx/irq.c
@@ -11,6 +11,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/module.h>
+#include <linux/irq.h>
#include <asm/irq_cpu.h>
#include <asm/mipsregs.h>
#include <bcm63xx_cpu.h>
diff --git a/arch/mips/boot/compressed/Makefile b/arch/mips/boot/compressed/Makefile
index ed9bb709c9a3..5042d51b0512 100644
--- a/arch/mips/boot/compressed/Makefile
+++ b/arch/mips/boot/compressed/Makefile
@@ -59,7 +59,7 @@ $(obj)/piggy.o: $(obj)/dummy.o $(obj)/vmlinux.bin.z FORCE
hostprogs-y := calc_vmlinuz_load_addr
VMLINUZ_LOAD_ADDRESS = $(shell $(obj)/calc_vmlinuz_load_addr \
- $(objtree)/$(KBUILD_IMAGE) $(VMLINUX_LOAD_ADDRESS))
+ $(obj)/vmlinux.bin $(VMLINUX_LOAD_ADDRESS))
vmlinuzobjs-y += $(obj)/piggy.o
@@ -105,4 +105,4 @@ OBJCOPYFLAGS_vmlinuz.srec := $(OBJCOPYFLAGS) -S -O srec
vmlinuz.srec: vmlinuz
$(call cmd,objcopy)
-clean-files := $(objtree)/vmlinuz.*
+clean-files := $(objtree)/vmlinuz $(objtree)/vmlinuz.{32,ecoff,bin,srec}
diff --git a/arch/mips/cavium-octeon/Kconfig b/arch/mips/cavium-octeon/Kconfig
index 094c17e38e16..47323ca452dc 100644
--- a/arch/mips/cavium-octeon/Kconfig
+++ b/arch/mips/cavium-octeon/Kconfig
@@ -83,3 +83,7 @@ config ARCH_SPARSEMEM_ENABLE
def_bool y
select SPARSEMEM_STATIC
depends on CPU_CAVIUM_OCTEON
+
+config CAVIUM_OCTEON_HELPER
+ def_bool y
+ depends on OCTEON_ETHERNET || PCI
diff --git a/arch/mips/cavium-octeon/cpu.c b/arch/mips/cavium-octeon/cpu.c
index c664c8cc2b42..a5b427909b5c 100644
--- a/arch/mips/cavium-octeon/cpu.c
+++ b/arch/mips/cavium-octeon/cpu.c
@@ -41,7 +41,7 @@ static int cnmips_cu2_call(struct notifier_block *nfb, unsigned long action,
return NOTIFY_OK; /* Let default notifier send signals */
}
-static int cnmips_cu2_setup(void)
+static int __init cnmips_cu2_setup(void)
{
return cu2_notifier(cnmips_cu2_call, 0);
}
diff --git a/arch/mips/cavium-octeon/executive/Makefile b/arch/mips/cavium-octeon/executive/Makefile
index 2fd66db6939e..7f41c5be2190 100644
--- a/arch/mips/cavium-octeon/executive/Makefile
+++ b/arch/mips/cavium-octeon/executive/Makefile
@@ -11,4 +11,4 @@
obj-y += cvmx-bootmem.o cvmx-l2c.o cvmx-sysinfo.o octeon-model.o
-obj-$(CONFIG_PCI) += cvmx-helper-errata.o cvmx-helper-jtag.o
+obj-$(CONFIG_CAVIUM_OCTEON_HELPER) += cvmx-helper-errata.o cvmx-helper-jtag.o
diff --git a/arch/mips/cavium-octeon/serial.c b/arch/mips/cavium-octeon/serial.c
index 638adab02842..12dbf533b77d 100644
--- a/arch/mips/cavium-octeon/serial.c
+++ b/arch/mips/cavium-octeon/serial.c
@@ -13,6 +13,7 @@
#include <linux/serial_8250.h>
#include <linux/serial_reg.h>
#include <linux/tty.h>
+#include <linux/irq.h>
#include <asm/time.h>
diff --git a/arch/mips/dec/Platform b/arch/mips/dec/Platform
index 3adbcbd95db1..cf55a6f4e720 100644
--- a/arch/mips/dec/Platform
+++ b/arch/mips/dec/Platform
@@ -1,7 +1,7 @@
#
# DECstation family
#
-platform-$(CONFIG_MACH_DECSTATION) = dec/
+platform-$(CONFIG_MACH_DECSTATION) += dec/
cflags-$(CONFIG_MACH_DECSTATION) += \
-I$(srctree)/arch/mips/include/asm/mach-dec
libs-$(CONFIG_MACH_DECSTATION) += arch/mips/dec/prom/
diff --git a/arch/mips/dec/setup.c b/arch/mips/dec/setup.c
index bd5431e1f408..fa45e924be05 100644
--- a/arch/mips/dec/setup.c
+++ b/arch/mips/dec/setup.c
@@ -18,6 +18,7 @@
#include <linux/spinlock.h>
#include <linux/types.h>
#include <linux/pm.h>
+#include <linux/irq.h>
#include <asm/bootinfo.h>
#include <asm/cpu.h>
diff --git a/arch/mips/include/asm/atomic.h b/arch/mips/include/asm/atomic.h
index c63c56bfd184..47d87da379f9 100644
--- a/arch/mips/include/asm/atomic.h
+++ b/arch/mips/include/asm/atomic.h
@@ -782,6 +782,10 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
*/
#define atomic64_add_negative(i, v) (atomic64_add_return(i, (v)) < 0)
+#else /* !CONFIG_64BIT */
+
+#include <asm-generic/atomic64.h>
+
#endif /* CONFIG_64BIT */
/*
diff --git a/arch/mips/include/asm/cop2.h b/arch/mips/include/asm/cop2.h
index 2cb2f0c2c4f8..3532e2c5f098 100644
--- a/arch/mips/include/asm/cop2.h
+++ b/arch/mips/include/asm/cop2.h
@@ -24,7 +24,7 @@ extern int cu2_notifier_call_chain(unsigned long val, void *v);
#define cu2_notifier(fn, pri) \
({ \
- static struct notifier_block fn##_nb __cpuinitdata = { \
+ static struct notifier_block fn##_nb = { \
.notifier_call = fn, \
.priority = pri \
}; \
diff --git a/arch/mips/include/asm/fcntl.h b/arch/mips/include/asm/fcntl.h
index e482fe90fe88..75eddedcfc3e 100644
--- a/arch/mips/include/asm/fcntl.h
+++ b/arch/mips/include/asm/fcntl.h
@@ -56,6 +56,7 @@
*/
#ifdef CONFIG_32BIT
+#include <linux/types.h>
struct flock {
short l_type;
diff --git a/arch/mips/include/asm/gic.h b/arch/mips/include/asm/gic.h
index 9b9436a4d816..86548da650e7 100644
--- a/arch/mips/include/asm/gic.h
+++ b/arch/mips/include/asm/gic.h
@@ -321,6 +321,7 @@ struct gic_intrmask_regs {
*/
struct gic_intr_map {
unsigned int cpunum; /* Directed to this CPU */
+#define GIC_UNUSED 0xdead /* Dummy data */
unsigned int pin; /* Directed to this Pin */
unsigned int polarity; /* Polarity : +/- */
unsigned int trigtype; /* Trigger : Edge/Levl */
diff --git a/arch/mips/include/asm/irqflags.h b/arch/mips/include/asm/irqflags.h
index 701ec0ba8fa9..9ef3b0d17896 100644
--- a/arch/mips/include/asm/irqflags.h
+++ b/arch/mips/include/asm/irqflags.h
@@ -17,7 +17,7 @@
#include <asm/hazards.h>
__asm__(
- " .macro raw_local_irq_enable \n"
+ " .macro arch_local_irq_enable \n"
" .set push \n"
" .set reorder \n"
" .set noat \n"
@@ -40,7 +40,7 @@ __asm__(
extern void smtc_ipi_replay(void);
-static inline void raw_local_irq_enable(void)
+static inline void arch_local_irq_enable(void)
{
#ifdef CONFIG_MIPS_MT_SMTC
/*
@@ -50,7 +50,7 @@ static inline void raw_local_irq_enable(void)
smtc_ipi_replay();
#endif
__asm__ __volatile__(
- "raw_local_irq_enable"
+ "arch_local_irq_enable"
: /* no outputs */
: /* no inputs */
: "memory");
@@ -76,7 +76,7 @@ static inline void raw_local_irq_enable(void)
* Workaround: mask EXL bit of the result or place a nop before mfc0.
*/
__asm__(
- " .macro raw_local_irq_disable\n"
+ " .macro arch_local_irq_disable\n"
" .set push \n"
" .set noat \n"
#ifdef CONFIG_MIPS_MT_SMTC
@@ -97,17 +97,17 @@ __asm__(
" .set pop \n"
" .endm \n");
-static inline void raw_local_irq_disable(void)
+static inline void arch_local_irq_disable(void)
{
__asm__ __volatile__(
- "raw_local_irq_disable"
+ "arch_local_irq_disable"
: /* no outputs */
: /* no inputs */
: "memory");
}
__asm__(
- " .macro raw_local_save_flags flags \n"
+ " .macro arch_local_save_flags flags \n"
" .set push \n"
" .set reorder \n"
#ifdef CONFIG_MIPS_MT_SMTC
@@ -118,13 +118,15 @@ __asm__(
" .set pop \n"
" .endm \n");
-#define raw_local_save_flags(x) \
-__asm__ __volatile__( \
- "raw_local_save_flags %0" \
- : "=r" (x))
+static inline unsigned long arch_local_save_flags(void)
+{
+ unsigned long flags;
+ asm volatile("arch_local_save_flags %0" : "=r" (flags));
+ return flags;
+}
__asm__(
- " .macro raw_local_irq_save result \n"
+ " .macro arch_local_irq_save result \n"
" .set push \n"
" .set reorder \n"
" .set noat \n"
@@ -148,15 +150,18 @@ __asm__(
" .set pop \n"
" .endm \n");
-#define raw_local_irq_save(x) \
-__asm__ __volatile__( \
- "raw_local_irq_save\t%0" \
- : "=r" (x) \
- : /* no inputs */ \
- : "memory")
+static inline unsigned long arch_local_irq_save(void)
+{
+ unsigned long flags;
+ asm volatile("arch_local_irq_save\t%0"
+ : "=r" (flags)
+ : /* no inputs */
+ : "memory");
+ return flags;
+}
__asm__(
- " .macro raw_local_irq_restore flags \n"
+ " .macro arch_local_irq_restore flags \n"
" .set push \n"
" .set noreorder \n"
" .set noat \n"
@@ -196,7 +201,7 @@ __asm__(
" .endm \n");
-static inline void raw_local_irq_restore(unsigned long flags)
+static inline void arch_local_irq_restore(unsigned long flags)
{
unsigned long __tmp1;
@@ -211,24 +216,24 @@ static inline void raw_local_irq_restore(unsigned long flags)
#endif
__asm__ __volatile__(
- "raw_local_irq_restore\t%0"
+ "arch_local_irq_restore\t%0"
: "=r" (__tmp1)
: "0" (flags)
: "memory");
}
-static inline void __raw_local_irq_restore(unsigned long flags)
+static inline void __arch_local_irq_restore(unsigned long flags)
{
unsigned long __tmp1;
__asm__ __volatile__(
- "raw_local_irq_restore\t%0"
+ "arch_local_irq_restore\t%0"
: "=r" (__tmp1)
: "0" (flags)
: "memory");
}
-static inline int raw_irqs_disabled_flags(unsigned long flags)
+static inline int arch_irqs_disabled_flags(unsigned long flags)
{
#ifdef CONFIG_MIPS_MT_SMTC
/*
diff --git a/arch/mips/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson/loongson.h
index cb6985f24303..1e29b9dd1d73 100644
--- a/arch/mips/include/asm/mach-loongson/loongson.h
+++ b/arch/mips/include/asm/mach-loongson/loongson.h
@@ -13,6 +13,7 @@
#include <linux/io.h>
#include <linux/init.h>
+#include <linux/irq.h>
/* loongson internal northbridge initialization */
extern void bonito_irq_init(void);
diff --git a/arch/mips/include/asm/mach-tx49xx/kmalloc.h b/arch/mips/include/asm/mach-tx49xx/kmalloc.h
index b74caf65482b..ff9a8b86cb93 100644
--- a/arch/mips/include/asm/mach-tx49xx/kmalloc.h
+++ b/arch/mips/include/asm/mach-tx49xx/kmalloc.h
@@ -1,6 +1,6 @@
#ifndef __ASM_MACH_TX49XX_KMALLOC_H
#define __ASM_MACH_TX49XX_KMALLOC_H
-#define ARCH_KMALLOC_MINALIGN L1_CACHE_BYTES
+#define ARCH_DMA_MINALIGN L1_CACHE_BYTES
#endif /* __ASM_MACH_TX49XX_KMALLOC_H */
diff --git a/arch/mips/include/asm/mips-boards/maltaint.h b/arch/mips/include/asm/mips-boards/maltaint.h
index cea872fc6f5c..d11aa02a956a 100644
--- a/arch/mips/include/asm/mips-boards/maltaint.h
+++ b/arch/mips/include/asm/mips-boards/maltaint.h
@@ -88,9 +88,6 @@
#define GIC_EXT_INTR(x) x
-/* Dummy data */
-#define X 0xdead
-
/* External Interrupts used for IPI */
#define GIC_IPI_EXT_INTR_RESCHED_VPE0 16
#define GIC_IPI_EXT_INTR_CALLFNC_VPE0 17
diff --git a/arch/mips/include/asm/page.h b/arch/mips/include/asm/page.h
index a16beafcea91..e59cd1ac09c2 100644
--- a/arch/mips/include/asm/page.h
+++ b/arch/mips/include/asm/page.h
@@ -150,6 +150,20 @@ typedef struct { unsigned long pgprot; } pgprot_t;
((unsigned long)(x) - PAGE_OFFSET + PHYS_OFFSET)
#endif
#define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET - PHYS_OFFSET))
+
+/*
+ * RELOC_HIDE was originally added by 6007b903dfe5f1d13e0c711ac2894bdd4a61b1ad
+ * (lmo) rsp. 8431fd094d625b94d364fe393076ccef88e6ce18 (kernel.org). The
+ * discussion can be found in lkml posting
+ * <a2ebde260608230500o3407b108hc03debb9da6e62c@mail.gmail.com> which is
+ * archived at http://lists.linuxcoding.com/kernel/2006-q3/msg17360.html
+ *
+ * It is unclear if the misscompilations mentioned in
+ * http://lkml.org/lkml/2010/8/8/138 also affect MIPS so we keep this one
+ * until GCC 3.x has been retired before we can apply
+ * https://patchwork.linux-mips.org/patch/1541/
+ */
+
#define __pa_symbol(x) __pa(RELOC_HIDE((unsigned long)(x), 0))
#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
diff --git a/arch/mips/include/asm/siginfo.h b/arch/mips/include/asm/siginfo.h
index 96e28f18dad1..1ca64b4d33d9 100644
--- a/arch/mips/include/asm/siginfo.h
+++ b/arch/mips/include/asm/siginfo.h
@@ -88,6 +88,7 @@ typedef struct siginfo {
#ifdef __ARCH_SI_TRAPNO
int _trapno; /* TRAP # which caused the signal */
#endif
+ short _addr_lsb;
} _sigfault;
/* SIGPOLL, SIGXFSZ (To do ...) */
diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h
index 2376f2e06e47..70df9c0d3c5b 100644
--- a/arch/mips/include/asm/thread_info.h
+++ b/arch/mips/include/asm/thread_info.h
@@ -146,7 +146,8 @@ register struct thread_info *__current_thread_info __asm__("$28");
#define _TIF_LOAD_WATCH (1<<TIF_LOAD_WATCH)
/* work to do on interrupt/exception return */
-#define _TIF_WORK_MASK (0x0000ffef & ~_TIF_SECCOMP)
+#define _TIF_WORK_MASK (0x0000ffef & \
+ ~(_TIF_SECCOMP | _TIF_SYSCALL_AUDIT))
/* work to do on any return to u-space */
#define _TIF_ALLWORK_MASK (0x8000ffff & ~_TIF_SECCOMP)
diff --git a/arch/mips/include/asm/unistd.h b/arch/mips/include/asm/unistd.h
index baa318a59c97..550725b881d5 100644
--- a/arch/mips/include/asm/unistd.h
+++ b/arch/mips/include/asm/unistd.h
@@ -356,16 +356,19 @@
#define __NR_perf_event_open (__NR_Linux + 333)
#define __NR_accept4 (__NR_Linux + 334)
#define __NR_recvmmsg (__NR_Linux + 335)
+#define __NR_fanotify_init (__NR_Linux + 336)
+#define __NR_fanotify_mark (__NR_Linux + 337)
+#define __NR_prlimit64 (__NR_Linux + 338)
/*
* Offset of the last Linux o32 flavoured syscall
*/
-#define __NR_Linux_syscalls 335
+#define __NR_Linux_syscalls 338
#endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
#define __NR_O32_Linux 4000
-#define __NR_O32_Linux_syscalls 335
+#define __NR_O32_Linux_syscalls 338
#if _MIPS_SIM == _MIPS_SIM_ABI64
@@ -668,16 +671,19 @@
#define __NR_perf_event_open (__NR_Linux + 292)
#define __NR_accept4 (__NR_Linux + 293)
#define __NR_recvmmsg (__NR_Linux + 294)
+#define __NR_fanotify_init (__NR_Linux + 295)
+#define __NR_fanotify_mark (__NR_Linux + 296)
+#define __NR_prlimit64 (__NR_Linux + 297)
/*
* Offset of the last Linux 64-bit flavoured syscall
*/
-#define __NR_Linux_syscalls 294
+#define __NR_Linux_syscalls 297
#endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
#define __NR_64_Linux 5000
-#define __NR_64_Linux_syscalls 294
+#define __NR_64_Linux_syscalls 297
#if _MIPS_SIM == _MIPS_SIM_NABI32
@@ -985,16 +991,19 @@
#define __NR_accept4 (__NR_Linux + 297)
#define __NR_recvmmsg (__NR_Linux + 298)
#define __NR_getdents64 (__NR_Linux + 299)
+#define __NR_fanotify_init (__NR_Linux + 300)
+#define __NR_fanotify_mark (__NR_Linux + 301)
+#define __NR_prlimit64 (__NR_Linux + 302)
/*
* Offset of the last N32 flavoured syscall
*/
-#define __NR_Linux_syscalls 299
+#define __NR_Linux_syscalls 302
#endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
#define __NR_N32_Linux 6000
-#define __NR_N32_Linux_syscalls 299
+#define __NR_N32_Linux_syscalls 302
#ifdef __KERNEL__
diff --git a/arch/mips/jazz/irq.c b/arch/mips/jazz/irq.c
index ee18028efe92..35b3e2f0af04 100644
--- a/arch/mips/jazz/irq.c
+++ b/arch/mips/jazz/irq.c
@@ -12,6 +12,7 @@
#include <linux/kernel.h>
#include <linux/smp.h>
#include <linux/spinlock.h>
+#include <linux/irq.h>
#include <asm/irq_cpu.h>
#include <asm/i8253.h>
diff --git a/arch/mips/jz4740/Platform b/arch/mips/jz4740/Platform
index 6a97230e3d05..ba91be9c21ef 100644
--- a/arch/mips/jz4740/Platform
+++ b/arch/mips/jz4740/Platform
@@ -1,3 +1,3 @@
-core-$(CONFIG_MACH_JZ4740) += arch/mips/jz4740/
+platform-$(CONFIG_MACH_JZ4740) += jz4740/
cflags-$(CONFIG_MACH_JZ4740) += -I$(srctree)/arch/mips/include/asm/mach-jz4740
load-$(CONFIG_MACH_JZ4740) += 0xffffffff80010000
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 0176ed015c89..32103cc2a257 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -40,7 +40,6 @@ int __compute_return_epc(struct pt_regs *regs)
return -EFAULT;
}
- regs->regs[0] = 0;
switch (insn.i_format.opcode) {
/*
* jr and jalr are in r_format format.
diff --git a/arch/mips/kernel/cevt-bcm1480.c b/arch/mips/kernel/cevt-bcm1480.c
index bfea327c636c..36c3898b76db 100644
--- a/arch/mips/kernel/cevt-bcm1480.c
+++ b/arch/mips/kernel/cevt-bcm1480.c
@@ -19,6 +19,7 @@
#include <linux/interrupt.h>
#include <linux/percpu.h>
#include <linux/smp.h>
+#include <linux/irq.h>
#include <asm/addrspace.h>
#include <asm/io.h>
diff --git a/arch/mips/kernel/cevt-ds1287.c b/arch/mips/kernel/cevt-ds1287.c
index 00a4da277cbb..939157e397b9 100644
--- a/arch/mips/kernel/cevt-ds1287.c
+++ b/arch/mips/kernel/cevt-ds1287.c
@@ -21,6 +21,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/mc146818rtc.h>
+#include <linux/irq.h>
#include <asm/time.h>
diff --git a/arch/mips/kernel/cevt-gt641xx.c b/arch/mips/kernel/cevt-gt641xx.c
index 392ef3756c56..339f3639b90e 100644
--- a/arch/mips/kernel/cevt-gt641xx.c
+++ b/arch/mips/kernel/cevt-gt641xx.c
@@ -21,6 +21,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
+#include <linux/irq.h>
#include <asm/gt64120.h>
#include <asm/time.h>
diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c
index 2a4d50ff5e2c..2f4d7a99bcc2 100644
--- a/arch/mips/kernel/cevt-r4k.c
+++ b/arch/mips/kernel/cevt-r4k.c
@@ -10,6 +10,7 @@
#include <linux/interrupt.h>
#include <linux/percpu.h>
#include <linux/smp.h>
+#include <linux/irq.h>
#include <asm/smtc_ipi.h>
#include <asm/time.h>
diff --git a/arch/mips/kernel/cevt-sb1250.c b/arch/mips/kernel/cevt-sb1250.c
index da78eeaea6e8..590c54f28a81 100644
--- a/arch/mips/kernel/cevt-sb1250.c
+++ b/arch/mips/kernel/cevt-sb1250.c
@@ -17,6 +17,7 @@
*/
#include <linux/clockchips.h>
#include <linux/interrupt.h>
+#include <linux/irq.h>
#include <linux/percpu.h>
#include <linux/smp.h>
diff --git a/arch/mips/kernel/cevt-smtc.c b/arch/mips/kernel/cevt-smtc.c
index b102e4f1630e..2e72d30b2f05 100644
--- a/arch/mips/kernel/cevt-smtc.c
+++ b/arch/mips/kernel/cevt-smtc.c
@@ -11,6 +11,7 @@
#include <linux/interrupt.h>
#include <linux/percpu.h>
#include <linux/smp.h>
+#include <linux/irq.h>
#include <asm/smtc_ipi.h>
#include <asm/time.h>
diff --git a/arch/mips/kernel/cevt-txx9.c b/arch/mips/kernel/cevt-txx9.c
index 218ee6bda935..0b7377361e22 100644
--- a/arch/mips/kernel/cevt-txx9.c
+++ b/arch/mips/kernel/cevt-txx9.c
@@ -13,6 +13,7 @@
*/
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <linux/irq.h>
#include <asm/time.h>
#include <asm/txx9tmr.h>
diff --git a/arch/mips/kernel/i8253.c b/arch/mips/kernel/i8253.c
index 94794062a177..2392a7a296d4 100644
--- a/arch/mips/kernel/i8253.c
+++ b/arch/mips/kernel/i8253.c
@@ -9,6 +9,7 @@
#include <linux/module.h>
#include <linux/smp.h>
#include <linux/spinlock.h>
+#include <linux/irq.h>
#include <asm/delay.h>
#include <asm/i8253.h>
diff --git a/arch/mips/kernel/i8259.c b/arch/mips/kernel/i8259.c
index 27799113332c..c58176cc796b 100644
--- a/arch/mips/kernel/i8259.c
+++ b/arch/mips/kernel/i8259.c
@@ -15,6 +15,7 @@
#include <linux/kernel.h>
#include <linux/spinlock.h>
#include <linux/sysdev.h>
+#include <linux/irq.h>
#include <asm/i8259.h>
#include <asm/io.h>
diff --git a/arch/mips/kernel/irq-gic.c b/arch/mips/kernel/irq-gic.c
index b181f2f0ea8e..1774271af848 100644
--- a/arch/mips/kernel/irq-gic.c
+++ b/arch/mips/kernel/irq-gic.c
@@ -3,12 +3,11 @@
#include <linux/bitmap.h>
#include <linux/init.h>
#include <linux/smp.h>
+#include <linux/irq.h>
#include <asm/io.h>
#include <asm/gic.h>
#include <asm/gcmpregs.h>
-#include <asm/mips-boards/maltaint.h>
-#include <asm/irq.h>
#include <linux/hardirq.h>
#include <asm-generic/bitops/find.h>
@@ -131,7 +130,7 @@ static int gic_set_affinity(unsigned int irq, const struct cpumask *cpumask)
int i;
irq -= _irqbase;
- pr_debug(KERN_DEBUG "%s(%d) called\n", __func__, irq);
+ pr_debug("%s(%d) called\n", __func__, irq);
cpumask_and(&tmp, cpumask, cpu_online_mask);
if (cpus_empty(tmp))
return -1;
@@ -222,7 +221,7 @@ static void __init gic_basic_init(int numintrs, int numvpes,
/* Setup specifics */
for (i = 0; i < mapsize; i++) {
cpu = intrmap[i].cpunum;
- if (cpu == X)
+ if (cpu == GIC_UNUSED)
continue;
if (cpu == 0 && i != 0 && intrmap[i].flags == 0)
continue;
diff --git a/arch/mips/kernel/irq-rm7000.c b/arch/mips/kernel/irq-rm7000.c
index fb50cc78b28b..9731e8b47862 100644
--- a/arch/mips/kernel/irq-rm7000.c
+++ b/arch/mips/kernel/irq-rm7000.c
@@ -11,6 +11,7 @@
*/
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <linux/irq.h>
#include <linux/kernel.h>
#include <asm/irq_cpu.h>
diff --git a/arch/mips/kernel/irq-rm9000.c b/arch/mips/kernel/irq-rm9000.c
index b47e4615ec12..b7e4025b58a8 100644
--- a/arch/mips/kernel/irq-rm9000.c
+++ b/arch/mips/kernel/irq-rm9000.c
@@ -11,6 +11,7 @@
*/
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/module.h>
diff --git a/arch/mips/kernel/irq_cpu.c b/arch/mips/kernel/irq_cpu.c
index 55c8a3ca507b..0262abe09121 100644
--- a/arch/mips/kernel/irq_cpu.c
+++ b/arch/mips/kernel/irq_cpu.c
@@ -30,6 +30,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
+#include <linux/irq.h>
#include <asm/irq_cpu.h>
#include <asm/mipsregs.h>
diff --git a/arch/mips/kernel/irq_txx9.c b/arch/mips/kernel/irq_txx9.c
index 9b78029bea70..95a96f69172d 100644
--- a/arch/mips/kernel/irq_txx9.c
+++ b/arch/mips/kernel/irq_txx9.c
@@ -16,6 +16,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/types.h>
+#include <linux/irq.h>
#include <asm/txx9irq.h>
struct txx9_irc_reg {
diff --git a/arch/mips/kernel/kgdb.c b/arch/mips/kernel/kgdb.c
index 1f4e2fa64140..f4546e97c60d 100644
--- a/arch/mips/kernel/kgdb.c
+++ b/arch/mips/kernel/kgdb.c
@@ -283,7 +283,7 @@ static int kgdb_mips_notify(struct notifier_block *self, unsigned long cmd,
struct pt_regs *regs = args->regs;
int trap = (regs->cp0_cause & 0x7c) >> 2;
- /* Userpace events, ignore. */
+ /* Userspace events, ignore. */
if (user_mode(regs))
return NOTIFY_DONE;
diff --git a/arch/mips/kernel/kspd.c b/arch/mips/kernel/kspd.c
index 80e2ba694bab..29811f043399 100644
--- a/arch/mips/kernel/kspd.c
+++ b/arch/mips/kernel/kspd.c
@@ -251,7 +251,7 @@ void sp_work_handle_request(void)
memset(&tz, 0, sizeof(tz));
if ((ret.retval = sp_syscall(__NR_gettimeofday, (int)&tv,
(int)&tz, 0, 0)) == 0)
- ret.retval = tv.tv_sec;
+ ret.retval = tv.tv_sec;
break;
case MTSP_SYSCALL_EXIT:
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c
index c2dab140dc98..6343b4a5b835 100644
--- a/arch/mips/kernel/linux32.c
+++ b/arch/mips/kernel/linux32.c
@@ -341,3 +341,10 @@ asmlinkage long sys32_lookup_dcookie(u32 a0, u32 a1, char __user *buf,
{
return sys_lookup_dcookie(merge_64(a0, a1), buf, len);
}
+
+SYSCALL_DEFINE6(32_fanotify_mark, int, fanotify_fd, unsigned int, flags,
+ u64, a3, u64, a4, int, dfd, const char __user *, pathname)
+{
+ return sys_fanotify_mark(fanotify_fd, flags, merge_64(a3, a4),
+ dfd, pathname);
+}
diff --git a/arch/mips/kernel/mips-mt-fpaff.c b/arch/mips/kernel/mips-mt-fpaff.c
index 2340f11dc29c..9a526ba6f257 100644
--- a/arch/mips/kernel/mips-mt-fpaff.c
+++ b/arch/mips/kernel/mips-mt-fpaff.c
@@ -103,7 +103,7 @@ asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len,
if (!check_same_owner(p) && !capable(CAP_SYS_NICE))
goto out_unlock;
- retval = security_task_setscheduler(p, 0, NULL);
+ retval = security_task_setscheduler(p)
if (retval)
goto out_unlock;
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index c51b95ff8644..c8777333e198 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -536,7 +536,7 @@ asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit)
{
/* do the secure computing check first */
if (!entryexit)
- secure_computing(regs->regs[0]);
+ secure_computing(regs->regs[2]);
if (unlikely(current->audit_context) && entryexit)
audit_syscall_exit(AUDITSC_RESULT(regs->regs[2]),
@@ -565,7 +565,7 @@ asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit)
out:
if (unlikely(current->audit_context) && !entryexit)
- audit_syscall_entry(audit_arch(), regs->regs[0],
+ audit_syscall_entry(audit_arch(), regs->regs[2],
regs->regs[4], regs->regs[5],
regs->regs[6], regs->regs[7]);
}
diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c
index 26f9b9ab19cc..557ef72472e0 100644
--- a/arch/mips/kernel/rtlx.c
+++ b/arch/mips/kernel/rtlx.c
@@ -468,7 +468,8 @@ static const struct file_operations rtlx_fops = {
.release = file_release,
.write = file_write,
.read = file_read,
- .poll = file_poll
+ .poll = file_poll,
+ .llseek = noop_llseek,
};
static struct irqaction rtlx_irq = {
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index 17202bbe843f..fbaabad0e6e2 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -63,9 +63,9 @@ stack_done:
sw t0, PT_R7(sp) # set error flag
beqz t0, 1f
+ lw t1, PT_R2(sp) # syscall number
negu v0 # error
- sw v0, PT_R0(sp) # set flag for syscall
- # restarting
+ sw t1, PT_R0(sp) # save it for syscall restarting
1: sw v0, PT_R2(sp) # result
o32_syscall_exit:
@@ -104,9 +104,9 @@ syscall_trace_entry:
sw t0, PT_R7(sp) # set error flag
beqz t0, 1f
+ lw t1, PT_R2(sp) # syscall number
negu v0 # error
- sw v0, PT_R0(sp) # set flag for syscall
- # restarting
+ sw t1, PT_R0(sp) # save it for syscall restarting
1: sw v0, PT_R2(sp) # result
j syscall_exit
@@ -169,8 +169,7 @@ stackargs:
* We probably should handle this case a bit more drastic.
*/
bad_stack:
- negu v0 # error
- sw v0, PT_R0(sp)
+ li v0, EFAULT
sw v0, PT_R2(sp)
li t0, 1 # set error flag
sw t0, PT_R7(sp)
@@ -583,7 +582,10 @@ einval: li v0, -ENOSYS
sys sys_rt_tgsigqueueinfo 4
sys sys_perf_event_open 5
sys sys_accept4 4
- sys sys_recvmmsg 5
+ sys sys_recvmmsg 5 /* 4335 */
+ sys sys_fanotify_init 2
+ sys sys_fanotify_mark 6
+ sys sys_prlimit64 4
.endm
/* We pre-compute the number of _instruction_ bytes needed to
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S
index a8a6c596eb04..3f4179283207 100644
--- a/arch/mips/kernel/scall64-64.S
+++ b/arch/mips/kernel/scall64-64.S
@@ -66,9 +66,9 @@ NESTED(handle_sys64, PT_SIZE, sp)
sd t0, PT_R7(sp) # set error flag
beqz t0, 1f
+ ld t1, PT_R2(sp) # syscall number
dnegu v0 # error
- sd v0, PT_R0(sp) # set flag for syscall
- # restarting
+ sd t1, PT_R0(sp) # save it for syscall restarting
1: sd v0, PT_R2(sp) # result
n64_syscall_exit:
@@ -109,8 +109,9 @@ syscall_trace_entry:
sd t0, PT_R7(sp) # set error flag
beqz t0, 1f
+ ld t1, PT_R2(sp) # syscall number
dnegu v0 # error
- sd v0, PT_R0(sp) # set flag for syscall restarting
+ sd t1, PT_R0(sp) # save it for syscall restarting
1: sd v0, PT_R2(sp) # result
j syscall_exit
@@ -416,9 +417,12 @@ sys_call_table:
PTR sys_pipe2
PTR sys_inotify_init1
PTR sys_preadv
- PTR sys_pwritev /* 5390 */
+ PTR sys_pwritev /* 5290 */
PTR sys_rt_tgsigqueueinfo
PTR sys_perf_event_open
PTR sys_accept4
- PTR sys_recvmmsg
+ PTR sys_recvmmsg
+ PTR sys_fanotify_init /* 5295 */
+ PTR sys_fanotify_mark
+ PTR sys_prlimit64
.size sys_call_table,.-sys_call_table
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index a3d66137731a..f08ece6d8acc 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -65,8 +65,9 @@ NESTED(handle_sysn32, PT_SIZE, sp)
sd t0, PT_R7(sp) # set error flag
beqz t0, 1f
+ ld t1, PT_R2(sp) # syscall number
dnegu v0 # error
- sd v0, PT_R0(sp) # set flag for syscall restarting
+ sd t1, PT_R0(sp) # save it for syscall restarting
1: sd v0, PT_R2(sp) # result
local_irq_disable # make sure need_resched and
@@ -106,8 +107,9 @@ n32_syscall_trace_entry:
sd t0, PT_R7(sp) # set error flag
beqz t0, 1f
+ ld t1, PT_R2(sp) # syscall number
dnegu v0 # error
- sd v0, PT_R0(sp) # set flag for syscall restarting
+ sd t1, PT_R0(sp) # save it for syscall restarting
1: sd v0, PT_R2(sp) # result
j syscall_exit
@@ -320,10 +322,10 @@ EXPORT(sysn32_call_table)
PTR sys_cacheflush
PTR sys_cachectl
PTR sys_sysmips
- PTR sys_io_setup /* 6200 */
+ PTR compat_sys_io_setup /* 6200 */
PTR sys_io_destroy
- PTR sys_io_getevents
- PTR sys_io_submit
+ PTR compat_sys_io_getevents
+ PTR compat_sys_io_submit
PTR sys_io_cancel
PTR sys_exit_group /* 6205 */
PTR sys_lookup_dcookie
@@ -419,5 +421,8 @@ EXPORT(sysn32_call_table)
PTR sys_perf_event_open
PTR sys_accept4
PTR compat_sys_recvmmsg
- PTR sys_getdents
+ PTR sys_getdents64
+ PTR sys_fanotify_init /* 6300 */
+ PTR sys_fanotify_mark
+ PTR sys_prlimit64
.size sysn32_call_table,.-sysn32_call_table
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index 813689ef2384..78d768a3e19d 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -93,8 +93,9 @@ NESTED(handle_sys, PT_SIZE, sp)
sd t0, PT_R7(sp) # set error flag
beqz t0, 1f
+ ld t1, PT_R2(sp) # syscall number
dnegu v0 # error
- sd v0, PT_R0(sp) # flag for syscall restarting
+ sd t1, PT_R0(sp) # save it for syscall restarting
1: sd v0, PT_R2(sp) # result
o32_syscall_exit:
@@ -142,8 +143,9 @@ trace_a_syscall:
sd t0, PT_R7(sp) # set error flag
beqz t0, 1f
+ ld t1, PT_R2(sp) # syscall number
dnegu v0 # error
- sd v0, PT_R0(sp) # set flag for syscall restarting
+ sd t1, PT_R0(sp) # save it for syscall restarting
1: sd v0, PT_R2(sp) # result
j syscall_exit
@@ -154,8 +156,7 @@ trace_a_syscall:
* The stackpointer for a call with more than 4 arguments is bad.
*/
bad_stack:
- dnegu v0 # error
- sd v0, PT_R0(sp)
+ li v0, EFAULT
sd v0, PT_R2(sp)
li t0, 1 # set error flag
sd t0, PT_R7(sp)
@@ -444,10 +445,10 @@ sys_call_table:
PTR compat_sys_futex
PTR compat_sys_sched_setaffinity
PTR compat_sys_sched_getaffinity /* 4240 */
- PTR sys_io_setup
+ PTR compat_sys_io_setup
PTR sys_io_destroy
- PTR sys_io_getevents
- PTR sys_io_submit
+ PTR compat_sys_io_getevents
+ PTR compat_sys_io_submit
PTR sys_io_cancel /* 4245 */
PTR sys_exit_group
PTR sys32_lookup_dcookie
@@ -538,5 +539,8 @@ sys_call_table:
PTR compat_sys_rt_tgsigqueueinfo
PTR sys_perf_event_open
PTR sys_accept4
- PTR compat_sys_recvmmsg
+ PTR compat_sys_recvmmsg /* 4335 */
+ PTR sys_fanotify_init
+ PTR sys_32_fanotify_mark
+ PTR sys_prlimit64
.size sys_call_table,.-sys_call_table
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index 2099d5a4c4b7..5922342bca39 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -390,7 +390,6 @@ asmlinkage void sys_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
{
struct rt_sigframe __user *frame;
sigset_t set;
- stack_t st;
int sig;
frame = (struct rt_sigframe __user *) regs.regs[29];
@@ -411,11 +410,9 @@ asmlinkage void sys_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
else if (sig)
force_sig(sig, current);
- if (__copy_from_user(&st, &frame->rs_uc.uc_stack, sizeof(st)))
- goto badframe;
/* It is more difficult to avoid calling this function than to
call it and ignore errors. */
- do_sigaltstack((stack_t __user *)&st, NULL, regs.regs[29]);
+ do_sigaltstack(&frame->rs_uc.uc_stack, NULL, regs.regs[29]);
/*
* Don't let your children do this ...
@@ -550,23 +547,26 @@ static int handle_signal(unsigned long sig, siginfo_t *info,
struct mips_abi *abi = current->thread.abi;
void *vdso = current->mm->context.vdso;
- switch(regs->regs[0]) {
- case ERESTART_RESTARTBLOCK:
- case ERESTARTNOHAND:
- regs->regs[2] = EINTR;
- break;
- case ERESTARTSYS:
- if (!(ka->sa.sa_flags & SA_RESTART)) {
+ if (regs->regs[0]) {
+ switch(regs->regs[2]) {
+ case ERESTART_RESTARTBLOCK:
+ case ERESTARTNOHAND:
regs->regs[2] = EINTR;
break;
+ case ERESTARTSYS:
+ if (!(ka->sa.sa_flags & SA_RESTART)) {
+ regs->regs[2] = EINTR;
+ break;
+ }
+ /* fallthrough */
+ case ERESTARTNOINTR:
+ regs->regs[7] = regs->regs[26];
+ regs->regs[2] = regs->regs[0];
+ regs->cp0_epc -= 4;
}
- /* fallthrough */
- case ERESTARTNOINTR: /* Userland will reload $v0. */
- regs->regs[7] = regs->regs[26];
- regs->cp0_epc -= 8;
- }
- regs->regs[0] = 0; /* Don't deal with this again. */
+ regs->regs[0] = 0; /* Don't deal with this again. */
+ }
if (sig_uses_siginfo(ka))
ret = abi->setup_rt_frame(vdso + abi->rt_signal_return_offset,
@@ -575,6 +575,9 @@ static int handle_signal(unsigned long sig, siginfo_t *info,
ret = abi->setup_frame(vdso + abi->signal_return_offset,
ka, regs, sig, oldset);
+ if (ret)
+ return ret;
+
spin_lock_irq(&current->sighand->siglock);
sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
if (!(ka->sa.sa_flags & SA_NODEFER))
@@ -622,17 +625,13 @@ static void do_signal(struct pt_regs *regs)
return;
}
- /*
- * Who's code doesn't conform to the restartable syscall convention
- * dies here!!! The li instruction, a single machine instruction,
- * must directly be followed by the syscall instruction.
- */
if (regs->regs[0]) {
if (regs->regs[2] == ERESTARTNOHAND ||
regs->regs[2] == ERESTARTSYS ||
regs->regs[2] == ERESTARTNOINTR) {
+ regs->regs[2] = regs->regs[0];
regs->regs[7] = regs->regs[26];
- regs->cp0_epc -= 8;
+ regs->cp0_epc -= 4;
}
if (regs->regs[2] == ERESTART_RESTARTBLOCK) {
regs->regs[2] = current->thread.abi->restart;
diff --git a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c
index 2c5df818c65a..ee24d814d5b9 100644
--- a/arch/mips/kernel/signal_n32.c
+++ b/arch/mips/kernel/signal_n32.c
@@ -109,6 +109,7 @@ asmlinkage int sysn32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
asmlinkage void sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
{
struct rt_sigframe_n32 __user *frame;
+ mm_segment_t old_fs;
sigset_t set;
stack_t st;
s32 sp;
@@ -143,7 +144,11 @@ asmlinkage void sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
/* It is more difficult to avoid calling this function than to
call it and ignore errors. */
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
do_sigaltstack((stack_t __user *)&st, NULL, regs.regs[29]);
+ set_fs(old_fs);
+
/*
* Don't let your children do this ...
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c
index cfeb2c155896..39c08254b0f1 100644
--- a/arch/mips/kernel/smtc.c
+++ b/arch/mips/kernel/smtc.c
@@ -1038,7 +1038,7 @@ void deferred_smtc_ipi(void)
* but it's more efficient, given that we're already
* running down the IPI queue.
*/
- __raw_local_irq_restore(flags);
+ __arch_local_irq_restore(flags);
}
}
@@ -1190,7 +1190,7 @@ void smtc_ipi_replay(void)
/*
** But use a raw restore here to avoid recursion.
*/
- __raw_local_irq_restore(flags);
+ __arch_local_irq_restore(flags);
if (pipi) {
self_ipi(pipi);
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 03ec0019032b..d053bf4759e4 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -28,6 +28,7 @@
#include <linux/kprobes.h>
#include <linux/notifier.h>
#include <linux/kdb.h>
+#include <linux/irq.h>
#include <asm/bootinfo.h>
#include <asm/branch.h>
@@ -51,7 +52,6 @@
#include <asm/mmu_context.h>
#include <asm/types.h>
#include <asm/stacktrace.h>
-#include <asm/irq.h>
#include <asm/uasm.h>
extern void check_wait(void);
diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c
index 69b039ca8d83..33d5a5ce4a29 100644
--- a/arch/mips/kernel/unaligned.c
+++ b/arch/mips/kernel/unaligned.c
@@ -109,8 +109,6 @@ static void emulate_load_store_insn(struct pt_regs *regs,
unsigned long value;
unsigned int res;
- regs->regs[0] = 0;
-
/*
* This load never faults.
*/
diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c
index 2bd2151c586a..3eb3cde2f661 100644
--- a/arch/mips/kernel/vpe.c
+++ b/arch/mips/kernel/vpe.c
@@ -1192,7 +1192,8 @@ static const struct file_operations vpe_fops = {
.owner = THIS_MODULE,
.open = vpe_open,
.release = vpe_release,
- .write = vpe_write
+ .write = vpe_write,
+ .llseek = noop_llseek,
};
/* module wrapper entry points */
diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c
index 7ba890860d98..469d4019f795 100644
--- a/arch/mips/mm/dma-default.c
+++ b/arch/mips/mm/dma-default.c
@@ -44,27 +44,39 @@ static inline int cpu_is_noncoherent_r10000(struct device *dev)
static gfp_t massage_gfp_flags(const struct device *dev, gfp_t gfp)
{
+ gfp_t dma_flag;
+
/* ignore region specifiers */
gfp &= ~(__GFP_DMA | __GFP_DMA32 | __GFP_HIGHMEM);
-#ifdef CONFIG_ZONE_DMA
+#ifdef CONFIG_ISA
if (dev == NULL)
- gfp |= __GFP_DMA;
- else if (dev->coherent_dma_mask < DMA_BIT_MASK(24))
- gfp |= __GFP_DMA;
+ dma_flag = __GFP_DMA;
else
#endif
-#ifdef CONFIG_ZONE_DMA32
+#if defined(CONFIG_ZONE_DMA32) && defined(CONFIG_ZONE_DMA)
if (dev->coherent_dma_mask < DMA_BIT_MASK(32))
- gfp |= __GFP_DMA32;
+ dma_flag = __GFP_DMA;
+ else if (dev->coherent_dma_mask < DMA_BIT_MASK(64))
+ dma_flag = __GFP_DMA32;
+ else
+#endif
+#if defined(CONFIG_ZONE_DMA32) && !defined(CONFIG_ZONE_DMA)
+ if (dev->coherent_dma_mask < DMA_BIT_MASK(64))
+ dma_flag = __GFP_DMA32;
+ else
+#endif
+#if defined(CONFIG_ZONE_DMA) && !defined(CONFIG_ZONE_DMA32)
+ if (dev->coherent_dma_mask < DMA_BIT_MASK(64))
+ dma_flag = __GFP_DMA;
else
#endif
- ;
+ dma_flag = 0;
/* Don't invoke OOM killer */
gfp |= __GFP_NORETRY;
- return gfp;
+ return gfp | dma_flag;
}
void *dma_alloc_noncoherent(struct device *dev, size_t size,
diff --git a/arch/mips/mm/sc-rm7k.c b/arch/mips/mm/sc-rm7k.c
index 1ef75cd80a0d..274af3be1442 100644
--- a/arch/mips/mm/sc-rm7k.c
+++ b/arch/mips/mm/sc-rm7k.c
@@ -30,7 +30,7 @@
#define tc_lsize 32
extern unsigned long icache_way_size, dcache_way_size;
-unsigned long tcache_size;
+static unsigned long tcache_size;
#include <asm/r4kcache.h>
diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c
index 15949b0be811..b79b24afe3a2 100644
--- a/arch/mips/mti-malta/malta-int.c
+++ b/arch/mips/mti-malta/malta-int.c
@@ -385,6 +385,8 @@ static int __initdata msc_nr_eicirqs = ARRAY_SIZE(msc_eicirqmap);
*/
#define GIC_CPU_NMI GIC_MAP_TO_NMI_MSK
+#define X GIC_UNUSED
+
static struct gic_intr_map gic_intr_map[GIC_NUM_INTRS] = {
{ X, X, X, X, 0 },
{ X, X, X, X, 0 },
@@ -404,6 +406,7 @@ static struct gic_intr_map gic_intr_map[GIC_NUM_INTRS] = {
{ X, X, X, X, 0 },
/* The remainder of this table is initialised by fill_ipi_map */
};
+#undef X
/*
* GCMP needs to be detected before any SMP initialisation
diff --git a/arch/mips/mti-malta/malta-platform.c b/arch/mips/mti-malta/malta-platform.c
index 72e32a7715be..4c35301720e7 100644
--- a/arch/mips/mti-malta/malta-platform.c
+++ b/arch/mips/mti-malta/malta-platform.c
@@ -25,6 +25,7 @@
#include <linux/serial_8250.h>
#include <linux/mc146818rtc.h>
#include <linux/module.h>
+#include <linux/irq.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/physmap.h>
#include <linux/platform_device.h>
diff --git a/arch/mips/pci/ops-tx3927.c b/arch/mips/pci/ops-tx3927.c
index 31c150196595..6a3bdb5ffa80 100644
--- a/arch/mips/pci/ops-tx3927.c
+++ b/arch/mips/pci/ops-tx3927.c
@@ -38,6 +38,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <linux/irq.h>
#include <asm/addrspace.h>
#include <asm/txx9irq.h>
diff --git a/arch/mips/pci/ops-tx4927.c b/arch/mips/pci/ops-tx4927.c
index 5989e747527f..a1e7e6d80c8c 100644
--- a/arch/mips/pci/ops-tx4927.c
+++ b/arch/mips/pci/ops-tx4927.c
@@ -17,6 +17,7 @@
*/
#include <linux/kernel.h>
#include <linux/interrupt.h>
+#include <linux/irq.h>
#include <asm/txx9/pci.h>
#include <asm/txx9/tx4927pcic.h>
diff --git a/arch/mips/pci/pci-rc32434.c b/arch/mips/pci/pci-rc32434.c
index 71f7d27b0d4c..f31218e17d3c 100644
--- a/arch/mips/pci/pci-rc32434.c
+++ b/arch/mips/pci/pci-rc32434.c
@@ -118,7 +118,7 @@ static int __init rc32434_pcibridge_init(void)
if (!((pcicvalue == PCIM_H_EA) ||
(pcicvalue == PCIM_H_IA_FIX) ||
(pcicvalue == PCIM_H_IA_RR))) {
- pr_err(KERN_ERR "PCI init error!!!\n");
+ pr_err("PCI init error!!!\n");
/* Not in Host Mode, return ERROR */
return -1;
}
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_irq_cic.c b/arch/mips/pmc-sierra/msp71xx/msp_irq_cic.c
index 94c9c2c9fbc1..07e71ff2433f 100644
--- a/arch/mips/pmc-sierra/msp71xx/msp_irq_cic.c
+++ b/arch/mips/pmc-sierra/msp71xx/msp_irq_cic.c
@@ -14,6 +14,7 @@
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/bitops.h>
+#include <linux/irq.h>
#include <asm/system.h>
diff --git a/arch/mips/pnx8550/common/reset.c b/arch/mips/pnx8550/common/reset.c
index fadd8744a6bc..e7a12ff304b9 100644
--- a/arch/mips/pnx8550/common/reset.c
+++ b/arch/mips/pnx8550/common/reset.c
@@ -22,29 +22,19 @@
*/
#include <linux/kernel.h>
+#include <asm/processor.h>
#include <asm/reboot.h>
#include <glb.h>
void pnx8550_machine_restart(char *command)
{
- char head[] = "************* Machine restart *************";
- char foot[] = "*******************************************";
-
- printk("\n\n");
- printk("%s\n", head);
- if (command != NULL)
- printk("* %s\n", command);
- printk("%s\n", foot);
-
PNX8550_RST_CTL = PNX8550_RST_DO_SW_RST;
}
void pnx8550_machine_halt(void)
{
- printk("*** Machine halt. (Not implemented) ***\n");
-}
-
-void pnx8550_machine_power_off(void)
-{
- printk("*** Machine power off. (Not implemented) ***\n");
+ while (1) {
+ if (cpu_wait)
+ cpu_wait();
+ }
}
diff --git a/arch/mips/pnx8550/common/setup.c b/arch/mips/pnx8550/common/setup.c
index 64246c9c875c..43cb3945fdbf 100644
--- a/arch/mips/pnx8550/common/setup.c
+++ b/arch/mips/pnx8550/common/setup.c
@@ -44,7 +44,6 @@
extern void __init board_setup(void);
extern void pnx8550_machine_restart(char *);
extern void pnx8550_machine_halt(void);
-extern void pnx8550_machine_power_off(void);
extern struct resource ioport_resource;
extern struct resource iomem_resource;
extern char *prom_getcmdline(void);
@@ -100,7 +99,7 @@ void __init plat_mem_setup(void)
_machine_restart = pnx8550_machine_restart;
_machine_halt = pnx8550_machine_halt;
- pm_power_off = pnx8550_machine_power_off;
+ pm_power_off = pnx8550_machine_halt;
/* Clear the Global 2 Register, PCI Inta Output Enable Registers
Bit 1:Enable DAC Powerdown
diff --git a/arch/mips/powertv/asic/irq_asic.c b/arch/mips/powertv/asic/irq_asic.c
index b54d24499b06..e55382434155 100644
--- a/arch/mips/powertv/asic/irq_asic.c
+++ b/arch/mips/powertv/asic/irq_asic.c
@@ -13,6 +13,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
+#include <linux/irq.h>
#include <asm/irq_cpu.h>
#include <asm/mipsregs.h>
diff --git a/arch/mips/rb532/serial.c b/arch/mips/rb532/serial.c
index 00ed19f0bdb5..70482540b3db 100644
--- a/arch/mips/rb532/serial.c
+++ b/arch/mips/rb532/serial.c
@@ -29,6 +29,7 @@
#include <linux/tty.h>
#include <linux/serial_core.h>
#include <linux/serial_8250.h>
+#include <linux/irq.h>
#include <asm/serial.h>
#include <asm/mach-rc32434/rb.h>
diff --git a/arch/mips/sibyte/common/sb_tbprof.c b/arch/mips/sibyte/common/sb_tbprof.c
index d4ed7a9156f5..ca35b730d189 100644
--- a/arch/mips/sibyte/common/sb_tbprof.c
+++ b/arch/mips/sibyte/common/sb_tbprof.c
@@ -545,6 +545,7 @@ static const struct file_operations sbprof_tb_fops = {
.unlocked_ioctl = sbprof_tb_ioctl,
.compat_ioctl = sbprof_tb_ioctl,
.mmap = NULL,
+ .llseek = default_llseek,
};
static struct class *tb_class;
diff --git a/arch/mips/sni/a20r.c b/arch/mips/sni/a20r.c
index e6980892834a..bbe7187879fa 100644
--- a/arch/mips/sni/a20r.c
+++ b/arch/mips/sni/a20r.c
@@ -10,6 +10,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <linux/irq.h>
#include <linux/platform_device.h>
#include <linux/serial_8250.h>
diff --git a/arch/mips/sni/pcimt.c b/arch/mips/sni/pcimt.c
index 51e62bbaa23b..8c92c73bc717 100644
--- a/arch/mips/sni/pcimt.c
+++ b/arch/mips/sni/pcimt.c
@@ -11,6 +11,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <linux/irq.h>
#include <linux/pci.h>
#include <linux/serial_8250.h>
diff --git a/arch/mips/sni/pcit.c b/arch/mips/sni/pcit.c
index f4699d35858b..dc9874553bec 100644
--- a/arch/mips/sni/pcit.c
+++ b/arch/mips/sni/pcit.c
@@ -10,6 +10,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <linux/irq.h>
#include <linux/pci.h>
#include <linux/serial_8250.h>
diff --git a/arch/mips/sni/rm200.c b/arch/mips/sni/rm200.c
index 90c558f7c0fa..0e6f42c2bbc8 100644
--- a/arch/mips/sni/rm200.c
+++ b/arch/mips/sni/rm200.c
@@ -13,6 +13,7 @@
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <linux/irq.h>
#include <linux/platform_device.h>
#include <linux/serial_8250.h>
#include <linux/io.h>
diff --git a/arch/mips/sni/time.c b/arch/mips/sni/time.c
index f3b60e671207..c76151b56568 100644
--- a/arch/mips/sni/time.c
+++ b/arch/mips/sni/time.c
@@ -1,5 +1,6 @@
#include <linux/types.h>
#include <linux/interrupt.h>
+#include <linux/irq.h>
#include <linux/smp.h>
#include <linux/time.h>
#include <linux/clockchips.h>
diff --git a/arch/mips/txx9/generic/irq_tx4927.c b/arch/mips/txx9/generic/irq_tx4927.c
index ad2870def8f1..e1828e8bcaef 100644
--- a/arch/mips/txx9/generic/irq_tx4927.c
+++ b/arch/mips/txx9/generic/irq_tx4927.c
@@ -25,6 +25,7 @@
*/
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <linux/irq.h>
#include <asm/irq_cpu.h>
#include <asm/txx9/tx4927.h>
diff --git a/arch/mips/txx9/generic/irq_tx4938.c b/arch/mips/txx9/generic/irq_tx4938.c
index 025ae11359a8..a6e6e805097a 100644
--- a/arch/mips/txx9/generic/irq_tx4938.c
+++ b/arch/mips/txx9/generic/irq_tx4938.c
@@ -13,6 +13,7 @@
*/
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <linux/irq.h>
#include <asm/irq_cpu.h>
#include <asm/txx9/tx4938.h>
diff --git a/arch/mips/txx9/generic/irq_tx4939.c b/arch/mips/txx9/generic/irq_tx4939.c
index 013213a8706b..3886ad77cbad 100644
--- a/arch/mips/txx9/generic/irq_tx4939.c
+++ b/arch/mips/txx9/generic/irq_tx4939.c
@@ -19,6 +19,7 @@
*/
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <linux/irq.h>
#include <linux/types.h>
#include <asm/irq_cpu.h>
#include <asm/txx9irq.h>
diff --git a/arch/mips/txx9/generic/setup.c b/arch/mips/txx9/generic/setup.c
index 575d219b8001..812816c45662 100644
--- a/arch/mips/txx9/generic/setup.c
+++ b/arch/mips/txx9/generic/setup.c
@@ -24,6 +24,7 @@
#include <linux/leds.h>
#include <linux/sysdev.h>
#include <linux/slab.h>
+#include <linux/irq.h>
#include <asm/bootinfo.h>
#include <asm/time.h>
#include <asm/reboot.h>
diff --git a/arch/mips/txx9/jmr3927/irq.c b/arch/mips/txx9/jmr3927/irq.c
index 6ec626c9473f..0a7f8e3b9fd7 100644
--- a/arch/mips/txx9/jmr3927/irq.c
+++ b/arch/mips/txx9/jmr3927/irq.c
@@ -32,6 +32,7 @@
#include <linux/init.h>
#include <linux/types.h>
#include <linux/interrupt.h>
+#include <linux/irq.h>
#include <asm/io.h>
#include <asm/mipsregs.h>
diff --git a/arch/mips/txx9/rbtx4927/irq.c b/arch/mips/txx9/rbtx4927/irq.c
index 9c14ebb26cb4..c4b54d20efd3 100644
--- a/arch/mips/txx9/rbtx4927/irq.c
+++ b/arch/mips/txx9/rbtx4927/irq.c
@@ -111,6 +111,7 @@
#include <linux/init.h>
#include <linux/types.h>
#include <linux/interrupt.h>
+#include <linux/irq.h>
#include <asm/io.h>
#include <asm/mipsregs.h>
#include <asm/txx9/generic.h>
diff --git a/arch/mips/txx9/rbtx4938/irq.c b/arch/mips/txx9/rbtx4938/irq.c
index 7d21befb8932..67a73a8065ec 100644
--- a/arch/mips/txx9/rbtx4938/irq.c
+++ b/arch/mips/txx9/rbtx4938/irq.c
@@ -64,6 +64,7 @@
*/
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <linux/irq.h>
#include <asm/mipsregs.h>
#include <asm/txx9/generic.h>
#include <asm/txx9/rbtx4938.h>
diff --git a/arch/mips/txx9/rbtx4939/irq.c b/arch/mips/txx9/rbtx4939/irq.c
index 500cc0a908e6..57fa740a7205 100644
--- a/arch/mips/txx9/rbtx4939/irq.c
+++ b/arch/mips/txx9/rbtx4939/irq.c
@@ -11,6 +11,7 @@
*/
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <linux/irq.h>
#include <asm/mipsregs.h>
#include <asm/txx9/rbtx4939.h>
diff --git a/arch/mips/vr41xx/common/irq.c b/arch/mips/vr41xx/common/irq.c
index bef06872f012..0975eb72d385 100644
--- a/arch/mips/vr41xx/common/irq.c
+++ b/arch/mips/vr41xx/common/irq.c
@@ -19,6 +19,7 @@
*/
#include <linux/interrupt.h>
#include <linux/module.h>
+#include <linux/irq.h>
#include <asm/irq_cpu.h>
#include <asm/system.h>
diff --git a/arch/mips/vr41xx/common/siu.c b/arch/mips/vr41xx/common/siu.c
index 54eae56108fb..bbd45d2559d6 100644
--- a/arch/mips/vr41xx/common/siu.c
+++ b/arch/mips/vr41xx/common/siu.c
@@ -22,6 +22,7 @@
#include <linux/ioport.h>
#include <linux/platform_device.h>
#include <linux/serial_core.h>
+#include <linux/irq.h>
#include <asm/cpu.h>
#include <asm/vr41xx/siu.h>
diff --git a/arch/mn10300/include/asm/ioctls.h b/arch/mn10300/include/asm/ioctls.h
index cb8cf1902234..0212f4b22557 100644
--- a/arch/mn10300/include/asm/ioctls.h
+++ b/arch/mn10300/include/asm/ioctls.h
@@ -1,88 +1,6 @@
#ifndef _ASM_IOCTLS_H
#define _ASM_IOCTLS_H
-#include <asm/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS 0x5401
-#define TCSETS 0x5402
-#define TCSETSW 0x5403
-#define TCSETSF 0x5404
-#define TCGETA 0x5405
-#define TCSETA 0x5406
-#define TCSETAW 0x5407
-#define TCSETAF 0x5408
-#define TCSBRK 0x5409
-#define TCXONC 0x540A
-#define TCFLSH 0x540B
-#define TIOCEXCL 0x540C
-#define TIOCNXCL 0x540D
-#define TIOCSCTTY 0x540E
-#define TIOCGPGRP 0x540F
-#define TIOCSPGRP 0x5410
-#define TIOCOUTQ 0x5411
-#define TIOCSTI 0x5412
-#define TIOCGWINSZ 0x5413
-#define TIOCSWINSZ 0x5414
-#define TIOCMGET 0x5415
-#define TIOCMBIS 0x5416
-#define TIOCMBIC 0x5417
-#define TIOCMSET 0x5418
-#define TIOCGSOFTCAR 0x5419
-#define TIOCSSOFTCAR 0x541A
-#define FIONREAD 0x541B
-#define TIOCINQ FIONREAD
-#define TIOCLINUX 0x541C
-#define TIOCCONS 0x541D
-#define TIOCGSERIAL 0x541E
-#define TIOCSSERIAL 0x541F
-#define TIOCPKT 0x5420
-#define FIONBIO 0x5421
-#define TIOCNOTTY 0x5422
-#define TIOCSETD 0x5423
-#define TIOCGETD 0x5424
-#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
-/* #define TIOCTTYGSTRUCT 0x5426 - Former debugging-only ioctl */
-#define TIOCSBRK 0x5427 /* BSD compatibility */
-#define TIOCCBRK 0x5428 /* BSD compatibility */
-#define TIOCGSID 0x5429 /* Return the session ID of FD */
-#define TCGETS2 _IOR('T', 0x2A, struct termios2)
-#define TCSETS2 _IOW('T', 0x2B, struct termios2)
-#define TCSETSW2 _IOW('T', 0x2C, struct termios2)
-#define TCSETSF2 _IOW('T', 0x2D, struct termios2)
-#define TIOCGPTN _IOR('T', 0x30, unsigned int) /* Get Pty Number
- * (of pty-mux device) */
-#define TIOCSPTLCK _IOW('T', 0x31, int) /* Lock/unlock Pty */
-#define TIOCSIG _IOW('T', 0x36, int) /* Generate signal on Pty slave */
-
-#define FIONCLEX 0x5450
-#define FIOCLEX 0x5451
-#define FIOASYNC 0x5452
-#define TIOCSERCONFIG 0x5453
-#define TIOCSERGWILD 0x5454
-#define TIOCSERSWILD 0x5455
-#define TIOCGLCKTRMIOS 0x5456
-#define TIOCSLCKTRMIOS 0x5457
-#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
-#define TIOCSERGETLSR 0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
-#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
-#define FIOQSIZE 0x5460
-
-/* Used for packet mode */
-#define TIOCPKT_DATA 0
-#define TIOCPKT_FLUSHREAD 1
-#define TIOCPKT_FLUSHWRITE 2
-#define TIOCPKT_STOP 4
-#define TIOCPKT_START 8
-#define TIOCPKT_NOSTOP 16
-#define TIOCPKT_DOSTOP 32
-#define TIOCPKT_IOCTL 64
-
-#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
+#include <asm-generic/ioctls.h>
#endif /* _ASM_IOCTLS_H */
diff --git a/arch/mn10300/include/asm/irqflags.h b/arch/mn10300/include/asm/irqflags.h
new file mode 100644
index 000000000000..5e529a117cb2
--- /dev/null
+++ b/arch/mn10300/include/asm/irqflags.h
@@ -0,0 +1,123 @@
+/* MN10300 IRQ flag handling
+ *
+ * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#ifndef _ASM_IRQFLAGS_H
+#define _ASM_IRQFLAGS_H
+
+#include <asm/cpu-regs.h>
+
+/*
+ * interrupt control
+ * - "disabled": run in IM1/2
+ * - level 0 - GDB stub
+ * - level 1 - virtual serial DMA (if present)
+ * - level 5 - normal interrupt priority
+ * - level 6 - timer interrupt
+ * - "enabled": run in IM7
+ */
+#ifdef CONFIG_MN10300_TTYSM
+#define MN10300_CLI_LEVEL EPSW_IM_2
+#else
+#define MN10300_CLI_LEVEL EPSW_IM_1
+#endif
+
+#ifndef __ASSEMBLY__
+
+static inline unsigned long arch_local_save_flags(void)
+{
+ unsigned long flags;
+
+ asm volatile("mov epsw,%0" : "=d"(flags));
+ return flags;
+}
+
+static inline void arch_local_irq_disable(void)
+{
+ asm volatile(
+ " and %0,epsw \n"
+ " or %1,epsw \n"
+ " nop \n"
+ " nop \n"
+ " nop \n"
+ :
+ : "i"(~EPSW_IM), "i"(EPSW_IE | MN10300_CLI_LEVEL)
+ : "memory");
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+ unsigned long flags;
+
+ flags = arch_local_save_flags();
+ arch_local_irq_disable();
+ return flags;
+}
+
+/*
+ * we make sure arch_irq_enable() doesn't cause priority inversion
+ */
+extern unsigned long __mn10300_irq_enabled_epsw;
+
+static inline void arch_local_irq_enable(void)
+{
+ unsigned long tmp;
+
+ asm volatile(
+ " mov epsw,%0 \n"
+ " and %1,%0 \n"
+ " or %2,%0 \n"
+ " mov %0,epsw \n"
+ : "=&d"(tmp)
+ : "i"(~EPSW_IM), "r"(__mn10300_irq_enabled_epsw)
+ : "memory");
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+ asm volatile(
+ " mov %0,epsw \n"
+ " nop \n"
+ " nop \n"
+ " nop \n"
+ :
+ : "d"(flags)
+ : "memory", "cc");
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+ return (flags & EPSW_IM) <= MN10300_CLI_LEVEL;
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+ return arch_irqs_disabled_flags(arch_local_save_flags());
+}
+
+/*
+ * Hook to save power by halting the CPU
+ * - called from the idle loop
+ * - must reenable interrupts (which takes three instruction cycles to complete)
+ */
+static inline void arch_safe_halt(void)
+{
+ asm volatile(
+ " or %0,epsw \n"
+ " nop \n"
+ " nop \n"
+ " bset %2,(%1) \n"
+ :
+ : "i"(EPSW_IE|EPSW_IM), "n"(&CPUM), "i"(CPUM_SLEEP)
+ : "cc");
+}
+
+#endif /* __ASSEMBLY__ */
+#endif /* _ASM_IRQFLAGS_H */
diff --git a/arch/mn10300/include/asm/system.h b/arch/mn10300/include/asm/system.h
index 3636c054dcd5..9f7c7e17c01e 100644
--- a/arch/mn10300/include/asm/system.h
+++ b/arch/mn10300/include/asm/system.h
@@ -17,6 +17,7 @@
#ifndef __ASSEMBLY__
#include <linux/kernel.h>
+#include <linux/irqflags.h>
struct task_struct;
struct thread_struct;
@@ -81,114 +82,6 @@ do { \
/*****************************************************************************/
/*
- * interrupt control
- * - "disabled": run in IM1/2
- * - level 0 - GDB stub
- * - level 1 - virtual serial DMA (if present)
- * - level 5 - normal interrupt priority
- * - level 6 - timer interrupt
- * - "enabled": run in IM7
- */
-#ifdef CONFIG_MN10300_TTYSM
-#define MN10300_CLI_LEVEL EPSW_IM_2
-#else
-#define MN10300_CLI_LEVEL EPSW_IM_1
-#endif
-
-#define local_save_flags(x) \
-do { \
- typecheck(unsigned long, x); \
- asm volatile( \
- " mov epsw,%0 \n" \
- : "=d"(x) \
- ); \
-} while (0)
-
-#define local_irq_disable() \
-do { \
- asm volatile( \
- " and %0,epsw \n" \
- " or %1,epsw \n" \
- " nop \n" \
- " nop \n" \
- " nop \n" \
- : \
- : "i"(~EPSW_IM), "i"(EPSW_IE | MN10300_CLI_LEVEL) \
- ); \
-} while (0)
-
-#define local_irq_save(x) \
-do { \
- local_save_flags(x); \
- local_irq_disable(); \
-} while (0)
-
-/*
- * we make sure local_irq_enable() doesn't cause priority inversion
- */
-#ifndef __ASSEMBLY__
-
-extern unsigned long __mn10300_irq_enabled_epsw;
-
-#endif
-
-#define local_irq_enable() \
-do { \
- unsigned long tmp; \
- \
- asm volatile( \
- " mov epsw,%0 \n" \
- " and %1,%0 \n" \
- " or %2,%0 \n" \
- " mov %0,epsw \n" \
- : "=&d"(tmp) \
- : "i"(~EPSW_IM), "r"(__mn10300_irq_enabled_epsw) \
- : "cc" \
- ); \
-} while (0)
-
-#define local_irq_restore(x) \
-do { \
- typecheck(unsigned long, x); \
- asm volatile( \
- " mov %0,epsw \n" \
- " nop \n" \
- " nop \n" \
- " nop \n" \
- : \
- : "d"(x) \
- : "memory", "cc" \
- ); \
-} while (0)
-
-#define irqs_disabled() \
-({ \
- unsigned long flags; \
- local_save_flags(flags); \
- (flags & EPSW_IM) <= MN10300_CLI_LEVEL; \
-})
-
-/* hook to save power by halting the CPU
- * - called from the idle loop
- * - must reenable interrupts (which takes three instruction cycles to complete)
- */
-#define safe_halt() \
-do { \
- asm volatile(" or %0,epsw \n" \
- " nop \n" \
- " nop \n" \
- " bset %2,(%1) \n" \
- : \
- : "i"(EPSW_IE|EPSW_IM), "n"(&CPUM), "i"(CPUM_SLEEP)\
- : "cc" \
- ); \
-} while (0)
-
-#define STI or EPSW_IE|EPSW_IM,epsw
-#define CLI and ~EPSW_IM,epsw; or EPSW_IE|MN10300_CLI_LEVEL,epsw; nop; nop; nop
-
-/*****************************************************************************/
-/*
* MN10300 doesn't actually have an exchange instruction
*/
#ifndef __ASSEMBLY__
diff --git a/arch/mn10300/kernel/entry.S b/arch/mn10300/kernel/entry.S
index d9ed5a15c547..3d394b4eefba 100644
--- a/arch/mn10300/kernel/entry.S
+++ b/arch/mn10300/kernel/entry.S
@@ -16,6 +16,7 @@
#include <linux/linkage.h>
#include <asm/smp.h>
#include <asm/system.h>
+#include <asm/irqflags.h>
#include <asm/thread_info.h>
#include <asm/intctl-regs.h>
#include <asm/busctl-regs.h>
diff --git a/arch/mn10300/kernel/module.c b/arch/mn10300/kernel/module.c
index 6aea7fd76993..196a111e2e29 100644
--- a/arch/mn10300/kernel/module.c
+++ b/arch/mn10300/kernel/module.c
@@ -206,7 +206,7 @@ int module_finalize(const Elf_Ehdr *hdr,
const Elf_Shdr *sechdrs,
struct module *me)
{
- return module_bug_finalize(hdr, sechdrs, me);
+ return 0;
}
/*
@@ -214,5 +214,4 @@ int module_finalize(const Elf_Ehdr *hdr,
*/
void module_arch_cleanup(struct module *mod)
{
- module_bug_cleanup(mod);
}
diff --git a/arch/mn10300/mm/cache.c b/arch/mn10300/mm/cache.c
index 1b76719ec1c3..9261217e8d2c 100644
--- a/arch/mn10300/mm/cache.c
+++ b/arch/mn10300/mm/cache.c
@@ -54,13 +54,30 @@ EXPORT_SYMBOL(flush_icache_page);
void flush_icache_range(unsigned long start, unsigned long end)
{
#ifdef CONFIG_MN10300_CACHE_WBACK
- unsigned long addr, size, off;
+ unsigned long addr, size, base, off;
struct page *page;
pgd_t *pgd;
pud_t *pud;
pmd_t *pmd;
pte_t *ppte, pte;
+ if (end > 0x80000000UL) {
+ /* addresses above 0xa0000000 do not go through the cache */
+ if (end > 0xa0000000UL) {
+ end = 0xa0000000UL;
+ if (start >= end)
+ return;
+ }
+
+ /* kernel addresses between 0x80000000 and 0x9fffffff do not
+ * require page tables, so we just map such addresses directly */
+ base = (start >= 0x80000000UL) ? start : 0x80000000UL;
+ mn10300_dcache_flush_range(base, end);
+ if (base == start)
+ goto invalidate;
+ end = base;
+ }
+
for (; start < end; start += size) {
/* work out how much of the page to flush */
off = start & (PAGE_SIZE - 1);
@@ -104,6 +121,7 @@ void flush_icache_range(unsigned long start, unsigned long end)
}
#endif
+invalidate:
mn10300_icache_inv();
}
EXPORT_SYMBOL(flush_icache_range);
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index 907417d187e1..79a04a9394d5 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -16,6 +16,7 @@ config PARISC
select RTC_DRV_GENERIC
select INIT_ALL_POSSIBLE
select BUG
+ select HAVE_IRQ_WORK
select HAVE_PERF_EVENTS
select GENERIC_ATOMIC64 if !64BIT
help
diff --git a/arch/parisc/include/asm/irqflags.h b/arch/parisc/include/asm/irqflags.h
new file mode 100644
index 000000000000..34f9cb9b4754
--- /dev/null
+++ b/arch/parisc/include/asm/irqflags.h
@@ -0,0 +1,46 @@
+#ifndef __PARISC_IRQFLAGS_H
+#define __PARISC_IRQFLAGS_H
+
+#include <linux/types.h>
+#include <asm/psw.h>
+
+static inline unsigned long arch_local_save_flags(void)
+{
+ unsigned long flags;
+ asm volatile("ssm 0, %0" : "=r" (flags) : : "memory");
+ return flags;
+}
+
+static inline void arch_local_irq_disable(void)
+{
+ asm volatile("rsm %0,%%r0\n" : : "i" (PSW_I) : "memory");
+}
+
+static inline void arch_local_irq_enable(void)
+{
+ asm volatile("ssm %0,%%r0\n" : : "i" (PSW_I) : "memory");
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+ unsigned long flags;
+ asm volatile("rsm %1,%0" : "=r" (flags) : "i" (PSW_I) : "memory");
+ return flags;
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+ asm volatile("mtsm %0" : : "r" (flags) : "memory");
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+ return (flags & PSW_I) == 0;
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+ return arch_irqs_disabled_flags(arch_local_save_flags());
+}
+
+#endif /* __PARISC_IRQFLAGS_H */
diff --git a/arch/parisc/include/asm/perf_event.h b/arch/parisc/include/asm/perf_event.h
index cc146427d8f9..1e0fd8ba6c03 100644
--- a/arch/parisc/include/asm/perf_event.h
+++ b/arch/parisc/include/asm/perf_event.h
@@ -1,7 +1,6 @@
#ifndef __ASM_PARISC_PERF_EVENT_H
#define __ASM_PARISC_PERF_EVENT_H
-/* parisc only supports software events through this interface. */
-static inline void set_perf_event_pending(void) { }
+/* Empty, just to avoid compiling error */
#endif /* __ASM_PARISC_PERF_EVENT_H */
diff --git a/arch/parisc/include/asm/system.h b/arch/parisc/include/asm/system.h
index 2ab4af58ecb9..b19e63a8e848 100644
--- a/arch/parisc/include/asm/system.h
+++ b/arch/parisc/include/asm/system.h
@@ -1,7 +1,7 @@
#ifndef __PARISC_SYSTEM_H
#define __PARISC_SYSTEM_H
-#include <asm/psw.h>
+#include <linux/irqflags.h>
/* The program status word as bitfields. */
struct pa_psw {
@@ -48,23 +48,6 @@ extern struct task_struct *_switch_to(struct task_struct *, struct task_struct *
(last) = _switch_to(prev, next); \
} while(0)
-/* interrupt control */
-#define local_save_flags(x) __asm__ __volatile__("ssm 0, %0" : "=r" (x) : : "memory")
-#define local_irq_disable() __asm__ __volatile__("rsm %0,%%r0\n" : : "i" (PSW_I) : "memory" )
-#define local_irq_enable() __asm__ __volatile__("ssm %0,%%r0\n" : : "i" (PSW_I) : "memory" )
-
-#define local_irq_save(x) \
- __asm__ __volatile__("rsm %1,%0" : "=r" (x) :"i" (PSW_I) : "memory" )
-#define local_irq_restore(x) \
- __asm__ __volatile__("mtsm %0" : : "r" (x) : "memory" )
-
-#define irqs_disabled() \
-({ \
- unsigned long flags; \
- local_save_flags(flags); \
- (flags & PSW_I) == 0; \
-})
-
#define mfctl(reg) ({ \
unsigned long cr; \
__asm__ __volatile__( \
diff --git a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c
index 159a2b81e90c..6e81bb596e5b 100644
--- a/arch/parisc/kernel/module.c
+++ b/arch/parisc/kernel/module.c
@@ -941,11 +941,10 @@ int module_finalize(const Elf_Ehdr *hdr,
nsyms = newptr - (Elf_Sym *)symhdr->sh_addr;
DEBUGP("NEW num_symtab %lu\n", nsyms);
symhdr->sh_size = nsyms * sizeof(Elf_Sym);
- return module_bug_finalize(hdr, sechdrs, me);
+ return 0;
}
void module_arch_cleanup(struct module *mod)
{
deregister_unwind_table(mod);
- module_bug_cleanup(mod);
}
diff --git a/arch/parisc/kernel/perf.c b/arch/parisc/kernel/perf.c
index f9f6783e4bdd..ba0c053e25ae 100644
--- a/arch/parisc/kernel/perf.c
+++ b/arch/parisc/kernel/perf.c
@@ -46,7 +46,6 @@
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/miscdevice.h>
-#include <linux/smp_lock.h>
#include <linux/spinlock.h>
#include <asm/uaccess.h>
@@ -261,16 +260,13 @@ printk("Preparing to start counters\n");
*/
static int perf_open(struct inode *inode, struct file *file)
{
- lock_kernel();
spin_lock(&perf_lock);
if (perf_enabled) {
spin_unlock(&perf_lock);
- unlock_kernel();
return -EBUSY;
}
perf_enabled = 1;
spin_unlock(&perf_lock);
- unlock_kernel();
return 0;
}
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 631e5a0fb6ab..4b1e521d966f 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -138,6 +138,7 @@ config PPC
select HAVE_OPROFILE
select HAVE_SYSCALL_WRAPPERS if PPC64
select GENERIC_ATOMIC64 if PPC32
+ select HAVE_IRQ_WORK
select HAVE_PERF_EVENTS
select HAVE_REGS_AND_STACK_ACCESS_API
select HAVE_HW_BREAKPOINT if PERF_EVENTS && PPC_BOOK3S_64
diff --git a/arch/powerpc/boot/addnote.c b/arch/powerpc/boot/addnote.c
index b1e5611b2ab1..349b5530d2c4 100644
--- a/arch/powerpc/boot/addnote.c
+++ b/arch/powerpc/boot/addnote.c
@@ -20,7 +20,7 @@
#include <string.h>
/* CHRP note section */
-char arch[] = "PowerPC";
+static const char arch[] = "PowerPC";
#define N_DESCR 6
unsigned int descr[N_DESCR] = {
@@ -33,7 +33,7 @@ unsigned int descr[N_DESCR] = {
};
/* RPA note section */
-char rpaname[] = "IBM,RPA-Client-Config";
+static const char rpaname[] = "IBM,RPA-Client-Config";
/*
* Note: setting ignore_my_client_config *should* mean that OF ignores
diff --git a/arch/powerpc/boot/dts/bluestone.dts b/arch/powerpc/boot/dts/bluestone.dts
new file mode 100644
index 000000000000..9bb3d72c0e5a
--- /dev/null
+++ b/arch/powerpc/boot/dts/bluestone.dts
@@ -0,0 +1,254 @@
+/*
+ * Device Tree for Bluestone (APM821xx) board.
+ *
+ * Copyright (c) 2010, Applied Micro Circuits Corporation
+ * Author: Tirumala R Marri <tmarri@apm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+/dts-v1/;
+
+/ {
+ #address-cells = <2>;
+ #size-cells = <1>;
+ model = "apm,bluestone";
+ compatible = "apm,bluestone";
+ dcr-parent = <&{/cpus/cpu@0}>;
+
+ aliases {
+ ethernet0 = &EMAC0;
+ serial0 = &UART0;
+ serial1 = &UART1;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ device_type = "cpu";
+ model = "PowerPC,apm821xx";
+ reg = <0x00000000>;
+ clock-frequency = <0>; /* Filled in by U-Boot */
+ timebase-frequency = <0>; /* Filled in by U-Boot */
+ i-cache-line-size = <32>;
+ d-cache-line-size = <32>;
+ i-cache-size = <32768>;
+ d-cache-size = <32768>;
+ dcr-controller;
+ dcr-access-method = "native";
+ next-level-cache = <&L2C0>;
+ };
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x00000000 0x00000000 0x00000000>; /* Filled in by U-Boot */
+ };
+
+ UIC0: interrupt-controller0 {
+ compatible = "ibm,uic";
+ interrupt-controller;
+ cell-index = <0>;
+ dcr-reg = <0x0c0 0x009>;
+ #address-cells = <0>;
+ #size-cells = <0>;
+ #interrupt-cells = <2>;
+ };
+
+ UIC1: interrupt-controller1 {
+ compatible = "ibm,uic";
+ interrupt-controller;
+ cell-index = <1>;
+ dcr-reg = <0x0d0 0x009>;
+ #address-cells = <0>;
+ #size-cells = <0>;
+ #interrupt-cells = <2>;
+ interrupts = <0x1e 0x4 0x1f 0x4>; /* cascade */
+ interrupt-parent = <&UIC0>;
+ };
+
+ UIC2: interrupt-controller2 {
+ compatible = "ibm,uic";
+ interrupt-controller;
+ cell-index = <2>;
+ dcr-reg = <0x0e0 0x009>;
+ #address-cells = <0>;
+ #size-cells = <0>;
+ #interrupt-cells = <2>;
+ interrupts = <0xa 0x4 0xb 0x4>; /* cascade */
+ interrupt-parent = <&UIC0>;
+ };
+
+ UIC3: interrupt-controller3 {
+ compatible = "ibm,uic";
+ interrupt-controller;
+ cell-index = <3>;
+ dcr-reg = <0x0f0 0x009>;
+ #address-cells = <0>;
+ #size-cells = <0>;
+ #interrupt-cells = <2>;
+ interrupts = <0x10 0x4 0x11 0x4>; /* cascade */
+ interrupt-parent = <&UIC0>;
+ };
+
+ SDR0: sdr {
+ compatible = "ibm,sdr-apm821xx";
+ dcr-reg = <0x00e 0x002>;
+ };
+
+ CPR0: cpr {
+ compatible = "ibm,cpr-apm821xx";
+ dcr-reg = <0x00c 0x002>;
+ };
+
+ plb {
+ compatible = "ibm,plb4";
+ #address-cells = <2>;
+ #size-cells = <1>;
+ ranges;
+ clock-frequency = <0>; /* Filled in by U-Boot */
+
+ SDRAM0: sdram {
+ compatible = "ibm,sdram-apm821xx";
+ dcr-reg = <0x010 0x002>;
+ };
+
+ MAL0: mcmal {
+ compatible = "ibm,mcmal2";
+ descriptor-memory = "ocm";
+ dcr-reg = <0x180 0x062>;
+ num-tx-chans = <1>;
+ num-rx-chans = <1>;
+ #address-cells = <0>;
+ #size-cells = <0>;
+ interrupt-parent = <&UIC2>;
+ interrupts = < /*TXEOB*/ 0x6 0x4
+ /*RXEOB*/ 0x7 0x4
+ /*SERR*/ 0x3 0x4
+ /*TXDE*/ 0x4 0x4
+ /*RXDE*/ 0x5 0x4
+ };
+
+ POB0: opb {
+ compatible = "ibm,opb";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0xb0000000 0x00000004 0xb0000000 0x50000000>;
+ clock-frequency = <0>; /* Filled in by U-Boot */
+
+ EBC0: ebc {
+ compatible = "ibm,ebc";
+ dcr-reg = <0x012 0x002>;
+ #address-cells = <2>;
+ #size-cells = <1>;
+ clock-frequency = <0>; /* Filled in by U-Boot */
+ /* ranges property is supplied by U-Boot */
+ ranges = < 0x00000003 0x00000000 0xe0000000 0x8000000>;
+ interrupts = <0x6 0x4>;
+ interrupt-parent = <&UIC1>;
+
+ nor_flash@0,0 {
+ compatible = "amd,s29gl512n", "cfi-flash";
+ bank-width = <2>;
+ reg = <0x00000000 0x00000000 0x00400000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ partition@0 {
+ label = "kernel";
+ reg = <0x00000000 0x00180000>;
+ };
+ partition@180000 {
+ label = "env";
+ reg = <0x00180000 0x00020000>;
+ };
+ partition@1a0000 {
+ label = "u-boot";
+ reg = <0x001a0000 0x00060000>;
+ };
+ };
+ }
+
+ UART0: serial@ef600300 {
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0xef600300 0x00000008>;
+ virtual-reg = <0xef600300>;
+ clock-frequency = <0>; /* Filled in by U-Boot */
+ current-speed = <0>; /* Filled in by U-Boot */
+ interrupt-parent = <&UIC1>;
+ interrupts = <0x1 0x4>;
+ };
+
+ IIC0: i2c@ef600700 {
+ compatible = "ibm,iic";
+ reg = <0xef600700 0x00000014>;
+ interrupt-parent = <&UIC0>;
+ interrupts = <0x2 0x4>;
+ };
+
+ IIC1: i2c@ef600800 {
+ compatible = "ibm,iic";
+ reg = <0xef600800 0x00000014>;
+ interrupt-parent = <&UIC0>;
+ interrupts = <0x3 0x4>;
+ };
+
+ RGMII0: emac-rgmii@ef601500 {
+ compatible = "ibm,rgmii";
+ reg = <0xef601500 0x00000008>;
+ has-mdio;
+ };
+
+ TAH0: emac-tah@ef601350 {
+ compatible = "ibm,tah";
+ reg = <0xef601350 0x00000030>;
+ };
+
+ EMAC0: ethernet@ef600c00 {
+ device_type = "network";
+ compatible = "ibm,emac4sync";
+ interrupt-parent = <&EMAC0>;
+ interrupts = <0x0 0x1>;
+ #interrupt-cells = <1>;
+ #address-cells = <0>;
+ #size-cells = <0>;
+ interrupt-map = </*Status*/ 0x0 &UIC2 0x10 0x4
+ /*Wake*/ 0x1 &UIC2 0x14 0x4>;
+ reg = <0xef600c00 0x000000c4>;
+ local-mac-address = [000000000000]; /* Filled in by U-Boot */
+ mal-device = <&MAL0>;
+ mal-tx-channel = <0>;
+ mal-rx-channel = <0>;
+ cell-index = <0>;
+ max-frame-size = <9000>;
+ rx-fifo-size = <16384>;
+ tx-fifo-size = <2048>;
+ phy-mode = "rgmii";
+ phy-map = <0x00000000>;
+ rgmii-device = <&RGMII0>;
+ rgmii-channel = <0>;
+ tah-device = <&TAH0>;
+ tah-channel = <0>;
+ has-inverted-stacr-oc;
+ has-new-stacr-staopc;
+ };
+ };
+
+ };
+};
diff --git a/arch/powerpc/boot/dts/mpc8308_p1m.dts b/arch/powerpc/boot/dts/mpc8308_p1m.dts
new file mode 100644
index 000000000000..05a76ccfd499
--- /dev/null
+++ b/arch/powerpc/boot/dts/mpc8308_p1m.dts
@@ -0,0 +1,332 @@
+/*
+ * mpc8308_p1m Device Tree Source
+ *
+ * Copyright 2010 Ilya Yanok, Emcraft Systems, yanok@emcraft.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+/dts-v1/;
+
+/ {
+ compatible = "denx,mpc8308_p1m";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ aliases {
+ ethernet0 = &enet0;
+ ethernet1 = &enet1;
+ serial0 = &serial0;
+ serial1 = &serial1;
+ pci0 = &pci0;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ PowerPC,8308@0 {
+ device_type = "cpu";
+ reg = <0x0>;
+ d-cache-line-size = <32>;
+ i-cache-line-size = <32>;
+ d-cache-size = <16384>;
+ i-cache-size = <16384>;
+ timebase-frequency = <0>; // from bootloader
+ bus-frequency = <0>; // from bootloader
+ clock-frequency = <0>; // from bootloader
+ };
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x00000000 0x08000000>; // 128MB at 0
+ };
+
+ localbus@e0005000 {
+ #address-cells = <2>;
+ #size-cells = <1>;
+ compatible = "fsl,mpc8315-elbc", "fsl,elbc", "simple-bus";
+ reg = <0xe0005000 0x1000>;
+ interrupts = <77 0x8>;
+ interrupt-parent = <&ipic>;
+
+ ranges = <0x0 0x0 0xfc000000 0x04000000
+ 0x1 0x0 0xfbff0000 0x00008000
+ 0x2 0x0 0xfbff8000 0x00008000>;
+
+ flash@0,0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "cfi-flash";
+ reg = <0x0 0x0 0x4000000>;
+ bank-width = <2>;
+ device-width = <1>;
+
+ u-boot@0 {
+ reg = <0x0 0x60000>;
+ read-only;
+ };
+ env@60000 {
+ reg = <0x60000 0x20000>;
+ };
+ env1@80000 {
+ reg = <0x80000 0x20000>;
+ };
+ kernel@a0000 {
+ reg = <0xa0000 0x200000>;
+ };
+ dtb@2a0000 {
+ reg = <0x2a0000 0x20000>;
+ };
+ ramdisk@2c0000 {
+ reg = <0x2c0000 0x640000>;
+ };
+ user@700000 {
+ reg = <0x700000 0x3900000>;
+ };
+ };
+
+ can@1,0 {
+ compatible = "nxp,sja1000";
+ reg = <0x1 0x0 0x80>;
+ interrupts = <18 0x8>;
+ interrups-parent = <&ipic>;
+ };
+
+ cpld@2,0 {
+ compatible = "denx,mpc8308_p1m-cpld";
+ reg = <0x2 0x0 0x8>;
+ interrupts = <48 0x8>;
+ interrups-parent = <&ipic>;
+ };
+ };
+
+ immr@e0000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "soc";
+ compatible = "fsl,mpc8308-immr", "simple-bus";
+ ranges = <0 0xe0000000 0x00100000>;
+ reg = <0xe0000000 0x00000200>;
+ bus-frequency = <0>;
+
+ i2c@3000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl-i2c";
+ reg = <0x3000 0x100>;
+ interrupts = <14 0x8>;
+ interrupt-parent = <&ipic>;
+ dfsrr;
+ fram@50 {
+ compatible = "ramtron,24c64";
+ reg = <0x50>;
+ };
+ };
+
+ i2c@3100 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl-i2c";
+ reg = <0x3100 0x100>;
+ interrupts = <15 0x8>;
+ interrupt-parent = <&ipic>;
+ dfsrr;
+ pwm@28 {
+ compatible = "maxim,ds1050";
+ reg = <0x28>;
+ };
+ sensor@48 {
+ compatible = "maxim,max6625";
+ reg = <0x48>;
+ };
+ sensor@49 {
+ compatible = "maxim,max6625";
+ reg = <0x49>;
+ };
+ sensor@4b {
+ compatible = "maxim,max6625";
+ reg = <0x4b>;
+ };
+ };
+
+ usb@23000 {
+ compatible = "fsl-usb2-dr";
+ reg = <0x23000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupt-parent = <&ipic>;
+ interrupts = <38 0x8>;
+ dr_mode = "peripheral";
+ phy_type = "ulpi";
+ };
+
+ enet0: ethernet@24000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x0 0x24000 0x1000>;
+
+ cell-index = <0>;
+ device_type = "network";
+ model = "eTSEC";
+ compatible = "gianfar";
+ reg = <0x24000 0x1000>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <32 0x8 33 0x8 34 0x8>;
+ interrupt-parent = <&ipic>;
+ phy-handle = < &phy1 >;
+
+ mdio@520 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,gianfar-mdio";
+ reg = <0x520 0x20>;
+ phy1: ethernet-phy@1 {
+ interrupt-parent = <&ipic>;
+ interrupts = <17 0x8>;
+ reg = <0x1>;
+ device_type = "ethernet-phy";
+ };
+ phy2: ethernet-phy@2 {
+ interrupt-parent = <&ipic>;
+ interrupts = <19 0x8>;
+ reg = <0x2>;
+ device_type = "ethernet-phy";
+ };
+ tbi0: tbi-phy@11 {
+ reg = <0x11>;
+ device_type = "tbi-phy";
+ };
+ };
+ };
+
+ enet1: ethernet@25000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ cell-index = <1>;
+ device_type = "network";
+ model = "eTSEC";
+ compatible = "gianfar";
+ reg = <0x25000 0x1000>;
+ ranges = <0x0 0x25000 0x1000>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <35 0x8 36 0x8 37 0x8>;
+ interrupt-parent = <&ipic>;
+ phy-handle = < &phy2 >;
+
+ mdio@520 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,gianfar-tbi";
+ reg = <0x520 0x20>;
+ tbi1: tbi-phy@11 {
+ reg = <0x11>;
+ device_type = "tbi-phy";
+ };
+ };
+ };
+
+ serial0: serial@4500 {
+ cell-index = <0>;
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0x4500 0x100>;
+ clock-frequency = <133333333>;
+ interrupts = <9 0x8>;
+ interrupt-parent = <&ipic>;
+ };
+
+ serial1: serial@4600 {
+ cell-index = <1>;
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0x4600 0x100>;
+ clock-frequency = <133333333>;
+ interrupts = <10 0x8>;
+ interrupt-parent = <&ipic>;
+ };
+
+ gpio@c00 {
+ #gpio-cells = <2>;
+ compatible = "fsl,mpc8308-gpio", "fsl,mpc8349-gpio";
+ reg = <0xc00 0x18>;
+ interrupts = <74 0x8>;
+ interrupt-parent = <&ipic>;
+ gpio-controller;
+ };
+
+ timer@500 {
+ compatible = "fsl,mpc8308-gtm", "fsl,gtm";
+ reg = <0x500 0x100>;
+ interrupts = <90 8 78 8 84 8 72 8>;
+ interrupt-parent = <&ipic>;
+ clock-frequency = <133333333>;
+ };
+
+ /* IPIC
+ * interrupts cell = <intr #, sense>
+ * sense values match linux IORESOURCE_IRQ_* defines:
+ * sense == 8: Level, low assertion
+ * sense == 2: Edge, high-to-low change
+ */
+ ipic: interrupt-controller@700 {
+ compatible = "fsl,ipic";
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+ reg = <0x700 0x100>;
+ device_type = "ipic";
+ };
+
+ ipic-msi@7c0 {
+ compatible = "fsl,ipic-msi";
+ reg = <0x7c0 0x40>;
+ msi-available-ranges = <0x0 0x100>;
+ interrupts = < 0x43 0x8
+ 0x4 0x8
+ 0x51 0x8
+ 0x52 0x8
+ 0x56 0x8
+ 0x57 0x8
+ 0x58 0x8
+ 0x59 0x8 >;
+ interrupt-parent = < &ipic >;
+ };
+
+ };
+
+ pci0: pcie@e0009000 {
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ device_type = "pci";
+ compatible = "fsl,mpc8308-pcie", "fsl,mpc8314-pcie";
+ reg = <0xe0009000 0x00001000
+ 0xb0000000 0x01000000>;
+ ranges = <0x02000000 0 0xa0000000 0xa0000000 0 0x10000000
+ 0x01000000 0 0x00000000 0xb1000000 0 0x00800000>;
+ bus-range = <0 0>;
+ interrupt-map-mask = <0 0 0 0>;
+ interrupt-map = <0 0 0 0 &ipic 1 8>;
+ interrupts = <0x1 0x8>;
+ interrupt-parent = <&ipic>;
+ clock-frequency = <0>;
+
+ pcie@0 {
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
+ reg = <0 0 0 0 0>;
+ ranges = <0x02000000 0 0xa0000000
+ 0x02000000 0 0xa0000000
+ 0 0x10000000
+ 0x01000000 0 0x00000000
+ 0x01000000 0 0x00000000
+ 0 0x00800000>;
+ };
+ };
+};
diff --git a/arch/powerpc/boot/dts/mpc8536ds.dts b/arch/powerpc/boot/dts/mpc8536ds.dts
index 815cebb2e3e5..a75c10eed269 100644
--- a/arch/powerpc/boot/dts/mpc8536ds.dts
+++ b/arch/powerpc/boot/dts/mpc8536ds.dts
@@ -108,6 +108,58 @@
};
};
+ spi@7000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,mpc8536-espi";
+ reg = <0x7000 0x1000>;
+ interrupts = <59 0x2>;
+ interrupt-parent = <&mpic>;
+ fsl,espi-num-chipselects = <4>;
+
+ flash@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "spansion,s25sl12801";
+ reg = <0>;
+ spi-max-frequency = <40000000>;
+ partition@u-boot {
+ label = "u-boot";
+ reg = <0x00000000 0x00100000>;
+ read-only;
+ };
+ partition@kernel {
+ label = "kernel";
+ reg = <0x00100000 0x00500000>;
+ read-only;
+ };
+ partition@dtb {
+ label = "dtb";
+ reg = <0x00600000 0x00100000>;
+ read-only;
+ };
+ partition@fs {
+ label = "file system";
+ reg = <0x00700000 0x00900000>;
+ };
+ };
+ flash@1 {
+ compatible = "spansion,s25sl12801";
+ reg = <1>;
+ spi-max-frequency = <40000000>;
+ };
+ flash@2 {
+ compatible = "spansion,s25sl12801";
+ reg = <2>;
+ spi-max-frequency = <40000000>;
+ };
+ flash@3 {
+ compatible = "spansion,s25sl12801";
+ reg = <3>;
+ spi-max-frequency = <40000000>;
+ };
+ };
+
dma@21300 {
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/powerpc/boot/dts/p1022ds.dts b/arch/powerpc/boot/dts/p1022ds.dts
index 8bcb10b92677..2bbecbb4cbf9 100644
--- a/arch/powerpc/boot/dts/p1022ds.dts
+++ b/arch/powerpc/boot/dts/p1022ds.dts
@@ -148,6 +148,17 @@
label = "reserved-nand";
};
};
+
+ board-control@3,0 {
+ compatible = "fsl,p1022ds-pixis";
+ reg = <3 0 0x30>;
+ interrupt-parent = <&mpic>;
+ /*
+ * IRQ8 is generated if the "EVENT" switch is pressed
+ * and PX_CTL[EVESEL] is set to 00.
+ */
+ interrupts = <8 8>;
+ };
};
soc@fffe00000 {
diff --git a/arch/powerpc/boot/dts/p4080ds.dts b/arch/powerpc/boot/dts/p4080ds.dts
index 2f0de24e3822..5b7fc29dd6cf 100644
--- a/arch/powerpc/boot/dts/p4080ds.dts
+++ b/arch/powerpc/boot/dts/p4080ds.dts
@@ -236,22 +236,19 @@
};
spi@110000 {
- cell-index = <0>;
#address-cells = <1>;
#size-cells = <0>;
- compatible = "fsl,espi";
+ compatible = "fsl,p4080-espi", "fsl,mpc8536-espi";
reg = <0x110000 0x1000>;
interrupts = <53 0x2>;
interrupt-parent = <&mpic>;
- espi,num-ss-bits = <4>;
- mode = "cpu";
+ fsl,espi-num-chipselects = <4>;
- fsl_m25p80@0 {
+ flash@0 {
#address-cells = <1>;
#size-cells = <1>;
- compatible = "fsl,espi-flash";
+ compatible = "spansion,s25sl12801";
reg = <0>;
- linux,modalias = "fsl_m25p80";
spi-max-frequency = <40000000>; /* input clock */
partition@u-boot {
label = "u-boot";
diff --git a/arch/powerpc/configs/44x/bluestone_defconfig b/arch/powerpc/configs/44x/bluestone_defconfig
new file mode 100644
index 000000000000..ac65b48b8ccd
--- /dev/null
+++ b/arch/powerpc/configs/44x/bluestone_defconfig
@@ -0,0 +1,68 @@
+CONFIG_44x=y
+CONFIG_EXPERIMENTAL=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_EMBEDDED=y
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_PCI_QUIRKS is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_BLUESTONE=y
+# CONFIG_EBONY is not set
+# CONFIG_KVM_GUEST is not set
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE=""
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_CONNECTOR=y
+CONFIG_MTD=y
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_OF_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_PROC_DEVICETREE=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=35000
+CONFIG_NETDEVICES=y
+CONFIG_NET_ETHERNET=y
+CONFIG_IBM_NEW_EMAC=y
+CONFIG_IBM_NEW_EMAC_RXB=256
+CONFIG_IBM_NEW_EMAC_TXB=256
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_IBM_IIC=y
+CONFIG_SENSORS_AD7414=y
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_M41T80=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_CRAMFS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS=y
diff --git a/arch/powerpc/configs/e55xx_smp_defconfig b/arch/powerpc/configs/e55xx_smp_defconfig
new file mode 100644
index 000000000000..94d120ef99cf
--- /dev/null
+++ b/arch/powerpc/configs/e55xx_smp_defconfig
@@ -0,0 +1,84 @@
+CONFIG_PPC64=y
+CONFIG_PPC_BOOK3E_64=y
+# CONFIG_VIRT_CPU_ACCOUNTING is not set
+CONFIG_SMP=y
+CONFIG_NR_CPUS=2
+CONFIG_EXPERIMENTAL=y
+CONFIG_SYSVIPC=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_P5020_DS=y
+# CONFIG_PPC_OF_BOOT_TRAMPOLINE is not set
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BINFMT_MISC=m
+CONFIG_SPARSE_IRQ=y
+# CONFIG_PCI is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_PROC_DEVICETREE=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=131072
+CONFIG_EEPROM_LEGACY=y
+CONFIG_INPUT_FF_MEMLESS=m
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+CONFIG_I2C=y
+# CONFIG_HWMON is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=y
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_DMADEVICES=y
+CONFIG_FSL_DMA=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_MAC_PARTITION=y
+CONFIG_NLS=y
+CONFIG_NLS_UTF8=m
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=m
+CONFIG_LIBCRC32C=m
+CONFIG_FRAME_WARN=1024
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_VIRQ_DEBUG=y
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_DEV_TALITOS=y
diff --git a/arch/powerpc/configs/ppc44x_defconfig b/arch/powerpc/configs/ppc44x_defconfig
index cd446fba3fae..2fa05f7be4cb 100644
--- a/arch/powerpc/configs/ppc44x_defconfig
+++ b/arch/powerpc/configs/ppc44x_defconfig
@@ -12,6 +12,7 @@ CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_BLK_DEV_BSG is not set
CONFIG_BAMBOO=y
+CONFIG_BLUESTONE=y
CONFIG_SAM440EP=y
CONFIG_SEQUOIA=y
CONFIG_TAISHAN=y
@@ -97,14 +98,17 @@ CONFIG_USB_STORAGE=m
CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=m
# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-CONFIG_INOTIFY=y
CONFIG_VFAT_FS=m
CONFIG_PROC_KCORE=y
CONFIG_TMPFS=y
CONFIG_JFFS2_FS=y
CONFIG_UBIFS_FS=m
CONFIG_UBIFS_FS_XATTR=y
+CONFIG_LOGFS=m
CONFIG_CRAMFS=y
+CONFIG_SQUASHFS=m
+CONFIG_SQUASHFS_XATTR=y
+CONFIG_SQUASHFS_LZO=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
CONFIG_ROOT_NFS=y
@@ -116,11 +120,8 @@ CONFIG_DEBUG_KERNEL=y
CONFIG_DETECT_HUNG_TASK=y
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_CRYPTO_CBC=y
CONFIG_CRYPTO_ECB=y
CONFIG_CRYPTO_PCBC=y
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_ANSI_CPRNG is not set
# CONFIG_CRYPTO_HW is not set
CONFIG_VIRTUALIZATION=y
diff --git a/arch/powerpc/configs/ppc64e_defconfig b/arch/powerpc/configs/ppc64e_defconfig
index 04ae0740b6d0..7bd1763877ba 100644
--- a/arch/powerpc/configs/ppc64e_defconfig
+++ b/arch/powerpc/configs/ppc64e_defconfig
@@ -18,6 +18,7 @@ CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_P5020_DS=y
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=y
CONFIG_CPU_FREQ_GOV_USERSPACE=y
@@ -256,7 +257,6 @@ CONFIG_HID_ZEROPLUS=y
CONFIG_USB=y
CONFIG_USB_DEVICEFS=y
CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_TT_NEWSCHED=y
# CONFIG_USB_EHCI_HCD_PPC_OF is not set
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_STORAGE=m
@@ -290,7 +290,6 @@ CONFIG_JFS_POSIX_ACL=y
CONFIG_JFS_SECURITY=y
CONFIG_XFS_FS=m
CONFIG_XFS_POSIX_ACL=y
-CONFIG_INOTIFY=y
CONFIG_AUTOFS4_FS=m
CONFIG_ISO9660_FS=y
CONFIG_UDF_FS=m
@@ -384,7 +383,6 @@ CONFIG_CRYPTO_TGR192=m
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_AES=m
CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_ARC4=m
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAST6=m
CONFIG_CRYPTO_KHAZAD=m
diff --git a/arch/powerpc/include/asm/checksum.h b/arch/powerpc/include/asm/checksum.h
index 7cdf358337cf..ce0c28495f9a 100644
--- a/arch/powerpc/include/asm/checksum.h
+++ b/arch/powerpc/include/asm/checksum.h
@@ -52,12 +52,22 @@ extern __wsum csum_partial(const void *buff, int len, __wsum sum);
extern __wsum csum_partial_copy_generic(const void *src, void *dst,
int len, __wsum sum,
int *src_err, int *dst_err);
+
+#ifdef __powerpc64__
+#define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER
+extern __wsum csum_and_copy_from_user(const void __user *src, void *dst,
+ int len, __wsum sum, int *err_ptr);
+#define HAVE_CSUM_COPY_USER
+extern __wsum csum_and_copy_to_user(const void *src, void __user *dst,
+ int len, __wsum sum, int *err_ptr);
+#else
/*
* the same as csum_partial, but copies from src to dst while it
* checksums.
*/
#define csum_partial_copy_from_user(src, dst, len, sum, errp) \
csum_partial_copy_generic((__force const void *)(src), (dst), (len), (sum), (errp), NULL)
+#endif
#define csum_partial_copy_nocheck(src, dst, len, sum) \
csum_partial_copy_generic((src), (dst), (len), (sum), NULL, NULL)
diff --git a/arch/powerpc/include/asm/compat.h b/arch/powerpc/include/asm/compat.h
index a11d4eac4f97..2296112e247b 100644
--- a/arch/powerpc/include/asm/compat.h
+++ b/arch/powerpc/include/asm/compat.h
@@ -143,7 +143,7 @@ static inline void __user *arch_compat_alloc_user_space(long len)
* We cant access below the stack pointer in the 32bit ABI and
* can access 288 bytes in the 64bit ABI
*/
- if (!(test_thread_flag(TIF_32BIT)))
+ if (!is_32bit_task())
usp -= 288;
return (void __user *) (usp - len);
@@ -213,7 +213,7 @@ struct compat_shmid64_ds {
static inline int is_compat_task(void)
{
- return test_thread_flag(TIF_32BIT);
+ return is_32bit_task();
}
#endif /* __KERNEL__ */
diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h
index 3a40a992e594..f3a1fdd9cf08 100644
--- a/arch/powerpc/include/asm/cputable.h
+++ b/arch/powerpc/include/asm/cputable.h
@@ -198,6 +198,7 @@ extern const char *powerpc_base_platform;
#define CPU_FTR_CP_USE_DCBTZ LONG_ASM_CONST(0x0040000000000000)
#define CPU_FTR_UNALIGNED_LD_STD LONG_ASM_CONST(0x0080000000000000)
#define CPU_FTR_ASYM_SMT LONG_ASM_CONST(0x0100000000000000)
+#define CPU_FTR_STCX_CHECKS_ADDRESS LONG_ASM_CONST(0x0200000000000000)
#ifndef __ASSEMBLY__
@@ -392,28 +393,31 @@ extern const char *powerpc_base_platform;
CPU_FTR_MMCRA | CPU_FTR_CTRL)
#define CPU_FTRS_POWER4 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
- CPU_FTR_MMCRA | CPU_FTR_CP_USE_DCBTZ)
+ CPU_FTR_MMCRA | CPU_FTR_CP_USE_DCBTZ | \
+ CPU_FTR_STCX_CHECKS_ADDRESS)
#define CPU_FTRS_PPC970 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
CPU_FTR_ALTIVEC_COMP | CPU_FTR_CAN_NAP | CPU_FTR_MMCRA | \
- CPU_FTR_CP_USE_DCBTZ)
+ CPU_FTR_CP_USE_DCBTZ | CPU_FTR_STCX_CHECKS_ADDRESS)
#define CPU_FTRS_POWER5 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
CPU_FTR_MMCRA | CPU_FTR_SMT | \
CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
- CPU_FTR_PURR)
+ CPU_FTR_PURR | CPU_FTR_STCX_CHECKS_ADDRESS)
#define CPU_FTRS_POWER6 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
CPU_FTR_MMCRA | CPU_FTR_SMT | \
CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \
- CPU_FTR_DSCR | CPU_FTR_UNALIGNED_LD_STD)
+ CPU_FTR_DSCR | CPU_FTR_UNALIGNED_LD_STD | \
+ CPU_FTR_STCX_CHECKS_ADDRESS)
#define CPU_FTRS_POWER7 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
CPU_FTR_MMCRA | CPU_FTR_SMT | \
CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \
- CPU_FTR_DSCR | CPU_FTR_SAO | CPU_FTR_ASYM_SMT)
+ CPU_FTR_DSCR | CPU_FTR_SAO | CPU_FTR_ASYM_SMT | \
+ CPU_FTR_STCX_CHECKS_ADDRESS)
#define CPU_FTRS_CELL (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h
index 8c9c6ad2004e..6d2416a85709 100644
--- a/arch/powerpc/include/asm/dma-mapping.h
+++ b/arch/powerpc/include/asm/dma-mapping.h
@@ -127,19 +127,7 @@ static inline int dma_supported(struct device *dev, u64 mask)
return dma_ops->dma_supported(dev, mask);
}
-static inline int dma_set_mask(struct device *dev, u64 dma_mask)
-{
- struct dma_map_ops *dma_ops = get_dma_ops(dev);
-
- if (unlikely(dma_ops == NULL))
- return -EIO;
- if (dma_ops->set_dma_mask != NULL)
- return dma_ops->set_dma_mask(dev, dma_mask);
- if (!dev->dma_mask || !dma_supported(dev, dma_mask))
- return -EIO;
- *dev->dma_mask = dma_mask;
- return 0;
-}
+extern int dma_set_mask(struct device *dev, u64 dma_mask);
static inline void *dma_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flag)
diff --git a/arch/powerpc/include/asm/elf.h b/arch/powerpc/include/asm/elf.h
index c376eda15313..2b917c69ed15 100644
--- a/arch/powerpc/include/asm/elf.h
+++ b/arch/powerpc/include/asm/elf.h
@@ -250,7 +250,7 @@ do { \
* the 64bit ABI has never had these issues dont enable the workaround
* even if we have an executable stack.
*/
-# define elf_read_implies_exec(ex, exec_stk) (test_thread_flag(TIF_32BIT) ? \
+# define elf_read_implies_exec(ex, exec_stk) (is_32bit_task() ? \
(exec_stk == EXSTACK_DEFAULT) : 0)
#else
# define SET_PERSONALITY(ex) \
diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h
index 57c400071995..7778d6f0c878 100644
--- a/arch/powerpc/include/asm/exception-64s.h
+++ b/arch/powerpc/include/asm/exception-64s.h
@@ -137,7 +137,8 @@
li r10,0; \
ld r11,exception_marker@toc(r2); \
std r10,RESULT(r1); /* clear regs->result */ \
- std r11,STACK_FRAME_OVERHEAD-16(r1); /* mark the frame */
+ std r11,STACK_FRAME_OVERHEAD-16(r1); /* mark the frame */ \
+ ACCOUNT_STOLEN_TIME
/*
* Exception vectors.
diff --git a/arch/powerpc/include/asm/fsl_85xx_cache_sram.h b/arch/powerpc/include/asm/fsl_85xx_cache_sram.h
new file mode 100644
index 000000000000..2af2bdc37b2e
--- /dev/null
+++ b/arch/powerpc/include/asm/fsl_85xx_cache_sram.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2009 Freescale Semiconductor, Inc.
+ *
+ * Cache SRAM handling for QorIQ platform
+ *
+ * Author: Vivek Mahajan <vivek.mahajan@freescale.com>
+
+ * This file is derived from the original work done
+ * by Sylvain Munaut for the Bestcomm SRAM allocator.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __ASM_POWERPC_FSL_85XX_CACHE_SRAM_H__
+#define __ASM_POWERPC_FSL_85XX_CACHE_SRAM_H__
+
+#include <asm/rheap.h>
+#include <linux/spinlock.h>
+
+/*
+ * Cache-SRAM
+ */
+
+struct mpc85xx_cache_sram {
+ phys_addr_t base_phys;
+ void *base_virt;
+ unsigned int size;
+ rh_info_t *rh;
+ spinlock_t lock;
+};
+
+extern void mpc85xx_cache_sram_free(void *ptr);
+extern void *mpc85xx_cache_sram_alloc(unsigned int size,
+ phys_addr_t *phys, unsigned int align);
+
+#endif /* __AMS_POWERPC_FSL_85XX_CACHE_SRAM_H__ */
diff --git a/arch/powerpc/include/asm/hw_irq.h b/arch/powerpc/include/asm/hw_irq.h
index bd100fcf40d0..ff08b70b36d4 100644
--- a/arch/powerpc/include/asm/hw_irq.h
+++ b/arch/powerpc/include/asm/hw_irq.h
@@ -16,42 +16,57 @@ extern void timer_interrupt(struct pt_regs *);
#ifdef CONFIG_PPC64
#include <asm/paca.h>
-static inline unsigned long local_get_flags(void)
+static inline unsigned long arch_local_save_flags(void)
{
unsigned long flags;
- __asm__ __volatile__("lbz %0,%1(13)"
- : "=r" (flags)
- : "i" (offsetof(struct paca_struct, soft_enabled)));
+ asm volatile(
+ "lbz %0,%1(13)"
+ : "=r" (flags)
+ : "i" (offsetof(struct paca_struct, soft_enabled)));
return flags;
}
-static inline unsigned long raw_local_irq_disable(void)
+static inline unsigned long arch_local_irq_disable(void)
{
unsigned long flags, zero;
- __asm__ __volatile__("li %1,0; lbz %0,%2(13); stb %1,%2(13)"
- : "=r" (flags), "=&r" (zero)
- : "i" (offsetof(struct paca_struct, soft_enabled))
- : "memory");
+ asm volatile(
+ "li %1,0; lbz %0,%2(13); stb %1,%2(13)"
+ : "=r" (flags), "=&r" (zero)
+ : "i" (offsetof(struct paca_struct, soft_enabled))
+ : "memory");
return flags;
}
-extern void raw_local_irq_restore(unsigned long);
+extern void arch_local_irq_restore(unsigned long);
extern void iseries_handle_interrupts(void);
-#define raw_local_irq_enable() raw_local_irq_restore(1)
-#define raw_local_save_flags(flags) ((flags) = local_get_flags())
-#define raw_local_irq_save(flags) ((flags) = raw_local_irq_disable())
+static inline void arch_local_irq_enable(void)
+{
+ arch_local_irq_restore(1);
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+ return arch_local_irq_disable();
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+ return flags == 0;
+}
-#define raw_irqs_disabled() (local_get_flags() == 0)
-#define raw_irqs_disabled_flags(flags) ((flags) == 0)
+static inline bool arch_irqs_disabled(void)
+{
+ return arch_irqs_disabled_flags(arch_local_save_flags());
+}
#ifdef CONFIG_PPC_BOOK3E
-#define __hard_irq_enable() __asm__ __volatile__("wrteei 1": : :"memory");
-#define __hard_irq_disable() __asm__ __volatile__("wrteei 0": : :"memory");
+#define __hard_irq_enable() asm volatile("wrteei 1" : : : "memory");
+#define __hard_irq_disable() asm volatile("wrteei 0" : : : "memory");
#else
#define __hard_irq_enable() __mtmsrd(mfmsr() | MSR_EE, 1)
#define __hard_irq_disable() __mtmsrd(mfmsr() & ~MSR_EE, 1)
@@ -64,64 +79,66 @@ extern void iseries_handle_interrupts(void);
get_paca()->hard_enabled = 0; \
} while(0)
-#else
+#else /* CONFIG_PPC64 */
-#if defined(CONFIG_BOOKE)
#define SET_MSR_EE(x) mtmsr(x)
-#define raw_local_irq_restore(flags) __asm__ __volatile__("wrtee %0" : : "r" (flags) : "memory")
+
+static inline unsigned long arch_local_save_flags(void)
+{
+ return mfmsr();
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+#if defined(CONFIG_BOOKE)
+ asm volatile("wrtee %0" : : "r" (flags) : "memory");
#else
-#define SET_MSR_EE(x) mtmsr(x)
-#define raw_local_irq_restore(flags) mtmsr(flags)
+ mtmsr(flags);
#endif
+}
-static inline void raw_local_irq_disable(void)
+static inline unsigned long arch_local_irq_save(void)
{
+ unsigned long flags = arch_local_save_flags();
#ifdef CONFIG_BOOKE
- __asm__ __volatile__("wrteei 0": : :"memory");
+ asm volatile("wrteei 0" : : : "memory");
#else
- unsigned long msr;
-
- msr = mfmsr();
- SET_MSR_EE(msr & ~MSR_EE);
+ SET_MSR_EE(flags & ~MSR_EE);
#endif
+ return flags;
}
-static inline void raw_local_irq_enable(void)
+static inline void arch_local_irq_disable(void)
{
#ifdef CONFIG_BOOKE
- __asm__ __volatile__("wrteei 1": : :"memory");
+ asm volatile("wrteei 0" : : : "memory");
#else
- unsigned long msr;
-
- msr = mfmsr();
- SET_MSR_EE(msr | MSR_EE);
+ arch_local_irq_save();
#endif
}
-static inline void raw_local_irq_save_ptr(unsigned long *flags)
+static inline void arch_local_irq_enable(void)
{
- unsigned long msr;
- msr = mfmsr();
- *flags = msr;
#ifdef CONFIG_BOOKE
- __asm__ __volatile__("wrteei 0": : :"memory");
+ asm volatile("wrteei 1" : : : "memory");
#else
- SET_MSR_EE(msr & ~MSR_EE);
+ unsigned long msr = mfmsr();
+ SET_MSR_EE(msr | MSR_EE);
#endif
}
-#define raw_local_save_flags(flags) ((flags) = mfmsr())
-#define raw_local_irq_save(flags) raw_local_irq_save_ptr(&flags)
-#define raw_irqs_disabled() ((mfmsr() & MSR_EE) == 0)
-#define raw_irqs_disabled_flags(flags) (((flags) & MSR_EE) == 0)
-
-#define hard_irq_disable() raw_local_irq_disable()
-
-static inline int irqs_disabled_flags(unsigned long flags)
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
{
return (flags & MSR_EE) == 0;
}
+static inline bool arch_irqs_disabled(void)
+{
+ return arch_irqs_disabled_flags(arch_local_save_flags());
+}
+
+#define hard_irq_disable() arch_local_irq_disable()
+
#endif /* CONFIG_PPC64 */
/*
diff --git a/arch/powerpc/include/asm/irqflags.h b/arch/powerpc/include/asm/irqflags.h
index 5f68ecfdf516..b85d8ddbb666 100644
--- a/arch/powerpc/include/asm/irqflags.h
+++ b/arch/powerpc/include/asm/irqflags.h
@@ -6,7 +6,7 @@
#ifndef __ASSEMBLY__
/*
- * Get definitions for raw_local_save_flags(x), etc.
+ * Get definitions for arch_local_save_flags(x), etc.
*/
#include <asm/hw_irq.h>
diff --git a/arch/powerpc/include/asm/kexec.h b/arch/powerpc/include/asm/kexec.h
index 076327f2eff7..f54408d995b5 100644
--- a/arch/powerpc/include/asm/kexec.h
+++ b/arch/powerpc/include/asm/kexec.h
@@ -91,6 +91,7 @@ extern void machine_kexec_simple(struct kimage *image);
extern void crash_kexec_secondary(struct pt_regs *regs);
extern int overlaps_crashkernel(unsigned long start, unsigned long size);
extern void reserve_crashkernel(void);
+extern void machine_kexec_mask_interrupts(void);
#else /* !CONFIG_KEXEC */
static inline int kexec_sr_activated(int cpu) { return 0; }
diff --git a/arch/powerpc/include/asm/kvm_fpu.h b/arch/powerpc/include/asm/kvm_fpu.h
index c3d4f0518a67..92daae132492 100644
--- a/arch/powerpc/include/asm/kvm_fpu.h
+++ b/arch/powerpc/include/asm/kvm_fpu.h
@@ -82,7 +82,7 @@ FPD_THREE_IN(fmadd)
FPD_THREE_IN(fnmsub)
FPD_THREE_IN(fnmadd)
-extern void kvm_cvt_fd(u32 *from, u64 *to, u64 *fpscr);
-extern void kvm_cvt_df(u64 *from, u32 *to, u64 *fpscr);
+extern void kvm_cvt_fd(u32 *from, u64 *to);
+extern void kvm_cvt_df(u64 *from, u32 *to);
#endif
diff --git a/arch/powerpc/include/asm/lppaca.h b/arch/powerpc/include/asm/lppaca.h
index 14b592dfb4e8..7f5e0fefebb0 100644
--- a/arch/powerpc/include/asm/lppaca.h
+++ b/arch/powerpc/include/asm/lppaca.h
@@ -153,6 +153,8 @@ struct lppaca {
extern struct lppaca lppaca[];
+#define lppaca_of(cpu) (*paca[cpu].lppaca_ptr)
+
/*
* SLB shadow buffer structure as defined in the PAPR. The save_area
* contains adjacent ESID and VSID pairs for each shadowed SLB. The
@@ -170,6 +172,33 @@ struct slb_shadow {
extern struct slb_shadow slb_shadow[];
+/*
+ * Layout of entries in the hypervisor's dispatch trace log buffer.
+ */
+struct dtl_entry {
+ u8 dispatch_reason;
+ u8 preempt_reason;
+ u16 processor_id;
+ u32 enqueue_to_dispatch_time;
+ u32 ready_to_enqueue_time;
+ u32 waiting_to_ready_time;
+ u64 timebase;
+ u64 fault_addr;
+ u64 srr0;
+ u64 srr1;
+};
+
+#define DISPATCH_LOG_BYTES 4096 /* bytes per cpu */
+#define N_DISPATCH_LOG (DISPATCH_LOG_BYTES / sizeof(struct dtl_entry))
+
+/*
+ * When CONFIG_VIRT_CPU_ACCOUNTING = y, the cpu accounting code controls
+ * reading from the dispatch trace log. If other code wants to consume
+ * DTL entries, it can set this pointer to a function that will get
+ * called once for each DTL entry that gets processed.
+ */
+extern void (*dtl_consumer)(struct dtl_entry *entry, u64 index);
+
#endif /* CONFIG_PPC_BOOK3S */
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_LPPACA_H */
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h
index adc8e6cdf339..d045b0145537 100644
--- a/arch/powerpc/include/asm/machdep.h
+++ b/arch/powerpc/include/asm/machdep.h
@@ -102,6 +102,9 @@ struct machdep_calls {
void (*pci_dma_dev_setup)(struct pci_dev *dev);
void (*pci_dma_bus_setup)(struct pci_bus *bus);
+ /* Platform set_dma_mask override */
+ int (*dma_set_mask)(struct device *dev, u64 dma_mask);
+
int (*probe)(void);
void (*setup_arch)(void); /* Optional, may be NULL */
void (*init_early)(void);
diff --git a/arch/powerpc/include/asm/memblock.h b/arch/powerpc/include/asm/memblock.h
index 3c29728b56b1..43efc345065e 100644
--- a/arch/powerpc/include/asm/memblock.h
+++ b/arch/powerpc/include/asm/memblock.h
@@ -5,11 +5,4 @@
#define MEMBLOCK_DBG(fmt...) udbg_printf(fmt)
-#ifdef CONFIG_PPC32
-extern phys_addr_t lowmem_end_addr;
-#define MEMBLOCK_REAL_LIMIT lowmem_end_addr
-#else
-#define MEMBLOCK_REAL_LIMIT 0
-#endif
-
#endif /* _ASM_POWERPC_MEMBLOCK_H */
diff --git a/arch/powerpc/include/asm/mmu-book3e.h b/arch/powerpc/include/asm/mmu-book3e.h
index 87a1d787c5b6..8eaed81ea642 100644
--- a/arch/powerpc/include/asm/mmu-book3e.h
+++ b/arch/powerpc/include/asm/mmu-book3e.h
@@ -114,6 +114,17 @@
#define MAS7_RPN 0xFFFFFFFF
+/* Bit definitions for MMUCFG */
+#define MMUCFG_MAVN 0x00000003 /* MMU Architecture Version Number */
+#define MMUCFG_MAVN_V1 0x00000000 /* v1.0 */
+#define MMUCFG_MAVN_V2 0x00000001 /* v2.0 */
+#define MMUCFG_NTLBS 0x0000000c /* Number of TLBs */
+#define MMUCFG_PIDSIZE 0x000007c0 /* PID Reg Size */
+#define MMUCFG_TWC 0x00008000 /* TLB Write Conditional (v2.0) */
+#define MMUCFG_LRAT 0x00010000 /* LRAT Supported (v2.0) */
+#define MMUCFG_RASIZE 0x00fe0000 /* Real Addr Size */
+#define MMUCFG_LPIDSIZE 0x0f000000 /* LPID Reg Size */
+
/* Bit definitions for MMUCSR0 */
#define MMUCSR0_TLB1FI 0x00000002 /* TLB1 Flash invalidate */
#define MMUCSR0_TLB0FI 0x00000004 /* TLB0 Flash invalidate */
@@ -133,6 +144,10 @@
#define TLBnCFG_GTWE 0x00010000 /* Guest can write */
#define TLBnCFG_IND 0x00020000 /* IND entries supported */
#define TLBnCFG_PT 0x00040000 /* Can load from page table */
+#define TLBnCFG_MINSIZE 0x00f00000 /* Minimum Page Size (v1.0) */
+#define TLBnCFG_MINSIZE_SHIFT 20
+#define TLBnCFG_MAXSIZE 0x000f0000 /* Maximum Page Size (v1.0) */
+#define TLBnCFG_MAXSIZE_SHIFT 16
#define TLBnCFG_ASSOC 0xff000000 /* Associativity */
/* TLBnPS encoding */
diff --git a/arch/powerpc/include/asm/mmu.h b/arch/powerpc/include/asm/mmu.h
index 7ebf42ed84a2..bb40a06d3b77 100644
--- a/arch/powerpc/include/asm/mmu.h
+++ b/arch/powerpc/include/asm/mmu.h
@@ -2,6 +2,8 @@
#define _ASM_POWERPC_MMU_H_
#ifdef __KERNEL__
+#include <linux/types.h>
+
#include <asm/asm-compat.h>
#include <asm/feature-fixups.h>
@@ -82,6 +84,16 @@ extern unsigned int __start___mmu_ftr_fixup, __stop___mmu_ftr_fixup;
extern void early_init_mmu(void);
extern void early_init_mmu_secondary(void);
+extern void setup_initial_memory_limit(phys_addr_t first_memblock_base,
+ phys_addr_t first_memblock_size);
+
+#ifdef CONFIG_PPC64
+/* This is our real memory area size on ppc64 server, on embedded, we
+ * make it match the size our of bolted TLB area
+ */
+extern u64 ppc64_rma_size;
+#endif /* CONFIG_PPC64 */
+
#endif /* !__ASSEMBLY__ */
/* The kernel use the constants below to index in the page sizes array.
diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h
index 1ff6662f7faf..ec57540cd7af 100644
--- a/arch/powerpc/include/asm/paca.h
+++ b/arch/powerpc/include/asm/paca.h
@@ -85,6 +85,8 @@ struct paca_struct {
u8 kexec_state; /* set when kexec down has irqs off */
#ifdef CONFIG_PPC_STD_MMU_64
struct slb_shadow *slb_shadow_ptr;
+ struct dtl_entry *dispatch_log;
+ struct dtl_entry *dispatch_log_end;
/*
* Now, starting in cacheline 2, the exception save areas
@@ -129,13 +131,19 @@ struct paca_struct {
u8 soft_enabled; /* irq soft-enable flag */
u8 hard_enabled; /* set if irqs are enabled in MSR */
u8 io_sync; /* writel() needs spin_unlock sync */
- u8 perf_event_pending; /* PM interrupt while soft-disabled */
+ u8 irq_work_pending; /* IRQ_WORK interrupt while soft-disable */
/* Stuff for accurate time accounting */
u64 user_time; /* accumulated usermode TB ticks */
u64 system_time; /* accumulated system TB ticks */
- u64 startpurr; /* PURR/TB value snapshot */
+ u64 user_time_scaled; /* accumulated usermode SPURR ticks */
+ u64 starttime; /* TB value snapshot */
+ u64 starttime_user; /* TB value on exit to usermode */
u64 startspurr; /* SPURR value snapshot */
+ u64 utime_sspurr; /* ->user_time when ->startspurr set */
+ u64 stolen_time; /* TB ticks taken by hypervisor */
+ u64 dtl_ridx; /* read index in dispatch log */
+ struct dtl_entry *dtl_curr; /* pointer corresponding to dtl_ridx */
#ifdef CONFIG_KVM_BOOK3S_HANDLER
/* We use this to store guest state in */
diff --git a/arch/powerpc/include/asm/page_64.h b/arch/powerpc/include/asm/page_64.h
index 358ff14ea25e..932f88dcf6fa 100644
--- a/arch/powerpc/include/asm/page_64.h
+++ b/arch/powerpc/include/asm/page_64.h
@@ -163,7 +163,7 @@ do { \
#endif /* !CONFIG_HUGETLB_PAGE */
#define VM_DATA_DEFAULT_FLAGS \
- (test_thread_flag(TIF_32BIT) ? \
+ (is_32bit_task() ? \
VM_DATA_DEFAULT_FLAGS32 : VM_DATA_DEFAULT_FLAGS64)
/*
@@ -179,7 +179,7 @@ do { \
VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
#define VM_STACK_DEFAULT_FLAGS \
- (test_thread_flag(TIF_32BIT) ? \
+ (is_32bit_task() ? \
VM_STACK_DEFAULT_FLAGS32 : VM_STACK_DEFAULT_FLAGS64)
#include <asm-generic/getorder.h>
diff --git a/arch/powerpc/include/asm/ppc-pci.h b/arch/powerpc/include/asm/ppc-pci.h
index 42fdff0e4b32..43268f15004e 100644
--- a/arch/powerpc/include/asm/ppc-pci.h
+++ b/arch/powerpc/include/asm/ppc-pci.h
@@ -28,8 +28,8 @@ extern void find_and_init_phbs(void);
extern struct pci_dev *isa_bridge_pcidev; /* may be NULL if no ISA bus */
/** Bus Unit ID macros; get low and hi 32-bits of the 64-bit BUID */
-#define BUID_HI(buid) ((buid) >> 32)
-#define BUID_LO(buid) ((buid) & 0xffffffff)
+#define BUID_HI(buid) upper_32_bits(buid)
+#define BUID_LO(buid) lower_32_bits(buid)
/* PCI device_node operations */
struct device_node;
diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h
index 498fe09263d3..98210067c1cc 100644
--- a/arch/powerpc/include/asm/ppc_asm.h
+++ b/arch/powerpc/include/asm/ppc_asm.h
@@ -9,6 +9,7 @@
#include <asm/asm-compat.h>
#include <asm/processor.h>
#include <asm/ppc-opcode.h>
+#include <asm/firmware.h>
#ifndef __ASSEMBLY__
#error __FILE__ should only be used in assembler files
@@ -26,17 +27,13 @@
#ifndef CONFIG_VIRT_CPU_ACCOUNTING
#define ACCOUNT_CPU_USER_ENTRY(ra, rb)
#define ACCOUNT_CPU_USER_EXIT(ra, rb)
+#define ACCOUNT_STOLEN_TIME
#else
#define ACCOUNT_CPU_USER_ENTRY(ra, rb) \
beq 2f; /* if from kernel mode */ \
-BEGIN_FTR_SECTION; \
- mfspr ra,SPRN_PURR; /* get processor util. reg */ \
-END_FTR_SECTION_IFSET(CPU_FTR_PURR); \
-BEGIN_FTR_SECTION; \
- MFTB(ra); /* or get TB if no PURR */ \
-END_FTR_SECTION_IFCLR(CPU_FTR_PURR); \
- ld rb,PACA_STARTPURR(r13); \
- std ra,PACA_STARTPURR(r13); \
+ MFTB(ra); /* get timebase */ \
+ ld rb,PACA_STARTTIME_USER(r13); \
+ std ra,PACA_STARTTIME(r13); \
subf rb,rb,ra; /* subtract start value */ \
ld ra,PACA_USER_TIME(r13); \
add ra,ra,rb; /* add on to user time */ \
@@ -44,19 +41,34 @@ END_FTR_SECTION_IFCLR(CPU_FTR_PURR); \
2:
#define ACCOUNT_CPU_USER_EXIT(ra, rb) \
-BEGIN_FTR_SECTION; \
- mfspr ra,SPRN_PURR; /* get processor util. reg */ \
-END_FTR_SECTION_IFSET(CPU_FTR_PURR); \
-BEGIN_FTR_SECTION; \
- MFTB(ra); /* or get TB if no PURR */ \
-END_FTR_SECTION_IFCLR(CPU_FTR_PURR); \
- ld rb,PACA_STARTPURR(r13); \
- std ra,PACA_STARTPURR(r13); \
+ MFTB(ra); /* get timebase */ \
+ ld rb,PACA_STARTTIME(r13); \
+ std ra,PACA_STARTTIME_USER(r13); \
subf rb,rb,ra; /* subtract start value */ \
ld ra,PACA_SYSTEM_TIME(r13); \
- add ra,ra,rb; /* add on to user time */ \
- std ra,PACA_SYSTEM_TIME(r13);
-#endif
+ add ra,ra,rb; /* add on to system time */ \
+ std ra,PACA_SYSTEM_TIME(r13)
+
+#ifdef CONFIG_PPC_SPLPAR
+#define ACCOUNT_STOLEN_TIME \
+BEGIN_FW_FTR_SECTION; \
+ beq 33f; \
+ /* from user - see if there are any DTL entries to process */ \
+ ld r10,PACALPPACAPTR(r13); /* get ptr to VPA */ \
+ ld r11,PACA_DTL_RIDX(r13); /* get log read index */ \
+ ld r10,LPPACA_DTLIDX(r10); /* get log write index */ \
+ cmpd cr1,r11,r10; \
+ beq+ cr1,33f; \
+ bl .accumulate_stolen_time; \
+33: \
+END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR)
+
+#else /* CONFIG_PPC_SPLPAR */
+#define ACCOUNT_STOLEN_TIME
+
+#endif /* CONFIG_PPC_SPLPAR */
+
+#endif /* CONFIG_VIRT_CPU_ACCOUNTING */
/*
* Macros for storing registers into and loading registers from
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
index 19c05b0f74be..4c14187ba02d 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -118,7 +118,7 @@ extern struct task_struct *last_task_used_spe;
#define TASK_UNMAPPED_BASE_USER32 (PAGE_ALIGN(TASK_SIZE_USER32 / 4))
#define TASK_UNMAPPED_BASE_USER64 (PAGE_ALIGN(TASK_SIZE_USER64 / 4))
-#define TASK_UNMAPPED_BASE ((test_thread_flag(TIF_32BIT)) ? \
+#define TASK_UNMAPPED_BASE ((is_32bit_task()) ? \
TASK_UNMAPPED_BASE_USER32 : TASK_UNMAPPED_BASE_USER64 )
#endif
@@ -128,7 +128,7 @@ extern struct task_struct *last_task_used_spe;
#define STACK_TOP_USER64 TASK_SIZE_USER64
#define STACK_TOP_USER32 TASK_SIZE_USER32
-#define STACK_TOP (test_thread_flag(TIF_32BIT) ? \
+#define STACK_TOP (is_32bit_task() ? \
STACK_TOP_USER32 : STACK_TOP_USER64)
#define STACK_TOP_MAX STACK_TOP_USER64
diff --git a/arch/powerpc/include/asm/pte-common.h b/arch/powerpc/include/asm/pte-common.h
index f2b370180a09..76bb195e4f24 100644
--- a/arch/powerpc/include/asm/pte-common.h
+++ b/arch/powerpc/include/asm/pte-common.h
@@ -171,6 +171,13 @@ extern unsigned long bad_call_to_PMD_PAGE_SIZE(void);
/* Make modules code happy. We don't set RO yet */
#define PAGE_KERNEL_EXEC PAGE_KERNEL_X
+/*
+ * Don't just check for any non zero bits in __PAGE_USER, since for book3e
+ * and PTE_64BIT, PAGE_KERNEL_X contains _PAGE_BAP_SR which is also in
+ * _PAGE_USER. Need to explictly match _PAGE_BAP_UR bit in that case too.
+ */
+#define pte_user(val) ((val & _PAGE_USER) == _PAGE_USER)
+
/* Advertise special mapping type for AGP */
#define PAGE_AGP (PAGE_KERNEL_NC)
#define HAVE_PAGE_AGP
diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h
index 3d35f8ae377e..9a1193e30f26 100644
--- a/arch/powerpc/include/asm/rtas.h
+++ b/arch/powerpc/include/asm/rtas.h
@@ -187,6 +187,7 @@ extern void rtas_progress(char *s, unsigned short hex);
extern void rtas_initialize(void);
extern int rtas_suspend_cpu(struct rtas_suspend_me_data *data);
extern int rtas_suspend_last_cpu(struct rtas_suspend_me_data *data);
+extern int rtas_ibm_suspend_me(struct rtas_args *);
struct rtc_time;
extern unsigned long rtas_get_boot_time(void);
diff --git a/arch/powerpc/include/asm/systbl.h b/arch/powerpc/include/asm/systbl.h
index 3d212669a130..aa0f1ebb4aaf 100644
--- a/arch/powerpc/include/asm/systbl.h
+++ b/arch/powerpc/include/asm/systbl.h
@@ -329,3 +329,22 @@ COMPAT_SYS(rt_tgsigqueueinfo)
SYSCALL(fanotify_init)
COMPAT_SYS(fanotify_mark)
SYSCALL_SPU(prlimit64)
+SYSCALL_SPU(socket)
+SYSCALL_SPU(bind)
+SYSCALL_SPU(connect)
+SYSCALL_SPU(listen)
+SYSCALL_SPU(accept)
+SYSCALL_SPU(getsockname)
+SYSCALL_SPU(getpeername)
+SYSCALL_SPU(socketpair)
+SYSCALL_SPU(send)
+SYSCALL_SPU(sendto)
+COMPAT_SYS_SPU(recv)
+COMPAT_SYS_SPU(recvfrom)
+SYSCALL_SPU(shutdown)
+COMPAT_SYS_SPU(setsockopt)
+COMPAT_SYS_SPU(getsockopt)
+COMPAT_SYS_SPU(sendmsg)
+COMPAT_SYS_SPU(recvmsg)
+COMPAT_SYS_SPU(recvmmsg)
+SYSCALL_SPU(accept4)
diff --git a/arch/powerpc/include/asm/system.h b/arch/powerpc/include/asm/system.h
index 6c294acac848..5e474ddd2273 100644
--- a/arch/powerpc/include/asm/system.h
+++ b/arch/powerpc/include/asm/system.h
@@ -154,8 +154,8 @@ extern void enable_kernel_spe(void);
extern void giveup_spe(struct task_struct *);
extern void load_up_spe(struct task_struct *);
extern int fix_alignment(struct pt_regs *);
-extern void cvt_fd(float *from, double *to, struct thread_struct *thread);
-extern void cvt_df(double *from, float *to, struct thread_struct *thread);
+extern void cvt_fd(float *from, double *to);
+extern void cvt_df(double *from, float *to);
#ifndef CONFIG_SMP
extern void discard_lazy_cpu_state(void);
@@ -542,10 +542,6 @@ extern void reloc_got2(unsigned long);
#define PTRRELOC(x) ((typeof(x)) add_reloc_offset((unsigned long)(x)))
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING
-extern void account_system_vtime(struct task_struct *);
-#endif
-
extern struct dentry *powerpc_debugfs_root;
#endif /* __KERNEL__ */
diff --git a/arch/powerpc/include/asm/time.h b/arch/powerpc/include/asm/time.h
index dc779dfcf258..fe6f7c2c9c68 100644
--- a/arch/powerpc/include/asm/time.h
+++ b/arch/powerpc/include/asm/time.h
@@ -34,7 +34,6 @@ extern void to_tm(int tim, struct rtc_time * tm);
extern void GregorianDay(struct rtc_time *tm);
extern void generic_calibrate_decr(void);
-extern void snapshot_timebase(void);
extern void set_dec_cpu6(unsigned int val);
@@ -212,12 +211,8 @@ struct cpu_usage {
DECLARE_PER_CPU(struct cpu_usage, cpu_usage_array);
#if defined(CONFIG_VIRT_CPU_ACCOUNTING)
-extern void calculate_steal_time(void);
-extern void snapshot_timebases(void);
#define account_process_vtime(tsk) account_process_tick(tsk, 0)
#else
-#define calculate_steal_time() do { } while (0)
-#define snapshot_timebases() do { } while (0)
#define account_process_vtime(tsk) do { } while (0)
#endif
diff --git a/arch/powerpc/include/asm/unistd.h b/arch/powerpc/include/asm/unistd.h
index 597e6f9d094a..6151937657f6 100644
--- a/arch/powerpc/include/asm/unistd.h
+++ b/arch/powerpc/include/asm/unistd.h
@@ -348,10 +348,29 @@
#define __NR_fanotify_init 323
#define __NR_fanotify_mark 324
#define __NR_prlimit64 325
+#define __NR_socket 326
+#define __NR_bind 327
+#define __NR_connect 328
+#define __NR_listen 329
+#define __NR_accept 330
+#define __NR_getsockname 331
+#define __NR_getpeername 332
+#define __NR_socketpair 333
+#define __NR_send 334
+#define __NR_sendto 335
+#define __NR_recv 336
+#define __NR_recvfrom 337
+#define __NR_shutdown 338
+#define __NR_setsockopt 339
+#define __NR_getsockopt 340
+#define __NR_sendmsg 341
+#define __NR_recvmsg 342
+#define __NR_recvmmsg 343
+#define __NR_accept4 344
#ifdef __KERNEL__
-#define __NR_syscalls 326
+#define __NR_syscalls 345
#define __NR__exit __NR_exit
#define NR_syscalls __NR_syscalls
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 1dda70129141..4ed076a4db24 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -55,7 +55,9 @@ obj-$(CONFIG_IBMVIO) += vio.o
obj-$(CONFIG_IBMEBUS) += ibmebus.o
obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o
obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
+ifeq ($(CONFIG_PPC32),y)
obj-$(CONFIG_E500) += idle_e500.o
+endif
obj-$(CONFIG_6xx) += idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o
obj-$(CONFIG_TAU) += tau_6xx.o
obj-$(CONFIG_HIBERNATION) += swsusp.o suspend.o
@@ -67,7 +69,7 @@ endif
obj64-$(CONFIG_HIBERNATION) += swsusp_asm64.o
obj-$(CONFIG_MODULES) += module.o module_$(CONFIG_WORD_SIZE).o
obj-$(CONFIG_44x) += cpu_setup_44x.o
-obj-$(CONFIG_FSL_BOOKE) += cpu_setup_fsl_booke.o dbell.o
+obj-$(CONFIG_PPC_FSL_BOOK3E) += cpu_setup_fsl_booke.o dbell.o
obj-$(CONFIG_PPC_BOOK3E_64) += dbell.o
extra-y := head_$(CONFIG_WORD_SIZE).o
diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c
index b876e989220b..8184ee97e484 100644
--- a/arch/powerpc/kernel/align.c
+++ b/arch/powerpc/kernel/align.c
@@ -889,7 +889,7 @@ int fix_alignment(struct pt_regs *regs)
#ifdef CONFIG_PPC_FPU
preempt_disable();
enable_kernel_fp();
- cvt_df(&data.dd, (float *)&data.v[4], &current->thread);
+ cvt_df(&data.dd, (float *)&data.v[4]);
preempt_enable();
#else
return 0;
@@ -933,7 +933,7 @@ int fix_alignment(struct pt_regs *regs)
#ifdef CONFIG_PPC_FPU
preempt_disable();
enable_kernel_fp();
- cvt_fd((float *)&data.v[4], &data.dd, &current->thread);
+ cvt_fd((float *)&data.v[4], &data.dd);
preempt_enable();
#else
return 0;
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 1c0607ddccc0..c3e01945ad4f 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -61,7 +61,7 @@
#endif
#endif
-#if defined(CONFIG_FSL_BOOKE)
+#if defined(CONFIG_PPC_FSL_BOOK3E)
#include "../mm/mmu_decl.h"
#endif
@@ -181,17 +181,19 @@ int main(void)
offsetof(struct slb_shadow, save_area[SLB_NUM_BOLTED - 1].vsid));
DEFINE(SLBSHADOW_STACKESID,
offsetof(struct slb_shadow, save_area[SLB_NUM_BOLTED - 1].esid));
+ DEFINE(SLBSHADOW_SAVEAREA, offsetof(struct slb_shadow, save_area));
DEFINE(LPPACASRR0, offsetof(struct lppaca, saved_srr0));
DEFINE(LPPACASRR1, offsetof(struct lppaca, saved_srr1));
DEFINE(LPPACAANYINT, offsetof(struct lppaca, int_dword.any_int));
DEFINE(LPPACADECRINT, offsetof(struct lppaca, int_dword.fields.decr_int));
- DEFINE(SLBSHADOW_SAVEAREA, offsetof(struct slb_shadow, save_area));
+ DEFINE(LPPACA_DTLIDX, offsetof(struct lppaca, dtl_idx));
+ DEFINE(PACA_DTL_RIDX, offsetof(struct paca_struct, dtl_ridx));
#endif /* CONFIG_PPC_STD_MMU_64 */
DEFINE(PACAEMERGSP, offsetof(struct paca_struct, emergency_sp));
DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id));
DEFINE(PACAKEXECSTATE, offsetof(struct paca_struct, kexec_state));
- DEFINE(PACA_STARTPURR, offsetof(struct paca_struct, startpurr));
- DEFINE(PACA_STARTSPURR, offsetof(struct paca_struct, startspurr));
+ DEFINE(PACA_STARTTIME, offsetof(struct paca_struct, starttime));
+ DEFINE(PACA_STARTTIME_USER, offsetof(struct paca_struct, starttime_user));
DEFINE(PACA_USER_TIME, offsetof(struct paca_struct, user_time));
DEFINE(PACA_SYSTEM_TIME, offsetof(struct paca_struct, system_time));
DEFINE(PACA_TRAP_SAVE, offsetof(struct paca_struct, trap_save));
@@ -468,7 +470,7 @@ int main(void)
DEFINE(PGD_T_LOG2, PGD_T_LOG2);
DEFINE(PTE_T_LOG2, PTE_T_LOG2);
#endif
-#ifdef CONFIG_FSL_BOOKE
+#ifdef CONFIG_PPC_FSL_BOOK3E
DEFINE(TLBCAM_SIZE, sizeof(struct tlbcam));
DEFINE(TLBCAM_MAS0, offsetof(struct tlbcam, MAS0));
DEFINE(TLBCAM_MAS1, offsetof(struct tlbcam, MAS1));
diff --git a/arch/powerpc/kernel/cpu_setup_44x.S b/arch/powerpc/kernel/cpu_setup_44x.S
index 7d606f89a839..e32b4a9a2c22 100644
--- a/arch/powerpc/kernel/cpu_setup_44x.S
+++ b/arch/powerpc/kernel/cpu_setup_44x.S
@@ -35,6 +35,7 @@ _GLOBAL(__setup_cpu_440grx)
_GLOBAL(__setup_cpu_460ex)
_GLOBAL(__setup_cpu_460gt)
_GLOBAL(__setup_cpu_460sx)
+_GLOBAL(__setup_cpu_apm821xx)
mflr r4
bl __init_fpu_44x
bl __fixup_440A_mcheck
diff --git a/arch/powerpc/kernel/cpu_setup_fsl_booke.S b/arch/powerpc/kernel/cpu_setup_fsl_booke.S
index 0adb50ad8031..894e64fa481e 100644
--- a/arch/powerpc/kernel/cpu_setup_fsl_booke.S
+++ b/arch/powerpc/kernel/cpu_setup_fsl_booke.S
@@ -51,6 +51,7 @@ _GLOBAL(__e500_dcache_setup)
isync
blr
+#ifdef CONFIG_PPC32
_GLOBAL(__setup_cpu_e200)
/* enable dedicated debug exception handling resources (Debug APU) */
mfspr r3,SPRN_HID0
@@ -72,3 +73,17 @@ _GLOBAL(__setup_cpu_e500mc)
bl __setup_e500mc_ivors
mtlr r4
blr
+#endif
+/* Right now, restore and setup are the same thing */
+_GLOBAL(__restore_cpu_e5500)
+_GLOBAL(__setup_cpu_e5500)
+ mflr r4
+ bl __e500_icache_setup
+ bl __e500_dcache_setup
+#ifdef CONFIG_PPC_BOOK3E_64
+ bl .__setup_base_ivors
+#else
+ bl __setup_e500mc_ivors
+#endif
+ mtlr r4
+ blr
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index 1f9123f412ec..96a908f1cd87 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -48,6 +48,7 @@ extern void __setup_cpu_440x5(unsigned long offset, struct cpu_spec* spec);
extern void __setup_cpu_460ex(unsigned long offset, struct cpu_spec* spec);
extern void __setup_cpu_460gt(unsigned long offset, struct cpu_spec* spec);
extern void __setup_cpu_460sx(unsigned long offset, struct cpu_spec *spec);
+extern void __setup_cpu_apm821xx(unsigned long offset, struct cpu_spec *spec);
extern void __setup_cpu_603(unsigned long offset, struct cpu_spec* spec);
extern void __setup_cpu_604(unsigned long offset, struct cpu_spec* spec);
extern void __setup_cpu_750(unsigned long offset, struct cpu_spec* spec);
@@ -66,6 +67,10 @@ extern void __restore_cpu_ppc970(void);
extern void __setup_cpu_power7(unsigned long offset, struct cpu_spec* spec);
extern void __restore_cpu_power7(void);
#endif /* CONFIG_PPC64 */
+#if defined(CONFIG_E500)
+extern void __setup_cpu_e5500(unsigned long offset, struct cpu_spec* spec);
+extern void __restore_cpu_e5500(void);
+#endif /* CONFIG_E500 */
/* This table only contains "desktop" CPUs, it need to be filled with embedded
* ones as well...
@@ -1805,6 +1810,20 @@ static struct cpu_spec __initdata cpu_specs[] = {
.machine_check = machine_check_440A,
.platform = "ppc440",
},
+ { /* 464 in APM821xx */
+ .pvr_mask = 0xffffff00,
+ .pvr_value = 0x12C41C80,
+ .cpu_name = "APM821XX",
+ .cpu_features = CPU_FTRS_44X,
+ .cpu_user_features = COMMON_USER_BOOKE |
+ PPC_FEATURE_HAS_FPU,
+ .mmu_features = MMU_FTR_TYPE_44x,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ .cpu_setup = __setup_cpu_apm821xx,
+ .machine_check = machine_check_440A,
+ .platform = "ppc440",
+ },
{ /* 476 core */
.pvr_mask = 0xffff0000,
.pvr_value = 0x11a50000,
@@ -1891,7 +1910,9 @@ static struct cpu_spec __initdata cpu_specs[] = {
.platform = "ppc5554",
}
#endif /* CONFIG_E200 */
+#endif /* CONFIG_PPC32 */
#ifdef CONFIG_E500
+#ifdef CONFIG_PPC32
{ /* e500 */
.pvr_mask = 0xffff0000,
.pvr_value = 0x80200000,
@@ -1946,6 +1967,26 @@ static struct cpu_spec __initdata cpu_specs[] = {
.machine_check = machine_check_e500mc,
.platform = "ppce500mc",
},
+#endif /* CONFIG_PPC32 */
+ { /* e5500 */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x80240000,
+ .cpu_name = "e5500",
+ .cpu_features = CPU_FTRS_E500MC,
+ .cpu_user_features = COMMON_USER_BOOKE,
+ .mmu_features = MMU_FTR_TYPE_FSL_E | MMU_FTR_BIG_PHYS |
+ MMU_FTR_USE_TLBILX,
+ .icache_bsize = 64,
+ .dcache_bsize = 64,
+ .num_pmcs = 4,
+ .oprofile_cpu_type = "ppc/e500mc",
+ .oprofile_type = PPC_OPROFILE_FSL_EMB,
+ .cpu_setup = __setup_cpu_e5500,
+ .cpu_restore = __restore_cpu_e5500,
+ .machine_check = machine_check_e500mc,
+ .platform = "ppce5500",
+ },
+#ifdef CONFIG_PPC32
{ /* default match */
.pvr_mask = 0x00000000,
.pvr_value = 0x00000000,
@@ -1960,8 +2001,8 @@ static struct cpu_spec __initdata cpu_specs[] = {
.machine_check = machine_check_e500,
.platform = "powerpc",
}
-#endif /* CONFIG_E500 */
#endif /* CONFIG_PPC32 */
+#endif /* CONFIG_E500 */
#ifdef CONFIG_PPC_BOOK3E_64
{ /* This is a default entry to get going, to be replaced by
diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c
index 4457382f8667..832c8c4db254 100644
--- a/arch/powerpc/kernel/crash.c
+++ b/arch/powerpc/kernel/crash.c
@@ -414,18 +414,7 @@ void default_machine_crash_shutdown(struct pt_regs *regs)
crash_kexec_wait_realmode(crashing_cpu);
#endif
- for_each_irq(i) {
- struct irq_desc *desc = irq_to_desc(i);
-
- if (!desc || !desc->chip || !desc->chip->eoi)
- continue;
-
- if (desc->status & IRQ_INPROGRESS)
- desc->chip->eoi(i);
-
- if (!(desc->status & IRQ_DISABLED))
- desc->chip->shutdown(i);
- }
+ machine_kexec_mask_interrupts();
/*
* Call registered shutdown routines savely. Swap out
diff --git a/arch/powerpc/kernel/dma-iommu.c b/arch/powerpc/kernel/dma-iommu.c
index 37771a518119..6e54a0fd31aa 100644
--- a/arch/powerpc/kernel/dma-iommu.c
+++ b/arch/powerpc/kernel/dma-iommu.c
@@ -74,16 +74,17 @@ static int dma_iommu_dma_supported(struct device *dev, u64 mask)
{
struct iommu_table *tbl = get_iommu_table_base(dev);
- if (!tbl || tbl->it_offset > mask) {
- printk(KERN_INFO
- "Warning: IOMMU offset too big for device mask\n");
- if (tbl)
- printk(KERN_INFO
- "mask: 0x%08llx, table offset: 0x%08lx\n",
- mask, tbl->it_offset);
- else
- printk(KERN_INFO "mask: 0x%08llx, table unavailable\n",
- mask);
+ if (!tbl) {
+ dev_info(dev, "Warning: IOMMU dma not supported: mask 0x%08llx"
+ ", table unavailable\n", mask);
+ return 0;
+ }
+
+ if ((tbl->it_offset + tbl->it_size) > (mask >> IOMMU_PAGE_SHIFT)) {
+ dev_info(dev, "Warning: IOMMU window too big for device mask\n");
+ dev_info(dev, "mask: 0x%08llx, table end: 0x%08lx\n",
+ mask, (tbl->it_offset + tbl->it_size) <<
+ IOMMU_PAGE_SHIFT);
return 0;
} else
return 1;
diff --git a/arch/powerpc/kernel/dma.c b/arch/powerpc/kernel/dma.c
index 84d6367ec003..cf02cad62d9a 100644
--- a/arch/powerpc/kernel/dma.c
+++ b/arch/powerpc/kernel/dma.c
@@ -12,6 +12,7 @@
#include <linux/memblock.h>
#include <asm/bug.h>
#include <asm/abs_addr.h>
+#include <asm/machdep.h>
/*
* Generic direct DMA implementation
@@ -89,7 +90,7 @@ static int dma_direct_dma_supported(struct device *dev, u64 mask)
/* Could be improved so platforms can set the limit in case
* they have limited DMA windows
*/
- return mask >= (memblock_end_of_DRAM() - 1);
+ return mask >= get_dma_offset(dev) + (memblock_end_of_DRAM() - 1);
#else
return 1;
#endif
@@ -154,6 +155,23 @@ EXPORT_SYMBOL(dma_direct_ops);
#define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16)
+int dma_set_mask(struct device *dev, u64 dma_mask)
+{
+ struct dma_map_ops *dma_ops = get_dma_ops(dev);
+
+ if (ppc_md.dma_set_mask)
+ return ppc_md.dma_set_mask(dev, dma_mask);
+ if (unlikely(dma_ops == NULL))
+ return -EIO;
+ if (dma_ops->set_dma_mask != NULL)
+ return dma_ops->set_dma_mask(dev, dma_mask);
+ if (!dev->dma_mask || !dma_supported(dev, dma_mask))
+ return -EIO;
+ *dev->dma_mask = dma_mask;
+ return 0;
+}
+EXPORT_SYMBOL(dma_set_mask);
+
static int __init dma_init(void)
{
dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index 42e9d908914a..d82878c4daa6 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -97,6 +97,24 @@ system_call_common:
addi r9,r1,STACK_FRAME_OVERHEAD
ld r11,exception_marker@toc(r2)
std r11,-16(r9) /* "regshere" marker */
+#if defined(CONFIG_VIRT_CPU_ACCOUNTING) && defined(CONFIG_PPC_SPLPAR)
+BEGIN_FW_FTR_SECTION
+ beq 33f
+ /* if from user, see if there are any DTL entries to process */
+ ld r10,PACALPPACAPTR(r13) /* get ptr to VPA */
+ ld r11,PACA_DTL_RIDX(r13) /* get log read index */
+ ld r10,LPPACA_DTLIDX(r10) /* get log write index */
+ cmpd cr1,r11,r10
+ beq+ cr1,33f
+ bl .accumulate_stolen_time
+ REST_GPR(0,r1)
+ REST_4GPRS(3,r1)
+ REST_2GPRS(7,r1)
+ addi r9,r1,STACK_FRAME_OVERHEAD
+33:
+END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR)
+#endif /* CONFIG_VIRT_CPU_ACCOUNTING && CONFIG_PPC_SPLPAR */
+
#ifdef CONFIG_TRACE_IRQFLAGS
bl .trace_hardirqs_on
REST_GPR(0,r1)
@@ -202,7 +220,9 @@ syscall_exit:
bge- syscall_error
syscall_error_cont:
ld r7,_NIP(r1)
+BEGIN_FTR_SECTION
stdcx. r0,0,r1 /* to clear the reservation */
+END_FTR_SECTION_IFCLR(CPU_FTR_STCX_CHECKS_ADDRESS)
andi. r6,r8,MSR_PR
ld r4,_LINK(r1)
/*
@@ -419,6 +439,17 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
sync
#endif /* CONFIG_SMP */
+ /*
+ * If we optimise away the clear of the reservation in system
+ * calls because we know the CPU tracks the address of the
+ * reservation, then we need to clear it here to cover the
+ * case that the kernel context switch path has no larx
+ * instructions.
+ */
+BEGIN_FTR_SECTION
+ ldarx r6,0,r1
+END_FTR_SECTION_IFSET(CPU_FTR_STCX_CHECKS_ADDRESS)
+
addi r6,r4,-THREAD /* Convert THREAD to 'current' */
std r6,PACACURRENT(r13) /* Set new 'current' */
@@ -576,7 +607,16 @@ ALT_FW_FTR_SECTION_END_IFCLR(FW_FEATURE_ISERIES)
andi. r0,r3,MSR_RI
beq- unrecov_restore
+ /*
+ * Clear the reservation. If we know the CPU tracks the address of
+ * the reservation then we can potentially save some cycles and use
+ * a larx. On POWER6 and POWER7 this is significantly faster.
+ */
+BEGIN_FTR_SECTION
stdcx. r0,0,r1 /* to clear the reservation */
+FTR_SECTION_ELSE
+ ldarx r4,0,r1
+ALT_FTR_SECTION_END_IFCLR(CPU_FTR_STCX_CHECKS_ADDRESS)
/*
* Clear RI before restoring r13. If we are returning to
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index f53029a01554..39b0c48872d2 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -818,12 +818,12 @@ END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES)
/*
* hash_page couldn't handle it, set soft interrupt enable back
- * to what it was before the trap. Note that .raw_local_irq_restore
+ * to what it was before the trap. Note that .arch_local_irq_restore
* handles any interrupts pending at this point.
*/
ld r3,SOFTE(r1)
TRACE_AND_RESTORE_IRQ_PARTIAL(r3, 11f)
- bl .raw_local_irq_restore
+ bl .arch_local_irq_restore
b 11f
/* We have a data breakpoint exception - handle it */
diff --git a/arch/powerpc/kernel/fpu.S b/arch/powerpc/kernel/fpu.S
index fc8f5b14019c..e86c040ae585 100644
--- a/arch/powerpc/kernel/fpu.S
+++ b/arch/powerpc/kernel/fpu.S
@@ -163,24 +163,14 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX)
/*
* These are used in the alignment trap handler when emulating
* single-precision loads and stores.
- * We restore and save the fpscr so the task gets the same result
- * and exceptions as if the cpu had performed the load or store.
*/
_GLOBAL(cvt_fd)
- lfd 0,THREAD_FPSCR(r5) /* load up fpscr value */
- MTFSF_L(0)
lfs 0,0(r3)
stfd 0,0(r4)
- mffs 0
- stfd 0,THREAD_FPSCR(r5) /* save new fpscr value */
blr
_GLOBAL(cvt_df)
- lfd 0,THREAD_FPSCR(r5) /* load up fpscr value */
- MTFSF_L(0)
lfd 0,0(r3)
stfs 0,0(r4)
- mffs 0
- stfd 0,THREAD_FPSCR(r5) /* save new fpscr value */
blr
diff --git a/arch/powerpc/kernel/head_40x.S b/arch/powerpc/kernel/head_40x.S
index a90625f9b485..8278e8bad5a0 100644
--- a/arch/powerpc/kernel/head_40x.S
+++ b/arch/powerpc/kernel/head_40x.S
@@ -923,11 +923,7 @@ initial_mmu:
mtspr SPRN_PID,r0
sync
- /* Configure and load two entries into TLB slots 62 and 63.
- * In case we are pinning TLBs, these are reserved in by the
- * other TLB functions. If not reserving, then it doesn't
- * matter where they are loaded.
- */
+ /* Configure and load one entry into TLB slots 63 */
clrrwi r4,r4,10 /* Mask off the real page number */
ori r4,r4,(TLB_WR | TLB_EX) /* Set the write and execute bits */
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S
index 4faeba247854..529b817f473b 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -152,8 +152,11 @@ _ENTRY(__early_start)
/* Check to see if we're the second processor, and jump
* to the secondary_start code if so
*/
- mfspr r24,SPRN_PIR
- cmpwi r24,0
+ lis r24, boot_cpuid@h
+ ori r24, r24, boot_cpuid@l
+ lwz r24, 0(r24)
+ cmpwi r24, -1
+ mfspr r24,SPRN_PIR
bne __secondary_start
#endif
@@ -175,6 +178,9 @@ _ENTRY(__early_start)
li r0,0
stwu r0,THREAD_SIZE-STACK_FRAME_OVERHEAD(r1)
+ rlwinm r22,r1,0,0,31-THREAD_SHIFT /* current thread_info */
+ stw r24, TI_CPU(r22)
+
bl early_init
#ifdef CONFIG_RELOCATABLE
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 4a65386995d7..ce557f6f00fc 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -116,7 +116,7 @@ static inline notrace void set_soft_enabled(unsigned long enable)
: : "r" (enable), "i" (offsetof(struct paca_struct, soft_enabled)));
}
-notrace void raw_local_irq_restore(unsigned long en)
+notrace void arch_local_irq_restore(unsigned long en)
{
/*
* get_paca()->soft_enabled = en;
@@ -192,7 +192,7 @@ notrace void raw_local_irq_restore(unsigned long en)
__hard_irq_enable();
}
-EXPORT_SYMBOL(raw_local_irq_restore);
+EXPORT_SYMBOL(arch_local_irq_restore);
#endif /* CONFIG_PPC64 */
static int show_other_interrupts(struct seq_file *p, int prec)
@@ -587,8 +587,10 @@ struct irq_host *irq_alloc_host(struct device_node *of_node,
* this will be fixed once slab is made available early
* instead of the current cruft
*/
- if (mem_init_done)
+ if (mem_init_done) {
+ of_node_put(host->of_node);
kfree(host);
+ }
return NULL;
}
irq_map[0].host = host;
@@ -1143,7 +1145,7 @@ static int virq_debug_show(struct seq_file *m, void *private)
unsigned long flags;
struct irq_desc *desc;
const char *p;
- char none[] = "none";
+ static const char none[] = "none";
int i;
seq_printf(m, "%-5s %-7s %-15s %s\n", "virq", "hwirq",
diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c
index 50362b6ef6e9..16468362ad57 100644
--- a/arch/powerpc/kernel/lparcfg.c
+++ b/arch/powerpc/kernel/lparcfg.c
@@ -56,7 +56,7 @@ static unsigned long get_purr(void)
for_each_possible_cpu(cpu) {
if (firmware_has_feature(FW_FEATURE_ISERIES))
- sum_purr += lppaca[cpu].emulated_time_base;
+ sum_purr += lppaca_of(cpu).emulated_time_base;
else {
struct cpu_usage *cu;
@@ -263,7 +263,7 @@ static void parse_ppp_data(struct seq_file *m)
ppp_data.active_system_procs);
/* pool related entries are apropriate for shared configs */
- if (lppaca[0].shared_proc) {
+ if (lppaca_of(0).shared_proc) {
unsigned long pool_idle_time, pool_procs;
seq_printf(m, "pool=%d\n", ppp_data.pool_num);
@@ -460,8 +460,8 @@ static void pseries_cmo_data(struct seq_file *m)
return;
for_each_possible_cpu(cpu) {
- cmo_faults += lppaca[cpu].cmo_faults;
- cmo_fault_time += lppaca[cpu].cmo_fault_time;
+ cmo_faults += lppaca_of(cpu).cmo_faults;
+ cmo_fault_time += lppaca_of(cpu).cmo_fault_time;
}
seq_printf(m, "cmo_faults=%lu\n", cmo_faults);
@@ -479,8 +479,8 @@ static void splpar_dispatch_data(struct seq_file *m)
unsigned long dispatch_dispersions = 0;
for_each_possible_cpu(cpu) {
- dispatches += lppaca[cpu].yield_count;
- dispatch_dispersions += lppaca[cpu].dispersion_count;
+ dispatches += lppaca_of(cpu).yield_count;
+ dispatch_dispersions += lppaca_of(cpu).dispersion_count;
}
seq_printf(m, "dispatches=%lu\n", dispatches);
@@ -545,7 +545,7 @@ static int pseries_lparcfg_data(struct seq_file *m, void *v)
seq_printf(m, "partition_potential_processors=%d\n",
partition_potential_processors);
- seq_printf(m, "shared_processor_mode=%d\n", lppaca[0].shared_proc);
+ seq_printf(m, "shared_processor_mode=%d\n", lppaca_of(0).shared_proc);
seq_printf(m, "slb_size=%d\n", mmu_slb_size);
@@ -780,6 +780,7 @@ static const struct file_operations lparcfg_fops = {
.write = lparcfg_write,
.open = lparcfg_open,
.release = single_release,
+ .llseek = seq_lseek,
};
static int __init lparcfg_init(void)
diff --git a/arch/powerpc/kernel/machine_kexec.c b/arch/powerpc/kernel/machine_kexec.c
index dd6c141f1662..df7e20c191cd 100644
--- a/arch/powerpc/kernel/machine_kexec.c
+++ b/arch/powerpc/kernel/machine_kexec.c
@@ -14,10 +14,34 @@
#include <linux/threads.h>
#include <linux/memblock.h>
#include <linux/of.h>
+#include <linux/irq.h>
+
#include <asm/machdep.h>
#include <asm/prom.h>
#include <asm/sections.h>
+void machine_kexec_mask_interrupts(void) {
+ unsigned int i;
+
+ for_each_irq(i) {
+ struct irq_desc *desc = irq_to_desc(i);
+
+ if (!desc || !desc->chip)
+ continue;
+
+ if (desc->chip->eoi &&
+ desc->status & IRQ_INPROGRESS)
+ desc->chip->eoi(i);
+
+ if (desc->chip->mask)
+ desc->chip->mask(i);
+
+ if (desc->chip->disable &&
+ !(desc->status & IRQ_DISABLED))
+ desc->chip->disable(i);
+ }
+}
+
void machine_crash_shutdown(struct pt_regs *regs)
{
if (ppc_md.machine_crash_shutdown)
diff --git a/arch/powerpc/kernel/machine_kexec_32.c b/arch/powerpc/kernel/machine_kexec_32.c
index ae63a964b858..e63f2e7d2efb 100644
--- a/arch/powerpc/kernel/machine_kexec_32.c
+++ b/arch/powerpc/kernel/machine_kexec_32.c
@@ -39,6 +39,10 @@ void default_machine_kexec(struct kimage *image)
/* Interrupts aren't acceptable while we reboot */
local_irq_disable();
+ /* mask each interrupt so we are in a more sane state for the
+ * kexec kernel */
+ machine_kexec_mask_interrupts();
+
page_list = image->head;
/* we need both effective and real address here */
diff --git a/arch/powerpc/kernel/module.c b/arch/powerpc/kernel/module.c
index 477c663e0140..49cee9df225b 100644
--- a/arch/powerpc/kernel/module.c
+++ b/arch/powerpc/kernel/module.c
@@ -63,11 +63,6 @@ int module_finalize(const Elf_Ehdr *hdr,
const Elf_Shdr *sechdrs, struct module *me)
{
const Elf_Shdr *sect;
- int err;
-
- err = module_bug_finalize(hdr, sechdrs, me);
- if (err)
- return err;
/* Apply feature fixups */
sect = find_section(hdr, sechdrs, "__ftr_fixup");
@@ -101,5 +96,4 @@ int module_finalize(const Elf_Ehdr *hdr,
void module_arch_cleanup(struct module *mod)
{
- module_bug_cleanup(mod);
}
diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c
index d0a26f1770fe..ebf9846f3c3b 100644
--- a/arch/powerpc/kernel/paca.c
+++ b/arch/powerpc/kernel/paca.c
@@ -27,6 +27,20 @@ extern unsigned long __toc_start;
#ifdef CONFIG_PPC_BOOK3S
/*
+ * We only have to have statically allocated lppaca structs on
+ * legacy iSeries, which supports at most 64 cpus.
+ */
+#ifdef CONFIG_PPC_ISERIES
+#if NR_CPUS < 64
+#define NR_LPPACAS NR_CPUS
+#else
+#define NR_LPPACAS 64
+#endif
+#else /* not iSeries */
+#define NR_LPPACAS 1
+#endif
+
+/*
* The structure which the hypervisor knows about - this structure
* should not cross a page boundary. The vpa_init/register_vpa call
* is now known to fail if the lppaca structure crosses a page
@@ -36,7 +50,7 @@ extern unsigned long __toc_start;
* will suffice to ensure that it doesn't cross a page boundary.
*/
struct lppaca lppaca[] = {
- [0 ... (NR_CPUS-1)] = {
+ [0 ... (NR_LPPACAS-1)] = {
.desc = 0xd397d781, /* "LpPa" */
.size = sizeof(struct lppaca),
.dyn_proc_status = 2,
@@ -49,6 +63,54 @@ struct lppaca lppaca[] = {
},
};
+static struct lppaca *extra_lppacas;
+static long __initdata lppaca_size;
+
+static void allocate_lppacas(int nr_cpus, unsigned long limit)
+{
+ if (nr_cpus <= NR_LPPACAS)
+ return;
+
+ lppaca_size = PAGE_ALIGN(sizeof(struct lppaca) *
+ (nr_cpus - NR_LPPACAS));
+ extra_lppacas = __va(memblock_alloc_base(lppaca_size,
+ PAGE_SIZE, limit));
+}
+
+static struct lppaca *new_lppaca(int cpu)
+{
+ struct lppaca *lp;
+
+ if (cpu < NR_LPPACAS)
+ return &lppaca[cpu];
+
+ lp = extra_lppacas + (cpu - NR_LPPACAS);
+ *lp = lppaca[0];
+
+ return lp;
+}
+
+static void free_lppacas(void)
+{
+ long new_size = 0, nr;
+
+ if (!lppaca_size)
+ return;
+ nr = num_possible_cpus() - NR_LPPACAS;
+ if (nr > 0)
+ new_size = PAGE_ALIGN(nr * sizeof(struct lppaca));
+ if (new_size >= lppaca_size)
+ return;
+
+ memblock_free(__pa(extra_lppacas) + new_size, lppaca_size - new_size);
+ lppaca_size = new_size;
+}
+
+#else
+
+static inline void allocate_lppacas(int nr_cpus, unsigned long limit) { }
+static inline void free_lppacas(void) { }
+
#endif /* CONFIG_PPC_BOOK3S */
#ifdef CONFIG_PPC_STD_MMU_64
@@ -88,7 +150,7 @@ void __init initialise_paca(struct paca_struct *new_paca, int cpu)
unsigned long kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL;
#ifdef CONFIG_PPC_BOOK3S
- new_paca->lppaca_ptr = &lppaca[cpu];
+ new_paca->lppaca_ptr = new_lppaca(cpu);
#else
new_paca->kernel_pgd = swapper_pg_dir;
#endif
@@ -127,7 +189,7 @@ void __init allocate_pacas(void)
* the first segment. On iSeries they must be within the area mapped
* by the HV, which is HvPagesToMap * HVPAGESIZE bytes.
*/
- limit = min(0x10000000ULL, memblock.rmo_size);
+ limit = min(0x10000000ULL, ppc64_rma_size);
if (firmware_has_feature(FW_FEATURE_ISERIES))
limit = min(limit, HvPagesToMap * HVPAGESIZE);
@@ -144,6 +206,8 @@ void __init allocate_pacas(void)
printk(KERN_DEBUG "Allocated %u bytes for %d pacas at %p\n",
paca_size, nr_cpus, paca);
+ allocate_lppacas(nr_cpus, limit);
+
/* Can't use for_each_*_cpu, as they aren't functional yet */
for (cpu = 0; cpu < nr_cpus; cpu++)
initialise_paca(&paca[cpu], cpu);
@@ -164,4 +228,6 @@ void __init free_unused_pacas(void)
paca_size - new_size);
paca_size = new_size;
+
+ free_lppacas();
}
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 9021c4ad4bbd..10a44e68ef11 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -1090,8 +1090,6 @@ void __devinit pcibios_setup_bus_devices(struct pci_bus *bus)
bus->number, bus->self ? pci_name(bus->self) : "PHB");
list_for_each_entry(dev, &bus->devices, bus_list) {
- struct dev_archdata *sd = &dev->dev.archdata;
-
/* Cardbus can call us to add new devices to a bus, so ignore
* those who are already fully discovered
*/
@@ -1107,7 +1105,7 @@ void __devinit pcibios_setup_bus_devices(struct pci_bus *bus)
set_dev_node(&dev->dev, pcibus_to_node(dev->bus));
/* Hook up default DMA ops */
- sd->dma_ops = pci_dma_ops;
+ set_dma_ops(&dev->dev, pci_dma_ops);
set_dma_offset(&dev->dev, PCI_DRAM_OFFSET);
/* Additional platform DMA/iommu setup */
diff --git a/arch/powerpc/kernel/perf_callchain.c b/arch/powerpc/kernel/perf_callchain.c
index 95ad9dad298e..d05ae4204bbf 100644
--- a/arch/powerpc/kernel/perf_callchain.c
+++ b/arch/powerpc/kernel/perf_callchain.c
@@ -23,18 +23,6 @@
#include "ppc32.h"
#endif
-/*
- * Store another value in a callchain_entry.
- */
-static inline void callchain_store(struct perf_callchain_entry *entry, u64 ip)
-{
- unsigned int nr = entry->nr;
-
- if (nr < PERF_MAX_STACK_DEPTH) {
- entry->ip[nr] = ip;
- entry->nr = nr + 1;
- }
-}
/*
* Is sp valid as the address of the next kernel stack frame after prev_sp?
@@ -58,8 +46,8 @@ static int valid_next_sp(unsigned long sp, unsigned long prev_sp)
return 0;
}
-static void perf_callchain_kernel(struct pt_regs *regs,
- struct perf_callchain_entry *entry)
+void
+perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs)
{
unsigned long sp, next_sp;
unsigned long next_ip;
@@ -69,8 +57,7 @@ static void perf_callchain_kernel(struct pt_regs *regs,
lr = regs->link;
sp = regs->gpr[1];
- callchain_store(entry, PERF_CONTEXT_KERNEL);
- callchain_store(entry, regs->nip);
+ perf_callchain_store(entry, regs->nip);
if (!validate_sp(sp, current, STACK_FRAME_OVERHEAD))
return;
@@ -89,7 +76,7 @@ static void perf_callchain_kernel(struct pt_regs *regs,
next_ip = regs->nip;
lr = regs->link;
level = 0;
- callchain_store(entry, PERF_CONTEXT_KERNEL);
+ perf_callchain_store(entry, PERF_CONTEXT_KERNEL);
} else {
if (level == 0)
@@ -111,7 +98,7 @@ static void perf_callchain_kernel(struct pt_regs *regs,
++level;
}
- callchain_store(entry, next_ip);
+ perf_callchain_store(entry, next_ip);
if (!valid_next_sp(next_sp, sp))
return;
sp = next_sp;
@@ -233,8 +220,8 @@ static int sane_signal_64_frame(unsigned long sp)
puc == (unsigned long) &sf->uc;
}
-static void perf_callchain_user_64(struct pt_regs *regs,
- struct perf_callchain_entry *entry)
+static void perf_callchain_user_64(struct perf_callchain_entry *entry,
+ struct pt_regs *regs)
{
unsigned long sp, next_sp;
unsigned long next_ip;
@@ -246,8 +233,7 @@ static void perf_callchain_user_64(struct pt_regs *regs,
next_ip = regs->nip;
lr = regs->link;
sp = regs->gpr[1];
- callchain_store(entry, PERF_CONTEXT_USER);
- callchain_store(entry, next_ip);
+ perf_callchain_store(entry, next_ip);
for (;;) {
fp = (unsigned long __user *) sp;
@@ -276,14 +262,14 @@ static void perf_callchain_user_64(struct pt_regs *regs,
read_user_stack_64(&uregs[PT_R1], &sp))
return;
level = 0;
- callchain_store(entry, PERF_CONTEXT_USER);
- callchain_store(entry, next_ip);
+ perf_callchain_store(entry, PERF_CONTEXT_USER);
+ perf_callchain_store(entry, next_ip);
continue;
}
if (level == 0)
next_ip = lr;
- callchain_store(entry, next_ip);
+ perf_callchain_store(entry, next_ip);
++level;
sp = next_sp;
}
@@ -315,8 +301,8 @@ static int read_user_stack_32(unsigned int __user *ptr, unsigned int *ret)
return __get_user_inatomic(*ret, ptr);
}
-static inline void perf_callchain_user_64(struct pt_regs *regs,
- struct perf_callchain_entry *entry)
+static inline void perf_callchain_user_64(struct perf_callchain_entry *entry,
+ struct pt_regs *regs)
{
}
@@ -435,8 +421,8 @@ static unsigned int __user *signal_frame_32_regs(unsigned int sp,
return mctx->mc_gregs;
}
-static void perf_callchain_user_32(struct pt_regs *regs,
- struct perf_callchain_entry *entry)
+static void perf_callchain_user_32(struct perf_callchain_entry *entry,
+ struct pt_regs *regs)
{
unsigned int sp, next_sp;
unsigned int next_ip;
@@ -447,8 +433,7 @@ static void perf_callchain_user_32(struct pt_regs *regs,
next_ip = regs->nip;
lr = regs->link;
sp = regs->gpr[1];
- callchain_store(entry, PERF_CONTEXT_USER);
- callchain_store(entry, next_ip);
+ perf_callchain_store(entry, next_ip);
while (entry->nr < PERF_MAX_STACK_DEPTH) {
fp = (unsigned int __user *) (unsigned long) sp;
@@ -470,45 +455,24 @@ static void perf_callchain_user_32(struct pt_regs *regs,
read_user_stack_32(&uregs[PT_R1], &sp))
return;
level = 0;
- callchain_store(entry, PERF_CONTEXT_USER);
- callchain_store(entry, next_ip);
+ perf_callchain_store(entry, PERF_CONTEXT_USER);
+ perf_callchain_store(entry, next_ip);
continue;
}
if (level == 0)
next_ip = lr;
- callchain_store(entry, next_ip);
+ perf_callchain_store(entry, next_ip);
++level;
sp = next_sp;
}
}
-/*
- * Since we can't get PMU interrupts inside a PMU interrupt handler,
- * we don't need separate irq and nmi entries here.
- */
-static DEFINE_PER_CPU(struct perf_callchain_entry, cpu_perf_callchain);
-
-struct perf_callchain_entry *perf_callchain(struct pt_regs *regs)
+void
+perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
{
- struct perf_callchain_entry *entry = &__get_cpu_var(cpu_perf_callchain);
-
- entry->nr = 0;
-
- if (!user_mode(regs)) {
- perf_callchain_kernel(regs, entry);
- if (current->mm)
- regs = task_pt_regs(current);
- else
- regs = NULL;
- }
-
- if (regs) {
- if (current_is_64bit())
- perf_callchain_user_64(regs, entry);
- else
- perf_callchain_user_32(regs, entry);
- }
-
- return entry;
+ if (current_is_64bit())
+ perf_callchain_user_64(entry, regs);
+ else
+ perf_callchain_user_32(entry, regs);
}
diff --git a/arch/powerpc/kernel/perf_event.c b/arch/powerpc/kernel/perf_event.c
index d301a30445e0..3129c855933c 100644
--- a/arch/powerpc/kernel/perf_event.c
+++ b/arch/powerpc/kernel/perf_event.c
@@ -402,6 +402,9 @@ static void power_pmu_read(struct perf_event *event)
{
s64 val, delta, prev;
+ if (event->hw.state & PERF_HES_STOPPED)
+ return;
+
if (!event->hw.idx)
return;
/*
@@ -517,7 +520,7 @@ static void write_mmcr0(struct cpu_hw_events *cpuhw, unsigned long mmcr0)
* Disable all events to prevent PMU interrupts and to allow
* events to be added or removed.
*/
-void hw_perf_disable(void)
+static void power_pmu_disable(struct pmu *pmu)
{
struct cpu_hw_events *cpuhw;
unsigned long flags;
@@ -565,7 +568,7 @@ void hw_perf_disable(void)
* If we were previously disabled and events were added, then
* put the new config on the PMU.
*/
-void hw_perf_enable(void)
+static void power_pmu_enable(struct pmu *pmu)
{
struct perf_event *event;
struct cpu_hw_events *cpuhw;
@@ -672,6 +675,8 @@ void hw_perf_enable(void)
}
local64_set(&event->hw.prev_count, val);
event->hw.idx = idx;
+ if (event->hw.state & PERF_HES_STOPPED)
+ val = 0;
write_pmc(idx, val);
perf_event_update_userpage(event);
}
@@ -727,7 +732,7 @@ static int collect_events(struct perf_event *group, int max_count,
* re-enable the PMU in order to get hw_perf_enable to do the
* actual work of reconfiguring the PMU.
*/
-static int power_pmu_enable(struct perf_event *event)
+static int power_pmu_add(struct perf_event *event, int ef_flags)
{
struct cpu_hw_events *cpuhw;
unsigned long flags;
@@ -735,7 +740,7 @@ static int power_pmu_enable(struct perf_event *event)
int ret = -EAGAIN;
local_irq_save(flags);
- perf_disable();
+ perf_pmu_disable(event->pmu);
/*
* Add the event to the list (if there is room)
@@ -749,6 +754,9 @@ static int power_pmu_enable(struct perf_event *event)
cpuhw->events[n0] = event->hw.config;
cpuhw->flags[n0] = event->hw.event_base;
+ if (!(ef_flags & PERF_EF_START))
+ event->hw.state = PERF_HES_STOPPED | PERF_HES_UPTODATE;
+
/*
* If group events scheduling transaction was started,
* skip the schedulability test here, it will be peformed
@@ -769,7 +777,7 @@ nocheck:
ret = 0;
out:
- perf_enable();
+ perf_pmu_enable(event->pmu);
local_irq_restore(flags);
return ret;
}
@@ -777,14 +785,14 @@ nocheck:
/*
* Remove a event from the PMU.
*/
-static void power_pmu_disable(struct perf_event *event)
+static void power_pmu_del(struct perf_event *event, int ef_flags)
{
struct cpu_hw_events *cpuhw;
long i;
unsigned long flags;
local_irq_save(flags);
- perf_disable();
+ perf_pmu_disable(event->pmu);
power_pmu_read(event);
@@ -821,34 +829,60 @@ static void power_pmu_disable(struct perf_event *event)
cpuhw->mmcr[0] &= ~(MMCR0_PMXE | MMCR0_FCECE);
}
- perf_enable();
+ perf_pmu_enable(event->pmu);
local_irq_restore(flags);
}
/*
- * Re-enable interrupts on a event after they were throttled
- * because they were coming too fast.
+ * POWER-PMU does not support disabling individual counters, hence
+ * program their cycle counter to their max value and ignore the interrupts.
*/
-static void power_pmu_unthrottle(struct perf_event *event)
+
+static void power_pmu_start(struct perf_event *event, int ef_flags)
+{
+ unsigned long flags;
+ s64 left;
+
+ if (!event->hw.idx || !event->hw.sample_period)
+ return;
+
+ if (!(event->hw.state & PERF_HES_STOPPED))
+ return;
+
+ if (ef_flags & PERF_EF_RELOAD)
+ WARN_ON_ONCE(!(event->hw.state & PERF_HES_UPTODATE));
+
+ local_irq_save(flags);
+ perf_pmu_disable(event->pmu);
+
+ event->hw.state = 0;
+ left = local64_read(&event->hw.period_left);
+ write_pmc(event->hw.idx, left);
+
+ perf_event_update_userpage(event);
+ perf_pmu_enable(event->pmu);
+ local_irq_restore(flags);
+}
+
+static void power_pmu_stop(struct perf_event *event, int ef_flags)
{
- s64 val, left;
unsigned long flags;
if (!event->hw.idx || !event->hw.sample_period)
return;
+
+ if (event->hw.state & PERF_HES_STOPPED)
+ return;
+
local_irq_save(flags);
- perf_disable();
+ perf_pmu_disable(event->pmu);
+
power_pmu_read(event);
- left = event->hw.sample_period;
- event->hw.last_period = left;
- val = 0;
- if (left < 0x80000000L)
- val = 0x80000000L - left;
- write_pmc(event->hw.idx, val);
- local64_set(&event->hw.prev_count, val);
- local64_set(&event->hw.period_left, left);
+ event->hw.state |= PERF_HES_STOPPED | PERF_HES_UPTODATE;
+ write_pmc(event->hw.idx, 0);
+
perf_event_update_userpage(event);
- perf_enable();
+ perf_pmu_enable(event->pmu);
local_irq_restore(flags);
}
@@ -857,10 +891,11 @@ static void power_pmu_unthrottle(struct perf_event *event)
* Set the flag to make pmu::enable() not perform the
* schedulability test, it will be performed at commit time
*/
-void power_pmu_start_txn(const struct pmu *pmu)
+void power_pmu_start_txn(struct pmu *pmu)
{
struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events);
+ perf_pmu_disable(pmu);
cpuhw->group_flag |= PERF_EVENT_TXN;
cpuhw->n_txn_start = cpuhw->n_events;
}
@@ -870,11 +905,12 @@ void power_pmu_start_txn(const struct pmu *pmu)
* Clear the flag and pmu::enable() will perform the
* schedulability test.
*/
-void power_pmu_cancel_txn(const struct pmu *pmu)
+void power_pmu_cancel_txn(struct pmu *pmu)
{
struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events);
cpuhw->group_flag &= ~PERF_EVENT_TXN;
+ perf_pmu_enable(pmu);
}
/*
@@ -882,7 +918,7 @@ void power_pmu_cancel_txn(const struct pmu *pmu)
* Perform the group schedulability test as a whole
* Return 0 if success
*/
-int power_pmu_commit_txn(const struct pmu *pmu)
+int power_pmu_commit_txn(struct pmu *pmu)
{
struct cpu_hw_events *cpuhw;
long i, n;
@@ -901,19 +937,10 @@ int power_pmu_commit_txn(const struct pmu *pmu)
cpuhw->event[i]->hw.config = cpuhw->events[i];
cpuhw->group_flag &= ~PERF_EVENT_TXN;
+ perf_pmu_enable(pmu);
return 0;
}
-struct pmu power_pmu = {
- .enable = power_pmu_enable,
- .disable = power_pmu_disable,
- .read = power_pmu_read,
- .unthrottle = power_pmu_unthrottle,
- .start_txn = power_pmu_start_txn,
- .cancel_txn = power_pmu_cancel_txn,
- .commit_txn = power_pmu_commit_txn,
-};
-
/*
* Return 1 if we might be able to put event on a limited PMC,
* or 0 if not.
@@ -1014,7 +1041,7 @@ static int hw_perf_cache_event(u64 config, u64 *eventp)
return 0;
}
-const struct pmu *hw_perf_event_init(struct perf_event *event)
+static int power_pmu_event_init(struct perf_event *event)
{
u64 ev;
unsigned long flags;
@@ -1026,25 +1053,27 @@ const struct pmu *hw_perf_event_init(struct perf_event *event)
struct cpu_hw_events *cpuhw;
if (!ppmu)
- return ERR_PTR(-ENXIO);
+ return -ENOENT;
+
switch (event->attr.type) {
case PERF_TYPE_HARDWARE:
ev = event->attr.config;
if (ev >= ppmu->n_generic || ppmu->generic_events[ev] == 0)
- return ERR_PTR(-EOPNOTSUPP);
+ return -EOPNOTSUPP;
ev = ppmu->generic_events[ev];
break;
case PERF_TYPE_HW_CACHE:
err = hw_perf_cache_event(event->attr.config, &ev);
if (err)
- return ERR_PTR(err);
+ return err;
break;
case PERF_TYPE_RAW:
ev = event->attr.config;
break;
default:
- return ERR_PTR(-EINVAL);
+ return -ENOENT;
}
+
event->hw.config_base = ev;
event->hw.idx = 0;
@@ -1063,7 +1092,7 @@ const struct pmu *hw_perf_event_init(struct perf_event *event)
* XXX we should check if the task is an idle task.
*/
flags = 0;
- if (event->ctx->task)
+ if (event->attach_state & PERF_ATTACH_TASK)
flags |= PPMU_ONLY_COUNT_RUN;
/*
@@ -1081,7 +1110,7 @@ const struct pmu *hw_perf_event_init(struct perf_event *event)
*/
ev = normal_pmc_alternative(ev, flags);
if (!ev)
- return ERR_PTR(-EINVAL);
+ return -EINVAL;
}
}
@@ -1095,19 +1124,19 @@ const struct pmu *hw_perf_event_init(struct perf_event *event)
n = collect_events(event->group_leader, ppmu->n_counter - 1,
ctrs, events, cflags);
if (n < 0)
- return ERR_PTR(-EINVAL);
+ return -EINVAL;
}
events[n] = ev;
ctrs[n] = event;
cflags[n] = flags;
if (check_excludes(ctrs, cflags, n, 1))
- return ERR_PTR(-EINVAL);
+ return -EINVAL;
cpuhw = &get_cpu_var(cpu_hw_events);
err = power_check_constraints(cpuhw, events, cflags, n + 1);
put_cpu_var(cpu_hw_events);
if (err)
- return ERR_PTR(-EINVAL);
+ return -EINVAL;
event->hw.config = events[n];
event->hw.event_base = cflags[n];
@@ -1132,11 +1161,23 @@ const struct pmu *hw_perf_event_init(struct perf_event *event)
}
event->destroy = hw_perf_event_destroy;
- if (err)
- return ERR_PTR(err);
- return &power_pmu;
+ return err;
}
+struct pmu power_pmu = {
+ .pmu_enable = power_pmu_enable,
+ .pmu_disable = power_pmu_disable,
+ .event_init = power_pmu_event_init,
+ .add = power_pmu_add,
+ .del = power_pmu_del,
+ .start = power_pmu_start,
+ .stop = power_pmu_stop,
+ .read = power_pmu_read,
+ .start_txn = power_pmu_start_txn,
+ .cancel_txn = power_pmu_cancel_txn,
+ .commit_txn = power_pmu_commit_txn,
+};
+
/*
* A counter has overflowed; update its count and record
* things if requested. Note that interrupts are hard-disabled
@@ -1149,6 +1190,11 @@ static void record_and_restart(struct perf_event *event, unsigned long val,
s64 prev, delta, left;
int record = 0;
+ if (event->hw.state & PERF_HES_STOPPED) {
+ write_pmc(event->hw.idx, 0);
+ return;
+ }
+
/* we don't have to worry about interrupts here */
prev = local64_read(&event->hw.prev_count);
delta = (val - prev) & 0xfffffffful;
@@ -1171,6 +1217,11 @@ static void record_and_restart(struct perf_event *event, unsigned long val,
val = 0x80000000LL - left;
}
+ write_pmc(event->hw.idx, val);
+ local64_set(&event->hw.prev_count, val);
+ local64_set(&event->hw.period_left, left);
+ perf_event_update_userpage(event);
+
/*
* Finally record data if requested.
*/
@@ -1183,23 +1234,9 @@ static void record_and_restart(struct perf_event *event, unsigned long val,
if (event->attr.sample_type & PERF_SAMPLE_ADDR)
perf_get_data_addr(regs, &data.addr);
- if (perf_event_overflow(event, nmi, &data, regs)) {
- /*
- * Interrupts are coming too fast - throttle them
- * by setting the event to 0, so it will be
- * at least 2^30 cycles until the next interrupt
- * (assuming each event counts at most 2 counts
- * per cycle).
- */
- val = 0;
- left = ~0ULL >> 1;
- }
+ if (perf_event_overflow(event, nmi, &data, regs))
+ power_pmu_stop(event, 0);
}
-
- write_pmc(event->hw.idx, val);
- local64_set(&event->hw.prev_count, val);
- local64_set(&event->hw.period_left, left);
- perf_event_update_userpage(event);
}
/*
@@ -1342,6 +1379,7 @@ int register_power_pmu(struct power_pmu *pmu)
freeze_events_kernel = MMCR0_FCHV;
#endif /* CONFIG_PPC64 */
+ perf_pmu_register(&power_pmu);
perf_cpu_notifier(power_pmu_notifier);
return 0;
diff --git a/arch/powerpc/kernel/perf_event_fsl_emb.c b/arch/powerpc/kernel/perf_event_fsl_emb.c
index 1ba45471ae43..7ecca59ddf77 100644
--- a/arch/powerpc/kernel/perf_event_fsl_emb.c
+++ b/arch/powerpc/kernel/perf_event_fsl_emb.c
@@ -156,6 +156,9 @@ static void fsl_emb_pmu_read(struct perf_event *event)
{
s64 val, delta, prev;
+ if (event->hw.state & PERF_HES_STOPPED)
+ return;
+
/*
* Performance monitor interrupts come even when interrupts
* are soft-disabled, as long as interrupts are hard-enabled.
@@ -177,7 +180,7 @@ static void fsl_emb_pmu_read(struct perf_event *event)
* Disable all events to prevent PMU interrupts and to allow
* events to be added or removed.
*/
-void hw_perf_disable(void)
+static void fsl_emb_pmu_disable(struct pmu *pmu)
{
struct cpu_hw_events *cpuhw;
unsigned long flags;
@@ -216,7 +219,7 @@ void hw_perf_disable(void)
* If we were previously disabled and events were added, then
* put the new config on the PMU.
*/
-void hw_perf_enable(void)
+static void fsl_emb_pmu_enable(struct pmu *pmu)
{
struct cpu_hw_events *cpuhw;
unsigned long flags;
@@ -262,8 +265,8 @@ static int collect_events(struct perf_event *group, int max_count,
return n;
}
-/* perf must be disabled, context locked on entry */
-static int fsl_emb_pmu_enable(struct perf_event *event)
+/* context locked on entry */
+static int fsl_emb_pmu_add(struct perf_event *event, int flags)
{
struct cpu_hw_events *cpuhw;
int ret = -EAGAIN;
@@ -271,6 +274,7 @@ static int fsl_emb_pmu_enable(struct perf_event *event)
u64 val;
int i;
+ perf_pmu_disable(event->pmu);
cpuhw = &get_cpu_var(cpu_hw_events);
if (event->hw.config & FSL_EMB_EVENT_RESTRICTED)
@@ -301,6 +305,12 @@ static int fsl_emb_pmu_enable(struct perf_event *event)
val = 0x80000000L - left;
}
local64_set(&event->hw.prev_count, val);
+
+ if (!(flags & PERF_EF_START)) {
+ event->hw.state = PERF_HES_STOPPED | PERF_HES_UPTODATE;
+ val = 0;
+ }
+
write_pmc(i, val);
perf_event_update_userpage(event);
@@ -310,15 +320,17 @@ static int fsl_emb_pmu_enable(struct perf_event *event)
ret = 0;
out:
put_cpu_var(cpu_hw_events);
+ perf_pmu_enable(event->pmu);
return ret;
}
-/* perf must be disabled, context locked on entry */
-static void fsl_emb_pmu_disable(struct perf_event *event)
+/* context locked on entry */
+static void fsl_emb_pmu_del(struct perf_event *event, int flags)
{
struct cpu_hw_events *cpuhw;
int i = event->hw.idx;
+ perf_pmu_disable(event->pmu);
if (i < 0)
goto out;
@@ -346,44 +358,57 @@ static void fsl_emb_pmu_disable(struct perf_event *event)
cpuhw->n_events--;
out:
+ perf_pmu_enable(event->pmu);
put_cpu_var(cpu_hw_events);
}
-/*
- * Re-enable interrupts on a event after they were throttled
- * because they were coming too fast.
- *
- * Context is locked on entry, but perf is not disabled.
- */
-static void fsl_emb_pmu_unthrottle(struct perf_event *event)
+static void fsl_emb_pmu_start(struct perf_event *event, int ef_flags)
{
- s64 val, left;
unsigned long flags;
+ s64 left;
if (event->hw.idx < 0 || !event->hw.sample_period)
return;
+
+ if (!(event->hw.state & PERF_HES_STOPPED))
+ return;
+
+ if (ef_flags & PERF_EF_RELOAD)
+ WARN_ON_ONCE(!(event->hw.state & PERF_HES_UPTODATE));
+
local_irq_save(flags);
- perf_disable();
- fsl_emb_pmu_read(event);
- left = event->hw.sample_period;
- event->hw.last_period = left;
- val = 0;
- if (left < 0x80000000L)
- val = 0x80000000L - left;
- write_pmc(event->hw.idx, val);
- local64_set(&event->hw.prev_count, val);
- local64_set(&event->hw.period_left, left);
+ perf_pmu_disable(event->pmu);
+
+ event->hw.state = 0;
+ left = local64_read(&event->hw.period_left);
+ write_pmc(event->hw.idx, left);
+
perf_event_update_userpage(event);
- perf_enable();
+ perf_pmu_enable(event->pmu);
local_irq_restore(flags);
}
-static struct pmu fsl_emb_pmu = {
- .enable = fsl_emb_pmu_enable,
- .disable = fsl_emb_pmu_disable,
- .read = fsl_emb_pmu_read,
- .unthrottle = fsl_emb_pmu_unthrottle,
-};
+static void fsl_emb_pmu_stop(struct perf_event *event, int ef_flags)
+{
+ unsigned long flags;
+
+ if (event->hw.idx < 0 || !event->hw.sample_period)
+ return;
+
+ if (event->hw.state & PERF_HES_STOPPED)
+ return;
+
+ local_irq_save(flags);
+ perf_pmu_disable(event->pmu);
+
+ fsl_emb_pmu_read(event);
+ event->hw.state |= PERF_HES_STOPPED | PERF_HES_UPTODATE;
+ write_pmc(event->hw.idx, 0);
+
+ perf_event_update_userpage(event);
+ perf_pmu_enable(event->pmu);
+ local_irq_restore(flags);
+}
/*
* Release the PMU if this is the last perf_event.
@@ -428,7 +453,7 @@ static int hw_perf_cache_event(u64 config, u64 *eventp)
return 0;
}
-const struct pmu *hw_perf_event_init(struct perf_event *event)
+static int fsl_emb_pmu_event_init(struct perf_event *event)
{
u64 ev;
struct perf_event *events[MAX_HWEVENTS];
@@ -441,14 +466,14 @@ const struct pmu *hw_perf_event_init(struct perf_event *event)
case PERF_TYPE_HARDWARE:
ev = event->attr.config;
if (ev >= ppmu->n_generic || ppmu->generic_events[ev] == 0)
- return ERR_PTR(-EOPNOTSUPP);
+ return -EOPNOTSUPP;
ev = ppmu->generic_events[ev];
break;
case PERF_TYPE_HW_CACHE:
err = hw_perf_cache_event(event->attr.config, &ev);
if (err)
- return ERR_PTR(err);
+ return err;
break;
case PERF_TYPE_RAW:
@@ -456,12 +481,12 @@ const struct pmu *hw_perf_event_init(struct perf_event *event)
break;
default:
- return ERR_PTR(-EINVAL);
+ return -ENOENT;
}
event->hw.config = ppmu->xlate_event(ev);
if (!(event->hw.config & FSL_EMB_EVENT_VALID))
- return ERR_PTR(-EINVAL);
+ return -EINVAL;
/*
* If this is in a group, check if it can go on with all the
@@ -473,7 +498,7 @@ const struct pmu *hw_perf_event_init(struct perf_event *event)
n = collect_events(event->group_leader,
ppmu->n_counter - 1, events);
if (n < 0)
- return ERR_PTR(-EINVAL);
+ return -EINVAL;
}
if (event->hw.config & FSL_EMB_EVENT_RESTRICTED) {
@@ -484,7 +509,7 @@ const struct pmu *hw_perf_event_init(struct perf_event *event)
}
if (num_restricted >= ppmu->n_restricted)
- return ERR_PTR(-EINVAL);
+ return -EINVAL;
}
event->hw.idx = -1;
@@ -497,7 +522,7 @@ const struct pmu *hw_perf_event_init(struct perf_event *event)
if (event->attr.exclude_kernel)
event->hw.config_base |= PMLCA_FCS;
if (event->attr.exclude_idle)
- return ERR_PTR(-ENOTSUPP);
+ return -ENOTSUPP;
event->hw.last_period = event->hw.sample_period;
local64_set(&event->hw.period_left, event->hw.last_period);
@@ -523,11 +548,20 @@ const struct pmu *hw_perf_event_init(struct perf_event *event)
}
event->destroy = hw_perf_event_destroy;
- if (err)
- return ERR_PTR(err);
- return &fsl_emb_pmu;
+ return err;
}
+static struct pmu fsl_emb_pmu = {
+ .pmu_enable = fsl_emb_pmu_enable,
+ .pmu_disable = fsl_emb_pmu_disable,
+ .event_init = fsl_emb_pmu_event_init,
+ .add = fsl_emb_pmu_add,
+ .del = fsl_emb_pmu_del,
+ .start = fsl_emb_pmu_start,
+ .stop = fsl_emb_pmu_stop,
+ .read = fsl_emb_pmu_read,
+};
+
/*
* A counter has overflowed; update its count and record
* things if requested. Note that interrupts are hard-disabled
@@ -540,6 +574,11 @@ static void record_and_restart(struct perf_event *event, unsigned long val,
s64 prev, delta, left;
int record = 0;
+ if (event->hw.state & PERF_HES_STOPPED) {
+ write_pmc(event->hw.idx, 0);
+ return;
+ }
+
/* we don't have to worry about interrupts here */
prev = local64_read(&event->hw.prev_count);
delta = (val - prev) & 0xfffffffful;
@@ -562,6 +601,11 @@ static void record_and_restart(struct perf_event *event, unsigned long val,
val = 0x80000000LL - left;
}
+ write_pmc(event->hw.idx, val);
+ local64_set(&event->hw.prev_count, val);
+ local64_set(&event->hw.period_left, left);
+ perf_event_update_userpage(event);
+
/*
* Finally record data if requested.
*/
@@ -571,23 +615,9 @@ static void record_and_restart(struct perf_event *event, unsigned long val,
perf_sample_data_init(&data, 0);
data.period = event->hw.last_period;
- if (perf_event_overflow(event, nmi, &data, regs)) {
- /*
- * Interrupts are coming too fast - throttle them
- * by setting the event to 0, so it will be
- * at least 2^30 cycles until the next interrupt
- * (assuming each event counts at most 2 counts
- * per cycle).
- */
- val = 0;
- left = ~0ULL >> 1;
- }
+ if (perf_event_overflow(event, nmi, &data, regs))
+ fsl_emb_pmu_stop(event, 0);
}
-
- write_pmc(event->hw.idx, val);
- local64_set(&event->hw.prev_count, val);
- local64_set(&event->hw.period_left, left);
- perf_event_update_userpage(event);
}
static void perf_event_interrupt(struct pt_regs *regs)
@@ -651,5 +681,7 @@ int register_fsl_emb_pmu(struct fsl_emb_pmu *pmu)
pr_info("%s performance monitor hardware support registered\n",
pmu->name);
+ perf_pmu_register(&fsl_emb_pmu);
+
return 0;
}
diff --git a/arch/powerpc/kernel/ppc970-pmu.c b/arch/powerpc/kernel/ppc970-pmu.c
index 8eff48e20dba..3fee685de4df 100644
--- a/arch/powerpc/kernel/ppc970-pmu.c
+++ b/arch/powerpc/kernel/ppc970-pmu.c
@@ -169,9 +169,11 @@ static int p970_marked_instr_event(u64 event)
switch (unit) {
case PM_VPU:
mask = 0x4c; /* byte 0 bits 2,3,6 */
+ break;
case PM_LSU0:
/* byte 2 bits 0,2,3,4,6; all of byte 1 */
mask = 0x085dff00;
+ break;
case PM_LSU1L:
mask = 0x50 << 24; /* byte 3 bits 4,6 */
break;
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index b1c648a36b03..84906d3fc860 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -517,7 +517,6 @@ struct task_struct *__switch_to(struct task_struct *prev,
account_system_vtime(current);
account_process_vtime(current);
- calculate_steal_time();
/*
* We can't take a PMU exception inside _switch() since there is a
@@ -1298,14 +1297,3 @@ unsigned long randomize_et_dyn(unsigned long base)
return ret;
}
-
-#ifdef CONFIG_SMP
-int arch_sd_sibling_asym_packing(void)
-{
- if (cpu_has_feature(CPU_FTR_ASYM_SMT)) {
- printk_once(KERN_INFO "Enabling Asymmetric SMT scheduling\n");
- return SD_ASYM_PACKING;
- }
- return 0;
-}
-#endif
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index fed9bf6187d1..c3c6a8857544 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -66,6 +66,7 @@
int __initdata iommu_is_off;
int __initdata iommu_force_on;
unsigned long tce_alloc_start, tce_alloc_end;
+u64 ppc64_rma_size;
#endif
static int __init early_parse_mem(char *p)
@@ -98,7 +99,7 @@ static void __init move_device_tree(void)
if ((memory_limit && (start + size) > memory_limit) ||
overlaps_crashkernel(start, size)) {
- p = __va(memblock_alloc_base(size, PAGE_SIZE, memblock.rmo_size));
+ p = __va(memblock_alloc(size, PAGE_SIZE));
memcpy(p, initial_boot_params, size);
initial_boot_params = (struct boot_param_header *)p;
DBG("Moved device tree to 0x%p\n", p);
@@ -492,7 +493,7 @@ static int __init early_init_dt_scan_memory_ppc(unsigned long node,
void __init early_init_dt_add_memory_arch(u64 base, u64 size)
{
-#if defined(CONFIG_PPC64)
+#ifdef CONFIG_PPC64
if (iommu_is_off) {
if (base >= 0x80000000ul)
return;
@@ -501,9 +502,13 @@ void __init early_init_dt_add_memory_arch(u64 base, u64 size)
}
#endif
- memblock_add(base, size);
-
+ /* First MEMBLOCK added, do some special initializations */
+ if (memstart_addr == ~(phys_addr_t)0)
+ setup_initial_memory_limit(base, size);
memstart_addr = min((u64)memstart_addr, base);
+
+ /* Add the chunk to the MEMBLOCK list */
+ memblock_add(base, size);
}
u64 __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
@@ -655,7 +660,6 @@ static void __init phyp_dump_reserve_mem(void)
static inline void __init phyp_dump_reserve_mem(void) {}
#endif /* CONFIG_PHYP_DUMP && CONFIG_PPC_RTAS */
-
void __init early_init_devtree(void *params)
{
phys_addr_t limit;
@@ -683,6 +687,7 @@ void __init early_init_devtree(void *params)
/* Scan memory nodes and rebuild MEMBLOCKs */
memblock_init();
+
of_scan_flat_dt(early_init_dt_scan_root, NULL);
of_scan_flat_dt(early_init_dt_scan_memory_ppc, NULL);
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index 11f3cd9c832f..286d9783d93f 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -1681,7 +1681,7 @@ long do_syscall_trace_enter(struct pt_regs *regs)
if (unlikely(current->audit_context)) {
#ifdef CONFIG_PPC64
- if (!test_thread_flag(TIF_32BIT))
+ if (!is_32bit_task())
audit_syscall_entry(AUDIT_ARCH_PPC64,
regs->gpr[0],
regs->gpr[3], regs->gpr[4],
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index 41048de3c6c3..8fe8bc61c10a 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -805,7 +805,7 @@ static void rtas_percpu_suspend_me(void *info)
__rtas_suspend_cpu((struct rtas_suspend_me_data *)info, 1);
}
-static int rtas_ibm_suspend_me(struct rtas_args *args)
+int rtas_ibm_suspend_me(struct rtas_args *args)
{
long state;
long rc;
@@ -855,7 +855,7 @@ static int rtas_ibm_suspend_me(struct rtas_args *args)
return atomic_read(&data.error);
}
#else /* CONFIG_PPC_PSERIES */
-static int rtas_ibm_suspend_me(struct rtas_args *args)
+int rtas_ibm_suspend_me(struct rtas_args *args)
{
return -ENOSYS;
}
@@ -969,7 +969,7 @@ void __init rtas_initialize(void)
*/
#ifdef CONFIG_PPC64
if (machine_is(pseries) && firmware_has_feature(FW_FEATURE_LPAR)) {
- rtas_region = min(memblock.rmo_size, RTAS_INSTANTIATE_MAX);
+ rtas_region = min(ppc64_rma_size, RTAS_INSTANTIATE_MAX);
ibm_suspend_me_token = rtas_token("ibm,suspend-me");
}
#endif
diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c
index 67a84d8f118d..2b442e6c21e6 100644
--- a/arch/powerpc/kernel/rtas_flash.c
+++ b/arch/powerpc/kernel/rtas_flash.c
@@ -716,6 +716,7 @@ static const struct file_operations rtas_flash_operations = {
.write = rtas_flash_write,
.open = rtas_excl_open,
.release = rtas_flash_release,
+ .llseek = default_llseek,
};
static const struct file_operations manage_flash_operations = {
@@ -724,6 +725,7 @@ static const struct file_operations manage_flash_operations = {
.write = manage_flash_write,
.open = rtas_excl_open,
.release = rtas_excl_release,
+ .llseek = default_llseek,
};
static const struct file_operations validate_flash_operations = {
@@ -732,6 +734,7 @@ static const struct file_operations validate_flash_operations = {
.write = validate_flash_write,
.open = rtas_excl_open,
.release = validate_flash_release,
+ .llseek = default_llseek,
};
static int __init rtas_flash_init(void)
diff --git a/arch/powerpc/kernel/rtasd.c b/arch/powerpc/kernel/rtasd.c
index 638883e23e3a..0438f819fe6b 100644
--- a/arch/powerpc/kernel/rtasd.c
+++ b/arch/powerpc/kernel/rtasd.c
@@ -354,6 +354,7 @@ static const struct file_operations proc_rtas_log_operations = {
.poll = rtas_log_poll,
.open = rtas_log_open,
.release = rtas_log_release,
+ .llseek = noop_llseek,
};
static int enable_surveillance(int timeout)
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index 93666f9cabf1..1d2fbc905303 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -46,7 +46,7 @@
extern void bootx_init(unsigned long r4, unsigned long phys);
-int boot_cpuid;
+int boot_cpuid = -1;
EXPORT_SYMBOL_GPL(boot_cpuid);
int boot_cpuid_phys;
@@ -246,7 +246,7 @@ static void __init irqstack_early_init(void)
unsigned int i;
/* interrupt stacks must be in lowmem, we get that for free on ppc32
- * as the memblock is limited to lowmem by MEMBLOCK_REAL_LIMIT */
+ * as the memblock is limited to lowmem by default */
for_each_possible_cpu(i) {
softirq_ctx[i] = (struct thread_info *)
__va(memblock_alloc(THREAD_SIZE, THREAD_SIZE));
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index e72690ec9b87..2a178b0ebcdf 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -486,7 +486,7 @@ static void __init emergency_stack_init(void)
* bringup, we need to get at them in real mode. This means they
* must also be within the RMO region.
*/
- limit = min(slb0_limit(), memblock.rmo_size);
+ limit = min(slb0_limit(), ppc64_rma_size);
for_each_possible_cpu(i) {
unsigned long sp;
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 0008bc58e826..68034bbf2e4f 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -508,9 +508,6 @@ int __devinit start_secondary(void *unused)
if (smp_ops->take_timebase)
smp_ops->take_timebase();
- if (system_state > SYSTEM_BOOTING)
- snapshot_timebase();
-
secondary_cpu_time_init();
ipi_call_lock();
@@ -575,11 +572,18 @@ void __init smp_cpus_done(unsigned int max_cpus)
free_cpumask_var(old_mask);
- snapshot_timebases();
-
dump_numa_cpu_topology();
}
+int arch_sd_sibling_asym_packing(void)
+{
+ if (cpu_has_feature(CPU_FTR_ASYM_SMT)) {
+ printk_once(KERN_INFO "Enabling Asymmetric SMT scheduling\n");
+ return SD_ASYM_PACKING;
+ }
+ return 0;
+}
+
#ifdef CONFIG_HOTPLUG_CPU
int __cpu_disable(void)
{
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 8533b3b83f5d..010406958d97 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -53,7 +53,7 @@
#include <linux/posix-timers.h>
#include <linux/irq.h>
#include <linux/delay.h>
-#include <linux/perf_event.h>
+#include <linux/irq_work.h>
#include <asm/trace.h>
#include <asm/io.h>
@@ -161,10 +161,9 @@ extern struct timezone sys_tz;
static long timezone_offset;
unsigned long ppc_proc_freq;
-EXPORT_SYMBOL(ppc_proc_freq);
+EXPORT_SYMBOL_GPL(ppc_proc_freq);
unsigned long ppc_tb_freq;
-
-static DEFINE_PER_CPU(u64, last_jiffy);
+EXPORT_SYMBOL_GPL(ppc_tb_freq);
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
/*
@@ -185,6 +184,8 @@ DEFINE_PER_CPU(unsigned long, cputime_scaled_last_delta);
cputime_t cputime_one_jiffy;
+void (*dtl_consumer)(struct dtl_entry *, u64);
+
static void calc_cputime_factors(void)
{
struct div_result res;
@@ -200,62 +201,153 @@ static void calc_cputime_factors(void)
}
/*
- * Read the PURR on systems that have it, otherwise the timebase.
+ * Read the SPURR on systems that have it, otherwise the PURR,
+ * or if that doesn't exist return the timebase value passed in.
*/
-static u64 read_purr(void)
+static u64 read_spurr(u64 tb)
{
+ if (cpu_has_feature(CPU_FTR_SPURR))
+ return mfspr(SPRN_SPURR);
if (cpu_has_feature(CPU_FTR_PURR))
return mfspr(SPRN_PURR);
- return mftb();
+ return tb;
}
+#ifdef CONFIG_PPC_SPLPAR
+
/*
- * Read the SPURR on systems that have it, otherwise the purr
+ * Scan the dispatch trace log and count up the stolen time.
+ * Should be called with interrupts disabled.
*/
-static u64 read_spurr(u64 purr)
+static u64 scan_dispatch_log(u64 stop_tb)
{
- /*
- * cpus without PURR won't have a SPURR
- * We already know the former when we use this, so tell gcc
- */
- if (cpu_has_feature(CPU_FTR_PURR) && cpu_has_feature(CPU_FTR_SPURR))
- return mfspr(SPRN_SPURR);
- return purr;
+ u64 i = local_paca->dtl_ridx;
+ struct dtl_entry *dtl = local_paca->dtl_curr;
+ struct dtl_entry *dtl_end = local_paca->dispatch_log_end;
+ struct lppaca *vpa = local_paca->lppaca_ptr;
+ u64 tb_delta;
+ u64 stolen = 0;
+ u64 dtb;
+
+ if (i == vpa->dtl_idx)
+ return 0;
+ while (i < vpa->dtl_idx) {
+ if (dtl_consumer)
+ dtl_consumer(dtl, i);
+ dtb = dtl->timebase;
+ tb_delta = dtl->enqueue_to_dispatch_time +
+ dtl->ready_to_enqueue_time;
+ barrier();
+ if (i + N_DISPATCH_LOG < vpa->dtl_idx) {
+ /* buffer has overflowed */
+ i = vpa->dtl_idx - N_DISPATCH_LOG;
+ dtl = local_paca->dispatch_log + (i % N_DISPATCH_LOG);
+ continue;
+ }
+ if (dtb > stop_tb)
+ break;
+ stolen += tb_delta;
+ ++i;
+ ++dtl;
+ if (dtl == dtl_end)
+ dtl = local_paca->dispatch_log;
+ }
+ local_paca->dtl_ridx = i;
+ local_paca->dtl_curr = dtl;
+ return stolen;
}
/*
+ * Accumulate stolen time by scanning the dispatch trace log.
+ * Called on entry from user mode.
+ */
+void accumulate_stolen_time(void)
+{
+ u64 sst, ust;
+
+ sst = scan_dispatch_log(get_paca()->starttime_user);
+ ust = scan_dispatch_log(get_paca()->starttime);
+ get_paca()->system_time -= sst;
+ get_paca()->user_time -= ust;
+ get_paca()->stolen_time += ust + sst;
+}
+
+static inline u64 calculate_stolen_time(u64 stop_tb)
+{
+ u64 stolen = 0;
+
+ if (get_paca()->dtl_ridx != get_paca()->lppaca_ptr->dtl_idx) {
+ stolen = scan_dispatch_log(stop_tb);
+ get_paca()->system_time -= stolen;
+ }
+
+ stolen += get_paca()->stolen_time;
+ get_paca()->stolen_time = 0;
+ return stolen;
+}
+
+#else /* CONFIG_PPC_SPLPAR */
+static inline u64 calculate_stolen_time(u64 stop_tb)
+{
+ return 0;
+}
+
+#endif /* CONFIG_PPC_SPLPAR */
+
+/*
* Account time for a transition between system, hard irq
* or soft irq state.
*/
void account_system_vtime(struct task_struct *tsk)
{
- u64 now, nowscaled, delta, deltascaled, sys_time;
+ u64 now, nowscaled, delta, deltascaled;
unsigned long flags;
+ u64 stolen, udelta, sys_scaled, user_scaled;
local_irq_save(flags);
- now = read_purr();
+ now = mftb();
nowscaled = read_spurr(now);
- delta = now - get_paca()->startpurr;
+ get_paca()->system_time += now - get_paca()->starttime;
+ get_paca()->starttime = now;
deltascaled = nowscaled - get_paca()->startspurr;
- get_paca()->startpurr = now;
get_paca()->startspurr = nowscaled;
- if (!in_interrupt()) {
- /* deltascaled includes both user and system time.
- * Hence scale it based on the purr ratio to estimate
- * the system time */
- sys_time = get_paca()->system_time;
- if (get_paca()->user_time)
- deltascaled = deltascaled * sys_time /
- (sys_time + get_paca()->user_time);
- delta += sys_time;
- get_paca()->system_time = 0;
+
+ stolen = calculate_stolen_time(now);
+
+ delta = get_paca()->system_time;
+ get_paca()->system_time = 0;
+ udelta = get_paca()->user_time - get_paca()->utime_sspurr;
+ get_paca()->utime_sspurr = get_paca()->user_time;
+
+ /*
+ * Because we don't read the SPURR on every kernel entry/exit,
+ * deltascaled includes both user and system SPURR ticks.
+ * Apportion these ticks to system SPURR ticks and user
+ * SPURR ticks in the same ratio as the system time (delta)
+ * and user time (udelta) values obtained from the timebase
+ * over the same interval. The system ticks get accounted here;
+ * the user ticks get saved up in paca->user_time_scaled to be
+ * used by account_process_tick.
+ */
+ sys_scaled = delta;
+ user_scaled = udelta;
+ if (deltascaled != delta + udelta) {
+ if (udelta) {
+ sys_scaled = deltascaled * delta / (delta + udelta);
+ user_scaled = deltascaled - sys_scaled;
+ } else {
+ sys_scaled = deltascaled;
+ }
+ }
+ get_paca()->user_time_scaled += user_scaled;
+
+ if (in_irq() || idle_task(smp_processor_id()) != tsk) {
+ account_system_time(tsk, 0, delta, sys_scaled);
+ if (stolen)
+ account_steal_time(stolen);
+ } else {
+ account_idle_time(delta + stolen);
}
- if (in_irq() || idle_task(smp_processor_id()) != tsk)
- account_system_time(tsk, 0, delta, deltascaled);
- else
- account_idle_time(delta);
- __get_cpu_var(cputime_last_delta) = delta;
- __get_cpu_var(cputime_scaled_last_delta) = deltascaled;
local_irq_restore(flags);
}
EXPORT_SYMBOL_GPL(account_system_vtime);
@@ -265,125 +357,26 @@ EXPORT_SYMBOL_GPL(account_system_vtime);
* by the exception entry and exit code to the generic process
* user and system time records.
* Must be called with interrupts disabled.
+ * Assumes that account_system_vtime() has been called recently
+ * (i.e. since the last entry from usermode) so that
+ * get_paca()->user_time_scaled is up to date.
*/
void account_process_tick(struct task_struct *tsk, int user_tick)
{
cputime_t utime, utimescaled;
utime = get_paca()->user_time;
+ utimescaled = get_paca()->user_time_scaled;
get_paca()->user_time = 0;
- utimescaled = cputime_to_scaled(utime);
+ get_paca()->user_time_scaled = 0;
+ get_paca()->utime_sspurr = 0;
account_user_time(tsk, utime, utimescaled);
}
-/*
- * Stuff for accounting stolen time.
- */
-struct cpu_purr_data {
- int initialized; /* thread is running */
- u64 tb; /* last TB value read */
- u64 purr; /* last PURR value read */
- u64 spurr; /* last SPURR value read */
-};
-
-/*
- * Each entry in the cpu_purr_data array is manipulated only by its
- * "owner" cpu -- usually in the timer interrupt but also occasionally
- * in process context for cpu online. As long as cpus do not touch
- * each others' cpu_purr_data, disabling local interrupts is
- * sufficient to serialize accesses.
- */
-static DEFINE_PER_CPU(struct cpu_purr_data, cpu_purr_data);
-
-static void snapshot_tb_and_purr(void *data)
-{
- unsigned long flags;
- struct cpu_purr_data *p = &__get_cpu_var(cpu_purr_data);
-
- local_irq_save(flags);
- p->tb = get_tb_or_rtc();
- p->purr = mfspr(SPRN_PURR);
- wmb();
- p->initialized = 1;
- local_irq_restore(flags);
-}
-
-/*
- * Called during boot when all cpus have come up.
- */
-void snapshot_timebases(void)
-{
- if (!cpu_has_feature(CPU_FTR_PURR))
- return;
- on_each_cpu(snapshot_tb_and_purr, NULL, 1);
-}
-
-/*
- * Must be called with interrupts disabled.
- */
-void calculate_steal_time(void)
-{
- u64 tb, purr;
- s64 stolen;
- struct cpu_purr_data *pme;
-
- pme = &__get_cpu_var(cpu_purr_data);
- if (!pme->initialized)
- return; /* !CPU_FTR_PURR or early in early boot */
- tb = mftb();
- purr = mfspr(SPRN_PURR);
- stolen = (tb - pme->tb) - (purr - pme->purr);
- if (stolen > 0) {
- if (idle_task(smp_processor_id()) != current)
- account_steal_time(stolen);
- else
- account_idle_time(stolen);
- }
- pme->tb = tb;
- pme->purr = purr;
-}
-
-#ifdef CONFIG_PPC_SPLPAR
-/*
- * Must be called before the cpu is added to the online map when
- * a cpu is being brought up at runtime.
- */
-static void snapshot_purr(void)
-{
- struct cpu_purr_data *pme;
- unsigned long flags;
-
- if (!cpu_has_feature(CPU_FTR_PURR))
- return;
- local_irq_save(flags);
- pme = &__get_cpu_var(cpu_purr_data);
- pme->tb = mftb();
- pme->purr = mfspr(SPRN_PURR);
- pme->initialized = 1;
- local_irq_restore(flags);
-}
-
-#endif /* CONFIG_PPC_SPLPAR */
-
#else /* ! CONFIG_VIRT_CPU_ACCOUNTING */
#define calc_cputime_factors()
-#define calculate_steal_time() do { } while (0)
#endif
-#if !(defined(CONFIG_VIRT_CPU_ACCOUNTING) && defined(CONFIG_PPC_SPLPAR))
-#define snapshot_purr() do { } while (0)
-#endif
-
-/*
- * Called when a cpu comes up after the system has finished booting,
- * i.e. as a result of a hotplug cpu action.
- */
-void snapshot_timebase(void)
-{
- __get_cpu_var(last_jiffy) = get_tb_or_rtc();
- snapshot_purr();
-}
-
void __delay(unsigned long loops)
{
unsigned long start;
@@ -493,60 +486,60 @@ void __init iSeries_time_init_early(void)
}
#endif /* CONFIG_PPC_ISERIES */
-#ifdef CONFIG_PERF_EVENTS
+#ifdef CONFIG_IRQ_WORK
/*
* 64-bit uses a byte in the PACA, 32-bit uses a per-cpu variable...
*/
#ifdef CONFIG_PPC64
-static inline unsigned long test_perf_event_pending(void)
+static inline unsigned long test_irq_work_pending(void)
{
unsigned long x;
asm volatile("lbz %0,%1(13)"
: "=r" (x)
- : "i" (offsetof(struct paca_struct, perf_event_pending)));
+ : "i" (offsetof(struct paca_struct, irq_work_pending)));
return x;
}
-static inline void set_perf_event_pending_flag(void)
+static inline void set_irq_work_pending_flag(void)
{
asm volatile("stb %0,%1(13)" : :
"r" (1),
- "i" (offsetof(struct paca_struct, perf_event_pending)));
+ "i" (offsetof(struct paca_struct, irq_work_pending)));
}
-static inline void clear_perf_event_pending(void)
+static inline void clear_irq_work_pending(void)
{
asm volatile("stb %0,%1(13)" : :
"r" (0),
- "i" (offsetof(struct paca_struct, perf_event_pending)));
+ "i" (offsetof(struct paca_struct, irq_work_pending)));
}
#else /* 32-bit */
-DEFINE_PER_CPU(u8, perf_event_pending);
+DEFINE_PER_CPU(u8, irq_work_pending);
-#define set_perf_event_pending_flag() __get_cpu_var(perf_event_pending) = 1
-#define test_perf_event_pending() __get_cpu_var(perf_event_pending)
-#define clear_perf_event_pending() __get_cpu_var(perf_event_pending) = 0
+#define set_irq_work_pending_flag() __get_cpu_var(irq_work_pending) = 1
+#define test_irq_work_pending() __get_cpu_var(irq_work_pending)
+#define clear_irq_work_pending() __get_cpu_var(irq_work_pending) = 0
#endif /* 32 vs 64 bit */
-void set_perf_event_pending(void)
+void set_irq_work_pending(void)
{
preempt_disable();
- set_perf_event_pending_flag();
+ set_irq_work_pending_flag();
set_dec(1);
preempt_enable();
}
-#else /* CONFIG_PERF_EVENTS */
+#else /* CONFIG_IRQ_WORK */
-#define test_perf_event_pending() 0
-#define clear_perf_event_pending()
+#define test_irq_work_pending() 0
+#define clear_irq_work_pending()
-#endif /* CONFIG_PERF_EVENTS */
+#endif /* CONFIG_IRQ_WORK */
/*
* For iSeries shared processors, we have to let the hypervisor
@@ -585,11 +578,9 @@ void timer_interrupt(struct pt_regs * regs)
old_regs = set_irq_regs(regs);
irq_enter();
- calculate_steal_time();
-
- if (test_perf_event_pending()) {
- clear_perf_event_pending();
- perf_event_do_pending();
+ if (test_irq_work_pending()) {
+ clear_irq_work_pending();
+ irq_work_run();
}
#ifdef CONFIG_PPC_ISERIES
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index a45a63c3a0c7..1b2cdc8eec90 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -538,6 +538,11 @@ int machine_check_e500(struct pt_regs *regs)
return 0;
}
+
+int machine_check_generic(struct pt_regs *regs)
+{
+ return 0;
+}
#elif defined(CONFIG_E200)
int machine_check_e200(struct pt_regs *regs)
{
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c
index 13002fe206e7..fd8728729abc 100644
--- a/arch/powerpc/kernel/vdso.c
+++ b/arch/powerpc/kernel/vdso.c
@@ -159,7 +159,7 @@ static void dump_vdso_pages(struct vm_area_struct * vma)
{
int i;
- if (!vma || test_thread_flag(TIF_32BIT)) {
+ if (!vma || is_32bit_task()) {
printk("vDSO32 @ %016lx:\n", (unsigned long)vdso32_kbase);
for (i=0; i<vdso32_pages; i++) {
struct page *pg = virt_to_page(vdso32_kbase +
@@ -170,7 +170,7 @@ static void dump_vdso_pages(struct vm_area_struct * vma)
dump_one_vdso_page(pg, upg);
}
}
- if (!vma || !test_thread_flag(TIF_32BIT)) {
+ if (!vma || !is_32bit_task()) {
printk("vDSO64 @ %016lx:\n", (unsigned long)vdso64_kbase);
for (i=0; i<vdso64_pages; i++) {
struct page *pg = virt_to_page(vdso64_kbase +
@@ -200,7 +200,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
return 0;
#ifdef CONFIG_PPC64
- if (test_thread_flag(TIF_32BIT)) {
+ if (is_32bit_task()) {
vdso_pagelist = vdso32_pagelist;
vdso_pages = vdso32_pages;
vdso_base = VDSO32_MBASE;
diff --git a/arch/powerpc/kernel/vdso32/Makefile b/arch/powerpc/kernel/vdso32/Makefile
index 51ead52141bd..9a7946c41738 100644
--- a/arch/powerpc/kernel/vdso32/Makefile
+++ b/arch/powerpc/kernel/vdso32/Makefile
@@ -14,10 +14,10 @@ obj-vdso32 := $(addprefix $(obj)/, $(obj-vdso32))
GCOV_PROFILE := n
-EXTRA_CFLAGS := -shared -fno-common -fno-builtin
-EXTRA_CFLAGS += -nostdlib -Wl,-soname=linux-vdso32.so.1 \
+ccflags-y := -shared -fno-common -fno-builtin
+ccflags-y += -nostdlib -Wl,-soname=linux-vdso32.so.1 \
$(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
-EXTRA_AFLAGS := -D__VDSO32__ -s
+asflags-y := -D__VDSO32__ -s
obj-y += vdso32_wrapper.o
extra-y += vdso32.lds
diff --git a/arch/powerpc/kernel/vdso64/Makefile b/arch/powerpc/kernel/vdso64/Makefile
index 79da65d44a2a..8c500d8622e4 100644
--- a/arch/powerpc/kernel/vdso64/Makefile
+++ b/arch/powerpc/kernel/vdso64/Makefile
@@ -9,10 +9,10 @@ obj-vdso64 := $(addprefix $(obj)/, $(obj-vdso64))
GCOV_PROFILE := n
-EXTRA_CFLAGS := -shared -fno-common -fno-builtin
-EXTRA_CFLAGS += -nostdlib -Wl,-soname=linux-vdso64.so.1 \
+ccflags-y := -shared -fno-common -fno-builtin
+ccflags-y += -nostdlib -Wl,-soname=linux-vdso64.so.1 \
$(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
-EXTRA_AFLAGS := -D__VDSO64__ -s
+asflags-y := -D__VDSO64__ -s
obj-y += vdso64_wrapper.o
extra-y += vdso64.lds
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index fa3469ddaef8..d692989a4318 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -1184,7 +1184,12 @@ EXPORT_SYMBOL(vio_unregister_driver);
/* vio_dev refcount hit 0 */
static void __devinit vio_dev_release(struct device *dev)
{
- /* XXX should free TCE table */
+ struct iommu_table *tbl = get_iommu_table_base(dev);
+
+ /* iSeries uses a common table for all vio devices */
+ if (!firmware_has_feature(FW_FEATURE_ISERIES) && tbl)
+ iommu_free_table(tbl, dev->of_node ?
+ dev->of_node->full_name : dev_name(dev));
of_node_put(dev->of_node);
kfree(to_vio_dev(dev));
}
@@ -1254,8 +1259,7 @@ struct vio_dev *vio_register_device_node(struct device_node *of_node)
if (device_register(&viodev->dev)) {
printk(KERN_ERR "%s: failed to register device %s\n",
__func__, dev_name(&viodev->dev));
- /* XXX free TCE table */
- kfree(viodev);
+ put_device(&viodev->dev);
return NULL;
}
diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile
index d45c818a384c..4d6863823f69 100644
--- a/arch/powerpc/kvm/Makefile
+++ b/arch/powerpc/kvm/Makefile
@@ -4,7 +4,7 @@
subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
-EXTRA_CFLAGS += -Ivirt/kvm -Iarch/powerpc/kvm
+ccflags-y := -Ivirt/kvm -Iarch/powerpc/kvm
common-objs-y = $(addprefix ../../../virt/kvm/, kvm_main.o coalesced_mmio.o)
diff --git a/arch/powerpc/kvm/book3s_paired_singles.c b/arch/powerpc/kvm/book3s_paired_singles.c
index 474f2e24050a..35a701f3ece4 100644
--- a/arch/powerpc/kvm/book3s_paired_singles.c
+++ b/arch/powerpc/kvm/book3s_paired_singles.c
@@ -159,7 +159,7 @@
static inline void kvmppc_sync_qpr(struct kvm_vcpu *vcpu, int rt)
{
- kvm_cvt_df(&vcpu->arch.fpr[rt], &vcpu->arch.qpr[rt], &vcpu->arch.fpscr);
+ kvm_cvt_df(&vcpu->arch.fpr[rt], &vcpu->arch.qpr[rt]);
}
static void kvmppc_inject_pf(struct kvm_vcpu *vcpu, ulong eaddr, bool is_store)
@@ -204,7 +204,7 @@ static int kvmppc_emulate_fpr_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
/* put in registers */
switch (ls_type) {
case FPU_LS_SINGLE:
- kvm_cvt_fd((u32*)tmp, &vcpu->arch.fpr[rs], &vcpu->arch.fpscr);
+ kvm_cvt_fd((u32*)tmp, &vcpu->arch.fpr[rs]);
vcpu->arch.qpr[rs] = *((u32*)tmp);
break;
case FPU_LS_DOUBLE:
@@ -230,7 +230,7 @@ static int kvmppc_emulate_fpr_store(struct kvm_run *run, struct kvm_vcpu *vcpu,
switch (ls_type) {
case FPU_LS_SINGLE:
- kvm_cvt_df(&vcpu->arch.fpr[rs], (u32*)tmp, &vcpu->arch.fpscr);
+ kvm_cvt_df(&vcpu->arch.fpr[rs], (u32*)tmp);
val = *((u32*)tmp);
len = sizeof(u32);
break;
@@ -296,7 +296,7 @@ static int kvmppc_emulate_psq_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
emulated = EMULATE_DONE;
/* put in registers */
- kvm_cvt_fd(&tmp[0], &vcpu->arch.fpr[rs], &vcpu->arch.fpscr);
+ kvm_cvt_fd(&tmp[0], &vcpu->arch.fpr[rs]);
vcpu->arch.qpr[rs] = tmp[1];
dprintk(KERN_INFO "KVM: PSQ_LD [0x%x, 0x%x] at 0x%lx (%d)\n", tmp[0],
@@ -314,7 +314,7 @@ static int kvmppc_emulate_psq_store(struct kvm_run *run, struct kvm_vcpu *vcpu,
u32 tmp[2];
int len = w ? sizeof(u32) : sizeof(u64);
- kvm_cvt_df(&vcpu->arch.fpr[rs], &tmp[0], &vcpu->arch.fpscr);
+ kvm_cvt_df(&vcpu->arch.fpr[rs], &tmp[0]);
tmp[1] = vcpu->arch.qpr[rs];
r = kvmppc_st(vcpu, &addr, len, tmp, true);
@@ -516,9 +516,9 @@ static int kvmppc_ps_three_in(struct kvm_vcpu *vcpu, bool rc,
WARN_ON(rc);
/* PS0 */
- kvm_cvt_df(&fpr[reg_in1], &ps0_in1, &vcpu->arch.fpscr);
- kvm_cvt_df(&fpr[reg_in2], &ps0_in2, &vcpu->arch.fpscr);
- kvm_cvt_df(&fpr[reg_in3], &ps0_in3, &vcpu->arch.fpscr);
+ kvm_cvt_df(&fpr[reg_in1], &ps0_in1);
+ kvm_cvt_df(&fpr[reg_in2], &ps0_in2);
+ kvm_cvt_df(&fpr[reg_in3], &ps0_in3);
if (scalar & SCALAR_LOW)
ps0_in2 = qpr[reg_in2];
@@ -529,7 +529,7 @@ static int kvmppc_ps_three_in(struct kvm_vcpu *vcpu, bool rc,
ps0_in1, ps0_in2, ps0_in3, ps0_out);
if (!(scalar & SCALAR_NO_PS0))
- kvm_cvt_fd(&ps0_out, &fpr[reg_out], &vcpu->arch.fpscr);
+ kvm_cvt_fd(&ps0_out, &fpr[reg_out]);
/* PS1 */
ps1_in1 = qpr[reg_in1];
@@ -566,12 +566,12 @@ static int kvmppc_ps_two_in(struct kvm_vcpu *vcpu, bool rc,
WARN_ON(rc);
/* PS0 */
- kvm_cvt_df(&fpr[reg_in1], &ps0_in1, &vcpu->arch.fpscr);
+ kvm_cvt_df(&fpr[reg_in1], &ps0_in1);
if (scalar & SCALAR_LOW)
ps0_in2 = qpr[reg_in2];
else
- kvm_cvt_df(&fpr[reg_in2], &ps0_in2, &vcpu->arch.fpscr);
+ kvm_cvt_df(&fpr[reg_in2], &ps0_in2);
func(&vcpu->arch.fpscr, &ps0_out, &ps0_in1, &ps0_in2);
@@ -579,7 +579,7 @@ static int kvmppc_ps_two_in(struct kvm_vcpu *vcpu, bool rc,
dprintk(KERN_INFO "PS2 ps0 -> f(0x%x, 0x%x) = 0x%x\n",
ps0_in1, ps0_in2, ps0_out);
- kvm_cvt_fd(&ps0_out, &fpr[reg_out], &vcpu->arch.fpscr);
+ kvm_cvt_fd(&ps0_out, &fpr[reg_out]);
}
/* PS1 */
@@ -615,13 +615,13 @@ static int kvmppc_ps_one_in(struct kvm_vcpu *vcpu, bool rc,
WARN_ON(rc);
/* PS0 */
- kvm_cvt_df(&fpr[reg_in], &ps0_in, &vcpu->arch.fpscr);
+ kvm_cvt_df(&fpr[reg_in], &ps0_in);
func(&vcpu->arch.fpscr, &ps0_out, &ps0_in);
dprintk(KERN_INFO "PS1 ps0 -> f(0x%x) = 0x%x\n",
ps0_in, ps0_out);
- kvm_cvt_fd(&ps0_out, &fpr[reg_out], &vcpu->arch.fpscr);
+ kvm_cvt_fd(&ps0_out, &fpr[reg_out]);
/* PS1 */
ps1_in = qpr[reg_in];
@@ -671,7 +671,7 @@ int kvmppc_emulate_paired_single(struct kvm_run *run, struct kvm_vcpu *vcpu)
#ifdef DEBUG
for (i = 0; i < ARRAY_SIZE(vcpu->arch.fpr); i++) {
u32 f;
- kvm_cvt_df(&vcpu->arch.fpr[i], &f, &vcpu->arch.fpscr);
+ kvm_cvt_df(&vcpu->arch.fpr[i], &f);
dprintk(KERN_INFO "FPR[%d] = 0x%x / 0x%llx QPR[%d] = 0x%x\n",
i, f, vcpu->arch.fpr[i], i, vcpu->arch.qpr[i]);
}
@@ -796,8 +796,7 @@ int kvmppc_emulate_paired_single(struct kvm_run *run, struct kvm_vcpu *vcpu)
vcpu->arch.fpr[ax_rd] = vcpu->arch.fpr[ax_ra];
/* vcpu->arch.qpr[ax_rd] = vcpu->arch.fpr[ax_rb]; */
kvm_cvt_df(&vcpu->arch.fpr[ax_rb],
- &vcpu->arch.qpr[ax_rd],
- &vcpu->arch.fpscr);
+ &vcpu->arch.qpr[ax_rd]);
break;
case OP_4X_PS_MERGE01:
WARN_ON(rcomp);
@@ -808,19 +807,16 @@ int kvmppc_emulate_paired_single(struct kvm_run *run, struct kvm_vcpu *vcpu)
WARN_ON(rcomp);
/* vcpu->arch.fpr[ax_rd] = vcpu->arch.qpr[ax_ra]; */
kvm_cvt_fd(&vcpu->arch.qpr[ax_ra],
- &vcpu->arch.fpr[ax_rd],
- &vcpu->arch.fpscr);
+ &vcpu->arch.fpr[ax_rd]);
/* vcpu->arch.qpr[ax_rd] = vcpu->arch.fpr[ax_rb]; */
kvm_cvt_df(&vcpu->arch.fpr[ax_rb],
- &vcpu->arch.qpr[ax_rd],
- &vcpu->arch.fpscr);
+ &vcpu->arch.qpr[ax_rd]);
break;
case OP_4X_PS_MERGE11:
WARN_ON(rcomp);
/* vcpu->arch.fpr[ax_rd] = vcpu->arch.qpr[ax_ra]; */
kvm_cvt_fd(&vcpu->arch.qpr[ax_ra],
- &vcpu->arch.fpr[ax_rd],
- &vcpu->arch.fpscr);
+ &vcpu->arch.fpr[ax_rd]);
vcpu->arch.qpr[ax_rd] = vcpu->arch.qpr[ax_rb];
break;
}
@@ -1255,7 +1251,7 @@ int kvmppc_emulate_paired_single(struct kvm_run *run, struct kvm_vcpu *vcpu)
#ifdef DEBUG
for (i = 0; i < ARRAY_SIZE(vcpu->arch.fpr); i++) {
u32 f;
- kvm_cvt_df(&vcpu->arch.fpr[i], &f, &vcpu->arch.fpscr);
+ kvm_cvt_df(&vcpu->arch.fpr[i], &f);
dprintk(KERN_INFO "FPR[%d] = 0x%x\n", i, f);
}
#endif
diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c
index 4568ec386c2a..b83ba581fd8e 100644
--- a/arch/powerpc/kvm/emulate.c
+++ b/arch/powerpc/kvm/emulate.c
@@ -145,7 +145,7 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
/* this default type might be overwritten by subcategories */
kvmppc_set_exit_type(vcpu, EMULATED_INST_EXITS);
- pr_debug(KERN_INFO "Emulating opcode %d / %d\n", get_op(inst), get_xop(inst));
+ pr_debug("Emulating opcode %d / %d\n", get_op(inst), get_xop(inst));
switch (get_op(inst)) {
case OP_TRAP:
@@ -275,7 +275,7 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
{
u64 jd = get_tb() - vcpu->arch.dec_jiffies;
kvmppc_set_gpr(vcpu, rt, vcpu->arch.dec - jd);
- pr_debug(KERN_INFO "mfDEC: %x - %llx = %lx\n",
+ pr_debug("mfDEC: %x - %llx = %lx\n",
vcpu->arch.dec, jd,
kvmppc_get_gpr(vcpu, rt));
break;
diff --git a/arch/powerpc/kvm/fpu.S b/arch/powerpc/kvm/fpu.S
index cb34bbe16113..bf68d597549e 100644
--- a/arch/powerpc/kvm/fpu.S
+++ b/arch/powerpc/kvm/fpu.S
@@ -273,19 +273,11 @@ FPD_THREE_IN(fnmsub)
FPD_THREE_IN(fnmadd)
_GLOBAL(kvm_cvt_fd)
- lfd 0,0(r5) /* load up fpscr value */
- MTFSF_L(0)
lfs 0,0(r3)
stfd 0,0(r4)
- mffs 0
- stfd 0,0(r5) /* save new fpscr value */
blr
_GLOBAL(kvm_cvt_df)
- lfd 0,0(r5) /* load up fpscr value */
- MTFSF_L(0)
lfd 0,0(r3)
stfs 0,0(r4)
- mffs 0
- stfd 0,0(r5) /* save new fpscr value */
blr
diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
index 5bb89c828070..889f2bc106dd 100644
--- a/arch/powerpc/lib/Makefile
+++ b/arch/powerpc/lib/Makefile
@@ -4,9 +4,7 @@
subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
-ifeq ($(CONFIG_PPC64),y)
-EXTRA_CFLAGS += -mno-minimal-toc
-endif
+ccflags-$(CONFIG_PPC64) := -mno-minimal-toc
CFLAGS_REMOVE_code-patching.o = -pg
CFLAGS_REMOVE_feature-fixups.o = -pg
@@ -17,7 +15,8 @@ obj-$(CONFIG_PPC32) += div64.o copy_32.o
obj-$(CONFIG_HAS_IOMEM) += devres.o
obj-$(CONFIG_PPC64) += copypage_64.o copyuser_64.o \
- memcpy_64.o usercopy_64.o mem_64.o string.o
+ memcpy_64.o usercopy_64.o mem_64.o string.o \
+ checksum_wrappers_64.o
obj-$(CONFIG_XMON) += sstep.o ldstfp.o
obj-$(CONFIG_KPROBES) += sstep.o ldstfp.o
obj-$(CONFIG_HAVE_HW_BREAKPOINT) += sstep.o ldstfp.o
diff --git a/arch/powerpc/lib/checksum_64.S b/arch/powerpc/lib/checksum_64.S
index ef96c6c58efc..18245af38aea 100644
--- a/arch/powerpc/lib/checksum_64.S
+++ b/arch/powerpc/lib/checksum_64.S
@@ -65,165 +65,393 @@ _GLOBAL(csum_tcpudp_magic)
srwi r3,r3,16
blr
+#define STACKFRAMESIZE 256
+#define STK_REG(i) (112 + ((i)-14)*8)
+
/*
* Computes the checksum of a memory block at buff, length len,
* and adds in "sum" (32-bit).
*
- * This code assumes at least halfword alignment, though the length
- * can be any number of bytes. The sum is accumulated in r5.
- *
* csum_partial(r3=buff, r4=len, r5=sum)
*/
_GLOBAL(csum_partial)
- subi r3,r3,8 /* we'll offset by 8 for the loads */
- srdi. r6,r4,3 /* divide by 8 for doubleword count */
- addic r5,r5,0 /* clear carry */
- beq 3f /* if we're doing < 8 bytes */
- andi. r0,r3,2 /* aligned on a word boundary already? */
- beq+ 1f
- lhz r6,8(r3) /* do 2 bytes to get aligned */
- addi r3,r3,2
- subi r4,r4,2
- addc r5,r5,r6
- srdi. r6,r4,3 /* recompute number of doublewords */
- beq 3f /* any left? */
-1: mtctr r6
-2: ldu r6,8(r3) /* main sum loop */
- adde r5,r5,r6
- bdnz 2b
- andi. r4,r4,7 /* compute bytes left to sum after doublewords */
-3: cmpwi 0,r4,4 /* is at least a full word left? */
- blt 4f
- lwz r6,8(r3) /* sum this word */
+ addic r0,r5,0 /* clear carry */
+
+ srdi. r6,r4,3 /* less than 8 bytes? */
+ beq .Lcsum_tail_word
+
+ /*
+ * If only halfword aligned, align to a double word. Since odd
+ * aligned addresses should be rare and they would require more
+ * work to calculate the correct checksum, we ignore that case
+ * and take the potential slowdown of unaligned loads.
+ */
+ rldicl. r6,r3,64-1,64-2 /* r6 = (r3 & 0x3) >> 1 */
+ beq .Lcsum_aligned
+
+ li r7,4
+ sub r6,r7,r6
+ mtctr r6
+
+1:
+ lhz r6,0(r3) /* align to doubleword */
+ subi r4,r4,2
+ addi r3,r3,2
+ adde r0,r0,r6
+ bdnz 1b
+
+.Lcsum_aligned:
+ /*
+ * We unroll the loop such that each iteration is 64 bytes with an
+ * entry and exit limb of 64 bytes, meaning a minimum size of
+ * 128 bytes.
+ */
+ srdi. r6,r4,7
+ beq .Lcsum_tail_doublewords /* len < 128 */
+
+ srdi r6,r4,6
+ subi r6,r6,1
+ mtctr r6
+
+ stdu r1,-STACKFRAMESIZE(r1)
+ std r14,STK_REG(r14)(r1)
+ std r15,STK_REG(r15)(r1)
+ std r16,STK_REG(r16)(r1)
+
+ ld r6,0(r3)
+ ld r9,8(r3)
+
+ ld r10,16(r3)
+ ld r11,24(r3)
+
+ /*
+ * On POWER6 and POWER7 back to back addes take 2 cycles because of
+ * the XER dependency. This means the fastest this loop can go is
+ * 16 cycles per iteration. The scheduling of the loop below has
+ * been shown to hit this on both POWER6 and POWER7.
+ */
+ .align 5
+2:
+ adde r0,r0,r6
+ ld r12,32(r3)
+ ld r14,40(r3)
+
+ adde r0,r0,r9
+ ld r15,48(r3)
+ ld r16,56(r3)
+ addi r3,r3,64
+
+ adde r0,r0,r10
+
+ adde r0,r0,r11
+
+ adde r0,r0,r12
+
+ adde r0,r0,r14
+
+ adde r0,r0,r15
+ ld r6,0(r3)
+ ld r9,8(r3)
+
+ adde r0,r0,r16
+ ld r10,16(r3)
+ ld r11,24(r3)
+ bdnz 2b
+
+
+ adde r0,r0,r6
+ ld r12,32(r3)
+ ld r14,40(r3)
+
+ adde r0,r0,r9
+ ld r15,48(r3)
+ ld r16,56(r3)
+ addi r3,r3,64
+
+ adde r0,r0,r10
+ adde r0,r0,r11
+ adde r0,r0,r12
+ adde r0,r0,r14
+ adde r0,r0,r15
+ adde r0,r0,r16
+
+ ld r14,STK_REG(r14)(r1)
+ ld r15,STK_REG(r15)(r1)
+ ld r16,STK_REG(r16)(r1)
+ addi r1,r1,STACKFRAMESIZE
+
+ andi. r4,r4,63
+
+.Lcsum_tail_doublewords: /* Up to 127 bytes to go */
+ srdi. r6,r4,3
+ beq .Lcsum_tail_word
+
+ mtctr r6
+3:
+ ld r6,0(r3)
+ addi r3,r3,8
+ adde r0,r0,r6
+ bdnz 3b
+
+ andi. r4,r4,7
+
+.Lcsum_tail_word: /* Up to 7 bytes to go */
+ srdi. r6,r4,2
+ beq .Lcsum_tail_halfword
+
+ lwz r6,0(r3)
addi r3,r3,4
+ adde r0,r0,r6
subi r4,r4,4
- adde r5,r5,r6
-4: cmpwi 0,r4,2 /* is at least a halfword left? */
- blt+ 5f
- lhz r6,8(r3) /* sum this halfword */
- addi r3,r3,2
- subi r4,r4,2
- adde r5,r5,r6
-5: cmpwi 0,r4,1 /* is at least a byte left? */
- bne+ 6f
- lbz r6,8(r3) /* sum this byte */
- slwi r6,r6,8 /* this byte is assumed to be the upper byte of a halfword */
- adde r5,r5,r6
-6: addze r5,r5 /* add in final carry */
- rldicl r4,r5,32,0 /* fold two 32-bit halves together */
- add r3,r4,r5
- srdi r3,r3,32
- blr
+
+.Lcsum_tail_halfword: /* Up to 3 bytes to go */
+ srdi. r6,r4,1
+ beq .Lcsum_tail_byte
+
+ lhz r6,0(r3)
+ addi r3,r3,2
+ adde r0,r0,r6
+ subi r4,r4,2
+
+.Lcsum_tail_byte: /* Up to 1 byte to go */
+ andi. r6,r4,1
+ beq .Lcsum_finish
+
+ lbz r6,0(r3)
+ sldi r9,r6,8 /* Pad the byte out to 16 bits */
+ adde r0,r0,r9
+
+.Lcsum_finish:
+ addze r0,r0 /* add in final carry */
+ rldicl r4,r0,32,0 /* fold two 32 bit halves together */
+ add r3,r4,r0
+ srdi r3,r3,32
+ blr
+
+
+ .macro source
+100:
+ .section __ex_table,"a"
+ .align 3
+ .llong 100b,.Lsrc_error
+ .previous
+ .endm
+
+ .macro dest
+200:
+ .section __ex_table,"a"
+ .align 3
+ .llong 200b,.Ldest_error
+ .previous
+ .endm
/*
* Computes the checksum of a memory block at src, length len,
* and adds in "sum" (32-bit), while copying the block to dst.
* If an access exception occurs on src or dst, it stores -EFAULT
- * to *src_err or *dst_err respectively, and (for an error on
- * src) zeroes the rest of dst.
- *
- * This code needs to be reworked to take advantage of 64 bit sum+copy.
- * However, due to tokenring halfword alignment problems this will be very
- * tricky. For now we'll leave it until we instrument it somehow.
+ * to *src_err or *dst_err respectively. The caller must take any action
+ * required in this case (zeroing memory, recalculating partial checksum etc).
*
* csum_partial_copy_generic(r3=src, r4=dst, r5=len, r6=sum, r7=src_err, r8=dst_err)
*/
_GLOBAL(csum_partial_copy_generic)
- addic r0,r6,0
- subi r3,r3,4
- subi r4,r4,4
- srwi. r6,r5,2
- beq 3f /* if we're doing < 4 bytes */
- andi. r9,r4,2 /* Align dst to longword boundary */
- beq+ 1f
-81: lhz r6,4(r3) /* do 2 bytes to get aligned */
- addi r3,r3,2
+ addic r0,r6,0 /* clear carry */
+
+ srdi. r6,r5,3 /* less than 8 bytes? */
+ beq .Lcopy_tail_word
+
+ /*
+ * If only halfword aligned, align to a double word. Since odd
+ * aligned addresses should be rare and they would require more
+ * work to calculate the correct checksum, we ignore that case
+ * and take the potential slowdown of unaligned loads.
+ *
+ * If the source and destination are relatively unaligned we only
+ * align the source. This keeps things simple.
+ */
+ rldicl. r6,r3,64-1,64-2 /* r6 = (r3 & 0x3) >> 1 */
+ beq .Lcopy_aligned
+
+ li r7,4
+ sub r6,r7,r6
+ mtctr r6
+
+1:
+source; lhz r6,0(r3) /* align to doubleword */
subi r5,r5,2
-91: sth r6,4(r4)
- addi r4,r4,2
- addc r0,r0,r6
- srwi. r6,r5,2 /* # words to do */
- beq 3f
-1: mtctr r6
-82: lwzu r6,4(r3) /* the bdnz has zero overhead, so it should */
-92: stwu r6,4(r4) /* be unnecessary to unroll this loop */
- adde r0,r0,r6
- bdnz 82b
- andi. r5,r5,3
-3: cmpwi 0,r5,2
- blt+ 4f
-83: lhz r6,4(r3)
addi r3,r3,2
- subi r5,r5,2
-93: sth r6,4(r4)
+ adde r0,r0,r6
+dest; sth r6,0(r4)
addi r4,r4,2
+ bdnz 1b
+
+.Lcopy_aligned:
+ /*
+ * We unroll the loop such that each iteration is 64 bytes with an
+ * entry and exit limb of 64 bytes, meaning a minimum size of
+ * 128 bytes.
+ */
+ srdi. r6,r5,7
+ beq .Lcopy_tail_doublewords /* len < 128 */
+
+ srdi r6,r5,6
+ subi r6,r6,1
+ mtctr r6
+
+ stdu r1,-STACKFRAMESIZE(r1)
+ std r14,STK_REG(r14)(r1)
+ std r15,STK_REG(r15)(r1)
+ std r16,STK_REG(r16)(r1)
+
+source; ld r6,0(r3)
+source; ld r9,8(r3)
+
+source; ld r10,16(r3)
+source; ld r11,24(r3)
+
+ /*
+ * On POWER6 and POWER7 back to back addes take 2 cycles because of
+ * the XER dependency. This means the fastest this loop can go is
+ * 16 cycles per iteration. The scheduling of the loop below has
+ * been shown to hit this on both POWER6 and POWER7.
+ */
+ .align 5
+2:
adde r0,r0,r6
-4: cmpwi 0,r5,1
- bne+ 5f
-84: lbz r6,4(r3)
-94: stb r6,4(r4)
- slwi r6,r6,8 /* Upper byte of word */
+source; ld r12,32(r3)
+source; ld r14,40(r3)
+
+ adde r0,r0,r9
+source; ld r15,48(r3)
+source; ld r16,56(r3)
+ addi r3,r3,64
+
+ adde r0,r0,r10
+dest; std r6,0(r4)
+dest; std r9,8(r4)
+
+ adde r0,r0,r11
+dest; std r10,16(r4)
+dest; std r11,24(r4)
+
+ adde r0,r0,r12
+dest; std r12,32(r4)
+dest; std r14,40(r4)
+
+ adde r0,r0,r14
+dest; std r15,48(r4)
+dest; std r16,56(r4)
+ addi r4,r4,64
+
+ adde r0,r0,r15
+source; ld r6,0(r3)
+source; ld r9,8(r3)
+
+ adde r0,r0,r16
+source; ld r10,16(r3)
+source; ld r11,24(r3)
+ bdnz 2b
+
+
adde r0,r0,r6
-5: addze r3,r0 /* add in final carry (unlikely with 64-bit regs) */
- rldicl r4,r3,32,0 /* fold 64 bit value */
- add r3,r4,r3
- srdi r3,r3,32
- blr
+source; ld r12,32(r3)
+source; ld r14,40(r3)
-/* These shouldn't go in the fixup section, since that would
- cause the ex_table addresses to get out of order. */
+ adde r0,r0,r9
+source; ld r15,48(r3)
+source; ld r16,56(r3)
+ addi r3,r3,64
+
+ adde r0,r0,r10
+dest; std r6,0(r4)
+dest; std r9,8(r4)
+
+ adde r0,r0,r11
+dest; std r10,16(r4)
+dest; std r11,24(r4)
+
+ adde r0,r0,r12
+dest; std r12,32(r4)
+dest; std r14,40(r4)
+
+ adde r0,r0,r14
+dest; std r15,48(r4)
+dest; std r16,56(r4)
+ addi r4,r4,64
+
+ adde r0,r0,r15
+ adde r0,r0,r16
+
+ ld r14,STK_REG(r14)(r1)
+ ld r15,STK_REG(r15)(r1)
+ ld r16,STK_REG(r16)(r1)
+ addi r1,r1,STACKFRAMESIZE
+
+ andi. r5,r5,63
+
+.Lcopy_tail_doublewords: /* Up to 127 bytes to go */
+ srdi. r6,r5,3
+ beq .Lcopy_tail_word
- .globl src_error_1
-src_error_1:
- li r6,0
- subi r5,r5,2
-95: sth r6,4(r4)
- addi r4,r4,2
- srwi. r6,r5,2
- beq 3f
mtctr r6
- .globl src_error_2
-src_error_2:
- li r6,0
-96: stwu r6,4(r4)
- bdnz 96b
-3: andi. r5,r5,3
- beq src_error
- .globl src_error_3
-src_error_3:
- li r6,0
- mtctr r5
- addi r4,r4,3
-97: stbu r6,1(r4)
- bdnz 97b
- .globl src_error
-src_error:
+3:
+source; ld r6,0(r3)
+ addi r3,r3,8
+ adde r0,r0,r6
+dest; std r6,0(r4)
+ addi r4,r4,8
+ bdnz 3b
+
+ andi. r5,r5,7
+
+.Lcopy_tail_word: /* Up to 7 bytes to go */
+ srdi. r6,r5,2
+ beq .Lcopy_tail_halfword
+
+source; lwz r6,0(r3)
+ addi r3,r3,4
+ adde r0,r0,r6
+dest; stw r6,0(r4)
+ addi r4,r4,4
+ subi r5,r5,4
+
+.Lcopy_tail_halfword: /* Up to 3 bytes to go */
+ srdi. r6,r5,1
+ beq .Lcopy_tail_byte
+
+source; lhz r6,0(r3)
+ addi r3,r3,2
+ adde r0,r0,r6
+dest; sth r6,0(r4)
+ addi r4,r4,2
+ subi r5,r5,2
+
+.Lcopy_tail_byte: /* Up to 1 byte to go */
+ andi. r6,r5,1
+ beq .Lcopy_finish
+
+source; lbz r6,0(r3)
+ sldi r9,r6,8 /* Pad the byte out to 16 bits */
+ adde r0,r0,r9
+dest; stb r6,0(r4)
+
+.Lcopy_finish:
+ addze r0,r0 /* add in final carry */
+ rldicl r4,r0,32,0 /* fold two 32 bit halves together */
+ add r3,r4,r0
+ srdi r3,r3,32
+ blr
+
+.Lsrc_error:
cmpdi 0,r7,0
- beq 1f
+ beqlr
li r6,-EFAULT
stw r6,0(r7)
-1: addze r3,r0
blr
- .globl dst_error
-dst_error:
+.Ldest_error:
cmpdi 0,r8,0
- beq 1f
+ beqlr
li r6,-EFAULT
stw r6,0(r8)
-1: addze r3,r0
blr
-
-.section __ex_table,"a"
- .align 3
- .llong 81b,src_error_1
- .llong 91b,dst_error
- .llong 82b,src_error_2
- .llong 92b,dst_error
- .llong 83b,src_error_3
- .llong 93b,dst_error
- .llong 84b,src_error_3
- .llong 94b,dst_error
- .llong 95b,dst_error
- .llong 96b,dst_error
- .llong 97b,dst_error
diff --git a/arch/powerpc/lib/checksum_wrappers_64.c b/arch/powerpc/lib/checksum_wrappers_64.c
new file mode 100644
index 000000000000..769b817fbb32
--- /dev/null
+++ b/arch/powerpc/lib/checksum_wrappers_64.c
@@ -0,0 +1,102 @@
+/*
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) IBM Corporation, 2010
+ *
+ * Author: Anton Blanchard <anton@au.ibm.com>
+ */
+#include <linux/module.h>
+#include <linux/compiler.h>
+#include <linux/types.h>
+#include <asm/checksum.h>
+#include <asm/uaccess.h>
+
+__wsum csum_and_copy_from_user(const void __user *src, void *dst,
+ int len, __wsum sum, int *err_ptr)
+{
+ unsigned int csum;
+
+ might_sleep();
+
+ *err_ptr = 0;
+
+ if (!len) {
+ csum = 0;
+ goto out;
+ }
+
+ if (unlikely((len < 0) || !access_ok(VERIFY_READ, src, len))) {
+ *err_ptr = -EFAULT;
+ csum = (__force unsigned int)sum;
+ goto out;
+ }
+
+ csum = csum_partial_copy_generic((void __force *)src, dst,
+ len, sum, err_ptr, NULL);
+
+ if (unlikely(*err_ptr)) {
+ int missing = __copy_from_user(dst, src, len);
+
+ if (missing) {
+ memset(dst + len - missing, 0, missing);
+ *err_ptr = -EFAULT;
+ } else {
+ *err_ptr = 0;
+ }
+
+ csum = csum_partial(dst, len, sum);
+ }
+
+out:
+ return (__force __wsum)csum;
+}
+EXPORT_SYMBOL(csum_and_copy_from_user);
+
+__wsum csum_and_copy_to_user(const void *src, void __user *dst, int len,
+ __wsum sum, int *err_ptr)
+{
+ unsigned int csum;
+
+ might_sleep();
+
+ *err_ptr = 0;
+
+ if (!len) {
+ csum = 0;
+ goto out;
+ }
+
+ if (unlikely((len < 0) || !access_ok(VERIFY_WRITE, dst, len))) {
+ *err_ptr = -EFAULT;
+ csum = -1; /* invalid checksum */
+ goto out;
+ }
+
+ csum = csum_partial_copy_generic(src, (void __force *)dst,
+ len, sum, NULL, err_ptr);
+
+ if (unlikely(*err_ptr)) {
+ csum = csum_partial(src, len, sum);
+
+ if (copy_to_user(dst, src, len)) {
+ *err_ptr = -EFAULT;
+ csum = -1; /* invalid checksum */
+ }
+ }
+
+out:
+ return (__force __wsum)csum;
+}
+EXPORT_SYMBOL(csum_and_copy_to_user);
diff --git a/arch/powerpc/lib/copy_32.S b/arch/powerpc/lib/copy_32.S
index 74a7f4130b4c..55f19f9fd708 100644
--- a/arch/powerpc/lib/copy_32.S
+++ b/arch/powerpc/lib/copy_32.S
@@ -62,7 +62,7 @@
.text
.stabs "arch/powerpc/lib/",N_SO,0,0,0f
- .stabs "copy32.S",N_SO,0,0,0f
+ .stabs "copy_32.S",N_SO,0,0,0f
0:
CACHELINE_BYTES = L1_CACHE_BYTES
diff --git a/arch/powerpc/lib/ldstfp.S b/arch/powerpc/lib/ldstfp.S
index f6448636baf5..6a85380520b6 100644
--- a/arch/powerpc/lib/ldstfp.S
+++ b/arch/powerpc/lib/ldstfp.S
@@ -17,6 +17,8 @@
#include <asm/asm-offsets.h>
#include <linux/errno.h>
+#ifdef CONFIG_PPC_FPU
+
#define STKFRM (PPC_MIN_STKFRM + 16)
.macro extab instr,handler
@@ -81,7 +83,7 @@ _GLOBAL(do_lfs)
mfmsr r6
ori r7,r6,MSR_FP
cmpwi cr7,r3,0
- mtmsrd r7
+ MTMSRD(r7)
isync
beq cr7,1f
stfd fr0,STKFRM-16(r1)
@@ -93,7 +95,7 @@ _GLOBAL(do_lfs)
lfd fr0,STKFRM-16(r1)
4: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1)
mtlr r0
- mtmsrd r6
+ MTMSRD(r6)
isync
mr r3,r9
addi r1,r1,STKFRM
@@ -108,7 +110,7 @@ _GLOBAL(do_lfd)
mfmsr r6
ori r7,r6,MSR_FP
cmpwi cr7,r3,0
- mtmsrd r7
+ MTMSRD(r7)
isync
beq cr7,1f
stfd fr0,STKFRM-16(r1)
@@ -120,7 +122,7 @@ _GLOBAL(do_lfd)
lfd fr0,STKFRM-16(r1)
4: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1)
mtlr r0
- mtmsrd r6
+ MTMSRD(r6)
isync
mr r3,r9
addi r1,r1,STKFRM
@@ -135,7 +137,7 @@ _GLOBAL(do_stfs)
mfmsr r6
ori r7,r6,MSR_FP
cmpwi cr7,r3,0
- mtmsrd r7
+ MTMSRD(r7)
isync
beq cr7,1f
stfd fr0,STKFRM-16(r1)
@@ -147,7 +149,7 @@ _GLOBAL(do_stfs)
lfd fr0,STKFRM-16(r1)
4: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1)
mtlr r0
- mtmsrd r6
+ MTMSRD(r6)
isync
mr r3,r9
addi r1,r1,STKFRM
@@ -162,7 +164,7 @@ _GLOBAL(do_stfd)
mfmsr r6
ori r7,r6,MSR_FP
cmpwi cr7,r3,0
- mtmsrd r7
+ MTMSRD(r7)
isync
beq cr7,1f
stfd fr0,STKFRM-16(r1)
@@ -174,7 +176,7 @@ _GLOBAL(do_stfd)
lfd fr0,STKFRM-16(r1)
4: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1)
mtlr r0
- mtmsrd r6
+ MTMSRD(r6)
isync
mr r3,r9
addi r1,r1,STKFRM
@@ -229,7 +231,7 @@ _GLOBAL(do_lvx)
oris r7,r6,MSR_VEC@h
cmpwi cr7,r3,0
li r8,STKFRM-16
- mtmsrd r7
+ MTMSRD(r7)
isync
beq cr7,1f
stvx vr0,r1,r8
@@ -241,7 +243,7 @@ _GLOBAL(do_lvx)
lvx vr0,r1,r8
4: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1)
mtlr r0
- mtmsrd r6
+ MTMSRD(r6)
isync
mr r3,r9
addi r1,r1,STKFRM
@@ -257,7 +259,7 @@ _GLOBAL(do_stvx)
oris r7,r6,MSR_VEC@h
cmpwi cr7,r3,0
li r8,STKFRM-16
- mtmsrd r7
+ MTMSRD(r7)
isync
beq cr7,1f
stvx vr0,r1,r8
@@ -269,7 +271,7 @@ _GLOBAL(do_stvx)
lvx vr0,r1,r8
4: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1)
mtlr r0
- mtmsrd r6
+ MTMSRD(r6)
isync
mr r3,r9
addi r1,r1,STKFRM
@@ -325,7 +327,7 @@ _GLOBAL(do_lxvd2x)
oris r7,r6,MSR_VSX@h
cmpwi cr7,r3,0
li r8,STKFRM-16
- mtmsrd r7
+ MTMSRD(r7)
isync
beq cr7,1f
STXVD2X(0,r1,r8)
@@ -337,7 +339,7 @@ _GLOBAL(do_lxvd2x)
LXVD2X(0,r1,r8)
4: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1)
mtlr r0
- mtmsrd r6
+ MTMSRD(r6)
isync
mr r3,r9
addi r1,r1,STKFRM
@@ -353,7 +355,7 @@ _GLOBAL(do_stxvd2x)
oris r7,r6,MSR_VSX@h
cmpwi cr7,r3,0
li r8,STKFRM-16
- mtmsrd r7
+ MTMSRD(r7)
isync
beq cr7,1f
STXVD2X(0,r1,r8)
@@ -365,7 +367,7 @@ _GLOBAL(do_stxvd2x)
LXVD2X(0,r1,r8)
4: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1)
mtlr r0
- mtmsrd r6
+ MTMSRD(r6)
isync
mr r3,r9
addi r1,r1,STKFRM
@@ -373,3 +375,5 @@ _GLOBAL(do_stxvd2x)
extab 2b,3b
#endif /* CONFIG_VSX */
+
+#endif /* CONFIG_PPC_FPU */
diff --git a/arch/powerpc/lib/locks.c b/arch/powerpc/lib/locks.c
index 58e14fba11b1..9b8182e82166 100644
--- a/arch/powerpc/lib/locks.c
+++ b/arch/powerpc/lib/locks.c
@@ -34,7 +34,7 @@ void __spin_yield(arch_spinlock_t *lock)
return;
holder_cpu = lock_value & 0xffff;
BUG_ON(holder_cpu >= NR_CPUS);
- yield_count = lppaca[holder_cpu].yield_count;
+ yield_count = lppaca_of(holder_cpu).yield_count;
if ((yield_count & 1) == 0)
return; /* virtual cpu is currently running */
rmb();
@@ -65,7 +65,7 @@ void __rw_yield(arch_rwlock_t *rw)
return; /* no write lock at present */
holder_cpu = lock_value & 0xffff;
BUG_ON(holder_cpu >= NR_CPUS);
- yield_count = lppaca[holder_cpu].yield_count;
+ yield_count = lppaca_of(holder_cpu).yield_count;
if ((yield_count & 1) == 0)
return; /* virtual cpu is currently running */
rmb();
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index e0a9858d537e..ae5189ab0049 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -30,6 +30,7 @@ extern char system_call_common[];
#define XER_OV 0x40000000U
#define XER_CA 0x20000000U
+#ifdef CONFIG_PPC_FPU
/*
* Functions in ldstfp.S
*/
@@ -41,6 +42,7 @@ extern int do_lvx(int rn, unsigned long ea);
extern int do_stvx(int rn, unsigned long ea);
extern int do_lxvd2x(int rn, unsigned long ea);
extern int do_stxvd2x(int rn, unsigned long ea);
+#endif
/*
* Determine whether a conditional branch instruction would branch.
@@ -290,6 +292,7 @@ static int __kprobes write_mem(unsigned long val, unsigned long ea, int nb,
return write_mem_unaligned(val, ea, nb, regs);
}
+#ifdef CONFIG_PPC_FPU
/*
* Check the address and alignment, and call func to do the actual
* load or store.
@@ -351,6 +354,7 @@ static int __kprobes do_fp_store(int rn, int (*func)(int, unsigned long),
}
return err;
}
+#endif
#ifdef CONFIG_ALTIVEC
/* For Altivec/VMX, no need to worry about alignment */
@@ -1393,6 +1397,7 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
regs->gpr[rd] = byterev_4(val);
goto ldst_done;
+#ifdef CONFIG_PPC_CPU
case 535: /* lfsx */
case 567: /* lfsux */
if (!(regs->msr & MSR_FP))
@@ -1424,6 +1429,7 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
ea = xform_ea(instr, regs, u);
err = do_fp_store(rd, do_stfd, ea, 8, regs);
goto ldst_done;
+#endif
#ifdef __powerpc64__
case 660: /* stdbrx */
@@ -1534,6 +1540,7 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
} while (++rd < 32);
goto instr_done;
+#ifdef CONFIG_PPC_FPU
case 48: /* lfs */
case 49: /* lfsu */
if (!(regs->msr & MSR_FP))
@@ -1565,6 +1572,7 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
ea = dform_ea(instr, regs);
err = do_fp_store(rd, do_stfd, ea, 8, regs);
goto ldst_done;
+#endif
#ifdef __powerpc64__
case 58: /* ld[u], lwa */
diff --git a/arch/powerpc/math-emu/Makefile b/arch/powerpc/math-emu/Makefile
index 0c16ab947f1f..7d1dba0d57f9 100644
--- a/arch/powerpc/math-emu/Makefile
+++ b/arch/powerpc/math-emu/Makefile
@@ -15,4 +15,4 @@ obj-$(CONFIG_SPE) += math_efp.o
CFLAGS_fabs.o = -fno-builtin-fabs
CFLAGS_math.o = -fno-builtin-fabs
-EXTRA_CFLAGS = -I. -Iinclude/math-emu -w
+ccflags-y = -I. -Iinclude/math-emu -w
diff --git a/arch/powerpc/mm/40x_mmu.c b/arch/powerpc/mm/40x_mmu.c
index 1dc2fa5ce1bd..5810967511d4 100644
--- a/arch/powerpc/mm/40x_mmu.c
+++ b/arch/powerpc/mm/40x_mmu.c
@@ -35,6 +35,7 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/highmem.h>
+#include <linux/memblock.h>
#include <asm/pgalloc.h>
#include <asm/prom.h>
@@ -47,6 +48,7 @@
#include <asm/bootx.h>
#include <asm/machdep.h>
#include <asm/setup.h>
+
#include "mmu_decl.h"
extern int __map_without_ltlbs;
@@ -139,8 +141,19 @@ unsigned long __init mmu_mapin_ram(unsigned long top)
* coverage with normal-sized pages (or other reasons) do not
* attempt to allocate outside the allowed range.
*/
-
- __initial_memory_limit_addr = memstart_addr + mapped;
+ memblock_set_current_limit(mapped);
return mapped;
}
+
+void setup_initial_memory_limit(phys_addr_t first_memblock_base,
+ phys_addr_t first_memblock_size)
+{
+ /* We don't currently support the first MEMBLOCK not mapping 0
+ * physical on those processors
+ */
+ BUG_ON(first_memblock_base != 0);
+
+ /* 40x can only access 16MB at the moment (see head_40x.S) */
+ memblock_set_current_limit(min_t(u64, first_memblock_size, 0x00800000));
+}
diff --git a/arch/powerpc/mm/44x_mmu.c b/arch/powerpc/mm/44x_mmu.c
index d8c6efb32bc6..024acab588fd 100644
--- a/arch/powerpc/mm/44x_mmu.c
+++ b/arch/powerpc/mm/44x_mmu.c
@@ -24,6 +24,8 @@
*/
#include <linux/init.h>
+#include <linux/memblock.h>
+
#include <asm/mmu.h>
#include <asm/system.h>
#include <asm/page.h>
@@ -213,6 +215,18 @@ unsigned long __init mmu_mapin_ram(unsigned long top)
return total_lowmem;
}
+void setup_initial_memory_limit(phys_addr_t first_memblock_base,
+ phys_addr_t first_memblock_size)
+{
+ /* We don't currently support the first MEMBLOCK not mapping 0
+ * physical on those processors
+ */
+ BUG_ON(first_memblock_base != 0);
+
+ /* 44x has a 256M TLB entry pinned at boot */
+ memblock_set_current_limit(min_t(u64, first_memblock_size, PPC_PIN_SIZE));
+}
+
#ifdef CONFIG_SMP
void __cpuinit mmu_init_secondary(int cpu)
{
diff --git a/arch/powerpc/mm/Makefile b/arch/powerpc/mm/Makefile
index ce68708bbad5..bdca46e08382 100644
--- a/arch/powerpc/mm/Makefile
+++ b/arch/powerpc/mm/Makefile
@@ -4,9 +4,7 @@
subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
-ifeq ($(CONFIG_PPC64),y)
-EXTRA_CFLAGS += -mno-minimal-toc
-endif
+ccflags-$(CONFIG_PPC64) := -mno-minimal-toc
obj-y := fault.o mem.o pgtable.o gup.o \
init_$(CONFIG_WORD_SIZE).o \
@@ -25,7 +23,7 @@ obj-$(CONFIG_PPC_STD_MMU) += hash_low_$(CONFIG_WORD_SIZE).o \
mmu_context_hash$(CONFIG_WORD_SIZE).o
obj-$(CONFIG_40x) += 40x_mmu.o
obj-$(CONFIG_44x) += 44x_mmu.o
-obj-$(CONFIG_FSL_BOOKE) += fsl_booke_mmu.o
+obj-$(CONFIG_PPC_FSL_BOOK3E) += fsl_booke_mmu.o
obj-$(CONFIG_NEED_MULTIPLE_NODES) += numa.o
obj-$(CONFIG_PPC_MM_SLICES) += slice.o
ifeq ($(CONFIG_HUGETLB_PAGE),y)
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index 1bd712c33ce2..54f4fb994e99 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -30,6 +30,7 @@
#include <linux/kprobes.h>
#include <linux/kdebug.h>
#include <linux/perf_event.h>
+#include <linux/magic.h>
#include <asm/firmware.h>
#include <asm/page.h>
@@ -385,6 +386,7 @@ do_sigbus:
void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)
{
const struct exception_table_entry *entry;
+ unsigned long *stackend;
/* Are we prepared to handle this fault? */
if ((entry = search_exception_tables(regs->nip)) != NULL) {
@@ -413,5 +415,9 @@ void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)
printk(KERN_ALERT "Faulting instruction address: 0x%08lx\n",
regs->nip);
+ stackend = end_of_stack(current);
+ if (current != &init_task && *stackend != STACK_END_MAGIC)
+ printk(KERN_ALERT "Thread overran stack, or stack corrupted\n");
+
die("Kernel access of bad area", regs, sig);
}
diff --git a/arch/powerpc/mm/fsl_booke_mmu.c b/arch/powerpc/mm/fsl_booke_mmu.c
index 4b66a1ece6d8..f7802c8bba0a 100644
--- a/arch/powerpc/mm/fsl_booke_mmu.c
+++ b/arch/powerpc/mm/fsl_booke_mmu.c
@@ -40,6 +40,7 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/highmem.h>
+#include <linux/memblock.h>
#include <asm/pgalloc.h>
#include <asm/prom.h>
@@ -56,11 +57,6 @@
unsigned int tlbcam_index;
-
-#if defined(CONFIG_LOWMEM_CAM_NUM_BOOL) && (CONFIG_LOWMEM_CAM_NUM >= NUM_TLBCAMS)
-#error "LOWMEM_CAM_NUM must be less than NUM_TLBCAMS"
-#endif
-
#define NUM_TLBCAMS (64)
struct tlbcam TLBCAM[NUM_TLBCAMS];
@@ -137,7 +133,8 @@ static void settlbcam(int index, unsigned long virt, phys_addr_t phys,
if (mmu_has_feature(MMU_FTR_BIG_PHYS))
TLBCAM[index].MAS7 = (u64)phys >> 32;
- if (flags & _PAGE_USER) {
+ /* Below is unlikely -- only for large user pages or similar */
+ if (pte_user(flags)) {
TLBCAM[index].MAS3 |= MAS3_UX | MAS3_UR;
TLBCAM[index].MAS3 |= ((flags & _PAGE_RW) ? MAS3_UW : 0);
}
@@ -184,6 +181,12 @@ unsigned long map_mem_in_cams(unsigned long ram, int max_cam_idx)
return amount_mapped;
}
+#ifdef CONFIG_PPC32
+
+#if defined(CONFIG_LOWMEM_CAM_NUM_BOOL) && (CONFIG_LOWMEM_CAM_NUM >= NUM_TLBCAMS)
+#error "LOWMEM_CAM_NUM must be less than NUM_TLBCAMS"
+#endif
+
unsigned long __init mmu_mapin_ram(unsigned long top)
{
return tlbcam_addrs[tlbcam_index - 1].limit - PAGE_OFFSET + 1;
@@ -213,5 +216,15 @@ void __init adjust_total_lowmem(void)
pr_cont("%lu Mb, residual: %dMb\n", tlbcam_sz(tlbcam_index - 1) >> 20,
(unsigned int)((total_lowmem - __max_low_memory) >> 20));
- __initial_memory_limit_addr = memstart_addr + __max_low_memory;
+ memblock_set_current_limit(memstart_addr + __max_low_memory);
}
+
+void setup_initial_memory_limit(phys_addr_t first_memblock_base,
+ phys_addr_t first_memblock_size)
+{
+ phys_addr_t limit = first_memblock_base + first_memblock_size;
+
+ /* 64M mapped initially according to head_fsl_booke.S */
+ memblock_set_current_limit(min_t(u64, limit, 0x04000000));
+}
+#endif
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index 09dffe6efa46..83f534d862db 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -588,7 +588,7 @@ static void __init htab_initialize(void)
unsigned long pteg_count;
unsigned long prot;
unsigned long base = 0, size = 0, limit;
- int i;
+ struct memblock_region *reg;
DBG(" -> htab_initialize()\n");
@@ -625,7 +625,7 @@ static void __init htab_initialize(void)
if (machine_is(cell))
limit = 0x80000000;
else
- limit = 0;
+ limit = MEMBLOCK_ALLOC_ANYWHERE;
table = memblock_alloc_base(htab_size_bytes, htab_size_bytes, limit);
@@ -649,7 +649,7 @@ static void __init htab_initialize(void)
#ifdef CONFIG_DEBUG_PAGEALLOC
linear_map_hash_count = memblock_end_of_DRAM() >> PAGE_SHIFT;
linear_map_hash_slots = __va(memblock_alloc_base(linear_map_hash_count,
- 1, memblock.rmo_size));
+ 1, ppc64_rma_size));
memset(linear_map_hash_slots, 0, linear_map_hash_count);
#endif /* CONFIG_DEBUG_PAGEALLOC */
@@ -659,9 +659,9 @@ static void __init htab_initialize(void)
*/
/* create bolted the linear mapping in the hash table */
- for (i=0; i < memblock.memory.cnt; i++) {
- base = (unsigned long)__va(memblock.memory.region[i].base);
- size = memblock.memory.region[i].size;
+ for_each_memblock(memory, reg) {
+ base = (unsigned long)__va(reg->base);
+ size = reg->size;
DBG("creating mapping for region: %lx..%lx (prot: %lx)\n",
base, size, prot);
@@ -696,7 +696,8 @@ static void __init htab_initialize(void)
#endif /* CONFIG_U3_DART */
BUG_ON(htab_bolt_mapping(base, base + size, __pa(base),
prot, mmu_linear_psize, mmu_kernel_ssize));
- }
+ }
+ memblock_set_current_limit(MEMBLOCK_ALLOC_ANYWHERE);
/*
* If we have a memory_limit and we've allocated TCEs then we need to
@@ -1247,3 +1248,23 @@ void kernel_map_pages(struct page *page, int numpages, int enable)
local_irq_restore(flags);
}
#endif /* CONFIG_DEBUG_PAGEALLOC */
+
+void setup_initial_memory_limit(phys_addr_t first_memblock_base,
+ phys_addr_t first_memblock_size)
+{
+ /* We don't currently support the first MEMBLOCK not mapping 0
+ * physical on those processors
+ */
+ BUG_ON(first_memblock_base != 0);
+
+ /* On LPAR systems, the first entry is our RMA region,
+ * non-LPAR 64-bit hash MMU systems don't have a limitation
+ * on real mode access, but using the first entry works well
+ * enough. We also clamp it to 1G to avoid some funky things
+ * such as RTAS bugs etc...
+ */
+ ppc64_rma_size = min_t(u64, first_memblock_size, 0x40000000);
+
+ /* Finally limit subsequent allocations */
+ memblock_set_current_limit(ppc64_rma_size);
+}
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c
index 6a6975dc2654..742da43b4ab6 100644
--- a/arch/powerpc/mm/init_32.c
+++ b/arch/powerpc/mm/init_32.c
@@ -92,12 +92,6 @@ int __allow_ioremap_reserved;
unsigned long __max_low_memory = MAX_LOW_MEM;
/*
- * address of the limit of what is accessible with initial MMU setup -
- * 256MB usually, but only 16MB on 601.
- */
-phys_addr_t __initial_memory_limit_addr = (phys_addr_t)0x10000000;
-
-/*
* Check for command-line options that affect what MMU_init will do.
*/
void MMU_setup(void)
@@ -126,13 +120,6 @@ void __init MMU_init(void)
if (ppc_md.progress)
ppc_md.progress("MMU:enter", 0x111);
- /* 601 can only access 16MB at the moment */
- if (PVR_VER(mfspr(SPRN_PVR)) == 1)
- __initial_memory_limit_addr = 0x01000000;
- /* 8xx can only access 8MB at the moment */
- if (PVR_VER(mfspr(SPRN_PVR)) == 0x50)
- __initial_memory_limit_addr = 0x00800000;
-
/* parse args from command line */
MMU_setup();
@@ -190,20 +177,18 @@ void __init MMU_init(void)
#ifdef CONFIG_BOOTX_TEXT
btext_unmap();
#endif
+
+ /* Shortly after that, the entire linear mapping will be available */
+ memblock_set_current_limit(lowmem_end_addr);
}
/* This is only called until mem_init is done. */
void __init *early_get_page(void)
{
- void *p;
-
- if (init_bootmem_done) {
- p = alloc_bootmem_pages(PAGE_SIZE);
- } else {
- p = __va(memblock_alloc_base(PAGE_SIZE, PAGE_SIZE,
- __initial_memory_limit_addr));
- }
- return p;
+ if (init_bootmem_done)
+ return alloc_bootmem_pages(PAGE_SIZE);
+ else
+ return __va(memblock_alloc(PAGE_SIZE, PAGE_SIZE));
}
/* Free up now-unused memory */
@@ -252,3 +237,17 @@ void free_initrd_mem(unsigned long start, unsigned long end)
}
#endif
+
+#ifdef CONFIG_8xx /* No 8xx specific .c file to put that in ... */
+void setup_initial_memory_limit(phys_addr_t first_memblock_base,
+ phys_addr_t first_memblock_size)
+{
+ /* We don't currently support the first MEMBLOCK not mapping 0
+ * physical on those processors
+ */
+ BUG_ON(first_memblock_base != 0);
+
+ /* 8xx can only access 8MB at the moment */
+ memblock_set_current_limit(min_t(u64, first_memblock_size, 0x00800000));
+}
+#endif /* CONFIG_8xx */
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c
index ace85fa74b29..6374b2196a17 100644
--- a/arch/powerpc/mm/init_64.c
+++ b/arch/powerpc/mm/init_64.c
@@ -330,3 +330,4 @@ int __meminit vmemmap_populate(struct page *start_page,
return 0;
}
#endif /* CONFIG_SPARSEMEM_VMEMMAP */
+
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index 1a84a8d00005..a66499650909 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -82,18 +82,11 @@ int page_is_ram(unsigned long pfn)
return pfn < max_pfn;
#else
unsigned long paddr = (pfn << PAGE_SHIFT);
- int i;
- for (i=0; i < memblock.memory.cnt; i++) {
- unsigned long base;
+ struct memblock_region *reg;
- base = memblock.memory.region[i].base;
-
- if ((paddr >= base) &&
- (paddr < (base + memblock.memory.region[i].size))) {
+ for_each_memblock(memory, reg)
+ if (paddr >= reg->base && paddr < (reg->base + reg->size))
return 1;
- }
- }
-
return 0;
#endif
}
@@ -149,23 +142,19 @@ int
walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages,
void *arg, int (*func)(unsigned long, unsigned long, void *))
{
- struct memblock_property res;
- unsigned long pfn, len;
- u64 end;
+ struct memblock_region *reg;
+ unsigned long end_pfn = start_pfn + nr_pages;
+ unsigned long tstart, tend;
int ret = -1;
- res.base = (u64) start_pfn << PAGE_SHIFT;
- res.size = (u64) nr_pages << PAGE_SHIFT;
-
- end = res.base + res.size - 1;
- while ((res.base < end) && (memblock_find(&res) >= 0)) {
- pfn = (unsigned long)(res.base >> PAGE_SHIFT);
- len = (unsigned long)(res.size >> PAGE_SHIFT);
- ret = (*func)(pfn, len, arg);
+ for_each_memblock(memory, reg) {
+ tstart = max(start_pfn, memblock_region_memory_base_pfn(reg));
+ tend = min(end_pfn, memblock_region_memory_end_pfn(reg));
+ if (tstart >= tend)
+ continue;
+ ret = (*func)(tstart, tend - tstart, arg);
if (ret)
break;
- res.base += (res.size + 1);
- res.size = (end - res.base + 1);
}
return ret;
}
@@ -179,9 +168,9 @@ EXPORT_SYMBOL_GPL(walk_system_ram_range);
#ifndef CONFIG_NEED_MULTIPLE_NODES
void __init do_init_bootmem(void)
{
- unsigned long i;
unsigned long start, bootmap_pages;
unsigned long total_pages;
+ struct memblock_region *reg;
int boot_mapsize;
max_low_pfn = max_pfn = memblock_end_of_DRAM() >> PAGE_SHIFT;
@@ -204,10 +193,10 @@ void __init do_init_bootmem(void)
boot_mapsize = init_bootmem_node(NODE_DATA(0), start >> PAGE_SHIFT, min_low_pfn, max_low_pfn);
/* Add active regions with valid PFNs */
- for (i = 0; i < memblock.memory.cnt; i++) {
+ for_each_memblock(memory, reg) {
unsigned long start_pfn, end_pfn;
- start_pfn = memblock.memory.region[i].base >> PAGE_SHIFT;
- end_pfn = start_pfn + memblock_size_pages(&memblock.memory, i);
+ start_pfn = memblock_region_memory_base_pfn(reg);
+ end_pfn = memblock_region_memory_end_pfn(reg);
add_active_range(0, start_pfn, end_pfn);
}
@@ -218,29 +207,21 @@ void __init do_init_bootmem(void)
free_bootmem_with_active_regions(0, lowmem_end_addr >> PAGE_SHIFT);
/* reserve the sections we're already using */
- for (i = 0; i < memblock.reserved.cnt; i++) {
- unsigned long addr = memblock.reserved.region[i].base +
- memblock_size_bytes(&memblock.reserved, i) - 1;
- if (addr < lowmem_end_addr)
- reserve_bootmem(memblock.reserved.region[i].base,
- memblock_size_bytes(&memblock.reserved, i),
- BOOTMEM_DEFAULT);
- else if (memblock.reserved.region[i].base < lowmem_end_addr) {
- unsigned long adjusted_size = lowmem_end_addr -
- memblock.reserved.region[i].base;
- reserve_bootmem(memblock.reserved.region[i].base,
- adjusted_size, BOOTMEM_DEFAULT);
+ for_each_memblock(reserved, reg) {
+ unsigned long top = reg->base + reg->size - 1;
+ if (top < lowmem_end_addr)
+ reserve_bootmem(reg->base, reg->size, BOOTMEM_DEFAULT);
+ else if (reg->base < lowmem_end_addr) {
+ unsigned long trunc_size = lowmem_end_addr - reg->base;
+ reserve_bootmem(reg->base, trunc_size, BOOTMEM_DEFAULT);
}
}
#else
free_bootmem_with_active_regions(0, max_pfn);
/* reserve the sections we're already using */
- for (i = 0; i < memblock.reserved.cnt; i++)
- reserve_bootmem(memblock.reserved.region[i].base,
- memblock_size_bytes(&memblock.reserved, i),
- BOOTMEM_DEFAULT);
-
+ for_each_memblock(reserved, reg)
+ reserve_bootmem(reg->base, reg->size, BOOTMEM_DEFAULT);
#endif
/* XXX need to clip this if using highmem? */
sparse_memory_present_with_active_regions(0);
@@ -251,22 +232,15 @@ void __init do_init_bootmem(void)
/* mark pages that don't exist as nosave */
static int __init mark_nonram_nosave(void)
{
- unsigned long memblock_next_region_start_pfn,
- memblock_region_max_pfn;
- int i;
-
- for (i = 0; i < memblock.memory.cnt - 1; i++) {
- memblock_region_max_pfn =
- (memblock.memory.region[i].base >> PAGE_SHIFT) +
- (memblock.memory.region[i].size >> PAGE_SHIFT);
- memblock_next_region_start_pfn =
- memblock.memory.region[i+1].base >> PAGE_SHIFT;
-
- if (memblock_region_max_pfn < memblock_next_region_start_pfn)
- register_nosave_region(memblock_region_max_pfn,
- memblock_next_region_start_pfn);
+ struct memblock_region *reg, *prev = NULL;
+
+ for_each_memblock(memory, reg) {
+ if (prev &&
+ memblock_region_memory_end_pfn(prev) < memblock_region_memory_base_pfn(reg))
+ register_nosave_region(memblock_region_memory_end_pfn(prev),
+ memblock_region_memory_base_pfn(reg));
+ prev = reg;
}
-
return 0;
}
@@ -327,7 +301,7 @@ void __init mem_init(void)
swiotlb_init(1);
#endif
- num_physpages = memblock.memory.size >> PAGE_SHIFT;
+ num_physpages = memblock_phys_mem_size() >> PAGE_SHIFT;
high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);
#ifdef CONFIG_NEED_MULTIPLE_NODES
diff --git a/arch/powerpc/mm/mmu_context_nohash.c b/arch/powerpc/mm/mmu_context_nohash.c
index ddfd7ad4e1d6..5ce99848d91e 100644
--- a/arch/powerpc/mm/mmu_context_nohash.c
+++ b/arch/powerpc/mm/mmu_context_nohash.c
@@ -334,7 +334,7 @@ static int __cpuinit mmu_context_cpu_notify(struct notifier_block *self,
/* We don't touch CPU 0 map, it's allocated at aboot and kept
* around forever
*/
- if (cpu == 0)
+ if (cpu == boot_cpuid)
return NOTIFY_OK;
switch (action) {
@@ -420,9 +420,11 @@ void __init mmu_context_init(void)
*/
context_map = alloc_bootmem(CTX_MAP_SIZE);
context_mm = alloc_bootmem(sizeof(void *) * (last_context + 1));
+#ifndef CONFIG_SMP
stale_map[0] = alloc_bootmem(CTX_MAP_SIZE);
+#else
+ stale_map[boot_cpuid] = alloc_bootmem(CTX_MAP_SIZE);
-#ifdef CONFIG_SMP
register_cpu_notifier(&mmu_context_cpu_nb);
#endif
diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h
index 63b84a0d3b10..dd0a2589591d 100644
--- a/arch/powerpc/mm/mmu_decl.h
+++ b/arch/powerpc/mm/mmu_decl.h
@@ -140,10 +140,13 @@ extern void wii_memory_fixups(void);
extern void MMU_init_hw(void);
extern unsigned long mmu_mapin_ram(unsigned long top);
-#elif defined(CONFIG_FSL_BOOKE)
+#elif defined(CONFIG_PPC_FSL_BOOK3E)
+extern unsigned long map_mem_in_cams(unsigned long ram, int max_cam_idx);
+#ifdef CONFIG_PPC32
extern void MMU_init_hw(void);
extern unsigned long mmu_mapin_ram(unsigned long top);
extern void adjust_total_lowmem(void);
+#endif
extern void loadcam_entry(unsigned int index);
struct tlbcam {
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index 002878ccf90b..74505b245374 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -802,16 +802,17 @@ static void __init setup_nonnuma(void)
unsigned long top_of_ram = memblock_end_of_DRAM();
unsigned long total_ram = memblock_phys_mem_size();
unsigned long start_pfn, end_pfn;
- unsigned int i, nid = 0;
+ unsigned int nid = 0;
+ struct memblock_region *reg;
printk(KERN_DEBUG "Top of RAM: 0x%lx, Total RAM: 0x%lx\n",
top_of_ram, total_ram);
printk(KERN_DEBUG "Memory hole size: %ldMB\n",
(top_of_ram - total_ram) >> 20);
- for (i = 0; i < memblock.memory.cnt; ++i) {
- start_pfn = memblock.memory.region[i].base >> PAGE_SHIFT;
- end_pfn = start_pfn + memblock_size_pages(&memblock.memory, i);
+ for_each_memblock(memory, reg) {
+ start_pfn = memblock_region_memory_base_pfn(reg);
+ end_pfn = memblock_region_memory_end_pfn(reg);
fake_numa_create_new_node(end_pfn, &nid);
add_active_range(nid, start_pfn, end_pfn);
@@ -947,11 +948,11 @@ static struct notifier_block __cpuinitdata ppc64_numa_nb = {
static void mark_reserved_regions_for_nid(int nid)
{
struct pglist_data *node = NODE_DATA(nid);
- int i;
+ struct memblock_region *reg;
- for (i = 0; i < memblock.reserved.cnt; i++) {
- unsigned long physbase = memblock.reserved.region[i].base;
- unsigned long size = memblock.reserved.region[i].size;
+ for_each_memblock(reserved, reg) {
+ unsigned long physbase = reg->base;
+ unsigned long size = reg->size;
unsigned long start_pfn = physbase >> PAGE_SHIFT;
unsigned long end_pfn = PFN_UP(physbase + size);
struct node_active_region node_ar;
diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c
index f8a01829d64f..11571e118831 100644
--- a/arch/powerpc/mm/ppc_mmu_32.c
+++ b/arch/powerpc/mm/ppc_mmu_32.c
@@ -223,8 +223,7 @@ void __init MMU_init_hw(void)
* Find some memory for the hash table.
*/
if ( ppc_md.progress ) ppc_md.progress("hash:find piece", 0x322);
- Hash = __va(memblock_alloc_base(Hash_size, Hash_size,
- __initial_memory_limit_addr));
+ Hash = __va(memblock_alloc(Hash_size, Hash_size));
cacheable_memzero(Hash, Hash_size);
_SDR1 = __pa(Hash) | SDR1_LOW_BITS;
@@ -272,3 +271,18 @@ void __init MMU_init_hw(void)
if ( ppc_md.progress ) ppc_md.progress("hash:done", 0x205);
}
+
+void setup_initial_memory_limit(phys_addr_t first_memblock_base,
+ phys_addr_t first_memblock_size)
+{
+ /* We don't currently support the first MEMBLOCK not mapping 0
+ * physical on those processors
+ */
+ BUG_ON(first_memblock_base != 0);
+
+ /* 601 can only access 16MB at the moment */
+ if (PVR_VER(mfspr(SPRN_PVR)) == 1)
+ memblock_set_current_limit(min_t(u64, first_memblock_size, 0x01000000));
+ else /* Anything else has 256M mapped */
+ memblock_set_current_limit(min_t(u64, first_memblock_size, 0x10000000));
+}
diff --git a/arch/powerpc/mm/tlb_nohash.c b/arch/powerpc/mm/tlb_nohash.c
index fe391e942521..36c0c449a899 100644
--- a/arch/powerpc/mm/tlb_nohash.c
+++ b/arch/powerpc/mm/tlb_nohash.c
@@ -349,11 +349,47 @@ void tlb_flush_pgtable(struct mmu_gather *tlb, unsigned long address)
static void setup_page_sizes(void)
{
- unsigned int tlb0cfg = mfspr(SPRN_TLB0CFG);
- unsigned int tlb0ps = mfspr(SPRN_TLB0PS);
- unsigned int eptcfg = mfspr(SPRN_EPTCFG);
+ unsigned int tlb0cfg;
+ unsigned int tlb0ps;
+ unsigned int eptcfg;
int i, psize;
+#ifdef CONFIG_PPC_FSL_BOOK3E
+ unsigned int mmucfg = mfspr(SPRN_MMUCFG);
+
+ if (((mmucfg & MMUCFG_MAVN) == MMUCFG_MAVN_V1) &&
+ (mmu_has_feature(MMU_FTR_TYPE_FSL_E))) {
+ unsigned int tlb1cfg = mfspr(SPRN_TLB1CFG);
+ unsigned int min_pg, max_pg;
+
+ min_pg = (tlb1cfg & TLBnCFG_MINSIZE) >> TLBnCFG_MINSIZE_SHIFT;
+ max_pg = (tlb1cfg & TLBnCFG_MAXSIZE) >> TLBnCFG_MAXSIZE_SHIFT;
+
+ for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) {
+ struct mmu_psize_def *def;
+ unsigned int shift;
+
+ def = &mmu_psize_defs[psize];
+ shift = def->shift;
+
+ if (shift == 0)
+ continue;
+
+ /* adjust to be in terms of 4^shift Kb */
+ shift = (shift - 10) >> 1;
+
+ if ((shift >= min_pg) && (shift <= max_pg))
+ def->flags |= MMU_PAGE_SIZE_DIRECT;
+ }
+
+ goto no_indirect;
+ }
+#endif
+
+ tlb0cfg = mfspr(SPRN_TLB0CFG);
+ tlb0ps = mfspr(SPRN_TLB0PS);
+ eptcfg = mfspr(SPRN_EPTCFG);
+
/* Look for supported direct sizes */
for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) {
struct mmu_psize_def *def = &mmu_psize_defs[psize];
@@ -505,10 +541,26 @@ static void __early_init_mmu(int boot_cpu)
*/
linear_map_top = memblock_end_of_DRAM();
+#ifdef CONFIG_PPC_FSL_BOOK3E
+ if (mmu_has_feature(MMU_FTR_TYPE_FSL_E)) {
+ unsigned int num_cams;
+
+ /* use a quarter of the TLBCAM for bolted linear map */
+ num_cams = (mfspr(SPRN_TLB1CFG) & TLBnCFG_N_ENTRY) / 4;
+ linear_map_top = map_mem_in_cams(linear_map_top, num_cams);
+
+ /* limit memory so we dont have linear faults */
+ memblock_enforce_memory_limit(linear_map_top);
+ memblock_analyze();
+ }
+#endif
+
/* A sync won't hurt us after mucking around with
* the MMU configuration
*/
mb();
+
+ memblock_set_current_limit(linear_map_top);
}
void __init early_init_mmu(void)
@@ -521,4 +573,18 @@ void __cpuinit early_init_mmu_secondary(void)
__early_init_mmu(0);
}
+void setup_initial_memory_limit(phys_addr_t first_memblock_base,
+ phys_addr_t first_memblock_size)
+{
+ /* On Embedded 64-bit, we adjust the RMA size to match
+ * the bolted TLB entry. We know for now that only 1G
+ * entries are supported though that may eventually
+ * change. We crop it to the size of the first MEMBLOCK to
+ * avoid going over total available memory just in case...
+ */
+ ppc64_rma_size = min_t(u64, first_memblock_size, 0x40000000);
+
+ /* Finally limit subsequent allocations */
+ memblock_set_current_limit(ppc64_memblock_base + ppc64_rma_size);
+}
#endif /* CONFIG_PPC64 */
diff --git a/arch/powerpc/mm/tlb_nohash_low.S b/arch/powerpc/mm/tlb_nohash_low.S
index b9d9fed8f36e..af405eefe48d 100644
--- a/arch/powerpc/mm/tlb_nohash_low.S
+++ b/arch/powerpc/mm/tlb_nohash_low.S
@@ -367,7 +367,7 @@ _GLOBAL(set_context)
#error Unsupported processor type !
#endif
-#if defined(CONFIG_FSL_BOOKE)
+#if defined(CONFIG_PPC_FSL_BOOK3E)
/*
* extern void loadcam_entry(unsigned int index)
*
diff --git a/arch/powerpc/oprofile/Makefile b/arch/powerpc/oprofile/Makefile
index e219ca43962d..73456c4cec28 100644
--- a/arch/powerpc/oprofile/Makefile
+++ b/arch/powerpc/oprofile/Makefile
@@ -1,8 +1,6 @@
subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
-ifeq ($(CONFIG_PPC64),y)
-EXTRA_CFLAGS += -mno-minimal-toc
-endif
+ccflags-$(CONFIG_PPC64) := -mno-minimal-toc
obj-$(CONFIG_OPROFILE) += oprofile.o
diff --git a/arch/powerpc/oprofile/backtrace.c b/arch/powerpc/oprofile/backtrace.c
index b4278cfd1f80..f75301f2c85f 100644
--- a/arch/powerpc/oprofile/backtrace.c
+++ b/arch/powerpc/oprofile/backtrace.c
@@ -105,7 +105,7 @@ void op_powerpc_backtrace(struct pt_regs * const regs, unsigned int depth)
}
} else {
#ifdef CONFIG_PPC64
- if (!test_thread_flag(TIF_32BIT)) {
+ if (!is_32bit_task()) {
while (depth--) {
sp = user_getsp64(sp, first_frame);
if (!sp)
diff --git a/arch/powerpc/oprofile/op_model_fsl_emb.c b/arch/powerpc/oprofile/op_model_fsl_emb.c
index 62312abffa28..d4e6507277b5 100644
--- a/arch/powerpc/oprofile/op_model_fsl_emb.c
+++ b/arch/powerpc/oprofile/op_model_fsl_emb.c
@@ -2,7 +2,7 @@
* Freescale Embedded oprofile support, based on ppc64 oprofile support
* Copyright (C) 2004 Anton Blanchard <anton@au.ibm.com>, IBM
*
- * Copyright (c) 2004 Freescale Semiconductor, Inc
+ * Copyright (c) 2004, 2010 Freescale Semiconductor, Inc
*
* Author: Andy Fleming
* Maintainer: Kumar Gala <galak@kernel.crashing.org>
@@ -321,9 +321,6 @@ static void fsl_emb_handle_interrupt(struct pt_regs *regs,
int val;
int i;
- /* set the PMM bit (see comment below) */
- mtmsr(mfmsr() | MSR_PMM);
-
pc = regs->nip;
is_kernel = is_kernel_addr(pc);
@@ -340,9 +337,13 @@ static void fsl_emb_handle_interrupt(struct pt_regs *regs,
}
/* The freeze bit was set by the interrupt. */
- /* Clear the freeze bit, and reenable the interrupt.
- * The counters won't actually start until the rfi clears
- * the PMM bit */
+ /* Clear the freeze bit, and reenable the interrupt. The
+ * counters won't actually start until the rfi clears the PMM
+ * bit. The PMM bit should not be set until after the interrupt
+ * is cleared to avoid it getting lost in some hypervisor
+ * environments.
+ */
+ mtmsr(mfmsr() | MSR_PMM);
pmc_start_ctrs(1);
}
diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig
index 69d668c072ae..0f979c5c756b 100644
--- a/arch/powerpc/platforms/44x/Kconfig
+++ b/arch/powerpc/platforms/44x/Kconfig
@@ -17,6 +17,16 @@ config BAMBOO
help
This option enables support for the IBM PPC440EP evaluation board.
+config BLUESTONE
+ bool "Bluestone"
+ depends on 44x
+ default n
+ select PPC44x_SIMPLE
+ select APM821xx
+ select IBM_NEW_EMAC_RGMII
+ help
+ This option enables support for the APM APM821xx Evaluation board.
+
config EBONY
bool "Ebony"
depends on 44x
@@ -293,6 +303,12 @@ config 460SX
select IBM_NEW_EMAC_ZMII
select IBM_NEW_EMAC_TAH
+config APM821xx
+ bool
+ select PPC_FPU
+ select IBM_NEW_EMAC_EMAC4
+ select IBM_NEW_EMAC_TAH
+
# 44x errata/workaround config symbols, selected by the CPU models above
config IBM440EP_ERR42
bool
diff --git a/arch/powerpc/platforms/44x/ppc44x_simple.c b/arch/powerpc/platforms/44x/ppc44x_simple.c
index 5f7a29d7f590..7ddcba3b9397 100644
--- a/arch/powerpc/platforms/44x/ppc44x_simple.c
+++ b/arch/powerpc/platforms/44x/ppc44x_simple.c
@@ -52,6 +52,7 @@ machine_device_initcall(ppc44x_simple, ppc44x_device_probe);
static char *board[] __initdata = {
"amcc,arches",
"amcc,bamboo",
+ "amcc,bluestone",
"amcc,canyonlands",
"amcc,glacier",
"ibm,ebony",
diff --git a/arch/powerpc/platforms/512x/clock.c b/arch/powerpc/platforms/512x/clock.c
index 5b243bd3eb3b..3dc2a8d262b8 100644
--- a/arch/powerpc/platforms/512x/clock.c
+++ b/arch/powerpc/platforms/512x/clock.c
@@ -57,7 +57,7 @@ static struct clk *mpc5121_clk_get(struct device *dev, const char *id)
int id_match = 0;
if (dev == NULL || id == NULL)
- return NULL;
+ return clk;
mutex_lock(&clocks_mutex);
list_for_each_entry(p, &clocks, node) {
diff --git a/arch/powerpc/platforms/52xx/efika.c b/arch/powerpc/platforms/52xx/efika.c
index 45c0cb9b67e6..18c104820198 100644
--- a/arch/powerpc/platforms/52xx/efika.c
+++ b/arch/powerpc/platforms/52xx/efika.c
@@ -99,7 +99,7 @@ static void __init efika_pcisetup(void)
if (bus_range == NULL || len < 2 * sizeof(int)) {
printk(KERN_WARNING EFIKA_PLATFORM_NAME
": Can't get bus-range for %s\n", pcictrl->full_name);
- return;
+ goto out_put;
}
if (bus_range[1] == bus_range[0])
@@ -111,12 +111,12 @@ static void __init efika_pcisetup(void)
printk(" controlled by %s\n", pcictrl->full_name);
printk("\n");
- hose = pcibios_alloc_controller(of_node_get(pcictrl));
+ hose = pcibios_alloc_controller(pcictrl);
if (!hose) {
printk(KERN_WARNING EFIKA_PLATFORM_NAME
": Can't allocate PCI controller structure for %s\n",
pcictrl->full_name);
- return;
+ goto out_put;
}
hose->first_busno = bus_range[0];
@@ -124,6 +124,9 @@ static void __init efika_pcisetup(void)
hose->ops = &rtas_pci_ops;
pci_process_bridge_OF_ranges(hose, pcictrl, 0);
+ return;
+out_put:
+ of_node_put(pcictrl);
}
#else
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_common.c b/arch/powerpc/platforms/52xx/mpc52xx_common.c
index 6e905314ad5d..41f3a7eda1de 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_common.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_common.c
@@ -325,12 +325,16 @@ int mpc5200_psc_ac97_gpio_reset(int psc_number)
clrbits32(&simple_gpio->simple_dvo, sync | out);
clrbits8(&wkup_gpio->wkup_dvo, reset);
- /* wait at lease 1 us */
- udelay(2);
+ /* wait for 1 us */
+ udelay(1);
/* Deassert reset */
setbits8(&wkup_gpio->wkup_dvo, reset);
+ /* wait at least 200ns */
+ /* 7 ~= (200ns * timebase) / ns2sec */
+ __delay(7);
+
/* Restore pin-muxing */
out_be32(&simple_gpio->port_config, mux);
diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig
index 021763a32c2f..73f4135f3a1a 100644
--- a/arch/powerpc/platforms/83xx/Kconfig
+++ b/arch/powerpc/platforms/83xx/Kconfig
@@ -10,12 +10,12 @@ menuconfig PPC_83xx
if PPC_83xx
config MPC830x_RDB
- bool "Freescale MPC830x RDB"
+ bool "Freescale MPC830x RDB and derivatives"
select DEFAULT_UIMAGE
select PPC_MPC831x
select FSL_GTM
help
- This option enables support for the MPC8308 RDB board.
+ This option enables support for the MPC8308 RDB and MPC8308 P1M boards.
config MPC831x_RDB
bool "Freescale MPC831x RDB"
diff --git a/arch/powerpc/platforms/83xx/mpc830x_rdb.c b/arch/powerpc/platforms/83xx/mpc830x_rdb.c
index ac102ee9abe8..846831d495b5 100644
--- a/arch/powerpc/platforms/83xx/mpc830x_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc830x_rdb.c
@@ -65,7 +65,8 @@ static int __init mpc830x_rdb_probe(void)
unsigned long root = of_get_flat_dt_root();
return of_flat_dt_is_compatible(root, "MPC8308RDB") ||
- of_flat_dt_is_compatible(root, "fsl,mpc8308rdb");
+ of_flat_dt_is_compatible(root, "fsl,mpc8308rdb") ||
+ of_flat_dt_is_compatible(root, "denx,mpc8308_p1m");
}
static struct of_device_id __initdata of_bus_ids[] = {
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
index bea1f5905ad4..b6976e1726e4 100644
--- a/arch/powerpc/platforms/85xx/Kconfig
+++ b/arch/powerpc/platforms/85xx/Kconfig
@@ -11,6 +11,8 @@ menuconfig FSL_SOC_BOOKE
if FSL_SOC_BOOKE
+if PPC32
+
config MPC8540_ADS
bool "Freescale MPC8540 ADS"
select DEFAULT_UIMAGE
@@ -153,10 +155,20 @@ config SBC8560
help
This option enables support for the Wind River SBC8560 board
+config P3041_DS
+ bool "Freescale P3041 DS"
+ select DEFAULT_UIMAGE
+ select PPC_E500MC
+ select PHYS_64BIT
+ select SWIOTLB
+ select MPC8xxx_GPIO
+ select HAS_RAPIDIO
+ help
+ This option enables support for the P3041 DS board
+
config P4080_DS
bool "Freescale P4080 DS"
select DEFAULT_UIMAGE
- select PPC_FSL_BOOK3E
select PPC_E500MC
select PHYS_64BIT
select SWIOTLB
@@ -165,6 +177,20 @@ config P4080_DS
help
This option enables support for the P4080 DS board
+endif # PPC32
+
+config P5020_DS
+ bool "Freescale P5020 DS"
+ select DEFAULT_UIMAGE
+ select E500
+ select PPC_E500MC
+ select PHYS_64BIT
+ select SWIOTLB
+ select MPC8xxx_GPIO
+ select HAS_RAPIDIO
+ help
+ This option enables support for the P5020 DS board
+
endif # FSL_SOC_BOOKE
config TQM85xx
diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile
index a2ec3f8f4d06..dd70db77d63e 100644
--- a/arch/powerpc/platforms/85xx/Makefile
+++ b/arch/powerpc/platforms/85xx/Makefile
@@ -11,7 +11,9 @@ obj-$(CONFIG_MPC85xx_DS) += mpc85xx_ds.o
obj-$(CONFIG_MPC85xx_MDS) += mpc85xx_mds.o
obj-$(CONFIG_MPC85xx_RDB) += mpc85xx_rdb.o
obj-$(CONFIG_P1022_DS) += p1022_ds.o
+obj-$(CONFIG_P3041_DS) += p3041_ds.o corenet_ds.o
obj-$(CONFIG_P4080_DS) += p4080_ds.o corenet_ds.o
+obj-$(CONFIG_P5020_DS) += p5020_ds.o corenet_ds.o
obj-$(CONFIG_STX_GP3) += stx_gp3.o
obj-$(CONFIG_TQM85xx) += tqm85xx.o
obj-$(CONFIG_SBC8560) += sbc8560.o
diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c
index 34e00902ce86..2b390d19a1d1 100644
--- a/arch/powerpc/platforms/85xx/p1022_ds.c
+++ b/arch/powerpc/platforms/85xx/p1022_ds.c
@@ -112,6 +112,8 @@ static struct of_device_id __initdata p1022_ds_ids[] = {
{ .compatible = "soc", },
{ .compatible = "simple-bus", },
{ .compatible = "gianfar", },
+ /* So that the DMA channel nodes can be probed individually: */
+ { .compatible = "fsl,eloplus-dma", },
{},
};
diff --git a/arch/powerpc/platforms/85xx/p3041_ds.c b/arch/powerpc/platforms/85xx/p3041_ds.c
new file mode 100644
index 000000000000..0ed52e18298c
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/p3041_ds.c
@@ -0,0 +1,64 @@
+/*
+ * P3041 DS Setup
+ *
+ * Maintained by Kumar Gala (see MAINTAINERS for contact information)
+ *
+ * Copyright 2009-2010 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 <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/phy.h>
+
+#include <asm/system.h>
+#include <asm/time.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <mm/mmu_decl.h>
+#include <asm/prom.h>
+#include <asm/udbg.h>
+#include <asm/mpic.h>
+
+#include <linux/of_platform.h>
+#include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
+
+#include "corenet_ds.h"
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init p3041_ds_probe(void)
+{
+ unsigned long root = of_get_flat_dt_root();
+
+ return of_flat_dt_is_compatible(root, "fsl,P3041DS");
+}
+
+define_machine(p3041_ds) {
+ .name = "P3041 DS",
+ .probe = p3041_ds_probe,
+ .setup_arch = corenet_ds_setup_arch,
+ .init_IRQ = corenet_ds_pic_init,
+#ifdef CONFIG_PCI
+ .pcibios_fixup_bus = fsl_pcibios_fixup_bus,
+#endif
+ .get_irq = mpic_get_coreint_irq,
+ .restart = fsl_rstcr_restart,
+ .calibrate_decr = generic_calibrate_decr,
+ .progress = udbg_progress,
+};
+
+machine_device_initcall(p3041_ds, corenet_ds_publish_devices);
+
+#ifdef CONFIG_SWIOTLB
+machine_arch_initcall(p3041_ds, swiotlb_setup_bus_notifier);
+#endif
diff --git a/arch/powerpc/platforms/85xx/p5020_ds.c b/arch/powerpc/platforms/85xx/p5020_ds.c
new file mode 100644
index 000000000000..7467b712ee00
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/p5020_ds.c
@@ -0,0 +1,69 @@
+/*
+ * P5020 DS Setup
+ *
+ * Maintained by Kumar Gala (see MAINTAINERS for contact information)
+ *
+ * Copyright 2009-2010 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 <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/phy.h>
+
+#include <asm/system.h>
+#include <asm/time.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <mm/mmu_decl.h>
+#include <asm/prom.h>
+#include <asm/udbg.h>
+#include <asm/mpic.h>
+
+#include <linux/of_platform.h>
+#include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
+
+#include "corenet_ds.h"
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init p5020_ds_probe(void)
+{
+ unsigned long root = of_get_flat_dt_root();
+
+ return of_flat_dt_is_compatible(root, "fsl,P5020DS");
+}
+
+define_machine(p5020_ds) {
+ .name = "P5020 DS",
+ .probe = p5020_ds_probe,
+ .setup_arch = corenet_ds_setup_arch,
+ .init_IRQ = corenet_ds_pic_init,
+#ifdef CONFIG_PCI
+ .pcibios_fixup_bus = fsl_pcibios_fixup_bus,
+#endif
+/* coreint doesn't play nice with lazy EE, use legacy mpic for now */
+#ifdef CONFIG_PPC64
+ .get_irq = mpic_get_irq,
+#else
+ .get_irq = mpic_get_coreint_irq,
+#endif
+ .restart = fsl_rstcr_restart,
+ .calibrate_decr = generic_calibrate_decr,
+ .progress = udbg_progress,
+};
+
+machine_device_initcall(p5020_ds, corenet_ds_publish_devices);
+
+#ifdef CONFIG_SWIOTLB
+machine_arch_initcall(p5020_ds, swiotlb_setup_bus_notifier);
+#endif
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
index a6b106557be4..5c91a992f02b 100644
--- a/arch/powerpc/platforms/85xx/smp.c
+++ b/arch/powerpc/platforms/85xx/smp.c
@@ -16,6 +16,7 @@
#include <linux/delay.h>
#include <linux/of.h>
#include <linux/kexec.h>
+#include <linux/highmem.h>
#include <asm/machdep.h>
#include <asm/pgtable.h>
@@ -79,6 +80,7 @@ smp_85xx_kick_cpu(int nr)
local_irq_save(flags);
out_be32(bptr_vaddr + BOOT_ENTRY_PIR, nr);
+#ifdef CONFIG_PPC32
out_be32(bptr_vaddr + BOOT_ENTRY_ADDR_LOWER, __pa(__early_start));
if (!ioremappable)
@@ -88,6 +90,12 @@ smp_85xx_kick_cpu(int nr)
/* Wait a bit for the CPU to ack. */
while ((__secondary_hold_acknowledge != nr) && (++n < 1000))
mdelay(1);
+#else
+ out_be64((u64 *)(bptr_vaddr + BOOT_ENTRY_ADDR_UPPER),
+ __pa((u64)*((unsigned long long *) generic_secondary_smp_init)));
+
+ smp_generic_kick_cpu(nr);
+#endif
local_irq_restore(flags);
@@ -114,19 +122,15 @@ struct smp_ops_t smp_85xx_ops = {
};
#ifdef CONFIG_KEXEC
-static int kexec_down_cpus = 0;
+atomic_t kexec_down_cpus = ATOMIC_INIT(0);
void mpc85xx_smp_kexec_cpu_down(int crash_shutdown, int secondary)
{
- mpic_teardown_this_cpu(1);
-
- /* When crashing, this gets called on all CPU's we only
- * take down the non-boot cpus */
- if (smp_processor_id() != boot_cpuid)
- {
- local_irq_disable();
- kexec_down_cpus++;
+ local_irq_disable();
+ if (secondary) {
+ atomic_inc(&kexec_down_cpus);
+ /* loop forever */
while (1);
}
}
@@ -137,16 +141,65 @@ static void mpc85xx_smp_kexec_down(void *arg)
ppc_md.kexec_cpu_down(0,1);
}
-static void mpc85xx_smp_machine_kexec(struct kimage *image)
+static void map_and_flush(unsigned long paddr)
{
- int timeout = 2000;
+ struct page *page = pfn_to_page(paddr >> PAGE_SHIFT);
+ unsigned long kaddr = (unsigned long)kmap(page);
+
+ flush_dcache_range(kaddr, kaddr + PAGE_SIZE);
+ kunmap(page);
+}
+
+/**
+ * Before we reset the other cores, we need to flush relevant cache
+ * out to memory so we don't get anything corrupted, some of these flushes
+ * are performed out of an overabundance of caution as interrupts are not
+ * disabled yet and we can switch cores
+ */
+static void mpc85xx_smp_flush_dcache_kexec(struct kimage *image)
+{
+ kimage_entry_t *ptr, entry;
+ unsigned long paddr;
int i;
- set_cpus_allowed(current, cpumask_of_cpu(boot_cpuid));
+ if (image->type == KEXEC_TYPE_DEFAULT) {
+ /* normal kexec images are stored in temporary pages */
+ for (ptr = &image->head; (entry = *ptr) && !(entry & IND_DONE);
+ ptr = (entry & IND_INDIRECTION) ?
+ phys_to_virt(entry & PAGE_MASK) : ptr + 1) {
+ if (!(entry & IND_DESTINATION)) {
+ map_and_flush(entry);
+ }
+ }
+ /* flush out last IND_DONE page */
+ map_and_flush(entry);
+ } else {
+ /* crash type kexec images are copied to the crash region */
+ for (i = 0; i < image->nr_segments; i++) {
+ struct kexec_segment *seg = &image->segment[i];
+ for (paddr = seg->mem; paddr < seg->mem + seg->memsz;
+ paddr += PAGE_SIZE) {
+ map_and_flush(paddr);
+ }
+ }
+ }
+
+ /* also flush the kimage struct to be passed in as well */
+ flush_dcache_range((unsigned long)image,
+ (unsigned long)image + sizeof(*image));
+}
+
+static void mpc85xx_smp_machine_kexec(struct kimage *image)
+{
+ int timeout = INT_MAX;
+ int i, num_cpus = num_present_cpus();
+
+ mpc85xx_smp_flush_dcache_kexec(image);
- smp_call_function(mpc85xx_smp_kexec_down, NULL, 0);
+ if (image->type == KEXEC_TYPE_DEFAULT)
+ smp_call_function(mpc85xx_smp_kexec_down, NULL, 0);
- while ( (kexec_down_cpus != (num_online_cpus() - 1)) &&
+ while ( (atomic_read(&kexec_down_cpus) != (num_cpus - 1)) &&
( timeout > 0 ) )
{
timeout--;
@@ -155,7 +208,7 @@ static void mpc85xx_smp_machine_kexec(struct kimage *image)
if ( !timeout )
printk(KERN_ERR "Unable to bring down secondary cpu(s)");
- for (i = 0; i < num_present_cpus(); i++)
+ for (i = 0; i < num_cpus; i++)
{
if ( i == smp_processor_id() ) continue;
mpic_reset_core(i);
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
index d361f8119b1e..111138c55f9c 100644
--- a/arch/powerpc/platforms/Kconfig.cputype
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -125,6 +125,7 @@ config 8xx
config E500
select FSL_EMB_PERFMON
+ select PPC_FSL_BOOK3E
bool
config PPC_E500MC
@@ -166,9 +167,14 @@ config BOOKE
config FSL_BOOKE
bool
- depends on E200 || E500
+ depends on (E200 || E500) && PPC32
default y
+# this is for common code between PPC32 & PPC64 FSL BOOKE
+config PPC_FSL_BOOK3E
+ bool
+ select FSL_EMB_PERFMON
+ default y if FSL_BOOKE
config PTE_64BIT
bool
diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c
index 97085530aa63..e3e379c6caa7 100644
--- a/arch/powerpc/platforms/cell/axon_msi.c
+++ b/arch/powerpc/platforms/cell/axon_msi.c
@@ -310,9 +310,9 @@ static void axon_msi_teardown_msi_irqs(struct pci_dev *dev)
}
static struct irq_chip msic_irq_chip = {
- .mask = mask_msi_irq,
- .unmask = unmask_msi_irq,
- .shutdown = unmask_msi_irq,
+ .irq_mask = mask_msi_irq,
+ .irq_unmask = unmask_msi_irq,
+ .irq_shutdown = mask_msi_irq,
.name = "AXON-MSI",
};
diff --git a/arch/powerpc/platforms/cell/ras.c b/arch/powerpc/platforms/cell/ras.c
index 1d3c4effea10..5ec1e47a0d77 100644
--- a/arch/powerpc/platforms/cell/ras.c
+++ b/arch/powerpc/platforms/cell/ras.c
@@ -173,8 +173,10 @@ static int __init cbe_ptcal_enable(void)
return -ENODEV;
size = of_get_property(np, "ibm,cbe-ptcal-size", NULL);
- if (!size)
+ if (!size) {
+ of_node_put(np);
return -ENODEV;
+ }
pr_debug("%s: enabling PTCAL, size = 0x%x\n", __func__, *size);
order = get_order(*size);
diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c
index 5876e888e412..3f2e557344a3 100644
--- a/arch/powerpc/platforms/cell/spider-pic.c
+++ b/arch/powerpc/platforms/cell/spider-pic.c
@@ -258,8 +258,10 @@ static unsigned int __init spider_find_cascade_and_node(struct spider_pic *pic)
return NO_IRQ;
imap += intsize + 1;
tmp = of_get_property(iic, "#interrupt-cells", NULL);
- if (tmp == NULL)
+ if (tmp == NULL) {
+ of_node_put(iic);
return NO_IRQ;
+ }
intsize = *tmp;
/* Assume unit is last entry of interrupt specifier */
unit = imap[intsize - 1];
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index 1a40da92154c..02f7b113a31b 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -154,6 +154,7 @@ static const struct file_operations __fops = { \
.release = spufs_attr_release, \
.read = spufs_attr_read, \
.write = spufs_attr_write, \
+ .llseek = generic_file_llseek, \
};
@@ -521,6 +522,7 @@ static const struct file_operations spufs_cntl_fops = {
.release = spufs_cntl_release,
.read = simple_attr_read,
.write = simple_attr_write,
+ .llseek = generic_file_llseek,
.mmap = spufs_cntl_mmap,
};
@@ -714,6 +716,7 @@ static ssize_t spufs_mbox_read(struct file *file, char __user *buf,
static const struct file_operations spufs_mbox_fops = {
.open = spufs_pipe_open,
.read = spufs_mbox_read,
+ .llseek = no_llseek,
};
static ssize_t spufs_mbox_stat_read(struct file *file, char __user *buf,
@@ -743,6 +746,7 @@ static ssize_t spufs_mbox_stat_read(struct file *file, char __user *buf,
static const struct file_operations spufs_mbox_stat_fops = {
.open = spufs_pipe_open,
.read = spufs_mbox_stat_read,
+ .llseek = no_llseek,
};
/* low-level ibox access function */
@@ -863,6 +867,7 @@ static const struct file_operations spufs_ibox_fops = {
.read = spufs_ibox_read,
.poll = spufs_ibox_poll,
.fasync = spufs_ibox_fasync,
+ .llseek = no_llseek,
};
static ssize_t spufs_ibox_stat_read(struct file *file, char __user *buf,
@@ -890,6 +895,7 @@ static ssize_t spufs_ibox_stat_read(struct file *file, char __user *buf,
static const struct file_operations spufs_ibox_stat_fops = {
.open = spufs_pipe_open,
.read = spufs_ibox_stat_read,
+ .llseek = no_llseek,
};
/* low-level mailbox write */
@@ -1011,6 +1017,7 @@ static const struct file_operations spufs_wbox_fops = {
.write = spufs_wbox_write,
.poll = spufs_wbox_poll,
.fasync = spufs_wbox_fasync,
+ .llseek = no_llseek,
};
static ssize_t spufs_wbox_stat_read(struct file *file, char __user *buf,
@@ -1038,6 +1045,7 @@ static ssize_t spufs_wbox_stat_read(struct file *file, char __user *buf,
static const struct file_operations spufs_wbox_stat_fops = {
.open = spufs_pipe_open,
.read = spufs_wbox_stat_read,
+ .llseek = no_llseek,
};
static int spufs_signal1_open(struct inode *inode, struct file *file)
@@ -1166,6 +1174,7 @@ static const struct file_operations spufs_signal1_fops = {
.read = spufs_signal1_read,
.write = spufs_signal1_write,
.mmap = spufs_signal1_mmap,
+ .llseek = no_llseek,
};
static const struct file_operations spufs_signal1_nosched_fops = {
@@ -1173,6 +1182,7 @@ static const struct file_operations spufs_signal1_nosched_fops = {
.release = spufs_signal1_release,
.write = spufs_signal1_write,
.mmap = spufs_signal1_mmap,
+ .llseek = no_llseek,
};
static int spufs_signal2_open(struct inode *inode, struct file *file)
@@ -1305,6 +1315,7 @@ static const struct file_operations spufs_signal2_fops = {
.read = spufs_signal2_read,
.write = spufs_signal2_write,
.mmap = spufs_signal2_mmap,
+ .llseek = no_llseek,
};
static const struct file_operations spufs_signal2_nosched_fops = {
@@ -1312,6 +1323,7 @@ static const struct file_operations spufs_signal2_nosched_fops = {
.release = spufs_signal2_release,
.write = spufs_signal2_write,
.mmap = spufs_signal2_mmap,
+ .llseek = no_llseek,
};
/*
@@ -1451,6 +1463,7 @@ static const struct file_operations spufs_mss_fops = {
.open = spufs_mss_open,
.release = spufs_mss_release,
.mmap = spufs_mss_mmap,
+ .llseek = no_llseek,
};
static int
@@ -1508,6 +1521,7 @@ static const struct file_operations spufs_psmap_fops = {
.open = spufs_psmap_open,
.release = spufs_psmap_release,
.mmap = spufs_psmap_mmap,
+ .llseek = no_llseek,
};
@@ -1871,6 +1885,7 @@ static const struct file_operations spufs_mfc_fops = {
.fsync = spufs_mfc_fsync,
.fasync = spufs_mfc_fasync,
.mmap = spufs_mfc_mmap,
+ .llseek = no_llseek,
};
static int spufs_npc_set(void *data, u64 val)
@@ -2246,6 +2261,7 @@ static ssize_t spufs_dma_info_read(struct file *file, char __user *buf,
static const struct file_operations spufs_dma_info_fops = {
.open = spufs_info_open,
.read = spufs_dma_info_read,
+ .llseek = no_llseek,
};
static ssize_t __spufs_proxydma_info_read(struct spu_context *ctx,
@@ -2299,6 +2315,7 @@ static ssize_t spufs_proxydma_info_read(struct file *file, char __user *buf,
static const struct file_operations spufs_proxydma_info_fops = {
.open = spufs_info_open,
.read = spufs_proxydma_info_read,
+ .llseek = no_llseek,
};
static int spufs_show_tid(struct seq_file *s, void *private)
@@ -2585,6 +2602,7 @@ static const struct file_operations spufs_switch_log_fops = {
.read = spufs_switch_log_read,
.poll = spufs_switch_log_poll,
.release = spufs_switch_log_release,
+ .llseek = no_llseek,
};
/**
diff --git a/arch/powerpc/platforms/chrp/nvram.c b/arch/powerpc/platforms/chrp/nvram.c
index ba3588f2d8e0..d3ceff04ffc7 100644
--- a/arch/powerpc/platforms/chrp/nvram.c
+++ b/arch/powerpc/platforms/chrp/nvram.c
@@ -74,8 +74,10 @@ void __init chrp_nvram_init(void)
return;
nbytes_p = of_get_property(nvram, "#bytes", &proplen);
- if (nbytes_p == NULL || proplen != sizeof(unsigned int))
+ if (nbytes_p == NULL || proplen != sizeof(unsigned int)) {
+ of_node_put(nvram);
return;
+ }
nvram_size = *nbytes_p;
diff --git a/arch/powerpc/platforms/embedded6xx/wii.c b/arch/powerpc/platforms/embedded6xx/wii.c
index 5cdcc7c8d973..649473a729b8 100644
--- a/arch/powerpc/platforms/embedded6xx/wii.c
+++ b/arch/powerpc/platforms/embedded6xx/wii.c
@@ -65,7 +65,7 @@ static int __init page_aligned(unsigned long x)
void __init wii_memory_fixups(void)
{
- struct memblock_property *p = memblock.memory.region;
+ struct memblock_region *p = memblock.memory.regions;
/*
* This is part of a workaround to allow the use of two
diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile
index ce014928d460..a7602b11ed9d 100644
--- a/arch/powerpc/platforms/iseries/Makefile
+++ b/arch/powerpc/platforms/iseries/Makefile
@@ -1,4 +1,4 @@
-EXTRA_CFLAGS += -mno-minimal-toc
+ccflags-y := -mno-minimal-toc
obj-y += exception.o
obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o dt.o mf.o lpevents.o \
diff --git a/arch/powerpc/platforms/iseries/dt.c b/arch/powerpc/platforms/iseries/dt.c
index 7f45a51fe793..fdb7384c0c4f 100644
--- a/arch/powerpc/platforms/iseries/dt.c
+++ b/arch/powerpc/platforms/iseries/dt.c
@@ -243,7 +243,7 @@ static void __init dt_cpus(struct iseries_flat_dt *dt)
pft_size[1] = __ilog2(HvCallHpt_getHptPages() * HW_PAGE_SIZE);
for (i = 0; i < NR_CPUS; i++) {
- if (lppaca[i].dyn_proc_status >= 2)
+ if (lppaca_of(i).dyn_proc_status >= 2)
continue;
snprintf(p, 32 - (p - buf), "@%d", i);
@@ -251,7 +251,7 @@ static void __init dt_cpus(struct iseries_flat_dt *dt)
dt_prop_str(dt, "device_type", device_type_cpu);
- index = lppaca[i].dyn_hv_phys_proc_index;
+ index = lppaca_of(i).dyn_hv_phys_proc_index;
d = &xIoHriProcessorVpd[index];
dt_prop_u32(dt, "i-cache-size", d->xInstCacheSize * 1024);
diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c
index 33e5fc7334fc..42d0a886de05 100644
--- a/arch/powerpc/platforms/iseries/mf.c
+++ b/arch/powerpc/platforms/iseries/mf.c
@@ -1249,6 +1249,7 @@ out:
static const struct file_operations proc_vmlinux_operations = {
.write = proc_mf_change_vmlinux,
+ .llseek = default_llseek,
};
static int __init mf_proc_init(void)
diff --git a/arch/powerpc/platforms/iseries/smp.c b/arch/powerpc/platforms/iseries/smp.c
index 6590850045af..6c6029914dbc 100644
--- a/arch/powerpc/platforms/iseries/smp.c
+++ b/arch/powerpc/platforms/iseries/smp.c
@@ -91,7 +91,7 @@ static void smp_iSeries_kick_cpu(int nr)
BUG_ON((nr < 0) || (nr >= NR_CPUS));
/* Verify that our partition has a processor nr */
- if (lppaca[nr].dyn_proc_status >= 2)
+ if (lppaca_of(nr).dyn_proc_status >= 2)
return;
/* The processor is currently spinning, waiting
diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c
index 3fff8d979b41..fe34c3d9bb74 100644
--- a/arch/powerpc/platforms/maple/setup.c
+++ b/arch/powerpc/platforms/maple/setup.c
@@ -358,6 +358,7 @@ static int __init maple_cpc925_edac_setup(void)
model = (const unsigned char *)of_get_property(np, "model", NULL);
if (!model) {
printk(KERN_ERR "%s: Unabel to get model info\n", __func__);
+ of_node_put(np);
return -ENODEV;
}
diff --git a/arch/powerpc/platforms/powermac/pfunc_core.c b/arch/powerpc/platforms/powermac/pfunc_core.c
index cec635942657..b0c3777528a1 100644
--- a/arch/powerpc/platforms/powermac/pfunc_core.c
+++ b/arch/powerpc/platforms/powermac/pfunc_core.c
@@ -837,8 +837,10 @@ struct pmf_function *__pmf_find_function(struct device_node *target,
return NULL;
find_it:
dev = pmf_find_device(actor);
- if (dev == NULL)
- return NULL;
+ if (dev == NULL) {
+ result = NULL;
+ goto out;
+ }
list_for_each_entry(func, &dev->functions, link) {
if (name && strcmp(name, func->name))
@@ -850,8 +852,9 @@ struct pmf_function *__pmf_find_function(struct device_node *target,
result = func;
break;
}
- of_node_put(actor);
pmf_put_device(dev);
+out:
+ of_node_put(actor);
return result;
}
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile
index 046ace9c4381..59eb8bdaa79d 100644
--- a/arch/powerpc/platforms/pseries/Makefile
+++ b/arch/powerpc/platforms/pseries/Makefile
@@ -1,14 +1,9 @@
-ifeq ($(CONFIG_PPC64),y)
-EXTRA_CFLAGS += -mno-minimal-toc
-endif
-
-ifeq ($(CONFIG_PPC_PSERIES_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
+ccflags-$(CONFIG_PPC64) := -mno-minimal-toc
+ccflags-$(CONFIG_PPC_PSERIES_DEBUG) += -DDEBUG
obj-y := lpar.o hvCall.o nvram.o reconfig.o \
setup.o iommu.o event_sources.o ras.o \
- firmware.o power.o dlpar.o
+ firmware.o power.o dlpar.o mobility.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_XICS) += xics.o
obj-$(CONFIG_SCANLOG) += scanlog.o
@@ -23,7 +18,7 @@ obj-$(CONFIG_MEMORY_HOTPLUG) += hotplug-memory.o
obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o
obj-$(CONFIG_HVCS) += hvcserver.o
obj-$(CONFIG_HCALL_STATS) += hvCall_inst.o
-obj-$(CONFIG_PHYP_DUMP) += phyp_dump.o
+obj-$(CONFIG_PHYP_DUMP) += phyp_dump.o
obj-$(CONFIG_CMM) += cmm.o
obj-$(CONFIG_DTL) += dtl.o
diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c
index 72d8054fa739..b74a9230edc9 100644
--- a/arch/powerpc/platforms/pseries/dlpar.c
+++ b/arch/powerpc/platforms/pseries/dlpar.c
@@ -33,7 +33,7 @@ struct cc_workarea {
u32 prop_offset;
};
-static void dlpar_free_cc_property(struct property *prop)
+void dlpar_free_cc_property(struct property *prop)
{
kfree(prop->name);
kfree(prop->value);
@@ -55,13 +55,12 @@ static struct property *dlpar_parse_cc_property(struct cc_workarea *ccwa)
prop->length = ccwa->prop_length;
value = (char *)ccwa + ccwa->prop_offset;
- prop->value = kzalloc(prop->length, GFP_KERNEL);
+ prop->value = kmemdup(value, prop->length, GFP_KERNEL);
if (!prop->value) {
dlpar_free_cc_property(prop);
return NULL;
}
- memcpy(prop->value, value, prop->length);
return prop;
}
@@ -102,7 +101,7 @@ static void dlpar_free_one_cc_node(struct device_node *dn)
kfree(dn);
}
-static void dlpar_free_cc_nodes(struct device_node *dn)
+void dlpar_free_cc_nodes(struct device_node *dn)
{
if (dn->child)
dlpar_free_cc_nodes(dn->child);
diff --git a/arch/powerpc/platforms/pseries/dtl.c b/arch/powerpc/platforms/pseries/dtl.c
index a00addb55945..c371bc06434b 100644
--- a/arch/powerpc/platforms/pseries/dtl.c
+++ b/arch/powerpc/platforms/pseries/dtl.c
@@ -23,37 +23,22 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/debugfs.h>
+#include <linux/spinlock.h>
#include <asm/smp.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/firmware.h>
+#include <asm/lppaca.h>
#include "plpar_wrappers.h"
-/*
- * Layout of entries in the hypervisor's DTL buffer. Although we don't
- * actually access the internals of an entry (we only need to know the size),
- * we might as well define it here for reference.
- */
-struct dtl_entry {
- u8 dispatch_reason;
- u8 preempt_reason;
- u16 processor_id;
- u32 enqueue_to_dispatch_time;
- u32 ready_to_enqueue_time;
- u32 waiting_to_ready_time;
- u64 timebase;
- u64 fault_addr;
- u64 srr0;
- u64 srr1;
-};
-
struct dtl {
struct dtl_entry *buf;
struct dentry *file;
int cpu;
int buf_entries;
u64 last_idx;
+ spinlock_t lock;
};
static DEFINE_PER_CPU(struct dtl, cpu_dtl);
@@ -72,25 +57,97 @@ static u8 dtl_event_mask = 0x7;
static int dtl_buf_entries = (16 * 85);
-static int dtl_enable(struct dtl *dtl)
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+struct dtl_ring {
+ u64 write_index;
+ struct dtl_entry *write_ptr;
+ struct dtl_entry *buf;
+ struct dtl_entry *buf_end;
+ u8 saved_dtl_mask;
+};
+
+static DEFINE_PER_CPU(struct dtl_ring, dtl_rings);
+
+static atomic_t dtl_count;
+
+/*
+ * The cpu accounting code controls the DTL ring buffer, and we get
+ * given entries as they are processed.
+ */
+static void consume_dtle(struct dtl_entry *dtle, u64 index)
{
- unsigned long addr;
- int ret, hwcpu;
+ struct dtl_ring *dtlr = &__get_cpu_var(dtl_rings);
+ struct dtl_entry *wp = dtlr->write_ptr;
+ struct lppaca *vpa = local_paca->lppaca_ptr;
- /* only allow one reader */
- if (dtl->buf)
- return -EBUSY;
+ if (!wp)
+ return;
- /* we need to store the original allocation size for use during read */
- dtl->buf_entries = dtl_buf_entries;
+ *wp = *dtle;
+ barrier();
- dtl->buf = kmalloc_node(dtl->buf_entries * sizeof(struct dtl_entry),
- GFP_KERNEL, cpu_to_node(dtl->cpu));
- if (!dtl->buf) {
- printk(KERN_WARNING "%s: buffer alloc failed for cpu %d\n",
- __func__, dtl->cpu);
- return -ENOMEM;
- }
+ /* check for hypervisor ring buffer overflow, ignore this entry if so */
+ if (index + N_DISPATCH_LOG < vpa->dtl_idx)
+ return;
+
+ ++wp;
+ if (wp == dtlr->buf_end)
+ wp = dtlr->buf;
+ dtlr->write_ptr = wp;
+
+ /* incrementing write_index makes the new entry visible */
+ smp_wmb();
+ ++dtlr->write_index;
+}
+
+static int dtl_start(struct dtl *dtl)
+{
+ struct dtl_ring *dtlr = &per_cpu(dtl_rings, dtl->cpu);
+
+ dtlr->buf = dtl->buf;
+ dtlr->buf_end = dtl->buf + dtl->buf_entries;
+ dtlr->write_index = 0;
+
+ /* setting write_ptr enables logging into our buffer */
+ smp_wmb();
+ dtlr->write_ptr = dtl->buf;
+
+ /* enable event logging */
+ dtlr->saved_dtl_mask = lppaca_of(dtl->cpu).dtl_enable_mask;
+ lppaca_of(dtl->cpu).dtl_enable_mask |= dtl_event_mask;
+
+ dtl_consumer = consume_dtle;
+ atomic_inc(&dtl_count);
+ return 0;
+}
+
+static void dtl_stop(struct dtl *dtl)
+{
+ struct dtl_ring *dtlr = &per_cpu(dtl_rings, dtl->cpu);
+
+ dtlr->write_ptr = NULL;
+ smp_wmb();
+
+ dtlr->buf = NULL;
+
+ /* restore dtl_enable_mask */
+ lppaca_of(dtl->cpu).dtl_enable_mask = dtlr->saved_dtl_mask;
+
+ if (atomic_dec_and_test(&dtl_count))
+ dtl_consumer = NULL;
+}
+
+static u64 dtl_current_index(struct dtl *dtl)
+{
+ return per_cpu(dtl_rings, dtl->cpu).write_index;
+}
+
+#else /* CONFIG_VIRT_CPU_ACCOUNTING */
+
+static int dtl_start(struct dtl *dtl)
+{
+ unsigned long addr;
+ int ret, hwcpu;
/* Register our dtl buffer with the hypervisor. The HV expects the
* buffer size to be passed in the second word of the buffer */
@@ -102,34 +159,82 @@ static int dtl_enable(struct dtl *dtl)
if (ret) {
printk(KERN_WARNING "%s: DTL registration for cpu %d (hw %d) "
"failed with %d\n", __func__, dtl->cpu, hwcpu, ret);
- kfree(dtl->buf);
return -EIO;
}
/* set our initial buffer indices */
- dtl->last_idx = lppaca[dtl->cpu].dtl_idx = 0;
+ lppaca_of(dtl->cpu).dtl_idx = 0;
/* ensure that our updates to the lppaca fields have occurred before
* we actually enable the logging */
smp_wmb();
/* enable event logging */
- lppaca[dtl->cpu].dtl_enable_mask = dtl_event_mask;
+ lppaca_of(dtl->cpu).dtl_enable_mask = dtl_event_mask;
return 0;
}
-static void dtl_disable(struct dtl *dtl)
+static void dtl_stop(struct dtl *dtl)
{
int hwcpu = get_hard_smp_processor_id(dtl->cpu);
- lppaca[dtl->cpu].dtl_enable_mask = 0x0;
+ lppaca_of(dtl->cpu).dtl_enable_mask = 0x0;
unregister_dtl(hwcpu, __pa(dtl->buf));
+}
+
+static u64 dtl_current_index(struct dtl *dtl)
+{
+ return lppaca_of(dtl->cpu).dtl_idx;
+}
+#endif /* CONFIG_VIRT_CPU_ACCOUNTING */
+
+static int dtl_enable(struct dtl *dtl)
+{
+ long int n_entries;
+ long int rc;
+ struct dtl_entry *buf = NULL;
+ /* only allow one reader */
+ if (dtl->buf)
+ return -EBUSY;
+
+ n_entries = dtl_buf_entries;
+ buf = kmalloc_node(n_entries * sizeof(struct dtl_entry),
+ GFP_KERNEL, cpu_to_node(dtl->cpu));
+ if (!buf) {
+ printk(KERN_WARNING "%s: buffer alloc failed for cpu %d\n",
+ __func__, dtl->cpu);
+ return -ENOMEM;
+ }
+
+ spin_lock(&dtl->lock);
+ rc = -EBUSY;
+ if (!dtl->buf) {
+ /* store the original allocation size for use during read */
+ dtl->buf_entries = n_entries;
+ dtl->buf = buf;
+ dtl->last_idx = 0;
+ rc = dtl_start(dtl);
+ if (rc)
+ dtl->buf = NULL;
+ }
+ spin_unlock(&dtl->lock);
+
+ if (rc)
+ kfree(buf);
+ return rc;
+}
+
+static void dtl_disable(struct dtl *dtl)
+{
+ spin_lock(&dtl->lock);
+ dtl_stop(dtl);
kfree(dtl->buf);
dtl->buf = NULL;
dtl->buf_entries = 0;
+ spin_unlock(&dtl->lock);
}
/* file interface */
@@ -157,8 +262,9 @@ static int dtl_file_release(struct inode *inode, struct file *filp)
static ssize_t dtl_file_read(struct file *filp, char __user *buf, size_t len,
loff_t *pos)
{
- int rc, cur_idx, last_idx, n_read, n_req, read_size;
+ long int rc, n_read, n_req, read_size;
struct dtl *dtl;
+ u64 cur_idx, last_idx, i;
if ((len % sizeof(struct dtl_entry)) != 0)
return -EINVAL;
@@ -171,41 +277,48 @@ static ssize_t dtl_file_read(struct file *filp, char __user *buf, size_t len,
/* actual number of entries read */
n_read = 0;
- cur_idx = lppaca[dtl->cpu].dtl_idx;
+ spin_lock(&dtl->lock);
+
+ cur_idx = dtl_current_index(dtl);
last_idx = dtl->last_idx;
- if (cur_idx - last_idx > dtl->buf_entries) {
- pr_debug("%s: hv buffer overflow for cpu %d, samples lost\n",
- __func__, dtl->cpu);
- }
+ if (last_idx + dtl->buf_entries <= cur_idx)
+ last_idx = cur_idx - dtl->buf_entries + 1;
+
+ if (last_idx + n_req > cur_idx)
+ n_req = cur_idx - last_idx;
+
+ if (n_req > 0)
+ dtl->last_idx = last_idx + n_req;
+
+ spin_unlock(&dtl->lock);
+
+ if (n_req <= 0)
+ return 0;
- cur_idx %= dtl->buf_entries;
- last_idx %= dtl->buf_entries;
+ i = last_idx % dtl->buf_entries;
/* read the tail of the buffer if we've wrapped */
- if (last_idx > cur_idx) {
- read_size = min(n_req, dtl->buf_entries - last_idx);
+ if (i + n_req > dtl->buf_entries) {
+ read_size = dtl->buf_entries - i;
- rc = copy_to_user(buf, &dtl->buf[last_idx],
+ rc = copy_to_user(buf, &dtl->buf[i],
read_size * sizeof(struct dtl_entry));
if (rc)
return -EFAULT;
- last_idx = 0;
+ i = 0;
n_req -= read_size;
n_read += read_size;
buf += read_size * sizeof(struct dtl_entry);
}
/* .. and now the head */
- read_size = min(n_req, cur_idx - last_idx);
- rc = copy_to_user(buf, &dtl->buf[last_idx],
- read_size * sizeof(struct dtl_entry));
+ rc = copy_to_user(buf, &dtl->buf[i], n_req * sizeof(struct dtl_entry));
if (rc)
return -EFAULT;
- n_read += read_size;
- dtl->last_idx += n_read;
+ n_read += n_req;
return n_read * sizeof(struct dtl_entry);
}
@@ -263,6 +376,7 @@ static int dtl_init(void)
/* set up the per-cpu log structures */
for_each_possible_cpu(i) {
struct dtl *dtl = &per_cpu(cpu_dtl, i);
+ spin_lock_init(&dtl->lock);
dtl->cpu = i;
rc = dtl_setup_file(dtl);
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index cf79b46d8f88..f129040d974c 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -248,11 +248,13 @@ void vpa_init(int cpu)
int hwcpu = get_hard_smp_processor_id(cpu);
unsigned long addr;
long ret;
+ struct paca_struct *pp;
+ struct dtl_entry *dtl;
if (cpu_has_feature(CPU_FTR_ALTIVEC))
- lppaca[cpu].vmxregs_in_use = 1;
+ lppaca_of(cpu).vmxregs_in_use = 1;
- addr = __pa(&lppaca[cpu]);
+ addr = __pa(&lppaca_of(cpu));
ret = register_vpa(hwcpu, addr);
if (ret) {
@@ -274,6 +276,25 @@ void vpa_init(int cpu)
"registration for cpu %d (hw %d) of area %lx "
"returns %ld\n", cpu, hwcpu, addr, ret);
}
+
+ /*
+ * Register dispatch trace log, if one has been allocated.
+ */
+ pp = &paca[cpu];
+ dtl = pp->dispatch_log;
+ if (dtl) {
+ pp->dtl_ridx = 0;
+ pp->dtl_curr = dtl;
+ lppaca_of(cpu).dtl_idx = 0;
+
+ /* hypervisor reads buffer length from this field */
+ dtl->enqueue_to_dispatch_time = DISPATCH_LOG_BYTES;
+ ret = register_dtl(hwcpu, __pa(dtl));
+ if (ret)
+ pr_warn("DTL registration failed for cpu %d (%ld)\n",
+ cpu, ret);
+ lppaca_of(cpu).dtl_enable_mask = 2;
+ }
}
static long pSeries_lpar_hpte_insert(unsigned long hpte_group,
diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platforms/pseries/mobility.c
new file mode 100644
index 000000000000..3e7f651e50ac
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/mobility.c
@@ -0,0 +1,362 @@
+/*
+ * Support for Partition Mobility/Migration
+ *
+ * Copyright (C) 2010 Nathan Fontenot
+ * Copyright (C) 2010 IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/kobject.h>
+#include <linux/smp.h>
+#include <linux/completion.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+
+#include <asm/rtas.h>
+#include "pseries.h"
+
+static struct kobject *mobility_kobj;
+
+struct update_props_workarea {
+ u32 phandle;
+ u32 state;
+ u64 reserved;
+ u32 nprops;
+};
+
+#define NODE_ACTION_MASK 0xff000000
+#define NODE_COUNT_MASK 0x00ffffff
+
+#define DELETE_DT_NODE 0x01000000
+#define UPDATE_DT_NODE 0x02000000
+#define ADD_DT_NODE 0x03000000
+
+static int mobility_rtas_call(int token, char *buf)
+{
+ int rc;
+
+ spin_lock(&rtas_data_buf_lock);
+
+ memcpy(rtas_data_buf, buf, RTAS_DATA_BUF_SIZE);
+ rc = rtas_call(token, 2, 1, NULL, rtas_data_buf, 1);
+ memcpy(buf, rtas_data_buf, RTAS_DATA_BUF_SIZE);
+
+ spin_unlock(&rtas_data_buf_lock);
+ return rc;
+}
+
+static int delete_dt_node(u32 phandle)
+{
+ struct device_node *dn;
+
+ dn = of_find_node_by_phandle(phandle);
+ if (!dn)
+ return -ENOENT;
+
+ dlpar_detach_node(dn);
+ return 0;
+}
+
+static int update_dt_property(struct device_node *dn, struct property **prop,
+ const char *name, u32 vd, char *value)
+{
+ struct property *new_prop = *prop;
+ struct property *old_prop;
+ int more = 0;
+
+ /* A negative 'vd' value indicates that only part of the new property
+ * value is contained in the buffer and we need to call
+ * ibm,update-properties again to get the rest of the value.
+ *
+ * A negative value is also the two's compliment of the actual value.
+ */
+ if (vd & 0x80000000) {
+ vd = ~vd + 1;
+ more = 1;
+ }
+
+ if (new_prop) {
+ /* partial property fixup */
+ char *new_data = kzalloc(new_prop->length + vd, GFP_KERNEL);
+ if (!new_data)
+ return -ENOMEM;
+
+ memcpy(new_data, new_prop->value, new_prop->length);
+ memcpy(new_data + new_prop->length, value, vd);
+
+ kfree(new_prop->value);
+ new_prop->value = new_data;
+ new_prop->length += vd;
+ } else {
+ new_prop = kzalloc(sizeof(*new_prop), GFP_KERNEL);
+ if (!new_prop)
+ return -ENOMEM;
+
+ new_prop->name = kstrdup(name, GFP_KERNEL);
+ if (!new_prop->name) {
+ kfree(new_prop);
+ return -ENOMEM;
+ }
+
+ new_prop->length = vd;
+ new_prop->value = kzalloc(new_prop->length, GFP_KERNEL);
+ if (!new_prop->value) {
+ kfree(new_prop->name);
+ kfree(new_prop);
+ return -ENOMEM;
+ }
+
+ memcpy(new_prop->value, value, vd);
+ *prop = new_prop;
+ }
+
+ if (!more) {
+ old_prop = of_find_property(dn, new_prop->name, NULL);
+ if (old_prop)
+ prom_update_property(dn, new_prop, old_prop);
+ else
+ prom_add_property(dn, new_prop);
+
+ new_prop = NULL;
+ }
+
+ return 0;
+}
+
+static int update_dt_node(u32 phandle)
+{
+ struct update_props_workarea *upwa;
+ struct device_node *dn;
+ struct property *prop = NULL;
+ int i, rc;
+ char *prop_data;
+ char *rtas_buf;
+ int update_properties_token;
+
+ update_properties_token = rtas_token("ibm,update-properties");
+ if (update_properties_token == RTAS_UNKNOWN_SERVICE)
+ return -EINVAL;
+
+ rtas_buf = kzalloc(RTAS_DATA_BUF_SIZE, GFP_KERNEL);
+ if (!rtas_buf)
+ return -ENOMEM;
+
+ dn = of_find_node_by_phandle(phandle);
+ if (!dn) {
+ kfree(rtas_buf);
+ return -ENOENT;
+ }
+
+ upwa = (struct update_props_workarea *)&rtas_buf[0];
+ upwa->phandle = phandle;
+
+ do {
+ rc = mobility_rtas_call(update_properties_token, rtas_buf);
+ if (rc < 0)
+ break;
+
+ prop_data = rtas_buf + sizeof(*upwa);
+
+ for (i = 0; i < upwa->nprops; i++) {
+ char *prop_name;
+ u32 vd;
+
+ prop_name = prop_data + 1;
+ prop_data += strlen(prop_name) + 1;
+ vd = *prop_data++;
+
+ switch (vd) {
+ case 0x00000000:
+ /* name only property, nothing to do */
+ break;
+
+ case 0x80000000:
+ prop = of_find_property(dn, prop_name, NULL);
+ prom_remove_property(dn, prop);
+ prop = NULL;
+ break;
+
+ default:
+ rc = update_dt_property(dn, &prop, prop_name,
+ vd, prop_data);
+ if (rc) {
+ printk(KERN_ERR "Could not update %s"
+ " property\n", prop_name);
+ }
+
+ prop_data += vd;
+ }
+ }
+ } while (rc == 1);
+
+ of_node_put(dn);
+ kfree(rtas_buf);
+ return 0;
+}
+
+static int add_dt_node(u32 parent_phandle, u32 drc_index)
+{
+ struct device_node *dn;
+ struct device_node *parent_dn;
+ int rc;
+
+ dn = dlpar_configure_connector(drc_index);
+ if (!dn)
+ return -ENOENT;
+
+ parent_dn = of_find_node_by_phandle(parent_phandle);
+ if (!parent_dn) {
+ dlpar_free_cc_nodes(dn);
+ return -ENOENT;
+ }
+
+ dn->parent = parent_dn;
+ rc = dlpar_attach_node(dn);
+ if (rc)
+ dlpar_free_cc_nodes(dn);
+
+ of_node_put(parent_dn);
+ return rc;
+}
+
+static int pseries_devicetree_update(void)
+{
+ char *rtas_buf;
+ u32 *data;
+ int update_nodes_token;
+ int rc;
+
+ update_nodes_token = rtas_token("ibm,update-nodes");
+ if (update_nodes_token == RTAS_UNKNOWN_SERVICE)
+ return -EINVAL;
+
+ rtas_buf = kzalloc(RTAS_DATA_BUF_SIZE, GFP_KERNEL);
+ if (!rtas_buf)
+ return -ENOMEM;
+
+ do {
+ rc = mobility_rtas_call(update_nodes_token, rtas_buf);
+ if (rc && rc != 1)
+ break;
+
+ data = (u32 *)rtas_buf + 4;
+ while (*data & NODE_ACTION_MASK) {
+ int i;
+ u32 action = *data & NODE_ACTION_MASK;
+ int node_count = *data & NODE_COUNT_MASK;
+
+ data++;
+
+ for (i = 0; i < node_count; i++) {
+ u32 phandle = *data++;
+ u32 drc_index;
+
+ switch (action) {
+ case DELETE_DT_NODE:
+ delete_dt_node(phandle);
+ break;
+ case UPDATE_DT_NODE:
+ update_dt_node(phandle);
+ break;
+ case ADD_DT_NODE:
+ drc_index = *data++;
+ add_dt_node(phandle, drc_index);
+ break;
+ }
+ }
+ }
+ } while (rc == 1);
+
+ kfree(rtas_buf);
+ return rc;
+}
+
+void post_mobility_fixup(void)
+{
+ int rc;
+ int activate_fw_token;
+
+ rc = pseries_devicetree_update();
+ if (rc) {
+ printk(KERN_ERR "Initial post-mobility device tree update "
+ "failed: %d\n", rc);
+ return;
+ }
+
+ activate_fw_token = rtas_token("ibm,activate-firmware");
+ if (activate_fw_token == RTAS_UNKNOWN_SERVICE) {
+ printk(KERN_ERR "Could not make post-mobility "
+ "activate-fw call.\n");
+ return;
+ }
+
+ rc = rtas_call(activate_fw_token, 0, 1, NULL);
+ if (!rc) {
+ rc = pseries_devicetree_update();
+ if (rc)
+ printk(KERN_ERR "Secondary post-mobility device tree "
+ "update failed: %d\n", rc);
+ } else {
+ printk(KERN_ERR "Post-mobility activate-fw failed: %d\n", rc);
+ return;
+ }
+
+ return;
+}
+
+static ssize_t migrate_store(struct class *class, struct class_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct rtas_args args;
+ u64 streamid;
+ int rc;
+
+ rc = strict_strtoull(buf, 0, &streamid);
+ if (rc)
+ return rc;
+
+ memset(&args, 0, sizeof(args));
+ args.token = rtas_token("ibm,suspend-me");
+ args.nargs = 2;
+ args.nret = 1;
+
+ args.args[0] = streamid >> 32 ;
+ args.args[1] = streamid & 0xffffffff;
+ args.rets = &args.args[args.nargs];
+
+ do {
+ args.rets[0] = 0;
+ rc = rtas_ibm_suspend_me(&args);
+ if (!rc && args.rets[0] == RTAS_NOT_SUSPENDABLE)
+ ssleep(1);
+ } while (!rc && args.rets[0] == RTAS_NOT_SUSPENDABLE);
+
+ if (rc)
+ return rc;
+ else if (args.rets[0])
+ return args.rets[0];
+
+ post_mobility_fixup();
+ return count;
+}
+
+static CLASS_ATTR(migration, S_IWUSR, NULL, migrate_store);
+
+static int __init mobility_sysfs_init(void)
+{
+ int rc;
+
+ mobility_kobj = kobject_create_and_add("mobility", kernel_kobj);
+ if (!mobility_kobj)
+ return -ENOMEM;
+
+ rc = sysfs_create_file(mobility_kobj, &class_attr_migration.attr);
+
+ return rc;
+}
+device_initcall(mobility_sysfs_init);
diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h
index 40c93cad91d2..e9f6d2859c3c 100644
--- a/arch/powerpc/platforms/pseries/pseries.h
+++ b/arch/powerpc/platforms/pseries/pseries.h
@@ -17,6 +17,8 @@ struct device_node;
extern void request_event_sources_irqs(struct device_node *np,
irq_handler_t handler, const char *name);
+#include <linux/of.h>
+
extern void __init fw_feature_init(const char *hypertas, unsigned long len);
struct pt_regs;
@@ -47,4 +49,11 @@ extern unsigned long rtas_poweron_auto;
extern void find_udbg_vterm(void);
+/* Dynamic logical Partitioning/Mobility */
+extern void dlpar_free_cc_nodes(struct device_node *);
+extern void dlpar_free_cc_property(struct property *);
+extern struct device_node *dlpar_configure_connector(u32);
+extern int dlpar_attach_node(struct device_node *);
+extern int dlpar_detach_node(struct device_node *);
+
#endif /* _PSERIES_PSERIES_H */
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c
index 57ddbb43b33a..1de2cbb92303 100644
--- a/arch/powerpc/platforms/pseries/reconfig.c
+++ b/arch/powerpc/platforms/pseries/reconfig.c
@@ -539,7 +539,8 @@ out:
}
static const struct file_operations ofdt_fops = {
- .write = ofdt_write
+ .write = ofdt_write,
+ .llseek = noop_llseek,
};
/* create /proc/powerpc/ofdt write-only by root */
diff --git a/arch/powerpc/platforms/pseries/scanlog.c b/arch/powerpc/platforms/pseries/scanlog.c
index 80e9e7652a4d..554457294a2b 100644
--- a/arch/powerpc/platforms/pseries/scanlog.c
+++ b/arch/powerpc/platforms/pseries/scanlog.c
@@ -170,6 +170,7 @@ const struct file_operations scanlog_fops = {
.write = scanlog_write,
.open = scanlog_open,
.release = scanlog_release,
+ .llseek = noop_llseek,
};
static int __init scanlog_init(void)
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index a6d19e3a505e..d345bfd56bbe 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -273,6 +273,58 @@ static struct notifier_block pci_dn_reconfig_nb = {
.notifier_call = pci_dn_reconfig_notifier,
};
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+/*
+ * Allocate space for the dispatch trace log for all possible cpus
+ * and register the buffers with the hypervisor. This is used for
+ * computing time stolen by the hypervisor.
+ */
+static int alloc_dispatch_logs(void)
+{
+ int cpu, ret;
+ struct paca_struct *pp;
+ struct dtl_entry *dtl;
+
+ if (!firmware_has_feature(FW_FEATURE_SPLPAR))
+ return 0;
+
+ for_each_possible_cpu(cpu) {
+ pp = &paca[cpu];
+ dtl = kmalloc_node(DISPATCH_LOG_BYTES, GFP_KERNEL,
+ cpu_to_node(cpu));
+ if (!dtl) {
+ pr_warn("Failed to allocate dispatch trace log for cpu %d\n",
+ cpu);
+ pr_warn("Stolen time statistics will be unreliable\n");
+ break;
+ }
+
+ pp->dtl_ridx = 0;
+ pp->dispatch_log = dtl;
+ pp->dispatch_log_end = dtl + N_DISPATCH_LOG;
+ pp->dtl_curr = dtl;
+ }
+
+ /* Register the DTL for the current (boot) cpu */
+ dtl = get_paca()->dispatch_log;
+ get_paca()->dtl_ridx = 0;
+ get_paca()->dtl_curr = dtl;
+ get_paca()->lppaca_ptr->dtl_idx = 0;
+
+ /* hypervisor reads buffer length from this field */
+ dtl->enqueue_to_dispatch_time = DISPATCH_LOG_BYTES;
+ ret = register_dtl(hard_smp_processor_id(), __pa(dtl));
+ if (ret)
+ pr_warn("DTL registration failed for boot cpu %d (%d)\n",
+ smp_processor_id(), ret);
+ get_paca()->lppaca_ptr->dtl_enable_mask = 2;
+
+ return 0;
+}
+
+early_initcall(alloc_dispatch_logs);
+#endif /* CONFIG_VIRT_CPU_ACCOUNTING */
+
static void __init pSeries_setup_arch(void)
{
/* Discover PIC type and setup ppc_md accordingly */
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index 93834b0d8272..7b96e5a270ce 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -178,7 +178,7 @@ static int get_irq_server(unsigned int virq, const struct cpumask *cpumask,
if (!distribute_irqs)
return default_server;
- if (!cpumask_equal(cpumask, cpu_all_mask)) {
+ if (!cpumask_subset(cpu_possible_mask, cpumask)) {
int server = cpumask_first_and(cpu_online_mask, cpumask);
if (server < nr_cpu_ids)
@@ -243,7 +243,7 @@ static unsigned int xics_startup(unsigned int virq)
* at that level, so we do it here by hand.
*/
if (irq_to_desc(virq)->msi_desc)
- unmask_msi_irq(virq);
+ unmask_msi_irq(irq_get_irq_data(virq));
/* unmask it */
xics_unmask_irq(virq);
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 5642924fb9fb..0bef9dacb64e 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -1,8 +1,6 @@
subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
-ifeq ($(CONFIG_PPC64),y)
-EXTRA_CFLAGS += -mno-minimal-toc
-endif
+ccflags-$(CONFIG_PPC64) := -mno-minimal-toc
mpic-msi-obj-$(CONFIG_PCI_MSI) += mpic_msi.o mpic_u3msi.o mpic_pasemi_msi.o
obj-$(CONFIG_MPIC) += mpic.o $(mpic-msi-obj-y)
@@ -20,6 +18,7 @@ obj-$(CONFIG_FSL_PMC) += fsl_pmc.o
obj-$(CONFIG_FSL_LBC) += fsl_lbc.o
obj-$(CONFIG_FSL_GTM) += fsl_gtm.o
obj-$(CONFIG_MPC8xxx_GPIO) += mpc8xxx_gpio.o
+obj-$(CONFIG_FSL_85XX_CACHE_SRAM) += fsl_85xx_l2ctlr.o fsl_85xx_cache_sram.o
obj-$(CONFIG_SIMPLE_GPIO) += simple_gpio.o
obj-$(CONFIG_RAPIDIO) += fsl_rio.o
obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o
diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c
index 559db2b846a9..17cf15ec38be 100644
--- a/arch/powerpc/sysdev/dart_iommu.c
+++ b/arch/powerpc/sysdev/dart_iommu.c
@@ -70,6 +70,8 @@ static int iommu_table_dart_inited;
static int dart_dirty;
static int dart_is_u4;
+#define DART_U4_BYPASS_BASE 0x8000000000ull
+
#define DBG(...)
static inline void dart_tlb_invalidate_all(void)
@@ -292,12 +294,20 @@ static void iommu_table_dart_setup(void)
set_bit(iommu_table_dart.it_size - 1, iommu_table_dart.it_map);
}
-static void pci_dma_dev_setup_dart(struct pci_dev *dev)
+static void dma_dev_setup_dart(struct device *dev)
{
/* We only have one iommu table on the mac for now, which makes
* things simple. Setup all PCI devices to point to this table
*/
- set_iommu_table_base(&dev->dev, &iommu_table_dart);
+ if (get_dma_ops(dev) == &dma_direct_ops)
+ set_dma_offset(dev, DART_U4_BYPASS_BASE);
+ else
+ set_iommu_table_base(dev, &iommu_table_dart);
+}
+
+static void pci_dma_dev_setup_dart(struct pci_dev *dev)
+{
+ dma_dev_setup_dart(&dev->dev);
}
static void pci_dma_bus_setup_dart(struct pci_bus *bus)
@@ -315,6 +325,45 @@ static void pci_dma_bus_setup_dart(struct pci_bus *bus)
PCI_DN(dn)->iommu_table = &iommu_table_dart;
}
+static bool dart_device_on_pcie(struct device *dev)
+{
+ struct device_node *np = of_node_get(dev->of_node);
+
+ while(np) {
+ if (of_device_is_compatible(np, "U4-pcie") ||
+ of_device_is_compatible(np, "u4-pcie")) {
+ of_node_put(np);
+ return true;
+ }
+ np = of_get_next_parent(np);
+ }
+ return false;
+}
+
+static int dart_dma_set_mask(struct device *dev, u64 dma_mask)
+{
+ if (!dev->dma_mask || !dma_supported(dev, dma_mask))
+ return -EIO;
+
+ /* U4 supports a DART bypass, we use it for 64-bit capable
+ * devices to improve performances. However, that only works
+ * for devices connected to U4 own PCIe interface, not bridged
+ * through hypertransport. We need the device to support at
+ * least 40 bits of addresses.
+ */
+ if (dart_device_on_pcie(dev) && dma_mask >= DMA_BIT_MASK(40)) {
+ dev_info(dev, "Using 64-bit DMA iommu bypass\n");
+ set_dma_ops(dev, &dma_direct_ops);
+ } else {
+ dev_info(dev, "Using 32-bit DMA via iommu\n");
+ set_dma_ops(dev, &dma_iommu_ops);
+ }
+ dma_dev_setup_dart(dev);
+
+ *dev->dma_mask = dma_mask;
+ return 0;
+}
+
void __init iommu_init_early_dart(void)
{
struct device_node *dn;
@@ -328,20 +377,25 @@ void __init iommu_init_early_dart(void)
dart_is_u4 = 1;
}
+ /* Initialize the DART HW */
+ if (dart_init(dn) != 0)
+ goto bail;
+
/* Setup low level TCE operations for the core IOMMU code */
ppc_md.tce_build = dart_build;
ppc_md.tce_free = dart_free;
ppc_md.tce_flush = dart_flush;
- /* Initialize the DART HW */
- if (dart_init(dn) == 0) {
- ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_dart;
- ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_dart;
+ /* Setup bypass if supported */
+ if (dart_is_u4)
+ ppc_md.dma_set_mask = dart_dma_set_mask;
- /* Setup pci_dma ops */
- set_pci_dma_ops(&dma_iommu_ops);
- return;
- }
+ ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_dart;
+ ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_dart;
+
+ /* Setup pci_dma ops */
+ set_pci_dma_ops(&dma_iommu_ops);
+ return;
bail:
/* If init failed, use direct iommu and null setup functions */
diff --git a/arch/powerpc/sysdev/fsl_85xx_cache_ctlr.h b/arch/powerpc/sysdev/fsl_85xx_cache_ctlr.h
new file mode 100644
index 000000000000..60c9c0bd5ba2
--- /dev/null
+++ b/arch/powerpc/sysdev/fsl_85xx_cache_ctlr.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2009-2010 Freescale Semiconductor, Inc
+ *
+ * QorIQ based Cache Controller Memory Mapped Registers
+ *
+ * Author: Vivek Mahajan <vivek.mahajan@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __FSL_85XX_CACHE_CTLR_H__
+#define __FSL_85XX_CACHE_CTLR_H__
+
+#define L2CR_L2FI 0x40000000 /* L2 flash invalidate */
+#define L2CR_L2IO 0x00200000 /* L2 instruction only */
+#define L2CR_SRAM_ZERO 0x00000000 /* L2SRAM zero size */
+#define L2CR_SRAM_FULL 0x00010000 /* L2SRAM full size */
+#define L2CR_SRAM_HALF 0x00020000 /* L2SRAM half size */
+#define L2CR_SRAM_TWO_HALFS 0x00030000 /* L2SRAM two half sizes */
+#define L2CR_SRAM_QUART 0x00040000 /* L2SRAM one quarter size */
+#define L2CR_SRAM_TWO_QUARTS 0x00050000 /* L2SRAM two quarter size */
+#define L2CR_SRAM_EIGHTH 0x00060000 /* L2SRAM one eighth size */
+#define L2CR_SRAM_TWO_EIGHTH 0x00070000 /* L2SRAM two eighth size */
+
+#define L2SRAM_OPTIMAL_SZ_SHIFT 0x00000003 /* Optimum size for L2SRAM */
+
+#define L2SRAM_BAR_MSK_LO18 0xFFFFC000 /* Lower 18 bits */
+#define L2SRAM_BARE_MSK_HI4 0x0000000F /* Upper 4 bits */
+
+enum cache_sram_lock_ways {
+ LOCK_WAYS_ZERO,
+ LOCK_WAYS_EIGHTH,
+ LOCK_WAYS_TWO_EIGHTH,
+ LOCK_WAYS_HALF = 4,
+ LOCK_WAYS_FULL = 8,
+};
+
+struct mpc85xx_l2ctlr {
+ u32 ctl; /* 0x000 - L2 control */
+ u8 res1[0xC];
+ u32 ewar0; /* 0x010 - External write address 0 */
+ u32 ewarea0; /* 0x014 - External write address extended 0 */
+ u32 ewcr0; /* 0x018 - External write ctrl */
+ u8 res2[4];
+ u32 ewar1; /* 0x020 - External write address 1 */
+ u32 ewarea1; /* 0x024 - External write address extended 1 */
+ u32 ewcr1; /* 0x028 - External write ctrl 1 */
+ u8 res3[4];
+ u32 ewar2; /* 0x030 - External write address 2 */
+ u32 ewarea2; /* 0x034 - External write address extended 2 */
+ u32 ewcr2; /* 0x038 - External write ctrl 2 */
+ u8 res4[4];
+ u32 ewar3; /* 0x040 - External write address 3 */
+ u32 ewarea3; /* 0x044 - External write address extended 3 */
+ u32 ewcr3; /* 0x048 - External write ctrl 3 */
+ u8 res5[0xB4];
+ u32 srbar0; /* 0x100 - SRAM base address 0 */
+ u32 srbarea0; /* 0x104 - SRAM base addr reg ext address 0 */
+ u32 srbar1; /* 0x108 - SRAM base address 1 */
+ u32 srbarea1; /* 0x10C - SRAM base addr reg ext address 1 */
+ u8 res6[0xCF0];
+ u32 errinjhi; /* 0xE00 - Error injection mask high */
+ u32 errinjlo; /* 0xE04 - Error injection mask low */
+ u32 errinjctl; /* 0xE08 - Error injection tag/ecc control */
+ u8 res7[0x14];
+ u32 captdatahi; /* 0xE20 - Error data high capture */
+ u32 captdatalo; /* 0xE24 - Error data low capture */
+ u32 captecc; /* 0xE28 - Error syndrome */
+ u8 res8[0x14];
+ u32 errdet; /* 0xE40 - Error detect */
+ u32 errdis; /* 0xE44 - Error disable */
+ u32 errinten; /* 0xE48 - Error interrupt enable */
+ u32 errattr; /* 0xE4c - Error attribute capture */
+ u32 erradrrl; /* 0xE50 - Error address capture low */
+ u32 erradrrh; /* 0xE54 - Error address capture high */
+ u32 errctl; /* 0xE58 - Error control */
+ u8 res9[0x1A4];
+};
+
+struct sram_parameters {
+ unsigned int sram_size;
+ uint64_t sram_offset;
+};
+
+extern int instantiate_cache_sram(struct platform_device *dev,
+ struct sram_parameters sram_params);
+extern void remove_cache_sram(struct platform_device *dev);
+
+#endif /* __FSL_85XX_CACHE_CTLR_H__ */
diff --git a/arch/powerpc/sysdev/fsl_85xx_cache_sram.c b/arch/powerpc/sysdev/fsl_85xx_cache_sram.c
new file mode 100644
index 000000000000..54fb1922fe30
--- /dev/null
+++ b/arch/powerpc/sysdev/fsl_85xx_cache_sram.c
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2009-2010 Freescale Semiconductor, Inc.
+ *
+ * Simple memory allocator abstraction for QorIQ (P1/P2) based Cache-SRAM
+ *
+ * Author: Vivek Mahajan <vivek.mahajan@freescale.com>
+ *
+ * This file is derived from the original work done
+ * by Sylvain Munaut for the Bestcomm SRAM allocator.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/of_platform.h>
+#include <asm/pgtable.h>
+#include <asm/fsl_85xx_cache_sram.h>
+
+#include "fsl_85xx_cache_ctlr.h"
+
+struct mpc85xx_cache_sram *cache_sram;
+
+void *mpc85xx_cache_sram_alloc(unsigned int size,
+ phys_addr_t *phys, unsigned int align)
+{
+ unsigned long offset;
+ unsigned long flags;
+
+ if (unlikely(cache_sram == NULL))
+ return NULL;
+
+ if (!size || (size > cache_sram->size) || (align > cache_sram->size)) {
+ pr_err("%s(): size(=%x) or align(=%x) zero or too big\n",
+ __func__, size, align);
+ return NULL;
+ }
+
+ if ((align & (align - 1)) || align <= 1) {
+ pr_err("%s(): align(=%x) must be power of two and >1\n",
+ __func__, align);
+ return NULL;
+ }
+
+ spin_lock_irqsave(&cache_sram->lock, flags);
+ offset = rh_alloc_align(cache_sram->rh, size, align, NULL);
+ spin_unlock_irqrestore(&cache_sram->lock, flags);
+
+ if (IS_ERR_VALUE(offset))
+ return NULL;
+
+ *phys = cache_sram->base_phys + offset;
+
+ return (unsigned char *)cache_sram->base_virt + offset;
+}
+EXPORT_SYMBOL(mpc85xx_cache_sram_alloc);
+
+void mpc85xx_cache_sram_free(void *ptr)
+{
+ unsigned long flags;
+ BUG_ON(!ptr);
+
+ spin_lock_irqsave(&cache_sram->lock, flags);
+ rh_free(cache_sram->rh, ptr - cache_sram->base_virt);
+ spin_unlock_irqrestore(&cache_sram->lock, flags);
+}
+EXPORT_SYMBOL(mpc85xx_cache_sram_free);
+
+int __init instantiate_cache_sram(struct platform_device *dev,
+ struct sram_parameters sram_params)
+{
+ int ret = 0;
+
+ if (cache_sram) {
+ dev_err(&dev->dev, "Already initialized cache-sram\n");
+ return -EBUSY;
+ }
+
+ cache_sram = kzalloc(sizeof(struct mpc85xx_cache_sram), GFP_KERNEL);
+ if (!cache_sram) {
+ dev_err(&dev->dev, "Out of memory for cache_sram structure\n");
+ return -ENOMEM;
+ }
+
+ cache_sram->base_phys = sram_params.sram_offset;
+ cache_sram->size = sram_params.sram_size;
+
+ if (!request_mem_region(cache_sram->base_phys, cache_sram->size,
+ "fsl_85xx_cache_sram")) {
+ dev_err(&dev->dev, "%s: request memory failed\n",
+ dev->dev.of_node->full_name);
+ ret = -ENXIO;
+ goto out_free;
+ }
+
+ cache_sram->base_virt = ioremap_flags(cache_sram->base_phys,
+ cache_sram->size, _PAGE_COHERENT | PAGE_KERNEL);
+ if (!cache_sram->base_virt) {
+ dev_err(&dev->dev, "%s: ioremap_flags failed\n",
+ dev->dev.of_node->full_name);
+ ret = -ENOMEM;
+ goto out_release;
+ }
+
+ cache_sram->rh = rh_create(sizeof(unsigned int));
+ if (IS_ERR(cache_sram->rh)) {
+ dev_err(&dev->dev, "%s: Unable to create remote heap\n",
+ dev->dev.of_node->full_name);
+ ret = PTR_ERR(cache_sram->rh);
+ goto out_unmap;
+ }
+
+ rh_attach_region(cache_sram->rh, 0, cache_sram->size);
+ spin_lock_init(&cache_sram->lock);
+
+ dev_info(&dev->dev, "[base:0x%llx, size:0x%x] configured and loaded\n",
+ (unsigned long long)cache_sram->base_phys, cache_sram->size);
+
+ return 0;
+
+out_unmap:
+ iounmap(cache_sram->base_virt);
+
+out_release:
+ release_mem_region(cache_sram->base_phys, cache_sram->size);
+
+out_free:
+ kfree(cache_sram);
+ return ret;
+}
+
+void remove_cache_sram(struct platform_device *dev)
+{
+ BUG_ON(!cache_sram);
+
+ rh_detach_region(cache_sram->rh, 0, cache_sram->size);
+ rh_destroy(cache_sram->rh);
+
+ iounmap(cache_sram->base_virt);
+ release_mem_region(cache_sram->base_phys, cache_sram->size);
+
+ kfree(cache_sram);
+ cache_sram = NULL;
+
+ dev_info(&dev->dev, "MPC85xx Cache-SRAM driver unloaded\n");
+}
diff --git a/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c b/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c
new file mode 100644
index 000000000000..cc8d6556d799
--- /dev/null
+++ b/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c
@@ -0,0 +1,231 @@
+/*
+ * Copyright 2009-2010 Freescale Semiconductor, Inc.
+ *
+ * QorIQ (P1/P2) L2 controller init for Cache-SRAM instantiation
+ *
+ * Author: Vivek Mahajan <vivek.mahajan@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/of_platform.h>
+#include <asm/io.h>
+
+#include "fsl_85xx_cache_ctlr.h"
+
+static char *sram_size;
+static char *sram_offset;
+struct mpc85xx_l2ctlr __iomem *l2ctlr;
+
+static long get_cache_sram_size(void)
+{
+ unsigned long val;
+
+ if (!sram_size || (strict_strtoul(sram_size, 0, &val) < 0))
+ return -EINVAL;
+
+ return val;
+}
+
+static long get_cache_sram_offset(void)
+{
+ unsigned long val;
+
+ if (!sram_offset || (strict_strtoul(sram_offset, 0, &val) < 0))
+ return -EINVAL;
+
+ return val;
+}
+
+static int __init get_size_from_cmdline(char *str)
+{
+ if (!str)
+ return 0;
+
+ sram_size = str;
+ return 1;
+}
+
+static int __init get_offset_from_cmdline(char *str)
+{
+ if (!str)
+ return 0;
+
+ sram_offset = str;
+ return 1;
+}
+
+__setup("cache-sram-size=", get_size_from_cmdline);
+__setup("cache-sram-offset=", get_offset_from_cmdline);
+
+static int __devinit mpc85xx_l2ctlr_of_probe(struct platform_device *dev,
+ const struct of_device_id *match)
+{
+ long rval;
+ unsigned int rem;
+ unsigned char ways;
+ const unsigned int *prop;
+ unsigned int l2cache_size;
+ struct sram_parameters sram_params;
+
+ if (!dev->dev.of_node) {
+ dev_err(&dev->dev, "Device's OF-node is NULL\n");
+ return -EINVAL;
+ }
+
+ prop = of_get_property(dev->dev.of_node, "cache-size", NULL);
+ if (!prop) {
+ dev_err(&dev->dev, "Missing L2 cache-size\n");
+ return -EINVAL;
+ }
+ l2cache_size = *prop;
+
+ sram_params.sram_size = get_cache_sram_size();
+ if (sram_params.sram_size <= 0) {
+ dev_err(&dev->dev,
+ "Entire L2 as cache, Aborting Cache-SRAM stuff\n");
+ return -EINVAL;
+ }
+
+ sram_params.sram_offset = get_cache_sram_offset();
+ if (sram_params.sram_offset <= 0) {
+ dev_err(&dev->dev,
+ "Entire L2 as cache, provide a valid sram offset\n");
+ return -EINVAL;
+ }
+
+
+ rem = l2cache_size % sram_params.sram_size;
+ ways = LOCK_WAYS_FULL * sram_params.sram_size / l2cache_size;
+ if (rem || (ways & (ways - 1))) {
+ dev_err(&dev->dev, "Illegal cache-sram-size in command line\n");
+ return -EINVAL;
+ }
+
+ l2ctlr = of_iomap(dev->dev.of_node, 0);
+ if (!l2ctlr) {
+ dev_err(&dev->dev, "Can't map L2 controller\n");
+ return -EINVAL;
+ }
+
+ /*
+ * Write bits[0-17] to srbar0
+ */
+ out_be32(&l2ctlr->srbar0,
+ sram_params.sram_offset & L2SRAM_BAR_MSK_LO18);
+
+ /*
+ * Write bits[18-21] to srbare0
+ */
+#ifdef CONFIG_PHYS_64BIT
+ out_be32(&l2ctlr->srbarea0,
+ (sram_params.sram_offset >> 32) & L2SRAM_BARE_MSK_HI4);
+#endif
+
+ clrsetbits_be32(&l2ctlr->ctl, L2CR_L2E, L2CR_L2FI);
+
+ switch (ways) {
+ case LOCK_WAYS_EIGHTH:
+ setbits32(&l2ctlr->ctl,
+ L2CR_L2E | L2CR_L2FI | L2CR_SRAM_EIGHTH);
+ break;
+
+ case LOCK_WAYS_TWO_EIGHTH:
+ setbits32(&l2ctlr->ctl,
+ L2CR_L2E | L2CR_L2FI | L2CR_SRAM_QUART);
+ break;
+
+ case LOCK_WAYS_HALF:
+ setbits32(&l2ctlr->ctl,
+ L2CR_L2E | L2CR_L2FI | L2CR_SRAM_HALF);
+ break;
+
+ case LOCK_WAYS_FULL:
+ default:
+ setbits32(&l2ctlr->ctl,
+ L2CR_L2E | L2CR_L2FI | L2CR_SRAM_FULL);
+ break;
+ }
+ eieio();
+
+ rval = instantiate_cache_sram(dev, sram_params);
+ if (rval < 0) {
+ dev_err(&dev->dev, "Can't instantiate Cache-SRAM\n");
+ iounmap(l2ctlr);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int __devexit mpc85xx_l2ctlr_of_remove(struct platform_device *dev)
+{
+ BUG_ON(!l2ctlr);
+
+ iounmap(l2ctlr);
+ remove_cache_sram(dev);
+ dev_info(&dev->dev, "MPC85xx L2 controller unloaded\n");
+
+ return 0;
+}
+
+static struct of_device_id mpc85xx_l2ctlr_of_match[] = {
+ {
+ .compatible = "fsl,p2020-l2-cache-controller",
+ },
+ {
+ .compatible = "fsl,p2010-l2-cache-controller",
+ },
+ {
+ .compatible = "fsl,p1020-l2-cache-controller",
+ },
+ {
+ .compatible = "fsl,p1011-l2-cache-controller",
+ },
+ {
+ .compatible = "fsl,p1013-l2-cache-controller",
+ },
+ {
+ .compatible = "fsl,p1022-l2-cache-controller",
+ },
+ {},
+};
+
+static struct of_platform_driver mpc85xx_l2ctlr_of_platform_driver = {
+ .driver = {
+ .name = "fsl-l2ctlr",
+ .owner = THIS_MODULE,
+ .of_match_table = mpc85xx_l2ctlr_of_match,
+ },
+ .probe = mpc85xx_l2ctlr_of_probe,
+ .remove = __devexit_p(mpc85xx_l2ctlr_of_remove),
+};
+
+static __init int mpc85xx_l2ctlr_of_init(void)
+{
+ return of_register_platform_driver(&mpc85xx_l2ctlr_of_platform_driver);
+}
+
+static void __exit mpc85xx_l2ctlr_of_exit(void)
+{
+ of_unregister_platform_driver(&mpc85xx_l2ctlr_of_platform_driver);
+}
+
+subsys_initcall(mpc85xx_l2ctlr_of_init);
+module_exit(mpc85xx_l2ctlr_of_exit);
+
+MODULE_DESCRIPTION("Freescale MPC85xx L2 controller init");
+MODULE_LICENSE("GPL v2");
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c
index 87991d3abbab..108d76fa8f1c 100644
--- a/arch/powerpc/sysdev/fsl_msi.c
+++ b/arch/powerpc/sysdev/fsl_msi.c
@@ -24,6 +24,7 @@
#include <asm/ppc-pci.h>
#include <asm/mpic.h>
#include "fsl_msi.h"
+#include "fsl_pci.h"
LIST_HEAD(msi_head);
@@ -51,8 +52,8 @@ static void fsl_msi_end_irq(unsigned int virq)
}
static struct irq_chip fsl_msi_chip = {
- .mask = mask_msi_irq,
- .unmask = unmask_msi_irq,
+ .irq_mask = mask_msi_irq,
+ .irq_unmask = unmask_msi_irq,
.ack = fsl_msi_end_irq,
.name = "FSL-MSI",
};
@@ -125,13 +126,11 @@ static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq,
{
struct fsl_msi *msi_data = fsl_msi_data;
struct pci_controller *hose = pci_bus_to_host(pdev->bus);
- u32 base = 0;
+ u64 base = fsl_pci_immrbar_base(hose);
- pci_bus_read_config_dword(hose->bus,
- PCI_DEVFN(0, 0), PCI_BASE_ADDRESS_0, &base);
+ msg->address_lo = msi_data->msi_addr_lo + lower_32_bits(base);
+ msg->address_hi = msi_data->msi_addr_hi + upper_32_bits(base);
- msg->address_lo = msi_data->msi_addr_lo + base;
- msg->address_hi = msi_data->msi_addr_hi;
msg->data = hwirq;
pr_debug("%s: allocated srs: %d, ibs: %d\n",
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 4ae933225251..818f7c6c8fa1 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -1,7 +1,7 @@
/*
* MPC83xx/85xx/86xx PCI/PCIE support routing.
*
- * Copyright 2007-2009 Freescale Semiconductor, Inc.
+ * Copyright 2007-2010 Freescale Semiconductor, Inc.
* Copyright 2008-2009 MontaVista Software, Inc.
*
* Initial author: Xianghua Xiao <x.xiao@freescale.com>
@@ -34,7 +34,7 @@
#include <sysdev/fsl_soc.h>
#include <sysdev/fsl_pci.h>
-static int fsl_pcie_bus_fixup;
+static int fsl_pcie_bus_fixup, is_mpc83xx_pci;
static void __init quirk_fsl_pcie_header(struct pci_dev *dev)
{
@@ -407,10 +407,18 @@ DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2010E, quirk_fsl_pcie_header);
DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2010, quirk_fsl_pcie_header);
DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2020E, quirk_fsl_pcie_header);
DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2020, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2040E, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2040, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P3041E, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P3041, quirk_fsl_pcie_header);
DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4040E, quirk_fsl_pcie_header);
DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4040, quirk_fsl_pcie_header);
DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4080E, quirk_fsl_pcie_header);
DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4080, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P5010E, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P5010, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P5020E, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P5020, quirk_fsl_pcie_header);
#endif /* CONFIG_FSL_SOC_BOOKE || CONFIG_PPC_86xx */
#if defined(CONFIG_PPC_83xx) || defined(CONFIG_PPC_MPC512x)
@@ -430,6 +438,13 @@ struct mpc83xx_pcie_priv {
u32 dev_base;
};
+struct pex_inbound_window {
+ u32 ar;
+ u32 tar;
+ u32 barl;
+ u32 barh;
+};
+
/*
* With the convention of u-boot, the PCIE outbound window 0 serves
* as configuration transactions outbound.
@@ -437,6 +452,8 @@ struct mpc83xx_pcie_priv {
#define PEX_OUTWIN0_BAR 0xCA4
#define PEX_OUTWIN0_TAL 0xCA8
#define PEX_OUTWIN0_TAH 0xCAC
+#define PEX_RC_INWIN_BASE 0xE60
+#define PEX_RCIWARn_EN 0x1
static int mpc83xx_pcie_exclude_device(struct pci_bus *bus, unsigned int devfn)
{
@@ -604,6 +621,8 @@ int __init mpc83xx_add_bridge(struct device_node *dev)
const int *bus_range;
int primary;
+ is_mpc83xx_pci = 1;
+
if (!of_device_is_available(dev)) {
pr_warning("%s: disabled by the firmware.\n",
dev->full_name);
@@ -683,3 +702,40 @@ err0:
return ret;
}
#endif /* CONFIG_PPC_83xx */
+
+u64 fsl_pci_immrbar_base(struct pci_controller *hose)
+{
+#ifdef CONFIG_PPC_83xx
+ if (is_mpc83xx_pci) {
+ struct mpc83xx_pcie_priv *pcie = hose->dn->data;
+ struct pex_inbound_window *in;
+ int i;
+
+ /* Walk the Root Complex Inbound windows to match IMMR base */
+ in = pcie->cfg_type0 + PEX_RC_INWIN_BASE;
+ for (i = 0; i < 4; i++) {
+ /* not enabled, skip */
+ if (!in_le32(&in[i].ar) & PEX_RCIWARn_EN)
+ continue;
+
+ if (get_immrbase() == in_le32(&in[i].tar))
+ return (u64)in_le32(&in[i].barh) << 32 |
+ in_le32(&in[i].barl);
+ }
+
+ printk(KERN_WARNING "could not find PCI BAR matching IMMR\n");
+ }
+#endif
+
+#if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx)
+ if (!is_mpc83xx_pci) {
+ u32 base;
+
+ pci_bus_read_config_dword(hose->bus,
+ PCI_DEVFN(0, 0), PCI_BASE_ADDRESS_0, &base);
+ return base;
+ }
+#endif
+
+ return 0;
+}
diff --git a/arch/powerpc/sysdev/fsl_pci.h b/arch/powerpc/sysdev/fsl_pci.h
index a9d8bbebed80..8ad72a11f77b 100644
--- a/arch/powerpc/sysdev/fsl_pci.h
+++ b/arch/powerpc/sysdev/fsl_pci.h
@@ -88,6 +88,7 @@ struct ccsr_pci {
extern int fsl_add_bridge(struct device_node *dev, int is_primary);
extern void fsl_pcibios_fixup_bus(struct pci_bus *bus);
extern int mpc83xx_add_bridge(struct device_node *dev);
+u64 fsl_pci_immrbar_base(struct pci_controller *hose);
#endif /* __POWERPC_FSL_PCI_H */
#endif /* __KERNEL__ */
diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c
index 3017532319c8..412763672d23 100644
--- a/arch/powerpc/sysdev/fsl_rio.c
+++ b/arch/powerpc/sysdev/fsl_rio.c
@@ -117,44 +117,59 @@ struct rio_atmu_regs {
};
struct rio_msg_regs {
- u32 omr;
- u32 osr;
+ u32 omr; /* 0xD_3000 - Outbound message 0 mode register */
+ u32 osr; /* 0xD_3004 - Outbound message 0 status register */
u32 pad1;
- u32 odqdpar;
+ u32 odqdpar; /* 0xD_300C - Outbound message 0 descriptor queue
+ dequeue pointer address register */
u32 pad2;
- u32 osar;
- u32 odpr;
- u32 odatr;
- u32 odcr;
+ u32 osar; /* 0xD_3014 - Outbound message 0 source address
+ register */
+ u32 odpr; /* 0xD_3018 - Outbound message 0 destination port
+ register */
+ u32 odatr; /* 0xD_301C - Outbound message 0 destination attributes
+ Register*/
+ u32 odcr; /* 0xD_3020 - Outbound message 0 double-word count
+ register */
u32 pad3;
- u32 odqepar;
+ u32 odqepar; /* 0xD_3028 - Outbound message 0 descriptor queue
+ enqueue pointer address register */
u32 pad4[13];
- u32 imr;
- u32 isr;
+ u32 imr; /* 0xD_3060 - Inbound message 0 mode register */
+ u32 isr; /* 0xD_3064 - Inbound message 0 status register */
u32 pad5;
- u32 ifqdpar;
+ u32 ifqdpar; /* 0xD_306C - Inbound message 0 frame queue dequeue
+ pointer address register*/
u32 pad6;
- u32 ifqepar;
+ u32 ifqepar; /* 0xD_3074 - Inbound message 0 frame queue enqueue
+ pointer address register */
u32 pad7[226];
- u32 odmr;
- u32 odsr;
+ u32 odmr; /* 0xD_3400 - Outbound doorbell mode register */
+ u32 odsr; /* 0xD_3404 - Outbound doorbell status register */
u32 res0[4];
- u32 oddpr;
- u32 oddatr;
+ u32 oddpr; /* 0xD_3418 - Outbound doorbell destination port
+ register */
+ u32 oddatr; /* 0xD_341c - Outbound doorbell destination attributes
+ register */
u32 res1[3];
- u32 odretcr;
+ u32 odretcr; /* 0xD_342C - Outbound doorbell retry error threshold
+ configuration register */
u32 res2[12];
- u32 dmr;
- u32 dsr;
+ u32 dmr; /* 0xD_3460 - Inbound doorbell mode register */
+ u32 dsr; /* 0xD_3464 - Inbound doorbell status register */
u32 pad8;
- u32 dqdpar;
+ u32 dqdpar; /* 0xD_346C - Inbound doorbell queue dequeue Pointer
+ address register */
u32 pad9;
- u32 dqepar;
+ u32 dqepar; /* 0xD_3474 - Inbound doorbell Queue enqueue pointer
+ address register */
u32 pad10[26];
- u32 pwmr;
- u32 pwsr;
- u32 epwqbar;
- u32 pwqbar;
+ u32 pwmr; /* 0xD_34E0 - Inbound port-write mode register */
+ u32 pwsr; /* 0xD_34E4 - Inbound port-write status register */
+ u32 epwqbar; /* 0xD_34E8 - Extended Port-Write Queue Base Address
+ register */
+ u32 pwqbar; /* 0xD_34EC - Inbound port-write queue base address
+ register */
};
struct rio_tx_desc {
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index b91f7acdda6f..19e5015e039b 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -209,186 +209,29 @@ static int __init of_add_fixed_phys(void)
arch_initcall(of_add_fixed_phys);
#endif /* CONFIG_FIXED_PHY */
-static enum fsl_usb2_phy_modes determine_usb_phy(const char *phy_type)
-{
- if (!phy_type)
- return FSL_USB2_PHY_NONE;
- if (!strcasecmp(phy_type, "ulpi"))
- return FSL_USB2_PHY_ULPI;
- if (!strcasecmp(phy_type, "utmi"))
- return FSL_USB2_PHY_UTMI;
- if (!strcasecmp(phy_type, "utmi_wide"))
- return FSL_USB2_PHY_UTMI_WIDE;
- if (!strcasecmp(phy_type, "serial"))
- return FSL_USB2_PHY_SERIAL;
-
- return FSL_USB2_PHY_NONE;
-}
+#if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx)
+static __be32 __iomem *rstcr;
-static int __init fsl_usb_of_init(void)
+static int __init setup_rstcr(void)
{
struct device_node *np;
- unsigned int i = 0;
- struct platform_device *usb_dev_mph = NULL, *usb_dev_dr_host = NULL,
- *usb_dev_dr_client = NULL;
- int ret;
-
- for_each_compatible_node(np, NULL, "fsl-usb2-mph") {
- struct resource r[2];
- struct fsl_usb2_platform_data usb_data;
- const unsigned char *prop = NULL;
-
- memset(&r, 0, sizeof(r));
- memset(&usb_data, 0, sizeof(usb_data));
-
- ret = of_address_to_resource(np, 0, &r[0]);
- if (ret)
- goto err;
-
- of_irq_to_resource(np, 0, &r[1]);
-
- usb_dev_mph =
- platform_device_register_simple("fsl-ehci", i, r, 2);
- if (IS_ERR(usb_dev_mph)) {
- ret = PTR_ERR(usb_dev_mph);
- goto err;
- }
-
- usb_dev_mph->dev.coherent_dma_mask = 0xffffffffUL;
- usb_dev_mph->dev.dma_mask = &usb_dev_mph->dev.coherent_dma_mask;
-
- usb_data.operating_mode = FSL_USB2_MPH_HOST;
-
- prop = of_get_property(np, "port0", NULL);
- if (prop)
- usb_data.port_enables |= FSL_USB2_PORT0_ENABLED;
-
- prop = of_get_property(np, "port1", NULL);
- if (prop)
- usb_data.port_enables |= FSL_USB2_PORT1_ENABLED;
-
- prop = of_get_property(np, "phy_type", NULL);
- usb_data.phy_mode = determine_usb_phy(prop);
-
- ret =
- platform_device_add_data(usb_dev_mph, &usb_data,
- sizeof(struct
- fsl_usb2_platform_data));
- if (ret)
- goto unreg_mph;
- i++;
- }
-
- for_each_compatible_node(np, NULL, "fsl-usb2-dr") {
- struct resource r[2];
- struct fsl_usb2_platform_data usb_data;
- const unsigned char *prop = NULL;
- if (!of_device_is_available(np))
- continue;
-
- memset(&r, 0, sizeof(r));
- memset(&usb_data, 0, sizeof(usb_data));
-
- ret = of_address_to_resource(np, 0, &r[0]);
- if (ret)
- goto unreg_mph;
-
- of_irq_to_resource(np, 0, &r[1]);
-
- prop = of_get_property(np, "dr_mode", NULL);
-
- if (!prop || !strcmp(prop, "host")) {
- usb_data.operating_mode = FSL_USB2_DR_HOST;
- usb_dev_dr_host = platform_device_register_simple(
- "fsl-ehci", i, r, 2);
- if (IS_ERR(usb_dev_dr_host)) {
- ret = PTR_ERR(usb_dev_dr_host);
- goto err;
- }
- } else if (prop && !strcmp(prop, "peripheral")) {
- usb_data.operating_mode = FSL_USB2_DR_DEVICE;
- usb_dev_dr_client = platform_device_register_simple(
- "fsl-usb2-udc", i, r, 2);
- if (IS_ERR(usb_dev_dr_client)) {
- ret = PTR_ERR(usb_dev_dr_client);
- goto err;
- }
- } else if (prop && !strcmp(prop, "otg")) {
- usb_data.operating_mode = FSL_USB2_DR_OTG;
- usb_dev_dr_host = platform_device_register_simple(
- "fsl-ehci", i, r, 2);
- if (IS_ERR(usb_dev_dr_host)) {
- ret = PTR_ERR(usb_dev_dr_host);
- goto err;
- }
- usb_dev_dr_client = platform_device_register_simple(
- "fsl-usb2-udc", i, r, 2);
- if (IS_ERR(usb_dev_dr_client)) {
- ret = PTR_ERR(usb_dev_dr_client);
- goto err;
- }
- } else {
- ret = -EINVAL;
- goto err;
+ for_each_node_by_name(np, "global-utilities") {
+ if ((of_get_property(np, "fsl,has-rstcr", NULL))) {
+ rstcr = of_iomap(np, 0) + 0xb0;
+ if (!rstcr)
+ printk (KERN_ERR "Error: reset control "
+ "register not mapped!\n");
+ break;
}
-
- prop = of_get_property(np, "phy_type", NULL);
- usb_data.phy_mode = determine_usb_phy(prop);
-
- if (usb_dev_dr_host) {
- usb_dev_dr_host->dev.coherent_dma_mask = 0xffffffffUL;
- usb_dev_dr_host->dev.dma_mask = &usb_dev_dr_host->
- dev.coherent_dma_mask;
- if ((ret = platform_device_add_data(usb_dev_dr_host,
- &usb_data, sizeof(struct
- fsl_usb2_platform_data))))
- goto unreg_dr;
- }
- if (usb_dev_dr_client) {
- usb_dev_dr_client->dev.coherent_dma_mask = 0xffffffffUL;
- usb_dev_dr_client->dev.dma_mask = &usb_dev_dr_client->
- dev.coherent_dma_mask;
- if ((ret = platform_device_add_data(usb_dev_dr_client,
- &usb_data, sizeof(struct
- fsl_usb2_platform_data))))
- goto unreg_dr;
- }
- i++;
}
- return 0;
-
-unreg_dr:
- if (usb_dev_dr_host)
- platform_device_unregister(usb_dev_dr_host);
- if (usb_dev_dr_client)
- platform_device_unregister(usb_dev_dr_client);
-unreg_mph:
- if (usb_dev_mph)
- platform_device_unregister(usb_dev_mph);
-err:
- return ret;
-}
-
-arch_initcall(fsl_usb_of_init);
-
-#if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx)
-static __be32 __iomem *rstcr;
-static int __init setup_rstcr(void)
-{
- struct device_node *np;
- np = of_find_node_by_name(NULL, "global-utilities");
- if ((np && of_get_property(np, "fsl,has-rstcr", NULL))) {
- rstcr = of_iomap(np, 0) + 0xb0;
- if (!rstcr)
- printk (KERN_EMERG "Error: reset control register "
- "not mapped!\n");
- } else if (ppc_md.restart == fsl_rstcr_restart)
+ if (!rstcr && ppc_md.restart == fsl_rstcr_restart)
printk(KERN_ERR "No RSTCR register, warm reboot won't work\n");
if (np)
of_node_put(np);
+
return 0;
}
diff --git a/arch/powerpc/sysdev/mpc8xxx_gpio.c b/arch/powerpc/sysdev/mpc8xxx_gpio.c
index 2b69084d0f0c..c0ea05e87f1d 100644
--- a/arch/powerpc/sysdev/mpc8xxx_gpio.c
+++ b/arch/powerpc/sysdev/mpc8xxx_gpio.c
@@ -330,6 +330,9 @@ static int __init mpc8xxx_add_gpiochips(void)
for_each_compatible_node(np, NULL, "fsl,mpc8610-gpio")
mpc8xxx_add_controller(np);
+ for_each_compatible_node(np, NULL, "fsl,qoriq-gpio")
+ mpc8xxx_add_controller(np);
+
return 0;
}
arch_initcall(mpc8xxx_add_gpiochips);
diff --git a/arch/powerpc/sysdev/mpic_pasemi_msi.c b/arch/powerpc/sysdev/mpic_pasemi_msi.c
index 3b6a9a43718f..320ad5a9a25d 100644
--- a/arch/powerpc/sysdev/mpic_pasemi_msi.c
+++ b/arch/powerpc/sysdev/mpic_pasemi_msi.c
@@ -39,24 +39,24 @@
static struct mpic *msi_mpic;
-static void mpic_pasemi_msi_mask_irq(unsigned int irq)
+static void mpic_pasemi_msi_mask_irq(struct irq_data *data)
{
- pr_debug("mpic_pasemi_msi_mask_irq %d\n", irq);
- mask_msi_irq(irq);
- mpic_mask_irq(irq);
+ pr_debug("mpic_pasemi_msi_mask_irq %d\n", data->irq);
+ mask_msi_irq(data);
+ mpic_mask_irq(data->irq);
}
-static void mpic_pasemi_msi_unmask_irq(unsigned int irq)
+static void mpic_pasemi_msi_unmask_irq(struct irq_data *data)
{
- pr_debug("mpic_pasemi_msi_unmask_irq %d\n", irq);
- mpic_unmask_irq(irq);
- unmask_msi_irq(irq);
+ pr_debug("mpic_pasemi_msi_unmask_irq %d\n", data->irq);
+ mpic_unmask_irq(data->irq);
+ unmask_msi_irq(data);
}
static struct irq_chip mpic_pasemi_msi_chip = {
- .shutdown = mpic_pasemi_msi_mask_irq,
- .mask = mpic_pasemi_msi_mask_irq,
- .unmask = mpic_pasemi_msi_unmask_irq,
+ .irq_shutdown = mpic_pasemi_msi_mask_irq,
+ .irq_mask = mpic_pasemi_msi_mask_irq,
+ .irq_unmask = mpic_pasemi_msi_unmask_irq,
.eoi = mpic_end_irq,
.set_type = mpic_set_irq_type,
.set_affinity = mpic_set_affinity,
diff --git a/arch/powerpc/sysdev/mpic_u3msi.c b/arch/powerpc/sysdev/mpic_u3msi.c
index bcbfe79c704b..a2b028b4a202 100644
--- a/arch/powerpc/sysdev/mpic_u3msi.c
+++ b/arch/powerpc/sysdev/mpic_u3msi.c
@@ -23,22 +23,22 @@
/* A bit ugly, can we get this from the pci_dev somehow? */
static struct mpic *msi_mpic;
-static void mpic_u3msi_mask_irq(unsigned int irq)
+static void mpic_u3msi_mask_irq(struct irq_data *data)
{
- mask_msi_irq(irq);
- mpic_mask_irq(irq);
+ mask_msi_irq(data);
+ mpic_mask_irq(data->irq);
}
-static void mpic_u3msi_unmask_irq(unsigned int irq)
+static void mpic_u3msi_unmask_irq(struct irq_data *data)
{
- mpic_unmask_irq(irq);
- unmask_msi_irq(irq);
+ mpic_unmask_irq(data->irq);
+ unmask_msi_irq(data);
}
static struct irq_chip mpic_u3msi_chip = {
- .shutdown = mpic_u3msi_mask_irq,
- .mask = mpic_u3msi_mask_irq,
- .unmask = mpic_u3msi_unmask_irq,
+ .irq_shutdown = mpic_u3msi_mask_irq,
+ .irq_mask = mpic_u3msi_mask_irq,
+ .irq_unmask = mpic_u3msi_unmask_irq,
.eoi = mpic_end_irq,
.set_type = mpic_set_irq_type,
.set_affinity = mpic_set_affinity,
diff --git a/arch/powerpc/sysdev/pmi.c b/arch/powerpc/sysdev/pmi.c
index 24a0bb955b18..4260f368db52 100644
--- a/arch/powerpc/sysdev/pmi.c
+++ b/arch/powerpc/sysdev/pmi.c
@@ -114,7 +114,7 @@ static void pmi_notify_handlers(struct work_struct *work)
spin_lock(&data->handler_spinlock);
list_for_each_entry(handler, &data->handler, node) {
- pr_debug(KERN_INFO "pmi: notifying handler %p\n", handler);
+ pr_debug("pmi: notifying handler %p\n", handler);
if (handler->type == data->msg.type)
handler->handle_pmi_message(data->msg);
}
diff --git a/arch/powerpc/xmon/Makefile b/arch/powerpc/xmon/Makefile
index faa81b6a6612..c168c54e3c40 100644
--- a/arch/powerpc/xmon/Makefile
+++ b/arch/powerpc/xmon/Makefile
@@ -4,9 +4,7 @@ subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
GCOV_PROFILE := n
-ifdef CONFIG_PPC64
-EXTRA_CFLAGS += -mno-minimal-toc
-endif
+ccflags-$(CONFIG_PPC64) := -mno-minimal-toc
obj-y += xmon.o start.o nonstdio.o
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index f0777a47e3a5..75976a141947 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -95,6 +95,7 @@ config S390
select HAVE_KVM if 64BIT
select HAVE_ARCH_TRACEHOOK
select INIT_ALL_POSSIBLE
+ select HAVE_IRQ_WORK
select HAVE_PERF_EVENTS
select HAVE_KERNEL_GZIP
select HAVE_KERNEL_BZIP2
@@ -198,6 +199,13 @@ config HOTPLUG_CPU
can be controlled through /sys/devices/system/cpu/cpu#.
Say N if you want to disable CPU hotplug.
+config SCHED_BOOK
+ bool "Book scheduler support"
+ depends on SMP
+ help
+ Book scheduler support improves the CPU scheduler's decision making
+ when dealing with machines that have several books.
+
config MATHEMU
bool "IEEE FPU emulation"
depends on MARCH_G5
diff --git a/arch/s390/crypto/prng.c b/arch/s390/crypto/prng.c
index aa819dac2360..975e3ab13cb5 100644
--- a/arch/s390/crypto/prng.c
+++ b/arch/s390/crypto/prng.c
@@ -152,6 +152,7 @@ static const struct file_operations prng_fops = {
.open = &prng_open,
.release = NULL,
.read = &prng_read,
+ .llseek = noop_llseek,
};
static struct miscdevice prng_dev = {
diff --git a/arch/s390/hypfs/hypfs_diag.c b/arch/s390/hypfs/hypfs_diag.c
index 1211bb1d2f24..020e51c063d2 100644
--- a/arch/s390/hypfs/hypfs_diag.c
+++ b/arch/s390/hypfs/hypfs_diag.c
@@ -618,6 +618,7 @@ static const struct file_operations dbfs_d204_ops = {
.open = dbfs_d204_open,
.read = dbfs_d204_read,
.release = dbfs_d204_release,
+ .llseek = no_llseek,
};
static int hypfs_dbfs_init(void)
diff --git a/arch/s390/hypfs/hypfs_vm.c b/arch/s390/hypfs/hypfs_vm.c
index ee5ab1a578e7..26cf177f6a3a 100644
--- a/arch/s390/hypfs/hypfs_vm.c
+++ b/arch/s390/hypfs/hypfs_vm.c
@@ -275,6 +275,7 @@ static const struct file_operations dbfs_d2fc_ops = {
.open = dbfs_d2fc_open,
.read = dbfs_d2fc_read,
.release = dbfs_d2fc_release,
+ .llseek = no_llseek,
};
int hypfs_vm_init(void)
diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c
index 98a4a4c267a7..74d98670be27 100644
--- a/arch/s390/hypfs/inode.c
+++ b/arch/s390/hypfs/inode.c
@@ -449,6 +449,7 @@ static const struct file_operations hypfs_file_ops = {
.write = do_sync_write,
.aio_read = hypfs_aio_read,
.aio_write = hypfs_aio_write,
+ .llseek = no_llseek,
};
static struct file_system_type hypfs_type = {
diff --git a/arch/s390/include/asm/hardirq.h b/arch/s390/include/asm/hardirq.h
index 498bc3892385..881d94590aeb 100644
--- a/arch/s390/include/asm/hardirq.h
+++ b/arch/s390/include/asm/hardirq.h
@@ -12,10 +12,6 @@
#ifndef __ASM_HARDIRQ_H
#define __ASM_HARDIRQ_H
-#include <linux/threads.h>
-#include <linux/sched.h>
-#include <linux/cache.h>
-#include <linux/interrupt.h>
#include <asm/lowcore.h>
#define local_softirq_pending() (S390_lowcore.softirq_pending)
diff --git a/arch/s390/include/asm/ioctls.h b/arch/s390/include/asm/ioctls.h
index 2f3d8736361f..960a4c1ebdf1 100644
--- a/arch/s390/include/asm/ioctls.h
+++ b/arch/s390/include/asm/ioctls.h
@@ -1,94 +1,8 @@
-/*
- * include/asm-s390/ioctls.h
- *
- * S390 version
- *
- * Derived from "include/asm-i386/ioctls.h"
- */
-
#ifndef __ARCH_S390_IOCTLS_H__
#define __ARCH_S390_IOCTLS_H__
-#include <asm/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS 0x5401
-#define TCSETS 0x5402
-#define TCSETSW 0x5403
-#define TCSETSF 0x5404
-#define TCGETA 0x5405
-#define TCSETA 0x5406
-#define TCSETAW 0x5407
-#define TCSETAF 0x5408
-#define TCSBRK 0x5409
-#define TCXONC 0x540A
-#define TCFLSH 0x540B
-#define TIOCEXCL 0x540C
-#define TIOCNXCL 0x540D
-#define TIOCSCTTY 0x540E
-#define TIOCGPGRP 0x540F
-#define TIOCSPGRP 0x5410
-#define TIOCOUTQ 0x5411
-#define TIOCSTI 0x5412
-#define TIOCGWINSZ 0x5413
-#define TIOCSWINSZ 0x5414
-#define TIOCMGET 0x5415
-#define TIOCMBIS 0x5416
-#define TIOCMBIC 0x5417
-#define TIOCMSET 0x5418
-#define TIOCGSOFTCAR 0x5419
-#define TIOCSSOFTCAR 0x541A
-#define FIONREAD 0x541B
-#define TIOCINQ FIONREAD
-#define TIOCLINUX 0x541C
-#define TIOCCONS 0x541D
-#define TIOCGSERIAL 0x541E
-#define TIOCSSERIAL 0x541F
-#define TIOCPKT 0x5420
-#define FIONBIO 0x5421
-#define TIOCNOTTY 0x5422
-#define TIOCSETD 0x5423
-#define TIOCGETD 0x5424
-#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
-#define TIOCSBRK 0x5427 /* BSD compatibility */
-#define TIOCCBRK 0x5428 /* BSD compatibility */
-#define TIOCGSID 0x5429 /* Return the session ID of FD */
-#define TCGETS2 _IOR('T',0x2A, struct termios2)
-#define TCSETS2 _IOW('T',0x2B, struct termios2)
-#define TCSETSW2 _IOW('T',0x2C, struct termios2)
-#define TCSETSF2 _IOW('T',0x2D, struct termios2)
-#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
-#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
-#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */
-
-#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */
-#define FIOCLEX 0x5451
-#define FIOASYNC 0x5452
-#define TIOCSERCONFIG 0x5453
-#define TIOCSERGWILD 0x5454
-#define TIOCSERSWILD 0x5455
-#define TIOCGLCKTRMIOS 0x5456
-#define TIOCSLCKTRMIOS 0x5457
-#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
-#define TIOCSERGETLSR 0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
-#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
#define FIOQSIZE 0x545E
-/* Used for packet mode */
-#define TIOCPKT_DATA 0
-#define TIOCPKT_FLUSHREAD 1
-#define TIOCPKT_FLUSHWRITE 2
-#define TIOCPKT_STOP 4
-#define TIOCPKT_START 8
-#define TIOCPKT_NOSTOP 16
-#define TIOCPKT_DOSTOP 32
-#define TIOCPKT_IOCTL 64
-
-#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
+#include <asm-generic/ioctls.h>
#endif
diff --git a/arch/s390/include/asm/irqflags.h b/arch/s390/include/asm/irqflags.h
index 15b3ac253898..865d6d891ace 100644
--- a/arch/s390/include/asm/irqflags.h
+++ b/arch/s390/include/asm/irqflags.h
@@ -8,8 +8,8 @@
#include <linux/types.h>
-/* store then or system mask. */
-#define __raw_local_irq_stosm(__or) \
+/* store then OR system mask. */
+#define __arch_local_irq_stosm(__or) \
({ \
unsigned long __mask; \
asm volatile( \
@@ -18,8 +18,8 @@
__mask; \
})
-/* store then and system mask. */
-#define __raw_local_irq_stnsm(__and) \
+/* store then AND system mask. */
+#define __arch_local_irq_stnsm(__and) \
({ \
unsigned long __mask; \
asm volatile( \
@@ -29,39 +29,44 @@
})
/* set system mask. */
-#define __raw_local_irq_ssm(__mask) \
-({ \
- asm volatile("ssm %0" : : "Q" (__mask) : "memory"); \
-})
+static inline void __arch_local_irq_ssm(unsigned long flags)
+{
+ asm volatile("ssm %0" : : "Q" (flags) : "memory");
+}
-/* interrupt control.. */
-static inline unsigned long raw_local_irq_enable(void)
+static inline unsigned long arch_local_save_flags(void)
{
- return __raw_local_irq_stosm(0x03);
+ return __arch_local_irq_stosm(0x00);
}
-static inline unsigned long raw_local_irq_disable(void)
+static inline unsigned long arch_local_irq_save(void)
{
- return __raw_local_irq_stnsm(0xfc);
+ return __arch_local_irq_stnsm(0xfc);
}
-#define raw_local_save_flags(x) \
-do { \
- typecheck(unsigned long, x); \
- (x) = __raw_local_irq_stosm(0x00); \
-} while (0)
+static inline void arch_local_irq_disable(void)
+{
+ arch_local_irq_save();
+}
-static inline void raw_local_irq_restore(unsigned long flags)
+static inline void arch_local_irq_enable(void)
{
- __raw_local_irq_ssm(flags);
+ __arch_local_irq_stosm(0x03);
}
-static inline int raw_irqs_disabled_flags(unsigned long flags)
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+ __arch_local_irq_ssm(flags);
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
{
return !(flags & (3UL << (BITS_PER_LONG - 8)));
}
-/* For spinlocks etc */
-#define raw_local_irq_save(x) ((x) = raw_local_irq_disable())
+static inline bool arch_irqs_disabled(void)
+{
+ return arch_irqs_disabled_flags(arch_local_save_flags());
+}
#endif /* __ASM_IRQFLAGS_H */
diff --git a/arch/s390/include/asm/perf_event.h b/arch/s390/include/asm/perf_event.h
index 3840cbe77637..a75f168d2718 100644
--- a/arch/s390/include/asm/perf_event.h
+++ b/arch/s390/include/asm/perf_event.h
@@ -4,7 +4,6 @@
* Copyright 2009 Martin Schwidefsky, IBM Corporation.
*/
-static inline void set_perf_event_pending(void) {}
-static inline void clear_perf_event_pending(void) {}
+/* Empty, just to avoid compiling error */
#define PERF_EVENT_INDEX_OFFSET 0
diff --git a/arch/s390/include/asm/qdio.h b/arch/s390/include/asm/qdio.h
index 2ba630276295..46e96bc1f5a1 100644
--- a/arch/s390/include/asm/qdio.h
+++ b/arch/s390/include/asm/qdio.h
@@ -360,6 +360,7 @@ struct qdio_initialize {
unsigned int no_output_qs;
qdio_handler_t *input_handler;
qdio_handler_t *output_handler;
+ void (*queue_start_poll) (struct ccw_device *, int, unsigned long);
unsigned long int_parm;
void **input_sbal_addr_array;
void **output_sbal_addr_array;
@@ -377,11 +378,13 @@ struct qdio_initialize {
extern int qdio_allocate(struct qdio_initialize *);
extern int qdio_establish(struct qdio_initialize *);
extern int qdio_activate(struct ccw_device *);
-
-extern int do_QDIO(struct ccw_device *cdev, unsigned int callflags,
- int q_nr, unsigned int bufnr, unsigned int count);
-extern int qdio_shutdown(struct ccw_device*, int);
+extern int do_QDIO(struct ccw_device *, unsigned int, int, unsigned int,
+ unsigned int);
+extern int qdio_start_irq(struct ccw_device *, int);
+extern int qdio_stop_irq(struct ccw_device *, int);
+extern int qdio_get_next_buffers(struct ccw_device *, int, int *, int *);
+extern int qdio_shutdown(struct ccw_device *, int);
extern int qdio_free(struct ccw_device *);
-extern int qdio_get_ssqd_desc(struct ccw_device *dev, struct qdio_ssqd_desc*);
+extern int qdio_get_ssqd_desc(struct ccw_device *, struct qdio_ssqd_desc *);
#endif /* __QDIO_H__ */
diff --git a/arch/s390/include/asm/system.h b/arch/s390/include/asm/system.h
index cef66210c846..1f2ebc4afd82 100644
--- a/arch/s390/include/asm/system.h
+++ b/arch/s390/include/asm/system.h
@@ -97,7 +97,6 @@ static inline void restore_access_regs(unsigned int *acrs)
extern void account_vtime(struct task_struct *, struct task_struct *);
extern void account_tick_vtime(struct task_struct *);
-extern void account_system_vtime(struct task_struct *);
#ifdef CONFIG_PFAULT
extern void pfault_irq_init(void);
@@ -399,7 +398,7 @@ static inline unsigned long __cmpxchg_local(volatile void *ptr,
static inline void
__set_psw_mask(unsigned long mask)
{
- __load_psw_mask(mask | (__raw_local_irq_stosm(0x00) & ~(-1UL >> 8)));
+ __load_psw_mask(mask | (arch_local_save_flags() & ~(-1UL >> 8)));
}
#define local_mcck_enable() __set_psw_mask(psw_kernel_bits)
diff --git a/arch/s390/include/asm/topology.h b/arch/s390/include/asm/topology.h
index 831bd033ea77..051107a2c5e2 100644
--- a/arch/s390/include/asm/topology.h
+++ b/arch/s390/include/asm/topology.h
@@ -3,15 +3,32 @@
#include <linux/cpumask.h>
-#define mc_capable() (1)
-
-const struct cpumask *cpu_coregroup_mask(unsigned int cpu);
-
extern unsigned char cpu_core_id[NR_CPUS];
extern cpumask_t cpu_core_map[NR_CPUS];
+static inline const struct cpumask *cpu_coregroup_mask(unsigned int cpu)
+{
+ return &cpu_core_map[cpu];
+}
+
#define topology_core_id(cpu) (cpu_core_id[cpu])
#define topology_core_cpumask(cpu) (&cpu_core_map[cpu])
+#define mc_capable() (1)
+
+#ifdef CONFIG_SCHED_BOOK
+
+extern unsigned char cpu_book_id[NR_CPUS];
+extern cpumask_t cpu_book_map[NR_CPUS];
+
+static inline const struct cpumask *cpu_book_mask(unsigned int cpu)
+{
+ return &cpu_book_map[cpu];
+}
+
+#define topology_book_id(cpu) (cpu_book_id[cpu])
+#define topology_book_cpumask(cpu) (&cpu_book_map[cpu])
+
+#endif /* CONFIG_SCHED_BOOK */
int topology_set_cpu_management(int fc);
void topology_schedule_update(void);
@@ -30,6 +47,8 @@ static inline void s390_init_cpu_topology(void)
};
#endif
+#define SD_BOOK_INIT SD_CPU_INIT
+
#include <asm-generic/topology.h>
#endif /* _ASM_S390_TOPOLOGY_H */
diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c
index 98192261491d..5ad6bc078bfd 100644
--- a/arch/s390/kernel/debug.c
+++ b/arch/s390/kernel/debug.c
@@ -174,6 +174,7 @@ static const struct file_operations debug_file_ops = {
.write = debug_input,
.open = debug_open,
.release = debug_close,
+ .llseek = no_llseek,
};
static struct dentry *debug_debugfs_root_entry;
diff --git a/arch/s390/kernel/mem_detect.c b/arch/s390/kernel/mem_detect.c
index 559af0d07878..0fbe4e32f7ba 100644
--- a/arch/s390/kernel/mem_detect.c
+++ b/arch/s390/kernel/mem_detect.c
@@ -54,11 +54,11 @@ void detect_memory_layout(struct mem_chunk chunk[])
* right thing and we don't get scheduled away with low address
* protection disabled.
*/
- flags = __raw_local_irq_stnsm(0xf8);
+ flags = __arch_local_irq_stnsm(0xf8);
__ctl_store(cr0, 0, 0);
__ctl_clear_bit(0, 28);
find_memory_chunks(chunk);
__ctl_load(cr0, 0, 0);
- __raw_local_irq_ssm(flags);
+ arch_local_irq_restore(flags);
}
EXPORT_SYMBOL(detect_memory_layout);
diff --git a/arch/s390/kernel/module.c b/arch/s390/kernel/module.c
index 22cfd634c355..f7167ee4604c 100644
--- a/arch/s390/kernel/module.c
+++ b/arch/s390/kernel/module.c
@@ -407,10 +407,9 @@ int module_finalize(const Elf_Ehdr *hdr,
{
vfree(me->arch.syminfo);
me->arch.syminfo = NULL;
- return module_bug_finalize(hdr, sechdrs, me);
+ return 0;
}
void module_arch_cleanup(struct module *mod)
{
- module_bug_cleanup(mod);
}
diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c
index bcef00766a64..13559c993847 100644
--- a/arch/s390/kernel/topology.c
+++ b/arch/s390/kernel/topology.c
@@ -57,8 +57,8 @@ struct tl_info {
union tl_entry tle[0];
};
-struct core_info {
- struct core_info *next;
+struct mask_info {
+ struct mask_info *next;
unsigned char id;
cpumask_t mask;
};
@@ -66,7 +66,6 @@ struct core_info {
static int topology_enabled;
static void topology_work_fn(struct work_struct *work);
static struct tl_info *tl_info;
-static struct core_info core_info;
static int machine_has_topology;
static struct timer_list topology_timer;
static void set_topology_timer(void);
@@ -74,38 +73,37 @@ static DECLARE_WORK(topology_work, topology_work_fn);
/* topology_lock protects the core linked list */
static DEFINE_SPINLOCK(topology_lock);
+static struct mask_info core_info;
cpumask_t cpu_core_map[NR_CPUS];
unsigned char cpu_core_id[NR_CPUS];
-static cpumask_t cpu_coregroup_map(unsigned int cpu)
+#ifdef CONFIG_SCHED_BOOK
+static struct mask_info book_info;
+cpumask_t cpu_book_map[NR_CPUS];
+unsigned char cpu_book_id[NR_CPUS];
+#endif
+
+static cpumask_t cpu_group_map(struct mask_info *info, unsigned int cpu)
{
- struct core_info *core = &core_info;
- unsigned long flags;
cpumask_t mask;
cpus_clear(mask);
if (!topology_enabled || !machine_has_topology)
return cpu_possible_map;
- spin_lock_irqsave(&topology_lock, flags);
- while (core) {
- if (cpu_isset(cpu, core->mask)) {
- mask = core->mask;
+ while (info) {
+ if (cpu_isset(cpu, info->mask)) {
+ mask = info->mask;
break;
}
- core = core->next;
+ info = info->next;
}
- spin_unlock_irqrestore(&topology_lock, flags);
if (cpus_empty(mask))
mask = cpumask_of_cpu(cpu);
return mask;
}
-const struct cpumask *cpu_coregroup_mask(unsigned int cpu)
-{
- return &cpu_core_map[cpu];
-}
-
-static void add_cpus_to_core(struct tl_cpu *tl_cpu, struct core_info *core)
+static void add_cpus_to_mask(struct tl_cpu *tl_cpu, struct mask_info *book,
+ struct mask_info *core)
{
unsigned int cpu;
@@ -117,23 +115,35 @@ static void add_cpus_to_core(struct tl_cpu *tl_cpu, struct core_info *core)
rcpu = CPU_BITS - 1 - cpu + tl_cpu->origin;
for_each_present_cpu(lcpu) {
- if (cpu_logical_map(lcpu) == rcpu) {
- cpu_set(lcpu, core->mask);
- cpu_core_id[lcpu] = core->id;
- smp_cpu_polarization[lcpu] = tl_cpu->pp;
- }
+ if (cpu_logical_map(lcpu) != rcpu)
+ continue;
+#ifdef CONFIG_SCHED_BOOK
+ cpu_set(lcpu, book->mask);
+ cpu_book_id[lcpu] = book->id;
+#endif
+ cpu_set(lcpu, core->mask);
+ cpu_core_id[lcpu] = core->id;
+ smp_cpu_polarization[lcpu] = tl_cpu->pp;
}
}
}
-static void clear_cores(void)
+static void clear_masks(void)
{
- struct core_info *core = &core_info;
+ struct mask_info *info;
- while (core) {
- cpus_clear(core->mask);
- core = core->next;
+ info = &core_info;
+ while (info) {
+ cpus_clear(info->mask);
+ info = info->next;
+ }
+#ifdef CONFIG_SCHED_BOOK
+ info = &book_info;
+ while (info) {
+ cpus_clear(info->mask);
+ info = info->next;
}
+#endif
}
static union tl_entry *next_tle(union tl_entry *tle)
@@ -146,29 +156,36 @@ static union tl_entry *next_tle(union tl_entry *tle)
static void tl_to_cores(struct tl_info *info)
{
+#ifdef CONFIG_SCHED_BOOK
+ struct mask_info *book = &book_info;
+#else
+ struct mask_info *book = NULL;
+#endif
+ struct mask_info *core = &core_info;
union tl_entry *tle, *end;
- struct core_info *core = &core_info;
+
spin_lock_irq(&topology_lock);
- clear_cores();
+ clear_masks();
tle = info->tle;
end = (union tl_entry *)((unsigned long)info + info->length);
while (tle < end) {
switch (tle->nl) {
- case 5:
- case 4:
- case 3:
+#ifdef CONFIG_SCHED_BOOK
case 2:
+ book = book->next;
+ book->id = tle->container.id;
break;
+#endif
case 1:
core = core->next;
core->id = tle->container.id;
break;
case 0:
- add_cpus_to_core(&tle->cpu, core);
+ add_cpus_to_mask(&tle->cpu, book, core);
break;
default:
- clear_cores();
+ clear_masks();
machine_has_topology = 0;
goto out;
}
@@ -221,10 +238,29 @@ int topology_set_cpu_management(int fc)
static void update_cpu_core_map(void)
{
+ unsigned long flags;
int cpu;
- for_each_possible_cpu(cpu)
- cpu_core_map[cpu] = cpu_coregroup_map(cpu);
+ spin_lock_irqsave(&topology_lock, flags);
+ for_each_possible_cpu(cpu) {
+ cpu_core_map[cpu] = cpu_group_map(&core_info, cpu);
+#ifdef CONFIG_SCHED_BOOK
+ cpu_book_map[cpu] = cpu_group_map(&book_info, cpu);
+#endif
+ }
+ spin_unlock_irqrestore(&topology_lock, flags);
+}
+
+static void store_topology(struct tl_info *info)
+{
+#ifdef CONFIG_SCHED_BOOK
+ int rc;
+
+ rc = stsi(info, 15, 1, 3);
+ if (rc != -ENOSYS)
+ return;
+#endif
+ stsi(info, 15, 1, 2);
}
int arch_update_cpu_topology(void)
@@ -238,7 +274,7 @@ int arch_update_cpu_topology(void)
topology_update_polarization_simple();
return 0;
}
- stsi(info, 15, 1, 2);
+ store_topology(info);
tl_to_cores(info);
update_cpu_core_map();
for_each_online_cpu(cpu) {
@@ -299,12 +335,24 @@ out:
}
__initcall(init_topology_update);
+static void alloc_masks(struct tl_info *info, struct mask_info *mask, int offset)
+{
+ int i, nr_masks;
+
+ nr_masks = info->mag[NR_MAG - offset];
+ for (i = 0; i < info->mnest - offset; i++)
+ nr_masks *= info->mag[NR_MAG - offset - 1 - i];
+ nr_masks = max(nr_masks, 1);
+ for (i = 0; i < nr_masks; i++) {
+ mask->next = alloc_bootmem(sizeof(struct mask_info));
+ mask = mask->next;
+ }
+}
+
void __init s390_init_cpu_topology(void)
{
unsigned long long facility_bits;
struct tl_info *info;
- struct core_info *core;
- int nr_cores;
int i;
if (stfle(&facility_bits, 1) <= 0)
@@ -315,25 +363,13 @@ void __init s390_init_cpu_topology(void)
tl_info = alloc_bootmem_pages(PAGE_SIZE);
info = tl_info;
- stsi(info, 15, 1, 2);
-
- nr_cores = info->mag[NR_MAG - 2];
- for (i = 0; i < info->mnest - 2; i++)
- nr_cores *= info->mag[NR_MAG - 3 - i];
-
+ store_topology(info);
pr_info("The CPU configuration topology of the machine is:");
for (i = 0; i < NR_MAG; i++)
printk(" %d", info->mag[i]);
printk(" / %d\n", info->mnest);
-
- core = &core_info;
- for (i = 0; i < nr_cores; i++) {
- core->next = alloc_bootmem(sizeof(struct core_info));
- core = core->next;
- if (!core)
- goto error;
- }
- return;
-error:
- machine_has_topology = 0;
+ alloc_masks(info, &core_info, 2);
+#ifdef CONFIG_SCHED_BOOK
+ alloc_masks(info, &book_info, 3);
+#endif
}
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index 30eb6d02ddb8..94b8ba2ec857 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -50,7 +50,6 @@ EXPORT_SYMBOL(empty_zero_page);
*/
void __init paging_init(void)
{
- static const int ssm_mask = 0x04000000L;
unsigned long max_zone_pfns[MAX_NR_ZONES];
unsigned long pgd_type;
@@ -72,7 +71,7 @@ void __init paging_init(void)
__ctl_load(S390_lowcore.kernel_asce, 1, 1);
__ctl_load(S390_lowcore.kernel_asce, 7, 7);
__ctl_load(S390_lowcore.kernel_asce, 13, 13);
- __raw_local_irq_ssm(ssm_mask);
+ arch_local_irq_restore(4UL << (BITS_PER_LONG - 8));
atomic_set(&init_mm.context.attach_count, 1);
diff --git a/arch/s390/mm/maccess.c b/arch/s390/mm/maccess.c
index a8c2af8c650f..71a4b0d34be0 100644
--- a/arch/s390/mm/maccess.c
+++ b/arch/s390/mm/maccess.c
@@ -71,7 +71,7 @@ int memcpy_real(void *dest, void *src, size_t count)
if (!count)
return 0;
- flags = __raw_local_irq_stnsm(0xf8UL);
+ flags = __arch_local_irq_stnsm(0xf8UL);
asm volatile (
"0: mvcle %1,%2,0x0\n"
"1: jo 0b\n"
@@ -82,6 +82,6 @@ int memcpy_real(void *dest, void *src, size_t count)
"+d" (_len2), "=m" (*((long *) dest))
: "m" (*((long *) src))
: "cc", "memory");
- __raw_local_irq_ssm(flags);
+ arch_local_irq_restore(flags);
return rc;
}
diff --git a/arch/score/include/asm/irqflags.h b/arch/score/include/asm/irqflags.h
index 690a6cae7294..5c7563891e28 100644
--- a/arch/score/include/asm/irqflags.h
+++ b/arch/score/include/asm/irqflags.h
@@ -3,107 +3,118 @@
#ifndef __ASSEMBLY__
-#define raw_local_irq_save(x) \
-{ \
- __asm__ __volatile__( \
- "mfcr r8, cr0;" \
- "li r9, 0xfffffffe;" \
- "nop;" \
- "mv %0, r8;" \
- "and r8, r8, r9;" \
- "mtcr r8, cr0;" \
- "nop;" \
- "nop;" \
- "nop;" \
- "nop;" \
- "nop;" \
- : "=r" (x) \
- : \
- : "r8", "r9" \
- ); \
+#include <linux/types.h>
+
+static inline unsigned long arch_local_save_flags(void)
+{
+ unsigned long flags;
+
+ asm volatile(
+ " mfcr r8, cr0 \n"
+ " nop \n"
+ " nop \n"
+ " mv %0, r8 \n"
+ " nop \n"
+ " nop \n"
+ " nop \n"
+ " nop \n"
+ " nop \n"
+ " ldi r9, 0x1 \n"
+ " and %0, %0, r9 \n"
+ : "=r" (flags)
+ :
+ : "r8", "r9");
+ return flags;
}
-#define raw_local_irq_restore(x) \
-{ \
- __asm__ __volatile__( \
- "mfcr r8, cr0;" \
- "ldi r9, 0x1;" \
- "and %0, %0, r9;" \
- "or r8, r8, %0;" \
- "mtcr r8, cr0;" \
- "nop;" \
- "nop;" \
- "nop;" \
- "nop;" \
- "nop;" \
- : \
- : "r"(x) \
- : "r8", "r9" \
- ); \
+static inline unsigned long arch_local_irq_save(void)
+{
+ unsigned long flags
+
+ asm volatile(
+ " mfcr r8, cr0 \n"
+ " li r9, 0xfffffffe \n"
+ " nop \n"
+ " mv %0, r8 \n"
+ " and r8, r8, r9 \n"
+ " mtcr r8, cr0 \n"
+ " nop \n"
+ " nop \n"
+ " nop \n"
+ " nop \n"
+ " nop \n"
+ : "=r" (flags)
+ :
+ : "r8", "r9", "memory");
+
+ return flags;
}
-#define raw_local_irq_enable(void) \
-{ \
- __asm__ __volatile__( \
- "mfcr\tr8,cr0;" \
- "nop;" \
- "nop;" \
- "ori\tr8,0x1;" \
- "mtcr\tr8,cr0;" \
- "nop;" \
- "nop;" \
- "nop;" \
- "nop;" \
- "nop;" \
- : \
- : \
- : "r8"); \
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+ asm volatile(
+ " mfcr r8, cr0 \n"
+ " ldi r9, 0x1 \n"
+ " and %0, %0, r9 \n"
+ " or r8, r8, %0 \n"
+ " mtcr r8, cr0 \n"
+ " nop \n"
+ " nop \n"
+ " nop \n"
+ " nop \n"
+ " nop \n"
+ :
+ : "r"(flags)
+ : "r8", "r9", "memory");
}
-#define raw_local_irq_disable(void) \
-{ \
- __asm__ __volatile__( \
- "mfcr\tr8,cr0;" \
- "nop;" \
- "nop;" \
- "srli\tr8,r8,1;" \
- "slli\tr8,r8,1;" \
- "mtcr\tr8,cr0;" \
- "nop;" \
- "nop;" \
- "nop;" \
- "nop;" \
- "nop;" \
- : \
- : \
- : "r8"); \
+static inline void arch_local_irq_enable(void)
+{
+ asm volatile(
+ " mfcr r8,cr0 \n"
+ " nop \n"
+ " nop \n"
+ " ori r8,0x1 \n"
+ " mtcr r8,cr0 \n"
+ " nop \n"
+ " nop \n"
+ " nop \n"
+ " nop \n"
+ " nop \n"
+ :
+ :
+ : "r8", "memory");
}
-#define raw_local_save_flags(x) \
-{ \
- __asm__ __volatile__( \
- "mfcr r8, cr0;" \
- "nop;" \
- "nop;" \
- "mv %0, r8;" \
- "nop;" \
- "nop;" \
- "nop;" \
- "nop;" \
- "nop;" \
- "ldi r9, 0x1;" \
- "and %0, %0, r9;" \
- : "=r" (x) \
- : \
- : "r8", "r9" \
- ); \
+static inline void arch_local_irq_disable(void)
+{
+ asm volatile(
+ " mfcr r8,cr0 \n"
+ " nop \n"
+ " nop \n"
+ " srli r8,r8,1 \n"
+ " slli r8,r8,1 \n"
+ " mtcr r8,cr0 \n"
+ " nop \n"
+ " nop \n"
+ " nop \n"
+ " nop \n"
+ " nop \n"
+ :
+ :
+ : "r8", "memory");
}
-static inline int raw_irqs_disabled_flags(unsigned long flags)
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
{
return !(flags & 1);
}
-#endif
+static inline bool arch_irqs_disabled(void)
+{
+ return arch_irqs_disabled_flags(arch_local_save_flags());
+}
+
+#endif /* __ASSEMBLY__ */
#endif /* _ASM_SCORE_IRQFLAGS_H */
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 33990fa95af0..35b6879628a0 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -16,6 +16,7 @@ config SUPERH
select HAVE_ARCH_TRACEHOOK
select HAVE_DMA_API_DEBUG
select HAVE_DMA_ATTRS
+ select HAVE_IRQ_WORK
select HAVE_PERF_EVENTS
select PERF_USE_VMALLOC
select HAVE_KERNEL_GZIP
@@ -249,6 +250,11 @@ config ARCH_SHMOBILE
select PM
select PM_RUNTIME
+config CPU_HAS_PMU
+ depends on CPU_SH4 || CPU_SH4A
+ default y
+ bool
+
if SUPERH32
choice
@@ -738,6 +744,14 @@ config GUSA_RB
LLSC, this should be more efficient than the other alternative of
disabling interrupts around the atomic sequence.
+config HW_PERF_EVENTS
+ bool "Enable hardware performance counter support for perf events"
+ depends on PERF_EVENTS && CPU_HAS_PMU
+ default y
+ help
+ Enable hardware performance counter support for perf events. If
+ disabled, perf events will use software events only.
+
source "drivers/sh/Kconfig"
endmenu
diff --git a/arch/sh/boards/mach-landisk/gio.c b/arch/sh/boards/mach-landisk/gio.c
index 01e6abb769b9..8132dff078fb 100644
--- a/arch/sh/boards/mach-landisk/gio.c
+++ b/arch/sh/boards/mach-landisk/gio.c
@@ -128,6 +128,7 @@ static const struct file_operations gio_fops = {
.open = gio_open, /* open */
.release = gio_close, /* release */
.unlocked_ioctl = gio_ioctl,
+ .llseek = noop_llseek,
};
static int __init gio_init(void)
diff --git a/arch/sh/include/asm/irqflags.h b/arch/sh/include/asm/irqflags.h
index a741153b41c2..43b7608606c3 100644
--- a/arch/sh/include/asm/irqflags.h
+++ b/arch/sh/include/asm/irqflags.h
@@ -1,8 +1,8 @@
#ifndef __ASM_SH_IRQFLAGS_H
#define __ASM_SH_IRQFLAGS_H
-#define RAW_IRQ_DISABLED 0xf0
-#define RAW_IRQ_ENABLED 0x00
+#define ARCH_IRQ_DISABLED 0xf0
+#define ARCH_IRQ_ENABLED 0x00
#include <asm-generic/irqflags.h>
diff --git a/arch/sh/include/asm/memblock.h b/arch/sh/include/asm/memblock.h
index dfe683b88075..e87063fad2ea 100644
--- a/arch/sh/include/asm/memblock.h
+++ b/arch/sh/include/asm/memblock.h
@@ -1,6 +1,4 @@
#ifndef __ASM_SH_MEMBLOCK_H
#define __ASM_SH_MEMBLOCK_H
-#define MEMBLOCK_REAL_LIMIT 0
-
#endif /* __ASM_SH_MEMBLOCK_H */
diff --git a/arch/sh/include/asm/perf_event.h b/arch/sh/include/asm/perf_event.h
index 3d0c9f36d150..14308bed7ea5 100644
--- a/arch/sh/include/asm/perf_event.h
+++ b/arch/sh/include/asm/perf_event.h
@@ -26,11 +26,4 @@ extern int register_sh_pmu(struct sh_pmu *);
extern int reserve_pmc_hardware(void);
extern void release_pmc_hardware(void);
-static inline void set_perf_event_pending(void)
-{
- /* Nothing to see here, move along. */
-}
-
-#define PERF_EVENT_INDEX_OFFSET 0
-
#endif /* __ASM_SH_PERF_EVENT_H */
diff --git a/arch/sh/include/asm/syscalls_32.h b/arch/sh/include/asm/syscalls_32.h
index be201fdc97aa..ae717e3c26d6 100644
--- a/arch/sh/include/asm/syscalls_32.h
+++ b/arch/sh/include/asm/syscalls_32.h
@@ -19,9 +19,10 @@ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
asmlinkage int sys_vfork(unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7,
struct pt_regs __regs);
-asmlinkage int sys_execve(const char __user *ufilename, char __user * __user *uargv,
- char __user * __user *uenvp, unsigned long r7,
- struct pt_regs __regs);
+asmlinkage int sys_execve(const char __user *ufilename,
+ const char __user *const __user *uargv,
+ const char __user *const __user *uenvp,
+ unsigned long r7, struct pt_regs __regs);
asmlinkage int sys_sigsuspend(old_sigset_t mask, unsigned long r5,
unsigned long r6, unsigned long r7,
struct pt_regs __regs);
diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c
index 257de1f0692b..ae5bac39b896 100644
--- a/arch/sh/kernel/irq.c
+++ b/arch/sh/kernel/irq.c
@@ -290,7 +290,7 @@ void __init init_IRQ(void)
int __init arch_probe_nr_irqs(void)
{
nr_irqs = sh_mv.mv_nr_irqs;
- return 0;
+ return NR_IRQS_LEGACY;
}
#endif
diff --git a/arch/sh/kernel/irq_32.c b/arch/sh/kernel/irq_32.c
index e33ab15831f9..e5a755be9129 100644
--- a/arch/sh/kernel/irq_32.c
+++ b/arch/sh/kernel/irq_32.c
@@ -10,11 +10,11 @@
#include <linux/irqflags.h>
#include <linux/module.h>
-void notrace raw_local_irq_restore(unsigned long flags)
+void notrace arch_local_irq_restore(unsigned long flags)
{
unsigned long __dummy0, __dummy1;
- if (flags == RAW_IRQ_DISABLED) {
+ if (flags == ARCH_IRQ_DISABLED) {
__asm__ __volatile__ (
"stc sr, %0\n\t"
"or #0xf0, %0\n\t"
@@ -33,14 +33,14 @@ void notrace raw_local_irq_restore(unsigned long flags)
#endif
"ldc %0, sr\n\t"
: "=&r" (__dummy0), "=r" (__dummy1)
- : "1" (~RAW_IRQ_DISABLED)
+ : "1" (~ARCH_IRQ_DISABLED)
: "memory"
);
}
}
-EXPORT_SYMBOL(raw_local_irq_restore);
+EXPORT_SYMBOL(arch_local_irq_restore);
-unsigned long notrace __raw_local_save_flags(void)
+unsigned long notrace arch_local_save_flags(void)
{
unsigned long flags;
@@ -54,4 +54,4 @@ unsigned long notrace __raw_local_save_flags(void)
return flags;
}
-EXPORT_SYMBOL(__raw_local_save_flags);
+EXPORT_SYMBOL(arch_local_save_flags);
diff --git a/arch/sh/kernel/module.c b/arch/sh/kernel/module.c
index 43adddfe4c04..ae0be697a89e 100644
--- a/arch/sh/kernel/module.c
+++ b/arch/sh/kernel/module.c
@@ -149,13 +149,11 @@ int module_finalize(const Elf_Ehdr *hdr,
int ret = 0;
ret |= module_dwarf_finalize(hdr, sechdrs, me);
- ret |= module_bug_finalize(hdr, sechdrs, me);
return ret;
}
void module_arch_cleanup(struct module *mod)
{
- module_bug_cleanup(mod);
module_dwarf_cleanup(mod);
}
diff --git a/arch/sh/kernel/perf_callchain.c b/arch/sh/kernel/perf_callchain.c
index a9dd3abde28e..d5ca1ef50fa9 100644
--- a/arch/sh/kernel/perf_callchain.c
+++ b/arch/sh/kernel/perf_callchain.c
@@ -14,11 +14,6 @@
#include <asm/unwinder.h>
#include <asm/ptrace.h>
-static inline void callchain_store(struct perf_callchain_entry *entry, u64 ip)
-{
- if (entry->nr < PERF_MAX_STACK_DEPTH)
- entry->ip[entry->nr++] = ip;
-}
static void callchain_warning(void *data, char *msg)
{
@@ -39,7 +34,7 @@ static void callchain_address(void *data, unsigned long addr, int reliable)
struct perf_callchain_entry *entry = data;
if (reliable)
- callchain_store(entry, addr);
+ perf_callchain_store(entry, addr);
}
static const struct stacktrace_ops callchain_ops = {
@@ -49,47 +44,10 @@ static const struct stacktrace_ops callchain_ops = {
.address = callchain_address,
};
-static void
-perf_callchain_kernel(struct pt_regs *regs, struct perf_callchain_entry *entry)
+void
+perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs)
{
- callchain_store(entry, PERF_CONTEXT_KERNEL);
- callchain_store(entry, regs->pc);
+ perf_callchain_store(entry, regs->pc);
unwind_stack(NULL, regs, NULL, &callchain_ops, entry);
}
-
-static void
-perf_do_callchain(struct pt_regs *regs, struct perf_callchain_entry *entry)
-{
- int is_user;
-
- if (!regs)
- return;
-
- is_user = user_mode(regs);
-
- if (is_user && current->state != TASK_RUNNING)
- return;
-
- /*
- * Only the kernel side is implemented for now.
- */
- if (!is_user)
- perf_callchain_kernel(regs, entry);
-}
-
-/*
- * No need for separate IRQ and NMI entries.
- */
-static DEFINE_PER_CPU(struct perf_callchain_entry, callchain);
-
-struct perf_callchain_entry *perf_callchain(struct pt_regs *regs)
-{
- struct perf_callchain_entry *entry = &__get_cpu_var(callchain);
-
- entry->nr = 0;
-
- perf_do_callchain(regs, entry);
-
- return entry;
-}
diff --git a/arch/sh/kernel/perf_event.c b/arch/sh/kernel/perf_event.c
index 7a3dc3567258..5a4b33435650 100644
--- a/arch/sh/kernel/perf_event.c
+++ b/arch/sh/kernel/perf_event.c
@@ -59,6 +59,24 @@ static inline int sh_pmu_initialized(void)
return !!sh_pmu;
}
+const char *perf_pmu_name(void)
+{
+ if (!sh_pmu)
+ return NULL;
+
+ return sh_pmu->name;
+}
+EXPORT_SYMBOL_GPL(perf_pmu_name);
+
+int perf_num_counters(void)
+{
+ if (!sh_pmu)
+ return 0;
+
+ return sh_pmu->num_events;
+}
+EXPORT_SYMBOL_GPL(perf_num_counters);
+
/*
* Release the PMU if this is the last perf_event.
*/
@@ -206,50 +224,80 @@ again:
local64_add(delta, &event->count);
}
-static void sh_pmu_disable(struct perf_event *event)
+static void sh_pmu_stop(struct perf_event *event, int flags)
{
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
struct hw_perf_event *hwc = &event->hw;
int idx = hwc->idx;
- clear_bit(idx, cpuc->active_mask);
- sh_pmu->disable(hwc, idx);
+ if (!(event->hw.state & PERF_HES_STOPPED)) {
+ sh_pmu->disable(hwc, idx);
+ cpuc->events[idx] = NULL;
+ event->hw.state |= PERF_HES_STOPPED;
+ }
+
+ if ((flags & PERF_EF_UPDATE) && !(event->hw.state & PERF_HES_UPTODATE)) {
+ sh_perf_event_update(event, &event->hw, idx);
+ event->hw.state |= PERF_HES_UPTODATE;
+ }
+}
+
+static void sh_pmu_start(struct perf_event *event, int flags)
+{
+ struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+ struct hw_perf_event *hwc = &event->hw;
+ int idx = hwc->idx;
+
+ if (WARN_ON_ONCE(idx == -1))
+ return;
+
+ if (flags & PERF_EF_RELOAD)
+ WARN_ON_ONCE(!(event->hw.state & PERF_HES_UPTODATE));
- barrier();
+ cpuc->events[idx] = event;
+ event->hw.state = 0;
+ sh_pmu->enable(hwc, idx);
+}
- sh_perf_event_update(event, &event->hw, idx);
+static void sh_pmu_del(struct perf_event *event, int flags)
+{
+ struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
- cpuc->events[idx] = NULL;
- clear_bit(idx, cpuc->used_mask);
+ sh_pmu_stop(event, PERF_EF_UPDATE);
+ __clear_bit(event->hw.idx, cpuc->used_mask);
perf_event_update_userpage(event);
}
-static int sh_pmu_enable(struct perf_event *event)
+static int sh_pmu_add(struct perf_event *event, int flags)
{
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
struct hw_perf_event *hwc = &event->hw;
int idx = hwc->idx;
+ int ret = -EAGAIN;
+
+ perf_pmu_disable(event->pmu);
- if (test_and_set_bit(idx, cpuc->used_mask)) {
+ if (__test_and_set_bit(idx, cpuc->used_mask)) {
idx = find_first_zero_bit(cpuc->used_mask, sh_pmu->num_events);
if (idx == sh_pmu->num_events)
- return -EAGAIN;
+ goto out;
- set_bit(idx, cpuc->used_mask);
+ __set_bit(idx, cpuc->used_mask);
hwc->idx = idx;
}
sh_pmu->disable(hwc, idx);
- cpuc->events[idx] = event;
- set_bit(idx, cpuc->active_mask);
-
- sh_pmu->enable(hwc, idx);
+ event->hw.state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
+ if (flags & PERF_EF_START)
+ sh_pmu_start(event, PERF_EF_RELOAD);
perf_event_update_userpage(event);
-
- return 0;
+ ret = 0;
+out:
+ perf_pmu_enable(event->pmu);
+ return ret;
}
static void sh_pmu_read(struct perf_event *event)
@@ -257,24 +305,56 @@ static void sh_pmu_read(struct perf_event *event)
sh_perf_event_update(event, &event->hw, event->hw.idx);
}
-static const struct pmu pmu = {
- .enable = sh_pmu_enable,
- .disable = sh_pmu_disable,
- .read = sh_pmu_read,
-};
-
-const struct pmu *hw_perf_event_init(struct perf_event *event)
+static int sh_pmu_event_init(struct perf_event *event)
{
- int err = __hw_perf_event_init(event);
+ int err;
+
+ switch (event->attr.type) {
+ case PERF_TYPE_RAW:
+ case PERF_TYPE_HW_CACHE:
+ case PERF_TYPE_HARDWARE:
+ err = __hw_perf_event_init(event);
+ break;
+
+ default:
+ return -ENOENT;
+ }
+
if (unlikely(err)) {
if (event->destroy)
event->destroy(event);
- return ERR_PTR(err);
}
- return &pmu;
+ return err;
+}
+
+static void sh_pmu_enable(struct pmu *pmu)
+{
+ if (!sh_pmu_initialized())
+ return;
+
+ sh_pmu->enable_all();
+}
+
+static void sh_pmu_disable(struct pmu *pmu)
+{
+ if (!sh_pmu_initialized())
+ return;
+
+ sh_pmu->disable_all();
}
+static struct pmu pmu = {
+ .pmu_enable = sh_pmu_enable,
+ .pmu_disable = sh_pmu_disable,
+ .event_init = sh_pmu_event_init,
+ .add = sh_pmu_add,
+ .del = sh_pmu_del,
+ .start = sh_pmu_start,
+ .stop = sh_pmu_stop,
+ .read = sh_pmu_read,
+};
+
static void sh_pmu_setup(int cpu)
{
struct cpu_hw_events *cpuhw = &per_cpu(cpu_hw_events, cpu);
@@ -299,32 +379,17 @@ sh_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu)
return NOTIFY_OK;
}
-void hw_perf_enable(void)
-{
- if (!sh_pmu_initialized())
- return;
-
- sh_pmu->enable_all();
-}
-
-void hw_perf_disable(void)
-{
- if (!sh_pmu_initialized())
- return;
-
- sh_pmu->disable_all();
-}
-
-int __cpuinit register_sh_pmu(struct sh_pmu *pmu)
+int __cpuinit register_sh_pmu(struct sh_pmu *_pmu)
{
if (sh_pmu)
return -EBUSY;
- sh_pmu = pmu;
+ sh_pmu = _pmu;
- pr_info("Performance Events: %s support registered\n", pmu->name);
+ pr_info("Performance Events: %s support registered\n", _pmu->name);
- WARN_ON(pmu->num_events > MAX_HWEVENTS);
+ WARN_ON(_pmu->num_events > MAX_HWEVENTS);
+ perf_pmu_register(&pmu);
perf_cpu_notifier(sh_pmu_notifier);
return 0;
}
diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c
index d0e249100e98..552bea5113f5 100644
--- a/arch/sh/mm/init.c
+++ b/arch/sh/mm/init.c
@@ -200,7 +200,6 @@ static void __init bootmem_init_one_node(unsigned int nid)
unsigned long total_pages, paddr;
unsigned long end_pfn;
struct pglist_data *p;
- int i;
p = NODE_DATA(nid);
@@ -226,11 +225,12 @@ static void __init bootmem_init_one_node(unsigned int nid)
* reservations in other nodes.
*/
if (nid == 0) {
+ struct memblock_region *reg;
+
/* Reserve the sections we're already using. */
- for (i = 0; i < memblock.reserved.cnt; i++)
- reserve_bootmem(memblock.reserved.region[i].base,
- memblock_size_bytes(&memblock.reserved, i),
- BOOTMEM_DEFAULT);
+ for_each_memblock(reserved, reg) {
+ reserve_bootmem(reg->base, reg->size, BOOTMEM_DEFAULT);
+ }
}
sparse_memory_present_with_active_regions(nid);
@@ -238,13 +238,14 @@ static void __init bootmem_init_one_node(unsigned int nid)
static void __init do_init_bootmem(void)
{
+ struct memblock_region *reg;
int i;
/* Add active regions with valid PFNs. */
- for (i = 0; i < memblock.memory.cnt; i++) {
+ for_each_memblock(memory, reg) {
unsigned long start_pfn, end_pfn;
- start_pfn = memblock.memory.region[i].base >> PAGE_SHIFT;
- end_pfn = start_pfn + memblock_size_pages(&memblock.memory, i);
+ start_pfn = memblock_region_memory_base_pfn(reg);
+ end_pfn = memblock_region_memory_end_pfn(reg);
__add_active_range(0, start_pfn, end_pfn);
}
diff --git a/arch/sh/oprofile/Makefile b/arch/sh/oprofile/Makefile
index 4886c5c1786c..e85aae73e3dc 100644
--- a/arch/sh/oprofile/Makefile
+++ b/arch/sh/oprofile/Makefile
@@ -6,4 +6,8 @@ DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \
oprofilefs.o oprofile_stats.o \
timer_int.o )
+ifeq ($(CONFIG_HW_PERF_EVENTS),y)
+DRIVER_OBJS += $(addprefix ../../../drivers/oprofile/, oprofile_perf.o)
+endif
+
oprofile-y := $(DRIVER_OBJS) common.o backtrace.o
diff --git a/arch/sh/oprofile/common.c b/arch/sh/oprofile/common.c
index ac604937f3ee..e10d89376f9b 100644
--- a/arch/sh/oprofile/common.c
+++ b/arch/sh/oprofile/common.c
@@ -17,114 +17,45 @@
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/smp.h>
+#include <linux/perf_event.h>
#include <asm/processor.h>
-#include "op_impl.h"
-
-static struct op_sh_model *model;
-
-static struct op_counter_config ctr[20];
+#ifdef CONFIG_HW_PERF_EVENTS
extern void sh_backtrace(struct pt_regs * const regs, unsigned int depth);
-static int op_sh_setup(void)
-{
- /* Pre-compute the values to stuff in the hardware registers. */
- model->reg_setup(ctr);
-
- /* Configure the registers on all cpus. */
- on_each_cpu(model->cpu_setup, NULL, 1);
-
- return 0;
-}
-
-static int op_sh_create_files(struct super_block *sb, struct dentry *root)
+char *op_name_from_perf_id(void)
{
- int i, ret = 0;
+ const char *pmu;
+ char buf[20];
+ int size;
- for (i = 0; i < model->num_counters; i++) {
- struct dentry *dir;
- char buf[4];
+ pmu = perf_pmu_name();
+ if (!pmu)
+ return NULL;
- snprintf(buf, sizeof(buf), "%d", i);
- dir = oprofilefs_mkdir(sb, root, buf);
+ size = snprintf(buf, sizeof(buf), "sh/%s", pmu);
+ if (size > -1 && size < sizeof(buf))
+ return buf;
- ret |= oprofilefs_create_ulong(sb, dir, "enabled", &ctr[i].enabled);
- ret |= oprofilefs_create_ulong(sb, dir, "event", &ctr[i].event);
- ret |= oprofilefs_create_ulong(sb, dir, "kernel", &ctr[i].kernel);
- ret |= oprofilefs_create_ulong(sb, dir, "user", &ctr[i].user);
-
- if (model->create_files)
- ret |= model->create_files(sb, dir);
- else
- ret |= oprofilefs_create_ulong(sb, dir, "count", &ctr[i].count);
-
- /* Dummy entries */
- ret |= oprofilefs_create_ulong(sb, dir, "unit_mask", &ctr[i].unit_mask);
- }
-
- return ret;
+ return NULL;
}
-static int op_sh_start(void)
+int __init oprofile_arch_init(struct oprofile_operations *ops)
{
- /* Enable performance monitoring for all counters. */
- on_each_cpu(model->cpu_start, NULL, 1);
+ ops->backtrace = sh_backtrace;
- return 0;
+ return oprofile_perf_init(ops);
}
-static void op_sh_stop(void)
+void __exit oprofile_arch_exit(void)
{
- /* Disable performance monitoring for all counters. */
- on_each_cpu(model->cpu_stop, NULL, 1);
+ oprofile_perf_exit();
}
-
+#else
int __init oprofile_arch_init(struct oprofile_operations *ops)
{
- struct op_sh_model *lmodel = NULL;
- int ret;
-
- /*
- * Always assign the backtrace op. If the counter initialization
- * fails, we fall back to the timer which will still make use of
- * this.
- */
- ops->backtrace = sh_backtrace;
-
- /*
- * XXX
- *
- * All of the SH7750/SH-4A counters have been converted to perf,
- * this infrastructure hook is left for other users until they've
- * had a chance to convert over, at which point all of this
- * will be deleted.
- */
-
- if (!lmodel)
- return -ENODEV;
- if (!(current_cpu_data.flags & CPU_HAS_PERF_COUNTER))
- return -ENODEV;
-
- ret = lmodel->init();
- if (unlikely(ret != 0))
- return ret;
-
- model = lmodel;
-
- ops->setup = op_sh_setup;
- ops->create_files = op_sh_create_files;
- ops->start = op_sh_start;
- ops->stop = op_sh_stop;
- ops->cpu_type = lmodel->cpu_type;
-
- printk(KERN_INFO "oprofile: using %s performance monitoring.\n",
- lmodel->cpu_type);
-
- return 0;
-}
-
-void oprofile_arch_exit(void)
-{
- if (model && model->exit)
- model->exit();
+ pr_info("oprofile: hardware counters not available\n");
+ return -ENODEV;
}
+void __exit oprofile_arch_exit(void) {}
+#endif /* CONFIG_HW_PERF_EVENTS */
diff --git a/arch/sh/oprofile/op_impl.h b/arch/sh/oprofile/op_impl.h
deleted file mode 100644
index 1244479ceb29..000000000000
--- a/arch/sh/oprofile/op_impl.h
+++ /dev/null
@@ -1,33 +0,0 @@
-#ifndef __OP_IMPL_H
-#define __OP_IMPL_H
-
-/* Per-counter configuration as set via oprofilefs. */
-struct op_counter_config {
- unsigned long enabled;
- unsigned long event;
-
- unsigned long count;
-
- /* Dummy values for userspace tool compliance */
- unsigned long kernel;
- unsigned long user;
- unsigned long unit_mask;
-};
-
-/* Per-architecture configury and hooks. */
-struct op_sh_model {
- void (*reg_setup)(struct op_counter_config *);
- int (*create_files)(struct super_block *sb, struct dentry *dir);
- void (*cpu_setup)(void *dummy);
- int (*init)(void);
- void (*exit)(void);
- void (*cpu_start)(void *args);
- void (*cpu_stop)(void *args);
- char *cpu_type;
- unsigned char num_counters;
-};
-
-/* arch/sh/oprofile/common.c */
-extern void sh_backtrace(struct pt_regs * const regs, unsigned int depth);
-
-#endif /* __OP_IMPL_H */
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 491e9d6de191..3e9d31401fb2 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -26,10 +26,12 @@ config SPARC
select ARCH_WANT_OPTIONAL_GPIOLIB
select RTC_CLASS
select RTC_DRV_M48T59
+ select HAVE_IRQ_WORK
select HAVE_PERF_EVENTS
select PERF_USE_VMALLOC
select HAVE_DMA_ATTRS
select HAVE_DMA_API_DEBUG
+ select HAVE_ARCH_JUMP_LABEL
config SPARC32
def_bool !64BIT
@@ -53,6 +55,7 @@ config SPARC64
select RTC_DRV_BQ4802
select RTC_DRV_SUN4V
select RTC_DRV_STARFIRE
+ select HAVE_IRQ_WORK
select HAVE_PERF_EVENTS
select PERF_USE_VMALLOC
diff --git a/arch/sparc/include/asm/irqflags_32.h b/arch/sparc/include/asm/irqflags_32.h
index 0fca9d97d44f..d4d0711de0f9 100644
--- a/arch/sparc/include/asm/irqflags_32.h
+++ b/arch/sparc/include/asm/irqflags_32.h
@@ -5,33 +5,40 @@
*
* This file gets included from lowlevel asm headers too, to provide
* wrapped versions of the local_irq_*() APIs, based on the
- * raw_local_irq_*() functions from the lowlevel headers.
+ * arch_local_irq_*() functions from the lowlevel headers.
*/
#ifndef _ASM_IRQFLAGS_H
#define _ASM_IRQFLAGS_H
#ifndef __ASSEMBLY__
-extern void raw_local_irq_restore(unsigned long);
-extern unsigned long __raw_local_irq_save(void);
-extern void raw_local_irq_enable(void);
+#include <linux/types.h>
-static inline unsigned long getipl(void)
+extern void arch_local_irq_restore(unsigned long);
+extern unsigned long arch_local_irq_save(void);
+extern void arch_local_irq_enable(void);
+
+static inline unsigned long arch_local_save_flags(void)
{
- unsigned long retval;
+ unsigned long flags;
+
+ asm volatile("rd %%psr, %0" : "=r" (flags));
+ return flags;
+}
- __asm__ __volatile__("rd %%psr, %0" : "=r" (retval));
- return retval;
+static inline void arch_local_irq_disable(void)
+{
+ arch_local_irq_save();
}
-#define raw_local_save_flags(flags) ((flags) = getipl())
-#define raw_local_irq_save(flags) ((flags) = __raw_local_irq_save())
-#define raw_local_irq_disable() ((void) __raw_local_irq_save())
-#define raw_irqs_disabled() ((getipl() & PSR_PIL) != 0)
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+ return (flags & PSR_PIL) != 0;
+}
-static inline int raw_irqs_disabled_flags(unsigned long flags)
+static inline bool arch_irqs_disabled(void)
{
- return ((flags & PSR_PIL) != 0);
+ return arch_irqs_disabled_flags(arch_local_save_flags());
}
#endif /* (__ASSEMBLY__) */
diff --git a/arch/sparc/include/asm/irqflags_64.h b/arch/sparc/include/asm/irqflags_64.h
index bfa1ea45b4cd..aab969c82c2b 100644
--- a/arch/sparc/include/asm/irqflags_64.h
+++ b/arch/sparc/include/asm/irqflags_64.h
@@ -5,7 +5,7 @@
*
* This file gets included from lowlevel asm headers too, to provide
* wrapped versions of the local_irq_*() APIs, based on the
- * raw_local_irq_*() functions from the lowlevel headers.
+ * arch_local_irq_*() functions from the lowlevel headers.
*/
#ifndef _ASM_IRQFLAGS_H
#define _ASM_IRQFLAGS_H
@@ -14,7 +14,7 @@
#ifndef __ASSEMBLY__
-static inline unsigned long __raw_local_save_flags(void)
+static inline unsigned long arch_local_save_flags(void)
{
unsigned long flags;
@@ -26,10 +26,7 @@ static inline unsigned long __raw_local_save_flags(void)
return flags;
}
-#define raw_local_save_flags(flags) \
- do { (flags) = __raw_local_save_flags(); } while (0)
-
-static inline void raw_local_irq_restore(unsigned long flags)
+static inline void arch_local_irq_restore(unsigned long flags)
{
__asm__ __volatile__(
"wrpr %0, %%pil"
@@ -39,7 +36,7 @@ static inline void raw_local_irq_restore(unsigned long flags)
);
}
-static inline void raw_local_irq_disable(void)
+static inline void arch_local_irq_disable(void)
{
__asm__ __volatile__(
"wrpr %0, %%pil"
@@ -49,7 +46,7 @@ static inline void raw_local_irq_disable(void)
);
}
-static inline void raw_local_irq_enable(void)
+static inline void arch_local_irq_enable(void)
{
__asm__ __volatile__(
"wrpr 0, %%pil"
@@ -59,22 +56,17 @@ static inline void raw_local_irq_enable(void)
);
}
-static inline int raw_irqs_disabled_flags(unsigned long flags)
+static inline int arch_irqs_disabled_flags(unsigned long flags)
{
return (flags > 0);
}
-static inline int raw_irqs_disabled(void)
+static inline int arch_irqs_disabled(void)
{
- unsigned long flags = __raw_local_save_flags();
-
- return raw_irqs_disabled_flags(flags);
+ return arch_irqs_disabled_flags(arch_local_save_flags());
}
-/*
- * For spinlocks, etc:
- */
-static inline unsigned long __raw_local_irq_save(void)
+static inline unsigned long arch_local_irq_save(void)
{
unsigned long flags, tmp;
@@ -100,9 +92,6 @@ static inline unsigned long __raw_local_irq_save(void)
return flags;
}
-#define raw_local_irq_save(flags) \
- do { (flags) = __raw_local_irq_save(); } while (0)
-
#endif /* (__ASSEMBLY__) */
#endif /* !(_ASM_IRQFLAGS_H) */
diff --git a/arch/sparc/include/asm/jump_label.h b/arch/sparc/include/asm/jump_label.h
new file mode 100644
index 000000000000..62e66d7b2fb6
--- /dev/null
+++ b/arch/sparc/include/asm/jump_label.h
@@ -0,0 +1,32 @@
+#ifndef _ASM_SPARC_JUMP_LABEL_H
+#define _ASM_SPARC_JUMP_LABEL_H
+
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+#include <asm/system.h>
+
+#define JUMP_LABEL_NOP_SIZE 4
+
+#define JUMP_LABEL(key, label) \
+ do { \
+ asm goto("1:\n\t" \
+ "nop\n\t" \
+ "nop\n\t" \
+ ".pushsection __jump_table, \"a\"\n\t"\
+ ".word 1b, %l[" #label "], %c0\n\t" \
+ ".popsection \n\t" \
+ : : "i" (key) : : label);\
+ } while (0)
+
+#endif /* __KERNEL__ */
+
+typedef u32 jump_label_t;
+
+struct jump_entry {
+ jump_label_t code;
+ jump_label_t target;
+ jump_label_t key;
+};
+
+#endif
diff --git a/arch/sparc/include/asm/memblock.h b/arch/sparc/include/asm/memblock.h
index f12af880649b..c67b047ef85e 100644
--- a/arch/sparc/include/asm/memblock.h
+++ b/arch/sparc/include/asm/memblock.h
@@ -5,6 +5,4 @@
#define MEMBLOCK_DBG(fmt...) prom_printf(fmt)
-#define MEMBLOCK_REAL_LIMIT 0
-
#endif /* !(_SPARC64_MEMBLOCK_H) */
diff --git a/arch/sparc/include/asm/perf_event.h b/arch/sparc/include/asm/perf_event.h
index 727af70646cb..6e8bfa1786da 100644
--- a/arch/sparc/include/asm/perf_event.h
+++ b/arch/sparc/include/asm/perf_event.h
@@ -1,10 +1,6 @@
#ifndef __ASM_SPARC_PERF_EVENT_H
#define __ASM_SPARC_PERF_EVENT_H
-extern void set_perf_event_pending(void);
-
-#define PERF_EVENT_INDEX_OFFSET 0
-
#ifdef CONFIG_PERF_EVENTS
#include <asm/ptrace.h>
diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile
index 0c2dc1f24a9a..599398fbbc7c 100644
--- a/arch/sparc/kernel/Makefile
+++ b/arch/sparc/kernel/Makefile
@@ -119,3 +119,5 @@ obj-$(CONFIG_COMPAT) += $(audit--y)
pc--$(CONFIG_PERF_EVENTS) := perf_event.o
obj-$(CONFIG_SPARC64) += $(pc--y)
+
+obj-$(CONFIG_SPARC64) += jump_label.o
diff --git a/arch/sparc/kernel/apc.c b/arch/sparc/kernel/apc.c
index 2c0046ecc715..52de4a9424e8 100644
--- a/arch/sparc/kernel/apc.c
+++ b/arch/sparc/kernel/apc.c
@@ -132,6 +132,7 @@ static const struct file_operations apc_fops = {
.unlocked_ioctl = apc_ioctl,
.open = apc_open,
.release = apc_release,
+ .llseek = noop_llseek,
};
static struct miscdevice apc_miscdev = { APC_MINOR, APC_DEVNAME, &apc_fops };
diff --git a/arch/sparc/kernel/irq_32.c b/arch/sparc/kernel/irq_32.c
index e1af43728329..0116d8d10def 100644
--- a/arch/sparc/kernel/irq_32.c
+++ b/arch/sparc/kernel/irq_32.c
@@ -57,7 +57,7 @@
#define SMP_NOP2
#define SMP_NOP3
#endif /* SMP */
-unsigned long __raw_local_irq_save(void)
+unsigned long arch_local_irq_save(void)
{
unsigned long retval;
unsigned long tmp;
@@ -74,8 +74,9 @@ unsigned long __raw_local_irq_save(void)
return retval;
}
+EXPORT_SYMBOL(arch_local_irq_save);
-void raw_local_irq_enable(void)
+void arch_local_irq_enable(void)
{
unsigned long tmp;
@@ -89,8 +90,9 @@ void raw_local_irq_enable(void)
: "i" (PSR_PIL)
: "memory");
}
+EXPORT_SYMBOL(arch_local_irq_enable);
-void raw_local_irq_restore(unsigned long old_psr)
+void arch_local_irq_restore(unsigned long old_psr)
{
unsigned long tmp;
@@ -105,10 +107,7 @@ void raw_local_irq_restore(unsigned long old_psr)
: "i" (PSR_PIL), "r" (old_psr)
: "memory");
}
-
-EXPORT_SYMBOL(__raw_local_irq_save);
-EXPORT_SYMBOL(raw_local_irq_enable);
-EXPORT_SYMBOL(raw_local_irq_restore);
+EXPORT_SYMBOL(arch_local_irq_restore);
/*
* Dave Redman (djhr@tadpole.co.uk)
diff --git a/arch/sparc/kernel/jump_label.c b/arch/sparc/kernel/jump_label.c
new file mode 100644
index 000000000000..ea2dafc93d78
--- /dev/null
+++ b/arch/sparc/kernel/jump_label.c
@@ -0,0 +1,47 @@
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mutex.h>
+#include <linux/cpu.h>
+
+#include <linux/jump_label.h>
+#include <linux/memory.h>
+
+#ifdef HAVE_JUMP_LABEL
+
+void arch_jump_label_transform(struct jump_entry *entry,
+ enum jump_label_type type)
+{
+ u32 val;
+ u32 *insn = (u32 *) (unsigned long) entry->code;
+
+ if (type == JUMP_LABEL_ENABLE) {
+ s32 off = (s32)entry->target - (s32)entry->code;
+
+#ifdef CONFIG_SPARC64
+ /* ba,pt %xcc, . + (off << 2) */
+ val = 0x10680000 | ((u32) off >> 2);
+#else
+ /* ba . + (off << 2) */
+ val = 0x10800000 | ((u32) off >> 2);
+#endif
+ } else {
+ val = 0x01000000;
+ }
+
+ get_online_cpus();
+ mutex_lock(&text_mutex);
+ *insn = val;
+ flushi(insn);
+ mutex_unlock(&text_mutex);
+ put_online_cpus();
+}
+
+void arch_jump_label_text_poke_early(jump_label_t addr)
+{
+ u32 *insn_p = (u32 *) (unsigned long) addr;
+
+ *insn_p = 0x01000000;
+ flushi(insn_p);
+}
+
+#endif
diff --git a/arch/sparc/kernel/mdesc.c b/arch/sparc/kernel/mdesc.c
index 83e85c2e802a..6addb914fcc8 100644
--- a/arch/sparc/kernel/mdesc.c
+++ b/arch/sparc/kernel/mdesc.c
@@ -890,6 +890,7 @@ static ssize_t mdesc_read(struct file *file, char __user *buf,
static const struct file_operations mdesc_fops = {
.read = mdesc_read,
.owner = THIS_MODULE,
+ .llseek = noop_llseek,
};
static struct miscdevice mdesc_misc = {
diff --git a/arch/sparc/kernel/module.c b/arch/sparc/kernel/module.c
index f848aadf54dc..ee3c7dde8d9f 100644
--- a/arch/sparc/kernel/module.c
+++ b/arch/sparc/kernel/module.c
@@ -18,6 +18,9 @@
#include <asm/spitfire.h>
#ifdef CONFIG_SPARC64
+
+#include <linux/jump_label.h>
+
static void *module_map(unsigned long size)
{
struct vm_struct *area;
@@ -227,6 +230,9 @@ int module_finalize(const Elf_Ehdr *hdr,
const Elf_Shdr *sechdrs,
struct module *me)
{
+ /* make jump label nops */
+ jump_label_apply_nops(me);
+
/* Cheetah's I-cache is fully coherent. */
if (tlb_type == spitfire) {
unsigned long va;
diff --git a/arch/sparc/kernel/pci_msi.c b/arch/sparc/kernel/pci_msi.c
index 548b8ca9c210..b210416ace7b 100644
--- a/arch/sparc/kernel/pci_msi.c
+++ b/arch/sparc/kernel/pci_msi.c
@@ -114,10 +114,10 @@ static void free_msi(struct pci_pbm_info *pbm, int msi_num)
static struct irq_chip msi_irq = {
.name = "PCI-MSI",
- .mask = mask_msi_irq,
- .unmask = unmask_msi_irq,
- .enable = unmask_msi_irq,
- .disable = mask_msi_irq,
+ .irq_mask = mask_msi_irq,
+ .irq_unmask = unmask_msi_irq,
+ .irq_enable = unmask_msi_irq,
+ .irq_disable = mask_msi_irq,
/* XXX affinity XXX */
};
diff --git a/arch/sparc/kernel/pcr.c b/arch/sparc/kernel/pcr.c
index c4a6a50b4849..b87873c0e8ea 100644
--- a/arch/sparc/kernel/pcr.c
+++ b/arch/sparc/kernel/pcr.c
@@ -7,7 +7,7 @@
#include <linux/init.h>
#include <linux/irq.h>
-#include <linux/perf_event.h>
+#include <linux/irq_work.h>
#include <linux/ftrace.h>
#include <asm/pil.h>
@@ -43,14 +43,14 @@ void __irq_entry deferred_pcr_work_irq(int irq, struct pt_regs *regs)
old_regs = set_irq_regs(regs);
irq_enter();
-#ifdef CONFIG_PERF_EVENTS
- perf_event_do_pending();
+#ifdef CONFIG_IRQ_WORK
+ irq_work_run();
#endif
irq_exit();
set_irq_regs(old_regs);
}
-void set_perf_event_pending(void)
+void arch_irq_work_raise(void)
{
set_softint(1 << PIL_DEFERRED_PCR_WORK);
}
diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c
index 6318e622cfb0..0d6deb55a2ae 100644
--- a/arch/sparc/kernel/perf_event.c
+++ b/arch/sparc/kernel/perf_event.c
@@ -658,13 +658,16 @@ static u64 maybe_change_configuration(struct cpu_hw_events *cpuc, u64 pcr)
enc = perf_event_get_enc(cpuc->events[i]);
pcr &= ~mask_for_index(idx);
- pcr |= event_encoding(enc, idx);
+ if (hwc->state & PERF_HES_STOPPED)
+ pcr |= nop_for_index(idx);
+ else
+ pcr |= event_encoding(enc, idx);
}
out:
return pcr;
}
-void hw_perf_enable(void)
+static void sparc_pmu_enable(struct pmu *pmu)
{
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
u64 pcr;
@@ -691,7 +694,7 @@ void hw_perf_enable(void)
pcr_ops->write(cpuc->pcr);
}
-void hw_perf_disable(void)
+static void sparc_pmu_disable(struct pmu *pmu)
{
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
u64 val;
@@ -710,19 +713,65 @@ void hw_perf_disable(void)
pcr_ops->write(cpuc->pcr);
}
-static void sparc_pmu_disable(struct perf_event *event)
+static int active_event_index(struct cpu_hw_events *cpuc,
+ struct perf_event *event)
+{
+ int i;
+
+ for (i = 0; i < cpuc->n_events; i++) {
+ if (cpuc->event[i] == event)
+ break;
+ }
+ BUG_ON(i == cpuc->n_events);
+ return cpuc->current_idx[i];
+}
+
+static void sparc_pmu_start(struct perf_event *event, int flags)
+{
+ struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+ int idx = active_event_index(cpuc, event);
+
+ if (flags & PERF_EF_RELOAD) {
+ WARN_ON_ONCE(!(event->hw.state & PERF_HES_UPTODATE));
+ sparc_perf_event_set_period(event, &event->hw, idx);
+ }
+
+ event->hw.state = 0;
+
+ sparc_pmu_enable_event(cpuc, &event->hw, idx);
+}
+
+static void sparc_pmu_stop(struct perf_event *event, int flags)
+{
+ struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+ int idx = active_event_index(cpuc, event);
+
+ if (!(event->hw.state & PERF_HES_STOPPED)) {
+ sparc_pmu_disable_event(cpuc, &event->hw, idx);
+ event->hw.state |= PERF_HES_STOPPED;
+ }
+
+ if (!(event->hw.state & PERF_HES_UPTODATE) && (flags & PERF_EF_UPDATE)) {
+ sparc_perf_event_update(event, &event->hw, idx);
+ event->hw.state |= PERF_HES_UPTODATE;
+ }
+}
+
+static void sparc_pmu_del(struct perf_event *event, int _flags)
{
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
- struct hw_perf_event *hwc = &event->hw;
unsigned long flags;
int i;
local_irq_save(flags);
- perf_disable();
+ perf_pmu_disable(event->pmu);
for (i = 0; i < cpuc->n_events; i++) {
if (event == cpuc->event[i]) {
- int idx = cpuc->current_idx[i];
+ /* Absorb the final count and turn off the
+ * event.
+ */
+ sparc_pmu_stop(event, PERF_EF_UPDATE);
/* Shift remaining entries down into
* the existing slot.
@@ -734,13 +783,6 @@ static void sparc_pmu_disable(struct perf_event *event)
cpuc->current_idx[i];
}
- /* Absorb the final count and turn off the
- * event.
- */
- sparc_pmu_disable_event(cpuc, hwc, idx);
- barrier();
- sparc_perf_event_update(event, hwc, idx);
-
perf_event_update_userpage(event);
cpuc->n_events--;
@@ -748,23 +790,10 @@ static void sparc_pmu_disable(struct perf_event *event)
}
}
- perf_enable();
+ perf_pmu_enable(event->pmu);
local_irq_restore(flags);
}
-static int active_event_index(struct cpu_hw_events *cpuc,
- struct perf_event *event)
-{
- int i;
-
- for (i = 0; i < cpuc->n_events; i++) {
- if (cpuc->event[i] == event)
- break;
- }
- BUG_ON(i == cpuc->n_events);
- return cpuc->current_idx[i];
-}
-
static void sparc_pmu_read(struct perf_event *event)
{
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
@@ -774,15 +803,6 @@ static void sparc_pmu_read(struct perf_event *event)
sparc_perf_event_update(event, hwc, idx);
}
-static void sparc_pmu_unthrottle(struct perf_event *event)
-{
- struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
- int idx = active_event_index(cpuc, event);
- struct hw_perf_event *hwc = &event->hw;
-
- sparc_pmu_enable_event(cpuc, hwc, idx);
-}
-
static atomic_t active_events = ATOMIC_INIT(0);
static DEFINE_MUTEX(pmc_grab_mutex);
@@ -877,7 +897,7 @@ static int sparc_check_constraints(struct perf_event **evts,
if (!n_ev)
return 0;
- if (n_ev > perf_max_events)
+ if (n_ev > MAX_HWEVENTS)
return -1;
msk0 = perf_event_get_msk(events[0]);
@@ -984,23 +1004,27 @@ static int collect_events(struct perf_event *group, int max_count,
return n;
}
-static int sparc_pmu_enable(struct perf_event *event)
+static int sparc_pmu_add(struct perf_event *event, int ef_flags)
{
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
int n0, ret = -EAGAIN;
unsigned long flags;
local_irq_save(flags);
- perf_disable();
+ perf_pmu_disable(event->pmu);
n0 = cpuc->n_events;
- if (n0 >= perf_max_events)
+ if (n0 >= MAX_HWEVENTS)
goto out;
cpuc->event[n0] = event;
cpuc->events[n0] = event->hw.event_base;
cpuc->current_idx[n0] = PIC_NO_INDEX;
+ event->hw.state = PERF_HES_UPTODATE;
+ if (!(ef_flags & PERF_EF_START))
+ event->hw.state |= PERF_HES_STOPPED;
+
/*
* If group events scheduling transaction was started,
* skip the schedulability test here, it will be peformed
@@ -1020,12 +1044,12 @@ nocheck:
ret = 0;
out:
- perf_enable();
+ perf_pmu_enable(event->pmu);
local_irq_restore(flags);
return ret;
}
-static int __hw_perf_event_init(struct perf_event *event)
+static int sparc_pmu_event_init(struct perf_event *event)
{
struct perf_event_attr *attr = &event->attr;
struct perf_event *evts[MAX_HWEVENTS];
@@ -1038,22 +1062,33 @@ static int __hw_perf_event_init(struct perf_event *event)
if (atomic_read(&nmi_active) < 0)
return -ENODEV;
- pmap = NULL;
- if (attr->type == PERF_TYPE_HARDWARE) {
+ switch (attr->type) {
+ case PERF_TYPE_HARDWARE:
if (attr->config >= sparc_pmu->max_events)
return -EINVAL;
pmap = sparc_pmu->event_map(attr->config);
- } else if (attr->type == PERF_TYPE_HW_CACHE) {
+ break;
+
+ case PERF_TYPE_HW_CACHE:
pmap = sparc_map_cache_event(attr->config);
if (IS_ERR(pmap))
return PTR_ERR(pmap);
- } else if (attr->type != PERF_TYPE_RAW)
- return -EOPNOTSUPP;
+ break;
+
+ case PERF_TYPE_RAW:
+ pmap = NULL;
+ break;
+
+ default:
+ return -ENOENT;
+
+ }
if (pmap) {
hwc->event_base = perf_event_encode(pmap);
} else {
- /* User gives us "(encoding << 16) | pic_mask" for
+ /*
+ * User gives us "(encoding << 16) | pic_mask" for
* PERF_TYPE_RAW events.
*/
hwc->event_base = attr->config;
@@ -1071,7 +1106,7 @@ static int __hw_perf_event_init(struct perf_event *event)
n = 0;
if (event->group_leader != event) {
n = collect_events(event->group_leader,
- perf_max_events - 1,
+ MAX_HWEVENTS - 1,
evts, events, current_idx_dmy);
if (n < 0)
return -EINVAL;
@@ -1107,10 +1142,11 @@ static int __hw_perf_event_init(struct perf_event *event)
* Set the flag to make pmu::enable() not perform the
* schedulability test, it will be performed at commit time
*/
-static void sparc_pmu_start_txn(const struct pmu *pmu)
+static void sparc_pmu_start_txn(struct pmu *pmu)
{
struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events);
+ perf_pmu_disable(pmu);
cpuhw->group_flag |= PERF_EVENT_TXN;
}
@@ -1119,11 +1155,12 @@ static void sparc_pmu_start_txn(const struct pmu *pmu)
* Clear the flag and pmu::enable() will perform the
* schedulability test.
*/
-static void sparc_pmu_cancel_txn(const struct pmu *pmu)
+static void sparc_pmu_cancel_txn(struct pmu *pmu)
{
struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events);
cpuhw->group_flag &= ~PERF_EVENT_TXN;
+ perf_pmu_enable(pmu);
}
/*
@@ -1131,7 +1168,7 @@ static void sparc_pmu_cancel_txn(const struct pmu *pmu)
* Perform the group schedulability test as a whole
* Return 0 if success
*/
-static int sparc_pmu_commit_txn(const struct pmu *pmu)
+static int sparc_pmu_commit_txn(struct pmu *pmu)
{
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
int n;
@@ -1147,28 +1184,24 @@ static int sparc_pmu_commit_txn(const struct pmu *pmu)
return -EAGAIN;
cpuc->group_flag &= ~PERF_EVENT_TXN;
+ perf_pmu_enable(pmu);
return 0;
}
-static const struct pmu pmu = {
- .enable = sparc_pmu_enable,
- .disable = sparc_pmu_disable,
+static struct pmu pmu = {
+ .pmu_enable = sparc_pmu_enable,
+ .pmu_disable = sparc_pmu_disable,
+ .event_init = sparc_pmu_event_init,
+ .add = sparc_pmu_add,
+ .del = sparc_pmu_del,
+ .start = sparc_pmu_start,
+ .stop = sparc_pmu_stop,
.read = sparc_pmu_read,
- .unthrottle = sparc_pmu_unthrottle,
.start_txn = sparc_pmu_start_txn,
.cancel_txn = sparc_pmu_cancel_txn,
.commit_txn = sparc_pmu_commit_txn,
};
-const struct pmu *hw_perf_event_init(struct perf_event *event)
-{
- int err = __hw_perf_event_init(event);
-
- if (err)
- return ERR_PTR(err);
- return &pmu;
-}
-
void perf_event_print_debug(void)
{
unsigned long flags;
@@ -1244,7 +1277,7 @@ static int __kprobes perf_event_nmi_handler(struct notifier_block *self,
continue;
if (perf_event_overflow(event, 1, &data, regs))
- sparc_pmu_disable_event(cpuc, hwc, idx);
+ sparc_pmu_stop(event, 0);
}
return NOTIFY_STOP;
@@ -1285,28 +1318,21 @@ void __init init_hw_perf_events(void)
pr_cont("Supported PMU type is '%s'\n", sparc_pmu_type);
- /* All sparc64 PMUs currently have 2 events. */
- perf_max_events = 2;
-
+ perf_pmu_register(&pmu);
register_die_notifier(&perf_event_nmi_notifier);
}
-static inline void callchain_store(struct perf_callchain_entry *entry, u64 ip)
-{
- if (entry->nr < PERF_MAX_STACK_DEPTH)
- entry->ip[entry->nr++] = ip;
-}
-
-static void perf_callchain_kernel(struct pt_regs *regs,
- struct perf_callchain_entry *entry)
+void perf_callchain_kernel(struct perf_callchain_entry *entry,
+ struct pt_regs *regs)
{
unsigned long ksp, fp;
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
int graph = 0;
#endif
- callchain_store(entry, PERF_CONTEXT_KERNEL);
- callchain_store(entry, regs->tpc);
+ stack_trace_flush();
+
+ perf_callchain_store(entry, regs->tpc);
ksp = regs->u_regs[UREG_I6];
fp = ksp + STACK_BIAS;
@@ -1330,13 +1356,13 @@ static void perf_callchain_kernel(struct pt_regs *regs,
pc = sf->callers_pc;
fp = (unsigned long)sf->fp + STACK_BIAS;
}
- callchain_store(entry, pc);
+ perf_callchain_store(entry, pc);
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
if ((pc + 8UL) == (unsigned long) &return_to_handler) {
int index = current->curr_ret_stack;
if (current->ret_stack && index >= graph) {
pc = current->ret_stack[index - graph].ret;
- callchain_store(entry, pc);
+ perf_callchain_store(entry, pc);
graph++;
}
}
@@ -1344,13 +1370,12 @@ static void perf_callchain_kernel(struct pt_regs *regs,
} while (entry->nr < PERF_MAX_STACK_DEPTH);
}
-static void perf_callchain_user_64(struct pt_regs *regs,
- struct perf_callchain_entry *entry)
+static void perf_callchain_user_64(struct perf_callchain_entry *entry,
+ struct pt_regs *regs)
{
unsigned long ufp;
- callchain_store(entry, PERF_CONTEXT_USER);
- callchain_store(entry, regs->tpc);
+ perf_callchain_store(entry, regs->tpc);
ufp = regs->u_regs[UREG_I6] + STACK_BIAS;
do {
@@ -1363,17 +1388,16 @@ static void perf_callchain_user_64(struct pt_regs *regs,
pc = sf.callers_pc;
ufp = (unsigned long)sf.fp + STACK_BIAS;
- callchain_store(entry, pc);
+ perf_callchain_store(entry, pc);
} while (entry->nr < PERF_MAX_STACK_DEPTH);
}
-static void perf_callchain_user_32(struct pt_regs *regs,
- struct perf_callchain_entry *entry)
+static void perf_callchain_user_32(struct perf_callchain_entry *entry,
+ struct pt_regs *regs)
{
unsigned long ufp;
- callchain_store(entry, PERF_CONTEXT_USER);
- callchain_store(entry, regs->tpc);
+ perf_callchain_store(entry, regs->tpc);
ufp = regs->u_regs[UREG_I6] & 0xffffffffUL;
do {
@@ -1386,34 +1410,16 @@ static void perf_callchain_user_32(struct pt_regs *regs,
pc = sf.callers_pc;
ufp = (unsigned long)sf.fp;
- callchain_store(entry, pc);
+ perf_callchain_store(entry, pc);
} while (entry->nr < PERF_MAX_STACK_DEPTH);
}
-/* Like powerpc we can't get PMU interrupts within the PMU handler,
- * so no need for separate NMI and IRQ chains as on x86.
- */
-static DEFINE_PER_CPU(struct perf_callchain_entry, callchain);
-
-struct perf_callchain_entry *perf_callchain(struct pt_regs *regs)
+void
+perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
{
- struct perf_callchain_entry *entry = &__get_cpu_var(callchain);
-
- entry->nr = 0;
- if (!user_mode(regs)) {
- stack_trace_flush();
- perf_callchain_kernel(regs, entry);
- if (current->mm)
- regs = task_pt_regs(current);
- else
- regs = NULL;
- }
- if (regs) {
- flushw_user();
- if (test_thread_flag(TIF_32BIT))
- perf_callchain_user_32(regs, entry);
- else
- perf_callchain_user_64(regs, entry);
- }
- return entry;
+ flushw_user();
+ if (test_thread_flag(TIF_32BIT))
+ perf_callchain_user_32(entry, regs);
+ else
+ perf_callchain_user_64(entry, regs);
}
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index f0434513df15..4c2572773b55 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -785,8 +785,7 @@ static int find_node(unsigned long addr)
return -1;
}
-static unsigned long long nid_range(unsigned long long start,
- unsigned long long end, int *nid)
+u64 memblock_nid_range(u64 start, u64 end, int *nid)
{
*nid = find_node(start);
start += PAGE_SIZE;
@@ -804,8 +803,7 @@ static unsigned long long nid_range(unsigned long long start,
return start;
}
#else
-static unsigned long long nid_range(unsigned long long start,
- unsigned long long end, int *nid)
+u64 memblock_nid_range(u64 start, u64 end, int *nid)
{
*nid = 0;
return end;
@@ -822,8 +820,7 @@ static void __init allocate_node_data(int nid)
struct pglist_data *p;
#ifdef CONFIG_NEED_MULTIPLE_NODES
- paddr = memblock_alloc_nid(sizeof(struct pglist_data),
- SMP_CACHE_BYTES, nid, nid_range);
+ paddr = memblock_alloc_try_nid(sizeof(struct pglist_data), SMP_CACHE_BYTES, nid);
if (!paddr) {
prom_printf("Cannot allocate pglist_data for nid[%d]\n", nid);
prom_halt();
@@ -843,8 +840,7 @@ static void __init allocate_node_data(int nid)
if (p->node_spanned_pages) {
num_pages = bootmem_bootmap_pages(p->node_spanned_pages);
- paddr = memblock_alloc_nid(num_pages << PAGE_SHIFT, PAGE_SIZE, nid,
- nid_range);
+ paddr = memblock_alloc_try_nid(num_pages << PAGE_SHIFT, PAGE_SIZE, nid);
if (!paddr) {
prom_printf("Cannot allocate bootmap for nid[%d]\n",
nid);
@@ -972,19 +968,19 @@ int of_node_to_nid(struct device_node *dp)
static void __init add_node_ranges(void)
{
- int i;
+ struct memblock_region *reg;
- for (i = 0; i < memblock.memory.cnt; i++) {
- unsigned long size = memblock_size_bytes(&memblock.memory, i);
+ for_each_memblock(memory, reg) {
+ unsigned long size = reg->size;
unsigned long start, end;
- start = memblock.memory.region[i].base;
+ start = reg->base;
end = start + size;
while (start < end) {
unsigned long this_end;
int nid;
- this_end = nid_range(start, end, &nid);
+ this_end = memblock_nid_range(start, end, &nid);
numadbg("Adding active range nid[%d] "
"start[%lx] end[%lx]\n",
@@ -1281,7 +1277,7 @@ static void __init bootmem_init_nonnuma(void)
{
unsigned long top_of_ram = memblock_end_of_DRAM();
unsigned long total_ram = memblock_phys_mem_size();
- unsigned int i;
+ struct memblock_region *reg;
numadbg("bootmem_init_nonnuma()\n");
@@ -1292,15 +1288,14 @@ static void __init bootmem_init_nonnuma(void)
init_node_masks_nonnuma();
- for (i = 0; i < memblock.memory.cnt; i++) {
- unsigned long size = memblock_size_bytes(&memblock.memory, i);
+ for_each_memblock(memory, reg) {
unsigned long start_pfn, end_pfn;
- if (!size)
+ if (!reg->size)
continue;
- start_pfn = memblock.memory.region[i].base >> PAGE_SHIFT;
- end_pfn = start_pfn + memblock_size_pages(&memblock.memory, i);
+ start_pfn = memblock_region_memory_base_pfn(reg);
+ end_pfn = memblock_region_memory_end_pfn(reg);
add_active_range(0, start_pfn, end_pfn);
}
@@ -1318,7 +1313,7 @@ static void __init reserve_range_in_node(int nid, unsigned long start,
unsigned long this_end;
int n;
- this_end = nid_range(start, end, &n);
+ this_end = memblock_nid_range(start, end, &n);
if (n == nid) {
numadbg(" MATCH reserving range [%lx:%lx]\n",
start, this_end);
@@ -1334,17 +1329,12 @@ static void __init reserve_range_in_node(int nid, unsigned long start,
static void __init trim_reserved_in_node(int nid)
{
- int i;
+ struct memblock_region *reg;
numadbg(" trim_reserved_in_node(%d)\n", nid);
- for (i = 0; i < memblock.reserved.cnt; i++) {
- unsigned long start = memblock.reserved.region[i].base;
- unsigned long size = memblock_size_bytes(&memblock.reserved, i);
- unsigned long end = start + size;
-
- reserve_range_in_node(nid, start, end);
- }
+ for_each_memblock(reserved, reg)
+ reserve_range_in_node(nid, reg->base, reg->base + reg->size);
}
static void __init bootmem_init_one_node(int nid)
diff --git a/arch/sparc/prom/p1275.c b/arch/sparc/prom/p1275.c
index fa6e4e219b9c..d9850c2b9bf2 100644
--- a/arch/sparc/prom/p1275.c
+++ b/arch/sparc/prom/p1275.c
@@ -39,7 +39,7 @@ void p1275_cmd_direct(unsigned long *args)
unsigned long flags;
raw_local_save_flags(flags);
- raw_local_irq_restore(PIL_NMI);
+ raw_local_irq_restore((unsigned long)PIL_NMI);
raw_spin_lock(&prom_entry_lock);
prom_world(1);
diff --git a/arch/tile/include/asm/bitops.h b/arch/tile/include/asm/bitops.h
index 6832b4be8990..6d4f0ff2c68c 100644
--- a/arch/tile/include/asm/bitops.h
+++ b/arch/tile/include/asm/bitops.h
@@ -120,6 +120,7 @@ static inline unsigned long __arch_hweight64(__u64 w)
#include <asm-generic/bitops/const_hweight.h>
#include <asm-generic/bitops/lock.h>
+#include <asm-generic/bitops/find.h>
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/ext2-non-atomic.h>
#include <asm-generic/bitops/minix.h>
diff --git a/arch/tile/include/asm/irqflags.h b/arch/tile/include/asm/irqflags.h
index 45cf67c2f286..a11d4837ee4d 100644
--- a/arch/tile/include/asm/irqflags.h
+++ b/arch/tile/include/asm/irqflags.h
@@ -103,55 +103,57 @@ DECLARE_PER_CPU(unsigned long long, interrupts_enabled_mask);
#define INITIAL_INTERRUPTS_ENABLED INT_MASK(INT_MEM_ERROR)
/* Disable interrupts. */
-#define raw_local_irq_disable() \
+#define arch_local_irq_disable() \
interrupt_mask_set_mask(LINUX_MASKABLE_INTERRUPTS)
/* Disable all interrupts, including NMIs. */
-#define raw_local_irq_disable_all() \
+#define arch_local_irq_disable_all() \
interrupt_mask_set_mask(-1UL)
/* Re-enable all maskable interrupts. */
-#define raw_local_irq_enable() \
+#define arch_local_irq_enable() \
interrupt_mask_reset_mask(__get_cpu_var(interrupts_enabled_mask))
/* Disable or enable interrupts based on flag argument. */
-#define raw_local_irq_restore(disabled) do { \
+#define arch_local_irq_restore(disabled) do { \
if (disabled) \
- raw_local_irq_disable(); \
+ arch_local_irq_disable(); \
else \
- raw_local_irq_enable(); \
+ arch_local_irq_enable(); \
} while (0)
/* Return true if "flags" argument means interrupts are disabled. */
-#define raw_irqs_disabled_flags(flags) ((flags) != 0)
+#define arch_irqs_disabled_flags(flags) ((flags) != 0)
/* Return true if interrupts are currently disabled. */
-#define raw_irqs_disabled() interrupt_mask_check(INT_MEM_ERROR)
+#define arch_irqs_disabled() interrupt_mask_check(INT_MEM_ERROR)
/* Save whether interrupts are currently disabled. */
-#define raw_local_save_flags(flags) ((flags) = raw_irqs_disabled())
+#define arch_local_save_flags() arch_irqs_disabled()
/* Save whether interrupts are currently disabled, then disable them. */
-#define raw_local_irq_save(flags) \
- do { raw_local_save_flags(flags); raw_local_irq_disable(); } while (0)
+#define arch_local_irq_save() ({ \
+ unsigned long __flags = arch_local_save_flags(); \
+ arch_local_irq_disable(); \
+ __flags; })
/* Prevent the given interrupt from being enabled next time we enable irqs. */
-#define raw_local_irq_mask(interrupt) \
+#define arch_local_irq_mask(interrupt) \
(__get_cpu_var(interrupts_enabled_mask) &= ~INT_MASK(interrupt))
/* Prevent the given interrupt from being enabled immediately. */
-#define raw_local_irq_mask_now(interrupt) do { \
- raw_local_irq_mask(interrupt); \
+#define arch_local_irq_mask_now(interrupt) do { \
+ arch_local_irq_mask(interrupt); \
interrupt_mask_set(interrupt); \
} while (0)
/* Allow the given interrupt to be enabled next time we enable irqs. */
-#define raw_local_irq_unmask(interrupt) \
+#define arch_local_irq_unmask(interrupt) \
(__get_cpu_var(interrupts_enabled_mask) |= INT_MASK(interrupt))
/* Allow the given interrupt to be enabled immediately, if !irqs_disabled. */
-#define raw_local_irq_unmask_now(interrupt) do { \
- raw_local_irq_unmask(interrupt); \
+#define arch_local_irq_unmask_now(interrupt) do { \
+ arch_local_irq_unmask(interrupt); \
if (!irqs_disabled()) \
interrupt_mask_reset(interrupt); \
} while (0)
diff --git a/arch/tile/kernel/hardwall.c b/arch/tile/kernel/hardwall.c
index 584b965dc824..1e54a7843410 100644
--- a/arch/tile/kernel/hardwall.c
+++ b/arch/tile/kernel/hardwall.c
@@ -774,6 +774,7 @@ static const struct file_operations dev_hardwall_fops = {
#endif
.flush = hardwall_flush,
.release = hardwall_release,
+ .llseek = noop_llseek,
};
static struct cdev hardwall_dev;
diff --git a/arch/tile/kernel/irq.c b/arch/tile/kernel/irq.c
index 596c60086930..9a27d563fc30 100644
--- a/arch/tile/kernel/irq.c
+++ b/arch/tile/kernel/irq.c
@@ -208,7 +208,7 @@ static void tile_irq_chip_eoi(unsigned int irq)
}
static struct irq_chip tile_irq_chip = {
- .typename = "tile_irq_chip",
+ .name = "tile_irq_chip",
.ack = tile_irq_chip_ack,
.eoi = tile_irq_chip_eoi,
.mask = tile_irq_chip_mask,
@@ -288,7 +288,7 @@ int show_interrupts(struct seq_file *p, void *v)
for_each_online_cpu(j)
seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
#endif
- seq_printf(p, " %14s", irq_desc[i].chip->typename);
+ seq_printf(p, " %14s", irq_desc[i].chip->name);
seq_printf(p, " %s", action->name);
for (action = action->next; action; action = action->next)
diff --git a/arch/um/drivers/harddog_kern.c b/arch/um/drivers/harddog_kern.c
index cfcac1ff4cf2..2d0266d0254d 100644
--- a/arch/um/drivers/harddog_kern.c
+++ b/arch/um/drivers/harddog_kern.c
@@ -42,7 +42,7 @@
#include <linux/miscdevice.h>
#include <linux/watchdog.h>
#include <linux/reboot.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/init.h>
#include <linux/spinlock.h>
#include <asm/uaccess.h>
@@ -50,6 +50,7 @@
MODULE_LICENSE("GPL");
+static DEFINE_MUTEX(harddog_mutex);
static DEFINE_SPINLOCK(lock);
static int timer_alive;
static int harddog_in_fd = -1;
@@ -66,7 +67,7 @@ static int harddog_open(struct inode *inode, struct file *file)
int err = -EBUSY;
char *sock = NULL;
- lock_kernel();
+ mutex_lock(&harddog_mutex);
spin_lock(&lock);
if(timer_alive)
goto err;
@@ -83,11 +84,11 @@ static int harddog_open(struct inode *inode, struct file *file)
timer_alive = 1;
spin_unlock(&lock);
- unlock_kernel();
+ mutex_unlock(&harddog_mutex);
return nonseekable_open(inode, file);
err:
spin_unlock(&lock);
- unlock_kernel();
+ mutex_unlock(&harddog_mutex);
return err;
}
@@ -153,9 +154,9 @@ static long harddog_ioctl(struct file *file,
{
long ret;
- lock_kernel();
+ mutex_lock(&harddog_mutex);
ret = harddog_ioctl_unlocked(file, cmd, arg);
- unlock_kernel();
+ mutex_unlock(&harddog_mutex);
return ret;
}
@@ -166,6 +167,7 @@ static const struct file_operations harddog_fops = {
.unlocked_ioctl = harddog_ioctl,
.open = harddog_open,
.release = harddog_release,
+ .llseek = no_llseek,
};
static struct miscdevice harddog_miscdev = {
diff --git a/arch/um/drivers/hostaudio_kern.c b/arch/um/drivers/hostaudio_kern.c
index 0c46e398cd8f..f9f6a4e20590 100644
--- a/arch/um/drivers/hostaudio_kern.c
+++ b/arch/um/drivers/hostaudio_kern.c
@@ -8,7 +8,7 @@
#include "linux/slab.h"
#include "linux/sound.h"
#include "linux/soundcard.h"
-#include "linux/smp_lock.h"
+#include "linux/mutex.h"
#include "asm/uaccess.h"
#include "init.h"
#include "os.h"
@@ -40,6 +40,11 @@ static char *mixer = HOSTAUDIO_DEV_MIXER;
" This is used to specify the host mixer device to the hostaudio driver.\n"\
" The default is \"" HOSTAUDIO_DEV_MIXER "\".\n\n"
+module_param(dsp, charp, 0644);
+MODULE_PARM_DESC(dsp, DSP_HELP);
+module_param(mixer, charp, 0644);
+MODULE_PARM_DESC(mixer, MIXER_HELP);
+
#ifndef MODULE
static int set_dsp(char *name, int *add)
{
@@ -56,17 +61,10 @@ static int set_mixer(char *name, int *add)
}
__uml_setup("mixer=", set_mixer, "mixer=<mixer device>\n" MIXER_HELP);
-
-#else /*MODULE*/
-
-module_param(dsp, charp, 0644);
-MODULE_PARM_DESC(dsp, DSP_HELP);
-
-module_param(mixer, charp, 0644);
-MODULE_PARM_DESC(mixer, MIXER_HELP);
-
#endif
+static DEFINE_MUTEX(hostaudio_mutex);
+
/* /dev/dsp file operations */
static ssize_t hostaudio_read(struct file *file, char __user *buffer,
@@ -202,9 +200,9 @@ static int hostaudio_open(struct inode *inode, struct file *file)
w = 1;
kparam_block_sysfs_write(dsp);
- lock_kernel();
+ mutex_lock(&hostaudio_mutex);
ret = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0);
- unlock_kernel();
+ mutex_unlock(&hostaudio_mutex);
kparam_unblock_sysfs_write(dsp);
if (ret < 0) {
@@ -263,9 +261,9 @@ static int hostmixer_open_mixdev(struct inode *inode, struct file *file)
w = 1;
kparam_block_sysfs_write(mixer);
- lock_kernel();
+ mutex_lock(&hostaudio_mutex);
ret = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0);
- unlock_kernel();
+ mutex_unlock(&hostaudio_mutex);
kparam_unblock_sysfs_write(mixer);
if (ret < 0) {
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index ebc680717e59..975613b23dcf 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -843,6 +843,7 @@ static ssize_t mconsole_proc_write(struct file *file,
static const struct file_operations mconsole_proc_fops = {
.owner = THIS_MODULE,
.write = mconsole_proc_write,
+ .llseek = noop_llseek,
};
static int create_proc_mconsole(void)
diff --git a/arch/um/drivers/mmapper_kern.c b/arch/um/drivers/mmapper_kern.c
index 7158393b6793..8501e7d0015c 100644
--- a/arch/um/drivers/mmapper_kern.c
+++ b/arch/um/drivers/mmapper_kern.c
@@ -93,6 +93,7 @@ static const struct file_operations mmapper_fops = {
.mmap = mmapper_mmap,
.open = mmapper_open,
.release = mmapper_release,
+ .llseek = default_llseek,
};
/*
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index 2ab233ba32c1..47d0c37897d5 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -255,18 +255,6 @@ static void uml_net_tx_timeout(struct net_device *dev)
netif_wake_queue(dev);
}
-static int uml_net_set_mac(struct net_device *dev, void *addr)
-{
- struct uml_net_private *lp = netdev_priv(dev);
- struct sockaddr *hwaddr = addr;
-
- spin_lock_irq(&lp->lock);
- eth_mac_addr(dev, hwaddr->sa_data);
- spin_unlock_irq(&lp->lock);
-
- return 0;
-}
-
static int uml_net_change_mtu(struct net_device *dev, int new_mtu)
{
dev->mtu = new_mtu;
@@ -373,7 +361,7 @@ static const struct net_device_ops uml_netdev_ops = {
.ndo_start_xmit = uml_net_start_xmit,
.ndo_set_multicast_list = uml_net_set_multicast_list,
.ndo_tx_timeout = uml_net_tx_timeout,
- .ndo_set_mac_address = uml_net_set_mac,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = uml_net_change_mtu,
.ndo_validate_addr = eth_validate_addr,
};
@@ -472,7 +460,8 @@ static void eth_configure(int n, void *init, char *mac,
((*transport->user->init)(&lp->user, dev) != 0))
goto out_unregister;
- eth_mac_addr(dev, device->mac);
+ /* don't use eth_mac_addr, it will not work here */
+ memcpy(dev->dev_addr, device->mac, ETH_ALEN);
dev->mtu = transport->user->mtu;
dev->netdev_ops = &uml_netdev_ops;
dev->ethtool_ops = &uml_net_ethtool_ops;
diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c
index 4949044773ba..981085a93f30 100644
--- a/arch/um/drivers/random.c
+++ b/arch/um/drivers/random.c
@@ -100,6 +100,7 @@ static const struct file_operations rng_chrdev_ops = {
.owner = THIS_MODULE,
.open = rng_dev_open,
.read = rng_dev_read,
+ .llseek = noop_llseek,
};
/* rng_init shouldn't be called more than once at boot time */
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 1bcd208c459f..ba4a98ba39c0 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -33,7 +33,7 @@
#include "linux/mm.h"
#include "linux/slab.h"
#include "linux/vmalloc.h"
-#include "linux/smp_lock.h"
+#include "linux/mutex.h"
#include "linux/blkpg.h"
#include "linux/genhd.h"
#include "linux/spinlock.h"
@@ -100,6 +100,7 @@ static inline void ubd_set_bit(__u64 bit, unsigned char *data)
#define DRIVER_NAME "uml-blkdev"
static DEFINE_MUTEX(ubd_lock);
+static DEFINE_MUTEX(ubd_mutex); /* replaces BKL, might not be needed */
static int ubd_open(struct block_device *bdev, fmode_t mode);
static int ubd_release(struct gendisk *disk, fmode_t mode);
@@ -163,6 +164,7 @@ struct ubd {
struct scatterlist sg[MAX_SG];
struct request *request;
int start_sg, end_sg;
+ sector_t rq_pos;
};
#define DEFAULT_COW { \
@@ -187,6 +189,7 @@ struct ubd {
.request = NULL, \
.start_sg = 0, \
.end_sg = 0, \
+ .rq_pos = 0, \
}
/* Protected by ubd_lock */
@@ -1099,7 +1102,7 @@ static int ubd_open(struct block_device *bdev, fmode_t mode)
struct ubd *ubd_dev = disk->private_data;
int err = 0;
- lock_kernel();
+ mutex_lock(&ubd_mutex);
if(ubd_dev->count == 0){
err = ubd_open_dev(ubd_dev);
if(err){
@@ -1118,7 +1121,7 @@ static int ubd_open(struct block_device *bdev, fmode_t mode)
err = -EROFS;
}*/
out:
- unlock_kernel();
+ mutex_unlock(&ubd_mutex);
return err;
}
@@ -1126,10 +1129,10 @@ static int ubd_release(struct gendisk *disk, fmode_t mode)
{
struct ubd *ubd_dev = disk->private_data;
- lock_kernel();
+ mutex_lock(&ubd_mutex);
if(--ubd_dev->count == 0)
ubd_close_dev(ubd_dev);
- unlock_kernel();
+ mutex_unlock(&ubd_mutex);
return 0;
}
@@ -1228,7 +1231,6 @@ static void do_ubd_request(struct request_queue *q)
{
struct io_thread_req *io_req;
struct request *req;
- sector_t sector;
int n;
while(1){
@@ -1239,12 +1241,12 @@ static void do_ubd_request(struct request_queue *q)
return;
dev->request = req;
+ dev->rq_pos = blk_rq_pos(req);
dev->start_sg = 0;
dev->end_sg = blk_rq_map_sg(q, req, dev->sg);
}
req = dev->request;
- sector = blk_rq_pos(req);
while(dev->start_sg < dev->end_sg){
struct scatterlist *sg = &dev->sg[dev->start_sg];
@@ -1256,10 +1258,9 @@ static void do_ubd_request(struct request_queue *q)
return;
}
prepare_request(req, io_req,
- (unsigned long long)sector << 9,
+ (unsigned long long)dev->rq_pos << 9,
sg->offset, sg->length, sg_page(sg));
- sector += sg->length >> 9;
n = os_write_file(thread_fd, &io_req,
sizeof(struct io_thread_req *));
if(n != sizeof(struct io_thread_req *)){
@@ -1272,6 +1273,7 @@ static void do_ubd_request(struct request_queue *q)
return;
}
+ dev->rq_pos += sg->length >> 9;
dev->start_sg++;
}
dev->end_sg = 0;
diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c
index 49b5e1eb3262..340268be00b5 100644
--- a/arch/um/kernel/exec.c
+++ b/arch/um/kernel/exec.c
@@ -78,13 +78,11 @@ long sys_execve(const char __user *file, const char __user *const __user *argv,
long error;
char *filename;
- lock_kernel();
filename = getname(file);
error = PTR_ERR(filename);
if (IS_ERR(filename)) goto out;
error = execve1(filename, argv, env);
putname(filename);
out:
- unlock_kernel();
return error;
}
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index a3f0b04d7101..a746e3037a5b 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -46,7 +46,7 @@ int show_interrupts(struct seq_file *p, void *v)
for_each_online_cpu(j)
seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
#endif
- seq_printf(p, " %14s", irq_desc[i].chip->typename);
+ seq_printf(p, " %14s", irq_desc[i].chip->name);
seq_printf(p, " %s", action->name);
for (action=action->next; action; action = action->next)
@@ -369,7 +369,7 @@ static void dummy(unsigned int irq)
/* This is used for everything else than the timer. */
static struct irq_chip normal_irq_type = {
- .typename = "SIGIO",
+ .name = "SIGIO",
.release = free_irq_by_irq_and_dev,
.disable = dummy,
.enable = dummy,
@@ -378,7 +378,7 @@ static struct irq_chip normal_irq_type = {
};
static struct irq_chip SIGVTALRM_irq_type = {
- .typename = "SIGVTALRM",
+ .name = "SIGVTALRM",
.release = free_irq_by_irq_and_dev,
.shutdown = dummy, /* never called */
.disable = dummy,
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index cea0cd9a316f..dfabfefc21c4 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -25,14 +25,17 @@ config X86
select HAVE_IDE
select HAVE_OPROFILE
select HAVE_PERF_EVENTS if (!M386 && !M486)
+ select HAVE_IRQ_WORK
select HAVE_IOREMAP_PROT
select HAVE_KPROBES
+ select HAVE_MEMBLOCK
select ARCH_WANT_OPTIONAL_GPIOLIB
select ARCH_WANT_FRAME_POINTERS
select HAVE_DMA_ATTRS
select HAVE_KRETPROBES
select HAVE_OPTPROBES
select HAVE_FTRACE_MCOUNT_RECORD
+ select HAVE_C_RECORDMCOUNT
select HAVE_DYNAMIC_FTRACE
select HAVE_FUNCTION_TRACER
select HAVE_FUNCTION_GRAPH_TRACER
@@ -59,6 +62,12 @@ config X86
select ANON_INODES
select HAVE_ARCH_KMEMCHECK
select HAVE_USER_RETURN_NOTIFIER
+ select HAVE_ARCH_JUMP_LABEL
+ select HAVE_TEXT_POKE_SMP
+ select HAVE_GENERIC_HARDIRQS
+ select HAVE_SPARSE_IRQ
+ select GENERIC_IRQ_PROBE
+ select GENERIC_PENDING_IRQ if SMP
config INSTRUCTION_DECODER
def_bool (KPROBES || PERF_EVENTS)
@@ -193,27 +202,10 @@ config ARCH_SUPPORTS_OPTIMIZED_INLINING
config ARCH_SUPPORTS_DEBUG_PAGEALLOC
def_bool y
-config HAVE_EARLY_RES
- def_bool y
-
config HAVE_INTEL_TXT
def_bool y
depends on EXPERIMENTAL && DMAR && ACPI
-# Use the generic interrupt handling code in kernel/irq/:
-config GENERIC_HARDIRQS
- def_bool y
-
-config GENERIC_HARDIRQS_NO__DO_IRQ
- def_bool y
-
-config GENERIC_IRQ_PROBE
- def_bool y
-
-config GENERIC_PENDING_IRQ
- def_bool y
- depends on GENERIC_HARDIRQS && SMP
-
config USE_GENERIC_SMP_HELPERS
def_bool y
depends on SMP
@@ -296,23 +288,6 @@ config X86_X2APIC
If you don't know what to do here, say N.
-config SPARSE_IRQ
- bool "Support sparse irq numbering"
- depends on PCI_MSI || HT_IRQ
- ---help---
- This enables support for sparse irqs. This is useful for distro
- kernels that want to define a high CONFIG_NR_CPUS value but still
- want to have low kernel memory footprint on smaller machines.
-
- ( Sparse IRQs can also be beneficial on NUMA boxes, as they spread
- out the irq_desc[] array in a more NUMA-friendly way. )
-
- If you don't know what to do here, say N.
-
-config NUMA_IRQ_DESC
- def_bool y
- depends on SPARSE_IRQ && NUMA
-
config X86_MPPARSE
bool "Enable MPS table" if ACPI
default y
@@ -517,25 +492,6 @@ if PARAVIRT_GUEST
source "arch/x86/xen/Kconfig"
-config VMI
- bool "VMI Guest support (DEPRECATED)"
- select PARAVIRT
- depends on X86_32
- ---help---
- VMI provides a paravirtualized interface to the VMware ESX server
- (it could be used by other hypervisors in theory too, but is not
- at the moment), by linking the kernel to a GPL-ed ROM module
- provided by the hypervisor.
-
- As of September 2009, VMware has started a phased retirement
- of this feature from VMware's products. Please see
- feature-removal-schedule.txt for details. If you are
- planning to enable this option, please note that you cannot
- live migrate a VMI enabled VM to a future VMware product,
- which doesn't support VMI. So if you expect your kernel to
- seamlessly migrate to newer VMware products, keep this
- disabled.
-
config KVM_CLOCK
bool "KVM paravirtualized clock"
select PARAVIRT
@@ -590,16 +546,7 @@ config PARAVIRT_DEBUG
a paravirt_op is missing when it is called.
config NO_BOOTMEM
- default y
- bool "Disable Bootmem code"
- ---help---
- Use early_res directly instead of bootmem before slab is ready.
- - allocator (buddy) [generic]
- - early allocator (bootmem) [generic]
- - very early allocator (reserve_early*()) [x86]
- - very very early allocator (early brk model) [x86]
- So reduce one layer between early allocator to final allocator
-
+ def_bool y
config MEMTEST
bool "Memtest"
@@ -670,7 +617,7 @@ config GART_IOMMU
bool "GART IOMMU support" if EMBEDDED
default y
select SWIOTLB
- depends on X86_64 && PCI && K8_NB
+ depends on X86_64 && PCI && AMD_NB
---help---
Support for full DMA access of devices with 32bit memory access only
on systems with more than 3GB. This is usually needed for USB,
@@ -795,6 +742,17 @@ config SCHED_MC
making when dealing with multi-core CPU chips at a cost of slightly
increased overhead in some places. If unsure say N here.
+config IRQ_TIME_ACCOUNTING
+ bool "Fine granularity task level IRQ time accounting"
+ default n
+ ---help---
+ Select this option to enable fine granularity task irq time
+ accounting. This is done by reading a timestamp on each
+ transitions between softirq and hardirq state, so there can be a
+ small performance impact.
+
+ If in doubt, say N here.
+
source "kernel/Kconfig.preempt"
config X86_UP_APIC
@@ -1148,6 +1106,9 @@ config X86_PAE
config ARCH_PHYS_ADDR_T_64BIT
def_bool X86_64 || X86_PAE
+config ARCH_DMA_ADDR_T_64BIT
+ def_bool X86_64 || HIGHMEM64G
+
config DIRECT_GBPAGES
bool "Enable 1GB pages for kernel pagetables" if EMBEDDED
default y
@@ -1326,25 +1287,34 @@ config X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK
Set whether the default state of memory_corruption_check is
on or off.
-config X86_RESERVE_LOW_64K
- bool "Reserve low 64K of RAM on AMI/Phoenix BIOSen"
- default y
+config X86_RESERVE_LOW
+ int "Amount of low memory, in kilobytes, to reserve for the BIOS"
+ default 64
+ range 4 640
---help---
- Reserve the first 64K of physical RAM on BIOSes that are known
- to potentially corrupt that memory range. A numbers of BIOSes are
- known to utilize this area during suspend/resume, so it must not
- be used by the kernel.
+ Specify the amount of low memory to reserve for the BIOS.
+
+ The first page contains BIOS data structures that the kernel
+ must not use, so that page must always be reserved.
+
+ By default we reserve the first 64K of physical RAM, as a
+ number of BIOSes are known to corrupt that memory range
+ during events such as suspend/resume or monitor cable
+ insertion, so it must not be used by the kernel.
- Set this to N if you are absolutely sure that you trust the BIOS
- to get all its memory reservations and usages right.
+ You can set this to 4 if you are absolutely sure that you
+ trust the BIOS to get all its memory reservations and usages
+ right. If you know your BIOS have problems beyond the
+ default 64K area, you can set this to 640 to avoid using the
+ entire low memory range.
- If you have doubts about the BIOS (e.g. suspend/resume does not
- work or there's kernel crashes after certain hardware hotplug
- events) and it's not AMI or Phoenix, then you might want to enable
- X86_CHECK_BIOS_CORRUPTION=y to allow the kernel to check typical
- corruption patterns.
+ If you have doubts about the BIOS (e.g. suspend/resume does
+ not work or there's kernel crashes after certain hardware
+ hotplug events) then you might want to enable
+ X86_CHECK_BIOS_CORRUPTION=y to allow the kernel to check
+ typical corruption patterns.
- Say Y if unsure.
+ Leave this to the default value of 64 if you are unsure.
config MATH_EMULATION
bool
@@ -1900,7 +1870,7 @@ config PCI_GODIRECT
bool "Direct"
config PCI_GOOLPC
- bool "OLPC"
+ bool "OLPC XO-1"
depends on OLPC
config PCI_GOANY
@@ -2061,14 +2031,21 @@ config SCx200HR_TIMER
config OLPC
bool "One Laptop Per Child support"
select GPIOLIB
+ select OLPC_OPENFIRMWARE
---help---
Add support for detecting the unique features of the OLPC
XO hardware.
+config OLPC_XO1
+ tristate "OLPC XO-1 support"
+ depends on OLPC && PCI
+ ---help---
+ Add support for non-essential features of the OLPC XO-1 laptop.
+
config OLPC_OPENFIRMWARE
bool "Support for OLPC's Open Firmware"
depends on !X86_64 && !X86_PAE
- default y if OLPC
+ default n
help
This option adds support for the implementation of Open Firmware
that is used on the OLPC XO-1 Children's Machine.
@@ -2076,7 +2053,7 @@ config OLPC_OPENFIRMWARE
endif # X86_32
-config K8_NB
+config AMD_NB
def_bool y
depends on CPU_SUP_AMD && PCI
@@ -2125,6 +2102,10 @@ config HAVE_ATOMIC_IOMAP
def_bool y
depends on X86_32
+config HAVE_TEXT_POKE_SMP
+ bool
+ select STOP_MACHINE if SMP
+
source "net/Kconfig"
source "drivers/Kconfig"
diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
index 75085080b63e..b59ee765414e 100644
--- a/arch/x86/Kconfig.debug
+++ b/arch/x86/Kconfig.debug
@@ -43,6 +43,10 @@ config EARLY_PRINTK
with klogd/syslogd or the X server. You should normally N here,
unless you want to debug such a crash.
+config EARLY_PRINTK_MRST
+ bool "Early printk for MRST platform support"
+ depends on EARLY_PRINTK && X86_MRST
+
config EARLY_PRINTK_DBGP
bool "Early printk via EHCI debug port"
depends on EARLY_PRINTK && PCI
@@ -121,16 +125,6 @@ config DEBUG_NX_TEST
and the software setup of this feature.
If in doubt, say "N"
-config 4KSTACKS
- bool "Use 4Kb for kernel stacks instead of 8Kb"
- depends on X86_32
- ---help---
- If you say Y here the kernel will use a 4Kb stacksize for the
- kernel stack attached to each process/thread. This facilitates
- running more threads on a system and also reduces the pressure
- on the VM subsystem for higher order allocations. This option
- will also use IRQ stacks to compensate for the reduced stackspace.
-
config DOUBLEFAULT
default y
bool "Enable doublefault exception handler" if EMBEDDED
diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index e8c8881351b3..b02e509072a7 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -96,8 +96,12 @@ cfi := $(call as-instr,.cfi_startproc\n.cfi_rel_offset $(sp-y)$(comma)0\n.cfi_en
# is .cfi_signal_frame supported too?
cfi-sigframe := $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1)
cfi-sections := $(call as-instr,.cfi_sections .debug_frame,-DCONFIG_AS_CFI_SECTIONS=1)
-KBUILD_AFLAGS += $(cfi) $(cfi-sigframe) $(cfi-sections)
-KBUILD_CFLAGS += $(cfi) $(cfi-sigframe) $(cfi-sections)
+
+# does binutils support specific instructions?
+asinstr := $(call as-instr,fxsaveq (%rax),-DCONFIG_AS_FXSAVEQ=1)
+
+KBUILD_AFLAGS += $(cfi) $(cfi-sigframe) $(cfi-sections) $(asinstr)
+KBUILD_CFLAGS += $(cfi) $(cfi-sigframe) $(cfi-sections) $(asinstr)
LDFLAGS := -m elf_$(UTS_MACHINE)
diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c
index 8f7bef8e9fff..23f315c9f215 100644
--- a/arch/x86/boot/compressed/misc.c
+++ b/arch/x86/boot/compressed/misc.c
@@ -229,18 +229,35 @@ void *memset(void *s, int c, size_t n)
ss[i] = c;
return s;
}
-
+#ifdef CONFIG_X86_32
void *memcpy(void *dest, const void *src, size_t n)
{
- int i;
- const char *s = src;
- char *d = dest;
+ int d0, d1, d2;
+ asm volatile(
+ "rep ; movsl\n\t"
+ "movl %4,%%ecx\n\t"
+ "rep ; movsb\n\t"
+ : "=&c" (d0), "=&D" (d1), "=&S" (d2)
+ : "0" (n >> 2), "g" (n & 3), "1" (dest), "2" (src)
+ : "memory");
- for (i = 0; i < n; i++)
- d[i] = s[i];
return dest;
}
+#else
+void *memcpy(void *dest, const void *src, size_t n)
+{
+ long d0, d1, d2;
+ asm volatile(
+ "rep ; movsq\n\t"
+ "movq %4,%%rcx\n\t"
+ "rep ; movsb\n\t"
+ : "=&c" (d0), "=&D" (d1), "=&S" (d2)
+ : "0" (n >> 3), "g" (n & 7), "1" (dest), "2" (src)
+ : "memory");
+ return dest;
+}
+#endif
static void error(char *x)
{
diff --git a/arch/x86/ia32/ia32_aout.c b/arch/x86/ia32/ia32_aout.c
index 0350311906ae..2d93bdbc9ac0 100644
--- a/arch/x86/ia32/ia32_aout.c
+++ b/arch/x86/ia32/ia32_aout.c
@@ -34,7 +34,7 @@
#include <asm/ia32.h>
#undef WARN_OLD
-#undef CORE_DUMP /* probably broken */
+#undef CORE_DUMP /* definitely broken */
static int load_aout_binary(struct linux_binprm *, struct pt_regs *regs);
static int load_aout_library(struct file *);
@@ -131,21 +131,15 @@ static void set_brk(unsigned long start, unsigned long end)
* macros to write out all the necessary info.
*/
-static int dump_write(struct file *file, const void *addr, int nr)
-{
- return file->f_op->write(file, addr, nr, &file->f_pos) == nr;
-}
+#include <linux/coredump.h>
#define DUMP_WRITE(addr, nr) \
if (!dump_write(file, (void *)(addr), (nr))) \
goto end_coredump;
-#define DUMP_SEEK(offset) \
- if (file->f_op->llseek) { \
- if (file->f_op->llseek(file, (offset), 0) != (offset)) \
- goto end_coredump; \
- } else \
- file->f_pos = (offset)
+#define DUMP_SEEK(offset) \
+ if (!dump_seek(file, offset)) \
+ goto end_coredump;
#define START_DATA() (u.u_tsize << PAGE_SHIFT)
#define START_STACK(u) (u.start_stack)
@@ -217,12 +211,6 @@ static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file,
dump_size = dump.u_ssize << PAGE_SHIFT;
DUMP_WRITE(dump_start, dump_size);
}
- /*
- * Finally dump the task struct. Not be used by gdb, but
- * could be useful
- */
- set_fs(KERNEL_DS);
- DUMP_WRITE(current, sizeof(*current));
end_coredump:
set_fs(fs);
return has_dumped;
diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h
index bc6abb7bc7ee..76561d20ea2f 100644
--- a/arch/x86/include/asm/alternative.h
+++ b/arch/x86/include/asm/alternative.h
@@ -4,6 +4,7 @@
#include <linux/types.h>
#include <linux/stddef.h>
#include <linux/stringify.h>
+#include <linux/jump_label.h>
#include <asm/asm.h>
/*
@@ -160,6 +161,8 @@ static inline void apply_paravirt(struct paravirt_patch_site *start,
#define __parainstructions_end NULL
#endif
+extern void *text_poke_early(void *addr, const void *opcode, size_t len);
+
/*
* Clear and restore the kernel write-protection flag on the local CPU.
* Allows the kernel to edit read-only pages.
@@ -180,4 +183,12 @@ static inline void apply_paravirt(struct paravirt_patch_site *start,
extern void *text_poke(void *addr, const void *opcode, size_t len);
extern void *text_poke_smp(void *addr, const void *opcode, size_t len);
+#if defined(CONFIG_DYNAMIC_FTRACE) || defined(HAVE_JUMP_LABEL)
+#define IDEAL_NOP_SIZE_5 5
+extern unsigned char ideal_nop5[IDEAL_NOP_SIZE_5];
+extern void arch_init_ideal_nop5(void);
+#else
+static inline void arch_init_ideal_nop5(void) {}
+#endif
+
#endif /* _ASM_X86_ALTERNATIVE_H */
diff --git a/arch/x86/include/asm/amd_iommu.h b/arch/x86/include/asm/amd_iommu.h
index 5af2982133b5..a6863a2dec1f 100644
--- a/arch/x86/include/asm/amd_iommu.h
+++ b/arch/x86/include/asm/amd_iommu.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007-2009 Advanced Micro Devices, Inc.
+ * Copyright (C) 2007-2010 Advanced Micro Devices, Inc.
* Author: Joerg Roedel <joerg.roedel@amd.com>
* Leo Duran <leo.duran@amd.com>
*
@@ -24,11 +24,11 @@
#ifdef CONFIG_AMD_IOMMU
-extern void amd_iommu_detect(void);
+extern int amd_iommu_detect(void);
#else
-static inline void amd_iommu_detect(void) { }
+static inline int amd_iommu_detect(void) { return -ENODEV; }
#endif
diff --git a/arch/x86/include/asm/amd_iommu_proto.h b/arch/x86/include/asm/amd_iommu_proto.h
index cb030374b90a..916bc8111a01 100644
--- a/arch/x86/include/asm/amd_iommu_proto.h
+++ b/arch/x86/include/asm/amd_iommu_proto.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 Advanced Micro Devices, Inc.
+ * Copyright (C) 2009-2010 Advanced Micro Devices, Inc.
* Author: Joerg Roedel <joerg.roedel@amd.com>
*
* This program is free software; you can redistribute it and/or modify it
diff --git a/arch/x86/include/asm/amd_iommu_types.h b/arch/x86/include/asm/amd_iommu_types.h
index 08616180deaf..e3509fc303bf 100644
--- a/arch/x86/include/asm/amd_iommu_types.h
+++ b/arch/x86/include/asm/amd_iommu_types.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007-2009 Advanced Micro Devices, Inc.
+ * Copyright (C) 2007-2010 Advanced Micro Devices, Inc.
* Author: Joerg Roedel <joerg.roedel@amd.com>
* Leo Duran <leo.duran@amd.com>
*
@@ -416,13 +416,22 @@ struct amd_iommu {
struct dma_ops_domain *default_dom;
/*
- * This array is required to work around a potential BIOS bug.
- * The BIOS may miss to restore parts of the PCI configuration
- * space when the system resumes from S3. The result is that the
- * IOMMU does not execute commands anymore which leads to system
- * failure.
+ * We can't rely on the BIOS to restore all values on reinit, so we
+ * need to stash them
*/
- u32 cache_cfg[4];
+
+ /* The iommu BAR */
+ u32 stored_addr_lo;
+ u32 stored_addr_hi;
+
+ /*
+ * Each iommu has 6 l1s, each of which is documented as having 0x12
+ * registers
+ */
+ u32 stored_l1[6][0x12];
+
+ /* The l2 indirect registers */
+ u32 stored_l2[0x83];
};
/*
diff --git a/arch/x86/include/asm/k8.h b/arch/x86/include/asm/amd_nb.h
index af00bd1d2089..c8517f81b21e 100644
--- a/arch/x86/include/asm/k8.h
+++ b/arch/x86/include/asm/amd_nb.h
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_K8_H
-#define _ASM_X86_K8_H
+#ifndef _ASM_X86_AMD_NB_H
+#define _ASM_X86_AMD_NB_H
#include <linux/pci.h>
@@ -7,24 +7,27 @@ extern struct pci_device_id k8_nb_ids[];
struct bootnode;
extern int early_is_k8_nb(u32 value);
-extern struct pci_dev **k8_northbridges;
-extern int num_k8_northbridges;
extern int cache_k8_northbridges(void);
extern void k8_flush_garts(void);
extern int k8_get_nodes(struct bootnode *nodes);
extern int k8_numa_init(unsigned long start_pfn, unsigned long end_pfn);
extern int k8_scan_nodes(void);
-#ifdef CONFIG_K8_NB
-extern int num_k8_northbridges;
+struct k8_northbridge_info {
+ u16 num;
+ u8 gart_supported;
+ struct pci_dev **nb_misc;
+};
+extern struct k8_northbridge_info k8_northbridges;
+
+#ifdef CONFIG_AMD_NB
static inline struct pci_dev *node_to_k8_nb_misc(int node)
{
- return (node < num_k8_northbridges) ? k8_northbridges[node] : NULL;
+ return (node < k8_northbridges.num) ? k8_northbridges.nb_misc[node] : NULL;
}
#else
-#define num_k8_northbridges 0
static inline struct pci_dev *node_to_k8_nb_misc(int node)
{
@@ -33,4 +36,4 @@ static inline struct pci_dev *node_to_k8_nb_misc(int node)
#endif
-#endif /* _ASM_X86_K8_H */
+#endif /* _ASM_X86_AMD_NB_H */
diff --git a/arch/x86/include/asm/apb_timer.h b/arch/x86/include/asm/apb_timer.h
index a69b1ac9eaf8..2fefa501d3ba 100644
--- a/arch/x86/include/asm/apb_timer.h
+++ b/arch/x86/include/asm/apb_timer.h
@@ -54,7 +54,6 @@ extern struct clock_event_device *global_clock_event;
extern unsigned long apbt_quick_calibrate(void);
extern int arch_setup_apbt_irqs(int irq, int trigger, int mask, int cpu);
extern void apbt_setup_secondary_clock(void);
-extern unsigned int boot_cpu_id;
extern struct sfi_timer_table_entry *sfi_get_mtmr(int hint);
extern void sfi_free_mtmr(struct sfi_timer_table_entry *mtmr);
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index 1fa03e04ae44..286de34b0ed6 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -252,9 +252,7 @@ static inline int apic_is_clustered_box(void)
}
#endif
-extern u8 setup_APIC_eilvt_mce(u8 vector, u8 msg_type, u8 mask);
-extern u8 setup_APIC_eilvt_ibs(u8 vector, u8 msg_type, u8 mask);
-
+extern int setup_APIC_eilvt(u8 lvt_off, u8 vector, u8 msg_type, u8 mask);
#else /* !CONFIG_X86_LOCAL_APIC */
static inline void lapic_shutdown(void) { }
diff --git a/arch/x86/include/asm/apicdef.h b/arch/x86/include/asm/apicdef.h
index 7fe3b3060f08..a859ca461fb0 100644
--- a/arch/x86/include/asm/apicdef.h
+++ b/arch/x86/include/asm/apicdef.h
@@ -131,6 +131,7 @@
#define APIC_EILVTn(n) (0x500 + 0x10 * n)
#define APIC_EILVT_NR_AMD_K8 1 /* # of extended interrupts */
#define APIC_EILVT_NR_AMD_10H 4
+#define APIC_EILVT_NR_MAX APIC_EILVT_NR_AMD_10H
#define APIC_EILVT_LVTOFF(x) (((x) >> 4) & 0xF)
#define APIC_EILVT_MSG_FIX 0x0
#define APIC_EILVT_MSG_SMI 0x2
diff --git a/arch/x86/include/asm/bitops.h b/arch/x86/include/asm/bitops.h
index bafd80defa43..903683b07e42 100644
--- a/arch/x86/include/asm/bitops.h
+++ b/arch/x86/include/asm/bitops.h
@@ -440,6 +440,8 @@ static inline int fls(int x)
#ifdef __KERNEL__
+#include <asm-generic/bitops/find.h>
+
#include <asm-generic/bitops/sched.h>
#define ARCH_HAS_FAST_MULTIPLIER 1
diff --git a/arch/x86/include/asm/calgary.h b/arch/x86/include/asm/calgary.h
index 0918654305af..0d467b338835 100644
--- a/arch/x86/include/asm/calgary.h
+++ b/arch/x86/include/asm/calgary.h
@@ -62,9 +62,9 @@ struct cal_chipset_ops {
extern int use_calgary;
#ifdef CONFIG_CALGARY_IOMMU
-extern void detect_calgary(void);
+extern int detect_calgary(void);
#else
-static inline void detect_calgary(void) { return; }
+static inline int detect_calgary(void) { return -ENODEV; }
#endif
#endif /* _ASM_X86_CALGARY_H */
diff --git a/arch/x86/include/asm/calling.h b/arch/x86/include/asm/calling.h
index 0e63c9a2a8d0..30af5a832163 100644
--- a/arch/x86/include/asm/calling.h
+++ b/arch/x86/include/asm/calling.h
@@ -48,36 +48,38 @@ For 32-bit we have the following conventions - kernel is built with
/*
- * 64-bit system call stack frame layout defines and helpers,
- * for assembly code:
+ * 64-bit system call stack frame layout defines and helpers, for
+ * assembly code (note that the seemingly unnecessary parentheses
+ * are to prevent cpp from inserting spaces in expressions that get
+ * passed to macros):
*/
-#define R15 0
-#define R14 8
-#define R13 16
-#define R12 24
-#define RBP 32
-#define RBX 40
+#define R15 (0)
+#define R14 (8)
+#define R13 (16)
+#define R12 (24)
+#define RBP (32)
+#define RBX (40)
/* arguments: interrupts/non tracing syscalls only save up to here: */
-#define R11 48
-#define R10 56
-#define R9 64
-#define R8 72
-#define RAX 80
-#define RCX 88
-#define RDX 96
-#define RSI 104
-#define RDI 112
-#define ORIG_RAX 120 /* + error_code */
+#define R11 (48)
+#define R10 (56)
+#define R9 (64)
+#define R8 (72)
+#define RAX (80)
+#define RCX (88)
+#define RDX (96)
+#define RSI (104)
+#define RDI (112)
+#define ORIG_RAX (120) /* + error_code */
/* end of arguments */
/* cpu exception frame or undefined in case of fast syscall: */
-#define RIP 128
-#define CS 136
-#define EFLAGS 144
-#define RSP 152
-#define SS 160
+#define RIP (128)
+#define CS (136)
+#define EFLAGS (144)
+#define RSP (152)
+#define SS (160)
#define ARGOFFSET R11
#define SWFRAME ORIG_RAX
@@ -111,7 +113,7 @@ For 32-bit we have the following conventions - kernel is built with
.endif
.endm
-#define ARG_SKIP 9*8
+#define ARG_SKIP (9*8)
.macro RESTORE_ARGS skiprax=0, addskip=0, skiprcx=0, skipr11=0, \
skipr8910=0, skiprdx=0
@@ -169,7 +171,7 @@ For 32-bit we have the following conventions - kernel is built with
.endif
.endm
-#define REST_SKIP 6*8
+#define REST_SKIP (6*8)
.macro SAVE_REST
subq $REST_SKIP, %rsp
diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h
index b185091bf19c..4fab24de26b1 100644
--- a/arch/x86/include/asm/cpu.h
+++ b/arch/x86/include/asm/cpu.h
@@ -32,6 +32,5 @@ extern void arch_unregister_cpu(int);
DECLARE_PER_CPU(int, cpu_state);
-extern unsigned int boot_cpu_id;
#endif /* _ASM_X86_CPU_H */
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index 3f76523589af..220e2ea08e80 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -152,10 +152,14 @@
#define X86_FEATURE_3DNOWPREFETCH (6*32+ 8) /* 3DNow prefetch instructions */
#define X86_FEATURE_OSVW (6*32+ 9) /* OS Visible Workaround */
#define X86_FEATURE_IBS (6*32+10) /* Instruction Based Sampling */
-#define X86_FEATURE_SSE5 (6*32+11) /* SSE-5 */
+#define X86_FEATURE_XOP (6*32+11) /* extended AVX instructions */
#define X86_FEATURE_SKINIT (6*32+12) /* SKINIT/STGI instructions */
#define X86_FEATURE_WDT (6*32+13) /* Watchdog timer */
+#define X86_FEATURE_LWP (6*32+15) /* Light Weight Profiling */
+#define X86_FEATURE_FMA4 (6*32+16) /* 4 operands MAC instructions */
#define X86_FEATURE_NODEID_MSR (6*32+19) /* NodeId MSR */
+#define X86_FEATURE_TBM (6*32+21) /* trailing bit manipulations */
+#define X86_FEATURE_TOPOEXT (6*32+22) /* topology extensions CPUID leafs */
/*
* Auxiliary flags: Linux defined - For features scattered in various
@@ -180,6 +184,13 @@
#define X86_FEATURE_LBRV (8*32+ 6) /* AMD LBR Virtualization support */
#define X86_FEATURE_SVML (8*32+ 7) /* "svm_lock" AMD SVM locking MSR */
#define X86_FEATURE_NRIPS (8*32+ 8) /* "nrip_save" AMD SVM next_rip save */
+#define X86_FEATURE_TSCRATEMSR (8*32+ 9) /* "tsc_scale" AMD TSC scaling support */
+#define X86_FEATURE_VMCBCLEAN (8*32+10) /* "vmcb_clean" AMD VMCB clean bits support */
+#define X86_FEATURE_FLUSHBYASID (8*32+11) /* AMD flush-by-ASID support */
+#define X86_FEATURE_DECODEASSISTS (8*32+12) /* AMD Decode Assists support */
+#define X86_FEATURE_PAUSEFILTER (8*32+13) /* AMD filtered pause intercept */
+#define X86_FEATURE_PFTHRESHOLD (8*32+14) /* AMD pause filter threshold */
+
/* Intel-defined CPU features, CPUID level 0x00000007:0 (ebx), word 9 */
#define X86_FEATURE_FSGSBASE (9*32+ 0) /* {RD/WR}{FS/GS}BASE instructions*/
diff --git a/arch/x86/include/asm/dwarf2.h b/arch/x86/include/asm/dwarf2.h
index 733f7e91e7a9..326099199318 100644
--- a/arch/x86/include/asm/dwarf2.h
+++ b/arch/x86/include/asm/dwarf2.h
@@ -89,6 +89,16 @@
CFI_ADJUST_CFA_OFFSET -8
.endm
+ .macro pushfq_cfi
+ pushfq
+ CFI_ADJUST_CFA_OFFSET 8
+ .endm
+
+ .macro popfq_cfi
+ popfq
+ CFI_ADJUST_CFA_OFFSET -8
+ .endm
+
.macro movq_cfi reg offset=0
movq %\reg, \offset(%rsp)
CFI_REL_OFFSET \reg, \offset
@@ -109,6 +119,16 @@
CFI_ADJUST_CFA_OFFSET -4
.endm
+ .macro pushfl_cfi
+ pushfl
+ CFI_ADJUST_CFA_OFFSET 4
+ .endm
+
+ .macro popfl_cfi
+ popfl
+ CFI_ADJUST_CFA_OFFSET -4
+ .endm
+
.macro movl_cfi reg offset=0
movl %\reg, \offset(%esp)
CFI_REL_OFFSET \reg, \offset
diff --git a/arch/x86/include/asm/e820.h b/arch/x86/include/asm/e820.h
index ec8a52d14ab1..5be1542fbfaf 100644
--- a/arch/x86/include/asm/e820.h
+++ b/arch/x86/include/asm/e820.h
@@ -112,23 +112,13 @@ static inline void early_memtest(unsigned long start, unsigned long end)
}
#endif
-extern unsigned long end_user_pfn;
-
-extern u64 find_e820_area(u64 start, u64 end, u64 size, u64 align);
-extern u64 find_e820_area_size(u64 start, u64 *sizep, u64 align);
-extern u64 early_reserve_e820(u64 startt, u64 sizet, u64 align);
-#include <linux/early_res.h>
-
extern unsigned long e820_end_of_ram_pfn(void);
extern unsigned long e820_end_of_low_ram_pfn(void);
-extern int e820_find_active_region(const struct e820entry *ei,
- unsigned long start_pfn,
- unsigned long last_pfn,
- unsigned long *ei_startpfn,
- unsigned long *ei_endpfn);
-extern void e820_register_active_regions(int nid, unsigned long start_pfn,
- unsigned long end_pfn);
-extern u64 e820_hole_size(u64 start, u64 end);
+extern u64 early_reserve_e820(u64 startt, u64 sizet, u64 align);
+
+void memblock_x86_fill(void);
+void memblock_find_dma_reserve(void);
+
extern void finish_e820_parsing(void);
extern void e820_reserve_resources(void);
extern void e820_reserve_resources_late(void);
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
index 8406ed7f9926..8e4a16508d4e 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -90,7 +90,7 @@ extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size,
#endif /* CONFIG_X86_32 */
extern int add_efi_memmap;
-extern void efi_reserve_early(void);
+extern void efi_memblock_x86_reserve_range(void);
extern void efi_call_phys_prelog(void);
extern void efi_call_phys_epilog(void);
diff --git a/arch/x86/include/asm/entry_arch.h b/arch/x86/include/asm/entry_arch.h
index 8e8ec663a98f..57650ab4a5f5 100644
--- a/arch/x86/include/asm/entry_arch.h
+++ b/arch/x86/include/asm/entry_arch.h
@@ -16,22 +16,11 @@ BUILD_INTERRUPT(call_function_single_interrupt,CALL_FUNCTION_SINGLE_VECTOR)
BUILD_INTERRUPT(irq_move_cleanup_interrupt,IRQ_MOVE_CLEANUP_VECTOR)
BUILD_INTERRUPT(reboot_interrupt,REBOOT_VECTOR)
-BUILD_INTERRUPT3(invalidate_interrupt0,INVALIDATE_TLB_VECTOR_START+0,
- smp_invalidate_interrupt)
-BUILD_INTERRUPT3(invalidate_interrupt1,INVALIDATE_TLB_VECTOR_START+1,
- smp_invalidate_interrupt)
-BUILD_INTERRUPT3(invalidate_interrupt2,INVALIDATE_TLB_VECTOR_START+2,
- smp_invalidate_interrupt)
-BUILD_INTERRUPT3(invalidate_interrupt3,INVALIDATE_TLB_VECTOR_START+3,
- smp_invalidate_interrupt)
-BUILD_INTERRUPT3(invalidate_interrupt4,INVALIDATE_TLB_VECTOR_START+4,
- smp_invalidate_interrupt)
-BUILD_INTERRUPT3(invalidate_interrupt5,INVALIDATE_TLB_VECTOR_START+5,
- smp_invalidate_interrupt)
-BUILD_INTERRUPT3(invalidate_interrupt6,INVALIDATE_TLB_VECTOR_START+6,
- smp_invalidate_interrupt)
-BUILD_INTERRUPT3(invalidate_interrupt7,INVALIDATE_TLB_VECTOR_START+7,
+.irpc idx, "01234567"
+BUILD_INTERRUPT3(invalidate_interrupt\idx,
+ (INVALIDATE_TLB_VECTOR_START)+\idx,
smp_invalidate_interrupt)
+.endr
#endif
BUILD_INTERRUPT(x86_platform_ipi, X86_PLATFORM_IPI_VECTOR)
@@ -49,8 +38,8 @@ BUILD_INTERRUPT(apic_timer_interrupt,LOCAL_TIMER_VECTOR)
BUILD_INTERRUPT(error_interrupt,ERROR_APIC_VECTOR)
BUILD_INTERRUPT(spurious_interrupt,SPURIOUS_APIC_VECTOR)
-#ifdef CONFIG_PERF_EVENTS
-BUILD_INTERRUPT(perf_pending_interrupt, LOCAL_PENDING_VECTOR)
+#ifdef CONFIG_IRQ_WORK
+BUILD_INTERRUPT(irq_work_interrupt, IRQ_WORK_VECTOR)
#endif
#ifdef CONFIG_X86_THERMAL_VECTOR
diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h
index d07b44f7d1dc..4d293dced62f 100644
--- a/arch/x86/include/asm/fixmap.h
+++ b/arch/x86/include/asm/fixmap.h
@@ -214,5 +214,20 @@ static inline unsigned long virt_to_fix(const unsigned long vaddr)
BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START);
return __virt_to_fix(vaddr);
}
+
+/* Return an pointer with offset calculated */
+static inline unsigned long __set_fixmap_offset(enum fixed_addresses idx,
+ phys_addr_t phys, pgprot_t flags)
+{
+ __set_fixmap(idx, phys, flags);
+ return fix_to_virt(idx) + (phys & (PAGE_SIZE - 1));
+}
+
+#define set_fixmap_offset(idx, phys) \
+ __set_fixmap_offset(idx, phys, PAGE_KERNEL)
+
+#define set_fixmap_offset_nocache(idx, phys) \
+ __set_fixmap_offset(idx, phys, PAGE_KERNEL_NOCACHE)
+
#endif /* !__ASSEMBLY__ */
#endif /* _ASM_X86_FIXMAP_H */
diff --git a/arch/x86/include/asm/gart.h b/arch/x86/include/asm/gart.h
index 4ac5b0f33fc1..43085bfc99c3 100644
--- a/arch/x86/include/asm/gart.h
+++ b/arch/x86/include/asm/gart.h
@@ -17,6 +17,7 @@ extern int fix_aperture;
#define GARTEN (1<<0)
#define DISGARTCPU (1<<4)
#define DISGARTIO (1<<5)
+#define DISTLBWALKPRB (1<<6)
/* GART cache control register bits. */
#define INVGART (1<<0)
@@ -27,7 +28,6 @@ extern int fix_aperture;
#define AMD64_GARTAPERTUREBASE 0x94
#define AMD64_GARTTABLEBASE 0x98
#define AMD64_GARTCACHECTL 0x9c
-#define AMD64_GARTEN (1<<0)
#ifdef CONFIG_GART_IOMMU
extern int gart_iommu_aperture;
@@ -37,7 +37,7 @@ extern int gart_iommu_aperture_disabled;
extern void early_gart_iommu_check(void);
extern int gart_iommu_init(void);
extern void __init gart_parse_options(char *);
-extern void gart_iommu_hole_init(void);
+extern int gart_iommu_hole_init(void);
#else
#define gart_iommu_aperture 0
@@ -50,13 +50,27 @@ static inline void early_gart_iommu_check(void)
static inline void gart_parse_options(char *options)
{
}
-static inline void gart_iommu_hole_init(void)
+static inline int gart_iommu_hole_init(void)
{
+ return -ENODEV;
}
#endif
extern int agp_amd64_init(void);
+static inline void gart_set_size_and_enable(struct pci_dev *dev, u32 order)
+{
+ u32 ctl;
+
+ /*
+ * Don't enable translation but enable GART IO and CPU accesses.
+ * Also, set DISTLBWALKPRB since GART tables memory is UC.
+ */
+ ctl = DISTLBWALKPRB | order << 1;
+
+ pci_write_config_dword(dev, AMD64_GARTAPERTURECTL, ctl);
+}
+
static inline void enable_gart_translation(struct pci_dev *dev, u64 addr)
{
u32 tmp, ctl;
diff --git a/arch/x86/include/asm/hardirq.h b/arch/x86/include/asm/hardirq.h
index aeab29aee617..55e4de613f0e 100644
--- a/arch/x86/include/asm/hardirq.h
+++ b/arch/x86/include/asm/hardirq.h
@@ -14,7 +14,7 @@ typedef struct {
#endif
unsigned int x86_platform_ipis; /* arch dependent */
unsigned int apic_perf_irqs;
- unsigned int apic_pending_irqs;
+ unsigned int apic_irq_work_irqs;
#ifdef CONFIG_SMP
unsigned int irq_resched_count;
unsigned int irq_call_count;
diff --git a/arch/x86/include/asm/hpet.h b/arch/x86/include/asm/hpet.h
index 1d5c08a1bdfd..2c392d663dce 100644
--- a/arch/x86/include/asm/hpet.h
+++ b/arch/x86/include/asm/hpet.h
@@ -74,10 +74,12 @@ extern void hpet_disable(void);
extern unsigned int hpet_readl(unsigned int a);
extern void force_hpet_resume(void);
-extern void hpet_msi_unmask(unsigned int irq);
-extern void hpet_msi_mask(unsigned int irq);
-extern void hpet_msi_write(unsigned int irq, struct msi_msg *msg);
-extern void hpet_msi_read(unsigned int irq, struct msi_msg *msg);
+struct irq_data;
+extern void hpet_msi_unmask(struct irq_data *data);
+extern void hpet_msi_mask(struct irq_data *data);
+struct hpet_dev;
+extern void hpet_msi_write(struct hpet_dev *hdev, struct msi_msg *msg);
+extern void hpet_msi_read(struct hpet_dev *hdev, struct msi_msg *msg);
#ifdef CONFIG_PCI_MSI
extern int arch_setup_hpet_msi(unsigned int irq, unsigned int id);
diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h
index 46c0fe05f230..0274ec5a7e62 100644
--- a/arch/x86/include/asm/hw_irq.h
+++ b/arch/x86/include/asm/hw_irq.h
@@ -29,7 +29,7 @@
extern void apic_timer_interrupt(void);
extern void x86_platform_ipi(void);
extern void error_interrupt(void);
-extern void perf_pending_interrupt(void);
+extern void irq_work_interrupt(void);
extern void spurious_interrupt(void);
extern void thermal_interrupt(void);
@@ -78,6 +78,13 @@ static inline void set_io_apic_irq_attr(struct io_apic_irq_attr *irq_attr,
irq_attr->polarity = polarity;
}
+struct irq_2_iommu {
+ struct intel_iommu *iommu;
+ u16 irte_index;
+ u16 sub_handle;
+ u8 irte_mask;
+};
+
/*
* This is performance-critical, we want to do it O(1)
*
@@ -89,15 +96,17 @@ struct irq_cfg {
cpumask_var_t old_domain;
u8 vector;
u8 move_in_progress : 1;
+#ifdef CONFIG_INTR_REMAP
+ struct irq_2_iommu irq_2_iommu;
+#endif
};
-extern struct irq_cfg *irq_cfg(unsigned int);
extern int assign_irq_vector(int, struct irq_cfg *, const struct cpumask *);
extern void send_cleanup_vector(struct irq_cfg *);
-struct irq_desc;
-extern unsigned int set_desc_affinity(struct irq_desc *, const struct cpumask *,
- unsigned int *dest_id);
+struct irq_data;
+int __ioapic_set_affinity(struct irq_data *, const struct cpumask *,
+ unsigned int *dest_id);
extern int IO_APIC_get_PCI_irq_vector(int bus, int devfn, int pin, struct io_apic_irq_attr *irq_attr);
extern void setup_ioapic_dest(void);
diff --git a/arch/x86/include/asm/i387.h b/arch/x86/include/asm/i387.h
index a73a8d5a5e69..4aa2bb3b242a 100644
--- a/arch/x86/include/asm/i387.h
+++ b/arch/x86/include/asm/i387.h
@@ -55,6 +55,12 @@ extern int save_i387_xstate_ia32(void __user *buf);
extern int restore_i387_xstate_ia32(void __user *buf);
#endif
+#ifdef CONFIG_MATH_EMULATION
+extern void finit_soft_fpu(struct i387_soft_struct *soft);
+#else
+static inline void finit_soft_fpu(struct i387_soft_struct *soft) {}
+#endif
+
#define X87_FSW_ES (1 << 7) /* Exception Summary */
static __always_inline __pure bool use_xsaveopt(void)
@@ -67,6 +73,11 @@ static __always_inline __pure bool use_xsave(void)
return static_cpu_has(X86_FEATURE_XSAVE);
}
+static __always_inline __pure bool use_fxsr(void)
+{
+ return static_cpu_has(X86_FEATURE_FXSR);
+}
+
extern void __sanitize_i387_state(struct task_struct *);
static inline void sanitize_i387_state(struct task_struct *tsk)
@@ -77,19 +88,11 @@ static inline void sanitize_i387_state(struct task_struct *tsk)
}
#ifdef CONFIG_X86_64
-
-/* Ignore delayed exceptions from user space */
-static inline void tolerant_fwait(void)
-{
- asm volatile("1: fwait\n"
- "2:\n"
- _ASM_EXTABLE(1b, 2b));
-}
-
static inline int fxrstor_checking(struct i387_fxsave_struct *fx)
{
int err;
+ /* See comment in fxsave() below. */
asm volatile("1: rex64/fxrstor (%[fx])\n\t"
"2:\n"
".section .fixup,\"ax\"\n"
@@ -98,44 +101,10 @@ static inline int fxrstor_checking(struct i387_fxsave_struct *fx)
".previous\n"
_ASM_EXTABLE(1b, 3b)
: [err] "=r" (err)
-#if 0 /* See comment in fxsave() below. */
- : [fx] "r" (fx), "m" (*fx), "0" (0));
-#else
- : [fx] "cdaSDb" (fx), "m" (*fx), "0" (0));
-#endif
+ : [fx] "R" (fx), "m" (*fx), "0" (0));
return err;
}
-/* AMD CPUs don't save/restore FDP/FIP/FOP unless an exception
- is pending. Clear the x87 state here by setting it to fixed
- values. The kernel data segment can be sometimes 0 and sometimes
- new user value. Both should be ok.
- Use the PDA as safe address because it should be already in L1. */
-static inline void fpu_clear(struct fpu *fpu)
-{
- struct xsave_struct *xstate = &fpu->state->xsave;
- struct i387_fxsave_struct *fx = &fpu->state->fxsave;
-
- /*
- * xsave header may indicate the init state of the FP.
- */
- if (use_xsave() &&
- !(xstate->xsave_hdr.xstate_bv & XSTATE_FP))
- return;
-
- if (unlikely(fx->swd & X87_FSW_ES))
- asm volatile("fnclex");
- alternative_input(ASM_NOP8 ASM_NOP2,
- " emms\n" /* clear stack tags */
- " fildl %%gs:0", /* load to clear state */
- X86_FEATURE_FXSAVE_LEAK);
-}
-
-static inline void clear_fpu_state(struct task_struct *tsk)
-{
- fpu_clear(&tsk->thread.fpu);
-}
-
static inline int fxsave_user(struct i387_fxsave_struct __user *fx)
{
int err;
@@ -149,6 +118,7 @@ static inline int fxsave_user(struct i387_fxsave_struct __user *fx)
if (unlikely(err))
return -EFAULT;
+ /* See comment in fxsave() below. */
asm volatile("1: rex64/fxsave (%[fx])\n\t"
"2:\n"
".section .fixup,\"ax\"\n"
@@ -157,11 +127,7 @@ static inline int fxsave_user(struct i387_fxsave_struct __user *fx)
".previous\n"
_ASM_EXTABLE(1b, 3b)
: [err] "=r" (err), "=m" (*fx)
-#if 0 /* See comment in fxsave() below. */
- : [fx] "r" (fx), "0" (0));
-#else
- : [fx] "cdaSDb" (fx), "0" (0));
-#endif
+ : [fx] "R" (fx), "0" (0));
if (unlikely(err) &&
__clear_user(fx, sizeof(struct i387_fxsave_struct)))
err = -EFAULT;
@@ -175,56 +141,29 @@ static inline void fpu_fxsave(struct fpu *fpu)
uses any extended registers for addressing, a second REX prefix
will be generated (to the assembler, rex64 followed by semicolon
is a separate instruction), and hence the 64-bitness is lost. */
-#if 0
+
+#ifdef CONFIG_AS_FXSAVEQ
/* Using "fxsaveq %0" would be the ideal choice, but is only supported
starting with gas 2.16. */
__asm__ __volatile__("fxsaveq %0"
: "=m" (fpu->state->fxsave));
-#elif 0
+#else
/* Using, as a workaround, the properly prefixed form below isn't
accepted by any binutils version so far released, complaining that
the same type of prefix is used twice if an extended register is
- needed for addressing (fix submitted to mainline 2005-11-21). */
- __asm__ __volatile__("rex64/fxsave %0"
- : "=m" (fpu->state->fxsave));
-#else
- /* This, however, we can work around by forcing the compiler to select
+ needed for addressing (fix submitted to mainline 2005-11-21).
+ asm volatile("rex64/fxsave %0"
+ : "=m" (fpu->state->fxsave));
+ This, however, we can work around by forcing the compiler to select
an addressing mode that doesn't require extended registers. */
- __asm__ __volatile__("rex64/fxsave (%1)"
- : "=m" (fpu->state->fxsave)
- : "cdaSDb" (&fpu->state->fxsave));
+ asm volatile("rex64/fxsave (%[fx])"
+ : "=m" (fpu->state->fxsave)
+ : [fx] "R" (&fpu->state->fxsave));
#endif
}
-static inline void fpu_save_init(struct fpu *fpu)
-{
- if (use_xsave())
- fpu_xsave(fpu);
- else
- fpu_fxsave(fpu);
-
- fpu_clear(fpu);
-}
-
-static inline void __save_init_fpu(struct task_struct *tsk)
-{
- fpu_save_init(&tsk->thread.fpu);
- task_thread_info(tsk)->status &= ~TS_USEDFPU;
-}
-
#else /* CONFIG_X86_32 */
-#ifdef CONFIG_MATH_EMULATION
-extern void finit_soft_fpu(struct i387_soft_struct *soft);
-#else
-static inline void finit_soft_fpu(struct i387_soft_struct *soft) {}
-#endif
-
-static inline void tolerant_fwait(void)
-{
- asm volatile("fnclex ; fwait");
-}
-
/* perform fxrstor iff the processor has extended states, otherwise frstor */
static inline int fxrstor_checking(struct i387_fxsave_struct *fx)
{
@@ -241,6 +180,14 @@ static inline int fxrstor_checking(struct i387_fxsave_struct *fx)
return 0;
}
+static inline void fpu_fxsave(struct fpu *fpu)
+{
+ asm volatile("fxsave %[fx]"
+ : [fx] "=m" (fpu->state->fxsave));
+}
+
+#endif /* CONFIG_X86_64 */
+
/* We need a safe address that is cheap to find and that is already
in L1 during context switch. The best choices are unfortunately
different for UP and SMP */
@@ -256,47 +203,33 @@ static inline int fxrstor_checking(struct i387_fxsave_struct *fx)
static inline void fpu_save_init(struct fpu *fpu)
{
if (use_xsave()) {
- struct xsave_struct *xstate = &fpu->state->xsave;
- struct i387_fxsave_struct *fx = &fpu->state->fxsave;
-
fpu_xsave(fpu);
/*
* xsave header may indicate the init state of the FP.
*/
- if (!(xstate->xsave_hdr.xstate_bv & XSTATE_FP))
- goto end;
-
- if (unlikely(fx->swd & X87_FSW_ES))
- asm volatile("fnclex");
-
- /*
- * we can do a simple return here or be paranoid :)
- */
- goto clear_state;
+ if (!(fpu->state->xsave.xsave_hdr.xstate_bv & XSTATE_FP))
+ return;
+ } else if (use_fxsr()) {
+ fpu_fxsave(fpu);
+ } else {
+ asm volatile("fsave %[fx]; fwait"
+ : [fx] "=m" (fpu->state->fsave));
+ return;
}
- /* Use more nops than strictly needed in case the compiler
- varies code */
- alternative_input(
- "fnsave %[fx] ;fwait;" GENERIC_NOP8 GENERIC_NOP4,
- "fxsave %[fx]\n"
- "bt $7,%[fsw] ; jnc 1f ; fnclex\n1:",
- X86_FEATURE_FXSR,
- [fx] "m" (fpu->state->fxsave),
- [fsw] "m" (fpu->state->fxsave.swd) : "memory");
-clear_state:
+ if (unlikely(fpu->state->fxsave.swd & X87_FSW_ES))
+ asm volatile("fnclex");
+
/* AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception
is pending. Clear the x87 state here by setting it to fixed
values. safe_address is a random variable that should be in L1 */
alternative_input(
- GENERIC_NOP8 GENERIC_NOP2,
+ ASM_NOP8 ASM_NOP2,
"emms\n\t" /* clear stack tags */
- "fildl %[addr]", /* set F?P to defined value */
+ "fildl %P[addr]", /* set F?P to defined value */
X86_FEATURE_FXSAVE_LEAK,
[addr] "m" (safe_address));
-end:
- ;
}
static inline void __save_init_fpu(struct task_struct *tsk)
@@ -305,9 +238,6 @@ static inline void __save_init_fpu(struct task_struct *tsk)
task_thread_info(tsk)->status &= ~TS_USEDFPU;
}
-
-#endif /* CONFIG_X86_64 */
-
static inline int fpu_fxrstor_checking(struct fpu *fpu)
{
return fxrstor_checking(&fpu->state->fxsave);
@@ -344,7 +274,10 @@ static inline void __unlazy_fpu(struct task_struct *tsk)
static inline void __clear_fpu(struct task_struct *tsk)
{
if (task_thread_info(tsk)->status & TS_USEDFPU) {
- tolerant_fwait();
+ /* Ignore delayed exceptions from user space */
+ asm volatile("1: fwait\n"
+ "2:\n"
+ _ASM_EXTABLE(1b, 2b));
task_thread_info(tsk)->status &= ~TS_USEDFPU;
stts();
}
@@ -405,19 +338,6 @@ static inline void irq_ts_restore(int TS_state)
stts();
}
-#ifdef CONFIG_X86_64
-
-static inline void save_init_fpu(struct task_struct *tsk)
-{
- __save_init_fpu(tsk);
- stts();
-}
-
-#define unlazy_fpu __unlazy_fpu
-#define clear_fpu __clear_fpu
-
-#else /* CONFIG_X86_32 */
-
/*
* These disable preemption on their own and are safe
*/
@@ -443,8 +363,6 @@ static inline void clear_fpu(struct task_struct *tsk)
preempt_enable();
}
-#endif /* CONFIG_X86_64 */
-
/*
* i387 state interaction
*/
@@ -508,7 +426,4 @@ extern void fpu_finit(struct fpu *fpu);
#endif /* __ASSEMBLY__ */
-#define PSHUFB_XMM5_XMM0 .byte 0x66, 0x0f, 0x38, 0x00, 0xc5
-#define PSHUFB_XMM5_XMM6 .byte 0x66, 0x0f, 0x38, 0x00, 0xf5
-
#endif /* _ASM_X86_I387_H */
diff --git a/arch/x86/include/asm/i8259.h b/arch/x86/include/asm/i8259.h
index 1655147646aa..a20365953bf8 100644
--- a/arch/x86/include/asm/i8259.h
+++ b/arch/x86/include/asm/i8259.h
@@ -55,6 +55,8 @@ extern struct irq_chip i8259A_chip;
struct legacy_pic {
int nr_legacy_irqs;
struct irq_chip *chip;
+ void (*mask)(unsigned int irq);
+ void (*unmask)(unsigned int irq);
void (*mask_all)(void);
void (*restore_mask)(void);
void (*init)(int auto_eoi);
diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h
index 30a3e9776123..f0203f4791a8 100644
--- a/arch/x86/include/asm/io.h
+++ b/arch/x86/include/asm/io.h
@@ -206,6 +206,7 @@ static inline void __iomem *ioremap(resource_size_t offset, unsigned long size)
extern void iounmap(volatile void __iomem *addr);
+extern void set_iounmap_nonlazy(void);
#ifdef __KERNEL__
@@ -348,6 +349,7 @@ extern void __iomem *early_memremap(resource_size_t phys_addr,
unsigned long size);
extern void early_iounmap(void __iomem *addr, unsigned long size);
extern void fixup_early_ioremap(void);
+extern bool is_early_ioremap_ptep(pte_t *ptep);
#define IO_SPACE_LIMIT 0xffff
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index 9cb2edb87c2f..c8be4566c3d2 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -170,12 +170,6 @@ extern int restore_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
extern void probe_nr_irqs_gsi(void);
-extern int setup_ioapic_entry(int apic, int irq,
- struct IO_APIC_route_entry *entry,
- unsigned int destination, int trigger,
- int polarity, int vector, int pin);
-extern void ioapic_write_entry(int apic, int pin,
- struct IO_APIC_route_entry e);
extern void setup_ioapic_ids_from_mpc(void);
struct mp_ioapic_gsi{
diff --git a/arch/x86/include/asm/iommu_table.h b/arch/x86/include/asm/iommu_table.h
new file mode 100644
index 000000000000..f229b13a5f30
--- /dev/null
+++ b/arch/x86/include/asm/iommu_table.h
@@ -0,0 +1,100 @@
+#ifndef _ASM_X86_IOMMU_TABLE_H
+#define _ASM_X86_IOMMU_TABLE_H
+
+#include <asm/swiotlb.h>
+
+/*
+ * History lesson:
+ * The execution chain of IOMMUs in 2.6.36 looks as so:
+ *
+ * [xen-swiotlb]
+ * |
+ * +----[swiotlb *]--+
+ * / | \
+ * / | \
+ * [GART] [Calgary] [Intel VT-d]
+ * /
+ * /
+ * [AMD-Vi]
+ *
+ * *: if SWIOTLB detected 'iommu=soft'/'swiotlb=force' it would skip
+ * over the rest of IOMMUs and unconditionally initialize the SWIOTLB.
+ * Also it would surreptitiously initialize set the swiotlb=1 if there were
+ * more than 4GB and if the user did not pass in 'iommu=off'. The swiotlb
+ * flag would be turned off by all IOMMUs except the Calgary one.
+ *
+ * The IOMMU_INIT* macros allow a similar tree (or more complex if desired)
+ * to be built by defining who we depend on.
+ *
+ * And all that needs to be done is to use one of the macros in the IOMMU
+ * and the pci-dma.c will take care of the rest.
+ */
+
+struct iommu_table_entry {
+ initcall_t detect;
+ initcall_t depend;
+ void (*early_init)(void); /* No memory allocate available. */
+ void (*late_init)(void); /* Yes, can allocate memory. */
+#define IOMMU_FINISH_IF_DETECTED (1<<0)
+#define IOMMU_DETECTED (1<<1)
+ int flags;
+};
+/*
+ * Macro fills out an entry in the .iommu_table that is equivalent
+ * to the fields that 'struct iommu_table_entry' has. The entries
+ * that are put in the .iommu_table section are not put in any order
+ * hence during boot-time we will have to resort them based on
+ * dependency. */
+
+
+#define __IOMMU_INIT(_detect, _depend, _early_init, _late_init, _finish)\
+ static const struct iommu_table_entry const \
+ __iommu_entry_##_detect __used \
+ __attribute__ ((unused, __section__(".iommu_table"), \
+ aligned((sizeof(void *))))) \
+ = {_detect, _depend, _early_init, _late_init, \
+ _finish ? IOMMU_FINISH_IF_DETECTED : 0}
+/*
+ * The simplest IOMMU definition. Provide the detection routine
+ * and it will be run after the SWIOTLB and the other IOMMUs
+ * that utilize this macro. If the IOMMU is detected (ie, the
+ * detect routine returns a positive value), the other IOMMUs
+ * are also checked. You can use IOMMU_INIT_POST_FINISH if you prefer
+ * to stop detecting the other IOMMUs after yours has been detected.
+ */
+#define IOMMU_INIT_POST(_detect) \
+ __IOMMU_INIT(_detect, pci_swiotlb_detect_4gb, 0, 0, 0)
+
+#define IOMMU_INIT_POST_FINISH(detect) \
+ __IOMMU_INIT(_detect, pci_swiotlb_detect_4gb, 0, 0, 1)
+
+/*
+ * A more sophisticated version of IOMMU_INIT. This variant requires:
+ * a). A detection routine function.
+ * b). The name of the detection routine we depend on to get called
+ * before us.
+ * c). The init routine which gets called if the detection routine
+ * returns a positive value from the pci_iommu_alloc. This means
+ * no presence of a memory allocator.
+ * d). Similar to the 'init', except that this gets called from pci_iommu_init
+ * where we do have a memory allocator.
+ *
+ * The standard vs the _FINISH differs in that the _FINISH variant will
+ * continue detecting other IOMMUs in the call list after the
+ * the detection routine returns a positive number. The _FINISH will
+ * stop the execution chain. Both will still call the 'init' and
+ * 'late_init' functions if they are set.
+ */
+#define IOMMU_INIT_FINISH(_detect, _depend, _init, _late_init) \
+ __IOMMU_INIT(_detect, _depend, _init, _late_init, 1)
+
+#define IOMMU_INIT(_detect, _depend, _init, _late_init) \
+ __IOMMU_INIT(_detect, _depend, _init, _late_init, 0)
+
+void sort_iommu_table(struct iommu_table_entry *start,
+ struct iommu_table_entry *finish);
+
+void check_iommu_entries(struct iommu_table_entry *start,
+ struct iommu_table_entry *finish);
+
+#endif /* _ASM_X86_IOMMU_TABLE_H */
diff --git a/arch/x86/include/asm/irq.h b/arch/x86/include/asm/irq.h
index 5458380b6ef8..0bf5b0083650 100644
--- a/arch/x86/include/asm/irq.h
+++ b/arch/x86/include/asm/irq.h
@@ -19,18 +19,16 @@ static inline int irq_canonicalize(int irq)
# define ARCH_HAS_NMI_WATCHDOG
#endif
-#ifdef CONFIG_4KSTACKS
- extern void irq_ctx_init(int cpu);
- extern void irq_ctx_exit(int cpu);
-# define __ARCH_HAS_DO_SOFTIRQ
+#ifdef CONFIG_X86_32
+extern void irq_ctx_init(int cpu);
+extern void irq_ctx_exit(int cpu);
#else
# define irq_ctx_init(cpu) do { } while (0)
# define irq_ctx_exit(cpu) do { } while (0)
-# ifdef CONFIG_X86_64
-# define __ARCH_HAS_DO_SOFTIRQ
-# endif
#endif
+#define __ARCH_HAS_DO_SOFTIRQ
+
#ifdef CONFIG_HOTPLUG_CPU
#include <linux/cpumask.h>
extern void fixup_irqs(void);
diff --git a/arch/x86/include/asm/irq_remapping.h b/arch/x86/include/asm/irq_remapping.h
index f275e2244505..1c23360fb2d8 100644
--- a/arch/x86/include/asm/irq_remapping.h
+++ b/arch/x86/include/asm/irq_remapping.h
@@ -3,4 +3,39 @@
#define IRTE_DEST(dest) ((x2apic_mode) ? dest : dest << 8)
+#ifdef CONFIG_INTR_REMAP
+static inline void prepare_irte(struct irte *irte, int vector,
+ unsigned int dest)
+{
+ memset(irte, 0, sizeof(*irte));
+
+ irte->present = 1;
+ irte->dst_mode = apic->irq_dest_mode;
+ /*
+ * Trigger mode in the IRTE will always be edge, and for IO-APIC, the
+ * actual level or edge trigger will be setup in the IO-APIC
+ * RTE. This will help simplify level triggered irq migration.
+ * For more details, see the comments (in io_apic.c) explainig IO-APIC
+ * irq migration in the presence of interrupt-remapping.
+ */
+ irte->trigger_mode = 0;
+ irte->dlvry_mode = apic->irq_delivery_mode;
+ irte->vector = vector;
+ irte->dest_id = IRTE_DEST(dest);
+ irte->redir_hint = 1;
+}
+static inline bool irq_remapped(struct irq_cfg *cfg)
+{
+ return cfg->irq_2_iommu.iommu != NULL;
+}
+#else
+static void prepare_irte(struct irte *irte, int vector, unsigned int dest)
+{
+}
+static inline bool irq_remapped(struct irq_cfg *cfg)
+{
+ return false;
+}
+#endif
+
#endif /* _ASM_X86_IRQ_REMAPPING_H */
diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h
index e2ca30092557..6af0894dafb4 100644
--- a/arch/x86/include/asm/irq_vectors.h
+++ b/arch/x86/include/asm/irq_vectors.h
@@ -114,9 +114,9 @@
#define X86_PLATFORM_IPI_VECTOR 0xed
/*
- * Performance monitoring pending work vector:
+ * IRQ work vector:
*/
-#define LOCAL_PENDING_VECTOR 0xec
+#define IRQ_WORK_VECTOR 0xec
#define UV_BAU_MESSAGE 0xea
diff --git a/arch/x86/include/asm/irqflags.h b/arch/x86/include/asm/irqflags.h
index 9e2b952f810a..5745ce8bf108 100644
--- a/arch/x86/include/asm/irqflags.h
+++ b/arch/x86/include/asm/irqflags.h
@@ -61,22 +61,22 @@ static inline void native_halt(void)
#else
#ifndef __ASSEMBLY__
-static inline unsigned long __raw_local_save_flags(void)
+static inline unsigned long arch_local_save_flags(void)
{
return native_save_fl();
}
-static inline void raw_local_irq_restore(unsigned long flags)
+static inline void arch_local_irq_restore(unsigned long flags)
{
native_restore_fl(flags);
}
-static inline void raw_local_irq_disable(void)
+static inline void arch_local_irq_disable(void)
{
native_irq_disable();
}
-static inline void raw_local_irq_enable(void)
+static inline void arch_local_irq_enable(void)
{
native_irq_enable();
}
@@ -85,7 +85,7 @@ static inline void raw_local_irq_enable(void)
* Used in the idle loop; sti takes one instruction cycle
* to complete:
*/
-static inline void raw_safe_halt(void)
+static inline void arch_safe_halt(void)
{
native_safe_halt();
}
@@ -102,12 +102,10 @@ static inline void halt(void)
/*
* For spinlocks, etc:
*/
-static inline unsigned long __raw_local_irq_save(void)
+static inline unsigned long arch_local_irq_save(void)
{
- unsigned long flags = __raw_local_save_flags();
-
- raw_local_irq_disable();
-
+ unsigned long flags = arch_local_save_flags();
+ arch_local_irq_disable();
return flags;
}
#else
@@ -153,22 +151,16 @@ static inline unsigned long __raw_local_irq_save(void)
#endif /* CONFIG_PARAVIRT */
#ifndef __ASSEMBLY__
-#define raw_local_save_flags(flags) \
- do { (flags) = __raw_local_save_flags(); } while (0)
-
-#define raw_local_irq_save(flags) \
- do { (flags) = __raw_local_irq_save(); } while (0)
-
-static inline int raw_irqs_disabled_flags(unsigned long flags)
+static inline int arch_irqs_disabled_flags(unsigned long flags)
{
return !(flags & X86_EFLAGS_IF);
}
-static inline int raw_irqs_disabled(void)
+static inline int arch_irqs_disabled(void)
{
- unsigned long flags = __raw_local_save_flags();
+ unsigned long flags = arch_local_save_flags();
- return raw_irqs_disabled_flags(flags);
+ return arch_irqs_disabled_flags(flags);
}
#else
diff --git a/arch/x86/include/asm/jump_label.h b/arch/x86/include/asm/jump_label.h
new file mode 100644
index 000000000000..f52d42e80585
--- /dev/null
+++ b/arch/x86/include/asm/jump_label.h
@@ -0,0 +1,37 @@
+#ifndef _ASM_X86_JUMP_LABEL_H
+#define _ASM_X86_JUMP_LABEL_H
+
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+#include <asm/nops.h>
+
+#define JUMP_LABEL_NOP_SIZE 5
+
+# define JUMP_LABEL_INITIAL_NOP ".byte 0xe9 \n\t .long 0\n\t"
+
+# define JUMP_LABEL(key, label) \
+ do { \
+ asm goto("1:" \
+ JUMP_LABEL_INITIAL_NOP \
+ ".pushsection __jump_table, \"a\" \n\t"\
+ _ASM_PTR "1b, %l[" #label "], %c0 \n\t" \
+ ".popsection \n\t" \
+ : : "i" (key) : : label); \
+ } while (0)
+
+#endif /* __KERNEL__ */
+
+#ifdef CONFIG_X86_64
+typedef u64 jump_label_t;
+#else
+typedef u32 jump_label_t;
+#endif
+
+struct jump_entry {
+ jump_label_t code;
+ jump_label_t target;
+ jump_label_t key;
+};
+
+#endif
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 502e53f999cf..c52e2eb40a1e 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -652,20 +652,6 @@ static inline struct kvm_mmu_page *page_header(hpa_t shadow_page)
return (struct kvm_mmu_page *)page_private(page);
}
-static inline u16 kvm_read_fs(void)
-{
- u16 seg;
- asm("mov %%fs, %0" : "=g"(seg));
- return seg;
-}
-
-static inline u16 kvm_read_gs(void)
-{
- u16 seg;
- asm("mov %%gs, %0" : "=g"(seg));
- return seg;
-}
-
static inline u16 kvm_read_ldt(void)
{
u16 ldt;
@@ -673,16 +659,6 @@ static inline u16 kvm_read_ldt(void)
return ldt;
}
-static inline void kvm_load_fs(u16 sel)
-{
- asm("mov %0, %%fs" : : "rm"(sel));
-}
-
-static inline void kvm_load_gs(u16 sel)
-{
- asm("mov %0, %%gs" : : "rm"(sel));
-}
-
static inline void kvm_load_ldt(u16 sel)
{
asm("lldt %0" : : "rm"(sel));
diff --git a/arch/x86/include/asm/memblock.h b/arch/x86/include/asm/memblock.h
new file mode 100644
index 000000000000..19ae14ba6978
--- /dev/null
+++ b/arch/x86/include/asm/memblock.h
@@ -0,0 +1,23 @@
+#ifndef _X86_MEMBLOCK_H
+#define _X86_MEMBLOCK_H
+
+#define ARCH_DISCARD_MEMBLOCK
+
+u64 memblock_x86_find_in_range_size(u64 start, u64 *sizep, u64 align);
+void memblock_x86_to_bootmem(u64 start, u64 end);
+
+void memblock_x86_reserve_range(u64 start, u64 end, char *name);
+void memblock_x86_free_range(u64 start, u64 end);
+struct range;
+int __get_free_all_memory_range(struct range **range, int nodeid,
+ unsigned long start_pfn, unsigned long end_pfn);
+int get_free_all_memory_range(struct range **rangep, int nodeid);
+
+void memblock_x86_register_active_regions(int nid, unsigned long start_pfn,
+ unsigned long last_pfn);
+u64 memblock_x86_hole_size(u64 start, u64 end);
+u64 memblock_x86_find_in_range_node(int nid, u64 start, u64 end, u64 size, u64 align);
+u64 memblock_x86_free_memory_in_range(u64 addr, u64 limit);
+u64 memblock_x86_memory_in_range(u64 addr, u64 limit);
+
+#endif
diff --git a/arch/x86/include/asm/module.h b/arch/x86/include/asm/module.h
index 3e2ce58a31a3..67763c5d8b4e 100644
--- a/arch/x86/include/asm/module.h
+++ b/arch/x86/include/asm/module.h
@@ -60,12 +60,7 @@
#endif
#ifdef CONFIG_X86_32
-# ifdef CONFIG_4KSTACKS
-# define MODULE_STACKSIZE "4KSTACKS "
-# else
-# define MODULE_STACKSIZE ""
-# endif
-# define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY MODULE_STACKSIZE
+# define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY
#endif
#endif /* _ASM_X86_MODULE_H */
diff --git a/arch/x86/include/asm/mrst.h b/arch/x86/include/asm/mrst.h
index 16350740edf6..4a711a684b17 100644
--- a/arch/x86/include/asm/mrst.h
+++ b/arch/x86/include/asm/mrst.h
@@ -10,6 +10,9 @@
*/
#ifndef _ASM_X86_MRST_H
#define _ASM_X86_MRST_H
+
+#include <linux/sfi.h>
+
extern int pci_mrst_init(void);
int __init sfi_parse_mrtc(struct sfi_table_header *table);
@@ -26,7 +29,7 @@ enum mrst_cpu_type {
};
extern enum mrst_cpu_type __mrst_cpu_chip;
-static enum mrst_cpu_type mrst_identify_cpu(void)
+static inline enum mrst_cpu_type mrst_identify_cpu(void)
{
return __mrst_cpu_chip;
}
@@ -42,4 +45,9 @@ extern enum mrst_timer_options mrst_timer_options;
#define SFI_MTMR_MAX_NUM 8
#define SFI_MRTC_MAX 8
+extern struct console early_mrst_console;
+extern void mrst_early_console_init(void);
+
+extern struct console early_hsu_console;
+extern void hsu_early_console_init(void);
#endif /* _ASM_X86_MRST_H */
diff --git a/arch/x86/include/asm/mwait.h b/arch/x86/include/asm/mwait.h
new file mode 100644
index 000000000000..bcdff997668c
--- /dev/null
+++ b/arch/x86/include/asm/mwait.h
@@ -0,0 +1,15 @@
+#ifndef _ASM_X86_MWAIT_H
+#define _ASM_X86_MWAIT_H
+
+#define MWAIT_SUBSTATE_MASK 0xf
+#define MWAIT_CSTATE_MASK 0xf
+#define MWAIT_SUBSTATE_SIZE 4
+#define MWAIT_MAX_NUM_CSTATES 8
+
+#define CPUID_MWAIT_LEAF 5
+#define CPUID5_ECX_EXTENSIONS_SUPPORTED 0x1
+#define CPUID5_ECX_INTERRUPT_BREAK 0x2
+
+#define MWAIT_ECX_INTERRUPT_BREAK 0x1
+
+#endif /* _ASM_X86_MWAIT_H */
diff --git a/arch/x86/include/asm/olpc_ofw.h b/arch/x86/include/asm/olpc_ofw.h
index 08fde475cb3b..2a8478140bb3 100644
--- a/arch/x86/include/asm/olpc_ofw.h
+++ b/arch/x86/include/asm/olpc_ofw.h
@@ -21,10 +21,14 @@ extern void olpc_ofw_detect(void);
/* install OFW's pde permanently into the kernel's pgtable */
extern void setup_olpc_ofw_pgd(void);
+/* check if OFW was detected during boot */
+extern bool olpc_ofw_present(void);
+
#else /* !CONFIG_OLPC_OPENFIRMWARE */
static inline void olpc_ofw_detect(void) { }
static inline void setup_olpc_ofw_pgd(void) { }
+static inline bool olpc_ofw_present(void) { return false; }
#endif /* !CONFIG_OLPC_OPENFIRMWARE */
diff --git a/arch/x86/include/asm/page_32_types.h b/arch/x86/include/asm/page_32_types.h
index 6f1b7331313f..ade619ff9e2a 100644
--- a/arch/x86/include/asm/page_32_types.h
+++ b/arch/x86/include/asm/page_32_types.h
@@ -15,11 +15,7 @@
*/
#define __PAGE_OFFSET _AC(CONFIG_PAGE_OFFSET, UL)
-#ifdef CONFIG_4KSTACKS
-#define THREAD_ORDER 0
-#else
#define THREAD_ORDER 1
-#endif
#define THREAD_SIZE (PAGE_SIZE << THREAD_ORDER)
#define STACKFAULT_STACK 0
diff --git a/arch/x86/include/asm/page_types.h b/arch/x86/include/asm/page_types.h
index a667f24c7254..1df66211fd1b 100644
--- a/arch/x86/include/asm/page_types.h
+++ b/arch/x86/include/asm/page_types.h
@@ -8,7 +8,7 @@
#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE-1))
-#define __PHYSICAL_MASK ((phys_addr_t)(1ULL << __PHYSICAL_MASK_SHIFT) - 1)
+#define __PHYSICAL_MASK ((phys_addr_t)((1ULL << __PHYSICAL_MASK_SHIFT) - 1))
#define __VIRTUAL_MASK ((1UL << __VIRTUAL_MASK_SHIFT) - 1)
/* Cast PAGE_MASK to a signed type so that it is sign-extended if
diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h
index 5653f43d90e5..18e3b8a8709f 100644
--- a/arch/x86/include/asm/paravirt.h
+++ b/arch/x86/include/asm/paravirt.h
@@ -105,7 +105,7 @@ static inline void write_cr8(unsigned long x)
}
#endif
-static inline void raw_safe_halt(void)
+static inline void arch_safe_halt(void)
{
PVOP_VCALL0(pv_irq_ops.safe_halt);
}
@@ -416,11 +416,6 @@ static inline void paravirt_alloc_pmd(struct mm_struct *mm, unsigned long pfn)
PVOP_VCALL2(pv_mmu_ops.alloc_pmd, mm, pfn);
}
-static inline void paravirt_alloc_pmd_clone(unsigned long pfn, unsigned long clonepfn,
- unsigned long start, unsigned long count)
-{
- PVOP_VCALL4(pv_mmu_ops.alloc_pmd_clone, pfn, clonepfn, start, count);
-}
static inline void paravirt_release_pmd(unsigned long pfn)
{
PVOP_VCALL1(pv_mmu_ops.release_pmd, pfn);
@@ -829,32 +824,32 @@ static __always_inline void arch_spin_unlock(struct arch_spinlock *lock)
#define __PV_IS_CALLEE_SAVE(func) \
((struct paravirt_callee_save) { func })
-static inline unsigned long __raw_local_save_flags(void)
+static inline unsigned long arch_local_save_flags(void)
{
return PVOP_CALLEE0(unsigned long, pv_irq_ops.save_fl);
}
-static inline void raw_local_irq_restore(unsigned long f)
+static inline void arch_local_irq_restore(unsigned long f)
{
PVOP_VCALLEE1(pv_irq_ops.restore_fl, f);
}
-static inline void raw_local_irq_disable(void)
+static inline void arch_local_irq_disable(void)
{
PVOP_VCALLEE0(pv_irq_ops.irq_disable);
}
-static inline void raw_local_irq_enable(void)
+static inline void arch_local_irq_enable(void)
{
PVOP_VCALLEE0(pv_irq_ops.irq_enable);
}
-static inline unsigned long __raw_local_irq_save(void)
+static inline unsigned long arch_local_irq_save(void)
{
unsigned long f;
- f = __raw_local_save_flags();
- raw_local_irq_disable();
+ f = arch_local_save_flags();
+ arch_local_irq_disable();
return f;
}
diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h
index db9ef5532341..b82bac975250 100644
--- a/arch/x86/include/asm/paravirt_types.h
+++ b/arch/x86/include/asm/paravirt_types.h
@@ -255,7 +255,6 @@ struct pv_mmu_ops {
*/
void (*alloc_pte)(struct mm_struct *mm, unsigned long pfn);
void (*alloc_pmd)(struct mm_struct *mm, unsigned long pfn);
- void (*alloc_pmd_clone)(unsigned long pfn, unsigned long clonepfn, unsigned long start, unsigned long count);
void (*alloc_pud)(struct mm_struct *mm, unsigned long pfn);
void (*release_pte)(unsigned long pfn);
void (*release_pmd)(unsigned long pfn);
diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h
index cd28f9ad910d..f899e01a8ac9 100644
--- a/arch/x86/include/asm/percpu.h
+++ b/arch/x86/include/asm/percpu.h
@@ -47,6 +47,20 @@
#ifdef CONFIG_SMP
#define __percpu_arg(x) "%%"__stringify(__percpu_seg)":%P" #x
#define __my_cpu_offset percpu_read(this_cpu_off)
+
+/*
+ * Compared to the generic __my_cpu_offset version, the following
+ * saves one instruction and avoids clobbering a temp register.
+ */
+#define __this_cpu_ptr(ptr) \
+({ \
+ unsigned long tcp_ptr__; \
+ __verify_pcpu_ptr(ptr); \
+ asm volatile("add " __percpu_arg(1) ", %0" \
+ : "=r" (tcp_ptr__) \
+ : "m" (this_cpu_off), "0" (ptr)); \
+ (typeof(*(ptr)) __kernel __force *)tcp_ptr__; \
+})
#else
#define __percpu_arg(x) "%P" #x
#endif
diff --git a/arch/x86/include/asm/perf_event_p4.h b/arch/x86/include/asm/perf_event_p4.h
index def500776b16..a70cd216be5d 100644
--- a/arch/x86/include/asm/perf_event_p4.h
+++ b/arch/x86/include/asm/perf_event_p4.h
@@ -36,19 +36,6 @@
#define P4_ESCR_EMASK(v) ((v) << P4_ESCR_EVENTMASK_SHIFT)
#define P4_ESCR_TAG(v) ((v) << P4_ESCR_TAG_SHIFT)
-/* Non HT mask */
-#define P4_ESCR_MASK \
- (P4_ESCR_EVENT_MASK | \
- P4_ESCR_EVENTMASK_MASK | \
- P4_ESCR_TAG_MASK | \
- P4_ESCR_TAG_ENABLE | \
- P4_ESCR_T0_OS | \
- P4_ESCR_T0_USR)
-
-/* HT mask */
-#define P4_ESCR_MASK_HT \
- (P4_ESCR_MASK | P4_ESCR_T1_OS | P4_ESCR_T1_USR)
-
#define P4_CCCR_OVF 0x80000000U
#define P4_CCCR_CASCADE 0x40000000U
#define P4_CCCR_OVF_PMI_T0 0x04000000U
@@ -70,23 +57,6 @@
#define P4_CCCR_THRESHOLD(v) ((v) << P4_CCCR_THRESHOLD_SHIFT)
#define P4_CCCR_ESEL(v) ((v) << P4_CCCR_ESCR_SELECT_SHIFT)
-/* Non HT mask */
-#define P4_CCCR_MASK \
- (P4_CCCR_OVF | \
- P4_CCCR_CASCADE | \
- P4_CCCR_OVF_PMI_T0 | \
- P4_CCCR_FORCE_OVF | \
- P4_CCCR_EDGE | \
- P4_CCCR_THRESHOLD_MASK | \
- P4_CCCR_COMPLEMENT | \
- P4_CCCR_COMPARE | \
- P4_CCCR_ESCR_SELECT_MASK | \
- P4_CCCR_ENABLE)
-
-/* HT mask */
-#define P4_CCCR_MASK_HT \
- (P4_CCCR_MASK | P4_CCCR_OVF_PMI_T1 | P4_CCCR_THREAD_ANY)
-
#define P4_GEN_ESCR_EMASK(class, name, bit) \
class##__##name = ((1 << bit) << P4_ESCR_EVENTMASK_SHIFT)
#define P4_ESCR_EMASK_BIT(class, name) class##__##name
@@ -127,6 +97,28 @@
#define P4_CONFIG_HT_SHIFT 63
#define P4_CONFIG_HT (1ULL << P4_CONFIG_HT_SHIFT)
+/*
+ * The bits we allow to pass for RAW events
+ */
+#define P4_CONFIG_MASK_ESCR \
+ P4_ESCR_EVENT_MASK | \
+ P4_ESCR_EVENTMASK_MASK | \
+ P4_ESCR_TAG_MASK | \
+ P4_ESCR_TAG_ENABLE
+
+#define P4_CONFIG_MASK_CCCR \
+ P4_CCCR_EDGE | \
+ P4_CCCR_THRESHOLD_MASK | \
+ P4_CCCR_COMPLEMENT | \
+ P4_CCCR_COMPARE | \
+ P4_CCCR_THREAD_ANY | \
+ P4_CCCR_RESERVED
+
+/* some dangerous bits are reserved for kernel internals */
+#define P4_CONFIG_MASK \
+ (p4_config_pack_escr(P4_CONFIG_MASK_ESCR)) | \
+ (p4_config_pack_cccr(P4_CONFIG_MASK_CCCR))
+
static inline bool p4_is_event_cascaded(u64 config)
{
u32 cccr = p4_config_unpack_cccr(config);
diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h
index a34c785c5a63..ada823a13c7c 100644
--- a/arch/x86/include/asm/pgtable.h
+++ b/arch/x86/include/asm/pgtable.h
@@ -28,6 +28,8 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
extern spinlock_t pgd_lock;
extern struct list_head pgd_list;
+extern struct mm_struct *pgd_page_get_mm(struct page *page);
+
#ifdef CONFIG_PARAVIRT
#include <asm/paravirt.h>
#else /* !CONFIG_PARAVIRT */
@@ -603,6 +605,8 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm,
pte_update(mm, addr, ptep);
}
+#define flush_tlb_fix_spurious_fault(vma, address)
+
/*
* clone_pgd_range(pgd_t *dst, pgd_t *src, int count);
*
diff --git a/arch/x86/include/asm/pgtable_32.h b/arch/x86/include/asm/pgtable_32.h
index f686f49e8b7b..8abde9ec90bf 100644
--- a/arch/x86/include/asm/pgtable_32.h
+++ b/arch/x86/include/asm/pgtable_32.h
@@ -26,7 +26,7 @@ struct mm_struct;
struct vm_area_struct;
extern pgd_t swapper_pg_dir[1024];
-extern pgd_t trampoline_pg_dir[1024];
+extern pgd_t initial_page_table[1024];
static inline void pgtable_cache_init(void) { }
static inline void check_pgt_cache(void) { }
diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h
index 076052cd62be..f96ac9bedf75 100644
--- a/arch/x86/include/asm/pgtable_64.h
+++ b/arch/x86/include/asm/pgtable_64.h
@@ -102,6 +102,8 @@ static inline void native_pgd_clear(pgd_t *pgd)
native_set_pgd(pgd, native_make_pgd(0));
}
+extern void sync_global_pgds(unsigned long start, unsigned long end);
+
/*
* Conversion functions: convert a page and protection to a page entry,
* and a page entry and page directory to the page they refer to.
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 325b7bdbebaa..cae9c3cb95cf 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -110,6 +110,8 @@ struct cpuinfo_x86 {
u16 phys_proc_id;
/* Core id: */
u16 cpu_core_id;
+ /* Compute unit id */
+ u8 compute_unit_id;
/* Index into per_cpu list: */
u16 cpu_index;
#endif
@@ -602,7 +604,7 @@ extern unsigned long mmu_cr4_features;
static inline void set_in_cr4(unsigned long mask)
{
- unsigned cr4;
+ unsigned long cr4;
mmu_cr4_features |= mask;
cr4 = read_cr4();
@@ -612,7 +614,7 @@ static inline void set_in_cr4(unsigned long mask)
static inline void clear_in_cr4(unsigned long mask)
{
- unsigned cr4;
+ unsigned long cr4;
mmu_cr4_features &= ~mask;
cr4 = read_cr4();
@@ -764,29 +766,6 @@ extern unsigned long idle_halt;
extern unsigned long idle_nomwait;
extern bool c1e_detected;
-/*
- * on systems with caches, caches must be flashed as the absolute
- * last instruction before going into a suspended halt. Otherwise,
- * dirty data can linger in the cache and become stale on resume,
- * leading to strange errors.
- *
- * perform a variety of operations to guarantee that the compiler
- * will not reorder instructions. wbinvd itself is serializing
- * so the processor will not reorder.
- *
- * Systems without cache can just go into halt.
- */
-static inline void wbinvd_halt(void)
-{
- mb();
- /* check for clflush to determine if wbinvd is legal */
- if (cpu_has_clflush)
- asm volatile("cli; wbinvd; 1: hlt; jmp 1b" : : : "memory");
- else
- while (1)
- halt();
-}
-
extern void enable_sep_cpu(void);
extern int sysenter_setup(void);
diff --git a/arch/x86/include/asm/segment.h b/arch/x86/include/asm/segment.h
index 14e0ed86a6f9..231f1c1d6607 100644
--- a/arch/x86/include/asm/segment.h
+++ b/arch/x86/include/asm/segment.h
@@ -73,31 +73,31 @@
#define GDT_ENTRY_DEFAULT_USER_DS 15
-#define GDT_ENTRY_KERNEL_BASE 12
+#define GDT_ENTRY_KERNEL_BASE (12)
-#define GDT_ENTRY_KERNEL_CS (GDT_ENTRY_KERNEL_BASE + 0)
+#define GDT_ENTRY_KERNEL_CS (GDT_ENTRY_KERNEL_BASE+0)
-#define GDT_ENTRY_KERNEL_DS (GDT_ENTRY_KERNEL_BASE + 1)
+#define GDT_ENTRY_KERNEL_DS (GDT_ENTRY_KERNEL_BASE+1)
-#define GDT_ENTRY_TSS (GDT_ENTRY_KERNEL_BASE + 4)
-#define GDT_ENTRY_LDT (GDT_ENTRY_KERNEL_BASE + 5)
+#define GDT_ENTRY_TSS (GDT_ENTRY_KERNEL_BASE+4)
+#define GDT_ENTRY_LDT (GDT_ENTRY_KERNEL_BASE+5)
-#define GDT_ENTRY_PNPBIOS_BASE (GDT_ENTRY_KERNEL_BASE + 6)
-#define GDT_ENTRY_APMBIOS_BASE (GDT_ENTRY_KERNEL_BASE + 11)
+#define GDT_ENTRY_PNPBIOS_BASE (GDT_ENTRY_KERNEL_BASE+6)
+#define GDT_ENTRY_APMBIOS_BASE (GDT_ENTRY_KERNEL_BASE+11)
-#define GDT_ENTRY_ESPFIX_SS (GDT_ENTRY_KERNEL_BASE + 14)
-#define __ESPFIX_SS (GDT_ENTRY_ESPFIX_SS * 8)
+#define GDT_ENTRY_ESPFIX_SS (GDT_ENTRY_KERNEL_BASE+14)
+#define __ESPFIX_SS (GDT_ENTRY_ESPFIX_SS*8)
-#define GDT_ENTRY_PERCPU (GDT_ENTRY_KERNEL_BASE + 15)
+#define GDT_ENTRY_PERCPU (GDT_ENTRY_KERNEL_BASE+15)
#ifdef CONFIG_SMP
#define __KERNEL_PERCPU (GDT_ENTRY_PERCPU * 8)
#else
#define __KERNEL_PERCPU 0
#endif
-#define GDT_ENTRY_STACK_CANARY (GDT_ENTRY_KERNEL_BASE + 16)
+#define GDT_ENTRY_STACK_CANARY (GDT_ENTRY_KERNEL_BASE+16)
#ifdef CONFIG_CC_STACKPROTECTOR
-#define __KERNEL_STACK_CANARY (GDT_ENTRY_STACK_CANARY * 8)
+#define __KERNEL_STACK_CANARY (GDT_ENTRY_STACK_CANARY*8)
#else
#define __KERNEL_STACK_CANARY 0
#endif
@@ -182,10 +182,10 @@
#endif
-#define __KERNEL_CS (GDT_ENTRY_KERNEL_CS * 8)
-#define __KERNEL_DS (GDT_ENTRY_KERNEL_DS * 8)
-#define __USER_DS (GDT_ENTRY_DEFAULT_USER_DS* 8 + 3)
-#define __USER_CS (GDT_ENTRY_DEFAULT_USER_CS* 8 + 3)
+#define __KERNEL_CS (GDT_ENTRY_KERNEL_CS*8)
+#define __KERNEL_DS (GDT_ENTRY_KERNEL_DS*8)
+#define __USER_DS (GDT_ENTRY_DEFAULT_USER_DS*8+3)
+#define __USER_CS (GDT_ENTRY_DEFAULT_USER_CS*8+3)
#ifndef CONFIG_PARAVIRT
#define get_kernel_rpl() 0
#endif
diff --git a/arch/x86/include/asm/setup.h b/arch/x86/include/asm/setup.h
index ef292c792d74..d6763b139a84 100644
--- a/arch/x86/include/asm/setup.h
+++ b/arch/x86/include/asm/setup.h
@@ -93,6 +93,11 @@ void *extend_brk(size_t size, size_t align);
: : "i" (sz)); \
}
+/* Helper for reserving space for arrays of things */
+#define RESERVE_BRK_ARRAY(type, name, entries) \
+ type *name; \
+ RESERVE_BRK(name, sizeof(type) * entries)
+
#ifdef __i386__
void __init i386_start_kernel(void);
diff --git a/arch/x86/include/asm/swiotlb.h b/arch/x86/include/asm/swiotlb.h
index 8085277e1b8b..977f1761a25d 100644
--- a/arch/x86/include/asm/swiotlb.h
+++ b/arch/x86/include/asm/swiotlb.h
@@ -5,17 +5,26 @@
#ifdef CONFIG_SWIOTLB
extern int swiotlb;
-extern int __init pci_swiotlb_detect(void);
+extern int __init pci_swiotlb_detect_override(void);
+extern int __init pci_swiotlb_detect_4gb(void);
extern void __init pci_swiotlb_init(void);
+extern void __init pci_swiotlb_late_init(void);
#else
#define swiotlb 0
-static inline int pci_swiotlb_detect(void)
+static inline int pci_swiotlb_detect_override(void)
+{
+ return 0;
+}
+static inline int pci_swiotlb_detect_4gb(void)
{
return 0;
}
static inline void pci_swiotlb_init(void)
{
}
+static inline void pci_swiotlb_late_init(void)
+{
+}
#endif
static inline void dma_mark_clean(void *addr, size_t size) {}
diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h
index 7f3eba08e7de..169be8938b96 100644
--- a/arch/x86/include/asm/tlbflush.h
+++ b/arch/x86/include/asm/tlbflush.h
@@ -172,6 +172,4 @@ static inline void flush_tlb_kernel_range(unsigned long start,
flush_tlb_all();
}
-extern void zap_low_mappings(bool early);
-
#endif /* _ASM_X86_TLBFLUSH_H */
diff --git a/arch/x86/include/asm/trampoline.h b/arch/x86/include/asm/trampoline.h
index 4dde797c0578..f4500fb3b485 100644
--- a/arch/x86/include/asm/trampoline.h
+++ b/arch/x86/include/asm/trampoline.h
@@ -13,16 +13,13 @@ extern unsigned char *trampoline_base;
extern unsigned long init_rsp;
extern unsigned long initial_code;
-extern unsigned long initial_page_table;
extern unsigned long initial_gs;
#define TRAMPOLINE_SIZE roundup(trampoline_end - trampoline_data, PAGE_SIZE)
extern unsigned long setup_trampoline(void);
-extern void __init setup_trampoline_page_table(void);
extern void __init reserve_trampoline_memory(void);
#else
-static inline void setup_trampoline_page_table(void) {}
static inline void reserve_trampoline_memory(void) {}
#endif /* CONFIG_X86_TRAMPOLINE */
diff --git a/arch/x86/include/asm/vmi.h b/arch/x86/include/asm/vmi.h
deleted file mode 100644
index 61e08c0a2907..000000000000
--- a/arch/x86/include/asm/vmi.h
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
- * VMI interface definition
- *
- * Copyright (C) 2005, VMware, 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.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Maintained by: Zachary Amsden zach@vmware.com
- *
- */
-#include <linux/types.h>
-
-/*
- *---------------------------------------------------------------------
- *
- * VMI Option ROM API
- *
- *---------------------------------------------------------------------
- */
-#define VMI_SIGNATURE 0x696d5663 /* "cVmi" */
-
-#define PCI_VENDOR_ID_VMWARE 0x15AD
-#define PCI_DEVICE_ID_VMWARE_VMI 0x0801
-
-/*
- * We use two version numbers for compatibility, with the major
- * number signifying interface breakages, and the minor number
- * interface extensions.
- */
-#define VMI_API_REV_MAJOR 3
-#define VMI_API_REV_MINOR 0
-
-#define VMI_CALL_CPUID 0
-#define VMI_CALL_WRMSR 1
-#define VMI_CALL_RDMSR 2
-#define VMI_CALL_SetGDT 3
-#define VMI_CALL_SetLDT 4
-#define VMI_CALL_SetIDT 5
-#define VMI_CALL_SetTR 6
-#define VMI_CALL_GetGDT 7
-#define VMI_CALL_GetLDT 8
-#define VMI_CALL_GetIDT 9
-#define VMI_CALL_GetTR 10
-#define VMI_CALL_WriteGDTEntry 11
-#define VMI_CALL_WriteLDTEntry 12
-#define VMI_CALL_WriteIDTEntry 13
-#define VMI_CALL_UpdateKernelStack 14
-#define VMI_CALL_SetCR0 15
-#define VMI_CALL_SetCR2 16
-#define VMI_CALL_SetCR3 17
-#define VMI_CALL_SetCR4 18
-#define VMI_CALL_GetCR0 19
-#define VMI_CALL_GetCR2 20
-#define VMI_CALL_GetCR3 21
-#define VMI_CALL_GetCR4 22
-#define VMI_CALL_WBINVD 23
-#define VMI_CALL_SetDR 24
-#define VMI_CALL_GetDR 25
-#define VMI_CALL_RDPMC 26
-#define VMI_CALL_RDTSC 27
-#define VMI_CALL_CLTS 28
-#define VMI_CALL_EnableInterrupts 29
-#define VMI_CALL_DisableInterrupts 30
-#define VMI_CALL_GetInterruptMask 31
-#define VMI_CALL_SetInterruptMask 32
-#define VMI_CALL_IRET 33
-#define VMI_CALL_SYSEXIT 34
-#define VMI_CALL_Halt 35
-#define VMI_CALL_Reboot 36
-#define VMI_CALL_Shutdown 37
-#define VMI_CALL_SetPxE 38
-#define VMI_CALL_SetPxELong 39
-#define VMI_CALL_UpdatePxE 40
-#define VMI_CALL_UpdatePxELong 41
-#define VMI_CALL_MachineToPhysical 42
-#define VMI_CALL_PhysicalToMachine 43
-#define VMI_CALL_AllocatePage 44
-#define VMI_CALL_ReleasePage 45
-#define VMI_CALL_InvalPage 46
-#define VMI_CALL_FlushTLB 47
-#define VMI_CALL_SetLinearMapping 48
-
-#define VMI_CALL_SetIOPLMask 61
-#define VMI_CALL_SetInitialAPState 62
-#define VMI_CALL_APICWrite 63
-#define VMI_CALL_APICRead 64
-#define VMI_CALL_IODelay 65
-#define VMI_CALL_SetLazyMode 73
-
-/*
- *---------------------------------------------------------------------
- *
- * MMU operation flags
- *
- *---------------------------------------------------------------------
- */
-
-/* Flags used by VMI_{Allocate|Release}Page call */
-#define VMI_PAGE_PAE 0x10 /* Allocate PAE shadow */
-#define VMI_PAGE_CLONE 0x20 /* Clone from another shadow */
-#define VMI_PAGE_ZEROED 0x40 /* Page is pre-zeroed */
-
-
-/* Flags shared by Allocate|Release Page and PTE updates */
-#define VMI_PAGE_PT 0x01
-#define VMI_PAGE_PD 0x02
-#define VMI_PAGE_PDP 0x04
-#define VMI_PAGE_PML4 0x08
-
-#define VMI_PAGE_NORMAL 0x00 /* for debugging */
-
-/* Flags used by PTE updates */
-#define VMI_PAGE_CURRENT_AS 0x10 /* implies VMI_PAGE_VA_MASK is valid */
-#define VMI_PAGE_DEFER 0x20 /* may queue update until TLB inval */
-#define VMI_PAGE_VA_MASK 0xfffff000
-
-#ifdef CONFIG_X86_PAE
-#define VMI_PAGE_L1 (VMI_PAGE_PT | VMI_PAGE_PAE | VMI_PAGE_ZEROED)
-#define VMI_PAGE_L2 (VMI_PAGE_PD | VMI_PAGE_PAE | VMI_PAGE_ZEROED)
-#else
-#define VMI_PAGE_L1 (VMI_PAGE_PT | VMI_PAGE_ZEROED)
-#define VMI_PAGE_L2 (VMI_PAGE_PD | VMI_PAGE_ZEROED)
-#endif
-
-/* Flags used by VMI_FlushTLB call */
-#define VMI_FLUSH_TLB 0x01
-#define VMI_FLUSH_GLOBAL 0x02
-
-/*
- *---------------------------------------------------------------------
- *
- * VMI relocation definitions for ROM call get_reloc
- *
- *---------------------------------------------------------------------
- */
-
-/* VMI Relocation types */
-#define VMI_RELOCATION_NONE 0
-#define VMI_RELOCATION_CALL_REL 1
-#define VMI_RELOCATION_JUMP_REL 2
-#define VMI_RELOCATION_NOP 3
-
-#ifndef __ASSEMBLY__
-struct vmi_relocation_info {
- unsigned char *eip;
- unsigned char type;
- unsigned char reserved[3];
-};
-#endif
-
-
-/*
- *---------------------------------------------------------------------
- *
- * Generic ROM structures and definitions
- *
- *---------------------------------------------------------------------
- */
-
-#ifndef __ASSEMBLY__
-
-struct vrom_header {
- u16 rom_signature; /* option ROM signature */
- u8 rom_length; /* ROM length in 512 byte chunks */
- u8 rom_entry[4]; /* 16-bit code entry point */
- u8 rom_pad0; /* 4-byte align pad */
- u32 vrom_signature; /* VROM identification signature */
- u8 api_version_min;/* Minor version of API */
- u8 api_version_maj;/* Major version of API */
- u8 jump_slots; /* Number of jump slots */
- u8 reserved1; /* Reserved for expansion */
- u32 virtual_top; /* Hypervisor virtual address start */
- u16 reserved2; /* Reserved for expansion */
- u16 license_offs; /* Offset to License string */
- u16 pci_header_offs;/* Offset to PCI OPROM header */
- u16 pnp_header_offs;/* Offset to PnP OPROM header */
- u32 rom_pad3; /* PnP reserverd / VMI reserved */
- u8 reserved[96]; /* Reserved for headers */
- char vmi_init[8]; /* VMI_Init jump point */
- char get_reloc[8]; /* VMI_GetRelocationInfo jump point */
-} __attribute__((packed));
-
-struct pnp_header {
- char sig[4];
- char rev;
- char size;
- short next;
- short res;
- long devID;
- unsigned short manufacturer_offset;
- unsigned short product_offset;
-} __attribute__((packed));
-
-struct pci_header {
- char sig[4];
- short vendorID;
- short deviceID;
- short vpdData;
- short size;
- char rev;
- char class;
- char subclass;
- char interface;
- short chunks;
- char rom_version_min;
- char rom_version_maj;
- char codetype;
- char lastRom;
- short reserved;
-} __attribute__((packed));
-
-/* Function prototypes for bootstrapping */
-#ifdef CONFIG_VMI
-extern void vmi_init(void);
-extern void vmi_activate(void);
-extern void vmi_bringup(void);
-#else
-static inline void vmi_init(void) {}
-static inline void vmi_activate(void) {}
-static inline void vmi_bringup(void) {}
-#endif
-
-/* State needed to start an application processor in an SMP system. */
-struct vmi_ap_state {
- u32 cr0;
- u32 cr2;
- u32 cr3;
- u32 cr4;
-
- u64 efer;
-
- u32 eip;
- u32 eflags;
- u32 eax;
- u32 ebx;
- u32 ecx;
- u32 edx;
- u32 esp;
- u32 ebp;
- u32 esi;
- u32 edi;
- u16 cs;
- u16 ss;
- u16 ds;
- u16 es;
- u16 fs;
- u16 gs;
- u16 ldtr;
-
- u16 gdtr_limit;
- u32 gdtr_base;
- u32 idtr_base;
- u16 idtr_limit;
-};
-
-#endif
diff --git a/arch/x86/include/asm/vmi_time.h b/arch/x86/include/asm/vmi_time.h
deleted file mode 100644
index c6e0bee93e3c..000000000000
--- a/arch/x86/include/asm/vmi_time.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * VMI Time wrappers
- *
- * Copyright (C) 2006, VMware, 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.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to dhecht@vmware.com
- *
- */
-
-#ifndef _ASM_X86_VMI_TIME_H
-#define _ASM_X86_VMI_TIME_H
-
-/*
- * Raw VMI call indices for timer functions
- */
-#define VMI_CALL_GetCycleFrequency 66
-#define VMI_CALL_GetCycleCounter 67
-#define VMI_CALL_SetAlarm 68
-#define VMI_CALL_CancelAlarm 69
-#define VMI_CALL_GetWallclockTime 70
-#define VMI_CALL_WallclockUpdated 71
-
-/* Cached VMI timer operations */
-extern struct vmi_timer_ops {
- u64 (*get_cycle_frequency)(void);
- u64 (*get_cycle_counter)(int);
- u64 (*get_wallclock)(void);
- int (*wallclock_updated)(void);
- void (*set_alarm)(u32 flags, u64 expiry, u64 period);
- void (*cancel_alarm)(u32 flags);
-} vmi_timer_ops;
-
-/* Prototypes */
-extern void __init vmi_time_init(void);
-extern unsigned long vmi_get_wallclock(void);
-extern int vmi_set_wallclock(unsigned long now);
-extern unsigned long long vmi_sched_clock(void);
-extern unsigned long vmi_tsc_khz(void);
-
-#ifdef CONFIG_X86_LOCAL_APIC
-extern void __devinit vmi_time_bsp_init(void);
-extern void __devinit vmi_time_ap_init(void);
-#endif
-
-/*
- * When run under a hypervisor, a vcpu is always in one of three states:
- * running, halted, or ready. The vcpu is in the 'running' state if it
- * is executing. When the vcpu executes the halt interface, the vcpu
- * enters the 'halted' state and remains halted until there is some work
- * pending for the vcpu (e.g. an alarm expires, host I/O completes on
- * behalf of virtual I/O). At this point, the vcpu enters the 'ready'
- * state (waiting for the hypervisor to reschedule it). Finally, at any
- * time when the vcpu is not in the 'running' state nor the 'halted'
- * state, it is in the 'ready' state.
- *
- * Real time is advances while the vcpu is 'running', 'ready', or
- * 'halted'. Stolen time is the time in which the vcpu is in the
- * 'ready' state. Available time is the remaining time -- the vcpu is
- * either 'running' or 'halted'.
- *
- * All three views of time are accessible through the VMI cycle
- * counters.
- */
-
-/* The cycle counters. */
-#define VMI_CYCLES_REAL 0
-#define VMI_CYCLES_AVAILABLE 1
-#define VMI_CYCLES_STOLEN 2
-
-/* The alarm interface 'flags' bits */
-#define VMI_ALARM_COUNTERS 2
-
-#define VMI_ALARM_COUNTER_MASK 0x000000ff
-
-#define VMI_ALARM_WIRED_IRQ0 0x00000000
-#define VMI_ALARM_WIRED_LVTT 0x00010000
-
-#define VMI_ALARM_IS_ONESHOT 0x00000000
-#define VMI_ALARM_IS_PERIODIC 0x00000100
-
-#define CONFIG_VMI_ALARM_HZ 100
-
-#endif /* _ASM_X86_VMI_TIME_H */
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index fedf32a8c3ec..2c833d8c4141 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -34,7 +34,8 @@ GCOV_PROFILE_paravirt.o := n
obj-y := process_$(BITS).o signal.o entry_$(BITS).o
obj-y += traps.o irq.o irq_$(BITS).o dumpstack_$(BITS).o
obj-y += time.o ioport.o ldt.o dumpstack.o
-obj-y += setup.o x86_init.o i8259.o irqinit.o
+obj-y += setup.o x86_init.o i8259.o irqinit.o jump_label.o
+obj-$(CONFIG_IRQ_WORK) += irq_work.o
obj-$(CONFIG_X86_VISWS) += visws_quirks.o
obj-$(CONFIG_X86_32) += probe_roms_32.o
obj-$(CONFIG_X86_32) += sys_i386_32.o i386_ksyms_32.o
@@ -44,6 +45,7 @@ obj-y += bootflag.o e820.o
obj-y += pci-dma.o quirks.o i8237.o topology.o kdebugfs.o
obj-y += alternative.o i8253.o pci-nommu.o hw_breakpoint.o
obj-y += tsc.o io_delay.o rtc.o
+obj-y += pci-iommu_table.o
obj-$(CONFIG_X86_TRAMPOLINE) += trampoline.o
obj-y += process.o
@@ -85,15 +87,15 @@ obj-$(CONFIG_DOUBLEFAULT) += doublefault_32.o
obj-$(CONFIG_KGDB) += kgdb.o
obj-$(CONFIG_VM86) += vm86_32.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
+obj-$(CONFIG_EARLY_PRINTK_MRST) += early_printk_mrst.o
obj-$(CONFIG_HPET_TIMER) += hpet.o
obj-$(CONFIG_APB_TIMER) += apb_timer.o
-obj-$(CONFIG_K8_NB) += k8.o
+obj-$(CONFIG_AMD_NB) += amd_nb.o
obj-$(CONFIG_DEBUG_RODATA_TEST) += test_rodata.o
obj-$(CONFIG_DEBUG_NX_TEST) += test_nx.o
-obj-$(CONFIG_VMI) += vmi_32.o vmiclock_32.o
obj-$(CONFIG_KVM_GUEST) += kvm.o
obj-$(CONFIG_KVM_CLOCK) += kvmclock.o
obj-$(CONFIG_PARAVIRT) += paravirt.o paravirt_patch_$(BITS).o
@@ -106,6 +108,7 @@ obj-$(CONFIG_SCx200) += scx200.o
scx200-y += scx200_32.o
obj-$(CONFIG_OLPC) += olpc.o
+obj-$(CONFIG_OLPC_XO1) += olpc-xo1.o
obj-$(CONFIG_OLPC_OPENFIRMWARE) += olpc_ofw.o
obj-$(CONFIG_X86_MRST) += mrst.o
@@ -122,7 +125,6 @@ obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o
# 64 bit specific files
ifeq ($(CONFIG_X86_64),y)
obj-$(CONFIG_X86_UV) += tlb_uv.o bios_uv.o uv_irq.o uv_sysfs.o uv_time.o
- obj-$(CONFIG_X86_PM_TIMER) += pmtimer_64.o
obj-$(CONFIG_AUDIT) += audit_64.o
obj-$(CONFIG_GART_IOMMU) += pci-gart_64.o aperture_64.o
diff --git a/arch/x86/kernel/acpi/cstate.c b/arch/x86/kernel/acpi/cstate.c
index fb7a5f052e2b..5812404a0d4c 100644
--- a/arch/x86/kernel/acpi/cstate.c
+++ b/arch/x86/kernel/acpi/cstate.c
@@ -13,6 +13,7 @@
#include <acpi/processor.h>
#include <asm/acpi.h>
+#include <asm/mwait.h>
/*
* Initialize bm_flags based on the CPU cache properties
@@ -61,20 +62,10 @@ struct cstate_entry {
unsigned int ecx;
} states[ACPI_PROCESSOR_MAX_POWER];
};
-static struct cstate_entry *cpu_cstate_entry; /* per CPU ptr */
+static struct cstate_entry __percpu *cpu_cstate_entry; /* per CPU ptr */
static short mwait_supported[ACPI_PROCESSOR_MAX_POWER];
-#define MWAIT_SUBSTATE_MASK (0xf)
-#define MWAIT_CSTATE_MASK (0xf)
-#define MWAIT_SUBSTATE_SIZE (4)
-
-#define CPUID_MWAIT_LEAF (5)
-#define CPUID5_ECX_EXTENSIONS_SUPPORTED (0x1)
-#define CPUID5_ECX_INTERRUPT_BREAK (0x2)
-
-#define MWAIT_ECX_INTERRUPT_BREAK (0x1)
-
#define NATIVE_CSTATE_BEYOND_HALT (2)
static long acpi_processor_ffh_cstate_probe_cpu(void *_cx)
diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c
index 33cec152070d..74a847835bab 100644
--- a/arch/x86/kernel/acpi/sleep.c
+++ b/arch/x86/kernel/acpi/sleep.c
@@ -7,11 +7,17 @@
#include <linux/acpi.h>
#include <linux/bootmem.h>
+#include <linux/memblock.h>
#include <linux/dmi.h>
#include <linux/cpumask.h>
#include <asm/segment.h>
#include <asm/desc.h>
+#ifdef CONFIG_X86_32
+#include <asm/pgtable.h>
+#include <asm/pgtable_32.h>
+#endif
+
#include "realmode/wakeup.h"
#include "sleep.h"
@@ -90,7 +96,7 @@ int acpi_save_state_mem(void)
#ifndef CONFIG_64BIT
header->pmode_entry = (u32)&wakeup_pmode_return;
- header->pmode_cr3 = (u32)(swsusp_pg_dir - __PAGE_OFFSET);
+ header->pmode_cr3 = (u32)__pa(&initial_page_table);
saved_magic = 0x12345678;
#else /* CONFIG_64BIT */
header->trampoline_segment = setup_trampoline() >> 4;
@@ -125,7 +131,7 @@ void acpi_restore_state_mem(void)
*/
void __init acpi_reserve_wakeup_memory(void)
{
- unsigned long mem;
+ phys_addr_t mem;
if ((&wakeup_code_end - &wakeup_code_start) > WAKEUP_SIZE) {
printk(KERN_ERR
@@ -133,15 +139,15 @@ void __init acpi_reserve_wakeup_memory(void)
return;
}
- mem = find_e820_area(0, 1<<20, WAKEUP_SIZE, PAGE_SIZE);
+ mem = memblock_find_in_range(0, 1<<20, WAKEUP_SIZE, PAGE_SIZE);
- if (mem == -1L) {
+ if (mem == MEMBLOCK_ERROR) {
printk(KERN_ERR "ACPI: Cannot allocate lowmem, S3 disabled.\n");
return;
}
acpi_realmode = (unsigned long) phys_to_virt(mem);
acpi_wakeup_address = mem;
- reserve_early(mem, mem + WAKEUP_SIZE, "ACPI WAKEUP");
+ memblock_x86_reserve_range(mem, mem + WAKEUP_SIZE, "ACPI WAKEUP");
}
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index f65ab8b014c4..a36bb90aef53 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -195,7 +195,7 @@ static void __init_or_module add_nops(void *insns, unsigned int len)
extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
extern s32 __smp_locks[], __smp_locks_end[];
-static void *text_poke_early(void *addr, const void *opcode, size_t len);
+void *text_poke_early(void *addr, const void *opcode, size_t len);
/* Replace instructions with better alternatives for this CPU type.
This runs before SMP is initialized to avoid SMP problems with
@@ -522,7 +522,7 @@ void __init alternative_instructions(void)
* instructions. And on the local CPU you need to be protected again NMI or MCE
* handlers seeing an inconsistent instruction while you patch.
*/
-static void *__init_or_module text_poke_early(void *addr, const void *opcode,
+void *__init_or_module text_poke_early(void *addr, const void *opcode,
size_t len)
{
unsigned long flags;
@@ -637,7 +637,72 @@ void *__kprobes text_poke_smp(void *addr, const void *opcode, size_t len)
tpp.len = len;
atomic_set(&stop_machine_first, 1);
wrote_text = 0;
- stop_machine(stop_machine_text_poke, (void *)&tpp, NULL);
+ /* Use __stop_machine() because the caller already got online_cpus. */
+ __stop_machine(stop_machine_text_poke, (void *)&tpp, NULL);
return addr;
}
+#if defined(CONFIG_DYNAMIC_FTRACE) || defined(HAVE_JUMP_LABEL)
+
+unsigned char ideal_nop5[IDEAL_NOP_SIZE_5];
+
+void __init arch_init_ideal_nop5(void)
+{
+ extern const unsigned char ftrace_test_p6nop[];
+ extern const unsigned char ftrace_test_nop5[];
+ extern const unsigned char ftrace_test_jmp[];
+ int faulted = 0;
+
+ /*
+ * There is no good nop for all x86 archs.
+ * We will default to using the P6_NOP5, but first we
+ * will test to make sure that the nop will actually
+ * work on this CPU. If it faults, we will then
+ * go to a lesser efficient 5 byte nop. If that fails
+ * we then just use a jmp as our nop. This isn't the most
+ * efficient nop, but we can not use a multi part nop
+ * since we would then risk being preempted in the middle
+ * of that nop, and if we enabled tracing then, it might
+ * cause a system crash.
+ *
+ * TODO: check the cpuid to determine the best nop.
+ */
+ asm volatile (
+ "ftrace_test_jmp:"
+ "jmp ftrace_test_p6nop\n"
+ "nop\n"
+ "nop\n"
+ "nop\n" /* 2 byte jmp + 3 bytes */
+ "ftrace_test_p6nop:"
+ P6_NOP5
+ "jmp 1f\n"
+ "ftrace_test_nop5:"
+ ".byte 0x66,0x66,0x66,0x66,0x90\n"
+ "1:"
+ ".section .fixup, \"ax\"\n"
+ "2: movl $1, %0\n"
+ " jmp ftrace_test_nop5\n"
+ "3: movl $2, %0\n"
+ " jmp 1b\n"
+ ".previous\n"
+ _ASM_EXTABLE(ftrace_test_p6nop, 2b)
+ _ASM_EXTABLE(ftrace_test_nop5, 3b)
+ : "=r"(faulted) : "0" (faulted));
+
+ switch (faulted) {
+ case 0:
+ pr_info("converting mcount calls to 0f 1f 44 00 00\n");
+ memcpy(ideal_nop5, ftrace_test_p6nop, IDEAL_NOP_SIZE_5);
+ break;
+ case 1:
+ pr_info("converting mcount calls to 66 66 66 66 90\n");
+ memcpy(ideal_nop5, ftrace_test_nop5, IDEAL_NOP_SIZE_5);
+ break;
+ case 2:
+ pr_info("converting mcount calls to jmp . + 5\n");
+ memcpy(ideal_nop5, ftrace_test_jmp, IDEAL_NOP_SIZE_5);
+ break;
+ }
+
+}
+#endif
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 679b6450382b..d2fdb0826df2 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007-2009 Advanced Micro Devices, Inc.
+ * Copyright (C) 2007-2010 Advanced Micro Devices, Inc.
* Author: Joerg Roedel <joerg.roedel@amd.com>
* Leo Duran <leo.duran@amd.com>
*
diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c
index 5a170cbbbed8..6e11c8134158 100644
--- a/arch/x86/kernel/amd_iommu_init.c
+++ b/arch/x86/kernel/amd_iommu_init.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007-2009 Advanced Micro Devices, Inc.
+ * Copyright (C) 2007-2010 Advanced Micro Devices, Inc.
* Author: Joerg Roedel <joerg.roedel@amd.com>
* Leo Duran <leo.duran@amd.com>
*
@@ -31,7 +31,7 @@
#include <asm/iommu.h>
#include <asm/gart.h>
#include <asm/x86_init.h>
-
+#include <asm/iommu_table.h>
/*
* definitions for the ACPI scanning code
*/
@@ -194,6 +194,39 @@ static inline unsigned long tbl_size(int entry_size)
return 1UL << shift;
}
+/* Access to l1 and l2 indexed register spaces */
+
+static u32 iommu_read_l1(struct amd_iommu *iommu, u16 l1, u8 address)
+{
+ u32 val;
+
+ pci_write_config_dword(iommu->dev, 0xf8, (address | l1 << 16));
+ pci_read_config_dword(iommu->dev, 0xfc, &val);
+ return val;
+}
+
+static void iommu_write_l1(struct amd_iommu *iommu, u16 l1, u8 address, u32 val)
+{
+ pci_write_config_dword(iommu->dev, 0xf8, (address | l1 << 16 | 1 << 31));
+ pci_write_config_dword(iommu->dev, 0xfc, val);
+ pci_write_config_dword(iommu->dev, 0xf8, (address | l1 << 16));
+}
+
+static u32 iommu_read_l2(struct amd_iommu *iommu, u8 address)
+{
+ u32 val;
+
+ pci_write_config_dword(iommu->dev, 0xf0, address);
+ pci_read_config_dword(iommu->dev, 0xf4, &val);
+ return val;
+}
+
+static void iommu_write_l2(struct amd_iommu *iommu, u8 address, u32 val)
+{
+ pci_write_config_dword(iommu->dev, 0xf0, (address | 1 << 8));
+ pci_write_config_dword(iommu->dev, 0xf4, val);
+}
+
/****************************************************************************
*
* AMD IOMMU MMIO register space handling functions
@@ -619,6 +652,7 @@ static void __init init_iommu_from_pci(struct amd_iommu *iommu)
{
int cap_ptr = iommu->cap_ptr;
u32 range, misc;
+ int i, j;
pci_read_config_dword(iommu->dev, cap_ptr + MMIO_CAP_HDR_OFFSET,
&iommu->cap);
@@ -633,12 +667,29 @@ static void __init init_iommu_from_pci(struct amd_iommu *iommu)
MMIO_GET_LD(range));
iommu->evt_msi_num = MMIO_MSI_NUM(misc);
- if (is_rd890_iommu(iommu->dev)) {
- pci_read_config_dword(iommu->dev, 0xf0, &iommu->cache_cfg[0]);
- pci_read_config_dword(iommu->dev, 0xf4, &iommu->cache_cfg[1]);
- pci_read_config_dword(iommu->dev, 0xf8, &iommu->cache_cfg[2]);
- pci_read_config_dword(iommu->dev, 0xfc, &iommu->cache_cfg[3]);
- }
+ if (!is_rd890_iommu(iommu->dev))
+ return;
+
+ /*
+ * Some rd890 systems may not be fully reconfigured by the BIOS, so
+ * it's necessary for us to store this information so it can be
+ * reprogrammed on resume
+ */
+
+ pci_read_config_dword(iommu->dev, iommu->cap_ptr + 4,
+ &iommu->stored_addr_lo);
+ pci_read_config_dword(iommu->dev, iommu->cap_ptr + 8,
+ &iommu->stored_addr_hi);
+
+ /* Low bit locks writes to configuration space */
+ iommu->stored_addr_lo &= ~1;
+
+ for (i = 0; i < 6; i++)
+ for (j = 0; j < 0x12; j++)
+ iommu->stored_l1[i][j] = iommu_read_l1(iommu, i, j);
+
+ for (i = 0; i < 0x83; i++)
+ iommu->stored_l2[i] = iommu_read_l2(iommu, i);
}
/*
@@ -1127,14 +1178,53 @@ static void iommu_init_flags(struct amd_iommu *iommu)
iommu_feature_enable(iommu, CONTROL_COHERENT_EN);
}
-static void iommu_apply_quirks(struct amd_iommu *iommu)
+static void iommu_apply_resume_quirks(struct amd_iommu *iommu)
{
- if (is_rd890_iommu(iommu->dev)) {
- pci_write_config_dword(iommu->dev, 0xf0, iommu->cache_cfg[0]);
- pci_write_config_dword(iommu->dev, 0xf4, iommu->cache_cfg[1]);
- pci_write_config_dword(iommu->dev, 0xf8, iommu->cache_cfg[2]);
- pci_write_config_dword(iommu->dev, 0xfc, iommu->cache_cfg[3]);
- }
+ int i, j;
+ u32 ioc_feature_control;
+ struct pci_dev *pdev = NULL;
+
+ /* RD890 BIOSes may not have completely reconfigured the iommu */
+ if (!is_rd890_iommu(iommu->dev))
+ return;
+
+ /*
+ * First, we need to ensure that the iommu is enabled. This is
+ * controlled by a register in the northbridge
+ */
+ pdev = pci_get_bus_and_slot(iommu->dev->bus->number, PCI_DEVFN(0, 0));
+
+ if (!pdev)
+ return;
+
+ /* Select Northbridge indirect register 0x75 and enable writing */
+ pci_write_config_dword(pdev, 0x60, 0x75 | (1 << 7));
+ pci_read_config_dword(pdev, 0x64, &ioc_feature_control);
+
+ /* Enable the iommu */
+ if (!(ioc_feature_control & 0x1))
+ pci_write_config_dword(pdev, 0x64, ioc_feature_control | 1);
+
+ pci_dev_put(pdev);
+
+ /* Restore the iommu BAR */
+ pci_write_config_dword(iommu->dev, iommu->cap_ptr + 4,
+ iommu->stored_addr_lo);
+ pci_write_config_dword(iommu->dev, iommu->cap_ptr + 8,
+ iommu->stored_addr_hi);
+
+ /* Restore the l1 indirect regs for each of the 6 l1s */
+ for (i = 0; i < 6; i++)
+ for (j = 0; j < 0x12; j++)
+ iommu_write_l1(iommu, i, j, iommu->stored_l1[i][j]);
+
+ /* Restore the l2 indirect regs */
+ for (i = 0; i < 0x83; i++)
+ iommu_write_l2(iommu, i, iommu->stored_l2[i]);
+
+ /* Lock PCI setup registers */
+ pci_write_config_dword(iommu->dev, iommu->cap_ptr + 4,
+ iommu->stored_addr_lo | 1);
}
/*
@@ -1147,7 +1237,6 @@ static void enable_iommus(void)
for_each_iommu(iommu) {
iommu_disable(iommu);
- iommu_apply_quirks(iommu);
iommu_init_flags(iommu);
iommu_set_device_table(iommu);
iommu_enable_command_buffer(iommu);
@@ -1173,6 +1262,11 @@ static void disable_iommus(void)
static int amd_iommu_resume(struct sys_device *dev)
{
+ struct amd_iommu *iommu;
+
+ for_each_iommu(iommu)
+ iommu_apply_resume_quirks(iommu);
+
/* re-load the hardware */
enable_iommus();
@@ -1405,13 +1499,13 @@ static int __init early_amd_iommu_detect(struct acpi_table_header *table)
return 0;
}
-void __init amd_iommu_detect(void)
+int __init amd_iommu_detect(void)
{
if (no_iommu || (iommu_detected && !gart_iommu_aperture))
- return;
+ return -ENODEV;
if (amd_iommu_disabled)
- return;
+ return -ENODEV;
if (acpi_table_parse("IVRS", early_amd_iommu_detect) == 0) {
iommu_detected = 1;
@@ -1420,7 +1514,9 @@ void __init amd_iommu_detect(void)
/* Make sure ACS will be enabled */
pci_request_acs();
+ return 1;
}
+ return -ENODEV;
}
/****************************************************************************
@@ -1451,3 +1547,8 @@ static int __init parse_amd_iommu_options(char *str)
__setup("amd_iommu_dump", parse_amd_iommu_dump);
__setup("amd_iommu=", parse_amd_iommu_options);
+
+IOMMU_INIT_FINISH(amd_iommu_detect,
+ gart_iommu_hole_init,
+ 0,
+ 0);
diff --git a/arch/x86/kernel/k8.c b/arch/x86/kernel/amd_nb.c
index 0f7bc20cfcde..8f6463d8ed0d 100644
--- a/arch/x86/kernel/k8.c
+++ b/arch/x86/kernel/amd_nb.c
@@ -8,21 +8,19 @@
#include <linux/errno.h>
#include <linux/module.h>
#include <linux/spinlock.h>
-#include <asm/k8.h>
-
-int num_k8_northbridges;
-EXPORT_SYMBOL(num_k8_northbridges);
+#include <asm/amd_nb.h>
static u32 *flush_words;
struct pci_device_id k8_nb_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MISC) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC) },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_MISC) },
{}
};
EXPORT_SYMBOL(k8_nb_ids);
-struct pci_dev **k8_northbridges;
+struct k8_northbridge_info k8_northbridges;
EXPORT_SYMBOL(k8_northbridges);
static struct pci_dev *next_k8_northbridge(struct pci_dev *dev)
@@ -40,36 +38,45 @@ int cache_k8_northbridges(void)
int i;
struct pci_dev *dev;
- if (num_k8_northbridges)
+ if (k8_northbridges.num)
return 0;
dev = NULL;
while ((dev = next_k8_northbridge(dev)) != NULL)
- num_k8_northbridges++;
+ k8_northbridges.num++;
+
+ /* some CPU families (e.g. family 0x11) do not support GART */
+ if (boot_cpu_data.x86 == 0xf || boot_cpu_data.x86 == 0x10 ||
+ boot_cpu_data.x86 == 0x15)
+ k8_northbridges.gart_supported = 1;
- k8_northbridges = kmalloc((num_k8_northbridges + 1) * sizeof(void *),
- GFP_KERNEL);
- if (!k8_northbridges)
+ k8_northbridges.nb_misc = kmalloc((k8_northbridges.num + 1) *
+ sizeof(void *), GFP_KERNEL);
+ if (!k8_northbridges.nb_misc)
return -ENOMEM;
- if (!num_k8_northbridges) {
- k8_northbridges[0] = NULL;
+ if (!k8_northbridges.num) {
+ k8_northbridges.nb_misc[0] = NULL;
return 0;
}
- flush_words = kmalloc(num_k8_northbridges * sizeof(u32), GFP_KERNEL);
- if (!flush_words) {
- kfree(k8_northbridges);
- return -ENOMEM;
+ if (k8_northbridges.gart_supported) {
+ flush_words = kmalloc(k8_northbridges.num * sizeof(u32),
+ GFP_KERNEL);
+ if (!flush_words) {
+ kfree(k8_northbridges.nb_misc);
+ return -ENOMEM;
+ }
}
dev = NULL;
i = 0;
while ((dev = next_k8_northbridge(dev)) != NULL) {
- k8_northbridges[i] = dev;
- pci_read_config_dword(dev, 0x9c, &flush_words[i++]);
+ k8_northbridges.nb_misc[i] = dev;
+ if (k8_northbridges.gart_supported)
+ pci_read_config_dword(dev, 0x9c, &flush_words[i++]);
}
- k8_northbridges[i] = NULL;
+ k8_northbridges.nb_misc[i] = NULL;
return 0;
}
EXPORT_SYMBOL_GPL(cache_k8_northbridges);
@@ -93,22 +100,25 @@ void k8_flush_garts(void)
unsigned long flags;
static DEFINE_SPINLOCK(gart_lock);
+ if (!k8_northbridges.gart_supported)
+ return;
+
/* Avoid races between AGP and IOMMU. In theory it's not needed
but I'm not sure if the hardware won't lose flush requests
when another is pending. This whole thing is so expensive anyways
that it doesn't matter to serialize more. -AK */
spin_lock_irqsave(&gart_lock, flags);
flushed = 0;
- for (i = 0; i < num_k8_northbridges; i++) {
- pci_write_config_dword(k8_northbridges[i], 0x9c,
+ for (i = 0; i < k8_northbridges.num; i++) {
+ pci_write_config_dword(k8_northbridges.nb_misc[i], 0x9c,
flush_words[i]|1);
flushed++;
}
- for (i = 0; i < num_k8_northbridges; i++) {
+ for (i = 0; i < k8_northbridges.num; i++) {
u32 w;
/* Make sure the hardware actually executed the flush*/
for (;;) {
- pci_read_config_dword(k8_northbridges[i],
+ pci_read_config_dword(k8_northbridges.nb_misc[i],
0x9c, &w);
if (!(w & 1))
break;
diff --git a/arch/x86/kernel/apb_timer.c b/arch/x86/kernel/apb_timer.c
index 8dd77800ff5d..92543c73cf8e 100644
--- a/arch/x86/kernel/apb_timer.c
+++ b/arch/x86/kernel/apb_timer.c
@@ -231,34 +231,6 @@ static void apbt_restart_clocksource(struct clocksource *cs)
apbt_start_counter(phy_cs_timer_id);
}
-/* Setup IRQ routing via IOAPIC */
-#ifdef CONFIG_SMP
-static void apbt_setup_irq(struct apbt_dev *adev)
-{
- struct irq_chip *chip;
- struct irq_desc *desc;
-
- /* timer0 irq has been setup early */
- if (adev->irq == 0)
- return;
- desc = irq_to_desc(adev->irq);
- chip = get_irq_chip(adev->irq);
- disable_irq(adev->irq);
- desc->status |= IRQ_MOVE_PCNTXT;
- irq_set_affinity(adev->irq, cpumask_of(adev->cpu));
- /* APB timer irqs are set up as mp_irqs, timer is edge triggerred */
- set_irq_chip_and_handler_name(adev->irq, chip, handle_edge_irq, "edge");
- enable_irq(adev->irq);
- if (system_state == SYSTEM_BOOTING)
- if (request_irq(adev->irq, apbt_interrupt_handler,
- IRQF_TIMER | IRQF_DISABLED | IRQF_NOBALANCING,
- adev->name, adev)) {
- printk(KERN_ERR "Failed request IRQ for APBT%d\n",
- adev->num);
- }
-}
-#endif
-
static void apbt_enable_int(int n)
{
unsigned long ctrl = apbt_readl(n, APBTMR_N_CONTROL);
@@ -334,6 +306,27 @@ static int __init apbt_clockevent_register(void)
}
#ifdef CONFIG_SMP
+
+static void apbt_setup_irq(struct apbt_dev *adev)
+{
+ /* timer0 irq has been setup early */
+ if (adev->irq == 0)
+ return;
+
+ if (system_state == SYSTEM_BOOTING) {
+ irq_modify_status(adev->irq, 0, IRQ_MOVE_PCNTXT);
+ /* APB timer irqs are set up as mp_irqs, timer is edge type */
+ __set_irq_handler(adev->irq, handle_edge_irq, 0, "edge");
+ if (request_irq(adev->irq, apbt_interrupt_handler,
+ IRQF_TIMER | IRQF_DISABLED | IRQF_NOBALANCING,
+ adev->name, adev)) {
+ printk(KERN_ERR "Failed request IRQ for APBT%d\n",
+ adev->num);
+ }
+ } else
+ enable_irq(adev->irq);
+}
+
/* Should be called with per cpu */
void apbt_setup_secondary_clock(void)
{
@@ -343,7 +336,7 @@ void apbt_setup_secondary_clock(void)
/* Don't register boot CPU clockevent */
cpu = smp_processor_id();
- if (cpu == boot_cpu_id)
+ if (!cpu)
return;
/*
* We need to calculate the scaled math multiplication factor for
@@ -389,16 +382,17 @@ static int apbt_cpuhp_notify(struct notifier_block *n,
switch (action & 0xf) {
case CPU_DEAD:
+ disable_irq(adev->irq);
apbt_disable_int(cpu);
- if (system_state == SYSTEM_RUNNING)
+ if (system_state == SYSTEM_RUNNING) {
pr_debug("skipping APBT CPU %lu offline\n", cpu);
- else if (adev) {
+ } else if (adev) {
pr_debug("APBT clockevent for cpu %lu offline\n", cpu);
free_irq(adev->irq, adev);
}
break;
default:
- pr_debug(KERN_INFO "APBT notified %lu, no action\n", action);
+ pr_debug("APBT notified %lu, no action\n", action);
}
return NOTIFY_OK;
}
@@ -552,7 +546,7 @@ bad_count:
pr_debug("APB CS going back %lx:%lx:%lx ",
t2, last_read, t2 - last_read);
bad_count_x3:
- pr_debug(KERN_INFO "tripple check enforced\n");
+ pr_debug("triple check enforced\n");
t0 = apbt_readl(phy_cs_timer_id,
APBTMR_N_CURRENT_VALUE);
udelay(1);
diff --git a/arch/x86/kernel/aperture_64.c b/arch/x86/kernel/aperture_64.c
index a2e0caf26e17..b3a16e8f0703 100644
--- a/arch/x86/kernel/aperture_64.c
+++ b/arch/x86/kernel/aperture_64.c
@@ -27,7 +27,7 @@
#include <asm/gart.h>
#include <asm/pci-direct.h>
#include <asm/dma.h>
-#include <asm/k8.h>
+#include <asm/amd_nb.h>
#include <asm/x86_init.h>
int gart_iommu_aperture;
@@ -307,7 +307,7 @@ void __init early_gart_iommu_check(void)
continue;
ctl = read_pci_config(bus, slot, 3, AMD64_GARTAPERTURECTL);
- aper_enabled = ctl & AMD64_GARTEN;
+ aper_enabled = ctl & GARTEN;
aper_order = (ctl >> 1) & 7;
aper_size = (32 * 1024 * 1024) << aper_order;
aper_base = read_pci_config(bus, slot, 3, AMD64_GARTAPERTUREBASE) & 0x7fff;
@@ -362,7 +362,7 @@ void __init early_gart_iommu_check(void)
continue;
ctl = read_pci_config(bus, slot, 3, AMD64_GARTAPERTURECTL);
- ctl &= ~AMD64_GARTEN;
+ ctl &= ~GARTEN;
write_pci_config(bus, slot, 3, AMD64_GARTAPERTURECTL, ctl);
}
}
@@ -371,7 +371,7 @@ void __init early_gart_iommu_check(void)
static int __initdata printed_gart_size_msg;
-void __init gart_iommu_hole_init(void)
+int __init gart_iommu_hole_init(void)
{
u32 agp_aper_base = 0, agp_aper_order = 0;
u32 aper_size, aper_alloc = 0, aper_order = 0, last_aper_order = 0;
@@ -381,7 +381,7 @@ void __init gart_iommu_hole_init(void)
if (gart_iommu_aperture_disabled || !fix_aperture ||
!early_pci_allowed())
- return;
+ return -ENODEV;
printk(KERN_INFO "Checking aperture...\n");
@@ -463,8 +463,9 @@ out:
unsigned long n = (32 * 1024 * 1024) << last_aper_order;
insert_aperture_resource((u32)last_aper_base, n);
+ return 1;
}
- return;
+ return 0;
}
if (!fallback_aper_force) {
@@ -500,13 +501,18 @@ out:
panic("Not enough memory for aperture");
}
} else {
- return;
+ return 0;
}
/* Fix up the north bridges */
for (i = 0; i < ARRAY_SIZE(bus_dev_ranges); i++) {
- int bus;
- int dev_base, dev_limit;
+ int bus, dev_base, dev_limit;
+
+ /*
+ * Don't enable translation yet but enable GART IO and CPU
+ * accesses and set DISTLBWALKPRB since GART table memory is UC.
+ */
+ u32 ctl = DISTLBWALKPRB | aper_order << 1;
bus = bus_dev_ranges[i].bus;
dev_base = bus_dev_ranges[i].dev_base;
@@ -515,13 +521,12 @@ out:
if (!early_is_k8_nb(read_pci_config(bus, slot, 3, 0x00)))
continue;
- /* Don't enable translation yet. That is done later.
- Assume this BIOS didn't initialise the GART so
- just overwrite all previous bits */
- write_pci_config(bus, slot, 3, AMD64_GARTAPERTURECTL, aper_order << 1);
+ write_pci_config(bus, slot, 3, AMD64_GARTAPERTURECTL, ctl);
write_pci_config(bus, slot, 3, AMD64_GARTAPERTUREBASE, aper_alloc >> 25);
}
}
set_up_gart_resume(aper_order, aper_alloc);
+
+ return 1;
}
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index e3b534cda49a..850657d1b0ed 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -52,6 +52,7 @@
#include <asm/mce.h>
#include <asm/kvm_para.h>
#include <asm/tsc.h>
+#include <asm/atomic.h>
unsigned int num_processors;
@@ -370,38 +371,87 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
}
/*
- * Setup extended LVT, AMD specific (K8, family 10h)
+ * Setup extended LVT, AMD specific
*
- * Vector mappings are hard coded. On K8 only offset 0 (APIC500) and
- * MCE interrupts are supported. Thus MCE offset must be set to 0.
+ * Software should use the LVT offsets the BIOS provides. The offsets
+ * are determined by the subsystems using it like those for MCE
+ * threshold or IBS. On K8 only offset 0 (APIC500) and MCE interrupts
+ * are supported. Beginning with family 10h at least 4 offsets are
+ * available.
*
- * If mask=1, the LVT entry does not generate interrupts while mask=0
- * enables the vector. See also the BKDGs.
+ * Since the offsets must be consistent for all cores, we keep track
+ * of the LVT offsets in software and reserve the offset for the same
+ * vector also to be used on other cores. An offset is freed by
+ * setting the entry to APIC_EILVT_MASKED.
+ *
+ * If the BIOS is right, there should be no conflicts. Otherwise a
+ * "[Firmware Bug]: ..." error message is generated. However, if
+ * software does not properly determines the offsets, it is not
+ * necessarily a BIOS bug.
*/
-#define APIC_EILVT_LVTOFF_MCE 0
-#define APIC_EILVT_LVTOFF_IBS 1
+static atomic_t eilvt_offsets[APIC_EILVT_NR_MAX];
-static void setup_APIC_eilvt(u8 lvt_off, u8 vector, u8 msg_type, u8 mask)
+static inline int eilvt_entry_is_changeable(unsigned int old, unsigned int new)
{
- unsigned long reg = (lvt_off << 4) + APIC_EILVTn(0);
- unsigned int v = (mask << 16) | (msg_type << 8) | vector;
-
- apic_write(reg, v);
+ return (old & APIC_EILVT_MASKED)
+ || (new == APIC_EILVT_MASKED)
+ || ((new & ~APIC_EILVT_MASKED) == old);
}
-u8 setup_APIC_eilvt_mce(u8 vector, u8 msg_type, u8 mask)
+static unsigned int reserve_eilvt_offset(int offset, unsigned int new)
{
- setup_APIC_eilvt(APIC_EILVT_LVTOFF_MCE, vector, msg_type, mask);
- return APIC_EILVT_LVTOFF_MCE;
+ unsigned int rsvd; /* 0: uninitialized */
+
+ if (offset >= APIC_EILVT_NR_MAX)
+ return ~0;
+
+ rsvd = atomic_read(&eilvt_offsets[offset]) & ~APIC_EILVT_MASKED;
+ do {
+ if (rsvd &&
+ !eilvt_entry_is_changeable(rsvd, new))
+ /* may not change if vectors are different */
+ return rsvd;
+ rsvd = atomic_cmpxchg(&eilvt_offsets[offset], rsvd, new);
+ } while (rsvd != new);
+
+ return new;
}
-u8 setup_APIC_eilvt_ibs(u8 vector, u8 msg_type, u8 mask)
+/*
+ * If mask=1, the LVT entry does not generate interrupts while mask=0
+ * enables the vector. See also the BKDGs.
+ */
+
+int setup_APIC_eilvt(u8 offset, u8 vector, u8 msg_type, u8 mask)
{
- setup_APIC_eilvt(APIC_EILVT_LVTOFF_IBS, vector, msg_type, mask);
- return APIC_EILVT_LVTOFF_IBS;
+ unsigned long reg = APIC_EILVTn(offset);
+ unsigned int new, old, reserved;
+
+ new = (mask << 16) | (msg_type << 8) | vector;
+ old = apic_read(reg);
+ reserved = reserve_eilvt_offset(offset, new);
+
+ if (reserved != new) {
+ pr_err(FW_BUG "cpu %d, try to setup vector 0x%x, but "
+ "vector 0x%x was already reserved by another core, "
+ "APIC%lX=0x%x\n",
+ smp_processor_id(), new, reserved, reg, old);
+ return -EINVAL;
+ }
+
+ if (!eilvt_entry_is_changeable(old, new)) {
+ pr_err(FW_BUG "cpu %d, try to setup vector 0x%x but "
+ "register already in use, APIC%lX=0x%x\n",
+ smp_processor_id(), new, reg, old);
+ return -EBUSY;
+ }
+
+ apic_write(reg, new);
+
+ return 0;
}
-EXPORT_SYMBOL_GPL(setup_APIC_eilvt_ibs);
+EXPORT_SYMBOL_GPL(setup_APIC_eilvt);
/*
* Program the next event, relative to now
@@ -1665,10 +1715,7 @@ int __init APIC_init_uniprocessor(void)
}
#endif
-#ifndef CONFIG_SMP
- enable_IR_x2apic();
default_setup_apic_routing();
-#endif
verify_local_APIC();
connect_bsp_APIC();
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index f1efebaf5510..8ae808d110f4 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -131,13 +131,9 @@ struct irq_pin_list {
struct irq_pin_list *next;
};
-static struct irq_pin_list *get_one_free_irq_2_pin(int node)
+static struct irq_pin_list *alloc_irq_pin_list(int node)
{
- struct irq_pin_list *pin;
-
- pin = kzalloc_node(sizeof(*pin), GFP_ATOMIC, node);
-
- return pin;
+ return kzalloc_node(sizeof(struct irq_pin_list), GFP_KERNEL, node);
}
/* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */
@@ -150,10 +146,7 @@ static struct irq_cfg irq_cfgx[NR_IRQS];
int __init arch_early_irq_init(void)
{
struct irq_cfg *cfg;
- struct irq_desc *desc;
- int count;
- int node;
- int i;
+ int count, node, i;
if (!legacy_pic->nr_legacy_irqs) {
nr_irqs_gsi = 0;
@@ -162,13 +155,15 @@ int __init arch_early_irq_init(void)
cfg = irq_cfgx;
count = ARRAY_SIZE(irq_cfgx);
- node= cpu_to_node(boot_cpu_id);
+ node = cpu_to_node(0);
+
+ /* Make sure the legacy interrupts are marked in the bitmap */
+ irq_reserve_irqs(0, legacy_pic->nr_legacy_irqs);
for (i = 0; i < count; i++) {
- desc = irq_to_desc(i);
- desc->chip_data = &cfg[i];
- zalloc_cpumask_var_node(&cfg[i].domain, GFP_NOWAIT, node);
- zalloc_cpumask_var_node(&cfg[i].old_domain, GFP_NOWAIT, node);
+ set_irq_chip_data(i, &cfg[i]);
+ zalloc_cpumask_var_node(&cfg[i].domain, GFP_KERNEL, node);
+ zalloc_cpumask_var_node(&cfg[i].old_domain, GFP_KERNEL, node);
/*
* For legacy IRQ's, start with assigning irq0 to irq15 to
* IRQ0_VECTOR to IRQ15_VECTOR on cpu 0.
@@ -183,165 +178,88 @@ int __init arch_early_irq_init(void)
}
#ifdef CONFIG_SPARSE_IRQ
-struct irq_cfg *irq_cfg(unsigned int irq)
+static struct irq_cfg *irq_cfg(unsigned int irq)
{
- struct irq_cfg *cfg = NULL;
- struct irq_desc *desc;
-
- desc = irq_to_desc(irq);
- if (desc)
- cfg = desc->chip_data;
-
- return cfg;
+ return get_irq_chip_data(irq);
}
-static struct irq_cfg *get_one_free_irq_cfg(int node)
+static struct irq_cfg *alloc_irq_cfg(unsigned int irq, int node)
{
struct irq_cfg *cfg;
- cfg = kzalloc_node(sizeof(*cfg), GFP_ATOMIC, node);
- if (cfg) {
- if (!zalloc_cpumask_var_node(&cfg->domain, GFP_ATOMIC, node)) {
- kfree(cfg);
- cfg = NULL;
- } else if (!zalloc_cpumask_var_node(&cfg->old_domain,
- GFP_ATOMIC, node)) {
- free_cpumask_var(cfg->domain);
- kfree(cfg);
- cfg = NULL;
- }
- }
-
+ cfg = kzalloc_node(sizeof(*cfg), GFP_KERNEL, node);
+ if (!cfg)
+ return NULL;
+ if (!zalloc_cpumask_var_node(&cfg->domain, GFP_KERNEL, node))
+ goto out_cfg;
+ if (!zalloc_cpumask_var_node(&cfg->old_domain, GFP_KERNEL, node))
+ goto out_domain;
return cfg;
+out_domain:
+ free_cpumask_var(cfg->domain);
+out_cfg:
+ kfree(cfg);
+ return NULL;
}
-int arch_init_chip_data(struct irq_desc *desc, int node)
-{
- struct irq_cfg *cfg;
-
- cfg = desc->chip_data;
- if (!cfg) {
- desc->chip_data = get_one_free_irq_cfg(node);
- if (!desc->chip_data) {
- printk(KERN_ERR "can not alloc irq_cfg\n");
- BUG_ON(1);
- }
- }
-
- return 0;
-}
-
-/* for move_irq_desc */
-static void
-init_copy_irq_2_pin(struct irq_cfg *old_cfg, struct irq_cfg *cfg, int node)
+static void free_irq_cfg(unsigned int at, struct irq_cfg *cfg)
{
- struct irq_pin_list *old_entry, *head, *tail, *entry;
-
- cfg->irq_2_pin = NULL;
- old_entry = old_cfg->irq_2_pin;
- if (!old_entry)
- return;
-
- entry = get_one_free_irq_2_pin(node);
- if (!entry)
+ if (!cfg)
return;
+ set_irq_chip_data(at, NULL);
+ free_cpumask_var(cfg->domain);
+ free_cpumask_var(cfg->old_domain);
+ kfree(cfg);
+}
- entry->apic = old_entry->apic;
- entry->pin = old_entry->pin;
- head = entry;
- tail = entry;
- old_entry = old_entry->next;
- while (old_entry) {
- entry = get_one_free_irq_2_pin(node);
- if (!entry) {
- entry = head;
- while (entry) {
- head = entry->next;
- kfree(entry);
- entry = head;
- }
- /* still use the old one */
- return;
- }
- entry->apic = old_entry->apic;
- entry->pin = old_entry->pin;
- tail->next = entry;
- tail = entry;
- old_entry = old_entry->next;
- }
+#else
- tail->next = NULL;
- cfg->irq_2_pin = head;
+struct irq_cfg *irq_cfg(unsigned int irq)
+{
+ return irq < nr_irqs ? irq_cfgx + irq : NULL;
}
-static void free_irq_2_pin(struct irq_cfg *old_cfg, struct irq_cfg *cfg)
+static struct irq_cfg *alloc_irq_cfg(unsigned int irq, int node)
{
- struct irq_pin_list *entry, *next;
-
- if (old_cfg->irq_2_pin == cfg->irq_2_pin)
- return;
+ return irq_cfgx + irq;
+}
- entry = old_cfg->irq_2_pin;
+static inline void free_irq_cfg(unsigned int at, struct irq_cfg *cfg) { }
- while (entry) {
- next = entry->next;
- kfree(entry);
- entry = next;
- }
- old_cfg->irq_2_pin = NULL;
-}
+#endif
-void arch_init_copy_chip_data(struct irq_desc *old_desc,
- struct irq_desc *desc, int node)
+static struct irq_cfg *alloc_irq_and_cfg_at(unsigned int at, int node)
{
+ int res = irq_alloc_desc_at(at, node);
struct irq_cfg *cfg;
- struct irq_cfg *old_cfg;
-
- cfg = get_one_free_irq_cfg(node);
-
- if (!cfg)
- return;
- desc->chip_data = cfg;
-
- old_cfg = old_desc->chip_data;
-
- memcpy(cfg, old_cfg, sizeof(struct irq_cfg));
-
- init_copy_irq_2_pin(old_cfg, cfg, node);
-}
+ if (res < 0) {
+ if (res != -EEXIST)
+ return NULL;
+ cfg = get_irq_chip_data(at);
+ if (cfg)
+ return cfg;
+ }
-static void free_irq_cfg(struct irq_cfg *old_cfg)
-{
- kfree(old_cfg);
+ cfg = alloc_irq_cfg(at, node);
+ if (cfg)
+ set_irq_chip_data(at, cfg);
+ else
+ irq_free_desc(at);
+ return cfg;
}
-void arch_free_chip_data(struct irq_desc *old_desc, struct irq_desc *desc)
+static int alloc_irq_from(unsigned int from, int node)
{
- struct irq_cfg *old_cfg, *cfg;
-
- old_cfg = old_desc->chip_data;
- cfg = desc->chip_data;
-
- if (old_cfg == cfg)
- return;
-
- if (old_cfg) {
- free_irq_2_pin(old_cfg, cfg);
- free_irq_cfg(old_cfg);
- old_desc->chip_data = NULL;
- }
+ return irq_alloc_desc_from(from, node);
}
-/* end for move_irq_desc */
-#else
-struct irq_cfg *irq_cfg(unsigned int irq)
+static void free_irq_at(unsigned int at, struct irq_cfg *cfg)
{
- return irq < nr_irqs ? irq_cfgx + irq : NULL;
+ free_irq_cfg(at, cfg);
+ irq_free_desc(at);
}
-#endif
-
struct io_apic {
unsigned int index;
unsigned int unused[3];
@@ -446,7 +364,7 @@ __ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
io_apic_write(apic, 0x10 + 2*pin, eu.w1);
}
-void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
+static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
{
unsigned long flags;
raw_spin_lock_irqsave(&ioapic_lock, flags);
@@ -476,7 +394,7 @@ static void ioapic_mask_entry(int apic, int pin)
* fast in the common case, and fast for shared ISA-space IRQs.
*/
static int
-add_pin_to_irq_node_nopanic(struct irq_cfg *cfg, int node, int apic, int pin)
+__add_pin_to_irq_node(struct irq_cfg *cfg, int node, int apic, int pin)
{
struct irq_pin_list **last, *entry;
@@ -488,7 +406,7 @@ add_pin_to_irq_node_nopanic(struct irq_cfg *cfg, int node, int apic, int pin)
last = &entry->next;
}
- entry = get_one_free_irq_2_pin(node);
+ entry = alloc_irq_pin_list(node);
if (!entry) {
printk(KERN_ERR "can not alloc irq_pin_list (%d,%d,%d)\n",
node, apic, pin);
@@ -503,7 +421,7 @@ add_pin_to_irq_node_nopanic(struct irq_cfg *cfg, int node, int apic, int pin)
static void add_pin_to_irq_node(struct irq_cfg *cfg, int node, int apic, int pin)
{
- if (add_pin_to_irq_node_nopanic(cfg, node, apic, pin))
+ if (__add_pin_to_irq_node(cfg, node, apic, pin))
panic("IO-APIC: failed to add irq-pin. Can not proceed\n");
}
@@ -566,11 +484,6 @@ static void __unmask_and_level_IO_APIC_irq(struct irq_pin_list *entry)
IO_APIC_REDIR_LEVEL_TRIGGER, NULL);
}
-static void __unmask_IO_APIC_irq(struct irq_cfg *cfg)
-{
- io_apic_modify_irq(cfg, ~IO_APIC_REDIR_MASKED, 0, NULL);
-}
-
static void io_apic_sync(struct irq_pin_list *entry)
{
/*
@@ -582,44 +495,37 @@ static void io_apic_sync(struct irq_pin_list *entry)
readl(&io_apic->data);
}
-static void __mask_IO_APIC_irq(struct irq_cfg *cfg)
+static void mask_ioapic(struct irq_cfg *cfg)
{
+ unsigned long flags;
+
+ raw_spin_lock_irqsave(&ioapic_lock, flags);
io_apic_modify_irq(cfg, ~0, IO_APIC_REDIR_MASKED, &io_apic_sync);
+ raw_spin_unlock_irqrestore(&ioapic_lock, flags);
}
-static void mask_IO_APIC_irq_desc(struct irq_desc *desc)
+static void mask_ioapic_irq(struct irq_data *data)
{
- struct irq_cfg *cfg = desc->chip_data;
- unsigned long flags;
-
- BUG_ON(!cfg);
+ mask_ioapic(data->chip_data);
+}
- raw_spin_lock_irqsave(&ioapic_lock, flags);
- __mask_IO_APIC_irq(cfg);
- raw_spin_unlock_irqrestore(&ioapic_lock, flags);
+static void __unmask_ioapic(struct irq_cfg *cfg)
+{
+ io_apic_modify_irq(cfg, ~IO_APIC_REDIR_MASKED, 0, NULL);
}
-static void unmask_IO_APIC_irq_desc(struct irq_desc *desc)
+static void unmask_ioapic(struct irq_cfg *cfg)
{
- struct irq_cfg *cfg = desc->chip_data;
unsigned long flags;
raw_spin_lock_irqsave(&ioapic_lock, flags);
- __unmask_IO_APIC_irq(cfg);
+ __unmask_ioapic(cfg);
raw_spin_unlock_irqrestore(&ioapic_lock, flags);
}
-static void mask_IO_APIC_irq(unsigned int irq)
-{
- struct irq_desc *desc = irq_to_desc(irq);
-
- mask_IO_APIC_irq_desc(desc);
-}
-static void unmask_IO_APIC_irq(unsigned int irq)
+static void unmask_ioapic_irq(struct irq_data *data)
{
- struct irq_desc *desc = irq_to_desc(irq);
-
- unmask_IO_APIC_irq_desc(desc);
+ unmask_ioapic(data->chip_data);
}
static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
@@ -689,14 +595,14 @@ struct IO_APIC_route_entry **alloc_ioapic_entries(void)
struct IO_APIC_route_entry **ioapic_entries;
ioapic_entries = kzalloc(sizeof(*ioapic_entries) * nr_ioapics,
- GFP_ATOMIC);
+ GFP_KERNEL);
if (!ioapic_entries)
return 0;
for (apic = 0; apic < nr_ioapics; apic++) {
ioapic_entries[apic] =
kzalloc(sizeof(struct IO_APIC_route_entry) *
- nr_ioapic_registers[apic], GFP_ATOMIC);
+ nr_ioapic_registers[apic], GFP_KERNEL);
if (!ioapic_entries[apic])
goto nomem;
}
@@ -1254,7 +1160,6 @@ void __setup_vector_irq(int cpu)
/* Initialize vector_irq on a new cpu */
int irq, vector;
struct irq_cfg *cfg;
- struct irq_desc *desc;
/*
* vector_lock will make sure that we don't run into irq vector
@@ -1263,9 +1168,10 @@ void __setup_vector_irq(int cpu)
*/
raw_spin_lock(&vector_lock);
/* Mark the inuse vectors */
- for_each_irq_desc(irq, desc) {
- cfg = desc->chip_data;
-
+ for_each_active_irq(irq) {
+ cfg = get_irq_chip_data(irq);
+ if (!cfg)
+ continue;
/*
* If it is a legacy IRQ handled by the legacy PIC, this cpu
* will be part of the irq_cfg's domain.
@@ -1322,17 +1228,17 @@ static inline int IO_APIC_irq_trigger(int irq)
}
#endif
-static void ioapic_register_intr(int irq, struct irq_desc *desc, unsigned long trigger)
+static void ioapic_register_intr(unsigned int irq, unsigned long trigger)
{
if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
trigger == IOAPIC_LEVEL)
- desc->status |= IRQ_LEVEL;
+ irq_set_status_flags(irq, IRQ_LEVEL);
else
- desc->status &= ~IRQ_LEVEL;
+ irq_clear_status_flags(irq, IRQ_LEVEL);
- if (irq_remapped(irq)) {
- desc->status |= IRQ_MOVE_PCNTXT;
+ if (irq_remapped(get_irq_chip_data(irq))) {
+ irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
if (trigger)
set_irq_chip_and_handler_name(irq, &ir_ioapic_chip,
handle_fasteoi_irq,
@@ -1353,10 +1259,10 @@ static void ioapic_register_intr(int irq, struct irq_desc *desc, unsigned long t
handle_edge_irq, "edge");
}
-int setup_ioapic_entry(int apic_id, int irq,
- struct IO_APIC_route_entry *entry,
- unsigned int destination, int trigger,
- int polarity, int vector, int pin)
+static int setup_ioapic_entry(int apic_id, int irq,
+ struct IO_APIC_route_entry *entry,
+ unsigned int destination, int trigger,
+ int polarity, int vector, int pin)
{
/*
* add it to the IO-APIC irq-routing table:
@@ -1377,21 +1283,7 @@ int setup_ioapic_entry(int apic_id, int irq,
if (index < 0)
panic("Failed to allocate IRTE for ioapic %d\n", apic_id);
- memset(&irte, 0, sizeof(irte));
-
- irte.present = 1;
- irte.dst_mode = apic->irq_dest_mode;
- /*
- * Trigger mode in the IRTE will always be edge, and the
- * actual level or edge trigger will be setup in the IO-APIC
- * RTE. This will help simplify level triggered irq migration.
- * For more details, see the comments above explainig IO-APIC
- * irq migration in the presence of interrupt-remapping.
- */
- irte.trigger_mode = 0;
- irte.dlvry_mode = apic->irq_delivery_mode;
- irte.vector = vector;
- irte.dest_id = IRTE_DEST(destination);
+ prepare_irte(&irte, vector, destination);
/* Set source-id of interrupt request */
set_ioapic_sid(&irte, apic_id);
@@ -1426,18 +1318,14 @@ int setup_ioapic_entry(int apic_id, int irq,
return 0;
}
-static void setup_IO_APIC_irq(int apic_id, int pin, unsigned int irq, struct irq_desc *desc,
- int trigger, int polarity)
+static void setup_ioapic_irq(int apic_id, int pin, unsigned int irq,
+ struct irq_cfg *cfg, int trigger, int polarity)
{
- struct irq_cfg *cfg;
struct IO_APIC_route_entry entry;
unsigned int dest;
if (!IO_APIC_IRQ(irq))
return;
-
- cfg = desc->chip_data;
-
/*
* For legacy irqs, cfg->domain starts with cpu 0 for legacy
* controllers like 8259. Now that IO-APIC can handle this irq, update
@@ -1466,9 +1354,9 @@ static void setup_IO_APIC_irq(int apic_id, int pin, unsigned int irq, struct irq
return;
}
- ioapic_register_intr(irq, desc, trigger);
+ ioapic_register_intr(irq, trigger);
if (irq < legacy_pic->nr_legacy_irqs)
- legacy_pic->chip->mask(irq);
+ legacy_pic->mask(irq);
ioapic_write_entry(apic_id, pin, entry);
}
@@ -1479,11 +1367,9 @@ static struct {
static void __init setup_IO_APIC_irqs(void)
{
- int apic_id, pin, idx, irq;
- int notcon = 0;
- struct irq_desc *desc;
+ int apic_id, pin, idx, irq, notcon = 0;
+ int node = cpu_to_node(0);
struct irq_cfg *cfg;
- int node = cpu_to_node(boot_cpu_id);
apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
@@ -1520,19 +1406,17 @@ static void __init setup_IO_APIC_irqs(void)
apic->multi_timer_check(apic_id, irq))
continue;
- desc = irq_to_desc_alloc_node(irq, node);
- if (!desc) {
- printk(KERN_INFO "can not get irq_desc for %d\n", irq);
+ cfg = alloc_irq_and_cfg_at(irq, node);
+ if (!cfg)
continue;
- }
- cfg = desc->chip_data;
+
add_pin_to_irq_node(cfg, node, apic_id, pin);
/*
* don't mark it in pin_programmed, so later acpi could
* set it correctly when irq < 16
*/
- setup_IO_APIC_irq(apic_id, pin, irq, desc,
- irq_trigger(idx), irq_polarity(idx));
+ setup_ioapic_irq(apic_id, pin, irq, cfg, irq_trigger(idx),
+ irq_polarity(idx));
}
if (notcon)
@@ -1547,9 +1431,7 @@ static void __init setup_IO_APIC_irqs(void)
*/
void setup_IO_APIC_irq_extra(u32 gsi)
{
- int apic_id = 0, pin, idx, irq;
- int node = cpu_to_node(boot_cpu_id);
- struct irq_desc *desc;
+ int apic_id = 0, pin, idx, irq, node = cpu_to_node(0);
struct irq_cfg *cfg;
/*
@@ -1565,18 +1447,15 @@ void setup_IO_APIC_irq_extra(u32 gsi)
return;
irq = pin_2_irq(idx, apic_id, pin);
-#ifdef CONFIG_SPARSE_IRQ
- desc = irq_to_desc(irq);
- if (desc)
+
+ /* Only handle the non legacy irqs on secondary ioapics */
+ if (apic_id == 0 || irq < NR_IRQS_LEGACY)
return;
-#endif
- desc = irq_to_desc_alloc_node(irq, node);
- if (!desc) {
- printk(KERN_INFO "can not get irq_desc for %d\n", irq);
+
+ cfg = alloc_irq_and_cfg_at(irq, node);
+ if (!cfg)
return;
- }
- cfg = desc->chip_data;
add_pin_to_irq_node(cfg, node, apic_id, pin);
if (test_bit(pin, mp_ioapic_routing[apic_id].pin_programmed)) {
@@ -1586,7 +1465,7 @@ void setup_IO_APIC_irq_extra(u32 gsi)
}
set_bit(pin, mp_ioapic_routing[apic_id].pin_programmed);
- setup_IO_APIC_irq(apic_id, pin, irq, desc,
+ setup_ioapic_irq(apic_id, pin, irq, cfg,
irq_trigger(idx), irq_polarity(idx));
}
@@ -1637,7 +1516,6 @@ __apicdebuginit(void) print_IO_APIC(void)
union IO_APIC_reg_03 reg_03;
unsigned long flags;
struct irq_cfg *cfg;
- struct irq_desc *desc;
unsigned int irq;
printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
@@ -1724,10 +1602,10 @@ __apicdebuginit(void) print_IO_APIC(void)
}
}
printk(KERN_DEBUG "IRQ to pin mappings:\n");
- for_each_irq_desc(irq, desc) {
+ for_each_active_irq(irq) {
struct irq_pin_list *entry;
- cfg = desc->chip_data;
+ cfg = get_irq_chip_data(irq);
if (!cfg)
continue;
entry = cfg->irq_2_pin;
@@ -2234,29 +2112,26 @@ static int __init timer_irq_works(void)
* an edge even if it isn't on the 8259A...
*/
-static unsigned int startup_ioapic_irq(unsigned int irq)
+static unsigned int startup_ioapic_irq(struct irq_data *data)
{
- int was_pending = 0;
+ int was_pending = 0, irq = data->irq;
unsigned long flags;
- struct irq_cfg *cfg;
raw_spin_lock_irqsave(&ioapic_lock, flags);
if (irq < legacy_pic->nr_legacy_irqs) {
- legacy_pic->chip->mask(irq);
+ legacy_pic->mask(irq);
if (legacy_pic->irq_pending(irq))
was_pending = 1;
}
- cfg = irq_cfg(irq);
- __unmask_IO_APIC_irq(cfg);
+ __unmask_ioapic(data->chip_data);
raw_spin_unlock_irqrestore(&ioapic_lock, flags);
return was_pending;
}
-static int ioapic_retrigger_irq(unsigned int irq)
+static int ioapic_retrigger_irq(struct irq_data *data)
{
-
- struct irq_cfg *cfg = irq_cfg(irq);
+ struct irq_cfg *cfg = data->chip_data;
unsigned long flags;
raw_spin_lock_irqsave(&vector_lock, flags);
@@ -2307,7 +2182,7 @@ static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, struct irq
* With interrupt-remapping, destination information comes
* from interrupt-remapping table entry.
*/
- if (!irq_remapped(irq))
+ if (!irq_remapped(cfg))
io_apic_write(apic, 0x11 + pin*2, dest);
reg = io_apic_read(apic, 0x10 + pin*2);
reg &= ~IO_APIC_REDIR_VECTOR_MASK;
@@ -2317,65 +2192,46 @@ static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, struct irq
}
/*
- * Either sets desc->affinity to a valid value, and returns
+ * Either sets data->affinity to a valid value, and returns
* ->cpu_mask_to_apicid of that in dest_id, or returns -1 and
- * leaves desc->affinity untouched.
+ * leaves data->affinity untouched.
*/
-unsigned int
-set_desc_affinity(struct irq_desc *desc, const struct cpumask *mask,
- unsigned int *dest_id)
+int __ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
+ unsigned int *dest_id)
{
- struct irq_cfg *cfg;
- unsigned int irq;
+ struct irq_cfg *cfg = data->chip_data;
if (!cpumask_intersects(mask, cpu_online_mask))
return -1;
- irq = desc->irq;
- cfg = desc->chip_data;
- if (assign_irq_vector(irq, cfg, mask))
+ if (assign_irq_vector(data->irq, data->chip_data, mask))
return -1;
- cpumask_copy(desc->affinity, mask);
+ cpumask_copy(data->affinity, mask);
- *dest_id = apic->cpu_mask_to_apicid_and(desc->affinity, cfg->domain);
+ *dest_id = apic->cpu_mask_to_apicid_and(mask, cfg->domain);
return 0;
}
static int
-set_ioapic_affinity_irq_desc(struct irq_desc *desc, const struct cpumask *mask)
+ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
+ bool force)
{
- struct irq_cfg *cfg;
+ unsigned int dest, irq = data->irq;
unsigned long flags;
- unsigned int dest;
- unsigned int irq;
- int ret = -1;
-
- irq = desc->irq;
- cfg = desc->chip_data;
+ int ret;
raw_spin_lock_irqsave(&ioapic_lock, flags);
- ret = set_desc_affinity(desc, mask, &dest);
+ ret = __ioapic_set_affinity(data, mask, &dest);
if (!ret) {
/* Only the high 8 bits are valid. */
dest = SET_APIC_LOGICAL_ID(dest);
- __target_IO_APIC_irq(irq, dest, cfg);
+ __target_IO_APIC_irq(irq, dest, data->chip_data);
}
raw_spin_unlock_irqrestore(&ioapic_lock, flags);
-
return ret;
}
-static int
-set_ioapic_affinity_irq(unsigned int irq, const struct cpumask *mask)
-{
- struct irq_desc *desc;
-
- desc = irq_to_desc(irq);
-
- return set_ioapic_affinity_irq_desc(desc, mask);
-}
-
#ifdef CONFIG_INTR_REMAP
/*
@@ -2390,24 +2246,21 @@ set_ioapic_affinity_irq(unsigned int irq, const struct cpumask *mask)
* the interrupt-remapping table entry.
*/
static int
-migrate_ioapic_irq_desc(struct irq_desc *desc, const struct cpumask *mask)
+ir_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
+ bool force)
{
- struct irq_cfg *cfg;
+ struct irq_cfg *cfg = data->chip_data;
+ unsigned int dest, irq = data->irq;
struct irte irte;
- unsigned int dest;
- unsigned int irq;
- int ret = -1;
if (!cpumask_intersects(mask, cpu_online_mask))
- return ret;
+ return -EINVAL;
- irq = desc->irq;
if (get_irte(irq, &irte))
- return ret;
+ return -EBUSY;
- cfg = desc->chip_data;
if (assign_irq_vector(irq, cfg, mask))
- return ret;
+ return -EBUSY;
dest = apic->cpu_mask_to_apicid_and(cfg->domain, mask);
@@ -2422,29 +2275,14 @@ migrate_ioapic_irq_desc(struct irq_desc *desc, const struct cpumask *mask)
if (cfg->move_in_progress)
send_cleanup_vector(cfg);
- cpumask_copy(desc->affinity, mask);
-
+ cpumask_copy(data->affinity, mask);
return 0;
}
-/*
- * Migrates the IRQ destination in the process context.
- */
-static int set_ir_ioapic_affinity_irq_desc(struct irq_desc *desc,
- const struct cpumask *mask)
-{
- return migrate_ioapic_irq_desc(desc, mask);
-}
-static int set_ir_ioapic_affinity_irq(unsigned int irq,
- const struct cpumask *mask)
-{
- struct irq_desc *desc = irq_to_desc(irq);
-
- return set_ir_ioapic_affinity_irq_desc(desc, mask);
-}
#else
-static inline int set_ir_ioapic_affinity_irq_desc(struct irq_desc *desc,
- const struct cpumask *mask)
+static inline int
+ir_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
+ bool force)
{
return 0;
}
@@ -2506,10 +2344,8 @@ unlock:
irq_exit();
}
-static void __irq_complete_move(struct irq_desc **descp, unsigned vector)
+static void __irq_complete_move(struct irq_cfg *cfg, unsigned vector)
{
- struct irq_desc *desc = *descp;
- struct irq_cfg *cfg = desc->chip_data;
unsigned me;
if (likely(!cfg->move_in_progress))
@@ -2521,31 +2357,28 @@ static void __irq_complete_move(struct irq_desc **descp, unsigned vector)
send_cleanup_vector(cfg);
}
-static void irq_complete_move(struct irq_desc **descp)
+static void irq_complete_move(struct irq_cfg *cfg)
{
- __irq_complete_move(descp, ~get_irq_regs()->orig_ax);
+ __irq_complete_move(cfg, ~get_irq_regs()->orig_ax);
}
void irq_force_complete_move(int irq)
{
- struct irq_desc *desc = irq_to_desc(irq);
- struct irq_cfg *cfg = desc->chip_data;
+ struct irq_cfg *cfg = get_irq_chip_data(irq);
if (!cfg)
return;
- __irq_complete_move(&desc, cfg->vector);
+ __irq_complete_move(cfg, cfg->vector);
}
#else
-static inline void irq_complete_move(struct irq_desc **descp) {}
+static inline void irq_complete_move(struct irq_cfg *cfg) { }
#endif
-static void ack_apic_edge(unsigned int irq)
+static void ack_apic_edge(struct irq_data *data)
{
- struct irq_desc *desc = irq_to_desc(irq);
-
- irq_complete_move(&desc);
- move_native_irq(irq);
+ irq_complete_move(data->chip_data);
+ move_native_irq(data->irq);
ack_APIC_irq();
}
@@ -2567,10 +2400,12 @@ atomic_t irq_mis_count;
* Otherwise, we simulate the EOI message manually by changing the trigger
* mode to edge and then back to level, with RTE being masked during this.
*/
-static void __eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg)
+static void eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg)
{
struct irq_pin_list *entry;
+ unsigned long flags;
+ raw_spin_lock_irqsave(&ioapic_lock, flags);
for_each_irq_pin(entry, cfg->irq_2_pin) {
if (mp_ioapics[entry->apic].apicver >= 0x20) {
/*
@@ -2579,7 +2414,7 @@ static void __eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg)
* intr-remapping table entry. Hence for the io-apic
* EOI we use the pin number.
*/
- if (irq_remapped(irq))
+ if (irq_remapped(cfg))
io_apic_eoi(entry->apic, entry->pin);
else
io_apic_eoi(entry->apic, cfg->vector);
@@ -2588,36 +2423,22 @@ static void __eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg)
__unmask_and_level_IO_APIC_irq(entry);
}
}
-}
-
-static void eoi_ioapic_irq(struct irq_desc *desc)
-{
- struct irq_cfg *cfg;
- unsigned long flags;
- unsigned int irq;
-
- irq = desc->irq;
- cfg = desc->chip_data;
-
- raw_spin_lock_irqsave(&ioapic_lock, flags);
- __eoi_ioapic_irq(irq, cfg);
raw_spin_unlock_irqrestore(&ioapic_lock, flags);
}
-static void ack_apic_level(unsigned int irq)
+static void ack_apic_level(struct irq_data *data)
{
+ struct irq_cfg *cfg = data->chip_data;
+ int i, do_unmask_irq = 0, irq = data->irq;
struct irq_desc *desc = irq_to_desc(irq);
unsigned long v;
- int i;
- struct irq_cfg *cfg;
- int do_unmask_irq = 0;
- irq_complete_move(&desc);
+ irq_complete_move(cfg);
#ifdef CONFIG_GENERIC_PENDING_IRQ
/* If we are moving the irq we need to mask it */
if (unlikely(desc->status & IRQ_MOVE_PENDING)) {
do_unmask_irq = 1;
- mask_IO_APIC_irq_desc(desc);
+ mask_ioapic(cfg);
}
#endif
@@ -2653,7 +2474,6 @@ static void ack_apic_level(unsigned int irq)
* we use the above logic (mask+edge followed by unmask+level) from
* Manfred Spraul to clear the remote IRR.
*/
- cfg = desc->chip_data;
i = cfg->vector;
v = apic_read(APIC_TMR + ((i & ~0x1f) >> 1));
@@ -2673,7 +2493,7 @@ static void ack_apic_level(unsigned int irq)
if (!(v & (1 << (i & 0x1f)))) {
atomic_inc(&irq_mis_count);
- eoi_ioapic_irq(desc);
+ eoi_ioapic_irq(irq, cfg);
}
/* Now we can move and renable the irq */
@@ -2704,61 +2524,57 @@ static void ack_apic_level(unsigned int irq)
* accurate and is causing problems then it is a hardware bug
* and you can go talk to the chipset vendor about it.
*/
- cfg = desc->chip_data;
if (!io_apic_level_ack_pending(cfg))
move_masked_irq(irq);
- unmask_IO_APIC_irq_desc(desc);
+ unmask_ioapic(cfg);
}
}
#ifdef CONFIG_INTR_REMAP
-static void ir_ack_apic_edge(unsigned int irq)
+static void ir_ack_apic_edge(struct irq_data *data)
{
ack_APIC_irq();
}
-static void ir_ack_apic_level(unsigned int irq)
+static void ir_ack_apic_level(struct irq_data *data)
{
- struct irq_desc *desc = irq_to_desc(irq);
-
ack_APIC_irq();
- eoi_ioapic_irq(desc);
+ eoi_ioapic_irq(data->irq, data->chip_data);
}
#endif /* CONFIG_INTR_REMAP */
static struct irq_chip ioapic_chip __read_mostly = {
- .name = "IO-APIC",
- .startup = startup_ioapic_irq,
- .mask = mask_IO_APIC_irq,
- .unmask = unmask_IO_APIC_irq,
- .ack = ack_apic_edge,
- .eoi = ack_apic_level,
+ .name = "IO-APIC",
+ .irq_startup = startup_ioapic_irq,
+ .irq_mask = mask_ioapic_irq,
+ .irq_unmask = unmask_ioapic_irq,
+ .irq_ack = ack_apic_edge,
+ .irq_eoi = ack_apic_level,
#ifdef CONFIG_SMP
- .set_affinity = set_ioapic_affinity_irq,
+ .irq_set_affinity = ioapic_set_affinity,
#endif
- .retrigger = ioapic_retrigger_irq,
+ .irq_retrigger = ioapic_retrigger_irq,
};
static struct irq_chip ir_ioapic_chip __read_mostly = {
- .name = "IR-IO-APIC",
- .startup = startup_ioapic_irq,
- .mask = mask_IO_APIC_irq,
- .unmask = unmask_IO_APIC_irq,
+ .name = "IR-IO-APIC",
+ .irq_startup = startup_ioapic_irq,
+ .irq_mask = mask_ioapic_irq,
+ .irq_unmask = unmask_ioapic_irq,
#ifdef CONFIG_INTR_REMAP
- .ack = ir_ack_apic_edge,
- .eoi = ir_ack_apic_level,
+ .irq_ack = ir_ack_apic_edge,
+ .irq_eoi = ir_ack_apic_level,
#ifdef CONFIG_SMP
- .set_affinity = set_ir_ioapic_affinity_irq,
+ .irq_set_affinity = ir_ioapic_set_affinity,
#endif
#endif
- .retrigger = ioapic_retrigger_irq,
+ .irq_retrigger = ioapic_retrigger_irq,
};
static inline void init_IO_APIC_traps(void)
{
- int irq;
- struct irq_desc *desc;
struct irq_cfg *cfg;
+ unsigned int irq;
/*
* NOTE! The local APIC isn't very good at handling
@@ -2771,8 +2587,8 @@ static inline void init_IO_APIC_traps(void)
* Also, we've got to be careful not to trash gate
* 0x80, because int 0x80 is hm, kind of importantish. ;)
*/
- for_each_irq_desc(irq, desc) {
- cfg = desc->chip_data;
+ for_each_active_irq(irq) {
+ cfg = get_irq_chip_data(irq);
if (IO_APIC_IRQ(irq) && cfg && !cfg->vector) {
/*
* Hmm.. We don't have an entry for this,
@@ -2783,7 +2599,7 @@ static inline void init_IO_APIC_traps(void)
legacy_pic->make_irq(irq);
else
/* Strange. Oh, well.. */
- desc->chip = &no_irq_chip;
+ set_irq_chip(irq, &no_irq_chip);
}
}
}
@@ -2792,7 +2608,7 @@ static inline void init_IO_APIC_traps(void)
* The local APIC irq-chip implementation:
*/
-static void mask_lapic_irq(unsigned int irq)
+static void mask_lapic_irq(struct irq_data *data)
{
unsigned long v;
@@ -2800,7 +2616,7 @@ static void mask_lapic_irq(unsigned int irq)
apic_write(APIC_LVT0, v | APIC_LVT_MASKED);
}
-static void unmask_lapic_irq(unsigned int irq)
+static void unmask_lapic_irq(struct irq_data *data)
{
unsigned long v;
@@ -2808,21 +2624,21 @@ static void unmask_lapic_irq(unsigned int irq)
apic_write(APIC_LVT0, v & ~APIC_LVT_MASKED);
}
-static void ack_lapic_irq(unsigned int irq)
+static void ack_lapic_irq(struct irq_data *data)
{
ack_APIC_irq();
}
static struct irq_chip lapic_chip __read_mostly = {
.name = "local-APIC",
- .mask = mask_lapic_irq,
- .unmask = unmask_lapic_irq,
- .ack = ack_lapic_irq,
+ .irq_mask = mask_lapic_irq,
+ .irq_unmask = unmask_lapic_irq,
+ .irq_ack = ack_lapic_irq,
};
-static void lapic_register_intr(int irq, struct irq_desc *desc)
+static void lapic_register_intr(int irq)
{
- desc->status &= ~IRQ_LEVEL;
+ irq_clear_status_flags(irq, IRQ_LEVEL);
set_irq_chip_and_handler_name(irq, &lapic_chip, handle_edge_irq,
"edge");
}
@@ -2925,9 +2741,8 @@ int timer_through_8259 __initdata;
*/
static inline void __init check_timer(void)
{
- struct irq_desc *desc = irq_to_desc(0);
- struct irq_cfg *cfg = desc->chip_data;
- int node = cpu_to_node(boot_cpu_id);
+ struct irq_cfg *cfg = get_irq_chip_data(0);
+ int node = cpu_to_node(0);
int apic1, pin1, apic2, pin2;
unsigned long flags;
int no_pin1 = 0;
@@ -2937,7 +2752,7 @@ static inline void __init check_timer(void)
/*
* get/set the timer IRQ vector:
*/
- legacy_pic->chip->mask(0);
+ legacy_pic->mask(0);
assign_irq_vector(0, cfg, apic->target_cpus());
/*
@@ -2996,7 +2811,7 @@ static inline void __init check_timer(void)
add_pin_to_irq_node(cfg, node, apic1, pin1);
setup_timer_IRQ0_pin(apic1, pin1, cfg->vector);
} else {
- /* for edge trigger, setup_IO_APIC_irq already
+ /* for edge trigger, setup_ioapic_irq already
* leave it unmasked.
* so only need to unmask if it is level-trigger
* do we really have level trigger timer?
@@ -3004,12 +2819,12 @@ static inline void __init check_timer(void)
int idx;
idx = find_irq_entry(apic1, pin1, mp_INT);
if (idx != -1 && irq_trigger(idx))
- unmask_IO_APIC_irq_desc(desc);
+ unmask_ioapic(cfg);
}
if (timer_irq_works()) {
if (nmi_watchdog == NMI_IO_APIC) {
setup_nmi();
- legacy_pic->chip->unmask(0);
+ legacy_pic->unmask(0);
}
if (disable_timer_pin_1 > 0)
clear_IO_APIC_pin(0, pin1);
@@ -3032,14 +2847,14 @@ static inline void __init check_timer(void)
*/
replace_pin_at_irq_node(cfg, node, apic1, pin1, apic2, pin2);
setup_timer_IRQ0_pin(apic2, pin2, cfg->vector);
- legacy_pic->chip->unmask(0);
+ legacy_pic->unmask(0);
if (timer_irq_works()) {
apic_printk(APIC_QUIET, KERN_INFO "....... works.\n");
timer_through_8259 = 1;
if (nmi_watchdog == NMI_IO_APIC) {
- legacy_pic->chip->mask(0);
+ legacy_pic->mask(0);
setup_nmi();
- legacy_pic->chip->unmask(0);
+ legacy_pic->unmask(0);
}
goto out;
}
@@ -3047,7 +2862,7 @@ static inline void __init check_timer(void)
* Cleanup, just in case ...
*/
local_irq_disable();
- legacy_pic->chip->mask(0);
+ legacy_pic->mask(0);
clear_IO_APIC_pin(apic2, pin2);
apic_printk(APIC_QUIET, KERN_INFO "....... failed.\n");
}
@@ -3064,16 +2879,16 @@ static inline void __init check_timer(void)
apic_printk(APIC_QUIET, KERN_INFO
"...trying to set up timer as Virtual Wire IRQ...\n");
- lapic_register_intr(0, desc);
+ lapic_register_intr(0);
apic_write(APIC_LVT0, APIC_DM_FIXED | cfg->vector); /* Fixed mode */
- legacy_pic->chip->unmask(0);
+ legacy_pic->unmask(0);
if (timer_irq_works()) {
apic_printk(APIC_QUIET, KERN_INFO "..... works.\n");
goto out;
}
local_irq_disable();
- legacy_pic->chip->mask(0);
+ legacy_pic->mask(0);
apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | cfg->vector);
apic_printk(APIC_QUIET, KERN_INFO "..... failed.\n");
@@ -3239,49 +3054,42 @@ device_initcall(ioapic_init_sysfs);
/*
* Dynamic irq allocate and deallocation
*/
-unsigned int create_irq_nr(unsigned int irq_want, int node)
+unsigned int create_irq_nr(unsigned int from, int node)
{
- /* Allocate an unused irq */
- unsigned int irq;
- unsigned int new;
+ struct irq_cfg *cfg;
unsigned long flags;
- struct irq_cfg *cfg_new = NULL;
- struct irq_desc *desc_new = NULL;
-
- irq = 0;
- if (irq_want < nr_irqs_gsi)
- irq_want = nr_irqs_gsi;
-
- raw_spin_lock_irqsave(&vector_lock, flags);
- for (new = irq_want; new < nr_irqs; new++) {
- desc_new = irq_to_desc_alloc_node(new, node);
- if (!desc_new) {
- printk(KERN_INFO "can not get irq_desc for %d\n", new);
- continue;
- }
- cfg_new = desc_new->chip_data;
-
- if (cfg_new->vector != 0)
- continue;
+ unsigned int ret = 0;
+ int irq;
- desc_new = move_irq_desc(desc_new, node);
- cfg_new = desc_new->chip_data;
+ if (from < nr_irqs_gsi)
+ from = nr_irqs_gsi;
- if (__assign_irq_vector(new, cfg_new, apic->target_cpus()) == 0)
- irq = new;
- break;
+ irq = alloc_irq_from(from, node);
+ if (irq < 0)
+ return 0;
+ cfg = alloc_irq_cfg(irq, node);
+ if (!cfg) {
+ free_irq_at(irq, NULL);
+ return 0;
}
- raw_spin_unlock_irqrestore(&vector_lock, flags);
- if (irq > 0)
- dynamic_irq_init_keep_chip_data(irq);
+ raw_spin_lock_irqsave(&vector_lock, flags);
+ if (!__assign_irq_vector(irq, cfg, apic->target_cpus()))
+ ret = irq;
+ raw_spin_unlock_irqrestore(&vector_lock, flags);
- return irq;
+ if (ret) {
+ set_irq_chip_data(irq, cfg);
+ irq_clear_status_flags(irq, IRQ_NOREQUEST);
+ } else {
+ free_irq_at(irq, cfg);
+ }
+ return ret;
}
int create_irq(void)
{
- int node = cpu_to_node(boot_cpu_id);
+ int node = cpu_to_node(0);
unsigned int irq_want;
int irq;
@@ -3296,14 +3104,17 @@ int create_irq(void)
void destroy_irq(unsigned int irq)
{
+ struct irq_cfg *cfg = get_irq_chip_data(irq);
unsigned long flags;
- dynamic_irq_cleanup_keep_chip_data(irq);
+ irq_set_status_flags(irq, IRQ_NOREQUEST|IRQ_NOPROBE);
- free_irte(irq);
+ if (intr_remapping_enabled)
+ free_irte(irq);
raw_spin_lock_irqsave(&vector_lock, flags);
- __clear_irq_vector(irq, get_irq_chip_data(irq));
+ __clear_irq_vector(irq, cfg);
raw_spin_unlock_irqrestore(&vector_lock, flags);
+ free_irq_at(irq, cfg);
}
/*
@@ -3327,7 +3138,7 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq,
dest = apic->cpu_mask_to_apicid_and(cfg->domain, apic->target_cpus());
- if (irq_remapped(irq)) {
+ if (irq_remapped(get_irq_chip_data(irq))) {
struct irte irte;
int ir_index;
u16 sub_handle;
@@ -3335,14 +3146,7 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq,
ir_index = map_irq_to_irte_handle(irq, &sub_handle);
BUG_ON(ir_index == -1);
- memset (&irte, 0, sizeof(irte));
-
- irte.present = 1;
- irte.dst_mode = apic->irq_dest_mode;
- irte.trigger_mode = 0; /* edge */
- irte.dlvry_mode = apic->irq_delivery_mode;
- irte.vector = cfg->vector;
- irte.dest_id = IRTE_DEST(dest);
+ prepare_irte(&irte, cfg->vector, dest);
/* Set source-id of interrupt request */
if (pdev)
@@ -3387,26 +3191,24 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq,
}
#ifdef CONFIG_SMP
-static int set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask)
+static int
+msi_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force)
{
- struct irq_desc *desc = irq_to_desc(irq);
- struct irq_cfg *cfg;
+ struct irq_cfg *cfg = data->chip_data;
struct msi_msg msg;
unsigned int dest;
- if (set_desc_affinity(desc, mask, &dest))
+ if (__ioapic_set_affinity(data, mask, &dest))
return -1;
- cfg = desc->chip_data;
-
- get_cached_msi_msg_desc(desc, &msg);
+ __get_cached_msi_msg(data->msi_desc, &msg);
msg.data &= ~MSI_DATA_VECTOR_MASK;
msg.data |= MSI_DATA_VECTOR(cfg->vector);
msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
msg.address_lo |= MSI_ADDR_DEST_ID(dest);
- write_msi_msg_desc(desc, &msg);
+ __write_msi_msg(data->msi_desc, &msg);
return 0;
}
@@ -3416,17 +3218,17 @@ static int set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask)
* done in the process context using interrupt-remapping hardware.
*/
static int
-ir_set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask)
+ir_msi_set_affinity(struct irq_data *data, const struct cpumask *mask,
+ bool force)
{
- struct irq_desc *desc = irq_to_desc(irq);
- struct irq_cfg *cfg = desc->chip_data;
- unsigned int dest;
+ struct irq_cfg *cfg = data->chip_data;
+ unsigned int dest, irq = data->irq;
struct irte irte;
if (get_irte(irq, &irte))
return -1;
- if (set_desc_affinity(desc, mask, &dest))
+ if (__ioapic_set_affinity(data, mask, &dest))
return -1;
irte.vector = cfg->vector;
@@ -3456,27 +3258,27 @@ ir_set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask)
* which implement the MSI or MSI-X Capability Structure.
*/
static struct irq_chip msi_chip = {
- .name = "PCI-MSI",
- .unmask = unmask_msi_irq,
- .mask = mask_msi_irq,
- .ack = ack_apic_edge,
+ .name = "PCI-MSI",
+ .irq_unmask = unmask_msi_irq,
+ .irq_mask = mask_msi_irq,
+ .irq_ack = ack_apic_edge,
#ifdef CONFIG_SMP
- .set_affinity = set_msi_irq_affinity,
+ .irq_set_affinity = msi_set_affinity,
#endif
- .retrigger = ioapic_retrigger_irq,
+ .irq_retrigger = ioapic_retrigger_irq,
};
static struct irq_chip msi_ir_chip = {
- .name = "IR-PCI-MSI",
- .unmask = unmask_msi_irq,
- .mask = mask_msi_irq,
+ .name = "IR-PCI-MSI",
+ .irq_unmask = unmask_msi_irq,
+ .irq_mask = mask_msi_irq,
#ifdef CONFIG_INTR_REMAP
- .ack = ir_ack_apic_edge,
+ .irq_ack = ir_ack_apic_edge,
#ifdef CONFIG_SMP
- .set_affinity = ir_set_msi_irq_affinity,
+ .irq_set_affinity = ir_msi_set_affinity,
#endif
#endif
- .retrigger = ioapic_retrigger_irq,
+ .irq_retrigger = ioapic_retrigger_irq,
};
/*
@@ -3508,8 +3310,8 @@ static int msi_alloc_irte(struct pci_dev *dev, int irq, int nvec)
static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int irq)
{
- int ret;
struct msi_msg msg;
+ int ret;
ret = msi_compose_msg(dev, irq, &msg, -1);
if (ret < 0)
@@ -3518,12 +3320,8 @@ static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int irq)
set_irq_msi(irq, msidesc);
write_msi_msg(irq, &msg);
- if (irq_remapped(irq)) {
- struct irq_desc *desc = irq_to_desc(irq);
- /*
- * irq migration in process context
- */
- desc->status |= IRQ_MOVE_PCNTXT;
+ if (irq_remapped(get_irq_chip_data(irq))) {
+ irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
set_irq_chip_and_handler_name(irq, &msi_ir_chip, handle_edge_irq, "edge");
} else
set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq, "edge");
@@ -3535,13 +3333,10 @@ static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int irq)
int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
{
- unsigned int irq;
- int ret, sub_handle;
+ int node, ret, sub_handle, index = 0;
+ unsigned int irq, irq_want;
struct msi_desc *msidesc;
- unsigned int irq_want;
struct intel_iommu *iommu = NULL;
- int index = 0;
- int node;
/* x86 doesn't support multiple MSI yet */
if (type == PCI_CAP_ID_MSI && nvec > 1)
@@ -3601,18 +3396,17 @@ void arch_teardown_msi_irq(unsigned int irq)
#if defined (CONFIG_DMAR) || defined (CONFIG_INTR_REMAP)
#ifdef CONFIG_SMP
-static int dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
+static int
+dmar_msi_set_affinity(struct irq_data *data, const struct cpumask *mask,
+ bool force)
{
- struct irq_desc *desc = irq_to_desc(irq);
- struct irq_cfg *cfg;
+ struct irq_cfg *cfg = data->chip_data;
+ unsigned int dest, irq = data->irq;
struct msi_msg msg;
- unsigned int dest;
- if (set_desc_affinity(desc, mask, &dest))
+ if (__ioapic_set_affinity(data, mask, &dest))
return -1;
- cfg = desc->chip_data;
-
dmar_msi_read(irq, &msg);
msg.data &= ~MSI_DATA_VECTOR_MASK;
@@ -3628,14 +3422,14 @@ static int dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
#endif /* CONFIG_SMP */
static struct irq_chip dmar_msi_type = {
- .name = "DMAR_MSI",
- .unmask = dmar_msi_unmask,
- .mask = dmar_msi_mask,
- .ack = ack_apic_edge,
+ .name = "DMAR_MSI",
+ .irq_unmask = dmar_msi_unmask,
+ .irq_mask = dmar_msi_mask,
+ .irq_ack = ack_apic_edge,
#ifdef CONFIG_SMP
- .set_affinity = dmar_msi_set_affinity,
+ .irq_set_affinity = dmar_msi_set_affinity,
#endif
- .retrigger = ioapic_retrigger_irq,
+ .irq_retrigger = ioapic_retrigger_irq,
};
int arch_setup_dmar_msi(unsigned int irq)
@@ -3656,26 +3450,24 @@ int arch_setup_dmar_msi(unsigned int irq)
#ifdef CONFIG_HPET_TIMER
#ifdef CONFIG_SMP
-static int hpet_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
+static int hpet_msi_set_affinity(struct irq_data *data,
+ const struct cpumask *mask, bool force)
{
- struct irq_desc *desc = irq_to_desc(irq);
- struct irq_cfg *cfg;
+ struct irq_cfg *cfg = data->chip_data;
struct msi_msg msg;
unsigned int dest;
- if (set_desc_affinity(desc, mask, &dest))
+ if (__ioapic_set_affinity(data, mask, &dest))
return -1;
- cfg = desc->chip_data;
-
- hpet_msi_read(irq, &msg);
+ hpet_msi_read(data->handler_data, &msg);
msg.data &= ~MSI_DATA_VECTOR_MASK;
msg.data |= MSI_DATA_VECTOR(cfg->vector);
msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
msg.address_lo |= MSI_ADDR_DEST_ID(dest);
- hpet_msi_write(irq, &msg);
+ hpet_msi_write(data->handler_data, &msg);
return 0;
}
@@ -3683,34 +3475,33 @@ static int hpet_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
#endif /* CONFIG_SMP */
static struct irq_chip ir_hpet_msi_type = {
- .name = "IR-HPET_MSI",
- .unmask = hpet_msi_unmask,
- .mask = hpet_msi_mask,
+ .name = "IR-HPET_MSI",
+ .irq_unmask = hpet_msi_unmask,
+ .irq_mask = hpet_msi_mask,
#ifdef CONFIG_INTR_REMAP
- .ack = ir_ack_apic_edge,
+ .irq_ack = ir_ack_apic_edge,
#ifdef CONFIG_SMP
- .set_affinity = ir_set_msi_irq_affinity,
+ .irq_set_affinity = ir_msi_set_affinity,
#endif
#endif
- .retrigger = ioapic_retrigger_irq,
+ .irq_retrigger = ioapic_retrigger_irq,
};
static struct irq_chip hpet_msi_type = {
.name = "HPET_MSI",
- .unmask = hpet_msi_unmask,
- .mask = hpet_msi_mask,
- .ack = ack_apic_edge,
+ .irq_unmask = hpet_msi_unmask,
+ .irq_mask = hpet_msi_mask,
+ .irq_ack = ack_apic_edge,
#ifdef CONFIG_SMP
- .set_affinity = hpet_msi_set_affinity,
+ .irq_set_affinity = hpet_msi_set_affinity,
#endif
- .retrigger = ioapic_retrigger_irq,
+ .irq_retrigger = ioapic_retrigger_irq,
};
int arch_setup_hpet_msi(unsigned int irq, unsigned int id)
{
- int ret;
struct msi_msg msg;
- struct irq_desc *desc = irq_to_desc(irq);
+ int ret;
if (intr_remapping_enabled) {
struct intel_iommu *iommu = map_hpet_to_ir(id);
@@ -3728,9 +3519,9 @@ int arch_setup_hpet_msi(unsigned int irq, unsigned int id)
if (ret < 0)
return ret;
- hpet_msi_write(irq, &msg);
- desc->status |= IRQ_MOVE_PCNTXT;
- if (irq_remapped(irq))
+ hpet_msi_write(get_irq_data(irq), &msg);
+ irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
+ if (irq_remapped(get_irq_chip_data(irq)))
set_irq_chip_and_handler_name(irq, &ir_hpet_msi_type,
handle_edge_irq, "edge");
else
@@ -3763,33 +3554,30 @@ static void target_ht_irq(unsigned int irq, unsigned int dest, u8 vector)
write_ht_irq_msg(irq, &msg);
}
-static int set_ht_irq_affinity(unsigned int irq, const struct cpumask *mask)
+static int
+ht_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force)
{
- struct irq_desc *desc = irq_to_desc(irq);
- struct irq_cfg *cfg;
+ struct irq_cfg *cfg = data->chip_data;
unsigned int dest;
- if (set_desc_affinity(desc, mask, &dest))
+ if (__ioapic_set_affinity(data, mask, &dest))
return -1;
- cfg = desc->chip_data;
-
- target_ht_irq(irq, dest, cfg->vector);
-
+ target_ht_irq(data->irq, dest, cfg->vector);
return 0;
}
#endif
static struct irq_chip ht_irq_chip = {
- .name = "PCI-HT",
- .mask = mask_ht_irq,
- .unmask = unmask_ht_irq,
- .ack = ack_apic_edge,
+ .name = "PCI-HT",
+ .irq_mask = mask_ht_irq,
+ .irq_unmask = unmask_ht_irq,
+ .irq_ack = ack_apic_edge,
#ifdef CONFIG_SMP
- .set_affinity = set_ht_irq_affinity,
+ .irq_set_affinity = ht_set_affinity,
#endif
- .retrigger = ioapic_retrigger_irq,
+ .irq_retrigger = ioapic_retrigger_irq,
};
int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
@@ -3880,14 +3668,13 @@ int __init arch_probe_nr_irqs(void)
if (nr < nr_irqs)
nr_irqs = nr;
- return 0;
+ return NR_IRQS_LEGACY;
}
#endif
static int __io_apic_set_pci_routing(struct device *dev, int irq,
struct io_apic_irq_attr *irq_attr)
{
- struct irq_desc *desc;
struct irq_cfg *cfg;
int node;
int ioapic, pin;
@@ -3903,13 +3690,11 @@ static int __io_apic_set_pci_routing(struct device *dev, int irq,
if (dev)
node = dev_to_node(dev);
else
- node = cpu_to_node(boot_cpu_id);
+ node = cpu_to_node(0);
- desc = irq_to_desc_alloc_node(irq, node);
- if (!desc) {
- printk(KERN_INFO "can not get irq_desc %d\n", irq);
+ cfg = alloc_irq_and_cfg_at(irq, node);
+ if (!cfg)
return 0;
- }
pin = irq_attr->ioapic_pin;
trigger = irq_attr->trigger;
@@ -3919,15 +3704,14 @@ static int __io_apic_set_pci_routing(struct device *dev, int irq,
* IRQs < 16 are already in the irq_2_pin[] map
*/
if (irq >= legacy_pic->nr_legacy_irqs) {
- cfg = desc->chip_data;
- if (add_pin_to_irq_node_nopanic(cfg, node, ioapic, pin)) {
+ if (__add_pin_to_irq_node(cfg, node, ioapic, pin)) {
printk(KERN_INFO "can not add pin %d for irq %d\n",
pin, irq);
return 0;
}
}
- setup_IO_APIC_irq(ioapic, pin, irq, desc, trigger, polarity);
+ setup_ioapic_irq(ioapic, pin, irq, cfg, trigger, polarity);
return 0;
}
@@ -4120,14 +3904,14 @@ void __init setup_ioapic_dest(void)
*/
if (desc->status &
(IRQ_NO_BALANCING | IRQ_AFFINITY_SET))
- mask = desc->affinity;
+ mask = desc->irq_data.affinity;
else
mask = apic->target_cpus();
if (intr_remapping_enabled)
- set_ir_ioapic_affinity_irq_desc(desc, mask);
+ ir_ioapic_set_affinity(&desc->irq_data, mask, false);
else
- set_ioapic_affinity_irq_desc(desc, mask);
+ ioapic_set_affinity(&desc->irq_data, mask, false);
}
}
@@ -4311,19 +4095,18 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
void __init pre_init_apic_IRQ0(void)
{
struct irq_cfg *cfg;
- struct irq_desc *desc;
printk(KERN_INFO "Early APIC setup for system timer0\n");
#ifndef CONFIG_SMP
phys_cpu_present_map = physid_mask_of_physid(boot_cpu_physical_apicid);
#endif
- desc = irq_to_desc_alloc_node(0, 0);
+ /* Make sure the irq descriptor is set up */
+ cfg = alloc_irq_and_cfg_at(0, 0);
setup_local_APIC();
- cfg = irq_cfg(0);
add_pin_to_irq_node(cfg, 0, 0, 0);
set_irq_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq, "edge");
- setup_IO_APIC_irq(0, 0, 0, desc, 0, 0);
+ setup_ioapic_irq(0, 0, 0, cfg, 0, 0);
}
diff --git a/arch/x86/kernel/apic/nmi.c b/arch/x86/kernel/apic/nmi.c
index a43f71cb30f8..c90041ccb742 100644
--- a/arch/x86/kernel/apic/nmi.c
+++ b/arch/x86/kernel/apic/nmi.c
@@ -178,7 +178,7 @@ int __init check_nmi_watchdog(void)
error:
if (nmi_watchdog == NMI_IO_APIC) {
if (!timer_through_8259)
- legacy_pic->chip->mask(0);
+ legacy_pic->mask(0);
on_each_cpu(__acpi_nmi_disable, NULL, 1);
}
diff --git a/arch/x86/kernel/apic/numaq_32.c b/arch/x86/kernel/apic/numaq_32.c
index 3e28401f161c..960f26ab5c9f 100644
--- a/arch/x86/kernel/apic/numaq_32.c
+++ b/arch/x86/kernel/apic/numaq_32.c
@@ -26,6 +26,7 @@
#include <linux/nodemask.h>
#include <linux/topology.h>
#include <linux/bootmem.h>
+#include <linux/memblock.h>
#include <linux/threads.h>
#include <linux/cpumask.h>
#include <linux/kernel.h>
@@ -88,7 +89,7 @@ static inline void numaq_register_node(int node, struct sys_cfg_data *scd)
node_end_pfn[node] =
MB_TO_PAGES(eq->hi_shrd_mem_start + eq->hi_shrd_mem_size);
- e820_register_active_regions(node, node_start_pfn[node],
+ memblock_x86_register_active_regions(node, node_start_pfn[node],
node_end_pfn[node]);
memory_present(node, node_start_pfn[node], node_end_pfn[node]);
diff --git a/arch/x86/kernel/apic/probe_64.c b/arch/x86/kernel/apic/probe_64.c
index 83e9be4778e2..f9e4e6a54073 100644
--- a/arch/x86/kernel/apic/probe_64.c
+++ b/arch/x86/kernel/apic/probe_64.c
@@ -54,6 +54,9 @@ static int apicid_phys_pkg_id(int initial_apic_id, int index_msb)
*/
void __init default_setup_apic_routing(void)
{
+
+ enable_IR_x2apic();
+
#ifdef CONFIG_X86_X2APIC
if (x2apic_mode
#ifdef CONFIG_X86_UV
diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c
index 4c9c67bf09b7..fbbc4dadecc4 100644
--- a/arch/x86/kernel/apm_32.c
+++ b/arch/x86/kernel/apm_32.c
@@ -1926,6 +1926,7 @@ static const struct file_operations apm_bios_fops = {
.unlocked_ioctl = do_ioctl,
.open = do_open,
.release = do_release,
+ .llseek = noop_llseek,
};
static struct miscdevice apm_device = {
diff --git a/arch/x86/kernel/asm-offsets_32.c b/arch/x86/kernel/asm-offsets_32.c
index dfdbf6403895..1a4088dda37a 100644
--- a/arch/x86/kernel/asm-offsets_32.c
+++ b/arch/x86/kernel/asm-offsets_32.c
@@ -99,9 +99,7 @@ void foo(void)
DEFINE(PAGE_SIZE_asm, PAGE_SIZE);
DEFINE(PAGE_SHIFT_asm, PAGE_SHIFT);
- DEFINE(PTRS_PER_PTE, PTRS_PER_PTE);
- DEFINE(PTRS_PER_PMD, PTRS_PER_PMD);
- DEFINE(PTRS_PER_PGD, PTRS_PER_PGD);
+ DEFINE(THREAD_SIZE_asm, THREAD_SIZE);
OFFSET(crypto_tfm_ctx_offset, crypto_tfm, __crt_ctx);
diff --git a/arch/x86/kernel/check.c b/arch/x86/kernel/check.c
index fc999e6fc46a..13a389179514 100644
--- a/arch/x86/kernel/check.c
+++ b/arch/x86/kernel/check.c
@@ -2,7 +2,8 @@
#include <linux/sched.h>
#include <linux/kthread.h>
#include <linux/workqueue.h>
-#include <asm/e820.h>
+#include <linux/memblock.h>
+
#include <asm/proto.h>
/*
@@ -18,10 +19,12 @@ static int __read_mostly memory_corruption_check = -1;
static unsigned __read_mostly corruption_check_size = 64*1024;
static unsigned __read_mostly corruption_check_period = 60; /* seconds */
-static struct e820entry scan_areas[MAX_SCAN_AREAS];
+static struct scan_area {
+ u64 addr;
+ u64 size;
+} scan_areas[MAX_SCAN_AREAS];
static int num_scan_areas;
-
static __init int set_corruption_check(char *arg)
{
char *end;
@@ -81,9 +84,9 @@ void __init setup_bios_corruption_check(void)
while (addr < corruption_check_size && num_scan_areas < MAX_SCAN_AREAS) {
u64 size;
- addr = find_e820_area_size(addr, &size, PAGE_SIZE);
+ addr = memblock_x86_find_in_range_size(addr, &size, PAGE_SIZE);
- if (!(addr + 1))
+ if (addr == MEMBLOCK_ERROR)
break;
if (addr >= corruption_check_size)
@@ -92,7 +95,7 @@ void __init setup_bios_corruption_check(void)
if ((addr + size) > corruption_check_size)
size = corruption_check_size - addr;
- e820_update_range(addr, size, E820_RAM, E820_RESERVED);
+ memblock_x86_reserve_range(addr, addr + size, "SCAN RAM");
scan_areas[num_scan_areas].addr = addr;
scan_areas[num_scan_areas].size = size;
num_scan_areas++;
@@ -105,7 +108,6 @@ void __init setup_bios_corruption_check(void)
printk(KERN_INFO "Scanning %d areas for low memory corruption\n",
num_scan_areas);
- update_e820();
}
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index ba5f62f45f01..9e093f8fe78c 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -148,7 +148,7 @@ static void __cpuinit amd_k7_smp_check(struct cpuinfo_x86 *c)
{
#ifdef CONFIG_SMP
/* calling is from identify_secondary_cpu() ? */
- if (c->cpu_index == boot_cpu_id)
+ if (!c->cpu_index)
return;
/*
@@ -253,37 +253,51 @@ static int __cpuinit nearby_node(int apicid)
#endif
/*
- * Fixup core topology information for AMD multi-node processors.
- * Assumption: Number of cores in each internal node is the same.
+ * Fixup core topology information for
+ * (1) AMD multi-node processors
+ * Assumption: Number of cores in each internal node is the same.
+ * (2) AMD processors supporting compute units
*/
#ifdef CONFIG_X86_HT
-static void __cpuinit amd_fixup_dcm(struct cpuinfo_x86 *c)
+static void __cpuinit amd_get_topology(struct cpuinfo_x86 *c)
{
- unsigned long long value;
- u32 nodes, cores_per_node;
+ u32 nodes;
+ u8 node_id;
int cpu = smp_processor_id();
- if (!cpu_has(c, X86_FEATURE_NODEID_MSR))
- return;
+ /* get information required for multi-node processors */
+ if (cpu_has(c, X86_FEATURE_TOPOEXT)) {
+ u32 eax, ebx, ecx, edx;
- /* fixup topology information only once for a core */
- if (cpu_has(c, X86_FEATURE_AMD_DCM))
- return;
+ cpuid(0x8000001e, &eax, &ebx, &ecx, &edx);
+ nodes = ((ecx >> 8) & 7) + 1;
+ node_id = ecx & 7;
- rdmsrl(MSR_FAM10H_NODE_ID, value);
+ /* get compute unit information */
+ smp_num_siblings = ((ebx >> 8) & 3) + 1;
+ c->compute_unit_id = ebx & 0xff;
+ } else if (cpu_has(c, X86_FEATURE_NODEID_MSR)) {
+ u64 value;
- nodes = ((value >> 3) & 7) + 1;
- if (nodes == 1)
+ rdmsrl(MSR_FAM10H_NODE_ID, value);
+ nodes = ((value >> 3) & 7) + 1;
+ node_id = value & 7;
+ } else
return;
- set_cpu_cap(c, X86_FEATURE_AMD_DCM);
- cores_per_node = c->x86_max_cores / nodes;
+ /* fixup multi-node processor information */
+ if (nodes > 1) {
+ u32 cores_per_node;
+
+ set_cpu_cap(c, X86_FEATURE_AMD_DCM);
+ cores_per_node = c->x86_max_cores / nodes;
- /* store NodeID, use llc_shared_map to store sibling info */
- per_cpu(cpu_llc_id, cpu) = value & 7;
+ /* store NodeID, use llc_shared_map to store sibling info */
+ per_cpu(cpu_llc_id, cpu) = node_id;
- /* fixup core id to be in range from 0 to (cores_per_node - 1) */
- c->cpu_core_id = c->cpu_core_id % cores_per_node;
+ /* core id to be in range from 0 to (cores_per_node - 1) */
+ c->cpu_core_id = c->cpu_core_id % cores_per_node;
+ }
}
#endif
@@ -304,9 +318,7 @@ static void __cpuinit amd_detect_cmp(struct cpuinfo_x86 *c)
c->phys_proc_id = c->initial_apicid >> bits;
/* use socket ID also for last level cache */
per_cpu(cpu_llc_id, cpu) = c->phys_proc_id;
- /* fixup topology information on multi-node processors */
- if ((c->x86 == 0x10) && (c->x86_model == 9))
- amd_fixup_dcm(c);
+ amd_get_topology(c);
#endif
}
@@ -412,6 +424,23 @@ static void __cpuinit early_init_amd(struct cpuinfo_x86 *c)
set_cpu_cap(c, X86_FEATURE_EXTD_APICID);
}
#endif
+
+ /* We need to do the following only once */
+ if (c != &boot_cpu_data)
+ return;
+
+ if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) {
+
+ if (c->x86 > 0x10 ||
+ (c->x86 == 0x10 && c->x86_model >= 0x2)) {
+ u64 val;
+
+ rdmsrl(MSR_K7_HWCR, val);
+ if (!(val & BIT(24)))
+ printk(KERN_WARNING FW_BUG "TSC doesn't count "
+ "with P0 frequency!\n");
+ }
+ }
}
static void __cpuinit init_amd(struct cpuinfo_x86 *c)
@@ -523,7 +552,7 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
#endif
if (c->extended_cpuid_level >= 0x80000006) {
- if ((c->x86 >= 0x0f) && (cpuid_edx(0x80000006) & 0xf000))
+ if (cpuid_edx(0x80000006) & 0xf000)
num_cache_leaves = 4;
else
num_cache_leaves = 3;
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 490dac63c2d2..4b68bda30938 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -545,7 +545,7 @@ void __cpuinit cpu_detect(struct cpuinfo_x86 *c)
}
}
-static void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c)
+void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c)
{
u32 tfms, xlvl;
u32 ebx;
@@ -665,7 +665,7 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c)
this_cpu->c_early_init(c);
#ifdef CONFIG_SMP
- c->cpu_index = boot_cpu_id;
+ c->cpu_index = 0;
#endif
filter_cpuid_features(c, false);
}
@@ -704,16 +704,21 @@ void __init early_cpu_init(void)
}
/*
- * The NOPL instruction is supposed to exist on all CPUs with
- * family >= 6; unfortunately, that's not true in practice because
- * of early VIA chips and (more importantly) broken virtualizers that
- * are not easy to detect. In the latter case it doesn't even *fail*
- * reliably, so probing for it doesn't even work. Disable it completely
+ * The NOPL instruction is supposed to exist on all CPUs of family >= 6;
+ * unfortunately, that's not true in practice because of early VIA
+ * chips and (more importantly) broken virtualizers that are not easy
+ * to detect. In the latter case it doesn't even *fail* reliably, so
+ * probing for it doesn't even work. Disable it completely on 32-bit
* unless we can find a reliable way to detect all the broken cases.
+ * Enable it explicitly on 64-bit for non-constant inputs of cpu_has().
*/
static void __cpuinit detect_nopl(struct cpuinfo_x86 *c)
{
+#ifdef CONFIG_X86_32
clear_cpu_cap(c, X86_FEATURE_NOPL);
+#else
+ set_cpu_cap(c, X86_FEATURE_NOPL);
+#endif
}
static void __cpuinit generic_identify(struct cpuinfo_x86 *c)
@@ -1264,13 +1269,6 @@ void __cpuinit cpu_init(void)
clear_all_debug_regs();
dbg_restore_debug_regs();
- /*
- * Force FPU initialization:
- */
- current_thread_info()->status = 0;
- clear_used_math();
- mxcsr_feature_mask_init();
-
fpu_init();
xsave_init();
}
diff --git a/arch/x86/kernel/cpu/cpu.h b/arch/x86/kernel/cpu/cpu.h
index 3624e8a0f71b..e765633f210e 100644
--- a/arch/x86/kernel/cpu/cpu.h
+++ b/arch/x86/kernel/cpu/cpu.h
@@ -32,6 +32,8 @@ struct cpu_dev {
extern const struct cpu_dev *const __x86_cpu_dev_start[],
*const __x86_cpu_dev_end[];
+extern void get_cpu_cap(struct cpuinfo_x86 *c);
extern void cpu_detect_cache_sizes(struct cpuinfo_x86 *c);
+extern void get_cpu_cap(struct cpuinfo_x86 *c);
#endif
diff --git a/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c
index 994230d4dc4e..4f6f679f2799 100644
--- a/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c
+++ b/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c
@@ -368,16 +368,22 @@ static int __init pcc_cpufreq_do_osc(acpi_handle *handle)
return -ENODEV;
out_obj = output.pointer;
- if (out_obj->type != ACPI_TYPE_BUFFER)
- return -ENODEV;
+ if (out_obj->type != ACPI_TYPE_BUFFER) {
+ ret = -ENODEV;
+ goto out_free;
+ }
errors = *((u32 *)out_obj->buffer.pointer) & ~(1 << 0);
- if (errors)
- return -ENODEV;
+ if (errors) {
+ ret = -ENODEV;
+ goto out_free;
+ }
supported = *((u32 *)(out_obj->buffer.pointer + 4));
- if (!(supported & 0x1))
- return -ENODEV;
+ if (!(supported & 0x1)) {
+ ret = -ENODEV;
+ goto out_free;
+ }
out_free:
kfree(output.pointer);
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index 85f69cdeae10..d16c2c53d6bf 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -39,6 +39,7 @@ static void __cpuinit early_init_intel(struct cpuinfo_x86 *c)
misc_enable &= ~MSR_IA32_MISC_ENABLE_LIMIT_CPUID;
wrmsrl(MSR_IA32_MISC_ENABLE, misc_enable);
c->cpuid_level = cpuid_eax(0);
+ get_cpu_cap(c);
}
}
@@ -169,7 +170,7 @@ static void __cpuinit intel_smp_check(struct cpuinfo_x86 *c)
{
#ifdef CONFIG_SMP
/* calling is from identify_secondary_cpu() ? */
- if (c->cpu_index == boot_cpu_id)
+ if (!c->cpu_index)
return;
/*
@@ -283,9 +284,7 @@ static void __cpuinit srat_detect_node(struct cpuinfo_x86 *c)
/* Don't do the funky fallback heuristics the AMD version employs
for now. */
node = apicid_to_node[apicid];
- if (node == NUMA_NO_NODE)
- node = first_node(node_online_map);
- else if (!node_online(node)) {
+ if (node == NUMA_NO_NODE || !node_online(node)) {
/* reuse the value from init_cpu_to_node() */
node = cpu_to_node(cpu);
}
diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c
index 898c2f4eab88..12cd823c8d03 100644
--- a/arch/x86/kernel/cpu/intel_cacheinfo.c
+++ b/arch/x86/kernel/cpu/intel_cacheinfo.c
@@ -17,7 +17,7 @@
#include <asm/processor.h>
#include <linux/smp.h>
-#include <asm/k8.h>
+#include <asm/amd_nb.h>
#include <asm/smp.h>
#define LVL_1_INST 1
@@ -306,7 +306,7 @@ struct _cache_attr {
ssize_t (*store)(struct _cpuid4_info *, const char *, size_t count);
};
-#ifdef CONFIG_CPU_SUP_AMD
+#ifdef CONFIG_AMD_NB
/*
* L3 cache descriptors
@@ -369,7 +369,7 @@ static void __cpuinit amd_check_l3_disable(struct _cpuid4_info_regs *this_leaf,
return;
/* not in virtualized environments */
- if (num_k8_northbridges == 0)
+ if (k8_northbridges.num == 0)
return;
/*
@@ -377,7 +377,7 @@ static void __cpuinit amd_check_l3_disable(struct _cpuid4_info_regs *this_leaf,
* never freed but this is done only on shutdown so it doesn't matter.
*/
if (!l3_caches) {
- int size = num_k8_northbridges * sizeof(struct amd_l3_cache *);
+ int size = k8_northbridges.num * sizeof(struct amd_l3_cache *);
l3_caches = kzalloc(size, GFP_ATOMIC);
if (!l3_caches)
@@ -556,12 +556,12 @@ static struct _cache_attr cache_disable_0 = __ATTR(cache_disable_0, 0644,
static struct _cache_attr cache_disable_1 = __ATTR(cache_disable_1, 0644,
show_cache_disable_1, store_cache_disable_1);
-#else /* CONFIG_CPU_SUP_AMD */
+#else /* CONFIG_AMD_NB */
static void __cpuinit
amd_check_l3_disable(struct _cpuid4_info_regs *this_leaf, int index)
{
};
-#endif /* CONFIG_CPU_SUP_AMD */
+#endif /* CONFIG_AMD_NB */
static int
__cpuinit cpuid4_cache_lookup_regs(int index,
@@ -1000,7 +1000,7 @@ static struct attribute *default_attrs[] = {
static struct attribute *default_l3_attrs[] = {
DEFAULT_SYSFS_CACHE_ATTRS,
-#ifdef CONFIG_CPU_SUP_AMD
+#ifdef CONFIG_AMD_NB
&cache_disable_0.attr,
&cache_disable_1.attr,
#endif
diff --git a/arch/x86/kernel/cpu/mcheck/mce-severity.c b/arch/x86/kernel/cpu/mcheck/mce-severity.c
index 8a85dd1b1aa1..1e8d66c1336a 100644
--- a/arch/x86/kernel/cpu/mcheck/mce-severity.c
+++ b/arch/x86/kernel/cpu/mcheck/mce-severity.c
@@ -192,6 +192,7 @@ static const struct file_operations severities_coverage_fops = {
.release = seq_release,
.read = seq_read,
.write = severities_coverage_write,
+ .llseek = seq_lseek,
};
static int __init severities_debugfs_init(void)
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index ed41562909fe..7a35b72d7c03 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -1665,6 +1665,7 @@ struct file_operations mce_chrdev_ops = {
.read = mce_read,
.poll = mce_poll,
.unlocked_ioctl = mce_ioctl,
+ .llseek = no_llseek,
};
EXPORT_SYMBOL_GPL(mce_chrdev_ops);
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index 5e975298fa81..80c482382d5c 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -131,7 +131,8 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c)
u32 low = 0, high = 0, address = 0;
unsigned int bank, block;
struct thresh_restart tr;
- u8 lvt_off;
+ int lvt_off = -1;
+ u8 offset;
for (bank = 0; bank < NR_BANKS; ++bank) {
for (block = 0; block < NR_BLOCKS; ++block) {
@@ -141,6 +142,7 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c)
address = (low & MASK_BLKPTR_LO) >> 21;
if (!address)
break;
+
address += MCG_XBLK_ADDR;
} else
++address;
@@ -148,12 +150,8 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c)
if (rdmsr_safe(address, &low, &high))
break;
- if (!(high & MASK_VALID_HI)) {
- if (block)
- continue;
- else
- break;
- }
+ if (!(high & MASK_VALID_HI))
+ continue;
if (!(high & MASK_CNTP_HI) ||
(high & MASK_LOCKED_HI))
@@ -165,8 +163,28 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c)
if (shared_bank[bank] && c->cpu_core_id)
break;
#endif
- lvt_off = setup_APIC_eilvt_mce(THRESHOLD_APIC_VECTOR,
- APIC_EILVT_MSG_FIX, 0);
+ offset = (high & MASK_LVTOFF_HI) >> 20;
+ if (lvt_off < 0) {
+ if (setup_APIC_eilvt(offset,
+ THRESHOLD_APIC_VECTOR,
+ APIC_EILVT_MSG_FIX, 0)) {
+ pr_err(FW_BUG "cpu %d, failed to "
+ "setup threshold interrupt "
+ "for bank %d, block %d "
+ "(MSR%08X=0x%x%08x)",
+ smp_processor_id(), bank, block,
+ address, high, low);
+ continue;
+ }
+ lvt_off = offset;
+ } else if (lvt_off != offset) {
+ pr_err(FW_BUG "cpu %d, invalid threshold "
+ "interrupt offset %d for bank %d,"
+ "block %d (MSR%08X=0x%x%08x)",
+ smp_processor_id(), lvt_off, bank,
+ block, address, high, low);
+ continue;
+ }
high &= ~MASK_LVTOFF_HI;
high |= lvt_off << 20;
diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c
index d9368eeda309..4b683267eca5 100644
--- a/arch/x86/kernel/cpu/mcheck/therm_throt.c
+++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c
@@ -216,7 +216,7 @@ static __cpuinit int thermal_throttle_add_dev(struct sys_device *sys_dev,
err = sysfs_add_file_to_group(&sys_dev->kobj,
&attr_core_power_limit_count.attr,
thermal_attr_group.name);
- if (cpu_has(c, X86_FEATURE_PTS))
+ if (cpu_has(c, X86_FEATURE_PTS)) {
err = sysfs_add_file_to_group(&sys_dev->kobj,
&attr_package_throttle_count.attr,
thermal_attr_group.name);
@@ -224,6 +224,7 @@ static __cpuinit int thermal_throttle_add_dev(struct sys_device *sys_dev,
err = sysfs_add_file_to_group(&sys_dev->kobj,
&attr_package_power_limit_count.attr,
thermal_attr_group.name);
+ }
return err;
}
@@ -349,7 +350,7 @@ static void intel_thermal_interrupt(void)
static void unexpected_thermal_interrupt(void)
{
- printk(KERN_ERR "CPU%d: Unexpected LVT TMR interrupt!\n",
+ printk(KERN_ERR "CPU%d: Unexpected LVT thermal interrupt!\n",
smp_processor_id());
add_taint(TAINT_MACHINE_CHECK);
}
diff --git a/arch/x86/kernel/cpu/mtrr/cleanup.c b/arch/x86/kernel/cpu/mtrr/cleanup.c
index c5f59d071425..ac140c7be396 100644
--- a/arch/x86/kernel/cpu/mtrr/cleanup.c
+++ b/arch/x86/kernel/cpu/mtrr/cleanup.c
@@ -827,7 +827,7 @@ int __init amd_special_default_mtrr(void)
if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
return 0;
- if (boot_cpu_data.x86 < 0xf || boot_cpu_data.x86 > 0x11)
+ if (boot_cpu_data.x86 < 0xf)
return 0;
/* In case some hypervisor doesn't pass SYSCFG through: */
if (rdmsr_safe(MSR_K8_SYSCFG, &l, &h) < 0)
diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c
index 7d28d7d03885..9f27228ceffd 100644
--- a/arch/x86/kernel/cpu/mtrr/generic.c
+++ b/arch/x86/kernel/cpu/mtrr/generic.c
@@ -64,18 +64,59 @@ static inline void k8_check_syscfg_dram_mod_en(void)
}
}
+/* Get the size of contiguous MTRR range */
+static u64 get_mtrr_size(u64 mask)
+{
+ u64 size;
+
+ mask >>= PAGE_SHIFT;
+ mask |= size_or_mask;
+ size = -mask;
+ size <<= PAGE_SHIFT;
+ return size;
+}
+
/*
- * Returns the effective MTRR type for the region
- * Error returns:
- * - 0xFE - when the range is "not entirely covered" by _any_ var range MTRR
- * - 0xFF - when MTRR is not enabled
+ * Check and return the effective type for MTRR-MTRR type overlap.
+ * Returns 1 if the effective type is UNCACHEABLE, else returns 0
*/
-u8 mtrr_type_lookup(u64 start, u64 end)
+static int check_type_overlap(u8 *prev, u8 *curr)
+{
+ if (*prev == MTRR_TYPE_UNCACHABLE || *curr == MTRR_TYPE_UNCACHABLE) {
+ *prev = MTRR_TYPE_UNCACHABLE;
+ *curr = MTRR_TYPE_UNCACHABLE;
+ return 1;
+ }
+
+ if ((*prev == MTRR_TYPE_WRBACK && *curr == MTRR_TYPE_WRTHROUGH) ||
+ (*prev == MTRR_TYPE_WRTHROUGH && *curr == MTRR_TYPE_WRBACK)) {
+ *prev = MTRR_TYPE_WRTHROUGH;
+ *curr = MTRR_TYPE_WRTHROUGH;
+ }
+
+ if (*prev != *curr) {
+ *prev = MTRR_TYPE_UNCACHABLE;
+ *curr = MTRR_TYPE_UNCACHABLE;
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * Error/Semi-error returns:
+ * 0xFF - when MTRR is not enabled
+ * *repeat == 1 implies [start:end] spanned across MTRR range and type returned
+ * corresponds only to [start:*partial_end].
+ * Caller has to lookup again for [*partial_end:end].
+ */
+static u8 __mtrr_type_lookup(u64 start, u64 end, u64 *partial_end, int *repeat)
{
int i;
u64 base, mask;
u8 prev_match, curr_match;
+ *repeat = 0;
if (!mtrr_state_set)
return 0xFF;
@@ -126,8 +167,34 @@ u8 mtrr_type_lookup(u64 start, u64 end)
start_state = ((start & mask) == (base & mask));
end_state = ((end & mask) == (base & mask));
- if (start_state != end_state)
- return 0xFE;
+
+ if (start_state != end_state) {
+ /*
+ * We have start:end spanning across an MTRR.
+ * We split the region into
+ * either
+ * (start:mtrr_end) (mtrr_end:end)
+ * or
+ * (start:mtrr_start) (mtrr_start:end)
+ * depending on kind of overlap.
+ * Return the type for first region and a pointer to
+ * the start of second region so that caller will
+ * lookup again on the second region.
+ * Note: This way we handle multiple overlaps as well.
+ */
+ if (start_state)
+ *partial_end = base + get_mtrr_size(mask);
+ else
+ *partial_end = base;
+
+ if (unlikely(*partial_end <= start)) {
+ WARN_ON(1);
+ *partial_end = start + PAGE_SIZE;
+ }
+
+ end = *partial_end - 1; /* end is inclusive */
+ *repeat = 1;
+ }
if ((start & mask) != (base & mask))
continue;
@@ -138,21 +205,8 @@ u8 mtrr_type_lookup(u64 start, u64 end)
continue;
}
- if (prev_match == MTRR_TYPE_UNCACHABLE ||
- curr_match == MTRR_TYPE_UNCACHABLE) {
- return MTRR_TYPE_UNCACHABLE;
- }
-
- if ((prev_match == MTRR_TYPE_WRBACK &&
- curr_match == MTRR_TYPE_WRTHROUGH) ||
- (prev_match == MTRR_TYPE_WRTHROUGH &&
- curr_match == MTRR_TYPE_WRBACK)) {
- prev_match = MTRR_TYPE_WRTHROUGH;
- curr_match = MTRR_TYPE_WRTHROUGH;
- }
-
- if (prev_match != curr_match)
- return MTRR_TYPE_UNCACHABLE;
+ if (check_type_overlap(&prev_match, &curr_match))
+ return curr_match;
}
if (mtrr_tom2) {
@@ -166,6 +220,36 @@ u8 mtrr_type_lookup(u64 start, u64 end)
return mtrr_state.def_type;
}
+/*
+ * Returns the effective MTRR type for the region
+ * Error return:
+ * 0xFF - when MTRR is not enabled
+ */
+u8 mtrr_type_lookup(u64 start, u64 end)
+{
+ u8 type, prev_type;
+ int repeat;
+ u64 partial_end;
+
+ type = __mtrr_type_lookup(start, end, &partial_end, &repeat);
+
+ /*
+ * Common path is with repeat = 0.
+ * However, we can have cases where [start:end] spans across some
+ * MTRR range. Do repeated lookups for that case here.
+ */
+ while (repeat) {
+ prev_type = type;
+ start = partial_end;
+ type = __mtrr_type_lookup(start, end, &partial_end, &repeat);
+
+ if (check_type_overlap(&prev_type, &type))
+ return type;
+ }
+
+ return type;
+}
+
/* Get the MSR pair relating to a var range */
static void
get_mtrr_var_range(unsigned int index, struct mtrr_var_range *vr)
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index 03a5b0385ad6..fe73c1844a9a 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -531,7 +531,7 @@ static int x86_pmu_hw_config(struct perf_event *event)
/*
* Setup the hardware configuration for a given attr_type
*/
-static int __hw_perf_event_init(struct perf_event *event)
+static int __x86_pmu_event_init(struct perf_event *event)
{
int err;
@@ -584,7 +584,7 @@ static void x86_pmu_disable_all(void)
}
}
-void hw_perf_disable(void)
+static void x86_pmu_disable(struct pmu *pmu)
{
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
@@ -619,7 +619,7 @@ static void x86_pmu_enable_all(int added)
}
}
-static const struct pmu pmu;
+static struct pmu pmu;
static inline int is_x86_event(struct perf_event *event)
{
@@ -801,10 +801,10 @@ static inline int match_prev_assignment(struct hw_perf_event *hwc,
hwc->last_tag == cpuc->tags[i];
}
-static int x86_pmu_start(struct perf_event *event);
-static void x86_pmu_stop(struct perf_event *event);
+static void x86_pmu_start(struct perf_event *event, int flags);
+static void x86_pmu_stop(struct perf_event *event, int flags);
-void hw_perf_enable(void)
+static void x86_pmu_enable(struct pmu *pmu)
{
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
struct perf_event *event;
@@ -840,7 +840,14 @@ void hw_perf_enable(void)
match_prev_assignment(hwc, cpuc, i))
continue;
- x86_pmu_stop(event);
+ /*
+ * Ensure we don't accidentally enable a stopped
+ * counter simply because we rescheduled.
+ */
+ if (hwc->state & PERF_HES_STOPPED)
+ hwc->state |= PERF_HES_ARCH;
+
+ x86_pmu_stop(event, PERF_EF_UPDATE);
}
for (i = 0; i < cpuc->n_events; i++) {
@@ -852,7 +859,10 @@ void hw_perf_enable(void)
else if (i < n_running)
continue;
- x86_pmu_start(event);
+ if (hwc->state & PERF_HES_ARCH)
+ continue;
+
+ x86_pmu_start(event, PERF_EF_RELOAD);
}
cpuc->n_added = 0;
perf_events_lapic_init();
@@ -953,15 +963,12 @@ static void x86_pmu_enable_event(struct perf_event *event)
}
/*
- * activate a single event
+ * Add a single event to the PMU.
*
* The event is added to the group of enabled events
* but only if it can be scehduled with existing events.
- *
- * Called with PMU disabled. If successful and return value 1,
- * then guaranteed to call perf_enable() and hw_perf_enable()
*/
-static int x86_pmu_enable(struct perf_event *event)
+static int x86_pmu_add(struct perf_event *event, int flags)
{
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
struct hw_perf_event *hwc;
@@ -970,58 +977,67 @@ static int x86_pmu_enable(struct perf_event *event)
hwc = &event->hw;
+ perf_pmu_disable(event->pmu);
n0 = cpuc->n_events;
- n = collect_events(cpuc, event, false);
- if (n < 0)
- return n;
+ ret = n = collect_events(cpuc, event, false);
+ if (ret < 0)
+ goto out;
+
+ hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
+ if (!(flags & PERF_EF_START))
+ hwc->state |= PERF_HES_ARCH;
/*
* If group events scheduling transaction was started,
* skip the schedulability test here, it will be peformed
- * at commit time(->commit_txn) as a whole
+ * at commit time (->commit_txn) as a whole
*/
if (cpuc->group_flag & PERF_EVENT_TXN)
- goto out;
+ goto done_collect;
ret = x86_pmu.schedule_events(cpuc, n, assign);
if (ret)
- return ret;
+ goto out;
/*
* copy new assignment, now we know it is possible
* will be used by hw_perf_enable()
*/
memcpy(cpuc->assign, assign, n*sizeof(int));
-out:
+done_collect:
cpuc->n_events = n;
cpuc->n_added += n - n0;
cpuc->n_txn += n - n0;
- return 0;
+ ret = 0;
+out:
+ perf_pmu_enable(event->pmu);
+ return ret;
}
-static int x86_pmu_start(struct perf_event *event)
+static void x86_pmu_start(struct perf_event *event, int flags)
{
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
int idx = event->hw.idx;
- if (idx == -1)
- return -EAGAIN;
+ if (WARN_ON_ONCE(!(event->hw.state & PERF_HES_STOPPED)))
+ return;
+
+ if (WARN_ON_ONCE(idx == -1))
+ return;
+
+ if (flags & PERF_EF_RELOAD) {
+ WARN_ON_ONCE(!(event->hw.state & PERF_HES_UPTODATE));
+ x86_perf_event_set_period(event);
+ }
+
+ event->hw.state = 0;
- x86_perf_event_set_period(event);
cpuc->events[idx] = event;
__set_bit(idx, cpuc->active_mask);
__set_bit(idx, cpuc->running);
x86_pmu.enable(event);
perf_event_update_userpage(event);
-
- return 0;
-}
-
-static void x86_pmu_unthrottle(struct perf_event *event)
-{
- int ret = x86_pmu_start(event);
- WARN_ON_ONCE(ret);
}
void perf_event_print_debug(void)
@@ -1078,27 +1094,29 @@ void perf_event_print_debug(void)
local_irq_restore(flags);
}
-static void x86_pmu_stop(struct perf_event *event)
+static void x86_pmu_stop(struct perf_event *event, int flags)
{
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
struct hw_perf_event *hwc = &event->hw;
- int idx = hwc->idx;
- if (!__test_and_clear_bit(idx, cpuc->active_mask))
- return;
-
- x86_pmu.disable(event);
-
- /*
- * Drain the remaining delta count out of a event
- * that we are disabling:
- */
- x86_perf_event_update(event);
+ if (__test_and_clear_bit(hwc->idx, cpuc->active_mask)) {
+ x86_pmu.disable(event);
+ cpuc->events[hwc->idx] = NULL;
+ WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED);
+ hwc->state |= PERF_HES_STOPPED;
+ }
- cpuc->events[idx] = NULL;
+ if ((flags & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) {
+ /*
+ * Drain the remaining delta count out of a event
+ * that we are disabling:
+ */
+ x86_perf_event_update(event);
+ hwc->state |= PERF_HES_UPTODATE;
+ }
}
-static void x86_pmu_disable(struct perf_event *event)
+static void x86_pmu_del(struct perf_event *event, int flags)
{
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
int i;
@@ -1111,7 +1129,7 @@ static void x86_pmu_disable(struct perf_event *event)
if (cpuc->group_flag & PERF_EVENT_TXN)
return;
- x86_pmu_stop(event);
+ x86_pmu_stop(event, PERF_EF_UPDATE);
for (i = 0; i < cpuc->n_events; i++) {
if (event == cpuc->event_list[i]) {
@@ -1134,7 +1152,6 @@ static int x86_pmu_handle_irq(struct pt_regs *regs)
struct perf_sample_data data;
struct cpu_hw_events *cpuc;
struct perf_event *event;
- struct hw_perf_event *hwc;
int idx, handled = 0;
u64 val;
@@ -1155,7 +1172,6 @@ static int x86_pmu_handle_irq(struct pt_regs *regs)
}
event = cpuc->events[idx];
- hwc = &event->hw;
val = x86_perf_event_update(event);
if (val & (1ULL << (x86_pmu.cntval_bits - 1)))
@@ -1171,7 +1187,7 @@ static int x86_pmu_handle_irq(struct pt_regs *regs)
continue;
if (perf_event_overflow(event, 1, &data, regs))
- x86_pmu_stop(event);
+ x86_pmu_stop(event, 0);
}
if (handled)
@@ -1180,25 +1196,6 @@ static int x86_pmu_handle_irq(struct pt_regs *regs)
return handled;
}
-void smp_perf_pending_interrupt(struct pt_regs *regs)
-{
- irq_enter();
- ack_APIC_irq();
- inc_irq_stat(apic_pending_irqs);
- perf_event_do_pending();
- irq_exit();
-}
-
-void set_perf_event_pending(void)
-{
-#ifdef CONFIG_X86_LOCAL_APIC
- if (!x86_pmu.apic || !x86_pmu_initialized())
- return;
-
- apic->send_IPI_self(LOCAL_PENDING_VECTOR);
-#endif
-}
-
void perf_events_lapic_init(void)
{
if (!x86_pmu.apic || !x86_pmu_initialized())
@@ -1388,7 +1385,6 @@ void __init init_hw_perf_events(void)
x86_pmu.num_counters = X86_PMC_MAX_GENERIC;
}
x86_pmu.intel_ctrl = (1 << x86_pmu.num_counters) - 1;
- perf_max_events = x86_pmu.num_counters;
if (x86_pmu.num_counters_fixed > X86_PMC_MAX_FIXED) {
WARN(1, KERN_ERR "hw perf events fixed %d > max(%d), clipping!",
@@ -1424,6 +1420,7 @@ void __init init_hw_perf_events(void)
pr_info("... fixed-purpose events: %d\n", x86_pmu.num_counters_fixed);
pr_info("... event mask: %016Lx\n", x86_pmu.intel_ctrl);
+ perf_pmu_register(&pmu);
perf_cpu_notifier(x86_pmu_notifier);
}
@@ -1437,10 +1434,11 @@ static inline void x86_pmu_read(struct perf_event *event)
* Set the flag to make pmu::enable() not perform the
* schedulability test, it will be performed at commit time
*/
-static void x86_pmu_start_txn(const struct pmu *pmu)
+static void x86_pmu_start_txn(struct pmu *pmu)
{
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+ perf_pmu_disable(pmu);
cpuc->group_flag |= PERF_EVENT_TXN;
cpuc->n_txn = 0;
}
@@ -1450,7 +1448,7 @@ static void x86_pmu_start_txn(const struct pmu *pmu)
* Clear the flag and pmu::enable() will perform the
* schedulability test.
*/
-static void x86_pmu_cancel_txn(const struct pmu *pmu)
+static void x86_pmu_cancel_txn(struct pmu *pmu)
{
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
@@ -1460,6 +1458,7 @@ static void x86_pmu_cancel_txn(const struct pmu *pmu)
*/
cpuc->n_added -= cpuc->n_txn;
cpuc->n_events -= cpuc->n_txn;
+ perf_pmu_enable(pmu);
}
/*
@@ -1467,7 +1466,7 @@ static void x86_pmu_cancel_txn(const struct pmu *pmu)
* Perform the group schedulability test as a whole
* Return 0 if success
*/
-static int x86_pmu_commit_txn(const struct pmu *pmu)
+static int x86_pmu_commit_txn(struct pmu *pmu)
{
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
int assign[X86_PMC_IDX_MAX];
@@ -1489,22 +1488,10 @@ static int x86_pmu_commit_txn(const struct pmu *pmu)
memcpy(cpuc->assign, assign, n*sizeof(int));
cpuc->group_flag &= ~PERF_EVENT_TXN;
-
+ perf_pmu_enable(pmu);
return 0;
}
-static const struct pmu pmu = {
- .enable = x86_pmu_enable,
- .disable = x86_pmu_disable,
- .start = x86_pmu_start,
- .stop = x86_pmu_stop,
- .read = x86_pmu_read,
- .unthrottle = x86_pmu_unthrottle,
- .start_txn = x86_pmu_start_txn,
- .cancel_txn = x86_pmu_cancel_txn,
- .commit_txn = x86_pmu_commit_txn,
-};
-
/*
* validate that we can schedule this event
*/
@@ -1579,12 +1566,22 @@ out:
return ret;
}
-const struct pmu *hw_perf_event_init(struct perf_event *event)
+int x86_pmu_event_init(struct perf_event *event)
{
- const struct pmu *tmp;
+ struct pmu *tmp;
int err;
- err = __hw_perf_event_init(event);
+ switch (event->attr.type) {
+ case PERF_TYPE_RAW:
+ case PERF_TYPE_HARDWARE:
+ case PERF_TYPE_HW_CACHE:
+ break;
+
+ default:
+ return -ENOENT;
+ }
+
+ err = __x86_pmu_event_init(event);
if (!err) {
/*
* we temporarily connect event to its pmu
@@ -1604,26 +1601,31 @@ const struct pmu *hw_perf_event_init(struct perf_event *event)
if (err) {
if (event->destroy)
event->destroy(event);
- return ERR_PTR(err);
}
- return &pmu;
+ return err;
}
-/*
- * callchain support
- */
+static struct pmu pmu = {
+ .pmu_enable = x86_pmu_enable,
+ .pmu_disable = x86_pmu_disable,
-static inline
-void callchain_store(struct perf_callchain_entry *entry, u64 ip)
-{
- if (entry->nr < PERF_MAX_STACK_DEPTH)
- entry->ip[entry->nr++] = ip;
-}
+ .event_init = x86_pmu_event_init,
-static DEFINE_PER_CPU(struct perf_callchain_entry, pmc_irq_entry);
-static DEFINE_PER_CPU(struct perf_callchain_entry, pmc_nmi_entry);
+ .add = x86_pmu_add,
+ .del = x86_pmu_del,
+ .start = x86_pmu_start,
+ .stop = x86_pmu_stop,
+ .read = x86_pmu_read,
+ .start_txn = x86_pmu_start_txn,
+ .cancel_txn = x86_pmu_cancel_txn,
+ .commit_txn = x86_pmu_commit_txn,
+};
+
+/*
+ * callchain support
+ */
static void
backtrace_warning_symbol(void *data, char *msg, unsigned long symbol)
@@ -1645,7 +1647,7 @@ static void backtrace_address(void *data, unsigned long addr, int reliable)
{
struct perf_callchain_entry *entry = data;
- callchain_store(entry, addr);
+ perf_callchain_store(entry, addr);
}
static const struct stacktrace_ops backtrace_ops = {
@@ -1656,11 +1658,15 @@ static const struct stacktrace_ops backtrace_ops = {
.walk_stack = print_context_stack_bp,
};
-static void
-perf_callchain_kernel(struct pt_regs *regs, struct perf_callchain_entry *entry)
+void
+perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs)
{
- callchain_store(entry, PERF_CONTEXT_KERNEL);
- callchain_store(entry, regs->ip);
+ if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
+ /* TODO: We don't support guest os callchain now */
+ return;
+ }
+
+ perf_callchain_store(entry, regs->ip);
dump_trace(NULL, regs, NULL, regs->bp, &backtrace_ops, entry);
}
@@ -1689,7 +1695,7 @@ perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry)
if (fp < compat_ptr(regs->sp))
break;
- callchain_store(entry, frame.return_address);
+ perf_callchain_store(entry, frame.return_address);
fp = compat_ptr(frame.next_frame);
}
return 1;
@@ -1702,19 +1708,20 @@ perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry)
}
#endif
-static void
-perf_callchain_user(struct pt_regs *regs, struct perf_callchain_entry *entry)
+void
+perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
{
struct stack_frame frame;
const void __user *fp;
- if (!user_mode(regs))
- regs = task_pt_regs(current);
+ if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
+ /* TODO: We don't support guest os callchain now */
+ return;
+ }
fp = (void __user *)regs->bp;
- callchain_store(entry, PERF_CONTEXT_USER);
- callchain_store(entry, regs->ip);
+ perf_callchain_store(entry, regs->ip);
if (perf_callchain_user32(regs, entry))
return;
@@ -1731,52 +1738,11 @@ perf_callchain_user(struct pt_regs *regs, struct perf_callchain_entry *entry)
if ((unsigned long)fp < regs->sp)
break;
- callchain_store(entry, frame.return_address);
+ perf_callchain_store(entry, frame.return_address);
fp = frame.next_frame;
}
}
-static void
-perf_do_callchain(struct pt_regs *regs, struct perf_callchain_entry *entry)
-{
- int is_user;
-
- if (!regs)
- return;
-
- is_user = user_mode(regs);
-
- if (is_user && current->state != TASK_RUNNING)
- return;
-
- if (!is_user)
- perf_callchain_kernel(regs, entry);
-
- if (current->mm)
- perf_callchain_user(regs, entry);
-}
-
-struct perf_callchain_entry *perf_callchain(struct pt_regs *regs)
-{
- struct perf_callchain_entry *entry;
-
- if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
- /* TODO: We don't support guest os callchain now */
- return NULL;
- }
-
- if (in_nmi())
- entry = &__get_cpu_var(pmc_nmi_entry);
- else
- entry = &__get_cpu_var(pmc_irq_entry);
-
- entry->nr = 0;
-
- perf_do_callchain(regs, entry);
-
- return entry;
-}
-
unsigned long perf_instruction_pointer(struct pt_regs *regs)
{
unsigned long ip;
diff --git a/arch/x86/kernel/cpu/perf_event_amd.c b/arch/x86/kernel/cpu/perf_event_amd.c
index c2897b7b4a3b..46d58448c3af 100644
--- a/arch/x86/kernel/cpu/perf_event_amd.c
+++ b/arch/x86/kernel/cpu/perf_event_amd.c
@@ -52,7 +52,7 @@ static __initconst const u64 amd_hw_cache_event_ids
[ C(DTLB) ] = {
[ C(OP_READ) ] = {
[ C(RESULT_ACCESS) ] = 0x0040, /* Data Cache Accesses */
- [ C(RESULT_MISS) ] = 0x0046, /* L1 DTLB and L2 DLTB Miss */
+ [ C(RESULT_MISS) ] = 0x0746, /* L1_DTLB_AND_L2_DLTB_MISS.ALL */
},
[ C(OP_WRITE) ] = {
[ C(RESULT_ACCESS) ] = 0,
@@ -66,7 +66,7 @@ static __initconst const u64 amd_hw_cache_event_ids
[ C(ITLB) ] = {
[ C(OP_READ) ] = {
[ C(RESULT_ACCESS) ] = 0x0080, /* Instruction fecthes */
- [ C(RESULT_MISS) ] = 0x0085, /* Instr. fetch ITLB misses */
+ [ C(RESULT_MISS) ] = 0x0385, /* L1_ITLB_AND_L2_ITLB_MISS.ALL */
},
[ C(OP_WRITE) ] = {
[ C(RESULT_ACCESS) ] = -1,
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c
index ee05c90012d2..c8f5c088cad1 100644
--- a/arch/x86/kernel/cpu/perf_event_intel.c
+++ b/arch/x86/kernel/cpu/perf_event_intel.c
@@ -713,18 +713,18 @@ static int intel_pmu_handle_irq(struct pt_regs *regs)
struct cpu_hw_events *cpuc;
int bit, loops;
u64 status;
- int handled = 0;
+ int handled;
perf_sample_data_init(&data, 0);
cpuc = &__get_cpu_var(cpu_hw_events);
intel_pmu_disable_all();
- intel_pmu_drain_bts_buffer();
+ handled = intel_pmu_drain_bts_buffer();
status = intel_pmu_get_status();
if (!status) {
intel_pmu_enable_all(0);
- return 0;
+ return handled;
}
loops = 0;
@@ -763,7 +763,7 @@ again:
data.period = event->hw.last_period;
if (perf_event_overflow(event, 1, &data, regs))
- x86_pmu_stop(event);
+ x86_pmu_stop(event, 0);
}
/*
diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c
index 18018d1311cd..4977f9c400e5 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_ds.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c
@@ -214,7 +214,7 @@ static void intel_pmu_disable_bts(void)
update_debugctlmsr(debugctlmsr);
}
-static void intel_pmu_drain_bts_buffer(void)
+static int intel_pmu_drain_bts_buffer(void)
{
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
struct debug_store *ds = cpuc->ds;
@@ -231,16 +231,16 @@ static void intel_pmu_drain_bts_buffer(void)
struct pt_regs regs;
if (!event)
- return;
+ return 0;
if (!ds)
- return;
+ return 0;
at = (struct bts_record *)(unsigned long)ds->bts_buffer_base;
top = (struct bts_record *)(unsigned long)ds->bts_index;
if (top <= at)
- return;
+ return 0;
ds->bts_index = ds->bts_buffer_base;
@@ -256,7 +256,7 @@ static void intel_pmu_drain_bts_buffer(void)
perf_prepare_sample(&header, &data, event, &regs);
if (perf_output_begin(&handle, event, header.size * (top - at), 1, 1))
- return;
+ return 1;
for (; at < top; at++) {
data.ip = at->from;
@@ -270,6 +270,7 @@ static void intel_pmu_drain_bts_buffer(void)
/* There's new data available. */
event->hw.interrupts++;
event->pending_kill = POLL_IN;
+ return 1;
}
/*
@@ -491,7 +492,7 @@ static void __intel_pmu_pebs_event(struct perf_event *event,
regs.flags &= ~PERF_EFLAGS_EXACT;
if (perf_event_overflow(event, 1, &data, &regs))
- x86_pmu_stop(event);
+ x86_pmu_stop(event, 0);
}
static void intel_pmu_drain_pebs_core(struct pt_regs *iregs)
diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c
index b560db3305be..81400b93e694 100644
--- a/arch/x86/kernel/cpu/perf_event_p4.c
+++ b/arch/x86/kernel/cpu/perf_event_p4.c
@@ -18,6 +18,8 @@
struct p4_event_bind {
unsigned int opcode; /* Event code and ESCR selector */
unsigned int escr_msr[2]; /* ESCR MSR for this event */
+ unsigned int escr_emask; /* valid ESCR EventMask bits */
+ unsigned int shared; /* event is shared across threads */
char cntr[2][P4_CNTR_LIMIT]; /* counter index (offset), -1 on abscence */
};
@@ -66,231 +68,435 @@ static struct p4_event_bind p4_event_bind_map[] = {
[P4_EVENT_TC_DELIVER_MODE] = {
.opcode = P4_OPCODE(P4_EVENT_TC_DELIVER_MODE),
.escr_msr = { MSR_P4_TC_ESCR0, MSR_P4_TC_ESCR1 },
+ .escr_emask =
+ P4_ESCR_EMASK_BIT(P4_EVENT_TC_DELIVER_MODE, DD) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_TC_DELIVER_MODE, DB) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_TC_DELIVER_MODE, DI) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_TC_DELIVER_MODE, BD) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_TC_DELIVER_MODE, BB) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_TC_DELIVER_MODE, BI) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_TC_DELIVER_MODE, ID),
+ .shared = 1,
.cntr = { {4, 5, -1}, {6, 7, -1} },
},
[P4_EVENT_BPU_FETCH_REQUEST] = {
.opcode = P4_OPCODE(P4_EVENT_BPU_FETCH_REQUEST),
.escr_msr = { MSR_P4_BPU_ESCR0, MSR_P4_BPU_ESCR1 },
+ .escr_emask =
+ P4_ESCR_EMASK_BIT(P4_EVENT_BPU_FETCH_REQUEST, TCMISS),
.cntr = { {0, -1, -1}, {2, -1, -1} },
},
[P4_EVENT_ITLB_REFERENCE] = {
.opcode = P4_OPCODE(P4_EVENT_ITLB_REFERENCE),
.escr_msr = { MSR_P4_ITLB_ESCR0, MSR_P4_ITLB_ESCR1 },
+ .escr_emask =
+ P4_ESCR_EMASK_BIT(P4_EVENT_ITLB_REFERENCE, HIT) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_ITLB_REFERENCE, MISS) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_ITLB_REFERENCE, HIT_UK),
.cntr = { {0, -1, -1}, {2, -1, -1} },
},
[P4_EVENT_MEMORY_CANCEL] = {
.opcode = P4_OPCODE(P4_EVENT_MEMORY_CANCEL),
.escr_msr = { MSR_P4_DAC_ESCR0, MSR_P4_DAC_ESCR1 },
+ .escr_emask =
+ P4_ESCR_EMASK_BIT(P4_EVENT_MEMORY_CANCEL, ST_RB_FULL) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_MEMORY_CANCEL, 64K_CONF),
.cntr = { {8, 9, -1}, {10, 11, -1} },
},
[P4_EVENT_MEMORY_COMPLETE] = {
.opcode = P4_OPCODE(P4_EVENT_MEMORY_COMPLETE),
.escr_msr = { MSR_P4_SAAT_ESCR0 , MSR_P4_SAAT_ESCR1 },
+ .escr_emask =
+ P4_ESCR_EMASK_BIT(P4_EVENT_MEMORY_COMPLETE, LSC) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_MEMORY_COMPLETE, SSC),
.cntr = { {8, 9, -1}, {10, 11, -1} },
},
[P4_EVENT_LOAD_PORT_REPLAY] = {
.opcode = P4_OPCODE(P4_EVENT_LOAD_PORT_REPLAY),
.escr_msr = { MSR_P4_SAAT_ESCR0, MSR_P4_SAAT_ESCR1 },
+ .escr_emask =
+ P4_ESCR_EMASK_BIT(P4_EVENT_LOAD_PORT_REPLAY, SPLIT_LD),
.cntr = { {8, 9, -1}, {10, 11, -1} },
},
[P4_EVENT_STORE_PORT_REPLAY] = {
.opcode = P4_OPCODE(P4_EVENT_STORE_PORT_REPLAY),
.escr_msr = { MSR_P4_SAAT_ESCR0 , MSR_P4_SAAT_ESCR1 },
+ .escr_emask =
+ P4_ESCR_EMASK_BIT(P4_EVENT_STORE_PORT_REPLAY, SPLIT_ST),
.cntr = { {8, 9, -1}, {10, 11, -1} },
},
[P4_EVENT_MOB_LOAD_REPLAY] = {
.opcode = P4_OPCODE(P4_EVENT_MOB_LOAD_REPLAY),
.escr_msr = { MSR_P4_MOB_ESCR0, MSR_P4_MOB_ESCR1 },
+ .escr_emask =
+ P4_ESCR_EMASK_BIT(P4_EVENT_MOB_LOAD_REPLAY, NO_STA) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_MOB_LOAD_REPLAY, NO_STD) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_MOB_LOAD_REPLAY, PARTIAL_DATA) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_MOB_LOAD_REPLAY, UNALGN_ADDR),
.cntr = { {0, -1, -1}, {2, -1, -1} },
},
[P4_EVENT_PAGE_WALK_TYPE] = {
.opcode = P4_OPCODE(P4_EVENT_PAGE_WALK_TYPE),
.escr_msr = { MSR_P4_PMH_ESCR0, MSR_P4_PMH_ESCR1 },
+ .escr_emask =
+ P4_ESCR_EMASK_BIT(P4_EVENT_PAGE_WALK_TYPE, DTMISS) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_PAGE_WALK_TYPE, ITMISS),
+ .shared = 1,
.cntr = { {0, -1, -1}, {2, -1, -1} },
},
[P4_EVENT_BSQ_CACHE_REFERENCE] = {
.opcode = P4_OPCODE(P4_EVENT_BSQ_CACHE_REFERENCE),
.escr_msr = { MSR_P4_BSU_ESCR0, MSR_P4_BSU_ESCR1 },
+ .escr_emask =
+ P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_2ndL_HITS) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_2ndL_HITE) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_2ndL_HITM) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_3rdL_HITS) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_3rdL_HITE) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_3rdL_HITM) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_2ndL_MISS) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_3rdL_MISS) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, WR_2ndL_MISS),
.cntr = { {0, -1, -1}, {2, -1, -1} },
},
[P4_EVENT_IOQ_ALLOCATION] = {
.opcode = P4_OPCODE(P4_EVENT_IOQ_ALLOCATION),
.escr_msr = { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 },
+ .escr_emask =
+ P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, DEFAULT) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, ALL_READ) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, ALL_WRITE) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, MEM_UC) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, MEM_WC) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, MEM_WT) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, MEM_WP) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, MEM_WB) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, OWN) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, OTHER) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, PREFETCH),
.cntr = { {0, -1, -1}, {2, -1, -1} },
},
[P4_EVENT_IOQ_ACTIVE_ENTRIES] = { /* shared ESCR */
.opcode = P4_OPCODE(P4_EVENT_IOQ_ACTIVE_ENTRIES),
.escr_msr = { MSR_P4_FSB_ESCR1, MSR_P4_FSB_ESCR1 },
+ .escr_emask =
+ P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, DEFAULT) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, ALL_READ) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, ALL_WRITE) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, MEM_UC) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, MEM_WC) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, MEM_WT) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, MEM_WP) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, MEM_WB) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, OWN) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, OTHER) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, PREFETCH),
.cntr = { {2, -1, -1}, {3, -1, -1} },
},
[P4_EVENT_FSB_DATA_ACTIVITY] = {
.opcode = P4_OPCODE(P4_EVENT_FSB_DATA_ACTIVITY),
.escr_msr = { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 },
+ .escr_emask =
+ P4_ESCR_EMASK_BIT(P4_EVENT_FSB_DATA_ACTIVITY, DRDY_DRV) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_FSB_DATA_ACTIVITY, DRDY_OWN) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_FSB_DATA_ACTIVITY, DRDY_OTHER) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_FSB_DATA_ACTIVITY, DBSY_DRV) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_FSB_DATA_ACTIVITY, DBSY_OWN) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_FSB_DATA_ACTIVITY, DBSY_OTHER),
+ .shared = 1,
.cntr = { {0, -1, -1}, {2, -1, -1} },
},
[P4_EVENT_BSQ_ALLOCATION] = { /* shared ESCR, broken CCCR1 */
.opcode = P4_OPCODE(P4_EVENT_BSQ_ALLOCATION),
.escr_msr = { MSR_P4_BSU_ESCR0, MSR_P4_BSU_ESCR0 },
+ .escr_emask =
+ P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_TYPE0) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_TYPE1) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_LEN0) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_LEN1) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_IO_TYPE) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_LOCK_TYPE) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_CACHE_TYPE) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_SPLIT_TYPE) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_DEM_TYPE) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_ORD_TYPE) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, MEM_TYPE0) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, MEM_TYPE1) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, MEM_TYPE2),
.cntr = { {0, -1, -1}, {1, -1, -1} },
},
[P4_EVENT_BSQ_ACTIVE_ENTRIES] = { /* shared ESCR */
.opcode = P4_OPCODE(P4_EVENT_BSQ_ACTIVE_ENTRIES),
.escr_msr = { MSR_P4_BSU_ESCR1 , MSR_P4_BSU_ESCR1 },
+ .escr_emask =
+ P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_TYPE0) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_TYPE1) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_LEN0) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_LEN1) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_IO_TYPE) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_LOCK_TYPE) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_CACHE_TYPE) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_SPLIT_TYPE) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_DEM_TYPE) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_ORD_TYPE) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, MEM_TYPE0) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, MEM_TYPE1) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, MEM_TYPE2),
.cntr = { {2, -1, -1}, {3, -1, -1} },
},
[P4_EVENT_SSE_INPUT_ASSIST] = {
.opcode = P4_OPCODE(P4_EVENT_SSE_INPUT_ASSIST),
.escr_msr = { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 },
+ .escr_emask =
+ P4_ESCR_EMASK_BIT(P4_EVENT_SSE_INPUT_ASSIST, ALL),
+ .shared = 1,
.cntr = { {8, 9, -1}, {10, 11, -1} },
},
[P4_EVENT_PACKED_SP_UOP] = {
.opcode = P4_OPCODE(P4_EVENT_PACKED_SP_UOP),
.escr_msr = { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 },
+ .escr_emask =
+ P4_ESCR_EMASK_BIT(P4_EVENT_PACKED_SP_UOP, ALL),
+ .shared = 1,
.cntr = { {8, 9, -1}, {10, 11, -1} },
},
[P4_EVENT_PACKED_DP_UOP] = {
.opcode = P4_OPCODE(P4_EVENT_PACKED_DP_UOP),
.escr_msr = { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 },
+ .escr_emask =
+ P4_ESCR_EMASK_BIT(P4_EVENT_PACKED_DP_UOP, ALL),
+ .shared = 1,
.cntr = { {8, 9, -1}, {10, 11, -1} },
},
[P4_EVENT_SCALAR_SP_UOP] = {
.opcode = P4_OPCODE(P4_EVENT_SCALAR_SP_UOP),
.escr_msr = { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 },
+ .escr_emask =
+ P4_ESCR_EMASK_BIT(P4_EVENT_SCALAR_SP_UOP, ALL),
+ .shared = 1,
.cntr = { {8, 9, -1}, {10, 11, -1} },
},
[P4_EVENT_SCALAR_DP_UOP] = {
.opcode = P4_OPCODE(P4_EVENT_SCALAR_DP_UOP),
.escr_msr = { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 },
+ .escr_emask =
+ P4_ESCR_EMASK_BIT(P4_EVENT_SCALAR_DP_UOP, ALL),
+ .shared = 1,
.cntr = { {8, 9, -1}, {10, 11, -1} },
},
[P4_EVENT_64BIT_MMX_UOP] = {
.opcode = P4_OPCODE(P4_EVENT_64BIT_MMX_UOP),
.escr_msr = { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 },
+ .escr_emask =
+ P4_ESCR_EMASK_BIT(P4_EVENT_64BIT_MMX_UOP, ALL),
+ .shared = 1,
.cntr = { {8, 9, -1}, {10, 11, -1} },
},
[P4_EVENT_128BIT_MMX_UOP] = {
.opcode = P4_OPCODE(P4_EVENT_128BIT_MMX_UOP),
.escr_msr = { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 },
+ .escr_emask =
+ P4_ESCR_EMASK_BIT(P4_EVENT_128BIT_MMX_UOP, ALL),
+ .shared = 1,
.cntr = { {8, 9, -1}, {10, 11, -1} },
},
[P4_EVENT_X87_FP_UOP] = {
.opcode = P4_OPCODE(P4_EVENT_X87_FP_UOP),
.escr_msr = { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 },
+ .escr_emask =
+ P4_ESCR_EMASK_BIT(P4_EVENT_X87_FP_UOP, ALL),
+ .shared = 1,
.cntr = { {8, 9, -1}, {10, 11, -1} },
},
[P4_EVENT_TC_MISC] = {
.opcode = P4_OPCODE(P4_EVENT_TC_MISC),
.escr_msr = { MSR_P4_TC_ESCR0, MSR_P4_TC_ESCR1 },
+ .escr_emask =
+ P4_ESCR_EMASK_BIT(P4_EVENT_TC_MISC, FLUSH),
.cntr = { {4, 5, -1}, {6, 7, -1} },
},
[P4_EVENT_GLOBAL_POWER_EVENTS] = {
.opcode = P4_OPCODE(P4_EVENT_GLOBAL_POWER_EVENTS),
.escr_msr = { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 },
+ .escr_emask =
+ P4_ESCR_EMASK_BIT(P4_EVENT_GLOBAL_POWER_EVENTS, RUNNING),
.cntr = { {0, -1, -1}, {2, -1, -1} },
},
[P4_EVENT_TC_MS_XFER] = {
.opcode = P4_OPCODE(P4_EVENT_TC_MS_XFER),
.escr_msr = { MSR_P4_MS_ESCR0, MSR_P4_MS_ESCR1 },
+ .escr_emask =
+ P4_ESCR_EMASK_BIT(P4_EVENT_TC_MS_XFER, CISC),
.cntr = { {4, 5, -1}, {6, 7, -1} },
},
[P4_EVENT_UOP_QUEUE_WRITES] = {
.opcode = P4_OPCODE(P4_EVENT_UOP_QUEUE_WRITES),
.escr_msr = { MSR_P4_MS_ESCR0, MSR_P4_MS_ESCR1 },
+ .escr_emask =
+ P4_ESCR_EMASK_BIT(P4_EVENT_UOP_QUEUE_WRITES, FROM_TC_BUILD) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_UOP_QUEUE_WRITES, FROM_TC_DELIVER) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_UOP_QUEUE_WRITES, FROM_ROM),
.cntr = { {4, 5, -1}, {6, 7, -1} },
},
[P4_EVENT_RETIRED_MISPRED_BRANCH_TYPE] = {
.opcode = P4_OPCODE(P4_EVENT_RETIRED_MISPRED_BRANCH_TYPE),
.escr_msr = { MSR_P4_TBPU_ESCR0 , MSR_P4_TBPU_ESCR0 },
+ .escr_emask =
+ P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_MISPRED_BRANCH_TYPE, CONDITIONAL) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_MISPRED_BRANCH_TYPE, CALL) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_MISPRED_BRANCH_TYPE, RETURN) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_MISPRED_BRANCH_TYPE, INDIRECT),
.cntr = { {4, 5, -1}, {6, 7, -1} },
},
[P4_EVENT_RETIRED_BRANCH_TYPE] = {
.opcode = P4_OPCODE(P4_EVENT_RETIRED_BRANCH_TYPE),
.escr_msr = { MSR_P4_TBPU_ESCR0 , MSR_P4_TBPU_ESCR1 },
+ .escr_emask =
+ P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_BRANCH_TYPE, CONDITIONAL) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_BRANCH_TYPE, CALL) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_BRANCH_TYPE, RETURN) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_BRANCH_TYPE, INDIRECT),
.cntr = { {4, 5, -1}, {6, 7, -1} },
},
[P4_EVENT_RESOURCE_STALL] = {
.opcode = P4_OPCODE(P4_EVENT_RESOURCE_STALL),
.escr_msr = { MSR_P4_ALF_ESCR0, MSR_P4_ALF_ESCR1 },
+ .escr_emask =
+ P4_ESCR_EMASK_BIT(P4_EVENT_RESOURCE_STALL, SBFULL),
.cntr = { {12, 13, 16}, {14, 15, 17} },
},
[P4_EVENT_WC_BUFFER] = {
.opcode = P4_OPCODE(P4_EVENT_WC_BUFFER),
.escr_msr = { MSR_P4_DAC_ESCR0, MSR_P4_DAC_ESCR1 },
+ .escr_emask =
+ P4_ESCR_EMASK_BIT(P4_EVENT_WC_BUFFER, WCB_EVICTS) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_WC_BUFFER, WCB_FULL_EVICTS),
+ .shared = 1,
.cntr = { {8, 9, -1}, {10, 11, -1} },
},
[P4_EVENT_B2B_CYCLES] = {
.opcode = P4_OPCODE(P4_EVENT_B2B_CYCLES),
.escr_msr = { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 },
+ .escr_emask = 0,
.cntr = { {0, -1, -1}, {2, -1, -1} },
},
[P4_EVENT_BNR] = {
.opcode = P4_OPCODE(P4_EVENT_BNR),
.escr_msr = { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 },
+ .escr_emask = 0,
.cntr = { {0, -1, -1}, {2, -1, -1} },
},
[P4_EVENT_SNOOP] = {
.opcode = P4_OPCODE(P4_EVENT_SNOOP),
.escr_msr = { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 },
+ .escr_emask = 0,
.cntr = { {0, -1, -1}, {2, -1, -1} },
},
[P4_EVENT_RESPONSE] = {
.opcode = P4_OPCODE(P4_EVENT_RESPONSE),
.escr_msr = { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 },
+ .escr_emask = 0,
.cntr = { {0, -1, -1}, {2, -1, -1} },
},
[P4_EVENT_FRONT_END_EVENT] = {
.opcode = P4_OPCODE(P4_EVENT_FRONT_END_EVENT),
.escr_msr = { MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR3 },
+ .escr_emask =
+ P4_ESCR_EMASK_BIT(P4_EVENT_FRONT_END_EVENT, NBOGUS) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_FRONT_END_EVENT, BOGUS),
.cntr = { {12, 13, 16}, {14, 15, 17} },
},
[P4_EVENT_EXECUTION_EVENT] = {
.opcode = P4_OPCODE(P4_EVENT_EXECUTION_EVENT),
.escr_msr = { MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR3 },
+ .escr_emask =
+ P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS0) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS1) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS2) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS3) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS0) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS1) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS2) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS3),
.cntr = { {12, 13, 16}, {14, 15, 17} },
},
[P4_EVENT_REPLAY_EVENT] = {
.opcode = P4_OPCODE(P4_EVENT_REPLAY_EVENT),
.escr_msr = { MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR3 },
+ .escr_emask =
+ P4_ESCR_EMASK_BIT(P4_EVENT_REPLAY_EVENT, NBOGUS) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_REPLAY_EVENT, BOGUS),
.cntr = { {12, 13, 16}, {14, 15, 17} },
},
[P4_EVENT_INSTR_RETIRED] = {
.opcode = P4_OPCODE(P4_EVENT_INSTR_RETIRED),
.escr_msr = { MSR_P4_CRU_ESCR0, MSR_P4_CRU_ESCR1 },
+ .escr_emask =
+ P4_ESCR_EMASK_BIT(P4_EVENT_INSTR_RETIRED, NBOGUSNTAG) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_INSTR_RETIRED, NBOGUSTAG) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_INSTR_RETIRED, BOGUSNTAG) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_INSTR_RETIRED, BOGUSTAG),
.cntr = { {12, 13, 16}, {14, 15, 17} },
},
[P4_EVENT_UOPS_RETIRED] = {
.opcode = P4_OPCODE(P4_EVENT_UOPS_RETIRED),
.escr_msr = { MSR_P4_CRU_ESCR0, MSR_P4_CRU_ESCR1 },
+ .escr_emask =
+ P4_ESCR_EMASK_BIT(P4_EVENT_UOPS_RETIRED, NBOGUS) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_UOPS_RETIRED, BOGUS),
.cntr = { {12, 13, 16}, {14, 15, 17} },
},
[P4_EVENT_UOP_TYPE] = {
.opcode = P4_OPCODE(P4_EVENT_UOP_TYPE),
.escr_msr = { MSR_P4_RAT_ESCR0, MSR_P4_RAT_ESCR1 },
+ .escr_emask =
+ P4_ESCR_EMASK_BIT(P4_EVENT_UOP_TYPE, TAGLOADS) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_UOP_TYPE, TAGSTORES),
.cntr = { {12, 13, 16}, {14, 15, 17} },
},
[P4_EVENT_BRANCH_RETIRED] = {
.opcode = P4_OPCODE(P4_EVENT_BRANCH_RETIRED),
.escr_msr = { MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR3 },
+ .escr_emask =
+ P4_ESCR_EMASK_BIT(P4_EVENT_BRANCH_RETIRED, MMNP) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_BRANCH_RETIRED, MMNM) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_BRANCH_RETIRED, MMTP) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_BRANCH_RETIRED, MMTM),
.cntr = { {12, 13, 16}, {14, 15, 17} },
},
[P4_EVENT_MISPRED_BRANCH_RETIRED] = {
.opcode = P4_OPCODE(P4_EVENT_MISPRED_BRANCH_RETIRED),
.escr_msr = { MSR_P4_CRU_ESCR0, MSR_P4_CRU_ESCR1 },
+ .escr_emask =
+ P4_ESCR_EMASK_BIT(P4_EVENT_MISPRED_BRANCH_RETIRED, NBOGUS),
.cntr = { {12, 13, 16}, {14, 15, 17} },
},
[P4_EVENT_X87_ASSIST] = {
.opcode = P4_OPCODE(P4_EVENT_X87_ASSIST),
.escr_msr = { MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR3 },
+ .escr_emask =
+ P4_ESCR_EMASK_BIT(P4_EVENT_X87_ASSIST, FPSU) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_X87_ASSIST, FPSO) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_X87_ASSIST, POAO) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_X87_ASSIST, POAU) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_X87_ASSIST, PREA),
.cntr = { {12, 13, 16}, {14, 15, 17} },
},
[P4_EVENT_MACHINE_CLEAR] = {
.opcode = P4_OPCODE(P4_EVENT_MACHINE_CLEAR),
.escr_msr = { MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR3 },
+ .escr_emask =
+ P4_ESCR_EMASK_BIT(P4_EVENT_MACHINE_CLEAR, CLEAR) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_MACHINE_CLEAR, MOCLEAR) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_MACHINE_CLEAR, SMCLEAR),
.cntr = { {12, 13, 16}, {14, 15, 17} },
},
[P4_EVENT_INSTR_COMPLETED] = {
.opcode = P4_OPCODE(P4_EVENT_INSTR_COMPLETED),
.escr_msr = { MSR_P4_CRU_ESCR0, MSR_P4_CRU_ESCR1 },
+ .escr_emask =
+ P4_ESCR_EMASK_BIT(P4_EVENT_INSTR_COMPLETED, NBOGUS) |
+ P4_ESCR_EMASK_BIT(P4_EVENT_INSTR_COMPLETED, BOGUS),
.cntr = { {12, 13, 16}, {14, 15, 17} },
},
};
@@ -428,29 +634,73 @@ static u64 p4_pmu_event_map(int hw_event)
return config;
}
+/* check cpu model specifics */
+static bool p4_event_match_cpu_model(unsigned int event_idx)
+{
+ /* INSTR_COMPLETED event only exist for model 3, 4, 6 (Prescott) */
+ if (event_idx == P4_EVENT_INSTR_COMPLETED) {
+ if (boot_cpu_data.x86_model != 3 &&
+ boot_cpu_data.x86_model != 4 &&
+ boot_cpu_data.x86_model != 6)
+ return false;
+ }
+
+ /*
+ * For info
+ * - IQ_ESCR0, IQ_ESCR1 only for models 1 and 2
+ */
+
+ return true;
+}
+
static int p4_validate_raw_event(struct perf_event *event)
{
- unsigned int v;
+ unsigned int v, emask;
- /* user data may have out-of-bound event index */
+ /* User data may have out-of-bound event index */
v = p4_config_unpack_event(event->attr.config);
- if (v >= ARRAY_SIZE(p4_event_bind_map)) {
- pr_warning("P4 PMU: Unknown event code: %d\n", v);
+ if (v >= ARRAY_SIZE(p4_event_bind_map))
+ return -EINVAL;
+
+ /* It may be unsupported: */
+ if (!p4_event_match_cpu_model(v))
return -EINVAL;
+
+ /*
+ * NOTE: P4_CCCR_THREAD_ANY has not the same meaning as
+ * in Architectural Performance Monitoring, it means not
+ * on _which_ logical cpu to count but rather _when_, ie it
+ * depends on logical cpu state -- count event if one cpu active,
+ * none, both or any, so we just allow user to pass any value
+ * desired.
+ *
+ * In turn we always set Tx_OS/Tx_USR bits bound to logical
+ * cpu without their propagation to another cpu
+ */
+
+ /*
+ * if an event is shared accross the logical threads
+ * the user needs special permissions to be able to use it
+ */
+ if (p4_event_bind_map[v].shared) {
+ if (perf_paranoid_cpu() && !capable(CAP_SYS_ADMIN))
+ return -EACCES;
}
+ /* ESCR EventMask bits may be invalid */
+ emask = p4_config_unpack_escr(event->attr.config) & P4_ESCR_EVENTMASK_MASK;
+ if (emask & ~p4_event_bind_map[v].escr_emask)
+ return -EINVAL;
+
/*
- * it may have some screwed PEBS bits
+ * it may have some invalid PEBS bits
*/
- if (p4_config_pebs_has(event->attr.config, P4_PEBS_CONFIG_ENABLE)) {
- pr_warning("P4 PMU: PEBS are not supported yet\n");
+ if (p4_config_pebs_has(event->attr.config, P4_PEBS_CONFIG_ENABLE))
return -EINVAL;
- }
+
v = p4_config_unpack_metric(event->attr.config);
- if (v >= ARRAY_SIZE(p4_pebs_bind_map)) {
- pr_warning("P4 PMU: Unknown metric code: %d\n", v);
+ if (v >= ARRAY_SIZE(p4_pebs_bind_map))
return -EINVAL;
- }
return 0;
}
@@ -478,27 +728,21 @@ static int p4_hw_config(struct perf_event *event)
if (event->attr.type == PERF_TYPE_RAW) {
+ /*
+ * Clear bits we reserve to be managed by kernel itself
+ * and never allowed from a user space
+ */
+ event->attr.config &= P4_CONFIG_MASK;
+
rc = p4_validate_raw_event(event);
if (rc)
goto out;
/*
- * We don't control raw events so it's up to the caller
- * to pass sane values (and we don't count the thread number
- * on HT machine but allow HT-compatible specifics to be
- * passed on)
- *
* Note that for RAW events we allow user to use P4_CCCR_RESERVED
* bits since we keep additional info here (for cache events and etc)
- *
- * XXX: HT wide things should check perf_paranoid_cpu() &&
- * CAP_SYS_ADMIN
*/
- event->hw.config |= event->attr.config &
- (p4_config_pack_escr(P4_ESCR_MASK_HT) |
- p4_config_pack_cccr(P4_CCCR_MASK_HT | P4_CCCR_RESERVED));
-
- event->hw.config &= ~P4_CCCR_FORCE_OVF;
+ event->hw.config |= event->attr.config;
}
rc = x86_setup_perfctr(event);
@@ -660,8 +904,12 @@ static int p4_pmu_handle_irq(struct pt_regs *regs)
for (idx = 0; idx < x86_pmu.num_counters; idx++) {
int overflow;
- if (!test_bit(idx, cpuc->active_mask))
+ if (!test_bit(idx, cpuc->active_mask)) {
+ /* catch in-flight IRQs */
+ if (__test_and_clear_bit(idx, cpuc->running))
+ handled++;
continue;
+ }
event = cpuc->events[idx];
hwc = &event->hw;
diff --git a/arch/x86/kernel/cpu/perfctr-watchdog.c b/arch/x86/kernel/cpu/perfctr-watchdog.c
index fb329e9f8494..d9f4ff8fcd69 100644
--- a/arch/x86/kernel/cpu/perfctr-watchdog.c
+++ b/arch/x86/kernel/cpu/perfctr-watchdog.c
@@ -700,11 +700,10 @@ static void probe_nmi_watchdog(void)
{
switch (boot_cpu_data.x86_vendor) {
case X86_VENDOR_AMD:
- if (boot_cpu_data.x86 != 6 && boot_cpu_data.x86 != 15 &&
- boot_cpu_data.x86 != 16 && boot_cpu_data.x86 != 17)
- return;
- wd_ops = &k7_wd_ops;
- break;
+ if (boot_cpu_data.x86 == 6 ||
+ (boot_cpu_data.x86 >= 0xf && boot_cpu_data.x86 <= 0x15))
+ wd_ops = &k7_wd_ops;
+ return;
case X86_VENDOR_INTEL:
/* Work around where perfctr1 doesn't have a working enable
* bit as described in the following errata:
diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c
index d49079515122..c7f64e6f537a 100644
--- a/arch/x86/kernel/cpu/scattered.c
+++ b/arch/x86/kernel/cpu/scattered.c
@@ -44,6 +44,12 @@ void __cpuinit init_scattered_cpuid_features(struct cpuinfo_x86 *c)
{ X86_FEATURE_LBRV, CR_EDX, 1, 0x8000000a, 0 },
{ X86_FEATURE_SVML, CR_EDX, 2, 0x8000000a, 0 },
{ X86_FEATURE_NRIPS, CR_EDX, 3, 0x8000000a, 0 },
+ { X86_FEATURE_TSCRATEMSR, CR_EDX, 4, 0x8000000a, 0 },
+ { X86_FEATURE_VMCBCLEAN, CR_EDX, 5, 0x8000000a, 0 },
+ { X86_FEATURE_FLUSHBYASID, CR_EDX, 6, 0x8000000a, 0 },
+ { X86_FEATURE_DECODEASSISTS, CR_EDX, 7, 0x8000000a, 0 },
+ { X86_FEATURE_PAUSEFILTER, CR_EDX,10, 0x8000000a, 0 },
+ { X86_FEATURE_PFTHRESHOLD, CR_EDX,12, 0x8000000a, 0 },
{ 0, 0, 0, 0, 0 }
};
diff --git a/arch/x86/kernel/crash_dump_64.c b/arch/x86/kernel/crash_dump_64.c
index 045b36cada65..994828899e09 100644
--- a/arch/x86/kernel/crash_dump_64.c
+++ b/arch/x86/kernel/crash_dump_64.c
@@ -34,7 +34,7 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
if (!csize)
return 0;
- vaddr = ioremap(pfn << PAGE_SHIFT, PAGE_SIZE);
+ vaddr = ioremap_cache(pfn << PAGE_SHIFT, PAGE_SIZE);
if (!vaddr)
return -ENOMEM;
@@ -46,6 +46,7 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
} else
memcpy(buf, vaddr + offset, csize);
+ set_iounmap_nonlazy();
iounmap(vaddr);
return csize;
}
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
index 0d6fc71bedb1..0c2b7ef7a34d 100644
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -15,6 +15,7 @@
#include <linux/pfn.h>
#include <linux/suspend.h>
#include <linux/firmware-map.h>
+#include <linux/memblock.h>
#include <asm/e820.h>
#include <asm/proto.h>
@@ -738,73 +739,7 @@ core_initcall(e820_mark_nvs_memory);
#endif
/*
- * Find a free area with specified alignment in a specific range.
- */
-u64 __init find_e820_area(u64 start, u64 end, u64 size, u64 align)
-{
- int i;
-
- for (i = 0; i < e820.nr_map; i++) {
- struct e820entry *ei = &e820.map[i];
- u64 addr;
- u64 ei_start, ei_last;
-
- if (ei->type != E820_RAM)
- continue;
-
- ei_last = ei->addr + ei->size;
- ei_start = ei->addr;
- addr = find_early_area(ei_start, ei_last, start, end,
- size, align);
-
- if (addr != -1ULL)
- return addr;
- }
- return -1ULL;
-}
-
-u64 __init find_fw_memmap_area(u64 start, u64 end, u64 size, u64 align)
-{
- return find_e820_area(start, end, size, align);
-}
-
-u64 __init get_max_mapped(void)
-{
- u64 end = max_pfn_mapped;
-
- end <<= PAGE_SHIFT;
-
- return end;
-}
-/*
- * Find next free range after *start
- */
-u64 __init find_e820_area_size(u64 start, u64 *sizep, u64 align)
-{
- int i;
-
- for (i = 0; i < e820.nr_map; i++) {
- struct e820entry *ei = &e820.map[i];
- u64 addr;
- u64 ei_start, ei_last;
-
- if (ei->type != E820_RAM)
- continue;
-
- ei_last = ei->addr + ei->size;
- ei_start = ei->addr;
- addr = find_early_area_size(ei_start, ei_last, start,
- sizep, align);
-
- if (addr != -1ULL)
- return addr;
- }
-
- return -1ULL;
-}
-
-/*
- * pre allocated 4k and reserved it in e820
+ * pre allocated 4k and reserved it in memblock and e820_saved
*/
u64 __init early_reserve_e820(u64 startt, u64 sizet, u64 align)
{
@@ -813,8 +748,8 @@ u64 __init early_reserve_e820(u64 startt, u64 sizet, u64 align)
u64 start;
for (start = startt; ; start += size) {
- start = find_e820_area_size(start, &size, align);
- if (!(start + 1))
+ start = memblock_x86_find_in_range_size(start, &size, align);
+ if (start == MEMBLOCK_ERROR)
return 0;
if (size >= sizet)
break;
@@ -830,10 +765,9 @@ u64 __init early_reserve_e820(u64 startt, u64 sizet, u64 align)
addr = round_down(start + size - sizet, align);
if (addr < start)
return 0;
- e820_update_range(addr, sizet, E820_RAM, E820_RESERVED);
+ memblock_x86_reserve_range(addr, addr + sizet, "new next");
e820_update_range_saved(addr, sizet, E820_RAM, E820_RESERVED);
- printk(KERN_INFO "update e820 for early_reserve_e820\n");
- update_e820();
+ printk(KERN_INFO "update e820_saved for early_reserve_e820\n");
update_e820_saved();
return addr;
@@ -895,74 +829,6 @@ unsigned long __init e820_end_of_low_ram_pfn(void)
{
return e820_end_pfn(1UL<<(32 - PAGE_SHIFT), E820_RAM);
}
-/*
- * Finds an active region in the address range from start_pfn to last_pfn and
- * returns its range in ei_startpfn and ei_endpfn for the e820 entry.
- */
-int __init e820_find_active_region(const struct e820entry *ei,
- unsigned long start_pfn,
- unsigned long last_pfn,
- unsigned long *ei_startpfn,
- unsigned long *ei_endpfn)
-{
- u64 align = PAGE_SIZE;
-
- *ei_startpfn = round_up(ei->addr, align) >> PAGE_SHIFT;
- *ei_endpfn = round_down(ei->addr + ei->size, align) >> PAGE_SHIFT;
-
- /* Skip map entries smaller than a page */
- if (*ei_startpfn >= *ei_endpfn)
- return 0;
-
- /* Skip if map is outside the node */
- if (ei->type != E820_RAM || *ei_endpfn <= start_pfn ||
- *ei_startpfn >= last_pfn)
- return 0;
-
- /* Check for overlaps */
- if (*ei_startpfn < start_pfn)
- *ei_startpfn = start_pfn;
- if (*ei_endpfn > last_pfn)
- *ei_endpfn = last_pfn;
-
- return 1;
-}
-
-/* Walk the e820 map and register active regions within a node */
-void __init e820_register_active_regions(int nid, unsigned long start_pfn,
- unsigned long last_pfn)
-{
- unsigned long ei_startpfn;
- unsigned long ei_endpfn;
- int i;
-
- for (i = 0; i < e820.nr_map; i++)
- if (e820_find_active_region(&e820.map[i],
- start_pfn, last_pfn,
- &ei_startpfn, &ei_endpfn))
- add_active_range(nid, ei_startpfn, ei_endpfn);
-}
-
-/*
- * Find the hole size (in bytes) in the memory range.
- * @start: starting address of the memory range to scan
- * @end: ending address of the memory range to scan
- */
-u64 __init e820_hole_size(u64 start, u64 end)
-{
- unsigned long start_pfn = start >> PAGE_SHIFT;
- unsigned long last_pfn = end >> PAGE_SHIFT;
- unsigned long ei_startpfn, ei_endpfn, ram = 0;
- int i;
-
- for (i = 0; i < e820.nr_map; i++) {
- if (e820_find_active_region(&e820.map[i],
- start_pfn, last_pfn,
- &ei_startpfn, &ei_endpfn))
- ram += ei_endpfn - ei_startpfn;
- }
- return end - start - ((u64)ram << PAGE_SHIFT);
-}
static void early_panic(char *msg)
{
@@ -1210,3 +1076,48 @@ void __init setup_memory_map(void)
printk(KERN_INFO "BIOS-provided physical RAM map:\n");
e820_print_map(who);
}
+
+void __init memblock_x86_fill(void)
+{
+ int i;
+ u64 end;
+
+ /*
+ * EFI may have more than 128 entries
+ * We are safe to enable resizing, beause memblock_x86_fill()
+ * is rather later for x86
+ */
+ memblock_can_resize = 1;
+
+ for (i = 0; i < e820.nr_map; i++) {
+ struct e820entry *ei = &e820.map[i];
+
+ end = ei->addr + ei->size;
+ if (end != (resource_size_t)end)
+ continue;
+
+ if (ei->type != E820_RAM && ei->type != E820_RESERVED_KERN)
+ continue;
+
+ memblock_add(ei->addr, ei->size);
+ }
+
+ memblock_analyze();
+ memblock_dump_all();
+}
+
+void __init memblock_find_dma_reserve(void)
+{
+#ifdef CONFIG_X86_64
+ u64 free_size_pfn;
+ u64 mem_size_pfn;
+ /*
+ * need to find out used area below MAX_DMA_PFN
+ * need to use memblock to get free size in [0, MAX_DMA_PFN]
+ * at first, and assume boot_mem will not take below MAX_DMA_PFN
+ */
+ mem_size_pfn = memblock_x86_memory_in_range(0, MAX_DMA_PFN << PAGE_SHIFT) >> PAGE_SHIFT;
+ free_size_pfn = memblock_x86_free_memory_in_range(0, MAX_DMA_PFN << PAGE_SHIFT) >> PAGE_SHIFT;
+ set_dma_reserve(mem_size_pfn - free_size_pfn);
+#endif
+}
diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c
index ebdb85cf2686..76b8cd953dee 100644
--- a/arch/x86/kernel/early-quirks.c
+++ b/arch/x86/kernel/early-quirks.c
@@ -97,7 +97,6 @@ static void __init nvidia_bugs(int num, int slot, int func)
}
#if defined(CONFIG_ACPI) && defined(CONFIG_X86_IO_APIC)
-#if defined(CONFIG_ACPI) && defined(CONFIG_X86_IO_APIC)
static u32 __init ati_ixp4x0_rev(int num, int slot, int func)
{
u32 d;
@@ -115,7 +114,6 @@ static u32 __init ati_ixp4x0_rev(int num, int slot, int func)
d &= 0xff;
return d;
}
-#endif
static void __init ati_bugs(int num, int slot, int func)
{
diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c
index fa99bae75ace..4572f25f9325 100644
--- a/arch/x86/kernel/early_printk.c
+++ b/arch/x86/kernel/early_printk.c
@@ -14,6 +14,7 @@
#include <xen/hvc-console.h>
#include <asm/pci-direct.h>
#include <asm/fixmap.h>
+#include <asm/mrst.h>
#include <asm/pgtable.h>
#include <linux/usb/ehci_def.h>
@@ -239,6 +240,18 @@ static int __init setup_early_printk(char *buf)
if (!strncmp(buf, "xen", 3))
early_console_register(&xenboot_console, keep);
#endif
+#ifdef CONFIG_X86_MRST_EARLY_PRINTK
+ if (!strncmp(buf, "mrst", 4)) {
+ mrst_early_console_init();
+ early_console_register(&early_mrst_console, keep);
+ }
+
+ if (!strncmp(buf, "hsu", 3)) {
+ hsu_early_console_init();
+ early_console_register(&early_hsu_console, keep);
+ }
+
+#endif
buf++;
}
return 0;
diff --git a/arch/x86/kernel/early_printk_mrst.c b/arch/x86/kernel/early_printk_mrst.c
new file mode 100644
index 000000000000..65df603622b2
--- /dev/null
+++ b/arch/x86/kernel/early_printk_mrst.c
@@ -0,0 +1,319 @@
+/*
+ * early_printk_mrst.c - early consoles for Intel MID platforms
+ *
+ * Copyright (c) 2008-2010, Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+/*
+ * This file implements two early consoles named mrst and hsu.
+ * mrst is based on Maxim3110 spi-uart device, it exists in both
+ * Moorestown and Medfield platforms, while hsu is based on a High
+ * Speed UART device which only exists in the Medfield platform
+ */
+
+#include <linux/serial_reg.h>
+#include <linux/serial_mfd.h>
+#include <linux/kmsg_dump.h>
+#include <linux/console.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/io.h>
+
+#include <asm/fixmap.h>
+#include <asm/pgtable.h>
+#include <asm/mrst.h>
+
+#define MRST_SPI_TIMEOUT 0x200000
+#define MRST_REGBASE_SPI0 0xff128000
+#define MRST_REGBASE_SPI1 0xff128400
+#define MRST_CLK_SPI0_REG 0xff11d86c
+
+/* Bit fields in CTRLR0 */
+#define SPI_DFS_OFFSET 0
+
+#define SPI_FRF_OFFSET 4
+#define SPI_FRF_SPI 0x0
+#define SPI_FRF_SSP 0x1
+#define SPI_FRF_MICROWIRE 0x2
+#define SPI_FRF_RESV 0x3
+
+#define SPI_MODE_OFFSET 6
+#define SPI_SCPH_OFFSET 6
+#define SPI_SCOL_OFFSET 7
+#define SPI_TMOD_OFFSET 8
+#define SPI_TMOD_TR 0x0 /* xmit & recv */
+#define SPI_TMOD_TO 0x1 /* xmit only */
+#define SPI_TMOD_RO 0x2 /* recv only */
+#define SPI_TMOD_EPROMREAD 0x3 /* eeprom read mode */
+
+#define SPI_SLVOE_OFFSET 10
+#define SPI_SRL_OFFSET 11
+#define SPI_CFS_OFFSET 12
+
+/* Bit fields in SR, 7 bits */
+#define SR_MASK 0x7f /* cover 7 bits */
+#define SR_BUSY (1 << 0)
+#define SR_TF_NOT_FULL (1 << 1)
+#define SR_TF_EMPT (1 << 2)
+#define SR_RF_NOT_EMPT (1 << 3)
+#define SR_RF_FULL (1 << 4)
+#define SR_TX_ERR (1 << 5)
+#define SR_DCOL (1 << 6)
+
+struct dw_spi_reg {
+ u32 ctrl0;
+ u32 ctrl1;
+ u32 ssienr;
+ u32 mwcr;
+ u32 ser;
+ u32 baudr;
+ u32 txfltr;
+ u32 rxfltr;
+ u32 txflr;
+ u32 rxflr;
+ u32 sr;
+ u32 imr;
+ u32 isr;
+ u32 risr;
+ u32 txoicr;
+ u32 rxoicr;
+ u32 rxuicr;
+ u32 msticr;
+ u32 icr;
+ u32 dmacr;
+ u32 dmatdlr;
+ u32 dmardlr;
+ u32 idr;
+ u32 version;
+
+ /* Currently operates as 32 bits, though only the low 16 bits matter */
+ u32 dr;
+} __packed;
+
+#define dw_readl(dw, name) __raw_readl(&(dw)->name)
+#define dw_writel(dw, name, val) __raw_writel((val), &(dw)->name)
+
+/* Default use SPI0 register for mrst, we will detect Penwell and use SPI1 */
+static unsigned long mrst_spi_paddr = MRST_REGBASE_SPI0;
+
+static u32 *pclk_spi0;
+/* Always contains an accessable address, start with 0 */
+static struct dw_spi_reg *pspi;
+
+static struct kmsg_dumper dw_dumper;
+static int dumper_registered;
+
+static void dw_kmsg_dump(struct kmsg_dumper *dumper,
+ enum kmsg_dump_reason reason,
+ const char *s1, unsigned long l1,
+ const char *s2, unsigned long l2)
+{
+ int i;
+
+ /* When run to this, we'd better re-init the HW */
+ mrst_early_console_init();
+
+ for (i = 0; i < l1; i++)
+ early_mrst_console.write(&early_mrst_console, s1 + i, 1);
+ for (i = 0; i < l2; i++)
+ early_mrst_console.write(&early_mrst_console, s2 + i, 1);
+}
+
+/* Set the ratio rate to 115200, 8n1, IRQ disabled */
+static void max3110_write_config(void)
+{
+ u16 config;
+
+ config = 0xc001;
+ dw_writel(pspi, dr, config);
+}
+
+/* Translate char to a eligible word and send to max3110 */
+static void max3110_write_data(char c)
+{
+ u16 data;
+
+ data = 0x8000 | c;
+ dw_writel(pspi, dr, data);
+}
+
+void mrst_early_console_init(void)
+{
+ u32 ctrlr0 = 0;
+ u32 spi0_cdiv;
+ u32 freq; /* Freqency info only need be searched once */
+
+ /* Base clk is 100 MHz, the actual clk = 100M / (clk_divider + 1) */
+ pclk_spi0 = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE,
+ MRST_CLK_SPI0_REG);
+ spi0_cdiv = ((*pclk_spi0) & 0xe00) >> 9;
+ freq = 100000000 / (spi0_cdiv + 1);
+
+ if (mrst_identify_cpu() == MRST_CPU_CHIP_PENWELL)
+ mrst_spi_paddr = MRST_REGBASE_SPI1;
+
+ pspi = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE,
+ mrst_spi_paddr);
+
+ /* Disable SPI controller */
+ dw_writel(pspi, ssienr, 0);
+
+ /* Set control param, 8 bits, transmit only mode */
+ ctrlr0 = dw_readl(pspi, ctrl0);
+
+ ctrlr0 &= 0xfcc0;
+ ctrlr0 |= 0xf | (SPI_FRF_SPI << SPI_FRF_OFFSET)
+ | (SPI_TMOD_TO << SPI_TMOD_OFFSET);
+ dw_writel(pspi, ctrl0, ctrlr0);
+
+ /*
+ * Change the spi0 clk to comply with 115200 bps, use 100000 to
+ * calculate the clk dividor to make the clock a little slower
+ * than real baud rate.
+ */
+ dw_writel(pspi, baudr, freq/100000);
+
+ /* Disable all INT for early phase */
+ dw_writel(pspi, imr, 0x0);
+
+ /* Set the cs to spi-uart */
+ dw_writel(pspi, ser, 0x2);
+
+ /* Enable the HW, the last step for HW init */
+ dw_writel(pspi, ssienr, 0x1);
+
+ /* Set the default configuration */
+ max3110_write_config();
+
+ /* Register the kmsg dumper */
+ if (!dumper_registered) {
+ dw_dumper.dump = dw_kmsg_dump;
+ kmsg_dump_register(&dw_dumper);
+ dumper_registered = 1;
+ }
+}
+
+/* Slave select should be called in the read/write function */
+static void early_mrst_spi_putc(char c)
+{
+ unsigned int timeout;
+ u32 sr;
+
+ timeout = MRST_SPI_TIMEOUT;
+ /* Early putc needs to make sure the TX FIFO is not full */
+ while (--timeout) {
+ sr = dw_readl(pspi, sr);
+ if (!(sr & SR_TF_NOT_FULL))
+ cpu_relax();
+ else
+ break;
+ }
+
+ if (!timeout)
+ pr_warning("MRST earlycon: timed out\n");
+ else
+ max3110_write_data(c);
+}
+
+/* Early SPI only uses polling mode */
+static void early_mrst_spi_write(struct console *con, const char *str, unsigned n)
+{
+ int i;
+
+ for (i = 0; i < n && *str; i++) {
+ if (*str == '\n')
+ early_mrst_spi_putc('\r');
+ early_mrst_spi_putc(*str);
+ str++;
+ }
+}
+
+struct console early_mrst_console = {
+ .name = "earlymrst",
+ .write = early_mrst_spi_write,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+};
+
+/*
+ * Following is the early console based on Medfield HSU (High
+ * Speed UART) device.
+ */
+#define HSU_PORT2_PADDR 0xffa28180
+
+static void __iomem *phsu;
+
+void hsu_early_console_init(void)
+{
+ u8 lcr;
+
+ phsu = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE,
+ HSU_PORT2_PADDR);
+
+ /* Disable FIFO */
+ writeb(0x0, phsu + UART_FCR);
+
+ /* Set to default 115200 bps, 8n1 */
+ lcr = readb(phsu + UART_LCR);
+ writeb((0x80 | lcr), phsu + UART_LCR);
+ writeb(0x18, phsu + UART_DLL);
+ writeb(lcr, phsu + UART_LCR);
+ writel(0x3600, phsu + UART_MUL*4);
+
+ writeb(0x8, phsu + UART_MCR);
+ writeb(0x7, phsu + UART_FCR);
+ writeb(0x3, phsu + UART_LCR);
+
+ /* Clear IRQ status */
+ readb(phsu + UART_LSR);
+ readb(phsu + UART_RX);
+ readb(phsu + UART_IIR);
+ readb(phsu + UART_MSR);
+
+ /* Enable FIFO */
+ writeb(0x7, phsu + UART_FCR);
+}
+
+#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
+
+static void early_hsu_putc(char ch)
+{
+ unsigned int timeout = 10000; /* 10ms */
+ u8 status;
+
+ while (--timeout) {
+ status = readb(phsu + UART_LSR);
+ if (status & BOTH_EMPTY)
+ break;
+ udelay(1);
+ }
+
+ /* Only write the char when there was no timeout */
+ if (timeout)
+ writeb(ch, phsu + UART_TX);
+}
+
+static void early_hsu_write(struct console *con, const char *str, unsigned n)
+{
+ int i;
+
+ for (i = 0; i < n && *str; i++) {
+ if (*str == '\n')
+ early_hsu_putc('\r');
+ early_hsu_putc(*str);
+ str++;
+ }
+}
+
+struct console early_hsu_console = {
+ .name = "earlyhsu",
+ .write = early_hsu_write,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+};
diff --git a/arch/x86/kernel/efi.c b/arch/x86/kernel/efi.c
index c2fa9b8b497e..0fe27d7c6258 100644
--- a/arch/x86/kernel/efi.c
+++ b/arch/x86/kernel/efi.c
@@ -30,6 +30,7 @@
#include <linux/init.h>
#include <linux/efi.h>
#include <linux/bootmem.h>
+#include <linux/memblock.h>
#include <linux/spinlock.h>
#include <linux/uaccess.h>
#include <linux/time.h>
@@ -275,7 +276,7 @@ static void __init do_add_efi_memmap(void)
sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
}
-void __init efi_reserve_early(void)
+void __init efi_memblock_x86_reserve_range(void)
{
unsigned long pmap;
@@ -290,7 +291,7 @@ void __init efi_reserve_early(void)
boot_params.efi_info.efi_memdesc_size;
memmap.desc_version = boot_params.efi_info.efi_memdesc_version;
memmap.desc_size = boot_params.efi_info.efi_memdesc_size;
- reserve_early(pmap, pmap + memmap.nr_map * memmap.desc_size,
+ memblock_x86_reserve_range(pmap, pmap + memmap.nr_map * memmap.desc_size,
"EFI memmap");
}
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
index 227d00920d2f..59e175e89599 100644
--- a/arch/x86/kernel/entry_32.S
+++ b/arch/x86/kernel/entry_32.S
@@ -115,8 +115,7 @@
/* unfortunately push/pop can't be no-op */
.macro PUSH_GS
- pushl $0
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi $0
.endm
.macro POP_GS pop=0
addl $(4 + \pop), %esp
@@ -140,14 +139,12 @@
#else /* CONFIG_X86_32_LAZY_GS */
.macro PUSH_GS
- pushl %gs
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi %gs
/*CFI_REL_OFFSET gs, 0*/
.endm
.macro POP_GS pop=0
-98: popl %gs
- CFI_ADJUST_CFA_OFFSET -4
+98: popl_cfi %gs
/*CFI_RESTORE gs*/
.if \pop <> 0
add $\pop, %esp
@@ -195,35 +192,25 @@
.macro SAVE_ALL
cld
PUSH_GS
- pushl %fs
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi %fs
/*CFI_REL_OFFSET fs, 0;*/
- pushl %es
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi %es
/*CFI_REL_OFFSET es, 0;*/
- pushl %ds
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi %ds
/*CFI_REL_OFFSET ds, 0;*/
- pushl %eax
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi %eax
CFI_REL_OFFSET eax, 0
- pushl %ebp
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi %ebp
CFI_REL_OFFSET ebp, 0
- pushl %edi
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi %edi
CFI_REL_OFFSET edi, 0
- pushl %esi
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi %esi
CFI_REL_OFFSET esi, 0
- pushl %edx
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi %edx
CFI_REL_OFFSET edx, 0
- pushl %ecx
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi %ecx
CFI_REL_OFFSET ecx, 0
- pushl %ebx
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi %ebx
CFI_REL_OFFSET ebx, 0
movl $(__USER_DS), %edx
movl %edx, %ds
@@ -234,39 +221,29 @@
.endm
.macro RESTORE_INT_REGS
- popl %ebx
- CFI_ADJUST_CFA_OFFSET -4
+ popl_cfi %ebx
CFI_RESTORE ebx
- popl %ecx
- CFI_ADJUST_CFA_OFFSET -4
+ popl_cfi %ecx
CFI_RESTORE ecx
- popl %edx
- CFI_ADJUST_CFA_OFFSET -4
+ popl_cfi %edx
CFI_RESTORE edx
- popl %esi
- CFI_ADJUST_CFA_OFFSET -4
+ popl_cfi %esi
CFI_RESTORE esi
- popl %edi
- CFI_ADJUST_CFA_OFFSET -4
+ popl_cfi %edi
CFI_RESTORE edi
- popl %ebp
- CFI_ADJUST_CFA_OFFSET -4
+ popl_cfi %ebp
CFI_RESTORE ebp
- popl %eax
- CFI_ADJUST_CFA_OFFSET -4
+ popl_cfi %eax
CFI_RESTORE eax
.endm
.macro RESTORE_REGS pop=0
RESTORE_INT_REGS
-1: popl %ds
- CFI_ADJUST_CFA_OFFSET -4
+1: popl_cfi %ds
/*CFI_RESTORE ds;*/
-2: popl %es
- CFI_ADJUST_CFA_OFFSET -4
+2: popl_cfi %es
/*CFI_RESTORE es;*/
-3: popl %fs
- CFI_ADJUST_CFA_OFFSET -4
+3: popl_cfi %fs
/*CFI_RESTORE fs;*/
POP_GS \pop
.pushsection .fixup, "ax"
@@ -320,16 +297,12 @@
ENTRY(ret_from_fork)
CFI_STARTPROC
- pushl %eax
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi %eax
call schedule_tail
GET_THREAD_INFO(%ebp)
- popl %eax
- CFI_ADJUST_CFA_OFFSET -4
- pushl $0x0202 # Reset kernel eflags
- CFI_ADJUST_CFA_OFFSET 4
- popfl
- CFI_ADJUST_CFA_OFFSET -4
+ popl_cfi %eax
+ pushl_cfi $0x0202 # Reset kernel eflags
+ popfl_cfi
jmp syscall_exit
CFI_ENDPROC
END(ret_from_fork)
@@ -409,29 +382,23 @@ sysenter_past_esp:
* enough kernel state to call TRACE_IRQS_OFF can be called - but
* we immediately enable interrupts at that point anyway.
*/
- pushl $(__USER_DS)
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi $__USER_DS
/*CFI_REL_OFFSET ss, 0*/
- pushl %ebp
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi %ebp
CFI_REL_OFFSET esp, 0
- pushfl
+ pushfl_cfi
orl $X86_EFLAGS_IF, (%esp)
- CFI_ADJUST_CFA_OFFSET 4
- pushl $(__USER_CS)
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi $__USER_CS
/*CFI_REL_OFFSET cs, 0*/
/*
* Push current_thread_info()->sysenter_return to the stack.
* A tiny bit of offset fixup is necessary - 4*4 means the 4 words
* pushed above; +8 corresponds to copy_thread's esp0 setting.
*/
- pushl (TI_sysenter_return-THREAD_SIZE+8+4*4)(%esp)
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi (TI_sysenter_return-THREAD_SIZE_asm+8+4*4)(%esp)
CFI_REL_OFFSET eip, 0
- pushl %eax
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi %eax
SAVE_ALL
ENABLE_INTERRUPTS(CLBR_NONE)
@@ -486,8 +453,7 @@ sysenter_audit:
movl %eax,%edx /* 2nd arg: syscall number */
movl $AUDIT_ARCH_I386,%eax /* 1st arg: audit arch */
call audit_syscall_entry
- pushl %ebx
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi %ebx
movl PT_EAX(%esp),%eax /* reload syscall number */
jmp sysenter_do_call
@@ -529,8 +495,7 @@ ENDPROC(ia32_sysenter_target)
# system call handler stub
ENTRY(system_call)
RING0_INT_FRAME # can't unwind into user space anyway
- pushl %eax # save orig_eax
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi %eax # save orig_eax
SAVE_ALL
GET_THREAD_INFO(%ebp)
# system call tracing in operation / emulation
@@ -566,7 +531,6 @@ restore_all_notrace:
je ldt_ss # returning to user-space with LDT SS
restore_nocheck:
RESTORE_REGS 4 # skip orig_eax/error_code
- CFI_ADJUST_CFA_OFFSET -4
irq_return:
INTERRUPT_RETURN
.section .fixup,"ax"
@@ -619,10 +583,8 @@ ldt_ss:
shr $16, %edx
mov %dl, GDT_ESPFIX_SS + 4 /* bits 16..23 */
mov %dh, GDT_ESPFIX_SS + 7 /* bits 24..31 */
- pushl $__ESPFIX_SS
- CFI_ADJUST_CFA_OFFSET 4
- push %eax /* new kernel esp */
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi $__ESPFIX_SS
+ pushl_cfi %eax /* new kernel esp */
/* Disable interrupts, but do not irqtrace this section: we
* will soon execute iret and the tracer was already set to
* the irqstate after the iret */
@@ -666,11 +628,9 @@ work_notifysig: # deal with pending signals and
ALIGN
work_notifysig_v86:
- pushl %ecx # save ti_flags for do_notify_resume
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi %ecx # save ti_flags for do_notify_resume
call save_v86_state # %eax contains pt_regs pointer
- popl %ecx
- CFI_ADJUST_CFA_OFFSET -4
+ popl_cfi %ecx
movl %eax, %esp
#else
movl %esp, %eax
@@ -750,14 +710,18 @@ ptregs_##name: \
#define PTREGSCALL3(name) \
ALIGN; \
ptregs_##name: \
+ CFI_STARTPROC; \
leal 4(%esp),%eax; \
- pushl %eax; \
+ pushl_cfi %eax; \
movl PT_EDX(%eax),%ecx; \
movl PT_ECX(%eax),%edx; \
movl PT_EBX(%eax),%eax; \
call sys_##name; \
addl $4,%esp; \
- ret
+ CFI_ADJUST_CFA_OFFSET -4; \
+ ret; \
+ CFI_ENDPROC; \
+ENDPROC(ptregs_##name)
PTREGSCALL1(iopl)
PTREGSCALL0(fork)
@@ -772,15 +736,19 @@ PTREGSCALL1(vm86old)
/* Clone is an oddball. The 4th arg is in %edi */
ALIGN;
ptregs_clone:
+ CFI_STARTPROC
leal 4(%esp),%eax
- pushl %eax
- pushl PT_EDI(%eax)
+ pushl_cfi %eax
+ pushl_cfi PT_EDI(%eax)
movl PT_EDX(%eax),%ecx
movl PT_ECX(%eax),%edx
movl PT_EBX(%eax),%eax
call sys_clone
addl $8,%esp
+ CFI_ADJUST_CFA_OFFSET -8
ret
+ CFI_ENDPROC
+ENDPROC(ptregs_clone)
.macro FIXUP_ESPFIX_STACK
/*
@@ -795,10 +763,8 @@ ptregs_clone:
mov GDT_ESPFIX_SS + 7, %ah /* bits 24..31 */
shl $16, %eax
addl %esp, %eax /* the adjusted stack pointer */
- pushl $__KERNEL_DS
- CFI_ADJUST_CFA_OFFSET 4
- pushl %eax
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi $__KERNEL_DS
+ pushl_cfi %eax
lss (%esp), %esp /* switch to the normal stack segment */
CFI_ADJUST_CFA_OFFSET -8
.endm
@@ -835,8 +801,7 @@ vector=FIRST_EXTERNAL_VECTOR
.if vector <> FIRST_EXTERNAL_VECTOR
CFI_ADJUST_CFA_OFFSET -4
.endif
-1: pushl $(~vector+0x80) /* Note: always in signed byte range */
- CFI_ADJUST_CFA_OFFSET 4
+1: pushl_cfi $(~vector+0x80) /* Note: always in signed byte range */
.if ((vector-FIRST_EXTERNAL_VECTOR)%7) <> 6
jmp 2f
.endif
@@ -876,8 +841,7 @@ ENDPROC(common_interrupt)
#define BUILD_INTERRUPT3(name, nr, fn) \
ENTRY(name) \
RING0_INT_FRAME; \
- pushl $~(nr); \
- CFI_ADJUST_CFA_OFFSET 4; \
+ pushl_cfi $~(nr); \
SAVE_ALL; \
TRACE_IRQS_OFF \
movl %esp,%eax; \
@@ -893,21 +857,18 @@ ENDPROC(name)
ENTRY(coprocessor_error)
RING0_INT_FRAME
- pushl $0
- CFI_ADJUST_CFA_OFFSET 4
- pushl $do_coprocessor_error
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi $0
+ pushl_cfi $do_coprocessor_error
jmp error_code
CFI_ENDPROC
END(coprocessor_error)
ENTRY(simd_coprocessor_error)
RING0_INT_FRAME
- pushl $0
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi $0
#ifdef CONFIG_X86_INVD_BUG
/* AMD 486 bug: invd from userspace calls exception 19 instead of #GP */
-661: pushl $do_general_protection
+661: pushl_cfi $do_general_protection
662:
.section .altinstructions,"a"
.balign 4
@@ -922,19 +883,16 @@ ENTRY(simd_coprocessor_error)
664:
.previous
#else
- pushl $do_simd_coprocessor_error
+ pushl_cfi $do_simd_coprocessor_error
#endif
- CFI_ADJUST_CFA_OFFSET 4
jmp error_code
CFI_ENDPROC
END(simd_coprocessor_error)
ENTRY(device_not_available)
RING0_INT_FRAME
- pushl $-1 # mark this as an int
- CFI_ADJUST_CFA_OFFSET 4
- pushl $do_device_not_available
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi $-1 # mark this as an int
+ pushl_cfi $do_device_not_available
jmp error_code
CFI_ENDPROC
END(device_not_available)
@@ -956,82 +914,68 @@ END(native_irq_enable_sysexit)
ENTRY(overflow)
RING0_INT_FRAME
- pushl $0
- CFI_ADJUST_CFA_OFFSET 4
- pushl $do_overflow
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi $0
+ pushl_cfi $do_overflow
jmp error_code
CFI_ENDPROC
END(overflow)
ENTRY(bounds)
RING0_INT_FRAME
- pushl $0
- CFI_ADJUST_CFA_OFFSET 4
- pushl $do_bounds
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi $0
+ pushl_cfi $do_bounds
jmp error_code
CFI_ENDPROC
END(bounds)
ENTRY(invalid_op)
RING0_INT_FRAME
- pushl $0
- CFI_ADJUST_CFA_OFFSET 4
- pushl $do_invalid_op
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi $0
+ pushl_cfi $do_invalid_op
jmp error_code
CFI_ENDPROC
END(invalid_op)
ENTRY(coprocessor_segment_overrun)
RING0_INT_FRAME
- pushl $0
- CFI_ADJUST_CFA_OFFSET 4
- pushl $do_coprocessor_segment_overrun
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi $0
+ pushl_cfi $do_coprocessor_segment_overrun
jmp error_code
CFI_ENDPROC
END(coprocessor_segment_overrun)
ENTRY(invalid_TSS)
RING0_EC_FRAME
- pushl $do_invalid_TSS
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi $do_invalid_TSS
jmp error_code
CFI_ENDPROC
END(invalid_TSS)
ENTRY(segment_not_present)
RING0_EC_FRAME
- pushl $do_segment_not_present
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi $do_segment_not_present
jmp error_code
CFI_ENDPROC
END(segment_not_present)
ENTRY(stack_segment)
RING0_EC_FRAME
- pushl $do_stack_segment
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi $do_stack_segment
jmp error_code
CFI_ENDPROC
END(stack_segment)
ENTRY(alignment_check)
RING0_EC_FRAME
- pushl $do_alignment_check
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi $do_alignment_check
jmp error_code
CFI_ENDPROC
END(alignment_check)
ENTRY(divide_error)
RING0_INT_FRAME
- pushl $0 # no error code
- CFI_ADJUST_CFA_OFFSET 4
- pushl $do_divide_error
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi $0 # no error code
+ pushl_cfi $do_divide_error
jmp error_code
CFI_ENDPROC
END(divide_error)
@@ -1039,10 +983,8 @@ END(divide_error)
#ifdef CONFIG_X86_MCE
ENTRY(machine_check)
RING0_INT_FRAME
- pushl $0
- CFI_ADJUST_CFA_OFFSET 4
- pushl machine_check_vector
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi $0
+ pushl_cfi machine_check_vector
jmp error_code
CFI_ENDPROC
END(machine_check)
@@ -1050,10 +992,8 @@ END(machine_check)
ENTRY(spurious_interrupt_bug)
RING0_INT_FRAME
- pushl $0
- CFI_ADJUST_CFA_OFFSET 4
- pushl $do_spurious_interrupt_bug
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi $0
+ pushl_cfi $do_spurious_interrupt_bug
jmp error_code
CFI_ENDPROC
END(spurious_interrupt_bug)
@@ -1084,8 +1024,7 @@ ENTRY(xen_sysenter_target)
ENTRY(xen_hypervisor_callback)
CFI_STARTPROC
- pushl $0
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi $0
SAVE_ALL
TRACE_IRQS_OFF
@@ -1121,23 +1060,20 @@ ENDPROC(xen_hypervisor_callback)
# We distinguish between categories by maintaining a status value in EAX.
ENTRY(xen_failsafe_callback)
CFI_STARTPROC
- pushl %eax
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi %eax
movl $1,%eax
1: mov 4(%esp),%ds
2: mov 8(%esp),%es
3: mov 12(%esp),%fs
4: mov 16(%esp),%gs
testl %eax,%eax
- popl %eax
- CFI_ADJUST_CFA_OFFSET -4
+ popl_cfi %eax
lea 16(%esp),%esp
CFI_ADJUST_CFA_OFFSET -16
jz 5f
addl $16,%esp
jmp iret_exc # EAX != 0 => Category 2 (Bad IRET)
-5: pushl $0 # EAX == 0 => Category 1 (Bad segment)
- CFI_ADJUST_CFA_OFFSET 4
+5: pushl_cfi $0 # EAX == 0 => Category 1 (Bad segment)
SAVE_ALL
jmp ret_from_exception
CFI_ENDPROC
@@ -1287,40 +1223,29 @@ syscall_table_size=(.-sys_call_table)
ENTRY(page_fault)
RING0_EC_FRAME
- pushl $do_page_fault
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi $do_page_fault
ALIGN
error_code:
/* the function address is in %gs's slot on the stack */
- pushl %fs
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi %fs
/*CFI_REL_OFFSET fs, 0*/
- pushl %es
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi %es
/*CFI_REL_OFFSET es, 0*/
- pushl %ds
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi %ds
/*CFI_REL_OFFSET ds, 0*/
- pushl %eax
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi %eax
CFI_REL_OFFSET eax, 0
- pushl %ebp
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi %ebp
CFI_REL_OFFSET ebp, 0
- pushl %edi
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi %edi
CFI_REL_OFFSET edi, 0
- pushl %esi
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi %esi
CFI_REL_OFFSET esi, 0
- pushl %edx
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi %edx
CFI_REL_OFFSET edx, 0
- pushl %ecx
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi %ecx
CFI_REL_OFFSET ecx, 0
- pushl %ebx
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi %ebx
CFI_REL_OFFSET ebx, 0
cld
movl $(__KERNEL_PERCPU), %ecx
@@ -1362,12 +1287,9 @@ END(page_fault)
movl TSS_sysenter_sp0 + \offset(%esp), %esp
CFI_DEF_CFA esp, 0
CFI_UNDEFINED eip
- pushfl
- CFI_ADJUST_CFA_OFFSET 4
- pushl $__KERNEL_CS
- CFI_ADJUST_CFA_OFFSET 4
- pushl $sysenter_past_esp
- CFI_ADJUST_CFA_OFFSET 4
+ pushfl_cfi
+ pushl_cfi $__KERNEL_CS
+ pushl_cfi $sysenter_past_esp
CFI_REL_OFFSET eip, 0
.endm
@@ -1377,8 +1299,7 @@ ENTRY(debug)
jne debug_stack_correct
FIX_STACK 12, debug_stack_correct, debug_esp_fix_insn
debug_stack_correct:
- pushl $-1 # mark this as an int
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi $-1 # mark this as an int
SAVE_ALL
TRACE_IRQS_OFF
xorl %edx,%edx # error code 0
@@ -1398,32 +1319,27 @@ END(debug)
*/
ENTRY(nmi)
RING0_INT_FRAME
- pushl %eax
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi %eax
movl %ss, %eax
cmpw $__ESPFIX_SS, %ax
- popl %eax
- CFI_ADJUST_CFA_OFFSET -4
+ popl_cfi %eax
je nmi_espfix_stack
cmpl $ia32_sysenter_target,(%esp)
je nmi_stack_fixup
- pushl %eax
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi %eax
movl %esp,%eax
/* Do not access memory above the end of our stack page,
* it might not exist.
*/
andl $(THREAD_SIZE-1),%eax
cmpl $(THREAD_SIZE-20),%eax
- popl %eax
- CFI_ADJUST_CFA_OFFSET -4
+ popl_cfi %eax
jae nmi_stack_correct
cmpl $ia32_sysenter_target,12(%esp)
je nmi_debug_stack_check
nmi_stack_correct:
/* We have a RING0_INT_FRAME here */
- pushl %eax
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi %eax
SAVE_ALL
xorl %edx,%edx # zero error code
movl %esp,%eax # pt_regs pointer
@@ -1452,18 +1368,14 @@ nmi_espfix_stack:
*
* create the pointer to lss back
*/
- pushl %ss
- CFI_ADJUST_CFA_OFFSET 4
- pushl %esp
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi %ss
+ pushl_cfi %esp
addl $4, (%esp)
/* copy the iret frame of 12 bytes */
.rept 3
- pushl 16(%esp)
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi 16(%esp)
.endr
- pushl %eax
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi %eax
SAVE_ALL
FIXUP_ESPFIX_STACK # %eax == %esp
xorl %edx,%edx # zero error code
@@ -1477,8 +1389,7 @@ END(nmi)
ENTRY(int3)
RING0_INT_FRAME
- pushl $-1 # mark this as an int
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi $-1 # mark this as an int
SAVE_ALL
TRACE_IRQS_OFF
xorl %edx,%edx # zero error code
@@ -1490,8 +1401,7 @@ END(int3)
ENTRY(general_protection)
RING0_EC_FRAME
- pushl $do_general_protection
- CFI_ADJUST_CFA_OFFSET 4
+ pushl_cfi $do_general_protection
jmp error_code
CFI_ENDPROC
END(general_protection)
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index 17be5ec7cbba..fe2690d71c0c 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -213,23 +213,17 @@ ENDPROC(native_usergs_sysret64)
.macro FAKE_STACK_FRAME child_rip
/* push in order ss, rsp, eflags, cs, rip */
xorl %eax, %eax
- pushq $__KERNEL_DS /* ss */
- CFI_ADJUST_CFA_OFFSET 8
+ pushq_cfi $__KERNEL_DS /* ss */
/*CFI_REL_OFFSET ss,0*/
- pushq %rax /* rsp */
- CFI_ADJUST_CFA_OFFSET 8
+ pushq_cfi %rax /* rsp */
CFI_REL_OFFSET rsp,0
- pushq $X86_EFLAGS_IF /* eflags - interrupts on */
- CFI_ADJUST_CFA_OFFSET 8
+ pushq_cfi $X86_EFLAGS_IF /* eflags - interrupts on */
/*CFI_REL_OFFSET rflags,0*/
- pushq $__KERNEL_CS /* cs */
- CFI_ADJUST_CFA_OFFSET 8
+ pushq_cfi $__KERNEL_CS /* cs */
/*CFI_REL_OFFSET cs,0*/
- pushq \child_rip /* rip */
- CFI_ADJUST_CFA_OFFSET 8
+ pushq_cfi \child_rip /* rip */
CFI_REL_OFFSET rip,0
- pushq %rax /* orig rax */
- CFI_ADJUST_CFA_OFFSET 8
+ pushq_cfi %rax /* orig rax */
.endm
.macro UNFAKE_STACK_FRAME
@@ -398,10 +392,8 @@ ENTRY(ret_from_fork)
LOCK ; btr $TIF_FORK,TI_flags(%r8)
- push kernel_eflags(%rip)
- CFI_ADJUST_CFA_OFFSET 8
- popf # reset kernel eflags
- CFI_ADJUST_CFA_OFFSET -8
+ pushq_cfi kernel_eflags(%rip)
+ popfq_cfi # reset kernel eflags
call schedule_tail # rdi: 'prev' task parameter
@@ -521,11 +513,9 @@ sysret_careful:
jnc sysret_signal
TRACE_IRQS_ON
ENABLE_INTERRUPTS(CLBR_NONE)
- pushq %rdi
- CFI_ADJUST_CFA_OFFSET 8
+ pushq_cfi %rdi
call schedule
- popq %rdi
- CFI_ADJUST_CFA_OFFSET -8
+ popq_cfi %rdi
jmp sysret_check
/* Handle a signal */
@@ -634,11 +624,9 @@ int_careful:
jnc int_very_careful
TRACE_IRQS_ON
ENABLE_INTERRUPTS(CLBR_NONE)
- pushq %rdi
- CFI_ADJUST_CFA_OFFSET 8
+ pushq_cfi %rdi
call schedule
- popq %rdi
- CFI_ADJUST_CFA_OFFSET -8
+ popq_cfi %rdi
DISABLE_INTERRUPTS(CLBR_NONE)
TRACE_IRQS_OFF
jmp int_with_check
@@ -652,12 +640,10 @@ int_check_syscall_exit_work:
/* Check for syscall exit trace */
testl $_TIF_WORK_SYSCALL_EXIT,%edx
jz int_signal
- pushq %rdi
- CFI_ADJUST_CFA_OFFSET 8
+ pushq_cfi %rdi
leaq 8(%rsp),%rdi # &ptregs -> arg1
call syscall_trace_leave
- popq %rdi
- CFI_ADJUST_CFA_OFFSET -8
+ popq_cfi %rdi
andl $~(_TIF_WORK_SYSCALL_EXIT|_TIF_SYSCALL_EMU),%edi
jmp int_restore_rest
@@ -714,9 +700,8 @@ END(ptregscall_common)
ENTRY(stub_execve)
CFI_STARTPROC
- popq %r11
- CFI_ADJUST_CFA_OFFSET -8
- CFI_REGISTER rip, r11
+ addq $8, %rsp
+ PARTIAL_FRAME 0
SAVE_REST
FIXUP_TOP_OF_STACK %r11
movq %rsp, %rcx
@@ -735,7 +720,7 @@ END(stub_execve)
ENTRY(stub_rt_sigreturn)
CFI_STARTPROC
addq $8, %rsp
- CFI_ADJUST_CFA_OFFSET -8
+ PARTIAL_FRAME 0
SAVE_REST
movq %rsp,%rdi
FIXUP_TOP_OF_STACK %r11
@@ -766,8 +751,7 @@ vector=FIRST_EXTERNAL_VECTOR
.if vector <> FIRST_EXTERNAL_VECTOR
CFI_ADJUST_CFA_OFFSET -8
.endif
-1: pushq $(~vector+0x80) /* Note: always in signed byte range */
- CFI_ADJUST_CFA_OFFSET 8
+1: pushq_cfi $(~vector+0x80) /* Note: always in signed byte range */
.if ((vector-FIRST_EXTERNAL_VECTOR)%7) <> 6
jmp 2f
.endif
@@ -796,8 +780,8 @@ END(interrupt)
/* 0(%rsp): ~(interrupt number) */
.macro interrupt func
- subq $10*8, %rsp
- CFI_ADJUST_CFA_OFFSET 10*8
+ subq $ORIG_RAX-ARGOFFSET+8, %rsp
+ CFI_ADJUST_CFA_OFFSET ORIG_RAX-ARGOFFSET+8
call save_args
PARTIAL_FRAME 0
call \func
@@ -822,6 +806,7 @@ ret_from_intr:
TRACE_IRQS_OFF
decl PER_CPU_VAR(irq_count)
leaveq
+ CFI_RESTORE rbp
CFI_DEF_CFA_REGISTER rsp
CFI_ADJUST_CFA_OFFSET -8
exit_intr:
@@ -903,11 +888,9 @@ retint_careful:
jnc retint_signal
TRACE_IRQS_ON
ENABLE_INTERRUPTS(CLBR_NONE)
- pushq %rdi
- CFI_ADJUST_CFA_OFFSET 8
+ pushq_cfi %rdi
call schedule
- popq %rdi
- CFI_ADJUST_CFA_OFFSET -8
+ popq_cfi %rdi
GET_THREAD_INFO(%rcx)
DISABLE_INTERRUPTS(CLBR_NONE)
TRACE_IRQS_OFF
@@ -956,8 +939,7 @@ END(common_interrupt)
.macro apicinterrupt num sym do_sym
ENTRY(\sym)
INTR_FRAME
- pushq $~(\num)
- CFI_ADJUST_CFA_OFFSET 8
+ pushq_cfi $~(\num)
interrupt \do_sym
jmp ret_from_intr
CFI_ENDPROC
@@ -981,22 +963,10 @@ apicinterrupt X86_PLATFORM_IPI_VECTOR \
x86_platform_ipi smp_x86_platform_ipi
#ifdef CONFIG_SMP
-apicinterrupt INVALIDATE_TLB_VECTOR_START+0 \
- invalidate_interrupt0 smp_invalidate_interrupt
-apicinterrupt INVALIDATE_TLB_VECTOR_START+1 \
- invalidate_interrupt1 smp_invalidate_interrupt
-apicinterrupt INVALIDATE_TLB_VECTOR_START+2 \
- invalidate_interrupt2 smp_invalidate_interrupt
-apicinterrupt INVALIDATE_TLB_VECTOR_START+3 \
- invalidate_interrupt3 smp_invalidate_interrupt
-apicinterrupt INVALIDATE_TLB_VECTOR_START+4 \
- invalidate_interrupt4 smp_invalidate_interrupt
-apicinterrupt INVALIDATE_TLB_VECTOR_START+5 \
- invalidate_interrupt5 smp_invalidate_interrupt
-apicinterrupt INVALIDATE_TLB_VECTOR_START+6 \
- invalidate_interrupt6 smp_invalidate_interrupt
-apicinterrupt INVALIDATE_TLB_VECTOR_START+7 \
- invalidate_interrupt7 smp_invalidate_interrupt
+.irpc idx, "01234567"
+apicinterrupt (INVALIDATE_TLB_VECTOR_START)+\idx \
+ invalidate_interrupt\idx smp_invalidate_interrupt
+.endr
#endif
apicinterrupt THRESHOLD_APIC_VECTOR \
@@ -1023,9 +993,9 @@ apicinterrupt ERROR_APIC_VECTOR \
apicinterrupt SPURIOUS_APIC_VECTOR \
spurious_interrupt smp_spurious_interrupt
-#ifdef CONFIG_PERF_EVENTS
-apicinterrupt LOCAL_PENDING_VECTOR \
- perf_pending_interrupt smp_perf_pending_interrupt
+#ifdef CONFIG_IRQ_WORK
+apicinterrupt IRQ_WORK_VECTOR \
+ irq_work_interrupt smp_irq_work_interrupt
#endif
/*
@@ -1036,8 +1006,8 @@ ENTRY(\sym)
INTR_FRAME
PARAVIRT_ADJUST_EXCEPTION_FRAME
pushq_cfi $-1 /* ORIG_RAX: no syscall to restart */
- subq $15*8,%rsp
- CFI_ADJUST_CFA_OFFSET 15*8
+ subq $ORIG_RAX-R15, %rsp
+ CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
call error_entry
DEFAULT_FRAME 0
movq %rsp,%rdi /* pt_regs pointer */
@@ -1052,9 +1022,9 @@ END(\sym)
ENTRY(\sym)
INTR_FRAME
PARAVIRT_ADJUST_EXCEPTION_FRAME
- pushq $-1 /* ORIG_RAX: no syscall to restart */
- CFI_ADJUST_CFA_OFFSET 8
- subq $15*8, %rsp
+ pushq_cfi $-1 /* ORIG_RAX: no syscall to restart */
+ subq $ORIG_RAX-R15, %rsp
+ CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
call save_paranoid
TRACE_IRQS_OFF
movq %rsp,%rdi /* pt_regs pointer */
@@ -1070,9 +1040,9 @@ END(\sym)
ENTRY(\sym)
INTR_FRAME
PARAVIRT_ADJUST_EXCEPTION_FRAME
- pushq $-1 /* ORIG_RAX: no syscall to restart */
- CFI_ADJUST_CFA_OFFSET 8
- subq $15*8, %rsp
+ pushq_cfi $-1 /* ORIG_RAX: no syscall to restart */
+ subq $ORIG_RAX-R15, %rsp
+ CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
call save_paranoid
TRACE_IRQS_OFF
movq %rsp,%rdi /* pt_regs pointer */
@@ -1089,8 +1059,8 @@ END(\sym)
ENTRY(\sym)
XCPT_FRAME
PARAVIRT_ADJUST_EXCEPTION_FRAME
- subq $15*8,%rsp
- CFI_ADJUST_CFA_OFFSET 15*8
+ subq $ORIG_RAX-R15, %rsp
+ CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
call error_entry
DEFAULT_FRAME 0
movq %rsp,%rdi /* pt_regs pointer */
@@ -1107,8 +1077,8 @@ END(\sym)
ENTRY(\sym)
XCPT_FRAME
PARAVIRT_ADJUST_EXCEPTION_FRAME
- subq $15*8,%rsp
- CFI_ADJUST_CFA_OFFSET 15*8
+ subq $ORIG_RAX-R15, %rsp
+ CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
call save_paranoid
DEFAULT_FRAME 0
TRACE_IRQS_OFF
@@ -1139,16 +1109,14 @@ zeroentry simd_coprocessor_error do_simd_coprocessor_error
/* edi: new selector */
ENTRY(native_load_gs_index)
CFI_STARTPROC
- pushf
- CFI_ADJUST_CFA_OFFSET 8
+ pushfq_cfi
DISABLE_INTERRUPTS(CLBR_ANY & ~CLBR_RDI)
SWAPGS
gs_change:
movl %edi,%gs
2: mfence /* workaround */
SWAPGS
- popf
- CFI_ADJUST_CFA_OFFSET -8
+ popfq_cfi
ret
CFI_ENDPROC
END(native_load_gs_index)
@@ -1215,8 +1183,7 @@ END(kernel_execve)
/* Call softirq on interrupt stack. Interrupts are off. */
ENTRY(call_softirq)
CFI_STARTPROC
- push %rbp
- CFI_ADJUST_CFA_OFFSET 8
+ pushq_cfi %rbp
CFI_REL_OFFSET rbp,0
mov %rsp,%rbp
CFI_DEF_CFA_REGISTER rbp
@@ -1225,6 +1192,7 @@ ENTRY(call_softirq)
push %rbp # backlink for old unwinder
call __do_softirq
leaveq
+ CFI_RESTORE rbp
CFI_DEF_CFA_REGISTER rsp
CFI_ADJUST_CFA_OFFSET -8
decl PER_CPU_VAR(irq_count)
@@ -1368,7 +1336,7 @@ paranoidzeroentry machine_check *machine_check_vector(%rip)
/* ebx: no swapgs flag */
ENTRY(paranoid_exit)
- INTR_FRAME
+ DEFAULT_FRAME
DISABLE_INTERRUPTS(CLBR_NONE)
TRACE_IRQS_OFF
testl %ebx,%ebx /* swapgs needed? */
@@ -1445,7 +1413,6 @@ error_swapgs:
error_sti:
TRACE_IRQS_OFF
ret
- CFI_ENDPROC
/*
* There are two places in the kernel that can potentially fault with
@@ -1470,6 +1437,7 @@ bstep_iret:
/* Fix truncated RIP */
movq %rcx,RIP+8(%rsp)
jmp error_swapgs
+ CFI_ENDPROC
END(error_entry)
@@ -1498,8 +1466,8 @@ ENTRY(nmi)
INTR_FRAME
PARAVIRT_ADJUST_EXCEPTION_FRAME
pushq_cfi $-1
- subq $15*8, %rsp
- CFI_ADJUST_CFA_OFFSET 15*8
+ subq $ORIG_RAX-R15, %rsp
+ CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
call save_paranoid
DEFAULT_FRAME 0
/* paranoidentry do_nmi, 0; without TRACE_IRQS_OFF */
diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c
index cd37469b54ee..3afb33f14d2d 100644
--- a/arch/x86/kernel/ftrace.c
+++ b/arch/x86/kernel/ftrace.c
@@ -257,14 +257,9 @@ do_ftrace_mod_code(unsigned long ip, void *new_code)
return mod_code_status;
}
-
-
-
-static unsigned char ftrace_nop[MCOUNT_INSN_SIZE];
-
static unsigned char *ftrace_nop_replace(void)
{
- return ftrace_nop;
+ return ideal_nop5;
}
static int
@@ -338,62 +333,6 @@ int ftrace_update_ftrace_func(ftrace_func_t func)
int __init ftrace_dyn_arch_init(void *data)
{
- extern const unsigned char ftrace_test_p6nop[];
- extern const unsigned char ftrace_test_nop5[];
- extern const unsigned char ftrace_test_jmp[];
- int faulted = 0;
-
- /*
- * There is no good nop for all x86 archs.
- * We will default to using the P6_NOP5, but first we
- * will test to make sure that the nop will actually
- * work on this CPU. If it faults, we will then
- * go to a lesser efficient 5 byte nop. If that fails
- * we then just use a jmp as our nop. This isn't the most
- * efficient nop, but we can not use a multi part nop
- * since we would then risk being preempted in the middle
- * of that nop, and if we enabled tracing then, it might
- * cause a system crash.
- *
- * TODO: check the cpuid to determine the best nop.
- */
- asm volatile (
- "ftrace_test_jmp:"
- "jmp ftrace_test_p6nop\n"
- "nop\n"
- "nop\n"
- "nop\n" /* 2 byte jmp + 3 bytes */
- "ftrace_test_p6nop:"
- P6_NOP5
- "jmp 1f\n"
- "ftrace_test_nop5:"
- ".byte 0x66,0x66,0x66,0x66,0x90\n"
- "1:"
- ".section .fixup, \"ax\"\n"
- "2: movl $1, %0\n"
- " jmp ftrace_test_nop5\n"
- "3: movl $2, %0\n"
- " jmp 1b\n"
- ".previous\n"
- _ASM_EXTABLE(ftrace_test_p6nop, 2b)
- _ASM_EXTABLE(ftrace_test_nop5, 3b)
- : "=r"(faulted) : "0" (faulted));
-
- switch (faulted) {
- case 0:
- pr_info("converting mcount calls to 0f 1f 44 00 00\n");
- memcpy(ftrace_nop, ftrace_test_p6nop, MCOUNT_INSN_SIZE);
- break;
- case 1:
- pr_info("converting mcount calls to 66 66 66 66 90\n");
- memcpy(ftrace_nop, ftrace_test_nop5, MCOUNT_INSN_SIZE);
- break;
- case 2:
- pr_info("converting mcount calls to jmp . + 5\n");
- memcpy(ftrace_nop, ftrace_test_jmp, MCOUNT_INSN_SIZE);
- break;
- }
-
/* The return code is retured via data */
*(unsigned long *)data = 0;
diff --git a/arch/x86/kernel/head.c b/arch/x86/kernel/head.c
index 3e66bd364a9d..af0699ba48cf 100644
--- a/arch/x86/kernel/head.c
+++ b/arch/x86/kernel/head.c
@@ -1,5 +1,6 @@
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/memblock.h>
#include <asm/setup.h>
#include <asm/bios_ebda.h>
@@ -51,5 +52,5 @@ void __init reserve_ebda_region(void)
lowmem = 0x9f000;
/* reserve all memory between lowmem and the 1MB mark */
- reserve_early_overlap_ok(lowmem, 0x100000, "BIOS reserved");
+ memblock_x86_reserve_range(lowmem, 0x100000, "* BIOS reserved");
}
diff --git a/arch/x86/kernel/head32.c b/arch/x86/kernel/head32.c
index 784360c0625c..763310165fa0 100644
--- a/arch/x86/kernel/head32.c
+++ b/arch/x86/kernel/head32.c
@@ -8,6 +8,7 @@
#include <linux/init.h>
#include <linux/start_kernel.h>
#include <linux/mm.h>
+#include <linux/memblock.h>
#include <asm/setup.h>
#include <asm/sections.h>
@@ -17,6 +18,7 @@
#include <asm/apic.h>
#include <asm/io_apic.h>
#include <asm/bios_ebda.h>
+#include <asm/tlbflush.h>
static void __init i386_default_early_setup(void)
{
@@ -30,17 +32,18 @@ static void __init i386_default_early_setup(void)
void __init i386_start_kernel(void)
{
+ memblock_init();
+
#ifdef CONFIG_X86_TRAMPOLINE
/*
* But first pinch a few for the stack/trampoline stuff
* FIXME: Don't need the extra page at 4K, but need to fix
* trampoline before removing it. (see the GDT stuff)
*/
- reserve_early_overlap_ok(PAGE_SIZE, PAGE_SIZE + PAGE_SIZE,
- "EX TRAMPOLINE");
+ memblock_x86_reserve_range(PAGE_SIZE, PAGE_SIZE + PAGE_SIZE, "EX TRAMPOLINE");
#endif
- reserve_early(__pa_symbol(&_text), __pa_symbol(&__bss_stop), "TEXT DATA BSS");
+ memblock_x86_reserve_range(__pa_symbol(&_text), __pa_symbol(&__bss_stop), "TEXT DATA BSS");
#ifdef CONFIG_BLK_DEV_INITRD
/* Reserve INITRD */
@@ -49,7 +52,7 @@ void __init i386_start_kernel(void)
u64 ramdisk_image = boot_params.hdr.ramdisk_image;
u64 ramdisk_size = boot_params.hdr.ramdisk_size;
u64 ramdisk_end = PAGE_ALIGN(ramdisk_image + ramdisk_size);
- reserve_early(ramdisk_image, ramdisk_end, "RAMDISK");
+ memblock_x86_reserve_range(ramdisk_image, ramdisk_end, "RAMDISK");
}
#endif
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index 7147143fd614..2d2673c28aff 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -12,6 +12,7 @@
#include <linux/percpu.h>
#include <linux/start_kernel.h>
#include <linux/io.h>
+#include <linux/memblock.h>
#include <asm/processor.h>
#include <asm/proto.h>
@@ -79,6 +80,8 @@ void __init x86_64_start_kernel(char * real_mode_data)
/* Cleanup the over mapped high alias */
cleanup_highmap();
+ max_pfn_mapped = KERNEL_IMAGE_SIZE >> PAGE_SHIFT;
+
for (i = 0; i < NUM_EXCEPTION_VECTORS; i++) {
#ifdef CONFIG_EARLY_PRINTK
set_intr_gate(i, &early_idt_handlers[i]);
@@ -98,7 +101,9 @@ void __init x86_64_start_reservations(char *real_mode_data)
{
copy_bootdata(__va(real_mode_data));
- reserve_early(__pa_symbol(&_text), __pa_symbol(&__bss_stop), "TEXT DATA BSS");
+ memblock_init();
+
+ memblock_x86_reserve_range(__pa_symbol(&_text), __pa_symbol(&__bss_stop), "TEXT DATA BSS");
#ifdef CONFIG_BLK_DEV_INITRD
/* Reserve INITRD */
@@ -107,7 +112,7 @@ void __init x86_64_start_reservations(char *real_mode_data)
unsigned long ramdisk_image = boot_params.hdr.ramdisk_image;
unsigned long ramdisk_size = boot_params.hdr.ramdisk_size;
unsigned long ramdisk_end = PAGE_ALIGN(ramdisk_image + ramdisk_size);
- reserve_early(ramdisk_image, ramdisk_end, "RAMDISK");
+ memblock_x86_reserve_range(ramdisk_image, ramdisk_end, "RAMDISK");
}
#endif
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
index fa8c1b8e09fb..bcece91dd311 100644
--- a/arch/x86/kernel/head_32.S
+++ b/arch/x86/kernel/head_32.S
@@ -183,13 +183,12 @@ default_entry:
#ifdef CONFIG_X86_PAE
/*
- * In PAE mode swapper_pg_dir is statically defined to contain enough
- * entries to cover the VMSPLIT option (that is the top 1, 2 or 3
- * entries). The identity mapping is handled by pointing two PGD
- * entries to the first kernel PMD.
+ * In PAE mode initial_page_table is statically defined to contain
+ * enough entries to cover the VMSPLIT option (that is the top 1, 2 or 3
+ * entries). The identity mapping is handled by pointing two PGD entries
+ * to the first kernel PMD.
*
- * Note the upper half of each PMD or PTE are always zero at
- * this stage.
+ * Note the upper half of each PMD or PTE are always zero at this stage.
*/
#define KPMDS (((-__PAGE_OFFSET) >> 30) & 3) /* Number of kernel PMDs */
@@ -197,7 +196,7 @@ default_entry:
xorl %ebx,%ebx /* %ebx is kept at zero */
movl $pa(__brk_base), %edi
- movl $pa(swapper_pg_pmd), %edx
+ movl $pa(initial_pg_pmd), %edx
movl $PTE_IDENT_ATTR, %eax
10:
leal PDE_IDENT_ATTR(%edi),%ecx /* Create PMD entry */
@@ -226,14 +225,14 @@ default_entry:
movl %eax, pa(max_pfn_mapped)
/* Do early initialization of the fixmap area */
- movl $pa(swapper_pg_fixmap)+PDE_IDENT_ATTR,%eax
- movl %eax,pa(swapper_pg_pmd+0x1000*KPMDS-8)
+ movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax
+ movl %eax,pa(initial_pg_pmd+0x1000*KPMDS-8)
#else /* Not PAE */
page_pde_offset = (__PAGE_OFFSET >> 20);
movl $pa(__brk_base), %edi
- movl $pa(swapper_pg_dir), %edx
+ movl $pa(initial_page_table), %edx
movl $PTE_IDENT_ATTR, %eax
10:
leal PDE_IDENT_ATTR(%edi),%ecx /* Create PDE entry */
@@ -257,8 +256,8 @@ page_pde_offset = (__PAGE_OFFSET >> 20);
movl %eax, pa(max_pfn_mapped)
/* Do early initialization of the fixmap area */
- movl $pa(swapper_pg_fixmap)+PDE_IDENT_ATTR,%eax
- movl %eax,pa(swapper_pg_dir+0xffc)
+ movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax
+ movl %eax,pa(initial_page_table+0xffc)
#endif
jmp 3f
/*
@@ -334,7 +333,7 @@ ENTRY(startup_32_smp)
/*
* Enable paging
*/
- movl pa(initial_page_table), %eax
+ movl $pa(initial_page_table), %eax
movl %eax,%cr3 /* set the page table pointer.. */
movl %cr0,%eax
orl $X86_CR0_PG,%eax
@@ -614,8 +613,6 @@ ignore_int:
.align 4
ENTRY(initial_code)
.long i386_start_kernel
-ENTRY(initial_page_table)
- .long pa(swapper_pg_dir)
/*
* BSS section
@@ -623,20 +620,18 @@ ENTRY(initial_page_table)
__PAGE_ALIGNED_BSS
.align PAGE_SIZE_asm
#ifdef CONFIG_X86_PAE
-swapper_pg_pmd:
+initial_pg_pmd:
.fill 1024*KPMDS,4,0
#else
-ENTRY(swapper_pg_dir)
+ENTRY(initial_page_table)
.fill 1024,4,0
#endif
-swapper_pg_fixmap:
+initial_pg_fixmap:
.fill 1024,4,0
-#ifdef CONFIG_X86_TRAMPOLINE
-ENTRY(trampoline_pg_dir)
- .fill 1024,4,0
-#endif
ENTRY(empty_zero_page)
.fill 4096,1,0
+ENTRY(swapper_pg_dir)
+ .fill 1024,4,0
/*
* This starts the data section.
@@ -645,20 +640,20 @@ ENTRY(empty_zero_page)
__PAGE_ALIGNED_DATA
/* Page-aligned for the benefit of paravirt? */
.align PAGE_SIZE_asm
-ENTRY(swapper_pg_dir)
- .long pa(swapper_pg_pmd+PGD_IDENT_ATTR),0 /* low identity map */
+ENTRY(initial_page_table)
+ .long pa(initial_pg_pmd+PGD_IDENT_ATTR),0 /* low identity map */
# if KPMDS == 3
- .long pa(swapper_pg_pmd+PGD_IDENT_ATTR),0
- .long pa(swapper_pg_pmd+PGD_IDENT_ATTR+0x1000),0
- .long pa(swapper_pg_pmd+PGD_IDENT_ATTR+0x2000),0
+ .long pa(initial_pg_pmd+PGD_IDENT_ATTR),0
+ .long pa(initial_pg_pmd+PGD_IDENT_ATTR+0x1000),0
+ .long pa(initial_pg_pmd+PGD_IDENT_ATTR+0x2000),0
# elif KPMDS == 2
.long 0,0
- .long pa(swapper_pg_pmd+PGD_IDENT_ATTR),0
- .long pa(swapper_pg_pmd+PGD_IDENT_ATTR+0x1000),0
+ .long pa(initial_pg_pmd+PGD_IDENT_ATTR),0
+ .long pa(initial_pg_pmd+PGD_IDENT_ATTR+0x1000),0
# elif KPMDS == 1
.long 0,0
.long 0,0
- .long pa(swapper_pg_pmd+PGD_IDENT_ATTR),0
+ .long pa(initial_pg_pmd+PGD_IDENT_ATTR),0
# else
# error "Kernel PMDs should be 1, 2 or 3"
# endif
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index 410fdb3f1939..aff0b3c27509 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -380,44 +380,35 @@ static int hpet_next_event(unsigned long delta,
struct clock_event_device *evt, int timer)
{
u32 cnt;
+ s32 res;
cnt = hpet_readl(HPET_COUNTER);
cnt += (u32) delta;
hpet_writel(cnt, HPET_Tn_CMP(timer));
/*
- * We need to read back the CMP register on certain HPET
- * implementations (ATI chipsets) which seem to delay the
- * transfer of the compare register into the internal compare
- * logic. With small deltas this might actually be too late as
- * the counter could already be higher than the compare value
- * at that point and we would wait for the next hpet interrupt
- * forever. We found out that reading the CMP register back
- * forces the transfer so we can rely on the comparison with
- * the counter register below. If the read back from the
- * compare register does not match the value we programmed
- * then we might have a real hardware problem. We can not do
- * much about it here, but at least alert the user/admin with
- * a prominent warning.
- *
- * An erratum on some chipsets (ICH9,..), results in
- * comparator read immediately following a write returning old
- * value. Workaround for this is to read this value second
- * time, when first read returns old value.
- *
- * In fact the write to the comparator register is delayed up
- * to two HPET cycles so the workaround we tried to restrict
- * the readback to those known to be borked ATI chipsets
- * failed miserably. So we give up on optimizations forever
- * and penalize all HPET incarnations unconditionally.
+ * HPETs are a complete disaster. The compare register is
+ * based on a equal comparison and neither provides a less
+ * than or equal functionality (which would require to take
+ * the wraparound into account) nor a simple count down event
+ * mode. Further the write to the comparator register is
+ * delayed internally up to two HPET clock cycles in certain
+ * chipsets (ATI, ICH9,10). We worked around that by reading
+ * back the compare register, but that required another
+ * workaround for ICH9,10 chips where the first readout after
+ * write can return the old stale value. We already have a
+ * minimum delta of 5us enforced, but a NMI or SMI hitting
+ * between the counter readout and the comparator write can
+ * move us behind that point easily. Now instead of reading
+ * the compare register back several times, we make the ETIME
+ * decision based on the following: Return ETIME if the
+ * counter value after the write is less than 8 HPET cycles
+ * away from the event or if the counter is already ahead of
+ * the event.
*/
- if (unlikely((u32)hpet_readl(HPET_Tn_CMP(timer)) != cnt)) {
- if (hpet_readl(HPET_Tn_CMP(timer)) != cnt)
- printk_once(KERN_WARNING
- "hpet: compare register read back failed.\n");
- }
+ res = (s32)(cnt - hpet_readl(HPET_COUNTER));
- return (s32)(hpet_readl(HPET_COUNTER) - cnt) >= 0 ? -ETIME : 0;
+ return res < 8 ? -ETIME : 0;
}
static void hpet_legacy_set_mode(enum clock_event_mode mode,
@@ -440,9 +431,9 @@ static int hpet_legacy_next_event(unsigned long delta,
static DEFINE_PER_CPU(struct hpet_dev *, cpu_hpet_dev);
static struct hpet_dev *hpet_devs;
-void hpet_msi_unmask(unsigned int irq)
+void hpet_msi_unmask(struct irq_data *data)
{
- struct hpet_dev *hdev = get_irq_data(irq);
+ struct hpet_dev *hdev = data->handler_data;
unsigned int cfg;
/* unmask it */
@@ -451,10 +442,10 @@ void hpet_msi_unmask(unsigned int irq)
hpet_writel(cfg, HPET_Tn_CFG(hdev->num));
}
-void hpet_msi_mask(unsigned int irq)
+void hpet_msi_mask(struct irq_data *data)
{
+ struct hpet_dev *hdev = data->handler_data;
unsigned int cfg;
- struct hpet_dev *hdev = get_irq_data(irq);
/* mask it */
cfg = hpet_readl(HPET_Tn_CFG(hdev->num));
@@ -462,18 +453,14 @@ void hpet_msi_mask(unsigned int irq)
hpet_writel(cfg, HPET_Tn_CFG(hdev->num));
}
-void hpet_msi_write(unsigned int irq, struct msi_msg *msg)
+void hpet_msi_write(struct hpet_dev *hdev, struct msi_msg *msg)
{
- struct hpet_dev *hdev = get_irq_data(irq);
-
hpet_writel(msg->data, HPET_Tn_ROUTE(hdev->num));
hpet_writel(msg->address_lo, HPET_Tn_ROUTE(hdev->num) + 4);
}
-void hpet_msi_read(unsigned int irq, struct msi_msg *msg)
+void hpet_msi_read(struct hpet_dev *hdev, struct msi_msg *msg)
{
- struct hpet_dev *hdev = get_irq_data(irq);
-
msg->data = hpet_readl(HPET_Tn_ROUTE(hdev->num));
msg->address_lo = hpet_readl(HPET_Tn_ROUTE(hdev->num) + 4);
msg->address_hi = 0;
@@ -506,7 +493,7 @@ static int hpet_assign_irq(struct hpet_dev *dev)
{
unsigned int irq;
- irq = create_irq();
+ irq = create_irq_nr(0, -1);
if (!irq)
return -EINVAL;
diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c
index a46cb3522c0c..58bb239a2fd7 100644
--- a/arch/x86/kernel/i387.c
+++ b/arch/x86/kernel/i387.c
@@ -68,19 +68,22 @@ static void __cpuinit init_thread_xstate(void)
*/
if (!HAVE_HWFP) {
+ /*
+ * Disable xsave as we do not support it if i387
+ * emulation is enabled.
+ */
+ setup_clear_cpu_cap(X86_FEATURE_XSAVE);
+ setup_clear_cpu_cap(X86_FEATURE_XSAVEOPT);
xstate_size = sizeof(struct i387_soft_struct);
return;
}
if (cpu_has_fxsr)
xstate_size = sizeof(struct i387_fxsave_struct);
-#ifdef CONFIG_X86_32
else
xstate_size = sizeof(struct i387_fsave_struct);
-#endif
}
-#ifdef CONFIG_X86_64
/*
* Called at bootup to set up the initial FPU state that is later cloned
* into all processes.
@@ -88,12 +91,21 @@ static void __cpuinit init_thread_xstate(void)
void __cpuinit fpu_init(void)
{
- unsigned long oldcr0 = read_cr0();
-
- set_in_cr4(X86_CR4_OSFXSR);
- set_in_cr4(X86_CR4_OSXMMEXCPT);
+ unsigned long cr0;
+ unsigned long cr4_mask = 0;
- write_cr0(oldcr0 & ~(X86_CR0_TS|X86_CR0_EM)); /* clear TS and EM */
+ if (cpu_has_fxsr)
+ cr4_mask |= X86_CR4_OSFXSR;
+ if (cpu_has_xmm)
+ cr4_mask |= X86_CR4_OSXMMEXCPT;
+ if (cr4_mask)
+ set_in_cr4(cr4_mask);
+
+ cr0 = read_cr0();
+ cr0 &= ~(X86_CR0_TS|X86_CR0_EM); /* clear TS and EM */
+ if (!HAVE_HWFP)
+ cr0 |= X86_CR0_EM;
+ write_cr0(cr0);
if (!smp_processor_id())
init_thread_xstate();
@@ -104,24 +116,12 @@ void __cpuinit fpu_init(void)
clear_used_math();
}
-#else /* CONFIG_X86_64 */
-
-void __cpuinit fpu_init(void)
-{
- if (!smp_processor_id())
- init_thread_xstate();
-}
-
-#endif /* CONFIG_X86_32 */
-
void fpu_finit(struct fpu *fpu)
{
-#ifdef CONFIG_X86_32
if (!HAVE_HWFP) {
finit_soft_fpu(&fpu->state->soft);
return;
}
-#endif
if (cpu_has_fxsr) {
struct i387_fxsave_struct *fx = &fpu->state->fxsave;
@@ -386,19 +386,17 @@ convert_from_fxsr(struct user_i387_ia32_struct *env, struct task_struct *tsk)
#ifdef CONFIG_X86_64
env->fip = fxsave->rip;
env->foo = fxsave->rdp;
+ /*
+ * should be actually ds/cs at fpu exception time, but
+ * that information is not available in 64bit mode.
+ */
+ env->fcs = task_pt_regs(tsk)->cs;
if (tsk == current) {
- /*
- * should be actually ds/cs at fpu exception time, but
- * that information is not available in 64bit mode.
- */
- asm("mov %%ds, %[fos]" : [fos] "=r" (env->fos));
- asm("mov %%cs, %[fcs]" : [fcs] "=r" (env->fcs));
+ savesegment(ds, env->fos);
} else {
- struct pt_regs *regs = task_pt_regs(tsk);
-
- env->fos = 0xffff0000 | tsk->thread.ds;
- env->fcs = regs->cs;
+ env->fos = tsk->thread.ds;
}
+ env->fos |= 0xffff0000;
#else
env->fip = fxsave->fip;
env->fcs = (u16) fxsave->fcs | ((u32) fxsave->fop << 16);
diff --git a/arch/x86/kernel/i8259.c b/arch/x86/kernel/i8259.c
index cafa7c80ac95..20757cb2efa3 100644
--- a/arch/x86/kernel/i8259.c
+++ b/arch/x86/kernel/i8259.c
@@ -29,24 +29,10 @@
* plus some generic x86 specific things if generic specifics makes
* any sense at all.
*/
+static void init_8259A(int auto_eoi);
static int i8259A_auto_eoi;
DEFINE_RAW_SPINLOCK(i8259A_lock);
-static void mask_and_ack_8259A(unsigned int);
-static void mask_8259A(void);
-static void unmask_8259A(void);
-static void disable_8259A_irq(unsigned int irq);
-static void enable_8259A_irq(unsigned int irq);
-static void init_8259A(int auto_eoi);
-static int i8259A_irq_pending(unsigned int irq);
-
-struct irq_chip i8259A_chip = {
- .name = "XT-PIC",
- .mask = disable_8259A_irq,
- .disable = disable_8259A_irq,
- .unmask = enable_8259A_irq,
- .mask_ack = mask_and_ack_8259A,
-};
/*
* 8259A PIC functions to handle ISA devices:
@@ -68,7 +54,7 @@ unsigned int cached_irq_mask = 0xffff;
*/
unsigned long io_apic_irqs;
-static void disable_8259A_irq(unsigned int irq)
+static void mask_8259A_irq(unsigned int irq)
{
unsigned int mask = 1 << irq;
unsigned long flags;
@@ -82,7 +68,12 @@ static void disable_8259A_irq(unsigned int irq)
raw_spin_unlock_irqrestore(&i8259A_lock, flags);
}
-static void enable_8259A_irq(unsigned int irq)
+static void disable_8259A_irq(struct irq_data *data)
+{
+ mask_8259A_irq(data->irq);
+}
+
+static void unmask_8259A_irq(unsigned int irq)
{
unsigned int mask = ~(1 << irq);
unsigned long flags;
@@ -96,6 +87,11 @@ static void enable_8259A_irq(unsigned int irq)
raw_spin_unlock_irqrestore(&i8259A_lock, flags);
}
+static void enable_8259A_irq(struct irq_data *data)
+{
+ unmask_8259A_irq(data->irq);
+}
+
static int i8259A_irq_pending(unsigned int irq)
{
unsigned int mask = 1<<irq;
@@ -117,7 +113,7 @@ static void make_8259A_irq(unsigned int irq)
disable_irq_nosync(irq);
io_apic_irqs &= ~(1<<irq);
set_irq_chip_and_handler_name(irq, &i8259A_chip, handle_level_irq,
- "XT");
+ i8259A_chip.name);
enable_irq(irq);
}
@@ -150,8 +146,9 @@ static inline int i8259A_irq_real(unsigned int irq)
* first, _then_ send the EOI, and the order of EOI
* to the two 8259s is important!
*/
-static void mask_and_ack_8259A(unsigned int irq)
+static void mask_and_ack_8259A(struct irq_data *data)
{
+ unsigned int irq = data->irq;
unsigned int irqmask = 1 << irq;
unsigned long flags;
@@ -223,6 +220,14 @@ spurious_8259A_irq:
}
}
+struct irq_chip i8259A_chip = {
+ .name = "XT-PIC",
+ .irq_mask = disable_8259A_irq,
+ .irq_disable = disable_8259A_irq,
+ .irq_unmask = enable_8259A_irq,
+ .irq_mask_ack = mask_and_ack_8259A,
+};
+
static char irq_trigger[2];
/**
* ELCR registers (0x4d0, 0x4d1) control edge/level of IRQ
@@ -342,9 +347,9 @@ static void init_8259A(int auto_eoi)
* In AEOI mode we just have to mask the interrupt
* when acking.
*/
- i8259A_chip.mask_ack = disable_8259A_irq;
+ i8259A_chip.irq_mask_ack = disable_8259A_irq;
else
- i8259A_chip.mask_ack = mask_and_ack_8259A;
+ i8259A_chip.irq_mask_ack = mask_and_ack_8259A;
udelay(100); /* wait for 8259A to initialize */
@@ -363,14 +368,6 @@ static void init_8259A(int auto_eoi)
static void legacy_pic_noop(void) { };
static void legacy_pic_uint_noop(unsigned int unused) { };
static void legacy_pic_int_noop(int unused) { };
-
-static struct irq_chip dummy_pic_chip = {
- .name = "dummy pic",
- .mask = legacy_pic_uint_noop,
- .unmask = legacy_pic_uint_noop,
- .disable = legacy_pic_uint_noop,
- .mask_ack = legacy_pic_uint_noop,
-};
static int legacy_pic_irq_pending_noop(unsigned int irq)
{
return 0;
@@ -378,7 +375,9 @@ static int legacy_pic_irq_pending_noop(unsigned int irq)
struct legacy_pic null_legacy_pic = {
.nr_legacy_irqs = 0,
- .chip = &dummy_pic_chip,
+ .chip = &dummy_irq_chip,
+ .mask = legacy_pic_uint_noop,
+ .unmask = legacy_pic_uint_noop,
.mask_all = legacy_pic_noop,
.restore_mask = legacy_pic_noop,
.init = legacy_pic_int_noop,
@@ -389,7 +388,9 @@ struct legacy_pic null_legacy_pic = {
struct legacy_pic default_legacy_pic = {
.nr_legacy_irqs = NR_IRQS_LEGACY,
.chip = &i8259A_chip,
- .mask_all = mask_8259A,
+ .mask = mask_8259A_irq,
+ .unmask = unmask_8259A_irq,
+ .mask_all = mask_8259A,
.restore_mask = unmask_8259A,
.init = init_8259A,
.irq_pending = i8259A_irq_pending,
diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c
index 91fd0c70a18a..83ec0175f986 100644
--- a/arch/x86/kernel/irq.c
+++ b/arch/x86/kernel/irq.c
@@ -67,10 +67,10 @@ static int show_other_interrupts(struct seq_file *p, int prec)
for_each_online_cpu(j)
seq_printf(p, "%10u ", irq_stats(j)->apic_perf_irqs);
seq_printf(p, " Performance monitoring interrupts\n");
- seq_printf(p, "%*s: ", prec, "PND");
+ seq_printf(p, "%*s: ", prec, "IWI");
for_each_online_cpu(j)
- seq_printf(p, "%10u ", irq_stats(j)->apic_pending_irqs);
- seq_printf(p, " Performance pending work\n");
+ seq_printf(p, "%10u ", irq_stats(j)->apic_irq_work_irqs);
+ seq_printf(p, " IRQ work interrupts\n");
#endif
if (x86_platform_ipi_callback) {
seq_printf(p, "%*s: ", prec, "PLT");
@@ -159,7 +159,7 @@ int show_interrupts(struct seq_file *p, void *v)
seq_printf(p, "%*d: ", prec, i);
for_each_online_cpu(j)
seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
- seq_printf(p, " %8s", desc->chip->name);
+ seq_printf(p, " %8s", desc->irq_data.chip->name);
seq_printf(p, "-%-8s", desc->name);
if (action) {
@@ -185,7 +185,7 @@ u64 arch_irq_stat_cpu(unsigned int cpu)
sum += irq_stats(cpu)->apic_timer_irqs;
sum += irq_stats(cpu)->irq_spurious_count;
sum += irq_stats(cpu)->apic_perf_irqs;
- sum += irq_stats(cpu)->apic_pending_irqs;
+ sum += irq_stats(cpu)->apic_irq_work_irqs;
#endif
if (x86_platform_ipi_callback)
sum += irq_stats(cpu)->x86_platform_ipis;
@@ -282,6 +282,7 @@ void fixup_irqs(void)
unsigned int irq, vector;
static int warned;
struct irq_desc *desc;
+ struct irq_data *data;
for_each_irq_desc(irq, desc) {
int break_affinity = 0;
@@ -296,7 +297,8 @@ void fixup_irqs(void)
/* interrupt's are disabled at this point */
raw_spin_lock(&desc->lock);
- affinity = desc->affinity;
+ data = &desc->irq_data;
+ affinity = data->affinity;
if (!irq_has_action(irq) ||
cpumask_equal(affinity, cpu_online_mask)) {
raw_spin_unlock(&desc->lock);
@@ -315,16 +317,16 @@ void fixup_irqs(void)
affinity = cpu_all_mask;
}
- if (!(desc->status & IRQ_MOVE_PCNTXT) && desc->chip->mask)
- desc->chip->mask(irq);
+ if (!(desc->status & IRQ_MOVE_PCNTXT) && data->chip->irq_mask)
+ data->chip->irq_mask(data);
- if (desc->chip->set_affinity)
- desc->chip->set_affinity(irq, affinity);
+ if (data->chip->irq_set_affinity)
+ data->chip->irq_set_affinity(data, affinity, true);
else if (!(warned++))
set_affinity = 0;
- if (!(desc->status & IRQ_MOVE_PCNTXT) && desc->chip->unmask)
- desc->chip->unmask(irq);
+ if (!(desc->status & IRQ_MOVE_PCNTXT) && data->chip->irq_unmask)
+ data->chip->irq_unmask(data);
raw_spin_unlock(&desc->lock);
@@ -355,10 +357,10 @@ void fixup_irqs(void)
if (irr & (1 << (vector % 32))) {
irq = __get_cpu_var(vector_irq)[vector];
- desc = irq_to_desc(irq);
+ data = irq_get_irq_data(irq);
raw_spin_lock(&desc->lock);
- if (desc->chip->retrigger)
- desc->chip->retrigger(irq);
+ if (data->chip->irq_retrigger)
+ data->chip->irq_retrigger(data);
raw_spin_unlock(&desc->lock);
}
}
diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c
index 10709f29d166..50fbbe60e507 100644
--- a/arch/x86/kernel/irq_32.c
+++ b/arch/x86/kernel/irq_32.c
@@ -49,20 +49,19 @@ static inline int check_stack_overflow(void) { return 0; }
static inline void print_stack_overflow(void) { }
#endif
-#ifdef CONFIG_4KSTACKS
/*
* per-CPU IRQ handling contexts (thread information and stack)
*/
union irq_ctx {
struct thread_info tinfo;
u32 stack[THREAD_SIZE/sizeof(u32)];
-} __attribute__((aligned(PAGE_SIZE)));
+} __attribute__((aligned(THREAD_SIZE)));
static DEFINE_PER_CPU(union irq_ctx *, hardirq_ctx);
static DEFINE_PER_CPU(union irq_ctx *, softirq_ctx);
-static DEFINE_PER_CPU_PAGE_ALIGNED(union irq_ctx, hardirq_stack);
-static DEFINE_PER_CPU_PAGE_ALIGNED(union irq_ctx, softirq_stack);
+static DEFINE_PER_CPU_MULTIPAGE_ALIGNED(union irq_ctx, hardirq_stack, THREAD_SIZE);
+static DEFINE_PER_CPU_MULTIPAGE_ALIGNED(union irq_ctx, softirq_stack, THREAD_SIZE);
static void call_on_stack(void *func, void *stack)
{
@@ -187,11 +186,6 @@ asmlinkage void do_softirq(void)
local_irq_restore(flags);
}
-#else
-static inline int
-execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq) { return 0; }
-#endif
-
bool handle_irq(unsigned irq, struct pt_regs *regs)
{
struct irq_desc *desc;
diff --git a/arch/x86/kernel/irq_work.c b/arch/x86/kernel/irq_work.c
new file mode 100644
index 000000000000..ca8f703a1e70
--- /dev/null
+++ b/arch/x86/kernel/irq_work.c
@@ -0,0 +1,30 @@
+/*
+ * x86 specific code for irq_work
+ *
+ * Copyright (C) 2010 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/irq_work.h>
+#include <linux/hardirq.h>
+#include <asm/apic.h>
+
+void smp_irq_work_interrupt(struct pt_regs *regs)
+{
+ irq_enter();
+ ack_APIC_irq();
+ inc_irq_stat(apic_irq_work_irqs);
+ irq_work_run();
+ irq_exit();
+}
+
+void arch_irq_work_raise(void)
+{
+#ifdef CONFIG_X86_LOCAL_APIC
+ if (!cpu_has_apic)
+ return;
+
+ apic->send_IPI_self(IRQ_WORK_VECTOR);
+ apic_wait_icr_idle();
+#endif
+}
diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c
index 990ae7cfc578..c752e973958d 100644
--- a/arch/x86/kernel/irqinit.c
+++ b/arch/x86/kernel/irqinit.c
@@ -100,6 +100,8 @@ int vector_used_by_percpu_irq(unsigned int vector)
void __init init_ISA_irqs(void)
{
+ struct irq_chip *chip = legacy_pic->chip;
+ const char *name = chip->name;
int i;
#if defined(CONFIG_X86_64) || defined(CONFIG_X86_LOCAL_APIC)
@@ -107,19 +109,8 @@ void __init init_ISA_irqs(void)
#endif
legacy_pic->init(0);
- /*
- * 16 old-style INTA-cycle interrupts:
- */
- for (i = 0; i < legacy_pic->nr_legacy_irqs; i++) {
- struct irq_desc *desc = irq_to_desc(i);
-
- desc->status = IRQ_DISABLED;
- desc->action = NULL;
- desc->depth = 1;
-
- set_irq_chip_and_handler_name(i, &i8259A_chip,
- handle_level_irq, "XT");
- }
+ for (i = 0; i < legacy_pic->nr_legacy_irqs; i++)
+ set_irq_chip_and_handler_name(i, chip, handle_level_irq, name);
}
void __init init_IRQ(void)
@@ -224,9 +215,9 @@ static void __init apic_intr_init(void)
alloc_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
- /* Performance monitoring interrupts: */
-# ifdef CONFIG_PERF_EVENTS
- alloc_intr_gate(LOCAL_PENDING_VECTOR, perf_pending_interrupt);
+ /* IRQ work interrupts: */
+# ifdef CONFIG_IRQ_WORK
+ alloc_intr_gate(IRQ_WORK_VECTOR, irq_work_interrupt);
# endif
#endif
diff --git a/arch/x86/kernel/jump_label.c b/arch/x86/kernel/jump_label.c
new file mode 100644
index 000000000000..961b6b30ba90
--- /dev/null
+++ b/arch/x86/kernel/jump_label.c
@@ -0,0 +1,50 @@
+/*
+ * jump label x86 support
+ *
+ * Copyright (C) 2009 Jason Baron <jbaron@redhat.com>
+ *
+ */
+#include <linux/jump_label.h>
+#include <linux/memory.h>
+#include <linux/uaccess.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/jhash.h>
+#include <linux/cpu.h>
+#include <asm/kprobes.h>
+#include <asm/alternative.h>
+
+#ifdef HAVE_JUMP_LABEL
+
+union jump_code_union {
+ char code[JUMP_LABEL_NOP_SIZE];
+ struct {
+ char jump;
+ int offset;
+ } __attribute__((packed));
+};
+
+void arch_jump_label_transform(struct jump_entry *entry,
+ enum jump_label_type type)
+{
+ union jump_code_union code;
+
+ if (type == JUMP_LABEL_ENABLE) {
+ code.jump = 0xe9;
+ code.offset = entry->target -
+ (entry->code + JUMP_LABEL_NOP_SIZE);
+ } else
+ memcpy(&code, ideal_nop5, JUMP_LABEL_NOP_SIZE);
+ get_online_cpus();
+ mutex_lock(&text_mutex);
+ text_poke_smp((void *)entry->code, &code, JUMP_LABEL_NOP_SIZE);
+ mutex_unlock(&text_mutex);
+ put_online_cpus();
+}
+
+void arch_jump_label_text_poke_early(jump_label_t addr)
+{
+ text_poke_early((void *)addr, ideal_nop5, JUMP_LABEL_NOP_SIZE);
+}
+
+#endif
diff --git a/arch/x86/kernel/kdebugfs.c b/arch/x86/kernel/kdebugfs.c
index 8afd9f321f10..90fcf62854bb 100644
--- a/arch/x86/kernel/kdebugfs.c
+++ b/arch/x86/kernel/kdebugfs.c
@@ -78,6 +78,7 @@ static int setup_data_open(struct inode *inode, struct file *file)
static const struct file_operations fops_setup_data = {
.read = setup_data_read,
.open = setup_data_open,
+ .llseek = default_llseek,
};
static int __init
diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c
index 852b81967a37..d81cfebb848f 100644
--- a/arch/x86/kernel/kgdb.c
+++ b/arch/x86/kernel/kgdb.c
@@ -477,8 +477,6 @@ int kgdb_arch_handle_exception(int e_vector, int signo, int err_code,
raw_smp_processor_id());
}
- kgdb_correct_hw_break();
-
return 0;
}
@@ -621,7 +619,12 @@ int kgdb_arch_init(void)
static void kgdb_hw_overflow_handler(struct perf_event *event, int nmi,
struct perf_sample_data *data, struct pt_regs *regs)
{
- kgdb_ll_trap(DIE_DEBUG, "debug", regs, 0, 0, SIGTRAP);
+ struct task_struct *tsk = current;
+ int i;
+
+ for (i = 0; i < 4; i++)
+ if (breakinfo[i].enabled)
+ tsk->thread.debugreg6 |= (DR_TRAP0 << i);
}
void kgdb_arch_late(void)
@@ -644,7 +647,7 @@ void kgdb_arch_late(void)
if (breakinfo[i].pev)
continue;
breakinfo[i].pev = register_wide_hw_breakpoint(&attr, NULL);
- if (IS_ERR(breakinfo[i].pev)) {
+ if (IS_ERR((void * __force)breakinfo[i].pev)) {
printk(KERN_ERR "kgdb: Could not allocate hw"
"breakpoints\nDisabling the kernel debugger\n");
breakinfo[i].pev = NULL;
diff --git a/arch/x86/kernel/kprobes.c b/arch/x86/kernel/kprobes.c
index 770ebfb349e9..1cbd54c0df99 100644
--- a/arch/x86/kernel/kprobes.c
+++ b/arch/x86/kernel/kprobes.c
@@ -230,9 +230,6 @@ static int recover_probed_instruction(kprobe_opcode_t *buf, unsigned long addr)
return 0;
}
-/* Dummy buffers for kallsyms_lookup */
-static char __dummy_buf[KSYM_NAME_LEN];
-
/* Check if paddr is at an instruction boundary */
static int __kprobes can_probe(unsigned long paddr)
{
@@ -241,7 +238,7 @@ static int __kprobes can_probe(unsigned long paddr)
struct insn insn;
kprobe_opcode_t buf[MAX_INSN_SIZE];
- if (!kallsyms_lookup(paddr, NULL, &offset, NULL, __dummy_buf))
+ if (!kallsyms_lookup_size_offset(paddr, NULL, &offset))
return 0;
/* Decode instructions */
@@ -1129,7 +1126,7 @@ static void __kprobes synthesize_set_arg1(kprobe_opcode_t *addr,
*(unsigned long *)addr = val;
}
-void __kprobes kprobes_optinsn_template_holder(void)
+static void __used __kprobes kprobes_optinsn_template_holder(void)
{
asm volatile (
".global optprobe_template_entry\n"
@@ -1221,7 +1218,8 @@ static int __kprobes copy_optimized_instructions(u8 *dest, u8 *src)
}
/* Check whether the address range is reserved */
if (ftrace_text_reserved(src, src + len - 1) ||
- alternatives_text_reserved(src, src + len - 1))
+ alternatives_text_reserved(src, src + len - 1) ||
+ jump_label_text_reserved(src, src + len - 1))
return -EBUSY;
return len;
@@ -1269,11 +1267,9 @@ static int __kprobes can_optimize(unsigned long paddr)
unsigned long addr, size = 0, offset = 0;
struct insn insn;
kprobe_opcode_t buf[MAX_INSN_SIZE];
- /* Dummy buffers for lookup_symbol_attrs */
- static char __dummy_buf[KSYM_NAME_LEN];
/* Lookup symbol including addr */
- if (!kallsyms_lookup(paddr, &size, &offset, NULL, __dummy_buf))
+ if (!kallsyms_lookup_size_offset(paddr, &size, &offset))
return 0;
/* Check there is enough space for a relative jump. */
diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c
index 035c8c529181..b3ea9db39db6 100644
--- a/arch/x86/kernel/machine_kexec_64.c
+++ b/arch/x86/kernel/machine_kexec_64.c
@@ -36,7 +36,7 @@ static int init_one_level2_page(struct kimage *image, pgd_t *pgd,
if (!page)
goto out;
pud = (pud_t *)page_address(page);
- memset(pud, 0, PAGE_SIZE);
+ clear_page(pud);
set_pgd(pgd, __pgd(__pa(pud) | _KERNPG_TABLE));
}
pud = pud_offset(pgd, addr);
@@ -45,7 +45,7 @@ static int init_one_level2_page(struct kimage *image, pgd_t *pgd,
if (!page)
goto out;
pmd = (pmd_t *)page_address(page);
- memset(pmd, 0, PAGE_SIZE);
+ clear_page(pmd);
set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE));
}
pmd = pmd_offset(pud, addr);
diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c
index fa6551d36c10..0b3d37e83606 100644
--- a/arch/x86/kernel/microcode_core.c
+++ b/arch/x86/kernel/microcode_core.c
@@ -232,6 +232,7 @@ static const struct file_operations microcode_fops = {
.owner = THIS_MODULE,
.write = microcode_write,
.open = microcode_open,
+ .llseek = no_llseek,
};
static struct miscdevice microcode_dev = {
diff --git a/arch/x86/kernel/module.c b/arch/x86/kernel/module.c
index e0bc186d7501..8f2956091735 100644
--- a/arch/x86/kernel/module.c
+++ b/arch/x86/kernel/module.c
@@ -239,11 +239,13 @@ int module_finalize(const Elf_Ehdr *hdr,
apply_paravirt(pseg, pseg + para->sh_size);
}
- return module_bug_finalize(hdr, sechdrs, me);
+ /* make jump label nops */
+ jump_label_apply_nops(me);
+
+ return 0;
}
void module_arch_cleanup(struct module *mod)
{
alternatives_smp_module_del(mod);
- module_bug_cleanup(mod);
}
diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c
index d7b6f7fb4fec..9af64d9c4b67 100644
--- a/arch/x86/kernel/mpparse.c
+++ b/arch/x86/kernel/mpparse.c
@@ -11,6 +11,7 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/bootmem.h>
+#include <linux/memblock.h>
#include <linux/kernel_stat.h>
#include <linux/mc146818rtc.h>
#include <linux/bitops.h>
@@ -657,7 +658,7 @@ static void __init smp_reserve_memory(struct mpf_intel *mpf)
{
unsigned long size = get_mpc_size(mpf->physptr);
- reserve_early_overlap_ok(mpf->physptr, mpf->physptr+size, "MP-table mpc");
+ memblock_x86_reserve_range(mpf->physptr, mpf->physptr+size, "* MP-table mpc");
}
static int __init smp_scan_config(unsigned long base, unsigned long length)
@@ -686,7 +687,7 @@ static int __init smp_scan_config(unsigned long base, unsigned long length)
mpf, (u64)virt_to_phys(mpf));
mem = virt_to_phys(mpf);
- reserve_early_overlap_ok(mem, mem + sizeof(*mpf), "MP-table mpf");
+ memblock_x86_reserve_range(mem, mem + sizeof(*mpf), "* MP-table mpf");
if (mpf->physptr)
smp_reserve_memory(mpf);
diff --git a/arch/x86/kernel/olpc-xo1.c b/arch/x86/kernel/olpc-xo1.c
new file mode 100644
index 000000000000..f5442c03abc3
--- /dev/null
+++ b/arch/x86/kernel/olpc-xo1.c
@@ -0,0 +1,140 @@
+/*
+ * Support for features of the OLPC XO-1 laptop
+ *
+ * Copyright (C) 2010 One Laptop per Child
+ * Copyright (C) 2006 Red Hat, Inc.
+ * Copyright (C) 2006 Advanced Micro Devices, 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 <linux/module.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+
+#include <asm/io.h>
+#include <asm/olpc.h>
+
+#define DRV_NAME "olpc-xo1"
+
+#define PMS_BAR 4
+#define ACPI_BAR 5
+
+/* PMC registers (PMS block) */
+#define PM_SCLK 0x10
+#define PM_IN_SLPCTL 0x20
+#define PM_WKXD 0x34
+#define PM_WKD 0x30
+#define PM_SSC 0x54
+
+/* PM registers (ACPI block) */
+#define PM1_CNT 0x08
+#define PM_GPE0_STS 0x18
+
+static unsigned long acpi_base;
+static unsigned long pms_base;
+
+static void xo1_power_off(void)
+{
+ printk(KERN_INFO "OLPC XO-1 power off sequence...\n");
+
+ /* Enable all of these controls with 0 delay */
+ outl(0x40000000, pms_base + PM_SCLK);
+ outl(0x40000000, pms_base + PM_IN_SLPCTL);
+ outl(0x40000000, pms_base + PM_WKXD);
+ outl(0x40000000, pms_base + PM_WKD);
+
+ /* Clear status bits (possibly unnecessary) */
+ outl(0x0002ffff, pms_base + PM_SSC);
+ outl(0xffffffff, acpi_base + PM_GPE0_STS);
+
+ /* Write SLP_EN bit to start the machinery */
+ outl(0x00002000, acpi_base + PM1_CNT);
+}
+
+/* Read the base addresses from the PCI BAR info */
+static int __devinit setup_bases(struct pci_dev *pdev)
+{
+ int r;
+
+ r = pci_enable_device_io(pdev);
+ if (r) {
+ dev_err(&pdev->dev, "can't enable device IO\n");
+ return r;
+ }
+
+ r = pci_request_region(pdev, ACPI_BAR, DRV_NAME);
+ if (r) {
+ dev_err(&pdev->dev, "can't alloc PCI BAR #%d\n", ACPI_BAR);
+ return r;
+ }
+
+ r = pci_request_region(pdev, PMS_BAR, DRV_NAME);
+ if (r) {
+ dev_err(&pdev->dev, "can't alloc PCI BAR #%d\n", PMS_BAR);
+ pci_release_region(pdev, ACPI_BAR);
+ return r;
+ }
+
+ acpi_base = pci_resource_start(pdev, ACPI_BAR);
+ pms_base = pci_resource_start(pdev, PMS_BAR);
+
+ return 0;
+}
+
+static int __devinit olpc_xo1_probe(struct platform_device *pdev)
+{
+ struct pci_dev *pcidev;
+ int r;
+
+ pcidev = pci_get_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA,
+ NULL);
+ if (!pdev)
+ return -ENODEV;
+
+ r = setup_bases(pcidev);
+ if (r)
+ return r;
+
+ pm_power_off = xo1_power_off;
+
+ printk(KERN_INFO "OLPC XO-1 support registered\n");
+ return 0;
+}
+
+static int __devexit olpc_xo1_remove(struct platform_device *pdev)
+{
+ pm_power_off = NULL;
+ return 0;
+}
+
+static struct platform_driver olpc_xo1_driver = {
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = olpc_xo1_probe,
+ .remove = __devexit_p(olpc_xo1_remove),
+};
+
+static int __init olpc_xo1_init(void)
+{
+ return platform_driver_register(&olpc_xo1_driver);
+}
+
+static void __exit olpc_xo1_exit(void)
+{
+ platform_driver_unregister(&olpc_xo1_driver);
+}
+
+MODULE_AUTHOR("Daniel Drake <dsd@laptop.org>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:olpc-xo1");
+
+module_init(olpc_xo1_init);
+module_exit(olpc_xo1_exit);
diff --git a/arch/x86/kernel/olpc.c b/arch/x86/kernel/olpc.c
index 0e0cdde519be..edaf3fe8dc5e 100644
--- a/arch/x86/kernel/olpc.c
+++ b/arch/x86/kernel/olpc.c
@@ -17,6 +17,7 @@
#include <linux/spinlock.h>
#include <linux/io.h>
#include <linux/string.h>
+#include <linux/platform_device.h>
#include <asm/geode.h>
#include <asm/setup.h>
@@ -114,6 +115,7 @@ int olpc_ec_cmd(unsigned char cmd, unsigned char *inbuf, size_t inlen,
unsigned long flags;
int ret = -EIO;
int i;
+ int restarts = 0;
spin_lock_irqsave(&ec_lock, flags);
@@ -169,7 +171,9 @@ restart:
if (wait_on_obf(0x6c, 1)) {
printk(KERN_ERR "olpc-ec: timeout waiting for"
" EC to provide data!\n");
- goto restart;
+ if (restarts++ < 10)
+ goto restart;
+ goto err;
}
outbuf[i] = inb(0x68);
pr_devel("olpc-ec: received 0x%x\n", outbuf[i]);
@@ -183,8 +187,21 @@ err:
}
EXPORT_SYMBOL_GPL(olpc_ec_cmd);
-#ifdef CONFIG_OLPC_OPENFIRMWARE
-static void __init platform_detect(void)
+static bool __init check_ofw_architecture(void)
+{
+ size_t propsize;
+ char olpc_arch[5];
+ const void *args[] = { NULL, "architecture", olpc_arch, (void *)5 };
+ void *res[] = { &propsize };
+
+ if (olpc_ofw("getprop", args, res)) {
+ printk(KERN_ERR "ofw: getprop call failed!\n");
+ return false;
+ }
+ return propsize == 5 && strncmp("OLPC", olpc_arch, 5) == 0;
+}
+
+static u32 __init get_board_revision(void)
{
size_t propsize;
__be32 rev;
@@ -193,45 +210,43 @@ static void __init platform_detect(void)
if (olpc_ofw("getprop", args, res) || propsize != 4) {
printk(KERN_ERR "ofw: getprop call failed!\n");
- rev = cpu_to_be32(0);
+ return cpu_to_be32(0);
}
- olpc_platform_info.boardrev = be32_to_cpu(rev);
+ return be32_to_cpu(rev);
}
-#else
-static void __init platform_detect(void)
+
+static bool __init platform_detect(void)
{
- /* stopgap until OFW support is added to the kernel */
- olpc_platform_info.boardrev = olpc_board(0xc2);
+ if (!check_ofw_architecture())
+ return false;
+ olpc_platform_info.flags |= OLPC_F_PRESENT;
+ olpc_platform_info.boardrev = get_board_revision();
+ return true;
}
-#endif
-static int __init olpc_init(void)
+static int __init add_xo1_platform_devices(void)
{
- unsigned char *romsig;
+ struct platform_device *pdev;
- /* The ioremap check is dangerous; limit what we run it on */
- if (!is_geode() || cs5535_has_vsa2())
- return 0;
+ pdev = platform_device_register_simple("xo1-rfkill", -1, NULL, 0);
+ if (IS_ERR(pdev))
+ return PTR_ERR(pdev);
- spin_lock_init(&ec_lock);
+ pdev = platform_device_register_simple("olpc-xo1", -1, NULL, 0);
+ if (IS_ERR(pdev))
+ return PTR_ERR(pdev);
- romsig = ioremap(0xffffffc0, 16);
- if (!romsig)
- return 0;
+ return 0;
+}
- if (strncmp(romsig, "CL1 Q", 7))
- goto unmap;
- if (strncmp(romsig+6, romsig+13, 3)) {
- printk(KERN_INFO "OLPC BIOS signature looks invalid. "
- "Assuming not OLPC\n");
- goto unmap;
- }
+static int __init olpc_init(void)
+{
+ int r = 0;
- printk(KERN_INFO "OLPC board with OpenFirmware %.16s\n", romsig);
- olpc_platform_info.flags |= OLPC_F_PRESENT;
+ if (!olpc_ofw_present() || !platform_detect())
+ return 0;
- /* get the platform revision */
- platform_detect();
+ spin_lock_init(&ec_lock);
/* assume B1 and above models always have a DCON */
if (olpc_board_at_least(olpc_board(0xb1)))
@@ -242,8 +257,10 @@ static int __init olpc_init(void)
(unsigned char *) &olpc_platform_info.ecver, 1);
#ifdef CONFIG_PCI_OLPC
- /* If the VSA exists let it emulate PCI, if not emulate in kernel */
- if (!cs5535_has_vsa2())
+ /* If the VSA exists let it emulate PCI, if not emulate in kernel.
+ * XO-1 only. */
+ if (olpc_platform_info.boardrev < olpc_board_pre(0xd0) &&
+ !cs5535_has_vsa2())
x86_init.pci.arch_init = pci_olpc_init;
#endif
@@ -252,8 +269,12 @@ static int __init olpc_init(void)
olpc_platform_info.boardrev >> 4,
olpc_platform_info.ecver);
-unmap:
- iounmap(romsig);
+ if (olpc_platform_info.boardrev < olpc_board_pre(0xd0)) { /* XO-1 */
+ r = add_xo1_platform_devices();
+ if (r)
+ return r;
+ }
+
return 0;
}
diff --git a/arch/x86/kernel/olpc_ofw.c b/arch/x86/kernel/olpc_ofw.c
index 3218aa71ab5e..787320464379 100644
--- a/arch/x86/kernel/olpc_ofw.c
+++ b/arch/x86/kernel/olpc_ofw.c
@@ -74,6 +74,12 @@ int __olpc_ofw(const char *name, int nr_args, const void **args, int nr_res,
}
EXPORT_SYMBOL_GPL(__olpc_ofw);
+bool olpc_ofw_present(void)
+{
+ return olpc_ofw_cif != NULL;
+}
+EXPORT_SYMBOL_GPL(olpc_ofw_present);
+
/* OFW cif _should_ be above this address */
#define OFW_MIN 0xff000000
diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c
index 1db183ed7c01..c5b250011fd4 100644
--- a/arch/x86/kernel/paravirt.c
+++ b/arch/x86/kernel/paravirt.c
@@ -413,7 +413,6 @@ struct pv_mmu_ops pv_mmu_ops = {
.alloc_pte = paravirt_nop,
.alloc_pmd = paravirt_nop,
- .alloc_pmd_clone = paravirt_nop,
.alloc_pud = paravirt_nop,
.release_pte = paravirt_nop,
.release_pmd = paravirt_nop,
diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c
index 078d4ec1a9d9..f56a117cef68 100644
--- a/arch/x86/kernel/pci-calgary_64.c
+++ b/arch/x86/kernel/pci-calgary_64.c
@@ -47,6 +47,7 @@
#include <asm/rio.h>
#include <asm/bios_ebda.h>
#include <asm/x86_init.h>
+#include <asm/iommu_table.h>
#ifdef CONFIG_CALGARY_IOMMU_ENABLED_BY_DEFAULT
int use_calgary __read_mostly = 1;
@@ -1364,7 +1365,7 @@ static int __init calgary_iommu_init(void)
return 0;
}
-void __init detect_calgary(void)
+int __init detect_calgary(void)
{
int bus;
void *tbl;
@@ -1378,13 +1379,13 @@ void __init detect_calgary(void)
* another HW IOMMU already, bail out.
*/
if (no_iommu || iommu_detected)
- return;
+ return -ENODEV;
if (!use_calgary)
- return;
+ return -ENODEV;
if (!early_pci_allowed())
- return;
+ return -ENODEV;
printk(KERN_DEBUG "Calgary: detecting Calgary via BIOS EBDA area\n");
@@ -1410,13 +1411,13 @@ void __init detect_calgary(void)
if (!rio_table_hdr) {
printk(KERN_DEBUG "Calgary: Unable to locate Rio Grande table "
"in EBDA - bailing!\n");
- return;
+ return -ENODEV;
}
ret = build_detail_arrays();
if (ret) {
printk(KERN_DEBUG "Calgary: build_detail_arrays ret %d\n", ret);
- return;
+ return -ENOMEM;
}
specified_table_size = determine_tce_table_size((is_kdump_kernel() ?
@@ -1464,7 +1465,7 @@ void __init detect_calgary(void)
x86_init.iommu.iommu_init = calgary_iommu_init;
}
- return;
+ return calgary_found;
cleanup:
for (--bus; bus >= 0; --bus) {
@@ -1473,6 +1474,7 @@ cleanup:
if (info->tce_space)
free_tce_table(info->tce_space);
}
+ return -ENOMEM;
}
static int __init calgary_parse_options(char *p)
@@ -1594,3 +1596,5 @@ static int __init calgary_fixup_tce_spaces(void)
* and before device_initcall.
*/
rootfs_initcall(calgary_fixup_tce_spaces);
+
+IOMMU_INIT_POST(detect_calgary);
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c
index 9f07cfcbd3a5..9ea999a4dcc1 100644
--- a/arch/x86/kernel/pci-dma.c
+++ b/arch/x86/kernel/pci-dma.c
@@ -11,9 +11,8 @@
#include <asm/iommu.h>
#include <asm/gart.h>
#include <asm/calgary.h>
-#include <asm/amd_iommu.h>
#include <asm/x86_init.h>
-#include <asm/xen/swiotlb-xen.h>
+#include <asm/iommu_table.h>
static int forbid_dac __read_mostly;
@@ -45,6 +44,8 @@ int iommu_detected __read_mostly = 0;
*/
int iommu_pass_through __read_mostly;
+extern struct iommu_table_entry __iommu_table[], __iommu_table_end[];
+
/* Dummy device used for NULL arguments (normally ISA). */
struct device x86_dma_fallback_dev = {
.init_name = "fallback device",
@@ -130,26 +131,24 @@ static void __init dma32_free_bootmem(void)
void __init pci_iommu_alloc(void)
{
+ struct iommu_table_entry *p;
+
/* free the range so iommu could get some range less than 4G */
dma32_free_bootmem();
- if (pci_xen_swiotlb_detect() || pci_swiotlb_detect())
- goto out;
-
- gart_iommu_hole_init();
-
- detect_calgary();
-
- detect_intel_iommu();
+ sort_iommu_table(__iommu_table, __iommu_table_end);
+ check_iommu_entries(__iommu_table, __iommu_table_end);
- /* needs to be called after gart_iommu_hole_init */
- amd_iommu_detect();
-out:
- pci_xen_swiotlb_init();
-
- pci_swiotlb_init();
+ for (p = __iommu_table; p < __iommu_table_end; p++) {
+ if (p && p->detect && p->detect() > 0) {
+ p->flags |= IOMMU_DETECTED;
+ if (p->early_init)
+ p->early_init();
+ if (p->flags & IOMMU_FINISH_IF_DETECTED)
+ break;
+ }
+ }
}
-
void *dma_generic_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_addr, gfp_t flag)
{
@@ -292,6 +291,7 @@ EXPORT_SYMBOL(dma_supported);
static int __init pci_iommu_init(void)
{
+ struct iommu_table_entry *p;
dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);
#ifdef CONFIG_PCI
@@ -299,12 +299,10 @@ static int __init pci_iommu_init(void)
#endif
x86_init.iommu.iommu_init();
- if (swiotlb || xen_swiotlb) {
- printk(KERN_INFO "PCI-DMA: "
- "Using software bounce buffering for IO (SWIOTLB)\n");
- swiotlb_print_info();
- } else
- swiotlb_free();
+ for (p = __iommu_table; p < __iommu_table_end; p++) {
+ if (p && (p->flags & IOMMU_DETECTED) && p->late_init)
+ p->late_init();
+ }
return 0;
}
diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c
index 0f7f130caa67..ba0f0ca9f280 100644
--- a/arch/x86/kernel/pci-gart_64.c
+++ b/arch/x86/kernel/pci-gart_64.c
@@ -39,8 +39,9 @@
#include <asm/cacheflush.h>
#include <asm/swiotlb.h>
#include <asm/dma.h>
-#include <asm/k8.h>
+#include <asm/amd_nb.h>
#include <asm/x86_init.h>
+#include <asm/iommu_table.h>
static unsigned long iommu_bus_base; /* GART remapping area (physical) */
static unsigned long iommu_size; /* size of remapping area bytes */
@@ -560,8 +561,11 @@ static void enable_gart_translations(void)
{
int i;
- for (i = 0; i < num_k8_northbridges; i++) {
- struct pci_dev *dev = k8_northbridges[i];
+ if (!k8_northbridges.gart_supported)
+ return;
+
+ for (i = 0; i < k8_northbridges.num; i++) {
+ struct pci_dev *dev = k8_northbridges.nb_misc[i];
enable_gart_translation(dev, __pa(agp_gatt_table));
}
@@ -592,16 +596,19 @@ static void gart_fixup_northbridges(struct sys_device *dev)
if (!fix_up_north_bridges)
return;
+ if (!k8_northbridges.gart_supported)
+ return;
+
pr_info("PCI-DMA: Restoring GART aperture settings\n");
- for (i = 0; i < num_k8_northbridges; i++) {
- struct pci_dev *dev = k8_northbridges[i];
+ for (i = 0; i < k8_northbridges.num; i++) {
+ struct pci_dev *dev = k8_northbridges.nb_misc[i];
/*
* Don't enable translations just yet. That is the next
* step. Restore the pre-suspend aperture settings.
*/
- pci_write_config_dword(dev, AMD64_GARTAPERTURECTL, aperture_order << 1);
+ gart_set_size_and_enable(dev, aperture_order);
pci_write_config_dword(dev, AMD64_GARTAPERTUREBASE, aperture_alloc >> 25);
}
}
@@ -649,8 +656,8 @@ static __init int init_k8_gatt(struct agp_kern_info *info)
aper_size = aper_base = info->aper_size = 0;
dev = NULL;
- for (i = 0; i < num_k8_northbridges; i++) {
- dev = k8_northbridges[i];
+ for (i = 0; i < k8_northbridges.num; i++) {
+ dev = k8_northbridges.nb_misc[i];
new_aper_base = read_aperture(dev, &new_aper_size);
if (!new_aper_base)
goto nommu;
@@ -718,10 +725,13 @@ static void gart_iommu_shutdown(void)
if (!no_agp)
return;
- for (i = 0; i < num_k8_northbridges; i++) {
+ if (!k8_northbridges.gart_supported)
+ return;
+
+ for (i = 0; i < k8_northbridges.num; i++) {
u32 ctl;
- dev = k8_northbridges[i];
+ dev = k8_northbridges.nb_misc[i];
pci_read_config_dword(dev, AMD64_GARTAPERTURECTL, &ctl);
ctl &= ~GARTEN;
@@ -739,7 +749,7 @@ int __init gart_iommu_init(void)
unsigned long scratch;
long i;
- if (num_k8_northbridges == 0)
+ if (!k8_northbridges.gart_supported)
return 0;
#ifndef CONFIG_AGP_AMD64
@@ -896,3 +906,4 @@ void __init gart_parse_options(char *p)
}
}
}
+IOMMU_INIT_POST(gart_iommu_hole_init);
diff --git a/arch/x86/kernel/pci-iommu_table.c b/arch/x86/kernel/pci-iommu_table.c
new file mode 100644
index 000000000000..55d745ec1181
--- /dev/null
+++ b/arch/x86/kernel/pci-iommu_table.c
@@ -0,0 +1,89 @@
+#include <linux/dma-mapping.h>
+#include <asm/iommu_table.h>
+#include <linux/string.h>
+#include <linux/kallsyms.h>
+
+
+#define DEBUG 1
+
+static struct iommu_table_entry * __init
+find_dependents_of(struct iommu_table_entry *start,
+ struct iommu_table_entry *finish,
+ struct iommu_table_entry *q)
+{
+ struct iommu_table_entry *p;
+
+ if (!q)
+ return NULL;
+
+ for (p = start; p < finish; p++)
+ if (p->detect == q->depend)
+ return p;
+
+ return NULL;
+}
+
+
+void __init sort_iommu_table(struct iommu_table_entry *start,
+ struct iommu_table_entry *finish) {
+
+ struct iommu_table_entry *p, *q, tmp;
+
+ for (p = start; p < finish; p++) {
+again:
+ q = find_dependents_of(start, finish, p);
+ /* We are bit sneaky here. We use the memory address to figure
+ * out if the node we depend on is past our point, if so, swap.
+ */
+ if (q > p) {
+ tmp = *p;
+ memmove(p, q, sizeof(*p));
+ *q = tmp;
+ goto again;
+ }
+ }
+
+}
+
+#ifdef DEBUG
+void __init check_iommu_entries(struct iommu_table_entry *start,
+ struct iommu_table_entry *finish)
+{
+ struct iommu_table_entry *p, *q, *x;
+ char sym_p[KSYM_SYMBOL_LEN];
+ char sym_q[KSYM_SYMBOL_LEN];
+
+ /* Simple cyclic dependency checker. */
+ for (p = start; p < finish; p++) {
+ q = find_dependents_of(start, finish, p);
+ x = find_dependents_of(start, finish, q);
+ if (p == x) {
+ sprint_symbol(sym_p, (unsigned long)p->detect);
+ sprint_symbol(sym_q, (unsigned long)q->detect);
+
+ printk(KERN_ERR "CYCLIC DEPENDENCY FOUND! %s depends" \
+ " on %s and vice-versa. BREAKING IT.\n",
+ sym_p, sym_q);
+ /* Heavy handed way..*/
+ x->depend = 0;
+ }
+ }
+
+ for (p = start; p < finish; p++) {
+ q = find_dependents_of(p, finish, p);
+ if (q && q > p) {
+ sprint_symbol(sym_p, (unsigned long)p->detect);
+ sprint_symbol(sym_q, (unsigned long)q->detect);
+
+ printk(KERN_ERR "EXECUTION ORDER INVALID! %s "\
+ "should be called before %s!\n",
+ sym_p, sym_q);
+ }
+ }
+}
+#else
+inline void check_iommu_entries(struct iommu_table_entry *start,
+ struct iommu_table_entry *finish)
+{
+}
+#endif
diff --git a/arch/x86/kernel/pci-swiotlb.c b/arch/x86/kernel/pci-swiotlb.c
index a5bc528d4328..8f972cbddef0 100644
--- a/arch/x86/kernel/pci-swiotlb.c
+++ b/arch/x86/kernel/pci-swiotlb.c
@@ -10,7 +10,8 @@
#include <asm/iommu.h>
#include <asm/swiotlb.h>
#include <asm/dma.h>
-
+#include <asm/xen/swiotlb-xen.h>
+#include <asm/iommu_table.h>
int swiotlb __read_mostly;
static void *x86_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
@@ -41,25 +42,42 @@ static struct dma_map_ops swiotlb_dma_ops = {
};
/*
- * pci_swiotlb_detect - set swiotlb to 1 if necessary
+ * pci_swiotlb_detect_override - set swiotlb to 1 if necessary
*
* This returns non-zero if we are forced to use swiotlb (by the boot
* option).
*/
-int __init pci_swiotlb_detect(void)
+int __init pci_swiotlb_detect_override(void)
{
int use_swiotlb = swiotlb | swiotlb_force;
+ if (swiotlb_force)
+ swiotlb = 1;
+
+ return use_swiotlb;
+}
+IOMMU_INIT_FINISH(pci_swiotlb_detect_override,
+ pci_xen_swiotlb_detect,
+ pci_swiotlb_init,
+ pci_swiotlb_late_init);
+
+/*
+ * if 4GB or more detected (and iommu=off not set) return 1
+ * and set swiotlb to 1.
+ */
+int __init pci_swiotlb_detect_4gb(void)
+{
/* don't initialize swiotlb if iommu=off (no_iommu=1) */
#ifdef CONFIG_X86_64
if (!no_iommu && max_pfn > MAX_DMA32_PFN)
swiotlb = 1;
#endif
- if (swiotlb_force)
- swiotlb = 1;
-
- return use_swiotlb;
+ return swiotlb;
}
+IOMMU_INIT(pci_swiotlb_detect_4gb,
+ pci_swiotlb_detect_override,
+ pci_swiotlb_init,
+ pci_swiotlb_late_init);
void __init pci_swiotlb_init(void)
{
@@ -68,3 +86,15 @@ void __init pci_swiotlb_init(void)
dma_ops = &swiotlb_dma_ops;
}
}
+
+void __init pci_swiotlb_late_init(void)
+{
+ /* An IOMMU turned us off. */
+ if (!swiotlb)
+ swiotlb_free();
+ else {
+ printk(KERN_INFO "PCI-DMA: "
+ "Using software bounce buffering for IO (SWIOTLB)\n");
+ swiotlb_print_info();
+ }
+}
diff --git a/arch/x86/kernel/pmtimer_64.c b/arch/x86/kernel/pmtimer_64.c
deleted file mode 100644
index b112406f1996..000000000000
--- a/arch/x86/kernel/pmtimer_64.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/* Ported over from i386 by AK, original copyright was:
- *
- * (C) Dominik Brodowski <linux@brodo.de> 2003
- *
- * Driver to use the Power Management Timer (PMTMR) available in some
- * southbridges as primary timing source for the Linux kernel.
- *
- * Based on parts of linux/drivers/acpi/hardware/hwtimer.c, timer_pit.c,
- * timer_hpet.c, and on Arjan van de Ven's implementation for 2.4.
- *
- * This file is licensed under the GPL v2.
- *
- * Dropped all the hardware bug workarounds for now. Hopefully they
- * are not needed on 64bit chipsets.
- */
-
-#include <linux/jiffies.h>
-#include <linux/kernel.h>
-#include <linux/time.h>
-#include <linux/init.h>
-#include <linux/cpumask.h>
-#include <linux/acpi_pmtmr.h>
-
-#include <asm/io.h>
-#include <asm/proto.h>
-#include <asm/msr.h>
-#include <asm/vsyscall.h>
-
-static inline u32 cyc2us(u32 cycles)
-{
- /* The Power Management Timer ticks at 3.579545 ticks per microsecond.
- * 1 / PM_TIMER_FREQUENCY == 0.27936511 =~ 286/1024 [error: 0.024%]
- *
- * Even with HZ = 100, delta is at maximum 35796 ticks, so it can
- * easily be multiplied with 286 (=0x11E) without having to fear
- * u32 overflows.
- */
- cycles *= 286;
- return (cycles >> 10);
-}
-
-static unsigned pmtimer_wait_tick(void)
-{
- u32 a, b;
- for (a = b = inl(pmtmr_ioport) & ACPI_PM_MASK;
- a == b;
- b = inl(pmtmr_ioport) & ACPI_PM_MASK)
- cpu_relax();
- return b;
-}
-
-/* note: wait time is rounded up to one tick */
-void pmtimer_wait(unsigned us)
-{
- u32 a, b;
- a = pmtimer_wait_tick();
- do {
- b = inl(pmtmr_ioport);
- cpu_relax();
- } while (cyc2us(b - a) < us);
-}
-
-static int __init nopmtimer_setup(char *s)
-{
- pmtmr_ioport = 0;
- return 1;
-}
-
-__setup("nopmtimer", nopmtimer_setup);
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index 3d9ea531ddd1..b3d7a3a04f38 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -424,7 +424,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
load_TLS(next, cpu);
/* Must be after DS reload */
- unlazy_fpu(prev_p);
+ __unlazy_fpu(prev_p);
/* Make sure cpu is ready for new context */
if (preload_fpu)
diff --git a/arch/x86/kernel/quirks.c b/arch/x86/kernel/quirks.c
index 939b9e98245f..8bbe8c56916d 100644
--- a/arch/x86/kernel/quirks.c
+++ b/arch/x86/kernel/quirks.c
@@ -344,6 +344,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235,
vt8237_force_enable_hpet);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237,
vt8237_force_enable_hpet);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_CX700,
+ vt8237_force_enable_hpet);
static void ati_force_hpet_resume(void)
{
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index e3af342fe83a..f7f53dcd3e0a 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -84,7 +84,7 @@ static int __init reboot_setup(char *str)
}
/* we will leave sorting out the final value
when we are ready to reboot, since we might not
- have set up boot_cpu_id or smp_num_cpu */
+ have detected BSP APIC ID or smp_num_cpu */
break;
#endif /* CONFIG_SMP */
@@ -371,16 +371,10 @@ void machine_real_restart(const unsigned char *code, int length)
CMOS_WRITE(0x00, 0x8f);
spin_unlock(&rtc_lock);
- /* Remap the kernel at virtual address zero, as well as offset zero
- from the kernel segment. This assumes the kernel segment starts at
- virtual address PAGE_OFFSET. */
- memcpy(swapper_pg_dir, swapper_pg_dir + KERNEL_PGD_BOUNDARY,
- sizeof(swapper_pg_dir [0]) * KERNEL_PGD_PTRS);
-
/*
- * Use `swapper_pg_dir' as our page directory.
+ * Switch back to the initial page table.
*/
- load_cr3(swapper_pg_dir);
+ load_cr3(initial_page_table);
/* Write 0x1234 to absolute memory location 0x472. The BIOS reads
this on booting to tell it to "Bypass memory test (also warm
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index c3a4fbb2b996..95a32746fbf9 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -31,6 +31,7 @@
#include <linux/apm_bios.h>
#include <linux/initrd.h>
#include <linux/bootmem.h>
+#include <linux/memblock.h>
#include <linux/seq_file.h>
#include <linux/console.h>
#include <linux/mca.h>
@@ -83,7 +84,6 @@
#include <asm/dmi.h>
#include <asm/io_apic.h>
#include <asm/ist.h>
-#include <asm/vmi.h>
#include <asm/setup_arch.h>
#include <asm/bios_ebda.h>
#include <asm/cacheflush.h>
@@ -107,11 +107,12 @@
#include <asm/percpu.h>
#include <asm/topology.h>
#include <asm/apicdef.h>
-#include <asm/k8.h>
+#include <asm/amd_nb.h>
#ifdef CONFIG_X86_64
#include <asm/numa_64.h>
#endif
#include <asm/mce.h>
+#include <asm/alternative.h>
/*
* end_pfn only includes RAM, while max_pfn_mapped includes all e820 entries.
@@ -125,7 +126,6 @@ unsigned long max_pfn_mapped;
RESERVE_BRK(dmi_alloc, 65536);
#endif
-unsigned int boot_cpu_id __read_mostly;
static __initdata unsigned long _brk_start = (unsigned long)__brk_base;
unsigned long _brk_end = (unsigned long)__brk_base;
@@ -302,7 +302,7 @@ static inline void init_gbpages(void)
static void __init reserve_brk(void)
{
if (_brk_end > _brk_start)
- reserve_early(__pa(_brk_start), __pa(_brk_end), "BRK");
+ memblock_x86_reserve_range(__pa(_brk_start), __pa(_brk_end), "BRK");
/* Mark brk area as locked down and no longer taking any
new allocations */
@@ -324,17 +324,16 @@ static void __init relocate_initrd(void)
char *p, *q;
/* We need to move the initrd down into lowmem */
- ramdisk_here = find_e820_area(0, end_of_lowmem, area_size,
+ ramdisk_here = memblock_find_in_range(0, end_of_lowmem, area_size,
PAGE_SIZE);
- if (ramdisk_here == -1ULL)
+ if (ramdisk_here == MEMBLOCK_ERROR)
panic("Cannot find place for new RAMDISK of size %lld\n",
ramdisk_size);
/* Note: this includes all the lowmem currently occupied by
the initrd, we rely on that fact to keep the data intact. */
- reserve_early(ramdisk_here, ramdisk_here + area_size,
- "NEW RAMDISK");
+ memblock_x86_reserve_range(ramdisk_here, ramdisk_here + area_size, "NEW RAMDISK");
initrd_start = ramdisk_here + PAGE_OFFSET;
initrd_end = initrd_start + ramdisk_size;
printk(KERN_INFO "Allocated new RAMDISK: %08llx - %08llx\n",
@@ -390,7 +389,7 @@ static void __init reserve_initrd(void)
initrd_start = 0;
if (ramdisk_size >= (end_of_lowmem>>1)) {
- free_early(ramdisk_image, ramdisk_end);
+ memblock_x86_free_range(ramdisk_image, ramdisk_end);
printk(KERN_ERR "initrd too large to handle, "
"disabling initrd\n");
return;
@@ -413,7 +412,7 @@ static void __init reserve_initrd(void)
relocate_initrd();
- free_early(ramdisk_image, ramdisk_end);
+ memblock_x86_free_range(ramdisk_image, ramdisk_end);
}
#else
static void __init reserve_initrd(void)
@@ -469,7 +468,7 @@ static void __init e820_reserve_setup_data(void)
e820_print_map("reserve setup_data");
}
-static void __init reserve_early_setup_data(void)
+static void __init memblock_x86_reserve_range_setup_data(void)
{
struct setup_data *data;
u64 pa_data;
@@ -481,7 +480,7 @@ static void __init reserve_early_setup_data(void)
while (pa_data) {
data = early_memremap(pa_data, sizeof(*data));
sprintf(buf, "setup data %x", data->type);
- reserve_early(pa_data, pa_data+sizeof(*data)+data->len, buf);
+ memblock_x86_reserve_range(pa_data, pa_data+sizeof(*data)+data->len, buf);
pa_data = data->next;
early_iounmap(data, sizeof(*data));
}
@@ -502,6 +501,7 @@ static inline unsigned long long get_total_mem(void)
return total << PAGE_SHIFT;
}
+#define DEFAULT_BZIMAGE_ADDR_MAX 0x37FFFFFF
static void __init reserve_crashkernel(void)
{
unsigned long long total_mem;
@@ -519,23 +519,27 @@ static void __init reserve_crashkernel(void)
if (crash_base <= 0) {
const unsigned long long alignment = 16<<20; /* 16M */
- crash_base = find_e820_area(alignment, ULONG_MAX, crash_size,
- alignment);
- if (crash_base == -1ULL) {
+ /*
+ * kexec want bzImage is below DEFAULT_BZIMAGE_ADDR_MAX
+ */
+ crash_base = memblock_find_in_range(alignment,
+ DEFAULT_BZIMAGE_ADDR_MAX, crash_size, alignment);
+
+ if (crash_base == MEMBLOCK_ERROR) {
pr_info("crashkernel reservation failed - No suitable area found.\n");
return;
}
} else {
unsigned long long start;
- start = find_e820_area(crash_base, ULONG_MAX, crash_size,
- 1<<20);
+ start = memblock_find_in_range(crash_base,
+ crash_base + crash_size, crash_size, 1<<20);
if (start != crash_base) {
pr_info("crashkernel reservation failed - memory is in use.\n");
return;
}
}
- reserve_early(crash_base, crash_base + crash_size, "CRASH KERNEL");
+ memblock_x86_reserve_range(crash_base, crash_base + crash_size, "CRASH KERNEL");
printk(KERN_INFO "Reserving %ldMB of memory at %ldMB "
"for crashkernel (System RAM: %ldMB)\n",
@@ -615,82 +619,10 @@ static __init void reserve_ibft_region(void)
addr = find_ibft_region(&size);
if (size)
- reserve_early_overlap_ok(addr, addr + size, "ibft");
+ memblock_x86_reserve_range(addr, addr + size, "* ibft");
}
-#ifdef CONFIG_X86_RESERVE_LOW_64K
-static int __init dmi_low_memory_corruption(const struct dmi_system_id *d)
-{
- printk(KERN_NOTICE
- "%s detected: BIOS may corrupt low RAM, working around it.\n",
- d->ident);
-
- e820_update_range(0, 0x10000, E820_RAM, E820_RESERVED);
- sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
-
- return 0;
-}
-#endif
-
-/* List of systems that have known low memory corruption BIOS problems */
-static struct dmi_system_id __initdata bad_bios_dmi_table[] = {
-#ifdef CONFIG_X86_RESERVE_LOW_64K
- {
- .callback = dmi_low_memory_corruption,
- .ident = "AMI BIOS",
- .matches = {
- DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."),
- },
- },
- {
- .callback = dmi_low_memory_corruption,
- .ident = "Phoenix BIOS",
- .matches = {
- DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies"),
- },
- },
- {
- .callback = dmi_low_memory_corruption,
- .ident = "Phoenix/MSC BIOS",
- .matches = {
- DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix/MSC"),
- },
- },
- /*
- * AMI BIOS with low memory corruption was found on Intel DG45ID and
- * DG45FC boards.
- * It has a different DMI_BIOS_VENDOR = "Intel Corp.", for now we will
- * match only DMI_BOARD_NAME and see if there is more bad products
- * with this vendor.
- */
- {
- .callback = dmi_low_memory_corruption,
- .ident = "AMI BIOS",
- .matches = {
- DMI_MATCH(DMI_BOARD_NAME, "DG45ID"),
- },
- },
- {
- .callback = dmi_low_memory_corruption,
- .ident = "AMI BIOS",
- .matches = {
- DMI_MATCH(DMI_BOARD_NAME, "DG45FC"),
- },
- },
- /*
- * The Dell Inspiron Mini 1012 has DMI_BIOS_VENDOR = "Dell Inc.", so
- * match on the product name.
- */
- {
- .callback = dmi_low_memory_corruption,
- .ident = "Phoenix BIOS",
- .matches = {
- DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1012"),
- },
- },
-#endif
- {}
-};
+static unsigned reserve_low = CONFIG_X86_RESERVE_LOW << 10;
static void __init trim_bios_range(void)
{
@@ -698,8 +630,14 @@ static void __init trim_bios_range(void)
* A special case is the first 4Kb of memory;
* This is a BIOS owned area, not kernel ram, but generally
* not listed as such in the E820 table.
+ *
+ * This typically reserves additional memory (64KiB by default)
+ * since some BIOSes are known to corrupt low memory. See the
+ * Kconfig help text for X86_RESERVE_LOW.
*/
- e820_update_range(0, PAGE_SIZE, E820_RAM, E820_RESERVED);
+ e820_update_range(0, ALIGN(reserve_low, PAGE_SIZE),
+ E820_RAM, E820_RESERVED);
+
/*
* special case: Some BIOSen report the PC BIOS
* area (640->1Mb) as ram even though it is not.
@@ -709,6 +647,37 @@ static void __init trim_bios_range(void)
sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
}
+static int __init parse_reservelow(char *p)
+{
+ unsigned long long size;
+
+ if (!p)
+ return -EINVAL;
+
+ size = memparse(p, &p);
+
+ if (size < 4096)
+ size = 4096;
+
+ if (size > 640*1024)
+ size = 640*1024;
+
+ reserve_low = size;
+
+ return 0;
+}
+
+early_param("reservelow", parse_reservelow);
+
+static u64 __init get_max_mapped(void)
+{
+ u64 end = max_pfn_mapped;
+
+ end <<= PAGE_SHIFT;
+
+ return end;
+}
+
/*
* Determine if we were loaded by an EFI loader. If so, then we have also been
* passed the efi memmap, systab, etc., so we should use these data structures
@@ -726,18 +695,30 @@ void __init setup_arch(char **cmdline_p)
{
int acpi = 0;
int k8 = 0;
+ unsigned long flags;
#ifdef CONFIG_X86_32
memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data));
visws_early_detect();
+
+ /*
+ * copy kernel address range established so far and switch
+ * to the proper swapper page table
+ */
+ clone_pgd_range(swapper_pg_dir + KERNEL_PGD_BOUNDARY,
+ initial_page_table + KERNEL_PGD_BOUNDARY,
+ KERNEL_PGD_PTRS);
+
+ load_cr3(swapper_pg_dir);
+ __flush_tlb_all();
#else
printk(KERN_INFO "Command line: %s\n", boot_command_line);
#endif
- /* VMI may relocate the fixmap; do this before touching ioremap area */
- vmi_init();
-
- /* OFW also may relocate the fixmap */
+ /*
+ * If we have OLPC OFW, we might end up relocating the fixmap due to
+ * reserve_top(), so do this before touching the ioremap area.
+ */
olpc_ofw_detect();
early_trap_init();
@@ -782,7 +763,7 @@ void __init setup_arch(char **cmdline_p)
#endif
4)) {
efi_enabled = 1;
- efi_reserve_early();
+ efi_memblock_x86_reserve_range();
}
#endif
@@ -838,11 +819,8 @@ void __init setup_arch(char **cmdline_p)
x86_report_nx();
- /* Must be before kernel pagetables are setup */
- vmi_activate();
-
/* after early param, so could get panic from serial */
- reserve_early_setup_data();
+ memblock_x86_reserve_range_setup_data();
if (acpi_mps_check()) {
#ifdef CONFIG_X86_LOCAL_APIC
@@ -863,8 +841,6 @@ void __init setup_arch(char **cmdline_p)
dmi_scan_machine();
- dmi_check_system(bad_bios_dmi_table);
-
/*
* VMware detection requires dmi to be available, so this
* needs to be done after dmi_scan_machine, for the BP.
@@ -897,8 +873,6 @@ void __init setup_arch(char **cmdline_p)
*/
max_pfn = e820_end_of_ram_pfn();
- /* preallocate 4k for mptable mpc */
- early_reserve_e820_mpc_new();
/* update e820 for memory not covered by WB MTRRs */
mtrr_bp_init();
if (mtrr_trim_uncached_memory(max_pfn))
@@ -920,18 +894,8 @@ void __init setup_arch(char **cmdline_p)
max_low_pfn = max_pfn;
high_memory = (void *)__va(max_pfn * PAGE_SIZE - 1) + 1;
- max_pfn_mapped = KERNEL_IMAGE_SIZE >> PAGE_SHIFT;
#endif
-#ifdef CONFIG_X86_CHECK_BIOS_CORRUPTION
- setup_bios_corruption_check();
-#endif
-
- printk(KERN_DEBUG "initial memory mapped : 0 - %08lx\n",
- max_pfn_mapped<<PAGE_SHIFT);
-
- reserve_brk();
-
/*
* Find and reserve possible boot-time SMP configuration:
*/
@@ -939,6 +903,26 @@ void __init setup_arch(char **cmdline_p)
reserve_ibft_region();
+ /*
+ * Need to conclude brk, before memblock_x86_fill()
+ * it could use memblock_find_in_range, could overlap with
+ * brk area.
+ */
+ reserve_brk();
+
+ memblock.current_limit = get_max_mapped();
+ memblock_x86_fill();
+
+ /* preallocate 4k for mptable mpc */
+ early_reserve_e820_mpc_new();
+
+#ifdef CONFIG_X86_CHECK_BIOS_CORRUPTION
+ setup_bios_corruption_check();
+#endif
+
+ printk(KERN_DEBUG "initial memory mapped : 0 - %08lx\n",
+ max_pfn_mapped<<PAGE_SHIFT);
+
reserve_trampoline_memory();
#ifdef CONFIG_ACPI_SLEEP
@@ -962,6 +946,7 @@ void __init setup_arch(char **cmdline_p)
max_low_pfn = max_pfn;
}
#endif
+ memblock.current_limit = get_max_mapped();
/*
* NOTE: On x86-32, only from this point on, fixmaps are ready for use.
@@ -1000,10 +985,7 @@ void __init setup_arch(char **cmdline_p)
#endif
initmem_init(0, max_pfn, acpi, k8);
-#ifndef CONFIG_NO_BOOTMEM
- early_res_to_bootmem(0, max_low_pfn<<PAGE_SHIFT);
-#endif
-
+ memblock_find_dma_reserve();
dma32_reserve_bootmem();
#ifdef CONFIG_KVM_CLOCK
@@ -1014,7 +996,12 @@ void __init setup_arch(char **cmdline_p)
paging_init();
x86_init.paging.pagetable_setup_done(swapper_pg_dir);
- setup_trampoline_page_table();
+#ifdef CONFIG_X86_32
+ /* sync back kernel address range */
+ clone_pgd_range(initial_page_table + KERNEL_PGD_BOUNDARY,
+ swapper_pg_dir + KERNEL_PGD_BOUNDARY,
+ KERNEL_PGD_PTRS);
+#endif
tboot_probe();
@@ -1071,6 +1058,10 @@ void __init setup_arch(char **cmdline_p)
x86_init.oem.banner();
mcheck_init();
+
+ local_irq_save(flags);
+ arch_init_ideal_nop5();
+ local_irq_restore(flags);
}
#ifdef CONFIG_X86_32
diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c
index a60df9ae6454..002b79685f73 100644
--- a/arch/x86/kernel/setup_percpu.c
+++ b/arch/x86/kernel/setup_percpu.c
@@ -131,13 +131,7 @@ static void * __init pcpu_fc_alloc(unsigned int cpu, size_t size, size_t align)
static void __init pcpu_fc_free(void *ptr, size_t size)
{
-#ifdef CONFIG_NO_BOOTMEM
- u64 start = __pa(ptr);
- u64 end = start + size;
- free_early_partial(start, end);
-#else
free_bootmem(__pa(ptr), size);
-#endif
}
static int __init pcpu_cpu_distance(unsigned int from, unsigned int to)
@@ -253,7 +247,7 @@ void __init setup_per_cpu_areas(void)
* Up to this point, the boot CPU has been using .init.data
* area. Reload any changed state for the boot CPU.
*/
- if (cpu == boot_cpu_id)
+ if (!cpu)
switch_to_new_gdt(cpu);
}
diff --git a/arch/x86/kernel/sfi.c b/arch/x86/kernel/sfi.c
index cb22acf3ed09..dd4c281ffe57 100644
--- a/arch/x86/kernel/sfi.c
+++ b/arch/x86/kernel/sfi.c
@@ -34,7 +34,7 @@
#ifdef CONFIG_X86_LOCAL_APIC
static unsigned long sfi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
-void __init mp_sfi_register_lapic_address(unsigned long address)
+static void __init mp_sfi_register_lapic_address(unsigned long address)
{
mp_lapic_addr = address;
@@ -46,7 +46,7 @@ void __init mp_sfi_register_lapic_address(unsigned long address)
}
/* All CPUs enumerated by SFI must be present and enabled */
-void __cpuinit mp_sfi_register_lapic(u8 id)
+static void __cpuinit mp_sfi_register_lapic(u8 id)
{
if (MAX_APICS - id <= 0) {
pr_warning("Processor #%d invalid (max %d)\n",
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 8b3bfc4dd708..6af118511b4a 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -62,7 +62,7 @@
#include <asm/pgtable.h>
#include <asm/tlbflush.h>
#include <asm/mtrr.h>
-#include <asm/vmi.h>
+#include <asm/mwait.h>
#include <asm/apic.h>
#include <asm/setup.h>
#include <asm/uv/uv.h>
@@ -299,23 +299,16 @@ notrace static void __cpuinit start_secondary(void *unused)
* fragile that we want to limit the things done here to the
* most necessary things.
*/
+ cpu_init();
+ preempt_disable();
+ smp_callin();
#ifdef CONFIG_X86_32
- /*
- * Switch away from the trampoline page-table
- *
- * Do this before cpu_init() because it needs to access per-cpu
- * data which may not be mapped in the trampoline page-table.
- */
+ /* switch away from the initial page table */
load_cr3(swapper_pg_dir);
__flush_tlb_all();
#endif
- vmi_bringup();
- cpu_init();
- preempt_disable();
- smp_callin();
-
/* otherwise gcc will move up smp_processor_id before the cpu_init */
barrier();
/*
@@ -324,9 +317,9 @@ notrace static void __cpuinit start_secondary(void *unused)
check_tsc_sync_target();
if (nmi_watchdog == NMI_IO_APIC) {
- legacy_pic->chip->mask(0);
+ legacy_pic->mask(0);
enable_NMI_through_LVT0();
- legacy_pic->chip->unmask(0);
+ legacy_pic->unmask(0);
}
/* This must be done before setting cpu_online_mask */
@@ -397,6 +390,19 @@ void __cpuinit smp_store_cpu_info(int id)
identify_secondary_cpu(c);
}
+static void __cpuinit link_thread_siblings(int cpu1, int cpu2)
+{
+ struct cpuinfo_x86 *c1 = &cpu_data(cpu1);
+ struct cpuinfo_x86 *c2 = &cpu_data(cpu2);
+
+ cpumask_set_cpu(cpu1, cpu_sibling_mask(cpu2));
+ cpumask_set_cpu(cpu2, cpu_sibling_mask(cpu1));
+ cpumask_set_cpu(cpu1, cpu_core_mask(cpu2));
+ cpumask_set_cpu(cpu2, cpu_core_mask(cpu1));
+ cpumask_set_cpu(cpu1, c2->llc_shared_map);
+ cpumask_set_cpu(cpu2, c1->llc_shared_map);
+}
+
void __cpuinit set_cpu_sibling_map(int cpu)
{
@@ -409,14 +415,13 @@ void __cpuinit set_cpu_sibling_map(int cpu)
for_each_cpu(i, cpu_sibling_setup_mask) {
struct cpuinfo_x86 *o = &cpu_data(i);
- if (c->phys_proc_id == o->phys_proc_id &&
- c->cpu_core_id == o->cpu_core_id) {
- cpumask_set_cpu(i, cpu_sibling_mask(cpu));
- cpumask_set_cpu(cpu, cpu_sibling_mask(i));
- cpumask_set_cpu(i, cpu_core_mask(cpu));
- cpumask_set_cpu(cpu, cpu_core_mask(i));
- cpumask_set_cpu(i, c->llc_shared_map);
- cpumask_set_cpu(cpu, o->llc_shared_map);
+ if (cpu_has(c, X86_FEATURE_TOPOEXT)) {
+ if (c->phys_proc_id == o->phys_proc_id &&
+ c->compute_unit_id == o->compute_unit_id)
+ link_thread_siblings(cpu, i);
+ } else if (c->phys_proc_id == o->phys_proc_id &&
+ c->cpu_core_id == o->cpu_core_id) {
+ link_thread_siblings(cpu, i);
}
}
} else {
@@ -774,7 +779,6 @@ do_rest:
#ifdef CONFIG_X86_32
/* Stack for startup_32 can be just as for start_secondary onwards */
irq_ctx_init(cpu);
- initial_page_table = __pa(&trampoline_pg_dir);
#else
clear_tsk_thread_flag(c_idle.idle, TIF_FORK);
initial_gs = per_cpu_offset(cpu);
@@ -923,7 +927,6 @@ int __cpuinit native_cpu_up(unsigned int cpu)
per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
err = do_boot_cpu(apicid, cpu);
-
if (err) {
pr_debug("do_boot_cpu failed %d\n", err);
return -EIO;
@@ -1109,8 +1112,6 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
}
set_cpu_sibling_map(0);
- enable_IR_x2apic();
- default_setup_apic_routing();
if (smp_sanity_check(max_cpus) < 0) {
printk(KERN_INFO "SMP disabled\n");
@@ -1118,6 +1119,8 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
goto out;
}
+ default_setup_apic_routing();
+
preempt_disable();
if (read_apic_id() != boot_cpu_physical_apicid) {
panic("Boot APIC ID in local APIC unexpected (%d vs %d)",
@@ -1383,11 +1386,88 @@ void play_dead_common(void)
local_irq_disable();
}
+/*
+ * We need to flush the caches before going to sleep, lest we have
+ * dirty data in our caches when we come back up.
+ */
+static inline void mwait_play_dead(void)
+{
+ unsigned int eax, ebx, ecx, edx;
+ unsigned int highest_cstate = 0;
+ unsigned int highest_subcstate = 0;
+ int i;
+ void *mwait_ptr;
+
+ if (!cpu_has(&current_cpu_data, X86_FEATURE_MWAIT))
+ return;
+ if (!cpu_has(&current_cpu_data, X86_FEATURE_CLFLSH))
+ return;
+ if (current_cpu_data.cpuid_level < CPUID_MWAIT_LEAF)
+ return;
+
+ eax = CPUID_MWAIT_LEAF;
+ ecx = 0;
+ native_cpuid(&eax, &ebx, &ecx, &edx);
+
+ /*
+ * eax will be 0 if EDX enumeration is not valid.
+ * Initialized below to cstate, sub_cstate value when EDX is valid.
+ */
+ if (!(ecx & CPUID5_ECX_EXTENSIONS_SUPPORTED)) {
+ eax = 0;
+ } else {
+ edx >>= MWAIT_SUBSTATE_SIZE;
+ for (i = 0; i < 7 && edx; i++, edx >>= MWAIT_SUBSTATE_SIZE) {
+ if (edx & MWAIT_SUBSTATE_MASK) {
+ highest_cstate = i;
+ highest_subcstate = edx & MWAIT_SUBSTATE_MASK;
+ }
+ }
+ eax = (highest_cstate << MWAIT_SUBSTATE_SIZE) |
+ (highest_subcstate - 1);
+ }
+
+ /*
+ * This should be a memory location in a cache line which is
+ * unlikely to be touched by other processors. The actual
+ * content is immaterial as it is not actually modified in any way.
+ */
+ mwait_ptr = &current_thread_info()->flags;
+
+ wbinvd();
+
+ while (1) {
+ /*
+ * The CLFLUSH is a workaround for erratum AAI65 for
+ * the Xeon 7400 series. It's not clear it is actually
+ * needed, but it should be harmless in either case.
+ * The WBINVD is insufficient due to the spurious-wakeup
+ * case where we return around the loop.
+ */
+ clflush(mwait_ptr);
+ __monitor(mwait_ptr, 0, 0);
+ mb();
+ __mwait(eax, 0);
+ }
+}
+
+static inline void hlt_play_dead(void)
+{
+ if (current_cpu_data.x86 >= 4)
+ wbinvd();
+
+ while (1) {
+ native_halt();
+ }
+}
+
void native_play_dead(void)
{
play_dead_common();
tboot_shutdown(TB_SHUTDOWN_WFS);
- wbinvd_halt();
+
+ mwait_play_dead(); /* Only returns on failure */
+ hlt_play_dead();
}
#else /* ... !CONFIG_HOTPLUG_CPU */
diff --git a/arch/x86/kernel/sys_i386_32.c b/arch/x86/kernel/sys_i386_32.c
index d5e06624e34a..0b0cb5fede19 100644
--- a/arch/x86/kernel/sys_i386_32.c
+++ b/arch/x86/kernel/sys_i386_32.c
@@ -33,8 +33,8 @@ int kernel_execve(const char *filename,
const char *const envp[])
{
long __res;
- asm volatile ("push %%ebx ; movl %2,%%ebx ; int $0x80 ; pop %%ebx"
+ asm volatile ("int $0x80"
: "=a" (__res)
- : "0" (__NR_execve), "ri" (filename), "c" (argv), "d" (envp) : "memory");
+ : "0" (__NR_execve), "b" (filename), "c" (argv), "d" (envp) : "memory");
return __res;
}
diff --git a/arch/x86/kernel/tlb_uv.c b/arch/x86/kernel/tlb_uv.c
index 312ef0292815..20ea20a39e2a 100644
--- a/arch/x86/kernel/tlb_uv.c
+++ b/arch/x86/kernel/tlb_uv.c
@@ -1001,10 +1001,10 @@ static int uv_ptc_seq_show(struct seq_file *file, void *data)
static ssize_t tunables_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
- char buf[300];
+ char *buf;
int ret;
- ret = snprintf(buf, 300, "%s %s %s\n%d %d %d %d %d %d %d %d %d\n",
+ buf = kasprintf(GFP_KERNEL, "%s %s %s\n%d %d %d %d %d %d %d %d %d\n",
"max_bau_concurrent plugged_delay plugsb4reset",
"timeoutsb4reset ipi_reset_limit complete_threshold",
"congested_response_us congested_reps congested_period",
@@ -1012,7 +1012,12 @@ static ssize_t tunables_read(struct file *file, char __user *userbuf,
timeoutsb4reset, ipi_reset_limit, complete_threshold,
congested_response_us, congested_reps, congested_period);
- return simple_read_from_buffer(userbuf, count, ppos, buf, ret);
+ if (!buf)
+ return -ENOMEM;
+
+ ret = simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf));
+ kfree(buf);
+ return ret;
}
/*
@@ -1285,6 +1290,7 @@ static const struct file_operations tunables_fops = {
.open = tunables_open,
.read = tunables_read,
.write = tunables_write,
+ .llseek = default_llseek,
};
static int __init uv_ptc_init(void)
diff --git a/arch/x86/kernel/trampoline.c b/arch/x86/kernel/trampoline.c
index e2a595257390..a375616d77f7 100644
--- a/arch/x86/kernel/trampoline.c
+++ b/arch/x86/kernel/trampoline.c
@@ -1,8 +1,8 @@
#include <linux/io.h>
+#include <linux/memblock.h>
#include <asm/trampoline.h>
#include <asm/pgtable.h>
-#include <asm/e820.h>
#if defined(CONFIG_X86_64) && defined(CONFIG_ACPI_SLEEP)
#define __trampinit
@@ -17,15 +17,15 @@ unsigned char *__trampinitdata trampoline_base;
void __init reserve_trampoline_memory(void)
{
- unsigned long mem;
+ phys_addr_t mem;
/* Has to be in very low memory so we can execute real-mode AP code. */
- mem = find_e820_area(0, 1<<20, TRAMPOLINE_SIZE, PAGE_SIZE);
- if (mem == -1L)
+ mem = memblock_find_in_range(0, 1<<20, TRAMPOLINE_SIZE, PAGE_SIZE);
+ if (mem == MEMBLOCK_ERROR)
panic("Cannot allocate trampoline\n");
trampoline_base = __va(mem);
- reserve_early(mem, mem + TRAMPOLINE_SIZE, "TRAMPOLINE");
+ memblock_x86_reserve_range(mem, mem + TRAMPOLINE_SIZE, "TRAMPOLINE");
}
/*
@@ -38,19 +38,3 @@ unsigned long __trampinit setup_trampoline(void)
memcpy(trampoline_base, trampoline_data, TRAMPOLINE_SIZE);
return virt_to_phys(trampoline_base);
}
-
-void __init setup_trampoline_page_table(void)
-{
-#ifdef CONFIG_X86_32
- /* Copy kernel address range */
- clone_pgd_range(trampoline_pg_dir + KERNEL_PGD_BOUNDARY,
- swapper_pg_dir + KERNEL_PGD_BOUNDARY,
- KERNEL_PGD_PTRS);
-
- /* Initialize low mappings */
- clone_pgd_range(trampoline_pg_dir,
- swapper_pg_dir + KERNEL_PGD_BOUNDARY,
- min_t(unsigned long, KERNEL_PGD_PTRS,
- KERNEL_PGD_BOUNDARY));
-#endif
-}
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index 60788dee0f8a..cb838ca42c96 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -575,6 +575,7 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code)
if (regs->flags & X86_VM_MASK) {
handle_vm86_trap((struct kernel_vm86_regs *) regs,
error_code, 1);
+ preempt_conditional_cli(regs);
return;
}
@@ -776,21 +777,10 @@ asmlinkage void math_state_restore(void)
}
EXPORT_SYMBOL_GPL(math_state_restore);
-#ifndef CONFIG_MATH_EMULATION
-void math_emulate(struct math_emu_info *info)
-{
- printk(KERN_EMERG
- "math-emulation not enabled and no coprocessor found.\n");
- printk(KERN_EMERG "killing %s.\n", current->comm);
- force_sig(SIGFPE, current);
- schedule();
-}
-#endif /* CONFIG_MATH_EMULATION */
-
dotraplinkage void __kprobes
do_device_not_available(struct pt_regs *regs, long error_code)
{
-#ifdef CONFIG_X86_32
+#ifdef CONFIG_MATH_EMULATION
if (read_cr0() & X86_CR0_EM) {
struct math_emu_info info = { };
@@ -798,12 +788,12 @@ do_device_not_available(struct pt_regs *regs, long error_code)
info.regs = regs;
math_emulate(&info);
- } else {
- math_state_restore(); /* interrupts still off */
- conditional_sti(regs);
+ return;
}
-#else
- math_state_restore();
+#endif
+ math_state_restore(); /* interrupts still off */
+#ifdef CONFIG_X86_32
+ conditional_sti(regs);
#endif
}
@@ -881,18 +871,6 @@ void __init trap_init(void)
#endif
#ifdef CONFIG_X86_32
- if (cpu_has_fxsr) {
- printk(KERN_INFO "Enabling fast FPU save and restore... ");
- set_in_cr4(X86_CR4_OSFXSR);
- printk("done.\n");
- }
- if (cpu_has_xmm) {
- printk(KERN_INFO
- "Enabling unmasked SIMD FPU exception support... ");
- set_in_cr4(X86_CR4_OSXMMEXCPT);
- printk("done.\n");
- }
-
set_system_trap_gate(SYSCALL_VECTOR, &system_call);
set_bit(SYSCALL_VECTOR, used_vectors);
#endif
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index 26a863a9c2a8..0c40d8b72416 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -104,10 +104,14 @@ int __init notsc_setup(char *str)
__setup("notsc", notsc_setup);
+static int no_sched_irq_time;
+
static int __init tsc_setup(char *str)
{
if (!strcmp(str, "reliable"))
tsc_clocksource_reliable = 1;
+ if (!strncmp(str, "noirqtime", 9))
+ no_sched_irq_time = 1;
return 1;
}
@@ -801,6 +805,7 @@ void mark_tsc_unstable(char *reason)
if (!tsc_unstable) {
tsc_unstable = 1;
sched_clock_stable = 0;
+ disable_sched_clock_irqtime();
printk(KERN_INFO "Marking TSC unstable due to %s\n", reason);
/* Change only the rating, when not registered */
if (clocksource_tsc.mult)
@@ -892,60 +897,6 @@ static void __init init_tsc_clocksource(void)
clocksource_register_khz(&clocksource_tsc, tsc_khz);
}
-#ifdef CONFIG_X86_64
-/*
- * calibrate_cpu is used on systems with fixed rate TSCs to determine
- * processor frequency
- */
-#define TICK_COUNT 100000000
-static unsigned long __init calibrate_cpu(void)
-{
- int tsc_start, tsc_now;
- int i, no_ctr_free;
- unsigned long evntsel3 = 0, pmc3 = 0, pmc_now = 0;
- unsigned long flags;
-
- for (i = 0; i < 4; i++)
- if (avail_to_resrv_perfctr_nmi_bit(i))
- break;
- no_ctr_free = (i == 4);
- if (no_ctr_free) {
- WARN(1, KERN_WARNING "Warning: AMD perfctrs busy ... "
- "cpu_khz value may be incorrect.\n");
- i = 3;
- rdmsrl(MSR_K7_EVNTSEL3, evntsel3);
- wrmsrl(MSR_K7_EVNTSEL3, 0);
- rdmsrl(MSR_K7_PERFCTR3, pmc3);
- } else {
- reserve_perfctr_nmi(MSR_K7_PERFCTR0 + i);
- reserve_evntsel_nmi(MSR_K7_EVNTSEL0 + i);
- }
- local_irq_save(flags);
- /* start measuring cycles, incrementing from 0 */
- wrmsrl(MSR_K7_PERFCTR0 + i, 0);
- wrmsrl(MSR_K7_EVNTSEL0 + i, 1 << 22 | 3 << 16 | 0x76);
- rdtscl(tsc_start);
- do {
- rdmsrl(MSR_K7_PERFCTR0 + i, pmc_now);
- tsc_now = get_cycles();
- } while ((tsc_now - tsc_start) < TICK_COUNT);
-
- local_irq_restore(flags);
- if (no_ctr_free) {
- wrmsrl(MSR_K7_EVNTSEL3, 0);
- wrmsrl(MSR_K7_PERFCTR3, pmc3);
- wrmsrl(MSR_K7_EVNTSEL3, evntsel3);
- } else {
- release_perfctr_nmi(MSR_K7_PERFCTR0 + i);
- release_evntsel_nmi(MSR_K7_EVNTSEL0 + i);
- }
-
- return pmc_now * tsc_khz / (tsc_now - tsc_start);
-}
-#else
-static inline unsigned long calibrate_cpu(void) { return cpu_khz; }
-#endif
-
void __init tsc_init(void)
{
u64 lpj;
@@ -964,10 +915,6 @@ void __init tsc_init(void)
return;
}
- if (cpu_has(&boot_cpu_data, X86_FEATURE_CONSTANT_TSC) &&
- (boot_cpu_data.x86_vendor == X86_VENDOR_AMD))
- cpu_khz = calibrate_cpu();
-
printk("Detected %lu.%03lu MHz processor.\n",
(unsigned long)cpu_khz / 1000,
(unsigned long)cpu_khz % 1000);
@@ -987,6 +934,9 @@ void __init tsc_init(void)
/* now allow native_sched_clock() to use rdtsc */
tsc_disabled = 0;
+ if (!no_sched_irq_time)
+ enable_sched_clock_irqtime();
+
lpj = ((u64)tsc_khz * 1000);
do_div(lpj, HZ);
lpj_fine = lpj;
diff --git a/arch/x86/kernel/uv_irq.c b/arch/x86/kernel/uv_irq.c
index 1132129db792..7b24460917d5 100644
--- a/arch/x86/kernel/uv_irq.c
+++ b/arch/x86/kernel/uv_irq.c
@@ -28,34 +28,21 @@ struct uv_irq_2_mmr_pnode{
static spinlock_t uv_irq_lock;
static struct rb_root uv_irq_root;
-static int uv_set_irq_affinity(unsigned int, const struct cpumask *);
+static int uv_set_irq_affinity(struct irq_data *, const struct cpumask *, bool);
-static void uv_noop(unsigned int irq)
-{
-}
-
-static unsigned int uv_noop_ret(unsigned int irq)
-{
- return 0;
-}
+static void uv_noop(struct irq_data *data) { }
-static void uv_ack_apic(unsigned int irq)
+static void uv_ack_apic(struct irq_data *data)
{
ack_APIC_irq();
}
static struct irq_chip uv_irq_chip = {
- .name = "UV-CORE",
- .startup = uv_noop_ret,
- .shutdown = uv_noop,
- .enable = uv_noop,
- .disable = uv_noop,
- .ack = uv_noop,
- .mask = uv_noop,
- .unmask = uv_noop,
- .eoi = uv_ack_apic,
- .end = uv_noop,
- .set_affinity = uv_set_irq_affinity,
+ .name = "UV-CORE",
+ .irq_mask = uv_noop,
+ .irq_unmask = uv_noop,
+ .irq_eoi = uv_ack_apic,
+ .irq_set_affinity = uv_set_irq_affinity,
};
/*
@@ -144,26 +131,22 @@ arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade,
unsigned long mmr_offset, int limit)
{
const struct cpumask *eligible_cpu = cpumask_of(cpu);
- struct irq_desc *desc = irq_to_desc(irq);
- struct irq_cfg *cfg;
- int mmr_pnode;
+ struct irq_cfg *cfg = get_irq_chip_data(irq);
unsigned long mmr_value;
struct uv_IO_APIC_route_entry *entry;
- int err;
+ int mmr_pnode, err;
BUILD_BUG_ON(sizeof(struct uv_IO_APIC_route_entry) !=
sizeof(unsigned long));
- cfg = irq_cfg(irq);
-
err = assign_irq_vector(irq, cfg, eligible_cpu);
if (err != 0)
return err;
if (limit == UV_AFFINITY_CPU)
- desc->status |= IRQ_NO_BALANCING;
+ irq_set_status_flags(irq, IRQ_NO_BALANCING);
else
- desc->status |= IRQ_MOVE_PCNTXT;
+ irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
set_irq_chip_and_handler_name(irq, &uv_irq_chip, handle_percpu_irq,
irq_name);
@@ -206,17 +189,17 @@ static void arch_disable_uv_irq(int mmr_pnode, unsigned long mmr_offset)
uv_write_global_mmr64(mmr_pnode, mmr_offset, mmr_value);
}
-static int uv_set_irq_affinity(unsigned int irq, const struct cpumask *mask)
+static int
+uv_set_irq_affinity(struct irq_data *data, const struct cpumask *mask,
+ bool force)
{
- struct irq_desc *desc = irq_to_desc(irq);
- struct irq_cfg *cfg = desc->chip_data;
+ struct irq_cfg *cfg = data->chip_data;
unsigned int dest;
- unsigned long mmr_value;
+ unsigned long mmr_value, mmr_offset;
struct uv_IO_APIC_route_entry *entry;
- unsigned long mmr_offset;
int mmr_pnode;
- if (set_desc_affinity(desc, mask, &dest))
+ if (__ioapic_set_affinity(data, mask, &dest))
return -1;
mmr_value = 0;
@@ -231,7 +214,7 @@ static int uv_set_irq_affinity(unsigned int irq, const struct cpumask *mask)
entry->dest = dest;
/* Get previously stored MMR and pnode of hub sourcing interrupts */
- if (uv_irq_2_mmr_info(irq, &mmr_offset, &mmr_pnode))
+ if (uv_irq_2_mmr_info(data->irq, &mmr_offset, &mmr_pnode))
return -1;
uv_write_global_mmr64(mmr_pnode, mmr_offset, mmr_value);
diff --git a/arch/x86/kernel/visws_quirks.c b/arch/x86/kernel/visws_quirks.c
index e680ea52db9b..3371bd053b89 100644
--- a/arch/x86/kernel/visws_quirks.c
+++ b/arch/x86/kernel/visws_quirks.c
@@ -66,10 +66,7 @@ static void __init visws_time_init(void)
}
/* Replaces the default init_ISA_irqs in the generic setup */
-static void __init visws_pre_intr_init(void)
-{
- init_VISWS_APIC_irqs();
-}
+static void __init visws_pre_intr_init(void);
/* Quirk for machine specific memory setup. */
@@ -429,67 +426,34 @@ static int is_co_apic(unsigned int irq)
/*
* This is the SGI Cobalt (IO-)APIC:
*/
-
-static void enable_cobalt_irq(unsigned int irq)
+static void enable_cobalt_irq(struct irq_data *data)
{
- co_apic_set(is_co_apic(irq), irq);
+ co_apic_set(is_co_apic(data->irq), data->irq);
}
-static void disable_cobalt_irq(unsigned int irq)
+static void disable_cobalt_irq(struct irq_data *data)
{
- int entry = is_co_apic(irq);
+ int entry = is_co_apic(data->irq);
co_apic_write(CO_APIC_LO(entry), CO_APIC_MASK);
co_apic_read(CO_APIC_LO(entry));
}
-/*
- * "irq" really just serves to identify the device. Here is where we
- * map this to the Cobalt APIC entry where it's physically wired.
- * This is called via request_irq -> setup_irq -> irq_desc->startup()
- */
-static unsigned int startup_cobalt_irq(unsigned int irq)
+static void ack_cobalt_irq(struct irq_data *data)
{
unsigned long flags;
- struct irq_desc *desc = irq_to_desc(irq);
spin_lock_irqsave(&cobalt_lock, flags);
- if ((desc->status & (IRQ_DISABLED | IRQ_INPROGRESS | IRQ_WAITING)))
- desc->status &= ~(IRQ_DISABLED | IRQ_INPROGRESS | IRQ_WAITING);
- enable_cobalt_irq(irq);
- spin_unlock_irqrestore(&cobalt_lock, flags);
- return 0;
-}
-
-static void ack_cobalt_irq(unsigned int irq)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&cobalt_lock, flags);
- disable_cobalt_irq(irq);
+ disable_cobalt_irq(data);
apic_write(APIC_EOI, APIC_EIO_ACK);
spin_unlock_irqrestore(&cobalt_lock, flags);
}
-static void end_cobalt_irq(unsigned int irq)
-{
- unsigned long flags;
- struct irq_desc *desc = irq_to_desc(irq);
-
- spin_lock_irqsave(&cobalt_lock, flags);
- if (!(desc->status & (IRQ_DISABLED | IRQ_INPROGRESS)))
- enable_cobalt_irq(irq);
- spin_unlock_irqrestore(&cobalt_lock, flags);
-}
-
static struct irq_chip cobalt_irq_type = {
- .name = "Cobalt-APIC",
- .startup = startup_cobalt_irq,
- .shutdown = disable_cobalt_irq,
- .enable = enable_cobalt_irq,
- .disable = disable_cobalt_irq,
- .ack = ack_cobalt_irq,
- .end = end_cobalt_irq,
+ .name = "Cobalt-APIC",
+ .irq_enable = enable_cobalt_irq,
+ .irq_disable = disable_cobalt_irq,
+ .irq_ack = ack_cobalt_irq,
};
@@ -503,35 +467,34 @@ static struct irq_chip cobalt_irq_type = {
* interrupt controller type, and through a special virtual interrupt-
* controller. Device drivers only see the virtual interrupt sources.
*/
-static unsigned int startup_piix4_master_irq(unsigned int irq)
+static unsigned int startup_piix4_master_irq(struct irq_data *data)
{
legacy_pic->init(0);
-
- return startup_cobalt_irq(irq);
+ enable_cobalt_irq(data);
}
-static void end_piix4_master_irq(unsigned int irq)
+static void end_piix4_master_irq(struct irq_data *data)
{
unsigned long flags;
spin_lock_irqsave(&cobalt_lock, flags);
- enable_cobalt_irq(irq);
+ enable_cobalt_irq(data);
spin_unlock_irqrestore(&cobalt_lock, flags);
}
static struct irq_chip piix4_master_irq_type = {
- .name = "PIIX4-master",
- .startup = startup_piix4_master_irq,
- .ack = ack_cobalt_irq,
- .end = end_piix4_master_irq,
+ .name = "PIIX4-master",
+ .irq_startup = startup_piix4_master_irq,
+ .irq_ack = ack_cobalt_irq,
};
+static void pii4_mask(struct irq_data *data) { }
static struct irq_chip piix4_virtual_irq_type = {
- .name = "PIIX4-virtual",
+ .name = "PIIX4-virtual",
+ .mask = pii4_mask,
};
-
/*
* PIIX4-8259 master/virtual functions to handle interrupt requests
* from legacy devices: floppy, parallel, serial, rtc.
@@ -549,9 +512,8 @@ static struct irq_chip piix4_virtual_irq_type = {
*/
static irqreturn_t piix4_master_intr(int irq, void *dev_id)
{
- int realirq;
- struct irq_desc *desc;
unsigned long flags;
+ int realirq;
raw_spin_lock_irqsave(&i8259A_lock, flags);
@@ -592,18 +554,10 @@ static irqreturn_t piix4_master_intr(int irq, void *dev_id)
raw_spin_unlock_irqrestore(&i8259A_lock, flags);
- desc = irq_to_desc(realirq);
-
/*
* handle this 'virtual interrupt' as a Cobalt one now.
*/
- kstat_incr_irqs_this_cpu(realirq, desc);
-
- if (likely(desc->action != NULL))
- handle_IRQ_event(realirq, desc->action);
-
- if (!(desc->status & IRQ_DISABLED))
- legacy_pic->chip->unmask(realirq);
+ generic_handle_irq(realirq);
return IRQ_HANDLED;
@@ -624,41 +578,35 @@ static struct irqaction cascade_action = {
static inline void set_piix4_virtual_irq_type(void)
{
- piix4_virtual_irq_type.shutdown = i8259A_chip.mask;
piix4_virtual_irq_type.enable = i8259A_chip.unmask;
piix4_virtual_irq_type.disable = i8259A_chip.mask;
+ piix4_virtual_irq_type.unmask = i8259A_chip.unmask;
}
-void init_VISWS_APIC_irqs(void)
+static void __init visws_pre_intr_init(void)
{
int i;
- for (i = 0; i < CO_IRQ_APIC0 + CO_APIC_LAST + 1; i++) {
- struct irq_desc *desc = irq_to_desc(i);
-
- desc->status = IRQ_DISABLED;
- desc->action = 0;
- desc->depth = 1;
+ set_piix4_virtual_irq_type();
- if (i == 0) {
- desc->chip = &cobalt_irq_type;
- }
- else if (i == CO_IRQ_IDE0) {
- desc->chip = &cobalt_irq_type;
- }
- else if (i == CO_IRQ_IDE1) {
- desc->chip = &cobalt_irq_type;
- }
- else if (i == CO_IRQ_8259) {
- desc->chip = &piix4_master_irq_type;
- }
- else if (i < CO_IRQ_APIC0) {
- set_piix4_virtual_irq_type();
- desc->chip = &piix4_virtual_irq_type;
- }
- else if (IS_CO_APIC(i)) {
- desc->chip = &cobalt_irq_type;
- }
+ for (i = 0; i < CO_IRQ_APIC0 + CO_APIC_LAST + 1; i++) {
+ struct irq_chip *chip = NULL;
+
+ if (i == 0)
+ chip = &cobalt_irq_type;
+ else if (i == CO_IRQ_IDE0)
+ chip = &cobalt_irq_type;
+ else if (i == CO_IRQ_IDE1)
+ >chip = &cobalt_irq_type;
+ else if (i == CO_IRQ_8259)
+ chip = &piix4_master_irq_type;
+ else if (i < CO_IRQ_APIC0)
+ chip = &piix4_virtual_irq_type;
+ else if (IS_CO_APIC(i))
+ chip = &cobalt_irq_type;
+
+ if (chip)
+ set_irq_chip(i, chip);
}
setup_irq(CO_IRQ_8259, &master_action);
diff --git a/arch/x86/kernel/vm86_32.c b/arch/x86/kernel/vm86_32.c
index 5ffb5622f793..61fb98519622 100644
--- a/arch/x86/kernel/vm86_32.c
+++ b/arch/x86/kernel/vm86_32.c
@@ -551,8 +551,14 @@ cannot_handle:
int handle_vm86_trap(struct kernel_vm86_regs *regs, long error_code, int trapno)
{
if (VMPI.is_vm86pus) {
- if ((trapno == 3) || (trapno == 1))
- return_to_32bit(regs, VM86_TRAP + (trapno << 8));
+ if ((trapno == 3) || (trapno == 1)) {
+ KVM86->regs32->ax = VM86_TRAP + (trapno << 8);
+ /* setting this flag forces the code in entry_32.S to
+ call save_v86_state() and change the stack pointer
+ to KVM86->regs32 */
+ set_thread_flag(TIF_IRET);
+ return 0;
+ }
do_int(regs, trapno, (unsigned char __user *) (regs->pt.ss << 4), SP(regs));
return 0;
}
diff --git a/arch/x86/kernel/vmi_32.c b/arch/x86/kernel/vmi_32.c
deleted file mode 100644
index ce9fbacb7526..000000000000
--- a/arch/x86/kernel/vmi_32.c
+++ /dev/null
@@ -1,893 +0,0 @@
-/*
- * VMI specific paravirt-ops implementation
- *
- * Copyright (C) 2005, VMware, 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.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to zach@vmware.com
- *
- */
-
-#include <linux/module.h>
-#include <linux/cpu.h>
-#include <linux/bootmem.h>
-#include <linux/mm.h>
-#include <linux/highmem.h>
-#include <linux/sched.h>
-#include <linux/gfp.h>
-#include <asm/vmi.h>
-#include <asm/io.h>
-#include <asm/fixmap.h>
-#include <asm/apicdef.h>
-#include <asm/apic.h>
-#include <asm/pgalloc.h>
-#include <asm/processor.h>
-#include <asm/timer.h>
-#include <asm/vmi_time.h>
-#include <asm/kmap_types.h>
-#include <asm/setup.h>
-
-/* Convenient for calling VMI functions indirectly in the ROM */
-typedef u32 __attribute__((regparm(1))) (VROMFUNC)(void);
-typedef u64 __attribute__((regparm(2))) (VROMLONGFUNC)(int);
-
-#define call_vrom_func(rom,func) \
- (((VROMFUNC *)(rom->func))())
-
-#define call_vrom_long_func(rom,func,arg) \
- (((VROMLONGFUNC *)(rom->func)) (arg))
-
-static struct vrom_header *vmi_rom;
-static int disable_pge;
-static int disable_pse;
-static int disable_sep;
-static int disable_tsc;
-static int disable_mtrr;
-static int disable_noidle;
-static int disable_vmi_timer;
-
-/* Cached VMI operations */
-static struct {
- void (*cpuid)(void /* non-c */);
- void (*_set_ldt)(u32 selector);
- void (*set_tr)(u32 selector);
- void (*write_idt_entry)(struct desc_struct *, int, u32, u32);
- void (*write_gdt_entry)(struct desc_struct *, int, u32, u32);
- void (*write_ldt_entry)(struct desc_struct *, int, u32, u32);
- void (*set_kernel_stack)(u32 selector, u32 sp0);
- void (*allocate_page)(u32, u32, u32, u32, u32);
- void (*release_page)(u32, u32);
- void (*set_pte)(pte_t, pte_t *, unsigned);
- void (*update_pte)(pte_t *, unsigned);
- void (*set_linear_mapping)(int, void *, u32, u32);
- void (*_flush_tlb)(int);
- void (*set_initial_ap_state)(int, int);
- void (*halt)(void);
- void (*set_lazy_mode)(int mode);
-} vmi_ops;
-
-/* Cached VMI operations */
-struct vmi_timer_ops vmi_timer_ops;
-
-/*
- * VMI patching routines.
- */
-#define MNEM_CALL 0xe8
-#define MNEM_JMP 0xe9
-#define MNEM_RET 0xc3
-
-#define IRQ_PATCH_INT_MASK 0
-#define IRQ_PATCH_DISABLE 5
-
-static inline void patch_offset(void *insnbuf,
- unsigned long ip, unsigned long dest)
-{
- *(unsigned long *)(insnbuf+1) = dest-ip-5;
-}
-
-static unsigned patch_internal(int call, unsigned len, void *insnbuf,
- unsigned long ip)
-{
- u64 reloc;
- struct vmi_relocation_info *const rel = (struct vmi_relocation_info *)&reloc;
- reloc = call_vrom_long_func(vmi_rom, get_reloc, call);
- switch(rel->type) {
- case VMI_RELOCATION_CALL_REL:
- BUG_ON(len < 5);
- *(char *)insnbuf = MNEM_CALL;
- patch_offset(insnbuf, ip, (unsigned long)rel->eip);
- return 5;
-
- case VMI_RELOCATION_JUMP_REL:
- BUG_ON(len < 5);
- *(char *)insnbuf = MNEM_JMP;
- patch_offset(insnbuf, ip, (unsigned long)rel->eip);
- return 5;
-
- case VMI_RELOCATION_NOP:
- /* obliterate the whole thing */
- return 0;
-
- case VMI_RELOCATION_NONE:
- /* leave native code in place */
- break;
-
- default:
- BUG();
- }
- return len;
-}
-
-/*
- * Apply patch if appropriate, return length of new instruction
- * sequence. The callee does nop padding for us.
- */
-static unsigned vmi_patch(u8 type, u16 clobbers, void *insns,
- unsigned long ip, unsigned len)
-{
- switch (type) {
- case PARAVIRT_PATCH(pv_irq_ops.irq_disable):
- return patch_internal(VMI_CALL_DisableInterrupts, len,
- insns, ip);
- case PARAVIRT_PATCH(pv_irq_ops.irq_enable):
- return patch_internal(VMI_CALL_EnableInterrupts, len,
- insns, ip);
- case PARAVIRT_PATCH(pv_irq_ops.restore_fl):
- return patch_internal(VMI_CALL_SetInterruptMask, len,
- insns, ip);
- case PARAVIRT_PATCH(pv_irq_ops.save_fl):
- return patch_internal(VMI_CALL_GetInterruptMask, len,
- insns, ip);
- case PARAVIRT_PATCH(pv_cpu_ops.iret):
- return patch_internal(VMI_CALL_IRET, len, insns, ip);
- case PARAVIRT_PATCH(pv_cpu_ops.irq_enable_sysexit):
- return patch_internal(VMI_CALL_SYSEXIT, len, insns, ip);
- default:
- break;
- }
- return len;
-}
-
-/* CPUID has non-C semantics, and paravirt-ops API doesn't match hardware ISA */
-static void vmi_cpuid(unsigned int *ax, unsigned int *bx,
- unsigned int *cx, unsigned int *dx)
-{
- int override = 0;
- if (*ax == 1)
- override = 1;
- asm volatile ("call *%6"
- : "=a" (*ax),
- "=b" (*bx),
- "=c" (*cx),
- "=d" (*dx)
- : "0" (*ax), "2" (*cx), "r" (vmi_ops.cpuid));
- if (override) {
- if (disable_pse)
- *dx &= ~X86_FEATURE_PSE;
- if (disable_pge)
- *dx &= ~X86_FEATURE_PGE;
- if (disable_sep)
- *dx &= ~X86_FEATURE_SEP;
- if (disable_tsc)
- *dx &= ~X86_FEATURE_TSC;
- if (disable_mtrr)
- *dx &= ~X86_FEATURE_MTRR;
- }
-}
-
-static inline void vmi_maybe_load_tls(struct desc_struct *gdt, int nr, struct desc_struct *new)
-{
- if (gdt[nr].a != new->a || gdt[nr].b != new->b)
- write_gdt_entry(gdt, nr, new, 0);
-}
-
-static void vmi_load_tls(struct thread_struct *t, unsigned int cpu)
-{
- struct desc_struct *gdt = get_cpu_gdt_table(cpu);
- vmi_maybe_load_tls(gdt, GDT_ENTRY_TLS_MIN + 0, &t->tls_array[0]);
- vmi_maybe_load_tls(gdt, GDT_ENTRY_TLS_MIN + 1, &t->tls_array[1]);
- vmi_maybe_load_tls(gdt, GDT_ENTRY_TLS_MIN + 2, &t->tls_array[2]);
-}
-
-static void vmi_set_ldt(const void *addr, unsigned entries)
-{
- unsigned cpu = smp_processor_id();
- struct desc_struct desc;
-
- pack_descriptor(&desc, (unsigned long)addr,
- entries * sizeof(struct desc_struct) - 1,
- DESC_LDT, 0);
- write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_LDT, &desc, DESC_LDT);
- vmi_ops._set_ldt(entries ? GDT_ENTRY_LDT*sizeof(struct desc_struct) : 0);
-}
-
-static void vmi_set_tr(void)
-{
- vmi_ops.set_tr(GDT_ENTRY_TSS*sizeof(struct desc_struct));
-}
-
-static void vmi_write_idt_entry(gate_desc *dt, int entry, const gate_desc *g)
-{
- u32 *idt_entry = (u32 *)g;
- vmi_ops.write_idt_entry(dt, entry, idt_entry[0], idt_entry[1]);
-}
-
-static void vmi_write_gdt_entry(struct desc_struct *dt, int entry,
- const void *desc, int type)
-{
- u32 *gdt_entry = (u32 *)desc;
- vmi_ops.write_gdt_entry(dt, entry, gdt_entry[0], gdt_entry[1]);
-}
-
-static void vmi_write_ldt_entry(struct desc_struct *dt, int entry,
- const void *desc)
-{
- u32 *ldt_entry = (u32 *)desc;
- vmi_ops.write_ldt_entry(dt, entry, ldt_entry[0], ldt_entry[1]);
-}
-
-static void vmi_load_sp0(struct tss_struct *tss,
- struct thread_struct *thread)
-{
- tss->x86_tss.sp0 = thread->sp0;
-
- /* This can only happen when SEP is enabled, no need to test "SEP"arately */
- if (unlikely(tss->x86_tss.ss1 != thread->sysenter_cs)) {
- tss->x86_tss.ss1 = thread->sysenter_cs;
- wrmsr(MSR_IA32_SYSENTER_CS, thread->sysenter_cs, 0);
- }
- vmi_ops.set_kernel_stack(__KERNEL_DS, tss->x86_tss.sp0);
-}
-
-static void vmi_flush_tlb_user(void)
-{
- vmi_ops._flush_tlb(VMI_FLUSH_TLB);
-}
-
-static void vmi_flush_tlb_kernel(void)
-{
- vmi_ops._flush_tlb(VMI_FLUSH_TLB | VMI_FLUSH_GLOBAL);
-}
-
-/* Stub to do nothing at all; used for delays and unimplemented calls */
-static void vmi_nop(void)
-{
-}
-
-static void vmi_allocate_pte(struct mm_struct *mm, unsigned long pfn)
-{
- vmi_ops.allocate_page(pfn, VMI_PAGE_L1, 0, 0, 0);
-}
-
-static void vmi_allocate_pmd(struct mm_struct *mm, unsigned long pfn)
-{
- /*
- * This call comes in very early, before mem_map is setup.
- * It is called only for swapper_pg_dir, which already has
- * data on it.
- */
- vmi_ops.allocate_page(pfn, VMI_PAGE_L2, 0, 0, 0);
-}
-
-static void vmi_allocate_pmd_clone(unsigned long pfn, unsigned long clonepfn, unsigned long start, unsigned long count)
-{
- vmi_ops.allocate_page(pfn, VMI_PAGE_L2 | VMI_PAGE_CLONE, clonepfn, start, count);
-}
-
-static void vmi_release_pte(unsigned long pfn)
-{
- vmi_ops.release_page(pfn, VMI_PAGE_L1);
-}
-
-static void vmi_release_pmd(unsigned long pfn)
-{
- vmi_ops.release_page(pfn, VMI_PAGE_L2);
-}
-
-/*
- * We use the pgd_free hook for releasing the pgd page:
- */
-static void vmi_pgd_free(struct mm_struct *mm, pgd_t *pgd)
-{
- unsigned long pfn = __pa(pgd) >> PAGE_SHIFT;
-
- vmi_ops.release_page(pfn, VMI_PAGE_L2);
-}
-
-/*
- * Helper macros for MMU update flags. We can defer updates until a flush
- * or page invalidation only if the update is to the current address space
- * (otherwise, there is no flush). We must check against init_mm, since
- * this could be a kernel update, which usually passes init_mm, although
- * sometimes this check can be skipped if we know the particular function
- * is only called on user mode PTEs. We could change the kernel to pass
- * current->active_mm here, but in particular, I was unsure if changing
- * mm/highmem.c to do this would still be correct on other architectures.
- */
-#define is_current_as(mm, mustbeuser) ((mm) == current->active_mm || \
- (!mustbeuser && (mm) == &init_mm))
-#define vmi_flags_addr(mm, addr, level, user) \
- ((level) | (is_current_as(mm, user) ? \
- (VMI_PAGE_CURRENT_AS | ((addr) & VMI_PAGE_VA_MASK)) : 0))
-#define vmi_flags_addr_defer(mm, addr, level, user) \
- ((level) | (is_current_as(mm, user) ? \
- (VMI_PAGE_DEFER | VMI_PAGE_CURRENT_AS | ((addr) & VMI_PAGE_VA_MASK)) : 0))
-
-static void vmi_update_pte(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
-{
- vmi_ops.update_pte(ptep, vmi_flags_addr(mm, addr, VMI_PAGE_PT, 0));
-}
-
-static void vmi_update_pte_defer(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
-{
- vmi_ops.update_pte(ptep, vmi_flags_addr_defer(mm, addr, VMI_PAGE_PT, 0));
-}
-
-static void vmi_set_pte(pte_t *ptep, pte_t pte)
-{
- /* XXX because of set_pmd_pte, this can be called on PT or PD layers */
- vmi_ops.set_pte(pte, ptep, VMI_PAGE_PT);
-}
-
-static void vmi_set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte)
-{
- vmi_ops.set_pte(pte, ptep, vmi_flags_addr(mm, addr, VMI_PAGE_PT, 0));
-}
-
-static void vmi_set_pmd(pmd_t *pmdp, pmd_t pmdval)
-{
-#ifdef CONFIG_X86_PAE
- const pte_t pte = { .pte = pmdval.pmd };
-#else
- const pte_t pte = { pmdval.pud.pgd.pgd };
-#endif
- vmi_ops.set_pte(pte, (pte_t *)pmdp, VMI_PAGE_PD);
-}
-
-#ifdef CONFIG_X86_PAE
-
-static void vmi_set_pte_atomic(pte_t *ptep, pte_t pteval)
-{
- /*
- * XXX This is called from set_pmd_pte, but at both PT
- * and PD layers so the VMI_PAGE_PT flag is wrong. But
- * it is only called for large page mapping changes,
- * the Xen backend, doesn't support large pages, and the
- * ESX backend doesn't depend on the flag.
- */
- set_64bit((unsigned long long *)ptep,pte_val(pteval));
- vmi_ops.update_pte(ptep, VMI_PAGE_PT);
-}
-
-static void vmi_set_pud(pud_t *pudp, pud_t pudval)
-{
- /* Um, eww */
- const pte_t pte = { .pte = pudval.pgd.pgd };
- vmi_ops.set_pte(pte, (pte_t *)pudp, VMI_PAGE_PDP);
-}
-
-static void vmi_pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
-{
- const pte_t pte = { .pte = 0 };
- vmi_ops.set_pte(pte, ptep, vmi_flags_addr(mm, addr, VMI_PAGE_PT, 0));
-}
-
-static void vmi_pmd_clear(pmd_t *pmd)
-{
- const pte_t pte = { .pte = 0 };
- vmi_ops.set_pte(pte, (pte_t *)pmd, VMI_PAGE_PD);
-}
-#endif
-
-#ifdef CONFIG_SMP
-static void __devinit
-vmi_startup_ipi_hook(int phys_apicid, unsigned long start_eip,
- unsigned long start_esp)
-{
- struct vmi_ap_state ap;
-
- /* Default everything to zero. This is fine for most GPRs. */
- memset(&ap, 0, sizeof(struct vmi_ap_state));
-
- ap.gdtr_limit = GDT_SIZE - 1;
- ap.gdtr_base = (unsigned long) get_cpu_gdt_table(phys_apicid);
-
- ap.idtr_limit = IDT_ENTRIES * 8 - 1;
- ap.idtr_base = (unsigned long) idt_table;
-
- ap.ldtr = 0;
-
- ap.cs = __KERNEL_CS;
- ap.eip = (unsigned long) start_eip;
- ap.ss = __KERNEL_DS;
- ap.esp = (unsigned long) start_esp;
-
- ap.ds = __USER_DS;
- ap.es = __USER_DS;
- ap.fs = __KERNEL_PERCPU;
- ap.gs = __KERNEL_STACK_CANARY;
-
- ap.eflags = 0;
-
-#ifdef CONFIG_X86_PAE
- /* efer should match BSP efer. */
- if (cpu_has_nx) {
- unsigned l, h;
- rdmsr(MSR_EFER, l, h);
- ap.efer = (unsigned long long) h << 32 | l;
- }
-#endif
-
- ap.cr3 = __pa(swapper_pg_dir);
- /* Protected mode, paging, AM, WP, NE, MP. */
- ap.cr0 = 0x80050023;
- ap.cr4 = mmu_cr4_features;
- vmi_ops.set_initial_ap_state((u32)&ap, phys_apicid);
-}
-#endif
-
-static void vmi_start_context_switch(struct task_struct *prev)
-{
- paravirt_start_context_switch(prev);
- vmi_ops.set_lazy_mode(2);
-}
-
-static void vmi_end_context_switch(struct task_struct *next)
-{
- vmi_ops.set_lazy_mode(0);
- paravirt_end_context_switch(next);
-}
-
-static void vmi_enter_lazy_mmu(void)
-{
- paravirt_enter_lazy_mmu();
- vmi_ops.set_lazy_mode(1);
-}
-
-static void vmi_leave_lazy_mmu(void)
-{
- vmi_ops.set_lazy_mode(0);
- paravirt_leave_lazy_mmu();
-}
-
-static inline int __init check_vmi_rom(struct vrom_header *rom)
-{
- struct pci_header *pci;
- struct pnp_header *pnp;
- const char *manufacturer = "UNKNOWN";
- const char *product = "UNKNOWN";
- const char *license = "unspecified";
-
- if (rom->rom_signature != 0xaa55)
- return 0;
- if (rom->vrom_signature != VMI_SIGNATURE)
- return 0;
- if (rom->api_version_maj != VMI_API_REV_MAJOR ||
- rom->api_version_min+1 < VMI_API_REV_MINOR+1) {
- printk(KERN_WARNING "VMI: Found mismatched rom version %d.%d\n",
- rom->api_version_maj,
- rom->api_version_min);
- return 0;
- }
-
- /*
- * Relying on the VMI_SIGNATURE field is not 100% safe, so check
- * the PCI header and device type to make sure this is really a
- * VMI device.
- */
- if (!rom->pci_header_offs) {
- printk(KERN_WARNING "VMI: ROM does not contain PCI header.\n");
- return 0;
- }
-
- pci = (struct pci_header *)((char *)rom+rom->pci_header_offs);
- if (pci->vendorID != PCI_VENDOR_ID_VMWARE ||
- pci->deviceID != PCI_DEVICE_ID_VMWARE_VMI) {
- /* Allow it to run... anyways, but warn */
- printk(KERN_WARNING "VMI: ROM from unknown manufacturer\n");
- }
-
- if (rom->pnp_header_offs) {
- pnp = (struct pnp_header *)((char *)rom+rom->pnp_header_offs);
- if (pnp->manufacturer_offset)
- manufacturer = (const char *)rom+pnp->manufacturer_offset;
- if (pnp->product_offset)
- product = (const char *)rom+pnp->product_offset;
- }
-
- if (rom->license_offs)
- license = (char *)rom+rom->license_offs;
-
- printk(KERN_INFO "VMI: Found %s %s, API version %d.%d, ROM version %d.%d\n",
- manufacturer, product,
- rom->api_version_maj, rom->api_version_min,
- pci->rom_version_maj, pci->rom_version_min);
-
- /* Don't allow BSD/MIT here for now because we don't want to end up
- with any binary only shim layers */
- if (strcmp(license, "GPL") && strcmp(license, "GPL v2")) {
- printk(KERN_WARNING "VMI: Non GPL license `%s' found for ROM. Not used.\n",
- license);
- return 0;
- }
-
- return 1;
-}
-
-/*
- * Probe for the VMI option ROM
- */
-static inline int __init probe_vmi_rom(void)
-{
- unsigned long base;
-
- /* VMI ROM is in option ROM area, check signature */
- for (base = 0xC0000; base < 0xE0000; base += 2048) {
- struct vrom_header *romstart;
- romstart = (struct vrom_header *)isa_bus_to_virt(base);
- if (check_vmi_rom(romstart)) {
- vmi_rom = romstart;
- return 1;
- }
- }
- return 0;
-}
-
-/*
- * VMI setup common to all processors
- */
-void vmi_bringup(void)
-{
- /* We must establish the lowmem mapping for MMU ops to work */
- if (vmi_ops.set_linear_mapping)
- vmi_ops.set_linear_mapping(0, (void *)__PAGE_OFFSET, MAXMEM_PFN, 0);
-}
-
-/*
- * Return a pointer to a VMI function or NULL if unimplemented
- */
-static void *vmi_get_function(int vmicall)
-{
- u64 reloc;
- const struct vmi_relocation_info *rel = (struct vmi_relocation_info *)&reloc;
- reloc = call_vrom_long_func(vmi_rom, get_reloc, vmicall);
- BUG_ON(rel->type == VMI_RELOCATION_JUMP_REL);
- if (rel->type == VMI_RELOCATION_CALL_REL)
- return (void *)rel->eip;
- else
- return NULL;
-}
-
-/*
- * Helper macro for making the VMI paravirt-ops fill code readable.
- * For unimplemented operations, fall back to default, unless nop
- * is returned by the ROM.
- */
-#define para_fill(opname, vmicall) \
-do { \
- reloc = call_vrom_long_func(vmi_rom, get_reloc, \
- VMI_CALL_##vmicall); \
- if (rel->type == VMI_RELOCATION_CALL_REL) \
- opname = (void *)rel->eip; \
- else if (rel->type == VMI_RELOCATION_NOP) \
- opname = (void *)vmi_nop; \
- else if (rel->type != VMI_RELOCATION_NONE) \
- printk(KERN_WARNING "VMI: Unknown relocation " \
- "type %d for " #vmicall"\n",\
- rel->type); \
-} while (0)
-
-/*
- * Helper macro for making the VMI paravirt-ops fill code readable.
- * For cached operations which do not match the VMI ROM ABI and must
- * go through a tranlation stub. Ignore NOPs, since it is not clear
- * a NOP * VMI function corresponds to a NOP paravirt-op when the
- * functions are not in 1-1 correspondence.
- */
-#define para_wrap(opname, wrapper, cache, vmicall) \
-do { \
- reloc = call_vrom_long_func(vmi_rom, get_reloc, \
- VMI_CALL_##vmicall); \
- BUG_ON(rel->type == VMI_RELOCATION_JUMP_REL); \
- if (rel->type == VMI_RELOCATION_CALL_REL) { \
- opname = wrapper; \
- vmi_ops.cache = (void *)rel->eip; \
- } \
-} while (0)
-
-/*
- * Activate the VMI interface and switch into paravirtualized mode
- */
-static inline int __init activate_vmi(void)
-{
- short kernel_cs;
- u64 reloc;
- const struct vmi_relocation_info *rel = (struct vmi_relocation_info *)&reloc;
-
- /*
- * Prevent page tables from being allocated in highmem, even if
- * CONFIG_HIGHPTE is enabled.
- */
- __userpte_alloc_gfp &= ~__GFP_HIGHMEM;
-
- if (call_vrom_func(vmi_rom, vmi_init) != 0) {
- printk(KERN_ERR "VMI ROM failed to initialize!");
- return 0;
- }
- savesegment(cs, kernel_cs);
-
- pv_info.paravirt_enabled = 1;
- pv_info.kernel_rpl = kernel_cs & SEGMENT_RPL_MASK;
- pv_info.name = "vmi [deprecated]";
-
- pv_init_ops.patch = vmi_patch;
-
- /*
- * Many of these operations are ABI compatible with VMI.
- * This means we can fill in the paravirt-ops with direct
- * pointers into the VMI ROM. If the calling convention for
- * these operations changes, this code needs to be updated.
- *
- * Exceptions
- * CPUID paravirt-op uses pointers, not the native ISA
- * halt has no VMI equivalent; all VMI halts are "safe"
- * no MSR support yet - just trap and emulate. VMI uses the
- * same ABI as the native ISA, but Linux wants exceptions
- * from bogus MSR read / write handled
- * rdpmc is not yet used in Linux
- */
-
- /* CPUID is special, so very special it gets wrapped like a present */
- para_wrap(pv_cpu_ops.cpuid, vmi_cpuid, cpuid, CPUID);
-
- para_fill(pv_cpu_ops.clts, CLTS);
- para_fill(pv_cpu_ops.get_debugreg, GetDR);
- para_fill(pv_cpu_ops.set_debugreg, SetDR);
- para_fill(pv_cpu_ops.read_cr0, GetCR0);
- para_fill(pv_mmu_ops.read_cr2, GetCR2);
- para_fill(pv_mmu_ops.read_cr3, GetCR3);
- para_fill(pv_cpu_ops.read_cr4, GetCR4);
- para_fill(pv_cpu_ops.write_cr0, SetCR0);
- para_fill(pv_mmu_ops.write_cr2, SetCR2);
- para_fill(pv_mmu_ops.write_cr3, SetCR3);
- para_fill(pv_cpu_ops.write_cr4, SetCR4);
-
- para_fill(pv_irq_ops.save_fl.func, GetInterruptMask);
- para_fill(pv_irq_ops.restore_fl.func, SetInterruptMask);
- para_fill(pv_irq_ops.irq_disable.func, DisableInterrupts);
- para_fill(pv_irq_ops.irq_enable.func, EnableInterrupts);
-
- para_fill(pv_cpu_ops.wbinvd, WBINVD);
- para_fill(pv_cpu_ops.read_tsc, RDTSC);
-
- /* The following we emulate with trap and emulate for now */
- /* paravirt_ops.read_msr = vmi_rdmsr */
- /* paravirt_ops.write_msr = vmi_wrmsr */
- /* paravirt_ops.rdpmc = vmi_rdpmc */
-
- /* TR interface doesn't pass TR value, wrap */
- para_wrap(pv_cpu_ops.load_tr_desc, vmi_set_tr, set_tr, SetTR);
-
- /* LDT is special, too */
- para_wrap(pv_cpu_ops.set_ldt, vmi_set_ldt, _set_ldt, SetLDT);
-
- para_fill(pv_cpu_ops.load_gdt, SetGDT);
- para_fill(pv_cpu_ops.load_idt, SetIDT);
- para_fill(pv_cpu_ops.store_gdt, GetGDT);
- para_fill(pv_cpu_ops.store_idt, GetIDT);
- para_fill(pv_cpu_ops.store_tr, GetTR);
- pv_cpu_ops.load_tls = vmi_load_tls;
- para_wrap(pv_cpu_ops.write_ldt_entry, vmi_write_ldt_entry,
- write_ldt_entry, WriteLDTEntry);
- para_wrap(pv_cpu_ops.write_gdt_entry, vmi_write_gdt_entry,
- write_gdt_entry, WriteGDTEntry);
- para_wrap(pv_cpu_ops.write_idt_entry, vmi_write_idt_entry,
- write_idt_entry, WriteIDTEntry);
- para_wrap(pv_cpu_ops.load_sp0, vmi_load_sp0, set_kernel_stack, UpdateKernelStack);
- para_fill(pv_cpu_ops.set_iopl_mask, SetIOPLMask);
- para_fill(pv_cpu_ops.io_delay, IODelay);
-
- para_wrap(pv_cpu_ops.start_context_switch, vmi_start_context_switch,
- set_lazy_mode, SetLazyMode);
- para_wrap(pv_cpu_ops.end_context_switch, vmi_end_context_switch,
- set_lazy_mode, SetLazyMode);
-
- para_wrap(pv_mmu_ops.lazy_mode.enter, vmi_enter_lazy_mmu,
- set_lazy_mode, SetLazyMode);
- para_wrap(pv_mmu_ops.lazy_mode.leave, vmi_leave_lazy_mmu,
- set_lazy_mode, SetLazyMode);
-
- /* user and kernel flush are just handled with different flags to FlushTLB */
- para_wrap(pv_mmu_ops.flush_tlb_user, vmi_flush_tlb_user, _flush_tlb, FlushTLB);
- para_wrap(pv_mmu_ops.flush_tlb_kernel, vmi_flush_tlb_kernel, _flush_tlb, FlushTLB);
- para_fill(pv_mmu_ops.flush_tlb_single, InvalPage);
-
- /*
- * Until a standard flag format can be agreed on, we need to
- * implement these as wrappers in Linux. Get the VMI ROM
- * function pointers for the two backend calls.
- */
-#ifdef CONFIG_X86_PAE
- vmi_ops.set_pte = vmi_get_function(VMI_CALL_SetPxELong);
- vmi_ops.update_pte = vmi_get_function(VMI_CALL_UpdatePxELong);
-#else
- vmi_ops.set_pte = vmi_get_function(VMI_CALL_SetPxE);
- vmi_ops.update_pte = vmi_get_function(VMI_CALL_UpdatePxE);
-#endif
-
- if (vmi_ops.set_pte) {
- pv_mmu_ops.set_pte = vmi_set_pte;
- pv_mmu_ops.set_pte_at = vmi_set_pte_at;
- pv_mmu_ops.set_pmd = vmi_set_pmd;
-#ifdef CONFIG_X86_PAE
- pv_mmu_ops.set_pte_atomic = vmi_set_pte_atomic;
- pv_mmu_ops.set_pud = vmi_set_pud;
- pv_mmu_ops.pte_clear = vmi_pte_clear;
- pv_mmu_ops.pmd_clear = vmi_pmd_clear;
-#endif
- }
-
- if (vmi_ops.update_pte) {
- pv_mmu_ops.pte_update = vmi_update_pte;
- pv_mmu_ops.pte_update_defer = vmi_update_pte_defer;
- }
-
- vmi_ops.allocate_page = vmi_get_function(VMI_CALL_AllocatePage);
- if (vmi_ops.allocate_page) {
- pv_mmu_ops.alloc_pte = vmi_allocate_pte;
- pv_mmu_ops.alloc_pmd = vmi_allocate_pmd;
- pv_mmu_ops.alloc_pmd_clone = vmi_allocate_pmd_clone;
- }
-
- vmi_ops.release_page = vmi_get_function(VMI_CALL_ReleasePage);
- if (vmi_ops.release_page) {
- pv_mmu_ops.release_pte = vmi_release_pte;
- pv_mmu_ops.release_pmd = vmi_release_pmd;
- pv_mmu_ops.pgd_free = vmi_pgd_free;
- }
-
- /* Set linear is needed in all cases */
- vmi_ops.set_linear_mapping = vmi_get_function(VMI_CALL_SetLinearMapping);
-
- /*
- * These MUST always be patched. Don't support indirect jumps
- * through these operations, as the VMI interface may use either
- * a jump or a call to get to these operations, depending on
- * the backend. They are performance critical anyway, so requiring
- * a patch is not a big problem.
- */
- pv_cpu_ops.irq_enable_sysexit = (void *)0xfeedbab0;
- pv_cpu_ops.iret = (void *)0xbadbab0;
-
-#ifdef CONFIG_SMP
- para_wrap(pv_apic_ops.startup_ipi_hook, vmi_startup_ipi_hook, set_initial_ap_state, SetInitialAPState);
-#endif
-
-#ifdef CONFIG_X86_LOCAL_APIC
- para_fill(apic->read, APICRead);
- para_fill(apic->write, APICWrite);
-#endif
-
- /*
- * Check for VMI timer functionality by probing for a cycle frequency method
- */
- reloc = call_vrom_long_func(vmi_rom, get_reloc, VMI_CALL_GetCycleFrequency);
- if (!disable_vmi_timer && rel->type != VMI_RELOCATION_NONE) {
- vmi_timer_ops.get_cycle_frequency = (void *)rel->eip;
- vmi_timer_ops.get_cycle_counter =
- vmi_get_function(VMI_CALL_GetCycleCounter);
- vmi_timer_ops.get_wallclock =
- vmi_get_function(VMI_CALL_GetWallclockTime);
- vmi_timer_ops.wallclock_updated =
- vmi_get_function(VMI_CALL_WallclockUpdated);
- vmi_timer_ops.set_alarm = vmi_get_function(VMI_CALL_SetAlarm);
- vmi_timer_ops.cancel_alarm =
- vmi_get_function(VMI_CALL_CancelAlarm);
- x86_init.timers.timer_init = vmi_time_init;
-#ifdef CONFIG_X86_LOCAL_APIC
- x86_init.timers.setup_percpu_clockev = vmi_time_bsp_init;
- x86_cpuinit.setup_percpu_clockev = vmi_time_ap_init;
-#endif
- pv_time_ops.sched_clock = vmi_sched_clock;
- x86_platform.calibrate_tsc = vmi_tsc_khz;
- x86_platform.get_wallclock = vmi_get_wallclock;
- x86_platform.set_wallclock = vmi_set_wallclock;
-
- /* We have true wallclock functions; disable CMOS clock sync */
- no_sync_cmos_clock = 1;
- } else {
- disable_noidle = 1;
- disable_vmi_timer = 1;
- }
-
- para_fill(pv_irq_ops.safe_halt, Halt);
-
- /*
- * Alternative instruction rewriting doesn't happen soon enough
- * to convert VMI_IRET to a call instead of a jump; so we have
- * to do this before IRQs get reenabled. Fortunately, it is
- * idempotent.
- */
- apply_paravirt(__parainstructions, __parainstructions_end);
-
- vmi_bringup();
-
- return 1;
-}
-
-#undef para_fill
-
-void __init vmi_init(void)
-{
- if (!vmi_rom)
- probe_vmi_rom();
- else
- check_vmi_rom(vmi_rom);
-
- /* In case probing for or validating the ROM failed, basil */
- if (!vmi_rom)
- return;
-
- reserve_top_address(-vmi_rom->virtual_top);
-
-#ifdef CONFIG_X86_IO_APIC
- /* This is virtual hardware; timer routing is wired correctly */
- no_timer_check = 1;
-#endif
-}
-
-void __init vmi_activate(void)
-{
- unsigned long flags;
-
- if (!vmi_rom)
- return;
-
- local_irq_save(flags);
- activate_vmi();
- local_irq_restore(flags & X86_EFLAGS_IF);
-}
-
-static int __init parse_vmi(char *arg)
-{
- if (!arg)
- return -EINVAL;
-
- if (!strcmp(arg, "disable_pge")) {
- clear_cpu_cap(&boot_cpu_data, X86_FEATURE_PGE);
- disable_pge = 1;
- } else if (!strcmp(arg, "disable_pse")) {
- clear_cpu_cap(&boot_cpu_data, X86_FEATURE_PSE);
- disable_pse = 1;
- } else if (!strcmp(arg, "disable_sep")) {
- clear_cpu_cap(&boot_cpu_data, X86_FEATURE_SEP);
- disable_sep = 1;
- } else if (!strcmp(arg, "disable_tsc")) {
- clear_cpu_cap(&boot_cpu_data, X86_FEATURE_TSC);
- disable_tsc = 1;
- } else if (!strcmp(arg, "disable_mtrr")) {
- clear_cpu_cap(&boot_cpu_data, X86_FEATURE_MTRR);
- disable_mtrr = 1;
- } else if (!strcmp(arg, "disable_timer")) {
- disable_vmi_timer = 1;
- disable_noidle = 1;
- } else if (!strcmp(arg, "disable_noidle"))
- disable_noidle = 1;
- return 0;
-}
-
-early_param("vmi", parse_vmi);
diff --git a/arch/x86/kernel/vmiclock_32.c b/arch/x86/kernel/vmiclock_32.c
deleted file mode 100644
index 5e1ff66ecd73..000000000000
--- a/arch/x86/kernel/vmiclock_32.c
+++ /dev/null
@@ -1,317 +0,0 @@
-/*
- * VMI paravirtual timer support routines.
- *
- * Copyright (C) 2007, VMware, 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.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#include <linux/smp.h>
-#include <linux/interrupt.h>
-#include <linux/cpumask.h>
-#include <linux/clocksource.h>
-#include <linux/clockchips.h>
-
-#include <asm/vmi.h>
-#include <asm/vmi_time.h>
-#include <asm/apicdef.h>
-#include <asm/apic.h>
-#include <asm/timer.h>
-#include <asm/i8253.h>
-#include <asm/irq_vectors.h>
-
-#define VMI_ONESHOT (VMI_ALARM_IS_ONESHOT | VMI_CYCLES_REAL | vmi_get_alarm_wiring())
-#define VMI_PERIODIC (VMI_ALARM_IS_PERIODIC | VMI_CYCLES_REAL | vmi_get_alarm_wiring())
-
-static DEFINE_PER_CPU(struct clock_event_device, local_events);
-
-static inline u32 vmi_counter(u32 flags)
-{
- /* Given VMI_ONESHOT or VMI_PERIODIC, return the corresponding
- * cycle counter. */
- return flags & VMI_ALARM_COUNTER_MASK;
-}
-
-/* paravirt_ops.get_wallclock = vmi_get_wallclock */
-unsigned long vmi_get_wallclock(void)
-{
- unsigned long long wallclock;
- wallclock = vmi_timer_ops.get_wallclock(); // nsec
- (void)do_div(wallclock, 1000000000); // sec
-
- return wallclock;
-}
-
-/* paravirt_ops.set_wallclock = vmi_set_wallclock */
-int vmi_set_wallclock(unsigned long now)
-{
- return 0;
-}
-
-/* paravirt_ops.sched_clock = vmi_sched_clock */
-unsigned long long vmi_sched_clock(void)
-{
- return cycles_2_ns(vmi_timer_ops.get_cycle_counter(VMI_CYCLES_AVAILABLE));
-}
-
-/* x86_platform.calibrate_tsc = vmi_tsc_khz */
-unsigned long vmi_tsc_khz(void)
-{
- unsigned long long khz;
- khz = vmi_timer_ops.get_cycle_frequency();
- (void)do_div(khz, 1000);
- return khz;
-}
-
-static inline unsigned int vmi_get_timer_vector(void)
-{
- return IRQ0_VECTOR;
-}
-
-/** vmi clockchip */
-#ifdef CONFIG_X86_LOCAL_APIC
-static unsigned int startup_timer_irq(unsigned int irq)
-{
- unsigned long val = apic_read(APIC_LVTT);
- apic_write(APIC_LVTT, vmi_get_timer_vector());
-
- return (val & APIC_SEND_PENDING);
-}
-
-static void mask_timer_irq(unsigned int irq)
-{
- unsigned long val = apic_read(APIC_LVTT);
- apic_write(APIC_LVTT, val | APIC_LVT_MASKED);
-}
-
-static void unmask_timer_irq(unsigned int irq)
-{
- unsigned long val = apic_read(APIC_LVTT);
- apic_write(APIC_LVTT, val & ~APIC_LVT_MASKED);
-}
-
-static void ack_timer_irq(unsigned int irq)
-{
- ack_APIC_irq();
-}
-
-static struct irq_chip vmi_chip __read_mostly = {
- .name = "VMI-LOCAL",
- .startup = startup_timer_irq,
- .mask = mask_timer_irq,
- .unmask = unmask_timer_irq,
- .ack = ack_timer_irq
-};
-#endif
-
-/** vmi clockevent */
-#define VMI_ALARM_WIRED_IRQ0 0x00000000
-#define VMI_ALARM_WIRED_LVTT 0x00010000
-static int vmi_wiring = VMI_ALARM_WIRED_IRQ0;
-
-static inline int vmi_get_alarm_wiring(void)
-{
- return vmi_wiring;
-}
-
-static void vmi_timer_set_mode(enum clock_event_mode mode,
- struct clock_event_device *evt)
-{
- cycle_t now, cycles_per_hz;
- BUG_ON(!irqs_disabled());
-
- switch (mode) {
- case CLOCK_EVT_MODE_ONESHOT:
- case CLOCK_EVT_MODE_RESUME:
- break;
- case CLOCK_EVT_MODE_PERIODIC:
- cycles_per_hz = vmi_timer_ops.get_cycle_frequency();
- (void)do_div(cycles_per_hz, HZ);
- now = vmi_timer_ops.get_cycle_counter(vmi_counter(VMI_PERIODIC));
- vmi_timer_ops.set_alarm(VMI_PERIODIC, now, cycles_per_hz);
- break;
- case CLOCK_EVT_MODE_UNUSED:
- case CLOCK_EVT_MODE_SHUTDOWN:
- switch (evt->mode) {
- case CLOCK_EVT_MODE_ONESHOT:
- vmi_timer_ops.cancel_alarm(VMI_ONESHOT);
- break;
- case CLOCK_EVT_MODE_PERIODIC:
- vmi_timer_ops.cancel_alarm(VMI_PERIODIC);
- break;
- default:
- break;
- }
- break;
- default:
- break;
- }
-}
-
-static int vmi_timer_next_event(unsigned long delta,
- struct clock_event_device *evt)
-{
- /* Unfortunately, set_next_event interface only passes relative
- * expiry, but we want absolute expiry. It'd be better if were
- * were passed an absolute expiry, since a bunch of time may
- * have been stolen between the time the delta is computed and
- * when we set the alarm below. */
- cycle_t now = vmi_timer_ops.get_cycle_counter(vmi_counter(VMI_ONESHOT));
-
- BUG_ON(evt->mode != CLOCK_EVT_MODE_ONESHOT);
- vmi_timer_ops.set_alarm(VMI_ONESHOT, now + delta, 0);
- return 0;
-}
-
-static struct clock_event_device vmi_clockevent = {
- .name = "vmi-timer",
- .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
- .shift = 22,
- .set_mode = vmi_timer_set_mode,
- .set_next_event = vmi_timer_next_event,
- .rating = 1000,
- .irq = 0,
-};
-
-static irqreturn_t vmi_timer_interrupt(int irq, void *dev_id)
-{
- struct clock_event_device *evt = &__get_cpu_var(local_events);
- evt->event_handler(evt);
- return IRQ_HANDLED;
-}
-
-static struct irqaction vmi_clock_action = {
- .name = "vmi-timer",
- .handler = vmi_timer_interrupt,
- .flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_TIMER,
-};
-
-static void __devinit vmi_time_init_clockevent(void)
-{
- cycle_t cycles_per_msec;
- struct clock_event_device *evt;
-
- int cpu = smp_processor_id();
- evt = &__get_cpu_var(local_events);
-
- /* Use cycles_per_msec since div_sc params are 32-bits. */
- cycles_per_msec = vmi_timer_ops.get_cycle_frequency();
- (void)do_div(cycles_per_msec, 1000);
-
- memcpy(evt, &vmi_clockevent, sizeof(*evt));
- /* Must pick .shift such that .mult fits in 32-bits. Choosing
- * .shift to be 22 allows 2^(32-22) cycles per nano-seconds
- * before overflow. */
- evt->mult = div_sc(cycles_per_msec, NSEC_PER_MSEC, evt->shift);
- /* Upper bound is clockevent's use of ulong for cycle deltas. */
- evt->max_delta_ns = clockevent_delta2ns(ULONG_MAX, evt);
- evt->min_delta_ns = clockevent_delta2ns(1, evt);
- evt->cpumask = cpumask_of(cpu);
-
- printk(KERN_WARNING "vmi: registering clock event %s. mult=%u shift=%u\n",
- evt->name, evt->mult, evt->shift);
- clockevents_register_device(evt);
-}
-
-void __init vmi_time_init(void)
-{
- unsigned int cpu;
- /* Disable PIT: BIOSes start PIT CH0 with 18.2hz peridic. */
- outb_pit(0x3a, PIT_MODE); /* binary, mode 5, LSB/MSB, ch 0 */
-
- vmi_time_init_clockevent();
- setup_irq(0, &vmi_clock_action);
- for_each_possible_cpu(cpu)
- per_cpu(vector_irq, cpu)[vmi_get_timer_vector()] = 0;
-}
-
-#ifdef CONFIG_X86_LOCAL_APIC
-void __devinit vmi_time_bsp_init(void)
-{
- /*
- * On APIC systems, we want local timers to fire on each cpu. We do
- * this by programming LVTT to deliver timer events to the IRQ handler
- * for IRQ-0, since we can't re-use the APIC local timer handler
- * without interfering with that code.
- */
- clockevents_notify(CLOCK_EVT_NOTIFY_SUSPEND, NULL);
- local_irq_disable();
-#ifdef CONFIG_SMP
- /*
- * XXX handle_percpu_irq only defined for SMP; we need to switch over
- * to using it, since this is a local interrupt, which each CPU must
- * handle individually without locking out or dropping simultaneous
- * local timers on other CPUs. We also don't want to trigger the
- * quirk workaround code for interrupts which gets invoked from
- * handle_percpu_irq via eoi, so we use our own IRQ chip.
- */
- set_irq_chip_and_handler_name(0, &vmi_chip, handle_percpu_irq, "lvtt");
-#else
- set_irq_chip_and_handler_name(0, &vmi_chip, handle_edge_irq, "lvtt");
-#endif
- vmi_wiring = VMI_ALARM_WIRED_LVTT;
- apic_write(APIC_LVTT, vmi_get_timer_vector());
- local_irq_enable();
- clockevents_notify(CLOCK_EVT_NOTIFY_RESUME, NULL);
-}
-
-void __devinit vmi_time_ap_init(void)
-{
- vmi_time_init_clockevent();
- apic_write(APIC_LVTT, vmi_get_timer_vector());
-}
-#endif
-
-/** vmi clocksource */
-static struct clocksource clocksource_vmi;
-
-static cycle_t read_real_cycles(struct clocksource *cs)
-{
- cycle_t ret = (cycle_t)vmi_timer_ops.get_cycle_counter(VMI_CYCLES_REAL);
- return max(ret, clocksource_vmi.cycle_last);
-}
-
-static struct clocksource clocksource_vmi = {
- .name = "vmi-timer",
- .rating = 450,
- .read = read_real_cycles,
- .mask = CLOCKSOURCE_MASK(64),
- .mult = 0, /* to be set */
- .shift = 22,
- .flags = CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
-static int __init init_vmi_clocksource(void)
-{
- cycle_t cycles_per_msec;
-
- if (!vmi_timer_ops.get_cycle_frequency)
- return 0;
- /* Use khz2mult rather than hz2mult since hz arg is only 32-bits. */
- cycles_per_msec = vmi_timer_ops.get_cycle_frequency();
- (void)do_div(cycles_per_msec, 1000);
-
- /* Note that clocksource.{mult, shift} converts in the opposite direction
- * as clockevents. */
- clocksource_vmi.mult = clocksource_khz2mult(cycles_per_msec,
- clocksource_vmi.shift);
-
- printk(KERN_WARNING "vmi: registering clock source khz=%lld\n", cycles_per_msec);
- return clocksource_register(&clocksource_vmi);
-
-}
-module_init(init_vmi_clocksource);
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index d0bb52296fa3..e03530aebfd0 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -242,6 +242,12 @@ SECTIONS
__x86_cpu_dev_end = .;
}
+ /*
+ * start address and size of operations which during runtime
+ * can be patched with virtualization friendly instructions or
+ * baremetal native ones. Think page table operations.
+ * Details in paravirt_types.h
+ */
. = ALIGN(8);
.parainstructions : AT(ADDR(.parainstructions) - LOAD_OFFSET) {
__parainstructions = .;
@@ -249,6 +255,11 @@ SECTIONS
__parainstructions_end = .;
}
+ /*
+ * struct alt_inst entries. From the header (alternative.h):
+ * "Alternative instructions for different CPU types or capabilities"
+ * Think locking instructions on spinlocks.
+ */
. = ALIGN(8);
.altinstructions : AT(ADDR(.altinstructions) - LOAD_OFFSET) {
__alt_instructions = .;
@@ -256,11 +267,28 @@ SECTIONS
__alt_instructions_end = .;
}
+ /*
+ * And here are the replacement instructions. The linker sticks
+ * them as binary blobs. The .altinstructions has enough data to
+ * get the address and the length of them to patch the kernel safely.
+ */
.altinstr_replacement : AT(ADDR(.altinstr_replacement) - LOAD_OFFSET) {
*(.altinstr_replacement)
}
/*
+ * struct iommu_table_entry entries are injected in this section.
+ * It is an array of IOMMUs which during run time gets sorted depending
+ * on its dependency order. After rootfs_initcall is complete
+ * this section can be safely removed.
+ */
+ .iommu_table : AT(ADDR(.iommu_table) - LOAD_OFFSET) {
+ __iommu_table = .;
+ *(.iommu_table)
+ __iommu_table_end = .;
+ }
+ . = ALIGN(8);
+ /*
* .exit.text is discard at runtime, not link time, to deal with
* references from .altinstructions and .eh_frame
*/
@@ -273,7 +301,7 @@ SECTIONS
}
#if !defined(CONFIG_X86_64) || !defined(CONFIG_SMP)
- PERCPU(PAGE_SIZE)
+ PERCPU(THREAD_SIZE)
#endif
. = ALIGN(PAGE_SIZE);
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 77d8c0f4817d..22b06f7660f4 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -1056,14 +1056,13 @@ int kvm_create_lapic(struct kvm_vcpu *vcpu)
vcpu->arch.apic = apic;
- apic->regs_page = alloc_page(GFP_KERNEL);
+ apic->regs_page = alloc_page(GFP_KERNEL|__GFP_ZERO);
if (apic->regs_page == NULL) {
printk(KERN_ERR "malloc apic regs error for vcpu %x\n",
vcpu->vcpu_id);
goto nomem_free_apic;
}
apic->regs = page_address(apic->regs_page);
- memset(apic->regs, 0, PAGE_SIZE);
apic->vcpu = vcpu;
hrtimer_init(&apic->lapic_timer.timer, CLOCK_MONOTONIC,
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index bc5b9b8d4a33..8a3f9f64f86f 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -766,7 +766,6 @@ static void init_vmcb(struct vcpu_svm *svm)
control->iopm_base_pa = iopm_base;
control->msrpm_base_pa = __pa(svm->msrpm);
- control->tsc_offset = 0;
control->int_ctl = V_INTR_MASKING_MASK;
init_seg(&save->es);
@@ -902,6 +901,7 @@ static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id)
svm->vmcb_pa = page_to_pfn(page) << PAGE_SHIFT;
svm->asid_generation = 0;
init_vmcb(svm);
+ svm->vmcb->control.tsc_offset = 0-native_read_tsc();
err = fx_init(&svm->vcpu);
if (err)
@@ -3163,8 +3163,8 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu)
sync_lapic_to_cr8(vcpu);
save_host_msrs(vcpu);
- fs_selector = kvm_read_fs();
- gs_selector = kvm_read_gs();
+ savesegment(fs, fs_selector);
+ savesegment(gs, gs_selector);
ldt_selector = kvm_read_ldt();
svm->vmcb->save.cr2 = vcpu->arch.cr2;
/* required for live migration with NPT */
@@ -3251,10 +3251,15 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu)
vcpu->arch.regs[VCPU_REGS_RSP] = svm->vmcb->save.rsp;
vcpu->arch.regs[VCPU_REGS_RIP] = svm->vmcb->save.rip;
- kvm_load_fs(fs_selector);
- kvm_load_gs(gs_selector);
- kvm_load_ldt(ldt_selector);
load_host_msrs(vcpu);
+ loadsegment(fs, fs_selector);
+#ifdef CONFIG_X86_64
+ load_gs_index(gs_selector);
+ wrmsrl(MSR_KERNEL_GS_BASE, current->thread.gs);
+#else
+ loadsegment(gs, gs_selector);
+#endif
+ kvm_load_ldt(ldt_selector);
reload_tss(vcpu);
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 49b25eee25ac..7bddfab12013 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -803,7 +803,7 @@ static void vmx_save_host_state(struct kvm_vcpu *vcpu)
*/
vmx->host_state.ldt_sel = kvm_read_ldt();
vmx->host_state.gs_ldt_reload_needed = vmx->host_state.ldt_sel;
- vmx->host_state.fs_sel = kvm_read_fs();
+ savesegment(fs, vmx->host_state.fs_sel);
if (!(vmx->host_state.fs_sel & 7)) {
vmcs_write16(HOST_FS_SELECTOR, vmx->host_state.fs_sel);
vmx->host_state.fs_reload_needed = 0;
@@ -811,7 +811,7 @@ static void vmx_save_host_state(struct kvm_vcpu *vcpu)
vmcs_write16(HOST_FS_SELECTOR, 0);
vmx->host_state.fs_reload_needed = 1;
}
- vmx->host_state.gs_sel = kvm_read_gs();
+ savesegment(gs, vmx->host_state.gs_sel);
if (!(vmx->host_state.gs_sel & 7))
vmcs_write16(HOST_GS_SELECTOR, vmx->host_state.gs_sel);
else {
@@ -841,27 +841,21 @@ static void vmx_save_host_state(struct kvm_vcpu *vcpu)
static void __vmx_load_host_state(struct vcpu_vmx *vmx)
{
- unsigned long flags;
-
if (!vmx->host_state.loaded)
return;
++vmx->vcpu.stat.host_state_reload;
vmx->host_state.loaded = 0;
if (vmx->host_state.fs_reload_needed)
- kvm_load_fs(vmx->host_state.fs_sel);
+ loadsegment(fs, vmx->host_state.fs_sel);
if (vmx->host_state.gs_ldt_reload_needed) {
kvm_load_ldt(vmx->host_state.ldt_sel);
- /*
- * If we have to reload gs, we must take care to
- * preserve our gs base.
- */
- local_irq_save(flags);
- kvm_load_gs(vmx->host_state.gs_sel);
#ifdef CONFIG_X86_64
- wrmsrl(MSR_GS_BASE, vmcs_readl(HOST_GS_BASE));
+ load_gs_index(vmx->host_state.gs_sel);
+ wrmsrl(MSR_KERNEL_GS_BASE, current->thread.gs);
+#else
+ loadsegment(gs, vmx->host_state.gs_sel);
#endif
- local_irq_restore(flags);
}
reload_tss();
#ifdef CONFIG_X86_64
@@ -2589,8 +2583,8 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
vmcs_write16(HOST_CS_SELECTOR, __KERNEL_CS); /* 22.2.4 */
vmcs_write16(HOST_DS_SELECTOR, __KERNEL_DS); /* 22.2.4 */
vmcs_write16(HOST_ES_SELECTOR, __KERNEL_DS); /* 22.2.4 */
- vmcs_write16(HOST_FS_SELECTOR, kvm_read_fs()); /* 22.2.4 */
- vmcs_write16(HOST_GS_SELECTOR, kvm_read_gs()); /* 22.2.4 */
+ vmcs_write16(HOST_FS_SELECTOR, 0); /* 22.2.4 */
+ vmcs_write16(HOST_GS_SELECTOR, 0); /* 22.2.4 */
vmcs_write16(HOST_SS_SELECTOR, __KERNEL_DS); /* 22.2.4 */
#ifdef CONFIG_X86_64
rdmsrl(MSR_FS_BASE, a);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 3a09c625d526..6c2ecf0a806d 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1991,13 +1991,14 @@ static void do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
0 /* Reserved */ | F(CX16) | 0 /* xTPR Update, PDCM */ |
0 /* Reserved, DCA */ | F(XMM4_1) |
F(XMM4_2) | F(X2APIC) | F(MOVBE) | F(POPCNT) |
- 0 /* Reserved, AES */ | F(XSAVE) | 0 /* OSXSAVE */ | F(AVX);
+ 0 /* Reserved*/ | F(AES) | F(XSAVE) | 0 /* OSXSAVE */ | F(AVX) |
+ F(F16C);
/* cpuid 0x80000001.ecx */
const u32 kvm_supported_word6_x86_features =
F(LAHF_LM) | F(CMP_LEGACY) | F(SVM) | 0 /* ExtApicSpace */ |
F(CR8_LEGACY) | F(ABM) | F(SSE4A) | F(MISALIGNSSE) |
- F(3DNOWPREFETCH) | 0 /* OSVW */ | 0 /* IBS */ | F(SSE5) |
- 0 /* SKINIT */ | 0 /* WDT */;
+ F(3DNOWPREFETCH) | 0 /* OSVW */ | 0 /* IBS */ | F(XOP) |
+ 0 /* SKINIT, WDT, LWP */ | F(FMA4) | F(TBM);
/* all calls to cpuid_count() should be made on the same cpu */
get_cpu();
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c
index 9d5f55848455..73b1e1a1f489 100644
--- a/arch/x86/lguest/boot.c
+++ b/arch/x86/lguest/boot.c
@@ -791,22 +791,22 @@ static void lguest_flush_tlb_kernel(void)
* simple as setting a bit. We don't actually "ack" interrupts as such, we
* just mask and unmask them. I wonder if we should be cleverer?
*/
-static void disable_lguest_irq(unsigned int irq)
+static void disable_lguest_irq(struct irq_data *data)
{
- set_bit(irq, lguest_data.blocked_interrupts);
+ set_bit(data->irq, lguest_data.blocked_interrupts);
}
-static void enable_lguest_irq(unsigned int irq)
+static void enable_lguest_irq(struct irq_data *data)
{
- clear_bit(irq, lguest_data.blocked_interrupts);
+ clear_bit(data->irq, lguest_data.blocked_interrupts);
}
/* This structure describes the lguest IRQ controller. */
static struct irq_chip lguest_irq_controller = {
.name = "lguest",
- .mask = disable_lguest_irq,
- .mask_ack = disable_lguest_irq,
- .unmask = enable_lguest_irq,
+ .irq_mask = disable_lguest_irq,
+ .irq_mask_ack = disable_lguest_irq,
+ .irq_unmask = enable_lguest_irq,
};
/*
@@ -838,12 +838,12 @@ static void __init lguest_init_IRQ(void)
* rather than set them in lguest_init_IRQ we are called here every time an
* lguest device needs an interrupt.
*
- * FIXME: irq_to_desc_alloc_node() can fail due to lack of memory, we should
+ * FIXME: irq_alloc_desc_at() can fail due to lack of memory, we should
* pass that up!
*/
void lguest_setup_irq(unsigned int irq)
{
- irq_to_desc_alloc_node(irq, 0);
+ irq_alloc_desc_at(irq, 0);
set_irq_chip_and_handler_name(irq, &lguest_irq_controller,
handle_level_irq, "level");
}
diff --git a/arch/x86/lib/memcpy_32.c b/arch/x86/lib/memcpy_32.c
index 5415a9d06f53..b908a59eccf5 100644
--- a/arch/x86/lib/memcpy_32.c
+++ b/arch/x86/lib/memcpy_32.c
@@ -22,22 +22,187 @@ EXPORT_SYMBOL(memset);
void *memmove(void *dest, const void *src, size_t n)
{
- int d0, d1, d2;
-
- if (dest < src) {
- memcpy(dest, src, n);
- } else {
- __asm__ __volatile__(
- "std\n\t"
- "rep\n\t"
- "movsb\n\t"
- "cld"
- : "=&c" (d0), "=&S" (d1), "=&D" (d2)
- :"0" (n),
- "1" (n-1+src),
- "2" (n-1+dest)
- :"memory");
- }
- return dest;
+ int d0,d1,d2,d3,d4,d5;
+ char *ret = dest;
+
+ __asm__ __volatile__(
+ /* Handle more 16bytes in loop */
+ "cmp $0x10, %0\n\t"
+ "jb 1f\n\t"
+
+ /* Decide forward/backward copy mode */
+ "cmp %2, %1\n\t"
+ "jb 2f\n\t"
+
+ /*
+ * movs instruction have many startup latency
+ * so we handle small size by general register.
+ */
+ "cmp $680, %0\n\t"
+ "jb 3f\n\t"
+ /*
+ * movs instruction is only good for aligned case.
+ */
+ "mov %1, %3\n\t"
+ "xor %2, %3\n\t"
+ "and $0xff, %3\n\t"
+ "jz 4f\n\t"
+ "3:\n\t"
+ "sub $0x10, %0\n\t"
+
+ /*
+ * We gobble 16byts forward in each loop.
+ */
+ "3:\n\t"
+ "sub $0x10, %0\n\t"
+ "mov 0*4(%1), %3\n\t"
+ "mov 1*4(%1), %4\n\t"
+ "mov %3, 0*4(%2)\n\t"
+ "mov %4, 1*4(%2)\n\t"
+ "mov 2*4(%1), %3\n\t"
+ "mov 3*4(%1), %4\n\t"
+ "mov %3, 2*4(%2)\n\t"
+ "mov %4, 3*4(%2)\n\t"
+ "lea 0x10(%1), %1\n\t"
+ "lea 0x10(%2), %2\n\t"
+ "jae 3b\n\t"
+ "add $0x10, %0\n\t"
+ "jmp 1f\n\t"
+
+ /*
+ * Handle data forward by movs.
+ */
+ ".p2align 4\n\t"
+ "4:\n\t"
+ "mov -4(%1, %0), %3\n\t"
+ "lea -4(%2, %0), %4\n\t"
+ "shr $2, %0\n\t"
+ "rep movsl\n\t"
+ "mov %3, (%4)\n\t"
+ "jmp 11f\n\t"
+ /*
+ * Handle data backward by movs.
+ */
+ ".p2align 4\n\t"
+ "6:\n\t"
+ "mov (%1), %3\n\t"
+ "mov %2, %4\n\t"
+ "lea -4(%1, %0), %1\n\t"
+ "lea -4(%2, %0), %2\n\t"
+ "shr $2, %0\n\t"
+ "std\n\t"
+ "rep movsl\n\t"
+ "mov %3,(%4)\n\t"
+ "cld\n\t"
+ "jmp 11f\n\t"
+
+ /*
+ * Start to prepare for backward copy.
+ */
+ ".p2align 4\n\t"
+ "2:\n\t"
+ "cmp $680, %0\n\t"
+ "jb 5f\n\t"
+ "mov %1, %3\n\t"
+ "xor %2, %3\n\t"
+ "and $0xff, %3\n\t"
+ "jz 6b\n\t"
+
+ /*
+ * Calculate copy position to tail.
+ */
+ "5:\n\t"
+ "add %0, %1\n\t"
+ "add %0, %2\n\t"
+ "sub $0x10, %0\n\t"
+
+ /*
+ * We gobble 16byts backward in each loop.
+ */
+ "7:\n\t"
+ "sub $0x10, %0\n\t"
+
+ "mov -1*4(%1), %3\n\t"
+ "mov -2*4(%1), %4\n\t"
+ "mov %3, -1*4(%2)\n\t"
+ "mov %4, -2*4(%2)\n\t"
+ "mov -3*4(%1), %3\n\t"
+ "mov -4*4(%1), %4\n\t"
+ "mov %3, -3*4(%2)\n\t"
+ "mov %4, -4*4(%2)\n\t"
+ "lea -0x10(%1), %1\n\t"
+ "lea -0x10(%2), %2\n\t"
+ "jae 7b\n\t"
+ /*
+ * Calculate copy position to head.
+ */
+ "add $0x10, %0\n\t"
+ "sub %0, %1\n\t"
+ "sub %0, %2\n\t"
+
+ /*
+ * Move data from 8 bytes to 15 bytes.
+ */
+ ".p2align 4\n\t"
+ "1:\n\t"
+ "cmp $8, %0\n\t"
+ "jb 8f\n\t"
+ "mov 0*4(%1), %3\n\t"
+ "mov 1*4(%1), %4\n\t"
+ "mov -2*4(%1, %0), %5\n\t"
+ "mov -1*4(%1, %0), %1\n\t"
+
+ "mov %3, 0*4(%2)\n\t"
+ "mov %4, 1*4(%2)\n\t"
+ "mov %5, -2*4(%2, %0)\n\t"
+ "mov %1, -1*4(%2, %0)\n\t"
+ "jmp 11f\n\t"
+
+ /*
+ * Move data from 4 bytes to 7 bytes.
+ */
+ ".p2align 4\n\t"
+ "8:\n\t"
+ "cmp $4, %0\n\t"
+ "jb 9f\n\t"
+ "mov 0*4(%1), %3\n\t"
+ "mov -1*4(%1, %0), %4\n\t"
+ "mov %3, 0*4(%2)\n\t"
+ "mov %4, -1*4(%2, %0)\n\t"
+ "jmp 11f\n\t"
+
+ /*
+ * Move data from 2 bytes to 3 bytes.
+ */
+ ".p2align 4\n\t"
+ "9:\n\t"
+ "cmp $2, %0\n\t"
+ "jb 10f\n\t"
+ "movw 0*2(%1), %%dx\n\t"
+ "movw -1*2(%1, %0), %%bx\n\t"
+ "movw %%dx, 0*2(%2)\n\t"
+ "movw %%bx, -1*2(%2, %0)\n\t"
+ "jmp 11f\n\t"
+
+ /*
+ * Move data for 1 byte.
+ */
+ ".p2align 4\n\t"
+ "10:\n\t"
+ "cmp $1, %0\n\t"
+ "jb 11f\n\t"
+ "movb (%1), %%cl\n\t"
+ "movb %%cl, (%2)\n\t"
+ ".p2align 4\n\t"
+ "11:"
+ : "=&c" (d0), "=&S" (d1), "=&D" (d2),
+ "=r" (d3),"=r" (d4), "=r"(d5)
+ :"0" (n),
+ "1" (src),
+ "2" (dest)
+ :"memory");
+
+ return ret;
+
}
EXPORT_SYMBOL(memmove);
diff --git a/arch/x86/lib/memcpy_64.S b/arch/x86/lib/memcpy_64.S
index bcbcd1e0f7d5..75ef61e35e38 100644
--- a/arch/x86/lib/memcpy_64.S
+++ b/arch/x86/lib/memcpy_64.S
@@ -40,84 +40,132 @@
ENTRY(__memcpy)
ENTRY(memcpy)
CFI_STARTPROC
+ movq %rdi, %rax
/*
- * Put the number of full 64-byte blocks into %ecx.
- * Tail portion is handled at the end:
+ * Use 32bit CMP here to avoid long NOP padding.
*/
- movq %rdi, %rax
- movl %edx, %ecx
- shrl $6, %ecx
- jz .Lhandle_tail
+ cmp $0x20, %edx
+ jb .Lhandle_tail
- .p2align 4
-.Lloop_64:
/*
- * We decrement the loop index here - and the zero-flag is
- * checked at the end of the loop (instructions inbetween do
- * not change the zero flag):
+ * We check whether memory false dependece could occur,
+ * then jump to corresponding copy mode.
*/
- decl %ecx
+ cmp %dil, %sil
+ jl .Lcopy_backward
+ subl $0x20, %edx
+.Lcopy_forward_loop:
+ subq $0x20, %rdx
/*
- * Move in blocks of 4x16 bytes:
+ * Move in blocks of 4x8 bytes:
*/
- movq 0*8(%rsi), %r11
- movq 1*8(%rsi), %r8
- movq %r11, 0*8(%rdi)
- movq %r8, 1*8(%rdi)
-
- movq 2*8(%rsi), %r9
- movq 3*8(%rsi), %r10
- movq %r9, 2*8(%rdi)
- movq %r10, 3*8(%rdi)
-
- movq 4*8(%rsi), %r11
- movq 5*8(%rsi), %r8
- movq %r11, 4*8(%rdi)
- movq %r8, 5*8(%rdi)
-
- movq 6*8(%rsi), %r9
- movq 7*8(%rsi), %r10
- movq %r9, 6*8(%rdi)
- movq %r10, 7*8(%rdi)
-
- leaq 64(%rsi), %rsi
- leaq 64(%rdi), %rdi
-
- jnz .Lloop_64
+ movq 0*8(%rsi), %r8
+ movq 1*8(%rsi), %r9
+ movq 2*8(%rsi), %r10
+ movq 3*8(%rsi), %r11
+ leaq 4*8(%rsi), %rsi
+
+ movq %r8, 0*8(%rdi)
+ movq %r9, 1*8(%rdi)
+ movq %r10, 2*8(%rdi)
+ movq %r11, 3*8(%rdi)
+ leaq 4*8(%rdi), %rdi
+ jae .Lcopy_forward_loop
+ addq $0x20, %rdx
+ jmp .Lhandle_tail
+
+.Lcopy_backward:
+ /*
+ * Calculate copy position to tail.
+ */
+ addq %rdx, %rsi
+ addq %rdx, %rdi
+ subq $0x20, %rdx
+ /*
+ * At most 3 ALU operations in one cycle,
+ * so append NOPS in the same 16bytes trunk.
+ */
+ .p2align 4
+.Lcopy_backward_loop:
+ subq $0x20, %rdx
+ movq -1*8(%rsi), %r8
+ movq -2*8(%rsi), %r9
+ movq -3*8(%rsi), %r10
+ movq -4*8(%rsi), %r11
+ leaq -4*8(%rsi), %rsi
+ movq %r8, -1*8(%rdi)
+ movq %r9, -2*8(%rdi)
+ movq %r10, -3*8(%rdi)
+ movq %r11, -4*8(%rdi)
+ leaq -4*8(%rdi), %rdi
+ jae .Lcopy_backward_loop
+ /*
+ * Calculate copy position to head.
+ */
+ addq $0x20, %rdx
+ subq %rdx, %rsi
+ subq %rdx, %rdi
.Lhandle_tail:
- movl %edx, %ecx
- andl $63, %ecx
- shrl $3, %ecx
- jz .Lhandle_7
+ cmpq $16, %rdx
+ jb .Lless_16bytes
+ /*
+ * Move data from 16 bytes to 31 bytes.
+ */
+ movq 0*8(%rsi), %r8
+ movq 1*8(%rsi), %r9
+ movq -2*8(%rsi, %rdx), %r10
+ movq -1*8(%rsi, %rdx), %r11
+ movq %r8, 0*8(%rdi)
+ movq %r9, 1*8(%rdi)
+ movq %r10, -2*8(%rdi, %rdx)
+ movq %r11, -1*8(%rdi, %rdx)
+ retq
.p2align 4
-.Lloop_8:
- decl %ecx
- movq (%rsi), %r8
- movq %r8, (%rdi)
- leaq 8(%rdi), %rdi
- leaq 8(%rsi), %rsi
- jnz .Lloop_8
-
-.Lhandle_7:
- movl %edx, %ecx
- andl $7, %ecx
- jz .Lend
+.Lless_16bytes:
+ cmpq $8, %rdx
+ jb .Lless_8bytes
+ /*
+ * Move data from 8 bytes to 15 bytes.
+ */
+ movq 0*8(%rsi), %r8
+ movq -1*8(%rsi, %rdx), %r9
+ movq %r8, 0*8(%rdi)
+ movq %r9, -1*8(%rdi, %rdx)
+ retq
+ .p2align 4
+.Lless_8bytes:
+ cmpq $4, %rdx
+ jb .Lless_3bytes
+ /*
+ * Move data from 4 bytes to 7 bytes.
+ */
+ movl (%rsi), %ecx
+ movl -4(%rsi, %rdx), %r8d
+ movl %ecx, (%rdi)
+ movl %r8d, -4(%rdi, %rdx)
+ retq
.p2align 4
+.Lless_3bytes:
+ cmpl $0, %edx
+ je .Lend
+ /*
+ * Move data from 1 bytes to 3 bytes.
+ */
.Lloop_1:
movb (%rsi), %r8b
movb %r8b, (%rdi)
incq %rdi
incq %rsi
- decl %ecx
+ decl %edx
jnz .Lloop_1
.Lend:
- ret
+ retq
CFI_ENDPROC
ENDPROC(memcpy)
ENDPROC(__memcpy)
diff --git a/arch/x86/lib/memmove_64.c b/arch/x86/lib/memmove_64.c
index 0a33909bf122..6d0f0ec41b34 100644
--- a/arch/x86/lib/memmove_64.c
+++ b/arch/x86/lib/memmove_64.c
@@ -8,14 +8,185 @@
#undef memmove
void *memmove(void *dest, const void *src, size_t count)
{
- if (dest < src) {
- return memcpy(dest, src, count);
- } else {
- char *p = dest + count;
- const char *s = src + count;
- while (count--)
- *--p = *--s;
- }
- return dest;
+ unsigned long d0,d1,d2,d3,d4,d5,d6,d7;
+ char *ret;
+
+ __asm__ __volatile__(
+ /* Handle more 32bytes in loop */
+ "mov %2, %3\n\t"
+ "cmp $0x20, %0\n\t"
+ "jb 1f\n\t"
+
+ /* Decide forward/backward copy mode */
+ "cmp %2, %1\n\t"
+ "jb 2f\n\t"
+
+ /*
+ * movsq instruction have many startup latency
+ * so we handle small size by general register.
+ */
+ "cmp $680, %0\n\t"
+ "jb 3f\n\t"
+ /*
+ * movsq instruction is only good for aligned case.
+ */
+ "cmpb %%dil, %%sil\n\t"
+ "je 4f\n\t"
+ "3:\n\t"
+ "sub $0x20, %0\n\t"
+ /*
+ * We gobble 32byts forward in each loop.
+ */
+ "5:\n\t"
+ "sub $0x20, %0\n\t"
+ "movq 0*8(%1), %4\n\t"
+ "movq 1*8(%1), %5\n\t"
+ "movq 2*8(%1), %6\n\t"
+ "movq 3*8(%1), %7\n\t"
+ "leaq 4*8(%1), %1\n\t"
+
+ "movq %4, 0*8(%2)\n\t"
+ "movq %5, 1*8(%2)\n\t"
+ "movq %6, 2*8(%2)\n\t"
+ "movq %7, 3*8(%2)\n\t"
+ "leaq 4*8(%2), %2\n\t"
+ "jae 5b\n\t"
+ "addq $0x20, %0\n\t"
+ "jmp 1f\n\t"
+ /*
+ * Handle data forward by movsq.
+ */
+ ".p2align 4\n\t"
+ "4:\n\t"
+ "movq %0, %8\n\t"
+ "movq -8(%1, %0), %4\n\t"
+ "lea -8(%2, %0), %5\n\t"
+ "shrq $3, %8\n\t"
+ "rep movsq\n\t"
+ "movq %4, (%5)\n\t"
+ "jmp 13f\n\t"
+ /*
+ * Handle data backward by movsq.
+ */
+ ".p2align 4\n\t"
+ "7:\n\t"
+ "movq %0, %8\n\t"
+ "movq (%1), %4\n\t"
+ "movq %2, %5\n\t"
+ "leaq -8(%1, %0), %1\n\t"
+ "leaq -8(%2, %0), %2\n\t"
+ "shrq $3, %8\n\t"
+ "std\n\t"
+ "rep movsq\n\t"
+ "cld\n\t"
+ "movq %4, (%5)\n\t"
+ "jmp 13f\n\t"
+
+ /*
+ * Start to prepare for backward copy.
+ */
+ ".p2align 4\n\t"
+ "2:\n\t"
+ "cmp $680, %0\n\t"
+ "jb 6f \n\t"
+ "cmp %%dil, %%sil\n\t"
+ "je 7b \n\t"
+ "6:\n\t"
+ /*
+ * Calculate copy position to tail.
+ */
+ "addq %0, %1\n\t"
+ "addq %0, %2\n\t"
+ "subq $0x20, %0\n\t"
+ /*
+ * We gobble 32byts backward in each loop.
+ */
+ "8:\n\t"
+ "subq $0x20, %0\n\t"
+ "movq -1*8(%1), %4\n\t"
+ "movq -2*8(%1), %5\n\t"
+ "movq -3*8(%1), %6\n\t"
+ "movq -4*8(%1), %7\n\t"
+ "leaq -4*8(%1), %1\n\t"
+
+ "movq %4, -1*8(%2)\n\t"
+ "movq %5, -2*8(%2)\n\t"
+ "movq %6, -3*8(%2)\n\t"
+ "movq %7, -4*8(%2)\n\t"
+ "leaq -4*8(%2), %2\n\t"
+ "jae 8b\n\t"
+ /*
+ * Calculate copy position to head.
+ */
+ "addq $0x20, %0\n\t"
+ "subq %0, %1\n\t"
+ "subq %0, %2\n\t"
+ "1:\n\t"
+ "cmpq $16, %0\n\t"
+ "jb 9f\n\t"
+ /*
+ * Move data from 16 bytes to 31 bytes.
+ */
+ "movq 0*8(%1), %4\n\t"
+ "movq 1*8(%1), %5\n\t"
+ "movq -2*8(%1, %0), %6\n\t"
+ "movq -1*8(%1, %0), %7\n\t"
+ "movq %4, 0*8(%2)\n\t"
+ "movq %5, 1*8(%2)\n\t"
+ "movq %6, -2*8(%2, %0)\n\t"
+ "movq %7, -1*8(%2, %0)\n\t"
+ "jmp 13f\n\t"
+ ".p2align 4\n\t"
+ "9:\n\t"
+ "cmpq $8, %0\n\t"
+ "jb 10f\n\t"
+ /*
+ * Move data from 8 bytes to 15 bytes.
+ */
+ "movq 0*8(%1), %4\n\t"
+ "movq -1*8(%1, %0), %5\n\t"
+ "movq %4, 0*8(%2)\n\t"
+ "movq %5, -1*8(%2, %0)\n\t"
+ "jmp 13f\n\t"
+ "10:\n\t"
+ "cmpq $4, %0\n\t"
+ "jb 11f\n\t"
+ /*
+ * Move data from 4 bytes to 7 bytes.
+ */
+ "movl (%1), %4d\n\t"
+ "movl -4(%1, %0), %5d\n\t"
+ "movl %4d, (%2)\n\t"
+ "movl %5d, -4(%2, %0)\n\t"
+ "jmp 13f\n\t"
+ "11:\n\t"
+ "cmp $2, %0\n\t"
+ "jb 12f\n\t"
+ /*
+ * Move data from 2 bytes to 3 bytes.
+ */
+ "movw (%1), %4w\n\t"
+ "movw -2(%1, %0), %5w\n\t"
+ "movw %4w, (%2)\n\t"
+ "movw %5w, -2(%2, %0)\n\t"
+ "jmp 13f\n\t"
+ "12:\n\t"
+ "cmp $1, %0\n\t"
+ "jb 13f\n\t"
+ /*
+ * Move data for 1 byte.
+ */
+ "movb (%1), %4b\n\t"
+ "movb %4b, (%2)\n\t"
+ "13:\n\t"
+ : "=&d" (d0), "=&S" (d1), "=&D" (d2), "=&a" (ret) ,
+ "=r"(d3), "=r"(d4), "=r"(d5), "=r"(d6), "=&c" (d7)
+ :"0" (count),
+ "1" (src),
+ "2" (dest)
+ :"memory");
+
+ return ret;
+
}
EXPORT_SYMBOL(memmove);
diff --git a/arch/x86/mm/Makefile b/arch/x86/mm/Makefile
index a4c768397baa..55543397a8a7 100644
--- a/arch/x86/mm/Makefile
+++ b/arch/x86/mm/Makefile
@@ -26,4 +26,6 @@ obj-$(CONFIG_NUMA) += numa.o numa_$(BITS).o
obj-$(CONFIG_K8_NUMA) += k8topology_64.o
obj-$(CONFIG_ACPI_NUMA) += srat_$(BITS).o
+obj-$(CONFIG_HAVE_MEMBLOCK) += memblock.o
+
obj-$(CONFIG_MEMTEST) += memtest.o
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index 4c4508e8a204..79b0b372d2d0 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -229,7 +229,16 @@ void vmalloc_sync_all(void)
spin_lock_irqsave(&pgd_lock, flags);
list_for_each_entry(page, &pgd_list, lru) {
- if (!vmalloc_sync_one(page_address(page), address))
+ spinlock_t *pgt_lock;
+ pmd_t *ret;
+
+ pgt_lock = &pgd_page_get_mm(page)->page_table_lock;
+
+ spin_lock(pgt_lock);
+ ret = vmalloc_sync_one(page_address(page), address);
+ spin_unlock(pgt_lock);
+
+ if (!ret)
break;
}
spin_unlock_irqrestore(&pgd_lock, flags);
@@ -251,6 +260,8 @@ static noinline __kprobes int vmalloc_fault(unsigned long address)
if (!(address >= VMALLOC_START && address < VMALLOC_END))
return -1;
+ WARN_ON_ONCE(in_nmi());
+
/*
* Synchronize this task's top level page-table
* with the 'reference' page table.
@@ -326,29 +337,7 @@ out:
void vmalloc_sync_all(void)
{
- unsigned long address;
-
- for (address = VMALLOC_START & PGDIR_MASK; address <= VMALLOC_END;
- address += PGDIR_SIZE) {
-
- const pgd_t *pgd_ref = pgd_offset_k(address);
- unsigned long flags;
- struct page *page;
-
- if (pgd_none(*pgd_ref))
- continue;
-
- spin_lock_irqsave(&pgd_lock, flags);
- list_for_each_entry(page, &pgd_list, lru) {
- pgd_t *pgd;
- pgd = (pgd_t *)page_address(page) + pgd_index(address);
- if (pgd_none(*pgd))
- set_pgd(pgd, *pgd_ref);
- else
- BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref));
- }
- spin_unlock_irqrestore(&pgd_lock, flags);
- }
+ sync_global_pgds(VMALLOC_START & PGDIR_MASK, VMALLOC_END);
}
/*
@@ -369,6 +358,8 @@ static noinline __kprobes int vmalloc_fault(unsigned long address)
if (!(address >= VMALLOC_START && address < VMALLOC_END))
return -1;
+ WARN_ON_ONCE(in_nmi());
+
/*
* Copy kernel mappings over when needed. This can also
* happen within a race in page table update. In the later
@@ -894,8 +885,14 @@ spurious_fault(unsigned long error_code, unsigned long address)
if (pmd_large(*pmd))
return spurious_fault_check(error_code, (pte_t *) pmd);
+ /*
+ * Note: don't use pte_present() here, since it returns true
+ * if the _PAGE_PROTNONE bit is set. However, this aliases the
+ * _PAGE_GLOBAL bit, which for kernel pages give false positives
+ * when CONFIG_DEBUG_PAGEALLOC is used.
+ */
pte = pte_offset_kernel(pmd, address);
- if (!pte_present(*pte))
+ if (!(pte_flags(*pte) & _PAGE_PRESENT))
return 0;
ret = spurious_fault_check(error_code, pte);
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
index b278535b14aa..c0e28a13de7d 100644
--- a/arch/x86/mm/init.c
+++ b/arch/x86/mm/init.c
@@ -2,6 +2,7 @@
#include <linux/initrd.h>
#include <linux/ioport.h>
#include <linux/swap.h>
+#include <linux/memblock.h>
#include <asm/cacheflush.h>
#include <asm/e820.h>
@@ -33,6 +34,7 @@ static void __init find_early_table_space(unsigned long end, int use_pse,
int use_gbpages)
{
unsigned long puds, pmds, ptes, tables, start;
+ phys_addr_t base;
puds = (end + PUD_SIZE - 1) >> PUD_SHIFT;
tables = roundup(puds * sizeof(pud_t), PAGE_SIZE);
@@ -75,12 +77,12 @@ static void __init find_early_table_space(unsigned long end, int use_pse,
#else
start = 0x8000;
#endif
- e820_table_start = find_e820_area(start, max_pfn_mapped<<PAGE_SHIFT,
+ base = memblock_find_in_range(start, max_pfn_mapped<<PAGE_SHIFT,
tables, PAGE_SIZE);
- if (e820_table_start == -1UL)
+ if (base == MEMBLOCK_ERROR)
panic("Cannot find space for the kernel page tables");
- e820_table_start >>= PAGE_SHIFT;
+ e820_table_start = base >> PAGE_SHIFT;
e820_table_end = e820_table_start;
e820_table_top = e820_table_start + (tables >> PAGE_SHIFT);
@@ -299,7 +301,7 @@ unsigned long __init_refok init_memory_mapping(unsigned long start,
__flush_tlb_all();
if (!after_bootmem && e820_table_end > e820_table_start)
- reserve_early(e820_table_start << PAGE_SHIFT,
+ memblock_x86_reserve_range(e820_table_start << PAGE_SHIFT,
e820_table_end << PAGE_SHIFT, "PGTABLE");
if (!after_bootmem)
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c
index bca79091b9d6..0e969f9f401b 100644
--- a/arch/x86/mm/init_32.c
+++ b/arch/x86/mm/init_32.c
@@ -25,6 +25,7 @@
#include <linux/pfn.h>
#include <linux/poison.h>
#include <linux/bootmem.h>
+#include <linux/memblock.h>
#include <linux/proc_fs.h>
#include <linux/memory_hotplug.h>
#include <linux/initrd.h>
@@ -67,7 +68,7 @@ static __init void *alloc_low_page(void)
panic("alloc_low_page: ran out of memory");
adr = __va(pfn * PAGE_SIZE);
- memset(adr, 0, PAGE_SIZE);
+ clear_page(adr);
return adr;
}
@@ -422,49 +423,28 @@ static void __init add_one_highpage_init(struct page *page)
totalhigh_pages++;
}
-struct add_highpages_data {
- unsigned long start_pfn;
- unsigned long end_pfn;
-};
-
-static int __init add_highpages_work_fn(unsigned long start_pfn,
- unsigned long end_pfn, void *datax)
+void __init add_highpages_with_active_regions(int nid,
+ unsigned long start_pfn, unsigned long end_pfn)
{
- int node_pfn;
- struct page *page;
- unsigned long final_start_pfn, final_end_pfn;
- struct add_highpages_data *data;
+ struct range *range;
+ int nr_range;
+ int i;
- data = (struct add_highpages_data *)datax;
+ nr_range = __get_free_all_memory_range(&range, nid, start_pfn, end_pfn);
- final_start_pfn = max(start_pfn, data->start_pfn);
- final_end_pfn = min(end_pfn, data->end_pfn);
- if (final_start_pfn >= final_end_pfn)
- return 0;
+ for (i = 0; i < nr_range; i++) {
+ struct page *page;
+ int node_pfn;
- for (node_pfn = final_start_pfn; node_pfn < final_end_pfn;
- node_pfn++) {
- if (!pfn_valid(node_pfn))
- continue;
- page = pfn_to_page(node_pfn);
- add_one_highpage_init(page);
+ for (node_pfn = range[i].start; node_pfn < range[i].end;
+ node_pfn++) {
+ if (!pfn_valid(node_pfn))
+ continue;
+ page = pfn_to_page(node_pfn);
+ add_one_highpage_init(page);
+ }
}
-
- return 0;
-
}
-
-void __init add_highpages_with_active_regions(int nid, unsigned long start_pfn,
- unsigned long end_pfn)
-{
- struct add_highpages_data data;
-
- data.start_pfn = start_pfn;
- data.end_pfn = end_pfn;
-
- work_with_active_regions(nid, add_highpages_work_fn, &data);
-}
-
#else
static inline void permanent_kmaps_init(pgd_t *pgd_base)
{
@@ -548,48 +528,6 @@ static void __init pagetable_init(void)
permanent_kmaps_init(pgd_base);
}
-#ifdef CONFIG_ACPI_SLEEP
-/*
- * ACPI suspend needs this for resume, because things like the intel-agp
- * driver might have split up a kernel 4MB mapping.
- */
-char swsusp_pg_dir[PAGE_SIZE]
- __attribute__ ((aligned(PAGE_SIZE)));
-
-static inline void save_pg_dir(void)
-{
- memcpy(swsusp_pg_dir, swapper_pg_dir, PAGE_SIZE);
-}
-#else /* !CONFIG_ACPI_SLEEP */
-static inline void save_pg_dir(void)
-{
-}
-#endif /* !CONFIG_ACPI_SLEEP */
-
-void zap_low_mappings(bool early)
-{
- int i;
-
- /*
- * Zap initial low-memory mappings.
- *
- * Note that "pgd_clear()" doesn't do it for
- * us, because pgd_clear() is a no-op on i386.
- */
- for (i = 0; i < KERNEL_PGD_BOUNDARY; i++) {
-#ifdef CONFIG_X86_PAE
- set_pgd(swapper_pg_dir+i, __pgd(1 + __pa(empty_zero_page)));
-#else
- set_pgd(swapper_pg_dir+i, __pgd(0));
-#endif
- }
-
- if (early)
- __flush_tlb();
- else
- flush_tlb_all();
-}
-
pteval_t __supported_pte_mask __read_mostly = ~(_PAGE_NX | _PAGE_GLOBAL | _PAGE_IOMAP);
EXPORT_SYMBOL_GPL(__supported_pte_mask);
@@ -712,14 +650,14 @@ void __init initmem_init(unsigned long start_pfn, unsigned long end_pfn,
highstart_pfn = highend_pfn = max_pfn;
if (max_pfn > max_low_pfn)
highstart_pfn = max_low_pfn;
- e820_register_active_regions(0, 0, highend_pfn);
+ memblock_x86_register_active_regions(0, 0, highend_pfn);
sparse_memory_present_with_active_regions(0);
printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",
pages_to_mb(highend_pfn - highstart_pfn));
num_physpages = highend_pfn;
high_memory = (void *) __va(highstart_pfn * PAGE_SIZE - 1) + 1;
#else
- e820_register_active_regions(0, 0, max_low_pfn);
+ memblock_x86_register_active_regions(0, 0, max_low_pfn);
sparse_memory_present_with_active_regions(0);
num_physpages = max_low_pfn;
high_memory = (void *) __va(max_low_pfn * PAGE_SIZE - 1) + 1;
@@ -750,68 +688,12 @@ static void __init zone_sizes_init(void)
free_area_init_nodes(max_zone_pfns);
}
-#ifndef CONFIG_NO_BOOTMEM
-static unsigned long __init setup_node_bootmem(int nodeid,
- unsigned long start_pfn,
- unsigned long end_pfn,
- unsigned long bootmap)
-{
- unsigned long bootmap_size;
-
- /* don't touch min_low_pfn */
- bootmap_size = init_bootmem_node(NODE_DATA(nodeid),
- bootmap >> PAGE_SHIFT,
- start_pfn, end_pfn);
- printk(KERN_INFO " node %d low ram: %08lx - %08lx\n",
- nodeid, start_pfn<<PAGE_SHIFT, end_pfn<<PAGE_SHIFT);
- printk(KERN_INFO " node %d bootmap %08lx - %08lx\n",
- nodeid, bootmap, bootmap + bootmap_size);
- free_bootmem_with_active_regions(nodeid, end_pfn);
-
- return bootmap + bootmap_size;
-}
-#endif
-
void __init setup_bootmem_allocator(void)
{
-#ifndef CONFIG_NO_BOOTMEM
- int nodeid;
- unsigned long bootmap_size, bootmap;
- /*
- * Initialize the boot-time allocator (with low memory only):
- */
- bootmap_size = bootmem_bootmap_pages(max_low_pfn)<<PAGE_SHIFT;
- bootmap = find_e820_area(0, max_pfn_mapped<<PAGE_SHIFT, bootmap_size,
- PAGE_SIZE);
- if (bootmap == -1L)
- panic("Cannot find bootmem map of size %ld\n", bootmap_size);
- reserve_early(bootmap, bootmap + bootmap_size, "BOOTMAP");
-#endif
-
printk(KERN_INFO " mapped low ram: 0 - %08lx\n",
max_pfn_mapped<<PAGE_SHIFT);
printk(KERN_INFO " low ram: 0 - %08lx\n", max_low_pfn<<PAGE_SHIFT);
-#ifndef CONFIG_NO_BOOTMEM
- for_each_online_node(nodeid) {
- unsigned long start_pfn, end_pfn;
-
-#ifdef CONFIG_NEED_MULTIPLE_NODES
- start_pfn = node_start_pfn[nodeid];
- end_pfn = node_end_pfn[nodeid];
- if (start_pfn > max_low_pfn)
- continue;
- if (end_pfn > max_low_pfn)
- end_pfn = max_low_pfn;
-#else
- start_pfn = 0;
- end_pfn = max_low_pfn;
-#endif
- bootmap = setup_node_bootmem(nodeid, start_pfn, end_pfn,
- bootmap);
- }
-#endif
-
after_bootmem = 1;
}
@@ -958,9 +840,6 @@ void __init mem_init(void)
if (boot_cpu_data.wp_works_ok < 0)
test_wp_bit();
-
- save_pg_dir();
- zap_low_mappings(true);
}
#ifdef CONFIG_MEMORY_HOTPLUG
@@ -1070,8 +949,3 @@ void mark_rodata_ro(void)
}
#endif
-int __init reserve_bootmem_generic(unsigned long phys, unsigned long len,
- int flags)
-{
- return reserve_bootmem(phys, len, flags);
-}
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index 9a6674689a20..84346200e783 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -21,6 +21,7 @@
#include <linux/initrd.h>
#include <linux/pagemap.h>
#include <linux/bootmem.h>
+#include <linux/memblock.h>
#include <linux/proc_fs.h>
#include <linux/pci.h>
#include <linux/pfn.h>
@@ -52,8 +53,6 @@
#include <asm/init.h>
#include <linux/bootmem.h>
-static unsigned long dma_reserve __initdata;
-
static int __init parse_direct_gbpages_off(char *arg)
{
direct_gbpages = 0;
@@ -98,6 +97,43 @@ static int __init nonx32_setup(char *str)
__setup("noexec32=", nonx32_setup);
/*
+ * When memory was added/removed make sure all the processes MM have
+ * suitable PGD entries in the local PGD level page.
+ */
+void sync_global_pgds(unsigned long start, unsigned long end)
+{
+ unsigned long address;
+
+ for (address = start; address <= end; address += PGDIR_SIZE) {
+ const pgd_t *pgd_ref = pgd_offset_k(address);
+ unsigned long flags;
+ struct page *page;
+
+ if (pgd_none(*pgd_ref))
+ continue;
+
+ spin_lock_irqsave(&pgd_lock, flags);
+ list_for_each_entry(page, &pgd_list, lru) {
+ pgd_t *pgd;
+ spinlock_t *pgt_lock;
+
+ pgd = (pgd_t *)page_address(page) + pgd_index(address);
+ pgt_lock = &pgd_page_get_mm(page)->page_table_lock;
+ spin_lock(pgt_lock);
+
+ if (pgd_none(*pgd))
+ set_pgd(pgd, *pgd_ref);
+ else
+ BUG_ON(pgd_page_vaddr(*pgd)
+ != pgd_page_vaddr(*pgd_ref));
+
+ spin_unlock(pgt_lock);
+ }
+ spin_unlock_irqrestore(&pgd_lock, flags);
+ }
+}
+
+/*
* NOTE: This function is marked __ref because it calls __init function
* (alloc_bootmem_pages). It's safe to do it ONLY when after_bootmem == 0.
*/
@@ -293,7 +329,7 @@ static __ref void *alloc_low_page(unsigned long *phys)
panic("alloc_low_page: ran out of memory");
adr = early_memremap(pfn * PAGE_SIZE, PAGE_SIZE);
- memset(adr, 0, PAGE_SIZE);
+ clear_page(adr);
*phys = pfn * PAGE_SIZE;
return adr;
}
@@ -534,11 +570,13 @@ kernel_physical_mapping_init(unsigned long start,
unsigned long end,
unsigned long page_size_mask)
{
-
+ bool pgd_changed = false;
unsigned long next, last_map_addr = end;
+ unsigned long addr;
start = (unsigned long)__va(start);
end = (unsigned long)__va(end);
+ addr = start;
for (; start < end; start = next) {
pgd_t *pgd = pgd_offset_k(start);
@@ -563,7 +601,12 @@ kernel_physical_mapping_init(unsigned long start,
spin_lock(&init_mm.page_table_lock);
pgd_populate(&init_mm, pgd, __va(pud_phys));
spin_unlock(&init_mm.page_table_lock);
+ pgd_changed = true;
}
+
+ if (pgd_changed)
+ sync_global_pgds(addr, end);
+
__flush_tlb_all();
return last_map_addr;
@@ -573,23 +616,7 @@ kernel_physical_mapping_init(unsigned long start,
void __init initmem_init(unsigned long start_pfn, unsigned long end_pfn,
int acpi, int k8)
{
-#ifndef CONFIG_NO_BOOTMEM
- unsigned long bootmap_size, bootmap;
-
- bootmap_size = bootmem_bootmap_pages(end_pfn)<<PAGE_SHIFT;
- bootmap = find_e820_area(0, end_pfn<<PAGE_SHIFT, bootmap_size,
- PAGE_SIZE);
- if (bootmap == -1L)
- panic("Cannot find bootmem map of size %ld\n", bootmap_size);
- reserve_early(bootmap, bootmap + bootmap_size, "BOOTMAP");
- /* don't touch min_low_pfn */
- bootmap_size = init_bootmem_node(NODE_DATA(0), bootmap >> PAGE_SHIFT,
- 0, end_pfn);
- e820_register_active_regions(0, start_pfn, end_pfn);
- free_bootmem_with_active_regions(0, end_pfn);
-#else
- e820_register_active_regions(0, start_pfn, end_pfn);
-#endif
+ memblock_x86_register_active_regions(0, start_pfn, end_pfn);
}
#endif
@@ -799,52 +826,6 @@ void mark_rodata_ro(void)
#endif
-int __init reserve_bootmem_generic(unsigned long phys, unsigned long len,
- int flags)
-{
-#ifdef CONFIG_NUMA
- int nid, next_nid;
- int ret;
-#endif
- unsigned long pfn = phys >> PAGE_SHIFT;
-
- if (pfn >= max_pfn) {
- /*
- * This can happen with kdump kernels when accessing
- * firmware tables:
- */
- if (pfn < max_pfn_mapped)
- return -EFAULT;
-
- printk(KERN_ERR "reserve_bootmem: illegal reserve %lx %lu\n",
- phys, len);
- return -EFAULT;
- }
-
- /* Should check here against the e820 map to avoid double free */
-#ifdef CONFIG_NUMA
- nid = phys_to_nid(phys);
- next_nid = phys_to_nid(phys + len - 1);
- if (nid == next_nid)
- ret = reserve_bootmem_node(NODE_DATA(nid), phys, len, flags);
- else
- ret = reserve_bootmem(phys, len, flags);
-
- if (ret != 0)
- return ret;
-
-#else
- reserve_bootmem(phys, len, flags);
-#endif
-
- if (phys+len <= MAX_DMA_PFN*PAGE_SIZE) {
- dma_reserve += len / PAGE_SIZE;
- set_dma_reserve(dma_reserve);
- }
-
- return 0;
-}
-
int kern_addr_valid(unsigned long addr)
{
unsigned long above = ((long)addr) >> __VIRTUAL_MASK_SHIFT;
@@ -1003,6 +984,7 @@ vmemmap_populate(struct page *start_page, unsigned long size, int node)
}
}
+ sync_global_pgds((unsigned long)start_page, end);
return 0;
}
diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index 3ba6e0608c55..0369843511dc 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -362,6 +362,11 @@ static inline pte_t * __init early_ioremap_pte(unsigned long addr)
return &bm_pte[pte_index(addr)];
}
+bool __init is_early_ioremap_ptep(pte_t *ptep)
+{
+ return ptep >= &bm_pte[0] && ptep < &bm_pte[PAGE_SIZE/sizeof(pte_t)];
+}
+
static unsigned long slot_virt[FIX_BTMAPS_SLOTS] __initdata;
void __init early_ioremap_init(void)
diff --git a/arch/x86/mm/k8topology_64.c b/arch/x86/mm/k8topology_64.c
index 970ed579d4e4..804a3b6c6e14 100644
--- a/arch/x86/mm/k8topology_64.c
+++ b/arch/x86/mm/k8topology_64.c
@@ -11,6 +11,8 @@
#include <linux/string.h>
#include <linux/module.h>
#include <linux/nodemask.h>
+#include <linux/memblock.h>
+
#include <asm/io.h>
#include <linux/pci_ids.h>
#include <linux/acpi.h>
@@ -22,7 +24,7 @@
#include <asm/numa.h>
#include <asm/mpspec.h>
#include <asm/apic.h>
-#include <asm/k8.h>
+#include <asm/amd_nb.h>
static struct bootnode __initdata nodes[8];
static nodemask_t __initdata nodes_parsed = NODE_MASK_NONE;
@@ -54,8 +56,8 @@ static __init int find_northbridge(void)
static __init void early_get_boot_cpu_id(void)
{
/*
- * need to get boot_cpu_id so can use that to create apicid_to_node
- * in k8_scan_nodes()
+ * need to get the APIC ID of the BSP so can use that to
+ * create apicid_to_node in k8_scan_nodes()
*/
#ifdef CONFIG_X86_MPPARSE
/*
@@ -212,7 +214,7 @@ int __init k8_scan_nodes(void)
bits = boot_cpu_data.x86_coreid_bits;
cores = (1<<bits);
apicid_base = 0;
- /* need to get boot_cpu_id early for system with apicid lifting */
+ /* get the APIC ID of the BSP early for systems with apicid lifting */
early_get_boot_cpu_id();
if (boot_cpu_physical_apicid > 0) {
pr_info("BSP APIC ID: %02x\n", boot_cpu_physical_apicid);
@@ -222,7 +224,7 @@ int __init k8_scan_nodes(void)
for_each_node_mask(i, node_possible_map) {
int j;
- e820_register_active_regions(i,
+ memblock_x86_register_active_regions(i,
nodes[i].start >> PAGE_SHIFT,
nodes[i].end >> PAGE_SHIFT);
for (j = apicid_base; j < cores + apicid_base; j++)
diff --git a/arch/x86/mm/kmemcheck/kmemcheck.c b/arch/x86/mm/kmemcheck/kmemcheck.c
index b3b531a4f8e5..d87dd6d042d6 100644
--- a/arch/x86/mm/kmemcheck/kmemcheck.c
+++ b/arch/x86/mm/kmemcheck/kmemcheck.c
@@ -631,6 +631,8 @@ bool kmemcheck_fault(struct pt_regs *regs, unsigned long address,
if (!pte)
return false;
+ WARN_ON_ONCE(in_nmi());
+
if (error_code & 2)
kmemcheck_access(regs, address, KMEMCHECK_WRITE);
else
diff --git a/arch/x86/mm/kmemcheck/opcode.c b/arch/x86/mm/kmemcheck/opcode.c
index 63c19e27aa6f..324aa3f07237 100644
--- a/arch/x86/mm/kmemcheck/opcode.c
+++ b/arch/x86/mm/kmemcheck/opcode.c
@@ -9,7 +9,7 @@ static bool opcode_is_prefix(uint8_t b)
b == 0xf0 || b == 0xf2 || b == 0xf3
/* Group 2 */
|| b == 0x2e || b == 0x36 || b == 0x3e || b == 0x26
- || b == 0x64 || b == 0x65 || b == 0x2e || b == 0x3e
+ || b == 0x64 || b == 0x65
/* Group 3 */
|| b == 0x66
/* Group 4 */
diff --git a/arch/x86/mm/memblock.c b/arch/x86/mm/memblock.c
new file mode 100644
index 000000000000..aa1169392b83
--- /dev/null
+++ b/arch/x86/mm/memblock.c
@@ -0,0 +1,348 @@
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/bitops.h>
+#include <linux/memblock.h>
+#include <linux/bootmem.h>
+#include <linux/mm.h>
+#include <linux/range.h>
+
+/* Check for already reserved areas */
+static bool __init check_with_memblock_reserved_size(u64 *addrp, u64 *sizep, u64 align)
+{
+ struct memblock_region *r;
+ u64 addr = *addrp, last;
+ u64 size = *sizep;
+ bool changed = false;
+
+again:
+ last = addr + size;
+ for_each_memblock(reserved, r) {
+ if (last > r->base && addr < r->base) {
+ size = r->base - addr;
+ changed = true;
+ goto again;
+ }
+ if (last > (r->base + r->size) && addr < (r->base + r->size)) {
+ addr = round_up(r->base + r->size, align);
+ size = last - addr;
+ changed = true;
+ goto again;
+ }
+ if (last <= (r->base + r->size) && addr >= r->base) {
+ *sizep = 0;
+ return false;
+ }
+ }
+ if (changed) {
+ *addrp = addr;
+ *sizep = size;
+ }
+ return changed;
+}
+
+/*
+ * Find next free range after start, and size is returned in *sizep
+ */
+u64 __init memblock_x86_find_in_range_size(u64 start, u64 *sizep, u64 align)
+{
+ struct memblock_region *r;
+
+ for_each_memblock(memory, r) {
+ u64 ei_start = r->base;
+ u64 ei_last = ei_start + r->size;
+ u64 addr;
+
+ addr = round_up(ei_start, align);
+ if (addr < start)
+ addr = round_up(start, align);
+ if (addr >= ei_last)
+ continue;
+ *sizep = ei_last - addr;
+ while (check_with_memblock_reserved_size(&addr, sizep, align))
+ ;
+
+ if (*sizep)
+ return addr;
+ }
+
+ return MEMBLOCK_ERROR;
+}
+
+static __init struct range *find_range_array(int count)
+{
+ u64 end, size, mem;
+ struct range *range;
+
+ size = sizeof(struct range) * count;
+ end = memblock.current_limit;
+
+ mem = memblock_find_in_range(0, end, size, sizeof(struct range));
+ if (mem == MEMBLOCK_ERROR)
+ panic("can not find more space for range array");
+
+ /*
+ * This range is tempoaray, so don't reserve it, it will not be
+ * overlapped because We will not alloccate new buffer before
+ * We discard this one
+ */
+ range = __va(mem);
+ memset(range, 0, size);
+
+ return range;
+}
+
+static void __init memblock_x86_subtract_reserved(struct range *range, int az)
+{
+ u64 final_start, final_end;
+ struct memblock_region *r;
+
+ /* Take out region array itself at first*/
+ memblock_free_reserved_regions();
+
+ memblock_dbg("Subtract (%ld early reservations)\n", memblock.reserved.cnt);
+
+ for_each_memblock(reserved, r) {
+ memblock_dbg(" [%010llx-%010llx]\n", (u64)r->base, (u64)r->base + r->size - 1);
+ final_start = PFN_DOWN(r->base);
+ final_end = PFN_UP(r->base + r->size);
+ if (final_start >= final_end)
+ continue;
+ subtract_range(range, az, final_start, final_end);
+ }
+
+ /* Put region array back ? */
+ memblock_reserve_reserved_regions();
+}
+
+struct count_data {
+ int nr;
+};
+
+static int __init count_work_fn(unsigned long start_pfn,
+ unsigned long end_pfn, void *datax)
+{
+ struct count_data *data = datax;
+
+ data->nr++;
+
+ return 0;
+}
+
+static int __init count_early_node_map(int nodeid)
+{
+ struct count_data data;
+
+ data.nr = 0;
+ work_with_active_regions(nodeid, count_work_fn, &data);
+
+ return data.nr;
+}
+
+int __init __get_free_all_memory_range(struct range **rangep, int nodeid,
+ unsigned long start_pfn, unsigned long end_pfn)
+{
+ int count;
+ struct range *range;
+ int nr_range;
+
+ count = (memblock.reserved.cnt + count_early_node_map(nodeid)) * 2;
+
+ range = find_range_array(count);
+ nr_range = 0;
+
+ /*
+ * Use early_node_map[] and memblock.reserved.region to get range array
+ * at first
+ */
+ nr_range = add_from_early_node_map(range, count, nr_range, nodeid);
+ subtract_range(range, count, 0, start_pfn);
+ subtract_range(range, count, end_pfn, -1ULL);
+
+ memblock_x86_subtract_reserved(range, count);
+ nr_range = clean_sort_range(range, count);
+
+ *rangep = range;
+ return nr_range;
+}
+
+int __init get_free_all_memory_range(struct range **rangep, int nodeid)
+{
+ unsigned long end_pfn = -1UL;
+
+#ifdef CONFIG_X86_32
+ end_pfn = max_low_pfn;
+#endif
+ return __get_free_all_memory_range(rangep, nodeid, 0, end_pfn);
+}
+
+static u64 __init __memblock_x86_memory_in_range(u64 addr, u64 limit, bool get_free)
+{
+ int i, count;
+ struct range *range;
+ int nr_range;
+ u64 final_start, final_end;
+ u64 free_size;
+ struct memblock_region *r;
+
+ count = (memblock.reserved.cnt + memblock.memory.cnt) * 2;
+
+ range = find_range_array(count);
+ nr_range = 0;
+
+ addr = PFN_UP(addr);
+ limit = PFN_DOWN(limit);
+
+ for_each_memblock(memory, r) {
+ final_start = PFN_UP(r->base);
+ final_end = PFN_DOWN(r->base + r->size);
+ if (final_start >= final_end)
+ continue;
+ if (final_start >= limit || final_end <= addr)
+ continue;
+
+ nr_range = add_range(range, count, nr_range, final_start, final_end);
+ }
+ subtract_range(range, count, 0, addr);
+ subtract_range(range, count, limit, -1ULL);
+
+ /* Subtract memblock.reserved.region in range ? */
+ if (!get_free)
+ goto sort_and_count_them;
+ for_each_memblock(reserved, r) {
+ final_start = PFN_DOWN(r->base);
+ final_end = PFN_UP(r->base + r->size);
+ if (final_start >= final_end)
+ continue;
+ if (final_start >= limit || final_end <= addr)
+ continue;
+
+ subtract_range(range, count, final_start, final_end);
+ }
+
+sort_and_count_them:
+ nr_range = clean_sort_range(range, count);
+
+ free_size = 0;
+ for (i = 0; i < nr_range; i++)
+ free_size += range[i].end - range[i].start;
+
+ return free_size << PAGE_SHIFT;
+}
+
+u64 __init memblock_x86_free_memory_in_range(u64 addr, u64 limit)
+{
+ return __memblock_x86_memory_in_range(addr, limit, true);
+}
+
+u64 __init memblock_x86_memory_in_range(u64 addr, u64 limit)
+{
+ return __memblock_x86_memory_in_range(addr, limit, false);
+}
+
+void __init memblock_x86_reserve_range(u64 start, u64 end, char *name)
+{
+ if (start == end)
+ return;
+
+ if (WARN_ONCE(start > end, "memblock_x86_reserve_range: wrong range [%#llx, %#llx)\n", start, end))
+ return;
+
+ memblock_dbg(" memblock_x86_reserve_range: [%#010llx-%#010llx] %16s\n", start, end - 1, name);
+
+ memblock_reserve(start, end - start);
+}
+
+void __init memblock_x86_free_range(u64 start, u64 end)
+{
+ if (start == end)
+ return;
+
+ if (WARN_ONCE(start > end, "memblock_x86_free_range: wrong range [%#llx, %#llx)\n", start, end))
+ return;
+
+ memblock_dbg(" memblock_x86_free_range: [%#010llx-%#010llx]\n", start, end - 1);
+
+ memblock_free(start, end - start);
+}
+
+/*
+ * Need to call this function after memblock_x86_register_active_regions,
+ * so early_node_map[] is filled already.
+ */
+u64 __init memblock_x86_find_in_range_node(int nid, u64 start, u64 end, u64 size, u64 align)
+{
+ u64 addr;
+ addr = find_memory_core_early(nid, size, align, start, end);
+ if (addr != MEMBLOCK_ERROR)
+ return addr;
+
+ /* Fallback, should already have start end within node range */
+ return memblock_find_in_range(start, end, size, align);
+}
+
+/*
+ * Finds an active region in the address range from start_pfn to last_pfn and
+ * returns its range in ei_startpfn and ei_endpfn for the memblock entry.
+ */
+static int __init memblock_x86_find_active_region(const struct memblock_region *ei,
+ unsigned long start_pfn,
+ unsigned long last_pfn,
+ unsigned long *ei_startpfn,
+ unsigned long *ei_endpfn)
+{
+ u64 align = PAGE_SIZE;
+
+ *ei_startpfn = round_up(ei->base, align) >> PAGE_SHIFT;
+ *ei_endpfn = round_down(ei->base + ei->size, align) >> PAGE_SHIFT;
+
+ /* Skip map entries smaller than a page */
+ if (*ei_startpfn >= *ei_endpfn)
+ return 0;
+
+ /* Skip if map is outside the node */
+ if (*ei_endpfn <= start_pfn || *ei_startpfn >= last_pfn)
+ return 0;
+
+ /* Check for overlaps */
+ if (*ei_startpfn < start_pfn)
+ *ei_startpfn = start_pfn;
+ if (*ei_endpfn > last_pfn)
+ *ei_endpfn = last_pfn;
+
+ return 1;
+}
+
+/* Walk the memblock.memory map and register active regions within a node */
+void __init memblock_x86_register_active_regions(int nid, unsigned long start_pfn,
+ unsigned long last_pfn)
+{
+ unsigned long ei_startpfn;
+ unsigned long ei_endpfn;
+ struct memblock_region *r;
+
+ for_each_memblock(memory, r)
+ if (memblock_x86_find_active_region(r, start_pfn, last_pfn,
+ &ei_startpfn, &ei_endpfn))
+ add_active_range(nid, ei_startpfn, ei_endpfn);
+}
+
+/*
+ * Find the hole size (in bytes) in the memory range.
+ * @start: starting address of the memory range to scan
+ * @end: ending address of the memory range to scan
+ */
+u64 __init memblock_x86_hole_size(u64 start, u64 end)
+{
+ unsigned long start_pfn = start >> PAGE_SHIFT;
+ unsigned long last_pfn = end >> PAGE_SHIFT;
+ unsigned long ei_startpfn, ei_endpfn, ram = 0;
+ struct memblock_region *r;
+
+ for_each_memblock(memory, r)
+ if (memblock_x86_find_active_region(r, start_pfn, last_pfn,
+ &ei_startpfn, &ei_endpfn))
+ ram += ei_endpfn - ei_startpfn;
+
+ return end - start - ((u64)ram << PAGE_SHIFT);
+}
diff --git a/arch/x86/mm/memtest.c b/arch/x86/mm/memtest.c
index 18d244f70205..92faf3a1c53e 100644
--- a/arch/x86/mm/memtest.c
+++ b/arch/x86/mm/memtest.c
@@ -6,8 +6,7 @@
#include <linux/smp.h>
#include <linux/init.h>
#include <linux/pfn.h>
-
-#include <asm/e820.h>
+#include <linux/memblock.h>
static u64 patterns[] __initdata = {
0,
@@ -35,7 +34,7 @@ static void __init reserve_bad_mem(u64 pattern, u64 start_bad, u64 end_bad)
(unsigned long long) pattern,
(unsigned long long) start_bad,
(unsigned long long) end_bad);
- reserve_early(start_bad, end_bad, "BAD RAM");
+ memblock_x86_reserve_range(start_bad, end_bad, "BAD RAM");
}
static void __init memtest(u64 pattern, u64 start_phys, u64 size)
@@ -74,7 +73,7 @@ static void __init do_one_pass(u64 pattern, u64 start, u64 end)
u64 size = 0;
while (start < end) {
- start = find_e820_area_size(start, &size, 1);
+ start = memblock_x86_find_in_range_size(start, &size, 1);
/* done ? */
if (start >= end)
diff --git a/arch/x86/mm/numa_32.c b/arch/x86/mm/numa_32.c
index 809baaaf48b1..84a3e4c9f277 100644
--- a/arch/x86/mm/numa_32.c
+++ b/arch/x86/mm/numa_32.c
@@ -24,6 +24,7 @@
#include <linux/mm.h>
#include <linux/bootmem.h>
+#include <linux/memblock.h>
#include <linux/mmzone.h>
#include <linux/highmem.h>
#include <linux/initrd.h>
@@ -120,7 +121,7 @@ int __init get_memcfg_numa_flat(void)
node_start_pfn[0] = 0;
node_end_pfn[0] = max_pfn;
- e820_register_active_regions(0, 0, max_pfn);
+ memblock_x86_register_active_regions(0, 0, max_pfn);
memory_present(0, 0, max_pfn);
node_remap_size[0] = node_memmap_size_bytes(0, 0, max_pfn);
@@ -161,14 +162,14 @@ static void __init allocate_pgdat(int nid)
NODE_DATA(nid) = (pg_data_t *)node_remap_start_vaddr[nid];
else {
unsigned long pgdat_phys;
- pgdat_phys = find_e820_area(min_low_pfn<<PAGE_SHIFT,
+ pgdat_phys = memblock_find_in_range(min_low_pfn<<PAGE_SHIFT,
max_pfn_mapped<<PAGE_SHIFT,
sizeof(pg_data_t),
PAGE_SIZE);
NODE_DATA(nid) = (pg_data_t *)(pfn_to_kaddr(pgdat_phys>>PAGE_SHIFT));
memset(buf, 0, sizeof(buf));
sprintf(buf, "NODE_DATA %d", nid);
- reserve_early(pgdat_phys, pgdat_phys + sizeof(pg_data_t), buf);
+ memblock_x86_reserve_range(pgdat_phys, pgdat_phys + sizeof(pg_data_t), buf);
}
printk(KERN_DEBUG "allocate_pgdat: node %d NODE_DATA %08lx\n",
nid, (unsigned long)NODE_DATA(nid));
@@ -291,15 +292,15 @@ static __init unsigned long calculate_numa_remap_pages(void)
PTRS_PER_PTE);
node_kva_target <<= PAGE_SHIFT;
do {
- node_kva_final = find_e820_area(node_kva_target,
+ node_kva_final = memblock_find_in_range(node_kva_target,
((u64)node_end_pfn[nid])<<PAGE_SHIFT,
((u64)size)<<PAGE_SHIFT,
LARGE_PAGE_BYTES);
node_kva_target -= LARGE_PAGE_BYTES;
- } while (node_kva_final == -1ULL &&
+ } while (node_kva_final == MEMBLOCK_ERROR &&
(node_kva_target>>PAGE_SHIFT) > (node_start_pfn[nid]));
- if (node_kva_final == -1ULL)
+ if (node_kva_final == MEMBLOCK_ERROR)
panic("Can not get kva ram\n");
node_remap_size[nid] = size;
@@ -318,15 +319,13 @@ static __init unsigned long calculate_numa_remap_pages(void)
* but we could have some hole in high memory, and it will only
* check page_is_ram(pfn) && !page_is_reserved_early(pfn) to decide
* to use it as free.
- * So reserve_early here, hope we don't run out of that array
+ * So memblock_x86_reserve_range here, hope we don't run out of that array
*/
- reserve_early(node_kva_final,
+ memblock_x86_reserve_range(node_kva_final,
node_kva_final+(((u64)size)<<PAGE_SHIFT),
"KVA RAM");
node_remap_start_pfn[nid] = node_kva_final>>PAGE_SHIFT;
- remove_active_range(nid, node_remap_start_pfn[nid],
- node_remap_start_pfn[nid] + size);
}
printk(KERN_INFO "Reserving total of %lx pages for numa KVA remap\n",
reserve_pages);
@@ -367,14 +366,14 @@ void __init initmem_init(unsigned long start_pfn, unsigned long end_pfn,
kva_target_pfn = round_down(max_low_pfn - kva_pages, PTRS_PER_PTE);
do {
- kva_start_pfn = find_e820_area(kva_target_pfn<<PAGE_SHIFT,
+ kva_start_pfn = memblock_find_in_range(kva_target_pfn<<PAGE_SHIFT,
max_low_pfn<<PAGE_SHIFT,
kva_pages<<PAGE_SHIFT,
PTRS_PER_PTE<<PAGE_SHIFT) >> PAGE_SHIFT;
kva_target_pfn -= PTRS_PER_PTE;
- } while (kva_start_pfn == -1UL && kva_target_pfn > min_low_pfn);
+ } while (kva_start_pfn == MEMBLOCK_ERROR && kva_target_pfn > min_low_pfn);
- if (kva_start_pfn == -1UL)
+ if (kva_start_pfn == MEMBLOCK_ERROR)
panic("Can not get kva space\n");
printk(KERN_INFO "kva_start_pfn ~ %lx max_low_pfn ~ %lx\n",
@@ -382,7 +381,7 @@ void __init initmem_init(unsigned long start_pfn, unsigned long end_pfn,
printk(KERN_INFO "max_pfn = %lx\n", max_pfn);
/* avoid clash with initrd */
- reserve_early(kva_start_pfn<<PAGE_SHIFT,
+ memblock_x86_reserve_range(kva_start_pfn<<PAGE_SHIFT,
(kva_start_pfn + kva_pages)<<PAGE_SHIFT,
"KVA PG");
#ifdef CONFIG_HIGHMEM
@@ -419,9 +418,6 @@ void __init initmem_init(unsigned long start_pfn, unsigned long end_pfn,
for_each_online_node(nid) {
memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));
NODE_DATA(nid)->node_id = nid;
-#ifndef CONFIG_NO_BOOTMEM
- NODE_DATA(nid)->bdata = &bootmem_node_data[nid];
-#endif
}
setup_bootmem_allocator();
diff --git a/arch/x86/mm/numa_64.c b/arch/x86/mm/numa_64.c
index a7bcc23ef96c..60f498511dd6 100644
--- a/arch/x86/mm/numa_64.c
+++ b/arch/x86/mm/numa_64.c
@@ -7,6 +7,7 @@
#include <linux/string.h>
#include <linux/init.h>
#include <linux/bootmem.h>
+#include <linux/memblock.h>
#include <linux/mmzone.h>
#include <linux/ctype.h>
#include <linux/module.h>
@@ -18,7 +19,7 @@
#include <asm/dma.h>
#include <asm/numa.h>
#include <asm/acpi.h>
-#include <asm/k8.h>
+#include <asm/amd_nb.h>
struct pglist_data *node_data[MAX_NUMNODES] __read_mostly;
EXPORT_SYMBOL(node_data);
@@ -86,16 +87,16 @@ static int __init allocate_cachealigned_memnodemap(void)
addr = 0x8000;
nodemap_size = roundup(sizeof(s16) * memnodemapsize, L1_CACHE_BYTES);
- nodemap_addr = find_e820_area(addr, max_pfn<<PAGE_SHIFT,
+ nodemap_addr = memblock_find_in_range(addr, max_pfn<<PAGE_SHIFT,
nodemap_size, L1_CACHE_BYTES);
- if (nodemap_addr == -1UL) {
+ if (nodemap_addr == MEMBLOCK_ERROR) {
printk(KERN_ERR
"NUMA: Unable to allocate Memory to Node hash map\n");
nodemap_addr = nodemap_size = 0;
return -1;
}
memnodemap = phys_to_virt(nodemap_addr);
- reserve_early(nodemap_addr, nodemap_addr + nodemap_size, "MEMNODEMAP");
+ memblock_x86_reserve_range(nodemap_addr, nodemap_addr + nodemap_size, "MEMNODEMAP");
printk(KERN_DEBUG "NUMA: Allocated memnodemap from %lx - %lx\n",
nodemap_addr, nodemap_addr + nodemap_size);
@@ -171,8 +172,8 @@ static void * __init early_node_mem(int nodeid, unsigned long start,
if (start < (MAX_DMA32_PFN<<PAGE_SHIFT) &&
end > (MAX_DMA32_PFN<<PAGE_SHIFT))
start = MAX_DMA32_PFN<<PAGE_SHIFT;
- mem = find_e820_area(start, end, size, align);
- if (mem != -1L)
+ mem = memblock_x86_find_in_range_node(nodeid, start, end, size, align);
+ if (mem != MEMBLOCK_ERROR)
return __va(mem);
/* extend the search scope */
@@ -181,8 +182,8 @@ static void * __init early_node_mem(int nodeid, unsigned long start,
start = MAX_DMA32_PFN<<PAGE_SHIFT;
else
start = MAX_DMA_PFN<<PAGE_SHIFT;
- mem = find_e820_area(start, end, size, align);
- if (mem != -1L)
+ mem = memblock_x86_find_in_range_node(nodeid, start, end, size, align);
+ if (mem != MEMBLOCK_ERROR)
return __va(mem);
printk(KERN_ERR "Cannot find %lu bytes in node %d\n",
@@ -198,10 +199,6 @@ setup_node_bootmem(int nodeid, unsigned long start, unsigned long end)
unsigned long start_pfn, last_pfn, nodedata_phys;
const int pgdat_size = roundup(sizeof(pg_data_t), PAGE_SIZE);
int nid;
-#ifndef CONFIG_NO_BOOTMEM
- unsigned long bootmap_start, bootmap_pages, bootmap_size;
- void *bootmap;
-#endif
if (!end)
return;
@@ -226,7 +223,7 @@ setup_node_bootmem(int nodeid, unsigned long start, unsigned long end)
if (node_data[nodeid] == NULL)
return;
nodedata_phys = __pa(node_data[nodeid]);
- reserve_early(nodedata_phys, nodedata_phys + pgdat_size, "NODE_DATA");
+ memblock_x86_reserve_range(nodedata_phys, nodedata_phys + pgdat_size, "NODE_DATA");
printk(KERN_INFO " NODE_DATA [%016lx - %016lx]\n", nodedata_phys,
nodedata_phys + pgdat_size - 1);
nid = phys_to_nid(nodedata_phys);
@@ -238,47 +235,6 @@ setup_node_bootmem(int nodeid, unsigned long start, unsigned long end)
NODE_DATA(nodeid)->node_start_pfn = start_pfn;
NODE_DATA(nodeid)->node_spanned_pages = last_pfn - start_pfn;
-#ifndef CONFIG_NO_BOOTMEM
- NODE_DATA(nodeid)->bdata = &bootmem_node_data[nodeid];
-
- /*
- * Find a place for the bootmem map
- * nodedata_phys could be on other nodes by alloc_bootmem,
- * so need to sure bootmap_start not to be small, otherwise
- * early_node_mem will get that with find_e820_area instead
- * of alloc_bootmem, that could clash with reserved range
- */
- bootmap_pages = bootmem_bootmap_pages(last_pfn - start_pfn);
- bootmap_start = roundup(nodedata_phys + pgdat_size, PAGE_SIZE);
- /*
- * SMP_CACHE_BYTES could be enough, but init_bootmem_node like
- * to use that to align to PAGE_SIZE
- */
- bootmap = early_node_mem(nodeid, bootmap_start, end,
- bootmap_pages<<PAGE_SHIFT, PAGE_SIZE);
- if (bootmap == NULL) {
- free_early(nodedata_phys, nodedata_phys + pgdat_size);
- node_data[nodeid] = NULL;
- return;
- }
- bootmap_start = __pa(bootmap);
- reserve_early(bootmap_start, bootmap_start+(bootmap_pages<<PAGE_SHIFT),
- "BOOTMAP");
-
- bootmap_size = init_bootmem_node(NODE_DATA(nodeid),
- bootmap_start >> PAGE_SHIFT,
- start_pfn, last_pfn);
-
- printk(KERN_INFO " bootmap [%016lx - %016lx] pages %lx\n",
- bootmap_start, bootmap_start + bootmap_size - 1,
- bootmap_pages);
- nid = phys_to_nid(bootmap_start);
- if (nid != nodeid)
- printk(KERN_INFO " bootmap(%d) on node %d\n", nodeid, nid);
-
- free_bootmem_with_active_regions(nodeid, end);
-#endif
-
node_set_online(nodeid);
}
@@ -416,7 +372,7 @@ static int __init split_nodes_interleave(u64 addr, u64 max_addr,
nr_nodes = MAX_NUMNODES;
}
- size = (max_addr - addr - e820_hole_size(addr, max_addr)) / nr_nodes;
+ size = (max_addr - addr - memblock_x86_hole_size(addr, max_addr)) / nr_nodes;
/*
* Calculate the number of big nodes that can be allocated as a result
* of consolidating the remainder.
@@ -452,7 +408,7 @@ static int __init split_nodes_interleave(u64 addr, u64 max_addr,
* non-reserved memory is less than the per-node size.
*/
while (end - physnodes[i].start -
- e820_hole_size(physnodes[i].start, end) < size) {
+ memblock_x86_hole_size(physnodes[i].start, end) < size) {
end += FAKE_NODE_MIN_SIZE;
if (end > physnodes[i].end) {
end = physnodes[i].end;
@@ -466,7 +422,7 @@ static int __init split_nodes_interleave(u64 addr, u64 max_addr,
* this one must extend to the boundary.
*/
if (end < dma32_end && dma32_end - end -
- e820_hole_size(end, dma32_end) < FAKE_NODE_MIN_SIZE)
+ memblock_x86_hole_size(end, dma32_end) < FAKE_NODE_MIN_SIZE)
end = dma32_end;
/*
@@ -475,7 +431,7 @@ static int __init split_nodes_interleave(u64 addr, u64 max_addr,
* physical node.
*/
if (physnodes[i].end - end -
- e820_hole_size(end, physnodes[i].end) < size)
+ memblock_x86_hole_size(end, physnodes[i].end) < size)
end = physnodes[i].end;
/*
@@ -503,7 +459,7 @@ static u64 __init find_end_of_node(u64 start, u64 max_addr, u64 size)
{
u64 end = start + size;
- while (end - start - e820_hole_size(start, end) < size) {
+ while (end - start - memblock_x86_hole_size(start, end) < size) {
end += FAKE_NODE_MIN_SIZE;
if (end > max_addr) {
end = max_addr;
@@ -532,7 +488,7 @@ static int __init split_nodes_size_interleave(u64 addr, u64 max_addr, u64 size)
* creates a uniform distribution of node sizes across the entire
* machine (but not necessarily over physical nodes).
*/
- min_size = (max_addr - addr - e820_hole_size(addr, max_addr)) /
+ min_size = (max_addr - addr - memblock_x86_hole_size(addr, max_addr)) /
MAX_NUMNODES;
min_size = max(min_size, FAKE_NODE_MIN_SIZE);
if ((min_size & FAKE_NODE_MIN_HASH_MASK) < min_size)
@@ -565,7 +521,7 @@ static int __init split_nodes_size_interleave(u64 addr, u64 max_addr, u64 size)
* this one must extend to the boundary.
*/
if (end < dma32_end && dma32_end - end -
- e820_hole_size(end, dma32_end) < FAKE_NODE_MIN_SIZE)
+ memblock_x86_hole_size(end, dma32_end) < FAKE_NODE_MIN_SIZE)
end = dma32_end;
/*
@@ -574,7 +530,7 @@ static int __init split_nodes_size_interleave(u64 addr, u64 max_addr, u64 size)
* physical node.
*/
if (physnodes[i].end - end -
- e820_hole_size(end, physnodes[i].end) < size)
+ memblock_x86_hole_size(end, physnodes[i].end) < size)
end = physnodes[i].end;
/*
@@ -638,7 +594,7 @@ static int __init numa_emulation(unsigned long start_pfn,
*/
remove_all_active_ranges();
for_each_node_mask(i, node_possible_map) {
- e820_register_active_regions(i, nodes[i].start >> PAGE_SHIFT,
+ memblock_x86_register_active_regions(i, nodes[i].start >> PAGE_SHIFT,
nodes[i].end >> PAGE_SHIFT);
setup_node_bootmem(i, nodes[i].start, nodes[i].end);
}
@@ -691,7 +647,7 @@ void __init initmem_init(unsigned long start_pfn, unsigned long last_pfn,
node_set(0, node_possible_map);
for (i = 0; i < nr_cpu_ids; i++)
numa_set_node(i, 0);
- e820_register_active_regions(0, start_pfn, last_pfn);
+ memblock_x86_register_active_regions(0, start_pfn, last_pfn);
setup_node_bootmem(0, start_pfn << PAGE_SHIFT, last_pfn << PAGE_SHIFT);
}
@@ -703,9 +659,7 @@ unsigned long __init numa_free_all_bootmem(void)
for_each_online_node(i)
pages += free_all_bootmem_node(NODE_DATA(i));
-#ifdef CONFIG_NO_BOOTMEM
pages += free_all_memory_core_early(MAX_NUMNODES);
-#endif
return pages;
}
diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c
index 5c4ee422590e..8be8c7d7bc89 100644
--- a/arch/x86/mm/pgtable.c
+++ b/arch/x86/mm/pgtable.c
@@ -87,7 +87,19 @@ static inline void pgd_list_del(pgd_t *pgd)
#define UNSHARED_PTRS_PER_PGD \
(SHARED_KERNEL_PMD ? KERNEL_PGD_BOUNDARY : PTRS_PER_PGD)
-static void pgd_ctor(pgd_t *pgd)
+
+static void pgd_set_mm(pgd_t *pgd, struct mm_struct *mm)
+{
+ BUILD_BUG_ON(sizeof(virt_to_page(pgd)->index) < sizeof(mm));
+ virt_to_page(pgd)->index = (pgoff_t)mm;
+}
+
+struct mm_struct *pgd_page_get_mm(struct page *page)
+{
+ return (struct mm_struct *)page->index;
+}
+
+static void pgd_ctor(struct mm_struct *mm, pgd_t *pgd)
{
/* If the pgd points to a shared pagetable level (either the
ptes in non-PAE, or shared PMD in PAE), then just copy the
@@ -98,15 +110,13 @@ static void pgd_ctor(pgd_t *pgd)
clone_pgd_range(pgd + KERNEL_PGD_BOUNDARY,
swapper_pg_dir + KERNEL_PGD_BOUNDARY,
KERNEL_PGD_PTRS);
- paravirt_alloc_pmd_clone(__pa(pgd) >> PAGE_SHIFT,
- __pa(swapper_pg_dir) >> PAGE_SHIFT,
- KERNEL_PGD_BOUNDARY,
- KERNEL_PGD_PTRS);
}
/* list required to sync kernel mapping updates */
- if (!SHARED_KERNEL_PMD)
+ if (!SHARED_KERNEL_PMD) {
+ pgd_set_mm(pgd, mm);
pgd_list_add(pgd);
+ }
}
static void pgd_dtor(pgd_t *pgd)
@@ -272,7 +282,7 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
*/
spin_lock_irqsave(&pgd_lock, flags);
- pgd_ctor(pgd);
+ pgd_ctor(mm, pgd);
pgd_prepopulate_pmd(mm, pgd, pmds);
spin_unlock_irqrestore(&pgd_lock, flags);
diff --git a/arch/x86/mm/srat_32.c b/arch/x86/mm/srat_32.c
index 9324f13492d5..a17dffd136c1 100644
--- a/arch/x86/mm/srat_32.c
+++ b/arch/x86/mm/srat_32.c
@@ -25,6 +25,7 @@
*/
#include <linux/mm.h>
#include <linux/bootmem.h>
+#include <linux/memblock.h>
#include <linux/mmzone.h>
#include <linux/acpi.h>
#include <linux/nodemask.h>
@@ -264,7 +265,7 @@ int __init get_memcfg_from_srat(void)
if (node_read_chunk(chunk->nid, chunk))
continue;
- e820_register_active_regions(chunk->nid, chunk->start_pfn,
+ memblock_x86_register_active_regions(chunk->nid, chunk->start_pfn,
min(chunk->end_pfn, max_pfn));
}
/* for out of order entries in SRAT */
diff --git a/arch/x86/mm/srat_64.c b/arch/x86/mm/srat_64.c
index f9897f7a9ef1..a35cb9d8b060 100644
--- a/arch/x86/mm/srat_64.c
+++ b/arch/x86/mm/srat_64.c
@@ -16,6 +16,7 @@
#include <linux/module.h>
#include <linux/topology.h>
#include <linux/bootmem.h>
+#include <linux/memblock.h>
#include <linux/mm.h>
#include <asm/proto.h>
#include <asm/numa.h>
@@ -98,15 +99,15 @@ void __init acpi_numa_slit_init(struct acpi_table_slit *slit)
unsigned long phys;
length = slit->header.length;
- phys = find_e820_area(0, max_pfn_mapped<<PAGE_SHIFT, length,
+ phys = memblock_find_in_range(0, max_pfn_mapped<<PAGE_SHIFT, length,
PAGE_SIZE);
- if (phys == -1L)
+ if (phys == MEMBLOCK_ERROR)
panic(" Can not save slit!\n");
acpi_slit = __va(phys);
memcpy(acpi_slit, slit, length);
- reserve_early(phys, phys + length, "ACPI SLIT");
+ memblock_x86_reserve_range(phys, phys + length, "ACPI SLIT");
}
/* Callback for Proximity Domain -> x2APIC mapping */
@@ -324,7 +325,7 @@ static int __init nodes_cover_memory(const struct bootnode *nodes)
pxmram = 0;
}
- e820ram = max_pfn - (e820_hole_size(0, max_pfn<<PAGE_SHIFT)>>PAGE_SHIFT);
+ e820ram = max_pfn - (memblock_x86_hole_size(0, max_pfn<<PAGE_SHIFT)>>PAGE_SHIFT);
/* We seem to lose 3 pages somewhere. Allow 1M of slack. */
if ((long)(e820ram - pxmram) >= (1<<(20 - PAGE_SHIFT))) {
printk(KERN_ERR
@@ -420,9 +421,11 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end)
return -1;
}
- for_each_node_mask(i, nodes_parsed)
- e820_register_active_regions(i, nodes[i].start >> PAGE_SHIFT,
- nodes[i].end >> PAGE_SHIFT);
+ for (i = 0; i < num_node_memblks; i++)
+ memblock_x86_register_active_regions(memblk_nodeid[i],
+ node_memblk_range[i].start >> PAGE_SHIFT,
+ node_memblk_range[i].end >> PAGE_SHIFT);
+
/* for out of order entries in SRAT */
sort_node_map();
if (!nodes_cover_memory(nodes)) {
diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c
index c03f14ab6667..49358481c733 100644
--- a/arch/x86/mm/tlb.c
+++ b/arch/x86/mm/tlb.c
@@ -5,6 +5,7 @@
#include <linux/smp.h>
#include <linux/interrupt.h>
#include <linux/module.h>
+#include <linux/cpu.h>
#include <asm/tlbflush.h>
#include <asm/mmu_context.h>
@@ -52,6 +53,8 @@ union smp_flush_state {
want false sharing in the per cpu data segment. */
static union smp_flush_state flush_state[NUM_INVALIDATE_TLB_VECTORS];
+static DEFINE_PER_CPU_READ_MOSTLY(int, tlb_vector_offset);
+
/*
* We cannot call mmdrop() because we are in interrupt context,
* instead update mm->cpu_vm_mask.
@@ -173,7 +176,7 @@ static void flush_tlb_others_ipi(const struct cpumask *cpumask,
union smp_flush_state *f;
/* Caller has disabled preemption */
- sender = smp_processor_id() % NUM_INVALIDATE_TLB_VECTORS;
+ sender = this_cpu_read(tlb_vector_offset);
f = &flush_state[sender];
/*
@@ -218,6 +221,47 @@ void native_flush_tlb_others(const struct cpumask *cpumask,
flush_tlb_others_ipi(cpumask, mm, va);
}
+static void __cpuinit calculate_tlb_offset(void)
+{
+ int cpu, node, nr_node_vecs;
+ /*
+ * we are changing tlb_vector_offset for each CPU in runtime, but this
+ * will not cause inconsistency, as the write is atomic under X86. we
+ * might see more lock contentions in a short time, but after all CPU's
+ * tlb_vector_offset are changed, everything should go normal
+ *
+ * Note: if NUM_INVALIDATE_TLB_VECTORS % nr_online_nodes !=0, we might
+ * waste some vectors.
+ **/
+ if (nr_online_nodes > NUM_INVALIDATE_TLB_VECTORS)
+ nr_node_vecs = 1;
+ else
+ nr_node_vecs = NUM_INVALIDATE_TLB_VECTORS/nr_online_nodes;
+
+ for_each_online_node(node) {
+ int node_offset = (node % NUM_INVALIDATE_TLB_VECTORS) *
+ nr_node_vecs;
+ int cpu_offset = 0;
+ for_each_cpu(cpu, cpumask_of_node(node)) {
+ per_cpu(tlb_vector_offset, cpu) = node_offset +
+ cpu_offset;
+ cpu_offset++;
+ cpu_offset = cpu_offset % nr_node_vecs;
+ }
+ }
+}
+
+static int tlb_cpuhp_notify(struct notifier_block *n,
+ unsigned long action, void *hcpu)
+{
+ switch (action & 0xf) {
+ case CPU_ONLINE:
+ case CPU_DEAD:
+ calculate_tlb_offset();
+ }
+ return NOTIFY_OK;
+}
+
static int __cpuinit init_smp_flush(void)
{
int i;
@@ -225,6 +269,8 @@ static int __cpuinit init_smp_flush(void)
for (i = 0; i < ARRAY_SIZE(flush_state); i++)
raw_spin_lock_init(&flush_state[i].tlbstate_lock);
+ calculate_tlb_offset();
+ hotcpu_notifier(tlb_cpuhp_notify, 0);
return 0;
}
core_initcall(init_smp_flush);
diff --git a/arch/x86/oprofile/backtrace.c b/arch/x86/oprofile/backtrace.c
index 3855096c59b8..2d49d4e19a36 100644
--- a/arch/x86/oprofile/backtrace.c
+++ b/arch/x86/oprofile/backtrace.c
@@ -14,6 +14,7 @@
#include <asm/ptrace.h>
#include <asm/uaccess.h>
#include <asm/stacktrace.h>
+#include <linux/compat.h>
static void backtrace_warning_symbol(void *data, char *msg,
unsigned long symbol)
@@ -48,14 +49,12 @@ static struct stacktrace_ops backtrace_ops = {
.walk_stack = print_context_stack,
};
-struct frame_head {
- struct frame_head *bp;
- unsigned long ret;
-} __attribute__((packed));
-
-static struct frame_head *dump_user_backtrace(struct frame_head *head)
+#ifdef CONFIG_COMPAT
+static struct stack_frame_ia32 *
+dump_user_backtrace_32(struct stack_frame_ia32 *head)
{
- struct frame_head bufhead[2];
+ struct stack_frame_ia32 bufhead[2];
+ struct stack_frame_ia32 *fp;
/* Also check accessibility of one struct frame_head beyond */
if (!access_ok(VERIFY_READ, head, sizeof(bufhead)))
@@ -63,20 +62,66 @@ static struct frame_head *dump_user_backtrace(struct frame_head *head)
if (__copy_from_user_inatomic(bufhead, head, sizeof(bufhead)))
return NULL;
- oprofile_add_trace(bufhead[0].ret);
+ fp = (struct stack_frame_ia32 *) compat_ptr(bufhead[0].next_frame);
+
+ oprofile_add_trace(bufhead[0].return_address);
+
+ /* frame pointers should strictly progress back up the stack
+ * (towards higher addresses) */
+ if (head >= fp)
+ return NULL;
+
+ return fp;
+}
+
+static inline int
+x86_backtrace_32(struct pt_regs * const regs, unsigned int depth)
+{
+ struct stack_frame_ia32 *head;
+
+ /* User process is 32-bit */
+ if (!current || !test_thread_flag(TIF_IA32))
+ return 0;
+
+ head = (struct stack_frame_ia32 *) regs->bp;
+ while (depth-- && head)
+ head = dump_user_backtrace_32(head);
+
+ return 1;
+}
+
+#else
+static inline int
+x86_backtrace_32(struct pt_regs * const regs, unsigned int depth)
+{
+ return 0;
+}
+#endif /* CONFIG_COMPAT */
+
+static struct stack_frame *dump_user_backtrace(struct stack_frame *head)
+{
+ struct stack_frame bufhead[2];
+
+ /* Also check accessibility of one struct stack_frame beyond */
+ if (!access_ok(VERIFY_READ, head, sizeof(bufhead)))
+ return NULL;
+ if (__copy_from_user_inatomic(bufhead, head, sizeof(bufhead)))
+ return NULL;
+
+ oprofile_add_trace(bufhead[0].return_address);
/* frame pointers should strictly progress back up the stack
* (towards higher addresses) */
- if (head >= bufhead[0].bp)
+ if (head >= bufhead[0].next_frame)
return NULL;
- return bufhead[0].bp;
+ return bufhead[0].next_frame;
}
void
x86_backtrace(struct pt_regs * const regs, unsigned int depth)
{
- struct frame_head *head = (struct frame_head *)frame_pointer(regs);
+ struct stack_frame *head = (struct stack_frame *)frame_pointer(regs);
if (!user_mode_vm(regs)) {
unsigned long stack = kernel_stack_pointer(regs);
@@ -86,6 +131,9 @@ x86_backtrace(struct pt_regs * const regs, unsigned int depth)
return;
}
+ if (x86_backtrace_32(regs, depth))
+ return;
+
while (depth-- && head)
head = dump_user_backtrace(head);
}
diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c
index 009b819f48d0..bd1489c3ce09 100644
--- a/arch/x86/oprofile/nmi_int.c
+++ b/arch/x86/oprofile/nmi_int.c
@@ -674,6 +674,7 @@ static int __init ppro_init(char **cpu_type)
case 0x0f:
case 0x16:
case 0x17:
+ case 0x1d:
*cpu_type = "i386/core_2";
break;
case 0x1a:
@@ -694,9 +695,6 @@ static int __init ppro_init(char **cpu_type)
return 1;
}
-/* in order to get sysfs right */
-static int using_nmi;
-
int __init op_nmi_init(struct oprofile_operations *ops)
{
__u8 vendor = boot_cpu_data.x86_vendor;
@@ -704,8 +702,6 @@ int __init op_nmi_init(struct oprofile_operations *ops)
char *cpu_type = NULL;
int ret = 0;
- using_nmi = 0;
-
if (!cpu_has_apic)
return -ENODEV;
@@ -789,13 +785,11 @@ int __init op_nmi_init(struct oprofile_operations *ops)
if (ret)
return ret;
- using_nmi = 1;
printk(KERN_INFO "oprofile: using NMI interrupt.\n");
return 0;
}
void op_nmi_exit(void)
{
- if (using_nmi)
- exit_sysfs();
+ exit_sysfs();
}
diff --git a/arch/x86/oprofile/op_model_amd.c b/arch/x86/oprofile/op_model_amd.c
index b67a6b5aa8d4..42fb46f83883 100644
--- a/arch/x86/oprofile/op_model_amd.c
+++ b/arch/x86/oprofile/op_model_amd.c
@@ -64,15 +64,22 @@ static u64 ibs_op_ctl;
* IBS cpuid feature detection
*/
-#define IBS_CPUID_FEATURES 0x8000001b
+#define IBS_CPUID_FEATURES 0x8000001b
/*
* Same bit mask as for IBS cpuid feature flags (Fn8000_001B_EAX), but
* bit 0 is used to indicate the existence of IBS.
*/
-#define IBS_CAPS_AVAIL (1LL<<0)
-#define IBS_CAPS_RDWROPCNT (1LL<<3)
-#define IBS_CAPS_OPCNT (1LL<<4)
+#define IBS_CAPS_AVAIL (1U<<0)
+#define IBS_CAPS_RDWROPCNT (1U<<3)
+#define IBS_CAPS_OPCNT (1U<<4)
+
+/*
+ * IBS APIC setup
+ */
+#define IBSCTL 0x1cc
+#define IBSCTL_LVT_OFFSET_VALID (1ULL<<8)
+#define IBSCTL_LVT_OFFSET_MASK 0x0F
/*
* IBS randomization macros
@@ -266,6 +273,74 @@ static void op_amd_stop_ibs(void)
wrmsrl(MSR_AMD64_IBSOPCTL, 0);
}
+static inline int eilvt_is_available(int offset)
+{
+ /* check if we may assign a vector */
+ return !setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_NMI, 1);
+}
+
+static inline int ibs_eilvt_valid(void)
+{
+ u64 val;
+ int offset;
+
+ rdmsrl(MSR_AMD64_IBSCTL, val);
+ if (!(val & IBSCTL_LVT_OFFSET_VALID)) {
+ pr_err(FW_BUG "cpu %d, invalid IBS "
+ "interrupt offset %d (MSR%08X=0x%016llx)",
+ smp_processor_id(), offset,
+ MSR_AMD64_IBSCTL, val);
+ return 0;
+ }
+
+ offset = val & IBSCTL_LVT_OFFSET_MASK;
+
+ if (eilvt_is_available(offset))
+ return !0;
+
+ pr_err(FW_BUG "cpu %d, IBS interrupt offset %d "
+ "not available (MSR%08X=0x%016llx)",
+ smp_processor_id(), offset,
+ MSR_AMD64_IBSCTL, val);
+
+ return 0;
+}
+
+static inline int get_ibs_offset(void)
+{
+ u64 val;
+
+ rdmsrl(MSR_AMD64_IBSCTL, val);
+ if (!(val & IBSCTL_LVT_OFFSET_VALID))
+ return -EINVAL;
+
+ return val & IBSCTL_LVT_OFFSET_MASK;
+}
+
+static void setup_APIC_ibs(void)
+{
+ int offset;
+
+ offset = get_ibs_offset();
+ if (offset < 0)
+ goto failed;
+
+ if (!setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_NMI, 0))
+ return;
+failed:
+ pr_warn("oprofile: IBS APIC setup failed on cpu #%d\n",
+ smp_processor_id());
+}
+
+static void clear_APIC_ibs(void)
+{
+ int offset;
+
+ offset = get_ibs_offset();
+ if (offset >= 0)
+ setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_FIX, 1);
+}
+
#ifdef CONFIG_OPROFILE_EVENT_MULTIPLEX
static void op_mux_switch_ctrl(struct op_x86_model_spec const *model,
@@ -376,13 +451,13 @@ static void op_amd_setup_ctrs(struct op_x86_model_spec const *model,
}
if (ibs_caps)
- setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_NMI, 0);
+ setup_APIC_ibs();
}
static void op_amd_cpu_shutdown(void)
{
if (ibs_caps)
- setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_FIX, 1);
+ clear_APIC_ibs();
}
static int op_amd_check_ctrs(struct pt_regs * const regs,
@@ -445,16 +520,11 @@ static void op_amd_stop(struct op_msrs const * const msrs)
op_amd_stop_ibs();
}
-static int __init_ibs_nmi(void)
+static int setup_ibs_ctl(int ibs_eilvt_off)
{
-#define IBSCTL_LVTOFFSETVAL (1 << 8)
-#define IBSCTL 0x1cc
struct pci_dev *cpu_cfg;
int nodes;
u32 value = 0;
- u8 ibs_eilvt_off;
-
- ibs_eilvt_off = setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_FIX, 1);
nodes = 0;
cpu_cfg = NULL;
@@ -466,21 +536,60 @@ static int __init_ibs_nmi(void)
break;
++nodes;
pci_write_config_dword(cpu_cfg, IBSCTL, ibs_eilvt_off
- | IBSCTL_LVTOFFSETVAL);
+ | IBSCTL_LVT_OFFSET_VALID);
pci_read_config_dword(cpu_cfg, IBSCTL, &value);
- if (value != (ibs_eilvt_off | IBSCTL_LVTOFFSETVAL)) {
+ if (value != (ibs_eilvt_off | IBSCTL_LVT_OFFSET_VALID)) {
pci_dev_put(cpu_cfg);
printk(KERN_DEBUG "Failed to setup IBS LVT offset, "
- "IBSCTL = 0x%08x", value);
- return 1;
+ "IBSCTL = 0x%08x\n", value);
+ return -EINVAL;
}
} while (1);
if (!nodes) {
- printk(KERN_DEBUG "No CPU node configured for IBS");
- return 1;
+ printk(KERN_DEBUG "No CPU node configured for IBS\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int force_ibs_eilvt_setup(void)
+{
+ int i;
+ int ret;
+
+ /* find the next free available EILVT entry */
+ for (i = 1; i < 4; i++) {
+ if (!eilvt_is_available(i))
+ continue;
+ ret = setup_ibs_ctl(i);
+ if (ret)
+ return ret;
+ return 0;
}
+ printk(KERN_DEBUG "No EILVT entry available\n");
+
+ return -EBUSY;
+}
+
+static int __init_ibs_nmi(void)
+{
+ int ret;
+
+ if (ibs_eilvt_valid())
+ return 0;
+
+ ret = force_ibs_eilvt_setup();
+ if (ret)
+ return ret;
+
+ if (!ibs_eilvt_valid())
+ return -EFAULT;
+
+ pr_err(FW_BUG "workaround enabled for IBS LVT offset\n");
+
return 0;
}
diff --git a/arch/x86/pci/olpc.c b/arch/x86/pci/olpc.c
index b34815408f58..13700ec8e2e4 100644
--- a/arch/x86/pci/olpc.c
+++ b/arch/x86/pci/olpc.c
@@ -304,7 +304,7 @@ static struct pci_raw_ops pci_olpc_conf = {
int __init pci_olpc_init(void)
{
- printk(KERN_INFO "PCI: Using configuration type OLPC\n");
+ printk(KERN_INFO "PCI: Using configuration type OLPC XO-1\n");
raw_pci_ops = &pci_olpc_conf;
is_lx = is_geode_lx();
return 0;
diff --git a/arch/x86/xen/debugfs.c b/arch/x86/xen/debugfs.c
index 1304bcec8ee5..7c0fedd98ea0 100644
--- a/arch/x86/xen/debugfs.c
+++ b/arch/x86/xen/debugfs.c
@@ -106,6 +106,7 @@ static const struct file_operations u32_array_fops = {
.open = u32_array_open,
.release= xen_array_release,
.read = u32_array_read,
+ .llseek = no_llseek,
};
struct dentry *xen_debugfs_create_u32_array(const char *name, mode_t mode,
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 7d46c8441418..63b83ceebd1a 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -30,6 +30,7 @@
#include <linux/console.h>
#include <linux/pci.h>
#include <linux/gfp.h>
+#include <linux/memblock.h>
#include <xen/xen.h>
#include <xen/interface/xen.h>
@@ -1183,6 +1184,8 @@ asmlinkage void __init xen_start_kernel(void)
local_irq_disable();
early_boot_irqs_off();
+ memblock_init();
+
xen_raw_console_write("mapping kernel into physical memory\n");
pgd = xen_setup_kernel_pagetable(pgd, xen_start_info->nr_pages);
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index 42086ac406af..f72d18c69221 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -45,6 +45,7 @@
#include <linux/vmalloc.h>
#include <linux/module.h>
#include <linux/gfp.h>
+#include <linux/memblock.h>
#include <asm/pgtable.h>
#include <asm/tlbflush.h>
@@ -55,6 +56,7 @@
#include <asm/e820.h>
#include <asm/linkage.h>
#include <asm/page.h>
+#include <asm/init.h>
#include <asm/xen/hypercall.h>
#include <asm/xen/hypervisor.h>
@@ -359,7 +361,8 @@ void make_lowmem_page_readonly(void *vaddr)
unsigned int level;
pte = lookup_address(address, &level);
- BUG_ON(pte == NULL);
+ if (pte == NULL)
+ return; /* vaddr missing */
ptev = pte_wrprotect(*pte);
@@ -374,7 +377,8 @@ void make_lowmem_page_readwrite(void *vaddr)
unsigned int level;
pte = lookup_address(address, &level);
- BUG_ON(pte == NULL);
+ if (pte == NULL)
+ return; /* vaddr missing */
ptev = pte_mkwrite(*pte);
@@ -1508,13 +1512,25 @@ static void xen_pgd_free(struct mm_struct *mm, pgd_t *pgd)
#endif
}
-#ifdef CONFIG_X86_32
static __init pte_t mask_rw_pte(pte_t *ptep, pte_t pte)
{
+ unsigned long pfn = pte_pfn(pte);
+
+#ifdef CONFIG_X86_32
/* If there's an existing pte, then don't allow _PAGE_RW to be set */
if (pte_val_ma(*ptep) & _PAGE_PRESENT)
pte = __pte_ma(((pte_val_ma(*ptep) & _PAGE_RW) | ~_PAGE_RW) &
pte_val_ma(pte));
+#endif
+
+ /*
+ * If the new pfn is within the range of the newly allocated
+ * kernel pagetable, and it isn't being mapped into an
+ * early_ioremap fixmap slot, make sure it is RO.
+ */
+ if (!is_early_ioremap_ptep(ptep) &&
+ pfn >= e820_table_start && pfn < e820_table_end)
+ pte = pte_wrprotect(pte);
return pte;
}
@@ -1527,7 +1543,6 @@ static __init void xen_set_pte_init(pte_t *ptep, pte_t pte)
xen_set_pte(ptep, pte);
}
-#endif
static void pin_pagetable_pfn(unsigned cmd, unsigned long pfn)
{
@@ -1814,7 +1829,7 @@ __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd,
__xen_write_cr3(true, __pa(pgd));
xen_mc_issue(PARAVIRT_LAZY_CPU);
- reserve_early(__pa(xen_start_info->pt_base),
+ memblock_x86_reserve_range(__pa(xen_start_info->pt_base),
__pa(xen_start_info->pt_base +
xen_start_info->nr_pt_frames * PAGE_SIZE),
"XEN PAGETABLES");
@@ -1852,7 +1867,7 @@ __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd,
pin_pagetable_pfn(MMUEXT_PIN_L3_TABLE, PFN_DOWN(__pa(swapper_pg_dir)));
- reserve_early(__pa(xen_start_info->pt_base),
+ memblock_x86_reserve_range(__pa(xen_start_info->pt_base),
__pa(xen_start_info->pt_base +
xen_start_info->nr_pt_frames * PAGE_SIZE),
"XEN PAGETABLES");
@@ -1969,14 +1984,9 @@ static const struct pv_mmu_ops xen_mmu_ops __initdata = {
.alloc_pte = xen_alloc_pte_init,
.release_pte = xen_release_pte_init,
.alloc_pmd = xen_alloc_pmd_init,
- .alloc_pmd_clone = paravirt_nop,
.release_pmd = xen_release_pmd_init,
-#ifdef CONFIG_X86_64
- .set_pte = xen_set_pte,
-#else
.set_pte = xen_set_pte_init,
-#endif
.set_pte_at = xen_set_pte_at,
.set_pmd = xen_set_pmd_hyper,
diff --git a/arch/x86/xen/pci-swiotlb-xen.c b/arch/x86/xen/pci-swiotlb-xen.c
index a013ec9d0c54..22471001b74c 100644
--- a/arch/x86/xen/pci-swiotlb-xen.c
+++ b/arch/x86/xen/pci-swiotlb-xen.c
@@ -5,6 +5,7 @@
#include <asm/xen/hypervisor.h>
#include <xen/xen.h>
+#include <asm/iommu_table.h>
int xen_swiotlb __read_mostly;
@@ -56,3 +57,7 @@ void __init pci_xen_swiotlb_init(void)
dma_ops = &xen_swiotlb_dma_ops;
}
}
+IOMMU_INIT_FINISH(pci_xen_swiotlb_detect,
+ 0,
+ pci_xen_swiotlb_init,
+ 0);
diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c
index 328b00305426..9729c903404b 100644
--- a/arch/x86/xen/setup.c
+++ b/arch/x86/xen/setup.c
@@ -8,6 +8,7 @@
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/pm.h>
+#include <linux/memblock.h>
#include <asm/elf.h>
#include <asm/vdso.h>
@@ -129,7 +130,7 @@ char * __init xen_memory_setup(void)
* - xen_start_info
* See comment above "struct start_info" in <xen/interface/xen.h>
*/
- reserve_early(__pa(xen_start_info->mfn_list),
+ memblock_x86_reserve_range(__pa(xen_start_info->mfn_list),
__pa(xen_start_info->pt_base),
"XEN START INFO");
diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c
index e0500646585d..23e061b9327b 100644
--- a/arch/x86/xen/spinlock.c
+++ b/arch/x86/xen/spinlock.c
@@ -224,7 +224,7 @@ static noinline int xen_spin_lock_slow(struct arch_spinlock *lock, bool irq_enab
goto out;
}
- flags = __raw_local_save_flags();
+ flags = arch_local_save_flags();
if (irq_enable) {
ADD_STATS(taken_slow_irqenable, 1);
raw_local_irq_enable();
diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c
index 1a5353a753fc..b2bb5aa3b054 100644
--- a/arch/x86/xen/time.c
+++ b/arch/x86/xen/time.c
@@ -489,8 +489,9 @@ static void xen_hvm_setup_cpu_clockevents(void)
__init void xen_hvm_init_time_ops(void)
{
/* vector callback is needed otherwise we cannot receive interrupts
- * on cpu > 0 */
- if (!xen_have_vector_callback && num_present_cpus() > 1)
+ * on cpu > 0 and at this point we don't know how many cpus are
+ * available */
+ if (!xen_have_vector_callback)
return;
if (!xen_feature(XENFEAT_hvm_safe_pvclock)) {
printk(KERN_INFO "Xen doesn't support pvclock on HVM,"
diff --git a/arch/xtensa/include/asm/irqflags.h b/arch/xtensa/include/asm/irqflags.h
new file mode 100644
index 000000000000..dae9a8bdcb17
--- /dev/null
+++ b/arch/xtensa/include/asm/irqflags.h
@@ -0,0 +1,58 @@
+/*
+ * Xtensa IRQ flags handling functions
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_IRQFLAGS_H
+#define _XTENSA_IRQFLAGS_H
+
+#include <linux/types.h>
+
+static inline unsigned long arch_local_save_flags(void)
+{
+ unsigned long flags;
+ asm volatile("rsr %0,"__stringify(PS) : "=a" (flags));
+ return flags;
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+ unsigned long flags;
+ asm volatile("rsil %0, "__stringify(LOCKLEVEL)
+ : "=a" (flags) :: "memory");
+ return flags;
+}
+
+static inline void arch_local_irq_disable(void)
+{
+ arch_local_irq_save();
+}
+
+static inline void arch_local_irq_enable(void)
+{
+ unsigned long flags;
+ asm volatile("rsil %0, 0" : "=a" (flags) :: "memory");
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+ asm volatile("wsr %0, "__stringify(PS)" ; rsync"
+ :: "a" (flags) : "memory");
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+ return (flags & 0xf) != 0;
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+ return arch_irqs_disabled_flags(arch_local_save_flags());
+}
+
+#endif /* _XTENSA_IRQFLAGS_H */
diff --git a/arch/xtensa/include/asm/system.h b/arch/xtensa/include/asm/system.h
index 62b1e8f3c13c..1e7e09ab6cd7 100644
--- a/arch/xtensa/include/asm/system.h
+++ b/arch/xtensa/include/asm/system.h
@@ -12,41 +12,10 @@
#define _XTENSA_SYSTEM_H
#include <linux/stringify.h>
+#include <linux/irqflags.h>
#include <asm/processor.h>
-/* interrupt control */
-
-#define local_save_flags(x) \
- __asm__ __volatile__ ("rsr %0,"__stringify(PS) : "=a" (x));
-#define local_irq_restore(x) do { \
- __asm__ __volatile__ ("wsr %0, "__stringify(PS)" ; rsync" \
- :: "a" (x) : "memory"); } while(0);
-#define local_irq_save(x) do { \
- __asm__ __volatile__ ("rsil %0, "__stringify(LOCKLEVEL) \
- : "=a" (x) :: "memory");} while(0);
-
-static inline void local_irq_disable(void)
-{
- unsigned long flags;
- __asm__ __volatile__ ("rsil %0, "__stringify(LOCKLEVEL)
- : "=a" (flags) :: "memory");
-}
-static inline void local_irq_enable(void)
-{
- unsigned long flags;
- __asm__ __volatile__ ("rsil %0, 0" : "=a" (flags) :: "memory");
-
-}
-
-static inline int irqs_disabled(void)
-{
- unsigned long flags;
- local_save_flags(flags);
- return flags & 0xf;
-}
-
-
#define smp_read_barrier_depends() do { } while(0)
#define read_barrier_depends() do { } while(0)
diff --git a/arch/xtensa/kernel/irq.c b/arch/xtensa/kernel/irq.c
index c64a5d387de5..87508886cbbd 100644
--- a/arch/xtensa/kernel/irq.c
+++ b/arch/xtensa/kernel/irq.c
@@ -92,7 +92,7 @@ int show_interrupts(struct seq_file *p, void *v)
for_each_online_cpu(j)
seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
#endif
- seq_printf(p, " %14s", irq_desc[i].chip->typename);
+ seq_printf(p, " %14s", irq_desc[i].chip->name);
seq_printf(p, " %s", action->name);
for (action=action->next; action; action = action->next)
diff --git a/block/Kconfig b/block/Kconfig
index 9be0b56eaee1..6c9213ef15a1 100644
--- a/block/Kconfig
+++ b/block/Kconfig
@@ -77,6 +77,18 @@ config BLK_DEV_INTEGRITY
T10/SCSI Data Integrity Field or the T13/ATA External Path
Protection. If in doubt, say N.
+config BLK_DEV_THROTTLING
+ bool "Block layer bio throttling support"
+ depends on BLK_CGROUP=y && EXPERIMENTAL
+ default n
+ ---help---
+ Block layer bio throttling support. It can be used to limit
+ the IO rate to a device. IO rate policies are per cgroup and
+ one needs to mount and use blkio cgroup controller for creating
+ cgroups and specifying per device IO rate policies.
+
+ See Documentation/cgroups/blkio-controller.txt for more information.
+
endif # BLOCK
config BLOCK_COMPAT
diff --git a/block/Makefile b/block/Makefile
index 0bb499a739cd..0fec4b3fab51 100644
--- a/block/Makefile
+++ b/block/Makefile
@@ -3,12 +3,13 @@
#
obj-$(CONFIG_BLOCK) := elevator.o blk-core.o blk-tag.o blk-sysfs.o \
- blk-barrier.o blk-settings.o blk-ioc.o blk-map.o \
+ blk-flush.o blk-settings.o blk-ioc.o blk-map.o \
blk-exec.o blk-merge.o blk-softirq.o blk-timeout.o \
blk-iopoll.o blk-lib.o ioctl.o genhd.o scsi_ioctl.o
obj-$(CONFIG_BLK_DEV_BSG) += bsg.o
obj-$(CONFIG_BLK_CGROUP) += blk-cgroup.o
+obj-$(CONFIG_BLK_DEV_THROTTLING) += blk-throttle.o
obj-$(CONFIG_IOSCHED_NOOP) += noop-iosched.o
obj-$(CONFIG_IOSCHED_DEADLINE) += deadline-iosched.o
obj-$(CONFIG_IOSCHED_CFQ) += cfq-iosched.o
diff --git a/block/blk-barrier.c b/block/blk-barrier.c
deleted file mode 100644
index f0faefca032f..000000000000
--- a/block/blk-barrier.c
+++ /dev/null
@@ -1,350 +0,0 @@
-/*
- * Functions related to barrier IO handling
- */
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/bio.h>
-#include <linux/blkdev.h>
-#include <linux/gfp.h>
-
-#include "blk.h"
-
-/**
- * blk_queue_ordered - does this queue support ordered writes
- * @q: the request queue
- * @ordered: one of QUEUE_ORDERED_*
- *
- * Description:
- * For journalled file systems, doing ordered writes on a commit
- * block instead of explicitly doing wait_on_buffer (which is bad
- * for performance) can be a big win. Block drivers supporting this
- * feature should call this function and indicate so.
- *
- **/
-int blk_queue_ordered(struct request_queue *q, unsigned ordered)
-{
- if (ordered != QUEUE_ORDERED_NONE &&
- ordered != QUEUE_ORDERED_DRAIN &&
- ordered != QUEUE_ORDERED_DRAIN_FLUSH &&
- ordered != QUEUE_ORDERED_DRAIN_FUA &&
- ordered != QUEUE_ORDERED_TAG &&
- ordered != QUEUE_ORDERED_TAG_FLUSH &&
- ordered != QUEUE_ORDERED_TAG_FUA) {
- printk(KERN_ERR "blk_queue_ordered: bad value %d\n", ordered);
- return -EINVAL;
- }
-
- q->ordered = ordered;
- q->next_ordered = ordered;
-
- return 0;
-}
-EXPORT_SYMBOL(blk_queue_ordered);
-
-/*
- * Cache flushing for ordered writes handling
- */
-unsigned blk_ordered_cur_seq(struct request_queue *q)
-{
- if (!q->ordseq)
- return 0;
- return 1 << ffz(q->ordseq);
-}
-
-unsigned blk_ordered_req_seq(struct request *rq)
-{
- struct request_queue *q = rq->q;
-
- BUG_ON(q->ordseq == 0);
-
- if (rq == &q->pre_flush_rq)
- return QUEUE_ORDSEQ_PREFLUSH;
- if (rq == &q->bar_rq)
- return QUEUE_ORDSEQ_BAR;
- if (rq == &q->post_flush_rq)
- return QUEUE_ORDSEQ_POSTFLUSH;
-
- /*
- * !fs requests don't need to follow barrier ordering. Always
- * put them at the front. This fixes the following deadlock.
- *
- * http://thread.gmane.org/gmane.linux.kernel/537473
- */
- if (rq->cmd_type != REQ_TYPE_FS)
- return QUEUE_ORDSEQ_DRAIN;
-
- if ((rq->cmd_flags & REQ_ORDERED_COLOR) ==
- (q->orig_bar_rq->cmd_flags & REQ_ORDERED_COLOR))
- return QUEUE_ORDSEQ_DRAIN;
- else
- return QUEUE_ORDSEQ_DONE;
-}
-
-bool blk_ordered_complete_seq(struct request_queue *q, unsigned seq, int error)
-{
- struct request *rq;
-
- if (error && !q->orderr)
- q->orderr = error;
-
- BUG_ON(q->ordseq & seq);
- q->ordseq |= seq;
-
- if (blk_ordered_cur_seq(q) != QUEUE_ORDSEQ_DONE)
- return false;
-
- /*
- * Okay, sequence complete.
- */
- q->ordseq = 0;
- rq = q->orig_bar_rq;
- __blk_end_request_all(rq, q->orderr);
- return true;
-}
-
-static void pre_flush_end_io(struct request *rq, int error)
-{
- elv_completed_request(rq->q, rq);
- blk_ordered_complete_seq(rq->q, QUEUE_ORDSEQ_PREFLUSH, error);
-}
-
-static void bar_end_io(struct request *rq, int error)
-{
- elv_completed_request(rq->q, rq);
- blk_ordered_complete_seq(rq->q, QUEUE_ORDSEQ_BAR, error);
-}
-
-static void post_flush_end_io(struct request *rq, int error)
-{
- elv_completed_request(rq->q, rq);
- blk_ordered_complete_seq(rq->q, QUEUE_ORDSEQ_POSTFLUSH, error);
-}
-
-static void queue_flush(struct request_queue *q, unsigned which)
-{
- struct request *rq;
- rq_end_io_fn *end_io;
-
- if (which == QUEUE_ORDERED_DO_PREFLUSH) {
- rq = &q->pre_flush_rq;
- end_io = pre_flush_end_io;
- } else {
- rq = &q->post_flush_rq;
- end_io = post_flush_end_io;
- }
-
- blk_rq_init(q, rq);
- rq->cmd_type = REQ_TYPE_FS;
- rq->cmd_flags = REQ_HARDBARRIER | REQ_FLUSH;
- rq->rq_disk = q->orig_bar_rq->rq_disk;
- rq->end_io = end_io;
-
- elv_insert(q, rq, ELEVATOR_INSERT_FRONT);
-}
-
-static inline bool start_ordered(struct request_queue *q, struct request **rqp)
-{
- struct request *rq = *rqp;
- unsigned skip = 0;
-
- q->orderr = 0;
- q->ordered = q->next_ordered;
- q->ordseq |= QUEUE_ORDSEQ_STARTED;
-
- /*
- * For an empty barrier, there's no actual BAR request, which
- * in turn makes POSTFLUSH unnecessary. Mask them off.
- */
- if (!blk_rq_sectors(rq)) {
- q->ordered &= ~(QUEUE_ORDERED_DO_BAR |
- QUEUE_ORDERED_DO_POSTFLUSH);
- /*
- * Empty barrier on a write-through device w/ ordered
- * tag has no command to issue and without any command
- * to issue, ordering by tag can't be used. Drain
- * instead.
- */
- if ((q->ordered & QUEUE_ORDERED_BY_TAG) &&
- !(q->ordered & QUEUE_ORDERED_DO_PREFLUSH)) {
- q->ordered &= ~QUEUE_ORDERED_BY_TAG;
- q->ordered |= QUEUE_ORDERED_BY_DRAIN;
- }
- }
-
- /* stash away the original request */
- blk_dequeue_request(rq);
- q->orig_bar_rq = rq;
- rq = NULL;
-
- /*
- * Queue ordered sequence. As we stack them at the head, we
- * need to queue in reverse order. Note that we rely on that
- * no fs request uses ELEVATOR_INSERT_FRONT and thus no fs
- * request gets inbetween ordered sequence.
- */
- if (q->ordered & QUEUE_ORDERED_DO_POSTFLUSH) {
- queue_flush(q, QUEUE_ORDERED_DO_POSTFLUSH);
- rq = &q->post_flush_rq;
- } else
- skip |= QUEUE_ORDSEQ_POSTFLUSH;
-
- if (q->ordered & QUEUE_ORDERED_DO_BAR) {
- rq = &q->bar_rq;
-
- /* initialize proxy request and queue it */
- blk_rq_init(q, rq);
- if (bio_data_dir(q->orig_bar_rq->bio) == WRITE)
- rq->cmd_flags |= REQ_WRITE;
- if (q->ordered & QUEUE_ORDERED_DO_FUA)
- rq->cmd_flags |= REQ_FUA;
- init_request_from_bio(rq, q->orig_bar_rq->bio);
- rq->end_io = bar_end_io;
-
- elv_insert(q, rq, ELEVATOR_INSERT_FRONT);
- } else
- skip |= QUEUE_ORDSEQ_BAR;
-
- if (q->ordered & QUEUE_ORDERED_DO_PREFLUSH) {
- queue_flush(q, QUEUE_ORDERED_DO_PREFLUSH);
- rq = &q->pre_flush_rq;
- } else
- skip |= QUEUE_ORDSEQ_PREFLUSH;
-
- if ((q->ordered & QUEUE_ORDERED_BY_DRAIN) && queue_in_flight(q))
- rq = NULL;
- else
- skip |= QUEUE_ORDSEQ_DRAIN;
-
- *rqp = rq;
-
- /*
- * Complete skipped sequences. If whole sequence is complete,
- * return false to tell elevator that this request is gone.
- */
- return !blk_ordered_complete_seq(q, skip, 0);
-}
-
-bool blk_do_ordered(struct request_queue *q, struct request **rqp)
-{
- struct request *rq = *rqp;
- const int is_barrier = rq->cmd_type == REQ_TYPE_FS &&
- (rq->cmd_flags & REQ_HARDBARRIER);
-
- if (!q->ordseq) {
- if (!is_barrier)
- return true;
-
- if (q->next_ordered != QUEUE_ORDERED_NONE)
- return start_ordered(q, rqp);
- else {
- /*
- * Queue ordering not supported. Terminate
- * with prejudice.
- */
- blk_dequeue_request(rq);
- __blk_end_request_all(rq, -EOPNOTSUPP);
- *rqp = NULL;
- return false;
- }
- }
-
- /*
- * Ordered sequence in progress
- */
-
- /* Special requests are not subject to ordering rules. */
- if (rq->cmd_type != REQ_TYPE_FS &&
- rq != &q->pre_flush_rq && rq != &q->post_flush_rq)
- return true;
-
- if (q->ordered & QUEUE_ORDERED_BY_TAG) {
- /* Ordered by tag. Blocking the next barrier is enough. */
- if (is_barrier && rq != &q->bar_rq)
- *rqp = NULL;
- } else {
- /* Ordered by draining. Wait for turn. */
- WARN_ON(blk_ordered_req_seq(rq) < blk_ordered_cur_seq(q));
- if (blk_ordered_req_seq(rq) > blk_ordered_cur_seq(q))
- *rqp = NULL;
- }
-
- return true;
-}
-
-static void bio_end_empty_barrier(struct bio *bio, int err)
-{
- if (err) {
- if (err == -EOPNOTSUPP)
- set_bit(BIO_EOPNOTSUPP, &bio->bi_flags);
- clear_bit(BIO_UPTODATE, &bio->bi_flags);
- }
- if (bio->bi_private)
- complete(bio->bi_private);
- bio_put(bio);
-}
-
-/**
- * blkdev_issue_flush - queue a flush
- * @bdev: blockdev to issue flush for
- * @gfp_mask: memory allocation flags (for bio_alloc)
- * @error_sector: error sector
- * @flags: BLKDEV_IFL_* flags to control behaviour
- *
- * Description:
- * Issue a flush for the block device in question. Caller can supply
- * room for storing the error offset in case of a flush error, if they
- * wish to. If WAIT flag is not passed then caller may check only what
- * request was pushed in some internal queue for later handling.
- */
-int blkdev_issue_flush(struct block_device *bdev, gfp_t gfp_mask,
- sector_t *error_sector, unsigned long flags)
-{
- DECLARE_COMPLETION_ONSTACK(wait);
- struct request_queue *q;
- struct bio *bio;
- int ret = 0;
-
- if (bdev->bd_disk == NULL)
- return -ENXIO;
-
- q = bdev_get_queue(bdev);
- if (!q)
- return -ENXIO;
-
- /*
- * some block devices may not have their queue correctly set up here
- * (e.g. loop device without a backing file) and so issuing a flush
- * here will panic. Ensure there is a request function before issuing
- * the barrier.
- */
- if (!q->make_request_fn)
- return -ENXIO;
-
- bio = bio_alloc(gfp_mask, 0);
- bio->bi_end_io = bio_end_empty_barrier;
- bio->bi_bdev = bdev;
- if (test_bit(BLKDEV_WAIT, &flags))
- bio->bi_private = &wait;
-
- bio_get(bio);
- submit_bio(WRITE_BARRIER, bio);
- if (test_bit(BLKDEV_WAIT, &flags)) {
- wait_for_completion(&wait);
- /*
- * The driver must store the error location in ->bi_sector, if
- * it supports it. For non-stacked drivers, this should be
- * copied from blk_rq_pos(rq).
- */
- if (error_sector)
- *error_sector = bio->bi_sector;
- }
-
- if (bio_flagged(bio, BIO_EOPNOTSUPP))
- ret = -EOPNOTSUPP;
- else if (!bio_flagged(bio, BIO_UPTODATE))
- ret = -EIO;
-
- bio_put(bio);
- return ret;
-}
-EXPORT_SYMBOL(blkdev_issue_flush);
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index 2fef1ef931a0..b1febd0f6d2a 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -37,6 +37,12 @@ static void blkiocg_attach(struct cgroup_subsys *, struct cgroup *,
static void blkiocg_destroy(struct cgroup_subsys *, struct cgroup *);
static int blkiocg_populate(struct cgroup_subsys *, struct cgroup *);
+/* for encoding cft->private value on file */
+#define BLKIOFILE_PRIVATE(x, val) (((x) << 16) | (val))
+/* What policy owns the file, proportional or throttle */
+#define BLKIOFILE_POLICY(val) (((val) >> 16) & 0xffff)
+#define BLKIOFILE_ATTR(val) ((val) & 0xffff)
+
struct cgroup_subsys blkio_subsys = {
.name = "blkio",
.create = blkiocg_create,
@@ -59,6 +65,27 @@ static inline void blkio_policy_insert_node(struct blkio_cgroup *blkcg,
list_add(&pn->node, &blkcg->policy_list);
}
+static inline bool cftype_blkg_same_policy(struct cftype *cft,
+ struct blkio_group *blkg)
+{
+ enum blkio_policy_id plid = BLKIOFILE_POLICY(cft->private);
+
+ if (blkg->plid == plid)
+ return 1;
+
+ return 0;
+}
+
+/* Determines if policy node matches cgroup file being accessed */
+static inline bool pn_matches_cftype(struct cftype *cft,
+ struct blkio_policy_node *pn)
+{
+ enum blkio_policy_id plid = BLKIOFILE_POLICY(cft->private);
+ int fileid = BLKIOFILE_ATTR(cft->private);
+
+ return (plid == pn->plid && fileid == pn->fileid);
+}
+
/* Must be called with blkcg->lock held */
static inline void blkio_policy_delete_node(struct blkio_policy_node *pn)
{
@@ -67,12 +94,13 @@ static inline void blkio_policy_delete_node(struct blkio_policy_node *pn)
/* Must be called with blkcg->lock held */
static struct blkio_policy_node *
-blkio_policy_search_node(const struct blkio_cgroup *blkcg, dev_t dev)
+blkio_policy_search_node(const struct blkio_cgroup *blkcg, dev_t dev,
+ enum blkio_policy_id plid, int fileid)
{
struct blkio_policy_node *pn;
list_for_each_entry(pn, &blkcg->policy_list, node) {
- if (pn->dev == dev)
+ if (pn->dev == dev && pn->plid == plid && pn->fileid == fileid)
return pn;
}
@@ -86,6 +114,67 @@ struct blkio_cgroup *cgroup_to_blkio_cgroup(struct cgroup *cgroup)
}
EXPORT_SYMBOL_GPL(cgroup_to_blkio_cgroup);
+static inline void
+blkio_update_group_weight(struct blkio_group *blkg, unsigned int weight)
+{
+ struct blkio_policy_type *blkiop;
+
+ list_for_each_entry(blkiop, &blkio_list, list) {
+ /* If this policy does not own the blkg, do not send updates */
+ if (blkiop->plid != blkg->plid)
+ continue;
+ if (blkiop->ops.blkio_update_group_weight_fn)
+ blkiop->ops.blkio_update_group_weight_fn(blkg->key,
+ blkg, weight);
+ }
+}
+
+static inline void blkio_update_group_bps(struct blkio_group *blkg, u64 bps,
+ int fileid)
+{
+ struct blkio_policy_type *blkiop;
+
+ list_for_each_entry(blkiop, &blkio_list, list) {
+
+ /* If this policy does not own the blkg, do not send updates */
+ if (blkiop->plid != blkg->plid)
+ continue;
+
+ if (fileid == BLKIO_THROTL_read_bps_device
+ && blkiop->ops.blkio_update_group_read_bps_fn)
+ blkiop->ops.blkio_update_group_read_bps_fn(blkg->key,
+ blkg, bps);
+
+ if (fileid == BLKIO_THROTL_write_bps_device
+ && blkiop->ops.blkio_update_group_write_bps_fn)
+ blkiop->ops.blkio_update_group_write_bps_fn(blkg->key,
+ blkg, bps);
+ }
+}
+
+static inline void blkio_update_group_iops(struct blkio_group *blkg,
+ unsigned int iops, int fileid)
+{
+ struct blkio_policy_type *blkiop;
+
+ list_for_each_entry(blkiop, &blkio_list, list) {
+
+ /* If this policy does not own the blkg, do not send updates */
+ if (blkiop->plid != blkg->plid)
+ continue;
+
+ if (fileid == BLKIO_THROTL_read_iops_device
+ && blkiop->ops.blkio_update_group_read_iops_fn)
+ blkiop->ops.blkio_update_group_read_iops_fn(blkg->key,
+ blkg, iops);
+
+ if (fileid == BLKIO_THROTL_write_iops_device
+ && blkiop->ops.blkio_update_group_write_iops_fn)
+ blkiop->ops.blkio_update_group_write_iops_fn(blkg->key,
+ blkg,iops);
+ }
+}
+
/*
* Add to the appropriate stat variable depending on the request type.
* This should be called with the blkg->stats_lock held.
@@ -341,7 +430,8 @@ void blkiocg_update_io_merged_stats(struct blkio_group *blkg, bool direction,
EXPORT_SYMBOL_GPL(blkiocg_update_io_merged_stats);
void blkiocg_add_blkio_group(struct blkio_cgroup *blkcg,
- struct blkio_group *blkg, void *key, dev_t dev)
+ struct blkio_group *blkg, void *key, dev_t dev,
+ enum blkio_policy_id plid)
{
unsigned long flags;
@@ -350,6 +440,7 @@ void blkiocg_add_blkio_group(struct blkio_cgroup *blkcg,
rcu_assign_pointer(blkg->key, key);
blkg->blkcg_id = css_id(&blkcg->css);
hlist_add_head_rcu(&blkg->blkcg_node, &blkcg->blkg_list);
+ blkg->plid = plid;
spin_unlock_irqrestore(&blkcg->lock, flags);
/* Need to take css reference ? */
cgroup_path(blkcg->css.cgroup, blkg->path, sizeof(blkg->path));
@@ -408,51 +499,6 @@ struct blkio_group *blkiocg_lookup_group(struct blkio_cgroup *blkcg, void *key)
}
EXPORT_SYMBOL_GPL(blkiocg_lookup_group);
-#define SHOW_FUNCTION(__VAR) \
-static u64 blkiocg_##__VAR##_read(struct cgroup *cgroup, \
- struct cftype *cftype) \
-{ \
- struct blkio_cgroup *blkcg; \
- \
- blkcg = cgroup_to_blkio_cgroup(cgroup); \
- return (u64)blkcg->__VAR; \
-}
-
-SHOW_FUNCTION(weight);
-#undef SHOW_FUNCTION
-
-static int
-blkiocg_weight_write(struct cgroup *cgroup, struct cftype *cftype, u64 val)
-{
- struct blkio_cgroup *blkcg;
- struct blkio_group *blkg;
- struct hlist_node *n;
- struct blkio_policy_type *blkiop;
- struct blkio_policy_node *pn;
-
- if (val < BLKIO_WEIGHT_MIN || val > BLKIO_WEIGHT_MAX)
- return -EINVAL;
-
- blkcg = cgroup_to_blkio_cgroup(cgroup);
- spin_lock(&blkio_list_lock);
- spin_lock_irq(&blkcg->lock);
- blkcg->weight = (unsigned int)val;
-
- hlist_for_each_entry(blkg, n, &blkcg->blkg_list, blkcg_node) {
- pn = blkio_policy_search_node(blkcg, blkg->dev);
-
- if (pn)
- continue;
-
- list_for_each_entry(blkiop, &blkio_list, list)
- blkiop->ops.blkio_update_group_weight_fn(blkg,
- blkcg->weight);
- }
- spin_unlock_irq(&blkcg->lock);
- spin_unlock(&blkio_list_lock);
- return 0;
-}
-
static int
blkiocg_reset_stats(struct cgroup *cgroup, struct cftype *cftype, u64 val)
{
@@ -593,52 +639,6 @@ static uint64_t blkio_get_stat(struct blkio_group *blkg,
return disk_total;
}
-#define SHOW_FUNCTION_PER_GROUP(__VAR, type, show_total) \
-static int blkiocg_##__VAR##_read(struct cgroup *cgroup, \
- struct cftype *cftype, struct cgroup_map_cb *cb) \
-{ \
- struct blkio_cgroup *blkcg; \
- struct blkio_group *blkg; \
- struct hlist_node *n; \
- uint64_t cgroup_total = 0; \
- \
- if (!cgroup_lock_live_group(cgroup)) \
- return -ENODEV; \
- \
- blkcg = cgroup_to_blkio_cgroup(cgroup); \
- rcu_read_lock(); \
- hlist_for_each_entry_rcu(blkg, n, &blkcg->blkg_list, blkcg_node) {\
- if (blkg->dev) { \
- spin_lock_irq(&blkg->stats_lock); \
- cgroup_total += blkio_get_stat(blkg, cb, \
- blkg->dev, type); \
- spin_unlock_irq(&blkg->stats_lock); \
- } \
- } \
- if (show_total) \
- cb->fill(cb, "Total", cgroup_total); \
- rcu_read_unlock(); \
- cgroup_unlock(); \
- return 0; \
-}
-
-SHOW_FUNCTION_PER_GROUP(time, BLKIO_STAT_TIME, 0);
-SHOW_FUNCTION_PER_GROUP(sectors, BLKIO_STAT_SECTORS, 0);
-SHOW_FUNCTION_PER_GROUP(io_service_bytes, BLKIO_STAT_SERVICE_BYTES, 1);
-SHOW_FUNCTION_PER_GROUP(io_serviced, BLKIO_STAT_SERVICED, 1);
-SHOW_FUNCTION_PER_GROUP(io_service_time, BLKIO_STAT_SERVICE_TIME, 1);
-SHOW_FUNCTION_PER_GROUP(io_wait_time, BLKIO_STAT_WAIT_TIME, 1);
-SHOW_FUNCTION_PER_GROUP(io_merged, BLKIO_STAT_MERGED, 1);
-SHOW_FUNCTION_PER_GROUP(io_queued, BLKIO_STAT_QUEUED, 1);
-#ifdef CONFIG_DEBUG_BLK_CGROUP
-SHOW_FUNCTION_PER_GROUP(dequeue, BLKIO_STAT_DEQUEUE, 0);
-SHOW_FUNCTION_PER_GROUP(avg_queue_size, BLKIO_STAT_AVG_QUEUE_SIZE, 0);
-SHOW_FUNCTION_PER_GROUP(group_wait_time, BLKIO_STAT_GROUP_WAIT_TIME, 0);
-SHOW_FUNCTION_PER_GROUP(idle_time, BLKIO_STAT_IDLE_TIME, 0);
-SHOW_FUNCTION_PER_GROUP(empty_time, BLKIO_STAT_EMPTY_TIME, 0);
-#endif
-#undef SHOW_FUNCTION_PER_GROUP
-
static int blkio_check_dev_num(dev_t dev)
{
int part = 0;
@@ -652,13 +652,14 @@ static int blkio_check_dev_num(dev_t dev)
}
static int blkio_policy_parse_and_set(char *buf,
- struct blkio_policy_node *newpn)
+ struct blkio_policy_node *newpn, enum blkio_policy_id plid, int fileid)
{
char *s[4], *p, *major_s = NULL, *minor_s = NULL;
int ret;
unsigned long major, minor, temp;
int i = 0;
dev_t dev;
+ u64 bps, iops;
memset(s, 0, sizeof(s));
@@ -705,12 +706,47 @@ static int blkio_policy_parse_and_set(char *buf,
if (s[1] == NULL)
return -EINVAL;
- ret = strict_strtoul(s[1], 10, &temp);
- if (ret || (temp < BLKIO_WEIGHT_MIN && temp > 0) ||
- temp > BLKIO_WEIGHT_MAX)
- return -EINVAL;
+ switch (plid) {
+ case BLKIO_POLICY_PROP:
+ ret = strict_strtoul(s[1], 10, &temp);
+ if (ret || (temp < BLKIO_WEIGHT_MIN && temp > 0) ||
+ temp > BLKIO_WEIGHT_MAX)
+ return -EINVAL;
- newpn->weight = temp;
+ newpn->plid = plid;
+ newpn->fileid = fileid;
+ newpn->val.weight = temp;
+ break;
+ case BLKIO_POLICY_THROTL:
+ switch(fileid) {
+ case BLKIO_THROTL_read_bps_device:
+ case BLKIO_THROTL_write_bps_device:
+ ret = strict_strtoull(s[1], 10, &bps);
+ if (ret)
+ return -EINVAL;
+
+ newpn->plid = plid;
+ newpn->fileid = fileid;
+ newpn->val.bps = bps;
+ break;
+ case BLKIO_THROTL_read_iops_device:
+ case BLKIO_THROTL_write_iops_device:
+ ret = strict_strtoull(s[1], 10, &iops);
+ if (ret)
+ return -EINVAL;
+
+ if (iops > THROTL_IOPS_MAX)
+ return -EINVAL;
+
+ newpn->plid = plid;
+ newpn->fileid = fileid;
+ newpn->val.iops = (unsigned int)iops;
+ break;
+ }
+ break;
+ default:
+ BUG();
+ }
return 0;
}
@@ -720,26 +756,180 @@ unsigned int blkcg_get_weight(struct blkio_cgroup *blkcg,
{
struct blkio_policy_node *pn;
- pn = blkio_policy_search_node(blkcg, dev);
+ pn = blkio_policy_search_node(blkcg, dev, BLKIO_POLICY_PROP,
+ BLKIO_PROP_weight_device);
if (pn)
- return pn->weight;
+ return pn->val.weight;
else
return blkcg->weight;
}
EXPORT_SYMBOL_GPL(blkcg_get_weight);
+uint64_t blkcg_get_read_bps(struct blkio_cgroup *blkcg, dev_t dev)
+{
+ struct blkio_policy_node *pn;
+
+ pn = blkio_policy_search_node(blkcg, dev, BLKIO_POLICY_THROTL,
+ BLKIO_THROTL_read_bps_device);
+ if (pn)
+ return pn->val.bps;
+ else
+ return -1;
+}
+
+uint64_t blkcg_get_write_bps(struct blkio_cgroup *blkcg, dev_t dev)
+{
+ struct blkio_policy_node *pn;
+ pn = blkio_policy_search_node(blkcg, dev, BLKIO_POLICY_THROTL,
+ BLKIO_THROTL_write_bps_device);
+ if (pn)
+ return pn->val.bps;
+ else
+ return -1;
+}
+
+unsigned int blkcg_get_read_iops(struct blkio_cgroup *blkcg, dev_t dev)
+{
+ struct blkio_policy_node *pn;
+
+ pn = blkio_policy_search_node(blkcg, dev, BLKIO_POLICY_THROTL,
+ BLKIO_THROTL_read_iops_device);
+ if (pn)
+ return pn->val.iops;
+ else
+ return -1;
+}
+
+unsigned int blkcg_get_write_iops(struct blkio_cgroup *blkcg, dev_t dev)
+{
+ struct blkio_policy_node *pn;
+ pn = blkio_policy_search_node(blkcg, dev, BLKIO_POLICY_THROTL,
+ BLKIO_THROTL_write_iops_device);
+ if (pn)
+ return pn->val.iops;
+ else
+ return -1;
+}
+
+/* Checks whether user asked for deleting a policy rule */
+static bool blkio_delete_rule_command(struct blkio_policy_node *pn)
+{
+ switch(pn->plid) {
+ case BLKIO_POLICY_PROP:
+ if (pn->val.weight == 0)
+ return 1;
+ break;
+ case BLKIO_POLICY_THROTL:
+ switch(pn->fileid) {
+ case BLKIO_THROTL_read_bps_device:
+ case BLKIO_THROTL_write_bps_device:
+ if (pn->val.bps == 0)
+ return 1;
+ break;
+ case BLKIO_THROTL_read_iops_device:
+ case BLKIO_THROTL_write_iops_device:
+ if (pn->val.iops == 0)
+ return 1;
+ }
+ break;
+ default:
+ BUG();
+ }
+
+ return 0;
+}
+
+static void blkio_update_policy_rule(struct blkio_policy_node *oldpn,
+ struct blkio_policy_node *newpn)
+{
+ switch(oldpn->plid) {
+ case BLKIO_POLICY_PROP:
+ oldpn->val.weight = newpn->val.weight;
+ break;
+ case BLKIO_POLICY_THROTL:
+ switch(newpn->fileid) {
+ case BLKIO_THROTL_read_bps_device:
+ case BLKIO_THROTL_write_bps_device:
+ oldpn->val.bps = newpn->val.bps;
+ break;
+ case BLKIO_THROTL_read_iops_device:
+ case BLKIO_THROTL_write_iops_device:
+ oldpn->val.iops = newpn->val.iops;
+ }
+ break;
+ default:
+ BUG();
+ }
+}
+
+/*
+ * Some rules/values in blkg have changed. Propogate those to respective
+ * policies.
+ */
+static void blkio_update_blkg_policy(struct blkio_cgroup *blkcg,
+ struct blkio_group *blkg, struct blkio_policy_node *pn)
+{
+ unsigned int weight, iops;
+ u64 bps;
+
+ switch(pn->plid) {
+ case BLKIO_POLICY_PROP:
+ weight = pn->val.weight ? pn->val.weight :
+ blkcg->weight;
+ blkio_update_group_weight(blkg, weight);
+ break;
+ case BLKIO_POLICY_THROTL:
+ switch(pn->fileid) {
+ case BLKIO_THROTL_read_bps_device:
+ case BLKIO_THROTL_write_bps_device:
+ bps = pn->val.bps ? pn->val.bps : (-1);
+ blkio_update_group_bps(blkg, bps, pn->fileid);
+ break;
+ case BLKIO_THROTL_read_iops_device:
+ case BLKIO_THROTL_write_iops_device:
+ iops = pn->val.iops ? pn->val.iops : (-1);
+ blkio_update_group_iops(blkg, iops, pn->fileid);
+ break;
+ }
+ break;
+ default:
+ BUG();
+ }
+}
+
+/*
+ * A policy node rule has been updated. Propogate this update to all the
+ * block groups which might be affected by this update.
+ */
+static void blkio_update_policy_node_blkg(struct blkio_cgroup *blkcg,
+ struct blkio_policy_node *pn)
+{
+ struct blkio_group *blkg;
+ struct hlist_node *n;
+
+ spin_lock(&blkio_list_lock);
+ spin_lock_irq(&blkcg->lock);
+
+ hlist_for_each_entry(blkg, n, &blkcg->blkg_list, blkcg_node) {
+ if (pn->dev != blkg->dev || pn->plid != blkg->plid)
+ continue;
+ blkio_update_blkg_policy(blkcg, blkg, pn);
+ }
+
+ spin_unlock_irq(&blkcg->lock);
+ spin_unlock(&blkio_list_lock);
+}
-static int blkiocg_weight_device_write(struct cgroup *cgrp, struct cftype *cft,
- const char *buffer)
+static int blkiocg_file_write(struct cgroup *cgrp, struct cftype *cft,
+ const char *buffer)
{
int ret = 0;
char *buf;
struct blkio_policy_node *newpn, *pn;
struct blkio_cgroup *blkcg;
- struct blkio_group *blkg;
int keep_newpn = 0;
- struct hlist_node *n;
- struct blkio_policy_type *blkiop;
+ enum blkio_policy_id plid = BLKIOFILE_POLICY(cft->private);
+ int fileid = BLKIOFILE_ATTR(cft->private);
buf = kstrdup(buffer, GFP_KERNEL);
if (!buf)
@@ -751,7 +941,7 @@ static int blkiocg_weight_device_write(struct cgroup *cgrp, struct cftype *cft,
goto free_buf;
}
- ret = blkio_policy_parse_and_set(buf, newpn);
+ ret = blkio_policy_parse_and_set(buf, newpn, plid, fileid);
if (ret)
goto free_newpn;
@@ -759,9 +949,9 @@ static int blkiocg_weight_device_write(struct cgroup *cgrp, struct cftype *cft,
spin_lock_irq(&blkcg->lock);
- pn = blkio_policy_search_node(blkcg, newpn->dev);
+ pn = blkio_policy_search_node(blkcg, newpn->dev, plid, fileid);
if (!pn) {
- if (newpn->weight != 0) {
+ if (!blkio_delete_rule_command(newpn)) {
blkio_policy_insert_node(blkcg, newpn);
keep_newpn = 1;
}
@@ -769,33 +959,17 @@ static int blkiocg_weight_device_write(struct cgroup *cgrp, struct cftype *cft,
goto update_io_group;
}
- if (newpn->weight == 0) {
- /* weight == 0 means deleteing a specific weight */
+ if (blkio_delete_rule_command(newpn)) {
blkio_policy_delete_node(pn);
spin_unlock_irq(&blkcg->lock);
goto update_io_group;
}
spin_unlock_irq(&blkcg->lock);
- pn->weight = newpn->weight;
+ blkio_update_policy_rule(pn, newpn);
update_io_group:
- /* update weight for each cfqg */
- spin_lock(&blkio_list_lock);
- spin_lock_irq(&blkcg->lock);
-
- hlist_for_each_entry(blkg, n, &blkcg->blkg_list, blkcg_node) {
- if (newpn->dev == blkg->dev) {
- list_for_each_entry(blkiop, &blkio_list, list)
- blkiop->ops.blkio_update_group_weight_fn(blkg,
- newpn->weight ?
- newpn->weight :
- blkcg->weight);
- }
- }
-
- spin_unlock_irq(&blkcg->lock);
- spin_unlock(&blkio_list_lock);
+ blkio_update_policy_node_blkg(blkcg, newpn);
free_newpn:
if (!keep_newpn)
@@ -805,23 +979,256 @@ free_buf:
return ret;
}
-static int blkiocg_weight_device_read(struct cgroup *cgrp, struct cftype *cft,
- struct seq_file *m)
+static void
+blkio_print_policy_node(struct seq_file *m, struct blkio_policy_node *pn)
{
- struct blkio_cgroup *blkcg;
- struct blkio_policy_node *pn;
+ switch(pn->plid) {
+ case BLKIO_POLICY_PROP:
+ if (pn->fileid == BLKIO_PROP_weight_device)
+ seq_printf(m, "%u:%u\t%u\n", MAJOR(pn->dev),
+ MINOR(pn->dev), pn->val.weight);
+ break;
+ case BLKIO_POLICY_THROTL:
+ switch(pn->fileid) {
+ case BLKIO_THROTL_read_bps_device:
+ case BLKIO_THROTL_write_bps_device:
+ seq_printf(m, "%u:%u\t%llu\n", MAJOR(pn->dev),
+ MINOR(pn->dev), pn->val.bps);
+ break;
+ case BLKIO_THROTL_read_iops_device:
+ case BLKIO_THROTL_write_iops_device:
+ seq_printf(m, "%u:%u\t%u\n", MAJOR(pn->dev),
+ MINOR(pn->dev), pn->val.iops);
+ break;
+ }
+ break;
+ default:
+ BUG();
+ }
+}
- seq_printf(m, "dev\tweight\n");
+/* cgroup files which read their data from policy nodes end up here */
+static void blkio_read_policy_node_files(struct cftype *cft,
+ struct blkio_cgroup *blkcg, struct seq_file *m)
+{
+ struct blkio_policy_node *pn;
- blkcg = cgroup_to_blkio_cgroup(cgrp);
if (!list_empty(&blkcg->policy_list)) {
spin_lock_irq(&blkcg->lock);
list_for_each_entry(pn, &blkcg->policy_list, node) {
- seq_printf(m, "%u:%u\t%u\n", MAJOR(pn->dev),
- MINOR(pn->dev), pn->weight);
+ if (!pn_matches_cftype(cft, pn))
+ continue;
+ blkio_print_policy_node(m, pn);
}
spin_unlock_irq(&blkcg->lock);
}
+}
+
+static int blkiocg_file_read(struct cgroup *cgrp, struct cftype *cft,
+ struct seq_file *m)
+{
+ struct blkio_cgroup *blkcg;
+ enum blkio_policy_id plid = BLKIOFILE_POLICY(cft->private);
+ int name = BLKIOFILE_ATTR(cft->private);
+
+ blkcg = cgroup_to_blkio_cgroup(cgrp);
+
+ switch(plid) {
+ case BLKIO_POLICY_PROP:
+ switch(name) {
+ case BLKIO_PROP_weight_device:
+ blkio_read_policy_node_files(cft, blkcg, m);
+ return 0;
+ default:
+ BUG();
+ }
+ break;
+ case BLKIO_POLICY_THROTL:
+ switch(name){
+ case BLKIO_THROTL_read_bps_device:
+ case BLKIO_THROTL_write_bps_device:
+ case BLKIO_THROTL_read_iops_device:
+ case BLKIO_THROTL_write_iops_device:
+ blkio_read_policy_node_files(cft, blkcg, m);
+ return 0;
+ default:
+ BUG();
+ }
+ break;
+ default:
+ BUG();
+ }
+
+ return 0;
+}
+
+static int blkio_read_blkg_stats(struct blkio_cgroup *blkcg,
+ struct cftype *cft, struct cgroup_map_cb *cb, enum stat_type type,
+ bool show_total)
+{
+ struct blkio_group *blkg;
+ struct hlist_node *n;
+ uint64_t cgroup_total = 0;
+
+ rcu_read_lock();
+ hlist_for_each_entry_rcu(blkg, n, &blkcg->blkg_list, blkcg_node) {
+ if (blkg->dev) {
+ if (!cftype_blkg_same_policy(cft, blkg))
+ continue;
+ spin_lock_irq(&blkg->stats_lock);
+ cgroup_total += blkio_get_stat(blkg, cb, blkg->dev,
+ type);
+ spin_unlock_irq(&blkg->stats_lock);
+ }
+ }
+ if (show_total)
+ cb->fill(cb, "Total", cgroup_total);
+ rcu_read_unlock();
+ return 0;
+}
+
+/* All map kind of cgroup file get serviced by this function */
+static int blkiocg_file_read_map(struct cgroup *cgrp, struct cftype *cft,
+ struct cgroup_map_cb *cb)
+{
+ struct blkio_cgroup *blkcg;
+ enum blkio_policy_id plid = BLKIOFILE_POLICY(cft->private);
+ int name = BLKIOFILE_ATTR(cft->private);
+
+ blkcg = cgroup_to_blkio_cgroup(cgrp);
+
+ switch(plid) {
+ case BLKIO_POLICY_PROP:
+ switch(name) {
+ case BLKIO_PROP_time:
+ return blkio_read_blkg_stats(blkcg, cft, cb,
+ BLKIO_STAT_TIME, 0);
+ case BLKIO_PROP_sectors:
+ return blkio_read_blkg_stats(blkcg, cft, cb,
+ BLKIO_STAT_SECTORS, 0);
+ case BLKIO_PROP_io_service_bytes:
+ return blkio_read_blkg_stats(blkcg, cft, cb,
+ BLKIO_STAT_SERVICE_BYTES, 1);
+ case BLKIO_PROP_io_serviced:
+ return blkio_read_blkg_stats(blkcg, cft, cb,
+ BLKIO_STAT_SERVICED, 1);
+ case BLKIO_PROP_io_service_time:
+ return blkio_read_blkg_stats(blkcg, cft, cb,
+ BLKIO_STAT_SERVICE_TIME, 1);
+ case BLKIO_PROP_io_wait_time:
+ return blkio_read_blkg_stats(blkcg, cft, cb,
+ BLKIO_STAT_WAIT_TIME, 1);
+ case BLKIO_PROP_io_merged:
+ return blkio_read_blkg_stats(blkcg, cft, cb,
+ BLKIO_STAT_MERGED, 1);
+ case BLKIO_PROP_io_queued:
+ return blkio_read_blkg_stats(blkcg, cft, cb,
+ BLKIO_STAT_QUEUED, 1);
+#ifdef CONFIG_DEBUG_BLK_CGROUP
+ case BLKIO_PROP_dequeue:
+ return blkio_read_blkg_stats(blkcg, cft, cb,
+ BLKIO_STAT_DEQUEUE, 0);
+ case BLKIO_PROP_avg_queue_size:
+ return blkio_read_blkg_stats(blkcg, cft, cb,
+ BLKIO_STAT_AVG_QUEUE_SIZE, 0);
+ case BLKIO_PROP_group_wait_time:
+ return blkio_read_blkg_stats(blkcg, cft, cb,
+ BLKIO_STAT_GROUP_WAIT_TIME, 0);
+ case BLKIO_PROP_idle_time:
+ return blkio_read_blkg_stats(blkcg, cft, cb,
+ BLKIO_STAT_IDLE_TIME, 0);
+ case BLKIO_PROP_empty_time:
+ return blkio_read_blkg_stats(blkcg, cft, cb,
+ BLKIO_STAT_EMPTY_TIME, 0);
+#endif
+ default:
+ BUG();
+ }
+ break;
+ case BLKIO_POLICY_THROTL:
+ switch(name){
+ case BLKIO_THROTL_io_service_bytes:
+ return blkio_read_blkg_stats(blkcg, cft, cb,
+ BLKIO_STAT_SERVICE_BYTES, 1);
+ case BLKIO_THROTL_io_serviced:
+ return blkio_read_blkg_stats(blkcg, cft, cb,
+ BLKIO_STAT_SERVICED, 1);
+ default:
+ BUG();
+ }
+ break;
+ default:
+ BUG();
+ }
+
+ return 0;
+}
+
+static int blkio_weight_write(struct blkio_cgroup *blkcg, u64 val)
+{
+ struct blkio_group *blkg;
+ struct hlist_node *n;
+ struct blkio_policy_node *pn;
+
+ if (val < BLKIO_WEIGHT_MIN || val > BLKIO_WEIGHT_MAX)
+ return -EINVAL;
+
+ spin_lock(&blkio_list_lock);
+ spin_lock_irq(&blkcg->lock);
+ blkcg->weight = (unsigned int)val;
+
+ hlist_for_each_entry(blkg, n, &blkcg->blkg_list, blkcg_node) {
+ pn = blkio_policy_search_node(blkcg, blkg->dev,
+ BLKIO_POLICY_PROP, BLKIO_PROP_weight_device);
+ if (pn)
+ continue;
+
+ blkio_update_group_weight(blkg, blkcg->weight);
+ }
+ spin_unlock_irq(&blkcg->lock);
+ spin_unlock(&blkio_list_lock);
+ return 0;
+}
+
+static u64 blkiocg_file_read_u64 (struct cgroup *cgrp, struct cftype *cft) {
+ struct blkio_cgroup *blkcg;
+ enum blkio_policy_id plid = BLKIOFILE_POLICY(cft->private);
+ int name = BLKIOFILE_ATTR(cft->private);
+
+ blkcg = cgroup_to_blkio_cgroup(cgrp);
+
+ switch(plid) {
+ case BLKIO_POLICY_PROP:
+ switch(name) {
+ case BLKIO_PROP_weight:
+ return (u64)blkcg->weight;
+ }
+ break;
+ default:
+ BUG();
+ }
+ return 0;
+}
+
+static int
+blkiocg_file_write_u64(struct cgroup *cgrp, struct cftype *cft, u64 val)
+{
+ struct blkio_cgroup *blkcg;
+ enum blkio_policy_id plid = BLKIOFILE_POLICY(cft->private);
+ int name = BLKIOFILE_ATTR(cft->private);
+
+ blkcg = cgroup_to_blkio_cgroup(cgrp);
+
+ switch(plid) {
+ case BLKIO_POLICY_PROP:
+ switch(name) {
+ case BLKIO_PROP_weight:
+ return blkio_weight_write(blkcg, val);
+ }
+ break;
+ default:
+ BUG();
+ }
return 0;
}
@@ -829,71 +1236,151 @@ static int blkiocg_weight_device_read(struct cgroup *cgrp, struct cftype *cft,
struct cftype blkio_files[] = {
{
.name = "weight_device",
- .read_seq_string = blkiocg_weight_device_read,
- .write_string = blkiocg_weight_device_write,
+ .private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
+ BLKIO_PROP_weight_device),
+ .read_seq_string = blkiocg_file_read,
+ .write_string = blkiocg_file_write,
.max_write_len = 256,
},
{
.name = "weight",
- .read_u64 = blkiocg_weight_read,
- .write_u64 = blkiocg_weight_write,
+ .private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
+ BLKIO_PROP_weight),
+ .read_u64 = blkiocg_file_read_u64,
+ .write_u64 = blkiocg_file_write_u64,
},
{
.name = "time",
- .read_map = blkiocg_time_read,
+ .private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
+ BLKIO_PROP_time),
+ .read_map = blkiocg_file_read_map,
},
{
.name = "sectors",
- .read_map = blkiocg_sectors_read,
+ .private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
+ BLKIO_PROP_sectors),
+ .read_map = blkiocg_file_read_map,
},
{
.name = "io_service_bytes",
- .read_map = blkiocg_io_service_bytes_read,
+ .private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
+ BLKIO_PROP_io_service_bytes),
+ .read_map = blkiocg_file_read_map,
},
{
.name = "io_serviced",
- .read_map = blkiocg_io_serviced_read,
+ .private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
+ BLKIO_PROP_io_serviced),
+ .read_map = blkiocg_file_read_map,
},
{
.name = "io_service_time",
- .read_map = blkiocg_io_service_time_read,
+ .private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
+ BLKIO_PROP_io_service_time),
+ .read_map = blkiocg_file_read_map,
},
{
.name = "io_wait_time",
- .read_map = blkiocg_io_wait_time_read,
+ .private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
+ BLKIO_PROP_io_wait_time),
+ .read_map = blkiocg_file_read_map,
},
{
.name = "io_merged",
- .read_map = blkiocg_io_merged_read,
+ .private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
+ BLKIO_PROP_io_merged),
+ .read_map = blkiocg_file_read_map,
},
{
.name = "io_queued",
- .read_map = blkiocg_io_queued_read,
+ .private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
+ BLKIO_PROP_io_queued),
+ .read_map = blkiocg_file_read_map,
},
{
.name = "reset_stats",
.write_u64 = blkiocg_reset_stats,
},
+#ifdef CONFIG_BLK_DEV_THROTTLING
+ {
+ .name = "throttle.read_bps_device",
+ .private = BLKIOFILE_PRIVATE(BLKIO_POLICY_THROTL,
+ BLKIO_THROTL_read_bps_device),
+ .read_seq_string = blkiocg_file_read,
+ .write_string = blkiocg_file_write,
+ .max_write_len = 256,
+ },
+
+ {
+ .name = "throttle.write_bps_device",
+ .private = BLKIOFILE_PRIVATE(BLKIO_POLICY_THROTL,
+ BLKIO_THROTL_write_bps_device),
+ .read_seq_string = blkiocg_file_read,
+ .write_string = blkiocg_file_write,
+ .max_write_len = 256,
+ },
+
+ {
+ .name = "throttle.read_iops_device",
+ .private = BLKIOFILE_PRIVATE(BLKIO_POLICY_THROTL,
+ BLKIO_THROTL_read_iops_device),
+ .read_seq_string = blkiocg_file_read,
+ .write_string = blkiocg_file_write,
+ .max_write_len = 256,
+ },
+
+ {
+ .name = "throttle.write_iops_device",
+ .private = BLKIOFILE_PRIVATE(BLKIO_POLICY_THROTL,
+ BLKIO_THROTL_write_iops_device),
+ .read_seq_string = blkiocg_file_read,
+ .write_string = blkiocg_file_write,
+ .max_write_len = 256,
+ },
+ {
+ .name = "throttle.io_service_bytes",
+ .private = BLKIOFILE_PRIVATE(BLKIO_POLICY_THROTL,
+ BLKIO_THROTL_io_service_bytes),
+ .read_map = blkiocg_file_read_map,
+ },
+ {
+ .name = "throttle.io_serviced",
+ .private = BLKIOFILE_PRIVATE(BLKIO_POLICY_THROTL,
+ BLKIO_THROTL_io_serviced),
+ .read_map = blkiocg_file_read_map,
+ },
+#endif /* CONFIG_BLK_DEV_THROTTLING */
+
#ifdef CONFIG_DEBUG_BLK_CGROUP
{
.name = "avg_queue_size",
- .read_map = blkiocg_avg_queue_size_read,
+ .private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
+ BLKIO_PROP_avg_queue_size),
+ .read_map = blkiocg_file_read_map,
},
{
.name = "group_wait_time",
- .read_map = blkiocg_group_wait_time_read,
+ .private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
+ BLKIO_PROP_group_wait_time),
+ .read_map = blkiocg_file_read_map,
},
{
.name = "idle_time",
- .read_map = blkiocg_idle_time_read,
+ .private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
+ BLKIO_PROP_idle_time),
+ .read_map = blkiocg_file_read_map,
},
{
.name = "empty_time",
- .read_map = blkiocg_empty_time_read,
+ .private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
+ BLKIO_PROP_empty_time),
+ .read_map = blkiocg_file_read_map,
},
{
.name = "dequeue",
- .read_map = blkiocg_dequeue_read,
+ .private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
+ BLKIO_PROP_dequeue),
+ .read_map = blkiocg_file_read_map,
},
#endif
};
@@ -932,13 +1419,14 @@ static void blkiocg_destroy(struct cgroup_subsys *subsys, struct cgroup *cgroup)
/*
* This blkio_group is being unlinked as associated cgroup is
* going away. Let all the IO controlling policies know about
- * this event. Currently this is static call to one io
- * controlling policy. Once we have more policies in place, we
- * need some dynamic registration of callback function.
+ * this event.
*/
spin_lock(&blkio_list_lock);
- list_for_each_entry(blkiop, &blkio_list, list)
+ list_for_each_entry(blkiop, &blkio_list, list) {
+ if (blkiop->plid != blkg->plid)
+ continue;
blkiop->ops.blkio_unlink_group_fn(key, blkg);
+ }
spin_unlock(&blkio_list_lock);
} while (1);
diff --git a/block/blk-cgroup.h b/block/blk-cgroup.h
index 2b866ec1dcea..ea4861bdd549 100644
--- a/block/blk-cgroup.h
+++ b/block/blk-cgroup.h
@@ -15,6 +15,14 @@
#include <linux/cgroup.h>
+enum blkio_policy_id {
+ BLKIO_POLICY_PROP = 0, /* Proportional Bandwidth division */
+ BLKIO_POLICY_THROTL, /* Throttling */
+};
+
+/* Max limits for throttle policy */
+#define THROTL_IOPS_MAX UINT_MAX
+
#if defined(CONFIG_BLK_CGROUP) || defined(CONFIG_BLK_CGROUP_MODULE)
#ifndef CONFIG_BLK_CGROUP
@@ -65,6 +73,35 @@ enum blkg_state_flags {
BLKG_empty,
};
+/* cgroup files owned by proportional weight policy */
+enum blkcg_file_name_prop {
+ BLKIO_PROP_weight = 1,
+ BLKIO_PROP_weight_device,
+ BLKIO_PROP_io_service_bytes,
+ BLKIO_PROP_io_serviced,
+ BLKIO_PROP_time,
+ BLKIO_PROP_sectors,
+ BLKIO_PROP_io_service_time,
+ BLKIO_PROP_io_wait_time,
+ BLKIO_PROP_io_merged,
+ BLKIO_PROP_io_queued,
+ BLKIO_PROP_avg_queue_size,
+ BLKIO_PROP_group_wait_time,
+ BLKIO_PROP_idle_time,
+ BLKIO_PROP_empty_time,
+ BLKIO_PROP_dequeue,
+};
+
+/* cgroup files owned by throttle policy */
+enum blkcg_file_name_throtl {
+ BLKIO_THROTL_read_bps_device,
+ BLKIO_THROTL_write_bps_device,
+ BLKIO_THROTL_read_iops_device,
+ BLKIO_THROTL_write_iops_device,
+ BLKIO_THROTL_io_service_bytes,
+ BLKIO_THROTL_io_serviced,
+};
+
struct blkio_cgroup {
struct cgroup_subsys_state css;
unsigned int weight;
@@ -112,6 +149,8 @@ struct blkio_group {
char path[128];
/* The device MKDEV(major, minor), this group has been created for */
dev_t dev;
+ /* policy which owns this blk group */
+ enum blkio_policy_id plid;
/* Need to serialize the stats in the case of reset/update */
spinlock_t stats_lock;
@@ -121,24 +160,60 @@ struct blkio_group {
struct blkio_policy_node {
struct list_head node;
dev_t dev;
- unsigned int weight;
+ /* This node belongs to max bw policy or porportional weight policy */
+ enum blkio_policy_id plid;
+ /* cgroup file to which this rule belongs to */
+ int fileid;
+
+ union {
+ unsigned int weight;
+ /*
+ * Rate read/write in terms of byptes per second
+ * Whether this rate represents read or write is determined
+ * by file type "fileid".
+ */
+ u64 bps;
+ unsigned int iops;
+ } val;
};
extern unsigned int blkcg_get_weight(struct blkio_cgroup *blkcg,
dev_t dev);
+extern uint64_t blkcg_get_read_bps(struct blkio_cgroup *blkcg,
+ dev_t dev);
+extern uint64_t blkcg_get_write_bps(struct blkio_cgroup *blkcg,
+ dev_t dev);
+extern unsigned int blkcg_get_read_iops(struct blkio_cgroup *blkcg,
+ dev_t dev);
+extern unsigned int blkcg_get_write_iops(struct blkio_cgroup *blkcg,
+ dev_t dev);
typedef void (blkio_unlink_group_fn) (void *key, struct blkio_group *blkg);
-typedef void (blkio_update_group_weight_fn) (struct blkio_group *blkg,
- unsigned int weight);
+
+typedef void (blkio_update_group_weight_fn) (void *key,
+ struct blkio_group *blkg, unsigned int weight);
+typedef void (blkio_update_group_read_bps_fn) (void * key,
+ struct blkio_group *blkg, u64 read_bps);
+typedef void (blkio_update_group_write_bps_fn) (void *key,
+ struct blkio_group *blkg, u64 write_bps);
+typedef void (blkio_update_group_read_iops_fn) (void *key,
+ struct blkio_group *blkg, unsigned int read_iops);
+typedef void (blkio_update_group_write_iops_fn) (void *key,
+ struct blkio_group *blkg, unsigned int write_iops);
struct blkio_policy_ops {
blkio_unlink_group_fn *blkio_unlink_group_fn;
blkio_update_group_weight_fn *blkio_update_group_weight_fn;
+ blkio_update_group_read_bps_fn *blkio_update_group_read_bps_fn;
+ blkio_update_group_write_bps_fn *blkio_update_group_write_bps_fn;
+ blkio_update_group_read_iops_fn *blkio_update_group_read_iops_fn;
+ blkio_update_group_write_iops_fn *blkio_update_group_write_iops_fn;
};
struct blkio_policy_type {
struct list_head list;
struct blkio_policy_ops ops;
+ enum blkio_policy_id plid;
};
/* Blkio controller policy registration */
@@ -212,7 +287,8 @@ static inline void blkiocg_set_start_empty_time(struct blkio_group *blkg) {}
extern struct blkio_cgroup blkio_root_cgroup;
extern struct blkio_cgroup *cgroup_to_blkio_cgroup(struct cgroup *cgroup);
extern void blkiocg_add_blkio_group(struct blkio_cgroup *blkcg,
- struct blkio_group *blkg, void *key, dev_t dev);
+ struct blkio_group *blkg, void *key, dev_t dev,
+ enum blkio_policy_id plid);
extern int blkiocg_del_blkio_group(struct blkio_group *blkg);
extern struct blkio_group *blkiocg_lookup_group(struct blkio_cgroup *blkcg,
void *key);
@@ -234,7 +310,8 @@ static inline struct blkio_cgroup *
cgroup_to_blkio_cgroup(struct cgroup *cgroup) { return NULL; }
static inline void blkiocg_add_blkio_group(struct blkio_cgroup *blkcg,
- struct blkio_group *blkg, void *key, dev_t dev) {}
+ struct blkio_group *blkg, void *key, dev_t dev,
+ enum blkio_policy_id plid) {}
static inline int
blkiocg_del_blkio_group(struct blkio_group *blkg) { return 0; }
diff --git a/block/blk-core.c b/block/blk-core.c
index 32a1c123dfb3..51efd835d4cf 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -64,13 +64,15 @@ static void drive_stat_acct(struct request *rq, int new_io)
return;
cpu = part_stat_lock();
- part = disk_map_sector_rcu(rq->rq_disk, blk_rq_pos(rq));
- if (!new_io)
+ if (!new_io) {
+ part = rq->part;
part_stat_inc(cpu, part, merges[rw]);
- else {
+ } else {
+ part = disk_map_sector_rcu(rq->rq_disk, blk_rq_pos(rq));
part_round_stats(cpu, part);
part_inc_in_flight(part, rw);
+ rq->part = part;
}
part_stat_unlock();
@@ -128,6 +130,7 @@ void blk_rq_init(struct request_queue *q, struct request *rq)
rq->ref_count = 1;
rq->start_time = jiffies;
set_start_time_ns(rq);
+ rq->part = NULL;
}
EXPORT_SYMBOL(blk_rq_init);
@@ -136,7 +139,7 @@ static void req_bio_endio(struct request *rq, struct bio *bio,
{
struct request_queue *q = rq->q;
- if (&q->bar_rq != rq) {
+ if (&q->flush_rq != rq) {
if (error)
clear_bit(BIO_UPTODATE, &bio->bi_flags);
else if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
@@ -160,13 +163,12 @@ static void req_bio_endio(struct request *rq, struct bio *bio,
if (bio->bi_size == 0)
bio_endio(bio, error);
} else {
-
/*
- * Okay, this is the barrier request in progress, just
- * record the error;
+ * Okay, this is the sequenced flush request in
+ * progress, just record the error;
*/
- if (error && !q->orderr)
- q->orderr = error;
+ if (error && !q->flush_err)
+ q->flush_err = error;
}
}
@@ -382,6 +384,7 @@ void blk_sync_queue(struct request_queue *q)
del_timer_sync(&q->unplug_timer);
del_timer_sync(&q->timeout);
cancel_work_sync(&q->unplug_work);
+ throtl_shutdown_timer_wq(q);
}
EXPORT_SYMBOL(blk_sync_queue);
@@ -515,11 +518,17 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id)
return NULL;
}
+ if (blk_throtl_init(q)) {
+ kmem_cache_free(blk_requestq_cachep, q);
+ return NULL;
+ }
+
setup_timer(&q->backing_dev_info.laptop_mode_wb_timer,
laptop_mode_timer_fn, (unsigned long) q);
init_timer(&q->unplug_timer);
setup_timer(&q->timeout, blk_rq_timed_out_timer, (unsigned long) q);
INIT_LIST_HEAD(&q->timeout_list);
+ INIT_LIST_HEAD(&q->pending_flushes);
INIT_WORK(&q->unplug_work, blk_unplug_work);
kobject_init(&q->kobj, &blk_queue_ktype);
@@ -796,11 +805,16 @@ static struct request *get_request(struct request_queue *q, int rw_flags,
rl->starved[is_sync] = 0;
priv = !test_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
- if (priv)
+ if (priv) {
rl->elvpriv++;
- if (blk_queue_io_stat(q))
- rw_flags |= REQ_IO_STAT;
+ /*
+ * Don't do stats for non-priv requests
+ */
+ if (blk_queue_io_stat(q))
+ rw_flags |= REQ_IO_STAT;
+ }
+
spin_unlock_irq(q->queue_lock);
rq = blk_alloc_request(q, rw_flags, priv, gfp_mask);
@@ -1037,22 +1051,6 @@ void blk_insert_request(struct request_queue *q, struct request *rq,
}
EXPORT_SYMBOL(blk_insert_request);
-/*
- * add-request adds a request to the linked list.
- * queue lock is held and interrupts disabled, as we muck with the
- * request queue list.
- */
-static inline void add_request(struct request_queue *q, struct request *req)
-{
- drive_stat_acct(req, 1);
-
- /*
- * elevator indicated where it wants this request to be
- * inserted at elevator_merge time
- */
- __elv_add_request(q, req, ELEVATOR_INSERT_SORT, 0);
-}
-
static void part_round_stats_single(int cpu, struct hd_struct *part,
unsigned long now)
{
@@ -1201,13 +1199,16 @@ static int __make_request(struct request_queue *q, struct bio *bio)
const bool sync = !!(bio->bi_rw & REQ_SYNC);
const bool unplug = !!(bio->bi_rw & REQ_UNPLUG);
const unsigned long ff = bio->bi_rw & REQ_FAILFAST_MASK;
+ int where = ELEVATOR_INSERT_SORT;
int rw_flags;
- if ((bio->bi_rw & REQ_HARDBARRIER) &&
- (q->next_ordered == QUEUE_ORDERED_NONE)) {
+ /* REQ_HARDBARRIER is no more */
+ if (WARN_ONCE(bio->bi_rw & REQ_HARDBARRIER,
+ "block: HARDBARRIER is deprecated, use FLUSH/FUA instead\n")) {
bio_endio(bio, -EOPNOTSUPP);
return 0;
}
+
/*
* low level driver can indicate that it wants pages above a
* certain limit bounced to low memory (ie for highmem, or even
@@ -1217,7 +1218,12 @@ static int __make_request(struct request_queue *q, struct bio *bio)
spin_lock_irq(q->queue_lock);
- if (unlikely((bio->bi_rw & REQ_HARDBARRIER)) || elv_queue_empty(q))
+ if (bio->bi_rw & (REQ_FLUSH | REQ_FUA)) {
+ where = ELEVATOR_INSERT_FRONT;
+ goto get_rq;
+ }
+
+ if (elv_queue_empty(q))
goto get_rq;
el_ret = elv_merge(q, &req, bio);
@@ -1314,7 +1320,10 @@ get_rq:
req->cpu = blk_cpu_to_group(smp_processor_id());
if (queue_should_plug(q) && elv_queue_empty(q))
blk_plug_device(q);
- add_request(q, req);
+
+ /* insert the request into the elevator */
+ drive_stat_acct(req, 1);
+ __elv_add_request(q, req, where, 0);
out:
if (unplug || !queue_should_plug(q))
__generic_unplug_device(q);
@@ -1514,6 +1523,19 @@ static inline void __generic_make_request(struct bio *bio)
if (bio_check_eod(bio, nr_sectors))
goto end_io;
+ /*
+ * Filter flush bio's early so that make_request based
+ * drivers without flush support don't have to worry
+ * about them.
+ */
+ if ((bio->bi_rw & (REQ_FLUSH | REQ_FUA)) && !q->flush_flags) {
+ bio->bi_rw &= ~(REQ_FLUSH | REQ_FUA);
+ if (!nr_sectors) {
+ err = 0;
+ goto end_io;
+ }
+ }
+
if ((bio->bi_rw & REQ_DISCARD) &&
(!blk_queue_discard(q) ||
((bio->bi_rw & REQ_SECURE) &&
@@ -1522,6 +1544,15 @@ static inline void __generic_make_request(struct bio *bio)
goto end_io;
}
+ blk_throtl_bio(q, &bio);
+
+ /*
+ * If bio = NULL, bio has been throttled and will be submitted
+ * later.
+ */
+ if (!bio)
+ break;
+
trace_block_bio_queue(q, bio);
ret = q->make_request_fn(q, bio);
@@ -1612,11 +1643,12 @@ void submit_bio(int rw, struct bio *bio)
if (unlikely(block_dump)) {
char b[BDEVNAME_SIZE];
- printk(KERN_DEBUG "%s(%d): %s block %Lu on %s\n",
+ printk(KERN_DEBUG "%s(%d): %s block %Lu on %s (%u sectors)\n",
current->comm, task_pid_nr(current),
(rw & WRITE) ? "WRITE" : "READ",
(unsigned long long)bio->bi_sector,
- bdevname(bio->bi_bdev, b));
+ bdevname(bio->bi_bdev, b),
+ count);
}
}
@@ -1759,7 +1791,7 @@ static void blk_account_io_completion(struct request *req, unsigned int bytes)
int cpu;
cpu = part_stat_lock();
- part = disk_map_sector_rcu(req->rq_disk, blk_rq_pos(req));
+ part = req->part;
part_stat_add(cpu, part, sectors[rw], bytes >> 9);
part_stat_unlock();
}
@@ -1768,18 +1800,18 @@ static void blk_account_io_completion(struct request *req, unsigned int bytes)
static void blk_account_io_done(struct request *req)
{
/*
- * Account IO completion. bar_rq isn't accounted as a normal
- * IO on queueing nor completion. Accounting the containing
- * request is enough.
+ * Account IO completion. flush_rq isn't accounted as a
+ * normal IO on queueing nor completion. Accounting the
+ * containing request is enough.
*/
- if (blk_do_io_stat(req) && req != &req->q->bar_rq) {
+ if (blk_do_io_stat(req) && req != &req->q->flush_rq) {
unsigned long duration = jiffies - req->start_time;
const int rw = rq_data_dir(req);
struct hd_struct *part;
int cpu;
cpu = part_stat_lock();
- part = disk_map_sector_rcu(req->rq_disk, blk_rq_pos(req));
+ part = req->part;
part_stat_inc(cpu, part, ios[rw]);
part_stat_add(cpu, part, ticks[rw], duration);
@@ -2497,9 +2529,7 @@ EXPORT_SYMBOL_GPL(blk_rq_unprep_clone);
static void __blk_rq_prep_clone(struct request *dst, struct request *src)
{
dst->cpu = src->cpu;
- dst->cmd_flags = (rq_data_dir(src) | REQ_NOMERGE);
- if (src->cmd_flags & REQ_DISCARD)
- dst->cmd_flags |= REQ_DISCARD;
+ dst->cmd_flags = (src->cmd_flags & REQ_CLONE_MASK) | REQ_NOMERGE;
dst->cmd_type = src->cmd_type;
dst->__sector = blk_rq_pos(src);
dst->__data_len = blk_rq_bytes(src);
@@ -2579,6 +2609,13 @@ int kblockd_schedule_work(struct request_queue *q, struct work_struct *work)
}
EXPORT_SYMBOL(kblockd_schedule_work);
+int kblockd_schedule_delayed_work(struct request_queue *q,
+ struct delayed_work *dwork, unsigned long delay)
+{
+ return queue_delayed_work(kblockd_workqueue, dwork, delay);
+}
+EXPORT_SYMBOL(kblockd_schedule_delayed_work);
+
int __init blk_dev_init(void)
{
BUILD_BUG_ON(__REQ_NR_BITS > 8 *
diff --git a/block/blk-exec.c b/block/blk-exec.c
index e1672f14840e..cf1456a02acd 100644
--- a/block/blk-exec.c
+++ b/block/blk-exec.c
@@ -80,6 +80,7 @@ int blk_execute_rq(struct request_queue *q, struct gendisk *bd_disk,
DECLARE_COMPLETION_ONSTACK(wait);
char sense[SCSI_SENSE_BUFFERSIZE];
int err = 0;
+ unsigned long hang_check;
/*
* we need an extra reference to the request, so we can look at
@@ -95,7 +96,13 @@ int blk_execute_rq(struct request_queue *q, struct gendisk *bd_disk,
rq->end_io_data = &wait;
blk_execute_rq_nowait(q, bd_disk, rq, at_head, blk_end_sync_rq);
- wait_for_completion(&wait);
+
+ /* Prevent hang_check timer from firing at us during very long I/O */
+ hang_check = sysctl_hung_task_timeout_secs;
+ if (hang_check)
+ while (!wait_for_completion_timeout(&wait, hang_check * (HZ/2)));
+ else
+ wait_for_completion(&wait);
if (rq->errors)
err = -EIO;
diff --git a/block/blk-flush.c b/block/blk-flush.c
new file mode 100644
index 000000000000..54b123d6563e
--- /dev/null
+++ b/block/blk-flush.c
@@ -0,0 +1,262 @@
+/*
+ * Functions to sequence FLUSH and FUA writes.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/bio.h>
+#include <linux/blkdev.h>
+#include <linux/gfp.h>
+
+#include "blk.h"
+
+/* FLUSH/FUA sequences */
+enum {
+ QUEUE_FSEQ_STARTED = (1 << 0), /* flushing in progress */
+ QUEUE_FSEQ_PREFLUSH = (1 << 1), /* pre-flushing in progress */
+ QUEUE_FSEQ_DATA = (1 << 2), /* data write in progress */
+ QUEUE_FSEQ_POSTFLUSH = (1 << 3), /* post-flushing in progress */
+ QUEUE_FSEQ_DONE = (1 << 4),
+};
+
+static struct request *queue_next_fseq(struct request_queue *q);
+
+unsigned blk_flush_cur_seq(struct request_queue *q)
+{
+ if (!q->flush_seq)
+ return 0;
+ return 1 << ffz(q->flush_seq);
+}
+
+static struct request *blk_flush_complete_seq(struct request_queue *q,
+ unsigned seq, int error)
+{
+ struct request *next_rq = NULL;
+
+ if (error && !q->flush_err)
+ q->flush_err = error;
+
+ BUG_ON(q->flush_seq & seq);
+ q->flush_seq |= seq;
+
+ if (blk_flush_cur_seq(q) != QUEUE_FSEQ_DONE) {
+ /* not complete yet, queue the next flush sequence */
+ next_rq = queue_next_fseq(q);
+ } else {
+ /* complete this flush request */
+ __blk_end_request_all(q->orig_flush_rq, q->flush_err);
+ q->orig_flush_rq = NULL;
+ q->flush_seq = 0;
+
+ /* dispatch the next flush if there's one */
+ if (!list_empty(&q->pending_flushes)) {
+ next_rq = list_entry_rq(q->pending_flushes.next);
+ list_move(&next_rq->queuelist, &q->queue_head);
+ }
+ }
+ return next_rq;
+}
+
+static void blk_flush_complete_seq_end_io(struct request_queue *q,
+ unsigned seq, int error)
+{
+ bool was_empty = elv_queue_empty(q);
+ struct request *next_rq;
+
+ next_rq = blk_flush_complete_seq(q, seq, error);
+
+ /*
+ * Moving a request silently to empty queue_head may stall the
+ * queue. Kick the queue in those cases.
+ */
+ if (was_empty && next_rq)
+ __blk_run_queue(q);
+}
+
+static void pre_flush_end_io(struct request *rq, int error)
+{
+ elv_completed_request(rq->q, rq);
+ blk_flush_complete_seq_end_io(rq->q, QUEUE_FSEQ_PREFLUSH, error);
+}
+
+static void flush_data_end_io(struct request *rq, int error)
+{
+ elv_completed_request(rq->q, rq);
+ blk_flush_complete_seq_end_io(rq->q, QUEUE_FSEQ_DATA, error);
+}
+
+static void post_flush_end_io(struct request *rq, int error)
+{
+ elv_completed_request(rq->q, rq);
+ blk_flush_complete_seq_end_io(rq->q, QUEUE_FSEQ_POSTFLUSH, error);
+}
+
+static void init_flush_request(struct request *rq, struct gendisk *disk)
+{
+ rq->cmd_type = REQ_TYPE_FS;
+ rq->cmd_flags = WRITE_FLUSH;
+ rq->rq_disk = disk;
+}
+
+static struct request *queue_next_fseq(struct request_queue *q)
+{
+ struct request *orig_rq = q->orig_flush_rq;
+ struct request *rq = &q->flush_rq;
+
+ blk_rq_init(q, rq);
+
+ switch (blk_flush_cur_seq(q)) {
+ case QUEUE_FSEQ_PREFLUSH:
+ init_flush_request(rq, orig_rq->rq_disk);
+ rq->end_io = pre_flush_end_io;
+ break;
+ case QUEUE_FSEQ_DATA:
+ init_request_from_bio(rq, orig_rq->bio);
+ /*
+ * orig_rq->rq_disk may be different from
+ * bio->bi_bdev->bd_disk if orig_rq got here through
+ * remapping drivers. Make sure rq->rq_disk points
+ * to the same one as orig_rq.
+ */
+ rq->rq_disk = orig_rq->rq_disk;
+ rq->cmd_flags &= ~(REQ_FLUSH | REQ_FUA);
+ rq->cmd_flags |= orig_rq->cmd_flags & (REQ_FLUSH | REQ_FUA);
+ rq->end_io = flush_data_end_io;
+ break;
+ case QUEUE_FSEQ_POSTFLUSH:
+ init_flush_request(rq, orig_rq->rq_disk);
+ rq->end_io = post_flush_end_io;
+ break;
+ default:
+ BUG();
+ }
+
+ elv_insert(q, rq, ELEVATOR_INSERT_FRONT);
+ return rq;
+}
+
+struct request *blk_do_flush(struct request_queue *q, struct request *rq)
+{
+ unsigned int fflags = q->flush_flags; /* may change, cache it */
+ bool has_flush = fflags & REQ_FLUSH, has_fua = fflags & REQ_FUA;
+ bool do_preflush = has_flush && (rq->cmd_flags & REQ_FLUSH);
+ bool do_postflush = has_flush && !has_fua && (rq->cmd_flags & REQ_FUA);
+ unsigned skip = 0;
+
+ /*
+ * Special case. If there's data but flush is not necessary,
+ * the request can be issued directly.
+ *
+ * Flush w/o data should be able to be issued directly too but
+ * currently some drivers assume that rq->bio contains
+ * non-zero data if it isn't NULL and empty FLUSH requests
+ * getting here usually have bio's without data.
+ */
+ if (blk_rq_sectors(rq) && !do_preflush && !do_postflush) {
+ rq->cmd_flags &= ~REQ_FLUSH;
+ if (!has_fua)
+ rq->cmd_flags &= ~REQ_FUA;
+ return rq;
+ }
+
+ /*
+ * Sequenced flushes can't be processed in parallel. If
+ * another one is already in progress, queue for later
+ * processing.
+ */
+ if (q->flush_seq) {
+ list_move_tail(&rq->queuelist, &q->pending_flushes);
+ return NULL;
+ }
+
+ /*
+ * Start a new flush sequence
+ */
+ q->flush_err = 0;
+ q->flush_seq |= QUEUE_FSEQ_STARTED;
+
+ /* adjust FLUSH/FUA of the original request and stash it away */
+ rq->cmd_flags &= ~REQ_FLUSH;
+ if (!has_fua)
+ rq->cmd_flags &= ~REQ_FUA;
+ blk_dequeue_request(rq);
+ q->orig_flush_rq = rq;
+
+ /* skip unneded sequences and return the first one */
+ if (!do_preflush)
+ skip |= QUEUE_FSEQ_PREFLUSH;
+ if (!blk_rq_sectors(rq))
+ skip |= QUEUE_FSEQ_DATA;
+ if (!do_postflush)
+ skip |= QUEUE_FSEQ_POSTFLUSH;
+ return blk_flush_complete_seq(q, skip, 0);
+}
+
+static void bio_end_flush(struct bio *bio, int err)
+{
+ if (err)
+ clear_bit(BIO_UPTODATE, &bio->bi_flags);
+ if (bio->bi_private)
+ complete(bio->bi_private);
+ bio_put(bio);
+}
+
+/**
+ * blkdev_issue_flush - queue a flush
+ * @bdev: blockdev to issue flush for
+ * @gfp_mask: memory allocation flags (for bio_alloc)
+ * @error_sector: error sector
+ *
+ * Description:
+ * Issue a flush for the block device in question. Caller can supply
+ * room for storing the error offset in case of a flush error, if they
+ * wish to. If WAIT flag is not passed then caller may check only what
+ * request was pushed in some internal queue for later handling.
+ */
+int blkdev_issue_flush(struct block_device *bdev, gfp_t gfp_mask,
+ sector_t *error_sector)
+{
+ DECLARE_COMPLETION_ONSTACK(wait);
+ struct request_queue *q;
+ struct bio *bio;
+ int ret = 0;
+
+ if (bdev->bd_disk == NULL)
+ return -ENXIO;
+
+ q = bdev_get_queue(bdev);
+ if (!q)
+ return -ENXIO;
+
+ /*
+ * some block devices may not have their queue correctly set up here
+ * (e.g. loop device without a backing file) and so issuing a flush
+ * here will panic. Ensure there is a request function before issuing
+ * the flush.
+ */
+ if (!q->make_request_fn)
+ return -ENXIO;
+
+ bio = bio_alloc(gfp_mask, 0);
+ bio->bi_end_io = bio_end_flush;
+ bio->bi_bdev = bdev;
+ bio->bi_private = &wait;
+
+ bio_get(bio);
+ submit_bio(WRITE_FLUSH, bio);
+ wait_for_completion(&wait);
+
+ /*
+ * The driver must store the error location in ->bi_sector, if
+ * it supports it. For non-stacked drivers, this should be
+ * copied from blk_rq_pos(rq).
+ */
+ if (error_sector)
+ *error_sector = bio->bi_sector;
+
+ if (!bio_flagged(bio, BIO_UPTODATE))
+ ret = -EIO;
+
+ bio_put(bio);
+ return ret;
+}
+EXPORT_SYMBOL(blkdev_issue_flush);
diff --git a/block/blk-integrity.c b/block/blk-integrity.c
index edce1ef7933d..54bcba6c02a7 100644
--- a/block/blk-integrity.c
+++ b/block/blk-integrity.c
@@ -32,24 +32,37 @@ static struct kmem_cache *integrity_cachep;
/**
* blk_rq_count_integrity_sg - Count number of integrity scatterlist elements
- * @rq: request with integrity metadata attached
+ * @q: request queue
+ * @bio: bio with integrity metadata attached
*
* Description: Returns the number of elements required in a
- * scatterlist corresponding to the integrity metadata in a request.
+ * scatterlist corresponding to the integrity metadata in a bio.
*/
-int blk_rq_count_integrity_sg(struct request *rq)
+int blk_rq_count_integrity_sg(struct request_queue *q, struct bio *bio)
{
- struct bio_vec *iv, *ivprv;
- struct req_iterator iter;
- unsigned int segments;
+ struct bio_vec *iv, *ivprv = NULL;
+ unsigned int segments = 0;
+ unsigned int seg_size = 0;
+ unsigned int i = 0;
- ivprv = NULL;
- segments = 0;
+ bio_for_each_integrity_vec(iv, bio, i) {
- rq_for_each_integrity_segment(iv, rq, iter) {
+ if (ivprv) {
+ if (!BIOVEC_PHYS_MERGEABLE(ivprv, iv))
+ goto new_segment;
+
+ if (!BIOVEC_SEG_BOUNDARY(q, ivprv, iv))
+ goto new_segment;
- if (!ivprv || !BIOVEC_PHYS_MERGEABLE(ivprv, iv))
+ if (seg_size + iv->bv_len > queue_max_segment_size(q))
+ goto new_segment;
+
+ seg_size += iv->bv_len;
+ } else {
+new_segment:
segments++;
+ seg_size = iv->bv_len;
+ }
ivprv = iv;
}
@@ -60,30 +73,34 @@ EXPORT_SYMBOL(blk_rq_count_integrity_sg);
/**
* blk_rq_map_integrity_sg - Map integrity metadata into a scatterlist
- * @rq: request with integrity metadata attached
+ * @q: request queue
+ * @bio: bio with integrity metadata attached
* @sglist: target scatterlist
*
* Description: Map the integrity vectors in request into a
* scatterlist. The scatterlist must be big enough to hold all
* elements. I.e. sized using blk_rq_count_integrity_sg().
*/
-int blk_rq_map_integrity_sg(struct request *rq, struct scatterlist *sglist)
+int blk_rq_map_integrity_sg(struct request_queue *q, struct bio *bio,
+ struct scatterlist *sglist)
{
- struct bio_vec *iv, *ivprv;
- struct req_iterator iter;
- struct scatterlist *sg;
- unsigned int segments;
-
- ivprv = NULL;
- sg = NULL;
- segments = 0;
+ struct bio_vec *iv, *ivprv = NULL;
+ struct scatterlist *sg = NULL;
+ unsigned int segments = 0;
+ unsigned int i = 0;
- rq_for_each_integrity_segment(iv, rq, iter) {
+ bio_for_each_integrity_vec(iv, bio, i) {
if (ivprv) {
if (!BIOVEC_PHYS_MERGEABLE(ivprv, iv))
goto new_segment;
+ if (!BIOVEC_SEG_BOUNDARY(q, ivprv, iv))
+ goto new_segment;
+
+ if (sg->length + iv->bv_len > queue_max_segment_size(q))
+ goto new_segment;
+
sg->length += iv->bv_len;
} else {
new_segment:
@@ -162,6 +179,40 @@ int blk_integrity_compare(struct gendisk *gd1, struct gendisk *gd2)
}
EXPORT_SYMBOL(blk_integrity_compare);
+int blk_integrity_merge_rq(struct request_queue *q, struct request *req,
+ struct request *next)
+{
+ if (blk_integrity_rq(req) != blk_integrity_rq(next))
+ return -1;
+
+ if (req->nr_integrity_segments + next->nr_integrity_segments >
+ q->limits.max_integrity_segments)
+ return -1;
+
+ return 0;
+}
+EXPORT_SYMBOL(blk_integrity_merge_rq);
+
+int blk_integrity_merge_bio(struct request_queue *q, struct request *req,
+ struct bio *bio)
+{
+ int nr_integrity_segs;
+ struct bio *next = bio->bi_next;
+
+ bio->bi_next = NULL;
+ nr_integrity_segs = blk_rq_count_integrity_sg(q, bio);
+ bio->bi_next = next;
+
+ if (req->nr_integrity_segments + nr_integrity_segs >
+ q->limits.max_integrity_segments)
+ return -1;
+
+ req->nr_integrity_segments += nr_integrity_segs;
+
+ return 0;
+}
+EXPORT_SYMBOL(blk_integrity_merge_bio);
+
struct integrity_sysfs_entry {
struct attribute attr;
ssize_t (*show)(struct blk_integrity *, char *);
@@ -381,7 +432,6 @@ void blk_integrity_unregister(struct gendisk *disk)
kobject_uevent(&bi->kobj, KOBJ_REMOVE);
kobject_del(&bi->kobj);
kobject_put(&bi->kobj);
- kmem_cache_free(integrity_cachep, bi);
disk->integrity = NULL;
}
EXPORT_SYMBOL(blk_integrity_unregister);
diff --git a/block/blk-lib.c b/block/blk-lib.c
index c392029a104e..1a320d2406b0 100644
--- a/block/blk-lib.c
+++ b/block/blk-lib.c
@@ -39,8 +39,7 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
{
DECLARE_COMPLETION_ONSTACK(wait);
struct request_queue *q = bdev_get_queue(bdev);
- int type = flags & BLKDEV_IFL_BARRIER ?
- DISCARD_BARRIER : DISCARD_NOBARRIER;
+ int type = REQ_WRITE | REQ_DISCARD;
unsigned int max_discard_sectors;
struct bio *bio;
int ret = 0;
@@ -62,10 +61,10 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
max_discard_sectors &= ~(disc_sects - 1);
}
- if (flags & BLKDEV_IFL_SECURE) {
+ if (flags & BLKDEV_DISCARD_SECURE) {
if (!blk_queue_secdiscard(q))
return -EOPNOTSUPP;
- type |= DISCARD_SECURE;
+ type |= REQ_SECURE;
}
while (nr_sects && !ret) {
@@ -78,8 +77,7 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
bio->bi_sector = sector;
bio->bi_end_io = blkdev_discard_end_io;
bio->bi_bdev = bdev;
- if (flags & BLKDEV_IFL_WAIT)
- bio->bi_private = &wait;
+ bio->bi_private = &wait;
if (nr_sects > max_discard_sectors) {
bio->bi_size = max_discard_sectors << 9;
@@ -93,8 +91,7 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
bio_get(bio);
submit_bio(type, bio);
- if (flags & BLKDEV_IFL_WAIT)
- wait_for_completion(&wait);
+ wait_for_completion(&wait);
if (bio_flagged(bio, BIO_EOPNOTSUPP))
ret = -EOPNOTSUPP;
@@ -140,7 +137,6 @@ static void bio_batch_end_io(struct bio *bio, int err)
* @sector: start sector
* @nr_sects: number of sectors to write
* @gfp_mask: memory allocation flags (for bio_alloc)
- * @flags: BLKDEV_IFL_* flags to control behaviour
*
* Description:
* Generate and issue number of bios with zerofiled pages.
@@ -149,7 +145,7 @@ static void bio_batch_end_io(struct bio *bio, int err)
*/
int blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
- sector_t nr_sects, gfp_t gfp_mask, unsigned long flags)
+ sector_t nr_sects, gfp_t gfp_mask)
{
int ret;
struct bio *bio;
@@ -162,12 +158,6 @@ int blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
bb.wait = &wait;
bb.end_io = NULL;
- if (flags & BLKDEV_IFL_BARRIER) {
- /* issue async barrier before the data */
- ret = blkdev_issue_flush(bdev, gfp_mask, NULL, 0);
- if (ret)
- return ret;
- }
submit:
ret = 0;
while (nr_sects != 0) {
@@ -181,8 +171,7 @@ submit:
bio->bi_sector = sector;
bio->bi_bdev = bdev;
bio->bi_end_io = bio_batch_end_io;
- if (flags & BLKDEV_IFL_WAIT)
- bio->bi_private = &bb;
+ bio->bi_private = &bb;
while (nr_sects != 0) {
sz = min((sector_t) PAGE_SIZE >> 9 , nr_sects);
@@ -199,18 +188,10 @@ submit:
issued++;
submit_bio(WRITE, bio);
}
- /*
- * When all data bios are in flight. Send final barrier if requeted.
- */
- if (nr_sects == 0 && flags & BLKDEV_IFL_BARRIER)
- ret = blkdev_issue_flush(bdev, gfp_mask, NULL,
- flags & BLKDEV_IFL_WAIT);
-
- if (flags & BLKDEV_IFL_WAIT)
- /* Wait for bios in-flight */
- while ( issued != atomic_read(&bb.done))
- wait_for_completion(&wait);
+ /* Wait for bios in-flight */
+ while (issued != atomic_read(&bb.done))
+ wait_for_completion(&wait);
if (!test_bit(BIO_UPTODATE, &bb.flags))
/* One of bios in the batch was completed with error.*/
diff --git a/block/blk-map.c b/block/blk-map.c
index ade0a08c9099..d4a586d8691e 100644
--- a/block/blk-map.c
+++ b/block/blk-map.c
@@ -54,7 +54,7 @@ static int __blk_rq_map_user(struct request_queue *q, struct request *rq,
* direct dma. else, set up kernel bounce buffers
*/
uaddr = (unsigned long) ubuf;
- if (blk_rq_aligned(q, ubuf, len) && !map_data)
+ if (blk_rq_aligned(q, uaddr, len) && !map_data)
bio = bio_map_user(q, NULL, uaddr, len, reading, gfp_mask);
else
bio = bio_copy_user(q, map_data, uaddr, len, reading, gfp_mask);
@@ -288,6 +288,7 @@ int blk_rq_map_kern(struct request_queue *q, struct request *rq, void *kbuf,
unsigned int len, gfp_t gfp_mask)
{
int reading = rq_data_dir(rq) == READ;
+ unsigned long addr = (unsigned long) kbuf;
int do_copy = 0;
struct bio *bio;
int ret;
@@ -297,7 +298,7 @@ int blk_rq_map_kern(struct request_queue *q, struct request *rq, void *kbuf,
if (!len || !kbuf)
return -EINVAL;
- do_copy = !blk_rq_aligned(q, kbuf, len) || object_is_on_stack(kbuf);
+ do_copy = !blk_rq_aligned(q, addr, len) || object_is_on_stack(kbuf);
if (do_copy)
bio = bio_copy_kern(q, kbuf, len, gfp_mask, reading);
else
diff --git a/block/blk-merge.c b/block/blk-merge.c
index eafc94f68d79..0a2fd8a48a38 100644
--- a/block/blk-merge.c
+++ b/block/blk-merge.c
@@ -205,12 +205,11 @@ static inline int ll_new_hw_segment(struct request_queue *q,
{
int nr_phys_segs = bio_phys_segments(q, bio);
- if (req->nr_phys_segments + nr_phys_segs > queue_max_segments(q)) {
- req->cmd_flags |= REQ_NOMERGE;
- if (req == q->last_merge)
- q->last_merge = NULL;
- return 0;
- }
+ if (req->nr_phys_segments + nr_phys_segs > queue_max_segments(q))
+ goto no_merge;
+
+ if (bio_integrity(bio) && blk_integrity_merge_bio(q, req, bio))
+ goto no_merge;
/*
* This will form the start of a new hw segment. Bump both
@@ -218,6 +217,12 @@ static inline int ll_new_hw_segment(struct request_queue *q,
*/
req->nr_phys_segments += nr_phys_segs;
return 1;
+
+no_merge:
+ req->cmd_flags |= REQ_NOMERGE;
+ if (req == q->last_merge)
+ q->last_merge = NULL;
+ return 0;
}
int ll_back_merge_fn(struct request_queue *q, struct request *req,
@@ -301,6 +306,9 @@ static int ll_merge_requests_fn(struct request_queue *q, struct request *req,
if (total_phys_segments > queue_max_segments(q))
return 0;
+ if (blk_integrity_rq(req) && blk_integrity_merge_rq(q, req, next))
+ return 0;
+
/* Merge is OK... */
req->nr_phys_segments = total_phys_segments;
return 1;
@@ -343,7 +351,7 @@ static void blk_account_io_merge(struct request *req)
int cpu;
cpu = part_stat_lock();
- part = disk_map_sector_rcu(req->rq_disk, blk_rq_pos(req));
+ part = req->part;
part_round_stats(cpu, part);
part_dec_in_flight(part, rq_data_dir(req));
@@ -384,9 +392,6 @@ static int attempt_merge(struct request_queue *q, struct request *req,
|| next->special)
return 0;
- if (blk_integrity_rq(req) != blk_integrity_rq(next))
- return 0;
-
/*
* If we are allowed to merge, then append bio list
* from next to rq and release next. merge_requests_fn
diff --git a/block/blk-settings.c b/block/blk-settings.c
index a234f4bf1d6f..701859fb9647 100644
--- a/block/blk-settings.c
+++ b/block/blk-settings.c
@@ -111,6 +111,7 @@ EXPORT_SYMBOL_GPL(blk_queue_lld_busy);
void blk_set_default_limits(struct queue_limits *lim)
{
lim->max_segments = BLK_MAX_SEGMENTS;
+ lim->max_integrity_segments = 0;
lim->seg_boundary_mask = BLK_SEG_BOUNDARY_MASK;
lim->max_segment_size = BLK_MAX_SEGMENT_SIZE;
lim->max_sectors = BLK_DEF_MAX_SECTORS;
@@ -213,7 +214,7 @@ void blk_queue_bounce_limit(struct request_queue *q, u64 dma_mask)
*/
if (b_pfn < (min_t(u64, 0xffffffffUL, BLK_BOUNCE_HIGH) >> PAGE_SHIFT))
dma = 1;
- q->limits.bounce_pfn = max_low_pfn;
+ q->limits.bounce_pfn = max(max_low_pfn, b_pfn);
#else
if (b_pfn < blk_max_low_pfn)
dma = 1;
@@ -343,7 +344,7 @@ EXPORT_SYMBOL(blk_queue_logical_block_size);
* hardware can operate on without reverting to read-modify-write
* operations.
*/
-void blk_queue_physical_block_size(struct request_queue *q, unsigned short size)
+void blk_queue_physical_block_size(struct request_queue *q, unsigned int size)
{
q->limits.physical_block_size = size;
@@ -455,11 +456,6 @@ void blk_queue_io_opt(struct request_queue *q, unsigned int opt)
}
EXPORT_SYMBOL(blk_queue_io_opt);
-/*
- * Returns the minimum that is _not_ zero, unless both are zero.
- */
-#define min_not_zero(l, r) (l == 0) ? r : ((r == 0) ? l : min(l, r))
-
/**
* blk_queue_stack_limits - inherit underlying queue limits for stacked drivers
* @t: the stacking driver (top)
@@ -514,6 +510,8 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
b->seg_boundary_mask);
t->max_segments = min_not_zero(t->max_segments, b->max_segments);
+ t->max_integrity_segments = min_not_zero(t->max_integrity_segments,
+ b->max_integrity_segments);
t->max_segment_size = min_not_zero(t->max_segment_size,
b->max_segment_size);
@@ -794,6 +792,26 @@ void blk_queue_update_dma_alignment(struct request_queue *q, int mask)
}
EXPORT_SYMBOL(blk_queue_update_dma_alignment);
+/**
+ * blk_queue_flush - configure queue's cache flush capability
+ * @q: the request queue for the device
+ * @flush: 0, REQ_FLUSH or REQ_FLUSH | REQ_FUA
+ *
+ * Tell block layer cache flush capability of @q. If it supports
+ * flushing, REQ_FLUSH should be set. If it supports bypassing
+ * write cache for individual writes, REQ_FUA should be set.
+ */
+void blk_queue_flush(struct request_queue *q, unsigned int flush)
+{
+ WARN_ON_ONCE(flush & ~(REQ_FLUSH | REQ_FUA));
+
+ if (WARN_ON_ONCE(!(flush & REQ_FLUSH) && (flush & REQ_FUA)))
+ flush &= ~REQ_FUA;
+
+ q->flush_flags = flush & (REQ_FLUSH | REQ_FUA);
+}
+EXPORT_SYMBOL_GPL(blk_queue_flush);
+
static int __init blk_settings_init(void)
{
blk_max_low_pfn = max_low_pfn - 1;
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
index 0749b89c6885..013457f47fdc 100644
--- a/block/blk-sysfs.c
+++ b/block/blk-sysfs.c
@@ -112,6 +112,11 @@ static ssize_t queue_max_segments_show(struct request_queue *q, char *page)
return queue_var_show(queue_max_segments(q), (page));
}
+static ssize_t queue_max_integrity_segments_show(struct request_queue *q, char *page)
+{
+ return queue_var_show(q->limits.max_integrity_segments, (page));
+}
+
static ssize_t queue_max_segment_size_show(struct request_queue *q, char *page)
{
if (test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags))
@@ -288,6 +293,11 @@ static struct queue_sysfs_entry queue_max_segments_entry = {
.show = queue_max_segments_show,
};
+static struct queue_sysfs_entry queue_max_integrity_segments_entry = {
+ .attr = {.name = "max_integrity_segments", .mode = S_IRUGO },
+ .show = queue_max_integrity_segments_show,
+};
+
static struct queue_sysfs_entry queue_max_segment_size_entry = {
.attr = {.name = "max_segment_size", .mode = S_IRUGO },
.show = queue_max_segment_size_show,
@@ -375,6 +385,7 @@ static struct attribute *default_attrs[] = {
&queue_max_hw_sectors_entry.attr,
&queue_max_sectors_entry.attr,
&queue_max_segments_entry.attr,
+ &queue_max_integrity_segments_entry.attr,
&queue_max_segment_size_entry.attr,
&queue_iosched_entry.attr,
&queue_hw_sector_size_entry.attr,
@@ -460,6 +471,8 @@ static void blk_release_queue(struct kobject *kobj)
blk_sync_queue(q);
+ blk_throtl_exit(q);
+
if (rl->rq_pool)
mempool_destroy(rl->rq_pool);
diff --git a/block/blk-throttle.c b/block/blk-throttle.c
new file mode 100644
index 000000000000..56ad4531b412
--- /dev/null
+++ b/block/blk-throttle.c
@@ -0,0 +1,1123 @@
+/*
+ * Interface for controlling IO bandwidth on a request queue
+ *
+ * Copyright (C) 2010 Vivek Goyal <vgoyal@redhat.com>
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/blkdev.h>
+#include <linux/bio.h>
+#include <linux/blktrace_api.h>
+#include "blk-cgroup.h"
+
+/* Max dispatch from a group in 1 round */
+static int throtl_grp_quantum = 8;
+
+/* Total max dispatch from all groups in one round */
+static int throtl_quantum = 32;
+
+/* Throttling is performed over 100ms slice and after that slice is renewed */
+static unsigned long throtl_slice = HZ/10; /* 100 ms */
+
+struct throtl_rb_root {
+ struct rb_root rb;
+ struct rb_node *left;
+ unsigned int count;
+ unsigned long min_disptime;
+};
+
+#define THROTL_RB_ROOT (struct throtl_rb_root) { .rb = RB_ROOT, .left = NULL, \
+ .count = 0, .min_disptime = 0}
+
+#define rb_entry_tg(node) rb_entry((node), struct throtl_grp, rb_node)
+
+struct throtl_grp {
+ /* List of throtl groups on the request queue*/
+ struct hlist_node tg_node;
+
+ /* active throtl group service_tree member */
+ struct rb_node rb_node;
+
+ /*
+ * Dispatch time in jiffies. This is the estimated time when group
+ * will unthrottle and is ready to dispatch more bio. It is used as
+ * key to sort active groups in service tree.
+ */
+ unsigned long disptime;
+
+ struct blkio_group blkg;
+ atomic_t ref;
+ unsigned int flags;
+
+ /* Two lists for READ and WRITE */
+ struct bio_list bio_lists[2];
+
+ /* Number of queued bios on READ and WRITE lists */
+ unsigned int nr_queued[2];
+
+ /* bytes per second rate limits */
+ uint64_t bps[2];
+
+ /* IOPS limits */
+ unsigned int iops[2];
+
+ /* Number of bytes disptached in current slice */
+ uint64_t bytes_disp[2];
+ /* Number of bio's dispatched in current slice */
+ unsigned int io_disp[2];
+
+ /* When did we start a new slice */
+ unsigned long slice_start[2];
+ unsigned long slice_end[2];
+
+ /* Some throttle limits got updated for the group */
+ bool limits_changed;
+};
+
+struct throtl_data
+{
+ /* List of throtl groups */
+ struct hlist_head tg_list;
+
+ /* service tree for active throtl groups */
+ struct throtl_rb_root tg_service_tree;
+
+ struct throtl_grp root_tg;
+ struct request_queue *queue;
+
+ /* Total Number of queued bios on READ and WRITE lists */
+ unsigned int nr_queued[2];
+
+ /*
+ * number of total undestroyed groups
+ */
+ unsigned int nr_undestroyed_grps;
+
+ /* Work for dispatching throttled bios */
+ struct delayed_work throtl_work;
+
+ atomic_t limits_changed;
+};
+
+enum tg_state_flags {
+ THROTL_TG_FLAG_on_rr = 0, /* on round-robin busy list */
+};
+
+#define THROTL_TG_FNS(name) \
+static inline void throtl_mark_tg_##name(struct throtl_grp *tg) \
+{ \
+ (tg)->flags |= (1 << THROTL_TG_FLAG_##name); \
+} \
+static inline void throtl_clear_tg_##name(struct throtl_grp *tg) \
+{ \
+ (tg)->flags &= ~(1 << THROTL_TG_FLAG_##name); \
+} \
+static inline int throtl_tg_##name(const struct throtl_grp *tg) \
+{ \
+ return ((tg)->flags & (1 << THROTL_TG_FLAG_##name)) != 0; \
+}
+
+THROTL_TG_FNS(on_rr);
+
+#define throtl_log_tg(td, tg, fmt, args...) \
+ blk_add_trace_msg((td)->queue, "throtl %s " fmt, \
+ blkg_path(&(tg)->blkg), ##args); \
+
+#define throtl_log(td, fmt, args...) \
+ blk_add_trace_msg((td)->queue, "throtl " fmt, ##args)
+
+static inline struct throtl_grp *tg_of_blkg(struct blkio_group *blkg)
+{
+ if (blkg)
+ return container_of(blkg, struct throtl_grp, blkg);
+
+ return NULL;
+}
+
+static inline int total_nr_queued(struct throtl_data *td)
+{
+ return (td->nr_queued[0] + td->nr_queued[1]);
+}
+
+static inline struct throtl_grp *throtl_ref_get_tg(struct throtl_grp *tg)
+{
+ atomic_inc(&tg->ref);
+ return tg;
+}
+
+static void throtl_put_tg(struct throtl_grp *tg)
+{
+ BUG_ON(atomic_read(&tg->ref) <= 0);
+ if (!atomic_dec_and_test(&tg->ref))
+ return;
+ kfree(tg);
+}
+
+static struct throtl_grp * throtl_find_alloc_tg(struct throtl_data *td,
+ struct cgroup *cgroup)
+{
+ struct blkio_cgroup *blkcg = cgroup_to_blkio_cgroup(cgroup);
+ struct throtl_grp *tg = NULL;
+ void *key = td;
+ struct backing_dev_info *bdi = &td->queue->backing_dev_info;
+ unsigned int major, minor;
+
+ /*
+ * TODO: Speed up blkiocg_lookup_group() by maintaining a radix
+ * tree of blkg (instead of traversing through hash list all
+ * the time.
+ */
+ tg = tg_of_blkg(blkiocg_lookup_group(blkcg, key));
+
+ /* Fill in device details for root group */
+ if (tg && !tg->blkg.dev && bdi->dev && dev_name(bdi->dev)) {
+ sscanf(dev_name(bdi->dev), "%u:%u", &major, &minor);
+ tg->blkg.dev = MKDEV(major, minor);
+ goto done;
+ }
+
+ if (tg)
+ goto done;
+
+ tg = kzalloc_node(sizeof(*tg), GFP_ATOMIC, td->queue->node);
+ if (!tg)
+ goto done;
+
+ INIT_HLIST_NODE(&tg->tg_node);
+ RB_CLEAR_NODE(&tg->rb_node);
+ bio_list_init(&tg->bio_lists[0]);
+ bio_list_init(&tg->bio_lists[1]);
+
+ /*
+ * Take the initial reference that will be released on destroy
+ * This can be thought of a joint reference by cgroup and
+ * request queue which will be dropped by either request queue
+ * exit or cgroup deletion path depending on who is exiting first.
+ */
+ atomic_set(&tg->ref, 1);
+
+ /* Add group onto cgroup list */
+ sscanf(dev_name(bdi->dev), "%u:%u", &major, &minor);
+ blkiocg_add_blkio_group(blkcg, &tg->blkg, (void *)td,
+ MKDEV(major, minor), BLKIO_POLICY_THROTL);
+
+ tg->bps[READ] = blkcg_get_read_bps(blkcg, tg->blkg.dev);
+ tg->bps[WRITE] = blkcg_get_write_bps(blkcg, tg->blkg.dev);
+ tg->iops[READ] = blkcg_get_read_iops(blkcg, tg->blkg.dev);
+ tg->iops[WRITE] = blkcg_get_write_iops(blkcg, tg->blkg.dev);
+
+ hlist_add_head(&tg->tg_node, &td->tg_list);
+ td->nr_undestroyed_grps++;
+done:
+ return tg;
+}
+
+static struct throtl_grp * throtl_get_tg(struct throtl_data *td)
+{
+ struct cgroup *cgroup;
+ struct throtl_grp *tg = NULL;
+
+ rcu_read_lock();
+ cgroup = task_cgroup(current, blkio_subsys_id);
+ tg = throtl_find_alloc_tg(td, cgroup);
+ if (!tg)
+ tg = &td->root_tg;
+ rcu_read_unlock();
+ return tg;
+}
+
+static struct throtl_grp *throtl_rb_first(struct throtl_rb_root *root)
+{
+ /* Service tree is empty */
+ if (!root->count)
+ return NULL;
+
+ if (!root->left)
+ root->left = rb_first(&root->rb);
+
+ if (root->left)
+ return rb_entry_tg(root->left);
+
+ return NULL;
+}
+
+static void rb_erase_init(struct rb_node *n, struct rb_root *root)
+{
+ rb_erase(n, root);
+ RB_CLEAR_NODE(n);
+}
+
+static void throtl_rb_erase(struct rb_node *n, struct throtl_rb_root *root)
+{
+ if (root->left == n)
+ root->left = NULL;
+ rb_erase_init(n, &root->rb);
+ --root->count;
+}
+
+static void update_min_dispatch_time(struct throtl_rb_root *st)
+{
+ struct throtl_grp *tg;
+
+ tg = throtl_rb_first(st);
+ if (!tg)
+ return;
+
+ st->min_disptime = tg->disptime;
+}
+
+static void
+tg_service_tree_add(struct throtl_rb_root *st, struct throtl_grp *tg)
+{
+ struct rb_node **node = &st->rb.rb_node;
+ struct rb_node *parent = NULL;
+ struct throtl_grp *__tg;
+ unsigned long key = tg->disptime;
+ int left = 1;
+
+ while (*node != NULL) {
+ parent = *node;
+ __tg = rb_entry_tg(parent);
+
+ if (time_before(key, __tg->disptime))
+ node = &parent->rb_left;
+ else {
+ node = &parent->rb_right;
+ left = 0;
+ }
+ }
+
+ if (left)
+ st->left = &tg->rb_node;
+
+ rb_link_node(&tg->rb_node, parent, node);
+ rb_insert_color(&tg->rb_node, &st->rb);
+}
+
+static void __throtl_enqueue_tg(struct throtl_data *td, struct throtl_grp *tg)
+{
+ struct throtl_rb_root *st = &td->tg_service_tree;
+
+ tg_service_tree_add(st, tg);
+ throtl_mark_tg_on_rr(tg);
+ st->count++;
+}
+
+static void throtl_enqueue_tg(struct throtl_data *td, struct throtl_grp *tg)
+{
+ if (!throtl_tg_on_rr(tg))
+ __throtl_enqueue_tg(td, tg);
+}
+
+static void __throtl_dequeue_tg(struct throtl_data *td, struct throtl_grp *tg)
+{
+ throtl_rb_erase(&tg->rb_node, &td->tg_service_tree);
+ throtl_clear_tg_on_rr(tg);
+}
+
+static void throtl_dequeue_tg(struct throtl_data *td, struct throtl_grp *tg)
+{
+ if (throtl_tg_on_rr(tg))
+ __throtl_dequeue_tg(td, tg);
+}
+
+static void throtl_schedule_next_dispatch(struct throtl_data *td)
+{
+ struct throtl_rb_root *st = &td->tg_service_tree;
+
+ /*
+ * If there are more bios pending, schedule more work.
+ */
+ if (!total_nr_queued(td))
+ return;
+
+ BUG_ON(!st->count);
+
+ update_min_dispatch_time(st);
+
+ if (time_before_eq(st->min_disptime, jiffies))
+ throtl_schedule_delayed_work(td->queue, 0);
+ else
+ throtl_schedule_delayed_work(td->queue,
+ (st->min_disptime - jiffies));
+}
+
+static inline void
+throtl_start_new_slice(struct throtl_data *td, struct throtl_grp *tg, bool rw)
+{
+ tg->bytes_disp[rw] = 0;
+ tg->io_disp[rw] = 0;
+ tg->slice_start[rw] = jiffies;
+ tg->slice_end[rw] = jiffies + throtl_slice;
+ throtl_log_tg(td, tg, "[%c] new slice start=%lu end=%lu jiffies=%lu",
+ rw == READ ? 'R' : 'W', tg->slice_start[rw],
+ tg->slice_end[rw], jiffies);
+}
+
+static inline void throtl_extend_slice(struct throtl_data *td,
+ struct throtl_grp *tg, bool rw, unsigned long jiffy_end)
+{
+ tg->slice_end[rw] = roundup(jiffy_end, throtl_slice);
+ throtl_log_tg(td, tg, "[%c] extend slice start=%lu end=%lu jiffies=%lu",
+ rw == READ ? 'R' : 'W', tg->slice_start[rw],
+ tg->slice_end[rw], jiffies);
+}
+
+/* Determine if previously allocated or extended slice is complete or not */
+static bool
+throtl_slice_used(struct throtl_data *td, struct throtl_grp *tg, bool rw)
+{
+ if (time_in_range(jiffies, tg->slice_start[rw], tg->slice_end[rw]))
+ return 0;
+
+ return 1;
+}
+
+/* Trim the used slices and adjust slice start accordingly */
+static inline void
+throtl_trim_slice(struct throtl_data *td, struct throtl_grp *tg, bool rw)
+{
+ unsigned long nr_slices, time_elapsed, io_trim;
+ u64 bytes_trim, tmp;
+
+ BUG_ON(time_before(tg->slice_end[rw], tg->slice_start[rw]));
+
+ /*
+ * If bps are unlimited (-1), then time slice don't get
+ * renewed. Don't try to trim the slice if slice is used. A new
+ * slice will start when appropriate.
+ */
+ if (throtl_slice_used(td, tg, rw))
+ return;
+
+ time_elapsed = jiffies - tg->slice_start[rw];
+
+ nr_slices = time_elapsed / throtl_slice;
+
+ if (!nr_slices)
+ return;
+ tmp = tg->bps[rw] * throtl_slice * nr_slices;
+ do_div(tmp, HZ);
+ bytes_trim = tmp;
+
+ io_trim = (tg->iops[rw] * throtl_slice * nr_slices)/HZ;
+
+ if (!bytes_trim && !io_trim)
+ return;
+
+ if (tg->bytes_disp[rw] >= bytes_trim)
+ tg->bytes_disp[rw] -= bytes_trim;
+ else
+ tg->bytes_disp[rw] = 0;
+
+ if (tg->io_disp[rw] >= io_trim)
+ tg->io_disp[rw] -= io_trim;
+ else
+ tg->io_disp[rw] = 0;
+
+ tg->slice_start[rw] += nr_slices * throtl_slice;
+
+ throtl_log_tg(td, tg, "[%c] trim slice nr=%lu bytes=%llu io=%lu"
+ " start=%lu end=%lu jiffies=%lu",
+ rw == READ ? 'R' : 'W', nr_slices, bytes_trim, io_trim,
+ tg->slice_start[rw], tg->slice_end[rw], jiffies);
+}
+
+static bool tg_with_in_iops_limit(struct throtl_data *td, struct throtl_grp *tg,
+ struct bio *bio, unsigned long *wait)
+{
+ bool rw = bio_data_dir(bio);
+ unsigned int io_allowed;
+ unsigned long jiffy_elapsed, jiffy_wait, jiffy_elapsed_rnd;
+ u64 tmp;
+
+ jiffy_elapsed = jiffy_elapsed_rnd = jiffies - tg->slice_start[rw];
+
+ /* Slice has just started. Consider one slice interval */
+ if (!jiffy_elapsed)
+ jiffy_elapsed_rnd = throtl_slice;
+
+ jiffy_elapsed_rnd = roundup(jiffy_elapsed_rnd, throtl_slice);
+
+ /*
+ * jiffy_elapsed_rnd should not be a big value as minimum iops can be
+ * 1 then at max jiffy elapsed should be equivalent of 1 second as we
+ * will allow dispatch after 1 second and after that slice should
+ * have been trimmed.
+ */
+
+ tmp = (u64)tg->iops[rw] * jiffy_elapsed_rnd;
+ do_div(tmp, HZ);
+
+ if (tmp > UINT_MAX)
+ io_allowed = UINT_MAX;
+ else
+ io_allowed = tmp;
+
+ if (tg->io_disp[rw] + 1 <= io_allowed) {
+ if (wait)
+ *wait = 0;
+ return 1;
+ }
+
+ /* Calc approx time to dispatch */
+ jiffy_wait = ((tg->io_disp[rw] + 1) * HZ)/tg->iops[rw] + 1;
+
+ if (jiffy_wait > jiffy_elapsed)
+ jiffy_wait = jiffy_wait - jiffy_elapsed;
+ else
+ jiffy_wait = 1;
+
+ if (wait)
+ *wait = jiffy_wait;
+ return 0;
+}
+
+static bool tg_with_in_bps_limit(struct throtl_data *td, struct throtl_grp *tg,
+ struct bio *bio, unsigned long *wait)
+{
+ bool rw = bio_data_dir(bio);
+ u64 bytes_allowed, extra_bytes, tmp;
+ unsigned long jiffy_elapsed, jiffy_wait, jiffy_elapsed_rnd;
+
+ jiffy_elapsed = jiffy_elapsed_rnd = jiffies - tg->slice_start[rw];
+
+ /* Slice has just started. Consider one slice interval */
+ if (!jiffy_elapsed)
+ jiffy_elapsed_rnd = throtl_slice;
+
+ jiffy_elapsed_rnd = roundup(jiffy_elapsed_rnd, throtl_slice);
+
+ tmp = tg->bps[rw] * jiffy_elapsed_rnd;
+ do_div(tmp, HZ);
+ bytes_allowed = tmp;
+
+ if (tg->bytes_disp[rw] + bio->bi_size <= bytes_allowed) {
+ if (wait)
+ *wait = 0;
+ return 1;
+ }
+
+ /* Calc approx time to dispatch */
+ extra_bytes = tg->bytes_disp[rw] + bio->bi_size - bytes_allowed;
+ jiffy_wait = div64_u64(extra_bytes * HZ, tg->bps[rw]);
+
+ if (!jiffy_wait)
+ jiffy_wait = 1;
+
+ /*
+ * This wait time is without taking into consideration the rounding
+ * up we did. Add that time also.
+ */
+ jiffy_wait = jiffy_wait + (jiffy_elapsed_rnd - jiffy_elapsed);
+ if (wait)
+ *wait = jiffy_wait;
+ return 0;
+}
+
+/*
+ * Returns whether one can dispatch a bio or not. Also returns approx number
+ * of jiffies to wait before this bio is with-in IO rate and can be dispatched
+ */
+static bool tg_may_dispatch(struct throtl_data *td, struct throtl_grp *tg,
+ struct bio *bio, unsigned long *wait)
+{
+ bool rw = bio_data_dir(bio);
+ unsigned long bps_wait = 0, iops_wait = 0, max_wait = 0;
+
+ /*
+ * Currently whole state machine of group depends on first bio
+ * queued in the group bio list. So one should not be calling
+ * this function with a different bio if there are other bios
+ * queued.
+ */
+ BUG_ON(tg->nr_queued[rw] && bio != bio_list_peek(&tg->bio_lists[rw]));
+
+ /* If tg->bps = -1, then BW is unlimited */
+ if (tg->bps[rw] == -1 && tg->iops[rw] == -1) {
+ if (wait)
+ *wait = 0;
+ return 1;
+ }
+
+ /*
+ * If previous slice expired, start a new one otherwise renew/extend
+ * existing slice to make sure it is at least throtl_slice interval
+ * long since now.
+ */
+ if (throtl_slice_used(td, tg, rw))
+ throtl_start_new_slice(td, tg, rw);
+ else {
+ if (time_before(tg->slice_end[rw], jiffies + throtl_slice))
+ throtl_extend_slice(td, tg, rw, jiffies + throtl_slice);
+ }
+
+ if (tg_with_in_bps_limit(td, tg, bio, &bps_wait)
+ && tg_with_in_iops_limit(td, tg, bio, &iops_wait)) {
+ if (wait)
+ *wait = 0;
+ return 1;
+ }
+
+ max_wait = max(bps_wait, iops_wait);
+
+ if (wait)
+ *wait = max_wait;
+
+ if (time_before(tg->slice_end[rw], jiffies + max_wait))
+ throtl_extend_slice(td, tg, rw, jiffies + max_wait);
+
+ return 0;
+}
+
+static void throtl_charge_bio(struct throtl_grp *tg, struct bio *bio)
+{
+ bool rw = bio_data_dir(bio);
+ bool sync = bio->bi_rw & REQ_SYNC;
+
+ /* Charge the bio to the group */
+ tg->bytes_disp[rw] += bio->bi_size;
+ tg->io_disp[rw]++;
+
+ /*
+ * TODO: This will take blkg->stats_lock. Figure out a way
+ * to avoid this cost.
+ */
+ blkiocg_update_dispatch_stats(&tg->blkg, bio->bi_size, rw, sync);
+}
+
+static void throtl_add_bio_tg(struct throtl_data *td, struct throtl_grp *tg,
+ struct bio *bio)
+{
+ bool rw = bio_data_dir(bio);
+
+ bio_list_add(&tg->bio_lists[rw], bio);
+ /* Take a bio reference on tg */
+ throtl_ref_get_tg(tg);
+ tg->nr_queued[rw]++;
+ td->nr_queued[rw]++;
+ throtl_enqueue_tg(td, tg);
+}
+
+static void tg_update_disptime(struct throtl_data *td, struct throtl_grp *tg)
+{
+ unsigned long read_wait = -1, write_wait = -1, min_wait = -1, disptime;
+ struct bio *bio;
+
+ if ((bio = bio_list_peek(&tg->bio_lists[READ])))
+ tg_may_dispatch(td, tg, bio, &read_wait);
+
+ if ((bio = bio_list_peek(&tg->bio_lists[WRITE])))
+ tg_may_dispatch(td, tg, bio, &write_wait);
+
+ min_wait = min(read_wait, write_wait);
+ disptime = jiffies + min_wait;
+
+ /* Update dispatch time */
+ throtl_dequeue_tg(td, tg);
+ tg->disptime = disptime;
+ throtl_enqueue_tg(td, tg);
+}
+
+static void tg_dispatch_one_bio(struct throtl_data *td, struct throtl_grp *tg,
+ bool rw, struct bio_list *bl)
+{
+ struct bio *bio;
+
+ bio = bio_list_pop(&tg->bio_lists[rw]);
+ tg->nr_queued[rw]--;
+ /* Drop bio reference on tg */
+ throtl_put_tg(tg);
+
+ BUG_ON(td->nr_queued[rw] <= 0);
+ td->nr_queued[rw]--;
+
+ throtl_charge_bio(tg, bio);
+ bio_list_add(bl, bio);
+ bio->bi_rw |= REQ_THROTTLED;
+
+ throtl_trim_slice(td, tg, rw);
+}
+
+static int throtl_dispatch_tg(struct throtl_data *td, struct throtl_grp *tg,
+ struct bio_list *bl)
+{
+ unsigned int nr_reads = 0, nr_writes = 0;
+ unsigned int max_nr_reads = throtl_grp_quantum*3/4;
+ unsigned int max_nr_writes = throtl_grp_quantum - nr_reads;
+ struct bio *bio;
+
+ /* Try to dispatch 75% READS and 25% WRITES */
+
+ while ((bio = bio_list_peek(&tg->bio_lists[READ]))
+ && tg_may_dispatch(td, tg, bio, NULL)) {
+
+ tg_dispatch_one_bio(td, tg, bio_data_dir(bio), bl);
+ nr_reads++;
+
+ if (nr_reads >= max_nr_reads)
+ break;
+ }
+
+ while ((bio = bio_list_peek(&tg->bio_lists[WRITE]))
+ && tg_may_dispatch(td, tg, bio, NULL)) {
+
+ tg_dispatch_one_bio(td, tg, bio_data_dir(bio), bl);
+ nr_writes++;
+
+ if (nr_writes >= max_nr_writes)
+ break;
+ }
+
+ return nr_reads + nr_writes;
+}
+
+static int throtl_select_dispatch(struct throtl_data *td, struct bio_list *bl)
+{
+ unsigned int nr_disp = 0;
+ struct throtl_grp *tg;
+ struct throtl_rb_root *st = &td->tg_service_tree;
+
+ while (1) {
+ tg = throtl_rb_first(st);
+
+ if (!tg)
+ break;
+
+ if (time_before(jiffies, tg->disptime))
+ break;
+
+ throtl_dequeue_tg(td, tg);
+
+ nr_disp += throtl_dispatch_tg(td, tg, bl);
+
+ if (tg->nr_queued[0] || tg->nr_queued[1]) {
+ tg_update_disptime(td, tg);
+ throtl_enqueue_tg(td, tg);
+ }
+
+ if (nr_disp >= throtl_quantum)
+ break;
+ }
+
+ return nr_disp;
+}
+
+static void throtl_process_limit_change(struct throtl_data *td)
+{
+ struct throtl_grp *tg;
+ struct hlist_node *pos, *n;
+
+ /*
+ * Make sure atomic_inc() effects from
+ * throtl_update_blkio_group_read_bps(), group of functions are
+ * visible.
+ * Is this required or smp_mb__after_atomic_inc() was suffcient
+ * after the atomic_inc().
+ */
+ smp_rmb();
+ if (!atomic_read(&td->limits_changed))
+ return;
+
+ throtl_log(td, "limit changed =%d", atomic_read(&td->limits_changed));
+
+ hlist_for_each_entry_safe(tg, pos, n, &td->tg_list, tg_node) {
+ /*
+ * Do I need an smp_rmb() here to make sure tg->limits_changed
+ * update is visible. I am relying on smp_rmb() at the
+ * beginning of function and not putting a new one here.
+ */
+
+ if (throtl_tg_on_rr(tg) && tg->limits_changed) {
+ throtl_log_tg(td, tg, "limit change rbps=%llu wbps=%llu"
+ " riops=%u wiops=%u", tg->bps[READ],
+ tg->bps[WRITE], tg->iops[READ],
+ tg->iops[WRITE]);
+ tg_update_disptime(td, tg);
+ tg->limits_changed = false;
+ }
+ }
+
+ smp_mb__before_atomic_dec();
+ atomic_dec(&td->limits_changed);
+ smp_mb__after_atomic_dec();
+}
+
+/* Dispatch throttled bios. Should be called without queue lock held. */
+static int throtl_dispatch(struct request_queue *q)
+{
+ struct throtl_data *td = q->td;
+ unsigned int nr_disp = 0;
+ struct bio_list bio_list_on_stack;
+ struct bio *bio;
+
+ spin_lock_irq(q->queue_lock);
+
+ throtl_process_limit_change(td);
+
+ if (!total_nr_queued(td))
+ goto out;
+
+ bio_list_init(&bio_list_on_stack);
+
+ throtl_log(td, "dispatch nr_queued=%lu read=%u write=%u",
+ total_nr_queued(td), td->nr_queued[READ],
+ td->nr_queued[WRITE]);
+
+ nr_disp = throtl_select_dispatch(td, &bio_list_on_stack);
+
+ if (nr_disp)
+ throtl_log(td, "bios disp=%u", nr_disp);
+
+ throtl_schedule_next_dispatch(td);
+out:
+ spin_unlock_irq(q->queue_lock);
+
+ /*
+ * If we dispatched some requests, unplug the queue to make sure
+ * immediate dispatch
+ */
+ if (nr_disp) {
+ while((bio = bio_list_pop(&bio_list_on_stack)))
+ generic_make_request(bio);
+ blk_unplug(q);
+ }
+ return nr_disp;
+}
+
+void blk_throtl_work(struct work_struct *work)
+{
+ struct throtl_data *td = container_of(work, struct throtl_data,
+ throtl_work.work);
+ struct request_queue *q = td->queue;
+
+ throtl_dispatch(q);
+}
+
+/* Call with queue lock held */
+void throtl_schedule_delayed_work(struct request_queue *q, unsigned long delay)
+{
+
+ struct throtl_data *td = q->td;
+ struct delayed_work *dwork = &td->throtl_work;
+
+ if (total_nr_queued(td) > 0) {
+ /*
+ * We might have a work scheduled to be executed in future.
+ * Cancel that and schedule a new one.
+ */
+ __cancel_delayed_work(dwork);
+ kblockd_schedule_delayed_work(q, dwork, delay);
+ throtl_log(td, "schedule work. delay=%lu jiffies=%lu",
+ delay, jiffies);
+ }
+}
+EXPORT_SYMBOL(throtl_schedule_delayed_work);
+
+static void
+throtl_destroy_tg(struct throtl_data *td, struct throtl_grp *tg)
+{
+ /* Something wrong if we are trying to remove same group twice */
+ BUG_ON(hlist_unhashed(&tg->tg_node));
+
+ hlist_del_init(&tg->tg_node);
+
+ /*
+ * Put the reference taken at the time of creation so that when all
+ * queues are gone, group can be destroyed.
+ */
+ throtl_put_tg(tg);
+ td->nr_undestroyed_grps--;
+}
+
+static void throtl_release_tgs(struct throtl_data *td)
+{
+ struct hlist_node *pos, *n;
+ struct throtl_grp *tg;
+
+ hlist_for_each_entry_safe(tg, pos, n, &td->tg_list, tg_node) {
+ /*
+ * If cgroup removal path got to blk_group first and removed
+ * it from cgroup list, then it will take care of destroying
+ * cfqg also.
+ */
+ if (!blkiocg_del_blkio_group(&tg->blkg))
+ throtl_destroy_tg(td, tg);
+ }
+}
+
+static void throtl_td_free(struct throtl_data *td)
+{
+ kfree(td);
+}
+
+/*
+ * Blk cgroup controller notification saying that blkio_group object is being
+ * delinked as associated cgroup object is going away. That also means that
+ * no new IO will come in this group. So get rid of this group as soon as
+ * any pending IO in the group is finished.
+ *
+ * This function is called under rcu_read_lock(). key is the rcu protected
+ * pointer. That means "key" is a valid throtl_data pointer as long as we are
+ * rcu read lock.
+ *
+ * "key" was fetched from blkio_group under blkio_cgroup->lock. That means
+ * it should not be NULL as even if queue was going away, cgroup deltion
+ * path got to it first.
+ */
+void throtl_unlink_blkio_group(void *key, struct blkio_group *blkg)
+{
+ unsigned long flags;
+ struct throtl_data *td = key;
+
+ spin_lock_irqsave(td->queue->queue_lock, flags);
+ throtl_destroy_tg(td, tg_of_blkg(blkg));
+ spin_unlock_irqrestore(td->queue->queue_lock, flags);
+}
+
+/*
+ * For all update functions, key should be a valid pointer because these
+ * update functions are called under blkcg_lock, that means, blkg is
+ * valid and in turn key is valid. queue exit path can not race becuase
+ * of blkcg_lock
+ *
+ * Can not take queue lock in update functions as queue lock under blkcg_lock
+ * is not allowed. Under other paths we take blkcg_lock under queue_lock.
+ */
+static void throtl_update_blkio_group_read_bps(void *key,
+ struct blkio_group *blkg, u64 read_bps)
+{
+ struct throtl_data *td = key;
+
+ tg_of_blkg(blkg)->bps[READ] = read_bps;
+ /* Make sure read_bps is updated before setting limits_changed */
+ smp_wmb();
+ tg_of_blkg(blkg)->limits_changed = true;
+
+ /* Make sure tg->limits_changed is updated before td->limits_changed */
+ smp_mb__before_atomic_inc();
+ atomic_inc(&td->limits_changed);
+ smp_mb__after_atomic_inc();
+
+ /* Schedule a work now to process the limit change */
+ throtl_schedule_delayed_work(td->queue, 0);
+}
+
+static void throtl_update_blkio_group_write_bps(void *key,
+ struct blkio_group *blkg, u64 write_bps)
+{
+ struct throtl_data *td = key;
+
+ tg_of_blkg(blkg)->bps[WRITE] = write_bps;
+ smp_wmb();
+ tg_of_blkg(blkg)->limits_changed = true;
+ smp_mb__before_atomic_inc();
+ atomic_inc(&td->limits_changed);
+ smp_mb__after_atomic_inc();
+ throtl_schedule_delayed_work(td->queue, 0);
+}
+
+static void throtl_update_blkio_group_read_iops(void *key,
+ struct blkio_group *blkg, unsigned int read_iops)
+{
+ struct throtl_data *td = key;
+
+ tg_of_blkg(blkg)->iops[READ] = read_iops;
+ smp_wmb();
+ tg_of_blkg(blkg)->limits_changed = true;
+ smp_mb__before_atomic_inc();
+ atomic_inc(&td->limits_changed);
+ smp_mb__after_atomic_inc();
+ throtl_schedule_delayed_work(td->queue, 0);
+}
+
+static void throtl_update_blkio_group_write_iops(void *key,
+ struct blkio_group *blkg, unsigned int write_iops)
+{
+ struct throtl_data *td = key;
+
+ tg_of_blkg(blkg)->iops[WRITE] = write_iops;
+ smp_wmb();
+ tg_of_blkg(blkg)->limits_changed = true;
+ smp_mb__before_atomic_inc();
+ atomic_inc(&td->limits_changed);
+ smp_mb__after_atomic_inc();
+ throtl_schedule_delayed_work(td->queue, 0);
+}
+
+void throtl_shutdown_timer_wq(struct request_queue *q)
+{
+ struct throtl_data *td = q->td;
+
+ cancel_delayed_work_sync(&td->throtl_work);
+}
+
+static struct blkio_policy_type blkio_policy_throtl = {
+ .ops = {
+ .blkio_unlink_group_fn = throtl_unlink_blkio_group,
+ .blkio_update_group_read_bps_fn =
+ throtl_update_blkio_group_read_bps,
+ .blkio_update_group_write_bps_fn =
+ throtl_update_blkio_group_write_bps,
+ .blkio_update_group_read_iops_fn =
+ throtl_update_blkio_group_read_iops,
+ .blkio_update_group_write_iops_fn =
+ throtl_update_blkio_group_write_iops,
+ },
+ .plid = BLKIO_POLICY_THROTL,
+};
+
+int blk_throtl_bio(struct request_queue *q, struct bio **biop)
+{
+ struct throtl_data *td = q->td;
+ struct throtl_grp *tg;
+ struct bio *bio = *biop;
+ bool rw = bio_data_dir(bio), update_disptime = true;
+
+ if (bio->bi_rw & REQ_THROTTLED) {
+ bio->bi_rw &= ~REQ_THROTTLED;
+ return 0;
+ }
+
+ spin_lock_irq(q->queue_lock);
+ tg = throtl_get_tg(td);
+
+ if (tg->nr_queued[rw]) {
+ /*
+ * There is already another bio queued in same dir. No
+ * need to update dispatch time.
+ * Still update the disptime if rate limits on this group
+ * were changed.
+ */
+ if (!tg->limits_changed)
+ update_disptime = false;
+ else
+ tg->limits_changed = false;
+
+ goto queue_bio;
+ }
+
+ /* Bio is with-in rate limit of group */
+ if (tg_may_dispatch(td, tg, bio, NULL)) {
+ throtl_charge_bio(tg, bio);
+ goto out;
+ }
+
+queue_bio:
+ throtl_log_tg(td, tg, "[%c] bio. bdisp=%u sz=%u bps=%llu"
+ " iodisp=%u iops=%u queued=%d/%d",
+ rw == READ ? 'R' : 'W',
+ tg->bytes_disp[rw], bio->bi_size, tg->bps[rw],
+ tg->io_disp[rw], tg->iops[rw],
+ tg->nr_queued[READ], tg->nr_queued[WRITE]);
+
+ throtl_add_bio_tg(q->td, tg, bio);
+ *biop = NULL;
+
+ if (update_disptime) {
+ tg_update_disptime(td, tg);
+ throtl_schedule_next_dispatch(td);
+ }
+
+out:
+ spin_unlock_irq(q->queue_lock);
+ return 0;
+}
+
+int blk_throtl_init(struct request_queue *q)
+{
+ struct throtl_data *td;
+ struct throtl_grp *tg;
+
+ td = kzalloc_node(sizeof(*td), GFP_KERNEL, q->node);
+ if (!td)
+ return -ENOMEM;
+
+ INIT_HLIST_HEAD(&td->tg_list);
+ td->tg_service_tree = THROTL_RB_ROOT;
+ atomic_set(&td->limits_changed, 0);
+
+ /* Init root group */
+ tg = &td->root_tg;
+ INIT_HLIST_NODE(&tg->tg_node);
+ RB_CLEAR_NODE(&tg->rb_node);
+ bio_list_init(&tg->bio_lists[0]);
+ bio_list_init(&tg->bio_lists[1]);
+
+ /* Practically unlimited BW */
+ tg->bps[0] = tg->bps[1] = -1;
+ tg->iops[0] = tg->iops[1] = -1;
+
+ /*
+ * Set root group reference to 2. One reference will be dropped when
+ * all groups on tg_list are being deleted during queue exit. Other
+ * reference will remain there as we don't want to delete this group
+ * as it is statically allocated and gets destroyed when throtl_data
+ * goes away.
+ */
+ atomic_set(&tg->ref, 2);
+ hlist_add_head(&tg->tg_node, &td->tg_list);
+ td->nr_undestroyed_grps++;
+
+ INIT_DELAYED_WORK(&td->throtl_work, blk_throtl_work);
+
+ rcu_read_lock();
+ blkiocg_add_blkio_group(&blkio_root_cgroup, &tg->blkg, (void *)td,
+ 0, BLKIO_POLICY_THROTL);
+ rcu_read_unlock();
+
+ /* Attach throtl data to request queue */
+ td->queue = q;
+ q->td = td;
+ return 0;
+}
+
+void blk_throtl_exit(struct request_queue *q)
+{
+ struct throtl_data *td = q->td;
+ bool wait = false;
+
+ BUG_ON(!td);
+
+ throtl_shutdown_timer_wq(q);
+
+ spin_lock_irq(q->queue_lock);
+ throtl_release_tgs(td);
+
+ /* If there are other groups */
+ if (td->nr_undestroyed_grps > 0)
+ wait = true;
+
+ spin_unlock_irq(q->queue_lock);
+
+ /*
+ * Wait for tg->blkg->key accessors to exit their grace periods.
+ * Do this wait only if there are other undestroyed groups out
+ * there (other than root group). This can happen if cgroup deletion
+ * path claimed the responsibility of cleaning up a group before
+ * queue cleanup code get to the group.
+ *
+ * Do not call synchronize_rcu() unconditionally as there are drivers
+ * which create/delete request queue hundreds of times during scan/boot
+ * and synchronize_rcu() can take significant time and slow down boot.
+ */
+ if (wait)
+ synchronize_rcu();
+
+ /*
+ * Just being safe to make sure after previous flush if some body did
+ * update limits through cgroup and another work got queued, cancel
+ * it.
+ */
+ throtl_shutdown_timer_wq(q);
+ throtl_td_free(td);
+}
+
+static int __init throtl_init(void)
+{
+ blkio_policy_register(&blkio_policy_throtl);
+ return 0;
+}
+
+module_init(throtl_init);
diff --git a/block/blk.h b/block/blk.h
index d6b911ac002c..1e675e5ade02 100644
--- a/block/blk.h
+++ b/block/blk.h
@@ -51,6 +51,8 @@ static inline void blk_clear_rq_complete(struct request *rq)
*/
#define ELV_ON_HASH(rq) (!hlist_unhashed(&(rq)->hash))
+struct request *blk_do_flush(struct request_queue *q, struct request *rq);
+
static inline struct request *__elv_next_request(struct request_queue *q)
{
struct request *rq;
@@ -58,7 +60,11 @@ static inline struct request *__elv_next_request(struct request_queue *q)
while (1) {
while (!list_empty(&q->queue_head)) {
rq = list_entry_rq(q->queue_head.next);
- if (blk_do_ordered(q, &rq))
+ if (!(rq->cmd_flags & (REQ_FLUSH | REQ_FUA)) ||
+ rq == &q->flush_rq)
+ return rq;
+ rq = blk_do_flush(q, rq);
+ if (rq)
return rq;
}
@@ -110,10 +116,6 @@ void blk_queue_congestion_threshold(struct request_queue *q);
int blk_dev_init(void);
-void elv_quiesce_start(struct request_queue *q);
-void elv_quiesce_end(struct request_queue *q);
-
-
/*
* Return the threshold (number of used requests) at which the queue is
* considered to be congested. It include a little hysteresis to keep the
@@ -132,14 +134,6 @@ static inline int queue_congestion_off_threshold(struct request_queue *q)
return q->nr_congestion_off;
}
-#if defined(CONFIG_BLK_DEV_INTEGRITY)
-
-#define rq_for_each_integrity_segment(bvl, _rq, _iter) \
- __rq_for_each_bio(_iter.bio, _rq) \
- bip_for_each_vec(bvl, _iter.bio->bi_integrity, _iter.i)
-
-#endif /* BLK_DEV_INTEGRITY */
-
static inline int blk_cpu_to_group(int cpu)
{
int group = NR_CPUS;
diff --git a/block/bsg.c b/block/bsg.c
index 82d58829ba59..f20d6a789d48 100644
--- a/block/bsg.c
+++ b/block/bsg.c
@@ -20,7 +20,6 @@
#include <linux/uio.h>
#include <linux/idr.h>
#include <linux/bsg.h>
-#include <linux/smp_lock.h>
#include <linux/slab.h>
#include <scsi/scsi.h>
@@ -426,7 +425,7 @@ static int blk_complete_sgv4_hdr_rq(struct request *rq, struct sg_io_v4 *hdr,
/*
* fill in all the output members
*/
- hdr->device_status = status_byte(rq->errors);
+ hdr->device_status = rq->errors & 0xff;
hdr->transport_status = host_byte(rq->errors);
hdr->driver_status = driver_byte(rq->errors);
hdr->info = 0;
@@ -843,9 +842,7 @@ static int bsg_open(struct inode *inode, struct file *file)
{
struct bsg_device *bd;
- lock_kernel();
bd = bsg_get_device(inode, file);
- unlock_kernel();
if (IS_ERR(bd))
return PTR_ERR(bd);
@@ -968,6 +965,7 @@ static const struct file_operations bsg_fops = {
.release = bsg_release,
.unlocked_ioctl = bsg_ioctl,
.owner = THIS_MODULE,
+ .llseek = default_llseek,
};
void bsg_unregister_queue(struct request_queue *q)
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 9eba291eb6fd..4cd59b0d7c15 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -160,6 +160,7 @@ enum wl_prio_t {
BE_WORKLOAD = 0,
RT_WORKLOAD = 1,
IDLE_WORKLOAD = 2,
+ CFQ_PRIO_NR,
};
/*
@@ -184,10 +185,19 @@ struct cfq_group {
/* number of cfqq currently on this group */
int nr_cfqq;
- /* Per group busy queus average. Useful for workload slice calc. */
- unsigned int busy_queues_avg[2];
/*
- * rr lists of queues with requests, onle rr for each priority class.
+ * Per group busy queus average. Useful for workload slice calc. We
+ * create the array for each prio class but at run time it is used
+ * only for RT and BE class and slot for IDLE class remains unused.
+ * This is primarily done to avoid confusion and a gcc warning.
+ */
+ unsigned int busy_queues_avg[CFQ_PRIO_NR];
+ /*
+ * rr lists of queues with requests. We maintain service trees for
+ * RT and BE classes. These trees are subdivided in subclasses
+ * of SYNC, SYNC_NOIDLE and ASYNC based on workload type. For IDLE
+ * class there is no subclassification and all the cfq queues go on
+ * a single tree service_tree_idle.
* Counts are embedded in the cfq_rb_root
*/
struct cfq_rb_root service_trees[2][3];
@@ -221,7 +231,6 @@ struct cfq_data {
enum wl_type_t serving_type;
unsigned long workload_expires;
struct cfq_group *serving_group;
- bool noidle_tree_requires_idle;
/*
* Each priority tree is sorted by next_request position. These
@@ -977,8 +986,8 @@ static inline struct cfq_group *cfqg_of_blkg(struct blkio_group *blkg)
return NULL;
}
-void
-cfq_update_blkio_group_weight(struct blkio_group *blkg, unsigned int weight)
+void cfq_update_blkio_group_weight(void *key, struct blkio_group *blkg,
+ unsigned int weight)
{
cfqg_of_blkg(blkg)->weight = weight;
}
@@ -2180,7 +2189,6 @@ static void choose_service_tree(struct cfq_data *cfqd, struct cfq_group *cfqg)
slice = max_t(unsigned, slice, CFQ_MIN_TT);
cfq_log(cfqd, "workload slice:%d", slice);
cfqd->workload_expires = jiffies + slice;
- cfqd->noidle_tree_requires_idle = false;
}
static struct cfq_group *cfq_get_next_cfqg(struct cfq_data *cfqd)
@@ -3177,7 +3185,9 @@ cfq_update_idle_window(struct cfq_data *cfqd, struct cfq_queue *cfqq,
if (cfqq->queued[0] + cfqq->queued[1] >= 4)
cfq_mark_cfqq_deep(cfqq);
- if (!atomic_read(&cic->ioc->nr_tasks) || !cfqd->cfq_slice_idle ||
+ if (cfqq->next_rq && (cfqq->next_rq->cmd_flags & REQ_NOIDLE))
+ enable_idle = 0;
+ else if (!atomic_read(&cic->ioc->nr_tasks) || !cfqd->cfq_slice_idle ||
(!cfq_cfqq_deep(cfqq) && CFQQ_SEEKY(cfqq)))
enable_idle = 0;
else if (sample_valid(cic->ttime_samples)) {
@@ -3494,17 +3504,7 @@ static void cfq_completed_request(struct request_queue *q, struct request *rq)
cfq_slice_expired(cfqd, 1);
else if (sync && cfqq_empty &&
!cfq_close_cooperator(cfqd, cfqq)) {
- cfqd->noidle_tree_requires_idle |=
- !(rq->cmd_flags & REQ_NOIDLE);
- /*
- * Idling is enabled for SYNC_WORKLOAD.
- * SYNC_NOIDLE_WORKLOAD idles at the end of the tree
- * only if we processed at least one !REQ_NOIDLE request
- */
- if (cfqd->serving_type == SYNC_WORKLOAD
- || cfqd->noidle_tree_requires_idle
- || cfqq->cfqg->nr_cfqq == 1)
- cfq_arm_slice_timer(cfqd);
+ cfq_arm_slice_timer(cfqd);
}
}
@@ -4090,6 +4090,7 @@ static struct blkio_policy_type blkio_policy_cfq = {
.blkio_unlink_group_fn = cfq_unlink_blkio_group,
.blkio_update_group_weight_fn = cfq_update_blkio_group_weight,
},
+ .plid = BLKIO_POLICY_PROP,
};
#else
static struct blkio_policy_type blkio_policy_cfq;
diff --git a/block/cfq.h b/block/cfq.h
index 93448e5a2e41..54a6d90f8e8c 100644
--- a/block/cfq.h
+++ b/block/cfq.h
@@ -69,7 +69,7 @@ static inline void cfq_blkiocg_update_completion_stats(struct blkio_group *blkg,
static inline void cfq_blkiocg_add_blkio_group(struct blkio_cgroup *blkcg,
struct blkio_group *blkg, void *key, dev_t dev) {
- blkiocg_add_blkio_group(blkcg, blkg, key, dev);
+ blkiocg_add_blkio_group(blkcg, blkg, key, dev, BLKIO_POLICY_PROP);
}
static inline int cfq_blkiocg_del_blkio_group(struct blkio_group *blkg)
diff --git a/block/elevator.c b/block/elevator.c
index 205b09a5bd9e..282e8308f7e2 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -617,8 +617,6 @@ void elv_quiesce_end(struct request_queue *q)
void elv_insert(struct request_queue *q, struct request *rq, int where)
{
- struct list_head *pos;
- unsigned ordseq;
int unplug_it = 1;
trace_block_rq_insert(q, rq);
@@ -626,9 +624,16 @@ void elv_insert(struct request_queue *q, struct request *rq, int where)
rq->q = q;
switch (where) {
+ case ELEVATOR_INSERT_REQUEUE:
+ /*
+ * Most requeues happen because of a busy condition,
+ * don't force unplug of the queue for that case.
+ * Clear unplug_it and fall through.
+ */
+ unplug_it = 0;
+
case ELEVATOR_INSERT_FRONT:
rq->cmd_flags |= REQ_SOFTBARRIER;
-
list_add(&rq->queuelist, &q->queue_head);
break;
@@ -668,36 +673,6 @@ void elv_insert(struct request_queue *q, struct request *rq, int where)
q->elevator->ops->elevator_add_req_fn(q, rq);
break;
- case ELEVATOR_INSERT_REQUEUE:
- /*
- * If ordered flush isn't in progress, we do front
- * insertion; otherwise, requests should be requeued
- * in ordseq order.
- */
- rq->cmd_flags |= REQ_SOFTBARRIER;
-
- /*
- * Most requeues happen because of a busy condition,
- * don't force unplug of the queue for that case.
- */
- unplug_it = 0;
-
- if (q->ordseq == 0) {
- list_add(&rq->queuelist, &q->queue_head);
- break;
- }
-
- ordseq = blk_ordered_req_seq(rq);
-
- list_for_each(pos, &q->queue_head) {
- struct request *pos_rq = list_entry_rq(pos);
- if (ordseq <= blk_ordered_req_seq(pos_rq))
- break;
- }
-
- list_add_tail(&rq->queuelist, pos);
- break;
-
default:
printk(KERN_ERR "%s: bad insertion point %d\n",
__func__, where);
@@ -716,26 +691,8 @@ void elv_insert(struct request_queue *q, struct request *rq, int where)
void __elv_add_request(struct request_queue *q, struct request *rq, int where,
int plug)
{
- if (q->ordcolor)
- rq->cmd_flags |= REQ_ORDERED_COLOR;
-
if (rq->cmd_flags & (REQ_SOFTBARRIER | REQ_HARDBARRIER)) {
- /*
- * toggle ordered color
- */
- if (rq->cmd_flags & REQ_HARDBARRIER)
- q->ordcolor ^= 1;
-
- /*
- * barriers implicitly indicate back insertion
- */
- if (where == ELEVATOR_INSERT_SORT)
- where = ELEVATOR_INSERT_BACK;
-
- /*
- * this request is scheduling boundary, update
- * end_sector
- */
+ /* barriers are scheduling boundary, update end_sector */
if (rq->cmd_type == REQ_TYPE_FS ||
(rq->cmd_flags & REQ_DISCARD)) {
q->end_sector = rq_end_sector(rq);
@@ -855,24 +812,6 @@ void elv_completed_request(struct request_queue *q, struct request *rq)
e->ops->elevator_completed_req_fn)
e->ops->elevator_completed_req_fn(q, rq);
}
-
- /*
- * Check if the queue is waiting for fs requests to be
- * drained for flush sequence.
- */
- if (unlikely(q->ordseq)) {
- struct request *next = NULL;
-
- if (!list_empty(&q->queue_head))
- next = list_entry_rq(q->queue_head.next);
-
- if (!queue_in_flight(q) &&
- blk_ordered_cur_seq(q) == QUEUE_ORDSEQ_DRAIN &&
- (!next || blk_ordered_req_seq(next) > QUEUE_ORDSEQ_DRAIN)) {
- blk_ordered_complete_seq(q, QUEUE_ORDSEQ_DRAIN, 0);
- __blk_run_queue(q);
- }
- }
}
#define to_elv(atr) container_of((atr), struct elv_fs_entry, attr)
@@ -938,6 +877,7 @@ int elv_register_queue(struct request_queue *q)
}
}
kobject_uevent(&e->kobj, KOBJ_ADD);
+ e->registered = 1;
}
return error;
}
@@ -947,6 +887,7 @@ static void __elv_unregister_queue(struct elevator_queue *e)
{
kobject_uevent(&e->kobj, KOBJ_REMOVE);
kobject_del(&e->kobj);
+ e->registered = 0;
}
void elv_unregister_queue(struct request_queue *q)
@@ -1042,11 +983,13 @@ static int elevator_switch(struct request_queue *q, struct elevator_type *new_e)
spin_unlock_irq(q->queue_lock);
- __elv_unregister_queue(old_elevator);
+ if (old_elevator->registered) {
+ __elv_unregister_queue(old_elevator);
- err = elv_register_queue(q);
- if (err)
- goto fail_register;
+ err = elv_register_queue(q);
+ if (err)
+ goto fail_register;
+ }
/*
* finally exit old elevator and turn off BYPASS.
diff --git a/block/genhd.c b/block/genhd.c
index 59a2db6fecef..a8adf96a4b41 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -22,9 +22,7 @@
#include "blk.h"
static DEFINE_MUTEX(block_class_lock);
-#ifndef CONFIG_SYSFS_DEPRECATED
struct kobject *block_depr;
-#endif
/* for extended dynamic devt allocation, currently only one major is used */
#define MAX_EXT_DEVT (1 << MINORBITS)
@@ -541,13 +539,15 @@ void add_disk(struct gendisk *disk)
disk->major = MAJOR(devt);
disk->first_minor = MINOR(devt);
+ /* Register BDI before referencing it from bdev */
+ bdi = &disk->queue->backing_dev_info;
+ bdi_register_dev(bdi, disk_devt(disk));
+
blk_register_region(disk_devt(disk), disk->minors, NULL,
exact_match, exact_lock, disk);
register_disk(disk);
blk_register_queue(disk);
- bdi = &disk->queue->backing_dev_info;
- bdi_register_dev(bdi, disk_devt(disk));
retval = sysfs_create_link(&disk_to_dev(disk)->kobj, &bdi->dev->kobj,
"bdi");
WARN_ON(retval);
@@ -642,6 +642,7 @@ void __init printk_all_partitions(void)
struct hd_struct *part;
char name_buf[BDEVNAME_SIZE];
char devt_buf[BDEVT_SIZE];
+ u8 uuid[PARTITION_META_INFO_UUIDLTH * 2 + 1];
/*
* Don't show empty devices or things that have been
@@ -660,10 +661,14 @@ void __init printk_all_partitions(void)
while ((part = disk_part_iter_next(&piter))) {
bool is_part0 = part == &disk->part0;
- printk("%s%s %10llu %s", is_part0 ? "" : " ",
+ uuid[0] = 0;
+ if (part->info)
+ part_unpack_uuid(part->info->uuid, uuid);
+
+ printk("%s%s %10llu %s %s", is_part0 ? "" : " ",
bdevt_str(part_devt(part), devt_buf),
(unsigned long long)part->nr_sects >> 1,
- disk_name(disk, part->partno, name_buf));
+ disk_name(disk, part->partno, name_buf), uuid);
if (is_part0) {
if (disk->driverfs_dev != NULL &&
disk->driverfs_dev->driver != NULL)
@@ -803,10 +808,9 @@ static int __init genhd_device_init(void)
register_blkdev(BLOCK_EXT_MAJOR, "blkext");
-#ifndef CONFIG_SYSFS_DEPRECATED
/* create top-level block dir */
- block_depr = kobject_create_and_add("block", NULL);
-#endif
+ if (!sysfs_deprecated)
+ block_depr = kobject_create_and_add("block", NULL);
return 0;
}
@@ -925,8 +929,15 @@ static void disk_free_ptbl_rcu_cb(struct rcu_head *head)
{
struct disk_part_tbl *ptbl =
container_of(head, struct disk_part_tbl, rcu_head);
+ struct gendisk *disk = ptbl->disk;
+ struct request_queue *q = disk->queue;
+ unsigned long flags;
kfree(ptbl);
+
+ spin_lock_irqsave(q->queue_lock, flags);
+ elv_quiesce_end(q);
+ spin_unlock_irqrestore(q->queue_lock, flags);
}
/**
@@ -944,11 +955,17 @@ static void disk_replace_part_tbl(struct gendisk *disk,
struct disk_part_tbl *new_ptbl)
{
struct disk_part_tbl *old_ptbl = disk->part_tbl;
+ struct request_queue *q = disk->queue;
rcu_assign_pointer(disk->part_tbl, new_ptbl);
if (old_ptbl) {
rcu_assign_pointer(old_ptbl->last_lookup, NULL);
+
+ spin_lock_irq(q->queue_lock);
+ elv_quiesce_start(q);
+ spin_unlock_irq(q->queue_lock);
+
call_rcu(&old_ptbl->rcu_head, disk_free_ptbl_rcu_cb);
}
}
@@ -989,6 +1006,7 @@ int disk_expand_part_tbl(struct gendisk *disk, int partno)
return -ENOMEM;
new_ptbl->len = target;
+ new_ptbl->disk = disk;
for (i = 0; i < len; i++)
rcu_assign_pointer(new_ptbl->part[i], old_ptbl->part[i]);
@@ -1004,6 +1022,7 @@ static void disk_release(struct device *dev)
kfree(disk->random);
disk_replace_part_tbl(disk, NULL);
free_part_stats(&disk->part0);
+ free_part_info(&disk->part0);
kfree(disk);
}
struct class block_class = {
diff --git a/block/ioctl.c b/block/ioctl.c
index d8052f0dabd3..d724ceb1d465 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -62,7 +62,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user
/* all seems OK */
part = add_partition(disk, partno, start, length,
- ADDPART_FLAG_NONE);
+ ADDPART_FLAG_NONE, NULL);
mutex_unlock(&bdev->bd_mutex);
return IS_ERR(part) ? PTR_ERR(part) : 0;
case BLKPG_DEL_PARTITION:
@@ -116,7 +116,7 @@ static int blkdev_reread_part(struct block_device *bdev)
static int blk_ioctl_discard(struct block_device *bdev, uint64_t start,
uint64_t len, int secure)
{
- unsigned long flags = BLKDEV_IFL_WAIT;
+ unsigned long flags = 0;
if (start & 511)
return -EINVAL;
@@ -128,7 +128,7 @@ static int blk_ioctl_discard(struct block_device *bdev, uint64_t start,
if (start + len > (bdev->bd_inode->i_size >> 9))
return -EINVAL;
if (secure)
- flags |= BLKDEV_IFL_SECURE;
+ flags |= BLKDEV_DISCARD_SECURE;
return blkdev_issue_discard(bdev, start, len, GFP_KERNEL, flags);
}
diff --git a/crypto/des_generic.c b/crypto/des_generic.c
index 249f903cc453..873818d48e86 100644
--- a/crypto/des_generic.c
+++ b/crypto/des_generic.c
@@ -614,7 +614,7 @@ static const u32 S8[64] = {
#define T3(x) pt[2 * (x) + 2]
#define T4(x) pt[2 * (x) + 3]
-#define PC2(a, b, c, d) (T4(d) | T3(c) | T2(b) | T1(a))
+#define DES_PC2(a, b, c, d) (T4(d) | T3(c) | T2(b) | T1(a))
/*
* Encryption key expansion
@@ -639,22 +639,22 @@ unsigned long des_ekey(u32 *pe, const u8 *k)
b = k[6]; b &= 0x0e; b <<= 4; b |= k[2] & 0x1e; b = pc1[b];
a = k[7]; a &= 0x0e; a <<= 4; a |= k[3] & 0x1e; a = pc1[a];
- pe[15 * 2 + 0] = PC2(a, b, c, d); d = rs[d];
- pe[14 * 2 + 0] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
- pe[13 * 2 + 0] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
- pe[12 * 2 + 0] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
- pe[11 * 2 + 0] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
- pe[10 * 2 + 0] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
- pe[ 9 * 2 + 0] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
- pe[ 8 * 2 + 0] = PC2(d, a, b, c); c = rs[c];
- pe[ 7 * 2 + 0] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
- pe[ 6 * 2 + 0] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
- pe[ 5 * 2 + 0] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
- pe[ 4 * 2 + 0] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
- pe[ 3 * 2 + 0] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
- pe[ 2 * 2 + 0] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
- pe[ 1 * 2 + 0] = PC2(c, d, a, b); b = rs[b];
- pe[ 0 * 2 + 0] = PC2(b, c, d, a);
+ pe[15 * 2 + 0] = DES_PC2(a, b, c, d); d = rs[d];
+ pe[14 * 2 + 0] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b];
+ pe[13 * 2 + 0] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d];
+ pe[12 * 2 + 0] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b];
+ pe[11 * 2 + 0] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d];
+ pe[10 * 2 + 0] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b];
+ pe[ 9 * 2 + 0] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d];
+ pe[ 8 * 2 + 0] = DES_PC2(d, a, b, c); c = rs[c];
+ pe[ 7 * 2 + 0] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a];
+ pe[ 6 * 2 + 0] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c];
+ pe[ 5 * 2 + 0] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a];
+ pe[ 4 * 2 + 0] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c];
+ pe[ 3 * 2 + 0] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a];
+ pe[ 2 * 2 + 0] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c];
+ pe[ 1 * 2 + 0] = DES_PC2(c, d, a, b); b = rs[b];
+ pe[ 0 * 2 + 0] = DES_PC2(b, c, d, a);
/* Check if first half is weak */
w = (a ^ c) | (b ^ d) | (rs[a] ^ c) | (b ^ rs[d]);
@@ -670,22 +670,22 @@ unsigned long des_ekey(u32 *pe, const u8 *k)
/* Check if second half is weak */
w |= (a ^ c) | (b ^ d) | (rs[a] ^ c) | (b ^ rs[d]);
- pe[15 * 2 + 1] = PC2(a, b, c, d); d = rs[d];
- pe[14 * 2 + 1] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
- pe[13 * 2 + 1] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
- pe[12 * 2 + 1] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
- pe[11 * 2 + 1] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
- pe[10 * 2 + 1] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
- pe[ 9 * 2 + 1] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
- pe[ 8 * 2 + 1] = PC2(d, a, b, c); c = rs[c];
- pe[ 7 * 2 + 1] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
- pe[ 6 * 2 + 1] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
- pe[ 5 * 2 + 1] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
- pe[ 4 * 2 + 1] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
- pe[ 3 * 2 + 1] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
- pe[ 2 * 2 + 1] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
- pe[ 1 * 2 + 1] = PC2(c, d, a, b); b = rs[b];
- pe[ 0 * 2 + 1] = PC2(b, c, d, a);
+ pe[15 * 2 + 1] = DES_PC2(a, b, c, d); d = rs[d];
+ pe[14 * 2 + 1] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b];
+ pe[13 * 2 + 1] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d];
+ pe[12 * 2 + 1] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b];
+ pe[11 * 2 + 1] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d];
+ pe[10 * 2 + 1] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b];
+ pe[ 9 * 2 + 1] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d];
+ pe[ 8 * 2 + 1] = DES_PC2(d, a, b, c); c = rs[c];
+ pe[ 7 * 2 + 1] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a];
+ pe[ 6 * 2 + 1] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c];
+ pe[ 5 * 2 + 1] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a];
+ pe[ 4 * 2 + 1] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c];
+ pe[ 3 * 2 + 1] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a];
+ pe[ 2 * 2 + 1] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c];
+ pe[ 1 * 2 + 1] = DES_PC2(c, d, a, b); b = rs[b];
+ pe[ 0 * 2 + 1] = DES_PC2(b, c, d, a);
/* Fixup: 2413 5768 -> 1357 2468 */
for (d = 0; d < 16; ++d) {
@@ -722,22 +722,22 @@ static void dkey(u32 *pe, const u8 *k)
b = k[6]; b &= 0x0e; b <<= 4; b |= k[2] & 0x1e; b = pc1[b];
a = k[7]; a &= 0x0e; a <<= 4; a |= k[3] & 0x1e; a = pc1[a];
- pe[ 0 * 2] = PC2(a, b, c, d); d = rs[d];
- pe[ 1 * 2] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
- pe[ 2 * 2] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
- pe[ 3 * 2] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
- pe[ 4 * 2] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
- pe[ 5 * 2] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
- pe[ 6 * 2] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
- pe[ 7 * 2] = PC2(d, a, b, c); c = rs[c];
- pe[ 8 * 2] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
- pe[ 9 * 2] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
- pe[10 * 2] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
- pe[11 * 2] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
- pe[12 * 2] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
- pe[13 * 2] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
- pe[14 * 2] = PC2(c, d, a, b); b = rs[b];
- pe[15 * 2] = PC2(b, c, d, a);
+ pe[ 0 * 2] = DES_PC2(a, b, c, d); d = rs[d];
+ pe[ 1 * 2] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b];
+ pe[ 2 * 2] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d];
+ pe[ 3 * 2] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b];
+ pe[ 4 * 2] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d];
+ pe[ 5 * 2] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b];
+ pe[ 6 * 2] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d];
+ pe[ 7 * 2] = DES_PC2(d, a, b, c); c = rs[c];
+ pe[ 8 * 2] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a];
+ pe[ 9 * 2] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c];
+ pe[10 * 2] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a];
+ pe[11 * 2] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c];
+ pe[12 * 2] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a];
+ pe[13 * 2] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c];
+ pe[14 * 2] = DES_PC2(c, d, a, b); b = rs[b];
+ pe[15 * 2] = DES_PC2(b, c, d, a);
/* Skip to next table set */
pt += 512;
@@ -747,22 +747,22 @@ static void dkey(u32 *pe, const u8 *k)
b = k[2]; b &= 0xe0; b >>= 4; b |= k[6] & 0xf0; b = pc1[b + 1];
a = k[3]; a &= 0xe0; a >>= 4; a |= k[7] & 0xf0; a = pc1[a + 1];
- pe[ 0 * 2 + 1] = PC2(a, b, c, d); d = rs[d];
- pe[ 1 * 2 + 1] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
- pe[ 2 * 2 + 1] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
- pe[ 3 * 2 + 1] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
- pe[ 4 * 2 + 1] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
- pe[ 5 * 2 + 1] = PC2(d, a, b, c); c = rs[c]; b = rs[b];
- pe[ 6 * 2 + 1] = PC2(b, c, d, a); a = rs[a]; d = rs[d];
- pe[ 7 * 2 + 1] = PC2(d, a, b, c); c = rs[c];
- pe[ 8 * 2 + 1] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
- pe[ 9 * 2 + 1] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
- pe[10 * 2 + 1] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
- pe[11 * 2 + 1] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
- pe[12 * 2 + 1] = PC2(c, d, a, b); b = rs[b]; a = rs[a];
- pe[13 * 2 + 1] = PC2(a, b, c, d); d = rs[d]; c = rs[c];
- pe[14 * 2 + 1] = PC2(c, d, a, b); b = rs[b];
- pe[15 * 2 + 1] = PC2(b, c, d, a);
+ pe[ 0 * 2 + 1] = DES_PC2(a, b, c, d); d = rs[d];
+ pe[ 1 * 2 + 1] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b];
+ pe[ 2 * 2 + 1] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d];
+ pe[ 3 * 2 + 1] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b];
+ pe[ 4 * 2 + 1] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d];
+ pe[ 5 * 2 + 1] = DES_PC2(d, a, b, c); c = rs[c]; b = rs[b];
+ pe[ 6 * 2 + 1] = DES_PC2(b, c, d, a); a = rs[a]; d = rs[d];
+ pe[ 7 * 2 + 1] = DES_PC2(d, a, b, c); c = rs[c];
+ pe[ 8 * 2 + 1] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a];
+ pe[ 9 * 2 + 1] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c];
+ pe[10 * 2 + 1] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a];
+ pe[11 * 2 + 1] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c];
+ pe[12 * 2 + 1] = DES_PC2(c, d, a, b); b = rs[b]; a = rs[a];
+ pe[13 * 2 + 1] = DES_PC2(a, b, c, d); d = rs[d]; c = rs[c];
+ pe[14 * 2 + 1] = DES_PC2(c, d, a, b); b = rs[b];
+ pe[15 * 2 + 1] = DES_PC2(b, c, d, a);
/* Fixup: 2413 5768 -> 1357 2468 */
for (d = 0; d < 16; ++d) {
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index b811f2173f6f..88681aca88c5 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -105,7 +105,7 @@ config ACPI_EC_DEBUGFS
Be aware that using this interface can confuse your Embedded
Controller in a way that a normal reboot is not enough. You then
- have to power of your system, and remove the laptop battery for
+ have to power off your system, and remove the laptop battery for
some seconds.
An Embedded Controller typically is available on laptops and reads
sensor values like battery state and temperature.
diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c
index b76848c80be3..6afceb3d4034 100644
--- a/drivers/acpi/acpi_pad.c
+++ b/drivers/acpi/acpi_pad.c
@@ -30,18 +30,13 @@
#include <linux/slab.h>
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
+#include <asm/mwait.h>
#define ACPI_PROCESSOR_AGGREGATOR_CLASS "acpi_pad"
#define ACPI_PROCESSOR_AGGREGATOR_DEVICE_NAME "Processor Aggregator"
#define ACPI_PROCESSOR_AGGREGATOR_NOTIFY 0x80
static DEFINE_MUTEX(isolated_cpus_lock);
-#define MWAIT_SUBSTATE_MASK (0xf)
-#define MWAIT_CSTATE_MASK (0xf)
-#define MWAIT_SUBSTATE_SIZE (4)
-#define CPUID_MWAIT_LEAF (5)
-#define CPUID5_ECX_EXTENSIONS_SUPPORTED (0x1)
-#define CPUID5_ECX_INTERRUPT_BREAK (0x2)
static unsigned long power_saving_mwait_eax;
static unsigned char tsc_detected_unstable;
@@ -382,31 +377,32 @@ static void acpi_pad_remove_sysfs(struct acpi_device *device)
device_remove_file(&device->dev, &dev_attr_rrtime);
}
-/* Query firmware how many CPUs should be idle */
-static int acpi_pad_pur(acpi_handle handle, int *num_cpus)
+/*
+ * Query firmware how many CPUs should be idle
+ * return -1 on failure
+ */
+static int acpi_pad_pur(acpi_handle handle)
{
struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
union acpi_object *package;
- int rev, num, ret = -EINVAL;
+ int num = -1;
if (ACPI_FAILURE(acpi_evaluate_object(handle, "_PUR", NULL, &buffer)))
- return -EINVAL;
+ return num;
if (!buffer.length || !buffer.pointer)
- return -EINVAL;
+ return num;
package = buffer.pointer;
- if (package->type != ACPI_TYPE_PACKAGE || package->package.count != 2)
- goto out;
- rev = package->package.elements[0].integer.value;
- num = package->package.elements[1].integer.value;
- if (rev != 1 || num < 0)
- goto out;
- *num_cpus = num;
- ret = 0;
-out:
+
+ if (package->type == ACPI_TYPE_PACKAGE &&
+ package->package.count == 2 &&
+ package->package.elements[0].integer.value == 1) /* rev 1 */
+
+ num = package->package.elements[1].integer.value;
+
kfree(buffer.pointer);
- return ret;
+ return num;
}
/* Notify firmware how many CPUs are idle */
@@ -433,7 +429,8 @@ static void acpi_pad_handle_notify(acpi_handle handle)
uint32_t idle_cpus;
mutex_lock(&isolated_cpus_lock);
- if (acpi_pad_pur(handle, &num_cpus)) {
+ num_cpus = acpi_pad_pur(handle);
+ if (num_cpus < 0) {
mutex_unlock(&isolated_cpus_lock);
return;
}
diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h
index df85b53a674f..7dad9160f209 100644
--- a/drivers/acpi/acpica/aclocal.h
+++ b/drivers/acpi/acpica/aclocal.h
@@ -854,6 +854,7 @@ struct acpi_bit_register_info {
ACPI_BITMASK_POWER_BUTTON_STATUS | \
ACPI_BITMASK_SLEEP_BUTTON_STATUS | \
ACPI_BITMASK_RT_CLOCK_STATUS | \
+ ACPI_BITMASK_PCIEXP_WAKE_DISABLE | \
ACPI_BITMASK_WAKE_STATUS)
#define ACPI_BITMASK_TIMER_ENABLE 0x0001
diff --git a/drivers/acpi/acpica/exutils.c b/drivers/acpi/acpica/exutils.c
index 74c24d517f81..4093522eed45 100644
--- a/drivers/acpi/acpica/exutils.c
+++ b/drivers/acpi/acpica/exutils.c
@@ -109,7 +109,7 @@ void acpi_ex_enter_interpreter(void)
*
* DESCRIPTION: Reacquire the interpreter execution region from within the
* interpreter code. Failure to enter the interpreter region is a
- * fatal system error. Used in conjuction with
+ * fatal system error. Used in conjunction with
* relinquish_interpreter
*
******************************************************************************/
diff --git a/drivers/acpi/acpica/rsutils.c b/drivers/acpi/acpica/rsutils.c
index 22cfcfbd9fff..491191e6cf69 100644
--- a/drivers/acpi/acpica/rsutils.c
+++ b/drivers/acpi/acpica/rsutils.c
@@ -149,7 +149,7 @@ acpi_rs_move_data(void *destination, void *source, u16 item_count, u8 move_type)
/*
* 16-, 32-, and 64-bit cases must use the move macros that perform
- * endian conversion and/or accomodate hardware that cannot perform
+ * endian conversion and/or accommodate hardware that cannot perform
* misaligned memory transfers
*/
case ACPI_RSC_MOVE16:
diff --git a/drivers/acpi/apei/Kconfig b/drivers/acpi/apei/Kconfig
index 907e350f1c7d..fca34ccfd294 100644
--- a/drivers/acpi/apei/Kconfig
+++ b/drivers/acpi/apei/Kconfig
@@ -34,6 +34,6 @@ config ACPI_APEI_ERST_DEBUG
depends on ACPI_APEI
help
ERST is a way provided by APEI to save and retrieve hardware
- error infomation to and from a persistent store. Enable this
+ error information to and from a persistent store. Enable this
if you want to debugging and testing the ERST kernel support
and firmware implementation.
diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c
index 73fd0c7487c1..4a904a4bf05f 100644
--- a/drivers/acpi/apei/apei-base.c
+++ b/drivers/acpi/apei/apei-base.c
@@ -445,11 +445,15 @@ EXPORT_SYMBOL_GPL(apei_resources_sub);
int apei_resources_request(struct apei_resources *resources,
const char *desc)
{
- struct apei_res *res, *res_bak;
+ struct apei_res *res, *res_bak = NULL;
struct resource *r;
+ int rc;
- apei_resources_sub(resources, &apei_resources_all);
+ rc = apei_resources_sub(resources, &apei_resources_all);
+ if (rc)
+ return rc;
+ rc = -EINVAL;
list_for_each_entry(res, &resources->iomem, list) {
r = request_mem_region(res->start, res->end - res->start,
desc);
@@ -475,7 +479,11 @@ int apei_resources_request(struct apei_resources *resources,
}
}
- apei_resources_merge(&apei_resources_all, resources);
+ rc = apei_resources_merge(&apei_resources_all, resources);
+ if (rc) {
+ pr_err(APEI_PFX "Fail to merge resources!\n");
+ goto err_unmap_ioport;
+ }
return 0;
err_unmap_ioport:
@@ -491,12 +499,13 @@ err_unmap_iomem:
break;
release_mem_region(res->start, res->end - res->start);
}
- return -EINVAL;
+ return rc;
}
EXPORT_SYMBOL_GPL(apei_resources_request);
void apei_resources_release(struct apei_resources *resources)
{
+ int rc;
struct apei_res *res;
list_for_each_entry(res, &resources->iomem, list)
@@ -504,7 +513,9 @@ void apei_resources_release(struct apei_resources *resources)
list_for_each_entry(res, &resources->ioport, list)
release_region(res->start, res->end - res->start);
- apei_resources_sub(&apei_resources_all, resources);
+ rc = apei_resources_sub(&apei_resources_all, resources);
+ if (rc)
+ pr_err(APEI_PFX "Fail to sub resources!\n");
}
EXPORT_SYMBOL_GPL(apei_resources_release);
diff --git a/drivers/acpi/apei/einj.c b/drivers/acpi/apei/einj.c
index 465c885938ee..cf29df69380b 100644
--- a/drivers/acpi/apei/einj.c
+++ b/drivers/acpi/apei/einj.c
@@ -426,7 +426,9 @@ DEFINE_SIMPLE_ATTRIBUTE(error_inject_fops, NULL,
static int einj_check_table(struct acpi_table_einj *einj_tab)
{
- if (einj_tab->header_length != sizeof(struct acpi_table_einj))
+ if ((einj_tab->header_length !=
+ (sizeof(struct acpi_table_einj) - sizeof(einj_tab->header)))
+ && (einj_tab->header_length != sizeof(struct acpi_table_einj)))
return -EINVAL;
if (einj_tab->header.length < sizeof(struct acpi_table_einj))
return -EINVAL;
diff --git a/drivers/acpi/apei/erst-dbg.c b/drivers/acpi/apei/erst-dbg.c
index 5281ddda2777..de73caf3cebc 100644
--- a/drivers/acpi/apei/erst-dbg.c
+++ b/drivers/acpi/apei/erst-dbg.c
@@ -2,7 +2,7 @@
* APEI Error Record Serialization Table debug support
*
* ERST is a way provided by APEI to save and retrieve hardware error
- * infomation to and from a persistent store. This file provide the
+ * information to and from a persistent store. This file provide the
* debugging/testing support for ERST kernel support and firmware
* implementation.
*
@@ -111,11 +111,13 @@ retry:
goto out;
}
if (len > erst_dbg_buf_len) {
- kfree(erst_dbg_buf);
+ void *p;
rc = -ENOMEM;
- erst_dbg_buf = kmalloc(len, GFP_KERNEL);
- if (!erst_dbg_buf)
+ p = kmalloc(len, GFP_KERNEL);
+ if (!p)
goto out;
+ kfree(erst_dbg_buf);
+ erst_dbg_buf = p;
erst_dbg_buf_len = len;
goto retry;
}
@@ -150,11 +152,13 @@ static ssize_t erst_dbg_write(struct file *filp, const char __user *ubuf,
if (mutex_lock_interruptible(&erst_dbg_mutex))
return -EINTR;
if (usize > erst_dbg_buf_len) {
- kfree(erst_dbg_buf);
+ void *p;
rc = -ENOMEM;
- erst_dbg_buf = kmalloc(usize, GFP_KERNEL);
- if (!erst_dbg_buf)
+ p = kmalloc(usize, GFP_KERNEL);
+ if (!p)
goto out;
+ kfree(erst_dbg_buf);
+ erst_dbg_buf = p;
erst_dbg_buf_len = usize;
}
rc = copy_from_user(erst_dbg_buf, ubuf, usize);
@@ -180,6 +184,7 @@ static const struct file_operations erst_dbg_ops = {
.read = erst_dbg_read,
.write = erst_dbg_write,
.unlocked_ioctl = erst_dbg_ioctl,
+ .llseek = no_llseek,
};
static struct miscdevice erst_dbg_dev = {
diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c
index 18645f4e83cd..1211c03149e8 100644
--- a/drivers/acpi/apei/erst.c
+++ b/drivers/acpi/apei/erst.c
@@ -2,7 +2,7 @@
* APEI Error Record Serialization Table support
*
* ERST is a way provided by APEI to save and retrieve hardware error
- * infomation to and from a persistent store.
+ * information to and from a persistent store.
*
* For more information about ERST, please refer to ACPI Specification
* version 4.0, section 17.4.
@@ -266,13 +266,30 @@ static int erst_exec_move_data(struct apei_exec_context *ctx,
{
int rc;
u64 offset;
+ void *src, *dst;
+
+ /* ioremap does not work in interrupt context */
+ if (in_interrupt()) {
+ pr_warning(ERST_PFX
+ "MOVE_DATA can not be used in interrupt context");
+ return -EBUSY;
+ }
rc = __apei_exec_read_register(entry, &offset);
if (rc)
return rc;
- memmove((void *)ctx->dst_base + offset,
- (void *)ctx->src_base + offset,
- ctx->var2);
+
+ src = ioremap(ctx->src_base + offset, ctx->var2);
+ if (!src)
+ return -ENOMEM;
+ dst = ioremap(ctx->dst_base + offset, ctx->var2);
+ if (!dst)
+ return -ENOMEM;
+
+ memmove(dst, src, ctx->var2);
+
+ iounmap(src);
+ iounmap(dst);
return 0;
}
@@ -750,7 +767,9 @@ __setup("erst_disable", setup_erst_disable);
static int erst_check_table(struct acpi_table_erst *erst_tab)
{
- if (erst_tab->header_length != sizeof(struct acpi_table_erst))
+ if ((erst_tab->header_length !=
+ (sizeof(struct acpi_table_erst) - sizeof(erst_tab->header)))
+ && (erst_tab->header_length != sizeof(struct acpi_table_einj)))
return -EINVAL;
if (erst_tab->header.length < sizeof(struct acpi_table_erst))
return -EINVAL;
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index 385a6059714a..0d505e59214d 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -302,7 +302,7 @@ static int __devinit ghes_probe(struct platform_device *ghes_dev)
struct ghes *ghes = NULL;
int rc = -EINVAL;
- generic = ghes_dev->dev.platform_data;
+ generic = *(struct acpi_hest_generic **)ghes_dev->dev.platform_data;
if (!generic->enabled)
return -ENODEV;
diff --git a/drivers/acpi/apei/hest.c b/drivers/acpi/apei/hest.c
index 343168d18266..1a3508a7fe03 100644
--- a/drivers/acpi/apei/hest.c
+++ b/drivers/acpi/apei/hest.c
@@ -137,20 +137,23 @@ static int hest_parse_ghes_count(struct acpi_hest_header *hest_hdr, void *data)
static int hest_parse_ghes(struct acpi_hest_header *hest_hdr, void *data)
{
- struct acpi_hest_generic *generic;
struct platform_device *ghes_dev;
struct ghes_arr *ghes_arr = data;
int rc;
if (hest_hdr->type != ACPI_HEST_TYPE_GENERIC_ERROR)
return 0;
- generic = (struct acpi_hest_generic *)hest_hdr;
- if (!generic->enabled)
+
+ if (!((struct acpi_hest_generic *)hest_hdr)->enabled)
return 0;
ghes_dev = platform_device_alloc("GHES", hest_hdr->source_id);
if (!ghes_dev)
return -ENOMEM;
- ghes_dev->dev.platform_data = generic;
+
+ rc = platform_device_add_data(ghes_dev, &hest_hdr, sizeof(void *));
+ if (rc)
+ goto err;
+
rc = platform_device_add(ghes_dev);
if (rc)
goto err;
diff --git a/drivers/acpi/atomicio.c b/drivers/acpi/atomicio.c
index 8f8bd736d4ff..542e53903891 100644
--- a/drivers/acpi/atomicio.c
+++ b/drivers/acpi/atomicio.c
@@ -142,7 +142,7 @@ static void __iomem *acpi_pre_map(phys_addr_t paddr,
list_add_tail_rcu(&map->list, &acpi_iomaps);
spin_unlock_irqrestore(&acpi_iomaps_lock, flags);
- return vaddr + (paddr - pg_off);
+ return map->vaddr + (paddr - map->paddr);
err_unmap:
iounmap(vaddr);
return NULL;
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index dc58402b0a17..98417201e9ce 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -273,7 +273,6 @@ static enum power_supply_property energy_battery_props[] = {
POWER_SUPPLY_PROP_CYCLE_COUNT,
POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
POWER_SUPPLY_PROP_VOLTAGE_NOW,
- POWER_SUPPLY_PROP_CURRENT_NOW,
POWER_SUPPLY_PROP_POWER_NOW,
POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
POWER_SUPPLY_PROP_ENERGY_FULL,
diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c
index 2bb28b9d91c4..af308d03f492 100644
--- a/drivers/acpi/blacklist.c
+++ b/drivers/acpi/blacklist.c
@@ -183,6 +183,8 @@ static int __init dmi_disable_osi_vista(const struct dmi_system_id *d)
{
printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident);
acpi_osi_setup("!Windows 2006");
+ acpi_osi_setup("!Windows 2006 SP1");
+ acpi_osi_setup("!Windows 2006 SP2");
return 0;
}
static int __init dmi_disable_osi_win7(const struct dmi_system_id *d)
@@ -202,6 +204,23 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
},
},
{
+ /*
+ * There have a NVIF method in MSI GX723 DSDT need call by Nvidia
+ * driver (e.g. nouveau) when user press brightness hotkey.
+ * Currently, nouveau driver didn't do the job and it causes there
+ * have a infinite while loop in DSDT when user press hotkey.
+ * We add MSI GX723's dmi information to this table for workaround
+ * this issue.
+ * Will remove MSI GX723 from the table after nouveau grows support.
+ */
+ .callback = dmi_disable_osi_vista,
+ .ident = "MSI GX723",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "GX723"),
+ },
+ },
+ {
.callback = dmi_disable_osi_vista,
.ident = "Sony VGN-NS10J_S",
.matches = {
@@ -226,6 +245,14 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
},
},
{
+ .callback = dmi_disable_osi_vista,
+ .ident = "Toshiba Satellite L355",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "Satellite L355"),
+ },
+ },
+ {
.callback = dmi_disable_osi_win7,
.ident = "ASUS K50IJ",
.matches = {
@@ -233,6 +260,14 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
DMI_MATCH(DMI_PRODUCT_NAME, "K50IJ"),
},
},
+ {
+ .callback = dmi_disable_osi_vista,
+ .ident = "Toshiba P305D",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P305D"),
+ },
+ },
/*
* BIOS invocation of _OSI(Linux) is almost always a BIOS bug.
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 5c221ab535d5..310e3b9749cb 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -55,7 +55,7 @@ EXPORT_SYMBOL(acpi_root_dir);
static int set_power_nocheck(const struct dmi_system_id *id)
{
printk(KERN_NOTICE PREFIX "%s detected - "
- "disable power check in power transistion\n", id->ident);
+ "disable power check in power transition\n", id->ident);
acpi_power_nocheck = 1;
return 0;
}
@@ -80,23 +80,15 @@ static int set_copy_dsdt(const struct dmi_system_id *id)
static struct dmi_system_id dsdt_dmi_table[] __initdata = {
/*
- * Insyde BIOS on some TOSHIBA machines corrupt the DSDT.
+ * Invoke DSDT corruption work-around on all Toshiba Satellite.
* https://bugzilla.kernel.org/show_bug.cgi?id=14679
*/
{
.callback = set_copy_dsdt,
- .ident = "TOSHIBA Satellite A505",
+ .ident = "TOSHIBA Satellite",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A505"),
- },
- },
- {
- .callback = set_copy_dsdt,
- .ident = "TOSHIBA Satellite L505D",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Satellite L505D"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Satellite"),
},
},
{}
@@ -1027,7 +1019,7 @@ static int __init acpi_init(void)
/*
* If the laptop falls into the DMI check table, the power state check
- * will be disabled in the course of device power transistion.
+ * will be disabled in the course of device power transition.
*/
dmi_check_system(power_nocheck_dmi_table);
diff --git a/drivers/acpi/debugfs.c b/drivers/acpi/debugfs.c
index 7de27d49c4b9..6355b575ee5a 100644
--- a/drivers/acpi/debugfs.c
+++ b/drivers/acpi/debugfs.c
@@ -69,6 +69,7 @@ static ssize_t cm_write(struct file *file, const char __user * user_buf,
static const struct file_operations cm_fops = {
.write = cm_write,
+ .llseek = default_llseek,
};
int __init acpi_debugfs_init(void)
diff --git a/drivers/acpi/ec_sys.c b/drivers/acpi/ec_sys.c
index 0e869b3f81ca..411620ef84c2 100644
--- a/drivers/acpi/ec_sys.c
+++ b/drivers/acpi/ec_sys.c
@@ -101,6 +101,7 @@ static struct file_operations acpi_ec_io_ops = {
.open = acpi_ec_open_io,
.read = acpi_ec_read_io,
.write = acpi_ec_write_io,
+ .llseek = default_llseek,
};
int acpi_ec_add_debugfs(struct acpi_ec *ec, unsigned int ec_device_count)
diff --git a/drivers/acpi/event.c b/drivers/acpi/event.c
index d439314a75d8..85d908993809 100644
--- a/drivers/acpi/event.c
+++ b/drivers/acpi/event.c
@@ -110,6 +110,7 @@ static const struct file_operations acpi_system_event_ops = {
.read = acpi_system_read_event,
.release = acpi_system_close_event,
.poll = acpi_system_poll_event,
+ .llseek = default_llseek,
};
#endif /* CONFIG_ACPI_PROC_EVENT */
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
index 8a3b840c0bb2..d94d2953c974 100644
--- a/drivers/acpi/fan.c
+++ b/drivers/acpi/fan.c
@@ -369,7 +369,9 @@ static void __exit acpi_fan_exit(void)
acpi_bus_unregister_driver(&acpi_fan_driver);
+#ifdef CONFIG_ACPI_PROCFS
remove_proc_entry(ACPI_FAN_CLASS, acpi_root_dir);
+#endif
return;
}
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index e9699aaed109..bec561c14beb 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -29,12 +29,6 @@ static int set_no_mwait(const struct dmi_system_id *id)
static struct dmi_system_id __cpuinitdata processor_idle_dmi_table[] = {
{
- set_no_mwait, "IFL91 board", {
- DMI_MATCH(DMI_BIOS_VENDOR, "COMPAL"),
- DMI_MATCH(DMI_SYS_VENDOR, "ZEPTO"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "3215W"),
- DMI_MATCH(DMI_BOARD_NAME, "IFL91") }, NULL},
- {
set_no_mwait, "Extensa 5220", {
DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
@@ -352,4 +346,5 @@ void __init acpi_early_processor_set_pdc(void)
acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
ACPI_UINT32_MAX,
early_init_pdc, NULL, NULL, NULL);
+ acpi_get_devices("ACPI0007", early_init_pdc, NULL, NULL);
}
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c
index 156021892389..347eb21b2353 100644
--- a/drivers/acpi/processor_driver.c
+++ b/drivers/acpi/processor_driver.c
@@ -850,7 +850,7 @@ static int __init acpi_processor_init(void)
printk(KERN_DEBUG "ACPI: %s registered with cpuidle\n",
acpi_idle_driver.name);
} else {
- printk(KERN_DEBUG "ACPI: acpi_idle yielding to %s",
+ printk(KERN_DEBUG "ACPI: acpi_idle yielding to %s\n",
cpuidle_get_driver()->name);
}
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index ba1bd263d903..3a73a93596e8 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -447,8 +447,8 @@ int acpi_processor_notify_smm(struct module *calling_module)
if (!try_module_get(calling_module))
return -EINVAL;
- /* is_done is set to negative if an error occured,
- * and to postitive if _no_ error occured, but SMM
+ /* is_done is set to negative if an error occurred,
+ * and to postitive if _no_ error occurred, but SMM
* was already notified. This avoids double notification
* which might lead to unexpected results...
*/
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index cf82989ae756..4754ff6e70e6 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -363,6 +363,12 @@ static int __init init_old_suspend_ordering(const struct dmi_system_id *d)
return 0;
}
+static int __init init_nvs_nosave(const struct dmi_system_id *d)
+{
+ acpi_nvs_nosave();
+ return 0;
+}
+
static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
{
.callback = init_old_suspend_ordering,
@@ -397,6 +403,22 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
DMI_MATCH(DMI_BOARD_NAME, "CF51-2L"),
},
},
+ {
+ .callback = init_nvs_nosave,
+ .ident = "Sony Vaio VGN-SR11M",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR11M"),
+ },
+ },
+ {
+ .callback = init_nvs_nosave,
+ .ident = "Everex StepNote Series",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Everex Systems, Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Everex StepNote Series"),
+ },
+ },
{},
};
#endif /* CONFIG_SUSPEND */
diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c
index 68e2e4582fa2..f8588f81048a 100644
--- a/drivers/acpi/sysfs.c
+++ b/drivers/acpi/sysfs.c
@@ -100,7 +100,7 @@ static const struct acpi_dlevel acpi_debug_levels[] = {
ACPI_DEBUG_INIT(ACPI_LV_EVENTS),
};
-static int param_get_debug_layer(char *buffer, struct kernel_param *kp)
+static int param_get_debug_layer(char *buffer, const struct kernel_param *kp)
{
int result = 0;
int i;
@@ -128,7 +128,7 @@ static int param_get_debug_layer(char *buffer, struct kernel_param *kp)
return result;
}
-static int param_get_debug_level(char *buffer, struct kernel_param *kp)
+static int param_get_debug_level(char *buffer, const struct kernel_param *kp)
{
int result = 0;
int i;
@@ -149,10 +149,18 @@ static int param_get_debug_level(char *buffer, struct kernel_param *kp)
return result;
}
-module_param_call(debug_layer, param_set_uint, param_get_debug_layer,
- &acpi_dbg_layer, 0644);
-module_param_call(debug_level, param_set_uint, param_get_debug_level,
- &acpi_dbg_level, 0644);
+static struct kernel_param_ops param_ops_debug_layer = {
+ .set = param_set_uint,
+ .get = param_get_debug_layer,
+};
+
+static struct kernel_param_ops param_ops_debug_level = {
+ .set = param_set_uint,
+ .get = param_get_debug_level,
+};
+
+module_param_cb(debug_layer, &param_ops_debug_layer, &acpi_dbg_layer, 0644);
+module_param_cb(debug_level, &param_ops_debug_level, &acpi_dbg_level, 0644);
static char trace_method_name[6];
module_param_string(trace_method_name, trace_method_name, 6, 0644);
diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c
index c5fef01b3c95..b83676126598 100644
--- a/drivers/acpi/video_detect.c
+++ b/drivers/acpi/video_detect.c
@@ -59,8 +59,8 @@ acpi_backlight_cap_match(acpi_handle handle, u32 level, void *context,
"support\n"));
*cap |= ACPI_VIDEO_BACKLIGHT;
if (ACPI_FAILURE(acpi_get_handle(handle, "_BQC", &h_dummy)))
- printk(KERN_WARNING FW_BUG PREFIX "ACPI brightness "
- "control misses _BQC function\n");
+ printk(KERN_WARNING FW_BUG PREFIX "No _BQC method, "
+ "cannot determine initial brightness\n");
/* We have backlight support, no need to scan further */
return AE_CTRL_TERMINATE;
}
diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
index d31590e7011b..2737b9752205 100644
--- a/drivers/amba/bus.c
+++ b/drivers/amba/bus.c
@@ -298,7 +298,7 @@ int amba_device_register(struct amba_device *dev, struct resource *parent)
amba_put_disable_pclk(dev);
- if (cid == 0xb105f00d)
+ if (cid == AMBA_CID)
dev->periphid = pid;
if (!dev->periphid)
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index d5df04a395ca..c501af5b12b9 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -99,7 +99,7 @@ obj-$(CONFIG_ATA_GENERIC) += ata_generic.o
# Should be last libata driver
obj-$(CONFIG_PATA_LEGACY) += pata_legacy.o
-libata-objs := libata-core.o libata-scsi.o libata-eh.o
+libata-y := libata-core.o libata-scsi.o libata-eh.o libata-transport.o
libata-$(CONFIG_ATA_SFF) += libata-sff.o
libata-$(CONFIG_SATA_PMP) += libata-pmp.o
libata-$(CONFIG_ATA_ACPI) += libata-acpi.o
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 99d0e5a51148..328826381a2d 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -1208,9 +1208,6 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
ata_port_pbar_desc(ap, AHCI_PCI_BAR,
0x100 + ap->port_no * 0x80, "port");
- /* set initial link pm policy */
- ap->pm_policy = NOT_AVAILABLE;
-
/* set enclosure management message type */
if (ap->flags & ATA_FLAG_EM)
ap->em_message_type = hpriv->em_msg_type;
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index e5fdeebf9ef0..329cbbb91284 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -72,6 +72,7 @@ enum {
AHCI_CMD_RESET = (1 << 8),
AHCI_CMD_CLR_BUSY = (1 << 10),
+ RX_FIS_PIO_SETUP = 0x20, /* offset of PIO Setup FIS data */
RX_FIS_D2H_REG = 0x40, /* offset of D2H Register FIS data */
RX_FIS_SDB = 0x58, /* offset of SDB FIS data */
RX_FIS_UNK = 0x60, /* offset of Unknown FIS data */
@@ -201,7 +202,6 @@ enum {
AHCI_HFLAG_MV_PATA = (1 << 4), /* PATA port */
AHCI_HFLAG_NO_MSI = (1 << 5), /* no PCI MSI */
AHCI_HFLAG_NO_PMP = (1 << 6), /* no PMP */
- AHCI_HFLAG_NO_HOTPLUG = (1 << 7), /* ignore PxSERR.DIAG.N */
AHCI_HFLAG_SECT255 = (1 << 8), /* max 255 sectors */
AHCI_HFLAG_YES_NCQ = (1 << 9), /* force NCQ cap on */
AHCI_HFLAG_NO_SUSPEND = (1 << 10), /* don't suspend */
@@ -216,7 +216,7 @@ enum {
AHCI_FLAG_COMMON = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
ATA_FLAG_ACPI_SATA | ATA_FLAG_AN |
- ATA_FLAG_IPM,
+ ATA_FLAG_LPM,
ICH_MAP = 0x90, /* ICH MAP register */
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index 84b643270e7a..6fef1fa75c54 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -129,9 +129,6 @@ static int __init ahci_probe(struct platform_device *pdev)
ata_port_desc(ap, "mmio %pR", mem);
ata_port_desc(ap, "port 0x%x", 0x100 + ap->port_no * 0x80);
- /* set initial link pm policy */
- ap->pm_policy = NOT_AVAILABLE;
-
/* set enclosure management message type */
if (ap->flags & ATA_FLAG_EM)
ap->em_message_type = hpriv->em_msg_type;
diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c
index cc5f7726bde7..6981f7680a00 100644
--- a/drivers/ata/ata_generic.c
+++ b/drivers/ata/ata_generic.c
@@ -35,6 +35,7 @@
enum {
ATA_GEN_CLASS_MATCH = (1 << 0),
ATA_GEN_FORCE_DMA = (1 << 1),
+ ATA_GEN_INTEL_IDER = (1 << 2),
};
/**
@@ -109,6 +110,49 @@ static struct ata_port_operations generic_port_ops = {
static int all_generic_ide; /* Set to claim all devices */
/**
+ * is_intel_ider - identify intel IDE-R devices
+ * @dev: PCI device
+ *
+ * Distinguish Intel IDE-R controller devices from other Intel IDE
+ * devices. IDE-R devices have no timing registers and are in
+ * most respects virtual. They should be driven by the ata_generic
+ * driver.
+ *
+ * IDE-R devices have PCI offset 0xF8.L as zero, later Intel ATA has
+ * it non zero. All Intel ATA has 0x40 writable (timing), but it is
+ * not writable on IDE-R devices (this is guaranteed).
+ */
+
+static int is_intel_ider(struct pci_dev *dev)
+{
+ /* For Intel IDE the value at 0xF8 is only zero on IDE-R
+ interfaces */
+ u32 r;
+ u16 t;
+
+ /* Check the manufacturing ID, it will be zero for IDE-R */
+ pci_read_config_dword(dev, 0xF8, &r);
+ /* Not IDE-R: punt so that ata_(old)piix gets it */
+ if (r != 0)
+ return 0;
+ /* 0xF8 will also be zero on some early Intel IDE devices
+ but they will have a sane timing register */
+ pci_read_config_word(dev, 0x40, &t);
+ if (t != 0)
+ return 0;
+ /* Finally check if the timing register is writable so that
+ we eliminate any early devices hot-docked in a docking
+ station */
+ pci_write_config_word(dev, 0x40, 1);
+ pci_read_config_word(dev, 0x40, &t);
+ if (t) {
+ pci_write_config_word(dev, 0x40, 0);
+ return 0;
+ }
+ return 1;
+}
+
+/**
* ata_generic_init - attach generic IDE
* @dev: PCI device found
* @id: match entry
@@ -134,6 +178,10 @@ static int ata_generic_init_one(struct pci_dev *dev, const struct pci_device_id
if ((id->driver_data & ATA_GEN_CLASS_MATCH) && all_generic_ide == 0)
return -ENODEV;
+ if (id->driver_data & ATA_GEN_INTEL_IDER)
+ if (!is_intel_ider(dev))
+ return -ENODEV;
+
/* Devices that need care */
if (dev->vendor == PCI_VENDOR_ID_UMC &&
dev->device == PCI_DEVICE_ID_UMC_UM8886A &&
@@ -186,7 +234,11 @@ static struct pci_device_id ata_generic[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2), },
{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_3), },
{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_5), },
-#endif
+#endif
+ /* Intel, IDE class device */
+ { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
+ PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL,
+ .driver_data = ATA_GEN_INTEL_IDER },
/* Must come last. If you add entries adjust this table appropriately */
{ PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL),
.driver_data = ATA_GEN_CLASS_MATCH },
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index d712675d0a96..6cb14ca8ee85 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -158,7 +158,6 @@ struct piix_map_db {
struct piix_host_priv {
const int *map;
u32 saved_iocfg;
- spinlock_t sidpr_lock; /* FIXME: remove once locking in EH is fixed */
void __iomem *sidpr;
};
@@ -175,6 +174,8 @@ static int piix_sidpr_scr_read(struct ata_link *link,
unsigned int reg, u32 *val);
static int piix_sidpr_scr_write(struct ata_link *link,
unsigned int reg, u32 val);
+static int piix_sidpr_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
+ unsigned hints);
static bool piix_irq_check(struct ata_port *ap);
#ifdef CONFIG_PM
static int piix_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
@@ -209,6 +210,8 @@ static const struct pci_device_id piix_pci_tbl[] = {
{ 0x8086, 0x248A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
/* Intel ICH3 (E7500/1) UDMA 100 */
{ 0x8086, 0x248B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
+ /* Intel ICH4-L */
+ { 0x8086, 0x24C1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
/* Intel ICH4 (i845GV, i845E, i852, i855) UDMA 100 */
{ 0x8086, 0x24CA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
{ 0x8086, 0x24CB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
@@ -348,11 +351,22 @@ static struct ata_port_operations ich_pata_ops = {
.set_dmamode = ich_set_dmamode,
};
+static struct device_attribute *piix_sidpr_shost_attrs[] = {
+ &dev_attr_link_power_management_policy,
+ NULL
+};
+
+static struct scsi_host_template piix_sidpr_sht = {
+ ATA_BMDMA_SHT(DRV_NAME),
+ .shost_attrs = piix_sidpr_shost_attrs,
+};
+
static struct ata_port_operations piix_sidpr_sata_ops = {
.inherits = &piix_sata_ops,
.hardreset = sata_std_hardreset,
.scr_read = piix_sidpr_scr_read,
.scr_write = piix_sidpr_scr_write,
+ .set_lpm = piix_sidpr_set_lpm,
};
static const struct piix_map_db ich5_map_db = {
@@ -956,15 +970,12 @@ static int piix_sidpr_scr_read(struct ata_link *link,
unsigned int reg, u32 *val)
{
struct piix_host_priv *hpriv = link->ap->host->private_data;
- unsigned long flags;
if (reg >= ARRAY_SIZE(piix_sidx_map))
return -EINVAL;
- spin_lock_irqsave(&hpriv->sidpr_lock, flags);
piix_sidpr_sel(link, reg);
*val = ioread32(hpriv->sidpr + PIIX_SIDPR_DATA);
- spin_unlock_irqrestore(&hpriv->sidpr_lock, flags);
return 0;
}
@@ -972,18 +983,21 @@ static int piix_sidpr_scr_write(struct ata_link *link,
unsigned int reg, u32 val)
{
struct piix_host_priv *hpriv = link->ap->host->private_data;
- unsigned long flags;
if (reg >= ARRAY_SIZE(piix_sidx_map))
return -EINVAL;
- spin_lock_irqsave(&hpriv->sidpr_lock, flags);
piix_sidpr_sel(link, reg);
iowrite32(val, hpriv->sidpr + PIIX_SIDPR_DATA);
- spin_unlock_irqrestore(&hpriv->sidpr_lock, flags);
return 0;
}
+static int piix_sidpr_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
+ unsigned hints)
+{
+ return sata_link_scr_lpm(link, policy, false);
+}
+
static bool piix_irq_check(struct ata_port *ap)
{
if (unlikely(!ap->ioaddr.bmdma_addr))
@@ -1543,6 +1557,7 @@ static int __devinit piix_init_one(struct pci_dev *pdev,
struct device *dev = &pdev->dev;
struct ata_port_info port_info[2];
const struct ata_port_info *ppi[] = { &port_info[0], &port_info[1] };
+ struct scsi_host_template *sht = &piix_sht;
unsigned long port_flags;
struct ata_host *host;
struct piix_host_priv *hpriv;
@@ -1577,7 +1592,6 @@ static int __devinit piix_init_one(struct pci_dev *pdev,
hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
if (!hpriv)
return -ENOMEM;
- spin_lock_init(&hpriv->sidpr_lock);
/* Save IOCFG, this will be used for cable detection, quirk
* detection and restoration on detach. This is necessary
@@ -1612,6 +1626,8 @@ static int __devinit piix_init_one(struct pci_dev *pdev,
rc = piix_init_sidpr(host);
if (rc)
return rc;
+ if (host->ports[0]->ops == &piix_sidpr_sata_ops)
+ sht = &piix_sidpr_sht;
}
/* apply IOCFG bit18 quirk */
@@ -1638,7 +1654,7 @@ static int __devinit piix_init_one(struct pci_dev *pdev,
host->flags |= ATA_HOST_PARALLEL_SCAN;
pci_set_master(pdev);
- return ata_pci_sff_activate_host(host, ata_bmdma_interrupt, &piix_sht);
+ return ata_pci_sff_activate_host(host, ata_bmdma_interrupt, sht);
}
static void piix_remove_one(struct pci_dev *pdev)
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index 8eea309ea212..ebc08d65b3dd 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -56,9 +56,8 @@ MODULE_PARM_DESC(skip_host_reset, "skip global host reset (0=don't skip, 1=skip)
module_param_named(ignore_sss, ahci_ignore_sss, int, 0444);
MODULE_PARM_DESC(ignore_sss, "Ignore staggered spinup flag (0=don't ignore, 1=ignore)");
-static int ahci_enable_alpm(struct ata_port *ap,
- enum link_pm policy);
-static void ahci_disable_alpm(struct ata_port *ap);
+static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
+ unsigned hints);
static ssize_t ahci_led_show(struct ata_port *ap, char *buf);
static ssize_t ahci_led_store(struct ata_port *ap, const char *buf,
size_t size);
@@ -164,8 +163,7 @@ struct ata_port_operations ahci_ops = {
.pmp_attach = ahci_pmp_attach,
.pmp_detach = ahci_pmp_detach,
- .enable_pm = ahci_enable_alpm,
- .disable_pm = ahci_disable_alpm,
+ .set_lpm = ahci_set_lpm,
.em_show = ahci_led_show,
.em_store = ahci_led_store,
.sw_activity_show = ahci_activity_show,
@@ -569,7 +567,7 @@ int ahci_stop_engine(struct ata_port *ap)
writel(tmp, port_mmio + PORT_CMD);
/* wait for engine to stop. This could be as long as 500 msec */
- tmp = ata_wait_register(port_mmio + PORT_CMD,
+ tmp = ata_wait_register(ap, port_mmio + PORT_CMD,
PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1, 500);
if (tmp & PORT_CMD_LIST_ON)
return -EIO;
@@ -616,7 +614,7 @@ static int ahci_stop_fis_rx(struct ata_port *ap)
writel(tmp, port_mmio + PORT_CMD);
/* wait for completion, spec says 500ms, give it 1000 */
- tmp = ata_wait_register(port_mmio + PORT_CMD, PORT_CMD_FIS_ON,
+ tmp = ata_wait_register(ap, port_mmio + PORT_CMD, PORT_CMD_FIS_ON,
PORT_CMD_FIS_ON, 10, 1000);
if (tmp & PORT_CMD_FIS_ON)
return -EBUSY;
@@ -642,127 +640,56 @@ static void ahci_power_up(struct ata_port *ap)
writel(cmd | PORT_CMD_ICC_ACTIVE, port_mmio + PORT_CMD);
}
-static void ahci_disable_alpm(struct ata_port *ap)
+static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
+ unsigned int hints)
{
+ struct ata_port *ap = link->ap;
struct ahci_host_priv *hpriv = ap->host->private_data;
- void __iomem *port_mmio = ahci_port_base(ap);
- u32 cmd;
struct ahci_port_priv *pp = ap->private_data;
-
- /* IPM bits should be disabled by libata-core */
- /* get the existing command bits */
- cmd = readl(port_mmio + PORT_CMD);
-
- /* disable ALPM and ASP */
- cmd &= ~PORT_CMD_ASP;
- cmd &= ~PORT_CMD_ALPE;
-
- /* force the interface back to active */
- cmd |= PORT_CMD_ICC_ACTIVE;
-
- /* write out new cmd value */
- writel(cmd, port_mmio + PORT_CMD);
- cmd = readl(port_mmio + PORT_CMD);
-
- /* wait 10ms to be sure we've come out of any low power state */
- msleep(10);
-
- /* clear out any PhyRdy stuff from interrupt status */
- writel(PORT_IRQ_PHYRDY, port_mmio + PORT_IRQ_STAT);
-
- /* go ahead and clean out PhyRdy Change from Serror too */
- ahci_scr_write(&ap->link, SCR_ERROR, ((1 << 16) | (1 << 18)));
-
- /*
- * Clear flag to indicate that we should ignore all PhyRdy
- * state changes
- */
- hpriv->flags &= ~AHCI_HFLAG_NO_HOTPLUG;
-
- /*
- * Enable interrupts on Phy Ready.
- */
- pp->intr_mask |= PORT_IRQ_PHYRDY;
- writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
-
- /*
- * don't change the link pm policy - we can be called
- * just to turn of link pm temporarily
- */
-}
-
-static int ahci_enable_alpm(struct ata_port *ap,
- enum link_pm policy)
-{
- struct ahci_host_priv *hpriv = ap->host->private_data;
void __iomem *port_mmio = ahci_port_base(ap);
- u32 cmd;
- struct ahci_port_priv *pp = ap->private_data;
- u32 asp;
- /* Make sure the host is capable of link power management */
- if (!(hpriv->cap & HOST_CAP_ALPM))
- return -EINVAL;
-
- switch (policy) {
- case MAX_PERFORMANCE:
- case NOT_AVAILABLE:
+ if (policy != ATA_LPM_MAX_POWER) {
/*
- * if we came here with NOT_AVAILABLE,
- * it just means this is the first time we
- * have tried to enable - default to max performance,
- * and let the user go to lower power modes on request.
+ * Disable interrupts on Phy Ready. This keeps us from
+ * getting woken up due to spurious phy ready
+ * interrupts.
*/
- ahci_disable_alpm(ap);
- return 0;
- case MIN_POWER:
- /* configure HBA to enter SLUMBER */
- asp = PORT_CMD_ASP;
- break;
- case MEDIUM_POWER:
- /* configure HBA to enter PARTIAL */
- asp = 0;
- break;
- default:
- return -EINVAL;
+ pp->intr_mask &= ~PORT_IRQ_PHYRDY;
+ writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
+
+ sata_link_scr_lpm(link, policy, false);
}
- /*
- * Disable interrupts on Phy Ready. This keeps us from
- * getting woken up due to spurious phy ready interrupts
- * TBD - Hot plug should be done via polling now, is
- * that even supported?
- */
- pp->intr_mask &= ~PORT_IRQ_PHYRDY;
- writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
+ if (hpriv->cap & HOST_CAP_ALPM) {
+ u32 cmd = readl(port_mmio + PORT_CMD);
- /*
- * Set a flag to indicate that we should ignore all PhyRdy
- * state changes since these can happen now whenever we
- * change link state
- */
- hpriv->flags |= AHCI_HFLAG_NO_HOTPLUG;
+ if (policy == ATA_LPM_MAX_POWER || !(hints & ATA_LPM_HIPM)) {
+ cmd &= ~(PORT_CMD_ASP | PORT_CMD_ALPE);
+ cmd |= PORT_CMD_ICC_ACTIVE;
- /* get the existing command bits */
- cmd = readl(port_mmio + PORT_CMD);
+ writel(cmd, port_mmio + PORT_CMD);
+ readl(port_mmio + PORT_CMD);
- /*
- * Set ASP based on Policy
- */
- cmd |= asp;
+ /* wait 10ms to be sure we've come out of LPM state */
+ ata_msleep(ap, 10);
+ } else {
+ cmd |= PORT_CMD_ALPE;
+ if (policy == ATA_LPM_MIN_POWER)
+ cmd |= PORT_CMD_ASP;
- /*
- * Setting this bit will instruct the HBA to aggressively
- * enter a lower power link state when it's appropriate and
- * based on the value set above for ASP
- */
- cmd |= PORT_CMD_ALPE;
+ /* write out new cmd value */
+ writel(cmd, port_mmio + PORT_CMD);
+ }
+ }
- /* write out new cmd value */
- writel(cmd, port_mmio + PORT_CMD);
- cmd = readl(port_mmio + PORT_CMD);
+ if (policy == ATA_LPM_MAX_POWER) {
+ sata_link_scr_lpm(link, policy, false);
+
+ /* turn PHYRDY IRQ back on */
+ pp->intr_mask |= PORT_IRQ_PHYRDY;
+ writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
+ }
- /* IPM bits should be set by libata-core */
return 0;
}
@@ -813,7 +740,7 @@ static void ahci_start_port(struct ata_port *ap)
emp->led_state,
4);
if (rc == -EBUSY)
- msleep(1);
+ ata_msleep(ap, 1);
else
break;
}
@@ -872,7 +799,7 @@ int ahci_reset_controller(struct ata_host *host)
* reset must complete within 1 second, or
* the hardware should be considered fried.
*/
- tmp = ata_wait_register(mmio + HOST_CTL, HOST_RESET,
+ tmp = ata_wait_register(NULL, mmio + HOST_CTL, HOST_RESET,
HOST_RESET, 10, 1000);
if (tmp & HOST_RESET) {
@@ -1252,7 +1179,7 @@ int ahci_kick_engine(struct ata_port *ap)
writel(tmp, port_mmio + PORT_CMD);
rc = 0;
- tmp = ata_wait_register(port_mmio + PORT_CMD,
+ tmp = ata_wait_register(ap, port_mmio + PORT_CMD,
PORT_CMD_CLO, PORT_CMD_CLO, 1, 500);
if (tmp & PORT_CMD_CLO)
rc = -EIO;
@@ -1282,8 +1209,8 @@ static int ahci_exec_polled_cmd(struct ata_port *ap, int pmp,
writel(1, port_mmio + PORT_CMD_ISSUE);
if (timeout_msec) {
- tmp = ata_wait_register(port_mmio + PORT_CMD_ISSUE, 0x1, 0x1,
- 1, timeout_msec);
+ tmp = ata_wait_register(ap, port_mmio + PORT_CMD_ISSUE,
+ 0x1, 0x1, 1, timeout_msec);
if (tmp & 0x1) {
ahci_kick_engine(ap);
return -EBUSY;
@@ -1330,7 +1257,7 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class,
}
/* spec says at least 5us, but be generous and sleep for 1ms */
- msleep(1);
+ ata_msleep(ap, 1);
/* issue the second D2H Register FIS */
tf.ctl &= ~ATA_SRST;
@@ -1660,15 +1587,10 @@ static void ahci_port_intr(struct ata_port *ap)
if (unlikely(resetting))
status &= ~PORT_IRQ_BAD_PMP;
- /* If we are getting PhyRdy, this is
- * just a power state change, we should
- * clear out this, plus the PhyRdy/Comm
- * Wake bits from Serror
- */
- if ((hpriv->flags & AHCI_HFLAG_NO_HOTPLUG) &&
- (status & PORT_IRQ_PHYRDY)) {
+ /* if LPM is enabled, PHYRDY doesn't mean anything */
+ if (ap->link.lpm_policy > ATA_LPM_MAX_POWER) {
status &= ~PORT_IRQ_PHYRDY;
- ahci_scr_write(&ap->link, SCR_ERROR, ((1 << 16) | (1 << 18)));
+ ahci_scr_write(&ap->link, SCR_ERROR, SERR_PHYRDY_CHG);
}
if (unlikely(status & PORT_IRQ_ERROR)) {
@@ -1830,12 +1752,24 @@ static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc)
static bool ahci_qc_fill_rtf(struct ata_queued_cmd *qc)
{
struct ahci_port_priv *pp = qc->ap->private_data;
- u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
+ u8 *rx_fis = pp->rx_fis;
if (pp->fbs_enabled)
- d2h_fis += qc->dev->link->pmp * AHCI_RX_FIS_SZ;
+ rx_fis += qc->dev->link->pmp * AHCI_RX_FIS_SZ;
+
+ /*
+ * After a successful execution of an ATA PIO data-in command,
+ * the device doesn't send D2H Reg FIS to update the TF and
+ * the host should take TF and E_Status from the preceding PIO
+ * Setup FIS.
+ */
+ if (qc->tf.protocol == ATA_PROT_PIO && qc->dma_dir == DMA_FROM_DEVICE &&
+ !(qc->flags & ATA_QCFLAG_FAILED)) {
+ ata_tf_from_fis(rx_fis + RX_FIS_PIO_SETUP, &qc->result_tf);
+ qc->result_tf.command = (rx_fis + RX_FIS_PIO_SETUP)[15];
+ } else
+ ata_tf_from_fis(rx_fis + RX_FIS_D2H_REG, &qc->result_tf);
- ata_tf_from_fis(d2h_fis, &qc->result_tf);
return true;
}
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 932eaee50245..7f77c67d267c 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -68,7 +68,7 @@
#include <linux/ratelimit.h>
#include "libata.h"
-
+#include "libata-transport.h"
/* debounce timing parameters in msecs { interval, duration, timeout } */
const unsigned long sata_deb_timing_normal[] = { 5, 100, 2000 };
@@ -91,8 +91,6 @@ const struct ata_port_operations sata_port_ops = {
static unsigned int ata_dev_init_params(struct ata_device *dev,
u16 heads, u16 sectors);
static unsigned int ata_dev_set_xfermode(struct ata_device *dev);
-static unsigned int ata_dev_set_feature(struct ata_device *dev,
- u8 enable, u8 feature);
static void ata_dev_xfermask(struct ata_device *dev);
static unsigned long ata_dev_blacklisted(const struct ata_device *dev);
@@ -1017,7 +1015,7 @@ const char *ata_mode_string(unsigned long xfer_mask)
return "<n/a>";
}
-static const char *sata_spd_string(unsigned int spd)
+const char *sata_spd_string(unsigned int spd)
{
static const char * const spd_str[] = {
"1.5 Gbps",
@@ -1030,182 +1028,6 @@ static const char *sata_spd_string(unsigned int spd)
return spd_str[spd - 1];
}
-static int ata_dev_set_dipm(struct ata_device *dev, enum link_pm policy)
-{
- struct ata_link *link = dev->link;
- struct ata_port *ap = link->ap;
- u32 scontrol;
- unsigned int err_mask;
- int rc;
-
- /*
- * disallow DIPM for drivers which haven't set
- * ATA_FLAG_IPM. This is because when DIPM is enabled,
- * phy ready will be set in the interrupt status on
- * state changes, which will cause some drivers to
- * think there are errors - additionally drivers will
- * need to disable hot plug.
- */
- if (!(ap->flags & ATA_FLAG_IPM) || !ata_dev_enabled(dev)) {
- ap->pm_policy = NOT_AVAILABLE;
- return -EINVAL;
- }
-
- /*
- * For DIPM, we will only enable it for the
- * min_power setting.
- *
- * Why? Because Disks are too stupid to know that
- * If the host rejects a request to go to SLUMBER
- * they should retry at PARTIAL, and instead it
- * just would give up. So, for medium_power to
- * work at all, we need to only allow HIPM.
- */
- rc = sata_scr_read(link, SCR_CONTROL, &scontrol);
- if (rc)
- return rc;
-
- switch (policy) {
- case MIN_POWER:
- /* no restrictions on IPM transitions */
- scontrol &= ~(0x3 << 8);
- rc = sata_scr_write(link, SCR_CONTROL, scontrol);
- if (rc)
- return rc;
-
- /* enable DIPM */
- if (dev->flags & ATA_DFLAG_DIPM)
- err_mask = ata_dev_set_feature(dev,
- SETFEATURES_SATA_ENABLE, SATA_DIPM);
- break;
- case MEDIUM_POWER:
- /* allow IPM to PARTIAL */
- scontrol &= ~(0x1 << 8);
- scontrol |= (0x2 << 8);
- rc = sata_scr_write(link, SCR_CONTROL, scontrol);
- if (rc)
- return rc;
-
- /*
- * we don't have to disable DIPM since IPM flags
- * disallow transitions to SLUMBER, which effectively
- * disable DIPM if it does not support PARTIAL
- */
- break;
- case NOT_AVAILABLE:
- case MAX_PERFORMANCE:
- /* disable all IPM transitions */
- scontrol |= (0x3 << 8);
- rc = sata_scr_write(link, SCR_CONTROL, scontrol);
- if (rc)
- return rc;
-
- /*
- * we don't have to disable DIPM since IPM flags
- * disallow all transitions which effectively
- * disable DIPM anyway.
- */
- break;
- }
-
- /* FIXME: handle SET FEATURES failure */
- (void) err_mask;
-
- return 0;
-}
-
-/**
- * ata_dev_enable_pm - enable SATA interface power management
- * @dev: device to enable power management
- * @policy: the link power management policy
- *
- * Enable SATA Interface power management. This will enable
- * Device Interface Power Management (DIPM) for min_power
- * policy, and then call driver specific callbacks for
- * enabling Host Initiated Power management.
- *
- * Locking: Caller.
- * Returns: -EINVAL if IPM is not supported, 0 otherwise.
- */
-void ata_dev_enable_pm(struct ata_device *dev, enum link_pm policy)
-{
- int rc = 0;
- struct ata_port *ap = dev->link->ap;
-
- /* set HIPM first, then DIPM */
- if (ap->ops->enable_pm)
- rc = ap->ops->enable_pm(ap, policy);
- if (rc)
- goto enable_pm_out;
- rc = ata_dev_set_dipm(dev, policy);
-
-enable_pm_out:
- if (rc)
- ap->pm_policy = MAX_PERFORMANCE;
- else
- ap->pm_policy = policy;
- return /* rc */; /* hopefully we can use 'rc' eventually */
-}
-
-#ifdef CONFIG_PM
-/**
- * ata_dev_disable_pm - disable SATA interface power management
- * @dev: device to disable power management
- *
- * Disable SATA Interface power management. This will disable
- * Device Interface Power Management (DIPM) without changing
- * policy, call driver specific callbacks for disabling Host
- * Initiated Power management.
- *
- * Locking: Caller.
- * Returns: void
- */
-static void ata_dev_disable_pm(struct ata_device *dev)
-{
- struct ata_port *ap = dev->link->ap;
-
- ata_dev_set_dipm(dev, MAX_PERFORMANCE);
- if (ap->ops->disable_pm)
- ap->ops->disable_pm(ap);
-}
-#endif /* CONFIG_PM */
-
-void ata_lpm_schedule(struct ata_port *ap, enum link_pm policy)
-{
- ap->pm_policy = policy;
- ap->link.eh_info.action |= ATA_EH_LPM;
- ap->link.eh_info.flags |= ATA_EHI_NO_AUTOPSY;
- ata_port_schedule_eh(ap);
-}
-
-#ifdef CONFIG_PM
-static void ata_lpm_enable(struct ata_host *host)
-{
- struct ata_link *link;
- struct ata_port *ap;
- struct ata_device *dev;
- int i;
-
- for (i = 0; i < host->n_ports; i++) {
- ap = host->ports[i];
- ata_for_each_link(link, ap, EDGE) {
- ata_for_each_dev(dev, link, ALL)
- ata_dev_disable_pm(dev);
- }
- }
-}
-
-static void ata_lpm_disable(struct ata_host *host)
-{
- int i;
-
- for (i = 0; i < host->n_ports; i++) {
- struct ata_port *ap = host->ports[i];
- ata_lpm_schedule(ap, ap->pm_policy);
- }
-}
-#endif /* CONFIG_PM */
-
/**
* ata_dev_classify - determine device type based on ATA-spec signature
* @tf: ATA taskfile register set for device to be identified
@@ -1806,8 +1628,14 @@ unsigned ata_exec_internal_sg(struct ata_device *dev,
}
}
+ if (ap->ops->error_handler)
+ ata_eh_release(ap);
+
rc = wait_for_completion_timeout(&wait, msecs_to_jiffies(timeout));
+ if (ap->ops->error_handler)
+ ata_eh_acquire(ap);
+
ata_sff_flush_pio_task(ap);
if (!rc) {
@@ -2564,13 +2392,6 @@ int ata_dev_configure(struct ata_device *dev)
if (dev->flags & ATA_DFLAG_LBA48)
dev->max_sectors = ATA_MAX_SECTORS_LBA48;
- if (!(dev->horkage & ATA_HORKAGE_IPM)) {
- if (ata_id_has_hipm(dev->id))
- dev->flags |= ATA_DFLAG_HIPM;
- if (ata_id_has_dipm(dev->id))
- dev->flags |= ATA_DFLAG_DIPM;
- }
-
/* Limit PATA drive on SATA cable bridge transfers to udma5,
200 sectors */
if (ata_dev_knobble(dev)) {
@@ -2591,13 +2412,6 @@ int ata_dev_configure(struct ata_device *dev)
dev->max_sectors = min_t(unsigned int, ATA_MAX_SECTORS_128,
dev->max_sectors);
- if (ata_dev_blacklisted(dev) & ATA_HORKAGE_IPM) {
- dev->horkage |= ATA_HORKAGE_IPM;
-
- /* reset link pm_policy for this port to no pm */
- ap->pm_policy = MAX_PERFORMANCE;
- }
-
if (ap->ops->dev_config)
ap->ops->dev_config(dev);
@@ -3596,7 +3410,7 @@ int ata_wait_ready(struct ata_link *link, unsigned long deadline,
warned = 1;
}
- msleep(50);
+ ata_msleep(link->ap, 50);
}
}
@@ -3617,7 +3431,7 @@ int ata_wait_ready(struct ata_link *link, unsigned long deadline,
int ata_wait_after_reset(struct ata_link *link, unsigned long deadline,
int (*check_ready)(struct ata_link *link))
{
- msleep(ATA_WAIT_AFTER_RESET);
+ ata_msleep(link->ap, ATA_WAIT_AFTER_RESET);
return ata_wait_ready(link, deadline, check_ready);
}
@@ -3628,7 +3442,7 @@ int ata_wait_after_reset(struct ata_link *link, unsigned long deadline,
* @params: timing parameters { interval, duratinon, timeout } in msec
* @deadline: deadline jiffies for the operation
*
-* Make sure SStatus of @link reaches stable state, determined by
+ * Make sure SStatus of @link reaches stable state, determined by
* holding the same value where DET is not 1 for @duration polled
* every @interval, before @timeout. Timeout constraints the
* beginning of the stable state. Because DET gets stuck at 1 on
@@ -3665,7 +3479,7 @@ int sata_link_debounce(struct ata_link *link, const unsigned long *params,
last_jiffies = jiffies;
while (1) {
- msleep(interval);
+ ata_msleep(link->ap, interval);
if ((rc = sata_scr_read(link, SCR_STATUS, &cur)))
return rc;
cur &= 0xf;
@@ -3730,7 +3544,7 @@ int sata_link_resume(struct ata_link *link, const unsigned long *params,
* immediately after resuming. Delay 200ms before
* debouncing.
*/
- msleep(200);
+ ata_msleep(link->ap, 200);
/* is SControl restored correctly? */
if ((rc = sata_scr_read(link, SCR_CONTROL, &scontrol)))
@@ -3760,6 +3574,72 @@ int sata_link_resume(struct ata_link *link, const unsigned long *params,
}
/**
+ * sata_link_scr_lpm - manipulate SControl IPM and SPM fields
+ * @link: ATA link to manipulate SControl for
+ * @policy: LPM policy to configure
+ * @spm_wakeup: initiate LPM transition to active state
+ *
+ * Manipulate the IPM field of the SControl register of @link
+ * according to @policy. If @policy is ATA_LPM_MAX_POWER and
+ * @spm_wakeup is %true, the SPM field is manipulated to wake up
+ * the link. This function also clears PHYRDY_CHG before
+ * returning.
+ *
+ * LOCKING:
+ * EH context.
+ *
+ * RETURNS:
+ * 0 on succes, -errno otherwise.
+ */
+int sata_link_scr_lpm(struct ata_link *link, enum ata_lpm_policy policy,
+ bool spm_wakeup)
+{
+ struct ata_eh_context *ehc = &link->eh_context;
+ bool woken_up = false;
+ u32 scontrol;
+ int rc;
+
+ rc = sata_scr_read(link, SCR_CONTROL, &scontrol);
+ if (rc)
+ return rc;
+
+ switch (policy) {
+ case ATA_LPM_MAX_POWER:
+ /* disable all LPM transitions */
+ scontrol |= (0x3 << 8);
+ /* initiate transition to active state */
+ if (spm_wakeup) {
+ scontrol |= (0x4 << 12);
+ woken_up = true;
+ }
+ break;
+ case ATA_LPM_MED_POWER:
+ /* allow LPM to PARTIAL */
+ scontrol &= ~(0x1 << 8);
+ scontrol |= (0x2 << 8);
+ break;
+ case ATA_LPM_MIN_POWER:
+ /* no restrictions on LPM transitions */
+ scontrol &= ~(0x3 << 8);
+ break;
+ default:
+ WARN_ON(1);
+ }
+
+ rc = sata_scr_write(link, SCR_CONTROL, scontrol);
+ if (rc)
+ return rc;
+
+ /* give the link time to transit out of LPM state */
+ if (woken_up)
+ msleep(10);
+
+ /* clear PHYRDY_CHG from SError */
+ ehc->i.serror &= ~SERR_PHYRDY_CHG;
+ return sata_scr_write(link, SCR_ERROR, SERR_PHYRDY_CHG);
+}
+
+/**
* ata_std_prereset - prepare for reset
* @link: ATA link to be reset
* @deadline: deadline jiffies for the operation
@@ -3868,7 +3748,7 @@ int sata_link_hardreset(struct ata_link *link, const unsigned long *timing,
/* Couldn't find anything in SATA I/II specs, but AHCI-1.1
* 10.4.2 says at least 1 ms.
*/
- msleep(1);
+ ata_msleep(link->ap, 1);
/* bring link back */
rc = sata_link_resume(link, timing, deadline);
@@ -4551,6 +4431,7 @@ static unsigned int ata_dev_set_xfermode(struct ata_device *dev)
DPRINTK("EXIT, err_mask=%x\n", err_mask);
return err_mask;
}
+
/**
* ata_dev_set_feature - Issue SET FEATURES - SATA FEATURES
* @dev: Device to which command will be sent
@@ -4566,8 +4447,7 @@ static unsigned int ata_dev_set_xfermode(struct ata_device *dev)
* RETURNS:
* 0 on success, AC_ERR_* mask otherwise.
*/
-static unsigned int ata_dev_set_feature(struct ata_device *dev, u8 enable,
- u8 feature)
+unsigned int ata_dev_set_feature(struct ata_device *dev, u8 enable, u8 feature)
{
struct ata_taskfile tf;
unsigned int err_mask;
@@ -4943,8 +4823,13 @@ static void ata_verify_xfer(struct ata_queued_cmd *qc)
* ata_qc_complete - Complete an active ATA command
* @qc: Command to complete
*
- * Indicate to the mid and upper layers that an ATA
- * command has completed, with either an ok or not-ok status.
+ * Indicate to the mid and upper layers that an ATA command has
+ * completed, with either an ok or not-ok status.
+ *
+ * Refrain from calling this function multiple times when
+ * successfully completing multiple NCQ commands.
+ * ata_qc_complete_multiple() should be used instead, which will
+ * properly update IRQ expect state.
*
* LOCKING:
* spin_lock_irqsave(host lock)
@@ -5037,6 +4922,10 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
* requests normally. ap->qc_active and @qc_active is compared
* and commands are completed accordingly.
*
+ * Always use this function when completing multiple NCQ commands
+ * from IRQ handlers instead of calling ata_qc_complete()
+ * multiple times to keep IRQ expect status properly in sync.
+ *
* LOCKING:
* spin_lock_irqsave(host lock)
*
@@ -5422,12 +5311,6 @@ int ata_host_suspend(struct ata_host *host, pm_message_t mesg)
int rc;
/*
- * disable link pm on all ports before requesting
- * any pm activity
- */
- ata_lpm_enable(host);
-
- /*
* On some hardware, device fails to respond after spun down
* for suspend. As the device won't be used before being
* resumed, we don't need to touch the device. Ask EH to skip
@@ -5460,9 +5343,6 @@ void ata_host_resume(struct ata_host *host)
ata_host_request_pm(host, PMSG_ON, ATA_EH_RESET,
ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET, 0);
host->dev->power.power_state = PMSG_ON;
-
- /* reenable link pm */
- ata_lpm_disable(host);
}
#endif
@@ -5517,7 +5397,8 @@ void ata_link_init(struct ata_port *ap, struct ata_link *link, int pmp)
int i;
/* clear everything except for devices */
- memset(link, 0, offsetof(struct ata_link, device[0]));
+ memset((void *)link + ATA_LINK_CLEAR_BEGIN, 0,
+ ATA_LINK_CLEAR_END - ATA_LINK_CLEAR_BEGIN);
link->ap = ap;
link->pmp = pmp;
@@ -5591,7 +5472,7 @@ struct ata_port *ata_port_alloc(struct ata_host *host)
ap = kzalloc(sizeof(*ap), GFP_KERNEL);
if (!ap)
return NULL;
-
+
ap->pflags |= ATA_PFLAG_INITIALIZING;
ap->lock = &host->lock;
ap->print_id = -1;
@@ -5695,6 +5576,7 @@ struct ata_host *ata_host_alloc(struct device *dev, int max_ports)
dev_set_drvdata(dev, host);
spin_lock_init(&host->lock);
+ mutex_init(&host->eh_mutex);
host->dev = dev;
host->n_ports = max_ports;
@@ -5992,6 +5874,7 @@ void ata_host_init(struct ata_host *host, struct device *dev,
unsigned long flags, struct ata_port_operations *ops)
{
spin_lock_init(&host->lock);
+ mutex_init(&host->eh_mutex);
host->dev = dev;
host->flags = flags;
host->ops = ops;
@@ -6022,7 +5905,7 @@ static void async_port_probe(void *data, async_cookie_t cookie)
spin_lock_irqsave(ap->lock, flags);
ehi->probe_mask |= ATA_ALL_DEVICES;
- ehi->action |= ATA_EH_RESET | ATA_EH_LPM;
+ ehi->action |= ATA_EH_RESET;
ehi->flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET;
ap->pflags &= ~ATA_PFLAG_INITIALIZING;
@@ -6093,9 +5976,18 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
for (i = 0; i < host->n_ports; i++)
host->ports[i]->print_id = ata_print_id++;
+
+ /* Create associated sysfs transport objects */
+ for (i = 0; i < host->n_ports; i++) {
+ rc = ata_tport_add(host->dev,host->ports[i]);
+ if (rc) {
+ goto err_tadd;
+ }
+ }
+
rc = ata_scsi_add_hosts(host, sht);
if (rc)
- return rc;
+ goto err_tadd;
/* associate with ACPI nodes */
ata_acpi_associate(host);
@@ -6136,6 +6028,13 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
}
return 0;
+
+ err_tadd:
+ while (--i >= 0) {
+ ata_tport_delete(host->ports[i]);
+ }
+ return rc;
+
}
/**
@@ -6226,6 +6125,13 @@ static void ata_port_detach(struct ata_port *ap)
cancel_rearming_delayed_work(&ap->hotplug_task);
skip_eh:
+ if (ap->pmp_link) {
+ int i;
+ for (i = 0; i < SATA_PMP_MAX_PORTS; i++)
+ ata_tlink_delete(&ap->pmp_link[i]);
+ }
+ ata_tport_delete(ap);
+
/* remove the associated SCSI host */
scsi_remove_host(ap->scsi_host);
}
@@ -6542,7 +6448,7 @@ static void __init ata_parse_force_param(void)
static int __init ata_init(void)
{
- int rc = -ENOMEM;
+ int rc;
ata_parse_force_param();
@@ -6552,12 +6458,25 @@ static int __init ata_init(void)
return rc;
}
+ libata_transport_init();
+ ata_scsi_transport_template = ata_attach_transport();
+ if (!ata_scsi_transport_template) {
+ ata_sff_exit();
+ rc = -ENOMEM;
+ goto err_out;
+ }
+
printk(KERN_DEBUG "libata version " DRV_VERSION " loaded.\n");
return 0;
+
+err_out:
+ return rc;
}
static void __exit ata_exit(void)
{
+ ata_release_transport(ata_scsi_transport_template);
+ libata_transport_exit();
ata_sff_exit();
kfree(ata_force_tbl);
}
@@ -6573,7 +6492,35 @@ int ata_ratelimit(void)
}
/**
+ * ata_msleep - ATA EH owner aware msleep
+ * @ap: ATA port to attribute the sleep to
+ * @msecs: duration to sleep in milliseconds
+ *
+ * Sleeps @msecs. If the current task is owner of @ap's EH, the
+ * ownership is released before going to sleep and reacquired
+ * after the sleep is complete. IOW, other ports sharing the
+ * @ap->host will be allowed to own the EH while this task is
+ * sleeping.
+ *
+ * LOCKING:
+ * Might sleep.
+ */
+void ata_msleep(struct ata_port *ap, unsigned int msecs)
+{
+ bool owns_eh = ap && ap->host->eh_owner == current;
+
+ if (owns_eh)
+ ata_eh_release(ap);
+
+ msleep(msecs);
+
+ if (owns_eh)
+ ata_eh_acquire(ap);
+}
+
+/**
* ata_wait_register - wait until register value changes
+ * @ap: ATA port to wait register for, can be NULL
* @reg: IO-mapped register
* @mask: Mask to apply to read register value
* @val: Wait condition
@@ -6595,7 +6542,7 @@ int ata_ratelimit(void)
* RETURNS:
* The final register value.
*/
-u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val,
+u32 ata_wait_register(struct ata_port *ap, void __iomem *reg, u32 mask, u32 val,
unsigned long interval, unsigned long timeout)
{
unsigned long deadline;
@@ -6610,7 +6557,7 @@ u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val,
deadline = ata_deadline(jiffies, timeout);
while ((tmp & mask) == val && time_before(jiffies, deadline)) {
- msleep(interval);
+ ata_msleep(ap, interval);
tmp = ioread32(reg);
}
@@ -6686,6 +6633,7 @@ EXPORT_SYMBOL_GPL(sata_set_spd);
EXPORT_SYMBOL_GPL(ata_wait_after_reset);
EXPORT_SYMBOL_GPL(sata_link_debounce);
EXPORT_SYMBOL_GPL(sata_link_resume);
+EXPORT_SYMBOL_GPL(sata_link_scr_lpm);
EXPORT_SYMBOL_GPL(ata_std_prereset);
EXPORT_SYMBOL_GPL(sata_link_hardreset);
EXPORT_SYMBOL_GPL(sata_std_hardreset);
@@ -6693,6 +6641,7 @@ EXPORT_SYMBOL_GPL(ata_std_postreset);
EXPORT_SYMBOL_GPL(ata_dev_classify);
EXPORT_SYMBOL_GPL(ata_dev_pair);
EXPORT_SYMBOL_GPL(ata_ratelimit);
+EXPORT_SYMBOL_GPL(ata_msleep);
EXPORT_SYMBOL_GPL(ata_wait_register);
EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);
EXPORT_SYMBOL_GPL(ata_scsi_slave_config);
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index e48302eae55f..5e590504f3aa 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -57,6 +57,7 @@ enum {
/* error flags */
ATA_EFLAG_IS_IO = (1 << 0),
ATA_EFLAG_DUBIOUS_XFER = (1 << 1),
+ ATA_EFLAG_OLD_ER = (1 << 31),
/* error categories */
ATA_ECAT_NONE = 0,
@@ -396,14 +397,9 @@ static struct ata_ering_entry *ata_ering_top(struct ata_ering *ering)
return NULL;
}
-static void ata_ering_clear(struct ata_ering *ering)
-{
- memset(ering, 0, sizeof(*ering));
-}
-
-static int ata_ering_map(struct ata_ering *ering,
- int (*map_fn)(struct ata_ering_entry *, void *),
- void *arg)
+int ata_ering_map(struct ata_ering *ering,
+ int (*map_fn)(struct ata_ering_entry *, void *),
+ void *arg)
{
int idx, rc = 0;
struct ata_ering_entry *ent;
@@ -422,6 +418,17 @@ static int ata_ering_map(struct ata_ering *ering,
return rc;
}
+int ata_ering_clear_cb(struct ata_ering_entry *ent, void *void_arg)
+{
+ ent->eflags |= ATA_EFLAG_OLD_ER;
+ return 0;
+}
+
+static void ata_ering_clear(struct ata_ering *ering)
+{
+ ata_ering_map(ering, ata_ering_clear_cb, NULL);
+}
+
static unsigned int ata_eh_dev_action(struct ata_device *dev)
{
struct ata_eh_context *ehc = &dev->link->eh_context;
@@ -456,6 +463,41 @@ static void ata_eh_clear_action(struct ata_link *link, struct ata_device *dev,
}
/**
+ * ata_eh_acquire - acquire EH ownership
+ * @ap: ATA port to acquire EH ownership for
+ *
+ * Acquire EH ownership for @ap. This is the basic exclusion
+ * mechanism for ports sharing a host. Only one port hanging off
+ * the same host can claim the ownership of EH.
+ *
+ * LOCKING:
+ * EH context.
+ */
+void ata_eh_acquire(struct ata_port *ap)
+{
+ mutex_lock(&ap->host->eh_mutex);
+ WARN_ON_ONCE(ap->host->eh_owner);
+ ap->host->eh_owner = current;
+}
+
+/**
+ * ata_eh_release - release EH ownership
+ * @ap: ATA port to release EH ownership for
+ *
+ * Release EH ownership for @ap if the caller. The caller must
+ * have acquired EH ownership using ata_eh_acquire() previously.
+ *
+ * LOCKING:
+ * EH context.
+ */
+void ata_eh_release(struct ata_port *ap)
+{
+ WARN_ON_ONCE(ap->host->eh_owner != current);
+ ap->host->eh_owner = NULL;
+ mutex_unlock(&ap->host->eh_mutex);
+}
+
+/**
* ata_scsi_timed_out - SCSI layer time out callback
* @cmd: timed out SCSI command
*
@@ -572,19 +614,19 @@ void ata_scsi_error(struct Scsi_Host *host)
int nr_timedout = 0;
spin_lock_irqsave(ap->lock, flags);
-
+
/* This must occur under the ap->lock as we don't want
a polled recovery to race the real interrupt handler
-
+
The lost_interrupt handler checks for any completed but
non-notified command and completes much like an IRQ handler.
-
+
We then fall into the error recovery code which will treat
this as if normal completion won the race */
if (ap->ops->lost_interrupt)
ap->ops->lost_interrupt(ap);
-
+
list_for_each_entry_safe(scmd, tmp, &host->eh_cmd_q, eh_entry) {
struct ata_queued_cmd *qc;
@@ -628,15 +670,17 @@ void ata_scsi_error(struct Scsi_Host *host)
ap->eh_tries = ATA_EH_MAX_TRIES;
} else
spin_unlock_wait(ap->lock);
-
+
/* If we timed raced normal completion and there is nothing to
recover nr_timedout == 0 why exactly are we doing error recovery ? */
- repeat:
/* invoke error handler */
if (ap->ops->error_handler) {
struct ata_link *link;
+ /* acquire EH ownership */
+ ata_eh_acquire(ap);
+ repeat:
/* kill fast drain timer */
del_timer_sync(&ap->fastdrain_timer);
@@ -711,6 +755,7 @@ void ata_scsi_error(struct Scsi_Host *host)
host->host_eh_scheduled = 0;
spin_unlock_irqrestore(ap->lock, flags);
+ ata_eh_release(ap);
} else {
WARN_ON(ata_qc_from_tag(ap, ap->link.active_tag) == NULL);
ap->ops->eng_timeout(ap);
@@ -772,7 +817,7 @@ void ata_port_wait_eh(struct ata_port *ap)
/* make sure SCSI EH is complete */
if (scsi_host_in_recovery(ap->scsi_host)) {
- msleep(10);
+ ata_msleep(ap, 10);
goto retry;
}
}
@@ -1573,9 +1618,9 @@ static void ata_eh_analyze_serror(struct ata_link *link)
* host links. For disabled PMP links, only N bit is
* considered as X bit is left at 1 for link plugging.
*/
- hotplug_mask = 0;
-
- if (!(link->flags & ATA_LFLAG_DISABLED) || ata_is_host_link(link))
+ if (link->lpm_policy != ATA_LPM_MAX_POWER)
+ hotplug_mask = 0; /* hotplug doesn't work w/ LPM */
+ else if (!(link->flags & ATA_LFLAG_DISABLED) || ata_is_host_link(link))
hotplug_mask = SERR_PHYRDY_CHG | SERR_DEV_XCHG;
else
hotplug_mask = SERR_PHYRDY_CHG;
@@ -1755,7 +1800,7 @@ static int speed_down_verdict_cb(struct ata_ering_entry *ent, void *void_arg)
struct speed_down_verdict_arg *arg = void_arg;
int cat;
- if (ent->timestamp < arg->since)
+ if ((ent->eflags & ATA_EFLAG_OLD_ER) || (ent->timestamp < arg->since))
return -1;
cat = ata_eh_categorize_error(ent->eflags, ent->err_mask,
@@ -2777,8 +2822,9 @@ int ata_eh_reset(struct ata_link *link, int classify,
ata_eh_done(link, NULL, ATA_EH_RESET);
if (slave)
ata_eh_done(slave, NULL, ATA_EH_RESET);
- ehc->last_reset = jiffies; /* update to completion time */
+ ehc->last_reset = jiffies; /* update to completion time */
ehc->i.action |= ATA_EH_REVALIDATE;
+ link->lpm_policy = ATA_LPM_UNKNOWN; /* reset LPM state */
rc = 0;
out:
@@ -2810,8 +2856,10 @@ int ata_eh_reset(struct ata_link *link, int classify,
"reset failed (errno=%d), retrying in %u secs\n",
rc, DIV_ROUND_UP(jiffies_to_msecs(delta), 1000));
+ ata_eh_release(ap);
while (delta)
delta = schedule_timeout_uninterruptible(delta);
+ ata_eh_acquire(ap);
}
if (try == max_tries - 1) {
@@ -3204,6 +3252,124 @@ static int ata_eh_maybe_retry_flush(struct ata_device *dev)
return rc;
}
+/**
+ * ata_eh_set_lpm - configure SATA interface power management
+ * @link: link to configure power management
+ * @policy: the link power management policy
+ * @r_failed_dev: out parameter for failed device
+ *
+ * Enable SATA Interface power management. This will enable
+ * Device Interface Power Management (DIPM) for min_power
+ * policy, and then call driver specific callbacks for
+ * enabling Host Initiated Power management.
+ *
+ * LOCKING:
+ * EH context.
+ *
+ * RETURNS:
+ * 0 on success, -errno on failure.
+ */
+static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
+ struct ata_device **r_failed_dev)
+{
+ struct ata_port *ap = ata_is_host_link(link) ? link->ap : NULL;
+ struct ata_eh_context *ehc = &link->eh_context;
+ struct ata_device *dev, *link_dev = NULL, *lpm_dev = NULL;
+ unsigned int hints = ATA_LPM_EMPTY | ATA_LPM_HIPM;
+ unsigned int err_mask;
+ int rc;
+
+ /* if the link or host doesn't do LPM, noop */
+ if ((link->flags & ATA_LFLAG_NO_LPM) || (ap && !ap->ops->set_lpm))
+ return 0;
+
+ /*
+ * DIPM is enabled only for MIN_POWER as some devices
+ * misbehave when the host NACKs transition to SLUMBER. Order
+ * device and link configurations such that the host always
+ * allows DIPM requests.
+ */
+ ata_for_each_dev(dev, link, ENABLED) {
+ bool hipm = ata_id_has_hipm(dev->id);
+ bool dipm = ata_id_has_dipm(dev->id);
+
+ /* find the first enabled and LPM enabled devices */
+ if (!link_dev)
+ link_dev = dev;
+
+ if (!lpm_dev && (hipm || dipm))
+ lpm_dev = dev;
+
+ hints &= ~ATA_LPM_EMPTY;
+ if (!hipm)
+ hints &= ~ATA_LPM_HIPM;
+
+ /* disable DIPM before changing link config */
+ if (policy != ATA_LPM_MIN_POWER && dipm) {
+ err_mask = ata_dev_set_feature(dev,
+ SETFEATURES_SATA_DISABLE, SATA_DIPM);
+ if (err_mask && err_mask != AC_ERR_DEV) {
+ ata_dev_printk(dev, KERN_WARNING,
+ "failed to disable DIPM, Emask 0x%x\n",
+ err_mask);
+ rc = -EIO;
+ goto fail;
+ }
+ }
+ }
+
+ if (ap) {
+ rc = ap->ops->set_lpm(link, policy, hints);
+ if (!rc && ap->slave_link)
+ rc = ap->ops->set_lpm(ap->slave_link, policy, hints);
+ } else
+ rc = sata_pmp_set_lpm(link, policy, hints);
+
+ /*
+ * Attribute link config failure to the first (LPM) enabled
+ * device on the link.
+ */
+ if (rc) {
+ if (rc == -EOPNOTSUPP) {
+ link->flags |= ATA_LFLAG_NO_LPM;
+ return 0;
+ }
+ dev = lpm_dev ? lpm_dev : link_dev;
+ goto fail;
+ }
+
+ /* host config updated, enable DIPM if transitioning to MIN_POWER */
+ ata_for_each_dev(dev, link, ENABLED) {
+ if (policy == ATA_LPM_MIN_POWER && ata_id_has_dipm(dev->id)) {
+ err_mask = ata_dev_set_feature(dev,
+ SETFEATURES_SATA_ENABLE, SATA_DIPM);
+ if (err_mask && err_mask != AC_ERR_DEV) {
+ ata_dev_printk(dev, KERN_WARNING,
+ "failed to enable DIPM, Emask 0x%x\n",
+ err_mask);
+ rc = -EIO;
+ goto fail;
+ }
+ }
+ }
+
+ link->lpm_policy = policy;
+ if (ap && ap->slave_link)
+ ap->slave_link->lpm_policy = policy;
+ return 0;
+
+fail:
+ /* if no device or only one more chance is left, disable LPM */
+ if (!dev || ehc->tries[dev->devno] <= 2) {
+ ata_link_printk(link, KERN_WARNING,
+ "disabling LPM on the link\n");
+ link->flags |= ATA_LFLAG_NO_LPM;
+ }
+ if (r_failed_dev)
+ *r_failed_dev = dev;
+ return rc;
+}
+
static int ata_link_nr_enabled(struct ata_link *link)
{
struct ata_device *dev;
@@ -3288,6 +3454,16 @@ static int ata_eh_schedule_probe(struct ata_device *dev)
ehc->saved_xfer_mode[dev->devno] = 0;
ehc->saved_ncq_enabled &= ~(1 << dev->devno);
+ /* the link maybe in a deep sleep, wake it up */
+ if (link->lpm_policy > ATA_LPM_MAX_POWER) {
+ if (ata_is_host_link(link))
+ link->ap->ops->set_lpm(link, ATA_LPM_MAX_POWER,
+ ATA_LPM_EMPTY);
+ else
+ sata_pmp_set_lpm(link, ATA_LPM_MAX_POWER,
+ ATA_LPM_EMPTY);
+ }
+
/* Record and count probe trials on the ering. The specific
* error mask used is irrelevant. Because a successful device
* detection clears the ering, this count accumulates only if
@@ -3389,8 +3565,7 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
{
struct ata_link *link;
struct ata_device *dev;
- int nr_failed_devs;
- int rc;
+ int rc, nr_fails;
unsigned long flags, deadline;
DPRINTK("ENTER\n");
@@ -3431,7 +3606,6 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
retry:
rc = 0;
- nr_failed_devs = 0;
/* if UNLOADING, finish immediately */
if (ap->pflags & ATA_PFLAG_UNLOADING)
@@ -3501,8 +3675,10 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
if (time_before_eq(deadline, now))
break;
+ ata_eh_release(ap);
deadline = wait_for_completion_timeout(&ap->park_req_pending,
deadline - now);
+ ata_eh_acquire(ap);
} while (deadline);
ata_for_each_link(link, ap, EDGE) {
ata_for_each_dev(dev, link, ALL) {
@@ -3516,13 +3692,17 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
}
/* the rest */
- ata_for_each_link(link, ap, EDGE) {
+ nr_fails = 0;
+ ata_for_each_link(link, ap, PMP_FIRST) {
struct ata_eh_context *ehc = &link->eh_context;
+ if (sata_pmp_attached(ap) && ata_is_host_link(link))
+ goto config_lpm;
+
/* revalidate existing devices and attach new ones */
rc = ata_eh_revalidate_and_attach(link, &dev);
if (rc)
- goto dev_fail;
+ goto rest_fail;
/* if PMP got attached, return, pmp EH will take care of it */
if (link->device->class == ATA_DEV_PMP) {
@@ -3534,7 +3714,7 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
if (ehc->i.flags & ATA_EHI_SETMODE) {
rc = ata_set_mode(link, &dev);
if (rc)
- goto dev_fail;
+ goto rest_fail;
ehc->i.flags &= ~ATA_EHI_SETMODE;
}
@@ -3547,7 +3727,7 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
continue;
rc = atapi_eh_clear_ua(dev);
if (rc)
- goto dev_fail;
+ goto rest_fail;
}
}
@@ -3557,21 +3737,25 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
continue;
rc = ata_eh_maybe_retry_flush(dev);
if (rc)
- goto dev_fail;
+ goto rest_fail;
}
+ config_lpm:
/* configure link power saving */
- if (ehc->i.action & ATA_EH_LPM)
- ata_for_each_dev(dev, link, ALL)
- ata_dev_enable_pm(dev, ap->pm_policy);
+ if (link->lpm_policy != ap->target_lpm_policy) {
+ rc = ata_eh_set_lpm(link, ap->target_lpm_policy, &dev);
+ if (rc)
+ goto rest_fail;
+ }
/* this link is okay now */
ehc->i.flags = 0;
continue;
-dev_fail:
- nr_failed_devs++;
- ata_eh_handle_dev_fail(dev, rc);
+ rest_fail:
+ nr_fails++;
+ if (dev)
+ ata_eh_handle_dev_fail(dev, rc);
if (ap->pflags & ATA_PFLAG_FROZEN) {
/* PMP reset requires working host port.
@@ -3583,7 +3767,7 @@ dev_fail:
}
}
- if (nr_failed_devs)
+ if (nr_fails)
goto retry;
out:
diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c
index 224faabd7b7e..3120596d4afc 100644
--- a/drivers/ata/libata-pmp.c
+++ b/drivers/ata/libata-pmp.c
@@ -11,6 +11,7 @@
#include <linux/libata.h>
#include <linux/slab.h>
#include "libata.h"
+#include "libata-transport.h"
const struct ata_port_operations sata_pmp_port_ops = {
.inherits = &sata_port_ops,
@@ -185,6 +186,27 @@ int sata_pmp_scr_write(struct ata_link *link, int reg, u32 val)
}
/**
+ * sata_pmp_set_lpm - configure LPM for a PMP link
+ * @link: PMP link to configure LPM for
+ * @policy: target LPM policy
+ * @hints: LPM hints
+ *
+ * Configure LPM for @link. This function will contain any PMP
+ * specific workarounds if necessary.
+ *
+ * LOCKING:
+ * EH context.
+ *
+ * RETURNS:
+ * 0 on success, -errno on failure.
+ */
+int sata_pmp_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
+ unsigned hints)
+{
+ return sata_link_scr_lpm(link, policy, true);
+}
+
+/**
* sata_pmp_read_gscr - read GSCR block of SATA PMP
* @dev: PMP device
* @gscr: buffer to read GSCR block into
@@ -312,10 +334,10 @@ static int sata_pmp_configure(struct ata_device *dev, int print_info)
return rc;
}
-static int sata_pmp_init_links(struct ata_port *ap, int nr_ports)
+static int sata_pmp_init_links (struct ata_port *ap, int nr_ports)
{
struct ata_link *pmp_link = ap->pmp_link;
- int i;
+ int i, err;
if (!pmp_link) {
pmp_link = kzalloc(sizeof(pmp_link[0]) * SATA_PMP_MAX_PORTS,
@@ -327,6 +349,13 @@ static int sata_pmp_init_links(struct ata_port *ap, int nr_ports)
ata_link_init(ap, &pmp_link[i], i);
ap->pmp_link = pmp_link;
+
+ for (i = 0; i < SATA_PMP_MAX_PORTS; i++) {
+ err = ata_tlink_add(&pmp_link[i]);
+ if (err) {
+ goto err_tlink;
+ }
+ }
}
for (i = 0; i < nr_ports; i++) {
@@ -339,6 +368,12 @@ static int sata_pmp_init_links(struct ata_port *ap, int nr_ports)
}
return 0;
+ err_tlink:
+ while (--i >= 0)
+ ata_tlink_delete(&pmp_link[i]);
+ kfree(pmp_link);
+ ap->pmp_link = NULL;
+ return err;
}
static void sata_pmp_quirks(struct ata_port *ap)
@@ -351,6 +386,9 @@ static void sata_pmp_quirks(struct ata_port *ap)
if (vendor == 0x1095 && devid == 0x3726) {
/* sil3726 quirks */
ata_for_each_link(link, ap, EDGE) {
+ /* link reports offline after LPM */
+ link->flags |= ATA_LFLAG_NO_LPM;
+
/* Class code report is unreliable and SRST
* times out under certain configurations.
*/
@@ -366,6 +404,9 @@ static void sata_pmp_quirks(struct ata_port *ap)
} else if (vendor == 0x1095 && devid == 0x4723) {
/* sil4723 quirks */
ata_for_each_link(link, ap, EDGE) {
+ /* link reports offline after LPM */
+ link->flags |= ATA_LFLAG_NO_LPM;
+
/* class code report is unreliable */
if (link->pmp < 2)
link->flags |= ATA_LFLAG_ASSUME_ATA;
@@ -378,6 +419,9 @@ static void sata_pmp_quirks(struct ata_port *ap)
} else if (vendor == 0x1095 && devid == 0x4726) {
/* sil4726 quirks */
ata_for_each_link(link, ap, EDGE) {
+ /* link reports offline after LPM */
+ link->flags |= ATA_LFLAG_NO_LPM;
+
/* Class code report is unreliable and SRST
* times out under certain configurations.
* Config device can be at port 0 or 5 and
@@ -938,15 +982,25 @@ static int sata_pmp_eh_recover(struct ata_port *ap)
if (rc)
goto link_fail;
- /* Connection status might have changed while resetting other
- * links, check SATA_PMP_GSCR_ERROR before returning.
- */
-
/* clear SNotification */
rc = sata_scr_read(&ap->link, SCR_NOTIFICATION, &sntf);
if (rc == 0)
sata_scr_write(&ap->link, SCR_NOTIFICATION, sntf);
+ /*
+ * If LPM is active on any fan-out port, hotplug wouldn't
+ * work. Return w/ PHY event notification disabled.
+ */
+ ata_for_each_link(link, ap, EDGE)
+ if (link->lpm_policy > ATA_LPM_MAX_POWER)
+ return 0;
+
+ /*
+ * Connection status might have changed while resetting other
+ * links, enable notification and check SATA_PMP_GSCR_ERROR
+ * before returning.
+ */
+
/* enable notification */
if (pmp_dev->flags & ATA_DFLAG_AN) {
gscr[SATA_PMP_GSCR_FEAT_EN] |= SATA_PMP_FEAT_NOTIFY;
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index a89172c100f5..d050e073e570 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -51,8 +51,8 @@
#include <asm/unaligned.h>
#include "libata.h"
+#include "libata-transport.h"
-#define SECTOR_SIZE 512
#define ATA_SCSI_RBUF_SIZE 4096
static DEFINE_SPINLOCK(ata_scsi_rbuf_lock);
@@ -64,9 +64,6 @@ static struct ata_device *__ata_scsi_find_dev(struct ata_port *ap,
const struct scsi_device *scsidev);
static struct ata_device *ata_scsi_find_dev(struct ata_port *ap,
const struct scsi_device *scsidev);
-static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
- unsigned int id, unsigned int lun);
-
#define RW_RECOVERY_MPAGE 0x1
#define RW_RECOVERY_MPAGE_LEN 12
@@ -106,83 +103,55 @@ static const u8 def_control_mpage[CONTROL_MPAGE_LEN] = {
0, 30 /* extended self test time, see 05-359r1 */
};
-/*
- * libata transport template. libata doesn't do real transport stuff.
- * It just needs the eh_timed_out hook.
- */
-static struct scsi_transport_template ata_scsi_transport_template = {
- .eh_strategy_handler = ata_scsi_error,
- .eh_timed_out = ata_scsi_timed_out,
- .user_scan = ata_scsi_user_scan,
-};
-
-
-static const struct {
- enum link_pm value;
- const char *name;
-} link_pm_policy[] = {
- { NOT_AVAILABLE, "max_performance" },
- { MIN_POWER, "min_power" },
- { MAX_PERFORMANCE, "max_performance" },
- { MEDIUM_POWER, "medium_power" },
+static const char *ata_lpm_policy_names[] = {
+ [ATA_LPM_UNKNOWN] = "max_performance",
+ [ATA_LPM_MAX_POWER] = "max_performance",
+ [ATA_LPM_MED_POWER] = "medium_power",
+ [ATA_LPM_MIN_POWER] = "min_power",
};
-static const char *ata_scsi_lpm_get(enum link_pm policy)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(link_pm_policy); i++)
- if (link_pm_policy[i].value == policy)
- return link_pm_policy[i].name;
-
- return NULL;
-}
-
-static ssize_t ata_scsi_lpm_put(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t ata_scsi_lpm_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct Scsi_Host *shost = class_to_shost(dev);
struct ata_port *ap = ata_shost_to_port(shost);
- enum link_pm policy = 0;
- int i;
+ enum ata_lpm_policy policy;
+ unsigned long flags;
- /*
- * we are skipping array location 0 on purpose - this
- * is because a value of NOT_AVAILABLE is displayed
- * to the user as max_performance, but when the user
- * writes "max_performance", they actually want the
- * value to match MAX_PERFORMANCE.
- */
- for (i = 1; i < ARRAY_SIZE(link_pm_policy); i++) {
- const int len = strlen(link_pm_policy[i].name);
- if (strncmp(link_pm_policy[i].name, buf, len) == 0) {
- policy = link_pm_policy[i].value;
+ /* UNKNOWN is internal state, iterate from MAX_POWER */
+ for (policy = ATA_LPM_MAX_POWER;
+ policy < ARRAY_SIZE(ata_lpm_policy_names); policy++) {
+ const char *name = ata_lpm_policy_names[policy];
+
+ if (strncmp(name, buf, strlen(name)) == 0)
break;
- }
}
- if (!policy)
+ if (policy == ARRAY_SIZE(ata_lpm_policy_names))
return -EINVAL;
- ata_lpm_schedule(ap, policy);
+ spin_lock_irqsave(ap->lock, flags);
+ ap->target_lpm_policy = policy;
+ ata_port_schedule_eh(ap);
+ spin_unlock_irqrestore(ap->lock, flags);
+
return count;
}
-static ssize_t
-ata_scsi_lpm_show(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t ata_scsi_lpm_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct Scsi_Host *shost = class_to_shost(dev);
struct ata_port *ap = ata_shost_to_port(shost);
- const char *policy =
- ata_scsi_lpm_get(ap->pm_policy);
- if (!policy)
+ if (ap->target_lpm_policy >= ARRAY_SIZE(ata_lpm_policy_names))
return -EINVAL;
- return snprintf(buf, 23, "%s\n", policy);
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ ata_lpm_policy_names[ap->target_lpm_policy]);
}
DEVICE_ATTR(link_power_management_policy, S_IRUGO | S_IWUSR,
- ata_scsi_lpm_show, ata_scsi_lpm_put);
+ ata_scsi_lpm_show, ata_scsi_lpm_store);
EXPORT_SYMBOL_GPL(dev_attr_link_power_management_policy);
static ssize_t ata_scsi_park_show(struct device *device,
@@ -516,7 +485,7 @@ int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg)
memset(scsi_cmd, 0, sizeof(scsi_cmd));
if (args[3]) {
- argsize = SECTOR_SIZE * args[3];
+ argsize = ATA_SECT_SIZE * args[3];
argbuf = kmalloc(argsize, GFP_KERNEL);
if (argbuf == NULL) {
rc = -ENOMEM;
@@ -1150,8 +1119,9 @@ static int ata_scsi_dev_config(struct scsi_device *sdev,
blk_queue_dma_drain(q, atapi_drain_needed, buf, ATAPI_MAX_DRAIN);
} else {
/* ATA devices must be sector aligned */
+ sdev->sector_size = ata_id_logical_sector_size(dev->id);
blk_queue_update_dma_alignment(sdev->request_queue,
- ATA_SECT_SIZE - 1);
+ sdev->sector_size - 1);
sdev->manage_start_stop = 1;
}
@@ -1166,6 +1136,7 @@ static int ata_scsi_dev_config(struct scsi_device *sdev,
scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, depth);
}
+ dev->sdev = sdev;
return 0;
}
@@ -1696,7 +1667,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc)
goto nothing_to_do;
qc->flags |= ATA_QCFLAG_IO;
- qc->nbytes = n_block * ATA_SECT_SIZE;
+ qc->nbytes = n_block * scmd->device->sector_size;
rc = ata_build_rw_tf(&qc->tf, qc->dev, block, n_block, tf_flags,
qc->tag);
@@ -2001,6 +1972,7 @@ static unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf)
0x89, /* page 0x89, ata info page */
0xb0, /* page 0xb0, block limits page */
0xb1, /* page 0xb1, block device characteristics page */
+ 0xb2, /* page 0xb2, thin provisioning page */
};
rbuf[3] = sizeof(pages); /* number of supported VPD pages */
@@ -2123,7 +2095,7 @@ static unsigned int ata_scsiop_inq_89(struct ata_scsi_args *args, u8 *rbuf)
static unsigned int ata_scsiop_inq_b0(struct ata_scsi_args *args, u8 *rbuf)
{
- u32 min_io_sectors;
+ u16 min_io_sectors;
rbuf[1] = 0xb0;
rbuf[3] = 0x3c; /* required VPD size with unmap support */
@@ -2135,10 +2107,7 @@ static unsigned int ata_scsiop_inq_b0(struct ata_scsi_args *args, u8 *rbuf)
* logical than physical sector size we need to figure out what the
* latter is.
*/
- if (ata_id_has_large_logical_sectors(args->id))
- min_io_sectors = ata_id_logical_per_physical_sectors(args->id);
- else
- min_io_sectors = 1;
+ min_io_sectors = 1 << ata_id_log2_per_physical_sector(args->id);
put_unaligned_be16(min_io_sectors, &rbuf[6]);
/*
@@ -2172,6 +2141,16 @@ static unsigned int ata_scsiop_inq_b1(struct ata_scsi_args *args, u8 *rbuf)
return 0;
}
+static unsigned int ata_scsiop_inq_b2(struct ata_scsi_args *args, u8 *rbuf)
+{
+ /* SCSI Thin Provisioning VPD page: SBC-3 rev 22 or later */
+ rbuf[1] = 0xb2;
+ rbuf[3] = 0x4;
+ rbuf[5] = 1 << 6; /* TPWS */
+
+ return 0;
+}
+
/**
* ata_scsiop_noop - Command handler that simply returns success.
* @args: device IDENTIFY data / SCSI command of interest.
@@ -2397,21 +2376,13 @@ static unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf)
{
struct ata_device *dev = args->dev;
u64 last_lba = dev->n_sectors - 1; /* LBA of the last block */
- u8 log_per_phys = 0;
- u16 lowest_aligned = 0;
- u16 word_106 = dev->id[106];
- u16 word_209 = dev->id[209];
-
- if ((word_106 & 0xc000) == 0x4000) {
- /* Number and offset of logical sectors per physical sector */
- if (word_106 & (1 << 13))
- log_per_phys = word_106 & 0xf;
- if ((word_209 & 0xc000) == 0x4000) {
- u16 first = dev->id[209] & 0x3fff;
- if (first > 0)
- lowest_aligned = (1 << log_per_phys) - first;
- }
- }
+ u32 sector_size; /* physical sector size in bytes */
+ u8 log2_per_phys;
+ u16 lowest_aligned;
+
+ sector_size = ata_id_logical_sector_size(dev->id);
+ log2_per_phys = ata_id_log2_per_physical_sector(dev->id);
+ lowest_aligned = ata_id_logical_sector_offset(dev->id, log2_per_phys);
VPRINTK("ENTER\n");
@@ -2426,8 +2397,10 @@ static unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf)
rbuf[3] = last_lba;
/* sector size */
- rbuf[6] = ATA_SECT_SIZE >> 8;
- rbuf[7] = ATA_SECT_SIZE & 0xff;
+ rbuf[4] = sector_size >> (8 * 3);
+ rbuf[5] = sector_size >> (8 * 2);
+ rbuf[6] = sector_size >> (8 * 1);
+ rbuf[7] = sector_size;
} else {
/* sector count, 64-bit */
rbuf[0] = last_lba >> (8 * 7);
@@ -2440,11 +2413,13 @@ static unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf)
rbuf[7] = last_lba;
/* sector size */
- rbuf[10] = ATA_SECT_SIZE >> 8;
- rbuf[11] = ATA_SECT_SIZE & 0xff;
+ rbuf[ 8] = sector_size >> (8 * 3);
+ rbuf[ 9] = sector_size >> (8 * 2);
+ rbuf[10] = sector_size >> (8 * 1);
+ rbuf[11] = sector_size;
rbuf[12] = 0;
- rbuf[13] = log_per_phys;
+ rbuf[13] = log2_per_phys;
rbuf[14] = (lowest_aligned >> 8) & 0x3f;
rbuf[15] = lowest_aligned;
@@ -2888,9 +2863,8 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
tf->device = dev->devno ?
tf->device | ATA_DEV1 : tf->device & ~ATA_DEV1;
- /* READ/WRITE LONG use a non-standard sect_size */
- qc->sect_size = ATA_SECT_SIZE;
switch (tf->command) {
+ /* READ/WRITE LONG use a non-standard sect_size */
case ATA_CMD_READ_LONG:
case ATA_CMD_READ_LONG_ONCE:
case ATA_CMD_WRITE_LONG:
@@ -2898,6 +2872,45 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
if (tf->protocol != ATA_PROT_PIO || tf->nsect != 1)
goto invalid_fld;
qc->sect_size = scsi_bufflen(scmd);
+ break;
+
+ /* commands using reported Logical Block size (e.g. 512 or 4K) */
+ case ATA_CMD_CFA_WRITE_NE:
+ case ATA_CMD_CFA_TRANS_SECT:
+ case ATA_CMD_CFA_WRITE_MULT_NE:
+ /* XXX: case ATA_CMD_CFA_WRITE_SECTORS_WITHOUT_ERASE: */
+ case ATA_CMD_READ:
+ case ATA_CMD_READ_EXT:
+ case ATA_CMD_READ_QUEUED:
+ /* XXX: case ATA_CMD_READ_QUEUED_EXT: */
+ case ATA_CMD_FPDMA_READ:
+ case ATA_CMD_READ_MULTI:
+ case ATA_CMD_READ_MULTI_EXT:
+ case ATA_CMD_PIO_READ:
+ case ATA_CMD_PIO_READ_EXT:
+ case ATA_CMD_READ_STREAM_DMA_EXT:
+ case ATA_CMD_READ_STREAM_EXT:
+ case ATA_CMD_VERIFY:
+ case ATA_CMD_VERIFY_EXT:
+ case ATA_CMD_WRITE:
+ case ATA_CMD_WRITE_EXT:
+ case ATA_CMD_WRITE_FUA_EXT:
+ case ATA_CMD_WRITE_QUEUED:
+ case ATA_CMD_WRITE_QUEUED_FUA_EXT:
+ case ATA_CMD_FPDMA_WRITE:
+ case ATA_CMD_WRITE_MULTI:
+ case ATA_CMD_WRITE_MULTI_EXT:
+ case ATA_CMD_WRITE_MULTI_FUA_EXT:
+ case ATA_CMD_PIO_WRITE:
+ case ATA_CMD_PIO_WRITE_EXT:
+ case ATA_CMD_WRITE_STREAM_DMA_EXT:
+ case ATA_CMD_WRITE_STREAM_EXT:
+ qc->sect_size = scmd->device->sector_size;
+ break;
+
+ /* Everything else uses 512 byte "sectors" */
+ default:
+ qc->sect_size = ATA_SECT_SIZE;
}
/*
@@ -3250,6 +3263,9 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd,
case 0xb1:
ata_scsi_rbuf_fill(&args, ata_scsiop_inq_b1);
break;
+ case 0xb2:
+ ata_scsi_rbuf_fill(&args, ata_scsiop_inq_b2);
+ break;
default:
ata_scsi_invalid_field(cmd, done);
break;
@@ -3334,7 +3350,7 @@ int ata_scsi_add_hosts(struct ata_host *host, struct scsi_host_template *sht)
*(struct ata_port **)&shost->hostdata[0] = ap;
ap->scsi_host = shost;
- shost->transportt = &ata_scsi_transport_template;
+ shost->transportt = ata_scsi_transport_template;
shost->unique_id = ap->print_id;
shost->max_id = 16;
shost->max_lun = 1;
@@ -3393,6 +3409,8 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync)
if (!IS_ERR(sdev)) {
dev->sdev = sdev;
scsi_device_put(sdev);
+ } else {
+ dev->sdev = NULL;
}
}
}
@@ -3616,8 +3634,8 @@ void ata_scsi_hotplug(struct work_struct *work)
* RETURNS:
* Zero.
*/
-static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
- unsigned int id, unsigned int lun)
+int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
+ unsigned int id, unsigned int lun)
{
struct ata_port *ap = ata_shost_to_port(shost);
unsigned long flags;
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index e30c537cce32..d05387d1e14b 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -222,7 +222,7 @@ int ata_sff_busy_sleep(struct ata_port *ap,
timeout = ata_deadline(timer_start, tmout_pat);
while (status != 0xff && (status & ATA_BUSY) &&
time_before(jiffies, timeout)) {
- msleep(50);
+ ata_msleep(ap, 50);
status = ata_sff_busy_wait(ap, ATA_BUSY, 3);
}
@@ -234,7 +234,7 @@ int ata_sff_busy_sleep(struct ata_port *ap,
timeout = ata_deadline(timer_start, tmout);
while (status != 0xff && (status & ATA_BUSY) &&
time_before(jiffies, timeout)) {
- msleep(50);
+ ata_msleep(ap, 50);
status = ap->ops->sff_check_status(ap);
}
@@ -360,7 +360,7 @@ static void ata_dev_select(struct ata_port *ap, unsigned int device,
if (wait) {
if (can_sleep && ap->link.device[device].class == ATA_DEV_ATAPI)
- msleep(150);
+ ata_msleep(ap, 150);
ata_wait_idle(ap);
}
}
@@ -1356,7 +1356,7 @@ fsm_start:
*/
status = ata_sff_busy_wait(ap, ATA_BUSY, 5);
if (status & ATA_BUSY) {
- msleep(2);
+ ata_msleep(ap, 2);
status = ata_sff_busy_wait(ap, ATA_BUSY, 10);
if (status & ATA_BUSY) {
ata_sff_queue_pio_task(link, ATA_SHORT_PAUSE);
@@ -1937,7 +1937,7 @@ int ata_sff_wait_after_reset(struct ata_link *link, unsigned int devmask,
unsigned int dev1 = devmask & (1 << 1);
int rc, ret = 0;
- msleep(ATA_WAIT_AFTER_RESET);
+ ata_msleep(ap, ATA_WAIT_AFTER_RESET);
/* always check readiness of the master device */
rc = ata_sff_wait_ready(link, deadline);
@@ -1966,7 +1966,7 @@ int ata_sff_wait_after_reset(struct ata_link *link, unsigned int devmask,
lbal = ioread8(ioaddr->lbal_addr);
if ((nsect == 1) && (lbal == 1))
break;
- msleep(50); /* give drive a breather */
+ ata_msleep(ap, 50); /* give drive a breather */
}
rc = ata_sff_wait_ready(link, deadline);
@@ -3335,14 +3335,14 @@ void ata_sff_port_init(struct ata_port *ap)
int __init ata_sff_init(void)
{
- ata_sff_wq = alloc_workqueue("ata_sff", WQ_RESCUER, WQ_MAX_ACTIVE);
+ ata_sff_wq = alloc_workqueue("ata_sff", WQ_MEM_RECLAIM, WQ_MAX_ACTIVE);
if (!ata_sff_wq)
return -ENOMEM;
return 0;
}
-void __exit ata_sff_exit(void)
+void ata_sff_exit(void)
{
destroy_workqueue(ata_sff_wq);
}
diff --git a/drivers/ata/libata-transport.c b/drivers/ata/libata-transport.c
new file mode 100644
index 000000000000..ce9dc6207f37
--- /dev/null
+++ b/drivers/ata/libata-transport.c
@@ -0,0 +1,774 @@
+/*
+ * Copyright 2008 ioogle, Inc. All rights reserved.
+ * Released under GPL v2.
+ *
+ * Libata transport class.
+ *
+ * The ATA transport class contains common code to deal with ATA HBAs,
+ * an approximated representation of ATA topologies in the driver model,
+ * and various sysfs attributes to expose these topologies and management
+ * interfaces to user-space.
+ *
+ * There are 3 objects defined in in this class:
+ * - ata_port
+ * - ata_link
+ * - ata_device
+ * Each port has a link object. Each link can have up to two devices for PATA
+ * and generally one for SATA.
+ * If there is SATA port multiplier [PMP], 15 additional ata_link object are
+ * created.
+ *
+ * These objects are created when the ata host is initialized and when a PMP is
+ * found. They are removed only when the HBA is removed, cleaned before the
+ * error handler runs.
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/blkdev.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <scsi/scsi_transport.h>
+#include <linux/libata.h>
+#include <linux/hdreg.h>
+#include <linux/uaccess.h>
+
+#include "libata.h"
+#include "libata-transport.h"
+
+#define ATA_PORT_ATTRS 2
+#define ATA_LINK_ATTRS 3
+#define ATA_DEV_ATTRS 9
+
+struct scsi_transport_template;
+struct scsi_transport_template *ata_scsi_transport_template;
+
+struct ata_internal {
+ struct scsi_transport_template t;
+
+ struct device_attribute private_port_attrs[ATA_PORT_ATTRS];
+ struct device_attribute private_link_attrs[ATA_LINK_ATTRS];
+ struct device_attribute private_dev_attrs[ATA_DEV_ATTRS];
+
+ struct transport_container link_attr_cont;
+ struct transport_container dev_attr_cont;
+
+ /*
+ * The array of null terminated pointers to attributes
+ * needed by scsi_sysfs.c
+ */
+ struct device_attribute *link_attrs[ATA_LINK_ATTRS + 1];
+ struct device_attribute *port_attrs[ATA_PORT_ATTRS + 1];
+ struct device_attribute *dev_attrs[ATA_DEV_ATTRS + 1];
+};
+#define to_ata_internal(tmpl) container_of(tmpl, struct ata_internal, t)
+
+
+#define tdev_to_device(d) \
+ container_of((d), struct ata_device, tdev)
+#define transport_class_to_dev(dev) \
+ tdev_to_device((dev)->parent)
+
+#define tdev_to_link(d) \
+ container_of((d), struct ata_link, tdev)
+#define transport_class_to_link(dev) \
+ tdev_to_link((dev)->parent)
+
+#define tdev_to_port(d) \
+ container_of((d), struct ata_port, tdev)
+#define transport_class_to_port(dev) \
+ tdev_to_port((dev)->parent)
+
+
+/* Device objects are always created whit link objects */
+static int ata_tdev_add(struct ata_device *dev);
+static void ata_tdev_delete(struct ata_device *dev);
+
+
+/*
+ * Hack to allow attributes of the same name in different objects.
+ */
+#define ATA_DEVICE_ATTR(_prefix,_name,_mode,_show,_store) \
+ struct device_attribute device_attr_##_prefix##_##_name = \
+ __ATTR(_name,_mode,_show,_store)
+
+#define ata_bitfield_name_match(title, table) \
+static ssize_t \
+get_ata_##title##_names(u32 table_key, char *buf) \
+{ \
+ char *prefix = ""; \
+ ssize_t len = 0; \
+ int i; \
+ \
+ for (i = 0; i < ARRAY_SIZE(table); i++) { \
+ if (table[i].value & table_key) { \
+ len += sprintf(buf + len, "%s%s", \
+ prefix, table[i].name); \
+ prefix = ", "; \
+ } \
+ } \
+ len += sprintf(buf + len, "\n"); \
+ return len; \
+}
+
+#define ata_bitfield_name_search(title, table) \
+static ssize_t \
+get_ata_##title##_names(u32 table_key, char *buf) \
+{ \
+ ssize_t len = 0; \
+ int i; \
+ \
+ for (i = 0; i < ARRAY_SIZE(table); i++) { \
+ if (table[i].value == table_key) { \
+ len += sprintf(buf + len, "%s", \
+ table[i].name); \
+ break; \
+ } \
+ } \
+ len += sprintf(buf + len, "\n"); \
+ return len; \
+}
+
+static struct {
+ u32 value;
+ char *name;
+} ata_class_names[] = {
+ { ATA_DEV_UNKNOWN, "unknown" },
+ { ATA_DEV_ATA, "ata" },
+ { ATA_DEV_ATA_UNSUP, "ata" },
+ { ATA_DEV_ATAPI, "atapi" },
+ { ATA_DEV_ATAPI_UNSUP, "atapi" },
+ { ATA_DEV_PMP, "pmp" },
+ { ATA_DEV_PMP_UNSUP, "pmp" },
+ { ATA_DEV_SEMB, "semb" },
+ { ATA_DEV_SEMB_UNSUP, "semb" },
+ { ATA_DEV_NONE, "none" }
+};
+ata_bitfield_name_search(class, ata_class_names)
+
+
+static struct {
+ u32 value;
+ char *name;
+} ata_err_names[] = {
+ { AC_ERR_DEV, "DeviceError" },
+ { AC_ERR_HSM, "HostStateMachineError" },
+ { AC_ERR_TIMEOUT, "Timeout" },
+ { AC_ERR_MEDIA, "MediaError" },
+ { AC_ERR_ATA_BUS, "BusError" },
+ { AC_ERR_HOST_BUS, "HostBusError" },
+ { AC_ERR_SYSTEM, "SystemError" },
+ { AC_ERR_INVALID, "InvalidArg" },
+ { AC_ERR_OTHER, "Unknown" },
+ { AC_ERR_NODEV_HINT, "NoDeviceHint" },
+ { AC_ERR_NCQ, "NCQError" }
+};
+ata_bitfield_name_match(err, ata_err_names)
+
+static struct {
+ u32 value;
+ char *name;
+} ata_xfer_names[] = {
+ { XFER_UDMA_7, "XFER_UDMA_7" },
+ { XFER_UDMA_6, "XFER_UDMA_6" },
+ { XFER_UDMA_5, "XFER_UDMA_5" },
+ { XFER_UDMA_4, "XFER_UDMA_4" },
+ { XFER_UDMA_3, "XFER_UDMA_3" },
+ { XFER_UDMA_2, "XFER_UDMA_2" },
+ { XFER_UDMA_1, "XFER_UDMA_1" },
+ { XFER_UDMA_0, "XFER_UDMA_0" },
+ { XFER_MW_DMA_4, "XFER_MW_DMA_4" },
+ { XFER_MW_DMA_3, "XFER_MW_DMA_3" },
+ { XFER_MW_DMA_2, "XFER_MW_DMA_2" },
+ { XFER_MW_DMA_1, "XFER_MW_DMA_1" },
+ { XFER_MW_DMA_0, "XFER_MW_DMA_0" },
+ { XFER_SW_DMA_2, "XFER_SW_DMA_2" },
+ { XFER_SW_DMA_1, "XFER_SW_DMA_1" },
+ { XFER_SW_DMA_0, "XFER_SW_DMA_0" },
+ { XFER_PIO_6, "XFER_PIO_6" },
+ { XFER_PIO_5, "XFER_PIO_5" },
+ { XFER_PIO_4, "XFER_PIO_4" },
+ { XFER_PIO_3, "XFER_PIO_3" },
+ { XFER_PIO_2, "XFER_PIO_2" },
+ { XFER_PIO_1, "XFER_PIO_1" },
+ { XFER_PIO_0, "XFER_PIO_0" },
+ { XFER_PIO_SLOW, "XFER_PIO_SLOW" }
+};
+ata_bitfield_name_match(xfer,ata_xfer_names)
+
+/*
+ * ATA Port attributes
+ */
+#define ata_port_show_simple(field, name, format_string, cast) \
+static ssize_t \
+show_ata_port_##name(struct device *dev, \
+ struct device_attribute *attr, char *buf) \
+{ \
+ struct ata_port *ap = transport_class_to_port(dev); \
+ \
+ return snprintf(buf, 20, format_string, cast ap->field); \
+}
+
+#define ata_port_simple_attr(field, name, format_string, type) \
+ ata_port_show_simple(field, name, format_string, (type)) \
+static DEVICE_ATTR(name, S_IRUGO, show_ata_port_##name, NULL)
+
+ata_port_simple_attr(nr_pmp_links, nr_pmp_links, "%d\n", int);
+ata_port_simple_attr(stats.idle_irq, idle_irq, "%ld\n", unsigned long);
+
+static DECLARE_TRANSPORT_CLASS(ata_port_class,
+ "ata_port", NULL, NULL, NULL);
+
+static void ata_tport_release(struct device *dev)
+{
+ put_device(dev->parent);
+}
+
+/**
+ * ata_is_port -- check if a struct device represents a ATA port
+ * @dev: device to check
+ *
+ * Returns:
+ * %1 if the device represents a ATA Port, %0 else
+ */
+int ata_is_port(const struct device *dev)
+{
+ return dev->release == ata_tport_release;
+}
+
+static int ata_tport_match(struct attribute_container *cont,
+ struct device *dev)
+{
+ if (!ata_is_port(dev))
+ return 0;
+ return &ata_scsi_transport_template->host_attrs.ac == cont;
+}
+
+/**
+ * ata_tport_delete -- remove ATA PORT
+ * @port: ATA PORT to remove
+ *
+ * Removes the specified ATA PORT. Remove the associated link as well.
+ */
+void ata_tport_delete(struct ata_port *ap)
+{
+ struct device *dev = &ap->tdev;
+
+ ata_tlink_delete(&ap->link);
+
+ transport_remove_device(dev);
+ device_del(dev);
+ transport_destroy_device(dev);
+ put_device(dev);
+}
+
+/** ata_tport_add - initialize a transport ATA port structure
+ *
+ * @parent: parent device
+ * @ap: existing ata_port structure
+ *
+ * Initialize a ATA port structure for sysfs. It will be added to the device
+ * tree below the device specified by @parent which could be a PCI device.
+ *
+ * Returns %0 on success
+ */
+int ata_tport_add(struct device *parent,
+ struct ata_port *ap)
+{
+ int error;
+ struct device *dev = &ap->tdev;
+
+ device_initialize(dev);
+
+ dev->parent = get_device(parent);
+ dev->release = ata_tport_release;
+ dev_set_name(dev, "ata%d", ap->print_id);
+ transport_setup_device(dev);
+ error = device_add(dev);
+ if (error) {
+ goto tport_err;
+ }
+
+ transport_add_device(dev);
+ transport_configure_device(dev);
+
+ error = ata_tlink_add(&ap->link);
+ if (error) {
+ goto tport_link_err;
+ }
+ return 0;
+
+ tport_link_err:
+ transport_remove_device(dev);
+ device_del(dev);
+
+ tport_err:
+ transport_destroy_device(dev);
+ put_device(dev);
+ return error;
+}
+
+
+/*
+ * ATA link attributes
+ */
+
+
+#define ata_link_show_linkspeed(field) \
+static ssize_t \
+show_ata_link_##field(struct device *dev, \
+ struct device_attribute *attr, char *buf) \
+{ \
+ struct ata_link *link = transport_class_to_link(dev); \
+ \
+ return sprintf(buf,"%s\n", sata_spd_string(fls(link->field))); \
+}
+
+#define ata_link_linkspeed_attr(field) \
+ ata_link_show_linkspeed(field) \
+static DEVICE_ATTR(field, S_IRUGO, show_ata_link_##field, NULL)
+
+ata_link_linkspeed_attr(hw_sata_spd_limit);
+ata_link_linkspeed_attr(sata_spd_limit);
+ata_link_linkspeed_attr(sata_spd);
+
+
+static DECLARE_TRANSPORT_CLASS(ata_link_class,
+ "ata_link", NULL, NULL, NULL);
+
+static void ata_tlink_release(struct device *dev)
+{
+ put_device(dev->parent);
+}
+
+/**
+ * ata_is_link -- check if a struct device represents a ATA link
+ * @dev: device to check
+ *
+ * Returns:
+ * %1 if the device represents a ATA link, %0 else
+ */
+int ata_is_link(const struct device *dev)
+{
+ return dev->release == ata_tlink_release;
+}
+
+static int ata_tlink_match(struct attribute_container *cont,
+ struct device *dev)
+{
+ struct ata_internal* i = to_ata_internal(ata_scsi_transport_template);
+ if (!ata_is_link(dev))
+ return 0;
+ return &i->link_attr_cont.ac == cont;
+}
+
+/**
+ * ata_tlink_delete -- remove ATA LINK
+ * @port: ATA LINK to remove
+ *
+ * Removes the specified ATA LINK. remove associated ATA device(s) as well.
+ */
+void ata_tlink_delete(struct ata_link *link)
+{
+ struct device *dev = &link->tdev;
+ struct ata_device *ata_dev;
+
+ ata_for_each_dev(ata_dev, link, ALL) {
+ ata_tdev_delete(ata_dev);
+ }
+
+ transport_remove_device(dev);
+ device_del(dev);
+ transport_destroy_device(dev);
+ put_device(dev);
+}
+
+/**
+ * ata_tlink_add -- initialize a transport ATA link structure
+ * @link: allocated ata_link structure.
+ *
+ * Initialize an ATA LINK structure for sysfs. It will be added in the
+ * device tree below the ATA PORT it belongs to.
+ *
+ * Returns %0 on success
+ */
+int ata_tlink_add(struct ata_link *link)
+{
+ struct device *dev = &link->tdev;
+ struct ata_port *ap = link->ap;
+ struct ata_device *ata_dev;
+ int error;
+
+ device_initialize(dev);
+ dev->parent = get_device(&ap->tdev);
+ dev->release = ata_tlink_release;
+ if (ata_is_host_link(link))
+ dev_set_name(dev, "link%d", ap->print_id);
+ else
+ dev_set_name(dev, "link%d.%d", ap->print_id, link->pmp);
+
+ transport_setup_device(dev);
+
+ error = device_add(dev);
+ if (error) {
+ goto tlink_err;
+ }
+
+ transport_add_device(dev);
+ transport_configure_device(dev);
+
+ ata_for_each_dev(ata_dev, link, ALL) {
+ error = ata_tdev_add(ata_dev);
+ if (error) {
+ goto tlink_dev_err;
+ }
+ }
+ return 0;
+ tlink_dev_err:
+ while (--ata_dev >= link->device) {
+ ata_tdev_delete(ata_dev);
+ }
+ transport_remove_device(dev);
+ device_del(dev);
+ tlink_err:
+ transport_destroy_device(dev);
+ put_device(dev);
+ return error;
+}
+
+/*
+ * ATA device attributes
+ */
+
+#define ata_dev_show_class(title, field) \
+static ssize_t \
+show_ata_dev_##field(struct device *dev, \
+ struct device_attribute *attr, char *buf) \
+{ \
+ struct ata_device *ata_dev = transport_class_to_dev(dev); \
+ \
+ return get_ata_##title##_names(ata_dev->field, buf); \
+}
+
+#define ata_dev_attr(title, field) \
+ ata_dev_show_class(title, field) \
+static DEVICE_ATTR(field, S_IRUGO, show_ata_dev_##field, NULL)
+
+ata_dev_attr(class, class);
+ata_dev_attr(xfer, pio_mode);
+ata_dev_attr(xfer, dma_mode);
+ata_dev_attr(xfer, xfer_mode);
+
+
+#define ata_dev_show_simple(field, format_string, cast) \
+static ssize_t \
+show_ata_dev_##field(struct device *dev, \
+ struct device_attribute *attr, char *buf) \
+{ \
+ struct ata_device *ata_dev = transport_class_to_dev(dev); \
+ \
+ return snprintf(buf, 20, format_string, cast ata_dev->field); \
+}
+
+#define ata_dev_simple_attr(field, format_string, type) \
+ ata_dev_show_simple(field, format_string, (type)) \
+static DEVICE_ATTR(field, S_IRUGO, \
+ show_ata_dev_##field, NULL)
+
+ata_dev_simple_attr(spdn_cnt, "%d\n", int);
+
+struct ata_show_ering_arg {
+ char* buf;
+ int written;
+};
+
+static int ata_show_ering(struct ata_ering_entry *ent, void *void_arg)
+{
+ struct ata_show_ering_arg* arg = void_arg;
+ struct timespec time;
+
+ jiffies_to_timespec(ent->timestamp,&time);
+ arg->written += sprintf(arg->buf + arg->written,
+ "[%5lu.%06lu]",
+ time.tv_sec, time.tv_nsec);
+ arg->written += get_ata_err_names(ent->err_mask,
+ arg->buf + arg->written);
+ return 0;
+}
+
+static ssize_t
+show_ata_dev_ering(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ata_device *ata_dev = transport_class_to_dev(dev);
+ struct ata_show_ering_arg arg = { buf, 0 };
+
+ ata_ering_map(&ata_dev->ering, ata_show_ering, &arg);
+ return arg.written;
+}
+
+
+static DEVICE_ATTR(ering, S_IRUGO, show_ata_dev_ering, NULL);
+
+static ssize_t
+show_ata_dev_id(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ata_device *ata_dev = transport_class_to_dev(dev);
+ int written = 0, i = 0;
+
+ if (ata_dev->class == ATA_DEV_PMP)
+ return 0;
+ for(i=0;i<ATA_ID_WORDS;i++) {
+ written += snprintf(buf+written, 20, "%04x%c",
+ ata_dev->id[i],
+ ((i+1) & 7) ? ' ' : '\n');
+ }
+ return written;
+}
+
+static DEVICE_ATTR(id, S_IRUGO, show_ata_dev_id, NULL);
+
+static ssize_t
+show_ata_dev_gscr(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ata_device *ata_dev = transport_class_to_dev(dev);
+ int written = 0, i = 0;
+
+ if (ata_dev->class != ATA_DEV_PMP)
+ return 0;
+ for(i=0;i<SATA_PMP_GSCR_DWORDS;i++) {
+ written += snprintf(buf+written, 20, "%08x%c",
+ ata_dev->gscr[i],
+ ((i+1) & 3) ? ' ' : '\n');
+ }
+ if (SATA_PMP_GSCR_DWORDS & 3)
+ buf[written-1] = '\n';
+ return written;
+}
+
+static DEVICE_ATTR(gscr, S_IRUGO, show_ata_dev_gscr, NULL);
+
+static DECLARE_TRANSPORT_CLASS(ata_dev_class,
+ "ata_device", NULL, NULL, NULL);
+
+static void ata_tdev_release(struct device *dev)
+{
+ put_device(dev->parent);
+}
+
+/**
+ * ata_is_ata_dev -- check if a struct device represents a ATA device
+ * @dev: device to check
+ *
+ * Returns:
+ * %1 if the device represents a ATA device, %0 else
+ */
+int ata_is_ata_dev(const struct device *dev)
+{
+ return dev->release == ata_tdev_release;
+}
+
+static int ata_tdev_match(struct attribute_container *cont,
+ struct device *dev)
+{
+ struct ata_internal* i = to_ata_internal(ata_scsi_transport_template);
+ if (!ata_is_ata_dev(dev))
+ return 0;
+ return &i->dev_attr_cont.ac == cont;
+}
+
+/**
+ * ata_tdev_free -- free a ATA LINK
+ * @dev: ATA PHY to free
+ *
+ * Frees the specified ATA PHY.
+ *
+ * Note:
+ * This function must only be called on a PHY that has not
+ * successfully been added using ata_tdev_add().
+ */
+static void ata_tdev_free(struct ata_device *dev)
+{
+ transport_destroy_device(&dev->tdev);
+ put_device(&dev->tdev);
+}
+
+/**
+ * ata_tdev_delete -- remove ATA device
+ * @port: ATA PORT to remove
+ *
+ * Removes the specified ATA device.
+ */
+static void ata_tdev_delete(struct ata_device *ata_dev)
+{
+ struct device *dev = &ata_dev->tdev;
+
+ transport_remove_device(dev);
+ device_del(dev);
+ ata_tdev_free(ata_dev);
+}
+
+
+/**
+ * ata_tdev_add -- initialize a transport ATA device structure.
+ * @ata_dev: ata_dev structure.
+ *
+ * Initialize an ATA device structure for sysfs. It will be added in the
+ * device tree below the ATA LINK device it belongs to.
+ *
+ * Returns %0 on success
+ */
+static int ata_tdev_add(struct ata_device *ata_dev)
+{
+ struct device *dev = &ata_dev->tdev;
+ struct ata_link *link = ata_dev->link;
+ struct ata_port *ap = link->ap;
+ int error;
+
+ device_initialize(dev);
+ dev->parent = get_device(&link->tdev);
+ dev->release = ata_tdev_release;
+ if (ata_is_host_link(link))
+ dev_set_name(dev, "dev%d.%d", ap->print_id,ata_dev->devno);
+ else
+ dev_set_name(dev, "dev%d.%d.0", ap->print_id, link->pmp);
+
+ transport_setup_device(dev);
+ error = device_add(dev);
+ if (error) {
+ ata_tdev_free(ata_dev);
+ return error;
+ }
+
+ transport_add_device(dev);
+ transport_configure_device(dev);
+ return 0;
+}
+
+
+/*
+ * Setup / Teardown code
+ */
+
+#define SETUP_TEMPLATE(attrb, field, perm, test) \
+ i->private_##attrb[count] = dev_attr_##field; \
+ i->private_##attrb[count].attr.mode = perm; \
+ i->attrb[count] = &i->private_##attrb[count]; \
+ if (test) \
+ count++
+
+#define SETUP_LINK_ATTRIBUTE(field) \
+ SETUP_TEMPLATE(link_attrs, field, S_IRUGO, 1)
+
+#define SETUP_PORT_ATTRIBUTE(field) \
+ SETUP_TEMPLATE(port_attrs, field, S_IRUGO, 1)
+
+#define SETUP_DEV_ATTRIBUTE(field) \
+ SETUP_TEMPLATE(dev_attrs, field, S_IRUGO, 1)
+
+/**
+ * ata_attach_transport -- instantiate ATA transport template
+ */
+struct scsi_transport_template *ata_attach_transport(void)
+{
+ struct ata_internal *i;
+ int count;
+
+ i = kzalloc(sizeof(struct ata_internal), GFP_KERNEL);
+ if (!i)
+ return NULL;
+
+ i->t.eh_strategy_handler = ata_scsi_error;
+ i->t.eh_timed_out = ata_scsi_timed_out;
+ i->t.user_scan = ata_scsi_user_scan;
+
+ i->t.host_attrs.ac.attrs = &i->port_attrs[0];
+ i->t.host_attrs.ac.class = &ata_port_class.class;
+ i->t.host_attrs.ac.match = ata_tport_match;
+ transport_container_register(&i->t.host_attrs);
+
+ i->link_attr_cont.ac.class = &ata_link_class.class;
+ i->link_attr_cont.ac.attrs = &i->link_attrs[0];
+ i->link_attr_cont.ac.match = ata_tlink_match;
+ transport_container_register(&i->link_attr_cont);
+
+ i->dev_attr_cont.ac.class = &ata_dev_class.class;
+ i->dev_attr_cont.ac.attrs = &i->dev_attrs[0];
+ i->dev_attr_cont.ac.match = ata_tdev_match;
+ transport_container_register(&i->dev_attr_cont);
+
+ count = 0;
+ SETUP_PORT_ATTRIBUTE(nr_pmp_links);
+ SETUP_PORT_ATTRIBUTE(idle_irq);
+ BUG_ON(count > ATA_PORT_ATTRS);
+ i->port_attrs[count] = NULL;
+
+ count = 0;
+ SETUP_LINK_ATTRIBUTE(hw_sata_spd_limit);
+ SETUP_LINK_ATTRIBUTE(sata_spd_limit);
+ SETUP_LINK_ATTRIBUTE(sata_spd);
+ BUG_ON(count > ATA_LINK_ATTRS);
+ i->link_attrs[count] = NULL;
+
+ count = 0;
+ SETUP_DEV_ATTRIBUTE(class);
+ SETUP_DEV_ATTRIBUTE(pio_mode);
+ SETUP_DEV_ATTRIBUTE(dma_mode);
+ SETUP_DEV_ATTRIBUTE(xfer_mode);
+ SETUP_DEV_ATTRIBUTE(spdn_cnt);
+ SETUP_DEV_ATTRIBUTE(ering);
+ SETUP_DEV_ATTRIBUTE(id);
+ SETUP_DEV_ATTRIBUTE(gscr);
+ BUG_ON(count > ATA_DEV_ATTRS);
+ i->dev_attrs[count] = NULL;
+
+ return &i->t;
+}
+
+/**
+ * ata_release_transport -- release ATA transport template instance
+ * @t: transport template instance
+ */
+void ata_release_transport(struct scsi_transport_template *t)
+{
+ struct ata_internal *i = to_ata_internal(t);
+
+ transport_container_unregister(&i->t.host_attrs);
+ transport_container_unregister(&i->link_attr_cont);
+ transport_container_unregister(&i->dev_attr_cont);
+
+ kfree(i);
+}
+
+__init int libata_transport_init(void)
+{
+ int error;
+
+ error = transport_class_register(&ata_link_class);
+ if (error)
+ goto out_unregister_transport;
+ error = transport_class_register(&ata_port_class);
+ if (error)
+ goto out_unregister_link;
+ error = transport_class_register(&ata_dev_class);
+ if (error)
+ goto out_unregister_port;
+ return 0;
+
+ out_unregister_port:
+ transport_class_unregister(&ata_port_class);
+ out_unregister_link:
+ transport_class_unregister(&ata_link_class);
+ out_unregister_transport:
+ return error;
+
+}
+
+void __exit libata_transport_exit(void)
+{
+ transport_class_unregister(&ata_link_class);
+ transport_class_unregister(&ata_port_class);
+ transport_class_unregister(&ata_dev_class);
+}
diff --git a/drivers/ata/libata-transport.h b/drivers/ata/libata-transport.h
new file mode 100644
index 000000000000..2820cf864f11
--- /dev/null
+++ b/drivers/ata/libata-transport.h
@@ -0,0 +1,18 @@
+#ifndef _LIBATA_TRANSPORT_H
+#define _LIBATA_TRANSPORT_H
+
+
+extern struct scsi_transport_template *ata_scsi_transport_template;
+
+int ata_tlink_add(struct ata_link *link);
+void ata_tlink_delete(struct ata_link *link);
+
+int ata_tport_add(struct device *parent, struct ata_port *ap);
+void ata_tport_delete(struct ata_port *ap);
+
+struct scsi_transport_template *ata_attach_transport(void);
+void ata_release_transport(struct scsi_transport_template *t);
+
+__init int libata_transport_init(void);
+void __exit libata_transport_exit(void);
+#endif
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index 9ce1ecc63e39..a9be110dbf51 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -86,6 +86,8 @@ extern int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,
extern int ata_dev_configure(struct ata_device *dev);
extern int sata_down_spd_limit(struct ata_link *link, u32 spd_limit);
extern int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel);
+extern unsigned int ata_dev_set_feature(struct ata_device *dev,
+ u8 enable, u8 feature);
extern void ata_sg_clean(struct ata_queued_cmd *qc);
extern void ata_qc_free(struct ata_queued_cmd *qc);
extern void ata_qc_issue(struct ata_queued_cmd *qc);
@@ -100,8 +102,7 @@ extern int sata_link_init_spd(struct ata_link *link);
extern int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg);
extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg);
extern struct ata_port *ata_port_alloc(struct ata_host *host);
-extern void ata_dev_enable_pm(struct ata_device *dev, enum link_pm policy);
-extern void ata_lpm_schedule(struct ata_port *ap, enum link_pm);
+extern const char *sata_spd_string(unsigned int spd);
/* libata-acpi.c */
#ifdef CONFIG_ATA_ACPI
@@ -137,10 +138,15 @@ extern void ata_scsi_hotplug(struct work_struct *work);
extern void ata_schedule_scsi_eh(struct Scsi_Host *shost);
extern void ata_scsi_dev_rescan(struct work_struct *work);
extern int ata_bus_probe(struct ata_port *ap);
+extern int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
+ unsigned int id, unsigned int lun);
+
/* libata-eh.c */
extern unsigned long ata_internal_cmd_timeout(struct ata_device *dev, u8 cmd);
extern void ata_internal_cmd_timed_out(struct ata_device *dev, u8 cmd);
+extern void ata_eh_acquire(struct ata_port *ap);
+extern void ata_eh_release(struct ata_port *ap);
extern enum blk_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd);
extern void ata_scsi_error(struct Scsi_Host *host);
extern void ata_port_wait_eh(struct ata_port *ap);
@@ -164,11 +170,16 @@ extern int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
ata_postreset_fn_t postreset,
struct ata_link **r_failed_disk);
extern void ata_eh_finish(struct ata_port *ap);
+extern int ata_ering_map(struct ata_ering *ering,
+ int (*map_fn)(struct ata_ering_entry *, void *),
+ void *arg);
/* libata-pmp.c */
#ifdef CONFIG_SATA_PMP
extern int sata_pmp_scr_read(struct ata_link *link, int reg, u32 *val);
extern int sata_pmp_scr_write(struct ata_link *link, int reg, u32 val);
+extern int sata_pmp_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
+ unsigned hints);
extern int sata_pmp_attach(struct ata_device *dev);
#else /* CONFIG_SATA_PMP */
static inline int sata_pmp_scr_read(struct ata_link *link, int reg, u32 *val)
@@ -181,6 +192,12 @@ static inline int sata_pmp_scr_write(struct ata_link *link, int reg, u32 val)
return -EINVAL;
}
+static inline int sata_pmp_set_lpm(struct ata_link *link,
+ enum ata_lpm_policy policy, unsigned hints)
+{
+ return -EINVAL;
+}
+
static inline int sata_pmp_attach(struct ata_device *dev)
{
return -EINVAL;
diff --git a/drivers/ata/pata_bf54x.c b/drivers/ata/pata_bf54x.c
index 9cae65de750e..ec2c777fcdb0 100644
--- a/drivers/ata/pata_bf54x.c
+++ b/drivers/ata/pata_bf54x.c
@@ -826,7 +826,7 @@ static void bfin_dev_select(struct ata_port *ap, unsigned int device)
* @ctl: value to write
*/
-static u8 bfin_set_devctl(struct ata_port *ap, u8 ctl)
+static void bfin_set_devctl(struct ata_port *ap, u8 ctl)
{
void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
write_atapi_register(base, ATA_REG_CTRL, ctl);
@@ -1046,7 +1046,7 @@ static void bfin_bus_post_reset(struct ata_port *ap, unsigned int devmask)
dev1 = 0;
break;
}
- msleep(50); /* give drive a breather */
+ ata_msleep(ap, 50); /* give drive a breather */
}
if (dev1)
ata_sff_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
@@ -1087,7 +1087,7 @@ static unsigned int bfin_bus_softreset(struct ata_port *ap,
*
* Old drivers/ide uses the 2mS rule and then waits for ready
*/
- msleep(150);
+ ata_msleep(ap, 150);
/* Before we perform post reset processing we want to see if
* the bus shows 0xFF because the odd clown forgets the D7
diff --git a/drivers/ata/pata_cmd640.c b/drivers/ata/pata_cmd640.c
index e5f289f59ca3..549d28dbf90d 100644
--- a/drivers/ata/pata_cmd640.c
+++ b/drivers/ata/pata_cmd640.c
@@ -161,6 +161,17 @@ static int cmd640_port_start(struct ata_port *ap)
return 0;
}
+static bool cmd640_sff_irq_check(struct ata_port *ap)
+{
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ int irq_reg = ap->port_no ? ARTIM23 : CFR;
+ u8 irq_stat, irq_mask = ap->port_no ? 0x10 : 0x04;
+
+ pci_read_config_byte(pdev, irq_reg, &irq_stat);
+
+ return irq_stat & irq_mask;
+}
+
static struct scsi_host_template cmd640_sht = {
ATA_PIO_SHT(DRV_NAME),
};
@@ -169,6 +180,7 @@ static struct ata_port_operations cmd640_port_ops = {
.inherits = &ata_sff_port_ops,
/* In theory xfer_noirq is not needed once we kill the prefetcher */
.sff_data_xfer = ata_sff_data_xfer_noirq,
+ .sff_irq_check = cmd640_sff_irq_check,
.qc_issue = cmd640_qc_issue,
.cable_detect = ata_cable_40wire,
.set_piomode = cmd640_set_piomode,
diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c
index e944aa0c5517..806292160b3f 100644
--- a/drivers/ata/pata_pcmcia.c
+++ b/drivers/ata/pata_pcmcia.c
@@ -34,7 +34,6 @@
#include <linux/ata.h>
#include <linux/libata.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
#include <pcmcia/cisreg.h>
@@ -168,63 +167,26 @@ static struct ata_port_operations pcmcia_8bit_port_ops = {
};
-struct pcmcia_config_check {
- unsigned long ctl_base;
- int skip_vcc;
- int is_kme;
-};
-
-static int pcmcia_check_one_config(struct pcmcia_device *pdev,
- cistpl_cftable_entry_t *cfg,
- cistpl_cftable_entry_t *dflt,
- unsigned int vcc,
- void *priv_data)
+static int pcmcia_check_one_config(struct pcmcia_device *pdev, void *priv_data)
{
- struct pcmcia_config_check *stk = priv_data;
-
- /* Check for matching Vcc, unless we're desperate */
- if (!stk->skip_vcc) {
- if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
- if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
- return -ENODEV;
- } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
- if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000)
- return -ENODEV;
- }
+ int *is_kme = priv_data;
+
+ if (!(pdev->resource[0]->flags & IO_DATA_PATH_WIDTH_8)) {
+ pdev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+ pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
}
+ pdev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
+ pdev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
- if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
- pdev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
- else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
- pdev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-
- if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
- cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
- pdev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
- pdev->resource[0]->start = io->win[0].base;
- if (!(io->flags & CISTPL_IO_16BIT)) {
- pdev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
- pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
- }
- if (io->nwin == 2) {
- pdev->resource[0]->end = 8;
- pdev->resource[1]->start = io->win[1].base;
- pdev->resource[1]->end = (stk->is_kme) ? 2 : 1;
- if (pcmcia_request_io(pdev) != 0)
- return -ENODEV;
- stk->ctl_base = pdev->resource[1]->start;
- } else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
- pdev->resource[0]->end = io->win[0].len;
- pdev->resource[1]->end = 0;
- if (pcmcia_request_io(pdev) != 0)
- return -ENODEV;
- stk->ctl_base = pdev->resource[0]->start + 0x0e;
- } else
+ if (pdev->resource[1]->end) {
+ pdev->resource[0]->end = 8;
+ pdev->resource[1]->end = (*is_kme) ? 2 : 1;
+ } else {
+ if (pdev->resource[0]->end < 16)
return -ENODEV;
- /* If we've got this far, we're done */
- return 0;
}
- return -ENODEV;
+
+ return pcmcia_request_io(pdev);
}
/**
@@ -239,7 +201,6 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
{
struct ata_host *host;
struct ata_port *ap;
- struct pcmcia_config_check *stk = NULL;
int is_kme = 0, ret = -ENOMEM, p;
unsigned long io_base, ctl_base;
void __iomem *io_addr, *ctl_addr;
@@ -247,10 +208,8 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
struct ata_port_operations *ops = &pcmcia_port_ops;
/* Set up attributes in order to probe card and get resources */
- pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
- pdev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
- pdev->conf.Attributes = CONF_ENABLE_IRQ;
- pdev->conf.IntType = INT_MEMORY_AND_IO;
+ pdev->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO |
+ CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC;
/* See if we have a manufacturer identifier. Use it to set is_kme for
vendor quirks */
@@ -258,25 +217,21 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
((pdev->card_id == PRODID_KME_KXLC005_A) ||
(pdev->card_id == PRODID_KME_KXLC005_B)));
- /* Allocate resoure probing structures */
-
- stk = kzalloc(sizeof(*stk), GFP_KERNEL);
- if (!stk)
- goto out1;
- stk->is_kme = is_kme;
- stk->skip_vcc = io_base = ctl_base = 0;
-
- if (pcmcia_loop_config(pdev, pcmcia_check_one_config, stk)) {
- stk->skip_vcc = 1;
- if (pcmcia_loop_config(pdev, pcmcia_check_one_config, stk))
+ if (pcmcia_loop_config(pdev, pcmcia_check_one_config, &is_kme)) {
+ pdev->config_flags &= ~CONF_AUTO_CHECK_VCC;
+ if (pcmcia_loop_config(pdev, pcmcia_check_one_config, &is_kme))
goto failed; /* No suitable config found */
}
io_base = pdev->resource[0]->start;
- ctl_base = stk->ctl_base;
+ if (pdev->resource[1]->end)
+ ctl_base = pdev->resource[1]->start;
+ else
+ ctl_base = pdev->resource[0]->start + 0x0e;
+
if (!pdev->irq)
goto failed;
- ret = pcmcia_request_configuration(pdev, &pdev->conf);
+ ret = pcmcia_enable_device(pdev);
if (ret)
goto failed;
@@ -329,13 +284,10 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
goto failed;
pdev->priv = host;
- kfree(stk);
return 0;
failed:
- kfree(stk);
pcmcia_disable_device(pdev);
-out1:
return ret;
}
@@ -430,9 +382,7 @@ MODULE_DEVICE_TABLE(pcmcia, pcmcia_devices);
static struct pcmcia_driver pcmcia_driver = {
.owner = THIS_MODULE,
- .drv = {
- .name = DRV_NAME,
- },
+ .name = DRV_NAME,
.id_table = pcmcia_devices,
.probe = pcmcia_init_one,
.remove = pcmcia_remove_one,
diff --git a/drivers/ata/pata_pdc202xx_old.c b/drivers/ata/pata_pdc202xx_old.c
index c39f213e1bbc..c2ed5868dda6 100644
--- a/drivers/ata/pata_pdc202xx_old.c
+++ b/drivers/ata/pata_pdc202xx_old.c
@@ -44,6 +44,27 @@ static void pdc202xx_exec_command(struct ata_port *ap,
ndelay(400);
}
+static bool pdc202xx_irq_check(struct ata_port *ap)
+{
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ unsigned long master = pci_resource_start(pdev, 4);
+ u8 sc1d = inb(master + 0x1d);
+
+ if (ap->port_no) {
+ /*
+ * bit 7: error, bit 6: interrupting,
+ * bit 5: FIFO full, bit 4: FIFO empty
+ */
+ return sc1d & 0x40;
+ } else {
+ /*
+ * bit 3: error, bit 2: interrupting,
+ * bit 1: FIFO full, bit 0: FIFO empty
+ */
+ return sc1d & 0x04;
+ }
+}
+
/**
* pdc202xx_configure_piomode - set chip PIO timing
* @ap: ATA interface
@@ -282,6 +303,7 @@ static struct ata_port_operations pdc2024x_port_ops = {
.set_dmamode = pdc202xx_set_dmamode,
.sff_exec_command = pdc202xx_exec_command,
+ .sff_irq_check = pdc202xx_irq_check,
};
static struct ata_port_operations pdc2026x_port_ops = {
@@ -297,6 +319,7 @@ static struct ata_port_operations pdc2026x_port_ops = {
.port_start = pdc2026x_port_start,
.sff_exec_command = pdc202xx_exec_command,
+ .sff_irq_check = pdc202xx_irq_check,
};
static int pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id)
diff --git a/drivers/ata/pata_samsung_cf.c b/drivers/ata/pata_samsung_cf.c
index 6f9cfb24b751..8a51d673e5b2 100644
--- a/drivers/ata/pata_samsung_cf.c
+++ b/drivers/ata/pata_samsung_cf.c
@@ -322,7 +322,7 @@ static int pata_s3c_wait_after_reset(struct ata_link *link,
{
int rc;
- msleep(ATA_WAIT_AFTER_RESET);
+ ata_msleep(link->ap, ATA_WAIT_AFTER_RESET);
/* always check readiness of the master device */
rc = ata_sff_wait_ready(link, deadline);
diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c
index fe36966f7e34..093715c3273a 100644
--- a/drivers/ata/pata_scc.c
+++ b/drivers/ata/pata_scc.c
@@ -530,7 +530,7 @@ static int scc_wait_after_reset(struct ata_link *link, unsigned int devmask,
*
* Old drivers/ide uses the 2mS rule and then waits for ready.
*/
- msleep(150);
+ ata_msleep(ap, 150);
/* always check readiness of the master device */
rc = ata_sff_wait_ready(link, deadline);
@@ -559,7 +559,7 @@ static int scc_wait_after_reset(struct ata_link *link, unsigned int devmask,
lbal = in_be32(ioaddr->lbal_addr);
if ((nsect == 1) && (lbal == 1))
break;
- msleep(50); /* give drive a breather */
+ ata_msleep(ap, 50); /* give drive a breather */
}
rc = ata_sff_wait_ready(link, deadline);
diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c
index d3190d7ec304..00eefbd84b33 100644
--- a/drivers/ata/pata_sil680.c
+++ b/drivers/ata/pata_sil680.c
@@ -202,14 +202,25 @@ static void sil680_set_dmamode(struct ata_port *ap, struct ata_device *adev)
* LOCKING:
* spin_lock_irqsave(host lock)
*/
-void sil680_sff_exec_command(struct ata_port *ap,
- const struct ata_taskfile *tf)
+static void sil680_sff_exec_command(struct ata_port *ap,
+ const struct ata_taskfile *tf)
{
DPRINTK("ata%u: cmd 0x%X\n", ap->print_id, tf->command);
iowrite8(tf->command, ap->ioaddr.command_addr);
ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
}
+static bool sil680_sff_irq_check(struct ata_port *ap)
+{
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ unsigned long addr = sil680_selreg(ap, 1);
+ u8 val;
+
+ pci_read_config_byte(pdev, addr, &val);
+
+ return val & 0x08;
+}
+
static struct scsi_host_template sil680_sht = {
ATA_BMDMA_SHT(DRV_NAME),
};
@@ -218,6 +229,7 @@ static struct scsi_host_template sil680_sht = {
static struct ata_port_operations sil680_port_ops = {
.inherits = &ata_bmdma32_port_ops,
.sff_exec_command = sil680_sff_exec_command,
+ .sff_irq_check = sil680_sff_irq_check,
.cable_detect = sil680_cable_detect,
.set_piomode = sil680_set_piomode,
.set_dmamode = sil680_set_dmamode,
diff --git a/drivers/ata/pata_sl82c105.c b/drivers/ata/pata_sl82c105.c
index 98548f640c8e..7f5d020ed56c 100644
--- a/drivers/ata/pata_sl82c105.c
+++ b/drivers/ata/pata_sl82c105.c
@@ -227,6 +227,16 @@ static int sl82c105_qc_defer(struct ata_queued_cmd *qc)
return 0;
}
+static bool sl82c105_sff_irq_check(struct ata_port *ap)
+{
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ u32 val, mask = ap->port_no ? CTRL_IDE_IRQB : CTRL_IDE_IRQA;
+
+ pci_read_config_dword(pdev, 0x40, &val);
+
+ return val & mask;
+}
+
static struct scsi_host_template sl82c105_sht = {
ATA_BMDMA_SHT(DRV_NAME),
};
@@ -239,6 +249,7 @@ static struct ata_port_operations sl82c105_port_ops = {
.cable_detect = ata_cable_40wire,
.set_piomode = sl82c105_set_piomode,
.prereset = sl82c105_pre_reset,
+ .sff_irq_check = sl82c105_sff_irq_check,
};
/**
diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c
index 7325f77480dc..b0214d00d50b 100644
--- a/drivers/ata/sata_fsl.c
+++ b/drivers/ata/sata_fsl.c
@@ -678,7 +678,7 @@ static void sata_fsl_port_stop(struct ata_port *ap)
iowrite32(temp, hcr_base + HCONTROL);
/* Poll for controller to go offline - should happen immediately */
- ata_wait_register(hcr_base + HSTATUS, ONLINE, ONLINE, 1, 1);
+ ata_wait_register(ap, hcr_base + HSTATUS, ONLINE, ONLINE, 1, 1);
ap->private_data = NULL;
dma_free_coherent(dev, SATA_FSL_PORT_PRIV_DMA_SZ,
@@ -729,7 +729,8 @@ try_offline_again:
iowrite32(temp, hcr_base + HCONTROL);
/* Poll for controller to go offline */
- temp = ata_wait_register(hcr_base + HSTATUS, ONLINE, ONLINE, 1, 500);
+ temp = ata_wait_register(ap, hcr_base + HSTATUS, ONLINE, ONLINE,
+ 1, 500);
if (temp & ONLINE) {
ata_port_printk(ap, KERN_ERR,
@@ -752,7 +753,7 @@ try_offline_again:
/*
* PHY reset should remain asserted for atleast 1ms
*/
- msleep(1);
+ ata_msleep(ap, 1);
/*
* Now, bring the host controller online again, this can take time
@@ -766,7 +767,7 @@ try_offline_again:
temp |= HCONTROL_PMP_ATTACHED;
iowrite32(temp, hcr_base + HCONTROL);
- temp = ata_wait_register(hcr_base + HSTATUS, ONLINE, 0, 1, 500);
+ temp = ata_wait_register(ap, hcr_base + HSTATUS, ONLINE, 0, 1, 500);
if (!(temp & ONLINE)) {
ata_port_printk(ap, KERN_ERR,
@@ -784,7 +785,7 @@ try_offline_again:
* presence
*/
- temp = ata_wait_register(hcr_base + HSTATUS, 0xFF, 0, 1, 500);
+ temp = ata_wait_register(ap, hcr_base + HSTATUS, 0xFF, 0, 1, 500);
if ((!(temp & 0x10)) || ata_link_offline(link)) {
ata_port_printk(ap, KERN_WARNING,
"No Device OR PHYRDY change,Hstatus = 0x%x\n",
@@ -797,7 +798,7 @@ try_offline_again:
* Wait for the first D2H from device,i.e,signature update notification
*/
start_jiffies = jiffies;
- temp = ata_wait_register(hcr_base + HSTATUS, 0xFF, 0x10,
+ temp = ata_wait_register(ap, hcr_base + HSTATUS, 0xFF, 0x10,
500, jiffies_to_msecs(deadline - start_jiffies));
if ((temp & 0xFF) != 0x18) {
@@ -880,7 +881,7 @@ static int sata_fsl_softreset(struct ata_link *link, unsigned int *class,
iowrite32(pmp, CQPMP + hcr_base);
iowrite32(1, CQ + hcr_base);
- temp = ata_wait_register(CQ + hcr_base, 0x1, 0x1, 1, 5000);
+ temp = ata_wait_register(ap, CQ + hcr_base, 0x1, 0x1, 1, 5000);
if (temp & 0x1) {
ata_port_printk(ap, KERN_WARNING, "ATA_SRST issue failed\n");
@@ -896,7 +897,7 @@ static int sata_fsl_softreset(struct ata_link *link, unsigned int *class,
goto err;
}
- msleep(1);
+ ata_msleep(ap, 1);
/*
* SATA device enters reset state after receving a Control register
@@ -915,7 +916,7 @@ static int sata_fsl_softreset(struct ata_link *link, unsigned int *class,
if (pmp != SATA_PMP_CTRL_PORT)
iowrite32(pmp, CQPMP + hcr_base);
iowrite32(1, CQ + hcr_base);
- msleep(150); /* ?? */
+ ata_msleep(ap, 150); /* ?? */
/*
* The above command would have signalled an interrupt on command
@@ -1137,17 +1138,13 @@ static void sata_fsl_host_intr(struct ata_port *ap)
ioread32(hcr_base + CE));
for (i = 0; i < SATA_FSL_QUEUE_DEPTH; i++) {
- if (done_mask & (1 << i)) {
- qc = ata_qc_from_tag(ap, i);
- if (qc) {
- ata_qc_complete(qc);
- }
+ if (done_mask & (1 << i))
DPRINTK
("completing ncq cmd,tag=%d,CC=0x%x,CA=0x%x\n",
i, ioread32(hcr_base + CC),
ioread32(hcr_base + CA));
- }
}
+ ata_qc_complete_multiple(ap, ap->qc_active ^ done_mask);
return;
} else if ((ap->qc_active & (1 << ATA_TAG_INTERNAL))) {
diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c
index a36149ebf4a2..83a44471b189 100644
--- a/drivers/ata/sata_inic162x.c
+++ b/drivers/ata/sata_inic162x.c
@@ -614,7 +614,7 @@ static int inic_hardreset(struct ata_link *link, unsigned int *class,
writew(IDMA_CTL_RST_ATA, idma_ctl);
readw(idma_ctl); /* flush */
- msleep(1);
+ ata_msleep(ap, 1);
writew(0, idma_ctl);
rc = sata_link_resume(link, timing, deadline);
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index a9fd9709c262..bf74a36d3cc3 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -2743,18 +2743,11 @@ static void mv_err_intr(struct ata_port *ap)
}
}
-static void mv_process_crpb_response(struct ata_port *ap,
+static bool mv_process_crpb_response(struct ata_port *ap,
struct mv_crpb *response, unsigned int tag, int ncq_enabled)
{
u8 ata_status;
u16 edma_status = le16_to_cpu(response->flags);
- struct ata_queued_cmd *qc = ata_qc_from_tag(ap, tag);
-
- if (unlikely(!qc)) {
- ata_port_printk(ap, KERN_ERR, "%s: no qc for tag=%d\n",
- __func__, tag);
- return;
- }
/*
* edma_status from a response queue entry:
@@ -2768,13 +2761,14 @@ static void mv_process_crpb_response(struct ata_port *ap,
* Error will be seen/handled by
* mv_err_intr(). So do nothing at all here.
*/
- return;
+ return false;
}
}
ata_status = edma_status >> CRPB_FLAG_STATUS_SHIFT;
if (!ac_err_mask(ata_status))
- ata_qc_complete(qc);
+ return true;
/* else: leave it for mv_err_intr() */
+ return false;
}
static void mv_process_crpb_entries(struct ata_port *ap, struct mv_port_priv *pp)
@@ -2783,6 +2777,7 @@ static void mv_process_crpb_entries(struct ata_port *ap, struct mv_port_priv *pp
struct mv_host_priv *hpriv = ap->host->private_data;
u32 in_index;
bool work_done = false;
+ u32 done_mask = 0;
int ncq_enabled = (pp->pp_flags & MV_PP_FLAG_NCQ_EN);
/* Get the hardware queue position index */
@@ -2803,15 +2798,19 @@ static void mv_process_crpb_entries(struct ata_port *ap, struct mv_port_priv *pp
/* Gen II/IIE: get command tag from CRPB entry */
tag = le16_to_cpu(response->id) & 0x1f;
}
- mv_process_crpb_response(ap, response, tag, ncq_enabled);
+ if (mv_process_crpb_response(ap, response, tag, ncq_enabled))
+ done_mask |= 1 << tag;
work_done = true;
}
- /* Update the software queue position index in hardware */
- if (work_done)
+ if (work_done) {
+ ata_qc_complete_multiple(ap, ap->qc_active ^ done_mask);
+
+ /* Update the software queue position index in hardware */
writelfl((pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK) |
(pp->resp_idx << EDMA_RSP_Q_PTR_SHIFT),
port_mmio + EDMA_RSP_Q_OUT_PTR);
+ }
}
static void mv_port_intr(struct ata_port *ap, u32 port_cause)
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
index cb89ef8d99d9..7254e255fd78 100644
--- a/drivers/ata/sata_nv.c
+++ b/drivers/ata/sata_nv.c
@@ -873,29 +873,11 @@ static int nv_adma_check_cpb(struct ata_port *ap, int cpb_num, int force_err)
ata_port_freeze(ap);
else
ata_port_abort(ap);
- return 1;
+ return -1;
}
- if (likely(flags & NV_CPB_RESP_DONE)) {
- struct ata_queued_cmd *qc = ata_qc_from_tag(ap, cpb_num);
- VPRINTK("CPB flags done, flags=0x%x\n", flags);
- if (likely(qc)) {
- DPRINTK("Completing qc from tag %d\n", cpb_num);
- ata_qc_complete(qc);
- } else {
- struct ata_eh_info *ehi = &ap->link.eh_info;
- /* Notifier bits set without a command may indicate the drive
- is misbehaving. Raise host state machine violation on this
- condition. */
- ata_port_printk(ap, KERN_ERR,
- "notifier for tag %d with no cmd?\n",
- cpb_num);
- ehi->err_mask |= AC_ERR_HSM;
- ehi->action |= ATA_EH_RESET;
- ata_port_freeze(ap);
- return 1;
- }
- }
+ if (likely(flags & NV_CPB_RESP_DONE))
+ return 1;
return 0;
}
@@ -1018,6 +1000,7 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
NV_ADMA_STAT_CPBERR |
NV_ADMA_STAT_CMD_COMPLETE)) {
u32 check_commands = notifier_clears[i];
+ u32 done_mask = 0;
int pos, rc;
if (status & NV_ADMA_STAT_CPBERR) {
@@ -1034,10 +1017,13 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
pos--;
rc = nv_adma_check_cpb(ap, pos,
notifier_error & (1 << pos));
- if (unlikely(rc))
+ if (rc > 0)
+ done_mask |= 1 << pos;
+ else if (unlikely(rc < 0))
check_commands = 0;
check_commands &= ~(1 << pos);
}
+ ata_qc_complete_multiple(ap, ap->qc_active ^ done_mask);
}
}
@@ -2132,7 +2118,6 @@ static int nv_swncq_sdbfis(struct ata_port *ap)
struct ata_eh_info *ehi = &ap->link.eh_info;
u32 sactive;
u32 done_mask;
- int i;
u8 host_stat;
u8 lack_dhfis = 0;
@@ -2152,27 +2137,11 @@ static int nv_swncq_sdbfis(struct ata_port *ap)
sactive = readl(pp->sactive_block);
done_mask = pp->qc_active ^ sactive;
- if (unlikely(done_mask & sactive)) {
- ata_ehi_clear_desc(ehi);
- ata_ehi_push_desc(ehi, "illegal SWNCQ:qc_active transition"
- "(%08x->%08x)", pp->qc_active, sactive);
- ehi->err_mask |= AC_ERR_HSM;
- ehi->action |= ATA_EH_RESET;
- return -EINVAL;
- }
- for (i = 0; i < ATA_MAX_QUEUE; i++) {
- if (!(done_mask & (1 << i)))
- continue;
-
- qc = ata_qc_from_tag(ap, i);
- if (qc) {
- ata_qc_complete(qc);
- pp->qc_active &= ~(1 << i);
- pp->dhfis_bits &= ~(1 << i);
- pp->dmafis_bits &= ~(1 << i);
- pp->sdbfis_bits |= (1 << i);
- }
- }
+ pp->qc_active &= ~done_mask;
+ pp->dhfis_bits &= ~done_mask;
+ pp->dmafis_bits &= ~done_mask;
+ pp->sdbfis_bits |= done_mask;
+ ata_qc_complete_multiple(ap, ap->qc_active ^ done_mask);
if (!ap->qc_active) {
DPRINTK("over\n");
diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c
index be7726d7686d..af41c6fd1254 100644
--- a/drivers/ata/sata_sil24.c
+++ b/drivers/ata/sata_sil24.c
@@ -589,9 +589,9 @@ static int sil24_init_port(struct ata_port *ap)
sil24_clear_pmp(ap);
writel(PORT_CS_INIT, port + PORT_CTRL_STAT);
- ata_wait_register(port + PORT_CTRL_STAT,
+ ata_wait_register(ap, port + PORT_CTRL_STAT,
PORT_CS_INIT, PORT_CS_INIT, 10, 100);
- tmp = ata_wait_register(port + PORT_CTRL_STAT,
+ tmp = ata_wait_register(ap, port + PORT_CTRL_STAT,
PORT_CS_RDY, 0, 10, 100);
if ((tmp & (PORT_CS_INIT | PORT_CS_RDY)) != PORT_CS_RDY) {
@@ -631,7 +631,7 @@ static int sil24_exec_polled_cmd(struct ata_port *ap, int pmp,
writel((u64)paddr >> 32, port + PORT_CMD_ACTIVATE + 4);
irq_mask = (PORT_IRQ_COMPLETE | PORT_IRQ_ERROR) << PORT_IRQ_RAW_SHIFT;
- irq_stat = ata_wait_register(port + PORT_IRQ_STAT, irq_mask, 0x0,
+ irq_stat = ata_wait_register(ap, port + PORT_IRQ_STAT, irq_mask, 0x0,
10, timeout_msec);
writel(irq_mask, port + PORT_IRQ_STAT); /* clear IRQs */
@@ -719,9 +719,9 @@ static int sil24_hardreset(struct ata_link *link, unsigned int *class,
"state, performing PORT_RST\n");
writel(PORT_CS_PORT_RST, port + PORT_CTRL_STAT);
- msleep(10);
+ ata_msleep(ap, 10);
writel(PORT_CS_PORT_RST, port + PORT_CTRL_CLR);
- ata_wait_register(port + PORT_CTRL_STAT, PORT_CS_RDY, 0,
+ ata_wait_register(ap, port + PORT_CTRL_STAT, PORT_CS_RDY, 0,
10, 5000);
/* restore port configuration */
@@ -740,7 +740,7 @@ static int sil24_hardreset(struct ata_link *link, unsigned int *class,
tout_msec = 5000;
writel(PORT_CS_DEV_RST, port + PORT_CTRL_STAT);
- tmp = ata_wait_register(port + PORT_CTRL_STAT,
+ tmp = ata_wait_register(ap, port + PORT_CTRL_STAT,
PORT_CS_DEV_RST, PORT_CS_DEV_RST, 10,
tout_msec);
@@ -1253,7 +1253,7 @@ static void sil24_init_controller(struct ata_host *host)
tmp = readl(port + PORT_CTRL_STAT);
if (tmp & PORT_CS_PORT_RST) {
writel(PORT_CS_PORT_RST, port + PORT_CTRL_CLR);
- tmp = ata_wait_register(port + PORT_CTRL_STAT,
+ tmp = ata_wait_register(NULL, port + PORT_CTRL_STAT,
PORT_CS_PORT_RST,
PORT_CS_PORT_RST, 10, 100);
if (tmp & PORT_CS_PORT_RST)
diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c
index 4730c42a5ee5..c21589986c69 100644
--- a/drivers/ata/sata_via.c
+++ b/drivers/ata/sata_via.c
@@ -349,7 +349,7 @@ static int vt6420_prereset(struct ata_link *link, unsigned long deadline)
/* wait for phy to become ready, if necessary */
do {
- msleep(200);
+ ata_msleep(link->ap, 200);
svia_scr_read(link, SCR_STATUS, &sstatus);
if ((sstatus & 0xf) != 1)
break;
diff --git a/drivers/atm/Makefile b/drivers/atm/Makefile
index 62c3cc1075ae..c6c9ee9f5da2 100644
--- a/drivers/atm/Makefile
+++ b/drivers/atm/Makefile
@@ -2,7 +2,7 @@
# Makefile for the Linux network (ATM) device drivers.
#
-fore_200e-objs := fore200e.o
+fore_200e-y := fore200e.o
obj-$(CONFIG_ATM_ZATM) += zatm.o uPD98402.o
obj-$(CONFIG_ATM_NICSTAR) += nicstar.o
diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c
index 8717809787fb..5d86bb803e94 100644
--- a/drivers/atm/firestream.c
+++ b/drivers/atm/firestream.c
@@ -444,8 +444,8 @@ static inline void fs_kfree_skb (struct sk_buff * skb)
#define ROUND_NEAREST 3
/********** make rate (not quite as much fun as Horizon) **********/
-static unsigned int make_rate (unsigned int rate, int r,
- u16 * bits, unsigned int * actual)
+static int make_rate(unsigned int rate, int r,
+ u16 *bits, unsigned int *actual)
{
unsigned char exp = -1; /* hush gcc */
unsigned int man = -1; /* hush gcc */
diff --git a/drivers/atm/horizon.c b/drivers/atm/horizon.c
index 54720baa7363..a95790452a68 100644
--- a/drivers/atm/horizon.c
+++ b/drivers/atm/horizon.c
@@ -1645,10 +1645,8 @@ static int hrz_send (struct atm_vcc * atm_vcc, struct sk_buff * skb) {
unsigned short d = 0;
char * s = skb->data;
if (*s++ == 'D') {
- for (i = 0; i < 4; ++i) {
- d = (d<<4) | ((*s <= '9') ? (*s - '0') : (*s - 'a' + 10));
- ++s;
- }
+ for (i = 0; i < 4; ++i)
+ d = (d << 4) | hex_to_bin(*s++);
PRINTK (KERN_INFO, "debug bitmap is now %hx", debug = d);
}
}
diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c
index 1679cbf0c584..bce57328ddde 100644
--- a/drivers/atm/idt77252.c
+++ b/drivers/atm/idt77252.c
@@ -3152,7 +3152,7 @@ deinit_card(struct idt77252_dev *card)
}
-static int __devinit
+static void __devinit
init_sram(struct idt77252_dev *card)
{
int i;
@@ -3298,7 +3298,6 @@ init_sram(struct idt77252_dev *card)
SAR_REG_RXFD);
IPRINTK("%s: SRAM initialization complete.\n", card->name);
- return 0;
}
static int __devinit
@@ -3410,8 +3409,7 @@ init_card(struct atm_dev *dev)
writel(readl(SAR_REG_CFG) | conf, SAR_REG_CFG);
- if (init_sram(card) < 0)
- return -1;
+ init_sram(card);
/********************************************************************/
/* A L L O C R A M A N D S E T V A R I O U S T H I N G S */
diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c
index ee9ddeb53417..9309d4724e13 100644
--- a/drivers/atm/iphase.c
+++ b/drivers/atm/iphase.c
@@ -220,7 +220,7 @@ static u16 get_desc (IADEV *dev, struct ia_vcc *iavcc) {
while (!desc_num || (dev->desc_tbl[desc_num -1]).timestamp) {
dev->ffL.tcq_rd += 2;
if (dev->ffL.tcq_rd > dev->ffL.tcq_ed)
- dev->ffL.tcq_rd = dev->ffL.tcq_st;
+ dev->ffL.tcq_rd = dev->ffL.tcq_st;
if (dev->ffL.tcq_rd == dev->host_tcq_wr)
return 0xFFFF;
desc_num = *(u_short *)(dev->seg_ram + dev->ffL.tcq_rd);
@@ -3156,7 +3156,6 @@ static int __devinit ia_init_one(struct pci_dev *pdev,
{
struct atm_dev *dev;
IADEV *iadev;
- unsigned long flags;
int ret;
iadev = kzalloc(sizeof(*iadev), GFP_KERNEL);
@@ -3188,19 +3187,14 @@ static int __devinit ia_init_one(struct pci_dev *pdev,
ia_dev[iadev_count] = iadev;
_ia_dev[iadev_count] = dev;
iadev_count++;
- spin_lock_init(&iadev->misc_lock);
- /* First fixes first. I don't want to think about this now. */
- spin_lock_irqsave(&iadev->misc_lock, flags);
if (ia_init(dev) || ia_start(dev)) {
IF_INIT(printk("IA register failed!\n");)
iadev_count--;
ia_dev[iadev_count] = NULL;
_ia_dev[iadev_count] = NULL;
- spin_unlock_irqrestore(&iadev->misc_lock, flags);
ret = -EINVAL;
goto err_out_deregister_dev;
}
- spin_unlock_irqrestore(&iadev->misc_lock, flags);
IF_EVENT(printk("iadev_count = %d\n", iadev_count);)
iadev->next_board = ia_boards;
diff --git a/drivers/atm/iphase.h b/drivers/atm/iphase.h
index b2cd20f549cb..077735e0e04b 100644
--- a/drivers/atm/iphase.h
+++ b/drivers/atm/iphase.h
@@ -1022,7 +1022,7 @@ typedef struct iadev_t {
struct dle_q rx_dle_q;
struct free_desc_q *rx_free_desc_qhead;
struct sk_buff_head rx_dma_q;
- spinlock_t rx_lock, misc_lock;
+ spinlock_t rx_lock;
struct atm_vcc **rx_open; /* list of all open VCs */
u16 num_rx_desc, rx_buf_sz, rxing;
u32 rx_pkt_ram, rx_tmp_cnt;
diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c
index f916ddf63938..f46138ab38b6 100644
--- a/drivers/atm/solos-pci.c
+++ b/drivers/atm/solos-pci.c
@@ -444,6 +444,7 @@ static ssize_t console_show(struct device *dev, struct device_attribute *attr,
struct atm_dev *atmdev = container_of(dev, struct atm_dev, class_dev);
struct solos_card *card = atmdev->dev_data;
struct sk_buff *skb;
+ unsigned int len;
spin_lock(&card->cli_queue_lock);
skb = skb_dequeue(&card->cli_queue[SOLOS_CHAN(atmdev)]);
@@ -451,11 +452,12 @@ static ssize_t console_show(struct device *dev, struct device_attribute *attr,
if(skb == NULL)
return sprintf(buf, "No data.\n");
- memcpy(buf, skb->data, skb->len);
- dev_dbg(&card->dev->dev, "len: %d\n", skb->len);
+ len = skb->len;
+ memcpy(buf, skb->data, len);
+ dev_dbg(&card->dev->dev, "len: %d\n", len);
kfree_skb(skb);
- return skb->len;
+ return len;
}
static int send_command(struct solos_card *card, int dev, const char *buf, size_t size)
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index ef38aff737eb..fd96345bc35c 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -71,7 +71,6 @@ config PREVENT_FIRMWARE_BUILD
config FW_LOADER
tristate "Userspace firmware loading support" if EMBEDDED
- depends on HOTPLUG
default y
---help---
This option is provided for the case where no in-kernel-tree modules
diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index c12c7f2f2a6f..5f51c3b4451e 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -19,7 +19,5 @@ obj-$(CONFIG_MODULES) += module.o
endif
obj-$(CONFIG_SYS_HYPERVISOR) += hypervisor.o
-ifeq ($(CONFIG_DEBUG_DRIVER),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
+ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index eb1b7fa20dce..33c270a64db7 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -440,22 +440,6 @@ static void device_remove_attrs(struct bus_type *bus, struct device *dev)
}
}
-#ifdef CONFIG_SYSFS_DEPRECATED
-static int make_deprecated_bus_links(struct device *dev)
-{
- return sysfs_create_link(&dev->kobj,
- &dev->bus->p->subsys.kobj, "bus");
-}
-
-static void remove_deprecated_bus_links(struct device *dev)
-{
- sysfs_remove_link(&dev->kobj, "bus");
-}
-#else
-static inline int make_deprecated_bus_links(struct device *dev) { return 0; }
-static inline void remove_deprecated_bus_links(struct device *dev) { }
-#endif
-
/**
* bus_add_device - add device to bus
* @dev: device being added
@@ -482,15 +466,10 @@ int bus_add_device(struct device *dev)
&dev->bus->p->subsys.kobj, "subsystem");
if (error)
goto out_subsys;
- error = make_deprecated_bus_links(dev);
- if (error)
- goto out_deprecated;
klist_add_tail(&dev->p->knode_bus, &bus->p->klist_devices);
}
return 0;
-out_deprecated:
- sysfs_remove_link(&dev->kobj, "subsystem");
out_subsys:
sysfs_remove_link(&bus->p->devices_kset->kobj, dev_name(dev));
out_id:
@@ -530,7 +509,6 @@ void bus_remove_device(struct device *dev)
{
if (dev->bus) {
sysfs_remove_link(&dev->kobj, "subsystem");
- remove_deprecated_bus_links(dev);
sysfs_remove_link(&dev->bus->p->devices_kset->kobj,
dev_name(dev));
device_remove_attrs(dev->bus, dev);
diff --git a/drivers/base/class.c b/drivers/base/class.c
index 8e231d05b400..9c63a5687d69 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -184,9 +184,9 @@ int __class_register(struct class *cls, struct lock_class_key *key)
if (!cls->dev_kobj)
cls->dev_kobj = sysfs_dev_char_kobj;
-#if defined(CONFIG_SYSFS_DEPRECATED) && defined(CONFIG_BLOCK)
+#if defined(CONFIG_BLOCK)
/* let the block class directory show up in the root of sysfs */
- if (cls != &block_class)
+ if (!sysfs_deprecated || cls != &block_class)
cp->class_subsys.kobj.kset = class_kset;
#else
cp->class_subsys.kobj.kset = class_kset;
@@ -276,25 +276,6 @@ void class_destroy(struct class *cls)
class_unregister(cls);
}
-#ifdef CONFIG_SYSFS_DEPRECATED
-char *make_class_name(const char *name, struct kobject *kobj)
-{
- char *class_name;
- int size;
-
- size = strlen(name) + strlen(kobject_name(kobj)) + 2;
-
- class_name = kmalloc(size, GFP_KERNEL);
- if (!class_name)
- return NULL;
-
- strcpy(class_name, name);
- strcat(class_name, ":");
- strcat(class_name, kobject_name(kobj));
- return class_name;
-}
-#endif
-
/**
* class_dev_iter_init - initialize class device iterator
* @iter: class iterator to initialize
diff --git a/drivers/base/core.c b/drivers/base/core.c
index d1b2c9adc271..2cb49a93b1e6 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -26,6 +26,19 @@
#include "base.h"
#include "power/power.h"
+#ifdef CONFIG_SYSFS_DEPRECATED
+#ifdef CONFIG_SYSFS_DEPRECATED_V2
+long sysfs_deprecated = 1;
+#else
+long sysfs_deprecated = 0;
+#endif
+static __init int sysfs_deprecated_setup(char *arg)
+{
+ return strict_strtol(arg, 10, &sysfs_deprecated);
+}
+early_param("sysfs.deprecated", sysfs_deprecated_setup);
+#endif
+
int (*platform_notify)(struct device *dev) = NULL;
int (*platform_notify_remove)(struct device *dev) = NULL;
static struct kobject *dev_kobj;
@@ -203,37 +216,6 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj,
if (dev->driver)
add_uevent_var(env, "DRIVER=%s", dev->driver->name);
-#ifdef CONFIG_SYSFS_DEPRECATED
- if (dev->class) {
- struct device *parent = dev->parent;
-
- /* find first bus device in parent chain */
- while (parent && !parent->bus)
- parent = parent->parent;
- if (parent && parent->bus) {
- const char *path;
-
- path = kobject_get_path(&parent->kobj, GFP_KERNEL);
- if (path) {
- add_uevent_var(env, "PHYSDEVPATH=%s", path);
- kfree(path);
- }
-
- add_uevent_var(env, "PHYSDEVBUS=%s", parent->bus->name);
-
- if (parent->driver)
- add_uevent_var(env, "PHYSDEVDRIVER=%s",
- parent->driver->name);
- }
- } else if (dev->bus) {
- add_uevent_var(env, "PHYSDEVBUS=%s", dev->bus->name);
-
- if (dev->driver)
- add_uevent_var(env, "PHYSDEVDRIVER=%s",
- dev->driver->name);
- }
-#endif
-
/* have the bus specific function add its stuff */
if (dev->bus && dev->bus->uevent) {
retval = dev->bus->uevent(dev, env);
@@ -578,24 +560,6 @@ void device_initialize(struct device *dev)
set_dev_node(dev, -1);
}
-#ifdef CONFIG_SYSFS_DEPRECATED
-static struct kobject *get_device_parent(struct device *dev,
- struct device *parent)
-{
- /* class devices without a parent live in /sys/class/<classname>/ */
- if (dev->class && (!parent || parent->class != dev->class))
- return &dev->class->p->class_subsys.kobj;
- /* all other devices keep their parent */
- else if (parent)
- return &parent->kobj;
-
- return NULL;
-}
-
-static inline void cleanup_device_parent(struct device *dev) {}
-static inline void cleanup_glue_dir(struct device *dev,
- struct kobject *glue_dir) {}
-#else
static struct kobject *virtual_device_parent(struct device *dev)
{
static struct kobject *virtual_dir = NULL;
@@ -666,6 +630,15 @@ static struct kobject *get_device_parent(struct device *dev,
struct kobject *parent_kobj;
struct kobject *k;
+#ifdef CONFIG_BLOCK
+ /* block disks show up in /sys/block */
+ if (sysfs_deprecated && dev->class == &block_class) {
+ if (parent && parent->class == &block_class)
+ return &parent->kobj;
+ return &block_class.p->class_subsys.kobj;
+ }
+#endif
+
/*
* If we have no parent, we live in "virtual".
* Class-devices with a non class-device as parent, live
@@ -719,7 +692,6 @@ static void cleanup_device_parent(struct device *dev)
{
cleanup_glue_dir(dev, dev->kobj.parent);
}
-#endif
static void setup_parent(struct device *dev, struct device *parent)
{
@@ -742,70 +714,29 @@ static int device_add_class_symlinks(struct device *dev)
if (error)
goto out;
-#ifdef CONFIG_SYSFS_DEPRECATED
- /* stacked class devices need a symlink in the class directory */
- if (dev->kobj.parent != &dev->class->p->class_subsys.kobj &&
- device_is_not_partition(dev)) {
- error = sysfs_create_link(&dev->class->p->class_subsys.kobj,
- &dev->kobj, dev_name(dev));
- if (error)
- goto out_subsys;
- }
-
if (dev->parent && device_is_not_partition(dev)) {
- struct device *parent = dev->parent;
- char *class_name;
-
- /*
- * stacked class devices have the 'device' link
- * pointing to the bus device instead of the parent
- */
- while (parent->class && !parent->bus && parent->parent)
- parent = parent->parent;
-
- error = sysfs_create_link(&dev->kobj,
- &parent->kobj,
+ error = sysfs_create_link(&dev->kobj, &dev->parent->kobj,
"device");
if (error)
- goto out_busid;
-
- class_name = make_class_name(dev->class->name,
- &dev->kobj);
- if (class_name)
- error = sysfs_create_link(&dev->parent->kobj,
- &dev->kobj, class_name);
- kfree(class_name);
- if (error)
- goto out_device;
+ goto out_subsys;
}
- return 0;
-out_device:
- if (dev->parent && device_is_not_partition(dev))
- sysfs_remove_link(&dev->kobj, "device");
-out_busid:
- if (dev->kobj.parent != &dev->class->p->class_subsys.kobj &&
- device_is_not_partition(dev))
- sysfs_delete_link(&dev->class->p->class_subsys.kobj, &dev->kobj,
- dev_name(dev));
-#else
+#ifdef CONFIG_BLOCK
+ /* /sys/block has directories and does not need symlinks */
+ if (sysfs_deprecated && dev->class == &block_class)
+ return 0;
+#endif
+
/* link in the class directory pointing to the device */
error = sysfs_create_link(&dev->class->p->class_subsys.kobj,
&dev->kobj, dev_name(dev));
if (error)
- goto out_subsys;
+ goto out_device;
- if (dev->parent && device_is_not_partition(dev)) {
- error = sysfs_create_link(&dev->kobj, &dev->parent->kobj,
- "device");
- if (error)
- goto out_busid;
- }
return 0;
-out_busid:
- sysfs_delete_link(&dev->class->p->class_subsys.kobj, &dev->kobj, dev_name(dev));
-#endif
+out_device:
+ sysfs_remove_link(&dev->kobj, "device");
out_subsys:
sysfs_remove_link(&dev->kobj, "subsystem");
@@ -818,30 +749,14 @@ static void device_remove_class_symlinks(struct device *dev)
if (!dev->class)
return;
-#ifdef CONFIG_SYSFS_DEPRECATED
- if (dev->parent && device_is_not_partition(dev)) {
- char *class_name;
-
- class_name = make_class_name(dev->class->name, &dev->kobj);
- if (class_name) {
- sysfs_remove_link(&dev->parent->kobj, class_name);
- kfree(class_name);
- }
- sysfs_remove_link(&dev->kobj, "device");
- }
-
- if (dev->kobj.parent != &dev->class->p->class_subsys.kobj &&
- device_is_not_partition(dev))
- sysfs_delete_link(&dev->class->p->class_subsys.kobj, &dev->kobj,
- dev_name(dev));
-#else
if (dev->parent && device_is_not_partition(dev))
sysfs_remove_link(&dev->kobj, "device");
-
- sysfs_delete_link(&dev->class->p->class_subsys.kobj, &dev->kobj, dev_name(dev));
-#endif
-
sysfs_remove_link(&dev->kobj, "subsystem");
+#ifdef CONFIG_BLOCK
+ if (sysfs_deprecated && dev->class == &block_class)
+ return;
+#endif
+ sysfs_delete_link(&dev->class->p->class_subsys.kobj, &dev->kobj, dev_name(dev));
}
/**
@@ -1613,41 +1528,23 @@ int device_rename(struct device *dev, const char *new_name)
pr_debug("device: '%s': %s: renaming to '%s'\n", dev_name(dev),
__func__, new_name);
-#ifdef CONFIG_SYSFS_DEPRECATED
- if ((dev->class) && (dev->parent))
- old_class_name = make_class_name(dev->class->name, &dev->kobj);
-#endif
-
old_device_name = kstrdup(dev_name(dev), GFP_KERNEL);
if (!old_device_name) {
error = -ENOMEM;
goto out;
}
-#ifndef CONFIG_SYSFS_DEPRECATED
if (dev->class) {
error = sysfs_rename_link(&dev->class->p->class_subsys.kobj,
&dev->kobj, old_device_name, new_name);
if (error)
goto out;
}
-#endif
+
error = kobject_rename(&dev->kobj, new_name);
if (error)
goto out;
-#ifdef CONFIG_SYSFS_DEPRECATED
- if (old_class_name) {
- new_class_name = make_class_name(dev->class->name, &dev->kobj);
- if (new_class_name) {
- error = sysfs_rename_link(&dev->parent->kobj,
- &dev->kobj,
- old_class_name,
- new_class_name);
- }
- }
-#endif
-
out:
put_device(dev);
@@ -1664,40 +1561,13 @@ static int device_move_class_links(struct device *dev,
struct device *new_parent)
{
int error = 0;
-#ifdef CONFIG_SYSFS_DEPRECATED
- char *class_name;
- class_name = make_class_name(dev->class->name, &dev->kobj);
- if (!class_name) {
- error = -ENOMEM;
- goto out;
- }
- if (old_parent) {
- sysfs_remove_link(&dev->kobj, "device");
- sysfs_remove_link(&old_parent->kobj, class_name);
- }
- if (new_parent) {
- error = sysfs_create_link(&dev->kobj, &new_parent->kobj,
- "device");
- if (error)
- goto out;
- error = sysfs_create_link(&new_parent->kobj, &dev->kobj,
- class_name);
- if (error)
- sysfs_remove_link(&dev->kobj, "device");
- } else
- error = 0;
-out:
- kfree(class_name);
- return error;
-#else
if (old_parent)
sysfs_remove_link(&dev->kobj, "device");
if (new_parent)
error = sysfs_create_link(&dev->kobj, &new_parent->kobj,
"device");
return error;
-#endif
}
/**
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index 933442f40321..cafeaaf0428f 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -27,6 +27,8 @@
#include <asm/atomic.h>
#include <asm/uaccess.h>
+static DEFINE_MUTEX(mem_sysfs_mutex);
+
#define MEMORY_CLASS_NAME "memory"
static struct sysdev_class memory_sysdev_class = {
@@ -435,6 +437,45 @@ int __weak arch_get_memory_phys_device(unsigned long start_pfn)
return 0;
}
+struct memory_block *find_memory_block_hinted(struct mem_section *section,
+ struct memory_block *hint)
+{
+ struct kobject *kobj;
+ struct sys_device *sysdev;
+ struct memory_block *mem;
+ char name[sizeof(MEMORY_CLASS_NAME) + 9 + 1];
+
+ kobj = hint ? &hint->sysdev.kobj : NULL;
+
+ /*
+ * This only works because we know that section == sysdev->id
+ * slightly redundant with sysdev_register()
+ */
+ sprintf(&name[0], "%s%d", MEMORY_CLASS_NAME, __section_nr(section));
+
+ kobj = kset_find_obj_hinted(&memory_sysdev_class.kset, name, kobj);
+ if (!kobj)
+ return NULL;
+
+ sysdev = container_of(kobj, struct sys_device, kobj);
+ mem = container_of(sysdev, struct memory_block, sysdev);
+
+ return mem;
+}
+
+/*
+ * For now, we have a linear search to go find the appropriate
+ * memory_block corresponding to a particular phys_index. If
+ * this gets to be a real problem, we can always use a radix
+ * tree or something here.
+ *
+ * This could be made generic for all sysdev classes.
+ */
+struct memory_block *find_memory_block(struct mem_section *section)
+{
+ return find_memory_block_hinted(section, NULL);
+}
+
static int add_memory_block(int nid, struct mem_section *section,
unsigned long state, enum mem_add_context context)
{
@@ -445,8 +486,11 @@ static int add_memory_block(int nid, struct mem_section *section,
if (!mem)
return -ENOMEM;
+ mutex_lock(&mem_sysfs_mutex);
+
mem->phys_index = __section_nr(section);
mem->state = state;
+ mem->section_count++;
mutex_init(&mem->state_mutex);
start_pfn = section_nr_to_pfn(mem->phys_index);
mem->phys_device = arch_get_memory_phys_device(start_pfn);
@@ -465,53 +509,29 @@ static int add_memory_block(int nid, struct mem_section *section,
ret = register_mem_sect_under_node(mem, nid);
}
+ mutex_unlock(&mem_sysfs_mutex);
return ret;
}
-/*
- * For now, we have a linear search to go find the appropriate
- * memory_block corresponding to a particular phys_index. If
- * this gets to be a real problem, we can always use a radix
- * tree or something here.
- *
- * This could be made generic for all sysdev classes.
- */
-struct memory_block *find_memory_block(struct mem_section *section)
-{
- struct kobject *kobj;
- struct sys_device *sysdev;
- struct memory_block *mem;
- char name[sizeof(MEMORY_CLASS_NAME) + 9 + 1];
-
- /*
- * This only works because we know that section == sysdev->id
- * slightly redundant with sysdev_register()
- */
- sprintf(&name[0], "%s%d", MEMORY_CLASS_NAME, __section_nr(section));
-
- kobj = kset_find_obj(&memory_sysdev_class.kset, name);
- if (!kobj)
- return NULL;
-
- sysdev = container_of(kobj, struct sys_device, kobj);
- mem = container_of(sysdev, struct memory_block, sysdev);
-
- return mem;
-}
-
int remove_memory_block(unsigned long node_id, struct mem_section *section,
int phys_device)
{
struct memory_block *mem;
+ mutex_lock(&mem_sysfs_mutex);
mem = find_memory_block(section);
- unregister_mem_sect_under_nodes(mem);
- mem_remove_simple_file(mem, phys_index);
- mem_remove_simple_file(mem, state);
- mem_remove_simple_file(mem, phys_device);
- mem_remove_simple_file(mem, removable);
- unregister_memory(mem, section);
+ mem->section_count--;
+ if (mem->section_count == 0) {
+ unregister_mem_sect_under_nodes(mem);
+ mem_remove_simple_file(mem, phys_index);
+ mem_remove_simple_file(mem, state);
+ mem_remove_simple_file(mem, phys_device);
+ mem_remove_simple_file(mem, removable);
+ unregister_memory(mem, section);
+ }
+
+ mutex_unlock(&mem_sysfs_mutex);
return 0;
}
diff --git a/drivers/base/node.c b/drivers/base/node.c
index 2872e86837b2..ee53558b452f 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -409,25 +409,27 @@ static int link_mem_sections(int nid)
unsigned long start_pfn = NODE_DATA(nid)->node_start_pfn;
unsigned long end_pfn = start_pfn + NODE_DATA(nid)->node_spanned_pages;
unsigned long pfn;
+ struct memory_block *mem_blk = NULL;
int err = 0;
for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
unsigned long section_nr = pfn_to_section_nr(pfn);
struct mem_section *mem_sect;
- struct memory_block *mem_blk;
int ret;
if (!present_section_nr(section_nr))
continue;
mem_sect = __nr_to_section(section_nr);
- mem_blk = find_memory_block(mem_sect);
+ mem_blk = find_memory_block_hinted(mem_sect, mem_blk);
ret = register_mem_sect_under_node(mem_blk, nid);
if (!err)
err = ret;
/* discard ref obtained in find_memory_block() */
- kobject_put(&mem_blk->sysdev.kobj);
}
+
+ if (mem_blk)
+ kobject_put(&mem_blk->sysdev.kobj);
return err;
}
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index c6c933f58102..3966e62ad019 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -192,6 +192,9 @@ int platform_device_add_resources(struct platform_device *pdev,
{
struct resource *r;
+ if (!res)
+ return 0;
+
r = kmemdup(res, sizeof(struct resource) * num, GFP_KERNEL);
if (r) {
pdev->resource = r;
@@ -215,8 +218,12 @@ EXPORT_SYMBOL_GPL(platform_device_add_resources);
int platform_device_add_data(struct platform_device *pdev, const void *data,
size_t size)
{
- void *d = kmemdup(data, size, GFP_KERNEL);
+ void *d;
+
+ if (!data)
+ return 0;
+ d = kmemdup(data, size, GFP_KERNEL);
if (d) {
pdev->dev.platform_data = d;
return 0;
@@ -373,17 +380,13 @@ struct platform_device *__init_or_module platform_device_register_resndata(
pdev->dev.parent = parent;
- if (res) {
- ret = platform_device_add_resources(pdev, res, num);
- if (ret)
- goto err;
- }
+ ret = platform_device_add_resources(pdev, res, num);
+ if (ret)
+ goto err;
- if (data) {
- ret = platform_device_add_data(pdev, data, size);
- if (ret)
- goto err;
- }
+ ret = platform_device_add_data(pdev, data, size);
+ if (ret)
+ goto err;
ret = platform_device_add(pdev);
if (ret) {
@@ -488,12 +491,12 @@ int __init_or_module platform_driver_probe(struct platform_driver *drv,
* if the probe was successful, and make sure any forced probes of
* new devices fail.
*/
- spin_lock(&platform_bus_type.p->klist_drivers.k_lock);
+ spin_lock(&drv->driver.bus->p->klist_drivers.k_lock);
drv->probe = NULL;
if (code == 0 && list_empty(&drv->driver.p->klist_devices.k_list))
retval = -ENODEV;
drv->driver.probe = platform_drv_probe_fail;
- spin_unlock(&platform_bus_type.p->klist_drivers.k_lock);
+ spin_unlock(&drv->driver.bus->p->klist_drivers.k_lock);
if (code != retval)
platform_driver_unregister(drv);
@@ -530,17 +533,13 @@ struct platform_device * __init_or_module platform_create_bundle(
goto err_out;
}
- if (res) {
- error = platform_device_add_resources(pdev, res, n_res);
- if (error)
- goto err_pdev_put;
- }
+ error = platform_device_add_resources(pdev, res, n_res);
+ if (error)
+ goto err_pdev_put;
- if (data) {
- error = platform_device_add_data(pdev, data, size);
- if (error)
- goto err_pdev_put;
- }
+ error = platform_device_add_data(pdev, data, size);
+ if (error)
+ goto err_pdev_put;
error = platform_device_add(pdev);
if (error)
@@ -976,6 +975,41 @@ struct bus_type platform_bus_type = {
};
EXPORT_SYMBOL_GPL(platform_bus_type);
+/**
+ * platform_bus_get_pm_ops() - return pointer to busses dev_pm_ops
+ *
+ * This function can be used by platform code to get the current
+ * set of dev_pm_ops functions used by the platform_bus_type.
+ */
+const struct dev_pm_ops * __init platform_bus_get_pm_ops(void)
+{
+ return platform_bus_type.pm;
+}
+
+/**
+ * platform_bus_set_pm_ops() - update dev_pm_ops for the platform_bus_type
+ *
+ * @pm: pointer to new dev_pm_ops struct to be used for platform_bus_type
+ *
+ * Platform code can override the dev_pm_ops methods of
+ * platform_bus_type by using this function. It is expected that
+ * platform code will first do a platform_bus_get_pm_ops(), then
+ * kmemdup it, then customize selected methods and pass a pointer to
+ * the new struct dev_pm_ops to this function.
+ *
+ * Since platform-specific code is customizing methods for *all*
+ * devices (not just platform-specific devices) it is expected that
+ * any custom overrides of these functions will keep existing behavior
+ * and simply extend it. For example, any customization of the
+ * runtime PM methods should continue to call the pm_generic_*
+ * functions as the default ones do in addition to the
+ * platform-specific behavior.
+ */
+void __init platform_bus_set_pm_ops(const struct dev_pm_ops *pm)
+{
+ platform_bus_type.pm = pm;
+}
+
int __init platform_bus_init(void)
{
int error;
diff --git a/drivers/base/power/Makefile b/drivers/base/power/Makefile
index cbccf9a3cee4..abe46edfe5b4 100644
--- a/drivers/base/power/Makefile
+++ b/drivers/base/power/Makefile
@@ -3,6 +3,7 @@ obj-$(CONFIG_PM_SLEEP) += main.o wakeup.o
obj-$(CONFIG_PM_RUNTIME) += runtime.o
obj-$(CONFIG_PM_OPS) += generic_ops.o
obj-$(CONFIG_PM_TRACE_RTC) += trace.o
+obj-$(CONFIG_PM_OPP) += opp.o
ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG
ccflags-$(CONFIG_PM_VERBOSE) += -DDEBUG
diff --git a/drivers/base/power/generic_ops.c b/drivers/base/power/generic_ops.c
index 4b29d4981253..81f2c84697f4 100644
--- a/drivers/base/power/generic_ops.c
+++ b/drivers/base/power/generic_ops.c
@@ -46,7 +46,7 @@ int pm_generic_runtime_suspend(struct device *dev)
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
int ret;
- ret = pm && pm->runtime_suspend ? pm->runtime_suspend(dev) : -EINVAL;
+ ret = pm && pm->runtime_suspend ? pm->runtime_suspend(dev) : 0;
return ret;
}
@@ -65,7 +65,7 @@ int pm_generic_runtime_resume(struct device *dev)
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
int ret;
- ret = pm && pm->runtime_resume ? pm->runtime_resume(dev) : -EINVAL;
+ ret = pm && pm->runtime_resume ? pm->runtime_resume(dev) : 0;
return ret;
}
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 276d5a701dc3..31b526661ec4 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -51,6 +51,8 @@ static pm_message_t pm_transition;
*/
static bool transition_started;
+static int async_error;
+
/**
* device_pm_init - Initialize the PM-related part of a device object.
* @dev: Device object being initialized.
@@ -60,7 +62,8 @@ void device_pm_init(struct device *dev)
dev->power.status = DPM_ON;
init_completion(&dev->power.completion);
complete_all(&dev->power.completion);
- dev->power.wakeup_count = 0;
+ dev->power.wakeup = NULL;
+ spin_lock_init(&dev->power.lock);
pm_runtime_init(dev);
}
@@ -120,6 +123,7 @@ void device_pm_remove(struct device *dev)
mutex_lock(&dpm_list_mtx);
list_del_init(&dev->power.entry);
mutex_unlock(&dpm_list_mtx);
+ device_wakeup_disable(dev);
pm_runtime_remove(dev);
}
@@ -407,7 +411,7 @@ static void pm_dev_err(struct device *dev, pm_message_t state, char *info,
static void dpm_show_time(ktime_t starttime, pm_message_t state, char *info)
{
ktime_t calltime;
- s64 usecs64;
+ u64 usecs64;
int usecs;
calltime = ktime_get();
@@ -600,6 +604,7 @@ static void dpm_resume(pm_message_t state)
INIT_LIST_HEAD(&list);
mutex_lock(&dpm_list_mtx);
pm_transition = state;
+ async_error = 0;
list_for_each_entry(dev, &dpm_list, power.entry) {
if (dev->power.status < DPM_OFF)
@@ -829,8 +834,6 @@ static int legacy_suspend(struct device *dev, pm_message_t state,
return error;
}
-static int async_error;
-
/**
* device_suspend - Execute "suspend" callbacks for given device.
* @dev: Device to handle.
@@ -885,6 +888,9 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
device_unlock(dev);
complete_all(&dev->power.completion);
+ if (error)
+ async_error = error;
+
return error;
}
@@ -894,10 +900,8 @@ static void async_suspend(void *data, async_cookie_t cookie)
int error;
error = __device_suspend(dev, pm_transition, true);
- if (error) {
+ if (error)
pm_dev_err(dev, pm_transition, " async", error);
- async_error = error;
- }
put_device(dev);
}
@@ -1085,8 +1089,9 @@ EXPORT_SYMBOL_GPL(__suspend_report_result);
* @dev: Device to wait for.
* @subordinate: Device that needs to wait for @dev.
*/
-void device_pm_wait_for_dev(struct device *subordinate, struct device *dev)
+int device_pm_wait_for_dev(struct device *subordinate, struct device *dev)
{
dpm_wait(dev, subordinate->power.async_suspend);
+ return async_error;
}
EXPORT_SYMBOL_GPL(device_pm_wait_for_dev);
diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
new file mode 100644
index 000000000000..2bb9b4cf59d7
--- /dev/null
+++ b/drivers/base/power/opp.c
@@ -0,0 +1,628 @@
+/*
+ * Generic OPP Interface
+ *
+ * Copyright (C) 2009-2010 Texas Instruments Incorporated.
+ * Nishanth Menon
+ * Romit Dasgupta
+ * Kevin Hilman
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/cpufreq.h>
+#include <linux/list.h>
+#include <linux/rculist.h>
+#include <linux/rcupdate.h>
+#include <linux/opp.h>
+
+/*
+ * Internal data structure organization with the OPP layer library is as
+ * follows:
+ * dev_opp_list (root)
+ * |- device 1 (represents voltage domain 1)
+ * | |- opp 1 (availability, freq, voltage)
+ * | |- opp 2 ..
+ * ... ...
+ * | `- opp n ..
+ * |- device 2 (represents the next voltage domain)
+ * ...
+ * `- device m (represents mth voltage domain)
+ * device 1, 2.. are represented by dev_opp structure while each opp
+ * is represented by the opp structure.
+ */
+
+/**
+ * struct opp - Generic OPP description structure
+ * @node: opp list node. The nodes are maintained throughout the lifetime
+ * of boot. It is expected only an optimal set of OPPs are
+ * added to the library by the SoC framework.
+ * RCU usage: opp list is traversed with RCU locks. node
+ * modification is possible realtime, hence the modifications
+ * are protected by the dev_opp_list_lock for integrity.
+ * IMPORTANT: the opp nodes should be maintained in increasing
+ * order.
+ * @available: true/false - marks if this OPP as available or not
+ * @rate: Frequency in hertz
+ * @u_volt: Nominal voltage in microvolts corresponding to this OPP
+ * @dev_opp: points back to the device_opp struct this opp belongs to
+ *
+ * This structure stores the OPP information for a given device.
+ */
+struct opp {
+ struct list_head node;
+
+ bool available;
+ unsigned long rate;
+ unsigned long u_volt;
+
+ struct device_opp *dev_opp;
+};
+
+/**
+ * struct device_opp - Device opp structure
+ * @node: list node - contains the devices with OPPs that
+ * have been registered. Nodes once added are not modified in this
+ * list.
+ * RCU usage: nodes are not modified in the list of device_opp,
+ * however addition is possible and is secured by dev_opp_list_lock
+ * @dev: device pointer
+ * @opp_list: list of opps
+ *
+ * This is an internal data structure maintaining the link to opps attached to
+ * a device. This structure is not meant to be shared to users as it is
+ * meant for book keeping and private to OPP library
+ */
+struct device_opp {
+ struct list_head node;
+
+ struct device *dev;
+ struct list_head opp_list;
+};
+
+/*
+ * The root of the list of all devices. All device_opp structures branch off
+ * from here, with each device_opp containing the list of opp it supports in
+ * various states of availability.
+ */
+static LIST_HEAD(dev_opp_list);
+/* Lock to allow exclusive modification to the device and opp lists */
+static DEFINE_MUTEX(dev_opp_list_lock);
+
+/**
+ * find_device_opp() - find device_opp struct using device pointer
+ * @dev: device pointer used to lookup device OPPs
+ *
+ * Search list of device OPPs for one containing matching device. Does a RCU
+ * reader operation to grab the pointer needed.
+ *
+ * Returns pointer to 'struct device_opp' if found, otherwise -ENODEV or
+ * -EINVAL based on type of error.
+ *
+ * Locking: This function must be called under rcu_read_lock(). device_opp
+ * is a RCU protected pointer. This means that device_opp is valid as long
+ * as we are under RCU lock.
+ */
+static struct device_opp *find_device_opp(struct device *dev)
+{
+ struct device_opp *tmp_dev_opp, *dev_opp = ERR_PTR(-ENODEV);
+
+ if (unlikely(IS_ERR_OR_NULL(dev))) {
+ pr_err("%s: Invalid parameters\n", __func__);
+ return ERR_PTR(-EINVAL);
+ }
+
+ list_for_each_entry_rcu(tmp_dev_opp, &dev_opp_list, node) {
+ if (tmp_dev_opp->dev == dev) {
+ dev_opp = tmp_dev_opp;
+ break;
+ }
+ }
+
+ return dev_opp;
+}
+
+/**
+ * opp_get_voltage() - Gets the voltage corresponding to an available opp
+ * @opp: opp for which voltage has to be returned for
+ *
+ * Return voltage in micro volt corresponding to the opp, else
+ * return 0
+ *
+ * Locking: This function must be called under rcu_read_lock(). opp is a rcu
+ * protected pointer. This means that opp which could have been fetched by
+ * opp_find_freq_{exact,ceil,floor} functions is valid as long as we are
+ * under RCU lock. The pointer returned by the opp_find_freq family must be
+ * used in the same section as the usage of this function with the pointer
+ * prior to unlocking with rcu_read_unlock() to maintain the integrity of the
+ * pointer.
+ */
+unsigned long opp_get_voltage(struct opp *opp)
+{
+ struct opp *tmp_opp;
+ unsigned long v = 0;
+
+ tmp_opp = rcu_dereference(opp);
+ if (unlikely(IS_ERR_OR_NULL(tmp_opp)) || !tmp_opp->available)
+ pr_err("%s: Invalid parameters\n", __func__);
+ else
+ v = tmp_opp->u_volt;
+
+ return v;
+}
+
+/**
+ * opp_get_freq() - Gets the frequency corresponding to an available opp
+ * @opp: opp for which frequency has to be returned for
+ *
+ * Return frequency in hertz corresponding to the opp, else
+ * return 0
+ *
+ * Locking: This function must be called under rcu_read_lock(). opp is a rcu
+ * protected pointer. This means that opp which could have been fetched by
+ * opp_find_freq_{exact,ceil,floor} functions is valid as long as we are
+ * under RCU lock. The pointer returned by the opp_find_freq family must be
+ * used in the same section as the usage of this function with the pointer
+ * prior to unlocking with rcu_read_unlock() to maintain the integrity of the
+ * pointer.
+ */
+unsigned long opp_get_freq(struct opp *opp)
+{
+ struct opp *tmp_opp;
+ unsigned long f = 0;
+
+ tmp_opp = rcu_dereference(opp);
+ if (unlikely(IS_ERR_OR_NULL(tmp_opp)) || !tmp_opp->available)
+ pr_err("%s: Invalid parameters\n", __func__);
+ else
+ f = tmp_opp->rate;
+
+ return f;
+}
+
+/**
+ * opp_get_opp_count() - Get number of opps available in the opp list
+ * @dev: device for which we do this operation
+ *
+ * This function returns the number of available opps if there are any,
+ * else returns 0 if none or the corresponding error value.
+ *
+ * Locking: This function must be called under rcu_read_lock(). This function
+ * internally references two RCU protected structures: device_opp and opp which
+ * are safe as long as we are under a common RCU locked section.
+ */
+int opp_get_opp_count(struct device *dev)
+{
+ struct device_opp *dev_opp;
+ struct opp *temp_opp;
+ int count = 0;
+
+ dev_opp = find_device_opp(dev);
+ if (IS_ERR(dev_opp)) {
+ int r = PTR_ERR(dev_opp);
+ dev_err(dev, "%s: device OPP not found (%d)\n", __func__, r);
+ return r;
+ }
+
+ list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) {
+ if (temp_opp->available)
+ count++;
+ }
+
+ return count;
+}
+
+/**
+ * opp_find_freq_exact() - search for an exact frequency
+ * @dev: device for which we do this operation
+ * @freq: frequency to search for
+ * @is_available: true/false - match for available opp
+ *
+ * Searches for exact match in the opp list and returns pointer to the matching
+ * opp if found, else returns ERR_PTR in case of error and should be handled
+ * using IS_ERR.
+ *
+ * Note: available is a modifier for the search. if available=true, then the
+ * match is for exact matching frequency and is available in the stored OPP
+ * table. if false, the match is for exact frequency which is not available.
+ *
+ * This provides a mechanism to enable an opp which is not available currently
+ * or the opposite as well.
+ *
+ * Locking: This function must be called under rcu_read_lock(). opp is a rcu
+ * protected pointer. The reason for the same is that the opp pointer which is
+ * returned will remain valid for use with opp_get_{voltage, freq} only while
+ * under the locked area. The pointer returned must be used prior to unlocking
+ * with rcu_read_unlock() to maintain the integrity of the pointer.
+ */
+struct opp *opp_find_freq_exact(struct device *dev, unsigned long freq,
+ bool available)
+{
+ struct device_opp *dev_opp;
+ struct opp *temp_opp, *opp = ERR_PTR(-ENODEV);
+
+ dev_opp = find_device_opp(dev);
+ if (IS_ERR(dev_opp)) {
+ int r = PTR_ERR(dev_opp);
+ dev_err(dev, "%s: device OPP not found (%d)\n", __func__, r);
+ return ERR_PTR(r);
+ }
+
+ list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) {
+ if (temp_opp->available == available &&
+ temp_opp->rate == freq) {
+ opp = temp_opp;
+ break;
+ }
+ }
+
+ return opp;
+}
+
+/**
+ * opp_find_freq_ceil() - Search for an rounded ceil freq
+ * @dev: device for which we do this operation
+ * @freq: Start frequency
+ *
+ * Search for the matching ceil *available* OPP from a starting freq
+ * for a device.
+ *
+ * Returns matching *opp and refreshes *freq accordingly, else returns
+ * ERR_PTR in case of error and should be handled using IS_ERR.
+ *
+ * Locking: This function must be called under rcu_read_lock(). opp is a rcu
+ * protected pointer. The reason for the same is that the opp pointer which is
+ * returned will remain valid for use with opp_get_{voltage, freq} only while
+ * under the locked area. The pointer returned must be used prior to unlocking
+ * with rcu_read_unlock() to maintain the integrity of the pointer.
+ */
+struct opp *opp_find_freq_ceil(struct device *dev, unsigned long *freq)
+{
+ struct device_opp *dev_opp;
+ struct opp *temp_opp, *opp = ERR_PTR(-ENODEV);
+
+ if (!dev || !freq) {
+ dev_err(dev, "%s: Invalid argument freq=%p\n", __func__, freq);
+ return ERR_PTR(-EINVAL);
+ }
+
+ dev_opp = find_device_opp(dev);
+ if (IS_ERR(dev_opp))
+ return opp;
+
+ list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) {
+ if (temp_opp->available && temp_opp->rate >= *freq) {
+ opp = temp_opp;
+ *freq = opp->rate;
+ break;
+ }
+ }
+
+ return opp;
+}
+
+/**
+ * opp_find_freq_floor() - Search for a rounded floor freq
+ * @dev: device for which we do this operation
+ * @freq: Start frequency
+ *
+ * Search for the matching floor *available* OPP from a starting freq
+ * for a device.
+ *
+ * Returns matching *opp and refreshes *freq accordingly, else returns
+ * ERR_PTR in case of error and should be handled using IS_ERR.
+ *
+ * Locking: This function must be called under rcu_read_lock(). opp is a rcu
+ * protected pointer. The reason for the same is that the opp pointer which is
+ * returned will remain valid for use with opp_get_{voltage, freq} only while
+ * under the locked area. The pointer returned must be used prior to unlocking
+ * with rcu_read_unlock() to maintain the integrity of the pointer.
+ */
+struct opp *opp_find_freq_floor(struct device *dev, unsigned long *freq)
+{
+ struct device_opp *dev_opp;
+ struct opp *temp_opp, *opp = ERR_PTR(-ENODEV);
+
+ if (!dev || !freq) {
+ dev_err(dev, "%s: Invalid argument freq=%p\n", __func__, freq);
+ return ERR_PTR(-EINVAL);
+ }
+
+ dev_opp = find_device_opp(dev);
+ if (IS_ERR(dev_opp))
+ return opp;
+
+ list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) {
+ if (temp_opp->available) {
+ /* go to the next node, before choosing prev */
+ if (temp_opp->rate > *freq)
+ break;
+ else
+ opp = temp_opp;
+ }
+ }
+ if (!IS_ERR(opp))
+ *freq = opp->rate;
+
+ return opp;
+}
+
+/**
+ * opp_add() - Add an OPP table from a table definitions
+ * @dev: device for which we do this operation
+ * @freq: Frequency in Hz for this OPP
+ * @u_volt: Voltage in uVolts for this OPP
+ *
+ * This function adds an opp definition to the opp list and returns status.
+ * The opp is made available by default and it can be controlled using
+ * opp_enable/disable functions.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks
+ * to keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex cannot be locked.
+ */
+int opp_add(struct device *dev, unsigned long freq, unsigned long u_volt)
+{
+ struct device_opp *dev_opp = NULL;
+ struct opp *opp, *new_opp;
+ struct list_head *head;
+
+ /* allocate new OPP node */
+ new_opp = kzalloc(sizeof(struct opp), GFP_KERNEL);
+ if (!new_opp) {
+ dev_warn(dev, "%s: Unable to create new OPP node\n", __func__);
+ return -ENOMEM;
+ }
+
+ /* Hold our list modification lock here */
+ mutex_lock(&dev_opp_list_lock);
+
+ /* Check for existing list for 'dev' */
+ dev_opp = find_device_opp(dev);
+ if (IS_ERR(dev_opp)) {
+ /*
+ * Allocate a new device OPP table. In the infrequent case
+ * where a new device is needed to be added, we pay this
+ * penalty.
+ */
+ dev_opp = kzalloc(sizeof(struct device_opp), GFP_KERNEL);
+ if (!dev_opp) {
+ mutex_unlock(&dev_opp_list_lock);
+ kfree(new_opp);
+ dev_warn(dev,
+ "%s: Unable to create device OPP structure\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ dev_opp->dev = dev;
+ INIT_LIST_HEAD(&dev_opp->opp_list);
+
+ /* Secure the device list modification */
+ list_add_rcu(&dev_opp->node, &dev_opp_list);
+ }
+
+ /* populate the opp table */
+ new_opp->dev_opp = dev_opp;
+ new_opp->rate = freq;
+ new_opp->u_volt = u_volt;
+ new_opp->available = true;
+
+ /* Insert new OPP in order of increasing frequency */
+ head = &dev_opp->opp_list;
+ list_for_each_entry_rcu(opp, &dev_opp->opp_list, node) {
+ if (new_opp->rate < opp->rate)
+ break;
+ else
+ head = &opp->node;
+ }
+
+ list_add_rcu(&new_opp->node, head);
+ mutex_unlock(&dev_opp_list_lock);
+
+ return 0;
+}
+
+/**
+ * opp_set_availability() - helper to set the availability of an opp
+ * @dev: device for which we do this operation
+ * @freq: OPP frequency to modify availability
+ * @availability_req: availability status requested for this opp
+ *
+ * Set the availability of an OPP with an RCU operation, opp_{enable,disable}
+ * share a common logic which is isolated here.
+ *
+ * Returns -EINVAL for bad pointers, -ENOMEM if no memory available for the
+ * copy operation, returns 0 if no modifcation was done OR modification was
+ * successful.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks to
+ * keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex locking or synchronize_rcu() blocking calls cannot be used.
+ */
+static int opp_set_availability(struct device *dev, unsigned long freq,
+ bool availability_req)
+{
+ struct device_opp *tmp_dev_opp, *dev_opp = NULL;
+ struct opp *new_opp, *tmp_opp, *opp = ERR_PTR(-ENODEV);
+ int r = 0;
+
+ /* keep the node allocated */
+ new_opp = kmalloc(sizeof(struct opp), GFP_KERNEL);
+ if (!new_opp) {
+ dev_warn(dev, "%s: Unable to create OPP\n", __func__);
+ return -ENOMEM;
+ }
+
+ mutex_lock(&dev_opp_list_lock);
+
+ /* Find the device_opp */
+ list_for_each_entry(tmp_dev_opp, &dev_opp_list, node) {
+ if (dev == tmp_dev_opp->dev) {
+ dev_opp = tmp_dev_opp;
+ break;
+ }
+ }
+ if (IS_ERR(dev_opp)) {
+ r = PTR_ERR(dev_opp);
+ dev_warn(dev, "%s: Device OPP not found (%d)\n", __func__, r);
+ goto unlock;
+ }
+
+ /* Do we have the frequency? */
+ list_for_each_entry(tmp_opp, &dev_opp->opp_list, node) {
+ if (tmp_opp->rate == freq) {
+ opp = tmp_opp;
+ break;
+ }
+ }
+ if (IS_ERR(opp)) {
+ r = PTR_ERR(opp);
+ goto unlock;
+ }
+
+ /* Is update really needed? */
+ if (opp->available == availability_req)
+ goto unlock;
+ /* copy the old data over */
+ *new_opp = *opp;
+
+ /* plug in new node */
+ new_opp->available = availability_req;
+
+ list_replace_rcu(&opp->node, &new_opp->node);
+ mutex_unlock(&dev_opp_list_lock);
+ synchronize_rcu();
+
+ /* clean up old opp */
+ new_opp = opp;
+ goto out;
+
+unlock:
+ mutex_unlock(&dev_opp_list_lock);
+out:
+ kfree(new_opp);
+ return r;
+}
+
+/**
+ * opp_enable() - Enable a specific OPP
+ * @dev: device for which we do this operation
+ * @freq: OPP frequency to enable
+ *
+ * Enables a provided opp. If the operation is valid, this returns 0, else the
+ * corresponding error value. It is meant to be used for users an OPP available
+ * after being temporarily made unavailable with opp_disable.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function indirectly uses RCU and mutex locks to keep the
+ * integrity of the internal data structures. Callers should ensure that
+ * this function is *NOT* called under RCU protection or in contexts where
+ * mutex locking or synchronize_rcu() blocking calls cannot be used.
+ */
+int opp_enable(struct device *dev, unsigned long freq)
+{
+ return opp_set_availability(dev, freq, true);
+}
+
+/**
+ * opp_disable() - Disable a specific OPP
+ * @dev: device for which we do this operation
+ * @freq: OPP frequency to disable
+ *
+ * Disables a provided opp. If the operation is valid, this returns
+ * 0, else the corresponding error value. It is meant to be a temporary
+ * control by users to make this OPP not available until the circumstances are
+ * right to make it available again (with a call to opp_enable).
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function indirectly uses RCU and mutex locks to keep the
+ * integrity of the internal data structures. Callers should ensure that
+ * this function is *NOT* called under RCU protection or in contexts where
+ * mutex locking or synchronize_rcu() blocking calls cannot be used.
+ */
+int opp_disable(struct device *dev, unsigned long freq)
+{
+ return opp_set_availability(dev, freq, false);
+}
+
+#ifdef CONFIG_CPU_FREQ
+/**
+ * opp_init_cpufreq_table() - create a cpufreq table for a device
+ * @dev: device for which we do this operation
+ * @table: Cpufreq table returned back to caller
+ *
+ * Generate a cpufreq table for a provided device- this assumes that the
+ * opp list is already initialized and ready for usage.
+ *
+ * This function allocates required memory for the cpufreq table. It is
+ * expected that the caller does the required maintenance such as freeing
+ * the table as required.
+ *
+ * Returns -EINVAL for bad pointers, -ENODEV if the device is not found, -ENOMEM
+ * if no memory available for the operation (table is not populated), returns 0
+ * if successful and table is populated.
+ *
+ * WARNING: It is important for the callers to ensure refreshing their copy of
+ * the table if any of the mentioned functions have been invoked in the interim.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * To simplify the logic, we pretend we are updater and hold relevant mutex here
+ * Callers should ensure that this function is *NOT* called under RCU protection
+ * or in contexts where mutex locking cannot be used.
+ */
+int opp_init_cpufreq_table(struct device *dev,
+ struct cpufreq_frequency_table **table)
+{
+ struct device_opp *dev_opp;
+ struct opp *opp;
+ struct cpufreq_frequency_table *freq_table;
+ int i = 0;
+
+ /* Pretend as if I am an updater */
+ mutex_lock(&dev_opp_list_lock);
+
+ dev_opp = find_device_opp(dev);
+ if (IS_ERR(dev_opp)) {
+ int r = PTR_ERR(dev_opp);
+ mutex_unlock(&dev_opp_list_lock);
+ dev_err(dev, "%s: Device OPP not found (%d)\n", __func__, r);
+ return r;
+ }
+
+ freq_table = kzalloc(sizeof(struct cpufreq_frequency_table) *
+ (opp_get_opp_count(dev) + 1), GFP_KERNEL);
+ if (!freq_table) {
+ mutex_unlock(&dev_opp_list_lock);
+ dev_warn(dev, "%s: Unable to allocate frequency table\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ list_for_each_entry(opp, &dev_opp->opp_list, node) {
+ if (opp->available) {
+ freq_table[i].index = i;
+ freq_table[i].frequency = opp->rate / 1000;
+ i++;
+ }
+ }
+ mutex_unlock(&dev_opp_list_lock);
+
+ freq_table[i].index = i;
+ freq_table[i].frequency = CPUFREQ_TABLE_END;
+
+ *table = &freq_table[0];
+
+ return 0;
+}
+#endif /* CONFIG_CPU_FREQ */
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
index c0bd03c83b9c..698dde742587 100644
--- a/drivers/base/power/power.h
+++ b/drivers/base/power/power.h
@@ -34,6 +34,7 @@ extern void device_pm_move_last(struct device *);
static inline void device_pm_init(struct device *dev)
{
+ spin_lock_init(&dev->power.lock);
pm_runtime_init(dev);
}
@@ -59,6 +60,7 @@ static inline void device_pm_move_last(struct device *dev) {}
extern int dpm_sysfs_add(struct device *);
extern void dpm_sysfs_remove(struct device *);
+extern void rpm_sysfs_remove(struct device *);
#else /* CONFIG_PM */
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index b78c401ffa73..1dd8676d7f55 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -2,17 +2,55 @@
* drivers/base/power/runtime.c - Helper functions for device run-time PM
*
* Copyright (c) 2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
+ * Copyright (C) 2010 Alan Stern <stern@rowland.harvard.edu>
*
* This file is released under the GPLv2.
*/
#include <linux/sched.h>
#include <linux/pm_runtime.h>
-#include <linux/jiffies.h>
+#include "power.h"
-static int __pm_runtime_resume(struct device *dev, bool from_wq);
-static int __pm_request_idle(struct device *dev);
-static int __pm_request_resume(struct device *dev);
+static int rpm_resume(struct device *dev, int rpmflags);
+static int rpm_suspend(struct device *dev, int rpmflags);
+
+/**
+ * update_pm_runtime_accounting - Update the time accounting of power states
+ * @dev: Device to update the accounting for
+ *
+ * In order to be able to have time accounting of the various power states
+ * (as used by programs such as PowerTOP to show the effectiveness of runtime
+ * PM), we need to track the time spent in each state.
+ * update_pm_runtime_accounting must be called each time before the
+ * runtime_status field is updated, to account the time in the old state
+ * correctly.
+ */
+void update_pm_runtime_accounting(struct device *dev)
+{
+ unsigned long now = jiffies;
+ int delta;
+
+ delta = now - dev->power.accounting_timestamp;
+
+ if (delta < 0)
+ delta = 0;
+
+ dev->power.accounting_timestamp = now;
+
+ if (dev->power.disable_depth > 0)
+ return;
+
+ if (dev->power.runtime_status == RPM_SUSPENDED)
+ dev->power.suspended_jiffies += delta;
+ else
+ dev->power.active_jiffies += delta;
+}
+
+static void __update_runtime_status(struct device *dev, enum rpm_status status)
+{
+ update_pm_runtime_accounting(dev);
+ dev->power.runtime_status = status;
+}
/**
* pm_runtime_deactivate_timer - Deactivate given device's suspend timer.
@@ -40,62 +78,154 @@ static void pm_runtime_cancel_pending(struct device *dev)
dev->power.request = RPM_REQ_NONE;
}
-/**
- * __pm_runtime_idle - Notify device bus type if the device can be suspended.
- * @dev: Device to notify the bus type about.
+/*
+ * pm_runtime_autosuspend_expiration - Get a device's autosuspend-delay expiration time.
+ * @dev: Device to handle.
*
- * This function must be called under dev->power.lock with interrupts disabled.
+ * Compute the autosuspend-delay expiration time based on the device's
+ * power.last_busy time. If the delay has already expired or is disabled
+ * (negative) or the power.use_autosuspend flag isn't set, return 0.
+ * Otherwise return the expiration time in jiffies (adjusted to be nonzero).
+ *
+ * This function may be called either with or without dev->power.lock held.
+ * Either way it can be racy, since power.last_busy may be updated at any time.
*/
-static int __pm_runtime_idle(struct device *dev)
- __releases(&dev->power.lock) __acquires(&dev->power.lock)
+unsigned long pm_runtime_autosuspend_expiration(struct device *dev)
+{
+ int autosuspend_delay;
+ long elapsed;
+ unsigned long last_busy;
+ unsigned long expires = 0;
+
+ if (!dev->power.use_autosuspend)
+ goto out;
+
+ autosuspend_delay = ACCESS_ONCE(dev->power.autosuspend_delay);
+ if (autosuspend_delay < 0)
+ goto out;
+
+ last_busy = ACCESS_ONCE(dev->power.last_busy);
+ elapsed = jiffies - last_busy;
+ if (elapsed < 0)
+ goto out; /* jiffies has wrapped around. */
+
+ /*
+ * If the autosuspend_delay is >= 1 second, align the timer by rounding
+ * up to the nearest second.
+ */
+ expires = last_busy + msecs_to_jiffies(autosuspend_delay);
+ if (autosuspend_delay >= 1000)
+ expires = round_jiffies(expires);
+ expires += !expires;
+ if (elapsed >= expires - last_busy)
+ expires = 0; /* Already expired. */
+
+ out:
+ return expires;
+}
+EXPORT_SYMBOL_GPL(pm_runtime_autosuspend_expiration);
+
+/**
+ * rpm_check_suspend_allowed - Test whether a device may be suspended.
+ * @dev: Device to test.
+ */
+static int rpm_check_suspend_allowed(struct device *dev)
{
int retval = 0;
if (dev->power.runtime_error)
retval = -EINVAL;
- else if (dev->power.idle_notification)
- retval = -EINPROGRESS;
else if (atomic_read(&dev->power.usage_count) > 0
- || dev->power.disable_depth > 0
- || dev->power.runtime_status != RPM_ACTIVE)
+ || dev->power.disable_depth > 0)
retval = -EAGAIN;
else if (!pm_children_suspended(dev))
retval = -EBUSY;
+
+ /* Pending resume requests take precedence over suspends. */
+ else if ((dev->power.deferred_resume
+ && dev->power.status == RPM_SUSPENDING)
+ || (dev->power.request_pending
+ && dev->power.request == RPM_REQ_RESUME))
+ retval = -EAGAIN;
+ else if (dev->power.runtime_status == RPM_SUSPENDED)
+ retval = 1;
+
+ return retval;
+}
+
+/**
+ * rpm_idle - Notify device bus type if the device can be suspended.
+ * @dev: Device to notify the bus type about.
+ * @rpmflags: Flag bits.
+ *
+ * Check if the device's run-time PM status allows it to be suspended. If
+ * another idle notification has been started earlier, return immediately. If
+ * the RPM_ASYNC flag is set then queue an idle-notification request; otherwise
+ * run the ->runtime_idle() callback directly.
+ *
+ * This function must be called under dev->power.lock with interrupts disabled.
+ */
+static int rpm_idle(struct device *dev, int rpmflags)
+{
+ int (*callback)(struct device *);
+ int retval;
+
+ retval = rpm_check_suspend_allowed(dev);
+ if (retval < 0)
+ ; /* Conditions are wrong. */
+
+ /* Idle notifications are allowed only in the RPM_ACTIVE state. */
+ else if (dev->power.runtime_status != RPM_ACTIVE)
+ retval = -EAGAIN;
+
+ /*
+ * Any pending request other than an idle notification takes
+ * precedence over us, except that the timer may be running.
+ */
+ else if (dev->power.request_pending &&
+ dev->power.request > RPM_REQ_IDLE)
+ retval = -EAGAIN;
+
+ /* Act as though RPM_NOWAIT is always set. */
+ else if (dev->power.idle_notification)
+ retval = -EINPROGRESS;
if (retval)
goto out;
- if (dev->power.request_pending) {
- /*
- * If an idle notification request is pending, cancel it. Any
- * other pending request takes precedence over us.
- */
- if (dev->power.request == RPM_REQ_IDLE) {
- dev->power.request = RPM_REQ_NONE;
- } else if (dev->power.request != RPM_REQ_NONE) {
- retval = -EAGAIN;
- goto out;
+ /* Pending requests need to be canceled. */
+ dev->power.request = RPM_REQ_NONE;
+
+ if (dev->power.no_callbacks) {
+ /* Assume ->runtime_idle() callback would have suspended. */
+ retval = rpm_suspend(dev, rpmflags);
+ goto out;
+ }
+
+ /* Carry out an asynchronous or a synchronous idle notification. */
+ if (rpmflags & RPM_ASYNC) {
+ dev->power.request = RPM_REQ_IDLE;
+ if (!dev->power.request_pending) {
+ dev->power.request_pending = true;
+ queue_work(pm_wq, &dev->power.work);
}
+ goto out;
}
dev->power.idle_notification = true;
- if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_idle) {
- spin_unlock_irq(&dev->power.lock);
-
- dev->bus->pm->runtime_idle(dev);
-
- spin_lock_irq(&dev->power.lock);
- } else if (dev->type && dev->type->pm && dev->type->pm->runtime_idle) {
- spin_unlock_irq(&dev->power.lock);
-
- dev->type->pm->runtime_idle(dev);
+ if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_idle)
+ callback = dev->bus->pm->runtime_idle;
+ else if (dev->type && dev->type->pm && dev->type->pm->runtime_idle)
+ callback = dev->type->pm->runtime_idle;
+ else if (dev->class && dev->class->pm)
+ callback = dev->class->pm->runtime_idle;
+ else
+ callback = NULL;
- spin_lock_irq(&dev->power.lock);
- } else if (dev->class && dev->class->pm
- && dev->class->pm->runtime_idle) {
+ if (callback) {
spin_unlock_irq(&dev->power.lock);
- dev->class->pm->runtime_idle(dev);
+ callback(dev);
spin_lock_irq(&dev->power.lock);
}
@@ -108,113 +238,99 @@ static int __pm_runtime_idle(struct device *dev)
}
/**
- * pm_runtime_idle - Notify device bus type if the device can be suspended.
- * @dev: Device to notify the bus type about.
+ * rpm_callback - Run a given runtime PM callback for a given device.
+ * @cb: Runtime PM callback to run.
+ * @dev: Device to run the callback for.
*/
-int pm_runtime_idle(struct device *dev)
+static int rpm_callback(int (*cb)(struct device *), struct device *dev)
+ __releases(&dev->power.lock) __acquires(&dev->power.lock)
{
int retval;
- spin_lock_irq(&dev->power.lock);
- retval = __pm_runtime_idle(dev);
- spin_unlock_irq(&dev->power.lock);
+ if (!cb)
+ return -ENOSYS;
- return retval;
-}
-EXPORT_SYMBOL_GPL(pm_runtime_idle);
-
-
-/**
- * update_pm_runtime_accounting - Update the time accounting of power states
- * @dev: Device to update the accounting for
- *
- * In order to be able to have time accounting of the various power states
- * (as used by programs such as PowerTOP to show the effectiveness of runtime
- * PM), we need to track the time spent in each state.
- * update_pm_runtime_accounting must be called each time before the
- * runtime_status field is updated, to account the time in the old state
- * correctly.
- */
-void update_pm_runtime_accounting(struct device *dev)
-{
- unsigned long now = jiffies;
- int delta;
-
- delta = now - dev->power.accounting_timestamp;
-
- if (delta < 0)
- delta = 0;
+ spin_unlock_irq(&dev->power.lock);
- dev->power.accounting_timestamp = now;
+ retval = cb(dev);
- if (dev->power.disable_depth > 0)
- return;
-
- if (dev->power.runtime_status == RPM_SUSPENDED)
- dev->power.suspended_jiffies += delta;
- else
- dev->power.active_jiffies += delta;
-}
+ spin_lock_irq(&dev->power.lock);
+ dev->power.runtime_error = retval;
-static void __update_runtime_status(struct device *dev, enum rpm_status status)
-{
- update_pm_runtime_accounting(dev);
- dev->power.runtime_status = status;
+ return retval;
}
/**
- * __pm_runtime_suspend - Carry out run-time suspend of given device.
+ * rpm_suspend - Carry out run-time suspend of given device.
* @dev: Device to suspend.
- * @from_wq: If set, the function has been called via pm_wq.
+ * @rpmflags: Flag bits.
*
- * Check if the device can be suspended and run the ->runtime_suspend() callback
- * provided by its bus type. If another suspend has been started earlier, wait
- * for it to finish. If an idle notification or suspend request is pending or
- * scheduled, cancel it.
+ * Check if the device's run-time PM status allows it to be suspended. If
+ * another suspend has been started earlier, either return immediately or wait
+ * for it to finish, depending on the RPM_NOWAIT and RPM_ASYNC flags. Cancel a
+ * pending idle notification. If the RPM_ASYNC flag is set then queue a
+ * suspend request; otherwise run the ->runtime_suspend() callback directly.
+ * If a deferred resume was requested while the callback was running then carry
+ * it out; otherwise send an idle notification for the device (if the suspend
+ * failed) or for its parent (if the suspend succeeded).
*
* This function must be called under dev->power.lock with interrupts disabled.
*/
-int __pm_runtime_suspend(struct device *dev, bool from_wq)
+static int rpm_suspend(struct device *dev, int rpmflags)
__releases(&dev->power.lock) __acquires(&dev->power.lock)
{
+ int (*callback)(struct device *);
struct device *parent = NULL;
- bool notify = false;
- int retval = 0;
+ int retval;
- dev_dbg(dev, "__pm_runtime_suspend()%s!\n",
- from_wq ? " from workqueue" : "");
+ dev_dbg(dev, "%s flags 0x%x\n", __func__, rpmflags);
repeat:
- if (dev->power.runtime_error) {
- retval = -EINVAL;
- goto out;
- }
+ retval = rpm_check_suspend_allowed(dev);
- /* Pending resume requests take precedence over us. */
- if (dev->power.request_pending
- && dev->power.request == RPM_REQ_RESUME) {
+ if (retval < 0)
+ ; /* Conditions are wrong. */
+
+ /* Synchronous suspends are not allowed in the RPM_RESUMING state. */
+ else if (dev->power.runtime_status == RPM_RESUMING &&
+ !(rpmflags & RPM_ASYNC))
retval = -EAGAIN;
+ if (retval)
goto out;
+
+ /* If the autosuspend_delay time hasn't expired yet, reschedule. */
+ if ((rpmflags & RPM_AUTO)
+ && dev->power.runtime_status != RPM_SUSPENDING) {
+ unsigned long expires = pm_runtime_autosuspend_expiration(dev);
+
+ if (expires != 0) {
+ /* Pending requests need to be canceled. */
+ dev->power.request = RPM_REQ_NONE;
+
+ /*
+ * Optimization: If the timer is already running and is
+ * set to expire at or before the autosuspend delay,
+ * avoid the overhead of resetting it. Just let it
+ * expire; pm_suspend_timer_fn() will take care of the
+ * rest.
+ */
+ if (!(dev->power.timer_expires && time_before_eq(
+ dev->power.timer_expires, expires))) {
+ dev->power.timer_expires = expires;
+ mod_timer(&dev->power.suspend_timer, expires);
+ }
+ dev->power.timer_autosuspends = 1;
+ goto out;
+ }
}
/* Other scheduled or pending requests need to be canceled. */
pm_runtime_cancel_pending(dev);
- if (dev->power.runtime_status == RPM_SUSPENDED)
- retval = 1;
- else if (dev->power.runtime_status == RPM_RESUMING
- || dev->power.disable_depth > 0
- || atomic_read(&dev->power.usage_count) > 0)
- retval = -EAGAIN;
- else if (!pm_children_suspended(dev))
- retval = -EBUSY;
- if (retval)
- goto out;
-
if (dev->power.runtime_status == RPM_SUSPENDING) {
DEFINE_WAIT(wait);
- if (from_wq) {
+ if (rpmflags & (RPM_ASYNC | RPM_NOWAIT)) {
retval = -EINPROGRESS;
goto out;
}
@@ -236,46 +352,42 @@ int __pm_runtime_suspend(struct device *dev, bool from_wq)
goto repeat;
}
- __update_runtime_status(dev, RPM_SUSPENDING);
dev->power.deferred_resume = false;
+ if (dev->power.no_callbacks)
+ goto no_callback; /* Assume success. */
+
+ /* Carry out an asynchronous or a synchronous suspend. */
+ if (rpmflags & RPM_ASYNC) {
+ dev->power.request = (rpmflags & RPM_AUTO) ?
+ RPM_REQ_AUTOSUSPEND : RPM_REQ_SUSPEND;
+ if (!dev->power.request_pending) {
+ dev->power.request_pending = true;
+ queue_work(pm_wq, &dev->power.work);
+ }
+ goto out;
+ }
- if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_suspend) {
- spin_unlock_irq(&dev->power.lock);
-
- retval = dev->bus->pm->runtime_suspend(dev);
-
- spin_lock_irq(&dev->power.lock);
- dev->power.runtime_error = retval;
- } else if (dev->type && dev->type->pm
- && dev->type->pm->runtime_suspend) {
- spin_unlock_irq(&dev->power.lock);
-
- retval = dev->type->pm->runtime_suspend(dev);
-
- spin_lock_irq(&dev->power.lock);
- dev->power.runtime_error = retval;
- } else if (dev->class && dev->class->pm
- && dev->class->pm->runtime_suspend) {
- spin_unlock_irq(&dev->power.lock);
-
- retval = dev->class->pm->runtime_suspend(dev);
+ __update_runtime_status(dev, RPM_SUSPENDING);
- spin_lock_irq(&dev->power.lock);
- dev->power.runtime_error = retval;
- } else {
- retval = -ENOSYS;
- }
+ if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_suspend)
+ callback = dev->bus->pm->runtime_suspend;
+ else if (dev->type && dev->type->pm && dev->type->pm->runtime_suspend)
+ callback = dev->type->pm->runtime_suspend;
+ else if (dev->class && dev->class->pm)
+ callback = dev->class->pm->runtime_suspend;
+ else
+ callback = NULL;
+ retval = rpm_callback(callback, dev);
if (retval) {
__update_runtime_status(dev, RPM_ACTIVE);
- if (retval == -EAGAIN || retval == -EBUSY) {
- if (dev->power.timer_expires == 0)
- notify = true;
+ dev->power.deferred_resume = 0;
+ if (retval == -EAGAIN || retval == -EBUSY)
dev->power.runtime_error = 0;
- } else {
+ else
pm_runtime_cancel_pending(dev);
- }
} else {
+ no_callback:
__update_runtime_status(dev, RPM_SUSPENDED);
pm_runtime_deactivate_timer(dev);
@@ -287,14 +399,11 @@ int __pm_runtime_suspend(struct device *dev, bool from_wq)
wake_up_all(&dev->power.wait_queue);
if (dev->power.deferred_resume) {
- __pm_runtime_resume(dev, false);
+ rpm_resume(dev, 0);
retval = -EAGAIN;
goto out;
}
- if (notify)
- __pm_runtime_idle(dev);
-
if (parent && !parent->power.ignore_children) {
spin_unlock_irq(&dev->power.lock);
@@ -304,72 +413,69 @@ int __pm_runtime_suspend(struct device *dev, bool from_wq)
}
out:
- dev_dbg(dev, "__pm_runtime_suspend() returns %d!\n", retval);
-
- return retval;
-}
-
-/**
- * pm_runtime_suspend - Carry out run-time suspend of given device.
- * @dev: Device to suspend.
- */
-int pm_runtime_suspend(struct device *dev)
-{
- int retval;
-
- spin_lock_irq(&dev->power.lock);
- retval = __pm_runtime_suspend(dev, false);
- spin_unlock_irq(&dev->power.lock);
+ dev_dbg(dev, "%s returns %d\n", __func__, retval);
return retval;
}
-EXPORT_SYMBOL_GPL(pm_runtime_suspend);
/**
- * __pm_runtime_resume - Carry out run-time resume of given device.
+ * rpm_resume - Carry out run-time resume of given device.
* @dev: Device to resume.
- * @from_wq: If set, the function has been called via pm_wq.
+ * @rpmflags: Flag bits.
*
- * Check if the device can be woken up and run the ->runtime_resume() callback
- * provided by its bus type. If another resume has been started earlier, wait
- * for it to finish. If there's a suspend running in parallel with this
- * function, wait for it to finish and resume the device. Cancel any scheduled
- * or pending requests.
+ * Check if the device's run-time PM status allows it to be resumed. Cancel
+ * any scheduled or pending requests. If another resume has been started
+ * earlier, either return imediately or wait for it to finish, depending on the
+ * RPM_NOWAIT and RPM_ASYNC flags. Similarly, if there's a suspend running in
+ * parallel with this function, either tell the other process to resume after
+ * suspending (deferred_resume) or wait for it to finish. If the RPM_ASYNC
+ * flag is set then queue a resume request; otherwise run the
+ * ->runtime_resume() callback directly. Queue an idle notification for the
+ * device if the resume succeeded.
*
* This function must be called under dev->power.lock with interrupts disabled.
*/
-int __pm_runtime_resume(struct device *dev, bool from_wq)
+static int rpm_resume(struct device *dev, int rpmflags)
__releases(&dev->power.lock) __acquires(&dev->power.lock)
{
+ int (*callback)(struct device *);
struct device *parent = NULL;
int retval = 0;
- dev_dbg(dev, "__pm_runtime_resume()%s!\n",
- from_wq ? " from workqueue" : "");
+ dev_dbg(dev, "%s flags 0x%x\n", __func__, rpmflags);
repeat:
- if (dev->power.runtime_error) {
+ if (dev->power.runtime_error)
retval = -EINVAL;
+ else if (dev->power.disable_depth > 0)
+ retval = -EAGAIN;
+ if (retval)
goto out;
- }
- pm_runtime_cancel_pending(dev);
+ /*
+ * Other scheduled or pending requests need to be canceled. Small
+ * optimization: If an autosuspend timer is running, leave it running
+ * rather than cancelling it now only to restart it again in the near
+ * future.
+ */
+ dev->power.request = RPM_REQ_NONE;
+ if (!dev->power.timer_autosuspends)
+ pm_runtime_deactivate_timer(dev);
- if (dev->power.runtime_status == RPM_ACTIVE)
+ if (dev->power.runtime_status == RPM_ACTIVE) {
retval = 1;
- else if (dev->power.disable_depth > 0)
- retval = -EAGAIN;
- if (retval)
goto out;
+ }
if (dev->power.runtime_status == RPM_RESUMING
|| dev->power.runtime_status == RPM_SUSPENDING) {
DEFINE_WAIT(wait);
- if (from_wq) {
+ if (rpmflags & (RPM_ASYNC | RPM_NOWAIT)) {
if (dev->power.runtime_status == RPM_SUSPENDING)
dev->power.deferred_resume = true;
- retval = -EINPROGRESS;
+ else
+ retval = -EINPROGRESS;
goto out;
}
@@ -391,6 +497,34 @@ int __pm_runtime_resume(struct device *dev, bool from_wq)
goto repeat;
}
+ /*
+ * See if we can skip waking up the parent. This is safe only if
+ * power.no_callbacks is set, because otherwise we don't know whether
+ * the resume will actually succeed.
+ */
+ if (dev->power.no_callbacks && !parent && dev->parent) {
+ spin_lock(&dev->parent->power.lock);
+ if (dev->parent->power.disable_depth > 0
+ || dev->parent->power.ignore_children
+ || dev->parent->power.runtime_status == RPM_ACTIVE) {
+ atomic_inc(&dev->parent->power.child_count);
+ spin_unlock(&dev->parent->power.lock);
+ goto no_callback; /* Assume success. */
+ }
+ spin_unlock(&dev->parent->power.lock);
+ }
+
+ /* Carry out an asynchronous or a synchronous resume. */
+ if (rpmflags & RPM_ASYNC) {
+ dev->power.request = RPM_REQ_RESUME;
+ if (!dev->power.request_pending) {
+ dev->power.request_pending = true;
+ queue_work(pm_wq, &dev->power.work);
+ }
+ retval = 0;
+ goto out;
+ }
+
if (!parent && dev->parent) {
/*
* Increment the parent's resume counter and resume it if
@@ -408,7 +542,7 @@ int __pm_runtime_resume(struct device *dev, bool from_wq)
*/
if (!parent->power.disable_depth
&& !parent->power.ignore_children) {
- __pm_runtime_resume(parent, false);
+ rpm_resume(parent, 0);
if (parent->power.runtime_status != RPM_ACTIVE)
retval = -EBUSY;
}
@@ -420,39 +554,26 @@ int __pm_runtime_resume(struct device *dev, bool from_wq)
goto repeat;
}
- __update_runtime_status(dev, RPM_RESUMING);
-
- if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_resume) {
- spin_unlock_irq(&dev->power.lock);
-
- retval = dev->bus->pm->runtime_resume(dev);
-
- spin_lock_irq(&dev->power.lock);
- dev->power.runtime_error = retval;
- } else if (dev->type && dev->type->pm
- && dev->type->pm->runtime_resume) {
- spin_unlock_irq(&dev->power.lock);
-
- retval = dev->type->pm->runtime_resume(dev);
+ if (dev->power.no_callbacks)
+ goto no_callback; /* Assume success. */
- spin_lock_irq(&dev->power.lock);
- dev->power.runtime_error = retval;
- } else if (dev->class && dev->class->pm
- && dev->class->pm->runtime_resume) {
- spin_unlock_irq(&dev->power.lock);
-
- retval = dev->class->pm->runtime_resume(dev);
+ __update_runtime_status(dev, RPM_RESUMING);
- spin_lock_irq(&dev->power.lock);
- dev->power.runtime_error = retval;
- } else {
- retval = -ENOSYS;
- }
+ if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_resume)
+ callback = dev->bus->pm->runtime_resume;
+ else if (dev->type && dev->type->pm && dev->type->pm->runtime_resume)
+ callback = dev->type->pm->runtime_resume;
+ else if (dev->class && dev->class->pm)
+ callback = dev->class->pm->runtime_resume;
+ else
+ callback = NULL;
+ retval = rpm_callback(callback, dev);
if (retval) {
__update_runtime_status(dev, RPM_SUSPENDED);
pm_runtime_cancel_pending(dev);
} else {
+ no_callback:
__update_runtime_status(dev, RPM_ACTIVE);
if (parent)
atomic_inc(&parent->power.child_count);
@@ -460,7 +581,7 @@ int __pm_runtime_resume(struct device *dev, bool from_wq)
wake_up_all(&dev->power.wait_queue);
if (!retval)
- __pm_request_idle(dev);
+ rpm_idle(dev, RPM_ASYNC);
out:
if (parent) {
@@ -471,28 +592,12 @@ int __pm_runtime_resume(struct device *dev, bool from_wq)
spin_lock_irq(&dev->power.lock);
}
- dev_dbg(dev, "__pm_runtime_resume() returns %d!\n", retval);
+ dev_dbg(dev, "%s returns %d\n", __func__, retval);
return retval;
}
/**
- * pm_runtime_resume - Carry out run-time resume of given device.
- * @dev: Device to suspend.
- */
-int pm_runtime_resume(struct device *dev)
-{
- int retval;
-
- spin_lock_irq(&dev->power.lock);
- retval = __pm_runtime_resume(dev, false);
- spin_unlock_irq(&dev->power.lock);
-
- return retval;
-}
-EXPORT_SYMBOL_GPL(pm_runtime_resume);
-
-/**
* pm_runtime_work - Universal run-time PM work function.
* @work: Work structure used for scheduling the execution of this function.
*
@@ -517,13 +622,16 @@ static void pm_runtime_work(struct work_struct *work)
case RPM_REQ_NONE:
break;
case RPM_REQ_IDLE:
- __pm_runtime_idle(dev);
+ rpm_idle(dev, RPM_NOWAIT);
break;
case RPM_REQ_SUSPEND:
- __pm_runtime_suspend(dev, true);
+ rpm_suspend(dev, RPM_NOWAIT);
+ break;
+ case RPM_REQ_AUTOSUSPEND:
+ rpm_suspend(dev, RPM_NOWAIT | RPM_AUTO);
break;
case RPM_REQ_RESUME:
- __pm_runtime_resume(dev, true);
+ rpm_resume(dev, RPM_NOWAIT);
break;
}
@@ -532,117 +640,10 @@ static void pm_runtime_work(struct work_struct *work)
}
/**
- * __pm_request_idle - Submit an idle notification request for given device.
- * @dev: Device to handle.
- *
- * Check if the device's run-time PM status is correct for suspending the device
- * and queue up a request to run __pm_runtime_idle() for it.
- *
- * This function must be called under dev->power.lock with interrupts disabled.
- */
-static int __pm_request_idle(struct device *dev)
-{
- int retval = 0;
-
- if (dev->power.runtime_error)
- retval = -EINVAL;
- else if (atomic_read(&dev->power.usage_count) > 0
- || dev->power.disable_depth > 0
- || dev->power.runtime_status == RPM_SUSPENDED
- || dev->power.runtime_status == RPM_SUSPENDING)
- retval = -EAGAIN;
- else if (!pm_children_suspended(dev))
- retval = -EBUSY;
- if (retval)
- return retval;
-
- if (dev->power.request_pending) {
- /* Any requests other then RPM_REQ_IDLE take precedence. */
- if (dev->power.request == RPM_REQ_NONE)
- dev->power.request = RPM_REQ_IDLE;
- else if (dev->power.request != RPM_REQ_IDLE)
- retval = -EAGAIN;
- return retval;
- }
-
- dev->power.request = RPM_REQ_IDLE;
- dev->power.request_pending = true;
- queue_work(pm_wq, &dev->power.work);
-
- return retval;
-}
-
-/**
- * pm_request_idle - Submit an idle notification request for given device.
- * @dev: Device to handle.
- */
-int pm_request_idle(struct device *dev)
-{
- unsigned long flags;
- int retval;
-
- spin_lock_irqsave(&dev->power.lock, flags);
- retval = __pm_request_idle(dev);
- spin_unlock_irqrestore(&dev->power.lock, flags);
-
- return retval;
-}
-EXPORT_SYMBOL_GPL(pm_request_idle);
-
-/**
- * __pm_request_suspend - Submit a suspend request for given device.
- * @dev: Device to suspend.
- *
- * This function must be called under dev->power.lock with interrupts disabled.
- */
-static int __pm_request_suspend(struct device *dev)
-{
- int retval = 0;
-
- if (dev->power.runtime_error)
- return -EINVAL;
-
- if (dev->power.runtime_status == RPM_SUSPENDED)
- retval = 1;
- else if (atomic_read(&dev->power.usage_count) > 0
- || dev->power.disable_depth > 0)
- retval = -EAGAIN;
- else if (dev->power.runtime_status == RPM_SUSPENDING)
- retval = -EINPROGRESS;
- else if (!pm_children_suspended(dev))
- retval = -EBUSY;
- if (retval < 0)
- return retval;
-
- pm_runtime_deactivate_timer(dev);
-
- if (dev->power.request_pending) {
- /*
- * Pending resume requests take precedence over us, but we can
- * overtake any other pending request.
- */
- if (dev->power.request == RPM_REQ_RESUME)
- retval = -EAGAIN;
- else if (dev->power.request != RPM_REQ_SUSPEND)
- dev->power.request = retval ?
- RPM_REQ_NONE : RPM_REQ_SUSPEND;
- return retval;
- } else if (retval) {
- return retval;
- }
-
- dev->power.request = RPM_REQ_SUSPEND;
- dev->power.request_pending = true;
- queue_work(pm_wq, &dev->power.work);
-
- return 0;
-}
-
-/**
* pm_suspend_timer_fn - Timer function for pm_schedule_suspend().
* @data: Device pointer passed by pm_schedule_suspend().
*
- * Check if the time is right and execute __pm_request_suspend() in that case.
+ * Check if the time is right and queue a suspend request.
*/
static void pm_suspend_timer_fn(unsigned long data)
{
@@ -656,7 +657,8 @@ static void pm_suspend_timer_fn(unsigned long data)
/* If 'expire' is after 'jiffies' we've been called too early. */
if (expires > 0 && !time_after(expires, jiffies)) {
dev->power.timer_expires = 0;
- __pm_request_suspend(dev);
+ rpm_suspend(dev, dev->power.timer_autosuspends ?
+ (RPM_ASYNC | RPM_AUTO) : RPM_ASYNC);
}
spin_unlock_irqrestore(&dev->power.lock, flags);
@@ -670,47 +672,25 @@ static void pm_suspend_timer_fn(unsigned long data)
int pm_schedule_suspend(struct device *dev, unsigned int delay)
{
unsigned long flags;
- int retval = 0;
+ int retval;
spin_lock_irqsave(&dev->power.lock, flags);
- if (dev->power.runtime_error) {
- retval = -EINVAL;
- goto out;
- }
-
if (!delay) {
- retval = __pm_request_suspend(dev);
+ retval = rpm_suspend(dev, RPM_ASYNC);
goto out;
}
- pm_runtime_deactivate_timer(dev);
-
- if (dev->power.request_pending) {
- /*
- * Pending resume requests take precedence over us, but any
- * other pending requests have to be canceled.
- */
- if (dev->power.request == RPM_REQ_RESUME) {
- retval = -EAGAIN;
- goto out;
- }
- dev->power.request = RPM_REQ_NONE;
- }
-
- if (dev->power.runtime_status == RPM_SUSPENDED)
- retval = 1;
- else if (atomic_read(&dev->power.usage_count) > 0
- || dev->power.disable_depth > 0)
- retval = -EAGAIN;
- else if (!pm_children_suspended(dev))
- retval = -EBUSY;
+ retval = rpm_check_suspend_allowed(dev);
if (retval)
goto out;
+ /* Other scheduled or pending requests need to be canceled. */
+ pm_runtime_cancel_pending(dev);
+
dev->power.timer_expires = jiffies + msecs_to_jiffies(delay);
- if (!dev->power.timer_expires)
- dev->power.timer_expires = 1;
+ dev->power.timer_expires += !dev->power.timer_expires;
+ dev->power.timer_autosuspends = 0;
mod_timer(&dev->power.suspend_timer, dev->power.timer_expires);
out:
@@ -721,103 +701,88 @@ int pm_schedule_suspend(struct device *dev, unsigned int delay)
EXPORT_SYMBOL_GPL(pm_schedule_suspend);
/**
- * pm_request_resume - Submit a resume request for given device.
- * @dev: Device to resume.
+ * __pm_runtime_idle - Entry point for run-time idle operations.
+ * @dev: Device to send idle notification for.
+ * @rpmflags: Flag bits.
*
- * This function must be called under dev->power.lock with interrupts disabled.
+ * If the RPM_GET_PUT flag is set, decrement the device's usage count and
+ * return immediately if it is larger than zero. Then carry out an idle
+ * notification, either synchronous or asynchronous.
+ *
+ * This routine may be called in atomic context if the RPM_ASYNC flag is set.
*/
-static int __pm_request_resume(struct device *dev)
+int __pm_runtime_idle(struct device *dev, int rpmflags)
{
- int retval = 0;
-
- if (dev->power.runtime_error)
- return -EINVAL;
-
- if (dev->power.runtime_status == RPM_ACTIVE)
- retval = 1;
- else if (dev->power.runtime_status == RPM_RESUMING)
- retval = -EINPROGRESS;
- else if (dev->power.disable_depth > 0)
- retval = -EAGAIN;
- if (retval < 0)
- return retval;
-
- pm_runtime_deactivate_timer(dev);
+ unsigned long flags;
+ int retval;
- if (dev->power.runtime_status == RPM_SUSPENDING) {
- dev->power.deferred_resume = true;
- return retval;
+ if (rpmflags & RPM_GET_PUT) {
+ if (!atomic_dec_and_test(&dev->power.usage_count))
+ return 0;
}
- if (dev->power.request_pending) {
- /* If non-resume request is pending, we can overtake it. */
- dev->power.request = retval ? RPM_REQ_NONE : RPM_REQ_RESUME;
- return retval;
- }
- if (retval)
- return retval;
- dev->power.request = RPM_REQ_RESUME;
- dev->power.request_pending = true;
- queue_work(pm_wq, &dev->power.work);
+ spin_lock_irqsave(&dev->power.lock, flags);
+ retval = rpm_idle(dev, rpmflags);
+ spin_unlock_irqrestore(&dev->power.lock, flags);
return retval;
}
+EXPORT_SYMBOL_GPL(__pm_runtime_idle);
/**
- * pm_request_resume - Submit a resume request for given device.
- * @dev: Device to resume.
+ * __pm_runtime_suspend - Entry point for run-time put/suspend operations.
+ * @dev: Device to suspend.
+ * @rpmflags: Flag bits.
+ *
+ * If the RPM_GET_PUT flag is set, decrement the device's usage count and
+ * return immediately if it is larger than zero. Then carry out a suspend,
+ * either synchronous or asynchronous.
+ *
+ * This routine may be called in atomic context if the RPM_ASYNC flag is set.
*/
-int pm_request_resume(struct device *dev)
+int __pm_runtime_suspend(struct device *dev, int rpmflags)
{
unsigned long flags;
int retval;
+ if (rpmflags & RPM_GET_PUT) {
+ if (!atomic_dec_and_test(&dev->power.usage_count))
+ return 0;
+ }
+
spin_lock_irqsave(&dev->power.lock, flags);
- retval = __pm_request_resume(dev);
+ retval = rpm_suspend(dev, rpmflags);
spin_unlock_irqrestore(&dev->power.lock, flags);
return retval;
}
-EXPORT_SYMBOL_GPL(pm_request_resume);
+EXPORT_SYMBOL_GPL(__pm_runtime_suspend);
/**
- * __pm_runtime_get - Reference count a device and wake it up, if necessary.
- * @dev: Device to handle.
- * @sync: If set and the device is suspended, resume it synchronously.
+ * __pm_runtime_resume - Entry point for run-time resume operations.
+ * @dev: Device to resume.
+ * @rpmflags: Flag bits.
+ *
+ * If the RPM_GET_PUT flag is set, increment the device's usage count. Then
+ * carry out a resume, either synchronous or asynchronous.
*
- * Increment the usage count of the device and resume it or submit a resume
- * request for it, depending on the value of @sync.
+ * This routine may be called in atomic context if the RPM_ASYNC flag is set.
*/
-int __pm_runtime_get(struct device *dev, bool sync)
+int __pm_runtime_resume(struct device *dev, int rpmflags)
{
+ unsigned long flags;
int retval;
- atomic_inc(&dev->power.usage_count);
- retval = sync ? pm_runtime_resume(dev) : pm_request_resume(dev);
+ if (rpmflags & RPM_GET_PUT)
+ atomic_inc(&dev->power.usage_count);
- return retval;
-}
-EXPORT_SYMBOL_GPL(__pm_runtime_get);
-
-/**
- * __pm_runtime_put - Decrement the device's usage counter and notify its bus.
- * @dev: Device to handle.
- * @sync: If the device's bus type is to be notified, do that synchronously.
- *
- * Decrement the usage count of the device and if it reaches zero, carry out a
- * synchronous idle notification or submit an idle notification request for it,
- * depending on the value of @sync.
- */
-int __pm_runtime_put(struct device *dev, bool sync)
-{
- int retval = 0;
-
- if (atomic_dec_and_test(&dev->power.usage_count))
- retval = sync ? pm_runtime_idle(dev) : pm_request_idle(dev);
+ spin_lock_irqsave(&dev->power.lock, flags);
+ retval = rpm_resume(dev, rpmflags);
+ spin_unlock_irqrestore(&dev->power.lock, flags);
return retval;
}
-EXPORT_SYMBOL_GPL(__pm_runtime_put);
+EXPORT_SYMBOL_GPL(__pm_runtime_resume);
/**
* __pm_runtime_set_status - Set run-time PM status of a device.
@@ -968,7 +933,7 @@ int pm_runtime_barrier(struct device *dev)
if (dev->power.request_pending
&& dev->power.request == RPM_REQ_RESUME) {
- __pm_runtime_resume(dev, false);
+ rpm_resume(dev, 0);
retval = 1;
}
@@ -1017,7 +982,7 @@ void __pm_runtime_disable(struct device *dev, bool check_resume)
*/
pm_runtime_get_noresume(dev);
- __pm_runtime_resume(dev, false);
+ rpm_resume(dev, 0);
pm_runtime_put_noidle(dev);
}
@@ -1065,7 +1030,7 @@ void pm_runtime_forbid(struct device *dev)
dev->power.runtime_auto = false;
atomic_inc(&dev->power.usage_count);
- __pm_runtime_resume(dev, false);
+ rpm_resume(dev, 0);
out:
spin_unlock_irq(&dev->power.lock);
@@ -1086,7 +1051,7 @@ void pm_runtime_allow(struct device *dev)
dev->power.runtime_auto = true;
if (atomic_dec_and_test(&dev->power.usage_count))
- __pm_runtime_idle(dev);
+ rpm_idle(dev, RPM_AUTO);
out:
spin_unlock_irq(&dev->power.lock);
@@ -1094,13 +1059,110 @@ void pm_runtime_allow(struct device *dev)
EXPORT_SYMBOL_GPL(pm_runtime_allow);
/**
+ * pm_runtime_no_callbacks - Ignore run-time PM callbacks for a device.
+ * @dev: Device to handle.
+ *
+ * Set the power.no_callbacks flag, which tells the PM core that this
+ * device is power-managed through its parent and has no run-time PM
+ * callbacks of its own. The run-time sysfs attributes will be removed.
+ *
+ */
+void pm_runtime_no_callbacks(struct device *dev)
+{
+ spin_lock_irq(&dev->power.lock);
+ dev->power.no_callbacks = 1;
+ spin_unlock_irq(&dev->power.lock);
+ if (device_is_registered(dev))
+ rpm_sysfs_remove(dev);
+}
+EXPORT_SYMBOL_GPL(pm_runtime_no_callbacks);
+
+/**
+ * update_autosuspend - Handle a change to a device's autosuspend settings.
+ * @dev: Device to handle.
+ * @old_delay: The former autosuspend_delay value.
+ * @old_use: The former use_autosuspend value.
+ *
+ * Prevent runtime suspend if the new delay is negative and use_autosuspend is
+ * set; otherwise allow it. Send an idle notification if suspends are allowed.
+ *
+ * This function must be called under dev->power.lock with interrupts disabled.
+ */
+static void update_autosuspend(struct device *dev, int old_delay, int old_use)
+{
+ int delay = dev->power.autosuspend_delay;
+
+ /* Should runtime suspend be prevented now? */
+ if (dev->power.use_autosuspend && delay < 0) {
+
+ /* If it used to be allowed then prevent it. */
+ if (!old_use || old_delay >= 0) {
+ atomic_inc(&dev->power.usage_count);
+ rpm_resume(dev, 0);
+ }
+ }
+
+ /* Runtime suspend should be allowed now. */
+ else {
+
+ /* If it used to be prevented then allow it. */
+ if (old_use && old_delay < 0)
+ atomic_dec(&dev->power.usage_count);
+
+ /* Maybe we can autosuspend now. */
+ rpm_idle(dev, RPM_AUTO);
+ }
+}
+
+/**
+ * pm_runtime_set_autosuspend_delay - Set a device's autosuspend_delay value.
+ * @dev: Device to handle.
+ * @delay: Value of the new delay in milliseconds.
+ *
+ * Set the device's power.autosuspend_delay value. If it changes to negative
+ * and the power.use_autosuspend flag is set, prevent run-time suspends. If it
+ * changes the other way, allow run-time suspends.
+ */
+void pm_runtime_set_autosuspend_delay(struct device *dev, int delay)
+{
+ int old_delay, old_use;
+
+ spin_lock_irq(&dev->power.lock);
+ old_delay = dev->power.autosuspend_delay;
+ old_use = dev->power.use_autosuspend;
+ dev->power.autosuspend_delay = delay;
+ update_autosuspend(dev, old_delay, old_use);
+ spin_unlock_irq(&dev->power.lock);
+}
+EXPORT_SYMBOL_GPL(pm_runtime_set_autosuspend_delay);
+
+/**
+ * __pm_runtime_use_autosuspend - Set a device's use_autosuspend flag.
+ * @dev: Device to handle.
+ * @use: New value for use_autosuspend.
+ *
+ * Set the device's power.use_autosuspend flag, and allow or prevent run-time
+ * suspends as needed.
+ */
+void __pm_runtime_use_autosuspend(struct device *dev, bool use)
+{
+ int old_delay, old_use;
+
+ spin_lock_irq(&dev->power.lock);
+ old_delay = dev->power.autosuspend_delay;
+ old_use = dev->power.use_autosuspend;
+ dev->power.use_autosuspend = use;
+ update_autosuspend(dev, old_delay, old_use);
+ spin_unlock_irq(&dev->power.lock);
+}
+EXPORT_SYMBOL_GPL(__pm_runtime_use_autosuspend);
+
+/**
* pm_runtime_init - Initialize run-time PM fields in given device object.
* @dev: Device object to initialize.
*/
void pm_runtime_init(struct device *dev)
{
- spin_lock_init(&dev->power.lock);
-
dev->power.runtime_status = RPM_SUSPENDED;
dev->power.idle_notification = false;
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
index e56b4388fe61..0b1e46bf3e56 100644
--- a/drivers/base/power/sysfs.c
+++ b/drivers/base/power/sysfs.c
@@ -75,12 +75,27 @@
* attribute is set to "enabled" by bus type code or device drivers and in
* that cases it should be safe to leave the default value.
*
+ * autosuspend_delay_ms - Report/change a device's autosuspend_delay value
+ *
+ * Some drivers don't want to carry out a runtime suspend as soon as a
+ * device becomes idle; they want it always to remain idle for some period
+ * of time before suspending it. This period is the autosuspend_delay
+ * value (expressed in milliseconds) and it can be controlled by the user.
+ * If the value is negative then the device will never be runtime
+ * suspended.
+ *
+ * NOTE: The autosuspend_delay_ms attribute and the autosuspend_delay
+ * value are used only if the driver calls pm_runtime_use_autosuspend().
+ *
* wakeup_count - Report the number of wakeup events related to the device
*/
static const char enabled[] = "enabled";
static const char disabled[] = "disabled";
+const char power_group_name[] = "power";
+EXPORT_SYMBOL_GPL(power_group_name);
+
#ifdef CONFIG_PM_RUNTIME
static const char ctrl_auto[] = "auto";
static const char ctrl_on[] = "on";
@@ -170,6 +185,33 @@ static ssize_t rtpm_status_show(struct device *dev,
}
static DEVICE_ATTR(runtime_status, 0444, rtpm_status_show, NULL);
+
+static ssize_t autosuspend_delay_ms_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ if (!dev->power.use_autosuspend)
+ return -EIO;
+ return sprintf(buf, "%d\n", dev->power.autosuspend_delay);
+}
+
+static ssize_t autosuspend_delay_ms_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t n)
+{
+ long delay;
+
+ if (!dev->power.use_autosuspend)
+ return -EIO;
+
+ if (strict_strtol(buf, 10, &delay) != 0 || delay != (int) delay)
+ return -EINVAL;
+
+ pm_runtime_set_autosuspend_delay(dev, delay);
+ return n;
+}
+
+static DEVICE_ATTR(autosuspend_delay_ms, 0644, autosuspend_delay_ms_show,
+ autosuspend_delay_ms_store);
+
#endif
static ssize_t
@@ -210,11 +252,122 @@ static DEVICE_ATTR(wakeup, 0644, wake_show, wake_store);
static ssize_t wakeup_count_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- return sprintf(buf, "%lu\n", dev->power.wakeup_count);
+ unsigned long count = 0;
+ bool enabled = false;
+
+ spin_lock_irq(&dev->power.lock);
+ if (dev->power.wakeup) {
+ count = dev->power.wakeup->event_count;
+ enabled = true;
+ }
+ spin_unlock_irq(&dev->power.lock);
+ return enabled ? sprintf(buf, "%lu\n", count) : sprintf(buf, "\n");
}
static DEVICE_ATTR(wakeup_count, 0444, wakeup_count_show, NULL);
-#endif
+
+static ssize_t wakeup_active_count_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long count = 0;
+ bool enabled = false;
+
+ spin_lock_irq(&dev->power.lock);
+ if (dev->power.wakeup) {
+ count = dev->power.wakeup->active_count;
+ enabled = true;
+ }
+ spin_unlock_irq(&dev->power.lock);
+ return enabled ? sprintf(buf, "%lu\n", count) : sprintf(buf, "\n");
+}
+
+static DEVICE_ATTR(wakeup_active_count, 0444, wakeup_active_count_show, NULL);
+
+static ssize_t wakeup_hit_count_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long count = 0;
+ bool enabled = false;
+
+ spin_lock_irq(&dev->power.lock);
+ if (dev->power.wakeup) {
+ count = dev->power.wakeup->hit_count;
+ enabled = true;
+ }
+ spin_unlock_irq(&dev->power.lock);
+ return enabled ? sprintf(buf, "%lu\n", count) : sprintf(buf, "\n");
+}
+
+static DEVICE_ATTR(wakeup_hit_count, 0444, wakeup_hit_count_show, NULL);
+
+static ssize_t wakeup_active_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned int active = 0;
+ bool enabled = false;
+
+ spin_lock_irq(&dev->power.lock);
+ if (dev->power.wakeup) {
+ active = dev->power.wakeup->active;
+ enabled = true;
+ }
+ spin_unlock_irq(&dev->power.lock);
+ return enabled ? sprintf(buf, "%u\n", active) : sprintf(buf, "\n");
+}
+
+static DEVICE_ATTR(wakeup_active, 0444, wakeup_active_show, NULL);
+
+static ssize_t wakeup_total_time_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ s64 msec = 0;
+ bool enabled = false;
+
+ spin_lock_irq(&dev->power.lock);
+ if (dev->power.wakeup) {
+ msec = ktime_to_ms(dev->power.wakeup->total_time);
+ enabled = true;
+ }
+ spin_unlock_irq(&dev->power.lock);
+ return enabled ? sprintf(buf, "%lld\n", msec) : sprintf(buf, "\n");
+}
+
+static DEVICE_ATTR(wakeup_total_time_ms, 0444, wakeup_total_time_show, NULL);
+
+static ssize_t wakeup_max_time_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ s64 msec = 0;
+ bool enabled = false;
+
+ spin_lock_irq(&dev->power.lock);
+ if (dev->power.wakeup) {
+ msec = ktime_to_ms(dev->power.wakeup->max_time);
+ enabled = true;
+ }
+ spin_unlock_irq(&dev->power.lock);
+ return enabled ? sprintf(buf, "%lld\n", msec) : sprintf(buf, "\n");
+}
+
+static DEVICE_ATTR(wakeup_max_time_ms, 0444, wakeup_max_time_show, NULL);
+
+static ssize_t wakeup_last_time_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ s64 msec = 0;
+ bool enabled = false;
+
+ spin_lock_irq(&dev->power.lock);
+ if (dev->power.wakeup) {
+ msec = ktime_to_ms(dev->power.wakeup->last_time);
+ enabled = true;
+ }
+ spin_unlock_irq(&dev->power.lock);
+ return enabled ? sprintf(buf, "%lld\n", msec) : sprintf(buf, "\n");
+}
+
+static DEVICE_ATTR(wakeup_last_time_ms, 0444, wakeup_last_time_show, NULL);
+#endif /* CONFIG_PM_SLEEP */
#ifdef CONFIG_PM_ADVANCED_DEBUG
#ifdef CONFIG_PM_RUNTIME
@@ -279,19 +432,20 @@ static DEVICE_ATTR(async, 0644, async_show, async_store);
#endif /* CONFIG_PM_ADVANCED_DEBUG */
static struct attribute * power_attrs[] = {
-#ifdef CONFIG_PM_RUNTIME
- &dev_attr_control.attr,
- &dev_attr_runtime_status.attr,
- &dev_attr_runtime_suspended_time.attr,
- &dev_attr_runtime_active_time.attr,
-#endif
&dev_attr_wakeup.attr,
#ifdef CONFIG_PM_SLEEP
&dev_attr_wakeup_count.attr,
+ &dev_attr_wakeup_active_count.attr,
+ &dev_attr_wakeup_hit_count.attr,
+ &dev_attr_wakeup_active.attr,
+ &dev_attr_wakeup_total_time_ms.attr,
+ &dev_attr_wakeup_max_time_ms.attr,
+ &dev_attr_wakeup_last_time_ms.attr,
#endif
#ifdef CONFIG_PM_ADVANCED_DEBUG
&dev_attr_async.attr,
#ifdef CONFIG_PM_RUNTIME
+ &dev_attr_runtime_status.attr,
&dev_attr_runtime_usage.attr,
&dev_attr_runtime_active_kids.attr,
&dev_attr_runtime_enabled.attr,
@@ -300,10 +454,53 @@ static struct attribute * power_attrs[] = {
NULL,
};
static struct attribute_group pm_attr_group = {
- .name = "power",
+ .name = power_group_name,
.attrs = power_attrs,
};
+#ifdef CONFIG_PM_RUNTIME
+
+static struct attribute *runtime_attrs[] = {
+#ifndef CONFIG_PM_ADVANCED_DEBUG
+ &dev_attr_runtime_status.attr,
+#endif
+ &dev_attr_control.attr,
+ &dev_attr_runtime_suspended_time.attr,
+ &dev_attr_runtime_active_time.attr,
+ &dev_attr_autosuspend_delay_ms.attr,
+ NULL,
+};
+static struct attribute_group pm_runtime_attr_group = {
+ .name = power_group_name,
+ .attrs = runtime_attrs,
+};
+
+int dpm_sysfs_add(struct device *dev)
+{
+ int rc;
+
+ rc = sysfs_create_group(&dev->kobj, &pm_attr_group);
+ if (rc == 0 && !dev->power.no_callbacks) {
+ rc = sysfs_merge_group(&dev->kobj, &pm_runtime_attr_group);
+ if (rc)
+ sysfs_remove_group(&dev->kobj, &pm_attr_group);
+ }
+ return rc;
+}
+
+void rpm_sysfs_remove(struct device *dev)
+{
+ sysfs_unmerge_group(&dev->kobj, &pm_runtime_attr_group);
+}
+
+void dpm_sysfs_remove(struct device *dev)
+{
+ rpm_sysfs_remove(dev);
+ sysfs_remove_group(&dev->kobj, &pm_attr_group);
+}
+
+#else /* CONFIG_PM_RUNTIME */
+
int dpm_sysfs_add(struct device * dev)
{
return sysfs_create_group(&dev->kobj, &pm_attr_group);
@@ -313,3 +510,5 @@ void dpm_sysfs_remove(struct device * dev)
{
sysfs_remove_group(&dev->kobj, &pm_attr_group);
}
+
+#endif
diff --git a/drivers/base/power/trace.c b/drivers/base/power/trace.c
index 0a1a2c4dbc6e..9f4258df4cfd 100644
--- a/drivers/base/power/trace.c
+++ b/drivers/base/power/trace.c
@@ -188,8 +188,10 @@ static int show_file_hash(unsigned int value)
static int show_dev_hash(unsigned int value)
{
int match = 0;
- struct list_head *entry = dpm_list.prev;
+ struct list_head *entry;
+ device_pm_lock();
+ entry = dpm_list.prev;
while (entry != &dpm_list) {
struct device * dev = to_device(entry);
unsigned int hash = hash_string(DEVSEED, dev_name(dev), DEVHASH);
@@ -199,11 +201,43 @@ static int show_dev_hash(unsigned int value)
}
entry = entry->prev;
}
+ device_pm_unlock();
return match;
}
static unsigned int hash_value_early_read;
+int show_trace_dev_match(char *buf, size_t size)
+{
+ unsigned int value = hash_value_early_read / (USERHASH * FILEHASH);
+ int ret = 0;
+ struct list_head *entry;
+
+ /*
+ * It's possible that multiple devices will match the hash and we can't
+ * tell which is the culprit, so it's best to output them all.
+ */
+ device_pm_lock();
+ entry = dpm_list.prev;
+ while (size && entry != &dpm_list) {
+ struct device *dev = to_device(entry);
+ unsigned int hash = hash_string(DEVSEED, dev_name(dev),
+ DEVHASH);
+ if (hash == value) {
+ int len = snprintf(buf, size, "%s\n",
+ dev_driver_string(dev));
+ if (len > size)
+ len = size;
+ buf += len;
+ ret += len;
+ size -= len;
+ }
+ entry = entry->prev;
+ }
+ device_pm_unlock();
+ return ret;
+}
+
static int early_resume_init(void)
{
hash_value_early_read = read_magic_time();
diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c
index eb594facfc3f..71c5528e1c35 100644
--- a/drivers/base/power/wakeup.c
+++ b/drivers/base/power/wakeup.c
@@ -11,7 +11,12 @@
#include <linux/sched.h>
#include <linux/capability.h>
#include <linux/suspend.h>
-#include <linux/pm.h>
+#include <linux/seq_file.h>
+#include <linux/debugfs.h>
+
+#include "power.h"
+
+#define TIMEOUT 100
/*
* If set, the suspend/hibernate code will abort transitions to a sleep state
@@ -20,18 +25,244 @@
bool events_check_enabled;
/* The counter of registered wakeup events. */
-static unsigned long event_count;
+static atomic_t event_count = ATOMIC_INIT(0);
/* A preserved old value of event_count. */
-static unsigned long saved_event_count;
+static unsigned int saved_count;
/* The counter of wakeup events being processed. */
-static unsigned long events_in_progress;
+static atomic_t events_in_progress = ATOMIC_INIT(0);
static DEFINE_SPINLOCK(events_lock);
static void pm_wakeup_timer_fn(unsigned long data);
-static DEFINE_TIMER(events_timer, pm_wakeup_timer_fn, 0, 0);
-static unsigned long events_timer_expires;
+static LIST_HEAD(wakeup_sources);
+
+/**
+ * wakeup_source_create - Create a struct wakeup_source object.
+ * @name: Name of the new wakeup source.
+ */
+struct wakeup_source *wakeup_source_create(const char *name)
+{
+ struct wakeup_source *ws;
+
+ ws = kzalloc(sizeof(*ws), GFP_KERNEL);
+ if (!ws)
+ return NULL;
+
+ spin_lock_init(&ws->lock);
+ if (name)
+ ws->name = kstrdup(name, GFP_KERNEL);
+
+ return ws;
+}
+EXPORT_SYMBOL_GPL(wakeup_source_create);
+
+/**
+ * wakeup_source_destroy - Destroy a struct wakeup_source object.
+ * @ws: Wakeup source to destroy.
+ */
+void wakeup_source_destroy(struct wakeup_source *ws)
+{
+ if (!ws)
+ return;
+
+ spin_lock_irq(&ws->lock);
+ while (ws->active) {
+ spin_unlock_irq(&ws->lock);
+
+ schedule_timeout_interruptible(msecs_to_jiffies(TIMEOUT));
+
+ spin_lock_irq(&ws->lock);
+ }
+ spin_unlock_irq(&ws->lock);
+
+ kfree(ws->name);
+ kfree(ws);
+}
+EXPORT_SYMBOL_GPL(wakeup_source_destroy);
+
+/**
+ * wakeup_source_add - Add given object to the list of wakeup sources.
+ * @ws: Wakeup source object to add to the list.
+ */
+void wakeup_source_add(struct wakeup_source *ws)
+{
+ if (WARN_ON(!ws))
+ return;
+
+ setup_timer(&ws->timer, pm_wakeup_timer_fn, (unsigned long)ws);
+ ws->active = false;
+
+ spin_lock_irq(&events_lock);
+ list_add_rcu(&ws->entry, &wakeup_sources);
+ spin_unlock_irq(&events_lock);
+ synchronize_rcu();
+}
+EXPORT_SYMBOL_GPL(wakeup_source_add);
+
+/**
+ * wakeup_source_remove - Remove given object from the wakeup sources list.
+ * @ws: Wakeup source object to remove from the list.
+ */
+void wakeup_source_remove(struct wakeup_source *ws)
+{
+ if (WARN_ON(!ws))
+ return;
+
+ spin_lock_irq(&events_lock);
+ list_del_rcu(&ws->entry);
+ spin_unlock_irq(&events_lock);
+ synchronize_rcu();
+}
+EXPORT_SYMBOL_GPL(wakeup_source_remove);
+
+/**
+ * wakeup_source_register - Create wakeup source and add it to the list.
+ * @name: Name of the wakeup source to register.
+ */
+struct wakeup_source *wakeup_source_register(const char *name)
+{
+ struct wakeup_source *ws;
+
+ ws = wakeup_source_create(name);
+ if (ws)
+ wakeup_source_add(ws);
+
+ return ws;
+}
+EXPORT_SYMBOL_GPL(wakeup_source_register);
+
+/**
+ * wakeup_source_unregister - Remove wakeup source from the list and remove it.
+ * @ws: Wakeup source object to unregister.
+ */
+void wakeup_source_unregister(struct wakeup_source *ws)
+{
+ wakeup_source_remove(ws);
+ wakeup_source_destroy(ws);
+}
+EXPORT_SYMBOL_GPL(wakeup_source_unregister);
+
+/**
+ * device_wakeup_attach - Attach a wakeup source object to a device object.
+ * @dev: Device to handle.
+ * @ws: Wakeup source object to attach to @dev.
+ *
+ * This causes @dev to be treated as a wakeup device.
+ */
+static int device_wakeup_attach(struct device *dev, struct wakeup_source *ws)
+{
+ spin_lock_irq(&dev->power.lock);
+ if (dev->power.wakeup) {
+ spin_unlock_irq(&dev->power.lock);
+ return -EEXIST;
+ }
+ dev->power.wakeup = ws;
+ spin_unlock_irq(&dev->power.lock);
+ return 0;
+}
+
+/**
+ * device_wakeup_enable - Enable given device to be a wakeup source.
+ * @dev: Device to handle.
+ *
+ * Create a wakeup source object, register it and attach it to @dev.
+ */
+int device_wakeup_enable(struct device *dev)
+{
+ struct wakeup_source *ws;
+ int ret;
+
+ if (!dev || !dev->power.can_wakeup)
+ return -EINVAL;
+
+ ws = wakeup_source_register(dev_name(dev));
+ if (!ws)
+ return -ENOMEM;
+
+ ret = device_wakeup_attach(dev, ws);
+ if (ret)
+ wakeup_source_unregister(ws);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(device_wakeup_enable);
+
+/**
+ * device_wakeup_detach - Detach a device's wakeup source object from it.
+ * @dev: Device to detach the wakeup source object from.
+ *
+ * After it returns, @dev will not be treated as a wakeup device any more.
+ */
+static struct wakeup_source *device_wakeup_detach(struct device *dev)
+{
+ struct wakeup_source *ws;
+
+ spin_lock_irq(&dev->power.lock);
+ ws = dev->power.wakeup;
+ dev->power.wakeup = NULL;
+ spin_unlock_irq(&dev->power.lock);
+ return ws;
+}
+
+/**
+ * device_wakeup_disable - Do not regard a device as a wakeup source any more.
+ * @dev: Device to handle.
+ *
+ * Detach the @dev's wakeup source object from it, unregister this wakeup source
+ * object and destroy it.
+ */
+int device_wakeup_disable(struct device *dev)
+{
+ struct wakeup_source *ws;
+
+ if (!dev || !dev->power.can_wakeup)
+ return -EINVAL;
+
+ ws = device_wakeup_detach(dev);
+ if (ws)
+ wakeup_source_unregister(ws);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(device_wakeup_disable);
+
+/**
+ * device_init_wakeup - Device wakeup initialization.
+ * @dev: Device to handle.
+ * @enable: Whether or not to enable @dev as a wakeup device.
+ *
+ * By default, most devices should leave wakeup disabled. The exceptions are
+ * devices that everyone expects to be wakeup sources: keyboards, power buttons,
+ * possibly network interfaces, etc.
+ */
+int device_init_wakeup(struct device *dev, bool enable)
+{
+ int ret = 0;
+
+ if (enable) {
+ device_set_wakeup_capable(dev, true);
+ ret = device_wakeup_enable(dev);
+ } else {
+ device_set_wakeup_capable(dev, false);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(device_init_wakeup);
+
+/**
+ * device_set_wakeup_enable - Enable or disable a device to wake up the system.
+ * @dev: Device to handle.
+ */
+int device_set_wakeup_enable(struct device *dev, bool enable)
+{
+ if (!dev || !dev->power.can_wakeup)
+ return -EINVAL;
+
+ return enable ? device_wakeup_enable(dev) : device_wakeup_disable(dev);
+}
+EXPORT_SYMBOL_GPL(device_set_wakeup_enable);
/*
* The functions below use the observation that each wakeup event starts a
@@ -55,118 +286,259 @@ static unsigned long events_timer_expires;
* knowledge, however, may not be available to it, so it can simply specify time
* to wait before the system can be suspended and pass it as the second
* argument of pm_wakeup_event().
+ *
+ * It is valid to call pm_relax() after pm_wakeup_event(), in which case the
+ * "no suspend" period will be ended either by the pm_relax(), or by the timer
+ * function executed when the timer expires, whichever comes first.
*/
/**
+ * wakup_source_activate - Mark given wakeup source as active.
+ * @ws: Wakeup source to handle.
+ *
+ * Update the @ws' statistics and, if @ws has just been activated, notify the PM
+ * core of the event by incrementing the counter of of wakeup events being
+ * processed.
+ */
+static void wakeup_source_activate(struct wakeup_source *ws)
+{
+ ws->active = true;
+ ws->active_count++;
+ ws->timer_expires = jiffies;
+ ws->last_time = ktime_get();
+
+ atomic_inc(&events_in_progress);
+}
+
+/**
+ * __pm_stay_awake - Notify the PM core of a wakeup event.
+ * @ws: Wakeup source object associated with the source of the event.
+ *
+ * It is safe to call this function from interrupt context.
+ */
+void __pm_stay_awake(struct wakeup_source *ws)
+{
+ unsigned long flags;
+
+ if (!ws)
+ return;
+
+ spin_lock_irqsave(&ws->lock, flags);
+ ws->event_count++;
+ if (!ws->active)
+ wakeup_source_activate(ws);
+ spin_unlock_irqrestore(&ws->lock, flags);
+}
+EXPORT_SYMBOL_GPL(__pm_stay_awake);
+
+/**
* pm_stay_awake - Notify the PM core that a wakeup event is being processed.
* @dev: Device the wakeup event is related to.
*
- * Notify the PM core of a wakeup event (signaled by @dev) by incrementing the
- * counter of wakeup events being processed. If @dev is not NULL, the counter
- * of wakeup events related to @dev is incremented too.
+ * Notify the PM core of a wakeup event (signaled by @dev) by calling
+ * __pm_stay_awake for the @dev's wakeup source object.
*
* Call this function after detecting of a wakeup event if pm_relax() is going
* to be called directly after processing the event (and possibly passing it to
* user space for further processing).
- *
- * It is safe to call this function from interrupt context.
*/
void pm_stay_awake(struct device *dev)
{
unsigned long flags;
- spin_lock_irqsave(&events_lock, flags);
- if (dev)
- dev->power.wakeup_count++;
+ if (!dev)
+ return;
- events_in_progress++;
- spin_unlock_irqrestore(&events_lock, flags);
+ spin_lock_irqsave(&dev->power.lock, flags);
+ __pm_stay_awake(dev->power.wakeup);
+ spin_unlock_irqrestore(&dev->power.lock, flags);
}
+EXPORT_SYMBOL_GPL(pm_stay_awake);
/**
- * pm_relax - Notify the PM core that processing of a wakeup event has ended.
+ * wakup_source_deactivate - Mark given wakeup source as inactive.
+ * @ws: Wakeup source to handle.
*
- * Notify the PM core that a wakeup event has been processed by decrementing
- * the counter of wakeup events being processed and incrementing the counter
- * of registered wakeup events.
+ * Update the @ws' statistics and notify the PM core that the wakeup source has
+ * become inactive by decrementing the counter of wakeup events being processed
+ * and incrementing the counter of registered wakeup events.
+ */
+static void wakeup_source_deactivate(struct wakeup_source *ws)
+{
+ ktime_t duration;
+ ktime_t now;
+
+ ws->relax_count++;
+ /*
+ * __pm_relax() may be called directly or from a timer function.
+ * If it is called directly right after the timer function has been
+ * started, but before the timer function calls __pm_relax(), it is
+ * possible that __pm_stay_awake() will be called in the meantime and
+ * will set ws->active. Then, ws->active may be cleared immediately
+ * by the __pm_relax() called from the timer function, but in such a
+ * case ws->relax_count will be different from ws->active_count.
+ */
+ if (ws->relax_count != ws->active_count) {
+ ws->relax_count--;
+ return;
+ }
+
+ ws->active = false;
+
+ now = ktime_get();
+ duration = ktime_sub(now, ws->last_time);
+ ws->total_time = ktime_add(ws->total_time, duration);
+ if (ktime_to_ns(duration) > ktime_to_ns(ws->max_time))
+ ws->max_time = duration;
+
+ del_timer(&ws->timer);
+
+ /*
+ * event_count has to be incremented before events_in_progress is
+ * modified, so that the callers of pm_check_wakeup_events() and
+ * pm_save_wakeup_count() don't see the old value of event_count and
+ * events_in_progress equal to zero at the same time.
+ */
+ atomic_inc(&event_count);
+ smp_mb__before_atomic_dec();
+ atomic_dec(&events_in_progress);
+}
+
+/**
+ * __pm_relax - Notify the PM core that processing of a wakeup event has ended.
+ * @ws: Wakeup source object associated with the source of the event.
*
* Call this function for wakeup events whose processing started with calling
- * pm_stay_awake().
+ * __pm_stay_awake().
*
* It is safe to call it from interrupt context.
*/
-void pm_relax(void)
+void __pm_relax(struct wakeup_source *ws)
{
unsigned long flags;
- spin_lock_irqsave(&events_lock, flags);
- if (events_in_progress) {
- events_in_progress--;
- event_count++;
- }
- spin_unlock_irqrestore(&events_lock, flags);
+ if (!ws)
+ return;
+
+ spin_lock_irqsave(&ws->lock, flags);
+ if (ws->active)
+ wakeup_source_deactivate(ws);
+ spin_unlock_irqrestore(&ws->lock, flags);
+}
+EXPORT_SYMBOL_GPL(__pm_relax);
+
+/**
+ * pm_relax - Notify the PM core that processing of a wakeup event has ended.
+ * @dev: Device that signaled the event.
+ *
+ * Execute __pm_relax() for the @dev's wakeup source object.
+ */
+void pm_relax(struct device *dev)
+{
+ unsigned long flags;
+
+ if (!dev)
+ return;
+
+ spin_lock_irqsave(&dev->power.lock, flags);
+ __pm_relax(dev->power.wakeup);
+ spin_unlock_irqrestore(&dev->power.lock, flags);
}
+EXPORT_SYMBOL_GPL(pm_relax);
/**
* pm_wakeup_timer_fn - Delayed finalization of a wakeup event.
+ * @data: Address of the wakeup source object associated with the event source.
*
- * Decrease the counter of wakeup events being processed after it was increased
- * by pm_wakeup_event().
+ * Call __pm_relax() for the wakeup source whose address is stored in @data.
*/
static void pm_wakeup_timer_fn(unsigned long data)
{
+ __pm_relax((struct wakeup_source *)data);
+}
+
+/**
+ * __pm_wakeup_event - Notify the PM core of a wakeup event.
+ * @ws: Wakeup source object associated with the event source.
+ * @msec: Anticipated event processing time (in milliseconds).
+ *
+ * Notify the PM core of a wakeup event whose source is @ws that will take
+ * approximately @msec milliseconds to be processed by the kernel. If @ws is
+ * not active, activate it. If @msec is nonzero, set up the @ws' timer to
+ * execute pm_wakeup_timer_fn() in future.
+ *
+ * It is safe to call this function from interrupt context.
+ */
+void __pm_wakeup_event(struct wakeup_source *ws, unsigned int msec)
+{
unsigned long flags;
+ unsigned long expires;
- spin_lock_irqsave(&events_lock, flags);
- if (events_timer_expires
- && time_before_eq(events_timer_expires, jiffies)) {
- events_in_progress--;
- events_timer_expires = 0;
+ if (!ws)
+ return;
+
+ spin_lock_irqsave(&ws->lock, flags);
+
+ ws->event_count++;
+ if (!ws->active)
+ wakeup_source_activate(ws);
+
+ if (!msec) {
+ wakeup_source_deactivate(ws);
+ goto unlock;
}
- spin_unlock_irqrestore(&events_lock, flags);
+
+ expires = jiffies + msecs_to_jiffies(msec);
+ if (!expires)
+ expires = 1;
+
+ if (time_after(expires, ws->timer_expires)) {
+ mod_timer(&ws->timer, expires);
+ ws->timer_expires = expires;
+ }
+
+ unlock:
+ spin_unlock_irqrestore(&ws->lock, flags);
}
+EXPORT_SYMBOL_GPL(__pm_wakeup_event);
+
/**
* pm_wakeup_event - Notify the PM core of a wakeup event.
* @dev: Device the wakeup event is related to.
* @msec: Anticipated event processing time (in milliseconds).
*
- * Notify the PM core of a wakeup event (signaled by @dev) that will take
- * approximately @msec milliseconds to be processed by the kernel. Increment
- * the counter of registered wakeup events and (if @msec is nonzero) set up
- * the wakeup events timer to execute pm_wakeup_timer_fn() in future (if the
- * timer has not been set up already, increment the counter of wakeup events
- * being processed). If @dev is not NULL, the counter of wakeup events related
- * to @dev is incremented too.
- *
- * It is safe to call this function from interrupt context.
+ * Call __pm_wakeup_event() for the @dev's wakeup source object.
*/
void pm_wakeup_event(struct device *dev, unsigned int msec)
{
unsigned long flags;
- spin_lock_irqsave(&events_lock, flags);
- event_count++;
- if (dev)
- dev->power.wakeup_count++;
-
- if (msec) {
- unsigned long expires;
+ if (!dev)
+ return;
- expires = jiffies + msecs_to_jiffies(msec);
- if (!expires)
- expires = 1;
+ spin_lock_irqsave(&dev->power.lock, flags);
+ __pm_wakeup_event(dev->power.wakeup, msec);
+ spin_unlock_irqrestore(&dev->power.lock, flags);
+}
+EXPORT_SYMBOL_GPL(pm_wakeup_event);
- if (!events_timer_expires
- || time_after(expires, events_timer_expires)) {
- if (!events_timer_expires)
- events_in_progress++;
+/**
+ * pm_wakeup_update_hit_counts - Update hit counts of all active wakeup sources.
+ */
+static void pm_wakeup_update_hit_counts(void)
+{
+ unsigned long flags;
+ struct wakeup_source *ws;
- mod_timer(&events_timer, expires);
- events_timer_expires = expires;
- }
+ rcu_read_lock();
+ list_for_each_entry_rcu(ws, &wakeup_sources, entry) {
+ spin_lock_irqsave(&ws->lock, flags);
+ if (ws->active)
+ ws->hit_count++;
+ spin_unlock_irqrestore(&ws->lock, flags);
}
- spin_unlock_irqrestore(&events_lock, flags);
+ rcu_read_unlock();
}
/**
@@ -184,10 +556,13 @@ bool pm_check_wakeup_events(void)
spin_lock_irqsave(&events_lock, flags);
if (events_check_enabled) {
- ret = (event_count == saved_event_count) && !events_in_progress;
+ ret = ((unsigned int)atomic_read(&event_count) == saved_count)
+ && !atomic_read(&events_in_progress);
events_check_enabled = ret;
}
spin_unlock_irqrestore(&events_lock, flags);
+ if (!ret)
+ pm_wakeup_update_hit_counts();
return ret;
}
@@ -202,24 +577,20 @@ bool pm_check_wakeup_events(void)
* drop down to zero has been interrupted by a signal (and the current number
* of wakeup events being processed is still nonzero). Otherwise return true.
*/
-bool pm_get_wakeup_count(unsigned long *count)
+bool pm_get_wakeup_count(unsigned int *count)
{
bool ret;
- spin_lock_irq(&events_lock);
if (capable(CAP_SYS_ADMIN))
events_check_enabled = false;
- while (events_in_progress && !signal_pending(current)) {
- spin_unlock_irq(&events_lock);
-
- schedule_timeout_interruptible(msecs_to_jiffies(100));
-
- spin_lock_irq(&events_lock);
+ while (atomic_read(&events_in_progress) && !signal_pending(current)) {
+ pm_wakeup_update_hit_counts();
+ schedule_timeout_interruptible(msecs_to_jiffies(TIMEOUT));
}
- *count = event_count;
- ret = !events_in_progress;
- spin_unlock_irq(&events_lock);
+
+ ret = !atomic_read(&events_in_progress);
+ *count = atomic_read(&event_count);
return ret;
}
@@ -232,16 +603,102 @@ bool pm_get_wakeup_count(unsigned long *count)
* old number of registered wakeup events to be used by pm_check_wakeup_events()
* and return true. Otherwise return false.
*/
-bool pm_save_wakeup_count(unsigned long count)
+bool pm_save_wakeup_count(unsigned int count)
{
bool ret = false;
spin_lock_irq(&events_lock);
- if (count == event_count && !events_in_progress) {
- saved_event_count = count;
+ if (count == (unsigned int)atomic_read(&event_count)
+ && !atomic_read(&events_in_progress)) {
+ saved_count = count;
events_check_enabled = true;
ret = true;
}
spin_unlock_irq(&events_lock);
+ if (!ret)
+ pm_wakeup_update_hit_counts();
+ return ret;
+}
+
+static struct dentry *wakeup_sources_stats_dentry;
+
+/**
+ * print_wakeup_source_stats - Print wakeup source statistics information.
+ * @m: seq_file to print the statistics into.
+ * @ws: Wakeup source object to print the statistics for.
+ */
+static int print_wakeup_source_stats(struct seq_file *m,
+ struct wakeup_source *ws)
+{
+ unsigned long flags;
+ ktime_t total_time;
+ ktime_t max_time;
+ unsigned long active_count;
+ ktime_t active_time;
+ int ret;
+
+ spin_lock_irqsave(&ws->lock, flags);
+
+ total_time = ws->total_time;
+ max_time = ws->max_time;
+ active_count = ws->active_count;
+ if (ws->active) {
+ active_time = ktime_sub(ktime_get(), ws->last_time);
+ total_time = ktime_add(total_time, active_time);
+ if (active_time.tv64 > max_time.tv64)
+ max_time = active_time;
+ } else {
+ active_time = ktime_set(0, 0);
+ }
+
+ ret = seq_printf(m, "%-12s\t%lu\t\t%lu\t\t%lu\t\t"
+ "%lld\t\t%lld\t\t%lld\t\t%lld\n",
+ ws->name, active_count, ws->event_count, ws->hit_count,
+ ktime_to_ms(active_time), ktime_to_ms(total_time),
+ ktime_to_ms(max_time), ktime_to_ms(ws->last_time));
+
+ spin_unlock_irqrestore(&ws->lock, flags);
+
return ret;
}
+
+/**
+ * wakeup_sources_stats_show - Print wakeup sources statistics information.
+ * @m: seq_file to print the statistics into.
+ */
+static int wakeup_sources_stats_show(struct seq_file *m, void *unused)
+{
+ struct wakeup_source *ws;
+
+ seq_puts(m, "name\t\tactive_count\tevent_count\thit_count\t"
+ "active_since\ttotal_time\tmax_time\tlast_change\n");
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(ws, &wakeup_sources, entry)
+ print_wakeup_source_stats(m, ws);
+ rcu_read_unlock();
+
+ return 0;
+}
+
+static int wakeup_sources_stats_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, wakeup_sources_stats_show, NULL);
+}
+
+static const struct file_operations wakeup_sources_stats_fops = {
+ .owner = THIS_MODULE,
+ .open = wakeup_sources_stats_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int __init wakeup_sources_debugfs_init(void)
+{
+ wakeup_sources_stats_dentry = debugfs_create_file("wakeup_sources",
+ S_IRUGO, NULL, NULL, &wakeup_sources_stats_fops);
+ return 0;
+}
+
+postcore_initcall(wakeup_sources_debugfs_init);
diff --git a/drivers/base/sys.c b/drivers/base/sys.c
index 9354dc10a363..1667aaf4fde6 100644
--- a/drivers/base/sys.c
+++ b/drivers/base/sys.c
@@ -432,13 +432,13 @@ int sysdev_suspend(pm_message_t state)
/* resume current sysdev */
cls_driver:
drv = NULL;
- printk(KERN_ERR "Class suspend failed for %s\n",
- kobject_name(&sysdev->kobj));
+ printk(KERN_ERR "Class suspend failed for %s: %d\n",
+ kobject_name(&sysdev->kobj), ret);
aux_driver:
if (drv)
- printk(KERN_ERR "Class driver suspend failed for %s\n",
- kobject_name(&sysdev->kobj));
+ printk(KERN_ERR "Class driver suspend failed for %s: %d\n",
+ kobject_name(&sysdev->kobj), ret);
list_for_each_entry(err_drv, &cls->drivers, entry) {
if (err_drv == drv)
break;
diff --git a/drivers/base/topology.c b/drivers/base/topology.c
index 9fc630ce1ddb..f6f37a05a0c3 100644
--- a/drivers/base/topology.c
+++ b/drivers/base/topology.c
@@ -45,7 +45,8 @@ static ssize_t show_##name(struct sys_device *dev, \
return sprintf(buf, "%d\n", topology_##name(cpu)); \
}
-#if defined(topology_thread_cpumask) || defined(topology_core_cpumask)
+#if defined(topology_thread_cpumask) || defined(topology_core_cpumask) || \
+ defined(topology_book_cpumask)
static ssize_t show_cpumap(int type, const struct cpumask *mask, char *buf)
{
ptrdiff_t len = PTR_ALIGN(buf + PAGE_SIZE - 1, PAGE_SIZE) - buf;
@@ -114,6 +115,14 @@ define_siblings_show_func(core_cpumask);
define_one_ro_named(core_siblings, show_core_cpumask);
define_one_ro_named(core_siblings_list, show_core_cpumask_list);
+#ifdef CONFIG_SCHED_BOOK
+define_id_show_func(book_id);
+define_one_ro(book_id);
+define_siblings_show_func(book_cpumask);
+define_one_ro_named(book_siblings, show_book_cpumask);
+define_one_ro_named(book_siblings_list, show_book_cpumask_list);
+#endif
+
static struct attribute *default_attrs[] = {
&attr_physical_package_id.attr,
&attr_core_id.attr,
@@ -121,6 +130,11 @@ static struct attribute *default_attrs[] = {
&attr_thread_siblings_list.attr,
&attr_core_siblings.attr,
&attr_core_siblings_list.attr,
+#ifdef CONFIG_SCHED_BOOK
+ &attr_book_id.attr,
+ &attr_book_siblings.attr,
+ &attr_book_siblings_list.attr,
+#endif
NULL
};
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index 4e2c367fec11..1f286ab461d3 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -36,7 +36,7 @@
#include <linux/ioport.h>
#include <linux/mm.h>
#include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/reboot.h>
@@ -54,6 +54,7 @@
#define DAC960_GAM_MINOR 252
+static DEFINE_MUTEX(DAC960_mutex);
static DAC960_Controller_T *DAC960_Controllers[DAC960_MaxControllers];
static int DAC960_ControllerCount;
static struct proc_dir_entry *DAC960_ProcDirectoryEntry;
@@ -81,7 +82,7 @@ static int DAC960_open(struct block_device *bdev, fmode_t mode)
int drive_nr = (long)disk->private_data;
int ret = -ENXIO;
- lock_kernel();
+ mutex_lock(&DAC960_mutex);
if (p->FirmwareType == DAC960_V1_Controller) {
if (p->V1.LogicalDriveInformation[drive_nr].
LogicalDriveState == DAC960_V1_LogicalDrive_Offline)
@@ -99,7 +100,7 @@ static int DAC960_open(struct block_device *bdev, fmode_t mode)
goto out;
ret = 0;
out:
- unlock_kernel();
+ mutex_unlock(&DAC960_mutex);
return ret;
}
@@ -6625,7 +6626,7 @@ static long DAC960_gam_ioctl(struct file *file, unsigned int Request,
long ErrorCode = 0;
if (!capable(CAP_SYS_ADMIN)) return -EACCES;
- lock_kernel();
+ mutex_lock(&DAC960_mutex);
switch (Request)
{
case DAC960_IOCTL_GET_CONTROLLER_COUNT:
@@ -7056,13 +7057,14 @@ static long DAC960_gam_ioctl(struct file *file, unsigned int Request,
default:
ErrorCode = -ENOTTY;
}
- unlock_kernel();
+ mutex_unlock(&DAC960_mutex);
return ErrorCode;
}
static const struct file_operations DAC960_gam_fops = {
.owner = THIS_MODULE,
- .unlocked_ioctl = DAC960_gam_ioctl
+ .unlocked_ioctl = DAC960_gam_ioctl,
+ .llseek = noop_llseek,
};
static struct miscdevice DAC960_gam_dev = {
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index de277689da61..4b9359a6f6ca 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -488,4 +488,21 @@ config BLK_DEV_HD
If unsure, say N.
+config BLK_DEV_RBD
+ tristate "Rados block device (RBD)"
+ depends on INET && EXPERIMENTAL && BLOCK
+ select CEPH_LIB
+ select LIBCRC32C
+ select CRYPTO_AES
+ select CRYPTO
+ default n
+ help
+ Say Y here if you want include the Rados block device, which stripes
+ a block device over objects stored in the Ceph distributed object
+ store.
+
+ More information at http://ceph.newdream.net/.
+
+ If unsure, say N.
+
endif # BLK_DEV
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index aff5ac925c34..d7f463d6312d 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -37,5 +37,6 @@ obj-$(CONFIG_BLK_DEV_HD) += hd.o
obj-$(CONFIG_XEN_BLKDEV_FRONTEND) += xen-blkfront.o
obj-$(CONFIG_BLK_DEV_DRBD) += drbd/
+obj-$(CONFIG_BLK_DEV_RBD) += rbd.o
swim_mod-objs := swim.o swim_asm.o
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c
index 76f114f0bba3..a1725e6488d3 100644
--- a/drivers/block/amiflop.c
+++ b/drivers/block/amiflop.c
@@ -60,7 +60,7 @@
#include <linux/hdreg.h>
#include <linux/delay.h>
#include <linux/init.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/amifdreg.h>
#include <linux/amifd.h>
#include <linux/buffer_head.h>
@@ -109,13 +109,12 @@
#define FD_HD_3 0x55555555 /* high-density 3.5" (1760K) drive */
#define FD_DD_5 0xaaaaaaaa /* double-density 5.25" (440K) drive */
+static DEFINE_MUTEX(amiflop_mutex);
static unsigned long int fd_def_df0 = FD_DD_3; /* default for df0 if it doesn't identify */
module_param(fd_def_df0, ulong, 0);
MODULE_LICENSE("GPL");
-static struct request_queue *floppy_queue;
-
/*
* Macros
*/
@@ -164,6 +163,7 @@ static volatile int selected = -1; /* currently selected drive */
static int writepending;
static int writefromint;
static char *raw_buf;
+static int fdc_queue;
static DEFINE_SPINLOCK(amiflop_lock);
@@ -1334,6 +1334,42 @@ static int get_track(int drive, int track)
return -1;
}
+/*
+ * Round-robin between our available drives, doing one request from each
+ */
+static struct request *set_next_request(void)
+{
+ struct request_queue *q;
+ int cnt = FD_MAX_UNITS;
+ struct request *rq;
+
+ /* Find next queue we can dispatch from */
+ fdc_queue = fdc_queue + 1;
+ if (fdc_queue == FD_MAX_UNITS)
+ fdc_queue = 0;
+
+ for(cnt = FD_MAX_UNITS; cnt > 0; cnt--) {
+
+ if (unit[fdc_queue].type->code == FD_NODRIVE) {
+ if (++fdc_queue == FD_MAX_UNITS)
+ fdc_queue = 0;
+ continue;
+ }
+
+ q = unit[fdc_queue].gendisk->queue;
+ if (q) {
+ rq = blk_fetch_request(q);
+ if (rq)
+ break;
+ }
+
+ if (++fdc_queue == FD_MAX_UNITS)
+ fdc_queue = 0;
+ }
+
+ return rq;
+}
+
static void redo_fd_request(void)
{
struct request *rq;
@@ -1345,7 +1381,7 @@ static void redo_fd_request(void)
int err;
next_req:
- rq = blk_fetch_request(floppy_queue);
+ rq = set_next_request();
if (!rq) {
/* Nothing left to do */
return;
@@ -1506,9 +1542,9 @@ static int fd_ioctl(struct block_device *bdev, fmode_t mode,
{
int ret;
- lock_kernel();
+ mutex_lock(&amiflop_mutex);
ret = fd_locked_ioctl(bdev, mode, cmd, param);
- unlock_kernel();
+ mutex_unlock(&amiflop_mutex);
return ret;
}
@@ -1555,11 +1591,11 @@ static int floppy_open(struct block_device *bdev, fmode_t mode)
int old_dev;
unsigned long flags;
- lock_kernel();
+ mutex_lock(&amiflop_mutex);
old_dev = fd_device[drive];
if (fd_ref[drive] && old_dev != system) {
- unlock_kernel();
+ mutex_unlock(&amiflop_mutex);
return -EBUSY;
}
@@ -1575,7 +1611,7 @@ static int floppy_open(struct block_device *bdev, fmode_t mode)
rel_fdc();
if (wrprot) {
- unlock_kernel();
+ mutex_unlock(&amiflop_mutex);
return -EROFS;
}
}
@@ -1594,7 +1630,7 @@ static int floppy_open(struct block_device *bdev, fmode_t mode)
printk(KERN_INFO "fd%d: accessing %s-disk with %s-layout\n",drive,
unit[drive].type->name, data_types[system].name);
- unlock_kernel();
+ mutex_unlock(&amiflop_mutex);
return 0;
}
@@ -1603,7 +1639,7 @@ static int floppy_release(struct gendisk *disk, fmode_t mode)
struct amiga_floppy_struct *p = disk->private_data;
int drive = p - unit;
- lock_kernel();
+ mutex_lock(&amiflop_mutex);
if (unit[drive].dirty == 1) {
del_timer (flush_track_timer + drive);
non_int_flush_track (drive);
@@ -1617,7 +1653,7 @@ static int floppy_release(struct gendisk *disk, fmode_t mode)
/* the mod_use counter is handled this way */
floppy_off (drive | 0x40000000);
#endif
- unlock_kernel();
+ mutex_unlock(&amiflop_mutex);
return 0;
}
@@ -1682,6 +1718,13 @@ static int __init fd_probe_drives(void)
continue;
}
unit[drive].gendisk = disk;
+
+ disk->queue = blk_init_queue(do_fd_request, &amiflop_lock);
+ if (!disk->queue) {
+ unit[drive].type->code = FD_NODRIVE;
+ continue;
+ }
+
drives++;
if ((unit[drive].trackbuf = kmalloc(FLOPPY_MAX_SECTORS * 512, GFP_KERNEL)) == NULL) {
printk("no mem for ");
@@ -1695,7 +1738,6 @@ static int __init fd_probe_drives(void)
disk->fops = &floppy_fops;
sprintf(disk->disk_name, "fd%d", drive);
disk->private_data = &unit[drive];
- disk->queue = floppy_queue;
set_capacity(disk, 880*2);
add_disk(disk);
}
@@ -1743,11 +1785,6 @@ static int __init amiga_floppy_probe(struct platform_device *pdev)
goto out_irq2;
}
- ret = -ENOMEM;
- floppy_queue = blk_init_queue(do_fd_request, &amiflop_lock);
- if (!floppy_queue)
- goto out_queue;
-
ret = -ENODEV;
if (fd_probe_drives() < 1) /* No usable drives */
goto out_probe;
@@ -1791,8 +1828,6 @@ static int __init amiga_floppy_probe(struct platform_device *pdev)
return 0;
out_probe:
- blk_cleanup_queue(floppy_queue);
-out_queue:
free_irq(IRQ_AMIGA_CIAA_TB, NULL);
out_irq2:
free_irq(IRQ_AMIGA_DSKBLK, NULL);
@@ -1810,9 +1845,12 @@ static int __exit amiga_floppy_remove(struct platform_device *pdev)
for( i = 0; i < FD_MAX_UNITS; i++) {
if (unit[i].type->code != FD_NODRIVE) {
+ struct request_queue *q = unit[i].gendisk->queue;
del_gendisk(unit[i].gendisk);
put_disk(unit[i].gendisk);
kfree(unit[i].trackbuf);
+ if (q)
+ blk_cleanup_queue(q);
}
}
blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
@@ -1820,7 +1858,6 @@ static int __exit amiga_floppy_remove(struct platform_device *pdev)
free_irq(IRQ_AMIGA_DSKBLK, NULL);
custom.dmacon = DMAF_DISK; /* disable DMA */
amiga_chip_free(raw_buf);
- blk_cleanup_queue(floppy_queue);
unregister_blkdev(FLOPPY_MAJOR, "fd");
}
#endif
diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c
index a946929735a5..f21c237a9e5e 100644
--- a/drivers/block/aoe/aoeblk.c
+++ b/drivers/block/aoe/aoeblk.c
@@ -12,9 +12,10 @@
#include <linux/slab.h>
#include <linux/genhd.h>
#include <linux/netdevice.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include "aoe.h"
+static DEFINE_MUTEX(aoeblk_mutex);
static struct kmem_cache *buf_pool_cache;
static ssize_t aoedisk_show_state(struct device *dev,
@@ -125,16 +126,16 @@ aoeblk_open(struct block_device *bdev, fmode_t mode)
struct aoedev *d = bdev->bd_disk->private_data;
ulong flags;
- lock_kernel();
+ mutex_lock(&aoeblk_mutex);
spin_lock_irqsave(&d->lock, flags);
if (d->flags & DEVFL_UP) {
d->nopen++;
spin_unlock_irqrestore(&d->lock, flags);
- unlock_kernel();
+ mutex_unlock(&aoeblk_mutex);
return 0;
}
spin_unlock_irqrestore(&d->lock, flags);
- unlock_kernel();
+ mutex_unlock(&aoeblk_mutex);
return -ENODEV;
}
diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c
index 4a1b9e7464aa..146296ca4965 100644
--- a/drivers/block/aoe/aoechr.c
+++ b/drivers/block/aoe/aoechr.c
@@ -9,7 +9,7 @@
#include <linux/completion.h>
#include <linux/delay.h>
#include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/skbuff.h>
#include "aoe.h"
@@ -37,6 +37,7 @@ struct ErrMsg {
char *msg;
};
+static DEFINE_MUTEX(aoechr_mutex);
static struct ErrMsg emsgs[NMSG];
static int emsgs_head_idx, emsgs_tail_idx;
static struct completion emsgs_comp;
@@ -183,16 +184,16 @@ aoechr_open(struct inode *inode, struct file *filp)
{
int n, i;
- lock_kernel();
+ mutex_lock(&aoechr_mutex);
n = iminor(inode);
filp->private_data = (void *) (unsigned long) n;
for (i = 0; i < ARRAY_SIZE(chardevs); ++i)
if (chardevs[i].minor == n) {
- unlock_kernel();
+ mutex_unlock(&aoechr_mutex);
return 0;
}
- unlock_kernel();
+ mutex_unlock(&aoechr_mutex);
return -EINVAL;
}
@@ -265,6 +266,7 @@ static const struct file_operations aoe_fops = {
.open = aoechr_open,
.release = aoechr_rel,
.owner = THIS_MODULE,
+ .llseek = noop_llseek,
};
static char *aoe_devnode(struct device *dev, mode_t *mode)
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c
index aceb96476524..4e4cc6c828cb 100644
--- a/drivers/block/ataflop.c
+++ b/drivers/block/ataflop.c
@@ -67,7 +67,7 @@
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/blkdev.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <asm/atafd.h>
#include <asm/atafdreg.h>
@@ -79,8 +79,9 @@
#undef DEBUG
-static struct request_queue *floppy_queue;
+static DEFINE_MUTEX(ataflop_mutex);
static struct request *fd_request;
+static int fdc_queue;
/* Disk types: DD, HD, ED */
static struct atari_disk_type {
@@ -1391,6 +1392,29 @@ static void setup_req_params( int drive )
ReqTrack, ReqSector, (unsigned long)ReqData ));
}
+/*
+ * Round-robin between our available drives, doing one request from each
+ */
+static struct request *set_next_request(void)
+{
+ struct request_queue *q;
+ int old_pos = fdc_queue;
+ struct request *rq;
+
+ do {
+ q = unit[fdc_queue].disk->queue;
+ if (++fdc_queue == FD_MAX_UNITS)
+ fdc_queue = 0;
+ if (q) {
+ rq = blk_fetch_request(q);
+ if (rq)
+ break;
+ }
+ } while (fdc_queue != old_pos);
+
+ return rq;
+}
+
static void redo_fd_request(void)
{
@@ -1405,7 +1429,7 @@ static void redo_fd_request(void)
repeat:
if (!fd_request) {
- fd_request = blk_fetch_request(floppy_queue);
+ fd_request = set_next_request();
if (!fd_request)
goto the_end;
}
@@ -1671,9 +1695,9 @@ static int fd_ioctl(struct block_device *bdev, fmode_t mode,
{
int ret;
- lock_kernel();
+ mutex_lock(&ataflop_mutex);
ret = fd_locked_ioctl(bdev, mode, cmd, arg);
- unlock_kernel();
+ mutex_unlock(&ataflop_mutex);
return ret;
}
@@ -1854,9 +1878,9 @@ static int floppy_unlocked_open(struct block_device *bdev, fmode_t mode)
{
int ret;
- lock_kernel();
+ mutex_lock(&ataflop_mutex);
ret = floppy_open(bdev, mode);
- unlock_kernel();
+ mutex_unlock(&ataflop_mutex);
return ret;
}
@@ -1864,14 +1888,14 @@ static int floppy_unlocked_open(struct block_device *bdev, fmode_t mode)
static int floppy_release(struct gendisk *disk, fmode_t mode)
{
struct atari_floppy_struct *p = disk->private_data;
- lock_kernel();
+ mutex_lock(&ataflop_mutex);
if (p->ref < 0)
p->ref = 0;
else if (!p->ref--) {
printk(KERN_ERR "floppy_release with fd_ref == 0");
p->ref = 0;
}
- unlock_kernel();
+ mutex_unlock(&ataflop_mutex);
return 0;
}
@@ -1932,10 +1956,6 @@ static int __init atari_floppy_init (void)
PhysTrackBuffer = virt_to_phys(TrackBuffer);
BufferDrive = BufferSide = BufferTrack = -1;
- floppy_queue = blk_init_queue(do_fd_request, &ataflop_lock);
- if (!floppy_queue)
- goto Enomem;
-
for (i = 0; i < FD_MAX_UNITS; i++) {
unit[i].track = -1;
unit[i].flags = 0;
@@ -1944,7 +1964,10 @@ static int __init atari_floppy_init (void)
sprintf(unit[i].disk->disk_name, "fd%d", i);
unit[i].disk->fops = &floppy_fops;
unit[i].disk->private_data = &unit[i];
- unit[i].disk->queue = floppy_queue;
+ unit[i].disk->queue = blk_init_queue(do_fd_request,
+ &ataflop_lock);
+ if (!unit[i].disk->queue)
+ goto Enomem;
set_capacity(unit[i].disk, MAX_DISK_SIZE * 2);
add_disk(unit[i].disk);
}
@@ -1959,10 +1982,14 @@ static int __init atari_floppy_init (void)
return 0;
Enomem:
- while (i--)
+ while (i--) {
+ struct request_queue *q = unit[i].disk->queue;
+
put_disk(unit[i].disk);
- if (floppy_queue)
- blk_cleanup_queue(floppy_queue);
+ if (q)
+ blk_cleanup_queue(q);
+ }
+
unregister_blkdev(FLOPPY_MAJOR, "fd");
return -ENOMEM;
}
@@ -2011,12 +2038,14 @@ static void __exit atari_floppy_exit(void)
int i;
blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
for (i = 0; i < FD_MAX_UNITS; i++) {
+ struct request_queue *q = unit[i].disk->queue;
+
del_gendisk(unit[i].disk);
put_disk(unit[i].disk);
+ blk_cleanup_queue(q);
}
unregister_blkdev(FLOPPY_MAJOR, "fd");
- blk_cleanup_queue(floppy_queue);
del_timer_sync(&fd_timer);
atari_stram_free( DMABuffer );
}
diff --git a/drivers/block/brd.c b/drivers/block/brd.c
index 1c7f63792ff8..b7f51e4594f8 100644
--- a/drivers/block/brd.c
+++ b/drivers/block/brd.c
@@ -15,7 +15,7 @@
#include <linux/blkdev.h>
#include <linux/bio.h>
#include <linux/highmem.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/radix-tree.h>
#include <linux/buffer_head.h> /* invalidate_bh_lrus() */
#include <linux/slab.h>
@@ -55,6 +55,7 @@ struct brd_device {
/*
* Look up and return a brd's page for a given sector.
*/
+static DEFINE_MUTEX(brd_mutex);
static struct page *brd_lookup_page(struct brd_device *brd, sector_t sector)
{
pgoff_t idx;
@@ -402,7 +403,7 @@ static int brd_ioctl(struct block_device *bdev, fmode_t mode,
* ram device BLKFLSBUF has special semantics, we want to actually
* release and destroy the ramdisk data.
*/
- lock_kernel();
+ mutex_lock(&brd_mutex);
mutex_lock(&bdev->bd_mutex);
error = -EBUSY;
if (bdev->bd_openers <= 1) {
@@ -419,7 +420,7 @@ static int brd_ioctl(struct block_device *bdev, fmode_t mode,
error = 0;
}
mutex_unlock(&bdev->bd_mutex);
- unlock_kernel();
+ mutex_unlock(&brd_mutex);
return error;
}
@@ -482,7 +483,6 @@ static struct brd_device *brd_alloc(int i)
if (!brd->brd_queue)
goto out_free_dev;
blk_queue_make_request(brd->brd_queue, brd_make_request);
- blk_queue_ordered(brd->brd_queue, QUEUE_ORDERED_TAG);
blk_queue_max_hw_sectors(brd->brd_queue, 1024);
blk_queue_bounce_limit(brd->brd_queue, BLK_BOUNCE_ANY);
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 5e4fadcdece9..f09e6df15aa7 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -26,7 +26,6 @@
#include <linux/pci.h>
#include <linux/kernel.h>
#include <linux/slab.h>
-#include <linux/smp_lock.h>
#include <linux/delay.h>
#include <linux/major.h>
#include <linux/fs.h>
@@ -66,6 +65,7 @@ MODULE_SUPPORTED_DEVICE("HP Smart Array Controllers");
MODULE_VERSION("3.6.26");
MODULE_LICENSE("GPL");
+static DEFINE_MUTEX(cciss_mutex);
static int cciss_allow_hpsa;
module_param(cciss_allow_hpsa, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(cciss_allow_hpsa,
@@ -105,11 +105,12 @@ static const struct pci_device_id cciss_pci_device_id[] = {
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3249},
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x324A},
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x324B},
- {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3250},
- {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3251},
- {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3252},
- {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3253},
- {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3254},
+ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSF, 0x103C, 0x3350},
+ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSF, 0x103C, 0x3351},
+ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSF, 0x103C, 0x3352},
+ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSF, 0x103C, 0x3353},
+ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSF, 0x103C, 0x3354},
+ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSF, 0x103C, 0x3355},
{0,}
};
@@ -149,11 +150,12 @@ static struct board_type products[] = {
{0x3249103C, "Smart Array P812", &SA5_access},
{0x324A103C, "Smart Array P712m", &SA5_access},
{0x324B103C, "Smart Array P711m", &SA5_access},
- {0x3250103C, "Smart Array", &SA5_access},
- {0x3251103C, "Smart Array", &SA5_access},
- {0x3252103C, "Smart Array", &SA5_access},
- {0x3253103C, "Smart Array", &SA5_access},
- {0x3254103C, "Smart Array", &SA5_access},
+ {0x3350103C, "Smart Array", &SA5_access},
+ {0x3351103C, "Smart Array", &SA5_access},
+ {0x3352103C, "Smart Array", &SA5_access},
+ {0x3353103C, "Smart Array", &SA5_access},
+ {0x3354103C, "Smart Array", &SA5_access},
+ {0x3355103C, "Smart Array", &SA5_access},
};
/* How long to wait (in milliseconds) for board to go into simple mode */
@@ -1059,9 +1061,9 @@ static int cciss_unlocked_open(struct block_device *bdev, fmode_t mode)
{
int ret;
- lock_kernel();
+ mutex_lock(&cciss_mutex);
ret = cciss_open(bdev, mode);
- unlock_kernel();
+ mutex_unlock(&cciss_mutex);
return ret;
}
@@ -1074,13 +1076,13 @@ static int cciss_release(struct gendisk *disk, fmode_t mode)
ctlr_info_t *h;
drive_info_struct *drv;
- lock_kernel();
+ mutex_lock(&cciss_mutex);
h = get_host(disk);
drv = get_drv(disk);
dev_dbg(&h->pdev->dev, "cciss_release %s\n", disk->disk_name);
drv->usage_count--;
h->usage_count--;
- unlock_kernel();
+ mutex_unlock(&cciss_mutex);
return 0;
}
@@ -1088,9 +1090,9 @@ static int do_ioctl(struct block_device *bdev, fmode_t mode,
unsigned cmd, unsigned long arg)
{
int ret;
- lock_kernel();
+ mutex_lock(&cciss_mutex);
ret = cciss_ioctl(bdev, mode, cmd, arg);
- unlock_kernel();
+ mutex_unlock(&cciss_mutex);
return ret;
}
@@ -1232,470 +1234,452 @@ static void check_ioctl_unit_attention(ctlr_info_t *h, CommandList_struct *c)
c->err_info->ScsiStatus != SAM_STAT_CHECK_CONDITION)
(void)check_for_unit_attention(h, c);
}
-/*
- * ioctl
- */
-static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
- unsigned int cmd, unsigned long arg)
+
+static int cciss_getpciinfo(ctlr_info_t *h, void __user *argp)
{
- struct gendisk *disk = bdev->bd_disk;
- ctlr_info_t *h = get_host(disk);
- drive_info_struct *drv = get_drv(disk);
- void __user *argp = (void __user *)arg;
+ cciss_pci_info_struct pciinfo;
- dev_dbg(&h->pdev->dev, "cciss_ioctl: Called with cmd=%x %lx\n",
- cmd, arg);
- switch (cmd) {
- case CCISS_GETPCIINFO:
- {
- cciss_pci_info_struct pciinfo;
-
- if (!arg)
- return -EINVAL;
- pciinfo.domain = pci_domain_nr(h->pdev->bus);
- pciinfo.bus = h->pdev->bus->number;
- pciinfo.dev_fn = h->pdev->devfn;
- pciinfo.board_id = h->board_id;
- if (copy_to_user
- (argp, &pciinfo, sizeof(cciss_pci_info_struct)))
- return -EFAULT;
- return 0;
- }
- case CCISS_GETINTINFO:
- {
- cciss_coalint_struct intinfo;
- if (!arg)
- return -EINVAL;
- intinfo.delay =
- readl(&h->cfgtable->HostWrite.CoalIntDelay);
- intinfo.count =
- readl(&h->cfgtable->HostWrite.CoalIntCount);
- if (copy_to_user
- (argp, &intinfo, sizeof(cciss_coalint_struct)))
- return -EFAULT;
- return 0;
- }
- case CCISS_SETINTINFO:
- {
- cciss_coalint_struct intinfo;
- unsigned long flags;
- int i;
-
- if (!arg)
- return -EINVAL;
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
- if (copy_from_user
- (&intinfo, argp, sizeof(cciss_coalint_struct)))
- return -EFAULT;
- if ((intinfo.delay == 0) && (intinfo.count == 0))
- return -EINVAL;
- spin_lock_irqsave(&h->lock, flags);
- /* Update the field, and then ring the doorbell */
- writel(intinfo.delay,
- &(h->cfgtable->HostWrite.CoalIntDelay));
- writel(intinfo.count,
- &(h->cfgtable->HostWrite.CoalIntCount));
- writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL);
-
- for (i = 0; i < MAX_IOCTL_CONFIG_WAIT; i++) {
- if (!(readl(h->vaddr + SA5_DOORBELL)
- & CFGTBL_ChangeReq))
- break;
- /* delay and try again */
- udelay(1000);
- }
- spin_unlock_irqrestore(&h->lock, flags);
- if (i >= MAX_IOCTL_CONFIG_WAIT)
- return -EAGAIN;
- return 0;
- }
- case CCISS_GETNODENAME:
- {
- NodeName_type NodeName;
- int i;
-
- if (!arg)
- return -EINVAL;
- for (i = 0; i < 16; i++)
- NodeName[i] =
- readb(&h->cfgtable->ServerName[i]);
- if (copy_to_user(argp, NodeName, sizeof(NodeName_type)))
- return -EFAULT;
- return 0;
- }
- case CCISS_SETNODENAME:
- {
- NodeName_type NodeName;
- unsigned long flags;
- int i;
+ if (!argp)
+ return -EINVAL;
+ pciinfo.domain = pci_domain_nr(h->pdev->bus);
+ pciinfo.bus = h->pdev->bus->number;
+ pciinfo.dev_fn = h->pdev->devfn;
+ pciinfo.board_id = h->board_id;
+ if (copy_to_user(argp, &pciinfo, sizeof(cciss_pci_info_struct)))
+ return -EFAULT;
+ return 0;
+}
- if (!arg)
- return -EINVAL;
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
+static int cciss_getintinfo(ctlr_info_t *h, void __user *argp)
+{
+ cciss_coalint_struct intinfo;
- if (copy_from_user
- (NodeName, argp, sizeof(NodeName_type)))
- return -EFAULT;
+ if (!argp)
+ return -EINVAL;
+ intinfo.delay = readl(&h->cfgtable->HostWrite.CoalIntDelay);
+ intinfo.count = readl(&h->cfgtable->HostWrite.CoalIntCount);
+ if (copy_to_user
+ (argp, &intinfo, sizeof(cciss_coalint_struct)))
+ return -EFAULT;
+ return 0;
+}
- spin_lock_irqsave(&h->lock, flags);
+static int cciss_setintinfo(ctlr_info_t *h, void __user *argp)
+{
+ cciss_coalint_struct intinfo;
+ unsigned long flags;
+ int i;
- /* Update the field, and then ring the doorbell */
- for (i = 0; i < 16; i++)
- writeb(NodeName[i],
- &h->cfgtable->ServerName[i]);
+ if (!argp)
+ return -EINVAL;
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ if (copy_from_user(&intinfo, argp, sizeof(intinfo)))
+ return -EFAULT;
+ if ((intinfo.delay == 0) && (intinfo.count == 0))
+ return -EINVAL;
+ spin_lock_irqsave(&h->lock, flags);
+ /* Update the field, and then ring the doorbell */
+ writel(intinfo.delay, &(h->cfgtable->HostWrite.CoalIntDelay));
+ writel(intinfo.count, &(h->cfgtable->HostWrite.CoalIntCount));
+ writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL);
- writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL);
+ for (i = 0; i < MAX_IOCTL_CONFIG_WAIT; i++) {
+ if (!(readl(h->vaddr + SA5_DOORBELL) & CFGTBL_ChangeReq))
+ break;
+ udelay(1000); /* delay and try again */
+ }
+ spin_unlock_irqrestore(&h->lock, flags);
+ if (i >= MAX_IOCTL_CONFIG_WAIT)
+ return -EAGAIN;
+ return 0;
+}
- for (i = 0; i < MAX_IOCTL_CONFIG_WAIT; i++) {
- if (!(readl(h->vaddr + SA5_DOORBELL)
- & CFGTBL_ChangeReq))
- break;
- /* delay and try again */
- udelay(1000);
- }
- spin_unlock_irqrestore(&h->lock, flags);
- if (i >= MAX_IOCTL_CONFIG_WAIT)
- return -EAGAIN;
- return 0;
- }
+static int cciss_getnodename(ctlr_info_t *h, void __user *argp)
+{
+ NodeName_type NodeName;
+ int i;
- case CCISS_GETHEARTBEAT:
- {
- Heartbeat_type heartbeat;
-
- if (!arg)
- return -EINVAL;
- heartbeat = readl(&h->cfgtable->HeartBeat);
- if (copy_to_user
- (argp, &heartbeat, sizeof(Heartbeat_type)))
- return -EFAULT;
- return 0;
- }
- case CCISS_GETBUSTYPES:
- {
- BusTypes_type BusTypes;
-
- if (!arg)
- return -EINVAL;
- BusTypes = readl(&h->cfgtable->BusTypes);
- if (copy_to_user
- (argp, &BusTypes, sizeof(BusTypes_type)))
- return -EFAULT;
- return 0;
- }
- case CCISS_GETFIRMVER:
- {
- FirmwareVer_type firmware;
+ if (!argp)
+ return -EINVAL;
+ for (i = 0; i < 16; i++)
+ NodeName[i] = readb(&h->cfgtable->ServerName[i]);
+ if (copy_to_user(argp, NodeName, sizeof(NodeName_type)))
+ return -EFAULT;
+ return 0;
+}
- if (!arg)
- return -EINVAL;
- memcpy(firmware, h->firm_ver, 4);
+static int cciss_setnodename(ctlr_info_t *h, void __user *argp)
+{
+ NodeName_type NodeName;
+ unsigned long flags;
+ int i;
- if (copy_to_user
- (argp, firmware, sizeof(FirmwareVer_type)))
- return -EFAULT;
- return 0;
- }
- case CCISS_GETDRIVVER:
- {
- DriverVer_type DriverVer = DRIVER_VERSION;
+ if (!argp)
+ return -EINVAL;
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ if (copy_from_user(NodeName, argp, sizeof(NodeName_type)))
+ return -EFAULT;
+ spin_lock_irqsave(&h->lock, flags);
+ /* Update the field, and then ring the doorbell */
+ for (i = 0; i < 16; i++)
+ writeb(NodeName[i], &h->cfgtable->ServerName[i]);
+ writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL);
+ for (i = 0; i < MAX_IOCTL_CONFIG_WAIT; i++) {
+ if (!(readl(h->vaddr + SA5_DOORBELL) & CFGTBL_ChangeReq))
+ break;
+ udelay(1000); /* delay and try again */
+ }
+ spin_unlock_irqrestore(&h->lock, flags);
+ if (i >= MAX_IOCTL_CONFIG_WAIT)
+ return -EAGAIN;
+ return 0;
+}
- if (!arg)
- return -EINVAL;
+static int cciss_getheartbeat(ctlr_info_t *h, void __user *argp)
+{
+ Heartbeat_type heartbeat;
- if (copy_to_user
- (argp, &DriverVer, sizeof(DriverVer_type)))
- return -EFAULT;
- return 0;
- }
+ if (!argp)
+ return -EINVAL;
+ heartbeat = readl(&h->cfgtable->HeartBeat);
+ if (copy_to_user(argp, &heartbeat, sizeof(Heartbeat_type)))
+ return -EFAULT;
+ return 0;
+}
- case CCISS_DEREGDISK:
- case CCISS_REGNEWD:
- case CCISS_REVALIDVOLS:
- return rebuild_lun_table(h, 0, 1);
+static int cciss_getbustypes(ctlr_info_t *h, void __user *argp)
+{
+ BusTypes_type BusTypes;
+
+ if (!argp)
+ return -EINVAL;
+ BusTypes = readl(&h->cfgtable->BusTypes);
+ if (copy_to_user(argp, &BusTypes, sizeof(BusTypes_type)))
+ return -EFAULT;
+ return 0;
+}
- case CCISS_GETLUNINFO:{
- LogvolInfo_struct luninfo;
+static int cciss_getfirmver(ctlr_info_t *h, void __user *argp)
+{
+ FirmwareVer_type firmware;
- memcpy(&luninfo.LunID, drv->LunID,
- sizeof(luninfo.LunID));
- luninfo.num_opens = drv->usage_count;
- luninfo.num_parts = 0;
- if (copy_to_user(argp, &luninfo,
- sizeof(LogvolInfo_struct)))
- return -EFAULT;
- return 0;
+ if (!argp)
+ return -EINVAL;
+ memcpy(firmware, h->firm_ver, 4);
+
+ if (copy_to_user
+ (argp, firmware, sizeof(FirmwareVer_type)))
+ return -EFAULT;
+ return 0;
+}
+
+static int cciss_getdrivver(ctlr_info_t *h, void __user *argp)
+{
+ DriverVer_type DriverVer = DRIVER_VERSION;
+
+ if (!argp)
+ return -EINVAL;
+ if (copy_to_user(argp, &DriverVer, sizeof(DriverVer_type)))
+ return -EFAULT;
+ return 0;
+}
+
+static int cciss_getluninfo(ctlr_info_t *h,
+ struct gendisk *disk, void __user *argp)
+{
+ LogvolInfo_struct luninfo;
+ drive_info_struct *drv = get_drv(disk);
+
+ if (!argp)
+ return -EINVAL;
+ memcpy(&luninfo.LunID, drv->LunID, sizeof(luninfo.LunID));
+ luninfo.num_opens = drv->usage_count;
+ luninfo.num_parts = 0;
+ if (copy_to_user(argp, &luninfo, sizeof(LogvolInfo_struct)))
+ return -EFAULT;
+ return 0;
+}
+
+static int cciss_passthru(ctlr_info_t *h, void __user *argp)
+{
+ IOCTL_Command_struct iocommand;
+ CommandList_struct *c;
+ char *buff = NULL;
+ u64bit temp64;
+ DECLARE_COMPLETION_ONSTACK(wait);
+
+ if (!argp)
+ return -EINVAL;
+
+ if (!capable(CAP_SYS_RAWIO))
+ return -EPERM;
+
+ if (copy_from_user
+ (&iocommand, argp, sizeof(IOCTL_Command_struct)))
+ return -EFAULT;
+ if ((iocommand.buf_size < 1) &&
+ (iocommand.Request.Type.Direction != XFER_NONE)) {
+ return -EINVAL;
+ }
+ if (iocommand.buf_size > 0) {
+ buff = kmalloc(iocommand.buf_size, GFP_KERNEL);
+ if (buff == NULL)
+ return -EFAULT;
+ }
+ if (iocommand.Request.Type.Direction == XFER_WRITE) {
+ /* Copy the data into the buffer we created */
+ if (copy_from_user(buff, iocommand.buf, iocommand.buf_size)) {
+ kfree(buff);
+ return -EFAULT;
}
- case CCISS_PASSTHRU:
- {
- IOCTL_Command_struct iocommand;
- CommandList_struct *c;
- char *buff = NULL;
- u64bit temp64;
- DECLARE_COMPLETION_ONSTACK(wait);
-
- if (!arg)
- return -EINVAL;
-
- if (!capable(CAP_SYS_RAWIO))
- return -EPERM;
-
- if (copy_from_user
- (&iocommand, argp, sizeof(IOCTL_Command_struct)))
- return -EFAULT;
- if ((iocommand.buf_size < 1) &&
- (iocommand.Request.Type.Direction != XFER_NONE)) {
- return -EINVAL;
- }
-#if 0 /* 'buf_size' member is 16-bits, and always smaller than kmalloc limit */
- /* Check kmalloc limits */
- if (iocommand.buf_size > 128000)
- return -EINVAL;
-#endif
- if (iocommand.buf_size > 0) {
- buff = kmalloc(iocommand.buf_size, GFP_KERNEL);
- if (buff == NULL)
- return -EFAULT;
- }
- if (iocommand.Request.Type.Direction == XFER_WRITE) {
- /* Copy the data into the buffer we created */
- if (copy_from_user
- (buff, iocommand.buf, iocommand.buf_size)) {
- kfree(buff);
- return -EFAULT;
- }
- } else {
- memset(buff, 0, iocommand.buf_size);
- }
- c = cmd_special_alloc(h);
- if (!c) {
- kfree(buff);
- return -ENOMEM;
- }
- /* Fill in the command type */
- c->cmd_type = CMD_IOCTL_PEND;
- /* Fill in Command Header */
- c->Header.ReplyQueue = 0; /* unused in simple mode */
- if (iocommand.buf_size > 0) /* buffer to fill */
- {
- c->Header.SGList = 1;
- c->Header.SGTotal = 1;
- } else /* no buffers to fill */
- {
- c->Header.SGList = 0;
- c->Header.SGTotal = 0;
- }
- c->Header.LUN = iocommand.LUN_info;
- /* use the kernel address the cmd block for tag */
- c->Header.Tag.lower = c->busaddr;
-
- /* Fill in Request block */
- c->Request = iocommand.Request;
-
- /* Fill in the scatter gather information */
- if (iocommand.buf_size > 0) {
- temp64.val = pci_map_single(h->pdev, buff,
- iocommand.buf_size,
- PCI_DMA_BIDIRECTIONAL);
- c->SG[0].Addr.lower = temp64.val32.lower;
- c->SG[0].Addr.upper = temp64.val32.upper;
- c->SG[0].Len = iocommand.buf_size;
- c->SG[0].Ext = 0; /* we are not chaining */
- }
- c->waiting = &wait;
+ } else {
+ memset(buff, 0, iocommand.buf_size);
+ }
+ c = cmd_special_alloc(h);
+ if (!c) {
+ kfree(buff);
+ return -ENOMEM;
+ }
+ /* Fill in the command type */
+ c->cmd_type = CMD_IOCTL_PEND;
+ /* Fill in Command Header */
+ c->Header.ReplyQueue = 0; /* unused in simple mode */
+ if (iocommand.buf_size > 0) { /* buffer to fill */
+ c->Header.SGList = 1;
+ c->Header.SGTotal = 1;
+ } else { /* no buffers to fill */
+ c->Header.SGList = 0;
+ c->Header.SGTotal = 0;
+ }
+ c->Header.LUN = iocommand.LUN_info;
+ /* use the kernel address the cmd block for tag */
+ c->Header.Tag.lower = c->busaddr;
- enqueue_cmd_and_start_io(h, c);
- wait_for_completion(&wait);
+ /* Fill in Request block */
+ c->Request = iocommand.Request;
- /* unlock the buffers from DMA */
- temp64.val32.lower = c->SG[0].Addr.lower;
- temp64.val32.upper = c->SG[0].Addr.upper;
- pci_unmap_single(h->pdev, (dma_addr_t) temp64.val,
- iocommand.buf_size,
- PCI_DMA_BIDIRECTIONAL);
+ /* Fill in the scatter gather information */
+ if (iocommand.buf_size > 0) {
+ temp64.val = pci_map_single(h->pdev, buff,
+ iocommand.buf_size, PCI_DMA_BIDIRECTIONAL);
+ c->SG[0].Addr.lower = temp64.val32.lower;
+ c->SG[0].Addr.upper = temp64.val32.upper;
+ c->SG[0].Len = iocommand.buf_size;
+ c->SG[0].Ext = 0; /* we are not chaining */
+ }
+ c->waiting = &wait;
- check_ioctl_unit_attention(h, c);
+ enqueue_cmd_and_start_io(h, c);
+ wait_for_completion(&wait);
- /* Copy the error information out */
- iocommand.error_info = *(c->err_info);
- if (copy_to_user
- (argp, &iocommand, sizeof(IOCTL_Command_struct))) {
- kfree(buff);
- cmd_special_free(h, c);
- return -EFAULT;
- }
+ /* unlock the buffers from DMA */
+ temp64.val32.lower = c->SG[0].Addr.lower;
+ temp64.val32.upper = c->SG[0].Addr.upper;
+ pci_unmap_single(h->pdev, (dma_addr_t) temp64.val, iocommand.buf_size,
+ PCI_DMA_BIDIRECTIONAL);
+ check_ioctl_unit_attention(h, c);
+
+ /* Copy the error information out */
+ iocommand.error_info = *(c->err_info);
+ if (copy_to_user(argp, &iocommand, sizeof(IOCTL_Command_struct))) {
+ kfree(buff);
+ cmd_special_free(h, c);
+ return -EFAULT;
+ }
- if (iocommand.Request.Type.Direction == XFER_READ) {
- /* Copy the data out of the buffer we created */
- if (copy_to_user
- (iocommand.buf, buff, iocommand.buf_size)) {
- kfree(buff);
- cmd_special_free(h, c);
- return -EFAULT;
- }
- }
+ if (iocommand.Request.Type.Direction == XFER_READ) {
+ /* Copy the data out of the buffer we created */
+ if (copy_to_user(iocommand.buf, buff, iocommand.buf_size)) {
kfree(buff);
cmd_special_free(h, c);
- return 0;
+ return -EFAULT;
}
- case CCISS_BIG_PASSTHRU:{
- BIG_IOCTL_Command_struct *ioc;
- CommandList_struct *c;
- unsigned char **buff = NULL;
- int *buff_size = NULL;
- u64bit temp64;
- BYTE sg_used = 0;
- int status = 0;
- int i;
- DECLARE_COMPLETION_ONSTACK(wait);
- __u32 left;
- __u32 sz;
- BYTE __user *data_ptr;
-
- if (!arg)
- return -EINVAL;
- if (!capable(CAP_SYS_RAWIO))
- return -EPERM;
- ioc = (BIG_IOCTL_Command_struct *)
- kmalloc(sizeof(*ioc), GFP_KERNEL);
- if (!ioc) {
- status = -ENOMEM;
- goto cleanup1;
- }
- if (copy_from_user(ioc, argp, sizeof(*ioc))) {
+ }
+ kfree(buff);
+ cmd_special_free(h, c);
+ return 0;
+}
+
+static int cciss_bigpassthru(ctlr_info_t *h, void __user *argp)
+{
+ BIG_IOCTL_Command_struct *ioc;
+ CommandList_struct *c;
+ unsigned char **buff = NULL;
+ int *buff_size = NULL;
+ u64bit temp64;
+ BYTE sg_used = 0;
+ int status = 0;
+ int i;
+ DECLARE_COMPLETION_ONSTACK(wait);
+ __u32 left;
+ __u32 sz;
+ BYTE __user *data_ptr;
+
+ if (!argp)
+ return -EINVAL;
+ if (!capable(CAP_SYS_RAWIO))
+ return -EPERM;
+ ioc = (BIG_IOCTL_Command_struct *)
+ kmalloc(sizeof(*ioc), GFP_KERNEL);
+ if (!ioc) {
+ status = -ENOMEM;
+ goto cleanup1;
+ }
+ if (copy_from_user(ioc, argp, sizeof(*ioc))) {
+ status = -EFAULT;
+ goto cleanup1;
+ }
+ if ((ioc->buf_size < 1) &&
+ (ioc->Request.Type.Direction != XFER_NONE)) {
+ status = -EINVAL;
+ goto cleanup1;
+ }
+ /* Check kmalloc limits using all SGs */
+ if (ioc->malloc_size > MAX_KMALLOC_SIZE) {
+ status = -EINVAL;
+ goto cleanup1;
+ }
+ if (ioc->buf_size > ioc->malloc_size * MAXSGENTRIES) {
+ status = -EINVAL;
+ goto cleanup1;
+ }
+ buff = kzalloc(MAXSGENTRIES * sizeof(char *), GFP_KERNEL);
+ if (!buff) {
+ status = -ENOMEM;
+ goto cleanup1;
+ }
+ buff_size = kmalloc(MAXSGENTRIES * sizeof(int), GFP_KERNEL);
+ if (!buff_size) {
+ status = -ENOMEM;
+ goto cleanup1;
+ }
+ left = ioc->buf_size;
+ data_ptr = ioc->buf;
+ while (left) {
+ sz = (left > ioc->malloc_size) ? ioc->malloc_size : left;
+ buff_size[sg_used] = sz;
+ buff[sg_used] = kmalloc(sz, GFP_KERNEL);
+ if (buff[sg_used] == NULL) {
+ status = -ENOMEM;
+ goto cleanup1;
+ }
+ if (ioc->Request.Type.Direction == XFER_WRITE) {
+ if (copy_from_user(buff[sg_used], data_ptr, sz)) {
status = -EFAULT;
goto cleanup1;
}
- if ((ioc->buf_size < 1) &&
- (ioc->Request.Type.Direction != XFER_NONE)) {
- status = -EINVAL;
- goto cleanup1;
- }
- /* Check kmalloc limits using all SGs */
- if (ioc->malloc_size > MAX_KMALLOC_SIZE) {
- status = -EINVAL;
- goto cleanup1;
- }
- if (ioc->buf_size > ioc->malloc_size * MAXSGENTRIES) {
- status = -EINVAL;
- goto cleanup1;
- }
- buff =
- kzalloc(MAXSGENTRIES * sizeof(char *), GFP_KERNEL);
- if (!buff) {
- status = -ENOMEM;
- goto cleanup1;
- }
- buff_size = kmalloc(MAXSGENTRIES * sizeof(int),
- GFP_KERNEL);
- if (!buff_size) {
- status = -ENOMEM;
- goto cleanup1;
- }
- left = ioc->buf_size;
- data_ptr = ioc->buf;
- while (left) {
- sz = (left >
- ioc->malloc_size) ? ioc->
- malloc_size : left;
- buff_size[sg_used] = sz;
- buff[sg_used] = kmalloc(sz, GFP_KERNEL);
- if (buff[sg_used] == NULL) {
- status = -ENOMEM;
- goto cleanup1;
- }
- if (ioc->Request.Type.Direction == XFER_WRITE) {
- if (copy_from_user
- (buff[sg_used], data_ptr, sz)) {
- status = -EFAULT;
- goto cleanup1;
- }
- } else {
- memset(buff[sg_used], 0, sz);
- }
- left -= sz;
- data_ptr += sz;
- sg_used++;
- }
- c = cmd_special_alloc(h);
- if (!c) {
- status = -ENOMEM;
- goto cleanup1;
- }
- c->cmd_type = CMD_IOCTL_PEND;
- c->Header.ReplyQueue = 0;
+ } else {
+ memset(buff[sg_used], 0, sz);
+ }
+ left -= sz;
+ data_ptr += sz;
+ sg_used++;
+ }
+ c = cmd_special_alloc(h);
+ if (!c) {
+ status = -ENOMEM;
+ goto cleanup1;
+ }
+ c->cmd_type = CMD_IOCTL_PEND;
+ c->Header.ReplyQueue = 0;
+ c->Header.SGList = sg_used;
+ c->Header.SGTotal = sg_used;
+ c->Header.LUN = ioc->LUN_info;
+ c->Header.Tag.lower = c->busaddr;
- if (ioc->buf_size > 0) {
- c->Header.SGList = sg_used;
- c->Header.SGTotal = sg_used;
- } else {
- c->Header.SGList = 0;
- c->Header.SGTotal = 0;
- }
- c->Header.LUN = ioc->LUN_info;
- c->Header.Tag.lower = c->busaddr;
-
- c->Request = ioc->Request;
- if (ioc->buf_size > 0) {
- for (i = 0; i < sg_used; i++) {
- temp64.val =
- pci_map_single(h->pdev, buff[i],
- buff_size[i],
- PCI_DMA_BIDIRECTIONAL);
- c->SG[i].Addr.lower =
- temp64.val32.lower;
- c->SG[i].Addr.upper =
- temp64.val32.upper;
- c->SG[i].Len = buff_size[i];
- c->SG[i].Ext = 0; /* we are not chaining */
- }
- }
- c->waiting = &wait;
- enqueue_cmd_and_start_io(h, c);
- wait_for_completion(&wait);
- /* unlock the buffers from DMA */
- for (i = 0; i < sg_used; i++) {
- temp64.val32.lower = c->SG[i].Addr.lower;
- temp64.val32.upper = c->SG[i].Addr.upper;
- pci_unmap_single(h->pdev,
- (dma_addr_t) temp64.val, buff_size[i],
- PCI_DMA_BIDIRECTIONAL);
- }
- check_ioctl_unit_attention(h, c);
- /* Copy the error information out */
- ioc->error_info = *(c->err_info);
- if (copy_to_user(argp, ioc, sizeof(*ioc))) {
+ c->Request = ioc->Request;
+ for (i = 0; i < sg_used; i++) {
+ temp64.val = pci_map_single(h->pdev, buff[i], buff_size[i],
+ PCI_DMA_BIDIRECTIONAL);
+ c->SG[i].Addr.lower = temp64.val32.lower;
+ c->SG[i].Addr.upper = temp64.val32.upper;
+ c->SG[i].Len = buff_size[i];
+ c->SG[i].Ext = 0; /* we are not chaining */
+ }
+ c->waiting = &wait;
+ enqueue_cmd_and_start_io(h, c);
+ wait_for_completion(&wait);
+ /* unlock the buffers from DMA */
+ for (i = 0; i < sg_used; i++) {
+ temp64.val32.lower = c->SG[i].Addr.lower;
+ temp64.val32.upper = c->SG[i].Addr.upper;
+ pci_unmap_single(h->pdev,
+ (dma_addr_t) temp64.val, buff_size[i],
+ PCI_DMA_BIDIRECTIONAL);
+ }
+ check_ioctl_unit_attention(h, c);
+ /* Copy the error information out */
+ ioc->error_info = *(c->err_info);
+ if (copy_to_user(argp, ioc, sizeof(*ioc))) {
+ cmd_special_free(h, c);
+ status = -EFAULT;
+ goto cleanup1;
+ }
+ if (ioc->Request.Type.Direction == XFER_READ) {
+ /* Copy the data out of the buffer we created */
+ BYTE __user *ptr = ioc->buf;
+ for (i = 0; i < sg_used; i++) {
+ if (copy_to_user(ptr, buff[i], buff_size[i])) {
cmd_special_free(h, c);
status = -EFAULT;
goto cleanup1;
}
- if (ioc->Request.Type.Direction == XFER_READ) {
- /* Copy the data out of the buffer we created */
- BYTE __user *ptr = ioc->buf;
- for (i = 0; i < sg_used; i++) {
- if (copy_to_user
- (ptr, buff[i], buff_size[i])) {
- cmd_special_free(h, c);
- status = -EFAULT;
- goto cleanup1;
- }
- ptr += buff_size[i];
- }
- }
- cmd_special_free(h, c);
- status = 0;
- cleanup1:
- if (buff) {
- for (i = 0; i < sg_used; i++)
- kfree(buff[i]);
- kfree(buff);
- }
- kfree(buff_size);
- kfree(ioc);
- return status;
+ ptr += buff_size[i];
}
+ }
+ cmd_special_free(h, c);
+ status = 0;
+cleanup1:
+ if (buff) {
+ for (i = 0; i < sg_used; i++)
+ kfree(buff[i]);
+ kfree(buff);
+ }
+ kfree(buff_size);
+ kfree(ioc);
+ return status;
+}
+
+static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
+ unsigned int cmd, unsigned long arg)
+{
+ struct gendisk *disk = bdev->bd_disk;
+ ctlr_info_t *h = get_host(disk);
+ void __user *argp = (void __user *)arg;
+
+ dev_dbg(&h->pdev->dev, "cciss_ioctl: Called with cmd=%x %lx\n",
+ cmd, arg);
+ switch (cmd) {
+ case CCISS_GETPCIINFO:
+ return cciss_getpciinfo(h, argp);
+ case CCISS_GETINTINFO:
+ return cciss_getintinfo(h, argp);
+ case CCISS_SETINTINFO:
+ return cciss_setintinfo(h, argp);
+ case CCISS_GETNODENAME:
+ return cciss_getnodename(h, argp);
+ case CCISS_SETNODENAME:
+ return cciss_setnodename(h, argp);
+ case CCISS_GETHEARTBEAT:
+ return cciss_getheartbeat(h, argp);
+ case CCISS_GETBUSTYPES:
+ return cciss_getbustypes(h, argp);
+ case CCISS_GETFIRMVER:
+ return cciss_getfirmver(h, argp);
+ case CCISS_GETDRIVVER:
+ return cciss_getdrivver(h, argp);
+ case CCISS_DEREGDISK:
+ case CCISS_REGNEWD:
+ case CCISS_REVALIDVOLS:
+ return rebuild_lun_table(h, 0, 1);
+ case CCISS_GETLUNINFO:
+ return cciss_getluninfo(h, disk, argp);
+ case CCISS_PASSTHRU:
+ return cciss_passthru(h, argp);
+ case CCISS_BIG_PASSTHRU:
+ return cciss_bigpassthru(h, argp);
/* scsi_cmd_ioctl handles these, below, though some are not */
/* very meaningful for cciss. SG_IO is the main one people want. */
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
index d53b0291c44b..946dad4caef3 100644
--- a/drivers/block/cpqarray.c
+++ b/drivers/block/cpqarray.c
@@ -35,7 +35,7 @@
#include <linux/seq_file.h>
#include <linux/init.h>
#include <linux/hdreg.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/spinlock.h>
#include <linux/blkdev.h>
#include <linux/genhd.h>
@@ -68,6 +68,7 @@ MODULE_LICENSE("GPL");
#define CPQARRAY_DMA_MASK 0xFFFFFFFF /* 32 bit DMA */
+static DEFINE_MUTEX(cpqarray_mutex);
static int nr_ctlr;
static ctlr_info_t *hba[MAX_CTLR];
@@ -845,9 +846,9 @@ static int ida_unlocked_open(struct block_device *bdev, fmode_t mode)
{
int ret;
- lock_kernel();
+ mutex_lock(&cpqarray_mutex);
ret = ida_open(bdev, mode);
- unlock_kernel();
+ mutex_unlock(&cpqarray_mutex);
return ret;
}
@@ -859,10 +860,10 @@ static int ida_release(struct gendisk *disk, fmode_t mode)
{
ctlr_info_t *host;
- lock_kernel();
+ mutex_lock(&cpqarray_mutex);
host = get_host(disk);
host->usage_count--;
- unlock_kernel();
+ mutex_unlock(&cpqarray_mutex);
return 0;
}
@@ -1217,9 +1218,9 @@ static int ida_ioctl(struct block_device *bdev, fmode_t mode,
{
int ret;
- lock_kernel();
+ mutex_lock(&cpqarray_mutex);
ret = ida_locked_ioctl(bdev, mode, cmd, param);
- unlock_kernel();
+ mutex_unlock(&cpqarray_mutex);
return ret;
}
diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c
index 9400845d602e..ac04ef97eac2 100644
--- a/drivers/block/drbd/drbd_actlog.c
+++ b/drivers/block/drbd/drbd_actlog.c
@@ -965,29 +965,30 @@ void __drbd_set_in_sync(struct drbd_conf *mdev, sector_t sector, int size,
* ok, (capacity & 7) != 0 sometimes, but who cares...
* we count rs_{total,left} in bits, not sectors.
*/
- spin_lock_irqsave(&mdev->al_lock, flags);
count = drbd_bm_clear_bits(mdev, sbnr, ebnr);
- if (count) {
- /* we need the lock for drbd_try_clear_on_disk_bm */
- if (jiffies - mdev->rs_mark_time > HZ*10) {
- /* should be rolling marks,
- * but we estimate only anyways. */
- if (mdev->rs_mark_left != drbd_bm_total_weight(mdev) &&
+ if (count && get_ldev(mdev)) {
+ unsigned long now = jiffies;
+ unsigned long last = mdev->rs_mark_time[mdev->rs_last_mark];
+ int next = (mdev->rs_last_mark + 1) % DRBD_SYNC_MARKS;
+ if (time_after_eq(now, last + DRBD_SYNC_MARK_STEP)) {
+ unsigned long tw = drbd_bm_total_weight(mdev);
+ if (mdev->rs_mark_left[mdev->rs_last_mark] != tw &&
mdev->state.conn != C_PAUSED_SYNC_T &&
mdev->state.conn != C_PAUSED_SYNC_S) {
- mdev->rs_mark_time = jiffies;
- mdev->rs_mark_left = drbd_bm_total_weight(mdev);
+ mdev->rs_mark_time[next] = now;
+ mdev->rs_mark_left[next] = tw;
+ mdev->rs_last_mark = next;
}
}
- if (get_ldev(mdev)) {
- drbd_try_clear_on_disk_bm(mdev, sector, count, TRUE);
- put_ldev(mdev);
- }
+ spin_lock_irqsave(&mdev->al_lock, flags);
+ drbd_try_clear_on_disk_bm(mdev, sector, count, TRUE);
+ spin_unlock_irqrestore(&mdev->al_lock, flags);
+
/* just wake_up unconditional now, various lc_chaged(),
* lc_put() in drbd_try_clear_on_disk_bm(). */
wake_up = 1;
+ put_ldev(mdev);
}
- spin_unlock_irqrestore(&mdev->al_lock, flags);
if (wake_up)
wake_up(&mdev->al_wait);
}
@@ -1118,7 +1119,7 @@ static int _is_in_al(struct drbd_conf *mdev, unsigned int enr)
* @mdev: DRBD device.
* @sector: The sector number.
*
- * This functions sleeps on al_wait. Returns 1 on success, 0 if interrupted.
+ * This functions sleeps on al_wait. Returns 0 on success, -EINTR if interrupted.
*/
int drbd_rs_begin_io(struct drbd_conf *mdev, sector_t sector)
{
@@ -1129,10 +1130,10 @@ int drbd_rs_begin_io(struct drbd_conf *mdev, sector_t sector)
sig = wait_event_interruptible(mdev->al_wait,
(bm_ext = _bme_get(mdev, enr)));
if (sig)
- return 0;
+ return -EINTR;
if (test_bit(BME_LOCKED, &bm_ext->flags))
- return 1;
+ return 0;
for (i = 0; i < AL_EXT_PER_BM_SECT; i++) {
sig = wait_event_interruptible(mdev->al_wait,
@@ -1145,13 +1146,11 @@ int drbd_rs_begin_io(struct drbd_conf *mdev, sector_t sector)
wake_up(&mdev->al_wait);
}
spin_unlock_irq(&mdev->al_lock);
- return 0;
+ return -EINTR;
}
}
-
set_bit(BME_LOCKED, &bm_ext->flags);
-
- return 1;
+ return 0;
}
/**
diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c
index e3f88d6e1412..fd42832f785b 100644
--- a/drivers/block/drbd/drbd_bitmap.c
+++ b/drivers/block/drbd/drbd_bitmap.c
@@ -569,7 +569,7 @@ int drbd_bm_resize(struct drbd_conf *mdev, sector_t capacity, int set_new_bits)
*
* maybe bm_set should be atomic_t ?
*/
-static unsigned long _drbd_bm_total_weight(struct drbd_conf *mdev)
+unsigned long _drbd_bm_total_weight(struct drbd_conf *mdev)
{
struct drbd_bitmap *b = mdev->bitmap;
unsigned long s;
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index 352441b0f92f..9bdcf4393c0a 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -337,13 +337,25 @@ static inline void bm_xfer_ctx_bit_to_word_offset(struct bm_xfer_ctx *c)
* NOTE that the payload starts at a long aligned offset,
* regardless of 32 or 64 bit arch!
*/
-struct p_header {
+struct p_header80 {
u32 magic;
u16 command;
u16 length; /* bytes of data after this header */
u8 payload[0];
} __packed;
-/* 8 bytes. packet FIXED for the next century! */
+
+/* Header for big packets, Used for data packets exceeding 64kB */
+struct p_header95 {
+ u16 magic; /* use DRBD_MAGIC_BIG here */
+ u16 command;
+ u32 length; /* Use only 24 bits of that. Ignore the highest 8 bit. */
+ u8 payload[0];
+} __packed;
+
+union p_header {
+ struct p_header80 h80;
+ struct p_header95 h95;
+};
/*
* short commands, packets without payload, plain p_header:
@@ -362,12 +374,16 @@ struct p_header {
*/
/* these defines must not be changed without changing the protocol version */
-#define DP_HARDBARRIER 1
-#define DP_RW_SYNC 2
+#define DP_HARDBARRIER 1 /* depricated */
+#define DP_RW_SYNC 2 /* equals REQ_SYNC */
#define DP_MAY_SET_IN_SYNC 4
+#define DP_UNPLUG 8 /* equals REQ_UNPLUG */
+#define DP_FUA 16 /* equals REQ_FUA */
+#define DP_FLUSH 32 /* equals REQ_FLUSH */
+#define DP_DISCARD 64 /* equals REQ_DISCARD */
struct p_data {
- struct p_header head;
+ union p_header head;
u64 sector; /* 64 bits sector number */
u64 block_id; /* to identify the request in protocol B&C */
u32 seq_num;
@@ -383,7 +399,7 @@ struct p_data {
* P_DATA_REQUEST, P_RS_DATA_REQUEST
*/
struct p_block_ack {
- struct p_header head;
+ struct p_header80 head;
u64 sector;
u64 block_id;
u32 blksize;
@@ -392,7 +408,7 @@ struct p_block_ack {
struct p_block_req {
- struct p_header head;
+ struct p_header80 head;
u64 sector;
u64 block_id;
u32 blksize;
@@ -409,7 +425,7 @@ struct p_block_req {
*/
struct p_handshake {
- struct p_header head; /* 8 bytes */
+ struct p_header80 head; /* 8 bytes */
u32 protocol_min;
u32 feature_flags;
u32 protocol_max;
@@ -424,19 +440,19 @@ struct p_handshake {
/* 80 bytes, FIXED for the next century */
struct p_barrier {
- struct p_header head;
+ struct p_header80 head;
u32 barrier; /* barrier number _handle_ only */
u32 pad; /* to multiple of 8 Byte */
} __packed;
struct p_barrier_ack {
- struct p_header head;
+ struct p_header80 head;
u32 barrier;
u32 set_size;
} __packed;
struct p_rs_param {
- struct p_header head;
+ struct p_header80 head;
u32 rate;
/* Since protocol version 88 and higher. */
@@ -444,20 +460,31 @@ struct p_rs_param {
} __packed;
struct p_rs_param_89 {
- struct p_header head;
+ struct p_header80 head;
u32 rate;
/* protocol version 89: */
char verify_alg[SHARED_SECRET_MAX];
char csums_alg[SHARED_SECRET_MAX];
} __packed;
+struct p_rs_param_95 {
+ struct p_header80 head;
+ u32 rate;
+ char verify_alg[SHARED_SECRET_MAX];
+ char csums_alg[SHARED_SECRET_MAX];
+ u32 c_plan_ahead;
+ u32 c_delay_target;
+ u32 c_fill_target;
+ u32 c_max_rate;
+} __packed;
+
enum drbd_conn_flags {
CF_WANT_LOSE = 1,
CF_DRY_RUN = 2,
};
struct p_protocol {
- struct p_header head;
+ struct p_header80 head;
u32 protocol;
u32 after_sb_0p;
u32 after_sb_1p;
@@ -471,17 +498,17 @@ struct p_protocol {
} __packed;
struct p_uuids {
- struct p_header head;
+ struct p_header80 head;
u64 uuid[UI_EXTENDED_SIZE];
} __packed;
struct p_rs_uuid {
- struct p_header head;
+ struct p_header80 head;
u64 uuid;
} __packed;
struct p_sizes {
- struct p_header head;
+ struct p_header80 head;
u64 d_size; /* size of disk */
u64 u_size; /* user requested size */
u64 c_size; /* current exported size */
@@ -491,18 +518,18 @@ struct p_sizes {
} __packed;
struct p_state {
- struct p_header head;
+ struct p_header80 head;
u32 state;
} __packed;
struct p_req_state {
- struct p_header head;
+ struct p_header80 head;
u32 mask;
u32 val;
} __packed;
struct p_req_state_reply {
- struct p_header head;
+ struct p_header80 head;
u32 retcode;
} __packed;
@@ -517,7 +544,7 @@ struct p_drbd06_param {
} __packed;
struct p_discard {
- struct p_header head;
+ struct p_header80 head;
u64 block_id;
u32 seq_num;
u32 pad;
@@ -533,7 +560,7 @@ enum drbd_bitmap_code {
};
struct p_compressed_bm {
- struct p_header head;
+ struct p_header80 head;
/* (encoding & 0x0f): actual encoding, see enum drbd_bitmap_code
* (encoding & 0x80): polarity (set/unset) of first runlength
* ((encoding >> 4) & 0x07): pad_bits, number of trailing zero bits
@@ -544,10 +571,10 @@ struct p_compressed_bm {
u8 code[0];
} __packed;
-struct p_delay_probe {
- struct p_header head;
- u32 seq_num; /* sequence number to match the two probe packets */
- u32 offset; /* usecs the probe got sent after the reference time point */
+struct p_delay_probe93 {
+ struct p_header80 head;
+ u32 seq_num; /* sequence number to match the two probe packets */
+ u32 offset; /* usecs the probe got sent after the reference time point */
} __packed;
/* DCBP: Drbd Compressed Bitmap Packet ... */
@@ -594,7 +621,7 @@ DCBP_set_pad_bits(struct p_compressed_bm *p, int n)
* so we need to use the fixed size 4KiB page size
* most architechtures have used for a long time.
*/
-#define BM_PACKET_PAYLOAD_BYTES (4096 - sizeof(struct p_header))
+#define BM_PACKET_PAYLOAD_BYTES (4096 - sizeof(struct p_header80))
#define BM_PACKET_WORDS (BM_PACKET_PAYLOAD_BYTES/sizeof(long))
#define BM_PACKET_VLI_BYTES_MAX (4096 - sizeof(struct p_compressed_bm))
#if (PAGE_SIZE < 4096)
@@ -603,13 +630,14 @@ DCBP_set_pad_bits(struct p_compressed_bm *p, int n)
#endif
union p_polymorph {
- struct p_header header;
+ union p_header header;
struct p_handshake handshake;
struct p_data data;
struct p_block_ack block_ack;
struct p_barrier barrier;
struct p_barrier_ack barrier_ack;
struct p_rs_param_89 rs_param_89;
+ struct p_rs_param_95 rs_param_95;
struct p_protocol protocol;
struct p_sizes sizes;
struct p_uuids uuids;
@@ -617,6 +645,8 @@ union p_polymorph {
struct p_req_state req_state;
struct p_req_state_reply req_state_reply;
struct p_block_req block_req;
+ struct p_delay_probe93 delay_probe93;
+ struct p_rs_uuid rs_uuid;
} __packed;
/**********************************************************************/
@@ -697,7 +727,7 @@ struct drbd_tl_epoch {
struct list_head requests; /* requests before */
struct drbd_tl_epoch *next; /* pointer to the next barrier */
unsigned int br_number; /* the barriers identifier. */
- int n_req; /* number of requests attached before this barrier */
+ int n_writes; /* number of requests attached before this barrier */
};
struct drbd_request;
@@ -747,7 +777,7 @@ struct digest_info {
struct drbd_epoch_entry {
struct drbd_work w;
struct hlist_node colision;
- struct drbd_epoch *epoch;
+ struct drbd_epoch *epoch; /* for writes */
struct drbd_conf *mdev;
struct page *pages;
atomic_t pending_bios;
@@ -755,7 +785,10 @@ struct drbd_epoch_entry {
/* see comments on ee flag bits below */
unsigned long flags;
sector_t sector;
- u64 block_id;
+ union {
+ u64 block_id;
+ struct digest_info *digest;
+ };
};
/* ee flag bits.
@@ -781,12 +814,16 @@ enum {
* if any of those fail, we set this flag atomically
* from the endio callback */
__EE_WAS_ERROR,
+
+ /* This ee has a pointer to a digest instead of a block id */
+ __EE_HAS_DIGEST,
};
#define EE_CALL_AL_COMPLETE_IO (1<<__EE_CALL_AL_COMPLETE_IO)
#define EE_MAY_SET_IN_SYNC (1<<__EE_MAY_SET_IN_SYNC)
#define EE_IS_BARRIER (1<<__EE_IS_BARRIER)
#define EE_RESUBMITTED (1<<__EE_RESUBMITTED)
#define EE_WAS_ERROR (1<<__EE_WAS_ERROR)
+#define EE_HAS_DIGEST (1<<__EE_HAS_DIGEST)
/* global flag bits */
enum {
@@ -794,7 +831,6 @@ enum {
SIGNAL_ASENDER, /* whether asender wants to be interrupted */
SEND_PING, /* whether asender should send a ping asap */
- STOP_SYNC_TIMER, /* tell timer to cancel itself */
UNPLUG_QUEUED, /* only relevant with kernel 2.4 */
UNPLUG_REMOTE, /* sending a "UnplugRemote" could help */
MD_DIRTY, /* current uuids and flags not yet on disk */
@@ -816,6 +852,7 @@ enum {
BITMAP_IO, /* suspend application io;
once no more io in flight, start bitmap io */
BITMAP_IO_QUEUED, /* Started bitmap IO */
+ GO_DISKLESS, /* Disk failed, local_cnt reached zero, we are going diskless */
RESYNC_AFTER_NEG, /* Resync after online grow after the attach&negotiate finished. */
NET_CONGESTED, /* The data socket is congested */
@@ -829,6 +866,8 @@ enum {
* the peer, if it changed there as well. */
CONN_DRY_RUN, /* Expect disconnect after resync handshake. */
GOT_PING_ACK, /* set when we receive a ping_ack packet, misc wait gets woken */
+ NEW_CUR_UUID, /* Create new current UUID when thawing IO */
+ AL_SUSPENDED, /* Activity logging is currently suspended. */
};
struct drbd_bitmap; /* opaque for drbd_conf */
@@ -838,10 +877,6 @@ struct drbd_bitmap; /* opaque for drbd_conf */
/* THINK maybe we actually want to use the default "event/%s" worker threads
* or similar in linux 2.6, which uses per cpu data and threads.
- *
- * To be general, this might need a spin_lock member.
- * For now, please use the mdev->req_lock to protect list_head,
- * see drbd_queue_work below.
*/
struct drbd_work_queue {
struct list_head q;
@@ -915,6 +950,12 @@ enum write_ordering_e {
WO_bio_barrier
};
+struct fifo_buffer {
+ int *values;
+ unsigned int head_index;
+ unsigned int size;
+};
+
struct drbd_conf {
/* things that are stored as / read from meta data on disk */
unsigned long flags;
@@ -936,9 +977,16 @@ struct drbd_conf {
unsigned int ko_count;
struct drbd_work resync_work,
unplug_work,
+ go_diskless,
md_sync_work;
struct timer_list resync_timer;
struct timer_list md_sync_timer;
+#ifdef DRBD_DEBUG_MD_SYNC
+ struct {
+ unsigned int line;
+ const char* func;
+ } last_md_mark_dirty;
+#endif
/* Used after attach while negotiating new disk state. */
union drbd_state new_state_tmp;
@@ -946,6 +994,7 @@ struct drbd_conf {
union drbd_state state;
wait_queue_head_t misc_wait;
wait_queue_head_t state_wait; /* upon each state change. */
+ wait_queue_head_t net_cnt_wait;
unsigned int send_cnt;
unsigned int recv_cnt;
unsigned int read_cnt;
@@ -974,12 +1023,16 @@ struct drbd_conf {
unsigned long rs_start;
/* cumulated time in PausedSyncX state [unit jiffies] */
unsigned long rs_paused;
+ /* skipped because csum was equal [unit BM_BLOCK_SIZE] */
+ unsigned long rs_same_csum;
+#define DRBD_SYNC_MARKS 8
+#define DRBD_SYNC_MARK_STEP (3*HZ)
/* block not up-to-date at mark [unit BM_BLOCK_SIZE] */
- unsigned long rs_mark_left;
+ unsigned long rs_mark_left[DRBD_SYNC_MARKS];
/* marks's time [unit jiffies] */
- unsigned long rs_mark_time;
- /* skipped because csum was equeal [unit BM_BLOCK_SIZE] */
- unsigned long rs_same_csum;
+ unsigned long rs_mark_time[DRBD_SYNC_MARKS];
+ /* current index into rs_mark_{left,time} */
+ int rs_last_mark;
/* where does the admin want us to start? (sector) */
sector_t ov_start_sector;
@@ -1012,10 +1065,10 @@ struct drbd_conf {
spinlock_t epoch_lock;
unsigned int epochs;
enum write_ordering_e write_ordering;
- struct list_head active_ee; /* IO in progress */
- struct list_head sync_ee; /* IO in progress */
+ struct list_head active_ee; /* IO in progress (P_DATA gets written to disk) */
+ struct list_head sync_ee; /* IO in progress (P_RS_DATA_REPLY gets written to disk) */
struct list_head done_ee; /* send ack */
- struct list_head read_ee; /* IO in progress */
+ struct list_head read_ee; /* IO in progress (any read) */
struct list_head net_ee; /* zero-copy network send in progress */
struct hlist_head *ee_hash; /* is proteced by req_lock! */
unsigned int ee_hash_s;
@@ -1026,7 +1079,8 @@ struct drbd_conf {
int next_barrier_nr;
struct hlist_head *app_reads_hash; /* is proteced by req_lock */
struct list_head resync_reads;
- atomic_t pp_in_use;
+ atomic_t pp_in_use; /* allocated from page pool */
+ atomic_t pp_in_use_by_net; /* sendpage()d, still referenced by tcp */
wait_queue_head_t ee_wait;
struct page *md_io_page; /* one page buffer for md_io */
struct page *md_io_tmpp; /* for logical_block_size != 512 */
@@ -1054,6 +1108,15 @@ struct drbd_conf {
u64 ed_uuid; /* UUID of the exposed data */
struct mutex state_mutex;
char congestion_reason; /* Why we where congested... */
+ atomic_t rs_sect_in; /* for incoming resync data rate, SyncTarget */
+ atomic_t rs_sect_ev; /* for submitted resync data rate, both */
+ int rs_last_sect_ev; /* counter to compare with */
+ int rs_last_events; /* counter of read or write "events" (unit sectors)
+ * on the lower level device when we last looked. */
+ int c_sync_rate; /* current resync rate after syncer throttle magic */
+ struct fifo_buffer rs_plan_s; /* correction values of resync planer */
+ int rs_in_flight; /* resync sectors in flight (to proxy, in proxy and from proxy) */
+ int rs_planed; /* resync sectors already planed */
};
static inline struct drbd_conf *minor_to_mdev(unsigned int minor)
@@ -1138,6 +1201,8 @@ extern void drbd_free_resources(struct drbd_conf *mdev);
extern void tl_release(struct drbd_conf *mdev, unsigned int barrier_nr,
unsigned int set_size);
extern void tl_clear(struct drbd_conf *mdev);
+enum drbd_req_event;
+extern void tl_restart(struct drbd_conf *mdev, enum drbd_req_event what);
extern void _tl_add_barrier(struct drbd_conf *, struct drbd_tl_epoch *);
extern void drbd_free_sock(struct drbd_conf *mdev);
extern int drbd_send(struct drbd_conf *mdev, struct socket *sock,
@@ -1150,12 +1215,12 @@ extern int drbd_send_sizes(struct drbd_conf *mdev, int trigger_reply, enum dds_f
extern int _drbd_send_state(struct drbd_conf *mdev);
extern int drbd_send_state(struct drbd_conf *mdev);
extern int _drbd_send_cmd(struct drbd_conf *mdev, struct socket *sock,
- enum drbd_packets cmd, struct p_header *h,
+ enum drbd_packets cmd, struct p_header80 *h,
size_t size, unsigned msg_flags);
#define USE_DATA_SOCKET 1
#define USE_META_SOCKET 0
extern int drbd_send_cmd(struct drbd_conf *mdev, int use_data_socket,
- enum drbd_packets cmd, struct p_header *h,
+ enum drbd_packets cmd, struct p_header80 *h,
size_t size);
extern int drbd_send_cmd2(struct drbd_conf *mdev, enum drbd_packets cmd,
char *data, size_t size);
@@ -1167,7 +1232,7 @@ extern int drbd_send_ack(struct drbd_conf *mdev, enum drbd_packets cmd,
extern int drbd_send_ack_rp(struct drbd_conf *mdev, enum drbd_packets cmd,
struct p_block_req *rp);
extern int drbd_send_ack_dp(struct drbd_conf *mdev, enum drbd_packets cmd,
- struct p_data *dp);
+ struct p_data *dp, int data_size);
extern int drbd_send_ack_ex(struct drbd_conf *mdev, enum drbd_packets cmd,
sector_t sector, int blksize, u64 block_id);
extern int drbd_send_block(struct drbd_conf *mdev, enum drbd_packets cmd,
@@ -1201,7 +1266,13 @@ extern void drbd_uuid_set_bm(struct drbd_conf *mdev, u64 val) __must_hold(local)
extern void drbd_md_set_flag(struct drbd_conf *mdev, int flags) __must_hold(local);
extern void drbd_md_clear_flag(struct drbd_conf *mdev, int flags)__must_hold(local);
extern int drbd_md_test_flag(struct drbd_backing_dev *, int);
+#ifndef DRBD_DEBUG_MD_SYNC
extern void drbd_md_mark_dirty(struct drbd_conf *mdev);
+#else
+#define drbd_md_mark_dirty(m) drbd_md_mark_dirty_(m, __LINE__ , __func__ )
+extern void drbd_md_mark_dirty_(struct drbd_conf *mdev,
+ unsigned int line, const char *func);
+#endif
extern void drbd_queue_bitmap_io(struct drbd_conf *mdev,
int (*io_fn)(struct drbd_conf *),
void (*done)(struct drbd_conf *, int),
@@ -1209,6 +1280,7 @@ extern void drbd_queue_bitmap_io(struct drbd_conf *mdev,
extern int drbd_bmio_set_n_write(struct drbd_conf *mdev);
extern int drbd_bmio_clear_n_write(struct drbd_conf *mdev);
extern int drbd_bitmap_io(struct drbd_conf *mdev, int (*io_fn)(struct drbd_conf *), char *why);
+extern void drbd_go_diskless(struct drbd_conf *mdev);
/* Meta data layout
@@ -1264,6 +1336,8 @@ struct bm_extent {
* Bit 1 ==> local node thinks this block needs to be synced.
*/
+#define SLEEP_TIME (HZ/10)
+
#define BM_BLOCK_SHIFT 12 /* 4k per bit */
#define BM_BLOCK_SIZE (1<<BM_BLOCK_SHIFT)
/* (9+3) : 512 bytes @ 8 bits; representing 16M storage
@@ -1335,11 +1409,13 @@ struct bm_extent {
#endif
/* Sector shift value for the "hash" functions of tl_hash and ee_hash tables.
- * With a value of 6 all IO in one 32K block make it to the same slot of the
+ * With a value of 8 all IO in one 128K block make it to the same slot of the
* hash table. */
-#define HT_SHIFT 6
+#define HT_SHIFT 8
#define DRBD_MAX_SEGMENT_SIZE (1U<<(9+HT_SHIFT))
+#define DRBD_MAX_SIZE_H80_PACKET (1 << 15) /* The old header only allows packets up to 32Kib data */
+
/* Number of elements in the app_reads_hash */
#define APP_R_HSIZE 15
@@ -1369,6 +1445,7 @@ extern unsigned long drbd_bm_find_next(struct drbd_conf *mdev, unsigned long bm_
/* bm_find_next variants for use while you hold drbd_bm_lock() */
extern unsigned long _drbd_bm_find_next(struct drbd_conf *mdev, unsigned long bm_fo);
extern unsigned long _drbd_bm_find_next_zero(struct drbd_conf *mdev, unsigned long bm_fo);
+extern unsigned long _drbd_bm_total_weight(struct drbd_conf *mdev);
extern unsigned long drbd_bm_total_weight(struct drbd_conf *mdev);
extern int drbd_bm_rs_done(struct drbd_conf *mdev);
/* for receive_bitmap */
@@ -1421,7 +1498,8 @@ extern void resync_after_online_grow(struct drbd_conf *);
extern void drbd_setup_queue_param(struct drbd_conf *mdev, unsigned int) __must_hold(local);
extern int drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role,
int force);
-enum drbd_disk_state drbd_try_outdate_peer(struct drbd_conf *mdev);
+extern enum drbd_disk_state drbd_try_outdate_peer(struct drbd_conf *mdev);
+extern void drbd_try_outdate_peer_async(struct drbd_conf *mdev);
extern int drbd_khelper(struct drbd_conf *mdev, char *cmd);
/* drbd_worker.c */
@@ -1467,10 +1545,12 @@ extern int w_send_barrier(struct drbd_conf *, struct drbd_work *, int);
extern int w_send_read_req(struct drbd_conf *, struct drbd_work *, int);
extern int w_prev_work_done(struct drbd_conf *, struct drbd_work *, int);
extern int w_e_reissue(struct drbd_conf *, struct drbd_work *, int);
+extern int w_restart_disk_io(struct drbd_conf *, struct drbd_work *, int);
extern void resync_timer_fn(unsigned long data);
/* drbd_receiver.c */
+extern int drbd_rs_should_slow_down(struct drbd_conf *mdev);
extern int drbd_submit_ee(struct drbd_conf *mdev, struct drbd_epoch_entry *e,
const unsigned rw, const int fault_type);
extern int drbd_release_ee(struct drbd_conf *mdev, struct list_head *list);
@@ -1479,7 +1559,10 @@ extern struct drbd_epoch_entry *drbd_alloc_ee(struct drbd_conf *mdev,
sector_t sector,
unsigned int data_size,
gfp_t gfp_mask) __must_hold(local);
-extern void drbd_free_ee(struct drbd_conf *mdev, struct drbd_epoch_entry *e);
+extern void drbd_free_some_ee(struct drbd_conf *mdev, struct drbd_epoch_entry *e,
+ int is_net);
+#define drbd_free_ee(m,e) drbd_free_some_ee(m, e, 0)
+#define drbd_free_net_ee(m,e) drbd_free_some_ee(m, e, 1)
extern void drbd_wait_ee_list_empty(struct drbd_conf *mdev,
struct list_head *head);
extern void _drbd_wait_ee_list_empty(struct drbd_conf *mdev,
@@ -1487,6 +1570,7 @@ extern void _drbd_wait_ee_list_empty(struct drbd_conf *mdev,
extern void drbd_set_recv_tcq(struct drbd_conf *mdev, int tcq_enabled);
extern void _drbd_clear_done_ee(struct drbd_conf *mdev, struct list_head *to_be_freed);
extern void drbd_flush_workqueue(struct drbd_conf *mdev);
+extern void drbd_free_tl_hash(struct drbd_conf *mdev);
/* yes, there is kernel_setsockopt, but only since 2.6.18. we don't need to
* mess with get_fs/set_fs, we know we are KERNEL_DS always. */
@@ -1600,6 +1684,8 @@ void drbd_bcast_ee(struct drbd_conf *mdev,
#define susp_MASK 1
#define user_isp_MASK 1
#define aftr_isp_MASK 1
+#define susp_nod_MASK 1
+#define susp_fen_MASK 1
#define NS(T, S) \
({ union drbd_state mask; mask.i = 0; mask.T = T##_MASK; mask; }), \
@@ -1856,13 +1942,6 @@ static inline sector_t drbd_md_ss__(struct drbd_conf *mdev,
}
static inline void
-_drbd_queue_work(struct drbd_work_queue *q, struct drbd_work *w)
-{
- list_add_tail(&w->list, &q->q);
- up(&q->s);
-}
-
-static inline void
drbd_queue_work_front(struct drbd_work_queue *q, struct drbd_work *w)
{
unsigned long flags;
@@ -1899,19 +1978,19 @@ static inline void request_ping(struct drbd_conf *mdev)
static inline int drbd_send_short_cmd(struct drbd_conf *mdev,
enum drbd_packets cmd)
{
- struct p_header h;
+ struct p_header80 h;
return drbd_send_cmd(mdev, USE_DATA_SOCKET, cmd, &h, sizeof(h));
}
static inline int drbd_send_ping(struct drbd_conf *mdev)
{
- struct p_header h;
+ struct p_header80 h;
return drbd_send_cmd(mdev, USE_META_SOCKET, P_PING, &h, sizeof(h));
}
static inline int drbd_send_ping_ack(struct drbd_conf *mdev)
{
- struct p_header h;
+ struct p_header80 h;
return drbd_send_cmd(mdev, USE_META_SOCKET, P_PING_ACK, &h, sizeof(h));
}
@@ -2013,7 +2092,7 @@ static inline void inc_unacked(struct drbd_conf *mdev)
static inline void put_net_conf(struct drbd_conf *mdev)
{
if (atomic_dec_and_test(&mdev->net_cnt))
- wake_up(&mdev->misc_wait);
+ wake_up(&mdev->net_cnt_wait);
}
/**
@@ -2044,10 +2123,14 @@ static inline int get_net_conf(struct drbd_conf *mdev)
static inline void put_ldev(struct drbd_conf *mdev)
{
+ int i = atomic_dec_return(&mdev->local_cnt);
__release(local);
- if (atomic_dec_and_test(&mdev->local_cnt))
+ D_ASSERT(i >= 0);
+ if (i == 0) {
+ if (mdev->state.disk == D_FAILED)
+ drbd_go_diskless(mdev);
wake_up(&mdev->misc_wait);
- D_ASSERT(atomic_read(&mdev->local_cnt) >= 0);
+ }
}
#ifndef __CHECKER__
@@ -2179,11 +2262,16 @@ static inline int drbd_state_is_stable(union drbd_state s)
return 1;
}
+static inline int is_susp(union drbd_state s)
+{
+ return s.susp || s.susp_nod || s.susp_fen;
+}
+
static inline int __inc_ap_bio_cond(struct drbd_conf *mdev)
{
int mxb = drbd_get_max_buffers(mdev);
- if (mdev->state.susp)
+ if (is_susp(mdev->state))
return 0;
if (test_bit(SUSPEND_IO, &mdev->flags))
return 0;
@@ -2321,8 +2409,7 @@ static inline void drbd_md_flush(struct drbd_conf *mdev)
if (test_bit(MD_NO_BARRIER, &mdev->flags))
return;
- r = blkdev_issue_flush(mdev->ldev->md_bdev, GFP_KERNEL, NULL,
- BLKDEV_IFL_WAIT);
+ r = blkdev_issue_flush(mdev->ldev->md_bdev, GFP_KERNEL, NULL);
if (r) {
set_bit(MD_NO_BARRIER, &mdev->flags);
dev_err(DEV, "meta data flush failed with status %d, disabling md-flushes\n", r);
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index fa650dd85b90..c5dfe6486cf3 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -32,7 +32,7 @@
#include <asm/types.h>
#include <net/sock.h>
#include <linux/ctype.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/fs.h>
#include <linux/file.h>
#include <linux/proc_fs.h>
@@ -64,6 +64,7 @@ struct after_state_chg_work {
struct completion *done;
};
+static DEFINE_MUTEX(drbd_main_mutex);
int drbdd_init(struct drbd_thread *);
int drbd_worker(struct drbd_thread *);
int drbd_asender(struct drbd_thread *);
@@ -77,6 +78,7 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
static int w_md_sync(struct drbd_conf *mdev, struct drbd_work *w, int unused);
static void md_sync_timer_fn(unsigned long data);
static int w_bitmap_io(struct drbd_conf *mdev, struct drbd_work *w, int unused);
+static int w_go_diskless(struct drbd_conf *mdev, struct drbd_work *w, int unused);
MODULE_AUTHOR("Philipp Reisner <phil@linbit.com>, "
"Lars Ellenberg <lars@linbit.com>");
@@ -199,7 +201,7 @@ static int tl_init(struct drbd_conf *mdev)
INIT_LIST_HEAD(&b->w.list);
b->next = NULL;
b->br_number = 4711;
- b->n_req = 0;
+ b->n_writes = 0;
b->w.cb = NULL; /* if this is != NULL, we need to dec_ap_pending in tl_clear */
mdev->oldest_tle = b;
@@ -240,7 +242,7 @@ void _tl_add_barrier(struct drbd_conf *mdev, struct drbd_tl_epoch *new)
INIT_LIST_HEAD(&new->w.list);
new->w.cb = NULL; /* if this is != NULL, we need to dec_ap_pending in tl_clear */
new->next = NULL;
- new->n_req = 0;
+ new->n_writes = 0;
newest_before = mdev->newest_tle;
/* never send a barrier number == 0, because that is special-cased
@@ -284,9 +286,9 @@ void tl_release(struct drbd_conf *mdev, unsigned int barrier_nr,
barrier_nr, b->br_number);
goto bail;
}
- if (b->n_req != set_size) {
- dev_err(DEV, "BAD! BarrierAck #%u received with n_req=%u, expected n_req=%u!\n",
- barrier_nr, set_size, b->n_req);
+ if (b->n_writes != set_size) {
+ dev_err(DEV, "BAD! BarrierAck #%u received with n_writes=%u, expected n_writes=%u!\n",
+ barrier_nr, set_size, b->n_writes);
goto bail;
}
@@ -333,6 +335,82 @@ bail:
drbd_force_state(mdev, NS(conn, C_PROTOCOL_ERROR));
}
+/**
+ * _tl_restart() - Walks the transfer log, and applies an action to all requests
+ * @mdev: DRBD device.
+ * @what: The action/event to perform with all request objects
+ *
+ * @what might be one of connection_lost_while_pending, resend, fail_frozen_disk_io,
+ * restart_frozen_disk_io.
+ */
+static void _tl_restart(struct drbd_conf *mdev, enum drbd_req_event what)
+{
+ struct drbd_tl_epoch *b, *tmp, **pn;
+ struct list_head *le, *tle, carry_reads;
+ struct drbd_request *req;
+ int rv, n_writes, n_reads;
+
+ b = mdev->oldest_tle;
+ pn = &mdev->oldest_tle;
+ while (b) {
+ n_writes = 0;
+ n_reads = 0;
+ INIT_LIST_HEAD(&carry_reads);
+ list_for_each_safe(le, tle, &b->requests) {
+ req = list_entry(le, struct drbd_request, tl_requests);
+ rv = _req_mod(req, what);
+
+ n_writes += (rv & MR_WRITE) >> MR_WRITE_SHIFT;
+ n_reads += (rv & MR_READ) >> MR_READ_SHIFT;
+ }
+ tmp = b->next;
+
+ if (n_writes) {
+ if (what == resend) {
+ b->n_writes = n_writes;
+ if (b->w.cb == NULL) {
+ b->w.cb = w_send_barrier;
+ inc_ap_pending(mdev);
+ set_bit(CREATE_BARRIER, &mdev->flags);
+ }
+
+ drbd_queue_work(&mdev->data.work, &b->w);
+ }
+ pn = &b->next;
+ } else {
+ if (n_reads)
+ list_add(&carry_reads, &b->requests);
+ /* there could still be requests on that ring list,
+ * in case local io is still pending */
+ list_del(&b->requests);
+
+ /* dec_ap_pending corresponding to queue_barrier.
+ * the newest barrier may not have been queued yet,
+ * in which case w.cb is still NULL. */
+ if (b->w.cb != NULL)
+ dec_ap_pending(mdev);
+
+ if (b == mdev->newest_tle) {
+ /* recycle, but reinit! */
+ D_ASSERT(tmp == NULL);
+ INIT_LIST_HEAD(&b->requests);
+ list_splice(&carry_reads, &b->requests);
+ INIT_LIST_HEAD(&b->w.list);
+ b->w.cb = NULL;
+ b->br_number = net_random();
+ b->n_writes = 0;
+
+ *pn = b;
+ break;
+ }
+ *pn = tmp;
+ kfree(b);
+ }
+ b = tmp;
+ list_splice(&carry_reads, &b->requests);
+ }
+}
+
/**
* tl_clear() - Clears all requests and &struct drbd_tl_epoch objects out of the TL
@@ -344,48 +422,12 @@ bail:
*/
void tl_clear(struct drbd_conf *mdev)
{
- struct drbd_tl_epoch *b, *tmp;
struct list_head *le, *tle;
struct drbd_request *r;
- int new_initial_bnr = net_random();
spin_lock_irq(&mdev->req_lock);
- b = mdev->oldest_tle;
- while (b) {
- list_for_each_safe(le, tle, &b->requests) {
- r = list_entry(le, struct drbd_request, tl_requests);
- /* It would be nice to complete outside of spinlock.
- * But this is easier for now. */
- _req_mod(r, connection_lost_while_pending);
- }
- tmp = b->next;
-
- /* there could still be requests on that ring list,
- * in case local io is still pending */
- list_del(&b->requests);
-
- /* dec_ap_pending corresponding to queue_barrier.
- * the newest barrier may not have been queued yet,
- * in which case w.cb is still NULL. */
- if (b->w.cb != NULL)
- dec_ap_pending(mdev);
-
- if (b == mdev->newest_tle) {
- /* recycle, but reinit! */
- D_ASSERT(tmp == NULL);
- INIT_LIST_HEAD(&b->requests);
- INIT_LIST_HEAD(&b->w.list);
- b->w.cb = NULL;
- b->br_number = new_initial_bnr;
- b->n_req = 0;
-
- mdev->oldest_tle = b;
- break;
- }
- kfree(b);
- b = tmp;
- }
+ _tl_restart(mdev, connection_lost_while_pending);
/* we expect this list to be empty. */
D_ASSERT(list_empty(&mdev->out_of_sequence_requests));
@@ -401,6 +443,15 @@ void tl_clear(struct drbd_conf *mdev)
/* ensure bit indicating barrier is required is clear */
clear_bit(CREATE_BARRIER, &mdev->flags);
+ memset(mdev->app_reads_hash, 0, APP_R_HSIZE*sizeof(void *));
+
+ spin_unlock_irq(&mdev->req_lock);
+}
+
+void tl_restart(struct drbd_conf *mdev, enum drbd_req_event what)
+{
+ spin_lock_irq(&mdev->req_lock);
+ _tl_restart(mdev, what);
spin_unlock_irq(&mdev->req_lock);
}
@@ -455,7 +506,7 @@ static int is_valid_state(struct drbd_conf *mdev, union drbd_state ns);
static int is_valid_state_transition(struct drbd_conf *,
union drbd_state, union drbd_state);
static union drbd_state sanitize_state(struct drbd_conf *mdev, union drbd_state os,
- union drbd_state ns, int *warn_sync_abort);
+ union drbd_state ns, const char **warn_sync_abort);
int drbd_send_state_req(struct drbd_conf *,
union drbd_state, union drbd_state);
@@ -605,7 +656,7 @@ static void print_st(struct drbd_conf *mdev, char *name, union drbd_state ns)
drbd_role_str(ns.peer),
drbd_disk_str(ns.disk),
drbd_disk_str(ns.pdsk),
- ns.susp ? 's' : 'r',
+ is_susp(ns) ? 's' : 'r',
ns.aftr_isp ? 'a' : '-',
ns.peer_isp ? 'p' : '-',
ns.user_isp ? 'u' : '-'
@@ -763,7 +814,7 @@ static int is_valid_state_transition(struct drbd_conf *mdev,
* to D_UNKNOWN. This rule and many more along those lines are in this function.
*/
static union drbd_state sanitize_state(struct drbd_conf *mdev, union drbd_state os,
- union drbd_state ns, int *warn_sync_abort)
+ union drbd_state ns, const char **warn_sync_abort)
{
enum drbd_fencing_p fp;
@@ -778,9 +829,10 @@ static union drbd_state sanitize_state(struct drbd_conf *mdev, union drbd_state
os.conn <= C_DISCONNECTING)
ns.conn = os.conn;
- /* After a network error (+C_TEAR_DOWN) only C_UNCONNECTED or C_DISCONNECTING can follow */
+ /* After a network error (+C_TEAR_DOWN) only C_UNCONNECTED or C_DISCONNECTING can follow.
+ * If you try to go into some Sync* state, that shall fail (elsewhere). */
if (os.conn >= C_TIMEOUT && os.conn <= C_TEAR_DOWN &&
- ns.conn != C_UNCONNECTED && ns.conn != C_DISCONNECTING)
+ ns.conn != C_UNCONNECTED && ns.conn != C_DISCONNECTING && ns.conn <= C_TEAR_DOWN)
ns.conn = os.conn;
/* After C_DISCONNECTING only C_STANDALONE may follow */
@@ -798,14 +850,13 @@ static union drbd_state sanitize_state(struct drbd_conf *mdev, union drbd_state
if (ns.conn == C_STANDALONE && ns.disk == D_DISKLESS && ns.role == R_SECONDARY)
ns.aftr_isp = 0;
- if (ns.conn <= C_DISCONNECTING && ns.disk == D_DISKLESS)
- ns.pdsk = D_UNKNOWN;
-
/* Abort resync if a disk fails/detaches */
if (os.conn > C_CONNECTED && ns.conn > C_CONNECTED &&
(ns.disk <= D_FAILED || ns.pdsk <= D_FAILED)) {
if (warn_sync_abort)
- *warn_sync_abort = 1;
+ *warn_sync_abort =
+ os.conn == C_VERIFY_S || os.conn == C_VERIFY_T ?
+ "Online-verify" : "Resync";
ns.conn = C_CONNECTED;
}
@@ -876,7 +927,12 @@ static union drbd_state sanitize_state(struct drbd_conf *mdev, union drbd_state
if (fp == FP_STONITH &&
(ns.role == R_PRIMARY && ns.conn < C_CONNECTED && ns.pdsk > D_OUTDATED) &&
!(os.role == R_PRIMARY && os.conn < C_CONNECTED && os.pdsk > D_OUTDATED))
- ns.susp = 1;
+ ns.susp_fen = 1; /* Suspend IO while fence-peer handler runs (peer lost) */
+
+ if (mdev->sync_conf.on_no_data == OND_SUSPEND_IO &&
+ (ns.role == R_PRIMARY && ns.disk < D_UP_TO_DATE && ns.pdsk < D_UP_TO_DATE) &&
+ !(os.role == R_PRIMARY && os.disk < D_UP_TO_DATE && os.pdsk < D_UP_TO_DATE))
+ ns.susp_nod = 1; /* Suspend IO while no data available (no accessible data available) */
if (ns.aftr_isp || ns.peer_isp || ns.user_isp) {
if (ns.conn == C_SYNC_SOURCE)
@@ -912,6 +968,12 @@ static void set_ov_position(struct drbd_conf *mdev, enum drbd_conns cs)
}
}
+static void drbd_resume_al(struct drbd_conf *mdev)
+{
+ if (test_and_clear_bit(AL_SUSPENDED, &mdev->flags))
+ dev_info(DEV, "Resumed AL updates\n");
+}
+
/**
* __drbd_set_state() - Set a new DRBD state
* @mdev: DRBD device.
@@ -927,7 +989,7 @@ int __drbd_set_state(struct drbd_conf *mdev,
{
union drbd_state os;
int rv = SS_SUCCESS;
- int warn_sync_abort = 0;
+ const char *warn_sync_abort = NULL;
struct after_state_chg_work *ascw;
os = mdev->state;
@@ -946,14 +1008,8 @@ int __drbd_set_state(struct drbd_conf *mdev,
/* If the old state was illegal as well, then let
this happen...*/
- if (is_valid_state(mdev, os) == rv) {
- dev_err(DEV, "Considering state change from bad state. "
- "Error would be: '%s'\n",
- drbd_set_st_err_str(rv));
- print_st(mdev, "old", os);
- print_st(mdev, "new", ns);
+ if (is_valid_state(mdev, os) == rv)
rv = is_valid_state_transition(mdev, ns, os);
- }
} else
rv = is_valid_state_transition(mdev, ns, os);
}
@@ -965,7 +1021,7 @@ int __drbd_set_state(struct drbd_conf *mdev,
}
if (warn_sync_abort)
- dev_warn(DEV, "Resync aborted.\n");
+ dev_warn(DEV, "%s aborted.\n", warn_sync_abort);
{
char *pbp, pb[300];
@@ -976,7 +1032,10 @@ int __drbd_set_state(struct drbd_conf *mdev,
PSC(conn);
PSC(disk);
PSC(pdsk);
- PSC(susp);
+ if (is_susp(ns) != is_susp(os))
+ pbp += sprintf(pbp, "susp( %s -> %s ) ",
+ drbd_susp_str(is_susp(os)),
+ drbd_susp_str(is_susp(ns)));
PSC(aftr_isp);
PSC(peer_isp);
PSC(user_isp);
@@ -1001,12 +1060,6 @@ int __drbd_set_state(struct drbd_conf *mdev,
wake_up(&mdev->misc_wait);
wake_up(&mdev->state_wait);
- /* post-state-change actions */
- if (os.conn >= C_SYNC_SOURCE && ns.conn <= C_CONNECTED) {
- set_bit(STOP_SYNC_TIMER, &mdev->flags);
- mod_timer(&mdev->resync_timer, jiffies);
- }
-
/* aborted verify run. log the last position */
if ((os.conn == C_VERIFY_S || os.conn == C_VERIFY_T) &&
ns.conn < C_CONNECTED) {
@@ -1019,41 +1072,42 @@ int __drbd_set_state(struct drbd_conf *mdev,
if ((os.conn == C_PAUSED_SYNC_T || os.conn == C_PAUSED_SYNC_S) &&
(ns.conn == C_SYNC_TARGET || ns.conn == C_SYNC_SOURCE)) {
dev_info(DEV, "Syncer continues.\n");
- mdev->rs_paused += (long)jiffies-(long)mdev->rs_mark_time;
- if (ns.conn == C_SYNC_TARGET) {
- if (!test_and_clear_bit(STOP_SYNC_TIMER, &mdev->flags))
- mod_timer(&mdev->resync_timer, jiffies);
- /* This if (!test_bit) is only needed for the case
- that a device that has ceased to used its timer,
- i.e. it is already in drbd_resync_finished() gets
- paused and resumed. */
- }
+ mdev->rs_paused += (long)jiffies
+ -(long)mdev->rs_mark_time[mdev->rs_last_mark];
+ if (ns.conn == C_SYNC_TARGET)
+ mod_timer(&mdev->resync_timer, jiffies);
}
if ((os.conn == C_SYNC_TARGET || os.conn == C_SYNC_SOURCE) &&
(ns.conn == C_PAUSED_SYNC_T || ns.conn == C_PAUSED_SYNC_S)) {
dev_info(DEV, "Resync suspended\n");
- mdev->rs_mark_time = jiffies;
- if (ns.conn == C_PAUSED_SYNC_T)
- set_bit(STOP_SYNC_TIMER, &mdev->flags);
+ mdev->rs_mark_time[mdev->rs_last_mark] = jiffies;
}
if (os.conn == C_CONNECTED &&
(ns.conn == C_VERIFY_S || ns.conn == C_VERIFY_T)) {
+ unsigned long now = jiffies;
+ int i;
+
mdev->ov_position = 0;
- mdev->rs_total =
- mdev->rs_mark_left = drbd_bm_bits(mdev);
+ mdev->rs_total = drbd_bm_bits(mdev);
if (mdev->agreed_pro_version >= 90)
set_ov_position(mdev, ns.conn);
else
mdev->ov_start_sector = 0;
mdev->ov_left = mdev->rs_total
- BM_SECT_TO_BIT(mdev->ov_position);
- mdev->rs_start =
- mdev->rs_mark_time = jiffies;
+ mdev->rs_start = now;
+ mdev->rs_last_events = 0;
+ mdev->rs_last_sect_ev = 0;
mdev->ov_last_oos_size = 0;
mdev->ov_last_oos_start = 0;
+ for (i = 0; i < DRBD_SYNC_MARKS; i++) {
+ mdev->rs_mark_left[i] = mdev->rs_total;
+ mdev->rs_mark_time[i] = now;
+ }
+
if (ns.conn == C_VERIFY_S) {
dev_info(DEV, "Starting Online Verify from sector %llu\n",
(unsigned long long)mdev->ov_position);
@@ -1106,6 +1160,10 @@ int __drbd_set_state(struct drbd_conf *mdev,
ns.conn <= C_TEAR_DOWN && ns.conn >= C_TIMEOUT)
drbd_thread_restart_nowait(&mdev->receiver);
+ /* Resume AL writing if we get a connection */
+ if (os.conn < C_CONNECTED && ns.conn >= C_CONNECTED)
+ drbd_resume_al(mdev);
+
ascw = kmalloc(sizeof(*ascw), GFP_ATOMIC);
if (ascw) {
ascw->os = os;
@@ -1164,6 +1222,8 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
union drbd_state ns, enum chg_state_flags flags)
{
enum drbd_fencing_p fp;
+ enum drbd_req_event what = nothing;
+ union drbd_state nsm = (union drbd_state){ .i = -1 };
if (os.conn != C_CONNECTED && ns.conn == C_CONNECTED) {
clear_bit(CRASHED_PRIMARY, &mdev->flags);
@@ -1187,17 +1247,49 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
/* Here we have the actions that are performed after a
state change. This function might sleep */
- if (fp == FP_STONITH && ns.susp) {
- /* case1: The outdate peer handler is successful:
- * case2: The connection was established again: */
- if ((os.pdsk > D_OUTDATED && ns.pdsk <= D_OUTDATED) ||
- (os.conn < C_CONNECTED && ns.conn >= C_CONNECTED)) {
+ nsm.i = -1;
+ if (ns.susp_nod) {
+ if (os.conn < C_CONNECTED && ns.conn >= C_CONNECTED) {
+ if (ns.conn == C_CONNECTED)
+ what = resend, nsm.susp_nod = 0;
+ else /* ns.conn > C_CONNECTED */
+ dev_err(DEV, "Unexpected Resynd going on!\n");
+ }
+
+ if (os.disk == D_ATTACHING && ns.disk > D_ATTACHING)
+ what = restart_frozen_disk_io, nsm.susp_nod = 0;
+
+ }
+
+ if (ns.susp_fen) {
+ /* case1: The outdate peer handler is successful: */
+ if (os.pdsk > D_OUTDATED && ns.pdsk <= D_OUTDATED) {
tl_clear(mdev);
+ if (test_bit(NEW_CUR_UUID, &mdev->flags)) {
+ drbd_uuid_new_current(mdev);
+ clear_bit(NEW_CUR_UUID, &mdev->flags);
+ drbd_md_sync(mdev);
+ }
spin_lock_irq(&mdev->req_lock);
- _drbd_set_state(_NS(mdev, susp, 0), CS_VERBOSE, NULL);
+ _drbd_set_state(_NS(mdev, susp_fen, 0), CS_VERBOSE, NULL);
spin_unlock_irq(&mdev->req_lock);
}
+ /* case2: The connection was established again: */
+ if (os.conn < C_CONNECTED && ns.conn >= C_CONNECTED) {
+ clear_bit(NEW_CUR_UUID, &mdev->flags);
+ what = resend;
+ nsm.susp_fen = 0;
+ }
+ }
+
+ if (what != nothing) {
+ spin_lock_irq(&mdev->req_lock);
+ _tl_restart(mdev, what);
+ nsm.i &= mdev->state.i;
+ _drbd_set_state(mdev, nsm, CS_VERBOSE, NULL);
+ spin_unlock_irq(&mdev->req_lock);
}
+
/* Do not change the order of the if above and the two below... */
if (os.pdsk == D_DISKLESS && ns.pdsk > D_DISKLESS) { /* attach on the peer */
drbd_send_uuids(mdev);
@@ -1216,16 +1308,22 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
if (get_ldev(mdev)) {
if ((ns.role == R_PRIMARY || ns.peer == R_PRIMARY) &&
mdev->ldev->md.uuid[UI_BITMAP] == 0 && ns.disk >= D_UP_TO_DATE) {
- drbd_uuid_new_current(mdev);
- drbd_send_uuids(mdev);
+ if (is_susp(mdev->state)) {
+ set_bit(NEW_CUR_UUID, &mdev->flags);
+ } else {
+ drbd_uuid_new_current(mdev);
+ drbd_send_uuids(mdev);
+ }
}
put_ldev(mdev);
}
}
if (ns.pdsk < D_INCONSISTENT && get_ldev(mdev)) {
- if (ns.peer == R_PRIMARY && mdev->ldev->md.uuid[UI_BITMAP] == 0)
+ if (ns.peer == R_PRIMARY && mdev->ldev->md.uuid[UI_BITMAP] == 0) {
drbd_uuid_new_current(mdev);
+ drbd_send_uuids(mdev);
+ }
/* D_DISKLESS Peer becomes secondary */
if (os.peer == R_PRIMARY && ns.peer == R_SECONDARY)
@@ -1267,42 +1365,51 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
os.disk > D_INCONSISTENT && ns.disk == D_INCONSISTENT)
drbd_queue_bitmap_io(mdev, &drbd_bmio_set_n_write, NULL, "set_n_write from invalidate");
+ /* first half of local IO error */
if (os.disk > D_FAILED && ns.disk == D_FAILED) {
- enum drbd_io_error_p eh;
+ enum drbd_io_error_p eh = EP_PASS_ON;
+
+ if (drbd_send_state(mdev))
+ dev_warn(DEV, "Notified peer that my disk is broken.\n");
+ else
+ dev_err(DEV, "Sending state for drbd_io_error() failed\n");
+
+ drbd_rs_cancel_all(mdev);
- eh = EP_PASS_ON;
if (get_ldev_if_state(mdev, D_FAILED)) {
eh = mdev->ldev->dc.on_io_error;
put_ldev(mdev);
}
+ if (eh == EP_CALL_HELPER)
+ drbd_khelper(mdev, "local-io-error");
+ }
- drbd_rs_cancel_all(mdev);
- /* since get_ldev() only works as long as disk>=D_INCONSISTENT,
- and it is D_DISKLESS here, local_cnt can only go down, it can
- not increase... It will reach zero */
- wait_event(mdev->misc_wait, !atomic_read(&mdev->local_cnt));
+
+ /* second half of local IO error handling,
+ * after local_cnt references have reached zero: */
+ if (os.disk == D_FAILED && ns.disk == D_DISKLESS) {
mdev->rs_total = 0;
mdev->rs_failed = 0;
atomic_set(&mdev->rs_pending_cnt, 0);
-
- spin_lock_irq(&mdev->req_lock);
- _drbd_set_state(_NS(mdev, disk, D_DISKLESS), CS_HARD, NULL);
- spin_unlock_irq(&mdev->req_lock);
-
- if (eh == EP_CALL_HELPER)
- drbd_khelper(mdev, "local-io-error");
}
if (os.disk > D_DISKLESS && ns.disk == D_DISKLESS) {
+ /* We must still be diskless,
+ * re-attach has to be serialized with this! */
+ if (mdev->state.disk != D_DISKLESS)
+ dev_err(DEV,
+ "ASSERT FAILED: disk is %s while going diskless\n",
+ drbd_disk_str(mdev->state.disk));
+
+ /* we cannot assert local_cnt == 0 here, as get_ldev_if_state
+ * will inc/dec it frequently. Since we became D_DISKLESS, no
+ * one has touched the protected members anymore, though, so we
+ * are safe to free them here. */
+ if (drbd_send_state(mdev))
+ dev_warn(DEV, "Notified peer that I detached my disk.\n");
+ else
+ dev_err(DEV, "Sending state for detach failed\n");
- if (os.disk == D_FAILED) /* && ns.disk == D_DISKLESS*/ {
- if (drbd_send_state(mdev))
- dev_warn(DEV, "Notified peer that my disk is broken.\n");
- else
- dev_err(DEV, "Sending state in drbd_io_error() failed\n");
- }
-
- wait_event(mdev->misc_wait, !atomic_read(&mdev->local_cnt));
lc_destroy(mdev->resync);
mdev->resync = NULL;
lc_destroy(mdev->act_log);
@@ -1311,8 +1418,10 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
drbd_free_bc(mdev->ldev);
mdev->ldev = NULL;);
- if (mdev->md_io_tmpp)
+ if (mdev->md_io_tmpp) {
__free_page(mdev->md_io_tmpp);
+ mdev->md_io_tmpp = NULL;
+ }
}
/* Disks got bigger while they were detached */
@@ -1328,6 +1437,15 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
(os.user_isp && !ns.user_isp))
resume_next_sg(mdev);
+ /* sync target done with resync. Explicitly notify peer, even though
+ * it should (at least for non-empty resyncs) already know itself. */
+ if (os.disk < D_UP_TO_DATE && os.conn >= C_SYNC_SOURCE && ns.conn == C_CONNECTED)
+ drbd_send_state(mdev);
+
+ /* free tl_hash if we Got thawed and are C_STANDALONE */
+ if (ns.conn == C_STANDALONE && !is_susp(ns) && mdev->tl_hash)
+ drbd_free_tl_hash(mdev);
+
/* Upon network connection, we need to start the receiver */
if (os.conn == C_STANDALONE && ns.conn == C_UNCONNECTED)
drbd_thread_start(&mdev->receiver);
@@ -1554,7 +1672,7 @@ void drbd_thread_current_set_cpu(struct drbd_conf *mdev)
/* the appropriate socket mutex must be held already */
int _drbd_send_cmd(struct drbd_conf *mdev, struct socket *sock,
- enum drbd_packets cmd, struct p_header *h,
+ enum drbd_packets cmd, struct p_header80 *h,
size_t size, unsigned msg_flags)
{
int sent, ok;
@@ -1564,7 +1682,7 @@ int _drbd_send_cmd(struct drbd_conf *mdev, struct socket *sock,
h->magic = BE_DRBD_MAGIC;
h->command = cpu_to_be16(cmd);
- h->length = cpu_to_be16(size-sizeof(struct p_header));
+ h->length = cpu_to_be16(size-sizeof(struct p_header80));
sent = drbd_send(mdev, sock, h, size, msg_flags);
@@ -1579,7 +1697,7 @@ int _drbd_send_cmd(struct drbd_conf *mdev, struct socket *sock,
* when we hold the appropriate socket mutex.
*/
int drbd_send_cmd(struct drbd_conf *mdev, int use_data_socket,
- enum drbd_packets cmd, struct p_header *h, size_t size)
+ enum drbd_packets cmd, struct p_header80 *h, size_t size)
{
int ok = 0;
struct socket *sock;
@@ -1607,7 +1725,7 @@ int drbd_send_cmd(struct drbd_conf *mdev, int use_data_socket,
int drbd_send_cmd2(struct drbd_conf *mdev, enum drbd_packets cmd, char *data,
size_t size)
{
- struct p_header h;
+ struct p_header80 h;
int ok;
h.magic = BE_DRBD_MAGIC;
@@ -1629,7 +1747,7 @@ int drbd_send_cmd2(struct drbd_conf *mdev, enum drbd_packets cmd, char *data,
int drbd_send_sync_param(struct drbd_conf *mdev, struct syncer_conf *sc)
{
- struct p_rs_param_89 *p;
+ struct p_rs_param_95 *p;
struct socket *sock;
int size, rv;
const int apv = mdev->agreed_pro_version;
@@ -1637,7 +1755,8 @@ int drbd_send_sync_param(struct drbd_conf *mdev, struct syncer_conf *sc)
size = apv <= 87 ? sizeof(struct p_rs_param)
: apv == 88 ? sizeof(struct p_rs_param)
+ strlen(mdev->sync_conf.verify_alg) + 1
- : /* 89 */ sizeof(struct p_rs_param_89);
+ : apv <= 94 ? sizeof(struct p_rs_param_89)
+ : /* apv >= 95 */ sizeof(struct p_rs_param_95);
/* used from admin command context and receiver/worker context.
* to avoid kmalloc, grab the socket right here,
@@ -1648,12 +1767,16 @@ int drbd_send_sync_param(struct drbd_conf *mdev, struct syncer_conf *sc)
if (likely(sock != NULL)) {
enum drbd_packets cmd = apv >= 89 ? P_SYNC_PARAM89 : P_SYNC_PARAM;
- p = &mdev->data.sbuf.rs_param_89;
+ p = &mdev->data.sbuf.rs_param_95;
/* initialize verify_alg and csums_alg */
memset(p->verify_alg, 0, 2 * SHARED_SECRET_MAX);
p->rate = cpu_to_be32(sc->rate);
+ p->c_plan_ahead = cpu_to_be32(sc->c_plan_ahead);
+ p->c_delay_target = cpu_to_be32(sc->c_delay_target);
+ p->c_fill_target = cpu_to_be32(sc->c_fill_target);
+ p->c_max_rate = cpu_to_be32(sc->c_max_rate);
if (apv >= 88)
strcpy(p->verify_alg, mdev->sync_conf.verify_alg);
@@ -1709,7 +1832,7 @@ int drbd_send_protocol(struct drbd_conf *mdev)
strcpy(p->integrity_alg, mdev->net_conf->integrity_alg);
rv = drbd_send_cmd(mdev, USE_DATA_SOCKET, P_PROTOCOL,
- (struct p_header *)p, size);
+ (struct p_header80 *)p, size);
kfree(p);
return rv;
}
@@ -1735,7 +1858,7 @@ int _drbd_send_uuids(struct drbd_conf *mdev, u64 uuid_flags)
put_ldev(mdev);
return drbd_send_cmd(mdev, USE_DATA_SOCKET, P_UUIDS,
- (struct p_header *)&p, sizeof(p));
+ (struct p_header80 *)&p, sizeof(p));
}
int drbd_send_uuids(struct drbd_conf *mdev)
@@ -1756,7 +1879,7 @@ int drbd_send_sync_uuid(struct drbd_conf *mdev, u64 val)
p.uuid = cpu_to_be64(val);
return drbd_send_cmd(mdev, USE_DATA_SOCKET, P_SYNC_UUID,
- (struct p_header *)&p, sizeof(p));
+ (struct p_header80 *)&p, sizeof(p));
}
int drbd_send_sizes(struct drbd_conf *mdev, int trigger_reply, enum dds_flags flags)
@@ -1786,7 +1909,7 @@ int drbd_send_sizes(struct drbd_conf *mdev, int trigger_reply, enum dds_flags fl
p.dds_flags = cpu_to_be16(flags);
ok = drbd_send_cmd(mdev, USE_DATA_SOCKET, P_SIZES,
- (struct p_header *)&p, sizeof(p));
+ (struct p_header80 *)&p, sizeof(p));
return ok;
}
@@ -1811,7 +1934,7 @@ int drbd_send_state(struct drbd_conf *mdev)
if (likely(sock != NULL)) {
ok = _drbd_send_cmd(mdev, sock, P_STATE,
- (struct p_header *)&p, sizeof(p), 0);
+ (struct p_header80 *)&p, sizeof(p), 0);
}
mutex_unlock(&mdev->data.mutex);
@@ -1829,7 +1952,7 @@ int drbd_send_state_req(struct drbd_conf *mdev,
p.val = cpu_to_be32(val.i);
return drbd_send_cmd(mdev, USE_DATA_SOCKET, P_STATE_CHG_REQ,
- (struct p_header *)&p, sizeof(p));
+ (struct p_header80 *)&p, sizeof(p));
}
int drbd_send_sr_reply(struct drbd_conf *mdev, int retcode)
@@ -1839,7 +1962,7 @@ int drbd_send_sr_reply(struct drbd_conf *mdev, int retcode)
p.retcode = cpu_to_be32(retcode);
return drbd_send_cmd(mdev, USE_META_SOCKET, P_STATE_CHG_REPLY,
- (struct p_header *)&p, sizeof(p));
+ (struct p_header80 *)&p, sizeof(p));
}
int fill_bitmap_rle_bits(struct drbd_conf *mdev,
@@ -1938,7 +2061,7 @@ int fill_bitmap_rle_bits(struct drbd_conf *mdev,
enum { OK, FAILED, DONE }
send_bitmap_rle_or_plain(struct drbd_conf *mdev,
- struct p_header *h, struct bm_xfer_ctx *c)
+ struct p_header80 *h, struct bm_xfer_ctx *c)
{
struct p_compressed_bm *p = (void*)h;
unsigned long num_words;
@@ -1968,12 +2091,12 @@ send_bitmap_rle_or_plain(struct drbd_conf *mdev,
if (len)
drbd_bm_get_lel(mdev, c->word_offset, num_words, (unsigned long*)h->payload);
ok = _drbd_send_cmd(mdev, mdev->data.socket, P_BITMAP,
- h, sizeof(struct p_header) + len, 0);
+ h, sizeof(struct p_header80) + len, 0);
c->word_offset += num_words;
c->bit_offset = c->word_offset * BITS_PER_LONG;
c->packets[1]++;
- c->bytes[1] += sizeof(struct p_header) + len;
+ c->bytes[1] += sizeof(struct p_header80) + len;
if (c->bit_offset > c->bm_bits)
c->bit_offset = c->bm_bits;
@@ -1989,14 +2112,14 @@ send_bitmap_rle_or_plain(struct drbd_conf *mdev,
int _drbd_send_bitmap(struct drbd_conf *mdev)
{
struct bm_xfer_ctx c;
- struct p_header *p;
+ struct p_header80 *p;
int ret;
ERR_IF(!mdev->bitmap) return FALSE;
/* maybe we should use some per thread scratch page,
* and allocate that during initial device creation? */
- p = (struct p_header *) __get_free_page(GFP_NOIO);
+ p = (struct p_header80 *) __get_free_page(GFP_NOIO);
if (!p) {
dev_err(DEV, "failed to allocate one page buffer in %s\n", __func__);
return FALSE;
@@ -2054,7 +2177,7 @@ int drbd_send_b_ack(struct drbd_conf *mdev, u32 barrier_nr, u32 set_size)
if (mdev->state.conn < C_CONNECTED)
return FALSE;
ok = drbd_send_cmd(mdev, USE_META_SOCKET, P_BARRIER_ACK,
- (struct p_header *)&p, sizeof(p));
+ (struct p_header80 *)&p, sizeof(p));
return ok;
}
@@ -2082,17 +2205,18 @@ static int _drbd_send_ack(struct drbd_conf *mdev, enum drbd_packets cmd,
if (!mdev->meta.socket || mdev->state.conn < C_CONNECTED)
return FALSE;
ok = drbd_send_cmd(mdev, USE_META_SOCKET, cmd,
- (struct p_header *)&p, sizeof(p));
+ (struct p_header80 *)&p, sizeof(p));
return ok;
}
+/* dp->sector and dp->block_id already/still in network byte order,
+ * data_size is payload size according to dp->head,
+ * and may need to be corrected for digest size. */
int drbd_send_ack_dp(struct drbd_conf *mdev, enum drbd_packets cmd,
- struct p_data *dp)
+ struct p_data *dp, int data_size)
{
- const int header_size = sizeof(struct p_data)
- - sizeof(struct p_header);
- int data_size = ((struct p_header *)dp)->length - header_size;
-
+ data_size -= (mdev->agreed_pro_version >= 87 && mdev->integrity_r_tfm) ?
+ crypto_hash_digestsize(mdev->integrity_r_tfm) : 0;
return _drbd_send_ack(mdev, cmd, dp->sector, cpu_to_be32(data_size),
dp->block_id);
}
@@ -2140,7 +2264,7 @@ int drbd_send_drequest(struct drbd_conf *mdev, int cmd,
p.blksize = cpu_to_be32(size);
ok = drbd_send_cmd(mdev, USE_DATA_SOCKET, cmd,
- (struct p_header *)&p, sizeof(p));
+ (struct p_header80 *)&p, sizeof(p));
return ok;
}
@@ -2158,7 +2282,7 @@ int drbd_send_drequest_csum(struct drbd_conf *mdev,
p.head.magic = BE_DRBD_MAGIC;
p.head.command = cpu_to_be16(cmd);
- p.head.length = cpu_to_be16(sizeof(p) - sizeof(struct p_header) + digest_size);
+ p.head.length = cpu_to_be16(sizeof(p) - sizeof(struct p_header80) + digest_size);
mutex_lock(&mdev->data.mutex);
@@ -2180,7 +2304,7 @@ int drbd_send_ov_request(struct drbd_conf *mdev, sector_t sector, int size)
p.blksize = cpu_to_be32(size);
ok = drbd_send_cmd(mdev, USE_DATA_SOCKET, P_OV_REQUEST,
- (struct p_header *)&p, sizeof(p));
+ (struct p_header80 *)&p, sizeof(p));
return ok;
}
@@ -2332,6 +2456,18 @@ static int _drbd_send_zc_ee(struct drbd_conf *mdev, struct drbd_epoch_entry *e)
return 1;
}
+static u32 bio_flags_to_wire(struct drbd_conf *mdev, unsigned long bi_rw)
+{
+ if (mdev->agreed_pro_version >= 95)
+ return (bi_rw & REQ_SYNC ? DP_RW_SYNC : 0) |
+ (bi_rw & REQ_UNPLUG ? DP_UNPLUG : 0) |
+ (bi_rw & REQ_FUA ? DP_FUA : 0) |
+ (bi_rw & REQ_FLUSH ? DP_FLUSH : 0) |
+ (bi_rw & REQ_DISCARD ? DP_DISCARD : 0);
+ else
+ return bi_rw & (REQ_SYNC | REQ_UNPLUG) ? DP_RW_SYNC : 0;
+}
+
/* Used to send write requests
* R_PRIMARY -> Peer (P_DATA)
*/
@@ -2349,30 +2485,25 @@ int drbd_send_dblock(struct drbd_conf *mdev, struct drbd_request *req)
dgs = (mdev->agreed_pro_version >= 87 && mdev->integrity_w_tfm) ?
crypto_hash_digestsize(mdev->integrity_w_tfm) : 0;
- p.head.magic = BE_DRBD_MAGIC;
- p.head.command = cpu_to_be16(P_DATA);
- p.head.length =
- cpu_to_be16(sizeof(p) - sizeof(struct p_header) + dgs + req->size);
+ if (req->size <= DRBD_MAX_SIZE_H80_PACKET) {
+ p.head.h80.magic = BE_DRBD_MAGIC;
+ p.head.h80.command = cpu_to_be16(P_DATA);
+ p.head.h80.length =
+ cpu_to_be16(sizeof(p) - sizeof(union p_header) + dgs + req->size);
+ } else {
+ p.head.h95.magic = BE_DRBD_MAGIC_BIG;
+ p.head.h95.command = cpu_to_be16(P_DATA);
+ p.head.h95.length =
+ cpu_to_be32(sizeof(p) - sizeof(union p_header) + dgs + req->size);
+ }
p.sector = cpu_to_be64(req->sector);
p.block_id = (unsigned long)req;
p.seq_num = cpu_to_be32(req->seq_num =
atomic_add_return(1, &mdev->packet_seq));
- dp_flags = 0;
- /* NOTE: no need to check if barriers supported here as we would
- * not pass the test in make_request_common in that case
- */
- if (req->master_bio->bi_rw & REQ_HARDBARRIER) {
- dev_err(DEV, "ASSERT FAILED would have set DP_HARDBARRIER\n");
- /* dp_flags |= DP_HARDBARRIER; */
- }
- if (req->master_bio->bi_rw & REQ_SYNC)
- dp_flags |= DP_RW_SYNC;
- /* for now handle SYNCIO and UNPLUG
- * as if they still were one and the same flag */
- if (req->master_bio->bi_rw & REQ_UNPLUG)
- dp_flags |= DP_RW_SYNC;
+ dp_flags = bio_flags_to_wire(mdev, req->master_bio->bi_rw);
+
if (mdev->state.conn >= C_SYNC_SOURCE &&
mdev->state.conn <= C_PAUSED_SYNC_T)
dp_flags |= DP_MAY_SET_IN_SYNC;
@@ -2413,10 +2544,17 @@ int drbd_send_block(struct drbd_conf *mdev, enum drbd_packets cmd,
dgs = (mdev->agreed_pro_version >= 87 && mdev->integrity_w_tfm) ?
crypto_hash_digestsize(mdev->integrity_w_tfm) : 0;
- p.head.magic = BE_DRBD_MAGIC;
- p.head.command = cpu_to_be16(cmd);
- p.head.length =
- cpu_to_be16(sizeof(p) - sizeof(struct p_header) + dgs + e->size);
+ if (e->size <= DRBD_MAX_SIZE_H80_PACKET) {
+ p.head.h80.magic = BE_DRBD_MAGIC;
+ p.head.h80.command = cpu_to_be16(cmd);
+ p.head.h80.length =
+ cpu_to_be16(sizeof(p) - sizeof(struct p_header80) + dgs + e->size);
+ } else {
+ p.head.h95.magic = BE_DRBD_MAGIC_BIG;
+ p.head.h95.command = cpu_to_be16(cmd);
+ p.head.h95.length =
+ cpu_to_be32(sizeof(p) - sizeof(struct p_header80) + dgs + e->size);
+ }
p.sector = cpu_to_be64(e->sector);
p.block_id = e->block_id;
@@ -2429,8 +2567,7 @@ int drbd_send_block(struct drbd_conf *mdev, enum drbd_packets cmd,
if (!drbd_get_data_sock(mdev))
return 0;
- ok = sizeof(p) == drbd_send(mdev, mdev->data.socket, &p,
- sizeof(p), dgs ? MSG_MORE : 0);
+ ok = sizeof(p) == drbd_send(mdev, mdev->data.socket, &p, sizeof(p), dgs ? MSG_MORE : 0);
if (ok && dgs) {
dgb = mdev->int_dig_out;
drbd_csum_ee(mdev, mdev->integrity_w_tfm, e, dgb);
@@ -2536,7 +2673,7 @@ static int drbd_open(struct block_device *bdev, fmode_t mode)
unsigned long flags;
int rv = 0;
- lock_kernel();
+ mutex_lock(&drbd_main_mutex);
spin_lock_irqsave(&mdev->req_lock, flags);
/* to have a stable mdev->state.role
* and no race with updating open_cnt */
@@ -2551,7 +2688,7 @@ static int drbd_open(struct block_device *bdev, fmode_t mode)
if (!rv)
mdev->open_cnt++;
spin_unlock_irqrestore(&mdev->req_lock, flags);
- unlock_kernel();
+ mutex_unlock(&drbd_main_mutex);
return rv;
}
@@ -2559,9 +2696,9 @@ static int drbd_open(struct block_device *bdev, fmode_t mode)
static int drbd_release(struct gendisk *gd, fmode_t mode)
{
struct drbd_conf *mdev = gd->private_data;
- lock_kernel();
+ mutex_lock(&drbd_main_mutex);
mdev->open_cnt--;
- unlock_kernel();
+ mutex_unlock(&drbd_main_mutex);
return 0;
}
@@ -2605,7 +2742,13 @@ static void drbd_set_defaults(struct drbd_conf *mdev)
/* .verify_alg = */ {}, 0,
/* .cpu_mask = */ {}, 0,
/* .csums_alg = */ {}, 0,
- /* .use_rle = */ 0
+ /* .use_rle = */ 0,
+ /* .on_no_data = */ DRBD_ON_NO_DATA_DEF,
+ /* .c_plan_ahead = */ DRBD_C_PLAN_AHEAD_DEF,
+ /* .c_delay_target = */ DRBD_C_DELAY_TARGET_DEF,
+ /* .c_fill_target = */ DRBD_C_FILL_TARGET_DEF,
+ /* .c_max_rate = */ DRBD_C_MAX_RATE_DEF,
+ /* .c_min_rate = */ DRBD_C_MIN_RATE_DEF
};
/* Have to use that way, because the layout differs between
@@ -2616,7 +2759,9 @@ static void drbd_set_defaults(struct drbd_conf *mdev)
.conn = C_STANDALONE,
.disk = D_DISKLESS,
.pdsk = D_UNKNOWN,
- .susp = 0
+ .susp = 0,
+ .susp_nod = 0,
+ .susp_fen = 0
} };
}
@@ -2640,6 +2785,9 @@ void drbd_init_set_defaults(struct drbd_conf *mdev)
atomic_set(&mdev->net_cnt, 0);
atomic_set(&mdev->packet_seq, 0);
atomic_set(&mdev->pp_in_use, 0);
+ atomic_set(&mdev->pp_in_use_by_net, 0);
+ atomic_set(&mdev->rs_sect_in, 0);
+ atomic_set(&mdev->rs_sect_ev, 0);
mutex_init(&mdev->md_io_mutex);
mutex_init(&mdev->data.mutex);
@@ -2666,11 +2814,13 @@ void drbd_init_set_defaults(struct drbd_conf *mdev)
INIT_LIST_HEAD(&mdev->meta.work.q);
INIT_LIST_HEAD(&mdev->resync_work.list);
INIT_LIST_HEAD(&mdev->unplug_work.list);
+ INIT_LIST_HEAD(&mdev->go_diskless.list);
INIT_LIST_HEAD(&mdev->md_sync_work.list);
INIT_LIST_HEAD(&mdev->bm_io_work.w.list);
mdev->resync_work.cb = w_resync_inactive;
mdev->unplug_work.cb = w_send_write_hint;
+ mdev->go_diskless.cb = w_go_diskless;
mdev->md_sync_work.cb = w_md_sync;
mdev->bm_io_work.w.cb = w_bitmap_io;
init_timer(&mdev->resync_timer);
@@ -2682,6 +2832,7 @@ void drbd_init_set_defaults(struct drbd_conf *mdev)
init_waitqueue_head(&mdev->misc_wait);
init_waitqueue_head(&mdev->state_wait);
+ init_waitqueue_head(&mdev->net_cnt_wait);
init_waitqueue_head(&mdev->ee_wait);
init_waitqueue_head(&mdev->al_wait);
init_waitqueue_head(&mdev->seq_wait);
@@ -2697,6 +2848,7 @@ void drbd_init_set_defaults(struct drbd_conf *mdev)
void drbd_mdev_cleanup(struct drbd_conf *mdev)
{
+ int i;
if (mdev->receiver.t_state != None)
dev_err(DEV, "ASSERT FAILED: receiver t_state == %d expected 0.\n",
mdev->receiver.t_state);
@@ -2713,9 +2865,13 @@ void drbd_mdev_cleanup(struct drbd_conf *mdev)
mdev->p_size =
mdev->rs_start =
mdev->rs_total =
- mdev->rs_failed =
- mdev->rs_mark_left =
- mdev->rs_mark_time = 0;
+ mdev->rs_failed = 0;
+ mdev->rs_last_events = 0;
+ mdev->rs_last_sect_ev = 0;
+ for (i = 0; i < DRBD_SYNC_MARKS; i++) {
+ mdev->rs_mark_left[i] = 0;
+ mdev->rs_mark_time[i] = 0;
+ }
D_ASSERT(mdev->net_conf == NULL);
drbd_set_my_capacity(mdev, 0);
@@ -2726,6 +2882,7 @@ void drbd_mdev_cleanup(struct drbd_conf *mdev)
}
drbd_free_resources(mdev);
+ clear_bit(AL_SUSPENDED, &mdev->flags);
/*
* currently we drbd_init_ee only on module load, so
@@ -2741,6 +2898,7 @@ void drbd_mdev_cleanup(struct drbd_conf *mdev)
D_ASSERT(list_empty(&mdev->meta.work.q));
D_ASSERT(list_empty(&mdev->resync_work.list));
D_ASSERT(list_empty(&mdev->unplug_work.list));
+ D_ASSERT(list_empty(&mdev->go_diskless.list));
}
@@ -3280,9 +3438,10 @@ void drbd_md_sync(struct drbd_conf *mdev)
sector_t sector;
int i;
+ del_timer(&mdev->md_sync_timer);
+ /* timer may be rearmed by drbd_md_mark_dirty() now. */
if (!test_and_clear_bit(MD_DIRTY, &mdev->flags))
return;
- del_timer(&mdev->md_sync_timer);
/* We use here D_FAILED and not D_ATTACHING because we try to write
* metadata even if we detach due to a disk failure! */
@@ -3310,12 +3469,9 @@ void drbd_md_sync(struct drbd_conf *mdev)
D_ASSERT(drbd_md_ss__(mdev, mdev->ldev) == mdev->ldev->md.md_offset);
sector = mdev->ldev->md.md_offset;
- if (drbd_md_sync_page_io(mdev, mdev->ldev, sector, WRITE)) {
- clear_bit(MD_DIRTY, &mdev->flags);
- } else {
+ if (!drbd_md_sync_page_io(mdev, mdev->ldev, sector, WRITE)) {
/* this was a try anyways ... */
dev_err(DEV, "meta data update failed!\n");
-
drbd_chk_io_error(mdev, 1, TRUE);
}
@@ -3402,6 +3558,28 @@ int drbd_md_read(struct drbd_conf *mdev, struct drbd_backing_dev *bdev)
return rv;
}
+static void debug_drbd_uuid(struct drbd_conf *mdev, enum drbd_uuid_index index)
+{
+ static char *uuid_str[UI_EXTENDED_SIZE] = {
+ [UI_CURRENT] = "CURRENT",
+ [UI_BITMAP] = "BITMAP",
+ [UI_HISTORY_START] = "HISTORY_START",
+ [UI_HISTORY_END] = "HISTORY_END",
+ [UI_SIZE] = "SIZE",
+ [UI_FLAGS] = "FLAGS",
+ };
+
+ if (index >= UI_EXTENDED_SIZE) {
+ dev_warn(DEV, " uuid_index >= EXTENDED_SIZE\n");
+ return;
+ }
+
+ dynamic_dev_dbg(DEV, " uuid[%s] now %016llX\n",
+ uuid_str[index],
+ (unsigned long long)mdev->ldev->md.uuid[index]);
+}
+
+
/**
* drbd_md_mark_dirty() - Mark meta data super block as dirty
* @mdev: DRBD device.
@@ -3410,19 +3588,31 @@ int drbd_md_read(struct drbd_conf *mdev, struct drbd_backing_dev *bdev)
* the meta-data super block. This function sets MD_DIRTY, and starts a
* timer that ensures that within five seconds you have to call drbd_md_sync().
*/
+#ifdef DEBUG
+void drbd_md_mark_dirty_(struct drbd_conf *mdev, unsigned int line, const char *func)
+{
+ if (!test_and_set_bit(MD_DIRTY, &mdev->flags)) {
+ mod_timer(&mdev->md_sync_timer, jiffies + HZ);
+ mdev->last_md_mark_dirty.line = line;
+ mdev->last_md_mark_dirty.func = func;
+ }
+}
+#else
void drbd_md_mark_dirty(struct drbd_conf *mdev)
{
- set_bit(MD_DIRTY, &mdev->flags);
- mod_timer(&mdev->md_sync_timer, jiffies + 5*HZ);
+ if (!test_and_set_bit(MD_DIRTY, &mdev->flags))
+ mod_timer(&mdev->md_sync_timer, jiffies + 5*HZ);
}
-
+#endif
static void drbd_uuid_move_history(struct drbd_conf *mdev) __must_hold(local)
{
int i;
- for (i = UI_HISTORY_START; i < UI_HISTORY_END; i++)
+ for (i = UI_HISTORY_START; i < UI_HISTORY_END; i++) {
mdev->ldev->md.uuid[i+1] = mdev->ldev->md.uuid[i];
+ debug_drbd_uuid(mdev, i+1);
+ }
}
void _drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local)
@@ -3437,6 +3627,7 @@ void _drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local)
}
mdev->ldev->md.uuid[idx] = val;
+ debug_drbd_uuid(mdev, idx);
drbd_md_mark_dirty(mdev);
}
@@ -3446,6 +3637,7 @@ void drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local)
if (mdev->ldev->md.uuid[idx]) {
drbd_uuid_move_history(mdev);
mdev->ldev->md.uuid[UI_HISTORY_START] = mdev->ldev->md.uuid[idx];
+ debug_drbd_uuid(mdev, UI_HISTORY_START);
}
_drbd_uuid_set(mdev, idx, val);
}
@@ -3464,6 +3656,7 @@ void drbd_uuid_new_current(struct drbd_conf *mdev) __must_hold(local)
dev_info(DEV, "Creating new current UUID\n");
D_ASSERT(mdev->ldev->md.uuid[UI_BITMAP] == 0);
mdev->ldev->md.uuid[UI_BITMAP] = mdev->ldev->md.uuid[UI_CURRENT];
+ debug_drbd_uuid(mdev, UI_BITMAP);
get_random_bytes(&val, sizeof(u64));
_drbd_uuid_set(mdev, UI_CURRENT, val);
@@ -3478,6 +3671,8 @@ void drbd_uuid_set_bm(struct drbd_conf *mdev, u64 val) __must_hold(local)
drbd_uuid_move_history(mdev);
mdev->ldev->md.uuid[UI_HISTORY_START] = mdev->ldev->md.uuid[UI_BITMAP];
mdev->ldev->md.uuid[UI_BITMAP] = 0;
+ debug_drbd_uuid(mdev, UI_HISTORY_START);
+ debug_drbd_uuid(mdev, UI_BITMAP);
} else {
if (mdev->ldev->md.uuid[UI_BITMAP])
dev_warn(DEV, "bm UUID already set");
@@ -3485,6 +3680,7 @@ void drbd_uuid_set_bm(struct drbd_conf *mdev, u64 val) __must_hold(local)
mdev->ldev->md.uuid[UI_BITMAP] = val;
mdev->ldev->md.uuid[UI_BITMAP] &= ~((u64)1);
+ debug_drbd_uuid(mdev, UI_BITMAP);
}
drbd_md_mark_dirty(mdev);
}
@@ -3527,6 +3723,7 @@ int drbd_bmio_clear_n_write(struct drbd_conf *mdev)
{
int rv = -EIO;
+ drbd_resume_al(mdev);
if (get_ldev_if_state(mdev, D_ATTACHING)) {
drbd_bm_clear_all(mdev);
rv = drbd_bm_write(mdev);
@@ -3559,6 +3756,32 @@ static int w_bitmap_io(struct drbd_conf *mdev, struct drbd_work *w, int unused)
return 1;
}
+static int w_go_diskless(struct drbd_conf *mdev, struct drbd_work *w, int unused)
+{
+ D_ASSERT(mdev->state.disk == D_FAILED);
+ /* we cannot assert local_cnt == 0 here, as get_ldev_if_state will
+ * inc/dec it frequently. Once we are D_DISKLESS, no one will touch
+ * the protected members anymore, though, so in the after_state_ch work
+ * it will be safe to free them. */
+ drbd_force_state(mdev, NS(disk, D_DISKLESS));
+ /* We need to wait for return of references checked out while we still
+ * have been D_FAILED, though (drbd_md_sync, bitmap io). */
+ wait_event(mdev->misc_wait, !atomic_read(&mdev->local_cnt));
+
+ clear_bit(GO_DISKLESS, &mdev->flags);
+ return 1;
+}
+
+void drbd_go_diskless(struct drbd_conf *mdev)
+{
+ D_ASSERT(mdev->state.disk == D_FAILED);
+ if (!test_and_set_bit(GO_DISKLESS, &mdev->flags))
+ drbd_queue_work(&mdev->data.work, &mdev->go_diskless);
+ /* don't drbd_queue_work_front,
+ * we need to serialize with the after_state_ch work
+ * of the -> D_FAILED transition. */
+}
+
/**
* drbd_queue_bitmap_io() - Queues an IO operation on the whole bitmap
* @mdev: DRBD device.
@@ -3655,8 +3878,11 @@ static void md_sync_timer_fn(unsigned long data)
static int w_md_sync(struct drbd_conf *mdev, struct drbd_work *w, int unused)
{
dev_warn(DEV, "md_sync_timer expired! Worker calls drbd_md_sync().\n");
+#ifdef DEBUG
+ dev_warn(DEV, "last md_mark_dirty: %s:%u\n",
+ mdev->last_md_mark_dirty.func, mdev->last_md_mark_dirty.line);
+#endif
drbd_md_sync(mdev);
-
return 1;
}
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index 73131c5ae339..87925e97e613 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -33,10 +33,13 @@
#include <linux/blkpg.h>
#include <linux/cpumask.h>
#include "drbd_int.h"
+#include "drbd_req.h"
#include "drbd_wrappers.h"
#include <asm/unaligned.h>
#include <linux/drbd_tag_magic.h>
#include <linux/drbd_limits.h>
+#include <linux/compiler.h>
+#include <linux/kthread.h>
static unsigned short *tl_add_blob(unsigned short *, enum drbd_tags, const void *, int);
static unsigned short *tl_add_str(unsigned short *, enum drbd_tags, const char *);
@@ -169,6 +172,10 @@ int drbd_khelper(struct drbd_conf *mdev, char *cmd)
put_net_conf(mdev);
}
+ /* The helper may take some time.
+ * write out any unsynced meta data changes now */
+ drbd_md_sync(mdev);
+
dev_info(DEV, "helper command: %s %s %s\n", usermode_helper, cmd, mb);
drbd_bcast_ev_helper(mdev, cmd);
@@ -202,12 +209,10 @@ enum drbd_disk_state drbd_try_outdate_peer(struct drbd_conf *mdev)
put_ldev(mdev);
} else {
dev_warn(DEV, "Not fencing peer, I'm not even Consistent myself.\n");
- return mdev->state.pdsk;
+ nps = mdev->state.pdsk;
+ goto out;
}
- if (fp == FP_STONITH)
- _drbd_request_state(mdev, NS(susp, 1), CS_WAIT_COMPLETE);
-
r = drbd_khelper(mdev, "fence-peer");
switch ((r>>8) & 0xff) {
@@ -252,9 +257,36 @@ enum drbd_disk_state drbd_try_outdate_peer(struct drbd_conf *mdev)
dev_info(DEV, "fence-peer helper returned %d (%s)\n",
(r>>8) & 0xff, ex_to_string);
+
+out:
+ if (mdev->state.susp_fen && nps >= D_UNKNOWN) {
+ /* The handler was not successful... unfreeze here, the
+ state engine can not unfreeze... */
+ _drbd_request_state(mdev, NS(susp_fen, 0), CS_VERBOSE);
+ }
+
return nps;
}
+static int _try_outdate_peer_async(void *data)
+{
+ struct drbd_conf *mdev = (struct drbd_conf *)data;
+ enum drbd_disk_state nps;
+
+ nps = drbd_try_outdate_peer(mdev);
+ drbd_request_state(mdev, NS(pdsk, nps));
+
+ return 0;
+}
+
+void drbd_try_outdate_peer_async(struct drbd_conf *mdev)
+{
+ struct task_struct *opa;
+
+ opa = kthread_run(_try_outdate_peer_async, mdev, "drbd%d_a_helper", mdev_to_minor(mdev));
+ if (IS_ERR(opa))
+ dev_err(DEV, "out of mem, failed to invoke fence-peer helper\n");
+}
int drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force)
{
@@ -394,6 +426,39 @@ int drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force)
return r;
}
+static struct drbd_conf *ensure_mdev(int minor, int create)
+{
+ struct drbd_conf *mdev;
+
+ if (minor >= minor_count)
+ return NULL;
+
+ mdev = minor_to_mdev(minor);
+
+ if (!mdev && create) {
+ struct gendisk *disk = NULL;
+ mdev = drbd_new_device(minor);
+
+ spin_lock_irq(&drbd_pp_lock);
+ if (minor_table[minor] == NULL) {
+ minor_table[minor] = mdev;
+ disk = mdev->vdisk;
+ mdev = NULL;
+ } /* else: we lost the race */
+ spin_unlock_irq(&drbd_pp_lock);
+
+ if (disk) /* we won the race above */
+ /* in case we ever add a drbd_delete_device(),
+ * don't forget the del_gendisk! */
+ add_disk(disk);
+ else /* we lost the race above */
+ drbd_free_mdev(mdev);
+
+ mdev = minor_to_mdev(minor);
+ }
+
+ return mdev;
+}
static int drbd_nl_primary(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
struct drbd_nl_cfg_reply *reply)
@@ -494,6 +559,8 @@ char *ppsize(char *buf, unsigned long long size)
void drbd_suspend_io(struct drbd_conf *mdev)
{
set_bit(SUSPEND_IO, &mdev->flags);
+ if (is_susp(mdev->state))
+ return;
wait_event(mdev->misc_wait, !atomic_read(&mdev->ap_bio_cnt));
}
@@ -713,9 +780,6 @@ void drbd_setup_queue_param(struct drbd_conf *mdev, unsigned int max_seg_s) __mu
blk_queue_segment_boundary(q, PAGE_SIZE-1);
blk_stack_limits(&q->limits, &b->limits, 0);
- if (b->merge_bvec_fn)
- dev_warn(DEV, "Backing device's merge_bvec_fn() = %p\n",
- b->merge_bvec_fn);
dev_info(DEV, "max_segment_size ( = BIO size ) = %u\n", queue_max_segment_size(q));
if (q->backing_dev_info.ra_pages != b->backing_dev_info.ra_pages) {
@@ -729,14 +793,16 @@ void drbd_setup_queue_param(struct drbd_conf *mdev, unsigned int max_seg_s) __mu
/* serialize deconfig (worker exiting, doing cleanup)
* and reconfig (drbdsetup disk, drbdsetup net)
*
- * wait for a potentially exiting worker, then restart it,
- * or start a new one.
+ * Wait for a potentially exiting worker, then restart it,
+ * or start a new one. Flush any pending work, there may still be an
+ * after_state_change queued.
*/
static void drbd_reconfig_start(struct drbd_conf *mdev)
{
wait_event(mdev->state_wait, !test_and_set_bit(CONFIG_PENDING, &mdev->flags));
wait_event(mdev->state_wait, !test_bit(DEVICE_DYING, &mdev->flags));
drbd_thread_start(&mdev->worker);
+ drbd_flush_workqueue(mdev);
}
/* if still unconfigured, stops worker again.
@@ -756,6 +822,29 @@ static void drbd_reconfig_done(struct drbd_conf *mdev)
wake_up(&mdev->state_wait);
}
+/* Make sure IO is suspended before calling this function(). */
+static void drbd_suspend_al(struct drbd_conf *mdev)
+{
+ int s = 0;
+
+ if (lc_try_lock(mdev->act_log)) {
+ drbd_al_shrink(mdev);
+ lc_unlock(mdev->act_log);
+ } else {
+ dev_warn(DEV, "Failed to lock al in drbd_suspend_al()\n");
+ return;
+ }
+
+ spin_lock_irq(&mdev->req_lock);
+ if (mdev->state.conn < C_CONNECTED)
+ s = !test_and_set_bit(AL_SUSPENDED, &mdev->flags);
+
+ spin_unlock_irq(&mdev->req_lock);
+
+ if (s)
+ dev_info(DEV, "Suspended AL updates\n");
+}
+
/* does always return 0;
* interesting return code is in reply->ret_code */
static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
@@ -769,6 +858,7 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
struct inode *inode, *inode2;
struct lru_cache *resync_lru = NULL;
union drbd_state ns, os;
+ unsigned int max_seg_s;
int rv;
int cp_discovered = 0;
int logical_block_size;
@@ -803,6 +893,15 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
goto fail;
}
+ if (get_net_conf(mdev)) {
+ int prot = mdev->net_conf->wire_protocol;
+ put_net_conf(mdev);
+ if (nbc->dc.fencing == FP_STONITH && prot == DRBD_PROT_A) {
+ retcode = ERR_STONITH_AND_PROT_A;
+ goto fail;
+ }
+ }
+
nbc->lo_file = filp_open(nbc->dc.backing_dev, O_RDWR, 0);
if (IS_ERR(nbc->lo_file)) {
dev_err(DEV, "open(\"%s\") failed with %ld\n", nbc->dc.backing_dev,
@@ -924,7 +1023,7 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
drbd_suspend_io(mdev);
/* also wait for the last barrier ack. */
- wait_event(mdev->misc_wait, !atomic_read(&mdev->ap_pending_cnt));
+ wait_event(mdev->misc_wait, !atomic_read(&mdev->ap_pending_cnt) || is_susp(mdev->state));
/* and for any other previously queued work */
drbd_flush_workqueue(mdev);
@@ -1021,7 +1120,8 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
else
clear_bit(CRASHED_PRIMARY, &mdev->flags);
- if (drbd_md_test_flag(mdev->ldev, MDF_PRIMARY_IND)) {
+ if (drbd_md_test_flag(mdev->ldev, MDF_PRIMARY_IND) &&
+ !(mdev->state.role == R_PRIMARY && mdev->state.susp_nod)) {
set_bit(CRASHED_PRIMARY, &mdev->flags);
cp_discovered = 1;
}
@@ -1031,7 +1131,20 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
mdev->read_cnt = 0;
mdev->writ_cnt = 0;
- drbd_setup_queue_param(mdev, DRBD_MAX_SEGMENT_SIZE);
+ max_seg_s = DRBD_MAX_SEGMENT_SIZE;
+ if (mdev->state.conn == C_CONNECTED) {
+ /* We are Primary, Connected, and now attach a new local
+ * backing store. We must not increase the user visible maximum
+ * bio size on this device to something the peer may not be
+ * able to handle. */
+ if (mdev->agreed_pro_version < 94)
+ max_seg_s = queue_max_segment_size(mdev->rq_queue);
+ else if (mdev->agreed_pro_version == 94)
+ max_seg_s = DRBD_MAX_SIZE_H80_PACKET;
+ /* else: drbd 8.3.9 and later, stay with default */
+ }
+
+ drbd_setup_queue_param(mdev, max_seg_s);
/* If I am currently not R_PRIMARY,
* but meta data primary indicator is set,
@@ -1079,6 +1192,9 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
drbd_al_to_on_disk_bm(mdev);
}
+ if (_drbd_bm_total_weight(mdev) == drbd_bm_bits(mdev))
+ drbd_suspend_al(mdev); /* IO is still suspended here... */
+
spin_lock_irq(&mdev->req_lock);
os = mdev->state;
ns.i = os.i;
@@ -1235,7 +1351,16 @@ static int drbd_nl_net_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
&& (new_conf->wire_protocol != DRBD_PROT_C)) {
retcode = ERR_NOT_PROTO_C;
goto fail;
- };
+ }
+
+ if (get_ldev(mdev)) {
+ enum drbd_fencing_p fp = mdev->ldev->dc.fencing;
+ put_ldev(mdev);
+ if (new_conf->wire_protocol == DRBD_PROT_A && fp == FP_STONITH) {
+ retcode = ERR_STONITH_AND_PROT_A;
+ goto fail;
+ }
+ }
if (mdev->state.role == R_PRIMARY && new_conf->want_lose) {
retcode = ERR_DISCARD;
@@ -1350,6 +1475,7 @@ static int drbd_nl_net_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
}
}
+ drbd_flush_workqueue(mdev);
spin_lock_irq(&mdev->req_lock);
if (mdev->net_conf != NULL) {
retcode = ERR_NET_CONFIGURED;
@@ -1388,10 +1514,9 @@ static int drbd_nl_net_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
mdev->int_dig_out=int_dig_out;
mdev->int_dig_in=int_dig_in;
mdev->int_dig_vv=int_dig_vv;
+ retcode = _drbd_set_state(_NS(mdev, conn, C_UNCONNECTED), CS_VERBOSE, NULL);
spin_unlock_irq(&mdev->req_lock);
- retcode = _drbd_request_state(mdev, NS(conn, C_UNCONNECTED), CS_VERBOSE);
-
kobject_uevent(&disk_to_dev(mdev->vdisk)->kobj, KOBJ_CHANGE);
reply->ret_code = retcode;
drbd_reconfig_done(mdev);
@@ -1546,6 +1671,8 @@ static int drbd_nl_syncer_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *n
struct crypto_hash *csums_tfm = NULL;
struct syncer_conf sc;
cpumask_var_t new_cpu_mask;
+ int *rs_plan_s = NULL;
+ int fifo_size;
if (!zalloc_cpumask_var(&new_cpu_mask, GFP_KERNEL)) {
retcode = ERR_NOMEM;
@@ -1557,6 +1684,12 @@ static int drbd_nl_syncer_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *n
sc.rate = DRBD_RATE_DEF;
sc.after = DRBD_AFTER_DEF;
sc.al_extents = DRBD_AL_EXTENTS_DEF;
+ sc.on_no_data = DRBD_ON_NO_DATA_DEF;
+ sc.c_plan_ahead = DRBD_C_PLAN_AHEAD_DEF;
+ sc.c_delay_target = DRBD_C_DELAY_TARGET_DEF;
+ sc.c_fill_target = DRBD_C_FILL_TARGET_DEF;
+ sc.c_max_rate = DRBD_C_MAX_RATE_DEF;
+ sc.c_min_rate = DRBD_C_MIN_RATE_DEF;
} else
memcpy(&sc, &mdev->sync_conf, sizeof(struct syncer_conf));
@@ -1634,6 +1767,12 @@ static int drbd_nl_syncer_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *n
}
#undef AL_MAX
+ /* to avoid spurious errors when configuring minors before configuring
+ * the minors they depend on: if necessary, first create the minor we
+ * depend on */
+ if (sc.after >= 0)
+ ensure_mdev(sc.after, 1);
+
/* most sanity checks done, try to assign the new sync-after
* dependency. need to hold the global lock in there,
* to avoid a race in the dependency loop check. */
@@ -1641,6 +1780,16 @@ static int drbd_nl_syncer_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *n
if (retcode != NO_ERROR)
goto fail;
+ fifo_size = (sc.c_plan_ahead * 10 * SLEEP_TIME) / HZ;
+ if (fifo_size != mdev->rs_plan_s.size && fifo_size > 0) {
+ rs_plan_s = kzalloc(sizeof(int) * fifo_size, GFP_KERNEL);
+ if (!rs_plan_s) {
+ dev_err(DEV, "kmalloc of fifo_buffer failed");
+ retcode = ERR_NOMEM;
+ goto fail;
+ }
+ }
+
/* ok, assign the rest of it as well.
* lock against receive_SyncParam() */
spin_lock(&mdev->peer_seq_lock);
@@ -1657,6 +1806,15 @@ static int drbd_nl_syncer_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *n
mdev->verify_tfm = verify_tfm;
verify_tfm = NULL;
}
+
+ if (fifo_size != mdev->rs_plan_s.size) {
+ kfree(mdev->rs_plan_s.values);
+ mdev->rs_plan_s.values = rs_plan_s;
+ mdev->rs_plan_s.size = fifo_size;
+ mdev->rs_planed = 0;
+ rs_plan_s = NULL;
+ }
+
spin_unlock(&mdev->peer_seq_lock);
if (get_ldev(mdev)) {
@@ -1688,6 +1846,7 @@ static int drbd_nl_syncer_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *n
kobject_uevent(&disk_to_dev(mdev->vdisk)->kobj, KOBJ_CHANGE);
fail:
+ kfree(rs_plan_s);
free_cpumask_var(new_cpu_mask);
crypto_free_hash(csums_tfm);
crypto_free_hash(verify_tfm);
@@ -1721,12 +1880,38 @@ static int drbd_nl_invalidate(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nl
return 0;
}
+static int drbd_bmio_set_susp_al(struct drbd_conf *mdev)
+{
+ int rv;
+
+ rv = drbd_bmio_set_n_write(mdev);
+ drbd_suspend_al(mdev);
+ return rv;
+}
+
static int drbd_nl_invalidate_peer(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
struct drbd_nl_cfg_reply *reply)
{
+ int retcode;
- reply->ret_code = drbd_request_state(mdev, NS(conn, C_STARTING_SYNC_S));
+ retcode = _drbd_request_state(mdev, NS(conn, C_STARTING_SYNC_S), CS_ORDERED);
+
+ if (retcode < SS_SUCCESS) {
+ if (retcode == SS_NEED_CONNECTION && mdev->state.role == R_PRIMARY) {
+ /* The peer will get a resync upon connect anyways. Just make that
+ into a full resync. */
+ retcode = drbd_request_state(mdev, NS(pdsk, D_INCONSISTENT));
+ if (retcode >= SS_SUCCESS) {
+ /* open coded drbd_bitmap_io() */
+ if (drbd_bitmap_io(mdev, &drbd_bmio_set_susp_al,
+ "set_n_write from invalidate_peer"))
+ retcode = ERR_IO_MD_DISK;
+ }
+ } else
+ retcode = drbd_request_state(mdev, NS(conn, C_STARTING_SYNC_S));
+ }
+ reply->ret_code = retcode;
return 0;
}
@@ -1765,7 +1950,21 @@ static int drbd_nl_suspend_io(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nl
static int drbd_nl_resume_io(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
struct drbd_nl_cfg_reply *reply)
{
- reply->ret_code = drbd_request_state(mdev, NS(susp, 0));
+ if (test_bit(NEW_CUR_UUID, &mdev->flags)) {
+ drbd_uuid_new_current(mdev);
+ clear_bit(NEW_CUR_UUID, &mdev->flags);
+ drbd_md_sync(mdev);
+ }
+ drbd_suspend_io(mdev);
+ reply->ret_code = drbd_request_state(mdev, NS3(susp, 0, susp_nod, 0, susp_fen, 0));
+ if (reply->ret_code == SS_SUCCESS) {
+ if (mdev->state.conn < C_CONNECTED)
+ tl_clear(mdev);
+ if (mdev->state.disk == D_DISKLESS || mdev->state.disk == D_FAILED)
+ tl_restart(mdev, fail_frozen_disk_io);
+ }
+ drbd_resume_io(mdev);
+
return 0;
}
@@ -1941,40 +2140,6 @@ out:
return 0;
}
-static struct drbd_conf *ensure_mdev(struct drbd_nl_cfg_req *nlp)
-{
- struct drbd_conf *mdev;
-
- if (nlp->drbd_minor >= minor_count)
- return NULL;
-
- mdev = minor_to_mdev(nlp->drbd_minor);
-
- if (!mdev && (nlp->flags & DRBD_NL_CREATE_DEVICE)) {
- struct gendisk *disk = NULL;
- mdev = drbd_new_device(nlp->drbd_minor);
-
- spin_lock_irq(&drbd_pp_lock);
- if (minor_table[nlp->drbd_minor] == NULL) {
- minor_table[nlp->drbd_minor] = mdev;
- disk = mdev->vdisk;
- mdev = NULL;
- } /* else: we lost the race */
- spin_unlock_irq(&drbd_pp_lock);
-
- if (disk) /* we won the race above */
- /* in case we ever add a drbd_delete_device(),
- * don't forget the del_gendisk! */
- add_disk(disk);
- else /* we lost the race above */
- drbd_free_mdev(mdev);
-
- mdev = minor_to_mdev(nlp->drbd_minor);
- }
-
- return mdev;
-}
-
struct cn_handler_struct {
int (*function)(struct drbd_conf *,
struct drbd_nl_cfg_req *,
@@ -2035,7 +2200,8 @@ static void drbd_connector_callback(struct cn_msg *req, struct netlink_skb_parms
goto fail;
}
- mdev = ensure_mdev(nlp);
+ mdev = ensure_mdev(nlp->drbd_minor,
+ (nlp->flags & DRBD_NL_CREATE_DEVICE));
if (!mdev) {
retcode = ERR_MINOR_INVALID;
goto fail;
diff --git a/drivers/block/drbd/drbd_proc.c b/drivers/block/drbd/drbd_proc.c
index be3374b68460..ad325c5d0ce1 100644
--- a/drivers/block/drbd/drbd_proc.c
+++ b/drivers/block/drbd/drbd_proc.c
@@ -57,6 +57,7 @@ static void drbd_syncer_progress(struct drbd_conf *mdev, struct seq_file *seq)
unsigned long db, dt, dbdt, rt, rs_left;
unsigned int res;
int i, x, y;
+ int stalled = 0;
drbd_get_syncer_progress(mdev, &rs_left, &res);
@@ -90,18 +91,17 @@ static void drbd_syncer_progress(struct drbd_conf *mdev, struct seq_file *seq)
* db: blocks written from mark until now
* rt: remaining time
*/
- dt = (jiffies - mdev->rs_mark_time) / HZ;
-
- if (dt > 20) {
- /* if we made no update to rs_mark_time for too long,
- * we are stalled. show that. */
- seq_printf(seq, "stalled\n");
- return;
- }
+ /* Rolling marks. last_mark+1 may just now be modified. last_mark+2 is
+ * at least (DRBD_SYNC_MARKS-2)*DRBD_SYNC_MARK_STEP old, and has at
+ * least DRBD_SYNC_MARK_STEP time before it will be modified. */
+ i = (mdev->rs_last_mark + 2) % DRBD_SYNC_MARKS;
+ dt = (jiffies - mdev->rs_mark_time[i]) / HZ;
+ if (dt > (DRBD_SYNC_MARK_STEP * DRBD_SYNC_MARKS))
+ stalled = 1;
if (!dt)
dt++;
- db = mdev->rs_mark_left - rs_left;
+ db = mdev->rs_mark_left[i] - rs_left;
rt = (dt * (rs_left / (db/100+1)))/100; /* seconds */
seq_printf(seq, "finish: %lu:%02lu:%02lu",
@@ -118,7 +118,7 @@ static void drbd_syncer_progress(struct drbd_conf *mdev, struct seq_file *seq)
/* mean speed since syncer started
* we do account for PausedSync periods */
dt = (jiffies - mdev->rs_start - mdev->rs_paused) / HZ;
- if (dt <= 0)
+ if (dt == 0)
dt = 1;
db = mdev->rs_total - rs_left;
dbdt = Bit2KB(db/dt);
@@ -128,7 +128,14 @@ static void drbd_syncer_progress(struct drbd_conf *mdev, struct seq_file *seq)
else
seq_printf(seq, " (%ld)", dbdt);
- seq_printf(seq, " K/sec\n");
+ if (mdev->state.conn == C_SYNC_TARGET) {
+ if (mdev->c_sync_rate > 1000)
+ seq_printf(seq, " want: %d,%03d",
+ mdev->c_sync_rate / 1000, mdev->c_sync_rate % 1000);
+ else
+ seq_printf(seq, " want: %d", mdev->c_sync_rate);
+ }
+ seq_printf(seq, " K/sec%s\n", stalled ? " (stalled)" : "");
}
static void resync_dump_detail(struct seq_file *seq, struct lc_element *e)
@@ -196,7 +203,7 @@ static int drbd_seq_show(struct seq_file *seq, void *v)
seq_printf(seq, "%2d: cs:Unconfigured\n", i);
} else {
seq_printf(seq,
- "%2d: cs:%s ro:%s/%s ds:%s/%s %c %c%c%c%c%c\n"
+ "%2d: cs:%s ro:%s/%s ds:%s/%s %c %c%c%c%c%c%c\n"
" ns:%u nr:%u dw:%u dr:%u al:%u bm:%u "
"lo:%d pe:%d ua:%d ap:%d ep:%d wo:%c",
i, sn,
@@ -206,11 +213,12 @@ static int drbd_seq_show(struct seq_file *seq, void *v)
drbd_disk_str(mdev->state.pdsk),
(mdev->net_conf == NULL ? ' ' :
(mdev->net_conf->wire_protocol - DRBD_PROT_A+'A')),
- mdev->state.susp ? 's' : 'r',
+ is_susp(mdev->state) ? 's' : 'r',
mdev->state.aftr_isp ? 'a' : '-',
mdev->state.peer_isp ? 'p' : '-',
mdev->state.user_isp ? 'u' : '-',
mdev->congestion_reason ?: '-',
+ test_bit(AL_SUSPENDED, &mdev->flags) ? 's' : '-',
mdev->send_cnt/2,
mdev->recv_cnt/2,
mdev->writ_cnt/2,
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index 081522d3c742..efd6169acf2f 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -241,7 +241,7 @@ static void drbd_kick_lo_and_reclaim_net(struct drbd_conf *mdev)
spin_unlock_irq(&mdev->req_lock);
list_for_each_entry_safe(e, t, &reclaimed, w.list)
- drbd_free_ee(mdev, e);
+ drbd_free_net_ee(mdev, e);
}
/**
@@ -298,9 +298,11 @@ static struct page *drbd_pp_alloc(struct drbd_conf *mdev, unsigned number, bool
* Is also used from inside an other spin_lock_irq(&mdev->req_lock);
* Either links the page chain back to the global pool,
* or returns all pages to the system. */
-static void drbd_pp_free(struct drbd_conf *mdev, struct page *page)
+static void drbd_pp_free(struct drbd_conf *mdev, struct page *page, int is_net)
{
+ atomic_t *a = is_net ? &mdev->pp_in_use_by_net : &mdev->pp_in_use;
int i;
+
if (drbd_pp_vacant > (DRBD_MAX_SEGMENT_SIZE/PAGE_SIZE)*minor_count)
i = page_chain_free(page);
else {
@@ -311,10 +313,10 @@ static void drbd_pp_free(struct drbd_conf *mdev, struct page *page)
drbd_pp_vacant += i;
spin_unlock(&drbd_pp_lock);
}
- atomic_sub(i, &mdev->pp_in_use);
- i = atomic_read(&mdev->pp_in_use);
+ i = atomic_sub_return(i, a);
if (i < 0)
- dev_warn(DEV, "ASSERTION FAILED: pp_in_use: %d < 0\n", i);
+ dev_warn(DEV, "ASSERTION FAILED: %s: %d < 0\n",
+ is_net ? "pp_in_use_by_net" : "pp_in_use", i);
wake_up(&drbd_pp_wait);
}
@@ -365,7 +367,6 @@ struct drbd_epoch_entry *drbd_alloc_ee(struct drbd_conf *mdev,
e->size = data_size;
e->flags = 0;
e->sector = sector;
- e->sector = sector;
e->block_id = id;
return e;
@@ -375,9 +376,11 @@ struct drbd_epoch_entry *drbd_alloc_ee(struct drbd_conf *mdev,
return NULL;
}
-void drbd_free_ee(struct drbd_conf *mdev, struct drbd_epoch_entry *e)
+void drbd_free_some_ee(struct drbd_conf *mdev, struct drbd_epoch_entry *e, int is_net)
{
- drbd_pp_free(mdev, e->pages);
+ if (e->flags & EE_HAS_DIGEST)
+ kfree(e->digest);
+ drbd_pp_free(mdev, e->pages, is_net);
D_ASSERT(atomic_read(&e->pending_bios) == 0);
D_ASSERT(hlist_unhashed(&e->colision));
mempool_free(e, drbd_ee_mempool);
@@ -388,13 +391,14 @@ int drbd_release_ee(struct drbd_conf *mdev, struct list_head *list)
LIST_HEAD(work_list);
struct drbd_epoch_entry *e, *t;
int count = 0;
+ int is_net = list == &mdev->net_ee;
spin_lock_irq(&mdev->req_lock);
list_splice_init(list, &work_list);
spin_unlock_irq(&mdev->req_lock);
list_for_each_entry_safe(e, t, &work_list, w.list) {
- drbd_free_ee(mdev, e);
+ drbd_free_some_ee(mdev, e, is_net);
count++;
}
return count;
@@ -423,7 +427,7 @@ static int drbd_process_done_ee(struct drbd_conf *mdev)
spin_unlock_irq(&mdev->req_lock);
list_for_each_entry_safe(e, t, &reclaimed, w.list)
- drbd_free_ee(mdev, e);
+ drbd_free_net_ee(mdev, e);
/* possible callbacks here:
* e_end_block, and e_end_resync_block, e_send_discard_ack.
@@ -719,14 +723,14 @@ out:
static int drbd_send_fp(struct drbd_conf *mdev,
struct socket *sock, enum drbd_packets cmd)
{
- struct p_header *h = (struct p_header *) &mdev->data.sbuf.header;
+ struct p_header80 *h = &mdev->data.sbuf.header.h80;
return _drbd_send_cmd(mdev, sock, cmd, h, sizeof(*h), 0);
}
static enum drbd_packets drbd_recv_fp(struct drbd_conf *mdev, struct socket *sock)
{
- struct p_header *h = (struct p_header *) &mdev->data.sbuf.header;
+ struct p_header80 *h = &mdev->data.rbuf.header.h80;
int rr;
rr = drbd_recv_short(mdev, sock, h, sizeof(*h), 0);
@@ -776,9 +780,6 @@ static int drbd_connect(struct drbd_conf *mdev)
D_ASSERT(!mdev->data.socket);
- if (test_and_clear_bit(CREATE_BARRIER, &mdev->flags))
- dev_err(DEV, "CREATE_BARRIER flag was set in drbd_connect - now cleared!\n");
-
if (drbd_request_state(mdev, NS(conn, C_WF_CONNECTION)) < SS_SUCCESS)
return -2;
@@ -927,6 +928,11 @@ retry:
drbd_thread_start(&mdev->asender);
+ if (mdev->agreed_pro_version < 95 && get_ldev(mdev)) {
+ drbd_setup_queue_param(mdev, DRBD_MAX_SIZE_H80_PACKET);
+ put_ldev(mdev);
+ }
+
if (!drbd_send_protocol(mdev))
return -1;
drbd_send_sync_param(mdev, &mdev->sync_conf);
@@ -946,22 +952,28 @@ out_release_sockets:
return -1;
}
-static int drbd_recv_header(struct drbd_conf *mdev, struct p_header *h)
+static int drbd_recv_header(struct drbd_conf *mdev, enum drbd_packets *cmd, unsigned int *packet_size)
{
+ union p_header *h = &mdev->data.rbuf.header;
int r;
r = drbd_recv(mdev, h, sizeof(*h));
-
if (unlikely(r != sizeof(*h))) {
dev_err(DEV, "short read expecting header on sock: r=%d\n", r);
return FALSE;
- };
- h->command = be16_to_cpu(h->command);
- h->length = be16_to_cpu(h->length);
- if (unlikely(h->magic != BE_DRBD_MAGIC)) {
- dev_err(DEV, "magic?? on data m: 0x%lx c: %d l: %d\n",
- (long)be32_to_cpu(h->magic),
- h->command, h->length);
+ }
+
+ if (likely(h->h80.magic == BE_DRBD_MAGIC)) {
+ *cmd = be16_to_cpu(h->h80.command);
+ *packet_size = be16_to_cpu(h->h80.length);
+ } else if (h->h95.magic == BE_DRBD_MAGIC_BIG) {
+ *cmd = be16_to_cpu(h->h95.command);
+ *packet_size = be32_to_cpu(h->h95.length);
+ } else {
+ dev_err(DEV, "magic?? on data m: 0x%08x c: %d l: %d\n",
+ be32_to_cpu(h->h80.magic),
+ be16_to_cpu(h->h80.command),
+ be16_to_cpu(h->h80.length));
return FALSE;
}
mdev->last_received = jiffies;
@@ -975,7 +987,7 @@ static enum finish_epoch drbd_flush_after_epoch(struct drbd_conf *mdev, struct d
if (mdev->write_ordering >= WO_bdev_flush && get_ldev(mdev)) {
rv = blkdev_issue_flush(mdev->ldev->backing_bdev, GFP_KERNEL,
- NULL, BLKDEV_IFL_WAIT);
+ NULL);
if (rv) {
dev_err(DEV, "local disk flush failed with status %d\n", rv);
/* would rather check on EOPNOTSUPP, but that is not reliable.
@@ -1268,17 +1280,12 @@ int w_e_reissue(struct drbd_conf *mdev, struct drbd_work *w, int cancel) __relea
return 1;
}
-static int receive_Barrier(struct drbd_conf *mdev, struct p_header *h)
+static int receive_Barrier(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
{
int rv, issue_flush;
- struct p_barrier *p = (struct p_barrier *)h;
+ struct p_barrier *p = &mdev->data.rbuf.barrier;
struct drbd_epoch *epoch;
- ERR_IF(h->length != (sizeof(*p)-sizeof(*h))) return FALSE;
-
- rv = drbd_recv(mdev, h->payload, h->length);
- ERR_IF(rv != h->length) return FALSE;
-
inc_unacked(mdev);
if (mdev->net_conf->wire_protocol != DRBD_PROT_C)
@@ -1457,7 +1464,7 @@ static int drbd_drain_block(struct drbd_conf *mdev, int data_size)
data_size -= rr;
}
kunmap(page);
- drbd_pp_free(mdev, page);
+ drbd_pp_free(mdev, page, 0);
return rv;
}
@@ -1562,30 +1569,29 @@ static int recv_resync_read(struct drbd_conf *mdev, sector_t sector, int data_si
list_add(&e->w.list, &mdev->sync_ee);
spin_unlock_irq(&mdev->req_lock);
+ atomic_add(data_size >> 9, &mdev->rs_sect_ev);
if (drbd_submit_ee(mdev, e, WRITE, DRBD_FAULT_RS_WR) == 0)
return TRUE;
+ /* drbd_submit_ee currently fails for one reason only:
+ * not being able to allocate enough bios.
+ * Is dropping the connection going to help? */
+ spin_lock_irq(&mdev->req_lock);
+ list_del(&e->w.list);
+ spin_unlock_irq(&mdev->req_lock);
+
drbd_free_ee(mdev, e);
fail:
put_ldev(mdev);
return FALSE;
}
-static int receive_DataReply(struct drbd_conf *mdev, struct p_header *h)
+static int receive_DataReply(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
{
struct drbd_request *req;
sector_t sector;
- unsigned int header_size, data_size;
int ok;
- struct p_data *p = (struct p_data *)h;
-
- header_size = sizeof(*p) - sizeof(*h);
- data_size = h->length - header_size;
-
- ERR_IF(data_size == 0) return FALSE;
-
- if (drbd_recv(mdev, h->payload, header_size) != header_size)
- return FALSE;
+ struct p_data *p = &mdev->data.rbuf.data;
sector = be64_to_cpu(p->sector);
@@ -1611,20 +1617,11 @@ static int receive_DataReply(struct drbd_conf *mdev, struct p_header *h)
return ok;
}
-static int receive_RSDataReply(struct drbd_conf *mdev, struct p_header *h)
+static int receive_RSDataReply(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
{
sector_t sector;
- unsigned int header_size, data_size;
int ok;
- struct p_data *p = (struct p_data *)h;
-
- header_size = sizeof(*p) - sizeof(*h);
- data_size = h->length - header_size;
-
- ERR_IF(data_size == 0) return FALSE;
-
- if (drbd_recv(mdev, h->payload, header_size) != header_size)
- return FALSE;
+ struct p_data *p = &mdev->data.rbuf.data;
sector = be64_to_cpu(p->sector);
D_ASSERT(p->block_id == ID_SYNCER);
@@ -1640,9 +1637,11 @@ static int receive_RSDataReply(struct drbd_conf *mdev, struct p_header *h)
ok = drbd_drain_block(mdev, data_size);
- drbd_send_ack_dp(mdev, P_NEG_ACK, p);
+ drbd_send_ack_dp(mdev, P_NEG_ACK, p, data_size);
}
+ atomic_add(data_size >> 9, &mdev->rs_sect_in);
+
return ok;
}
@@ -1765,24 +1764,27 @@ static int drbd_wait_peer_seq(struct drbd_conf *mdev, const u32 packet_seq)
return ret;
}
+static unsigned long write_flags_to_bio(struct drbd_conf *mdev, u32 dpf)
+{
+ if (mdev->agreed_pro_version >= 95)
+ return (dpf & DP_RW_SYNC ? REQ_SYNC : 0) |
+ (dpf & DP_UNPLUG ? REQ_UNPLUG : 0) |
+ (dpf & DP_FUA ? REQ_FUA : 0) |
+ (dpf & DP_FLUSH ? REQ_FUA : 0) |
+ (dpf & DP_DISCARD ? REQ_DISCARD : 0);
+ else
+ return dpf & DP_RW_SYNC ? (REQ_SYNC | REQ_UNPLUG) : 0;
+}
+
/* mirrored write */
-static int receive_Data(struct drbd_conf *mdev, struct p_header *h)
+static int receive_Data(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
{
sector_t sector;
struct drbd_epoch_entry *e;
- struct p_data *p = (struct p_data *)h;
- int header_size, data_size;
+ struct p_data *p = &mdev->data.rbuf.data;
int rw = WRITE;
u32 dp_flags;
- header_size = sizeof(*p) - sizeof(*h);
- data_size = h->length - header_size;
-
- ERR_IF(data_size == 0) return FALSE;
-
- if (drbd_recv(mdev, h->payload, header_size) != header_size)
- return FALSE;
-
if (!get_ldev(mdev)) {
if (__ratelimit(&drbd_ratelimit_state))
dev_err(DEV, "Can not write mirrored data block "
@@ -1792,7 +1794,7 @@ static int receive_Data(struct drbd_conf *mdev, struct p_header *h)
mdev->peer_seq++;
spin_unlock(&mdev->peer_seq_lock);
- drbd_send_ack_dp(mdev, P_NEG_ACK, p);
+ drbd_send_ack_dp(mdev, P_NEG_ACK, p, data_size);
atomic_inc(&mdev->current_epoch->epoch_size);
return drbd_drain_block(mdev, data_size);
}
@@ -1839,12 +1841,8 @@ static int receive_Data(struct drbd_conf *mdev, struct p_header *h)
spin_unlock(&mdev->epoch_lock);
dp_flags = be32_to_cpu(p->dp_flags);
- if (dp_flags & DP_HARDBARRIER) {
- dev_err(DEV, "ASSERT FAILED would have submitted barrier request\n");
- /* rw |= REQ_HARDBARRIER; */
- }
- if (dp_flags & DP_RW_SYNC)
- rw |= REQ_SYNC | REQ_UNPLUG;
+ rw |= write_flags_to_bio(mdev, dp_flags);
+
if (dp_flags & DP_MAY_SET_IN_SYNC)
e->flags |= EE_MAY_SET_IN_SYNC;
@@ -2007,6 +2005,16 @@ static int receive_Data(struct drbd_conf *mdev, struct p_header *h)
if (drbd_submit_ee(mdev, e, rw, DRBD_FAULT_DT_WR) == 0)
return TRUE;
+ /* drbd_submit_ee currently fails for one reason only:
+ * not being able to allocate enough bios.
+ * Is dropping the connection going to help? */
+ spin_lock_irq(&mdev->req_lock);
+ list_del(&e->w.list);
+ hlist_del_init(&e->colision);
+ spin_unlock_irq(&mdev->req_lock);
+ if (e->flags & EE_CALL_AL_COMPLETE_IO)
+ drbd_al_complete_io(mdev, e->sector);
+
out_interrupted:
/* yes, the epoch_size now is imbalanced.
* but we drop the connection anyways, so we don't have a chance to
@@ -2016,20 +2024,64 @@ out_interrupted:
return FALSE;
}
-static int receive_DataRequest(struct drbd_conf *mdev, struct p_header *h)
+/* We may throttle resync, if the lower device seems to be busy,
+ * and current sync rate is above c_min_rate.
+ *
+ * To decide whether or not the lower device is busy, we use a scheme similar
+ * to MD RAID is_mddev_idle(): if the partition stats reveal "significant"
+ * (more than 64 sectors) of activity we cannot account for with our own resync
+ * activity, it obviously is "busy".
+ *
+ * The current sync rate used here uses only the most recent two step marks,
+ * to have a short time average so we can react faster.
+ */
+int drbd_rs_should_slow_down(struct drbd_conf *mdev)
+{
+ struct gendisk *disk = mdev->ldev->backing_bdev->bd_contains->bd_disk;
+ unsigned long db, dt, dbdt;
+ int curr_events;
+ int throttle = 0;
+
+ /* feature disabled? */
+ if (mdev->sync_conf.c_min_rate == 0)
+ return 0;
+
+ curr_events = (int)part_stat_read(&disk->part0, sectors[0]) +
+ (int)part_stat_read(&disk->part0, sectors[1]) -
+ atomic_read(&mdev->rs_sect_ev);
+ if (!mdev->rs_last_events || curr_events - mdev->rs_last_events > 64) {
+ unsigned long rs_left;
+ int i;
+
+ mdev->rs_last_events = curr_events;
+
+ /* sync speed average over the last 2*DRBD_SYNC_MARK_STEP,
+ * approx. */
+ i = (mdev->rs_last_mark + DRBD_SYNC_MARKS-2) % DRBD_SYNC_MARKS;
+ rs_left = drbd_bm_total_weight(mdev) - mdev->rs_failed;
+
+ dt = ((long)jiffies - (long)mdev->rs_mark_time[i]) / HZ;
+ if (!dt)
+ dt++;
+ db = mdev->rs_mark_left[i] - rs_left;
+ dbdt = Bit2KB(db/dt);
+
+ if (dbdt > mdev->sync_conf.c_min_rate)
+ throttle = 1;
+ }
+ return throttle;
+}
+
+
+static int receive_DataRequest(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int digest_size)
{
sector_t sector;
const sector_t capacity = drbd_get_capacity(mdev->this_bdev);
struct drbd_epoch_entry *e;
struct digest_info *di = NULL;
- int size, digest_size;
+ int size, verb;
unsigned int fault_type;
- struct p_block_req *p =
- (struct p_block_req *)h;
- const int brps = sizeof(*p)-sizeof(*h);
-
- if (drbd_recv(mdev, h->payload, brps) != brps)
- return FALSE;
+ struct p_block_req *p = &mdev->data.rbuf.block_req;
sector = be64_to_cpu(p->sector);
size = be32_to_cpu(p->blksize);
@@ -2046,12 +2098,31 @@ static int receive_DataRequest(struct drbd_conf *mdev, struct p_header *h)
}
if (!get_ldev_if_state(mdev, D_UP_TO_DATE)) {
- if (__ratelimit(&drbd_ratelimit_state))
+ verb = 1;
+ switch (cmd) {
+ case P_DATA_REQUEST:
+ drbd_send_ack_rp(mdev, P_NEG_DREPLY, p);
+ break;
+ case P_RS_DATA_REQUEST:
+ case P_CSUM_RS_REQUEST:
+ case P_OV_REQUEST:
+ drbd_send_ack_rp(mdev, P_NEG_RS_DREPLY , p);
+ break;
+ case P_OV_REPLY:
+ verb = 0;
+ dec_rs_pending(mdev);
+ drbd_send_ack_ex(mdev, P_OV_RESULT, sector, size, ID_IN_SYNC);
+ break;
+ default:
+ dev_err(DEV, "unexpected command (%s) in receive_DataRequest\n",
+ cmdname(cmd));
+ }
+ if (verb && __ratelimit(&drbd_ratelimit_state))
dev_err(DEV, "Can not satisfy peer's read request, "
"no local data.\n");
- drbd_send_ack_rp(mdev, h->command == P_DATA_REQUEST ? P_NEG_DREPLY :
- P_NEG_RS_DREPLY , p);
- return drbd_drain_block(mdev, h->length - brps);
+
+ /* drain possibly payload */
+ return drbd_drain_block(mdev, digest_size);
}
/* GFP_NOIO, because we must not cause arbitrary write-out: in a DRBD
@@ -2063,31 +2134,21 @@ static int receive_DataRequest(struct drbd_conf *mdev, struct p_header *h)
return FALSE;
}
- switch (h->command) {
+ switch (cmd) {
case P_DATA_REQUEST:
e->w.cb = w_e_end_data_req;
fault_type = DRBD_FAULT_DT_RD;
- break;
+ /* application IO, don't drbd_rs_begin_io */
+ goto submit;
+
case P_RS_DATA_REQUEST:
e->w.cb = w_e_end_rsdata_req;
fault_type = DRBD_FAULT_RS_RD;
- /* Eventually this should become asynchronously. Currently it
- * blocks the whole receiver just to delay the reading of a
- * resync data block.
- * the drbd_work_queue mechanism is made for this...
- */
- if (!drbd_rs_begin_io(mdev, sector)) {
- /* we have been interrupted,
- * probably connection lost! */
- D_ASSERT(signal_pending(current));
- goto out_free_e;
- }
break;
case P_OV_REPLY:
case P_CSUM_RS_REQUEST:
fault_type = DRBD_FAULT_RS_RD;
- digest_size = h->length - brps ;
di = kmalloc(sizeof(*di) + digest_size, GFP_NOIO);
if (!di)
goto out_free_e;
@@ -2095,31 +2156,25 @@ static int receive_DataRequest(struct drbd_conf *mdev, struct p_header *h)
di->digest_size = digest_size;
di->digest = (((char *)di)+sizeof(struct digest_info));
+ e->digest = di;
+ e->flags |= EE_HAS_DIGEST;
+
if (drbd_recv(mdev, di->digest, digest_size) != digest_size)
goto out_free_e;
- e->block_id = (u64)(unsigned long)di;
- if (h->command == P_CSUM_RS_REQUEST) {
+ if (cmd == P_CSUM_RS_REQUEST) {
D_ASSERT(mdev->agreed_pro_version >= 89);
e->w.cb = w_e_end_csum_rs_req;
- } else if (h->command == P_OV_REPLY) {
+ } else if (cmd == P_OV_REPLY) {
e->w.cb = w_e_end_ov_reply;
dec_rs_pending(mdev);
- break;
- }
-
- if (!drbd_rs_begin_io(mdev, sector)) {
- /* we have been interrupted, probably connection lost! */
- D_ASSERT(signal_pending(current));
- goto out_free_e;
+ /* drbd_rs_begin_io done when we sent this request,
+ * but accounting still needs to be done. */
+ goto submit_for_resync;
}
break;
case P_OV_REQUEST:
- if (mdev->state.conn >= C_CONNECTED &&
- mdev->state.conn != C_VERIFY_T)
- dev_warn(DEV, "ASSERT FAILED: got P_OV_REQUEST while being %s\n",
- drbd_conn_str(mdev->state.conn));
if (mdev->ov_start_sector == ~(sector_t)0 &&
mdev->agreed_pro_version >= 90) {
mdev->ov_start_sector = sector;
@@ -2130,37 +2185,63 @@ static int receive_DataRequest(struct drbd_conf *mdev, struct p_header *h)
}
e->w.cb = w_e_end_ov_req;
fault_type = DRBD_FAULT_RS_RD;
- /* Eventually this should become asynchronous. Currently it
- * blocks the whole receiver just to delay the reading of a
- * resync data block.
- * the drbd_work_queue mechanism is made for this...
- */
- if (!drbd_rs_begin_io(mdev, sector)) {
- /* we have been interrupted,
- * probably connection lost! */
- D_ASSERT(signal_pending(current));
- goto out_free_e;
- }
break;
-
default:
dev_err(DEV, "unexpected command (%s) in receive_DataRequest\n",
- cmdname(h->command));
+ cmdname(cmd));
fault_type = DRBD_FAULT_MAX;
+ goto out_free_e;
}
- spin_lock_irq(&mdev->req_lock);
- list_add(&e->w.list, &mdev->read_ee);
- spin_unlock_irq(&mdev->req_lock);
+ /* Throttle, drbd_rs_begin_io and submit should become asynchronous
+ * wrt the receiver, but it is not as straightforward as it may seem.
+ * Various places in the resync start and stop logic assume resync
+ * requests are processed in order, requeuing this on the worker thread
+ * introduces a bunch of new code for synchronization between threads.
+ *
+ * Unlimited throttling before drbd_rs_begin_io may stall the resync
+ * "forever", throttling after drbd_rs_begin_io will lock that extent
+ * for application writes for the same time. For now, just throttle
+ * here, where the rest of the code expects the receiver to sleep for
+ * a while, anyways.
+ */
+
+ /* Throttle before drbd_rs_begin_io, as that locks out application IO;
+ * this defers syncer requests for some time, before letting at least
+ * on request through. The resync controller on the receiving side
+ * will adapt to the incoming rate accordingly.
+ *
+ * We cannot throttle here if remote is Primary/SyncTarget:
+ * we would also throttle its application reads.
+ * In that case, throttling is done on the SyncTarget only.
+ */
+ if (mdev->state.peer != R_PRIMARY && drbd_rs_should_slow_down(mdev))
+ msleep(100);
+ if (drbd_rs_begin_io(mdev, e->sector))
+ goto out_free_e;
+submit_for_resync:
+ atomic_add(size >> 9, &mdev->rs_sect_ev);
+
+submit:
inc_unacked(mdev);
+ spin_lock_irq(&mdev->req_lock);
+ list_add_tail(&e->w.list, &mdev->read_ee);
+ spin_unlock_irq(&mdev->req_lock);
if (drbd_submit_ee(mdev, e, READ, fault_type) == 0)
return TRUE;
+ /* drbd_submit_ee currently fails for one reason only:
+ * not being able to allocate enough bios.
+ * Is dropping the connection going to help? */
+ spin_lock_irq(&mdev->req_lock);
+ list_del(&e->w.list);
+ spin_unlock_irq(&mdev->req_lock);
+ /* no drbd_rs_complete_io(), we are dropping the connection anyways */
+
out_free_e:
- kfree(di);
put_ldev(mdev);
drbd_free_ee(mdev, e);
return FALSE;
@@ -2699,20 +2780,13 @@ static int cmp_after_sb(enum drbd_after_sb_p peer, enum drbd_after_sb_p self)
return 1;
}
-static int receive_protocol(struct drbd_conf *mdev, struct p_header *h)
+static int receive_protocol(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
{
- struct p_protocol *p = (struct p_protocol *)h;
- int header_size, data_size;
+ struct p_protocol *p = &mdev->data.rbuf.protocol;
int p_proto, p_after_sb_0p, p_after_sb_1p, p_after_sb_2p;
int p_want_lose, p_two_primaries, cf;
char p_integrity_alg[SHARED_SECRET_MAX] = "";
- header_size = sizeof(*p) - sizeof(*h);
- data_size = h->length - header_size;
-
- if (drbd_recv(mdev, h->payload, header_size) != header_size)
- return FALSE;
-
p_proto = be32_to_cpu(p->protocol);
p_after_sb_0p = be32_to_cpu(p->after_sb_0p);
p_after_sb_1p = be32_to_cpu(p->after_sb_1p);
@@ -2805,39 +2879,46 @@ struct crypto_hash *drbd_crypto_alloc_digest_safe(const struct drbd_conf *mdev,
return tfm;
}
-static int receive_SyncParam(struct drbd_conf *mdev, struct p_header *h)
+static int receive_SyncParam(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int packet_size)
{
int ok = TRUE;
- struct p_rs_param_89 *p = (struct p_rs_param_89 *)h;
+ struct p_rs_param_95 *p = &mdev->data.rbuf.rs_param_95;
unsigned int header_size, data_size, exp_max_sz;
struct crypto_hash *verify_tfm = NULL;
struct crypto_hash *csums_tfm = NULL;
const int apv = mdev->agreed_pro_version;
+ int *rs_plan_s = NULL;
+ int fifo_size = 0;
exp_max_sz = apv <= 87 ? sizeof(struct p_rs_param)
: apv == 88 ? sizeof(struct p_rs_param)
+ SHARED_SECRET_MAX
- : /* 89 */ sizeof(struct p_rs_param_89);
+ : apv <= 94 ? sizeof(struct p_rs_param_89)
+ : /* apv >= 95 */ sizeof(struct p_rs_param_95);
- if (h->length > exp_max_sz) {
+ if (packet_size > exp_max_sz) {
dev_err(DEV, "SyncParam packet too long: received %u, expected <= %u bytes\n",
- h->length, exp_max_sz);
+ packet_size, exp_max_sz);
return FALSE;
}
if (apv <= 88) {
- header_size = sizeof(struct p_rs_param) - sizeof(*h);
- data_size = h->length - header_size;
- } else /* apv >= 89 */ {
- header_size = sizeof(struct p_rs_param_89) - sizeof(*h);
- data_size = h->length - header_size;
+ header_size = sizeof(struct p_rs_param) - sizeof(struct p_header80);
+ data_size = packet_size - header_size;
+ } else if (apv <= 94) {
+ header_size = sizeof(struct p_rs_param_89) - sizeof(struct p_header80);
+ data_size = packet_size - header_size;
+ D_ASSERT(data_size == 0);
+ } else {
+ header_size = sizeof(struct p_rs_param_95) - sizeof(struct p_header80);
+ data_size = packet_size - header_size;
D_ASSERT(data_size == 0);
}
/* initialize verify_alg and csums_alg */
memset(p->verify_alg, 0, 2 * SHARED_SECRET_MAX);
- if (drbd_recv(mdev, h->payload, header_size) != header_size)
+ if (drbd_recv(mdev, &p->head.payload, header_size) != header_size)
return FALSE;
mdev->sync_conf.rate = be32_to_cpu(p->rate);
@@ -2896,6 +2977,22 @@ static int receive_SyncParam(struct drbd_conf *mdev, struct p_header *h)
}
}
+ if (apv > 94) {
+ mdev->sync_conf.rate = be32_to_cpu(p->rate);
+ mdev->sync_conf.c_plan_ahead = be32_to_cpu(p->c_plan_ahead);
+ mdev->sync_conf.c_delay_target = be32_to_cpu(p->c_delay_target);
+ mdev->sync_conf.c_fill_target = be32_to_cpu(p->c_fill_target);
+ mdev->sync_conf.c_max_rate = be32_to_cpu(p->c_max_rate);
+
+ fifo_size = (mdev->sync_conf.c_plan_ahead * 10 * SLEEP_TIME) / HZ;
+ if (fifo_size != mdev->rs_plan_s.size && fifo_size > 0) {
+ rs_plan_s = kzalloc(sizeof(int) * fifo_size, GFP_KERNEL);
+ if (!rs_plan_s) {
+ dev_err(DEV, "kmalloc of fifo_buffer failed");
+ goto disconnect;
+ }
+ }
+ }
spin_lock(&mdev->peer_seq_lock);
/* lock against drbd_nl_syncer_conf() */
@@ -2913,6 +3010,12 @@ static int receive_SyncParam(struct drbd_conf *mdev, struct p_header *h)
mdev->csums_tfm = csums_tfm;
dev_info(DEV, "using csums-alg: \"%s\"\n", p->csums_alg);
}
+ if (fifo_size != mdev->rs_plan_s.size) {
+ kfree(mdev->rs_plan_s.values);
+ mdev->rs_plan_s.values = rs_plan_s;
+ mdev->rs_plan_s.size = fifo_size;
+ mdev->rs_planed = 0;
+ }
spin_unlock(&mdev->peer_seq_lock);
}
@@ -2946,19 +3049,15 @@ static void warn_if_differ_considerably(struct drbd_conf *mdev,
(unsigned long long)a, (unsigned long long)b);
}
-static int receive_sizes(struct drbd_conf *mdev, struct p_header *h)
+static int receive_sizes(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
{
- struct p_sizes *p = (struct p_sizes *)h;
+ struct p_sizes *p = &mdev->data.rbuf.sizes;
enum determine_dev_size dd = unchanged;
unsigned int max_seg_s;
sector_t p_size, p_usize, my_usize;
int ldsc = 0; /* local disk size changed */
enum dds_flags ddsf;
- ERR_IF(h->length != (sizeof(*p)-sizeof(*h))) return FALSE;
- if (drbd_recv(mdev, h->payload, h->length) != h->length)
- return FALSE;
-
p_size = be64_to_cpu(p->d_size);
p_usize = be64_to_cpu(p->u_size);
@@ -2972,7 +3071,6 @@ static int receive_sizes(struct drbd_conf *mdev, struct p_header *h)
* we still need to figure out whether we accept that. */
mdev->p_size = p_size;
-#define min_not_zero(l, r) (l == 0) ? r : ((r == 0) ? l : min(l, r))
if (get_ldev(mdev)) {
warn_if_differ_considerably(mdev, "lower level device sizes",
p_size, drbd_get_max_capacity(mdev->ldev));
@@ -3029,6 +3127,8 @@ static int receive_sizes(struct drbd_conf *mdev, struct p_header *h)
if (mdev->agreed_pro_version < 94)
max_seg_s = be32_to_cpu(p->max_segment_size);
+ else if (mdev->agreed_pro_version == 94)
+ max_seg_s = DRBD_MAX_SIZE_H80_PACKET;
else /* drbd 8.3.8 onwards */
max_seg_s = DRBD_MAX_SEGMENT_SIZE;
@@ -3062,16 +3162,12 @@ static int receive_sizes(struct drbd_conf *mdev, struct p_header *h)
return TRUE;
}
-static int receive_uuids(struct drbd_conf *mdev, struct p_header *h)
+static int receive_uuids(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
{
- struct p_uuids *p = (struct p_uuids *)h;
+ struct p_uuids *p = &mdev->data.rbuf.uuids;
u64 *p_uuid;
int i;
- ERR_IF(h->length != (sizeof(*p)-sizeof(*h))) return FALSE;
- if (drbd_recv(mdev, h->payload, h->length) != h->length)
- return FALSE;
-
p_uuid = kmalloc(sizeof(u64)*UI_EXTENDED_SIZE, GFP_NOIO);
for (i = UI_CURRENT; i < UI_EXTENDED_SIZE; i++)
@@ -3107,6 +3203,11 @@ static int receive_uuids(struct drbd_conf *mdev, struct p_header *h)
drbd_md_sync(mdev);
}
put_ldev(mdev);
+ } else if (mdev->state.disk < D_INCONSISTENT &&
+ mdev->state.role == R_PRIMARY) {
+ /* I am a diskless primary, the peer just created a new current UUID
+ for me. */
+ drbd_set_ed_uuid(mdev, p_uuid[UI_CURRENT]);
}
/* Before we test for the disk state, we should wait until an eventually
@@ -3150,16 +3251,12 @@ static union drbd_state convert_state(union drbd_state ps)
return ms;
}
-static int receive_req_state(struct drbd_conf *mdev, struct p_header *h)
+static int receive_req_state(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
{
- struct p_req_state *p = (struct p_req_state *)h;
+ struct p_req_state *p = &mdev->data.rbuf.req_state;
union drbd_state mask, val;
int rv;
- ERR_IF(h->length != (sizeof(*p)-sizeof(*h))) return FALSE;
- if (drbd_recv(mdev, h->payload, h->length) != h->length)
- return FALSE;
-
mask.i = be32_to_cpu(p->mask);
val.i = be32_to_cpu(p->val);
@@ -3180,20 +3277,14 @@ static int receive_req_state(struct drbd_conf *mdev, struct p_header *h)
return TRUE;
}
-static int receive_state(struct drbd_conf *mdev, struct p_header *h)
+static int receive_state(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
{
- struct p_state *p = (struct p_state *)h;
- enum drbd_conns nconn, oconn;
- union drbd_state ns, peer_state;
+ struct p_state *p = &mdev->data.rbuf.state;
+ union drbd_state os, ns, peer_state;
enum drbd_disk_state real_peer_disk;
+ enum chg_state_flags cs_flags;
int rv;
- ERR_IF(h->length != (sizeof(*p)-sizeof(*h)))
- return FALSE;
-
- if (drbd_recv(mdev, h->payload, h->length) != h->length)
- return FALSE;
-
peer_state.i = be32_to_cpu(p->state);
real_peer_disk = peer_state.disk;
@@ -3204,38 +3295,72 @@ static int receive_state(struct drbd_conf *mdev, struct p_header *h)
spin_lock_irq(&mdev->req_lock);
retry:
- oconn = nconn = mdev->state.conn;
+ os = ns = mdev->state;
spin_unlock_irq(&mdev->req_lock);
- if (nconn == C_WF_REPORT_PARAMS)
- nconn = C_CONNECTED;
+ /* peer says his disk is uptodate, while we think it is inconsistent,
+ * and this happens while we think we have a sync going on. */
+ if (os.pdsk == D_INCONSISTENT && real_peer_disk == D_UP_TO_DATE &&
+ os.conn > C_CONNECTED && os.disk == D_UP_TO_DATE) {
+ /* If we are (becoming) SyncSource, but peer is still in sync
+ * preparation, ignore its uptodate-ness to avoid flapping, it
+ * will change to inconsistent once the peer reaches active
+ * syncing states.
+ * It may have changed syncer-paused flags, however, so we
+ * cannot ignore this completely. */
+ if (peer_state.conn > C_CONNECTED &&
+ peer_state.conn < C_SYNC_SOURCE)
+ real_peer_disk = D_INCONSISTENT;
+
+ /* if peer_state changes to connected at the same time,
+ * it explicitly notifies us that it finished resync.
+ * Maybe we should finish it up, too? */
+ else if (os.conn >= C_SYNC_SOURCE &&
+ peer_state.conn == C_CONNECTED) {
+ if (drbd_bm_total_weight(mdev) <= mdev->rs_failed)
+ drbd_resync_finished(mdev);
+ return TRUE;
+ }
+ }
+
+ /* peer says his disk is inconsistent, while we think it is uptodate,
+ * and this happens while the peer still thinks we have a sync going on,
+ * but we think we are already done with the sync.
+ * We ignore this to avoid flapping pdsk.
+ * This should not happen, if the peer is a recent version of drbd. */
+ if (os.pdsk == D_UP_TO_DATE && real_peer_disk == D_INCONSISTENT &&
+ os.conn == C_CONNECTED && peer_state.conn > C_SYNC_SOURCE)
+ real_peer_disk = D_UP_TO_DATE;
+
+ if (ns.conn == C_WF_REPORT_PARAMS)
+ ns.conn = C_CONNECTED;
if (mdev->p_uuid && peer_state.disk >= D_NEGOTIATING &&
get_ldev_if_state(mdev, D_NEGOTIATING)) {
int cr; /* consider resync */
/* if we established a new connection */
- cr = (oconn < C_CONNECTED);
+ cr = (os.conn < C_CONNECTED);
/* if we had an established connection
* and one of the nodes newly attaches a disk */
- cr |= (oconn == C_CONNECTED &&
+ cr |= (os.conn == C_CONNECTED &&
(peer_state.disk == D_NEGOTIATING ||
- mdev->state.disk == D_NEGOTIATING));
+ os.disk == D_NEGOTIATING));
/* if we have both been inconsistent, and the peer has been
* forced to be UpToDate with --overwrite-data */
cr |= test_bit(CONSIDER_RESYNC, &mdev->flags);
/* if we had been plain connected, and the admin requested to
* start a sync by "invalidate" or "invalidate-remote" */
- cr |= (oconn == C_CONNECTED &&
+ cr |= (os.conn == C_CONNECTED &&
(peer_state.conn >= C_STARTING_SYNC_S &&
peer_state.conn <= C_WF_BITMAP_T));
if (cr)
- nconn = drbd_sync_handshake(mdev, peer_state.role, real_peer_disk);
+ ns.conn = drbd_sync_handshake(mdev, peer_state.role, real_peer_disk);
put_ldev(mdev);
- if (nconn == C_MASK) {
- nconn = C_CONNECTED;
+ if (ns.conn == C_MASK) {
+ ns.conn = C_CONNECTED;
if (mdev->state.disk == D_NEGOTIATING) {
drbd_force_state(mdev, NS(disk, D_DISKLESS));
} else if (peer_state.disk == D_NEGOTIATING) {
@@ -3245,7 +3370,7 @@ static int receive_state(struct drbd_conf *mdev, struct p_header *h)
} else {
if (test_and_clear_bit(CONN_DRY_RUN, &mdev->flags))
return FALSE;
- D_ASSERT(oconn == C_WF_REPORT_PARAMS);
+ D_ASSERT(os.conn == C_WF_REPORT_PARAMS);
drbd_force_state(mdev, NS(conn, C_DISCONNECTING));
return FALSE;
}
@@ -3253,18 +3378,28 @@ static int receive_state(struct drbd_conf *mdev, struct p_header *h)
}
spin_lock_irq(&mdev->req_lock);
- if (mdev->state.conn != oconn)
+ if (mdev->state.i != os.i)
goto retry;
clear_bit(CONSIDER_RESYNC, &mdev->flags);
- ns.i = mdev->state.i;
- ns.conn = nconn;
ns.peer = peer_state.role;
ns.pdsk = real_peer_disk;
ns.peer_isp = (peer_state.aftr_isp | peer_state.user_isp);
- if ((nconn == C_CONNECTED || nconn == C_WF_BITMAP_S) && ns.disk == D_NEGOTIATING)
+ if ((ns.conn == C_CONNECTED || ns.conn == C_WF_BITMAP_S) && ns.disk == D_NEGOTIATING)
ns.disk = mdev->new_state_tmp.disk;
-
- rv = _drbd_set_state(mdev, ns, CS_VERBOSE | CS_HARD, NULL);
+ cs_flags = CS_VERBOSE + (os.conn < C_CONNECTED && ns.conn >= C_CONNECTED ? 0 : CS_HARD);
+ if (ns.pdsk == D_CONSISTENT && is_susp(ns) && ns.conn == C_CONNECTED && os.conn < C_CONNECTED &&
+ test_bit(NEW_CUR_UUID, &mdev->flags)) {
+ /* Do not allow tl_restart(resend) for a rebooted peer. We can only allow this
+ for temporal network outages! */
+ spin_unlock_irq(&mdev->req_lock);
+ dev_err(DEV, "Aborting Connect, can not thaw IO with an only Consistent peer\n");
+ tl_clear(mdev);
+ drbd_uuid_new_current(mdev);
+ clear_bit(NEW_CUR_UUID, &mdev->flags);
+ drbd_force_state(mdev, NS2(conn, C_PROTOCOL_ERROR, susp, 0));
+ return FALSE;
+ }
+ rv = _drbd_set_state(mdev, ns, cs_flags, NULL);
ns = mdev->state;
spin_unlock_irq(&mdev->req_lock);
@@ -3273,8 +3408,8 @@ static int receive_state(struct drbd_conf *mdev, struct p_header *h)
return FALSE;
}
- if (oconn > C_WF_REPORT_PARAMS) {
- if (nconn > C_CONNECTED && peer_state.conn <= C_CONNECTED &&
+ if (os.conn > C_WF_REPORT_PARAMS) {
+ if (ns.conn > C_CONNECTED && peer_state.conn <= C_CONNECTED &&
peer_state.disk != D_NEGOTIATING ) {
/* we want resync, peer has not yet decided to sync... */
/* Nowadays only used when forcing a node into primary role and
@@ -3291,9 +3426,9 @@ static int receive_state(struct drbd_conf *mdev, struct p_header *h)
return TRUE;
}
-static int receive_sync_uuid(struct drbd_conf *mdev, struct p_header *h)
+static int receive_sync_uuid(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
{
- struct p_rs_uuid *p = (struct p_rs_uuid *)h;
+ struct p_rs_uuid *p = &mdev->data.rbuf.rs_uuid;
wait_event(mdev->misc_wait,
mdev->state.conn == C_WF_SYNC_UUID ||
@@ -3302,10 +3437,6 @@ static int receive_sync_uuid(struct drbd_conf *mdev, struct p_header *h)
/* D_ASSERT( mdev->state.conn == C_WF_SYNC_UUID ); */
- ERR_IF(h->length != (sizeof(*p)-sizeof(*h))) return FALSE;
- if (drbd_recv(mdev, h->payload, h->length) != h->length)
- return FALSE;
-
/* Here the _drbd_uuid_ functions are right, current should
_not_ be rotated into the history */
if (get_ldev_if_state(mdev, D_NEGOTIATING)) {
@@ -3324,14 +3455,14 @@ static int receive_sync_uuid(struct drbd_conf *mdev, struct p_header *h)
enum receive_bitmap_ret { OK, DONE, FAILED };
static enum receive_bitmap_ret
-receive_bitmap_plain(struct drbd_conf *mdev, struct p_header *h,
- unsigned long *buffer, struct bm_xfer_ctx *c)
+receive_bitmap_plain(struct drbd_conf *mdev, unsigned int data_size,
+ unsigned long *buffer, struct bm_xfer_ctx *c)
{
unsigned num_words = min_t(size_t, BM_PACKET_WORDS, c->bm_words - c->word_offset);
unsigned want = num_words * sizeof(long);
- if (want != h->length) {
- dev_err(DEV, "%s:want (%u) != h->length (%u)\n", __func__, want, h->length);
+ if (want != data_size) {
+ dev_err(DEV, "%s:want (%u) != data_size (%u)\n", __func__, want, data_size);
return FAILED;
}
if (want == 0)
@@ -3360,7 +3491,7 @@ recv_bm_rle_bits(struct drbd_conf *mdev,
u64 tmp;
unsigned long s = c->bit_offset;
unsigned long e;
- int len = p->head.length - (sizeof(*p) - sizeof(p->head));
+ int len = be16_to_cpu(p->head.length) - (sizeof(*p) - sizeof(p->head));
int toggle = DCBP_get_start(p);
int have;
int bits;
@@ -3429,7 +3560,7 @@ void INFO_bm_xfer_stats(struct drbd_conf *mdev,
const char *direction, struct bm_xfer_ctx *c)
{
/* what would it take to transfer it "plaintext" */
- unsigned plain = sizeof(struct p_header) *
+ unsigned plain = sizeof(struct p_header80) *
((c->bm_words+BM_PACKET_WORDS-1)/BM_PACKET_WORDS+1)
+ c->bm_words * sizeof(long);
unsigned total = c->bytes[0] + c->bytes[1];
@@ -3467,12 +3598,13 @@ void INFO_bm_xfer_stats(struct drbd_conf *mdev,
in order to be agnostic to the 32 vs 64 bits issue.
returns 0 on failure, 1 if we successfully received it. */
-static int receive_bitmap(struct drbd_conf *mdev, struct p_header *h)
+static int receive_bitmap(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
{
struct bm_xfer_ctx c;
void *buffer;
enum receive_bitmap_ret ret;
int ok = FALSE;
+ struct p_header80 *h = &mdev->data.rbuf.header.h80;
wait_event(mdev->misc_wait, !atomic_read(&mdev->ap_bio_cnt));
@@ -3492,39 +3624,39 @@ static int receive_bitmap(struct drbd_conf *mdev, struct p_header *h)
};
do {
- if (h->command == P_BITMAP) {
- ret = receive_bitmap_plain(mdev, h, buffer, &c);
- } else if (h->command == P_COMPRESSED_BITMAP) {
+ if (cmd == P_BITMAP) {
+ ret = receive_bitmap_plain(mdev, data_size, buffer, &c);
+ } else if (cmd == P_COMPRESSED_BITMAP) {
/* MAYBE: sanity check that we speak proto >= 90,
* and the feature is enabled! */
struct p_compressed_bm *p;
- if (h->length > BM_PACKET_PAYLOAD_BYTES) {
+ if (data_size > BM_PACKET_PAYLOAD_BYTES) {
dev_err(DEV, "ReportCBitmap packet too large\n");
goto out;
}
/* use the page buff */
p = buffer;
memcpy(p, h, sizeof(*h));
- if (drbd_recv(mdev, p->head.payload, h->length) != h->length)
+ if (drbd_recv(mdev, p->head.payload, data_size) != data_size)
goto out;
- if (p->head.length <= (sizeof(*p) - sizeof(p->head))) {
- dev_err(DEV, "ReportCBitmap packet too small (l:%u)\n", p->head.length);
+ if (data_size <= (sizeof(*p) - sizeof(p->head))) {
+ dev_err(DEV, "ReportCBitmap packet too small (l:%u)\n", data_size);
return FAILED;
}
ret = decode_bitmap_c(mdev, p, &c);
} else {
- dev_warn(DEV, "receive_bitmap: h->command neither ReportBitMap nor ReportCBitMap (is 0x%x)", h->command);
+ dev_warn(DEV, "receive_bitmap: cmd neither ReportBitMap nor ReportCBitMap (is 0x%x)", cmd);
goto out;
}
- c.packets[h->command == P_BITMAP]++;
- c.bytes[h->command == P_BITMAP] += sizeof(struct p_header) + h->length;
+ c.packets[cmd == P_BITMAP]++;
+ c.bytes[cmd == P_BITMAP] += sizeof(struct p_header80) + data_size;
if (ret != OK)
break;
- if (!drbd_recv_header(mdev, h))
+ if (!drbd_recv_header(mdev, &cmd, &data_size))
goto out;
} while (ret == OK);
if (ret == FAILED)
@@ -3555,17 +3687,16 @@ static int receive_bitmap(struct drbd_conf *mdev, struct p_header *h)
return ok;
}
-static int receive_skip_(struct drbd_conf *mdev, struct p_header *h, int silent)
+static int receive_skip(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
{
/* TODO zero copy sink :) */
static char sink[128];
int size, want, r;
- if (!silent)
- dev_warn(DEV, "skipping unknown optional packet type %d, l: %d!\n",
- h->command, h->length);
+ dev_warn(DEV, "skipping unknown optional packet type %d, l: %d!\n",
+ cmd, data_size);
- size = h->length;
+ size = data_size;
while (size > 0) {
want = min_t(int, size, sizeof(sink));
r = drbd_recv(mdev, sink, want);
@@ -3575,17 +3706,7 @@ static int receive_skip_(struct drbd_conf *mdev, struct p_header *h, int silent)
return size == 0;
}
-static int receive_skip(struct drbd_conf *mdev, struct p_header *h)
-{
- return receive_skip_(mdev, h, 0);
-}
-
-static int receive_skip_silent(struct drbd_conf *mdev, struct p_header *h)
-{
- return receive_skip_(mdev, h, 1);
-}
-
-static int receive_UnplugRemote(struct drbd_conf *mdev, struct p_header *h)
+static int receive_UnplugRemote(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
{
if (mdev->state.disk >= D_INCONSISTENT)
drbd_kick_lo(mdev);
@@ -3597,108 +3718,94 @@ static int receive_UnplugRemote(struct drbd_conf *mdev, struct p_header *h)
return TRUE;
}
-typedef int (*drbd_cmd_handler_f)(struct drbd_conf *, struct p_header *);
-
-static drbd_cmd_handler_f drbd_default_handler[] = {
- [P_DATA] = receive_Data,
- [P_DATA_REPLY] = receive_DataReply,
- [P_RS_DATA_REPLY] = receive_RSDataReply,
- [P_BARRIER] = receive_Barrier,
- [P_BITMAP] = receive_bitmap,
- [P_COMPRESSED_BITMAP] = receive_bitmap,
- [P_UNPLUG_REMOTE] = receive_UnplugRemote,
- [P_DATA_REQUEST] = receive_DataRequest,
- [P_RS_DATA_REQUEST] = receive_DataRequest,
- [P_SYNC_PARAM] = receive_SyncParam,
- [P_SYNC_PARAM89] = receive_SyncParam,
- [P_PROTOCOL] = receive_protocol,
- [P_UUIDS] = receive_uuids,
- [P_SIZES] = receive_sizes,
- [P_STATE] = receive_state,
- [P_STATE_CHG_REQ] = receive_req_state,
- [P_SYNC_UUID] = receive_sync_uuid,
- [P_OV_REQUEST] = receive_DataRequest,
- [P_OV_REPLY] = receive_DataRequest,
- [P_CSUM_RS_REQUEST] = receive_DataRequest,
- [P_DELAY_PROBE] = receive_skip_silent,
+typedef int (*drbd_cmd_handler_f)(struct drbd_conf *, enum drbd_packets cmd, unsigned int to_receive);
+
+struct data_cmd {
+ int expect_payload;
+ size_t pkt_size;
+ drbd_cmd_handler_f function;
+};
+
+static struct data_cmd drbd_cmd_handler[] = {
+ [P_DATA] = { 1, sizeof(struct p_data), receive_Data },
+ [P_DATA_REPLY] = { 1, sizeof(struct p_data), receive_DataReply },
+ [P_RS_DATA_REPLY] = { 1, sizeof(struct p_data), receive_RSDataReply } ,
+ [P_BARRIER] = { 0, sizeof(struct p_barrier), receive_Barrier } ,
+ [P_BITMAP] = { 1, sizeof(struct p_header80), receive_bitmap } ,
+ [P_COMPRESSED_BITMAP] = { 1, sizeof(struct p_header80), receive_bitmap } ,
+ [P_UNPLUG_REMOTE] = { 0, sizeof(struct p_header80), receive_UnplugRemote },
+ [P_DATA_REQUEST] = { 0, sizeof(struct p_block_req), receive_DataRequest },
+ [P_RS_DATA_REQUEST] = { 0, sizeof(struct p_block_req), receive_DataRequest },
+ [P_SYNC_PARAM] = { 1, sizeof(struct p_header80), receive_SyncParam },
+ [P_SYNC_PARAM89] = { 1, sizeof(struct p_header80), receive_SyncParam },
+ [P_PROTOCOL] = { 1, sizeof(struct p_protocol), receive_protocol },
+ [P_UUIDS] = { 0, sizeof(struct p_uuids), receive_uuids },
+ [P_SIZES] = { 0, sizeof(struct p_sizes), receive_sizes },
+ [P_STATE] = { 0, sizeof(struct p_state), receive_state },
+ [P_STATE_CHG_REQ] = { 0, sizeof(struct p_req_state), receive_req_state },
+ [P_SYNC_UUID] = { 0, sizeof(struct p_rs_uuid), receive_sync_uuid },
+ [P_OV_REQUEST] = { 0, sizeof(struct p_block_req), receive_DataRequest },
+ [P_OV_REPLY] = { 1, sizeof(struct p_block_req), receive_DataRequest },
+ [P_CSUM_RS_REQUEST] = { 1, sizeof(struct p_block_req), receive_DataRequest },
+ [P_DELAY_PROBE] = { 0, sizeof(struct p_delay_probe93), receive_skip },
/* anything missing from this table is in
* the asender_tbl, see get_asender_cmd */
- [P_MAX_CMD] = NULL,
+ [P_MAX_CMD] = { 0, 0, NULL },
};
-static drbd_cmd_handler_f *drbd_cmd_handler = drbd_default_handler;
-static drbd_cmd_handler_f *drbd_opt_cmd_handler;
+/* All handler functions that expect a sub-header get that sub-heder in
+ mdev->data.rbuf.header.head.payload.
+
+ Usually in mdev->data.rbuf.header.head the callback can find the usual
+ p_header, but they may not rely on that. Since there is also p_header95 !
+ */
static void drbdd(struct drbd_conf *mdev)
{
- drbd_cmd_handler_f handler;
- struct p_header *header = &mdev->data.rbuf.header;
+ union p_header *header = &mdev->data.rbuf.header;
+ unsigned int packet_size;
+ enum drbd_packets cmd;
+ size_t shs; /* sub header size */
+ int rv;
while (get_t_state(&mdev->receiver) == Running) {
drbd_thread_current_set_cpu(mdev);
- if (!drbd_recv_header(mdev, header)) {
- drbd_force_state(mdev, NS(conn, C_PROTOCOL_ERROR));
- break;
- }
+ if (!drbd_recv_header(mdev, &cmd, &packet_size))
+ goto err_out;
- if (header->command < P_MAX_CMD)
- handler = drbd_cmd_handler[header->command];
- else if (P_MAY_IGNORE < header->command
- && header->command < P_MAX_OPT_CMD)
- handler = drbd_opt_cmd_handler[header->command-P_MAY_IGNORE];
- else if (header->command > P_MAX_OPT_CMD)
- handler = receive_skip;
- else
- handler = NULL;
+ if (unlikely(cmd >= P_MAX_CMD || !drbd_cmd_handler[cmd].function)) {
+ dev_err(DEV, "unknown packet type %d, l: %d!\n", cmd, packet_size);
+ goto err_out;
+ }
- if (unlikely(!handler)) {
- dev_err(DEV, "unknown packet type %d, l: %d!\n",
- header->command, header->length);
- drbd_force_state(mdev, NS(conn, C_PROTOCOL_ERROR));
- break;
+ shs = drbd_cmd_handler[cmd].pkt_size - sizeof(union p_header);
+ rv = drbd_recv(mdev, &header->h80.payload, shs);
+ if (unlikely(rv != shs)) {
+ dev_err(DEV, "short read while reading sub header: rv=%d\n", rv);
+ goto err_out;
}
- if (unlikely(!handler(mdev, header))) {
- dev_err(DEV, "error receiving %s, l: %d!\n",
- cmdname(header->command), header->length);
- drbd_force_state(mdev, NS(conn, C_PROTOCOL_ERROR));
- break;
+
+ if (packet_size - shs > 0 && !drbd_cmd_handler[cmd].expect_payload) {
+ dev_err(DEV, "No payload expected %s l:%d\n", cmdname(cmd), packet_size);
+ goto err_out;
}
- }
-}
-static void drbd_fail_pending_reads(struct drbd_conf *mdev)
-{
- struct hlist_head *slot;
- struct hlist_node *pos;
- struct hlist_node *tmp;
- struct drbd_request *req;
- int i;
+ rv = drbd_cmd_handler[cmd].function(mdev, cmd, packet_size - shs);
- /*
- * Application READ requests
- */
- spin_lock_irq(&mdev->req_lock);
- for (i = 0; i < APP_R_HSIZE; i++) {
- slot = mdev->app_reads_hash+i;
- hlist_for_each_entry_safe(req, pos, tmp, slot, colision) {
- /* it may (but should not any longer!)
- * be on the work queue; if that assert triggers,
- * we need to also grab the
- * spin_lock_irq(&mdev->data.work.q_lock);
- * and list_del_init here. */
- D_ASSERT(list_empty(&req->w.list));
- /* It would be nice to complete outside of spinlock.
- * But this is easier for now. */
- _req_mod(req, connection_lost_while_pending);
+ if (unlikely(!rv)) {
+ dev_err(DEV, "error receiving %s, l: %d!\n",
+ cmdname(cmd), packet_size);
+ goto err_out;
}
}
- for (i = 0; i < APP_R_HSIZE; i++)
- if (!hlist_empty(mdev->app_reads_hash+i))
- dev_warn(DEV, "ASSERT FAILED: app_reads_hash[%d].first: "
- "%p, should be NULL\n", i, mdev->app_reads_hash[i].first);
- memset(mdev->app_reads_hash, 0, APP_R_HSIZE*sizeof(void *));
- spin_unlock_irq(&mdev->req_lock);
+ if (0) {
+ err_out:
+ drbd_force_state(mdev, NS(conn, C_PROTOCOL_ERROR));
+ }
+ /* If we leave here, we probably want to update at least the
+ * "Connected" indicator on stable storage. Do so explicitly here. */
+ drbd_md_sync(mdev);
}
void drbd_flush_workqueue(struct drbd_conf *mdev)
@@ -3711,6 +3818,36 @@ void drbd_flush_workqueue(struct drbd_conf *mdev)
wait_for_completion(&barr.done);
}
+void drbd_free_tl_hash(struct drbd_conf *mdev)
+{
+ struct hlist_head *h;
+
+ spin_lock_irq(&mdev->req_lock);
+
+ if (!mdev->tl_hash || mdev->state.conn != C_STANDALONE) {
+ spin_unlock_irq(&mdev->req_lock);
+ return;
+ }
+ /* paranoia code */
+ for (h = mdev->ee_hash; h < mdev->ee_hash + mdev->ee_hash_s; h++)
+ if (h->first)
+ dev_err(DEV, "ASSERT FAILED ee_hash[%u].first == %p, expected NULL\n",
+ (int)(h - mdev->ee_hash), h->first);
+ kfree(mdev->ee_hash);
+ mdev->ee_hash = NULL;
+ mdev->ee_hash_s = 0;
+
+ /* paranoia code */
+ for (h = mdev->tl_hash; h < mdev->tl_hash + mdev->tl_hash_s; h++)
+ if (h->first)
+ dev_err(DEV, "ASSERT FAILED tl_hash[%u] == %p, expected NULL\n",
+ (int)(h - mdev->tl_hash), h->first);
+ kfree(mdev->tl_hash);
+ mdev->tl_hash = NULL;
+ mdev->tl_hash_s = 0;
+ spin_unlock_irq(&mdev->req_lock);
+}
+
static void drbd_disconnect(struct drbd_conf *mdev)
{
enum drbd_fencing_p fp;
@@ -3728,6 +3865,7 @@ static void drbd_disconnect(struct drbd_conf *mdev)
drbd_thread_stop(&mdev->asender);
drbd_free_sock(mdev);
+ /* wait for current activity to cease. */
spin_lock_irq(&mdev->req_lock);
_drbd_wait_ee_list_empty(mdev, &mdev->active_ee);
_drbd_wait_ee_list_empty(mdev, &mdev->sync_ee);
@@ -3752,7 +3890,6 @@ static void drbd_disconnect(struct drbd_conf *mdev)
/* make sure syncer is stopped and w_resume_next_sg queued */
del_timer_sync(&mdev->resync_timer);
- set_bit(STOP_SYNC_TIMER, &mdev->flags);
resync_timer_fn((unsigned long)mdev);
/* wait for all w_e_end_data_req, w_e_end_rsdata_req, w_send_barrier,
@@ -3767,11 +3904,9 @@ static void drbd_disconnect(struct drbd_conf *mdev)
kfree(mdev->p_uuid);
mdev->p_uuid = NULL;
- if (!mdev->state.susp)
+ if (!is_susp(mdev->state))
tl_clear(mdev);
- drbd_fail_pending_reads(mdev);
-
dev_info(DEV, "Connection closed\n");
drbd_md_sync(mdev);
@@ -3782,12 +3917,8 @@ static void drbd_disconnect(struct drbd_conf *mdev)
put_ldev(mdev);
}
- if (mdev->state.role == R_PRIMARY) {
- if (fp >= FP_RESOURCE && mdev->state.pdsk >= D_UNKNOWN) {
- enum drbd_disk_state nps = drbd_try_outdate_peer(mdev);
- drbd_request_state(mdev, NS(pdsk, nps));
- }
- }
+ if (mdev->state.role == R_PRIMARY && fp >= FP_RESOURCE && mdev->state.pdsk >= D_UNKNOWN)
+ drbd_try_outdate_peer_async(mdev);
spin_lock_irq(&mdev->req_lock);
os = mdev->state;
@@ -3800,32 +3931,14 @@ static void drbd_disconnect(struct drbd_conf *mdev)
spin_unlock_irq(&mdev->req_lock);
if (os.conn == C_DISCONNECTING) {
- struct hlist_head *h;
- wait_event(mdev->misc_wait, atomic_read(&mdev->net_cnt) == 0);
+ wait_event(mdev->net_cnt_wait, atomic_read(&mdev->net_cnt) == 0);
- /* we must not free the tl_hash
- * while application io is still on the fly */
- wait_event(mdev->misc_wait, atomic_read(&mdev->ap_bio_cnt) == 0);
-
- spin_lock_irq(&mdev->req_lock);
- /* paranoia code */
- for (h = mdev->ee_hash; h < mdev->ee_hash + mdev->ee_hash_s; h++)
- if (h->first)
- dev_err(DEV, "ASSERT FAILED ee_hash[%u].first == %p, expected NULL\n",
- (int)(h - mdev->ee_hash), h->first);
- kfree(mdev->ee_hash);
- mdev->ee_hash = NULL;
- mdev->ee_hash_s = 0;
-
- /* paranoia code */
- for (h = mdev->tl_hash; h < mdev->tl_hash + mdev->tl_hash_s; h++)
- if (h->first)
- dev_err(DEV, "ASSERT FAILED tl_hash[%u] == %p, expected NULL\n",
- (int)(h - mdev->tl_hash), h->first);
- kfree(mdev->tl_hash);
- mdev->tl_hash = NULL;
- mdev->tl_hash_s = 0;
- spin_unlock_irq(&mdev->req_lock);
+ if (!is_susp(mdev->state)) {
+ /* we must not free the tl_hash
+ * while application io is still on the fly */
+ wait_event(mdev->misc_wait, !atomic_read(&mdev->ap_bio_cnt));
+ drbd_free_tl_hash(mdev);
+ }
crypto_free_hash(mdev->cram_hmac_tfm);
mdev->cram_hmac_tfm = NULL;
@@ -3845,6 +3958,9 @@ static void drbd_disconnect(struct drbd_conf *mdev)
i = drbd_release_ee(mdev, &mdev->net_ee);
if (i)
dev_info(DEV, "net_ee not empty, killed %u entries\n", i);
+ i = atomic_read(&mdev->pp_in_use_by_net);
+ if (i)
+ dev_info(DEV, "pp_in_use_by_net = %d, expected 0\n", i);
i = atomic_read(&mdev->pp_in_use);
if (i)
dev_info(DEV, "pp_in_use = %d, expected 0\n", i);
@@ -3888,7 +4004,7 @@ static int drbd_send_handshake(struct drbd_conf *mdev)
p->protocol_min = cpu_to_be32(PRO_VERSION_MIN);
p->protocol_max = cpu_to_be32(PRO_VERSION_MAX);
ok = _drbd_send_cmd( mdev, mdev->data.socket, P_HAND_SHAKE,
- (struct p_header *)p, sizeof(*p), 0 );
+ (struct p_header80 *)p, sizeof(*p), 0 );
mutex_unlock(&mdev->data.mutex);
return ok;
}
@@ -3904,27 +4020,28 @@ static int drbd_do_handshake(struct drbd_conf *mdev)
{
/* ASSERT current == mdev->receiver ... */
struct p_handshake *p = &mdev->data.rbuf.handshake;
- const int expect = sizeof(struct p_handshake)
- -sizeof(struct p_header);
+ const int expect = sizeof(struct p_handshake) - sizeof(struct p_header80);
+ unsigned int length;
+ enum drbd_packets cmd;
int rv;
rv = drbd_send_handshake(mdev);
if (!rv)
return 0;
- rv = drbd_recv_header(mdev, &p->head);
+ rv = drbd_recv_header(mdev, &cmd, &length);
if (!rv)
return 0;
- if (p->head.command != P_HAND_SHAKE) {
+ if (cmd != P_HAND_SHAKE) {
dev_err(DEV, "expected HandShake packet, received: %s (0x%04x)\n",
- cmdname(p->head.command), p->head.command);
+ cmdname(cmd), cmd);
return -1;
}
- if (p->head.length != expect) {
+ if (length != expect) {
dev_err(DEV, "expected HandShake length: %u, received: %u\n",
- expect, p->head.length);
+ expect, length);
return -1;
}
@@ -3982,10 +4099,11 @@ static int drbd_do_auth(struct drbd_conf *mdev)
char *response = NULL;
char *right_response = NULL;
char *peers_ch = NULL;
- struct p_header p;
unsigned int key_len = strlen(mdev->net_conf->shared_secret);
unsigned int resp_size;
struct hash_desc desc;
+ enum drbd_packets cmd;
+ unsigned int length;
int rv;
desc.tfm = mdev->cram_hmac_tfm;
@@ -4005,33 +4123,33 @@ static int drbd_do_auth(struct drbd_conf *mdev)
if (!rv)
goto fail;
- rv = drbd_recv_header(mdev, &p);
+ rv = drbd_recv_header(mdev, &cmd, &length);
if (!rv)
goto fail;
- if (p.command != P_AUTH_CHALLENGE) {
+ if (cmd != P_AUTH_CHALLENGE) {
dev_err(DEV, "expected AuthChallenge packet, received: %s (0x%04x)\n",
- cmdname(p.command), p.command);
+ cmdname(cmd), cmd);
rv = 0;
goto fail;
}
- if (p.length > CHALLENGE_LEN*2) {
+ if (length > CHALLENGE_LEN * 2) {
dev_err(DEV, "expected AuthChallenge payload too big.\n");
rv = -1;
goto fail;
}
- peers_ch = kmalloc(p.length, GFP_NOIO);
+ peers_ch = kmalloc(length, GFP_NOIO);
if (peers_ch == NULL) {
dev_err(DEV, "kmalloc of peers_ch failed\n");
rv = -1;
goto fail;
}
- rv = drbd_recv(mdev, peers_ch, p.length);
+ rv = drbd_recv(mdev, peers_ch, length);
- if (rv != p.length) {
+ if (rv != length) {
dev_err(DEV, "short read AuthChallenge: l=%u\n", rv);
rv = 0;
goto fail;
@@ -4046,7 +4164,7 @@ static int drbd_do_auth(struct drbd_conf *mdev)
}
sg_init_table(&sg, 1);
- sg_set_buf(&sg, peers_ch, p.length);
+ sg_set_buf(&sg, peers_ch, length);
rv = crypto_hash_digest(&desc, &sg, sg.length, response);
if (rv) {
@@ -4059,18 +4177,18 @@ static int drbd_do_auth(struct drbd_conf *mdev)
if (!rv)
goto fail;
- rv = drbd_recv_header(mdev, &p);
+ rv = drbd_recv_header(mdev, &cmd, &length);
if (!rv)
goto fail;
- if (p.command != P_AUTH_RESPONSE) {
+ if (cmd != P_AUTH_RESPONSE) {
dev_err(DEV, "expected AuthResponse packet, received: %s (0x%04x)\n",
- cmdname(p.command), p.command);
+ cmdname(cmd), cmd);
rv = 0;
goto fail;
}
- if (p.length != resp_size) {
+ if (length != resp_size) {
dev_err(DEV, "expected AuthResponse payload of wrong size\n");
rv = 0;
goto fail;
@@ -4155,7 +4273,7 @@ int drbdd_init(struct drbd_thread *thi)
/* ********* acknowledge sender ******** */
-static int got_RqSReply(struct drbd_conf *mdev, struct p_header *h)
+static int got_RqSReply(struct drbd_conf *mdev, struct p_header80 *h)
{
struct p_req_state_reply *p = (struct p_req_state_reply *)h;
@@ -4173,13 +4291,13 @@ static int got_RqSReply(struct drbd_conf *mdev, struct p_header *h)
return TRUE;
}
-static int got_Ping(struct drbd_conf *mdev, struct p_header *h)
+static int got_Ping(struct drbd_conf *mdev, struct p_header80 *h)
{
return drbd_send_ping_ack(mdev);
}
-static int got_PingAck(struct drbd_conf *mdev, struct p_header *h)
+static int got_PingAck(struct drbd_conf *mdev, struct p_header80 *h)
{
/* restore idle timeout */
mdev->meta.socket->sk->sk_rcvtimeo = mdev->net_conf->ping_int*HZ;
@@ -4189,7 +4307,7 @@ static int got_PingAck(struct drbd_conf *mdev, struct p_header *h)
return TRUE;
}
-static int got_IsInSync(struct drbd_conf *mdev, struct p_header *h)
+static int got_IsInSync(struct drbd_conf *mdev, struct p_header80 *h)
{
struct p_block_ack *p = (struct p_block_ack *)h;
sector_t sector = be64_to_cpu(p->sector);
@@ -4199,11 +4317,15 @@ static int got_IsInSync(struct drbd_conf *mdev, struct p_header *h)
update_peer_seq(mdev, be32_to_cpu(p->seq_num));
- drbd_rs_complete_io(mdev, sector);
- drbd_set_in_sync(mdev, sector, blksize);
- /* rs_same_csums is supposed to count in units of BM_BLOCK_SIZE */
- mdev->rs_same_csum += (blksize >> BM_BLOCK_SHIFT);
+ if (get_ldev(mdev)) {
+ drbd_rs_complete_io(mdev, sector);
+ drbd_set_in_sync(mdev, sector, blksize);
+ /* rs_same_csums is supposed to count in units of BM_BLOCK_SIZE */
+ mdev->rs_same_csum += (blksize >> BM_BLOCK_SHIFT);
+ put_ldev(mdev);
+ }
dec_rs_pending(mdev);
+ atomic_add(blksize >> 9, &mdev->rs_sect_in);
return TRUE;
}
@@ -4259,7 +4381,7 @@ static int validate_req_change_req_state(struct drbd_conf *mdev,
return TRUE;
}
-static int got_BlockAck(struct drbd_conf *mdev, struct p_header *h)
+static int got_BlockAck(struct drbd_conf *mdev, struct p_header80 *h)
{
struct p_block_ack *p = (struct p_block_ack *)h;
sector_t sector = be64_to_cpu(p->sector);
@@ -4299,7 +4421,7 @@ static int got_BlockAck(struct drbd_conf *mdev, struct p_header *h)
_ack_id_to_req, __func__ , what);
}
-static int got_NegAck(struct drbd_conf *mdev, struct p_header *h)
+static int got_NegAck(struct drbd_conf *mdev, struct p_header80 *h)
{
struct p_block_ack *p = (struct p_block_ack *)h;
sector_t sector = be64_to_cpu(p->sector);
@@ -4319,7 +4441,7 @@ static int got_NegAck(struct drbd_conf *mdev, struct p_header *h)
_ack_id_to_req, __func__ , neg_acked);
}
-static int got_NegDReply(struct drbd_conf *mdev, struct p_header *h)
+static int got_NegDReply(struct drbd_conf *mdev, struct p_header80 *h)
{
struct p_block_ack *p = (struct p_block_ack *)h;
sector_t sector = be64_to_cpu(p->sector);
@@ -4332,7 +4454,7 @@ static int got_NegDReply(struct drbd_conf *mdev, struct p_header *h)
_ar_id_to_req, __func__ , neg_acked);
}
-static int got_NegRSDReply(struct drbd_conf *mdev, struct p_header *h)
+static int got_NegRSDReply(struct drbd_conf *mdev, struct p_header80 *h)
{
sector_t sector;
int size;
@@ -4354,7 +4476,7 @@ static int got_NegRSDReply(struct drbd_conf *mdev, struct p_header *h)
return TRUE;
}
-static int got_BarrierAck(struct drbd_conf *mdev, struct p_header *h)
+static int got_BarrierAck(struct drbd_conf *mdev, struct p_header80 *h)
{
struct p_barrier_ack *p = (struct p_barrier_ack *)h;
@@ -4363,7 +4485,7 @@ static int got_BarrierAck(struct drbd_conf *mdev, struct p_header *h)
return TRUE;
}
-static int got_OVResult(struct drbd_conf *mdev, struct p_header *h)
+static int got_OVResult(struct drbd_conf *mdev, struct p_header80 *h)
{
struct p_block_ack *p = (struct p_block_ack *)h;
struct drbd_work *w;
@@ -4380,6 +4502,9 @@ static int got_OVResult(struct drbd_conf *mdev, struct p_header *h)
else
ov_oos_print(mdev);
+ if (!get_ldev(mdev))
+ return TRUE;
+
drbd_rs_complete_io(mdev, sector);
dec_rs_pending(mdev);
@@ -4394,18 +4519,18 @@ static int got_OVResult(struct drbd_conf *mdev, struct p_header *h)
drbd_resync_finished(mdev);
}
}
+ put_ldev(mdev);
return TRUE;
}
-static int got_something_to_ignore_m(struct drbd_conf *mdev, struct p_header *h)
+static int got_skip(struct drbd_conf *mdev, struct p_header80 *h)
{
- /* IGNORE */
return TRUE;
}
struct asender_cmd {
size_t pkt_size;
- int (*process)(struct drbd_conf *mdev, struct p_header *h);
+ int (*process)(struct drbd_conf *mdev, struct p_header80 *h);
};
static struct asender_cmd *get_asender_cmd(int cmd)
@@ -4414,8 +4539,8 @@ static struct asender_cmd *get_asender_cmd(int cmd)
/* anything missing from this table is in
* the drbd_cmd_handler (drbd_default_handler) table,
* see the beginning of drbdd() */
- [P_PING] = { sizeof(struct p_header), got_Ping },
- [P_PING_ACK] = { sizeof(struct p_header), got_PingAck },
+ [P_PING] = { sizeof(struct p_header80), got_Ping },
+ [P_PING_ACK] = { sizeof(struct p_header80), got_PingAck },
[P_RECV_ACK] = { sizeof(struct p_block_ack), got_BlockAck },
[P_WRITE_ACK] = { sizeof(struct p_block_ack), got_BlockAck },
[P_RS_WRITE_ACK] = { sizeof(struct p_block_ack), got_BlockAck },
@@ -4427,7 +4552,7 @@ static struct asender_cmd *get_asender_cmd(int cmd)
[P_BARRIER_ACK] = { sizeof(struct p_barrier_ack), got_BarrierAck },
[P_STATE_CHG_REPLY] = { sizeof(struct p_req_state_reply), got_RqSReply },
[P_RS_IS_IN_SYNC] = { sizeof(struct p_block_ack), got_IsInSync },
- [P_DELAY_PROBE] = { sizeof(struct p_delay_probe), got_something_to_ignore_m },
+ [P_DELAY_PROBE] = { sizeof(struct p_delay_probe93), got_skip },
[P_MAX_CMD] = { 0, NULL },
};
if (cmd > P_MAX_CMD || asender_tbl[cmd].process == NULL)
@@ -4438,13 +4563,13 @@ static struct asender_cmd *get_asender_cmd(int cmd)
int drbd_asender(struct drbd_thread *thi)
{
struct drbd_conf *mdev = thi->mdev;
- struct p_header *h = &mdev->meta.rbuf.header;
+ struct p_header80 *h = &mdev->meta.rbuf.header.h80;
struct asender_cmd *cmd = NULL;
int rv, len;
void *buf = h;
int received = 0;
- int expect = sizeof(struct p_header);
+ int expect = sizeof(struct p_header80);
int empty;
sprintf(current->comm, "drbd%d_asender", mdev_to_minor(mdev));
@@ -4468,10 +4593,8 @@ int drbd_asender(struct drbd_thread *thi)
while (1) {
clear_bit(SIGNAL_ASENDER, &mdev->flags);
flush_signals(current);
- if (!drbd_process_done_ee(mdev)) {
- dev_err(DEV, "process_done_ee() = NOT_OK\n");
+ if (!drbd_process_done_ee(mdev))
goto reconnect;
- }
/* to avoid race with newly queued ACKs */
set_bit(SIGNAL_ASENDER, &mdev->flags);
spin_lock_irq(&mdev->req_lock);
@@ -4530,21 +4653,23 @@ int drbd_asender(struct drbd_thread *thi)
if (received == expect && cmd == NULL) {
if (unlikely(h->magic != BE_DRBD_MAGIC)) {
- dev_err(DEV, "magic?? on meta m: 0x%lx c: %d l: %d\n",
- (long)be32_to_cpu(h->magic),
- h->command, h->length);
+ dev_err(DEV, "magic?? on meta m: 0x%08x c: %d l: %d\n",
+ be32_to_cpu(h->magic),
+ be16_to_cpu(h->command),
+ be16_to_cpu(h->length));
goto reconnect;
}
cmd = get_asender_cmd(be16_to_cpu(h->command));
len = be16_to_cpu(h->length);
if (unlikely(cmd == NULL)) {
- dev_err(DEV, "unknown command?? on meta m: 0x%lx c: %d l: %d\n",
- (long)be32_to_cpu(h->magic),
- h->command, h->length);
+ dev_err(DEV, "unknown command?? on meta m: 0x%08x c: %d l: %d\n",
+ be32_to_cpu(h->magic),
+ be16_to_cpu(h->command),
+ be16_to_cpu(h->length));
goto disconnect;
}
expect = cmd->pkt_size;
- ERR_IF(len != expect-sizeof(struct p_header))
+ ERR_IF(len != expect-sizeof(struct p_header80))
goto reconnect;
}
if (received == expect) {
@@ -4554,7 +4679,7 @@ int drbd_asender(struct drbd_thread *thi)
buf = h;
received = 0;
- expect = sizeof(struct p_header);
+ expect = sizeof(struct p_header80);
cmd = NULL;
}
}
@@ -4562,10 +4687,12 @@ int drbd_asender(struct drbd_thread *thi)
if (0) {
reconnect:
drbd_force_state(mdev, NS(conn, C_NETWORK_FAILURE));
+ drbd_md_sync(mdev);
}
if (0) {
disconnect:
drbd_force_state(mdev, NS(conn, C_DISCONNECTING));
+ drbd_md_sync(mdev);
}
clear_bit(SIGNAL_ASENDER, &mdev->flags);
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
index f761d98a4e90..9e91a2545fc8 100644
--- a/drivers/block/drbd/drbd_req.c
+++ b/drivers/block/drbd/drbd_req.c
@@ -59,17 +59,19 @@ static void _drbd_end_io_acct(struct drbd_conf *mdev, struct drbd_request *req)
static void _req_is_done(struct drbd_conf *mdev, struct drbd_request *req, const int rw)
{
const unsigned long s = req->rq_state;
+
+ /* remove it from the transfer log.
+ * well, only if it had been there in the first
+ * place... if it had not (local only or conflicting
+ * and never sent), it should still be "empty" as
+ * initialized in drbd_req_new(), so we can list_del() it
+ * here unconditionally */
+ list_del(&req->tl_requests);
+
/* if it was a write, we may have to set the corresponding
* bit(s) out-of-sync first. If it had a local part, we need to
* release the reference to the activity log. */
if (rw == WRITE) {
- /* remove it from the transfer log.
- * well, only if it had been there in the first
- * place... if it had not (local only or conflicting
- * and never sent), it should still be "empty" as
- * initialized in drbd_req_new(), so we can list_del() it
- * here unconditionally */
- list_del(&req->tl_requests);
/* Set out-of-sync unless both OK flags are set
* (local only or remote failed).
* Other places where we set out-of-sync:
@@ -92,7 +94,8 @@ static void _req_is_done(struct drbd_conf *mdev, struct drbd_request *req, const
*/
if (s & RQ_LOCAL_MASK) {
if (get_ldev_if_state(mdev, D_FAILED)) {
- drbd_al_complete_io(mdev, req->sector);
+ if (s & RQ_IN_ACT_LOG)
+ drbd_al_complete_io(mdev, req->sector);
put_ldev(mdev);
} else if (__ratelimit(&drbd_ratelimit_state)) {
dev_warn(DEV, "Should have called drbd_al_complete_io(, %llu), "
@@ -280,6 +283,14 @@ void _req_may_be_done(struct drbd_request *req, struct bio_and_error *m)
* protocol A or B, barrier ack still pending... */
}
+static void _req_may_be_done_not_susp(struct drbd_request *req, struct bio_and_error *m)
+{
+ struct drbd_conf *mdev = req->mdev;
+
+ if (!is_susp(mdev->state))
+ _req_may_be_done(req, m);
+}
+
/*
* checks whether there was an overlapping request
* or ee already registered.
@@ -380,10 +391,11 @@ out_conflict:
* and it enforces that we have to think in a very structured manner
* about the "events" that may happen to a request during its life time ...
*/
-void __req_mod(struct drbd_request *req, enum drbd_req_event what,
+int __req_mod(struct drbd_request *req, enum drbd_req_event what,
struct bio_and_error *m)
{
struct drbd_conf *mdev = req->mdev;
+ int rv = 0;
m->bio = NULL;
switch (what) {
@@ -420,7 +432,7 @@ void __req_mod(struct drbd_request *req, enum drbd_req_event what,
req->rq_state |= (RQ_LOCAL_COMPLETED|RQ_LOCAL_OK);
req->rq_state &= ~RQ_LOCAL_PENDING;
- _req_may_be_done(req, m);
+ _req_may_be_done_not_susp(req, m);
put_ldev(mdev);
break;
@@ -429,7 +441,7 @@ void __req_mod(struct drbd_request *req, enum drbd_req_event what,
req->rq_state &= ~RQ_LOCAL_PENDING;
__drbd_chk_io_error(mdev, FALSE);
- _req_may_be_done(req, m);
+ _req_may_be_done_not_susp(req, m);
put_ldev(mdev);
break;
@@ -437,7 +449,7 @@ void __req_mod(struct drbd_request *req, enum drbd_req_event what,
/* it is legal to fail READA */
req->rq_state |= RQ_LOCAL_COMPLETED;
req->rq_state &= ~RQ_LOCAL_PENDING;
- _req_may_be_done(req, m);
+ _req_may_be_done_not_susp(req, m);
put_ldev(mdev);
break;
@@ -455,7 +467,7 @@ void __req_mod(struct drbd_request *req, enum drbd_req_event what,
/* no point in retrying if there is no good remote data,
* or we have no connection. */
if (mdev->state.pdsk != D_UP_TO_DATE) {
- _req_may_be_done(req, m);
+ _req_may_be_done_not_susp(req, m);
break;
}
@@ -517,11 +529,9 @@ void __req_mod(struct drbd_request *req, enum drbd_req_event what,
D_ASSERT(test_bit(CREATE_BARRIER, &mdev->flags) == 0);
req->epoch = mdev->newest_tle->br_number;
- list_add_tail(&req->tl_requests,
- &mdev->newest_tle->requests);
/* increment size of current epoch */
- mdev->newest_tle->n_req++;
+ mdev->newest_tle->n_writes++;
/* queue work item to send data */
D_ASSERT(req->rq_state & RQ_NET_PENDING);
@@ -530,7 +540,7 @@ void __req_mod(struct drbd_request *req, enum drbd_req_event what,
drbd_queue_work(&mdev->data.work, &req->w);
/* close the epoch, in case it outgrew the limit */
- if (mdev->newest_tle->n_req >= mdev->net_conf->max_epoch_size)
+ if (mdev->newest_tle->n_writes >= mdev->net_conf->max_epoch_size)
queue_barrier(mdev);
break;
@@ -543,7 +553,7 @@ void __req_mod(struct drbd_request *req, enum drbd_req_event what,
req->rq_state &= ~RQ_NET_QUEUED;
/* if we did it right, tl_clear should be scheduled only after
* this, so this should not be necessary! */
- _req_may_be_done(req, m);
+ _req_may_be_done_not_susp(req, m);
break;
case handed_over_to_network:
@@ -568,7 +578,7 @@ void __req_mod(struct drbd_request *req, enum drbd_req_event what,
* "completed_ok" events came in, once we return from
* _drbd_send_zc_bio (drbd_send_dblock), we have to check
* whether it is done already, and end it. */
- _req_may_be_done(req, m);
+ _req_may_be_done_not_susp(req, m);
break;
case read_retry_remote_canceled:
@@ -584,7 +594,7 @@ void __req_mod(struct drbd_request *req, enum drbd_req_event what,
/* if it is still queued, we may not complete it here.
* it will be canceled soon. */
if (!(req->rq_state & RQ_NET_QUEUED))
- _req_may_be_done(req, m);
+ _req_may_be_done(req, m); /* Allowed while state.susp */
break;
case write_acked_by_peer_and_sis:
@@ -619,7 +629,7 @@ void __req_mod(struct drbd_request *req, enum drbd_req_event what,
D_ASSERT(req->rq_state & RQ_NET_PENDING);
dec_ap_pending(mdev);
req->rq_state &= ~RQ_NET_PENDING;
- _req_may_be_done(req, m);
+ _req_may_be_done_not_susp(req, m);
break;
case neg_acked:
@@ -629,11 +639,50 @@ void __req_mod(struct drbd_request *req, enum drbd_req_event what,
req->rq_state &= ~(RQ_NET_OK|RQ_NET_PENDING);
req->rq_state |= RQ_NET_DONE;
- _req_may_be_done(req, m);
+ _req_may_be_done_not_susp(req, m);
/* else: done by handed_over_to_network */
break;
+ case fail_frozen_disk_io:
+ if (!(req->rq_state & RQ_LOCAL_COMPLETED))
+ break;
+
+ _req_may_be_done(req, m); /* Allowed while state.susp */
+ break;
+
+ case restart_frozen_disk_io:
+ if (!(req->rq_state & RQ_LOCAL_COMPLETED))
+ break;
+
+ req->rq_state &= ~RQ_LOCAL_COMPLETED;
+
+ rv = MR_READ;
+ if (bio_data_dir(req->master_bio) == WRITE)
+ rv = MR_WRITE;
+
+ get_ldev(mdev);
+ req->w.cb = w_restart_disk_io;
+ drbd_queue_work(&mdev->data.work, &req->w);
+ break;
+
+ case resend:
+ /* If RQ_NET_OK is already set, we got a P_WRITE_ACK or P_RECV_ACK
+ before the connection loss (B&C only); only P_BARRIER_ACK was missing.
+ Trowing them out of the TL here by pretending we got a BARRIER_ACK
+ We ensure that the peer was not rebooted */
+ if (!(req->rq_state & RQ_NET_OK)) {
+ if (req->w.cb) {
+ drbd_queue_work(&mdev->data.work, &req->w);
+ rv = req->rq_state & RQ_WRITE ? MR_WRITE : MR_READ;
+ }
+ break;
+ }
+ /* else, fall through to barrier_acked */
+
case barrier_acked:
+ if (!(req->rq_state & RQ_WRITE))
+ break;
+
if (req->rq_state & RQ_NET_PENDING) {
/* barrier came in before all requests have been acked.
* this is bad, because if the connection is lost now,
@@ -643,7 +692,7 @@ void __req_mod(struct drbd_request *req, enum drbd_req_event what,
}
D_ASSERT(req->rq_state & RQ_NET_SENT);
req->rq_state |= RQ_NET_DONE;
- _req_may_be_done(req, m);
+ _req_may_be_done(req, m); /* Allowed while state.susp */
break;
case data_received:
@@ -651,9 +700,11 @@ void __req_mod(struct drbd_request *req, enum drbd_req_event what,
dec_ap_pending(mdev);
req->rq_state &= ~RQ_NET_PENDING;
req->rq_state |= (RQ_NET_OK|RQ_NET_DONE);
- _req_may_be_done(req, m);
+ _req_may_be_done_not_susp(req, m);
break;
};
+
+ return rv;
}
/* we may do a local read if:
@@ -752,14 +803,16 @@ static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio)
* resync extent to finish, and, if necessary, pulls in the target
* extent into the activity log, which involves further disk io because
* of transactional on-disk meta data updates. */
- if (rw == WRITE && local)
+ if (rw == WRITE && local && !test_bit(AL_SUSPENDED, &mdev->flags)) {
+ req->rq_state |= RQ_IN_ACT_LOG;
drbd_al_begin_io(mdev, sector);
+ }
remote = remote && (mdev->state.pdsk == D_UP_TO_DATE ||
(mdev->state.pdsk == D_INCONSISTENT &&
mdev->state.conn >= C_CONNECTED));
- if (!(local || remote) && !mdev->state.susp) {
+ if (!(local || remote) && !is_susp(mdev->state)) {
dev_err(DEV, "IO ERROR: neither local nor remote disk\n");
goto fail_free_complete;
}
@@ -785,7 +838,7 @@ allocate_barrier:
/* GOOD, everything prepared, grab the spin_lock */
spin_lock_irq(&mdev->req_lock);
- if (mdev->state.susp) {
+ if (is_susp(mdev->state)) {
/* If we got suspended, use the retry mechanism of
generic_make_request() to restart processing of this
bio. In the next call to drbd_make_request_26
@@ -867,30 +920,10 @@ allocate_barrier:
/* check this request on the collision detection hash tables.
* if we have a conflict, just complete it here.
* THINK do we want to check reads, too? (I don't think so...) */
- if (rw == WRITE && _req_conflicts(req)) {
- /* this is a conflicting request.
- * even though it may have been only _partially_
- * overlapping with one of the currently pending requests,
- * without even submitting or sending it, we will
- * pretend that it was successfully served right now.
- */
- if (local) {
- bio_put(req->private_bio);
- req->private_bio = NULL;
- drbd_al_complete_io(mdev, req->sector);
- put_ldev(mdev);
- local = 0;
- }
- if (remote)
- dec_ap_pending(mdev);
- _drbd_end_io_acct(mdev, req);
- /* THINK: do we want to fail it (-EIO), or pretend success? */
- bio_endio(req->master_bio, 0);
- req->master_bio = NULL;
- dec_ap_bio(mdev);
- drbd_req_free(req);
- remote = 0;
- }
+ if (rw == WRITE && _req_conflicts(req))
+ goto fail_conflicting;
+
+ list_add_tail(&req->tl_requests, &mdev->newest_tle->requests);
/* NOTE remote first: to get the concurrent write detection right,
* we must register the request before start of local IO. */
@@ -923,6 +956,21 @@ allocate_barrier:
return 0;
+fail_conflicting:
+ /* this is a conflicting request.
+ * even though it may have been only _partially_
+ * overlapping with one of the currently pending requests,
+ * without even submitting or sending it, we will
+ * pretend that it was successfully served right now.
+ */
+ _drbd_end_io_acct(mdev, req);
+ spin_unlock_irq(&mdev->req_lock);
+ if (remote)
+ dec_ap_pending(mdev);
+ /* THINK: do we want to fail it (-EIO), or pretend success?
+ * this pretends success. */
+ err = 0;
+
fail_free_complete:
if (rw == WRITE && local)
drbd_al_complete_io(mdev, sector);
@@ -961,21 +1009,6 @@ static int drbd_fail_request_early(struct drbd_conf *mdev, int is_write)
return 1;
}
- /*
- * Paranoia: we might have been primary, but sync target, or
- * even diskless, then lost the connection.
- * This should have been handled (panic? suspend?) somewhere
- * else. But maybe it was not, so check again here.
- * Caution: as long as we do not have a read/write lock on mdev,
- * to serialize state changes, this is racy, since we may lose
- * the connection *after* we test for the cstate.
- */
- if (mdev->state.disk < D_UP_TO_DATE && mdev->state.pdsk < D_UP_TO_DATE) {
- if (__ratelimit(&drbd_ratelimit_state))
- dev_err(DEV, "Sorry, I have no access to good data anymore.\n");
- return 1;
- }
-
return 0;
}
diff --git a/drivers/block/drbd/drbd_req.h b/drivers/block/drbd/drbd_req.h
index 02d575d24518..181ea0364822 100644
--- a/drivers/block/drbd/drbd_req.h
+++ b/drivers/block/drbd/drbd_req.h
@@ -104,6 +104,9 @@ enum drbd_req_event {
read_ahead_completed_with_error,
write_completed_with_error,
completed_ok,
+ resend,
+ fail_frozen_disk_io,
+ restart_frozen_disk_io,
nothing, /* for tracing only */
};
@@ -183,6 +186,12 @@ enum drbd_req_state_bits {
/* keep this last, its for the RQ_NET_MASK */
__RQ_NET_MAX,
+
+ /* Set when this is a write, clear for a read */
+ __RQ_WRITE,
+
+ /* Should call drbd_al_complete_io() for this request... */
+ __RQ_IN_ACT_LOG,
};
#define RQ_LOCAL_PENDING (1UL << __RQ_LOCAL_PENDING)
@@ -201,6 +210,16 @@ enum drbd_req_state_bits {
/* 0x1f8 */
#define RQ_NET_MASK (((1UL << __RQ_NET_MAX)-1) & ~RQ_LOCAL_MASK)
+#define RQ_WRITE (1UL << __RQ_WRITE)
+#define RQ_IN_ACT_LOG (1UL << __RQ_IN_ACT_LOG)
+
+/* For waking up the frozen transfer log mod_req() has to return if the request
+ should be counted in the epoch object*/
+#define MR_WRITE_SHIFT 0
+#define MR_WRITE (1 << MR_WRITE_SHIFT)
+#define MR_READ_SHIFT 1
+#define MR_READ (1 << MR_READ_SHIFT)
+
/* epoch entries */
static inline
struct hlist_head *ee_hash_slot(struct drbd_conf *mdev, sector_t sector)
@@ -244,30 +263,36 @@ static inline struct drbd_request *_ar_id_to_req(struct drbd_conf *mdev,
return NULL;
}
+static inline void drbd_req_make_private_bio(struct drbd_request *req, struct bio *bio_src)
+{
+ struct bio *bio;
+ bio = bio_clone(bio_src, GFP_NOIO); /* XXX cannot fail?? */
+
+ req->private_bio = bio;
+
+ bio->bi_private = req;
+ bio->bi_end_io = drbd_endio_pri;
+ bio->bi_next = NULL;
+}
+
static inline struct drbd_request *drbd_req_new(struct drbd_conf *mdev,
struct bio *bio_src)
{
- struct bio *bio;
struct drbd_request *req =
mempool_alloc(drbd_request_mempool, GFP_NOIO);
if (likely(req)) {
- bio = bio_clone(bio_src, GFP_NOIO); /* XXX cannot fail?? */
+ drbd_req_make_private_bio(req, bio_src);
- req->rq_state = 0;
+ req->rq_state = bio_data_dir(bio_src) == WRITE ? RQ_WRITE : 0;
req->mdev = mdev;
req->master_bio = bio_src;
- req->private_bio = bio;
req->epoch = 0;
- req->sector = bio->bi_sector;
- req->size = bio->bi_size;
+ req->sector = bio_src->bi_sector;
+ req->size = bio_src->bi_size;
req->start_time = jiffies;
INIT_HLIST_NODE(&req->colision);
INIT_LIST_HEAD(&req->tl_requests);
INIT_LIST_HEAD(&req->w.list);
-
- bio->bi_private = req;
- bio->bi_end_io = drbd_endio_pri;
- bio->bi_next = NULL;
}
return req;
}
@@ -292,36 +317,43 @@ struct bio_and_error {
extern void _req_may_be_done(struct drbd_request *req,
struct bio_and_error *m);
-extern void __req_mod(struct drbd_request *req, enum drbd_req_event what,
+extern int __req_mod(struct drbd_request *req, enum drbd_req_event what,
struct bio_and_error *m);
extern void complete_master_bio(struct drbd_conf *mdev,
struct bio_and_error *m);
/* use this if you don't want to deal with calling complete_master_bio()
* outside the spinlock, e.g. when walking some list on cleanup. */
-static inline void _req_mod(struct drbd_request *req, enum drbd_req_event what)
+static inline int _req_mod(struct drbd_request *req, enum drbd_req_event what)
{
struct drbd_conf *mdev = req->mdev;
struct bio_and_error m;
+ int rv;
/* __req_mod possibly frees req, do not touch req after that! */
- __req_mod(req, what, &m);
+ rv = __req_mod(req, what, &m);
if (m.bio)
complete_master_bio(mdev, &m);
+
+ return rv;
}
/* completion of master bio is outside of spinlock.
* If you need it irqsave, do it your self! */
-static inline void req_mod(struct drbd_request *req,
+static inline int req_mod(struct drbd_request *req,
enum drbd_req_event what)
{
struct drbd_conf *mdev = req->mdev;
struct bio_and_error m;
+ int rv;
+
spin_lock_irq(&mdev->req_lock);
- __req_mod(req, what, &m);
+ rv = __req_mod(req, what, &m);
spin_unlock_irq(&mdev->req_lock);
if (m.bio)
complete_master_bio(mdev, &m);
+
+ return rv;
}
#endif
diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c
index ca4a16cea2d8..108d58015cd1 100644
--- a/drivers/block/drbd/drbd_worker.c
+++ b/drivers/block/drbd/drbd_worker.c
@@ -39,8 +39,6 @@
#include "drbd_int.h"
#include "drbd_req.h"
-#define SLEEP_TIME (HZ/10)
-
static int w_make_ov_request(struct drbd_conf *mdev, struct drbd_work *w, int cancel);
@@ -217,10 +215,8 @@ void drbd_endio_sec(struct bio *bio, int error)
*/
void drbd_endio_pri(struct bio *bio, int error)
{
- unsigned long flags;
struct drbd_request *req = bio->bi_private;
struct drbd_conf *mdev = req->mdev;
- struct bio_and_error m;
enum drbd_req_event what;
int uptodate = bio_flagged(bio, BIO_UPTODATE);
@@ -246,12 +242,7 @@ void drbd_endio_pri(struct bio *bio, int error)
bio_put(req->private_bio);
req->private_bio = ERR_PTR(error);
- spin_lock_irqsave(&mdev->req_lock, flags);
- __req_mod(req, what, &m);
- spin_unlock_irqrestore(&mdev->req_lock, flags);
-
- if (m.bio)
- complete_master_bio(mdev, &m);
+ req_mod(req, what);
}
int w_read_retry_remote(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
@@ -376,54 +367,145 @@ static int read_for_csum(struct drbd_conf *mdev, sector_t sector, int size)
struct drbd_epoch_entry *e;
if (!get_ldev(mdev))
- return 0;
+ return -EIO;
+
+ if (drbd_rs_should_slow_down(mdev))
+ goto defer;
/* GFP_TRY, because if there is no memory available right now, this may
* be rescheduled for later. It is "only" background resync, after all. */
e = drbd_alloc_ee(mdev, DRBD_MAGIC+0xbeef, sector, size, GFP_TRY);
if (!e)
- goto fail;
+ goto defer;
+ e->w.cb = w_e_send_csum;
spin_lock_irq(&mdev->req_lock);
list_add(&e->w.list, &mdev->read_ee);
spin_unlock_irq(&mdev->req_lock);
- e->w.cb = w_e_send_csum;
+ atomic_add(size >> 9, &mdev->rs_sect_ev);
if (drbd_submit_ee(mdev, e, READ, DRBD_FAULT_RS_RD) == 0)
- return 1;
+ return 0;
+
+ /* drbd_submit_ee currently fails for one reason only:
+ * not being able to allocate enough bios.
+ * Is dropping the connection going to help? */
+ spin_lock_irq(&mdev->req_lock);
+ list_del(&e->w.list);
+ spin_unlock_irq(&mdev->req_lock);
drbd_free_ee(mdev, e);
-fail:
+defer:
put_ldev(mdev);
- return 2;
+ return -EAGAIN;
}
void resync_timer_fn(unsigned long data)
{
- unsigned long flags;
struct drbd_conf *mdev = (struct drbd_conf *) data;
int queue;
- spin_lock_irqsave(&mdev->req_lock, flags);
-
- if (likely(!test_and_clear_bit(STOP_SYNC_TIMER, &mdev->flags))) {
- queue = 1;
- if (mdev->state.conn == C_VERIFY_S)
- mdev->resync_work.cb = w_make_ov_request;
- else
- mdev->resync_work.cb = w_make_resync_request;
- } else {
+ queue = 1;
+ switch (mdev->state.conn) {
+ case C_VERIFY_S:
+ mdev->resync_work.cb = w_make_ov_request;
+ break;
+ case C_SYNC_TARGET:
+ mdev->resync_work.cb = w_make_resync_request;
+ break;
+ default:
queue = 0;
mdev->resync_work.cb = w_resync_inactive;
}
- spin_unlock_irqrestore(&mdev->req_lock, flags);
-
/* harmless race: list_empty outside data.work.q_lock */
if (list_empty(&mdev->resync_work.list) && queue)
drbd_queue_work(&mdev->data.work, &mdev->resync_work);
}
+static void fifo_set(struct fifo_buffer *fb, int value)
+{
+ int i;
+
+ for (i = 0; i < fb->size; i++)
+ fb->values[i] = value;
+}
+
+static int fifo_push(struct fifo_buffer *fb, int value)
+{
+ int ov;
+
+ ov = fb->values[fb->head_index];
+ fb->values[fb->head_index++] = value;
+
+ if (fb->head_index >= fb->size)
+ fb->head_index = 0;
+
+ return ov;
+}
+
+static void fifo_add_val(struct fifo_buffer *fb, int value)
+{
+ int i;
+
+ for (i = 0; i < fb->size; i++)
+ fb->values[i] += value;
+}
+
+int drbd_rs_controller(struct drbd_conf *mdev)
+{
+ unsigned int sect_in; /* Number of sectors that came in since the last turn */
+ unsigned int want; /* The number of sectors we want in the proxy */
+ int req_sect; /* Number of sectors to request in this turn */
+ int correction; /* Number of sectors more we need in the proxy*/
+ int cps; /* correction per invocation of drbd_rs_controller() */
+ int steps; /* Number of time steps to plan ahead */
+ int curr_corr;
+ int max_sect;
+
+ sect_in = atomic_xchg(&mdev->rs_sect_in, 0); /* Number of sectors that came in */
+ mdev->rs_in_flight -= sect_in;
+
+ spin_lock(&mdev->peer_seq_lock); /* get an atomic view on mdev->rs_plan_s */
+
+ steps = mdev->rs_plan_s.size; /* (mdev->sync_conf.c_plan_ahead * 10 * SLEEP_TIME) / HZ; */
+
+ if (mdev->rs_in_flight + sect_in == 0) { /* At start of resync */
+ want = ((mdev->sync_conf.rate * 2 * SLEEP_TIME) / HZ) * steps;
+ } else { /* normal path */
+ want = mdev->sync_conf.c_fill_target ? mdev->sync_conf.c_fill_target :
+ sect_in * mdev->sync_conf.c_delay_target * HZ / (SLEEP_TIME * 10);
+ }
+
+ correction = want - mdev->rs_in_flight - mdev->rs_planed;
+
+ /* Plan ahead */
+ cps = correction / steps;
+ fifo_add_val(&mdev->rs_plan_s, cps);
+ mdev->rs_planed += cps * steps;
+
+ /* What we do in this step */
+ curr_corr = fifo_push(&mdev->rs_plan_s, 0);
+ spin_unlock(&mdev->peer_seq_lock);
+ mdev->rs_planed -= curr_corr;
+
+ req_sect = sect_in + curr_corr;
+ if (req_sect < 0)
+ req_sect = 0;
+
+ max_sect = (mdev->sync_conf.c_max_rate * 2 * SLEEP_TIME) / HZ;
+ if (req_sect > max_sect)
+ req_sect = max_sect;
+
+ /*
+ dev_warn(DEV, "si=%u if=%d wa=%u co=%d st=%d cps=%d pl=%d cc=%d rs=%d\n",
+ sect_in, mdev->rs_in_flight, want, correction,
+ steps, cps, mdev->rs_planed, curr_corr, req_sect);
+ */
+
+ return req_sect;
+}
+
int w_make_resync_request(struct drbd_conf *mdev,
struct drbd_work *w, int cancel)
{
@@ -431,8 +513,9 @@ int w_make_resync_request(struct drbd_conf *mdev,
sector_t sector;
const sector_t capacity = drbd_get_capacity(mdev->this_bdev);
int max_segment_size;
- int number, i, size, pe, mx;
+ int number, rollback_i, size, pe, mx;
int align, queued, sndbuf;
+ int i = 0;
if (unlikely(cancel))
return 1;
@@ -446,6 +529,12 @@ int w_make_resync_request(struct drbd_conf *mdev,
dev_err(DEV, "%s in w_make_resync_request\n",
drbd_conn_str(mdev->state.conn));
+ if (mdev->rs_total == 0) {
+ /* empty resync? */
+ drbd_resync_finished(mdev);
+ return 1;
+ }
+
if (!get_ldev(mdev)) {
/* Since we only need to access mdev->rsync a
get_ldev_if_state(mdev,D_FAILED) would be sufficient, but
@@ -458,11 +547,25 @@ int w_make_resync_request(struct drbd_conf *mdev,
/* starting with drbd 8.3.8, we can handle multi-bio EEs,
* if it should be necessary */
- max_segment_size = mdev->agreed_pro_version < 94 ?
- queue_max_segment_size(mdev->rq_queue) : DRBD_MAX_SEGMENT_SIZE;
+ max_segment_size =
+ mdev->agreed_pro_version < 94 ? queue_max_segment_size(mdev->rq_queue) :
+ mdev->agreed_pro_version < 95 ? DRBD_MAX_SIZE_H80_PACKET : DRBD_MAX_SEGMENT_SIZE;
- number = SLEEP_TIME * mdev->sync_conf.rate / ((BM_BLOCK_SIZE / 1024) * HZ);
- pe = atomic_read(&mdev->rs_pending_cnt);
+ if (mdev->rs_plan_s.size) { /* mdev->sync_conf.c_plan_ahead */
+ number = drbd_rs_controller(mdev) >> (BM_BLOCK_SHIFT - 9);
+ mdev->c_sync_rate = number * HZ * (BM_BLOCK_SIZE / 1024) / SLEEP_TIME;
+ } else {
+ mdev->c_sync_rate = mdev->sync_conf.rate;
+ number = SLEEP_TIME * mdev->c_sync_rate / ((BM_BLOCK_SIZE / 1024) * HZ);
+ }
+
+ /* Throttle resync on lower level disk activity, which may also be
+ * caused by application IO on Primary/SyncTarget.
+ * Keep this after the call to drbd_rs_controller, as that assumes
+ * to be called as precisely as possible every SLEEP_TIME,
+ * and would be confused otherwise. */
+ if (drbd_rs_should_slow_down(mdev))
+ goto requeue;
mutex_lock(&mdev->data.mutex);
if (mdev->data.socket)
@@ -476,6 +579,7 @@ int w_make_resync_request(struct drbd_conf *mdev,
mx = number;
/* Limit the number of pending RS requests to no more than the peer's receive buffer */
+ pe = atomic_read(&mdev->rs_pending_cnt);
if ((pe + number) > mx) {
number = mx - pe;
}
@@ -526,6 +630,7 @@ next_sector:
* be prepared for all stripe sizes of software RAIDs.
*/
align = 1;
+ rollback_i = i;
for (;;) {
if (size + BM_BLOCK_SIZE > max_segment_size)
break;
@@ -561,14 +666,19 @@ next_sector:
size = (capacity-sector)<<9;
if (mdev->agreed_pro_version >= 89 && mdev->csums_tfm) {
switch (read_for_csum(mdev, sector, size)) {
- case 0: /* Disk failure*/
+ case -EIO: /* Disk failure */
put_ldev(mdev);
return 0;
- case 2: /* Allocation failed */
+ case -EAGAIN: /* allocation failed, or ldev busy */
drbd_rs_complete_io(mdev, sector);
mdev->bm_resync_fo = BM_SECT_TO_BIT(sector);
+ i = rollback_i;
goto requeue;
- /* case 1: everything ok */
+ case 0:
+ /* everything ok */
+ break;
+ default:
+ BUG();
}
} else {
inc_rs_pending(mdev);
@@ -595,6 +705,7 @@ next_sector:
}
requeue:
+ mdev->rs_in_flight += (i << (BM_BLOCK_SHIFT - 9));
mod_timer(&mdev->resync_timer, jiffies + SLEEP_TIME);
put_ldev(mdev);
return 1;
@@ -670,6 +781,14 @@ static int w_resync_finished(struct drbd_conf *mdev, struct drbd_work *w, int ca
return 1;
}
+static void ping_peer(struct drbd_conf *mdev)
+{
+ clear_bit(GOT_PING_ACK, &mdev->flags);
+ request_ping(mdev);
+ wait_event(mdev->misc_wait,
+ test_bit(GOT_PING_ACK, &mdev->flags) || mdev->state.conn < C_CONNECTED);
+}
+
int drbd_resync_finished(struct drbd_conf *mdev)
{
unsigned long db, dt, dbdt;
@@ -709,6 +828,8 @@ int drbd_resync_finished(struct drbd_conf *mdev)
if (!get_ldev(mdev))
goto out;
+ ping_peer(mdev);
+
spin_lock_irq(&mdev->req_lock);
os = mdev->state;
@@ -801,6 +922,8 @@ out:
mdev->rs_paused = 0;
mdev->ov_start_sector = 0;
+ drbd_md_sync(mdev);
+
if (test_and_clear_bit(WRITE_BM_AFTER_RESYNC, &mdev->flags)) {
dev_warn(DEV, "Writing the whole bitmap, due to failed kmalloc\n");
drbd_queue_bitmap_io(mdev, &drbd_bm_write, NULL, "write from resync_finished");
@@ -817,9 +940,13 @@ static void move_to_net_ee_or_free(struct drbd_conf *mdev, struct drbd_epoch_ent
{
if (drbd_ee_has_active_page(e)) {
/* This might happen if sendpage() has not finished */
+ int i = (e->size + PAGE_SIZE -1) >> PAGE_SHIFT;
+ atomic_add(i, &mdev->pp_in_use_by_net);
+ atomic_sub(i, &mdev->pp_in_use);
spin_lock_irq(&mdev->req_lock);
list_add_tail(&e->w.list, &mdev->net_ee);
spin_unlock_irq(&mdev->req_lock);
+ wake_up(&drbd_pp_wait);
} else
drbd_free_ee(mdev, e);
}
@@ -926,9 +1053,12 @@ int w_e_end_csum_rs_req(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
return 1;
}
- drbd_rs_complete_io(mdev, e->sector);
+ if (get_ldev(mdev)) {
+ drbd_rs_complete_io(mdev, e->sector);
+ put_ldev(mdev);
+ }
- di = (struct digest_info *)(unsigned long)e->block_id;
+ di = e->digest;
if (likely((e->flags & EE_WAS_ERROR) == 0)) {
/* quick hack to try to avoid a race against reconfiguration.
@@ -952,7 +1082,9 @@ int w_e_end_csum_rs_req(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
ok = drbd_send_ack(mdev, P_RS_IS_IN_SYNC, e);
} else {
inc_rs_pending(mdev);
- e->block_id = ID_SYNCER;
+ e->block_id = ID_SYNCER; /* By setting block_id, digest pointer becomes invalid! */
+ e->flags &= ~EE_HAS_DIGEST; /* This e no longer has a digest pointer */
+ kfree(di);
ok = drbd_send_block(mdev, P_RS_DATA_REPLY, e);
}
} else {
@@ -962,9 +1094,6 @@ int w_e_end_csum_rs_req(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
}
dec_unacked(mdev);
-
- kfree(di);
-
move_to_net_ee_or_free(mdev, e);
if (unlikely(!ok))
@@ -1034,9 +1163,12 @@ int w_e_end_ov_reply(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
/* after "cancel", because after drbd_disconnect/drbd_rs_cancel_all
* the resync lru has been cleaned up already */
- drbd_rs_complete_io(mdev, e->sector);
+ if (get_ldev(mdev)) {
+ drbd_rs_complete_io(mdev, e->sector);
+ put_ldev(mdev);
+ }
- di = (struct digest_info *)(unsigned long)e->block_id;
+ di = e->digest;
if (likely((e->flags & EE_WAS_ERROR) == 0)) {
digest_size = crypto_hash_digestsize(mdev->verify_tfm);
@@ -1055,9 +1187,6 @@ int w_e_end_ov_reply(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
}
dec_unacked(mdev);
-
- kfree(di);
-
if (!eq)
drbd_ov_oos_found(mdev, e->sector, e->size);
else
@@ -1108,7 +1237,7 @@ int w_send_barrier(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
* dec_ap_pending will be done in got_BarrierAck
* or (on connection loss) in w_clear_epoch. */
ok = _drbd_send_cmd(mdev, mdev->data.socket, P_BARRIER,
- (struct p_header *)p, sizeof(*p), 0);
+ (struct p_header80 *)p, sizeof(*p), 0);
drbd_put_data_sock(mdev);
return ok;
@@ -1173,6 +1302,24 @@ int w_send_read_req(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
return ok;
}
+int w_restart_disk_io(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
+{
+ struct drbd_request *req = container_of(w, struct drbd_request, w);
+
+ if (bio_data_dir(req->master_bio) == WRITE && req->rq_state & RQ_IN_ACT_LOG)
+ drbd_al_begin_io(mdev, req->sector);
+ /* Calling drbd_al_begin_io() out of the worker might deadlocks
+ theoretically. Practically it can not deadlock, since this is
+ only used when unfreezing IOs. All the extents of the requests
+ that made it into the TL are already active */
+
+ drbd_req_make_private_bio(req, req->master_bio);
+ req->private_bio->bi_bdev = mdev->ldev->backing_bdev;
+ generic_make_request(req->private_bio);
+
+ return 1;
+}
+
static int _drbd_may_sync_now(struct drbd_conf *mdev)
{
struct drbd_conf *odev = mdev;
@@ -1298,14 +1445,6 @@ int drbd_alter_sa(struct drbd_conf *mdev, int na)
return retcode;
}
-static void ping_peer(struct drbd_conf *mdev)
-{
- clear_bit(GOT_PING_ACK, &mdev->flags);
- request_ping(mdev);
- wait_event(mdev->misc_wait,
- test_bit(GOT_PING_ACK, &mdev->flags) || mdev->state.conn < C_CONNECTED);
-}
-
/**
* drbd_start_resync() - Start the resync process
* @mdev: DRBD device.
@@ -1379,13 +1518,21 @@ void drbd_start_resync(struct drbd_conf *mdev, enum drbd_conns side)
r = SS_UNKNOWN_ERROR;
if (r == SS_SUCCESS) {
- mdev->rs_total =
- mdev->rs_mark_left = drbd_bm_total_weight(mdev);
+ unsigned long tw = drbd_bm_total_weight(mdev);
+ unsigned long now = jiffies;
+ int i;
+
mdev->rs_failed = 0;
mdev->rs_paused = 0;
- mdev->rs_start =
- mdev->rs_mark_time = jiffies;
mdev->rs_same_csum = 0;
+ mdev->rs_last_events = 0;
+ mdev->rs_last_sect_ev = 0;
+ mdev->rs_total = tw;
+ mdev->rs_start = now;
+ for (i = 0; i < DRBD_SYNC_MARKS; i++) {
+ mdev->rs_mark_left[i] = tw;
+ mdev->rs_mark_time[i] = now;
+ }
_drbd_pause_after(mdev);
}
write_unlock_irq(&global_state_lock);
@@ -1397,12 +1544,31 @@ void drbd_start_resync(struct drbd_conf *mdev, enum drbd_conns side)
(unsigned long) mdev->rs_total << (BM_BLOCK_SHIFT-10),
(unsigned long) mdev->rs_total);
- if (mdev->rs_total == 0) {
- /* Peer still reachable? Beware of failing before-resync-target handlers! */
- ping_peer(mdev);
+ if (mdev->agreed_pro_version < 95 && mdev->rs_total == 0) {
+ /* This still has a race (about when exactly the peers
+ * detect connection loss) that can lead to a full sync
+ * on next handshake. In 8.3.9 we fixed this with explicit
+ * resync-finished notifications, but the fix
+ * introduces a protocol change. Sleeping for some
+ * time longer than the ping interval + timeout on the
+ * SyncSource, to give the SyncTarget the chance to
+ * detect connection loss, then waiting for a ping
+ * response (implicit in drbd_resync_finished) reduces
+ * the race considerably, but does not solve it. */
+ if (side == C_SYNC_SOURCE)
+ schedule_timeout_interruptible(
+ mdev->net_conf->ping_int * HZ +
+ mdev->net_conf->ping_timeo*HZ/9);
drbd_resync_finished(mdev);
}
+ atomic_set(&mdev->rs_sect_in, 0);
+ atomic_set(&mdev->rs_sect_ev, 0);
+ mdev->rs_in_flight = 0;
+ mdev->rs_planed = 0;
+ spin_lock(&mdev->peer_seq_lock);
+ fifo_set(&mdev->rs_plan_s, 0);
+ spin_unlock(&mdev->peer_seq_lock);
/* ns.conn may already be != mdev->state.conn,
* we may have been paused in between, or become paused until
* the timer triggers.
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index cf04c1b234ed..767107cce982 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -178,7 +178,6 @@ static int print_unex = 1;
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/bio.h>
-#include <linux/smp_lock.h>
#include <linux/string.h>
#include <linux/jiffies.h>
#include <linux/fcntl.h>
@@ -199,6 +198,7 @@ static int print_unex = 1;
* It's been recommended that take about 1/4 of the default speed
* in some more extreme cases.
*/
+static DEFINE_MUTEX(floppy_mutex);
static int slow_floppy;
#include <asm/dma.h>
@@ -258,8 +258,8 @@ static int irqdma_allocated;
#include <linux/completion.h>
static struct request *current_req;
-static struct request_queue *floppy_queue;
static void do_fd_request(struct request_queue *q);
+static int set_next_request(void);
#ifndef fd_get_dma_residue
#define fd_get_dma_residue() get_dma_residue(FLOPPY_DMA)
@@ -413,6 +413,7 @@ static struct gendisk *disks[N_DRIVE];
static struct block_device *opened_bdev[N_DRIVE];
static DEFINE_MUTEX(open_lock);
static struct floppy_raw_cmd *raw_cmd, default_raw_cmd;
+static int fdc_queue;
/*
* This struct defines the different floppy types.
@@ -890,8 +891,8 @@ static void unlock_fdc(void)
del_timer(&fd_timeout);
cont = NULL;
clear_bit(0, &fdc_busy);
- if (current_req || blk_peek_request(floppy_queue))
- do_fd_request(floppy_queue);
+ if (current_req || set_next_request())
+ do_fd_request(current_req->q);
spin_unlock_irqrestore(&floppy_lock, flags);
wake_up(&fdc_wait);
}
@@ -2243,8 +2244,8 @@ static void floppy_end_request(struct request *req, int error)
* logical buffer */
static void request_done(int uptodate)
{
- struct request_queue *q = floppy_queue;
struct request *req = current_req;
+ struct request_queue *q;
unsigned long flags;
int block;
char msg[sizeof("request done ") + sizeof(int) * 3];
@@ -2258,6 +2259,8 @@ static void request_done(int uptodate)
return;
}
+ q = req->q;
+
if (uptodate) {
/* maintain values for invalidation on geometry
* change */
@@ -2811,6 +2814,28 @@ static int make_raw_rw_request(void)
return 2;
}
+/*
+ * Round-robin between our available drives, doing one request from each
+ */
+static int set_next_request(void)
+{
+ struct request_queue *q;
+ int old_pos = fdc_queue;
+
+ do {
+ q = disks[fdc_queue]->queue;
+ if (++fdc_queue == N_DRIVE)
+ fdc_queue = 0;
+ if (q) {
+ current_req = blk_fetch_request(q);
+ if (current_req)
+ break;
+ }
+ } while (fdc_queue != old_pos);
+
+ return current_req != NULL;
+}
+
static void redo_fd_request(void)
{
int drive;
@@ -2822,17 +2847,17 @@ static void redo_fd_request(void)
do_request:
if (!current_req) {
- struct request *req;
+ int pending;
+
+ spin_lock_irq(&floppy_lock);
+ pending = set_next_request();
+ spin_unlock_irq(&floppy_lock);
- spin_lock_irq(floppy_queue->queue_lock);
- req = blk_fetch_request(floppy_queue);
- spin_unlock_irq(floppy_queue->queue_lock);
- if (!req) {
+ if (!pending) {
do_floppy = NULL;
unlock_fdc();
return;
}
- current_req = req;
}
drive = (long)current_req->rq_disk->private_data;
set_fdc(drive);
@@ -3553,9 +3578,9 @@ static int fd_ioctl(struct block_device *bdev, fmode_t mode,
{
int ret;
- lock_kernel();
+ mutex_lock(&floppy_mutex);
ret = fd_locked_ioctl(bdev, mode, cmd, param);
- unlock_kernel();
+ mutex_unlock(&floppy_mutex);
return ret;
}
@@ -3616,7 +3641,7 @@ static int floppy_release(struct gendisk *disk, fmode_t mode)
{
int drive = (long)disk->private_data;
- lock_kernel();
+ mutex_lock(&floppy_mutex);
mutex_lock(&open_lock);
if (UDRS->fd_ref < 0)
UDRS->fd_ref = 0;
@@ -3627,7 +3652,7 @@ static int floppy_release(struct gendisk *disk, fmode_t mode)
if (!UDRS->fd_ref)
opened_bdev[drive] = NULL;
mutex_unlock(&open_lock);
- unlock_kernel();
+ mutex_unlock(&floppy_mutex);
return 0;
}
@@ -3645,7 +3670,7 @@ static int floppy_open(struct block_device *bdev, fmode_t mode)
int res = -EBUSY;
char *tmp;
- lock_kernel();
+ mutex_lock(&floppy_mutex);
mutex_lock(&open_lock);
old_dev = UDRS->fd_device;
if (opened_bdev[drive] && opened_bdev[drive] != bdev)
@@ -3722,7 +3747,7 @@ static int floppy_open(struct block_device *bdev, fmode_t mode)
goto out;
}
mutex_unlock(&open_lock);
- unlock_kernel();
+ mutex_unlock(&floppy_mutex);
return 0;
out:
if (UDRS->fd_ref < 0)
@@ -3733,7 +3758,7 @@ out:
opened_bdev[drive] = NULL;
out2:
mutex_unlock(&open_lock);
- unlock_kernel();
+ mutex_unlock(&floppy_mutex);
return res;
}
@@ -4165,6 +4190,13 @@ static int __init floppy_init(void)
goto out_put_disk;
}
+ disks[dr]->queue = blk_init_queue(do_fd_request, &floppy_lock);
+ if (!disks[dr]->queue) {
+ err = -ENOMEM;
+ goto out_put_disk;
+ }
+
+ blk_queue_max_hw_sectors(disks[dr]->queue, 64);
disks[dr]->major = FLOPPY_MAJOR;
disks[dr]->first_minor = TOMINOR(dr);
disks[dr]->fops = &floppy_fops;
@@ -4183,13 +4215,6 @@ static int __init floppy_init(void)
if (err)
goto out_unreg_blkdev;
- floppy_queue = blk_init_queue(do_fd_request, &floppy_lock);
- if (!floppy_queue) {
- err = -ENOMEM;
- goto out_unreg_driver;
- }
- blk_queue_max_hw_sectors(floppy_queue, 64);
-
blk_register_region(MKDEV(FLOPPY_MAJOR, 0), 256, THIS_MODULE,
floppy_find, NULL, NULL);
@@ -4317,7 +4342,6 @@ static int __init floppy_init(void)
/* to be cleaned up... */
disks[drive]->private_data = (void *)(long)drive;
- disks[drive]->queue = floppy_queue;
disks[drive]->flags |= GENHD_FL_REMOVABLE;
disks[drive]->driverfs_dev = &floppy_device[drive].dev;
add_disk(disks[drive]);
@@ -4333,8 +4357,6 @@ out_flush_work:
floppy_release_irq_and_dma();
out_unreg_region:
blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
- blk_cleanup_queue(floppy_queue);
-out_unreg_driver:
platform_driver_unregister(&floppy_driver);
out_unreg_blkdev:
unregister_blkdev(FLOPPY_MAJOR, "fd");
@@ -4342,6 +4364,8 @@ out_put_disk:
while (dr--) {
del_timer(&motor_off_timer[dr]);
put_disk(disks[dr]);
+ if (disks[dr]->queue)
+ blk_cleanup_queue(disks[dr]->queue);
}
return err;
}
@@ -4550,11 +4574,11 @@ static void __exit floppy_module_exit(void)
platform_device_unregister(&floppy_device[drive]);
}
put_disk(disks[drive]);
+ blk_cleanup_queue(disks[drive]->queue);
}
del_timer_sync(&fd_timeout);
del_timer_sync(&fd_timer);
- blk_cleanup_queue(floppy_queue);
if (atomic_read(&usage_count))
floppy_release_irq_and_dma();
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 91797bbbe702..6c48b3545f84 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -67,16 +67,18 @@
#include <linux/compat.h>
#include <linux/suspend.h>
#include <linux/freezer.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/writeback.h>
#include <linux/buffer_head.h> /* for invalidate_bdev() */
#include <linux/completion.h>
#include <linux/highmem.h>
#include <linux/kthread.h>
#include <linux/splice.h>
+#include <linux/sysfs.h>
#include <asm/uaccess.h>
+static DEFINE_MUTEX(loop_mutex);
static LIST_HEAD(loop_devices);
static DEFINE_MUTEX(loop_devices_mutex);
@@ -477,17 +479,17 @@ static int do_bio_filebacked(struct loop_device *lo, struct bio *bio)
pos = ((loff_t) bio->bi_sector << 9) + lo->lo_offset;
if (bio_rw(bio) == WRITE) {
- bool barrier = !!(bio->bi_rw & REQ_HARDBARRIER);
struct file *file = lo->lo_backing_file;
- if (barrier) {
- if (unlikely(!file->f_op->fsync)) {
- ret = -EOPNOTSUPP;
- goto out;
- }
+ /* REQ_HARDBARRIER is deprecated */
+ if (bio->bi_rw & REQ_HARDBARRIER) {
+ ret = -EOPNOTSUPP;
+ goto out;
+ }
+ if (bio->bi_rw & REQ_FLUSH) {
ret = vfs_fsync(file, 0);
- if (unlikely(ret)) {
+ if (unlikely(ret && ret != -EINVAL)) {
ret = -EIO;
goto out;
}
@@ -495,9 +497,9 @@ static int do_bio_filebacked(struct loop_device *lo, struct bio *bio)
ret = lo_send(lo, bio, pos);
- if (barrier && !ret) {
+ if ((bio->bi_rw & REQ_FUA) && !ret) {
ret = vfs_fsync(file, 0);
- if (unlikely(ret))
+ if (unlikely(ret && ret != -EINVAL))
ret = -EIO;
}
} else
@@ -737,6 +739,103 @@ static inline int is_loop_device(struct file *file)
return i && S_ISBLK(i->i_mode) && MAJOR(i->i_rdev) == LOOP_MAJOR;
}
+/* loop sysfs attributes */
+
+static ssize_t loop_attr_show(struct device *dev, char *page,
+ ssize_t (*callback)(struct loop_device *, char *))
+{
+ struct loop_device *l, *lo = NULL;
+
+ mutex_lock(&loop_devices_mutex);
+ list_for_each_entry(l, &loop_devices, lo_list)
+ if (disk_to_dev(l->lo_disk) == dev) {
+ lo = l;
+ break;
+ }
+ mutex_unlock(&loop_devices_mutex);
+
+ return lo ? callback(lo, page) : -EIO;
+}
+
+#define LOOP_ATTR_RO(_name) \
+static ssize_t loop_attr_##_name##_show(struct loop_device *, char *); \
+static ssize_t loop_attr_do_show_##_name(struct device *d, \
+ struct device_attribute *attr, char *b) \
+{ \
+ return loop_attr_show(d, b, loop_attr_##_name##_show); \
+} \
+static struct device_attribute loop_attr_##_name = \
+ __ATTR(_name, S_IRUGO, loop_attr_do_show_##_name, NULL);
+
+static ssize_t loop_attr_backing_file_show(struct loop_device *lo, char *buf)
+{
+ ssize_t ret;
+ char *p = NULL;
+
+ mutex_lock(&lo->lo_ctl_mutex);
+ if (lo->lo_backing_file)
+ p = d_path(&lo->lo_backing_file->f_path, buf, PAGE_SIZE - 1);
+ mutex_unlock(&lo->lo_ctl_mutex);
+
+ if (IS_ERR_OR_NULL(p))
+ ret = PTR_ERR(p);
+ else {
+ ret = strlen(p);
+ memmove(buf, p, ret);
+ buf[ret++] = '\n';
+ buf[ret] = 0;
+ }
+
+ return ret;
+}
+
+static ssize_t loop_attr_offset_show(struct loop_device *lo, char *buf)
+{
+ return sprintf(buf, "%llu\n", (unsigned long long)lo->lo_offset);
+}
+
+static ssize_t loop_attr_sizelimit_show(struct loop_device *lo, char *buf)
+{
+ return sprintf(buf, "%llu\n", (unsigned long long)lo->lo_sizelimit);
+}
+
+static ssize_t loop_attr_autoclear_show(struct loop_device *lo, char *buf)
+{
+ int autoclear = (lo->lo_flags & LO_FLAGS_AUTOCLEAR);
+
+ return sprintf(buf, "%s\n", autoclear ? "1" : "0");
+}
+
+LOOP_ATTR_RO(backing_file);
+LOOP_ATTR_RO(offset);
+LOOP_ATTR_RO(sizelimit);
+LOOP_ATTR_RO(autoclear);
+
+static struct attribute *loop_attrs[] = {
+ &loop_attr_backing_file.attr,
+ &loop_attr_offset.attr,
+ &loop_attr_sizelimit.attr,
+ &loop_attr_autoclear.attr,
+ NULL,
+};
+
+static struct attribute_group loop_attribute_group = {
+ .name = "loop",
+ .attrs= loop_attrs,
+};
+
+static int loop_sysfs_init(struct loop_device *lo)
+{
+ return sysfs_create_group(&disk_to_dev(lo->lo_disk)->kobj,
+ &loop_attribute_group);
+}
+
+static void loop_sysfs_exit(struct loop_device *lo)
+{
+ sysfs_remove_group(&disk_to_dev(lo->lo_disk)->kobj,
+ &loop_attribute_group);
+}
+
static int loop_set_fd(struct loop_device *lo, fmode_t mode,
struct block_device *bdev, unsigned int arg)
{
@@ -832,10 +931,11 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
lo->lo_queue->unplug_fn = loop_unplug;
if (!(lo_flags & LO_FLAGS_READ_ONLY) && file->f_op->fsync)
- blk_queue_ordered(lo->lo_queue, QUEUE_ORDERED_DRAIN);
+ blk_queue_flush(lo->lo_queue, REQ_FLUSH);
set_capacity(lo->lo_disk, size);
bd_set_size(bdev, size << 9);
+ loop_sysfs_init(lo);
/* let user-space know about the new size */
kobject_uevent(&disk_to_dev(bdev->bd_disk)->kobj, KOBJ_CHANGE);
@@ -854,6 +954,7 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
return 0;
out_clr:
+ loop_sysfs_exit(lo);
lo->lo_thread = NULL;
lo->lo_device = NULL;
lo->lo_backing_file = NULL;
@@ -950,6 +1051,7 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
set_capacity(lo->lo_disk, 0);
if (bdev) {
bd_set_size(bdev, 0);
+ loop_sysfs_exit(lo);
/* let user-space know about this change */
kobject_uevent(&disk_to_dev(bdev->bd_disk)->kobj, KOBJ_CHANGE);
}
@@ -1409,11 +1511,11 @@ static int lo_open(struct block_device *bdev, fmode_t mode)
{
struct loop_device *lo = bdev->bd_disk->private_data;
- lock_kernel();
+ mutex_lock(&loop_mutex);
mutex_lock(&lo->lo_ctl_mutex);
lo->lo_refcnt++;
mutex_unlock(&lo->lo_ctl_mutex);
- unlock_kernel();
+ mutex_unlock(&loop_mutex);
return 0;
}
@@ -1423,7 +1525,7 @@ static int lo_release(struct gendisk *disk, fmode_t mode)
struct loop_device *lo = disk->private_data;
int err;
- lock_kernel();
+ mutex_lock(&loop_mutex);
mutex_lock(&lo->lo_ctl_mutex);
if (--lo->lo_refcnt)
@@ -1448,7 +1550,7 @@ static int lo_release(struct gendisk *disk, fmode_t mode)
out:
mutex_unlock(&lo->lo_ctl_mutex);
out_unlocked:
- lock_kernel();
+ mutex_unlock(&loop_mutex);
return 0;
}
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 0daa422aa281..a32fb41246f8 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -24,7 +24,7 @@
#include <linux/errno.h>
#include <linux/file.h>
#include <linux/ioctl.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/compiler.h>
#include <linux/err.h>
#include <linux/kernel.h>
@@ -53,6 +53,7 @@
#define DBG_BLKDEV 0x0100
#define DBG_RX 0x0200
#define DBG_TX 0x0400
+static DEFINE_MUTEX(nbd_mutex);
static unsigned int debugflags;
#endif /* NDEBUG */
@@ -717,11 +718,11 @@ static int nbd_ioctl(struct block_device *bdev, fmode_t mode,
dprintk(DBG_IOCTL, "%s: nbd_ioctl cmd=%s(0x%x) arg=%lu\n",
lo->disk->disk_name, ioctl_cmd_to_ascii(cmd), cmd, arg);
- lock_kernel();
+ mutex_lock(&nbd_mutex);
mutex_lock(&lo->tx_lock);
error = __nbd_ioctl(bdev, lo, cmd, arg);
mutex_unlock(&lo->tx_lock);
- unlock_kernel();
+ mutex_unlock(&nbd_mutex);
return error;
}
diff --git a/drivers/block/osdblk.c b/drivers/block/osdblk.c
index 2284b4f05c62..87311ebac0db 100644
--- a/drivers/block/osdblk.c
+++ b/drivers/block/osdblk.c
@@ -310,8 +310,7 @@ static void osdblk_rq_fn(struct request_queue *q)
break;
/* filter out block requests we don't understand */
- if (rq->cmd_type != REQ_TYPE_FS &&
- !(rq->cmd_flags & REQ_HARDBARRIER)) {
+ if (rq->cmd_type != REQ_TYPE_FS) {
blk_end_request_all(rq, 0);
continue;
}
@@ -439,7 +438,7 @@ static int osdblk_init_disk(struct osdblk_device *osdev)
blk_queue_stack_limits(q, osd_request_queue(osdev->osd));
blk_queue_prep_rq(q, blk_queue_start_tag);
- blk_queue_ordered(q, QUEUE_ORDERED_DRAIN_FLUSH);
+ blk_queue_flush(q, REQ_FLUSH);
disk->queue = q;
diff --git a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c
index 76f8565e1e8d..62cec6afd7ad 100644
--- a/drivers/block/paride/pcd.c
+++ b/drivers/block/paride/pcd.c
@@ -138,9 +138,10 @@ enum {D_PRT, D_PRO, D_UNI, D_MOD, D_SLV, D_DLY};
#include <linux/cdrom.h>
#include <linux/spinlock.h>
#include <linux/blkdev.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <asm/uaccess.h>
+static DEFINE_MUTEX(pcd_mutex);
static DEFINE_SPINLOCK(pcd_lock);
module_param(verbose, bool, 0644);
@@ -227,9 +228,9 @@ static int pcd_block_open(struct block_device *bdev, fmode_t mode)
struct pcd_unit *cd = bdev->bd_disk->private_data;
int ret;
- lock_kernel();
+ mutex_lock(&pcd_mutex);
ret = cdrom_open(&cd->info, bdev, mode);
- unlock_kernel();
+ mutex_unlock(&pcd_mutex);
return ret;
}
@@ -237,9 +238,9 @@ static int pcd_block_open(struct block_device *bdev, fmode_t mode)
static int pcd_block_release(struct gendisk *disk, fmode_t mode)
{
struct pcd_unit *cd = disk->private_data;
- lock_kernel();
+ mutex_lock(&pcd_mutex);
cdrom_release(&cd->info, mode);
- unlock_kernel();
+ mutex_unlock(&pcd_mutex);
return 0;
}
@@ -249,9 +250,9 @@ static int pcd_block_ioctl(struct block_device *bdev, fmode_t mode,
struct pcd_unit *cd = bdev->bd_disk->private_data;
int ret;
- lock_kernel();
+ mutex_lock(&pcd_mutex);
ret = cdrom_ioctl(&cd->info, bdev, mode, cmd, arg);
- unlock_kernel();
+ mutex_unlock(&pcd_mutex);
return ret;
}
diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
index 985f0d4f1d1e..c0ee1558b9bb 100644
--- a/drivers/block/paride/pd.c
+++ b/drivers/block/paride/pd.c
@@ -153,10 +153,11 @@ enum {D_PRT, D_PRO, D_UNI, D_MOD, D_GEO, D_SBY, D_DLY, D_SLV};
#include <linux/blkdev.h>
#include <linux/blkpg.h>
#include <linux/kernel.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <asm/uaccess.h>
#include <linux/workqueue.h>
+static DEFINE_MUTEX(pd_mutex);
static DEFINE_SPINLOCK(pd_lock);
module_param(verbose, bool, 0);
@@ -736,14 +737,14 @@ static int pd_open(struct block_device *bdev, fmode_t mode)
{
struct pd_unit *disk = bdev->bd_disk->private_data;
- lock_kernel();
+ mutex_lock(&pd_mutex);
disk->access++;
if (disk->removable) {
pd_special_command(disk, pd_media_check);
pd_special_command(disk, pd_door_lock);
}
- unlock_kernel();
+ mutex_unlock(&pd_mutex);
return 0;
}
@@ -771,10 +772,10 @@ static int pd_ioctl(struct block_device *bdev, fmode_t mode,
switch (cmd) {
case CDROMEJECT:
- lock_kernel();
+ mutex_lock(&pd_mutex);
if (disk->access == 1)
pd_special_command(disk, pd_eject);
- unlock_kernel();
+ mutex_unlock(&pd_mutex);
return 0;
default:
return -EINVAL;
@@ -785,10 +786,10 @@ static int pd_release(struct gendisk *p, fmode_t mode)
{
struct pd_unit *disk = p->private_data;
- lock_kernel();
+ mutex_lock(&pd_mutex);
if (!--disk->access && disk->removable)
pd_special_command(disk, pd_door_unlock);
- unlock_kernel();
+ mutex_unlock(&pd_mutex);
return 0;
}
diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c
index 4457b494882a..635f25dd9e10 100644
--- a/drivers/block/paride/pf.c
+++ b/drivers/block/paride/pf.c
@@ -152,9 +152,10 @@ enum {D_PRT, D_PRO, D_UNI, D_MOD, D_SLV, D_LUN, D_DLY};
#include <linux/spinlock.h>
#include <linux/blkdev.h>
#include <linux/blkpg.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <asm/uaccess.h>
+static DEFINE_MUTEX(pf_mutex);
static DEFINE_SPINLOCK(pf_spin_lock);
module_param(verbose, bool, 0644);
@@ -302,7 +303,7 @@ static int pf_open(struct block_device *bdev, fmode_t mode)
struct pf_unit *pf = bdev->bd_disk->private_data;
int ret;
- lock_kernel();
+ mutex_lock(&pf_mutex);
pf_identify(pf);
ret = -ENODEV;
@@ -318,7 +319,7 @@ static int pf_open(struct block_device *bdev, fmode_t mode)
if (pf->removable)
pf_lock(pf, 1);
out:
- unlock_kernel();
+ mutex_unlock(&pf_mutex);
return ret;
}
@@ -349,9 +350,9 @@ static int pf_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, u
if (pf->access != 1)
return -EBUSY;
- lock_kernel();
+ mutex_lock(&pf_mutex);
pf_eject(pf);
- unlock_kernel();
+ mutex_unlock(&pf_mutex);
return 0;
}
@@ -360,9 +361,9 @@ static int pf_release(struct gendisk *disk, fmode_t mode)
{
struct pf_unit *pf = disk->private_data;
- lock_kernel();
+ mutex_lock(&pf_mutex);
if (pf->access <= 0) {
- unlock_kernel();
+ mutex_unlock(&pf_mutex);
return -EINVAL;
}
@@ -371,7 +372,7 @@ static int pf_release(struct gendisk *disk, fmode_t mode)
if (!pf->access && pf->removable)
pf_lock(pf, 0);
- unlock_kernel();
+ mutex_unlock(&pf_mutex);
return 0;
}
diff --git a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c
index c397b3ddba9b..6b9a2000d56a 100644
--- a/drivers/block/paride/pg.c
+++ b/drivers/block/paride/pg.c
@@ -162,7 +162,7 @@ enum {D_PRT, D_PRO, D_UNI, D_MOD, D_SLV, D_DLY};
#include <linux/pg.h>
#include <linux/device.h>
#include <linux/sched.h> /* current, TASK_* */
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/jiffies.h>
#include <asm/uaccess.h>
@@ -193,6 +193,7 @@ module_param_array(drive3, int, NULL, 0);
#define ATAPI_IDENTIFY 0x12
+static DEFINE_MUTEX(pg_mutex);
static int pg_open(struct inode *inode, struct file *file);
static int pg_release(struct inode *inode, struct file *file);
static ssize_t pg_read(struct file *filp, char __user *buf,
@@ -234,6 +235,7 @@ static const struct file_operations pg_fops = {
.write = pg_write,
.open = pg_open,
.release = pg_release,
+ .llseek = noop_llseek,
};
static void pg_init_units(void)
@@ -518,7 +520,7 @@ static int pg_open(struct inode *inode, struct file *file)
struct pg *dev = &devices[unit];
int ret = 0;
- lock_kernel();
+ mutex_lock(&pg_mutex);
if ((unit >= PG_UNITS) || (!dev->present)) {
ret = -ENODEV;
goto out;
@@ -547,7 +549,7 @@ static int pg_open(struct inode *inode, struct file *file)
file->private_data = dev;
out:
- unlock_kernel();
+ mutex_unlock(&pg_mutex);
return ret;
}
diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c
index bc5825fdeaab..7179f79d7468 100644
--- a/drivers/block/paride/pt.c
+++ b/drivers/block/paride/pt.c
@@ -146,7 +146,7 @@ static int (*drives[4])[6] = {&drive0, &drive1, &drive2, &drive3};
#include <linux/mtio.h>
#include <linux/device.h>
#include <linux/sched.h> /* current, TASK_*, schedule_timeout() */
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <asm/uaccess.h>
@@ -189,6 +189,7 @@ module_param_array(drive3, int, NULL, 0);
#define ATAPI_MODE_SENSE 0x1a
#define ATAPI_LOG_SENSE 0x4d
+static DEFINE_MUTEX(pt_mutex);
static int pt_open(struct inode *inode, struct file *file);
static long pt_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
static int pt_release(struct inode *inode, struct file *file);
@@ -239,6 +240,7 @@ static const struct file_operations pt_fops = {
.unlocked_ioctl = pt_ioctl,
.open = pt_open,
.release = pt_release,
+ .llseek = noop_llseek,
};
/* sysfs class support */
@@ -650,9 +652,9 @@ static int pt_open(struct inode *inode, struct file *file)
struct pt_unit *tape = pt + unit;
int err;
- lock_kernel();
+ mutex_lock(&pt_mutex);
if (unit >= PT_UNITS || (!tape->present)) {
- unlock_kernel();
+ mutex_unlock(&pt_mutex);
return -ENODEV;
}
@@ -681,12 +683,12 @@ static int pt_open(struct inode *inode, struct file *file)
}
file->private_data = tape;
- unlock_kernel();
+ mutex_unlock(&pt_mutex);
return 0;
out:
atomic_inc(&tape->available);
- unlock_kernel();
+ mutex_unlock(&pt_mutex);
return err;
}
@@ -704,15 +706,15 @@ static long pt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
switch (mtop.mt_op) {
case MTREW:
- lock_kernel();
+ mutex_lock(&pt_mutex);
pt_rewind(tape);
- unlock_kernel();
+ mutex_unlock(&pt_mutex);
return 0;
case MTWEOF:
- lock_kernel();
+ mutex_lock(&pt_mutex);
pt_write_fm(tape);
- unlock_kernel();
+ mutex_unlock(&pt_mutex);
return 0;
default:
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index 37a2bb595076..19b3568e9326 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -57,7 +57,6 @@
#include <linux/seq_file.h>
#include <linux/miscdevice.h>
#include <linux/freezer.h>
-#include <linux/smp_lock.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <scsi/scsi_cmnd.h>
@@ -86,6 +85,7 @@
#define ZONE(sector, pd) (((sector) + (pd)->offset) & ~((pd)->settings.size - 1))
+static DEFINE_MUTEX(pktcdvd_mutex);
static struct pktcdvd_device *pkt_devs[MAX_WRITERS];
static struct proc_dir_entry *pkt_proc;
static int pktdev_major;
@@ -753,7 +753,6 @@ static int pkt_generic_packet(struct pktcdvd_device *pd, struct packet_command *
rq->timeout = 60*HZ;
rq->cmd_type = REQ_TYPE_BLOCK_PC;
- rq->cmd_flags |= REQ_HARDBARRIER;
if (cgc->quiet)
rq->cmd_flags |= REQ_QUIET;
@@ -2383,7 +2382,7 @@ static int pkt_open(struct block_device *bdev, fmode_t mode)
VPRINTK(DRIVER_NAME": entering open\n");
- lock_kernel();
+ mutex_lock(&pktcdvd_mutex);
mutex_lock(&ctl_mutex);
pd = pkt_find_dev_from_minor(MINOR(bdev->bd_dev));
if (!pd) {
@@ -2411,7 +2410,7 @@ static int pkt_open(struct block_device *bdev, fmode_t mode)
}
mutex_unlock(&ctl_mutex);
- unlock_kernel();
+ mutex_unlock(&pktcdvd_mutex);
return 0;
out_dec:
@@ -2419,7 +2418,7 @@ out_dec:
out:
VPRINTK(DRIVER_NAME": failed open (%d)\n", ret);
mutex_unlock(&ctl_mutex);
- unlock_kernel();
+ mutex_unlock(&pktcdvd_mutex);
return ret;
}
@@ -2428,7 +2427,7 @@ static int pkt_close(struct gendisk *disk, fmode_t mode)
struct pktcdvd_device *pd = disk->private_data;
int ret = 0;
- lock_kernel();
+ mutex_lock(&pktcdvd_mutex);
mutex_lock(&ctl_mutex);
pd->refcnt--;
BUG_ON(pd->refcnt < 0);
@@ -2437,7 +2436,7 @@ static int pkt_close(struct gendisk *disk, fmode_t mode)
pkt_release_dev(pd, flush);
}
mutex_unlock(&ctl_mutex);
- unlock_kernel();
+ mutex_unlock(&pktcdvd_mutex);
return ret;
}
@@ -2773,7 +2772,7 @@ static int pkt_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
VPRINTK("pkt_ioctl: cmd %x, dev %d:%d\n", cmd,
MAJOR(bdev->bd_dev), MINOR(bdev->bd_dev));
- lock_kernel();
+ mutex_lock(&pktcdvd_mutex);
switch (cmd) {
case CDROMEJECT:
/*
@@ -2798,7 +2797,7 @@ static int pkt_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
VPRINTK(DRIVER_NAME": Unknown ioctl for %s (%x)\n", pd->name, cmd);
ret = -ENOTTY;
}
- unlock_kernel();
+ mutex_unlock(&pktcdvd_mutex);
return ret;
}
@@ -3046,6 +3045,7 @@ static const struct file_operations pkt_ctl_fops = {
.compat_ioctl = pkt_ctl_compat_ioctl,
#endif
.owner = THIS_MODULE,
+ .llseek = no_llseek,
};
static struct miscdevice pkt_misc = {
diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c
index e9da874d0419..8e1ce2e2916a 100644
--- a/drivers/block/ps3disk.c
+++ b/drivers/block/ps3disk.c
@@ -113,7 +113,7 @@ static void ps3disk_scatter_gather(struct ps3_storage_device *dev,
memcpy(buf, dev->bounce_buf+offset, size);
offset += size;
flush_kernel_dcache_page(bvec->bv_page);
- bvec_kunmap_irq(bvec, &flags);
+ bvec_kunmap_irq(buf, &flags);
i++;
}
}
@@ -468,7 +468,7 @@ static int __devinit ps3disk_probe(struct ps3_system_bus_device *_dev)
blk_queue_dma_alignment(queue, dev->blk_size-1);
blk_queue_logical_block_size(queue, dev->blk_size);
- blk_queue_ordered(queue, QUEUE_ORDERED_DRAIN_FLUSH);
+ blk_queue_flush(queue, REQ_FLUSH);
blk_queue_max_segments(queue, -1);
blk_queue_max_segment_size(queue, dev->bounce_size);
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
new file mode 100644
index 000000000000..6ec9d53806c5
--- /dev/null
+++ b/drivers/block/rbd.c
@@ -0,0 +1,1841 @@
+/*
+ rbd.c -- Export ceph rados objects as a Linux block device
+
+
+ based on drivers/block/osdblk.c:
+
+ Copyright 2009 Red Hat, 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.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+
+ Instructions for use
+ --------------------
+
+ 1) Map a Linux block device to an existing rbd image.
+
+ Usage: <mon ip addr> <options> <pool name> <rbd image name> [snap name]
+
+ $ echo "192.168.0.1 name=admin rbd foo" > /sys/class/rbd/add
+
+ The snapshot name can be "-" or omitted to map the image read/write.
+
+ 2) List all active blkdev<->object mappings.
+
+ In this example, we have performed step #1 twice, creating two blkdevs,
+ mapped to two separate rados objects in the rados rbd pool
+
+ $ cat /sys/class/rbd/list
+ #id major client_name pool name snap KB
+ 0 254 client4143 rbd foo - 1024000
+
+ The columns, in order, are:
+ - blkdev unique id
+ - blkdev assigned major
+ - rados client id
+ - rados pool name
+ - rados block device name
+ - mapped snapshot ("-" if none)
+ - device size in KB
+
+
+ 3) Create a snapshot.
+
+ Usage: <blkdev id> <snapname>
+
+ $ echo "0 mysnap" > /sys/class/rbd/snap_create
+
+
+ 4) Listing a snapshot.
+
+ $ cat /sys/class/rbd/snaps_list
+ #id snap KB
+ 0 - 1024000 (*)
+ 0 foo 1024000
+
+ The columns, in order, are:
+ - blkdev unique id
+ - snapshot name, '-' means none (active read/write version)
+ - size of device at time of snapshot
+ - the (*) indicates this is the active version
+
+ 5) Rollback to snapshot.
+
+ Usage: <blkdev id> <snapname>
+
+ $ echo "0 mysnap" > /sys/class/rbd/snap_rollback
+
+
+ 6) Mapping an image using snapshot.
+
+ A snapshot mapping is read-only. This is being done by passing
+ snap=<snapname> to the options when adding a device.
+
+ $ echo "192.168.0.1 name=admin,snap=mysnap rbd foo" > /sys/class/rbd/add
+
+
+ 7) Remove an active blkdev<->rbd image mapping.
+
+ In this example, we remove the mapping with blkdev unique id 1.
+
+ $ echo 1 > /sys/class/rbd/remove
+
+
+ NOTE: The actual creation and deletion of rados objects is outside the scope
+ of this driver.
+
+ */
+
+#include <linux/ceph/libceph.h>
+#include <linux/ceph/osd_client.h>
+#include <linux/ceph/mon_client.h>
+#include <linux/ceph/decode.h>
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/blkdev.h>
+
+#include "rbd_types.h"
+
+#define DRV_NAME "rbd"
+#define DRV_NAME_LONG "rbd (rados block device)"
+
+#define RBD_MINORS_PER_MAJOR 256 /* max minors per blkdev */
+
+#define RBD_MAX_MD_NAME_LEN (96 + sizeof(RBD_SUFFIX))
+#define RBD_MAX_POOL_NAME_LEN 64
+#define RBD_MAX_SNAP_NAME_LEN 32
+#define RBD_MAX_OPT_LEN 1024
+
+#define RBD_SNAP_HEAD_NAME "-"
+
+#define DEV_NAME_LEN 32
+
+/*
+ * block device image metadata (in-memory version)
+ */
+struct rbd_image_header {
+ u64 image_size;
+ char block_name[32];
+ __u8 obj_order;
+ __u8 crypt_type;
+ __u8 comp_type;
+ struct rw_semaphore snap_rwsem;
+ struct ceph_snap_context *snapc;
+ size_t snap_names_len;
+ u64 snap_seq;
+ u32 total_snaps;
+
+ char *snap_names;
+ u64 *snap_sizes;
+};
+
+/*
+ * an instance of the client. multiple devices may share a client.
+ */
+struct rbd_client {
+ struct ceph_client *client;
+ struct kref kref;
+ struct list_head node;
+};
+
+/*
+ * a single io request
+ */
+struct rbd_request {
+ struct request *rq; /* blk layer request */
+ struct bio *bio; /* cloned bio */
+ struct page **pages; /* list of used pages */
+ u64 len;
+};
+
+/*
+ * a single device
+ */
+struct rbd_device {
+ int id; /* blkdev unique id */
+
+ int major; /* blkdev assigned major */
+ struct gendisk *disk; /* blkdev's gendisk and rq */
+ struct request_queue *q;
+
+ struct ceph_client *client;
+ struct rbd_client *rbd_client;
+
+ char name[DEV_NAME_LEN]; /* blkdev name, e.g. rbd3 */
+
+ spinlock_t lock; /* queue lock */
+
+ struct rbd_image_header header;
+ char obj[RBD_MAX_OBJ_NAME_LEN]; /* rbd image name */
+ int obj_len;
+ char obj_md_name[RBD_MAX_MD_NAME_LEN]; /* hdr nm. */
+ char pool_name[RBD_MAX_POOL_NAME_LEN];
+ int poolid;
+
+ char snap_name[RBD_MAX_SNAP_NAME_LEN];
+ u32 cur_snap; /* index+1 of current snapshot within snap context
+ 0 - for the head */
+ int read_only;
+
+ struct list_head node;
+};
+
+static spinlock_t node_lock; /* protects client get/put */
+
+static struct class *class_rbd; /* /sys/class/rbd */
+static DEFINE_MUTEX(ctl_mutex); /* Serialize open/close/setup/teardown */
+static LIST_HEAD(rbd_dev_list); /* devices */
+static LIST_HEAD(rbd_client_list); /* clients */
+
+
+static int rbd_open(struct block_device *bdev, fmode_t mode)
+{
+ struct gendisk *disk = bdev->bd_disk;
+ struct rbd_device *rbd_dev = disk->private_data;
+
+ set_device_ro(bdev, rbd_dev->read_only);
+
+ if ((mode & FMODE_WRITE) && rbd_dev->read_only)
+ return -EROFS;
+
+ return 0;
+}
+
+static const struct block_device_operations rbd_bd_ops = {
+ .owner = THIS_MODULE,
+ .open = rbd_open,
+};
+
+/*
+ * Initialize an rbd client instance.
+ * We own *opt.
+ */
+static struct rbd_client *rbd_client_create(struct ceph_options *opt)
+{
+ struct rbd_client *rbdc;
+ int ret = -ENOMEM;
+
+ dout("rbd_client_create\n");
+ rbdc = kmalloc(sizeof(struct rbd_client), GFP_KERNEL);
+ if (!rbdc)
+ goto out_opt;
+
+ kref_init(&rbdc->kref);
+ INIT_LIST_HEAD(&rbdc->node);
+
+ rbdc->client = ceph_create_client(opt, rbdc);
+ if (IS_ERR(rbdc->client))
+ goto out_rbdc;
+ opt = NULL; /* Now rbdc->client is responsible for opt */
+
+ ret = ceph_open_session(rbdc->client);
+ if (ret < 0)
+ goto out_err;
+
+ spin_lock(&node_lock);
+ list_add_tail(&rbdc->node, &rbd_client_list);
+ spin_unlock(&node_lock);
+
+ dout("rbd_client_create created %p\n", rbdc);
+ return rbdc;
+
+out_err:
+ ceph_destroy_client(rbdc->client);
+out_rbdc:
+ kfree(rbdc);
+out_opt:
+ if (opt)
+ ceph_destroy_options(opt);
+ return ERR_PTR(ret);
+}
+
+/*
+ * Find a ceph client with specific addr and configuration.
+ */
+static struct rbd_client *__rbd_client_find(struct ceph_options *opt)
+{
+ struct rbd_client *client_node;
+
+ if (opt->flags & CEPH_OPT_NOSHARE)
+ return NULL;
+
+ list_for_each_entry(client_node, &rbd_client_list, node)
+ if (ceph_compare_options(opt, client_node->client) == 0)
+ return client_node;
+ return NULL;
+}
+
+/*
+ * Get a ceph client with specific addr and configuration, if one does
+ * not exist create it.
+ */
+static int rbd_get_client(struct rbd_device *rbd_dev, const char *mon_addr,
+ char *options)
+{
+ struct rbd_client *rbdc;
+ struct ceph_options *opt;
+ int ret;
+
+ ret = ceph_parse_options(&opt, options, mon_addr,
+ mon_addr + strlen(mon_addr), NULL, NULL);
+ if (ret < 0)
+ return ret;
+
+ spin_lock(&node_lock);
+ rbdc = __rbd_client_find(opt);
+ if (rbdc) {
+ ceph_destroy_options(opt);
+
+ /* using an existing client */
+ kref_get(&rbdc->kref);
+ rbd_dev->rbd_client = rbdc;
+ rbd_dev->client = rbdc->client;
+ spin_unlock(&node_lock);
+ return 0;
+ }
+ spin_unlock(&node_lock);
+
+ rbdc = rbd_client_create(opt);
+ if (IS_ERR(rbdc))
+ return PTR_ERR(rbdc);
+
+ rbd_dev->rbd_client = rbdc;
+ rbd_dev->client = rbdc->client;
+ return 0;
+}
+
+/*
+ * Destroy ceph client
+ */
+static void rbd_client_release(struct kref *kref)
+{
+ struct rbd_client *rbdc = container_of(kref, struct rbd_client, kref);
+
+ dout("rbd_release_client %p\n", rbdc);
+ spin_lock(&node_lock);
+ list_del(&rbdc->node);
+ spin_unlock(&node_lock);
+
+ ceph_destroy_client(rbdc->client);
+ kfree(rbdc);
+}
+
+/*
+ * Drop reference to ceph client node. If it's not referenced anymore, release
+ * it.
+ */
+static void rbd_put_client(struct rbd_device *rbd_dev)
+{
+ kref_put(&rbd_dev->rbd_client->kref, rbd_client_release);
+ rbd_dev->rbd_client = NULL;
+ rbd_dev->client = NULL;
+}
+
+
+/*
+ * Create a new header structure, translate header format from the on-disk
+ * header.
+ */
+static int rbd_header_from_disk(struct rbd_image_header *header,
+ struct rbd_image_header_ondisk *ondisk,
+ int allocated_snaps,
+ gfp_t gfp_flags)
+{
+ int i;
+ u32 snap_count = le32_to_cpu(ondisk->snap_count);
+ int ret = -ENOMEM;
+
+ init_rwsem(&header->snap_rwsem);
+
+ header->snap_names_len = le64_to_cpu(ondisk->snap_names_len);
+ header->snapc = kmalloc(sizeof(struct ceph_snap_context) +
+ snap_count *
+ sizeof(struct rbd_image_snap_ondisk),
+ gfp_flags);
+ if (!header->snapc)
+ return -ENOMEM;
+ if (snap_count) {
+ header->snap_names = kmalloc(header->snap_names_len,
+ GFP_KERNEL);
+ if (!header->snap_names)
+ goto err_snapc;
+ header->snap_sizes = kmalloc(snap_count * sizeof(u64),
+ GFP_KERNEL);
+ if (!header->snap_sizes)
+ goto err_names;
+ } else {
+ header->snap_names = NULL;
+ header->snap_sizes = NULL;
+ }
+ memcpy(header->block_name, ondisk->block_name,
+ sizeof(ondisk->block_name));
+
+ header->image_size = le64_to_cpu(ondisk->image_size);
+ header->obj_order = ondisk->options.order;
+ header->crypt_type = ondisk->options.crypt_type;
+ header->comp_type = ondisk->options.comp_type;
+
+ atomic_set(&header->snapc->nref, 1);
+ header->snap_seq = le64_to_cpu(ondisk->snap_seq);
+ header->snapc->num_snaps = snap_count;
+ header->total_snaps = snap_count;
+
+ if (snap_count &&
+ allocated_snaps == snap_count) {
+ for (i = 0; i < snap_count; i++) {
+ header->snapc->snaps[i] =
+ le64_to_cpu(ondisk->snaps[i].id);
+ header->snap_sizes[i] =
+ le64_to_cpu(ondisk->snaps[i].image_size);
+ }
+
+ /* copy snapshot names */
+ memcpy(header->snap_names, &ondisk->snaps[i],
+ header->snap_names_len);
+ }
+
+ return 0;
+
+err_names:
+ kfree(header->snap_names);
+err_snapc:
+ kfree(header->snapc);
+ return ret;
+}
+
+static int snap_index(struct rbd_image_header *header, int snap_num)
+{
+ return header->total_snaps - snap_num;
+}
+
+static u64 cur_snap_id(struct rbd_device *rbd_dev)
+{
+ struct rbd_image_header *header = &rbd_dev->header;
+
+ if (!rbd_dev->cur_snap)
+ return 0;
+
+ return header->snapc->snaps[snap_index(header, rbd_dev->cur_snap)];
+}
+
+static int snap_by_name(struct rbd_image_header *header, const char *snap_name,
+ u64 *seq, u64 *size)
+{
+ int i;
+ char *p = header->snap_names;
+
+ for (i = 0; i < header->total_snaps; i++, p += strlen(p) + 1) {
+ if (strcmp(snap_name, p) == 0)
+ break;
+ }
+ if (i == header->total_snaps)
+ return -ENOENT;
+ if (seq)
+ *seq = header->snapc->snaps[i];
+
+ if (size)
+ *size = header->snap_sizes[i];
+
+ return i;
+}
+
+static int rbd_header_set_snap(struct rbd_device *dev,
+ const char *snap_name,
+ u64 *size)
+{
+ struct rbd_image_header *header = &dev->header;
+ struct ceph_snap_context *snapc = header->snapc;
+ int ret = -ENOENT;
+
+ down_write(&header->snap_rwsem);
+
+ if (!snap_name ||
+ !*snap_name ||
+ strcmp(snap_name, "-") == 0 ||
+ strcmp(snap_name, RBD_SNAP_HEAD_NAME) == 0) {
+ if (header->total_snaps)
+ snapc->seq = header->snap_seq;
+ else
+ snapc->seq = 0;
+ dev->cur_snap = 0;
+ dev->read_only = 0;
+ if (size)
+ *size = header->image_size;
+ } else {
+ ret = snap_by_name(header, snap_name, &snapc->seq, size);
+ if (ret < 0)
+ goto done;
+
+ dev->cur_snap = header->total_snaps - ret;
+ dev->read_only = 1;
+ }
+
+ ret = 0;
+done:
+ up_write(&header->snap_rwsem);
+ return ret;
+}
+
+static void rbd_header_free(struct rbd_image_header *header)
+{
+ kfree(header->snapc);
+ kfree(header->snap_names);
+ kfree(header->snap_sizes);
+}
+
+/*
+ * get the actual striped segment name, offset and length
+ */
+static u64 rbd_get_segment(struct rbd_image_header *header,
+ const char *block_name,
+ u64 ofs, u64 len,
+ char *seg_name, u64 *segofs)
+{
+ u64 seg = ofs >> header->obj_order;
+
+ if (seg_name)
+ snprintf(seg_name, RBD_MAX_SEG_NAME_LEN,
+ "%s.%012llx", block_name, seg);
+
+ ofs = ofs & ((1 << header->obj_order) - 1);
+ len = min_t(u64, len, (1 << header->obj_order) - ofs);
+
+ if (segofs)
+ *segofs = ofs;
+
+ return len;
+}
+
+/*
+ * bio helpers
+ */
+
+static void bio_chain_put(struct bio *chain)
+{
+ struct bio *tmp;
+
+ while (chain) {
+ tmp = chain;
+ chain = chain->bi_next;
+ bio_put(tmp);
+ }
+}
+
+/*
+ * zeros a bio chain, starting at specific offset
+ */
+static void zero_bio_chain(struct bio *chain, int start_ofs)
+{
+ struct bio_vec *bv;
+ unsigned long flags;
+ void *buf;
+ int i;
+ int pos = 0;
+
+ while (chain) {
+ bio_for_each_segment(bv, chain, i) {
+ if (pos + bv->bv_len > start_ofs) {
+ int remainder = max(start_ofs - pos, 0);
+ buf = bvec_kmap_irq(bv, &flags);
+ memset(buf + remainder, 0,
+ bv->bv_len - remainder);
+ bvec_kunmap_irq(buf, &flags);
+ }
+ pos += bv->bv_len;
+ }
+
+ chain = chain->bi_next;
+ }
+}
+
+/*
+ * bio_chain_clone - clone a chain of bios up to a certain length.
+ * might return a bio_pair that will need to be released.
+ */
+static struct bio *bio_chain_clone(struct bio **old, struct bio **next,
+ struct bio_pair **bp,
+ int len, gfp_t gfpmask)
+{
+ struct bio *tmp, *old_chain = *old, *new_chain = NULL, *tail = NULL;
+ int total = 0;
+
+ if (*bp) {
+ bio_pair_release(*bp);
+ *bp = NULL;
+ }
+
+ while (old_chain && (total < len)) {
+ tmp = bio_kmalloc(gfpmask, old_chain->bi_max_vecs);
+ if (!tmp)
+ goto err_out;
+
+ if (total + old_chain->bi_size > len) {
+ struct bio_pair *bp;
+
+ /*
+ * this split can only happen with a single paged bio,
+ * split_bio will BUG_ON if this is not the case
+ */
+ dout("bio_chain_clone split! total=%d remaining=%d"
+ "bi_size=%d\n",
+ (int)total, (int)len-total,
+ (int)old_chain->bi_size);
+
+ /* split the bio. We'll release it either in the next
+ call, or it will have to be released outside */
+ bp = bio_split(old_chain, (len - total) / 512ULL);
+ if (!bp)
+ goto err_out;
+
+ __bio_clone(tmp, &bp->bio1);
+
+ *next = &bp->bio2;
+ } else {
+ __bio_clone(tmp, old_chain);
+ *next = old_chain->bi_next;
+ }
+
+ tmp->bi_bdev = NULL;
+ gfpmask &= ~__GFP_WAIT;
+ tmp->bi_next = NULL;
+
+ if (!new_chain) {
+ new_chain = tail = tmp;
+ } else {
+ tail->bi_next = tmp;
+ tail = tmp;
+ }
+ old_chain = old_chain->bi_next;
+
+ total += tmp->bi_size;
+ }
+
+ BUG_ON(total < len);
+
+ if (tail)
+ tail->bi_next = NULL;
+
+ *old = old_chain;
+
+ return new_chain;
+
+err_out:
+ dout("bio_chain_clone with err\n");
+ bio_chain_put(new_chain);
+ return NULL;
+}
+
+/*
+ * helpers for osd request op vectors.
+ */
+static int rbd_create_rw_ops(struct ceph_osd_req_op **ops,
+ int num_ops,
+ int opcode,
+ u32 payload_len)
+{
+ *ops = kzalloc(sizeof(struct ceph_osd_req_op) * (num_ops + 1),
+ GFP_NOIO);
+ if (!*ops)
+ return -ENOMEM;
+ (*ops)[0].op = opcode;
+ /*
+ * op extent offset and length will be set later on
+ * in calc_raw_layout()
+ */
+ (*ops)[0].payload_len = payload_len;
+ return 0;
+}
+
+static void rbd_destroy_ops(struct ceph_osd_req_op *ops)
+{
+ kfree(ops);
+}
+
+/*
+ * Send ceph osd request
+ */
+static int rbd_do_request(struct request *rq,
+ struct rbd_device *dev,
+ struct ceph_snap_context *snapc,
+ u64 snapid,
+ const char *obj, u64 ofs, u64 len,
+ struct bio *bio,
+ struct page **pages,
+ int num_pages,
+ int flags,
+ struct ceph_osd_req_op *ops,
+ int num_reply,
+ void (*rbd_cb)(struct ceph_osd_request *req,
+ struct ceph_msg *msg))
+{
+ struct ceph_osd_request *req;
+ struct ceph_file_layout *layout;
+ int ret;
+ u64 bno;
+ struct timespec mtime = CURRENT_TIME;
+ struct rbd_request *req_data;
+ struct ceph_osd_request_head *reqhead;
+ struct rbd_image_header *header = &dev->header;
+
+ ret = -ENOMEM;
+ req_data = kzalloc(sizeof(*req_data), GFP_NOIO);
+ if (!req_data)
+ goto done;
+
+ dout("rbd_do_request len=%lld ofs=%lld\n", len, ofs);
+
+ down_read(&header->snap_rwsem);
+
+ req = ceph_osdc_alloc_request(&dev->client->osdc, flags,
+ snapc,
+ ops,
+ false,
+ GFP_NOIO, pages, bio);
+ if (IS_ERR(req)) {
+ up_read(&header->snap_rwsem);
+ ret = PTR_ERR(req);
+ goto done_pages;
+ }
+
+ req->r_callback = rbd_cb;
+
+ req_data->rq = rq;
+ req_data->bio = bio;
+ req_data->pages = pages;
+ req_data->len = len;
+
+ req->r_priv = req_data;
+
+ reqhead = req->r_request->front.iov_base;
+ reqhead->snapid = cpu_to_le64(CEPH_NOSNAP);
+
+ strncpy(req->r_oid, obj, sizeof(req->r_oid));
+ req->r_oid_len = strlen(req->r_oid);
+
+ layout = &req->r_file_layout;
+ memset(layout, 0, sizeof(*layout));
+ layout->fl_stripe_unit = cpu_to_le32(1 << RBD_MAX_OBJ_ORDER);
+ layout->fl_stripe_count = cpu_to_le32(1);
+ layout->fl_object_size = cpu_to_le32(1 << RBD_MAX_OBJ_ORDER);
+ layout->fl_pg_preferred = cpu_to_le32(-1);
+ layout->fl_pg_pool = cpu_to_le32(dev->poolid);
+ ceph_calc_raw_layout(&dev->client->osdc, layout, snapid,
+ ofs, &len, &bno, req, ops);
+
+ ceph_osdc_build_request(req, ofs, &len,
+ ops,
+ snapc,
+ &mtime,
+ req->r_oid, req->r_oid_len);
+ up_read(&header->snap_rwsem);
+
+ ret = ceph_osdc_start_request(&dev->client->osdc, req, false);
+ if (ret < 0)
+ goto done_err;
+
+ if (!rbd_cb) {
+ ret = ceph_osdc_wait_request(&dev->client->osdc, req);
+ ceph_osdc_put_request(req);
+ }
+ return ret;
+
+done_err:
+ bio_chain_put(req_data->bio);
+ ceph_osdc_put_request(req);
+done_pages:
+ kfree(req_data);
+done:
+ if (rq)
+ blk_end_request(rq, ret, len);
+ return ret;
+}
+
+/*
+ * Ceph osd op callback
+ */
+static void rbd_req_cb(struct ceph_osd_request *req, struct ceph_msg *msg)
+{
+ struct rbd_request *req_data = req->r_priv;
+ struct ceph_osd_reply_head *replyhead;
+ struct ceph_osd_op *op;
+ __s32 rc;
+ u64 bytes;
+ int read_op;
+
+ /* parse reply */
+ replyhead = msg->front.iov_base;
+ WARN_ON(le32_to_cpu(replyhead->num_ops) == 0);
+ op = (void *)(replyhead + 1);
+ rc = le32_to_cpu(replyhead->result);
+ bytes = le64_to_cpu(op->extent.length);
+ read_op = (le32_to_cpu(op->op) == CEPH_OSD_OP_READ);
+
+ dout("rbd_req_cb bytes=%lld readop=%d rc=%d\n", bytes, read_op, rc);
+
+ if (rc == -ENOENT && read_op) {
+ zero_bio_chain(req_data->bio, 0);
+ rc = 0;
+ } else if (rc == 0 && read_op && bytes < req_data->len) {
+ zero_bio_chain(req_data->bio, bytes);
+ bytes = req_data->len;
+ }
+
+ blk_end_request(req_data->rq, rc, bytes);
+
+ if (req_data->bio)
+ bio_chain_put(req_data->bio);
+
+ ceph_osdc_put_request(req);
+ kfree(req_data);
+}
+
+/*
+ * Do a synchronous ceph osd operation
+ */
+static int rbd_req_sync_op(struct rbd_device *dev,
+ struct ceph_snap_context *snapc,
+ u64 snapid,
+ int opcode,
+ int flags,
+ struct ceph_osd_req_op *orig_ops,
+ int num_reply,
+ const char *obj,
+ u64 ofs, u64 len,
+ char *buf)
+{
+ int ret;
+ struct page **pages;
+ int num_pages;
+ struct ceph_osd_req_op *ops = orig_ops;
+ u32 payload_len;
+
+ num_pages = calc_pages_for(ofs , len);
+ pages = ceph_alloc_page_vector(num_pages, GFP_KERNEL);
+ if (IS_ERR(pages))
+ return PTR_ERR(pages);
+
+ if (!orig_ops) {
+ payload_len = (flags & CEPH_OSD_FLAG_WRITE ? len : 0);
+ ret = rbd_create_rw_ops(&ops, 1, opcode, payload_len);
+ if (ret < 0)
+ goto done;
+
+ if ((flags & CEPH_OSD_FLAG_WRITE) && buf) {
+ ret = ceph_copy_to_page_vector(pages, buf, ofs, len);
+ if (ret < 0)
+ goto done_ops;
+ }
+ }
+
+ ret = rbd_do_request(NULL, dev, snapc, snapid,
+ obj, ofs, len, NULL,
+ pages, num_pages,
+ flags,
+ ops,
+ 2,
+ NULL);
+ if (ret < 0)
+ goto done_ops;
+
+ if ((flags & CEPH_OSD_FLAG_READ) && buf)
+ ret = ceph_copy_from_page_vector(pages, buf, ofs, ret);
+
+done_ops:
+ if (!orig_ops)
+ rbd_destroy_ops(ops);
+done:
+ ceph_release_page_vector(pages, num_pages);
+ return ret;
+}
+
+/*
+ * Do an asynchronous ceph osd operation
+ */
+static int rbd_do_op(struct request *rq,
+ struct rbd_device *rbd_dev ,
+ struct ceph_snap_context *snapc,
+ u64 snapid,
+ int opcode, int flags, int num_reply,
+ u64 ofs, u64 len,
+ struct bio *bio)
+{
+ char *seg_name;
+ u64 seg_ofs;
+ u64 seg_len;
+ int ret;
+ struct ceph_osd_req_op *ops;
+ u32 payload_len;
+
+ seg_name = kmalloc(RBD_MAX_SEG_NAME_LEN + 1, GFP_NOIO);
+ if (!seg_name)
+ return -ENOMEM;
+
+ seg_len = rbd_get_segment(&rbd_dev->header,
+ rbd_dev->header.block_name,
+ ofs, len,
+ seg_name, &seg_ofs);
+
+ payload_len = (flags & CEPH_OSD_FLAG_WRITE ? seg_len : 0);
+
+ ret = rbd_create_rw_ops(&ops, 1, opcode, payload_len);
+ if (ret < 0)
+ goto done;
+
+ /* we've taken care of segment sizes earlier when we
+ cloned the bios. We should never have a segment
+ truncated at this point */
+ BUG_ON(seg_len < len);
+
+ ret = rbd_do_request(rq, rbd_dev, snapc, snapid,
+ seg_name, seg_ofs, seg_len,
+ bio,
+ NULL, 0,
+ flags,
+ ops,
+ num_reply,
+ rbd_req_cb);
+done:
+ kfree(seg_name);
+ return ret;
+}
+
+/*
+ * Request async osd write
+ */
+static int rbd_req_write(struct request *rq,
+ struct rbd_device *rbd_dev,
+ struct ceph_snap_context *snapc,
+ u64 ofs, u64 len,
+ struct bio *bio)
+{
+ return rbd_do_op(rq, rbd_dev, snapc, CEPH_NOSNAP,
+ CEPH_OSD_OP_WRITE,
+ CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK,
+ 2,
+ ofs, len, bio);
+}
+
+/*
+ * Request async osd read
+ */
+static int rbd_req_read(struct request *rq,
+ struct rbd_device *rbd_dev,
+ u64 snapid,
+ u64 ofs, u64 len,
+ struct bio *bio)
+{
+ return rbd_do_op(rq, rbd_dev, NULL,
+ (snapid ? snapid : CEPH_NOSNAP),
+ CEPH_OSD_OP_READ,
+ CEPH_OSD_FLAG_READ,
+ 2,
+ ofs, len, bio);
+}
+
+/*
+ * Request sync osd read
+ */
+static int rbd_req_sync_read(struct rbd_device *dev,
+ struct ceph_snap_context *snapc,
+ u64 snapid,
+ const char *obj,
+ u64 ofs, u64 len,
+ char *buf)
+{
+ return rbd_req_sync_op(dev, NULL,
+ (snapid ? snapid : CEPH_NOSNAP),
+ CEPH_OSD_OP_READ,
+ CEPH_OSD_FLAG_READ,
+ NULL,
+ 1, obj, ofs, len, buf);
+}
+
+/*
+ * Request sync osd read
+ */
+static int rbd_req_sync_rollback_obj(struct rbd_device *dev,
+ u64 snapid,
+ const char *obj)
+{
+ struct ceph_osd_req_op *ops;
+ int ret = rbd_create_rw_ops(&ops, 1, CEPH_OSD_OP_ROLLBACK, 0);
+ if (ret < 0)
+ return ret;
+
+ ops[0].snap.snapid = snapid;
+
+ ret = rbd_req_sync_op(dev, NULL,
+ CEPH_NOSNAP,
+ 0,
+ CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK,
+ ops,
+ 1, obj, 0, 0, NULL);
+
+ rbd_destroy_ops(ops);
+
+ if (ret < 0)
+ return ret;
+
+ return ret;
+}
+
+/*
+ * Request sync osd read
+ */
+static int rbd_req_sync_exec(struct rbd_device *dev,
+ const char *obj,
+ const char *cls,
+ const char *method,
+ const char *data,
+ int len)
+{
+ struct ceph_osd_req_op *ops;
+ int cls_len = strlen(cls);
+ int method_len = strlen(method);
+ int ret = rbd_create_rw_ops(&ops, 1, CEPH_OSD_OP_CALL,
+ cls_len + method_len + len);
+ if (ret < 0)
+ return ret;
+
+ ops[0].cls.class_name = cls;
+ ops[0].cls.class_len = (__u8)cls_len;
+ ops[0].cls.method_name = method;
+ ops[0].cls.method_len = (__u8)method_len;
+ ops[0].cls.argc = 0;
+ ops[0].cls.indata = data;
+ ops[0].cls.indata_len = len;
+
+ ret = rbd_req_sync_op(dev, NULL,
+ CEPH_NOSNAP,
+ 0,
+ CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK,
+ ops,
+ 1, obj, 0, 0, NULL);
+
+ rbd_destroy_ops(ops);
+
+ dout("cls_exec returned %d\n", ret);
+ return ret;
+}
+
+/*
+ * block device queue callback
+ */
+static void rbd_rq_fn(struct request_queue *q)
+{
+ struct rbd_device *rbd_dev = q->queuedata;
+ struct request *rq;
+ struct bio_pair *bp = NULL;
+
+ rq = blk_fetch_request(q);
+
+ while (1) {
+ struct bio *bio;
+ struct bio *rq_bio, *next_bio = NULL;
+ bool do_write;
+ int size, op_size = 0;
+ u64 ofs;
+
+ /* peek at request from block layer */
+ if (!rq)
+ break;
+
+ dout("fetched request\n");
+
+ /* filter out block requests we don't understand */
+ if ((rq->cmd_type != REQ_TYPE_FS)) {
+ __blk_end_request_all(rq, 0);
+ goto next;
+ }
+
+ /* deduce our operation (read, write) */
+ do_write = (rq_data_dir(rq) == WRITE);
+
+ size = blk_rq_bytes(rq);
+ ofs = blk_rq_pos(rq) * 512ULL;
+ rq_bio = rq->bio;
+ if (do_write && rbd_dev->read_only) {
+ __blk_end_request_all(rq, -EROFS);
+ goto next;
+ }
+
+ spin_unlock_irq(q->queue_lock);
+
+ dout("%s 0x%x bytes at 0x%llx\n",
+ do_write ? "write" : "read",
+ size, blk_rq_pos(rq) * 512ULL);
+
+ do {
+ /* a bio clone to be passed down to OSD req */
+ dout("rq->bio->bi_vcnt=%d\n", rq->bio->bi_vcnt);
+ op_size = rbd_get_segment(&rbd_dev->header,
+ rbd_dev->header.block_name,
+ ofs, size,
+ NULL, NULL);
+ bio = bio_chain_clone(&rq_bio, &next_bio, &bp,
+ op_size, GFP_ATOMIC);
+ if (!bio) {
+ spin_lock_irq(q->queue_lock);
+ __blk_end_request_all(rq, -ENOMEM);
+ goto next;
+ }
+
+ /* init OSD command: write or read */
+ if (do_write)
+ rbd_req_write(rq, rbd_dev,
+ rbd_dev->header.snapc,
+ ofs,
+ op_size, bio);
+ else
+ rbd_req_read(rq, rbd_dev,
+ cur_snap_id(rbd_dev),
+ ofs,
+ op_size, bio);
+
+ size -= op_size;
+ ofs += op_size;
+
+ rq_bio = next_bio;
+ } while (size > 0);
+
+ if (bp)
+ bio_pair_release(bp);
+
+ spin_lock_irq(q->queue_lock);
+next:
+ rq = blk_fetch_request(q);
+ }
+}
+
+/*
+ * a queue callback. Makes sure that we don't create a bio that spans across
+ * multiple osd objects. One exception would be with a single page bios,
+ * which we handle later at bio_chain_clone
+ */
+static int rbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bmd,
+ struct bio_vec *bvec)
+{
+ struct rbd_device *rbd_dev = q->queuedata;
+ unsigned int chunk_sectors = 1 << (rbd_dev->header.obj_order - 9);
+ sector_t sector = bmd->bi_sector + get_start_sect(bmd->bi_bdev);
+ unsigned int bio_sectors = bmd->bi_size >> 9;
+ int max;
+
+ max = (chunk_sectors - ((sector & (chunk_sectors - 1))
+ + bio_sectors)) << 9;
+ if (max < 0)
+ max = 0; /* bio_add cannot handle a negative return */
+ if (max <= bvec->bv_len && bio_sectors == 0)
+ return bvec->bv_len;
+ return max;
+}
+
+static void rbd_free_disk(struct rbd_device *rbd_dev)
+{
+ struct gendisk *disk = rbd_dev->disk;
+
+ if (!disk)
+ return;
+
+ rbd_header_free(&rbd_dev->header);
+
+ if (disk->flags & GENHD_FL_UP)
+ del_gendisk(disk);
+ if (disk->queue)
+ blk_cleanup_queue(disk->queue);
+ put_disk(disk);
+}
+
+/*
+ * reload the ondisk the header
+ */
+static int rbd_read_header(struct rbd_device *rbd_dev,
+ struct rbd_image_header *header)
+{
+ ssize_t rc;
+ struct rbd_image_header_ondisk *dh;
+ int snap_count = 0;
+ u64 snap_names_len = 0;
+
+ while (1) {
+ int len = sizeof(*dh) +
+ snap_count * sizeof(struct rbd_image_snap_ondisk) +
+ snap_names_len;
+
+ rc = -ENOMEM;
+ dh = kmalloc(len, GFP_KERNEL);
+ if (!dh)
+ return -ENOMEM;
+
+ rc = rbd_req_sync_read(rbd_dev,
+ NULL, CEPH_NOSNAP,
+ rbd_dev->obj_md_name,
+ 0, len,
+ (char *)dh);
+ if (rc < 0)
+ goto out_dh;
+
+ rc = rbd_header_from_disk(header, dh, snap_count, GFP_KERNEL);
+ if (rc < 0)
+ goto out_dh;
+
+ if (snap_count != header->total_snaps) {
+ snap_count = header->total_snaps;
+ snap_names_len = header->snap_names_len;
+ rbd_header_free(header);
+ kfree(dh);
+ continue;
+ }
+ break;
+ }
+
+out_dh:
+ kfree(dh);
+ return rc;
+}
+
+/*
+ * create a snapshot
+ */
+static int rbd_header_add_snap(struct rbd_device *dev,
+ const char *snap_name,
+ gfp_t gfp_flags)
+{
+ int name_len = strlen(snap_name);
+ u64 new_snapid;
+ int ret;
+ void *data, *data_start, *data_end;
+
+ /* we should create a snapshot only if we're pointing at the head */
+ if (dev->cur_snap)
+ return -EINVAL;
+
+ ret = ceph_monc_create_snapid(&dev->client->monc, dev->poolid,
+ &new_snapid);
+ dout("created snapid=%lld\n", new_snapid);
+ if (ret < 0)
+ return ret;
+
+ data = kmalloc(name_len + 16, gfp_flags);
+ if (!data)
+ return -ENOMEM;
+
+ data_start = data;
+ data_end = data + name_len + 16;
+
+ ceph_encode_string_safe(&data, data_end, snap_name, name_len, bad);
+ ceph_encode_64_safe(&data, data_end, new_snapid, bad);
+
+ ret = rbd_req_sync_exec(dev, dev->obj_md_name, "rbd", "snap_add",
+ data_start, data - data_start);
+
+ kfree(data_start);
+
+ if (ret < 0)
+ return ret;
+
+ dev->header.snapc->seq = new_snapid;
+
+ return 0;
+bad:
+ return -ERANGE;
+}
+
+/*
+ * only read the first part of the ondisk header, without the snaps info
+ */
+static int rbd_update_snaps(struct rbd_device *rbd_dev)
+{
+ int ret;
+ struct rbd_image_header h;
+ u64 snap_seq;
+
+ ret = rbd_read_header(rbd_dev, &h);
+ if (ret < 0)
+ return ret;
+
+ down_write(&rbd_dev->header.snap_rwsem);
+
+ snap_seq = rbd_dev->header.snapc->seq;
+
+ kfree(rbd_dev->header.snapc);
+ kfree(rbd_dev->header.snap_names);
+ kfree(rbd_dev->header.snap_sizes);
+
+ rbd_dev->header.total_snaps = h.total_snaps;
+ rbd_dev->header.snapc = h.snapc;
+ rbd_dev->header.snap_names = h.snap_names;
+ rbd_dev->header.snap_sizes = h.snap_sizes;
+ rbd_dev->header.snapc->seq = snap_seq;
+
+ up_write(&rbd_dev->header.snap_rwsem);
+
+ return 0;
+}
+
+static int rbd_init_disk(struct rbd_device *rbd_dev)
+{
+ struct gendisk *disk;
+ struct request_queue *q;
+ int rc;
+ u64 total_size = 0;
+
+ /* contact OSD, request size info about the object being mapped */
+ rc = rbd_read_header(rbd_dev, &rbd_dev->header);
+ if (rc)
+ return rc;
+
+ rc = rbd_header_set_snap(rbd_dev, rbd_dev->snap_name, &total_size);
+ if (rc)
+ return rc;
+
+ /* create gendisk info */
+ rc = -ENOMEM;
+ disk = alloc_disk(RBD_MINORS_PER_MAJOR);
+ if (!disk)
+ goto out;
+
+ sprintf(disk->disk_name, DRV_NAME "%d", rbd_dev->id);
+ disk->major = rbd_dev->major;
+ disk->first_minor = 0;
+ disk->fops = &rbd_bd_ops;
+ disk->private_data = rbd_dev;
+
+ /* init rq */
+ rc = -ENOMEM;
+ q = blk_init_queue(rbd_rq_fn, &rbd_dev->lock);
+ if (!q)
+ goto out_disk;
+ blk_queue_merge_bvec(q, rbd_merge_bvec);
+ disk->queue = q;
+
+ q->queuedata = rbd_dev;
+
+ rbd_dev->disk = disk;
+ rbd_dev->q = q;
+
+ /* finally, announce the disk to the world */
+ set_capacity(disk, total_size / 512ULL);
+ add_disk(disk);
+
+ pr_info("%s: added with size 0x%llx\n",
+ disk->disk_name, (unsigned long long)total_size);
+ return 0;
+
+out_disk:
+ put_disk(disk);
+out:
+ return rc;
+}
+
+/********************************************************************
+ * /sys/class/rbd/
+ * add map rados objects to blkdev
+ * remove unmap rados objects
+ * list show mappings
+ *******************************************************************/
+
+static void class_rbd_release(struct class *cls)
+{
+ kfree(cls);
+}
+
+static ssize_t class_rbd_list(struct class *c,
+ struct class_attribute *attr,
+ char *data)
+{
+ int n = 0;
+ struct list_head *tmp;
+ int max = PAGE_SIZE;
+
+ mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+
+ n += snprintf(data, max,
+ "#id\tmajor\tclient_name\tpool\tname\tsnap\tKB\n");
+
+ list_for_each(tmp, &rbd_dev_list) {
+ struct rbd_device *rbd_dev;
+
+ rbd_dev = list_entry(tmp, struct rbd_device, node);
+ n += snprintf(data+n, max-n,
+ "%d\t%d\tclient%lld\t%s\t%s\t%s\t%lld\n",
+ rbd_dev->id,
+ rbd_dev->major,
+ ceph_client_id(rbd_dev->client),
+ rbd_dev->pool_name,
+ rbd_dev->obj, rbd_dev->snap_name,
+ rbd_dev->header.image_size >> 10);
+ if (n == max)
+ break;
+ }
+
+ mutex_unlock(&ctl_mutex);
+ return n;
+}
+
+static ssize_t class_rbd_add(struct class *c,
+ struct class_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ceph_osd_client *osdc;
+ struct rbd_device *rbd_dev;
+ ssize_t rc = -ENOMEM;
+ int irc, new_id = 0;
+ struct list_head *tmp;
+ char *mon_dev_name;
+ char *options;
+
+ if (!try_module_get(THIS_MODULE))
+ return -ENODEV;
+
+ mon_dev_name = kmalloc(RBD_MAX_OPT_LEN, GFP_KERNEL);
+ if (!mon_dev_name)
+ goto err_out_mod;
+
+ options = kmalloc(RBD_MAX_OPT_LEN, GFP_KERNEL);
+ if (!options)
+ goto err_mon_dev;
+
+ /* new rbd_device object */
+ rbd_dev = kzalloc(sizeof(*rbd_dev), GFP_KERNEL);
+ if (!rbd_dev)
+ goto err_out_opt;
+
+ /* static rbd_device initialization */
+ spin_lock_init(&rbd_dev->lock);
+ INIT_LIST_HEAD(&rbd_dev->node);
+
+ /* generate unique id: find highest unique id, add one */
+ mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+
+ list_for_each(tmp, &rbd_dev_list) {
+ struct rbd_device *rbd_dev;
+
+ rbd_dev = list_entry(tmp, struct rbd_device, node);
+ if (rbd_dev->id >= new_id)
+ new_id = rbd_dev->id + 1;
+ }
+
+ rbd_dev->id = new_id;
+
+ /* add to global list */
+ list_add_tail(&rbd_dev->node, &rbd_dev_list);
+
+ /* parse add command */
+ if (sscanf(buf, "%" __stringify(RBD_MAX_OPT_LEN) "s "
+ "%" __stringify(RBD_MAX_OPT_LEN) "s "
+ "%" __stringify(RBD_MAX_POOL_NAME_LEN) "s "
+ "%" __stringify(RBD_MAX_OBJ_NAME_LEN) "s"
+ "%" __stringify(RBD_MAX_SNAP_NAME_LEN) "s",
+ mon_dev_name, options, rbd_dev->pool_name,
+ rbd_dev->obj, rbd_dev->snap_name) < 4) {
+ rc = -EINVAL;
+ goto err_out_slot;
+ }
+
+ if (rbd_dev->snap_name[0] == 0)
+ rbd_dev->snap_name[0] = '-';
+
+ rbd_dev->obj_len = strlen(rbd_dev->obj);
+ snprintf(rbd_dev->obj_md_name, sizeof(rbd_dev->obj_md_name), "%s%s",
+ rbd_dev->obj, RBD_SUFFIX);
+
+ /* initialize rest of new object */
+ snprintf(rbd_dev->name, DEV_NAME_LEN, DRV_NAME "%d", rbd_dev->id);
+ rc = rbd_get_client(rbd_dev, mon_dev_name, options);
+ if (rc < 0)
+ goto err_out_slot;
+
+ mutex_unlock(&ctl_mutex);
+
+ /* pick the pool */
+ osdc = &rbd_dev->client->osdc;
+ rc = ceph_pg_poolid_by_name(osdc->osdmap, rbd_dev->pool_name);
+ if (rc < 0)
+ goto err_out_client;
+ rbd_dev->poolid = rc;
+
+ /* register our block device */
+ irc = register_blkdev(0, rbd_dev->name);
+ if (irc < 0) {
+ rc = irc;
+ goto err_out_client;
+ }
+ rbd_dev->major = irc;
+
+ /* set up and announce blkdev mapping */
+ rc = rbd_init_disk(rbd_dev);
+ if (rc)
+ goto err_out_blkdev;
+
+ return count;
+
+err_out_blkdev:
+ unregister_blkdev(rbd_dev->major, rbd_dev->name);
+err_out_client:
+ rbd_put_client(rbd_dev);
+ mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+err_out_slot:
+ list_del_init(&rbd_dev->node);
+ mutex_unlock(&ctl_mutex);
+
+ kfree(rbd_dev);
+err_out_opt:
+ kfree(options);
+err_mon_dev:
+ kfree(mon_dev_name);
+err_out_mod:
+ dout("Error adding device %s\n", buf);
+ module_put(THIS_MODULE);
+ return rc;
+}
+
+static struct rbd_device *__rbd_get_dev(unsigned long id)
+{
+ struct list_head *tmp;
+ struct rbd_device *rbd_dev;
+
+ list_for_each(tmp, &rbd_dev_list) {
+ rbd_dev = list_entry(tmp, struct rbd_device, node);
+ if (rbd_dev->id == id)
+ return rbd_dev;
+ }
+ return NULL;
+}
+
+static ssize_t class_rbd_remove(struct class *c,
+ struct class_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct rbd_device *rbd_dev = NULL;
+ int target_id, rc;
+ unsigned long ul;
+
+ rc = strict_strtoul(buf, 10, &ul);
+ if (rc)
+ return rc;
+
+ /* convert to int; abort if we lost anything in the conversion */
+ target_id = (int) ul;
+ if (target_id != ul)
+ return -EINVAL;
+
+ /* remove object from list immediately */
+ mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+
+ rbd_dev = __rbd_get_dev(target_id);
+ if (rbd_dev)
+ list_del_init(&rbd_dev->node);
+
+ mutex_unlock(&ctl_mutex);
+
+ if (!rbd_dev)
+ return -ENOENT;
+
+ rbd_put_client(rbd_dev);
+
+ /* clean up and free blkdev */
+ rbd_free_disk(rbd_dev);
+ unregister_blkdev(rbd_dev->major, rbd_dev->name);
+ kfree(rbd_dev);
+
+ /* release module ref */
+ module_put(THIS_MODULE);
+
+ return count;
+}
+
+static ssize_t class_rbd_snaps_list(struct class *c,
+ struct class_attribute *attr,
+ char *data)
+{
+ struct rbd_device *rbd_dev = NULL;
+ struct list_head *tmp;
+ struct rbd_image_header *header;
+ int i, n = 0, max = PAGE_SIZE;
+ int ret;
+
+ mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+
+ n += snprintf(data, max, "#id\tsnap\tKB\n");
+
+ list_for_each(tmp, &rbd_dev_list) {
+ char *names, *p;
+ struct ceph_snap_context *snapc;
+
+ rbd_dev = list_entry(tmp, struct rbd_device, node);
+ header = &rbd_dev->header;
+
+ down_read(&header->snap_rwsem);
+
+ names = header->snap_names;
+ snapc = header->snapc;
+
+ n += snprintf(data + n, max - n, "%d\t%s\t%lld%s\n",
+ rbd_dev->id, RBD_SNAP_HEAD_NAME,
+ header->image_size >> 10,
+ (!rbd_dev->cur_snap ? " (*)" : ""));
+ if (n == max)
+ break;
+
+ p = names;
+ for (i = 0; i < header->total_snaps; i++, p += strlen(p) + 1) {
+ n += snprintf(data + n, max - n, "%d\t%s\t%lld%s\n",
+ rbd_dev->id, p, header->snap_sizes[i] >> 10,
+ (rbd_dev->cur_snap &&
+ (snap_index(header, i) == rbd_dev->cur_snap) ?
+ " (*)" : ""));
+ if (n == max)
+ break;
+ }
+
+ up_read(&header->snap_rwsem);
+ }
+
+
+ ret = n;
+ mutex_unlock(&ctl_mutex);
+ return ret;
+}
+
+static ssize_t class_rbd_snaps_refresh(struct class *c,
+ struct class_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct rbd_device *rbd_dev = NULL;
+ int target_id, rc;
+ unsigned long ul;
+ int ret = count;
+
+ rc = strict_strtoul(buf, 10, &ul);
+ if (rc)
+ return rc;
+
+ /* convert to int; abort if we lost anything in the conversion */
+ target_id = (int) ul;
+ if (target_id != ul)
+ return -EINVAL;
+
+ mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+
+ rbd_dev = __rbd_get_dev(target_id);
+ if (!rbd_dev) {
+ ret = -ENOENT;
+ goto done;
+ }
+
+ rc = rbd_update_snaps(rbd_dev);
+ if (rc < 0)
+ ret = rc;
+
+done:
+ mutex_unlock(&ctl_mutex);
+ return ret;
+}
+
+static ssize_t class_rbd_snap_create(struct class *c,
+ struct class_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct rbd_device *rbd_dev = NULL;
+ int target_id, ret;
+ char *name;
+
+ name = kmalloc(RBD_MAX_SNAP_NAME_LEN + 1, GFP_KERNEL);
+ if (!name)
+ return -ENOMEM;
+
+ /* parse snaps add command */
+ if (sscanf(buf, "%d "
+ "%" __stringify(RBD_MAX_SNAP_NAME_LEN) "s",
+ &target_id,
+ name) != 2) {
+ ret = -EINVAL;
+ goto done;
+ }
+
+ mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+
+ rbd_dev = __rbd_get_dev(target_id);
+ if (!rbd_dev) {
+ ret = -ENOENT;
+ goto done_unlock;
+ }
+
+ ret = rbd_header_add_snap(rbd_dev,
+ name, GFP_KERNEL);
+ if (ret < 0)
+ goto done_unlock;
+
+ ret = rbd_update_snaps(rbd_dev);
+ if (ret < 0)
+ goto done_unlock;
+
+ ret = count;
+done_unlock:
+ mutex_unlock(&ctl_mutex);
+done:
+ kfree(name);
+ return ret;
+}
+
+static ssize_t class_rbd_rollback(struct class *c,
+ struct class_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct rbd_device *rbd_dev = NULL;
+ int target_id, ret;
+ u64 snapid;
+ char snap_name[RBD_MAX_SNAP_NAME_LEN];
+ u64 cur_ofs;
+ char *seg_name;
+
+ /* parse snaps add command */
+ if (sscanf(buf, "%d "
+ "%" __stringify(RBD_MAX_SNAP_NAME_LEN) "s",
+ &target_id,
+ snap_name) != 2) {
+ return -EINVAL;
+ }
+
+ ret = -ENOMEM;
+ seg_name = kmalloc(RBD_MAX_SEG_NAME_LEN + 1, GFP_NOIO);
+ if (!seg_name)
+ return ret;
+
+ mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+
+ rbd_dev = __rbd_get_dev(target_id);
+ if (!rbd_dev) {
+ ret = -ENOENT;
+ goto done_unlock;
+ }
+
+ ret = snap_by_name(&rbd_dev->header, snap_name, &snapid, NULL);
+ if (ret < 0)
+ goto done_unlock;
+
+ dout("snapid=%lld\n", snapid);
+
+ cur_ofs = 0;
+ while (cur_ofs < rbd_dev->header.image_size) {
+ cur_ofs += rbd_get_segment(&rbd_dev->header,
+ rbd_dev->obj,
+ cur_ofs, (u64)-1,
+ seg_name, NULL);
+ dout("seg_name=%s\n", seg_name);
+
+ ret = rbd_req_sync_rollback_obj(rbd_dev, snapid, seg_name);
+ if (ret < 0)
+ pr_warning("could not roll back obj %s err=%d\n",
+ seg_name, ret);
+ }
+
+ ret = rbd_update_snaps(rbd_dev);
+ if (ret < 0)
+ goto done_unlock;
+
+ ret = count;
+
+done_unlock:
+ mutex_unlock(&ctl_mutex);
+ kfree(seg_name);
+
+ return ret;
+}
+
+static struct class_attribute class_rbd_attrs[] = {
+ __ATTR(add, 0200, NULL, class_rbd_add),
+ __ATTR(remove, 0200, NULL, class_rbd_remove),
+ __ATTR(list, 0444, class_rbd_list, NULL),
+ __ATTR(snaps_refresh, 0200, NULL, class_rbd_snaps_refresh),
+ __ATTR(snap_create, 0200, NULL, class_rbd_snap_create),
+ __ATTR(snaps_list, 0444, class_rbd_snaps_list, NULL),
+ __ATTR(snap_rollback, 0200, NULL, class_rbd_rollback),
+ __ATTR_NULL
+};
+
+/*
+ * create control files in sysfs
+ * /sys/class/rbd/...
+ */
+static int rbd_sysfs_init(void)
+{
+ int ret = -ENOMEM;
+
+ class_rbd = kzalloc(sizeof(*class_rbd), GFP_KERNEL);
+ if (!class_rbd)
+ goto out;
+
+ class_rbd->name = DRV_NAME;
+ class_rbd->owner = THIS_MODULE;
+ class_rbd->class_release = class_rbd_release;
+ class_rbd->class_attrs = class_rbd_attrs;
+
+ ret = class_register(class_rbd);
+ if (ret)
+ goto out_class;
+ return 0;
+
+out_class:
+ kfree(class_rbd);
+ class_rbd = NULL;
+ pr_err(DRV_NAME ": failed to create class rbd\n");
+out:
+ return ret;
+}
+
+static void rbd_sysfs_cleanup(void)
+{
+ if (class_rbd)
+ class_destroy(class_rbd);
+ class_rbd = NULL;
+}
+
+int __init rbd_init(void)
+{
+ int rc;
+
+ rc = rbd_sysfs_init();
+ if (rc)
+ return rc;
+ spin_lock_init(&node_lock);
+ pr_info("loaded " DRV_NAME_LONG "\n");
+ return 0;
+}
+
+void __exit rbd_exit(void)
+{
+ rbd_sysfs_cleanup();
+}
+
+module_init(rbd_init);
+module_exit(rbd_exit);
+
+MODULE_AUTHOR("Sage Weil <sage@newdream.net>");
+MODULE_AUTHOR("Yehuda Sadeh <yehuda@hq.newdream.net>");
+MODULE_DESCRIPTION("rados block device");
+
+/* following authorship retained from original osdblk.c */
+MODULE_AUTHOR("Jeff Garzik <jeff@garzik.org>");
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/block/rbd_types.h b/drivers/block/rbd_types.h
new file mode 100644
index 000000000000..fc6c678aa2cb
--- /dev/null
+++ b/drivers/block/rbd_types.h
@@ -0,0 +1,73 @@
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2004-2010 Sage Weil <sage@newdream.net>
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation. See file COPYING.
+ *
+ */
+
+#ifndef CEPH_RBD_TYPES_H
+#define CEPH_RBD_TYPES_H
+
+#include <linux/types.h>
+
+/*
+ * rbd image 'foo' consists of objects
+ * foo.rbd - image metadata
+ * foo.00000000
+ * foo.00000001
+ * ... - data
+ */
+
+#define RBD_SUFFIX ".rbd"
+#define RBD_DIRECTORY "rbd_directory"
+#define RBD_INFO "rbd_info"
+
+#define RBD_DEFAULT_OBJ_ORDER 22 /* 4MB */
+#define RBD_MIN_OBJ_ORDER 16
+#define RBD_MAX_OBJ_ORDER 30
+
+#define RBD_MAX_OBJ_NAME_LEN 96
+#define RBD_MAX_SEG_NAME_LEN 128
+
+#define RBD_COMP_NONE 0
+#define RBD_CRYPT_NONE 0
+
+#define RBD_HEADER_TEXT "<<< Rados Block Device Image >>>\n"
+#define RBD_HEADER_SIGNATURE "RBD"
+#define RBD_HEADER_VERSION "001.005"
+
+struct rbd_info {
+ __le64 max_id;
+} __attribute__ ((packed));
+
+struct rbd_image_snap_ondisk {
+ __le64 id;
+ __le64 image_size;
+} __attribute__((packed));
+
+struct rbd_image_header_ondisk {
+ char text[40];
+ char block_name[24];
+ char signature[4];
+ char version[8];
+ struct {
+ __u8 order;
+ __u8 crypt_type;
+ __u8 comp_type;
+ __u8 unused;
+ } __attribute__((packed)) options;
+ __le64 image_size;
+ __le64 snap_seq;
+ __le32 snap_count;
+ __le32 reserved;
+ __le64 snap_names_len;
+ struct rbd_image_snap_ondisk snaps[0];
+} __attribute__((packed));
+
+
+#endif
diff --git a/drivers/block/swim.c b/drivers/block/swim.c
index 2e46815876df..75333d0a3327 100644
--- a/drivers/block/swim.c
+++ b/drivers/block/swim.c
@@ -20,7 +20,7 @@
#include <linux/fd.h>
#include <linux/slab.h>
#include <linux/blkdev.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/hdreg.h>
#include <linux/kernel.h>
#include <linux/delay.h>
@@ -222,6 +222,7 @@ extern int swim_read_sector_header(struct swim __iomem *base,
extern int swim_read_sector_data(struct swim __iomem *base,
unsigned char *data);
+static DEFINE_MUTEX(swim_mutex);
static inline void set_swim_mode(struct swim __iomem *base, int enable)
{
struct iwm __iomem *iwm_base;
@@ -666,9 +667,9 @@ static int floppy_unlocked_open(struct block_device *bdev, fmode_t mode)
{
int ret;
- lock_kernel();
+ mutex_lock(&swim_mutex);
ret = floppy_open(bdev, mode);
- unlock_kernel();
+ mutex_unlock(&swim_mutex);
return ret;
}
@@ -678,7 +679,7 @@ static int floppy_release(struct gendisk *disk, fmode_t mode)
struct floppy_state *fs = disk->private_data;
struct swim __iomem *base = fs->swd->base;
- lock_kernel();
+ mutex_lock(&swim_mutex);
if (fs->ref_count < 0)
fs->ref_count = 0;
else if (fs->ref_count > 0)
@@ -686,7 +687,7 @@ static int floppy_release(struct gendisk *disk, fmode_t mode)
if (fs->ref_count == 0)
swim_motor(base, OFF);
- unlock_kernel();
+ mutex_unlock(&swim_mutex);
return 0;
}
@@ -704,9 +705,9 @@ static int floppy_ioctl(struct block_device *bdev, fmode_t mode,
case FDEJECT:
if (fs->ref_count != 1)
return -EBUSY;
- lock_kernel();
+ mutex_lock(&swim_mutex);
err = floppy_eject(fs);
- unlock_kernel();
+ mutex_unlock(&swim_mutex);
return err;
case FDGETPRM:
diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c
index cc6a3864822c..bf3a5b859299 100644
--- a/drivers/block/swim3.c
+++ b/drivers/block/swim3.c
@@ -25,7 +25,7 @@
#include <linux/ioctl.h>
#include <linux/blkdev.h>
#include <linux/interrupt.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include <asm/io.h>
@@ -36,6 +36,7 @@
#include <asm/machdep.h>
#include <asm/pmac_feature.h>
+static DEFINE_MUTEX(swim3_mutex);
static struct request_queue *swim3_queue;
static struct gendisk *disks[2];
static struct request *fd_req;
@@ -873,9 +874,9 @@ static int floppy_ioctl(struct block_device *bdev, fmode_t mode,
{
int ret;
- lock_kernel();
+ mutex_lock(&swim3_mutex);
ret = floppy_locked_ioctl(bdev, mode, cmd, param);
- unlock_kernel();
+ mutex_unlock(&swim3_mutex);
return ret;
}
@@ -953,9 +954,9 @@ static int floppy_unlocked_open(struct block_device *bdev, fmode_t mode)
{
int ret;
- lock_kernel();
+ mutex_lock(&swim3_mutex);
ret = floppy_open(bdev, mode);
- unlock_kernel();
+ mutex_unlock(&swim3_mutex);
return ret;
}
@@ -964,13 +965,13 @@ static int floppy_release(struct gendisk *disk, fmode_t mode)
{
struct floppy_state *fs = disk->private_data;
struct swim3 __iomem *sw = fs->swim3;
- lock_kernel();
+ mutex_lock(&swim3_mutex);
if (fs->ref_count > 0 && --fs->ref_count == 0) {
swim3_action(fs, MOTOR_OFF);
out_8(&sw->control_bic, 0xff);
swim3_select(fs, RELAX);
}
- unlock_kernel();
+ mutex_unlock(&swim3_mutex);
return 0;
}
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index c48e14878582..9ae3bb713286 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -28,7 +28,7 @@
#include <linux/timer.h>
#include <linux/scatterlist.h>
#include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <scsi/scsi.h>
#define DRV_NAME "ub"
@@ -248,6 +248,7 @@ struct ub_completion {
spinlock_t lock;
};
+static DEFINE_MUTEX(ub_mutex);
static inline void ub_init_completion(struct ub_completion *x)
{
x->done = 0;
@@ -396,7 +397,7 @@ static int ub_probe_lun(struct ub_dev *sc, int lnum);
#else
static const struct usb_device_id ub_usb_ids[] = {
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_BULK) },
+ { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, USB_SC_SCSI, USB_PR_BULK) },
{ }
};
@@ -1715,9 +1716,9 @@ static int ub_bd_unlocked_open(struct block_device *bdev, fmode_t mode)
{
int ret;
- lock_kernel();
+ mutex_lock(&ub_mutex);
ret = ub_bd_open(bdev, mode);
- unlock_kernel();
+ mutex_unlock(&ub_mutex);
return ret;
}
@@ -1730,9 +1731,9 @@ static int ub_bd_release(struct gendisk *disk, fmode_t mode)
struct ub_lun *lun = disk->private_data;
struct ub_dev *sc = lun->udev;
- lock_kernel();
+ mutex_lock(&ub_mutex);
ub_put(sc);
- unlock_kernel();
+ mutex_unlock(&ub_mutex);
return 0;
}
@@ -1747,9 +1748,9 @@ static int ub_bd_ioctl(struct block_device *bdev, fmode_t mode,
void __user *usermem = (void __user *) arg;
int ret;
- lock_kernel();
+ mutex_lock(&ub_mutex);
ret = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, usermem);
- unlock_kernel();
+ mutex_unlock(&ub_mutex);
return ret;
}
diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c
index f651e51a3319..e2ff697697c2 100644
--- a/drivers/block/viodasd.c
+++ b/drivers/block/viodasd.c
@@ -41,7 +41,7 @@
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/string.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/dma-mapping.h>
#include <linux/completion.h>
#include <linux/device.h>
@@ -73,6 +73,7 @@ enum {
MAX_DISK_NAME = FIELD_SIZEOF(struct gendisk, disk_name)
};
+static DEFINE_MUTEX(viodasd_mutex);
static DEFINE_SPINLOCK(viodasd_spinlock);
#define VIOMAXREQ 16
@@ -180,9 +181,9 @@ static int viodasd_unlocked_open(struct block_device *bdev, fmode_t mode)
{
int ret;
- lock_kernel();
+ mutex_lock(&viodasd_mutex);
ret = viodasd_open(bdev, mode);
- unlock_kernel();
+ mutex_unlock(&viodasd_mutex);
return ret;
}
@@ -196,7 +197,7 @@ static int viodasd_release(struct gendisk *disk, fmode_t mode)
struct viodasd_device *d = disk->private_data;
HvLpEvent_Rc hvrc;
- lock_kernel();
+ mutex_lock(&viodasd_mutex);
/* Send the event to OS/400. We DON'T expect a response */
hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
HvLpEvent_Type_VirtualIo,
@@ -210,7 +211,7 @@ static int viodasd_release(struct gendisk *disk, fmode_t mode)
if (hvrc != 0)
pr_warning("HV close call failed %d\n", (int)hvrc);
- unlock_kernel();
+ mutex_unlock(&viodasd_mutex);
return 0;
}
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index 2aafafca2b13..6ecf89cdf006 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -2,7 +2,6 @@
#include <linux/spinlock.h>
#include <linux/slab.h>
#include <linux/blkdev.h>
-#include <linux/smp_lock.h>
#include <linux/hdreg.h>
#include <linux/virtio.h>
#include <linux/virtio_blk.h>
@@ -128,9 +127,6 @@ static bool do_req(struct request_queue *q, struct virtio_blk *vblk,
}
}
- if (vbr->req->cmd_flags & REQ_HARDBARRIER)
- vbr->out_hdr.type |= VIRTIO_BLK_T_BARRIER;
-
sg_set_buf(&vblk->sg[out++], &vbr->out_hdr, sizeof(vbr->out_hdr));
/*
@@ -202,6 +198,7 @@ static int virtblk_get_id(struct gendisk *disk, char *id_str)
struct virtio_blk *vblk = disk->private_data;
struct request *req;
struct bio *bio;
+ int err;
bio = bio_map_kern(vblk->disk->queue, id_str, VIRTIO_BLK_ID_BYTES,
GFP_KERNEL);
@@ -215,11 +212,14 @@ static int virtblk_get_id(struct gendisk *disk, char *id_str)
}
req->cmd_type = REQ_TYPE_SPECIAL;
- return blk_execute_rq(vblk->disk->queue, vblk->disk, req, false);
+ err = blk_execute_rq(vblk->disk->queue, vblk->disk, req, false);
+ blk_put_request(req);
+
+ return err;
}
-static int virtblk_locked_ioctl(struct block_device *bdev, fmode_t mode,
- unsigned cmd, unsigned long data)
+static int virtblk_ioctl(struct block_device *bdev, fmode_t mode,
+ unsigned int cmd, unsigned long data)
{
struct gendisk *disk = bdev->bd_disk;
struct virtio_blk *vblk = disk->private_data;
@@ -234,18 +234,6 @@ static int virtblk_locked_ioctl(struct block_device *bdev, fmode_t mode,
(void __user *)data);
}
-static int virtblk_ioctl(struct block_device *bdev, fmode_t mode,
- unsigned int cmd, unsigned long param)
-{
- int ret;
-
- lock_kernel();
- ret = virtblk_locked_ioctl(bdev, mode, cmd, param);
- unlock_kernel();
-
- return ret;
-}
-
/* We provide getgeo only to please some old bootloader/partitioning tools */
static int virtblk_getgeo(struct block_device *bd, struct hd_geometry *geo)
{
@@ -388,31 +376,9 @@ static int __devinit virtblk_probe(struct virtio_device *vdev)
vblk->disk->driverfs_dev = &vdev->dev;
index++;
- if (virtio_has_feature(vdev, VIRTIO_BLK_F_FLUSH)) {
- /*
- * If the FLUSH feature is supported we do have support for
- * flushing a volatile write cache on the host. Use that
- * to implement write barrier support.
- */
- blk_queue_ordered(q, QUEUE_ORDERED_DRAIN_FLUSH);
- } else if (virtio_has_feature(vdev, VIRTIO_BLK_F_BARRIER)) {
- /*
- * If the BARRIER feature is supported the host expects us
- * to order request by tags. This implies there is not
- * volatile write cache on the host, and that the host
- * never re-orders outstanding I/O. This feature is not
- * useful for real life scenarious and deprecated.
- */
- blk_queue_ordered(q, QUEUE_ORDERED_TAG);
- } else {
- /*
- * If the FLUSH feature is not supported we must assume that
- * the host does not perform any kind of volatile write
- * caching. We still need to drain the queue to provider
- * proper barrier semantics.
- */
- blk_queue_ordered(q, QUEUE_ORDERED_DRAIN);
- }
+ /* configure queue flush support */
+ if (virtio_has_feature(vdev, VIRTIO_BLK_F_FLUSH))
+ blk_queue_flush(q, REQ_FLUSH);
/* If disk is read-only in the host, the guest should obey */
if (virtio_has_feature(vdev, VIRTIO_BLK_F_RO))
@@ -531,9 +497,9 @@ static const struct virtio_device_id id_table[] = {
};
static unsigned int features[] = {
- VIRTIO_BLK_F_BARRIER, VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX,
- VIRTIO_BLK_F_GEOMETRY, VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE,
- VIRTIO_BLK_F_SCSI, VIRTIO_BLK_F_FLUSH, VIRTIO_BLK_F_TOPOLOGY
+ VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX, VIRTIO_BLK_F_GEOMETRY,
+ VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE, VIRTIO_BLK_F_SCSI,
+ VIRTIO_BLK_F_FLUSH, VIRTIO_BLK_F_TOPOLOGY
};
/*
diff --git a/drivers/block/xd.c b/drivers/block/xd.c
index d5a3cd750561..4abd2bcd20fb 100644
--- a/drivers/block/xd.c
+++ b/drivers/block/xd.c
@@ -46,7 +46,7 @@
#include <linux/init.h>
#include <linux/wait.h>
#include <linux/blkdev.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/blkpg.h>
#include <linux/delay.h>
#include <linux/io.h>
@@ -58,6 +58,7 @@
#include "xd.h"
+static DEFINE_MUTEX(xd_mutex);
static void __init do_xd_setup (int *integers);
#ifdef MODULE
static int xd[5] = { -1,-1,-1,-1, };
@@ -381,9 +382,9 @@ static int xd_ioctl(struct block_device *bdev, fmode_t mode,
{
int ret;
- lock_kernel();
+ mutex_lock(&xd_mutex);
ret = xd_locked_ioctl(bdev, mode, cmd, param);
- unlock_kernel();
+ mutex_unlock(&xd_mutex);
return ret;
}
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index ab735a605cf3..4b33a18c32e0 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -41,7 +41,7 @@
#include <linux/cdrom.h>
#include <linux/module.h>
#include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/scatterlist.h>
#include <xen/xen.h>
@@ -69,6 +69,7 @@ struct blk_shadow {
unsigned long frame[BLKIF_MAX_SEGMENTS_PER_REQUEST];
};
+static DEFINE_MUTEX(blkfront_mutex);
static const struct block_device_operations xlvbd_block_fops;
#define BLK_RING_SIZE __RING_SIZE((struct blkif_sring *)0, PAGE_SIZE)
@@ -95,7 +96,7 @@ struct blkfront_info
struct gnttab_free_callback callback;
struct blk_shadow shadow[BLK_RING_SIZE];
unsigned long shadow_free;
- int feature_barrier;
+ unsigned int feature_flush;
int is_ready;
};
@@ -418,26 +419,12 @@ static int xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size)
}
-static int xlvbd_barrier(struct blkfront_info *info)
+static void xlvbd_flush(struct blkfront_info *info)
{
- int err;
- const char *barrier;
-
- switch (info->feature_barrier) {
- case QUEUE_ORDERED_DRAIN: barrier = "enabled (drain)"; break;
- case QUEUE_ORDERED_TAG: barrier = "enabled (tag)"; break;
- case QUEUE_ORDERED_NONE: barrier = "disabled"; break;
- default: return -EINVAL;
- }
-
- err = blk_queue_ordered(info->rq, info->feature_barrier);
-
- if (err)
- return err;
-
+ blk_queue_flush(info->rq, info->feature_flush);
printk(KERN_INFO "blkfront: %s: barriers %s\n",
- info->gd->disk_name, barrier);
- return 0;
+ info->gd->disk_name,
+ info->feature_flush ? "enabled" : "disabled");
}
@@ -516,7 +503,7 @@ static int xlvbd_alloc_gendisk(blkif_sector_t capacity,
info->rq = gd->queue;
info->gd = gd;
- xlvbd_barrier(info);
+ xlvbd_flush(info);
if (vdisk_info & VDISK_READONLY)
set_disk_ro(gd, 1);
@@ -662,8 +649,8 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
printk(KERN_WARNING "blkfront: %s: write barrier op failed\n",
info->gd->disk_name);
error = -EOPNOTSUPP;
- info->feature_barrier = QUEUE_ORDERED_NONE;
- xlvbd_barrier(info);
+ info->feature_flush = 0;
+ xlvbd_flush(info);
}
/* fall through */
case BLKIF_OP_READ:
@@ -1076,20 +1063,20 @@ static void blkfront_connect(struct blkfront_info *info)
/*
* If there's no "feature-barrier" defined, then it means
* we're dealing with a very old backend which writes
- * synchronously; draining will do what needs to get done.
+ * synchronously; nothing to do.
*
- * If there are barriers, then we can do full queued writes
- * with tagged barriers.
- *
- * If barriers are not supported, then there's no much we can
- * do, so just set ordering to NONE.
+ * If there are barriers, then we use flush.
*/
- if (err)
- info->feature_barrier = QUEUE_ORDERED_DRAIN;
- else if (barrier)
- info->feature_barrier = QUEUE_ORDERED_TAG;
- else
- info->feature_barrier = QUEUE_ORDERED_NONE;
+ info->feature_flush = 0;
+
+ /*
+ * The driver doesn't properly handled empty flushes, so
+ * lets disable barrier support for now.
+ */
+#if 0
+ if (!err && barrier)
+ info->feature_flush = REQ_FLUSH;
+#endif
err = xlvbd_alloc_gendisk(sectors, info, binfo, sector_size);
if (err) {
@@ -1201,7 +1188,7 @@ static int blkif_open(struct block_device *bdev, fmode_t mode)
struct blkfront_info *info;
int err = 0;
- lock_kernel();
+ mutex_lock(&blkfront_mutex);
info = disk->private_data;
if (!info) {
@@ -1219,7 +1206,7 @@ static int blkif_open(struct block_device *bdev, fmode_t mode)
mutex_unlock(&info->mutex);
out:
- unlock_kernel();
+ mutex_unlock(&blkfront_mutex);
return err;
}
@@ -1229,7 +1216,7 @@ static int blkif_release(struct gendisk *disk, fmode_t mode)
struct block_device *bdev;
struct xenbus_device *xbdev;
- lock_kernel();
+ mutex_lock(&blkfront_mutex);
bdev = bdget_disk(disk, 0);
bdput(bdev);
@@ -1263,7 +1250,7 @@ static int blkif_release(struct gendisk *disk, fmode_t mode)
}
out:
- unlock_kernel();
+ mutex_unlock(&blkfront_mutex);
return 0;
}
diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c
index 057413bb16e2..6e968cd4893c 100644
--- a/drivers/block/xsysace.c
+++ b/drivers/block/xsysace.c
@@ -89,7 +89,7 @@
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/blkdev.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/ata.h>
#include <linux/hdreg.h>
#include <linux/platform_device.h>
@@ -214,6 +214,7 @@ struct ace_device {
u16 cf_id[ATA_ID_WORDS];
};
+static DEFINE_MUTEX(xsysace_mutex);
static int ace_major;
/* ---------------------------------------------------------------------
@@ -903,13 +904,13 @@ static int ace_open(struct block_device *bdev, fmode_t mode)
dev_dbg(ace->dev, "ace_open() users=%i\n", ace->users + 1);
- lock_kernel();
+ mutex_lock(&xsysace_mutex);
spin_lock_irqsave(&ace->lock, flags);
ace->users++;
spin_unlock_irqrestore(&ace->lock, flags);
check_disk_change(bdev);
- unlock_kernel();
+ mutex_unlock(&xsysace_mutex);
return 0;
}
@@ -922,7 +923,7 @@ static int ace_release(struct gendisk *disk, fmode_t mode)
dev_dbg(ace->dev, "ace_release() users=%i\n", ace->users - 1);
- lock_kernel();
+ mutex_lock(&xsysace_mutex);
spin_lock_irqsave(&ace->lock, flags);
ace->users--;
if (ace->users == 0) {
@@ -930,7 +931,7 @@ static int ace_release(struct gendisk *disk, fmode_t mode)
ace_out(ace, ACE_CTRL, val & ~ACE_CTRL_LOCKREQ);
}
spin_unlock_irqrestore(&ace->lock, flags);
- unlock_kernel();
+ mutex_unlock(&xsysace_mutex);
return 0;
}
diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c
index d75b2bb601ad..dcd4cfcf4126 100644
--- a/drivers/block/z2ram.c
+++ b/drivers/block/z2ram.c
@@ -33,7 +33,7 @@
#include <linux/module.h>
#include <linux/blkdev.h>
#include <linux/bitops.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/slab.h>
#include <asm/setup.h>
@@ -57,6 +57,7 @@ extern struct mem_info m68k_memory[NUM_MEMINFO];
#define Z2RAM_CHUNK1024 ( Z2RAM_CHUNKSIZE >> 10 )
+static DEFINE_MUTEX(z2ram_mutex);
static u_long *z2ram_map = NULL;
static u_long z2ram_size = 0;
static int z2_count = 0;
@@ -154,7 +155,7 @@ static int z2_open(struct block_device *bdev, fmode_t mode)
device = MINOR(bdev->bd_dev);
- lock_kernel();
+ mutex_lock(&z2ram_mutex);
if ( current_device != -1 && current_device != device )
{
rc = -EBUSY;
@@ -296,25 +297,25 @@ static int z2_open(struct block_device *bdev, fmode_t mode)
set_capacity(z2ram_gendisk, z2ram_size >> 9);
}
- unlock_kernel();
+ mutex_unlock(&z2ram_mutex);
return 0;
err_out_kfree:
kfree(z2ram_map);
err_out:
- unlock_kernel();
+ mutex_unlock(&z2ram_mutex);
return rc;
}
static int
z2_release(struct gendisk *disk, fmode_t mode)
{
- lock_kernel();
+ mutex_lock(&z2ram_mutex);
if ( current_device == -1 ) {
- unlock_kernel();
+ mutex_unlock(&z2ram_mutex);
return 0;
}
- unlock_kernel();
+ mutex_unlock(&z2ram_mutex);
/*
* FIXME: unmap memory
*/
diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c
index d52e90a5a617..4104b7feae67 100644
--- a/drivers/bluetooth/bluecard_cs.c
+++ b/drivers/bluetooth/bluecard_cs.c
@@ -39,7 +39,6 @@
#include <linux/skbuff.h>
#include <linux/io.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ciscode.h>
#include <pcmcia/ds.h>
@@ -865,8 +864,7 @@ static int bluecard_probe(struct pcmcia_device *link)
info->p_dev = link;
link->priv = info;
- link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.IntType = INT_MEMORY_AND_IO;
+ link->config_flags |= CONF_ENABLE_IRQ;
return bluecard_config(link);
}
@@ -886,7 +884,7 @@ static int bluecard_config(struct pcmcia_device *link)
bluecard_info_t *info = link->priv;
int i, n;
- link->conf.ConfigIndex = 0x20;
+ link->config_index = 0x20;
link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
link->resource[0]->end = 64;
@@ -906,7 +904,7 @@ static int bluecard_config(struct pcmcia_device *link)
if (i != 0)
goto failed;
- i = pcmcia_request_configuration(link, &link->conf);
+ i = pcmcia_enable_device(link);
if (i != 0)
goto failed;
@@ -942,9 +940,7 @@ MODULE_DEVICE_TABLE(pcmcia, bluecard_ids);
static struct pcmcia_driver bluecard_driver = {
.owner = THIS_MODULE,
- .drv = {
- .name = "bluecard_cs",
- },
+ .name = "bluecard_cs",
.probe = bluecard_probe,
.remove = bluecard_detach,
.id_table = bluecard_ids,
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c
index 7ab8f29d5e0d..0c8a65587491 100644
--- a/drivers/bluetooth/bt3c_cs.c
+++ b/drivers/bluetooth/bt3c_cs.c
@@ -45,7 +45,6 @@
#include <linux/device.h>
#include <linux/firmware.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ciscode.h>
#include <pcmcia/ds.h>
@@ -657,11 +656,8 @@ static int bt3c_probe(struct pcmcia_device *link)
info->p_dev = link;
link->priv = info;
- link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
- link->resource[0]->end = 8;
-
- link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.IntType = INT_MEMORY_AND_IO;
+ link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP |
+ CONF_AUTO_SET_IO;
return bt3c_config(link);
}
@@ -675,43 +671,41 @@ static void bt3c_detach(struct pcmcia_device *link)
kfree(info);
}
-static int bt3c_check_config(struct pcmcia_device *p_dev,
- cistpl_cftable_entry_t *cf,
- cistpl_cftable_entry_t *dflt,
- unsigned int vcc,
- void *priv_data)
+static int bt3c_check_config(struct pcmcia_device *p_dev, void *priv_data)
{
- unsigned long try = (unsigned long) priv_data;
+ int *try = priv_data;
- p_dev->io_lines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK;
+ if (try == 0)
+ p_dev->io_lines = 16;
- if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
- p_dev->conf.Vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
- if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) &&
- (cf->io.win[0].base != 0)) {
- p_dev->resource[0]->start = cf->io.win[0].base;
- if (!pcmcia_request_io(p_dev))
- return 0;
- }
- return -ENODEV;
+ if ((p_dev->resource[0]->end != 8) || (p_dev->resource[0]->start == 0))
+ return -EINVAL;
+
+ p_dev->resource[0]->end = 8;
+ p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+ p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+
+ return pcmcia_request_io(p_dev);
}
static int bt3c_check_config_notpicky(struct pcmcia_device *p_dev,
- cistpl_cftable_entry_t *cf,
- cistpl_cftable_entry_t *dflt,
- unsigned int vcc,
void *priv_data)
{
static unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
int j;
- if ((cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
- for (j = 0; j < 5; j++) {
- p_dev->resource[0]->start = base[j];
- p_dev->io_lines = base[j] ? 16 : 3;
- if (!pcmcia_request_io(p_dev))
- return 0;
- }
+ if (p_dev->io_lines > 3)
+ return -ENODEV;
+
+ p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+ p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+ p_dev->resource[0]->end = 8;
+
+ for (j = 0; j < 5; j++) {
+ p_dev->resource[0]->start = base[j];
+ p_dev->io_lines = base[j] ? 16 : 3;
+ if (!pcmcia_request_io(p_dev))
+ return 0;
}
return -ENODEV;
}
@@ -742,7 +736,7 @@ found_port:
if (i != 0)
goto failed;
- i = pcmcia_request_configuration(link, &link->conf);
+ i = pcmcia_enable_device(link);
if (i != 0)
goto failed;
@@ -775,9 +769,7 @@ MODULE_DEVICE_TABLE(pcmcia, bt3c_ids);
static struct pcmcia_driver bt3c_driver = {
.owner = THIS_MODULE,
- .drv = {
- .name = "bt3c_cs",
- },
+ .name = "bt3c_cs",
.probe = bt3c_probe,
.remove = bt3c_detach,
.id_table = bt3c_ids,
diff --git a/drivers/bluetooth/btmrvl_debugfs.c b/drivers/bluetooth/btmrvl_debugfs.c
index 54739b08c308..fd6305bf953e 100644
--- a/drivers/bluetooth/btmrvl_debugfs.c
+++ b/drivers/bluetooth/btmrvl_debugfs.c
@@ -92,6 +92,7 @@ static const struct file_operations btmrvl_hscfgcmd_fops = {
.read = btmrvl_hscfgcmd_read,
.write = btmrvl_hscfgcmd_write,
.open = btmrvl_open_generic,
+ .llseek = default_llseek,
};
static ssize_t btmrvl_psmode_write(struct file *file, const char __user *ubuf,
@@ -130,6 +131,7 @@ static const struct file_operations btmrvl_psmode_fops = {
.read = btmrvl_psmode_read,
.write = btmrvl_psmode_write,
.open = btmrvl_open_generic,
+ .llseek = default_llseek,
};
static ssize_t btmrvl_pscmd_write(struct file *file, const char __user *ubuf,
@@ -173,6 +175,7 @@ static const struct file_operations btmrvl_pscmd_fops = {
.read = btmrvl_pscmd_read,
.write = btmrvl_pscmd_write,
.open = btmrvl_open_generic,
+ .llseek = default_llseek,
};
static ssize_t btmrvl_gpiogap_write(struct file *file, const char __user *ubuf,
@@ -211,6 +214,7 @@ static const struct file_operations btmrvl_gpiogap_fops = {
.read = btmrvl_gpiogap_read,
.write = btmrvl_gpiogap_write,
.open = btmrvl_open_generic,
+ .llseek = default_llseek,
};
static ssize_t btmrvl_hscmd_write(struct file *file, const char __user *ubuf,
@@ -252,6 +256,7 @@ static const struct file_operations btmrvl_hscmd_fops = {
.read = btmrvl_hscmd_read,
.write = btmrvl_hscmd_write,
.open = btmrvl_open_generic,
+ .llseek = default_llseek,
};
static ssize_t btmrvl_hsmode_write(struct file *file, const char __user *ubuf,
@@ -289,6 +294,7 @@ static const struct file_operations btmrvl_hsmode_fops = {
.read = btmrvl_hsmode_read,
.write = btmrvl_hsmode_write,
.open = btmrvl_open_generic,
+ .llseek = default_llseek,
};
static ssize_t btmrvl_curpsmode_read(struct file *file, char __user *userbuf,
@@ -306,6 +312,7 @@ static ssize_t btmrvl_curpsmode_read(struct file *file, char __user *userbuf,
static const struct file_operations btmrvl_curpsmode_fops = {
.read = btmrvl_curpsmode_read,
.open = btmrvl_open_generic,
+ .llseek = default_llseek,
};
static ssize_t btmrvl_psstate_read(struct file *file, char __user * userbuf,
@@ -323,6 +330,7 @@ static ssize_t btmrvl_psstate_read(struct file *file, char __user * userbuf,
static const struct file_operations btmrvl_psstate_fops = {
.read = btmrvl_psstate_read,
.open = btmrvl_open_generic,
+ .llseek = default_llseek,
};
static ssize_t btmrvl_hsstate_read(struct file *file, char __user *userbuf,
@@ -340,6 +348,7 @@ static ssize_t btmrvl_hsstate_read(struct file *file, char __user *userbuf,
static const struct file_operations btmrvl_hsstate_fops = {
.read = btmrvl_hsstate_read,
.open = btmrvl_open_generic,
+ .llseek = default_llseek,
};
static ssize_t btmrvl_txdnldready_read(struct file *file, char __user *userbuf,
@@ -358,6 +367,7 @@ static ssize_t btmrvl_txdnldready_read(struct file *file, char __user *userbuf,
static const struct file_operations btmrvl_txdnldready_fops = {
.read = btmrvl_txdnldready_read,
.open = btmrvl_open_generic,
+ .llseek = default_llseek,
};
void btmrvl_debugfs_init(struct hci_dev *hdev)
diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c
index 0d32ec82e9bf..548d1d9e4dda 100644
--- a/drivers/bluetooth/btmrvl_main.c
+++ b/drivers/bluetooth/btmrvl_main.c
@@ -117,8 +117,8 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb)
(event->data[2] == MODULE_ALREADY_UP)) ?
"Bring-up succeed" : "Bring-up failed");
- if (event->length > 3)
- priv->btmrvl_dev.dev_type = event->data[3];
+ if (event->length > 3 && event->data[3])
+ priv->btmrvl_dev.dev_type = HCI_AMP;
else
priv->btmrvl_dev.dev_type = HCI_BREDR;
diff --git a/drivers/bluetooth/btsdio.c b/drivers/bluetooth/btsdio.c
index 76e5127884f0..792e32d29a1d 100644
--- a/drivers/bluetooth/btsdio.c
+++ b/drivers/bluetooth/btsdio.c
@@ -46,6 +46,9 @@ static const struct sdio_device_id btsdio_table[] = {
/* Generic Bluetooth Type-B SDIO device */
{ SDIO_DEVICE_CLASS(SDIO_CLASS_BT_B) },
+ /* Generic Bluetooth AMP controller */
+ { SDIO_DEVICE_CLASS(SDIO_CLASS_BT_AMP) },
+
{ } /* Terminating entry */
};
@@ -329,6 +332,11 @@ static int btsdio_probe(struct sdio_func *func,
hdev->bus = HCI_SDIO;
hdev->driver_data = data;
+ if (id->class == SDIO_CLASS_BT_AMP)
+ hdev->dev_type = HCI_AMP;
+ else
+ hdev->dev_type = HCI_BREDR;
+
data->hdev = hdev;
SET_HCIDEV_DEV(hdev, &func->dev);
diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c
index 1c4f5e863b03..f8a0708e2311 100644
--- a/drivers/bluetooth/btuart_cs.c
+++ b/drivers/bluetooth/btuart_cs.c
@@ -41,7 +41,6 @@
#include <asm/system.h>
#include <asm/io.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ciscode.h>
#include <pcmcia/ds.h>
@@ -586,11 +585,8 @@ static int btuart_probe(struct pcmcia_device *link)
info->p_dev = link;
link->priv = info;
- link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
- link->resource[0]->end = 8;
-
- link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.IntType = INT_MEMORY_AND_IO;
+ link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP |
+ CONF_AUTO_SET_IO;
return btuart_config(link);
}
@@ -604,43 +600,41 @@ static void btuart_detach(struct pcmcia_device *link)
kfree(info);
}
-static int btuart_check_config(struct pcmcia_device *p_dev,
- cistpl_cftable_entry_t *cf,
- cistpl_cftable_entry_t *dflt,
- unsigned int vcc,
- void *priv_data)
+static int btuart_check_config(struct pcmcia_device *p_dev, void *priv_data)
{
int *try = priv_data;
- p_dev->io_lines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK;
+ if (try == 0)
+ p_dev->io_lines = 16;
- if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
- p_dev->conf.Vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
- if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) &&
- (cf->io.win[0].base != 0)) {
- p_dev->resource[0]->start = cf->io.win[0].base;
- if (!pcmcia_request_io(p_dev))
- return 0;
- }
- return -ENODEV;
+ if ((p_dev->resource[0]->end != 8) || (p_dev->resource[0]->start == 0))
+ return -EINVAL;
+
+ p_dev->resource[0]->end = 8;
+ p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+ p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+
+ return pcmcia_request_io(p_dev);
}
static int btuart_check_config_notpicky(struct pcmcia_device *p_dev,
- cistpl_cftable_entry_t *cf,
- cistpl_cftable_entry_t *dflt,
- unsigned int vcc,
void *priv_data)
{
static unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
int j;
- if ((cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
- for (j = 0; j < 5; j++) {
- p_dev->resource[0]->start = base[j];
- p_dev->io_lines = base[j] ? 16 : 3;
- if (!pcmcia_request_io(p_dev))
- return 0;
- }
+ if (p_dev->io_lines > 3)
+ return -ENODEV;
+
+ p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+ p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+ p_dev->resource[0]->end = 8;
+
+ for (j = 0; j < 5; j++) {
+ p_dev->resource[0]->start = base[j];
+ p_dev->io_lines = base[j] ? 16 : 3;
+ if (!pcmcia_request_io(p_dev))
+ return 0;
}
return -ENODEV;
}
@@ -671,7 +665,7 @@ found_port:
if (i != 0)
goto failed;
- i = pcmcia_request_configuration(link, &link->conf);
+ i = pcmcia_enable_device(link);
if (i != 0)
goto failed;
@@ -703,9 +697,7 @@ MODULE_DEVICE_TABLE(pcmcia, btuart_ids);
static struct pcmcia_driver btuart_driver = {
.owner = THIS_MODULE,
- .drv = {
- .name = "btuart_cs",
- },
+ .name = "btuart_cs",
.probe = btuart_probe,
.remove = btuart_detach,
.id_table = btuart_ids,
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index d22ce3cc611e..d120a5c1c093 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -59,9 +59,15 @@ static struct usb_device_id btusb_table[] = {
/* Generic Bluetooth USB device */
{ USB_DEVICE_INFO(0xe0, 0x01, 0x01) },
+ /* Apple MacBookPro 7,1 */
+ { USB_DEVICE(0x05ac, 0x8213) },
+
/* Apple iMac11,1 */
{ USB_DEVICE(0x05ac, 0x8215) },
+ /* Apple MacBookPro6,2 */
+ { USB_DEVICE(0x05ac, 0x8218) },
+
/* AVM BlueFRITZ! USB v2.0 */
{ USB_DEVICE(0x057c, 0x3800) },
diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c
index db7c8db695fc..26ee0cf88d20 100644
--- a/drivers/bluetooth/dtl1_cs.c
+++ b/drivers/bluetooth/dtl1_cs.c
@@ -41,7 +41,6 @@
#include <asm/system.h>
#include <asm/io.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ciscode.h>
#include <pcmcia/ds.h>
@@ -572,11 +571,7 @@ static int dtl1_probe(struct pcmcia_device *link)
info->p_dev = link;
link->priv = info;
- link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
- link->resource[0]->end = 8;
-
- link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.IntType = INT_MEMORY_AND_IO;
+ link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
return dtl1_config(link);
}
@@ -591,18 +586,14 @@ static void dtl1_detach(struct pcmcia_device *link)
kfree(info);
}
-static int dtl1_confcheck(struct pcmcia_device *p_dev,
- cistpl_cftable_entry_t *cf,
- cistpl_cftable_entry_t *dflt,
- unsigned int vcc,
- void *priv_data)
+static int dtl1_confcheck(struct pcmcia_device *p_dev, void *priv_data)
{
- if ((cf->io.nwin != 1) || (cf->io.win[0].len <= 8))
+ if ((p_dev->resource[1]->end) || (p_dev->resource[1]->end < 8))
return -ENODEV;
- p_dev->resource[0]->start = cf->io.win[0].base;
- p_dev->resource[0]->end = cf->io.win[0].len; /*yo */
- p_dev->io_lines = cf->io.flags & CISTPL_IO_LINES_MASK;
+ p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+ p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+
return pcmcia_request_io(p_dev);
}
@@ -620,7 +611,7 @@ static int dtl1_config(struct pcmcia_device *link)
if (i != 0)
goto failed;
- i = pcmcia_request_configuration(link, &link->conf);
+ i = pcmcia_enable_device(link);
if (i != 0)
goto failed;
@@ -656,9 +647,7 @@ MODULE_DEVICE_TABLE(pcmcia, dtl1_ids);
static struct pcmcia_driver dtl1_driver = {
.owner = THIS_MODULE,
- .drv = {
- .name = "dtl1_cs",
- },
+ .name = "dtl1_cs",
.probe = dtl1_probe,
.remove = dtl1_detach,
.id_table = dtl1_ids,
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 998833d93c13..720148294e64 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -101,7 +101,7 @@ static inline void hci_uart_tx_complete(struct hci_uart *hu, int pkt_type)
break;
case HCI_SCODATA_PKT:
- hdev->stat.cmd_tx++;
+ hdev->stat.sco_tx++;
break;
}
}
@@ -256,9 +256,16 @@ static int hci_uart_tty_open(struct tty_struct *tty)
BT_DBG("tty %p", tty);
+ /* FIXME: This btw is bogus, nothing requires the old ldisc to clear
+ the pointer */
if (hu)
return -EEXIST;
+ /* Error if the tty has no write op instead of leaving an exploitable
+ hole */
+ if (tty->ops->write == NULL)
+ return -EOPNOTSUPP;
+
if (!(hu = kzalloc(sizeof(struct hci_uart), GFP_KERNEL))) {
BT_ERR("Can't allocate control structure");
return -ENFILE;
diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c
index 3aa7b2a54b6f..67c180c2c1e0 100644
--- a/drivers/bluetooth/hci_vhci.c
+++ b/drivers/bluetooth/hci_vhci.c
@@ -282,6 +282,7 @@ static const struct file_operations vhci_fops = {
.poll = vhci_poll,
.open = vhci_open,
.release = vhci_release,
+ .llseek = no_llseek,
};
static struct miscdevice vhci_miscdev= {
diff --git a/drivers/cdrom/gdrom.c b/drivers/cdrom/gdrom.c
index 261107d1457c..3af6516919b7 100644
--- a/drivers/cdrom/gdrom.c
+++ b/drivers/cdrom/gdrom.c
@@ -34,7 +34,7 @@
#include <linux/blkdev.h>
#include <linux/interrupt.h>
#include <linux/device.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/wait.h>
#include <linux/workqueue.h>
#include <linux/platform_device.h>
@@ -81,6 +81,7 @@
#define GDROM_DEFAULT_TIMEOUT (HZ * 7)
+static DEFINE_MUTEX(gdrom_mutex);
static const struct {
int sense_key;
const char * const text;
@@ -494,17 +495,17 @@ static struct cdrom_device_ops gdrom_ops = {
static int gdrom_bdops_open(struct block_device *bdev, fmode_t mode)
{
int ret;
- lock_kernel();
+ mutex_lock(&gdrom_mutex);
ret = cdrom_open(gd.cd_info, bdev, mode);
- unlock_kernel();
+ mutex_unlock(&gdrom_mutex);
return ret;
}
static int gdrom_bdops_release(struct gendisk *disk, fmode_t mode)
{
- lock_kernel();
+ mutex_lock(&gdrom_mutex);
cdrom_release(gd.cd_info, mode);
- unlock_kernel();
+ mutex_unlock(&gdrom_mutex);
return 0;
}
@@ -518,9 +519,9 @@ static int gdrom_bdops_ioctl(struct block_device *bdev, fmode_t mode,
{
int ret;
- lock_kernel();
+ mutex_lock(&gdrom_mutex);
ret = cdrom_ioctl(gd.cd_info, bdev, mode, cmd, arg);
- unlock_kernel();
+ mutex_unlock(&gdrom_mutex);
return ret;
}
diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c
index 56bf9f44700c..be73a9b493a6 100644
--- a/drivers/cdrom/viocd.c
+++ b/drivers/cdrom/viocd.c
@@ -42,7 +42,7 @@
#include <linux/module.h>
#include <linux/completion.h>
#include <linux/proc_fs.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/seq_file.h>
#include <linux/scatterlist.h>
@@ -61,6 +61,7 @@
*/
#define VIOCD_MAX_CD HVMAXARCHITECTEDVIRTUALCDROMS
+static DEFINE_MUTEX(viocd_mutex);
static const struct vio_error_entry viocd_err_table[] = {
{0x0201, EINVAL, "Invalid Range"},
{0x0202, EINVAL, "Invalid Token"},
@@ -156,9 +157,9 @@ static int viocd_blk_open(struct block_device *bdev, fmode_t mode)
struct disk_info *di = bdev->bd_disk->private_data;
int ret;
- lock_kernel();
+ mutex_lock(&viocd_mutex);
ret = cdrom_open(&di->viocd_info, bdev, mode);
- unlock_kernel();
+ mutex_unlock(&viocd_mutex);
return ret;
}
@@ -166,9 +167,9 @@ static int viocd_blk_open(struct block_device *bdev, fmode_t mode)
static int viocd_blk_release(struct gendisk *disk, fmode_t mode)
{
struct disk_info *di = disk->private_data;
- lock_kernel();
+ mutex_lock(&viocd_mutex);
cdrom_release(&di->viocd_info, mode);
- unlock_kernel();
+ mutex_unlock(&viocd_mutex);
return 0;
}
@@ -178,9 +179,9 @@ static int viocd_blk_ioctl(struct block_device *bdev, fmode_t mode,
struct disk_info *di = bdev->bd_disk->private_data;
int ret;
- lock_kernel();
+ mutex_lock(&viocd_mutex);
ret = cdrom_ioctl(&di->viocd_info, bdev, mode, cmd, arg);
- unlock_kernel();
+ mutex_unlock(&viocd_mutex);
return ret;
}
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 3d44ec724c17..43d3395325c5 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -493,6 +493,21 @@ config LEGACY_PTY_COUNT
When not in use, each legacy PTY occupies 12 bytes on 32-bit
architectures and 24 bytes on 64-bit architectures.
+config TTY_PRINTK
+ bool "TTY driver to output user messages via printk"
+ depends on EMBEDDED
+ default n
+ ---help---
+ If you say Y here, the support for writing user messages (i.e.
+ console messages) via printk is available.
+
+ The feature is useful to inline user messages with kernel
+ messages.
+ In order to use this feature, you should output user messages
+ to /dev/ttyprintk or redirect console to this TTY.
+
+ If unsure, say N.
+
config BRIQ_PANEL
tristate 'Total Impact briQ front panel driver'
depends on PPC_CHRP
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index dc9641660605..3a9c01416839 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -12,6 +12,7 @@ obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o tty_buffer.o t
obj-y += tty_mutex.o
obj-$(CONFIG_LEGACY_PTYS) += pty.o
obj-$(CONFIG_UNIX98_PTYS) += pty.o
+obj-$(CONFIG_TTY_PRINTK) += ttyprintk.o
obj-y += misc.o
obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o selection.o keyboard.o
obj-$(CONFIG_BFIN_JTAG_COMM) += bfin_jtag_comm.o
diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig
index 4b66c69eaf57..5ddf67e76f8b 100644
--- a/drivers/char/agp/Kconfig
+++ b/drivers/char/agp/Kconfig
@@ -57,7 +57,7 @@ config AGP_AMD
config AGP_AMD64
tristate "AMD Opteron/Athlon64 on-CPU GART support"
- depends on AGP && X86 && K8_NB
+ depends on AGP && X86 && AMD_NB
help
This option gives you AGP support for the GLX component of
X using the on-CPU northbridge of the AMD Athlon64/Opteron CPUs.
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index 70312da4c968..42396df55556 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -15,7 +15,7 @@
#include <linux/mmzone.h>
#include <asm/page.h> /* PAGE_SIZE */
#include <asm/e820.h>
-#include <asm/k8.h>
+#include <asm/amd_nb.h>
#include <asm/gart.h>
#include "agp.h"
@@ -124,7 +124,7 @@ static int amd64_fetch_size(void)
u32 temp;
struct aper_size_info_32 *values;
- dev = k8_northbridges[0];
+ dev = k8_northbridges.nb_misc[0];
if (dev==NULL)
return 0;
@@ -181,10 +181,14 @@ static int amd_8151_configure(void)
unsigned long gatt_bus = virt_to_phys(agp_bridge->gatt_table_real);
int i;
+ if (!k8_northbridges.gart_supported)
+ return 0;
+
/* Configure AGP regs in each x86-64 host bridge. */
- for (i = 0; i < num_k8_northbridges; i++) {
+ for (i = 0; i < k8_northbridges.num; i++) {
agp_bridge->gart_bus_addr =
- amd64_configure(k8_northbridges[i], gatt_bus);
+ amd64_configure(k8_northbridges.nb_misc[i],
+ gatt_bus);
}
k8_flush_garts();
return 0;
@@ -195,11 +199,15 @@ static void amd64_cleanup(void)
{
u32 tmp;
int i;
- for (i = 0; i < num_k8_northbridges; i++) {
- struct pci_dev *dev = k8_northbridges[i];
+
+ if (!k8_northbridges.gart_supported)
+ return;
+
+ for (i = 0; i < k8_northbridges.num; i++) {
+ struct pci_dev *dev = k8_northbridges.nb_misc[i];
/* disable gart translation */
pci_read_config_dword(dev, AMD64_GARTAPERTURECTL, &tmp);
- tmp &= ~AMD64_GARTEN;
+ tmp &= ~GARTEN;
pci_write_config_dword(dev, AMD64_GARTAPERTURECTL, tmp);
}
}
@@ -313,22 +321,25 @@ static __devinit int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp,
if (order < 0 || !agp_aperture_valid(aper, (32*1024*1024)<<order))
return -1;
- pci_write_config_dword(nb, AMD64_GARTAPERTURECTL, order << 1);
+ gart_set_size_and_enable(nb, order);
pci_write_config_dword(nb, AMD64_GARTAPERTUREBASE, aper >> 25);
return 0;
}
-static __devinit int cache_nbs (struct pci_dev *pdev, u32 cap_ptr)
+static __devinit int cache_nbs(struct pci_dev *pdev, u32 cap_ptr)
{
int i;
if (cache_k8_northbridges() < 0)
return -ENODEV;
+ if (!k8_northbridges.gart_supported)
+ return -ENODEV;
+
i = 0;
- for (i = 0; i < num_k8_northbridges; i++) {
- struct pci_dev *dev = k8_northbridges[i];
+ for (i = 0; i < k8_northbridges.num; i++) {
+ struct pci_dev *dev = k8_northbridges.nb_misc[i];
if (fix_northbridge(dev, pdev, cap_ptr) < 0) {
dev_err(&dev->dev, "no usable aperture found\n");
#ifdef __x86_64__
@@ -405,7 +416,8 @@ static int __devinit uli_agp_init(struct pci_dev *pdev)
}
/* shadow x86-64 registers into ULi registers */
- pci_read_config_dword (k8_northbridges[0], AMD64_GARTAPERTUREBASE, &httfea);
+ pci_read_config_dword (k8_northbridges.nb_misc[0], AMD64_GARTAPERTUREBASE,
+ &httfea);
/* if x86-64 aperture base is beyond 4G, exit here */
if ((httfea & 0x7fff) >> (32 - 25)) {
@@ -472,7 +484,8 @@ static int nforce3_agp_init(struct pci_dev *pdev)
pci_write_config_dword(dev1, NVIDIA_X86_64_1_APSIZE, tmp);
/* shadow x86-64 registers into NVIDIA registers */
- pci_read_config_dword (k8_northbridges[0], AMD64_GARTAPERTUREBASE, &apbase);
+ pci_read_config_dword (k8_northbridges.nb_misc[0], AMD64_GARTAPERTUREBASE,
+ &apbase);
/* if x86-64 aperture base is beyond 4G, exit here */
if ( (apbase & 0x7fff) >> (32 - 25) ) {
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
index d2abf5143983..64255cef8a7d 100644
--- a/drivers/char/agp/generic.c
+++ b/drivers/char/agp/generic.c
@@ -984,7 +984,9 @@ int agp_generic_create_gatt_table(struct agp_bridge_data *bridge)
bridge->driver->cache_flush();
#ifdef CONFIG_X86
- set_memory_uc((unsigned long)table, 1 << page_order);
+ if (set_memory_uc((unsigned long)table, 1 << page_order))
+ printk(KERN_WARNING "Could not set GATT table memory to UC!");
+
bridge->gatt_table = (void *)table;
#else
bridge->gatt_table = ioremap_nocache(virt_to_phys(table),
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c
index a11c8c9ca3d4..b0a70461a12c 100644
--- a/drivers/char/amiserial.c
+++ b/drivers/char/amiserial.c
@@ -1263,6 +1263,36 @@ static int rs_break(struct tty_struct *tty, int break_state)
return 0;
}
+/*
+ * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
+ * Return: write counters to the user passed counter struct
+ * NB: both 1->0 and 0->1 transitions are counted except for
+ * RI where only 0->1 is counted.
+ */
+static int rs_get_icount(struct tty_struct *tty,
+ struct serial_icounter_struct *icount)
+{
+ struct async_struct *info = tty->driver_data;
+ struct async_icount cnow;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ cnow = info->state->icount;
+ local_irq_restore(flags);
+ icount->cts = cnow.cts;
+ icount->dsr = cnow.dsr;
+ icount->rng = cnow.rng;
+ icount->dcd = cnow.dcd;
+ icount->rx = cnow.rx;
+ icount->tx = cnow.tx;
+ icount->frame = cnow.frame;
+ icount->overrun = cnow.overrun;
+ icount->parity = cnow.parity;
+ icount->brk = cnow.brk;
+ icount->buf_overrun = cnow.buf_overrun;
+
+ return 0;
+}
static int rs_ioctl(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg)
@@ -1332,31 +1362,6 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
}
/* NOTREACHED */
- /*
- * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
- * Return: write counters to the user passed counter struct
- * NB: both 1->0 and 0->1 transitions are counted except for
- * RI where only 0->1 is counted.
- */
- case TIOCGICOUNT:
- local_irq_save(flags);
- cnow = info->state->icount;
- local_irq_restore(flags);
- icount.cts = cnow.cts;
- icount.dsr = cnow.dsr;
- icount.rng = cnow.rng;
- icount.dcd = cnow.dcd;
- icount.rx = cnow.rx;
- icount.tx = cnow.tx;
- icount.frame = cnow.frame;
- icount.overrun = cnow.overrun;
- icount.parity = cnow.parity;
- icount.brk = cnow.brk;
- icount.buf_overrun = cnow.buf_overrun;
-
- if (copy_to_user(argp, &icount, sizeof(icount)))
- return -EFAULT;
- return 0;
case TIOCSERGWILD:
case TIOCSERSWILD:
/* "setserial -W" is called in Debian boot */
@@ -1958,6 +1963,7 @@ static const struct tty_operations serial_ops = {
.wait_until_sent = rs_wait_until_sent,
.tiocmget = rs_tiocmget,
.tiocmset = rs_tiocmset,
+ .get_icount = rs_get_icount,
.proc_fops = &rs_proc_fops,
};
diff --git a/drivers/char/apm-emulation.c b/drivers/char/apm-emulation.c
index 033e1505fca9..3022801669b1 100644
--- a/drivers/char/apm-emulation.c
+++ b/drivers/char/apm-emulation.c
@@ -13,7 +13,7 @@
#include <linux/module.h>
#include <linux/poll.h>
#include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/miscdevice.h>
@@ -126,6 +126,7 @@ struct apm_user {
/*
* Local variables
*/
+static DEFINE_MUTEX(apm_mutex);
static atomic_t suspend_acks_pending = ATOMIC_INIT(0);
static atomic_t userspace_notification_inhibit = ATOMIC_INIT(0);
static int apm_disabled;
@@ -274,7 +275,7 @@ apm_ioctl(struct file *filp, u_int cmd, u_long arg)
if (!as->suser || !as->writer)
return -EPERM;
- lock_kernel();
+ mutex_lock(&apm_mutex);
switch (cmd) {
case APM_IOC_SUSPEND:
mutex_lock(&state_lock);
@@ -335,7 +336,7 @@ apm_ioctl(struct file *filp, u_int cmd, u_long arg)
mutex_unlock(&state_lock);
break;
}
- unlock_kernel();
+ mutex_unlock(&apm_mutex);
return err;
}
@@ -370,7 +371,7 @@ static int apm_open(struct inode * inode, struct file * filp)
{
struct apm_user *as;
- lock_kernel();
+ mutex_lock(&apm_mutex);
as = kzalloc(sizeof(*as), GFP_KERNEL);
if (as) {
/*
@@ -390,7 +391,7 @@ static int apm_open(struct inode * inode, struct file * filp)
filp->private_data = as;
}
- unlock_kernel();
+ mutex_unlock(&apm_mutex);
return as ? 0 : -ENOMEM;
}
@@ -402,6 +403,7 @@ static const struct file_operations apm_bios_fops = {
.unlocked_ioctl = apm_ioctl,
.open = apm_open,
.release = apm_release,
+ .llseek = noop_llseek,
};
static struct miscdevice apm_device = {
diff --git a/drivers/char/applicom.c b/drivers/char/applicom.c
index f4ae0e0fb631..e7ba774beda6 100644
--- a/drivers/char/applicom.c
+++ b/drivers/char/applicom.c
@@ -26,7 +26,7 @@
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/errno.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/miscdevice.h>
#include <linux/pci.h>
#include <linux/wait.h>
@@ -60,6 +60,7 @@
#define PCI_DEVICE_ID_APPLICOM_PCI2000PFB 0x0003
#endif
+static DEFINE_MUTEX(ac_mutex);
static char *applicom_pci_devnames[] = {
"PCI board",
"PCI2000IBS / PCI2000CAN",
@@ -707,7 +708,7 @@ static long ac_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
if (IS_ERR(adgl))
return PTR_ERR(adgl);
- lock_kernel();
+ mutex_lock(&ac_mutex);
IndexCard = adgl->num_card-1;
if(cmd != 6 && ((IndexCard >= MAX_BOARD) || !apbs[IndexCard].RamIO)) {
@@ -717,7 +718,7 @@ static long ac_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
warncount--;
}
kfree(adgl);
- unlock_kernel();
+ mutex_unlock(&ac_mutex);
return -EINVAL;
}
@@ -835,7 +836,7 @@ static long ac_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
}
Dummy = readb(apbs[IndexCard].RamIO + VERS);
kfree(adgl);
- unlock_kernel();
+ mutex_unlock(&ac_mutex);
return 0;
}
diff --git a/drivers/char/bfin-otp.c b/drivers/char/bfin-otp.c
index 836d4f0a876f..44660f1c4849 100644
--- a/drivers/char/bfin-otp.c
+++ b/drivers/char/bfin-otp.c
@@ -222,6 +222,7 @@ static const struct file_operations bfin_otp_fops = {
.unlocked_ioctl = bfin_otp_ioctl,
.read = bfin_otp_read,
.write = bfin_otp_write,
+ .llseek = default_llseek,
};
static struct miscdevice bfin_otp_misc_device = {
diff --git a/drivers/char/briq_panel.c b/drivers/char/briq_panel.c
index d5fa113afe37..f6718f05dad4 100644
--- a/drivers/char/briq_panel.c
+++ b/drivers/char/briq_panel.c
@@ -186,6 +186,7 @@ static const struct file_operations briq_panel_fops = {
.write = briq_panel_write,
.open = briq_panel_open,
.release = briq_panel_release,
+ .llseek = noop_llseek,
};
static struct miscdevice briq_panel_miscdev = {
diff --git a/drivers/char/bsr.c b/drivers/char/bsr.c
index 91917133ae0a..a4a6c2f044b5 100644
--- a/drivers/char/bsr.c
+++ b/drivers/char/bsr.c
@@ -155,6 +155,7 @@ static const struct file_operations bsr_fops = {
.owner = THIS_MODULE,
.mmap = bsr_mmap,
.open = bsr_open,
+ .llseek = noop_llseek,
};
static void bsr_cleanup_devs(void)
diff --git a/drivers/char/cs5535_gpio.c b/drivers/char/cs5535_gpio.c
index 4d830dc482ef..0cf1e5fad9ab 100644
--- a/drivers/char/cs5535_gpio.c
+++ b/drivers/char/cs5535_gpio.c
@@ -169,7 +169,8 @@ static const struct file_operations cs5535_gpio_fops = {
.owner = THIS_MODULE,
.write = cs5535_gpio_write,
.read = cs5535_gpio_read,
- .open = cs5535_gpio_open
+ .open = cs5535_gpio_open,
+ .llseek = no_llseek,
};
static int __init cs5535_gpio_init(void)
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index 27aad9422332..4f152c28f40e 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -2790,29 +2790,6 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
* NB: both 1->0 and 0->1 transitions are counted except for
* RI where only 0->1 is counted.
*/
- case TIOCGICOUNT: {
- struct serial_icounter_struct sic = { };
-
- spin_lock_irqsave(&info->card->card_lock, flags);
- cnow = info->icount;
- spin_unlock_irqrestore(&info->card->card_lock, flags);
-
- sic.cts = cnow.cts;
- sic.dsr = cnow.dsr;
- sic.rng = cnow.rng;
- sic.dcd = cnow.dcd;
- sic.rx = cnow.rx;
- sic.tx = cnow.tx;
- sic.frame = cnow.frame;
- sic.overrun = cnow.overrun;
- sic.parity = cnow.parity;
- sic.brk = cnow.brk;
- sic.buf_overrun = cnow.buf_overrun;
-
- if (copy_to_user(argp, &sic, sizeof(sic)))
- ret_val = -EFAULT;
- break;
- }
default:
ret_val = -ENOIOCTLCMD;
}
@@ -2823,6 +2800,31 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
return ret_val;
} /* cy_ioctl */
+static int cy_get_icount(struct tty_struct *tty,
+ struct serial_icounter_struct *sic)
+{
+ struct cyclades_port *info = tty->driver_data;
+ struct cyclades_icount cnow; /* Used to snapshot */
+ unsigned long flags;
+
+ spin_lock_irqsave(&info->card->card_lock, flags);
+ cnow = info->icount;
+ spin_unlock_irqrestore(&info->card->card_lock, flags);
+
+ sic->cts = cnow.cts;
+ sic->dsr = cnow.dsr;
+ sic->rng = cnow.rng;
+ sic->dcd = cnow.dcd;
+ sic->rx = cnow.rx;
+ sic->tx = cnow.tx;
+ sic->frame = cnow.frame;
+ sic->overrun = cnow.overrun;
+ sic->parity = cnow.parity;
+ sic->brk = cnow.brk;
+ sic->buf_overrun = cnow.buf_overrun;
+ return 0;
+}
+
/*
* This routine allows the tty driver to be notified when
* device's termios settings have changed. Note that a
@@ -4084,6 +4086,7 @@ static const struct tty_operations cy_ops = {
.wait_until_sent = cy_wait_until_sent,
.tiocmget = cy_tiocmget,
.tiocmset = cy_tiocmset,
+ .get_icount = cy_get_icount,
.proc_fops = &cyclades_proc_fops,
};
diff --git a/drivers/char/ds1302.c b/drivers/char/ds1302.c
index 170693c93c73..ed8303f9890c 100644
--- a/drivers/char/ds1302.c
+++ b/drivers/char/ds1302.c
@@ -20,7 +20,7 @@
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <linux/bcd.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/uaccess.h>
#include <linux/io.h>
@@ -32,6 +32,7 @@
#define RTC_MAJOR_NR 121 /* local major, change later */
+static DEFINE_MUTEX(rtc_mutex);
static const char ds1302_name[] = "ds1302";
/* Send 8 bits. */
@@ -164,9 +165,9 @@ static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
struct rtc_time rtc_tm;
memset(&rtc_tm, 0, sizeof (struct rtc_time));
- lock_kernel();
+ mutex_lock(&rtc_mutex);
get_rtc_time(&rtc_tm);
- unlock_kernel();
+ mutex_unlock(&rtc_mutex);
if (copy_to_user((struct rtc_time*)arg, &rtc_tm, sizeof(struct rtc_time)))
return -EFAULT;
return 0;
@@ -218,7 +219,7 @@ static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
mon = bin2bcd(mon);
yrs = bin2bcd(yrs);
- lock_kernel();
+ mutex_lock(&rtc_mutex);
local_irq_save(flags);
CMOS_WRITE(yrs, RTC_YEAR);
CMOS_WRITE(mon, RTC_MONTH);
@@ -227,7 +228,7 @@ static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
CMOS_WRITE(min, RTC_MINUTES);
CMOS_WRITE(sec, RTC_SECONDS);
local_irq_restore(flags);
- unlock_kernel();
+ mutex_unlock(&rtc_mutex);
/* Notice that at this point, the RTC is updated but
* the kernel is still running with the old time.
@@ -247,10 +248,10 @@ static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
if(copy_from_user(&tcs_val, (int*)arg, sizeof(int)))
return -EFAULT;
- lock_kernel();
+ mutex_lock(&rtc_mutex);
tcs_val = RTC_TCR_PATTERN | (tcs_val & 0x0F);
ds1302_writereg(RTC_TRICKLECHARGER, tcs_val);
- unlock_kernel();
+ mutex_unlock(&rtc_mutex);
return 0;
}
default:
@@ -288,6 +289,7 @@ get_rtc_status(char *buf)
static const struct file_operations rtc_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = rtc_ioctl,
+ .llseek = noop_llseek,
};
/* Probe for the chip by writing something to its RAM and try reading it back. */
diff --git a/drivers/char/ds1620.c b/drivers/char/ds1620.c
index dbee8688f75c..aab9605f0b43 100644
--- a/drivers/char/ds1620.c
+++ b/drivers/char/ds1620.c
@@ -8,7 +8,7 @@
#include <linux/proc_fs.h>
#include <linux/capability.h>
#include <linux/init.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <mach/hardware.h>
#include <asm/mach-types.h>
@@ -34,6 +34,7 @@
#define CFG_CPU 2
#define CFG_1SHOT 1
+static DEFINE_MUTEX(ds1620_mutex);
static const char *fan_state[] = { "off", "on", "on (hardwired)" };
/*
@@ -210,7 +211,6 @@ static void ds1620_read_state(struct therm *therm)
static int ds1620_open(struct inode *inode, struct file *file)
{
- cycle_kernel_lock();
return nonseekable_open(inode, file);
}
@@ -321,9 +321,9 @@ ds1620_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
int ret;
- lock_kernel();
+ mutex_lock(&ds1620_mutex);
ret = ds1620_ioctl(file, cmd, arg);
- unlock_kernel();
+ mutex_unlock(&ds1620_mutex);
return ret;
}
@@ -357,6 +357,7 @@ static const struct file_operations ds1620_fops = {
.open = ds1620_open,
.read = ds1620_read,
.unlocked_ioctl = ds1620_unlocked_ioctl,
+ .llseek = no_llseek,
};
static struct miscdevice ds1620_miscdev = {
diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c
index 8a1b28a10ef0..052797b32bd3 100644
--- a/drivers/char/dsp56k.c
+++ b/drivers/char/dsp56k.c
@@ -32,7 +32,7 @@
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/device.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/firmware.h>
#include <linux/platform_device.h>
#include <linux/uaccess.h> /* For put_user and get_user */
@@ -94,6 +94,7 @@
} \
}
+static DEFINE_MUTEX(dsp56k_mutex);
static struct dsp56k_device {
unsigned long in_use;
long maxio, timeout;
@@ -330,9 +331,9 @@ static long dsp56k_ioctl(struct file *file, unsigned int cmd,
if (len > DSP56K_MAX_BINARY_LENGTH) {
return -EINVAL;
}
- lock_kernel();
+ mutex_lock(&dsp56k_mutex);
r = dsp56k_upload(bin, len);
- unlock_kernel();
+ mutex_unlock(&dsp56k_mutex);
if (r < 0) {
return r;
}
@@ -342,16 +343,16 @@ static long dsp56k_ioctl(struct file *file, unsigned int cmd,
case DSP56K_SET_TX_WSIZE:
if (arg > 4 || arg < 1)
return -EINVAL;
- lock_kernel();
+ mutex_lock(&dsp56k_mutex);
dsp56k.tx_wsize = (int) arg;
- unlock_kernel();
+ mutex_unlock(&dsp56k_mutex);
break;
case DSP56K_SET_RX_WSIZE:
if (arg > 4 || arg < 1)
return -EINVAL;
- lock_kernel();
+ mutex_lock(&dsp56k_mutex);
dsp56k.rx_wsize = (int) arg;
- unlock_kernel();
+ mutex_unlock(&dsp56k_mutex);
break;
case DSP56K_HOST_FLAGS:
{
@@ -363,7 +364,7 @@ static long dsp56k_ioctl(struct file *file, unsigned int cmd,
if(get_user(out, &hf->out) < 0)
return -EFAULT;
- lock_kernel();
+ mutex_lock(&dsp56k_mutex);
if ((dir & 0x1) && (out & 0x1))
dsp56k_host_interface.icr |= DSP56K_ICR_HF0;
else if (dir & 0x1)
@@ -378,16 +379,16 @@ static long dsp56k_ioctl(struct file *file, unsigned int cmd,
if (dsp56k_host_interface.icr & DSP56K_ICR_HF1) status |= 0x2;
if (dsp56k_host_interface.isr & DSP56K_ISR_HF2) status |= 0x4;
if (dsp56k_host_interface.isr & DSP56K_ISR_HF3) status |= 0x8;
- unlock_kernel();
+ mutex_unlock(&dsp56k_mutex);
return put_user(status, &hf->status);
}
case DSP56K_HOST_CMD:
if (arg > 31 || arg < 0)
return -EINVAL;
- lock_kernel();
+ mutex_lock(&dsp56k_mutex);
dsp56k_host_interface.cvr = (u_char)((arg & DSP56K_CVR_HV_MASK) |
DSP56K_CVR_HC);
- unlock_kernel();
+ mutex_unlock(&dsp56k_mutex);
break;
default:
return -EINVAL;
@@ -427,7 +428,7 @@ static int dsp56k_open(struct inode *inode, struct file *file)
int dev = iminor(inode) & 0x0f;
int ret = 0;
- lock_kernel();
+ mutex_lock(&dsp56k_mutex);
switch(dev)
{
case DSP56K_DEV_56001:
@@ -454,7 +455,7 @@ static int dsp56k_open(struct inode *inode, struct file *file)
ret = -ENODEV;
}
out:
- unlock_kernel();
+ mutex_unlock(&dsp56k_mutex);
return ret;
}
@@ -482,6 +483,7 @@ static const struct file_operations dsp56k_fops = {
.unlocked_ioctl = dsp56k_ioctl,
.open = dsp56k_open,
.release = dsp56k_release,
+ .llseek = noop_llseek,
};
diff --git a/drivers/char/dtlk.c b/drivers/char/dtlk.c
index e3859d4eaead..85156dd0caee 100644
--- a/drivers/char/dtlk.c
+++ b/drivers/char/dtlk.c
@@ -57,7 +57,7 @@
#include <linux/ioport.h> /* for request_region */
#include <linux/delay.h> /* for loops_per_jiffy */
#include <linux/sched.h>
-#include <linux/smp_lock.h> /* cycle_kernel_lock() */
+#include <linux/mutex.h>
#include <asm/io.h> /* for inb_p, outb_p, inb, outb, etc. */
#include <asm/uaccess.h> /* for get_user, etc. */
#include <linux/wait.h> /* for wait_queue */
@@ -73,6 +73,7 @@
#define TRACE_RET ((void) 0)
#endif /* TRACING */
+static DEFINE_MUTEX(dtlk_mutex);
static void dtlk_timer_tick(unsigned long data);
static int dtlk_major;
@@ -105,6 +106,7 @@ static const struct file_operations dtlk_fops =
.unlocked_ioctl = dtlk_ioctl,
.open = dtlk_open,
.release = dtlk_release,
+ .llseek = no_llseek,
};
/* local prototypes */
@@ -275,9 +277,9 @@ static long dtlk_ioctl(struct file *file,
switch (cmd) {
case DTLK_INTERROGATE:
- lock_kernel();
+ mutex_lock(&dtlk_mutex);
sp = dtlk_interrogate();
- unlock_kernel();
+ mutex_unlock(&dtlk_mutex);
if (copy_to_user(argp, sp, sizeof(struct dtlk_settings)))
return -EINVAL;
return 0;
@@ -296,7 +298,6 @@ static int dtlk_open(struct inode *inode, struct file *file)
{
TRACE_TEXT("(dtlk_open");
- cycle_kernel_lock();
nonseekable_open(inode, file);
switch (iminor(inode)) {
case DTLK_MINOR:
diff --git a/drivers/char/generic_nvram.c b/drivers/char/generic_nvram.c
index 82b5a88a82d7..0e941b57482e 100644
--- a/drivers/char/generic_nvram.c
+++ b/drivers/char/generic_nvram.c
@@ -19,7 +19,7 @@
#include <linux/miscdevice.h>
#include <linux/fcntl.h>
#include <linux/init.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <asm/uaccess.h>
#include <asm/nvram.h>
#ifdef CONFIG_PPC_PMAC
@@ -28,6 +28,7 @@
#define NVRAM_SIZE 8192
+static DEFINE_MUTEX(nvram_mutex);
static ssize_t nvram_len;
static loff_t nvram_llseek(struct file *file, loff_t offset, int origin)
@@ -120,9 +121,9 @@ static long nvram_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned l
{
int ret;
- lock_kernel();
+ mutex_lock(&nvram_mutex);
ret = nvram_ioctl(file, cmd, arg);
- unlock_kernel();
+ mutex_unlock(&nvram_mutex);
return ret;
}
diff --git a/drivers/char/genrtc.c b/drivers/char/genrtc.c
index b6c2cc167c11..f773a9dd14f3 100644
--- a/drivers/char/genrtc.c
+++ b/drivers/char/genrtc.c
@@ -52,7 +52,7 @@
#include <linux/init.h>
#include <linux/poll.h>
#include <linux/proc_fs.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/workqueue.h>
#include <asm/uaccess.h>
@@ -66,6 +66,7 @@
* ioctls.
*/
+static DEFINE_MUTEX(gen_rtc_mutex);
static DECLARE_WAIT_QUEUE_HEAD(gen_rtc_wait);
/*
@@ -337,9 +338,9 @@ static long gen_rtc_unlocked_ioctl(struct file *file, unsigned int cmd,
{
int ret;
- lock_kernel();
+ mutex_lock(&gen_rtc_mutex);
ret = gen_rtc_ioctl(file, cmd, arg);
- unlock_kernel();
+ mutex_unlock(&gen_rtc_mutex);
return ret;
}
@@ -352,16 +353,16 @@ static long gen_rtc_unlocked_ioctl(struct file *file, unsigned int cmd,
static int gen_rtc_open(struct inode *inode, struct file *file)
{
- lock_kernel();
+ mutex_lock(&gen_rtc_mutex);
if (gen_rtc_status & RTC_IS_OPEN) {
- unlock_kernel();
+ mutex_unlock(&gen_rtc_mutex);
return -EBUSY;
}
gen_rtc_status |= RTC_IS_OPEN;
gen_rtc_irq_data = 0;
irq_active = 0;
- unlock_kernel();
+ mutex_unlock(&gen_rtc_mutex);
return 0;
}
@@ -497,6 +498,7 @@ static const struct file_operations gen_rtc_fops = {
.unlocked_ioctl = gen_rtc_unlocked_ioctl,
.open = gen_rtc_open,
.release = gen_rtc_release,
+ .llseek = noop_llseek,
};
static struct miscdevice rtc_gen_dev =
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index a0a1829d3198..a4eee324eb1e 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -30,6 +30,7 @@
#include <linux/bcd.h>
#include <linux/seq_file.h>
#include <linux/bitops.h>
+#include <linux/compat.h>
#include <linux/clocksource.h>
#include <linux/slab.h>
@@ -67,6 +68,7 @@
#define read_counter(MC) readl(MC)
#endif
+static DEFINE_MUTEX(hpet_mutex); /* replaces BKL */
static u32 hpet_nhpet, hpet_max_freq = HPET_USER_FREQ;
/* This clocksource driver currently only works on ia64 */
@@ -250,7 +252,7 @@ static int hpet_open(struct inode *inode, struct file *file)
if (file->f_mode & FMODE_WRITE)
return -EINVAL;
- lock_kernel();
+ mutex_lock(&hpet_mutex);
spin_lock_irq(&hpet_lock);
for (devp = NULL, hpetp = hpets; hpetp && !devp; hpetp = hpetp->hp_next)
@@ -264,7 +266,7 @@ static int hpet_open(struct inode *inode, struct file *file)
if (!devp) {
spin_unlock_irq(&hpet_lock);
- unlock_kernel();
+ mutex_unlock(&hpet_mutex);
return -EBUSY;
}
@@ -272,7 +274,7 @@ static int hpet_open(struct inode *inode, struct file *file)
devp->hd_irqdata = 0;
devp->hd_flags |= HPET_OPEN;
spin_unlock_irq(&hpet_lock);
- unlock_kernel();
+ mutex_unlock(&hpet_mutex);
hpet_timer_set_irq(devp);
@@ -429,22 +431,6 @@ static int hpet_release(struct inode *inode, struct file *file)
return 0;
}
-static int hpet_ioctl_common(struct hpet_dev *, int, unsigned long, int);
-
-static long hpet_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- struct hpet_dev *devp;
- int ret;
-
- devp = file->private_data;
- lock_kernel();
- ret = hpet_ioctl_common(devp, cmd, arg, 0);
- unlock_kernel();
-
- return ret;
-}
-
static int hpet_ioctl_ieon(struct hpet_dev *devp)
{
struct hpet_timer __iomem *timer;
@@ -553,7 +539,8 @@ static inline unsigned long hpet_time_div(struct hpets *hpets,
}
static int
-hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg, int kernel)
+hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg,
+ struct hpet_info *info)
{
struct hpet_timer __iomem *timer;
struct hpet __iomem *hpet;
@@ -594,23 +581,15 @@ hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg, int kernel)
break;
case HPET_INFO:
{
- struct hpet_info info;
-
if (devp->hd_ireqfreq)
- info.hi_ireqfreq =
+ info->hi_ireqfreq =
hpet_time_div(hpetp, devp->hd_ireqfreq);
else
- info.hi_ireqfreq = 0;
- info.hi_flags =
+ info->hi_ireqfreq = 0;
+ info->hi_flags =
readq(&timer->hpet_config) & Tn_PER_INT_CAP_MASK;
- info.hi_hpet = hpetp->hp_which;
- info.hi_timer = devp - hpetp->hp_dev;
- if (kernel)
- memcpy((void *)arg, &info, sizeof(info));
- else
- if (copy_to_user((void __user *)arg, &info,
- sizeof(info)))
- err = -EFAULT;
+ info->hi_hpet = hpetp->hp_which;
+ info->hi_timer = devp - hpetp->hp_dev;
break;
}
case HPET_EPI:
@@ -636,7 +615,7 @@ hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg, int kernel)
devp->hd_flags &= ~HPET_PERIODIC;
break;
case HPET_IRQFREQ:
- if (!kernel && (arg > hpet_max_freq) &&
+ if ((arg > hpet_max_freq) &&
!capable(CAP_SYS_RESOURCE)) {
err = -EACCES;
break;
@@ -653,12 +632,63 @@ hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg, int kernel)
return err;
}
+static long
+hpet_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct hpet_info info;
+ int err;
+
+ mutex_lock(&hpet_mutex);
+ err = hpet_ioctl_common(file->private_data, cmd, arg, &info);
+ mutex_unlock(&hpet_mutex);
+
+ if ((cmd == HPET_INFO) && !err &&
+ (copy_to_user((void __user *)arg, &info, sizeof(info))))
+ err = -EFAULT;
+
+ return err;
+}
+
+#ifdef CONFIG_COMPAT
+struct compat_hpet_info {
+ compat_ulong_t hi_ireqfreq; /* Hz */
+ compat_ulong_t hi_flags; /* information */
+ unsigned short hi_hpet;
+ unsigned short hi_timer;
+};
+
+static long
+hpet_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct hpet_info info;
+ int err;
+
+ mutex_lock(&hpet_mutex);
+ err = hpet_ioctl_common(file->private_data, cmd, arg, &info);
+ mutex_unlock(&hpet_mutex);
+
+ if ((cmd == HPET_INFO) && !err) {
+ struct compat_hpet_info __user *u = compat_ptr(arg);
+ if (put_user(info.hi_ireqfreq, &u->hi_ireqfreq) ||
+ put_user(info.hi_flags, &u->hi_flags) ||
+ put_user(info.hi_hpet, &u->hi_hpet) ||
+ put_user(info.hi_timer, &u->hi_timer))
+ err = -EFAULT;
+ }
+
+ return err;
+}
+#endif
+
static const struct file_operations hpet_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.read = hpet_read,
.poll = hpet_poll,
.unlocked_ioctl = hpet_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = hpet_compat_ioctl,
+#endif
.open = hpet_open,
.release = hpet_release,
.fasync = hpet_fasync,
diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c
index 3d9c61e5acbf..788da05190cc 100644
--- a/drivers/char/hw_random/core.c
+++ b/drivers/char/hw_random/core.c
@@ -170,6 +170,7 @@ static const struct file_operations rng_chrdev_ops = {
.owner = THIS_MODULE,
.open = rng_dev_open,
.read = rng_dev_read,
+ .llseek = noop_llseek,
};
static struct miscdevice rng_miscdev = {
diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c
index 4cd8b227c11f..3bc0eef88717 100644
--- a/drivers/char/i8k.c
+++ b/drivers/char/i8k.c
@@ -23,7 +23,7 @@
#include <linux/seq_file.h>
#include <linux/dmi.h>
#include <linux/capability.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -56,6 +56,7 @@
#define I8K_TEMPERATURE_BUG 1
+static DEFINE_MUTEX(i8k_mutex);
static char bios_version[4];
MODULE_AUTHOR("Massimo Dal Zotto (dz@debian.org)");
@@ -399,9 +400,9 @@ static long i8k_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
{
long ret;
- lock_kernel();
+ mutex_lock(&i8k_mutex);
ret = i8k_ioctl_unlocked(fp, cmd, arg);
- unlock_kernel();
+ mutex_unlock(&i8k_mutex);
return ret;
}
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c
index d4b71e8d0d23..fcd02baa7d65 100644
--- a/drivers/char/ip2/ip2main.c
+++ b/drivers/char/ip2/ip2main.c
@@ -98,7 +98,7 @@
#include <linux/major.h>
#include <linux/wait.h>
#include <linux/device.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/firmware.h>
#include <linux/platform_device.h>
@@ -138,6 +138,7 @@
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
+static DEFINE_MUTEX(ip2_mutex);
static const struct file_operations ip2mem_proc_fops;
static const struct file_operations ip2_proc_fops;
@@ -183,6 +184,8 @@ static void ip2_hangup(PTTY);
static int ip2_tiocmget(struct tty_struct *tty, struct file *file);
static int ip2_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear);
+static int ip2_get_icount(struct tty_struct *tty,
+ struct serial_icounter_struct *icount);
static void set_irq(int, int);
static void ip2_interrupt_bh(struct work_struct *work);
@@ -236,6 +239,7 @@ static const struct file_operations ip2_ipl = {
.write = ip2_ipl_write,
.unlocked_ioctl = ip2_ipl_ioctl,
.open = ip2_ipl_open,
+ .llseek = noop_llseek,
};
static unsigned long irq_counter;
@@ -454,6 +458,7 @@ static const struct tty_operations ip2_ops = {
.hangup = ip2_hangup,
.tiocmget = ip2_tiocmget,
.tiocmset = ip2_tiocmset,
+ .get_icount = ip2_get_icount,
.proc_fops = &ip2_proc_fops,
};
@@ -2128,7 +2133,6 @@ ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg )
i2ChanStrPtr pCh = DevTable[tty->index];
i2eBordStrPtr pB;
struct async_icount cprev, cnow; /* kernel counter temps */
- struct serial_icounter_struct __user *p_cuser;
int rc = 0;
unsigned long flags;
void __user *argp = (void __user *)arg;
@@ -2297,34 +2301,6 @@ ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg )
break;
/*
- * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
- * Return: write counters to the user passed counter struct
- * NB: both 1->0 and 0->1 transitions are counted except for RI where
- * only 0->1 is counted. The controller is quite capable of counting
- * both, but this done to preserve compatibility with the standard
- * serial driver.
- */
- case TIOCGICOUNT:
- ip2trace (CHANN, ITRC_IOCTL, 11, 1, rc );
-
- write_lock_irqsave(&pB->read_fifo_spinlock, flags);
- cnow = pCh->icount;
- write_unlock_irqrestore(&pB->read_fifo_spinlock, flags);
- p_cuser = argp;
- rc = put_user(cnow.cts, &p_cuser->cts);
- rc = put_user(cnow.dsr, &p_cuser->dsr);
- rc = put_user(cnow.rng, &p_cuser->rng);
- rc = put_user(cnow.dcd, &p_cuser->dcd);
- rc = put_user(cnow.rx, &p_cuser->rx);
- rc = put_user(cnow.tx, &p_cuser->tx);
- rc = put_user(cnow.frame, &p_cuser->frame);
- rc = put_user(cnow.overrun, &p_cuser->overrun);
- rc = put_user(cnow.parity, &p_cuser->parity);
- rc = put_user(cnow.brk, &p_cuser->brk);
- rc = put_user(cnow.buf_overrun, &p_cuser->buf_overrun);
- break;
-
- /*
* The rest are not supported by this driver. By returning -ENOIOCTLCMD they
* will be passed to the line discipline for it to handle.
*/
@@ -2348,6 +2324,46 @@ ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg )
return rc;
}
+static int ip2_get_icount(struct tty_struct *tty,
+ struct serial_icounter_struct *icount)
+{
+ i2ChanStrPtr pCh = DevTable[tty->index];
+ i2eBordStrPtr pB;
+ struct async_icount cnow; /* kernel counter temp */
+ unsigned long flags;
+
+ if ( pCh == NULL )
+ return -ENODEV;
+
+ pB = pCh->pMyBord;
+
+ /*
+ * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
+ * Return: write counters to the user passed counter struct
+ * NB: both 1->0 and 0->1 transitions are counted except for RI where
+ * only 0->1 is counted. The controller is quite capable of counting
+ * both, but this done to preserve compatibility with the standard
+ * serial driver.
+ */
+
+ write_lock_irqsave(&pB->read_fifo_spinlock, flags);
+ cnow = pCh->icount;
+ write_unlock_irqrestore(&pB->read_fifo_spinlock, flags);
+
+ icount->cts = cnow.cts;
+ icount->dsr = cnow.dsr;
+ icount->rng = cnow.rng;
+ icount->dcd = cnow.dcd;
+ icount->rx = cnow.rx;
+ icount->tx = cnow.tx;
+ icount->frame = cnow.frame;
+ icount->overrun = cnow.overrun;
+ icount->parity = cnow.parity;
+ icount->brk = cnow.brk;
+ icount->buf_overrun = cnow.buf_overrun;
+ return 0;
+}
+
/******************************************************************************/
/* Function: GetSerialInfo() */
/* Parameters: Pointer to channel structure */
@@ -2897,7 +2913,7 @@ ip2_ipl_ioctl (struct file *pFile, UINT cmd, ULONG arg )
printk (KERN_DEBUG "IP2IPL: ioctl cmd %d, arg %ld\n", cmd, arg );
#endif
- lock_kernel();
+ mutex_lock(&ip2_mutex);
switch ( iplminor ) {
case 0: // IPL device
@@ -2961,7 +2977,7 @@ ip2_ipl_ioctl (struct file *pFile, UINT cmd, ULONG arg )
rc = -ENODEV;
break;
}
- unlock_kernel();
+ mutex_unlock(&ip2_mutex);
return rc;
}
@@ -2982,7 +2998,6 @@ ip2_ipl_open( struct inode *pInode, struct file *pFile )
#ifdef IP2DEBUG_IPL
printk (KERN_DEBUG "IP2IPL: open\n" );
#endif
- cycle_kernel_lock();
return 0;
}
diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c
index d8ec92a38980..1fc8876af1f5 100644
--- a/drivers/char/ipmi/ipmi_devintf.c
+++ b/drivers/char/ipmi/ipmi_devintf.c
@@ -44,7 +44,6 @@
#include <linux/init.h>
#include <linux/device.h>
#include <linux/compat.h>
-#include <linux/smp_lock.h>
struct ipmi_file_private
{
@@ -59,6 +58,7 @@ struct ipmi_file_private
unsigned int default_retry_time_ms;
};
+static DEFINE_MUTEX(ipmi_mutex);
static void file_receive_handler(struct ipmi_recv_msg *msg,
void *handler_data)
{
@@ -102,9 +102,9 @@ static int ipmi_fasync(int fd, struct file *file, int on)
struct ipmi_file_private *priv = file->private_data;
int result;
- lock_kernel(); /* could race against open() otherwise */
+ mutex_lock(&ipmi_mutex); /* could race against open() otherwise */
result = fasync_helper(fd, file, on, &priv->fasync_queue);
- unlock_kernel();
+ mutex_unlock(&ipmi_mutex);
return (result);
}
@@ -125,7 +125,7 @@ static int ipmi_open(struct inode *inode, struct file *file)
if (!priv)
return -ENOMEM;
- lock_kernel();
+ mutex_lock(&ipmi_mutex);
priv->file = file;
rv = ipmi_create_user(if_num,
@@ -150,7 +150,7 @@ static int ipmi_open(struct inode *inode, struct file *file)
priv->default_retry_time_ms = 0;
out:
- unlock_kernel();
+ mutex_unlock(&ipmi_mutex);
return rv;
}
@@ -639,9 +639,9 @@ static long ipmi_unlocked_ioctl(struct file *file,
{
int ret;
- lock_kernel();
+ mutex_lock(&ipmi_mutex);
ret = ipmi_ioctl(file, cmd, data);
- unlock_kernel();
+ mutex_unlock(&ipmi_mutex);
return ret;
}
@@ -850,6 +850,7 @@ static const struct file_operations ipmi_fops = {
.release = ipmi_release,
.fasync = ipmi_fasync,
.poll = ipmi_poll,
+ .llseek = noop_llseek,
};
#define DEVICE_NAME "ipmidev"
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c
index 654d566ca57c..f4d334f2536e 100644
--- a/drivers/char/ipmi/ipmi_watchdog.c
+++ b/drivers/char/ipmi/ipmi_watchdog.c
@@ -35,7 +35,7 @@
#include <linux/moduleparam.h>
#include <linux/ipmi.h>
#include <linux/ipmi_smi.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/watchdog.h>
#include <linux/miscdevice.h>
#include <linux/init.h>
@@ -149,6 +149,7 @@
#define WDIOC_GET_PRETIMEOUT _IOW(WATCHDOG_IOCTL_BASE, 22, int)
#endif
+static DEFINE_MUTEX(ipmi_watchdog_mutex);
static int nowayout = WATCHDOG_NOWAYOUT;
static ipmi_user_t watchdog_user;
@@ -748,9 +749,9 @@ static long ipmi_unlocked_ioctl(struct file *file,
{
int ret;
- lock_kernel();
+ mutex_lock(&ipmi_watchdog_mutex);
ret = ipmi_ioctl(file, cmd, arg);
- unlock_kernel();
+ mutex_unlock(&ipmi_watchdog_mutex);
return ret;
}
@@ -844,7 +845,6 @@ static int ipmi_open(struct inode *ino, struct file *filep)
if (test_and_set_bit(0, &ipmi_wdog_open))
return -EBUSY;
- cycle_kernel_lock();
/*
* Don't start the timer now, let it start on the
@@ -909,6 +909,7 @@ static const struct file_operations ipmi_wdog_fops = {
.open = ipmi_open,
.release = ipmi_close,
.fasync = ipmi_fasync,
+ .llseek = no_llseek,
};
static struct miscdevice ipmi_wdog_miscdev = {
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index be28391adb79..667abd23ad6a 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -704,6 +704,7 @@ static const struct file_operations stli_fsiomem = {
.read = stli_memread,
.write = stli_memwrite,
.unlocked_ioctl = stli_memioctl,
+ .llseek = default_llseek,
};
/*****************************************************************************/
diff --git a/drivers/char/lp.c b/drivers/char/lp.c
index 938a3a273886..97c3edb95ae7 100644
--- a/drivers/char/lp.c
+++ b/drivers/char/lp.c
@@ -126,7 +126,7 @@
#include <linux/device.h>
#include <linux/wait.h>
#include <linux/jiffies.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/compat.h>
#include <linux/parport.h>
@@ -140,6 +140,7 @@
/* if you have more than 8 printers, remember to increase LP_NO */
#define LP_NO 8
+static DEFINE_MUTEX(lp_mutex);
static struct lp_struct lp_table[LP_NO];
static unsigned int lp_count = 0;
@@ -493,7 +494,7 @@ static int lp_open(struct inode * inode, struct file * file)
unsigned int minor = iminor(inode);
int ret = 0;
- lock_kernel();
+ mutex_lock(&lp_mutex);
if (minor >= LP_NO) {
ret = -ENXIO;
goto out;
@@ -554,7 +555,7 @@ static int lp_open(struct inode * inode, struct file * file)
lp_release_parport (&lp_table[minor]);
lp_table[minor].current_mode = IEEE1284_MODE_COMPAT;
out:
- unlock_kernel();
+ mutex_unlock(&lp_mutex);
return ret;
}
@@ -680,7 +681,7 @@ static long lp_ioctl(struct file *file, unsigned int cmd,
int ret;
minor = iminor(file->f_path.dentry->d_inode);
- lock_kernel();
+ mutex_lock(&lp_mutex);
switch (cmd) {
case LPSETTIMEOUT:
if (copy_from_user(&par_timeout, (void __user *)arg,
@@ -694,7 +695,7 @@ static long lp_ioctl(struct file *file, unsigned int cmd,
ret = lp_do_ioctl(minor, cmd, arg, (void __user *)arg);
break;
}
- unlock_kernel();
+ mutex_unlock(&lp_mutex);
return ret;
}
@@ -709,7 +710,7 @@ static long lp_compat_ioctl(struct file *file, unsigned int cmd,
int ret;
minor = iminor(file->f_path.dentry->d_inode);
- lock_kernel();
+ mutex_lock(&lp_mutex);
switch (cmd) {
case LPSETTIMEOUT:
tc = compat_ptr(arg);
@@ -730,7 +731,7 @@ static long lp_compat_ioctl(struct file *file, unsigned int cmd,
ret = lp_do_ioctl(minor, cmd, arg, compat_ptr(arg));
break;
}
- unlock_kernel();
+ mutex_unlock(&lp_mutex);
return ret;
}
@@ -748,6 +749,7 @@ static const struct file_operations lp_fops = {
#ifdef CONFIG_PARPORT_1284
.read = lp_read,
#endif
+ .llseek = noop_llseek,
};
/* --- support for console on the line printer ----------------- */
diff --git a/drivers/char/mbcs.c b/drivers/char/mbcs.c
index 83bef4efe376..1aeaaba680d2 100644
--- a/drivers/char/mbcs.c
+++ b/drivers/char/mbcs.c
@@ -25,7 +25,6 @@
#include <linux/mm.h>
#include <linux/uio.h>
#include <linux/mutex.h>
-#include <linux/smp_lock.h>
#include <linux/slab.h>
#include <asm/io.h>
#include <asm/uaccess.h>
@@ -42,6 +41,7 @@
#else
#define DBG(fmt...)
#endif
+static DEFINE_MUTEX(mbcs_mutex);
static int mbcs_major;
static LIST_HEAD(soft_list);
@@ -385,19 +385,19 @@ static int mbcs_open(struct inode *ip, struct file *fp)
struct mbcs_soft *soft;
int minor;
- lock_kernel();
+ mutex_lock(&mbcs_mutex);
minor = iminor(ip);
/* Nothing protects access to this list... */
list_for_each_entry(soft, &soft_list, list) {
if (soft->nasid == minor) {
fp->private_data = soft->cxdev;
- unlock_kernel();
+ mutex_unlock(&mbcs_mutex);
return 0;
}
}
- unlock_kernel();
+ mutex_unlock(&mbcs_mutex);
return -ENODEV;
}
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 1f528fad3516..e985b1c2730e 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -805,6 +805,7 @@ static const struct file_operations full_fops = {
static const struct file_operations oldmem_fops = {
.read = read_oldmem,
.open = open_oldmem,
+ .llseek = default_llseek,
};
#endif
@@ -831,6 +832,7 @@ static ssize_t kmsg_write(struct file *file, const char __user *buf,
static const struct file_operations kmsg_fops = {
.write = kmsg_write,
+ .llseek = noop_llseek,
};
static const struct memdev {
@@ -882,6 +884,7 @@ static int memory_open(struct inode *inode, struct file *filp)
static const struct file_operations memory_fops = {
.open = memory_open,
+ .llseek = noop_llseek,
};
static char *mem_devnode(struct device *dev, mode_t *mode)
diff --git a/drivers/char/misc.c b/drivers/char/misc.c
index abdafd488980..778273c93242 100644
--- a/drivers/char/misc.c
+++ b/drivers/char/misc.c
@@ -162,6 +162,7 @@ static struct class *misc_class;
static const struct file_operations misc_fops = {
.owner = THIS_MODULE,
.open = misc_open,
+ .llseek = noop_llseek,
};
/**
diff --git a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c
index ea7c99fa978f..c070b53984e4 100644
--- a/drivers/char/mmtimer.c
+++ b/drivers/char/mmtimer.c
@@ -32,7 +32,7 @@
#include <linux/interrupt.h>
#include <linux/time.h>
#include <linux/math64.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/slab.h>
#include <asm/uaccess.h>
@@ -59,6 +59,7 @@ extern unsigned long sn_rtc_cycles_per_second;
#define rtc_time() (*RTC_COUNTER_ADDR)
+static DEFINE_MUTEX(mmtimer_mutex);
static long mmtimer_ioctl(struct file *file, unsigned int cmd,
unsigned long arg);
static int mmtimer_mmap(struct file *file, struct vm_area_struct *vma);
@@ -72,6 +73,7 @@ static const struct file_operations mmtimer_fops = {
.owner = THIS_MODULE,
.mmap = mmtimer_mmap,
.unlocked_ioctl = mmtimer_ioctl,
+ .llseek = noop_llseek,
};
/*
@@ -371,7 +373,7 @@ static long mmtimer_ioctl(struct file *file, unsigned int cmd,
{
int ret = 0;
- lock_kernel();
+ mutex_lock(&mmtimer_mutex);
switch (cmd) {
case MMTIMER_GETOFFSET: /* offset of the counter */
@@ -414,7 +416,7 @@ static long mmtimer_ioctl(struct file *file, unsigned int cmd,
ret = -ENOTTY;
break;
}
- unlock_kernel();
+ mutex_unlock(&mmtimer_mutex);
return ret;
}
diff --git a/drivers/char/mspec.c b/drivers/char/mspec.c
index ecb89d798e35..966a95bc974b 100644
--- a/drivers/char/mspec.c
+++ b/drivers/char/mspec.c
@@ -316,7 +316,8 @@ uncached_mmap(struct file *file, struct vm_area_struct *vma)
static const struct file_operations fetchop_fops = {
.owner = THIS_MODULE,
- .mmap = fetchop_mmap
+ .mmap = fetchop_mmap,
+ .llseek = noop_llseek,
};
static struct miscdevice fetchop_miscdev = {
@@ -327,7 +328,8 @@ static struct miscdevice fetchop_miscdev = {
static const struct file_operations cached_fops = {
.owner = THIS_MODULE,
- .mmap = cached_mmap
+ .mmap = cached_mmap,
+ .llseek = noop_llseek,
};
static struct miscdevice cached_miscdev = {
@@ -338,7 +340,8 @@ static struct miscdevice cached_miscdev = {
static const struct file_operations uncached_fops = {
.owner = THIS_MODULE,
- .mmap = uncached_mmap
+ .mmap = uncached_mmap,
+ .llseek = noop_llseek,
};
static struct miscdevice uncached_miscdev = {
diff --git a/drivers/char/mwave/mwavedd.c b/drivers/char/mwave/mwavedd.c
index a4ec50c95072..1d82d5838f0c 100644
--- a/drivers/char/mwave/mwavedd.c
+++ b/drivers/char/mwave/mwavedd.c
@@ -56,7 +56,7 @@
#include <linux/serial.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/delay.h>
#include <linux/serial_8250.h>
#include "smapi.h"
@@ -73,6 +73,7 @@ MODULE_LICENSE("GPL");
* checks are made against other devices (ie. superio) for conflicts.
* We'll depend on users using the tpctl utility to do that for now
*/
+static DEFINE_MUTEX(mwave_mutex);
int mwave_debug = 0;
int mwave_3780i_irq = 0;
int mwave_3780i_io = 0;
@@ -101,7 +102,6 @@ static int mwave_open(struct inode *inode, struct file *file)
PRINTK_2(TRACE_MWAVE,
"mwavedd::mwave_open, exit return retval %x\n", retval);
- cycle_kernel_lock();
return retval;
}
@@ -136,9 +136,9 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
PRINTK_1(TRACE_MWAVE,
"mwavedd::mwave_ioctl, IOCTL_MW_RESET"
" calling tp3780I_ResetDSP\n");
- lock_kernel();
+ mutex_lock(&mwave_mutex);
retval = tp3780I_ResetDSP(&pDrvData->rBDData);
- unlock_kernel();
+ mutex_unlock(&mwave_mutex);
PRINTK_2(TRACE_MWAVE,
"mwavedd::mwave_ioctl, IOCTL_MW_RESET"
" retval %x from tp3780I_ResetDSP\n",
@@ -149,9 +149,9 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
PRINTK_1(TRACE_MWAVE,
"mwavedd::mwave_ioctl, IOCTL_MW_RUN"
" calling tp3780I_StartDSP\n");
- lock_kernel();
+ mutex_lock(&mwave_mutex);
retval = tp3780I_StartDSP(&pDrvData->rBDData);
- unlock_kernel();
+ mutex_unlock(&mwave_mutex);
PRINTK_2(TRACE_MWAVE,
"mwavedd::mwave_ioctl, IOCTL_MW_RUN"
" retval %x from tp3780I_StartDSP\n",
@@ -165,10 +165,10 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
"mwavedd::mwave_ioctl,"
" IOCTL_MW_DSP_ABILITIES calling"
" tp3780I_QueryAbilities\n");
- lock_kernel();
+ mutex_lock(&mwave_mutex);
retval = tp3780I_QueryAbilities(&pDrvData->rBDData,
&rAbilities);
- unlock_kernel();
+ mutex_unlock(&mwave_mutex);
PRINTK_2(TRACE_MWAVE,
"mwavedd::mwave_ioctl, IOCTL_MW_DSP_ABILITIES"
" retval %x from tp3780I_QueryAbilities\n",
@@ -199,13 +199,13 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
"mwavedd::mwave_ioctl IOCTL_MW_READ_DATA,"
" size %lx, ioarg %lx pusBuffer %p\n",
rReadData.ulDataLength, ioarg, pusBuffer);
- lock_kernel();
+ mutex_lock(&mwave_mutex);
retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData,
iocmd,
pusBuffer,
rReadData.ulDataLength,
rReadData.usDspAddress);
- unlock_kernel();
+ mutex_unlock(&mwave_mutex);
}
break;
@@ -223,12 +223,12 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
" size %lx, ioarg %lx pusBuffer %p\n",
rReadData.ulDataLength / 2, ioarg,
pusBuffer);
- lock_kernel();
+ mutex_lock(&mwave_mutex);
retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData,
iocmd, pusBuffer,
rReadData.ulDataLength / 2,
rReadData.usDspAddress);
- unlock_kernel();
+ mutex_unlock(&mwave_mutex);
}
break;
@@ -246,12 +246,12 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
" size %lx, ioarg %lx pusBuffer %p\n",
rWriteData.ulDataLength, ioarg,
pusBuffer);
- lock_kernel();
+ mutex_lock(&mwave_mutex);
retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData,
iocmd, pusBuffer,
rWriteData.ulDataLength,
rWriteData.usDspAddress);
- unlock_kernel();
+ mutex_unlock(&mwave_mutex);
}
break;
@@ -269,12 +269,12 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
" size %lx, ioarg %lx pusBuffer %p\n",
rWriteData.ulDataLength, ioarg,
pusBuffer);
- lock_kernel();
+ mutex_lock(&mwave_mutex);
retval = tp3780I_ReadWriteDspIStore(&pDrvData->rBDData,
iocmd, pusBuffer,
rWriteData.ulDataLength,
rWriteData.usDspAddress);
- unlock_kernel();
+ mutex_unlock(&mwave_mutex);
}
break;
@@ -295,10 +295,10 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
ipcnum,
pDrvData->IPCs[ipcnum].usIntCount);
- lock_kernel();
+ mutex_lock(&mwave_mutex);
pDrvData->IPCs[ipcnum].bIsHere = FALSE;
pDrvData->IPCs[ipcnum].bIsEnabled = TRUE;
- unlock_kernel();
+ mutex_unlock(&mwave_mutex);
PRINTK_2(TRACE_MWAVE,
"mwavedd::mwave_ioctl IOCTL_MW_REGISTER_IPC"
@@ -323,7 +323,7 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
ipcnum,
pDrvData->IPCs[ipcnum].usIntCount);
- lock_kernel();
+ mutex_lock(&mwave_mutex);
if (pDrvData->IPCs[ipcnum].bIsEnabled == TRUE) {
DECLARE_WAITQUEUE(wait, current);
@@ -364,7 +364,7 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
" processing\n",
ipcnum);
}
- unlock_kernel();
+ mutex_unlock(&mwave_mutex);
}
break;
@@ -383,14 +383,14 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
ipcnum);
return -EINVAL;
}
- lock_kernel();
+ mutex_lock(&mwave_mutex);
if (pDrvData->IPCs[ipcnum].bIsEnabled == TRUE) {
pDrvData->IPCs[ipcnum].bIsEnabled = FALSE;
if (pDrvData->IPCs[ipcnum].bIsHere == TRUE) {
wake_up_interruptible(&pDrvData->IPCs[ipcnum].ipc_wait_queue);
}
}
- unlock_kernel();
+ mutex_unlock(&mwave_mutex);
}
break;
@@ -479,7 +479,8 @@ static const struct file_operations mwave_fops = {
.write = mwave_write,
.unlocked_ioctl = mwave_ioctl,
.open = mwave_open,
- .release = mwave_close
+ .release = mwave_close,
+ .llseek = default_llseek,
};
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index 3fc89da856ae..463df27494bd 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -1700,7 +1700,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
return 0;
}
- if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT && cmd != TIOCGICOUNT &&
+ if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT &&
test_bit(TTY_IO_ERROR, &tty->flags))
return -EIO;
@@ -1730,32 +1730,6 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
return wait_event_interruptible(info->port.delta_msr_wait,
mxser_cflags_changed(info, arg, &cnow));
- /*
- * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
- * Return: write counters to the user passed counter struct
- * NB: both 1->0 and 0->1 transitions are counted except for
- * RI where only 0->1 is counted.
- */
- case TIOCGICOUNT: {
- struct serial_icounter_struct icnt = { 0 };
- spin_lock_irqsave(&info->slock, flags);
- cnow = info->icount;
- spin_unlock_irqrestore(&info->slock, flags);
-
- icnt.frame = cnow.frame;
- icnt.brk = cnow.brk;
- icnt.overrun = cnow.overrun;
- icnt.buf_overrun = cnow.buf_overrun;
- icnt.parity = cnow.parity;
- icnt.rx = cnow.rx;
- icnt.tx = cnow.tx;
- icnt.cts = cnow.cts;
- icnt.dsr = cnow.dsr;
- icnt.rng = cnow.rng;
- icnt.dcd = cnow.dcd;
-
- return copy_to_user(argp, &icnt, sizeof(icnt)) ? -EFAULT : 0;
- }
case MOXA_HighSpeedOn:
return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp);
case MOXA_SDS_RSTICOUNTER:
@@ -1828,6 +1802,39 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
return 0;
}
+ /*
+ * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
+ * Return: write counters to the user passed counter struct
+ * NB: both 1->0 and 0->1 transitions are counted except for
+ * RI where only 0->1 is counted.
+ */
+
+static int mxser_get_icount(struct tty_struct *tty,
+ struct serial_icounter_struct *icount)
+
+{
+ struct mxser_port *info = tty->driver_data;
+ struct async_icount cnow;
+ unsigned long flags;
+
+ spin_lock_irqsave(&info->slock, flags);
+ cnow = info->icount;
+ spin_unlock_irqrestore(&info->slock, flags);
+
+ icount->frame = cnow.frame;
+ icount->brk = cnow.brk;
+ icount->overrun = cnow.overrun;
+ icount->buf_overrun = cnow.buf_overrun;
+ icount->parity = cnow.parity;
+ icount->rx = cnow.rx;
+ icount->tx = cnow.tx;
+ icount->cts = cnow.cts;
+ icount->dsr = cnow.dsr;
+ icount->rng = cnow.rng;
+ icount->dcd = cnow.dcd;
+ return 0;
+}
+
static void mxser_stoprx(struct tty_struct *tty)
{
struct mxser_port *info = tty->driver_data;
@@ -2326,6 +2333,7 @@ static const struct tty_operations mxser_ops = {
.wait_until_sent = mxser_wait_until_sent,
.tiocmget = mxser_tiocmget,
.tiocmset = mxser_tiocmset,
+ .get_icount = mxser_get_icount,
};
struct tty_port_operations mxser_port_ops = {
@@ -2339,20 +2347,11 @@ struct tty_port_operations mxser_port_ops = {
* The MOXA Smartio/Industio serial driver boot-time initialization code!
*/
-static void mxser_release_res(struct mxser_board *brd, struct pci_dev *pdev,
- unsigned int irq)
+static void mxser_release_ISA_res(struct mxser_board *brd)
{
- if (irq)
- free_irq(brd->irq, brd);
- if (pdev != NULL) { /* PCI */
-#ifdef CONFIG_PCI
- pci_release_region(pdev, 2);
- pci_release_region(pdev, 3);
-#endif
- } else {
- release_region(brd->ports[0].ioaddr, 8 * brd->info->nports);
- release_region(brd->vector, 1);
- }
+ free_irq(brd->irq, brd);
+ release_region(brd->ports[0].ioaddr, 8 * brd->info->nports);
+ release_region(brd->vector, 1);
}
static int __devinit mxser_initbrd(struct mxser_board *brd,
@@ -2397,13 +2396,11 @@ static int __devinit mxser_initbrd(struct mxser_board *brd,
retval = request_irq(brd->irq, mxser_interrupt, IRQF_SHARED, "mxser",
brd);
- if (retval) {
+ if (retval)
printk(KERN_ERR "Board %s: Request irq failed, IRQ (%d) may "
"conflict with another device.\n",
brd->info->name, brd->irq);
- /* We hold resources, we need to release them. */
- mxser_release_res(brd, pdev, 0);
- }
+
return retval;
}
@@ -2555,7 +2552,7 @@ static int __devinit mxser_probe(struct pci_dev *pdev,
ioaddress = pci_resource_start(pdev, 2);
retval = pci_request_region(pdev, 2, "mxser(IO)");
if (retval)
- goto err;
+ goto err_dis;
brd->info = &mxser_cards[ent->driver_data];
for (i = 0; i < brd->info->nports; i++)
@@ -2565,7 +2562,7 @@ static int __devinit mxser_probe(struct pci_dev *pdev,
ioaddress = pci_resource_start(pdev, 3);
retval = pci_request_region(pdev, 3, "mxser(vector)");
if (retval)
- goto err_relio;
+ goto err_zero;
brd->vector = ioaddress;
/* irq */
@@ -2608,7 +2605,7 @@ static int __devinit mxser_probe(struct pci_dev *pdev,
/* mxser_initbrd will hook ISR. */
retval = mxser_initbrd(brd, pdev);
if (retval)
- goto err_null;
+ goto err_rel3;
for (i = 0; i < brd->info->nports; i++)
tty_register_device(mxvar_sdriver, brd->idx + i, &pdev->dev);
@@ -2616,10 +2613,13 @@ static int __devinit mxser_probe(struct pci_dev *pdev,
pci_set_drvdata(pdev, brd);
return 0;
-err_relio:
- pci_release_region(pdev, 2);
-err_null:
+err_rel3:
+ pci_release_region(pdev, 3);
+err_zero:
brd->info = NULL;
+ pci_release_region(pdev, 2);
+err_dis:
+ pci_disable_device(pdev);
err:
return retval;
#else
@@ -2629,14 +2629,19 @@ err:
static void __devexit mxser_remove(struct pci_dev *pdev)
{
+#ifdef CONFIG_PCI
struct mxser_board *brd = pci_get_drvdata(pdev);
unsigned int i;
for (i = 0; i < brd->info->nports; i++)
tty_unregister_device(mxvar_sdriver, brd->idx + i);
- mxser_release_res(brd, pdev, 1);
+ free_irq(pdev->irq, brd);
+ pci_release_region(pdev, 2);
+ pci_release_region(pdev, 3);
+ pci_disable_device(pdev);
brd->info = NULL;
+#endif
}
static struct pci_driver mxser_driver = {
@@ -2741,7 +2746,7 @@ static void __exit mxser_module_exit(void)
for (i = 0; i < MXSER_BOARDS; i++)
if (mxser_boards[i].info != NULL)
- mxser_release_res(&mxser_boards[i], NULL, 1);
+ mxser_release_ISA_res(&mxser_boards[i]);
}
module_init(mxser_module_init);
diff --git a/drivers/char/nozomi.c b/drivers/char/nozomi.c
index 817169cbb245..dd3f9b1f11b4 100644
--- a/drivers/char/nozomi.c
+++ b/drivers/char/nozomi.c
@@ -1804,24 +1804,24 @@ static int ntty_cflags_changed(struct port *port, unsigned long flags,
return ret;
}
-static int ntty_ioctl_tiocgicount(struct port *port, void __user *argp)
+static int ntty_tiocgicount(struct tty_struct *tty,
+ struct serial_icounter_struct *icount)
{
+ struct port *port = tty->driver_data;
const struct async_icount cnow = port->tty_icount;
- struct serial_icounter_struct icount;
-
- icount.cts = cnow.cts;
- icount.dsr = cnow.dsr;
- icount.rng = cnow.rng;
- icount.dcd = cnow.dcd;
- icount.rx = cnow.rx;
- icount.tx = cnow.tx;
- icount.frame = cnow.frame;
- icount.overrun = cnow.overrun;
- icount.parity = cnow.parity;
- icount.brk = cnow.brk;
- icount.buf_overrun = cnow.buf_overrun;
-
- return copy_to_user(argp, &icount, sizeof(icount)) ? -EFAULT : 0;
+
+ icount->cts = cnow.cts;
+ icount->dsr = cnow.dsr;
+ icount->rng = cnow.rng;
+ icount->dcd = cnow.dcd;
+ icount->rx = cnow.rx;
+ icount->tx = cnow.tx;
+ icount->frame = cnow.frame;
+ icount->overrun = cnow.overrun;
+ icount->parity = cnow.parity;
+ icount->brk = cnow.brk;
+ icount->buf_overrun = cnow.buf_overrun;
+ return 0;
}
static int ntty_ioctl(struct tty_struct *tty, struct file *file,
@@ -1840,9 +1840,7 @@ static int ntty_ioctl(struct tty_struct *tty, struct file *file,
rval = wait_event_interruptible(port->tty_wait,
ntty_cflags_changed(port, arg, &cprev));
break;
- } case TIOCGICOUNT:
- rval = ntty_ioctl_tiocgicount(port, argp);
- break;
+ }
default:
DBG1("ERR: 0x%08X, %d", cmd, cmd);
break;
@@ -1922,6 +1920,7 @@ static const struct tty_operations tty_ops = {
.chars_in_buffer = ntty_chars_in_buffer,
.tiocmget = ntty_tiocmget,
.tiocmset = ntty_tiocmset,
+ .get_icount = ntty_tiocgicount,
.install = ntty_install,
.cleanup = ntty_cleanup,
};
diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c
index 66d2917b003f..166f1e7aaa7e 100644
--- a/drivers/char/nvram.c
+++ b/drivers/char/nvram.c
@@ -109,10 +109,11 @@
#include <linux/spinlock.h>
#include <linux/io.h>
#include <linux/uaccess.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <asm/system.h>
+static DEFINE_MUTEX(nvram_mutex);
static DEFINE_SPINLOCK(nvram_state_lock);
static int nvram_open_cnt; /* #times opened */
static int nvram_open_mode; /* special open modes */
@@ -308,7 +309,7 @@ static long nvram_ioctl(struct file *file, unsigned int cmd,
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
- lock_kernel();
+ mutex_lock(&nvram_mutex);
spin_lock_irq(&rtc_lock);
for (i = 0; i < NVRAM_BYTES; ++i)
@@ -316,7 +317,7 @@ static long nvram_ioctl(struct file *file, unsigned int cmd,
__nvram_set_checksum();
spin_unlock_irq(&rtc_lock);
- unlock_kernel();
+ mutex_unlock(&nvram_mutex);
return 0;
case NVRAM_SETCKS:
@@ -325,11 +326,11 @@ static long nvram_ioctl(struct file *file, unsigned int cmd,
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
- lock_kernel();
+ mutex_lock(&nvram_mutex);
spin_lock_irq(&rtc_lock);
__nvram_set_checksum();
spin_unlock_irq(&rtc_lock);
- unlock_kernel();
+ mutex_unlock(&nvram_mutex);
return 0;
default:
diff --git a/drivers/char/nwbutton.c b/drivers/char/nwbutton.c
index 2604246501e4..8994ce32e6c7 100644
--- a/drivers/char/nwbutton.c
+++ b/drivers/char/nwbutton.c
@@ -182,6 +182,7 @@ static int button_read (struct file *filp, char __user *buffer,
static const struct file_operations button_fops = {
.owner = THIS_MODULE,
.read = button_read,
+ .llseek = noop_llseek,
};
/*
diff --git a/drivers/char/nwflash.c b/drivers/char/nwflash.c
index 043a1c7b86be..a12f52400dbc 100644
--- a/drivers/char/nwflash.c
+++ b/drivers/char/nwflash.c
@@ -25,7 +25,6 @@
#include <linux/spinlock.h>
#include <linux/rwsem.h>
#include <linux/init.h>
-#include <linux/smp_lock.h>
#include <linux/mutex.h>
#include <linux/jiffies.h>
@@ -41,6 +40,7 @@
#define NWFLASH_VERSION "6.4"
+static DEFINE_MUTEX(flash_mutex);
static void kick_open(void);
static int get_flash_id(void);
static int erase_block(int nBlock);
@@ -96,7 +96,7 @@ static int get_flash_id(void)
static long flash_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
{
- lock_kernel();
+ mutex_lock(&flash_mutex);
switch (cmd) {
case CMD_WRITE_DISABLE:
gbWriteBase64Enable = 0;
@@ -114,10 +114,10 @@ static long flash_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
default:
gbWriteBase64Enable = 0;
gbWriteEnable = 0;
- unlock_kernel();
+ mutex_unlock(&flash_mutex);
return -EINVAL;
}
- unlock_kernel();
+ mutex_unlock(&flash_mutex);
return 0;
}
@@ -282,7 +282,7 @@ static loff_t flash_llseek(struct file *file, loff_t offset, int orig)
{
loff_t ret;
- lock_kernel();
+ mutex_lock(&flash_mutex);
if (flashdebug)
printk(KERN_DEBUG "flash_llseek: offset=0x%X, orig=0x%X.\n",
(unsigned int) offset, orig);
@@ -317,7 +317,7 @@ static loff_t flash_llseek(struct file *file, loff_t offset, int orig)
default:
ret = -EINVAL;
}
- unlock_kernel();
+ mutex_unlock(&flash_mutex);
return ret;
}
diff --git a/drivers/char/pc8736x_gpio.c b/drivers/char/pc8736x_gpio.c
index 8ecbcc174c15..b304ec052501 100644
--- a/drivers/char/pc8736x_gpio.c
+++ b/drivers/char/pc8736x_gpio.c
@@ -234,6 +234,7 @@ static const struct file_operations pc8736x_gpio_fileops = {
.open = pc8736x_gpio_open,
.write = nsc_gpio_write,
.read = nsc_gpio_read,
+ .llseek = no_llseek,
};
static void __init pc8736x_init_shadow(void)
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c
index ec73d9f6d9ed..6835c23e9a51 100644
--- a/drivers/char/pcmcia/cm4000_cs.c
+++ b/drivers/char/pcmcia/cm4000_cs.c
@@ -30,11 +30,10 @@
#include <linux/fs.h>
#include <linux/delay.h>
#include <linux/bitrev.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/uaccess.h>
#include <linux/io.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/ciscode.h>
@@ -55,7 +54,7 @@
__func__ , ## args); \
} while (0)
-static char *version = "cm4000_cs.c v2.4.0gm6 - All bugs added by Harald Welte";
+static DEFINE_MUTEX(cmm_mutex);
#define T_1SEC (HZ)
#define T_10MSEC msecs_to_jiffies(10)
@@ -1418,7 +1417,7 @@ static long cmm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
iminor(inode), ioctl_names[_IOC_NR(cmd)]);
#endif
- lock_kernel();
+ mutex_lock(&cmm_mutex);
rc = -ENODEV;
link = dev_table[iminor(inode)];
if (!pcmcia_dev_present(link)) {
@@ -1626,7 +1625,7 @@ static long cmm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
rc = -ENOTTY;
}
out:
- unlock_kernel();
+ mutex_unlock(&cmm_mutex);
return rc;
}
@@ -1640,7 +1639,7 @@ static int cmm_open(struct inode *inode, struct file *filp)
if (minor >= CM4000_MAX_DEV)
return -ENODEV;
- lock_kernel();
+ mutex_lock(&cmm_mutex);
link = dev_table[minor];
if (link == NULL || !pcmcia_dev_present(link)) {
ret = -ENODEV;
@@ -1685,7 +1684,7 @@ static int cmm_open(struct inode *inode, struct file *filp)
DEBUGP(2, dev, "<- cmm_open\n");
ret = nonseekable_open(inode, filp);
out:
- unlock_kernel();
+ mutex_unlock(&cmm_mutex);
return ret;
}
@@ -1742,20 +1741,8 @@ static void cmm_cm4000_release(struct pcmcia_device * link)
/*==== Interface to PCMCIA Layer =======================================*/
-static int cm4000_config_check(struct pcmcia_device *p_dev,
- cistpl_cftable_entry_t *cfg,
- cistpl_cftable_entry_t *dflt,
- unsigned int vcc,
- void *priv_data)
+static int cm4000_config_check(struct pcmcia_device *p_dev, void *priv_data)
{
- if (!cfg->io.nwin)
- return -ENODEV;
-
- p_dev->resource[0]->start = cfg->io.win[0].base;
- p_dev->resource[0]->end = cfg->io.win[0].len;
- p_dev->resource[0]->flags |= pcmcia_io_cfg_data_width(cfg->io.flags);
- p_dev->io_lines = cfg->io.flags & CISTPL_IO_LINES_MASK;
-
return pcmcia_request_io(p_dev);
}
@@ -1763,13 +1750,13 @@ static int cm4000_config(struct pcmcia_device * link, int devno)
{
struct cm4000_dev *dev;
+ link->config_flags |= CONF_AUTO_SET_IO;
+
/* read the config-tuples */
if (pcmcia_loop_config(link, cm4000_config_check, NULL))
goto cs_release;
- link->conf.IntType = 00000002;
-
- if (pcmcia_request_configuration(link, &link->conf))
+ if (pcmcia_enable_device(link))
goto cs_release;
dev = link->priv;
@@ -1829,7 +1816,6 @@ static int cm4000_probe(struct pcmcia_device *link)
dev->p_dev = link;
link->priv = dev;
- link->conf.IntType = INT_MEMORY_AND_IO;
dev_table[i] = link;
init_waitqueue_head(&dev->devq);
@@ -1880,6 +1866,7 @@ static const struct file_operations cm4000_fops = {
.unlocked_ioctl = cmm_ioctl,
.open = cmm_open,
.release= cmm_close,
+ .llseek = no_llseek,
};
static struct pcmcia_device_id cm4000_ids[] = {
@@ -1891,9 +1878,7 @@ MODULE_DEVICE_TABLE(pcmcia, cm4000_ids);
static struct pcmcia_driver cm4000_driver = {
.owner = THIS_MODULE,
- .drv = {
- .name = "cm4000_cs",
- },
+ .name = "cm4000_cs",
.probe = cm4000_probe,
.remove = cm4000_detach,
.suspend = cm4000_suspend,
@@ -1905,8 +1890,6 @@ static int __init cmm_init(void)
{
int rc;
- printk(KERN_INFO "%s\n", version);
-
cmm_class = class_create(THIS_MODULE, "cardman_4000");
if (IS_ERR(cmm_class))
return PTR_ERR(cmm_class);
@@ -1931,7 +1914,6 @@ static int __init cmm_init(void)
static void __exit cmm_exit(void)
{
- printk(KERN_INFO MODULE_NAME ": unloading\n");
pcmcia_unregister_driver(&cm4000_driver);
unregister_chrdev(major, DEVICE_NAME);
class_destroy(cmm_class);
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c
index 815cde1d0570..5d8d59e865f4 100644
--- a/drivers/char/pcmcia/cm4040_cs.c
+++ b/drivers/char/pcmcia/cm4040_cs.c
@@ -24,12 +24,11 @@
#include <linux/fs.h>
#include <linux/delay.h>
#include <linux/poll.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/wait.h>
#include <asm/uaccess.h>
#include <asm/io.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/ciscode.h>
@@ -49,8 +48,7 @@
__func__ , ## args); \
} while (0)
-static char *version =
-"OMNIKEY CardMan 4040 v1.1.0gm5 - All bugs added by Harald Welte";
+static DEFINE_MUTEX(cm4040_mutex);
#define CCID_DRIVER_BULK_DEFAULT_TIMEOUT (150*HZ)
#define CCID_DRIVER_ASYNC_POWERUP_TIMEOUT (35*HZ)
@@ -444,7 +442,7 @@ static int cm4040_open(struct inode *inode, struct file *filp)
if (minor >= CM_MAX_DEV)
return -ENODEV;
- lock_kernel();
+ mutex_lock(&cm4040_mutex);
link = dev_table[minor];
if (link == NULL || !pcmcia_dev_present(link)) {
ret = -ENODEV;
@@ -473,7 +471,7 @@ static int cm4040_open(struct inode *inode, struct file *filp)
DEBUGP(2, dev, "<- cm4040_open (successfully)\n");
ret = nonseekable_open(inode, filp);
out:
- unlock_kernel();
+ mutex_unlock(&cm4040_mutex);
return ret;
}
@@ -516,26 +514,9 @@ static void cm4040_reader_release(struct pcmcia_device *link)
return;
}
-static int cm4040_config_check(struct pcmcia_device *p_dev,
- cistpl_cftable_entry_t *cfg,
- cistpl_cftable_entry_t *dflt,
- unsigned int vcc,
- void *priv_data)
+static int cm4040_config_check(struct pcmcia_device *p_dev, void *priv_data)
{
- int rc;
- if (!cfg->io.nwin)
- return -ENODEV;
-
- /* Get the IOaddr */
- p_dev->resource[0]->start = cfg->io.win[0].base;
- p_dev->resource[0]->end = cfg->io.win[0].len;
- p_dev->resource[0]->flags |= pcmcia_io_cfg_data_width(cfg->io.flags);
- p_dev->io_lines = cfg->io.flags & CISTPL_IO_LINES_MASK;
- rc = pcmcia_request_io(p_dev);
-
- dev_printk(KERN_INFO, &p_dev->dev,
- "pcmcia_request_io returned 0x%x\n", rc);
- return rc;
+ return pcmcia_request_io(p_dev);
}
@@ -544,15 +525,15 @@ static int reader_config(struct pcmcia_device *link, int devno)
struct reader_dev *dev;
int fail_rc;
+ link->config_flags |= CONF_AUTO_SET_IO;
+
if (pcmcia_loop_config(link, cm4040_config_check, NULL))
goto cs_release;
- link->conf.IntType = 00000002;
-
- fail_rc = pcmcia_request_configuration(link, &link->conf);
+ fail_rc = pcmcia_enable_device(link);
if (fail_rc != 0) {
dev_printk(KERN_INFO, &link->dev,
- "pcmcia_request_configuration failed 0x%x\n",
+ "pcmcia_enable_device failed 0x%x\n",
fail_rc);
goto cs_release;
}
@@ -599,7 +580,6 @@ static int reader_probe(struct pcmcia_device *link)
link->priv = dev;
dev->p_dev = link;
- link->conf.IntType = INT_MEMORY_AND_IO;
dev_table[i] = link;
init_waitqueue_head(&dev->devq);
@@ -650,6 +630,7 @@ static const struct file_operations reader_fops = {
.open = cm4040_open,
.release = cm4040_close,
.poll = cm4040_poll,
+ .llseek = no_llseek,
};
static struct pcmcia_device_id cm4040_ids[] = {
@@ -662,9 +643,7 @@ MODULE_DEVICE_TABLE(pcmcia, cm4040_ids);
static struct pcmcia_driver reader_driver = {
.owner = THIS_MODULE,
- .drv = {
- .name = "cm4040_cs",
- },
+ .name = "cm4040_cs",
.probe = reader_probe,
.remove = reader_detach,
.id_table = cm4040_ids,
@@ -674,7 +653,6 @@ static int __init cm4040_init(void)
{
int rc;
- printk(KERN_INFO "%s\n", version);
cmx_class = class_create(THIS_MODULE, "cardman_4040");
if (IS_ERR(cmx_class))
return PTR_ERR(cmx_class);
@@ -699,7 +677,6 @@ static int __init cm4040_init(void)
static void __exit cm4040_exit(void)
{
- printk(KERN_INFO MODULE_NAME ": unloading\n");
pcmcia_unregister_driver(&reader_driver);
unregister_chrdev(major, DEVICE_NAME);
class_destroy(cmx_class);
diff --git a/drivers/char/pcmcia/ipwireless/main.c b/drivers/char/pcmcia/ipwireless/main.c
index 67bdb05798b1..94b8eb4d691d 100644
--- a/drivers/char/pcmcia/ipwireless/main.c
+++ b/drivers/char/pcmcia/ipwireless/main.c
@@ -32,7 +32,6 @@
#include <pcmcia/device_id.h>
#include <pcmcia/ss.h>
#include <pcmcia/ds.h>
-#include <pcmcia/cs.h>
static struct pcmcia_device_id ipw_ids[] = {
PCMCIA_DEVICE_MANF_CARD(0x02f2, 0x0100),
@@ -76,23 +75,18 @@ static void signalled_reboot_callback(void *callback_data)
schedule_work(&ipw->work_reboot);
}
-static int ipwireless_probe(struct pcmcia_device *p_dev,
- cistpl_cftable_entry_t *cfg,
- cistpl_cftable_entry_t *dflt,
- unsigned int vcc,
- void *priv_data)
+static int ipwireless_probe(struct pcmcia_device *p_dev, void *priv_data)
{
struct ipw_dev *ipw = priv_data;
struct resource *io_resource;
int ret;
+ p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
- p_dev->resource[0]->start = cfg->io.win[0].base;
- p_dev->resource[0]->end = cfg->io.win[0].len;
/* 0x40 causes it to generate level mode interrupts. */
/* 0x04 enables IREQ pin. */
- p_dev->conf.ConfigIndex = cfg->index | 0x44;
+ p_dev->config_index |= 0x44;
p_dev->io_lines = 16;
ret = pcmcia_request_io(p_dev);
if (ret)
@@ -102,65 +96,49 @@ static int ipwireless_probe(struct pcmcia_device *p_dev,
resource_size(p_dev->resource[0]),
IPWIRELESS_PCCARD_NAME);
- if (cfg->mem.nwin == 0)
- return 0;
-
- ipw->request_common_memory.Attributes =
+ p_dev->resource[2]->flags |=
WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE;
- ipw->request_common_memory.Base = cfg->mem.win[0].host_addr;
- ipw->request_common_memory.Size = cfg->mem.win[0].len;
- if (ipw->request_common_memory.Size < 0x1000)
- ipw->request_common_memory.Size = 0x1000;
- ipw->request_common_memory.AccessSpeed = 0;
-
- ret = pcmcia_request_window(p_dev, &ipw->request_common_memory,
- &ipw->handle_common_memory);
+ ret = pcmcia_request_window(p_dev, p_dev->resource[2], 0);
if (ret != 0)
goto exit1;
- ret = pcmcia_map_mem_page(p_dev, ipw->handle_common_memory,
- cfg->mem.win[0].card_addr);
-
+ ret = pcmcia_map_mem_page(p_dev, p_dev->resource[2], p_dev->card_addr);
if (ret != 0)
goto exit2;
- ipw->is_v2_card = cfg->mem.win[0].len == 0x100;
+ ipw->is_v2_card = resource_size(p_dev->resource[2]) == 0x100;
- ipw->common_memory = ioremap(ipw->request_common_memory.Base,
- ipw->request_common_memory.Size);
- request_mem_region(ipw->request_common_memory.Base,
- ipw->request_common_memory.Size,
+ ipw->attr_memory = ioremap(p_dev->resource[2]->start,
+ resource_size(p_dev->resource[2]));
+ request_mem_region(p_dev->resource[2]->start,
+ resource_size(p_dev->resource[2]),
IPWIRELESS_PCCARD_NAME);
- ipw->request_attr_memory.Attributes =
- WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM | WIN_ENABLE;
- ipw->request_attr_memory.Base = 0;
- ipw->request_attr_memory.Size = 0; /* this used to be 0x1000 */
- ipw->request_attr_memory.AccessSpeed = 0;
-
- ret = pcmcia_request_window(p_dev, &ipw->request_attr_memory,
- &ipw->handle_attr_memory);
-
+ p_dev->resource[3]->flags |= WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM |
+ WIN_ENABLE;
+ p_dev->resource[3]->end = 0; /* this used to be 0x1000 */
+ ret = pcmcia_request_window(p_dev, p_dev->resource[3], 0);
if (ret != 0)
goto exit2;
- ret = pcmcia_map_mem_page(p_dev, ipw->handle_attr_memory, 0);
+ ret = pcmcia_map_mem_page(p_dev, p_dev->resource[3], 0);
if (ret != 0)
goto exit3;
- ipw->attr_memory = ioremap(ipw->request_attr_memory.Base,
- ipw->request_attr_memory.Size);
- request_mem_region(ipw->request_attr_memory.Base,
- ipw->request_attr_memory.Size, IPWIRELESS_PCCARD_NAME);
+ ipw->attr_memory = ioremap(p_dev->resource[3]->start,
+ resource_size(p_dev->resource[3]));
+ request_mem_region(p_dev->resource[3]->start,
+ resource_size(p_dev->resource[3]),
+ IPWIRELESS_PCCARD_NAME);
return 0;
exit3:
exit2:
if (ipw->common_memory) {
- release_mem_region(ipw->request_common_memory.Base,
- ipw->request_common_memory.Size);
+ release_mem_region(p_dev->resource[2]->start,
+ resource_size(p_dev->resource[2]));
iounmap(ipw->common_memory);
}
exit1:
@@ -175,14 +153,13 @@ static int config_ipwireless(struct ipw_dev *ipw)
int ret = 0;
ipw->is_v2_card = 0;
+ link->config_flags |= CONF_AUTO_SET_IO | CONF_AUTO_SET_IOMEM |
+ CONF_ENABLE_IRQ;
ret = pcmcia_loop_config(link, ipwireless_probe, ipw);
if (ret != 0)
return ret;
- link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.IntType = INT_MEMORY_AND_IO;
-
INIT_WORK(&ipw->work_reboot, signalled_reboot_work);
ipwireless_init_hardware_v1(ipw->hardware, link->resource[0]->start,
@@ -201,13 +178,9 @@ static int config_ipwireless(struct ipw_dev *ipw)
(unsigned int) link->irq);
if (ipw->attr_memory && ipw->common_memory)
printk(KERN_INFO IPWIRELESS_PCCARD_NAME
- ": attr memory 0x%08lx-0x%08lx, common memory 0x%08lx-0x%08lx\n",
- ipw->request_attr_memory.Base,
- ipw->request_attr_memory.Base
- + ipw->request_attr_memory.Size - 1,
- ipw->request_common_memory.Base,
- ipw->request_common_memory.Base
- + ipw->request_common_memory.Size - 1);
+ ": attr memory %pR, common memory %pR\n",
+ link->resource[3],
+ link->resource[2]);
ipw->network = ipwireless_network_create(ipw->hardware);
if (!ipw->network)
@@ -223,25 +196,23 @@ static int config_ipwireless(struct ipw_dev *ipw)
* Do the RequestConfiguration last, because it enables interrupts.
* Then we don't get any interrupts before we're ready for them.
*/
- ret = pcmcia_request_configuration(link, &link->conf);
-
+ ret = pcmcia_enable_device(link);
if (ret != 0)
goto exit;
return 0;
exit:
- if (ipw->attr_memory) {
- release_mem_region(ipw->request_attr_memory.Base,
- ipw->request_attr_memory.Size);
- iounmap(ipw->attr_memory);
-
- }
if (ipw->common_memory) {
- release_mem_region(ipw->request_common_memory.Base,
- ipw->request_common_memory.Size);
+ release_mem_region(link->resource[2]->start,
+ resource_size(link->resource[2]));
iounmap(ipw->common_memory);
}
+ if (ipw->attr_memory) {
+ release_mem_region(link->resource[3]->start,
+ resource_size(link->resource[3]));
+ iounmap(ipw->attr_memory);
+ }
pcmcia_disable_device(link);
return -1;
}
@@ -249,13 +220,13 @@ exit:
static void release_ipwireless(struct ipw_dev *ipw)
{
if (ipw->common_memory) {
- release_mem_region(ipw->request_common_memory.Base,
- ipw->request_common_memory.Size);
+ release_mem_region(ipw->link->resource[2]->start,
+ resource_size(ipw->link->resource[2]));
iounmap(ipw->common_memory);
}
if (ipw->attr_memory) {
- release_mem_region(ipw->request_attr_memory.Base,
- ipw->request_attr_memory.Size);
+ release_mem_region(ipw->link->resource[3]->start,
+ resource_size(ipw->link->resource[3]));
iounmap(ipw->attr_memory);
}
pcmcia_disable_device(ipw->link);
@@ -324,7 +295,7 @@ static struct pcmcia_driver me = {
.owner = THIS_MODULE,
.probe = ipwireless_attach,
.remove = ipwireless_detach,
- .drv = { .name = IPWIRELESS_PCCARD_NAME },
+ .name = IPWIRELESS_PCCARD_NAME,
.id_table = ipw_ids
};
@@ -336,9 +307,6 @@ static int __init init_ipwireless(void)
{
int ret;
- printk(KERN_INFO IPWIRELESS_PCCARD_NAME " "
- IPWIRELESS_PCMCIA_VERSION " by " IPWIRELESS_PCMCIA_AUTHOR "\n");
-
ret = ipwireless_tty_init();
if (ret != 0)
return ret;
@@ -355,9 +323,6 @@ static int __init init_ipwireless(void)
*/
static void __exit exit_ipwireless(void)
{
- printk(KERN_INFO IPWIRELESS_PCCARD_NAME " "
- IPWIRELESS_PCMCIA_VERSION " removed\n");
-
pcmcia_unregister_driver(&me);
ipwireless_tty_release();
}
diff --git a/drivers/char/pcmcia/ipwireless/main.h b/drivers/char/pcmcia/ipwireless/main.h
index c207be87b597..f2cbb116bccb 100644
--- a/drivers/char/pcmcia/ipwireless/main.h
+++ b/drivers/char/pcmcia/ipwireless/main.h
@@ -21,7 +21,6 @@
#include <linux/sched.h>
#include <linux/types.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
@@ -45,13 +44,9 @@ struct ipw_dev {
struct pcmcia_device *link;
int is_v2_card;
- window_handle_t handle_attr_memory;
void __iomem *attr_memory;
- win_req_t request_attr_memory;
- window_handle_t handle_common_memory;
void __iomem *common_memory;
- win_req_t request_common_memory;
/* Reference to attribute memory, containing CIS data */
void *attribute_memory;
diff --git a/drivers/char/pcmcia/ipwireless/tty.h b/drivers/char/pcmcia/ipwireless/tty.h
index 3e163d4cab15..747b2d637860 100644
--- a/drivers/char/pcmcia/ipwireless/tty.h
+++ b/drivers/char/pcmcia/ipwireless/tty.h
@@ -21,7 +21,6 @@
#include <linux/types.h>
#include <linux/sched.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index 9ecd6bef5d3b..bfc10f89d951 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -70,7 +70,6 @@
#include <linux/workqueue.h>
#include <linux/hdlc.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/ds.h>
@@ -550,9 +549,6 @@ static int mgslpc_probe(struct pcmcia_device *link)
/* Initialize the struct pcmcia_device structure */
- link->conf.Attributes = 0;
- link->conf.IntType = INT_MEMORY_AND_IO;
-
ret = mgslpc_config(link);
if (ret)
return ret;
@@ -565,20 +561,8 @@ static int mgslpc_probe(struct pcmcia_device *link)
/* Card has been inserted.
*/
-static int mgslpc_ioprobe(struct pcmcia_device *p_dev,
- cistpl_cftable_entry_t *cfg,
- cistpl_cftable_entry_t *dflt,
- unsigned int vcc,
- void *priv_data)
+static int mgslpc_ioprobe(struct pcmcia_device *p_dev, void *priv_data)
{
- if (!cfg->io.nwin)
- return -ENODEV;
-
- p_dev->resource[0]->start = cfg->io.win[0].base;
- p_dev->resource[0]->end = cfg->io.win[0].len;
- p_dev->resource[0]->flags |= pcmcia_io_cfg_data_width(cfg->io.flags);
- p_dev->io_lines = cfg->io.flags & CISTPL_IO_LINES_MASK;
-
return pcmcia_request_io(p_dev);
}
@@ -590,32 +574,24 @@ static int mgslpc_config(struct pcmcia_device *link)
if (debug_level >= DEBUG_LEVEL_INFO)
printk("mgslpc_config(0x%p)\n", link);
+ link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+
ret = pcmcia_loop_config(link, mgslpc_ioprobe, NULL);
if (ret != 0)
goto failed;
- link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.IntType = INT_MEMORY_AND_IO;
- link->conf.ConfigIndex = 8;
- link->conf.Present = PRESENT_OPTION;
+ link->config_index = 8;
+ link->config_regs = PRESENT_OPTION;
ret = pcmcia_request_irq(link, mgslpc_isr);
if (ret)
goto failed;
- ret = pcmcia_request_configuration(link, &link->conf);
+ ret = pcmcia_enable_device(link);
if (ret)
goto failed;
info->io_base = link->resource[0]->start;
info->irq_level = link->irq;
-
- dev_info(&link->dev, "index 0x%02x:",
- link->conf.ConfigIndex);
- if (link->conf.Attributes & CONF_ENABLE_IRQ)
- printk(", irq %d", link->irq);
- if (link->resource[0])
- printk(", io %pR", link->resource[0]);
- printk("\n");
return 0;
failed:
@@ -2215,6 +2191,32 @@ static int mgslpc_break(struct tty_struct *tty, int break_state)
return 0;
}
+static int mgslpc_get_icount(struct tty_struct *tty,
+ struct serial_icounter_struct *icount)
+{
+ MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data;
+ struct mgsl_icount cnow; /* kernel counter temps */
+ unsigned long flags;
+
+ spin_lock_irqsave(&info->lock,flags);
+ cnow = info->icount;
+ spin_unlock_irqrestore(&info->lock,flags);
+
+ icount->cts = cnow.cts;
+ icount->dsr = cnow.dsr;
+ icount->rng = cnow.rng;
+ icount->dcd = cnow.dcd;
+ icount->rx = cnow.rx;
+ icount->tx = cnow.tx;
+ icount->frame = cnow.frame;
+ icount->overrun = cnow.overrun;
+ icount->parity = cnow.parity;
+ icount->brk = cnow.brk;
+ icount->buf_overrun = cnow.buf_overrun;
+
+ return 0;
+}
+
/* Service an IOCTL request
*
* Arguments:
@@ -2230,11 +2232,7 @@ static int mgslpc_ioctl(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg)
{
MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data;
- int error;
- struct mgsl_icount cnow; /* kernel counter temps */
- struct serial_icounter_struct __user *p_cuser; /* user space */
void __user *argp = (void __user *)arg;
- unsigned long flags;
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):mgslpc_ioctl %s cmd=%08X\n", __FILE__,__LINE__,
@@ -2244,7 +2242,7 @@ static int mgslpc_ioctl(struct tty_struct *tty, struct file * file,
return -ENODEV;
if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
- (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
+ (cmd != TIOCMIWAIT)) {
if (tty->flags & (1 << TTY_IO_ERROR))
return -EIO;
}
@@ -2274,34 +2272,6 @@ static int mgslpc_ioctl(struct tty_struct *tty, struct file * file,
return wait_events(info, argp);
case TIOCMIWAIT:
return modem_input_wait(info,(int)arg);
- case TIOCGICOUNT:
- spin_lock_irqsave(&info->lock,flags);
- cnow = info->icount;
- spin_unlock_irqrestore(&info->lock,flags);
- p_cuser = argp;
- PUT_USER(error,cnow.cts, &p_cuser->cts);
- if (error) return error;
- PUT_USER(error,cnow.dsr, &p_cuser->dsr);
- if (error) return error;
- PUT_USER(error,cnow.rng, &p_cuser->rng);
- if (error) return error;
- PUT_USER(error,cnow.dcd, &p_cuser->dcd);
- if (error) return error;
- PUT_USER(error,cnow.rx, &p_cuser->rx);
- if (error) return error;
- PUT_USER(error,cnow.tx, &p_cuser->tx);
- if (error) return error;
- PUT_USER(error,cnow.frame, &p_cuser->frame);
- if (error) return error;
- PUT_USER(error,cnow.overrun, &p_cuser->overrun);
- if (error) return error;
- PUT_USER(error,cnow.parity, &p_cuser->parity);
- if (error) return error;
- PUT_USER(error,cnow.brk, &p_cuser->brk);
- if (error) return error;
- PUT_USER(error,cnow.buf_overrun, &p_cuser->buf_overrun);
- if (error) return error;
- return 0;
default:
return -ENOIOCTLCMD;
}
@@ -2797,9 +2767,7 @@ MODULE_DEVICE_TABLE(pcmcia, mgslpc_ids);
static struct pcmcia_driver mgslpc_driver = {
.owner = THIS_MODULE,
- .drv = {
- .name = "synclink_cs",
- },
+ .name = "synclink_cs",
.probe = mgslpc_probe,
.remove = mgslpc_detach,
.id_table = mgslpc_ids,
@@ -2835,8 +2803,6 @@ static void synclink_cs_cleanup(void)
{
int rc;
- printk("Unloading %s: version %s\n", driver_name, driver_version);
-
while(mgslpc_device_list)
mgslpc_remove_device(mgslpc_device_list);
@@ -2859,8 +2825,6 @@ static int __init synclink_cs_init(void)
BREAKPOINT();
}
- printk("%s %s\n", driver_name, driver_version);
-
if ((rc = pcmcia_register_driver(&mgslpc_driver)) < 0)
return rc;
@@ -4127,6 +4091,8 @@ static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
if (cmd != SIOCWANDEV)
return hdlc_ioctl(dev, ifr, cmd);
+ memset(&new_line, 0, size);
+
switch(ifr->ifr_settings.type) {
case IF_GET_IFACE: /* return current sync_serial_settings */
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c
index 02abfddce45a..723152d978a9 100644
--- a/drivers/char/ppdev.c
+++ b/drivers/char/ppdev.c
@@ -67,7 +67,7 @@
#include <linux/slab.h>
#include <linux/major.h>
#include <linux/ppdev.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/uaccess.h>
#define PP_VERSION "ppdev: user-space parallel port driver"
@@ -97,6 +97,7 @@ struct pp_struct {
/* ROUND_UP macro from fs/select.c */
#define ROUND_UP(x,y) (((x)+(y)-1)/(y))
+static DEFINE_MUTEX(pp_do_mutex);
static inline void pp_enable_irq (struct pp_struct *pp)
{
struct parport *port = pp->pdev->port;
@@ -630,9 +631,9 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
static long pp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
long ret;
- lock_kernel();
+ mutex_lock(&pp_do_mutex);
ret = pp_do_ioctl(file, cmd, arg);
- unlock_kernel();
+ mutex_unlock(&pp_do_mutex);
return ret;
}
@@ -641,7 +642,6 @@ static int pp_open (struct inode * inode, struct file * file)
unsigned int minor = iminor(inode);
struct pp_struct *pp;
- cycle_kernel_lock();
if (minor >= PARPORT_MAX)
return -ENXIO;
diff --git a/drivers/char/pty.c b/drivers/char/pty.c
index c350d01716bd..923a48585501 100644
--- a/drivers/char/pty.c
+++ b/drivers/char/pty.c
@@ -676,7 +676,9 @@ static int ptmx_open(struct inode *inode, struct file *filp)
set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
- tty_add_file(tty, filp);
+ retval = tty_add_file(tty, filp);
+ if (retval)
+ goto out;
retval = devpts_pty_new(inode, tty->link);
if (retval)
diff --git a/drivers/char/random.c b/drivers/char/random.c
index caef35a46890..5a1aa64f4e76 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1165,6 +1165,7 @@ const struct file_operations random_fops = {
.poll = random_poll,
.unlocked_ioctl = random_ioctl,
.fasync = random_fasync,
+ .llseek = noop_llseek,
};
const struct file_operations urandom_fops = {
@@ -1172,6 +1173,7 @@ const struct file_operations urandom_fops = {
.write = random_write,
.unlocked_ioctl = random_ioctl,
.fasync = random_fasync,
+ .llseek = noop_llseek,
};
/***************************************************************
diff --git a/drivers/char/raw.c b/drivers/char/raw.c
index b38942f6bf31..bfe25ea9766b 100644
--- a/drivers/char/raw.c
+++ b/drivers/char/raw.c
@@ -19,8 +19,8 @@
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/mutex.h>
-#include <linux/smp_lock.h>
#include <linux/gfp.h>
+#include <linux/compat.h>
#include <asm/uaccess.h>
@@ -55,7 +55,6 @@ static int raw_open(struct inode *inode, struct file *filp)
return 0;
}
- lock_kernel();
mutex_lock(&raw_mutex);
/*
@@ -82,7 +81,6 @@ static int raw_open(struct inode *inode, struct file *filp)
bdev->bd_inode->i_mapping;
filp->private_data = bdev;
mutex_unlock(&raw_mutex);
- unlock_kernel();
return 0;
out2:
@@ -91,7 +89,6 @@ out1:
blkdev_put(bdev, filp->f_mode);
out:
mutex_unlock(&raw_mutex);
- unlock_kernel();
return err;
}
@@ -125,20 +122,84 @@ static long
raw_ioctl(struct file *filp, unsigned int command, unsigned long arg)
{
struct block_device *bdev = filp->private_data;
- int ret;
+ return blkdev_ioctl(bdev, 0, command, arg);
+}
+
+static int bind_set(int number, u64 major, u64 minor)
+{
+ dev_t dev = MKDEV(major, minor);
+ struct raw_device_data *rawdev;
+ int err = 0;
- lock_kernel();
- ret = blkdev_ioctl(bdev, 0, command, arg);
- unlock_kernel();
+ if (number <= 0 || number >= MAX_RAW_MINORS)
+ return -EINVAL;
- return ret;
+ if (MAJOR(dev) != major || MINOR(dev) != minor)
+ return -EINVAL;
+
+ rawdev = &raw_devices[number];
+
+ /*
+ * This is like making block devices, so demand the
+ * same capability
+ */
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ /*
+ * For now, we don't need to check that the underlying
+ * block device is present or not: we can do that when
+ * the raw device is opened. Just check that the
+ * major/minor numbers make sense.
+ */
+
+ if (MAJOR(dev) == 0 && dev != 0)
+ return -EINVAL;
+
+ mutex_lock(&raw_mutex);
+ if (rawdev->inuse) {
+ mutex_unlock(&raw_mutex);
+ return -EBUSY;
+ }
+ if (rawdev->binding) {
+ bdput(rawdev->binding);
+ module_put(THIS_MODULE);
+ }
+ if (!dev) {
+ /* unbind */
+ rawdev->binding = NULL;
+ device_destroy(raw_class, MKDEV(RAW_MAJOR, number));
+ } else {
+ rawdev->binding = bdget(dev);
+ if (rawdev->binding == NULL) {
+ err = -ENOMEM;
+ } else {
+ dev_t raw = MKDEV(RAW_MAJOR, number);
+ __module_get(THIS_MODULE);
+ device_destroy(raw_class, raw);
+ device_create(raw_class, NULL, raw, NULL,
+ "raw%d", number);
+ }
+ }
+ mutex_unlock(&raw_mutex);
+ return err;
}
-static void bind_device(struct raw_config_request *rq)
+static int bind_get(int number, dev_t *dev)
{
- device_destroy(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor));
- device_create(raw_class, NULL, MKDEV(RAW_MAJOR, rq->raw_minor), NULL,
- "raw%d", rq->raw_minor);
+ struct raw_device_data *rawdev;
+ struct block_device *bdev;
+
+ if (number <= 0 || number >= MAX_RAW_MINORS)
+ return -EINVAL;
+
+ rawdev = &raw_devices[number];
+
+ mutex_lock(&raw_mutex);
+ bdev = rawdev->binding;
+ *dev = bdev ? bdev->bd_dev : 0;
+ mutex_unlock(&raw_mutex);
+ return 0;
}
/*
@@ -149,105 +210,78 @@ static long raw_ctl_ioctl(struct file *filp, unsigned int command,
unsigned long arg)
{
struct raw_config_request rq;
- struct raw_device_data *rawdev;
- int err = 0;
+ dev_t dev;
+ int err;
- lock_kernel();
switch (command) {
case RAW_SETBIND:
+ if (copy_from_user(&rq, (void __user *) arg, sizeof(rq)))
+ return -EFAULT;
+
+ return bind_set(rq.raw_minor, rq.block_major, rq.block_minor);
+
case RAW_GETBIND:
+ if (copy_from_user(&rq, (void __user *) arg, sizeof(rq)))
+ return -EFAULT;
- /* First, find out which raw minor we want */
+ err = bind_get(rq.raw_minor, &dev);
+ if (err)
+ return err;
- if (copy_from_user(&rq, (void __user *) arg, sizeof(rq))) {
- err = -EFAULT;
- goto out;
- }
+ rq.block_major = MAJOR(dev);
+ rq.block_minor = MINOR(dev);
- if (rq.raw_minor <= 0 || rq.raw_minor >= MAX_RAW_MINORS) {
- err = -EINVAL;
- goto out;
- }
- rawdev = &raw_devices[rq.raw_minor];
-
- if (command == RAW_SETBIND) {
- dev_t dev;
-
- /*
- * This is like making block devices, so demand the
- * same capability
- */
- if (!capable(CAP_SYS_ADMIN)) {
- err = -EPERM;
- goto out;
- }
-
- /*
- * For now, we don't need to check that the underlying
- * block device is present or not: we can do that when
- * the raw device is opened. Just check that the
- * major/minor numbers make sense.
- */
-
- dev = MKDEV(rq.block_major, rq.block_minor);
- if ((rq.block_major == 0 && rq.block_minor != 0) ||
- MAJOR(dev) != rq.block_major ||
- MINOR(dev) != rq.block_minor) {
- err = -EINVAL;
- goto out;
- }
-
- mutex_lock(&raw_mutex);
- if (rawdev->inuse) {
- mutex_unlock(&raw_mutex);
- err = -EBUSY;
- goto out;
- }
- if (rawdev->binding) {
- bdput(rawdev->binding);
- module_put(THIS_MODULE);
- }
- if (rq.block_major == 0 && rq.block_minor == 0) {
- /* unbind */
- rawdev->binding = NULL;
- device_destroy(raw_class,
- MKDEV(RAW_MAJOR, rq.raw_minor));
- } else {
- rawdev->binding = bdget(dev);
- if (rawdev->binding == NULL)
- err = -ENOMEM;
- else {
- __module_get(THIS_MODULE);
- bind_device(&rq);
- }
- }
- mutex_unlock(&raw_mutex);
- } else {
- struct block_device *bdev;
-
- mutex_lock(&raw_mutex);
- bdev = rawdev->binding;
- if (bdev) {
- rq.block_major = MAJOR(bdev->bd_dev);
- rq.block_minor = MINOR(bdev->bd_dev);
- } else {
- rq.block_major = rq.block_minor = 0;
- }
- mutex_unlock(&raw_mutex);
- if (copy_to_user((void __user *)arg, &rq, sizeof(rq))) {
- err = -EFAULT;
- goto out;
- }
- }
- break;
- default:
- err = -EINVAL;
- break;
+ if (copy_to_user((void __user *)arg, &rq, sizeof(rq)))
+ return -EFAULT;
+
+ return 0;
}
-out:
- unlock_kernel();
- return err;
+
+ return -EINVAL;
+}
+
+#ifdef CONFIG_COMPAT
+struct raw32_config_request {
+ compat_int_t raw_minor;
+ compat_u64 block_major;
+ compat_u64 block_minor;
+};
+
+static long raw_ctl_compat_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ struct raw32_config_request __user *user_req = compat_ptr(arg);
+ struct raw32_config_request rq;
+ dev_t dev;
+ int err = 0;
+
+ switch (cmd) {
+ case RAW_SETBIND:
+ if (copy_from_user(&rq, user_req, sizeof(rq)))
+ return -EFAULT;
+
+ return bind_set(rq.raw_minor, rq.block_major, rq.block_minor);
+
+ case RAW_GETBIND:
+ if (copy_from_user(&rq, user_req, sizeof(rq)))
+ return -EFAULT;
+
+ err = bind_get(rq.raw_minor, &dev);
+ if (err)
+ return err;
+
+ rq.block_major = MAJOR(dev);
+ rq.block_minor = MINOR(dev);
+
+ if (copy_to_user(user_req, &rq, sizeof(rq)))
+ return -EFAULT;
+
+ return 0;
+ }
+
+ return -EINVAL;
}
+#endif
static const struct file_operations raw_fops = {
.read = do_sync_read,
@@ -258,13 +292,18 @@ static const struct file_operations raw_fops = {
.open = raw_open,
.release = raw_release,
.unlocked_ioctl = raw_ioctl,
+ .llseek = default_llseek,
.owner = THIS_MODULE,
};
static const struct file_operations raw_ctl_fops = {
.unlocked_ioctl = raw_ctl_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = raw_ctl_compat_ioctl,
+#endif
.open = raw_open,
.owner = THIS_MODULE,
+ .llseek = noop_llseek,
};
static struct cdev raw_cdev;
diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c
index d58c2eb07f07..5e33293d24e3 100644
--- a/drivers/char/rio/rio_linux.c
+++ b/drivers/char/rio/rio_linux.c
@@ -44,7 +44,7 @@
#include <linux/delay.h>
#include <linux/pci.h>
#include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/miscdevice.h>
#include <linux/init.h>
@@ -122,6 +122,7 @@ more than 512 ports.... */
/* These constants are derived from SCO Source */
+static DEFINE_MUTEX(rio_fw_mutex);
static struct Conf
RIOConf = {
/* locator */ "RIO Config here",
@@ -241,6 +242,7 @@ static struct real_driver rio_real_driver = {
static const struct file_operations rio_fw_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = rio_fw_ioctl,
+ .llseek = noop_llseek,
};
static struct miscdevice rio_fw_device = {
@@ -566,9 +568,9 @@ static long rio_fw_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
func_enter();
/* The "dev" argument isn't used. */
- lock_kernel();
+ mutex_lock(&rio_fw_mutex);
rc = riocontrol(p, 0, cmd, arg, capable(CAP_SYS_ADMIN));
- unlock_kernel();
+ mutex_unlock(&rio_fw_mutex);
func_exit();
return rc;
diff --git a/drivers/char/scx200_gpio.c b/drivers/char/scx200_gpio.c
index 99e5272e3c53..0bc135b9b16f 100644
--- a/drivers/char/scx200_gpio.c
+++ b/drivers/char/scx200_gpio.c
@@ -67,6 +67,7 @@ static const struct file_operations scx200_gpio_fileops = {
.read = nsc_gpio_read,
.open = scx200_gpio_open,
.release = scx200_gpio_release,
+ .llseek = no_llseek,
};
static struct cdev scx200_gpio_cdev; /* use 1 cdev for all pins */
diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c
index 32b74de18f5f..5816b39ff5a9 100644
--- a/drivers/char/snsc.c
+++ b/drivers/char/snsc.c
@@ -21,7 +21,7 @@
#include <linux/poll.h>
#include <linux/module.h>
#include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <asm/sn/io.h>
#include <asm/sn/sn_sal.h>
#include <asm/sn/module.h>
@@ -34,6 +34,7 @@
#define SCDRV_BUFSZ 2048
#define SCDRV_TIMEOUT 1000
+static DEFINE_MUTEX(scdrv_mutex);
static irqreturn_t
scdrv_interrupt(int irq, void *subch_data)
{
@@ -105,7 +106,7 @@ scdrv_open(struct inode *inode, struct file *file)
file->private_data = sd;
/* hook this subchannel up to the system controller interrupt */
- lock_kernel();
+ mutex_lock(&scdrv_mutex);
rv = request_irq(SGI_UART_VECTOR, scdrv_interrupt,
IRQF_SHARED | IRQF_DISABLED,
SYSCTL_BASENAME, sd);
@@ -113,10 +114,10 @@ scdrv_open(struct inode *inode, struct file *file)
ia64_sn_irtr_close(sd->sd_nasid, sd->sd_subch);
kfree(sd);
printk("%s: irq request failed (%d)\n", __func__, rv);
- unlock_kernel();
+ mutex_unlock(&scdrv_mutex);
return -EBUSY;
}
- unlock_kernel();
+ mutex_unlock(&scdrv_mutex);
return 0;
}
@@ -357,6 +358,7 @@ static const struct file_operations scdrv_fops = {
.poll = scdrv_poll,
.open = scdrv_open,
.release = scdrv_release,
+ .llseek = noop_llseek,
};
static struct class *snsc_class;
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index f2167f8e5aab..8ef16490810c 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -608,6 +608,7 @@ static unsigned int sc26198_baudtable[] = {
static const struct file_operations stl_fsiomem = {
.owner = THIS_MODULE,
.unlocked_ioctl = stl_memioctl,
+ .llseek = noop_llseek,
};
static struct class *stallion_class;
diff --git a/drivers/char/sx.c b/drivers/char/sx.c
index 5b24db4ff7f1..e53f16865397 100644
--- a/drivers/char/sx.c
+++ b/drivers/char/sx.c
@@ -397,6 +397,7 @@ static struct real_driver sx_real_driver = {
static const struct file_operations sx_fw_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = sx_fw_ioctl,
+ .llseek = noop_llseek,
};
static struct miscdevice sx_fw_device = {
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index a2a58004e188..3a6824f12be2 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -2925,6 +2925,38 @@ static int mgsl_break(struct tty_struct *tty, int break_state)
} /* end of mgsl_break() */
+/*
+ * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
+ * Return: write counters to the user passed counter struct
+ * NB: both 1->0 and 0->1 transitions are counted except for
+ * RI where only 0->1 is counted.
+ */
+static int msgl_get_icount(struct tty_struct *tty,
+ struct serial_icounter_struct *icount)
+
+{
+ struct mgsl_struct * info = tty->driver_data;
+ struct mgsl_icount cnow; /* kernel counter temps */
+ unsigned long flags;
+
+ spin_lock_irqsave(&info->irq_spinlock,flags);
+ cnow = info->icount;
+ spin_unlock_irqrestore(&info->irq_spinlock,flags);
+
+ icount->cts = cnow.cts;
+ icount->dsr = cnow.dsr;
+ icount->rng = cnow.rng;
+ icount->dcd = cnow.dcd;
+ icount->rx = cnow.rx;
+ icount->tx = cnow.tx;
+ icount->frame = cnow.frame;
+ icount->overrun = cnow.overrun;
+ icount->parity = cnow.parity;
+ icount->brk = cnow.brk;
+ icount->buf_overrun = cnow.buf_overrun;
+ return 0;
+}
+
/* mgsl_ioctl() Service an IOCTL request
*
* Arguments:
@@ -2949,7 +2981,7 @@ static int mgsl_ioctl(struct tty_struct *tty, struct file * file,
return -ENODEV;
if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
- (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
+ (cmd != TIOCMIWAIT)) {
if (tty->flags & (1 << TTY_IO_ERROR))
return -EIO;
}
@@ -2959,11 +2991,7 @@ static int mgsl_ioctl(struct tty_struct *tty, struct file * file,
static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg)
{
- int error;
- struct mgsl_icount cnow; /* kernel counter temps */
void __user *argp = (void __user *)arg;
- struct serial_icounter_struct __user *p_cuser; /* user space */
- unsigned long flags;
switch (cmd) {
case MGSL_IOCGPARAMS:
@@ -2992,40 +3020,6 @@ static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigne
case TIOCMIWAIT:
return modem_input_wait(info,(int)arg);
- /*
- * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
- * Return: write counters to the user passed counter struct
- * NB: both 1->0 and 0->1 transitions are counted except for
- * RI where only 0->1 is counted.
- */
- case TIOCGICOUNT:
- spin_lock_irqsave(&info->irq_spinlock,flags);
- cnow = info->icount;
- spin_unlock_irqrestore(&info->irq_spinlock,flags);
- p_cuser = argp;
- PUT_USER(error,cnow.cts, &p_cuser->cts);
- if (error) return error;
- PUT_USER(error,cnow.dsr, &p_cuser->dsr);
- if (error) return error;
- PUT_USER(error,cnow.rng, &p_cuser->rng);
- if (error) return error;
- PUT_USER(error,cnow.dcd, &p_cuser->dcd);
- if (error) return error;
- PUT_USER(error,cnow.rx, &p_cuser->rx);
- if (error) return error;
- PUT_USER(error,cnow.tx, &p_cuser->tx);
- if (error) return error;
- PUT_USER(error,cnow.frame, &p_cuser->frame);
- if (error) return error;
- PUT_USER(error,cnow.overrun, &p_cuser->overrun);
- if (error) return error;
- PUT_USER(error,cnow.parity, &p_cuser->parity);
- if (error) return error;
- PUT_USER(error,cnow.brk, &p_cuser->brk);
- if (error) return error;
- PUT_USER(error,cnow.buf_overrun, &p_cuser->buf_overrun);
- if (error) return error;
- return 0;
default:
return -ENOIOCTLCMD;
}
@@ -4328,6 +4322,7 @@ static const struct tty_operations mgsl_ops = {
.hangup = mgsl_hangup,
.tiocmget = tiocmget,
.tiocmset = tiocmset,
+ .get_icount = msgl_get_icount,
.proc_fops = &mgsl_proc_fops,
};
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index e63b830c86cc..1746d91205f7 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -1032,9 +1032,6 @@ static int ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct slgt_info *info = tty->driver_data;
- struct mgsl_icount cnow; /* kernel counter temps */
- struct serial_icounter_struct __user *p_cuser; /* user space */
- unsigned long flags;
void __user *argp = (void __user *)arg;
int ret;
@@ -1043,7 +1040,7 @@ static int ioctl(struct tty_struct *tty, struct file *file,
DBGINFO(("%s ioctl() cmd=%08X\n", info->device_name, cmd));
if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
- (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
+ (cmd != TIOCMIWAIT)) {
if (tty->flags & (1 << TTY_IO_ERROR))
return -EIO;
}
@@ -1053,24 +1050,6 @@ static int ioctl(struct tty_struct *tty, struct file *file,
return wait_mgsl_event(info, argp);
case TIOCMIWAIT:
return modem_input_wait(info,(int)arg);
- case TIOCGICOUNT:
- spin_lock_irqsave(&info->lock,flags);
- cnow = info->icount;
- spin_unlock_irqrestore(&info->lock,flags);
- p_cuser = argp;
- if (put_user(cnow.cts, &p_cuser->cts) ||
- put_user(cnow.dsr, &p_cuser->dsr) ||
- put_user(cnow.rng, &p_cuser->rng) ||
- put_user(cnow.dcd, &p_cuser->dcd) ||
- put_user(cnow.rx, &p_cuser->rx) ||
- put_user(cnow.tx, &p_cuser->tx) ||
- put_user(cnow.frame, &p_cuser->frame) ||
- put_user(cnow.overrun, &p_cuser->overrun) ||
- put_user(cnow.parity, &p_cuser->parity) ||
- put_user(cnow.brk, &p_cuser->brk) ||
- put_user(cnow.buf_overrun, &p_cuser->buf_overrun))
- return -EFAULT;
- return 0;
case MGSL_IOCSGPIO:
return set_gpio(info, argp);
case MGSL_IOCGGPIO:
@@ -1117,6 +1096,33 @@ static int ioctl(struct tty_struct *tty, struct file *file,
return ret;
}
+static int get_icount(struct tty_struct *tty,
+ struct serial_icounter_struct *icount)
+
+{
+ struct slgt_info *info = tty->driver_data;
+ struct mgsl_icount cnow; /* kernel counter temps */
+ unsigned long flags;
+
+ spin_lock_irqsave(&info->lock,flags);
+ cnow = info->icount;
+ spin_unlock_irqrestore(&info->lock,flags);
+
+ icount->cts = cnow.cts;
+ icount->dsr = cnow.dsr;
+ icount->rng = cnow.rng;
+ icount->dcd = cnow.dcd;
+ icount->rx = cnow.rx;
+ icount->tx = cnow.tx;
+ icount->frame = cnow.frame;
+ icount->overrun = cnow.overrun;
+ icount->parity = cnow.parity;
+ icount->brk = cnow.brk;
+ icount->buf_overrun = cnow.buf_overrun;
+
+ return 0;
+}
+
/*
* support for 32 bit ioctl calls on 64 bit systems
*/
@@ -1206,10 +1212,6 @@ static long slgt_compat_ioctl(struct tty_struct *tty, struct file *file,
case MGSL_IOCSGPIO:
case MGSL_IOCGGPIO:
case MGSL_IOCWAITGPIO:
- case TIOCGICOUNT:
- rc = ioctl(tty, file, cmd, (unsigned long)(compat_ptr(arg)));
- break;
-
case MGSL_IOCSTXIDLE:
case MGSL_IOCTXENABLE:
case MGSL_IOCRXENABLE:
@@ -3642,6 +3644,7 @@ static const struct tty_operations ops = {
.hangup = hangup,
.tiocmget = tiocmget,
.tiocmset = tiocmset,
+ .get_icount = get_icount,
.proc_fops = &synclink_gt_proc_fops,
};
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
index e56caf7d82aa..2f9eb4b0dec1 100644
--- a/drivers/char/synclinkmp.c
+++ b/drivers/char/synclinkmp.c
@@ -1258,10 +1258,6 @@ static int ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
SLMP_INFO *info = tty->driver_data;
- int error;
- struct mgsl_icount cnow; /* kernel counter temps */
- struct serial_icounter_struct __user *p_cuser; /* user space */
- unsigned long flags;
void __user *argp = (void __user *)arg;
if (debug_level >= DEBUG_LEVEL_INFO)
@@ -1272,7 +1268,7 @@ static int ioctl(struct tty_struct *tty, struct file *file,
return -ENODEV;
if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
- (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
+ (cmd != TIOCMIWAIT)) {
if (tty->flags & (1 << TTY_IO_ERROR))
return -EIO;
}
@@ -1310,40 +1306,38 @@ static int ioctl(struct tty_struct *tty, struct file *file,
* NB: both 1->0 and 0->1 transitions are counted except for
* RI where only 0->1 is counted.
*/
- case TIOCGICOUNT:
- spin_lock_irqsave(&info->lock,flags);
- cnow = info->icount;
- spin_unlock_irqrestore(&info->lock,flags);
- p_cuser = argp;
- PUT_USER(error,cnow.cts, &p_cuser->cts);
- if (error) return error;
- PUT_USER(error,cnow.dsr, &p_cuser->dsr);
- if (error) return error;
- PUT_USER(error,cnow.rng, &p_cuser->rng);
- if (error) return error;
- PUT_USER(error,cnow.dcd, &p_cuser->dcd);
- if (error) return error;
- PUT_USER(error,cnow.rx, &p_cuser->rx);
- if (error) return error;
- PUT_USER(error,cnow.tx, &p_cuser->tx);
- if (error) return error;
- PUT_USER(error,cnow.frame, &p_cuser->frame);
- if (error) return error;
- PUT_USER(error,cnow.overrun, &p_cuser->overrun);
- if (error) return error;
- PUT_USER(error,cnow.parity, &p_cuser->parity);
- if (error) return error;
- PUT_USER(error,cnow.brk, &p_cuser->brk);
- if (error) return error;
- PUT_USER(error,cnow.buf_overrun, &p_cuser->buf_overrun);
- if (error) return error;
- return 0;
default:
return -ENOIOCTLCMD;
}
return 0;
}
+static int get_icount(struct tty_struct *tty,
+ struct serial_icounter_struct *icount)
+{
+ SLMP_INFO *info = tty->driver_data;
+ struct mgsl_icount cnow; /* kernel counter temps */
+ unsigned long flags;
+
+ spin_lock_irqsave(&info->lock,flags);
+ cnow = info->icount;
+ spin_unlock_irqrestore(&info->lock,flags);
+
+ icount->cts = cnow.cts;
+ icount->dsr = cnow.dsr;
+ icount->rng = cnow.rng;
+ icount->dcd = cnow.dcd;
+ icount->rx = cnow.rx;
+ icount->tx = cnow.tx;
+ icount->frame = cnow.frame;
+ icount->overrun = cnow.overrun;
+ icount->parity = cnow.parity;
+ icount->brk = cnow.brk;
+ icount->buf_overrun = cnow.buf_overrun;
+
+ return 0;
+}
+
/*
* /proc fs routines....
*/
@@ -3909,6 +3903,7 @@ static const struct tty_operations ops = {
.hangup = hangup,
.tiocmget = tiocmget,
.tiocmset = tiocmset,
+ .get_icount = get_icount,
.proc_fops = &synclinkmp_proc_fops,
};
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index ef31bb81e843..f3019f53e875 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -772,6 +772,7 @@ static ssize_t write_sysrq_trigger(struct file *file, const char __user *buf,
static const struct file_operations proc_sysrq_trigger_operations = {
.write = write_sysrq_trigger,
+ .llseek = noop_llseek,
};
static void sysrq_init_procfs(void)
diff --git a/drivers/char/tb0219.c b/drivers/char/tb0219.c
index cad4eb65f13d..ad264185eb10 100644
--- a/drivers/char/tb0219.c
+++ b/drivers/char/tb0219.c
@@ -261,6 +261,7 @@ static const struct file_operations tb0219_fops = {
.write = tanbac_tb0219_write,
.open = tanbac_tb0219_open,
.release = tanbac_tb0219_release,
+ .llseek = no_llseek,
};
static void tb0219_restart(char *command)
diff --git a/drivers/char/tlclk.c b/drivers/char/tlclk.c
index 80ea6bcfffdc..0c964cdcc223 100644
--- a/drivers/char/tlclk.c
+++ b/drivers/char/tlclk.c
@@ -37,7 +37,7 @@
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/timer.h>
#include <linux/sysfs.h>
#include <linux/device.h>
@@ -206,7 +206,7 @@ static int tlclk_open(struct inode *inode, struct file *filp)
{
int result;
- lock_kernel();
+ mutex_lock(&tlclk_mutex);
if (test_and_set_bit(0, &useflags)) {
result = -EBUSY;
/* this legacy device is always one per system and it doesn't
@@ -229,7 +229,7 @@ static int tlclk_open(struct inode *inode, struct file *filp)
inb(TLCLK_REG6); /* Clear interrupt events */
out:
- unlock_kernel();
+ mutex_unlock(&tlclk_mutex);
return result;
}
@@ -267,6 +267,7 @@ static const struct file_operations tlclk_fops = {
.read = tlclk_read,
.open = tlclk_open,
.release = tlclk_release,
+ .llseek = noop_llseek,
};
diff --git a/drivers/char/toshiba.c b/drivers/char/toshiba.c
index f8bc79f6de34..014c9d90d297 100644
--- a/drivers/char/toshiba.c
+++ b/drivers/char/toshiba.c
@@ -68,7 +68,7 @@
#include <linux/stat.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/toshiba.h>
#define TOSH_MINOR_DEV 181
@@ -78,6 +78,7 @@ MODULE_AUTHOR("Jonathan Buzzard <jonathan@buzzard.org.uk>");
MODULE_DESCRIPTION("Toshiba laptop SMM driver");
MODULE_SUPPORTED_DEVICE("toshiba");
+static DEFINE_MUTEX(tosh_mutex);
static int tosh_fn;
module_param_named(fn, tosh_fn, int, 0);
MODULE_PARM_DESC(fn, "User specified Fn key detection port");
@@ -95,6 +96,7 @@ static long tosh_ioctl(struct file *, unsigned int,
static const struct file_operations tosh_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = tosh_ioctl,
+ .llseek = noop_llseek,
};
static struct miscdevice tosh_device = {
@@ -274,16 +276,16 @@ static long tosh_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
return -EINVAL;
/* do we need to emulate the fan ? */
- lock_kernel();
+ mutex_lock(&tosh_mutex);
if (tosh_fan==1) {
if (((ax==0xf300) || (ax==0xf400)) && (bx==0x0004)) {
err = tosh_emulate_fan(&regs);
- unlock_kernel();
+ mutex_unlock(&tosh_mutex);
break;
}
}
err = tosh_smm(&regs);
- unlock_kernel();
+ mutex_unlock(&tosh_mutex);
break;
default:
return -EINVAL;
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 05ad4a17a28f..7c4133582dba 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -47,6 +47,16 @@ enum tpm_duration {
#define TPM_MAX_PROTECTED_ORDINAL 12
#define TPM_PROTECTED_ORDINAL_MASK 0xFF
+/*
+ * Bug workaround - some TPM's don't flush the most
+ * recently changed pcr on suspend, so force the flush
+ * with an extend to the selected _unused_ non-volatile pcr.
+ */
+static int tpm_suspend_pcr;
+module_param_named(suspend_pcr, tpm_suspend_pcr, uint, 0644);
+MODULE_PARM_DESC(suspend_pcr,
+ "PCR to use for dummy writes to faciltate flush on suspend.");
+
static LIST_HEAD(tpm_chip_list);
static DEFINE_SPINLOCK(driver_lock);
static DECLARE_BITMAP(dev_mask, TPM_NUM_DEVICES);
@@ -1077,18 +1087,6 @@ static struct tpm_input_header savestate_header = {
.ordinal = TPM_ORD_SAVESTATE
};
-/* Bug workaround - some TPM's don't flush the most
- * recently changed pcr on suspend, so force the flush
- * with an extend to the selected _unused_ non-volatile pcr.
- */
-static int tpm_suspend_pcr;
-static int __init tpm_suspend_setup(char *str)
-{
- get_option(&str, &tpm_suspend_pcr);
- return 1;
-}
-__setup("tpm_suspend_pcr=", tpm_suspend_setup);
-
/*
* We are about to suspend. Save the TPM state
* so that it can be restored.
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 613c852ee0fe..c05c5af5aa04 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -96,6 +96,7 @@
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/seq_file.h>
+#include <linux/serial.h>
#include <linux/uaccess.h>
#include <asm/system.h>
@@ -183,6 +184,8 @@ struct tty_struct *alloc_tty_struct(void)
void free_tty_struct(struct tty_struct *tty)
{
+ if (tty->dev)
+ put_device(tty->dev);
kfree(tty->write_buf);
tty_buffer_free_all(tty);
kfree(tty);
@@ -194,12 +197,13 @@ static inline struct tty_struct *file_tty(struct file *file)
}
/* Associate a new file with the tty structure */
-void tty_add_file(struct tty_struct *tty, struct file *file)
+int tty_add_file(struct tty_struct *tty, struct file *file)
{
struct tty_file_private *priv;
- /* XXX: must implement proper error handling in callers */
- priv = kmalloc(sizeof(*priv), GFP_KERNEL|__GFP_NOFAIL);
+ priv = kmalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
priv->tty = tty;
priv->file = file;
@@ -208,6 +212,8 @@ void tty_add_file(struct tty_struct *tty, struct file *file)
spin_lock(&tty_files_lock);
list_add(&priv->list, &tty->tty_files);
spin_unlock(&tty_files_lock);
+
+ return 0;
}
/* Delete file from its tty */
@@ -1875,7 +1881,11 @@ got_driver:
return PTR_ERR(tty);
}
- tty_add_file(tty, filp);
+ retval = tty_add_file(tty, filp);
+ if (retval) {
+ tty_unlock();
+ return retval;
+ }
check_tty_count(tty, "tty_open");
if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
@@ -2502,6 +2512,20 @@ static int tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int
return tty->ops->tiocmset(tty, file, set, clear);
}
+static int tty_tiocgicount(struct tty_struct *tty, void __user *arg)
+{
+ int retval = -EINVAL;
+ struct serial_icounter_struct icount;
+ memset(&icount, 0, sizeof(icount));
+ if (tty->ops->get_icount)
+ retval = tty->ops->get_icount(tty, &icount);
+ if (retval != 0)
+ return retval;
+ if (copy_to_user(arg, &icount, sizeof(icount)))
+ return -EFAULT;
+ return 0;
+}
+
struct tty_struct *tty_pair_get_tty(struct tty_struct *tty)
{
if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
@@ -2622,6 +2646,12 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case TIOCMBIC:
case TIOCMBIS:
return tty_tiocmset(tty, file, cmd, p);
+ case TIOCGICOUNT:
+ retval = tty_tiocgicount(tty, p);
+ /* For the moment allow fall through to the old method */
+ if (retval != -EINVAL)
+ return retval;
+ break;
case TCFLSH:
switch (arg) {
case TCIFLUSH:
@@ -2783,6 +2813,20 @@ void do_SAK(struct tty_struct *tty)
EXPORT_SYMBOL(do_SAK);
+static int dev_match_devt(struct device *dev, void *data)
+{
+ dev_t *devt = data;
+ return dev->devt == *devt;
+}
+
+/* Must put_device() after it's unused! */
+static struct device *tty_get_device(struct tty_struct *tty)
+{
+ dev_t devt = tty_devnum(tty);
+ return class_find_device(tty_class, NULL, &devt, dev_match_devt);
+}
+
+
/**
* initialize_tty_struct
* @tty: tty to initialize
@@ -2823,6 +2867,7 @@ void initialize_tty_struct(struct tty_struct *tty,
tty->ops = driver->ops;
tty->index = idx;
tty_line_name(driver, idx, tty->name);
+ tty->dev = tty_get_device(tty);
}
/**
@@ -2980,6 +3025,7 @@ int tty_register_driver(struct tty_driver *driver)
int i;
dev_t dev;
void **p = NULL;
+ struct device *d;
if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM) && driver->num) {
p = kzalloc(driver->num * 2 * sizeof(void *), GFP_KERNEL);
@@ -3027,12 +3073,31 @@ int tty_register_driver(struct tty_driver *driver)
mutex_unlock(&tty_mutex);
if (!(driver->flags & TTY_DRIVER_DYNAMIC_DEV)) {
- for (i = 0; i < driver->num; i++)
- tty_register_device(driver, i, NULL);
+ for (i = 0; i < driver->num; i++) {
+ d = tty_register_device(driver, i, NULL);
+ if (IS_ERR(d)) {
+ error = PTR_ERR(d);
+ goto err;
+ }
+ }
}
proc_tty_register_driver(driver);
driver->flags |= TTY_DRIVER_INSTALLED;
return 0;
+
+err:
+ for (i--; i >= 0; i--)
+ tty_unregister_device(driver, i);
+
+ mutex_lock(&tty_mutex);
+ list_del(&driver->tty_drivers);
+ mutex_unlock(&tty_mutex);
+
+ unregister_chrdev_region(dev, driver->num);
+ driver->ttys = NULL;
+ driver->termios = NULL;
+ kfree(p);
+ return error;
}
EXPORT_SYMBOL(tty_register_driver);
diff --git a/drivers/char/ttyprintk.c b/drivers/char/ttyprintk.c
new file mode 100644
index 000000000000..c40c1612c8a7
--- /dev/null
+++ b/drivers/char/ttyprintk.c
@@ -0,0 +1,225 @@
+/*
+ * linux/drivers/char/ttyprintk.c
+ *
+ * Copyright (C) 2010 Samo Pogacnik
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the smems of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ */
+
+/*
+ * This pseudo device allows user to make printk messages. It is possible
+ * to store "console" messages inline with kernel messages for better analyses
+ * of the boot process, for example.
+ */
+
+#include <linux/device.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+
+struct ttyprintk_port {
+ struct tty_port port;
+ struct mutex port_write_mutex;
+};
+
+static struct ttyprintk_port tpk_port;
+
+/*
+ * Our simple preformatting supports transparent output of (time-stamped)
+ * printk messages (also suitable for logging service):
+ * - any cr is replaced by nl
+ * - adds a ttyprintk source tag in front of each line
+ * - too long message is fragmeted, with '\'nl between fragments
+ * - TPK_STR_SIZE isn't really the write_room limiting factor, bcause
+ * it is emptied on the fly during preformatting.
+ */
+#define TPK_STR_SIZE 508 /* should be bigger then max expected line length */
+#define TPK_MAX_ROOM 4096 /* we could assume 4K for instance */
+static const char *tpk_tag = "[U] "; /* U for User */
+static int tpk_curr;
+
+static int tpk_printk(const unsigned char *buf, int count)
+{
+ static char tmp[TPK_STR_SIZE + 4];
+ int i = tpk_curr;
+
+ if (buf == NULL) {
+ /* flush tmp[] */
+ if (tpk_curr > 0) {
+ /* non nl or cr terminated message - add nl */
+ tmp[tpk_curr + 0] = '\n';
+ tmp[tpk_curr + 1] = '\0';
+ printk(KERN_INFO "%s%s", tpk_tag, tmp);
+ tpk_curr = 0;
+ }
+ return i;
+ }
+
+ for (i = 0; i < count; i++) {
+ tmp[tpk_curr] = buf[i];
+ if (tpk_curr < TPK_STR_SIZE) {
+ switch (buf[i]) {
+ case '\r':
+ /* replace cr with nl */
+ tmp[tpk_curr + 0] = '\n';
+ tmp[tpk_curr + 1] = '\0';
+ printk(KERN_INFO "%s%s", tpk_tag, tmp);
+ tpk_curr = 0;
+ if (buf[i + 1] == '\n')
+ i++;
+ break;
+ case '\n':
+ tmp[tpk_curr + 1] = '\0';
+ printk(KERN_INFO "%s%s", tpk_tag, tmp);
+ tpk_curr = 0;
+ break;
+ default:
+ tpk_curr++;
+ }
+ } else {
+ /* end of tmp buffer reached: cut the message in two */
+ tmp[tpk_curr + 1] = '\\';
+ tmp[tpk_curr + 2] = '\n';
+ tmp[tpk_curr + 3] = '\0';
+ printk(KERN_INFO "%s%s", tpk_tag, tmp);
+ tpk_curr = 0;
+ }
+ }
+
+ return count;
+}
+
+/*
+ * TTY operations open function.
+ */
+static int tpk_open(struct tty_struct *tty, struct file *filp)
+{
+ tty->driver_data = &tpk_port;
+
+ return tty_port_open(&tpk_port.port, tty, filp);
+}
+
+/*
+ * TTY operations close function.
+ */
+static void tpk_close(struct tty_struct *tty, struct file *filp)
+{
+ struct ttyprintk_port *tpkp = tty->driver_data;
+
+ mutex_lock(&tpkp->port_write_mutex);
+ /* flush tpk_printk buffer */
+ tpk_printk(NULL, 0);
+ mutex_unlock(&tpkp->port_write_mutex);
+
+ tty_port_close(&tpkp->port, tty, filp);
+}
+
+/*
+ * TTY operations write function.
+ */
+static int tpk_write(struct tty_struct *tty,
+ const unsigned char *buf, int count)
+{
+ struct ttyprintk_port *tpkp = tty->driver_data;
+ int ret;
+
+
+ /* exclusive use of tpk_printk within this tty */
+ mutex_lock(&tpkp->port_write_mutex);
+ ret = tpk_printk(buf, count);
+ mutex_unlock(&tpkp->port_write_mutex);
+
+ return ret;
+}
+
+/*
+ * TTY operations write_room function.
+ */
+static int tpk_write_room(struct tty_struct *tty)
+{
+ return TPK_MAX_ROOM;
+}
+
+/*
+ * TTY operations ioctl function.
+ */
+static int tpk_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct ttyprintk_port *tpkp = tty->driver_data;
+
+ if (!tpkp)
+ return -EINVAL;
+
+ switch (cmd) {
+ /* Stop TIOCCONS */
+ case TIOCCONS:
+ return -EOPNOTSUPP;
+ default:
+ return -ENOIOCTLCMD;
+ }
+ return 0;
+}
+
+static const struct tty_operations ttyprintk_ops = {
+ .open = tpk_open,
+ .close = tpk_close,
+ .write = tpk_write,
+ .write_room = tpk_write_room,
+ .ioctl = tpk_ioctl,
+};
+
+struct tty_port_operations null_ops = { };
+
+static struct tty_driver *ttyprintk_driver;
+
+static int __init ttyprintk_init(void)
+{
+ int ret = -ENOMEM;
+ void *rp;
+
+ ttyprintk_driver = alloc_tty_driver(1);
+ if (!ttyprintk_driver)
+ return ret;
+
+ ttyprintk_driver->owner = THIS_MODULE;
+ ttyprintk_driver->driver_name = "ttyprintk";
+ ttyprintk_driver->name = "ttyprintk";
+ ttyprintk_driver->major = TTYAUX_MAJOR;
+ ttyprintk_driver->minor_start = 3;
+ ttyprintk_driver->num = 1;
+ ttyprintk_driver->type = TTY_DRIVER_TYPE_CONSOLE;
+ ttyprintk_driver->init_termios = tty_std_termios;
+ ttyprintk_driver->init_termios.c_oflag = OPOST | OCRNL | ONOCR | ONLRET;
+ ttyprintk_driver->flags = TTY_DRIVER_RESET_TERMIOS |
+ TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+ tty_set_operations(ttyprintk_driver, &ttyprintk_ops);
+
+ ret = tty_register_driver(ttyprintk_driver);
+ if (ret < 0) {
+ printk(KERN_ERR "Couldn't register ttyprintk driver\n");
+ goto error;
+ }
+
+ /* create our unnumbered device */
+ rp = device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 3), NULL,
+ ttyprintk_driver->name);
+ if (IS_ERR(rp)) {
+ printk(KERN_ERR "Couldn't create ttyprintk device\n");
+ ret = PTR_ERR(rp);
+ goto error;
+ }
+
+ tty_port_init(&tpk_port.port);
+ tpk_port.port.ops = &null_ops;
+ mutex_init(&tpk_port.port_write_mutex);
+
+ return 0;
+
+error:
+ put_tty_driver(ttyprintk_driver);
+ ttyprintk_driver = NULL;
+ return ret;
+}
+module_init(ttyprintk_init);
diff --git a/drivers/char/uv_mmtimer.c b/drivers/char/uv_mmtimer.c
index c7072ba14f48..493b47a0d511 100644
--- a/drivers/char/uv_mmtimer.c
+++ b/drivers/char/uv_mmtimer.c
@@ -52,6 +52,7 @@ static const struct file_operations uv_mmtimer_fops = {
.owner = THIS_MODULE,
.mmap = uv_mmtimer_mmap,
.unlocked_ioctl = uv_mmtimer_ioctl,
+ .llseek = noop_llseek,
};
/**
diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c
index bcce46c96b88..273ab44cc91d 100644
--- a/drivers/char/vc_screen.c
+++ b/drivers/char/vc_screen.c
@@ -35,6 +35,12 @@
#include <linux/console.h>
#include <linux/device.h>
#include <linux/smp_lock.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <linux/signal.h>
+#include <linux/slab.h>
+#include <linux/notifier.h>
#include <asm/uaccess.h>
#include <asm/byteorder.h>
@@ -45,6 +51,86 @@
#undef addr
#define HEADER_SIZE 4
+struct vcs_poll_data {
+ struct notifier_block notifier;
+ unsigned int cons_num;
+ bool seen_last_update;
+ wait_queue_head_t waitq;
+ struct fasync_struct *fasync;
+};
+
+static int
+vcs_notifier(struct notifier_block *nb, unsigned long code, void *_param)
+{
+ struct vt_notifier_param *param = _param;
+ struct vc_data *vc = param->vc;
+ struct vcs_poll_data *poll =
+ container_of(nb, struct vcs_poll_data, notifier);
+ int currcons = poll->cons_num;
+
+ if (code != VT_UPDATE)
+ return NOTIFY_DONE;
+
+ if (currcons == 0)
+ currcons = fg_console;
+ else
+ currcons--;
+ if (currcons != vc->vc_num)
+ return NOTIFY_DONE;
+
+ poll->seen_last_update = false;
+ wake_up_interruptible(&poll->waitq);
+ kill_fasync(&poll->fasync, SIGIO, POLL_IN);
+ return NOTIFY_OK;
+}
+
+static void
+vcs_poll_data_free(struct vcs_poll_data *poll)
+{
+ unregister_vt_notifier(&poll->notifier);
+ kfree(poll);
+}
+
+static struct vcs_poll_data *
+vcs_poll_data_get(struct file *file)
+{
+ struct vcs_poll_data *poll = file->private_data;
+
+ if (poll)
+ return poll;
+
+ poll = kzalloc(sizeof(*poll), GFP_KERNEL);
+ if (!poll)
+ return NULL;
+ poll->cons_num = iminor(file->f_path.dentry->d_inode) & 127;
+ init_waitqueue_head(&poll->waitq);
+ poll->notifier.notifier_call = vcs_notifier;
+ if (register_vt_notifier(&poll->notifier) != 0) {
+ kfree(poll);
+ return NULL;
+ }
+
+ /*
+ * This code may be called either through ->poll() or ->fasync().
+ * If we have two threads using the same file descriptor, they could
+ * both enter this function, both notice that the structure hasn't
+ * been allocated yet and go ahead allocating it in parallel, but
+ * only one of them must survive and be shared otherwise we'd leak
+ * memory with a dangling notifier callback.
+ */
+ spin_lock(&file->f_lock);
+ if (!file->private_data) {
+ file->private_data = poll;
+ } else {
+ /* someone else raced ahead of us */
+ vcs_poll_data_free(poll);
+ poll = file->private_data;
+ }
+ spin_unlock(&file->f_lock);
+
+ return poll;
+}
+
static int
vcs_size(struct inode *inode)
{
@@ -102,6 +188,7 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
struct inode *inode = file->f_path.dentry->d_inode;
unsigned int currcons = iminor(inode);
struct vc_data *vc;
+ struct vcs_poll_data *poll;
long pos;
long viewed, attr, read;
int col, maxcol;
@@ -134,6 +221,9 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
ret = -EINVAL;
if (pos < 0)
goto unlock_out;
+ poll = file->private_data;
+ if (count && poll)
+ poll->seen_last_update = true;
read = 0;
ret = 0;
while (count) {
@@ -448,6 +538,8 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
}
*ppos += written;
ret = written;
+ if (written)
+ vcs_scr_updated(vc);
unlock_out:
release_console_sem();
@@ -457,6 +549,37 @@ unlock_out:
return ret;
}
+static unsigned int
+vcs_poll(struct file *file, poll_table *wait)
+{
+ struct vcs_poll_data *poll = vcs_poll_data_get(file);
+ int ret = 0;
+
+ if (poll) {
+ poll_wait(file, &poll->waitq, wait);
+ if (!poll->seen_last_update)
+ ret = POLLIN | POLLRDNORM;
+ }
+ return ret;
+}
+
+static int
+vcs_fasync(int fd, struct file *file, int on)
+{
+ struct vcs_poll_data *poll = file->private_data;
+
+ if (!poll) {
+ /* don't allocate anything if all we want is disable fasync */
+ if (!on)
+ return 0;
+ poll = vcs_poll_data_get(file);
+ if (!poll)
+ return -ENOMEM;
+ }
+
+ return fasync_helper(fd, file, on, &poll->fasync);
+}
+
static int
vcs_open(struct inode *inode, struct file *filp)
{
@@ -470,11 +593,23 @@ vcs_open(struct inode *inode, struct file *filp)
return ret;
}
+static int vcs_release(struct inode *inode, struct file *file)
+{
+ struct vcs_poll_data *poll = file->private_data;
+
+ if (poll)
+ vcs_poll_data_free(poll);
+ return 0;
+}
+
static const struct file_operations vcs_fops = {
.llseek = vcs_lseek,
.read = vcs_read,
.write = vcs_write,
+ .poll = vcs_poll,
+ .fasync = vcs_fasync,
.open = vcs_open,
+ .release = vcs_release,
};
static struct class *vc_class;
diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c
index 42f7fa442ff8..ad6e64a2912d 100644
--- a/drivers/char/viotape.c
+++ b/drivers/char/viotape.c
@@ -46,7 +46,7 @@
#include <linux/completion.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/slab.h>
#include <asm/uaccess.h>
@@ -64,6 +64,7 @@
#define VIOTAPE_KERN_WARN KERN_WARNING "viotape: "
#define VIOTAPE_KERN_INFO KERN_INFO "viotape: "
+static DEFINE_MUTEX(proc_viotape_mutex);
static int viotape_numdev;
/*
@@ -684,9 +685,9 @@ static long viotap_unlocked_ioctl(struct file *file,
{
long rc;
- lock_kernel();
+ mutex_lock(&proc_viotape_mutex);
rc = viotap_ioctl(file->f_path.dentry->d_inode, file, cmd, arg);
- unlock_kernel();
+ mutex_unlock(&proc_viotape_mutex);
return rc;
}
@@ -700,7 +701,7 @@ static int viotap_open(struct inode *inode, struct file *file)
if (op == NULL)
return -ENOMEM;
- lock_kernel();
+ mutex_lock(&proc_viotape_mutex);
get_dev_info(file->f_path.dentry->d_inode, &devi);
/* Note: We currently only support one mode! */
@@ -731,7 +732,7 @@ static int viotap_open(struct inode *inode, struct file *file)
free_op:
free_op_struct(op);
- unlock_kernel();
+ mutex_unlock(&proc_viotape_mutex);
return ret;
}
@@ -804,6 +805,7 @@ const struct file_operations viotap_fops = {
.unlocked_ioctl = viotap_unlocked_ioctl,
.open = viotap_open,
.release = viotap_release,
+ .llseek = noop_llseek,
};
/* Handle interrupt events for tape */
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index c810481a5bc2..6c1b676643a9 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -48,6 +48,9 @@ struct ports_driver_data {
/* Used for exporting per-port information to debugfs */
struct dentry *debugfs_dir;
+ /* List of all the devices we're handling */
+ struct list_head portdevs;
+
/* Number of devices this driver is handling */
unsigned int index;
@@ -108,6 +111,9 @@ struct port_buffer {
* ports for that device (vdev->priv).
*/
struct ports_device {
+ /* Next portdev in the list, head is in the pdrvdata struct */
+ struct list_head list;
+
/*
* Workqueue handlers where we process deferred work after
* notification
@@ -178,15 +184,21 @@ struct port {
struct console cons;
/* Each port associates with a separate char device */
- struct cdev cdev;
+ struct cdev *cdev;
struct device *dev;
+ /* Reference-counting to handle port hot-unplugs and file operations */
+ struct kref kref;
+
/* A waitqueue for poll() or blocking read operations */
wait_queue_head_t waitqueue;
/* The 'name' of the port that we expose via sysfs properties */
char *name;
+ /* We can notify apps of host connect / disconnect events via SIGIO */
+ struct fasync_struct *async_queue;
+
/* The 'id' to identify the port with the Host */
u32 id;
@@ -221,6 +233,41 @@ out:
return port;
}
+static struct port *find_port_by_devt_in_portdev(struct ports_device *portdev,
+ dev_t dev)
+{
+ struct port *port;
+ unsigned long flags;
+
+ spin_lock_irqsave(&portdev->ports_lock, flags);
+ list_for_each_entry(port, &portdev->ports, list)
+ if (port->cdev->dev == dev)
+ goto out;
+ port = NULL;
+out:
+ spin_unlock_irqrestore(&portdev->ports_lock, flags);
+
+ return port;
+}
+
+static struct port *find_port_by_devt(dev_t dev)
+{
+ struct ports_device *portdev;
+ struct port *port;
+ unsigned long flags;
+
+ spin_lock_irqsave(&pdrvdata_lock, flags);
+ list_for_each_entry(portdev, &pdrvdata.portdevs, list) {
+ port = find_port_by_devt_in_portdev(portdev, dev);
+ if (port)
+ goto out;
+ }
+ port = NULL;
+out:
+ spin_unlock_irqrestore(&pdrvdata_lock, flags);
+ return port;
+}
+
static struct port *find_port_by_id(struct ports_device *portdev, u32 id)
{
struct port *port;
@@ -410,7 +457,10 @@ static ssize_t __send_control_msg(struct ports_device *portdev, u32 port_id,
static ssize_t send_control_msg(struct port *port, unsigned int event,
unsigned int value)
{
- return __send_control_msg(port->portdev, port->id, event, value);
+ /* Did the port get unplugged before userspace closed it? */
+ if (port->portdev)
+ return __send_control_msg(port->portdev, port->id, event, value);
+ return 0;
}
/* Callers must take the port->outvq_lock */
@@ -459,9 +509,12 @@ static ssize_t send_buf(struct port *port, void *in_buf, size_t in_count,
/*
* Wait till the host acknowledges it pushed out the data we
- * sent. This is done for ports in blocking mode or for data
- * from the hvc_console; the tty operations are performed with
- * spinlocks held so we can't sleep here.
+ * sent. This is done for data from the hvc_console; the tty
+ * operations are performed with spinlocks held so we can't
+ * sleep here. An alternative would be to copy the data to a
+ * buffer and relax the spinning requirement. The downside is
+ * we need to kmalloc a GFP_ATOMIC buffer each time the
+ * console driver writes something out.
*/
while (!virtqueue_get_buf(out_vq, &len))
cpu_relax();
@@ -522,6 +575,10 @@ static ssize_t fill_readbuf(struct port *port, char *out_buf, size_t out_count,
/* The condition that must be true for polling to end */
static bool will_read_block(struct port *port)
{
+ if (!port->guest_connected) {
+ /* Port got hot-unplugged. Let's exit. */
+ return false;
+ }
return !port_has_data(port) && port->host_connected;
}
@@ -572,6 +629,9 @@ static ssize_t port_fops_read(struct file *filp, char __user *ubuf,
if (ret < 0)
return ret;
}
+ /* Port got hot-unplugged. */
+ if (!port->guest_connected)
+ return -ENODEV;
/*
* We could've received a disconnection message while we were
* waiting for more data.
@@ -613,6 +673,9 @@ static ssize_t port_fops_write(struct file *filp, const char __user *ubuf,
if (ret < 0)
return ret;
}
+ /* Port got hot-unplugged. */
+ if (!port->guest_connected)
+ return -ENODEV;
count = min((size_t)(32 * 1024), count);
@@ -626,6 +689,14 @@ static ssize_t port_fops_write(struct file *filp, const char __user *ubuf,
goto free_buf;
}
+ /*
+ * We now ask send_buf() to not spin for generic ports -- we
+ * can re-use the same code path that non-blocking file
+ * descriptors take for blocking file descriptors since the
+ * wait is already done and we're certain the write will go
+ * through to the host.
+ */
+ nonblock = true;
ret = send_buf(port, buf, count, nonblock);
if (nonblock && ret > 0)
@@ -645,6 +716,10 @@ static unsigned int port_fops_poll(struct file *filp, poll_table *wait)
port = filp->private_data;
poll_wait(filp, &port->waitqueue, wait);
+ if (!port->guest_connected) {
+ /* Port got unplugged */
+ return POLLHUP;
+ }
ret = 0;
if (!will_read_block(port))
ret |= POLLIN | POLLRDNORM;
@@ -656,6 +731,8 @@ static unsigned int port_fops_poll(struct file *filp, poll_table *wait)
return ret;
}
+static void remove_port(struct kref *kref);
+
static int port_fops_release(struct inode *inode, struct file *filp)
{
struct port *port;
@@ -676,6 +753,16 @@ static int port_fops_release(struct inode *inode, struct file *filp)
reclaim_consumed_buffers(port);
spin_unlock_irq(&port->outvq_lock);
+ /*
+ * Locks aren't necessary here as a port can't be opened after
+ * unplug, and if a port isn't unplugged, a kref would already
+ * exist for the port. Plus, taking ports_lock here would
+ * create a dependency on other locks taken by functions
+ * inside remove_port if we're the last holder of the port,
+ * creating many problems.
+ */
+ kref_put(&port->kref, remove_port);
+
return 0;
}
@@ -683,22 +770,31 @@ static int port_fops_open(struct inode *inode, struct file *filp)
{
struct cdev *cdev = inode->i_cdev;
struct port *port;
+ int ret;
- port = container_of(cdev, struct port, cdev);
+ port = find_port_by_devt(cdev->dev);
filp->private_data = port;
+ /* Prevent against a port getting hot-unplugged at the same time */
+ spin_lock_irq(&port->portdev->ports_lock);
+ kref_get(&port->kref);
+ spin_unlock_irq(&port->portdev->ports_lock);
+
/*
* Don't allow opening of console port devices -- that's done
* via /dev/hvc
*/
- if (is_console_port(port))
- return -ENXIO;
+ if (is_console_port(port)) {
+ ret = -ENXIO;
+ goto out;
+ }
/* Allow only one process to open a particular port at a time */
spin_lock_irq(&port->inbuf_lock);
if (port->guest_connected) {
spin_unlock_irq(&port->inbuf_lock);
- return -EMFILE;
+ ret = -EMFILE;
+ goto out;
}
port->guest_connected = true;
@@ -713,10 +809,23 @@ static int port_fops_open(struct inode *inode, struct file *filp)
reclaim_consumed_buffers(port);
spin_unlock_irq(&port->outvq_lock);
+ nonseekable_open(inode, filp);
+
/* Notify host of port being opened */
send_control_msg(filp->private_data, VIRTIO_CONSOLE_PORT_OPEN, 1);
return 0;
+out:
+ kref_put(&port->kref, remove_port);
+ return ret;
+}
+
+static int port_fops_fasync(int fd, struct file *filp, int mode)
+{
+ struct port *port;
+
+ port = filp->private_data;
+ return fasync_helper(fd, filp, mode, &port->async_queue);
}
/*
@@ -732,6 +841,8 @@ static const struct file_operations port_fops = {
.write = port_fops_write,
.poll = port_fops_poll,
.release = port_fops_release,
+ .fasync = port_fops_fasync,
+ .llseek = no_llseek,
};
/*
@@ -990,6 +1101,12 @@ static unsigned int fill_queue(struct virtqueue *vq, spinlock_t *lock)
return nr_added_bufs;
}
+static void send_sigio_to_port(struct port *port)
+{
+ if (port->async_queue && port->guest_connected)
+ kill_fasync(&port->async_queue, SIGIO, POLL_OUT);
+}
+
static int add_port(struct ports_device *portdev, u32 id)
{
char debugfs_name[16];
@@ -1004,6 +1121,7 @@ static int add_port(struct ports_device *portdev, u32 id)
err = -ENOMEM;
goto fail;
}
+ kref_init(&port->kref);
port->portdev = portdev;
port->id = id;
@@ -1011,6 +1129,7 @@ static int add_port(struct ports_device *portdev, u32 id)
port->name = NULL;
port->inbuf = NULL;
port->cons.hvc = NULL;
+ port->async_queue = NULL;
port->cons.ws.ws_row = port->cons.ws.ws_col = 0;
@@ -1021,14 +1140,20 @@ static int add_port(struct ports_device *portdev, u32 id)
port->in_vq = portdev->in_vqs[port->id];
port->out_vq = portdev->out_vqs[port->id];
- cdev_init(&port->cdev, &port_fops);
+ port->cdev = cdev_alloc();
+ if (!port->cdev) {
+ dev_err(&port->portdev->vdev->dev, "Error allocating cdev\n");
+ err = -ENOMEM;
+ goto free_port;
+ }
+ port->cdev->ops = &port_fops;
devt = MKDEV(portdev->chr_major, id);
- err = cdev_add(&port->cdev, devt, 1);
+ err = cdev_add(port->cdev, devt, 1);
if (err < 0) {
dev_err(&port->portdev->vdev->dev,
"Error %d adding cdev for port %u\n", err, id);
- goto free_port;
+ goto free_cdev;
}
port->dev = device_create(pdrvdata.class, &port->portdev->vdev->dev,
devt, port, "vport%up%u",
@@ -1093,7 +1218,7 @@ free_inbufs:
free_device:
device_destroy(pdrvdata.class, port->dev->devt);
free_cdev:
- cdev_del(&port->cdev);
+ cdev_del(port->cdev);
free_port:
kfree(port);
fail:
@@ -1102,21 +1227,45 @@ fail:
return err;
}
-/* Remove all port-specific data. */
-static int remove_port(struct port *port)
+/* No users remain, remove all port-specific data. */
+static void remove_port(struct kref *kref)
+{
+ struct port *port;
+
+ port = container_of(kref, struct port, kref);
+
+ sysfs_remove_group(&port->dev->kobj, &port_attribute_group);
+ device_destroy(pdrvdata.class, port->dev->devt);
+ cdev_del(port->cdev);
+
+ kfree(port->name);
+
+ debugfs_remove(port->debugfs_file);
+
+ kfree(port);
+}
+
+/*
+ * Port got unplugged. Remove port from portdev's list and drop the
+ * kref reference. If no userspace has this port opened, it will
+ * result in immediate removal the port.
+ */
+static void unplug_port(struct port *port)
{
struct port_buffer *buf;
+ spin_lock_irq(&port->portdev->ports_lock);
+ list_del(&port->list);
+ spin_unlock_irq(&port->portdev->ports_lock);
+
if (port->guest_connected) {
port->guest_connected = false;
port->host_connected = false;
wake_up_interruptible(&port->waitqueue);
- send_control_msg(port, VIRTIO_CONSOLE_PORT_OPEN, 0);
- }
- spin_lock_irq(&port->portdev->ports_lock);
- list_del(&port->list);
- spin_unlock_irq(&port->portdev->ports_lock);
+ /* Let the app know the port is going down. */
+ send_sigio_to_port(port);
+ }
if (is_console_port(port)) {
spin_lock_irq(&pdrvdata_lock);
@@ -1135,9 +1284,6 @@ static int remove_port(struct port *port)
hvc_remove(port->cons.hvc);
#endif
}
- sysfs_remove_group(&port->dev->kobj, &port_attribute_group);
- device_destroy(pdrvdata.class, port->dev->devt);
- cdev_del(&port->cdev);
/* Remove unused data this port might have received. */
discard_port_data(port);
@@ -1148,12 +1294,19 @@ static int remove_port(struct port *port)
while ((buf = virtqueue_detach_unused_buf(port->in_vq)))
free_buf(buf);
- kfree(port->name);
-
- debugfs_remove(port->debugfs_file);
+ /*
+ * We should just assume the device itself has gone off --
+ * else a close on an open port later will try to send out a
+ * control message.
+ */
+ port->portdev = NULL;
- kfree(port);
- return 0;
+ /*
+ * Locks around here are not necessary - a port can't be
+ * opened after we removed the port struct from ports_list
+ * above.
+ */
+ kref_put(&port->kref, remove_port);
}
/* Any private messages that the Host and Guest want to share */
@@ -1192,7 +1345,7 @@ static void handle_control_message(struct ports_device *portdev,
add_port(portdev, cpkt->id);
break;
case VIRTIO_CONSOLE_PORT_REMOVE:
- remove_port(port);
+ unplug_port(port);
break;
case VIRTIO_CONSOLE_CONSOLE_PORT:
if (!cpkt->value)
@@ -1234,6 +1387,12 @@ static void handle_control_message(struct ports_device *portdev,
spin_lock_irq(&port->outvq_lock);
reclaim_consumed_buffers(port);
spin_unlock_irq(&port->outvq_lock);
+
+ /*
+ * If the guest is connected, it'll be interested in
+ * knowing the host connection state changed.
+ */
+ send_sigio_to_port(port);
break;
case VIRTIO_CONSOLE_PORT_NAME:
/*
@@ -1330,6 +1489,9 @@ static void in_intr(struct virtqueue *vq)
wake_up_interruptible(&port->waitqueue);
+ /* Send a SIGIO indicating new data in case the process asked for it */
+ send_sigio_to_port(port);
+
if (is_console_port(port) && hvc_poll(port->cons.hvc))
hvc_kick();
}
@@ -1566,6 +1728,10 @@ static int __devinit virtcons_probe(struct virtio_device *vdev)
add_port(portdev, 0);
}
+ spin_lock_irq(&pdrvdata_lock);
+ list_add_tail(&portdev->list, &pdrvdata.portdevs);
+ spin_unlock_irq(&pdrvdata_lock);
+
__send_control_msg(portdev, VIRTIO_CONSOLE_BAD_ID,
VIRTIO_CONSOLE_DEVICE_READY, 1);
return 0;
@@ -1589,23 +1755,41 @@ static void virtcons_remove(struct virtio_device *vdev)
{
struct ports_device *portdev;
struct port *port, *port2;
- struct port_buffer *buf;
- unsigned int len;
portdev = vdev->priv;
+ spin_lock_irq(&pdrvdata_lock);
+ list_del(&portdev->list);
+ spin_unlock_irq(&pdrvdata_lock);
+
+ /* Disable interrupts for vqs */
+ vdev->config->reset(vdev);
+ /* Finish up work that's lined up */
cancel_work_sync(&portdev->control_work);
list_for_each_entry_safe(port, port2, &portdev->ports, list)
- remove_port(port);
+ unplug_port(port);
unregister_chrdev(portdev->chr_major, "virtio-portsdev");
- while ((buf = virtqueue_get_buf(portdev->c_ivq, &len)))
- free_buf(buf);
+ /*
+ * When yanking out a device, we immediately lose the
+ * (device-side) queues. So there's no point in keeping the
+ * guest side around till we drop our final reference. This
+ * also means that any ports which are in an open state will
+ * have to just stop using the port, as the vqs are going
+ * away.
+ */
+ if (use_multiport(portdev)) {
+ struct port_buffer *buf;
+ unsigned int len;
- while ((buf = virtqueue_detach_unused_buf(portdev->c_ivq)))
- free_buf(buf);
+ while ((buf = virtqueue_get_buf(portdev->c_ivq, &len)))
+ free_buf(buf);
+
+ while ((buf = virtqueue_detach_unused_buf(portdev->c_ivq)))
+ free_buf(buf);
+ }
vdev->config->del_vqs(vdev);
kfree(portdev->in_vqs);
@@ -1652,6 +1836,7 @@ static int __init init(void)
PTR_ERR(pdrvdata.debugfs_dir));
}
INIT_LIST_HEAD(&pdrvdata.consoles);
+ INIT_LIST_HEAD(&pdrvdata.portdevs);
return register_virtio_driver(&virtio_console);
}
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 281aada7b4a1..a8ec48ed14d9 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -4182,6 +4182,11 @@ void vcs_scr_writew(struct vc_data *vc, u16 val, u16 *org)
}
}
+void vcs_scr_updated(struct vc_data *vc)
+{
+ notify_update(vc);
+}
+
/*
* Visible symbols for modules
*/
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
index b663d573aad9..9f2272e6de1c 100644
--- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c
+++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
@@ -81,7 +81,6 @@
#include <linux/poll.h>
#include <linux/proc_fs.h>
#include <linux/mutex.h>
-#include <linux/smp_lock.h>
#include <linux/sysctl.h>
#include <linux/fs.h>
#include <linux/cdev.h>
@@ -112,6 +111,7 @@
#define HWICAP_DEVICES 1
/* An array, which is set to true when the device is registered. */
+static DEFINE_MUTEX(hwicap_mutex);
static bool probed_devices[HWICAP_DEVICES];
static struct mutex icap_sem;
@@ -502,7 +502,7 @@ static int hwicap_open(struct inode *inode, struct file *file)
struct hwicap_drvdata *drvdata;
int status;
- lock_kernel();
+ mutex_lock(&hwicap_mutex);
drvdata = container_of(inode->i_cdev, struct hwicap_drvdata, cdev);
status = mutex_lock_interruptible(&drvdata->sem);
@@ -528,7 +528,7 @@ static int hwicap_open(struct inode *inode, struct file *file)
error:
mutex_unlock(&drvdata->sem);
out:
- unlock_kernel();
+ mutex_unlock(&hwicap_mutex);
return status;
}
@@ -567,6 +567,7 @@ static const struct file_operations hwicap_fops = {
.read = hwicap_read,
.open = hwicap_open,
.release = hwicap_release,
+ .llseek = noop_llseek,
};
static int __devinit hwicap_setup(struct device *dev, int id,
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c
index c2408bbe9c2e..f508690eb958 100644
--- a/drivers/cpuidle/governors/menu.c
+++ b/drivers/cpuidle/governors/menu.c
@@ -80,7 +80,7 @@
* Limiting Performance Impact
* ---------------------------
* C states, especially those with large exit latencies, can have a real
- * noticable impact on workloads, which is not acceptable for most sysadmins,
+ * noticeable impact on workloads, which is not acceptable for most sysadmins,
* and in addition, less performance has a power price of its own.
*
* As a general rule of thumb, menu assumes that the following heuristic
diff --git a/drivers/dma/coh901318.c b/drivers/dma/coh901318.c
index 557e2272e5b3..ae2b8714d190 100644
--- a/drivers/dma/coh901318.c
+++ b/drivers/dma/coh901318.c
@@ -157,6 +157,7 @@ static const struct file_operations coh901318_debugfs_status_operations = {
.owner = THIS_MODULE,
.open = coh901318_debugfs_open,
.read = coh901318_debugfs_read,
+ .llseek = default_llseek,
};
diff --git a/drivers/dma/ioat/dma_v2.c b/drivers/dma/ioat/dma_v2.c
index 216f9d383b5b..effd140fc042 100644
--- a/drivers/dma/ioat/dma_v2.c
+++ b/drivers/dma/ioat/dma_v2.c
@@ -879,7 +879,7 @@ int __devinit ioat2_dma_probe(struct ioatdma_device *device, int dca)
dma->device_issue_pending = ioat2_issue_pending;
dma->device_alloc_chan_resources = ioat2_alloc_chan_resources;
dma->device_free_chan_resources = ioat2_free_chan_resources;
- dma->device_tx_status = ioat_tx_status;
+ dma->device_tx_status = ioat_dma_tx_status;
err = ioat_probe(device);
if (err)
diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c
index fb64cf36ba61..eb6b54dbb806 100644
--- a/drivers/dma/shdma.c
+++ b/drivers/dma/shdma.c
@@ -580,7 +580,6 @@ static struct dma_async_tx_descriptor *sh_dmae_prep_slave_sg(
sh_chan = to_sh_chan(chan);
param = chan->private;
- slave_addr = param->config->addr;
/* Someone calling slave DMA on a public channel? */
if (!param || !sg_len) {
@@ -589,6 +588,8 @@ static struct dma_async_tx_descriptor *sh_dmae_prep_slave_sg(
return NULL;
}
+ slave_addr = param->config->addr;
+
/*
* if (param != NULL), this is a successfully requested slave channel,
* therefore param->config != NULL too.
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index 70bb350de996..9dbb28b9559f 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -39,7 +39,7 @@ config EDAC_DEBUG
there're four debug levels (x=0,1,2,3 from low to high).
Usually you should select 'N'.
- config EDAC_DECODE_MCE
+config EDAC_DECODE_MCE
tristate "Decode MCEs in human-readable form (only on AMD for now)"
depends on CPU_SUP_AMD && X86_MCE
default y
@@ -51,6 +51,16 @@ config EDAC_DEBUG
which occur really early upon boot, before the module infrastructure
has been initialized.
+config EDAC_MCE_INJ
+ tristate "Simple MCE injection interface over /sysfs"
+ depends on EDAC_DECODE_MCE
+ default n
+ help
+ This is a simple interface to inject MCEs over /sysfs and test
+ the MCE decoding code in EDAC.
+
+ This is currently AMD-only.
+
config EDAC_MM_EDAC
tristate "Main Memory EDAC (Error Detection And Correction) reporting"
help
@@ -66,13 +76,13 @@ config EDAC_MCE
config EDAC_AMD64
tristate "AMD64 (Opteron, Athlon64) K8, F10h, F11h"
- depends on EDAC_MM_EDAC && K8_NB && X86_64 && PCI && EDAC_DECODE_MCE
+ depends on EDAC_MM_EDAC && AMD_NB && X86_64 && PCI && EDAC_DECODE_MCE
help
Support for error detection and correction on the AMD 64
Families of Memory Controllers (K8, F10h and F11h)
config EDAC_AMD64_ERROR_INJECTION
- bool "Sysfs Error Injection facilities"
+ bool "Sysfs HW Error injection facilities"
depends on EDAC_AMD64
help
Recent Opterons (Family 10h and later) provide for Memory Error
diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile
index ca6b1bb24ccc..32c7bc93c525 100644
--- a/drivers/edac/Makefile
+++ b/drivers/edac/Makefile
@@ -17,6 +17,9 @@ ifdef CONFIG_PCI
edac_core-objs += edac_pci.o edac_pci_sysfs.o
endif
+obj-$(CONFIG_EDAC_MCE_INJ) += mce_amd_inj.o
+
+edac_mce_amd-objs := mce_amd.o
obj-$(CONFIG_EDAC_DECODE_MCE) += edac_mce_amd.o
obj-$(CONFIG_EDAC_AMD76X) += amd76x_edac.o
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index e7d5d6b5dcf6..8521401bbd75 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -1,5 +1,5 @@
#include "amd64_edac.h"
-#include <asm/k8.h>
+#include <asm/amd_nb.h>
static struct edac_pci_ctl_info *amd64_ctl_pci;
@@ -2073,11 +2073,18 @@ static inline void __amd64_decode_bus_error(struct mem_ctl_info *mci,
amd64_handle_ue(mci, info);
}
-void amd64_decode_bus_error(int node_id, struct err_regs *regs)
+void amd64_decode_bus_error(int node_id, struct mce *m, u32 nbcfg)
{
struct mem_ctl_info *mci = mci_lookup[node_id];
+ struct err_regs regs;
- __amd64_decode_bus_error(mci, regs);
+ regs.nbsl = (u32) m->status;
+ regs.nbsh = (u32)(m->status >> 32);
+ regs.nbeal = (u32) m->addr;
+ regs.nbeah = (u32)(m->addr >> 32);
+ regs.nbcfg = nbcfg;
+
+ __amd64_decode_bus_error(mci, &regs);
/*
* Check the UE bit of the NB status high register, if set generate some
@@ -2086,7 +2093,7 @@ void amd64_decode_bus_error(int node_id, struct err_regs *regs)
*
* FIXME: this should go somewhere else, if at all.
*/
- if (regs->nbsh & K8_NBSH_UC_ERR && !report_gart_errors)
+ if (regs.nbsh & K8_NBSH_UC_ERR && !report_gart_errors)
edac_mc_handle_ue_no_info(mci, "UE bit is set");
}
@@ -2927,7 +2934,7 @@ static int __init amd64_edac_init(void)
* to finish initialization of the MC instances.
*/
err = -ENODEV;
- for (nb = 0; nb < num_k8_northbridges; nb++) {
+ for (nb = 0; nb < k8_northbridges.num; nb++) {
if (!pvt_lookup[nb])
continue;
diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h
index 613b9381e71a..044aee4f944d 100644
--- a/drivers/edac/amd64_edac.h
+++ b/drivers/edac/amd64_edac.h
@@ -72,7 +72,7 @@
#include <linux/edac.h>
#include <asm/msr.h>
#include "edac_core.h"
-#include "edac_mce_amd.h"
+#include "mce_amd.h"
#define amd64_printk(level, fmt, arg...) \
edac_printk(level, "amd64", fmt, ##arg)
@@ -482,11 +482,10 @@ extern const char *rrrr_msgs[16];
extern const char *to_msgs[2];
extern const char *pp_msgs[4];
extern const char *ii_msgs[4];
-extern const char *ext_msgs[32];
extern const char *htlink_msgs[8];
#ifdef CONFIG_EDAC_DEBUG
-#define NUM_DBG_ATTRS 9
+#define NUM_DBG_ATTRS 5
#else
#define NUM_DBG_ATTRS 0
#endif
diff --git a/drivers/edac/amd64_edac_dbg.c b/drivers/edac/amd64_edac_dbg.c
index 59cf2cf6e11e..e3562288f4ce 100644
--- a/drivers/edac/amd64_edac_dbg.c
+++ b/drivers/edac/amd64_edac_dbg.c
@@ -1,167 +1,16 @@
#include "amd64_edac.h"
-/*
- * accept a hex value and store it into the virtual error register file, field:
- * nbeal and nbeah. Assume virtual error values have already been set for: NBSL,
- * NBSH and NBCFG. Then proceed to map the error values to a MC, CSROW and
- * CHANNEL
- */
-static ssize_t amd64_nbea_store(struct mem_ctl_info *mci, const char *data,
- size_t count)
-{
- struct amd64_pvt *pvt = mci->pvt_info;
- unsigned long long value;
- int ret = 0;
-
- ret = strict_strtoull(data, 16, &value);
- if (ret != -EINVAL) {
- debugf0("received NBEA= 0x%llx\n", value);
-
- /* place the value into the virtual error packet */
- pvt->ctl_error_info.nbeal = (u32) value;
- value >>= 32;
- pvt->ctl_error_info.nbeah = (u32) value;
-
- /* Process the Mapping request */
- /* TODO: Add race prevention */
- amd_decode_nb_mce(pvt->mc_node_id, &pvt->ctl_error_info, 1);
-
- return count;
- }
- return ret;
-}
-
-/* display back what the last NBEA (MCA NB Address (MC4_ADDR)) was written */
-static ssize_t amd64_nbea_show(struct mem_ctl_info *mci, char *data)
-{
- struct amd64_pvt *pvt = mci->pvt_info;
- u64 value;
-
- value = pvt->ctl_error_info.nbeah;
- value <<= 32;
- value |= pvt->ctl_error_info.nbeal;
-
- return sprintf(data, "%llx\n", value);
-}
-
-/* store the NBSL (MCA NB Status Low (MC4_STATUS)) value user desires */
-static ssize_t amd64_nbsl_store(struct mem_ctl_info *mci, const char *data,
- size_t count)
-{
- struct amd64_pvt *pvt = mci->pvt_info;
- unsigned long value;
- int ret = 0;
-
- ret = strict_strtoul(data, 16, &value);
- if (ret != -EINVAL) {
- debugf0("received NBSL= 0x%lx\n", value);
-
- pvt->ctl_error_info.nbsl = (u32) value;
-
- return count;
- }
- return ret;
-}
-
-/* display back what the last NBSL value written */
-static ssize_t amd64_nbsl_show(struct mem_ctl_info *mci, char *data)
-{
- struct amd64_pvt *pvt = mci->pvt_info;
- u32 value;
-
- value = pvt->ctl_error_info.nbsl;
-
- return sprintf(data, "%x\n", value);
-}
-
-/* store the NBSH (MCA NB Status High) value user desires */
-static ssize_t amd64_nbsh_store(struct mem_ctl_info *mci, const char *data,
- size_t count)
-{
- struct amd64_pvt *pvt = mci->pvt_info;
- unsigned long value;
- int ret = 0;
-
- ret = strict_strtoul(data, 16, &value);
- if (ret != -EINVAL) {
- debugf0("received NBSH= 0x%lx\n", value);
-
- pvt->ctl_error_info.nbsh = (u32) value;
-
- return count;
- }
- return ret;
-}
-
-/* display back what the last NBSH value written */
-static ssize_t amd64_nbsh_show(struct mem_ctl_info *mci, char *data)
-{
- struct amd64_pvt *pvt = mci->pvt_info;
- u32 value;
-
- value = pvt->ctl_error_info.nbsh;
-
- return sprintf(data, "%x\n", value);
+#define EDAC_DCT_ATTR_SHOW(reg) \
+static ssize_t amd64_##reg##_show(struct mem_ctl_info *mci, char *data) \
+{ \
+ struct amd64_pvt *pvt = mci->pvt_info; \
+ return sprintf(data, "0x%016llx\n", (u64)pvt->reg); \
}
-/* accept and store the NBCFG (MCA NB Configuration) value user desires */
-static ssize_t amd64_nbcfg_store(struct mem_ctl_info *mci,
- const char *data, size_t count)
-{
- struct amd64_pvt *pvt = mci->pvt_info;
- unsigned long value;
- int ret = 0;
-
- ret = strict_strtoul(data, 16, &value);
- if (ret != -EINVAL) {
- debugf0("received NBCFG= 0x%lx\n", value);
-
- pvt->ctl_error_info.nbcfg = (u32) value;
-
- return count;
- }
- return ret;
-}
-
-/* various show routines for the controls of a MCI */
-static ssize_t amd64_nbcfg_show(struct mem_ctl_info *mci, char *data)
-{
- struct amd64_pvt *pvt = mci->pvt_info;
-
- return sprintf(data, "%x\n", pvt->ctl_error_info.nbcfg);
-}
-
-
-static ssize_t amd64_dhar_show(struct mem_ctl_info *mci, char *data)
-{
- struct amd64_pvt *pvt = mci->pvt_info;
-
- return sprintf(data, "%x\n", pvt->dhar);
-}
-
-
-static ssize_t amd64_dbam_show(struct mem_ctl_info *mci, char *data)
-{
- struct amd64_pvt *pvt = mci->pvt_info;
-
- return sprintf(data, "%x\n", pvt->dbam0);
-}
-
-
-static ssize_t amd64_topmem_show(struct mem_ctl_info *mci, char *data)
-{
- struct amd64_pvt *pvt = mci->pvt_info;
-
- return sprintf(data, "%llx\n", pvt->top_mem);
-}
-
-
-static ssize_t amd64_topmem2_show(struct mem_ctl_info *mci, char *data)
-{
- struct amd64_pvt *pvt = mci->pvt_info;
-
- return sprintf(data, "%llx\n", pvt->top_mem2);
-}
+EDAC_DCT_ATTR_SHOW(dhar);
+EDAC_DCT_ATTR_SHOW(dbam0);
+EDAC_DCT_ATTR_SHOW(top_mem);
+EDAC_DCT_ATTR_SHOW(top_mem2);
static ssize_t amd64_hole_show(struct mem_ctl_info *mci, char *data)
{
@@ -182,38 +31,6 @@ struct mcidev_sysfs_attribute amd64_dbg_attrs[] = {
{
.attr = {
- .name = "nbea_ctl",
- .mode = (S_IRUGO | S_IWUSR)
- },
- .show = amd64_nbea_show,
- .store = amd64_nbea_store,
- },
- {
- .attr = {
- .name = "nbsl_ctl",
- .mode = (S_IRUGO | S_IWUSR)
- },
- .show = amd64_nbsl_show,
- .store = amd64_nbsl_store,
- },
- {
- .attr = {
- .name = "nbsh_ctl",
- .mode = (S_IRUGO | S_IWUSR)
- },
- .show = amd64_nbsh_show,
- .store = amd64_nbsh_store,
- },
- {
- .attr = {
- .name = "nbcfg_ctl",
- .mode = (S_IRUGO | S_IWUSR)
- },
- .show = amd64_nbcfg_show,
- .store = amd64_nbcfg_store,
- },
- {
- .attr = {
.name = "dhar",
.mode = (S_IRUGO)
},
@@ -225,7 +42,7 @@ struct mcidev_sysfs_attribute amd64_dbg_attrs[] = {
.name = "dbam",
.mode = (S_IRUGO)
},
- .show = amd64_dbam_show,
+ .show = amd64_dbam0_show,
.store = NULL,
},
{
@@ -233,7 +50,7 @@ struct mcidev_sysfs_attribute amd64_dbg_attrs[] = {
.name = "topmem",
.mode = (S_IRUGO)
},
- .show = amd64_topmem_show,
+ .show = amd64_top_mem_show,
.store = NULL,
},
{
@@ -241,7 +58,7 @@ struct mcidev_sysfs_attribute amd64_dbg_attrs[] = {
.name = "topmem2",
.mode = (S_IRUGO)
},
- .show = amd64_topmem2_show,
+ .show = amd64_top_mem2_show,
.store = NULL,
},
{
diff --git a/drivers/edac/edac_device_sysfs.c b/drivers/edac/edac_device_sysfs.c
index 070968178a24..2941dca91aae 100644
--- a/drivers/edac/edac_device_sysfs.c
+++ b/drivers/edac/edac_device_sysfs.c
@@ -13,6 +13,7 @@
#include <linux/ctype.h>
#include <linux/module.h>
#include <linux/slab.h>
+#include <linux/edac.h>
#include "edac_core.h"
#include "edac_module.h"
@@ -235,7 +236,7 @@ int edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev)
debugf1("%s()\n", __func__);
/* get the /sys/devices/system/edac reference */
- edac_class = edac_get_edac_class();
+ edac_class = edac_get_sysfs_class();
if (edac_class == NULL) {
debugf1("%s() no edac_class error\n", __func__);
err = -ENODEV;
@@ -255,7 +256,7 @@ int edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev)
if (!try_module_get(edac_dev->owner)) {
err = -ENODEV;
- goto err_out;
+ goto err_mod_get;
}
/* register */
@@ -282,6 +283,9 @@ int edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev)
err_kobj_reg:
module_put(edac_dev->owner);
+err_mod_get:
+ edac_put_sysfs_class();
+
err_out:
return err;
}
@@ -290,12 +294,11 @@ err_out:
* edac_device_unregister_sysfs_main_kobj:
* the '..../edac/<name>' kobject
*/
-void edac_device_unregister_sysfs_main_kobj(
- struct edac_device_ctl_info *edac_dev)
+void edac_device_unregister_sysfs_main_kobj(struct edac_device_ctl_info *dev)
{
debugf0("%s()\n", __func__);
debugf4("%s() name of kobject is: %s\n",
- __func__, kobject_name(&edac_dev->kobj));
+ __func__, kobject_name(&dev->kobj));
/*
* Unregister the edac device's kobject and
@@ -304,7 +307,8 @@ void edac_device_unregister_sysfs_main_kobj(
* a) module_put() this module
* b) 'kfree' the memory
*/
- kobject_put(&edac_dev->kobj);
+ kobject_put(&dev->kobj);
+ edac_put_sysfs_class();
}
/* edac_dev -> instance information */
diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c
index 8aad94d10c0c..a4135860149b 100644
--- a/drivers/edac/edac_mc_sysfs.c
+++ b/drivers/edac/edac_mc_sysfs.c
@@ -11,6 +11,7 @@
#include <linux/ctype.h>
#include <linux/slab.h>
+#include <linux/edac.h>
#include <linux/bug.h>
#include "edac_core.h"
@@ -1011,13 +1012,13 @@ void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci)
*/
int edac_sysfs_setup_mc_kset(void)
{
- int err = 0;
+ int err = -EINVAL;
struct sysdev_class *edac_class;
debugf1("%s()\n", __func__);
/* get the /sys/devices/system/edac class reference */
- edac_class = edac_get_edac_class();
+ edac_class = edac_get_sysfs_class();
if (edac_class == NULL) {
debugf1("%s() no edac_class error=%d\n", __func__, err);
goto fail_out;
@@ -1028,15 +1029,16 @@ int edac_sysfs_setup_mc_kset(void)
if (!mc_kset) {
err = -ENOMEM;
debugf1("%s() Failed to register '.../edac/mc'\n", __func__);
- goto fail_out;
+ goto fail_kset;
}
debugf1("%s() Registered '.../edac/mc' kobject\n", __func__);
return 0;
+fail_kset:
+ edac_put_sysfs_class();
- /* error unwind stack */
fail_out:
return err;
}
@@ -1049,5 +1051,6 @@ fail_out:
void edac_sysfs_teardown_mc_kset(void)
{
kset_unregister(mc_kset);
+ edac_put_sysfs_class();
}
diff --git a/drivers/edac/edac_mce_amd.c b/drivers/edac/edac_mce_amd.c
deleted file mode 100644
index 9014df6f605d..000000000000
--- a/drivers/edac/edac_mce_amd.c
+++ /dev/null
@@ -1,452 +0,0 @@
-#include <linux/module.h>
-#include "edac_mce_amd.h"
-
-static bool report_gart_errors;
-static void (*nb_bus_decoder)(int node_id, struct err_regs *regs);
-
-void amd_report_gart_errors(bool v)
-{
- report_gart_errors = v;
-}
-EXPORT_SYMBOL_GPL(amd_report_gart_errors);
-
-void amd_register_ecc_decoder(void (*f)(int, struct err_regs *))
-{
- nb_bus_decoder = f;
-}
-EXPORT_SYMBOL_GPL(amd_register_ecc_decoder);
-
-void amd_unregister_ecc_decoder(void (*f)(int, struct err_regs *))
-{
- if (nb_bus_decoder) {
- WARN_ON(nb_bus_decoder != f);
-
- nb_bus_decoder = NULL;
- }
-}
-EXPORT_SYMBOL_GPL(amd_unregister_ecc_decoder);
-
-/*
- * string representation for the different MCA reported error types, see F3x48
- * or MSR0000_0411.
- */
-const char *tt_msgs[] = { /* transaction type */
- "instruction",
- "data",
- "generic",
- "reserved"
-};
-EXPORT_SYMBOL_GPL(tt_msgs);
-
-const char *ll_msgs[] = { /* cache level */
- "L0",
- "L1",
- "L2",
- "L3/generic"
-};
-EXPORT_SYMBOL_GPL(ll_msgs);
-
-const char *rrrr_msgs[] = {
- "generic",
- "generic read",
- "generic write",
- "data read",
- "data write",
- "inst fetch",
- "prefetch",
- "evict",
- "snoop",
- "reserved RRRR= 9",
- "reserved RRRR= 10",
- "reserved RRRR= 11",
- "reserved RRRR= 12",
- "reserved RRRR= 13",
- "reserved RRRR= 14",
- "reserved RRRR= 15"
-};
-EXPORT_SYMBOL_GPL(rrrr_msgs);
-
-const char *pp_msgs[] = { /* participating processor */
- "local node originated (SRC)",
- "local node responded to request (RES)",
- "local node observed as 3rd party (OBS)",
- "generic"
-};
-EXPORT_SYMBOL_GPL(pp_msgs);
-
-const char *to_msgs[] = {
- "no timeout",
- "timed out"
-};
-EXPORT_SYMBOL_GPL(to_msgs);
-
-const char *ii_msgs[] = { /* memory or i/o */
- "mem access",
- "reserved",
- "i/o access",
- "generic"
-};
-EXPORT_SYMBOL_GPL(ii_msgs);
-
-/*
- * Map the 4 or 5 (family-specific) bits of Extended Error code to the
- * string table.
- */
-const char *ext_msgs[] = {
- "K8 ECC error", /* 0_0000b */
- "CRC error on link", /* 0_0001b */
- "Sync error packets on link", /* 0_0010b */
- "Master Abort during link operation", /* 0_0011b */
- "Target Abort during link operation", /* 0_0100b */
- "Invalid GART PTE entry during table walk", /* 0_0101b */
- "Unsupported atomic RMW command received", /* 0_0110b */
- "WDT error: NB transaction timeout", /* 0_0111b */
- "ECC/ChipKill ECC error", /* 0_1000b */
- "SVM DEV Error", /* 0_1001b */
- "Link Data error", /* 0_1010b */
- "Link/L3/Probe Filter Protocol error", /* 0_1011b */
- "NB Internal Arrays Parity error", /* 0_1100b */
- "DRAM Address/Control Parity error", /* 0_1101b */
- "Link Transmission error", /* 0_1110b */
- "GART/DEV Table Walk Data error" /* 0_1111b */
- "Res 0x100 error", /* 1_0000b */
- "Res 0x101 error", /* 1_0001b */
- "Res 0x102 error", /* 1_0010b */
- "Res 0x103 error", /* 1_0011b */
- "Res 0x104 error", /* 1_0100b */
- "Res 0x105 error", /* 1_0101b */
- "Res 0x106 error", /* 1_0110b */
- "Res 0x107 error", /* 1_0111b */
- "Res 0x108 error", /* 1_1000b */
- "Res 0x109 error", /* 1_1001b */
- "Res 0x10A error", /* 1_1010b */
- "Res 0x10B error", /* 1_1011b */
- "ECC error in L3 Cache Data", /* 1_1100b */
- "L3 Cache Tag error", /* 1_1101b */
- "L3 Cache LRU Parity error", /* 1_1110b */
- "Probe Filter error" /* 1_1111b */
-};
-EXPORT_SYMBOL_GPL(ext_msgs);
-
-static void amd_decode_dc_mce(u64 mc0_status)
-{
- u32 ec = mc0_status & 0xffff;
- u32 xec = (mc0_status >> 16) & 0xf;
-
- pr_emerg("Data Cache Error");
-
- if (xec == 1 && TLB_ERROR(ec))
- pr_cont(": %s TLB multimatch.\n", LL_MSG(ec));
- else if (xec == 0) {
- if (mc0_status & (1ULL << 40))
- pr_cont(" during Data Scrub.\n");
- else if (TLB_ERROR(ec))
- pr_cont(": %s TLB parity error.\n", LL_MSG(ec));
- else if (MEM_ERROR(ec)) {
- u8 ll = ec & 0x3;
- u8 tt = (ec >> 2) & 0x3;
- u8 rrrr = (ec >> 4) & 0xf;
-
- /* see F10h BKDG (31116), Table 92. */
- if (ll == 0x1) {
- if (tt != 0x1)
- goto wrong_dc_mce;
-
- pr_cont(": Data/Tag %s error.\n", RRRR_MSG(ec));
-
- } else if (ll == 0x2 && rrrr == 0x3)
- pr_cont(" during L1 linefill from L2.\n");
- else
- goto wrong_dc_mce;
- } else if (BUS_ERROR(ec) && boot_cpu_data.x86 == 0xf)
- pr_cont(" during system linefill.\n");
- else
- goto wrong_dc_mce;
- } else
- goto wrong_dc_mce;
-
- return;
-
-wrong_dc_mce:
- pr_warning("Corrupted DC MCE info?\n");
-}
-
-static void amd_decode_ic_mce(u64 mc1_status)
-{
- u32 ec = mc1_status & 0xffff;
- u32 xec = (mc1_status >> 16) & 0xf;
-
- pr_emerg("Instruction Cache Error");
-
- if (xec == 1 && TLB_ERROR(ec))
- pr_cont(": %s TLB multimatch.\n", LL_MSG(ec));
- else if (xec == 0) {
- if (TLB_ERROR(ec))
- pr_cont(": %s TLB Parity error.\n", LL_MSG(ec));
- else if (BUS_ERROR(ec)) {
- if (boot_cpu_data.x86 == 0xf &&
- (mc1_status & (1ULL << 58)))
- pr_cont(" during system linefill.\n");
- else
- pr_cont(" during attempted NB data read.\n");
- } else if (MEM_ERROR(ec)) {
- u8 ll = ec & 0x3;
- u8 rrrr = (ec >> 4) & 0xf;
-
- if (ll == 0x2)
- pr_cont(" during a linefill from L2.\n");
- else if (ll == 0x1) {
-
- switch (rrrr) {
- case 0x5:
- pr_cont(": Parity error during "
- "data load.\n");
- break;
-
- case 0x7:
- pr_cont(": Copyback Parity/Victim"
- " error.\n");
- break;
-
- case 0x8:
- pr_cont(": Tag Snoop error.\n");
- break;
-
- default:
- goto wrong_ic_mce;
- break;
- }
- }
- } else
- goto wrong_ic_mce;
- } else
- goto wrong_ic_mce;
-
- return;
-
-wrong_ic_mce:
- pr_warning("Corrupted IC MCE info?\n");
-}
-
-static void amd_decode_bu_mce(u64 mc2_status)
-{
- u32 ec = mc2_status & 0xffff;
- u32 xec = (mc2_status >> 16) & 0xf;
-
- pr_emerg("Bus Unit Error");
-
- if (xec == 0x1)
- pr_cont(" in the write data buffers.\n");
- else if (xec == 0x3)
- pr_cont(" in the victim data buffers.\n");
- else if (xec == 0x2 && MEM_ERROR(ec))
- pr_cont(": %s error in the L2 cache tags.\n", RRRR_MSG(ec));
- else if (xec == 0x0) {
- if (TLB_ERROR(ec))
- pr_cont(": %s error in a Page Descriptor Cache or "
- "Guest TLB.\n", TT_MSG(ec));
- else if (BUS_ERROR(ec))
- pr_cont(": %s/ECC error in data read from NB: %s.\n",
- RRRR_MSG(ec), PP_MSG(ec));
- else if (MEM_ERROR(ec)) {
- u8 rrrr = (ec >> 4) & 0xf;
-
- if (rrrr >= 0x7)
- pr_cont(": %s error during data copyback.\n",
- RRRR_MSG(ec));
- else if (rrrr <= 0x1)
- pr_cont(": %s parity/ECC error during data "
- "access from L2.\n", RRRR_MSG(ec));
- else
- goto wrong_bu_mce;
- } else
- goto wrong_bu_mce;
- } else
- goto wrong_bu_mce;
-
- return;
-
-wrong_bu_mce:
- pr_warning("Corrupted BU MCE info?\n");
-}
-
-static void amd_decode_ls_mce(u64 mc3_status)
-{
- u32 ec = mc3_status & 0xffff;
- u32 xec = (mc3_status >> 16) & 0xf;
-
- pr_emerg("Load Store Error");
-
- if (xec == 0x0) {
- u8 rrrr = (ec >> 4) & 0xf;
-
- if (!BUS_ERROR(ec) || (rrrr != 0x3 && rrrr != 0x4))
- goto wrong_ls_mce;
-
- pr_cont(" during %s.\n", RRRR_MSG(ec));
- }
- return;
-
-wrong_ls_mce:
- pr_warning("Corrupted LS MCE info?\n");
-}
-
-void amd_decode_nb_mce(int node_id, struct err_regs *regs, int handle_errors)
-{
- u32 ec = ERROR_CODE(regs->nbsl);
-
- if (!handle_errors)
- return;
-
- /*
- * GART TLB error reporting is disabled by default. Bail out early.
- */
- if (TLB_ERROR(ec) && !report_gart_errors)
- return;
-
- pr_emerg("Northbridge Error, node %d", node_id);
-
- /*
- * F10h, revD can disable ErrCpu[3:0] so check that first and also the
- * value encoding has changed so interpret those differently
- */
- if ((boot_cpu_data.x86 == 0x10) &&
- (boot_cpu_data.x86_model > 7)) {
- if (regs->nbsh & K8_NBSH_ERR_CPU_VAL)
- pr_cont(", core: %u\n", (u8)(regs->nbsh & 0xf));
- } else {
- u8 assoc_cpus = regs->nbsh & 0xf;
-
- if (assoc_cpus > 0)
- pr_cont(", core: %d", fls(assoc_cpus) - 1);
-
- pr_cont("\n");
- }
-
- pr_emerg("%s.\n", EXT_ERR_MSG(regs->nbsl));
-
- if (BUS_ERROR(ec) && nb_bus_decoder)
- nb_bus_decoder(node_id, regs);
-}
-EXPORT_SYMBOL_GPL(amd_decode_nb_mce);
-
-static void amd_decode_fr_mce(u64 mc5_status)
-{
- /* we have only one error signature so match all fields at once. */
- if ((mc5_status & 0xffff) == 0x0f0f)
- pr_emerg(" FR Error: CPU Watchdog timer expire.\n");
- else
- pr_warning("Corrupted FR MCE info?\n");
-}
-
-static inline void amd_decode_err_code(unsigned int ec)
-{
- if (TLB_ERROR(ec)) {
- pr_emerg("Transaction: %s, Cache Level %s\n",
- TT_MSG(ec), LL_MSG(ec));
- } else if (MEM_ERROR(ec)) {
- pr_emerg("Transaction: %s, Type: %s, Cache Level: %s",
- RRRR_MSG(ec), TT_MSG(ec), LL_MSG(ec));
- } else if (BUS_ERROR(ec)) {
- pr_emerg("Transaction type: %s(%s), %s, Cache Level: %s, "
- "Participating Processor: %s\n",
- RRRR_MSG(ec), II_MSG(ec), TO_MSG(ec), LL_MSG(ec),
- PP_MSG(ec));
- } else
- pr_warning("Huh? Unknown MCE error 0x%x\n", ec);
-}
-
-static int amd_decode_mce(struct notifier_block *nb, unsigned long val,
- void *data)
-{
- struct mce *m = (struct mce *)data;
- struct err_regs regs;
- int node, ecc;
-
- pr_emerg("MC%d_STATUS: ", m->bank);
-
- pr_cont("%sorrected error, other errors lost: %s, "
- "CPU context corrupt: %s",
- ((m->status & MCI_STATUS_UC) ? "Unc" : "C"),
- ((m->status & MCI_STATUS_OVER) ? "yes" : "no"),
- ((m->status & MCI_STATUS_PCC) ? "yes" : "no"));
-
- /* do the two bits[14:13] together */
- ecc = (m->status >> 45) & 0x3;
- if (ecc)
- pr_cont(", %sECC Error", ((ecc == 2) ? "C" : "U"));
-
- pr_cont("\n");
-
- switch (m->bank) {
- case 0:
- amd_decode_dc_mce(m->status);
- break;
-
- case 1:
- amd_decode_ic_mce(m->status);
- break;
-
- case 2:
- amd_decode_bu_mce(m->status);
- break;
-
- case 3:
- amd_decode_ls_mce(m->status);
- break;
-
- case 4:
- regs.nbsl = (u32) m->status;
- regs.nbsh = (u32)(m->status >> 32);
- regs.nbeal = (u32) m->addr;
- regs.nbeah = (u32)(m->addr >> 32);
- node = amd_get_nb_id(m->extcpu);
-
- amd_decode_nb_mce(node, &regs, 1);
- break;
-
- case 5:
- amd_decode_fr_mce(m->status);
- break;
-
- default:
- break;
- }
-
- amd_decode_err_code(m->status & 0xffff);
-
- return NOTIFY_STOP;
-}
-
-static struct notifier_block amd_mce_dec_nb = {
- .notifier_call = amd_decode_mce,
-};
-
-static int __init mce_amd_init(void)
-{
- /*
- * We can decode MCEs for K8, F10h and F11h CPUs:
- */
- if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
- return 0;
-
- if (boot_cpu_data.x86 < 0xf || boot_cpu_data.x86 > 0x11)
- return 0;
-
- atomic_notifier_chain_register(&x86_mce_decoder_chain, &amd_mce_dec_nb);
-
- return 0;
-}
-early_initcall(mce_amd_init);
-
-#ifdef MODULE
-static void __exit mce_amd_exit(void)
-{
- atomic_notifier_chain_unregister(&x86_mce_decoder_chain, &amd_mce_dec_nb);
-}
-
-MODULE_DESCRIPTION("AMD MCE decoder");
-MODULE_ALIAS("edac-mce-amd");
-MODULE_LICENSE("GPL");
-module_exit(mce_amd_exit);
-#endif
diff --git a/drivers/edac/edac_module.c b/drivers/edac/edac_module.c
index 7e1374afd967..be4b075c3098 100644
--- a/drivers/edac/edac_module.c
+++ b/drivers/edac/edac_module.c
@@ -27,15 +27,6 @@ EXPORT_SYMBOL_GPL(edac_debug_level);
struct workqueue_struct *edac_workqueue;
/*
- * sysfs object: /sys/devices/system/edac
- * need to export to other files in this modules
- */
-static struct sysdev_class edac_class = {
- .name = "edac",
-};
-static int edac_class_valid;
-
-/*
* edac_op_state_to_string()
*/
char *edac_op_state_to_string(int opstate)
@@ -55,60 +46,6 @@ char *edac_op_state_to_string(int opstate)
}
/*
- * edac_get_edac_class()
- *
- * return pointer to the edac class of 'edac'
- */
-struct sysdev_class *edac_get_edac_class(void)
-{
- struct sysdev_class *classptr = NULL;
-
- if (edac_class_valid)
- classptr = &edac_class;
-
- return classptr;
-}
-
-/*
- * edac_register_sysfs_edac_name()
- *
- * register the 'edac' into /sys/devices/system
- *
- * return:
- * 0 success
- * !0 error
- */
-static int edac_register_sysfs_edac_name(void)
-{
- int err;
-
- /* create the /sys/devices/system/edac directory */
- err = sysdev_class_register(&edac_class);
-
- if (err) {
- debugf1("%s() error=%d\n", __func__, err);
- return err;
- }
-
- edac_class_valid = 1;
- return 0;
-}
-
-/*
- * sysdev_class_unregister()
- *
- * unregister the 'edac' from /sys/devices/system
- */
-static void edac_unregister_sysfs_edac_name(void)
-{
- /* only if currently registered, then unregister it */
- if (edac_class_valid)
- sysdev_class_unregister(&edac_class);
-
- edac_class_valid = 0;
-}
-
-/*
* edac_workqueue_setup
* initialize the edac work queue for polling operations
*/
@@ -154,21 +91,11 @@ static int __init edac_init(void)
edac_pci_clear_parity_errors();
/*
- * perform the registration of the /sys/devices/system/edac class object
- */
- if (edac_register_sysfs_edac_name()) {
- edac_printk(KERN_ERR, EDAC_MC,
- "Error initializing 'edac' kobject\n");
- err = -ENODEV;
- goto error;
- }
-
- /*
* now set up the mc_kset under the edac class object
*/
err = edac_sysfs_setup_mc_kset();
if (err)
- goto sysfs_setup_fail;
+ goto error;
/* Setup/Initialize the workq for this core */
err = edac_workqueue_setup();
@@ -183,9 +110,6 @@ static int __init edac_init(void)
workq_fail:
edac_sysfs_teardown_mc_kset();
-sysfs_setup_fail:
- edac_unregister_sysfs_edac_name();
-
error:
return err;
}
@@ -201,7 +125,6 @@ static void __exit edac_exit(void)
/* tear down the various subsystems */
edac_workqueue_teardown();
edac_sysfs_teardown_mc_kset();
- edac_unregister_sysfs_edac_name();
}
/*
diff --git a/drivers/edac/edac_module.h b/drivers/edac/edac_module.h
index 233d4798c3aa..17aabb7b90ec 100644
--- a/drivers/edac/edac_module.h
+++ b/drivers/edac/edac_module.h
@@ -42,7 +42,6 @@ extern void edac_device_unregister_sysfs_main_kobj(
struct edac_device_ctl_info *edac_dev);
extern int edac_device_create_sysfs(struct edac_device_ctl_info *edac_dev);
extern void edac_device_remove_sysfs(struct edac_device_ctl_info *edac_dev);
-extern struct sysdev_class *edac_get_edac_class(void);
/* edac core workqueue: single CPU mode */
extern struct workqueue_struct *edac_workqueue;
diff --git a/drivers/edac/edac_pci_sysfs.c b/drivers/edac/edac_pci_sysfs.c
index c39697df9cb4..023b01cb5175 100644
--- a/drivers/edac/edac_pci_sysfs.c
+++ b/drivers/edac/edac_pci_sysfs.c
@@ -7,7 +7,7 @@
*
*/
#include <linux/module.h>
-#include <linux/sysdev.h>
+#include <linux/edac.h>
#include <linux/slab.h>
#include <linux/ctype.h>
@@ -354,7 +354,7 @@ static int edac_pci_main_kobj_setup(void)
/* First time, so create the main kobject and its
* controls and atributes
*/
- edac_class = edac_get_edac_class();
+ edac_class = edac_get_sysfs_class();
if (edac_class == NULL) {
debugf1("%s() no edac_class\n", __func__);
err = -ENODEV;
@@ -368,7 +368,7 @@ static int edac_pci_main_kobj_setup(void)
if (!try_module_get(THIS_MODULE)) {
debugf1("%s() try_module_get() failed\n", __func__);
err = -ENODEV;
- goto decrement_count_fail;
+ goto mod_get_fail;
}
edac_pci_top_main_kobj = kzalloc(sizeof(struct kobject), GFP_KERNEL);
@@ -403,6 +403,9 @@ kobject_init_and_add_fail:
kzalloc_fail:
module_put(THIS_MODULE);
+mod_get_fail:
+ edac_put_sysfs_class();
+
decrement_count_fail:
/* if are on this error exit, nothing to tear down */
atomic_dec(&edac_pci_sysfs_refcount);
@@ -429,6 +432,7 @@ static void edac_pci_main_kobj_teardown(void)
__func__);
kobject_put(edac_pci_top_main_kobj);
}
+ edac_put_sysfs_class();
}
/*
diff --git a/drivers/edac/edac_stub.c b/drivers/edac/edac_stub.c
index 20b428aa155e..aab970760b75 100644
--- a/drivers/edac/edac_stub.c
+++ b/drivers/edac/edac_stub.c
@@ -3,10 +3,13 @@
*
* Author: Dave Jiang <djiang@mvista.com>
*
- * 2007 (c) 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 kind, whether express
- * or implied.
+ * 2007 (c) MontaVista Software, Inc.
+ * 2010 (c) Advanced Micro Devices Inc.
+ * Borislav Petkov <borislav.petkov@amd.com>
+ *
+ * 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 <linux/module.h>
@@ -23,6 +26,8 @@ EXPORT_SYMBOL_GPL(edac_handlers);
int edac_err_assert = 0;
EXPORT_SYMBOL_GPL(edac_err_assert);
+static atomic_t edac_class_valid = ATOMIC_INIT(0);
+
/*
* called to determine if there is an EDAC driver interested in
* knowing an event (such as NMI) occurred
@@ -44,3 +49,41 @@ void edac_atomic_assert_error(void)
edac_err_assert++;
}
EXPORT_SYMBOL_GPL(edac_atomic_assert_error);
+
+/*
+ * sysfs object: /sys/devices/system/edac
+ * need to export to other files
+ */
+struct sysdev_class edac_class = {
+ .name = "edac",
+};
+EXPORT_SYMBOL_GPL(edac_class);
+
+/* return pointer to the 'edac' node in sysfs */
+struct sysdev_class *edac_get_sysfs_class(void)
+{
+ int err = 0;
+
+ if (atomic_read(&edac_class_valid))
+ goto out;
+
+ /* create the /sys/devices/system/edac directory */
+ err = sysdev_class_register(&edac_class);
+ if (err) {
+ printk(KERN_ERR "Error registering toplevel EDAC sysfs dir\n");
+ return NULL;
+ }
+
+out:
+ atomic_inc(&edac_class_valid);
+ return &edac_class;
+}
+EXPORT_SYMBOL_GPL(edac_get_sysfs_class);
+
+void edac_put_sysfs_class(void)
+{
+ /* last user unregisters it */
+ if (atomic_dec_and_test(&edac_class_valid))
+ sysdev_class_unregister(&edac_class);
+}
+EXPORT_SYMBOL_GPL(edac_put_sysfs_class);
diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c
index e0187d16dd7c..0fd5b85a0f75 100644
--- a/drivers/edac/i7core_edac.c
+++ b/drivers/edac/i7core_edac.c
@@ -1140,6 +1140,7 @@ static struct mcidev_sysfs_attribute i7core_udimm_counters_attrs[] = {
ATTR_COUNTER(0),
ATTR_COUNTER(1),
ATTR_COUNTER(2),
+ { .attr = { .name = NULL } }
};
static struct mcidev_sysfs_group i7core_udimm_counters = {
diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c
new file mode 100644
index 000000000000..c0181093b490
--- /dev/null
+++ b/drivers/edac/mce_amd.c
@@ -0,0 +1,680 @@
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "mce_amd.h"
+
+static struct amd_decoder_ops *fam_ops;
+
+static u8 nb_err_cpumask = 0xf;
+
+static bool report_gart_errors;
+static void (*nb_bus_decoder)(int node_id, struct mce *m, u32 nbcfg);
+
+void amd_report_gart_errors(bool v)
+{
+ report_gart_errors = v;
+}
+EXPORT_SYMBOL_GPL(amd_report_gart_errors);
+
+void amd_register_ecc_decoder(void (*f)(int, struct mce *, u32))
+{
+ nb_bus_decoder = f;
+}
+EXPORT_SYMBOL_GPL(amd_register_ecc_decoder);
+
+void amd_unregister_ecc_decoder(void (*f)(int, struct mce *, u32))
+{
+ if (nb_bus_decoder) {
+ WARN_ON(nb_bus_decoder != f);
+
+ nb_bus_decoder = NULL;
+ }
+}
+EXPORT_SYMBOL_GPL(amd_unregister_ecc_decoder);
+
+/*
+ * string representation for the different MCA reported error types, see F3x48
+ * or MSR0000_0411.
+ */
+
+/* transaction type */
+const char *tt_msgs[] = { "INSN", "DATA", "GEN", "RESV" };
+EXPORT_SYMBOL_GPL(tt_msgs);
+
+/* cache level */
+const char *ll_msgs[] = { "RESV", "L1", "L2", "L3/GEN" };
+EXPORT_SYMBOL_GPL(ll_msgs);
+
+/* memory transaction type */
+const char *rrrr_msgs[] = {
+ "GEN", "RD", "WR", "DRD", "DWR", "IRD", "PRF", "EV", "SNP"
+};
+EXPORT_SYMBOL_GPL(rrrr_msgs);
+
+/* participating processor */
+const char *pp_msgs[] = { "SRC", "RES", "OBS", "GEN" };
+EXPORT_SYMBOL_GPL(pp_msgs);
+
+/* request timeout */
+const char *to_msgs[] = { "no timeout", "timed out" };
+EXPORT_SYMBOL_GPL(to_msgs);
+
+/* memory or i/o */
+const char *ii_msgs[] = { "MEM", "RESV", "IO", "GEN" };
+EXPORT_SYMBOL_GPL(ii_msgs);
+
+static const char *f10h_nb_mce_desc[] = {
+ "HT link data error",
+ "Protocol error (link, L3, probe filter, etc.)",
+ "Parity error in NB-internal arrays",
+ "Link Retry due to IO link transmission error",
+ "L3 ECC data cache error",
+ "ECC error in L3 cache tag",
+ "L3 LRU parity bits error",
+ "ECC Error in the Probe Filter directory"
+};
+
+static bool f12h_dc_mce(u16 ec)
+{
+ bool ret = false;
+
+ if (MEM_ERROR(ec)) {
+ u8 ll = ec & 0x3;
+ ret = true;
+
+ if (ll == LL_L2)
+ pr_cont("during L1 linefill from L2.\n");
+ else if (ll == LL_L1)
+ pr_cont("Data/Tag %s error.\n", RRRR_MSG(ec));
+ else
+ ret = false;
+ }
+ return ret;
+}
+
+static bool f10h_dc_mce(u16 ec)
+{
+ u8 r4 = (ec >> 4) & 0xf;
+ u8 ll = ec & 0x3;
+
+ if (r4 == R4_GEN && ll == LL_L1) {
+ pr_cont("during data scrub.\n");
+ return true;
+ }
+ return f12h_dc_mce(ec);
+}
+
+static bool k8_dc_mce(u16 ec)
+{
+ if (BUS_ERROR(ec)) {
+ pr_cont("during system linefill.\n");
+ return true;
+ }
+
+ return f10h_dc_mce(ec);
+}
+
+static bool f14h_dc_mce(u16 ec)
+{
+ u8 r4 = (ec >> 4) & 0xf;
+ u8 ll = ec & 0x3;
+ u8 tt = (ec >> 2) & 0x3;
+ u8 ii = tt;
+ bool ret = true;
+
+ if (MEM_ERROR(ec)) {
+
+ if (tt != TT_DATA || ll != LL_L1)
+ return false;
+
+ switch (r4) {
+ case R4_DRD:
+ case R4_DWR:
+ pr_cont("Data/Tag parity error due to %s.\n",
+ (r4 == R4_DRD ? "load/hw prf" : "store"));
+ break;
+ case R4_EVICT:
+ pr_cont("Copyback parity error on a tag miss.\n");
+ break;
+ case R4_SNOOP:
+ pr_cont("Tag parity error during snoop.\n");
+ break;
+ default:
+ ret = false;
+ }
+ } else if (BUS_ERROR(ec)) {
+
+ if ((ii != II_MEM && ii != II_IO) || ll != LL_LG)
+ return false;
+
+ pr_cont("System read data error on a ");
+
+ switch (r4) {
+ case R4_RD:
+ pr_cont("TLB reload.\n");
+ break;
+ case R4_DWR:
+ pr_cont("store.\n");
+ break;
+ case R4_DRD:
+ pr_cont("load.\n");
+ break;
+ default:
+ ret = false;
+ }
+ } else {
+ ret = false;
+ }
+
+ return ret;
+}
+
+static void amd_decode_dc_mce(struct mce *m)
+{
+ u16 ec = m->status & 0xffff;
+ u8 xec = (m->status >> 16) & 0xf;
+
+ pr_emerg(HW_ERR "Data Cache Error: ");
+
+ /* TLB error signatures are the same across families */
+ if (TLB_ERROR(ec)) {
+ u8 tt = (ec >> 2) & 0x3;
+
+ if (tt == TT_DATA) {
+ pr_cont("%s TLB %s.\n", LL_MSG(ec),
+ (xec ? "multimatch" : "parity error"));
+ return;
+ }
+ else
+ goto wrong_dc_mce;
+ }
+
+ if (!fam_ops->dc_mce(ec))
+ goto wrong_dc_mce;
+
+ return;
+
+wrong_dc_mce:
+ pr_emerg(HW_ERR "Corrupted DC MCE info?\n");
+}
+
+static bool k8_ic_mce(u16 ec)
+{
+ u8 ll = ec & 0x3;
+ u8 r4 = (ec >> 4) & 0xf;
+ bool ret = true;
+
+ if (!MEM_ERROR(ec))
+ return false;
+
+ if (ll == 0x2)
+ pr_cont("during a linefill from L2.\n");
+ else if (ll == 0x1) {
+ switch (r4) {
+ case R4_IRD:
+ pr_cont("Parity error during data load.\n");
+ break;
+
+ case R4_EVICT:
+ pr_cont("Copyback Parity/Victim error.\n");
+ break;
+
+ case R4_SNOOP:
+ pr_cont("Tag Snoop error.\n");
+ break;
+
+ default:
+ ret = false;
+ break;
+ }
+ } else
+ ret = false;
+
+ return ret;
+}
+
+static bool f14h_ic_mce(u16 ec)
+{
+ u8 ll = ec & 0x3;
+ u8 tt = (ec >> 2) & 0x3;
+ u8 r4 = (ec >> 4) & 0xf;
+ bool ret = true;
+
+ if (MEM_ERROR(ec)) {
+ if (tt != 0 || ll != 1)
+ ret = false;
+
+ if (r4 == R4_IRD)
+ pr_cont("Data/tag array parity error for a tag hit.\n");
+ else if (r4 == R4_SNOOP)
+ pr_cont("Tag error during snoop/victimization.\n");
+ else
+ ret = false;
+ }
+ return ret;
+}
+
+static void amd_decode_ic_mce(struct mce *m)
+{
+ u16 ec = m->status & 0xffff;
+ u8 xec = (m->status >> 16) & 0xf;
+
+ pr_emerg(HW_ERR "Instruction Cache Error: ");
+
+ if (TLB_ERROR(ec))
+ pr_cont("%s TLB %s.\n", LL_MSG(ec),
+ (xec ? "multimatch" : "parity error"));
+ else if (BUS_ERROR(ec)) {
+ bool k8 = (boot_cpu_data.x86 == 0xf && (m->status & BIT_64(58)));
+
+ pr_cont("during %s.\n", (k8 ? "system linefill" : "NB data read"));
+ } else if (fam_ops->ic_mce(ec))
+ ;
+ else
+ pr_emerg(HW_ERR "Corrupted IC MCE info?\n");
+}
+
+static void amd_decode_bu_mce(struct mce *m)
+{
+ u32 ec = m->status & 0xffff;
+ u32 xec = (m->status >> 16) & 0xf;
+
+ pr_emerg(HW_ERR "Bus Unit Error");
+
+ if (xec == 0x1)
+ pr_cont(" in the write data buffers.\n");
+ else if (xec == 0x3)
+ pr_cont(" in the victim data buffers.\n");
+ else if (xec == 0x2 && MEM_ERROR(ec))
+ pr_cont(": %s error in the L2 cache tags.\n", RRRR_MSG(ec));
+ else if (xec == 0x0) {
+ if (TLB_ERROR(ec))
+ pr_cont(": %s error in a Page Descriptor Cache or "
+ "Guest TLB.\n", TT_MSG(ec));
+ else if (BUS_ERROR(ec))
+ pr_cont(": %s/ECC error in data read from NB: %s.\n",
+ RRRR_MSG(ec), PP_MSG(ec));
+ else if (MEM_ERROR(ec)) {
+ u8 rrrr = (ec >> 4) & 0xf;
+
+ if (rrrr >= 0x7)
+ pr_cont(": %s error during data copyback.\n",
+ RRRR_MSG(ec));
+ else if (rrrr <= 0x1)
+ pr_cont(": %s parity/ECC error during data "
+ "access from L2.\n", RRRR_MSG(ec));
+ else
+ goto wrong_bu_mce;
+ } else
+ goto wrong_bu_mce;
+ } else
+ goto wrong_bu_mce;
+
+ return;
+
+wrong_bu_mce:
+ pr_emerg(HW_ERR "Corrupted BU MCE info?\n");
+}
+
+static void amd_decode_ls_mce(struct mce *m)
+{
+ u16 ec = m->status & 0xffff;
+ u8 xec = (m->status >> 16) & 0xf;
+
+ if (boot_cpu_data.x86 == 0x14) {
+ pr_emerg("You shouldn't be seeing an LS MCE on this cpu family,"
+ " please report on LKML.\n");
+ return;
+ }
+
+ pr_emerg(HW_ERR "Load Store Error");
+
+ if (xec == 0x0) {
+ u8 r4 = (ec >> 4) & 0xf;
+
+ if (!BUS_ERROR(ec) || (r4 != R4_DRD && r4 != R4_DWR))
+ goto wrong_ls_mce;
+
+ pr_cont(" during %s.\n", RRRR_MSG(ec));
+ } else
+ goto wrong_ls_mce;
+
+ return;
+
+wrong_ls_mce:
+ pr_emerg(HW_ERR "Corrupted LS MCE info?\n");
+}
+
+static bool k8_nb_mce(u16 ec, u8 xec)
+{
+ bool ret = true;
+
+ switch (xec) {
+ case 0x1:
+ pr_cont("CRC error detected on HT link.\n");
+ break;
+
+ case 0x5:
+ pr_cont("Invalid GART PTE entry during GART table walk.\n");
+ break;
+
+ case 0x6:
+ pr_cont("Unsupported atomic RMW received from an IO link.\n");
+ break;
+
+ case 0x0:
+ case 0x8:
+ if (boot_cpu_data.x86 == 0x11)
+ return false;
+
+ pr_cont("DRAM ECC error detected on the NB.\n");
+ break;
+
+ case 0xd:
+ pr_cont("Parity error on the DRAM addr/ctl signals.\n");
+ break;
+
+ default:
+ ret = false;
+ break;
+ }
+
+ return ret;
+}
+
+static bool f10h_nb_mce(u16 ec, u8 xec)
+{
+ bool ret = true;
+ u8 offset = 0;
+
+ if (k8_nb_mce(ec, xec))
+ return true;
+
+ switch(xec) {
+ case 0xa ... 0xc:
+ offset = 10;
+ break;
+
+ case 0xe:
+ offset = 11;
+ break;
+
+ case 0xf:
+ if (TLB_ERROR(ec))
+ pr_cont("GART Table Walk data error.\n");
+ else if (BUS_ERROR(ec))
+ pr_cont("DMA Exclusion Vector Table Walk error.\n");
+ else
+ ret = false;
+
+ goto out;
+ break;
+
+ case 0x1c ... 0x1f:
+ offset = 24;
+ break;
+
+ default:
+ ret = false;
+
+ goto out;
+ break;
+ }
+
+ pr_cont("%s.\n", f10h_nb_mce_desc[xec - offset]);
+
+out:
+ return ret;
+}
+
+static bool nb_noop_mce(u16 ec, u8 xec)
+{
+ return false;
+}
+
+void amd_decode_nb_mce(int node_id, struct mce *m, u32 nbcfg)
+{
+ u8 xec = (m->status >> 16) & 0x1f;
+ u16 ec = m->status & 0xffff;
+ u32 nbsh = (u32)(m->status >> 32);
+
+ pr_emerg(HW_ERR "Northbridge Error, node %d: ", node_id);
+
+ /*
+ * F10h, revD can disable ErrCpu[3:0] so check that first and also the
+ * value encoding has changed so interpret those differently
+ */
+ if ((boot_cpu_data.x86 == 0x10) &&
+ (boot_cpu_data.x86_model > 7)) {
+ if (nbsh & K8_NBSH_ERR_CPU_VAL)
+ pr_cont(", core: %u", (u8)(nbsh & nb_err_cpumask));
+ } else {
+ u8 assoc_cpus = nbsh & nb_err_cpumask;
+
+ if (assoc_cpus > 0)
+ pr_cont(", core: %d", fls(assoc_cpus) - 1);
+ }
+
+ switch (xec) {
+ case 0x2:
+ pr_cont("Sync error (sync packets on HT link detected).\n");
+ return;
+
+ case 0x3:
+ pr_cont("HT Master abort.\n");
+ return;
+
+ case 0x4:
+ pr_cont("HT Target abort.\n");
+ return;
+
+ case 0x7:
+ pr_cont("NB Watchdog timeout.\n");
+ return;
+
+ case 0x9:
+ pr_cont("SVM DMA Exclusion Vector error.\n");
+ return;
+
+ default:
+ break;
+ }
+
+ if (!fam_ops->nb_mce(ec, xec))
+ goto wrong_nb_mce;
+
+ if (boot_cpu_data.x86 == 0xf || boot_cpu_data.x86 == 0x10)
+ if ((xec == 0x8 || xec == 0x0) && nb_bus_decoder)
+ nb_bus_decoder(node_id, m, nbcfg);
+
+ return;
+
+wrong_nb_mce:
+ pr_emerg(HW_ERR "Corrupted NB MCE info?\n");
+}
+EXPORT_SYMBOL_GPL(amd_decode_nb_mce);
+
+static void amd_decode_fr_mce(struct mce *m)
+{
+ if (boot_cpu_data.x86 == 0xf ||
+ boot_cpu_data.x86 == 0x11)
+ goto wrong_fr_mce;
+
+ /* we have only one error signature so match all fields at once. */
+ if ((m->status & 0xffff) == 0x0f0f) {
+ pr_emerg(HW_ERR "FR Error: CPU Watchdog timer expire.\n");
+ return;
+ }
+
+wrong_fr_mce:
+ pr_emerg(HW_ERR "Corrupted FR MCE info?\n");
+}
+
+static inline void amd_decode_err_code(u16 ec)
+{
+ if (TLB_ERROR(ec)) {
+ pr_emerg(HW_ERR "Transaction: %s, Cache Level: %s\n",
+ TT_MSG(ec), LL_MSG(ec));
+ } else if (MEM_ERROR(ec)) {
+ pr_emerg(HW_ERR "Transaction: %s, Type: %s, Cache Level: %s\n",
+ RRRR_MSG(ec), TT_MSG(ec), LL_MSG(ec));
+ } else if (BUS_ERROR(ec)) {
+ pr_emerg(HW_ERR "Transaction: %s (%s), %s, Cache Level: %s, "
+ "Participating Processor: %s\n",
+ RRRR_MSG(ec), II_MSG(ec), TO_MSG(ec), LL_MSG(ec),
+ PP_MSG(ec));
+ } else
+ pr_emerg(HW_ERR "Huh? Unknown MCE error 0x%x\n", ec);
+}
+
+/*
+ * Filter out unwanted MCE signatures here.
+ */
+static bool amd_filter_mce(struct mce *m)
+{
+ u8 xec = (m->status >> 16) & 0x1f;
+
+ /*
+ * NB GART TLB error reporting is disabled by default.
+ */
+ if (m->bank == 4 && xec == 0x5 && !report_gart_errors)
+ return true;
+
+ return false;
+}
+
+int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data)
+{
+ struct mce *m = (struct mce *)data;
+ int node, ecc;
+
+ if (amd_filter_mce(m))
+ return NOTIFY_STOP;
+
+ pr_emerg(HW_ERR "MC%d_STATUS: ", m->bank);
+
+ pr_cont("%sorrected error, other errors lost: %s, "
+ "CPU context corrupt: %s",
+ ((m->status & MCI_STATUS_UC) ? "Unc" : "C"),
+ ((m->status & MCI_STATUS_OVER) ? "yes" : "no"),
+ ((m->status & MCI_STATUS_PCC) ? "yes" : "no"));
+
+ /* do the two bits[14:13] together */
+ ecc = (m->status >> 45) & 0x3;
+ if (ecc)
+ pr_cont(", %sECC Error", ((ecc == 2) ? "C" : "U"));
+
+ pr_cont("\n");
+
+ switch (m->bank) {
+ case 0:
+ amd_decode_dc_mce(m);
+ break;
+
+ case 1:
+ amd_decode_ic_mce(m);
+ break;
+
+ case 2:
+ amd_decode_bu_mce(m);
+ break;
+
+ case 3:
+ amd_decode_ls_mce(m);
+ break;
+
+ case 4:
+ node = amd_get_nb_id(m->extcpu);
+ amd_decode_nb_mce(node, m, 0);
+ break;
+
+ case 5:
+ amd_decode_fr_mce(m);
+ break;
+
+ default:
+ break;
+ }
+
+ amd_decode_err_code(m->status & 0xffff);
+
+ return NOTIFY_STOP;
+}
+EXPORT_SYMBOL_GPL(amd_decode_mce);
+
+static struct notifier_block amd_mce_dec_nb = {
+ .notifier_call = amd_decode_mce,
+};
+
+static int __init mce_amd_init(void)
+{
+ if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
+ return 0;
+
+ if ((boot_cpu_data.x86 < 0xf || boot_cpu_data.x86 > 0x12) &&
+ (boot_cpu_data.x86 != 0x14 || boot_cpu_data.x86_model > 0xf))
+ return 0;
+
+ fam_ops = kzalloc(sizeof(struct amd_decoder_ops), GFP_KERNEL);
+ if (!fam_ops)
+ return -ENOMEM;
+
+ switch (boot_cpu_data.x86) {
+ case 0xf:
+ fam_ops->dc_mce = k8_dc_mce;
+ fam_ops->ic_mce = k8_ic_mce;
+ fam_ops->nb_mce = k8_nb_mce;
+ break;
+
+ case 0x10:
+ fam_ops->dc_mce = f10h_dc_mce;
+ fam_ops->ic_mce = k8_ic_mce;
+ fam_ops->nb_mce = f10h_nb_mce;
+ break;
+
+ case 0x11:
+ fam_ops->dc_mce = k8_dc_mce;
+ fam_ops->ic_mce = k8_ic_mce;
+ fam_ops->nb_mce = f10h_nb_mce;
+ break;
+
+ case 0x12:
+ fam_ops->dc_mce = f12h_dc_mce;
+ fam_ops->ic_mce = k8_ic_mce;
+ fam_ops->nb_mce = nb_noop_mce;
+ break;
+
+ case 0x14:
+ nb_err_cpumask = 0x3;
+ fam_ops->dc_mce = f14h_dc_mce;
+ fam_ops->ic_mce = f14h_ic_mce;
+ fam_ops->nb_mce = nb_noop_mce;
+ break;
+
+ default:
+ printk(KERN_WARNING "Huh? What family is that: %d?!\n",
+ boot_cpu_data.x86);
+ kfree(fam_ops);
+ return -EINVAL;
+ }
+
+ pr_info("MCE: In-kernel MCE decoding enabled.\n");
+
+ atomic_notifier_chain_register(&x86_mce_decoder_chain, &amd_mce_dec_nb);
+
+ return 0;
+}
+early_initcall(mce_amd_init);
+
+#ifdef MODULE
+static void __exit mce_amd_exit(void)
+{
+ atomic_notifier_chain_unregister(&x86_mce_decoder_chain, &amd_mce_dec_nb);
+ kfree(fam_ops);
+}
+
+MODULE_DESCRIPTION("AMD MCE decoder");
+MODULE_ALIAS("edac-mce-amd");
+MODULE_LICENSE("GPL");
+module_exit(mce_amd_exit);
+#endif
diff --git a/drivers/edac/edac_mce_amd.h b/drivers/edac/mce_amd.h
index df23ee065f79..35f6e0e3b297 100644
--- a/drivers/edac/edac_mce_amd.h
+++ b/drivers/edac/mce_amd.h
@@ -1,11 +1,14 @@
#ifndef _EDAC_MCE_AMD_H
#define _EDAC_MCE_AMD_H
+#include <linux/notifier.h>
+
#include <asm/mce.h>
+#define BIT_64(n) (U64_C(1) << (n))
+
#define ERROR_CODE(x) ((x) & 0xffff)
#define EXT_ERROR_CODE(x) (((x) >> 16) & 0x1f)
-#define EXT_ERR_MSG(x) ext_msgs[EXT_ERROR_CODE(x)]
#define LOW_SYNDROME(x) (((x) >> 15) & 0xff)
#define HIGH_SYNDROME(x) (((x) >> 24) & 0xff)
@@ -20,13 +23,14 @@
#define II_MSG(x) ii_msgs[II(x)]
#define LL(x) (((x) >> 0) & 0x3)
#define LL_MSG(x) ll_msgs[LL(x)]
-#define RRRR(x) (((x) >> 4) & 0xf)
-#define RRRR_MSG(x) rrrr_msgs[RRRR(x)]
#define TO(x) (((x) >> 8) & 0x1)
#define TO_MSG(x) to_msgs[TO(x)]
#define PP(x) (((x) >> 9) & 0x3)
#define PP_MSG(x) pp_msgs[PP(x)]
+#define RRRR(x) (((x) >> 4) & 0xf)
+#define RRRR_MSG(x) ((RRRR(x) < 9) ? rrrr_msgs[RRRR(x)] : "Wrong R4!")
+
#define K8_NBSH 0x4C
#define K8_NBSH_VALID_BIT BIT(31)
@@ -41,13 +45,45 @@
#define K8_NBSH_UECC BIT(13)
#define K8_NBSH_ERR_SCRUBER BIT(8)
+enum tt_ids {
+ TT_INSTR = 0,
+ TT_DATA,
+ TT_GEN,
+ TT_RESV,
+};
+
+enum ll_ids {
+ LL_RESV = 0,
+ LL_L1,
+ LL_L2,
+ LL_LG,
+};
+
+enum ii_ids {
+ II_MEM = 0,
+ II_RESV,
+ II_IO,
+ II_GEN,
+};
+
+enum rrrr_ids {
+ R4_GEN = 0,
+ R4_RD,
+ R4_WR,
+ R4_DRD,
+ R4_DWR,
+ R4_IRD,
+ R4_PREF,
+ R4_EVICT,
+ R4_SNOOP,
+};
+
extern const char *tt_msgs[];
extern const char *ll_msgs[];
extern const char *rrrr_msgs[];
extern const char *pp_msgs[];
extern const char *to_msgs[];
extern const char *ii_msgs[];
-extern const char *ext_msgs[];
/*
* relevant NB regs
@@ -60,10 +96,19 @@ struct err_regs {
u32 nbeal;
};
+/*
+ * per-family decoder ops
+ */
+struct amd_decoder_ops {
+ bool (*dc_mce)(u16);
+ bool (*ic_mce)(u16);
+ bool (*nb_mce)(u16, u8);
+};
void amd_report_gart_errors(bool);
-void amd_register_ecc_decoder(void (*f)(int, struct err_regs *));
-void amd_unregister_ecc_decoder(void (*f)(int, struct err_regs *));
-void amd_decode_nb_mce(int, struct err_regs *, int);
+void amd_register_ecc_decoder(void (*f)(int, struct mce *, u32));
+void amd_unregister_ecc_decoder(void (*f)(int, struct mce *, u32));
+void amd_decode_nb_mce(int, struct mce *, u32);
+int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data);
#endif /* _EDAC_MCE_AMD_H */
diff --git a/drivers/edac/mce_amd_inj.c b/drivers/edac/mce_amd_inj.c
new file mode 100644
index 000000000000..8d0688f36d4c
--- /dev/null
+++ b/drivers/edac/mce_amd_inj.c
@@ -0,0 +1,171 @@
+/*
+ * A simple MCE injection facility for testing the MCE decoding code. This
+ * driver should be built as module so that it can be loaded on production
+ * kernels for testing purposes.
+ *
+ * This file may be distributed under the terms of the GNU General Public
+ * License version 2.
+ *
+ * Copyright (c) 2010: Borislav Petkov <borislav.petkov@amd.com>
+ * Advanced Micro Devices Inc.
+ */
+
+#include <linux/kobject.h>
+#include <linux/sysdev.h>
+#include <linux/edac.h>
+#include <asm/mce.h>
+
+#include "mce_amd.h"
+
+struct edac_mce_attr {
+ struct attribute attr;
+ ssize_t (*show) (struct kobject *kobj, struct edac_mce_attr *attr, char *buf);
+ ssize_t (*store)(struct kobject *kobj, struct edac_mce_attr *attr,
+ const char *buf, size_t count);
+};
+
+#define EDAC_MCE_ATTR(_name, _mode, _show, _store) \
+static struct edac_mce_attr mce_attr_##_name = __ATTR(_name, _mode, _show, _store)
+
+static struct kobject *mce_kobj;
+
+/*
+ * Collect all the MCi_XXX settings
+ */
+static struct mce i_mce;
+
+#define MCE_INJECT_STORE(reg) \
+static ssize_t edac_inject_##reg##_store(struct kobject *kobj, \
+ struct edac_mce_attr *attr, \
+ const char *data, size_t count)\
+{ \
+ int ret = 0; \
+ unsigned long value; \
+ \
+ ret = strict_strtoul(data, 16, &value); \
+ if (ret < 0) \
+ printk(KERN_ERR "Error writing MCE " #reg " field.\n"); \
+ \
+ i_mce.reg = value; \
+ \
+ return count; \
+}
+
+MCE_INJECT_STORE(status);
+MCE_INJECT_STORE(misc);
+MCE_INJECT_STORE(addr);
+
+#define MCE_INJECT_SHOW(reg) \
+static ssize_t edac_inject_##reg##_show(struct kobject *kobj, \
+ struct edac_mce_attr *attr, \
+ char *buf) \
+{ \
+ return sprintf(buf, "0x%016llx\n", i_mce.reg); \
+}
+
+MCE_INJECT_SHOW(status);
+MCE_INJECT_SHOW(misc);
+MCE_INJECT_SHOW(addr);
+
+EDAC_MCE_ATTR(status, 0644, edac_inject_status_show, edac_inject_status_store);
+EDAC_MCE_ATTR(misc, 0644, edac_inject_misc_show, edac_inject_misc_store);
+EDAC_MCE_ATTR(addr, 0644, edac_inject_addr_show, edac_inject_addr_store);
+
+/*
+ * This denotes into which bank we're injecting and triggers
+ * the injection, at the same time.
+ */
+static ssize_t edac_inject_bank_store(struct kobject *kobj,
+ struct edac_mce_attr *attr,
+ const char *data, size_t count)
+{
+ int ret = 0;
+ unsigned long value;
+
+ ret = strict_strtoul(data, 10, &value);
+ if (ret < 0) {
+ printk(KERN_ERR "Invalid bank value!\n");
+ return -EINVAL;
+ }
+
+ if (value > 5) {
+ printk(KERN_ERR "Non-existant MCE bank: %lu\n", value);
+ return -EINVAL;
+ }
+
+ i_mce.bank = value;
+
+ amd_decode_mce(NULL, 0, &i_mce);
+
+ return count;
+}
+
+static ssize_t edac_inject_bank_show(struct kobject *kobj,
+ struct edac_mce_attr *attr, char *buf)
+{
+ return sprintf(buf, "%d\n", i_mce.bank);
+}
+
+EDAC_MCE_ATTR(bank, 0644, edac_inject_bank_show, edac_inject_bank_store);
+
+static struct edac_mce_attr *sysfs_attrs[] = { &mce_attr_status, &mce_attr_misc,
+ &mce_attr_addr, &mce_attr_bank
+};
+
+static int __init edac_init_mce_inject(void)
+{
+ struct sysdev_class *edac_class = NULL;
+ int i, err = 0;
+
+ edac_class = edac_get_sysfs_class();
+ if (!edac_class)
+ return -EINVAL;
+
+ mce_kobj = kobject_create_and_add("mce", &edac_class->kset.kobj);
+ if (!mce_kobj) {
+ printk(KERN_ERR "Error creating a mce kset.\n");
+ err = -ENOMEM;
+ goto err_mce_kobj;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(sysfs_attrs); i++) {
+ err = sysfs_create_file(mce_kobj, &sysfs_attrs[i]->attr);
+ if (err) {
+ printk(KERN_ERR "Error creating %s in sysfs.\n",
+ sysfs_attrs[i]->attr.name);
+ goto err_sysfs_create;
+ }
+ }
+ return 0;
+
+err_sysfs_create:
+ while (i-- >= 0)
+ sysfs_remove_file(mce_kobj, &sysfs_attrs[i]->attr);
+
+ kobject_del(mce_kobj);
+
+err_mce_kobj:
+ edac_put_sysfs_class();
+
+ return err;
+}
+
+static void __exit edac_exit_mce_inject(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(sysfs_attrs); i++)
+ sysfs_remove_file(mce_kobj, &sysfs_attrs[i]->attr);
+
+ kobject_del(mce_kobj);
+
+ edac_put_sysfs_class();
+}
+
+module_init(edac_init_mce_inject);
+module_exit(edac_exit_mce_inject);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Borislav Petkov <borislav.petkov@amd.com>");
+MODULE_AUTHOR("AMD Inc.");
+MODULE_DESCRIPTION("MCE injection facility for testing MCE decoding");
diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c
index 33f8421c71cc..18fdd9703b48 100644
--- a/drivers/firewire/net.c
+++ b/drivers/firewire/net.c
@@ -8,7 +8,6 @@
#include <linux/bug.h>
#include <linux/device.h>
-#include <linux/ethtool.h>
#include <linux/firewire.h>
#include <linux/firewire-constants.h>
#include <linux/highmem.h>
@@ -1361,17 +1360,6 @@ static int fwnet_change_mtu(struct net_device *net, int new_mtu)
return 0;
}
-static void fwnet_get_drvinfo(struct net_device *net,
- struct ethtool_drvinfo *info)
-{
- strcpy(info->driver, KBUILD_MODNAME);
- strcpy(info->bus_info, "ieee1394");
-}
-
-static const struct ethtool_ops fwnet_ethtool_ops = {
- .get_drvinfo = fwnet_get_drvinfo,
-};
-
static const struct net_device_ops fwnet_netdev_ops = {
.ndo_open = fwnet_open,
.ndo_stop = fwnet_stop,
@@ -1390,7 +1378,6 @@ static void fwnet_init_dev(struct net_device *net)
net->hard_header_len = FWNET_HLEN;
net->type = ARPHRD_IEEE1394;
net->tx_queue_len = 10;
- SET_ETHTOOL_OPS(net, &fwnet_ethtool_ops);
}
/* caller must hold fwnet_device_mutex */
diff --git a/drivers/firewire/nosy.c b/drivers/firewire/nosy.c
index 8528b10763ed..bf184fb59a5e 100644
--- a/drivers/firewire/nosy.c
+++ b/drivers/firewire/nosy.c
@@ -405,6 +405,7 @@ static const struct file_operations nosy_ops = {
.poll = nosy_poll,
.open = nosy_open,
.release = nosy_release,
+ .llseek = noop_llseek,
};
#define PHY_PACKET_SIZE 12 /* 1 payload, 1 inverse, 1 ack = 3 quadlets */
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index 1b05896648bc..9dcb17d51aee 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -2840,7 +2840,7 @@ static int __devinit pci_probe(struct pci_dev *dev,
const struct pci_device_id *ent)
{
struct fw_ohci *ohci;
- u32 bus_options, max_receive, link_speed, version, link_enh;
+ u32 bus_options, max_receive, link_speed, version;
u64 guid;
int i, err, n_ir, n_it;
size_t size;
@@ -2894,23 +2894,6 @@ static int __devinit pci_probe(struct pci_dev *dev,
if (param_quirks)
ohci->quirks = param_quirks;
- /* TI OHCI-Lynx and compatible: set recommended configuration bits. */
- if (dev->vendor == PCI_VENDOR_ID_TI) {
- pci_read_config_dword(dev, PCI_CFG_TI_LinkEnh, &link_enh);
-
- /* adjust latency of ATx FIFO: use 1.7 KB threshold */
- link_enh &= ~TI_LinkEnh_atx_thresh_mask;
- link_enh |= TI_LinkEnh_atx_thresh_1_7K;
-
- /* use priority arbitration for asynchronous responses */
- link_enh |= TI_LinkEnh_enab_unfair;
-
- /* required for aPhyEnhanceEnable to work */
- link_enh |= TI_LinkEnh_enab_accel;
-
- pci_write_config_dword(dev, PCI_CFG_TI_LinkEnh, link_enh);
- }
-
ar_context_init(&ohci->ar_request_ctx, ohci,
OHCI1394_AsReqRcvContextControlSet);
diff --git a/drivers/firewire/ohci.h b/drivers/firewire/ohci.h
index 0e6c5a466908..ef5e7336da68 100644
--- a/drivers/firewire/ohci.h
+++ b/drivers/firewire/ohci.h
@@ -155,12 +155,4 @@
#define OHCI1394_phy_tcode 0xe
-/* TI extensions */
-
-#define PCI_CFG_TI_LinkEnh 0xf4
-#define TI_LinkEnh_enab_accel 0x00000002
-#define TI_LinkEnh_enab_unfair 0x00000080
-#define TI_LinkEnh_atx_thresh_mask 0x00003000
-#define TI_LinkEnh_atx_thresh_1_7K 0x00001000
-
#endif /* _FIREWIRE_OHCI_H */
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index 280c9b5ad9e3..88a3ae6cd023 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -125,7 +125,7 @@ config ISCSI_IBFT_FIND
config ISCSI_IBFT
tristate "iSCSI Boot Firmware Table Attributes module"
select ISCSI_BOOT_SYSFS
- depends on ISCSI_IBFT_FIND && SCSI
+ depends on ISCSI_IBFT_FIND && SCSI && SCSI_LOWLEVEL
default n
help
This option enables support for detection and exposing of iSCSI
diff --git a/drivers/gpio/tc35892-gpio.c b/drivers/gpio/tc35892-gpio.c
index 1be6288780de..7e10c935a047 100644
--- a/drivers/gpio/tc35892-gpio.c
+++ b/drivers/gpio/tc35892-gpio.c
@@ -322,6 +322,9 @@ static int __devinit tc35892_gpio_probe(struct platform_device *pdev)
goto out_freeirq;
}
+ if (pdata->setup)
+ pdata->setup(tc35892, tc35892_gpio->chip.base);
+
platform_set_drvdata(pdev, tc35892_gpio);
return 0;
@@ -338,9 +341,14 @@ out_free:
static int __devexit tc35892_gpio_remove(struct platform_device *pdev)
{
struct tc35892_gpio *tc35892_gpio = platform_get_drvdata(pdev);
+ struct tc35892 *tc35892 = tc35892_gpio->tc35892;
+ struct tc35892_gpio_platform_data *pdata = tc35892->pdata->gpio;
int irq = platform_get_irq(pdev, 0);
int ret;
+ if (pdata->remove)
+ pdata->remove(tc35892, tc35892_gpio->chip.base);
+
ret = gpiochip_remove(&tc35892_gpio->chip);
if (ret < 0) {
dev_err(tc35892_gpio->dev,
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 4cab0c6397e3..7af443672626 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -73,7 +73,8 @@ source "drivers/gpu/drm/radeon/Kconfig"
config DRM_I810
tristate "Intel I810"
- depends on DRM && AGP && AGP_INTEL
+ # BKL usage in order to avoid AB-BA deadlocks, may become BROKEN_ON_SMP
+ depends on DRM && AGP && AGP_INTEL && BKL
help
Choose this option if you have an Intel I810 graphics card. If M is
selected, the module will be called i810. AGP support is required
@@ -86,6 +87,8 @@ choice
config DRM_I830
tristate "i830 driver"
+ # BKL usage in order to avoid AB-BA deadlocks, i830 may get removed
+ depends on BKL
help
Choose this option if you have a system that has Intel 830M, 845G,
852GM, 855GM or 865G integrated graphics. If M is selected, the
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 84da748555bc..ff6690f4fc87 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -284,7 +284,8 @@ EXPORT_SYMBOL(drm_exit);
/** File operations structure */
static const struct file_operations drm_stub_fops = {
.owner = THIS_MODULE,
- .open = drm_stub_open
+ .open = drm_stub_open,
+ .llseek = noop_llseek,
};
static int __init drm_core_init(void)
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index bf92d07510df..5663d2719063 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -148,7 +148,7 @@ int drm_gem_object_init(struct drm_device *dev,
return -ENOMEM;
kref_init(&obj->refcount);
- kref_init(&obj->handlecount);
+ atomic_set(&obj->handle_count, 0);
obj->size = size;
atomic_inc(&dev->object_count);
@@ -462,28 +462,6 @@ drm_gem_object_free(struct kref *kref)
}
EXPORT_SYMBOL(drm_gem_object_free);
-/**
- * Called after the last reference to the object has been lost.
- * Must be called without holding struct_mutex
- *
- * Frees the object
- */
-void
-drm_gem_object_free_unlocked(struct kref *kref)
-{
- struct drm_gem_object *obj = (struct drm_gem_object *) kref;
- struct drm_device *dev = obj->dev;
-
- if (dev->driver->gem_free_object_unlocked != NULL)
- dev->driver->gem_free_object_unlocked(obj);
- else if (dev->driver->gem_free_object != NULL) {
- mutex_lock(&dev->struct_mutex);
- dev->driver->gem_free_object(obj);
- mutex_unlock(&dev->struct_mutex);
- }
-}
-EXPORT_SYMBOL(drm_gem_object_free_unlocked);
-
static void drm_gem_object_ref_bug(struct kref *list_kref)
{
BUG();
@@ -496,12 +474,8 @@ static void drm_gem_object_ref_bug(struct kref *list_kref)
* called before drm_gem_object_free or we'll be touching
* freed memory
*/
-void
-drm_gem_object_handle_free(struct kref *kref)
+void drm_gem_object_handle_free(struct drm_gem_object *obj)
{
- struct drm_gem_object *obj = container_of(kref,
- struct drm_gem_object,
- handlecount);
struct drm_device *dev = obj->dev;
/* Remove any name for this object */
@@ -528,6 +502,10 @@ void drm_gem_vm_open(struct vm_area_struct *vma)
struct drm_gem_object *obj = vma->vm_private_data;
drm_gem_object_reference(obj);
+
+ mutex_lock(&obj->dev->struct_mutex);
+ drm_vm_open_locked(vma);
+ mutex_unlock(&obj->dev->struct_mutex);
}
EXPORT_SYMBOL(drm_gem_vm_open);
@@ -535,7 +513,10 @@ void drm_gem_vm_close(struct vm_area_struct *vma)
{
struct drm_gem_object *obj = vma->vm_private_data;
- drm_gem_object_unreference_unlocked(obj);
+ mutex_lock(&obj->dev->struct_mutex);
+ drm_vm_close_locked(vma);
+ drm_gem_object_unreference(obj);
+ mutex_unlock(&obj->dev->struct_mutex);
}
EXPORT_SYMBOL(drm_gem_vm_close);
diff --git a/drivers/gpu/drm/drm_info.c b/drivers/gpu/drm/drm_info.c
index 2ef2c7827243..974e970ce3f8 100644
--- a/drivers/gpu/drm/drm_info.c
+++ b/drivers/gpu/drm/drm_info.c
@@ -255,7 +255,7 @@ int drm_gem_one_name_info(int id, void *ptr, void *data)
seq_printf(m, "%6d %8zd %7d %8d\n",
obj->name, obj->size,
- atomic_read(&obj->handlecount.refcount),
+ atomic_read(&obj->handle_count),
atomic_read(&obj->refcount.refcount));
return 0;
}
diff --git a/drivers/gpu/drm/drm_vm.c b/drivers/gpu/drm/drm_vm.c
index fda67468e603..5df450683aab 100644
--- a/drivers/gpu/drm/drm_vm.c
+++ b/drivers/gpu/drm/drm_vm.c
@@ -433,15 +433,7 @@ static void drm_vm_open(struct vm_area_struct *vma)
mutex_unlock(&dev->struct_mutex);
}
-/**
- * \c close method for all virtual memory types.
- *
- * \param vma virtual memory area.
- *
- * Search the \p vma private data entry in drm_device::vmalist, unlink it, and
- * free it.
- */
-static void drm_vm_close(struct vm_area_struct *vma)
+void drm_vm_close_locked(struct vm_area_struct *vma)
{
struct drm_file *priv = vma->vm_file->private_data;
struct drm_device *dev = priv->minor->dev;
@@ -451,7 +443,6 @@ static void drm_vm_close(struct vm_area_struct *vma)
vma->vm_start, vma->vm_end - vma->vm_start);
atomic_dec(&dev->vma_count);
- mutex_lock(&dev->struct_mutex);
list_for_each_entry_safe(pt, temp, &dev->vmalist, head) {
if (pt->vma == vma) {
list_del(&pt->head);
@@ -459,6 +450,23 @@ static void drm_vm_close(struct vm_area_struct *vma)
break;
}
}
+}
+
+/**
+ * \c close method for all virtual memory types.
+ *
+ * \param vma virtual memory area.
+ *
+ * Search the \p vma private data entry in drm_device::vmalist, unlink it, and
+ * free it.
+ */
+static void drm_vm_close(struct vm_area_struct *vma)
+{
+ struct drm_file *priv = vma->vm_file->private_data;
+ struct drm_device *dev = priv->minor->dev;
+
+ mutex_lock(&dev->struct_mutex);
+ drm_vm_close_locked(vma);
mutex_unlock(&dev->struct_mutex);
}
diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c
index 61b4caf220fa..ff33e53bbbf8 100644
--- a/drivers/gpu/drm/i810/i810_dma.c
+++ b/drivers/gpu/drm/i810/i810_dma.c
@@ -116,9 +116,10 @@ static int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
static const struct file_operations i810_buffer_fops = {
.open = drm_open,
.release = drm_release,
- .unlocked_ioctl = drm_ioctl,
+ .unlocked_ioctl = i810_ioctl,
.mmap = i810_mmap_buffers,
.fasync = drm_fasync,
+ .llseek = noop_llseek,
};
static int i810_map_buffer(struct drm_buf *buf, struct drm_file *file_priv)
diff --git a/drivers/gpu/drm/i810/i810_drv.c b/drivers/gpu/drm/i810/i810_drv.c
index b4250b2cac1f..fe69914ce507 100644
--- a/drivers/gpu/drm/i810/i810_drv.c
+++ b/drivers/gpu/drm/i810/i810_drv.c
@@ -63,6 +63,7 @@ static struct drm_driver driver = {
.mmap = drm_mmap,
.poll = drm_poll,
.fasync = drm_fasync,
+ .llseek = noop_llseek,
},
.pci_driver = {
diff --git a/drivers/gpu/drm/i830/i830_dma.c b/drivers/gpu/drm/i830/i830_dma.c
index 671aa18415ac..ca6f31ff0eec 100644
--- a/drivers/gpu/drm/i830/i830_dma.c
+++ b/drivers/gpu/drm/i830/i830_dma.c
@@ -118,9 +118,10 @@ static int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
static const struct file_operations i830_buffer_fops = {
.open = drm_open,
.release = drm_release,
- .unlocked_ioctl = drm_ioctl,
+ .unlocked_ioctl = i830_ioctl,
.mmap = i830_mmap_buffers,
.fasync = drm_fasync,
+ .llseek = noop_llseek,
};
static int i830_map_buffer(struct drm_buf *buf, struct drm_file *file_priv)
diff --git a/drivers/gpu/drm/i830/i830_drv.c b/drivers/gpu/drm/i830/i830_drv.c
index a5c66aa82f0c..5b6298b24e24 100644
--- a/drivers/gpu/drm/i830/i830_drv.c
+++ b/drivers/gpu/drm/i830/i830_drv.c
@@ -74,6 +74,7 @@ static struct drm_driver driver = {
.mmap = drm_mmap,
.poll = drm_poll,
.fasync = drm_fasync,
+ .llseek = noop_llseek,
},
.pci_driver = {
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 5e43d7076789..048149748fdc 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -782,6 +782,7 @@ static const struct file_operations i915_wedged_fops = {
.open = i915_wedged_open,
.read = i915_wedged_read,
.write = i915_wedged_write,
+ .llseek = default_llseek,
};
/* As the drm_debugfs_init() routines are called before dev->dev_private is
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 9d67b4853030..2dd2c93ebfa3 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1787,9 +1787,9 @@ unsigned long i915_chipset_val(struct drm_i915_private *dev_priv)
}
}
- div_u64(diff, diff1);
+ diff = div_u64(diff, diff1);
ret = ((m * diff) + c);
- div_u64(ret, 10);
+ ret = div_u64(ret, 10);
dev_priv->last_count1 = total_count;
dev_priv->last_time1 = now;
@@ -1858,7 +1858,7 @@ void i915_update_gfx_val(struct drm_i915_private *dev_priv)
/* More magic constants... */
diff = diff * 1181;
- div_u64(diff, diffms * 10);
+ diff = div_u64(diff, diffms * 10);
dev_priv->gfx_power = diff;
}
@@ -2231,6 +2231,9 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
dev_priv->mchdev_lock = &mchdev_lock;
spin_unlock(&mchdev_lock);
+ /* XXX Prevent module unload due to memory corruption bugs. */
+ __module_get(THIS_MODULE);
+
return 0;
out_workqueue_free:
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 6dbe14cc4f74..895ab896e336 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -548,6 +548,7 @@ static struct drm_driver driver = {
#ifdef CONFIG_COMPAT
.compat_ioctl = i915_compat_ioctl,
#endif
+ .llseek = noop_llseek,
},
.pci_driver = {
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index bced9b25c71e..90b1d6753b9d 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -136,14 +136,12 @@ i915_gem_create_ioctl(struct drm_device *dev, void *data,
return -ENOMEM;
ret = drm_gem_handle_create(file_priv, obj, &handle);
+ /* drop reference from allocate - handle holds it now */
+ drm_gem_object_unreference_unlocked(obj);
if (ret) {
- drm_gem_object_unreference_unlocked(obj);
return ret;
}
- /* Sink the floating reference from kref_init(handlecount) */
- drm_gem_object_handle_unreference_unlocked(obj);
-
args->handle = handle;
return 0;
}
@@ -471,14 +469,17 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data,
return -ENOENT;
obj_priv = to_intel_bo(obj);
- /* Bounds check source.
- *
- * XXX: This could use review for overflow issues...
- */
- if (args->offset > obj->size || args->size > obj->size ||
- args->offset + args->size > obj->size) {
- drm_gem_object_unreference_unlocked(obj);
- return -EINVAL;
+ /* Bounds check source. */
+ if (args->offset > obj->size || args->size > obj->size - args->offset) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ if (!access_ok(VERIFY_WRITE,
+ (char __user *)(uintptr_t)args->data_ptr,
+ args->size)) {
+ ret = -EFAULT;
+ goto err;
}
if (i915_gem_object_needs_bit17_swizzle(obj)) {
@@ -490,8 +491,8 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data,
file_priv);
}
+err:
drm_gem_object_unreference_unlocked(obj);
-
return ret;
}
@@ -580,8 +581,6 @@ i915_gem_gtt_pwrite_fast(struct drm_device *dev, struct drm_gem_object *obj,
user_data = (char __user *) (uintptr_t) args->data_ptr;
remain = args->size;
- if (!access_ok(VERIFY_READ, user_data, remain))
- return -EFAULT;
mutex_lock(&dev->struct_mutex);
@@ -934,14 +933,17 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
return -ENOENT;
obj_priv = to_intel_bo(obj);
- /* Bounds check destination.
- *
- * XXX: This could use review for overflow issues...
- */
- if (args->offset > obj->size || args->size > obj->size ||
- args->offset + args->size > obj->size) {
- drm_gem_object_unreference_unlocked(obj);
- return -EINVAL;
+ /* Bounds check destination. */
+ if (args->offset > obj->size || args->size > obj->size - args->offset) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ if (!access_ok(VERIFY_READ,
+ (char __user *)(uintptr_t)args->data_ptr,
+ args->size)) {
+ ret = -EFAULT;
+ goto err;
}
/* We can only do the GTT pwrite on untiled buffers, as otherwise
@@ -975,8 +977,8 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
DRM_INFO("pwrite failed %d\n", ret);
#endif
+err:
drm_gem_object_unreference_unlocked(obj);
-
return ret;
}
@@ -3258,6 +3260,8 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
(int) reloc->offset,
reloc->read_domains,
reloc->write_domain);
+ drm_gem_object_unreference(target_obj);
+ i915_gem_object_unpin(obj);
return -EINVAL;
}
if (reloc->write_domain & I915_GEM_DOMAIN_CPU ||
diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c
index e85246ef691c..5c428fa3e0b3 100644
--- a/drivers/gpu/drm/i915/i915_gem_evict.c
+++ b/drivers/gpu/drm/i915/i915_gem_evict.c
@@ -93,7 +93,7 @@ i915_gem_evict_something(struct drm_device *dev, int min_size, unsigned alignmen
{
drm_i915_private_t *dev_priv = dev->dev_private;
struct list_head eviction_list, unwind_list;
- struct drm_i915_gem_object *obj_priv, *tmp_obj_priv;
+ struct drm_i915_gem_object *obj_priv;
struct list_head *render_iter, *bsd_iter;
int ret = 0;
@@ -175,39 +175,34 @@ i915_gem_evict_something(struct drm_device *dev, int min_size, unsigned alignmen
return -ENOSPC;
found:
+ /* drm_mm doesn't allow any other other operations while
+ * scanning, therefore store to be evicted objects on a
+ * temporary list. */
INIT_LIST_HEAD(&eviction_list);
- list_for_each_entry_safe(obj_priv, tmp_obj_priv,
- &unwind_list, evict_list) {
+ while (!list_empty(&unwind_list)) {
+ obj_priv = list_first_entry(&unwind_list,
+ struct drm_i915_gem_object,
+ evict_list);
if (drm_mm_scan_remove_block(obj_priv->gtt_space)) {
- /* drm_mm doesn't allow any other other operations while
- * scanning, therefore store to be evicted objects on a
- * temporary list. */
list_move(&obj_priv->evict_list, &eviction_list);
- } else
- drm_gem_object_unreference(&obj_priv->base);
+ continue;
+ }
+ list_del(&obj_priv->evict_list);
+ drm_gem_object_unreference(&obj_priv->base);
}
/* Unbinding will emit any required flushes */
- list_for_each_entry_safe(obj_priv, tmp_obj_priv,
- &eviction_list, evict_list) {
-#if WATCH_LRU
- DRM_INFO("%s: evicting %p\n", __func__, &obj_priv->base);
-#endif
- ret = i915_gem_object_unbind(&obj_priv->base);
- if (ret)
- return ret;
-
+ while (!list_empty(&eviction_list)) {
+ obj_priv = list_first_entry(&eviction_list,
+ struct drm_i915_gem_object,
+ evict_list);
+ if (ret == 0)
+ ret = i915_gem_object_unbind(&obj_priv->base);
+ list_del(&obj_priv->evict_list);
drm_gem_object_unreference(&obj_priv->base);
}
- /* The just created free hole should be on the top of the free stack
- * maintained by drm_mm, so this BUG_ON actually executes in O(1).
- * Furthermore all accessed data has just recently been used, so it
- * should be really fast, too. */
- BUG_ON(!drm_mm_search_free(&dev_priv->mm.gtt_space, min_size,
- alignment, 0));
-
- return 0;
+ return ret;
}
int
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index b5bf51a4502d..979228594599 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1013,8 +1013,8 @@ void intel_wait_for_vblank(struct drm_device *dev, int pipe)
DRM_DEBUG_KMS("vblank wait timed out\n");
}
-/**
- * intel_wait_for_vblank_off - wait for vblank after disabling a pipe
+/*
+ * intel_wait_for_pipe_off - wait for pipe to turn off
* @dev: drm device
* @pipe: pipe to wait for
*
@@ -1022,25 +1022,39 @@ void intel_wait_for_vblank(struct drm_device *dev, int pipe)
* spinning on the vblank interrupt status bit, since we won't actually
* see an interrupt when the pipe is disabled.
*
- * So this function waits for the display line value to settle (it
- * usually ends up stopping at the start of the next frame).
+ * On Gen4 and above:
+ * wait for the pipe register state bit to turn off
+ *
+ * Otherwise:
+ * wait for the display line value to settle (it usually
+ * ends up stopping at the start of the next frame).
+ *
*/
-void intel_wait_for_vblank_off(struct drm_device *dev, int pipe)
+static void intel_wait_for_pipe_off(struct drm_device *dev, int pipe)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- int pipedsl_reg = (pipe == 0 ? PIPEADSL : PIPEBDSL);
- unsigned long timeout = jiffies + msecs_to_jiffies(100);
- u32 last_line;
-
- /* Wait for the display line to settle */
- do {
- last_line = I915_READ(pipedsl_reg) & DSL_LINEMASK;
- mdelay(5);
- } while (((I915_READ(pipedsl_reg) & DSL_LINEMASK) != last_line) &&
- time_after(timeout, jiffies));
-
- if (time_after(jiffies, timeout))
- DRM_DEBUG_KMS("vblank wait timed out\n");
+
+ if (INTEL_INFO(dev)->gen >= 4) {
+ int pipeconf_reg = (pipe == 0 ? PIPEACONF : PIPEBCONF);
+
+ /* Wait for the Pipe State to go off */
+ if (wait_for((I915_READ(pipeconf_reg) & I965_PIPECONF_ACTIVE) == 0,
+ 100, 0))
+ DRM_DEBUG_KMS("pipe_off wait timed out\n");
+ } else {
+ u32 last_line;
+ int pipedsl_reg = (pipe == 0 ? PIPEADSL : PIPEBDSL);
+ unsigned long timeout = jiffies + msecs_to_jiffies(100);
+
+ /* Wait for the display line to settle */
+ do {
+ last_line = I915_READ(pipedsl_reg) & DSL_LINEMASK;
+ mdelay(5);
+ } while (((I915_READ(pipedsl_reg) & DSL_LINEMASK) != last_line) &&
+ time_after(timeout, jiffies));
+ if (time_after(jiffies, timeout))
+ DRM_DEBUG_KMS("pipe_off wait timed out\n");
+ }
}
/* Parameters have changed, update FBC info */
@@ -2328,13 +2342,13 @@ static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode)
I915_READ(dspbase_reg);
}
- /* Wait for vblank for the disable to take effect */
- intel_wait_for_vblank_off(dev, pipe);
-
/* Don't disable pipe A or pipe A PLLs if needed */
if (pipeconf_reg == PIPEACONF &&
- (dev_priv->quirks & QUIRK_PIPEA_FORCE))
+ (dev_priv->quirks & QUIRK_PIPEA_FORCE)) {
+ /* Wait for vblank for the disable to take effect */
+ intel_wait_for_vblank(dev, pipe);
goto skip_pipe_off;
+ }
/* Next, disable display pipes */
temp = I915_READ(pipeconf_reg);
@@ -2343,8 +2357,8 @@ static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode)
I915_READ(pipeconf_reg);
}
- /* Wait for vblank for the disable to take effect. */
- intel_wait_for_vblank_off(dev, pipe);
+ /* Wait for the pipe to turn off */
+ intel_wait_for_pipe_off(dev, pipe);
temp = I915_READ(dpll_reg);
if ((temp & DPLL_VCO_ENABLE) != 0) {
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 1a51ee07de3e..9ab8708ac6ba 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1138,18 +1138,14 @@ static bool
intel_dp_set_link_train(struct intel_dp *intel_dp,
uint32_t dp_reg_value,
uint8_t dp_train_pat,
- uint8_t train_set[4],
- bool first)
+ uint8_t train_set[4])
{
struct drm_device *dev = intel_dp->base.enc.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
- struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.enc.crtc);
int ret;
I915_WRITE(intel_dp->output_reg, dp_reg_value);
POSTING_READ(intel_dp->output_reg);
- if (first)
- intel_wait_for_vblank(dev, intel_crtc->pipe);
intel_dp_aux_native_write_1(intel_dp,
DP_TRAINING_PATTERN_SET,
@@ -1174,10 +1170,15 @@ intel_dp_link_train(struct intel_dp *intel_dp)
uint8_t voltage;
bool clock_recovery = false;
bool channel_eq = false;
- bool first = true;
int tries;
u32 reg;
uint32_t DP = intel_dp->DP;
+ struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.enc.crtc);
+
+ /* Enable output, wait for it to become active */
+ I915_WRITE(intel_dp->output_reg, intel_dp->DP);
+ POSTING_READ(intel_dp->output_reg);
+ intel_wait_for_vblank(dev, intel_crtc->pipe);
/* Write the link configuration data */
intel_dp_aux_native_write(intel_dp, DP_LINK_BW_SET,
@@ -1210,9 +1211,8 @@ intel_dp_link_train(struct intel_dp *intel_dp)
reg = DP | DP_LINK_TRAIN_PAT_1;
if (!intel_dp_set_link_train(intel_dp, reg,
- DP_TRAINING_PATTERN_1, train_set, first))
+ DP_TRAINING_PATTERN_1, train_set))
break;
- first = false;
/* Set training pattern 1 */
udelay(100);
@@ -1266,8 +1266,7 @@ intel_dp_link_train(struct intel_dp *intel_dp)
/* channel eq pattern */
if (!intel_dp_set_link_train(intel_dp, reg,
- DP_TRAINING_PATTERN_2, train_set,
- false))
+ DP_TRAINING_PATTERN_2, train_set))
break;
udelay(400);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index ad312ca6b3e5..8828b3ac6414 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -229,7 +229,6 @@ extern struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
struct drm_crtc *crtc);
int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
struct drm_file *file_priv);
-extern void intel_wait_for_vblank_off(struct drm_device *dev, int pipe);
extern void intel_wait_for_vblank(struct drm_device *dev, int pipe);
extern struct drm_crtc *intel_get_crtc_from_pipe(struct drm_device *dev, int pipe);
extern struct drm_crtc *intel_get_load_detect_pipe(struct intel_encoder *intel_encoder,
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c
index 7bdc96256bf5..b61966c126d3 100644
--- a/drivers/gpu/drm/i915/intel_fb.c
+++ b/drivers/gpu/drm/i915/intel_fb.c
@@ -237,8 +237,10 @@ int intel_fbdev_destroy(struct drm_device *dev,
drm_fb_helper_fini(&ifbdev->helper);
drm_framebuffer_cleanup(&ifb->base);
- if (ifb->obj)
+ if (ifb->obj) {
drm_gem_object_unreference(ifb->obj);
+ ifb->obj = NULL;
+ }
return 0;
}
diff --git a/drivers/gpu/drm/mga/mga_drv.c b/drivers/gpu/drm/mga/mga_drv.c
index 26d0d8ced80d..ac64f0b0392e 100644
--- a/drivers/gpu/drm/mga/mga_drv.c
+++ b/drivers/gpu/drm/mga/mga_drv.c
@@ -75,6 +75,7 @@ static struct drm_driver driver = {
#ifdef CONFIG_COMPAT
.compat_ioctl = mga_compat_ioctl,
#endif
+ .llseek = noop_llseek,
},
.pci_driver = {
.name = DRIVER_NAME,
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c
index 1de5eb53e016..eb15345162a0 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.c
@@ -393,6 +393,7 @@ static struct drm_driver driver = {
#if defined(CONFIG_COMPAT)
.compat_ioctl = nouveau_compat_ioctl,
#endif
+ .llseek = noop_llseek,
},
.pci_driver = {
.name = DRIVER_NAME,
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c
index ead7b8fc53fc..19620a6709f5 100644
--- a/drivers/gpu/drm/nouveau/nouveau_gem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
@@ -167,11 +167,9 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data,
goto out;
ret = drm_gem_handle_create(file_priv, nvbo->gem, &req->info.handle);
+ /* drop reference from allocate - handle holds it now */
+ drm_gem_object_unreference_unlocked(nvbo->gem);
out:
- drm_gem_object_handle_unreference_unlocked(nvbo->gem);
-
- if (ret)
- drm_gem_object_unreference_unlocked(nvbo->gem);
return ret;
}
diff --git a/drivers/gpu/drm/r128/r128_drv.c b/drivers/gpu/drm/r128/r128_drv.c
index 1e2971f13aa1..d42c76c23714 100644
--- a/drivers/gpu/drm/r128/r128_drv.c
+++ b/drivers/gpu/drm/r128/r128_drv.c
@@ -71,6 +71,7 @@ static struct drm_driver driver = {
#ifdef CONFIG_COMPAT
.compat_ioctl = r128_compat_ioctl,
#endif
+ .llseek = noop_llseek,
},
.pci_driver = {
.name = DRIVER_NAME,
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index 79082d4398ae..2f93d46ae69a 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -1137,7 +1137,7 @@ static void evergreen_gpu_init(struct radeon_device *rdev)
WREG32(RCU_IND_INDEX, 0x203);
efuse_straps_3 = RREG32(RCU_IND_DATA);
- efuse_box_bit_127_124 = (u8)(efuse_straps_3 & 0xF0000000) >> 28;
+ efuse_box_bit_127_124 = (u8)((efuse_straps_3 & 0xF0000000) >> 28);
switch(efuse_box_bit_127_124) {
case 0x0:
@@ -1407,6 +1407,7 @@ int evergreen_mc_init(struct radeon_device *rdev)
rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024;
rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024;
rdev->mc.visible_vram_size = rdev->mc.aper_size;
+ rdev->mc.active_vram_size = rdev->mc.visible_vram_size;
r600_vram_gtt_location(rdev, &rdev->mc);
radeon_update_bandwidth_info(rdev);
@@ -1520,7 +1521,7 @@ void evergreen_disable_interrupt_state(struct radeon_device *rdev)
{
u32 tmp;
- WREG32(CP_INT_CNTL, 0);
+ WREG32(CP_INT_CNTL, CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE);
WREG32(GRBM_INT_CNTL, 0);
WREG32(INT_MASK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0);
WREG32(INT_MASK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0);
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index e151f16a8f86..e59422320bb6 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -1030,6 +1030,7 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size)
return r;
}
rdev->cp.ready = true;
+ rdev->mc.active_vram_size = rdev->mc.real_vram_size;
return 0;
}
@@ -1047,6 +1048,7 @@ void r100_cp_fini(struct radeon_device *rdev)
void r100_cp_disable(struct radeon_device *rdev)
{
/* Disable ring */
+ rdev->mc.active_vram_size = rdev->mc.visible_vram_size;
rdev->cp.ready = false;
WREG32(RADEON_CP_CSQ_MODE, 0);
WREG32(RADEON_CP_CSQ_CNTL, 0);
@@ -2295,6 +2297,7 @@ void r100_vram_init_sizes(struct radeon_device *rdev)
/* FIXME we don't use the second aperture yet when we could use it */
if (rdev->mc.visible_vram_size > rdev->mc.aper_size)
rdev->mc.visible_vram_size = rdev->mc.aper_size;
+ rdev->mc.active_vram_size = rdev->mc.visible_vram_size;
config_aper_size = RREG32(RADEON_CONFIG_APER_SIZE);
if (rdev->flags & RADEON_IS_IGP) {
uint32_t tom;
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index ddc3adea1dda..7b65e4efe8af 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -1248,6 +1248,7 @@ int r600_mc_init(struct radeon_device *rdev)
rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE);
rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE);
rdev->mc.visible_vram_size = rdev->mc.aper_size;
+ rdev->mc.active_vram_size = rdev->mc.visible_vram_size;
r600_vram_gtt_location(rdev, &rdev->mc);
if (rdev->flags & RADEON_IS_IGP) {
@@ -1917,6 +1918,7 @@ void r600_pciep_wreg(struct radeon_device *rdev, u32 reg, u32 v)
*/
void r600_cp_stop(struct radeon_device *rdev)
{
+ rdev->mc.active_vram_size = rdev->mc.visible_vram_size;
WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1));
}
@@ -2910,7 +2912,7 @@ static void r600_disable_interrupt_state(struct radeon_device *rdev)
{
u32 tmp;
- WREG32(CP_INT_CNTL, 0);
+ WREG32(CP_INT_CNTL, CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE);
WREG32(GRBM_INT_CNTL, 0);
WREG32(DxMODE_INT_MASK, 0);
if (ASIC_IS_DCE3(rdev)) {
@@ -3528,7 +3530,8 @@ void r600_ioctl_wait_idle(struct radeon_device *rdev, struct radeon_bo *bo)
/* r7xx hw bug. write to HDP_DEBUG1 followed by fb read
* rather than write to HDP_REG_COHERENCY_FLUSH_CNTL
*/
- if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740)) {
+ if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740) &&
+ rdev->vram_scratch.ptr) {
void __iomem *ptr = (void *)rdev->vram_scratch.ptr;
u32 tmp;
diff --git a/drivers/gpu/drm/radeon/r600_blit_kms.c b/drivers/gpu/drm/radeon/r600_blit_kms.c
index 9ceb2a1ce799..3473c00781ff 100644
--- a/drivers/gpu/drm/radeon/r600_blit_kms.c
+++ b/drivers/gpu/drm/radeon/r600_blit_kms.c
@@ -532,6 +532,7 @@ int r600_blit_init(struct radeon_device *rdev)
memcpy(ptr + rdev->r600_blit.ps_offset, r6xx_ps, r6xx_ps_size * 4);
radeon_bo_kunmap(rdev->r600_blit.shader_obj);
radeon_bo_unreserve(rdev->r600_blit.shader_obj);
+ rdev->mc.active_vram_size = rdev->mc.real_vram_size;
return 0;
}
@@ -539,6 +540,7 @@ void r600_blit_fini(struct radeon_device *rdev)
{
int r;
+ rdev->mc.active_vram_size = rdev->mc.visible_vram_size;
if (rdev->r600_blit.shader_obj == NULL)
return;
/* If we can't reserve the bo, unref should be enough to destroy
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index a168d644bf9e..9ff38c99a6ea 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -344,6 +344,7 @@ struct radeon_mc {
* about vram size near mc fb location */
u64 mc_vram_size;
u64 visible_vram_size;
+ u64 active_vram_size;
u64 gtt_size;
u64 gtt_start;
u64 gtt_end;
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c
index ebae14c4b768..8e43ddae70cc 100644
--- a/drivers/gpu/drm/radeon/radeon_atombios.c
+++ b/drivers/gpu/drm/radeon/radeon_atombios.c
@@ -317,6 +317,15 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev,
*connector_type = DRM_MODE_CONNECTOR_DVID;
}
+ /* MSI K9A2GM V2/V3 board has no HDMI or DVI */
+ if ((dev->pdev->device == 0x796e) &&
+ (dev->pdev->subsystem_vendor == 0x1462) &&
+ (dev->pdev->subsystem_device == 0x7302)) {
+ if ((supported_device == ATOM_DEVICE_DFP2_SUPPORT) ||
+ (supported_device == ATOM_DEVICE_DFP3_SUPPORT))
+ return false;
+ }
+
/* a-bit f-i90hd - ciaranm on #radeonhd - this board has no DVI */
if ((dev->pdev->device == 0x7941) &&
(dev->pdev->subsystem_vendor == 0x147b) &&
@@ -1549,39 +1558,39 @@ radeon_atombios_get_tv_info(struct radeon_device *rdev)
switch (tv_info->ucTV_BootUpDefaultStandard) {
case ATOM_TV_NTSC:
tv_std = TV_STD_NTSC;
- DRM_INFO("Default TV standard: NTSC\n");
+ DRM_DEBUG_KMS("Default TV standard: NTSC\n");
break;
case ATOM_TV_NTSCJ:
tv_std = TV_STD_NTSC_J;
- DRM_INFO("Default TV standard: NTSC-J\n");
+ DRM_DEBUG_KMS("Default TV standard: NTSC-J\n");
break;
case ATOM_TV_PAL:
tv_std = TV_STD_PAL;
- DRM_INFO("Default TV standard: PAL\n");
+ DRM_DEBUG_KMS("Default TV standard: PAL\n");
break;
case ATOM_TV_PALM:
tv_std = TV_STD_PAL_M;
- DRM_INFO("Default TV standard: PAL-M\n");
+ DRM_DEBUG_KMS("Default TV standard: PAL-M\n");
break;
case ATOM_TV_PALN:
tv_std = TV_STD_PAL_N;
- DRM_INFO("Default TV standard: PAL-N\n");
+ DRM_DEBUG_KMS("Default TV standard: PAL-N\n");
break;
case ATOM_TV_PALCN:
tv_std = TV_STD_PAL_CN;
- DRM_INFO("Default TV standard: PAL-CN\n");
+ DRM_DEBUG_KMS("Default TV standard: PAL-CN\n");
break;
case ATOM_TV_PAL60:
tv_std = TV_STD_PAL_60;
- DRM_INFO("Default TV standard: PAL-60\n");
+ DRM_DEBUG_KMS("Default TV standard: PAL-60\n");
break;
case ATOM_TV_SECAM:
tv_std = TV_STD_SECAM;
- DRM_INFO("Default TV standard: SECAM\n");
+ DRM_DEBUG_KMS("Default TV standard: SECAM\n");
break;
default:
tv_std = TV_STD_NTSC;
- DRM_INFO("Unknown TV standard; defaulting to NTSC\n");
+ DRM_DEBUG_KMS("Unknown TV standard; defaulting to NTSC\n");
break;
}
}
diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c
index a04b7a6ad95f..7b7ea269549c 100644
--- a/drivers/gpu/drm/radeon/radeon_combios.c
+++ b/drivers/gpu/drm/radeon/radeon_combios.c
@@ -913,47 +913,47 @@ radeon_combios_get_tv_info(struct radeon_device *rdev)
switch (RBIOS8(tv_info + 7) & 0xf) {
case 1:
tv_std = TV_STD_NTSC;
- DRM_INFO("Default TV standard: NTSC\n");
+ DRM_DEBUG_KMS("Default TV standard: NTSC\n");
break;
case 2:
tv_std = TV_STD_PAL;
- DRM_INFO("Default TV standard: PAL\n");
+ DRM_DEBUG_KMS("Default TV standard: PAL\n");
break;
case 3:
tv_std = TV_STD_PAL_M;
- DRM_INFO("Default TV standard: PAL-M\n");
+ DRM_DEBUG_KMS("Default TV standard: PAL-M\n");
break;
case 4:
tv_std = TV_STD_PAL_60;
- DRM_INFO("Default TV standard: PAL-60\n");
+ DRM_DEBUG_KMS("Default TV standard: PAL-60\n");
break;
case 5:
tv_std = TV_STD_NTSC_J;
- DRM_INFO("Default TV standard: NTSC-J\n");
+ DRM_DEBUG_KMS("Default TV standard: NTSC-J\n");
break;
case 6:
tv_std = TV_STD_SCART_PAL;
- DRM_INFO("Default TV standard: SCART-PAL\n");
+ DRM_DEBUG_KMS("Default TV standard: SCART-PAL\n");
break;
default:
tv_std = TV_STD_NTSC;
- DRM_INFO
+ DRM_DEBUG_KMS
("Unknown TV standard; defaulting to NTSC\n");
break;
}
switch ((RBIOS8(tv_info + 9) >> 2) & 0x3) {
case 0:
- DRM_INFO("29.498928713 MHz TV ref clk\n");
+ DRM_DEBUG_KMS("29.498928713 MHz TV ref clk\n");
break;
case 1:
- DRM_INFO("28.636360000 MHz TV ref clk\n");
+ DRM_DEBUG_KMS("28.636360000 MHz TV ref clk\n");
break;
case 2:
- DRM_INFO("14.318180000 MHz TV ref clk\n");
+ DRM_DEBUG_KMS("14.318180000 MHz TV ref clk\n");
break;
case 3:
- DRM_INFO("27.000000000 MHz TV ref clk\n");
+ DRM_DEBUG_KMS("27.000000000 MHz TV ref clk\n");
break;
default:
break;
@@ -1324,7 +1324,7 @@ bool radeon_legacy_get_tmds_info_from_combios(struct radeon_encoder *encoder,
if (tmds_info) {
ver = RBIOS8(tmds_info);
- DRM_INFO("DFP table revision: %d\n", ver);
+ DRM_DEBUG_KMS("DFP table revision: %d\n", ver);
if (ver == 3) {
n = RBIOS8(tmds_info + 5) + 1;
if (n > 4)
@@ -1408,7 +1408,7 @@ bool radeon_legacy_get_ext_tmds_info_from_combios(struct radeon_encoder *encoder
offset = combios_get_table_offset(dev, COMBIOS_EXT_TMDS_INFO_TABLE);
if (offset) {
ver = RBIOS8(offset);
- DRM_INFO("External TMDS Table revision: %d\n", ver);
+ DRM_DEBUG_KMS("External TMDS Table revision: %d\n", ver);
tmds->slave_addr = RBIOS8(offset + 4 + 2);
tmds->slave_addr >>= 1; /* 7 bit addressing */
gpio = RBIOS8(offset + 4 + 3);
diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c b/drivers/gpu/drm/radeon/radeon_cursor.c
index 5731fc9b1ae3..3eef567b0421 100644
--- a/drivers/gpu/drm/radeon/radeon_cursor.c
+++ b/drivers/gpu/drm/radeon/radeon_cursor.c
@@ -203,6 +203,7 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc,
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
struct radeon_device *rdev = crtc->dev->dev_private;
int xorigin = 0, yorigin = 0;
+ int w = radeon_crtc->cursor_width;
if (x < 0)
xorigin = -x + 1;
@@ -213,22 +214,7 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc,
if (yorigin >= CURSOR_HEIGHT)
yorigin = CURSOR_HEIGHT - 1;
- radeon_lock_cursor(crtc, true);
- if (ASIC_IS_DCE4(rdev)) {
- /* cursors are offset into the total surface */
- x += crtc->x;
- y += crtc->y;
- DRM_DEBUG("x %d y %d c->x %d c->y %d\n", x, y, crtc->x, crtc->y);
-
- /* XXX: check if evergreen has the same issues as avivo chips */
- WREG32(EVERGREEN_CUR_POSITION + radeon_crtc->crtc_offset,
- ((xorigin ? 0 : x) << 16) |
- (yorigin ? 0 : y));
- WREG32(EVERGREEN_CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin);
- WREG32(EVERGREEN_CUR_SIZE + radeon_crtc->crtc_offset,
- ((radeon_crtc->cursor_width - 1) << 16) | (radeon_crtc->cursor_height - 1));
- } else if (ASIC_IS_AVIVO(rdev)) {
- int w = radeon_crtc->cursor_width;
+ if (ASIC_IS_AVIVO(rdev)) {
int i = 0;
struct drm_crtc *crtc_p;
@@ -260,7 +246,17 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc,
if (w <= 0)
w = 1;
}
+ }
+ radeon_lock_cursor(crtc, true);
+ if (ASIC_IS_DCE4(rdev)) {
+ WREG32(EVERGREEN_CUR_POSITION + radeon_crtc->crtc_offset,
+ ((xorigin ? 0 : x) << 16) |
+ (yorigin ? 0 : y));
+ WREG32(EVERGREEN_CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin);
+ WREG32(EVERGREEN_CUR_SIZE + radeon_crtc->crtc_offset,
+ ((w - 1) << 16) | (radeon_crtc->cursor_height - 1));
+ } else if (ASIC_IS_AVIVO(rdev)) {
WREG32(AVIVO_D1CUR_POSITION + radeon_crtc->crtc_offset,
((xorigin ? 0 : x) << 16) |
(yorigin ? 0 : y));
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 127a395f70fb..b92d2f2fcbed 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -349,6 +349,8 @@ static void radeon_print_display_setup(struct drm_device *dev)
DRM_INFO(" DFP4: %s\n", encoder_names[radeon_encoder->encoder_id]);
if (devices & ATOM_DEVICE_DFP5_SUPPORT)
DRM_INFO(" DFP5: %s\n", encoder_names[radeon_encoder->encoder_id]);
+ if (devices & ATOM_DEVICE_DFP6_SUPPORT)
+ DRM_INFO(" DFP6: %s\n", encoder_names[radeon_encoder->encoder_id]);
if (devices & ATOM_DEVICE_TV1_SUPPORT)
DRM_INFO(" TV1: %s\n", encoder_names[radeon_encoder->encoder_id]);
if (devices & ATOM_DEVICE_CV_SUPPORT)
@@ -841,8 +843,9 @@ static void radeon_user_framebuffer_destroy(struct drm_framebuffer *fb)
{
struct radeon_framebuffer *radeon_fb = to_radeon_framebuffer(fb);
- if (radeon_fb->obj)
+ if (radeon_fb->obj) {
drm_gem_object_unreference_unlocked(radeon_fb->obj);
+ }
drm_framebuffer_cleanup(fb);
kfree(radeon_fb);
}
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index 795403b0e2cd..29c1237c2e7b 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -219,6 +219,7 @@ static struct drm_driver driver_old = {
#ifdef CONFIG_COMPAT
.compat_ioctl = radeon_compat_ioctl,
#endif
+ .llseek = noop_llseek,
},
.pci_driver = {
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c
index c74a8b20d941..40b0c087b592 100644
--- a/drivers/gpu/drm/radeon/radeon_fb.c
+++ b/drivers/gpu/drm/radeon/radeon_fb.c
@@ -94,6 +94,7 @@ static void radeonfb_destroy_pinned_object(struct drm_gem_object *gobj)
ret = radeon_bo_reserve(rbo, false);
if (likely(ret == 0)) {
radeon_bo_kunmap(rbo);
+ radeon_bo_unpin(rbo);
radeon_bo_unreserve(rbo);
}
drm_gem_object_unreference_unlocked(gobj);
@@ -325,8 +326,6 @@ static int radeon_fbdev_destroy(struct drm_device *dev, struct radeon_fbdev *rfb
{
struct fb_info *info;
struct radeon_framebuffer *rfb = &rfbdev->rfb;
- struct radeon_bo *rbo;
- int r;
if (rfbdev->helper.fbdev) {
info = rfbdev->helper.fbdev;
@@ -338,14 +337,8 @@ static int radeon_fbdev_destroy(struct drm_device *dev, struct radeon_fbdev *rfb
}
if (rfb->obj) {
- rbo = rfb->obj->driver_private;
- r = radeon_bo_reserve(rbo, false);
- if (likely(r == 0)) {
- radeon_bo_kunmap(rbo);
- radeon_bo_unpin(rbo);
- radeon_bo_unreserve(rbo);
- }
- drm_gem_object_unreference_unlocked(rfb->obj);
+ radeonfb_destroy_pinned_object(rfb->obj);
+ rfb->obj = NULL;
}
drm_fb_helper_fini(&rfbdev->helper);
drm_framebuffer_cleanup(&rfb->base);
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c
index c578f265b24c..d1e595d91723 100644
--- a/drivers/gpu/drm/radeon/radeon_gem.c
+++ b/drivers/gpu/drm/radeon/radeon_gem.c
@@ -201,11 +201,11 @@ int radeon_gem_create_ioctl(struct drm_device *dev, void *data,
return r;
}
r = drm_gem_handle_create(filp, gobj, &handle);
+ /* drop reference from allocate - handle holds it now */
+ drm_gem_object_unreference_unlocked(gobj);
if (r) {
- drm_gem_object_unreference_unlocked(gobj);
return r;
}
- drm_gem_object_handle_unreference_unlocked(gobj);
args->handle = handle;
return 0;
}
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c
index 0afd1e62347d..b3b5306bb578 100644
--- a/drivers/gpu/drm/radeon/radeon_object.c
+++ b/drivers/gpu/drm/radeon/radeon_object.c
@@ -69,7 +69,7 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain)
u32 c = 0;
rbo->placement.fpfn = 0;
- rbo->placement.lpfn = 0;
+ rbo->placement.lpfn = rbo->rdev->mc.active_vram_size >> PAGE_SHIFT;
rbo->placement.placement = rbo->placements;
rbo->placement.busy_placement = rbo->placements;
if (domain & RADEON_GEM_DOMAIN_VRAM)
diff --git a/drivers/gpu/drm/radeon/radeon_object.h b/drivers/gpu/drm/radeon/radeon_object.h
index 353998dc2c03..3481bc7f6f58 100644
--- a/drivers/gpu/drm/radeon/radeon_object.h
+++ b/drivers/gpu/drm/radeon/radeon_object.h
@@ -124,11 +124,8 @@ static inline int radeon_bo_wait(struct radeon_bo *bo, u32 *mem_type,
int r;
r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, 0);
- if (unlikely(r != 0)) {
- if (r != -ERESTARTSYS)
- dev_err(bo->rdev->dev, "%p reserve failed for wait\n", bo);
+ if (unlikely(r != 0))
return r;
- }
spin_lock(&bo->tbo.lock);
if (mem_type)
*mem_type = bo->tbo.mem.mem_type;
diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c
index cc05b230d7ef..51d5f7b5ab21 100644
--- a/drivers/gpu/drm/radeon/rs600.c
+++ b/drivers/gpu/drm/radeon/rs600.c
@@ -693,6 +693,7 @@ void rs600_mc_init(struct radeon_device *rdev)
rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE);
rdev->mc.mc_vram_size = rdev->mc.real_vram_size;
rdev->mc.visible_vram_size = rdev->mc.aper_size;
+ rdev->mc.active_vram_size = rdev->mc.visible_vram_size;
rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev);
base = RREG32_MC(R_000004_MC_FB_LOCATION);
base = G_000004_MC_FB_START(base) << 16;
diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c
index 3e3f75718be3..4dc2a87ea680 100644
--- a/drivers/gpu/drm/radeon/rs690.c
+++ b/drivers/gpu/drm/radeon/rs690.c
@@ -157,6 +157,7 @@ void rs690_mc_init(struct radeon_device *rdev)
rdev->mc.aper_base = pci_resource_start(rdev->pdev, 0);
rdev->mc.aper_size = pci_resource_len(rdev->pdev, 0);
rdev->mc.visible_vram_size = rdev->mc.aper_size;
+ rdev->mc.active_vram_size = rdev->mc.visible_vram_size;
base = RREG32_MC(R_000100_MCCFG_FB_LOCATION);
base = G_000100_MC_FB_START(base) << 16;
rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev);
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c
index bfa59db374d2..9490da700749 100644
--- a/drivers/gpu/drm/radeon/rv770.c
+++ b/drivers/gpu/drm/radeon/rv770.c
@@ -267,6 +267,7 @@ static void rv770_mc_program(struct radeon_device *rdev)
*/
void r700_cp_stop(struct radeon_device *rdev)
{
+ rdev->mc.active_vram_size = rdev->mc.visible_vram_size;
WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT));
}
@@ -992,6 +993,7 @@ int rv770_mc_init(struct radeon_device *rdev)
rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE);
rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE);
rdev->mc.visible_vram_size = rdev->mc.aper_size;
+ rdev->mc.active_vram_size = rdev->mc.visible_vram_size;
r600_vram_gtt_location(rdev, &rdev->mc);
radeon_update_bandwidth_info(rdev);
diff --git a/drivers/gpu/drm/savage/savage_drv.c b/drivers/gpu/drm/savage/savage_drv.c
index 021de44c15ab..2a2830f5a840 100644
--- a/drivers/gpu/drm/savage/savage_drv.c
+++ b/drivers/gpu/drm/savage/savage_drv.c
@@ -54,6 +54,7 @@ static struct drm_driver driver = {
.mmap = drm_mmap,
.poll = drm_poll,
.fasync = drm_fasync,
+ .llseek = noop_llseek,
},
.pci_driver = {
diff --git a/drivers/gpu/drm/sis/sis_drv.c b/drivers/gpu/drm/sis/sis_drv.c
index 776bf9e9ea1a..4bb10ef6676a 100644
--- a/drivers/gpu/drm/sis/sis_drv.c
+++ b/drivers/gpu/drm/sis/sis_drv.c
@@ -83,6 +83,7 @@ static struct drm_driver driver = {
.mmap = drm_mmap,
.poll = drm_poll,
.fasync = drm_fasync,
+ .llseek = noop_llseek,
},
.pci_driver = {
.name = DRIVER_NAME,
diff --git a/drivers/gpu/drm/tdfx/tdfx_drv.c b/drivers/gpu/drm/tdfx/tdfx_drv.c
index ec5a43e65722..640567ef713d 100644
--- a/drivers/gpu/drm/tdfx/tdfx_drv.c
+++ b/drivers/gpu/drm/tdfx/tdfx_drv.c
@@ -52,6 +52,7 @@ static struct drm_driver driver = {
.mmap = drm_mmap,
.poll = drm_poll,
.fasync = drm_fasync,
+ .llseek = noop_llseek,
},
.pci_driver = {
.name = DRIVER_NAME,
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index cb4cf7ef4d1e..db809e034cc4 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -442,6 +442,43 @@ out_err:
}
/**
+ * Call bo::reserved and with the lru lock held.
+ * Will release GPU memory type usage on destruction.
+ * This is the place to put in driver specific hooks.
+ * Will release the bo::reserved lock and the
+ * lru lock on exit.
+ */
+
+static void ttm_bo_cleanup_memtype_use(struct ttm_buffer_object *bo)
+{
+ struct ttm_bo_global *glob = bo->glob;
+
+ if (bo->ttm) {
+
+ /**
+ * Release the lru_lock, since we don't want to have
+ * an atomic requirement on ttm_tt[unbind|destroy].
+ */
+
+ spin_unlock(&glob->lru_lock);
+ ttm_tt_unbind(bo->ttm);
+ ttm_tt_destroy(bo->ttm);
+ bo->ttm = NULL;
+ spin_lock(&glob->lru_lock);
+ }
+
+ if (bo->mem.mm_node) {
+ drm_mm_put_block(bo->mem.mm_node);
+ bo->mem.mm_node = NULL;
+ }
+
+ atomic_set(&bo->reserved, 0);
+ wake_up_all(&bo->event_queue);
+ spin_unlock(&glob->lru_lock);
+}
+
+
+/**
* If bo idle, remove from delayed- and lru lists, and unref.
* If not idle, and already on delayed list, do nothing.
* If not idle, and not on delayed list, put on delayed list,
@@ -456,6 +493,7 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo, bool remove_all)
int ret;
spin_lock(&bo->lock);
+retry:
(void) ttm_bo_wait(bo, false, false, !remove_all);
if (!bo->sync_obj) {
@@ -464,31 +502,52 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo, bool remove_all)
spin_unlock(&bo->lock);
spin_lock(&glob->lru_lock);
- put_count = ttm_bo_del_from_lru(bo);
+ ret = ttm_bo_reserve_locked(bo, false, !remove_all, false, 0);
+
+ /**
+ * Someone else has the object reserved. Bail and retry.
+ */
- ret = ttm_bo_reserve_locked(bo, false, false, false, 0);
- BUG_ON(ret);
- if (bo->ttm)
- ttm_tt_unbind(bo->ttm);
+ if (unlikely(ret == -EBUSY)) {
+ spin_unlock(&glob->lru_lock);
+ spin_lock(&bo->lock);
+ goto requeue;
+ }
+
+ /**
+ * We can re-check for sync object without taking
+ * the bo::lock since setting the sync object requires
+ * also bo::reserved. A busy object at this point may
+ * be caused by another thread starting an accelerated
+ * eviction.
+ */
+
+ if (unlikely(bo->sync_obj)) {
+ atomic_set(&bo->reserved, 0);
+ wake_up_all(&bo->event_queue);
+ spin_unlock(&glob->lru_lock);
+ spin_lock(&bo->lock);
+ if (remove_all)
+ goto retry;
+ else
+ goto requeue;
+ }
+
+ put_count = ttm_bo_del_from_lru(bo);
if (!list_empty(&bo->ddestroy)) {
list_del_init(&bo->ddestroy);
++put_count;
}
- if (bo->mem.mm_node) {
- drm_mm_put_block(bo->mem.mm_node);
- bo->mem.mm_node = NULL;
- }
- spin_unlock(&glob->lru_lock);
- atomic_set(&bo->reserved, 0);
+ ttm_bo_cleanup_memtype_use(bo);
while (put_count--)
kref_put(&bo->list_kref, ttm_bo_ref_bug);
return 0;
}
-
+requeue:
spin_lock(&glob->lru_lock);
if (list_empty(&bo->ddestroy)) {
void *sync_obj = bo->sync_obj;
diff --git a/drivers/gpu/drm/via/via_drv.c b/drivers/gpu/drm/via/via_drv.c
index 7a1b210401e0..b8984a5ae521 100644
--- a/drivers/gpu/drm/via/via_drv.c
+++ b/drivers/gpu/drm/via/via_drv.c
@@ -62,6 +62,7 @@ static struct drm_driver driver = {
.mmap = drm_mmap,
.poll = drm_poll,
.fasync = drm_fasync,
+ .llseek = noop_llseek,
},
.pci_driver = {
.name = DRIVER_NAME,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 72ec2e2b6e97..2ef93df9e8ae 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -148,13 +148,16 @@ static struct pci_device_id vmw_pci_id_list[] = {
{0, 0, 0}
};
-static char *vmw_devname = "vmwgfx";
+static int enable_fbdev;
static int vmw_probe(struct pci_dev *, const struct pci_device_id *);
static void vmw_master_init(struct vmw_master *);
static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,
void *ptr);
+MODULE_PARM_DESC(enable_fbdev, "Enable vmwgfx fbdev");
+module_param_named(enable_fbdev, enable_fbdev, int, 0600);
+
static void vmw_print_capabilities(uint32_t capabilities)
{
DRM_INFO("Capabilities:\n");
@@ -192,8 +195,6 @@ static int vmw_request_device(struct vmw_private *dev_priv)
{
int ret;
- vmw_kms_save_vga(dev_priv);
-
ret = vmw_fifo_init(dev_priv, &dev_priv->fifo);
if (unlikely(ret != 0)) {
DRM_ERROR("Unable to initialize FIFO.\n");
@@ -206,9 +207,35 @@ static int vmw_request_device(struct vmw_private *dev_priv)
static void vmw_release_device(struct vmw_private *dev_priv)
{
vmw_fifo_release(dev_priv, &dev_priv->fifo);
- vmw_kms_restore_vga(dev_priv);
}
+int vmw_3d_resource_inc(struct vmw_private *dev_priv)
+{
+ int ret = 0;
+
+ mutex_lock(&dev_priv->release_mutex);
+ if (unlikely(dev_priv->num_3d_resources++ == 0)) {
+ ret = vmw_request_device(dev_priv);
+ if (unlikely(ret != 0))
+ --dev_priv->num_3d_resources;
+ }
+ mutex_unlock(&dev_priv->release_mutex);
+ return ret;
+}
+
+
+void vmw_3d_resource_dec(struct vmw_private *dev_priv)
+{
+ int32_t n3d;
+
+ mutex_lock(&dev_priv->release_mutex);
+ if (unlikely(--dev_priv->num_3d_resources == 0))
+ vmw_release_device(dev_priv);
+ n3d = (int32_t) dev_priv->num_3d_resources;
+ mutex_unlock(&dev_priv->release_mutex);
+
+ BUG_ON(n3d < 0);
+}
static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
{
@@ -228,6 +255,7 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
dev_priv->last_read_sequence = (uint32_t) -100;
mutex_init(&dev_priv->hw_mutex);
mutex_init(&dev_priv->cmdbuf_mutex);
+ mutex_init(&dev_priv->release_mutex);
rwlock_init(&dev_priv->resource_lock);
idr_init(&dev_priv->context_idr);
idr_init(&dev_priv->surface_idr);
@@ -244,6 +272,8 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
dev_priv->vram_start = pci_resource_start(dev->pdev, 1);
dev_priv->mmio_start = pci_resource_start(dev->pdev, 2);
+ dev_priv->enable_fb = enable_fbdev;
+
mutex_lock(&dev_priv->hw_mutex);
vmw_write(dev_priv, SVGA_REG_ID, SVGA_ID_2);
@@ -343,17 +373,6 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
dev->dev_private = dev_priv;
- if (!dev->devname)
- dev->devname = vmw_devname;
-
- if (dev_priv->capabilities & SVGA_CAP_IRQMASK) {
- ret = drm_irq_install(dev);
- if (unlikely(ret != 0)) {
- DRM_ERROR("Failed installing irq: %d\n", ret);
- goto out_no_irq;
- }
- }
-
ret = pci_request_regions(dev->pdev, "vmwgfx probe");
dev_priv->stealth = (ret != 0);
if (dev_priv->stealth) {
@@ -369,26 +388,52 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
goto out_no_device;
}
}
- ret = vmw_request_device(dev_priv);
+ ret = vmw_kms_init(dev_priv);
if (unlikely(ret != 0))
- goto out_no_device;
- vmw_kms_init(dev_priv);
+ goto out_no_kms;
vmw_overlay_init(dev_priv);
- vmw_fb_init(dev_priv);
+ if (dev_priv->enable_fb) {
+ ret = vmw_3d_resource_inc(dev_priv);
+ if (unlikely(ret != 0))
+ goto out_no_fifo;
+ vmw_kms_save_vga(dev_priv);
+ vmw_fb_init(dev_priv);
+ DRM_INFO("%s", vmw_fifo_have_3d(dev_priv) ?
+ "Detected device 3D availability.\n" :
+ "Detected no device 3D availability.\n");
+ } else {
+ DRM_INFO("Delayed 3D detection since we're not "
+ "running the device in SVGA mode yet.\n");
+ }
+
+ if (dev_priv->capabilities & SVGA_CAP_IRQMASK) {
+ ret = drm_irq_install(dev);
+ if (unlikely(ret != 0)) {
+ DRM_ERROR("Failed installing irq: %d\n", ret);
+ goto out_no_irq;
+ }
+ }
dev_priv->pm_nb.notifier_call = vmwgfx_pm_notifier;
register_pm_notifier(&dev_priv->pm_nb);
- DRM_INFO("%s", vmw_fifo_have_3d(dev_priv) ? "Have 3D\n" : "No 3D\n");
-
return 0;
-out_no_device:
- if (dev_priv->capabilities & SVGA_CAP_IRQMASK)
- drm_irq_uninstall(dev_priv->dev);
- if (dev->devname == vmw_devname)
- dev->devname = NULL;
out_no_irq:
+ if (dev_priv->enable_fb) {
+ vmw_fb_close(dev_priv);
+ vmw_kms_restore_vga(dev_priv);
+ vmw_3d_resource_dec(dev_priv);
+ }
+out_no_fifo:
+ vmw_overlay_close(dev_priv);
+ vmw_kms_close(dev_priv);
+out_no_kms:
+ if (dev_priv->stealth)
+ pci_release_region(dev->pdev, 2);
+ else
+ pci_release_regions(dev->pdev);
+out_no_device:
ttm_object_device_release(&dev_priv->tdev);
out_err4:
iounmap(dev_priv->mmio_virt);
@@ -415,19 +460,20 @@ static int vmw_driver_unload(struct drm_device *dev)
unregister_pm_notifier(&dev_priv->pm_nb);
- vmw_fb_close(dev_priv);
+ if (dev_priv->capabilities & SVGA_CAP_IRQMASK)
+ drm_irq_uninstall(dev_priv->dev);
+ if (dev_priv->enable_fb) {
+ vmw_fb_close(dev_priv);
+ vmw_kms_restore_vga(dev_priv);
+ vmw_3d_resource_dec(dev_priv);
+ }
vmw_kms_close(dev_priv);
vmw_overlay_close(dev_priv);
- vmw_release_device(dev_priv);
if (dev_priv->stealth)
pci_release_region(dev->pdev, 2);
else
pci_release_regions(dev->pdev);
- if (dev_priv->capabilities & SVGA_CAP_IRQMASK)
- drm_irq_uninstall(dev_priv->dev);
- if (dev->devname == vmw_devname)
- dev->devname = NULL;
ttm_object_device_release(&dev_priv->tdev);
iounmap(dev_priv->mmio_virt);
drm_mtrr_del(dev_priv->mmio_mtrr, dev_priv->mmio_start,
@@ -500,7 +546,7 @@ static long vmw_unlocked_ioctl(struct file *filp, unsigned int cmd,
struct drm_ioctl_desc *ioctl =
&vmw_ioctls[nr - DRM_COMMAND_BASE];
- if (unlikely(ioctl->cmd != cmd)) {
+ if (unlikely(ioctl->cmd_drv != cmd)) {
DRM_ERROR("Invalid command format, ioctl %d\n",
nr - DRM_COMMAND_BASE);
return -EINVAL;
@@ -589,6 +635,16 @@ static int vmw_master_set(struct drm_device *dev,
struct vmw_master *vmaster = vmw_master(file_priv->master);
int ret = 0;
+ if (!dev_priv->enable_fb) {
+ ret = vmw_3d_resource_inc(dev_priv);
+ if (unlikely(ret != 0))
+ return ret;
+ vmw_kms_save_vga(dev_priv);
+ mutex_lock(&dev_priv->hw_mutex);
+ vmw_write(dev_priv, SVGA_REG_TRACES, 0);
+ mutex_unlock(&dev_priv->hw_mutex);
+ }
+
if (active) {
BUG_ON(active != &dev_priv->fbdev_master);
ret = ttm_vt_lock(&active->lock, false, vmw_fp->tfile);
@@ -617,7 +673,13 @@ static int vmw_master_set(struct drm_device *dev,
return 0;
out_no_active_lock:
- vmw_release_device(dev_priv);
+ if (!dev_priv->enable_fb) {
+ mutex_lock(&dev_priv->hw_mutex);
+ vmw_write(dev_priv, SVGA_REG_TRACES, 1);
+ mutex_unlock(&dev_priv->hw_mutex);
+ vmw_kms_restore_vga(dev_priv);
+ vmw_3d_resource_dec(dev_priv);
+ }
return ret;
}
@@ -645,11 +707,23 @@ static void vmw_master_drop(struct drm_device *dev,
ttm_lock_set_kill(&vmaster->lock, true, SIGTERM);
+ if (!dev_priv->enable_fb) {
+ ret = ttm_bo_evict_mm(&dev_priv->bdev, TTM_PL_VRAM);
+ if (unlikely(ret != 0))
+ DRM_ERROR("Unable to clean VRAM on master drop.\n");
+ mutex_lock(&dev_priv->hw_mutex);
+ vmw_write(dev_priv, SVGA_REG_TRACES, 1);
+ mutex_unlock(&dev_priv->hw_mutex);
+ vmw_kms_restore_vga(dev_priv);
+ vmw_3d_resource_dec(dev_priv);
+ }
+
dev_priv->active_master = &dev_priv->fbdev_master;
ttm_lock_set_kill(&dev_priv->fbdev_master.lock, false, SIGTERM);
ttm_vt_unlock(&dev_priv->fbdev_master.lock);
- vmw_fb_on(dev_priv);
+ if (dev_priv->enable_fb)
+ vmw_fb_on(dev_priv);
}
@@ -722,6 +796,7 @@ static struct drm_driver driver = {
.irq_postinstall = vmw_irq_postinstall,
.irq_uninstall = vmw_irq_uninstall,
.irq_handler = vmw_irq_handler,
+ .get_vblank_counter = vmw_get_vblank_counter,
.reclaim_buffers_locked = NULL,
.get_map_ofs = drm_core_get_map_ofs,
.get_reg_ofs = drm_core_get_reg_ofs,
@@ -745,6 +820,7 @@ static struct drm_driver driver = {
#if defined(CONFIG_COMPAT)
.compat_ioctl = drm_compat_ioctl,
#endif
+ .llseek = noop_llseek,
},
.pci_driver = {
.name = VMWGFX_DRIVER_NAME,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index 429f917b60bf..58de6393f611 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -277,6 +277,7 @@ struct vmw_private {
bool stealth;
bool is_opened;
+ bool enable_fb;
/**
* Master management.
@@ -285,6 +286,9 @@ struct vmw_private {
struct vmw_master *active_master;
struct vmw_master fbdev_master;
struct notifier_block pm_nb;
+
+ struct mutex release_mutex;
+ uint32_t num_3d_resources;
};
static inline struct vmw_private *vmw_priv(struct drm_device *dev)
@@ -319,6 +323,9 @@ static inline uint32_t vmw_read(struct vmw_private *dev_priv,
return val;
}
+int vmw_3d_resource_inc(struct vmw_private *dev_priv);
+void vmw_3d_resource_dec(struct vmw_private *dev_priv);
+
/**
* GMR utilities - vmwgfx_gmr.c
*/
@@ -511,6 +518,7 @@ void vmw_kms_write_svga(struct vmw_private *vmw_priv,
unsigned bbp, unsigned depth);
int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
+u32 vmw_get_vblank_counter(struct drm_device *dev, int crtc);
/**
* Overlay control - vmwgfx_overlay.c
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
index 870967a97c15..409e172f4abf 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
@@ -615,6 +615,11 @@ int vmw_dmabuf_to_start_of_vram(struct vmw_private *vmw_priv,
if (unlikely(ret != 0))
goto err_unlock;
+ if (bo->mem.mem_type == TTM_PL_VRAM &&
+ bo->mem.mm_node->start < bo->num_pages)
+ (void) ttm_bo_validate(bo, &vmw_sys_placement, false,
+ false, false);
+
ret = ttm_bo_validate(bo, &ne_placement, false, false, false);
/* Could probably bug on */
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
index e6a1eb7ea954..0fe31766e4cf 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
@@ -106,6 +106,7 @@ int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
mutex_lock(&dev_priv->hw_mutex);
dev_priv->enable_state = vmw_read(dev_priv, SVGA_REG_ENABLE);
dev_priv->config_done_state = vmw_read(dev_priv, SVGA_REG_CONFIG_DONE);
+ dev_priv->traces_state = vmw_read(dev_priv, SVGA_REG_TRACES);
vmw_write(dev_priv, SVGA_REG_ENABLE, 1);
min = 4;
@@ -175,6 +176,8 @@ void vmw_fifo_release(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
dev_priv->config_done_state);
vmw_write(dev_priv, SVGA_REG_ENABLE,
dev_priv->enable_state);
+ vmw_write(dev_priv, SVGA_REG_TRACES,
+ dev_priv->traces_state);
mutex_unlock(&dev_priv->hw_mutex);
vmw_fence_queue_takedown(&fifo->fence_queue);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 64d7f47df868..e882ba099f0c 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -898,7 +898,19 @@ int vmw_kms_save_vga(struct vmw_private *vmw_priv)
save->width = vmw_read(vmw_priv, SVGA_REG_DISPLAY_WIDTH);
save->height = vmw_read(vmw_priv, SVGA_REG_DISPLAY_HEIGHT);
vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
+ if (i == 0 && vmw_priv->num_displays == 1 &&
+ save->width == 0 && save->height == 0) {
+
+ /*
+ * It should be fairly safe to assume that these
+ * values are uninitialized.
+ */
+
+ save->width = vmw_priv->vga_width - save->pos_x;
+ save->height = vmw_priv->vga_height - save->pos_y;
+ }
}
+
return 0;
}
@@ -984,3 +996,8 @@ out_unlock:
ttm_read_unlock(&vmaster->lock);
return ret;
}
+
+u32 vmw_get_vblank_counter(struct drm_device *dev, int crtc)
+{
+ return 0;
+}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
index 7083b1a24df3..11cb39e3accb 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
@@ -27,6 +27,8 @@
#include "vmwgfx_kms.h"
+#define VMWGFX_LDU_NUM_DU 8
+
#define vmw_crtc_to_ldu(x) \
container_of(x, struct vmw_legacy_display_unit, base.crtc)
#define vmw_encoder_to_ldu(x) \
@@ -536,6 +538,10 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv)
{
+ struct drm_device *dev = dev_priv->dev;
+ int i;
+ int ret;
+
if (dev_priv->ldu_priv) {
DRM_INFO("ldu system already on\n");
return -EINVAL;
@@ -553,23 +559,24 @@ int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv)
drm_mode_create_dirty_info_property(dev_priv->dev);
- vmw_ldu_init(dev_priv, 0);
- /* for old hardware without multimon only enable one display */
if (dev_priv->capabilities & SVGA_CAP_MULTIMON) {
- vmw_ldu_init(dev_priv, 1);
- vmw_ldu_init(dev_priv, 2);
- vmw_ldu_init(dev_priv, 3);
- vmw_ldu_init(dev_priv, 4);
- vmw_ldu_init(dev_priv, 5);
- vmw_ldu_init(dev_priv, 6);
- vmw_ldu_init(dev_priv, 7);
+ for (i = 0; i < VMWGFX_LDU_NUM_DU; ++i)
+ vmw_ldu_init(dev_priv, i);
+ ret = drm_vblank_init(dev, VMWGFX_LDU_NUM_DU);
+ } else {
+ /* for old hardware without multimon only enable one display */
+ vmw_ldu_init(dev_priv, 0);
+ ret = drm_vblank_init(dev, 1);
}
- return 0;
+ return ret;
}
int vmw_kms_close_legacy_display_system(struct vmw_private *dev_priv)
{
+ struct drm_device *dev = dev_priv->dev;
+
+ drm_vblank_cleanup(dev);
if (!dev_priv->ldu_priv)
return -ENOSYS;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
index 5f2d5df01e5c..c8c40e9979db 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
@@ -211,6 +211,7 @@ static void vmw_hw_context_destroy(struct vmw_resource *res)
cmd->body.cid = cpu_to_le32(res->id);
vmw_fifo_commit(dev_priv, sizeof(*cmd));
+ vmw_3d_resource_dec(dev_priv);
}
static int vmw_context_init(struct vmw_private *dev_priv,
@@ -247,6 +248,7 @@ static int vmw_context_init(struct vmw_private *dev_priv,
cmd->body.cid = cpu_to_le32(res->id);
vmw_fifo_commit(dev_priv, sizeof(*cmd));
+ (void) vmw_3d_resource_inc(dev_priv);
vmw_resource_activate(res, vmw_hw_context_destroy);
return 0;
}
@@ -406,6 +408,7 @@ static void vmw_hw_surface_destroy(struct vmw_resource *res)
cmd->body.sid = cpu_to_le32(res->id);
vmw_fifo_commit(dev_priv, sizeof(*cmd));
+ vmw_3d_resource_dec(dev_priv);
}
void vmw_surface_res_free(struct vmw_resource *res)
@@ -473,6 +476,7 @@ int vmw_surface_init(struct vmw_private *dev_priv,
}
vmw_fifo_commit(dev_priv, submit_size);
+ (void) vmw_3d_resource_inc(dev_priv);
vmw_resource_activate(res, vmw_hw_surface_destroy);
return 0;
}
diff --git a/drivers/gpu/vga/vgaarb.c b/drivers/gpu/vga/vgaarb.c
index f366f968155a..c380c65da417 100644
--- a/drivers/gpu/vga/vgaarb.c
+++ b/drivers/gpu/vga/vgaarb.c
@@ -1211,6 +1211,7 @@ static const struct file_operations vga_arb_device_fops = {
.poll = vga_arb_fpoll,
.open = vga_arb_open,
.release = vga_arb_release,
+ .llseek = noop_llseek,
};
static struct miscdevice vga_arb_device = {
diff --git a/drivers/hid/hid-cando.c b/drivers/hid/hid-cando.c
index 4267a6fdc277..5925bdcd417d 100644
--- a/drivers/hid/hid-cando.c
+++ b/drivers/hid/hid-cando.c
@@ -237,6 +237,8 @@ static const struct hid_device_id cando_devices[] = {
USB_DEVICE_ID_CANDO_MULTI_TOUCH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
+ USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) },
{ }
};
MODULE_DEVICE_TABLE(hid, cando_devices);
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 3f7292486024..3cb6632d4518 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1292,6 +1292,7 @@ static const struct hid_device_id hid_blacklist[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) },
@@ -1661,6 +1662,7 @@ static const struct hid_device_id hid_ignore_list[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1006) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1007) },
{ HID_USB_DEVICE(USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_JESS, USB_DEVICE_ID_JESS_YUREX) },
{ HID_USB_DEVICE(USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_KWORLD, USB_DEVICE_ID_KWORLD_RADIO_FM700) },
{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_GPEN_560) },
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c
index 850d02a7a925..61a3e572224a 100644
--- a/drivers/hid/hid-debug.c
+++ b/drivers/hid/hid-debug.c
@@ -1051,6 +1051,7 @@ static const struct file_operations hid_debug_events_fops = {
.read = hid_debug_events_read,
.poll = hid_debug_events_poll,
.release = hid_debug_events_release,
+ .llseek = noop_llseek,
};
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 765a4f53eb5c..855aa8e355f4 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -134,6 +134,7 @@
#define USB_VENDOR_ID_CANDO 0x2087
#define USB_DEVICE_ID_CANDO_MULTI_TOUCH 0x0a01
#define USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6 0x0b03
+#define USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6 0x0f01
#define USB_VENDOR_ID_CH 0x068e
#define USB_DEVICE_ID_CH_PRO_PEDALS 0x00f2
@@ -303,6 +304,9 @@
#define USB_VENDOR_ID_IMATION 0x0718
#define USB_DEVICE_ID_DISC_STAKKA 0xd000
+#define USB_VENDOR_ID_JESS 0x0c45
+#define USB_DEVICE_ID_JESS_YUREX 0x1010
+
#define USB_VENDOR_ID_KBGEAR 0x084e
#define USB_DEVICE_ID_KBGEAR_JAMSTUDIO 0x1001
@@ -503,6 +507,7 @@
#define USB_VENDOR_ID_TURBOX 0x062a
#define USB_DEVICE_ID_TURBOX_KEYBOARD 0x0201
+#define USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART 0x7100
#define USB_VENDOR_ID_TWINHAN 0x6253
#define USB_DEVICE_ID_TWINHAN_IR_REMOTE 0x0100
diff --git a/drivers/hid/hid-roccat.c b/drivers/hid/hid-roccat.c
index f6e80c7ca61e..5a6879e235ac 100644
--- a/drivers/hid/hid-roccat.c
+++ b/drivers/hid/hid-roccat.c
@@ -384,6 +384,7 @@ static const struct file_operations roccat_ops = {
.poll = roccat_poll,
.open = roccat_open,
.release = roccat_release,
+ .llseek = noop_llseek,
};
static int __init roccat_init(void)
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index 47d70c523d93..925992f549f0 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -109,6 +109,12 @@ static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t
int ret = 0;
mutex_lock(&minors_lock);
+
+ if (!hidraw_table[minor]) {
+ ret = -ENODEV;
+ goto out;
+ }
+
dev = hidraw_table[minor]->hid;
if (!dev->hid_output_raw_report) {
@@ -244,6 +250,10 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd,
mutex_lock(&minors_lock);
dev = hidraw_table[minor];
+ if (!dev) {
+ ret = -ENODEV;
+ goto out;
+ }
switch (cmd) {
case HIDIOCGRDESCSIZE:
@@ -317,6 +327,7 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd,
ret = -ENOTTY;
}
+out:
mutex_unlock(&minors_lock);
return ret;
}
@@ -329,6 +340,7 @@ static const struct file_operations hidraw_ops = {
.open = hidraw_open,
.release = hidraw_release,
.unlocked_ioctl = hidraw_ioctl,
+ .llseek = noop_llseek,
};
void hidraw_report_event(struct hid_device *hid, u8 *data, int len)
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index 70da3181c8a0..f0260c699adb 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -36,6 +36,7 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_DWAV, USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER, HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET },
{ USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH, HID_QUIRK_MULTI_INPUT },
{ USB_VENDOR_ID_MOJO, USB_DEVICE_ID_RETRO_ADAPTER, HID_QUIRK_MULTI_INPUT },
+ { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART, HID_QUIRK_MULTI_INPUT },
{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c
index 681e620eb95b..dfcb27613ec5 100644
--- a/drivers/hid/usbhid/hiddev.c
+++ b/drivers/hid/usbhid/hiddev.c
@@ -847,6 +847,7 @@ static const struct file_operations hiddev_fops = {
#ifdef CONFIG_COMPAT
.compat_ioctl = hiddev_compat_ioctl,
#endif
+ .llseek = noop_llseek,
};
static char *hiddev_devnode(struct device *dev, mode_t *mode)
diff --git a/drivers/hwmon/asus_atk0110.c b/drivers/hwmon/asus_atk0110.c
index 653db1bda934..23b8555215d2 100644
--- a/drivers/hwmon/asus_atk0110.c
+++ b/drivers/hwmon/asus_atk0110.c
@@ -762,6 +762,7 @@ static const struct file_operations atk_debugfs_ggrp_fops = {
.read = atk_debugfs_ggrp_read,
.open = atk_debugfs_ggrp_open,
.release = atk_debugfs_ggrp_release,
+ .llseek = no_llseek,
};
static void atk_debugfs_init(struct atk_data *data)
diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c
index 537841ef44b9..75afb3b0e076 100644
--- a/drivers/hwmon/f71882fg.c
+++ b/drivers/hwmon/f71882fg.c
@@ -111,7 +111,7 @@ static struct platform_device *f71882fg_pdev;
/* Super-I/O Function prototypes */
static inline int superio_inb(int base, int reg);
static inline int superio_inw(int base, int reg);
-static inline void superio_enter(int base);
+static inline int superio_enter(int base);
static inline void superio_select(int base, int ld);
static inline void superio_exit(int base);
@@ -861,11 +861,20 @@ static int superio_inw(int base, int reg)
return val;
}
-static inline void superio_enter(int base)
+static inline int superio_enter(int base)
{
+ /* Don't step on other drivers' I/O space by accident */
+ if (!request_muxed_region(base, 2, DRVNAME)) {
+ printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n",
+ base);
+ return -EBUSY;
+ }
+
/* according to the datasheet the key must be send twice! */
outb(SIO_UNLOCK_KEY, base);
outb(SIO_UNLOCK_KEY, base);
+
+ return 0;
}
static inline void superio_select(int base, int ld)
@@ -877,6 +886,7 @@ static inline void superio_select(int base, int ld)
static inline void superio_exit(int base)
{
outb(SIO_LOCK_KEY, base);
+ release_region(base, 2);
}
static inline int fan_from_reg(u16 reg)
@@ -2175,21 +2185,15 @@ static int f71882fg_remove(struct platform_device *pdev)
static int __init f71882fg_find(int sioaddr, unsigned short *address,
struct f71882fg_sio_data *sio_data)
{
- int err = -ENODEV;
u16 devid;
-
- /* Don't step on other drivers' I/O space by accident */
- if (!request_region(sioaddr, 2, DRVNAME)) {
- printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n",
- (int)sioaddr);
- return -EBUSY;
- }
-
- superio_enter(sioaddr);
+ int err = superio_enter(sioaddr);
+ if (err)
+ return err;
devid = superio_inw(sioaddr, SIO_REG_MANID);
if (devid != SIO_FINTEK_ID) {
pr_debug(DRVNAME ": Not a Fintek device\n");
+ err = -ENODEV;
goto exit;
}
@@ -2213,6 +2217,7 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address,
default:
printk(KERN_INFO DRVNAME ": Unsupported Fintek device: %04x\n",
(unsigned int)devid);
+ err = -ENODEV;
goto exit;
}
@@ -2223,12 +2228,14 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address,
if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) {
printk(KERN_WARNING DRVNAME ": Device not activated\n");
+ err = -ENODEV;
goto exit;
}
*address = superio_inw(sioaddr, SIO_REG_ADDR);
if (*address == 0) {
printk(KERN_WARNING DRVNAME ": Base address not set\n");
+ err = -ENODEV;
goto exit;
}
*address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */
@@ -2239,7 +2246,6 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address,
(int)superio_inb(sioaddr, SIO_REG_DEVREV));
exit:
superio_exit(sioaddr);
- release_region(sioaddr, 2);
return err;
}
diff --git a/drivers/hwmon/fschmd.c b/drivers/hwmon/fschmd.c
index b7ca2a9676cf..d4d4ca65d371 100644
--- a/drivers/hwmon/fschmd.c
+++ b/drivers/hwmon/fschmd.c
@@ -38,7 +38,6 @@
#include <linux/i2c.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
-#include <linux/smp_lock.h>
#include <linux/err.h>
#include <linux/mutex.h>
#include <linux/sysfs.h>
@@ -50,6 +49,7 @@
#include <linux/kref.h>
/* Addresses to scan */
+static DEFINE_MUTEX(watchdog_mutex);
static const unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END };
/* Insmod parameters */
@@ -858,7 +858,7 @@ static long watchdog_ioctl(struct file *filp, unsigned int cmd, unsigned long ar
int i, ret = 0;
struct fschmd_data *data = filp->private_data;
- lock_kernel();
+ mutex_lock(&watchdog_mutex);
switch (cmd) {
case WDIOC_GETSUPPORT:
ident.firmware_version = data->revision;
@@ -915,7 +915,7 @@ static long watchdog_ioctl(struct file *filp, unsigned int cmd, unsigned long ar
default:
ret = -ENOTTY;
}
- unlock_kernel();
+ mutex_unlock(&watchdog_mutex);
return ret;
}
diff --git a/drivers/hwmon/w83793.c b/drivers/hwmon/w83793.c
index 697202e27891..8e540ada47d2 100644
--- a/drivers/hwmon/w83793.c
+++ b/drivers/hwmon/w83793.c
@@ -35,7 +35,6 @@
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/hwmon.h>
-#include <linux/smp_lock.h>
#include <linux/hwmon-vid.h>
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
@@ -52,6 +51,7 @@
#define WATCHDOG_TIMEOUT 2 /* 2 minute default timeout */
/* Addresses to scan */
+static DEFINE_MUTEX(watchdog_mutex);
static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f,
I2C_CLIENT_END };
@@ -1333,7 +1333,7 @@ static long watchdog_ioctl(struct file *filp, unsigned int cmd,
int val, ret = 0;
struct w83793_data *data = filp->private_data;
- lock_kernel();
+ mutex_lock(&watchdog_mutex);
switch (cmd) {
case WDIOC_GETSUPPORT:
if (!nowayout)
@@ -1387,7 +1387,7 @@ static long watchdog_ioctl(struct file *filp, unsigned int cmd,
default:
ret = -ENOTTY;
}
- unlock_kernel();
+ mutex_unlock(&watchdog_mutex);
return ret;
}
diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c
index f7bd2613cecc..f2de3be35df3 100644
--- a/drivers/i2c/busses/i2c-cpm.c
+++ b/drivers/i2c/busses/i2c-cpm.c
@@ -677,6 +677,11 @@ static int __devinit cpm_i2c_probe(struct platform_device *ofdev,
dev_dbg(&ofdev->dev, "hw routines for %s registered.\n",
cpm->adap.name);
+ /*
+ * register OF I2C devices
+ */
+ of_i2c_register_devices(&cpm->adap);
+
return 0;
out_shut:
cpm_i2c_shutdown(cpm);
diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
index 2222c87876b9..5795c8398c7c 100644
--- a/drivers/i2c/busses/i2c-davinci.c
+++ b/drivers/i2c/busses/i2c-davinci.c
@@ -331,21 +331,16 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
INIT_COMPLETION(dev->cmd_complete);
dev->cmd_err = 0;
- /* Take I2C out of reset, configure it as master and set the
- * start bit */
- flag = DAVINCI_I2C_MDR_IRS | DAVINCI_I2C_MDR_MST | DAVINCI_I2C_MDR_STT;
+ /* Take I2C out of reset and configure it as master */
+ flag = DAVINCI_I2C_MDR_IRS | DAVINCI_I2C_MDR_MST;
/* if the slave address is ten bit address, enable XA bit */
if (msg->flags & I2C_M_TEN)
flag |= DAVINCI_I2C_MDR_XA;
if (!(msg->flags & I2C_M_RD))
flag |= DAVINCI_I2C_MDR_TRX;
- if (stop)
- flag |= DAVINCI_I2C_MDR_STP;
- if (msg->len == 0) {
+ if (msg->len == 0)
flag |= DAVINCI_I2C_MDR_RM;
- flag &= ~DAVINCI_I2C_MDR_STP;
- }
/* Enable receive or transmit interrupts */
w = davinci_i2c_read_reg(dev, DAVINCI_I2C_IMR_REG);
@@ -357,7 +352,11 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
dev->terminate = 0;
- /* write the data into mode register */
+ /*
+ * Write mode register first as needed for correct behaviour
+ * on OMAP-L138, but don't set STT yet to avoid a race with XRDY
+ * occuring before we have loaded DXR
+ */
davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
/*
@@ -365,12 +364,19 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
* because transmit-data-ready interrupt can come before
* NACK-interrupt during sending of previous message and
* ICDXR may have wrong data
+ * It also saves us one interrupt, slightly faster
*/
if ((!(msg->flags & I2C_M_RD)) && dev->buf_len) {
davinci_i2c_write_reg(dev, DAVINCI_I2C_DXR_REG, *dev->buf++);
dev->buf_len--;
}
+ /* Set STT to begin transmit now DXR is loaded */
+ flag |= DAVINCI_I2C_MDR_STT;
+ if (stop && msg->len != 0)
+ flag |= DAVINCI_I2C_MDR_STP;
+ davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
+
r = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
dev->adapter.timeout);
if (r == 0) {
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
index 43ca32fddde2..89eedf45d30e 100644
--- a/drivers/i2c/busses/i2c-ibm_iic.c
+++ b/drivers/i2c/busses/i2c-ibm_iic.c
@@ -761,6 +761,9 @@ static int __devinit iic_probe(struct platform_device *ofdev,
dev_info(&ofdev->dev, "using %s mode\n",
dev->fast_mode ? "fast (400 kHz)" : "standard (100 kHz)");
+ /* Now register all the child nodes */
+ of_i2c_register_devices(adap);
+
return 0;
error_cleanup:
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index d1ff9408dc1f..4c2a62b75b5c 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -159,15 +159,9 @@ static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy)
static int i2c_imx_trx_complete(struct imx_i2c_struct *i2c_imx)
{
- int result;
-
- result = wait_event_interruptible_timeout(i2c_imx->queue,
- i2c_imx->i2csr & I2SR_IIF, HZ / 10);
+ wait_event_timeout(i2c_imx->queue, i2c_imx->i2csr & I2SR_IIF, HZ / 10);
- if (unlikely(result < 0)) {
- dev_dbg(&i2c_imx->adapter.dev, "<%s> result < 0\n", __func__);
- return result;
- } else if (unlikely(!(i2c_imx->i2csr & I2SR_IIF))) {
+ if (unlikely(!(i2c_imx->i2csr & I2SR_IIF))) {
dev_dbg(&i2c_imx->adapter.dev, "<%s> Timeout\n", __func__);
return -ETIMEDOUT;
}
@@ -295,7 +289,7 @@ static irqreturn_t i2c_imx_isr(int irq, void *dev_id)
i2c_imx->i2csr = temp;
temp &= ~I2SR_IIF;
writeb(temp, i2c_imx->base + IMX_I2C_I2SR);
- wake_up_interruptible(&i2c_imx->queue);
+ wake_up(&i2c_imx->queue);
return IRQ_HANDLED;
}
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index a1c419a716af..b74e6dc6886c 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -632,6 +632,7 @@ static int __devinit fsl_i2c_probe(struct platform_device *op,
dev_err(i2c->dev, "failed to add adapter\n");
goto fail_add;
}
+ of_i2c_register_devices(&i2c->adap);
return result;
diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c
index 0e9f85d0a835..56dbe54e8811 100644
--- a/drivers/i2c/busses/i2c-octeon.c
+++ b/drivers/i2c/busses/i2c-octeon.c
@@ -218,7 +218,7 @@ static int octeon_i2c_wait(struct octeon_i2c *i2c)
return result;
} else if (result == 0) {
dev_dbg(i2c->dev, "%s: timeout\n", __func__);
- result = -ETIMEDOUT;
+ return -ETIMEDOUT;
}
return 0;
diff --git a/drivers/i2c/busses/i2c-pasemi.c b/drivers/i2c/busses/i2c-pasemi.c
index 4174101660c9..837b8c1aa02a 100644
--- a/drivers/i2c/busses/i2c-pasemi.c
+++ b/drivers/i2c/busses/i2c-pasemi.c
@@ -88,7 +88,7 @@ static void pasemi_smb_clear(struct pasemi_smbus *smbus)
reg_write(smbus, REG_SMSTA, status);
}
-static unsigned int pasemi_smb_waitready(struct pasemi_smbus *smbus)
+static int pasemi_smb_waitready(struct pasemi_smbus *smbus)
{
int timeout = 10;
unsigned int status;
diff --git a/drivers/i2c/busses/i2c-pca-isa.c b/drivers/i2c/busses/i2c-pca-isa.c
index bbd77603a417..29933f87d8fa 100644
--- a/drivers/i2c/busses/i2c-pca-isa.c
+++ b/drivers/i2c/busses/i2c-pca-isa.c
@@ -71,8 +71,8 @@ static int pca_isa_readbyte(void *pd, int reg)
static int pca_isa_waitforcompletion(void *pd)
{
- long ret = ~0;
unsigned long timeout;
+ long ret;
if (irq > -1) {
ret = wait_event_timeout(pca_wait,
@@ -81,11 +81,15 @@ static int pca_isa_waitforcompletion(void *pd)
} else {
/* Do polling */
timeout = jiffies + pca_isa_ops.timeout;
- while (((pca_isa_readbyte(pd, I2C_PCA_CON)
- & I2C_PCA_CON_SI) == 0)
- && (ret = time_before(jiffies, timeout)))
+ do {
+ ret = time_before(jiffies, timeout);
+ if (pca_isa_readbyte(pd, I2C_PCA_CON)
+ & I2C_PCA_CON_SI)
+ break;
udelay(100);
+ } while (ret);
}
+
return ret > 0;
}
diff --git a/drivers/i2c/busses/i2c-pca-platform.c b/drivers/i2c/busses/i2c-pca-platform.c
index ef5c78487eb7..5f6d7f89e225 100644
--- a/drivers/i2c/busses/i2c-pca-platform.c
+++ b/drivers/i2c/busses/i2c-pca-platform.c
@@ -80,8 +80,8 @@ static void i2c_pca_pf_writebyte32(void *pd, int reg, int val)
static int i2c_pca_pf_waitforcompletion(void *pd)
{
struct i2c_pca_pf_data *i2c = pd;
- long ret = ~0;
unsigned long timeout;
+ long ret;
if (i2c->irq) {
ret = wait_event_timeout(i2c->wait,
@@ -90,10 +90,13 @@ static int i2c_pca_pf_waitforcompletion(void *pd)
} else {
/* Do polling */
timeout = jiffies + i2c->adap.timeout;
- while (((i2c->algo_data.read_byte(i2c, I2C_PCA_CON)
- & I2C_PCA_CON_SI) == 0)
- && (ret = time_before(jiffies, timeout)))
+ do {
+ ret = time_before(jiffies, timeout);
+ if (i2c->algo_data.read_byte(i2c, I2C_PCA_CON)
+ & I2C_PCA_CON_SI)
+ break;
udelay(100);
+ } while (ret);
}
return ret > 0;
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index 72902e0bbfa7..bf831bf81587 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -662,8 +662,8 @@ static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got)
unsigned long sda_delay;
if (pdata->sda_delay) {
- sda_delay = (freq / 1000) * pdata->sda_delay;
- sda_delay /= 1000000;
+ sda_delay = clkin * pdata->sda_delay;
+ sda_delay = DIV_ROUND_UP(sda_delay, 1000000);
sda_delay = DIV_ROUND_UP(sda_delay, 5);
if (sda_delay > 3)
sda_delay = 3;
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 6649176de940..bea4c5021d26 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -32,7 +32,6 @@
#include <linux/init.h>
#include <linux/idr.h>
#include <linux/mutex.h>
-#include <linux/of_i2c.h>
#include <linux/of_device.h>
#include <linux/completion.h>
#include <linux/hardirq.h>
@@ -197,11 +196,12 @@ static int i2c_device_pm_suspend(struct device *dev)
{
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
- if (pm_runtime_suspended(dev))
- return 0;
-
- if (pm)
- return pm->suspend ? pm->suspend(dev) : 0;
+ if (pm) {
+ if (pm_runtime_suspended(dev))
+ return 0;
+ else
+ return pm->suspend ? pm->suspend(dev) : 0;
+ }
return i2c_legacy_suspend(dev, PMSG_SUSPEND);
}
@@ -216,12 +216,6 @@ static int i2c_device_pm_resume(struct device *dev)
else
ret = i2c_legacy_resume(dev);
- if (!ret) {
- pm_runtime_disable(dev);
- pm_runtime_set_active(dev);
- pm_runtime_enable(dev);
- }
-
return ret;
}
@@ -229,11 +223,12 @@ static int i2c_device_pm_freeze(struct device *dev)
{
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
- if (pm_runtime_suspended(dev))
- return 0;
-
- if (pm)
- return pm->freeze ? pm->freeze(dev) : 0;
+ if (pm) {
+ if (pm_runtime_suspended(dev))
+ return 0;
+ else
+ return pm->freeze ? pm->freeze(dev) : 0;
+ }
return i2c_legacy_suspend(dev, PMSG_FREEZE);
}
@@ -242,11 +237,12 @@ static int i2c_device_pm_thaw(struct device *dev)
{
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
- if (pm_runtime_suspended(dev))
- return 0;
-
- if (pm)
- return pm->thaw ? pm->thaw(dev) : 0;
+ if (pm) {
+ if (pm_runtime_suspended(dev))
+ return 0;
+ else
+ return pm->thaw ? pm->thaw(dev) : 0;
+ }
return i2c_legacy_resume(dev);
}
@@ -255,11 +251,12 @@ static int i2c_device_pm_poweroff(struct device *dev)
{
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
- if (pm_runtime_suspended(dev))
- return 0;
-
- if (pm)
- return pm->poweroff ? pm->poweroff(dev) : 0;
+ if (pm) {
+ if (pm_runtime_suspended(dev))
+ return 0;
+ else
+ return pm->poweroff ? pm->poweroff(dev) : 0;
+ }
return i2c_legacy_suspend(dev, PMSG_HIBERNATE);
}
@@ -876,9 +873,6 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
if (adap->nr < __i2c_first_dynamic_bus_num)
i2c_scan_static_board_info(adap);
- /* Register devices from the device tree */
- of_i2c_register_devices(adap);
-
/* Notify drivers */
mutex_lock(&core_lock);
bus_for_each_drv(&i2c_bus_type, NULL, adap, __process_new_adapter);
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 31fc76960a8f..0c73fe39a236 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -31,7 +31,6 @@
#include <linux/delay.h>
#include <linux/timer.h>
#include <linux/seq_file.h>
-#include <linux/smp_lock.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/errno.h>
@@ -52,6 +51,7 @@
#include "ide-cd.h"
+static DEFINE_MUTEX(ide_cd_mutex);
static DEFINE_MUTEX(idecd_ref_mutex);
static void ide_cd_release(struct device *);
@@ -1602,7 +1602,7 @@ static int idecd_open(struct block_device *bdev, fmode_t mode)
struct cdrom_info *info;
int rc = -ENXIO;
- lock_kernel();
+ mutex_lock(&ide_cd_mutex);
info = ide_cd_get(bdev->bd_disk);
if (!info)
goto out;
@@ -1611,7 +1611,7 @@ static int idecd_open(struct block_device *bdev, fmode_t mode)
if (rc < 0)
ide_cd_put(info);
out:
- unlock_kernel();
+ mutex_unlock(&ide_cd_mutex);
return rc;
}
@@ -1619,11 +1619,11 @@ static int idecd_release(struct gendisk *disk, fmode_t mode)
{
struct cdrom_info *info = ide_drv_g(disk, cdrom_info);
- lock_kernel();
+ mutex_lock(&ide_cd_mutex);
cdrom_release(&info->devinfo, mode);
ide_cd_put(info);
- unlock_kernel();
+ mutex_unlock(&ide_cd_mutex);
return 0;
}
@@ -1694,9 +1694,9 @@ static int idecd_ioctl(struct block_device *bdev, fmode_t mode,
{
int ret;
- lock_kernel();
+ mutex_lock(&ide_cd_mutex);
ret = idecd_locked_ioctl(bdev, mode, cmd, arg);
- unlock_kernel();
+ mutex_unlock(&ide_cd_mutex);
return ret;
}
diff --git a/drivers/ide/ide-cs.c b/drivers/ide/ide-cs.c
index 2a4cb9c18f01..404843e8611b 100644
--- a/drivers/ide/ide-cs.c
+++ b/drivers/ide/ide-cs.c
@@ -43,7 +43,6 @@
#include <asm/io.h>
#include <asm/system.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
#include <pcmcia/cisreg.h>
@@ -72,17 +71,6 @@ static int ide_config(struct pcmcia_device *);
static void ide_detach(struct pcmcia_device *p_dev);
-
-
-
-/*======================================================================
-
- ide_attach() creates an "instance" of the driver, allocating
- local data structures for one device. The device is registered
- with Card Services.
-
-======================================================================*/
-
static int ide_probe(struct pcmcia_device *link)
{
ide_info_t *info;
@@ -97,23 +85,12 @@ static int ide_probe(struct pcmcia_device *link)
info->p_dev = link;
link->priv = info;
- link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
- link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
- link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.IntType = INT_MEMORY_AND_IO;
+ link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO |
+ CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC;
return ide_config(link);
} /* ide_attach */
-/*======================================================================
-
- This deletes a driver "instance". The device is de-registered
- with Card Services. If it has been released, all local data
- structures are freed. Otherwise, the structures will be freed
- when the device is released.
-
-======================================================================*/
-
static void ide_detach(struct pcmcia_device *link)
{
ide_info_t *info = link->priv;
@@ -187,79 +164,31 @@ out_release:
return NULL;
}
-/*======================================================================
-
- ide_config() is scheduled to run after a CARD_INSERTION event
- is received, to configure the PCMCIA socket, and to make the
- ide device available to the system.
-
-======================================================================*/
-
-struct pcmcia_config_check {
- unsigned long ctl_base;
- int skip_vcc;
- int is_kme;
-};
-
-static int pcmcia_check_one_config(struct pcmcia_device *pdev,
- cistpl_cftable_entry_t *cfg,
- cistpl_cftable_entry_t *dflt,
- unsigned int vcc,
- void *priv_data)
+static int pcmcia_check_one_config(struct pcmcia_device *pdev, void *priv_data)
{
- struct pcmcia_config_check *stk = priv_data;
-
- /* Check for matching Vcc, unless we're desperate */
- if (!stk->skip_vcc) {
- if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
- if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
- return -ENODEV;
- } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
- if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000)
- return -ENODEV;
- }
- }
+ int *is_kme = priv_data;
- if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
- pdev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
- else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
- pdev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-
- if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
- cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
- pdev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-
- pdev->conf.ConfigIndex = cfg->index;
- pdev->resource[0]->start = io->win[0].base;
- if (!(io->flags & CISTPL_IO_16BIT)) {
- pdev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
- pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
- }
- if (io->nwin == 2) {
- pdev->resource[0]->end = 8;
- pdev->resource[1]->start = io->win[1].base;
- pdev->resource[1]->end = (stk->is_kme) ? 2 : 1;
- if (pcmcia_request_io(pdev) != 0)
- return -ENODEV;
- stk->ctl_base = pdev->resource[1]->start;
- } else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
- pdev->resource[0]->end = io->win[0].len;
- pdev->resource[1]->end = 0;
- if (pcmcia_request_io(pdev) != 0)
- return -ENODEV;
- stk->ctl_base = pdev->resource[0]->start + 0x0e;
- } else
+ if (!(pdev->resource[0]->flags & IO_DATA_PATH_WIDTH_8)) {
+ pdev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+ pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
+ }
+ pdev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
+ pdev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
+
+ if (pdev->resource[1]->end) {
+ pdev->resource[0]->end = 8;
+ pdev->resource[1]->end = (*is_kme) ? 2 : 1;
+ } else {
+ if (pdev->resource[0]->end < 16)
return -ENODEV;
- /* If we've got this far, we're done */
- return 0;
}
- return -ENODEV;
+
+ return pcmcia_request_io(pdev);
}
static int ide_config(struct pcmcia_device *link)
{
ide_info_t *info = link->priv;
- struct pcmcia_config_check *stk = NULL;
int ret = 0, is_kme = 0;
unsigned long io_base, ctl_base;
struct ide_host *host;
@@ -270,23 +199,21 @@ static int ide_config(struct pcmcia_device *link)
((link->card_id == PRODID_KME_KXLC005_A) ||
(link->card_id == PRODID_KME_KXLC005_B)));
- stk = kzalloc(sizeof(*stk), GFP_KERNEL);
- if (!stk)
- goto err_mem;
- stk->is_kme = is_kme;
- stk->skip_vcc = io_base = ctl_base = 0;
-
- if (pcmcia_loop_config(link, pcmcia_check_one_config, stk)) {
- stk->skip_vcc = 1;
- if (pcmcia_loop_config(link, pcmcia_check_one_config, stk))
+ if (pcmcia_loop_config(link, pcmcia_check_one_config, &is_kme)) {
+ link->config_flags &= ~CONF_AUTO_CHECK_VCC;
+ if (pcmcia_loop_config(link, pcmcia_check_one_config, &is_kme))
goto failed; /* No suitable config found */
}
io_base = link->resource[0]->start;
- ctl_base = stk->ctl_base;
+ if (link->resource[1]->end)
+ ctl_base = link->resource[1]->start;
+ else
+ ctl_base = link->resource[0]->start + 0x0e;
if (!link->irq)
goto failed;
- ret = pcmcia_request_configuration(link, &link->conf);
+
+ ret = pcmcia_enable_device(link);
if (ret)
goto failed;
@@ -311,29 +238,15 @@ static int ide_config(struct pcmcia_device *link)
info->host = host;
dev_info(&link->dev, "ide-cs: hd%c: Vpp = %d.%d\n",
'a' + host->ports[0]->index * 2,
- link->conf.Vpp / 10, link->conf.Vpp % 10);
+ link->vpp / 10, link->vpp % 10);
- kfree(stk);
return 0;
-err_mem:
- printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n");
- goto failed;
-
failed:
- kfree(stk);
ide_release(link);
return -ENODEV;
} /* ide_config */
-/*======================================================================
-
- After a card is removed, ide_release() will unregister the net
- device, and release the PCMCIA configuration. If the device is
- still open, this will be postponed until it is closed.
-
-======================================================================*/
-
static void ide_release(struct pcmcia_device *link)
{
ide_info_t *info = link->priv;
@@ -359,15 +272,6 @@ static void ide_release(struct pcmcia_device *link)
} /* ide_release */
-/*======================================================================
-
- The card status event handler. Mostly, this schedules other
- stuff to run after an event is received. A CARD_REMOVAL event
- also sets some flags to discourage the ide drivers from
- talking to the ports.
-
-======================================================================*/
-
static struct pcmcia_device_id ide_ids[] = {
PCMCIA_DEVICE_FUNC_ID(4),
PCMCIA_DEVICE_MANF_CARD(0x0000, 0x0000), /* Corsair */
@@ -440,9 +344,7 @@ MODULE_DEVICE_TABLE(pcmcia, ide_ids);
static struct pcmcia_driver ide_cs_driver = {
.owner = THIS_MODULE,
- .drv = {
- .name = "ide-cs",
- },
+ .name = "ide-cs",
.probe = ide_probe,
.remove = ide_detach,
.id_table = ide_ids,
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 7433e07de30e..7c5b01ce51d2 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -516,10 +516,10 @@ static int ide_do_setfeature(ide_drive_t *drive, u8 feature, u8 nsect)
return ide_no_data_taskfile(drive, &cmd);
}
-static void update_ordered(ide_drive_t *drive)
+static void update_flush(ide_drive_t *drive)
{
u16 *id = drive->id;
- unsigned ordered = QUEUE_ORDERED_NONE;
+ unsigned flush = 0;
if (drive->dev_flags & IDE_DFLAG_WCACHE) {
unsigned long long capacity;
@@ -543,13 +543,12 @@ static void update_ordered(ide_drive_t *drive)
drive->name, barrier ? "" : "not ");
if (barrier) {
- ordered = QUEUE_ORDERED_DRAIN_FLUSH;
+ flush = REQ_FLUSH;
blk_queue_prep_rq(drive->queue, idedisk_prep_fn);
}
- } else
- ordered = QUEUE_ORDERED_DRAIN;
+ }
- blk_queue_ordered(drive->queue, ordered);
+ blk_queue_flush(drive->queue, flush);
}
ide_devset_get_flag(wcache, IDE_DFLAG_WCACHE);
@@ -572,7 +571,7 @@ static int set_wcache(ide_drive_t *drive, int arg)
}
}
- update_ordered(drive);
+ update_flush(drive);
return err;
}
diff --git a/drivers/ide/ide-disk_ioctl.c b/drivers/ide/ide-disk_ioctl.c
index ec94c66918f6..da36f729ff32 100644
--- a/drivers/ide/ide-disk_ioctl.c
+++ b/drivers/ide/ide-disk_ioctl.c
@@ -1,10 +1,11 @@
#include <linux/kernel.h>
#include <linux/ide.h>
#include <linux/hdreg.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include "ide-disk.h"
+static DEFINE_MUTEX(ide_disk_ioctl_mutex);
static const struct ide_ioctl_devset ide_disk_ioctl_settings[] = {
{ HDIO_GET_ADDRESS, HDIO_SET_ADDRESS, &ide_devset_address },
{ HDIO_GET_MULTCOUNT, HDIO_SET_MULTCOUNT, &ide_devset_multcount },
@@ -19,13 +20,13 @@ int ide_disk_ioctl(ide_drive_t *drive, struct block_device *bdev, fmode_t mode,
{
int err;
- lock_kernel();
+ mutex_lock(&ide_disk_ioctl_mutex);
err = ide_setting_ioctl(drive, bdev, cmd, arg, ide_disk_ioctl_settings);
if (err != -EOPNOTSUPP)
goto out;
err = generic_ide_ioctl(drive, bdev, cmd, arg);
out:
- unlock_kernel();
+ mutex_unlock(&ide_disk_ioctl_mutex);
return err;
}
diff --git a/drivers/ide/ide-floppy_ioctl.c b/drivers/ide/ide-floppy_ioctl.c
index fd3d05ab3417..d267b7affad6 100644
--- a/drivers/ide/ide-floppy_ioctl.c
+++ b/drivers/ide/ide-floppy_ioctl.c
@@ -5,7 +5,7 @@
#include <linux/kernel.h>
#include <linux/ide.h>
#include <linux/cdrom.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <asm/unaligned.h>
@@ -32,6 +32,7 @@
* On exit we set nformats to the number of records we've actually initialized.
*/
+static DEFINE_MUTEX(ide_floppy_ioctl_mutex);
static int ide_floppy_get_format_capacities(ide_drive_t *drive,
struct ide_atapi_pc *pc,
int __user *arg)
@@ -276,7 +277,7 @@ int ide_floppy_ioctl(ide_drive_t *drive, struct block_device *bdev,
void __user *argp = (void __user *)arg;
int err;
- lock_kernel();
+ mutex_lock(&ide_floppy_ioctl_mutex);
if (cmd == CDROMEJECT || cmd == CDROM_LOCKDOOR) {
err = ide_floppy_lockdoor(drive, &pc, arg, cmd);
goto out;
@@ -298,6 +299,6 @@ int ide_floppy_ioctl(ide_drive_t *drive, struct block_device *bdev,
err = generic_ide_ioctl(drive, bdev, cmd, arg);
out:
- unlock_kernel();
+ mutex_unlock(&ide_floppy_ioctl_mutex);
return err;
}
diff --git a/drivers/ide/ide-gd.c b/drivers/ide/ide-gd.c
index 70aeeb18833e..35c4b43585e3 100644
--- a/drivers/ide/ide-gd.c
+++ b/drivers/ide/ide-gd.c
@@ -1,4 +1,3 @@
-#include <linux/smp_lock.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/string.h>
@@ -23,6 +22,7 @@
#define IDE_GD_VERSION "1.18"
/* module parameters */
+static DEFINE_MUTEX(ide_gd_mutex);
static unsigned long debug_mask;
module_param(debug_mask, ulong, 0644);
@@ -242,9 +242,9 @@ static int ide_gd_unlocked_open(struct block_device *bdev, fmode_t mode)
{
int ret;
- lock_kernel();
+ mutex_lock(&ide_gd_mutex);
ret = ide_gd_open(bdev, mode);
- unlock_kernel();
+ mutex_unlock(&ide_gd_mutex);
return ret;
}
@@ -257,7 +257,7 @@ static int ide_gd_release(struct gendisk *disk, fmode_t mode)
ide_debug_log(IDE_DBG_FUNC, "enter");
- lock_kernel();
+ mutex_lock(&ide_gd_mutex);
if (idkp->openers == 1)
drive->disk_ops->flush(drive);
@@ -269,7 +269,7 @@ static int ide_gd_release(struct gendisk *disk, fmode_t mode)
idkp->openers--;
ide_disk_put(idkp);
- unlock_kernel();
+ mutex_unlock(&ide_gd_mutex);
return 0;
}
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index a381be814070..999dac054bcc 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -441,19 +441,6 @@ void do_ide_request(struct request_queue *q)
struct request *rq = NULL;
ide_startstop_t startstop;
- /*
- * drive is doing pre-flush, ordered write, post-flush sequence. even
- * though that is 3 requests, it must be seen as a single transaction.
- * we must not preempt this drive until that is complete
- */
- if (blk_queue_flushing(q))
- /*
- * small race where queue could get replugged during
- * the 3-request flush cycle, just yank the plug since
- * we want it to finish asap
- */
- blk_remove_plug(q);
-
spin_unlock_irq(q->queue_lock);
/* HLD do_request() callback might sleep, make sure it's okay */
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index 6d622cb5ac81..7ecb1ade8874 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -32,11 +32,9 @@
#include <linux/errno.h>
#include <linux/genhd.h>
#include <linux/seq_file.h>
-#include <linux/smp_lock.h>
#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/ide.h>
-#include <linux/smp_lock.h>
#include <linux/completion.h>
#include <linux/bitops.h>
#include <linux/mutex.h>
@@ -220,6 +218,7 @@ typedef struct ide_tape_obj {
char write_prot;
} idetape_tape_t;
+static DEFINE_MUTEX(ide_tape_mutex);
static DEFINE_MUTEX(idetape_ref_mutex);
static DEFINE_MUTEX(idetape_chrdev_mutex);
@@ -1426,9 +1425,9 @@ static long idetape_chrdev_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
long ret;
- lock_kernel();
+ mutex_lock(&ide_tape_mutex);
ret = do_idetape_chrdev_ioctl(file, cmd, arg);
- unlock_kernel();
+ mutex_unlock(&ide_tape_mutex);
return ret;
}
@@ -1903,15 +1902,16 @@ static const struct file_operations idetape_fops = {
.unlocked_ioctl = idetape_chrdev_ioctl,
.open = idetape_chrdev_open,
.release = idetape_chrdev_release,
+ .llseek = noop_llseek,
};
static int idetape_open(struct block_device *bdev, fmode_t mode)
{
struct ide_tape_obj *tape;
- lock_kernel();
+ mutex_lock(&ide_tape_mutex);
tape = ide_tape_get(bdev->bd_disk, false, 0);
- unlock_kernel();
+ mutex_unlock(&ide_tape_mutex);
if (!tape)
return -ENXIO;
@@ -1923,9 +1923,9 @@ static int idetape_release(struct gendisk *disk, fmode_t mode)
{
struct ide_tape_obj *tape = ide_drv_g(disk, ide_tape_obj);
- lock_kernel();
+ mutex_lock(&ide_tape_mutex);
ide_tape_put(tape);
- unlock_kernel();
+ mutex_unlock(&ide_tape_mutex);
return 0;
}
@@ -1937,11 +1937,11 @@ static int idetape_ioctl(struct block_device *bdev, fmode_t mode,
ide_drive_t *drive = tape->drive;
int err;
- lock_kernel();
+ mutex_lock(&ide_tape_mutex);
err = generic_ide_ioctl(drive, bdev, cmd, arg);
if (err == -EINVAL)
err = idetape_blkdev_ioctl(drive, cmd, arg);
- unlock_kernel();
+ mutex_unlock(&ide_tape_mutex);
return err;
}
diff --git a/drivers/idle/i7300_idle.c b/drivers/idle/i7300_idle.c
index 15341fc1c68b..c976285d313e 100644
--- a/drivers/idle/i7300_idle.c
+++ b/drivers/idle/i7300_idle.c
@@ -536,6 +536,7 @@ static ssize_t stats_read_ul(struct file *fp, char __user *ubuf, size_t count,
static const struct file_operations idle_fops = {
.open = stats_open_generic,
.read = stats_read_ul,
+ .llseek = default_llseek,
};
struct debugfs_file_info {
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index a10152bb1427..cb3ccf3ed221 100755..100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -59,18 +59,11 @@
#include <linux/hrtimer.h> /* ktime_get_real() */
#include <trace/events/power.h>
#include <linux/sched.h>
+#include <asm/mwait.h>
#define INTEL_IDLE_VERSION "0.4"
#define PREFIX "intel_idle: "
-#define MWAIT_SUBSTATE_MASK (0xf)
-#define MWAIT_CSTATE_MASK (0xf)
-#define MWAIT_SUBSTATE_SIZE (4)
-#define MWAIT_MAX_NUM_CSTATES 8
-#define CPUID_MWAIT_LEAF (5)
-#define CPUID5_ECX_EXTENSIONS_SUPPORTED (0x1)
-#define CPUID5_ECX_INTERRUPT_BREAK (0x2)
-
static struct cpuidle_driver intel_idle_driver = {
.name = "intel_idle",
.owner = THIS_MODULE,
@@ -83,7 +76,7 @@ static unsigned int mwait_substates;
/* Reliable LAPIC Timer States, bit 1 for C1 etc. */
static unsigned int lapic_timer_reliable_states;
-static struct cpuidle_device *intel_idle_cpuidle_devices;
+static struct cpuidle_device __percpu *intel_idle_cpuidle_devices;
static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state);
static struct cpuidle_state *cpuidle_state_table;
@@ -108,7 +101,7 @@ static struct cpuidle_state nehalem_cstates[MWAIT_MAX_NUM_CSTATES] = {
.name = "NHM-C3",
.desc = "MWAIT 0x10",
.driver_data = (void *) 0x10,
- .flags = CPUIDLE_FLAG_TIME_VALID,
+ .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
.exit_latency = 20,
.power_usage = 500,
.target_residency = 80,
@@ -117,7 +110,7 @@ static struct cpuidle_state nehalem_cstates[MWAIT_MAX_NUM_CSTATES] = {
.name = "NHM-C6",
.desc = "MWAIT 0x20",
.driver_data = (void *) 0x20,
- .flags = CPUIDLE_FLAG_TIME_VALID,
+ .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
.exit_latency = 200,
.power_usage = 350,
.target_residency = 800,
@@ -149,7 +142,7 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
.name = "ATM-C4",
.desc = "MWAIT 0x30",
.driver_data = (void *) 0x30,
- .flags = CPUIDLE_FLAG_TIME_VALID,
+ .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
.exit_latency = 100,
.power_usage = 250,
.target_residency = 400,
@@ -157,13 +150,13 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
{ /* MWAIT C5 */ },
{ /* MWAIT C6 */
.name = "ATM-C6",
- .desc = "MWAIT 0x40",
- .driver_data = (void *) 0x40,
- .flags = CPUIDLE_FLAG_TIME_VALID,
- .exit_latency = 200,
+ .desc = "MWAIT 0x52",
+ .driver_data = (void *) 0x52,
+ .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
+ .exit_latency = 140,
.power_usage = 150,
- .target_residency = 800,
- .enter = NULL }, /* disabled */
+ .target_residency = 560,
+ .enter = &intel_idle },
};
/**
@@ -185,6 +178,16 @@ static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state)
local_irq_disable();
+ /*
+ * If the state flag indicates that the TLB will be flushed or if this
+ * is the deepest c-state supported, do a voluntary leave mm to avoid
+ * costly and mostly unnecessary wakeups for flushing the user TLB's
+ * associated with the active mm.
+ */
+ if (state->flags & CPUIDLE_FLAG_TLB_FLUSHED ||
+ (&dev->states[dev->state_count - 1] == state))
+ leave_mm(cpu);
+
if (!(lapic_timer_reliable_states & (1 << (cstate))))
clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c
index bc289e367e30..63403822330e 100644
--- a/drivers/ieee1394/eth1394.c
+++ b/drivers/ieee1394/eth1394.c
@@ -58,7 +58,6 @@
#include <linux/tcp.h>
#include <linux/skbuff.h>
#include <linux/bitops.h>
-#include <linux/ethtool.h>
#include <asm/uaccess.h>
#include <asm/delay.h>
#include <asm/unaligned.h>
@@ -173,8 +172,6 @@ static netdev_tx_t ether1394_tx(struct sk_buff *skb,
struct net_device *dev);
static void ether1394_iso(struct hpsb_iso *iso);
-static const struct ethtool_ops ethtool_ops;
-
static int ether1394_write(struct hpsb_host *host, int srcid, int destid,
quadlet_t *data, u64 addr, size_t len, u16 flags);
static void ether1394_add_host(struct hpsb_host *host);
@@ -525,8 +522,6 @@ static void ether1394_init_dev(struct net_device *dev)
dev->header_ops = &ether1394_header_ops;
dev->netdev_ops = &ether1394_netdev_ops;
- SET_ETHTOOL_OPS(dev, &ethtool_ops);
-
dev->watchdog_timeo = ETHER1394_TIMEOUT;
dev->flags = IFF_BROADCAST | IFF_MULTICAST;
dev->features = NETIF_F_HIGHDMA;
@@ -1695,17 +1690,6 @@ fail:
return NETDEV_TX_OK;
}
-static void ether1394_get_drvinfo(struct net_device *dev,
- struct ethtool_drvinfo *info)
-{
- strcpy(info->driver, driver_name);
- strcpy(info->bus_info, "ieee1394"); /* FIXME provide more detail? */
-}
-
-static const struct ethtool_ops ethtool_ops = {
- .get_drvinfo = ether1394_get_drvinfo
-};
-
static int __init ether1394_init_module(void)
{
int err;
diff --git a/drivers/infiniband/hw/ipath/ipath_diag.c b/drivers/infiniband/hw/ipath/ipath_diag.c
index d4ce8b63e19e..daef61d5e5bb 100644
--- a/drivers/infiniband/hw/ipath/ipath_diag.c
+++ b/drivers/infiniband/hw/ipath/ipath_diag.c
@@ -65,7 +65,8 @@ static const struct file_operations diag_file_ops = {
.write = ipath_diag_write,
.read = ipath_diag_read,
.open = ipath_diag_open,
- .release = ipath_diag_release
+ .release = ipath_diag_release,
+ .llseek = default_llseek,
};
static ssize_t ipath_diagpkt_write(struct file *fp,
@@ -75,6 +76,7 @@ static ssize_t ipath_diagpkt_write(struct file *fp,
static const struct file_operations diagpkt_file_ops = {
.owner = THIS_MODULE,
.write = ipath_diagpkt_write,
+ .llseek = noop_llseek,
};
static atomic_t diagpkt_count = ATOMIC_INIT(0);
diff --git a/drivers/infiniband/hw/ipath/ipath_file_ops.c b/drivers/infiniband/hw/ipath/ipath_file_ops.c
index 65eb8929db22..6078992da3f0 100644
--- a/drivers/infiniband/hw/ipath/ipath_file_ops.c
+++ b/drivers/infiniband/hw/ipath/ipath_file_ops.c
@@ -63,7 +63,8 @@ static const struct file_operations ipath_file_ops = {
.open = ipath_open,
.release = ipath_close,
.poll = ipath_poll,
- .mmap = ipath_mmap
+ .mmap = ipath_mmap,
+ .llseek = noop_llseek,
};
/*
diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c
index 2fca70836dae..d13e72685dcf 100644
--- a/drivers/infiniband/hw/ipath/ipath_fs.c
+++ b/drivers/infiniband/hw/ipath/ipath_fs.c
@@ -103,6 +103,7 @@ static ssize_t atomic_stats_read(struct file *file, char __user *buf,
static const struct file_operations atomic_stats_ops = {
.read = atomic_stats_read,
+ .llseek = default_llseek,
};
static ssize_t atomic_counters_read(struct file *file, char __user *buf,
@@ -120,6 +121,7 @@ static ssize_t atomic_counters_read(struct file *file, char __user *buf,
static const struct file_operations atomic_counters_ops = {
.read = atomic_counters_read,
+ .llseek = default_llseek,
};
static ssize_t flash_read(struct file *file, char __user *buf,
@@ -224,6 +226,7 @@ bail:
static const struct file_operations flash_ops = {
.read = flash_read,
.write = flash_write,
+ .llseek = default_llseek,
};
static int create_device_files(struct super_block *sb,
diff --git a/drivers/infiniband/hw/mlx4/Kconfig b/drivers/infiniband/hw/mlx4/Kconfig
index 4175a4bd0c78..bd995b2b50d8 100644
--- a/drivers/infiniband/hw/mlx4/Kconfig
+++ b/drivers/infiniband/hw/mlx4/Kconfig
@@ -1,5 +1,6 @@
config MLX4_INFINIBAND
tristate "Mellanox ConnectX HCA support"
+ depends on NETDEVICES && NETDEV_10000 && PCI
select MLX4_CORE
---help---
This driver provides low-level InfiniBand support for
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c
index 61e0efd4ccfb..6220d9d75b58 100644
--- a/drivers/infiniband/hw/nes/nes_cm.c
+++ b/drivers/infiniband/hw/nes/nes_cm.c
@@ -2701,7 +2701,7 @@ static int nes_disconnect(struct nes_qp *nesqp, int abrupt)
nesibdev = nesvnic->nesibdev;
nes_debug(NES_DBG_CM, "netdev refcnt = %u.\n",
- atomic_read(&nesvnic->netdev->refcnt));
+ netdev_refcnt_read(nesvnic->netdev));
if (nesqp->active_conn) {
@@ -2791,7 +2791,7 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
atomic_inc(&cm_accepts);
nes_debug(NES_DBG_CM, "netdev refcnt = %u.\n",
- atomic_read(&nesvnic->netdev->refcnt));
+ netdev_refcnt_read(nesvnic->netdev));
/* allocate the ietf frame and space for private data */
nesqp->ietf_frame = pci_alloc_consistent(nesdev->pcidev,
diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c
index 9046e6675686..546fc22405fe 100644
--- a/drivers/infiniband/hw/nes/nes_verbs.c
+++ b/drivers/infiniband/hw/nes/nes_verbs.c
@@ -785,7 +785,7 @@ static struct ib_pd *nes_alloc_pd(struct ib_device *ibdev,
nes_debug(NES_DBG_PD, "nesvnic=%p, netdev=%p %s, ibdev=%p, context=%p, netdev refcnt=%u\n",
nesvnic, nesdev->netdev[0], nesdev->netdev[0]->name, ibdev, context,
- atomic_read(&nesvnic->netdev->refcnt));
+ netdev_refcnt_read(nesvnic->netdev));
err = nes_alloc_resource(nesadapter, nesadapter->allocated_pds,
nesadapter->max_pd, &pd_num, &nesadapter->next_pd);
@@ -1416,7 +1416,7 @@ static struct ib_qp *nes_create_qp(struct ib_pd *ibpd,
/* update the QP table */
nesdev->nesadapter->qp_table[nesqp->hwqp.qp_id-NES_FIRST_QPN] = nesqp;
nes_debug(NES_DBG_QP, "netdev refcnt=%u\n",
- atomic_read(&nesvnic->netdev->refcnt));
+ netdev_refcnt_read(nesvnic->netdev));
return &nesqp->ibqp;
}
diff --git a/drivers/infiniband/hw/qib/qib_diag.c b/drivers/infiniband/hw/qib/qib_diag.c
index 05dcf0d9a7d3..204c4dd9dce0 100644
--- a/drivers/infiniband/hw/qib/qib_diag.c
+++ b/drivers/infiniband/hw/qib/qib_diag.c
@@ -136,7 +136,8 @@ static const struct file_operations diag_file_ops = {
.write = qib_diag_write,
.read = qib_diag_read,
.open = qib_diag_open,
- .release = qib_diag_release
+ .release = qib_diag_release,
+ .llseek = default_llseek,
};
static atomic_t diagpkt_count = ATOMIC_INIT(0);
@@ -149,6 +150,7 @@ static ssize_t qib_diagpkt_write(struct file *fp, const char __user *data,
static const struct file_operations diagpkt_file_ops = {
.owner = THIS_MODULE,
.write = qib_diagpkt_write,
+ .llseek = noop_llseek,
};
int qib_diag_add(struct qib_devdata *dd)
diff --git a/drivers/infiniband/hw/qib/qib_file_ops.c b/drivers/infiniband/hw/qib/qib_file_ops.c
index 6b11645edf35..aa2be214270f 100644
--- a/drivers/infiniband/hw/qib/qib_file_ops.c
+++ b/drivers/infiniband/hw/qib/qib_file_ops.c
@@ -63,7 +63,8 @@ static const struct file_operations qib_file_ops = {
.open = qib_open,
.release = qib_close,
.poll = qib_poll,
- .mmap = qib_mmapf
+ .mmap = qib_mmapf,
+ .llseek = noop_llseek,
};
/*
diff --git a/drivers/infiniband/hw/qib/qib_fs.c b/drivers/infiniband/hw/qib/qib_fs.c
index 9f989c0ba9d3..a0e6613e8be6 100644
--- a/drivers/infiniband/hw/qib/qib_fs.c
+++ b/drivers/infiniband/hw/qib/qib_fs.c
@@ -367,6 +367,7 @@ bail:
static const struct file_operations flash_ops = {
.read = flash_read,
.write = flash_write,
+ .llseek = default_llseek,
};
static int add_cntr_files(struct super_block *sb, struct qib_devdata *dd)
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index c908c5f83645..535fea4fe67f 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -28,7 +28,7 @@ struct evdev {
int minor;
struct input_handle handle;
wait_queue_head_t wait;
- struct evdev_client *grab;
+ struct evdev_client __rcu *grab;
struct list_head client_list;
spinlock_t client_lock; /* protects client_list */
struct mutex mutex;
@@ -669,6 +669,9 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) {
+ if (!dev->absinfo)
+ return -EINVAL;
+
t = _IOC_NR(cmd) & ABS_MAX;
abs = dev->absinfo[t];
@@ -680,10 +683,13 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
}
}
- if (_IOC_DIR(cmd) == _IOC_READ) {
+ if (_IOC_DIR(cmd) == _IOC_WRITE) {
if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) {
+ if (!dev->absinfo)
+ return -EINVAL;
+
t = _IOC_NR(cmd) & ABS_MAX;
if (copy_from_user(&abs, p, min_t(size_t,
@@ -761,7 +767,8 @@ static const struct file_operations evdev_fops = {
.compat_ioctl = evdev_ioctl_compat,
#endif
.fasync = evdev_fasync,
- .flush = evdev_flush
+ .flush = evdev_flush,
+ .llseek = no_llseek,
};
static int evdev_install_chrdev(struct evdev *evdev)
diff --git a/drivers/input/input.c b/drivers/input/input.c
index ab6982056518..7919c2537225 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -2047,6 +2047,7 @@ out:
static const struct file_operations input_fops = {
.owner = THIS_MODULE,
.open = input_open_file,
+ .llseek = noop_llseek,
};
static int __init input_init(void)
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index d85bd8a7967d..9d424cebfd2c 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -483,6 +483,9 @@ static int joydev_handle_JSIOCSAXMAP(struct joydev *joydev,
memcpy(joydev->abspam, abspam, len);
+ for (i = 0; i < joydev->nabs; i++)
+ joydev->absmap[joydev->abspam[i]] = i;
+
out:
kfree(abspam);
return retval;
@@ -736,6 +739,7 @@ static const struct file_operations joydev_fops = {
.compat_ioctl = joydev_compat_ioctl,
#endif
.fasync = joydev_fasync,
+ .llseek = no_llseek,
};
static int joydev_install_chrdev(struct joydev *joydev)
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index 9cc488d21490..aa037fec2f86 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -338,7 +338,7 @@ config KEYBOARD_OPENCORES
config KEYBOARD_PXA27x
tristate "PXA27x/PXA3xx keypad support"
- depends on PXA27x || PXA3xx
+ depends on PXA27x || PXA3xx || ARCH_MMP
help
Enable support for PXA27x/PXA3xx keypad controller.
diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c
index f32404f99189..4b0ec35259a1 100644
--- a/drivers/input/keyboard/pxa27x_keypad.c
+++ b/drivers/input/keyboard/pxa27x_keypad.c
@@ -32,7 +32,7 @@
#include <asm/mach/map.h>
#include <mach/hardware.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
/*
* Keypad Controller registers
*/
@@ -330,11 +330,21 @@ static void pxa27x_keypad_scan_direct(struct pxa27x_keypad *keypad)
keypad->direct_key_state = new_state;
}
+static void clear_wakeup_event(struct pxa27x_keypad *keypad)
+{
+ struct pxa27x_keypad_platform_data *pdata = keypad->pdata;
+
+ if (pdata->clear_wakeup_event)
+ (pdata->clear_wakeup_event)();
+}
+
static irqreturn_t pxa27x_keypad_irq_handler(int irq, void *dev_id)
{
struct pxa27x_keypad *keypad = dev_id;
unsigned long kpc = keypad_readl(KPC);
+ clear_wakeup_event(keypad);
+
if (kpc & KPC_DI)
pxa27x_keypad_scan_direct(keypad);
diff --git a/drivers/input/misc/hp_sdc_rtc.c b/drivers/input/misc/hp_sdc_rtc.c
index c19066479057..0b4f54265f62 100644
--- a/drivers/input/misc/hp_sdc_rtc.c
+++ b/drivers/input/misc/hp_sdc_rtc.c
@@ -43,7 +43,7 @@
#include <linux/proc_fs.h>
#include <linux/poll.h>
#include <linux/rtc.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/semaphore.h>
MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
@@ -52,6 +52,7 @@ MODULE_LICENSE("Dual BSD/GPL");
#define RTC_VERSION "1.10d"
+static DEFINE_MUTEX(hp_sdc_rtc_mutex);
static unsigned long epoch = 2000;
static struct semaphore i8042tregs;
@@ -104,7 +105,7 @@ static int hp_sdc_rtc_do_read_bbrtc (struct rtc_time *rtctm)
t.endidx = 91;
t.seq = tseq;
t.act.semaphore = &tsem;
- init_MUTEX_LOCKED(&tsem);
+ sema_init(&tsem, 0);
if (hp_sdc_enqueue_transaction(&t)) return -1;
@@ -665,9 +666,9 @@ static long hp_sdc_rtc_unlocked_ioctl(struct file *file,
{
int ret;
- lock_kernel();
+ mutex_lock(&hp_sdc_rtc_mutex);
ret = hp_sdc_rtc_ioctl(file, cmd, arg);
- unlock_kernel();
+ mutex_unlock(&hp_sdc_rtc_mutex);
return ret;
}
@@ -698,7 +699,7 @@ static int __init hp_sdc_rtc_init(void)
return -ENODEV;
#endif
- init_MUTEX(&i8042tregs);
+ sema_init(&i8042tregs, 1);
if ((ret = hp_sdc_request_timer_irq(&hp_sdc_rtc_isr)))
return ret;
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
index 0d4266a533a5..b9410784e6a1 100644
--- a/drivers/input/misc/uinput.c
+++ b/drivers/input/misc/uinput.c
@@ -404,6 +404,13 @@ static int uinput_setup_device(struct uinput_device *udev, const char __user *bu
retval = uinput_validate_absbits(dev);
if (retval < 0)
goto exit;
+ if (test_bit(ABS_MT_SLOT, dev->absbit)) {
+ int nslot = input_abs_get_max(dev, ABS_MT_SLOT) + 1;
+ input_mt_create_slots(dev, nslot);
+ input_set_events_per_packet(dev, 6 * nslot);
+ } else if (test_bit(ABS_MT_POSITION_X, dev->absbit)) {
+ input_set_events_per_packet(dev, 60);
+ }
}
udev->state = UIST_SETUP_COMPLETE;
@@ -804,6 +811,7 @@ static const struct file_operations uinput_fops = {
#ifdef CONFIG_COMPAT
.compat_ioctl = uinput_compat_ioctl,
#endif
+ .llseek = no_llseek,
};
static struct miscdevice uinput_misc = {
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index d528a2dba064..31ec7265aac6 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -792,6 +792,7 @@ static const struct file_operations mousedev_fops = {
.open = mousedev_open,
.release = mousedev_release,
.fasync = mousedev_fasync,
+ .llseek = noop_llseek,
};
static int mousedev_install_chrdev(struct mousedev *mousedev)
diff --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c
index c92f4edfee7b..e5624d8f1709 100644
--- a/drivers/input/serio/hil_mlc.c
+++ b/drivers/input/serio/hil_mlc.c
@@ -915,15 +915,15 @@ int hil_mlc_register(hil_mlc *mlc)
mlc->ostarted = 0;
rwlock_init(&mlc->lock);
- init_MUTEX(&mlc->osem);
+ sema_init(&mlc->osem, 1);
- init_MUTEX(&mlc->isem);
+ sema_init(&mlc->isem, 1);
mlc->icount = -1;
mlc->imatch = 0;
mlc->opercnt = 0;
- init_MUTEX_LOCKED(&(mlc->csem));
+ sema_init(&(mlc->csem), 0);
hil_mlc_clear_di_scratch(mlc);
hil_mlc_clear_di_map(mlc, 0);
diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c
index bcc2d30ec245..8c0b51c31424 100644
--- a/drivers/input/serio/hp_sdc.c
+++ b/drivers/input/serio/hp_sdc.c
@@ -905,7 +905,7 @@ static int __init hp_sdc_init(void)
ts_sync[1] = 0x0f;
ts_sync[2] = ts_sync[3] = ts_sync[4] = ts_sync[5] = 0;
t_sync.act.semaphore = &s_sync;
- init_MUTEX_LOCKED(&s_sync);
+ sema_init(&s_sync, 0);
hp_sdc_enqueue_transaction(&t_sync);
down(&s_sync); /* Wait for t_sync to complete */
@@ -1039,7 +1039,7 @@ static int __init hp_sdc_register(void)
return hp_sdc.dev_err;
}
- init_MUTEX_LOCKED(&tq_init_sem);
+ sema_init(&tq_init_sem, 0);
tq_init.actidx = 0;
tq_init.idx = 1;
diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c
index 998664854440..cd82bb125915 100644
--- a/drivers/input/serio/serio_raw.c
+++ b/drivers/input/serio/serio_raw.c
@@ -243,6 +243,7 @@ static const struct file_operations serio_raw_fops = {
.write = serio_raw_write,
.poll = serio_raw_poll,
.fasync = serio_raw_fasync,
+ .llseek = noop_llseek,
};
diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c
index 6d345112bcb7..6e362de3f412 100644
--- a/drivers/input/serio/serport.c
+++ b/drivers/input/serio/serport.c
@@ -165,6 +165,7 @@ static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, u
serio->open = serport_serio_open;
serio->close = serport_serio_close;
serio->port_data = serport;
+ serio->dev.parent = tty->dev;
serio_register_port(serport->serio);
printk(KERN_INFO "serio: Serial port %s\n", tty_name(tty, name));
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index 42ba3691d908..b35876ee6908 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -103,27 +103,26 @@ static void wacom_sys_irq(struct urb *urb)
static int wacom_open(struct input_dev *dev)
{
struct wacom *wacom = input_get_drvdata(dev);
+ int retval = 0;
- mutex_lock(&wacom->lock);
-
- wacom->irq->dev = wacom->usbdev;
-
- if (usb_autopm_get_interface(wacom->intf) < 0) {
- mutex_unlock(&wacom->lock);
+ if (usb_autopm_get_interface(wacom->intf) < 0)
return -EIO;
- }
+
+ mutex_lock(&wacom->lock);
if (usb_submit_urb(wacom->irq, GFP_KERNEL)) {
- usb_autopm_put_interface(wacom->intf);
- mutex_unlock(&wacom->lock);
- return -EIO;
+ retval = -EIO;
+ goto out;
}
wacom->open = true;
wacom->intf->needs_remote_wakeup = 1;
+out:
mutex_unlock(&wacom->lock);
- return 0;
+ if (retval)
+ usb_autopm_put_interface(wacom->intf);
+ return retval;
}
static void wacom_close(struct input_dev *dev)
@@ -135,6 +134,8 @@ static void wacom_close(struct input_dev *dev)
wacom->open = false;
wacom->intf->needs_remote_wakeup = 0;
mutex_unlock(&wacom->lock);
+
+ usb_autopm_put_interface(wacom->intf);
}
static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hid_desc,
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index 6e29badb969e..47fd7a041c52 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -442,8 +442,10 @@ static void wacom_intuos_general(struct wacom_wac *wacom)
/* general pen packet */
if ((data[1] & 0xb8) == 0xa0) {
t = (data[6] << 2) | ((data[7] >> 6) & 3);
- if (features->type >= INTUOS4S && features->type <= INTUOS4L)
+ if ((features->type >= INTUOS4S && features->type <= INTUOS4L) ||
+ features->type == WACOM_21UX2) {
t = (t << 1) | (data[1] & 1);
+ }
input_report_abs(input, ABS_PRESSURE, t);
input_report_abs(input, ABS_TILT_X,
((data[7] << 1) & 0x7e) | (data[8] >> 7));
diff --git a/drivers/isdn/act2000/act2000.h b/drivers/isdn/act2000/act2000.h
index d4c50512a1ff..88c9423500d8 100644
--- a/drivers/isdn/act2000/act2000.h
+++ b/drivers/isdn/act2000/act2000.h
@@ -141,9 +141,9 @@ typedef struct irq_data_isa {
__u8 rcvhdr[8];
} irq_data_isa;
-typedef union irq_data {
+typedef union act2000_irq_data {
irq_data_isa isa;
-} irq_data;
+} act2000_irq_data;
/*
* Per card driver data
@@ -176,7 +176,7 @@ typedef struct act2000_card {
char *status_buf_read;
char *status_buf_write;
char *status_buf_end;
- irq_data idat; /* Data used for IRQ handler */
+ act2000_irq_data idat; /* Data used for IRQ handler */
isdn_if interface; /* Interface to upper layer */
char regname[35]; /* Name used for request_region */
} act2000_card;
diff --git a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c
index 2978bdaa6b88..e54e79d4e2c1 100644
--- a/drivers/isdn/capi/capidrv.c
+++ b/drivers/isdn/capi/capidrv.c
@@ -1515,8 +1515,13 @@ static int decodeFVteln(char *teln, unsigned long *bmaskp, int *activep)
while (*s) {
int digit1 = 0;
int digit2 = 0;
- if (!isdigit(*s)) return -3;
- while (isdigit(*s)) { digit1 = digit1*10 + (*s - '0'); s++; }
+ char *endp;
+
+ digit1 = simple_strtoul(s, &endp, 10);
+ if (s == endp)
+ return -3;
+ s = endp;
+
if (digit1 <= 0 || digit1 > 30) return -4;
if (*s == 0 || *s == ',' || *s == ' ') {
bmask |= (1 << digit1);
@@ -1526,8 +1531,12 @@ static int decodeFVteln(char *teln, unsigned long *bmaskp, int *activep)
}
if (*s != '-') return -5;
s++;
- if (!isdigit(*s)) return -3;
- while (isdigit(*s)) { digit2 = digit2*10 + (*s - '0'); s++; }
+
+ digit2 = simple_strtoul(s, &endp, 10);
+ if (s == endp)
+ return -3;
+ s = endp;
+
if (digit2 <= 0 || digit2 > 30) return -4;
if (*s == 0 || *s == ',' || *s == ' ') {
if (digit1 > digit2)
diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c
index b054494df846..3acf94cc5acd 100644
--- a/drivers/isdn/capi/kcapi.c
+++ b/drivers/isdn/capi/kcapi.c
@@ -98,6 +98,16 @@ static inline struct capi_ctr *get_capi_ctr_by_nr(u16 contr)
return capi_controller[contr - 1];
}
+static inline struct capi20_appl *__get_capi_appl_by_nr(u16 applid)
+{
+ lockdep_assert_held(&capi_controller_lock);
+
+ if (applid - 1 >= CAPI_MAXAPPL)
+ return NULL;
+
+ return capi_applications[applid - 1];
+}
+
static inline struct capi20_appl *get_capi_appl_by_nr(u16 applid)
{
if (applid - 1 >= CAPI_MAXAPPL)
@@ -185,10 +195,9 @@ static void notify_up(u32 contr)
ctr->state = CAPI_CTR_RUNNING;
for (applid = 1; applid <= CAPI_MAXAPPL; applid++) {
- ap = get_capi_appl_by_nr(applid);
- if (!ap)
- continue;
- register_appl(ctr, applid, &ap->rparam);
+ ap = __get_capi_appl_by_nr(applid);
+ if (ap)
+ register_appl(ctr, applid, &ap->rparam);
}
wake_up_interruptible_all(&ctr->state_wait_queue);
@@ -215,7 +224,7 @@ static void ctr_down(struct capi_ctr *ctr, int new_state)
memset(ctr->serial, 0, sizeof(ctr->serial));
for (applid = 1; applid <= CAPI_MAXAPPL; applid++) {
- ap = get_capi_appl_by_nr(applid);
+ ap = __get_capi_appl_by_nr(applid);
if (ap)
capi_ctr_put(ctr);
}
diff --git a/drivers/isdn/divert/isdn_divert.c b/drivers/isdn/divert/isdn_divert.c
index 70cf6bac7a5a..48e6d220f62c 100644
--- a/drivers/isdn/divert/isdn_divert.c
+++ b/drivers/isdn/divert/isdn_divert.c
@@ -77,7 +77,7 @@ static void deflect_timer_expire(ulong arg)
case DEFLECT_ALERT:
cs->ics.command = ISDN_CMD_REDIR; /* protocol */
- strcpy(cs->ics.parm.setup.phone,cs->deflect_dest);
+ strlcpy(cs->ics.parm.setup.phone, cs->deflect_dest, sizeof(cs->ics.parm.setup.phone));
strcpy(cs->ics.parm.setup.eazmsn,"Testtext delayed");
divert_if.ll_cmd(&cs->ics);
spin_lock_irqsave(&divert_lock, flags);
@@ -251,7 +251,7 @@ int deflect_extern_action(u_char cmd, ulong callid, char *to_nr)
case 2: /* redir */
del_timer(&cs->timer);
- strcpy(cs->ics.parm.setup.phone, to_nr);
+ strlcpy(cs->ics.parm.setup.phone, to_nr, sizeof(cs->ics.parm.setup.phone));
strcpy(cs->ics.parm.setup.eazmsn, "Testtext manual");
ic.command = ISDN_CMD_REDIR;
if ((i = divert_if.ll_cmd(&ic)))
@@ -480,7 +480,7 @@ static int isdn_divert_icall(isdn_ctrl *ic)
if (!cs->timer.expires)
{ strcpy(ic->parm.setup.eazmsn,"Testtext direct");
ic->parm.setup.screen = dv->rule.screen;
- strcpy(ic->parm.setup.phone,dv->rule.to_nr);
+ strlcpy(ic->parm.setup.phone, dv->rule.to_nr, sizeof(ic->parm.setup.phone));
cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
retval = 5;
diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c
index 707d9c94cf9e..178942a2ee61 100644
--- a/drivers/isdn/gigaset/bas-gigaset.c
+++ b/drivers/isdn/gigaset/bas-gigaset.c
@@ -109,6 +109,9 @@ struct bas_cardstate {
struct urb *urb_int_in; /* URB for interrupt pipe */
unsigned char *int_in_buf;
+ struct work_struct int_in_wq; /* for usb_clear_halt() */
+ struct timer_list timer_int_in; /* int read retry delay */
+ int retry_int_in;
spinlock_t lock; /* locks all following */
int basstate; /* bitmap (BS_*) */
@@ -169,7 +172,7 @@ static char *get_usb_rcmsg(int rc)
case -EAGAIN:
return "start frame too early or too much scheduled";
case -EFBIG:
- return "too many isochronous frames requested";
+ return "too many isoc frames requested";
case -EPIPE:
return "endpoint stalled";
case -EMSGSIZE:
@@ -200,13 +203,13 @@ static char *get_usb_statmsg(int status)
case -ENOENT:
return "unlinked (sync)";
case -EINPROGRESS:
- return "pending";
+ return "URB still pending";
case -EPROTO:
- return "bit stuffing error, timeout, or unknown USB error";
+ return "bitstuff error, timeout, or unknown USB error";
case -EILSEQ:
return "CRC mismatch, timeout, or unknown USB error";
case -ETIME:
- return "timed out";
+ return "USB response timeout";
case -EPIPE:
return "endpoint stalled";
case -ECOMM:
@@ -214,15 +217,15 @@ static char *get_usb_statmsg(int status)
case -ENOSR:
return "OUT buffer underrun";
case -EOVERFLOW:
- return "too much data";
+ return "endpoint babble";
case -EREMOTEIO:
- return "short packet detected";
+ return "short packet";
case -ENODEV:
return "device removed";
case -EXDEV:
- return "partial isochronous transfer";
+ return "partial isoc transfer";
case -EINVAL:
- return "invalid argument";
+ return "ISO madness";
case -ECONNRESET:
return "unlinked (async)";
case -ESHUTDOWN:
@@ -350,7 +353,7 @@ static inline void error_hangup(struct bc_state *bcs)
* reset Gigaset device because of an unrecoverable error
* This function may be called from any context, and takes care of
* scheduling the necessary actions for execution outside of interrupt context.
- * cs->lock must not be held.
+ * cs->hw.bas->lock must not be held.
* argument:
* controller state structure
*/
@@ -358,7 +361,9 @@ static inline void error_reset(struct cardstate *cs)
{
/* reset interrupt pipe to recover (ignore errors) */
update_basstate(cs->hw.bas, BS_RESETTING, 0);
- req_submit(cs->bcs, HD_RESET_INTERRUPT_PIPE, 0, BAS_TIMEOUT);
+ if (req_submit(cs->bcs, HD_RESET_INTERRUPT_PIPE, 0, BAS_TIMEOUT))
+ /* submission failed, escalate to USB port reset */
+ usb_queue_reset_device(cs->hw.bas->interface);
}
/* check_pending
@@ -438,23 +443,27 @@ static void cmd_in_timeout(unsigned long data)
return;
}
- if (ucs->retry_cmd_in++ < BAS_RETRY) {
- dev_notice(cs->dev, "control read: timeout, retry %d\n",
- ucs->retry_cmd_in);
- rc = atread_submit(cs, BAS_TIMEOUT);
- if (rc >= 0 || rc == -ENODEV)
- /* resubmitted or disconnected */
- /* - bypass regular exit block */
- return;
- } else {
+ if (ucs->retry_cmd_in++ >= BAS_RETRY) {
dev_err(cs->dev,
"control read: timeout, giving up after %d tries\n",
ucs->retry_cmd_in);
+ kfree(ucs->rcvbuf);
+ ucs->rcvbuf = NULL;
+ ucs->rcvbuf_size = 0;
+ error_reset(cs);
+ return;
+ }
+
+ gig_dbg(DEBUG_USBREQ, "%s: timeout, retry %d",
+ __func__, ucs->retry_cmd_in);
+ rc = atread_submit(cs, BAS_TIMEOUT);
+ if (rc < 0) {
+ kfree(ucs->rcvbuf);
+ ucs->rcvbuf = NULL;
+ ucs->rcvbuf_size = 0;
+ if (rc != -ENODEV)
+ error_reset(cs);
}
- kfree(ucs->rcvbuf);
- ucs->rcvbuf = NULL;
- ucs->rcvbuf_size = 0;
- error_reset(cs);
}
/* read_ctrl_callback
@@ -470,18 +479,11 @@ static void read_ctrl_callback(struct urb *urb)
struct cardstate *cs = inbuf->cs;
struct bas_cardstate *ucs = cs->hw.bas;
int status = urb->status;
- int have_data = 0;
unsigned numbytes;
int rc;
update_basstate(ucs, 0, BS_ATRDPEND);
wake_up(&ucs->waitqueue);
-
- if (!ucs->rcvbuf_size) {
- dev_warn(cs->dev, "%s: no receive in progress\n", __func__);
- return;
- }
-
del_timer(&ucs->timer_cmd_in);
switch (status) {
@@ -495,19 +497,10 @@ static void read_ctrl_callback(struct urb *urb)
numbytes = ucs->rcvbuf_size;
}
- /* copy received bytes to inbuf */
- have_data = gigaset_fill_inbuf(inbuf, ucs->rcvbuf, numbytes);
-
- if (unlikely(numbytes < ucs->rcvbuf_size)) {
- /* incomplete - resubmit for remaining bytes */
- ucs->rcvbuf_size -= numbytes;
- ucs->retry_cmd_in = 0;
- rc = atread_submit(cs, BAS_TIMEOUT);
- if (rc >= 0 || rc == -ENODEV)
- /* resubmitted or disconnected */
- /* - bypass regular exit block */
- return;
- error_reset(cs);
+ /* copy received bytes to inbuf, notify event layer */
+ if (gigaset_fill_inbuf(inbuf, ucs->rcvbuf, numbytes)) {
+ gig_dbg(DEBUG_INTR, "%s-->BH", __func__);
+ gigaset_schedule_event(cs);
}
break;
@@ -516,37 +509,32 @@ static void read_ctrl_callback(struct urb *urb)
case -EINPROGRESS: /* pending */
case -ENODEV: /* device removed */
case -ESHUTDOWN: /* device shut down */
- /* no action necessary */
+ /* no further action necessary */
gig_dbg(DEBUG_USBREQ, "%s: %s",
__func__, get_usb_statmsg(status));
break;
- default: /* severe trouble */
- dev_warn(cs->dev, "control read: %s\n",
- get_usb_statmsg(status));
+ default: /* other errors: retry */
if (ucs->retry_cmd_in++ < BAS_RETRY) {
- dev_notice(cs->dev, "control read: retry %d\n",
- ucs->retry_cmd_in);
+ gig_dbg(DEBUG_USBREQ, "%s: %s, retry %d", __func__,
+ get_usb_statmsg(status), ucs->retry_cmd_in);
rc = atread_submit(cs, BAS_TIMEOUT);
- if (rc >= 0 || rc == -ENODEV)
- /* resubmitted or disconnected */
- /* - bypass regular exit block */
+ if (rc >= 0)
+ /* successfully resubmitted, skip freeing */
return;
- } else {
- dev_err(cs->dev,
- "control read: giving up after %d tries\n",
- ucs->retry_cmd_in);
+ if (rc == -ENODEV)
+ /* disconnect, no further action necessary */
+ break;
}
+ dev_err(cs->dev, "control read: %s, giving up after %d tries\n",
+ get_usb_statmsg(status), ucs->retry_cmd_in);
error_reset(cs);
}
+ /* read finished, free buffer */
kfree(ucs->rcvbuf);
ucs->rcvbuf = NULL;
ucs->rcvbuf_size = 0;
- if (have_data) {
- gig_dbg(DEBUG_INTR, "%s-->BH", __func__);
- gigaset_schedule_event(cs);
- }
}
/* atread_submit
@@ -605,14 +593,67 @@ static int atread_submit(struct cardstate *cs, int timeout)
if (timeout > 0) {
gig_dbg(DEBUG_USBREQ, "setting timeout of %d/10 secs", timeout);
- ucs->timer_cmd_in.expires = jiffies + timeout * HZ / 10;
- ucs->timer_cmd_in.data = (unsigned long) cs;
- ucs->timer_cmd_in.function = cmd_in_timeout;
- add_timer(&ucs->timer_cmd_in);
+ mod_timer(&ucs->timer_cmd_in, jiffies + timeout * HZ / 10);
}
return 0;
}
+/* int_in_work
+ * workqueue routine to clear halt on interrupt in endpoint
+ */
+
+static void int_in_work(struct work_struct *work)
+{
+ struct bas_cardstate *ucs =
+ container_of(work, struct bas_cardstate, int_in_wq);
+ struct urb *urb = ucs->urb_int_in;
+ struct cardstate *cs = urb->context;
+ int rc;
+
+ /* clear halt condition */
+ rc = usb_clear_halt(ucs->udev, urb->pipe);
+ gig_dbg(DEBUG_USBREQ, "clear_halt: %s", get_usb_rcmsg(rc));
+ if (rc == 0)
+ /* success, resubmit interrupt read URB */
+ rc = usb_submit_urb(urb, GFP_ATOMIC);
+ if (rc != 0 && rc != -ENODEV) {
+ dev_err(cs->dev, "clear halt failed: %s\n", get_usb_rcmsg(rc));
+ rc = usb_lock_device_for_reset(ucs->udev, ucs->interface);
+ if (rc == 0) {
+ rc = usb_reset_device(ucs->udev);
+ usb_unlock_device(ucs->udev);
+ }
+ }
+ ucs->retry_int_in = 0;
+}
+
+/* int_in_resubmit
+ * timer routine for interrupt read delayed resubmit
+ * argument:
+ * controller state structure
+ */
+static void int_in_resubmit(unsigned long data)
+{
+ struct cardstate *cs = (struct cardstate *) data;
+ struct bas_cardstate *ucs = cs->hw.bas;
+ int rc;
+
+ if (ucs->retry_int_in++ >= BAS_RETRY) {
+ dev_err(cs->dev, "interrupt read: giving up after %d tries\n",
+ ucs->retry_int_in);
+ usb_queue_reset_device(ucs->interface);
+ return;
+ }
+
+ gig_dbg(DEBUG_USBREQ, "%s: retry %d", __func__, ucs->retry_int_in);
+ rc = usb_submit_urb(ucs->urb_int_in, GFP_ATOMIC);
+ if (rc != 0 && rc != -ENODEV) {
+ dev_err(cs->dev, "could not resubmit interrupt URB: %s\n",
+ get_usb_rcmsg(rc));
+ usb_queue_reset_device(ucs->interface);
+ }
+}
+
/* read_int_callback
* USB completion handler for interrupt pipe input
* called by the USB subsystem in interrupt context
@@ -633,19 +674,29 @@ static void read_int_callback(struct urb *urb)
switch (status) {
case 0: /* success */
+ ucs->retry_int_in = 0;
break;
+ case -EPIPE: /* endpoint stalled */
+ schedule_work(&ucs->int_in_wq);
+ /* fall through */
case -ENOENT: /* cancelled */
case -ECONNRESET: /* cancelled (async) */
case -EINPROGRESS: /* pending */
- /* ignore silently */
+ case -ENODEV: /* device removed */
+ case -ESHUTDOWN: /* device shut down */
+ /* no further action necessary */
gig_dbg(DEBUG_USBREQ, "%s: %s",
__func__, get_usb_statmsg(status));
return;
- case -ENODEV: /* device removed */
- case -ESHUTDOWN: /* device shut down */
- gig_dbg(DEBUG_USBREQ, "%s: device disconnected", __func__);
+ case -EPROTO: /* protocol error or unplug */
+ case -EILSEQ:
+ case -ETIME:
+ /* resubmit after delay */
+ gig_dbg(DEBUG_USBREQ, "%s: %s",
+ __func__, get_usb_statmsg(status));
+ mod_timer(&ucs->timer_int_in, jiffies + HZ / 10);
return;
- default: /* severe trouble */
+ default: /* other errors: just resubmit */
dev_warn(cs->dev, "interrupt read: %s\n",
get_usb_statmsg(status));
goto resubmit;
@@ -723,6 +774,13 @@ static void read_int_callback(struct urb *urb)
break;
}
spin_lock_irqsave(&cs->lock, flags);
+ if (ucs->basstate & BS_ATRDPEND) {
+ spin_unlock_irqrestore(&cs->lock, flags);
+ dev_warn(cs->dev,
+ "HD_RECEIVEATDATA_ACK(%d) during HD_READ_ATMESSAGE(%d) ignored\n",
+ l, ucs->rcvbuf_size);
+ break;
+ }
if (ucs->rcvbuf_size) {
/* throw away previous buffer - we have no queue */
dev_err(cs->dev,
@@ -735,7 +793,6 @@ static void read_int_callback(struct urb *urb)
if (ucs->rcvbuf == NULL) {
spin_unlock_irqrestore(&cs->lock, flags);
dev_err(cs->dev, "out of memory receiving AT data\n");
- error_reset(cs);
break;
}
ucs->rcvbuf_size = l;
@@ -745,13 +802,10 @@ static void read_int_callback(struct urb *urb)
kfree(ucs->rcvbuf);
ucs->rcvbuf = NULL;
ucs->rcvbuf_size = 0;
- if (rc != -ENODEV) {
- spin_unlock_irqrestore(&cs->lock, flags);
- error_reset(cs);
- break;
- }
}
spin_unlock_irqrestore(&cs->lock, flags);
+ if (rc < 0 && rc != -ENODEV)
+ error_reset(cs);
break;
case HD_RESET_INTERRUPT_PIPE_ACK:
@@ -818,6 +872,7 @@ static void read_iso_callback(struct urb *urb)
tasklet_hi_schedule(&ubc->rcvd_tasklet);
} else {
/* tasklet still busy, drop data and resubmit URB */
+ gig_dbg(DEBUG_ISO, "%s: overrun", __func__);
ubc->loststatus = status;
for (i = 0; i < BAS_NUMFRAMES; i++) {
ubc->isoinlost += urb->iso_frame_desc[i].actual_length;
@@ -833,13 +888,11 @@ static void read_iso_callback(struct urb *urb)
urb->dev = bcs->cs->hw.bas->udev;
urb->transfer_flags = URB_ISO_ASAP;
urb->number_of_packets = BAS_NUMFRAMES;
- gig_dbg(DEBUG_ISO, "%s: isoc read overrun/resubmit",
- __func__);
rc = usb_submit_urb(urb, GFP_ATOMIC);
if (unlikely(rc != 0 && rc != -ENODEV)) {
dev_err(bcs->cs->dev,
- "could not resubmit isochronous read "
- "URB: %s\n", get_usb_rcmsg(rc));
+ "could not resubmit isoc read URB: %s\n",
+ get_usb_rcmsg(rc));
dump_urb(DEBUG_ISO, "isoc read", urb);
error_hangup(bcs);
}
@@ -1081,7 +1134,7 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx)
gig_dbg(DEBUG_ISO, "%s: disconnected", __func__);
else
dev_err(ucx->bcs->cs->dev,
- "could not submit isochronous write URB: %s\n",
+ "could not submit isoc write URB: %s\n",
get_usb_rcmsg(rc));
return rc;
}
@@ -1126,7 +1179,7 @@ static void write_iso_tasklet(unsigned long data)
ubc->isooutovfl = NULL;
spin_unlock_irqrestore(&ubc->isooutlock, flags);
if (ovfl) {
- dev_err(cs->dev, "isochronous write buffer underrun\n");
+ dev_err(cs->dev, "isoc write underrun\n");
error_hangup(bcs);
break;
}
@@ -1151,7 +1204,7 @@ static void write_iso_tasklet(unsigned long data)
if (next) {
/* couldn't put it back */
dev_err(cs->dev,
- "losing isochronous write URB\n");
+ "losing isoc write URB\n");
error_hangup(bcs);
}
}
@@ -1178,10 +1231,10 @@ static void write_iso_tasklet(unsigned long data)
if (ifd->status ||
ifd->actual_length != ifd->length) {
dev_warn(cs->dev,
- "isochronous write: frame %d: %s, "
- "only %d of %d bytes sent\n",
- i, get_usb_statmsg(ifd->status),
- ifd->actual_length, ifd->length);
+ "isoc write: frame %d[%d/%d]: %s\n",
+ i, ifd->actual_length,
+ ifd->length,
+ get_usb_statmsg(ifd->status));
offset = (ifd->offset +
ifd->actual_length)
% BAS_OUTBUFSIZE;
@@ -1190,11 +1243,11 @@ static void write_iso_tasklet(unsigned long data)
}
break;
case -EPIPE: /* stall - probably underrun */
- dev_err(cs->dev, "isochronous write stalled\n");
+ dev_err(cs->dev, "isoc write: stalled\n");
error_hangup(bcs);
break;
- default: /* severe trouble */
- dev_warn(cs->dev, "isochronous write: %s\n",
+ default: /* other errors */
+ dev_warn(cs->dev, "isoc write: %s\n",
get_usb_statmsg(status));
}
@@ -1250,6 +1303,7 @@ static void read_iso_tasklet(unsigned long data)
struct cardstate *cs = bcs->cs;
struct urb *urb;
int status;
+ struct usb_iso_packet_descriptor *ifd;
char *rcvbuf;
unsigned long flags;
int totleft, numbytes, offset, frame, rc;
@@ -1267,8 +1321,7 @@ static void read_iso_tasklet(unsigned long data)
ubc->isoindone = NULL;
if (unlikely(ubc->loststatus != -EINPROGRESS)) {
dev_warn(cs->dev,
- "isochronous read overrun, "
- "dropped URB with status: %s, %d bytes lost\n",
+ "isoc read overrun, URB dropped (status: %s, %d bytes)\n",
get_usb_statmsg(ubc->loststatus),
ubc->isoinlost);
ubc->loststatus = -EINPROGRESS;
@@ -1298,11 +1351,11 @@ static void read_iso_tasklet(unsigned long data)
__func__, get_usb_statmsg(status));
continue; /* -> skip */
case -EPIPE:
- dev_err(cs->dev, "isochronous read stalled\n");
+ dev_err(cs->dev, "isoc read: stalled\n");
error_hangup(bcs);
continue; /* -> skip */
- default: /* severe trouble */
- dev_warn(cs->dev, "isochronous read: %s\n",
+ default: /* other error */
+ dev_warn(cs->dev, "isoc read: %s\n",
get_usb_statmsg(status));
goto error;
}
@@ -1310,40 +1363,52 @@ static void read_iso_tasklet(unsigned long data)
rcvbuf = urb->transfer_buffer;
totleft = urb->actual_length;
for (frame = 0; totleft > 0 && frame < BAS_NUMFRAMES; frame++) {
- numbytes = urb->iso_frame_desc[frame].actual_length;
- if (unlikely(urb->iso_frame_desc[frame].status))
+ ifd = &urb->iso_frame_desc[frame];
+ numbytes = ifd->actual_length;
+ switch (ifd->status) {
+ case 0: /* success */
+ break;
+ case -EPROTO: /* protocol error or unplug */
+ case -EILSEQ:
+ case -ETIME:
+ /* probably just disconnected, ignore */
+ gig_dbg(DEBUG_ISO,
+ "isoc read: frame %d[%d]: %s\n",
+ frame, numbytes,
+ get_usb_statmsg(ifd->status));
+ break;
+ default: /* other error */
+ /* report, assume transferred bytes are ok */
dev_warn(cs->dev,
- "isochronous read: frame %d[%d]: %s\n",
+ "isoc read: frame %d[%d]: %s\n",
frame, numbytes,
- get_usb_statmsg(
- urb->iso_frame_desc[frame].status));
+ get_usb_statmsg(ifd->status));
+ }
if (unlikely(numbytes > BAS_MAXFRAME))
dev_warn(cs->dev,
- "isochronous read: frame %d: "
- "numbytes (%d) > BAS_MAXFRAME\n",
- frame, numbytes);
+ "isoc read: frame %d[%d]: %s\n",
+ frame, numbytes,
+ "exceeds max frame size");
if (unlikely(numbytes > totleft)) {
dev_warn(cs->dev,
- "isochronous read: frame %d: "
- "numbytes (%d) > totleft (%d)\n",
- frame, numbytes, totleft);
+ "isoc read: frame %d[%d]: %s\n",
+ frame, numbytes,
+ "exceeds total transfer length");
numbytes = totleft;
}
- offset = urb->iso_frame_desc[frame].offset;
+ offset = ifd->offset;
if (unlikely(offset + numbytes > BAS_INBUFSIZE)) {
dev_warn(cs->dev,
- "isochronous read: frame %d: "
- "offset (%d) + numbytes (%d) "
- "> BAS_INBUFSIZE\n",
- frame, offset, numbytes);
+ "isoc read: frame %d[%d]: %s\n",
+ frame, numbytes,
+ "exceeds end of buffer");
numbytes = BAS_INBUFSIZE - offset;
}
gigaset_isoc_receive(rcvbuf + offset, numbytes, bcs);
totleft -= numbytes;
}
if (unlikely(totleft > 0))
- dev_warn(cs->dev,
- "isochronous read: %d data bytes missing\n",
+ dev_warn(cs->dev, "isoc read: %d data bytes missing\n",
totleft);
error:
@@ -1359,9 +1424,9 @@ error:
rc = usb_submit_urb(urb, GFP_ATOMIC);
if (unlikely(rc != 0 && rc != -ENODEV)) {
dev_err(cs->dev,
- "could not resubmit isochronous read URB: %s\n",
+ "could not resubmit isoc read URB: %s\n",
get_usb_rcmsg(rc));
- dump_urb(DEBUG_ISO, "resubmit iso read", urb);
+ dump_urb(DEBUG_ISO, "resubmit isoc read", urb);
error_hangup(bcs);
}
}
@@ -1373,12 +1438,12 @@ error:
/* req_timeout
* timeout routine for control output request
* argument:
- * B channel control structure
+ * controller state structure
*/
static void req_timeout(unsigned long data)
{
- struct bc_state *bcs = (struct bc_state *) data;
- struct bas_cardstate *ucs = bcs->cs->hw.bas;
+ struct cardstate *cs = (struct cardstate *) data;
+ struct bas_cardstate *ucs = cs->hw.bas;
int pending;
unsigned long flags;
@@ -1395,38 +1460,44 @@ static void req_timeout(unsigned long data)
break;
case HD_OPEN_ATCHANNEL:
- dev_err(bcs->cs->dev, "timeout opening AT channel\n");
- error_reset(bcs->cs);
+ dev_err(cs->dev, "timeout opening AT channel\n");
+ error_reset(cs);
break;
- case HD_OPEN_B2CHANNEL:
case HD_OPEN_B1CHANNEL:
- dev_err(bcs->cs->dev, "timeout opening channel %d\n",
- bcs->channel + 1);
- error_hangup(bcs);
+ dev_err(cs->dev, "timeout opening channel 1\n");
+ error_hangup(&cs->bcs[0]);
+ break;
+
+ case HD_OPEN_B2CHANNEL:
+ dev_err(cs->dev, "timeout opening channel 2\n");
+ error_hangup(&cs->bcs[1]);
break;
case HD_CLOSE_ATCHANNEL:
- dev_err(bcs->cs->dev, "timeout closing AT channel\n");
- error_reset(bcs->cs);
+ dev_err(cs->dev, "timeout closing AT channel\n");
+ error_reset(cs);
break;
- case HD_CLOSE_B2CHANNEL:
case HD_CLOSE_B1CHANNEL:
- dev_err(bcs->cs->dev, "timeout closing channel %d\n",
- bcs->channel + 1);
- error_reset(bcs->cs);
+ dev_err(cs->dev, "timeout closing channel 1\n");
+ error_reset(cs);
+ break;
+
+ case HD_CLOSE_B2CHANNEL:
+ dev_err(cs->dev, "timeout closing channel 2\n");
+ error_reset(cs);
break;
case HD_RESET_INTERRUPT_PIPE:
/* error recovery escalation */
- dev_err(bcs->cs->dev,
+ dev_err(cs->dev,
"reset interrupt pipe timeout, attempting USB reset\n");
- usb_queue_reset_device(bcs->cs->hw.bas->interface);
+ usb_queue_reset_device(ucs->interface);
break;
default:
- dev_warn(bcs->cs->dev, "request 0x%02x timed out, clearing\n",
+ dev_warn(cs->dev, "request 0x%02x timed out, clearing\n",
pending);
}
@@ -1557,10 +1628,7 @@ static int req_submit(struct bc_state *bcs, int req, int val, int timeout)
if (timeout > 0) {
gig_dbg(DEBUG_USBREQ, "setting timeout of %d/10 secs", timeout);
- ucs->timer_ctrl.expires = jiffies + timeout * HZ / 10;
- ucs->timer_ctrl.data = (unsigned long) bcs;
- ucs->timer_ctrl.function = req_timeout;
- add_timer(&ucs->timer_ctrl);
+ mod_timer(&ucs->timer_ctrl, jiffies + timeout * HZ / 10);
}
spin_unlock_irqrestore(&ucs->lock, flags);
@@ -1590,21 +1658,20 @@ static int gigaset_init_bchannel(struct bc_state *bcs)
if (cs->hw.bas->basstate & BS_SUSPEND) {
dev_notice(cs->dev,
- "not starting isochronous I/O, "
- "suspend in progress\n");
+ "not starting isoc I/O, suspend in progress\n");
spin_unlock_irqrestore(&cs->lock, flags);
return -EHOSTUNREACH;
}
ret = starturbs(bcs);
if (ret < 0) {
+ spin_unlock_irqrestore(&cs->lock, flags);
dev_err(cs->dev,
- "could not start isochronous I/O for channel B%d: %s\n",
+ "could not start isoc I/O for channel B%d: %s\n",
bcs->channel + 1,
ret == -EFAULT ? "null URB" : get_usb_rcmsg(ret));
if (ret != -ENODEV)
error_hangup(bcs);
- spin_unlock_irqrestore(&cs->lock, flags);
return ret;
}
@@ -1614,11 +1681,11 @@ static int gigaset_init_bchannel(struct bc_state *bcs)
dev_err(cs->dev, "could not open channel B%d\n",
bcs->channel + 1);
stopurbs(bcs->hw.bas);
- if (ret != -ENODEV)
- error_hangup(bcs);
}
spin_unlock_irqrestore(&cs->lock, flags);
+ if (ret < 0 && ret != -ENODEV)
+ error_hangup(bcs);
return ret;
}
@@ -1826,10 +1893,7 @@ static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len)
if (!(update_basstate(ucs, BS_ATTIMER, BS_ATREADY) & BS_ATTIMER)) {
gig_dbg(DEBUG_OUTPUT, "setting ATREADY timeout of %d/10 secs",
ATRDY_TIMEOUT);
- ucs->timer_atrdy.expires = jiffies + ATRDY_TIMEOUT * HZ / 10;
- ucs->timer_atrdy.data = (unsigned long) cs;
- ucs->timer_atrdy.function = atrdy_timeout;
- add_timer(&ucs->timer_atrdy);
+ mod_timer(&ucs->timer_atrdy, jiffies + ATRDY_TIMEOUT * HZ / 10);
}
return 0;
}
@@ -1914,6 +1978,28 @@ static int gigaset_write_cmd(struct cardstate *cs, struct cmdbuf_t *cb)
* The next command will reopen the AT channel automatically.
*/
if (cb->len == 3 && !memcmp(cb->buf, "+++", 3)) {
+ /* If an HD_RECEIVEATDATA_ACK message remains unhandled
+ * because of an error, the base never sends another one.
+ * The response channel is thus effectively blocked.
+ * Closing and reopening the AT channel does *not* clear
+ * this condition.
+ * As a stopgap measure, submit a zero-length AT read
+ * before closing the AT channel. This has the undocumented
+ * effect of triggering a new HD_RECEIVEATDATA_ACK message
+ * from the base if necessary.
+ * The subsequent AT channel close then discards any pending
+ * messages.
+ */
+ spin_lock_irqsave(&cs->lock, flags);
+ if (!(cs->hw.bas->basstate & BS_ATRDPEND)) {
+ kfree(cs->hw.bas->rcvbuf);
+ cs->hw.bas->rcvbuf = NULL;
+ cs->hw.bas->rcvbuf_size = 0;
+ cs->hw.bas->retry_cmd_in = 0;
+ atread_submit(cs, 0);
+ }
+ spin_unlock_irqrestore(&cs->lock, flags);
+
rc = req_submit(cs->bcs, HD_CLOSE_ATCHANNEL, 0, BAS_TIMEOUT);
if (cb->wake_tasklet)
tasklet_schedule(cb->wake_tasklet);
@@ -2010,7 +2096,7 @@ static int gigaset_freebcshw(struct bc_state *bcs)
/* kill URBs and tasklets before freeing - better safe than sorry */
ubc->running = 0;
- gig_dbg(DEBUG_INIT, "%s: killing iso URBs", __func__);
+ gig_dbg(DEBUG_INIT, "%s: killing isoc URBs", __func__);
for (i = 0; i < BAS_OUTURBS; ++i) {
usb_kill_urb(ubc->isoouturbs[i].urb);
usb_free_urb(ubc->isoouturbs[i].urb);
@@ -2131,10 +2217,12 @@ static int gigaset_initcshw(struct cardstate *cs)
ucs->pending = 0;
ucs->basstate = 0;
- init_timer(&ucs->timer_ctrl);
- init_timer(&ucs->timer_atrdy);
- init_timer(&ucs->timer_cmd_in);
+ setup_timer(&ucs->timer_ctrl, req_timeout, (unsigned long) cs);
+ setup_timer(&ucs->timer_atrdy, atrdy_timeout, (unsigned long) cs);
+ setup_timer(&ucs->timer_cmd_in, cmd_in_timeout, (unsigned long) cs);
+ setup_timer(&ucs->timer_int_in, int_in_resubmit, (unsigned long) cs);
init_waitqueue_head(&ucs->waitqueue);
+ INIT_WORK(&ucs->int_in_wq, int_in_work);
return 1;
}
@@ -2282,6 +2370,7 @@ static int gigaset_probe(struct usb_interface *interface,
get_usb_rcmsg(rc));
goto error;
}
+ ucs->retry_int_in = 0;
/* tell the device that the driver is ready */
rc = req_submit(cs->bcs, HD_DEVICE_INIT_ACK, 0, 0);
@@ -2334,10 +2423,12 @@ static void gigaset_disconnect(struct usb_interface *interface)
/* stop driver (common part) */
gigaset_stop(cs);
- /* stop timers and URBs, free ressources */
+ /* stop delayed work and URBs, free ressources */
del_timer_sync(&ucs->timer_ctrl);
del_timer_sync(&ucs->timer_atrdy);
del_timer_sync(&ucs->timer_cmd_in);
+ del_timer_sync(&ucs->timer_int_in);
+ cancel_work_sync(&ucs->int_in_wq);
freeurbs(cs);
usb_set_intfdata(interface, NULL);
kfree(ucs->rcvbuf);
@@ -2400,10 +2491,14 @@ static int gigaset_suspend(struct usb_interface *intf, pm_message_t message)
/* in case of timeout, proceed anyway */
}
- /* kill all URBs and timers that might still be pending */
+ /* kill all URBs and delayed work that might still be pending */
usb_kill_urb(ucs->urb_ctrl);
usb_kill_urb(ucs->urb_int_in);
del_timer_sync(&ucs->timer_ctrl);
+ del_timer_sync(&ucs->timer_atrdy);
+ del_timer_sync(&ucs->timer_cmd_in);
+ del_timer_sync(&ucs->timer_int_in);
+ cancel_work_sync(&ucs->int_in_wq);
gig_dbg(DEBUG_SUSPEND, "suspend complete");
return 0;
@@ -2425,6 +2520,7 @@ static int gigaset_resume(struct usb_interface *intf)
get_usb_rcmsg(rc));
return rc;
}
+ ucs->retry_int_in = 0;
/* clear suspend flag to reallow activity */
update_basstate(ucs, 0, BS_SUSPEND);
diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c
index 3ca561eccd9f..db621db67f61 100644
--- a/drivers/isdn/gigaset/common.c
+++ b/drivers/isdn/gigaset/common.c
@@ -1026,32 +1026,6 @@ struct cardstate *gigaset_get_cs_by_id(int id)
return ret;
}
-void gigaset_debugdrivers(void)
-{
- unsigned long flags;
- static struct cardstate *cs;
- struct gigaset_driver *drv;
- unsigned i;
-
- spin_lock_irqsave(&driver_lock, flags);
- list_for_each_entry(drv, &drivers, list) {
- gig_dbg(DEBUG_DRIVER, "driver %p", drv);
- spin_lock(&drv->lock);
- for (i = 0; i < drv->minors; ++i) {
- gig_dbg(DEBUG_DRIVER, " index %u", i);
- cs = drv->cs + i;
- gig_dbg(DEBUG_DRIVER, " cardstate %p", cs);
- gig_dbg(DEBUG_DRIVER, " flags 0x%02x", cs->flags);
- gig_dbg(DEBUG_DRIVER, " minor_index %u",
- cs->minor_index);
- gig_dbg(DEBUG_DRIVER, " driver %p", cs->driver);
- gig_dbg(DEBUG_DRIVER, " i4l id %d", cs->myid);
- }
- spin_unlock(&drv->lock);
- }
- spin_unlock_irqrestore(&driver_lock, flags);
-}
-
static struct cardstate *gigaset_get_cs_by_minor(unsigned minor)
{
unsigned long flags;
diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h
index a69512fb1195..6dd360734cfd 100644
--- a/drivers/isdn/gigaset/gigaset.h
+++ b/drivers/isdn/gigaset/gigaset.h
@@ -70,7 +70,6 @@ enum debuglevel {
DEBUG_STREAM_DUMP = 0x00080, /* application data stream content */
DEBUG_LLDATA = 0x00100, /* sent/received LL data */
DEBUG_EVENT = 0x00200, /* event processing */
- DEBUG_DRIVER = 0x00400, /* driver structure */
DEBUG_HDLC = 0x00800, /* M10x HDLC processing */
DEBUG_CHANNEL = 0x01000, /* channel allocation/deallocation */
DEBUG_TRANSCMD = 0x02000, /* AT-COMMANDS+RESPONSES */
@@ -727,7 +726,7 @@ struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors,
/* Deallocate driver structure. */
void gigaset_freedriver(struct gigaset_driver *drv);
-void gigaset_debugdrivers(void);
+
struct cardstate *gigaset_get_cs_by_tty(struct tty_struct *tty);
struct cardstate *gigaset_get_cs_by_id(int id);
void gigaset_blockdriver(struct gigaset_driver *drv);
diff --git a/drivers/isdn/gigaset/i4l.c b/drivers/isdn/gigaset/i4l.c
index 34bca37d65b9..9bec8b969964 100644
--- a/drivers/isdn/gigaset/i4l.c
+++ b/drivers/isdn/gigaset/i4l.c
@@ -201,8 +201,6 @@ static int command_from_LL(isdn_ctrl *cntrl)
int i;
size_t l;
- gigaset_debugdrivers();
-
gig_dbg(DEBUG_CMD, "driver: %d, command: %d, arg: 0x%lx",
cntrl->driver, cntrl->command, cntrl->arg);
diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c
index 2dfd346fc889..f39ccdf87a17 100644
--- a/drivers/isdn/gigaset/isocdata.c
+++ b/drivers/isdn/gigaset/isocdata.c
@@ -842,13 +842,14 @@ static inline void trans_receive(unsigned char *src, unsigned count,
if (unlikely(bcs->ignore)) {
bcs->ignore--;
- hdlc_flush(bcs);
return;
}
skb = bcs->rx_skb;
- if (skb == NULL)
+ if (skb == NULL) {
skb = gigaset_new_rx_skb(bcs);
- bcs->hw.bas->goodbytes += skb->len;
+ if (skb == NULL)
+ return;
+ }
dobytes = bcs->rx_bufsize - skb->len;
while (count > 0) {
dst = skb_put(skb, count < dobytes ? count : dobytes);
@@ -860,6 +861,7 @@ static inline void trans_receive(unsigned char *src, unsigned count,
if (dobytes == 0) {
dump_bytes(DEBUG_STREAM_DUMP,
"rcv data", skb->data, skb->len);
+ bcs->hw.bas->goodbytes += skb->len;
gigaset_skb_rcvd(bcs, skb);
skb = gigaset_new_rx_skb(bcs);
if (skb == NULL)
diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c
index 09b1795516f4..91f06a3ef002 100644
--- a/drivers/isdn/hardware/avm/avm_cs.c
+++ b/drivers/isdn/hardware/avm/avm_cs.c
@@ -20,7 +20,6 @@
#include <asm/io.h>
#include <asm/system.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ciscode.h>
#include <pcmcia/ds.h>
@@ -39,87 +38,32 @@ MODULE_LICENSE("GPL");
/*====================================================================*/
-/*
- The event() function is this driver's Card Services event handler.
- It will be called by Card Services when an appropriate card status
- event is received. The config() and release() entry points are
- used to configure or release a socket, in response to card insertion
- and ejection events. They are invoked from the skeleton event
- handler.
-*/
-
static int avmcs_config(struct pcmcia_device *link);
static void avmcs_release(struct pcmcia_device *link);
-
-/*
- The attach() and detach() entry points are used to create and destroy
- "instances" of the driver, where each instance represents everything
- needed to manage one actual PCMCIA card.
-*/
-
static void avmcs_detach(struct pcmcia_device *p_dev);
-/*======================================================================
-
- avmcs_attach() creates an "instance" of the driver, allocating
- local data structures for one device. The device is registered
- with Card Services.
-
- The dev_link structure is initialized, but we don't actually
- configure the card at this point -- we wait until we receive a
- card insertion event.
-
-======================================================================*/
-
static int avmcs_probe(struct pcmcia_device *p_dev)
{
-
- /* The io structure describes IO port mapping */
- p_dev->resource[0]->end = 16;
- p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-
/* General socket configuration */
- p_dev->conf.Attributes = CONF_ENABLE_IRQ;
- p_dev->conf.IntType = INT_MEMORY_AND_IO;
- p_dev->conf.ConfigIndex = 1;
- p_dev->conf.Present = PRESENT_OPTION;
+ p_dev->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+ p_dev->config_index = 1;
+ p_dev->config_regs = PRESENT_OPTION;
return avmcs_config(p_dev);
} /* avmcs_attach */
-/*======================================================================
-
- This deletes a driver "instance". The device is de-registered
- with Card Services. If it has been released, all local data
- structures are freed. Otherwise, the structures will be freed
- when the device is released.
-
-======================================================================*/
static void avmcs_detach(struct pcmcia_device *link)
{
avmcs_release(link);
} /* avmcs_detach */
-/*======================================================================
-
- avmcs_config() is scheduled to run after a CARD_INSERTION event
- is received, to configure the PCMCIA socket, and to make the
- ethernet device available to the system.
-
-======================================================================*/
-
-static int avmcs_configcheck(struct pcmcia_device *p_dev,
- cistpl_cftable_entry_t *cf,
- cistpl_cftable_entry_t *dflt,
- unsigned int vcc,
- void *priv_data)
+static int avmcs_configcheck(struct pcmcia_device *p_dev, void *priv_data)
{
- if (cf->io.nwin <= 0)
- return -ENODEV;
+ p_dev->resource[0]->end = 16;
+ p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+ p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
- p_dev->resource[0]->start = cf->io.win[0].base;
- p_dev->resource[0]->end = cf->io.win[0].len;
return pcmcia_request_io(p_dev);
}
@@ -150,7 +94,7 @@ static int avmcs_config(struct pcmcia_device *link)
/*
* configure the PCMCIA socket
*/
- i = pcmcia_request_configuration(link, &link->conf);
+ i = pcmcia_enable_device(link);
if (i != 0) {
pcmcia_disable_device(link);
break;
@@ -197,13 +141,6 @@ static int avmcs_config(struct pcmcia_device *link)
} /* avmcs_config */
-/*======================================================================
-
- After a card is removed, avmcs_release() will unregister the net
- device, and release the PCMCIA configuration. If the device is
- still open, this will be postponed until it is closed.
-
-======================================================================*/
static void avmcs_release(struct pcmcia_device *link)
{
@@ -222,9 +159,7 @@ MODULE_DEVICE_TABLE(pcmcia, avmcs_ids);
static struct pcmcia_driver avmcs_driver = {
.owner = THIS_MODULE,
- .drv = {
- .name = "avm_cs",
- },
+ .name = "avm_cs",
.probe = avmcs_probe,
.remove = avmcs_detach,
.id_table = avmcs_ids,
diff --git a/drivers/isdn/hardware/eicon/debug.c b/drivers/isdn/hardware/eicon/debug.c
index 33ce89eed65b..362640120886 100644
--- a/drivers/isdn/hardware/eicon/debug.c
+++ b/drivers/isdn/hardware/eicon/debug.c
@@ -862,7 +862,7 @@ void diva_mnt_add_xdi_adapter (const DESCRIPTOR* d) {
diva_os_spin_lock_magic_t old_irql, old_irql1;
dword sec, usec, logical, serial, org_mask;
int id, best_id = 0, free_id = -1;
- char tmp[256];
+ char tmp[128];
diva_dbg_entry_head_t* pmsg = NULL;
int len;
word size;
diff --git a/drivers/isdn/hardware/eicon/debuglib.h b/drivers/isdn/hardware/eicon/debuglib.h
index 8ea587783e14..02eed6b4354c 100644
--- a/drivers/isdn/hardware/eicon/debuglib.h
+++ b/drivers/isdn/hardware/eicon/debuglib.h
@@ -249,7 +249,7 @@ typedef struct _DbgHandle_
} regTime ; /* timestamp for registration */
void *pIrp ; /* ptr to pending i/o request */
unsigned long dbgMask ; /* current debug mask */
- char drvName[16] ; /* ASCII name of registered driver */
+ char drvName[128] ; /* ASCII name of registered driver */
char drvTag[64] ; /* revision string */
DbgEnd dbg_end ; /* function for debug closing */
DbgLog dbg_prt ; /* function for debug appending */
diff --git a/drivers/isdn/hardware/eicon/divasmain.c b/drivers/isdn/hardware/eicon/divasmain.c
index ed9c55506797..f332b60eff6b 100644
--- a/drivers/isdn/hardware/eicon/divasmain.c
+++ b/drivers/isdn/hardware/eicon/divasmain.c
@@ -15,7 +15,6 @@
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/ioport.h>
-#include <linux/workqueue.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
#include <linux/list.h>
@@ -546,7 +545,6 @@ void diva_os_remove_soft_isr(diva_os_soft_isr_t * psoft_isr)
void *mem;
tasklet_kill(&pdpc->divas_task);
- flush_scheduled_work();
mem = psoft_isr->object;
psoft_isr->object = NULL;
diva_os_free(0, mem);
diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c
index 94263c22b874..ac4dd7857cbd 100644
--- a/drivers/isdn/hisax/avma1_cs.c
+++ b/drivers/isdn/hisax/avma1_cs.c
@@ -20,7 +20,6 @@
#include <asm/io.h>
#include <asm/system.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
#include "hisax_cfg.h"
@@ -40,67 +39,22 @@ module_param(isdnprot, int, 0);
/*====================================================================*/
-/*
- The event() function is this driver's Card Services event handler.
- It will be called by Card Services when an appropriate card status
- event is received. The config() and release() entry points are
- used to configure or release a socket, in response to card insertion
- and ejection events. They are invoked from the skeleton event
- handler.
-*/
-
static int avma1cs_config(struct pcmcia_device *link) __devinit ;
static void avma1cs_release(struct pcmcia_device *link);
-
-/*
- The attach() and detach() entry points are used to create and destroy
- "instances" of the driver, where each instance represents everything
- needed to manage one actual PCMCIA card.
-*/
-
static void avma1cs_detach(struct pcmcia_device *p_dev) __devexit ;
-
-/*======================================================================
-
- avma1cs_attach() creates an "instance" of the driver, allocating
- local data structures for one device. The device is registered
- with Card Services.
-
- The dev_link structure is initialized, but we don't actually
- configure the card at this point -- we wait until we receive a
- card insertion event.
-
-======================================================================*/
-
static int __devinit avma1cs_probe(struct pcmcia_device *p_dev)
{
dev_dbg(&p_dev->dev, "avma1cs_attach()\n");
- /* The io structure describes IO port mapping */
- p_dev->resource[0]->end = 16;
- p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
- p_dev->resource[1]->end = 16;
- p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_16;
-
/* General socket configuration */
- p_dev->conf.Attributes = CONF_ENABLE_IRQ;
- p_dev->conf.IntType = INT_MEMORY_AND_IO;
- p_dev->conf.ConfigIndex = 1;
- p_dev->conf.Present = PRESENT_OPTION;
+ p_dev->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+ p_dev->config_index = 1;
+ p_dev->config_regs = PRESENT_OPTION;
return avma1cs_config(p_dev);
} /* avma1cs_attach */
-/*======================================================================
-
- This deletes a driver "instance". The device is de-registered
- with Card Services. If it has been released, all local data
- structures are freed. Otherwise, the structures will be freed
- when the device is released.
-
-======================================================================*/
-
static void __devexit avma1cs_detach(struct pcmcia_device *link)
{
dev_dbg(&link->dev, "avma1cs_detach(0x%p)\n", link);
@@ -108,26 +62,13 @@ static void __devexit avma1cs_detach(struct pcmcia_device *link)
kfree(link->priv);
} /* avma1cs_detach */
-/*======================================================================
-
- avma1cs_config() is scheduled to run after a CARD_INSERTION event
- is received, to configure the PCMCIA socket, and to make the
- ethernet device available to the system.
-
-======================================================================*/
-
-static int avma1cs_configcheck(struct pcmcia_device *p_dev,
- cistpl_cftable_entry_t *cf,
- cistpl_cftable_entry_t *dflt,
- unsigned int vcc,
- void *priv_data)
+static int avma1cs_configcheck(struct pcmcia_device *p_dev, void *priv_data)
{
- if (cf->io.nwin <= 0)
- return -ENODEV;
-
- p_dev->resource[0]->start = cf->io.win[0].base;
- p_dev->resource[0]->end = cf->io.win[0].len;
+ p_dev->resource[0]->end = 16;
+ p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+ p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
p_dev->io_lines = 5;
+
return pcmcia_request_io(p_dev);
}
@@ -161,7 +102,7 @@ static int __devinit avma1cs_config(struct pcmcia_device *link)
/*
* configure the PCMCIA socket
*/
- i = pcmcia_request_configuration(link, &link->conf);
+ i = pcmcia_enable_device(link);
if (i != 0) {
pcmcia_disable_device(link);
break;
@@ -175,9 +116,6 @@ static int __devinit avma1cs_config(struct pcmcia_device *link)
return -ENODEV;
}
- printk(KERN_NOTICE "avma1_cs: checking at i/o %#x, irq %d\n",
- (unsigned int) link->resource[0]->start, link->irq);
-
icard.para[0] = link->irq;
icard.para[1] = link->resource[0]->start;
icard.protocol = isdnprot;
@@ -196,14 +134,6 @@ static int __devinit avma1cs_config(struct pcmcia_device *link)
return 0;
} /* avma1cs_config */
-/*======================================================================
-
- After a card is removed, avma1cs_release() will unregister the net
- device, and release the PCMCIA configuration. If the device is
- still open, this will be postponed until it is closed.
-
-======================================================================*/
-
static void avma1cs_release(struct pcmcia_device *link)
{
unsigned long minor = (unsigned long) link->priv;
@@ -216,7 +146,6 @@ static void avma1cs_release(struct pcmcia_device *link)
pcmcia_disable_device(link);
} /* avma1cs_release */
-
static struct pcmcia_device_id avma1cs_ids[] = {
PCMCIA_DEVICE_PROD_ID12("AVM", "ISDN A", 0x95d42008, 0xadc9d4bb),
PCMCIA_DEVICE_PROD_ID12("ISDN", "CARD", 0x8d9761c8, 0x01c5aa7b),
@@ -226,19 +155,15 @@ MODULE_DEVICE_TABLE(pcmcia, avma1cs_ids);
static struct pcmcia_driver avma1cs_driver = {
.owner = THIS_MODULE,
- .drv = {
- .name = "avma1_cs",
- },
+ .name = "avma1_cs",
.probe = avma1cs_probe,
.remove = __devexit_p(avma1cs_detach),
.id_table = avma1cs_ids,
};
-/*====================================================================*/
-
static int __init init_avma1_cs(void)
{
- return(pcmcia_register_driver(&avma1cs_driver));
+ return pcmcia_register_driver(&avma1cs_driver);
}
static void __exit exit_avma1_cs(void)
diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c
index 6f9afcd5ca4e..b133378d4dc9 100644
--- a/drivers/isdn/hisax/config.c
+++ b/drivers/isdn/hisax/config.c
@@ -801,6 +801,16 @@ static void closecard(int cardnr)
ll_unload(csta);
}
+static irqreturn_t card_irq(int intno, void *dev_id)
+{
+ struct IsdnCardState *cs = dev_id;
+ irqreturn_t ret = cs->irq_func(intno, cs);
+
+ if (ret == IRQ_HANDLED)
+ cs->irq_cnt++;
+ return ret;
+}
+
static int init_card(struct IsdnCardState *cs)
{
int irq_cnt, cnt = 3, ret;
@@ -809,10 +819,10 @@ static int init_card(struct IsdnCardState *cs)
ret = cs->cardmsg(cs, CARD_INIT, NULL);
return(ret);
}
- irq_cnt = kstat_irqs(cs->irq);
+ irq_cnt = cs->irq_cnt = 0;
printk(KERN_INFO "%s: IRQ %d count %d\n", CardType[cs->typ],
cs->irq, irq_cnt);
- if (request_irq(cs->irq, cs->irq_func, cs->irq_flags, "HiSax", cs)) {
+ if (request_irq(cs->irq, card_irq, cs->irq_flags, "HiSax", cs)) {
printk(KERN_WARNING "HiSax: couldn't get interrupt %d\n",
cs->irq);
return 1;
@@ -822,8 +832,8 @@ static int init_card(struct IsdnCardState *cs)
/* Timeout 10ms */
msleep(10);
printk(KERN_INFO "%s: IRQ %d count %d\n",
- CardType[cs->typ], cs->irq, kstat_irqs(cs->irq));
- if (kstat_irqs(cs->irq) == irq_cnt) {
+ CardType[cs->typ], cs->irq, cs->irq_cnt);
+ if (cs->irq_cnt == irq_cnt) {
printk(KERN_WARNING
"%s: IRQ(%d) getting no interrupts during init %d\n",
CardType[cs->typ], cs->irq, 4 - cnt);
diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c
index b3c08aaf41c4..496d477af0f8 100644
--- a/drivers/isdn/hisax/elsa_cs.c
+++ b/drivers/isdn/hisax/elsa_cs.c
@@ -46,7 +46,6 @@
#include <asm/io.h>
#include <asm/system.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/ds.h>
@@ -64,26 +63,8 @@ MODULE_LICENSE("Dual MPL/GPL");
static int protocol = 2; /* EURO-ISDN Default */
module_param(protocol, int, 0);
-/*====================================================================*/
-
-/*
- The event() function is this driver's Card Services event handler.
- It will be called by Card Services when an appropriate card status
- event is received. The config() and release() entry points are
- used to configure or release a socket, in response to card insertion
- and ejection events. They are invoked from the elsa_cs event
- handler.
-*/
-
static int elsa_cs_config(struct pcmcia_device *link) __devinit ;
static void elsa_cs_release(struct pcmcia_device *link);
-
-/*
- The attach() and detach() entry points are used to create and destroy
- "instances" of the driver, where each instance represents everything
- needed to manage one actual PCMCIA card.
-*/
-
static void elsa_cs_detach(struct pcmcia_device *p_dev) __devexit;
typedef struct local_info_t {
@@ -92,18 +73,6 @@ typedef struct local_info_t {
int cardnr;
} local_info_t;
-/*======================================================================
-
- elsa_cs_attach() creates an "instance" of the driver, allocatingx
- local data structures for one device. The device is registered
- with Card Services.
-
- The dev_link structure is initialized, but we don't actually
- configure the card at this point -- we wait until we receive a
- card insertion event.
-
-======================================================================*/
-
static int __devinit elsa_cs_probe(struct pcmcia_device *link)
{
local_info_t *local;
@@ -119,31 +88,9 @@ static int __devinit elsa_cs_probe(struct pcmcia_device *link)
local->cardnr = -1;
- /*
- General socket configuration defaults can go here. In this
- client, we assume very little, and rely on the CIS for almost
- everything. In most clients, many details (i.e., number, sizes,
- and attributes of IO windows) are fixed by the nature of the
- device, and can be hard-wired here.
- */
- link->resource[0]->end = 8;
- link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-
- link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.IntType = INT_MEMORY_AND_IO;
-
return elsa_cs_config(link);
} /* elsa_cs_attach */
-/*======================================================================
-
- This deletes a driver "instance". The device is de-registered
- with Card Services. If it has been released, all local data
- structures are freed. Otherwise, the structures will be freed
- when the device is released.
-
-======================================================================*/
-
static void __devexit elsa_cs_detach(struct pcmcia_device *link)
{
local_info_t *info = link->priv;
@@ -156,27 +103,17 @@ static void __devexit elsa_cs_detach(struct pcmcia_device *link)
kfree(info);
} /* elsa_cs_detach */
-/*======================================================================
-
- elsa_cs_config() is scheduled to run after a CARD_INSERTION event
- is received, to configure the PCMCIA socket, and to make the
- device available to the system.
-
-======================================================================*/
-
-static int elsa_cs_configcheck(struct pcmcia_device *p_dev,
- cistpl_cftable_entry_t *cf,
- cistpl_cftable_entry_t *dflt,
- unsigned int vcc,
- void *priv_data)
+static int elsa_cs_configcheck(struct pcmcia_device *p_dev, void *priv_data)
{
int j;
p_dev->io_lines = 3;
+ p_dev->resource[0]->end = 8;
+ p_dev->resource[0]->flags &= IO_DATA_PATH_WIDTH;
+ p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
- if ((cf->io.nwin > 0) && cf->io.win[0].base) {
+ if ((p_dev->resource[0]->end) && p_dev->resource[0]->start) {
printk(KERN_INFO "(elsa_cs: looks like the 96 model)\n");
- p_dev->resource[0]->start = cf->io.win[0].base;
if (!pcmcia_request_io(p_dev))
return 0;
} else {
@@ -199,6 +136,8 @@ static int __devinit elsa_cs_config(struct pcmcia_device *link)
dev_dbg(&link->dev, "elsa_config(0x%p)\n", link);
dev = link->priv;
+ link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+
i = pcmcia_loop_config(link, elsa_cs_configcheck, NULL);
if (i != 0)
goto failed;
@@ -206,21 +145,10 @@ static int __devinit elsa_cs_config(struct pcmcia_device *link)
if (!link->irq)
goto failed;
- i = pcmcia_request_configuration(link, &link->conf);
+ i = pcmcia_enable_device(link);
if (i != 0)
goto failed;
- /* Finally, report what we've done */
- dev_info(&link->dev, "index 0x%02x: ",
- link->conf.ConfigIndex);
- if (link->conf.Attributes & CONF_ENABLE_IRQ)
- printk(", irq %d", link->irq);
- if (link->resource[0])
- printk(" & %pR", link->resource[0]);
- if (link->resource[1])
- printk(" & %pR", link->resource[1]);
- printk("\n");
-
icard.para[0] = link->irq;
icard.para[1] = link->resource[0]->start;
icard.protocol = protocol;
@@ -240,14 +168,6 @@ failed:
return -ENODEV;
} /* elsa_cs_config */
-/*======================================================================
-
- After a card is removed, elsa_cs_release() will unregister the net
- device, and release the PCMCIA configuration. If the device is
- still open, this will be postponed until it is closed.
-
-======================================================================*/
-
static void elsa_cs_release(struct pcmcia_device *link)
{
local_info_t *local = link->priv;
@@ -291,9 +211,7 @@ MODULE_DEVICE_TABLE(pcmcia, elsa_ids);
static struct pcmcia_driver elsa_cs_driver = {
.owner = THIS_MODULE,
- .drv = {
- .name = "elsa_cs",
- },
+ .name = "elsa_cs",
.probe = elsa_cs_probe,
.remove = __devexit_p(elsa_cs_detach),
.id_table = elsa_ids,
diff --git a/drivers/isdn/hisax/hfc_sx.c b/drivers/isdn/hisax/hfc_sx.c
index be5faf4aa868..5aa138eb0b3c 100644
--- a/drivers/isdn/hisax/hfc_sx.c
+++ b/drivers/isdn/hisax/hfc_sx.c
@@ -234,13 +234,14 @@ read_fifo(struct IsdnCardState *cs, u_char fifo, int trans_max)
count++;
if (count > trans_max)
count = trans_max; /* limit length */
- if ((skb = dev_alloc_skb(count))) {
- dst = skb_put(skb, count);
- while (count--)
+ skb = dev_alloc_skb(count);
+ if (skb) {
+ dst = skb_put(skb, count);
+ while (count--)
*dst++ = Read_hfc(cs, HFCSX_FIF_DRD);
- return(skb);
- }
- else return(NULL); /* no memory */
+ return skb;
+ } else
+ return NULL; /* no memory */
}
do {
diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h
index 832a87855ffb..32ab3924aa73 100644
--- a/drivers/isdn/hisax/hisax.h
+++ b/drivers/isdn/hisax/hisax.h
@@ -959,6 +959,7 @@ struct IsdnCardState {
u_long event;
struct work_struct tqueue;
struct timer_list dbusytimer;
+ unsigned int irq_cnt;
#ifdef ERROR_STATISTIC
int err_crc;
int err_tx;
diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c
index a024192b672a..360204bc2777 100644
--- a/drivers/isdn/hisax/sedlbauer_cs.c
+++ b/drivers/isdn/hisax/sedlbauer_cs.c
@@ -46,7 +46,6 @@
#include <asm/io.h>
#include <asm/system.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/ds.h>
@@ -64,26 +63,9 @@ MODULE_LICENSE("Dual MPL/GPL");
static int protocol = 2; /* EURO-ISDN Default */
module_param(protocol, int, 0);
-/*====================================================================*/
-
-/*
- The event() function is this driver's Card Services event handler.
- It will be called by Card Services when an appropriate card status
- event is received. The config() and release() entry points are
- used to configure or release a socket, in response to card
- insertion and ejection events. They are invoked from the sedlbauer
- event handler.
-*/
-
static int sedlbauer_config(struct pcmcia_device *link) __devinit ;
static void sedlbauer_release(struct pcmcia_device *link);
-/*
- The attach() and detach() entry points are used to create and destroy
- "instances" of the driver, where each instance represents everything
- needed to manage one actual PCMCIA card.
-*/
-
static void sedlbauer_detach(struct pcmcia_device *p_dev) __devexit;
typedef struct local_info_t {
@@ -92,18 +74,6 @@ typedef struct local_info_t {
int cardnr;
} local_info_t;
-/*======================================================================
-
- sedlbauer_attach() creates an "instance" of the driver, allocating
- local data structures for one device. The device is registered
- with Card Services.
-
- The dev_link structure is initialized, but we don't actually
- configure the card at this point -- we wait until we receive a
- card insertion event.
-
-======================================================================*/
-
static int __devinit sedlbauer_probe(struct pcmcia_device *link)
{
local_info_t *local;
@@ -118,35 +88,9 @@ static int __devinit sedlbauer_probe(struct pcmcia_device *link)
local->p_dev = link;
link->priv = local;
- /*
- General socket configuration defaults can go here. In this
- client, we assume very little, and rely on the CIS for almost
- everything. In most clients, many details (i.e., number, sizes,
- and attributes of IO windows) are fixed by the nature of the
- device, and can be hard-wired here.
- */
-
- /* from old sedl_cs
- */
- /* The io structure describes IO port mapping */
- link->resource[0]->end = 8;
- link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-
- link->conf.Attributes = 0;
- link->conf.IntType = INT_MEMORY_AND_IO;
-
return sedlbauer_config(link);
} /* sedlbauer_attach */
-/*======================================================================
-
- This deletes a driver "instance". The device is de-registered
- with Card Services. If it has been released, all local data
- structures are freed. Otherwise, the structures will be freed
- when the device is released.
-
-======================================================================*/
-
static void __devexit sedlbauer_detach(struct pcmcia_device *link)
{
dev_dbg(&link->dev, "sedlbauer_detach(0x%p)\n", link);
@@ -158,70 +102,15 @@ static void __devexit sedlbauer_detach(struct pcmcia_device *link)
kfree(link->priv);
} /* sedlbauer_detach */
-/*======================================================================
-
- sedlbauer_config() is scheduled to run after a CARD_INSERTION event
- is received, to configure the PCMCIA socket, and to make the
- device available to the system.
-
-======================================================================*/
-static int sedlbauer_config_check(struct pcmcia_device *p_dev,
- cistpl_cftable_entry_t *cfg,
- cistpl_cftable_entry_t *dflt,
- unsigned int vcc,
- void *priv_data)
+static int sedlbauer_config_check(struct pcmcia_device *p_dev, void *priv_data)
{
- if (cfg->index == 0)
- return -ENODEV;
-
- /* Does this card need audio output? */
- if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
- p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
- p_dev->conf.Status = CCSR_AUDIO_ENA;
- }
+ if (p_dev->config_index == 0)
+ return -EINVAL;
- /* Use power settings for Vcc and Vpp if present */
- /* Note that the CIS values need to be rescaled */
- if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {
- if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM]/10000)
- return -ENODEV;
- } else if (dflt->vcc.present & (1<<CISTPL_POWER_VNOM)) {
- if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM]/10000)
- return -ENODEV;
- }
-
- if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
- p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
- else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM))
- p_dev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM]/10000;
-
- p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
-
- /* IO window settings */
- p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
- if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
- cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
- p_dev->resource[0]->start = io->win[0].base;
- p_dev->resource[0]->end = io->win[0].len;
- p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
- p_dev->resource[0]->flags |=
- pcmcia_io_cfg_data_width(io->flags);
- if (io->nwin > 1) {
- p_dev->resource[1]->flags = p_dev->resource[0]->flags;
- p_dev->resource[1]->start = io->win[1].base;
- p_dev->resource[1]->end = io->win[1].len;
- }
- /* This reserves IO space but doesn't actually enable it */
- p_dev->io_lines = 3;
- if (pcmcia_request_io(p_dev) != 0)
- return -ENODEV;
- }
-
- return 0;
+ p_dev->io_lines = 3;
+ return pcmcia_request_io(p_dev);
}
-
-
static int __devinit sedlbauer_config(struct pcmcia_device *link)
{
int ret;
@@ -229,44 +118,17 @@ static int __devinit sedlbauer_config(struct pcmcia_device *link)
dev_dbg(&link->dev, "sedlbauer_config(0x%p)\n", link);
- /*
- In this loop, we scan the CIS for configuration table entries,
- each of which describes a valid card configuration, including
- voltage, IO window, memory window, and interrupt settings.
-
- We make no assumptions about the card to be configured: we use
- just the information available in the CIS. In an ideal world,
- this would work for any PCMCIA card, but it requires a complete
- and accurate CIS. In practice, a driver usually "knows" most of
- these things without consulting the CIS, and most client drivers
- will only use the CIS to fill in implementation-defined details.
- */
+ link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_CHECK_VCC |
+ CONF_AUTO_SET_VPP | CONF_AUTO_AUDIO | CONF_AUTO_SET_IO;
+
ret = pcmcia_loop_config(link, sedlbauer_config_check, NULL);
if (ret)
goto failed;
- /*
- This actually configures the PCMCIA socket -- setting up
- the I/O windows and the interrupt mapping, and putting the
- card and host interface into "Memory and IO" mode.
- */
- ret = pcmcia_request_configuration(link, &link->conf);
+ ret = pcmcia_enable_device(link);
if (ret)
goto failed;
- /* Finally, report what we've done */
- dev_info(&link->dev, "index 0x%02x:",
- link->conf.ConfigIndex);
- if (link->conf.Vpp)
- printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10);
- if (link->conf.Attributes & CONF_ENABLE_IRQ)
- printk(", irq %d", link->irq);
- if (link->resource[0])
- printk(" & %pR", link->resource[0]);
- if (link->resource[1])
- printk(" & %pR", link->resource[1]);
- printk("\n");
-
icard.para[0] = link->irq;
icard.para[1] = link->resource[0]->start;
icard.protocol = protocol;
@@ -290,14 +152,6 @@ failed:
} /* sedlbauer_config */
-/*======================================================================
-
- After a card is removed, sedlbauer_release() will unregister the
- device, and release the PCMCIA configuration. If the device is
- still open, this will be postponed until it is closed.
-
-======================================================================*/
-
static void sedlbauer_release(struct pcmcia_device *link)
{
local_info_t *local = link->priv;
@@ -346,9 +200,7 @@ MODULE_DEVICE_TABLE(pcmcia, sedlbauer_ids);
static struct pcmcia_driver sedlbauer_driver = {
.owner = THIS_MODULE,
- .drv = {
- .name = "sedlbauer_cs",
- },
+ .name = "sedlbauer_cs",
.probe = sedlbauer_probe,
.remove = __devexit_p(sedlbauer_detach),
.id_table = sedlbauer_ids,
diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c
index 7296102ca255..282a4467ef19 100644
--- a/drivers/isdn/hisax/teles_cs.c
+++ b/drivers/isdn/hisax/teles_cs.c
@@ -27,7 +27,6 @@
#include <asm/io.h>
#include <asm/system.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/ds.h>
@@ -45,26 +44,8 @@ MODULE_LICENSE("GPL");
static int protocol = 2; /* EURO-ISDN Default */
module_param(protocol, int, 0);
-/*====================================================================*/
-
-/*
- The event() function is this driver's Card Services event handler.
- It will be called by Card Services when an appropriate card status
- event is received. The config() and release() entry points are
- used to configure or release a socket, in response to card insertion
- and ejection events. They are invoked from the teles_cs event
- handler.
-*/
-
static int teles_cs_config(struct pcmcia_device *link) __devinit ;
static void teles_cs_release(struct pcmcia_device *link);
-
-/*
- The attach() and detach() entry points are used to create and destroy
- "instances" of the driver, where each instance represents everything
- needed to manage one actual PCMCIA card.
-*/
-
static void teles_detach(struct pcmcia_device *p_dev) __devexit ;
typedef struct local_info_t {
@@ -73,18 +54,6 @@ typedef struct local_info_t {
int cardnr;
} local_info_t;
-/*======================================================================
-
- teles_attach() creates an "instance" of the driver, allocatingx
- local data structures for one device. The device is registered
- with Card Services.
-
- The dev_link structure is initialized, but we don't actually
- configure the card at this point -- we wait until we receive a
- card insertion event.
-
-======================================================================*/
-
static int __devinit teles_probe(struct pcmcia_device *link)
{
local_info_t *local;
@@ -99,31 +68,11 @@ static int __devinit teles_probe(struct pcmcia_device *link)
local->p_dev = link;
link->priv = local;
- /*
- General socket configuration defaults can go here. In this
- client, we assume very little, and rely on the CIS for almost
- everything. In most clients, many details (i.e., number, sizes,
- and attributes of IO windows) are fixed by the nature of the
- device, and can be hard-wired here.
- */
- link->resource[0]->end = 96;
- link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-
- link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.IntType = INT_MEMORY_AND_IO;
+ link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
return teles_cs_config(link);
} /* teles_attach */
-/*======================================================================
-
- This deletes a driver "instance". The device is de-registered
- with Card Services. If it has been released, all local data
- structures are freed. Otherwise, the structures will be freed
- when the device is released.
-
-======================================================================*/
-
static void __devexit teles_detach(struct pcmcia_device *link)
{
local_info_t *info = link->priv;
@@ -136,27 +85,17 @@ static void __devexit teles_detach(struct pcmcia_device *link)
kfree(info);
} /* teles_detach */
-/*======================================================================
-
- teles_cs_config() is scheduled to run after a CARD_INSERTION event
- is received, to configure the PCMCIA socket, and to make the
- device available to the system.
-
-======================================================================*/
-
-static int teles_cs_configcheck(struct pcmcia_device *p_dev,
- cistpl_cftable_entry_t *cf,
- cistpl_cftable_entry_t *dflt,
- unsigned int vcc,
- void *priv_data)
+static int teles_cs_configcheck(struct pcmcia_device *p_dev, void *priv_data)
{
int j;
p_dev->io_lines = 5;
+ p_dev->resource[0]->end = 96;
+ p_dev->resource[0]->flags &= IO_DATA_PATH_WIDTH;
+ p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
- if ((cf->io.nwin > 0) && cf->io.win[0].base) {
+ if ((p_dev->resource[0]->end) && p_dev->resource[0]->start) {
printk(KERN_INFO "(teles_cs: looks like the 96 model)\n");
- p_dev->resource[0]->start = cf->io.win[0].base;
if (!pcmcia_request_io(p_dev))
return 0;
} else {
@@ -186,21 +125,10 @@ static int __devinit teles_cs_config(struct pcmcia_device *link)
if (!link->irq)
goto cs_failed;
- i = pcmcia_request_configuration(link, &link->conf);
+ i = pcmcia_enable_device(link);
if (i != 0)
goto cs_failed;
- /* Finally, report what we've done */
- dev_info(&link->dev, "index 0x%02x:",
- link->conf.ConfigIndex);
- if (link->conf.Attributes & CONF_ENABLE_IRQ)
- printk(", irq %d", link->irq);
- if (link->resource[0])
- printk(" & %pR", link->resource[0]);
- if (link->resource[1])
- printk(" & %pR", link->resource[1]);
- printk("\n");
-
icard.para[0] = link->irq;
icard.para[1] = link->resource[0]->start;
icard.protocol = protocol;
@@ -222,14 +150,6 @@ cs_failed:
return -ENODEV;
} /* teles_cs_config */
-/*======================================================================
-
- After a card is removed, teles_cs_release() will unregister the net
- device, and release the PCMCIA configuration. If the device is
- still open, this will be postponed until it is closed.
-
-======================================================================*/
-
static void teles_cs_release(struct pcmcia_device *link)
{
local_info_t *local = link->priv;
@@ -273,9 +193,7 @@ MODULE_DEVICE_TABLE(pcmcia, teles_ids);
static struct pcmcia_driver teles_cs_driver = {
.owner = THIS_MODULE,
- .drv = {
- .name = "teles_cs",
- },
+ .name = "teles_cs",
.probe = teles_probe,
.remove = __devexit_p(teles_detach),
.id_table = teles_ids,
diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c
index 51dc60da333b..c463162843ba 100644
--- a/drivers/isdn/i4l/isdn_tty.c
+++ b/drivers/isdn/i4l/isdn_tty.c
@@ -14,7 +14,7 @@
#include <linux/isdn.h>
#include <linux/slab.h>
#include <linux/delay.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include "isdn_common.h"
#include "isdn_tty.h"
#ifdef CONFIG_ISDN_AUDIO
@@ -28,6 +28,7 @@
/* Prototypes */
+static DEFINE_MUTEX(modem_info_mutex);
static int isdn_tty_edit_at(const char *, int, modem_info *);
static void isdn_tty_check_esc(const u_char *, u_char, int, int *, u_long *);
static void isdn_tty_modem_reset_regs(modem_info *, int);
@@ -1354,14 +1355,14 @@ isdn_tty_tiocmget(struct tty_struct *tty, struct file *file)
if (tty->flags & (1 << TTY_IO_ERROR))
return -EIO;
- lock_kernel();
+ mutex_lock(&modem_info_mutex);
#ifdef ISDN_DEBUG_MODEM_IOCTL
printk(KERN_DEBUG "ttyI%d ioctl TIOCMGET\n", info->line);
#endif
control = info->mcr;
status = info->msr;
- unlock_kernel();
+ mutex_unlock(&modem_info_mutex);
return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
| ((control & UART_MCR_DTR) ? TIOCM_DTR : 0)
| ((status & UART_MSR_DCD) ? TIOCM_CAR : 0)
@@ -1385,7 +1386,7 @@ isdn_tty_tiocmset(struct tty_struct *tty, struct file *file,
printk(KERN_DEBUG "ttyI%d ioctl TIOCMxxx: %x %x\n", info->line, set, clear);
#endif
- lock_kernel();
+ mutex_lock(&modem_info_mutex);
if (set & TIOCM_RTS)
info->mcr |= UART_MCR_RTS;
if (set & TIOCM_DTR) {
@@ -1407,7 +1408,7 @@ isdn_tty_tiocmset(struct tty_struct *tty, struct file *file,
isdn_tty_modem_hup(info, 1);
}
}
- unlock_kernel();
+ mutex_unlock(&modem_info_mutex);
return 0;
}
@@ -3515,7 +3516,7 @@ isdn_tty_parse_at(modem_info * info)
{
atemu *m = &info->emu;
char *p;
- char ds[40];
+ char ds[ISDN_MSNLEN];
#ifdef ISDN_DEBUG_AT
printk(KERN_DEBUG "AT: '%s'\n", m->mdmcmd);
@@ -3594,7 +3595,7 @@ isdn_tty_parse_at(modem_info * info)
break;
case '3':
p++;
- sprintf(ds, "\r\n%d", info->emu.charge);
+ snprintf(ds, sizeof(ds), "\r\n%d", info->emu.charge);
isdn_tty_at_cout(ds, info);
break;
default:;
diff --git a/drivers/isdn/mISDN/dsp_cmx.c b/drivers/isdn/mISDN/dsp_cmx.c
index 713ef2b805a2..76d9e673b4e1 100644
--- a/drivers/isdn/mISDN/dsp_cmx.c
+++ b/drivers/isdn/mISDN/dsp_cmx.c
@@ -1237,6 +1237,7 @@ dsp_cmx_receive(struct dsp *dsp, struct sk_buff *skb)
if (dsp->cmx_delay)
dsp->rx_W = (dsp->rx_R + dsp->cmx_delay)
& CMX_BUFF_MASK;
+ else
dsp->rx_W = (dsp->rx_R + (dsp_poll >> 1))
& CMX_BUFF_MASK;
} else {
diff --git a/drivers/isdn/mISDN/l1oip_core.c b/drivers/isdn/mISDN/l1oip_core.c
index 22f38e48ac4e..5b59796ed250 100644
--- a/drivers/isdn/mISDN/l1oip_core.c
+++ b/drivers/isdn/mISDN/l1oip_core.c
@@ -972,7 +972,7 @@ channel_dctrl(struct dchannel *dch, struct mISDN_ctrl_req *cq)
if (debug & DEBUG_L1OIP_SOCKET)
printk(KERN_DEBUG "%s: got new ip address from user "
"space.\n", __func__);
- l1oip_socket_open(hc);
+ l1oip_socket_open(hc);
break;
case MISDN_CTRL_UNSETPEER:
if (debug & DEBUG_L1OIP_SOCKET)
diff --git a/drivers/isdn/mISDN/stack.c b/drivers/isdn/mISDN/stack.c
index b159bd59e64e..a5b632e67552 100644
--- a/drivers/isdn/mISDN/stack.c
+++ b/drivers/isdn/mISDN/stack.c
@@ -18,7 +18,6 @@
#include <linux/slab.h>
#include <linux/mISDNif.h>
#include <linux/kthread.h>
-#include <linux/smp_lock.h>
#include "core.h"
static u_int *debug;
@@ -205,13 +204,7 @@ mISDNStackd(void *data)
struct mISDNstack *st = data;
int err = 0;
-#ifdef CONFIG_SMP
- lock_kernel();
-#endif
sigfillset(&current->blocked);
-#ifdef CONFIG_SMP
- unlock_kernel();
-#endif
if (*debug & DEBUG_MSG_THREAD)
printk(KERN_DEBUG "mISDNStackd %s started\n",
dev_name(&st->dev->dev));
diff --git a/drivers/isdn/mISDN/timerdev.c b/drivers/isdn/mISDN/timerdev.c
index de43c8c70ad0..859c81e9483b 100644
--- a/drivers/isdn/mISDN/timerdev.c
+++ b/drivers/isdn/mISDN/timerdev.c
@@ -267,6 +267,7 @@ static const struct file_operations mISDN_fops = {
.unlocked_ioctl = mISDN_ioctl,
.open = mISDN_open,
.release = mISDN_close,
+ .llseek = no_llseek,
};
static struct miscdevice mISDNtimer = {
diff --git a/drivers/isdn/pcbit/edss1.c b/drivers/isdn/pcbit/edss1.c
index d5920ae22d73..80c9c16fd5ef 100644
--- a/drivers/isdn/pcbit/edss1.c
+++ b/drivers/isdn/pcbit/edss1.c
@@ -33,7 +33,7 @@
#include "callbacks.h"
-char * isdn_state_table[] = {
+const char * const isdn_state_table[] = {
"Closed",
"Call initiated",
"Overlap sending",
diff --git a/drivers/isdn/pcbit/edss1.h b/drivers/isdn/pcbit/edss1.h
index 0b64f97015d8..39f8346e28c5 100644
--- a/drivers/isdn/pcbit/edss1.h
+++ b/drivers/isdn/pcbit/edss1.h
@@ -90,7 +90,7 @@ struct fsm_timer_entry {
unsigned long timeout; /* in seconds */
};
-extern char * isdn_state_table[];
+extern const char * const isdn_state_table[];
void pcbit_fsm_event(struct pcbit_dev *, struct pcbit_chan *,
unsigned short event, struct callb_data *);
diff --git a/drivers/isdn/sc/interrupt.c b/drivers/isdn/sc/interrupt.c
index 485be8b1e1b3..f0225bc0f267 100644
--- a/drivers/isdn/sc/interrupt.c
+++ b/drivers/isdn/sc/interrupt.c
@@ -112,11 +112,19 @@ irqreturn_t interrupt_handler(int dummy, void *card_inst)
}
else if(callid>=0x0000 && callid<=0x7FFF)
{
+ int len;
+
pr_debug("%s: Got Incoming Call\n",
sc_adapter[card]->devicename);
- strcpy(setup.phone,&(rcvmsg.msg_data.byte_array[4]));
- strcpy(setup.eazmsn,
- sc_adapter[card]->channel[rcvmsg.phy_link_no-1].dn);
+ len = strlcpy(setup.phone, &(rcvmsg.msg_data.byte_array[4]),
+ sizeof(setup.phone));
+ if (len >= sizeof(setup.phone))
+ continue;
+ len = strlcpy(setup.eazmsn,
+ sc_adapter[card]->channel[rcvmsg.phy_link_no - 1].dn,
+ sizeof(setup.eazmsn));
+ if (len >= sizeof(setup.eazmsn))
+ continue;
setup.si1 = 7;
setup.si2 = 0;
setup.plan = 0;
@@ -176,7 +184,9 @@ irqreturn_t interrupt_handler(int dummy, void *card_inst)
* Handle a GetMyNumber Rsp
*/
if (IS_CE_MESSAGE(rcvmsg,Call,0,GetMyNumber)){
- strcpy(sc_adapter[card]->channel[rcvmsg.phy_link_no-1].dn,rcvmsg.msg_data.byte_array);
+ strlcpy(sc_adapter[card]->channel[rcvmsg.phy_link_no - 1].dn,
+ rcvmsg.msg_data.byte_array,
+ sizeof(rcvmsg.msg_data.byte_array));
continue;
}
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index e4112622e5a2..cc2a88d5192f 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -304,13 +304,22 @@ config LEDS_MC13783
config LEDS_NS2
tristate "LED support for Network Space v2 GPIO LEDs"
- depends on MACH_NETSPACE_V2 || MACH_INETSPACE_V2 || MACH_NETSPACE_MAX_V2
+ depends on MACH_NETSPACE_V2 || MACH_INETSPACE_V2 || MACH_NETSPACE_MAX_V2 || D2NET_V2
default y
help
This option enable support for the dual-GPIO LED found on the
Network Space v2 board (and parents). This include Internet Space v2,
Network Space (Max) v2 and d2 Network v2 boards.
+config LEDS_NETXBIG
+ tristate "LED support for Big Network series LEDs"
+ depends on MACH_NET2BIG_V2 || MACH_NET5BIG_V2
+ default y
+ help
+ This option enable support for LEDs found on the LaCie 2Big
+ and 5Big Network v2 boards. The LEDs are wired to a CPLD and are
+ controlled through a GPIO extension bus.
+
config LEDS_TRIGGERS
bool "LED Trigger support"
help
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 7d6b95831f8e..9c96db40ef6d 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -38,6 +38,7 @@ obj-$(CONFIG_LEDS_ADP5520) += leds-adp5520.o
obj-$(CONFIG_LEDS_DELL_NETBOOKS) += dell-led.o
obj-$(CONFIG_LEDS_MC13783) += leds-mc13783.o
obj-$(CONFIG_LEDS_NS2) += leds-ns2.o
+obj-$(CONFIG_LEDS_NETXBIG) += leds-netxbig.o
# LED SPI Drivers
obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o
diff --git a/drivers/leds/leds-netxbig.c b/drivers/leds/leds-netxbig.c
new file mode 100644
index 000000000000..f2e51c134399
--- /dev/null
+++ b/drivers/leds/leds-netxbig.c
@@ -0,0 +1,449 @@
+/*
+ * leds-netxbig.c - Driver for the 2Big and 5Big Network series LEDs
+ *
+ * Copyright (C) 2010 LaCie
+ *
+ * Author: Simon Guinot <sguinot@lacie.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <mach/leds-netxbig.h>
+
+/*
+ * GPIO extension bus.
+ */
+
+static DEFINE_SPINLOCK(gpio_ext_lock);
+
+static void gpio_ext_set_addr(struct netxbig_gpio_ext *gpio_ext, int addr)
+{
+ int pin;
+
+ for (pin = 0; pin < gpio_ext->num_addr; pin++)
+ gpio_set_value(gpio_ext->addr[pin], (addr >> pin) & 1);
+}
+
+static void gpio_ext_set_data(struct netxbig_gpio_ext *gpio_ext, int data)
+{
+ int pin;
+
+ for (pin = 0; pin < gpio_ext->num_data; pin++)
+ gpio_set_value(gpio_ext->data[pin], (data >> pin) & 1);
+}
+
+static void gpio_ext_enable_select(struct netxbig_gpio_ext *gpio_ext)
+{
+ /* Enable select is done on the raising edge. */
+ gpio_set_value(gpio_ext->enable, 0);
+ gpio_set_value(gpio_ext->enable, 1);
+}
+
+static void gpio_ext_set_value(struct netxbig_gpio_ext *gpio_ext,
+ int addr, int value)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&gpio_ext_lock, flags);
+ gpio_ext_set_addr(gpio_ext, addr);
+ gpio_ext_set_data(gpio_ext, value);
+ gpio_ext_enable_select(gpio_ext);
+ spin_unlock_irqrestore(&gpio_ext_lock, flags);
+}
+
+static int __devinit gpio_ext_init(struct netxbig_gpio_ext *gpio_ext)
+{
+ int err;
+ int i;
+
+ if (unlikely(!gpio_ext))
+ return -EINVAL;
+
+ /* Configure address GPIOs. */
+ for (i = 0; i < gpio_ext->num_addr; i++) {
+ err = gpio_request(gpio_ext->addr[i], "GPIO extension addr");
+ if (err)
+ goto err_free_addr;
+ err = gpio_direction_output(gpio_ext->addr[i], 0);
+ if (err) {
+ gpio_free(gpio_ext->addr[i]);
+ goto err_free_addr;
+ }
+ }
+ /* Configure data GPIOs. */
+ for (i = 0; i < gpio_ext->num_data; i++) {
+ err = gpio_request(gpio_ext->data[i], "GPIO extension data");
+ if (err)
+ goto err_free_data;
+ err = gpio_direction_output(gpio_ext->data[i], 0);
+ if (err) {
+ gpio_free(gpio_ext->data[i]);
+ goto err_free_data;
+ }
+ }
+ /* Configure "enable select" GPIO. */
+ err = gpio_request(gpio_ext->enable, "GPIO extension enable");
+ if (err)
+ goto err_free_data;
+ err = gpio_direction_output(gpio_ext->enable, 0);
+ if (err) {
+ gpio_free(gpio_ext->enable);
+ goto err_free_data;
+ }
+
+ return 0;
+
+err_free_data:
+ for (i = i - 1; i >= 0; i--)
+ gpio_free(gpio_ext->data[i]);
+ i = gpio_ext->num_addr;
+err_free_addr:
+ for (i = i - 1; i >= 0; i--)
+ gpio_free(gpio_ext->addr[i]);
+
+ return err;
+}
+
+static void __devexit gpio_ext_free(struct netxbig_gpio_ext *gpio_ext)
+{
+ int i;
+
+ gpio_free(gpio_ext->enable);
+ for (i = gpio_ext->num_addr - 1; i >= 0; i--)
+ gpio_free(gpio_ext->addr[i]);
+ for (i = gpio_ext->num_data - 1; i >= 0; i--)
+ gpio_free(gpio_ext->data[i]);
+}
+
+/*
+ * Class LED driver.
+ */
+
+struct netxbig_led_data {
+ struct netxbig_gpio_ext *gpio_ext;
+ struct led_classdev cdev;
+ int mode_addr;
+ int *mode_val;
+ int bright_addr;
+ int bright_max;
+ struct netxbig_led_timer *timer;
+ int num_timer;
+ enum netxbig_led_mode mode;
+ int sata;
+ spinlock_t lock;
+};
+
+static int netxbig_led_get_timer_mode(enum netxbig_led_mode *mode,
+ unsigned long delay_on,
+ unsigned long delay_off,
+ struct netxbig_led_timer *timer,
+ int num_timer)
+{
+ int i;
+
+ for (i = 0; i < num_timer; i++) {
+ if (timer[i].delay_on == delay_on &&
+ timer[i].delay_off == delay_off) {
+ *mode = timer[i].mode;
+ return 0;
+ }
+ }
+ return -EINVAL;
+}
+
+static int netxbig_led_blink_set(struct led_classdev *led_cdev,
+ unsigned long *delay_on,
+ unsigned long *delay_off)
+{
+ struct netxbig_led_data *led_dat =
+ container_of(led_cdev, struct netxbig_led_data, cdev);
+ enum netxbig_led_mode mode;
+ int mode_val;
+ int ret;
+
+ /* Look for a LED mode with the requested timer frequency. */
+ ret = netxbig_led_get_timer_mode(&mode, *delay_on, *delay_off,
+ led_dat->timer, led_dat->num_timer);
+ if (ret < 0)
+ return ret;
+
+ mode_val = led_dat->mode_val[mode];
+ if (mode_val == NETXBIG_LED_INVALID_MODE)
+ return -EINVAL;
+
+ spin_lock_irq(&led_dat->lock);
+
+ gpio_ext_set_value(led_dat->gpio_ext, led_dat->mode_addr, mode_val);
+ led_dat->mode = mode;
+
+ spin_unlock_irq(&led_dat->lock);
+
+ return 0;
+}
+
+static void netxbig_led_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ struct netxbig_led_data *led_dat =
+ container_of(led_cdev, struct netxbig_led_data, cdev);
+ enum netxbig_led_mode mode;
+ int mode_val, bright_val;
+ int set_brightness = 1;
+ unsigned long flags;
+
+ spin_lock_irqsave(&led_dat->lock, flags);
+
+ if (value == LED_OFF) {
+ mode = NETXBIG_LED_OFF;
+ set_brightness = 0;
+ } else {
+ if (led_dat->sata)
+ mode = NETXBIG_LED_SATA;
+ else if (led_dat->mode == NETXBIG_LED_OFF)
+ mode = NETXBIG_LED_ON;
+ else /* Keep 'timer' mode. */
+ mode = led_dat->mode;
+ }
+ mode_val = led_dat->mode_val[mode];
+
+ gpio_ext_set_value(led_dat->gpio_ext, led_dat->mode_addr, mode_val);
+ led_dat->mode = mode;
+ /*
+ * Note that the brightness register is shared between all the
+ * SATA LEDs. So, change the brightness setting for a single
+ * SATA LED will affect all the others.
+ */
+ if (set_brightness) {
+ bright_val = DIV_ROUND_UP(value * led_dat->bright_max,
+ LED_FULL);
+ gpio_ext_set_value(led_dat->gpio_ext,
+ led_dat->bright_addr, bright_val);
+ }
+
+ spin_unlock_irqrestore(&led_dat->lock, flags);
+}
+
+static ssize_t netxbig_led_sata_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buff, size_t count)
+{
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+ struct netxbig_led_data *led_dat =
+ container_of(led_cdev, struct netxbig_led_data, cdev);
+ unsigned long enable;
+ enum netxbig_led_mode mode;
+ int mode_val;
+ int ret;
+
+ ret = strict_strtoul(buff, 10, &enable);
+ if (ret < 0)
+ return ret;
+
+ enable = !!enable;
+
+ spin_lock_irq(&led_dat->lock);
+
+ if (led_dat->sata == enable) {
+ ret = count;
+ goto exit_unlock;
+ }
+
+ if (led_dat->mode != NETXBIG_LED_ON &&
+ led_dat->mode != NETXBIG_LED_SATA)
+ mode = led_dat->mode; /* Keep modes 'off' and 'timer'. */
+ else if (enable)
+ mode = NETXBIG_LED_SATA;
+ else
+ mode = NETXBIG_LED_ON;
+
+ mode_val = led_dat->mode_val[mode];
+ if (mode_val == NETXBIG_LED_INVALID_MODE) {
+ ret = -EINVAL;
+ goto exit_unlock;
+ }
+
+ gpio_ext_set_value(led_dat->gpio_ext, led_dat->mode_addr, mode_val);
+ led_dat->mode = mode;
+ led_dat->sata = enable;
+
+ ret = count;
+
+exit_unlock:
+ spin_unlock_irq(&led_dat->lock);
+
+ return ret;
+}
+
+static ssize_t netxbig_led_sata_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+ struct netxbig_led_data *led_dat =
+ container_of(led_cdev, struct netxbig_led_data, cdev);
+
+ return sprintf(buf, "%d\n", led_dat->sata);
+}
+
+static DEVICE_ATTR(sata, 0644, netxbig_led_sata_show, netxbig_led_sata_store);
+
+static void __devexit delete_netxbig_led(struct netxbig_led_data *led_dat)
+{
+ if (led_dat->mode_val[NETXBIG_LED_SATA] != NETXBIG_LED_INVALID_MODE)
+ device_remove_file(led_dat->cdev.dev, &dev_attr_sata);
+ led_classdev_unregister(&led_dat->cdev);
+}
+
+static int __devinit
+create_netxbig_led(struct platform_device *pdev,
+ struct netxbig_led_data *led_dat,
+ const struct netxbig_led *template)
+{
+ struct netxbig_led_platform_data *pdata = pdev->dev.platform_data;
+ int ret;
+
+ spin_lock_init(&led_dat->lock);
+ led_dat->gpio_ext = pdata->gpio_ext;
+ led_dat->cdev.name = template->name;
+ led_dat->cdev.default_trigger = template->default_trigger;
+ led_dat->cdev.blink_set = netxbig_led_blink_set;
+ led_dat->cdev.brightness_set = netxbig_led_set;
+ /*
+ * Because the GPIO extension bus don't allow to read registers
+ * value, there is no way to probe the LED initial state.
+ * So, the initial sysfs LED value for the "brightness" and "sata"
+ * attributes are inconsistent.
+ *
+ * Note that the initial LED state can't be reconfigured.
+ * The reason is that the LED behaviour must stay uniform during
+ * the whole boot process (bootloader+linux).
+ */
+ led_dat->sata = 0;
+ led_dat->cdev.brightness = LED_OFF;
+ led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
+ led_dat->mode_addr = template->mode_addr;
+ led_dat->mode_val = template->mode_val;
+ led_dat->bright_addr = template->bright_addr;
+ led_dat->bright_max = (1 << pdata->gpio_ext->num_data) - 1;
+ led_dat->timer = pdata->timer;
+ led_dat->num_timer = pdata->num_timer;
+
+ ret = led_classdev_register(&pdev->dev, &led_dat->cdev);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * If available, expose the SATA activity blink capability through
+ * a "sata" sysfs attribute.
+ */
+ if (led_dat->mode_val[NETXBIG_LED_SATA] != NETXBIG_LED_INVALID_MODE) {
+ ret = device_create_file(led_dat->cdev.dev, &dev_attr_sata);
+ if (ret)
+ led_classdev_unregister(&led_dat->cdev);
+ }
+
+ return ret;
+}
+
+static int __devinit netxbig_led_probe(struct platform_device *pdev)
+{
+ struct netxbig_led_platform_data *pdata = pdev->dev.platform_data;
+ struct netxbig_led_data *leds_data;
+ int i;
+ int ret;
+
+ if (!pdata)
+ return -EINVAL;
+
+ leds_data = kzalloc(sizeof(struct netxbig_led_data) * pdata->num_leds,
+ GFP_KERNEL);
+ if (!leds_data)
+ return -ENOMEM;
+
+ ret = gpio_ext_init(pdata->gpio_ext);
+ if (ret < 0)
+ goto err_free_data;
+
+ for (i = 0; i < pdata->num_leds; i++) {
+ ret = create_netxbig_led(pdev, &leds_data[i], &pdata->leds[i]);
+ if (ret < 0)
+ goto err_free_leds;
+ }
+
+ platform_set_drvdata(pdev, leds_data);
+
+ return 0;
+
+err_free_leds:
+ for (i = i - 1; i >= 0; i--)
+ delete_netxbig_led(&leds_data[i]);
+
+ gpio_ext_free(pdata->gpio_ext);
+err_free_data:
+ kfree(leds_data);
+
+ return ret;
+}
+
+static int __devexit netxbig_led_remove(struct platform_device *pdev)
+{
+ struct netxbig_led_platform_data *pdata = pdev->dev.platform_data;
+ struct netxbig_led_data *leds_data;
+ int i;
+
+ leds_data = platform_get_drvdata(pdev);
+
+ for (i = 0; i < pdata->num_leds; i++)
+ delete_netxbig_led(&leds_data[i]);
+
+ gpio_ext_free(pdata->gpio_ext);
+ kfree(leds_data);
+
+ return 0;
+}
+
+static struct platform_driver netxbig_led_driver = {
+ .probe = netxbig_led_probe,
+ .remove = __devexit_p(netxbig_led_remove),
+ .driver = {
+ .name = "leds-netxbig",
+ .owner = THIS_MODULE,
+ },
+};
+MODULE_ALIAS("platform:leds-netxbig");
+
+static int __init netxbig_led_init(void)
+{
+ return platform_driver_register(&netxbig_led_driver);
+}
+
+static void __exit netxbig_led_exit(void)
+{
+ platform_driver_unregister(&netxbig_led_driver);
+}
+
+module_init(netxbig_led_init);
+module_exit(netxbig_led_exit);
+
+MODULE_AUTHOR("Simon Guinot <sguinot@lacie.com>");
+MODULE_DESCRIPTION("LED driver for LaCie xBig Network boards");
+MODULE_LICENSE("GPL");
diff --git a/drivers/leds/leds-ns2.c b/drivers/leds/leds-ns2.c
index 350eb34f049c..f77d48d0b3e4 100644
--- a/drivers/leds/leds-ns2.c
+++ b/drivers/leds/leds-ns2.c
@@ -141,10 +141,12 @@ static ssize_t ns2_led_sata_store(struct device *dev,
struct device_attribute *attr,
const char *buff, size_t count)
{
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+ struct ns2_led_data *led_dat =
+ container_of(led_cdev, struct ns2_led_data, cdev);
int ret;
unsigned long enable;
enum ns2_led_modes mode;
- struct ns2_led_data *led_dat = dev_get_drvdata(dev);
ret = strict_strtoul(buff, 10, &enable);
if (ret < 0)
@@ -172,7 +174,9 @@ static ssize_t ns2_led_sata_store(struct device *dev,
static ssize_t ns2_led_sata_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct ns2_led_data *led_dat = dev_get_drvdata(dev);
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+ struct ns2_led_data *led_dat =
+ container_of(led_cdev, struct ns2_led_data, cdev);
return sprintf(buf, "%d\n", led_dat->sata);
}
@@ -234,7 +238,6 @@ create_ns2_led(struct platform_device *pdev, struct ns2_led_data *led_dat,
if (ret < 0)
goto err_free_slow;
- dev_set_drvdata(led_dat->cdev.dev, led_dat);
ret = device_create_file(led_dat->cdev.dev, &dev_attr_sata);
if (ret < 0)
goto err_free_cdev;
diff --git a/drivers/lguest/lguest_user.c b/drivers/lguest/lguest_user.c
index 85b714df8eae..3c781cdddda9 100644
--- a/drivers/lguest/lguest_user.c
+++ b/drivers/lguest/lguest_user.c
@@ -514,6 +514,7 @@ static const struct file_operations lguest_fops = {
.release = close,
.write = write,
.read = read,
+ .llseek = default_llseek,
};
/*
diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c
index 1c4ee6e77937..75049e765191 100644
--- a/drivers/macintosh/adb.c
+++ b/drivers/macintosh/adb.c
@@ -24,7 +24,6 @@
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/sched.h>
-#include <linux/smp_lock.h>
#include <linux/adb.h>
#include <linux/cuda.h>
#include <linux/pmu.h>
@@ -55,6 +54,7 @@ extern struct adb_driver adb_iop_driver;
extern struct adb_driver via_pmu_driver;
extern struct adb_driver macio_adb_driver;
+static DEFINE_MUTEX(adb_mutex);
static struct adb_driver *adb_driver_list[] = {
#ifdef CONFIG_ADB_MACII
&via_macii_driver,
@@ -83,7 +83,7 @@ static struct adb_driver *adb_controller;
BLOCKING_NOTIFIER_HEAD(adb_client_list);
static int adb_got_sleep;
static int adb_inited;
-static DECLARE_MUTEX(adb_probe_mutex);
+static DEFINE_SEMAPHORE(adb_probe_mutex);
static int sleepy_trackpad;
static int autopoll_devs;
int __adb_probe_sync;
@@ -647,7 +647,7 @@ static int adb_open(struct inode *inode, struct file *file)
struct adbdev_state *state;
int ret = 0;
- lock_kernel();
+ mutex_lock(&adb_mutex);
if (iminor(inode) > 0 || adb_controller == NULL) {
ret = -ENXIO;
goto out;
@@ -665,7 +665,7 @@ static int adb_open(struct inode *inode, struct file *file)
state->inuse = 1;
out:
- unlock_kernel();
+ mutex_unlock(&adb_mutex);
return ret;
}
@@ -674,7 +674,7 @@ static int adb_release(struct inode *inode, struct file *file)
struct adbdev_state *state = file->private_data;
unsigned long flags;
- lock_kernel();
+ mutex_lock(&adb_mutex);
if (state) {
file->private_data = NULL;
spin_lock_irqsave(&state->lock, flags);
@@ -687,7 +687,7 @@ static int adb_release(struct inode *inode, struct file *file)
spin_unlock_irqrestore(&state->lock, flags);
}
}
- unlock_kernel();
+ mutex_unlock(&adb_mutex);
return 0;
}
diff --git a/drivers/macintosh/ans-lcd.c b/drivers/macintosh/ans-lcd.c
index a3d25da2f275..1a57e88a38f7 100644
--- a/drivers/macintosh/ans-lcd.c
+++ b/drivers/macintosh/ans-lcd.c
@@ -137,6 +137,7 @@ const struct file_operations anslcd_fops = {
.write = anslcd_write,
.unlocked_ioctl = anslcd_ioctl,
.open = anslcd_open,
+ .llseek = default_llseek,
};
static struct miscdevice anslcd_dev = {
diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c
index e58c3d33e035..290cb325a94c 100644
--- a/drivers/macintosh/smu.c
+++ b/drivers/macintosh/smu.c
@@ -19,7 +19,6 @@
* the userland interface
*/
-#include <linux/smp_lock.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/device.h>
@@ -97,6 +96,7 @@ struct smu_device {
* I don't think there will ever be more than one SMU, so
* for now, just hard code that
*/
+static DEFINE_MUTEX(smu_mutex);
static struct smu_device *smu;
static DEFINE_MUTEX(smu_part_access);
static int smu_irq_inited;
@@ -1095,12 +1095,12 @@ static int smu_open(struct inode *inode, struct file *file)
pp->mode = smu_file_commands;
init_waitqueue_head(&pp->wait);
- lock_kernel();
+ mutex_lock(&smu_mutex);
spin_lock_irqsave(&smu_clist_lock, flags);
list_add(&pp->list, &smu_clist);
spin_unlock_irqrestore(&smu_clist_lock, flags);
file->private_data = pp;
- unlock_kernel();
+ mutex_unlock(&smu_mutex);
return 0;
}
diff --git a/drivers/macintosh/via-pmu-led.c b/drivers/macintosh/via-pmu-led.c
index d242976bcfe7..19c371809d77 100644
--- a/drivers/macintosh/via-pmu-led.c
+++ b/drivers/macintosh/via-pmu-led.c
@@ -92,8 +92,10 @@ static int __init via_pmu_led_init(void)
if (dt == NULL)
return -ENODEV;
model = of_get_property(dt, "model", NULL);
- if (model == NULL)
+ if (model == NULL) {
+ of_node_put(dt);
return -ENODEV;
+ }
if (strncmp(model, "PowerBook", strlen("PowerBook")) != 0 &&
strncmp(model, "iBook", strlen("iBook")) != 0 &&
strcmp(model, "PowerMac7,2") != 0 &&
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index 2d17e76066bd..cd29c8248386 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -18,7 +18,7 @@
*
*/
#include <stdarg.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/kernel.h>
@@ -73,6 +73,7 @@
/* How many iterations between battery polls */
#define BATTERY_POLLING_COUNT 2
+static DEFINE_MUTEX(pmu_info_proc_mutex);
static volatile unsigned char __iomem *via;
/* VIA registers - spaced 0x200 bytes apart */
@@ -2078,7 +2079,7 @@ pmu_open(struct inode *inode, struct file *file)
pp->rb_get = pp->rb_put = 0;
spin_lock_init(&pp->lock);
init_waitqueue_head(&pp->wait);
- lock_kernel();
+ mutex_lock(&pmu_info_proc_mutex);
spin_lock_irqsave(&all_pvt_lock, flags);
#if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT)
pp->backlight_locker = 0;
@@ -2086,7 +2087,7 @@ pmu_open(struct inode *inode, struct file *file)
list_add(&pp->list, &all_pmu_pvt);
spin_unlock_irqrestore(&all_pvt_lock, flags);
file->private_data = pp;
- unlock_kernel();
+ mutex_unlock(&pmu_info_proc_mutex);
return 0;
}
@@ -2343,9 +2344,9 @@ static long pmu_unlocked_ioctl(struct file *filp,
{
int ret;
- lock_kernel();
+ mutex_lock(&pmu_info_proc_mutex);
ret = pmu_ioctl(filp, cmd, arg);
- unlock_kernel();
+ mutex_unlock(&pmu_info_proc_mutex);
return ret;
}
@@ -2398,6 +2399,7 @@ static const struct file_operations pmu_device_fops = {
#endif
.open = pmu_open,
.release = pmu_release,
+ .llseek = noop_llseek,
};
static struct miscdevice pmu_device = {
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index ed4900ade93a..e4fb58db5454 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -1000,10 +1000,11 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
page = bitmap->sb_page;
offset = sizeof(bitmap_super_t);
if (!file)
- read_sb_page(bitmap->mddev,
- bitmap->mddev->bitmap_info.offset,
- page,
- index, count);
+ page = read_sb_page(
+ bitmap->mddev,
+ bitmap->mddev->bitmap_info.offset,
+ page,
+ index, count);
} else if (file) {
page = read_page(file, index, bitmap, count);
offset = 0;
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 368e8e98f705..d5b0e4c0e702 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -1278,7 +1278,7 @@ static int crypt_map(struct dm_target *ti, struct bio *bio,
struct dm_crypt_io *io;
struct crypt_config *cc;
- if (unlikely(bio_empty_barrier(bio))) {
+ if (bio->bi_rw & REQ_FLUSH) {
cc = ti->private;
bio->bi_bdev = cc->dev->bdev;
return DM_MAPIO_REMAPPED;
diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c
index 0590c75b0ab6..136d4f71a116 100644
--- a/drivers/md/dm-io.c
+++ b/drivers/md/dm-io.c
@@ -31,7 +31,6 @@ struct dm_io_client {
*/
struct io {
unsigned long error_bits;
- unsigned long eopnotsupp_bits;
atomic_t count;
struct task_struct *sleeper;
struct dm_io_client *client;
@@ -130,11 +129,8 @@ static void retrieve_io_and_region_from_bio(struct bio *bio, struct io **io,
*---------------------------------------------------------------*/
static void dec_count(struct io *io, unsigned int region, int error)
{
- if (error) {
+ if (error)
set_bit(region, &io->error_bits);
- if (error == -EOPNOTSUPP)
- set_bit(region, &io->eopnotsupp_bits);
- }
if (atomic_dec_and_test(&io->count)) {
if (io->sleeper)
@@ -310,8 +306,8 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where,
sector_t remaining = where->count;
/*
- * where->count may be zero if rw holds a write barrier and we
- * need to send a zero-sized barrier.
+ * where->count may be zero if rw holds a flush and we need to
+ * send a zero-sized flush.
*/
do {
/*
@@ -364,7 +360,7 @@ static void dispatch_io(int rw, unsigned int num_regions,
*/
for (i = 0; i < num_regions; i++) {
*dp = old_pages;
- if (where[i].count || (rw & REQ_HARDBARRIER))
+ if (where[i].count || (rw & REQ_FLUSH))
do_region(rw, i, where + i, dp, io);
}
@@ -393,9 +389,7 @@ static int sync_io(struct dm_io_client *client, unsigned int num_regions,
return -EIO;
}
-retry:
io->error_bits = 0;
- io->eopnotsupp_bits = 0;
atomic_set(&io->count, 1); /* see dispatch_io() */
io->sleeper = current;
io->client = client;
@@ -412,11 +406,6 @@ retry:
}
set_current_state(TASK_RUNNING);
- if (io->eopnotsupp_bits && (rw & REQ_HARDBARRIER)) {
- rw &= ~REQ_HARDBARRIER;
- goto retry;
- }
-
if (error_bits)
*error_bits = io->error_bits;
@@ -437,7 +426,6 @@ static int async_io(struct dm_io_client *client, unsigned int num_regions,
io = mempool_alloc(client->pool, GFP_NOIO);
io->error_bits = 0;
- io->eopnotsupp_bits = 0;
atomic_set(&io->count, 1); /* see dispatch_io() */
io->sleeper = NULL;
io->client = client;
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index 3e39193e5036..4b54618b4159 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -1596,6 +1596,7 @@ static const struct file_operations _ctl_fops = {
.unlocked_ioctl = dm_ctl_ioctl,
.compat_ioctl = dm_compat_ctl_ioctl,
.owner = THIS_MODULE,
+ .llseek = noop_llseek,
};
static struct miscdevice _dm_misc = {
diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c
index 5a08be0222db..33420e68d153 100644
--- a/drivers/md/dm-log.c
+++ b/drivers/md/dm-log.c
@@ -300,7 +300,7 @@ static int flush_header(struct log_c *lc)
.count = 0,
};
- lc->io_req.bi_rw = WRITE_BARRIER;
+ lc->io_req.bi_rw = WRITE_FLUSH;
return dm_io(&lc->io_req, 1, &null_location, NULL);
}
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index 7c081bcbc3cf..19a59b041c27 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -259,7 +259,7 @@ static int mirror_flush(struct dm_target *ti)
struct dm_io_region io[ms->nr_mirrors];
struct mirror *m;
struct dm_io_request io_req = {
- .bi_rw = WRITE_BARRIER,
+ .bi_rw = WRITE_FLUSH,
.mem.type = DM_IO_KMEM,
.mem.ptr.bvec = NULL,
.client = ms->io_client,
@@ -629,7 +629,7 @@ static void do_write(struct mirror_set *ms, struct bio *bio)
struct dm_io_region io[ms->nr_mirrors], *dest = io;
struct mirror *m;
struct dm_io_request io_req = {
- .bi_rw = WRITE | (bio->bi_rw & WRITE_BARRIER),
+ .bi_rw = WRITE | (bio->bi_rw & WRITE_FLUSH_FUA),
.mem.type = DM_IO_BVEC,
.mem.ptr.bvec = bio->bi_io_vec + bio->bi_idx,
.notify.fn = write_callback,
@@ -670,7 +670,7 @@ static void do_writes(struct mirror_set *ms, struct bio_list *writes)
bio_list_init(&requeue);
while ((bio = bio_list_pop(writes))) {
- if (unlikely(bio_empty_barrier(bio))) {
+ if (bio->bi_rw & REQ_FLUSH) {
bio_list_add(&sync, bio);
continue;
}
@@ -1203,7 +1203,7 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio,
* We need to dec pending if this was a write.
*/
if (rw == WRITE) {
- if (likely(!bio_empty_barrier(bio)))
+ if (!(bio->bi_rw & REQ_FLUSH))
dm_rh_dec(ms->rh, map_context->ll);
return error;
}
diff --git a/drivers/md/dm-region-hash.c b/drivers/md/dm-region-hash.c
index bd5c58b28868..dad011aed0c9 100644
--- a/drivers/md/dm-region-hash.c
+++ b/drivers/md/dm-region-hash.c
@@ -81,9 +81,9 @@ struct dm_region_hash {
struct list_head failed_recovered_regions;
/*
- * If there was a barrier failure no regions can be marked clean.
+ * If there was a flush failure no regions can be marked clean.
*/
- int barrier_failure;
+ int flush_failure;
void *context;
sector_t target_begin;
@@ -217,7 +217,7 @@ struct dm_region_hash *dm_region_hash_create(
INIT_LIST_HEAD(&rh->quiesced_regions);
INIT_LIST_HEAD(&rh->recovered_regions);
INIT_LIST_HEAD(&rh->failed_recovered_regions);
- rh->barrier_failure = 0;
+ rh->flush_failure = 0;
rh->region_pool = mempool_create_kmalloc_pool(MIN_REGIONS,
sizeof(struct dm_region));
@@ -399,8 +399,8 @@ void dm_rh_mark_nosync(struct dm_region_hash *rh, struct bio *bio)
region_t region = dm_rh_bio_to_region(rh, bio);
int recovering = 0;
- if (bio_empty_barrier(bio)) {
- rh->barrier_failure = 1;
+ if (bio->bi_rw & REQ_FLUSH) {
+ rh->flush_failure = 1;
return;
}
@@ -524,7 +524,7 @@ void dm_rh_inc_pending(struct dm_region_hash *rh, struct bio_list *bios)
struct bio *bio;
for (bio = bios->head; bio; bio = bio->bi_next) {
- if (bio_empty_barrier(bio))
+ if (bio->bi_rw & REQ_FLUSH)
continue;
rh_inc(rh, dm_rh_bio_to_region(rh, bio));
}
@@ -555,9 +555,9 @@ void dm_rh_dec(struct dm_region_hash *rh, region_t region)
*/
/* do nothing for DM_RH_NOSYNC */
- if (unlikely(rh->barrier_failure)) {
+ if (unlikely(rh->flush_failure)) {
/*
- * If a write barrier failed some time ago, we
+ * If a write flush failed some time ago, we
* don't know whether or not this write made it
* to the disk, so we must resync the device.
*/
diff --git a/drivers/md/dm-snap-persistent.c b/drivers/md/dm-snap-persistent.c
index cc2bdb83f9ad..0b61792a2780 100644
--- a/drivers/md/dm-snap-persistent.c
+++ b/drivers/md/dm-snap-persistent.c
@@ -687,7 +687,7 @@ static void persistent_commit_exception(struct dm_exception_store *store,
/*
* Commit exceptions to disk.
*/
- if (ps->valid && area_io(ps, WRITE_BARRIER))
+ if (ps->valid && area_io(ps, WRITE_FLUSH_FUA))
ps->valid = 0;
/*
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index 5974d3094d97..53cf79d8bcbc 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -706,8 +706,6 @@ static int dm_add_exception(void *context, chunk_t old, chunk_t new)
return 0;
}
-#define min_not_zero(l, r) (((l) == 0) ? (r) : (((r) == 0) ? (l) : min(l, r)))
-
/*
* Return a minimum chunk size of all snapshots that have the specified origin.
* Return zero if the origin has no snapshots.
@@ -1587,7 +1585,7 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio,
chunk_t chunk;
struct dm_snap_pending_exception *pe = NULL;
- if (unlikely(bio_empty_barrier(bio))) {
+ if (bio->bi_rw & REQ_FLUSH) {
bio->bi_bdev = s->cow->bdev;
return DM_MAPIO_REMAPPED;
}
@@ -1691,7 +1689,7 @@ static int snapshot_merge_map(struct dm_target *ti, struct bio *bio,
int r = DM_MAPIO_REMAPPED;
chunk_t chunk;
- if (unlikely(bio_empty_barrier(bio))) {
+ if (bio->bi_rw & REQ_FLUSH) {
if (!map_context->target_request_nr)
bio->bi_bdev = s->origin->bdev;
else
@@ -2135,7 +2133,7 @@ static int origin_map(struct dm_target *ti, struct bio *bio,
struct dm_dev *dev = ti->private;
bio->bi_bdev = dev->bdev;
- if (unlikely(bio_empty_barrier(bio)))
+ if (bio->bi_rw & REQ_FLUSH)
return DM_MAPIO_REMAPPED;
/* Only tell snapshots if this is a write */
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c
index c297f6da91ea..f0371b4c4fbf 100644
--- a/drivers/md/dm-stripe.c
+++ b/drivers/md/dm-stripe.c
@@ -271,7 +271,7 @@ static int stripe_map(struct dm_target *ti, struct bio *bio,
uint32_t stripe;
unsigned target_request_nr;
- if (unlikely(bio_empty_barrier(bio))) {
+ if (bio->bi_rw & REQ_FLUSH) {
target_request_nr = map_context->target_request_nr;
BUG_ON(target_request_nr >= sc->stripes);
bio->bi_bdev = sc->stripe[target_request_nr].dev->bdev;
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index f9fc07d7a4b9..90267f8d64ee 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -486,11 +486,6 @@ static int __table_get_device(struct dm_table *t, struct dm_target *ti,
return 0;
}
-/*
- * Returns the minimum that is _not_ zero, unless both are zero.
- */
-#define min_not_zero(l, r) (l == 0) ? r : ((r == 0) ? l : min(l, r))
-
int dm_set_device_limits(struct dm_target *ti, struct dm_dev *dev,
sector_t start, sector_t len, void *data)
{
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index ac384b2a6a33..7cb1352f7e7a 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -15,7 +15,6 @@
#include <linux/blkpg.h>
#include <linux/bio.h>
#include <linux/buffer_head.h>
-#include <linux/smp_lock.h>
#include <linux/mempool.h>
#include <linux/slab.h>
#include <linux/idr.h>
@@ -33,6 +32,7 @@
#define DM_COOKIE_ENV_VAR_NAME "DM_COOKIE"
#define DM_COOKIE_LENGTH 24
+static DEFINE_MUTEX(dm_mutex);
static const char *_name = DM_NAME;
static unsigned int major = 0;
@@ -110,7 +110,6 @@ EXPORT_SYMBOL_GPL(dm_get_rq_mapinfo);
#define DMF_FREEING 3
#define DMF_DELETING 4
#define DMF_NOFLUSH_SUSPENDING 5
-#define DMF_QUEUE_IO_TO_THREAD 6
/*
* Work processed by per-device workqueue.
@@ -144,24 +143,9 @@ struct mapped_device {
spinlock_t deferred_lock;
/*
- * An error from the barrier request currently being processed.
- */
- int barrier_error;
-
- /*
- * Protect barrier_error from concurrent endio processing
- * in request-based dm.
- */
- spinlock_t barrier_error_lock;
-
- /*
- * Processing queue (flush/barriers)
+ * Processing queue (flush)
*/
struct workqueue_struct *wq;
- struct work_struct barrier_work;
-
- /* A pointer to the currently processing pre/post flush request */
- struct request *flush_request;
/*
* The current mapping.
@@ -200,8 +184,8 @@ struct mapped_device {
/* sysfs handle */
struct kobject kobj;
- /* zero-length barrier that will be cloned and submitted to targets */
- struct bio barrier_bio;
+ /* zero-length flush that will be cloned and submitted to targets */
+ struct bio flush_bio;
};
/*
@@ -344,7 +328,7 @@ static int dm_blk_open(struct block_device *bdev, fmode_t mode)
{
struct mapped_device *md;
- lock_kernel();
+ mutex_lock(&dm_mutex);
spin_lock(&_minor_lock);
md = bdev->bd_disk->private_data;
@@ -362,7 +346,7 @@ static int dm_blk_open(struct block_device *bdev, fmode_t mode)
out:
spin_unlock(&_minor_lock);
- unlock_kernel();
+ mutex_unlock(&dm_mutex);
return md ? 0 : -ENXIO;
}
@@ -371,10 +355,10 @@ static int dm_blk_close(struct gendisk *disk, fmode_t mode)
{
struct mapped_device *md = disk->private_data;
- lock_kernel();
+ mutex_lock(&dm_mutex);
atomic_dec(&md->open_count);
dm_put(md);
- unlock_kernel();
+ mutex_unlock(&dm_mutex);
return 0;
}
@@ -512,7 +496,7 @@ static void end_io_acct(struct dm_io *io)
/*
* After this is decremented the bio must not be touched if it is
- * a barrier.
+ * a flush.
*/
dm_disk(md)->part0.in_flight[rw] = pending =
atomic_dec_return(&md->pending[rw]);
@@ -528,16 +512,12 @@ static void end_io_acct(struct dm_io *io)
*/
static void queue_io(struct mapped_device *md, struct bio *bio)
{
- down_write(&md->io_lock);
+ unsigned long flags;
- spin_lock_irq(&md->deferred_lock);
+ spin_lock_irqsave(&md->deferred_lock, flags);
bio_list_add(&md->deferred, bio);
- spin_unlock_irq(&md->deferred_lock);
-
- if (!test_and_set_bit(DMF_QUEUE_IO_TO_THREAD, &md->flags))
- queue_work(md->wq, &md->work);
-
- up_write(&md->io_lock);
+ spin_unlock_irqrestore(&md->deferred_lock, flags);
+ queue_work(md->wq, &md->work);
}
/*
@@ -625,11 +605,9 @@ static void dec_pending(struct dm_io *io, int error)
* Target requested pushing back the I/O.
*/
spin_lock_irqsave(&md->deferred_lock, flags);
- if (__noflush_suspending(md)) {
- if (!(io->bio->bi_rw & REQ_HARDBARRIER))
- bio_list_add_head(&md->deferred,
- io->bio);
- } else
+ if (__noflush_suspending(md))
+ bio_list_add_head(&md->deferred, io->bio);
+ else
/* noflush suspend was interrupted. */
io->error = -EIO;
spin_unlock_irqrestore(&md->deferred_lock, flags);
@@ -637,32 +615,23 @@ static void dec_pending(struct dm_io *io, int error)
io_error = io->error;
bio = io->bio;
+ end_io_acct(io);
+ free_io(md, io);
+
+ if (io_error == DM_ENDIO_REQUEUE)
+ return;
- if (bio->bi_rw & REQ_HARDBARRIER) {
+ if ((bio->bi_rw & REQ_FLUSH) && bio->bi_size) {
/*
- * There can be just one barrier request so we use
- * a per-device variable for error reporting.
- * Note that you can't touch the bio after end_io_acct
- *
- * We ignore -EOPNOTSUPP for empty flush reported by
- * underlying devices. We assume that if the device
- * doesn't support empty barriers, it doesn't need
- * cache flushing commands.
+ * Preflush done for flush with data, reissue
+ * without REQ_FLUSH.
*/
- if (!md->barrier_error &&
- !(bio_empty_barrier(bio) && io_error == -EOPNOTSUPP))
- md->barrier_error = io_error;
- end_io_acct(io);
- free_io(md, io);
+ bio->bi_rw &= ~REQ_FLUSH;
+ queue_io(md, bio);
} else {
- end_io_acct(io);
- free_io(md, io);
-
- if (io_error != DM_ENDIO_REQUEUE) {
- trace_block_bio_complete(md->queue, bio);
-
- bio_endio(bio, io_error);
- }
+ /* done with normal IO or empty flush */
+ trace_block_bio_complete(md->queue, bio);
+ bio_endio(bio, io_error);
}
}
}
@@ -755,23 +724,6 @@ static void end_clone_bio(struct bio *clone, int error)
blk_update_request(tio->orig, 0, nr_bytes);
}
-static void store_barrier_error(struct mapped_device *md, int error)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&md->barrier_error_lock, flags);
- /*
- * Basically, the first error is taken, but:
- * -EOPNOTSUPP supersedes any I/O error.
- * Requeue request supersedes any I/O error but -EOPNOTSUPP.
- */
- if (!md->barrier_error || error == -EOPNOTSUPP ||
- (md->barrier_error != -EOPNOTSUPP &&
- error == DM_ENDIO_REQUEUE))
- md->barrier_error = error;
- spin_unlock_irqrestore(&md->barrier_error_lock, flags);
-}
-
/*
* Don't touch any member of the md after calling this function because
* the md may be freed in dm_put() at the end of this function.
@@ -809,13 +761,11 @@ static void free_rq_clone(struct request *clone)
static void dm_end_request(struct request *clone, int error)
{
int rw = rq_data_dir(clone);
- int run_queue = 1;
- bool is_barrier = clone->cmd_flags & REQ_HARDBARRIER;
struct dm_rq_target_io *tio = clone->end_io_data;
struct mapped_device *md = tio->md;
struct request *rq = tio->orig;
- if (rq->cmd_type == REQ_TYPE_BLOCK_PC && !is_barrier) {
+ if (rq->cmd_type == REQ_TYPE_BLOCK_PC) {
rq->errors = clone->errors;
rq->resid_len = clone->resid_len;
@@ -829,15 +779,8 @@ static void dm_end_request(struct request *clone, int error)
}
free_rq_clone(clone);
-
- if (unlikely(is_barrier)) {
- if (unlikely(error))
- store_barrier_error(md, error);
- run_queue = 0;
- } else
- blk_end_request_all(rq, error);
-
- rq_completed(md, rw, run_queue);
+ blk_end_request_all(rq, error);
+ rq_completed(md, rw, true);
}
static void dm_unprep_request(struct request *rq)
@@ -862,16 +805,6 @@ void dm_requeue_unmapped_request(struct request *clone)
struct request_queue *q = rq->q;
unsigned long flags;
- if (unlikely(clone->cmd_flags & REQ_HARDBARRIER)) {
- /*
- * Barrier clones share an original request.
- * Leave it to dm_end_request(), which handles this special
- * case.
- */
- dm_end_request(clone, DM_ENDIO_REQUEUE);
- return;
- }
-
dm_unprep_request(rq);
spin_lock_irqsave(q->queue_lock, flags);
@@ -961,19 +894,6 @@ static void dm_complete_request(struct request *clone, int error)
struct dm_rq_target_io *tio = clone->end_io_data;
struct request *rq = tio->orig;
- if (unlikely(clone->cmd_flags & REQ_HARDBARRIER)) {
- /*
- * Barrier clones share an original request. So can't use
- * softirq_done with the original.
- * Pass the clone to dm_done() directly in this special case.
- * It is safe (even if clone->q->queue_lock is held here)
- * because there is no I/O dispatching during the completion
- * of barrier clone.
- */
- dm_done(clone, error, true);
- return;
- }
-
tio->error = error;
rq->completion_data = clone;
blk_complete_request(rq);
@@ -990,17 +910,6 @@ void dm_kill_unmapped_request(struct request *clone, int error)
struct dm_rq_target_io *tio = clone->end_io_data;
struct request *rq = tio->orig;
- if (unlikely(clone->cmd_flags & REQ_HARDBARRIER)) {
- /*
- * Barrier clones share an original request.
- * Leave it to dm_end_request(), which handles this special
- * case.
- */
- BUG_ON(error > 0);
- dm_end_request(clone, error);
- return;
- }
-
rq->cmd_flags |= REQ_FAILED;
dm_complete_request(clone, error);
}
@@ -1119,7 +1028,7 @@ static void dm_bio_destructor(struct bio *bio)
}
/*
- * Creates a little bio that is just does part of a bvec.
+ * Creates a little bio that just does part of a bvec.
*/
static struct bio *split_bvec(struct bio *bio, sector_t sector,
unsigned short idx, unsigned int offset,
@@ -1134,7 +1043,7 @@ static struct bio *split_bvec(struct bio *bio, sector_t sector,
clone->bi_sector = sector;
clone->bi_bdev = bio->bi_bdev;
- clone->bi_rw = bio->bi_rw & ~REQ_HARDBARRIER;
+ clone->bi_rw = bio->bi_rw;
clone->bi_vcnt = 1;
clone->bi_size = to_bytes(len);
clone->bi_io_vec->bv_offset = offset;
@@ -1161,7 +1070,6 @@ static struct bio *clone_bio(struct bio *bio, sector_t sector,
clone = bio_alloc_bioset(GFP_NOIO, bio->bi_max_vecs, bs);
__bio_clone(clone, bio);
- clone->bi_rw &= ~REQ_HARDBARRIER;
clone->bi_destructor = dm_bio_destructor;
clone->bi_sector = sector;
clone->bi_idx = idx;
@@ -1225,16 +1133,15 @@ static void __issue_target_requests(struct clone_info *ci, struct dm_target *ti,
__issue_target_request(ci, ti, request_nr, len);
}
-static int __clone_and_map_empty_barrier(struct clone_info *ci)
+static int __clone_and_map_empty_flush(struct clone_info *ci)
{
unsigned target_nr = 0;
struct dm_target *ti;
+ BUG_ON(bio_has_data(ci->bio));
while ((ti = dm_table_get_target(ci->map, target_nr++)))
__issue_target_requests(ci, ti, ti->num_flush_requests, 0);
- ci->sector_count = 0;
-
return 0;
}
@@ -1289,9 +1196,6 @@ static int __clone_and_map(struct clone_info *ci)
sector_t len = 0, max;
struct dm_target_io *tio;
- if (unlikely(bio_empty_barrier(bio)))
- return __clone_and_map_empty_barrier(ci);
-
if (unlikely(bio->bi_rw & REQ_DISCARD))
return __clone_and_map_discard(ci);
@@ -1383,16 +1287,11 @@ static void __split_and_process_bio(struct mapped_device *md, struct bio *bio)
ci.map = dm_get_live_table(md);
if (unlikely(!ci.map)) {
- if (!(bio->bi_rw & REQ_HARDBARRIER))
- bio_io_error(bio);
- else
- if (!md->barrier_error)
- md->barrier_error = -EIO;
+ bio_io_error(bio);
return;
}
ci.md = md;
- ci.bio = bio;
ci.io = alloc_io(md);
ci.io->error = 0;
atomic_set(&ci.io->io_count, 1);
@@ -1400,14 +1299,20 @@ static void __split_and_process_bio(struct mapped_device *md, struct bio *bio)
ci.io->md = md;
spin_lock_init(&ci.io->endio_lock);
ci.sector = bio->bi_sector;
- ci.sector_count = bio_sectors(bio);
- if (unlikely(bio_empty_barrier(bio)))
- ci.sector_count = 1;
ci.idx = bio->bi_idx;
start_io_acct(ci.io);
- while (ci.sector_count && !error)
- error = __clone_and_map(&ci);
+ if (bio->bi_rw & REQ_FLUSH) {
+ ci.bio = &ci.md->flush_bio;
+ ci.sector_count = 0;
+ error = __clone_and_map_empty_flush(&ci);
+ /* dec_pending submits any data associated with flush */
+ } else {
+ ci.bio = bio;
+ ci.sector_count = bio_sectors(bio);
+ while (ci.sector_count && !error)
+ error = __clone_and_map(&ci);
+ }
/* drop the extra reference count */
dec_pending(ci.io, error);
@@ -1491,22 +1396,14 @@ static int _dm_request(struct request_queue *q, struct bio *bio)
part_stat_add(cpu, &dm_disk(md)->part0, sectors[rw], bio_sectors(bio));
part_stat_unlock();
- /*
- * If we're suspended or the thread is processing barriers
- * we have to queue this io for later.
- */
- if (unlikely(test_bit(DMF_QUEUE_IO_TO_THREAD, &md->flags)) ||
- unlikely(bio->bi_rw & REQ_HARDBARRIER)) {
+ /* if we're suspended, we have to queue this io for later */
+ if (unlikely(test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags))) {
up_read(&md->io_lock);
- if (unlikely(test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags)) &&
- bio_rw(bio) == READA) {
+ if (bio_rw(bio) != READA)
+ queue_io(md, bio);
+ else
bio_io_error(bio);
- return 0;
- }
-
- queue_io(md, bio);
-
return 0;
}
@@ -1537,14 +1434,6 @@ static int dm_request(struct request_queue *q, struct bio *bio)
return _dm_request(q, bio);
}
-static bool dm_rq_is_flush_request(struct request *rq)
-{
- if (rq->cmd_flags & REQ_FLUSH)
- return true;
- else
- return false;
-}
-
void dm_dispatch_request(struct request *rq)
{
int r;
@@ -1592,22 +1481,15 @@ static int setup_clone(struct request *clone, struct request *rq,
{
int r;
- if (dm_rq_is_flush_request(rq)) {
- blk_rq_init(NULL, clone);
- clone->cmd_type = REQ_TYPE_FS;
- clone->cmd_flags |= (REQ_HARDBARRIER | WRITE);
- } else {
- r = blk_rq_prep_clone(clone, rq, tio->md->bs, GFP_ATOMIC,
- dm_rq_bio_constructor, tio);
- if (r)
- return r;
-
- clone->cmd = rq->cmd;
- clone->cmd_len = rq->cmd_len;
- clone->sense = rq->sense;
- clone->buffer = rq->buffer;
- }
+ r = blk_rq_prep_clone(clone, rq, tio->md->bs, GFP_ATOMIC,
+ dm_rq_bio_constructor, tio);
+ if (r)
+ return r;
+ clone->cmd = rq->cmd;
+ clone->cmd_len = rq->cmd_len;
+ clone->sense = rq->sense;
+ clone->buffer = rq->buffer;
clone->end_io = end_clone_request;
clone->end_io_data = tio;
@@ -1648,9 +1530,6 @@ static int dm_prep_fn(struct request_queue *q, struct request *rq)
struct mapped_device *md = q->queuedata;
struct request *clone;
- if (unlikely(dm_rq_is_flush_request(rq)))
- return BLKPREP_OK;
-
if (unlikely(rq->special)) {
DMWARN("Already has something in rq->special.");
return BLKPREP_KILL;
@@ -1727,6 +1606,7 @@ static void dm_request_fn(struct request_queue *q)
struct dm_table *map = dm_get_live_table(md);
struct dm_target *ti;
struct request *rq, *clone;
+ sector_t pos;
/*
* For suspend, check blk_queue_stopped() and increment
@@ -1739,15 +1619,14 @@ static void dm_request_fn(struct request_queue *q)
if (!rq)
goto plug_and_out;
- if (unlikely(dm_rq_is_flush_request(rq))) {
- BUG_ON(md->flush_request);
- md->flush_request = rq;
- blk_start_request(rq);
- queue_work(md->wq, &md->barrier_work);
- goto out;
- }
+ /* always use block 0 to find the target for flushes for now */
+ pos = 0;
+ if (!(rq->cmd_flags & REQ_FLUSH))
+ pos = blk_rq_pos(rq);
+
+ ti = dm_table_find_target(map, pos);
+ BUG_ON(!dm_target_is_valid(ti));
- ti = dm_table_find_target(map, blk_rq_pos(rq));
if (ti->type->busy && ti->type->busy(ti))
goto plug_and_out;
@@ -1918,7 +1797,6 @@ out:
static const struct block_device_operations dm_blk_dops;
static void dm_wq_work(struct work_struct *work);
-static void dm_rq_barrier_work(struct work_struct *work);
static void dm_init_md_queue(struct mapped_device *md)
{
@@ -1940,6 +1818,7 @@ static void dm_init_md_queue(struct mapped_device *md)
blk_queue_bounce_limit(md->queue, BLK_BOUNCE_ANY);
md->queue->unplug_fn = dm_unplug_all;
blk_queue_merge_bvec(md->queue, dm_merge_bvec);
+ blk_queue_flush(md->queue, REQ_FLUSH | REQ_FUA);
}
/*
@@ -1972,7 +1851,6 @@ static struct mapped_device *alloc_dev(int minor)
mutex_init(&md->suspend_lock);
mutex_init(&md->type_lock);
spin_lock_init(&md->deferred_lock);
- spin_lock_init(&md->barrier_error_lock);
rwlock_init(&md->map_lock);
atomic_set(&md->holders, 1);
atomic_set(&md->open_count, 0);
@@ -1995,7 +1873,6 @@ static struct mapped_device *alloc_dev(int minor)
atomic_set(&md->pending[1], 0);
init_waitqueue_head(&md->wait);
INIT_WORK(&md->work, dm_wq_work);
- INIT_WORK(&md->barrier_work, dm_rq_barrier_work);
init_waitqueue_head(&md->eventq);
md->disk->major = _major;
@@ -2015,6 +1892,10 @@ static struct mapped_device *alloc_dev(int minor)
if (!md->bdev)
goto bad_bdev;
+ bio_init(&md->flush_bio);
+ md->flush_bio.bi_bdev = md->bdev;
+ md->flush_bio.bi_rw = WRITE_FLUSH;
+
/* Populate the mapping, nobody knows we exist yet */
spin_lock(&_minor_lock);
old_md = idr_replace(&_minor_idr, md, minor);
@@ -2245,7 +2126,6 @@ static int dm_init_request_based_queue(struct mapped_device *md)
blk_queue_softirq_done(md->queue, dm_softirq_done);
blk_queue_prep_rq(md->queue, dm_prep_fn);
blk_queue_lld_busy(md->queue, dm_lld_busy);
- blk_queue_ordered(md->queue, QUEUE_ORDERED_DRAIN_FLUSH);
elv_register_queue(md->queue);
@@ -2406,43 +2286,6 @@ static int dm_wait_for_completion(struct mapped_device *md, int interruptible)
return r;
}
-static void dm_flush(struct mapped_device *md)
-{
- dm_wait_for_completion(md, TASK_UNINTERRUPTIBLE);
-
- bio_init(&md->barrier_bio);
- md->barrier_bio.bi_bdev = md->bdev;
- md->barrier_bio.bi_rw = WRITE_BARRIER;
- __split_and_process_bio(md, &md->barrier_bio);
-
- dm_wait_for_completion(md, TASK_UNINTERRUPTIBLE);
-}
-
-static void process_barrier(struct mapped_device *md, struct bio *bio)
-{
- md->barrier_error = 0;
-
- dm_flush(md);
-
- if (!bio_empty_barrier(bio)) {
- __split_and_process_bio(md, bio);
- /*
- * If the request isn't supported, don't waste time with
- * the second flush.
- */
- if (md->barrier_error != -EOPNOTSUPP)
- dm_flush(md);
- }
-
- if (md->barrier_error != DM_ENDIO_REQUEUE)
- bio_endio(bio, md->barrier_error);
- else {
- spin_lock_irq(&md->deferred_lock);
- bio_list_add_head(&md->deferred, bio);
- spin_unlock_irq(&md->deferred_lock);
- }
-}
-
/*
* Process the deferred bios
*/
@@ -2452,33 +2295,27 @@ static void dm_wq_work(struct work_struct *work)
work);
struct bio *c;
- down_write(&md->io_lock);
+ down_read(&md->io_lock);
while (!test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags)) {
spin_lock_irq(&md->deferred_lock);
c = bio_list_pop(&md->deferred);
spin_unlock_irq(&md->deferred_lock);
- if (!c) {
- clear_bit(DMF_QUEUE_IO_TO_THREAD, &md->flags);
+ if (!c)
break;
- }
- up_write(&md->io_lock);
+ up_read(&md->io_lock);
if (dm_request_based(md))
generic_make_request(c);
- else {
- if (c->bi_rw & REQ_HARDBARRIER)
- process_barrier(md, c);
- else
- __split_and_process_bio(md, c);
- }
+ else
+ __split_and_process_bio(md, c);
- down_write(&md->io_lock);
+ down_read(&md->io_lock);
}
- up_write(&md->io_lock);
+ up_read(&md->io_lock);
}
static void dm_queue_flush(struct mapped_device *md)
@@ -2488,73 +2325,6 @@ static void dm_queue_flush(struct mapped_device *md)
queue_work(md->wq, &md->work);
}
-static void dm_rq_set_target_request_nr(struct request *clone, unsigned request_nr)
-{
- struct dm_rq_target_io *tio = clone->end_io_data;
-
- tio->info.target_request_nr = request_nr;
-}
-
-/* Issue barrier requests to targets and wait for their completion. */
-static int dm_rq_barrier(struct mapped_device *md)
-{
- int i, j;
- struct dm_table *map = dm_get_live_table(md);
- unsigned num_targets = dm_table_get_num_targets(map);
- struct dm_target *ti;
- struct request *clone;
-
- md->barrier_error = 0;
-
- for (i = 0; i < num_targets; i++) {
- ti = dm_table_get_target(map, i);
- for (j = 0; j < ti->num_flush_requests; j++) {
- clone = clone_rq(md->flush_request, md, GFP_NOIO);
- dm_rq_set_target_request_nr(clone, j);
- atomic_inc(&md->pending[rq_data_dir(clone)]);
- map_request(ti, clone, md);
- }
- }
-
- dm_wait_for_completion(md, TASK_UNINTERRUPTIBLE);
- dm_table_put(map);
-
- return md->barrier_error;
-}
-
-static void dm_rq_barrier_work(struct work_struct *work)
-{
- int error;
- struct mapped_device *md = container_of(work, struct mapped_device,
- barrier_work);
- struct request_queue *q = md->queue;
- struct request *rq;
- unsigned long flags;
-
- /*
- * Hold the md reference here and leave it at the last part so that
- * the md can't be deleted by device opener when the barrier request
- * completes.
- */
- dm_get(md);
-
- error = dm_rq_barrier(md);
-
- rq = md->flush_request;
- md->flush_request = NULL;
-
- if (error == DM_ENDIO_REQUEUE) {
- spin_lock_irqsave(q->queue_lock, flags);
- blk_requeue_request(q, rq);
- spin_unlock_irqrestore(q->queue_lock, flags);
- } else
- blk_end_request_all(rq, error);
-
- blk_run_queue(q);
-
- dm_put(md);
-}
-
/*
* Swap in a new table, returning the old one for the caller to destroy.
*/
@@ -2677,23 +2447,17 @@ int dm_suspend(struct mapped_device *md, unsigned suspend_flags)
*
* To get all processes out of __split_and_process_bio in dm_request,
* we take the write lock. To prevent any process from reentering
- * __split_and_process_bio from dm_request, we set
- * DMF_QUEUE_IO_TO_THREAD.
- *
- * To quiesce the thread (dm_wq_work), we set DMF_BLOCK_IO_FOR_SUSPEND
- * and call flush_workqueue(md->wq). flush_workqueue will wait until
- * dm_wq_work exits and DMF_BLOCK_IO_FOR_SUSPEND will prevent any
- * further calls to __split_and_process_bio from dm_wq_work.
+ * __split_and_process_bio from dm_request and quiesce the thread
+ * (dm_wq_work), we set BMF_BLOCK_IO_FOR_SUSPEND and call
+ * flush_workqueue(md->wq).
*/
down_write(&md->io_lock);
set_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags);
- set_bit(DMF_QUEUE_IO_TO_THREAD, &md->flags);
up_write(&md->io_lock);
/*
- * Request-based dm uses md->wq for barrier (dm_rq_barrier_work) which
- * can be kicked until md->queue is stopped. So stop md->queue before
- * flushing md->wq.
+ * Stop md->queue before flushing md->wq in case request-based
+ * dm defers requests to md->wq from md->queue.
*/
if (dm_request_based(md))
stop_queue(md->queue);
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index ba19060bcf3f..8a2f767f26d8 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -294,8 +294,8 @@ static int linear_make_request (mddev_t *mddev, struct bio *bio)
dev_info_t *tmp_dev;
sector_t start_sector;
- if (unlikely(bio->bi_rw & REQ_HARDBARRIER)) {
- md_barrier_request(mddev, bio);
+ if (unlikely(bio->bi_rw & REQ_FLUSH)) {
+ md_flush_request(mddev, bio);
return 0;
}
diff --git a/drivers/md/md.c b/drivers/md/md.c
index f20d13e717d5..225815197a3d 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -36,7 +36,7 @@
#include <linux/blkdev.h>
#include <linux/sysctl.h>
#include <linux/seq_file.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/buffer_head.h> /* for invalidate_bdev */
#include <linux/poll.h>
#include <linux/ctype.h>
@@ -57,6 +57,7 @@
#define DEBUG 0
#define dprintk(x...) ((void)(DEBUG && printk(x)))
+static DEFINE_MUTEX(md_mutex);
#ifndef MODULE
static void autostart_arrays(int part);
@@ -226,12 +227,12 @@ static int md_make_request(struct request_queue *q, struct bio *bio)
return 0;
}
rcu_read_lock();
- if (mddev->suspended || mddev->barrier) {
+ if (mddev->suspended) {
DEFINE_WAIT(__wait);
for (;;) {
prepare_to_wait(&mddev->sb_wait, &__wait,
TASK_UNINTERRUPTIBLE);
- if (!mddev->suspended && !mddev->barrier)
+ if (!mddev->suspended)
break;
rcu_read_unlock();
schedule();
@@ -282,40 +283,29 @@ EXPORT_SYMBOL_GPL(mddev_resume);
int mddev_congested(mddev_t *mddev, int bits)
{
- if (mddev->barrier)
- return 1;
return mddev->suspended;
}
EXPORT_SYMBOL(mddev_congested);
/*
- * Generic barrier handling for md
+ * Generic flush handling for md
*/
-#define POST_REQUEST_BARRIER ((void*)1)
-
-static void md_end_barrier(struct bio *bio, int err)
+static void md_end_flush(struct bio *bio, int err)
{
mdk_rdev_t *rdev = bio->bi_private;
mddev_t *mddev = rdev->mddev;
- if (err == -EOPNOTSUPP && mddev->barrier != POST_REQUEST_BARRIER)
- set_bit(BIO_EOPNOTSUPP, &mddev->barrier->bi_flags);
rdev_dec_pending(rdev, mddev);
if (atomic_dec_and_test(&mddev->flush_pending)) {
- if (mddev->barrier == POST_REQUEST_BARRIER) {
- /* This was a post-request barrier */
- mddev->barrier = NULL;
- wake_up(&mddev->sb_wait);
- } else
- /* The pre-request barrier has finished */
- schedule_work(&mddev->barrier_work);
+ /* The pre-request flush has finished */
+ schedule_work(&mddev->flush_work);
}
bio_put(bio);
}
-static void submit_barriers(mddev_t *mddev)
+static void submit_flushes(mddev_t *mddev)
{
mdk_rdev_t *rdev;
@@ -332,60 +322,56 @@ static void submit_barriers(mddev_t *mddev)
atomic_inc(&rdev->nr_pending);
rcu_read_unlock();
bi = bio_alloc(GFP_KERNEL, 0);
- bi->bi_end_io = md_end_barrier;
+ bi->bi_end_io = md_end_flush;
bi->bi_private = rdev;
bi->bi_bdev = rdev->bdev;
atomic_inc(&mddev->flush_pending);
- submit_bio(WRITE_BARRIER, bi);
+ submit_bio(WRITE_FLUSH, bi);
rcu_read_lock();
rdev_dec_pending(rdev, mddev);
}
rcu_read_unlock();
}
-static void md_submit_barrier(struct work_struct *ws)
+static void md_submit_flush_data(struct work_struct *ws)
{
- mddev_t *mddev = container_of(ws, mddev_t, barrier_work);
- struct bio *bio = mddev->barrier;
+ mddev_t *mddev = container_of(ws, mddev_t, flush_work);
+ struct bio *bio = mddev->flush_bio;
atomic_set(&mddev->flush_pending, 1);
- if (test_bit(BIO_EOPNOTSUPP, &bio->bi_flags))
- bio_endio(bio, -EOPNOTSUPP);
- else if (bio->bi_size == 0)
+ if (bio->bi_size == 0)
/* an empty barrier - all done */
bio_endio(bio, 0);
else {
- bio->bi_rw &= ~REQ_HARDBARRIER;
+ bio->bi_rw &= ~REQ_FLUSH;
if (mddev->pers->make_request(mddev, bio))
generic_make_request(bio);
- mddev->barrier = POST_REQUEST_BARRIER;
- submit_barriers(mddev);
}
if (atomic_dec_and_test(&mddev->flush_pending)) {
- mddev->barrier = NULL;
+ mddev->flush_bio = NULL;
wake_up(&mddev->sb_wait);
}
}
-void md_barrier_request(mddev_t *mddev, struct bio *bio)
+void md_flush_request(mddev_t *mddev, struct bio *bio)
{
spin_lock_irq(&mddev->write_lock);
wait_event_lock_irq(mddev->sb_wait,
- !mddev->barrier,
+ !mddev->flush_bio,
mddev->write_lock, /*nothing*/);
- mddev->barrier = bio;
+ mddev->flush_bio = bio;
spin_unlock_irq(&mddev->write_lock);
atomic_set(&mddev->flush_pending, 1);
- INIT_WORK(&mddev->barrier_work, md_submit_barrier);
+ INIT_WORK(&mddev->flush_work, md_submit_flush_data);
- submit_barriers(mddev);
+ submit_flushes(mddev);
if (atomic_dec_and_test(&mddev->flush_pending))
- schedule_work(&mddev->barrier_work);
+ schedule_work(&mddev->flush_work);
}
-EXPORT_SYMBOL(md_barrier_request);
+EXPORT_SYMBOL(md_flush_request);
/* Support for plugging.
* This mirrors the plugging support in request_queue, but does not
@@ -696,31 +682,6 @@ static void super_written(struct bio *bio, int error)
bio_put(bio);
}
-static void super_written_barrier(struct bio *bio, int error)
-{
- struct bio *bio2 = bio->bi_private;
- mdk_rdev_t *rdev = bio2->bi_private;
- mddev_t *mddev = rdev->mddev;
-
- if (!test_bit(BIO_UPTODATE, &bio->bi_flags) &&
- error == -EOPNOTSUPP) {
- unsigned long flags;
- /* barriers don't appear to be supported :-( */
- set_bit(BarriersNotsupp, &rdev->flags);
- mddev->barriers_work = 0;
- spin_lock_irqsave(&mddev->write_lock, flags);
- bio2->bi_next = mddev->biolist;
- mddev->biolist = bio2;
- spin_unlock_irqrestore(&mddev->write_lock, flags);
- wake_up(&mddev->sb_wait);
- bio_put(bio);
- } else {
- bio_put(bio2);
- bio->bi_private = rdev;
- super_written(bio, error);
- }
-}
-
void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev,
sector_t sector, int size, struct page *page)
{
@@ -729,51 +690,28 @@ void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev,
* and decrement it on completion, waking up sb_wait
* if zero is reached.
* If an error occurred, call md_error
- *
- * As we might need to resubmit the request if REQ_HARDBARRIER
- * causes ENOTSUPP, we allocate a spare bio...
*/
struct bio *bio = bio_alloc(GFP_NOIO, 1);
- int rw = REQ_WRITE | REQ_SYNC | REQ_UNPLUG;
bio->bi_bdev = rdev->bdev;
bio->bi_sector = sector;
bio_add_page(bio, page, size, 0);
bio->bi_private = rdev;
bio->bi_end_io = super_written;
- bio->bi_rw = rw;
atomic_inc(&mddev->pending_writes);
- if (!test_bit(BarriersNotsupp, &rdev->flags)) {
- struct bio *rbio;
- rw |= REQ_HARDBARRIER;
- rbio = bio_clone(bio, GFP_NOIO);
- rbio->bi_private = bio;
- rbio->bi_end_io = super_written_barrier;
- submit_bio(rw, rbio);
- } else
- submit_bio(rw, bio);
+ submit_bio(REQ_WRITE | REQ_SYNC | REQ_UNPLUG | REQ_FLUSH | REQ_FUA,
+ bio);
}
void md_super_wait(mddev_t *mddev)
{
- /* wait for all superblock writes that were scheduled to complete.
- * if any had to be retried (due to BARRIER problems), retry them
- */
+ /* wait for all superblock writes that were scheduled to complete */
DEFINE_WAIT(wq);
for(;;) {
prepare_to_wait(&mddev->sb_wait, &wq, TASK_UNINTERRUPTIBLE);
if (atomic_read(&mddev->pending_writes)==0)
break;
- while (mddev->biolist) {
- struct bio *bio;
- spin_lock_irq(&mddev->write_lock);
- bio = mddev->biolist;
- mddev->biolist = bio->bi_next ;
- bio->bi_next = NULL;
- spin_unlock_irq(&mddev->write_lock);
- submit_bio(bio->bi_rw, bio);
- }
schedule();
}
finish_wait(&mddev->sb_wait, &wq);
@@ -1070,7 +1008,6 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
clear_bit(Faulty, &rdev->flags);
clear_bit(In_sync, &rdev->flags);
clear_bit(WriteMostly, &rdev->flags);
- clear_bit(BarriersNotsupp, &rdev->flags);
if (mddev->raid_disks == 0) {
mddev->major_version = 0;
@@ -1485,7 +1422,6 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
clear_bit(Faulty, &rdev->flags);
clear_bit(In_sync, &rdev->flags);
clear_bit(WriteMostly, &rdev->flags);
- clear_bit(BarriersNotsupp, &rdev->flags);
if (mddev->raid_disks == 0) {
mddev->major_version = 1;
@@ -4504,7 +4440,6 @@ int md_run(mddev_t *mddev)
/* may be over-ridden by personality */
mddev->resync_max_sectors = mddev->dev_sectors;
- mddev->barriers_work = 1;
mddev->ok_start_degraded = start_dirty_degraded;
if (start_readonly && mddev->ro == 0)
@@ -4683,7 +4618,6 @@ static void md_clean(mddev_t *mddev)
mddev->recovery = 0;
mddev->in_sync = 0;
mddev->degraded = 0;
- mddev->barriers_work = 0;
mddev->safemode = 0;
mddev->bitmap_info.offset = 0;
mddev->bitmap_info.default_offset = 0;
@@ -5951,7 +5885,7 @@ static int md_open(struct block_device *bdev, fmode_t mode)
mddev_t *mddev = mddev_find(bdev->bd_dev);
int err;
- lock_kernel();
+ mutex_lock(&md_mutex);
if (mddev->gendisk != bdev->bd_disk) {
/* we are racing with mddev_put which is discarding this
* bd_disk.
@@ -5960,7 +5894,7 @@ static int md_open(struct block_device *bdev, fmode_t mode)
/* Wait until bdev->bd_disk is definitely gone */
flush_scheduled_work();
/* Then retry the open from the top */
- unlock_kernel();
+ mutex_unlock(&md_mutex);
return -ERESTARTSYS;
}
BUG_ON(mddev != bdev->bd_disk->private_data);
@@ -5974,7 +5908,7 @@ static int md_open(struct block_device *bdev, fmode_t mode)
check_disk_size_change(mddev->gendisk, bdev);
out:
- unlock_kernel();
+ mutex_unlock(&md_mutex);
return err;
}
@@ -5983,10 +5917,10 @@ static int md_release(struct gendisk *disk, fmode_t mode)
mddev_t *mddev = disk->private_data;
BUG_ON(!mddev);
- lock_kernel();
+ mutex_lock(&md_mutex);
atomic_dec(&mddev->openers);
mddev_put(mddev);
- unlock_kernel();
+ mutex_unlock(&md_mutex);
return 0;
}
diff --git a/drivers/md/md.h b/drivers/md/md.h
index 3931299788dc..112a2c32db0c 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -87,7 +87,6 @@ struct mdk_rdev_s
#define Faulty 1 /* device is known to have a fault */
#define In_sync 2 /* device is in_sync with rest of array */
#define WriteMostly 4 /* Avoid reading if at all possible */
-#define BarriersNotsupp 5 /* REQ_HARDBARRIER is not supported */
#define AllReserved 6 /* If whole device is reserved for
* one array */
#define AutoDetected 7 /* added by auto-detect */
@@ -273,13 +272,6 @@ struct mddev_s
int degraded; /* whether md should consider
* adding a spare
*/
- int barriers_work; /* initialised to true, cleared as soon
- * as a barrier request to slave
- * fails. Only supported
- */
- struct bio *biolist; /* bios that need to be retried
- * because REQ_HARDBARRIER is not supported
- */
atomic_t recovery_active; /* blocks scheduled, but not written */
wait_queue_head_t recovery_wait;
@@ -339,16 +331,13 @@ struct mddev_s
struct attribute_group *to_remove;
struct plug_handle *plug; /* if used by personality */
- /* Generic barrier handling.
- * If there is a pending barrier request, all other
- * writes are blocked while the devices are flushed.
- * The last to finish a flush schedules a worker to
- * submit the barrier request (without the barrier flag),
- * then submit more flush requests.
+ /* Generic flush handling.
+ * The last to finish preflush schedules a worker to submit
+ * the rest of the request (without the REQ_FLUSH flag).
*/
- struct bio *barrier;
+ struct bio *flush_bio;
atomic_t flush_pending;
- struct work_struct barrier_work;
+ struct work_struct flush_work;
struct work_struct event_work; /* used by dm to report failure event */
};
@@ -502,7 +491,7 @@ extern void md_done_sync(mddev_t *mddev, int blocks, int ok);
extern void md_error(mddev_t *mddev, mdk_rdev_t *rdev);
extern int mddev_congested(mddev_t *mddev, int bits);
-extern void md_barrier_request(mddev_t *mddev, struct bio *bio);
+extern void md_flush_request(mddev_t *mddev, struct bio *bio);
extern void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev,
sector_t sector, int size, struct page *page);
extern void md_super_wait(mddev_t *mddev);
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index 0307d217e7a4..6d7ddf32ef2e 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -142,8 +142,8 @@ static int multipath_make_request(mddev_t *mddev, struct bio * bio)
struct multipath_bh * mp_bh;
struct multipath_info *multipath;
- if (unlikely(bio->bi_rw & REQ_HARDBARRIER)) {
- md_barrier_request(mddev, bio);
+ if (unlikely(bio->bi_rw & REQ_FLUSH)) {
+ md_flush_request(mddev, bio);
return 0;
}
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index 6f7af46d623c..a39f4c355e55 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -483,8 +483,8 @@ static int raid0_make_request(mddev_t *mddev, struct bio *bio)
struct strip_zone *zone;
mdk_rdev_t *tmp_dev;
- if (unlikely(bio->bi_rw & REQ_HARDBARRIER)) {
- md_barrier_request(mddev, bio);
+ if (unlikely(bio->bi_rw & REQ_FLUSH)) {
+ md_flush_request(mddev, bio);
return 0;
}
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index ad83a4dcadc3..378a25894c57 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -319,83 +319,74 @@ static void raid1_end_write_request(struct bio *bio, int error)
if (r1_bio->bios[mirror] == bio)
break;
- if (error == -EOPNOTSUPP && test_bit(R1BIO_Barrier, &r1_bio->state)) {
- set_bit(BarriersNotsupp, &conf->mirrors[mirror].rdev->flags);
- set_bit(R1BIO_BarrierRetry, &r1_bio->state);
- r1_bio->mddev->barriers_work = 0;
- /* Don't rdev_dec_pending in this branch - keep it for the retry */
- } else {
+ /*
+ * 'one mirror IO has finished' event handler:
+ */
+ r1_bio->bios[mirror] = NULL;
+ to_put = bio;
+ if (!uptodate) {
+ md_error(r1_bio->mddev, conf->mirrors[mirror].rdev);
+ /* an I/O failed, we can't clear the bitmap */
+ set_bit(R1BIO_Degraded, &r1_bio->state);
+ } else
/*
- * this branch is our 'one mirror IO has finished' event handler:
+ * Set R1BIO_Uptodate in our master bio, so that we
+ * will return a good error code for to the higher
+ * levels even if IO on some other mirrored buffer
+ * fails.
+ *
+ * The 'master' represents the composite IO operation
+ * to user-side. So if something waits for IO, then it
+ * will wait for the 'master' bio.
*/
- r1_bio->bios[mirror] = NULL;
- to_put = bio;
- if (!uptodate) {
- md_error(r1_bio->mddev, conf->mirrors[mirror].rdev);
- /* an I/O failed, we can't clear the bitmap */
- set_bit(R1BIO_Degraded, &r1_bio->state);
- } else
- /*
- * Set R1BIO_Uptodate in our master bio, so that
- * we will return a good error code for to the higher
- * levels even if IO on some other mirrored buffer fails.
- *
- * The 'master' represents the composite IO operation to
- * user-side. So if something waits for IO, then it will
- * wait for the 'master' bio.
- */
- set_bit(R1BIO_Uptodate, &r1_bio->state);
-
- update_head_pos(mirror, r1_bio);
-
- if (behind) {
- if (test_bit(WriteMostly, &conf->mirrors[mirror].rdev->flags))
- atomic_dec(&r1_bio->behind_remaining);
-
- /* In behind mode, we ACK the master bio once the I/O has safely
- * reached all non-writemostly disks. Setting the Returned bit
- * ensures that this gets done only once -- we don't ever want to
- * return -EIO here, instead we'll wait */
-
- if (atomic_read(&r1_bio->behind_remaining) >= (atomic_read(&r1_bio->remaining)-1) &&
- test_bit(R1BIO_Uptodate, &r1_bio->state)) {
- /* Maybe we can return now */
- if (!test_and_set_bit(R1BIO_Returned, &r1_bio->state)) {
- struct bio *mbio = r1_bio->master_bio;
- PRINTK(KERN_DEBUG "raid1: behind end write sectors %llu-%llu\n",
- (unsigned long long) mbio->bi_sector,
- (unsigned long long) mbio->bi_sector +
- (mbio->bi_size >> 9) - 1);
- bio_endio(mbio, 0);
- }
+ set_bit(R1BIO_Uptodate, &r1_bio->state);
+
+ update_head_pos(mirror, r1_bio);
+
+ if (behind) {
+ if (test_bit(WriteMostly, &conf->mirrors[mirror].rdev->flags))
+ atomic_dec(&r1_bio->behind_remaining);
+
+ /*
+ * In behind mode, we ACK the master bio once the I/O
+ * has safely reached all non-writemostly
+ * disks. Setting the Returned bit ensures that this
+ * gets done only once -- we don't ever want to return
+ * -EIO here, instead we'll wait
+ */
+ if (atomic_read(&r1_bio->behind_remaining) >= (atomic_read(&r1_bio->remaining)-1) &&
+ test_bit(R1BIO_Uptodate, &r1_bio->state)) {
+ /* Maybe we can return now */
+ if (!test_and_set_bit(R1BIO_Returned, &r1_bio->state)) {
+ struct bio *mbio = r1_bio->master_bio;
+ PRINTK(KERN_DEBUG "raid1: behind end write sectors %llu-%llu\n",
+ (unsigned long long) mbio->bi_sector,
+ (unsigned long long) mbio->bi_sector +
+ (mbio->bi_size >> 9) - 1);
+ bio_endio(mbio, 0);
}
}
- rdev_dec_pending(conf->mirrors[mirror].rdev, conf->mddev);
}
+ rdev_dec_pending(conf->mirrors[mirror].rdev, conf->mddev);
+
/*
- *
* Let's see if all mirrored write operations have finished
* already.
*/
if (atomic_dec_and_test(&r1_bio->remaining)) {
- if (test_bit(R1BIO_BarrierRetry, &r1_bio->state))
- reschedule_retry(r1_bio);
- else {
- /* it really is the end of this request */
- if (test_bit(R1BIO_BehindIO, &r1_bio->state)) {
- /* free extra copy of the data pages */
- int i = bio->bi_vcnt;
- while (i--)
- safe_put_page(bio->bi_io_vec[i].bv_page);
- }
- /* clear the bitmap if all writes complete successfully */
- bitmap_endwrite(r1_bio->mddev->bitmap, r1_bio->sector,
- r1_bio->sectors,
- !test_bit(R1BIO_Degraded, &r1_bio->state),
- behind);
- md_write_end(r1_bio->mddev);
- raid_end_bio_io(r1_bio);
+ if (test_bit(R1BIO_BehindIO, &r1_bio->state)) {
+ /* free extra copy of the data pages */
+ int i = bio->bi_vcnt;
+ while (i--)
+ safe_put_page(bio->bi_io_vec[i].bv_page);
}
+ /* clear the bitmap if all writes complete successfully */
+ bitmap_endwrite(r1_bio->mddev->bitmap, r1_bio->sector,
+ r1_bio->sectors,
+ !test_bit(R1BIO_Degraded, &r1_bio->state),
+ behind);
+ md_write_end(r1_bio->mddev);
+ raid_end_bio_io(r1_bio);
}
if (to_put)
@@ -788,16 +779,13 @@ static int make_request(mddev_t *mddev, struct bio * bio)
struct page **behind_pages = NULL;
const int rw = bio_data_dir(bio);
const unsigned long do_sync = (bio->bi_rw & REQ_SYNC);
- unsigned long do_barriers;
+ const unsigned long do_flush_fua = (bio->bi_rw & (REQ_FLUSH | REQ_FUA));
mdk_rdev_t *blocked_rdev;
/*
* Register the new request and wait if the reconstruction
* thread has put up a bar for new requests.
* Continue immediately if no resync is active currently.
- * We test barriers_work *after* md_write_start as md_write_start
- * may cause the first superblock write, and that will check out
- * if barriers work.
*/
md_write_start(mddev, bio); /* wait on superblock update early */
@@ -821,13 +809,6 @@ static int make_request(mddev_t *mddev, struct bio * bio)
}
finish_wait(&conf->wait_barrier, &w);
}
- if (unlikely(!mddev->barriers_work &&
- (bio->bi_rw & REQ_HARDBARRIER))) {
- if (rw == WRITE)
- md_write_end(mddev);
- bio_endio(bio, -EOPNOTSUPP);
- return 0;
- }
wait_barrier(conf);
@@ -959,10 +940,6 @@ static int make_request(mddev_t *mddev, struct bio * bio)
atomic_set(&r1_bio->remaining, 0);
atomic_set(&r1_bio->behind_remaining, 0);
- do_barriers = bio->bi_rw & REQ_HARDBARRIER;
- if (do_barriers)
- set_bit(R1BIO_Barrier, &r1_bio->state);
-
bio_list_init(&bl);
for (i = 0; i < disks; i++) {
struct bio *mbio;
@@ -975,7 +952,7 @@ static int make_request(mddev_t *mddev, struct bio * bio)
mbio->bi_sector = r1_bio->sector + conf->mirrors[i].rdev->data_offset;
mbio->bi_bdev = conf->mirrors[i].rdev->bdev;
mbio->bi_end_io = raid1_end_write_request;
- mbio->bi_rw = WRITE | do_barriers | do_sync;
+ mbio->bi_rw = WRITE | do_flush_fua | do_sync;
mbio->bi_private = r1_bio;
if (behind_pages) {
@@ -1634,41 +1611,6 @@ static void raid1d(mddev_t *mddev)
if (test_bit(R1BIO_IsSync, &r1_bio->state)) {
sync_request_write(mddev, r1_bio);
unplug = 1;
- } else if (test_bit(R1BIO_BarrierRetry, &r1_bio->state)) {
- /* some requests in the r1bio were REQ_HARDBARRIER
- * requests which failed with -EOPNOTSUPP. Hohumm..
- * Better resubmit without the barrier.
- * We know which devices to resubmit for, because
- * all others have had their bios[] entry cleared.
- * We already have a nr_pending reference on these rdevs.
- */
- int i;
- const unsigned long do_sync = (r1_bio->master_bio->bi_rw & REQ_SYNC);
- clear_bit(R1BIO_BarrierRetry, &r1_bio->state);
- clear_bit(R1BIO_Barrier, &r1_bio->state);
- for (i=0; i < conf->raid_disks; i++)
- if (r1_bio->bios[i])
- atomic_inc(&r1_bio->remaining);
- for (i=0; i < conf->raid_disks; i++)
- if (r1_bio->bios[i]) {
- struct bio_vec *bvec;
- int j;
-
- bio = bio_clone(r1_bio->master_bio, GFP_NOIO);
- /* copy pages from the failed bio, as
- * this might be a write-behind device */
- __bio_for_each_segment(bvec, bio, j, 0)
- bvec->bv_page = bio_iovec_idx(r1_bio->bios[i], j)->bv_page;
- bio_put(r1_bio->bios[i]);
- bio->bi_sector = r1_bio->sector +
- conf->mirrors[i].rdev->data_offset;
- bio->bi_bdev = conf->mirrors[i].rdev->bdev;
- bio->bi_end_io = raid1_end_write_request;
- bio->bi_rw = WRITE | do_sync;
- bio->bi_private = r1_bio;
- r1_bio->bios[i] = bio;
- generic_make_request(bio);
- }
} else {
int disk;
@@ -1839,7 +1781,9 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
/* take from bio_init */
bio->bi_next = NULL;
+ bio->bi_flags &= ~(BIO_POOL_MASK-1);
bio->bi_flags |= 1 << BIO_UPTODATE;
+ bio->bi_comp_cpu = -1;
bio->bi_rw = READ;
bio->bi_vcnt = 0;
bio->bi_idx = 0;
@@ -1912,7 +1856,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
!test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery))
break;
BUG_ON(sync_blocks < (PAGE_SIZE>>9));
- if (len > (sync_blocks<<9))
+ if ((len >> 9) > sync_blocks)
len = sync_blocks<<9;
}
diff --git a/drivers/md/raid1.h b/drivers/md/raid1.h
index 5f2d443ae28a..adf8cfd73313 100644
--- a/drivers/md/raid1.h
+++ b/drivers/md/raid1.h
@@ -117,8 +117,6 @@ struct r1bio_s {
#define R1BIO_IsSync 1
#define R1BIO_Degraded 2
#define R1BIO_BehindIO 3
-#define R1BIO_Barrier 4
-#define R1BIO_BarrierRetry 5
/* For write-behind requests, we call bi_end_io when
* the last non-write-behind device completes, providing
* any write was successful. Otherwise we call when
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 84718383124d..f0d082f749be 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -800,12 +800,13 @@ static int make_request(mddev_t *mddev, struct bio * bio)
int chunk_sects = conf->chunk_mask + 1;
const int rw = bio_data_dir(bio);
const unsigned long do_sync = (bio->bi_rw & REQ_SYNC);
+ const unsigned long do_fua = (bio->bi_rw & REQ_FUA);
struct bio_list bl;
unsigned long flags;
mdk_rdev_t *blocked_rdev;
- if (unlikely(bio->bi_rw & REQ_HARDBARRIER)) {
- md_barrier_request(mddev, bio);
+ if (unlikely(bio->bi_rw & REQ_FLUSH)) {
+ md_flush_request(mddev, bio);
return 0;
}
@@ -965,7 +966,7 @@ static int make_request(mddev_t *mddev, struct bio * bio)
conf->mirrors[d].rdev->data_offset;
mbio->bi_bdev = conf->mirrors[d].rdev->bdev;
mbio->bi_end_io = raid10_end_write_request;
- mbio->bi_rw = WRITE | do_sync;
+ mbio->bi_rw = WRITE | do_sync | do_fua;
mbio->bi_private = r10_bio;
atomic_inc(&r10_bio->remaining);
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 69b0a169e43d..31140d1259dc 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -506,9 +506,12 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
int rw;
struct bio *bi;
mdk_rdev_t *rdev;
- if (test_and_clear_bit(R5_Wantwrite, &sh->dev[i].flags))
- rw = WRITE;
- else if (test_and_clear_bit(R5_Wantread, &sh->dev[i].flags))
+ if (test_and_clear_bit(R5_Wantwrite, &sh->dev[i].flags)) {
+ if (test_and_clear_bit(R5_WantFUA, &sh->dev[i].flags))
+ rw = WRITE_FUA;
+ else
+ rw = WRITE;
+ } else if (test_and_clear_bit(R5_Wantread, &sh->dev[i].flags))
rw = READ;
else
continue;
@@ -1031,6 +1034,8 @@ ops_run_biodrain(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
while (wbi && wbi->bi_sector <
dev->sector + STRIPE_SECTORS) {
+ if (wbi->bi_rw & REQ_FUA)
+ set_bit(R5_WantFUA, &dev->flags);
tx = async_copy_data(1, wbi, dev->page,
dev->sector, tx);
wbi = r5_next_bio(wbi, dev->sector);
@@ -1048,15 +1053,22 @@ static void ops_complete_reconstruct(void *stripe_head_ref)
int pd_idx = sh->pd_idx;
int qd_idx = sh->qd_idx;
int i;
+ bool fua = false;
pr_debug("%s: stripe %llu\n", __func__,
(unsigned long long)sh->sector);
+ for (i = disks; i--; )
+ fua |= test_bit(R5_WantFUA, &sh->dev[i].flags);
+
for (i = disks; i--; ) {
struct r5dev *dev = &sh->dev[i];
- if (dev->written || i == pd_idx || i == qd_idx)
+ if (dev->written || i == pd_idx || i == qd_idx) {
set_bit(R5_UPTODATE, &dev->flags);
+ if (fua)
+ set_bit(R5_WantFUA, &dev->flags);
+ }
}
if (sh->reconstruct_state == reconstruct_state_drain_run)
@@ -3281,7 +3293,7 @@ static void handle_stripe5(struct stripe_head *sh)
if (dec_preread_active) {
/* We delay this until after ops_run_io so that if make_request
- * is waiting on a barrier, it won't continue until the writes
+ * is waiting on a flush, it won't continue until the writes
* have actually been submitted.
*/
atomic_dec(&conf->preread_active_stripes);
@@ -3583,7 +3595,7 @@ static void handle_stripe6(struct stripe_head *sh)
if (dec_preread_active) {
/* We delay this until after ops_run_io so that if make_request
- * is waiting on a barrier, it won't continue until the writes
+ * is waiting on a flush, it won't continue until the writes
* have actually been submitted.
*/
atomic_dec(&conf->preread_active_stripes);
@@ -3978,14 +3990,8 @@ static int make_request(mddev_t *mddev, struct bio * bi)
const int rw = bio_data_dir(bi);
int remaining;
- if (unlikely(bi->bi_rw & REQ_HARDBARRIER)) {
- /* Drain all pending writes. We only really need
- * to ensure they have been submitted, but this is
- * easier.
- */
- mddev->pers->quiesce(mddev, 1);
- mddev->pers->quiesce(mddev, 0);
- md_barrier_request(mddev, bi);
+ if (unlikely(bi->bi_rw & REQ_FLUSH)) {
+ md_flush_request(mddev, bi);
return 0;
}
@@ -4103,7 +4109,7 @@ static int make_request(mddev_t *mddev, struct bio * bi)
finish_wait(&conf->wait_for_overlap, &w);
set_bit(STRIPE_HANDLE, &sh->state);
clear_bit(STRIPE_DELAYED, &sh->state);
- if (mddev->barrier &&
+ if ((bi->bi_rw & REQ_SYNC) &&
!test_and_set_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
atomic_inc(&conf->preread_active_stripes);
release_stripe(sh);
@@ -4126,13 +4132,6 @@ static int make_request(mddev_t *mddev, struct bio * bi)
bio_endio(bi, 0);
}
- if (mddev->barrier) {
- /* We need to wait for the stripes to all be handled.
- * So: wait for preread_active_stripes to drop to 0.
- */
- wait_event(mddev->thread->wqueue,
- atomic_read(&conf->preread_active_stripes) == 0);
- }
return 0;
}
diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h
index 36eaed5dfd6e..2ace0582b409 100644
--- a/drivers/md/raid5.h
+++ b/drivers/md/raid5.h
@@ -275,6 +275,7 @@ struct r6_state {
* filling
*/
#define R5_Wantdrain 13 /* dev->towrite needs to be drained */
+#define R5_WantFUA 14 /* Write should be FUA */
/*
* Write method
*/
diff --git a/drivers/media/IR/imon.c b/drivers/media/IR/imon.c
index c185422ef28c..faed5a332c71 100644
--- a/drivers/media/IR/imon.c
+++ b/drivers/media/IR/imon.c
@@ -151,7 +151,8 @@ static const struct file_operations vfd_fops = {
.owner = THIS_MODULE,
.open = &display_open,
.write = &vfd_write,
- .release = &display_close
+ .release = &display_close,
+ .llseek = noop_llseek,
};
/* lcd character device file operations */
@@ -159,7 +160,8 @@ static const struct file_operations lcd_fops = {
.owner = THIS_MODULE,
.open = &display_open,
.write = &lcd_write,
- .release = &display_close
+ .release = &display_close,
+ .llseek = noop_llseek,
};
enum {
diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c
index 7e82a9df726b..7961d59f5cac 100644
--- a/drivers/media/IR/ir-keytable.c
+++ b/drivers/media/IR/ir-keytable.c
@@ -319,7 +319,7 @@ static void ir_timer_keyup(unsigned long cookie)
* a keyup event might follow immediately after the keydown.
*/
spin_lock_irqsave(&ir->keylock, flags);
- if (time_is_after_eq_jiffies(ir->keyup_jiffies))
+ if (time_is_before_eq_jiffies(ir->keyup_jiffies))
ir_keyup(ir);
spin_unlock_irqrestore(&ir->keylock, flags);
}
@@ -510,6 +510,13 @@ int __ir_input_register(struct input_dev *input_dev,
(ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_IR_RAW) ?
" in raw mode" : "");
+ /*
+ * Default delay of 250ms is too short for some protocols, expecially
+ * since the timeout is currently set to 250ms. Increase it to 500ms,
+ * to avoid wrong repetition of the keycodes.
+ */
+ input_dev->rep[REP_DELAY] = 500;
+
return 0;
out_event:
diff --git a/drivers/media/IR/ir-lirc-codec.c b/drivers/media/IR/ir-lirc-codec.c
index 77b5946413c0..1983cd3f3994 100644
--- a/drivers/media/IR/ir-lirc-codec.c
+++ b/drivers/media/IR/ir-lirc-codec.c
@@ -235,6 +235,7 @@ static struct file_operations lirc_fops = {
.poll = lirc_dev_fop_poll,
.open = lirc_dev_fop_open,
.release = lirc_dev_fop_close,
+ .llseek = no_llseek,
};
static int ir_lirc_register(struct input_dev *input_dev)
@@ -267,7 +268,7 @@ static int ir_lirc_register(struct input_dev *input_dev)
features |= LIRC_CAN_SET_SEND_CARRIER;
if (ir_dev->props->s_tx_duty_cycle)
- features |= LIRC_CAN_SET_REC_DUTY_CYCLE;
+ features |= LIRC_CAN_SET_SEND_DUTY_CYCLE;
}
if (ir_dev->props->s_rx_carrier_range)
diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c
index 43094e7eccfa..8e0e1b1f8c87 100644
--- a/drivers/media/IR/ir-raw-event.c
+++ b/drivers/media/IR/ir-raw-event.c
@@ -279,9 +279,11 @@ int ir_raw_event_register(struct input_dev *input_dev)
"rc%u", (unsigned int)ir->devno);
if (IS_ERR(ir->raw->thread)) {
+ int ret = PTR_ERR(ir->raw->thread);
+
kfree(ir->raw);
ir->raw = NULL;
- return PTR_ERR(ir->raw->thread);
+ return ret;
}
mutex_lock(&ir_raw_handler_lock);
diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c
index 96dafc425c8e..46d42467f9b4 100644
--- a/drivers/media/IR/ir-sysfs.c
+++ b/drivers/media/IR/ir-sysfs.c
@@ -67,13 +67,14 @@ static ssize_t show_protocols(struct device *d,
char *tmp = buf;
int i;
- if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE) {
+ if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) {
enabled = ir_dev->rc_tab.ir_type;
allowed = ir_dev->props->allowed_protos;
- } else {
+ } else if (ir_dev->raw) {
enabled = ir_dev->raw->enabled_protocols;
allowed = ir_raw_get_allowed_protocols();
- }
+ } else
+ return sprintf(tmp, "[builtin]\n");
IR_dprintk(1, "allowed - 0x%llx, enabled - 0x%llx\n",
(long long)allowed,
@@ -121,10 +122,14 @@ static ssize_t store_protocols(struct device *d,
int rc, i, count = 0;
unsigned long flags;
- if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE)
+ if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE)
type = ir_dev->rc_tab.ir_type;
- else
+ else if (ir_dev->raw)
type = ir_dev->raw->enabled_protocols;
+ else {
+ IR_dprintk(1, "Protocol switching not supported\n");
+ return -EINVAL;
+ }
while ((tmp = strsep((char **) &data, " \n")) != NULL) {
if (!*tmp)
@@ -185,7 +190,7 @@ static ssize_t store_protocols(struct device *d,
}
}
- if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE) {
+ if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) {
spin_lock_irqsave(&ir_dev->rc_tab.lock, flags);
ir_dev->rc_tab.ir_type = type;
spin_unlock_irqrestore(&ir_dev->rc_tab.lock, flags);
diff --git a/drivers/media/IR/keymaps/rc-rc6-mce.c b/drivers/media/IR/keymaps/rc-rc6-mce.c
index 64264f7f838f..39557ad401b6 100644
--- a/drivers/media/IR/keymaps/rc-rc6-mce.c
+++ b/drivers/media/IR/keymaps/rc-rc6-mce.c
@@ -19,6 +19,7 @@ static struct ir_scancode rc6_mce[] = {
{ 0x800f0416, KEY_PLAY },
{ 0x800f0418, KEY_PAUSE },
+ { 0x800f046e, KEY_PLAYPAUSE },
{ 0x800f0419, KEY_STOP },
{ 0x800f0417, KEY_RECORD },
@@ -37,6 +38,8 @@ static struct ir_scancode rc6_mce[] = {
{ 0x800f0411, KEY_VOLUMEDOWN },
{ 0x800f0412, KEY_CHANNELUP },
{ 0x800f0413, KEY_CHANNELDOWN },
+ { 0x800f043a, KEY_BRIGHTNESSUP },
+ { 0x800f0480, KEY_BRIGHTNESSDOWN },
{ 0x800f0401, KEY_NUMERIC_1 },
{ 0x800f0402, KEY_NUMERIC_2 },
diff --git a/drivers/media/IR/lirc_dev.c b/drivers/media/IR/lirc_dev.c
index 899891bec352..0acf6396e068 100644
--- a/drivers/media/IR/lirc_dev.c
+++ b/drivers/media/IR/lirc_dev.c
@@ -163,6 +163,7 @@ static struct file_operations fops = {
.unlocked_ioctl = lirc_dev_fop_ioctl,
.open = lirc_dev_fop_open,
.release = lirc_dev_fop_close,
+ .llseek = noop_llseek,
};
static int lirc_cdev_add(struct irctl *ir)
@@ -460,6 +461,8 @@ error:
mutex_unlock(&lirc_dev_lock);
+ nonseekable_open(inode, file);
+
return retval;
}
EXPORT_SYMBOL(lirc_dev_fop_open);
diff --git a/drivers/media/IR/mceusb.c b/drivers/media/IR/mceusb.c
index ac6bb2c01a48..bc620e10ef77 100644
--- a/drivers/media/IR/mceusb.c
+++ b/drivers/media/IR/mceusb.c
@@ -120,6 +120,10 @@ static struct usb_device_id mceusb_dev_table[] = {
{ USB_DEVICE(VENDOR_PHILIPS, 0x0613) },
/* Philips eHome Infrared Transceiver */
{ USB_DEVICE(VENDOR_PHILIPS, 0x0815) },
+ /* Philips/Spinel plus IR transceiver for ASUS */
+ { USB_DEVICE(VENDOR_PHILIPS, 0x206c) },
+ /* Philips/Spinel plus IR transceiver for ASUS */
+ { USB_DEVICE(VENDOR_PHILIPS, 0x2088) },
/* Realtek MCE IR Receiver */
{ USB_DEVICE(VENDOR_REALTEK, 0x0161) },
/* SMK/Toshiba G83C0004D410 */
diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig
index a28541b2b1a2..bad2cedb8d96 100644
--- a/drivers/media/Kconfig
+++ b/drivers/media/Kconfig
@@ -19,6 +19,7 @@ comment "Multimedia core support"
config VIDEO_DEV
tristate "Video For Linux"
+ depends on BKL # used in many drivers for ioctl handling, need to kill
---help---
V4L core support for video capture and overlay devices, webcams and
AM/FM radio cards.
diff --git a/drivers/media/dvb/bt8xx/dst_ca.c b/drivers/media/dvb/bt8xx/dst_ca.c
index cf8705162845..48e48e8af55a 100644
--- a/drivers/media/dvb/bt8xx/dst_ca.c
+++ b/drivers/media/dvb/bt8xx/dst_ca.c
@@ -22,7 +22,7 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/init.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/string.h>
#include <linux/dvb/ca.h>
#include "dvbdev.h"
@@ -52,6 +52,7 @@
} while(0)
+static DEFINE_MUTEX(dst_ca_mutex);
static unsigned int verbose = 5;
module_param(verbose, int, 0644);
MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)");
@@ -564,7 +565,7 @@ static long dst_ca_ioctl(struct file *file, unsigned int cmd, unsigned long ioct
void __user *arg = (void __user *)ioctl_arg;
int result = 0;
- lock_kernel();
+ mutex_lock(&dst_ca_mutex);
dvbdev = file->private_data;
state = (struct dst_state *)dvbdev->priv;
p_ca_message = kmalloc(sizeof (struct ca_msg), GFP_KERNEL);
@@ -652,7 +653,7 @@ static long dst_ca_ioctl(struct file *file, unsigned int cmd, unsigned long ioct
kfree (p_ca_slot_info);
kfree (p_ca_caps);
- unlock_kernel();
+ mutex_unlock(&dst_ca_mutex);
return result;
}
@@ -694,7 +695,8 @@ static const struct file_operations dst_ca_fops = {
.open = dst_ca_open,
.release = dst_ca_release,
.read = dst_ca_read,
- .write = dst_ca_write
+ .write = dst_ca_write,
+ .llseek = noop_llseek,
};
static struct dvb_device dvbdev_ca = {
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index 0042306ea11b..ad1f61d301e1 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -25,7 +25,6 @@
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/module.h>
-#include <linux/smp_lock.h>
#include <linux/poll.h>
#include <linux/ioctl.h>
#include <linux/wait.h>
@@ -1088,13 +1087,7 @@ static int dvb_demux_do_ioctl(struct file *file,
static long dvb_demux_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
- int ret;
-
- lock_kernel();
- ret = dvb_usercopy(file, cmd, arg, dvb_demux_do_ioctl);
- unlock_kernel();
-
- return ret;
+ return dvb_usercopy(file, cmd, arg, dvb_demux_do_ioctl);
}
static unsigned int dvb_demux_poll(struct file *file, poll_table *wait)
@@ -1150,6 +1143,7 @@ static const struct file_operations dvb_demux_fops = {
.open = dvb_demux_open,
.release = dvb_demux_release,
.poll = dvb_demux_poll,
+ .llseek = default_llseek,
};
static struct dvb_device dvbdev_demux = {
@@ -1186,13 +1180,7 @@ static int dvb_dvr_do_ioctl(struct file *file,
static long dvb_dvr_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
- int ret;
-
- lock_kernel();
- ret = dvb_usercopy(file, cmd, arg, dvb_dvr_do_ioctl);
- unlock_kernel();
-
- return ret;
+ return dvb_usercopy(file, cmd, arg, dvb_dvr_do_ioctl);
}
static unsigned int dvb_dvr_poll(struct file *file, poll_table *wait)
@@ -1225,6 +1213,7 @@ static const struct file_operations dvb_dvr_fops = {
.open = dvb_dvr_open,
.release = dvb_dvr_release,
.poll = dvb_dvr_poll,
+ .llseek = default_llseek,
};
static struct dvb_device dvbdev_dvr = {
diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
index cb97e6b85432..4d0646da6087 100644
--- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
+++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
@@ -1259,13 +1259,7 @@ static int dvb_ca_en50221_io_do_ioctl(struct file *file,
static long dvb_ca_en50221_io_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
- int ret;
-
- lock_kernel();
- ret = dvb_usercopy(file, cmd, arg, dvb_ca_en50221_io_do_ioctl);
- unlock_kernel();
-
- return ret;
+ return dvb_usercopy(file, cmd, arg, dvb_ca_en50221_io_do_ioctl);
}
@@ -1628,6 +1622,7 @@ static const struct file_operations dvb_ca_fops = {
.open = dvb_ca_en50221_io_open,
.release = dvb_ca_en50221_io_release,
.poll = dvb_ca_en50221_io_poll,
+ .llseek = noop_llseek,
};
static struct dvb_device dvbdev_ca = {
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
index 4d45b7d6b3fb..970c9b8882d4 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -2034,7 +2034,8 @@ static const struct file_operations dvb_frontend_fops = {
.unlocked_ioctl = dvb_generic_ioctl,
.poll = dvb_frontend_poll,
.open = dvb_frontend_open,
- .release = dvb_frontend_release
+ .release = dvb_frontend_release,
+ .llseek = noop_llseek,
};
int dvb_register_frontend(struct dvb_adapter* dvb,
diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c
index 6c3a8a06ccab..4df42aaae7f7 100644
--- a/drivers/media/dvb/dvb-core/dvb_net.c
+++ b/drivers/media/dvb/dvb-core/dvb_net.c
@@ -59,7 +59,6 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/dvb/net.h>
-#include <linux/smp_lock.h>
#include <linux/uio.h>
#include <asm/uaccess.h>
#include <linux/crc32.h>
@@ -1445,13 +1444,7 @@ static int dvb_net_do_ioctl(struct file *file,
static long dvb_net_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
- int ret;
-
- lock_kernel();
- ret = dvb_usercopy(file, cmd, arg, dvb_net_do_ioctl);
- unlock_kernel();
-
- return ret;
+ return dvb_usercopy(file, cmd, arg, dvb_net_do_ioctl);
}
static int dvb_net_close(struct inode *inode, struct file *file)
@@ -1475,6 +1468,7 @@ static const struct file_operations dvb_net_fops = {
.unlocked_ioctl = dvb_net_ioctl,
.open = dvb_generic_open,
.release = dvb_net_close,
+ .llseek = noop_llseek,
};
static struct dvb_device dvbdev_net = {
diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c
index b915c39d782f..f73287775953 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.c
+++ b/drivers/media/dvb/dvb-core/dvbdev.c
@@ -32,9 +32,9 @@
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/mutex.h>
-#include <linux/smp_lock.h>
#include "dvbdev.h"
+static DEFINE_MUTEX(dvbdev_mutex);
static int dvbdev_debug;
module_param(dvbdev_debug, int, 0644);
@@ -68,7 +68,7 @@ static int dvb_device_open(struct inode *inode, struct file *file)
{
struct dvb_device *dvbdev;
- lock_kernel();
+ mutex_lock(&dvbdev_mutex);
down_read(&minor_rwsem);
dvbdev = dvb_minors[iminor(inode)];
@@ -91,12 +91,12 @@ static int dvb_device_open(struct inode *inode, struct file *file)
}
fops_put(old_fops);
up_read(&minor_rwsem);
- unlock_kernel();
+ mutex_unlock(&dvbdev_mutex);
return err;
}
fail:
up_read(&minor_rwsem);
- unlock_kernel();
+ mutex_unlock(&dvbdev_mutex);
return -ENODEV;
}
@@ -105,6 +105,7 @@ static const struct file_operations dvb_device_fops =
{
.owner = THIS_MODULE,
.open = dvb_device_open,
+ .llseek = noop_llseek,
};
static struct cdev dvb_device_cdev;
@@ -158,7 +159,6 @@ long dvb_generic_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
struct dvb_device *dvbdev = file->private_data;
- int ret;
if (!dvbdev)
return -ENODEV;
@@ -166,11 +166,7 @@ long dvb_generic_ioctl(struct file *file,
if (!dvbdev->kernel_ioctl)
return -EINVAL;
- lock_kernel();
- ret = dvb_usercopy(file, cmd, arg, dvbdev->kernel_ioctl);
- unlock_kernel();
-
- return ret;
+ return dvb_usercopy(file, cmd, arg, dvbdev->kernel_ioctl);
}
EXPORT_SYMBOL(dvb_generic_ioctl);
@@ -421,8 +417,10 @@ int dvb_usercopy(struct file *file,
}
/* call driver */
+ mutex_lock(&dvbdev_mutex);
if ((err = func(file, cmd, parg)) == -ENOIOCTLCMD)
err = -EINVAL;
+ mutex_unlock(&dvbdev_mutex);
if (err < 0)
goto out;
diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c
index fe818348b8a3..48397f103d32 100644
--- a/drivers/media/dvb/dvb-usb/dib0700_core.c
+++ b/drivers/media/dvb/dvb-usb/dib0700_core.c
@@ -673,9 +673,6 @@ static int dib0700_probe(struct usb_interface *intf,
else
dev->props.rc.core.bulk_mode = false;
- /* Need a higher delay, to avoid wrong repeat */
- dev->rc_input_dev->rep[REP_DELAY] = 500;
-
dib0700_rc_setup(dev);
return 0;
diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c
index f634d2e784b2..e06acd1fecb6 100644
--- a/drivers/media/dvb/dvb-usb/dib0700_devices.c
+++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c
@@ -940,6 +940,58 @@ static int stk7070p_frontend_attach(struct dvb_usb_adapter *adap)
return adap->fe == NULL ? -ENODEV : 0;
}
+/* STK7770P */
+static struct dib7000p_config dib7770p_dib7000p_config = {
+ .output_mpeg2_in_188_bytes = 1,
+
+ .agc_config_count = 1,
+ .agc = &dib7070_agc_config,
+ .bw = &dib7070_bw_config_12_mhz,
+ .tuner_is_baseband = 1,
+ .spur_protect = 1,
+
+ .gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS,
+ .gpio_val = DIB7000P_GPIO_DEFAULT_VALUES,
+ .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
+
+ .hostbus_diversity = 1,
+ .enable_current_mirror = 1,
+ .disable_sample_and_hold = 0,
+};
+
+static int stk7770p_frontend_attach(struct dvb_usb_adapter *adap)
+{
+ struct usb_device_descriptor *p = &adap->dev->udev->descriptor;
+ if (p->idVendor == cpu_to_le16(USB_VID_PINNACLE) &&
+ p->idProduct == cpu_to_le16(USB_PID_PINNACLE_PCTV72E))
+ dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
+ else
+ dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
+ msleep(10);
+ dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
+ dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
+ dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
+ dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
+
+ dib0700_ctrl_clock(adap->dev, 72, 1);
+
+ msleep(10);
+ dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
+ msleep(10);
+ dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
+
+ if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
+ &dib7770p_dib7000p_config) != 0) {
+ err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n",
+ __func__);
+ return -ENODEV;
+ }
+
+ adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
+ &dib7770p_dib7000p_config);
+ return adap->fe == NULL ? -ENODEV : 0;
+}
+
/* DIB807x generic */
static struct dibx000_agc_config dib807x_agc_config[2] = {
{
@@ -1781,7 +1833,7 @@ struct usb_device_id dib0700_usb_id_table[] = {
/* 60 */{ USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_XXS_2) },
{ USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK807XPVR) },
{ USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK807XP) },
- { USB_DEVICE(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD) },
+ { USB_DEVICE_VER(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD, 0x000, 0x3f00) },
{ USB_DEVICE(USB_VID_EVOLUTEPC, USB_PID_TVWAY_PLUS) },
/* 65 */{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV73ESE) },
{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV282E) },
@@ -2406,7 +2458,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.pid_filter_count = 32,
.pid_filter = stk70x0p_pid_filter,
.pid_filter_ctrl = stk70x0p_pid_filter_ctrl,
- .frontend_attach = stk7070p_frontend_attach,
+ .frontend_attach = stk7770p_frontend_attach,
.tuner_attach = dib7770p_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
diff --git a/drivers/media/dvb/dvb-usb/opera1.c b/drivers/media/dvb/dvb-usb/opera1.c
index 6b22ec64ab0c..f896337b4535 100644
--- a/drivers/media/dvb/dvb-usb/opera1.c
+++ b/drivers/media/dvb/dvb-usb/opera1.c
@@ -483,9 +483,7 @@ static int opera1_xilinx_load_firmware(struct usb_device *dev,
}
}
kfree(p);
- if (fw) {
- release_firmware(fw);
- }
+ release_firmware(fw);
return ret;
}
diff --git a/drivers/media/dvb/firewire/firedtv-ci.c b/drivers/media/dvb/firewire/firedtv-ci.c
index d3c2cf60de76..8ffb565f0704 100644
--- a/drivers/media/dvb/firewire/firedtv-ci.c
+++ b/drivers/media/dvb/firewire/firedtv-ci.c
@@ -220,6 +220,7 @@ static const struct file_operations fdtv_ca_fops = {
.open = dvb_generic_open,
.release = dvb_generic_release,
.poll = fdtv_ca_io_poll,
+ .llseek = noop_llseek,
};
static struct dvb_device fdtv_ca = {
diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb/frontends/dib7000p.c
index 2e28b973dfd3..3aed0d433921 100644
--- a/drivers/media/dvb/frontends/dib7000p.c
+++ b/drivers/media/dvb/frontends/dib7000p.c
@@ -260,6 +260,9 @@ static void dib7000p_set_adc_state(struct dib7000p_state *state, enum dibx000_ad
// dprintk( "908: %x, 909: %x\n", reg_908, reg_909);
+ reg_909 |= (state->cfg.disable_sample_and_hold & 1) << 4;
+ reg_908 |= (state->cfg.enable_current_mirror & 1) << 7;
+
dib7000p_write_word(state, 908, reg_908);
dib7000p_write_word(state, 909, reg_909);
}
@@ -778,7 +781,10 @@ static void dib7000p_set_channel(struct dib7000p_state *state, struct dvb_fronte
default:
case GUARD_INTERVAL_1_32: value *= 1; break;
}
- state->div_sync_wait = (value * 3) / 2 + 32; // add 50% SFN margin + compensate for one DVSY-fifo TODO
+ if (state->cfg.diversity_delay == 0)
+ state->div_sync_wait = (value * 3) / 2 + 48; // add 50% SFN margin + compensate for one DVSY-fifo
+ else
+ state->div_sync_wait = (value * 3) / 2 + state->cfg.diversity_delay; // add 50% SFN margin + compensate for one DVSY-fifo
/* deactive the possibility of diversity reception if extended interleaver */
state->div_force_off = !1 && ch->u.ofdm.transmission_mode != TRANSMISSION_MODE_8K;
diff --git a/drivers/media/dvb/frontends/dib7000p.h b/drivers/media/dvb/frontends/dib7000p.h
index 805dd13a97ee..da17345bf5bd 100644
--- a/drivers/media/dvb/frontends/dib7000p.h
+++ b/drivers/media/dvb/frontends/dib7000p.h
@@ -33,6 +33,11 @@ struct dib7000p_config {
int (*agc_control) (struct dvb_frontend *, u8 before);
u8 output_mode;
+ u8 disable_sample_and_hold : 1;
+
+ u8 enable_current_mirror : 1;
+ u8 diversity_delay;
+
};
#define DEFAULT_DIB7000P_I2C_ADDRESS 18
diff --git a/drivers/media/dvb/siano/smscoreapi.c b/drivers/media/dvb/siano/smscoreapi.c
index d93468cd3a85..ff3b0fa901b3 100644
--- a/drivers/media/dvb/siano/smscoreapi.c
+++ b/drivers/media/dvb/siano/smscoreapi.c
@@ -1098,33 +1098,26 @@ EXPORT_SYMBOL_GPL(smscore_onresponse);
*
* @return pointer to descriptor on success, NULL on error.
*/
-struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev)
+
+struct smscore_buffer_t *get_entry(struct smscore_device_t *coredev)
{
struct smscore_buffer_t *cb = NULL;
unsigned long flags;
- DEFINE_WAIT(wait);
-
spin_lock_irqsave(&coredev->bufferslock, flags);
-
- /* This function must return a valid buffer, since the buffer list is
- * finite, we check that there is an available buffer, if not, we wait
- * until such buffer become available.
- */
-
- prepare_to_wait(&coredev->buffer_mng_waitq, &wait, TASK_INTERRUPTIBLE);
- if (list_empty(&coredev->buffers)) {
- spin_unlock_irqrestore(&coredev->bufferslock, flags);
- schedule();
- spin_lock_irqsave(&coredev->bufferslock, flags);
+ if (!list_empty(&coredev->buffers)) {
+ cb = (struct smscore_buffer_t *) coredev->buffers.next;
+ list_del(&cb->entry);
}
+ spin_unlock_irqrestore(&coredev->bufferslock, flags);
+ return cb;
+}
- finish_wait(&coredev->buffer_mng_waitq, &wait);
-
- cb = (struct smscore_buffer_t *) coredev->buffers.next;
- list_del(&cb->entry);
+struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev)
+{
+ struct smscore_buffer_t *cb = NULL;
- spin_unlock_irqrestore(&coredev->bufferslock, flags);
+ wait_event(coredev->buffer_mng_waitq, (cb = get_entry(coredev)));
return cb;
}
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c
index a6be529eec5c..893fbc57c72f 100644
--- a/drivers/media/dvb/ttpci/av7110.c
+++ b/drivers/media/dvb/ttpci/av7110.c
@@ -730,6 +730,7 @@ static const struct file_operations dvb_osd_fops = {
.unlocked_ioctl = dvb_generic_ioctl,
.open = dvb_generic_open,
.release = dvb_generic_release,
+ .llseek = noop_llseek,
};
static struct dvb_device dvbdev_osd = {
diff --git a/drivers/media/dvb/ttpci/av7110_av.c b/drivers/media/dvb/ttpci/av7110_av.c
index 13efba942dac..6ef3996565ad 100644
--- a/drivers/media/dvb/ttpci/av7110_av.c
+++ b/drivers/media/dvb/ttpci/av7110_av.c
@@ -1521,6 +1521,7 @@ static const struct file_operations dvb_video_fops = {
.open = dvb_video_open,
.release = dvb_video_release,
.poll = dvb_video_poll,
+ .llseek = noop_llseek,
};
static struct dvb_device dvbdev_video = {
@@ -1539,6 +1540,7 @@ static const struct file_operations dvb_audio_fops = {
.open = dvb_audio_open,
.release = dvb_audio_release,
.poll = dvb_audio_poll,
+ .llseek = noop_llseek,
};
static struct dvb_device dvbdev_audio = {
diff --git a/drivers/media/dvb/ttpci/av7110_ca.c b/drivers/media/dvb/ttpci/av7110_ca.c
index 4eba35a018e3..43f61f2eca98 100644
--- a/drivers/media/dvb/ttpci/av7110_ca.c
+++ b/drivers/media/dvb/ttpci/av7110_ca.c
@@ -353,6 +353,7 @@ static const struct file_operations dvb_ca_fops = {
.open = dvb_ca_open,
.release = dvb_generic_release,
.poll = dvb_ca_poll,
+ .llseek = default_llseek,
};
static struct dvb_device dvbdev_ca = {
diff --git a/drivers/media/dvb/ttpci/av7110_ir.c b/drivers/media/dvb/ttpci/av7110_ir.c
index b070e88d8c6b..908f272fe26c 100644
--- a/drivers/media/dvb/ttpci/av7110_ir.c
+++ b/drivers/media/dvb/ttpci/av7110_ir.c
@@ -312,6 +312,7 @@ static ssize_t av7110_ir_proc_write(struct file *file, const char __user *buffer
static const struct file_operations av7110_ir_proc_fops = {
.owner = THIS_MODULE,
.write = av7110_ir_proc_write,
+ .llseek = noop_llseek,
};
/* interrupt handler */
diff --git a/drivers/media/radio/si470x/radio-si470x-i2c.c b/drivers/media/radio/si470x/radio-si470x-i2c.c
index 67a4ec8768a6..4ce541a5eb47 100644
--- a/drivers/media/radio/si470x/radio-si470x-i2c.c
+++ b/drivers/media/radio/si470x/radio-si470x-i2c.c
@@ -395,7 +395,7 @@ static int __devinit si470x_i2c_probe(struct i2c_client *client,
radio->registers[POWERCFG] = POWERCFG_ENABLE;
if (si470x_set_register(radio, POWERCFG) < 0) {
retval = -EIO;
- goto err_all;
+ goto err_video;
}
msleep(110);
diff --git a/drivers/media/video/cx231xx/Makefile b/drivers/media/video/cx231xx/Makefile
index 755dd0ce65ff..6f2b57384488 100644
--- a/drivers/media/video/cx231xx/Makefile
+++ b/drivers/media/video/cx231xx/Makefile
@@ -11,4 +11,5 @@ EXTRA_CFLAGS += -Idrivers/media/video
EXTRA_CFLAGS += -Idrivers/media/common/tuners
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-usb
diff --git a/drivers/media/video/cx231xx/cx231xx-cards.c b/drivers/media/video/cx231xx/cx231xx-cards.c
index 6bdc0ef18119..f2a4900014bc 100644
--- a/drivers/media/video/cx231xx/cx231xx-cards.c
+++ b/drivers/media/video/cx231xx/cx231xx-cards.c
@@ -32,6 +32,7 @@
#include <media/v4l2-chip-ident.h>
#include <media/cx25840.h>
+#include "dvb-usb-ids.h"
#include "xc5000.h"
#include "cx231xx.h"
@@ -175,6 +176,8 @@ struct usb_device_id cx231xx_id_table[] = {
.driver_info = CX231XX_BOARD_CNXT_RDE_250},
{USB_DEVICE(0x0572, 0x58A1),
.driver_info = CX231XX_BOARD_CNXT_RDU_250},
+ {USB_DEVICE_VER(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD, 0x4000,0x4fff),
+ .driver_info = CX231XX_BOARD_UNKNOWN},
{},
};
@@ -226,14 +229,16 @@ void cx231xx_pre_card_setup(struct cx231xx *dev)
dev->board.name, dev->model);
/* set the direction for GPIO pins */
- cx231xx_set_gpio_direction(dev, dev->board.tuner_gpio->bit, 1);
- cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit, 1);
- cx231xx_set_gpio_direction(dev, dev->board.tuner_sif_gpio, 1);
+ if (dev->board.tuner_gpio) {
+ cx231xx_set_gpio_direction(dev, dev->board.tuner_gpio->bit, 1);
+ cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit, 1);
+ cx231xx_set_gpio_direction(dev, dev->board.tuner_sif_gpio, 1);
- /* request some modules if any required */
+ /* request some modules if any required */
- /* reset the Tuner */
- cx231xx_gpio_set(dev, dev->board.tuner_gpio);
+ /* reset the Tuner */
+ cx231xx_gpio_set(dev, dev->board.tuner_gpio);
+ }
/* set the mode to Analog mode initially */
cx231xx_set_mode(dev, CX231XX_ANALOG_MODE);
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c
index 86ca8c2359dd..f5a3e74c3c7c 100644
--- a/drivers/media/video/cx25840/cx25840-core.c
+++ b/drivers/media/video/cx25840/cx25840-core.c
@@ -1996,7 +1996,7 @@ static int cx25840_probe(struct i2c_client *client,
state->volume = v4l2_ctrl_new_std(&state->hdl,
&cx25840_audio_ctrl_ops, V4L2_CID_AUDIO_VOLUME,
- 0, 65335, 65535 / 100, default_volume);
+ 0, 65535, 65535 / 100, default_volume);
state->mute = v4l2_ctrl_new_std(&state->hdl,
&cx25840_audio_ctrl_ops, V4L2_CID_AUDIO_MUTE,
0, 1, 1, 0);
diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig
index 99dbae117591..0fa85cbefbb1 100644
--- a/drivers/media/video/cx88/Kconfig
+++ b/drivers/media/video/cx88/Kconfig
@@ -17,7 +17,7 @@ config VIDEO_CX88
config VIDEO_CX88_ALSA
tristate "Conexant 2388x DMA audio support"
- depends on VIDEO_CX88 && SND && EXPERIMENTAL
+ depends on VIDEO_CX88 && SND
select SND_PCM
---help---
This is a video4linux driver for direct (DMA) audio on
diff --git a/drivers/media/video/dabusb.c b/drivers/media/video/dabusb.c
index 5b176bd7afdb..f3e25e91366d 100644
--- a/drivers/media/video/dabusb.c
+++ b/drivers/media/video/dabusb.c
@@ -32,7 +32,6 @@
#include <linux/list.h>
#include <linux/vmalloc.h>
#include <linux/slab.h>
-#include <linux/smp_lock.h>
#include <linux/init.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
@@ -621,7 +620,6 @@ static int dabusb_open (struct inode *inode, struct file *file)
if (devnum < DABUSB_MINOR || devnum >= (DABUSB_MINOR + NRDABUSB))
return -EIO;
- lock_kernel();
s = &dabusb[devnum - DABUSB_MINOR];
dbg("dabusb_open");
@@ -630,21 +628,17 @@ static int dabusb_open (struct inode *inode, struct file *file)
while (!s->usbdev || s->opened) {
mutex_unlock(&s->mutex);
- if (file->f_flags & O_NONBLOCK) {
+ if (file->f_flags & O_NONBLOCK)
return -EBUSY;
- }
msleep_interruptible(500);
- if (signal_pending (current)) {
- unlock_kernel();
+ if (signal_pending (current))
return -EAGAIN;
- }
mutex_lock(&s->mutex);
}
if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) {
mutex_unlock(&s->mutex);
dev_err(&s->usbdev->dev, "set_interface failed\n");
- unlock_kernel();
return -EINVAL;
}
s->opened = 1;
@@ -654,7 +648,6 @@ static int dabusb_open (struct inode *inode, struct file *file)
file->private_data = s;
r = nonseekable_open(inode, file);
- unlock_kernel();
return r;
}
@@ -689,17 +682,13 @@ static long dabusb_ioctl (struct file *file, unsigned int cmd, unsigned long arg
dbg("dabusb_ioctl");
- lock_kernel();
- if (s->remove_pending) {
- unlock_kernel();
+ if (s->remove_pending)
return -EIO;
- }
mutex_lock(&s->mutex);
if (!s->usbdev) {
mutex_unlock(&s->mutex);
- unlock_kernel();
return -EIO;
}
@@ -735,7 +724,6 @@ static long dabusb_ioctl (struct file *file, unsigned int cmd, unsigned long arg
break;
}
mutex_unlock(&s->mutex);
- unlock_kernel();
return ret;
}
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c
index b9846106913e..78abc1c1f9d5 100644
--- a/drivers/media/video/gspca/gspca.c
+++ b/drivers/media/video/gspca/gspca.c
@@ -223,6 +223,7 @@ static int alloc_and_submit_int_urb(struct gspca_dev *gspca_dev,
usb_rcvintpipe(dev, ep->bEndpointAddress),
buffer, buffer_len,
int_irq, (void *)gspca_dev, interval);
+ urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
gspca_dev->int_urb = urb;
ret = usb_submit_urb(urb, GFP_KERNEL);
if (ret < 0) {
diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c
index 83a718f0f3f9..9052d5702556 100644
--- a/drivers/media/video/gspca/sn9c20x.c
+++ b/drivers/media/video/gspca/sn9c20x.c
@@ -2357,8 +2357,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
(data[33] << 10);
avg_lum >>= 9;
atomic_set(&sd->avg_lum, avg_lum);
- gspca_frame_add(gspca_dev, LAST_PACKET,
- data, len);
+ gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
return;
}
if (gspca_dev->last_packet_type == LAST_PACKET) {
diff --git a/drivers/media/video/ivtv/ivtvfb.c b/drivers/media/video/ivtv/ivtvfb.c
index be03a712731c..f0316d02f09f 100644
--- a/drivers/media/video/ivtv/ivtvfb.c
+++ b/drivers/media/video/ivtv/ivtvfb.c
@@ -466,6 +466,8 @@ static int ivtvfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long ar
struct fb_vblank vblank;
u32 trace;
+ memset(&vblank, 0, sizeof(struct fb_vblank));
+
vblank.flags = FB_VBLANK_HAVE_COUNT |FB_VBLANK_HAVE_VCOUNT |
FB_VBLANK_HAVE_VSYNC;
trace = read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16;
diff --git a/drivers/media/video/mem2mem_testdev.c b/drivers/media/video/mem2mem_testdev.c
index 4525335f9bd4..a7210d981388 100644
--- a/drivers/media/video/mem2mem_testdev.c
+++ b/drivers/media/video/mem2mem_testdev.c
@@ -239,7 +239,7 @@ static int device_process(struct m2mtest_ctx *ctx,
return -EFAULT;
}
- if (in_buf->vb.size < out_buf->vb.size) {
+ if (in_buf->vb.size > out_buf->vb.size) {
v4l2_err(&dev->v4l2_dev, "Output buffer is too small\n");
return -EINVAL;
}
@@ -1014,6 +1014,7 @@ static int m2mtest_remove(struct platform_device *pdev)
v4l2_m2m_release(dev->m2m_dev);
del_timer_sync(&dev->timer);
video_unregister_device(dev->vfd);
+ video_device_release(dev->vfd);
v4l2_device_unregister(&dev->v4l2_dev);
kfree(dev);
diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c
index 758a4db27d65..c71af4e0e517 100644
--- a/drivers/media/video/mt9m111.c
+++ b/drivers/media/video/mt9m111.c
@@ -447,6 +447,9 @@ static int mt9m111_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
dev_dbg(&client->dev, "%s left=%d, top=%d, width=%d, height=%d\n",
__func__, rect.left, rect.top, rect.width, rect.height);
+ if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+
ret = mt9m111_make_rect(client, &rect);
if (!ret)
mt9m111->rect = rect;
@@ -466,12 +469,14 @@ static int mt9m111_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
static int mt9m111_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
{
+ if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+
a->bounds.left = MT9M111_MIN_DARK_COLS;
a->bounds.top = MT9M111_MIN_DARK_ROWS;
a->bounds.width = MT9M111_MAX_WIDTH;
a->bounds.height = MT9M111_MAX_HEIGHT;
a->defrect = a->bounds;
- a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
a->pixelaspect.numerator = 1;
a->pixelaspect.denominator = 1;
@@ -487,6 +492,7 @@ static int mt9m111_g_fmt(struct v4l2_subdev *sd,
mf->width = mt9m111->rect.width;
mf->height = mt9m111->rect.height;
mf->code = mt9m111->fmt->code;
+ mf->colorspace = mt9m111->fmt->colorspace;
mf->field = V4L2_FIELD_NONE;
return 0;
diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c
index e7cd23cd6394..b48473c7896b 100644
--- a/drivers/media/video/mt9v022.c
+++ b/drivers/media/video/mt9v022.c
@@ -402,9 +402,6 @@ static int mt9v022_s_fmt(struct v4l2_subdev *sd,
if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATC)
return -EINVAL;
break;
- case 0:
- /* No format change, only geometry */
- break;
default:
return -EINVAL;
}
diff --git a/drivers/media/video/mx2_camera.c b/drivers/media/video/mx2_camera.c
index 66ff174151b5..b6ea67221d1d 100644
--- a/drivers/media/video/mx2_camera.c
+++ b/drivers/media/video/mx2_camera.c
@@ -378,6 +378,9 @@ static void mx25_camera_frame_done(struct mx2_camera_dev *pcdev, int fb,
spin_lock_irqsave(&pcdev->lock, flags);
+ if (*fb_active == NULL)
+ goto out;
+
vb = &(*fb_active)->vb;
dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
vb, vb->baddr, vb->bsize);
@@ -402,6 +405,7 @@ static void mx25_camera_frame_done(struct mx2_camera_dev *pcdev, int fb,
*fb_active = buf;
+out:
spin_unlock_irqrestore(&pcdev->lock, flags);
}
diff --git a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c
index 1b992b847198..55ea914c7fcd 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c
@@ -513,7 +513,7 @@ int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *cptr,
if (ret >= 0) {
ret = pvr2_ctrl_range_check(cptr,*valptr);
}
- if (maskptr) *maskptr = ~0;
+ *maskptr = ~0;
} else if (cptr->info->type == pvr2_ctl_bool) {
ret = parse_token(ptr,len,valptr,boolNames,
ARRAY_SIZE(boolNames));
@@ -522,7 +522,7 @@ int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *cptr,
} else if (ret == 0) {
*valptr = (*valptr & 1) ? !0 : 0;
}
- if (maskptr) *maskptr = 1;
+ *maskptr = 1;
} else if (cptr->info->type == pvr2_ctl_enum) {
ret = parse_token(
ptr,len,valptr,
@@ -531,7 +531,7 @@ int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *cptr,
if (ret >= 0) {
ret = pvr2_ctrl_range_check(cptr,*valptr);
}
- if (maskptr) *maskptr = ~0;
+ *maskptr = ~0;
} else if (cptr->info->type == pvr2_ctl_bitmask) {
ret = parse_tlist(
ptr,len,maskptr,valptr,
diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c
index b151c7be8a50..6961c55baf9b 100644
--- a/drivers/media/video/s5p-fimc/fimc-core.c
+++ b/drivers/media/video/s5p-fimc/fimc-core.c
@@ -393,6 +393,37 @@ static void fimc_set_yuv_order(struct fimc_ctx *ctx)
dbg("ctx->out_order_1p= %d", ctx->out_order_1p);
}
+static void fimc_prepare_dma_offset(struct fimc_ctx *ctx, struct fimc_frame *f)
+{
+ struct samsung_fimc_variant *variant = ctx->fimc_dev->variant;
+
+ f->dma_offset.y_h = f->offs_h;
+ if (!variant->pix_hoff)
+ f->dma_offset.y_h *= (f->fmt->depth >> 3);
+
+ f->dma_offset.y_v = f->offs_v;
+
+ f->dma_offset.cb_h = f->offs_h;
+ f->dma_offset.cb_v = f->offs_v;
+
+ f->dma_offset.cr_h = f->offs_h;
+ f->dma_offset.cr_v = f->offs_v;
+
+ if (!variant->pix_hoff) {
+ if (f->fmt->planes_cnt == 3) {
+ f->dma_offset.cb_h >>= 1;
+ f->dma_offset.cr_h >>= 1;
+ }
+ if (f->fmt->color == S5P_FIMC_YCBCR420) {
+ f->dma_offset.cb_v >>= 1;
+ f->dma_offset.cr_v >>= 1;
+ }
+ }
+
+ dbg("in_offset: color= %d, y_h= %d, y_v= %d",
+ f->fmt->color, f->dma_offset.y_h, f->dma_offset.y_v);
+}
+
/**
* fimc_prepare_config - check dimensions, operation and color mode
* and pre-calculate offset and the scaling coefficients.
@@ -406,7 +437,6 @@ static int fimc_prepare_config(struct fimc_ctx *ctx, u32 flags)
{
struct fimc_frame *s_frame, *d_frame;
struct fimc_vid_buffer *buf = NULL;
- struct samsung_fimc_variant *variant = ctx->fimc_dev->variant;
int ret = 0;
s_frame = &ctx->s_frame;
@@ -419,61 +449,16 @@ static int fimc_prepare_config(struct fimc_ctx *ctx, u32 flags)
swap(d_frame->width, d_frame->height);
}
- /* Prepare the output offset ratios for scaler. */
- d_frame->dma_offset.y_h = d_frame->offs_h;
- if (!variant->pix_hoff)
- d_frame->dma_offset.y_h *= (d_frame->fmt->depth >> 3);
-
- d_frame->dma_offset.y_v = d_frame->offs_v;
-
- d_frame->dma_offset.cb_h = d_frame->offs_h;
- d_frame->dma_offset.cb_v = d_frame->offs_v;
-
- d_frame->dma_offset.cr_h = d_frame->offs_h;
- d_frame->dma_offset.cr_v = d_frame->offs_v;
+ /* Prepare the DMA offset ratios for scaler. */
+ fimc_prepare_dma_offset(ctx, &ctx->s_frame);
+ fimc_prepare_dma_offset(ctx, &ctx->d_frame);
- if (!variant->pix_hoff && d_frame->fmt->planes_cnt == 3) {
- d_frame->dma_offset.cb_h >>= 1;
- d_frame->dma_offset.cb_v >>= 1;
- d_frame->dma_offset.cr_h >>= 1;
- d_frame->dma_offset.cr_v >>= 1;
- }
-
- dbg("out offset: color= %d, y_h= %d, y_v= %d",
- d_frame->fmt->color,
- d_frame->dma_offset.y_h, d_frame->dma_offset.y_v);
-
- /* Prepare the input offset ratios for scaler. */
- s_frame->dma_offset.y_h = s_frame->offs_h;
- if (!variant->pix_hoff)
- s_frame->dma_offset.y_h *= (s_frame->fmt->depth >> 3);
- s_frame->dma_offset.y_v = s_frame->offs_v;
-
- s_frame->dma_offset.cb_h = s_frame->offs_h;
- s_frame->dma_offset.cb_v = s_frame->offs_v;
-
- s_frame->dma_offset.cr_h = s_frame->offs_h;
- s_frame->dma_offset.cr_v = s_frame->offs_v;
-
- if (!variant->pix_hoff && s_frame->fmt->planes_cnt == 3) {
- s_frame->dma_offset.cb_h >>= 1;
- s_frame->dma_offset.cb_v >>= 1;
- s_frame->dma_offset.cr_h >>= 1;
- s_frame->dma_offset.cr_v >>= 1;
- }
-
- dbg("in offset: color= %d, y_h= %d, y_v= %d",
- s_frame->fmt->color, s_frame->dma_offset.y_h,
- s_frame->dma_offset.y_v);
-
- fimc_set_yuv_order(ctx);
-
- /* Check against the scaler ratio. */
if (s_frame->height > (SCALER_MAX_VRATIO * d_frame->height) ||
s_frame->width > (SCALER_MAX_HRATIO * d_frame->width)) {
err("out of scaler range");
return -EINVAL;
}
+ fimc_set_yuv_order(ctx);
}
/* Input DMA mode is not allowed when the scaler is disabled. */
@@ -822,7 +807,8 @@ static int fimc_m2m_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
} else {
v4l2_err(&ctx->fimc_dev->m2m.v4l2_dev,
"Wrong buffer/video queue type (%d)\n", f->type);
- return -EINVAL;
+ ret = -EINVAL;
+ goto s_fmt_out;
}
pix = &f->fmt.pix;
@@ -1414,8 +1400,10 @@ static int fimc_probe(struct platform_device *pdev)
}
fimc->work_queue = create_workqueue(dev_name(&fimc->pdev->dev));
- if (!fimc->work_queue)
+ if (!fimc->work_queue) {
+ ret = -ENOMEM;
goto err_irq;
+ }
ret = fimc_register_m2m_device(fimc);
if (ret)
@@ -1492,6 +1480,7 @@ static struct samsung_fimc_variant fimc2_variant_s5p = {
};
static struct samsung_fimc_variant fimc01_variant_s5pv210 = {
+ .pix_hoff = 1,
.has_inp_rot = 1,
.has_out_rot = 1,
.min_inp_pixsize = 16,
@@ -1506,6 +1495,7 @@ static struct samsung_fimc_variant fimc01_variant_s5pv210 = {
};
static struct samsung_fimc_variant fimc2_variant_s5pv210 = {
+ .pix_hoff = 1,
.min_inp_pixsize = 16,
.min_out_pixsize = 32,
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
index ec697fcd406e..bb8d83d8ddaf 100644
--- a/drivers/media/video/saa7134/saa7134-cards.c
+++ b/drivers/media/video/saa7134/saa7134-cards.c
@@ -4323,13 +4323,13 @@ struct saa7134_board saa7134_boards[] = {
},
[SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM] = {
/* Beholder Intl. Ltd. 2008 */
- /*Dmitry Belimov <d.belimov@gmail.com> */
- .name = "Beholder BeholdTV Columbus TVFM",
+ /* Dmitry Belimov <d.belimov@gmail.com> */
+ .name = "Beholder BeholdTV Columbus TV/FM",
.audio_clock = 0x00187de7,
.tuner_type = TUNER_ALPS_TSBE5_PAL,
- .radio_type = UNSET,
- .tuner_addr = ADDR_UNSET,
- .radio_addr = ADDR_UNSET,
+ .radio_type = TUNER_TEA5767,
+ .tuner_addr = 0xc2 >> 1,
+ .radio_addr = 0xc0 >> 1,
.tda9887_conf = TDA9887_PRESENT,
.gpiomask = 0x000A8004,
.inputs = {{
diff --git a/drivers/media/video/saa7164/saa7164-buffer.c b/drivers/media/video/saa7164/saa7164-buffer.c
index 5713f3a4b76c..ddd25d32723d 100644
--- a/drivers/media/video/saa7164/saa7164-buffer.c
+++ b/drivers/media/video/saa7164/saa7164-buffer.c
@@ -136,10 +136,11 @@ ret:
int saa7164_buffer_dealloc(struct saa7164_tsport *port,
struct saa7164_buffer *buf)
{
- struct saa7164_dev *dev = port->dev;
+ struct saa7164_dev *dev;
- if ((buf == 0) || (port == 0))
+ if (!buf || !port)
return SAA_ERR_BAD_PARAMETER;
+ dev = port->dev;
dprintk(DBGLVL_BUF, "%s() deallocating buffer @ 0x%p\n", __func__, buf);
diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c
index 8bdd940f32e6..2ac85d8984f0 100644
--- a/drivers/media/video/uvc/uvc_driver.c
+++ b/drivers/media/video/uvc/uvc_driver.c
@@ -486,6 +486,12 @@ static int uvc_parse_format(struct uvc_device *dev,
max(frame->dwFrameInterval[0],
frame->dwDefaultFrameInterval));
+ if (dev->quirks & UVC_QUIRK_RESTRICT_FRAME_RATE) {
+ frame->bFrameIntervalType = 1;
+ frame->dwFrameInterval[0] =
+ frame->dwDefaultFrameInterval;
+ }
+
uvc_trace(UVC_TRACE_DESCR, "- %ux%u (%u.%u fps)\n",
frame->wWidth, frame->wHeight,
10000000/frame->dwDefaultFrameInterval,
@@ -2026,6 +2032,15 @@ static struct usb_device_id uvc_ids[] = {
.bInterfaceClass = USB_CLASS_VENDOR_SPEC,
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 0 },
+ /* Chicony CNF7129 (Asus EEE 100HE) */
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
+ | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = 0x04f2,
+ .idProduct = 0xb071,
+ .bInterfaceClass = USB_CLASS_VIDEO,
+ .bInterfaceSubClass = 1,
+ .bInterfaceProtocol = 0,
+ .driver_info = UVC_QUIRK_RESTRICT_FRAME_RATE },
/* Alcor Micro AU3820 (Future Boy PC USB Webcam) */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_INT_INFO,
@@ -2091,6 +2106,15 @@ static struct usb_device_id uvc_ids[] = {
.bInterfaceProtocol = 0,
.driver_info = UVC_QUIRK_PROBE_MINMAX
| UVC_QUIRK_PROBE_DEF },
+ /* IMC Networks (Medion Akoya) */
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
+ | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = 0x13d3,
+ .idProduct = 0x5103,
+ .bInterfaceClass = USB_CLASS_VIDEO,
+ .bInterfaceSubClass = 1,
+ .bInterfaceProtocol = 0,
+ .driver_info = UVC_QUIRK_STREAM_NO_FID },
/* Syntek (HP Spartan) */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_INT_INFO,
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h
index bdacf3beabf5..892e0e51916c 100644
--- a/drivers/media/video/uvc/uvcvideo.h
+++ b/drivers/media/video/uvc/uvcvideo.h
@@ -182,6 +182,7 @@ struct uvc_xu_control {
#define UVC_QUIRK_IGNORE_SELECTOR_UNIT 0x00000020
#define UVC_QUIRK_FIX_BANDWIDTH 0x00000080
#define UVC_QUIRK_PROBE_DEF 0x00000100
+#define UVC_QUIRK_RESTRICT_FRAME_RATE 0x00000200
/* Format flags */
#define UVC_FMT_FLAG_COMPRESSED 0x00000001
diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/video/v4l2-compat-ioctl32.c
index 073f01390cdd..86294ed35c9b 100644
--- a/drivers/media/video/v4l2-compat-ioctl32.c
+++ b/drivers/media/video/v4l2-compat-ioctl32.c
@@ -193,17 +193,24 @@ static int put_video_window32(struct video_window *kp, struct video_window32 __u
struct video_code32 {
char loadwhat[16]; /* name or tag of file being passed */
compat_int_t datasize;
- unsigned char *data;
+ compat_uptr_t data;
};
-static int get_microcode32(struct video_code *kp, struct video_code32 __user *up)
+static struct video_code __user *get_microcode32(struct video_code32 *kp)
{
- 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;
+ struct video_code __user *up;
+
+ up = compat_alloc_user_space(sizeof(*up));
+
+ /*
+ * NOTE! We don't actually care if these fail. If the
+ * user address is invalid, the native ioctl will do
+ * the error handling for us
+ */
+ (void) copy_to_user(up->loadwhat, kp->loadwhat, sizeof(up->loadwhat));
+ (void) put_user(kp->datasize, &up->datasize);
+ (void) put_user(compat_ptr(kp->data), &up->data);
+ return up;
}
#define VIDIOCGTUNER32 _IOWR('v', 4, struct video_tuner32)
@@ -739,7 +746,7 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
struct video_tuner vt;
struct video_buffer vb;
struct video_window vw;
- struct video_code vc;
+ struct video_code32 vc;
struct video_audio va;
#endif
struct v4l2_format v2f;
@@ -818,8 +825,11 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
break;
case VIDIOCSMICROCODE:
- err = get_microcode32(&karg.vc, up);
- compatible_arg = 0;
+ /* Copy the 32-bit "video_code32" to kernel space */
+ if (copy_from_user(&karg.vc, up, sizeof(karg.vc)))
+ return -EFAULT;
+ /* Convert the 32-bit version to a 64-bit version in user space */
+ up = get_microcode32(&karg.vc);
break;
case VIDIOCSFREQ:
diff --git a/drivers/media/video/videobuf-dma-contig.c b/drivers/media/video/videobuf-dma-contig.c
index 372b87efcd05..6ff9e4bac3ea 100644
--- a/drivers/media/video/videobuf-dma-contig.c
+++ b/drivers/media/video/videobuf-dma-contig.c
@@ -393,8 +393,10 @@ void videobuf_dma_contig_free(struct videobuf_queue *q,
}
/* read() method */
- dma_free_coherent(q->dev, mem->size, mem->vaddr, mem->dma_handle);
- mem->vaddr = NULL;
+ if (mem->vaddr) {
+ dma_free_coherent(q->dev, mem->size, mem->vaddr, mem->dma_handle);
+ mem->vaddr = NULL;
+ }
}
EXPORT_SYMBOL_GPL(videobuf_dma_contig_free);
diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c
index 06f9a9c2a39a..2ad0bc252b0e 100644
--- a/drivers/media/video/videobuf-dma-sg.c
+++ b/drivers/media/video/videobuf-dma-sg.c
@@ -94,7 +94,7 @@ err:
* must free the memory.
*/
static struct scatterlist *videobuf_pages_to_sg(struct page **pages,
- int nr_pages, int offset)
+ int nr_pages, int offset, size_t size)
{
struct scatterlist *sglist;
int i;
@@ -110,12 +110,14 @@ static struct scatterlist *videobuf_pages_to_sg(struct page **pages,
/* DMA to highmem pages might not work */
goto highmem;
sg_set_page(&sglist[0], pages[0], PAGE_SIZE - offset, offset);
+ size -= PAGE_SIZE - offset;
for (i = 1; i < nr_pages; i++) {
if (NULL == pages[i])
goto nopage;
if (PageHighMem(pages[i]))
goto highmem;
- sg_set_page(&sglist[i], pages[i], PAGE_SIZE, 0);
+ sg_set_page(&sglist[i], pages[i], min(PAGE_SIZE, size), 0);
+ size -= min(PAGE_SIZE, size);
}
return sglist;
@@ -170,7 +172,8 @@ static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma,
first = (data & PAGE_MASK) >> PAGE_SHIFT;
last = ((data+size-1) & PAGE_MASK) >> PAGE_SHIFT;
- dma->offset = data & ~PAGE_MASK;
+ dma->offset = data & ~PAGE_MASK;
+ dma->size = size;
dma->nr_pages = last-first+1;
dma->pages = kmalloc(dma->nr_pages * sizeof(struct page *), GFP_KERNEL);
if (NULL == dma->pages)
@@ -252,7 +255,7 @@ int videobuf_dma_map(struct device *dev, struct videobuf_dmabuf *dma)
if (dma->pages) {
dma->sglist = videobuf_pages_to_sg(dma->pages, dma->nr_pages,
- dma->offset);
+ dma->offset, dma->size);
}
if (dma->vaddr) {
dma->sglist = videobuf_vmalloc_to_sg(dma->vaddr,
diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c
index d3f1a087eced..02362eccc588 100644
--- a/drivers/memstick/core/mspro_block.c
+++ b/drivers/memstick/core/mspro_block.c
@@ -18,11 +18,12 @@
#include <linux/kthread.h>
#include <linux/delay.h>
#include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/memstick.h>
#define DRIVER_NAME "mspro_block"
+static DEFINE_MUTEX(mspro_block_mutex);
static int major;
module_param(major, int, 0644);
@@ -180,7 +181,7 @@ static int mspro_block_bd_open(struct block_device *bdev, fmode_t mode)
struct mspro_block_data *msb = disk->private_data;
int rc = -ENXIO;
- lock_kernel();
+ mutex_lock(&mspro_block_mutex);
mutex_lock(&mspro_block_disk_lock);
if (msb && msb->card) {
@@ -192,7 +193,7 @@ static int mspro_block_bd_open(struct block_device *bdev, fmode_t mode)
}
mutex_unlock(&mspro_block_disk_lock);
- unlock_kernel();
+ mutex_unlock(&mspro_block_mutex);
return rc;
}
@@ -225,9 +226,9 @@ static int mspro_block_disk_release(struct gendisk *disk)
static int mspro_block_bd_release(struct gendisk *disk, fmode_t mode)
{
int ret;
- lock_kernel();
+ mutex_lock(&mspro_block_mutex);
ret = mspro_block_disk_release(disk);
- unlock_kernel();
+ mutex_unlock(&mspro_block_mutex);
return ret;
}
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index 6837a8ef9371..3e57b61ca446 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -5945,8 +5945,10 @@ mpt_findImVolumes(MPT_ADAPTER *ioc)
goto out;
mem = kmalloc(iocpage2sz, GFP_KERNEL);
- if (!mem)
+ if (!mem) {
+ rc = -ENOMEM;
goto out;
+ }
memcpy(mem, (u8 *)pIoc2, iocpage2sz);
ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem;
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
index d8ddfdf8be14..a3856ed90aef 100644
--- a/drivers/message/fusion/mptctl.c
+++ b/drivers/message/fusion/mptctl.c
@@ -54,7 +54,7 @@
#include <linux/pci.h>
#include <linux/delay.h> /* for mdelay */
#include <linux/miscdevice.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/compat.h>
#include <asm/io.h>
@@ -83,6 +83,7 @@ MODULE_VERSION(my_VERSION);
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static DEFINE_MUTEX(mpctl_mutex);
static u8 mptctl_id = MPT_MAX_PROTOCOL_DRIVERS;
static u8 mptctl_taskmgmt_id = MPT_MAX_PROTOCOL_DRIVERS;
@@ -601,12 +602,12 @@ mptctl_fasync(int fd, struct file *filep, int mode)
MPT_ADAPTER *ioc;
int ret;
- lock_kernel();
+ mutex_lock(&mpctl_mutex);
list_for_each_entry(ioc, &ioc_list, list)
ioc->aen_event_read_flag=0;
ret = fasync_helper(fd, filep, mode, &async_queue);
- unlock_kernel();
+ mutex_unlock(&mpctl_mutex);
return ret;
}
@@ -698,9 +699,9 @@ static long
mptctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
long ret;
- lock_kernel();
+ mutex_lock(&mpctl_mutex);
ret = __mptctl_ioctl(file, cmd, arg);
- unlock_kernel();
+ mutex_unlock(&mpctl_mutex);
return ret;
}
@@ -2926,7 +2927,7 @@ compat_mpt_command(struct file *filp, unsigned int cmd,
static long compat_mpctl_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
{
long ret;
- lock_kernel();
+ mutex_lock(&mpctl_mutex);
switch (cmd) {
case MPTIOCINFO:
case MPTIOCINFO1:
@@ -2951,7 +2952,7 @@ static long compat_mpctl_ioctl(struct file *f, unsigned int cmd, unsigned long a
ret = -ENOIOCTLCMD;
break;
}
- unlock_kernel();
+ mutex_unlock(&mpctl_mutex);
return ret;
}
diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c
index f0f1e667000f..f87a9d405a5e 100644
--- a/drivers/message/i2o/i2o_block.c
+++ b/drivers/message/i2o/i2o_block.c
@@ -53,7 +53,7 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/i2o.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/mempool.h>
@@ -69,6 +69,7 @@
#define OSM_VERSION "1.325"
#define OSM_DESCRIPTION "I2O Block Device OSM"
+static DEFINE_MUTEX(i2o_block_mutex);
static struct i2o_driver i2o_block_driver;
/* global Block OSM request mempool */
@@ -578,7 +579,7 @@ static int i2o_block_open(struct block_device *bdev, fmode_t mode)
if (!dev->i2o_dev)
return -ENODEV;
- lock_kernel();
+ mutex_lock(&i2o_block_mutex);
if (dev->power > 0x1f)
i2o_block_device_power(dev, 0x02);
@@ -587,7 +588,7 @@ static int i2o_block_open(struct block_device *bdev, fmode_t mode)
i2o_block_device_lock(dev->i2o_dev, -1);
osm_debug("Ready.\n");
- unlock_kernel();
+ mutex_unlock(&i2o_block_mutex);
return 0;
};
@@ -618,7 +619,7 @@ static int i2o_block_release(struct gendisk *disk, fmode_t mode)
if (!dev->i2o_dev)
return 0;
- lock_kernel();
+ mutex_lock(&i2o_block_mutex);
i2o_block_device_flush(dev->i2o_dev);
i2o_block_device_unlock(dev->i2o_dev, -1);
@@ -629,7 +630,7 @@ static int i2o_block_release(struct gendisk *disk, fmode_t mode)
operation = 0x24;
i2o_block_device_power(dev, operation);
- unlock_kernel();
+ mutex_unlock(&i2o_block_mutex);
return 0;
}
@@ -664,7 +665,7 @@ static int i2o_block_ioctl(struct block_device *bdev, fmode_t mode,
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- lock_kernel();
+ mutex_lock(&i2o_block_mutex);
switch (cmd) {
case BLKI2OGRSTRAT:
ret = put_user(dev->rcache, (int __user *)arg);
@@ -688,7 +689,7 @@ static int i2o_block_ioctl(struct block_device *bdev, fmode_t mode,
ret = 0;
break;
}
- unlock_kernel();
+ mutex_unlock(&i2o_block_mutex);
return ret;
};
diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c
index 068ba0785bb4..7d3cc575c361 100644
--- a/drivers/message/i2o/i2o_config.c
+++ b/drivers/message/i2o/i2o_config.c
@@ -31,7 +31,7 @@
*/
#include <linux/miscdevice.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/compat.h>
#include <linux/slab.h>
@@ -41,6 +41,7 @@
#define SG_TABLESIZE 30
+static DEFINE_MUTEX(i2o_cfg_mutex);
static long i2o_cfg_ioctl(struct file *, unsigned int, unsigned long);
static spinlock_t i2o_config_lock;
@@ -741,7 +742,7 @@ static long i2o_cfg_compat_ioctl(struct file *file, unsigned cmd,
unsigned long arg)
{
int ret;
- lock_kernel();
+ mutex_lock(&i2o_cfg_mutex);
switch (cmd) {
case I2OGETIOPS:
ret = i2o_cfg_ioctl(file, cmd, arg);
@@ -753,7 +754,7 @@ static long i2o_cfg_compat_ioctl(struct file *file, unsigned cmd,
ret = -ENOIOCTLCMD;
break;
}
- unlock_kernel();
+ mutex_unlock(&i2o_cfg_mutex);
return ret;
}
@@ -981,7 +982,7 @@ static long i2o_cfg_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
{
int ret;
- lock_kernel();
+ mutex_lock(&i2o_cfg_mutex);
switch (cmd) {
case I2OGETIOPS:
ret = i2o_cfg_getiops(arg);
@@ -1037,7 +1038,7 @@ static long i2o_cfg_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
osm_debug("unknown ioctl called!\n");
ret = -EINVAL;
}
- unlock_kernel();
+ mutex_unlock(&i2o_cfg_mutex);
return ret;
}
@@ -1051,7 +1052,7 @@ static int cfg_open(struct inode *inode, struct file *file)
if (!tmp)
return -ENOMEM;
- lock_kernel();
+ mutex_lock(&i2o_cfg_mutex);
file->private_data = (void *)(i2o_cfg_info_id++);
tmp->fp = file;
tmp->fasync = NULL;
@@ -1065,7 +1066,7 @@ static int cfg_open(struct inode *inode, struct file *file)
spin_lock_irqsave(&i2o_config_lock, flags);
open_files = tmp;
spin_unlock_irqrestore(&i2o_config_lock, flags);
- unlock_kernel();
+ mutex_unlock(&i2o_cfg_mutex);
return 0;
}
@@ -1076,14 +1077,14 @@ static int cfg_fasync(int fd, struct file *fp, int on)
struct i2o_cfg_info *p;
int ret = -EBADF;
- lock_kernel();
+ mutex_lock(&i2o_cfg_mutex);
for (p = open_files; p; p = p->next)
if (p->q_id == id)
break;
if (p)
ret = fasync_helper(fd, fp, on, &p->fasync);
- unlock_kernel();
+ mutex_unlock(&i2o_cfg_mutex);
return ret;
}
@@ -1093,7 +1094,7 @@ static int cfg_release(struct inode *inode, struct file *file)
struct i2o_cfg_info *p, **q;
unsigned long flags;
- lock_kernel();
+ mutex_lock(&i2o_cfg_mutex);
spin_lock_irqsave(&i2o_config_lock, flags);
for (q = &open_files; (p = *q) != NULL; q = &p->next) {
if (p->q_id == id) {
@@ -1103,7 +1104,7 @@ static int cfg_release(struct inode *inode, struct file *file)
}
}
spin_unlock_irqrestore(&i2o_config_lock, flags);
- unlock_kernel();
+ mutex_unlock(&i2o_cfg_mutex);
return 0;
}
diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c
index 66379b413906..b048ecc56db9 100644
--- a/drivers/mfd/ab3100-core.c
+++ b/drivers/mfd/ab3100-core.c
@@ -583,6 +583,7 @@ static ssize_t ab3100_get_set_reg(struct file *file,
static const struct file_operations ab3100_get_set_reg_fops = {
.open = ab3100_get_set_reg_open_file,
.write = ab3100_get_set_reg,
+ .llseek = noop_llseek,
};
static struct dentry *ab3100_dir;
diff --git a/drivers/mfd/ab8500-spi.c b/drivers/mfd/ab8500-spi.c
index e1c8b62b086d..01b6d584442c 100644
--- a/drivers/mfd/ab8500-spi.c
+++ b/drivers/mfd/ab8500-spi.c
@@ -83,6 +83,11 @@ static int __devinit ab8500_spi_probe(struct spi_device *spi)
struct ab8500 *ab8500;
int ret;
+ spi->bits_per_word = 24;
+ ret = spi_setup(spi);
+ if (ret < 0)
+ return ret;
+
ab8500 = kzalloc(sizeof *ab8500, GFP_KERNEL);
if (!ab8500)
return -ENOMEM;
diff --git a/drivers/mfd/max8925-core.c b/drivers/mfd/max8925-core.c
index 04028a9ee082..428377a5a6f5 100644
--- a/drivers/mfd/max8925-core.c
+++ b/drivers/mfd/max8925-core.c
@@ -429,24 +429,25 @@ static void max8925_irq_sync_unlock(unsigned int irq)
irq_tsc = cache_tsc;
for (i = 0; i < ARRAY_SIZE(max8925_irqs); i++) {
irq_data = &max8925_irqs[i];
+ /* 1 -- disable, 0 -- enable */
switch (irq_data->mask_reg) {
case MAX8925_CHG_IRQ1_MASK:
- irq_chg[0] &= irq_data->enable;
+ irq_chg[0] &= ~irq_data->enable;
break;
case MAX8925_CHG_IRQ2_MASK:
- irq_chg[1] &= irq_data->enable;
+ irq_chg[1] &= ~irq_data->enable;
break;
case MAX8925_ON_OFF_IRQ1_MASK:
- irq_on[0] &= irq_data->enable;
+ irq_on[0] &= ~irq_data->enable;
break;
case MAX8925_ON_OFF_IRQ2_MASK:
- irq_on[1] &= irq_data->enable;
+ irq_on[1] &= ~irq_data->enable;
break;
case MAX8925_RTC_IRQ_MASK:
- irq_rtc &= irq_data->enable;
+ irq_rtc &= ~irq_data->enable;
break;
case MAX8925_TSC_IRQ_MASK:
- irq_tsc &= irq_data->enable;
+ irq_tsc &= ~irq_data->enable;
break;
default:
dev_err(chip->dev, "wrong IRQ\n");
diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c
index 097f24d8bceb..b9fda7018cef 100644
--- a/drivers/mfd/twl4030-irq.c
+++ b/drivers/mfd/twl4030-irq.c
@@ -78,7 +78,7 @@ struct sih {
u8 irq_lines; /* number of supported irq lines */
/* SIR ignored -- set interrupt, for testing only */
- struct irq_data {
+ struct sih_irq_data {
u8 isr_offset;
u8 imr_offset;
} mask[2];
@@ -810,7 +810,7 @@ int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end)
twl4030_irq_chip = dummy_irq_chip;
twl4030_irq_chip.name = "twl4030";
- twl4030_sih_irq_chip.ack = dummy_irq_chip.ack;
+ twl4030_sih_irq_chip.irq_ack = dummy_irq_chip.irq_ack;
for (i = irq_base; i < irq_end; i++) {
set_irq_chip_and_handler(i, &twl4030_irq_chip,
diff --git a/drivers/mfd/wm831x-irq.c b/drivers/mfd/wm831x-irq.c
index 7dabe4dbd373..294183b6260b 100644
--- a/drivers/mfd/wm831x-irq.c
+++ b/drivers/mfd/wm831x-irq.c
@@ -394,8 +394,13 @@ static int wm831x_irq_set_type(unsigned int irq, unsigned int type)
irq = irq - wm831x->irq_base;
- if (irq < WM831X_IRQ_GPIO_1 || irq > WM831X_IRQ_GPIO_11)
- return -EINVAL;
+ if (irq < WM831X_IRQ_GPIO_1 || irq > WM831X_IRQ_GPIO_11) {
+ /* Ignore internal-only IRQs */
+ if (irq >= 0 && irq < WM831X_NUM_IRQS)
+ return 0;
+ else
+ return -EINVAL;
+ }
switch (type) {
case IRQ_TYPE_EDGE_BOTH:
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index b74331260744..db2fbe2d4146 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -248,15 +248,15 @@ config CS5535_CLOCK_EVENT_SRC
generic PIT, and are suitable for use as high-res timers.
config HP_ILO
- tristate "Channel interface driver for HP iLO/iLO2 processor"
+ tristate "Channel interface driver for the HP iLO processor"
depends on PCI
default n
help
The channel interface driver allows applications to communicate
- with iLO/iLO2 management processors present on HP ProLiant
- servers. Upon loading, the driver creates /dev/hpilo/dXccbN files,
- which can be used to gather data from the management processor,
- via read and write system calls.
+ with iLO management processors present on HP ProLiant servers.
+ Upon loading, the driver creates /dev/hpilo/dXccbN files, which
+ can be used to gather data from the management processor, via
+ read and write system calls.
To compile this driver as a module, choose M here: the
module will be called hpilo.
@@ -390,6 +390,18 @@ config BMP085
To compile this driver as a module, choose M here: the
module will be called bmp085.
+config PCH_PHUB
+ tristate "PCH Packet Hub of Intel Topcliff"
+ depends on PCI
+ help
+ This driver is for PCH(Platform controller Hub) PHUB(Packet Hub) of
+ Intel Topcliff which is an IOH(Input/Output Hub) for x86 embedded
+ processor. The Topcliff has MAC address and Option ROM data in SROM.
+ This driver can access MAC address and Option ROM data in SROM.
+
+ To compile this driver as a module, choose M here: the module will
+ be called pch_phub.
+
source "drivers/misc/c2port/Kconfig"
source "drivers/misc/eeprom/Kconfig"
source "drivers/misc/cb710/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 42eab95cde2a..9f2986b4da2f 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -35,3 +35,4 @@ obj-y += eeprom/
obj-y += cb710/
obj-$(CONFIG_VMWARE_BALLOON) += vmw_balloon.o
obj-$(CONFIG_ARM_CHARLCD) += arm-charlcd.o
+obj-$(CONFIG_PCH_PHUB) += pch_phub.o
diff --git a/drivers/misc/bh1780gli.c b/drivers/misc/bh1780gli.c
index 714c6b487313..d5f3a3fd2319 100644
--- a/drivers/misc/bh1780gli.c
+++ b/drivers/misc/bh1780gli.c
@@ -190,7 +190,6 @@ static int __devexit bh1780_remove(struct i2c_client *client)
ddata = i2c_get_clientdata(client);
sysfs_remove_group(&client->dev.kobj, &bh1780_attr_group);
- i2c_set_clientdata(client, NULL);
kfree(ddata);
return 0;
diff --git a/drivers/misc/hpilo.c b/drivers/misc/hpilo.c
index 557a8c2a7336..fffc227181b0 100644
--- a/drivers/misc/hpilo.c
+++ b/drivers/misc/hpilo.c
@@ -1,5 +1,5 @@
/*
- * Driver for HP iLO/iLO2 management processor.
+ * Driver for the HP iLO management processor.
*
* Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
* David Altobelli <david.altobelli@hp.com>
@@ -640,6 +640,7 @@ static const struct file_operations ilo_fops = {
.poll = ilo_poll,
.open = ilo_open,
.release = ilo_close,
+ .llseek = noop_llseek,
};
static irqreturn_t ilo_isr(int irq, void *data)
diff --git a/drivers/misc/ibmasm/ibmasmfs.c b/drivers/misc/ibmasm/ibmasmfs.c
index 8844a3f45381..af2497ae5fe3 100644
--- a/drivers/misc/ibmasm/ibmasmfs.c
+++ b/drivers/misc/ibmasm/ibmasmfs.c
@@ -584,6 +584,7 @@ static const struct file_operations command_fops = {
.release = command_file_close,
.read = command_file_read,
.write = command_file_write,
+ .llseek = generic_file_llseek,
};
static const struct file_operations event_fops = {
@@ -591,6 +592,7 @@ static const struct file_operations event_fops = {
.release = event_file_close,
.read = event_file_read,
.write = event_file_write,
+ .llseek = generic_file_llseek,
};
static const struct file_operations r_heartbeat_fops = {
@@ -598,6 +600,7 @@ static const struct file_operations r_heartbeat_fops = {
.release = r_heartbeat_file_close,
.read = r_heartbeat_file_read,
.write = r_heartbeat_file_write,
+ .llseek = generic_file_llseek,
};
static const struct file_operations remote_settings_fops = {
@@ -605,6 +608,7 @@ static const struct file_operations remote_settings_fops = {
.release = remote_settings_file_close,
.read = remote_settings_file_read,
.write = remote_settings_file_write,
+ .llseek = generic_file_llseek,
};
diff --git a/drivers/misc/iwmc3200top/debugfs.c b/drivers/misc/iwmc3200top/debugfs.c
index e9eda471f6e0..62fbaec48207 100644
--- a/drivers/misc/iwmc3200top/debugfs.c
+++ b/drivers/misc/iwmc3200top/debugfs.c
@@ -71,6 +71,7 @@ ssize_t iwmct_dbgfs_##name##_write(struct file *file, \
static const struct file_operations iwmct_dbgfs_##name##_ops = { \
.read = iwmct_dbgfs_##name##_read, \
.open = iwmct_dbgfs_open_file_generic, \
+ .llseek = generic_file_llseek, \
};
#define DEBUGFS_WRITE_FILE_OPS(name) \
@@ -78,6 +79,7 @@ ssize_t iwmct_dbgfs_##name##_write(struct file *file, \
static const struct file_operations iwmct_dbgfs_##name##_ops = { \
.write = iwmct_dbgfs_##name##_write, \
.open = iwmct_dbgfs_open_file_generic, \
+ .llseek = generic_file_llseek, \
};
#define DEBUGFS_READ_WRITE_FILE_OPS(name) \
@@ -87,6 +89,7 @@ ssize_t iwmct_dbgfs_##name##_write(struct file *file, \
.write = iwmct_dbgfs_##name##_write, \
.read = iwmct_dbgfs_##name##_read, \
.open = iwmct_dbgfs_open_file_generic, \
+ .llseek = generic_file_llseek, \
};
diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c
index ef34de7a8026..343b5d8ea697 100644
--- a/drivers/misc/lkdtm.c
+++ b/drivers/misc/lkdtm.c
@@ -575,30 +575,39 @@ struct crash_entry {
static const struct crash_entry crash_entries[] = {
{"DIRECT", {.read = lkdtm_debugfs_read,
+ .llseek = generic_file_llseek,
.open = lkdtm_debugfs_open,
.write = direct_entry} },
{"INT_HARDWARE_ENTRY", {.read = lkdtm_debugfs_read,
+ .llseek = generic_file_llseek,
.open = lkdtm_debugfs_open,
.write = int_hardware_entry} },
{"INT_HW_IRQ_EN", {.read = lkdtm_debugfs_read,
+ .llseek = generic_file_llseek,
.open = lkdtm_debugfs_open,
.write = int_hw_irq_en} },
{"INT_TASKLET_ENTRY", {.read = lkdtm_debugfs_read,
+ .llseek = generic_file_llseek,
.open = lkdtm_debugfs_open,
.write = int_tasklet_entry} },
{"FS_DEVRW", {.read = lkdtm_debugfs_read,
+ .llseek = generic_file_llseek,
.open = lkdtm_debugfs_open,
.write = fs_devrw_entry} },
{"MEM_SWAPOUT", {.read = lkdtm_debugfs_read,
+ .llseek = generic_file_llseek,
.open = lkdtm_debugfs_open,
.write = mem_swapout_entry} },
{"TIMERADD", {.read = lkdtm_debugfs_read,
+ .llseek = generic_file_llseek,
.open = lkdtm_debugfs_open,
.write = timeradd_entry} },
{"SCSI_DISPATCH_CMD", {.read = lkdtm_debugfs_read,
+ .llseek = generic_file_llseek,
.open = lkdtm_debugfs_open,
.write = scsi_dispatch_cmd_entry} },
{"IDE_CORE_CP", {.read = lkdtm_debugfs_read,
+ .llseek = generic_file_llseek,
.open = lkdtm_debugfs_open,
.write = ide_core_cp_entry} },
};
diff --git a/drivers/misc/pch_phub.c b/drivers/misc/pch_phub.c
new file mode 100644
index 000000000000..744b804aca15
--- /dev/null
+++ b/drivers/misc/pch_phub.c
@@ -0,0 +1,717 @@
+/*
+ * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/if_ether.h>
+#include <linux/ctype.h>
+
+#define PHUB_STATUS 0x00 /* Status Register offset */
+#define PHUB_CONTROL 0x04 /* Control Register offset */
+#define PHUB_TIMEOUT 0x05 /* Time out value for Status Register */
+#define PCH_PHUB_ROM_WRITE_ENABLE 0x01 /* Enabling for writing ROM */
+#define PCH_PHUB_ROM_WRITE_DISABLE 0x00 /* Disabling for writing ROM */
+#define PCH_PHUB_ROM_START_ADDR 0x14 /* ROM data area start address offset */
+
+/* MAX number of INT_REDUCE_CONTROL registers */
+#define MAX_NUM_INT_REDUCE_CONTROL_REG 128
+#define PCI_DEVICE_ID_PCH1_PHUB 0x8801
+#define PCH_MINOR_NOS 1
+#define CLKCFG_CAN_50MHZ 0x12000000
+#define CLKCFG_CANCLK_MASK 0xFF000000
+
+/* SROM ACCESS Macro */
+#define PCH_WORD_ADDR_MASK (~((1 << 2) - 1))
+
+/* Registers address offset */
+#define PCH_PHUB_ID_REG 0x0000
+#define PCH_PHUB_QUEUE_PRI_VAL_REG 0x0004
+#define PCH_PHUB_RC_QUEUE_MAXSIZE_REG 0x0008
+#define PCH_PHUB_BRI_QUEUE_MAXSIZE_REG 0x000C
+#define PCH_PHUB_COMP_RESP_TIMEOUT_REG 0x0010
+#define PCH_PHUB_BUS_SLAVE_CONTROL_REG 0x0014
+#define PCH_PHUB_DEADLOCK_AVOID_TYPE_REG 0x0018
+#define PCH_PHUB_INTPIN_REG_WPERMIT_REG0 0x0020
+#define PCH_PHUB_INTPIN_REG_WPERMIT_REG1 0x0024
+#define PCH_PHUB_INTPIN_REG_WPERMIT_REG2 0x0028
+#define PCH_PHUB_INTPIN_REG_WPERMIT_REG3 0x002C
+#define PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE 0x0040
+#define CLKCFG_REG_OFFSET 0x500
+
+#define PCH_PHUB_OROM_SIZE 15360
+
+/**
+ * struct pch_phub_reg - PHUB register structure
+ * @phub_id_reg: PHUB_ID register val
+ * @q_pri_val_reg: QUEUE_PRI_VAL register val
+ * @rc_q_maxsize_reg: RC_QUEUE_MAXSIZE register val
+ * @bri_q_maxsize_reg: BRI_QUEUE_MAXSIZE register val
+ * @comp_resp_timeout_reg: COMP_RESP_TIMEOUT register val
+ * @bus_slave_control_reg: BUS_SLAVE_CONTROL_REG register val
+ * @deadlock_avoid_type_reg: DEADLOCK_AVOID_TYPE register val
+ * @intpin_reg_wpermit_reg0: INTPIN_REG_WPERMIT register 0 val
+ * @intpin_reg_wpermit_reg1: INTPIN_REG_WPERMIT register 1 val
+ * @intpin_reg_wpermit_reg2: INTPIN_REG_WPERMIT register 2 val
+ * @intpin_reg_wpermit_reg3: INTPIN_REG_WPERMIT register 3 val
+ * @int_reduce_control_reg: INT_REDUCE_CONTROL registers val
+ * @clkcfg_reg: CLK CFG register val
+ * @pch_phub_base_address: Register base address
+ * @pch_phub_extrom_base_address: external rom base address
+ */
+struct pch_phub_reg {
+ u32 phub_id_reg;
+ u32 q_pri_val_reg;
+ u32 rc_q_maxsize_reg;
+ u32 bri_q_maxsize_reg;
+ u32 comp_resp_timeout_reg;
+ u32 bus_slave_control_reg;
+ u32 deadlock_avoid_type_reg;
+ u32 intpin_reg_wpermit_reg0;
+ u32 intpin_reg_wpermit_reg1;
+ u32 intpin_reg_wpermit_reg2;
+ u32 intpin_reg_wpermit_reg3;
+ u32 int_reduce_control_reg[MAX_NUM_INT_REDUCE_CONTROL_REG];
+ u32 clkcfg_reg;
+ void __iomem *pch_phub_base_address;
+ void __iomem *pch_phub_extrom_base_address;
+};
+
+/* SROM SPEC for MAC address assignment offset */
+static const int pch_phub_mac_offset[ETH_ALEN] = {0x3, 0x2, 0x1, 0x0, 0xb, 0xa};
+
+static DEFINE_MUTEX(pch_phub_mutex);
+
+/**
+ * pch_phub_read_modify_write_reg() - Reading modifying and writing register
+ * @reg_addr_offset: Register offset address value.
+ * @data: Writing value.
+ * @mask: Mask value.
+ */
+static void pch_phub_read_modify_write_reg(struct pch_phub_reg *chip,
+ unsigned int reg_addr_offset,
+ unsigned int data, unsigned int mask)
+{
+ void __iomem *reg_addr = chip->pch_phub_base_address + reg_addr_offset;
+ iowrite32(((ioread32(reg_addr) & ~mask)) | data, reg_addr);
+}
+
+/* pch_phub_save_reg_conf - saves register configuration */
+static void pch_phub_save_reg_conf(struct pci_dev *pdev)
+{
+ unsigned int i;
+ struct pch_phub_reg *chip = pci_get_drvdata(pdev);
+
+ void __iomem *p = chip->pch_phub_base_address;
+
+ chip->phub_id_reg = ioread32(p + PCH_PHUB_ID_REG);
+ chip->q_pri_val_reg = ioread32(p + PCH_PHUB_QUEUE_PRI_VAL_REG);
+ chip->rc_q_maxsize_reg = ioread32(p + PCH_PHUB_RC_QUEUE_MAXSIZE_REG);
+ chip->bri_q_maxsize_reg = ioread32(p + PCH_PHUB_BRI_QUEUE_MAXSIZE_REG);
+ chip->comp_resp_timeout_reg =
+ ioread32(p + PCH_PHUB_COMP_RESP_TIMEOUT_REG);
+ chip->bus_slave_control_reg =
+ ioread32(p + PCH_PHUB_BUS_SLAVE_CONTROL_REG);
+ chip->deadlock_avoid_type_reg =
+ ioread32(p + PCH_PHUB_DEADLOCK_AVOID_TYPE_REG);
+ chip->intpin_reg_wpermit_reg0 =
+ ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG0);
+ chip->intpin_reg_wpermit_reg1 =
+ ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG1);
+ chip->intpin_reg_wpermit_reg2 =
+ ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG2);
+ chip->intpin_reg_wpermit_reg3 =
+ ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG3);
+ dev_dbg(&pdev->dev, "%s : "
+ "chip->phub_id_reg=%x, "
+ "chip->q_pri_val_reg=%x, "
+ "chip->rc_q_maxsize_reg=%x, "
+ "chip->bri_q_maxsize_reg=%x, "
+ "chip->comp_resp_timeout_reg=%x, "
+ "chip->bus_slave_control_reg=%x, "
+ "chip->deadlock_avoid_type_reg=%x, "
+ "chip->intpin_reg_wpermit_reg0=%x, "
+ "chip->intpin_reg_wpermit_reg1=%x, "
+ "chip->intpin_reg_wpermit_reg2=%x, "
+ "chip->intpin_reg_wpermit_reg3=%x\n", __func__,
+ chip->phub_id_reg,
+ chip->q_pri_val_reg,
+ chip->rc_q_maxsize_reg,
+ chip->bri_q_maxsize_reg,
+ chip->comp_resp_timeout_reg,
+ chip->bus_slave_control_reg,
+ chip->deadlock_avoid_type_reg,
+ chip->intpin_reg_wpermit_reg0,
+ chip->intpin_reg_wpermit_reg1,
+ chip->intpin_reg_wpermit_reg2,
+ chip->intpin_reg_wpermit_reg3);
+ for (i = 0; i < MAX_NUM_INT_REDUCE_CONTROL_REG; i++) {
+ chip->int_reduce_control_reg[i] =
+ ioread32(p + PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE + 4 * i);
+ dev_dbg(&pdev->dev, "%s : "
+ "chip->int_reduce_control_reg[%d]=%x\n",
+ __func__, i, chip->int_reduce_control_reg[i]);
+ }
+ chip->clkcfg_reg = ioread32(p + CLKCFG_REG_OFFSET);
+}
+
+/* pch_phub_restore_reg_conf - restore register configuration */
+static void pch_phub_restore_reg_conf(struct pci_dev *pdev)
+{
+ unsigned int i;
+ struct pch_phub_reg *chip = pci_get_drvdata(pdev);
+ void __iomem *p;
+ p = chip->pch_phub_base_address;
+
+ iowrite32(chip->phub_id_reg, p + PCH_PHUB_ID_REG);
+ iowrite32(chip->q_pri_val_reg, p + PCH_PHUB_QUEUE_PRI_VAL_REG);
+ iowrite32(chip->rc_q_maxsize_reg, p + PCH_PHUB_RC_QUEUE_MAXSIZE_REG);
+ iowrite32(chip->bri_q_maxsize_reg, p + PCH_PHUB_BRI_QUEUE_MAXSIZE_REG);
+ iowrite32(chip->comp_resp_timeout_reg,
+ p + PCH_PHUB_COMP_RESP_TIMEOUT_REG);
+ iowrite32(chip->bus_slave_control_reg,
+ p + PCH_PHUB_BUS_SLAVE_CONTROL_REG);
+ iowrite32(chip->deadlock_avoid_type_reg,
+ p + PCH_PHUB_DEADLOCK_AVOID_TYPE_REG);
+ iowrite32(chip->intpin_reg_wpermit_reg0,
+ p + PCH_PHUB_INTPIN_REG_WPERMIT_REG0);
+ iowrite32(chip->intpin_reg_wpermit_reg1,
+ p + PCH_PHUB_INTPIN_REG_WPERMIT_REG1);
+ iowrite32(chip->intpin_reg_wpermit_reg2,
+ p + PCH_PHUB_INTPIN_REG_WPERMIT_REG2);
+ iowrite32(chip->intpin_reg_wpermit_reg3,
+ p + PCH_PHUB_INTPIN_REG_WPERMIT_REG3);
+ dev_dbg(&pdev->dev, "%s : "
+ "chip->phub_id_reg=%x, "
+ "chip->q_pri_val_reg=%x, "
+ "chip->rc_q_maxsize_reg=%x, "
+ "chip->bri_q_maxsize_reg=%x, "
+ "chip->comp_resp_timeout_reg=%x, "
+ "chip->bus_slave_control_reg=%x, "
+ "chip->deadlock_avoid_type_reg=%x, "
+ "chip->intpin_reg_wpermit_reg0=%x, "
+ "chip->intpin_reg_wpermit_reg1=%x, "
+ "chip->intpin_reg_wpermit_reg2=%x, "
+ "chip->intpin_reg_wpermit_reg3=%x\n", __func__,
+ chip->phub_id_reg,
+ chip->q_pri_val_reg,
+ chip->rc_q_maxsize_reg,
+ chip->bri_q_maxsize_reg,
+ chip->comp_resp_timeout_reg,
+ chip->bus_slave_control_reg,
+ chip->deadlock_avoid_type_reg,
+ chip->intpin_reg_wpermit_reg0,
+ chip->intpin_reg_wpermit_reg1,
+ chip->intpin_reg_wpermit_reg2,
+ chip->intpin_reg_wpermit_reg3);
+ for (i = 0; i < MAX_NUM_INT_REDUCE_CONTROL_REG; i++) {
+ iowrite32(chip->int_reduce_control_reg[i],
+ p + PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE + 4 * i);
+ dev_dbg(&pdev->dev, "%s : "
+ "chip->int_reduce_control_reg[%d]=%x\n",
+ __func__, i, chip->int_reduce_control_reg[i]);
+ }
+
+ iowrite32(chip->clkcfg_reg, p + CLKCFG_REG_OFFSET);
+}
+
+/**
+ * pch_phub_read_serial_rom() - Reading Serial ROM
+ * @offset_address: Serial ROM offset address to read.
+ * @data: Read buffer for specified Serial ROM value.
+ */
+static void pch_phub_read_serial_rom(struct pch_phub_reg *chip,
+ unsigned int offset_address, u8 *data)
+{
+ void __iomem *mem_addr = chip->pch_phub_extrom_base_address +
+ offset_address;
+
+ *data = ioread8(mem_addr);
+}
+
+/**
+ * pch_phub_write_serial_rom() - Writing Serial ROM
+ * @offset_address: Serial ROM offset address.
+ * @data: Serial ROM value to write.
+ */
+static int pch_phub_write_serial_rom(struct pch_phub_reg *chip,
+ unsigned int offset_address, u8 data)
+{
+ void __iomem *mem_addr = chip->pch_phub_extrom_base_address +
+ (offset_address & PCH_WORD_ADDR_MASK);
+ int i;
+ unsigned int word_data;
+ unsigned int pos;
+ unsigned int mask;
+ pos = (offset_address % 4) * 8;
+ mask = ~(0xFF << pos);
+
+ iowrite32(PCH_PHUB_ROM_WRITE_ENABLE,
+ chip->pch_phub_extrom_base_address + PHUB_CONTROL);
+
+ word_data = ioread32(mem_addr);
+ iowrite32((word_data & mask) | (u32)data << pos, mem_addr);
+
+ i = 0;
+ while (ioread8(chip->pch_phub_extrom_base_address +
+ PHUB_STATUS) != 0x00) {
+ msleep(1);
+ if (i == PHUB_TIMEOUT)
+ return -ETIMEDOUT;
+ i++;
+ }
+
+ iowrite32(PCH_PHUB_ROM_WRITE_DISABLE,
+ chip->pch_phub_extrom_base_address + PHUB_CONTROL);
+
+ return 0;
+}
+
+/**
+ * pch_phub_read_serial_rom_val() - Read Serial ROM value
+ * @offset_address: Serial ROM address offset value.
+ * @data: Serial ROM value to read.
+ */
+static void pch_phub_read_serial_rom_val(struct pch_phub_reg *chip,
+ unsigned int offset_address, u8 *data)
+{
+ unsigned int mem_addr;
+
+ mem_addr = PCH_PHUB_ROM_START_ADDR +
+ pch_phub_mac_offset[offset_address];
+
+ pch_phub_read_serial_rom(chip, mem_addr, data);
+}
+
+/**
+ * pch_phub_write_serial_rom_val() - writing Serial ROM value
+ * @offset_address: Serial ROM address offset value.
+ * @data: Serial ROM value.
+ */
+static int pch_phub_write_serial_rom_val(struct pch_phub_reg *chip,
+ unsigned int offset_address, u8 data)
+{
+ int retval;
+ unsigned int mem_addr;
+
+ mem_addr = PCH_PHUB_ROM_START_ADDR +
+ pch_phub_mac_offset[offset_address];
+
+ retval = pch_phub_write_serial_rom(chip, mem_addr, data);
+
+ return retval;
+}
+
+/* pch_phub_gbe_serial_rom_conf - makes Serial ROM header format configuration
+ * for Gigabit Ethernet MAC address
+ */
+static int pch_phub_gbe_serial_rom_conf(struct pch_phub_reg *chip)
+{
+ int retval;
+
+ retval = pch_phub_write_serial_rom(chip, 0x0b, 0xbc);
+ retval |= pch_phub_write_serial_rom(chip, 0x0a, 0x10);
+ retval |= pch_phub_write_serial_rom(chip, 0x09, 0x01);
+ retval |= pch_phub_write_serial_rom(chip, 0x08, 0x02);
+
+ retval |= pch_phub_write_serial_rom(chip, 0x0f, 0x00);
+ retval |= pch_phub_write_serial_rom(chip, 0x0e, 0x00);
+ retval |= pch_phub_write_serial_rom(chip, 0x0d, 0x00);
+ retval |= pch_phub_write_serial_rom(chip, 0x0c, 0x80);
+
+ retval |= pch_phub_write_serial_rom(chip, 0x13, 0xbc);
+ retval |= pch_phub_write_serial_rom(chip, 0x12, 0x10);
+ retval |= pch_phub_write_serial_rom(chip, 0x11, 0x01);
+ retval |= pch_phub_write_serial_rom(chip, 0x10, 0x18);
+
+ retval |= pch_phub_write_serial_rom(chip, 0x1b, 0xbc);
+ retval |= pch_phub_write_serial_rom(chip, 0x1a, 0x10);
+ retval |= pch_phub_write_serial_rom(chip, 0x19, 0x01);
+ retval |= pch_phub_write_serial_rom(chip, 0x18, 0x19);
+
+ retval |= pch_phub_write_serial_rom(chip, 0x23, 0xbc);
+ retval |= pch_phub_write_serial_rom(chip, 0x22, 0x10);
+ retval |= pch_phub_write_serial_rom(chip, 0x21, 0x01);
+ retval |= pch_phub_write_serial_rom(chip, 0x20, 0x3a);
+
+ retval |= pch_phub_write_serial_rom(chip, 0x27, 0x01);
+ retval |= pch_phub_write_serial_rom(chip, 0x26, 0x00);
+ retval |= pch_phub_write_serial_rom(chip, 0x25, 0x00);
+ retval |= pch_phub_write_serial_rom(chip, 0x24, 0x00);
+
+ return retval;
+}
+
+/**
+ * pch_phub_read_gbe_mac_addr() - Read Gigabit Ethernet MAC address
+ * @offset_address: Gigabit Ethernet MAC address offset value.
+ * @data: Buffer of the Gigabit Ethernet MAC address value.
+ */
+static void pch_phub_read_gbe_mac_addr(struct pch_phub_reg *chip, u8 *data)
+{
+ int i;
+ for (i = 0; i < ETH_ALEN; i++)
+ pch_phub_read_serial_rom_val(chip, i, &data[i]);
+}
+
+/**
+ * pch_phub_write_gbe_mac_addr() - Write MAC address
+ * @offset_address: Gigabit Ethernet MAC address offset value.
+ * @data: Gigabit Ethernet MAC address value.
+ */
+static int pch_phub_write_gbe_mac_addr(struct pch_phub_reg *chip, u8 *data)
+{
+ int retval;
+ int i;
+
+ retval = pch_phub_gbe_serial_rom_conf(chip);
+ if (retval)
+ return retval;
+
+ for (i = 0; i < ETH_ALEN; i++) {
+ retval = pch_phub_write_serial_rom_val(chip, i, data[i]);
+ if (retval)
+ return retval;
+ }
+
+ return retval;
+}
+
+static ssize_t pch_phub_bin_read(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf,
+ loff_t off, size_t count)
+{
+ unsigned int rom_signature;
+ unsigned char rom_length;
+ unsigned int tmp;
+ unsigned int addr_offset;
+ unsigned int orom_size;
+ int ret;
+ int err;
+
+ struct pch_phub_reg *chip =
+ dev_get_drvdata(container_of(kobj, struct device, kobj));
+
+ ret = mutex_lock_interruptible(&pch_phub_mutex);
+ if (ret) {
+ err = -ERESTARTSYS;
+ goto return_err_nomutex;
+ }
+
+ /* Get Rom signature */
+ pch_phub_read_serial_rom(chip, 0x80, (unsigned char *)&rom_signature);
+ rom_signature &= 0xff;
+ pch_phub_read_serial_rom(chip, 0x81, (unsigned char *)&tmp);
+ rom_signature |= (tmp & 0xff) << 8;
+ if (rom_signature == 0xAA55) {
+ pch_phub_read_serial_rom(chip, 0x82, &rom_length);
+ orom_size = rom_length * 512;
+ if (orom_size < off) {
+ addr_offset = 0;
+ goto return_ok;
+ }
+ if (orom_size < count) {
+ addr_offset = 0;
+ goto return_ok;
+ }
+
+ for (addr_offset = 0; addr_offset < count; addr_offset++) {
+ pch_phub_read_serial_rom(chip, 0x80 + addr_offset + off,
+ &buf[addr_offset]);
+ }
+ } else {
+ err = -ENODATA;
+ goto return_err;
+ }
+return_ok:
+ mutex_unlock(&pch_phub_mutex);
+ return addr_offset;
+
+return_err:
+ mutex_unlock(&pch_phub_mutex);
+return_err_nomutex:
+ return err;
+}
+
+static ssize_t pch_phub_bin_write(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *attr,
+ char *buf, loff_t off, size_t count)
+{
+ int err;
+ unsigned int addr_offset;
+ int ret;
+ struct pch_phub_reg *chip =
+ dev_get_drvdata(container_of(kobj, struct device, kobj));
+
+ ret = mutex_lock_interruptible(&pch_phub_mutex);
+ if (ret)
+ return -ERESTARTSYS;
+
+ if (off > PCH_PHUB_OROM_SIZE) {
+ addr_offset = 0;
+ goto return_ok;
+ }
+ if (count > PCH_PHUB_OROM_SIZE) {
+ addr_offset = 0;
+ goto return_ok;
+ }
+
+ for (addr_offset = 0; addr_offset < count; addr_offset++) {
+ if (PCH_PHUB_OROM_SIZE < off + addr_offset)
+ goto return_ok;
+
+ ret = pch_phub_write_serial_rom(chip, 0x80 + addr_offset + off,
+ buf[addr_offset]);
+ if (ret) {
+ err = ret;
+ goto return_err;
+ }
+ }
+
+return_ok:
+ mutex_unlock(&pch_phub_mutex);
+ return addr_offset;
+
+return_err:
+ mutex_unlock(&pch_phub_mutex);
+ return err;
+}
+
+static ssize_t show_pch_mac(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ u8 mac[8];
+ struct pch_phub_reg *chip = dev_get_drvdata(dev);
+
+ pch_phub_read_gbe_mac_addr(chip, mac);
+
+ return sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x\n",
+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+}
+
+static ssize_t store_pch_mac(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ u8 mac[6];
+ struct pch_phub_reg *chip = dev_get_drvdata(dev);
+
+ if (count != 18)
+ return -EINVAL;
+
+ sscanf(buf, "%02x:%02x:%02x:%02x:%02x:%02x",
+ (u32 *)&mac[0], (u32 *)&mac[1], (u32 *)&mac[2], (u32 *)&mac[3],
+ (u32 *)&mac[4], (u32 *)&mac[5]);
+
+ pch_phub_write_gbe_mac_addr(chip, mac);
+
+ return count;
+}
+
+static DEVICE_ATTR(pch_mac, S_IRUGO | S_IWUSR, show_pch_mac, store_pch_mac);
+
+static struct bin_attribute pch_bin_attr = {
+ .attr = {
+ .name = "pch_firmware",
+ .mode = S_IRUGO | S_IWUSR,
+ },
+ .size = PCH_PHUB_OROM_SIZE + 1,
+ .read = pch_phub_bin_read,
+ .write = pch_phub_bin_write,
+};
+
+static int __devinit pch_phub_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ int retval;
+
+ int ret;
+ ssize_t rom_size;
+ struct pch_phub_reg *chip;
+
+ chip = kzalloc(sizeof(struct pch_phub_reg), GFP_KERNEL);
+ if (chip == NULL)
+ return -ENOMEM;
+
+ ret = pci_enable_device(pdev);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "%s : pci_enable_device FAILED(ret=%d)", __func__, ret);
+ goto err_pci_enable_dev;
+ }
+ dev_dbg(&pdev->dev, "%s : pci_enable_device returns %d\n", __func__,
+ ret);
+
+ ret = pci_request_regions(pdev, KBUILD_MODNAME);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "%s : pci_request_regions FAILED(ret=%d)", __func__, ret);
+ goto err_req_regions;
+ }
+ dev_dbg(&pdev->dev, "%s : "
+ "pci_request_regions returns %d\n", __func__, ret);
+
+ chip->pch_phub_base_address = pci_iomap(pdev, 1, 0);
+
+
+ if (chip->pch_phub_base_address == 0) {
+ dev_err(&pdev->dev, "%s : pci_iomap FAILED", __func__);
+ ret = -ENOMEM;
+ goto err_pci_iomap;
+ }
+ dev_dbg(&pdev->dev, "%s : pci_iomap SUCCESS and value "
+ "in pch_phub_base_address variable is %p\n", __func__,
+ chip->pch_phub_base_address);
+ chip->pch_phub_extrom_base_address = pci_map_rom(pdev, &rom_size);
+
+ if (chip->pch_phub_extrom_base_address == 0) {
+ dev_err(&pdev->dev, "%s : pci_map_rom FAILED", __func__);
+ ret = -ENOMEM;
+ goto err_pci_map;
+ }
+ dev_dbg(&pdev->dev, "%s : "
+ "pci_map_rom SUCCESS and value in "
+ "pch_phub_extrom_base_address variable is %p\n", __func__,
+ chip->pch_phub_extrom_base_address);
+
+ pci_set_drvdata(pdev, chip);
+
+ retval = sysfs_create_file(&pdev->dev.kobj, &dev_attr_pch_mac.attr);
+ if (retval)
+ goto err_sysfs_create;
+
+ retval = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr);
+ if (retval)
+ goto exit_bin_attr;
+
+ pch_phub_read_modify_write_reg(chip, (unsigned int)CLKCFG_REG_OFFSET,
+ CLKCFG_CAN_50MHZ, CLKCFG_CANCLK_MASK);
+
+ /* set the prefech value */
+ iowrite32(0x000affaa, chip->pch_phub_base_address + 0x14);
+ /* set the interrupt delay value */
+ iowrite32(0x25, chip->pch_phub_base_address + 0x44);
+
+ return 0;
+exit_bin_attr:
+ sysfs_remove_file(&pdev->dev.kobj, &dev_attr_pch_mac.attr);
+
+err_sysfs_create:
+ pci_unmap_rom(pdev, chip->pch_phub_extrom_base_address);
+err_pci_map:
+ pci_iounmap(pdev, chip->pch_phub_base_address);
+err_pci_iomap:
+ pci_release_regions(pdev);
+err_req_regions:
+ pci_disable_device(pdev);
+err_pci_enable_dev:
+ kfree(chip);
+ dev_err(&pdev->dev, "%s returns %d\n", __func__, ret);
+ return ret;
+}
+
+static void __devexit pch_phub_remove(struct pci_dev *pdev)
+{
+ struct pch_phub_reg *chip = pci_get_drvdata(pdev);
+
+ sysfs_remove_file(&pdev->dev.kobj, &dev_attr_pch_mac.attr);
+ sysfs_remove_bin_file(&pdev->dev.kobj, &pch_bin_attr);
+ pci_unmap_rom(pdev, chip->pch_phub_extrom_base_address);
+ pci_iounmap(pdev, chip->pch_phub_base_address);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+ kfree(chip);
+}
+
+#ifdef CONFIG_PM
+
+static int pch_phub_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ int ret;
+
+ pch_phub_save_reg_conf(pdev);
+ ret = pci_save_state(pdev);
+ if (ret) {
+ dev_err(&pdev->dev,
+ " %s -pci_save_state returns %d\n", __func__, ret);
+ return ret;
+ }
+ pci_enable_wake(pdev, PCI_D3hot, 0);
+ pci_disable_device(pdev);
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+ return 0;
+}
+
+static int pch_phub_resume(struct pci_dev *pdev)
+{
+ int ret;
+
+ pci_set_power_state(pdev, PCI_D0);
+ pci_restore_state(pdev);
+ ret = pci_enable_device(pdev);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "%s-pci_enable_device failed(ret=%d) ", __func__, ret);
+ return ret;
+ }
+
+ pci_enable_wake(pdev, PCI_D3hot, 0);
+ pch_phub_restore_reg_conf(pdev);
+
+ return 0;
+}
+#else
+#define pch_phub_suspend NULL
+#define pch_phub_resume NULL
+#endif /* CONFIG_PM */
+
+static struct pci_device_id pch_phub_pcidev_id[] = {
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PCH1_PHUB)},
+ {0,}
+};
+
+static struct pci_driver pch_phub_driver = {
+ .name = "pch_phub",
+ .id_table = pch_phub_pcidev_id,
+ .probe = pch_phub_probe,
+ .remove = __devexit_p(pch_phub_remove),
+ .suspend = pch_phub_suspend,
+ .resume = pch_phub_resume
+};
+
+static int __init pch_phub_pci_init(void)
+{
+ return pci_register_driver(&pch_phub_driver);
+}
+
+static void __exit pch_phub_pci_exit(void)
+{
+ pci_unregister_driver(&pch_phub_driver);
+}
+
+module_init(pch_phub_pci_init);
+module_exit(pch_phub_pci_exit);
+
+MODULE_DESCRIPTION("PCH Packet Hub PCI Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/phantom.c b/drivers/misc/phantom.c
index 75ee0d3f6f45..4197a3cb26ba 100644
--- a/drivers/misc/phantom.c
+++ b/drivers/misc/phantom.c
@@ -24,7 +24,7 @@
#include <linux/slab.h>
#include <linux/phantom.h>
#include <linux/sched.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <asm/atomic.h>
#include <asm/io.h>
@@ -38,6 +38,7 @@
#define PHB_RUNNING 1
#define PHB_NOT_OH 2
+static DEFINE_MUTEX(phantom_mutex);
static struct class *phantom_class;
static int phantom_major;
@@ -215,17 +216,17 @@ static int phantom_open(struct inode *inode, struct file *file)
struct phantom_device *dev = container_of(inode->i_cdev,
struct phantom_device, cdev);
- lock_kernel();
+ mutex_lock(&phantom_mutex);
nonseekable_open(inode, file);
if (mutex_lock_interruptible(&dev->open_lock)) {
- unlock_kernel();
+ mutex_unlock(&phantom_mutex);
return -ERESTARTSYS;
}
if (dev->opened) {
mutex_unlock(&dev->open_lock);
- unlock_kernel();
+ mutex_unlock(&phantom_mutex);
return -EINVAL;
}
@@ -236,7 +237,7 @@ static int phantom_open(struct inode *inode, struct file *file)
atomic_set(&dev->counter, 0);
dev->opened++;
mutex_unlock(&dev->open_lock);
- unlock_kernel();
+ mutex_unlock(&phantom_mutex);
return 0;
}
@@ -279,6 +280,7 @@ static const struct file_operations phantom_file_ops = {
.unlocked_ioctl = phantom_ioctl,
.compat_ioctl = phantom_compat_ioctl,
.poll = phantom_poll,
+ .llseek = no_llseek,
};
static irqreturn_t phantom_isr(int irq, void *data)
diff --git a/drivers/misc/sgi-gru/grufile.c b/drivers/misc/sgi-gru/grufile.c
index cb3b4d228475..28852dfa310d 100644
--- a/drivers/misc/sgi-gru/grufile.c
+++ b/drivers/misc/sgi-gru/grufile.c
@@ -587,6 +587,7 @@ static const struct file_operations gru_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = gru_file_unlocked_ioctl,
.mmap = gru_file_mmap,
+ .llseek = noop_llseek,
};
static struct miscdevice gru_miscdev = {
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index d545f79f6000..00073b7c0368 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -29,7 +29,6 @@
#include <linux/kdev_t.h>
#include <linux/blkdev.h>
#include <linux/mutex.h>
-#include <linux/smp_lock.h>
#include <linux/scatterlist.h>
#include <linux/string_helpers.h>
@@ -51,6 +50,7 @@ MODULE_ALIAS("mmc:block");
#define MMC_SHIFT 3
#define MMC_NUM_MINORS (256 >> MMC_SHIFT)
+static DEFINE_MUTEX(block_mutex);
static DECLARE_BITMAP(dev_use, MMC_NUM_MINORS);
/*
@@ -108,7 +108,7 @@ static int mmc_blk_open(struct block_device *bdev, fmode_t mode)
struct mmc_blk_data *md = mmc_blk_get(bdev->bd_disk);
int ret = -ENXIO;
- lock_kernel();
+ mutex_lock(&block_mutex);
if (md) {
if (md->usage == 2)
check_disk_change(bdev);
@@ -119,7 +119,7 @@ static int mmc_blk_open(struct block_device *bdev, fmode_t mode)
ret = -EROFS;
}
}
- unlock_kernel();
+ mutex_unlock(&block_mutex);
return ret;
}
@@ -128,9 +128,9 @@ static int mmc_blk_release(struct gendisk *disk, fmode_t mode)
{
struct mmc_blk_data *md = disk->private_data;
- lock_kernel();
+ mutex_lock(&block_mutex);
mmc_blk_put(md);
- unlock_kernel();
+ mutex_unlock(&block_mutex);
return 0;
}
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index e876678176be..9c0b42bfe089 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -128,7 +128,6 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock
mq->req = NULL;
blk_queue_prep_rq(mq->queue, mmc_prep_request);
- blk_queue_ordered(mq->queue, QUEUE_ORDERED_DRAIN);
queue_flag_set_unlocked(QUEUE_FLAG_NONROT, mq->queue);
if (mmc_can_erase(card)) {
queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mq->queue);
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 5db49b124ffa..09eee6df0653 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1631,6 +1631,19 @@ int mmc_suspend_host(struct mmc_host *host)
if (host->bus_ops && !host->bus_dead) {
if (host->bus_ops->suspend)
err = host->bus_ops->suspend(host);
+ if (err == -ENOSYS || !host->bus_ops->resume) {
+ /*
+ * We simply "remove" the card in this case.
+ * It will be redetected on resume.
+ */
+ if (host->bus_ops->remove)
+ host->bus_ops->remove(host);
+ mmc_claim_host(host);
+ mmc_detach_bus(host);
+ mmc_release_host(host);
+ host->pm_flags = 0;
+ err = 0;
+ }
}
mmc_bus_put(host);
diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c
index 53cb380c0987..46bc6d7551a3 100644
--- a/drivers/mmc/core/debugfs.c
+++ b/drivers/mmc/core/debugfs.c
@@ -245,6 +245,7 @@ static const struct file_operations mmc_dbg_ext_csd_fops = {
.open = mmc_ext_csd_open,
.read = mmc_ext_csd_read,
.release = mmc_ext_csd_release,
+ .llseek = default_llseek,
};
void mmc_add_card_debugfs(struct mmc_card *card)
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 840b301b5671..f2e02d7d9f3d 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -41,23 +41,35 @@ static unsigned int fmax = 515633;
* @clkreg: default value for MCICLOCK register
* @clkreg_enable: enable value for MMCICLOCK register
* @datalength_bits: number of bits in the MMCIDATALENGTH register
+ * @fifosize: number of bytes that can be written when MMCI_TXFIFOEMPTY
+ * is asserted (likewise for RX)
+ * @fifohalfsize: number of bytes that can be written when MCI_TXFIFOHALFEMPTY
+ * is asserted (likewise for RX)
*/
struct variant_data {
unsigned int clkreg;
unsigned int clkreg_enable;
unsigned int datalength_bits;
+ unsigned int fifosize;
+ unsigned int fifohalfsize;
};
static struct variant_data variant_arm = {
+ .fifosize = 16 * 4,
+ .fifohalfsize = 8 * 4,
.datalength_bits = 16,
};
static struct variant_data variant_u300 = {
+ .fifosize = 16 * 4,
+ .fifohalfsize = 8 * 4,
.clkreg_enable = 1 << 13, /* HWFCEN */
.datalength_bits = 16,
};
static struct variant_data variant_ux500 = {
+ .fifosize = 30 * 4,
+ .fifohalfsize = 8 * 4,
.clkreg = MCI_CLK_ENABLE,
.clkreg_enable = 1 << 14, /* HWFCEN */
.datalength_bits = 24,
@@ -138,6 +150,7 @@ static void mmci_init_sg(struct mmci_host *host, struct mmc_data *data)
static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
{
+ struct variant_data *variant = host->variant;
unsigned int datactrl, timeout, irqmask;
unsigned long long clks;
void __iomem *base;
@@ -173,7 +186,7 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
* If we have less than a FIFOSIZE of bytes to transfer,
* trigger a PIO interrupt as soon as any data is available.
*/
- if (host->size < MCI_FIFOSIZE)
+ if (host->size < variant->fifosize)
irqmask |= MCI_RXDATAAVLBLMASK;
} else {
/*
@@ -332,13 +345,15 @@ static int mmci_pio_read(struct mmci_host *host, char *buffer, unsigned int rema
static int mmci_pio_write(struct mmci_host *host, char *buffer, unsigned int remain, u32 status)
{
+ struct variant_data *variant = host->variant;
void __iomem *base = host->base;
char *ptr = buffer;
do {
unsigned int count, maxcnt;
- maxcnt = status & MCI_TXFIFOEMPTY ? MCI_FIFOSIZE : MCI_FIFOHALFSIZE;
+ maxcnt = status & MCI_TXFIFOEMPTY ?
+ variant->fifosize : variant->fifohalfsize;
count = min(remain, maxcnt);
writesl(base + MMCIFIFO, ptr, count >> 2);
@@ -362,6 +377,7 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id)
{
struct mmci_host *host = dev_id;
struct sg_mapping_iter *sg_miter = &host->sg_miter;
+ struct variant_data *variant = host->variant;
void __iomem *base = host->base;
unsigned long flags;
u32 status;
@@ -420,7 +436,7 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id)
* If we're nearing the end of the read, switch to
* "any data available" mode.
*/
- if (status & MCI_RXACTIVE && host->size < MCI_FIFOSIZE)
+ if (status & MCI_RXACTIVE && host->size < variant->fifosize)
writel(MCI_RXDATAAVLBLMASK, base + MMCIMASK1);
/*
@@ -564,18 +580,23 @@ static int mmci_get_ro(struct mmc_host *mmc)
if (host->gpio_wp == -ENOSYS)
return -ENOSYS;
- return gpio_get_value(host->gpio_wp);
+ return gpio_get_value_cansleep(host->gpio_wp);
}
static int mmci_get_cd(struct mmc_host *mmc)
{
struct mmci_host *host = mmc_priv(mmc);
+ struct mmci_platform_data *plat = host->plat;
unsigned int status;
- if (host->gpio_cd == -ENOSYS)
- status = host->plat->status(mmc_dev(host->mmc));
- else
- status = !gpio_get_value(host->gpio_cd);
+ if (host->gpio_cd == -ENOSYS) {
+ if (!plat->status)
+ return 1; /* Assume always present */
+
+ status = plat->status(mmc_dev(host->mmc));
+ } else
+ status = !!gpio_get_value_cansleep(host->gpio_cd)
+ ^ plat->cd_invert;
/*
* Use positive logic throughout - status is zero for no card,
@@ -584,6 +605,15 @@ static int mmci_get_cd(struct mmc_host *mmc)
return status;
}
+static irqreturn_t mmci_cd_irq(int irq, void *dev_id)
+{
+ struct mmci_host *host = dev_id;
+
+ mmc_detect_change(host->mmc, msecs_to_jiffies(500));
+
+ return IRQ_HANDLED;
+}
+
static const struct mmc_host_ops mmci_ops = {
.request = mmci_request,
.set_ios = mmci_set_ios,
@@ -620,6 +650,7 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)
host->gpio_wp = -ENOSYS;
host->gpio_cd = -ENOSYS;
+ host->gpio_cd_irq = -1;
host->hw_designer = amba_manf(dev);
host->hw_revision = amba_rev(dev);
@@ -699,7 +730,6 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)
if (host->vcc == NULL)
mmc->ocr_avail = plat->ocr_mask;
mmc->caps = plat->capabilities;
- mmc->caps |= MMC_CAP_NEEDS_POLL;
/*
* We can do SGIO
@@ -744,6 +774,12 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)
host->gpio_cd = plat->gpio_cd;
else if (ret != -ENOSYS)
goto err_gpio_cd;
+
+ ret = request_any_context_irq(gpio_to_irq(plat->gpio_cd),
+ mmci_cd_irq, 0,
+ DRIVER_NAME " (cd)", host);
+ if (ret >= 0)
+ host->gpio_cd_irq = gpio_to_irq(plat->gpio_cd);
}
if (gpio_is_valid(plat->gpio_wp)) {
ret = gpio_request(plat->gpio_wp, DRIVER_NAME " (wp)");
@@ -755,6 +791,10 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)
goto err_gpio_wp;
}
+ if ((host->plat->status || host->gpio_cd != -ENOSYS)
+ && host->gpio_cd_irq < 0)
+ mmc->caps |= MMC_CAP_NEEDS_POLL;
+
ret = request_irq(dev->irq[0], mmci_irq, IRQF_SHARED, DRIVER_NAME " (cmd)", host);
if (ret)
goto unmap;
@@ -781,6 +821,8 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)
if (host->gpio_wp != -ENOSYS)
gpio_free(host->gpio_wp);
err_gpio_wp:
+ if (host->gpio_cd_irq >= 0)
+ free_irq(host->gpio_cd_irq, host);
if (host->gpio_cd != -ENOSYS)
gpio_free(host->gpio_cd);
err_gpio_cd:
@@ -819,6 +861,8 @@ static int __devexit mmci_remove(struct amba_device *dev)
if (host->gpio_wp != -ENOSYS)
gpio_free(host->gpio_wp);
+ if (host->gpio_cd_irq >= 0)
+ free_irq(host->gpio_cd_irq, host);
if (host->gpio_cd != -ENOSYS)
gpio_free(host->gpio_cd);
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index 68970cfb81e1..4ae887fc0189 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -54,10 +54,16 @@
#define MCI_DPSM_MODE (1 << 2)
#define MCI_DPSM_DMAENABLE (1 << 3)
#define MCI_DPSM_BLOCKSIZE (1 << 4)
-#define MCI_DPSM_RWSTART (1 << 8)
-#define MCI_DPSM_RWSTOP (1 << 9)
-#define MCI_DPSM_RWMOD (1 << 10)
-#define MCI_DPSM_SDIOEN (1 << 11)
+/* Control register extensions in the ST Micro U300 and Ux500 versions */
+#define MCI_ST_DPSM_RWSTART (1 << 8)
+#define MCI_ST_DPSM_RWSTOP (1 << 9)
+#define MCI_ST_DPSM_RWMOD (1 << 10)
+#define MCI_ST_DPSM_SDIOEN (1 << 11)
+/* Control register extensions in the ST Micro Ux500 versions */
+#define MCI_ST_DPSM_DMAREQCTL (1 << 12)
+#define MCI_ST_DPSM_DBOOTMODEEN (1 << 13)
+#define MCI_ST_DPSM_BUSYMODE (1 << 14)
+#define MCI_ST_DPSM_DDRMODE (1 << 15)
#define MMCIDATACNT 0x030
#define MMCISTATUS 0x034
@@ -133,13 +139,6 @@
MCI_DATATIMEOUTMASK|MCI_TXUNDERRUNMASK|MCI_RXOVERRUNMASK| \
MCI_CMDRESPENDMASK|MCI_CMDSENTMASK|MCI_DATABLOCKENDMASK)
-/*
- * The size of the FIFO in bytes.
- */
-#define MCI_FIFOSIZE (16*4)
-
-#define MCI_FIFOHALFSIZE (MCI_FIFOSIZE / 2)
-
#define NR_SG 16
struct clk;
@@ -154,6 +153,7 @@ struct mmci_host {
struct clk *clk;
int gpio_cd;
int gpio_wp;
+ int gpio_cd_irq;
unsigned int data_xfered;
diff --git a/drivers/mmc/host/sdricoh_cs.c b/drivers/mmc/host/sdricoh_cs.c
index 7aa65bb2af4a..f472c2714eb8 100644
--- a/drivers/mmc/host/sdricoh_cs.c
+++ b/drivers/mmc/host/sdricoh_cs.c
@@ -30,7 +30,6 @@
#include <linux/ioport.h>
#include <linux/scatterlist.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
#include <linux/io.h>
@@ -536,9 +535,7 @@ static int sdricoh_pcmcia_resume(struct pcmcia_device *link)
#endif
static struct pcmcia_driver sdricoh_driver = {
- .drv = {
- .name = DRIVER_NAME,
- },
+ .name = DRIVER_NAME,
.probe = sdricoh_pcmcia_probe,
.remove = sdricoh_pcmcia_detach,
.id_table = pcmcia_ids,
diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c
index e9ca5ba7d9d2..57a1acfe22c4 100644
--- a/drivers/mtd/maps/pcmciamtd.c
+++ b/drivers/mtd/maps/pcmciamtd.c
@@ -16,7 +16,6 @@
#include <asm/io.h>
#include <asm/system.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
@@ -101,7 +100,7 @@ MODULE_PARM_DESC(mem_type, "Set Memory type (0=Flash, 1=RAM, 2=ROM, default=0)")
static caddr_t remap_window(struct map_info *map, unsigned long to)
{
struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
- window_handle_t win = (window_handle_t)map->map_priv_2;
+ struct resource *win = (struct resource *) map->map_priv_2;
unsigned int offset;
int ret;
@@ -316,30 +315,19 @@ static void pcmciamtd_set_vpp(struct map_info *map, int on)
{
struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
struct pcmcia_device *link = dev->p_dev;
- modconf_t mod;
- int ret;
-
- mod.Attributes = CONF_VPP1_CHANGE_VALID | CONF_VPP2_CHANGE_VALID;
- mod.Vcc = 0;
- mod.Vpp1 = mod.Vpp2 = on ? dev->vpp : 0;
DEBUG(2, "dev = %p on = %d vpp = %d\n", dev, on, dev->vpp);
- ret = pcmcia_modify_configuration(link, &mod);
+ pcmcia_fixup_vpp(link, on ? dev->vpp : 0);
}
-/* After a card is removed, pcmciamtd_release() will unregister the
- * device, and release the PCMCIA configuration. If the device is
- * still open, this will be postponed until it is closed.
- */
-
static void pcmciamtd_release(struct pcmcia_device *link)
{
struct pcmciamtd_dev *dev = link->priv;
DEBUG(3, "link = 0x%p", link);
- if (link->win) {
+ if (link->resource[2]->end) {
if(dev->win_base) {
iounmap(dev->win_base);
dev->win_base = NULL;
@@ -482,18 +470,12 @@ static void card_settings(struct pcmciamtd_dev *dev, struct pcmcia_device *p_dev
}
-/* pcmciamtd_config() is scheduled to run after a CARD_INSERTION event
- * is received, to configure the PCMCIA socket, and to make the
- * MTD device available to the system.
- */
-
static int pcmciamtd_config(struct pcmcia_device *link)
{
struct pcmciamtd_dev *dev = link->priv;
struct mtd_info *mtd = NULL;
- win_req_t req;
int ret;
- int i;
+ int i, j = 0;
static char *probes[] = { "jedec_probe", "cfi_probe" };
int new_name = 0;
@@ -520,28 +502,34 @@ static int pcmciamtd_config(struct pcmcia_device *link)
* smaller windows until we succeed
*/
- req.Attributes = WIN_MEMORY_TYPE_CM | WIN_ENABLE;
- req.Attributes |= (dev->pcmcia_map.bankwidth == 1) ? WIN_DATA_WIDTH_8 : WIN_DATA_WIDTH_16;
- req.Base = 0;
- req.AccessSpeed = mem_speed;
- link->win = (window_handle_t)link;
- req.Size = (force_size) ? force_size << 20 : MAX_PCMCIA_ADDR;
+ link->resource[2]->flags |= WIN_MEMORY_TYPE_CM | WIN_ENABLE;
+ link->resource[2]->flags |= (dev->pcmcia_map.bankwidth == 1) ?
+ WIN_DATA_WIDTH_8 : WIN_DATA_WIDTH_16;
+ link->resource[2]->start = 0;
+ link->resource[2]->end = (force_size) ? force_size << 20 :
+ MAX_PCMCIA_ADDR;
dev->win_size = 0;
do {
int ret;
- DEBUG(2, "requesting window with size = %dKiB memspeed = %d",
- req.Size >> 10, req.AccessSpeed);
- ret = pcmcia_request_window(link, &req, &link->win);
+ DEBUG(2, "requesting window with size = %luKiB memspeed = %d",
+ (unsigned long) resource_size(link->resource[2]) >> 10,
+ mem_speed);
+ ret = pcmcia_request_window(link, link->resource[2], mem_speed);
DEBUG(2, "ret = %d dev->win_size = %d", ret, dev->win_size);
if(ret) {
- req.Size >>= 1;
+ j++;
+ link->resource[2]->start = 0;
+ link->resource[2]->end = (force_size) ?
+ force_size << 20 : MAX_PCMCIA_ADDR;
+ link->resource[2]->end >>= j;
} else {
- DEBUG(2, "Got window of size %dKiB", req.Size >> 10);
- dev->win_size = req.Size;
+ DEBUG(2, "Got window of size %luKiB", (unsigned long)
+ resource_size(link->resource[2]) >> 10);
+ dev->win_size = resource_size(link->resource[2]);
break;
}
- } while(req.Size >= 0x1000);
+ } while (link->resource[2]->end >= 0x1000);
DEBUG(2, "dev->win_size = %d", dev->win_size);
@@ -553,33 +541,31 @@ static int pcmciamtd_config(struct pcmcia_device *link)
DEBUG(1, "Allocated a window of %dKiB", dev->win_size >> 10);
/* Get write protect status */
- DEBUG(2, "window handle = 0x%8.8lx", (unsigned long)link->win);
- dev->win_base = ioremap(req.Base, req.Size);
+ dev->win_base = ioremap(link->resource[2]->start,
+ resource_size(link->resource[2]));
if(!dev->win_base) {
- dev_err(&dev->p_dev->dev, "ioremap(%lu, %u) failed\n",
- req.Base, req.Size);
+ dev_err(&dev->p_dev->dev, "ioremap(%pR) failed\n",
+ link->resource[2]);
pcmciamtd_release(link);
return -ENODEV;
}
- DEBUG(1, "mapped window dev = %p req.base = 0x%lx base = %p size = 0x%x",
- dev, req.Base, dev->win_base, req.Size);
+ DEBUG(1, "mapped window dev = %p @ %pR, base = %p",
+ dev, link->resource[2], dev->win_base);
dev->offset = 0;
dev->pcmcia_map.map_priv_1 = (unsigned long)dev;
- dev->pcmcia_map.map_priv_2 = (unsigned long)link->win;
+ dev->pcmcia_map.map_priv_2 = (unsigned long)link->resource[2];
dev->vpp = (vpp) ? vpp : link->socket->socket.Vpp;
- link->conf.Attributes = 0;
if(setvpp == 2) {
- link->conf.Vpp = dev->vpp;
+ link->vpp = dev->vpp;
} else {
- link->conf.Vpp = 0;
+ link->vpp = 0;
}
- link->conf.IntType = INT_MEMORY;
- link->conf.ConfigIndex = 0;
+ link->config_index = 0;
DEBUG(2, "Setting Configuration");
- ret = pcmcia_request_configuration(link, &link->conf);
+ ret = pcmcia_enable_device(link);
if (ret != 0) {
if (dev->win_base) {
iounmap(dev->win_base);
@@ -680,12 +666,6 @@ static int pcmciamtd_resume(struct pcmcia_device *dev)
}
-/* This deletes a driver "instance". The device is de-registered
- * with Card Services. If it has been released, all local data
- * structures are freed. Otherwise, the structures will be freed
- * when the device is released.
- */
-
static void pcmciamtd_detach(struct pcmcia_device *link)
{
struct pcmciamtd_dev *dev = link->priv;
@@ -703,11 +683,6 @@ static void pcmciamtd_detach(struct pcmcia_device *link)
}
-/* pcmciamtd_attach() creates an "instance" of the driver, allocating
- * local data structures for one device. The device is registered
- * with Card Services.
- */
-
static int pcmciamtd_probe(struct pcmcia_device *link)
{
struct pcmciamtd_dev *dev;
@@ -720,9 +695,6 @@ static int pcmciamtd_probe(struct pcmcia_device *link)
dev->p_dev = link;
link->priv = dev;
- link->conf.Attributes = 0;
- link->conf.IntType = INT_MEMORY;
-
return pcmciamtd_config(link);
}
@@ -757,9 +729,7 @@ static struct pcmcia_device_id pcmciamtd_ids[] = {
MODULE_DEVICE_TABLE(pcmcia, pcmciamtd_ids);
static struct pcmcia_driver pcmciamtd_driver = {
- .drv = {
- .name = "pcmciamtd"
- },
+ .name = "pcmciamtd",
.probe = pcmciamtd_probe,
.remove = pcmciamtd_detach,
.owner = THIS_MODULE,
@@ -771,8 +741,6 @@ static struct pcmcia_driver pcmciamtd_driver = {
static int __init init_pcmciamtd(void)
{
- info(DRIVER_DESC);
-
if(bankwidth && bankwidth != 1 && bankwidth != 2) {
info("bad bankwidth (%d), using default", bankwidth);
bankwidth = 2;
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index 62e68707b07f..50ab431b24eb 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -29,7 +29,6 @@
#include <linux/blkdev.h>
#include <linux/blkpg.h>
#include <linux/spinlock.h>
-#include <linux/smp_lock.h>
#include <linux/hdreg.h>
#include <linux/init.h>
#include <linux/mutex.h>
@@ -38,6 +37,7 @@
#include "mtdcore.h"
+static DEFINE_MUTEX(mtd_blkdevs_mutex);
static LIST_HEAD(blktrans_majors);
static DEFINE_MUTEX(blktrans_ref_mutex);
@@ -181,7 +181,7 @@ static int blktrans_open(struct block_device *bdev, fmode_t mode)
if (!dev)
return -ERESTARTSYS; /* FIXME: busy loop! -arnd*/
- lock_kernel();
+ mutex_lock(&mtd_blkdevs_mutex);
mutex_lock(&dev->lock);
if (!dev->mtd) {
@@ -198,7 +198,7 @@ static int blktrans_open(struct block_device *bdev, fmode_t mode)
unlock:
mutex_unlock(&dev->lock);
blktrans_dev_put(dev);
- unlock_kernel();
+ mutex_unlock(&mtd_blkdevs_mutex);
return ret;
}
@@ -210,7 +210,7 @@ static int blktrans_release(struct gendisk *disk, fmode_t mode)
if (!dev)
return ret;
- lock_kernel();
+ mutex_lock(&mtd_blkdevs_mutex);
mutex_lock(&dev->lock);
/* Release one reference, we sure its not the last one here*/
@@ -223,7 +223,7 @@ static int blktrans_release(struct gendisk *disk, fmode_t mode)
unlock:
mutex_unlock(&dev->lock);
blktrans_dev_put(dev);
- unlock_kernel();
+ mutex_unlock(&mtd_blkdevs_mutex);
return ret;
}
@@ -256,7 +256,7 @@ static int blktrans_ioctl(struct block_device *bdev, fmode_t mode,
if (!dev)
return ret;
- lock_kernel();
+ mutex_lock(&mtd_blkdevs_mutex);
mutex_lock(&dev->lock);
if (!dev->mtd)
@@ -271,7 +271,7 @@ static int blktrans_ioctl(struct block_device *bdev, fmode_t mode,
}
unlock:
mutex_unlock(&dev->lock);
- unlock_kernel();
+ mutex_unlock(&mtd_blkdevs_mutex);
blktrans_dev_put(dev);
return ret;
}
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index a825002123c8..5ef45487b65f 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -26,7 +26,7 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/sched.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/backing-dev.h>
#include <linux/compat.h>
#include <linux/mount.h>
@@ -37,6 +37,7 @@
#include <asm/uaccess.h>
#define MTD_INODE_FS_MAGIC 0x11307854
+static DEFINE_MUTEX(mtd_mutex);
static struct vfsmount *mtd_inode_mnt __read_mostly;
/*
@@ -90,7 +91,7 @@ static int mtd_open(struct inode *inode, struct file *file)
if ((file->f_mode & FMODE_WRITE) && (minor & 1))
return -EACCES;
- lock_kernel();
+ mutex_lock(&mtd_mutex);
mtd = get_mtd_device(NULL, devnum);
if (IS_ERR(mtd)) {
@@ -138,7 +139,7 @@ static int mtd_open(struct inode *inode, struct file *file)
file->private_data = mfi;
out:
- unlock_kernel();
+ mutex_unlock(&mtd_mutex);
return ret;
} /* mtd_open */
@@ -866,9 +867,9 @@ static long mtd_unlocked_ioctl(struct file *file, u_int cmd, u_long arg)
{
int ret;
- lock_kernel();
+ mutex_lock(&mtd_mutex);
ret = mtd_ioctl(file, cmd, arg);
- unlock_kernel();
+ mutex_unlock(&mtd_mutex);
return ret;
}
@@ -892,7 +893,7 @@ static long mtd_compat_ioctl(struct file *file, unsigned int cmd,
void __user *argp = compat_ptr(arg);
int ret = 0;
- lock_kernel();
+ mutex_lock(&mtd_mutex);
switch (cmd) {
case MEMWRITEOOB32:
@@ -927,7 +928,7 @@ static long mtd_compat_ioctl(struct file *file, unsigned int cmd,
ret = mtd_ioctl(file, cmd, (unsigned long)argp);
}
- unlock_kernel();
+ mutex_unlock(&mtd_mutex);
return ret;
}
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index b2828e84d243..214b03afdd48 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -30,6 +30,8 @@
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/completion.h>
#include <asm/mach/flash.h>
#include <mach/mxc_nand.h>
@@ -151,7 +153,7 @@ struct mxc_nand_host {
int irq;
int eccsize;
- wait_queue_head_t irq_waitq;
+ struct completion op_completion;
uint8_t *data_buf;
unsigned int buf_start;
@@ -164,6 +166,7 @@ struct mxc_nand_host {
void (*send_read_id)(struct mxc_nand_host *);
uint16_t (*get_dev_status)(struct mxc_nand_host *);
int (*check_int)(struct mxc_nand_host *);
+ void (*irq_control)(struct mxc_nand_host *, int);
};
/* OOB placement block for use with hardware ecc generation */
@@ -216,9 +219,12 @@ static irqreturn_t mxc_nfc_irq(int irq, void *dev_id)
{
struct mxc_nand_host *host = dev_id;
- disable_irq_nosync(irq);
+ if (!host->check_int(host))
+ return IRQ_NONE;
- wake_up(&host->irq_waitq);
+ host->irq_control(host, 0);
+
+ complete(&host->op_completion);
return IRQ_HANDLED;
}
@@ -245,11 +251,54 @@ static int check_int_v1_v2(struct mxc_nand_host *host)
if (!(tmp & NFC_V1_V2_CONFIG2_INT))
return 0;
- writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2);
+ if (!cpu_is_mx21())
+ writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2);
return 1;
}
+/*
+ * It has been observed that the i.MX21 cannot read the CONFIG2:INT bit
+ * if interrupts are masked (CONFIG1:INT_MSK is set). To handle this, the
+ * driver can enable/disable the irq line rather than simply masking the
+ * interrupts.
+ */
+static void irq_control_mx21(struct mxc_nand_host *host, int activate)
+{
+ if (activate)
+ enable_irq(host->irq);
+ else
+ disable_irq_nosync(host->irq);
+}
+
+static void irq_control_v1_v2(struct mxc_nand_host *host, int activate)
+{
+ uint16_t tmp;
+
+ tmp = readw(NFC_V1_V2_CONFIG1);
+
+ if (activate)
+ tmp &= ~NFC_V1_V2_CONFIG1_INT_MSK;
+ else
+ tmp |= NFC_V1_V2_CONFIG1_INT_MSK;
+
+ writew(tmp, NFC_V1_V2_CONFIG1);
+}
+
+static void irq_control_v3(struct mxc_nand_host *host, int activate)
+{
+ uint32_t tmp;
+
+ tmp = readl(NFC_V3_CONFIG2);
+
+ if (activate)
+ tmp &= ~NFC_V3_CONFIG2_INT_MSK;
+ else
+ tmp |= NFC_V3_CONFIG2_INT_MSK;
+
+ writel(tmp, NFC_V3_CONFIG2);
+}
+
/* This function polls the NANDFC to wait for the basic operation to
* complete by checking the INT bit of config2 register.
*/
@@ -259,10 +308,9 @@ static void wait_op_done(struct mxc_nand_host *host, int useirq)
if (useirq) {
if (!host->check_int(host)) {
-
- enable_irq(host->irq);
-
- wait_event(host->irq_waitq, host->check_int(host));
+ INIT_COMPLETION(host->op_completion);
+ host->irq_control(host, 1);
+ wait_for_completion(&host->op_completion);
}
} else {
while (max_retries-- > 0) {
@@ -799,6 +847,7 @@ static void preset_v3(struct mtd_info *mtd)
NFC_V3_CONFIG2_2CMD_PHASES |
NFC_V3_CONFIG2_SPAS(mtd->oobsize >> 1) |
NFC_V3_CONFIG2_ST_CMD(0x70) |
+ NFC_V3_CONFIG2_INT_MSK |
NFC_V3_CONFIG2_NUM_ADDR_PHASE0;
if (chip->ecc.mode == NAND_ECC_HW)
@@ -1024,6 +1073,10 @@ static int __init mxcnd_probe(struct platform_device *pdev)
host->send_read_id = send_read_id_v1_v2;
host->get_dev_status = get_dev_status_v1_v2;
host->check_int = check_int_v1_v2;
+ if (cpu_is_mx21())
+ host->irq_control = irq_control_mx21;
+ else
+ host->irq_control = irq_control_v1_v2;
}
if (nfc_is_v21()) {
@@ -1062,6 +1115,7 @@ static int __init mxcnd_probe(struct platform_device *pdev)
host->send_read_id = send_read_id_v3;
host->check_int = check_int_v3;
host->get_dev_status = get_dev_status_v3;
+ host->irq_control = irq_control_v3;
oob_smallpage = &nandv2_hw_eccoob_smallpage;
oob_largepage = &nandv2_hw_eccoob_largepage;
} else
@@ -1093,14 +1147,34 @@ static int __init mxcnd_probe(struct platform_device *pdev)
this->options |= NAND_USE_FLASH_BBT;
}
- init_waitqueue_head(&host->irq_waitq);
+ init_completion(&host->op_completion);
host->irq = platform_get_irq(pdev, 0);
+ /*
+ * mask the interrupt. For i.MX21 explicitely call
+ * irq_control_v1_v2 to use the mask bit. We can't call
+ * disable_irq_nosync() for an interrupt we do not own yet.
+ */
+ if (cpu_is_mx21())
+ irq_control_v1_v2(host, 0);
+ else
+ host->irq_control(host, 0);
+
err = request_irq(host->irq, mxc_nfc_irq, IRQF_DISABLED, DRIVER_NAME, host);
if (err)
goto eirq;
+ host->irq_control(host, 0);
+
+ /*
+ * Now that the interrupt is disabled make sure the interrupt
+ * mask bit is cleared on i.MX21. Otherwise we can't read
+ * the interrupt status bit on this machine.
+ */
+ if (cpu_is_mx21())
+ irq_control_v1_v2(host, 1);
+
/* first scan to find the device and get the page size */
if (nand_scan_ident(mtd, 1, NULL)) {
err = -ENXIO;
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 133d51528f8d..513e0a76a4a7 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -413,7 +413,7 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
prefetch_status = gpmc_read_status(GPMC_PREFETCH_COUNT);
} while (prefetch_status);
/* disable and stop the PFPW engine */
- gpmc_prefetch_reset();
+ gpmc_prefetch_reset(info->gpmc_cs);
dma_unmap_single(&info->pdev->dev, dma_addr, len, dir);
return 0;
diff --git a/drivers/mtd/ubi/Kconfig b/drivers/mtd/ubi/Kconfig
index f702a163d8df..3cf193fb5e00 100644
--- a/drivers/mtd/ubi/Kconfig
+++ b/drivers/mtd/ubi/Kconfig
@@ -1,9 +1,5 @@
-menu "UBI - Unsorted block images"
- depends on MTD
-
-config MTD_UBI
- tristate "Enable UBI"
- depends on MTD
+menuconfig MTD_UBI
+ tristate "Enable UBI - Unsorted block images"
select CRC32
help
UBI is a software layer above MTD layer which admits of LVM-like
@@ -12,11 +8,12 @@ config MTD_UBI
capabilities. Please, consult the MTD web site for more details
(www.linux-mtd.infradead.org).
+if MTD_UBI
+
config MTD_UBI_WL_THRESHOLD
int "UBI wear-leveling threshold"
default 4096
range 2 65536
- depends on MTD_UBI
help
This parameter defines the maximum difference between the highest
erase counter value and the lowest erase counter value of eraseblocks
@@ -34,7 +31,6 @@ config MTD_UBI_BEB_RESERVE
int "Percentage of reserved eraseblocks for bad eraseblocks handling"
default 1
range 0 25
- depends on MTD_UBI
help
If the MTD device admits of bad eraseblocks (e.g. NAND flash), UBI
reserves some amount of physical eraseblocks to handle new bad
@@ -48,8 +44,6 @@ config MTD_UBI_BEB_RESERVE
config MTD_UBI_GLUEBI
tristate "MTD devices emulation driver (gluebi)"
- default n
- depends on MTD_UBI
help
This option enables gluebi - an additional driver which emulates MTD
devices on top of UBI volumes: for each UBI volumes an MTD device is
@@ -59,4 +53,5 @@ config MTD_UBI_GLUEBI
software.
source "drivers/mtd/ubi/Kconfig.debug"
-endmenu
+
+endif # MTD_UBI
diff --git a/drivers/mtd/ubi/Kconfig.debug b/drivers/mtd/ubi/Kconfig.debug
index 61f6e5e40458..fad4adc0fe2c 100644
--- a/drivers/mtd/ubi/Kconfig.debug
+++ b/drivers/mtd/ubi/Kconfig.debug
@@ -1,94 +1,73 @@
comment "UBI debugging options"
- depends on MTD_UBI
config MTD_UBI_DEBUG
bool "UBI debugging"
depends on SYSFS
- depends on MTD_UBI
select DEBUG_FS
select KALLSYMS_ALL if KALLSYMS && DEBUG_KERNEL
help
This option enables UBI debugging.
+if MTD_UBI_DEBUG
+
config MTD_UBI_DEBUG_MSG
bool "UBI debugging messages"
- depends on MTD_UBI_DEBUG
- default n
help
This option enables UBI debugging messages.
config MTD_UBI_DEBUG_PARANOID
bool "Extra self-checks"
- default n
- depends on MTD_UBI_DEBUG
help
This option enables extra checks in UBI code. Note this slows UBI down
significantly.
config MTD_UBI_DEBUG_DISABLE_BGT
bool "Do not enable the UBI background thread"
- depends on MTD_UBI_DEBUG
- default n
help
This option switches the background thread off by default. The thread
may be also be enabled/disabled via UBI sysfs.
config MTD_UBI_DEBUG_EMULATE_BITFLIPS
bool "Emulate flash bit-flips"
- depends on MTD_UBI_DEBUG
- default n
help
This option emulates bit-flips with probability 1/50, which in turn
causes scrubbing. Useful for debugging and stressing UBI.
config MTD_UBI_DEBUG_EMULATE_WRITE_FAILURES
bool "Emulate flash write failures"
- depends on MTD_UBI_DEBUG
- default n
help
This option emulates write failures with probability 1/100. Useful for
debugging and testing how UBI handlines errors.
config MTD_UBI_DEBUG_EMULATE_ERASE_FAILURES
bool "Emulate flash erase failures"
- depends on MTD_UBI_DEBUG
- default n
help
This option emulates erase failures with probability 1/100. Useful for
debugging and testing how UBI handlines errors.
-menu "Additional UBI debugging messages"
- depends on MTD_UBI_DEBUG
+comment "Additional UBI debugging messages"
config MTD_UBI_DEBUG_MSG_BLD
bool "Additional UBI initialization and build messages"
- default n
- depends on MTD_UBI_DEBUG
help
This option enables detailed UBI initialization and device build
debugging messages.
config MTD_UBI_DEBUG_MSG_EBA
bool "Eraseblock association unit messages"
- default n
- depends on MTD_UBI_DEBUG
help
This option enables debugging messages from the UBI eraseblock
association unit.
config MTD_UBI_DEBUG_MSG_WL
bool "Wear-leveling unit messages"
- default n
- depends on MTD_UBI_DEBUG
help
This option enables debugging messages from the UBI wear-leveling
unit.
config MTD_UBI_DEBUG_MSG_IO
bool "Input/output unit messages"
- default n
- depends on MTD_UBI_DEBUG
help
This option enables debugging messages from the UBI input/output unit.
-endmenu # UBI debugging messages
+endif # MTD_UBI_DEBUG
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index 78ae89488a4f..5ebe280225d6 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -95,8 +95,8 @@ DEFINE_MUTEX(ubi_devices_mutex);
static DEFINE_SPINLOCK(ubi_devices_lock);
/* "Show" method for files in '/<sysfs>/class/ubi/' */
-static ssize_t ubi_version_show(struct class *class, struct class_attribute *attr,
- char *buf)
+static ssize_t ubi_version_show(struct class *class,
+ struct class_attribute *attr, char *buf)
{
return sprintf(buf, "%d\n", UBI_VERSION);
}
@@ -591,6 +591,7 @@ static int attach_by_scanning(struct ubi_device *ubi)
ubi->bad_peb_count = si->bad_peb_count;
ubi->good_peb_count = ubi->peb_count - ubi->bad_peb_count;
+ ubi->corr_peb_count = si->corr_peb_count;
ubi->max_ec = si->max_ec;
ubi->mean_ec = si->mean_ec;
ubi_msg("max. sequence number: %llu", si->max_sqnum);
@@ -972,6 +973,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
ubi_msg("MTD device size: %llu MiB", ubi->flash_size >> 20);
ubi_msg("number of good PEBs: %d", ubi->good_peb_count);
ubi_msg("number of bad PEBs: %d", ubi->bad_peb_count);
+ ubi_msg("number of corrupted PEBs: %d", ubi->corr_peb_count);
ubi_msg("max. allowed volumes: %d", ubi->vtbl_slots);
ubi_msg("wear-leveling threshold: %d", CONFIG_MTD_UBI_WL_THRESHOLD);
ubi_msg("number of internal volumes: %d", UBI_INT_VOL_COUNT);
diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c
index 3d2d1a69e9a0..af9fb0ff8210 100644
--- a/drivers/mtd/ubi/cdev.c
+++ b/drivers/mtd/ubi/cdev.c
@@ -1100,4 +1100,5 @@ const struct file_operations ubi_ctrl_cdev_operations = {
.owner = THIS_MODULE,
.unlocked_ioctl = ctrl_cdev_ioctl,
.compat_ioctl = ctrl_cdev_compat_ioctl,
+ .llseek = noop_llseek,
};
diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h
index 17a107129726..9eca95074bc2 100644
--- a/drivers/mtd/ubi/debug.h
+++ b/drivers/mtd/ubi/debug.h
@@ -57,6 +57,9 @@ void ubi_dbg_dump_seb(const struct ubi_scan_leb *seb, int type);
void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req);
void ubi_dbg_dump_flash(struct ubi_device *ubi, int pnum, int offset, int len);
+#define ubi_dbg_print_hex_dump(l, ps, pt, r, g, b, len, a) \
+ print_hex_dump(l, ps, pt, r, g, b, len, a)
+
#ifdef CONFIG_MTD_UBI_DEBUG_MSG
/* General debugging messages */
#define dbg_gen(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__)
@@ -172,6 +175,7 @@ static inline int ubi_dbg_is_erase_failure(void)
#define ubi_dbg_dump_seb(seb, type) ({})
#define ubi_dbg_dump_mkvol_req(req) ({})
#define ubi_dbg_dump_flash(ubi, pnum, offset, len) ({})
+#define ubi_dbg_print_hex_dump(l, ps, pt, r, g, b, len, a) ({})
#define UBI_IO_DEBUG 0
#define DBG_DISABLE_BGT 0
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c
index fe74749e0dae..4be671815014 100644
--- a/drivers/mtd/ubi/eba.c
+++ b/drivers/mtd/ubi/eba.c
@@ -418,7 +418,7 @@ retry:
* may try to recover data. FIXME: but this is
* not implemented.
*/
- if (err == UBI_IO_BAD_HDR_READ ||
+ if (err == UBI_IO_BAD_HDR_EBADMSG ||
err == UBI_IO_BAD_HDR) {
ubi_warn("corrupted VID header at PEB "
"%d, LEB %d:%d", pnum, vol_id,
@@ -963,7 +963,7 @@ write_error:
static int is_error_sane(int err)
{
if (err == -EIO || err == -ENOMEM || err == UBI_IO_BAD_HDR ||
- err == UBI_IO_BAD_HDR_READ || err == -ETIMEDOUT)
+ err == UBI_IO_BAD_HDR_EBADMSG || err == -ETIMEDOUT)
return 0;
return 1;
}
@@ -1201,6 +1201,9 @@ static void print_rsvd_warning(struct ubi_device *ubi,
ubi_warn("cannot reserve enough PEBs for bad PEB handling, reserved %d,"
" need %d", ubi->beb_rsvd_pebs, ubi->beb_rsvd_level);
+ if (ubi->corr_peb_count)
+ ubi_warn("%d PEBs are corrupted and not used",
+ ubi->corr_peb_count);
}
/**
@@ -1263,6 +1266,9 @@ int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
if (ubi->avail_pebs < EBA_RESERVED_PEBS) {
ubi_err("no enough physical eraseblocks (%d, need %d)",
ubi->avail_pebs, EBA_RESERVED_PEBS);
+ if (ubi->corr_peb_count)
+ ubi_err("%d PEBs are corrupted and not used",
+ ubi->corr_peb_count);
err = -ENOSPC;
goto out_free;
}
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c
index 332f992f13d9..c2960ac9f39c 100644
--- a/drivers/mtd/ubi/io.c
+++ b/drivers/mtd/ubi/io.c
@@ -376,25 +376,6 @@ retry:
return 0;
}
-/**
- * check_pattern - check if buffer contains only a certain byte pattern.
- * @buf: buffer to check
- * @patt: the pattern to check
- * @size: buffer size in bytes
- *
- * This function returns %1 in there are only @patt bytes in @buf, and %0 if
- * something else was also found.
- */
-static int check_pattern(const void *buf, uint8_t patt, int size)
-{
- int i;
-
- for (i = 0; i < size; i++)
- if (((const uint8_t *)buf)[i] != patt)
- return 0;
- return 1;
-}
-
/* Patterns to write to a physical eraseblock when torturing it */
static uint8_t patterns[] = {0xa5, 0x5a, 0x0};
@@ -426,7 +407,7 @@ static int torture_peb(struct ubi_device *ubi, int pnum)
if (err)
goto out;
- err = check_pattern(ubi->peb_buf1, 0xFF, ubi->peb_size);
+ err = ubi_check_pattern(ubi->peb_buf1, 0xFF, ubi->peb_size);
if (err == 0) {
ubi_err("erased PEB %d, but a non-0xFF byte found",
pnum);
@@ -445,7 +426,8 @@ static int torture_peb(struct ubi_device *ubi, int pnum)
if (err)
goto out;
- err = check_pattern(ubi->peb_buf1, patterns[i], ubi->peb_size);
+ err = ubi_check_pattern(ubi->peb_buf1, patterns[i],
+ ubi->peb_size);
if (err == 0) {
ubi_err("pattern %x checking failed for PEB %d",
patterns[i], pnum);
@@ -517,7 +499,7 @@ static int nor_erase_prepare(struct ubi_device *ubi, int pnum)
* In this case we probably anyway have garbage in this PEB.
*/
err1 = ubi_io_read_vid_hdr(ubi, pnum, &vid_hdr, 0);
- if (err1 == UBI_IO_BAD_HDR_READ || err1 == UBI_IO_BAD_HDR)
+ if (err1 == UBI_IO_BAD_HDR_EBADMSG || err1 == UBI_IO_BAD_HDR)
/*
* The VID header is corrupted, so we can safely erase this
* PEB and not afraid that it will be treated as a valid PEB in
@@ -712,47 +694,47 @@ bad:
* and corrected by the flash driver; this is harmless but may indicate that
* this eraseblock may become bad soon (but may be not);
* o %UBI_IO_BAD_HDR if the erase counter header is corrupted (a CRC error);
- * o %UBI_IO_PEB_EMPTY if the physical eraseblock is empty;
+ * o %UBI_IO_BAD_HDR_EBADMSG is the same as %UBI_IO_BAD_HDR, but there also was
+ * a data integrity error (uncorrectable ECC error in case of NAND);
+ * o %UBI_IO_FF if only 0xFF bytes were read (the PEB is supposedly empty)
* o a negative error code in case of failure.
*/
int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
struct ubi_ec_hdr *ec_hdr, int verbose)
{
- int err, read_err = 0;
+ int err, read_err;
uint32_t crc, magic, hdr_crc;
dbg_io("read EC header from PEB %d", pnum);
ubi_assert(pnum >= 0 && pnum < ubi->peb_count);
- err = ubi_io_read(ubi, ec_hdr, pnum, 0, UBI_EC_HDR_SIZE);
- if (err) {
- if (err != UBI_IO_BITFLIPS && err != -EBADMSG)
- return err;
+ read_err = ubi_io_read(ubi, ec_hdr, pnum, 0, UBI_EC_HDR_SIZE);
+ if (read_err) {
+ if (read_err != UBI_IO_BITFLIPS && read_err != -EBADMSG)
+ return read_err;
/*
* We read all the data, but either a correctable bit-flip
- * occurred, or MTD reported about some data integrity error,
- * like an ECC error in case of NAND. The former is harmless,
- * the later may mean that the read data is corrupted. But we
- * have a CRC check-sum and we will detect this. If the EC
- * header is still OK, we just report this as there was a
- * bit-flip.
+ * occurred, or MTD reported a data integrity error
+ * (uncorrectable ECC error in case of NAND). The former is
+ * harmless, the later may mean that the read data is
+ * corrupted. But we have a CRC check-sum and we will detect
+ * this. If the EC header is still OK, we just report this as
+ * there was a bit-flip, to force scrubbing.
*/
- if (err == -EBADMSG)
- read_err = UBI_IO_BAD_HDR_READ;
}
magic = be32_to_cpu(ec_hdr->magic);
if (magic != UBI_EC_HDR_MAGIC) {
- if (read_err)
- return read_err;
+ if (read_err == -EBADMSG)
+ return UBI_IO_BAD_HDR_EBADMSG;
/*
* The magic field is wrong. Let's check if we have read all
* 0xFF. If yes, this physical eraseblock is assumed to be
* empty.
*/
- if (check_pattern(ec_hdr, 0xFF, UBI_EC_HDR_SIZE)) {
+ if (ubi_check_pattern(ec_hdr, 0xFF, UBI_EC_HDR_SIZE)) {
/* The physical eraseblock is supposedly empty */
if (verbose)
ubi_warn("no EC header found at PEB %d, "
@@ -760,7 +742,10 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
else if (UBI_IO_DEBUG)
dbg_msg("no EC header found at PEB %d, "
"only 0xFF bytes", pnum);
- return UBI_IO_PEB_EMPTY;
+ if (!read_err)
+ return UBI_IO_FF;
+ else
+ return UBI_IO_FF_BITFLIPS;
}
/*
@@ -788,7 +773,11 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
} else if (UBI_IO_DEBUG)
dbg_msg("bad EC header CRC at PEB %d, calculated "
"%#08x, read %#08x", pnum, crc, hdr_crc);
- return read_err ?: UBI_IO_BAD_HDR;
+
+ if (!read_err)
+ return UBI_IO_BAD_HDR;
+ else
+ return UBI_IO_BAD_HDR_EBADMSG;
}
/* And of course validate what has just been read from the media */
@@ -975,22 +964,16 @@ bad:
*
* This function reads the volume identifier header from physical eraseblock
* @pnum and stores it in @vid_hdr. It also checks CRC checksum of the read
- * volume identifier header. The following codes may be returned:
+ * volume identifier header. The error codes are the same as in
+ * 'ubi_io_read_ec_hdr()'.
*
- * o %0 if the CRC checksum is correct and the header was successfully read;
- * o %UBI_IO_BITFLIPS if the CRC is correct, but bit-flips were detected
- * and corrected by the flash driver; this is harmless but may indicate that
- * this eraseblock may become bad soon;
- * o %UBI_IO_BAD_HDR if the volume identifier header is corrupted (a CRC
- * error detected);
- * o %UBI_IO_PEB_FREE if the physical eraseblock is free (i.e., there is no VID
- * header there);
- * o a negative error code in case of failure.
+ * Note, the implementation of this function is also very similar to
+ * 'ubi_io_read_ec_hdr()', so refer commentaries in 'ubi_io_read_ec_hdr()'.
*/
int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
struct ubi_vid_hdr *vid_hdr, int verbose)
{
- int err, read_err = 0;
+ int err, read_err;
uint32_t crc, magic, hdr_crc;
void *p;
@@ -998,48 +981,29 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
ubi_assert(pnum >= 0 && pnum < ubi->peb_count);
p = (char *)vid_hdr - ubi->vid_hdr_shift;
- err = ubi_io_read(ubi, p, pnum, ubi->vid_hdr_aloffset,
+ read_err = ubi_io_read(ubi, p, pnum, ubi->vid_hdr_aloffset,
ubi->vid_hdr_alsize);
- if (err) {
- if (err != UBI_IO_BITFLIPS && err != -EBADMSG)
- return err;
-
- /*
- * We read all the data, but either a correctable bit-flip
- * occurred, or MTD reported about some data integrity error,
- * like an ECC error in case of NAND. The former is harmless,
- * the later may mean the read data is corrupted. But we have a
- * CRC check-sum and we will identify this. If the VID header is
- * still OK, we just report this as there was a bit-flip.
- */
- if (err == -EBADMSG)
- read_err = UBI_IO_BAD_HDR_READ;
- }
+ if (read_err && read_err != UBI_IO_BITFLIPS && read_err != -EBADMSG)
+ return read_err;
magic = be32_to_cpu(vid_hdr->magic);
if (magic != UBI_VID_HDR_MAGIC) {
- if (read_err)
- return read_err;
+ if (read_err == -EBADMSG)
+ return UBI_IO_BAD_HDR_EBADMSG;
- /*
- * If we have read all 0xFF bytes, the VID header probably does
- * not exist and the physical eraseblock is assumed to be free.
- */
- if (check_pattern(vid_hdr, 0xFF, UBI_VID_HDR_SIZE)) {
- /* The physical eraseblock is supposedly free */
+ if (ubi_check_pattern(vid_hdr, 0xFF, UBI_VID_HDR_SIZE)) {
if (verbose)
ubi_warn("no VID header found at PEB %d, "
"only 0xFF bytes", pnum);
else if (UBI_IO_DEBUG)
dbg_msg("no VID header found at PEB %d, "
"only 0xFF bytes", pnum);
- return UBI_IO_PEB_FREE;
+ if (!read_err)
+ return UBI_IO_FF;
+ else
+ return UBI_IO_FF_BITFLIPS;
}
- /*
- * This is not a valid VID header, and these are not 0xFF
- * bytes. Report that the header is corrupted.
- */
if (verbose) {
ubi_warn("bad magic number at PEB %d: %08x instead of "
"%08x", pnum, magic, UBI_VID_HDR_MAGIC);
@@ -1061,20 +1025,18 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
} else if (UBI_IO_DEBUG)
dbg_msg("bad CRC at PEB %d, calculated %#08x, "
"read %#08x", pnum, crc, hdr_crc);
- return read_err ?: UBI_IO_BAD_HDR;
+ if (!read_err)
+ return UBI_IO_BAD_HDR;
+ else
+ return UBI_IO_BAD_HDR_EBADMSG;
}
- /* Validate the VID header that we have just read */
err = validate_vid_hdr(ubi, vid_hdr);
if (err) {
ubi_err("validation failed for PEB %d", pnum);
return -EINVAL;
}
- /*
- * If there was a read error (%-EBADMSG), but the header CRC is still
- * OK, report about a bit-flip to force scrubbing on this PEB.
- */
return read_err ? UBI_IO_BITFLIPS : 0;
}
@@ -1383,7 +1345,7 @@ int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len)
goto error;
}
- err = check_pattern(ubi->dbg_peb_buf, 0xFF, len);
+ err = ubi_check_pattern(ubi->dbg_peb_buf, 0xFF, len);
if (err == 0) {
ubi_err("flash region at PEB %d:%d, length %d does not "
"contain all 0xFF bytes", pnum, offset, len);
diff --git a/drivers/mtd/ubi/misc.c b/drivers/mtd/ubi/misc.c
index 22ad31402945..ff2a65c37f69 100644
--- a/drivers/mtd/ubi/misc.c
+++ b/drivers/mtd/ubi/misc.c
@@ -103,3 +103,22 @@ void ubi_calculate_reserved(struct ubi_device *ubi)
if (ubi->beb_rsvd_level < MIN_RESEVED_PEBS)
ubi->beb_rsvd_level = MIN_RESEVED_PEBS;
}
+
+/**
+ * ubi_check_pattern - check if buffer contains only a certain byte pattern.
+ * @buf: buffer to check
+ * @patt: the pattern to check
+ * @size: buffer size in bytes
+ *
+ * This function returns %1 in there are only @patt bytes in @buf, and %0 if
+ * something else was also found.
+ */
+int ubi_check_pattern(const void *buf, uint8_t patt, int size)
+{
+ int i;
+
+ for (i = 0; i < size; i++)
+ if (((const uint8_t *)buf)[i] != patt)
+ return 0;
+ return 1;
+}
diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c
index 69b52e9c9489..3c631863bf40 100644
--- a/drivers/mtd/ubi/scan.c
+++ b/drivers/mtd/ubi/scan.c
@@ -29,7 +29,7 @@
* objects which are kept in volume RB-tree with root at the @volumes field.
* The RB-tree is indexed by the volume ID.
*
- * Found logical eraseblocks are represented by &struct ubi_scan_leb objects.
+ * Scanned logical eraseblocks are represented by &struct ubi_scan_leb objects.
* These objects are kept in per-volume RB-trees with the root at the
* corresponding &struct ubi_scan_volume object. To put it differently, we keep
* an RB-tree of per-volume objects and each of these objects is the root of
@@ -38,6 +38,33 @@
* Corrupted physical eraseblocks are put to the @corr list, free physical
* eraseblocks are put to the @free list and the physical eraseblock to be
* erased are put to the @erase list.
+ *
+ * UBI tries to distinguish between 2 types of corruptions.
+ * 1. Corruptions caused by power cuts. These are harmless and expected
+ * corruptions and UBI tries to handle them gracefully, without printing too
+ * many warnings and error messages. The idea is that we do not lose
+ * important data in these case - we may lose only the data which was being
+ * written to the media just before the power cut happened, and the upper
+ * layers (e.g., UBIFS) are supposed to handle these situations. UBI puts
+ * these PEBs to the head of the @erase list and they are scheduled for
+ * erasure.
+ *
+ * 2. Unexpected corruptions which are not caused by power cuts. During
+ * scanning, such PEBs are put to the @corr list and UBI preserves them.
+ * Obviously, this lessens the amount of available PEBs, and if at some
+ * point UBI runs out of free PEBs, it switches to R/O mode. UBI also loudly
+ * informs about such PEBs every time the MTD device is attached.
+ *
+ * However, it is difficult to reliably distinguish between these types of
+ * corruptions and UBI's strategy is as follows. UBI assumes (2.) if the VID
+ * header is corrupted and the data area does not contain all 0xFFs, and there
+ * were not bit-flips or integrity errors while reading the data area. Otherwise
+ * UBI assumes (1.). The assumptions are:
+ * o if the data area contains only 0xFFs, there is no data, and it is safe
+ * to just erase this PEB.
+ * o if the data area has bit-flips and data integrity errors (ECC errors on
+ * NAND), it is probably a PEB which was being erased when power cut
+ * happened.
*/
#include <linux/err.h>
@@ -62,26 +89,26 @@ static struct ubi_vid_hdr *vidh;
* @si: scanning information
* @pnum: physical eraseblock number to add
* @ec: erase counter of the physical eraseblock
+ * @to_head: if not zero, add to the head of the list
* @list: the list to add to
*
- * This function adds physical eraseblock @pnum to free, erase, corrupted or
- * alien lists. Returns zero in case of success and a negative error code in
- * case of failure.
+ * This function adds physical eraseblock @pnum to free, erase, or alien lists.
+ * If @to_head is not zero, PEB will be added to the head of the list, which
+ * basically means it will be processed first later. E.g., we add corrupted
+ * PEBs (corrupted due to power cuts) to the head of the erase list to make
+ * sure we erase them first and get rid of corruptions ASAP. This function
+ * returns zero in case of success and a negative error code in case of
+ * failure.
*/
-static int add_to_list(struct ubi_scan_info *si, int pnum, int ec,
+static int add_to_list(struct ubi_scan_info *si, int pnum, int ec, int to_head,
struct list_head *list)
{
struct ubi_scan_leb *seb;
if (list == &si->free) {
dbg_bld("add to free: PEB %d, EC %d", pnum, ec);
- si->free_peb_count += 1;
} else if (list == &si->erase) {
dbg_bld("add to erase: PEB %d, EC %d", pnum, ec);
- si->erase_peb_count += 1;
- } else if (list == &si->corr) {
- dbg_bld("add to corrupted: PEB %d, EC %d", pnum, ec);
- si->corr_peb_count += 1;
} else if (list == &si->alien) {
dbg_bld("add to alien: PEB %d, EC %d", pnum, ec);
si->alien_peb_count += 1;
@@ -94,7 +121,37 @@ static int add_to_list(struct ubi_scan_info *si, int pnum, int ec,
seb->pnum = pnum;
seb->ec = ec;
- list_add_tail(&seb->u.list, list);
+ if (to_head)
+ list_add(&seb->u.list, list);
+ else
+ list_add_tail(&seb->u.list, list);
+ return 0;
+}
+
+/**
+ * add_corrupted - add a corrupted physical eraseblock.
+ * @si: scanning information
+ * @pnum: physical eraseblock number to add
+ * @ec: erase counter of the physical eraseblock
+ *
+ * This function adds corrupted physical eraseblock @pnum to the 'corr' list.
+ * The corruption was presumably not caused by a power cut. Returns zero in
+ * case of success and a negative error code in case of failure.
+ */
+static int add_corrupted(struct ubi_scan_info *si, int pnum, int ec)
+{
+ struct ubi_scan_leb *seb;
+
+ dbg_bld("add to corrupted: PEB %d, EC %d", pnum, ec);
+
+ seb = kmalloc(sizeof(struct ubi_scan_leb), GFP_KERNEL);
+ if (!seb)
+ return -ENOMEM;
+
+ si->corr_peb_count += 1;
+ seb->pnum = pnum;
+ seb->ec = ec;
+ list_add(&seb->u.list, &si->corr);
return 0;
}
@@ -258,8 +315,8 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb,
* created before sequence numbers support has been added. At
* that times we used 32-bit LEB versions stored in logical
* eraseblocks. That was before UBI got into mainline. We do not
- * support these images anymore. Well, those images will work
- * still work, but only if no unclean reboots happened.
+ * support these images anymore. Well, those images still work,
+ * but only if no unclean reboots happened.
*/
ubi_err("unsupported on-flash UBI format\n");
return -EINVAL;
@@ -285,19 +342,25 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb,
return 1;
}
} else {
- pnum = seb->pnum;
+ if (!seb->copy_flag) {
+ /* It is not a copy, so it is newer */
+ dbg_bld("first PEB %d is newer, copy_flag is unset",
+ pnum);
+ return bitflips << 1;
+ }
vh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL);
if (!vh)
return -ENOMEM;
+ pnum = seb->pnum;
err = ubi_io_read_vid_hdr(ubi, pnum, vh, 0);
if (err) {
if (err == UBI_IO_BITFLIPS)
bitflips = 1;
else {
dbg_err("VID of PEB %d header is bad, but it "
- "was OK earlier", pnum);
+ "was OK earlier, err %d", pnum, err);
if (err > 0)
err = -EIO;
@@ -305,14 +368,6 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb,
}
}
- if (!vh->copy_flag) {
- /* It is not a copy, so it is newer */
- dbg_bld("first PEB %d is newer, copy_flag is unset",
- pnum);
- err = bitflips << 1;
- goto out_free_vidh;
- }
-
vid_hdr = vh;
}
@@ -463,18 +518,15 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
if (err)
return err;
- if (cmp_res & 4)
- err = add_to_list(si, seb->pnum, seb->ec,
- &si->corr);
- else
- err = add_to_list(si, seb->pnum, seb->ec,
- &si->erase);
+ err = add_to_list(si, seb->pnum, seb->ec, cmp_res & 4,
+ &si->erase);
if (err)
return err;
seb->ec = ec;
seb->pnum = pnum;
seb->scrub = ((cmp_res & 2) || bitflips);
+ seb->copy_flag = vid_hdr->copy_flag;
seb->sqnum = sqnum;
if (sv->highest_lnum == lnum)
@@ -487,10 +539,8 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
* This logical eraseblock is older than the one found
* previously.
*/
- if (cmp_res & 4)
- return add_to_list(si, pnum, ec, &si->corr);
- else
- return add_to_list(si, pnum, ec, &si->erase);
+ return add_to_list(si, pnum, ec, cmp_res & 4,
+ &si->erase);
}
}
@@ -510,8 +560,9 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
seb->ec = ec;
seb->pnum = pnum;
seb->lnum = lnum;
- seb->sqnum = sqnum;
seb->scrub = bitflips;
+ seb->copy_flag = vid_hdr->copy_flag;
+ seb->sqnum = sqnum;
if (sv->highest_lnum <= lnum) {
sv->highest_lnum = lnum;
@@ -521,7 +572,6 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
sv->leb_count += 1;
rb_link_node(&seb->u.rb, parent, p);
rb_insert_color(&seb->u.rb, &sv->root);
- si->used_peb_count += 1;
return 0;
}
@@ -668,8 +718,8 @@ out_free:
struct ubi_scan_leb *ubi_scan_get_free_peb(struct ubi_device *ubi,
struct ubi_scan_info *si)
{
- int err = 0, i;
- struct ubi_scan_leb *seb;
+ int err = 0;
+ struct ubi_scan_leb *seb, *tmp_seb;
if (!list_empty(&si->free)) {
seb = list_entry(si->free.next, struct ubi_scan_leb, u.list);
@@ -678,38 +728,86 @@ struct ubi_scan_leb *ubi_scan_get_free_peb(struct ubi_device *ubi,
return seb;
}
- for (i = 0; i < 2; i++) {
- struct list_head *head;
- struct ubi_scan_leb *tmp_seb;
+ /*
+ * We try to erase the first physical eraseblock from the erase list
+ * and pick it if we succeed, or try to erase the next one if not. And
+ * so forth. We don't want to take care about bad eraseblocks here -
+ * they'll be handled later.
+ */
+ list_for_each_entry_safe(seb, tmp_seb, &si->erase, u.list) {
+ if (seb->ec == UBI_SCAN_UNKNOWN_EC)
+ seb->ec = si->mean_ec;
- if (i == 0)
- head = &si->erase;
- else
- head = &si->corr;
+ err = ubi_scan_erase_peb(ubi, si, seb->pnum, seb->ec+1);
+ if (err)
+ continue;
+ seb->ec += 1;
+ list_del(&seb->u.list);
+ dbg_bld("return PEB %d, EC %d", seb->pnum, seb->ec);
+ return seb;
+ }
+
+ ubi_err("no free eraseblocks");
+ return ERR_PTR(-ENOSPC);
+}
+
+/**
+ * check_corruption - check the data area of PEB.
+ * @ubi: UBI device description object
+ * @vid_hrd: the (corrupted) VID header of this PEB
+ * @pnum: the physical eraseblock number to check
+ *
+ * This is a helper function which is used to distinguish between VID header
+ * corruptions caused by power cuts and other reasons. If the PEB contains only
+ * 0xFF bytes in the data area, the VID header is most probably corrupted
+ * because of a power cut (%0 is returned in this case). Otherwise, it was
+ * probably corrupted for some other reasons (%1 is returned in this case). A
+ * negative error code is returned if a read error occurred.
+ *
+ * If the corruption reason was a power cut, UBI can safely erase this PEB.
+ * Otherwise, it should preserve it to avoid possibly destroying important
+ * information.
+ */
+static int check_corruption(struct ubi_device *ubi, struct ubi_vid_hdr *vid_hdr,
+ int pnum)
+{
+ int err;
+
+ mutex_lock(&ubi->buf_mutex);
+ memset(ubi->peb_buf1, 0x00, ubi->leb_size);
+
+ err = ubi_io_read(ubi, ubi->peb_buf1, pnum, ubi->leb_start,
+ ubi->leb_size);
+ if (err == UBI_IO_BITFLIPS || err == -EBADMSG) {
/*
- * We try to erase the first physical eraseblock from the @head
- * list and pick it if we succeed, or try to erase the
- * next one if not. And so forth. We don't want to take care
- * about bad eraseblocks here - they'll be handled later.
+ * Bit-flips or integrity errors while reading the data area.
+ * It is difficult to say for sure what type of corruption is
+ * this, but presumably a power cut happened while this PEB was
+ * erased, so it became unstable and corrupted, and should be
+ * erased.
*/
- list_for_each_entry_safe(seb, tmp_seb, head, u.list) {
- if (seb->ec == UBI_SCAN_UNKNOWN_EC)
- seb->ec = si->mean_ec;
+ return 0;
+ }
- err = ubi_scan_erase_peb(ubi, si, seb->pnum, seb->ec+1);
- if (err)
- continue;
+ if (err)
+ return err;
- seb->ec += 1;
- list_del(&seb->u.list);
- dbg_bld("return PEB %d, EC %d", seb->pnum, seb->ec);
- return seb;
- }
+ if (ubi_check_pattern(ubi->peb_buf1, 0xFF, ubi->leb_size)) {
+ mutex_unlock(&ubi->buf_mutex);
+ return 0;
}
- ubi_err("no eraseblocks found");
- return ERR_PTR(-ENOSPC);
+ ubi_err("PEB %d contains corrupted VID header, and the data does not "
+ "contain all 0xFF, this may be a non-UBI PEB or a severe VID "
+ "header corruption which requires manual inspection", pnum);
+ ubi_dbg_dump_vid_hdr(vid_hdr);
+ dbg_msg("hexdump of PEB %d offset %d, length %d",
+ pnum, ubi->leb_start, ubi->leb_size);
+ ubi_dbg_print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
+ ubi->peb_buf1, ubi->leb_size, 1);
+ mutex_unlock(&ubi->buf_mutex);
+ return 1;
}
/**
@@ -725,7 +823,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
int pnum)
{
long long uninitialized_var(ec);
- int err, bitflips = 0, vol_id, ec_corr = 0;
+ int err, bitflips = 0, vol_id, ec_err = 0;
dbg_bld("scan PEB %d", pnum);
@@ -746,22 +844,37 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
err = ubi_io_read_ec_hdr(ubi, pnum, ech, 0);
if (err < 0)
return err;
- else if (err == UBI_IO_BITFLIPS)
+ switch (err) {
+ case 0:
+ break;
+ case UBI_IO_BITFLIPS:
bitflips = 1;
- else if (err == UBI_IO_PEB_EMPTY)
- return add_to_list(si, pnum, UBI_SCAN_UNKNOWN_EC, &si->erase);
- else if (err == UBI_IO_BAD_HDR_READ || err == UBI_IO_BAD_HDR) {
+ break;
+ case UBI_IO_FF:
+ si->empty_peb_count += 1;
+ return add_to_list(si, pnum, UBI_SCAN_UNKNOWN_EC, 0,
+ &si->erase);
+ case UBI_IO_FF_BITFLIPS:
+ si->empty_peb_count += 1;
+ return add_to_list(si, pnum, UBI_SCAN_UNKNOWN_EC, 1,
+ &si->erase);
+ case UBI_IO_BAD_HDR_EBADMSG:
+ case UBI_IO_BAD_HDR:
/*
* We have to also look at the VID header, possibly it is not
* corrupted. Set %bitflips flag in order to make this PEB be
* moved and EC be re-created.
*/
- ec_corr = err;
+ ec_err = err;
ec = UBI_SCAN_UNKNOWN_EC;
bitflips = 1;
+ break;
+ default:
+ ubi_err("'ubi_io_read_ec_hdr()' returned unknown code %d", err);
+ return -EINVAL;
}
- if (!ec_corr) {
+ if (!ec_err) {
int image_seq;
/* Make sure UBI version is OK */
@@ -814,24 +927,67 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
err = ubi_io_read_vid_hdr(ubi, pnum, vidh, 0);
if (err < 0)
return err;
- else if (err == UBI_IO_BITFLIPS)
+ switch (err) {
+ case 0:
+ break;
+ case UBI_IO_BITFLIPS:
bitflips = 1;
- else if (err == UBI_IO_BAD_HDR_READ || err == UBI_IO_BAD_HDR ||
- (err == UBI_IO_PEB_FREE && ec_corr)) {
- /* VID header is corrupted */
- if (err == UBI_IO_BAD_HDR_READ ||
- ec_corr == UBI_IO_BAD_HDR_READ)
- si->read_err_count += 1;
- err = add_to_list(si, pnum, ec, &si->corr);
+ break;
+ case UBI_IO_BAD_HDR_EBADMSG:
+ if (ec_err == UBI_IO_BAD_HDR_EBADMSG)
+ /*
+ * Both EC and VID headers are corrupted and were read
+ * with data integrity error, probably this is a bad
+ * PEB, bit it is not marked as bad yet. This may also
+ * be a result of power cut during erasure.
+ */
+ si->maybe_bad_peb_count += 1;
+ case UBI_IO_BAD_HDR:
+ if (ec_err)
+ /*
+ * Both headers are corrupted. There is a possibility
+ * that this a valid UBI PEB which has corresponding
+ * LEB, but the headers are corrupted. However, it is
+ * impossible to distinguish it from a PEB which just
+ * contains garbage because of a power cut during erase
+ * operation. So we just schedule this PEB for erasure.
+ */
+ err = 0;
+ else
+ /*
+ * The EC was OK, but the VID header is corrupted. We
+ * have to check what is in the data area.
+ */
+ err = check_corruption(ubi, vidh, pnum);
+
+ if (err < 0)
+ return err;
+ else if (!err)
+ /* This corruption is caused by a power cut */
+ err = add_to_list(si, pnum, ec, 1, &si->erase);
+ else
+ /* This is an unexpected corruption */
+ err = add_corrupted(si, pnum, ec);
if (err)
return err;
goto adjust_mean_ec;
- } else if (err == UBI_IO_PEB_FREE) {
- /* No VID header - the physical eraseblock is free */
- err = add_to_list(si, pnum, ec, &si->free);
+ case UBI_IO_FF_BITFLIPS:
+ err = add_to_list(si, pnum, ec, 1, &si->erase);
if (err)
return err;
goto adjust_mean_ec;
+ case UBI_IO_FF:
+ if (ec_err)
+ err = add_to_list(si, pnum, ec, 1, &si->erase);
+ else
+ err = add_to_list(si, pnum, ec, 0, &si->free);
+ if (err)
+ return err;
+ goto adjust_mean_ec;
+ default:
+ ubi_err("'ubi_io_read_vid_hdr()' returned unknown code %d",
+ err);
+ return -EINVAL;
}
vol_id = be32_to_cpu(vidh->vol_id);
@@ -843,7 +999,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
case UBI_COMPAT_DELETE:
ubi_msg("\"delete\" compatible internal volume %d:%d"
" found, will remove it", vol_id, lnum);
- err = add_to_list(si, pnum, ec, &si->erase);
+ err = add_to_list(si, pnum, ec, 1, &si->erase);
if (err)
return err;
return 0;
@@ -858,7 +1014,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
case UBI_COMPAT_PRESERVE:
ubi_msg("\"preserve\" compatible internal volume %d:%d"
" found", vol_id, lnum);
- err = add_to_list(si, pnum, ec, &si->alien);
+ err = add_to_list(si, pnum, ec, 0, &si->alien);
if (err)
return err;
return 0;
@@ -870,7 +1026,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
}
}
- if (ec_corr)
+ if (ec_err)
ubi_warn("valid VID header but corrupted EC header at PEB %d",
pnum);
err = ubi_scan_add_used(ubi, si, pnum, ec, vidh, bitflips);
@@ -878,7 +1034,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
return err;
adjust_mean_ec:
- if (!ec_corr) {
+ if (!ec_err) {
si->ec_sum += ec;
si->ec_count += 1;
if (ec > si->max_ec)
@@ -904,19 +1060,20 @@ adjust_mean_ec:
static int check_what_we_have(struct ubi_device *ubi, struct ubi_scan_info *si)
{
struct ubi_scan_leb *seb;
- int max_corr;
+ int max_corr, peb_count;
- max_corr = ubi->peb_count - si->bad_peb_count - si->alien_peb_count;
- max_corr = max_corr / 20 ?: 8;
+ peb_count = ubi->peb_count - si->bad_peb_count - si->alien_peb_count;
+ max_corr = peb_count / 20 ?: 8;
/*
- * Few corrupted PEBs are not a problem and may be just a result of
+ * Few corrupted PEBs is not a problem and may be just a result of
* unclean reboots. However, many of them may indicate some problems
* with the flash HW or driver.
*/
- if (si->corr_peb_count >= 8) {
- ubi_warn("%d PEBs are corrupted", si->corr_peb_count);
- printk(KERN_WARNING "corrupted PEBs are:");
+ if (si->corr_peb_count) {
+ ubi_err("%d PEBs are corrupted and preserved",
+ si->corr_peb_count);
+ printk(KERN_ERR "Corrupted PEBs are:");
list_for_each_entry(seb, &si->corr, u.list)
printk(KERN_CONT " %d", seb->pnum);
printk(KERN_CONT "\n");
@@ -931,41 +1088,35 @@ static int check_what_we_have(struct ubi_device *ubi, struct ubi_scan_info *si)
}
}
- if (si->free_peb_count + si->used_peb_count +
- si->alien_peb_count == 0) {
- /* No UBI-formatted eraseblocks were found */
- if (si->corr_peb_count == si->read_err_count &&
- si->corr_peb_count < 8) {
- /* No or just few corrupted PEBs, and all of them had a
- * read error. We assume that those are bad PEBs, which
- * were just not marked as bad so far.
- *
- * This piece of code basically tries to distinguish
- * between the following 2 situations:
- *
- * 1. Flash is empty, but there are few bad PEBs, which
- * are not marked as bad so far, and which were read
- * with error. We want to go ahead and format this
- * flash. While formating, the faulty PEBs will
- * probably be marked as bad.
- *
- * 2. Flash probably contains non-UBI data and we do
- * not want to format it and destroy possibly needed
- * data (e.g., consider the case when the bootloader
- * MTD partition was accidentally fed to UBI).
- */
+ if (si->empty_peb_count + si->maybe_bad_peb_count == peb_count) {
+ /*
+ * All PEBs are empty, or almost all - a couple PEBs look like
+ * they may be bad PEBs which were not marked as bad yet.
+ *
+ * This piece of code basically tries to distinguish between
+ * the following situations:
+ *
+ * 1. Flash is empty, but there are few bad PEBs, which are not
+ * marked as bad so far, and which were read with error. We
+ * want to go ahead and format this flash. While formatting,
+ * the faulty PEBs will probably be marked as bad.
+ *
+ * 2. Flash contains non-UBI data and we do not want to format
+ * it and destroy possibly important information.
+ */
+ if (si->maybe_bad_peb_count <= 2) {
si->is_empty = 1;
ubi_msg("empty MTD device detected");
- get_random_bytes(&ubi->image_seq, sizeof(ubi->image_seq));
+ get_random_bytes(&ubi->image_seq,
+ sizeof(ubi->image_seq));
} else {
- ubi_err("MTD device possibly contains non-UBI data, "
- "refusing it");
+ ubi_err("MTD device is not UBI-formatted and possibly "
+ "contains non-UBI data - refusing it");
return -EINVAL;
}
+
}
- if (si->corr_peb_count > 0)
- ubi_msg("corrupted PEBs will be formatted");
return 0;
}
diff --git a/drivers/mtd/ubi/scan.h b/drivers/mtd/ubi/scan.h
index 2576a8d1532b..a3264f0bef2b 100644
--- a/drivers/mtd/ubi/scan.h
+++ b/drivers/mtd/ubi/scan.h
@@ -30,6 +30,7 @@
* @pnum: physical eraseblock number
* @lnum: logical eraseblock number
* @scrub: if this physical eraseblock needs scrubbing
+ * @copy_flag: this LEB is a copy (@copy_flag is set in VID header of this LEB)
* @sqnum: sequence number
* @u: unions RB-tree or @list links
* @u.rb: link in the per-volume RB-tree of &struct ubi_scan_leb objects
@@ -42,7 +43,8 @@ struct ubi_scan_leb {
int ec;
int pnum;
int lnum;
- int scrub;
+ unsigned int scrub:1;
+ unsigned int copy_flag:1;
unsigned long long sqnum;
union {
struct rb_node rb;
@@ -91,14 +93,13 @@ struct ubi_scan_volume {
* @erase: list of physical eraseblocks which have to be erased
* @alien: list of physical eraseblocks which should not be used by UBI (e.g.,
* those belonging to "preserve"-compatible internal volumes)
- * @used_peb_count: count of used PEBs
* @corr_peb_count: count of PEBs in the @corr list
- * @read_err_count: count of PEBs read with error (%UBI_IO_BAD_HDR_READ was
- * returned)
- * @free_peb_count: count of PEBs in the @free list
- * @erase_peb_count: count of PEBs in the @erase list
+ * @empty_peb_count: count of PEBs which are presumably empty (contain only
+ * 0xFF bytes)
* @alien_peb_count: count of PEBs in the @alien list
* @bad_peb_count: count of bad physical eraseblocks
+ * @maybe_bad_peb_count: count of bad physical eraseblocks which are not marked
+ * as bad yet, but which look like bad
* @vols_found: number of volumes found during scanning
* @highest_vol_id: highest volume ID
* @is_empty: flag indicating whether the MTD device is empty or not
@@ -119,13 +120,11 @@ struct ubi_scan_info {
struct list_head free;
struct list_head erase;
struct list_head alien;
- int used_peb_count;
int corr_peb_count;
- int read_err_count;
- int free_peb_count;
- int erase_peb_count;
+ int empty_peb_count;
int alien_peb_count;
int bad_peb_count;
+ int maybe_bad_peb_count;
int vols_found;
int highest_vol_id;
int is_empty;
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index 0359e0cce482..0b0149c41fe3 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -85,21 +85,26 @@
/*
* Error codes returned by the I/O sub-system.
*
- * UBI_IO_PEB_EMPTY: the physical eraseblock is empty, i.e. it contains only
- * %0xFF bytes
- * UBI_IO_PEB_FREE: the physical eraseblock is free, i.e. it contains only a
- * valid erase counter header, and the rest are %0xFF bytes
+ * UBI_IO_FF: the read region of flash contains only 0xFFs
+ * UBI_IO_FF_BITFLIPS: the same as %UBI_IO_FF, but also also there was a data
+ * integrity error reported by the MTD driver
+ * (uncorrectable ECC error in case of NAND)
* UBI_IO_BAD_HDR: the EC or VID header is corrupted (bad magic or CRC)
- * UBI_IO_BAD_HDR_READ: the same as %UBI_IO_BAD_HDR, but also there was a read
- * error reported by the flash driver
+ * UBI_IO_BAD_HDR_EBADMSG: the same as %UBI_IO_BAD_HDR, but also there was a
+ * data integrity error reported by the MTD driver
+ * (uncorrectable ECC error in case of NAND)
* UBI_IO_BITFLIPS: bit-flips were detected and corrected
+ *
+ * Note, it is probably better to have bit-flip and ebadmsg as flags which can
+ * be or'ed with other error code. But this is a big change because there are
+ * may callers, so it does not worth the risk of introducing a bug
*/
enum {
- UBI_IO_PEB_EMPTY = 1,
- UBI_IO_PEB_FREE,
+ UBI_IO_FF = 1,
+ UBI_IO_FF_BITFLIPS,
UBI_IO_BAD_HDR,
- UBI_IO_BAD_HDR_READ,
- UBI_IO_BITFLIPS
+ UBI_IO_BAD_HDR_EBADMSG,
+ UBI_IO_BITFLIPS,
};
/*
@@ -356,6 +361,8 @@ struct ubi_wl_entry;
* @peb_size: physical eraseblock size
* @bad_peb_count: count of bad physical eraseblocks
* @good_peb_count: count of good physical eraseblocks
+ * @corr_peb_count: count of corrupted physical eraseblocks (preserved and not
+ * used by UBI)
* @erroneous_peb_count: count of erroneous physical eraseblocks in @erroneous
* @max_erroneous: maximum allowed amount of erroneous physical eraseblocks
* @min_io_size: minimal input/output unit size of the underlying MTD device
@@ -442,6 +449,7 @@ struct ubi_device {
int peb_size;
int bad_peb_count;
int good_peb_count;
+ int corr_peb_count;
int erroneous_peb_count;
int max_erroneous;
int min_io_size;
@@ -506,6 +514,7 @@ int ubi_calc_data_len(const struct ubi_device *ubi, const void *buf,
int length);
int ubi_check_volume(struct ubi_device *ubi, int vol_id);
void ubi_calculate_reserved(struct ubi_device *ubi);
+int ubi_check_pattern(const void *buf, uint8_t patt, int size);
/* eba.c */
int ubi_eba_unmap_leb(struct ubi_device *ubi, struct ubi_volume *vol,
diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c
index e42afab9a9fe..c47620dfc722 100644
--- a/drivers/mtd/ubi/vmt.c
+++ b/drivers/mtd/ubi/vmt.c
@@ -261,6 +261,9 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
/* Reserve physical eraseblocks */
if (vol->reserved_pebs > ubi->avail_pebs) {
dbg_err("not enough PEBs, only %d available", ubi->avail_pebs);
+ if (ubi->corr_peb_count)
+ dbg_err("%d PEBs are corrupted and not used",
+ ubi->corr_peb_count);
err = -ENOSPC;
goto out_unlock;
}
@@ -527,6 +530,9 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs)
if (pebs > ubi->avail_pebs) {
dbg_err("not enough PEBs: requested %d, available %d",
pebs, ubi->avail_pebs);
+ if (ubi->corr_peb_count)
+ dbg_err("%d PEBs are corrupted and not used",
+ ubi->corr_peb_count);
spin_unlock(&ubi->volumes_lock);
err = -ENOSPC;
goto out_free;
diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c
index 14c10bed94ee..fcdb7f65fe0b 100644
--- a/drivers/mtd/ubi/vtbl.c
+++ b/drivers/mtd/ubi/vtbl.c
@@ -366,7 +366,7 @@ write_error:
* Probably this physical eraseblock went bad, try to pick
* another one.
*/
- list_add_tail(&new_seb->u.list, &si->corr);
+ list_add(&new_seb->u.list, &si->erase);
goto retry;
}
kfree(new_seb);
@@ -662,9 +662,13 @@ static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si,
ubi->vol_count += 1;
vol->ubi = ubi;
- if (reserved_pebs > ubi->avail_pebs)
+ if (reserved_pebs > ubi->avail_pebs) {
ubi_err("not enough PEBs, required %d, available %d",
reserved_pebs, ubi->avail_pebs);
+ if (ubi->corr_peb_count)
+ ubi_err("%d PEBs are corrupted and not used",
+ ubi->corr_peb_count);
+ }
ubi->rsvd_pebs += reserved_pebs;
ubi->avail_pebs -= reserved_pebs;
@@ -837,7 +841,7 @@ int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si)
return PTR_ERR(ubi->vtbl);
}
- ubi->avail_pebs = ubi->good_peb_count;
+ ubi->avail_pebs = ubi->good_peb_count - ubi->corr_peb_count;
/*
* The layout volume is OK, initialize the corresponding in-RAM data
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index 97a435672eaf..655bbbe415d9 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -745,7 +745,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
err = ubi_io_read_vid_hdr(ubi, e1->pnum, vid_hdr, 0);
if (err && err != UBI_IO_BITFLIPS) {
- if (err == UBI_IO_PEB_FREE) {
+ if (err == UBI_IO_FF) {
/*
* We are trying to move PEB without a VID header. UBI
* always write VID headers shortly after the PEB was
@@ -759,6 +759,16 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
dbg_wl("PEB %d has no VID header", e1->pnum);
protect = 1;
goto out_not_moved;
+ } else if (err == UBI_IO_FF_BITFLIPS) {
+ /*
+ * The same situation as %UBI_IO_FF, but bit-flips were
+ * detected. It is better to schedule this PEB for
+ * scrubbing.
+ */
+ dbg_wl("PEB %d has no VID header but has bit-flips",
+ e1->pnum);
+ scrubbing = 1;
+ goto out_not_moved;
}
ubi_err("error %d while reading VID header from PEB %d",
@@ -1468,22 +1478,6 @@ int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
ubi->lookuptbl[e->pnum] = e;
}
- list_for_each_entry(seb, &si->corr, u.list) {
- cond_resched();
-
- e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL);
- if (!e)
- goto out_free;
-
- e->pnum = seb->pnum;
- e->ec = seb->ec;
- ubi->lookuptbl[e->pnum] = e;
- if (schedule_erase(ubi, e, 0)) {
- kmem_cache_free(ubi_wl_entry_slab, e);
- goto out_free;
- }
- }
-
ubi_rb_for_each_entry(rb1, sv, &si->volumes, rb) {
ubi_rb_for_each_entry(rb2, seb, &sv->root, u.rb) {
cond_resched();
@@ -1510,6 +1504,9 @@ int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
if (ubi->avail_pebs < WL_RESERVED_PEBS) {
ubi_err("no enough physical eraseblocks (%d, need %d)",
ubi->avail_pebs, WL_RESERVED_PEBS);
+ if (ubi->corr_peb_count)
+ ubi_err("%d PEBs are corrupted and not used",
+ ubi->corr_peb_count);
goto out_free;
}
ubi->avail_pebs -= WL_RESERVED_PEBS;
diff --git a/drivers/net/3c503.c b/drivers/net/3c503.c
index baac246561b9..4777a1cbcd8d 100644
--- a/drivers/net/3c503.c
+++ b/drivers/net/3c503.c
@@ -337,10 +337,10 @@ el2_probe1(struct net_device *dev, int ioaddr)
/* Finish setting the board's parameters. */
ei_status.stop_page = EL2_MB1_STOP_PG;
ei_status.word16 = wordlength;
- ei_status.reset_8390 = &el2_reset_8390;
- ei_status.get_8390_hdr = &el2_get_8390_hdr;
- ei_status.block_input = &el2_block_input;
- ei_status.block_output = &el2_block_output;
+ ei_status.reset_8390 = el2_reset_8390;
+ ei_status.get_8390_hdr = el2_get_8390_hdr;
+ ei_status.block_input = el2_block_input;
+ ei_status.block_output = el2_block_output;
if (dev->irq == 2)
dev->irq = 9;
diff --git a/drivers/net/3c515.c b/drivers/net/3c515.c
index 3bba835f1a21..cdf7226a7c43 100644
--- a/drivers/net/3c515.c
+++ b/drivers/net/3c515.c
@@ -662,7 +662,9 @@ static int corkscrew_setup(struct net_device *dev, int ioaddr,
pr_warning(" *** Warning: this IRQ is unlikely to work! ***\n");
{
- char *ram_split[] = { "5:3", "3:1", "1:1", "3:5" };
+ static const char * const ram_split[] = {
+ "5:3", "3:1", "1:1", "3:5"
+ };
__u32 config;
EL3WINDOW(3);
vp->available_media = inw(ioaddr + Wn3_Options);
@@ -734,7 +736,7 @@ static int corkscrew_open(struct net_device *dev)
init_timer(&vp->timer);
vp->timer.expires = jiffies + media_tbl[dev->if_port].wait;
vp->timer.data = (unsigned long) dev;
- vp->timer.function = &corkscrew_timer; /* timer handler */
+ vp->timer.function = corkscrew_timer; /* timer handler */
add_timer(&vp->timer);
} else
dev->if_port = vp->default_media;
diff --git a/drivers/net/3c523.c b/drivers/net/3c523.c
index a7b0e5e43a52..de579d043169 100644
--- a/drivers/net/3c523.c
+++ b/drivers/net/3c523.c
@@ -287,7 +287,7 @@ static int elmc_open(struct net_device *dev)
elmc_id_attn586(); /* disable interrupts */
- ret = request_irq(dev->irq, elmc_interrupt, IRQF_SHARED | IRQF_SAMPLE_RANDOM,
+ ret = request_irq(dev->irq, elmc_interrupt, IRQF_SHARED,
dev->name, dev);
if (ret) {
pr_err("%s: couldn't get irq %d\n", dev->name, dev->irq);
@@ -463,7 +463,7 @@ static int __init do_elmc_probe(struct net_device *dev)
/* we didn't find any 3c523 in the slots we checked for */
if (slot == MCA_NOTFOUND)
- return ((base_addr || irq) ? -ENXIO : -ENODEV);
+ return (base_addr || irq) ? -ENXIO : -ENODEV;
mca_set_adapter_name(slot, "3Com 3c523 Etherlink/MC");
mca_set_adapter_procfn(slot, (MCA_ProcFn) elmc_getinfo, dev);
diff --git a/drivers/net/3c527.c b/drivers/net/3c527.c
index 70705d1306b9..013b7c396663 100644
--- a/drivers/net/3c527.c
+++ b/drivers/net/3c527.c
@@ -443,7 +443,7 @@ static int __init mc32_probe1(struct net_device *dev, int slot)
* Grab the IRQ
*/
- err = request_irq(dev->irq, mc32_interrupt, IRQF_SHARED | IRQF_SAMPLE_RANDOM, DRV_NAME, dev);
+ err = request_irq(dev->irq, mc32_interrupt, IRQF_SHARED, DRV_NAME, dev);
if (err) {
release_region(dev->base_addr, MC32_IO_EXTENT);
pr_err("%s: unable to get IRQ %d.\n", DRV_NAME, dev->irq);
@@ -522,7 +522,7 @@ static int __init mc32_probe1(struct net_device *dev, int slot)
lp->tx_len = lp->exec_box->data[9]; /* Transmit list count */
lp->rx_len = lp->exec_box->data[11]; /* Receive list count */
- init_MUTEX_LOCKED(&lp->cmd_mutex);
+ sema_init(&lp->cmd_mutex, 0);
init_completion(&lp->execution_cmd);
init_completion(&lp->xceiver_cmd);
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index 179871d9e71f..e1da258bbfb7 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -1742,7 +1742,7 @@ vortex_open(struct net_device *dev)
/* Use the now-standard shared IRQ implementation. */
if ((retval = request_irq(dev->irq, vp->full_bus_master_rx ?
- &boomerang_interrupt : &vortex_interrupt, IRQF_SHARED, dev->name, dev))) {
+ boomerang_interrupt : vortex_interrupt, IRQF_SHARED, dev->name, dev))) {
pr_err("%s: Could not reserve IRQ %d\n", dev->name, dev->irq);
goto err;
}
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index 4a4f6b81e32d..ac422cd332ea 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -561,7 +561,7 @@ rx_status_loop:
if (cp_rx_csum_ok(status))
skb->ip_summed = CHECKSUM_UNNECESSARY;
else
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
skb_put(skb, len);
@@ -754,7 +754,7 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
}
#if CP_VLAN_TAG_USED
- if (cp->vlgrp && vlan_tx_tag_present(skb))
+ if (vlan_tx_tag_present(skb))
vlan_tag = TxVlanTag | swab16(vlan_tx_tag_get(skb));
#endif
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 2cc81a54cbf3..7ca1fc8a3a76 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2,6 +2,9 @@
# Network device configuration
#
+config HAVE_NET_MACB
+ bool
+
menuconfig NETDEVICES
default y if UML
depends on NET
@@ -177,6 +180,13 @@ config NET_SB1000
source "drivers/net/arcnet/Kconfig"
+config MII
+ tristate "Generic Media Independent Interface device support"
+ help
+ Most ethernet controllers have MII transceiver either as an external
+ or internal device. It is safe to say Y or M here even if your
+ ethernet card lacks MII.
+
source "drivers/net/phy/Kconfig"
#
@@ -212,16 +222,9 @@ menuconfig NET_ETHERNET
if NET_ETHERNET
-config MII
- tristate "Generic Media Independent Interface device support"
- help
- Most ethernet controllers have MII transceiver either as an external
- or internal device. It is safe to say Y or M here even if your
- ethernet card lack MII.
-
config MACB
tristate "Atmel MACB support"
- depends on AVR32 || ARCH_AT91SAM9260 || ARCH_AT91SAM9263 || ARCH_AT91SAM9G20 || ARCH_AT91SAM9G45 || ARCH_AT91CAP9
+ depends on HAVE_NET_MACB
select PHYLIB
help
The Atmel MACB ethernet interface is found on many AT32 and AT91
@@ -2428,7 +2431,7 @@ config UGETH_TX_ON_DEMAND
config MV643XX_ETH
tristate "Marvell Discovery (643XX) and Orion ethernet support"
- depends on MV64X60 || PPC32 || PLAT_ORION
+ depends on (MV64X60 || PPC32 || PLAT_ORION) && INET
select INET_LRO
select PHYLIB
help
@@ -2515,6 +2518,18 @@ config S6GMAC
source "drivers/net/stmmac/Kconfig"
+config PCH_GBE
+ tristate "PCH Gigabit Ethernet"
+ depends on PCI
+ ---help---
+ This is a gigabit ethernet driver for Topcliff PCH.
+ Topcliff PCH is the platform controller hub that is used in Intel's
+ general embedded platform.
+ Topcliff PCH has Gigabit Ethernet interface.
+ Using this interface, it is able to access system devices connected
+ to Gigabit Ethernet.
+ This driver enables Gigabit Ethernet function.
+
endif # NETDEV_1000
#
@@ -2803,7 +2818,7 @@ config NIU
config PASEMI_MAC
tristate "PA Semi 1/10Gbit MAC"
- depends on PPC_PASEMI && PCI
+ depends on PPC_PASEMI && PCI && INET
select PHYLIB
select INET_LRO
help
@@ -2869,6 +2884,20 @@ config QLGE
To compile this driver as a module, choose M here: the module
will be called qlge.
+config BNA
+ tristate "Brocade 1010/1020 10Gb Ethernet Driver support"
+ depends on PCI
+ ---help---
+ This driver supports Brocade 1010/1020 10Gb CEE capable Ethernet
+ cards.
+ To compile this driver as a module, choose M here: the module
+ will be called bna.
+
+ For general information and support, go to the Brocade support
+ website at:
+
+ <http://support.brocade.com>
+
source "drivers/net/sfc/Kconfig"
source "drivers/net/benet/Kconfig"
@@ -3202,6 +3231,17 @@ config PPPOE
which contains instruction on how to use this driver (under
the heading "Kernel mode PPPoE").
+config PPTP
+ tristate "PPP over IPv4 (PPTP) (EXPERIMENTAL)"
+ depends on EXPERIMENTAL && PPP && NET_IPGRE_DEMUX
+ help
+ Support for PPP over IPv4.(Point-to-Point Tunneling Protocol)
+
+ This driver requires pppd plugin to work in client mode or
+ modified pptpd (poptop) to work in server mode.
+ See http://accel-pptp.sourceforge.net/ for information how to
+ utilize this module.
+
config PPPOATM
tristate "PPP over ATM"
depends on ATM && PPP
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 3e8f150c4b14..b8bf93d4a132 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_ENIC) += enic/
obj-$(CONFIG_JME) += jme.o
obj-$(CONFIG_BE2NET) += benet/
obj-$(CONFIG_VMXNET3) += vmxnet3/
+obj-$(CONFIG_BNA) += bna/
gianfar_driver-objs := gianfar.o \
gianfar_ethtool.o \
@@ -162,6 +163,7 @@ obj-$(CONFIG_PPP_BSDCOMP) += bsd_comp.o
obj-$(CONFIG_PPP_MPPE) += ppp_mppe.o
obj-$(CONFIG_PPPOE) += pppox.o pppoe.o
obj-$(CONFIG_PPPOL2TP) += pppox.o
+obj-$(CONFIG_PPTP) += pppox.o pptp.o
obj-$(CONFIG_SLIP) += slip.o
obj-$(CONFIG_SLHC) += slhc.o
@@ -296,3 +298,4 @@ obj-$(CONFIG_WIMAX) += wimax/
obj-$(CONFIG_CAIF) += caif/
obj-$(CONFIG_OCTEON_MGMT_ETHERNET) += octeon/
+obj-$(CONFIG_PCH_GBE) += pch_gbe/
diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c
index b9a591604e5b..41d9911202d0 100644
--- a/drivers/net/acenic.c
+++ b/drivers/net/acenic.c
@@ -2033,7 +2033,7 @@ static void ace_rx_int(struct net_device *dev, u32 rxretprd, u32 rxretcsm)
skb->csum = htons(csum);
skb->ip_summed = CHECKSUM_COMPLETE;
} else {
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
}
/* send it up */
diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c
index 585c25f4b60c..2ca880b4c0db 100644
--- a/drivers/net/amd8111e.c
+++ b/drivers/net/amd8111e.c
@@ -396,7 +396,7 @@ static int amd8111e_set_coalesce(struct net_device * dev, enum coal_mode cmod)
event_count = coal_conf->rx_event_count;
if( timeout > MAX_TIMEOUT ||
event_count > MAX_EVENT_COUNT )
- return -EINVAL;
+ return -EINVAL;
timeout = timeout * DELAY_TIMER_CONV;
writel(VAL0|STINTEN, mmio+INTEN0);
@@ -409,7 +409,7 @@ static int amd8111e_set_coalesce(struct net_device * dev, enum coal_mode cmod)
event_count = coal_conf->tx_event_count;
if( timeout > MAX_TIMEOUT ||
event_count > MAX_EVENT_COUNT )
- return -EINVAL;
+ return -EINVAL;
timeout = timeout * DELAY_TIMER_CONV;
@@ -903,18 +903,18 @@ static int amd8111e_read_mib(void __iomem *mmio, u8 MIB_COUNTER)
}
/*
-This function reads the mib registers and returns the hardware statistics. It updates previous internal driver statistics with new values.
-*/
-static struct net_device_stats *amd8111e_get_stats(struct net_device * dev)
+ * This function reads the mib registers and returns the hardware statistics.
+ * It updates previous internal driver statistics with new values.
+ */
+static struct net_device_stats *amd8111e_get_stats(struct net_device *dev)
{
struct amd8111e_priv *lp = netdev_priv(dev);
void __iomem *mmio = lp->mmio;
unsigned long flags;
- /* struct net_device_stats *prev_stats = &lp->prev_stats; */
- struct net_device_stats* new_stats = &lp->stats;
+ struct net_device_stats *new_stats = &dev->stats;
- if(!lp->opened)
- return &lp->stats;
+ if (!lp->opened)
+ return new_stats;
spin_lock_irqsave (&lp->lock, flags);
/* stats.rx_packets */
@@ -1315,7 +1315,7 @@ static netdev_tx_t amd8111e_start_xmit(struct sk_buff *skb,
lp->tx_ring[tx_index].tx_flags = 0;
#if AMD8111E_VLAN_TAG_USED
- if((lp->vlgrp != NULL) && vlan_tx_tag_present(skb)){
+ if (vlan_tx_tag_present(skb)) {
lp->tx_ring[tx_index].tag_ctrl_cmd |=
cpu_to_le16(TCC_VLAN_INSERT);
lp->tx_ring[tx_index].tag_ctrl_info =
diff --git a/drivers/net/amd8111e.h b/drivers/net/amd8111e.h
index ac36eb6981e3..b5926af03a7e 100644
--- a/drivers/net/amd8111e.h
+++ b/drivers/net/amd8111e.h
@@ -787,7 +787,6 @@ struct amd8111e_priv{
struct vlan_group *vlgrp;
#endif
char opened;
- struct net_device_stats stats;
unsigned int drv_rx_errors;
struct amd8111e_coalesce_conf coal_conf;
diff --git a/drivers/net/appletalk/Kconfig b/drivers/net/appletalk/Kconfig
index 0a0e0cd81a23..20f97e7017ce 100644
--- a/drivers/net/appletalk/Kconfig
+++ b/drivers/net/appletalk/Kconfig
@@ -3,6 +3,7 @@
#
config ATALK
tristate "Appletalk protocol support"
+ depends on BKL # waiting to be removed from net/appletalk/ddp.c
select LLC
---help---
AppleTalk is the protocol that Apple computers can use to communicate
diff --git a/drivers/net/appletalk/ipddp.c b/drivers/net/appletalk/ipddp.c
index 0362c8d31a08..10d0dba572c2 100644
--- a/drivers/net/appletalk/ipddp.c
+++ b/drivers/net/appletalk/ipddp.c
@@ -244,7 +244,7 @@ static int ipddp_delete(struct ipddp_route *rt)
}
spin_unlock_bh(&ipddp_route_lock);
- return (-ENOENT);
+ return -ENOENT;
}
/*
@@ -259,10 +259,10 @@ static struct ipddp_route* __ipddp_find_route(struct ipddp_route *rt)
if(f->ip == rt->ip &&
f->at.s_net == rt->at.s_net &&
f->at.s_node == rt->at.s_node)
- return (f);
+ return f;
}
- return (NULL);
+ return NULL;
}
static int ipddp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
@@ -279,7 +279,7 @@ static int ipddp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
switch(cmd)
{
case SIOCADDIPDDPRT:
- return (ipddp_create(&rcp));
+ return ipddp_create(&rcp);
case SIOCFINDIPDDPRT:
spin_lock_bh(&ipddp_route_lock);
@@ -297,7 +297,7 @@ static int ipddp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
return -ENOENT;
case SIOCDELIPDDPRT:
- return (ipddp_delete(&rcp));
+ return ipddp_delete(&rcp);
default:
return -EINVAL;
diff --git a/drivers/net/appletalk/ltpc.c b/drivers/net/appletalk/ltpc.c
index adc07551739e..e69eead12ec7 100644
--- a/drivers/net/appletalk/ltpc.c
+++ b/drivers/net/appletalk/ltpc.c
@@ -727,7 +727,7 @@ static int sendup_buffer (struct net_device *dev)
if (ltc->command != LT_RCVLAP) {
printk("unknown command 0x%02x from ltpc card\n",ltc->command);
- return(-1);
+ return -1;
}
dnode = ltc->dnode;
snode = ltc->snode;
diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c
index 8c496fb1ac9e..62f21106efec 100644
--- a/drivers/net/arm/am79c961a.c
+++ b/drivers/net/arm/am79c961a.c
@@ -300,8 +300,6 @@ am79c961_open(struct net_device *dev)
struct dev_priv *priv = netdev_priv(dev);
int ret;
- memset (&priv->stats, 0, sizeof (priv->stats));
-
ret = request_irq(dev->irq, am79c961_interrupt, 0, dev->name, dev);
if (ret)
return ret;
@@ -347,8 +345,7 @@ am79c961_close(struct net_device *dev)
*/
static struct net_device_stats *am79c961_getstats (struct net_device *dev)
{
- struct dev_priv *priv = netdev_priv(dev);
- return &priv->stats;
+ return &dev->stats;
}
static void am79c961_mc_hash(char *addr, unsigned short *hash)
@@ -510,14 +507,14 @@ am79c961_rx(struct net_device *dev, struct dev_priv *priv)
if ((status & (RMD_ERR|RMD_STP|RMD_ENP)) != (RMD_STP|RMD_ENP)) {
am_writeword (dev, hdraddr + 2, RMD_OWN);
- priv->stats.rx_errors ++;
+ dev->stats.rx_errors++;
if (status & RMD_ERR) {
if (status & RMD_FRAM)
- priv->stats.rx_frame_errors ++;
+ dev->stats.rx_frame_errors++;
if (status & RMD_CRC)
- priv->stats.rx_crc_errors ++;
+ dev->stats.rx_crc_errors++;
} else if (status & RMD_STP)
- priv->stats.rx_length_errors ++;
+ dev->stats.rx_length_errors++;
continue;
}
@@ -531,12 +528,12 @@ am79c961_rx(struct net_device *dev, struct dev_priv *priv)
am_writeword(dev, hdraddr + 2, RMD_OWN);
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
- priv->stats.rx_bytes += len;
- priv->stats.rx_packets ++;
+ dev->stats.rx_bytes += len;
+ dev->stats.rx_packets++;
} else {
am_writeword (dev, hdraddr + 2, RMD_OWN);
printk (KERN_WARNING "%s: memory squeeze, dropping packet.\n", dev->name);
- priv->stats.rx_dropped ++;
+ dev->stats.rx_dropped++;
break;
}
} while (1);
@@ -565,7 +562,7 @@ am79c961_tx(struct net_device *dev, struct dev_priv *priv)
if (status & TMD_ERR) {
u_int status2;
- priv->stats.tx_errors ++;
+ dev->stats.tx_errors++;
status2 = am_readword (dev, hdraddr + 6);
@@ -575,18 +572,18 @@ am79c961_tx(struct net_device *dev, struct dev_priv *priv)
am_writeword (dev, hdraddr + 6, 0);
if (status2 & TST_RTRY)
- priv->stats.collisions += 16;
+ dev->stats.collisions += 16;
if (status2 & TST_LCOL)
- priv->stats.tx_window_errors ++;
+ dev->stats.tx_window_errors++;
if (status2 & TST_LCAR)
- priv->stats.tx_carrier_errors ++;
+ dev->stats.tx_carrier_errors++;
if (status2 & TST_UFLO)
- priv->stats.tx_fifo_errors ++;
+ dev->stats.tx_fifo_errors++;
continue;
}
- priv->stats.tx_packets ++;
+ dev->stats.tx_packets++;
len = am_readword (dev, hdraddr + 4);
- priv->stats.tx_bytes += -len;
+ dev->stats.tx_bytes += -len;
} while (priv->txtail != priv->txhead);
netif_wake_queue(dev);
@@ -616,7 +613,7 @@ am79c961_interrupt(int irq, void *dev_id)
}
if (status & CSR0_MISS) {
handled = 1;
- priv->stats.rx_dropped ++;
+ dev->stats.rx_dropped++;
}
if (status & CSR0_CERR) {
handled = 1;
diff --git a/drivers/net/arm/am79c961a.h b/drivers/net/arm/am79c961a.h
index 483009fe6ec2..fd634d32756b 100644
--- a/drivers/net/arm/am79c961a.h
+++ b/drivers/net/arm/am79c961a.h
@@ -130,7 +130,6 @@
#define ISALED0_LNKST 0x8000
struct dev_priv {
- struct net_device_stats stats;
unsigned long rxbuffer[RX_BUFFERS];
unsigned long txbuffer[TX_BUFFERS];
unsigned char txhead;
diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c
index 4a5ec9470aa1..5a77001b6d10 100644
--- a/drivers/net/arm/ep93xx_eth.c
+++ b/drivers/net/arm/ep93xx_eth.c
@@ -175,8 +175,6 @@ struct ep93xx_priv
struct net_device *dev;
struct napi_struct napi;
- struct net_device_stats stats;
-
struct mii_if_info mii;
u8 mdc_divisor;
};
@@ -230,12 +228,6 @@ static void ep93xx_mdio_write(struct net_device *dev, int phy_id, int reg, int d
pr_info("mdio write timed out\n");
}
-static struct net_device_stats *ep93xx_get_stats(struct net_device *dev)
-{
- struct ep93xx_priv *ep = netdev_priv(dev);
- return &(ep->stats);
-}
-
static int ep93xx_rx(struct net_device *dev, int processed, int budget)
{
struct ep93xx_priv *ep = netdev_priv(dev);
@@ -267,15 +259,15 @@ static int ep93xx_rx(struct net_device *dev, int processed, int budget)
pr_crit("entry mismatch %.8x %.8x\n", rstat0, rstat1);
if (!(rstat0 & RSTAT0_RWE)) {
- ep->stats.rx_errors++;
+ dev->stats.rx_errors++;
if (rstat0 & RSTAT0_OE)
- ep->stats.rx_fifo_errors++;
+ dev->stats.rx_fifo_errors++;
if (rstat0 & RSTAT0_FE)
- ep->stats.rx_frame_errors++;
+ dev->stats.rx_frame_errors++;
if (rstat0 & (RSTAT0_RUNT | RSTAT0_EDATA))
- ep->stats.rx_length_errors++;
+ dev->stats.rx_length_errors++;
if (rstat0 & RSTAT0_CRCE)
- ep->stats.rx_crc_errors++;
+ dev->stats.rx_crc_errors++;
goto err;
}
@@ -300,10 +292,10 @@ static int ep93xx_rx(struct net_device *dev, int processed, int budget)
netif_receive_skb(skb);
- ep->stats.rx_packets++;
- ep->stats.rx_bytes += length;
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += length;
} else {
- ep->stats.rx_dropped++;
+ dev->stats.rx_dropped++;
}
err:
@@ -359,7 +351,7 @@ static int ep93xx_xmit(struct sk_buff *skb, struct net_device *dev)
int entry;
if (unlikely(skb->len > MAX_PKT_SIZE)) {
- ep->stats.tx_dropped++;
+ dev->stats.tx_dropped++;
dev_kfree_skb(skb);
return NETDEV_TX_OK;
}
@@ -415,17 +407,17 @@ static void ep93xx_tx_complete(struct net_device *dev)
if (tstat0 & TSTAT0_TXWE) {
int length = ep->descs->tdesc[entry].tdesc1 & 0xfff;
- ep->stats.tx_packets++;
- ep->stats.tx_bytes += length;
+ dev->stats.tx_packets++;
+ dev->stats.tx_bytes += length;
} else {
- ep->stats.tx_errors++;
+ dev->stats.tx_errors++;
}
if (tstat0 & TSTAT0_OW)
- ep->stats.tx_window_errors++;
+ dev->stats.tx_window_errors++;
if (tstat0 & TSTAT0_TXU)
- ep->stats.tx_fifo_errors++;
- ep->stats.collisions += (tstat0 >> 16) & 0x1f;
+ dev->stats.tx_fifo_errors++;
+ dev->stats.collisions += (tstat0 >> 16) & 0x1f;
ep->tx_clean_pointer = (entry + 1) & (TX_QUEUE_ENTRIES - 1);
if (ep->tx_pending == TX_QUEUE_ENTRIES)
@@ -758,7 +750,6 @@ static const struct net_device_ops ep93xx_netdev_ops = {
.ndo_open = ep93xx_open,
.ndo_stop = ep93xx_close,
.ndo_start_xmit = ep93xx_xmit,
- .ndo_get_stats = ep93xx_get_stats,
.ndo_do_ioctl = ep93xx_ioctl,
.ndo_validate_addr = eth_validate_addr,
.ndo_change_mtu = eth_change_mtu,
diff --git a/drivers/net/arm/ether1.c b/drivers/net/arm/ether1.c
index b17ab5153f51..b00781c02d5d 100644
--- a/drivers/net/arm/ether1.c
+++ b/drivers/net/arm/ether1.c
@@ -68,7 +68,6 @@ static int ether1_open(struct net_device *dev);
static int ether1_sendpacket(struct sk_buff *skb, struct net_device *dev);
static irqreturn_t ether1_interrupt(int irq, void *dev_id);
static int ether1_close(struct net_device *dev);
-static struct net_device_stats *ether1_getstats(struct net_device *dev);
static void ether1_setmulticastlist(struct net_device *dev);
static void ether1_timeout(struct net_device *dev);
@@ -649,8 +648,6 @@ ether1_open (struct net_device *dev)
if (request_irq(dev->irq, ether1_interrupt, 0, "ether1", dev))
return -EAGAIN;
- memset (&priv(dev)->stats, 0, sizeof (struct net_device_stats));
-
if (ether1_init_for_open (dev)) {
free_irq (dev->irq, dev);
return -EAGAIN;
@@ -673,7 +670,7 @@ ether1_timeout(struct net_device *dev)
if (ether1_init_for_open (dev))
printk (KERN_ERR "%s: unable to restart interface\n", dev->name);
- priv(dev)->stats.tx_errors++;
+ dev->stats.tx_errors++;
netif_wake_queue(dev);
}
@@ -802,21 +799,21 @@ again:
while (nop.nop_status & STAT_COMPLETE) {
if (nop.nop_status & STAT_OK) {
- priv(dev)->stats.tx_packets ++;
- priv(dev)->stats.collisions += (nop.nop_status & STAT_COLLISIONS);
+ dev->stats.tx_packets++;
+ dev->stats.collisions += (nop.nop_status & STAT_COLLISIONS);
} else {
- priv(dev)->stats.tx_errors ++;
+ dev->stats.tx_errors++;
if (nop.nop_status & STAT_COLLAFTERTX)
- priv(dev)->stats.collisions ++;
+ dev->stats.collisions++;
if (nop.nop_status & STAT_NOCARRIER)
- priv(dev)->stats.tx_carrier_errors ++;
+ dev->stats.tx_carrier_errors++;
if (nop.nop_status & STAT_TXLOSTCTS)
printk (KERN_WARNING "%s: cts lost\n", dev->name);
if (nop.nop_status & STAT_TXSLOWDMA)
- priv(dev)->stats.tx_fifo_errors ++;
+ dev->stats.tx_fifo_errors++;
if (nop.nop_status & STAT_COLLEXCESSIVE)
- priv(dev)->stats.collisions += 16;
+ dev->stats.collisions += 16;
}
if (nop.nop_link == caddr) {
@@ -879,13 +876,13 @@ ether1_recv_done (struct net_device *dev)
skb->protocol = eth_type_trans (skb, dev);
netif_rx (skb);
- priv(dev)->stats.rx_packets ++;
+ dev->stats.rx_packets++;
} else
- priv(dev)->stats.rx_dropped ++;
+ dev->stats.rx_dropped++;
} else {
printk(KERN_WARNING "%s: %s\n", dev->name,
(rbd.rbd_status & RBD_EOF) ? "oversized packet" : "acnt not valid");
- priv(dev)->stats.rx_dropped ++;
+ dev->stats.rx_dropped++;
}
nexttail = ether1_readw(dev, priv(dev)->rx_tail, rfd_t, rfd_link, NORMALIRQS);
@@ -939,7 +936,7 @@ ether1_interrupt (int irq, void *dev_id)
printk (KERN_WARNING "%s: RU went not ready: RU suspended\n", dev->name);
ether1_writew(dev, SCB_CMDRXRESUME, SCB_ADDR, scb_t, scb_command, NORMALIRQS);
writeb(CTRL_CA, REG_CONTROL);
- priv(dev)->stats.rx_dropped ++; /* we suspended due to lack of buffer space */
+ dev->stats.rx_dropped++; /* we suspended due to lack of buffer space */
} else
printk(KERN_WARNING "%s: RU went not ready: %04X\n", dev->name,
ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS));
@@ -962,12 +959,6 @@ ether1_close (struct net_device *dev)
return 0;
}
-static struct net_device_stats *
-ether1_getstats (struct net_device *dev)
-{
- return &priv(dev)->stats;
-}
-
/*
* Set or clear the multicast filter for this adaptor.
* num_addrs == -1 Promiscuous mode, receive all packets.
@@ -994,7 +985,6 @@ static const struct net_device_ops ether1_netdev_ops = {
.ndo_open = ether1_open,
.ndo_stop = ether1_close,
.ndo_start_xmit = ether1_sendpacket,
- .ndo_get_stats = ether1_getstats,
.ndo_set_multicast_list = ether1_setmulticastlist,
.ndo_tx_timeout = ether1_timeout,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/arm/ether1.h b/drivers/net/arm/ether1.h
index c8a4b2389d85..3a5830ab3dc7 100644
--- a/drivers/net/arm/ether1.h
+++ b/drivers/net/arm/ether1.h
@@ -38,7 +38,6 @@
struct ether1_priv {
void __iomem *base;
- struct net_device_stats stats;
unsigned int tx_link;
unsigned int tx_head;
volatile unsigned int tx_tail;
diff --git a/drivers/net/arm/ether3.c b/drivers/net/arm/ether3.c
index 1361b7367c28..44a8746f4014 100644
--- a/drivers/net/arm/ether3.c
+++ b/drivers/net/arm/ether3.c
@@ -81,7 +81,6 @@ static int ether3_open (struct net_device *dev);
static int ether3_sendpacket (struct sk_buff *skb, struct net_device *dev);
static irqreturn_t ether3_interrupt (int irq, void *dev_id);
static int ether3_close (struct net_device *dev);
-static struct net_device_stats *ether3_getstats (struct net_device *dev);
static void ether3_setmulticastlist (struct net_device *dev);
static void ether3_timeout(struct net_device *dev);
@@ -323,8 +322,6 @@ ether3_init_for_open(struct net_device *dev)
{
int i;
- memset(&priv(dev)->stats, 0, sizeof(struct net_device_stats));
-
/* Reset the chip */
ether3_outw(CFG2_RESET, REG_CONFIG2);
udelay(4);
@@ -442,15 +439,6 @@ ether3_close(struct net_device *dev)
}
/*
- * Get the current statistics. This may be called with the card open or
- * closed.
- */
-static struct net_device_stats *ether3_getstats(struct net_device *dev)
-{
- return &priv(dev)->stats;
-}
-
-/*
* Set or clear promiscuous/multicast mode filter for this adaptor.
*
* We don't attempt any packet filtering. The card may have a SEEQ 8004
@@ -490,7 +478,7 @@ static void ether3_timeout(struct net_device *dev)
local_irq_restore(flags);
priv(dev)->regs.config2 |= CFG2_CTRLO;
- priv(dev)->stats.tx_errors += 1;
+ dev->stats.tx_errors += 1;
ether3_outw(priv(dev)->regs.config2, REG_CONFIG2);
priv(dev)->tx_head = priv(dev)->tx_tail = 0;
@@ -509,7 +497,7 @@ ether3_sendpacket(struct sk_buff *skb, struct net_device *dev)
if (priv(dev)->broken) {
dev_kfree_skb(skb);
- priv(dev)->stats.tx_dropped ++;
+ dev->stats.tx_dropped++;
netif_start_queue(dev);
return NETDEV_TX_OK;
}
@@ -673,7 +661,7 @@ if (next_ptr < RX_START || next_ptr >= RX_END) {
} else
goto dropping;
} else {
- struct net_device_stats *stats = &priv(dev)->stats;
+ struct net_device_stats *stats = &dev->stats;
ether3_outw(next_ptr >> 8, REG_RECVEND);
if (status & RXSTAT_OVERSIZE) stats->rx_over_errors ++;
if (status & RXSTAT_CRCERROR) stats->rx_crc_errors ++;
@@ -685,14 +673,14 @@ if (next_ptr < RX_START || next_ptr >= RX_END) {
while (-- maxcnt);
done:
- priv(dev)->stats.rx_packets += received;
+ dev->stats.rx_packets += received;
priv(dev)->rx_head = next_ptr;
/*
* If rx went off line, then that means that the buffer may be full. We
* have dropped at least one packet.
*/
if (!(ether3_inw(REG_STATUS) & STAT_RXON)) {
- priv(dev)->stats.rx_dropped ++;
+ dev->stats.rx_dropped++;
ether3_outw(next_ptr, REG_RECVPTR);
ether3_outw(priv(dev)->regs.command | CMD_RXON, REG_COMMAND);
}
@@ -710,7 +698,7 @@ dropping:{
last_warned = jiffies;
printk("%s: memory squeeze, dropping packet.\n", dev->name);
}
- priv(dev)->stats.rx_dropped ++;
+ dev->stats.rx_dropped++;
goto done;
}
}
@@ -743,13 +731,13 @@ static void ether3_tx(struct net_device *dev)
* Update errors
*/
if (!(status & (TXSTAT_BABBLED | TXSTAT_16COLLISIONS)))
- priv(dev)->stats.tx_packets++;
+ dev->stats.tx_packets++;
else {
- priv(dev)->stats.tx_errors ++;
+ dev->stats.tx_errors++;
if (status & TXSTAT_16COLLISIONS)
- priv(dev)->stats.collisions += 16;
+ dev->stats.collisions += 16;
if (status & TXSTAT_BABBLED)
- priv(dev)->stats.tx_fifo_errors ++;
+ dev->stats.tx_fifo_errors++;
}
tx_tail = (tx_tail + 1) & 15;
@@ -773,7 +761,6 @@ static const struct net_device_ops ether3_netdev_ops = {
.ndo_open = ether3_open,
.ndo_stop = ether3_close,
.ndo_start_xmit = ether3_sendpacket,
- .ndo_get_stats = ether3_getstats,
.ndo_set_multicast_list = ether3_setmulticastlist,
.ndo_tx_timeout = ether3_timeout,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/arm/ether3.h b/drivers/net/arm/ether3.h
index 1921a3a07da7..2db63b08bdf3 100644
--- a/drivers/net/arm/ether3.h
+++ b/drivers/net/arm/ether3.h
@@ -164,7 +164,6 @@ struct dev_priv {
unsigned char tx_head; /* buffer nr to insert next packet */
unsigned char tx_tail; /* buffer nr of transmitting packet */
unsigned int rx_head; /* address to fetch next packet from */
- struct net_device_stats stats;
struct timer_list timer;
int broken; /* 0 = ok, 1 = something went wrong */
};
diff --git a/drivers/net/atarilance.c b/drivers/net/atarilance.c
index b57d7dee389a..3134e5326231 100644
--- a/drivers/net/atarilance.c
+++ b/drivers/net/atarilance.c
@@ -362,7 +362,7 @@ static void *slow_memcpy( void *dst, const void *src, size_t len )
*cto++ = *cfrom++;
MFPDELAY();
}
- return( dst );
+ return dst;
}
@@ -449,7 +449,7 @@ static noinline int __init addr_accessible(volatile void *regp, int wordflag,
vbr[2] = save_berr;
local_irq_restore(flags);
- return( ret );
+ return ret;
}
static const struct net_device_ops lance_netdev_ops = {
@@ -526,7 +526,7 @@ static unsigned long __init lance_probe1( struct net_device *dev,
goto probe_ok;
probe_fail:
- return( 0 );
+ return 0;
probe_ok:
lp = netdev_priv(dev);
@@ -556,7 +556,7 @@ static unsigned long __init lance_probe1( struct net_device *dev,
if (request_irq(IRQ_AUTO_5, lance_interrupt, IRQ_TYPE_PRIO,
"PAM/Riebl-ST Ethernet", dev)) {
printk( "Lance: request for irq %d failed\n", IRQ_AUTO_5 );
- return( 0 );
+ return 0;
}
dev->irq = (unsigned short)IRQ_AUTO_5;
}
@@ -568,12 +568,12 @@ static unsigned long __init lance_probe1( struct net_device *dev,
unsigned long irq = atari_register_vme_int();
if (!irq) {
printk( "Lance: request for VME interrupt failed\n" );
- return( 0 );
+ return 0;
}
if (request_irq(irq, lance_interrupt, IRQ_TYPE_PRIO,
"Riebl-VME Ethernet", dev)) {
printk( "Lance: request for irq %ld failed\n", irq );
- return( 0 );
+ return 0;
}
dev->irq = irq;
}
@@ -637,7 +637,7 @@ static unsigned long __init lance_probe1( struct net_device *dev,
/* XXX MSch */
dev->watchdog_timeo = TX_TIMEOUT;
- return( 1 );
+ return 1;
}
@@ -666,7 +666,7 @@ static int lance_open( struct net_device *dev )
DPRINTK( 2, ( "lance_open(): opening %s failed, i=%d, csr0=%04x\n",
dev->name, i, DREG ));
DREG = CSR0_STOP;
- return( -EIO );
+ return -EIO;
}
DREG = CSR0_IDON;
DREG = CSR0_STRT;
@@ -676,7 +676,7 @@ static int lance_open( struct net_device *dev )
DPRINTK( 2, ( "%s: LANCE is open, csr0 %04x\n", dev->name, DREG ));
- return( 0 );
+ return 0;
}
@@ -1126,13 +1126,13 @@ static int lance_set_mac_address( struct net_device *dev, void *addr )
int i;
if (lp->cardtype != OLD_RIEBL && lp->cardtype != NEW_RIEBL)
- return( -EOPNOTSUPP );
+ return -EOPNOTSUPP;
if (netif_running(dev)) {
/* Only possible while card isn't started */
DPRINTK( 1, ( "%s: hwaddr can be set only while card isn't open.\n",
dev->name ));
- return( -EIO );
+ return -EIO;
}
memcpy( dev->dev_addr, saddr->sa_data, dev->addr_len );
@@ -1142,7 +1142,7 @@ static int lance_set_mac_address( struct net_device *dev, void *addr )
/* set also the magic for future sessions */
*RIEBL_MAGIC_ADDR = RIEBL_MAGIC;
- return( 0 );
+ return 0;
}
diff --git a/drivers/net/atl1c/atl1c.h b/drivers/net/atl1c/atl1c.h
index 52abbbdf8a08..ef4115b897bf 100644
--- a/drivers/net/atl1c/atl1c.h
+++ b/drivers/net/atl1c/atl1c.h
@@ -559,7 +559,6 @@ struct atl1c_adapter {
struct napi_struct napi;
struct atl1c_hw hw;
struct atl1c_hw_stats hw_stats;
- struct net_device_stats net_stats;
struct mii_if_info mii; /* MII interface info */
u16 rx_buffer_len;
diff --git a/drivers/net/atl1c/atl1c_hw.c b/drivers/net/atl1c/atl1c_hw.c
index d8501f060957..919080b2c3a5 100644
--- a/drivers/net/atl1c/atl1c_hw.c
+++ b/drivers/net/atl1c/atl1c_hw.c
@@ -480,7 +480,7 @@ int atl1c_phy_reset(struct atl1c_hw *hw)
atl1c_write_phy_reg(hw, MII_DBG_DATA, 0x929D);
}
if (hw->nic_type == athr_l1c || hw->nic_type == athr_l2c_b2
- || hw->nic_type == athr_l2c || hw->nic_type == athr_l2c) {
+ || hw->nic_type == athr_l2c) {
atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x29);
atl1c_write_phy_reg(hw, MII_DBG_DATA, 0xB6DD);
}
diff --git a/drivers/net/atl1c/atl1c_main.c b/drivers/net/atl1c/atl1c_main.c
index c7b8ef507ebd..99ffcf667d1f 100644
--- a/drivers/net/atl1c/atl1c_main.c
+++ b/drivers/net/atl1c/atl1c_main.c
@@ -1562,7 +1562,7 @@ static struct net_device_stats *atl1c_get_stats(struct net_device *netdev)
{
struct atl1c_adapter *adapter = netdev_priv(netdev);
struct atl1c_hw_stats *hw_stats = &adapter->hw_stats;
- struct net_device_stats *net_stats = &adapter->net_stats;
+ struct net_device_stats *net_stats = &netdev->stats;
atl1c_update_hw_stats(adapter);
net_stats->rx_packets = hw_stats->rx_ok;
@@ -1590,7 +1590,7 @@ static struct net_device_stats *atl1c_get_stats(struct net_device *netdev)
net_stats->tx_aborted_errors = hw_stats->tx_abort_col;
net_stats->tx_window_errors = hw_stats->tx_late_col;
- return &adapter->net_stats;
+ return net_stats;
}
static inline void atl1c_clear_phy_int(struct atl1c_adapter *adapter)
@@ -1700,7 +1700,7 @@ static irqreturn_t atl1c_intr(int irq, void *data)
/* link event */
if (status & (ISR_GPHY | ISR_MANUAL)) {
- adapter->net_stats.tx_carrier_errors++;
+ netdev->stats.tx_carrier_errors++;
atl1c_link_chg_event(adapter);
break;
}
@@ -1719,7 +1719,7 @@ static inline void atl1c_rx_checksum(struct atl1c_adapter *adapter,
* cannot figure out if the packet is fragmented or not,
* so we tell the KERNEL CHECKSUM_NONE
*/
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
}
static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter, const int ringid)
@@ -2243,7 +2243,7 @@ static netdev_tx_t atl1c_xmit_frame(struct sk_buff *skb,
return NETDEV_TX_OK;
}
- if (unlikely(adapter->vlgrp && vlan_tx_tag_present(skb))) {
+ if (unlikely(vlan_tx_tag_present(skb))) {
u16 vlan = vlan_tx_tag_get(skb);
__le16 tag;
diff --git a/drivers/net/atl1e/atl1e_main.c b/drivers/net/atl1e/atl1e_main.c
index 1acea5774e89..ef6349bf3b33 100644
--- a/drivers/net/atl1e/atl1e_main.c
+++ b/drivers/net/atl1e/atl1e_main.c
@@ -1331,7 +1331,7 @@ static inline void atl1e_rx_checksum(struct atl1e_adapter *adapter,
u16 pkt_flags;
u16 err_flags;
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
pkt_flags = prrs->pkt_flag;
err_flags = prrs->err_flag;
if (((pkt_flags & RRS_IS_IPV4) || (pkt_flags & RRS_IS_IPV6)) &&
@@ -1814,7 +1814,7 @@ static netdev_tx_t atl1e_xmit_frame(struct sk_buff *skb,
tpd = atl1e_get_tpd(adapter);
- if (unlikely(adapter->vlgrp && vlan_tx_tag_present(skb))) {
+ if (unlikely(vlan_tx_tag_present(skb))) {
u16 vlan_tag = vlan_tx_tag_get(skb);
u16 atl1e_vlan_tag;
@@ -2316,7 +2316,7 @@ static int __devinit atl1e_probe(struct pci_dev *pdev,
netif_napi_add(netdev, &adapter->napi, atl1e_clean, 64);
init_timer(&adapter->phy_config_timer);
- adapter->phy_config_timer.function = &atl1e_phy_config;
+ adapter->phy_config_timer.function = atl1e_phy_config;
adapter->phy_config_timer.data = (unsigned long) adapter;
/* get user settings */
diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c
index c73be2848319..dbd27b8e66bd 100644
--- a/drivers/net/atlx/atl1.c
+++ b/drivers/net/atlx/atl1.c
@@ -1811,7 +1811,7 @@ static void atl1_rx_checksum(struct atl1_adapter *adapter,
* the higher layers and let it be sorted out there.
*/
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
if (unlikely(rrd->pkt_flg & PACKET_FLAG_ERR)) {
if (rrd->err_flg & (ERR_FLAG_CRC | ERR_FLAG_TRUNC |
@@ -2100,9 +2100,9 @@ static u16 atl1_tpd_avail(struct atl1_tpd_ring *tpd_ring)
{
u16 next_to_clean = atomic_read(&tpd_ring->next_to_clean);
u16 next_to_use = atomic_read(&tpd_ring->next_to_use);
- return ((next_to_clean > next_to_use) ?
+ return (next_to_clean > next_to_use) ?
next_to_clean - next_to_use - 1 :
- tpd_ring->count + next_to_clean - next_to_use - 1);
+ tpd_ring->count + next_to_clean - next_to_use - 1;
}
static int atl1_tso(struct atl1_adapter *adapter, struct sk_buff *skb,
@@ -2408,7 +2408,7 @@ static netdev_tx_t atl1_xmit_frame(struct sk_buff *skb,
(u16) atomic_read(&tpd_ring->next_to_use));
memset(ptpd, 0, sizeof(struct tx_packet_desc));
- if (adapter->vlgrp && vlan_tx_tag_present(skb)) {
+ if (vlan_tx_tag_present(skb)) {
vlan_tag = vlan_tx_tag_get(skb);
vlan_tag = (vlan_tag << 4) | (vlan_tag >> 13) |
((vlan_tag >> 9) & 0x8);
@@ -3043,7 +3043,7 @@ static int __devinit atl1_probe(struct pci_dev *pdev,
netif_carrier_off(netdev);
netif_stop_queue(netdev);
- setup_timer(&adapter->phy_config_timer, &atl1_phy_config,
+ setup_timer(&adapter->phy_config_timer, atl1_phy_config,
(unsigned long)adapter);
adapter->phy_timer_pending = false;
diff --git a/drivers/net/atlx/atl2.c b/drivers/net/atlx/atl2.c
index 8da87383fb39..35b14bec1207 100644
--- a/drivers/net/atlx/atl2.c
+++ b/drivers/net/atlx/atl2.c
@@ -51,10 +51,10 @@
#define ATL2_DRV_VERSION "2.2.3"
-static char atl2_driver_name[] = "atl2";
+static const char atl2_driver_name[] = "atl2";
static const char atl2_driver_string[] = "Atheros(R) L2 Ethernet Driver";
-static char atl2_copyright[] = "Copyright (c) 2007 Atheros Corporation.";
-static char atl2_driver_version[] = ATL2_DRV_VERSION;
+static const char atl2_copyright[] = "Copyright (c) 2007 Atheros Corporation.";
+static const char atl2_driver_version[] = ATL2_DRV_VERSION;
MODULE_AUTHOR("Atheros Corporation <xiong.huang@atheros.com>, Chris Snook <csnook@redhat.com>");
MODULE_DESCRIPTION("Atheros Fast Ethernet Network Driver");
@@ -870,7 +870,7 @@ static netdev_tx_t atl2_xmit_frame(struct sk_buff *skb,
offset = ((u32)(skb->len-copy_len + 3) & ~3);
}
#ifdef NETIF_F_HW_VLAN_TX
- if (adapter->vlgrp && vlan_tx_tag_present(skb)) {
+ if (vlan_tx_tag_present(skb)) {
u16 vlan_tag = vlan_tx_tag_get(skb);
vlan_tag = (vlan_tag << 4) |
(vlan_tag >> 13) |
@@ -1444,11 +1444,11 @@ static int __devinit atl2_probe(struct pci_dev *pdev,
atl2_check_options(adapter);
init_timer(&adapter->watchdog_timer);
- adapter->watchdog_timer.function = &atl2_watchdog;
+ adapter->watchdog_timer.function = atl2_watchdog;
adapter->watchdog_timer.data = (unsigned long) adapter;
init_timer(&adapter->phy_config_timer);
- adapter->phy_config_timer.function = &atl2_phy_config;
+ adapter->phy_config_timer.function = atl2_phy_config;
adapter->phy_config_timer.data = (unsigned long) adapter;
INIT_WORK(&adapter->reset_task, atl2_reset_task);
diff --git a/drivers/net/atp.c b/drivers/net/atp.c
index bd2f9d331dac..dfd96b20547f 100644
--- a/drivers/net/atp.c
+++ b/drivers/net/atp.c
@@ -445,7 +445,7 @@ static int net_open(struct net_device *dev)
init_timer(&lp->timer);
lp->timer.expires = jiffies + TIMED_CHECKER;
lp->timer.data = (unsigned long)dev;
- lp->timer.function = &atp_timed_checker; /* timer handler */
+ lp->timer.function = atp_timed_checker; /* timer handler */
add_timer(&lp->timer);
netif_start_queue(dev);
diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
index 15ae6df2ff00..43489f89c142 100644
--- a/drivers/net/au1000_eth.c
+++ b/drivers/net/au1000_eth.c
@@ -13,7 +13,7 @@
* converted to use linux-2.6.x's PHY framework
*
* Author: MontaVista Software, Inc.
- * ppopov@mvista.com or source@mvista.com
+ * ppopov@mvista.com or source@mvista.com
*
* ########################################################################
*
@@ -34,6 +34,8 @@
*
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/capability.h>
#include <linux/dma-mapping.h>
#include <linux/module.h>
@@ -56,11 +58,11 @@
#include <linux/crc32.h>
#include <linux/phy.h>
#include <linux/platform_device.h>
+#include <linux/cpu.h>
+#include <linux/io.h>
-#include <asm/cpu.h>
#include <asm/mipsregs.h>
#include <asm/irq.h>
-#include <asm/io.h>
#include <asm/processor.h>
#include <au1000.h>
@@ -152,11 +154,11 @@ static void au1000_enable_mac(struct net_device *dev, int force_reset)
spin_lock_irqsave(&aup->lock, flags);
- if(force_reset || (!aup->mac_enabled)) {
- *aup->enable = MAC_EN_CLOCK_ENABLE;
+ if (force_reset || (!aup->mac_enabled)) {
+ writel(MAC_EN_CLOCK_ENABLE, &aup->enable);
au_sync_delay(2);
- *aup->enable = (MAC_EN_RESET0 | MAC_EN_RESET1 | MAC_EN_RESET2
- | MAC_EN_CLOCK_ENABLE);
+ writel((MAC_EN_RESET0 | MAC_EN_RESET1 | MAC_EN_RESET2
+ | MAC_EN_CLOCK_ENABLE), &aup->enable);
au_sync_delay(2);
aup->mac_enabled = 1;
@@ -171,12 +173,12 @@ static void au1000_enable_mac(struct net_device *dev, int force_reset)
static int au1000_mdio_read(struct net_device *dev, int phy_addr, int reg)
{
struct au1000_private *aup = netdev_priv(dev);
- volatile u32 *const mii_control_reg = &aup->mac->mii_control;
- volatile u32 *const mii_data_reg = &aup->mac->mii_data;
+ u32 *const mii_control_reg = &aup->mac->mii_control;
+ u32 *const mii_data_reg = &aup->mac->mii_data;
u32 timedout = 20;
u32 mii_control;
- while (*mii_control_reg & MAC_MII_BUSY) {
+ while (readl(mii_control_reg) & MAC_MII_BUSY) {
mdelay(1);
if (--timedout == 0) {
netdev_err(dev, "read_MII busy timeout!!\n");
@@ -187,29 +189,29 @@ static int au1000_mdio_read(struct net_device *dev, int phy_addr, int reg)
mii_control = MAC_SET_MII_SELECT_REG(reg) |
MAC_SET_MII_SELECT_PHY(phy_addr) | MAC_MII_READ;
- *mii_control_reg = mii_control;
+ writel(mii_control, mii_control_reg);
timedout = 20;
- while (*mii_control_reg & MAC_MII_BUSY) {
+ while (readl(mii_control_reg) & MAC_MII_BUSY) {
mdelay(1);
if (--timedout == 0) {
netdev_err(dev, "mdio_read busy timeout!!\n");
return -1;
}
}
- return (int)*mii_data_reg;
+ return readl(mii_data_reg);
}
static void au1000_mdio_write(struct net_device *dev, int phy_addr,
int reg, u16 value)
{
struct au1000_private *aup = netdev_priv(dev);
- volatile u32 *const mii_control_reg = &aup->mac->mii_control;
- volatile u32 *const mii_data_reg = &aup->mac->mii_data;
+ u32 *const mii_control_reg = &aup->mac->mii_control;
+ u32 *const mii_data_reg = &aup->mac->mii_data;
u32 timedout = 20;
u32 mii_control;
- while (*mii_control_reg & MAC_MII_BUSY) {
+ while (readl(mii_control_reg) & MAC_MII_BUSY) {
mdelay(1);
if (--timedout == 0) {
netdev_err(dev, "mdio_write busy timeout!!\n");
@@ -220,18 +222,22 @@ static void au1000_mdio_write(struct net_device *dev, int phy_addr,
mii_control = MAC_SET_MII_SELECT_REG(reg) |
MAC_SET_MII_SELECT_PHY(phy_addr) | MAC_MII_WRITE;
- *mii_data_reg = value;
- *mii_control_reg = mii_control;
+ writel(value, mii_data_reg);
+ writel(mii_control, mii_control_reg);
}
static int au1000_mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum)
{
/* WARNING: bus->phy_map[phy_addr].attached_dev == dev does
- * _NOT_ hold (e.g. when PHY is accessed through other MAC's MII bus) */
+ * _NOT_ hold (e.g. when PHY is accessed through other MAC's MII bus)
+ */
struct net_device *const dev = bus->priv;
- au1000_enable_mac(dev, 0); /* make sure the MAC associated with this
- * mii_bus is enabled */
+ /* make sure the MAC associated with this
+ * mii_bus is enabled
+ */
+ au1000_enable_mac(dev, 0);
+
return au1000_mdio_read(dev, phy_addr, regnum);
}
@@ -240,8 +246,11 @@ static int au1000_mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum,
{
struct net_device *const dev = bus->priv;
- au1000_enable_mac(dev, 0); /* make sure the MAC associated with this
- * mii_bus is enabled */
+ /* make sure the MAC associated with this
+ * mii_bus is enabled
+ */
+ au1000_enable_mac(dev, 0);
+
au1000_mdio_write(dev, phy_addr, regnum, value);
return 0;
}
@@ -250,28 +259,37 @@ static int au1000_mdiobus_reset(struct mii_bus *bus)
{
struct net_device *const dev = bus->priv;
- au1000_enable_mac(dev, 0); /* make sure the MAC associated with this
- * mii_bus is enabled */
+ /* make sure the MAC associated with this
+ * mii_bus is enabled
+ */
+ au1000_enable_mac(dev, 0);
+
return 0;
}
static void au1000_hard_stop(struct net_device *dev)
{
struct au1000_private *aup = netdev_priv(dev);
+ u32 reg;
netif_dbg(aup, drv, dev, "hard stop\n");
- aup->mac->control &= ~(MAC_RX_ENABLE | MAC_TX_ENABLE);
+ reg = readl(&aup->mac->control);
+ reg &= ~(MAC_RX_ENABLE | MAC_TX_ENABLE);
+ writel(reg, &aup->mac->control);
au_sync_delay(10);
}
static void au1000_enable_rx_tx(struct net_device *dev)
{
struct au1000_private *aup = netdev_priv(dev);
+ u32 reg;
netif_dbg(aup, hw, dev, "enable_rx_tx\n");
- aup->mac->control |= (MAC_RX_ENABLE | MAC_TX_ENABLE);
+ reg = readl(&aup->mac->control);
+ reg |= (MAC_RX_ENABLE | MAC_TX_ENABLE);
+ writel(reg, &aup->mac->control);
au_sync_delay(10);
}
@@ -281,6 +299,7 @@ au1000_adjust_link(struct net_device *dev)
struct au1000_private *aup = netdev_priv(dev);
struct phy_device *phydev = aup->phy_dev;
unsigned long flags;
+ u32 reg;
int status_change = 0;
@@ -312,14 +331,15 @@ au1000_adjust_link(struct net_device *dev)
/* switching duplex mode requires to disable rx and tx! */
au1000_hard_stop(dev);
- if (DUPLEX_FULL == phydev->duplex)
- aup->mac->control = ((aup->mac->control
- | MAC_FULL_DUPLEX)
- & ~MAC_DISABLE_RX_OWN);
- else
- aup->mac->control = ((aup->mac->control
- & ~MAC_FULL_DUPLEX)
- | MAC_DISABLE_RX_OWN);
+ reg = readl(&aup->mac->control);
+ if (DUPLEX_FULL == phydev->duplex) {
+ reg |= MAC_FULL_DUPLEX;
+ reg &= ~MAC_DISABLE_RX_OWN;
+ } else {
+ reg &= ~MAC_FULL_DUPLEX;
+ reg |= MAC_DISABLE_RX_OWN;
+ }
+ writel(reg, &aup->mac->control);
au_sync_delay(1);
au1000_enable_rx_tx(dev);
@@ -353,10 +373,11 @@ au1000_adjust_link(struct net_device *dev)
}
}
-static int au1000_mii_probe (struct net_device *dev)
+static int au1000_mii_probe(struct net_device *dev)
{
struct au1000_private *const aup = netdev_priv(dev);
struct phy_device *phydev = NULL;
+ int phy_addr;
if (aup->phy_static_config) {
BUG_ON(aup->mac_id < 0 || aup->mac_id > 1);
@@ -366,42 +387,46 @@ static int au1000_mii_probe (struct net_device *dev)
else
netdev_info(dev, "using PHY-less setup\n");
return 0;
- } else {
- int phy_addr;
-
- /* find the first (lowest address) PHY on the current MAC's MII bus */
- for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++)
- if (aup->mii_bus->phy_map[phy_addr]) {
- phydev = aup->mii_bus->phy_map[phy_addr];
- if (!aup->phy_search_highest_addr)
- break; /* break out with first one found */
- }
-
- if (aup->phy1_search_mac0) {
- /* try harder to find a PHY */
- if (!phydev && (aup->mac_id == 1)) {
- /* no PHY found, maybe we have a dual PHY? */
- dev_info(&dev->dev, ": no PHY found on MAC1, "
- "let's see if it's attached to MAC0...\n");
-
- /* find the first (lowest address) non-attached PHY on
- * the MAC0 MII bus */
- for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
- struct phy_device *const tmp_phydev =
- aup->mii_bus->phy_map[phy_addr];
-
- if (aup->mac_id == 1)
- break;
-
- if (!tmp_phydev)
- continue; /* no PHY here... */
+ }
- if (tmp_phydev->attached_dev)
- continue; /* already claimed by MAC0 */
+ /* find the first (lowest address) PHY
+ * on the current MAC's MII bus
+ */
+ for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++)
+ if (aup->mii_bus->phy_map[phy_addr]) {
+ phydev = aup->mii_bus->phy_map[phy_addr];
+ if (!aup->phy_search_highest_addr)
+ /* break out with first one found */
+ break;
+ }
- phydev = tmp_phydev;
- break; /* found it */
- }
+ if (aup->phy1_search_mac0) {
+ /* try harder to find a PHY */
+ if (!phydev && (aup->mac_id == 1)) {
+ /* no PHY found, maybe we have a dual PHY? */
+ dev_info(&dev->dev, ": no PHY found on MAC1, "
+ "let's see if it's attached to MAC0...\n");
+
+ /* find the first (lowest address) non-attached
+ * PHY on the MAC0 MII bus
+ */
+ for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
+ struct phy_device *const tmp_phydev =
+ aup->mii_bus->phy_map[phy_addr];
+
+ if (aup->mac_id == 1)
+ break;
+
+ /* no PHY here... */
+ if (!tmp_phydev)
+ continue;
+
+ /* already claimed by MAC0 */
+ if (tmp_phydev->attached_dev)
+ continue;
+
+ phydev = tmp_phydev;
+ break; /* found it */
}
}
}
@@ -452,20 +477,20 @@ static int au1000_mii_probe (struct net_device *dev)
* has the virtual and dma address of a buffer suitable for
* both, receive and transmit operations.
*/
-static db_dest_t *au1000_GetFreeDB(struct au1000_private *aup)
+static struct db_dest *au1000_GetFreeDB(struct au1000_private *aup)
{
- db_dest_t *pDB;
+ struct db_dest *pDB;
pDB = aup->pDBfree;
- if (pDB) {
+ if (pDB)
aup->pDBfree = pDB->pnext;
- }
+
return pDB;
}
-void au1000_ReleaseDB(struct au1000_private *aup, db_dest_t *pDB)
+void au1000_ReleaseDB(struct au1000_private *aup, struct db_dest *pDB)
{
- db_dest_t *pDBfree = aup->pDBfree;
+ struct db_dest *pDBfree = aup->pDBfree;
if (pDBfree)
pDBfree->pnext = pDB;
aup->pDBfree = pDB;
@@ -478,9 +503,9 @@ static void au1000_reset_mac_unlocked(struct net_device *dev)
au1000_hard_stop(dev);
- *aup->enable = MAC_EN_CLOCK_ENABLE;
+ writel(MAC_EN_CLOCK_ENABLE, &aup->enable);
au_sync_delay(2);
- *aup->enable = 0;
+ writel(0, &aup->enable);
au_sync_delay(2);
aup->tx_full = 0;
@@ -507,7 +532,7 @@ static void au1000_reset_mac(struct net_device *dev)
spin_lock_irqsave(&aup->lock, flags);
- au1000_reset_mac_unlocked (dev);
+ au1000_reset_mac_unlocked(dev);
spin_unlock_irqrestore(&aup->lock, flags);
}
@@ -524,11 +549,13 @@ au1000_setup_hw_rings(struct au1000_private *aup, u32 rx_base, u32 tx_base)
for (i = 0; i < NUM_RX_DMA; i++) {
aup->rx_dma_ring[i] =
- (volatile rx_dma_t *) (rx_base + sizeof(rx_dma_t)*i);
+ (struct rx_dma *)
+ (rx_base + sizeof(struct rx_dma)*i);
}
for (i = 0; i < NUM_TX_DMA; i++) {
aup->tx_dma_ring[i] =
- (volatile tx_dma_t *) (tx_base + sizeof(tx_dma_t)*i);
+ (struct tx_dma *)
+ (tx_base + sizeof(struct tx_dma)*i);
}
}
@@ -616,18 +643,21 @@ static int au1000_init(struct net_device *dev)
spin_lock_irqsave(&aup->lock, flags);
- aup->mac->control = 0;
+ writel(0, &aup->mac->control);
aup->tx_head = (aup->tx_dma_ring[0]->buff_stat & 0xC) >> 2;
aup->tx_tail = aup->tx_head;
aup->rx_head = (aup->rx_dma_ring[0]->buff_stat & 0xC) >> 2;
- aup->mac->mac_addr_high = dev->dev_addr[5]<<8 | dev->dev_addr[4];
- aup->mac->mac_addr_low = dev->dev_addr[3]<<24 | dev->dev_addr[2]<<16 |
- dev->dev_addr[1]<<8 | dev->dev_addr[0];
+ writel(dev->dev_addr[5]<<8 | dev->dev_addr[4],
+ &aup->mac->mac_addr_high);
+ writel(dev->dev_addr[3]<<24 | dev->dev_addr[2]<<16 |
+ dev->dev_addr[1]<<8 | dev->dev_addr[0],
+ &aup->mac->mac_addr_low);
- for (i = 0; i < NUM_RX_DMA; i++) {
+
+ for (i = 0; i < NUM_RX_DMA; i++)
aup->rx_dma_ring[i]->buff_stat |= RX_DMA_ENABLE;
- }
+
au_sync();
control = MAC_RX_ENABLE | MAC_TX_ENABLE;
@@ -643,8 +673,8 @@ static int au1000_init(struct net_device *dev)
control |= MAC_FULL_DUPLEX;
}
- aup->mac->control = control;
- aup->mac->vlan1_tag = 0x8100; /* activate vlan support */
+ writel(control, &aup->mac->control);
+ writel(0x8100, &aup->mac->vlan1_tag); /* activate vlan support */
au_sync();
spin_unlock_irqrestore(&aup->lock, flags);
@@ -681,9 +711,9 @@ static int au1000_rx(struct net_device *dev)
{
struct au1000_private *aup = netdev_priv(dev);
struct sk_buff *skb;
- volatile rx_dma_t *prxd;
+ struct rx_dma *prxd;
u32 buff_stat, status;
- db_dest_t *pDB;
+ struct db_dest *pDB;
u32 frmlen;
netif_dbg(aup, rx_status, dev, "au1000_rx head %d\n", aup->rx_head);
@@ -713,24 +743,26 @@ static int au1000_rx(struct net_device *dev)
netif_rx(skb); /* pass the packet to upper layers */
} else {
if (au1000_debug > 4) {
+ pr_err("rx_error(s):");
if (status & RX_MISSED_FRAME)
- printk("rx miss\n");
+ pr_cont(" miss");
if (status & RX_WDOG_TIMER)
- printk("rx wdog\n");
+ pr_cont(" wdog");
if (status & RX_RUNT)
- printk("rx runt\n");
+ pr_cont(" runt");
if (status & RX_OVERLEN)
- printk("rx overlen\n");
+ pr_cont(" overlen");
if (status & RX_COLL)
- printk("rx coll\n");
+ pr_cont(" coll");
if (status & RX_MII_ERROR)
- printk("rx mii error\n");
+ pr_cont(" mii error");
if (status & RX_CRC_ERROR)
- printk("rx crc error\n");
+ pr_cont(" crc error");
if (status & RX_LEN_ERROR)
- printk("rx len error\n");
+ pr_cont(" len error");
if (status & RX_U_CNTRL_FRAME)
- printk("rx u control frame\n");
+ pr_cont(" u control frame");
+ pr_cont("\n");
}
}
prxd->buff_stat = (u32)(pDB->dma_addr | RX_DMA_ENABLE);
@@ -753,7 +785,8 @@ static void au1000_update_tx_stats(struct net_device *dev, u32 status)
if (!aup->phy_dev || (DUPLEX_FULL == aup->phy_dev->duplex)) {
if (status & (TX_JAB_TIMEOUT | TX_UNDERRUN)) {
/* any other tx errors are only valid
- * in half duplex mode */
+ * in half duplex mode
+ */
ps->tx_errors++;
ps->tx_aborted_errors++;
}
@@ -774,7 +807,7 @@ static void au1000_update_tx_stats(struct net_device *dev, u32 status)
static void au1000_tx_ack(struct net_device *dev)
{
struct au1000_private *aup = netdev_priv(dev);
- volatile tx_dma_t *ptxd;
+ struct tx_dma *ptxd;
ptxd = aup->tx_dma_ring[aup->tx_tail];
@@ -854,7 +887,7 @@ static int au1000_close(struct net_device *dev)
spin_lock_irqsave(&aup->lock, flags);
- au1000_reset_mac_unlocked (dev);
+ au1000_reset_mac_unlocked(dev);
/* stop the device */
netif_stop_queue(dev);
@@ -873,9 +906,9 @@ static netdev_tx_t au1000_tx(struct sk_buff *skb, struct net_device *dev)
{
struct au1000_private *aup = netdev_priv(dev);
struct net_device_stats *ps = &dev->stats;
- volatile tx_dma_t *ptxd;
+ struct tx_dma *ptxd;
u32 buff_stat;
- db_dest_t *pDB;
+ struct db_dest *pDB;
int i;
netif_dbg(aup, tx_queued, dev, "tx: aup %x len=%d, data=%p, head %d\n",
@@ -902,9 +935,9 @@ static netdev_tx_t au1000_tx(struct sk_buff *skb, struct net_device *dev)
pDB = aup->tx_db_inuse[aup->tx_head];
skb_copy_from_linear_data(skb, (void *)pDB->vaddr, skb->len);
if (skb->len < ETH_ZLEN) {
- for (i = skb->len; i < ETH_ZLEN; i++) {
+ for (i = skb->len; i < ETH_ZLEN; i++)
((char *)pDB->vaddr)[i] = 0;
- }
+
ptxd->len = ETH_ZLEN;
} else
ptxd->len = skb->len;
@@ -935,15 +968,16 @@ static void au1000_tx_timeout(struct net_device *dev)
static void au1000_multicast_list(struct net_device *dev)
{
struct au1000_private *aup = netdev_priv(dev);
+ u32 reg;
- netif_dbg(aup, drv, dev, "au1000_multicast_list: flags=%x\n", dev->flags);
-
+ netif_dbg(aup, drv, dev, "%s: flags=%x\n", __func__, dev->flags);
+ reg = readl(&aup->mac->control);
if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */
- aup->mac->control |= MAC_PROMISCUOUS;
+ reg |= MAC_PROMISCUOUS;
} else if ((dev->flags & IFF_ALLMULTI) ||
netdev_mc_count(dev) > MULTICAST_FILTER_LIMIT) {
- aup->mac->control |= MAC_PASS_ALL_MULTI;
- aup->mac->control &= ~MAC_PROMISCUOUS;
+ reg |= MAC_PASS_ALL_MULTI;
+ reg &= ~MAC_PROMISCUOUS;
netdev_info(dev, "Pass all multicast\n");
} else {
struct netdev_hw_addr *ha;
@@ -953,11 +987,12 @@ static void au1000_multicast_list(struct net_device *dev)
netdev_for_each_mc_addr(ha, dev)
set_bit(ether_crc(ETH_ALEN, ha->addr)>>26,
(long *)mc_filter);
- aup->mac->multi_hash_high = mc_filter[1];
- aup->mac->multi_hash_low = mc_filter[0];
- aup->mac->control &= ~MAC_PROMISCUOUS;
- aup->mac->control |= MAC_HASH_MODE;
+ writel(mc_filter[1], &aup->mac->multi_hash_high);
+ writel(mc_filter[0], &aup->mac->multi_hash_low);
+ reg &= ~MAC_PROMISCUOUS;
+ reg |= MAC_HASH_MODE;
}
+ writel(reg, &aup->mac->control);
}
static int au1000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
@@ -991,7 +1026,7 @@ static int __devinit au1000_probe(struct platform_device *pdev)
struct au1000_private *aup = NULL;
struct au1000_eth_platform_data *pd;
struct net_device *dev = NULL;
- db_dest_t *pDB, *pDBfree;
+ struct db_dest *pDB, *pDBfree;
int irq, i, err = 0;
struct resource *base, *macen;
@@ -1016,13 +1051,15 @@ static int __devinit au1000_probe(struct platform_device *pdev)
goto out;
}
- if (!request_mem_region(base->start, resource_size(base), pdev->name)) {
+ if (!request_mem_region(base->start, resource_size(base),
+ pdev->name)) {
dev_err(&pdev->dev, "failed to request memory region for base registers\n");
err = -ENXIO;
goto out;
}
- if (!request_mem_region(macen->start, resource_size(macen), pdev->name)) {
+ if (!request_mem_region(macen->start, resource_size(macen),
+ pdev->name)) {
dev_err(&pdev->dev, "failed to request memory region for MAC enable register\n");
err = -ENXIO;
goto err_request;
@@ -1040,10 +1077,12 @@ static int __devinit au1000_probe(struct platform_device *pdev)
aup = netdev_priv(dev);
spin_lock_init(&aup->lock);
- aup->msg_enable = (au1000_debug < 4 ? AU1000_DEF_MSG_ENABLE : au1000_debug);
+ aup->msg_enable = (au1000_debug < 4 ?
+ AU1000_DEF_MSG_ENABLE : au1000_debug);
- /* Allocate the data buffers */
- /* Snooping works fine with eth on all au1xxx */
+ /* Allocate the data buffers
+ * Snooping works fine with eth on all au1xxx
+ */
aup->vaddr = (u32)dma_alloc_noncoherent(NULL, MAX_BUF_SIZE *
(NUM_TX_BUFFS + NUM_RX_BUFFS),
&aup->dma_addr, 0);
@@ -1054,15 +1093,17 @@ static int __devinit au1000_probe(struct platform_device *pdev)
}
/* aup->mac is the base address of the MAC's registers */
- aup->mac = (volatile mac_reg_t *)ioremap_nocache(base->start, resource_size(base));
+ aup->mac = (struct mac_reg *)
+ ioremap_nocache(base->start, resource_size(base));
if (!aup->mac) {
dev_err(&pdev->dev, "failed to ioremap MAC registers\n");
err = -ENXIO;
goto err_remap1;
}
- /* Setup some variables for quick register address access */
- aup->enable = (volatile u32 *)ioremap_nocache(macen->start, resource_size(macen));
+ /* Setup some variables for quick register address access */
+ aup->enable = (u32 *)ioremap_nocache(macen->start,
+ resource_size(macen));
if (!aup->enable) {
dev_err(&pdev->dev, "failed to ioremap MAC enable register\n");
err = -ENXIO;
@@ -1078,12 +1119,13 @@ static int __devinit au1000_probe(struct platform_device *pdev)
/* set a random MAC now in case platform_data doesn't provide one */
random_ether_addr(dev->dev_addr);
- *aup->enable = 0;
+ writel(0, &aup->enable);
aup->mac_enabled = 0;
pd = pdev->dev.platform_data;
if (!pd) {
- dev_info(&pdev->dev, "no platform_data passed, PHY search on MAC0\n");
+ dev_info(&pdev->dev, "no platform_data passed,"
+ " PHY search on MAC0\n");
aup->phy1_search_mac0 = 1;
} else {
if (is_valid_ether_addr(pd->mac))
@@ -1098,8 +1140,7 @@ static int __devinit au1000_probe(struct platform_device *pdev)
}
if (aup->phy_busid && aup->phy_busid > 0) {
- dev_err(&pdev->dev, "MAC0-associated PHY attached 2nd MACs MII"
- "bus not supported yet\n");
+ dev_err(&pdev->dev, "MAC0-associated PHY attached 2nd MACs MII bus not supported yet\n");
err = -ENODEV;
goto err_mdiobus_alloc;
}
@@ -1151,17 +1192,17 @@ static int __devinit au1000_probe(struct platform_device *pdev)
for (i = 0; i < NUM_RX_DMA; i++) {
pDB = au1000_GetFreeDB(aup);
- if (!pDB) {
+ if (!pDB)
goto err_out;
- }
+
aup->rx_dma_ring[i]->buff_stat = (unsigned)pDB->dma_addr;
aup->rx_db_inuse[i] = pDB;
}
for (i = 0; i < NUM_TX_DMA; i++) {
pDB = au1000_GetFreeDB(aup);
- if (!pDB) {
+ if (!pDB)
goto err_out;
- }
+
aup->tx_dma_ring[i]->buff_stat = (unsigned)pDB->dma_addr;
aup->tx_dma_ring[i]->len = 0;
aup->tx_db_inuse[i] = pDB;
@@ -1188,7 +1229,8 @@ static int __devinit au1000_probe(struct platform_device *pdev)
netdev_info(dev, "Au1xx0 Ethernet found at 0x%lx, irq %d\n",
(unsigned long)base->start, irq);
if (version_printed++ == 0)
- printk("%s version %s %s\n", DRV_NAME, DRV_VERSION, DRV_AUTHOR);
+ pr_info("%s version %s %s\n",
+ DRV_NAME, DRV_VERSION, DRV_AUTHOR);
return 0;
@@ -1197,7 +1239,8 @@ err_out:
mdiobus_unregister(aup->mii_bus);
/* here we should have a valid dev plus aup-> register addresses
- * so we can reset the mac properly.*/
+ * so we can reset the mac properly.
+ */
au1000_reset_mac(dev);
for (i = 0; i < NUM_RX_DMA; i++) {
diff --git a/drivers/net/au1000_eth.h b/drivers/net/au1000_eth.h
index d06ec008fbf1..6229c774552c 100644
--- a/drivers/net/au1000_eth.h
+++ b/drivers/net/au1000_eth.h
@@ -44,34 +44,34 @@
* Data Buffer Descriptor. Data buffers must be aligned on 32 byte
* boundary for both, receive and transmit.
*/
-typedef struct db_dest {
+struct db_dest {
struct db_dest *pnext;
- volatile u32 *vaddr;
+ u32 *vaddr;
dma_addr_t dma_addr;
-} db_dest_t;
+};
/*
* The transmit and receive descriptors are memory
* mapped registers.
*/
-typedef struct tx_dma {
+struct tx_dma {
u32 status;
u32 buff_stat;
u32 len;
u32 pad;
-} tx_dma_t;
+};
-typedef struct rx_dma {
+struct rx_dma {
u32 status;
u32 buff_stat;
u32 pad[2];
-} rx_dma_t;
+};
/*
* MAC control registers, memory mapped.
*/
-typedef struct mac_reg {
+struct mac_reg {
u32 control;
u32 mac_addr_high;
u32 mac_addr_low;
@@ -82,16 +82,16 @@ typedef struct mac_reg {
u32 flow_control;
u32 vlan1_tag;
u32 vlan2_tag;
-} mac_reg_t;
+};
struct au1000_private {
- db_dest_t *pDBfree;
- db_dest_t db[NUM_RX_BUFFS+NUM_TX_BUFFS];
- volatile rx_dma_t *rx_dma_ring[NUM_RX_DMA];
- volatile tx_dma_t *tx_dma_ring[NUM_TX_DMA];
- db_dest_t *rx_db_inuse[NUM_RX_DMA];
- db_dest_t *tx_db_inuse[NUM_TX_DMA];
+ struct db_dest *pDBfree;
+ struct db_dest db[NUM_RX_BUFFS+NUM_TX_BUFFS];
+ struct rx_dma *rx_dma_ring[NUM_RX_DMA];
+ struct tx_dma *tx_dma_ring[NUM_TX_DMA];
+ struct db_dest *rx_db_inuse[NUM_RX_DMA];
+ struct db_dest *tx_db_inuse[NUM_TX_DMA];
u32 rx_head;
u32 tx_head;
u32 tx_tail;
@@ -99,7 +99,9 @@ struct au1000_private {
int mac_id;
- int mac_enabled; /* whether MAC is currently enabled and running (req. for mdio) */
+ int mac_enabled; /* whether MAC is currently enabled and running
+ * (req. for mdio)
+ */
int old_link; /* used by au1000_adjust_link */
int old_speed;
@@ -117,9 +119,11 @@ struct au1000_private {
int phy_busid;
int phy_irq;
- /* These variables are just for quick access to certain regs addresses. */
- volatile mac_reg_t *mac; /* mac registers */
- volatile u32 *enable; /* address of MAC Enable Register */
+ /* These variables are just for quick access
+ * to certain regs addresses.
+ */
+ struct mac_reg *mac; /* mac registers */
+ u32 *enable; /* address of MAC Enable Register */
u32 vaddr; /* virtual address of rx/tx buffers */
dma_addr_t dma_addr; /* dma address of rx/tx buffers */
diff --git a/drivers/net/ax88796.c b/drivers/net/ax88796.c
index 20e946b1e744..b6da4cf3694b 100644
--- a/drivers/net/ax88796.c
+++ b/drivers/net/ax88796.c
@@ -864,6 +864,7 @@ static int ax_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (res == NULL) {
dev_err(&pdev->dev, "no IRQ specified\n");
+ ret = -ENXIO;
goto exit_mem;
}
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index 1e620e287ae0..c6e86315b3f8 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -818,7 +818,7 @@ static int b44_rx(struct b44 *bp, int budget)
copy_skb->data, len);
skb = copy_skb;
}
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
skb->protocol = eth_type_trans(skb, bp->dev);
netif_receive_skb(skb);
received++;
@@ -2170,8 +2170,6 @@ static int __devinit b44_init_one(struct ssb_device *sdev,
dev->irq = sdev->irq;
SET_ETHTOOL_OPS(dev, &b44_ethtool_ops);
- netif_carrier_off(dev);
-
err = ssb_bus_powerup(sdev->bus, 0);
if (err) {
dev_err(sdev->dev,
@@ -2213,6 +2211,8 @@ static int __devinit b44_init_one(struct ssb_device *sdev,
goto err_out_powerdown;
}
+ netif_carrier_off(dev);
+
ssb_set_drvdata(sdev, dev);
/* Chip reset provides power to the b44 MAC & PCI cores, which
@@ -2296,18 +2296,27 @@ static int b44_resume(struct ssb_device *sdev)
if (!netif_running(dev))
return 0;
+ spin_lock_irq(&bp->lock);
+ b44_init_rings(bp);
+ b44_init_hw(bp, B44_FULL_RESET);
+ spin_unlock_irq(&bp->lock);
+
+ /*
+ * As a shared interrupt, the handler can be called immediately. To be
+ * able to check the interrupt status the hardware must already be
+ * powered back on (b44_init_hw).
+ */
rc = request_irq(dev->irq, b44_interrupt, IRQF_SHARED, dev->name, dev);
if (rc) {
netdev_err(dev, "request_irq failed\n");
+ spin_lock_irq(&bp->lock);
+ b44_halt(bp);
+ b44_free_rings(bp);
+ spin_unlock_irq(&bp->lock);
return rc;
}
- spin_lock_irq(&bp->lock);
-
- b44_init_rings(bp);
- b44_init_hw(bp, B44_FULL_RESET);
netif_device_attach(bp->dev);
- spin_unlock_irq(&bp->lock);
b44_enable_ints(bp);
netif_wake_queue(dev);
diff --git a/drivers/net/bcm63xx_enet.c b/drivers/net/bcm63xx_enet.c
index 0d2c5da08937..ecfef240a303 100644
--- a/drivers/net/bcm63xx_enet.c
+++ b/drivers/net/bcm63xx_enet.c
@@ -293,22 +293,22 @@ static int bcm_enet_receive_queue(struct net_device *dev, int budget)
/* if the packet does not have start of packet _and_
* end of packet flag set, then just recycle it */
if ((len_stat & DMADESC_ESOP_MASK) != DMADESC_ESOP_MASK) {
- priv->stats.rx_dropped++;
+ dev->stats.rx_dropped++;
continue;
}
/* recycle packet if it's marked as bad */
if (unlikely(len_stat & DMADESC_ERR_MASK)) {
- priv->stats.rx_errors++;
+ dev->stats.rx_errors++;
if (len_stat & DMADESC_OVSIZE_MASK)
- priv->stats.rx_length_errors++;
+ dev->stats.rx_length_errors++;
if (len_stat & DMADESC_CRC_MASK)
- priv->stats.rx_crc_errors++;
+ dev->stats.rx_crc_errors++;
if (len_stat & DMADESC_UNDER_MASK)
- priv->stats.rx_frame_errors++;
+ dev->stats.rx_frame_errors++;
if (len_stat & DMADESC_OV_MASK)
- priv->stats.rx_fifo_errors++;
+ dev->stats.rx_fifo_errors++;
continue;
}
@@ -324,7 +324,7 @@ static int bcm_enet_receive_queue(struct net_device *dev, int budget)
nskb = netdev_alloc_skb_ip_align(dev, len);
if (!nskb) {
/* forget packet, just rearm desc */
- priv->stats.rx_dropped++;
+ dev->stats.rx_dropped++;
continue;
}
@@ -342,8 +342,8 @@ static int bcm_enet_receive_queue(struct net_device *dev, int budget)
skb_put(skb, len);
skb->protocol = eth_type_trans(skb, dev);
- priv->stats.rx_packets++;
- priv->stats.rx_bytes += len;
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += len;
netif_receive_skb(skb);
} while (--budget > 0);
@@ -403,7 +403,7 @@ static int bcm_enet_tx_reclaim(struct net_device *dev, int force)
spin_unlock(&priv->tx_lock);
if (desc->len_stat & DMADESC_UNDER_MASK)
- priv->stats.tx_errors++;
+ dev->stats.tx_errors++;
dev_kfree_skb(skb);
released++;
@@ -563,8 +563,8 @@ static int bcm_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (!priv->tx_desc_count)
netif_stop_queue(dev);
- priv->stats.tx_bytes += skb->len;
- priv->stats.tx_packets++;
+ dev->stats.tx_bytes += skb->len;
+ dev->stats.tx_packets++;
ret = NETDEV_TX_OK;
out_unlock:
@@ -798,7 +798,7 @@ static int bcm_enet_open(struct net_device *dev)
snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT,
priv->mac_id ? "1" : "0", priv->phy_id);
- phydev = phy_connect(dev, phy_id, &bcm_enet_adjust_phy_link, 0,
+ phydev = phy_connect(dev, phy_id, bcm_enet_adjust_phy_link, 0,
PHY_INTERFACE_MODE_MII);
if (IS_ERR(phydev)) {
@@ -1141,17 +1141,6 @@ static int bcm_enet_stop(struct net_device *dev)
}
/*
- * core request to return device rx/tx stats
- */
-static struct net_device_stats *bcm_enet_get_stats(struct net_device *dev)
-{
- struct bcm_enet_priv *priv;
-
- priv = netdev_priv(dev);
- return &priv->stats;
-}
-
-/*
* ethtool callbacks
*/
struct bcm_enet_stats {
@@ -1163,16 +1152,18 @@ struct bcm_enet_stats {
#define GEN_STAT(m) sizeof(((struct bcm_enet_priv *)0)->m), \
offsetof(struct bcm_enet_priv, m)
+#define DEV_STAT(m) sizeof(((struct net_device_stats *)0)->m), \
+ offsetof(struct net_device_stats, m)
static const struct bcm_enet_stats bcm_enet_gstrings_stats[] = {
- { "rx_packets", GEN_STAT(stats.rx_packets), -1 },
- { "tx_packets", GEN_STAT(stats.tx_packets), -1 },
- { "rx_bytes", GEN_STAT(stats.rx_bytes), -1 },
- { "tx_bytes", GEN_STAT(stats.tx_bytes), -1 },
- { "rx_errors", GEN_STAT(stats.rx_errors), -1 },
- { "tx_errors", GEN_STAT(stats.tx_errors), -1 },
- { "rx_dropped", GEN_STAT(stats.rx_dropped), -1 },
- { "tx_dropped", GEN_STAT(stats.tx_dropped), -1 },
+ { "rx_packets", DEV_STAT(rx_packets), -1 },
+ { "tx_packets", DEV_STAT(tx_packets), -1 },
+ { "rx_bytes", DEV_STAT(rx_bytes), -1 },
+ { "tx_bytes", DEV_STAT(tx_bytes), -1 },
+ { "rx_errors", DEV_STAT(rx_errors), -1 },
+ { "tx_errors", DEV_STAT(tx_errors), -1 },
+ { "rx_dropped", DEV_STAT(rx_dropped), -1 },
+ { "tx_dropped", DEV_STAT(tx_dropped), -1 },
{ "rx_good_octets", GEN_STAT(mib.rx_gd_octets), ETH_MIB_RX_GD_OCTETS},
{ "rx_good_pkts", GEN_STAT(mib.rx_gd_pkts), ETH_MIB_RX_GD_PKTS },
@@ -1328,7 +1319,11 @@ static void bcm_enet_get_ethtool_stats(struct net_device *netdev,
char *p;
s = &bcm_enet_gstrings_stats[i];
- p = (char *)priv + s->stat_offset;
+ if (s->mib_reg == -1)
+ p = (char *)&netdev->stats;
+ else
+ p = (char *)priv;
+ p += s->stat_offset;
data[i] = (s->sizeof_stat == sizeof(u64)) ?
*(u64 *)p : *(u32 *)p;
}
@@ -1605,7 +1600,6 @@ static const struct net_device_ops bcm_enet_ops = {
.ndo_open = bcm_enet_open,
.ndo_stop = bcm_enet_stop,
.ndo_start_xmit = bcm_enet_start_xmit,
- .ndo_get_stats = bcm_enet_get_stats,
.ndo_set_mac_address = bcm_enet_set_mac_address,
.ndo_set_multicast_list = bcm_enet_set_multicast_list,
.ndo_do_ioctl = bcm_enet_ioctl,
diff --git a/drivers/net/bcm63xx_enet.h b/drivers/net/bcm63xx_enet.h
index bd3684d42d74..0e3048b788c2 100644
--- a/drivers/net/bcm63xx_enet.h
+++ b/drivers/net/bcm63xx_enet.h
@@ -274,7 +274,6 @@ struct bcm_enet_priv {
int pause_tx;
/* stats */
- struct net_device_stats stats;
struct bcm_enet_mib_counters mib;
/* after mib interrupt, mib registers update is done in this
diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h
index 53306bf3f401..4594a28b1f66 100644
--- a/drivers/net/benet/be.h
+++ b/drivers/net/benet/be.h
@@ -78,6 +78,8 @@ static inline char *nic_name(struct pci_dev *pdev)
#define MCC_Q_LEN 128 /* total size not to exceed 8 pages */
#define MCC_CQ_LEN 256
+#define MAX_RSS_QS 4 /* BE limit is 4 queues/port */
+#define BE_MAX_MSIX_VECTORS (MAX_RSS_QS + 1 + 1)/* RSS qs + 1 def Rx + Tx */
#define BE_NAPI_WEIGHT 64
#define MAX_RX_POST BE_NAPI_WEIGHT /* Frags posted at a time */
#define RX_FRAGS_REFILL_WM (RX_Q_LEN - MAX_RX_POST)
@@ -157,10 +159,9 @@ struct be_mcc_obj {
bool rearm_cq;
};
-struct be_drvr_stats {
+struct be_tx_stats {
u32 be_tx_reqs; /* number of TX requests initiated */
u32 be_tx_stops; /* number of times TX Q was stopped */
- u32 be_fwd_reqs; /* number of send reqs through forwarding i/f */
u32 be_tx_wrbs; /* number of tx WRBs used */
u32 be_tx_events; /* number of tx completion events */
u32 be_tx_compl; /* number of tx completion entries processed */
@@ -169,35 +170,6 @@ struct be_drvr_stats {
u64 be_tx_bytes_prev;
u64 be_tx_pkts;
u32 be_tx_rate;
-
- u32 cache_barrier[16];
-
- u32 be_ethrx_post_fail;/* number of ethrx buffer alloc failures */
- u32 be_rx_polls; /* number of times NAPI called poll function */
- u32 be_rx_events; /* number of ucast rx completion events */
- u32 be_rx_compl; /* number of rx completion entries processed */
- ulong be_rx_jiffies;
- u64 be_rx_bytes;
- u64 be_rx_bytes_prev;
- u64 be_rx_pkts;
- u32 be_rx_rate;
- u32 be_rx_mcast_pkt;
- /* number of non ether type II frames dropped where
- * frame len > length field of Mac Hdr */
- u32 be_802_3_dropped_frames;
- /* number of non ether type II frames malformed where
- * in frame len < length field of Mac Hdr */
- u32 be_802_3_malformed_frames;
- u32 be_rxcp_err; /* Num rx completion entries w/ err set. */
- ulong rx_fps_jiffies; /* jiffies at last FPS calc */
- u32 be_rx_frags;
- u32 be_prev_rx_frags;
- u32 be_rx_fps; /* Rx frags per second */
-};
-
-struct be_stats_obj {
- struct be_drvr_stats drvr_stats;
- struct be_dma_mem cmd;
};
struct be_tx_obj {
@@ -215,10 +187,34 @@ struct be_rx_page_info {
bool last_page_user;
};
+struct be_rx_stats {
+ u32 rx_post_fail;/* number of ethrx buffer alloc failures */
+ u32 rx_polls; /* number of times NAPI called poll function */
+ u32 rx_events; /* number of ucast rx completion events */
+ u32 rx_compl; /* number of rx completion entries processed */
+ ulong rx_jiffies;
+ u64 rx_bytes;
+ u64 rx_bytes_prev;
+ u64 rx_pkts;
+ u32 rx_rate;
+ u32 rx_mcast_pkts;
+ u32 rxcp_err; /* Num rx completion entries w/ err set. */
+ ulong rx_fps_jiffies; /* jiffies at last FPS calc */
+ u32 rx_frags;
+ u32 prev_rx_frags;
+ u32 rx_fps; /* Rx frags per second */
+};
+
struct be_rx_obj {
+ struct be_adapter *adapter;
struct be_queue_info q;
struct be_queue_info cq;
struct be_rx_page_info page_info_tbl[RX_Q_LEN];
+ struct be_eq_obj rx_eq;
+ struct be_rx_stats stats;
+ u8 rss_id;
+ bool rx_post_starved; /* Zero rx frags have been posted to BE */
+ u32 cache_line_barrier[16];
};
struct be_vf_cfg {
@@ -229,7 +225,6 @@ struct be_vf_cfg {
u32 vf_tx_rate;
};
-#define BE_NUM_MSIX_VECTORS 2 /* 1 each for Tx and Rx */
#define BE_INVALID_PMAC_ID 0xffffffff
struct be_adapter {
struct pci_dev *pdev;
@@ -249,29 +244,31 @@ struct be_adapter {
spinlock_t mcc_lock; /* For serializing mcc cmds to BE card */
spinlock_t mcc_cq_lock;
- struct msix_entry msix_entries[BE_NUM_MSIX_VECTORS];
+ struct msix_entry msix_entries[BE_MAX_MSIX_VECTORS];
bool msix_enabled;
bool isr_registered;
/* TX Rings */
struct be_eq_obj tx_eq;
struct be_tx_obj tx_obj;
+ struct be_tx_stats tx_stats;
u32 cache_line_break[8];
/* Rx rings */
- struct be_eq_obj rx_eq;
- struct be_rx_obj rx_obj;
+ struct be_rx_obj rx_obj[MAX_RSS_QS + 1]; /* one default non-rss Q */
+ u32 num_rx_qs;
u32 big_page_size; /* Compounded page size shared by rx wrbs */
- bool rx_post_starved; /* Zero rx frags have been posted to BE */
struct vlan_group *vlan_grp;
u16 vlans_added;
u16 max_vlans; /* Number of vlans supported */
- u8 vlan_tag[VLAN_GROUP_ARRAY_LEN];
+ u8 vlan_tag[VLAN_N_VID];
+ u8 vlan_prio_bmap; /* Available Priority BitMap */
+ u16 recommended_prio; /* Recommended Priority */
struct be_dma_mem mc_cmd_mem;
- struct be_stats_obj stats;
+ struct be_dma_mem stats_cmd;
/* Work queue used to perform periodic tasks like getting statistics */
struct delayed_work work;
@@ -287,6 +284,7 @@ struct be_adapter {
bool promiscuous;
bool wol;
u32 function_mode;
+ u32 function_caps;
u32 rx_fc; /* Rx flow control */
u32 tx_fc; /* Tx flow control */
bool ue_detected;
@@ -313,10 +311,20 @@ struct be_adapter {
extern const struct ethtool_ops be_ethtool_ops;
-#define drvr_stats(adapter) (&adapter->stats.drvr_stats)
+#define tx_stats(adapter) (&adapter->tx_stats)
+#define rx_stats(rxo) (&rxo->stats)
#define BE_SET_NETDEV_OPS(netdev, ops) (netdev->netdev_ops = ops)
+#define for_all_rx_queues(adapter, rxo, i) \
+ for (i = 0, rxo = &adapter->rx_obj[i]; i < adapter->num_rx_qs; \
+ i++, rxo++)
+
+/* Just skip the first default non-rss queue */
+#define for_all_rss_queues(adapter, rxo, i) \
+ for (i = 0, rxo = &adapter->rx_obj[i+1]; i < (adapter->num_rx_qs - 1);\
+ i++, rxo++)
+
#define PAGE_SHIFT_4K 12
#define PAGE_SIZE_4K (1 << PAGE_SHIFT_4K)
@@ -414,6 +422,20 @@ static inline void be_check_sriov_fn_type(struct be_adapter *adapter)
adapter->is_virtfn = (data != 0xAA);
}
+static inline void be_vf_eth_addr_generate(struct be_adapter *adapter, u8 *mac)
+{
+ u32 addr;
+
+ addr = jhash(adapter->netdev->dev_addr, ETH_ALEN, 0);
+
+ mac[5] = (u8)(addr & 0xFF);
+ mac[4] = (u8)((addr >> 8) & 0xFF);
+ mac[3] = (u8)((addr >> 16) & 0xFF);
+ mac[2] = 0xC9;
+ mac[1] = 0x00;
+ mac[0] = 0x00;
+}
+
extern void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm,
u16 num_popped);
extern void be_link_status_update(struct be_adapter *adapter, bool link_up);
diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c
index 34abcc9403d6..1e7f305ed00b 100644
--- a/drivers/net/benet/be_cmds.c
+++ b/drivers/net/benet/be_cmds.c
@@ -71,7 +71,7 @@ static int be_mcc_compl_process(struct be_adapter *adapter,
if (compl_status == MCC_STATUS_SUCCESS) {
if (compl->tag0 == OPCODE_ETH_GET_STATISTICS) {
struct be_cmd_resp_get_stats *resp =
- adapter->stats.cmd.va;
+ adapter->stats_cmd.va;
be_dws_le_to_cpu(&resp->hw_stats,
sizeof(resp->hw_stats));
netdev_stats_update(adapter);
@@ -96,11 +96,62 @@ static void be_async_link_state_process(struct be_adapter *adapter,
evt->port_link_status == ASYNC_EVENT_LINK_UP);
}
+/* Grp5 CoS Priority evt */
+static void be_async_grp5_cos_priority_process(struct be_adapter *adapter,
+ struct be_async_event_grp5_cos_priority *evt)
+{
+ if (evt->valid) {
+ adapter->vlan_prio_bmap = evt->available_priority_bmap;
+ adapter->recommended_prio =
+ evt->reco_default_priority << VLAN_PRIO_SHIFT;
+ }
+}
+
+/* Grp5 QOS Speed evt */
+static void be_async_grp5_qos_speed_process(struct be_adapter *adapter,
+ struct be_async_event_grp5_qos_link_speed *evt)
+{
+ if (evt->physical_port == adapter->port_num) {
+ /* qos_link_speed is in units of 10 Mbps */
+ adapter->link_speed = evt->qos_link_speed * 10;
+ }
+}
+
+static void be_async_grp5_evt_process(struct be_adapter *adapter,
+ u32 trailer, struct be_mcc_compl *evt)
+{
+ u8 event_type = 0;
+
+ event_type = (trailer >> ASYNC_TRAILER_EVENT_TYPE_SHIFT) &
+ ASYNC_TRAILER_EVENT_TYPE_MASK;
+
+ switch (event_type) {
+ case ASYNC_EVENT_COS_PRIORITY:
+ be_async_grp5_cos_priority_process(adapter,
+ (struct be_async_event_grp5_cos_priority *)evt);
+ break;
+ case ASYNC_EVENT_QOS_SPEED:
+ be_async_grp5_qos_speed_process(adapter,
+ (struct be_async_event_grp5_qos_link_speed *)evt);
+ break;
+ default:
+ dev_warn(&adapter->pdev->dev, "Unknown grp5 event!\n");
+ break;
+ }
+}
+
static inline bool is_link_state_evt(u32 trailer)
{
+ return ((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) &
+ ASYNC_TRAILER_EVENT_CODE_MASK) ==
+ ASYNC_EVENT_CODE_LINK_STATE;
+}
+
+static inline bool is_grp5_evt(u32 trailer)
+{
return (((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) &
ASYNC_TRAILER_EVENT_CODE_MASK) ==
- ASYNC_EVENT_CODE_LINK_STATE);
+ ASYNC_EVENT_CODE_GRP_5);
}
static struct be_mcc_compl *be_mcc_compl_get(struct be_adapter *adapter)
@@ -143,6 +194,9 @@ int be_process_mcc(struct be_adapter *adapter, int *status)
if (is_link_state_evt(compl->flags))
be_async_link_state_process(adapter,
(struct be_async_event_link_state *) compl);
+ else if (is_grp5_evt(compl->flags))
+ be_async_grp5_evt_process(adapter,
+ compl->flags, compl);
} else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) {
*status = be_mcc_compl_process(adapter, compl);
atomic_dec(&mcc_obj->q.used);
@@ -677,10 +731,10 @@ int be_cmd_mccq_create(struct be_adapter *adapter,
ctxt = &req->context;
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
- OPCODE_COMMON_MCC_CREATE);
+ OPCODE_COMMON_MCC_CREATE_EXT);
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
- OPCODE_COMMON_MCC_CREATE, sizeof(*req));
+ OPCODE_COMMON_MCC_CREATE_EXT, sizeof(*req));
req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
@@ -688,7 +742,8 @@ int be_cmd_mccq_create(struct be_adapter *adapter,
AMAP_SET_BITS(struct amap_mcc_context, ring_size, ctxt,
be_encoded_q_len(mccq->len));
AMAP_SET_BITS(struct amap_mcc_context, cq_id, ctxt, cq->id);
-
+ /* Subscribe to Link State and Group 5 Events(bits 1 and 5 set) */
+ req->async_event_bitmap[0] |= 0x00000022;
be_dws_cpu_to_le(ctxt, sizeof(req->context));
be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
@@ -754,7 +809,7 @@ int be_cmd_txq_create(struct be_adapter *adapter,
/* Uses mbox */
int be_cmd_rxq_create(struct be_adapter *adapter,
struct be_queue_info *rxq, u16 cq_id, u16 frag_size,
- u16 max_frame_size, u32 if_id, u32 rss)
+ u16 max_frame_size, u32 if_id, u32 rss, u8 *rss_id)
{
struct be_mcc_wrb *wrb;
struct be_cmd_req_eth_rx_create *req;
@@ -785,6 +840,7 @@ int be_cmd_rxq_create(struct be_adapter *adapter,
struct be_cmd_resp_eth_rx_create *resp = embedded_payload(wrb);
rxq->id = le16_to_cpu(resp->id);
rxq->created = true;
+ *rss_id = resp->rss_id;
}
spin_unlock(&adapter->mbox_lock);
@@ -1259,7 +1315,8 @@ err:
}
/* Uses mbox */
-int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num, u32 *mode)
+int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num,
+ u32 *mode, u32 *caps)
{
struct be_mcc_wrb *wrb;
struct be_cmd_req_query_fw_cfg *req;
@@ -1281,6 +1338,7 @@ int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num, u32 *mode)
struct be_cmd_resp_query_fw_cfg *resp = embedded_payload(wrb);
*port_num = le32_to_cpu(resp->phys_port);
*mode = le32_to_cpu(resp->function_mode);
+ *caps = le32_to_cpu(resp->function_caps);
}
spin_unlock(&adapter->mbox_lock);
@@ -1311,6 +1369,37 @@ int be_cmd_reset_function(struct be_adapter *adapter)
return status;
}
+int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable, u16 table_size)
+{
+ struct be_mcc_wrb *wrb;
+ struct be_cmd_req_rss_config *req;
+ u32 myhash[10];
+ int status;
+
+ spin_lock(&adapter->mbox_lock);
+
+ wrb = wrb_from_mbox(adapter);
+ req = embedded_payload(wrb);
+
+ be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
+ OPCODE_ETH_RSS_CONFIG);
+
+ be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
+ OPCODE_ETH_RSS_CONFIG, sizeof(*req));
+
+ req->if_id = cpu_to_le32(adapter->if_handle);
+ req->enable_rss = cpu_to_le16(RSS_ENABLE_TCP_IPV4 | RSS_ENABLE_IPV4);
+ req->cpu_table_size_log2 = cpu_to_le16(fls(table_size) - 1);
+ memcpy(req->cpu_table, rsstable, table_size);
+ memcpy(req->hash, myhash, sizeof(myhash));
+ be_dws_cpu_to_le(req->hash, sizeof(req->hash));
+
+ status = be_mbox_notify_wait(adapter);
+
+ spin_unlock(&adapter->mbox_lock);
+ return status;
+}
+
/* Uses sync mcc */
int be_cmd_set_beacon_state(struct be_adapter *adapter, u8 port_num,
u8 bcn, u8 sts, u8 state)
diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h
index ad1e6fac60c5..c7f6cdfe1c73 100644
--- a/drivers/net/benet/be_cmds.h
+++ b/drivers/net/benet/be_cmds.h
@@ -82,7 +82,12 @@ struct be_mcc_compl {
*/
#define ASYNC_TRAILER_EVENT_CODE_SHIFT 8 /* bits 8 - 15 */
#define ASYNC_TRAILER_EVENT_CODE_MASK 0xFF
+#define ASYNC_TRAILER_EVENT_TYPE_SHIFT 16
+#define ASYNC_TRAILER_EVENT_TYPE_MASK 0xFF
#define ASYNC_EVENT_CODE_LINK_STATE 0x1
+#define ASYNC_EVENT_CODE_GRP_5 0x5
+#define ASYNC_EVENT_QOS_SPEED 0x1
+#define ASYNC_EVENT_COS_PRIORITY 0x2
struct be_async_event_trailer {
u32 code;
};
@@ -105,6 +110,30 @@ struct be_async_event_link_state {
struct be_async_event_trailer trailer;
} __packed;
+/* When the event code of an async trailer is GRP-5 and event_type is QOS_SPEED
+ * the mcc_compl must be interpreted as follows
+ */
+struct be_async_event_grp5_qos_link_speed {
+ u8 physical_port;
+ u8 rsvd[5];
+ u16 qos_link_speed;
+ u32 event_tag;
+ struct be_async_event_trailer trailer;
+} __packed;
+
+/* When the event code of an async trailer is GRP5 and event type is
+ * CoS-Priority, the mcc_compl must be interpreted as follows
+ */
+struct be_async_event_grp5_cos_priority {
+ u8 physical_port;
+ u8 available_priority_bmap;
+ u8 reco_default_priority;
+ u8 valid;
+ u8 rsvd0;
+ u8 event_tag;
+ struct be_async_event_trailer trailer;
+} __packed;
+
struct be_mcc_mailbox {
struct be_mcc_wrb wrb;
struct be_mcc_compl compl;
@@ -123,8 +152,9 @@ struct be_mcc_mailbox {
#define OPCODE_COMMON_WRITE_FLASHROM 7
#define OPCODE_COMMON_CQ_CREATE 12
#define OPCODE_COMMON_EQ_CREATE 13
-#define OPCODE_COMMON_MCC_CREATE 21
+#define OPCODE_COMMON_MCC_CREATE 21
#define OPCODE_COMMON_SET_QOS 28
+#define OPCODE_COMMON_MCC_CREATE_EXT 90
#define OPCODE_COMMON_SEEPROM_READ 30
#define OPCODE_COMMON_NTWK_RX_FILTER 34
#define OPCODE_COMMON_GET_FW_VERSION 35
@@ -147,6 +177,7 @@ struct be_mcc_mailbox {
#define OPCODE_COMMON_READ_TRANSRECV_DATA 73
#define OPCODE_COMMON_GET_PHY_DETAILS 102
+#define OPCODE_ETH_RSS_CONFIG 1
#define OPCODE_ETH_ACPI_CONFIG 2
#define OPCODE_ETH_PROMISCUOUS 3
#define OPCODE_ETH_GET_STATISTICS 4
@@ -337,6 +368,7 @@ struct be_cmd_req_mcc_create {
struct be_cmd_req_hdr hdr;
u16 num_pages;
u16 rsvd0;
+ u32 async_event_bitmap[1];
u8 context[sizeof(struct amap_mcc_context) / 8];
struct phys_addr pages[8];
} __packed;
@@ -409,7 +441,7 @@ struct be_cmd_req_eth_rx_create {
struct be_cmd_resp_eth_rx_create {
struct be_cmd_resp_hdr hdr;
u16 id;
- u8 cpu_id;
+ u8 rss_id;
u8 rsvd0;
} __packed;
@@ -739,9 +771,10 @@ struct be_cmd_resp_modify_eq_delay {
} __packed;
/******************** Get FW Config *******************/
+#define BE_FUNCTION_CAPS_RSS 0x2
struct be_cmd_req_query_fw_cfg {
struct be_cmd_req_hdr hdr;
- u32 rsvd[30];
+ u32 rsvd[31];
};
struct be_cmd_resp_query_fw_cfg {
@@ -751,6 +784,26 @@ struct be_cmd_resp_query_fw_cfg {
u32 phys_port;
u32 function_mode;
u32 rsvd[26];
+ u32 function_caps;
+};
+
+/******************** RSS Config *******************/
+/* RSS types */
+#define RSS_ENABLE_NONE 0x0
+#define RSS_ENABLE_IPV4 0x1
+#define RSS_ENABLE_TCP_IPV4 0x2
+#define RSS_ENABLE_IPV6 0x4
+#define RSS_ENABLE_TCP_IPV6 0x8
+
+struct be_cmd_req_rss_config {
+ struct be_cmd_req_hdr hdr;
+ u32 if_id;
+ u16 enable_rss;
+ u16 cpu_table_size_log2;
+ u32 hash[10];
+ u8 cpu_table[128];
+ u8 flush;
+ u8 rsvd0[3];
};
/******************** Port Beacon ***************************/
@@ -937,7 +990,7 @@ extern int be_cmd_txq_create(struct be_adapter *adapter,
extern int be_cmd_rxq_create(struct be_adapter *adapter,
struct be_queue_info *rxq, u16 cq_id,
u16 frag_size, u16 max_frame_size, u32 if_id,
- u32 rss);
+ u32 rss, u8 *rss_id);
extern int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q,
int type);
extern int be_cmd_link_status_query(struct be_adapter *adapter,
@@ -960,8 +1013,10 @@ extern int be_cmd_set_flow_control(struct be_adapter *adapter,
extern int be_cmd_get_flow_control(struct be_adapter *adapter,
u32 *tx_fc, u32 *rx_fc);
extern int be_cmd_query_fw_cfg(struct be_adapter *adapter,
- u32 *port_num, u32 *cap);
+ u32 *port_num, u32 *function_mode, u32 *function_caps);
extern int be_cmd_reset_function(struct be_adapter *adapter);
+extern int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable,
+ u16 table_size);
extern int be_process_mcc(struct be_adapter *adapter, int *status);
extern int be_cmd_set_beacon_state(struct be_adapter *adapter,
u8 port_num, u8 beacon, u8 status, u8 state);
diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c
index 13f0abbc5205..0f46366ecc48 100644
--- a/drivers/net/benet/be_ethtool.c
+++ b/drivers/net/benet/be_ethtool.c
@@ -26,14 +26,16 @@ struct be_ethtool_stat {
int offset;
};
-enum {NETSTAT, PORTSTAT, MISCSTAT, DRVSTAT, ERXSTAT};
+enum {NETSTAT, PORTSTAT, MISCSTAT, DRVSTAT_TX, DRVSTAT_RX, ERXSTAT};
#define FIELDINFO(_struct, field) FIELD_SIZEOF(_struct, field), \
offsetof(_struct, field)
#define NETSTAT_INFO(field) #field, NETSTAT,\
FIELDINFO(struct net_device_stats,\
field)
-#define DRVSTAT_INFO(field) #field, DRVSTAT,\
- FIELDINFO(struct be_drvr_stats, field)
+#define DRVSTAT_TX_INFO(field) #field, DRVSTAT_TX,\
+ FIELDINFO(struct be_tx_stats, field)
+#define DRVSTAT_RX_INFO(field) #field, DRVSTAT_RX,\
+ FIELDINFO(struct be_rx_stats, field)
#define MISCSTAT_INFO(field) #field, MISCSTAT,\
FIELDINFO(struct be_rxf_stats, field)
#define PORTSTAT_INFO(field) #field, PORTSTAT,\
@@ -51,21 +53,12 @@ static const struct be_ethtool_stat et_stats[] = {
{NETSTAT_INFO(tx_errors)},
{NETSTAT_INFO(rx_dropped)},
{NETSTAT_INFO(tx_dropped)},
- {DRVSTAT_INFO(be_tx_reqs)},
- {DRVSTAT_INFO(be_tx_stops)},
- {DRVSTAT_INFO(be_fwd_reqs)},
- {DRVSTAT_INFO(be_tx_wrbs)},
- {DRVSTAT_INFO(be_rx_polls)},
- {DRVSTAT_INFO(be_tx_events)},
- {DRVSTAT_INFO(be_rx_events)},
- {DRVSTAT_INFO(be_tx_compl)},
- {DRVSTAT_INFO(be_rx_compl)},
- {DRVSTAT_INFO(be_rx_mcast_pkt)},
- {DRVSTAT_INFO(be_ethrx_post_fail)},
- {DRVSTAT_INFO(be_802_3_dropped_frames)},
- {DRVSTAT_INFO(be_802_3_malformed_frames)},
- {DRVSTAT_INFO(be_tx_rate)},
- {DRVSTAT_INFO(be_rx_rate)},
+ {DRVSTAT_TX_INFO(be_tx_rate)},
+ {DRVSTAT_TX_INFO(be_tx_reqs)},
+ {DRVSTAT_TX_INFO(be_tx_wrbs)},
+ {DRVSTAT_TX_INFO(be_tx_stops)},
+ {DRVSTAT_TX_INFO(be_tx_events)},
+ {DRVSTAT_TX_INFO(be_tx_compl)},
{PORTSTAT_INFO(rx_unicast_frames)},
{PORTSTAT_INFO(rx_multicast_frames)},
{PORTSTAT_INFO(rx_broadcast_frames)},
@@ -91,6 +84,9 @@ static const struct be_ethtool_stat et_stats[] = {
{PORTSTAT_INFO(rx_non_rss_packets)},
{PORTSTAT_INFO(rx_ipv4_packets)},
{PORTSTAT_INFO(rx_ipv6_packets)},
+ {PORTSTAT_INFO(rx_switched_unicast_packets)},
+ {PORTSTAT_INFO(rx_switched_multicast_packets)},
+ {PORTSTAT_INFO(rx_switched_broadcast_packets)},
{PORTSTAT_INFO(tx_unicastframes)},
{PORTSTAT_INFO(tx_multicastframes)},
{PORTSTAT_INFO(tx_broadcastframes)},
@@ -103,11 +99,24 @@ static const struct be_ethtool_stat et_stats[] = {
{MISCSTAT_INFO(rx_drops_too_many_frags)},
{MISCSTAT_INFO(rx_drops_invalid_ring)},
{MISCSTAT_INFO(forwarded_packets)},
- {MISCSTAT_INFO(rx_drops_mtu)},
- {ERXSTAT_INFO(rx_drops_no_fragments)},
+ {MISCSTAT_INFO(rx_drops_mtu)}
};
#define ETHTOOL_STATS_NUM ARRAY_SIZE(et_stats)
+/* Stats related to multi RX queues */
+static const struct be_ethtool_stat et_rx_stats[] = {
+ {DRVSTAT_RX_INFO(rx_bytes)},
+ {DRVSTAT_RX_INFO(rx_pkts)},
+ {DRVSTAT_RX_INFO(rx_rate)},
+ {DRVSTAT_RX_INFO(rx_polls)},
+ {DRVSTAT_RX_INFO(rx_events)},
+ {DRVSTAT_RX_INFO(rx_compl)},
+ {DRVSTAT_RX_INFO(rx_mcast_pkts)},
+ {DRVSTAT_RX_INFO(rx_post_fail)},
+ {ERXSTAT_INFO(rx_drops_no_fragments)}
+};
+#define ETHTOOL_RXSTATS_NUM (ARRAY_SIZE(et_rx_stats))
+
static const char et_self_tests[][ETH_GSTRING_LEN] = {
"MAC Loopback test",
"PHY Loopback test",
@@ -140,7 +149,7 @@ static int
be_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
{
struct be_adapter *adapter = netdev_priv(netdev);
- struct be_eq_obj *rx_eq = &adapter->rx_eq;
+ struct be_eq_obj *rx_eq = &adapter->rx_obj[0].rx_eq;
struct be_eq_obj *tx_eq = &adapter->tx_eq;
coalesce->rx_coalesce_usecs = rx_eq->cur_eqd;
@@ -164,25 +173,49 @@ static int
be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
{
struct be_adapter *adapter = netdev_priv(netdev);
- struct be_eq_obj *rx_eq = &adapter->rx_eq;
+ struct be_rx_obj *rxo;
+ struct be_eq_obj *rx_eq;
struct be_eq_obj *tx_eq = &adapter->tx_eq;
u32 tx_max, tx_min, tx_cur;
u32 rx_max, rx_min, rx_cur;
- int status = 0;
+ int status = 0, i;
if (coalesce->use_adaptive_tx_coalesce == 1)
return -EINVAL;
- /* if AIC is being turned on now, start with an EQD of 0 */
- if (rx_eq->enable_aic == 0 &&
- coalesce->use_adaptive_rx_coalesce == 1) {
- rx_eq->cur_eqd = 0;
+ for_all_rx_queues(adapter, rxo, i) {
+ rx_eq = &rxo->rx_eq;
+
+ if (!rx_eq->enable_aic && coalesce->use_adaptive_rx_coalesce)
+ rx_eq->cur_eqd = 0;
+ rx_eq->enable_aic = coalesce->use_adaptive_rx_coalesce;
+
+ rx_max = coalesce->rx_coalesce_usecs_high;
+ rx_min = coalesce->rx_coalesce_usecs_low;
+ rx_cur = coalesce->rx_coalesce_usecs;
+
+ if (rx_eq->enable_aic) {
+ if (rx_max > BE_MAX_EQD)
+ rx_max = BE_MAX_EQD;
+ if (rx_min > rx_max)
+ rx_min = rx_max;
+ rx_eq->max_eqd = rx_max;
+ rx_eq->min_eqd = rx_min;
+ if (rx_eq->cur_eqd > rx_max)
+ rx_eq->cur_eqd = rx_max;
+ if (rx_eq->cur_eqd < rx_min)
+ rx_eq->cur_eqd = rx_min;
+ } else {
+ if (rx_cur > BE_MAX_EQD)
+ rx_cur = BE_MAX_EQD;
+ if (rx_eq->cur_eqd != rx_cur) {
+ status = be_cmd_modify_eqd(adapter, rx_eq->q.id,
+ rx_cur);
+ if (!status)
+ rx_eq->cur_eqd = rx_cur;
+ }
+ }
}
- rx_eq->enable_aic = coalesce->use_adaptive_rx_coalesce;
-
- rx_max = coalesce->rx_coalesce_usecs_high;
- rx_min = coalesce->rx_coalesce_usecs_low;
- rx_cur = coalesce->rx_coalesce_usecs;
tx_max = coalesce->tx_coalesce_usecs_high;
tx_min = coalesce->tx_coalesce_usecs_low;
@@ -196,27 +229,6 @@ be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
tx_eq->cur_eqd = tx_cur;
}
- if (rx_eq->enable_aic) {
- if (rx_max > BE_MAX_EQD)
- rx_max = BE_MAX_EQD;
- if (rx_min > rx_max)
- rx_min = rx_max;
- rx_eq->max_eqd = rx_max;
- rx_eq->min_eqd = rx_min;
- if (rx_eq->cur_eqd > rx_max)
- rx_eq->cur_eqd = rx_max;
- if (rx_eq->cur_eqd < rx_min)
- rx_eq->cur_eqd = rx_min;
- } else {
- if (rx_cur > BE_MAX_EQD)
- rx_cur = BE_MAX_EQD;
- if (rx_eq->cur_eqd != rx_cur) {
- status = be_cmd_modify_eqd(adapter, rx_eq->q.id,
- rx_cur);
- if (!status)
- rx_eq->cur_eqd = rx_cur;
- }
- }
return 0;
}
@@ -244,32 +256,25 @@ be_get_ethtool_stats(struct net_device *netdev,
struct ethtool_stats *stats, uint64_t *data)
{
struct be_adapter *adapter = netdev_priv(netdev);
- struct be_drvr_stats *drvr_stats = &adapter->stats.drvr_stats;
- struct be_hw_stats *hw_stats = hw_stats_from_cmd(adapter->stats.cmd.va);
- struct be_rxf_stats *rxf_stats = &hw_stats->rxf;
- struct be_port_rxf_stats *port_stats =
- &rxf_stats->port[adapter->port_num];
- struct net_device_stats *net_stats = &netdev->stats;
+ struct be_hw_stats *hw_stats = hw_stats_from_cmd(adapter->stats_cmd.va);
struct be_erx_stats *erx_stats = &hw_stats->erx;
+ struct be_rx_obj *rxo;
void *p = NULL;
- int i;
+ int i, j;
for (i = 0; i < ETHTOOL_STATS_NUM; i++) {
switch (et_stats[i].type) {
case NETSTAT:
- p = net_stats;
+ p = &netdev->stats;
break;
- case DRVSTAT:
- p = drvr_stats;
+ case DRVSTAT_TX:
+ p = &adapter->tx_stats;
break;
case PORTSTAT:
- p = port_stats;
+ p = &hw_stats->rxf.port[adapter->port_num];
break;
case MISCSTAT:
- p = rxf_stats;
- break;
- case ERXSTAT: /* Currently only one ERX stat is provided */
- p = (u32 *)erx_stats + adapter->rx_obj.q.id;
+ p = &hw_stats->rxf;
break;
}
@@ -277,19 +282,44 @@ be_get_ethtool_stats(struct net_device *netdev,
data[i] = (et_stats[i].size == sizeof(u64)) ?
*(u64 *)p: *(u32 *)p;
}
+
+ for_all_rx_queues(adapter, rxo, j) {
+ for (i = 0; i < ETHTOOL_RXSTATS_NUM; i++) {
+ switch (et_rx_stats[i].type) {
+ case DRVSTAT_RX:
+ p = (u8 *)&rxo->stats + et_rx_stats[i].offset;
+ break;
+ case ERXSTAT:
+ p = (u32 *)erx_stats + rxo->q.id;
+ break;
+ }
+ data[ETHTOOL_STATS_NUM + j * ETHTOOL_RXSTATS_NUM + i] =
+ (et_rx_stats[i].size == sizeof(u64)) ?
+ *(u64 *)p: *(u32 *)p;
+ }
+ }
}
static void
be_get_stat_strings(struct net_device *netdev, uint32_t stringset,
uint8_t *data)
{
- int i;
+ struct be_adapter *adapter = netdev_priv(netdev);
+ int i, j;
+
switch (stringset) {
case ETH_SS_STATS:
for (i = 0; i < ETHTOOL_STATS_NUM; i++) {
memcpy(data, et_stats[i].desc, ETH_GSTRING_LEN);
data += ETH_GSTRING_LEN;
}
+ for (i = 0; i < adapter->num_rx_qs; i++) {
+ for (j = 0; j < ETHTOOL_RXSTATS_NUM; j++) {
+ sprintf(data, "rxq%d: %s", i,
+ et_rx_stats[j].desc);
+ data += ETH_GSTRING_LEN;
+ }
+ }
break;
case ETH_SS_TEST:
for (i = 0; i < ETHTOOL_TESTS_NUM; i++) {
@@ -302,11 +332,14 @@ be_get_stat_strings(struct net_device *netdev, uint32_t stringset,
static int be_get_sset_count(struct net_device *netdev, int stringset)
{
+ struct be_adapter *adapter = netdev_priv(netdev);
+
switch (stringset) {
case ETH_SS_TEST:
return ETHTOOL_TESTS_NUM;
case ETH_SS_STATS:
- return ETHTOOL_STATS_NUM;
+ return ETHTOOL_STATS_NUM +
+ adapter->num_rx_qs * ETHTOOL_RXSTATS_NUM;
default:
return -EINVAL;
}
@@ -421,10 +454,10 @@ be_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring)
{
struct be_adapter *adapter = netdev_priv(netdev);
- ring->rx_max_pending = adapter->rx_obj.q.len;
+ ring->rx_max_pending = adapter->rx_obj[0].q.len;
ring->tx_max_pending = adapter->tx_obj.q.len;
- ring->rx_pending = atomic_read(&adapter->rx_obj.q.used);
+ ring->rx_pending = atomic_read(&adapter->rx_obj[0].q.used);
ring->tx_pending = atomic_read(&adapter->tx_obj.q.used);
}
diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c
index 6eda7a022256..45b1f6635282 100644
--- a/drivers/net/benet/be_main.c
+++ b/drivers/net/benet/be_main.c
@@ -32,6 +32,10 @@ module_param(num_vfs, uint, S_IRUGO);
MODULE_PARM_DESC(rx_frag_size, "Size of a fragment that holds rcvd data.");
MODULE_PARM_DESC(num_vfs, "Number of PCI VFs to initialize");
+static bool multi_rxq = true;
+module_param(multi_rxq, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(multi_rxq, "Multi Rx Queue support. Enabled by default");
+
static DEFINE_PCI_DEVICE_TABLE(be_dev_ids) = {
{ PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) },
{ PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID2) },
@@ -111,6 +115,11 @@ static char *ue_status_hi_desc[] = {
"Unknown"
};
+static inline bool be_multi_rxq(struct be_adapter *adapter)
+{
+ return (adapter->num_rx_qs > 1);
+}
+
static void be_queue_free(struct be_adapter *adapter, struct be_queue_info *q)
{
struct be_dma_mem *mem = &q->dma_mem;
@@ -236,18 +245,27 @@ netdev_addr:
void netdev_stats_update(struct be_adapter *adapter)
{
- struct be_hw_stats *hw_stats = hw_stats_from_cmd(adapter->stats.cmd.va);
+ struct be_hw_stats *hw_stats = hw_stats_from_cmd(adapter->stats_cmd.va);
struct be_rxf_stats *rxf_stats = &hw_stats->rxf;
struct be_port_rxf_stats *port_stats =
&rxf_stats->port[adapter->port_num];
struct net_device_stats *dev_stats = &adapter->netdev->stats;
struct be_erx_stats *erx_stats = &hw_stats->erx;
+ struct be_rx_obj *rxo;
+ int i;
+
+ memset(dev_stats, 0, sizeof(*dev_stats));
+ for_all_rx_queues(adapter, rxo, i) {
+ dev_stats->rx_packets += rx_stats(rxo)->rx_pkts;
+ dev_stats->rx_bytes += rx_stats(rxo)->rx_bytes;
+ dev_stats->multicast += rx_stats(rxo)->rx_mcast_pkts;
+ /* no space in linux buffers: best possible approximation */
+ dev_stats->rx_dropped +=
+ erx_stats->rx_drops_no_fragments[rxo->q.id];
+ }
- dev_stats->rx_packets = drvr_stats(adapter)->be_rx_pkts;
- dev_stats->tx_packets = drvr_stats(adapter)->be_tx_pkts;
- dev_stats->rx_bytes = drvr_stats(adapter)->be_rx_bytes;
- dev_stats->tx_bytes = drvr_stats(adapter)->be_tx_bytes;
- dev_stats->multicast = drvr_stats(adapter)->be_rx_mcast_pkt;
+ dev_stats->tx_packets = tx_stats(adapter)->be_tx_pkts;
+ dev_stats->tx_bytes = tx_stats(adapter)->be_tx_bytes;
/* bad pkts received */
dev_stats->rx_errors = port_stats->rx_crc_errors +
@@ -264,18 +282,11 @@ void netdev_stats_update(struct be_adapter *adapter)
port_stats->rx_ip_checksum_errs +
port_stats->rx_udp_checksum_errs;
- /* no space in linux buffers: best possible approximation */
- dev_stats->rx_dropped =
- erx_stats->rx_drops_no_fragments[adapter->rx_obj.q.id];
-
/* detailed rx errors */
dev_stats->rx_length_errors = port_stats->rx_in_range_errors +
port_stats->rx_out_range_errors +
port_stats->rx_frame_too_long;
- /* receive ring buffer overflow */
- dev_stats->rx_over_errors = 0;
-
dev_stats->rx_crc_errors = port_stats->rx_crc_errors;
/* frame alignment errors */
@@ -286,23 +297,6 @@ void netdev_stats_update(struct be_adapter *adapter)
dev_stats->rx_fifo_errors = port_stats->rx_fifo_overflow +
port_stats->rx_input_fifo_overflow +
rxf_stats->rx_drops_no_pbuf;
- /* receiver missed packetd */
- dev_stats->rx_missed_errors = 0;
-
- /* packet transmit problems */
- dev_stats->tx_errors = 0;
-
- /* no space available in linux */
- dev_stats->tx_dropped = 0;
-
- dev_stats->collisions = 0;
-
- /* detailed tx_errors */
- dev_stats->tx_aborted_errors = 0;
- dev_stats->tx_carrier_errors = 0;
- dev_stats->tx_fifo_errors = 0;
- dev_stats->tx_heartbeat_errors = 0;
- dev_stats->tx_window_errors = 0;
}
void be_link_status_update(struct be_adapter *adapter, bool link_up)
@@ -326,10 +320,10 @@ void be_link_status_update(struct be_adapter *adapter, bool link_up)
}
/* Update the EQ delay n BE based on the RX frags consumed / sec */
-static void be_rx_eqd_update(struct be_adapter *adapter)
+static void be_rx_eqd_update(struct be_adapter *adapter, struct be_rx_obj *rxo)
{
- struct be_eq_obj *rx_eq = &adapter->rx_eq;
- struct be_drvr_stats *stats = &adapter->stats.drvr_stats;
+ struct be_eq_obj *rx_eq = &rxo->rx_eq;
+ struct be_rx_stats *stats = &rxo->stats;
ulong now = jiffies;
u32 eqd;
@@ -346,12 +340,12 @@ static void be_rx_eqd_update(struct be_adapter *adapter)
if ((now - stats->rx_fps_jiffies) < HZ)
return;
- stats->be_rx_fps = (stats->be_rx_frags - stats->be_prev_rx_frags) /
+ stats->rx_fps = (stats->rx_frags - stats->prev_rx_frags) /
((now - stats->rx_fps_jiffies) / HZ);
stats->rx_fps_jiffies = now;
- stats->be_prev_rx_frags = stats->be_rx_frags;
- eqd = stats->be_rx_fps / 110000;
+ stats->prev_rx_frags = stats->rx_frags;
+ eqd = stats->rx_fps / 110000;
eqd = eqd << 3;
if (eqd > rx_eq->max_eqd)
eqd = rx_eq->max_eqd;
@@ -365,11 +359,6 @@ static void be_rx_eqd_update(struct be_adapter *adapter)
rx_eq->cur_eqd = eqd;
}
-static struct net_device_stats *be_get_stats(struct net_device *dev)
-{
- return &dev->stats;
-}
-
static u32 be_calc_rate(u64 bytes, unsigned long ticks)
{
u64 rate = bytes;
@@ -383,7 +372,7 @@ static u32 be_calc_rate(u64 bytes, unsigned long ticks)
static void be_tx_rate_update(struct be_adapter *adapter)
{
- struct be_drvr_stats *stats = drvr_stats(adapter);
+ struct be_tx_stats *stats = tx_stats(adapter);
ulong now = jiffies;
/* Wrapped around? */
@@ -405,7 +394,7 @@ static void be_tx_rate_update(struct be_adapter *adapter)
static void be_tx_stats_update(struct be_adapter *adapter,
u32 wrb_cnt, u32 copied, u32 gso_segs, bool stopped)
{
- struct be_drvr_stats *stats = drvr_stats(adapter);
+ struct be_tx_stats *stats = tx_stats(adapter);
stats->be_tx_reqs++;
stats->be_tx_wrbs += wrb_cnt;
stats->be_tx_bytes += copied;
@@ -440,9 +429,12 @@ static inline void wrb_fill(struct be_eth_wrb *wrb, u64 addr, int len)
wrb->frag_len = len & ETH_WRB_FRAG_LEN_MASK;
}
-static void wrb_fill_hdr(struct be_eth_hdr_wrb *hdr, struct sk_buff *skb,
- bool vlan, u32 wrb_cnt, u32 len)
+static void wrb_fill_hdr(struct be_adapter *adapter, struct be_eth_hdr_wrb *hdr,
+ struct sk_buff *skb, u32 wrb_cnt, u32 len)
{
+ u8 vlan_prio = 0;
+ u16 vlan_tag = 0;
+
memset(hdr, 0, sizeof(*hdr));
AMAP_SET_BITS(struct amap_eth_hdr_wrb, crc, hdr, 1);
@@ -460,10 +452,15 @@ static void wrb_fill_hdr(struct be_eth_hdr_wrb *hdr, struct sk_buff *skb,
AMAP_SET_BITS(struct amap_eth_hdr_wrb, udpcs, hdr, 1);
}
- if (vlan && vlan_tx_tag_present(skb)) {
+ if (adapter->vlan_grp && vlan_tx_tag_present(skb)) {
AMAP_SET_BITS(struct amap_eth_hdr_wrb, vlan, hdr, 1);
- AMAP_SET_BITS(struct amap_eth_hdr_wrb, vlan_tag,
- hdr, vlan_tx_tag_get(skb));
+ vlan_tag = vlan_tx_tag_get(skb);
+ vlan_prio = (vlan_tag & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT;
+ /* If vlan priority provided by OS is NOT in available bmap */
+ if (!(adapter->vlan_prio_bmap & (1 << vlan_prio)))
+ vlan_tag = (vlan_tag & ~VLAN_PRIO_MASK) |
+ adapter->recommended_prio;
+ AMAP_SET_BITS(struct amap_eth_hdr_wrb, vlan_tag, hdr, vlan_tag);
}
AMAP_SET_BITS(struct amap_eth_hdr_wrb, event, hdr, 1);
@@ -543,8 +540,7 @@ static int make_tx_wrbs(struct be_adapter *adapter,
queue_head_inc(txq);
}
- wrb_fill_hdr(hdr, first_skb, adapter->vlan_grp ? true : false,
- wrb_cnt, copied);
+ wrb_fill_hdr(adapter, hdr, first_skb, wrb_cnt, copied);
be_dws_cpu_to_le(hdr, sizeof(*hdr));
return copied;
@@ -637,7 +633,7 @@ static int be_vid_config(struct be_adapter *adapter, bool vf, u32 vf_num)
if (adapter->vlans_added <= adapter->max_vlans) {
/* Construct VLAN Table to give to HW */
- for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
+ for (i = 0; i < VLAN_N_VID; i++) {
if (adapter->vlan_tag[i]) {
vtag[ntags] = cpu_to_le16(i);
ntags++;
@@ -656,14 +652,8 @@ static int be_vid_config(struct be_adapter *adapter, bool vf, u32 vf_num)
static void be_vlan_register(struct net_device *netdev, struct vlan_group *grp)
{
struct be_adapter *adapter = netdev_priv(netdev);
- struct be_eq_obj *rx_eq = &adapter->rx_eq;
- struct be_eq_obj *tx_eq = &adapter->tx_eq;
- be_eq_notify(adapter, rx_eq->q.id, false, false, 0);
- be_eq_notify(adapter, tx_eq->q.id, false, false, 0);
adapter->vlan_grp = grp;
- be_eq_notify(adapter, rx_eq->q.id, true, false, 0);
- be_eq_notify(adapter, tx_eq->q.id, true, false, 0);
}
static void be_vlan_add_vid(struct net_device *netdev, u16 vid)
@@ -825,40 +815,38 @@ static int be_set_vf_tx_rate(struct net_device *netdev,
return status;
}
-static void be_rx_rate_update(struct be_adapter *adapter)
+static void be_rx_rate_update(struct be_rx_obj *rxo)
{
- struct be_drvr_stats *stats = drvr_stats(adapter);
+ struct be_rx_stats *stats = &rxo->stats;
ulong now = jiffies;
/* Wrapped around */
- if (time_before(now, stats->be_rx_jiffies)) {
- stats->be_rx_jiffies = now;
+ if (time_before(now, stats->rx_jiffies)) {
+ stats->rx_jiffies = now;
return;
}
/* Update the rate once in two seconds */
- if ((now - stats->be_rx_jiffies) < 2 * HZ)
+ if ((now - stats->rx_jiffies) < 2 * HZ)
return;
- stats->be_rx_rate = be_calc_rate(stats->be_rx_bytes
- - stats->be_rx_bytes_prev,
- now - stats->be_rx_jiffies);
- stats->be_rx_jiffies = now;
- stats->be_rx_bytes_prev = stats->be_rx_bytes;
+ stats->rx_rate = be_calc_rate(stats->rx_bytes - stats->rx_bytes_prev,
+ now - stats->rx_jiffies);
+ stats->rx_jiffies = now;
+ stats->rx_bytes_prev = stats->rx_bytes;
}
-static void be_rx_stats_update(struct be_adapter *adapter,
+static void be_rx_stats_update(struct be_rx_obj *rxo,
u32 pktsize, u16 numfrags, u8 pkt_type)
{
- struct be_drvr_stats *stats = drvr_stats(adapter);
-
- stats->be_rx_compl++;
- stats->be_rx_frags += numfrags;
- stats->be_rx_bytes += pktsize;
- stats->be_rx_pkts++;
+ struct be_rx_stats *stats = &rxo->stats;
+ stats->rx_compl++;
+ stats->rx_frags += numfrags;
+ stats->rx_bytes += pktsize;
+ stats->rx_pkts++;
if (pkt_type == BE_MULTICAST_PACKET)
- stats->be_rx_mcast_pkt++;
+ stats->rx_mcast_pkts++;
}
static inline bool do_pkt_csum(struct be_eth_rx_compl *rxcp, bool cso)
@@ -878,12 +866,14 @@ static inline bool do_pkt_csum(struct be_eth_rx_compl *rxcp, bool cso)
}
static struct be_rx_page_info *
-get_rx_page_info(struct be_adapter *adapter, u16 frag_idx)
+get_rx_page_info(struct be_adapter *adapter,
+ struct be_rx_obj *rxo,
+ u16 frag_idx)
{
struct be_rx_page_info *rx_page_info;
- struct be_queue_info *rxq = &adapter->rx_obj.q;
+ struct be_queue_info *rxq = &rxo->q;
- rx_page_info = &adapter->rx_obj.page_info_tbl[frag_idx];
+ rx_page_info = &rxo->page_info_tbl[frag_idx];
BUG_ON(!rx_page_info->page);
if (rx_page_info->last_page_user) {
@@ -898,9 +888,10 @@ get_rx_page_info(struct be_adapter *adapter, u16 frag_idx)
/* Throwaway the data in the Rx completion */
static void be_rx_compl_discard(struct be_adapter *adapter,
- struct be_eth_rx_compl *rxcp)
+ struct be_rx_obj *rxo,
+ struct be_eth_rx_compl *rxcp)
{
- struct be_queue_info *rxq = &adapter->rx_obj.q;
+ struct be_queue_info *rxq = &rxo->q;
struct be_rx_page_info *page_info;
u16 rxq_idx, i, num_rcvd;
@@ -908,7 +899,7 @@ static void be_rx_compl_discard(struct be_adapter *adapter,
num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp);
for (i = 0; i < num_rcvd; i++) {
- page_info = get_rx_page_info(adapter, rxq_idx);
+ page_info = get_rx_page_info(adapter, rxo, rxq_idx);
put_page(page_info->page);
memset(page_info, 0, sizeof(*page_info));
index_inc(&rxq_idx, rxq->len);
@@ -919,11 +910,11 @@ static void be_rx_compl_discard(struct be_adapter *adapter,
* skb_fill_rx_data forms a complete skb for an ether frame
* indicated by rxcp.
*/
-static void skb_fill_rx_data(struct be_adapter *adapter,
+static void skb_fill_rx_data(struct be_adapter *adapter, struct be_rx_obj *rxo,
struct sk_buff *skb, struct be_eth_rx_compl *rxcp,
u16 num_rcvd)
{
- struct be_queue_info *rxq = &adapter->rx_obj.q;
+ struct be_queue_info *rxq = &rxo->q;
struct be_rx_page_info *page_info;
u16 rxq_idx, i, j;
u32 pktsize, hdr_len, curr_frag_len, size;
@@ -934,7 +925,7 @@ static void skb_fill_rx_data(struct be_adapter *adapter,
pktsize = AMAP_GET_BITS(struct amap_eth_rx_compl, pktsize, rxcp);
pkt_type = AMAP_GET_BITS(struct amap_eth_rx_compl, cast_enc, rxcp);
- page_info = get_rx_page_info(adapter, rxq_idx);
+ page_info = get_rx_page_info(adapter, rxo, rxq_idx);
start = page_address(page_info->page) + page_info->page_offset;
prefetch(start);
@@ -972,7 +963,7 @@ static void skb_fill_rx_data(struct be_adapter *adapter,
for (i = 1, j = 0; i < num_rcvd; i++) {
size -= curr_frag_len;
index_inc(&rxq_idx, rxq->len);
- page_info = get_rx_page_info(adapter, rxq_idx);
+ page_info = get_rx_page_info(adapter, rxo, rxq_idx);
curr_frag_len = min(size, rx_frag_size);
@@ -998,11 +989,12 @@ static void skb_fill_rx_data(struct be_adapter *adapter,
BUG_ON(j > MAX_SKB_FRAGS);
done:
- be_rx_stats_update(adapter, pktsize, num_rcvd, pkt_type);
+ be_rx_stats_update(rxo, pktsize, num_rcvd, pkt_type);
}
/* Process the RX completion indicated by rxcp when GRO is disabled */
static void be_rx_compl_process(struct be_adapter *adapter,
+ struct be_rx_obj *rxo,
struct be_eth_rx_compl *rxcp)
{
struct sk_buff *skb;
@@ -1019,14 +1011,14 @@ static void be_rx_compl_process(struct be_adapter *adapter,
if (unlikely(!skb)) {
if (net_ratelimit())
dev_warn(&adapter->pdev->dev, "skb alloc failed\n");
- be_rx_compl_discard(adapter, rxcp);
+ be_rx_compl_discard(adapter, rxo, rxcp);
return;
}
- skb_fill_rx_data(adapter, skb, rxcp, num_rcvd);
+ skb_fill_rx_data(adapter, rxo, skb, rxcp, num_rcvd);
if (do_pkt_csum(rxcp, adapter->rx_csum))
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
else
skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -1056,12 +1048,13 @@ static void be_rx_compl_process(struct be_adapter *adapter,
/* Process the RX completion indicated by rxcp when GRO is enabled */
static void be_rx_compl_process_gro(struct be_adapter *adapter,
- struct be_eth_rx_compl *rxcp)
+ struct be_rx_obj *rxo,
+ struct be_eth_rx_compl *rxcp)
{
struct be_rx_page_info *page_info;
struct sk_buff *skb = NULL;
- struct be_queue_info *rxq = &adapter->rx_obj.q;
- struct be_eq_obj *eq_obj = &adapter->rx_eq;
+ struct be_queue_info *rxq = &rxo->q;
+ struct be_eq_obj *eq_obj = &rxo->rx_eq;
u32 num_rcvd, pkt_size, remaining, vlanf, curr_frag_len;
u16 i, rxq_idx = 0, vid, j;
u8 vtm;
@@ -1085,13 +1078,13 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter,
skb = napi_get_frags(&eq_obj->napi);
if (!skb) {
- be_rx_compl_discard(adapter, rxcp);
+ be_rx_compl_discard(adapter, rxo, rxcp);
return;
}
remaining = pkt_size;
for (i = 0, j = -1; i < num_rcvd; i++) {
- page_info = get_rx_page_info(adapter, rxq_idx);
+ page_info = get_rx_page_info(adapter, rxo, rxq_idx);
curr_frag_len = min(remaining, rx_frag_size);
@@ -1132,12 +1125,12 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter,
vlan_gro_frags(&eq_obj->napi, adapter->vlan_grp, vid);
}
- be_rx_stats_update(adapter, pkt_size, num_rcvd, pkt_type);
+ be_rx_stats_update(rxo, pkt_size, num_rcvd, pkt_type);
}
-static struct be_eth_rx_compl *be_rx_compl_get(struct be_adapter *adapter)
+static struct be_eth_rx_compl *be_rx_compl_get(struct be_rx_obj *rxo)
{
- struct be_eth_rx_compl *rxcp = queue_tail_node(&adapter->rx_obj.cq);
+ struct be_eth_rx_compl *rxcp = queue_tail_node(&rxo->cq);
if (rxcp->dw[offsetof(struct amap_eth_rx_compl, valid) / 32] == 0)
return NULL;
@@ -1145,7 +1138,7 @@ static struct be_eth_rx_compl *be_rx_compl_get(struct be_adapter *adapter)
rmb();
be_dws_le_to_cpu(rxcp, sizeof(*rxcp));
- queue_tail_inc(&adapter->rx_obj.cq);
+ queue_tail_inc(&rxo->cq);
return rxcp;
}
@@ -1171,22 +1164,23 @@ static inline struct page *be_alloc_pages(u32 size)
* Allocate a page, split it to fragments of size rx_frag_size and post as
* receive buffers to BE
*/
-static void be_post_rx_frags(struct be_adapter *adapter)
+static void be_post_rx_frags(struct be_rx_obj *rxo)
{
- struct be_rx_page_info *page_info_tbl = adapter->rx_obj.page_info_tbl;
+ struct be_adapter *adapter = rxo->adapter;
+ struct be_rx_page_info *page_info_tbl = rxo->page_info_tbl;
struct be_rx_page_info *page_info = NULL, *prev_page_info = NULL;
- struct be_queue_info *rxq = &adapter->rx_obj.q;
+ struct be_queue_info *rxq = &rxo->q;
struct page *pagep = NULL;
struct be_eth_rx_d *rxd;
u64 page_dmaaddr = 0, frag_dmaaddr;
u32 posted, page_offset = 0;
- page_info = &page_info_tbl[rxq->head];
+ page_info = &rxo->page_info_tbl[rxq->head];
for (posted = 0; posted < MAX_RX_POST && !page_info->page; posted++) {
if (!pagep) {
pagep = be_alloc_pages(adapter->big_page_size);
if (unlikely(!pagep)) {
- drvr_stats(adapter)->be_ethrx_post_fail++;
+ rxo->stats.rx_post_fail++;
break;
}
page_dmaaddr = pci_map_page(adapter->pdev, pagep, 0,
@@ -1225,7 +1219,7 @@ static void be_post_rx_frags(struct be_adapter *adapter)
be_rxq_notify(adapter, rxq->id, posted);
} else if (atomic_read(&rxq->used) == 0) {
/* Let be_worker replenish when memory is available */
- adapter->rx_post_starved = true;
+ rxo->rx_post_starved = true;
}
}
@@ -1328,17 +1322,17 @@ static void be_eq_clean(struct be_adapter *adapter,
be_eq_notify(adapter, eq_obj->q.id, false, true, num);
}
-static void be_rx_q_clean(struct be_adapter *adapter)
+static void be_rx_q_clean(struct be_adapter *adapter, struct be_rx_obj *rxo)
{
struct be_rx_page_info *page_info;
- struct be_queue_info *rxq = &adapter->rx_obj.q;
- struct be_queue_info *rx_cq = &adapter->rx_obj.cq;
+ struct be_queue_info *rxq = &rxo->q;
+ struct be_queue_info *rx_cq = &rxo->cq;
struct be_eth_rx_compl *rxcp;
u16 tail;
/* First cleanup pending rx completions */
- while ((rxcp = be_rx_compl_get(adapter)) != NULL) {
- be_rx_compl_discard(adapter, rxcp);
+ while ((rxcp = be_rx_compl_get(rxo)) != NULL) {
+ be_rx_compl_discard(adapter, rxo, rxcp);
be_rx_compl_reset(rxcp);
be_cq_notify(adapter, rx_cq->id, true, 1);
}
@@ -1346,7 +1340,7 @@ static void be_rx_q_clean(struct be_adapter *adapter)
/* Then free posted rx buffer that were not used */
tail = (rxq->head + rxq->len - atomic_read(&rxq->used)) % rxq->len;
for (; atomic_read(&rxq->used) > 0; index_inc(&tail, rxq->len)) {
- page_info = get_rx_page_info(adapter, tail);
+ page_info = get_rx_page_info(adapter, rxo, tail);
put_page(page_info->page);
memset(page_info, 0, sizeof(*page_info));
}
@@ -1524,92 +1518,101 @@ tx_eq_free:
static void be_rx_queues_destroy(struct be_adapter *adapter)
{
struct be_queue_info *q;
-
- q = &adapter->rx_obj.q;
- if (q->created) {
- be_cmd_q_destroy(adapter, q, QTYPE_RXQ);
-
- /* After the rxq is invalidated, wait for a grace time
- * of 1ms for all dma to end and the flush compl to arrive
- */
- mdelay(1);
- be_rx_q_clean(adapter);
+ struct be_rx_obj *rxo;
+ int i;
+
+ for_all_rx_queues(adapter, rxo, i) {
+ q = &rxo->q;
+ if (q->created) {
+ be_cmd_q_destroy(adapter, q, QTYPE_RXQ);
+ /* After the rxq is invalidated, wait for a grace time
+ * of 1ms for all dma to end and the flush compl to
+ * arrive
+ */
+ mdelay(1);
+ be_rx_q_clean(adapter, rxo);
+ }
+ be_queue_free(adapter, q);
+
+ q = &rxo->cq;
+ if (q->created)
+ be_cmd_q_destroy(adapter, q, QTYPE_CQ);
+ be_queue_free(adapter, q);
+
+ /* Clear any residual events */
+ q = &rxo->rx_eq.q;
+ if (q->created) {
+ be_eq_clean(adapter, &rxo->rx_eq);
+ be_cmd_q_destroy(adapter, q, QTYPE_EQ);
+ }
+ be_queue_free(adapter, q);
}
- be_queue_free(adapter, q);
-
- q = &adapter->rx_obj.cq;
- if (q->created)
- be_cmd_q_destroy(adapter, q, QTYPE_CQ);
- be_queue_free(adapter, q);
-
- /* Clear any residual events */
- be_eq_clean(adapter, &adapter->rx_eq);
-
- q = &adapter->rx_eq.q;
- if (q->created)
- be_cmd_q_destroy(adapter, q, QTYPE_EQ);
- be_queue_free(adapter, q);
}
static int be_rx_queues_create(struct be_adapter *adapter)
{
struct be_queue_info *eq, *q, *cq;
- int rc;
+ struct be_rx_obj *rxo;
+ int rc, i;
adapter->big_page_size = (1 << get_order(rx_frag_size)) * PAGE_SIZE;
- adapter->rx_eq.max_eqd = BE_MAX_EQD;
- adapter->rx_eq.min_eqd = 0;
- adapter->rx_eq.cur_eqd = 0;
- adapter->rx_eq.enable_aic = true;
-
- /* Alloc Rx Event queue */
- eq = &adapter->rx_eq.q;
- rc = be_queue_alloc(adapter, eq, EVNT_Q_LEN,
- sizeof(struct be_eq_entry));
- if (rc)
- return rc;
-
- /* Ask BE to create Rx Event queue */
- rc = be_cmd_eq_create(adapter, eq, adapter->rx_eq.cur_eqd);
- if (rc)
- goto rx_eq_free;
-
- /* Alloc RX eth compl queue */
- cq = &adapter->rx_obj.cq;
- rc = be_queue_alloc(adapter, cq, RX_CQ_LEN,
- sizeof(struct be_eth_rx_compl));
- if (rc)
- goto rx_eq_destroy;
-
- /* Ask BE to create Rx eth compl queue */
- rc = be_cmd_cq_create(adapter, cq, eq, false, false, 3);
- if (rc)
- goto rx_cq_free;
-
- /* Alloc RX eth queue */
- q = &adapter->rx_obj.q;
- rc = be_queue_alloc(adapter, q, RX_Q_LEN, sizeof(struct be_eth_rx_d));
- if (rc)
- goto rx_cq_destroy;
-
- /* Ask BE to create Rx eth queue */
- rc = be_cmd_rxq_create(adapter, q, cq->id, rx_frag_size,
- BE_MAX_JUMBO_FRAME_SIZE, adapter->if_handle, false);
- if (rc)
- goto rx_q_free;
+ for_all_rx_queues(adapter, rxo, i) {
+ rxo->adapter = adapter;
+ rxo->rx_eq.max_eqd = BE_MAX_EQD;
+ rxo->rx_eq.enable_aic = true;
+
+ /* EQ */
+ eq = &rxo->rx_eq.q;
+ rc = be_queue_alloc(adapter, eq, EVNT_Q_LEN,
+ sizeof(struct be_eq_entry));
+ if (rc)
+ goto err;
+
+ rc = be_cmd_eq_create(adapter, eq, rxo->rx_eq.cur_eqd);
+ if (rc)
+ goto err;
+
+ /* CQ */
+ cq = &rxo->cq;
+ rc = be_queue_alloc(adapter, cq, RX_CQ_LEN,
+ sizeof(struct be_eth_rx_compl));
+ if (rc)
+ goto err;
+
+ rc = be_cmd_cq_create(adapter, cq, eq, false, false, 3);
+ if (rc)
+ goto err;
+
+ /* Rx Q */
+ q = &rxo->q;
+ rc = be_queue_alloc(adapter, q, RX_Q_LEN,
+ sizeof(struct be_eth_rx_d));
+ if (rc)
+ goto err;
+
+ rc = be_cmd_rxq_create(adapter, q, cq->id, rx_frag_size,
+ BE_MAX_JUMBO_FRAME_SIZE, adapter->if_handle,
+ (i > 0) ? 1 : 0/* rss enable */, &rxo->rss_id);
+ if (rc)
+ goto err;
+ }
+
+ if (be_multi_rxq(adapter)) {
+ u8 rsstable[MAX_RSS_QS];
+
+ for_all_rss_queues(adapter, rxo, i)
+ rsstable[i] = rxo->rss_id;
+
+ rc = be_cmd_rss_config(adapter, rsstable,
+ adapter->num_rx_qs - 1);
+ if (rc)
+ goto err;
+ }
return 0;
-rx_q_free:
- be_queue_free(adapter, q);
-rx_cq_destroy:
- be_cmd_q_destroy(adapter, cq, QTYPE_CQ);
-rx_cq_free:
- be_queue_free(adapter, cq);
-rx_eq_destroy:
- be_cmd_q_destroy(adapter, eq, QTYPE_EQ);
-rx_eq_free:
- be_queue_free(adapter, eq);
- return rc;
+err:
+ be_rx_queues_destroy(adapter);
+ return -1;
}
/* There are 8 evt ids per func. Retruns the evt id's bit number */
@@ -1621,24 +1624,31 @@ static inline int be_evt_bit_get(struct be_adapter *adapter, u32 eq_id)
static irqreturn_t be_intx(int irq, void *dev)
{
struct be_adapter *adapter = dev;
- int isr;
+ struct be_rx_obj *rxo;
+ int isr, i;
isr = ioread32(adapter->csr + CEV_ISR0_OFFSET +
(adapter->tx_eq.q.id/ 8) * CEV_ISR_SIZE);
if (!isr)
return IRQ_NONE;
- event_handle(adapter, &adapter->tx_eq);
- event_handle(adapter, &adapter->rx_eq);
+ if ((1 << be_evt_bit_get(adapter, adapter->tx_eq.q.id) & isr))
+ event_handle(adapter, &adapter->tx_eq);
+
+ for_all_rx_queues(adapter, rxo, i) {
+ if ((1 << be_evt_bit_get(adapter, rxo->rx_eq.q.id) & isr))
+ event_handle(adapter, &rxo->rx_eq);
+ }
return IRQ_HANDLED;
}
static irqreturn_t be_msix_rx(int irq, void *dev)
{
- struct be_adapter *adapter = dev;
+ struct be_rx_obj *rxo = dev;
+ struct be_adapter *adapter = rxo->adapter;
- event_handle(adapter, &adapter->rx_eq);
+ event_handle(adapter, &rxo->rx_eq);
return IRQ_HANDLED;
}
@@ -1652,14 +1662,14 @@ static irqreturn_t be_msix_tx_mcc(int irq, void *dev)
return IRQ_HANDLED;
}
-static inline bool do_gro(struct be_adapter *adapter,
+static inline bool do_gro(struct be_adapter *adapter, struct be_rx_obj *rxo,
struct be_eth_rx_compl *rxcp)
{
int err = AMAP_GET_BITS(struct amap_eth_rx_compl, err, rxcp);
int tcp_frame = AMAP_GET_BITS(struct amap_eth_rx_compl, tcpf, rxcp);
if (err)
- drvr_stats(adapter)->be_rxcp_err++;
+ rxo->stats.rxcp_err++;
return (tcp_frame && !err) ? true : false;
}
@@ -1667,29 +1677,29 @@ static inline bool do_gro(struct be_adapter *adapter,
int be_poll_rx(struct napi_struct *napi, int budget)
{
struct be_eq_obj *rx_eq = container_of(napi, struct be_eq_obj, napi);
- struct be_adapter *adapter =
- container_of(rx_eq, struct be_adapter, rx_eq);
- struct be_queue_info *rx_cq = &adapter->rx_obj.cq;
+ struct be_rx_obj *rxo = container_of(rx_eq, struct be_rx_obj, rx_eq);
+ struct be_adapter *adapter = rxo->adapter;
+ struct be_queue_info *rx_cq = &rxo->cq;
struct be_eth_rx_compl *rxcp;
u32 work_done;
- adapter->stats.drvr_stats.be_rx_polls++;
+ rxo->stats.rx_polls++;
for (work_done = 0; work_done < budget; work_done++) {
- rxcp = be_rx_compl_get(adapter);
+ rxcp = be_rx_compl_get(rxo);
if (!rxcp)
break;
- if (do_gro(adapter, rxcp))
- be_rx_compl_process_gro(adapter, rxcp);
+ if (do_gro(adapter, rxo, rxcp))
+ be_rx_compl_process_gro(adapter, rxo, rxcp);
else
- be_rx_compl_process(adapter, rxcp);
+ be_rx_compl_process(adapter, rxo, rxcp);
be_rx_compl_reset(rxcp);
}
/* Refill the queue */
- if (atomic_read(&adapter->rx_obj.q.used) < RX_FRAGS_REFILL_WM)
- be_post_rx_frags(adapter);
+ if (atomic_read(&rxo->q.used) < RX_FRAGS_REFILL_WM)
+ be_post_rx_frags(rxo);
/* All consumed */
if (work_done < budget) {
@@ -1743,8 +1753,8 @@ static int be_poll_tx_mcc(struct napi_struct *napi, int budget)
netif_wake_queue(adapter->netdev);
}
- drvr_stats(adapter)->be_tx_events++;
- drvr_stats(adapter)->be_tx_compl += tx_compl;
+ tx_stats(adapter)->be_tx_events++;
+ tx_stats(adapter)->be_tx_compl += tx_compl;
}
return 1;
@@ -1793,20 +1803,24 @@ static void be_worker(struct work_struct *work)
{
struct be_adapter *adapter =
container_of(work, struct be_adapter, work.work);
+ struct be_rx_obj *rxo;
+ int i;
if (!adapter->stats_ioctl_sent)
- be_cmd_get_stats(adapter, &adapter->stats.cmd);
-
- /* Set EQ delay */
- be_rx_eqd_update(adapter);
+ be_cmd_get_stats(adapter, &adapter->stats_cmd);
be_tx_rate_update(adapter);
- be_rx_rate_update(adapter);
- if (adapter->rx_post_starved) {
- adapter->rx_post_starved = false;
- be_post_rx_frags(adapter);
+ for_all_rx_queues(adapter, rxo, i) {
+ be_rx_rate_update(rxo);
+ be_rx_eqd_update(adapter, rxo);
+
+ if (rxo->rx_post_starved) {
+ rxo->rx_post_starved = false;
+ be_post_rx_frags(rxo);
+ }
}
+
if (!adapter->ue_detected)
be_detect_dump_ue(adapter);
@@ -1821,17 +1835,45 @@ static void be_msix_disable(struct be_adapter *adapter)
}
}
+static int be_num_rxqs_get(struct be_adapter *adapter)
+{
+ if (multi_rxq && (adapter->function_caps & BE_FUNCTION_CAPS_RSS) &&
+ !adapter->sriov_enabled && !(adapter->function_mode & 0x400)) {
+ return 1 + MAX_RSS_QS; /* one default non-RSS queue */
+ } else {
+ dev_warn(&adapter->pdev->dev,
+ "No support for multiple RX queues\n");
+ return 1;
+ }
+}
+
static void be_msix_enable(struct be_adapter *adapter)
{
+#define BE_MIN_MSIX_VECTORS (1 + 1) /* Rx + Tx */
int i, status;
- for (i = 0; i < BE_NUM_MSIX_VECTORS; i++)
+ adapter->num_rx_qs = be_num_rxqs_get(adapter);
+
+ for (i = 0; i < (adapter->num_rx_qs + 1); i++)
adapter->msix_entries[i].entry = i;
status = pci_enable_msix(adapter->pdev, adapter->msix_entries,
- BE_NUM_MSIX_VECTORS);
- if (status == 0)
- adapter->msix_enabled = true;
+ adapter->num_rx_qs + 1);
+ if (status == 0) {
+ goto done;
+ } else if (status >= BE_MIN_MSIX_VECTORS) {
+ if (pci_enable_msix(adapter->pdev, adapter->msix_entries,
+ status) == 0) {
+ adapter->num_rx_qs = status - 1;
+ dev_warn(&adapter->pdev->dev,
+ "Could alloc only %d MSIx vectors. "
+ "Using %d RX Qs\n", status, adapter->num_rx_qs);
+ goto done;
+ }
+ }
+ return;
+done:
+ adapter->msix_enabled = true;
}
static void be_sriov_enable(struct be_adapter *adapter)
@@ -1865,38 +1907,50 @@ static inline int be_msix_vec_get(struct be_adapter *adapter, u32 eq_id)
static int be_request_irq(struct be_adapter *adapter,
struct be_eq_obj *eq_obj,
- void *handler, char *desc)
+ void *handler, char *desc, void *context)
{
struct net_device *netdev = adapter->netdev;
int vec;
sprintf(eq_obj->desc, "%s-%s", netdev->name, desc);
vec = be_msix_vec_get(adapter, eq_obj->q.id);
- return request_irq(vec, handler, 0, eq_obj->desc, adapter);
+ return request_irq(vec, handler, 0, eq_obj->desc, context);
}
-static void be_free_irq(struct be_adapter *adapter, struct be_eq_obj *eq_obj)
+static void be_free_irq(struct be_adapter *adapter, struct be_eq_obj *eq_obj,
+ void *context)
{
int vec = be_msix_vec_get(adapter, eq_obj->q.id);
- free_irq(vec, adapter);
+ free_irq(vec, context);
}
static int be_msix_register(struct be_adapter *adapter)
{
- int status;
+ struct be_rx_obj *rxo;
+ int status, i;
+ char qname[10];
- status = be_request_irq(adapter, &adapter->tx_eq, be_msix_tx_mcc, "tx");
+ status = be_request_irq(adapter, &adapter->tx_eq, be_msix_tx_mcc, "tx",
+ adapter);
if (status)
goto err;
- status = be_request_irq(adapter, &adapter->rx_eq, be_msix_rx, "rx");
- if (status)
- goto free_tx_irq;
+ for_all_rx_queues(adapter, rxo, i) {
+ sprintf(qname, "rxq%d", i);
+ status = be_request_irq(adapter, &rxo->rx_eq, be_msix_rx,
+ qname, rxo);
+ if (status)
+ goto err_msix;
+ }
return 0;
-free_tx_irq:
- be_free_irq(adapter, &adapter->tx_eq);
+err_msix:
+ be_free_irq(adapter, &adapter->tx_eq, adapter);
+
+ for (i--, rxo = &adapter->rx_obj[i]; i >= 0; i--, rxo--)
+ be_free_irq(adapter, &rxo->rx_eq, rxo);
+
err:
dev_warn(&adapter->pdev->dev,
"MSIX Request IRQ failed - err %d\n", status);
@@ -1936,6 +1990,8 @@ done:
static void be_irq_unregister(struct be_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
+ struct be_rx_obj *rxo;
+ int i;
if (!adapter->isr_registered)
return;
@@ -1947,8 +2003,11 @@ static void be_irq_unregister(struct be_adapter *adapter)
}
/* MSIx */
- be_free_irq(adapter, &adapter->tx_eq);
- be_free_irq(adapter, &adapter->rx_eq);
+ be_free_irq(adapter, &adapter->tx_eq, adapter);
+
+ for_all_rx_queues(adapter, rxo, i)
+ be_free_irq(adapter, &rxo->rx_eq, rxo);
+
done:
adapter->isr_registered = false;
}
@@ -1956,9 +2015,9 @@ done:
static int be_close(struct net_device *netdev)
{
struct be_adapter *adapter = netdev_priv(netdev);
- struct be_eq_obj *rx_eq = &adapter->rx_eq;
+ struct be_rx_obj *rxo;
struct be_eq_obj *tx_eq = &adapter->tx_eq;
- int vec;
+ int vec, i;
cancel_delayed_work_sync(&adapter->work);
@@ -1973,14 +2032,19 @@ static int be_close(struct net_device *netdev)
if (adapter->msix_enabled) {
vec = be_msix_vec_get(adapter, tx_eq->q.id);
synchronize_irq(vec);
- vec = be_msix_vec_get(adapter, rx_eq->q.id);
- synchronize_irq(vec);
+
+ for_all_rx_queues(adapter, rxo, i) {
+ vec = be_msix_vec_get(adapter, rxo->rx_eq.q.id);
+ synchronize_irq(vec);
+ }
} else {
synchronize_irq(netdev->irq);
}
be_irq_unregister(adapter);
- napi_disable(&rx_eq->napi);
+ for_all_rx_queues(adapter, rxo, i)
+ napi_disable(&rxo->rx_eq.napi);
+
napi_disable(&tx_eq->napi);
/* Wait for all pending tx completions to arrive so that
@@ -1994,17 +2058,17 @@ static int be_close(struct net_device *netdev)
static int be_open(struct net_device *netdev)
{
struct be_adapter *adapter = netdev_priv(netdev);
- struct be_eq_obj *rx_eq = &adapter->rx_eq;
struct be_eq_obj *tx_eq = &adapter->tx_eq;
+ struct be_rx_obj *rxo;
bool link_up;
- int status;
+ int status, i;
u8 mac_speed;
u16 link_speed;
- /* First time posting */
- be_post_rx_frags(adapter);
-
- napi_enable(&rx_eq->napi);
+ for_all_rx_queues(adapter, rxo, i) {
+ be_post_rx_frags(rxo);
+ napi_enable(&rxo->rx_eq.napi);
+ }
napi_enable(&tx_eq->napi);
be_irq_register(adapter);
@@ -2012,12 +2076,12 @@ static int be_open(struct net_device *netdev)
be_intr_set(adapter, true);
/* The evt queues are created in unarmed state; arm them */
- be_eq_notify(adapter, rx_eq->q.id, true, false, 0);
+ for_all_rx_queues(adapter, rxo, i) {
+ be_eq_notify(adapter, rxo->rx_eq.q.id, true, false, 0);
+ be_cq_notify(adapter, rxo->cq.id, true, 0);
+ }
be_eq_notify(adapter, tx_eq->q.id, true, false, 0);
- /* Rx compl queue may be in unarmed state; rearm it */
- be_cq_notify(adapter, adapter->rx_obj.cq.id, true, 0);
-
/* Now that interrupts are on we can process async mcc */
be_async_mcc_enable(adapter);
@@ -2084,6 +2148,47 @@ static int be_setup_wol(struct be_adapter *adapter, bool enable)
return status;
}
+/*
+ * Generate a seed MAC address from the PF MAC Address using jhash.
+ * MAC Address for VFs are assigned incrementally starting from the seed.
+ * These addresses are programmed in the ASIC by the PF and the VF driver
+ * queries for the MAC address during its probe.
+ */
+static inline int be_vf_eth_addr_config(struct be_adapter *adapter)
+{
+ u32 vf = 0;
+ int status = 0;
+ u8 mac[ETH_ALEN];
+
+ be_vf_eth_addr_generate(adapter, mac);
+
+ for (vf = 0; vf < num_vfs; vf++) {
+ status = be_cmd_pmac_add(adapter, mac,
+ adapter->vf_cfg[vf].vf_if_handle,
+ &adapter->vf_cfg[vf].vf_pmac_id);
+ if (status)
+ dev_err(&adapter->pdev->dev,
+ "Mac address add failed for VF %d\n", vf);
+ else
+ memcpy(adapter->vf_cfg[vf].vf_mac_addr, mac, ETH_ALEN);
+
+ mac[5] += 1;
+ }
+ return status;
+}
+
+static inline void be_vf_eth_addr_rem(struct be_adapter *adapter)
+{
+ u32 vf;
+
+ for (vf = 0; vf < num_vfs; vf++) {
+ if (adapter->vf_cfg[vf].vf_pmac_id != BE_INVALID_PMAC_ID)
+ be_cmd_pmac_del(adapter,
+ adapter->vf_cfg[vf].vf_if_handle,
+ adapter->vf_cfg[vf].vf_pmac_id);
+ }
+}
+
static int be_setup(struct be_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
@@ -2098,6 +2203,11 @@ static int be_setup(struct be_adapter *adapter)
BE_IF_FLAGS_PROMISCUOUS |
BE_IF_FLAGS_PASS_L3L4_ERRORS;
en_flags |= BE_IF_FLAGS_PASS_L3L4_ERRORS;
+
+ if (be_multi_rxq(adapter)) {
+ cap_flags |= BE_IF_FLAGS_RSS;
+ en_flags |= BE_IF_FLAGS_RSS;
+ }
}
status = be_cmd_if_create(adapter, cap_flags, en_flags,
@@ -2143,10 +2253,20 @@ static int be_setup(struct be_adapter *adapter)
if (status != 0)
goto rx_qs_destroy;
+ if (be_physfn(adapter)) {
+ status = be_vf_eth_addr_config(adapter);
+ if (status)
+ goto mcc_q_destroy;
+ }
+
adapter->link_speed = -1;
return 0;
+mcc_q_destroy:
+ if (be_physfn(adapter))
+ be_vf_eth_addr_rem(adapter);
+ be_mcc_queues_destroy(adapter);
rx_qs_destroy:
be_rx_queues_destroy(adapter);
tx_qs_destroy:
@@ -2163,6 +2283,9 @@ do_none:
static int be_clear(struct be_adapter *adapter)
{
+ if (be_physfn(adapter))
+ be_vf_eth_addr_rem(adapter);
+
be_mcc_queues_destroy(adapter);
be_rx_queues_destroy(adapter);
be_tx_queues_destroy(adapter);
@@ -2390,7 +2513,6 @@ static struct net_device_ops be_netdev_ops = {
.ndo_open = be_open,
.ndo_stop = be_close,
.ndo_start_xmit = be_xmit,
- .ndo_get_stats = be_get_stats,
.ndo_set_rx_mode = be_set_multicast_list,
.ndo_set_mac_address = be_mac_addr_set,
.ndo_change_mtu = be_change_mtu,
@@ -2407,6 +2529,8 @@ static struct net_device_ops be_netdev_ops = {
static void be_netdev_init(struct net_device *netdev)
{
struct be_adapter *adapter = netdev_priv(netdev);
+ struct be_rx_obj *rxo;
+ int i;
netdev->features |= NETIF_F_SG | NETIF_F_HW_VLAN_RX | NETIF_F_TSO |
NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER | NETIF_F_HW_CSUM |
@@ -2428,8 +2552,10 @@ static void be_netdev_init(struct net_device *netdev)
SET_ETHTOOL_OPS(netdev, &be_ethtool_ops);
- netif_napi_add(netdev, &adapter->rx_eq.napi, be_poll_rx,
- BE_NAPI_WEIGHT);
+ for_all_rx_queues(adapter, rxo, i)
+ netif_napi_add(netdev, &rxo->rx_eq.napi, be_poll_rx,
+ BE_NAPI_WEIGHT);
+
netif_napi_add(netdev, &adapter->tx_eq.napi, be_poll_tx_mcc,
BE_NAPI_WEIGHT);
@@ -2563,8 +2689,7 @@ done:
static void be_stats_cleanup(struct be_adapter *adapter)
{
- struct be_stats_obj *stats = &adapter->stats;
- struct be_dma_mem *cmd = &stats->cmd;
+ struct be_dma_mem *cmd = &adapter->stats_cmd;
if (cmd->va)
pci_free_consistent(adapter->pdev, cmd->size,
@@ -2573,8 +2698,7 @@ static void be_stats_cleanup(struct be_adapter *adapter)
static int be_stats_init(struct be_adapter *adapter)
{
- struct be_stats_obj *stats = &adapter->stats;
- struct be_dma_mem *cmd = &stats->cmd;
+ struct be_dma_mem *cmd = &adapter->stats_cmd;
cmd->size = sizeof(struct be_cmd_req_get_stats);
cmd->va = pci_alloc_consistent(adapter->pdev, cmd->size, &cmd->dma);
@@ -2619,8 +2743,8 @@ static int be_get_config(struct be_adapter *adapter)
if (status)
return status;
- status = be_cmd_query_fw_cfg(adapter,
- &adapter->port_num, &adapter->function_mode);
+ status = be_cmd_query_fw_cfg(adapter, &adapter->port_num,
+ &adapter->function_mode, &adapter->function_caps);
if (status)
return status;
@@ -2655,7 +2779,6 @@ static int __devinit be_probe(struct pci_dev *pdev,
struct be_adapter *adapter;
struct net_device *netdev;
-
status = pci_enable_device(pdev);
if (status)
goto do_none;
@@ -2688,11 +2811,8 @@ static int __devinit be_probe(struct pci_dev *pdev,
adapter->pdev = pdev;
pci_set_drvdata(pdev, adapter);
adapter->netdev = netdev;
- be_netdev_init(netdev);
SET_NETDEV_DEV(netdev, &pdev->dev);
- be_msix_enable(adapter);
-
status = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
if (!status) {
netdev->features |= NETIF_F_HIGHDMA;
@@ -2736,12 +2856,15 @@ static int __devinit be_probe(struct pci_dev *pdev,
if (status)
goto stats_clean;
+ be_msix_enable(adapter);
+
INIT_DELAYED_WORK(&adapter->work, be_worker);
status = be_setup(adapter);
if (status)
- goto stats_clean;
+ goto msix_disable;
+ be_netdev_init(netdev);
status = register_netdev(netdev);
if (status != 0)
goto unsetup;
@@ -2751,12 +2874,13 @@ static int __devinit be_probe(struct pci_dev *pdev,
unsetup:
be_clear(adapter);
+msix_disable:
+ be_msix_disable(adapter);
stats_clean:
be_stats_cleanup(adapter);
ctrl_clean:
be_ctrl_cleanup(adapter);
free_netdev:
- be_msix_disable(adapter);
be_sriov_disable(adapter);
free_netdev(adapter->netdev);
pci_set_drvdata(pdev, NULL);
diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c
index 012613fde3f4..f7233191162b 100644
--- a/drivers/net/bfin_mac.c
+++ b/drivers/net/bfin_mac.c
@@ -38,6 +38,7 @@
#include <asm/blackfin.h>
#include <asm/cacheflush.h>
#include <asm/portmux.h>
+#include <mach/pll.h>
#include "bfin_mac.h"
@@ -803,15 +804,14 @@ static void bfin_dump_hwtamp(char *s, ktime_t *hw, ktime_t *ts, struct timecompa
static void bfin_tx_hwtstamp(struct net_device *netdev, struct sk_buff *skb)
{
struct bfin_mac_local *lp = netdev_priv(netdev);
- union skb_shared_tx *shtx = skb_tx(skb);
- if (shtx->hardware) {
+ if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) {
int timeout_cnt = MAX_TIMEOUT_CNT;
/* When doing time stamping, keep the connection to the socket
* a while longer
*/
- shtx->in_progress = 1;
+ skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
/*
* The timestamping is done at the EMAC module's MII/RMII interface
@@ -991,7 +991,6 @@ static int bfin_mac_hard_start_xmit(struct sk_buff *skb,
struct bfin_mac_local *lp = netdev_priv(dev);
u16 *data;
u32 data_align = (unsigned long)(skb->data) & 0x3;
- union skb_shared_tx *shtx = skb_tx(skb);
current_tx_ptr->skb = skb;
@@ -1005,7 +1004,7 @@ static int bfin_mac_hard_start_xmit(struct sk_buff *skb,
* of this field are the length of the packet payload in bytes and the higher
* 4 bits are the timestamping enable field.
*/
- if (shtx->hardware)
+ if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)
*data |= 0x1000;
current_tx_ptr->desc_a.start_addr = (u32)data;
@@ -1015,7 +1014,7 @@ static int bfin_mac_hard_start_xmit(struct sk_buff *skb,
} else {
*((u16 *)(current_tx_ptr->packet)) = (u16)(skb->len);
/* enable timestamping for the sent packet */
- if (shtx->hardware)
+ if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)
*((u16 *)(current_tx_ptr->packet)) |= 0x1000;
memcpy((u8 *)(current_tx_ptr->packet + 2), skb->data,
skb->len);
diff --git a/drivers/net/bmac.c b/drivers/net/bmac.c
index 959add2410bf..a1b8c8b8010b 100644
--- a/drivers/net/bmac.c
+++ b/drivers/net/bmac.c
@@ -1233,15 +1233,8 @@ static void bmac_reset_and_enable(struct net_device *dev)
}
spin_unlock_irqrestore(&bp->lock, flags);
}
-static void bmac_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
-{
- struct bmac_data *bp = netdev_priv(dev);
- strcpy(info->driver, "bmac");
- strcpy(info->bus_info, dev_name(&bp->mdev->ofdev.dev));
-}
static const struct ethtool_ops bmac_ethtool_ops = {
- .get_drvinfo = bmac_get_drvinfo,
.get_link = ethtool_op_get_link,
};
@@ -1588,7 +1581,7 @@ bmac_proc_info(char *buffer, char **start, off_t offset, int length)
int i;
if (bmac_devs == NULL)
- return (-ENOSYS);
+ return -ENOSYS;
len += sprintf(buffer, "BMAC counters & registers\n");
diff --git a/drivers/net/bna/Makefile b/drivers/net/bna/Makefile
new file mode 100644
index 000000000000..a5d604de7fea
--- /dev/null
+++ b/drivers/net/bna/Makefile
@@ -0,0 +1,11 @@
+#
+# Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+# All rights reserved.
+#
+
+obj-$(CONFIG_BNA) += bna.o
+
+bna-objs := bnad.o bnad_ethtool.o bna_ctrl.o bna_txrx.o
+bna-objs += bfa_ioc.o bfa_ioc_ct.o bfa_cee.o cna_fwimg.o
+
+EXTRA_CFLAGS := -Idrivers/net/bna
diff --git a/drivers/net/bna/bfa_cee.c b/drivers/net/bna/bfa_cee.c
new file mode 100644
index 000000000000..f7b789a3b217
--- /dev/null
+++ b/drivers/net/bna/bfa_cee.c
@@ -0,0 +1,291 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+
+#include "bfa_defs_cna.h"
+#include "cna.h"
+#include "bfa_cee.h"
+#include "bfi_cna.h"
+#include "bfa_ioc.h"
+
+#define bfa_ioc_portid(__ioc) ((__ioc)->port_id)
+#define bfa_lpuid(__arg) bfa_ioc_portid(&(__arg)->ioc)
+
+static void bfa_cee_format_lldp_cfg(struct bfa_cee_lldp_cfg *lldp_cfg);
+static void bfa_cee_format_cee_cfg(void *buffer);
+
+static void
+bfa_cee_format_cee_cfg(void *buffer)
+{
+ struct bfa_cee_attr *cee_cfg = buffer;
+ bfa_cee_format_lldp_cfg(&cee_cfg->lldp_remote);
+}
+
+static void
+bfa_cee_stats_swap(struct bfa_cee_stats *stats)
+{
+ u32 *buffer = (u32 *)stats;
+ int i;
+
+ for (i = 0; i < (sizeof(struct bfa_cee_stats) / sizeof(u32));
+ i++) {
+ buffer[i] = ntohl(buffer[i]);
+ }
+}
+
+static void
+bfa_cee_format_lldp_cfg(struct bfa_cee_lldp_cfg *lldp_cfg)
+{
+ lldp_cfg->time_to_live =
+ ntohs(lldp_cfg->time_to_live);
+ lldp_cfg->enabled_system_cap =
+ ntohs(lldp_cfg->enabled_system_cap);
+}
+
+/**
+ * bfa_cee_attr_meminfo()
+ *
+ * @brief Returns the size of the DMA memory needed by CEE attributes
+ *
+ * @param[in] void
+ *
+ * @return Size of DMA region
+ */
+static u32
+bfa_cee_attr_meminfo(void)
+{
+ return roundup(sizeof(struct bfa_cee_attr), BFA_DMA_ALIGN_SZ);
+}
+/**
+ * bfa_cee_stats_meminfo()
+ *
+ * @brief Returns the size of the DMA memory needed by CEE stats
+ *
+ * @param[in] void
+ *
+ * @return Size of DMA region
+ */
+static u32
+bfa_cee_stats_meminfo(void)
+{
+ return roundup(sizeof(struct bfa_cee_stats), BFA_DMA_ALIGN_SZ);
+}
+
+/**
+ * bfa_cee_get_attr_isr()
+ *
+ * @brief CEE ISR for get-attributes responses from f/w
+ *
+ * @param[in] cee - Pointer to the CEE module
+ * status - Return status from the f/w
+ *
+ * @return void
+ */
+static void
+bfa_cee_get_attr_isr(struct bfa_cee *cee, enum bfa_status status)
+{
+ cee->get_attr_status = status;
+ if (status == BFA_STATUS_OK) {
+ memcpy(cee->attr, cee->attr_dma.kva,
+ sizeof(struct bfa_cee_attr));
+ bfa_cee_format_cee_cfg(cee->attr);
+ }
+ cee->get_attr_pending = false;
+ if (cee->cbfn.get_attr_cbfn)
+ cee->cbfn.get_attr_cbfn(cee->cbfn.get_attr_cbarg, status);
+}
+
+/**
+ * bfa_cee_get_attr_isr()
+ *
+ * @brief CEE ISR for get-stats responses from f/w
+ *
+ * @param[in] cee - Pointer to the CEE module
+ * status - Return status from the f/w
+ *
+ * @return void
+ */
+static void
+bfa_cee_get_stats_isr(struct bfa_cee *cee, enum bfa_status status)
+{
+ cee->get_stats_status = status;
+ if (status == BFA_STATUS_OK) {
+ memcpy(cee->stats, cee->stats_dma.kva,
+ sizeof(struct bfa_cee_stats));
+ bfa_cee_stats_swap(cee->stats);
+ }
+ cee->get_stats_pending = false;
+ if (cee->cbfn.get_stats_cbfn)
+ cee->cbfn.get_stats_cbfn(cee->cbfn.get_stats_cbarg, status);
+}
+
+/**
+ * bfa_cee_get_attr_isr()
+ *
+ * @brief CEE ISR for reset-stats responses from f/w
+ *
+ * @param[in] cee - Pointer to the CEE module
+ * status - Return status from the f/w
+ *
+ * @return void
+ */
+static void
+bfa_cee_reset_stats_isr(struct bfa_cee *cee, enum bfa_status status)
+{
+ cee->reset_stats_status = status;
+ cee->reset_stats_pending = false;
+ if (cee->cbfn.reset_stats_cbfn)
+ cee->cbfn.reset_stats_cbfn(cee->cbfn.reset_stats_cbarg, status);
+}
+/**
+ * bfa_nw_cee_meminfo()
+ *
+ * @brief Returns the size of the DMA memory needed by CEE module
+ *
+ * @param[in] void
+ *
+ * @return Size of DMA region
+ */
+u32
+bfa_nw_cee_meminfo(void)
+{
+ return bfa_cee_attr_meminfo() + bfa_cee_stats_meminfo();
+}
+
+/**
+ * bfa_nw_cee_mem_claim()
+ *
+ * @brief Initialized CEE DMA Memory
+ *
+ * @param[in] cee CEE module pointer
+ * dma_kva Kernel Virtual Address of CEE DMA Memory
+ * dma_pa Physical Address of CEE DMA Memory
+ *
+ * @return void
+ */
+void
+bfa_nw_cee_mem_claim(struct bfa_cee *cee, u8 *dma_kva, u64 dma_pa)
+{
+ cee->attr_dma.kva = dma_kva;
+ cee->attr_dma.pa = dma_pa;
+ cee->stats_dma.kva = dma_kva + bfa_cee_attr_meminfo();
+ cee->stats_dma.pa = dma_pa + bfa_cee_attr_meminfo();
+ cee->attr = (struct bfa_cee_attr *) dma_kva;
+ cee->stats = (struct bfa_cee_stats *)
+ (dma_kva + bfa_cee_attr_meminfo());
+}
+
+/**
+ * bfa_cee_isrs()
+ *
+ * @brief Handles Mail-box interrupts for CEE module.
+ *
+ * @param[in] Pointer to the CEE module data structure.
+ *
+ * @return void
+ */
+
+static void
+bfa_cee_isr(void *cbarg, struct bfi_mbmsg *m)
+{
+ union bfi_cee_i2h_msg_u *msg;
+ struct bfi_cee_get_rsp *get_rsp;
+ struct bfa_cee *cee = (struct bfa_cee *) cbarg;
+ msg = (union bfi_cee_i2h_msg_u *) m;
+ get_rsp = (struct bfi_cee_get_rsp *) m;
+ switch (msg->mh.msg_id) {
+ case BFI_CEE_I2H_GET_CFG_RSP:
+ bfa_cee_get_attr_isr(cee, get_rsp->cmd_status);
+ break;
+ case BFI_CEE_I2H_GET_STATS_RSP:
+ bfa_cee_get_stats_isr(cee, get_rsp->cmd_status);
+ break;
+ case BFI_CEE_I2H_RESET_STATS_RSP:
+ bfa_cee_reset_stats_isr(cee, get_rsp->cmd_status);
+ break;
+ default:
+ BUG_ON(1);
+ }
+}
+
+/**
+ * bfa_cee_hbfail()
+ *
+ * @brief CEE module heart-beat failure handler.
+ *
+ * @param[in] Pointer to the CEE module data structure.
+ *
+ * @return void
+ */
+
+static void
+bfa_cee_hbfail(void *arg)
+{
+ struct bfa_cee *cee;
+ cee = (struct bfa_cee *) arg;
+
+ if (cee->get_attr_pending == true) {
+ cee->get_attr_status = BFA_STATUS_FAILED;
+ cee->get_attr_pending = false;
+ if (cee->cbfn.get_attr_cbfn) {
+ cee->cbfn.get_attr_cbfn(cee->cbfn.get_attr_cbarg,
+ BFA_STATUS_FAILED);
+ }
+ }
+ if (cee->get_stats_pending == true) {
+ cee->get_stats_status = BFA_STATUS_FAILED;
+ cee->get_stats_pending = false;
+ if (cee->cbfn.get_stats_cbfn) {
+ cee->cbfn.get_stats_cbfn(cee->cbfn.get_stats_cbarg,
+ BFA_STATUS_FAILED);
+ }
+ }
+ if (cee->reset_stats_pending == true) {
+ cee->reset_stats_status = BFA_STATUS_FAILED;
+ cee->reset_stats_pending = false;
+ if (cee->cbfn.reset_stats_cbfn) {
+ cee->cbfn.reset_stats_cbfn(cee->cbfn.reset_stats_cbarg,
+ BFA_STATUS_FAILED);
+ }
+ }
+}
+
+/**
+ * bfa_nw_cee_attach()
+ *
+ * @brief CEE module-attach API
+ *
+ * @param[in] cee - Pointer to the CEE module data structure
+ * ioc - Pointer to the ioc module data structure
+ * dev - Pointer to the device driver module data structure
+ * The device driver specific mbox ISR functions have
+ * this pointer as one of the parameters.
+ *
+ * @return void
+ */
+void
+bfa_nw_cee_attach(struct bfa_cee *cee, struct bfa_ioc *ioc,
+ void *dev)
+{
+ BUG_ON(!(cee != NULL));
+ cee->dev = dev;
+ cee->ioc = ioc;
+
+ bfa_nw_ioc_mbox_regisr(cee->ioc, BFI_MC_CEE, bfa_cee_isr, cee);
+ bfa_ioc_hbfail_init(&cee->hbfail, bfa_cee_hbfail, cee);
+ bfa_nw_ioc_hbfail_register(cee->ioc, &cee->hbfail);
+}
diff --git a/drivers/net/bna/bfa_cee.h b/drivers/net/bna/bfa_cee.h
new file mode 100644
index 000000000000..20543d15b64f
--- /dev/null
+++ b/drivers/net/bna/bfa_cee.h
@@ -0,0 +1,64 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+
+#ifndef __BFA_CEE_H__
+#define __BFA_CEE_H__
+
+#include "bfa_defs_cna.h"
+#include "bfa_ioc.h"
+
+typedef void (*bfa_cee_get_attr_cbfn_t) (void *dev, enum bfa_status status);
+typedef void (*bfa_cee_get_stats_cbfn_t) (void *dev, enum bfa_status status);
+typedef void (*bfa_cee_reset_stats_cbfn_t) (void *dev, enum bfa_status status);
+typedef void (*bfa_cee_hbfail_cbfn_t) (void *dev, enum bfa_status status);
+
+struct bfa_cee_cbfn {
+ bfa_cee_get_attr_cbfn_t get_attr_cbfn;
+ void *get_attr_cbarg;
+ bfa_cee_get_stats_cbfn_t get_stats_cbfn;
+ void *get_stats_cbarg;
+ bfa_cee_reset_stats_cbfn_t reset_stats_cbfn;
+ void *reset_stats_cbarg;
+};
+
+struct bfa_cee {
+ void *dev;
+ bool get_attr_pending;
+ bool get_stats_pending;
+ bool reset_stats_pending;
+ enum bfa_status get_attr_status;
+ enum bfa_status get_stats_status;
+ enum bfa_status reset_stats_status;
+ struct bfa_cee_cbfn cbfn;
+ struct bfa_ioc_hbfail_notify hbfail;
+ struct bfa_cee_attr *attr;
+ struct bfa_cee_stats *stats;
+ struct bfa_dma attr_dma;
+ struct bfa_dma stats_dma;
+ struct bfa_ioc *ioc;
+ struct bfa_mbox_cmd get_cfg_mb;
+ struct bfa_mbox_cmd get_stats_mb;
+ struct bfa_mbox_cmd reset_stats_mb;
+};
+
+u32 bfa_nw_cee_meminfo(void);
+void bfa_nw_cee_mem_claim(struct bfa_cee *cee, u8 *dma_kva,
+ u64 dma_pa);
+void bfa_nw_cee_attach(struct bfa_cee *cee, struct bfa_ioc *ioc, void *dev);
+
+#endif /* __BFA_CEE_H__ */
diff --git a/drivers/net/bna/bfa_defs.h b/drivers/net/bna/bfa_defs.h
new file mode 100644
index 000000000000..29c1b8de2c2d
--- /dev/null
+++ b/drivers/net/bna/bfa_defs.h
@@ -0,0 +1,243 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+
+#ifndef __BFA_DEFS_H__
+#define __BFA_DEFS_H__
+
+#include "cna.h"
+#include "bfa_defs_status.h"
+#include "bfa_defs_mfg_comm.h"
+
+#define BFA_STRING_32 32
+#define BFA_VERSION_LEN 64
+
+/**
+ * ---------------------- adapter definitions ------------
+ */
+
+/**
+ * BFA adapter level attributes.
+ */
+enum {
+ BFA_ADAPTER_SERIAL_NUM_LEN = STRSZ(BFA_MFG_SERIALNUM_SIZE),
+ /*
+ *!< adapter serial num length
+ */
+ BFA_ADAPTER_MODEL_NAME_LEN = 16, /*!< model name length */
+ BFA_ADAPTER_MODEL_DESCR_LEN = 128, /*!< model description length */
+ BFA_ADAPTER_MFG_NAME_LEN = 8, /*!< manufacturer name length */
+ BFA_ADAPTER_SYM_NAME_LEN = 64, /*!< adapter symbolic name length */
+ BFA_ADAPTER_OS_TYPE_LEN = 64, /*!< adapter os type length */
+};
+
+struct bfa_adapter_attr {
+ char manufacturer[BFA_ADAPTER_MFG_NAME_LEN];
+ char serial_num[BFA_ADAPTER_SERIAL_NUM_LEN];
+ u32 card_type;
+ char model[BFA_ADAPTER_MODEL_NAME_LEN];
+ char model_descr[BFA_ADAPTER_MODEL_DESCR_LEN];
+ u64 pwwn;
+ char node_symname[FC_SYMNAME_MAX];
+ char hw_ver[BFA_VERSION_LEN];
+ char fw_ver[BFA_VERSION_LEN];
+ char optrom_ver[BFA_VERSION_LEN];
+ char os_type[BFA_ADAPTER_OS_TYPE_LEN];
+ struct bfa_mfg_vpd vpd;
+ struct mac mac;
+
+ u8 nports;
+ u8 max_speed;
+ u8 prototype;
+ char asic_rev;
+
+ u8 pcie_gen;
+ u8 pcie_lanes_orig;
+ u8 pcie_lanes;
+ u8 cna_capable;
+
+ u8 is_mezz;
+ u8 trunk_capable;
+};
+
+/**
+ * ---------------------- IOC definitions ------------
+ */
+
+enum {
+ BFA_IOC_DRIVER_LEN = 16,
+ BFA_IOC_CHIP_REV_LEN = 8,
+};
+
+/**
+ * Driver and firmware versions.
+ */
+struct bfa_ioc_driver_attr {
+ char driver[BFA_IOC_DRIVER_LEN]; /*!< driver name */
+ char driver_ver[BFA_VERSION_LEN]; /*!< driver version */
+ char fw_ver[BFA_VERSION_LEN]; /*!< firmware version */
+ char bios_ver[BFA_VERSION_LEN]; /*!< bios version */
+ char efi_ver[BFA_VERSION_LEN]; /*!< EFI version */
+ char ob_ver[BFA_VERSION_LEN]; /*!< openboot version */
+};
+
+/**
+ * IOC PCI device attributes
+ */
+struct bfa_ioc_pci_attr {
+ u16 vendor_id; /*!< PCI vendor ID */
+ u16 device_id; /*!< PCI device ID */
+ u16 ssid; /*!< subsystem ID */
+ u16 ssvid; /*!< subsystem vendor ID */
+ u32 pcifn; /*!< PCI device function */
+ u32 rsvd; /* padding */
+ char chip_rev[BFA_IOC_CHIP_REV_LEN]; /*!< chip revision */
+};
+
+/**
+ * IOC states
+ */
+enum bfa_ioc_state {
+ BFA_IOC_RESET = 1, /*!< IOC is in reset state */
+ BFA_IOC_SEMWAIT = 2, /*!< Waiting for IOC h/w semaphore */
+ BFA_IOC_HWINIT = 3, /*!< IOC h/w is being initialized */
+ BFA_IOC_GETATTR = 4, /*!< IOC is being configured */
+ BFA_IOC_OPERATIONAL = 5, /*!< IOC is operational */
+ BFA_IOC_INITFAIL = 6, /*!< IOC hardware failure */
+ BFA_IOC_HBFAIL = 7, /*!< IOC heart-beat failure */
+ BFA_IOC_DISABLING = 8, /*!< IOC is being disabled */
+ BFA_IOC_DISABLED = 9, /*!< IOC is disabled */
+ BFA_IOC_FWMISMATCH = 10, /*!< IOC f/w different from drivers */
+};
+
+/**
+ * IOC firmware stats
+ */
+struct bfa_fw_ioc_stats {
+ u32 enable_reqs;
+ u32 disable_reqs;
+ u32 get_attr_reqs;
+ u32 dbg_sync;
+ u32 dbg_dump;
+ u32 unknown_reqs;
+};
+
+/**
+ * IOC driver stats
+ */
+struct bfa_ioc_drv_stats {
+ u32 ioc_isrs;
+ u32 ioc_enables;
+ u32 ioc_disables;
+ u32 ioc_hbfails;
+ u32 ioc_boots;
+ u32 stats_tmos;
+ u32 hb_count;
+ u32 disable_reqs;
+ u32 enable_reqs;
+ u32 disable_replies;
+ u32 enable_replies;
+};
+
+/**
+ * IOC statistics
+ */
+struct bfa_ioc_stats {
+ struct bfa_ioc_drv_stats drv_stats; /*!< driver IOC stats */
+ struct bfa_fw_ioc_stats fw_stats; /*!< firmware IOC stats */
+};
+
+enum bfa_ioc_type {
+ BFA_IOC_TYPE_FC = 1,
+ BFA_IOC_TYPE_FCoE = 2,
+ BFA_IOC_TYPE_LL = 3,
+};
+
+/**
+ * IOC attributes returned in queries
+ */
+struct bfa_ioc_attr {
+ enum bfa_ioc_type ioc_type;
+ enum bfa_ioc_state state; /*!< IOC state */
+ struct bfa_adapter_attr adapter_attr; /*!< HBA attributes */
+ struct bfa_ioc_driver_attr driver_attr; /*!< driver attr */
+ struct bfa_ioc_pci_attr pci_attr;
+ u8 port_id; /*!< port number */
+ u8 rsvd[7]; /*!< 64bit align */
+};
+
+/**
+ * ---------------------- mfg definitions ------------
+ */
+
+/**
+ * Checksum size
+ */
+#define BFA_MFG_CHKSUM_SIZE 16
+
+#define BFA_MFG_PARTNUM_SIZE 14
+#define BFA_MFG_SUPPLIER_ID_SIZE 10
+#define BFA_MFG_SUPPLIER_PARTNUM_SIZE 20
+#define BFA_MFG_SUPPLIER_SERIALNUM_SIZE 20
+#define BFA_MFG_SUPPLIER_REVISION_SIZE 4
+
+#pragma pack(1)
+
+/**
+ * @brief BFA adapter manufacturing block definition.
+ *
+ * All numerical fields are in big-endian format.
+ */
+struct bfa_mfg_block {
+ u8 version; /*!< manufacturing block version */
+ u8 mfg_sig[3]; /*!< characters 'M', 'F', 'G' */
+ u16 mfgsize; /*!< mfg block size */
+ u16 u16_chksum; /*!< old u16 checksum */
+ char brcd_serialnum[STRSZ(BFA_MFG_SERIALNUM_SIZE)];
+ char brcd_partnum[STRSZ(BFA_MFG_PARTNUM_SIZE)];
+ u8 mfg_day; /*!< manufacturing day */
+ u8 mfg_month; /*!< manufacturing month */
+ u16 mfg_year; /*!< manufacturing year */
+ u64 mfg_wwn; /*!< wwn base for this adapter */
+ u8 num_wwn; /*!< number of wwns assigned */
+ u8 mfg_speeds; /*!< speeds allowed for this adapter */
+ u8 rsv[2];
+ char supplier_id[STRSZ(BFA_MFG_SUPPLIER_ID_SIZE)];
+ char supplier_partnum[STRSZ(BFA_MFG_SUPPLIER_PARTNUM_SIZE)];
+ char
+ supplier_serialnum[STRSZ(BFA_MFG_SUPPLIER_SERIALNUM_SIZE)];
+ char
+ supplier_revision[STRSZ(BFA_MFG_SUPPLIER_REVISION_SIZE)];
+ mac_t mfg_mac; /*!< mac address */
+ u8 num_mac; /*!< number of mac addresses */
+ u8 rsv2;
+ u32 mfg_type; /*!< card type */
+ u8 rsv3[108];
+ u8 md5_chksum[BFA_MFG_CHKSUM_SIZE]; /*!< md5 checksum */
+};
+
+#pragma pack()
+
+/**
+ * ---------------------- pci definitions ------------
+ */
+
+#define bfa_asic_id_ct(devid) \
+ ((devid) == PCI_DEVICE_ID_BROCADE_CT || \
+ (devid) == PCI_DEVICE_ID_BROCADE_CT_FC)
+
+#endif /* __BFA_DEFS_H__ */
diff --git a/drivers/net/bna/bfa_defs_cna.h b/drivers/net/bna/bfa_defs_cna.h
new file mode 100644
index 000000000000..7e0a9187bdd5
--- /dev/null
+++ b/drivers/net/bna/bfa_defs_cna.h
@@ -0,0 +1,223 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+
+#ifndef __BFA_DEFS_CNA_H__
+#define __BFA_DEFS_CNA_H__
+
+#include "bfa_defs.h"
+
+/**
+ * @brief
+ * FC physical port statistics.
+ */
+struct bfa_port_fc_stats {
+ u64 secs_reset; /*!< Seconds since stats is reset */
+ u64 tx_frames; /*!< Tx frames */
+ u64 tx_words; /*!< Tx words */
+ u64 tx_lip; /*!< Tx LIP */
+ u64 tx_nos; /*!< Tx NOS */
+ u64 tx_ols; /*!< Tx OLS */
+ u64 tx_lr; /*!< Tx LR */
+ u64 tx_lrr; /*!< Tx LRR */
+ u64 rx_frames; /*!< Rx frames */
+ u64 rx_words; /*!< Rx words */
+ u64 lip_count; /*!< Rx LIP */
+ u64 nos_count; /*!< Rx NOS */
+ u64 ols_count; /*!< Rx OLS */
+ u64 lr_count; /*!< Rx LR */
+ u64 lrr_count; /*!< Rx LRR */
+ u64 invalid_crcs; /*!< Rx CRC err frames */
+ u64 invalid_crc_gd_eof; /*!< Rx CRC err good EOF frames */
+ u64 undersized_frm; /*!< Rx undersized frames */
+ u64 oversized_frm; /*!< Rx oversized frames */
+ u64 bad_eof_frm; /*!< Rx frames with bad EOF */
+ u64 error_frames; /*!< Errored frames */
+ u64 dropped_frames; /*!< Dropped frames */
+ u64 link_failures; /*!< Link Failure (LF) count */
+ u64 loss_of_syncs; /*!< Loss of sync count */
+ u64 loss_of_signals; /*!< Loss of signal count */
+ u64 primseq_errs; /*!< Primitive sequence protocol err. */
+ u64 bad_os_count; /*!< Invalid ordered sets */
+ u64 err_enc_out; /*!< Encoding err nonframe_8b10b */
+ u64 err_enc; /*!< Encoding err frame_8b10b */
+};
+
+/**
+ * @brief
+ * Eth Physical Port statistics.
+ */
+struct bfa_port_eth_stats {
+ u64 secs_reset; /*!< Seconds since stats is reset */
+ u64 frame_64; /*!< Frames 64 bytes */
+ u64 frame_65_127; /*!< Frames 65-127 bytes */
+ u64 frame_128_255; /*!< Frames 128-255 bytes */
+ u64 frame_256_511; /*!< Frames 256-511 bytes */
+ u64 frame_512_1023; /*!< Frames 512-1023 bytes */
+ u64 frame_1024_1518; /*!< Frames 1024-1518 bytes */
+ u64 frame_1519_1522; /*!< Frames 1519-1522 bytes */
+ u64 tx_bytes; /*!< Tx bytes */
+ u64 tx_packets; /*!< Tx packets */
+ u64 tx_mcast_packets; /*!< Tx multicast packets */
+ u64 tx_bcast_packets; /*!< Tx broadcast packets */
+ u64 tx_control_frame; /*!< Tx control frame */
+ u64 tx_drop; /*!< Tx drops */
+ u64 tx_jabber; /*!< Tx jabber */
+ u64 tx_fcs_error; /*!< Tx FCS errors */
+ u64 tx_fragments; /*!< Tx fragments */
+ u64 rx_bytes; /*!< Rx bytes */
+ u64 rx_packets; /*!< Rx packets */
+ u64 rx_mcast_packets; /*!< Rx multicast packets */
+ u64 rx_bcast_packets; /*!< Rx broadcast packets */
+ u64 rx_control_frames; /*!< Rx control frames */
+ u64 rx_unknown_opcode; /*!< Rx unknown opcode */
+ u64 rx_drop; /*!< Rx drops */
+ u64 rx_jabber; /*!< Rx jabber */
+ u64 rx_fcs_error; /*!< Rx FCS errors */
+ u64 rx_alignment_error; /*!< Rx alignment errors */
+ u64 rx_frame_length_error; /*!< Rx frame len errors */
+ u64 rx_code_error; /*!< Rx code errors */
+ u64 rx_fragments; /*!< Rx fragments */
+ u64 rx_pause; /*!< Rx pause */
+ u64 rx_zero_pause; /*!< Rx zero pause */
+ u64 tx_pause; /*!< Tx pause */
+ u64 tx_zero_pause; /*!< Tx zero pause */
+ u64 rx_fcoe_pause; /*!< Rx FCoE pause */
+ u64 rx_fcoe_zero_pause; /*!< Rx FCoE zero pause */
+ u64 tx_fcoe_pause; /*!< Tx FCoE pause */
+ u64 tx_fcoe_zero_pause; /*!< Tx FCoE zero pause */
+};
+
+/**
+ * @brief
+ * Port statistics.
+ */
+union bfa_port_stats_u {
+ struct bfa_port_fc_stats fc;
+ struct bfa_port_eth_stats eth;
+};
+
+#pragma pack(1)
+
+#define BFA_CEE_LLDP_MAX_STRING_LEN (128)
+#define BFA_CEE_DCBX_MAX_PRIORITY (8)
+#define BFA_CEE_DCBX_MAX_PGID (8)
+
+#define BFA_CEE_LLDP_SYS_CAP_OTHER 0x0001
+#define BFA_CEE_LLDP_SYS_CAP_REPEATER 0x0002
+#define BFA_CEE_LLDP_SYS_CAP_MAC_BRIDGE 0x0004
+#define BFA_CEE_LLDP_SYS_CAP_WLAN_AP 0x0008
+#define BFA_CEE_LLDP_SYS_CAP_ROUTER 0x0010
+#define BFA_CEE_LLDP_SYS_CAP_TELEPHONE 0x0020
+#define BFA_CEE_LLDP_SYS_CAP_DOCSIS_CD 0x0040
+#define BFA_CEE_LLDP_SYS_CAP_STATION 0x0080
+#define BFA_CEE_LLDP_SYS_CAP_CVLAN 0x0100
+#define BFA_CEE_LLDP_SYS_CAP_SVLAN 0x0200
+#define BFA_CEE_LLDP_SYS_CAP_TPMR 0x0400
+
+/* LLDP string type */
+struct bfa_cee_lldp_str {
+ u8 sub_type;
+ u8 len;
+ u8 rsvd[2];
+ u8 value[BFA_CEE_LLDP_MAX_STRING_LEN];
+};
+
+/* LLDP paramters */
+struct bfa_cee_lldp_cfg {
+ struct bfa_cee_lldp_str chassis_id;
+ struct bfa_cee_lldp_str port_id;
+ struct bfa_cee_lldp_str port_desc;
+ struct bfa_cee_lldp_str sys_name;
+ struct bfa_cee_lldp_str sys_desc;
+ struct bfa_cee_lldp_str mgmt_addr;
+ u16 time_to_live;
+ u16 enabled_system_cap;
+};
+
+enum bfa_cee_dcbx_version {
+ DCBX_PROTOCOL_PRECEE = 1,
+ DCBX_PROTOCOL_CEE = 2,
+};
+
+enum bfa_cee_lls {
+ /* LLS is down because the TLV not sent by the peer */
+ CEE_LLS_DOWN_NO_TLV = 0,
+ /* LLS is down as advertised by the peer */
+ CEE_LLS_DOWN = 1,
+ CEE_LLS_UP = 2,
+};
+
+/* CEE/DCBX parameters */
+struct bfa_cee_dcbx_cfg {
+ u8 pgid[BFA_CEE_DCBX_MAX_PRIORITY];
+ u8 pg_percentage[BFA_CEE_DCBX_MAX_PGID];
+ u8 pfc_primap; /* bitmap of priorties with PFC enabled */
+ u8 fcoe_primap; /* bitmap of priorities used for FcoE traffic */
+ u8 iscsi_primap; /* bitmap of priorities used for iSCSI traffic */
+ u8 dcbx_version; /* operating version:CEE or preCEE */
+ u8 lls_fcoe; /* FCoE Logical Link Status */
+ u8 lls_lan; /* LAN Logical Link Status */
+ u8 rsvd[2];
+};
+
+/* CEE status */
+/* Making this to tri-state for the benefit of port list command */
+enum bfa_cee_status {
+ CEE_UP = 0,
+ CEE_PHY_UP = 1,
+ CEE_LOOPBACK = 2,
+ CEE_PHY_DOWN = 3,
+};
+
+/* CEE Query */
+struct bfa_cee_attr {
+ u8 cee_status;
+ u8 error_reason;
+ struct bfa_cee_lldp_cfg lldp_remote;
+ struct bfa_cee_dcbx_cfg dcbx_remote;
+ mac_t src_mac;
+ u8 link_speed;
+ u8 nw_priority;
+ u8 filler[2];
+};
+
+/* LLDP/DCBX/CEE Statistics */
+struct bfa_cee_stats {
+ u32 lldp_tx_frames; /*!< LLDP Tx Frames */
+ u32 lldp_rx_frames; /*!< LLDP Rx Frames */
+ u32 lldp_rx_frames_invalid; /*!< LLDP Rx Frames invalid */
+ u32 lldp_rx_frames_new; /*!< LLDP Rx Frames new */
+ u32 lldp_tlvs_unrecognized; /*!< LLDP Rx unrecognized TLVs */
+ u32 lldp_rx_shutdown_tlvs; /*!< LLDP Rx shutdown TLVs */
+ u32 lldp_info_aged_out; /*!< LLDP remote info aged out */
+ u32 dcbx_phylink_ups; /*!< DCBX phy link ups */
+ u32 dcbx_phylink_downs; /*!< DCBX phy link downs */
+ u32 dcbx_rx_tlvs; /*!< DCBX Rx TLVs */
+ u32 dcbx_rx_tlvs_invalid; /*!< DCBX Rx TLVs invalid */
+ u32 dcbx_control_tlv_error; /*!< DCBX control TLV errors */
+ u32 dcbx_feature_tlv_error; /*!< DCBX feature TLV errors */
+ u32 dcbx_cee_cfg_new; /*!< DCBX new CEE cfg rcvd */
+ u32 cee_status_down; /*!< CEE status down */
+ u32 cee_status_up; /*!< CEE status up */
+ u32 cee_hw_cfg_changed; /*!< CEE hw cfg changed */
+ u32 cee_rx_invalid_cfg; /*!< CEE invalid cfg */
+};
+
+#pragma pack()
+
+#endif /* __BFA_DEFS_CNA_H__ */
diff --git a/drivers/net/bna/bfa_defs_mfg_comm.h b/drivers/net/bna/bfa_defs_mfg_comm.h
new file mode 100644
index 000000000000..987978fcb3fe
--- /dev/null
+++ b/drivers/net/bna/bfa_defs_mfg_comm.h
@@ -0,0 +1,244 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+#ifndef __BFA_DEFS_MFG_COMM_H__
+#define __BFA_DEFS_MFG_COMM_H__
+
+#include "cna.h"
+
+/**
+ * Manufacturing block version
+ */
+#define BFA_MFG_VERSION 2
+#define BFA_MFG_VERSION_UNINIT 0xFF
+
+/**
+ * Manufacturing block encrypted version
+ */
+#define BFA_MFG_ENC_VER 2
+
+/**
+ * Manufacturing block version 1 length
+ */
+#define BFA_MFG_VER1_LEN 128
+
+/**
+ * Manufacturing block header length
+ */
+#define BFA_MFG_HDR_LEN 4
+
+#define BFA_MFG_SERIALNUM_SIZE 11
+#define STRSZ(_n) (((_n) + 4) & ~3)
+
+/**
+ * Manufacturing card type
+ */
+enum {
+ BFA_MFG_TYPE_CB_MAX = 825, /*!< Crossbow card type max */
+ BFA_MFG_TYPE_FC8P2 = 825, /*!< 8G 2port FC card */
+ BFA_MFG_TYPE_FC8P1 = 815, /*!< 8G 1port FC card */
+ BFA_MFG_TYPE_FC4P2 = 425, /*!< 4G 2port FC card */
+ BFA_MFG_TYPE_FC4P1 = 415, /*!< 4G 1port FC card */
+ BFA_MFG_TYPE_CNA10P2 = 1020, /*!< 10G 2port CNA card */
+ BFA_MFG_TYPE_CNA10P1 = 1010, /*!< 10G 1port CNA card */
+ BFA_MFG_TYPE_JAYHAWK = 804, /*!< Jayhawk mezz card */
+ BFA_MFG_TYPE_WANCHESE = 1007, /*!< Wanchese mezz card */
+ BFA_MFG_TYPE_ASTRA = 807, /*!< Astra mezz card */
+ BFA_MFG_TYPE_LIGHTNING_P0 = 902, /*!< Lightning mezz card - old */
+ BFA_MFG_TYPE_LIGHTNING = 1741, /*!< Lightning mezz card */
+ BFA_MFG_TYPE_INVALID = 0, /*!< Invalid card type */
+};
+
+#pragma pack(1)
+
+/**
+ * Check if 1-port card
+ */
+#define bfa_mfg_is_1port(type) (( \
+ (type) == BFA_MFG_TYPE_FC8P1 || \
+ (type) == BFA_MFG_TYPE_FC4P1 || \
+ (type) == BFA_MFG_TYPE_CNA10P1))
+
+/**
+ * Check if Mezz card
+ */
+#define bfa_mfg_is_mezz(type) (( \
+ (type) == BFA_MFG_TYPE_JAYHAWK || \
+ (type) == BFA_MFG_TYPE_WANCHESE || \
+ (type) == BFA_MFG_TYPE_ASTRA || \
+ (type) == BFA_MFG_TYPE_LIGHTNING_P0 || \
+ (type) == BFA_MFG_TYPE_LIGHTNING))
+
+/**
+ * Check if card type valid
+ */
+#define bfa_mfg_is_card_type_valid(type) (( \
+ (type) == BFA_MFG_TYPE_FC8P2 || \
+ (type) == BFA_MFG_TYPE_FC8P1 || \
+ (type) == BFA_MFG_TYPE_FC4P2 || \
+ (type) == BFA_MFG_TYPE_FC4P1 || \
+ (type) == BFA_MFG_TYPE_CNA10P2 || \
+ (type) == BFA_MFG_TYPE_CNA10P1 || \
+ bfa_mfg_is_mezz(type)))
+
+/**
+ * Check if the card having old wwn/mac handling
+ */
+#define bfa_mfg_is_old_wwn_mac_model(type) (( \
+ (type) == BFA_MFG_TYPE_FC8P2 || \
+ (type) == BFA_MFG_TYPE_FC8P1 || \
+ (type) == BFA_MFG_TYPE_FC4P2 || \
+ (type) == BFA_MFG_TYPE_FC4P1 || \
+ (type) == BFA_MFG_TYPE_CNA10P2 || \
+ (type) == BFA_MFG_TYPE_CNA10P1 || \
+ (type) == BFA_MFG_TYPE_JAYHAWK || \
+ (type) == BFA_MFG_TYPE_WANCHESE))
+
+#define bfa_mfg_increment_wwn_mac(m, i) \
+do { \
+ u32 t = ((m)[0] << 16) | ((m)[1] << 8) | (m)[2]; \
+ t += (i); \
+ (m)[0] = (t >> 16) & 0xFF; \
+ (m)[1] = (t >> 8) & 0xFF; \
+ (m)[2] = t & 0xFF; \
+} while (0)
+
+#define bfa_mfg_adapter_prop_init_flash(card_type, prop) \
+do { \
+ switch ((card_type)) { \
+ case BFA_MFG_TYPE_FC8P2: \
+ case BFA_MFG_TYPE_JAYHAWK: \
+ case BFA_MFG_TYPE_ASTRA: \
+ (prop) = BFI_ADAPTER_SETP(NPORTS, 2) | \
+ BFI_ADAPTER_SETP(SPEED, 8); \
+ break; \
+ case BFA_MFG_TYPE_FC8P1: \
+ (prop) = BFI_ADAPTER_SETP(NPORTS, 1) | \
+ BFI_ADAPTER_SETP(SPEED, 8); \
+ break; \
+ case BFA_MFG_TYPE_FC4P2: \
+ (prop) = BFI_ADAPTER_SETP(NPORTS, 2) | \
+ BFI_ADAPTER_SETP(SPEED, 4); \
+ break; \
+ case BFA_MFG_TYPE_FC4P1: \
+ (prop) = BFI_ADAPTER_SETP(NPORTS, 1) | \
+ BFI_ADAPTER_SETP(SPEED, 4); \
+ break; \
+ case BFA_MFG_TYPE_CNA10P2: \
+ case BFA_MFG_TYPE_WANCHESE: \
+ case BFA_MFG_TYPE_LIGHTNING_P0: \
+ case BFA_MFG_TYPE_LIGHTNING: \
+ (prop) = BFI_ADAPTER_SETP(NPORTS, 2); \
+ (prop) |= BFI_ADAPTER_SETP(SPEED, 10); \
+ break; \
+ case BFA_MFG_TYPE_CNA10P1: \
+ (prop) = BFI_ADAPTER_SETP(NPORTS, 1); \
+ (prop) |= BFI_ADAPTER_SETP(SPEED, 10); \
+ break; \
+ default: \
+ (prop) = BFI_ADAPTER_UNSUPP; \
+ } \
+} while (0)
+
+enum {
+ CB_GPIO_TTV = (1), /*!< TTV debug capable cards */
+ CB_GPIO_FC8P2 = (2), /*!< 8G 2port FC card */
+ CB_GPIO_FC8P1 = (3), /*!< 8G 1port FC card */
+ CB_GPIO_FC4P2 = (4), /*!< 4G 2port FC card */
+ CB_GPIO_FC4P1 = (5), /*!< 4G 1port FC card */
+ CB_GPIO_DFLY = (6), /*!< 8G 2port FC mezzanine card */
+ CB_GPIO_PROTO = (1 << 7) /*!< 8G 2port FC prototypes */
+};
+
+#define bfa_mfg_adapter_prop_init_gpio(gpio, card_type, prop) \
+do { \
+ if ((gpio) & CB_GPIO_PROTO) { \
+ (prop) |= BFI_ADAPTER_PROTO; \
+ (gpio) &= ~CB_GPIO_PROTO; \
+ } \
+ switch ((gpio)) { \
+ case CB_GPIO_TTV: \
+ (prop) |= BFI_ADAPTER_TTV; \
+ case CB_GPIO_DFLY: \
+ case CB_GPIO_FC8P2: \
+ (prop) |= BFI_ADAPTER_SETP(NPORTS, 2); \
+ (prop) |= BFI_ADAPTER_SETP(SPEED, 8); \
+ (card_type) = BFA_MFG_TYPE_FC8P2; \
+ break; \
+ case CB_GPIO_FC8P1: \
+ (prop) |= BFI_ADAPTER_SETP(NPORTS, 1); \
+ (prop) |= BFI_ADAPTER_SETP(SPEED, 8); \
+ (card_type) = BFA_MFG_TYPE_FC8P1; \
+ break; \
+ case CB_GPIO_FC4P2: \
+ (prop) |= BFI_ADAPTER_SETP(NPORTS, 2); \
+ (prop) |= BFI_ADAPTER_SETP(SPEED, 4); \
+ (card_type) = BFA_MFG_TYPE_FC4P2; \
+ break; \
+ case CB_GPIO_FC4P1: \
+ (prop) |= BFI_ADAPTER_SETP(NPORTS, 1); \
+ (prop) |= BFI_ADAPTER_SETP(SPEED, 4); \
+ (card_type) = BFA_MFG_TYPE_FC4P1; \
+ break; \
+ default: \
+ (prop) |= BFI_ADAPTER_UNSUPP; \
+ (card_type) = BFA_MFG_TYPE_INVALID; \
+ } \
+} while (0)
+
+/**
+ * VPD data length
+ */
+#define BFA_MFG_VPD_LEN 512
+#define BFA_MFG_VPD_LEN_INVALID 0
+
+#define BFA_MFG_VPD_PCI_HDR_OFF 137
+#define BFA_MFG_VPD_PCI_VER_MASK 0x07 /*!< version mask 3 bits */
+#define BFA_MFG_VPD_PCI_VDR_MASK 0xf8 /*!< vendor mask 5 bits */
+
+/**
+ * VPD vendor tag
+ */
+enum {
+ BFA_MFG_VPD_UNKNOWN = 0, /*!< vendor unknown */
+ BFA_MFG_VPD_IBM = 1, /*!< vendor IBM */
+ BFA_MFG_VPD_HP = 2, /*!< vendor HP */
+ BFA_MFG_VPD_DELL = 3, /*!< vendor DELL */
+ BFA_MFG_VPD_PCI_IBM = 0x08, /*!< PCI VPD IBM */
+ BFA_MFG_VPD_PCI_HP = 0x10, /*!< PCI VPD HP */
+ BFA_MFG_VPD_PCI_DELL = 0x20, /*!< PCI VPD DELL */
+ BFA_MFG_VPD_PCI_BRCD = 0xf8, /*!< PCI VPD Brocade */
+};
+
+/**
+ * @brief BFA adapter flash vpd data definition.
+ *
+ * All numerical fields are in big-endian format.
+ */
+struct bfa_mfg_vpd {
+ u8 version; /*!< vpd data version */
+ u8 vpd_sig[3]; /*!< characters 'V', 'P', 'D' */
+ u8 chksum; /*!< u8 checksum */
+ u8 vendor; /*!< vendor */
+ u8 len; /*!< vpd data length excluding header */
+ u8 rsv;
+ u8 data[BFA_MFG_VPD_LEN]; /*!< vpd data */
+};
+
+#pragma pack()
+
+#endif /* __BFA_DEFS_MFG_H__ */
diff --git a/drivers/net/bna/bfa_defs_status.h b/drivers/net/bna/bfa_defs_status.h
new file mode 100644
index 000000000000..af951126375c
--- /dev/null
+++ b/drivers/net/bna/bfa_defs_status.h
@@ -0,0 +1,216 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+#ifndef __BFA_DEFS_STATUS_H__
+#define __BFA_DEFS_STATUS_H__
+
+/**
+ * API status return values
+ *
+ * NOTE: The error msgs are auto generated from the comments. Only singe line
+ * comments are supported
+ */
+enum bfa_status {
+ BFA_STATUS_OK = 0,
+ BFA_STATUS_FAILED = 1,
+ BFA_STATUS_EINVAL = 2,
+ BFA_STATUS_ENOMEM = 3,
+ BFA_STATUS_ENOSYS = 4,
+ BFA_STATUS_ETIMER = 5,
+ BFA_STATUS_EPROTOCOL = 6,
+ BFA_STATUS_ENOFCPORTS = 7,
+ BFA_STATUS_NOFLASH = 8,
+ BFA_STATUS_BADFLASH = 9,
+ BFA_STATUS_SFP_UNSUPP = 10,
+ BFA_STATUS_UNKNOWN_VFID = 11,
+ BFA_STATUS_DATACORRUPTED = 12,
+ BFA_STATUS_DEVBUSY = 13,
+ BFA_STATUS_ABORTED = 14,
+ BFA_STATUS_NODEV = 15,
+ BFA_STATUS_HDMA_FAILED = 16,
+ BFA_STATUS_FLASH_BAD_LEN = 17,
+ BFA_STATUS_UNKNOWN_LWWN = 18,
+ BFA_STATUS_UNKNOWN_RWWN = 19,
+ BFA_STATUS_FCPT_LS_RJT = 20,
+ BFA_STATUS_VPORT_EXISTS = 21,
+ BFA_STATUS_VPORT_MAX = 22,
+ BFA_STATUS_UNSUPP_SPEED = 23,
+ BFA_STATUS_INVLD_DFSZ = 24,
+ BFA_STATUS_CNFG_FAILED = 25,
+ BFA_STATUS_CMD_NOTSUPP = 26,
+ BFA_STATUS_NO_ADAPTER = 27,
+ BFA_STATUS_LINKDOWN = 28,
+ BFA_STATUS_FABRIC_RJT = 29,
+ BFA_STATUS_UNKNOWN_VWWN = 30,
+ BFA_STATUS_NSLOGIN_FAILED = 31,
+ BFA_STATUS_NO_RPORTS = 32,
+ BFA_STATUS_NSQUERY_FAILED = 33,
+ BFA_STATUS_PORT_OFFLINE = 34,
+ BFA_STATUS_RPORT_OFFLINE = 35,
+ BFA_STATUS_TGTOPEN_FAILED = 36,
+ BFA_STATUS_BAD_LUNS = 37,
+ BFA_STATUS_IO_FAILURE = 38,
+ BFA_STATUS_NO_FABRIC = 39,
+ BFA_STATUS_EBADF = 40,
+ BFA_STATUS_EINTR = 41,
+ BFA_STATUS_EIO = 42,
+ BFA_STATUS_ENOTTY = 43,
+ BFA_STATUS_ENXIO = 44,
+ BFA_STATUS_EFOPEN = 45,
+ BFA_STATUS_VPORT_WWN_BP = 46,
+ BFA_STATUS_PORT_NOT_DISABLED = 47,
+ BFA_STATUS_BADFRMHDR = 48,
+ BFA_STATUS_BADFRMSZ = 49,
+ BFA_STATUS_MISSINGFRM = 50,
+ BFA_STATUS_LINKTIMEOUT = 51,
+ BFA_STATUS_NO_FCPIM_NEXUS = 52,
+ BFA_STATUS_CHECKSUM_FAIL = 53,
+ BFA_STATUS_GZME_FAILED = 54,
+ BFA_STATUS_SCSISTART_REQD = 55,
+ BFA_STATUS_IOC_FAILURE = 56,
+ BFA_STATUS_INVALID_WWN = 57,
+ BFA_STATUS_MISMATCH = 58,
+ BFA_STATUS_IOC_ENABLED = 59,
+ BFA_STATUS_ADAPTER_ENABLED = 60,
+ BFA_STATUS_IOC_NON_OP = 61,
+ BFA_STATUS_ADDR_MAP_FAILURE = 62,
+ BFA_STATUS_SAME_NAME = 63,
+ BFA_STATUS_PENDING = 64,
+ BFA_STATUS_8G_SPD = 65,
+ BFA_STATUS_4G_SPD = 66,
+ BFA_STATUS_AD_IS_ENABLE = 67,
+ BFA_STATUS_EINVAL_TOV = 68,
+ BFA_STATUS_EINVAL_QDEPTH = 69,
+ BFA_STATUS_VERSION_FAIL = 70,
+ BFA_STATUS_DIAG_BUSY = 71,
+ BFA_STATUS_BEACON_ON = 72,
+ BFA_STATUS_BEACON_OFF = 73,
+ BFA_STATUS_LBEACON_ON = 74,
+ BFA_STATUS_LBEACON_OFF = 75,
+ BFA_STATUS_PORT_NOT_INITED = 76,
+ BFA_STATUS_RPSC_ENABLED = 77,
+ BFA_STATUS_ENOFSAVE = 78,
+ BFA_STATUS_BAD_FILE = 79,
+ BFA_STATUS_RLIM_EN = 80,
+ BFA_STATUS_RLIM_DIS = 81,
+ BFA_STATUS_IOC_DISABLED = 82,
+ BFA_STATUS_ADAPTER_DISABLED = 83,
+ BFA_STATUS_BIOS_DISABLED = 84,
+ BFA_STATUS_AUTH_ENABLED = 85,
+ BFA_STATUS_AUTH_DISABLED = 86,
+ BFA_STATUS_ERROR_TRL_ENABLED = 87,
+ BFA_STATUS_ERROR_QOS_ENABLED = 88,
+ BFA_STATUS_NO_SFP_DEV = 89,
+ BFA_STATUS_MEMTEST_FAILED = 90,
+ BFA_STATUS_INVALID_DEVID = 91,
+ BFA_STATUS_QOS_ENABLED = 92,
+ BFA_STATUS_QOS_DISABLED = 93,
+ BFA_STATUS_INCORRECT_DRV_CONFIG = 94,
+ BFA_STATUS_REG_FAIL = 95,
+ BFA_STATUS_IM_INV_CODE = 96,
+ BFA_STATUS_IM_INV_VLAN = 97,
+ BFA_STATUS_IM_INV_ADAPT_NAME = 98,
+ BFA_STATUS_IM_LOW_RESOURCES = 99,
+ BFA_STATUS_IM_VLANID_IS_PVID = 100,
+ BFA_STATUS_IM_VLANID_EXISTS = 101,
+ BFA_STATUS_IM_FW_UPDATE_FAIL = 102,
+ BFA_STATUS_PORTLOG_ENABLED = 103,
+ BFA_STATUS_PORTLOG_DISABLED = 104,
+ BFA_STATUS_FILE_NOT_FOUND = 105,
+ BFA_STATUS_QOS_FC_ONLY = 106,
+ BFA_STATUS_RLIM_FC_ONLY = 107,
+ BFA_STATUS_CT_SPD = 108,
+ BFA_STATUS_LEDTEST_OP = 109,
+ BFA_STATUS_CEE_NOT_DN = 110,
+ BFA_STATUS_10G_SPD = 111,
+ BFA_STATUS_IM_INV_TEAM_NAME = 112,
+ BFA_STATUS_IM_DUP_TEAM_NAME = 113,
+ BFA_STATUS_IM_ADAPT_ALREADY_IN_TEAM = 114,
+ BFA_STATUS_IM_ADAPT_HAS_VLANS = 115,
+ BFA_STATUS_IM_PVID_MISMATCH = 116,
+ BFA_STATUS_IM_LINK_SPEED_MISMATCH = 117,
+ BFA_STATUS_IM_MTU_MISMATCH = 118,
+ BFA_STATUS_IM_RSS_MISMATCH = 119,
+ BFA_STATUS_IM_HDS_MISMATCH = 120,
+ BFA_STATUS_IM_OFFLOAD_MISMATCH = 121,
+ BFA_STATUS_IM_PORT_PARAMS = 122,
+ BFA_STATUS_IM_PORT_NOT_IN_TEAM = 123,
+ BFA_STATUS_IM_CANNOT_REM_PRI = 124,
+ BFA_STATUS_IM_MAX_PORTS_REACHED = 125,
+ BFA_STATUS_IM_LAST_PORT_DELETE = 126,
+ BFA_STATUS_IM_NO_DRIVER = 127,
+ BFA_STATUS_IM_MAX_VLANS_REACHED = 128,
+ BFA_STATUS_TOMCAT_SPD_NOT_ALLOWED = 129,
+ BFA_STATUS_NO_MINPORT_DRIVER = 130,
+ BFA_STATUS_CARD_TYPE_MISMATCH = 131,
+ BFA_STATUS_BAD_ASICBLK = 132,
+ BFA_STATUS_NO_DRIVER = 133,
+ BFA_STATUS_INVALID_MAC = 134,
+ BFA_STATUS_IM_NO_VLAN = 135,
+ BFA_STATUS_IM_ETH_LB_FAILED = 136,
+ BFA_STATUS_IM_PVID_REMOVE = 137,
+ BFA_STATUS_IM_PVID_EDIT = 138,
+ BFA_STATUS_CNA_NO_BOOT = 139,
+ BFA_STATUS_IM_PVID_NON_ZERO = 140,
+ BFA_STATUS_IM_INETCFG_LOCK_FAILED = 141,
+ BFA_STATUS_IM_GET_INETCFG_FAILED = 142,
+ BFA_STATUS_IM_NOT_BOUND = 143,
+ BFA_STATUS_INSUFFICIENT_PERMS = 144,
+ BFA_STATUS_IM_INV_VLAN_NAME = 145,
+ BFA_STATUS_CMD_NOTSUPP_CNA = 146,
+ BFA_STATUS_IM_PASSTHRU_EDIT = 147,
+ BFA_STATUS_IM_BIND_FAILED = 148,
+ BFA_STATUS_IM_UNBIND_FAILED = 149,
+ BFA_STATUS_IM_PORT_IN_TEAM = 150,
+ BFA_STATUS_IM_VLAN_NOT_FOUND = 151,
+ BFA_STATUS_IM_TEAM_NOT_FOUND = 152,
+ BFA_STATUS_IM_TEAM_CFG_NOT_ALLOWED = 153,
+ BFA_STATUS_PBC = 154,
+ BFA_STATUS_DEVID_MISSING = 155,
+ BFA_STATUS_BAD_FWCFG = 156,
+ BFA_STATUS_CREATE_FILE = 157,
+ BFA_STATUS_INVALID_VENDOR = 158,
+ BFA_STATUS_SFP_NOT_READY = 159,
+ BFA_STATUS_FLASH_UNINIT = 160,
+ BFA_STATUS_FLASH_EMPTY = 161,
+ BFA_STATUS_FLASH_CKFAIL = 162,
+ BFA_STATUS_TRUNK_UNSUPP = 163,
+ BFA_STATUS_TRUNK_ENABLED = 164,
+ BFA_STATUS_TRUNK_DISABLED = 165,
+ BFA_STATUS_TRUNK_ERROR_TRL_ENABLED = 166,
+ BFA_STATUS_BOOT_CODE_UPDATED = 167,
+ BFA_STATUS_BOOT_VERSION = 168,
+ BFA_STATUS_CARDTYPE_MISSING = 169,
+ BFA_STATUS_INVALID_CARDTYPE = 170,
+ BFA_STATUS_NO_TOPOLOGY_FOR_CNA = 171,
+ BFA_STATUS_IM_VLAN_OVER_TEAM_DELETE_FAILED = 172,
+ BFA_STATUS_ETHBOOT_ENABLED = 173,
+ BFA_STATUS_ETHBOOT_DISABLED = 174,
+ BFA_STATUS_IOPROFILE_OFF = 175,
+ BFA_STATUS_NO_PORT_INSTANCE = 176,
+ BFA_STATUS_BOOT_CODE_TIMEDOUT = 177,
+ BFA_STATUS_NO_VPORT_LOCK = 178,
+ BFA_STATUS_VPORT_NO_CNFG = 179,
+ BFA_STATUS_MAX_VAL
+};
+
+enum bfa_eproto_status {
+ BFA_EPROTO_BAD_ACCEPT = 0,
+ BFA_EPROTO_UNKNOWN_RSP = 1
+};
+
+#endif /* __BFA_DEFS_STATUS_H__ */
diff --git a/drivers/net/bna/bfa_ioc.c b/drivers/net/bna/bfa_ioc.c
new file mode 100644
index 000000000000..e94e5aa97515
--- /dev/null
+++ b/drivers/net/bna/bfa_ioc.c
@@ -0,0 +1,1732 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+
+#include "bfa_ioc.h"
+#include "cna.h"
+#include "bfi.h"
+#include "bfi_ctreg.h"
+#include "bfa_defs.h"
+
+/**
+ * IOC local definitions
+ */
+
+#define bfa_ioc_timer_start(__ioc) \
+ mod_timer(&(__ioc)->ioc_timer, jiffies + \
+ msecs_to_jiffies(BFA_IOC_TOV))
+#define bfa_ioc_timer_stop(__ioc) del_timer(&(__ioc)->ioc_timer)
+
+#define bfa_ioc_recovery_timer_start(__ioc) \
+ mod_timer(&(__ioc)->ioc_timer, jiffies + \
+ msecs_to_jiffies(BFA_IOC_TOV_RECOVER))
+
+#define bfa_sem_timer_start(__ioc) \
+ mod_timer(&(__ioc)->sem_timer, jiffies + \
+ msecs_to_jiffies(BFA_IOC_HWSEM_TOV))
+#define bfa_sem_timer_stop(__ioc) del_timer(&(__ioc)->sem_timer)
+
+#define bfa_hb_timer_start(__ioc) \
+ mod_timer(&(__ioc)->hb_timer, jiffies + \
+ msecs_to_jiffies(BFA_IOC_HB_TOV))
+#define bfa_hb_timer_stop(__ioc) del_timer(&(__ioc)->hb_timer)
+
+/**
+ * Asic specific macros : see bfa_hw_cb.c and bfa_hw_ct.c for details.
+ */
+
+#define bfa_ioc_firmware_lock(__ioc) \
+ ((__ioc)->ioc_hwif->ioc_firmware_lock(__ioc))
+#define bfa_ioc_firmware_unlock(__ioc) \
+ ((__ioc)->ioc_hwif->ioc_firmware_unlock(__ioc))
+#define bfa_ioc_reg_init(__ioc) ((__ioc)->ioc_hwif->ioc_reg_init(__ioc))
+#define bfa_ioc_map_port(__ioc) ((__ioc)->ioc_hwif->ioc_map_port(__ioc))
+#define bfa_ioc_notify_hbfail(__ioc) \
+ ((__ioc)->ioc_hwif->ioc_notify_hbfail(__ioc))
+
+#define bfa_ioc_is_optrom(__ioc) \
+ (bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(__ioc)) < BFA_IOC_FWIMG_MINSZ)
+
+#define bfa_ioc_mbox_cmd_pending(__ioc) \
+ (!list_empty(&((__ioc)->mbox_mod.cmd_q)) || \
+ readl((__ioc)->ioc_regs.hfn_mbox_cmd))
+
+static bool bfa_nw_auto_recover = true;
+
+/*
+ * forward declarations
+ */
+static void bfa_ioc_hw_sem_get(struct bfa_ioc *ioc);
+static void bfa_ioc_hw_sem_get_cancel(struct bfa_ioc *ioc);
+static void bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force);
+static void bfa_ioc_send_enable(struct bfa_ioc *ioc);
+static void bfa_ioc_send_disable(struct bfa_ioc *ioc);
+static void bfa_ioc_send_getattr(struct bfa_ioc *ioc);
+static void bfa_ioc_hb_monitor(struct bfa_ioc *ioc);
+static void bfa_ioc_hb_stop(struct bfa_ioc *ioc);
+static void bfa_ioc_reset(struct bfa_ioc *ioc, bool force);
+static void bfa_ioc_mbox_poll(struct bfa_ioc *ioc);
+static void bfa_ioc_mbox_hbfail(struct bfa_ioc *ioc);
+static void bfa_ioc_recover(struct bfa_ioc *ioc);
+static void bfa_ioc_check_attr_wwns(struct bfa_ioc *ioc);
+static void bfa_ioc_disable_comp(struct bfa_ioc *ioc);
+static void bfa_ioc_lpu_stop(struct bfa_ioc *ioc);
+static void bfa_ioc_boot(struct bfa_ioc *ioc, u32 boot_type,
+ u32 boot_param);
+static u32 bfa_ioc_smem_pgnum(struct bfa_ioc *ioc, u32 fmaddr);
+static u32 bfa_ioc_smem_pgoff(struct bfa_ioc *ioc, u32 fmaddr);
+static void bfa_ioc_get_adapter_serial_num(struct bfa_ioc *ioc,
+ char *serial_num);
+static void bfa_ioc_get_adapter_fw_ver(struct bfa_ioc *ioc,
+ char *fw_ver);
+static void bfa_ioc_get_pci_chip_rev(struct bfa_ioc *ioc,
+ char *chip_rev);
+static void bfa_ioc_get_adapter_optrom_ver(struct bfa_ioc *ioc,
+ char *optrom_ver);
+static void bfa_ioc_get_adapter_manufacturer(struct bfa_ioc *ioc,
+ char *manufacturer);
+static void bfa_ioc_get_adapter_model(struct bfa_ioc *ioc, char *model);
+static u64 bfa_ioc_get_pwwn(struct bfa_ioc *ioc);
+static mac_t bfa_ioc_get_mfg_mac(struct bfa_ioc *ioc);
+
+/**
+ * IOC state machine events
+ */
+enum ioc_event {
+ IOC_E_ENABLE = 1, /*!< IOC enable request */
+ IOC_E_DISABLE = 2, /*!< IOC disable request */
+ IOC_E_TIMEOUT = 3, /*!< f/w response timeout */
+ IOC_E_FWREADY = 4, /*!< f/w initialization done */
+ IOC_E_FWRSP_GETATTR = 5, /*!< IOC get attribute response */
+ IOC_E_FWRSP_ENABLE = 6, /*!< enable f/w response */
+ IOC_E_FWRSP_DISABLE = 7, /*!< disable f/w response */
+ IOC_E_HBFAIL = 8, /*!< heartbeat failure */
+ IOC_E_HWERROR = 9, /*!< hardware error interrupt */
+ IOC_E_SEMLOCKED = 10, /*!< h/w semaphore is locked */
+ IOC_E_DETACH = 11, /*!< driver detach cleanup */
+};
+
+bfa_fsm_state_decl(bfa_ioc, reset, struct bfa_ioc, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, fwcheck, struct bfa_ioc, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, mismatch, struct bfa_ioc, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, semwait, struct bfa_ioc, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, hwinit, struct bfa_ioc, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, enabling, struct bfa_ioc, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, getattr, struct bfa_ioc, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, op, struct bfa_ioc, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, initfail, struct bfa_ioc, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, hbfail, struct bfa_ioc, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, disabling, struct bfa_ioc, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, disabled, struct bfa_ioc, enum ioc_event);
+
+static struct bfa_sm_table ioc_sm_table[] = {
+ {BFA_SM(bfa_ioc_sm_reset), BFA_IOC_RESET},
+ {BFA_SM(bfa_ioc_sm_fwcheck), BFA_IOC_FWMISMATCH},
+ {BFA_SM(bfa_ioc_sm_mismatch), BFA_IOC_FWMISMATCH},
+ {BFA_SM(bfa_ioc_sm_semwait), BFA_IOC_SEMWAIT},
+ {BFA_SM(bfa_ioc_sm_hwinit), BFA_IOC_HWINIT},
+ {BFA_SM(bfa_ioc_sm_enabling), BFA_IOC_HWINIT},
+ {BFA_SM(bfa_ioc_sm_getattr), BFA_IOC_GETATTR},
+ {BFA_SM(bfa_ioc_sm_op), BFA_IOC_OPERATIONAL},
+ {BFA_SM(bfa_ioc_sm_initfail), BFA_IOC_INITFAIL},
+ {BFA_SM(bfa_ioc_sm_hbfail), BFA_IOC_HBFAIL},
+ {BFA_SM(bfa_ioc_sm_disabling), BFA_IOC_DISABLING},
+ {BFA_SM(bfa_ioc_sm_disabled), BFA_IOC_DISABLED},
+};
+
+/**
+ * Reset entry actions -- initialize state machine
+ */
+static void
+bfa_ioc_sm_reset_entry(struct bfa_ioc *ioc)
+{
+ ioc->retry_count = 0;
+ ioc->auto_recover = bfa_nw_auto_recover;
+}
+
+/**
+ * Beginning state. IOC is in reset state.
+ */
+static void
+bfa_ioc_sm_reset(struct bfa_ioc *ioc, enum ioc_event event)
+{
+ switch (event) {
+ case IOC_E_ENABLE:
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_fwcheck);
+ break;
+
+ case IOC_E_DISABLE:
+ bfa_ioc_disable_comp(ioc);
+ break;
+
+ case IOC_E_DETACH:
+ break;
+
+ default:
+ bfa_sm_fault(ioc, event);
+ }
+}
+
+/**
+ * Semaphore should be acquired for version check.
+ */
+static void
+bfa_ioc_sm_fwcheck_entry(struct bfa_ioc *ioc)
+{
+ bfa_ioc_hw_sem_get(ioc);
+}
+
+/**
+ * Awaiting h/w semaphore to continue with version check.
+ */
+static void
+bfa_ioc_sm_fwcheck(struct bfa_ioc *ioc, enum ioc_event event)
+{
+ switch (event) {
+ case IOC_E_SEMLOCKED:
+ if (bfa_ioc_firmware_lock(ioc)) {
+ ioc->retry_count = 0;
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_hwinit);
+ } else {
+ bfa_nw_ioc_hw_sem_release(ioc);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_mismatch);
+ }
+ break;
+
+ case IOC_E_DISABLE:
+ bfa_ioc_disable_comp(ioc);
+ /* fall through */
+
+ case IOC_E_DETACH:
+ bfa_ioc_hw_sem_get_cancel(ioc);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
+ break;
+
+ case IOC_E_FWREADY:
+ break;
+
+ default:
+ bfa_sm_fault(ioc, event);
+ }
+}
+
+/**
+ * Notify enable completion callback and generate mismatch AEN.
+ */
+static void
+bfa_ioc_sm_mismatch_entry(struct bfa_ioc *ioc)
+{
+ /**
+ * Provide enable completion callback and AEN notification only once.
+ */
+ if (ioc->retry_count == 0)
+ ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+ ioc->retry_count++;
+ bfa_ioc_timer_start(ioc);
+}
+
+/**
+ * Awaiting firmware version match.
+ */
+static void
+bfa_ioc_sm_mismatch(struct bfa_ioc *ioc, enum ioc_event event)
+{
+ switch (event) {
+ case IOC_E_TIMEOUT:
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_fwcheck);
+ break;
+
+ case IOC_E_DISABLE:
+ bfa_ioc_disable_comp(ioc);
+ /* fall through */
+
+ case IOC_E_DETACH:
+ bfa_ioc_timer_stop(ioc);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
+ break;
+
+ case IOC_E_FWREADY:
+ break;
+
+ default:
+ bfa_sm_fault(ioc, event);
+ }
+}
+
+/**
+ * Request for semaphore.
+ */
+static void
+bfa_ioc_sm_semwait_entry(struct bfa_ioc *ioc)
+{
+ bfa_ioc_hw_sem_get(ioc);
+}
+
+/**
+ * Awaiting semaphore for h/w initialzation.
+ */
+static void
+bfa_ioc_sm_semwait(struct bfa_ioc *ioc, enum ioc_event event)
+{
+ switch (event) {
+ case IOC_E_SEMLOCKED:
+ ioc->retry_count = 0;
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_hwinit);
+ break;
+
+ case IOC_E_DISABLE:
+ bfa_ioc_hw_sem_get_cancel(ioc);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+ break;
+
+ default:
+ bfa_sm_fault(ioc, event);
+ }
+}
+
+static void
+bfa_ioc_sm_hwinit_entry(struct bfa_ioc *ioc)
+{
+ bfa_ioc_timer_start(ioc);
+ bfa_ioc_reset(ioc, false);
+}
+
+/**
+ * @brief
+ * Hardware is being initialized. Interrupts are enabled.
+ * Holding hardware semaphore lock.
+ */
+static void
+bfa_ioc_sm_hwinit(struct bfa_ioc *ioc, enum ioc_event event)
+{
+ switch (event) {
+ case IOC_E_FWREADY:
+ bfa_ioc_timer_stop(ioc);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_enabling);
+ break;
+
+ case IOC_E_HWERROR:
+ bfa_ioc_timer_stop(ioc);
+ /* fall through */
+
+ case IOC_E_TIMEOUT:
+ ioc->retry_count++;
+ if (ioc->retry_count < BFA_IOC_HWINIT_MAX) {
+ bfa_ioc_timer_start(ioc);
+ bfa_ioc_reset(ioc, true);
+ break;
+ }
+
+ bfa_nw_ioc_hw_sem_release(ioc);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
+ break;
+
+ case IOC_E_DISABLE:
+ bfa_nw_ioc_hw_sem_release(ioc);
+ bfa_ioc_timer_stop(ioc);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+ break;
+
+ default:
+ bfa_sm_fault(ioc, event);
+ }
+}
+
+static void
+bfa_ioc_sm_enabling_entry(struct bfa_ioc *ioc)
+{
+ bfa_ioc_timer_start(ioc);
+ bfa_ioc_send_enable(ioc);
+}
+
+/**
+ * Host IOC function is being enabled, awaiting response from firmware.
+ * Semaphore is acquired.
+ */
+static void
+bfa_ioc_sm_enabling(struct bfa_ioc *ioc, enum ioc_event event)
+{
+ switch (event) {
+ case IOC_E_FWRSP_ENABLE:
+ bfa_ioc_timer_stop(ioc);
+ bfa_nw_ioc_hw_sem_release(ioc);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
+ break;
+
+ case IOC_E_HWERROR:
+ bfa_ioc_timer_stop(ioc);
+ /* fall through */
+
+ case IOC_E_TIMEOUT:
+ ioc->retry_count++;
+ if (ioc->retry_count < BFA_IOC_HWINIT_MAX) {
+ writel(BFI_IOC_UNINIT,
+ ioc->ioc_regs.ioc_fwstate);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_hwinit);
+ break;
+ }
+
+ bfa_nw_ioc_hw_sem_release(ioc);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
+ break;
+
+ case IOC_E_DISABLE:
+ bfa_ioc_timer_stop(ioc);
+ bfa_nw_ioc_hw_sem_release(ioc);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+ break;
+
+ case IOC_E_FWREADY:
+ bfa_ioc_send_enable(ioc);
+ break;
+
+ default:
+ bfa_sm_fault(ioc, event);
+ }
+}
+
+static void
+bfa_ioc_sm_getattr_entry(struct bfa_ioc *ioc)
+{
+ bfa_ioc_timer_start(ioc);
+ bfa_ioc_send_getattr(ioc);
+}
+
+/**
+ * @brief
+ * IOC configuration in progress. Timer is active.
+ */
+static void
+bfa_ioc_sm_getattr(struct bfa_ioc *ioc, enum ioc_event event)
+{
+ switch (event) {
+ case IOC_E_FWRSP_GETATTR:
+ bfa_ioc_timer_stop(ioc);
+ bfa_ioc_check_attr_wwns(ioc);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_op);
+ break;
+
+ case IOC_E_HWERROR:
+ bfa_ioc_timer_stop(ioc);
+ /* fall through */
+
+ case IOC_E_TIMEOUT:
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
+ break;
+
+ case IOC_E_DISABLE:
+ bfa_ioc_timer_stop(ioc);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+ break;
+
+ default:
+ bfa_sm_fault(ioc, event);
+ }
+}
+
+static void
+bfa_ioc_sm_op_entry(struct bfa_ioc *ioc)
+{
+ ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_OK);
+ bfa_ioc_hb_monitor(ioc);
+}
+
+static void
+bfa_ioc_sm_op(struct bfa_ioc *ioc, enum ioc_event event)
+{
+ switch (event) {
+ case IOC_E_ENABLE:
+ break;
+
+ case IOC_E_DISABLE:
+ bfa_ioc_hb_stop(ioc);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
+ break;
+
+ case IOC_E_HWERROR:
+ case IOC_E_FWREADY:
+ /**
+ * Hard error or IOC recovery by other function.
+ * Treat it same as heartbeat failure.
+ */
+ bfa_ioc_hb_stop(ioc);
+ /* !!! fall through !!! */
+
+ case IOC_E_HBFAIL:
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_hbfail);
+ break;
+
+ default:
+ bfa_sm_fault(ioc, event);
+ }
+}
+
+static void
+bfa_ioc_sm_disabling_entry(struct bfa_ioc *ioc)
+{
+ bfa_ioc_timer_start(ioc);
+ bfa_ioc_send_disable(ioc);
+}
+
+/**
+ * IOC is being disabled
+ */
+static void
+bfa_ioc_sm_disabling(struct bfa_ioc *ioc, enum ioc_event event)
+{
+ switch (event) {
+ case IOC_E_FWRSP_DISABLE:
+ bfa_ioc_timer_stop(ioc);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+ break;
+
+ case IOC_E_HWERROR:
+ bfa_ioc_timer_stop(ioc);
+ /*
+ * !!! fall through !!!
+ */
+
+ case IOC_E_TIMEOUT:
+ writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+ break;
+
+ default:
+ bfa_sm_fault(ioc, event);
+ }
+}
+
+/**
+ * IOC disable completion entry.
+ */
+static void
+bfa_ioc_sm_disabled_entry(struct bfa_ioc *ioc)
+{
+ bfa_ioc_disable_comp(ioc);
+}
+
+static void
+bfa_ioc_sm_disabled(struct bfa_ioc *ioc, enum ioc_event event)
+{
+ switch (event) {
+ case IOC_E_ENABLE:
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_semwait);
+ break;
+
+ case IOC_E_DISABLE:
+ ioc->cbfn->disable_cbfn(ioc->bfa);
+ break;
+
+ case IOC_E_FWREADY:
+ break;
+
+ case IOC_E_DETACH:
+ bfa_ioc_firmware_unlock(ioc);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
+ break;
+
+ default:
+ bfa_sm_fault(ioc, event);
+ }
+}
+
+static void
+bfa_ioc_sm_initfail_entry(struct bfa_ioc *ioc)
+{
+ ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+ bfa_ioc_timer_start(ioc);
+}
+
+/**
+ * @brief
+ * Hardware initialization failed.
+ */
+static void
+bfa_ioc_sm_initfail(struct bfa_ioc *ioc, enum ioc_event event)
+{
+ switch (event) {
+ case IOC_E_DISABLE:
+ bfa_ioc_timer_stop(ioc);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+ break;
+
+ case IOC_E_DETACH:
+ bfa_ioc_timer_stop(ioc);
+ bfa_ioc_firmware_unlock(ioc);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
+ break;
+
+ case IOC_E_TIMEOUT:
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_semwait);
+ break;
+
+ default:
+ bfa_sm_fault(ioc, event);
+ }
+}
+
+static void
+bfa_ioc_sm_hbfail_entry(struct bfa_ioc *ioc)
+{
+ struct list_head *qe;
+ struct bfa_ioc_hbfail_notify *notify;
+
+ /**
+ * Mark IOC as failed in hardware and stop firmware.
+ */
+ bfa_ioc_lpu_stop(ioc);
+ writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
+
+ /**
+ * Notify other functions on HB failure.
+ */
+ bfa_ioc_notify_hbfail(ioc);
+
+ /**
+ * Notify driver and common modules registered for notification.
+ */
+ ioc->cbfn->hbfail_cbfn(ioc->bfa);
+ list_for_each(qe, &ioc->hb_notify_q) {
+ notify = (struct bfa_ioc_hbfail_notify *) qe;
+ notify->cbfn(notify->cbarg);
+ }
+
+ /**
+ * Flush any queued up mailbox requests.
+ */
+ bfa_ioc_mbox_hbfail(ioc);
+
+ /**
+ * Trigger auto-recovery after a delay.
+ */
+ if (ioc->auto_recover)
+ mod_timer(&ioc->ioc_timer, jiffies +
+ msecs_to_jiffies(BFA_IOC_TOV_RECOVER));
+}
+
+/**
+ * @brief
+ * IOC heartbeat failure.
+ */
+static void
+bfa_ioc_sm_hbfail(struct bfa_ioc *ioc, enum ioc_event event)
+{
+ switch (event) {
+
+ case IOC_E_ENABLE:
+ ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+ break;
+
+ case IOC_E_DISABLE:
+ if (ioc->auto_recover)
+ bfa_ioc_timer_stop(ioc);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+ break;
+
+ case IOC_E_TIMEOUT:
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_semwait);
+ break;
+
+ case IOC_E_FWREADY:
+ /**
+ * Recovery is already initiated by other function.
+ */
+ break;
+
+ case IOC_E_HWERROR:
+ /*
+ * HB failure notification, ignore.
+ */
+ break;
+ default:
+ bfa_sm_fault(ioc, event);
+ }
+}
+
+/**
+ * BFA IOC private functions
+ */
+
+static void
+bfa_ioc_disable_comp(struct bfa_ioc *ioc)
+{
+ struct list_head *qe;
+ struct bfa_ioc_hbfail_notify *notify;
+
+ ioc->cbfn->disable_cbfn(ioc->bfa);
+
+ /**
+ * Notify common modules registered for notification.
+ */
+ list_for_each(qe, &ioc->hb_notify_q) {
+ notify = (struct bfa_ioc_hbfail_notify *) qe;
+ notify->cbfn(notify->cbarg);
+ }
+}
+
+void
+bfa_nw_ioc_sem_timeout(void *ioc_arg)
+{
+ struct bfa_ioc *ioc = (struct bfa_ioc *) ioc_arg;
+
+ bfa_ioc_hw_sem_get(ioc);
+}
+
+bool
+bfa_nw_ioc_sem_get(void __iomem *sem_reg)
+{
+ u32 r32;
+ int cnt = 0;
+#define BFA_SEM_SPINCNT 3000
+
+ r32 = readl(sem_reg);
+
+ while (r32 && (cnt < BFA_SEM_SPINCNT)) {
+ cnt++;
+ udelay(2);
+ r32 = readl(sem_reg);
+ }
+
+ if (r32 == 0)
+ return true;
+
+ BUG_ON(!(cnt < BFA_SEM_SPINCNT));
+ return false;
+}
+
+void
+bfa_nw_ioc_sem_release(void __iomem *sem_reg)
+{
+ writel(1, sem_reg);
+}
+
+static void
+bfa_ioc_hw_sem_get(struct bfa_ioc *ioc)
+{
+ u32 r32;
+
+ /**
+ * First read to the semaphore register will return 0, subsequent reads
+ * will return 1. Semaphore is released by writing 1 to the register
+ */
+ r32 = readl(ioc->ioc_regs.ioc_sem_reg);
+ if (r32 == 0) {
+ bfa_fsm_send_event(ioc, IOC_E_SEMLOCKED);
+ return;
+ }
+
+ mod_timer(&ioc->sem_timer, jiffies +
+ msecs_to_jiffies(BFA_IOC_HWSEM_TOV));
+}
+
+void
+bfa_nw_ioc_hw_sem_release(struct bfa_ioc *ioc)
+{
+ writel(1, ioc->ioc_regs.ioc_sem_reg);
+}
+
+static void
+bfa_ioc_hw_sem_get_cancel(struct bfa_ioc *ioc)
+{
+ del_timer(&ioc->sem_timer);
+}
+
+/**
+ * @brief
+ * Initialize LPU local memory (aka secondary memory / SRAM)
+ */
+static void
+bfa_ioc_lmem_init(struct bfa_ioc *ioc)
+{
+ u32 pss_ctl;
+ int i;
+#define PSS_LMEM_INIT_TIME 10000
+
+ pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);
+ pss_ctl &= ~__PSS_LMEM_RESET;
+ pss_ctl |= __PSS_LMEM_INIT_EN;
+
+ /*
+ * i2c workaround 12.5khz clock
+ */
+ pss_ctl |= __PSS_I2C_CLK_DIV(3UL);
+ writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);
+
+ /**
+ * wait for memory initialization to be complete
+ */
+ i = 0;
+ do {
+ pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);
+ i++;
+ } while (!(pss_ctl & __PSS_LMEM_INIT_DONE) && (i < PSS_LMEM_INIT_TIME));
+
+ /**
+ * If memory initialization is not successful, IOC timeout will catch
+ * such failures.
+ */
+ BUG_ON(!(pss_ctl & __PSS_LMEM_INIT_DONE));
+
+ pss_ctl &= ~(__PSS_LMEM_INIT_DONE | __PSS_LMEM_INIT_EN);
+ writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);
+}
+
+static void
+bfa_ioc_lpu_start(struct bfa_ioc *ioc)
+{
+ u32 pss_ctl;
+
+ /**
+ * Take processor out of reset.
+ */
+ pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);
+ pss_ctl &= ~__PSS_LPU0_RESET;
+
+ writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);
+}
+
+static void
+bfa_ioc_lpu_stop(struct bfa_ioc *ioc)
+{
+ u32 pss_ctl;
+
+ /**
+ * Put processors in reset.
+ */
+ pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);
+ pss_ctl |= (__PSS_LPU0_RESET | __PSS_LPU1_RESET);
+
+ writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);
+}
+
+/**
+ * Get driver and firmware versions.
+ */
+void
+bfa_nw_ioc_fwver_get(struct bfa_ioc *ioc, struct bfi_ioc_image_hdr *fwhdr)
+{
+ u32 pgnum, pgoff;
+ u32 loff = 0;
+ int i;
+ u32 *fwsig = (u32 *) fwhdr;
+
+ pgnum = bfa_ioc_smem_pgnum(ioc, loff);
+ pgoff = bfa_ioc_smem_pgoff(ioc, loff);
+ writel(pgnum, ioc->ioc_regs.host_page_num_fn);
+
+ for (i = 0; i < (sizeof(struct bfi_ioc_image_hdr) / sizeof(u32));
+ i++) {
+ fwsig[i] =
+ swab32(readl((loff) + (ioc->ioc_regs.smem_page_start)));
+ loff += sizeof(u32);
+ }
+}
+
+/**
+ * Returns TRUE if same.
+ */
+bool
+bfa_nw_ioc_fwver_cmp(struct bfa_ioc *ioc, struct bfi_ioc_image_hdr *fwhdr)
+{
+ struct bfi_ioc_image_hdr *drv_fwhdr;
+ int i;
+
+ drv_fwhdr = (struct bfi_ioc_image_hdr *)
+ bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0);
+
+ for (i = 0; i < BFI_IOC_MD5SUM_SZ; i++) {
+ if (fwhdr->md5sum[i] != drv_fwhdr->md5sum[i])
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Return true if current running version is valid. Firmware signature and
+ * execution context (driver/bios) must match.
+ */
+static bool
+bfa_ioc_fwver_valid(struct bfa_ioc *ioc)
+{
+ struct bfi_ioc_image_hdr fwhdr, *drv_fwhdr;
+
+ /**
+ * If bios/efi boot (flash based) -- return true
+ */
+ if (bfa_ioc_is_optrom(ioc))
+ return true;
+
+ bfa_nw_ioc_fwver_get(ioc, &fwhdr);
+ drv_fwhdr = (struct bfi_ioc_image_hdr *)
+ bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0);
+
+ if (fwhdr.signature != drv_fwhdr->signature)
+ return false;
+
+ if (fwhdr.exec != drv_fwhdr->exec)
+ return false;
+
+ return bfa_nw_ioc_fwver_cmp(ioc, &fwhdr);
+}
+
+/**
+ * Conditionally flush any pending message from firmware at start.
+ */
+static void
+bfa_ioc_msgflush(struct bfa_ioc *ioc)
+{
+ u32 r32;
+
+ r32 = readl(ioc->ioc_regs.lpu_mbox_cmd);
+ if (r32)
+ writel(1, ioc->ioc_regs.lpu_mbox_cmd);
+}
+
+/**
+ * @img ioc_init_logic.jpg
+ */
+static void
+bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force)
+{
+ enum bfi_ioc_state ioc_fwstate;
+ bool fwvalid;
+
+ ioc_fwstate = readl(ioc->ioc_regs.ioc_fwstate);
+
+ if (force)
+ ioc_fwstate = BFI_IOC_UNINIT;
+
+ /**
+ * check if firmware is valid
+ */
+ fwvalid = (ioc_fwstate == BFI_IOC_UNINIT) ?
+ false : bfa_ioc_fwver_valid(ioc);
+
+ if (!fwvalid) {
+ bfa_ioc_boot(ioc, BFI_BOOT_TYPE_NORMAL, ioc->pcidev.device_id);
+ return;
+ }
+
+ /**
+ * If hardware initialization is in progress (initialized by other IOC),
+ * just wait for an initialization completion interrupt.
+ */
+ if (ioc_fwstate == BFI_IOC_INITING) {
+ ioc->cbfn->reset_cbfn(ioc->bfa);
+ return;
+ }
+
+ /**
+ * If IOC function is disabled and firmware version is same,
+ * just re-enable IOC.
+ *
+ * If option rom, IOC must not be in operational state. With
+ * convergence, IOC will be in operational state when 2nd driver
+ * is loaded.
+ */
+ if (ioc_fwstate == BFI_IOC_DISABLED ||
+ (!bfa_ioc_is_optrom(ioc) && ioc_fwstate == BFI_IOC_OP)) {
+ /**
+ * When using MSI-X any pending firmware ready event should
+ * be flushed. Otherwise MSI-X interrupts are not delivered.
+ */
+ bfa_ioc_msgflush(ioc);
+ ioc->cbfn->reset_cbfn(ioc->bfa);
+ bfa_fsm_send_event(ioc, IOC_E_FWREADY);
+ return;
+ }
+
+ /**
+ * Initialize the h/w for any other states.
+ */
+ bfa_ioc_boot(ioc, BFI_BOOT_TYPE_NORMAL, ioc->pcidev.device_id);
+}
+
+void
+bfa_nw_ioc_timeout(void *ioc_arg)
+{
+ struct bfa_ioc *ioc = (struct bfa_ioc *) ioc_arg;
+
+ bfa_fsm_send_event(ioc, IOC_E_TIMEOUT);
+}
+
+static void
+bfa_ioc_mbox_send(struct bfa_ioc *ioc, void *ioc_msg, int len)
+{
+ u32 *msgp = (u32 *) ioc_msg;
+ u32 i;
+
+ BUG_ON(!(len <= BFI_IOC_MSGLEN_MAX));
+
+ /*
+ * first write msg to mailbox registers
+ */
+ for (i = 0; i < len / sizeof(u32); i++)
+ writel(cpu_to_le32(msgp[i]),
+ ioc->ioc_regs.hfn_mbox + i * sizeof(u32));
+
+ for (; i < BFI_IOC_MSGLEN_MAX / sizeof(u32); i++)
+ writel(0, ioc->ioc_regs.hfn_mbox + i * sizeof(u32));
+
+ /*
+ * write 1 to mailbox CMD to trigger LPU event
+ */
+ writel(1, ioc->ioc_regs.hfn_mbox_cmd);
+ (void) readl(ioc->ioc_regs.hfn_mbox_cmd);
+}
+
+static void
+bfa_ioc_send_enable(struct bfa_ioc *ioc)
+{
+ struct bfi_ioc_ctrl_req enable_req;
+ struct timeval tv;
+
+ bfi_h2i_set(enable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_ENABLE_REQ,
+ bfa_ioc_portid(ioc));
+ enable_req.ioc_class = ioc->ioc_mc;
+ do_gettimeofday(&tv);
+ enable_req.tv_sec = ntohl(tv.tv_sec);
+ bfa_ioc_mbox_send(ioc, &enable_req, sizeof(struct bfi_ioc_ctrl_req));
+}
+
+static void
+bfa_ioc_send_disable(struct bfa_ioc *ioc)
+{
+ struct bfi_ioc_ctrl_req disable_req;
+
+ bfi_h2i_set(disable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_DISABLE_REQ,
+ bfa_ioc_portid(ioc));
+ bfa_ioc_mbox_send(ioc, &disable_req, sizeof(struct bfi_ioc_ctrl_req));
+}
+
+static void
+bfa_ioc_send_getattr(struct bfa_ioc *ioc)
+{
+ struct bfi_ioc_getattr_req attr_req;
+
+ bfi_h2i_set(attr_req.mh, BFI_MC_IOC, BFI_IOC_H2I_GETATTR_REQ,
+ bfa_ioc_portid(ioc));
+ bfa_dma_be_addr_set(attr_req.attr_addr, ioc->attr_dma.pa);
+ bfa_ioc_mbox_send(ioc, &attr_req, sizeof(attr_req));
+}
+
+void
+bfa_nw_ioc_hb_check(void *cbarg)
+{
+ struct bfa_ioc *ioc = cbarg;
+ u32 hb_count;
+
+ hb_count = readl(ioc->ioc_regs.heartbeat);
+ if (ioc->hb_count == hb_count) {
+ pr_crit("Firmware heartbeat failure at %d", hb_count);
+ bfa_ioc_recover(ioc);
+ return;
+ } else {
+ ioc->hb_count = hb_count;
+ }
+
+ bfa_ioc_mbox_poll(ioc);
+ mod_timer(&ioc->hb_timer, jiffies +
+ msecs_to_jiffies(BFA_IOC_HB_TOV));
+}
+
+static void
+bfa_ioc_hb_monitor(struct bfa_ioc *ioc)
+{
+ ioc->hb_count = readl(ioc->ioc_regs.heartbeat);
+ mod_timer(&ioc->hb_timer, jiffies +
+ msecs_to_jiffies(BFA_IOC_HB_TOV));
+}
+
+static void
+bfa_ioc_hb_stop(struct bfa_ioc *ioc)
+{
+ del_timer(&ioc->hb_timer);
+}
+
+/**
+ * @brief
+ * Initiate a full firmware download.
+ */
+static void
+bfa_ioc_download_fw(struct bfa_ioc *ioc, u32 boot_type,
+ u32 boot_param)
+{
+ u32 *fwimg;
+ u32 pgnum, pgoff;
+ u32 loff = 0;
+ u32 chunkno = 0;
+ u32 i;
+
+ /**
+ * Initialize LMEM first before code download
+ */
+ bfa_ioc_lmem_init(ioc);
+
+ /**
+ * Flash based firmware boot
+ */
+ if (bfa_ioc_is_optrom(ioc))
+ boot_type = BFI_BOOT_TYPE_FLASH;
+ fwimg = bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), chunkno);
+
+ pgnum = bfa_ioc_smem_pgnum(ioc, loff);
+ pgoff = bfa_ioc_smem_pgoff(ioc, loff);
+
+ writel(pgnum, ioc->ioc_regs.host_page_num_fn);
+
+ for (i = 0; i < bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)); i++) {
+ if (BFA_IOC_FLASH_CHUNK_NO(i) != chunkno) {
+ chunkno = BFA_IOC_FLASH_CHUNK_NO(i);
+ fwimg = bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc),
+ BFA_IOC_FLASH_CHUNK_ADDR(chunkno));
+ }
+
+ /**
+ * write smem
+ */
+ writel((swab32(fwimg[BFA_IOC_FLASH_OFFSET_IN_CHUNK(i)])),
+ ((ioc->ioc_regs.smem_page_start) + (loff)));
+
+ loff += sizeof(u32);
+
+ /**
+ * handle page offset wrap around
+ */
+ loff = PSS_SMEM_PGOFF(loff);
+ if (loff == 0) {
+ pgnum++;
+ writel(pgnum,
+ ioc->ioc_regs.host_page_num_fn);
+ }
+ }
+
+ writel(bfa_ioc_smem_pgnum(ioc, 0),
+ ioc->ioc_regs.host_page_num_fn);
+
+ /*
+ * Set boot type and boot param at the end.
+ */
+ writel((swab32(swab32(boot_type))), ((ioc->ioc_regs.smem_page_start)
+ + (BFI_BOOT_TYPE_OFF)));
+ writel((swab32(swab32(boot_param))), ((ioc->ioc_regs.smem_page_start)
+ + (BFI_BOOT_PARAM_OFF)));
+}
+
+static void
+bfa_ioc_reset(struct bfa_ioc *ioc, bool force)
+{
+ bfa_ioc_hwinit(ioc, force);
+}
+
+/**
+ * @brief
+ * Update BFA configuration from firmware configuration.
+ */
+static void
+bfa_ioc_getattr_reply(struct bfa_ioc *ioc)
+{
+ struct bfi_ioc_attr *attr = ioc->attr;
+
+ attr->adapter_prop = ntohl(attr->adapter_prop);
+ attr->card_type = ntohl(attr->card_type);
+ attr->maxfrsize = ntohs(attr->maxfrsize);
+
+ bfa_fsm_send_event(ioc, IOC_E_FWRSP_GETATTR);
+}
+
+/**
+ * Attach time initialization of mbox logic.
+ */
+static void
+bfa_ioc_mbox_attach(struct bfa_ioc *ioc)
+{
+ struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;
+ int mc;
+
+ INIT_LIST_HEAD(&mod->cmd_q);
+ for (mc = 0; mc < BFI_MC_MAX; mc++) {
+ mod->mbhdlr[mc].cbfn = NULL;
+ mod->mbhdlr[mc].cbarg = ioc->bfa;
+ }
+}
+
+/**
+ * Mbox poll timer -- restarts any pending mailbox requests.
+ */
+static void
+bfa_ioc_mbox_poll(struct bfa_ioc *ioc)
+{
+ struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;
+ struct bfa_mbox_cmd *cmd;
+ u32 stat;
+
+ /**
+ * If no command pending, do nothing
+ */
+ if (list_empty(&mod->cmd_q))
+ return;
+
+ /**
+ * If previous command is not yet fetched by firmware, do nothing
+ */
+ stat = readl(ioc->ioc_regs.hfn_mbox_cmd);
+ if (stat)
+ return;
+
+ /**
+ * Enqueue command to firmware.
+ */
+ bfa_q_deq(&mod->cmd_q, &cmd);
+ bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg));
+}
+
+/**
+ * Cleanup any pending requests.
+ */
+static void
+bfa_ioc_mbox_hbfail(struct bfa_ioc *ioc)
+{
+ struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;
+ struct bfa_mbox_cmd *cmd;
+
+ while (!list_empty(&mod->cmd_q))
+ bfa_q_deq(&mod->cmd_q, &cmd);
+}
+
+/**
+ * IOC public
+ */
+static enum bfa_status
+bfa_ioc_pll_init(struct bfa_ioc *ioc)
+{
+ /*
+ * Hold semaphore so that nobody can access the chip during init.
+ */
+ bfa_nw_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg);
+
+ bfa_ioc_pll_init_asic(ioc);
+
+ ioc->pllinit = true;
+ /*
+ * release semaphore.
+ */
+ bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_init_sem_reg);
+
+ return BFA_STATUS_OK;
+}
+
+/**
+ * Interface used by diag module to do firmware boot with memory test
+ * as the entry vector.
+ */
+static void
+bfa_ioc_boot(struct bfa_ioc *ioc, u32 boot_type, u32 boot_param)
+{
+ void __iomem *rb;
+
+ bfa_ioc_stats(ioc, ioc_boots);
+
+ if (bfa_ioc_pll_init(ioc) != BFA_STATUS_OK)
+ return;
+
+ /**
+ * Initialize IOC state of all functions on a chip reset.
+ */
+ rb = ioc->pcidev.pci_bar_kva;
+ if (boot_param == BFI_BOOT_TYPE_MEMTEST) {
+ writel(BFI_IOC_MEMTEST, (rb + BFA_IOC0_STATE_REG));
+ writel(BFI_IOC_MEMTEST, (rb + BFA_IOC1_STATE_REG));
+ } else {
+ writel(BFI_IOC_INITING, (rb + BFA_IOC0_STATE_REG));
+ writel(BFI_IOC_INITING, (rb + BFA_IOC1_STATE_REG));
+ }
+
+ bfa_ioc_msgflush(ioc);
+ bfa_ioc_download_fw(ioc, boot_type, boot_param);
+
+ /**
+ * Enable interrupts just before starting LPU
+ */
+ ioc->cbfn->reset_cbfn(ioc->bfa);
+ bfa_ioc_lpu_start(ioc);
+}
+
+/**
+ * Enable/disable IOC failure auto recovery.
+ */
+void
+bfa_nw_ioc_auto_recover(bool auto_recover)
+{
+ bfa_nw_auto_recover = auto_recover;
+}
+
+static void
+bfa_ioc_msgget(struct bfa_ioc *ioc, void *mbmsg)
+{
+ u32 *msgp = mbmsg;
+ u32 r32;
+ int i;
+
+ /**
+ * read the MBOX msg
+ */
+ for (i = 0; i < (sizeof(union bfi_ioc_i2h_msg_u) / sizeof(u32));
+ i++) {
+ r32 = readl(ioc->ioc_regs.lpu_mbox +
+ i * sizeof(u32));
+ msgp[i] = htonl(r32);
+ }
+
+ /**
+ * turn off mailbox interrupt by clearing mailbox status
+ */
+ writel(1, ioc->ioc_regs.lpu_mbox_cmd);
+ readl(ioc->ioc_regs.lpu_mbox_cmd);
+}
+
+static void
+bfa_ioc_isr(struct bfa_ioc *ioc, struct bfi_mbmsg *m)
+{
+ union bfi_ioc_i2h_msg_u *msg;
+
+ msg = (union bfi_ioc_i2h_msg_u *) m;
+
+ bfa_ioc_stats(ioc, ioc_isrs);
+
+ switch (msg->mh.msg_id) {
+ case BFI_IOC_I2H_HBEAT:
+ break;
+
+ case BFI_IOC_I2H_READY_EVENT:
+ bfa_fsm_send_event(ioc, IOC_E_FWREADY);
+ break;
+
+ case BFI_IOC_I2H_ENABLE_REPLY:
+ bfa_fsm_send_event(ioc, IOC_E_FWRSP_ENABLE);
+ break;
+
+ case BFI_IOC_I2H_DISABLE_REPLY:
+ bfa_fsm_send_event(ioc, IOC_E_FWRSP_DISABLE);
+ break;
+
+ case BFI_IOC_I2H_GETATTR_REPLY:
+ bfa_ioc_getattr_reply(ioc);
+ break;
+
+ default:
+ BUG_ON(1);
+ }
+}
+
+/**
+ * IOC attach time initialization and setup.
+ *
+ * @param[in] ioc memory for IOC
+ * @param[in] bfa driver instance structure
+ */
+void
+bfa_nw_ioc_attach(struct bfa_ioc *ioc, void *bfa, struct bfa_ioc_cbfn *cbfn)
+{
+ ioc->bfa = bfa;
+ ioc->cbfn = cbfn;
+ ioc->fcmode = false;
+ ioc->pllinit = false;
+ ioc->dbg_fwsave_once = true;
+
+ bfa_ioc_mbox_attach(ioc);
+ INIT_LIST_HEAD(&ioc->hb_notify_q);
+
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
+}
+
+/**
+ * Driver detach time IOC cleanup.
+ */
+void
+bfa_nw_ioc_detach(struct bfa_ioc *ioc)
+{
+ bfa_fsm_send_event(ioc, IOC_E_DETACH);
+}
+
+/**
+ * Setup IOC PCI properties.
+ *
+ * @param[in] pcidev PCI device information for this IOC
+ */
+void
+bfa_nw_ioc_pci_init(struct bfa_ioc *ioc, struct bfa_pcidev *pcidev,
+ enum bfi_mclass mc)
+{
+ ioc->ioc_mc = mc;
+ ioc->pcidev = *pcidev;
+ ioc->ctdev = bfa_asic_id_ct(ioc->pcidev.device_id);
+ ioc->cna = ioc->ctdev && !ioc->fcmode;
+
+ bfa_nw_ioc_set_ct_hwif(ioc);
+
+ bfa_ioc_map_port(ioc);
+ bfa_ioc_reg_init(ioc);
+}
+
+/**
+ * Initialize IOC dma memory
+ *
+ * @param[in] dm_kva kernel virtual address of IOC dma memory
+ * @param[in] dm_pa physical address of IOC dma memory
+ */
+void
+bfa_nw_ioc_mem_claim(struct bfa_ioc *ioc, u8 *dm_kva, u64 dm_pa)
+{
+ /**
+ * dma memory for firmware attribute
+ */
+ ioc->attr_dma.kva = dm_kva;
+ ioc->attr_dma.pa = dm_pa;
+ ioc->attr = (struct bfi_ioc_attr *) dm_kva;
+}
+
+/**
+ * Return size of dma memory required.
+ */
+u32
+bfa_nw_ioc_meminfo(void)
+{
+ return roundup(sizeof(struct bfi_ioc_attr), BFA_DMA_ALIGN_SZ);
+}
+
+void
+bfa_nw_ioc_enable(struct bfa_ioc *ioc)
+{
+ bfa_ioc_stats(ioc, ioc_enables);
+ ioc->dbg_fwsave_once = true;
+
+ bfa_fsm_send_event(ioc, IOC_E_ENABLE);
+}
+
+void
+bfa_nw_ioc_disable(struct bfa_ioc *ioc)
+{
+ bfa_ioc_stats(ioc, ioc_disables);
+ bfa_fsm_send_event(ioc, IOC_E_DISABLE);
+}
+
+static u32
+bfa_ioc_smem_pgnum(struct bfa_ioc *ioc, u32 fmaddr)
+{
+ return PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, fmaddr);
+}
+
+static u32
+bfa_ioc_smem_pgoff(struct bfa_ioc *ioc, u32 fmaddr)
+{
+ return PSS_SMEM_PGOFF(fmaddr);
+}
+
+/**
+ * Register mailbox message handler function, to be called by common modules
+ */
+void
+bfa_nw_ioc_mbox_regisr(struct bfa_ioc *ioc, enum bfi_mclass mc,
+ bfa_ioc_mbox_mcfunc_t cbfn, void *cbarg)
+{
+ struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;
+
+ mod->mbhdlr[mc].cbfn = cbfn;
+ mod->mbhdlr[mc].cbarg = cbarg;
+}
+
+/**
+ * Queue a mailbox command request to firmware. Waits if mailbox is busy.
+ * Responsibility of caller to serialize
+ *
+ * @param[in] ioc IOC instance
+ * @param[i] cmd Mailbox command
+ */
+void
+bfa_nw_ioc_mbox_queue(struct bfa_ioc *ioc, struct bfa_mbox_cmd *cmd)
+{
+ struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;
+ u32 stat;
+
+ /**
+ * If a previous command is pending, queue new command
+ */
+ if (!list_empty(&mod->cmd_q)) {
+ list_add_tail(&cmd->qe, &mod->cmd_q);
+ return;
+ }
+
+ /**
+ * If mailbox is busy, queue command for poll timer
+ */
+ stat = readl(ioc->ioc_regs.hfn_mbox_cmd);
+ if (stat) {
+ list_add_tail(&cmd->qe, &mod->cmd_q);
+ return;
+ }
+
+ /**
+ * mailbox is free -- queue command to firmware
+ */
+ bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg));
+}
+
+/**
+ * Handle mailbox interrupts
+ */
+void
+bfa_nw_ioc_mbox_isr(struct bfa_ioc *ioc)
+{
+ struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;
+ struct bfi_mbmsg m;
+ int mc;
+
+ bfa_ioc_msgget(ioc, &m);
+
+ /**
+ * Treat IOC message class as special.
+ */
+ mc = m.mh.msg_class;
+ if (mc == BFI_MC_IOC) {
+ bfa_ioc_isr(ioc, &m);
+ return;
+ }
+
+ if ((mc >= BFI_MC_MAX) || (mod->mbhdlr[mc].cbfn == NULL))
+ return;
+
+ mod->mbhdlr[mc].cbfn(mod->mbhdlr[mc].cbarg, &m);
+}
+
+void
+bfa_nw_ioc_error_isr(struct bfa_ioc *ioc)
+{
+ bfa_fsm_send_event(ioc, IOC_E_HWERROR);
+}
+
+/**
+ * Add to IOC heartbeat failure notification queue. To be used by common
+ * modules such as cee, port, diag.
+ */
+void
+bfa_nw_ioc_hbfail_register(struct bfa_ioc *ioc,
+ struct bfa_ioc_hbfail_notify *notify)
+{
+ list_add_tail(&notify->qe, &ioc->hb_notify_q);
+}
+
+#define BFA_MFG_NAME "Brocade"
+static void
+bfa_ioc_get_adapter_attr(struct bfa_ioc *ioc,
+ struct bfa_adapter_attr *ad_attr)
+{
+ struct bfi_ioc_attr *ioc_attr;
+
+ ioc_attr = ioc->attr;
+
+ bfa_ioc_get_adapter_serial_num(ioc, ad_attr->serial_num);
+ bfa_ioc_get_adapter_fw_ver(ioc, ad_attr->fw_ver);
+ bfa_ioc_get_adapter_optrom_ver(ioc, ad_attr->optrom_ver);
+ bfa_ioc_get_adapter_manufacturer(ioc, ad_attr->manufacturer);
+ memcpy(&ad_attr->vpd, &ioc_attr->vpd,
+ sizeof(struct bfa_mfg_vpd));
+
+ ad_attr->nports = bfa_ioc_get_nports(ioc);
+ ad_attr->max_speed = bfa_ioc_speed_sup(ioc);
+
+ bfa_ioc_get_adapter_model(ioc, ad_attr->model);
+ /* For now, model descr uses same model string */
+ bfa_ioc_get_adapter_model(ioc, ad_attr->model_descr);
+
+ ad_attr->card_type = ioc_attr->card_type;
+ ad_attr->is_mezz = bfa_mfg_is_mezz(ioc_attr->card_type);
+
+ if (BFI_ADAPTER_IS_SPECIAL(ioc_attr->adapter_prop))
+ ad_attr->prototype = 1;
+ else
+ ad_attr->prototype = 0;
+
+ ad_attr->pwwn = bfa_ioc_get_pwwn(ioc);
+ ad_attr->mac = bfa_nw_ioc_get_mac(ioc);
+
+ ad_attr->pcie_gen = ioc_attr->pcie_gen;
+ ad_attr->pcie_lanes = ioc_attr->pcie_lanes;
+ ad_attr->pcie_lanes_orig = ioc_attr->pcie_lanes_orig;
+ ad_attr->asic_rev = ioc_attr->asic_rev;
+
+ bfa_ioc_get_pci_chip_rev(ioc, ad_attr->hw_ver);
+
+ ad_attr->cna_capable = ioc->cna;
+ ad_attr->trunk_capable = (ad_attr->nports > 1) && !ioc->cna;
+}
+
+static enum bfa_ioc_type
+bfa_ioc_get_type(struct bfa_ioc *ioc)
+{
+ if (!ioc->ctdev || ioc->fcmode)
+ return BFA_IOC_TYPE_FC;
+ else if (ioc->ioc_mc == BFI_MC_IOCFC)
+ return BFA_IOC_TYPE_FCoE;
+ else if (ioc->ioc_mc == BFI_MC_LL)
+ return BFA_IOC_TYPE_LL;
+ else {
+ BUG_ON(!(ioc->ioc_mc == BFI_MC_LL));
+ return BFA_IOC_TYPE_LL;
+ }
+}
+
+static void
+bfa_ioc_get_adapter_serial_num(struct bfa_ioc *ioc, char *serial_num)
+{
+ memset(serial_num, 0, BFA_ADAPTER_SERIAL_NUM_LEN);
+ memcpy(serial_num,
+ (void *)ioc->attr->brcd_serialnum,
+ BFA_ADAPTER_SERIAL_NUM_LEN);
+}
+
+static void
+bfa_ioc_get_adapter_fw_ver(struct bfa_ioc *ioc, char *fw_ver)
+{
+ memset(fw_ver, 0, BFA_VERSION_LEN);
+ memcpy(fw_ver, ioc->attr->fw_version, BFA_VERSION_LEN);
+}
+
+static void
+bfa_ioc_get_pci_chip_rev(struct bfa_ioc *ioc, char *chip_rev)
+{
+ BUG_ON(!(chip_rev));
+
+ memset(chip_rev, 0, BFA_IOC_CHIP_REV_LEN);
+
+ chip_rev[0] = 'R';
+ chip_rev[1] = 'e';
+ chip_rev[2] = 'v';
+ chip_rev[3] = '-';
+ chip_rev[4] = ioc->attr->asic_rev;
+ chip_rev[5] = '\0';
+}
+
+static void
+bfa_ioc_get_adapter_optrom_ver(struct bfa_ioc *ioc, char *optrom_ver)
+{
+ memset(optrom_ver, 0, BFA_VERSION_LEN);
+ memcpy(optrom_ver, ioc->attr->optrom_version,
+ BFA_VERSION_LEN);
+}
+
+static void
+bfa_ioc_get_adapter_manufacturer(struct bfa_ioc *ioc, char *manufacturer)
+{
+ memset(manufacturer, 0, BFA_ADAPTER_MFG_NAME_LEN);
+ memcpy(manufacturer, BFA_MFG_NAME, BFA_ADAPTER_MFG_NAME_LEN);
+}
+
+static void
+bfa_ioc_get_adapter_model(struct bfa_ioc *ioc, char *model)
+{
+ struct bfi_ioc_attr *ioc_attr;
+
+ BUG_ON(!(model));
+ memset(model, 0, BFA_ADAPTER_MODEL_NAME_LEN);
+
+ ioc_attr = ioc->attr;
+
+ /**
+ * model name
+ */
+ snprintf(model, BFA_ADAPTER_MODEL_NAME_LEN, "%s-%u",
+ BFA_MFG_NAME, ioc_attr->card_type);
+}
+
+static enum bfa_ioc_state
+bfa_ioc_get_state(struct bfa_ioc *ioc)
+{
+ return bfa_sm_to_state(ioc_sm_table, ioc->fsm);
+}
+
+void
+bfa_nw_ioc_get_attr(struct bfa_ioc *ioc, struct bfa_ioc_attr *ioc_attr)
+{
+ memset((void *)ioc_attr, 0, sizeof(struct bfa_ioc_attr));
+
+ ioc_attr->state = bfa_ioc_get_state(ioc);
+ ioc_attr->port_id = ioc->port_id;
+
+ ioc_attr->ioc_type = bfa_ioc_get_type(ioc);
+
+ bfa_ioc_get_adapter_attr(ioc, &ioc_attr->adapter_attr);
+
+ ioc_attr->pci_attr.device_id = ioc->pcidev.device_id;
+ ioc_attr->pci_attr.pcifn = ioc->pcidev.pci_func;
+ bfa_ioc_get_pci_chip_rev(ioc, ioc_attr->pci_attr.chip_rev);
+}
+
+/**
+ * WWN public
+ */
+static u64
+bfa_ioc_get_pwwn(struct bfa_ioc *ioc)
+{
+ return ioc->attr->pwwn;
+}
+
+mac_t
+bfa_nw_ioc_get_mac(struct bfa_ioc *ioc)
+{
+ /*
+ * Currently mfg mac is used as FCoE enode mac (not configured by PBC)
+ */
+ if (bfa_ioc_get_type(ioc) == BFA_IOC_TYPE_FCoE)
+ return bfa_ioc_get_mfg_mac(ioc);
+ else
+ return ioc->attr->mac;
+}
+
+static mac_t
+bfa_ioc_get_mfg_mac(struct bfa_ioc *ioc)
+{
+ mac_t m;
+
+ m = ioc->attr->mfg_mac;
+ if (bfa_mfg_is_old_wwn_mac_model(ioc->attr->card_type))
+ m.mac[MAC_ADDRLEN - 1] += bfa_ioc_pcifn(ioc);
+ else
+ bfa_mfg_increment_wwn_mac(&(m.mac[MAC_ADDRLEN-3]),
+ bfa_ioc_pcifn(ioc));
+
+ return m;
+}
+
+/**
+ * Firmware failure detected. Start recovery actions.
+ */
+static void
+bfa_ioc_recover(struct bfa_ioc *ioc)
+{
+ bfa_ioc_stats(ioc, ioc_hbfails);
+ bfa_fsm_send_event(ioc, IOC_E_HBFAIL);
+}
+
+static void
+bfa_ioc_check_attr_wwns(struct bfa_ioc *ioc)
+{
+ if (bfa_ioc_get_type(ioc) == BFA_IOC_TYPE_LL)
+ return;
+
+}
diff --git a/drivers/net/bna/bfa_ioc.h b/drivers/net/bna/bfa_ioc.h
new file mode 100644
index 000000000000..a73d84ec808c
--- /dev/null
+++ b/drivers/net/bna/bfa_ioc.h
@@ -0,0 +1,300 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+
+#ifndef __BFA_IOC_H__
+#define __BFA_IOC_H__
+
+#include "bfa_sm.h"
+#include "bfi.h"
+#include "cna.h"
+
+#define BFA_IOC_TOV 3000 /* msecs */
+#define BFA_IOC_HWSEM_TOV 500 /* msecs */
+#define BFA_IOC_HB_TOV 500 /* msecs */
+#define BFA_IOC_HWINIT_MAX 2
+#define BFA_IOC_TOV_RECOVER BFA_IOC_HB_TOV
+
+/**
+ * Generic Scatter Gather Element used by driver
+ */
+struct bfa_sge {
+ u32 sg_len;
+ void *sg_addr;
+};
+
+/**
+ * PCI device information required by IOC
+ */
+struct bfa_pcidev {
+ int pci_slot;
+ u8 pci_func;
+ u16 device_id;
+ void __iomem *pci_bar_kva;
+};
+
+/**
+ * Structure used to remember the DMA-able memory block's KVA and Physical
+ * Address
+ */
+struct bfa_dma {
+ void *kva; /* ! Kernel virtual address */
+ u64 pa; /* ! Physical address */
+};
+
+#define BFA_DMA_ALIGN_SZ 256
+
+/**
+ * smem size for Crossbow and Catapult
+ */
+#define BFI_SMEM_CB_SIZE 0x200000U /* ! 2MB for crossbow */
+#define BFI_SMEM_CT_SIZE 0x280000U /* ! 2.5MB for catapult */
+
+/**
+ * @brief BFA dma address assignment macro
+ */
+#define bfa_dma_addr_set(dma_addr, pa) \
+ __bfa_dma_addr_set(&dma_addr, (u64)pa)
+
+static inline void
+__bfa_dma_addr_set(union bfi_addr_u *dma_addr, u64 pa)
+{
+ dma_addr->a32.addr_lo = (u32) pa;
+ dma_addr->a32.addr_hi = (u32) (upper_32_bits(pa));
+}
+
+/**
+ * @brief BFA dma address assignment macro. (big endian format)
+ */
+#define bfa_dma_be_addr_set(dma_addr, pa) \
+ __bfa_dma_be_addr_set(&dma_addr, (u64)pa)
+static inline void
+__bfa_dma_be_addr_set(union bfi_addr_u *dma_addr, u64 pa)
+{
+ dma_addr->a32.addr_lo = (u32) htonl(pa);
+ dma_addr->a32.addr_hi = (u32) htonl(upper_32_bits(pa));
+}
+
+struct bfa_ioc_regs {
+ void __iomem *hfn_mbox_cmd;
+ void __iomem *hfn_mbox;
+ void __iomem *lpu_mbox_cmd;
+ void __iomem *lpu_mbox;
+ void __iomem *pss_ctl_reg;
+ void __iomem *pss_err_status_reg;
+ void __iomem *app_pll_fast_ctl_reg;
+ void __iomem *app_pll_slow_ctl_reg;
+ void __iomem *ioc_sem_reg;
+ void __iomem *ioc_usage_sem_reg;
+ void __iomem *ioc_init_sem_reg;
+ void __iomem *ioc_usage_reg;
+ void __iomem *host_page_num_fn;
+ void __iomem *heartbeat;
+ void __iomem *ioc_fwstate;
+ void __iomem *ll_halt;
+ void __iomem *err_set;
+ void __iomem *shirq_isr_next;
+ void __iomem *shirq_msk_next;
+ void __iomem *smem_page_start;
+ u32 smem_pg0;
+};
+
+/**
+ * IOC Mailbox structures
+ */
+struct bfa_mbox_cmd {
+ struct list_head qe;
+ u32 msg[BFI_IOC_MSGSZ];
+};
+
+/**
+ * IOC mailbox module
+ */
+typedef void (*bfa_ioc_mbox_mcfunc_t)(void *cbarg, struct bfi_mbmsg *m);
+struct bfa_ioc_mbox_mod {
+ struct list_head cmd_q; /*!< pending mbox queue */
+ int nmclass; /*!< number of handlers */
+ struct {
+ bfa_ioc_mbox_mcfunc_t cbfn; /*!< message handlers */
+ void *cbarg;
+ } mbhdlr[BFI_MC_MAX];
+};
+
+/**
+ * IOC callback function interfaces
+ */
+typedef void (*bfa_ioc_enable_cbfn_t)(void *bfa, enum bfa_status status);
+typedef void (*bfa_ioc_disable_cbfn_t)(void *bfa);
+typedef void (*bfa_ioc_hbfail_cbfn_t)(void *bfa);
+typedef void (*bfa_ioc_reset_cbfn_t)(void *bfa);
+struct bfa_ioc_cbfn {
+ bfa_ioc_enable_cbfn_t enable_cbfn;
+ bfa_ioc_disable_cbfn_t disable_cbfn;
+ bfa_ioc_hbfail_cbfn_t hbfail_cbfn;
+ bfa_ioc_reset_cbfn_t reset_cbfn;
+};
+
+/**
+ * Heartbeat failure notification queue element.
+ */
+struct bfa_ioc_hbfail_notify {
+ struct list_head qe;
+ bfa_ioc_hbfail_cbfn_t cbfn;
+ void *cbarg;
+};
+
+/**
+ * Initialize a heartbeat failure notification structure
+ */
+#define bfa_ioc_hbfail_init(__notify, __cbfn, __cbarg) do { \
+ (__notify)->cbfn = (__cbfn); \
+ (__notify)->cbarg = (__cbarg); \
+} while (0)
+
+struct bfa_ioc {
+ bfa_fsm_t fsm;
+ struct bfa *bfa;
+ struct bfa_pcidev pcidev;
+ struct bfa_timer_mod *timer_mod;
+ struct timer_list ioc_timer;
+ struct timer_list sem_timer;
+ struct timer_list hb_timer;
+ u32 hb_count;
+ u32 retry_count;
+ struct list_head hb_notify_q;
+ void *dbg_fwsave;
+ int dbg_fwsave_len;
+ bool dbg_fwsave_once;
+ enum bfi_mclass ioc_mc;
+ struct bfa_ioc_regs ioc_regs;
+ struct bfa_ioc_drv_stats stats;
+ bool auto_recover;
+ bool fcmode;
+ bool ctdev;
+ bool cna;
+ bool pllinit;
+ bool stats_busy; /*!< outstanding stats */
+ u8 port_id;
+
+ struct bfa_dma attr_dma;
+ struct bfi_ioc_attr *attr;
+ struct bfa_ioc_cbfn *cbfn;
+ struct bfa_ioc_mbox_mod mbox_mod;
+ struct bfa_ioc_hwif *ioc_hwif;
+};
+
+struct bfa_ioc_hwif {
+ enum bfa_status (*ioc_pll_init) (void __iomem *rb, bool fcmode);
+ bool (*ioc_firmware_lock) (struct bfa_ioc *ioc);
+ void (*ioc_firmware_unlock) (struct bfa_ioc *ioc);
+ void (*ioc_reg_init) (struct bfa_ioc *ioc);
+ void (*ioc_map_port) (struct bfa_ioc *ioc);
+ void (*ioc_isr_mode_set) (struct bfa_ioc *ioc,
+ bool msix);
+ void (*ioc_notify_hbfail) (struct bfa_ioc *ioc);
+ void (*ioc_ownership_reset) (struct bfa_ioc *ioc);
+};
+
+#define bfa_ioc_pcifn(__ioc) ((__ioc)->pcidev.pci_func)
+#define bfa_ioc_devid(__ioc) ((__ioc)->pcidev.device_id)
+#define bfa_ioc_bar0(__ioc) ((__ioc)->pcidev.pci_bar_kva)
+#define bfa_ioc_portid(__ioc) ((__ioc)->port_id)
+#define bfa_ioc_fetch_stats(__ioc, __stats) \
+ (((__stats)->drv_stats) = (__ioc)->stats)
+#define bfa_ioc_clr_stats(__ioc) \
+ memset(&(__ioc)->stats, 0, sizeof((__ioc)->stats))
+#define bfa_ioc_maxfrsize(__ioc) ((__ioc)->attr->maxfrsize)
+#define bfa_ioc_rx_bbcredit(__ioc) ((__ioc)->attr->rx_bbcredit)
+#define bfa_ioc_speed_sup(__ioc) \
+ BFI_ADAPTER_GETP(SPEED, (__ioc)->attr->adapter_prop)
+#define bfa_ioc_get_nports(__ioc) \
+ BFI_ADAPTER_GETP(NPORTS, (__ioc)->attr->adapter_prop)
+
+#define bfa_ioc_stats(_ioc, _stats) ((_ioc)->stats._stats++)
+#define BFA_IOC_FWIMG_MINSZ (16 * 1024)
+#define BFA_IOC_FWIMG_TYPE(__ioc) \
+ (((__ioc)->ctdev) ? \
+ (((__ioc)->fcmode) ? BFI_IMAGE_CT_FC : BFI_IMAGE_CT_CNA) : \
+ BFI_IMAGE_CB_FC)
+#define BFA_IOC_FW_SMEM_SIZE(__ioc) \
+ (((__ioc)->ctdev) ? BFI_SMEM_CT_SIZE : BFI_SMEM_CB_SIZE)
+#define BFA_IOC_FLASH_CHUNK_NO(off) (off / BFI_FLASH_CHUNK_SZ_WORDS)
+#define BFA_IOC_FLASH_OFFSET_IN_CHUNK(off) (off % BFI_FLASH_CHUNK_SZ_WORDS)
+#define BFA_IOC_FLASH_CHUNK_ADDR(chunkno) (chunkno * BFI_FLASH_CHUNK_SZ_WORDS)
+
+/**
+ * IOC mailbox interface
+ */
+void bfa_nw_ioc_mbox_queue(struct bfa_ioc *ioc, struct bfa_mbox_cmd *cmd);
+void bfa_nw_ioc_mbox_isr(struct bfa_ioc *ioc);
+void bfa_nw_ioc_mbox_regisr(struct bfa_ioc *ioc, enum bfi_mclass mc,
+ bfa_ioc_mbox_mcfunc_t cbfn, void *cbarg);
+
+/**
+ * IOC interfaces
+ */
+
+#define bfa_ioc_pll_init_asic(__ioc) \
+ ((__ioc)->ioc_hwif->ioc_pll_init((__ioc)->pcidev.pci_bar_kva, \
+ (__ioc)->fcmode))
+
+#define bfa_ioc_isr_mode_set(__ioc, __msix) \
+ ((__ioc)->ioc_hwif->ioc_isr_mode_set(__ioc, __msix))
+#define bfa_ioc_ownership_reset(__ioc) \
+ ((__ioc)->ioc_hwif->ioc_ownership_reset(__ioc))
+
+void bfa_nw_ioc_set_ct_hwif(struct bfa_ioc *ioc);
+
+void bfa_nw_ioc_attach(struct bfa_ioc *ioc, void *bfa,
+ struct bfa_ioc_cbfn *cbfn);
+void bfa_nw_ioc_auto_recover(bool auto_recover);
+void bfa_nw_ioc_detach(struct bfa_ioc *ioc);
+void bfa_nw_ioc_pci_init(struct bfa_ioc *ioc, struct bfa_pcidev *pcidev,
+ enum bfi_mclass mc);
+u32 bfa_nw_ioc_meminfo(void);
+void bfa_nw_ioc_mem_claim(struct bfa_ioc *ioc, u8 *dm_kva, u64 dm_pa);
+void bfa_nw_ioc_enable(struct bfa_ioc *ioc);
+void bfa_nw_ioc_disable(struct bfa_ioc *ioc);
+
+void bfa_nw_ioc_error_isr(struct bfa_ioc *ioc);
+
+void bfa_nw_ioc_get_attr(struct bfa_ioc *ioc, struct bfa_ioc_attr *ioc_attr);
+void bfa_nw_ioc_hbfail_register(struct bfa_ioc *ioc,
+ struct bfa_ioc_hbfail_notify *notify);
+bool bfa_nw_ioc_sem_get(void __iomem *sem_reg);
+void bfa_nw_ioc_sem_release(void __iomem *sem_reg);
+void bfa_nw_ioc_hw_sem_release(struct bfa_ioc *ioc);
+void bfa_nw_ioc_fwver_get(struct bfa_ioc *ioc,
+ struct bfi_ioc_image_hdr *fwhdr);
+bool bfa_nw_ioc_fwver_cmp(struct bfa_ioc *ioc,
+ struct bfi_ioc_image_hdr *fwhdr);
+mac_t bfa_nw_ioc_get_mac(struct bfa_ioc *ioc);
+
+/*
+ * Timeout APIs
+ */
+void bfa_nw_ioc_timeout(void *ioc);
+void bfa_nw_ioc_hb_check(void *ioc);
+void bfa_nw_ioc_sem_timeout(void *ioc);
+
+/*
+ * F/W Image Size & Chunk
+ */
+u32 *bfa_cb_image_get_chunk(int type, u32 off);
+u32 bfa_cb_image_get_size(int type);
+
+#endif /* __BFA_IOC_H__ */
diff --git a/drivers/net/bna/bfa_ioc_ct.c b/drivers/net/bna/bfa_ioc_ct.c
new file mode 100644
index 000000000000..121cfd6d48b1
--- /dev/null
+++ b/drivers/net/bna/bfa_ioc_ct.c
@@ -0,0 +1,392 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+
+#include "bfa_ioc.h"
+#include "cna.h"
+#include "bfi.h"
+#include "bfi_ctreg.h"
+#include "bfa_defs.h"
+
+/*
+ * forward declarations
+ */
+static bool bfa_ioc_ct_firmware_lock(struct bfa_ioc *ioc);
+static void bfa_ioc_ct_firmware_unlock(struct bfa_ioc *ioc);
+static void bfa_ioc_ct_reg_init(struct bfa_ioc *ioc);
+static void bfa_ioc_ct_map_port(struct bfa_ioc *ioc);
+static void bfa_ioc_ct_isr_mode_set(struct bfa_ioc *ioc, bool msix);
+static void bfa_ioc_ct_notify_hbfail(struct bfa_ioc *ioc);
+static void bfa_ioc_ct_ownership_reset(struct bfa_ioc *ioc);
+static enum bfa_status bfa_ioc_ct_pll_init(void __iomem *rb, bool fcmode);
+
+static struct bfa_ioc_hwif nw_hwif_ct;
+
+/**
+ * Called from bfa_ioc_attach() to map asic specific calls.
+ */
+void
+bfa_nw_ioc_set_ct_hwif(struct bfa_ioc *ioc)
+{
+ nw_hwif_ct.ioc_pll_init = bfa_ioc_ct_pll_init;
+ nw_hwif_ct.ioc_firmware_lock = bfa_ioc_ct_firmware_lock;
+ nw_hwif_ct.ioc_firmware_unlock = bfa_ioc_ct_firmware_unlock;
+ nw_hwif_ct.ioc_reg_init = bfa_ioc_ct_reg_init;
+ nw_hwif_ct.ioc_map_port = bfa_ioc_ct_map_port;
+ nw_hwif_ct.ioc_isr_mode_set = bfa_ioc_ct_isr_mode_set;
+ nw_hwif_ct.ioc_notify_hbfail = bfa_ioc_ct_notify_hbfail;
+ nw_hwif_ct.ioc_ownership_reset = bfa_ioc_ct_ownership_reset;
+
+ ioc->ioc_hwif = &nw_hwif_ct;
+}
+
+/**
+ * Return true if firmware of current driver matches the running firmware.
+ */
+static bool
+bfa_ioc_ct_firmware_lock(struct bfa_ioc *ioc)
+{
+ enum bfi_ioc_state ioc_fwstate;
+ u32 usecnt;
+ struct bfi_ioc_image_hdr fwhdr;
+
+ /**
+ * Firmware match check is relevant only for CNA.
+ */
+ if (!ioc->cna)
+ return true;
+
+ /**
+ * If bios boot (flash based) -- do not increment usage count
+ */
+ if (bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)) <
+ BFA_IOC_FWIMG_MINSZ)
+ return true;
+
+ bfa_nw_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);
+ usecnt = readl(ioc->ioc_regs.ioc_usage_reg);
+
+ /**
+ * If usage count is 0, always return TRUE.
+ */
+ if (usecnt == 0) {
+ writel(1, ioc->ioc_regs.ioc_usage_reg);
+ bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg);
+ return true;
+ }
+
+ ioc_fwstate = readl(ioc->ioc_regs.ioc_fwstate);
+
+ /**
+ * Use count cannot be non-zero and chip in uninitialized state.
+ */
+ BUG_ON(!(ioc_fwstate != BFI_IOC_UNINIT));
+
+ /**
+ * Check if another driver with a different firmware is active
+ */
+ bfa_nw_ioc_fwver_get(ioc, &fwhdr);
+ if (!bfa_nw_ioc_fwver_cmp(ioc, &fwhdr)) {
+ bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg);
+ return false;
+ }
+
+ /**
+ * Same firmware version. Increment the reference count.
+ */
+ usecnt++;
+ writel(usecnt, ioc->ioc_regs.ioc_usage_reg);
+ bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg);
+ return true;
+}
+
+static void
+bfa_ioc_ct_firmware_unlock(struct bfa_ioc *ioc)
+{
+ u32 usecnt;
+
+ /**
+ * Firmware lock is relevant only for CNA.
+ */
+ if (!ioc->cna)
+ return;
+
+ /**
+ * If bios boot (flash based) -- do not decrement usage count
+ */
+ if (bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)) <
+ BFA_IOC_FWIMG_MINSZ)
+ return;
+
+ /**
+ * decrement usage count
+ */
+ bfa_nw_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);
+ usecnt = readl(ioc->ioc_regs.ioc_usage_reg);
+ BUG_ON(!(usecnt > 0));
+
+ usecnt--;
+ writel(usecnt, ioc->ioc_regs.ioc_usage_reg);
+
+ bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg);
+}
+
+/**
+ * Notify other functions on HB failure.
+ */
+static void
+bfa_ioc_ct_notify_hbfail(struct bfa_ioc *ioc)
+{
+ if (ioc->cna) {
+ writel(__FW_INIT_HALT_P, ioc->ioc_regs.ll_halt);
+ /* Wait for halt to take effect */
+ readl(ioc->ioc_regs.ll_halt);
+ } else {
+ writel(__PSS_ERR_STATUS_SET, ioc->ioc_regs.err_set);
+ readl(ioc->ioc_regs.err_set);
+ }
+}
+
+/**
+ * Host to LPU mailbox message addresses
+ */
+static struct { u32 hfn_mbox, lpu_mbox, hfn_pgn; } iocreg_fnreg[] = {
+ { HOSTFN0_LPU_MBOX0_0, LPU_HOSTFN0_MBOX0_0, HOST_PAGE_NUM_FN0 },
+ { HOSTFN1_LPU_MBOX0_8, LPU_HOSTFN1_MBOX0_8, HOST_PAGE_NUM_FN1 },
+ { HOSTFN2_LPU_MBOX0_0, LPU_HOSTFN2_MBOX0_0, HOST_PAGE_NUM_FN2 },
+ { HOSTFN3_LPU_MBOX0_8, LPU_HOSTFN3_MBOX0_8, HOST_PAGE_NUM_FN3 }
+};
+
+/**
+ * Host <-> LPU mailbox command/status registers - port 0
+ */
+static struct { u32 hfn, lpu; } iocreg_mbcmd_p0[] = {
+ { HOSTFN0_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN0_MBOX0_CMD_STAT },
+ { HOSTFN1_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN1_MBOX0_CMD_STAT },
+ { HOSTFN2_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN2_MBOX0_CMD_STAT },
+ { HOSTFN3_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN3_MBOX0_CMD_STAT }
+};
+
+/**
+ * Host <-> LPU mailbox command/status registers - port 1
+ */
+static struct { u32 hfn, lpu; } iocreg_mbcmd_p1[] = {
+ { HOSTFN0_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN0_MBOX0_CMD_STAT },
+ { HOSTFN1_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN1_MBOX0_CMD_STAT },
+ { HOSTFN2_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN2_MBOX0_CMD_STAT },
+ { HOSTFN3_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN3_MBOX0_CMD_STAT }
+};
+
+static void
+bfa_ioc_ct_reg_init(struct bfa_ioc *ioc)
+{
+ void __iomem *rb;
+ int pcifn = bfa_ioc_pcifn(ioc);
+
+ rb = bfa_ioc_bar0(ioc);
+
+ ioc->ioc_regs.hfn_mbox = rb + iocreg_fnreg[pcifn].hfn_mbox;
+ ioc->ioc_regs.lpu_mbox = rb + iocreg_fnreg[pcifn].lpu_mbox;
+ ioc->ioc_regs.host_page_num_fn = rb + iocreg_fnreg[pcifn].hfn_pgn;
+
+ if (ioc->port_id == 0) {
+ ioc->ioc_regs.heartbeat = rb + BFA_IOC0_HBEAT_REG;
+ ioc->ioc_regs.ioc_fwstate = rb + BFA_IOC0_STATE_REG;
+ ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd_p0[pcifn].hfn;
+ ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd_p0[pcifn].lpu;
+ ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P0;
+ } else {
+ ioc->ioc_regs.heartbeat = (rb + BFA_IOC1_HBEAT_REG);
+ ioc->ioc_regs.ioc_fwstate = (rb + BFA_IOC1_STATE_REG);
+ ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd_p1[pcifn].hfn;
+ ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd_p1[pcifn].lpu;
+ ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P1;
+ }
+
+ /*
+ * PSS control registers
+ */
+ ioc->ioc_regs.pss_ctl_reg = (rb + PSS_CTL_REG);
+ ioc->ioc_regs.pss_err_status_reg = (rb + PSS_ERR_STATUS_REG);
+ ioc->ioc_regs.app_pll_fast_ctl_reg = (rb + APP_PLL_425_CTL_REG);
+ ioc->ioc_regs.app_pll_slow_ctl_reg = (rb + APP_PLL_312_CTL_REG);
+
+ /*
+ * IOC semaphore registers and serialization
+ */
+ ioc->ioc_regs.ioc_sem_reg = (rb + HOST_SEM0_REG);
+ ioc->ioc_regs.ioc_usage_sem_reg = (rb + HOST_SEM1_REG);
+ ioc->ioc_regs.ioc_init_sem_reg = (rb + HOST_SEM2_REG);
+ ioc->ioc_regs.ioc_usage_reg = (rb + BFA_FW_USE_COUNT);
+
+ /**
+ * sram memory access
+ */
+ ioc->ioc_regs.smem_page_start = (rb + PSS_SMEM_PAGE_START);
+ ioc->ioc_regs.smem_pg0 = BFI_IOC_SMEM_PG0_CT;
+
+ /*
+ * err set reg : for notification of hb failure in fcmode
+ */
+ ioc->ioc_regs.err_set = (rb + ERR_SET_REG);
+}
+
+/**
+ * Initialize IOC to port mapping.
+ */
+
+#define FNC_PERS_FN_SHIFT(__fn) ((__fn) * 8)
+static void
+bfa_ioc_ct_map_port(struct bfa_ioc *ioc)
+{
+ void __iomem *rb = ioc->pcidev.pci_bar_kva;
+ u32 r32;
+
+ /**
+ * For catapult, base port id on personality register and IOC type
+ */
+ r32 = readl(rb + FNC_PERS_REG);
+ r32 >>= FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc));
+ ioc->port_id = (r32 & __F0_PORT_MAP_MK) >> __F0_PORT_MAP_SH;
+
+}
+
+/**
+ * Set interrupt mode for a function: INTX or MSIX
+ */
+static void
+bfa_ioc_ct_isr_mode_set(struct bfa_ioc *ioc, bool msix)
+{
+ void __iomem *rb = ioc->pcidev.pci_bar_kva;
+ u32 r32, mode;
+
+ r32 = readl(rb + FNC_PERS_REG);
+
+ mode = (r32 >> FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc))) &
+ __F0_INTX_STATUS;
+
+ /**
+ * If already in desired mode, do not change anything
+ */
+ if (!msix && mode)
+ return;
+
+ if (msix)
+ mode = __F0_INTX_STATUS_MSIX;
+ else
+ mode = __F0_INTX_STATUS_INTA;
+
+ r32 &= ~(__F0_INTX_STATUS << FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc)));
+ r32 |= (mode << FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc)));
+
+ writel(r32, rb + FNC_PERS_REG);
+}
+
+/**
+ * Cleanup hw semaphore and usecnt registers
+ */
+static void
+bfa_ioc_ct_ownership_reset(struct bfa_ioc *ioc)
+{
+ if (ioc->cna) {
+ bfa_nw_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);
+ writel(0, ioc->ioc_regs.ioc_usage_reg);
+ bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg);
+ }
+
+ /*
+ * Read the hw sem reg to make sure that it is locked
+ * before we clear it. If it is not locked, writing 1
+ * will lock it instead of clearing it.
+ */
+ readl(ioc->ioc_regs.ioc_sem_reg);
+ bfa_nw_ioc_hw_sem_release(ioc);
+}
+
+static enum bfa_status
+bfa_ioc_ct_pll_init(void __iomem *rb, bool fcmode)
+{
+ u32 pll_sclk, pll_fclk, r32;
+
+ pll_sclk = __APP_PLL_312_LRESETN | __APP_PLL_312_ENARST |
+ __APP_PLL_312_RSEL200500 | __APP_PLL_312_P0_1(3U) |
+ __APP_PLL_312_JITLMT0_1(3U) |
+ __APP_PLL_312_CNTLMT0_1(1U);
+ pll_fclk = __APP_PLL_425_LRESETN | __APP_PLL_425_ENARST |
+ __APP_PLL_425_RSEL200500 | __APP_PLL_425_P0_1(3U) |
+ __APP_PLL_425_JITLMT0_1(3U) |
+ __APP_PLL_425_CNTLMT0_1(1U);
+ if (fcmode) {
+ writel(0, (rb + OP_MODE));
+ writel(__APP_EMS_CMLCKSEL |
+ __APP_EMS_REFCKBUFEN2 |
+ __APP_EMS_CHANNEL_SEL,
+ (rb + ETH_MAC_SER_REG));
+ } else {
+ writel(__GLOBAL_FCOE_MODE, (rb + OP_MODE));
+ writel(__APP_EMS_REFCKBUFEN1,
+ (rb + ETH_MAC_SER_REG));
+ }
+ writel(BFI_IOC_UNINIT, (rb + BFA_IOC0_STATE_REG));
+ writel(BFI_IOC_UNINIT, (rb + BFA_IOC1_STATE_REG));
+ writel(0xffffffffU, (rb + HOSTFN0_INT_MSK));
+ writel(0xffffffffU, (rb + HOSTFN1_INT_MSK));
+ writel(0xffffffffU, (rb + HOSTFN0_INT_STATUS));
+ writel(0xffffffffU, (rb + HOSTFN1_INT_STATUS));
+ writel(0xffffffffU, (rb + HOSTFN0_INT_MSK));
+ writel(0xffffffffU, (rb + HOSTFN1_INT_MSK));
+ writel(pll_sclk |
+ __APP_PLL_312_LOGIC_SOFT_RESET,
+ rb + APP_PLL_312_CTL_REG);
+ writel(pll_fclk |
+ __APP_PLL_425_LOGIC_SOFT_RESET,
+ rb + APP_PLL_425_CTL_REG);
+ writel(pll_sclk |
+ __APP_PLL_312_LOGIC_SOFT_RESET | __APP_PLL_312_ENABLE,
+ rb + APP_PLL_312_CTL_REG);
+ writel(pll_fclk |
+ __APP_PLL_425_LOGIC_SOFT_RESET | __APP_PLL_425_ENABLE,
+ rb + APP_PLL_425_CTL_REG);
+ readl(rb + HOSTFN0_INT_MSK);
+ udelay(2000);
+ writel(0xffffffffU, (rb + HOSTFN0_INT_STATUS));
+ writel(0xffffffffU, (rb + HOSTFN1_INT_STATUS));
+ writel(pll_sclk |
+ __APP_PLL_312_ENABLE,
+ rb + APP_PLL_312_CTL_REG);
+ writel(pll_fclk |
+ __APP_PLL_425_ENABLE,
+ rb + APP_PLL_425_CTL_REG);
+ if (!fcmode) {
+ writel(__PMM_1T_RESET_P, (rb + PMM_1T_RESET_REG_P0));
+ writel(__PMM_1T_RESET_P, (rb + PMM_1T_RESET_REG_P1));
+ }
+ r32 = readl((rb + PSS_CTL_REG));
+ r32 &= ~__PSS_LMEM_RESET;
+ writel(r32, (rb + PSS_CTL_REG));
+ udelay(1000);
+ if (!fcmode) {
+ writel(0, (rb + PMM_1T_RESET_REG_P0));
+ writel(0, (rb + PMM_1T_RESET_REG_P1));
+ }
+
+ writel(__EDRAM_BISTR_START, (rb + MBIST_CTL_REG));
+ udelay(1000);
+ r32 = readl((rb + MBIST_STAT_REG));
+ writel(0, (rb + MBIST_CTL_REG));
+ return BFA_STATUS_OK;
+}
diff --git a/drivers/scsi/bfa/include/cs/bfa_sm.h b/drivers/net/bna/bfa_sm.h
index 11fba9082f05..46462c49b6f9 100644
--- a/drivers/scsi/bfa/include/cs/bfa_sm.h
+++ b/drivers/net/bna/bfa_sm.h
@@ -1,9 +1,5 @@
/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ * Linux network driver for Brocade Converged Network Adapter.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License (GPL) Version 2 as
@@ -14,22 +10,30 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
/**
- * bfasm.h State machine defines
+ * @file bfasm.h State machine defines
*/
#ifndef __BFA_SM_H__
#define __BFA_SM_H__
+#include "cna.h"
+
typedef void (*bfa_sm_t)(void *sm, int event);
+
/**
* oc - object class eg. bfa_ioc
* st - state, eg. reset
- * otype - object type, eg. struct bfa_ioc_s
+ * otype - object type, eg. struct bfa_ioc
* etype - object type, eg. enum ioc_event
*/
-#define bfa_sm_state_decl(oc, st, otype, etype) \
+#define bfa_sm_state_decl(oc, st, otype, etype) \
static void oc ## _sm_ ## st(otype * fsm, etype event)
#define bfa_sm_set_state(_sm, _state) ((_sm)->sm = (bfa_sm_t)(_state))
@@ -40,15 +44,13 @@ typedef void (*bfa_sm_t)(void *sm, int event);
/**
* For converting from state machine function to state encoding.
*/
-struct bfa_sm_table_s {
- bfa_sm_t sm; /* state machine function */
- int state; /* state machine encoding */
- char *name; /* state name for display */
+struct bfa_sm_table {
+ bfa_sm_t sm; /*!< state machine function */
+ int state; /*!< state machine encoding */
+ char *name; /*!< state name for display */
};
#define BFA_SM(_sm) ((bfa_sm_t)(_sm))
-int bfa_sm_to_state(struct bfa_sm_table_s *smt, bfa_sm_t sm);
-
/**
* State machine with entry actions.
*/
@@ -57,21 +59,30 @@ typedef void (*bfa_fsm_t)(void *fsm, int event);
/**
* oc - object class eg. bfa_ioc
* st - state, eg. reset
- * otype - object type, eg. struct bfa_ioc_s
+ * otype - object type, eg. struct bfa_ioc
* etype - object type, eg. enum ioc_event
*/
#define bfa_fsm_state_decl(oc, st, otype, etype) \
- static void oc ## _sm_ ## st(otype * fsm, etype event); \
+ static void oc ## _sm_ ## st(otype * fsm, etype event); \
static void oc ## _sm_ ## st ## _entry(otype * fsm)
#define bfa_fsm_set_state(_fsm, _state) do { \
- (_fsm)->fsm = (bfa_fsm_t)(_state); \
- _state ## _entry(_fsm); \
+ (_fsm)->fsm = (bfa_fsm_t)(_state); \
+ _state ## _entry(_fsm); \
} while (0)
-#define bfa_fsm_send_event(_fsm, _event) \
- ((_fsm)->fsm((_fsm), (_event)))
+#define bfa_fsm_send_event(_fsm, _event) ((_fsm)->fsm((_fsm), (_event)))
+#define bfa_fsm_get_state(_fsm) ((_fsm)->fsm)
#define bfa_fsm_cmp_state(_fsm, _state) \
((_fsm)->fsm == (bfa_fsm_t)(_state))
+static inline int
+bfa_sm_to_state(const struct bfa_sm_table *smt, bfa_sm_t sm)
+{
+ int i = 0;
+
+ while (smt[i].sm && smt[i].sm != sm)
+ i++;
+ return smt[i].state;
+}
#endif
diff --git a/drivers/scsi/bfa/include/cs/bfa_wc.h b/drivers/net/bna/bfa_wc.h
index 0460bd4fc7c4..d0e4caee67b0 100644
--- a/drivers/scsi/bfa/include/cs/bfa_wc.h
+++ b/drivers/net/bna/bfa_wc.h
@@ -1,9 +1,5 @@
/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ * Linux network driver for Brocade Converged Network Adapter.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License (GPL) Version 2 as
@@ -14,9 +10,14 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
/**
- * bfa_wc.h Generic wait counter.
+ * @file bfa_wc.h Generic wait counter.
*/
#ifndef __BFA_WC_H__
@@ -24,20 +25,20 @@
typedef void (*bfa_wc_resume_t) (void *cbarg);
-struct bfa_wc_s {
+struct bfa_wc {
bfa_wc_resume_t wc_resume;
void *wc_cbarg;
int wc_count;
};
static inline void
-bfa_wc_up(struct bfa_wc_s *wc)
+bfa_wc_up(struct bfa_wc *wc)
{
wc->wc_count++;
}
static inline void
-bfa_wc_down(struct bfa_wc_s *wc)
+bfa_wc_down(struct bfa_wc *wc)
{
wc->wc_count--;
if (wc->wc_count == 0)
@@ -48,7 +49,7 @@ bfa_wc_down(struct bfa_wc_s *wc)
* Initialize a waiting counter.
*/
static inline void
-bfa_wc_init(struct bfa_wc_s *wc, bfa_wc_resume_t wc_resume, void *wc_cbarg)
+bfa_wc_init(struct bfa_wc *wc, bfa_wc_resume_t wc_resume, void *wc_cbarg)
{
wc->wc_resume = wc_resume;
wc->wc_cbarg = wc_cbarg;
@@ -60,7 +61,7 @@ bfa_wc_init(struct bfa_wc_s *wc, bfa_wc_resume_t wc_resume, void *wc_cbarg)
* Wait for counter to reach zero
*/
static inline void
-bfa_wc_wait(struct bfa_wc_s *wc)
+bfa_wc_wait(struct bfa_wc *wc)
{
bfa_wc_down(wc);
}
diff --git a/drivers/net/bna/bfi.h b/drivers/net/bna/bfi.h
new file mode 100644
index 000000000000..a97396811050
--- /dev/null
+++ b/drivers/net/bna/bfi.h
@@ -0,0 +1,392 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+
+#ifndef __BFI_H__
+#define __BFI_H__
+
+#include "bfa_defs.h"
+
+#pragma pack(1)
+
+/**
+ * BFI FW image type
+ */
+#define BFI_FLASH_CHUNK_SZ 256 /*!< Flash chunk size */
+#define BFI_FLASH_CHUNK_SZ_WORDS (BFI_FLASH_CHUNK_SZ/sizeof(u32))
+enum {
+ BFI_IMAGE_CB_FC,
+ BFI_IMAGE_CT_FC,
+ BFI_IMAGE_CT_CNA,
+ BFI_IMAGE_MAX,
+};
+
+/**
+ * Msg header common to all msgs
+ */
+struct bfi_mhdr {
+ u8 msg_class; /*!< @ref enum bfi_mclass */
+ u8 msg_id; /*!< msg opcode with in the class */
+ union {
+ struct {
+ u8 rsvd;
+ u8 lpu_id; /*!< msg destination */
+ } h2i;
+ u16 i2htok; /*!< token in msgs to host */
+ } mtag;
+};
+
+#define bfi_h2i_set(_mh, _mc, _op, _lpuid) do { \
+ (_mh).msg_class = (_mc); \
+ (_mh).msg_id = (_op); \
+ (_mh).mtag.h2i.lpu_id = (_lpuid); \
+} while (0)
+
+#define bfi_i2h_set(_mh, _mc, _op, _i2htok) do { \
+ (_mh).msg_class = (_mc); \
+ (_mh).msg_id = (_op); \
+ (_mh).mtag.i2htok = (_i2htok); \
+} while (0)
+
+/*
+ * Message opcodes: 0-127 to firmware, 128-255 to host
+ */
+#define BFI_I2H_OPCODE_BASE 128
+#define BFA_I2HM(_x) ((_x) + BFI_I2H_OPCODE_BASE)
+
+/**
+ ****************************************************************************
+ *
+ * Scatter Gather Element and Page definition
+ *
+ ****************************************************************************
+ */
+
+#define BFI_SGE_INLINE 1
+#define BFI_SGE_INLINE_MAX (BFI_SGE_INLINE + 1)
+
+/**
+ * SG Flags
+ */
+enum {
+ BFI_SGE_DATA = 0, /*!< data address, not last */
+ BFI_SGE_DATA_CPL = 1, /*!< data addr, last in current page */
+ BFI_SGE_DATA_LAST = 3, /*!< data address, last */
+ BFI_SGE_LINK = 2, /*!< link address */
+ BFI_SGE_PGDLEN = 2, /*!< cumulative data length for page */
+};
+
+/**
+ * DMA addresses
+ */
+union bfi_addr_u {
+ struct {
+ u32 addr_lo;
+ u32 addr_hi;
+ } a32;
+};
+
+/**
+ * Scatter Gather Element
+ */
+struct bfi_sge {
+#ifdef __BIGENDIAN
+ u32 flags:2,
+ rsvd:2,
+ sg_len:28;
+#else
+ u32 sg_len:28,
+ rsvd:2,
+ flags:2;
+#endif
+ union bfi_addr_u sga;
+};
+
+/**
+ * Scatter Gather Page
+ */
+#define BFI_SGPG_DATA_SGES 7
+#define BFI_SGPG_SGES_MAX (BFI_SGPG_DATA_SGES + 1)
+#define BFI_SGPG_RSVD_WD_LEN 8
+struct bfi_sgpg {
+ struct bfi_sge sges[BFI_SGPG_SGES_MAX];
+ u32 rsvd[BFI_SGPG_RSVD_WD_LEN];
+};
+
+/*
+ * Large Message structure - 128 Bytes size Msgs
+ */
+#define BFI_LMSG_SZ 128
+#define BFI_LMSG_PL_WSZ \
+ ((BFI_LMSG_SZ - sizeof(struct bfi_mhdr)) / 4)
+
+struct bfi_msg {
+ struct bfi_mhdr mhdr;
+ u32 pl[BFI_LMSG_PL_WSZ];
+};
+
+/**
+ * Mailbox message structure
+ */
+#define BFI_MBMSG_SZ 7
+struct bfi_mbmsg {
+ struct bfi_mhdr mh;
+ u32 pl[BFI_MBMSG_SZ];
+};
+
+/**
+ * Message Classes
+ */
+enum bfi_mclass {
+ BFI_MC_IOC = 1, /*!< IO Controller (IOC) */
+ BFI_MC_DIAG = 2, /*!< Diagnostic Msgs */
+ BFI_MC_FLASH = 3, /*!< Flash message class */
+ BFI_MC_CEE = 4, /*!< CEE */
+ BFI_MC_FCPORT = 5, /*!< FC port */
+ BFI_MC_IOCFC = 6, /*!< FC - IO Controller (IOC) */
+ BFI_MC_LL = 7, /*!< Link Layer */
+ BFI_MC_UF = 8, /*!< Unsolicited frame receive */
+ BFI_MC_FCXP = 9, /*!< FC Transport */
+ BFI_MC_LPS = 10, /*!< lport fc login services */
+ BFI_MC_RPORT = 11, /*!< Remote port */
+ BFI_MC_ITNIM = 12, /*!< I-T nexus (Initiator mode) */
+ BFI_MC_IOIM_READ = 13, /*!< read IO (Initiator mode) */
+ BFI_MC_IOIM_WRITE = 14, /*!< write IO (Initiator mode) */
+ BFI_MC_IOIM_IO = 15, /*!< IO (Initiator mode) */
+ BFI_MC_IOIM = 16, /*!< IO (Initiator mode) */
+ BFI_MC_IOIM_IOCOM = 17, /*!< good IO completion */
+ BFI_MC_TSKIM = 18, /*!< Initiator Task management */
+ BFI_MC_SBOOT = 19, /*!< SAN boot services */
+ BFI_MC_IPFC = 20, /*!< IP over FC Msgs */
+ BFI_MC_PORT = 21, /*!< Physical port */
+ BFI_MC_SFP = 22, /*!< SFP module */
+ BFI_MC_MSGQ = 23, /*!< MSGQ */
+ BFI_MC_ENET = 24, /*!< ENET commands/responses */
+ BFI_MC_MAX = 32
+};
+
+#define BFI_IOC_MAX_CQS 4
+#define BFI_IOC_MAX_CQS_ASIC 8
+#define BFI_IOC_MSGLEN_MAX 32 /* 32 bytes */
+
+#define BFI_BOOT_TYPE_OFF 8
+#define BFI_BOOT_PARAM_OFF 12
+
+#define BFI_BOOT_TYPE_NORMAL 0 /* param is device id */
+#define BFI_BOOT_TYPE_FLASH 1
+#define BFI_BOOT_TYPE_MEMTEST 2
+
+#define BFI_BOOT_MEMTEST_RES_ADDR 0x900
+#define BFI_BOOT_MEMTEST_RES_SIG 0xA0A1A2A3
+
+/**
+ *----------------------------------------------------------------------
+ * IOC
+ *----------------------------------------------------------------------
+ */
+
+enum bfi_ioc_h2i_msgs {
+ BFI_IOC_H2I_ENABLE_REQ = 1,
+ BFI_IOC_H2I_DISABLE_REQ = 2,
+ BFI_IOC_H2I_GETATTR_REQ = 3,
+ BFI_IOC_H2I_DBG_SYNC = 4,
+ BFI_IOC_H2I_DBG_DUMP = 5,
+};
+
+enum bfi_ioc_i2h_msgs {
+ BFI_IOC_I2H_ENABLE_REPLY = BFA_I2HM(1),
+ BFI_IOC_I2H_DISABLE_REPLY = BFA_I2HM(2),
+ BFI_IOC_I2H_GETATTR_REPLY = BFA_I2HM(3),
+ BFI_IOC_I2H_READY_EVENT = BFA_I2HM(4),
+ BFI_IOC_I2H_HBEAT = BFA_I2HM(5),
+};
+
+/**
+ * BFI_IOC_H2I_GETATTR_REQ message
+ */
+struct bfi_ioc_getattr_req {
+ struct bfi_mhdr mh;
+ union bfi_addr_u attr_addr;
+};
+
+struct bfi_ioc_attr {
+ u64 mfg_pwwn; /*!< Mfg port wwn */
+ u64 mfg_nwwn; /*!< Mfg node wwn */
+ mac_t mfg_mac; /*!< Mfg mac */
+ u16 rsvd_a;
+ u64 pwwn;
+ u64 nwwn;
+ mac_t mac; /*!< PBC or Mfg mac */
+ u16 rsvd_b;
+ mac_t fcoe_mac;
+ u16 rsvd_c;
+ char brcd_serialnum[STRSZ(BFA_MFG_SERIALNUM_SIZE)];
+ u8 pcie_gen;
+ u8 pcie_lanes_orig;
+ u8 pcie_lanes;
+ u8 rx_bbcredit; /*!< receive buffer credits */
+ u32 adapter_prop; /*!< adapter properties */
+ u16 maxfrsize; /*!< max receive frame size */
+ char asic_rev;
+ u8 rsvd_d;
+ char fw_version[BFA_VERSION_LEN];
+ char optrom_version[BFA_VERSION_LEN];
+ struct bfa_mfg_vpd vpd;
+ u32 card_type; /*!< card type */
+};
+
+/**
+ * BFI_IOC_I2H_GETATTR_REPLY message
+ */
+struct bfi_ioc_getattr_reply {
+ struct bfi_mhdr mh; /*!< Common msg header */
+ u8 status; /*!< cfg reply status */
+ u8 rsvd[3];
+};
+
+/**
+ * Firmware memory page offsets
+ */
+#define BFI_IOC_SMEM_PG0_CB (0x40)
+#define BFI_IOC_SMEM_PG0_CT (0x180)
+
+/**
+ * Firmware statistic offset
+ */
+#define BFI_IOC_FWSTATS_OFF (0x6B40)
+#define BFI_IOC_FWSTATS_SZ (4096)
+
+/**
+ * Firmware trace offset
+ */
+#define BFI_IOC_TRC_OFF (0x4b00)
+#define BFI_IOC_TRC_ENTS 256
+
+#define BFI_IOC_FW_SIGNATURE (0xbfadbfad)
+#define BFI_IOC_MD5SUM_SZ 4
+struct bfi_ioc_image_hdr {
+ u32 signature; /*!< constant signature */
+ u32 rsvd_a;
+ u32 exec; /*!< exec vector */
+ u32 param; /*!< parameters */
+ u32 rsvd_b[4];
+ u32 md5sum[BFI_IOC_MD5SUM_SZ];
+};
+
+/**
+ * BFI_IOC_I2H_READY_EVENT message
+ */
+struct bfi_ioc_rdy_event {
+ struct bfi_mhdr mh; /*!< common msg header */
+ u8 init_status; /*!< init event status */
+ u8 rsvd[3];
+};
+
+struct bfi_ioc_hbeat {
+ struct bfi_mhdr mh; /*!< common msg header */
+ u32 hb_count; /*!< current heart beat count */
+};
+
+/**
+ * IOC hardware/firmware state
+ */
+enum bfi_ioc_state {
+ BFI_IOC_UNINIT = 0, /*!< not initialized */
+ BFI_IOC_INITING = 1, /*!< h/w is being initialized */
+ BFI_IOC_HWINIT = 2, /*!< h/w is initialized */
+ BFI_IOC_CFG = 3, /*!< IOC configuration in progress */
+ BFI_IOC_OP = 4, /*!< IOC is operational */
+ BFI_IOC_DISABLING = 5, /*!< IOC is being disabled */
+ BFI_IOC_DISABLED = 6, /*!< IOC is disabled */
+ BFI_IOC_CFG_DISABLED = 7, /*!< IOC is being disabled;transient */
+ BFI_IOC_FAIL = 8, /*!< IOC heart-beat failure */
+ BFI_IOC_MEMTEST = 9, /*!< IOC is doing memtest */
+};
+
+#define BFI_IOC_ENDIAN_SIG 0x12345678
+
+enum {
+ BFI_ADAPTER_TYPE_FC = 0x01, /*!< FC adapters */
+ BFI_ADAPTER_TYPE_MK = 0x0f0000, /*!< adapter type mask */
+ BFI_ADAPTER_TYPE_SH = 16, /*!< adapter type shift */
+ BFI_ADAPTER_NPORTS_MK = 0xff00, /*!< number of ports mask */
+ BFI_ADAPTER_NPORTS_SH = 8, /*!< number of ports shift */
+ BFI_ADAPTER_SPEED_MK = 0xff, /*!< adapter speed mask */
+ BFI_ADAPTER_SPEED_SH = 0, /*!< adapter speed shift */
+ BFI_ADAPTER_PROTO = 0x100000, /*!< prototype adapaters */
+ BFI_ADAPTER_TTV = 0x200000, /*!< TTV debug capable */
+ BFI_ADAPTER_UNSUPP = 0x400000, /*!< unknown adapter type */
+};
+
+#define BFI_ADAPTER_GETP(__prop, __adap_prop) \
+ (((__adap_prop) & BFI_ADAPTER_ ## __prop ## _MK) >> \
+ BFI_ADAPTER_ ## __prop ## _SH)
+#define BFI_ADAPTER_SETP(__prop, __val) \
+ ((__val) << BFI_ADAPTER_ ## __prop ## _SH)
+#define BFI_ADAPTER_IS_PROTO(__adap_type) \
+ ((__adap_type) & BFI_ADAPTER_PROTO)
+#define BFI_ADAPTER_IS_TTV(__adap_type) \
+ ((__adap_type) & BFI_ADAPTER_TTV)
+#define BFI_ADAPTER_IS_UNSUPP(__adap_type) \
+ ((__adap_type) & BFI_ADAPTER_UNSUPP)
+#define BFI_ADAPTER_IS_SPECIAL(__adap_type) \
+ ((__adap_type) & (BFI_ADAPTER_TTV | BFI_ADAPTER_PROTO | \
+ BFI_ADAPTER_UNSUPP))
+
+/**
+ * BFI_IOC_H2I_ENABLE_REQ & BFI_IOC_H2I_DISABLE_REQ messages
+ */
+struct bfi_ioc_ctrl_req {
+ struct bfi_mhdr mh;
+ u8 ioc_class;
+ u8 rsvd[3];
+ u32 tv_sec;
+};
+
+/**
+ * BFI_IOC_I2H_ENABLE_REPLY & BFI_IOC_I2H_DISABLE_REPLY messages
+ */
+struct bfi_ioc_ctrl_reply {
+ struct bfi_mhdr mh; /*!< Common msg header */
+ u8 status; /*!< enable/disable status */
+ u8 rsvd[3];
+};
+
+#define BFI_IOC_MSGSZ 8
+/**
+ * H2I Messages
+ */
+union bfi_ioc_h2i_msg_u {
+ struct bfi_mhdr mh;
+ struct bfi_ioc_ctrl_req enable_req;
+ struct bfi_ioc_ctrl_req disable_req;
+ struct bfi_ioc_getattr_req getattr_req;
+ u32 mboxmsg[BFI_IOC_MSGSZ];
+};
+
+/**
+ * I2H Messages
+ */
+union bfi_ioc_i2h_msg_u {
+ struct bfi_mhdr mh;
+ struct bfi_ioc_rdy_event rdy_event;
+ u32 mboxmsg[BFI_IOC_MSGSZ];
+};
+
+#pragma pack()
+
+#endif /* __BFI_H__ */
diff --git a/drivers/net/bna/bfi_cna.h b/drivers/net/bna/bfi_cna.h
new file mode 100644
index 000000000000..4eecabea397b
--- /dev/null
+++ b/drivers/net/bna/bfi_cna.h
@@ -0,0 +1,199 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+#ifndef __BFI_CNA_H__
+#define __BFI_CNA_H__
+
+#include "bfi.h"
+#include "bfa_defs_cna.h"
+
+#pragma pack(1)
+
+enum bfi_port_h2i {
+ BFI_PORT_H2I_ENABLE_REQ = (1),
+ BFI_PORT_H2I_DISABLE_REQ = (2),
+ BFI_PORT_H2I_GET_STATS_REQ = (3),
+ BFI_PORT_H2I_CLEAR_STATS_REQ = (4),
+};
+
+enum bfi_port_i2h {
+ BFI_PORT_I2H_ENABLE_RSP = BFA_I2HM(1),
+ BFI_PORT_I2H_DISABLE_RSP = BFA_I2HM(2),
+ BFI_PORT_I2H_GET_STATS_RSP = BFA_I2HM(3),
+ BFI_PORT_I2H_CLEAR_STATS_RSP = BFA_I2HM(4),
+};
+
+/**
+ * Generic REQ type
+ */
+struct bfi_port_generic_req {
+ struct bfi_mhdr mh; /*!< msg header */
+ u32 msgtag; /*!< msgtag for reply */
+ u32 rsvd;
+};
+
+/**
+ * Generic RSP type
+ */
+struct bfi_port_generic_rsp {
+ struct bfi_mhdr mh; /*!< common msg header */
+ u8 status; /*!< port enable status */
+ u8 rsvd[3];
+ u32 msgtag; /*!< msgtag for reply */
+};
+
+/**
+ * @todo
+ * BFI_PORT_H2I_ENABLE_REQ
+ */
+
+/**
+ * @todo
+ * BFI_PORT_I2H_ENABLE_RSP
+ */
+
+/**
+ * BFI_PORT_H2I_DISABLE_REQ
+ */
+
+/**
+ * BFI_PORT_I2H_DISABLE_RSP
+ */
+
+/**
+ * BFI_PORT_H2I_GET_STATS_REQ
+ */
+struct bfi_port_get_stats_req {
+ struct bfi_mhdr mh; /*!< common msg header */
+ union bfi_addr_u dma_addr;
+};
+
+/**
+ * BFI_PORT_I2H_GET_STATS_RSP
+ */
+
+/**
+ * BFI_PORT_H2I_CLEAR_STATS_REQ
+ */
+
+/**
+ * BFI_PORT_I2H_CLEAR_STATS_RSP
+ */
+
+union bfi_port_h2i_msg_u {
+ struct bfi_mhdr mh;
+ struct bfi_port_generic_req enable_req;
+ struct bfi_port_generic_req disable_req;
+ struct bfi_port_get_stats_req getstats_req;
+ struct bfi_port_generic_req clearstats_req;
+};
+
+union bfi_port_i2h_msg_u {
+ struct bfi_mhdr mh;
+ struct bfi_port_generic_rsp enable_rsp;
+ struct bfi_port_generic_rsp disable_rsp;
+ struct bfi_port_generic_rsp getstats_rsp;
+ struct bfi_port_generic_rsp clearstats_rsp;
+};
+
+/* @brief Mailbox commands from host to (DCBX/LLDP) firmware */
+enum bfi_cee_h2i_msgs {
+ BFI_CEE_H2I_GET_CFG_REQ = 1,
+ BFI_CEE_H2I_RESET_STATS = 2,
+ BFI_CEE_H2I_GET_STATS_REQ = 3,
+};
+
+/* @brief Mailbox reply and AEN messages from DCBX/LLDP firmware to host */
+enum bfi_cee_i2h_msgs {
+ BFI_CEE_I2H_GET_CFG_RSP = BFA_I2HM(1),
+ BFI_CEE_I2H_RESET_STATS_RSP = BFA_I2HM(2),
+ BFI_CEE_I2H_GET_STATS_RSP = BFA_I2HM(3),
+};
+
+/* Data structures */
+
+/*
+ * @brief H2I command structure for resetting the stats.
+ * BFI_CEE_H2I_RESET_STATS
+ */
+struct bfi_lldp_reset_stats {
+ struct bfi_mhdr mh;
+};
+
+/*
+ * @brief H2I command structure for resetting the stats.
+ * BFI_CEE_H2I_RESET_STATS
+ */
+struct bfi_cee_reset_stats {
+ struct bfi_mhdr mh;
+};
+
+/*
+ * @brief get configuration command from host
+ * BFI_CEE_H2I_GET_CFG_REQ
+ */
+struct bfi_cee_get_req {
+ struct bfi_mhdr mh;
+ union bfi_addr_u dma_addr;
+};
+
+/*
+ * @brief reply message from firmware
+ * BFI_CEE_I2H_GET_CFG_RSP
+ */
+struct bfi_cee_get_rsp {
+ struct bfi_mhdr mh;
+ u8 cmd_status;
+ u8 rsvd[3];
+};
+
+/*
+ * @brief get configuration command from host
+ * BFI_CEE_H2I_GET_STATS_REQ
+ */
+struct bfi_cee_stats_req {
+ struct bfi_mhdr mh;
+ union bfi_addr_u dma_addr;
+};
+
+/*
+ * @brief reply message from firmware
+ * BFI_CEE_I2H_GET_STATS_RSP
+ */
+struct bfi_cee_stats_rsp {
+ struct bfi_mhdr mh;
+ u8 cmd_status;
+ u8 rsvd[3];
+};
+
+/* @brief mailbox command structures from host to firmware */
+union bfi_cee_h2i_msg_u {
+ struct bfi_mhdr mh;
+ struct bfi_cee_get_req get_req;
+ struct bfi_cee_stats_req stats_req;
+};
+
+/* @brief mailbox message structures from firmware to host */
+union bfi_cee_i2h_msg_u {
+ struct bfi_mhdr mh;
+ struct bfi_cee_get_rsp get_rsp;
+ struct bfi_cee_stats_rsp stats_rsp;
+};
+
+#pragma pack()
+
+#endif /* __BFI_CNA_H__ */
diff --git a/drivers/net/bna/bfi_ctreg.h b/drivers/net/bna/bfi_ctreg.h
new file mode 100644
index 000000000000..404ea351d4a1
--- /dev/null
+++ b/drivers/net/bna/bfi_ctreg.h
@@ -0,0 +1,637 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+
+/*
+ * bfi_ctreg.h catapult host block register definitions
+ *
+ * !!! Do not edit. Auto generated. !!!
+ */
+
+#ifndef __BFI_CTREG_H__
+#define __BFI_CTREG_H__
+
+#define HOSTFN0_LPU_MBOX0_0 0x00019200
+#define HOSTFN1_LPU_MBOX0_8 0x00019260
+#define LPU_HOSTFN0_MBOX0_0 0x00019280
+#define LPU_HOSTFN1_MBOX0_8 0x000192e0
+#define HOSTFN2_LPU_MBOX0_0 0x00019400
+#define HOSTFN3_LPU_MBOX0_8 0x00019460
+#define LPU_HOSTFN2_MBOX0_0 0x00019480
+#define LPU_HOSTFN3_MBOX0_8 0x000194e0
+#define HOSTFN0_INT_STATUS 0x00014000
+#define __HOSTFN0_HALT_OCCURRED 0x01000000
+#define __HOSTFN0_INT_STATUS_LVL_MK 0x00f00000
+#define __HOSTFN0_INT_STATUS_LVL_SH 20
+#define __HOSTFN0_INT_STATUS_LVL(_v) ((_v) << __HOSTFN0_INT_STATUS_LVL_SH)
+#define __HOSTFN0_INT_STATUS_P_MK 0x000f0000
+#define __HOSTFN0_INT_STATUS_P_SH 16
+#define __HOSTFN0_INT_STATUS_P(_v) ((_v) << __HOSTFN0_INT_STATUS_P_SH)
+#define __HOSTFN0_INT_STATUS_F 0x0000ffff
+#define HOSTFN0_INT_MSK 0x00014004
+#define HOST_PAGE_NUM_FN0 0x00014008
+#define __HOST_PAGE_NUM_FN 0x000001ff
+#define HOST_MSIX_ERR_INDEX_FN0 0x0001400c
+#define __MSIX_ERR_INDEX_FN 0x000001ff
+#define HOSTFN1_INT_STATUS 0x00014100
+#define __HOSTFN1_HALT_OCCURRED 0x01000000
+#define __HOSTFN1_INT_STATUS_LVL_MK 0x00f00000
+#define __HOSTFN1_INT_STATUS_LVL_SH 20
+#define __HOSTFN1_INT_STATUS_LVL(_v) ((_v) << __HOSTFN1_INT_STATUS_LVL_SH)
+#define __HOSTFN1_INT_STATUS_P_MK 0x000f0000
+#define __HOSTFN1_INT_STATUS_P_SH 16
+#define __HOSTFN1_INT_STATUS_P(_v) ((_v) << __HOSTFN1_INT_STATUS_P_SH)
+#define __HOSTFN1_INT_STATUS_F 0x0000ffff
+#define HOSTFN1_INT_MSK 0x00014104
+#define HOST_PAGE_NUM_FN1 0x00014108
+#define HOST_MSIX_ERR_INDEX_FN1 0x0001410c
+#define APP_PLL_425_CTL_REG 0x00014204
+#define __P_425_PLL_LOCK 0x80000000
+#define __APP_PLL_425_SRAM_USE_100MHZ 0x00100000
+#define __APP_PLL_425_RESET_TIMER_MK 0x000e0000
+#define __APP_PLL_425_RESET_TIMER_SH 17
+#define __APP_PLL_425_RESET_TIMER(_v) ((_v) << __APP_PLL_425_RESET_TIMER_SH)
+#define __APP_PLL_425_LOGIC_SOFT_RESET 0x00010000
+#define __APP_PLL_425_CNTLMT0_1_MK 0x0000c000
+#define __APP_PLL_425_CNTLMT0_1_SH 14
+#define __APP_PLL_425_CNTLMT0_1(_v) ((_v) << __APP_PLL_425_CNTLMT0_1_SH)
+#define __APP_PLL_425_JITLMT0_1_MK 0x00003000
+#define __APP_PLL_425_JITLMT0_1_SH 12
+#define __APP_PLL_425_JITLMT0_1(_v) ((_v) << __APP_PLL_425_JITLMT0_1_SH)
+#define __APP_PLL_425_HREF 0x00000800
+#define __APP_PLL_425_HDIV 0x00000400
+#define __APP_PLL_425_P0_1_MK 0x00000300
+#define __APP_PLL_425_P0_1_SH 8
+#define __APP_PLL_425_P0_1(_v) ((_v) << __APP_PLL_425_P0_1_SH)
+#define __APP_PLL_425_Z0_2_MK 0x000000e0
+#define __APP_PLL_425_Z0_2_SH 5
+#define __APP_PLL_425_Z0_2(_v) ((_v) << __APP_PLL_425_Z0_2_SH)
+#define __APP_PLL_425_RSEL200500 0x00000010
+#define __APP_PLL_425_ENARST 0x00000008
+#define __APP_PLL_425_BYPASS 0x00000004
+#define __APP_PLL_425_LRESETN 0x00000002
+#define __APP_PLL_425_ENABLE 0x00000001
+#define APP_PLL_312_CTL_REG 0x00014208
+#define __P_312_PLL_LOCK 0x80000000
+#define __ENABLE_MAC_AHB_1 0x00800000
+#define __ENABLE_MAC_AHB_0 0x00400000
+#define __ENABLE_MAC_1 0x00200000
+#define __ENABLE_MAC_0 0x00100000
+#define __APP_PLL_312_RESET_TIMER_MK 0x000e0000
+#define __APP_PLL_312_RESET_TIMER_SH 17
+#define __APP_PLL_312_RESET_TIMER(_v) ((_v) << __APP_PLL_312_RESET_TIMER_SH)
+#define __APP_PLL_312_LOGIC_SOFT_RESET 0x00010000
+#define __APP_PLL_312_CNTLMT0_1_MK 0x0000c000
+#define __APP_PLL_312_CNTLMT0_1_SH 14
+#define __APP_PLL_312_CNTLMT0_1(_v) ((_v) << __APP_PLL_312_CNTLMT0_1_SH)
+#define __APP_PLL_312_JITLMT0_1_MK 0x00003000
+#define __APP_PLL_312_JITLMT0_1_SH 12
+#define __APP_PLL_312_JITLMT0_1(_v) ((_v) << __APP_PLL_312_JITLMT0_1_SH)
+#define __APP_PLL_312_HREF 0x00000800
+#define __APP_PLL_312_HDIV 0x00000400
+#define __APP_PLL_312_P0_1_MK 0x00000300
+#define __APP_PLL_312_P0_1_SH 8
+#define __APP_PLL_312_P0_1(_v) ((_v) << __APP_PLL_312_P0_1_SH)
+#define __APP_PLL_312_Z0_2_MK 0x000000e0
+#define __APP_PLL_312_Z0_2_SH 5
+#define __APP_PLL_312_Z0_2(_v) ((_v) << __APP_PLL_312_Z0_2_SH)
+#define __APP_PLL_312_RSEL200500 0x00000010
+#define __APP_PLL_312_ENARST 0x00000008
+#define __APP_PLL_312_BYPASS 0x00000004
+#define __APP_PLL_312_LRESETN 0x00000002
+#define __APP_PLL_312_ENABLE 0x00000001
+#define MBIST_CTL_REG 0x00014220
+#define __EDRAM_BISTR_START 0x00000004
+#define __MBIST_RESET 0x00000002
+#define __MBIST_START 0x00000001
+#define MBIST_STAT_REG 0x00014224
+#define __EDRAM_BISTR_STATUS 0x00000008
+#define __EDRAM_BISTR_DONE 0x00000004
+#define __MEM_BIT_STATUS 0x00000002
+#define __MBIST_DONE 0x00000001
+#define HOST_SEM0_REG 0x00014230
+#define __HOST_SEMAPHORE 0x00000001
+#define HOST_SEM1_REG 0x00014234
+#define HOST_SEM2_REG 0x00014238
+#define HOST_SEM3_REG 0x0001423c
+#define HOST_SEM0_INFO_REG 0x00014240
+#define HOST_SEM1_INFO_REG 0x00014244
+#define HOST_SEM2_INFO_REG 0x00014248
+#define HOST_SEM3_INFO_REG 0x0001424c
+#define ETH_MAC_SER_REG 0x00014288
+#define __APP_EMS_CKBUFAMPIN 0x00000020
+#define __APP_EMS_REFCLKSEL 0x00000010
+#define __APP_EMS_CMLCKSEL 0x00000008
+#define __APP_EMS_REFCKBUFEN2 0x00000004
+#define __APP_EMS_REFCKBUFEN1 0x00000002
+#define __APP_EMS_CHANNEL_SEL 0x00000001
+#define HOSTFN2_INT_STATUS 0x00014300
+#define __HOSTFN2_HALT_OCCURRED 0x01000000
+#define __HOSTFN2_INT_STATUS_LVL_MK 0x00f00000
+#define __HOSTFN2_INT_STATUS_LVL_SH 20
+#define __HOSTFN2_INT_STATUS_LVL(_v) ((_v) << __HOSTFN2_INT_STATUS_LVL_SH)
+#define __HOSTFN2_INT_STATUS_P_MK 0x000f0000
+#define __HOSTFN2_INT_STATUS_P_SH 16
+#define __HOSTFN2_INT_STATUS_P(_v) ((_v) << __HOSTFN2_INT_STATUS_P_SH)
+#define __HOSTFN2_INT_STATUS_F 0x0000ffff
+#define HOSTFN2_INT_MSK 0x00014304
+#define HOST_PAGE_NUM_FN2 0x00014308
+#define HOST_MSIX_ERR_INDEX_FN2 0x0001430c
+#define HOSTFN3_INT_STATUS 0x00014400
+#define __HALT_OCCURRED 0x01000000
+#define __HOSTFN3_INT_STATUS_LVL_MK 0x00f00000
+#define __HOSTFN3_INT_STATUS_LVL_SH 20
+#define __HOSTFN3_INT_STATUS_LVL(_v) ((_v) << __HOSTFN3_INT_STATUS_LVL_SH)
+#define __HOSTFN3_INT_STATUS_P_MK 0x000f0000
+#define __HOSTFN3_INT_STATUS_P_SH 16
+#define __HOSTFN3_INT_STATUS_P(_v) ((_v) << __HOSTFN3_INT_STATUS_P_SH)
+#define __HOSTFN3_INT_STATUS_F 0x0000ffff
+#define HOSTFN3_INT_MSK 0x00014404
+#define HOST_PAGE_NUM_FN3 0x00014408
+#define HOST_MSIX_ERR_INDEX_FN3 0x0001440c
+#define FNC_ID_REG 0x00014600
+#define __FUNCTION_NUMBER 0x00000007
+#define FNC_PERS_REG 0x00014604
+#define __F3_FUNCTION_ACTIVE 0x80000000
+#define __F3_FUNCTION_MODE 0x40000000
+#define __F3_PORT_MAP_MK 0x30000000
+#define __F3_PORT_MAP_SH 28
+#define __F3_PORT_MAP(_v) ((_v) << __F3_PORT_MAP_SH)
+#define __F3_VM_MODE 0x08000000
+#define __F3_INTX_STATUS_MK 0x07000000
+#define __F3_INTX_STATUS_SH 24
+#define __F3_INTX_STATUS(_v) ((_v) << __F3_INTX_STATUS_SH)
+#define __F2_FUNCTION_ACTIVE 0x00800000
+#define __F2_FUNCTION_MODE 0x00400000
+#define __F2_PORT_MAP_MK 0x00300000
+#define __F2_PORT_MAP_SH 20
+#define __F2_PORT_MAP(_v) ((_v) << __F2_PORT_MAP_SH)
+#define __F2_VM_MODE 0x00080000
+#define __F2_INTX_STATUS_MK 0x00070000
+#define __F2_INTX_STATUS_SH 16
+#define __F2_INTX_STATUS(_v) ((_v) << __F2_INTX_STATUS_SH)
+#define __F1_FUNCTION_ACTIVE 0x00008000
+#define __F1_FUNCTION_MODE 0x00004000
+#define __F1_PORT_MAP_MK 0x00003000
+#define __F1_PORT_MAP_SH 12
+#define __F1_PORT_MAP(_v) ((_v) << __F1_PORT_MAP_SH)
+#define __F1_VM_MODE 0x00000800
+#define __F1_INTX_STATUS_MK 0x00000700
+#define __F1_INTX_STATUS_SH 8
+#define __F1_INTX_STATUS(_v) ((_v) << __F1_INTX_STATUS_SH)
+#define __F0_FUNCTION_ACTIVE 0x00000080
+#define __F0_FUNCTION_MODE 0x00000040
+#define __F0_PORT_MAP_MK 0x00000030
+#define __F0_PORT_MAP_SH 4
+#define __F0_PORT_MAP(_v) ((_v) << __F0_PORT_MAP_SH)
+#define __F0_VM_MODE 0x00000008
+#define __F0_INTX_STATUS 0x00000007
+enum {
+ __F0_INTX_STATUS_MSIX = 0x0,
+ __F0_INTX_STATUS_INTA = 0x1,
+ __F0_INTX_STATUS_INTB = 0x2,
+ __F0_INTX_STATUS_INTC = 0x3,
+ __F0_INTX_STATUS_INTD = 0x4,
+};
+#define OP_MODE 0x0001460c
+#define __APP_ETH_CLK_LOWSPEED 0x00000004
+#define __GLOBAL_CORECLK_HALFSPEED 0x00000002
+#define __GLOBAL_FCOE_MODE 0x00000001
+#define HOST_SEM4_REG 0x00014610
+#define HOST_SEM5_REG 0x00014614
+#define HOST_SEM6_REG 0x00014618
+#define HOST_SEM7_REG 0x0001461c
+#define HOST_SEM4_INFO_REG 0x00014620
+#define HOST_SEM5_INFO_REG 0x00014624
+#define HOST_SEM6_INFO_REG 0x00014628
+#define HOST_SEM7_INFO_REG 0x0001462c
+#define HOSTFN0_LPU0_MBOX0_CMD_STAT 0x00019000
+#define __HOSTFN0_LPU0_MBOX0_INFO_MK 0xfffffffe
+#define __HOSTFN0_LPU0_MBOX0_INFO_SH 1
+#define __HOSTFN0_LPU0_MBOX0_INFO(_v) ((_v) << __HOSTFN0_LPU0_MBOX0_INFO_SH)
+#define __HOSTFN0_LPU0_MBOX0_CMD_STATUS 0x00000001
+#define HOSTFN0_LPU1_MBOX0_CMD_STAT 0x00019004
+#define __HOSTFN0_LPU1_MBOX0_INFO_MK 0xfffffffe
+#define __HOSTFN0_LPU1_MBOX0_INFO_SH 1
+#define __HOSTFN0_LPU1_MBOX0_INFO(_v) ((_v) << __HOSTFN0_LPU1_MBOX0_INFO_SH)
+#define __HOSTFN0_LPU1_MBOX0_CMD_STATUS 0x00000001
+#define LPU0_HOSTFN0_MBOX0_CMD_STAT 0x00019008
+#define __LPU0_HOSTFN0_MBOX0_INFO_MK 0xfffffffe
+#define __LPU0_HOSTFN0_MBOX0_INFO_SH 1
+#define __LPU0_HOSTFN0_MBOX0_INFO(_v) ((_v) << __LPU0_HOSTFN0_MBOX0_INFO_SH)
+#define __LPU0_HOSTFN0_MBOX0_CMD_STATUS 0x00000001
+#define LPU1_HOSTFN0_MBOX0_CMD_STAT 0x0001900c
+#define __LPU1_HOSTFN0_MBOX0_INFO_MK 0xfffffffe
+#define __LPU1_HOSTFN0_MBOX0_INFO_SH 1
+#define __LPU1_HOSTFN0_MBOX0_INFO(_v) ((_v) << __LPU1_HOSTFN0_MBOX0_INFO_SH)
+#define __LPU1_HOSTFN0_MBOX0_CMD_STATUS 0x00000001
+#define HOSTFN1_LPU0_MBOX0_CMD_STAT 0x00019010
+#define __HOSTFN1_LPU0_MBOX0_INFO_MK 0xfffffffe
+#define __HOSTFN1_LPU0_MBOX0_INFO_SH 1
+#define __HOSTFN1_LPU0_MBOX0_INFO(_v) ((_v) << __HOSTFN1_LPU0_MBOX0_INFO_SH)
+#define __HOSTFN1_LPU0_MBOX0_CMD_STATUS 0x00000001
+#define HOSTFN1_LPU1_MBOX0_CMD_STAT 0x00019014
+#define __HOSTFN1_LPU1_MBOX0_INFO_MK 0xfffffffe
+#define __HOSTFN1_LPU1_MBOX0_INFO_SH 1
+#define __HOSTFN1_LPU1_MBOX0_INFO(_v) ((_v) << __HOSTFN1_LPU1_MBOX0_INFO_SH)
+#define __HOSTFN1_LPU1_MBOX0_CMD_STATUS 0x00000001
+#define LPU0_HOSTFN1_MBOX0_CMD_STAT 0x00019018
+#define __LPU0_HOSTFN1_MBOX0_INFO_MK 0xfffffffe
+#define __LPU0_HOSTFN1_MBOX0_INFO_SH 1
+#define __LPU0_HOSTFN1_MBOX0_INFO(_v) ((_v) << __LPU0_HOSTFN1_MBOX0_INFO_SH)
+#define __LPU0_HOSTFN1_MBOX0_CMD_STATUS 0x00000001
+#define LPU1_HOSTFN1_MBOX0_CMD_STAT 0x0001901c
+#define __LPU1_HOSTFN1_MBOX0_INFO_MK 0xfffffffe
+#define __LPU1_HOSTFN1_MBOX0_INFO_SH 1
+#define __LPU1_HOSTFN1_MBOX0_INFO(_v) ((_v) << __LPU1_HOSTFN1_MBOX0_INFO_SH)
+#define __LPU1_HOSTFN1_MBOX0_CMD_STATUS 0x00000001
+#define HOSTFN2_LPU0_MBOX0_CMD_STAT 0x00019150
+#define __HOSTFN2_LPU0_MBOX0_INFO_MK 0xfffffffe
+#define __HOSTFN2_LPU0_MBOX0_INFO_SH 1
+#define __HOSTFN2_LPU0_MBOX0_INFO(_v) ((_v) << __HOSTFN2_LPU0_MBOX0_INFO_SH)
+#define __HOSTFN2_LPU0_MBOX0_CMD_STATUS 0x00000001
+#define HOSTFN2_LPU1_MBOX0_CMD_STAT 0x00019154
+#define __HOSTFN2_LPU1_MBOX0_INFO_MK 0xfffffffe
+#define __HOSTFN2_LPU1_MBOX0_INFO_SH 1
+#define __HOSTFN2_LPU1_MBOX0_INFO(_v) ((_v) << __HOSTFN2_LPU1_MBOX0_INFO_SH)
+#define __HOSTFN2_LPU1_MBOX0BOX0_CMD_STATUS 0x00000001
+#define LPU0_HOSTFN2_MBOX0_CMD_STAT 0x00019158
+#define __LPU0_HOSTFN2_MBOX0_INFO_MK 0xfffffffe
+#define __LPU0_HOSTFN2_MBOX0_INFO_SH 1
+#define __LPU0_HOSTFN2_MBOX0_INFO(_v) ((_v) << __LPU0_HOSTFN2_MBOX0_INFO_SH)
+#define __LPU0_HOSTFN2_MBOX0_CMD_STATUS 0x00000001
+#define LPU1_HOSTFN2_MBOX0_CMD_STAT 0x0001915c
+#define __LPU1_HOSTFN2_MBOX0_INFO_MK 0xfffffffe
+#define __LPU1_HOSTFN2_MBOX0_INFO_SH 1
+#define __LPU1_HOSTFN2_MBOX0_INFO(_v) ((_v) << __LPU1_HOSTFN2_MBOX0_INFO_SH)
+#define __LPU1_HOSTFN2_MBOX0_CMD_STATUS 0x00000001
+#define HOSTFN3_LPU0_MBOX0_CMD_STAT 0x00019160
+#define __HOSTFN3_LPU0_MBOX0_INFO_MK 0xfffffffe
+#define __HOSTFN3_LPU0_MBOX0_INFO_SH 1
+#define __HOSTFN3_LPU0_MBOX0_INFO(_v) ((_v) << __HOSTFN3_LPU0_MBOX0_INFO_SH)
+#define __HOSTFN3_LPU0_MBOX0_CMD_STATUS 0x00000001
+#define HOSTFN3_LPU1_MBOX0_CMD_STAT 0x00019164
+#define __HOSTFN3_LPU1_MBOX0_INFO_MK 0xfffffffe
+#define __HOSTFN3_LPU1_MBOX0_INFO_SH 1
+#define __HOSTFN3_LPU1_MBOX0_INFO(_v) ((_v) << __HOSTFN3_LPU1_MBOX0_INFO_SH)
+#define __HOSTFN3_LPU1_MBOX0_CMD_STATUS 0x00000001
+#define LPU0_HOSTFN3_MBOX0_CMD_STAT 0x00019168
+#define __LPU0_HOSTFN3_MBOX0_INFO_MK 0xfffffffe
+#define __LPU0_HOSTFN3_MBOX0_INFO_SH 1
+#define __LPU0_HOSTFN3_MBOX0_INFO(_v) ((_v) << __LPU0_HOSTFN3_MBOX0_INFO_SH)
+#define __LPU0_HOSTFN3_MBOX0_CMD_STATUS 0x00000001
+#define LPU1_HOSTFN3_MBOX0_CMD_STAT 0x0001916c
+#define __LPU1_HOSTFN3_MBOX0_INFO_MK 0xfffffffe
+#define __LPU1_HOSTFN3_MBOX0_INFO_SH 1
+#define __LPU1_HOSTFN3_MBOX0_INFO(_v) ((_v) << __LPU1_HOSTFN3_MBOX0_INFO_SH)
+#define __LPU1_HOSTFN3_MBOX0_CMD_STATUS 0x00000001
+#define FW_INIT_HALT_P0 0x000191ac
+#define __FW_INIT_HALT_P 0x00000001
+#define FW_INIT_HALT_P1 0x000191bc
+#define CPE_PI_PTR_Q0 0x00038000
+#define __CPE_PI_UNUSED_MK 0xffff0000
+#define __CPE_PI_UNUSED_SH 16
+#define __CPE_PI_UNUSED(_v) ((_v) << __CPE_PI_UNUSED_SH)
+#define __CPE_PI_PTR 0x0000ffff
+#define CPE_PI_PTR_Q1 0x00038040
+#define CPE_CI_PTR_Q0 0x00038004
+#define __CPE_CI_UNUSED_MK 0xffff0000
+#define __CPE_CI_UNUSED_SH 16
+#define __CPE_CI_UNUSED(_v) ((_v) << __CPE_CI_UNUSED_SH)
+#define __CPE_CI_PTR 0x0000ffff
+#define CPE_CI_PTR_Q1 0x00038044
+#define CPE_DEPTH_Q0 0x00038008
+#define __CPE_DEPTH_UNUSED_MK 0xf8000000
+#define __CPE_DEPTH_UNUSED_SH 27
+#define __CPE_DEPTH_UNUSED(_v) ((_v) << __CPE_DEPTH_UNUSED_SH)
+#define __CPE_MSIX_VEC_INDEX_MK 0x07ff0000
+#define __CPE_MSIX_VEC_INDEX_SH 16
+#define __CPE_MSIX_VEC_INDEX(_v) ((_v) << __CPE_MSIX_VEC_INDEX_SH)
+#define __CPE_DEPTH 0x0000ffff
+#define CPE_DEPTH_Q1 0x00038048
+#define CPE_QCTRL_Q0 0x0003800c
+#define __CPE_CTRL_UNUSED30_MK 0xfc000000
+#define __CPE_CTRL_UNUSED30_SH 26
+#define __CPE_CTRL_UNUSED30(_v) ((_v) << __CPE_CTRL_UNUSED30_SH)
+#define __CPE_FUNC_INT_CTRL_MK 0x03000000
+#define __CPE_FUNC_INT_CTRL_SH 24
+#define __CPE_FUNC_INT_CTRL(_v) ((_v) << __CPE_FUNC_INT_CTRL_SH)
+enum {
+ __CPE_FUNC_INT_CTRL_DISABLE = 0x0,
+ __CPE_FUNC_INT_CTRL_F2NF = 0x1,
+ __CPE_FUNC_INT_CTRL_3QUART = 0x2,
+ __CPE_FUNC_INT_CTRL_HALF = 0x3,
+};
+#define __CPE_CTRL_UNUSED20_MK 0x00f00000
+#define __CPE_CTRL_UNUSED20_SH 20
+#define __CPE_CTRL_UNUSED20(_v) ((_v) << __CPE_CTRL_UNUSED20_SH)
+#define __CPE_SCI_TH_MK 0x000f0000
+#define __CPE_SCI_TH_SH 16
+#define __CPE_SCI_TH(_v) ((_v) << __CPE_SCI_TH_SH)
+#define __CPE_CTRL_UNUSED10_MK 0x0000c000
+#define __CPE_CTRL_UNUSED10_SH 14
+#define __CPE_CTRL_UNUSED10(_v) ((_v) << __CPE_CTRL_UNUSED10_SH)
+#define __CPE_ACK_PENDING 0x00002000
+#define __CPE_CTRL_UNUSED40_MK 0x00001c00
+#define __CPE_CTRL_UNUSED40_SH 10
+#define __CPE_CTRL_UNUSED40(_v) ((_v) << __CPE_CTRL_UNUSED40_SH)
+#define __CPE_PCIEID_MK 0x00000300
+#define __CPE_PCIEID_SH 8
+#define __CPE_PCIEID(_v) ((_v) << __CPE_PCIEID_SH)
+#define __CPE_CTRL_UNUSED00_MK 0x000000fe
+#define __CPE_CTRL_UNUSED00_SH 1
+#define __CPE_CTRL_UNUSED00(_v) ((_v) << __CPE_CTRL_UNUSED00_SH)
+#define __CPE_ESIZE 0x00000001
+#define CPE_QCTRL_Q1 0x0003804c
+#define __CPE_CTRL_UNUSED31_MK 0xfc000000
+#define __CPE_CTRL_UNUSED31_SH 26
+#define __CPE_CTRL_UNUSED31(_v) ((_v) << __CPE_CTRL_UNUSED31_SH)
+#define __CPE_CTRL_UNUSED21_MK 0x00f00000
+#define __CPE_CTRL_UNUSED21_SH 20
+#define __CPE_CTRL_UNUSED21(_v) ((_v) << __CPE_CTRL_UNUSED21_SH)
+#define __CPE_CTRL_UNUSED11_MK 0x0000c000
+#define __CPE_CTRL_UNUSED11_SH 14
+#define __CPE_CTRL_UNUSED11(_v) ((_v) << __CPE_CTRL_UNUSED11_SH)
+#define __CPE_CTRL_UNUSED41_MK 0x00001c00
+#define __CPE_CTRL_UNUSED41_SH 10
+#define __CPE_CTRL_UNUSED41(_v) ((_v) << __CPE_CTRL_UNUSED41_SH)
+#define __CPE_CTRL_UNUSED01_MK 0x000000fe
+#define __CPE_CTRL_UNUSED01_SH 1
+#define __CPE_CTRL_UNUSED01(_v) ((_v) << __CPE_CTRL_UNUSED01_SH)
+#define RME_PI_PTR_Q0 0x00038020
+#define __LATENCY_TIME_STAMP_MK 0xffff0000
+#define __LATENCY_TIME_STAMP_SH 16
+#define __LATENCY_TIME_STAMP(_v) ((_v) << __LATENCY_TIME_STAMP_SH)
+#define __RME_PI_PTR 0x0000ffff
+#define RME_PI_PTR_Q1 0x00038060
+#define RME_CI_PTR_Q0 0x00038024
+#define __DELAY_TIME_STAMP_MK 0xffff0000
+#define __DELAY_TIME_STAMP_SH 16
+#define __DELAY_TIME_STAMP(_v) ((_v) << __DELAY_TIME_STAMP_SH)
+#define __RME_CI_PTR 0x0000ffff
+#define RME_CI_PTR_Q1 0x00038064
+#define RME_DEPTH_Q0 0x00038028
+#define __RME_DEPTH_UNUSED_MK 0xf8000000
+#define __RME_DEPTH_UNUSED_SH 27
+#define __RME_DEPTH_UNUSED(_v) ((_v) << __RME_DEPTH_UNUSED_SH)
+#define __RME_MSIX_VEC_INDEX_MK 0x07ff0000
+#define __RME_MSIX_VEC_INDEX_SH 16
+#define __RME_MSIX_VEC_INDEX(_v) ((_v) << __RME_MSIX_VEC_INDEX_SH)
+#define __RME_DEPTH 0x0000ffff
+#define RME_DEPTH_Q1 0x00038068
+#define RME_QCTRL_Q0 0x0003802c
+#define __RME_INT_LATENCY_TIMER_MK 0xff000000
+#define __RME_INT_LATENCY_TIMER_SH 24
+#define __RME_INT_LATENCY_TIMER(_v) ((_v) << __RME_INT_LATENCY_TIMER_SH)
+#define __RME_INT_DELAY_TIMER_MK 0x00ff0000
+#define __RME_INT_DELAY_TIMER_SH 16
+#define __RME_INT_DELAY_TIMER(_v) ((_v) << __RME_INT_DELAY_TIMER_SH)
+#define __RME_INT_DELAY_DISABLE 0x00008000
+#define __RME_DLY_DELAY_DISABLE 0x00004000
+#define __RME_ACK_PENDING 0x00002000
+#define __RME_FULL_INTERRUPT_DISABLE 0x00001000
+#define __RME_CTRL_UNUSED10_MK 0x00000c00
+#define __RME_CTRL_UNUSED10_SH 10
+#define __RME_CTRL_UNUSED10(_v) ((_v) << __RME_CTRL_UNUSED10_SH)
+#define __RME_PCIEID_MK 0x00000300
+#define __RME_PCIEID_SH 8
+#define __RME_PCIEID(_v) ((_v) << __RME_PCIEID_SH)
+#define __RME_CTRL_UNUSED00_MK 0x000000fe
+#define __RME_CTRL_UNUSED00_SH 1
+#define __RME_CTRL_UNUSED00(_v) ((_v) << __RME_CTRL_UNUSED00_SH)
+#define __RME_ESIZE 0x00000001
+#define RME_QCTRL_Q1 0x0003806c
+#define __RME_CTRL_UNUSED11_MK 0x00000c00
+#define __RME_CTRL_UNUSED11_SH 10
+#define __RME_CTRL_UNUSED11(_v) ((_v) << __RME_CTRL_UNUSED11_SH)
+#define __RME_CTRL_UNUSED01_MK 0x000000fe
+#define __RME_CTRL_UNUSED01_SH 1
+#define __RME_CTRL_UNUSED01(_v) ((_v) << __RME_CTRL_UNUSED01_SH)
+#define PSS_CTL_REG 0x00018800
+#define __PSS_I2C_CLK_DIV_MK 0x007f0000
+#define __PSS_I2C_CLK_DIV_SH 16
+#define __PSS_I2C_CLK_DIV(_v) ((_v) << __PSS_I2C_CLK_DIV_SH)
+#define __PSS_LMEM_INIT_DONE 0x00001000
+#define __PSS_LMEM_RESET 0x00000200
+#define __PSS_LMEM_INIT_EN 0x00000100
+#define __PSS_LPU1_RESET 0x00000002
+#define __PSS_LPU0_RESET 0x00000001
+#define PSS_ERR_STATUS_REG 0x00018810
+#define __PSS_LPU1_TCM_READ_ERR 0x00200000
+#define __PSS_LPU0_TCM_READ_ERR 0x00100000
+#define __PSS_LMEM5_CORR_ERR 0x00080000
+#define __PSS_LMEM4_CORR_ERR 0x00040000
+#define __PSS_LMEM3_CORR_ERR 0x00020000
+#define __PSS_LMEM2_CORR_ERR 0x00010000
+#define __PSS_LMEM1_CORR_ERR 0x00008000
+#define __PSS_LMEM0_CORR_ERR 0x00004000
+#define __PSS_LMEM5_UNCORR_ERR 0x00002000
+#define __PSS_LMEM4_UNCORR_ERR 0x00001000
+#define __PSS_LMEM3_UNCORR_ERR 0x00000800
+#define __PSS_LMEM2_UNCORR_ERR 0x00000400
+#define __PSS_LMEM1_UNCORR_ERR 0x00000200
+#define __PSS_LMEM0_UNCORR_ERR 0x00000100
+#define __PSS_BAL_PERR 0x00000080
+#define __PSS_DIP_IF_ERR 0x00000040
+#define __PSS_IOH_IF_ERR 0x00000020
+#define __PSS_TDS_IF_ERR 0x00000010
+#define __PSS_RDS_IF_ERR 0x00000008
+#define __PSS_SGM_IF_ERR 0x00000004
+#define __PSS_LPU1_RAM_ERR 0x00000002
+#define __PSS_LPU0_RAM_ERR 0x00000001
+#define ERR_SET_REG 0x00018818
+#define __PSS_ERR_STATUS_SET 0x003fffff
+#define PMM_1T_RESET_REG_P0 0x0002381c
+#define __PMM_1T_RESET_P 0x00000001
+#define PMM_1T_RESET_REG_P1 0x00023c1c
+#define HQM_QSET0_RXQ_DRBL_P0 0x00038000
+#define __RXQ0_ADD_VECTORS_P 0x80000000
+#define __RXQ0_STOP_P 0x40000000
+#define __RXQ0_PRD_PTR_P 0x0000ffff
+#define HQM_QSET1_RXQ_DRBL_P0 0x00038080
+#define __RXQ1_ADD_VECTORS_P 0x80000000
+#define __RXQ1_STOP_P 0x40000000
+#define __RXQ1_PRD_PTR_P 0x0000ffff
+#define HQM_QSET0_RXQ_DRBL_P1 0x0003c000
+#define HQM_QSET1_RXQ_DRBL_P1 0x0003c080
+#define HQM_QSET0_TXQ_DRBL_P0 0x00038020
+#define __TXQ0_ADD_VECTORS_P 0x80000000
+#define __TXQ0_STOP_P 0x40000000
+#define __TXQ0_PRD_PTR_P 0x0000ffff
+#define HQM_QSET1_TXQ_DRBL_P0 0x000380a0
+#define __TXQ1_ADD_VECTORS_P 0x80000000
+#define __TXQ1_STOP_P 0x40000000
+#define __TXQ1_PRD_PTR_P 0x0000ffff
+#define HQM_QSET0_TXQ_DRBL_P1 0x0003c020
+#define HQM_QSET1_TXQ_DRBL_P1 0x0003c0a0
+#define HQM_QSET0_IB_DRBL_1_P0 0x00038040
+#define __IB1_0_ACK_P 0x80000000
+#define __IB1_0_DISABLE_P 0x40000000
+#define __IB1_0_COALESCING_CFG_P_MK 0x00ff0000
+#define __IB1_0_COALESCING_CFG_P_SH 16
+#define __IB1_0_COALESCING_CFG_P(_v) ((_v) << __IB1_0_COALESCING_CFG_P_SH)
+#define __IB1_0_NUM_OF_ACKED_EVENTS_P 0x0000ffff
+#define HQM_QSET1_IB_DRBL_1_P0 0x000380c0
+#define __IB1_1_ACK_P 0x80000000
+#define __IB1_1_DISABLE_P 0x40000000
+#define __IB1_1_COALESCING_CFG_P_MK 0x00ff0000
+#define __IB1_1_COALESCING_CFG_P_SH 16
+#define __IB1_1_COALESCING_CFG_P(_v) ((_v) << __IB1_1_COALESCING_CFG_P_SH)
+#define __IB1_1_NUM_OF_ACKED_EVENTS_P 0x0000ffff
+#define HQM_QSET0_IB_DRBL_1_P1 0x0003c040
+#define HQM_QSET1_IB_DRBL_1_P1 0x0003c0c0
+#define HQM_QSET0_IB_DRBL_2_P0 0x00038060
+#define __IB2_0_ACK_P 0x80000000
+#define __IB2_0_DISABLE_P 0x40000000
+#define __IB2_0_COALESCING_CFG_P_MK 0x00ff0000
+#define __IB2_0_COALESCING_CFG_P_SH 16
+#define __IB2_0_COALESCING_CFG_P(_v) ((_v) << __IB2_0_COALESCING_CFG_P_SH)
+#define __IB2_0_NUM_OF_ACKED_EVENTS_P 0x0000ffff
+#define HQM_QSET1_IB_DRBL_2_P0 0x000380e0
+#define __IB2_1_ACK_P 0x80000000
+#define __IB2_1_DISABLE_P 0x40000000
+#define __IB2_1_COALESCING_CFG_P_MK 0x00ff0000
+#define __IB2_1_COALESCING_CFG_P_SH 16
+#define __IB2_1_COALESCING_CFG_P(_v) ((_v) << __IB2_1_COALESCING_CFG_P_SH)
+#define __IB2_1_NUM_OF_ACKED_EVENTS_P 0x0000ffff
+#define HQM_QSET0_IB_DRBL_2_P1 0x0003c060
+#define HQM_QSET1_IB_DRBL_2_P1 0x0003c0e0
+
+/*
+ * These definitions are either in error/missing in spec. Its auto-generated
+ * from hard coded values in regparse.pl.
+ */
+#define __EMPHPOST_AT_4G_MK_FIX 0x0000001c
+#define __EMPHPOST_AT_4G_SH_FIX 0x00000002
+#define __EMPHPRE_AT_4G_FIX 0x00000003
+#define __SFP_TXRATE_EN_FIX 0x00000100
+#define __SFP_RXRATE_EN_FIX 0x00000080
+
+/*
+ * These register definitions are auto-generated from hard coded values
+ * in regparse.pl.
+ */
+
+/*
+ * These register mapping definitions are auto-generated from mapping tables
+ * in regparse.pl.
+ */
+#define BFA_IOC0_HBEAT_REG HOST_SEM0_INFO_REG
+#define BFA_IOC0_STATE_REG HOST_SEM1_INFO_REG
+#define BFA_IOC1_HBEAT_REG HOST_SEM2_INFO_REG
+#define BFA_IOC1_STATE_REG HOST_SEM3_INFO_REG
+#define BFA_FW_USE_COUNT HOST_SEM4_INFO_REG
+
+#define CPE_DEPTH_Q(__n) \
+ (CPE_DEPTH_Q0 + (__n) * (CPE_DEPTH_Q1 - CPE_DEPTH_Q0))
+#define CPE_QCTRL_Q(__n) \
+ (CPE_QCTRL_Q0 + (__n) * (CPE_QCTRL_Q1 - CPE_QCTRL_Q0))
+#define CPE_PI_PTR_Q(__n) \
+ (CPE_PI_PTR_Q0 + (__n) * (CPE_PI_PTR_Q1 - CPE_PI_PTR_Q0))
+#define CPE_CI_PTR_Q(__n) \
+ (CPE_CI_PTR_Q0 + (__n) * (CPE_CI_PTR_Q1 - CPE_CI_PTR_Q0))
+#define RME_DEPTH_Q(__n) \
+ (RME_DEPTH_Q0 + (__n) * (RME_DEPTH_Q1 - RME_DEPTH_Q0))
+#define RME_QCTRL_Q(__n) \
+ (RME_QCTRL_Q0 + (__n) * (RME_QCTRL_Q1 - RME_QCTRL_Q0))
+#define RME_PI_PTR_Q(__n) \
+ (RME_PI_PTR_Q0 + (__n) * (RME_PI_PTR_Q1 - RME_PI_PTR_Q0))
+#define RME_CI_PTR_Q(__n) \
+ (RME_CI_PTR_Q0 + (__n) * (RME_CI_PTR_Q1 - RME_CI_PTR_Q0))
+#define HQM_QSET_RXQ_DRBL_P0(__n) (HQM_QSET0_RXQ_DRBL_P0 + (__n) \
+ * (HQM_QSET1_RXQ_DRBL_P0 - HQM_QSET0_RXQ_DRBL_P0))
+#define HQM_QSET_TXQ_DRBL_P0(__n) (HQM_QSET0_TXQ_DRBL_P0 + (__n) \
+ * (HQM_QSET1_TXQ_DRBL_P0 - HQM_QSET0_TXQ_DRBL_P0))
+#define HQM_QSET_IB_DRBL_1_P0(__n) (HQM_QSET0_IB_DRBL_1_P0 + (__n) \
+ * (HQM_QSET1_IB_DRBL_1_P0 - HQM_QSET0_IB_DRBL_1_P0))
+#define HQM_QSET_IB_DRBL_2_P0(__n) (HQM_QSET0_IB_DRBL_2_P0 + (__n) \
+ * (HQM_QSET1_IB_DRBL_2_P0 - HQM_QSET0_IB_DRBL_2_P0))
+#define HQM_QSET_RXQ_DRBL_P1(__n) (HQM_QSET0_RXQ_DRBL_P1 + (__n) \
+ * (HQM_QSET1_RXQ_DRBL_P1 - HQM_QSET0_RXQ_DRBL_P1))
+#define HQM_QSET_TXQ_DRBL_P1(__n) (HQM_QSET0_TXQ_DRBL_P1 + (__n) \
+ * (HQM_QSET1_TXQ_DRBL_P1 - HQM_QSET0_TXQ_DRBL_P1))
+#define HQM_QSET_IB_DRBL_1_P1(__n) (HQM_QSET0_IB_DRBL_1_P1 + (__n) \
+ * (HQM_QSET1_IB_DRBL_1_P1 - HQM_QSET0_IB_DRBL_1_P1))
+#define HQM_QSET_IB_DRBL_2_P1(__n) (HQM_QSET0_IB_DRBL_2_P1 + (__n) \
+ * (HQM_QSET1_IB_DRBL_2_P1 - HQM_QSET0_IB_DRBL_2_P1))
+
+#define CPE_Q_NUM(__fn, __q) (((__fn) << 2) + (__q))
+#define RME_Q_NUM(__fn, __q) (((__fn) << 2) + (__q))
+#define CPE_Q_MASK(__q) ((__q) & 0x3)
+#define RME_Q_MASK(__q) ((__q) & 0x3)
+
+/*
+ * PCI MSI-X vector defines
+ */
+enum {
+ BFA_MSIX_CPE_Q0 = 0,
+ BFA_MSIX_CPE_Q1 = 1,
+ BFA_MSIX_CPE_Q2 = 2,
+ BFA_MSIX_CPE_Q3 = 3,
+ BFA_MSIX_RME_Q0 = 4,
+ BFA_MSIX_RME_Q1 = 5,
+ BFA_MSIX_RME_Q2 = 6,
+ BFA_MSIX_RME_Q3 = 7,
+ BFA_MSIX_LPU_ERR = 8,
+ BFA_MSIX_CT_MAX = 9,
+};
+
+/*
+ * And corresponding host interrupt status bit field defines
+ */
+#define __HFN_INT_CPE_Q0 0x00000001U
+#define __HFN_INT_CPE_Q1 0x00000002U
+#define __HFN_INT_CPE_Q2 0x00000004U
+#define __HFN_INT_CPE_Q3 0x00000008U
+#define __HFN_INT_CPE_Q4 0x00000010U
+#define __HFN_INT_CPE_Q5 0x00000020U
+#define __HFN_INT_CPE_Q6 0x00000040U
+#define __HFN_INT_CPE_Q7 0x00000080U
+#define __HFN_INT_RME_Q0 0x00000100U
+#define __HFN_INT_RME_Q1 0x00000200U
+#define __HFN_INT_RME_Q2 0x00000400U
+#define __HFN_INT_RME_Q3 0x00000800U
+#define __HFN_INT_RME_Q4 0x00001000U
+#define __HFN_INT_RME_Q5 0x00002000U
+#define __HFN_INT_RME_Q6 0x00004000U
+#define __HFN_INT_RME_Q7 0x00008000U
+#define __HFN_INT_ERR_EMC 0x00010000U
+#define __HFN_INT_ERR_LPU0 0x00020000U
+#define __HFN_INT_ERR_LPU1 0x00040000U
+#define __HFN_INT_ERR_PSS 0x00080000U
+#define __HFN_INT_MBOX_LPU0 0x00100000U
+#define __HFN_INT_MBOX_LPU1 0x00200000U
+#define __HFN_INT_MBOX1_LPU0 0x00400000U
+#define __HFN_INT_MBOX1_LPU1 0x00800000U
+#define __HFN_INT_LL_HALT 0x01000000U
+#define __HFN_INT_CPE_MASK 0x000000ffU
+#define __HFN_INT_RME_MASK 0x0000ff00U
+
+/*
+ * catapult memory map.
+ */
+#define LL_PGN_HQM0 0x0096
+#define LL_PGN_HQM1 0x0097
+#define PSS_SMEM_PAGE_START 0x8000
+#define PSS_SMEM_PGNUM(_pg0, _ma) ((_pg0) + ((_ma) >> 15))
+#define PSS_SMEM_PGOFF(_ma) ((_ma) & 0x7fff)
+
+/*
+ * End of catapult memory map
+ */
+
+#endif /* __BFI_CTREG_H__ */
diff --git a/drivers/net/bna/bfi_ll.h b/drivers/net/bna/bfi_ll.h
new file mode 100644
index 000000000000..bee4d054066a
--- /dev/null
+++ b/drivers/net/bna/bfi_ll.h
@@ -0,0 +1,438 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+#ifndef __BFI_LL_H__
+#define __BFI_LL_H__
+
+#include "bfi.h"
+
+#pragma pack(1)
+
+/**
+ * @brief
+ * "enums" for all LL mailbox messages other than IOC
+ */
+enum {
+ BFI_LL_H2I_MAC_UCAST_SET_REQ = 1,
+ BFI_LL_H2I_MAC_UCAST_ADD_REQ = 2,
+ BFI_LL_H2I_MAC_UCAST_DEL_REQ = 3,
+
+ BFI_LL_H2I_MAC_MCAST_ADD_REQ = 4,
+ BFI_LL_H2I_MAC_MCAST_DEL_REQ = 5,
+ BFI_LL_H2I_MAC_MCAST_FILTER_REQ = 6,
+ BFI_LL_H2I_MAC_MCAST_DEL_ALL_REQ = 7,
+
+ BFI_LL_H2I_PORT_ADMIN_REQ = 8,
+ BFI_LL_H2I_STATS_GET_REQ = 9,
+ BFI_LL_H2I_STATS_CLEAR_REQ = 10,
+
+ BFI_LL_H2I_RXF_PROMISCUOUS_SET_REQ = 11,
+ BFI_LL_H2I_RXF_DEFAULT_SET_REQ = 12,
+
+ BFI_LL_H2I_TXQ_STOP_REQ = 13,
+ BFI_LL_H2I_RXQ_STOP_REQ = 14,
+
+ BFI_LL_H2I_DIAG_LOOPBACK_REQ = 15,
+
+ BFI_LL_H2I_SET_PAUSE_REQ = 16,
+ BFI_LL_H2I_MTU_INFO_REQ = 17,
+
+ BFI_LL_H2I_RX_REQ = 18,
+} ;
+
+enum {
+ BFI_LL_I2H_MAC_UCAST_SET_RSP = BFA_I2HM(1),
+ BFI_LL_I2H_MAC_UCAST_ADD_RSP = BFA_I2HM(2),
+ BFI_LL_I2H_MAC_UCAST_DEL_RSP = BFA_I2HM(3),
+
+ BFI_LL_I2H_MAC_MCAST_ADD_RSP = BFA_I2HM(4),
+ BFI_LL_I2H_MAC_MCAST_DEL_RSP = BFA_I2HM(5),
+ BFI_LL_I2H_MAC_MCAST_FILTER_RSP = BFA_I2HM(6),
+ BFI_LL_I2H_MAC_MCAST_DEL_ALL_RSP = BFA_I2HM(7),
+
+ BFI_LL_I2H_PORT_ADMIN_RSP = BFA_I2HM(8),
+ BFI_LL_I2H_STATS_GET_RSP = BFA_I2HM(9),
+ BFI_LL_I2H_STATS_CLEAR_RSP = BFA_I2HM(10),
+
+ BFI_LL_I2H_RXF_PROMISCUOUS_SET_RSP = BFA_I2HM(11),
+ BFI_LL_I2H_RXF_DEFAULT_SET_RSP = BFA_I2HM(12),
+
+ BFI_LL_I2H_TXQ_STOP_RSP = BFA_I2HM(13),
+ BFI_LL_I2H_RXQ_STOP_RSP = BFA_I2HM(14),
+
+ BFI_LL_I2H_DIAG_LOOPBACK_RSP = BFA_I2HM(15),
+
+ BFI_LL_I2H_SET_PAUSE_RSP = BFA_I2HM(16),
+
+ BFI_LL_I2H_MTU_INFO_RSP = BFA_I2HM(17),
+ BFI_LL_I2H_RX_RSP = BFA_I2HM(18),
+
+ BFI_LL_I2H_LINK_DOWN_AEN = BFA_I2HM(19),
+ BFI_LL_I2H_LINK_UP_AEN = BFA_I2HM(20),
+
+ BFI_LL_I2H_PORT_ENABLE_AEN = BFA_I2HM(21),
+ BFI_LL_I2H_PORT_DISABLE_AEN = BFA_I2HM(22),
+} ;
+
+/**
+ * @brief bfi_ll_mac_addr_req is used by:
+ * BFI_LL_H2I_MAC_UCAST_SET_REQ
+ * BFI_LL_H2I_MAC_UCAST_ADD_REQ
+ * BFI_LL_H2I_MAC_UCAST_DEL_REQ
+ * BFI_LL_H2I_MAC_MCAST_ADD_REQ
+ * BFI_LL_H2I_MAC_MCAST_DEL_REQ
+ */
+struct bfi_ll_mac_addr_req {
+ struct bfi_mhdr mh; /*!< common msg header */
+ u8 rxf_id;
+ u8 rsvd1[3];
+ mac_t mac_addr;
+ u8 rsvd2[2];
+};
+
+/**
+ * @brief bfi_ll_mcast_filter_req is used by:
+ * BFI_LL_H2I_MAC_MCAST_FILTER_REQ
+ */
+struct bfi_ll_mcast_filter_req {
+ struct bfi_mhdr mh; /*!< common msg header */
+ u8 rxf_id;
+ u8 enable;
+ u8 rsvd[2];
+};
+
+/**
+ * @brief bfi_ll_mcast_del_all is used by:
+ * BFI_LL_H2I_MAC_MCAST_DEL_ALL_REQ
+ */
+struct bfi_ll_mcast_del_all_req {
+ struct bfi_mhdr mh; /*!< common msg header */
+ u8 rxf_id;
+ u8 rsvd[3];
+};
+
+/**
+ * @brief bfi_ll_q_stop_req is used by:
+ * BFI_LL_H2I_TXQ_STOP_REQ
+ * BFI_LL_H2I_RXQ_STOP_REQ
+ */
+struct bfi_ll_q_stop_req {
+ struct bfi_mhdr mh; /*!< common msg header */
+ u32 q_id_mask[2]; /* !< bit-mask for queue ids */
+};
+
+/**
+ * @brief bfi_ll_stats_req is used by:
+ * BFI_LL_I2H_STATS_GET_REQ
+ * BFI_LL_I2H_STATS_CLEAR_REQ
+ */
+struct bfi_ll_stats_req {
+ struct bfi_mhdr mh; /*!< common msg header */
+ u16 stats_mask; /* !< bit-mask for non-function statistics */
+ u8 rsvd[2];
+ u32 rxf_id_mask[2]; /* !< bit-mask for RxF Statistics */
+ u32 txf_id_mask[2]; /* !< bit-mask for TxF Statistics */
+ union bfi_addr_u host_buffer; /* !< where statistics are returned */
+};
+
+/**
+ * @brief defines for "stats_mask" above.
+ */
+#define BFI_LL_STATS_MAC (1 << 0) /* !< MAC Statistics */
+#define BFI_LL_STATS_BPC (1 << 1) /* !< Pause Stats from BPC */
+#define BFI_LL_STATS_RAD (1 << 2) /* !< Rx Admission Statistics */
+#define BFI_LL_STATS_RX_FC (1 << 3) /* !< Rx FC Stats from RxA */
+#define BFI_LL_STATS_TX_FC (1 << 4) /* !< Tx FC Stats from TxA */
+
+#define BFI_LL_STATS_ALL 0x1f
+
+/**
+ * @brief bfi_ll_port_admin_req
+ */
+struct bfi_ll_port_admin_req {
+ struct bfi_mhdr mh; /*!< common msg header */
+ u8 up;
+ u8 rsvd[3];
+};
+
+/**
+ * @brief bfi_ll_rxf_req is used by:
+ * BFI_LL_H2I_RXF_PROMISCUOUS_SET_REQ
+ * BFI_LL_H2I_RXF_DEFAULT_SET_REQ
+ */
+struct bfi_ll_rxf_req {
+ struct bfi_mhdr mh; /*!< common msg header */
+ u8 rxf_id;
+ u8 enable;
+ u8 rsvd[2];
+};
+
+/**
+ * @brief bfi_ll_rxf_multi_req is used by:
+ * BFI_LL_H2I_RX_REQ
+ */
+struct bfi_ll_rxf_multi_req {
+ struct bfi_mhdr mh; /*!< common msg header */
+ u32 rxf_id_mask[2];
+ u8 enable;
+ u8 rsvd[3];
+};
+
+/**
+ * @brief enum for Loopback opmodes
+ */
+enum {
+ BFI_LL_DIAG_LB_OPMODE_EXT = 0,
+ BFI_LL_DIAG_LB_OPMODE_CBL = 1,
+};
+
+/**
+ * @brief bfi_ll_set_pause_req is used by:
+ * BFI_LL_H2I_SET_PAUSE_REQ
+ */
+struct bfi_ll_set_pause_req {
+ struct bfi_mhdr mh;
+ u8 tx_pause; /* 1 = enable, 0 = disable */
+ u8 rx_pause; /* 1 = enable, 0 = disable */
+ u8 rsvd[2];
+};
+
+/**
+ * @brief bfi_ll_mtu_info_req is used by:
+ * BFI_LL_H2I_MTU_INFO_REQ
+ */
+struct bfi_ll_mtu_info_req {
+ struct bfi_mhdr mh;
+ u16 mtu;
+ u8 rsvd[2];
+};
+
+/**
+ * @brief
+ * Response header format used by all responses
+ * For both responses and asynchronous notifications
+ */
+struct bfi_ll_rsp {
+ struct bfi_mhdr mh; /*!< common msg header */
+ u8 error;
+ u8 rsvd[3];
+};
+
+/**
+ * @brief bfi_ll_cee_aen is used by:
+ * BFI_LL_I2H_LINK_DOWN_AEN
+ * BFI_LL_I2H_LINK_UP_AEN
+ */
+struct bfi_ll_aen {
+ struct bfi_mhdr mh; /*!< common msg header */
+ u32 reason;
+ u8 cee_linkup;
+ u8 prio_map; /*!< LL priority bit-map */
+ u8 rsvd[2];
+};
+
+/**
+ * @brief
+ * The following error codes can be returned
+ * by the mbox commands
+ */
+enum {
+ BFI_LL_CMD_OK = 0,
+ BFI_LL_CMD_FAIL = 1,
+ BFI_LL_CMD_DUP_ENTRY = 2, /* !< Duplicate entry in CAM */
+ BFI_LL_CMD_CAM_FULL = 3, /* !< CAM is full */
+ BFI_LL_CMD_NOT_OWNER = 4, /* !< Not permitted, b'cos not owner */
+ BFI_LL_CMD_NOT_EXEC = 5, /* !< Was not sent to f/w at all */
+ BFI_LL_CMD_WAITING = 6, /* !< Waiting for completion (VMware) */
+ BFI_LL_CMD_PORT_DISABLED = 7, /* !< port in disabled state */
+} ;
+
+/* Statistics */
+#define BFI_LL_TXF_ID_MAX 64
+#define BFI_LL_RXF_ID_MAX 64
+
+/* TxF Frame Statistics */
+struct bfi_ll_stats_txf {
+ u64 ucast_octets;
+ u64 ucast;
+ u64 ucast_vlan;
+
+ u64 mcast_octets;
+ u64 mcast;
+ u64 mcast_vlan;
+
+ u64 bcast_octets;
+ u64 bcast;
+ u64 bcast_vlan;
+
+ u64 errors;
+ u64 filter_vlan; /* frames filtered due to VLAN */
+ u64 filter_mac_sa; /* frames filtered due to SA check */
+};
+
+/* RxF Frame Statistics */
+struct bfi_ll_stats_rxf {
+ u64 ucast_octets;
+ u64 ucast;
+ u64 ucast_vlan;
+
+ u64 mcast_octets;
+ u64 mcast;
+ u64 mcast_vlan;
+
+ u64 bcast_octets;
+ u64 bcast;
+ u64 bcast_vlan;
+ u64 frame_drops;
+};
+
+/* FC Tx Frame Statistics */
+struct bfi_ll_stats_fc_tx {
+ u64 txf_ucast_octets;
+ u64 txf_ucast;
+ u64 txf_ucast_vlan;
+
+ u64 txf_mcast_octets;
+ u64 txf_mcast;
+ u64 txf_mcast_vlan;
+
+ u64 txf_bcast_octets;
+ u64 txf_bcast;
+ u64 txf_bcast_vlan;
+
+ u64 txf_parity_errors;
+ u64 txf_timeout;
+ u64 txf_fid_parity_errors;
+};
+
+/* FC Rx Frame Statistics */
+struct bfi_ll_stats_fc_rx {
+ u64 rxf_ucast_octets;
+ u64 rxf_ucast;
+ u64 rxf_ucast_vlan;
+
+ u64 rxf_mcast_octets;
+ u64 rxf_mcast;
+ u64 rxf_mcast_vlan;
+
+ u64 rxf_bcast_octets;
+ u64 rxf_bcast;
+ u64 rxf_bcast_vlan;
+};
+
+/* RAD Frame Statistics */
+struct bfi_ll_stats_rad {
+ u64 rx_frames;
+ u64 rx_octets;
+ u64 rx_vlan_frames;
+
+ u64 rx_ucast;
+ u64 rx_ucast_octets;
+ u64 rx_ucast_vlan;
+
+ u64 rx_mcast;
+ u64 rx_mcast_octets;
+ u64 rx_mcast_vlan;
+
+ u64 rx_bcast;
+ u64 rx_bcast_octets;
+ u64 rx_bcast_vlan;
+
+ u64 rx_drops;
+};
+
+/* BPC Tx Registers */
+struct bfi_ll_stats_bpc {
+ /* transmit stats */
+ u64 tx_pause[8];
+ u64 tx_zero_pause[8]; /*!< Pause cancellation */
+ /*!<Pause initiation rather than retention */
+ u64 tx_first_pause[8];
+
+ /* receive stats */
+ u64 rx_pause[8];
+ u64 rx_zero_pause[8]; /*!< Pause cancellation */
+ /*!<Pause initiation rather than retention */
+ u64 rx_first_pause[8];
+};
+
+/* MAC Rx Statistics */
+struct bfi_ll_stats_mac {
+ u64 frame_64; /* both rx and tx counter */
+ u64 frame_65_127; /* both rx and tx counter */
+ u64 frame_128_255; /* both rx and tx counter */
+ u64 frame_256_511; /* both rx and tx counter */
+ u64 frame_512_1023; /* both rx and tx counter */
+ u64 frame_1024_1518; /* both rx and tx counter */
+ u64 frame_1519_1522; /* both rx and tx counter */
+
+ /* receive stats */
+ u64 rx_bytes;
+ u64 rx_packets;
+ u64 rx_fcs_error;
+ u64 rx_multicast;
+ u64 rx_broadcast;
+ u64 rx_control_frames;
+ u64 rx_pause;
+ u64 rx_unknown_opcode;
+ u64 rx_alignment_error;
+ u64 rx_frame_length_error;
+ u64 rx_code_error;
+ u64 rx_carrier_sense_error;
+ u64 rx_undersize;
+ u64 rx_oversize;
+ u64 rx_fragments;
+ u64 rx_jabber;
+ u64 rx_drop;
+
+ /* transmit stats */
+ u64 tx_bytes;
+ u64 tx_packets;
+ u64 tx_multicast;
+ u64 tx_broadcast;
+ u64 tx_pause;
+ u64 tx_deferral;
+ u64 tx_excessive_deferral;
+ u64 tx_single_collision;
+ u64 tx_muliple_collision;
+ u64 tx_late_collision;
+ u64 tx_excessive_collision;
+ u64 tx_total_collision;
+ u64 tx_pause_honored;
+ u64 tx_drop;
+ u64 tx_jabber;
+ u64 tx_fcs_error;
+ u64 tx_control_frame;
+ u64 tx_oversize;
+ u64 tx_undersize;
+ u64 tx_fragments;
+};
+
+/* Complete statistics */
+struct bfi_ll_stats {
+ struct bfi_ll_stats_mac mac_stats;
+ struct bfi_ll_stats_bpc bpc_stats;
+ struct bfi_ll_stats_rad rad_stats;
+ struct bfi_ll_stats_fc_rx fc_rx_stats;
+ struct bfi_ll_stats_fc_tx fc_tx_stats;
+ struct bfi_ll_stats_rxf rxf_stats[BFI_LL_RXF_ID_MAX];
+ struct bfi_ll_stats_txf txf_stats[BFI_LL_TXF_ID_MAX];
+};
+
+#pragma pack()
+
+#endif /* __BFI_LL_H__ */
diff --git a/drivers/net/bna/bna.h b/drivers/net/bna/bna.h
new file mode 100644
index 000000000000..df6676bbc84e
--- /dev/null
+++ b/drivers/net/bna/bna.h
@@ -0,0 +1,550 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+#ifndef __BNA_H__
+#define __BNA_H__
+
+#include "bfa_wc.h"
+#include "bfa_ioc.h"
+#include "cna.h"
+#include "bfi_ll.h"
+#include "bna_types.h"
+
+extern const u32 bna_napi_dim_vector[][BNA_BIAS_T_MAX];
+
+/**
+ *
+ * Macros and constants
+ *
+ */
+
+#define BNA_IOC_TIMER_FREQ 200
+
+/* Log string size */
+#define BNA_MESSAGE_SIZE 256
+
+#define bna_device_timer(_dev) bfa_timer_beat(&((_dev)->timer_mod))
+
+/* MBOX API for PORT, TX, RX */
+#define bna_mbox_qe_fill(_qe, _cmd, _cmd_len, _cbfn, _cbarg) \
+do { \
+ memcpy(&((_qe)->cmd.msg[0]), (_cmd), (_cmd_len)); \
+ (_qe)->cbfn = (_cbfn); \
+ (_qe)->cbarg = (_cbarg); \
+} while (0)
+
+#define bna_is_small_rxq(rcb) ((rcb)->id == 1)
+
+#define BNA_MAC_IS_EQUAL(_mac1, _mac2) \
+ (!memcmp((_mac1), (_mac2), sizeof(mac_t)))
+
+#define BNA_POWER_OF_2(x) (((x) & ((x) - 1)) == 0)
+
+#define BNA_TO_POWER_OF_2(x) \
+do { \
+ int _shift = 0; \
+ while ((x) && (x) != 1) { \
+ (x) >>= 1; \
+ _shift++; \
+ } \
+ (x) <<= _shift; \
+} while (0)
+
+#define BNA_TO_POWER_OF_2_HIGH(x) \
+do { \
+ int n = 1; \
+ while (n < (x)) \
+ n <<= 1; \
+ (x) = n; \
+} while (0)
+
+/*
+ * input : _addr-> os dma addr in host endian format,
+ * output : _bna_dma_addr-> pointer to hw dma addr
+ */
+#define BNA_SET_DMA_ADDR(_addr, _bna_dma_addr) \
+do { \
+ u64 tmp_addr = \
+ cpu_to_be64((u64)(_addr)); \
+ (_bna_dma_addr)->msb = ((struct bna_dma_addr *)&tmp_addr)->msb; \
+ (_bna_dma_addr)->lsb = ((struct bna_dma_addr *)&tmp_addr)->lsb; \
+} while (0)
+
+/*
+ * input : _bna_dma_addr-> pointer to hw dma addr
+ * output : _addr-> os dma addr in host endian format
+ */
+#define BNA_GET_DMA_ADDR(_bna_dma_addr, _addr) \
+do { \
+ (_addr) = ((((u64)ntohl((_bna_dma_addr)->msb))) << 32) \
+ | ((ntohl((_bna_dma_addr)->lsb) & 0xffffffff)); \
+} while (0)
+
+#define containing_rec(addr, type, field) \
+ ((type *)((unsigned char *)(addr) - \
+ (unsigned char *)(&((type *)0)->field)))
+
+#define BNA_TXQ_WI_NEEDED(_vectors) (((_vectors) + 3) >> 2)
+
+/* TxQ element is 64 bytes */
+#define BNA_TXQ_PAGE_INDEX_MAX (PAGE_SIZE >> 6)
+#define BNA_TXQ_PAGE_INDEX_MAX_SHIFT (PAGE_SHIFT - 6)
+
+#define BNA_TXQ_QPGE_PTR_GET(_qe_idx, _qpt_ptr, _qe_ptr, _qe_ptr_range) \
+{ \
+ unsigned int page_index; /* index within a page */ \
+ void *page_addr; \
+ page_index = (_qe_idx) & (BNA_TXQ_PAGE_INDEX_MAX - 1); \
+ (_qe_ptr_range) = (BNA_TXQ_PAGE_INDEX_MAX - page_index); \
+ page_addr = (_qpt_ptr)[((_qe_idx) >> BNA_TXQ_PAGE_INDEX_MAX_SHIFT)];\
+ (_qe_ptr) = &((struct bna_txq_entry *)(page_addr))[page_index]; \
+}
+
+/* RxQ element is 8 bytes */
+#define BNA_RXQ_PAGE_INDEX_MAX (PAGE_SIZE >> 3)
+#define BNA_RXQ_PAGE_INDEX_MAX_SHIFT (PAGE_SHIFT - 3)
+
+#define BNA_RXQ_QPGE_PTR_GET(_qe_idx, _qpt_ptr, _qe_ptr, _qe_ptr_range) \
+{ \
+ unsigned int page_index; /* index within a page */ \
+ void *page_addr; \
+ page_index = (_qe_idx) & (BNA_RXQ_PAGE_INDEX_MAX - 1); \
+ (_qe_ptr_range) = (BNA_RXQ_PAGE_INDEX_MAX - page_index); \
+ page_addr = (_qpt_ptr)[((_qe_idx) >> \
+ BNA_RXQ_PAGE_INDEX_MAX_SHIFT)]; \
+ (_qe_ptr) = &((struct bna_rxq_entry *)(page_addr))[page_index]; \
+}
+
+/* CQ element is 16 bytes */
+#define BNA_CQ_PAGE_INDEX_MAX (PAGE_SIZE >> 4)
+#define BNA_CQ_PAGE_INDEX_MAX_SHIFT (PAGE_SHIFT - 4)
+
+#define BNA_CQ_QPGE_PTR_GET(_qe_idx, _qpt_ptr, _qe_ptr, _qe_ptr_range) \
+{ \
+ unsigned int page_index; /* index within a page */ \
+ void *page_addr; \
+ \
+ page_index = (_qe_idx) & (BNA_CQ_PAGE_INDEX_MAX - 1); \
+ (_qe_ptr_range) = (BNA_CQ_PAGE_INDEX_MAX - page_index); \
+ page_addr = (_qpt_ptr)[((_qe_idx) >> \
+ BNA_CQ_PAGE_INDEX_MAX_SHIFT)]; \
+ (_qe_ptr) = &((struct bna_cq_entry *)(page_addr))[page_index];\
+}
+
+#define BNA_QE_INDX_2_PTR(_cast, _qe_idx, _q_base) \
+ (&((_cast *)(_q_base))[(_qe_idx)])
+
+#define BNA_QE_INDX_RANGE(_qe_idx, _q_depth) ((_q_depth) - (_qe_idx))
+
+#define BNA_QE_INDX_ADD(_qe_idx, _qe_num, _q_depth) \
+ ((_qe_idx) = ((_qe_idx) + (_qe_num)) & ((_q_depth) - 1))
+
+#define BNA_Q_INDEX_CHANGE(_old_idx, _updated_idx, _q_depth) \
+ (((_updated_idx) - (_old_idx)) & ((_q_depth) - 1))
+
+#define BNA_QE_FREE_CNT(_q_ptr, _q_depth) \
+ (((_q_ptr)->consumer_index - (_q_ptr)->producer_index - 1) & \
+ ((_q_depth) - 1))
+
+#define BNA_QE_IN_USE_CNT(_q_ptr, _q_depth) \
+ ((((_q_ptr)->producer_index - (_q_ptr)->consumer_index)) & \
+ (_q_depth - 1))
+
+#define BNA_Q_GET_CI(_q_ptr) ((_q_ptr)->q.consumer_index)
+
+#define BNA_Q_GET_PI(_q_ptr) ((_q_ptr)->q.producer_index)
+
+#define BNA_Q_PI_ADD(_q_ptr, _num) \
+ (_q_ptr)->q.producer_index = \
+ (((_q_ptr)->q.producer_index + (_num)) & \
+ ((_q_ptr)->q.q_depth - 1))
+
+#define BNA_Q_CI_ADD(_q_ptr, _num) \
+ (_q_ptr)->q.consumer_index = \
+ (((_q_ptr)->q.consumer_index + (_num)) \
+ & ((_q_ptr)->q.q_depth - 1))
+
+#define BNA_Q_FREE_COUNT(_q_ptr) \
+ (BNA_QE_FREE_CNT(&((_q_ptr)->q), (_q_ptr)->q.q_depth))
+
+#define BNA_Q_IN_USE_COUNT(_q_ptr) \
+ (BNA_QE_IN_USE_CNT(&(_q_ptr)->q, (_q_ptr)->q.q_depth))
+
+/* These macros build the data portion of the TxQ/RxQ doorbell */
+#define BNA_DOORBELL_Q_PRD_IDX(_pi) (0x80000000 | (_pi))
+#define BNA_DOORBELL_Q_STOP (0x40000000)
+
+/* These macros build the data portion of the IB doorbell */
+#define BNA_DOORBELL_IB_INT_ACK(_timeout, _events) \
+ (0x80000000 | ((_timeout) << 16) | (_events))
+#define BNA_DOORBELL_IB_INT_DISABLE (0x40000000)
+
+/* Set the coalescing timer for the given ib */
+#define bna_ib_coalescing_timer_set(_i_dbell, _cls_timer) \
+ ((_i_dbell)->doorbell_ack = BNA_DOORBELL_IB_INT_ACK((_cls_timer), 0));
+
+/* Acks 'events' # of events for a given ib */
+#define bna_ib_ack(_i_dbell, _events) \
+ (writel(((_i_dbell)->doorbell_ack | (_events)), \
+ (_i_dbell)->doorbell_addr));
+
+#define bna_txq_prod_indx_doorbell(_tcb) \
+ (writel(BNA_DOORBELL_Q_PRD_IDX((_tcb)->producer_index), \
+ (_tcb)->q_dbell));
+
+#define bna_rxq_prod_indx_doorbell(_rcb) \
+ (writel(BNA_DOORBELL_Q_PRD_IDX((_rcb)->producer_index), \
+ (_rcb)->q_dbell));
+
+#define BNA_LARGE_PKT_SIZE 1000
+
+#define BNA_UPDATE_PKT_CNT(_pkt, _len) \
+do { \
+ if ((_len) > BNA_LARGE_PKT_SIZE) { \
+ (_pkt)->large_pkt_cnt++; \
+ } else { \
+ (_pkt)->small_pkt_cnt++; \
+ } \
+} while (0)
+
+#define call_rxf_stop_cbfn(rxf, status) \
+ if ((rxf)->stop_cbfn) { \
+ (*(rxf)->stop_cbfn)((rxf)->stop_cbarg, (status)); \
+ (rxf)->stop_cbfn = NULL; \
+ (rxf)->stop_cbarg = NULL; \
+ }
+
+#define call_rxf_start_cbfn(rxf, status) \
+ if ((rxf)->start_cbfn) { \
+ (*(rxf)->start_cbfn)((rxf)->start_cbarg, (status)); \
+ (rxf)->start_cbfn = NULL; \
+ (rxf)->start_cbarg = NULL; \
+ }
+
+#define call_rxf_cam_fltr_cbfn(rxf, status) \
+ if ((rxf)->cam_fltr_cbfn) { \
+ (*(rxf)->cam_fltr_cbfn)((rxf)->cam_fltr_cbarg, rxf->rx, \
+ (status)); \
+ (rxf)->cam_fltr_cbfn = NULL; \
+ (rxf)->cam_fltr_cbarg = NULL; \
+ }
+
+#define call_rxf_pause_cbfn(rxf, status) \
+ if ((rxf)->oper_state_cbfn) { \
+ (*(rxf)->oper_state_cbfn)((rxf)->oper_state_cbarg, rxf->rx,\
+ (status)); \
+ (rxf)->rxf_flags &= ~BNA_RXF_FL_OPERSTATE_CHANGED; \
+ (rxf)->oper_state_cbfn = NULL; \
+ (rxf)->oper_state_cbarg = NULL; \
+ }
+
+#define call_rxf_resume_cbfn(rxf, status) call_rxf_pause_cbfn(rxf, status)
+
+#define is_xxx_enable(mode, bitmask, xxx) ((bitmask & xxx) && (mode & xxx))
+
+#define is_xxx_disable(mode, bitmask, xxx) ((bitmask & xxx) && !(mode & xxx))
+
+#define xxx_enable(mode, bitmask, xxx) \
+do { \
+ bitmask |= xxx; \
+ mode |= xxx; \
+} while (0)
+
+#define xxx_disable(mode, bitmask, xxx) \
+do { \
+ bitmask |= xxx; \
+ mode &= ~xxx; \
+} while (0)
+
+#define xxx_inactive(mode, bitmask, xxx) \
+do { \
+ bitmask &= ~xxx; \
+ mode &= ~xxx; \
+} while (0)
+
+#define is_promisc_enable(mode, bitmask) \
+ is_xxx_enable(mode, bitmask, BNA_RXMODE_PROMISC)
+
+#define is_promisc_disable(mode, bitmask) \
+ is_xxx_disable(mode, bitmask, BNA_RXMODE_PROMISC)
+
+#define promisc_enable(mode, bitmask) \
+ xxx_enable(mode, bitmask, BNA_RXMODE_PROMISC)
+
+#define promisc_disable(mode, bitmask) \
+ xxx_disable(mode, bitmask, BNA_RXMODE_PROMISC)
+
+#define promisc_inactive(mode, bitmask) \
+ xxx_inactive(mode, bitmask, BNA_RXMODE_PROMISC)
+
+#define is_default_enable(mode, bitmask) \
+ is_xxx_enable(mode, bitmask, BNA_RXMODE_DEFAULT)
+
+#define is_default_disable(mode, bitmask) \
+ is_xxx_disable(mode, bitmask, BNA_RXMODE_DEFAULT)
+
+#define default_enable(mode, bitmask) \
+ xxx_enable(mode, bitmask, BNA_RXMODE_DEFAULT)
+
+#define default_disable(mode, bitmask) \
+ xxx_disable(mode, bitmask, BNA_RXMODE_DEFAULT)
+
+#define default_inactive(mode, bitmask) \
+ xxx_inactive(mode, bitmask, BNA_RXMODE_DEFAULT)
+
+#define is_allmulti_enable(mode, bitmask) \
+ is_xxx_enable(mode, bitmask, BNA_RXMODE_ALLMULTI)
+
+#define is_allmulti_disable(mode, bitmask) \
+ is_xxx_disable(mode, bitmask, BNA_RXMODE_ALLMULTI)
+
+#define allmulti_enable(mode, bitmask) \
+ xxx_enable(mode, bitmask, BNA_RXMODE_ALLMULTI)
+
+#define allmulti_disable(mode, bitmask) \
+ xxx_disable(mode, bitmask, BNA_RXMODE_ALLMULTI)
+
+#define allmulti_inactive(mode, bitmask) \
+ xxx_inactive(mode, bitmask, BNA_RXMODE_ALLMULTI)
+
+#define GET_RXQS(rxp, q0, q1) do { \
+ switch ((rxp)->type) { \
+ case BNA_RXP_SINGLE: \
+ (q0) = rxp->rxq.single.only; \
+ (q1) = NULL; \
+ break; \
+ case BNA_RXP_SLR: \
+ (q0) = rxp->rxq.slr.large; \
+ (q1) = rxp->rxq.slr.small; \
+ break; \
+ case BNA_RXP_HDS: \
+ (q0) = rxp->rxq.hds.data; \
+ (q1) = rxp->rxq.hds.hdr; \
+ break; \
+ } \
+} while (0)
+
+/**
+ *
+ * Function prototypes
+ *
+ */
+
+/**
+ * BNA
+ */
+
+/* APIs for BNAD */
+void bna_res_req(struct bna_res_info *res_info);
+void bna_init(struct bna *bna, struct bnad *bnad,
+ struct bfa_pcidev *pcidev,
+ struct bna_res_info *res_info);
+void bna_uninit(struct bna *bna);
+void bna_stats_get(struct bna *bna);
+void bna_get_perm_mac(struct bna *bna, u8 *mac);
+
+/* APIs for Rx */
+int bna_rit_mod_can_satisfy(struct bna_rit_mod *rit_mod, int seg_size);
+
+/* APIs for RxF */
+struct bna_mac *bna_ucam_mod_mac_get(struct bna_ucam_mod *ucam_mod);
+void bna_ucam_mod_mac_put(struct bna_ucam_mod *ucam_mod,
+ struct bna_mac *mac);
+struct bna_mac *bna_mcam_mod_mac_get(struct bna_mcam_mod *mcam_mod);
+void bna_mcam_mod_mac_put(struct bna_mcam_mod *mcam_mod,
+ struct bna_mac *mac);
+struct bna_rit_segment *
+bna_rit_mod_seg_get(struct bna_rit_mod *rit_mod, int seg_size);
+void bna_rit_mod_seg_put(struct bna_rit_mod *rit_mod,
+ struct bna_rit_segment *seg);
+
+/**
+ * DEVICE
+ */
+
+/* APIs for BNAD */
+void bna_device_enable(struct bna_device *device);
+void bna_device_disable(struct bna_device *device,
+ enum bna_cleanup_type type);
+
+/**
+ * MBOX
+ */
+
+/* APIs for PORT, TX, RX */
+void bna_mbox_handler(struct bna *bna, u32 intr_status);
+void bna_mbox_send(struct bna *bna, struct bna_mbox_qe *mbox_qe);
+
+/**
+ * PORT
+ */
+
+/* API for RX */
+int bna_port_mtu_get(struct bna_port *port);
+void bna_llport_admin_up(struct bna_llport *llport);
+void bna_llport_admin_down(struct bna_llport *llport);
+
+/* API for BNAD */
+void bna_port_enable(struct bna_port *port);
+void bna_port_disable(struct bna_port *port, enum bna_cleanup_type type,
+ void (*cbfn)(void *, enum bna_cb_status));
+void bna_port_pause_config(struct bna_port *port,
+ struct bna_pause_config *pause_config,
+ void (*cbfn)(struct bnad *, enum bna_cb_status));
+void bna_port_mtu_set(struct bna_port *port, int mtu,
+ void (*cbfn)(struct bnad *, enum bna_cb_status));
+void bna_port_mac_get(struct bna_port *port, mac_t *mac);
+
+/* Callbacks for TX, RX */
+void bna_port_cb_tx_stopped(struct bna_port *port,
+ enum bna_cb_status status);
+void bna_port_cb_rx_stopped(struct bna_port *port,
+ enum bna_cb_status status);
+
+/**
+ * IB
+ */
+
+/* APIs for BNA */
+void bna_ib_mod_init(struct bna_ib_mod *ib_mod, struct bna *bna,
+ struct bna_res_info *res_info);
+void bna_ib_mod_uninit(struct bna_ib_mod *ib_mod);
+
+/**
+ * TX MODULE AND TX
+ */
+
+/* APIs for BNA */
+void bna_tx_mod_init(struct bna_tx_mod *tx_mod, struct bna *bna,
+ struct bna_res_info *res_info);
+void bna_tx_mod_uninit(struct bna_tx_mod *tx_mod);
+int bna_tx_state_get(struct bna_tx *tx);
+
+/* APIs for PORT */
+void bna_tx_mod_start(struct bna_tx_mod *tx_mod, enum bna_tx_type type);
+void bna_tx_mod_stop(struct bna_tx_mod *tx_mod, enum bna_tx_type type);
+void bna_tx_mod_fail(struct bna_tx_mod *tx_mod);
+void bna_tx_mod_prio_changed(struct bna_tx_mod *tx_mod, int prio);
+void bna_tx_mod_cee_link_status(struct bna_tx_mod *tx_mod, int cee_link);
+
+/* APIs for BNAD */
+void bna_tx_res_req(int num_txq, int txq_depth,
+ struct bna_res_info *res_info);
+struct bna_tx *bna_tx_create(struct bna *bna, struct bnad *bnad,
+ struct bna_tx_config *tx_cfg,
+ struct bna_tx_event_cbfn *tx_cbfn,
+ struct bna_res_info *res_info, void *priv);
+void bna_tx_destroy(struct bna_tx *tx);
+void bna_tx_enable(struct bna_tx *tx);
+void bna_tx_disable(struct bna_tx *tx, enum bna_cleanup_type type,
+ void (*cbfn)(void *, struct bna_tx *,
+ enum bna_cb_status));
+void bna_tx_coalescing_timeo_set(struct bna_tx *tx, int coalescing_timeo);
+
+/**
+ * RX MODULE, RX, RXF
+ */
+
+/* Internal APIs */
+void rxf_cb_cam_fltr_mbox_cmd(void *arg, int status);
+void rxf_cam_mbox_cmd(struct bna_rxf *rxf, u8 cmd,
+ const struct bna_mac *mac_addr);
+void __rxf_vlan_filter_set(struct bna_rxf *rxf, enum bna_status status);
+void bna_rxf_adv_init(struct bna_rxf *rxf,
+ struct bna_rx *rx,
+ struct bna_rx_config *q_config);
+int rxf_process_packet_filter_ucast(struct bna_rxf *rxf);
+int rxf_process_packet_filter_promisc(struct bna_rxf *rxf);
+int rxf_process_packet_filter_default(struct bna_rxf *rxf);
+int rxf_process_packet_filter_allmulti(struct bna_rxf *rxf);
+int rxf_clear_packet_filter_ucast(struct bna_rxf *rxf);
+int rxf_clear_packet_filter_promisc(struct bna_rxf *rxf);
+int rxf_clear_packet_filter_default(struct bna_rxf *rxf);
+int rxf_clear_packet_filter_allmulti(struct bna_rxf *rxf);
+void rxf_reset_packet_filter_ucast(struct bna_rxf *rxf);
+void rxf_reset_packet_filter_promisc(struct bna_rxf *rxf);
+void rxf_reset_packet_filter_default(struct bna_rxf *rxf);
+void rxf_reset_packet_filter_allmulti(struct bna_rxf *rxf);
+
+/* APIs for BNA */
+void bna_rx_mod_init(struct bna_rx_mod *rx_mod, struct bna *bna,
+ struct bna_res_info *res_info);
+void bna_rx_mod_uninit(struct bna_rx_mod *rx_mod);
+int bna_rx_state_get(struct bna_rx *rx);
+int bna_rxf_state_get(struct bna_rxf *rxf);
+
+/* APIs for PORT */
+void bna_rx_mod_start(struct bna_rx_mod *rx_mod, enum bna_rx_type type);
+void bna_rx_mod_stop(struct bna_rx_mod *rx_mod, enum bna_rx_type type);
+void bna_rx_mod_fail(struct bna_rx_mod *rx_mod);
+
+/* APIs for BNAD */
+void bna_rx_res_req(struct bna_rx_config *rx_config,
+ struct bna_res_info *res_info);
+struct bna_rx *bna_rx_create(struct bna *bna, struct bnad *bnad,
+ struct bna_rx_config *rx_cfg,
+ struct bna_rx_event_cbfn *rx_cbfn,
+ struct bna_res_info *res_info, void *priv);
+void bna_rx_destroy(struct bna_rx *rx);
+void bna_rx_enable(struct bna_rx *rx);
+void bna_rx_disable(struct bna_rx *rx, enum bna_cleanup_type type,
+ void (*cbfn)(void *, struct bna_rx *,
+ enum bna_cb_status));
+void bna_rx_coalescing_timeo_set(struct bna_rx *rx, int coalescing_timeo);
+void bna_rx_dim_reconfig(struct bna *bna, const u32 vector[][BNA_BIAS_T_MAX]);
+void bna_rx_dim_update(struct bna_ccb *ccb);
+enum bna_cb_status
+bna_rx_ucast_set(struct bna_rx *rx, u8 *ucmac,
+ void (*cbfn)(struct bnad *, struct bna_rx *,
+ enum bna_cb_status));
+enum bna_cb_status
+bna_rx_mcast_add(struct bna_rx *rx, u8 *mcmac,
+ void (*cbfn)(struct bnad *, struct bna_rx *,
+ enum bna_cb_status));
+enum bna_cb_status
+bna_rx_mcast_listset(struct bna_rx *rx, int count, u8 *mcmac,
+ void (*cbfn)(struct bnad *, struct bna_rx *,
+ enum bna_cb_status));
+enum bna_cb_status
+bna_rx_mode_set(struct bna_rx *rx, enum bna_rxmode rxmode,
+ enum bna_rxmode bitmask,
+ void (*cbfn)(struct bnad *, struct bna_rx *,
+ enum bna_cb_status));
+void bna_rx_vlan_add(struct bna_rx *rx, int vlan_id);
+void bna_rx_vlan_del(struct bna_rx *rx, int vlan_id);
+void bna_rx_vlanfilter_enable(struct bna_rx *rx);
+void bna_rx_hds_enable(struct bna_rx *rx, struct bna_rxf_hds *hds_config,
+ void (*cbfn)(struct bnad *, struct bna_rx *,
+ enum bna_cb_status));
+void bna_rx_hds_disable(struct bna_rx *rx,
+ void (*cbfn)(struct bnad *, struct bna_rx *,
+ enum bna_cb_status));
+
+/**
+ * BNAD
+ */
+
+/* Callbacks for BNA */
+void bnad_cb_stats_get(struct bnad *bnad, enum bna_cb_status status,
+ struct bna_stats *stats);
+
+/* Callbacks for DEVICE */
+void bnad_cb_device_enabled(struct bnad *bnad, enum bna_cb_status status);
+void bnad_cb_device_disabled(struct bnad *bnad, enum bna_cb_status status);
+void bnad_cb_device_enable_mbox_intr(struct bnad *bnad);
+void bnad_cb_device_disable_mbox_intr(struct bnad *bnad);
+
+/* Callbacks for port */
+void bnad_cb_port_link_status(struct bnad *bnad,
+ enum bna_link_status status);
+
+#endif /* __BNA_H__ */
diff --git a/drivers/net/bna/bna_ctrl.c b/drivers/net/bna/bna_ctrl.c
new file mode 100644
index 000000000000..07b26598546e
--- /dev/null
+++ b/drivers/net/bna/bna_ctrl.c
@@ -0,0 +1,3261 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+#include "bna.h"
+#include "bfa_sm.h"
+#include "bfa_wc.h"
+
+static void bna_device_cb_port_stopped(void *arg, enum bna_cb_status status);
+
+static void
+bna_port_cb_link_up(struct bna_port *port, struct bfi_ll_aen *aen,
+ int status)
+{
+ int i;
+ u8 prio_map;
+
+ port->llport.link_status = BNA_LINK_UP;
+ if (aen->cee_linkup)
+ port->llport.link_status = BNA_CEE_UP;
+
+ /* Compute the priority */
+ prio_map = aen->prio_map;
+ if (prio_map) {
+ for (i = 0; i < 8; i++) {
+ if ((prio_map >> i) & 0x1)
+ break;
+ }
+ port->priority = i;
+ } else
+ port->priority = 0;
+
+ /* Dispatch events */
+ bna_tx_mod_cee_link_status(&port->bna->tx_mod, aen->cee_linkup);
+ bna_tx_mod_prio_changed(&port->bna->tx_mod, port->priority);
+ port->link_cbfn(port->bna->bnad, port->llport.link_status);
+}
+
+static void
+bna_port_cb_link_down(struct bna_port *port, int status)
+{
+ port->llport.link_status = BNA_LINK_DOWN;
+
+ /* Dispatch events */
+ bna_tx_mod_cee_link_status(&port->bna->tx_mod, BNA_LINK_DOWN);
+ port->link_cbfn(port->bna->bnad, BNA_LINK_DOWN);
+}
+
+/**
+ * MBOX
+ */
+static int
+bna_is_aen(u8 msg_id)
+{
+ return msg_id == BFI_LL_I2H_LINK_DOWN_AEN ||
+ msg_id == BFI_LL_I2H_LINK_UP_AEN;
+}
+
+static void
+bna_mbox_aen_callback(struct bna *bna, struct bfi_mbmsg *msg)
+{
+ struct bfi_ll_aen *aen = (struct bfi_ll_aen *)(msg);
+
+ switch (aen->mh.msg_id) {
+ case BFI_LL_I2H_LINK_UP_AEN:
+ bna_port_cb_link_up(&bna->port, aen, aen->reason);
+ break;
+ case BFI_LL_I2H_LINK_DOWN_AEN:
+ bna_port_cb_link_down(&bna->port, aen->reason);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+bna_ll_isr(void *llarg, struct bfi_mbmsg *msg)
+{
+ struct bna *bna = (struct bna *)(llarg);
+ struct bfi_ll_rsp *mb_rsp = (struct bfi_ll_rsp *)(msg);
+ struct bfi_mhdr *cmd_h, *rsp_h;
+ struct bna_mbox_qe *mb_qe = NULL;
+ int to_post = 0;
+ u8 aen = 0;
+ char message[BNA_MESSAGE_SIZE];
+
+ aen = bna_is_aen(mb_rsp->mh.msg_id);
+
+ if (!aen) {
+ mb_qe = bfa_q_first(&bna->mbox_mod.posted_q);
+ cmd_h = (struct bfi_mhdr *)(&mb_qe->cmd.msg[0]);
+ rsp_h = (struct bfi_mhdr *)(&mb_rsp->mh);
+
+ if ((BFA_I2HM(cmd_h->msg_id) == rsp_h->msg_id) &&
+ (cmd_h->mtag.i2htok == rsp_h->mtag.i2htok)) {
+ /* Remove the request from posted_q, update state */
+ list_del(&mb_qe->qe);
+ bna->mbox_mod.msg_pending--;
+ if (list_empty(&bna->mbox_mod.posted_q))
+ bna->mbox_mod.state = BNA_MBOX_FREE;
+ else
+ to_post = 1;
+
+ /* Dispatch the cbfn */
+ if (mb_qe->cbfn)
+ mb_qe->cbfn(mb_qe->cbarg, mb_rsp->error);
+
+ /* Post the next entry, if needed */
+ if (to_post) {
+ mb_qe = bfa_q_first(&bna->mbox_mod.posted_q);
+ bfa_nw_ioc_mbox_queue(&bna->device.ioc,
+ &mb_qe->cmd);
+ }
+ } else {
+ snprintf(message, BNA_MESSAGE_SIZE,
+ "No matching rsp for [%d:%d:%d]\n",
+ mb_rsp->mh.msg_class, mb_rsp->mh.msg_id,
+ mb_rsp->mh.mtag.i2htok);
+ pr_info("%s", message);
+ }
+
+ } else
+ bna_mbox_aen_callback(bna, msg);
+}
+
+static void
+bna_err_handler(struct bna *bna, u32 intr_status)
+{
+ u32 init_halt;
+
+ if (intr_status & __HALT_STATUS_BITS) {
+ init_halt = readl(bna->device.ioc.ioc_regs.ll_halt);
+ init_halt &= ~__FW_INIT_HALT_P;
+ writel(init_halt, bna->device.ioc.ioc_regs.ll_halt);
+ }
+
+ bfa_nw_ioc_error_isr(&bna->device.ioc);
+}
+
+void
+bna_mbox_handler(struct bna *bna, u32 intr_status)
+{
+ if (BNA_IS_ERR_INTR(intr_status)) {
+ bna_err_handler(bna, intr_status);
+ return;
+ }
+ if (BNA_IS_MBOX_INTR(intr_status))
+ bfa_nw_ioc_mbox_isr(&bna->device.ioc);
+}
+
+void
+bna_mbox_send(struct bna *bna, struct bna_mbox_qe *mbox_qe)
+{
+ struct bfi_mhdr *mh;
+
+ mh = (struct bfi_mhdr *)(&mbox_qe->cmd.msg[0]);
+
+ mh->mtag.i2htok = htons(bna->mbox_mod.msg_ctr);
+ bna->mbox_mod.msg_ctr++;
+ bna->mbox_mod.msg_pending++;
+ if (bna->mbox_mod.state == BNA_MBOX_FREE) {
+ list_add_tail(&mbox_qe->qe, &bna->mbox_mod.posted_q);
+ bfa_nw_ioc_mbox_queue(&bna->device.ioc, &mbox_qe->cmd);
+ bna->mbox_mod.state = BNA_MBOX_POSTED;
+ } else {
+ list_add_tail(&mbox_qe->qe, &bna->mbox_mod.posted_q);
+ }
+}
+
+static void
+bna_mbox_flush_q(struct bna *bna, struct list_head *q)
+{
+ struct bna_mbox_qe *mb_qe = NULL;
+ struct bfi_mhdr *cmd_h;
+ struct list_head *mb_q;
+ void (*cbfn)(void *arg, int status);
+ void *cbarg;
+
+ mb_q = &bna->mbox_mod.posted_q;
+
+ while (!list_empty(mb_q)) {
+ bfa_q_deq(mb_q, &mb_qe);
+ cbfn = mb_qe->cbfn;
+ cbarg = mb_qe->cbarg;
+ bfa_q_qe_init(mb_qe);
+ bna->mbox_mod.msg_pending--;
+
+ cmd_h = (struct bfi_mhdr *)(&mb_qe->cmd.msg[0]);
+ if (cbfn)
+ cbfn(cbarg, BNA_CB_NOT_EXEC);
+ }
+
+ bna->mbox_mod.state = BNA_MBOX_FREE;
+}
+
+static void
+bna_mbox_mod_start(struct bna_mbox_mod *mbox_mod)
+{
+}
+
+static void
+bna_mbox_mod_stop(struct bna_mbox_mod *mbox_mod)
+{
+ bna_mbox_flush_q(mbox_mod->bna, &mbox_mod->posted_q);
+}
+
+static void
+bna_mbox_mod_init(struct bna_mbox_mod *mbox_mod, struct bna *bna)
+{
+ bfa_nw_ioc_mbox_regisr(&bna->device.ioc, BFI_MC_LL, bna_ll_isr, bna);
+ mbox_mod->state = BNA_MBOX_FREE;
+ mbox_mod->msg_ctr = mbox_mod->msg_pending = 0;
+ INIT_LIST_HEAD(&mbox_mod->posted_q);
+ mbox_mod->bna = bna;
+}
+
+static void
+bna_mbox_mod_uninit(struct bna_mbox_mod *mbox_mod)
+{
+ mbox_mod->bna = NULL;
+}
+
+/**
+ * LLPORT
+ */
+#define call_llport_stop_cbfn(llport, status)\
+do {\
+ if ((llport)->stop_cbfn)\
+ (llport)->stop_cbfn(&(llport)->bna->port, status);\
+ (llport)->stop_cbfn = NULL;\
+} while (0)
+
+static void bna_fw_llport_up(struct bna_llport *llport);
+static void bna_fw_cb_llport_up(void *arg, int status);
+static void bna_fw_llport_down(struct bna_llport *llport);
+static void bna_fw_cb_llport_down(void *arg, int status);
+static void bna_llport_start(struct bna_llport *llport);
+static void bna_llport_stop(struct bna_llport *llport);
+static void bna_llport_fail(struct bna_llport *llport);
+
+enum bna_llport_event {
+ LLPORT_E_START = 1,
+ LLPORT_E_STOP = 2,
+ LLPORT_E_FAIL = 3,
+ LLPORT_E_UP = 4,
+ LLPORT_E_DOWN = 5,
+ LLPORT_E_FWRESP_UP = 6,
+ LLPORT_E_FWRESP_DOWN = 7
+};
+
+enum bna_llport_state {
+ BNA_LLPORT_STOPPED = 1,
+ BNA_LLPORT_DOWN = 2,
+ BNA_LLPORT_UP_RESP_WAIT = 3,
+ BNA_LLPORT_DOWN_RESP_WAIT = 4,
+ BNA_LLPORT_UP = 5,
+ BNA_LLPORT_LAST_RESP_WAIT = 6
+};
+
+bfa_fsm_state_decl(bna_llport, stopped, struct bna_llport,
+ enum bna_llport_event);
+bfa_fsm_state_decl(bna_llport, down, struct bna_llport,
+ enum bna_llport_event);
+bfa_fsm_state_decl(bna_llport, up_resp_wait, struct bna_llport,
+ enum bna_llport_event);
+bfa_fsm_state_decl(bna_llport, down_resp_wait, struct bna_llport,
+ enum bna_llport_event);
+bfa_fsm_state_decl(bna_llport, up, struct bna_llport,
+ enum bna_llport_event);
+bfa_fsm_state_decl(bna_llport, last_resp_wait, struct bna_llport,
+ enum bna_llport_event);
+
+static struct bfa_sm_table llport_sm_table[] = {
+ {BFA_SM(bna_llport_sm_stopped), BNA_LLPORT_STOPPED},
+ {BFA_SM(bna_llport_sm_down), BNA_LLPORT_DOWN},
+ {BFA_SM(bna_llport_sm_up_resp_wait), BNA_LLPORT_UP_RESP_WAIT},
+ {BFA_SM(bna_llport_sm_down_resp_wait), BNA_LLPORT_DOWN_RESP_WAIT},
+ {BFA_SM(bna_llport_sm_up), BNA_LLPORT_UP},
+ {BFA_SM(bna_llport_sm_last_resp_wait), BNA_LLPORT_LAST_RESP_WAIT}
+};
+
+static void
+bna_llport_sm_stopped_entry(struct bna_llport *llport)
+{
+ llport->bna->port.link_cbfn((llport)->bna->bnad, BNA_LINK_DOWN);
+ call_llport_stop_cbfn(llport, BNA_CB_SUCCESS);
+}
+
+static void
+bna_llport_sm_stopped(struct bna_llport *llport,
+ enum bna_llport_event event)
+{
+ switch (event) {
+ case LLPORT_E_START:
+ bfa_fsm_set_state(llport, bna_llport_sm_down);
+ break;
+
+ case LLPORT_E_STOP:
+ call_llport_stop_cbfn(llport, BNA_CB_SUCCESS);
+ break;
+
+ case LLPORT_E_FAIL:
+ break;
+
+ case LLPORT_E_DOWN:
+ /* This event is received due to Rx objects failing */
+ /* No-op */
+ break;
+
+ case LLPORT_E_FWRESP_UP:
+ case LLPORT_E_FWRESP_DOWN:
+ /**
+ * These events are received due to flushing of mbox when
+ * device fails
+ */
+ /* No-op */
+ break;
+
+ default:
+ bfa_sm_fault(llport->bna, event);
+ }
+}
+
+static void
+bna_llport_sm_down_entry(struct bna_llport *llport)
+{
+ bnad_cb_port_link_status((llport)->bna->bnad, BNA_LINK_DOWN);
+}
+
+static void
+bna_llport_sm_down(struct bna_llport *llport,
+ enum bna_llport_event event)
+{
+ switch (event) {
+ case LLPORT_E_STOP:
+ bfa_fsm_set_state(llport, bna_llport_sm_stopped);
+ break;
+
+ case LLPORT_E_FAIL:
+ bfa_fsm_set_state(llport, bna_llport_sm_stopped);
+ break;
+
+ case LLPORT_E_UP:
+ bfa_fsm_set_state(llport, bna_llport_sm_up_resp_wait);
+ bna_fw_llport_up(llport);
+ break;
+
+ default:
+ bfa_sm_fault(llport->bna, event);
+ }
+}
+
+static void
+bna_llport_sm_up_resp_wait_entry(struct bna_llport *llport)
+{
+ /**
+ * NOTE: Do not call bna_fw_llport_up() here. That will over step
+ * mbox due to down_resp_wait -> up_resp_wait transition on event
+ * LLPORT_E_UP
+ */
+}
+
+static void
+bna_llport_sm_up_resp_wait(struct bna_llport *llport,
+ enum bna_llport_event event)
+{
+ switch (event) {
+ case LLPORT_E_STOP:
+ bfa_fsm_set_state(llport, bna_llport_sm_last_resp_wait);
+ break;
+
+ case LLPORT_E_FAIL:
+ bfa_fsm_set_state(llport, bna_llport_sm_stopped);
+ break;
+
+ case LLPORT_E_DOWN:
+ bfa_fsm_set_state(llport, bna_llport_sm_down_resp_wait);
+ break;
+
+ case LLPORT_E_FWRESP_UP:
+ bfa_fsm_set_state(llport, bna_llport_sm_up);
+ break;
+
+ case LLPORT_E_FWRESP_DOWN:
+ /* down_resp_wait -> up_resp_wait transition on LLPORT_E_UP */
+ bna_fw_llport_up(llport);
+ break;
+
+ default:
+ bfa_sm_fault(llport->bna, event);
+ }
+}
+
+static void
+bna_llport_sm_down_resp_wait_entry(struct bna_llport *llport)
+{
+ /**
+ * NOTE: Do not call bna_fw_llport_down() here. That will over step
+ * mbox due to up_resp_wait -> down_resp_wait transition on event
+ * LLPORT_E_DOWN
+ */
+}
+
+static void
+bna_llport_sm_down_resp_wait(struct bna_llport *llport,
+ enum bna_llport_event event)
+{
+ switch (event) {
+ case LLPORT_E_STOP:
+ bfa_fsm_set_state(llport, bna_llport_sm_last_resp_wait);
+ break;
+
+ case LLPORT_E_FAIL:
+ bfa_fsm_set_state(llport, bna_llport_sm_stopped);
+ break;
+
+ case LLPORT_E_UP:
+ bfa_fsm_set_state(llport, bna_llport_sm_up_resp_wait);
+ break;
+
+ case LLPORT_E_FWRESP_UP:
+ /* up_resp_wait->down_resp_wait transition on LLPORT_E_DOWN */
+ bna_fw_llport_down(llport);
+ break;
+
+ case LLPORT_E_FWRESP_DOWN:
+ bfa_fsm_set_state(llport, bna_llport_sm_down);
+ break;
+
+ default:
+ bfa_sm_fault(llport->bna, event);
+ }
+}
+
+static void
+bna_llport_sm_up_entry(struct bna_llport *llport)
+{
+}
+
+static void
+bna_llport_sm_up(struct bna_llport *llport,
+ enum bna_llport_event event)
+{
+ switch (event) {
+ case LLPORT_E_STOP:
+ bfa_fsm_set_state(llport, bna_llport_sm_last_resp_wait);
+ bna_fw_llport_down(llport);
+ break;
+
+ case LLPORT_E_FAIL:
+ bfa_fsm_set_state(llport, bna_llport_sm_stopped);
+ break;
+
+ case LLPORT_E_DOWN:
+ bfa_fsm_set_state(llport, bna_llport_sm_down_resp_wait);
+ bna_fw_llport_down(llport);
+ break;
+
+ default:
+ bfa_sm_fault(llport->bna, event);
+ }
+}
+
+static void
+bna_llport_sm_last_resp_wait_entry(struct bna_llport *llport)
+{
+}
+
+static void
+bna_llport_sm_last_resp_wait(struct bna_llport *llport,
+ enum bna_llport_event event)
+{
+ switch (event) {
+ case LLPORT_E_FAIL:
+ bfa_fsm_set_state(llport, bna_llport_sm_stopped);
+ break;
+
+ case LLPORT_E_DOWN:
+ /**
+ * This event is received due to Rx objects stopping in
+ * parallel to llport
+ */
+ /* No-op */
+ break;
+
+ case LLPORT_E_FWRESP_UP:
+ /* up_resp_wait->last_resp_wait transition on LLPORT_T_STOP */
+ bna_fw_llport_down(llport);
+ break;
+
+ case LLPORT_E_FWRESP_DOWN:
+ bfa_fsm_set_state(llport, bna_llport_sm_stopped);
+ break;
+
+ default:
+ bfa_sm_fault(llport->bna, event);
+ }
+}
+
+static void
+bna_fw_llport_admin_up(struct bna_llport *llport)
+{
+ struct bfi_ll_port_admin_req ll_req;
+
+ memset(&ll_req, 0, sizeof(ll_req));
+ ll_req.mh.msg_class = BFI_MC_LL;
+ ll_req.mh.msg_id = BFI_LL_H2I_PORT_ADMIN_REQ;
+ ll_req.mh.mtag.h2i.lpu_id = 0;
+
+ ll_req.up = BNA_STATUS_T_ENABLED;
+
+ bna_mbox_qe_fill(&llport->mbox_qe, &ll_req, sizeof(ll_req),
+ bna_fw_cb_llport_up, llport);
+
+ bna_mbox_send(llport->bna, &llport->mbox_qe);
+}
+
+static void
+bna_fw_llport_up(struct bna_llport *llport)
+{
+ if (llport->type == BNA_PORT_T_REGULAR)
+ bna_fw_llport_admin_up(llport);
+}
+
+static void
+bna_fw_cb_llport_up(void *arg, int status)
+{
+ struct bna_llport *llport = (struct bna_llport *)arg;
+
+ bfa_q_qe_init(&llport->mbox_qe.qe);
+ bfa_fsm_send_event(llport, LLPORT_E_FWRESP_UP);
+}
+
+static void
+bna_fw_llport_admin_down(struct bna_llport *llport)
+{
+ struct bfi_ll_port_admin_req ll_req;
+
+ memset(&ll_req, 0, sizeof(ll_req));
+ ll_req.mh.msg_class = BFI_MC_LL;
+ ll_req.mh.msg_id = BFI_LL_H2I_PORT_ADMIN_REQ;
+ ll_req.mh.mtag.h2i.lpu_id = 0;
+
+ ll_req.up = BNA_STATUS_T_DISABLED;
+
+ bna_mbox_qe_fill(&llport->mbox_qe, &ll_req, sizeof(ll_req),
+ bna_fw_cb_llport_down, llport);
+
+ bna_mbox_send(llport->bna, &llport->mbox_qe);
+}
+
+static void
+bna_fw_llport_down(struct bna_llport *llport)
+{
+ if (llport->type == BNA_PORT_T_REGULAR)
+ bna_fw_llport_admin_down(llport);
+}
+
+static void
+bna_fw_cb_llport_down(void *arg, int status)
+{
+ struct bna_llport *llport = (struct bna_llport *)arg;
+
+ bfa_q_qe_init(&llport->mbox_qe.qe);
+ bfa_fsm_send_event(llport, LLPORT_E_FWRESP_DOWN);
+}
+
+static void
+bna_port_cb_llport_stopped(struct bna_port *port,
+ enum bna_cb_status status)
+{
+ bfa_wc_down(&port->chld_stop_wc);
+}
+
+static void
+bna_llport_init(struct bna_llport *llport, struct bna *bna)
+{
+ llport->flags |= BNA_LLPORT_F_ENABLED;
+ llport->type = BNA_PORT_T_REGULAR;
+ llport->bna = bna;
+
+ llport->link_status = BNA_LINK_DOWN;
+
+ llport->admin_up_count = 0;
+
+ llport->stop_cbfn = NULL;
+
+ bfa_q_qe_init(&llport->mbox_qe.qe);
+
+ bfa_fsm_set_state(llport, bna_llport_sm_stopped);
+}
+
+static void
+bna_llport_uninit(struct bna_llport *llport)
+{
+ llport->flags &= ~BNA_LLPORT_F_ENABLED;
+
+ llport->bna = NULL;
+}
+
+static void
+bna_llport_start(struct bna_llport *llport)
+{
+ bfa_fsm_send_event(llport, LLPORT_E_START);
+}
+
+static void
+bna_llport_stop(struct bna_llport *llport)
+{
+ llport->stop_cbfn = bna_port_cb_llport_stopped;
+
+ bfa_fsm_send_event(llport, LLPORT_E_STOP);
+}
+
+static void
+bna_llport_fail(struct bna_llport *llport)
+{
+ bfa_fsm_send_event(llport, LLPORT_E_FAIL);
+}
+
+static int
+bna_llport_state_get(struct bna_llport *llport)
+{
+ return bfa_sm_to_state(llport_sm_table, llport->fsm);
+}
+
+void
+bna_llport_admin_up(struct bna_llport *llport)
+{
+ llport->admin_up_count++;
+
+ if (llport->admin_up_count == 1) {
+ llport->flags |= BNA_LLPORT_F_RX_ENABLED;
+ if (llport->flags & BNA_LLPORT_F_ENABLED)
+ bfa_fsm_send_event(llport, LLPORT_E_UP);
+ }
+}
+
+void
+bna_llport_admin_down(struct bna_llport *llport)
+{
+ llport->admin_up_count--;
+
+ if (llport->admin_up_count == 0) {
+ llport->flags &= ~BNA_LLPORT_F_RX_ENABLED;
+ if (llport->flags & BNA_LLPORT_F_ENABLED)
+ bfa_fsm_send_event(llport, LLPORT_E_DOWN);
+ }
+}
+
+/**
+ * PORT
+ */
+#define bna_port_chld_start(port)\
+do {\
+ enum bna_tx_type tx_type = ((port)->type == BNA_PORT_T_REGULAR) ?\
+ BNA_TX_T_REGULAR : BNA_TX_T_LOOPBACK;\
+ enum bna_rx_type rx_type = ((port)->type == BNA_PORT_T_REGULAR) ?\
+ BNA_RX_T_REGULAR : BNA_RX_T_LOOPBACK;\
+ bna_llport_start(&(port)->llport);\
+ bna_tx_mod_start(&(port)->bna->tx_mod, tx_type);\
+ bna_rx_mod_start(&(port)->bna->rx_mod, rx_type);\
+} while (0)
+
+#define bna_port_chld_stop(port)\
+do {\
+ enum bna_tx_type tx_type = ((port)->type == BNA_PORT_T_REGULAR) ?\
+ BNA_TX_T_REGULAR : BNA_TX_T_LOOPBACK;\
+ enum bna_rx_type rx_type = ((port)->type == BNA_PORT_T_REGULAR) ?\
+ BNA_RX_T_REGULAR : BNA_RX_T_LOOPBACK;\
+ bfa_wc_up(&(port)->chld_stop_wc);\
+ bfa_wc_up(&(port)->chld_stop_wc);\
+ bfa_wc_up(&(port)->chld_stop_wc);\
+ bna_llport_stop(&(port)->llport);\
+ bna_tx_mod_stop(&(port)->bna->tx_mod, tx_type);\
+ bna_rx_mod_stop(&(port)->bna->rx_mod, rx_type);\
+} while (0)
+
+#define bna_port_chld_fail(port)\
+do {\
+ bna_llport_fail(&(port)->llport);\
+ bna_tx_mod_fail(&(port)->bna->tx_mod);\
+ bna_rx_mod_fail(&(port)->bna->rx_mod);\
+} while (0)
+
+#define bna_port_rx_start(port)\
+do {\
+ enum bna_rx_type rx_type = ((port)->type == BNA_PORT_T_REGULAR) ?\
+ BNA_RX_T_REGULAR : BNA_RX_T_LOOPBACK;\
+ bna_rx_mod_start(&(port)->bna->rx_mod, rx_type);\
+} while (0)
+
+#define bna_port_rx_stop(port)\
+do {\
+ enum bna_rx_type rx_type = ((port)->type == BNA_PORT_T_REGULAR) ?\
+ BNA_RX_T_REGULAR : BNA_RX_T_LOOPBACK;\
+ bfa_wc_up(&(port)->chld_stop_wc);\
+ bna_rx_mod_stop(&(port)->bna->rx_mod, rx_type);\
+} while (0)
+
+#define call_port_stop_cbfn(port, status)\
+do {\
+ if ((port)->stop_cbfn)\
+ (port)->stop_cbfn((port)->stop_cbarg, status);\
+ (port)->stop_cbfn = NULL;\
+ (port)->stop_cbarg = NULL;\
+} while (0)
+
+#define call_port_pause_cbfn(port, status)\
+do {\
+ if ((port)->pause_cbfn)\
+ (port)->pause_cbfn((port)->bna->bnad, status);\
+ (port)->pause_cbfn = NULL;\
+} while (0)
+
+#define call_port_mtu_cbfn(port, status)\
+do {\
+ if ((port)->mtu_cbfn)\
+ (port)->mtu_cbfn((port)->bna->bnad, status);\
+ (port)->mtu_cbfn = NULL;\
+} while (0)
+
+static void bna_fw_pause_set(struct bna_port *port);
+static void bna_fw_cb_pause_set(void *arg, int status);
+static void bna_fw_mtu_set(struct bna_port *port);
+static void bna_fw_cb_mtu_set(void *arg, int status);
+
+enum bna_port_event {
+ PORT_E_START = 1,
+ PORT_E_STOP = 2,
+ PORT_E_FAIL = 3,
+ PORT_E_PAUSE_CFG = 4,
+ PORT_E_MTU_CFG = 5,
+ PORT_E_CHLD_STOPPED = 6,
+ PORT_E_FWRESP_PAUSE = 7,
+ PORT_E_FWRESP_MTU = 8
+};
+
+enum bna_port_state {
+ BNA_PORT_STOPPED = 1,
+ BNA_PORT_MTU_INIT_WAIT = 2,
+ BNA_PORT_PAUSE_INIT_WAIT = 3,
+ BNA_PORT_LAST_RESP_WAIT = 4,
+ BNA_PORT_STARTED = 5,
+ BNA_PORT_PAUSE_CFG_WAIT = 6,
+ BNA_PORT_RX_STOP_WAIT = 7,
+ BNA_PORT_MTU_CFG_WAIT = 8,
+ BNA_PORT_CHLD_STOP_WAIT = 9
+};
+
+bfa_fsm_state_decl(bna_port, stopped, struct bna_port,
+ enum bna_port_event);
+bfa_fsm_state_decl(bna_port, mtu_init_wait, struct bna_port,
+ enum bna_port_event);
+bfa_fsm_state_decl(bna_port, pause_init_wait, struct bna_port,
+ enum bna_port_event);
+bfa_fsm_state_decl(bna_port, last_resp_wait, struct bna_port,
+ enum bna_port_event);
+bfa_fsm_state_decl(bna_port, started, struct bna_port,
+ enum bna_port_event);
+bfa_fsm_state_decl(bna_port, pause_cfg_wait, struct bna_port,
+ enum bna_port_event);
+bfa_fsm_state_decl(bna_port, rx_stop_wait, struct bna_port,
+ enum bna_port_event);
+bfa_fsm_state_decl(bna_port, mtu_cfg_wait, struct bna_port,
+ enum bna_port_event);
+bfa_fsm_state_decl(bna_port, chld_stop_wait, struct bna_port,
+ enum bna_port_event);
+
+static struct bfa_sm_table port_sm_table[] = {
+ {BFA_SM(bna_port_sm_stopped), BNA_PORT_STOPPED},
+ {BFA_SM(bna_port_sm_mtu_init_wait), BNA_PORT_MTU_INIT_WAIT},
+ {BFA_SM(bna_port_sm_pause_init_wait), BNA_PORT_PAUSE_INIT_WAIT},
+ {BFA_SM(bna_port_sm_last_resp_wait), BNA_PORT_LAST_RESP_WAIT},
+ {BFA_SM(bna_port_sm_started), BNA_PORT_STARTED},
+ {BFA_SM(bna_port_sm_pause_cfg_wait), BNA_PORT_PAUSE_CFG_WAIT},
+ {BFA_SM(bna_port_sm_rx_stop_wait), BNA_PORT_RX_STOP_WAIT},
+ {BFA_SM(bna_port_sm_mtu_cfg_wait), BNA_PORT_MTU_CFG_WAIT},
+ {BFA_SM(bna_port_sm_chld_stop_wait), BNA_PORT_CHLD_STOP_WAIT}
+};
+
+static void
+bna_port_sm_stopped_entry(struct bna_port *port)
+{
+ call_port_pause_cbfn(port, BNA_CB_SUCCESS);
+ call_port_mtu_cbfn(port, BNA_CB_SUCCESS);
+ call_port_stop_cbfn(port, BNA_CB_SUCCESS);
+}
+
+static void
+bna_port_sm_stopped(struct bna_port *port, enum bna_port_event event)
+{
+ switch (event) {
+ case PORT_E_START:
+ bfa_fsm_set_state(port, bna_port_sm_mtu_init_wait);
+ break;
+
+ case PORT_E_STOP:
+ call_port_stop_cbfn(port, BNA_CB_SUCCESS);
+ break;
+
+ case PORT_E_FAIL:
+ /* No-op */
+ break;
+
+ case PORT_E_PAUSE_CFG:
+ call_port_pause_cbfn(port, BNA_CB_SUCCESS);
+ break;
+
+ case PORT_E_MTU_CFG:
+ call_port_mtu_cbfn(port, BNA_CB_SUCCESS);
+ break;
+
+ case PORT_E_CHLD_STOPPED:
+ /**
+ * This event is received due to LLPort, Tx and Rx objects
+ * failing
+ */
+ /* No-op */
+ break;
+
+ case PORT_E_FWRESP_PAUSE:
+ case PORT_E_FWRESP_MTU:
+ /**
+ * These events are received due to flushing of mbox when
+ * device fails
+ */
+ /* No-op */
+ break;
+
+ default:
+ bfa_sm_fault(port->bna, event);
+ }
+}
+
+static void
+bna_port_sm_mtu_init_wait_entry(struct bna_port *port)
+{
+ bna_fw_mtu_set(port);
+}
+
+static void
+bna_port_sm_mtu_init_wait(struct bna_port *port, enum bna_port_event event)
+{
+ switch (event) {
+ case PORT_E_STOP:
+ bfa_fsm_set_state(port, bna_port_sm_last_resp_wait);
+ break;
+
+ case PORT_E_FAIL:
+ bfa_fsm_set_state(port, bna_port_sm_stopped);
+ break;
+
+ case PORT_E_PAUSE_CFG:
+ /* No-op */
+ break;
+
+ case PORT_E_MTU_CFG:
+ port->flags |= BNA_PORT_F_MTU_CHANGED;
+ break;
+
+ case PORT_E_FWRESP_MTU:
+ if (port->flags & BNA_PORT_F_MTU_CHANGED) {
+ port->flags &= ~BNA_PORT_F_MTU_CHANGED;
+ bna_fw_mtu_set(port);
+ } else {
+ bfa_fsm_set_state(port, bna_port_sm_pause_init_wait);
+ }
+ break;
+
+ default:
+ bfa_sm_fault(port->bna, event);
+ }
+}
+
+static void
+bna_port_sm_pause_init_wait_entry(struct bna_port *port)
+{
+ bna_fw_pause_set(port);
+}
+
+static void
+bna_port_sm_pause_init_wait(struct bna_port *port,
+ enum bna_port_event event)
+{
+ switch (event) {
+ case PORT_E_STOP:
+ bfa_fsm_set_state(port, bna_port_sm_last_resp_wait);
+ break;
+
+ case PORT_E_FAIL:
+ bfa_fsm_set_state(port, bna_port_sm_stopped);
+ break;
+
+ case PORT_E_PAUSE_CFG:
+ port->flags |= BNA_PORT_F_PAUSE_CHANGED;
+ break;
+
+ case PORT_E_MTU_CFG:
+ port->flags |= BNA_PORT_F_MTU_CHANGED;
+ break;
+
+ case PORT_E_FWRESP_PAUSE:
+ if (port->flags & BNA_PORT_F_PAUSE_CHANGED) {
+ port->flags &= ~BNA_PORT_F_PAUSE_CHANGED;
+ bna_fw_pause_set(port);
+ } else if (port->flags & BNA_PORT_F_MTU_CHANGED) {
+ port->flags &= ~BNA_PORT_F_MTU_CHANGED;
+ bfa_fsm_set_state(port, bna_port_sm_mtu_init_wait);
+ } else {
+ bfa_fsm_set_state(port, bna_port_sm_started);
+ bna_port_chld_start(port);
+ }
+ break;
+
+ default:
+ bfa_sm_fault(port->bna, event);
+ }
+}
+
+static void
+bna_port_sm_last_resp_wait_entry(struct bna_port *port)
+{
+}
+
+static void
+bna_port_sm_last_resp_wait(struct bna_port *port,
+ enum bna_port_event event)
+{
+ switch (event) {
+ case PORT_E_FAIL:
+ case PORT_E_FWRESP_PAUSE:
+ case PORT_E_FWRESP_MTU:
+ bfa_fsm_set_state(port, bna_port_sm_stopped);
+ break;
+
+ default:
+ bfa_sm_fault(port->bna, event);
+ }
+}
+
+static void
+bna_port_sm_started_entry(struct bna_port *port)
+{
+ /**
+ * NOTE: Do not call bna_port_chld_start() here, since it will be
+ * inadvertently called during pause_cfg_wait->started transition
+ * as well
+ */
+ call_port_pause_cbfn(port, BNA_CB_SUCCESS);
+ call_port_mtu_cbfn(port, BNA_CB_SUCCESS);
+}
+
+static void
+bna_port_sm_started(struct bna_port *port,
+ enum bna_port_event event)
+{
+ switch (event) {
+ case PORT_E_STOP:
+ bfa_fsm_set_state(port, bna_port_sm_chld_stop_wait);
+ break;
+
+ case PORT_E_FAIL:
+ bfa_fsm_set_state(port, bna_port_sm_stopped);
+ bna_port_chld_fail(port);
+ break;
+
+ case PORT_E_PAUSE_CFG:
+ bfa_fsm_set_state(port, bna_port_sm_pause_cfg_wait);
+ break;
+
+ case PORT_E_MTU_CFG:
+ bfa_fsm_set_state(port, bna_port_sm_rx_stop_wait);
+ break;
+
+ default:
+ bfa_sm_fault(port->bna, event);
+ }
+}
+
+static void
+bna_port_sm_pause_cfg_wait_entry(struct bna_port *port)
+{
+ bna_fw_pause_set(port);
+}
+
+static void
+bna_port_sm_pause_cfg_wait(struct bna_port *port,
+ enum bna_port_event event)
+{
+ switch (event) {
+ case PORT_E_FAIL:
+ bfa_fsm_set_state(port, bna_port_sm_stopped);
+ bna_port_chld_fail(port);
+ break;
+
+ case PORT_E_FWRESP_PAUSE:
+ bfa_fsm_set_state(port, bna_port_sm_started);
+ break;
+
+ default:
+ bfa_sm_fault(port->bna, event);
+ }
+}
+
+static void
+bna_port_sm_rx_stop_wait_entry(struct bna_port *port)
+{
+ bna_port_rx_stop(port);
+}
+
+static void
+bna_port_sm_rx_stop_wait(struct bna_port *port,
+ enum bna_port_event event)
+{
+ switch (event) {
+ case PORT_E_FAIL:
+ bfa_fsm_set_state(port, bna_port_sm_stopped);
+ bna_port_chld_fail(port);
+ break;
+
+ case PORT_E_CHLD_STOPPED:
+ bfa_fsm_set_state(port, bna_port_sm_mtu_cfg_wait);
+ break;
+
+ default:
+ bfa_sm_fault(port->bna, event);
+ }
+}
+
+static void
+bna_port_sm_mtu_cfg_wait_entry(struct bna_port *port)
+{
+ bna_fw_mtu_set(port);
+}
+
+static void
+bna_port_sm_mtu_cfg_wait(struct bna_port *port, enum bna_port_event event)
+{
+ switch (event) {
+ case PORT_E_FAIL:
+ bfa_fsm_set_state(port, bna_port_sm_stopped);
+ bna_port_chld_fail(port);
+ break;
+
+ case PORT_E_FWRESP_MTU:
+ bfa_fsm_set_state(port, bna_port_sm_started);
+ bna_port_rx_start(port);
+ break;
+
+ default:
+ bfa_sm_fault(port->bna, event);
+ }
+}
+
+static void
+bna_port_sm_chld_stop_wait_entry(struct bna_port *port)
+{
+ bna_port_chld_stop(port);
+}
+
+static void
+bna_port_sm_chld_stop_wait(struct bna_port *port,
+ enum bna_port_event event)
+{
+ switch (event) {
+ case PORT_E_FAIL:
+ bfa_fsm_set_state(port, bna_port_sm_stopped);
+ bna_port_chld_fail(port);
+ break;
+
+ case PORT_E_CHLD_STOPPED:
+ bfa_fsm_set_state(port, bna_port_sm_stopped);
+ break;
+
+ default:
+ bfa_sm_fault(port->bna, event);
+ }
+}
+
+static void
+bna_fw_pause_set(struct bna_port *port)
+{
+ struct bfi_ll_set_pause_req ll_req;
+
+ memset(&ll_req, 0, sizeof(ll_req));
+ ll_req.mh.msg_class = BFI_MC_LL;
+ ll_req.mh.msg_id = BFI_LL_H2I_SET_PAUSE_REQ;
+ ll_req.mh.mtag.h2i.lpu_id = 0;
+
+ ll_req.tx_pause = port->pause_config.tx_pause;
+ ll_req.rx_pause = port->pause_config.rx_pause;
+
+ bna_mbox_qe_fill(&port->mbox_qe, &ll_req, sizeof(ll_req),
+ bna_fw_cb_pause_set, port);
+
+ bna_mbox_send(port->bna, &port->mbox_qe);
+}
+
+static void
+bna_fw_cb_pause_set(void *arg, int status)
+{
+ struct bna_port *port = (struct bna_port *)arg;
+
+ bfa_q_qe_init(&port->mbox_qe.qe);
+ bfa_fsm_send_event(port, PORT_E_FWRESP_PAUSE);
+}
+
+void
+bna_fw_mtu_set(struct bna_port *port)
+{
+ struct bfi_ll_mtu_info_req ll_req;
+
+ bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_MTU_INFO_REQ, 0);
+ ll_req.mtu = htons((u16)port->mtu);
+
+ bna_mbox_qe_fill(&port->mbox_qe, &ll_req, sizeof(ll_req),
+ bna_fw_cb_mtu_set, port);
+ bna_mbox_send(port->bna, &port->mbox_qe);
+}
+
+void
+bna_fw_cb_mtu_set(void *arg, int status)
+{
+ struct bna_port *port = (struct bna_port *)arg;
+
+ bfa_q_qe_init(&port->mbox_qe.qe);
+ bfa_fsm_send_event(port, PORT_E_FWRESP_MTU);
+}
+
+static void
+bna_port_cb_chld_stopped(void *arg)
+{
+ struct bna_port *port = (struct bna_port *)arg;
+
+ bfa_fsm_send_event(port, PORT_E_CHLD_STOPPED);
+}
+
+static void
+bna_port_init(struct bna_port *port, struct bna *bna)
+{
+ port->bna = bna;
+ port->flags = 0;
+ port->mtu = 0;
+ port->type = BNA_PORT_T_REGULAR;
+
+ port->link_cbfn = bnad_cb_port_link_status;
+
+ port->chld_stop_wc.wc_resume = bna_port_cb_chld_stopped;
+ port->chld_stop_wc.wc_cbarg = port;
+ port->chld_stop_wc.wc_count = 0;
+
+ port->stop_cbfn = NULL;
+ port->stop_cbarg = NULL;
+
+ port->pause_cbfn = NULL;
+
+ port->mtu_cbfn = NULL;
+
+ bfa_q_qe_init(&port->mbox_qe.qe);
+
+ bfa_fsm_set_state(port, bna_port_sm_stopped);
+
+ bna_llport_init(&port->llport, bna);
+}
+
+static void
+bna_port_uninit(struct bna_port *port)
+{
+ bna_llport_uninit(&port->llport);
+
+ port->flags = 0;
+
+ port->bna = NULL;
+}
+
+static int
+bna_port_state_get(struct bna_port *port)
+{
+ return bfa_sm_to_state(port_sm_table, port->fsm);
+}
+
+static void
+bna_port_start(struct bna_port *port)
+{
+ port->flags |= BNA_PORT_F_DEVICE_READY;
+ if (port->flags & BNA_PORT_F_ENABLED)
+ bfa_fsm_send_event(port, PORT_E_START);
+}
+
+static void
+bna_port_stop(struct bna_port *port)
+{
+ port->stop_cbfn = bna_device_cb_port_stopped;
+ port->stop_cbarg = &port->bna->device;
+
+ port->flags &= ~BNA_PORT_F_DEVICE_READY;
+ bfa_fsm_send_event(port, PORT_E_STOP);
+}
+
+static void
+bna_port_fail(struct bna_port *port)
+{
+ port->flags &= ~BNA_PORT_F_DEVICE_READY;
+ bfa_fsm_send_event(port, PORT_E_FAIL);
+}
+
+void
+bna_port_cb_tx_stopped(struct bna_port *port, enum bna_cb_status status)
+{
+ bfa_wc_down(&port->chld_stop_wc);
+}
+
+void
+bna_port_cb_rx_stopped(struct bna_port *port, enum bna_cb_status status)
+{
+ bfa_wc_down(&port->chld_stop_wc);
+}
+
+int
+bna_port_mtu_get(struct bna_port *port)
+{
+ return port->mtu;
+}
+
+void
+bna_port_enable(struct bna_port *port)
+{
+ if (port->fsm != (bfa_sm_t)bna_port_sm_stopped)
+ return;
+
+ port->flags |= BNA_PORT_F_ENABLED;
+
+ if (port->flags & BNA_PORT_F_DEVICE_READY)
+ bfa_fsm_send_event(port, PORT_E_START);
+}
+
+void
+bna_port_disable(struct bna_port *port, enum bna_cleanup_type type,
+ void (*cbfn)(void *, enum bna_cb_status))
+{
+ if (type == BNA_SOFT_CLEANUP) {
+ (*cbfn)(port->bna->bnad, BNA_CB_SUCCESS);
+ return;
+ }
+
+ port->stop_cbfn = cbfn;
+ port->stop_cbarg = port->bna->bnad;
+
+ port->flags &= ~BNA_PORT_F_ENABLED;
+
+ bfa_fsm_send_event(port, PORT_E_STOP);
+}
+
+void
+bna_port_pause_config(struct bna_port *port,
+ struct bna_pause_config *pause_config,
+ void (*cbfn)(struct bnad *, enum bna_cb_status))
+{
+ port->pause_config = *pause_config;
+
+ port->pause_cbfn = cbfn;
+
+ bfa_fsm_send_event(port, PORT_E_PAUSE_CFG);
+}
+
+void
+bna_port_mtu_set(struct bna_port *port, int mtu,
+ void (*cbfn)(struct bnad *, enum bna_cb_status))
+{
+ port->mtu = mtu;
+
+ port->mtu_cbfn = cbfn;
+
+ bfa_fsm_send_event(port, PORT_E_MTU_CFG);
+}
+
+void
+bna_port_mac_get(struct bna_port *port, mac_t *mac)
+{
+ *mac = bfa_nw_ioc_get_mac(&port->bna->device.ioc);
+}
+
+/**
+ * DEVICE
+ */
+#define enable_mbox_intr(_device)\
+do {\
+ u32 intr_status;\
+ bna_intr_status_get((_device)->bna, intr_status);\
+ bnad_cb_device_enable_mbox_intr((_device)->bna->bnad);\
+ bna_mbox_intr_enable((_device)->bna);\
+} while (0)
+
+#define disable_mbox_intr(_device)\
+do {\
+ bna_mbox_intr_disable((_device)->bna);\
+ bnad_cb_device_disable_mbox_intr((_device)->bna->bnad);\
+} while (0)
+
+static const struct bna_chip_regs_offset reg_offset[] =
+{{HOST_PAGE_NUM_FN0, HOSTFN0_INT_STATUS,
+ HOSTFN0_INT_MASK, HOST_MSIX_ERR_INDEX_FN0},
+{HOST_PAGE_NUM_FN1, HOSTFN1_INT_STATUS,
+ HOSTFN1_INT_MASK, HOST_MSIX_ERR_INDEX_FN1},
+{HOST_PAGE_NUM_FN2, HOSTFN2_INT_STATUS,
+ HOSTFN2_INT_MASK, HOST_MSIX_ERR_INDEX_FN2},
+{HOST_PAGE_NUM_FN3, HOSTFN3_INT_STATUS,
+ HOSTFN3_INT_MASK, HOST_MSIX_ERR_INDEX_FN3},
+};
+
+enum bna_device_event {
+ DEVICE_E_ENABLE = 1,
+ DEVICE_E_DISABLE = 2,
+ DEVICE_E_IOC_READY = 3,
+ DEVICE_E_IOC_FAILED = 4,
+ DEVICE_E_IOC_DISABLED = 5,
+ DEVICE_E_IOC_RESET = 6,
+ DEVICE_E_PORT_STOPPED = 7,
+};
+
+enum bna_device_state {
+ BNA_DEVICE_STOPPED = 1,
+ BNA_DEVICE_IOC_READY_WAIT = 2,
+ BNA_DEVICE_READY = 3,
+ BNA_DEVICE_PORT_STOP_WAIT = 4,
+ BNA_DEVICE_IOC_DISABLE_WAIT = 5,
+ BNA_DEVICE_FAILED = 6
+};
+
+bfa_fsm_state_decl(bna_device, stopped, struct bna_device,
+ enum bna_device_event);
+bfa_fsm_state_decl(bna_device, ioc_ready_wait, struct bna_device,
+ enum bna_device_event);
+bfa_fsm_state_decl(bna_device, ready, struct bna_device,
+ enum bna_device_event);
+bfa_fsm_state_decl(bna_device, port_stop_wait, struct bna_device,
+ enum bna_device_event);
+bfa_fsm_state_decl(bna_device, ioc_disable_wait, struct bna_device,
+ enum bna_device_event);
+bfa_fsm_state_decl(bna_device, failed, struct bna_device,
+ enum bna_device_event);
+
+static struct bfa_sm_table device_sm_table[] = {
+ {BFA_SM(bna_device_sm_stopped), BNA_DEVICE_STOPPED},
+ {BFA_SM(bna_device_sm_ioc_ready_wait), BNA_DEVICE_IOC_READY_WAIT},
+ {BFA_SM(bna_device_sm_ready), BNA_DEVICE_READY},
+ {BFA_SM(bna_device_sm_port_stop_wait), BNA_DEVICE_PORT_STOP_WAIT},
+ {BFA_SM(bna_device_sm_ioc_disable_wait), BNA_DEVICE_IOC_DISABLE_WAIT},
+ {BFA_SM(bna_device_sm_failed), BNA_DEVICE_FAILED},
+};
+
+static void
+bna_device_sm_stopped_entry(struct bna_device *device)
+{
+ if (device->stop_cbfn)
+ device->stop_cbfn(device->stop_cbarg, BNA_CB_SUCCESS);
+
+ device->stop_cbfn = NULL;
+ device->stop_cbarg = NULL;
+}
+
+static void
+bna_device_sm_stopped(struct bna_device *device,
+ enum bna_device_event event)
+{
+ switch (event) {
+ case DEVICE_E_ENABLE:
+ if (device->intr_type == BNA_INTR_T_MSIX)
+ bna_mbox_msix_idx_set(device);
+ bfa_nw_ioc_enable(&device->ioc);
+ bfa_fsm_set_state(device, bna_device_sm_ioc_ready_wait);
+ break;
+
+ case DEVICE_E_DISABLE:
+ bfa_fsm_set_state(device, bna_device_sm_stopped);
+ break;
+
+ case DEVICE_E_IOC_RESET:
+ enable_mbox_intr(device);
+ break;
+
+ case DEVICE_E_IOC_FAILED:
+ bfa_fsm_set_state(device, bna_device_sm_failed);
+ break;
+
+ default:
+ bfa_sm_fault(device->bna, event);
+ }
+}
+
+static void
+bna_device_sm_ioc_ready_wait_entry(struct bna_device *device)
+{
+ /**
+ * Do not call bfa_ioc_enable() here. It must be called in the
+ * previous state due to failed -> ioc_ready_wait transition.
+ */
+}
+
+static void
+bna_device_sm_ioc_ready_wait(struct bna_device *device,
+ enum bna_device_event event)
+{
+ switch (event) {
+ case DEVICE_E_DISABLE:
+ if (device->ready_cbfn)
+ device->ready_cbfn(device->ready_cbarg,
+ BNA_CB_INTERRUPT);
+ device->ready_cbfn = NULL;
+ device->ready_cbarg = NULL;
+ bfa_fsm_set_state(device, bna_device_sm_ioc_disable_wait);
+ break;
+
+ case DEVICE_E_IOC_READY:
+ bfa_fsm_set_state(device, bna_device_sm_ready);
+ break;
+
+ case DEVICE_E_IOC_FAILED:
+ bfa_fsm_set_state(device, bna_device_sm_failed);
+ break;
+
+ case DEVICE_E_IOC_RESET:
+ enable_mbox_intr(device);
+ break;
+
+ default:
+ bfa_sm_fault(device->bna, event);
+ }
+}
+
+static void
+bna_device_sm_ready_entry(struct bna_device *device)
+{
+ bna_mbox_mod_start(&device->bna->mbox_mod);
+ bna_port_start(&device->bna->port);
+
+ if (device->ready_cbfn)
+ device->ready_cbfn(device->ready_cbarg,
+ BNA_CB_SUCCESS);
+ device->ready_cbfn = NULL;
+ device->ready_cbarg = NULL;
+}
+
+static void
+bna_device_sm_ready(struct bna_device *device, enum bna_device_event event)
+{
+ switch (event) {
+ case DEVICE_E_DISABLE:
+ bfa_fsm_set_state(device, bna_device_sm_port_stop_wait);
+ break;
+
+ case DEVICE_E_IOC_FAILED:
+ bfa_fsm_set_state(device, bna_device_sm_failed);
+ break;
+
+ default:
+ bfa_sm_fault(device->bna, event);
+ }
+}
+
+static void
+bna_device_sm_port_stop_wait_entry(struct bna_device *device)
+{
+ bna_port_stop(&device->bna->port);
+}
+
+static void
+bna_device_sm_port_stop_wait(struct bna_device *device,
+ enum bna_device_event event)
+{
+ switch (event) {
+ case DEVICE_E_PORT_STOPPED:
+ bna_mbox_mod_stop(&device->bna->mbox_mod);
+ bfa_fsm_set_state(device, bna_device_sm_ioc_disable_wait);
+ break;
+
+ case DEVICE_E_IOC_FAILED:
+ disable_mbox_intr(device);
+ bna_port_fail(&device->bna->port);
+ break;
+
+ default:
+ bfa_sm_fault(device->bna, event);
+ }
+}
+
+static void
+bna_device_sm_ioc_disable_wait_entry(struct bna_device *device)
+{
+ bfa_nw_ioc_disable(&device->ioc);
+}
+
+static void
+bna_device_sm_ioc_disable_wait(struct bna_device *device,
+ enum bna_device_event event)
+{
+ switch (event) {
+ case DEVICE_E_IOC_DISABLED:
+ disable_mbox_intr(device);
+ bfa_fsm_set_state(device, bna_device_sm_stopped);
+ break;
+
+ default:
+ bfa_sm_fault(device->bna, event);
+ }
+}
+
+static void
+bna_device_sm_failed_entry(struct bna_device *device)
+{
+ disable_mbox_intr(device);
+ bna_port_fail(&device->bna->port);
+ bna_mbox_mod_stop(&device->bna->mbox_mod);
+
+ if (device->ready_cbfn)
+ device->ready_cbfn(device->ready_cbarg,
+ BNA_CB_FAIL);
+ device->ready_cbfn = NULL;
+ device->ready_cbarg = NULL;
+}
+
+static void
+bna_device_sm_failed(struct bna_device *device,
+ enum bna_device_event event)
+{
+ switch (event) {
+ case DEVICE_E_DISABLE:
+ bfa_fsm_set_state(device, bna_device_sm_ioc_disable_wait);
+ break;
+
+ case DEVICE_E_IOC_RESET:
+ enable_mbox_intr(device);
+ bfa_fsm_set_state(device, bna_device_sm_ioc_ready_wait);
+ break;
+
+ default:
+ bfa_sm_fault(device->bna, event);
+ }
+}
+
+/* IOC callback functions */
+
+static void
+bna_device_cb_iocll_ready(void *dev, enum bfa_status error)
+{
+ struct bna_device *device = (struct bna_device *)dev;
+
+ if (error)
+ bfa_fsm_send_event(device, DEVICE_E_IOC_FAILED);
+ else
+ bfa_fsm_send_event(device, DEVICE_E_IOC_READY);
+}
+
+static void
+bna_device_cb_iocll_disabled(void *dev)
+{
+ struct bna_device *device = (struct bna_device *)dev;
+
+ bfa_fsm_send_event(device, DEVICE_E_IOC_DISABLED);
+}
+
+static void
+bna_device_cb_iocll_failed(void *dev)
+{
+ struct bna_device *device = (struct bna_device *)dev;
+
+ bfa_fsm_send_event(device, DEVICE_E_IOC_FAILED);
+}
+
+static void
+bna_device_cb_iocll_reset(void *dev)
+{
+ struct bna_device *device = (struct bna_device *)dev;
+
+ bfa_fsm_send_event(device, DEVICE_E_IOC_RESET);
+}
+
+static struct bfa_ioc_cbfn bfa_iocll_cbfn = {
+ bna_device_cb_iocll_ready,
+ bna_device_cb_iocll_disabled,
+ bna_device_cb_iocll_failed,
+ bna_device_cb_iocll_reset
+};
+
+/* device */
+static void
+bna_adv_device_init(struct bna_device *device, struct bna *bna,
+ struct bna_res_info *res_info)
+{
+ u8 *kva;
+ u64 dma;
+
+ device->bna = bna;
+
+ kva = res_info[BNA_RES_MEM_T_FWTRC].res_u.mem_info.mdl[0].kva;
+
+ /**
+ * Attach common modules (Diag, SFP, CEE, Port) and claim respective
+ * DMA memory.
+ */
+ BNA_GET_DMA_ADDR(
+ &res_info[BNA_RES_MEM_T_COM].res_u.mem_info.mdl[0].dma, dma);
+ kva = res_info[BNA_RES_MEM_T_COM].res_u.mem_info.mdl[0].kva;
+
+ bfa_nw_cee_attach(&bna->cee, &device->ioc, bna);
+ bfa_nw_cee_mem_claim(&bna->cee, kva, dma);
+ kva += bfa_nw_cee_meminfo();
+ dma += bfa_nw_cee_meminfo();
+
+}
+
+static void
+bna_device_init(struct bna_device *device, struct bna *bna,
+ struct bna_res_info *res_info)
+{
+ u64 dma;
+
+ device->bna = bna;
+
+ /**
+ * Attach IOC and claim:
+ * 1. DMA memory for IOC attributes
+ * 2. Kernel memory for FW trace
+ */
+ bfa_nw_ioc_attach(&device->ioc, device, &bfa_iocll_cbfn);
+ bfa_nw_ioc_pci_init(&device->ioc, &bna->pcidev, BFI_MC_LL);
+
+ BNA_GET_DMA_ADDR(
+ &res_info[BNA_RES_MEM_T_ATTR].res_u.mem_info.mdl[0].dma, dma);
+ bfa_nw_ioc_mem_claim(&device->ioc,
+ res_info[BNA_RES_MEM_T_ATTR].res_u.mem_info.mdl[0].kva,
+ dma);
+
+ bna_adv_device_init(device, bna, res_info);
+ /*
+ * Initialize mbox_mod only after IOC, so that mbox handler
+ * registration goes through
+ */
+ device->intr_type =
+ res_info[BNA_RES_INTR_T_MBOX].res_u.intr_info.intr_type;
+ device->vector =
+ res_info[BNA_RES_INTR_T_MBOX].res_u.intr_info.idl[0].vector;
+ bna_mbox_mod_init(&bna->mbox_mod, bna);
+
+ device->ready_cbfn = device->stop_cbfn = NULL;
+ device->ready_cbarg = device->stop_cbarg = NULL;
+
+ bfa_fsm_set_state(device, bna_device_sm_stopped);
+}
+
+static void
+bna_device_uninit(struct bna_device *device)
+{
+ bna_mbox_mod_uninit(&device->bna->mbox_mod);
+
+ bfa_nw_ioc_detach(&device->ioc);
+
+ device->bna = NULL;
+}
+
+static void
+bna_device_cb_port_stopped(void *arg, enum bna_cb_status status)
+{
+ struct bna_device *device = (struct bna_device *)arg;
+
+ bfa_fsm_send_event(device, DEVICE_E_PORT_STOPPED);
+}
+
+static int
+bna_device_status_get(struct bna_device *device)
+{
+ return device->fsm == (bfa_fsm_t)bna_device_sm_ready;
+}
+
+void
+bna_device_enable(struct bna_device *device)
+{
+ if (device->fsm != (bfa_fsm_t)bna_device_sm_stopped) {
+ bnad_cb_device_enabled(device->bna->bnad, BNA_CB_BUSY);
+ return;
+ }
+
+ device->ready_cbfn = bnad_cb_device_enabled;
+ device->ready_cbarg = device->bna->bnad;
+
+ bfa_fsm_send_event(device, DEVICE_E_ENABLE);
+}
+
+void
+bna_device_disable(struct bna_device *device, enum bna_cleanup_type type)
+{
+ if (type == BNA_SOFT_CLEANUP) {
+ bnad_cb_device_disabled(device->bna->bnad, BNA_CB_SUCCESS);
+ return;
+ }
+
+ device->stop_cbfn = bnad_cb_device_disabled;
+ device->stop_cbarg = device->bna->bnad;
+
+ bfa_fsm_send_event(device, DEVICE_E_DISABLE);
+}
+
+static int
+bna_device_state_get(struct bna_device *device)
+{
+ return bfa_sm_to_state(device_sm_table, device->fsm);
+}
+
+const u32 bna_napi_dim_vector[BNA_LOAD_T_MAX][BNA_BIAS_T_MAX] = {
+ {12, 12},
+ {6, 10},
+ {5, 10},
+ {4, 8},
+ {3, 6},
+ {3, 6},
+ {2, 4},
+ {1, 2},
+};
+
+/* utils */
+
+static void
+bna_adv_res_req(struct bna_res_info *res_info)
+{
+ /* DMA memory for COMMON_MODULE */
+ res_info[BNA_RES_MEM_T_COM].res_type = BNA_RES_T_MEM;
+ res_info[BNA_RES_MEM_T_COM].res_u.mem_info.mem_type = BNA_MEM_T_DMA;
+ res_info[BNA_RES_MEM_T_COM].res_u.mem_info.num = 1;
+ res_info[BNA_RES_MEM_T_COM].res_u.mem_info.len = ALIGN(
+ bfa_nw_cee_meminfo(), PAGE_SIZE);
+
+ /* Virtual memory for retreiving fw_trc */
+ res_info[BNA_RES_MEM_T_FWTRC].res_type = BNA_RES_T_MEM;
+ res_info[BNA_RES_MEM_T_FWTRC].res_u.mem_info.mem_type = BNA_MEM_T_KVA;
+ res_info[BNA_RES_MEM_T_FWTRC].res_u.mem_info.num = 0;
+ res_info[BNA_RES_MEM_T_FWTRC].res_u.mem_info.len = 0;
+
+ /* DMA memory for retreiving stats */
+ res_info[BNA_RES_MEM_T_STATS].res_type = BNA_RES_T_MEM;
+ res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.mem_type = BNA_MEM_T_DMA;
+ res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.num = 1;
+ res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.len =
+ ALIGN(BFI_HW_STATS_SIZE, PAGE_SIZE);
+
+ /* Virtual memory for soft stats */
+ res_info[BNA_RES_MEM_T_SWSTATS].res_type = BNA_RES_T_MEM;
+ res_info[BNA_RES_MEM_T_SWSTATS].res_u.mem_info.mem_type = BNA_MEM_T_KVA;
+ res_info[BNA_RES_MEM_T_SWSTATS].res_u.mem_info.num = 1;
+ res_info[BNA_RES_MEM_T_SWSTATS].res_u.mem_info.len =
+ sizeof(struct bna_sw_stats);
+}
+
+static void
+bna_sw_stats_get(struct bna *bna, struct bna_sw_stats *sw_stats)
+{
+ struct bna_tx *tx;
+ struct bna_txq *txq;
+ struct bna_rx *rx;
+ struct bna_rxp *rxp;
+ struct list_head *qe;
+ struct list_head *txq_qe;
+ struct list_head *rxp_qe;
+ struct list_head *mac_qe;
+ int i;
+
+ sw_stats->device_state = bna_device_state_get(&bna->device);
+ sw_stats->port_state = bna_port_state_get(&bna->port);
+ sw_stats->port_flags = bna->port.flags;
+ sw_stats->llport_state = bna_llport_state_get(&bna->port.llport);
+ sw_stats->priority = bna->port.priority;
+
+ i = 0;
+ list_for_each(qe, &bna->tx_mod.tx_active_q) {
+ tx = (struct bna_tx *)qe;
+ sw_stats->tx_stats[i].tx_state = bna_tx_state_get(tx);
+ sw_stats->tx_stats[i].tx_flags = tx->flags;
+
+ sw_stats->tx_stats[i].num_txqs = 0;
+ sw_stats->tx_stats[i].txq_bmap[0] = 0;
+ sw_stats->tx_stats[i].txq_bmap[1] = 0;
+ list_for_each(txq_qe, &tx->txq_q) {
+ txq = (struct bna_txq *)txq_qe;
+ if (txq->txq_id < 32)
+ sw_stats->tx_stats[i].txq_bmap[0] |=
+ ((u32)1 << txq->txq_id);
+ else
+ sw_stats->tx_stats[i].txq_bmap[1] |=
+ ((u32)
+ 1 << (txq->txq_id - 32));
+ sw_stats->tx_stats[i].num_txqs++;
+ }
+
+ sw_stats->tx_stats[i].txf_id = tx->txf.txf_id;
+
+ i++;
+ }
+ sw_stats->num_active_tx = i;
+
+ i = 0;
+ list_for_each(qe, &bna->rx_mod.rx_active_q) {
+ rx = (struct bna_rx *)qe;
+ sw_stats->rx_stats[i].rx_state = bna_rx_state_get(rx);
+ sw_stats->rx_stats[i].rx_flags = rx->rx_flags;
+
+ sw_stats->rx_stats[i].num_rxps = 0;
+ sw_stats->rx_stats[i].num_rxqs = 0;
+ sw_stats->rx_stats[i].rxq_bmap[0] = 0;
+ sw_stats->rx_stats[i].rxq_bmap[1] = 0;
+ sw_stats->rx_stats[i].cq_bmap[0] = 0;
+ sw_stats->rx_stats[i].cq_bmap[1] = 0;
+ list_for_each(rxp_qe, &rx->rxp_q) {
+ rxp = (struct bna_rxp *)rxp_qe;
+
+ sw_stats->rx_stats[i].num_rxqs += 1;
+
+ if (rxp->type == BNA_RXP_SINGLE) {
+ if (rxp->rxq.single.only->rxq_id < 32) {
+ sw_stats->rx_stats[i].rxq_bmap[0] |=
+ ((u32)1 <<
+ rxp->rxq.single.only->rxq_id);
+ } else {
+ sw_stats->rx_stats[i].rxq_bmap[1] |=
+ ((u32)1 <<
+ (rxp->rxq.single.only->rxq_id - 32));
+ }
+ } else {
+ if (rxp->rxq.slr.large->rxq_id < 32) {
+ sw_stats->rx_stats[i].rxq_bmap[0] |=
+ ((u32)1 <<
+ rxp->rxq.slr.large->rxq_id);
+ } else {
+ sw_stats->rx_stats[i].rxq_bmap[1] |=
+ ((u32)1 <<
+ (rxp->rxq.slr.large->rxq_id - 32));
+ }
+
+ if (rxp->rxq.slr.small->rxq_id < 32) {
+ sw_stats->rx_stats[i].rxq_bmap[0] |=
+ ((u32)1 <<
+ rxp->rxq.slr.small->rxq_id);
+ } else {
+ sw_stats->rx_stats[i].rxq_bmap[1] |=
+ ((u32)1 <<
+ (rxp->rxq.slr.small->rxq_id - 32));
+ }
+ sw_stats->rx_stats[i].num_rxqs += 1;
+ }
+
+ if (rxp->cq.cq_id < 32)
+ sw_stats->rx_stats[i].cq_bmap[0] |=
+ (1 << rxp->cq.cq_id);
+ else
+ sw_stats->rx_stats[i].cq_bmap[1] |=
+ (1 << (rxp->cq.cq_id - 32));
+
+ sw_stats->rx_stats[i].num_rxps++;
+ }
+
+ sw_stats->rx_stats[i].rxf_id = rx->rxf.rxf_id;
+ sw_stats->rx_stats[i].rxf_state = bna_rxf_state_get(&rx->rxf);
+ sw_stats->rx_stats[i].rxf_oper_state = rx->rxf.rxf_oper_state;
+
+ sw_stats->rx_stats[i].num_active_ucast = 0;
+ if (rx->rxf.ucast_active_mac)
+ sw_stats->rx_stats[i].num_active_ucast++;
+ list_for_each(mac_qe, &rx->rxf.ucast_active_q)
+ sw_stats->rx_stats[i].num_active_ucast++;
+
+ sw_stats->rx_stats[i].num_active_mcast = 0;
+ list_for_each(mac_qe, &rx->rxf.mcast_active_q)
+ sw_stats->rx_stats[i].num_active_mcast++;
+
+ sw_stats->rx_stats[i].rxmode_active = rx->rxf.rxmode_active;
+ sw_stats->rx_stats[i].vlan_filter_status =
+ rx->rxf.vlan_filter_status;
+ memcpy(sw_stats->rx_stats[i].vlan_filter_table,
+ rx->rxf.vlan_filter_table,
+ sizeof(u32) * ((BFI_MAX_VLAN + 1) / 32));
+
+ sw_stats->rx_stats[i].rss_status = rx->rxf.rss_status;
+ sw_stats->rx_stats[i].hds_status = rx->rxf.hds_status;
+
+ i++;
+ }
+ sw_stats->num_active_rx = i;
+}
+
+static void
+bna_fw_cb_stats_get(void *arg, int status)
+{
+ struct bna *bna = (struct bna *)arg;
+ u64 *p_stats;
+ int i, count;
+ int rxf_count, txf_count;
+ u64 rxf_bmap, txf_bmap;
+
+ bfa_q_qe_init(&bna->mbox_qe.qe);
+
+ if (status == 0) {
+ p_stats = (u64 *)bna->stats.hw_stats;
+ count = sizeof(struct bfi_ll_stats) / sizeof(u64);
+ for (i = 0; i < count; i++)
+ p_stats[i] = cpu_to_be64(p_stats[i]);
+
+ rxf_count = 0;
+ rxf_bmap = (u64)bna->stats.rxf_bmap[0] |
+ ((u64)bna->stats.rxf_bmap[1] << 32);
+ for (i = 0; i < BFI_LL_RXF_ID_MAX; i++)
+ if (rxf_bmap & ((u64)1 << i))
+ rxf_count++;
+
+ txf_count = 0;
+ txf_bmap = (u64)bna->stats.txf_bmap[0] |
+ ((u64)bna->stats.txf_bmap[1] << 32);
+ for (i = 0; i < BFI_LL_TXF_ID_MAX; i++)
+ if (txf_bmap & ((u64)1 << i))
+ txf_count++;
+
+ p_stats = (u64 *)&bna->stats.hw_stats->rxf_stats[0] +
+ ((rxf_count * sizeof(struct bfi_ll_stats_rxf) +
+ txf_count * sizeof(struct bfi_ll_stats_txf))/
+ sizeof(u64));
+
+ /* Populate the TXF stats from the firmware DMAed copy */
+ for (i = (BFI_LL_TXF_ID_MAX - 1); i >= 0; i--)
+ if (txf_bmap & ((u64)1 << i)) {
+ p_stats -= sizeof(struct bfi_ll_stats_txf)/
+ sizeof(u64);
+ memcpy(&bna->stats.hw_stats->txf_stats[i],
+ p_stats,
+ sizeof(struct bfi_ll_stats_txf));
+ }
+
+ /* Populate the RXF stats from the firmware DMAed copy */
+ for (i = (BFI_LL_RXF_ID_MAX - 1); i >= 0; i--)
+ if (rxf_bmap & ((u64)1 << i)) {
+ p_stats -= sizeof(struct bfi_ll_stats_rxf)/
+ sizeof(u64);
+ memcpy(&bna->stats.hw_stats->rxf_stats[i],
+ p_stats,
+ sizeof(struct bfi_ll_stats_rxf));
+ }
+
+ bna_sw_stats_get(bna, bna->stats.sw_stats);
+ bnad_cb_stats_get(bna->bnad, BNA_CB_SUCCESS, &bna->stats);
+ } else
+ bnad_cb_stats_get(bna->bnad, BNA_CB_FAIL, &bna->stats);
+}
+
+static void
+bna_fw_stats_get(struct bna *bna)
+{
+ struct bfi_ll_stats_req ll_req;
+
+ bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_STATS_GET_REQ, 0);
+ ll_req.stats_mask = htons(BFI_LL_STATS_ALL);
+
+ ll_req.rxf_id_mask[0] = htonl(bna->rx_mod.rxf_bmap[0]);
+ ll_req.rxf_id_mask[1] = htonl(bna->rx_mod.rxf_bmap[1]);
+ ll_req.txf_id_mask[0] = htonl(bna->tx_mod.txf_bmap[0]);
+ ll_req.txf_id_mask[1] = htonl(bna->tx_mod.txf_bmap[1]);
+
+ ll_req.host_buffer.a32.addr_hi = bna->hw_stats_dma.msb;
+ ll_req.host_buffer.a32.addr_lo = bna->hw_stats_dma.lsb;
+
+ bna_mbox_qe_fill(&bna->mbox_qe, &ll_req, sizeof(ll_req),
+ bna_fw_cb_stats_get, bna);
+ bna_mbox_send(bna, &bna->mbox_qe);
+
+ bna->stats.rxf_bmap[0] = bna->rx_mod.rxf_bmap[0];
+ bna->stats.rxf_bmap[1] = bna->rx_mod.rxf_bmap[1];
+ bna->stats.txf_bmap[0] = bna->tx_mod.txf_bmap[0];
+ bna->stats.txf_bmap[1] = bna->tx_mod.txf_bmap[1];
+}
+
+void
+bna_stats_get(struct bna *bna)
+{
+ if (bna_device_status_get(&bna->device))
+ bna_fw_stats_get(bna);
+ else
+ bnad_cb_stats_get(bna->bnad, BNA_CB_FAIL, &bna->stats);
+}
+
+/* IB */
+static void
+bna_ib_coalescing_timeo_set(struct bna_ib *ib, u8 coalescing_timeo)
+{
+ ib->ib_config.coalescing_timeo = coalescing_timeo;
+
+ if (ib->start_count)
+ ib->door_bell.doorbell_ack = BNA_DOORBELL_IB_INT_ACK(
+ (u32)ib->ib_config.coalescing_timeo, 0);
+}
+
+/* RxF */
+void
+bna_rxf_adv_init(struct bna_rxf *rxf,
+ struct bna_rx *rx,
+ struct bna_rx_config *q_config)
+{
+ switch (q_config->rxp_type) {
+ case BNA_RXP_SINGLE:
+ /* No-op */
+ break;
+ case BNA_RXP_SLR:
+ rxf->ctrl_flags |= BNA_RXF_CF_SM_LG_RXQ;
+ break;
+ case BNA_RXP_HDS:
+ rxf->hds_cfg.hdr_type = q_config->hds_config.hdr_type;
+ rxf->hds_cfg.header_size =
+ q_config->hds_config.header_size;
+ rxf->forced_offset = 0;
+ break;
+ default:
+ break;
+ }
+
+ if (q_config->rss_status == BNA_STATUS_T_ENABLED) {
+ rxf->ctrl_flags |= BNA_RXF_CF_RSS_ENABLE;
+ rxf->rss_cfg.hash_type = q_config->rss_config.hash_type;
+ rxf->rss_cfg.hash_mask = q_config->rss_config.hash_mask;
+ memcpy(&rxf->rss_cfg.toeplitz_hash_key[0],
+ &q_config->rss_config.toeplitz_hash_key[0],
+ sizeof(rxf->rss_cfg.toeplitz_hash_key));
+ }
+}
+
+static void
+rxf_fltr_mbox_cmd(struct bna_rxf *rxf, u8 cmd, enum bna_status status)
+{
+ struct bfi_ll_rxf_req req;
+
+ bfi_h2i_set(req.mh, BFI_MC_LL, cmd, 0);
+
+ req.rxf_id = rxf->rxf_id;
+ req.enable = status;
+
+ bna_mbox_qe_fill(&rxf->mbox_qe, &req, sizeof(req),
+ rxf_cb_cam_fltr_mbox_cmd, rxf);
+
+ bna_mbox_send(rxf->rx->bna, &rxf->mbox_qe);
+}
+
+static void
+__rxf_default_function_config(struct bna_rxf *rxf, enum bna_status status)
+{
+ struct bna_rx_fndb_ram *rx_fndb_ram;
+ u32 ctrl_flags;
+ int i;
+
+ rx_fndb_ram = (struct bna_rx_fndb_ram *)
+ BNA_GET_MEM_BASE_ADDR(rxf->rx->bna->pcidev.pci_bar_kva,
+ RX_FNDB_RAM_BASE_OFFSET);
+
+ for (i = 0; i < BFI_MAX_RXF; i++) {
+ if (status == BNA_STATUS_T_ENABLED) {
+ if (i == rxf->rxf_id)
+ continue;
+
+ ctrl_flags =
+ readl(&rx_fndb_ram[i].control_flags);
+ ctrl_flags |= BNA_RXF_CF_DEFAULT_FUNCTION_ENABLE;
+ writel(ctrl_flags,
+ &rx_fndb_ram[i].control_flags);
+ } else {
+ ctrl_flags =
+ readl(&rx_fndb_ram[i].control_flags);
+ ctrl_flags &= ~BNA_RXF_CF_DEFAULT_FUNCTION_ENABLE;
+ writel(ctrl_flags,
+ &rx_fndb_ram[i].control_flags);
+ }
+ }
+}
+
+int
+rxf_process_packet_filter_ucast(struct bna_rxf *rxf)
+{
+ struct bna_mac *mac = NULL;
+ struct list_head *qe;
+
+ /* Add additional MAC entries */
+ if (!list_empty(&rxf->ucast_pending_add_q)) {
+ bfa_q_deq(&rxf->ucast_pending_add_q, &qe);
+ bfa_q_qe_init(qe);
+ mac = (struct bna_mac *)qe;
+ rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_UCAST_ADD_REQ, mac);
+ list_add_tail(&mac->qe, &rxf->ucast_active_q);
+ return 1;
+ }
+
+ /* Delete MAC addresses previousely added */
+ if (!list_empty(&rxf->ucast_pending_del_q)) {
+ bfa_q_deq(&rxf->ucast_pending_del_q, &qe);
+ bfa_q_qe_init(qe);
+ mac = (struct bna_mac *)qe;
+ rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_UCAST_DEL_REQ, mac);
+ bna_ucam_mod_mac_put(&rxf->rx->bna->ucam_mod, mac);
+ return 1;
+ }
+
+ return 0;
+}
+
+int
+rxf_process_packet_filter_promisc(struct bna_rxf *rxf)
+{
+ struct bna *bna = rxf->rx->bna;
+
+ /* Enable/disable promiscuous mode */
+ if (is_promisc_enable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask)) {
+ /* move promisc configuration from pending -> active */
+ promisc_inactive(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask);
+ rxf->rxmode_active |= BNA_RXMODE_PROMISC;
+
+ /* Disable VLAN filter to allow all VLANs */
+ __rxf_vlan_filter_set(rxf, BNA_STATUS_T_DISABLED);
+ rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_RXF_PROMISCUOUS_SET_REQ,
+ BNA_STATUS_T_ENABLED);
+ return 1;
+ } else if (is_promisc_disable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask)) {
+ /* move promisc configuration from pending -> active */
+ promisc_inactive(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask);
+ rxf->rxmode_active &= ~BNA_RXMODE_PROMISC;
+ bna->rxf_promisc_id = BFI_MAX_RXF;
+
+ /* Revert VLAN filter */
+ __rxf_vlan_filter_set(rxf, rxf->vlan_filter_status);
+ rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_RXF_PROMISCUOUS_SET_REQ,
+ BNA_STATUS_T_DISABLED);
+ return 1;
+ }
+
+ return 0;
+}
+
+int
+rxf_process_packet_filter_default(struct bna_rxf *rxf)
+{
+ struct bna *bna = rxf->rx->bna;
+
+ /* Enable/disable default mode */
+ if (is_default_enable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask)) {
+ /* move default configuration from pending -> active */
+ default_inactive(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask);
+ rxf->rxmode_active |= BNA_RXMODE_DEFAULT;
+
+ /* Disable VLAN filter to allow all VLANs */
+ __rxf_vlan_filter_set(rxf, BNA_STATUS_T_DISABLED);
+ /* Redirect all other RxF vlan filtering to this one */
+ __rxf_default_function_config(rxf, BNA_STATUS_T_ENABLED);
+ rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_RXF_DEFAULT_SET_REQ,
+ BNA_STATUS_T_ENABLED);
+ return 1;
+ } else if (is_default_disable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask)) {
+ /* move default configuration from pending -> active */
+ default_inactive(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask);
+ rxf->rxmode_active &= ~BNA_RXMODE_DEFAULT;
+ bna->rxf_default_id = BFI_MAX_RXF;
+
+ /* Revert VLAN filter */
+ __rxf_vlan_filter_set(rxf, rxf->vlan_filter_status);
+ /* Stop RxF vlan filter table redirection */
+ __rxf_default_function_config(rxf, BNA_STATUS_T_DISABLED);
+ rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_RXF_DEFAULT_SET_REQ,
+ BNA_STATUS_T_DISABLED);
+ return 1;
+ }
+
+ return 0;
+}
+
+int
+rxf_process_packet_filter_allmulti(struct bna_rxf *rxf)
+{
+ /* Enable/disable allmulti mode */
+ if (is_allmulti_enable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask)) {
+ /* move allmulti configuration from pending -> active */
+ allmulti_inactive(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask);
+ rxf->rxmode_active |= BNA_RXMODE_ALLMULTI;
+
+ rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_FILTER_REQ,
+ BNA_STATUS_T_ENABLED);
+ return 1;
+ } else if (is_allmulti_disable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask)) {
+ /* move allmulti configuration from pending -> active */
+ allmulti_inactive(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask);
+ rxf->rxmode_active &= ~BNA_RXMODE_ALLMULTI;
+
+ rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_FILTER_REQ,
+ BNA_STATUS_T_DISABLED);
+ return 1;
+ }
+
+ return 0;
+}
+
+int
+rxf_clear_packet_filter_ucast(struct bna_rxf *rxf)
+{
+ struct bna_mac *mac = NULL;
+ struct list_head *qe;
+
+ /* 1. delete pending ucast entries */
+ if (!list_empty(&rxf->ucast_pending_del_q)) {
+ bfa_q_deq(&rxf->ucast_pending_del_q, &qe);
+ bfa_q_qe_init(qe);
+ mac = (struct bna_mac *)qe;
+ rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_UCAST_DEL_REQ, mac);
+ bna_ucam_mod_mac_put(&rxf->rx->bna->ucam_mod, mac);
+ return 1;
+ }
+
+ /* 2. clear active ucast entries; move them to pending_add_q */
+ if (!list_empty(&rxf->ucast_active_q)) {
+ bfa_q_deq(&rxf->ucast_active_q, &qe);
+ bfa_q_qe_init(qe);
+ mac = (struct bna_mac *)qe;
+ rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_UCAST_DEL_REQ, mac);
+ list_add_tail(&mac->qe, &rxf->ucast_pending_add_q);
+ return 1;
+ }
+
+ return 0;
+}
+
+int
+rxf_clear_packet_filter_promisc(struct bna_rxf *rxf)
+{
+ struct bna *bna = rxf->rx->bna;
+
+ /* 6. Execute pending promisc mode disable command */
+ if (is_promisc_disable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask)) {
+ /* move promisc configuration from pending -> active */
+ promisc_inactive(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask);
+ rxf->rxmode_active &= ~BNA_RXMODE_PROMISC;
+ bna->rxf_promisc_id = BFI_MAX_RXF;
+
+ /* Revert VLAN filter */
+ __rxf_vlan_filter_set(rxf, rxf->vlan_filter_status);
+ rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_RXF_PROMISCUOUS_SET_REQ,
+ BNA_STATUS_T_DISABLED);
+ return 1;
+ }
+
+ /* 7. Clear active promisc mode; move it to pending enable */
+ if (rxf->rxmode_active & BNA_RXMODE_PROMISC) {
+ /* move promisc configuration from active -> pending */
+ promisc_enable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask);
+ rxf->rxmode_active &= ~BNA_RXMODE_PROMISC;
+
+ /* Revert VLAN filter */
+ __rxf_vlan_filter_set(rxf, rxf->vlan_filter_status);
+ rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_RXF_PROMISCUOUS_SET_REQ,
+ BNA_STATUS_T_DISABLED);
+ return 1;
+ }
+
+ return 0;
+}
+
+int
+rxf_clear_packet_filter_default(struct bna_rxf *rxf)
+{
+ struct bna *bna = rxf->rx->bna;
+
+ /* 8. Execute pending default mode disable command */
+ if (is_default_disable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask)) {
+ /* move default configuration from pending -> active */
+ default_inactive(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask);
+ rxf->rxmode_active &= ~BNA_RXMODE_DEFAULT;
+ bna->rxf_default_id = BFI_MAX_RXF;
+
+ /* Revert VLAN filter */
+ __rxf_vlan_filter_set(rxf, rxf->vlan_filter_status);
+ /* Stop RxF vlan filter table redirection */
+ __rxf_default_function_config(rxf, BNA_STATUS_T_DISABLED);
+ rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_RXF_DEFAULT_SET_REQ,
+ BNA_STATUS_T_DISABLED);
+ return 1;
+ }
+
+ /* 9. Clear active default mode; move it to pending enable */
+ if (rxf->rxmode_active & BNA_RXMODE_DEFAULT) {
+ /* move default configuration from active -> pending */
+ default_enable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask);
+ rxf->rxmode_active &= ~BNA_RXMODE_DEFAULT;
+
+ /* Revert VLAN filter */
+ __rxf_vlan_filter_set(rxf, rxf->vlan_filter_status);
+ /* Stop RxF vlan filter table redirection */
+ __rxf_default_function_config(rxf, BNA_STATUS_T_DISABLED);
+ rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_RXF_DEFAULT_SET_REQ,
+ BNA_STATUS_T_DISABLED);
+ return 1;
+ }
+
+ return 0;
+}
+
+int
+rxf_clear_packet_filter_allmulti(struct bna_rxf *rxf)
+{
+ /* 10. Execute pending allmulti mode disable command */
+ if (is_allmulti_disable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask)) {
+ /* move allmulti configuration from pending -> active */
+ allmulti_inactive(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask);
+ rxf->rxmode_active &= ~BNA_RXMODE_ALLMULTI;
+ rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_FILTER_REQ,
+ BNA_STATUS_T_DISABLED);
+ return 1;
+ }
+
+ /* 11. Clear active allmulti mode; move it to pending enable */
+ if (rxf->rxmode_active & BNA_RXMODE_ALLMULTI) {
+ /* move allmulti configuration from active -> pending */
+ allmulti_enable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask);
+ rxf->rxmode_active &= ~BNA_RXMODE_ALLMULTI;
+ rxf_fltr_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_FILTER_REQ,
+ BNA_STATUS_T_DISABLED);
+ return 1;
+ }
+
+ return 0;
+}
+
+void
+rxf_reset_packet_filter_ucast(struct bna_rxf *rxf)
+{
+ struct list_head *qe;
+ struct bna_mac *mac;
+
+ /* 1. Move active ucast entries to pending_add_q */
+ while (!list_empty(&rxf->ucast_active_q)) {
+ bfa_q_deq(&rxf->ucast_active_q, &qe);
+ bfa_q_qe_init(qe);
+ list_add_tail(qe, &rxf->ucast_pending_add_q);
+ }
+
+ /* 2. Throw away delete pending ucast entries */
+ while (!list_empty(&rxf->ucast_pending_del_q)) {
+ bfa_q_deq(&rxf->ucast_pending_del_q, &qe);
+ bfa_q_qe_init(qe);
+ mac = (struct bna_mac *)qe;
+ bna_ucam_mod_mac_put(&rxf->rx->bna->ucam_mod, mac);
+ }
+}
+
+void
+rxf_reset_packet_filter_promisc(struct bna_rxf *rxf)
+{
+ struct bna *bna = rxf->rx->bna;
+
+ /* 6. Clear pending promisc mode disable */
+ if (is_promisc_disable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask)) {
+ promisc_inactive(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask);
+ rxf->rxmode_active &= ~BNA_RXMODE_PROMISC;
+ bna->rxf_promisc_id = BFI_MAX_RXF;
+ }
+
+ /* 7. Move promisc mode config from active -> pending */
+ if (rxf->rxmode_active & BNA_RXMODE_PROMISC) {
+ promisc_enable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask);
+ rxf->rxmode_active &= ~BNA_RXMODE_PROMISC;
+ }
+
+}
+
+void
+rxf_reset_packet_filter_default(struct bna_rxf *rxf)
+{
+ struct bna *bna = rxf->rx->bna;
+
+ /* 8. Clear pending default mode disable */
+ if (is_default_disable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask)) {
+ default_inactive(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask);
+ rxf->rxmode_active &= ~BNA_RXMODE_DEFAULT;
+ bna->rxf_default_id = BFI_MAX_RXF;
+ }
+
+ /* 9. Move default mode config from active -> pending */
+ if (rxf->rxmode_active & BNA_RXMODE_DEFAULT) {
+ default_enable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask);
+ rxf->rxmode_active &= ~BNA_RXMODE_DEFAULT;
+ }
+}
+
+void
+rxf_reset_packet_filter_allmulti(struct bna_rxf *rxf)
+{
+ /* 10. Clear pending allmulti mode disable */
+ if (is_allmulti_disable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask)) {
+ allmulti_inactive(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask);
+ rxf->rxmode_active &= ~BNA_RXMODE_ALLMULTI;
+ }
+
+ /* 11. Move allmulti mode config from active -> pending */
+ if (rxf->rxmode_active & BNA_RXMODE_ALLMULTI) {
+ allmulti_enable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask);
+ rxf->rxmode_active &= ~BNA_RXMODE_ALLMULTI;
+ }
+}
+
+/**
+ * Should only be called by bna_rxf_mode_set.
+ * Helps deciding if h/w configuration is needed or not.
+ * Returns:
+ * 0 = no h/w change
+ * 1 = need h/w change
+ */
+static int
+rxf_promisc_enable(struct bna_rxf *rxf)
+{
+ struct bna *bna = rxf->rx->bna;
+ int ret = 0;
+
+ /* There can not be any pending disable command */
+
+ /* Do nothing if pending enable or already enabled */
+ if (is_promisc_enable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask) ||
+ (rxf->rxmode_active & BNA_RXMODE_PROMISC)) {
+ /* Schedule enable */
+ } else {
+ /* Promisc mode should not be active in the system */
+ promisc_enable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask);
+ bna->rxf_promisc_id = rxf->rxf_id;
+ ret = 1;
+ }
+
+ return ret;
+}
+
+/**
+ * Should only be called by bna_rxf_mode_set.
+ * Helps deciding if h/w configuration is needed or not.
+ * Returns:
+ * 0 = no h/w change
+ * 1 = need h/w change
+ */
+static int
+rxf_promisc_disable(struct bna_rxf *rxf)
+{
+ struct bna *bna = rxf->rx->bna;
+ int ret = 0;
+
+ /* There can not be any pending disable */
+
+ /* Turn off pending enable command , if any */
+ if (is_promisc_enable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask)) {
+ /* Promisc mode should not be active */
+ /* system promisc state should be pending */
+ promisc_inactive(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask);
+ /* Remove the promisc state from the system */
+ bna->rxf_promisc_id = BFI_MAX_RXF;
+
+ /* Schedule disable */
+ } else if (rxf->rxmode_active & BNA_RXMODE_PROMISC) {
+ /* Promisc mode should be active in the system */
+ promisc_disable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask);
+ ret = 1;
+
+ /* Do nothing if already disabled */
+ } else {
+ }
+
+ return ret;
+}
+
+/**
+ * Should only be called by bna_rxf_mode_set.
+ * Helps deciding if h/w configuration is needed or not.
+ * Returns:
+ * 0 = no h/w change
+ * 1 = need h/w change
+ */
+static int
+rxf_default_enable(struct bna_rxf *rxf)
+{
+ struct bna *bna = rxf->rx->bna;
+ int ret = 0;
+
+ /* There can not be any pending disable command */
+
+ /* Do nothing if pending enable or already enabled */
+ if (is_default_enable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask) ||
+ (rxf->rxmode_active & BNA_RXMODE_DEFAULT)) {
+ /* Schedule enable */
+ } else {
+ /* Default mode should not be active in the system */
+ default_enable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask);
+ bna->rxf_default_id = rxf->rxf_id;
+ ret = 1;
+ }
+
+ return ret;
+}
+
+/**
+ * Should only be called by bna_rxf_mode_set.
+ * Helps deciding if h/w configuration is needed or not.
+ * Returns:
+ * 0 = no h/w change
+ * 1 = need h/w change
+ */
+static int
+rxf_default_disable(struct bna_rxf *rxf)
+{
+ struct bna *bna = rxf->rx->bna;
+ int ret = 0;
+
+ /* There can not be any pending disable */
+
+ /* Turn off pending enable command , if any */
+ if (is_default_enable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask)) {
+ /* Promisc mode should not be active */
+ /* system default state should be pending */
+ default_inactive(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask);
+ /* Remove the default state from the system */
+ bna->rxf_default_id = BFI_MAX_RXF;
+
+ /* Schedule disable */
+ } else if (rxf->rxmode_active & BNA_RXMODE_DEFAULT) {
+ /* Default mode should be active in the system */
+ default_disable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask);
+ ret = 1;
+
+ /* Do nothing if already disabled */
+ } else {
+ }
+
+ return ret;
+}
+
+/**
+ * Should only be called by bna_rxf_mode_set.
+ * Helps deciding if h/w configuration is needed or not.
+ * Returns:
+ * 0 = no h/w change
+ * 1 = need h/w change
+ */
+static int
+rxf_allmulti_enable(struct bna_rxf *rxf)
+{
+ int ret = 0;
+
+ /* There can not be any pending disable command */
+
+ /* Do nothing if pending enable or already enabled */
+ if (is_allmulti_enable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask) ||
+ (rxf->rxmode_active & BNA_RXMODE_ALLMULTI)) {
+ /* Schedule enable */
+ } else {
+ allmulti_enable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask);
+ ret = 1;
+ }
+
+ return ret;
+}
+
+/**
+ * Should only be called by bna_rxf_mode_set.
+ * Helps deciding if h/w configuration is needed or not.
+ * Returns:
+ * 0 = no h/w change
+ * 1 = need h/w change
+ */
+static int
+rxf_allmulti_disable(struct bna_rxf *rxf)
+{
+ int ret = 0;
+
+ /* There can not be any pending disable */
+
+ /* Turn off pending enable command , if any */
+ if (is_allmulti_enable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask)) {
+ /* Allmulti mode should not be active */
+ allmulti_inactive(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask);
+
+ /* Schedule disable */
+ } else if (rxf->rxmode_active & BNA_RXMODE_ALLMULTI) {
+ allmulti_disable(rxf->rxmode_pending,
+ rxf->rxmode_pending_bitmask);
+ ret = 1;
+ }
+
+ return ret;
+}
+
+/* RxF <- bnad */
+enum bna_cb_status
+bna_rx_mode_set(struct bna_rx *rx, enum bna_rxmode new_mode,
+ enum bna_rxmode bitmask,
+ void (*cbfn)(struct bnad *, struct bna_rx *,
+ enum bna_cb_status))
+{
+ struct bna_rxf *rxf = &rx->rxf;
+ int need_hw_config = 0;
+
+ /* Error checks */
+
+ if (is_promisc_enable(new_mode, bitmask)) {
+ /* If promisc mode is already enabled elsewhere in the system */
+ if ((rx->bna->rxf_promisc_id != BFI_MAX_RXF) &&
+ (rx->bna->rxf_promisc_id != rxf->rxf_id))
+ goto err_return;
+
+ /* If default mode is already enabled in the system */
+ if (rx->bna->rxf_default_id != BFI_MAX_RXF)
+ goto err_return;
+
+ /* Trying to enable promiscuous and default mode together */
+ if (is_default_enable(new_mode, bitmask))
+ goto err_return;
+ }
+
+ if (is_default_enable(new_mode, bitmask)) {
+ /* If default mode is already enabled elsewhere in the system */
+ if ((rx->bna->rxf_default_id != BFI_MAX_RXF) &&
+ (rx->bna->rxf_default_id != rxf->rxf_id)) {
+ goto err_return;
+ }
+
+ /* If promiscuous mode is already enabled in the system */
+ if (rx->bna->rxf_promisc_id != BFI_MAX_RXF)
+ goto err_return;
+ }
+
+ /* Process the commands */
+
+ if (is_promisc_enable(new_mode, bitmask)) {
+ if (rxf_promisc_enable(rxf))
+ need_hw_config = 1;
+ } else if (is_promisc_disable(new_mode, bitmask)) {
+ if (rxf_promisc_disable(rxf))
+ need_hw_config = 1;
+ }
+
+ if (is_default_enable(new_mode, bitmask)) {
+ if (rxf_default_enable(rxf))
+ need_hw_config = 1;
+ } else if (is_default_disable(new_mode, bitmask)) {
+ if (rxf_default_disable(rxf))
+ need_hw_config = 1;
+ }
+
+ if (is_allmulti_enable(new_mode, bitmask)) {
+ if (rxf_allmulti_enable(rxf))
+ need_hw_config = 1;
+ } else if (is_allmulti_disable(new_mode, bitmask)) {
+ if (rxf_allmulti_disable(rxf))
+ need_hw_config = 1;
+ }
+
+ /* Trigger h/w if needed */
+
+ if (need_hw_config) {
+ rxf->cam_fltr_cbfn = cbfn;
+ rxf->cam_fltr_cbarg = rx->bna->bnad;
+ bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD);
+ } else if (cbfn)
+ (*cbfn)(rx->bna->bnad, rx, BNA_CB_SUCCESS);
+
+ return BNA_CB_SUCCESS;
+
+err_return:
+ return BNA_CB_FAIL;
+}
+
+void
+/* RxF <- bnad */
+bna_rx_vlanfilter_enable(struct bna_rx *rx)
+{
+ struct bna_rxf *rxf = &rx->rxf;
+
+ if (rxf->vlan_filter_status == BNA_STATUS_T_DISABLED) {
+ rxf->rxf_flags |= BNA_RXF_FL_VLAN_CONFIG_PENDING;
+ rxf->vlan_filter_status = BNA_STATUS_T_ENABLED;
+ bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD);
+ }
+}
+
+/* Rx */
+
+/* Rx <- bnad */
+void
+bna_rx_coalescing_timeo_set(struct bna_rx *rx, int coalescing_timeo)
+{
+ struct bna_rxp *rxp;
+ struct list_head *qe;
+
+ list_for_each(qe, &rx->rxp_q) {
+ rxp = (struct bna_rxp *)qe;
+ rxp->cq.ccb->rx_coalescing_timeo = coalescing_timeo;
+ bna_ib_coalescing_timeo_set(rxp->cq.ib, coalescing_timeo);
+ }
+}
+
+/* Rx <- bnad */
+void
+bna_rx_dim_reconfig(struct bna *bna, const u32 vector[][BNA_BIAS_T_MAX])
+{
+ int i, j;
+
+ for (i = 0; i < BNA_LOAD_T_MAX; i++)
+ for (j = 0; j < BNA_BIAS_T_MAX; j++)
+ bna->rx_mod.dim_vector[i][j] = vector[i][j];
+}
+
+/* Rx <- bnad */
+void
+bna_rx_dim_update(struct bna_ccb *ccb)
+{
+ struct bna *bna = ccb->cq->rx->bna;
+ u32 load, bias;
+ u32 pkt_rt, small_rt, large_rt;
+ u8 coalescing_timeo;
+
+ if ((ccb->pkt_rate.small_pkt_cnt == 0) &&
+ (ccb->pkt_rate.large_pkt_cnt == 0))
+ return;
+
+ /* Arrive at preconfigured coalescing timeo value based on pkt rate */
+
+ small_rt = ccb->pkt_rate.small_pkt_cnt;
+ large_rt = ccb->pkt_rate.large_pkt_cnt;
+
+ pkt_rt = small_rt + large_rt;
+
+ if (pkt_rt < BNA_PKT_RATE_10K)
+ load = BNA_LOAD_T_LOW_4;
+ else if (pkt_rt < BNA_PKT_RATE_20K)
+ load = BNA_LOAD_T_LOW_3;
+ else if (pkt_rt < BNA_PKT_RATE_30K)
+ load = BNA_LOAD_T_LOW_2;
+ else if (pkt_rt < BNA_PKT_RATE_40K)
+ load = BNA_LOAD_T_LOW_1;
+ else if (pkt_rt < BNA_PKT_RATE_50K)
+ load = BNA_LOAD_T_HIGH_1;
+ else if (pkt_rt < BNA_PKT_RATE_60K)
+ load = BNA_LOAD_T_HIGH_2;
+ else if (pkt_rt < BNA_PKT_RATE_80K)
+ load = BNA_LOAD_T_HIGH_3;
+ else
+ load = BNA_LOAD_T_HIGH_4;
+
+ if (small_rt > (large_rt << 1))
+ bias = 0;
+ else
+ bias = 1;
+
+ ccb->pkt_rate.small_pkt_cnt = 0;
+ ccb->pkt_rate.large_pkt_cnt = 0;
+
+ coalescing_timeo = bna->rx_mod.dim_vector[load][bias];
+ ccb->rx_coalescing_timeo = coalescing_timeo;
+
+ /* Set it to IB */
+ bna_ib_coalescing_timeo_set(ccb->cq->ib, coalescing_timeo);
+}
+
+/* Tx */
+/* TX <- bnad */
+void
+bna_tx_coalescing_timeo_set(struct bna_tx *tx, int coalescing_timeo)
+{
+ struct bna_txq *txq;
+ struct list_head *qe;
+
+ list_for_each(qe, &tx->txq_q) {
+ txq = (struct bna_txq *)qe;
+ bna_ib_coalescing_timeo_set(txq->ib, coalescing_timeo);
+ }
+}
+
+/*
+ * Private data
+ */
+
+struct bna_ritseg_pool_cfg {
+ u32 pool_size;
+ u32 pool_entry_size;
+};
+init_ritseg_pool(ritseg_pool_cfg);
+
+/*
+ * Private functions
+ */
+static void
+bna_ucam_mod_init(struct bna_ucam_mod *ucam_mod, struct bna *bna,
+ struct bna_res_info *res_info)
+{
+ int i;
+
+ ucam_mod->ucmac = (struct bna_mac *)
+ res_info[BNA_RES_MEM_T_UCMAC_ARRAY].res_u.mem_info.mdl[0].kva;
+
+ INIT_LIST_HEAD(&ucam_mod->free_q);
+ for (i = 0; i < BFI_MAX_UCMAC; i++) {
+ bfa_q_qe_init(&ucam_mod->ucmac[i].qe);
+ list_add_tail(&ucam_mod->ucmac[i].qe, &ucam_mod->free_q);
+ }
+
+ ucam_mod->bna = bna;
+}
+
+static void
+bna_ucam_mod_uninit(struct bna_ucam_mod *ucam_mod)
+{
+ struct list_head *qe;
+ int i = 0;
+
+ list_for_each(qe, &ucam_mod->free_q)
+ i++;
+
+ ucam_mod->bna = NULL;
+}
+
+static void
+bna_mcam_mod_init(struct bna_mcam_mod *mcam_mod, struct bna *bna,
+ struct bna_res_info *res_info)
+{
+ int i;
+
+ mcam_mod->mcmac = (struct bna_mac *)
+ res_info[BNA_RES_MEM_T_MCMAC_ARRAY].res_u.mem_info.mdl[0].kva;
+
+ INIT_LIST_HEAD(&mcam_mod->free_q);
+ for (i = 0; i < BFI_MAX_MCMAC; i++) {
+ bfa_q_qe_init(&mcam_mod->mcmac[i].qe);
+ list_add_tail(&mcam_mod->mcmac[i].qe, &mcam_mod->free_q);
+ }
+
+ mcam_mod->bna = bna;
+}
+
+static void
+bna_mcam_mod_uninit(struct bna_mcam_mod *mcam_mod)
+{
+ struct list_head *qe;
+ int i = 0;
+
+ list_for_each(qe, &mcam_mod->free_q)
+ i++;
+
+ mcam_mod->bna = NULL;
+}
+
+static void
+bna_rit_mod_init(struct bna_rit_mod *rit_mod,
+ struct bna_res_info *res_info)
+{
+ int i;
+ int j;
+ int count;
+ int offset;
+
+ rit_mod->rit = (struct bna_rit_entry *)
+ res_info[BNA_RES_MEM_T_RIT_ENTRY].res_u.mem_info.mdl[0].kva;
+ rit_mod->rit_segment = (struct bna_rit_segment *)
+ res_info[BNA_RES_MEM_T_RIT_SEGMENT].res_u.mem_info.mdl[0].kva;
+
+ count = 0;
+ offset = 0;
+ for (i = 0; i < BFI_RIT_SEG_TOTAL_POOLS; i++) {
+ INIT_LIST_HEAD(&rit_mod->rit_seg_pool[i]);
+ for (j = 0; j < ritseg_pool_cfg[i].pool_size; j++) {
+ bfa_q_qe_init(&rit_mod->rit_segment[count].qe);
+ rit_mod->rit_segment[count].max_rit_size =
+ ritseg_pool_cfg[i].pool_entry_size;
+ rit_mod->rit_segment[count].rit_offset = offset;
+ rit_mod->rit_segment[count].rit =
+ &rit_mod->rit[offset];
+ list_add_tail(&rit_mod->rit_segment[count].qe,
+ &rit_mod->rit_seg_pool[i]);
+ count++;
+ offset += ritseg_pool_cfg[i].pool_entry_size;
+ }
+ }
+}
+
+static void
+bna_rit_mod_uninit(struct bna_rit_mod *rit_mod)
+{
+ struct bna_rit_segment *rit_segment;
+ struct list_head *qe;
+ int i;
+ int j;
+
+ for (i = 0; i < BFI_RIT_SEG_TOTAL_POOLS; i++) {
+ j = 0;
+ list_for_each(qe, &rit_mod->rit_seg_pool[i]) {
+ rit_segment = (struct bna_rit_segment *)qe;
+ j++;
+ }
+ }
+}
+
+/*
+ * Public functions
+ */
+
+/* Called during probe(), before calling bna_init() */
+void
+bna_res_req(struct bna_res_info *res_info)
+{
+ bna_adv_res_req(res_info);
+
+ /* DMA memory for retrieving IOC attributes */
+ res_info[BNA_RES_MEM_T_ATTR].res_type = BNA_RES_T_MEM;
+ res_info[BNA_RES_MEM_T_ATTR].res_u.mem_info.mem_type = BNA_MEM_T_DMA;
+ res_info[BNA_RES_MEM_T_ATTR].res_u.mem_info.num = 1;
+ res_info[BNA_RES_MEM_T_ATTR].res_u.mem_info.len =
+ ALIGN(bfa_nw_ioc_meminfo(), PAGE_SIZE);
+
+ /* DMA memory for index segment of an IB */
+ res_info[BNA_RES_MEM_T_IBIDX].res_type = BNA_RES_T_MEM;
+ res_info[BNA_RES_MEM_T_IBIDX].res_u.mem_info.mem_type = BNA_MEM_T_DMA;
+ res_info[BNA_RES_MEM_T_IBIDX].res_u.mem_info.len =
+ BFI_IBIDX_SIZE * BFI_IBIDX_MAX_SEGSIZE;
+ res_info[BNA_RES_MEM_T_IBIDX].res_u.mem_info.num = BFI_MAX_IB;
+
+ /* Virtual memory for IB objects - stored by IB module */
+ res_info[BNA_RES_MEM_T_IB_ARRAY].res_type = BNA_RES_T_MEM;
+ res_info[BNA_RES_MEM_T_IB_ARRAY].res_u.mem_info.mem_type =
+ BNA_MEM_T_KVA;
+ res_info[BNA_RES_MEM_T_IB_ARRAY].res_u.mem_info.num = 1;
+ res_info[BNA_RES_MEM_T_IB_ARRAY].res_u.mem_info.len =
+ BFI_MAX_IB * sizeof(struct bna_ib);
+
+ /* Virtual memory for intr objects - stored by IB module */
+ res_info[BNA_RES_MEM_T_INTR_ARRAY].res_type = BNA_RES_T_MEM;
+ res_info[BNA_RES_MEM_T_INTR_ARRAY].res_u.mem_info.mem_type =
+ BNA_MEM_T_KVA;
+ res_info[BNA_RES_MEM_T_INTR_ARRAY].res_u.mem_info.num = 1;
+ res_info[BNA_RES_MEM_T_INTR_ARRAY].res_u.mem_info.len =
+ BFI_MAX_IB * sizeof(struct bna_intr);
+
+ /* Virtual memory for idx_seg objects - stored by IB module */
+ res_info[BNA_RES_MEM_T_IDXSEG_ARRAY].res_type = BNA_RES_T_MEM;
+ res_info[BNA_RES_MEM_T_IDXSEG_ARRAY].res_u.mem_info.mem_type =
+ BNA_MEM_T_KVA;
+ res_info[BNA_RES_MEM_T_IDXSEG_ARRAY].res_u.mem_info.num = 1;
+ res_info[BNA_RES_MEM_T_IDXSEG_ARRAY].res_u.mem_info.len =
+ BFI_IBIDX_TOTAL_SEGS * sizeof(struct bna_ibidx_seg);
+
+ /* Virtual memory for Tx objects - stored by Tx module */
+ res_info[BNA_RES_MEM_T_TX_ARRAY].res_type = BNA_RES_T_MEM;
+ res_info[BNA_RES_MEM_T_TX_ARRAY].res_u.mem_info.mem_type =
+ BNA_MEM_T_KVA;
+ res_info[BNA_RES_MEM_T_TX_ARRAY].res_u.mem_info.num = 1;
+ res_info[BNA_RES_MEM_T_TX_ARRAY].res_u.mem_info.len =
+ BFI_MAX_TXQ * sizeof(struct bna_tx);
+
+ /* Virtual memory for TxQ - stored by Tx module */
+ res_info[BNA_RES_MEM_T_TXQ_ARRAY].res_type = BNA_RES_T_MEM;
+ res_info[BNA_RES_MEM_T_TXQ_ARRAY].res_u.mem_info.mem_type =
+ BNA_MEM_T_KVA;
+ res_info[BNA_RES_MEM_T_TXQ_ARRAY].res_u.mem_info.num = 1;
+ res_info[BNA_RES_MEM_T_TXQ_ARRAY].res_u.mem_info.len =
+ BFI_MAX_TXQ * sizeof(struct bna_txq);
+
+ /* Virtual memory for Rx objects - stored by Rx module */
+ res_info[BNA_RES_MEM_T_RX_ARRAY].res_type = BNA_RES_T_MEM;
+ res_info[BNA_RES_MEM_T_RX_ARRAY].res_u.mem_info.mem_type =
+ BNA_MEM_T_KVA;
+ res_info[BNA_RES_MEM_T_RX_ARRAY].res_u.mem_info.num = 1;
+ res_info[BNA_RES_MEM_T_RX_ARRAY].res_u.mem_info.len =
+ BFI_MAX_RXQ * sizeof(struct bna_rx);
+
+ /* Virtual memory for RxPath - stored by Rx module */
+ res_info[BNA_RES_MEM_T_RXP_ARRAY].res_type = BNA_RES_T_MEM;
+ res_info[BNA_RES_MEM_T_RXP_ARRAY].res_u.mem_info.mem_type =
+ BNA_MEM_T_KVA;
+ res_info[BNA_RES_MEM_T_RXP_ARRAY].res_u.mem_info.num = 1;
+ res_info[BNA_RES_MEM_T_RXP_ARRAY].res_u.mem_info.len =
+ BFI_MAX_RXQ * sizeof(struct bna_rxp);
+
+ /* Virtual memory for RxQ - stored by Rx module */
+ res_info[BNA_RES_MEM_T_RXQ_ARRAY].res_type = BNA_RES_T_MEM;
+ res_info[BNA_RES_MEM_T_RXQ_ARRAY].res_u.mem_info.mem_type =
+ BNA_MEM_T_KVA;
+ res_info[BNA_RES_MEM_T_RXQ_ARRAY].res_u.mem_info.num = 1;
+ res_info[BNA_RES_MEM_T_RXQ_ARRAY].res_u.mem_info.len =
+ BFI_MAX_RXQ * sizeof(struct bna_rxq);
+
+ /* Virtual memory for Unicast MAC address - stored by ucam module */
+ res_info[BNA_RES_MEM_T_UCMAC_ARRAY].res_type = BNA_RES_T_MEM;
+ res_info[BNA_RES_MEM_T_UCMAC_ARRAY].res_u.mem_info.mem_type =
+ BNA_MEM_T_KVA;
+ res_info[BNA_RES_MEM_T_UCMAC_ARRAY].res_u.mem_info.num = 1;
+ res_info[BNA_RES_MEM_T_UCMAC_ARRAY].res_u.mem_info.len =
+ BFI_MAX_UCMAC * sizeof(struct bna_mac);
+
+ /* Virtual memory for Multicast MAC address - stored by mcam module */
+ res_info[BNA_RES_MEM_T_MCMAC_ARRAY].res_type = BNA_RES_T_MEM;
+ res_info[BNA_RES_MEM_T_MCMAC_ARRAY].res_u.mem_info.mem_type =
+ BNA_MEM_T_KVA;
+ res_info[BNA_RES_MEM_T_MCMAC_ARRAY].res_u.mem_info.num = 1;
+ res_info[BNA_RES_MEM_T_MCMAC_ARRAY].res_u.mem_info.len =
+ BFI_MAX_MCMAC * sizeof(struct bna_mac);
+
+ /* Virtual memory for RIT entries */
+ res_info[BNA_RES_MEM_T_RIT_ENTRY].res_type = BNA_RES_T_MEM;
+ res_info[BNA_RES_MEM_T_RIT_ENTRY].res_u.mem_info.mem_type =
+ BNA_MEM_T_KVA;
+ res_info[BNA_RES_MEM_T_RIT_ENTRY].res_u.mem_info.num = 1;
+ res_info[BNA_RES_MEM_T_RIT_ENTRY].res_u.mem_info.len =
+ BFI_MAX_RIT_SIZE * sizeof(struct bna_rit_entry);
+
+ /* Virtual memory for RIT segment table */
+ res_info[BNA_RES_MEM_T_RIT_SEGMENT].res_type = BNA_RES_T_MEM;
+ res_info[BNA_RES_MEM_T_RIT_SEGMENT].res_u.mem_info.mem_type =
+ BNA_MEM_T_KVA;
+ res_info[BNA_RES_MEM_T_RIT_SEGMENT].res_u.mem_info.num = 1;
+ res_info[BNA_RES_MEM_T_RIT_SEGMENT].res_u.mem_info.len =
+ BFI_RIT_TOTAL_SEGS * sizeof(struct bna_rit_segment);
+
+ /* Interrupt resource for mailbox interrupt */
+ res_info[BNA_RES_INTR_T_MBOX].res_type = BNA_RES_T_INTR;
+ res_info[BNA_RES_INTR_T_MBOX].res_u.intr_info.intr_type =
+ BNA_INTR_T_MSIX;
+ res_info[BNA_RES_INTR_T_MBOX].res_u.intr_info.num = 1;
+}
+
+/* Called during probe() */
+void
+bna_init(struct bna *bna, struct bnad *bnad, struct bfa_pcidev *pcidev,
+ struct bna_res_info *res_info)
+{
+ bna->bnad = bnad;
+ bna->pcidev = *pcidev;
+
+ bna->stats.hw_stats = (struct bfi_ll_stats *)
+ res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.mdl[0].kva;
+ bna->hw_stats_dma.msb =
+ res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.mdl[0].dma.msb;
+ bna->hw_stats_dma.lsb =
+ res_info[BNA_RES_MEM_T_STATS].res_u.mem_info.mdl[0].dma.lsb;
+ bna->stats.sw_stats = (struct bna_sw_stats *)
+ res_info[BNA_RES_MEM_T_SWSTATS].res_u.mem_info.mdl[0].kva;
+
+ bna->regs.page_addr = bna->pcidev.pci_bar_kva +
+ reg_offset[bna->pcidev.pci_func].page_addr;
+ bna->regs.fn_int_status = bna->pcidev.pci_bar_kva +
+ reg_offset[bna->pcidev.pci_func].fn_int_status;
+ bna->regs.fn_int_mask = bna->pcidev.pci_bar_kva +
+ reg_offset[bna->pcidev.pci_func].fn_int_mask;
+
+ if (bna->pcidev.pci_func < 3)
+ bna->port_num = 0;
+ else
+ bna->port_num = 1;
+
+ /* Also initializes diag, cee, sfp, phy_port and mbox_mod */
+ bna_device_init(&bna->device, bna, res_info);
+
+ bna_port_init(&bna->port, bna);
+
+ bna_tx_mod_init(&bna->tx_mod, bna, res_info);
+
+ bna_rx_mod_init(&bna->rx_mod, bna, res_info);
+
+ bna_ib_mod_init(&bna->ib_mod, bna, res_info);
+
+ bna_rit_mod_init(&bna->rit_mod, res_info);
+
+ bna_ucam_mod_init(&bna->ucam_mod, bna, res_info);
+
+ bna_mcam_mod_init(&bna->mcam_mod, bna, res_info);
+
+ bna->rxf_default_id = BFI_MAX_RXF;
+ bna->rxf_promisc_id = BFI_MAX_RXF;
+
+ /* Mbox q element for posting stat request to f/w */
+ bfa_q_qe_init(&bna->mbox_qe.qe);
+}
+
+void
+bna_uninit(struct bna *bna)
+{
+ bna_mcam_mod_uninit(&bna->mcam_mod);
+
+ bna_ucam_mod_uninit(&bna->ucam_mod);
+
+ bna_rit_mod_uninit(&bna->rit_mod);
+
+ bna_ib_mod_uninit(&bna->ib_mod);
+
+ bna_rx_mod_uninit(&bna->rx_mod);
+
+ bna_tx_mod_uninit(&bna->tx_mod);
+
+ bna_port_uninit(&bna->port);
+
+ bna_device_uninit(&bna->device);
+
+ bna->bnad = NULL;
+}
+
+struct bna_mac *
+bna_ucam_mod_mac_get(struct bna_ucam_mod *ucam_mod)
+{
+ struct list_head *qe;
+
+ if (list_empty(&ucam_mod->free_q))
+ return NULL;
+
+ bfa_q_deq(&ucam_mod->free_q, &qe);
+
+ return (struct bna_mac *)qe;
+}
+
+void
+bna_ucam_mod_mac_put(struct bna_ucam_mod *ucam_mod, struct bna_mac *mac)
+{
+ list_add_tail(&mac->qe, &ucam_mod->free_q);
+}
+
+struct bna_mac *
+bna_mcam_mod_mac_get(struct bna_mcam_mod *mcam_mod)
+{
+ struct list_head *qe;
+
+ if (list_empty(&mcam_mod->free_q))
+ return NULL;
+
+ bfa_q_deq(&mcam_mod->free_q, &qe);
+
+ return (struct bna_mac *)qe;
+}
+
+void
+bna_mcam_mod_mac_put(struct bna_mcam_mod *mcam_mod, struct bna_mac *mac)
+{
+ list_add_tail(&mac->qe, &mcam_mod->free_q);
+}
+
+/**
+ * Note: This should be called in the same locking context as the call to
+ * bna_rit_mod_seg_get()
+ */
+int
+bna_rit_mod_can_satisfy(struct bna_rit_mod *rit_mod, int seg_size)
+{
+ int i;
+
+ /* Select the pool for seg_size */
+ for (i = 0; i < BFI_RIT_SEG_TOTAL_POOLS; i++) {
+ if (seg_size <= ritseg_pool_cfg[i].pool_entry_size)
+ break;
+ }
+
+ if (i == BFI_RIT_SEG_TOTAL_POOLS)
+ return 0;
+
+ if (list_empty(&rit_mod->rit_seg_pool[i]))
+ return 0;
+
+ return 1;
+}
+
+struct bna_rit_segment *
+bna_rit_mod_seg_get(struct bna_rit_mod *rit_mod, int seg_size)
+{
+ struct bna_rit_segment *seg;
+ struct list_head *qe;
+ int i;
+
+ /* Select the pool for seg_size */
+ for (i = 0; i < BFI_RIT_SEG_TOTAL_POOLS; i++) {
+ if (seg_size <= ritseg_pool_cfg[i].pool_entry_size)
+ break;
+ }
+
+ if (i == BFI_RIT_SEG_TOTAL_POOLS)
+ return NULL;
+
+ if (list_empty(&rit_mod->rit_seg_pool[i]))
+ return NULL;
+
+ bfa_q_deq(&rit_mod->rit_seg_pool[i], &qe);
+ seg = (struct bna_rit_segment *)qe;
+ bfa_q_qe_init(&seg->qe);
+ seg->rit_size = seg_size;
+
+ return seg;
+}
+
+void
+bna_rit_mod_seg_put(struct bna_rit_mod *rit_mod,
+ struct bna_rit_segment *seg)
+{
+ int i;
+
+ /* Select the pool for seg->max_rit_size */
+ for (i = 0; i < BFI_RIT_SEG_TOTAL_POOLS; i++) {
+ if (seg->max_rit_size == ritseg_pool_cfg[i].pool_entry_size)
+ break;
+ }
+
+ seg->rit_size = 0;
+ list_add_tail(&seg->qe, &rit_mod->rit_seg_pool[i]);
+}
diff --git a/drivers/net/bna/bna_hw.h b/drivers/net/bna/bna_hw.h
new file mode 100644
index 000000000000..806b224a4c63
--- /dev/null
+++ b/drivers/net/bna/bna_hw.h
@@ -0,0 +1,1490 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * File for interrupt macros and functions
+ */
+
+#ifndef __BNA_HW_H__
+#define __BNA_HW_H__
+
+#include "bfi_ctreg.h"
+
+/**
+ *
+ * SW imposed limits
+ *
+ */
+
+#ifndef BNA_BIOS_BUILD
+
+#define BFI_MAX_TXQ 64
+#define BFI_MAX_RXQ 64
+#define BFI_MAX_RXF 64
+#define BFI_MAX_IB 128
+#define BFI_MAX_RIT_SIZE 256
+#define BFI_RSS_RIT_SIZE 64
+#define BFI_NONRSS_RIT_SIZE 1
+#define BFI_MAX_UCMAC 256
+#define BFI_MAX_MCMAC 512
+#define BFI_IBIDX_SIZE 4
+#define BFI_MAX_VLAN 4095
+
+/**
+ * There are 2 free IB index pools:
+ * pool1: 120 segments of 1 index each
+ * pool8: 1 segment of 8 indexes
+ */
+#define BFI_IBIDX_POOL1_SIZE 116
+#define BFI_IBIDX_POOL1_ENTRY_SIZE 1
+#define BFI_IBIDX_POOL2_SIZE 2
+#define BFI_IBIDX_POOL2_ENTRY_SIZE 2
+#define BFI_IBIDX_POOL8_SIZE 1
+#define BFI_IBIDX_POOL8_ENTRY_SIZE 8
+#define BFI_IBIDX_TOTAL_POOLS 3
+#define BFI_IBIDX_TOTAL_SEGS 119 /* (POOL1 + POOL2 + POOL8)_SIZE */
+#define BFI_IBIDX_MAX_SEGSIZE 8
+#define init_ibidx_pool(name) \
+static struct bna_ibidx_pool name[BFI_IBIDX_TOTAL_POOLS] = \
+{ \
+ { BFI_IBIDX_POOL1_SIZE, BFI_IBIDX_POOL1_ENTRY_SIZE }, \
+ { BFI_IBIDX_POOL2_SIZE, BFI_IBIDX_POOL2_ENTRY_SIZE }, \
+ { BFI_IBIDX_POOL8_SIZE, BFI_IBIDX_POOL8_ENTRY_SIZE } \
+}
+
+/**
+ * There are 2 free RIT segment pools:
+ * Pool1: 192 segments of 1 RIT entry each
+ * Pool2: 1 segment of 64 RIT entry
+ */
+#define BFI_RIT_SEG_POOL1_SIZE 192
+#define BFI_RIT_SEG_POOL1_ENTRY_SIZE 1
+#define BFI_RIT_SEG_POOLRSS_SIZE 1
+#define BFI_RIT_SEG_POOLRSS_ENTRY_SIZE 64
+#define BFI_RIT_SEG_TOTAL_POOLS 2
+#define BFI_RIT_TOTAL_SEGS 193 /* POOL1_SIZE + POOLRSS_SIZE */
+#define init_ritseg_pool(name) \
+static struct bna_ritseg_pool_cfg name[BFI_RIT_SEG_TOTAL_POOLS] = \
+{ \
+ { BFI_RIT_SEG_POOL1_SIZE, BFI_RIT_SEG_POOL1_ENTRY_SIZE }, \
+ { BFI_RIT_SEG_POOLRSS_SIZE, BFI_RIT_SEG_POOLRSS_ENTRY_SIZE } \
+}
+
+#else /* BNA_BIOS_BUILD */
+
+#define BFI_MAX_TXQ 1
+#define BFI_MAX_RXQ 1
+#define BFI_MAX_RXF 1
+#define BFI_MAX_IB 2
+#define BFI_MAX_RIT_SIZE 2
+#define BFI_RSS_RIT_SIZE 64
+#define BFI_NONRSS_RIT_SIZE 1
+#define BFI_MAX_UCMAC 1
+#define BFI_MAX_MCMAC 8
+#define BFI_IBIDX_SIZE 4
+#define BFI_MAX_VLAN 4095
+/* There is one free pool: 2 segments of 1 index each */
+#define BFI_IBIDX_POOL1_SIZE 2
+#define BFI_IBIDX_POOL1_ENTRY_SIZE 1
+#define BFI_IBIDX_TOTAL_POOLS 1
+#define BFI_IBIDX_TOTAL_SEGS 2 /* POOL1_SIZE */
+#define BFI_IBIDX_MAX_SEGSIZE 1
+#define init_ibidx_pool(name) \
+static struct bna_ibidx_pool name[BFI_IBIDX_TOTAL_POOLS] = \
+{ \
+ { BFI_IBIDX_POOL1_SIZE, BFI_IBIDX_POOL1_ENTRY_SIZE } \
+}
+
+#define BFI_RIT_SEG_POOL1_SIZE 1
+#define BFI_RIT_SEG_POOL1_ENTRY_SIZE 1
+#define BFI_RIT_SEG_TOTAL_POOLS 1
+#define BFI_RIT_TOTAL_SEGS 1 /* POOL1_SIZE */
+#define init_ritseg_pool(name) \
+static struct bna_ritseg_pool_cfg name[BFI_RIT_SEG_TOTAL_POOLS] = \
+{ \
+ { BFI_RIT_SEG_POOL1_SIZE, BFI_RIT_SEG_POOL1_ENTRY_SIZE } \
+}
+
+#endif /* BNA_BIOS_BUILD */
+
+#define BFI_RSS_HASH_KEY_LEN 10
+
+#define BFI_COALESCING_TIMER_UNIT 5 /* 5us */
+#define BFI_MAX_COALESCING_TIMEO 0xFF /* in 5us units */
+#define BFI_MAX_INTERPKT_COUNT 0xFF
+#define BFI_MAX_INTERPKT_TIMEO 0xF /* in 0.5us units */
+#define BFI_TX_COALESCING_TIMEO 20 /* 20 * 5 = 100us */
+#define BFI_TX_INTERPKT_COUNT 32
+#define BFI_RX_COALESCING_TIMEO 12 /* 12 * 5 = 60us */
+#define BFI_RX_INTERPKT_COUNT 6 /* Pkt Cnt = 6 */
+#define BFI_RX_INTERPKT_TIMEO 3 /* 3 * 0.5 = 1.5us */
+
+#define BFI_TXQ_WI_SIZE 64 /* bytes */
+#define BFI_RXQ_WI_SIZE 8 /* bytes */
+#define BFI_CQ_WI_SIZE 16 /* bytes */
+#define BFI_TX_MAX_WRR_QUOTA 0xFFF
+
+#define BFI_TX_MAX_VECTORS_PER_WI 4
+#define BFI_TX_MAX_VECTORS_PER_PKT 0xFF
+#define BFI_TX_MAX_DATA_PER_VECTOR 0xFFFF
+#define BFI_TX_MAX_DATA_PER_PKT 0xFFFFFF
+
+/* Small Q buffer size */
+#define BFI_SMALL_RXBUF_SIZE 128
+
+/* Defined separately since BFA_FLASH_DMA_BUF_SZ is in bfa_flash.c */
+#define BFI_FLASH_DMA_BUF_SZ 0x010000 /* 64K DMA */
+#define BFI_HW_STATS_SIZE 0x4000 /* 16K DMA */
+
+/**
+ *
+ * HW register offsets, macros
+ *
+ */
+
+/* DMA Block Register Host Window Start Address */
+#define DMA_BLK_REG_ADDR 0x00013000
+
+/* DMA Block Internal Registers */
+#define DMA_CTRL_REG0 (DMA_BLK_REG_ADDR + 0x000)
+#define DMA_CTRL_REG1 (DMA_BLK_REG_ADDR + 0x004)
+#define DMA_ERR_INT_STATUS (DMA_BLK_REG_ADDR + 0x008)
+#define DMA_ERR_INT_ENABLE (DMA_BLK_REG_ADDR + 0x00c)
+#define DMA_ERR_INT_STATUS_SET (DMA_BLK_REG_ADDR + 0x010)
+
+/* APP Block Register Address Offset from BAR0 */
+#define APP_BLK_REG_ADDR 0x00014000
+
+/* Host Function Interrupt Mask Registers */
+#define HOSTFN0_INT_MASK (APP_BLK_REG_ADDR + 0x004)
+#define HOSTFN1_INT_MASK (APP_BLK_REG_ADDR + 0x104)
+#define HOSTFN2_INT_MASK (APP_BLK_REG_ADDR + 0x304)
+#define HOSTFN3_INT_MASK (APP_BLK_REG_ADDR + 0x404)
+
+/**
+ * Host Function PCIe Error Registers
+ * Duplicates "Correctable" & "Uncorrectable"
+ * registers in PCIe Config space.
+ */
+#define FN0_PCIE_ERR_REG (APP_BLK_REG_ADDR + 0x014)
+#define FN1_PCIE_ERR_REG (APP_BLK_REG_ADDR + 0x114)
+#define FN2_PCIE_ERR_REG (APP_BLK_REG_ADDR + 0x314)
+#define FN3_PCIE_ERR_REG (APP_BLK_REG_ADDR + 0x414)
+
+/* Host Function Error Type Status Registers */
+#define FN0_ERR_TYPE_STATUS_REG (APP_BLK_REG_ADDR + 0x018)
+#define FN1_ERR_TYPE_STATUS_REG (APP_BLK_REG_ADDR + 0x118)
+#define FN2_ERR_TYPE_STATUS_REG (APP_BLK_REG_ADDR + 0x318)
+#define FN3_ERR_TYPE_STATUS_REG (APP_BLK_REG_ADDR + 0x418)
+
+/* Host Function Error Type Mask Registers */
+#define FN0_ERR_TYPE_MSK_STATUS_REG (APP_BLK_REG_ADDR + 0x01c)
+#define FN1_ERR_TYPE_MSK_STATUS_REG (APP_BLK_REG_ADDR + 0x11c)
+#define FN2_ERR_TYPE_MSK_STATUS_REG (APP_BLK_REG_ADDR + 0x31c)
+#define FN3_ERR_TYPE_MSK_STATUS_REG (APP_BLK_REG_ADDR + 0x41c)
+
+/* Catapult Host Semaphore Status Registers (App block) */
+#define HOST_SEM_STS0_REG (APP_BLK_REG_ADDR + 0x630)
+#define HOST_SEM_STS1_REG (APP_BLK_REG_ADDR + 0x634)
+#define HOST_SEM_STS2_REG (APP_BLK_REG_ADDR + 0x638)
+#define HOST_SEM_STS3_REG (APP_BLK_REG_ADDR + 0x63c)
+#define HOST_SEM_STS4_REG (APP_BLK_REG_ADDR + 0x640)
+#define HOST_SEM_STS5_REG (APP_BLK_REG_ADDR + 0x644)
+#define HOST_SEM_STS6_REG (APP_BLK_REG_ADDR + 0x648)
+#define HOST_SEM_STS7_REG (APP_BLK_REG_ADDR + 0x64c)
+
+/* PCIe Misc Register */
+#define PCIE_MISC_REG (APP_BLK_REG_ADDR + 0x200)
+
+/* Temp Sensor Control Registers */
+#define TEMPSENSE_CNTL_REG (APP_BLK_REG_ADDR + 0x250)
+#define TEMPSENSE_STAT_REG (APP_BLK_REG_ADDR + 0x254)
+
+/* APP Block local error registers */
+#define APP_LOCAL_ERR_STAT (APP_BLK_REG_ADDR + 0x258)
+#define APP_LOCAL_ERR_MSK (APP_BLK_REG_ADDR + 0x25c)
+
+/* PCIe Link Error registers */
+#define PCIE_LNK_ERR_STAT (APP_BLK_REG_ADDR + 0x260)
+#define PCIE_LNK_ERR_MSK (APP_BLK_REG_ADDR + 0x264)
+
+/**
+ * FCoE/FIP Ethertype Register
+ * 31:16 -- Chip wide value for FIP type
+ * 15:0 -- Chip wide value for FCoE type
+ */
+#define FCOE_FIP_ETH_TYPE (APP_BLK_REG_ADDR + 0x280)
+
+/**
+ * Reserved Ethertype Register
+ * 31:16 -- Reserved
+ * 15:0 -- Other ethertype
+ */
+#define RESV_ETH_TYPE (APP_BLK_REG_ADDR + 0x284)
+
+/**
+ * Host Command Status Registers
+ * Each set consists of 3 registers :
+ * clear, set, cmd
+ * 16 such register sets in all
+ * See catapult_spec.pdf for detailed functionality
+ * Put each type in a single macro accessed by _num ?
+ */
+#define HOST_CMDSTS0_CLR_REG (APP_BLK_REG_ADDR + 0x500)
+#define HOST_CMDSTS0_SET_REG (APP_BLK_REG_ADDR + 0x504)
+#define HOST_CMDSTS0_REG (APP_BLK_REG_ADDR + 0x508)
+#define HOST_CMDSTS1_CLR_REG (APP_BLK_REG_ADDR + 0x510)
+#define HOST_CMDSTS1_SET_REG (APP_BLK_REG_ADDR + 0x514)
+#define HOST_CMDSTS1_REG (APP_BLK_REG_ADDR + 0x518)
+#define HOST_CMDSTS2_CLR_REG (APP_BLK_REG_ADDR + 0x520)
+#define HOST_CMDSTS2_SET_REG (APP_BLK_REG_ADDR + 0x524)
+#define HOST_CMDSTS2_REG (APP_BLK_REG_ADDR + 0x528)
+#define HOST_CMDSTS3_CLR_REG (APP_BLK_REG_ADDR + 0x530)
+#define HOST_CMDSTS3_SET_REG (APP_BLK_REG_ADDR + 0x534)
+#define HOST_CMDSTS3_REG (APP_BLK_REG_ADDR + 0x538)
+#define HOST_CMDSTS4_CLR_REG (APP_BLK_REG_ADDR + 0x540)
+#define HOST_CMDSTS4_SET_REG (APP_BLK_REG_ADDR + 0x544)
+#define HOST_CMDSTS4_REG (APP_BLK_REG_ADDR + 0x548)
+#define HOST_CMDSTS5_CLR_REG (APP_BLK_REG_ADDR + 0x550)
+#define HOST_CMDSTS5_SET_REG (APP_BLK_REG_ADDR + 0x554)
+#define HOST_CMDSTS5_REG (APP_BLK_REG_ADDR + 0x558)
+#define HOST_CMDSTS6_CLR_REG (APP_BLK_REG_ADDR + 0x560)
+#define HOST_CMDSTS6_SET_REG (APP_BLK_REG_ADDR + 0x564)
+#define HOST_CMDSTS6_REG (APP_BLK_REG_ADDR + 0x568)
+#define HOST_CMDSTS7_CLR_REG (APP_BLK_REG_ADDR + 0x570)
+#define HOST_CMDSTS7_SET_REG (APP_BLK_REG_ADDR + 0x574)
+#define HOST_CMDSTS7_REG (APP_BLK_REG_ADDR + 0x578)
+#define HOST_CMDSTS8_CLR_REG (APP_BLK_REG_ADDR + 0x580)
+#define HOST_CMDSTS8_SET_REG (APP_BLK_REG_ADDR + 0x584)
+#define HOST_CMDSTS8_REG (APP_BLK_REG_ADDR + 0x588)
+#define HOST_CMDSTS9_CLR_REG (APP_BLK_REG_ADDR + 0x590)
+#define HOST_CMDSTS9_SET_REG (APP_BLK_REG_ADDR + 0x594)
+#define HOST_CMDSTS9_REG (APP_BLK_REG_ADDR + 0x598)
+#define HOST_CMDSTS10_CLR_REG (APP_BLK_REG_ADDR + 0x5A0)
+#define HOST_CMDSTS10_SET_REG (APP_BLK_REG_ADDR + 0x5A4)
+#define HOST_CMDSTS10_REG (APP_BLK_REG_ADDR + 0x5A8)
+#define HOST_CMDSTS11_CLR_REG (APP_BLK_REG_ADDR + 0x5B0)
+#define HOST_CMDSTS11_SET_REG (APP_BLK_REG_ADDR + 0x5B4)
+#define HOST_CMDSTS11_REG (APP_BLK_REG_ADDR + 0x5B8)
+#define HOST_CMDSTS12_CLR_REG (APP_BLK_REG_ADDR + 0x5C0)
+#define HOST_CMDSTS12_SET_REG (APP_BLK_REG_ADDR + 0x5C4)
+#define HOST_CMDSTS12_REG (APP_BLK_REG_ADDR + 0x5C8)
+#define HOST_CMDSTS13_CLR_REG (APP_BLK_REG_ADDR + 0x5D0)
+#define HOST_CMDSTS13_SET_REG (APP_BLK_REG_ADDR + 0x5D4)
+#define HOST_CMDSTS13_REG (APP_BLK_REG_ADDR + 0x5D8)
+#define HOST_CMDSTS14_CLR_REG (APP_BLK_REG_ADDR + 0x5E0)
+#define HOST_CMDSTS14_SET_REG (APP_BLK_REG_ADDR + 0x5E4)
+#define HOST_CMDSTS14_REG (APP_BLK_REG_ADDR + 0x5E8)
+#define HOST_CMDSTS15_CLR_REG (APP_BLK_REG_ADDR + 0x5F0)
+#define HOST_CMDSTS15_SET_REG (APP_BLK_REG_ADDR + 0x5F4)
+#define HOST_CMDSTS15_REG (APP_BLK_REG_ADDR + 0x5F8)
+
+/**
+ * LPU0 Block Register Address Offset from BAR0
+ * Range 0x18000 - 0x18033
+ */
+#define LPU0_BLK_REG_ADDR 0x00018000
+
+/**
+ * LPU0 Registers
+ * Should they be directly used from host,
+ * except for diagnostics ?
+ * CTL_REG : Control register
+ * CMD_REG : Triggers exec. of cmd. in
+ * Mailbox memory
+ */
+#define LPU0_MBOX_CTL_REG (LPU0_BLK_REG_ADDR + 0x000)
+#define LPU0_MBOX_CMD_REG (LPU0_BLK_REG_ADDR + 0x004)
+#define LPU0_MBOX_LINK_0REG (LPU0_BLK_REG_ADDR + 0x008)
+#define LPU1_MBOX_LINK_0REG (LPU0_BLK_REG_ADDR + 0x00c)
+#define LPU0_MBOX_STATUS_0REG (LPU0_BLK_REG_ADDR + 0x010)
+#define LPU1_MBOX_STATUS_0REG (LPU0_BLK_REG_ADDR + 0x014)
+#define LPU0_ERR_STATUS_REG (LPU0_BLK_REG_ADDR + 0x018)
+#define LPU0_ERR_SET_REG (LPU0_BLK_REG_ADDR + 0x020)
+
+/**
+ * LPU1 Block Register Address Offset from BAR0
+ * Range 0x18400 - 0x18433
+ */
+#define LPU1_BLK_REG_ADDR 0x00018400
+
+/**
+ * LPU1 Registers
+ * Same as LPU0 registers above
+ */
+#define LPU1_MBOX_CTL_REG (LPU1_BLK_REG_ADDR + 0x000)
+#define LPU1_MBOX_CMD_REG (LPU1_BLK_REG_ADDR + 0x004)
+#define LPU0_MBOX_LINK_1REG (LPU1_BLK_REG_ADDR + 0x008)
+#define LPU1_MBOX_LINK_1REG (LPU1_BLK_REG_ADDR + 0x00c)
+#define LPU0_MBOX_STATUS_1REG (LPU1_BLK_REG_ADDR + 0x010)
+#define LPU1_MBOX_STATUS_1REG (LPU1_BLK_REG_ADDR + 0x014)
+#define LPU1_ERR_STATUS_REG (LPU1_BLK_REG_ADDR + 0x018)
+#define LPU1_ERR_SET_REG (LPU1_BLK_REG_ADDR + 0x020)
+
+/**
+ * PSS Block Register Address Offset from BAR0
+ * Range 0x18800 - 0x188DB
+ */
+#define PSS_BLK_REG_ADDR 0x00018800
+
+/**
+ * PSS Registers
+ * For details, see catapult_spec.pdf
+ * ERR_STATUS_REG : Indicates error in PSS module
+ * RAM_ERR_STATUS_REG : Indicates RAM module that detected error
+ */
+#define ERR_STATUS_SET (PSS_BLK_REG_ADDR + 0x018)
+#define PSS_RAM_ERR_STATUS_REG (PSS_BLK_REG_ADDR + 0x01C)
+
+/**
+ * PSS Semaphore Lock Registers, total 16
+ * First read when unlocked returns 0,
+ * and is set to 1, atomically.
+ * Subsequent reads returns 1.
+ * To clear set the value to 0.
+ * Range : 0x20 to 0x5c
+ */
+#define PSS_SEM_LOCK_REG(_num) \
+ (PSS_BLK_REG_ADDR + 0x020 + ((_num) << 2))
+
+/**
+ * PSS Semaphore Status Registers,
+ * corresponding to the lock registers above
+ */
+#define PSS_SEM_STATUS_REG(_num) \
+ (PSS_BLK_REG_ADDR + 0x060 + ((_num) << 2))
+
+/**
+ * Catapult CPQ Registers
+ * Defines for Mailbox Registers
+ * Used to send mailbox commands to firmware from
+ * host. The data part is written to the MBox
+ * memory, registers are used to indicate that
+ * a commnad is resident in memory.
+ *
+ * Note : LPU0<->LPU1 mailboxes are not listed here
+ */
+#define CPQ_BLK_REG_ADDR 0x00019000
+
+#define HOSTFN0_LPU0_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x130)
+#define HOSTFN0_LPU1_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x134)
+#define LPU0_HOSTFN0_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x138)
+#define LPU1_HOSTFN0_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x13C)
+
+#define HOSTFN1_LPU0_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x140)
+#define HOSTFN1_LPU1_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x144)
+#define LPU0_HOSTFN1_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x148)
+#define LPU1_HOSTFN1_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x14C)
+
+#define HOSTFN2_LPU0_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x170)
+#define HOSTFN2_LPU1_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x174)
+#define LPU0_HOSTFN2_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x178)
+#define LPU1_HOSTFN2_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x17C)
+
+#define HOSTFN3_LPU0_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x180)
+#define HOSTFN3_LPU1_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x184)
+#define LPU0_HOSTFN3_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x188)
+#define LPU1_HOSTFN3_MBOX1_CMD_STAT (CPQ_BLK_REG_ADDR + 0x18C)
+
+/* Host Function Force Parity Error Registers */
+#define HOSTFN0_LPU_FORCE_PERR (CPQ_BLK_REG_ADDR + 0x120)
+#define HOSTFN1_LPU_FORCE_PERR (CPQ_BLK_REG_ADDR + 0x124)
+#define HOSTFN2_LPU_FORCE_PERR (CPQ_BLK_REG_ADDR + 0x128)
+#define HOSTFN3_LPU_FORCE_PERR (CPQ_BLK_REG_ADDR + 0x12C)
+
+/* LL Port[0|1] Halt Mask Registers */
+#define LL_HALT_MSK_P0 (CPQ_BLK_REG_ADDR + 0x1A0)
+#define LL_HALT_MSK_P1 (CPQ_BLK_REG_ADDR + 0x1B0)
+
+/* LL Port[0|1] Error Mask Registers */
+#define LL_ERR_MSK_P0 (CPQ_BLK_REG_ADDR + 0x1D0)
+#define LL_ERR_MSK_P1 (CPQ_BLK_REG_ADDR + 0x1D4)
+
+/* EMC FLI (Flash Controller) Block Register Address Offset from BAR0 */
+#define FLI_BLK_REG_ADDR 0x0001D000
+
+/* EMC FLI Registers */
+#define FLI_CMD_REG (FLI_BLK_REG_ADDR + 0x000)
+#define FLI_ADDR_REG (FLI_BLK_REG_ADDR + 0x004)
+#define FLI_CTL_REG (FLI_BLK_REG_ADDR + 0x008)
+#define FLI_WRDATA_REG (FLI_BLK_REG_ADDR + 0x00C)
+#define FLI_RDDATA_REG (FLI_BLK_REG_ADDR + 0x010)
+#define FLI_DEV_STATUS_REG (FLI_BLK_REG_ADDR + 0x014)
+#define FLI_SIG_WD_REG (FLI_BLK_REG_ADDR + 0x018)
+
+/**
+ * RO register
+ * 31:16 -- Vendor Id
+ * 15:0 -- Device Id
+ */
+#define FLI_DEV_VENDOR_REG (FLI_BLK_REG_ADDR + 0x01C)
+#define FLI_ERR_STATUS_REG (FLI_BLK_REG_ADDR + 0x020)
+
+/**
+ * RAD (RxAdm) Block Register Address Offset from BAR0
+ * RAD0 Range : 0x20000 - 0x203FF
+ * RAD1 Range : 0x20400 - 0x207FF
+ */
+#define RAD0_BLK_REG_ADDR 0x00020000
+#define RAD1_BLK_REG_ADDR 0x00020400
+
+/* RAD0 Registers */
+#define RAD0_CTL_REG (RAD0_BLK_REG_ADDR + 0x000)
+#define RAD0_PE_PARM_REG (RAD0_BLK_REG_ADDR + 0x004)
+#define RAD0_BCN_REG (RAD0_BLK_REG_ADDR + 0x008)
+
+/* Default function ID register */
+#define RAD0_DEFAULT_REG (RAD0_BLK_REG_ADDR + 0x00C)
+
+/* Default promiscuous ID register */
+#define RAD0_PROMISC_REG (RAD0_BLK_REG_ADDR + 0x010)
+
+#define RAD0_BCNQ_REG (RAD0_BLK_REG_ADDR + 0x014)
+
+/*
+ * This register selects 1 of 8 PM Q's using
+ * VLAN pri, for non-BCN packets without a VLAN tag
+ */
+#define RAD0_DEFAULTQ_REG (RAD0_BLK_REG_ADDR + 0x018)
+
+#define RAD0_ERR_STS (RAD0_BLK_REG_ADDR + 0x01C)
+#define RAD0_SET_ERR_STS (RAD0_BLK_REG_ADDR + 0x020)
+#define RAD0_ERR_INT_EN (RAD0_BLK_REG_ADDR + 0x024)
+#define RAD0_FIRST_ERR (RAD0_BLK_REG_ADDR + 0x028)
+#define RAD0_FORCE_ERR (RAD0_BLK_REG_ADDR + 0x02C)
+
+#define RAD0_IF_RCVD (RAD0_BLK_REG_ADDR + 0x030)
+#define RAD0_IF_RCVD_OCTETS_HIGH (RAD0_BLK_REG_ADDR + 0x034)
+#define RAD0_IF_RCVD_OCTETS_LOW (RAD0_BLK_REG_ADDR + 0x038)
+#define RAD0_IF_RCVD_VLAN (RAD0_BLK_REG_ADDR + 0x03C)
+#define RAD0_IF_RCVD_UCAST (RAD0_BLK_REG_ADDR + 0x040)
+#define RAD0_IF_RCVD_UCAST_OCTETS_HIGH (RAD0_BLK_REG_ADDR + 0x044)
+#define RAD0_IF_RCVD_UCAST_OCTETS_LOW (RAD0_BLK_REG_ADDR + 0x048)
+#define RAD0_IF_RCVD_UCAST_VLAN (RAD0_BLK_REG_ADDR + 0x04C)
+#define RAD0_IF_RCVD_MCAST (RAD0_BLK_REG_ADDR + 0x050)
+#define RAD0_IF_RCVD_MCAST_OCTETS_HIGH (RAD0_BLK_REG_ADDR + 0x054)
+#define RAD0_IF_RCVD_MCAST_OCTETS_LOW (RAD0_BLK_REG_ADDR + 0x058)
+#define RAD0_IF_RCVD_MCAST_VLAN (RAD0_BLK_REG_ADDR + 0x05C)
+#define RAD0_IF_RCVD_BCAST (RAD0_BLK_REG_ADDR + 0x060)
+#define RAD0_IF_RCVD_BCAST_OCTETS_HIGH (RAD0_BLK_REG_ADDR + 0x064)
+#define RAD0_IF_RCVD_BCAST_OCTETS_LOW (RAD0_BLK_REG_ADDR + 0x068)
+#define RAD0_IF_RCVD_BCAST_VLAN (RAD0_BLK_REG_ADDR + 0x06C)
+#define RAD0_DROPPED_FRAMES (RAD0_BLK_REG_ADDR + 0x070)
+
+#define RAD0_MAC_MAN_1H (RAD0_BLK_REG_ADDR + 0x080)
+#define RAD0_MAC_MAN_1L (RAD0_BLK_REG_ADDR + 0x084)
+#define RAD0_MAC_MAN_2H (RAD0_BLK_REG_ADDR + 0x088)
+#define RAD0_MAC_MAN_2L (RAD0_BLK_REG_ADDR + 0x08C)
+#define RAD0_MAC_MAN_3H (RAD0_BLK_REG_ADDR + 0x090)
+#define RAD0_MAC_MAN_3L (RAD0_BLK_REG_ADDR + 0x094)
+#define RAD0_MAC_MAN_4H (RAD0_BLK_REG_ADDR + 0x098)
+#define RAD0_MAC_MAN_4L (RAD0_BLK_REG_ADDR + 0x09C)
+
+#define RAD0_LAST4_IP (RAD0_BLK_REG_ADDR + 0x100)
+
+/* RAD1 Registers */
+#define RAD1_CTL_REG (RAD1_BLK_REG_ADDR + 0x000)
+#define RAD1_PE_PARM_REG (RAD1_BLK_REG_ADDR + 0x004)
+#define RAD1_BCN_REG (RAD1_BLK_REG_ADDR + 0x008)
+
+/* Default function ID register */
+#define RAD1_DEFAULT_REG (RAD1_BLK_REG_ADDR + 0x00C)
+
+/* Promiscuous function ID register */
+#define RAD1_PROMISC_REG (RAD1_BLK_REG_ADDR + 0x010)
+
+#define RAD1_BCNQ_REG (RAD1_BLK_REG_ADDR + 0x014)
+
+/*
+ * This register selects 1 of 8 PM Q's using
+ * VLAN pri, for non-BCN packets without a VLAN tag
+ */
+#define RAD1_DEFAULTQ_REG (RAD1_BLK_REG_ADDR + 0x018)
+
+#define RAD1_ERR_STS (RAD1_BLK_REG_ADDR + 0x01C)
+#define RAD1_SET_ERR_STS (RAD1_BLK_REG_ADDR + 0x020)
+#define RAD1_ERR_INT_EN (RAD1_BLK_REG_ADDR + 0x024)
+
+/**
+ * TXA Block Register Address Offset from BAR0
+ * TXA0 Range : 0x21000 - 0x213FF
+ * TXA1 Range : 0x21400 - 0x217FF
+ */
+#define TXA0_BLK_REG_ADDR 0x00021000
+#define TXA1_BLK_REG_ADDR 0x00021400
+
+/* TXA Registers */
+#define TXA0_CTRL_REG (TXA0_BLK_REG_ADDR + 0x000)
+#define TXA1_CTRL_REG (TXA1_BLK_REG_ADDR + 0x000)
+
+/**
+ * TSO Sequence # Registers (RO)
+ * Total 8 (for 8 queues)
+ * Holds the last seq.# for TSO frames
+ * See catapult_spec.pdf for more details
+ */
+#define TXA0_TSO_TCP_SEQ_REG(_num) \
+ (TXA0_BLK_REG_ADDR + 0x020 + ((_num) << 2))
+
+#define TXA1_TSO_TCP_SEQ_REG(_num) \
+ (TXA1_BLK_REG_ADDR + 0x020 + ((_num) << 2))
+
+/**
+ * TSO IP ID # Registers (RO)
+ * Total 8 (for 8 queues)
+ * Holds the last IP ID for TSO frames
+ * See catapult_spec.pdf for more details
+ */
+#define TXA0_TSO_IP_INFO_REG(_num) \
+ (TXA0_BLK_REG_ADDR + 0x040 + ((_num) << 2))
+
+#define TXA1_TSO_IP_INFO_REG(_num) \
+ (TXA1_BLK_REG_ADDR + 0x040 + ((_num) << 2))
+
+/**
+ * RXA Block Register Address Offset from BAR0
+ * RXA0 Range : 0x21800 - 0x21BFF
+ * RXA1 Range : 0x21C00 - 0x21FFF
+ */
+#define RXA0_BLK_REG_ADDR 0x00021800
+#define RXA1_BLK_REG_ADDR 0x00021C00
+
+/* RXA Registers */
+#define RXA0_CTL_REG (RXA0_BLK_REG_ADDR + 0x040)
+#define RXA1_CTL_REG (RXA1_BLK_REG_ADDR + 0x040)
+
+/**
+ * PPLB Block Register Address Offset from BAR0
+ * PPLB0 Range : 0x22000 - 0x223FF
+ * PPLB1 Range : 0x22400 - 0x227FF
+ */
+#define PLB0_BLK_REG_ADDR 0x00022000
+#define PLB1_BLK_REG_ADDR 0x00022400
+
+/**
+ * PLB Registers
+ * Holds RL timer used time stamps in RLT tagged frames
+ */
+#define PLB0_ECM_TIMER_REG (PLB0_BLK_REG_ADDR + 0x05C)
+#define PLB1_ECM_TIMER_REG (PLB1_BLK_REG_ADDR + 0x05C)
+
+/* Controls the rate-limiter on each of the priority class */
+#define PLB0_RL_CTL (PLB0_BLK_REG_ADDR + 0x060)
+#define PLB1_RL_CTL (PLB1_BLK_REG_ADDR + 0x060)
+
+/**
+ * Max byte register, total 8, 0-7
+ * see catapult_spec.pdf for details
+ */
+#define PLB0_RL_MAX_BC(_num) \
+ (PLB0_BLK_REG_ADDR + 0x064 + ((_num) << 2))
+#define PLB1_RL_MAX_BC(_num) \
+ (PLB1_BLK_REG_ADDR + 0x064 + ((_num) << 2))
+
+/**
+ * RL Time Unit Register for priority 0-7
+ * 4 bits per priority
+ * (2^rl_unit)*1us is the actual time period
+ */
+#define PLB0_RL_TU_PRIO (PLB0_BLK_REG_ADDR + 0x084)
+#define PLB1_RL_TU_PRIO (PLB1_BLK_REG_ADDR + 0x084)
+
+/**
+ * RL byte count register,
+ * bytes transmitted in (rl_unit*1)us time period
+ * 1 per priority, 8 in all, 0-7.
+ */
+#define PLB0_RL_BYTE_CNT(_num) \
+ (PLB0_BLK_REG_ADDR + 0x088 + ((_num) << 2))
+#define PLB1_RL_BYTE_CNT(_num) \
+ (PLB1_BLK_REG_ADDR + 0x088 + ((_num) << 2))
+
+/**
+ * RL Min factor register
+ * 2 bits per priority,
+ * 4 factors possible: 1, 0.5, 0.25, 0
+ * 2'b00 - 0; 2'b01 - 0.25; 2'b10 - 0.5; 2'b11 - 1
+ */
+#define PLB0_RL_MIN_REG (PLB0_BLK_REG_ADDR + 0x0A8)
+#define PLB1_RL_MIN_REG (PLB1_BLK_REG_ADDR + 0x0A8)
+
+/**
+ * RL Max factor register
+ * 2 bits per priority,
+ * 4 factors possible: 1, 0.5, 0.25, 0
+ * 2'b00 - 0; 2'b01 - 0.25; 2'b10 - 0.5; 2'b11 - 1
+ */
+#define PLB0_RL_MAX_REG (PLB0_BLK_REG_ADDR + 0x0AC)
+#define PLB1_RL_MAX_REG (PLB1_BLK_REG_ADDR + 0x0AC)
+
+/* MAC SERDES Address Paging register */
+#define PLB0_EMS_ADD_REG (PLB0_BLK_REG_ADDR + 0xD0)
+#define PLB1_EMS_ADD_REG (PLB1_BLK_REG_ADDR + 0xD0)
+
+/* LL EMS Registers */
+#define LL_EMS0_BLK_REG_ADDR 0x00026800
+#define LL_EMS1_BLK_REG_ADDR 0x00026C00
+
+/**
+ * BPC Block Register Address Offset from BAR0
+ * BPC0 Range : 0x23000 - 0x233FF
+ * BPC1 Range : 0x23400 - 0x237FF
+ */
+#define BPC0_BLK_REG_ADDR 0x00023000
+#define BPC1_BLK_REG_ADDR 0x00023400
+
+/**
+ * PMM Block Register Address Offset from BAR0
+ * PMM0 Range : 0x23800 - 0x23BFF
+ * PMM1 Range : 0x23C00 - 0x23FFF
+ */
+#define PMM0_BLK_REG_ADDR 0x00023800
+#define PMM1_BLK_REG_ADDR 0x00023C00
+
+/**
+ * HQM Block Register Address Offset from BAR0
+ * HQM0 Range : 0x24000 - 0x243FF
+ * HQM1 Range : 0x24400 - 0x247FF
+ */
+#define HQM0_BLK_REG_ADDR 0x00024000
+#define HQM1_BLK_REG_ADDR 0x00024400
+
+/**
+ * HQM Control Register
+ * Controls some aspects of IB
+ * See catapult_spec.pdf for details
+ */
+#define HQM0_CTL_REG (HQM0_BLK_REG_ADDR + 0x000)
+#define HQM1_CTL_REG (HQM1_BLK_REG_ADDR + 0x000)
+
+/**
+ * HQM Stop Q Semaphore Registers.
+ * Only one Queue resource can be stopped at
+ * any given time. This register controls access
+ * to the single stop Q resource.
+ * See catapult_spec.pdf for details
+ */
+#define HQM0_RXQ_STOP_SEM (HQM0_BLK_REG_ADDR + 0x028)
+#define HQM0_TXQ_STOP_SEM (HQM0_BLK_REG_ADDR + 0x02C)
+#define HQM1_RXQ_STOP_SEM (HQM1_BLK_REG_ADDR + 0x028)
+#define HQM1_TXQ_STOP_SEM (HQM1_BLK_REG_ADDR + 0x02C)
+
+/**
+ * LUT Block Register Address Offset from BAR0
+ * LUT0 Range : 0x25800 - 0x25BFF
+ * LUT1 Range : 0x25C00 - 0x25FFF
+ */
+#define LUT0_BLK_REG_ADDR 0x00025800
+#define LUT1_BLK_REG_ADDR 0x00025C00
+
+/**
+ * LUT Registers
+ * See catapult_spec.pdf for details
+ */
+#define LUT0_ERR_STS (LUT0_BLK_REG_ADDR + 0x000)
+#define LUT1_ERR_STS (LUT1_BLK_REG_ADDR + 0x000)
+#define LUT0_SET_ERR_STS (LUT0_BLK_REG_ADDR + 0x004)
+#define LUT1_SET_ERR_STS (LUT1_BLK_REG_ADDR + 0x004)
+
+/**
+ * TRC (Debug/Trace) Register Offset from BAR0
+ * Range : 0x26000 -- 0x263FFF
+ */
+#define TRC_BLK_REG_ADDR 0x00026000
+
+/**
+ * TRC Registers
+ * See catapult_spec.pdf for details of each
+ */
+#define TRC_CTL_REG (TRC_BLK_REG_ADDR + 0x000)
+#define TRC_MODS_REG (TRC_BLK_REG_ADDR + 0x004)
+#define TRC_TRGC_REG (TRC_BLK_REG_ADDR + 0x008)
+#define TRC_CNT1_REG (TRC_BLK_REG_ADDR + 0x010)
+#define TRC_CNT2_REG (TRC_BLK_REG_ADDR + 0x014)
+#define TRC_NXTS_REG (TRC_BLK_REG_ADDR + 0x018)
+#define TRC_DIRR_REG (TRC_BLK_REG_ADDR + 0x01C)
+
+/**
+ * TRC Trigger match filters, total 10
+ * Determines the trigger condition
+ */
+#define TRC_TRGM_REG(_num) \
+ (TRC_BLK_REG_ADDR + 0x040 + ((_num) << 2))
+
+/**
+ * TRC Next State filters, total 10
+ * Determines the next state conditions
+ */
+#define TRC_NXTM_REG(_num) \
+ (TRC_BLK_REG_ADDR + 0x080 + ((_num) << 2))
+
+/**
+ * TRC Store Match filters, total 10
+ * Determines the store conditions
+ */
+#define TRC_STRM_REG(_num) \
+ (TRC_BLK_REG_ADDR + 0x0C0 + ((_num) << 2))
+
+/* DOORBELLS ACCESS */
+
+/**
+ * Catapult doorbells
+ * Each doorbell-queue set has
+ * 1 RxQ, 1 TxQ, 2 IBs in that order
+ * Size of each entry in 32 bytes, even though only 1 word
+ * is used. For Non-VM case each doorbell-q set is
+ * separated by 128 bytes, for VM case it is separated
+ * by 4K bytes
+ * Non VM case Range : 0x38000 - 0x39FFF
+ * VM case Range : 0x100000 - 0x11FFFF
+ * The range applies to both HQMs
+ */
+#define HQM_DOORBELL_BLK_BASE_ADDR 0x00038000
+#define HQM_DOORBELL_VM_BLK_BASE_ADDR 0x00100000
+
+/* MEMORY ACCESS */
+
+/**
+ * Catapult H/W Block Memory Access Address
+ * To the host a memory space of 32K (page) is visible
+ * at a time. The address range is from 0x08000 to 0x0FFFF
+ */
+#define HW_BLK_HOST_MEM_ADDR 0x08000
+
+/**
+ * Catapult LUT Memory Access Page Numbers
+ * Range : LUT0 0xa0-0xa1
+ * LUT1 0xa2-0xa3
+ */
+#define LUT0_MEM_BLK_BASE_PG_NUM 0x000000A0
+#define LUT1_MEM_BLK_BASE_PG_NUM 0x000000A2
+
+/**
+ * Catapult RxFn Database Memory Block Base Offset
+ *
+ * The Rx function database exists in LUT block.
+ * In PCIe space this is accessible as a 256x32
+ * bit block. Each entry in this database is 4
+ * (4 byte) words. Max. entries is 64.
+ * Address of an entry corresponding to a function
+ * = base_addr + (function_no. * 16)
+ */
+#define RX_FNDB_RAM_BASE_OFFSET 0x0000B400
+
+/**
+ * Catapult TxFn Database Memory Block Base Offset Address
+ *
+ * The Tx function database exists in LUT block.
+ * In PCIe space this is accessible as a 64x32
+ * bit block. Each entry in this database is 1
+ * (4 byte) word. Max. entries is 64.
+ * Address of an entry corresponding to a function
+ * = base_addr + (function_no. * 4)
+ */
+#define TX_FNDB_RAM_BASE_OFFSET 0x0000B800
+
+/**
+ * Catapult Unicast CAM Base Offset Address
+ *
+ * Exists in LUT memory space.
+ * Shared by both the LL & FCoE driver.
+ * Size is 256x48 bits; mapped to PCIe space
+ * 512x32 bit blocks. For each address, bits
+ * are written in the order : [47:32] and then
+ * [31:0].
+ */
+#define UCAST_CAM_BASE_OFFSET 0x0000A800
+
+/**
+ * Catapult Unicast RAM Base Offset Address
+ *
+ * Exists in LUT memory space.
+ * Shared by both the LL & FCoE driver.
+ * Size is 256x9 bits.
+ */
+#define UCAST_RAM_BASE_OFFSET 0x0000B000
+
+/**
+ * Catapult Mulicast CAM Base Offset Address
+ *
+ * Exists in LUT memory space.
+ * Shared by both the LL & FCoE driver.
+ * Size is 256x48 bits; mapped to PCIe space
+ * 512x32 bit blocks. For each address, bits
+ * are written in the order : [47:32] and then
+ * [31:0].
+ */
+#define MCAST_CAM_BASE_OFFSET 0x0000A000
+
+/**
+ * Catapult VLAN RAM Base Offset Address
+ *
+ * Exists in LUT memory space.
+ * Size is 4096x66 bits; mapped to PCIe space as
+ * 8192x32 bit blocks.
+ * All the 4K entries are within the address range
+ * 0x0000 to 0x8000, so in the first LUT page.
+ */
+#define VLAN_RAM_BASE_OFFSET 0x00000000
+
+/**
+ * Catapult Tx Stats RAM Base Offset Address
+ *
+ * Exists in LUT memory space.
+ * Size is 1024x33 bits;
+ * Each Tx function has 64 bytes of space
+ */
+#define TX_STATS_RAM_BASE_OFFSET 0x00009000
+
+/**
+ * Catapult Rx Stats RAM Base Offset Address
+ *
+ * Exists in LUT memory space.
+ * Size is 1024x33 bits;
+ * Each Rx function has 64 bytes of space
+ */
+#define RX_STATS_RAM_BASE_OFFSET 0x00008000
+
+/* Catapult RXA Memory Access Page Numbers */
+#define RXA0_MEM_BLK_BASE_PG_NUM 0x0000008C
+#define RXA1_MEM_BLK_BASE_PG_NUM 0x0000008D
+
+/**
+ * Catapult Multicast Vector Table Base Offset Address
+ *
+ * Exists in RxA memory space.
+ * Organized as 512x65 bit block.
+ * However for each entry 16 bytes allocated (power of 2)
+ * Total size 512*16 bytes.
+ * There are two logical divisions, 256 entries each :
+ * a) Entries 0x00 to 0xff (256) -- Approx. MVT
+ * Offset 0x000 to 0xFFF
+ * b) Entries 0x100 to 0x1ff (256) -- Exact MVT
+ * Offsets 0x1000 to 0x1FFF
+ */
+#define MCAST_APPROX_MVT_BASE_OFFSET 0x00000000
+#define MCAST_EXACT_MVT_BASE_OFFSET 0x00001000
+
+/**
+ * Catapult RxQ Translate Table (RIT) Base Offset Address
+ *
+ * Exists in RxA memory space
+ * Total no. of entries 64
+ * Each entry is 1 (4 byte) word.
+ * 31:12 -- Reserved
+ * 11:0 -- Two 6 bit RxQ Ids
+ */
+#define FUNCTION_TO_RXQ_TRANSLATE 0x00002000
+
+/* Catapult RxAdm (RAD) Memory Access Page Numbers */
+#define RAD0_MEM_BLK_BASE_PG_NUM 0x00000086
+#define RAD1_MEM_BLK_BASE_PG_NUM 0x00000087
+
+/**
+ * Catapult RSS Table Base Offset Address
+ *
+ * Exists in RAD memory space.
+ * Each entry is 352 bits, but alligned on
+ * 64 byte (512 bit) boundary. Accessed
+ * 4 byte words, the whole entry can be
+ * broken into 11 word accesses.
+ */
+#define RSS_TABLE_BASE_OFFSET 0x00000800
+
+/**
+ * Catapult CPQ Block Page Number
+ * This value is written to the page number registers
+ * to access the memory associated with the mailboxes.
+ */
+#define CPQ_BLK_PG_NUM 0x00000005
+
+/**
+ * Clarification :
+ * LL functions are 2 & 3; can HostFn0/HostFn1
+ * <-> LPU0/LPU1 memories be used ?
+ */
+/**
+ * Catapult HostFn0/HostFn1 to LPU0/LPU1 Mbox memory
+ * Per catapult_spec.pdf, the offset of the mbox
+ * memory is in the register space at an offset of 0x200
+ */
+#define CPQ_BLK_REG_MBOX_ADDR (CPQ_BLK_REG_ADDR + 0x200)
+
+#define HOSTFN_LPU_MBOX (CPQ_BLK_REG_MBOX_ADDR + 0x000)
+
+/* Catapult LPU0/LPU1 to HostFn0/HostFn1 Mbox memory */
+#define LPU_HOSTFN_MBOX (CPQ_BLK_REG_MBOX_ADDR + 0x080)
+
+/**
+ * Catapult HQM Block Page Number
+ * This is written to the page number register for
+ * the appropriate function to access the memory
+ * associated with HQM
+ */
+#define HQM0_BLK_PG_NUM 0x00000096
+#define HQM1_BLK_PG_NUM 0x00000097
+
+/**
+ * Note that TxQ and RxQ entries are interlaced
+ * the HQM memory, i.e RXQ0, TXQ0, RXQ1, TXQ1.. etc.
+ */
+
+#define HQM_RXTX_Q_RAM_BASE_OFFSET 0x00004000
+
+/**
+ * CQ Memory
+ * Exists in HQM Memory space
+ * Each entry is 16 (4 byte) words of which
+ * only 12 words are used for configuration
+ * Total 64 entries per HQM memory space
+ */
+#define HQM_CQ_RAM_BASE_OFFSET 0x00006000
+
+/**
+ * Interrupt Block (IB) Memory
+ * Exists in HQM Memory space
+ * Each entry is 8 (4 byte) words of which
+ * only 5 words are used for configuration
+ * Total 128 entries per HQM memory space
+ */
+#define HQM_IB_RAM_BASE_OFFSET 0x00001000
+
+/**
+ * Index Table (IT) Memory
+ * Exists in HQM Memory space
+ * Each entry is 1 (4 byte) word which
+ * is used for configuration
+ * Total 128 entries per HQM memory space
+ */
+#define HQM_INDX_TBL_RAM_BASE_OFFSET 0x00002000
+
+/**
+ * PSS Block Memory Page Number
+ * This is written to the appropriate page number
+ * register to access the CPU memory.
+ * Also known as the PSS secondary memory (SMEM).
+ * Range : 0x180 to 0x1CF
+ * See catapult_spec.pdf for details
+ */
+#define PSS_BLK_PG_NUM 0x00000180
+
+/**
+ * Offsets of different instances of PSS SMEM
+ * 2.5M of continuous 1T memory space : 2 blocks
+ * of 1M each (32 pages each, page=32KB) and 4 smaller
+ * blocks of 128K each (4 pages each, page=32KB)
+ * PSS_LMEM_INST0 is used for firmware download
+ */
+#define PSS_LMEM_INST0 0x00000000
+#define PSS_LMEM_INST1 0x00100000
+#define PSS_LMEM_INST2 0x00200000
+#define PSS_LMEM_INST3 0x00220000
+#define PSS_LMEM_INST4 0x00240000
+#define PSS_LMEM_INST5 0x00260000
+
+#define BNA_PCI_REG_CT_ADDRSZ (0x40000)
+
+#define BNA_GET_PAGE_NUM(_base_page, _offset) \
+ ((_base_page) + ((_offset) >> 15))
+
+#define BNA_GET_PAGE_OFFSET(_offset) \
+ ((_offset) & 0x7fff)
+
+#define BNA_GET_MEM_BASE_ADDR(_bar0, _base_offset) \
+ ((_bar0) + HW_BLK_HOST_MEM_ADDR \
+ + BNA_GET_PAGE_OFFSET((_base_offset)))
+
+#define BNA_GET_VLAN_MEM_ENTRY_ADDR(_bar0, _fn_id, _vlan_id)\
+ (_bar0 + (HW_BLK_HOST_MEM_ADDR) \
+ + (BNA_GET_PAGE_OFFSET(VLAN_RAM_BASE_OFFSET)) \
+ + (((_fn_id) & 0x3f) << 9) \
+ + (((_vlan_id) & 0xfe0) >> 3))
+
+/**
+ *
+ * Interrupt related bits, flags and macros
+ *
+ */
+
+#define __LPU02HOST_MBOX0_STATUS_BITS 0x00100000
+#define __LPU12HOST_MBOX0_STATUS_BITS 0x00200000
+#define __LPU02HOST_MBOX1_STATUS_BITS 0x00400000
+#define __LPU12HOST_MBOX1_STATUS_BITS 0x00800000
+
+#define __LPU02HOST_MBOX0_MASK_BITS 0x00100000
+#define __LPU12HOST_MBOX0_MASK_BITS 0x00200000
+#define __LPU02HOST_MBOX1_MASK_BITS 0x00400000
+#define __LPU12HOST_MBOX1_MASK_BITS 0x00800000
+
+#define __LPU2HOST_MBOX_MASK_BITS \
+ (__LPU02HOST_MBOX0_MASK_BITS | __LPU02HOST_MBOX1_MASK_BITS | \
+ __LPU12HOST_MBOX0_MASK_BITS | __LPU12HOST_MBOX1_MASK_BITS)
+
+#define __LPU2HOST_IB_STATUS_BITS 0x0000ffff
+
+#define BNA_IS_LPU0_MBOX_INTR(_intr_status) \
+ ((_intr_status) & (__LPU02HOST_MBOX0_STATUS_BITS | \
+ __LPU02HOST_MBOX1_STATUS_BITS))
+
+#define BNA_IS_LPU1_MBOX_INTR(_intr_status) \
+ ((_intr_status) & (__LPU12HOST_MBOX0_STATUS_BITS | \
+ __LPU12HOST_MBOX1_STATUS_BITS))
+
+#define BNA_IS_MBOX_INTR(_intr_status) \
+ ((_intr_status) & \
+ (__LPU02HOST_MBOX0_STATUS_BITS | \
+ __LPU02HOST_MBOX1_STATUS_BITS | \
+ __LPU12HOST_MBOX0_STATUS_BITS | \
+ __LPU12HOST_MBOX1_STATUS_BITS))
+
+#define __EMC_ERROR_STATUS_BITS 0x00010000
+#define __LPU0_ERROR_STATUS_BITS 0x00020000
+#define __LPU1_ERROR_STATUS_BITS 0x00040000
+#define __PSS_ERROR_STATUS_BITS 0x00080000
+
+#define __HALT_STATUS_BITS 0x01000000
+
+#define __EMC_ERROR_MASK_BITS 0x00010000
+#define __LPU0_ERROR_MASK_BITS 0x00020000
+#define __LPU1_ERROR_MASK_BITS 0x00040000
+#define __PSS_ERROR_MASK_BITS 0x00080000
+
+#define __HALT_MASK_BITS 0x01000000
+
+#define __ERROR_MASK_BITS \
+ (__EMC_ERROR_MASK_BITS | __LPU0_ERROR_MASK_BITS | \
+ __LPU1_ERROR_MASK_BITS | __PSS_ERROR_MASK_BITS | \
+ __HALT_MASK_BITS)
+
+#define BNA_IS_ERR_INTR(_intr_status) \
+ ((_intr_status) & \
+ (__EMC_ERROR_STATUS_BITS | \
+ __LPU0_ERROR_STATUS_BITS | \
+ __LPU1_ERROR_STATUS_BITS | \
+ __PSS_ERROR_STATUS_BITS | \
+ __HALT_STATUS_BITS))
+
+#define BNA_IS_MBOX_ERR_INTR(_intr_status) \
+ (BNA_IS_MBOX_INTR((_intr_status)) | \
+ BNA_IS_ERR_INTR((_intr_status)))
+
+#define BNA_IS_INTX_DATA_INTR(_intr_status) \
+ ((_intr_status) & __LPU2HOST_IB_STATUS_BITS)
+
+#define BNA_INTR_STATUS_MBOX_CLR(_intr_status) \
+do { \
+ (_intr_status) &= ~(__LPU02HOST_MBOX0_STATUS_BITS | \
+ __LPU02HOST_MBOX1_STATUS_BITS | \
+ __LPU12HOST_MBOX0_STATUS_BITS | \
+ __LPU12HOST_MBOX1_STATUS_BITS); \
+} while (0)
+
+#define BNA_INTR_STATUS_ERR_CLR(_intr_status) \
+do { \
+ (_intr_status) &= ~(__EMC_ERROR_STATUS_BITS | \
+ __LPU0_ERROR_STATUS_BITS | \
+ __LPU1_ERROR_STATUS_BITS | \
+ __PSS_ERROR_STATUS_BITS | \
+ __HALT_STATUS_BITS); \
+} while (0)
+
+#define bna_intx_disable(_bna, _cur_mask) \
+{ \
+ (_cur_mask) = readl((_bna)->regs.fn_int_mask);\
+ writel(0xffffffff, (_bna)->regs.fn_int_mask);\
+}
+
+#define bna_intx_enable(bna, new_mask) \
+ writel((new_mask), (bna)->regs.fn_int_mask)
+
+#define bna_mbox_intr_disable(bna) \
+ writel((readl((bna)->regs.fn_int_mask) | \
+ (__LPU2HOST_MBOX_MASK_BITS | __ERROR_MASK_BITS)), \
+ (bna)->regs.fn_int_mask)
+
+#define bna_mbox_intr_enable(bna) \
+ writel((readl((bna)->regs.fn_int_mask) & \
+ ~(__LPU2HOST_MBOX_MASK_BITS | __ERROR_MASK_BITS)), \
+ (bna)->regs.fn_int_mask)
+
+#define bna_intr_status_get(_bna, _status) \
+{ \
+ (_status) = readl((_bna)->regs.fn_int_status); \
+ if ((_status)) { \
+ writel((_status) & ~(__LPU02HOST_MBOX0_STATUS_BITS |\
+ __LPU02HOST_MBOX1_STATUS_BITS |\
+ __LPU12HOST_MBOX0_STATUS_BITS |\
+ __LPU12HOST_MBOX1_STATUS_BITS), \
+ (_bna)->regs.fn_int_status);\
+ } \
+}
+
+#define bna_intr_status_get_no_clr(_bna, _status) \
+ (_status) = readl((_bna)->regs.fn_int_status)
+
+#define bna_intr_mask_get(bna, mask) \
+ (*mask) = readl((bna)->regs.fn_int_mask)
+
+#define bna_intr_ack(bna, intr_bmap) \
+ writel((intr_bmap), (bna)->regs.fn_int_status)
+
+#define bna_ib_intx_disable(bna, ib_id) \
+ writel(readl((bna)->regs.fn_int_mask) | \
+ (1 << (ib_id)), \
+ (bna)->regs.fn_int_mask)
+
+#define bna_ib_intx_enable(bna, ib_id) \
+ writel(readl((bna)->regs.fn_int_mask) & \
+ ~(1 << (ib_id)), \
+ (bna)->regs.fn_int_mask)
+
+#define bna_mbox_msix_idx_set(_device) \
+do {\
+ writel(((_device)->vector & 0x000001FF), \
+ (_device)->bna->pcidev.pci_bar_kva + \
+ reg_offset[(_device)->bna->pcidev.pci_func].msix_idx);\
+} while (0)
+
+/**
+ *
+ * TxQ, RxQ, CQ related bits, offsets, macros
+ *
+ */
+
+#define BNA_Q_IDLE_STATE 0x00008001
+
+#define BNA_GET_DOORBELL_BASE_ADDR(_bar0) \
+ ((_bar0) + HQM_DOORBELL_BLK_BASE_ADDR)
+
+#define BNA_GET_DOORBELL_ENTRY_OFFSET(_entry) \
+ ((HQM_DOORBELL_BLK_BASE_ADDR) \
+ + (_entry << 7))
+
+#define BNA_DOORBELL_IB_INT_ACK(_timeout, _events) \
+ (0x80000000 | ((_timeout) << 16) | (_events))
+
+#define BNA_DOORBELL_IB_INT_DISABLE (0x40000000)
+
+/* TxQ Entry Opcodes */
+#define BNA_TXQ_WI_SEND (0x402) /* Single Frame Transmission */
+#define BNA_TXQ_WI_SEND_LSO (0x403) /* Multi-Frame Transmission */
+#define BNA_TXQ_WI_EXTENSION (0x104) /* Extension WI */
+
+/* TxQ Entry Control Flags */
+#define BNA_TXQ_WI_CF_FCOE_CRC (1 << 8)
+#define BNA_TXQ_WI_CF_IPID_MODE (1 << 5)
+#define BNA_TXQ_WI_CF_INS_PRIO (1 << 4)
+#define BNA_TXQ_WI_CF_INS_VLAN (1 << 3)
+#define BNA_TXQ_WI_CF_UDP_CKSUM (1 << 2)
+#define BNA_TXQ_WI_CF_TCP_CKSUM (1 << 1)
+#define BNA_TXQ_WI_CF_IP_CKSUM (1 << 0)
+
+#define BNA_TXQ_WI_L4_HDR_N_OFFSET(_hdr_size, _offset) \
+ (((_hdr_size) << 10) | ((_offset) & 0x3FF))
+
+/*
+ * Completion Q defines
+ */
+/* CQ Entry Flags */
+#define BNA_CQ_EF_MAC_ERROR (1 << 0)
+#define BNA_CQ_EF_FCS_ERROR (1 << 1)
+#define BNA_CQ_EF_TOO_LONG (1 << 2)
+#define BNA_CQ_EF_FC_CRC_OK (1 << 3)
+
+#define BNA_CQ_EF_RSVD1 (1 << 4)
+#define BNA_CQ_EF_L4_CKSUM_OK (1 << 5)
+#define BNA_CQ_EF_L3_CKSUM_OK (1 << 6)
+#define BNA_CQ_EF_HDS_HEADER (1 << 7)
+
+#define BNA_CQ_EF_UDP (1 << 8)
+#define BNA_CQ_EF_TCP (1 << 9)
+#define BNA_CQ_EF_IP_OPTIONS (1 << 10)
+#define BNA_CQ_EF_IPV6 (1 << 11)
+
+#define BNA_CQ_EF_IPV4 (1 << 12)
+#define BNA_CQ_EF_VLAN (1 << 13)
+#define BNA_CQ_EF_RSS (1 << 14)
+#define BNA_CQ_EF_RSVD2 (1 << 15)
+
+#define BNA_CQ_EF_MCAST_MATCH (1 << 16)
+#define BNA_CQ_EF_MCAST (1 << 17)
+#define BNA_CQ_EF_BCAST (1 << 18)
+#define BNA_CQ_EF_REMOTE (1 << 19)
+
+#define BNA_CQ_EF_LOCAL (1 << 20)
+
+/**
+ *
+ * Data structures
+ *
+ */
+
+enum txf_flags {
+ BFI_TXF_CF_ENABLE = 1 << 0,
+ BFI_TXF_CF_VLAN_FILTER = 1 << 8,
+ BFI_TXF_CF_VLAN_ADMIT = 1 << 9,
+ BFI_TXF_CF_VLAN_INSERT = 1 << 10,
+ BFI_TXF_CF_RSVD1 = 1 << 11,
+ BFI_TXF_CF_MAC_SA_CHECK = 1 << 12,
+ BFI_TXF_CF_VLAN_WI_BASED = 1 << 13,
+ BFI_TXF_CF_VSWITCH_MCAST = 1 << 14,
+ BFI_TXF_CF_VSWITCH_UCAST = 1 << 15,
+ BFI_TXF_CF_RSVD2 = 0x7F << 1
+};
+
+enum ib_flags {
+ BFI_IB_CF_MASTER_ENABLE = (1 << 0),
+ BFI_IB_CF_MSIX_MODE = (1 << 1),
+ BFI_IB_CF_COALESCING_MODE = (1 << 2),
+ BFI_IB_CF_INTER_PKT_ENABLE = (1 << 3),
+ BFI_IB_CF_INT_ENABLE = (1 << 4),
+ BFI_IB_CF_INTER_PKT_DMA = (1 << 5),
+ BFI_IB_CF_ACK_PENDING = (1 << 6),
+ BFI_IB_CF_RESERVED1 = (1 << 7)
+};
+
+enum rss_hash_type {
+ BFI_RSS_T_V4_TCP = (1 << 11),
+ BFI_RSS_T_V4_IP = (1 << 10),
+ BFI_RSS_T_V6_TCP = (1 << 9),
+ BFI_RSS_T_V6_IP = (1 << 8)
+};
+enum hds_header_type {
+ BNA_HDS_T_V4_TCP = (1 << 11),
+ BNA_HDS_T_V4_UDP = (1 << 10),
+ BNA_HDS_T_V6_TCP = (1 << 9),
+ BNA_HDS_T_V6_UDP = (1 << 8),
+ BNA_HDS_FORCED = (1 << 7),
+};
+enum rxf_flags {
+ BNA_RXF_CF_SM_LG_RXQ = (1 << 15),
+ BNA_RXF_CF_DEFAULT_VLAN = (1 << 14),
+ BNA_RXF_CF_DEFAULT_FUNCTION_ENABLE = (1 << 13),
+ BNA_RXF_CF_VLAN_STRIP = (1 << 12),
+ BNA_RXF_CF_RSS_ENABLE = (1 << 8)
+};
+struct bna_chip_regs_offset {
+ u32 page_addr;
+ u32 fn_int_status;
+ u32 fn_int_mask;
+ u32 msix_idx;
+};
+
+struct bna_chip_regs {
+ void __iomem *page_addr;
+ void __iomem *fn_int_status;
+ void __iomem *fn_int_mask;
+};
+
+struct bna_txq_mem {
+ u32 pg_tbl_addr_lo;
+ u32 pg_tbl_addr_hi;
+ u32 cur_q_entry_lo;
+ u32 cur_q_entry_hi;
+ u32 reserved1;
+ u32 reserved2;
+ u32 pg_cnt_n_prd_ptr; /* 31:16->total page count */
+ /* 15:0 ->producer pointer (index?) */
+ u32 entry_n_pg_size; /* 31:16->entry size */
+ /* 15:0 ->page size */
+ u32 int_blk_n_cns_ptr; /* 31:24->Int Blk Id; */
+ /* 23:16->Int Blk Offset */
+ /* 15:0 ->consumer pointer(index?) */
+ u32 cns_ptr2_n_q_state; /* 31:16->cons. ptr 2; 15:0-> Q state */
+ u32 nxt_qid_n_fid_n_pri; /* 17:10->next */
+ /* QId;9:3->FID;2:0->Priority */
+ u32 wvc_n_cquota_n_rquota; /* 31:24->WI Vector Count; */
+ /* 23:12->Cfg Quota; */
+ /* 11:0 ->Run Quota */
+ u32 reserved3[4];
+};
+
+struct bna_rxq_mem {
+ u32 pg_tbl_addr_lo;
+ u32 pg_tbl_addr_hi;
+ u32 cur_q_entry_lo;
+ u32 cur_q_entry_hi;
+ u32 reserved1;
+ u32 reserved2;
+ u32 pg_cnt_n_prd_ptr; /* 31:16->total page count */
+ /* 15:0 ->producer pointer (index?) */
+ u32 entry_n_pg_size; /* 31:16->entry size */
+ /* 15:0 ->page size */
+ u32 sg_n_cq_n_cns_ptr; /* 31:28->reserved; 27:24->sg count */
+ /* 23:16->CQ; */
+ /* 15:0->consumer pointer(index?) */
+ u32 buf_sz_n_q_state; /* 31:16->buffer size; 15:0-> Q state */
+ u32 next_qid; /* 17:10->next QId */
+ u32 reserved3;
+ u32 reserved4[4];
+};
+
+struct bna_rxtx_q_mem {
+ struct bna_rxq_mem rxq;
+ struct bna_txq_mem txq;
+};
+
+struct bna_cq_mem {
+ u32 pg_tbl_addr_lo;
+ u32 pg_tbl_addr_hi;
+ u32 cur_q_entry_lo;
+ u32 cur_q_entry_hi;
+
+ u32 reserved1;
+ u32 reserved2;
+ u32 pg_cnt_n_prd_ptr; /* 31:16->total page count */
+ /* 15:0 ->producer pointer (index?) */
+ u32 entry_n_pg_size; /* 31:16->entry size */
+ /* 15:0 ->page size */
+ u32 int_blk_n_cns_ptr; /* 31:24->Int Blk Id; */
+ /* 23:16->Int Blk Offset */
+ /* 15:0 ->consumer pointer(index?) */
+ u32 q_state; /* 31:16->reserved; 15:0-> Q state */
+ u32 reserved3[2];
+ u32 reserved4[4];
+};
+
+struct bna_ib_blk_mem {
+ u32 host_addr_lo;
+ u32 host_addr_hi;
+ u32 clsc_n_ctrl_n_msix; /* 31:24->coalescing; */
+ /* 23:16->coalescing cfg; */
+ /* 15:8 ->control; */
+ /* 7:0 ->msix; */
+ u32 ipkt_n_ent_n_idxof;
+ u32 ipkt_cnt_cfg_n_unacked;
+
+ u32 reserved[3];
+};
+
+struct bna_idx_tbl_mem {
+ u32 idx; /* !< 31:16->res;15:0->idx; */
+};
+
+struct bna_doorbell_qset {
+ u32 rxq[0x20 >> 2];
+ u32 txq[0x20 >> 2];
+ u32 ib0[0x20 >> 2];
+ u32 ib1[0x20 >> 2];
+};
+
+struct bna_rx_fndb_ram {
+ u32 rss_prop;
+ u32 size_routing_props;
+ u32 rit_hds_mcastq;
+ u32 control_flags;
+};
+
+struct bna_tx_fndb_ram {
+ u32 vlan_n_ctrl_flags;
+};
+
+/**
+ * @brief
+ * Structure which maps to RxFn Indirection Table (RIT)
+ * Size : 1 word
+ * See catapult_spec.pdf, RxA for details
+ */
+struct bna_rit_mem {
+ u32 rxq_ids; /* !< 31:12->res;11:0->two 6 bit RxQ Ids */
+};
+
+/**
+ * @brief
+ * Structure which maps to RSS Table entry
+ * Size : 16 words
+ * See catapult_spec.pdf, RAD for details
+ */
+struct bna_rss_mem {
+ /*
+ * 31:12-> res
+ * 11:8 -> protocol type
+ * 7:0 -> hash index
+ */
+ u32 type_n_hash;
+ u32 hash_key[10]; /* !< 40 byte Toeplitz hash key */
+ u32 reserved[5];
+};
+
+/* TxQ Vector (a.k.a. Tx-Buffer Descriptor) */
+struct bna_dma_addr {
+ u32 msb;
+ u32 lsb;
+};
+
+struct bna_txq_wi_vector {
+ u16 reserved;
+ u16 length; /* Only 14 LSB are valid */
+ struct bna_dma_addr host_addr; /* Tx-Buf DMA addr */
+};
+
+typedef u16 bna_txq_wi_opcode_t;
+
+typedef u16 bna_txq_wi_ctrl_flag_t;
+
+/**
+ * TxQ Entry Structure
+ *
+ * BEWARE: Load values into this structure with correct endianess.
+ */
+struct bna_txq_entry {
+ union {
+ struct {
+ u8 reserved;
+ u8 num_vectors; /* number of vectors present */
+ bna_txq_wi_opcode_t opcode; /* Either */
+ /* BNA_TXQ_WI_SEND or */
+ /* BNA_TXQ_WI_SEND_LSO */
+ bna_txq_wi_ctrl_flag_t flags; /* OR of all the flags */
+ u16 l4_hdr_size_n_offset;
+ u16 vlan_tag;
+ u16 lso_mss; /* Only 14 LSB are valid */
+ u32 frame_length; /* Only 24 LSB are valid */
+ } wi;
+
+ struct {
+ u16 reserved;
+ bna_txq_wi_opcode_t opcode; /* Must be */
+ /* BNA_TXQ_WI_EXTENSION */
+ u32 reserved2[3]; /* Place holder for */
+ /* removed vector (12 bytes) */
+ } wi_ext;
+ } hdr;
+ struct bna_txq_wi_vector vector[4];
+};
+#define wi_hdr hdr.wi
+#define wi_ext_hdr hdr.wi_ext
+
+/* RxQ Entry Structure */
+struct bna_rxq_entry { /* Rx-Buffer */
+ struct bna_dma_addr host_addr; /* Rx-Buffer DMA address */
+};
+
+typedef u32 bna_cq_e_flag_t;
+
+/* CQ Entry Structure */
+struct bna_cq_entry {
+ bna_cq_e_flag_t flags;
+ u16 vlan_tag;
+ u16 length;
+ u32 rss_hash;
+ u8 valid;
+ u8 reserved1;
+ u8 reserved2;
+ u8 rxq_id;
+};
+
+#endif /* __BNA_HW_H__ */
diff --git a/drivers/net/bna/bna_txrx.c b/drivers/net/bna/bna_txrx.c
new file mode 100644
index 000000000000..ad93fdb0f427
--- /dev/null
+++ b/drivers/net/bna/bna_txrx.c
@@ -0,0 +1,4172 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+#include "bna.h"
+#include "bfa_sm.h"
+#include "bfi.h"
+
+/**
+ * IB
+ */
+#define bna_ib_find_free_ibidx(_mask, _pos)\
+do {\
+ (_pos) = 0;\
+ while (((_pos) < (BFI_IBIDX_MAX_SEGSIZE)) &&\
+ ((1 << (_pos)) & (_mask)))\
+ (_pos)++;\
+} while (0)
+
+#define bna_ib_count_ibidx(_mask, _count)\
+do {\
+ int pos = 0;\
+ (_count) = 0;\
+ while (pos < (BFI_IBIDX_MAX_SEGSIZE)) {\
+ if ((1 << pos) & (_mask))\
+ (_count) = pos + 1;\
+ pos++;\
+ } \
+} while (0)
+
+#define bna_ib_select_segpool(_count, _q_idx)\
+do {\
+ int i;\
+ (_q_idx) = -1;\
+ for (i = 0; i < BFI_IBIDX_TOTAL_POOLS; i++) {\
+ if ((_count <= ibidx_pool[i].pool_entry_size)) {\
+ (_q_idx) = i;\
+ break;\
+ } \
+ } \
+} while (0)
+
+struct bna_ibidx_pool {
+ int pool_size;
+ int pool_entry_size;
+};
+init_ibidx_pool(ibidx_pool);
+
+static struct bna_intr *
+bna_intr_get(struct bna_ib_mod *ib_mod, enum bna_intr_type intr_type,
+ int vector)
+{
+ struct bna_intr *intr;
+ struct list_head *qe;
+
+ list_for_each(qe, &ib_mod->intr_active_q) {
+ intr = (struct bna_intr *)qe;
+
+ if ((intr->intr_type == intr_type) &&
+ (intr->vector == vector)) {
+ intr->ref_count++;
+ return intr;
+ }
+ }
+
+ if (list_empty(&ib_mod->intr_free_q))
+ return NULL;
+
+ bfa_q_deq(&ib_mod->intr_free_q, &intr);
+ bfa_q_qe_init(&intr->qe);
+
+ intr->ref_count = 1;
+ intr->intr_type = intr_type;
+ intr->vector = vector;
+
+ list_add_tail(&intr->qe, &ib_mod->intr_active_q);
+
+ return intr;
+}
+
+static void
+bna_intr_put(struct bna_ib_mod *ib_mod,
+ struct bna_intr *intr)
+{
+ intr->ref_count--;
+
+ if (intr->ref_count == 0) {
+ intr->ib = NULL;
+ list_del(&intr->qe);
+ bfa_q_qe_init(&intr->qe);
+ list_add_tail(&intr->qe, &ib_mod->intr_free_q);
+ }
+}
+
+void
+bna_ib_mod_init(struct bna_ib_mod *ib_mod, struct bna *bna,
+ struct bna_res_info *res_info)
+{
+ int i;
+ int j;
+ int count;
+ u8 offset;
+ struct bna_doorbell_qset *qset;
+ unsigned long off;
+
+ ib_mod->bna = bna;
+
+ ib_mod->ib = (struct bna_ib *)
+ res_info[BNA_RES_MEM_T_IB_ARRAY].res_u.mem_info.mdl[0].kva;
+ ib_mod->intr = (struct bna_intr *)
+ res_info[BNA_RES_MEM_T_INTR_ARRAY].res_u.mem_info.mdl[0].kva;
+ ib_mod->idx_seg = (struct bna_ibidx_seg *)
+ res_info[BNA_RES_MEM_T_IDXSEG_ARRAY].res_u.mem_info.mdl[0].kva;
+
+ INIT_LIST_HEAD(&ib_mod->ib_free_q);
+ INIT_LIST_HEAD(&ib_mod->intr_free_q);
+ INIT_LIST_HEAD(&ib_mod->intr_active_q);
+
+ for (i = 0; i < BFI_IBIDX_TOTAL_POOLS; i++)
+ INIT_LIST_HEAD(&ib_mod->ibidx_seg_pool[i]);
+
+ for (i = 0; i < BFI_MAX_IB; i++) {
+ ib_mod->ib[i].ib_id = i;
+
+ ib_mod->ib[i].ib_seg_host_addr_kva =
+ res_info[BNA_RES_MEM_T_IBIDX].res_u.mem_info.mdl[i].kva;
+ ib_mod->ib[i].ib_seg_host_addr.lsb =
+ res_info[BNA_RES_MEM_T_IBIDX].res_u.mem_info.mdl[i].dma.lsb;
+ ib_mod->ib[i].ib_seg_host_addr.msb =
+ res_info[BNA_RES_MEM_T_IBIDX].res_u.mem_info.mdl[i].dma.msb;
+
+ qset = (struct bna_doorbell_qset *)0;
+ off = (unsigned long)(&qset[i >> 1].ib0[(i & 0x1)
+ * (0x20 >> 2)]);
+ ib_mod->ib[i].door_bell.doorbell_addr = off +
+ BNA_GET_DOORBELL_BASE_ADDR(bna->pcidev.pci_bar_kva);
+
+ bfa_q_qe_init(&ib_mod->ib[i].qe);
+ list_add_tail(&ib_mod->ib[i].qe, &ib_mod->ib_free_q);
+
+ bfa_q_qe_init(&ib_mod->intr[i].qe);
+ list_add_tail(&ib_mod->intr[i].qe, &ib_mod->intr_free_q);
+ }
+
+ count = 0;
+ offset = 0;
+ for (i = 0; i < BFI_IBIDX_TOTAL_POOLS; i++) {
+ for (j = 0; j < ibidx_pool[i].pool_size; j++) {
+ bfa_q_qe_init(&ib_mod->idx_seg[count]);
+ ib_mod->idx_seg[count].ib_seg_size =
+ ibidx_pool[i].pool_entry_size;
+ ib_mod->idx_seg[count].ib_idx_tbl_offset = offset;
+ list_add_tail(&ib_mod->idx_seg[count].qe,
+ &ib_mod->ibidx_seg_pool[i]);
+ count++;
+ offset += ibidx_pool[i].pool_entry_size;
+ }
+ }
+}
+
+void
+bna_ib_mod_uninit(struct bna_ib_mod *ib_mod)
+{
+ int i;
+ int j;
+ struct list_head *qe;
+
+ i = 0;
+ list_for_each(qe, &ib_mod->ib_free_q)
+ i++;
+
+ i = 0;
+ list_for_each(qe, &ib_mod->intr_free_q)
+ i++;
+
+ for (i = 0; i < BFI_IBIDX_TOTAL_POOLS; i++) {
+ j = 0;
+ list_for_each(qe, &ib_mod->ibidx_seg_pool[i])
+ j++;
+ }
+
+ ib_mod->bna = NULL;
+}
+
+static struct bna_ib *
+bna_ib_get(struct bna_ib_mod *ib_mod,
+ enum bna_intr_type intr_type,
+ int vector)
+{
+ struct bna_ib *ib;
+ struct bna_intr *intr;
+
+ if (intr_type == BNA_INTR_T_INTX)
+ vector = (1 << vector);
+
+ intr = bna_intr_get(ib_mod, intr_type, vector);
+ if (intr == NULL)
+ return NULL;
+
+ if (intr->ib) {
+ if (intr->ib->ref_count == BFI_IBIDX_MAX_SEGSIZE) {
+ bna_intr_put(ib_mod, intr);
+ return NULL;
+ }
+ intr->ib->ref_count++;
+ return intr->ib;
+ }
+
+ if (list_empty(&ib_mod->ib_free_q)) {
+ bna_intr_put(ib_mod, intr);
+ return NULL;
+ }
+
+ bfa_q_deq(&ib_mod->ib_free_q, &ib);
+ bfa_q_qe_init(&ib->qe);
+
+ ib->ref_count = 1;
+ ib->start_count = 0;
+ ib->idx_mask = 0;
+
+ ib->intr = intr;
+ ib->idx_seg = NULL;
+ intr->ib = ib;
+
+ ib->bna = ib_mod->bna;
+
+ return ib;
+}
+
+static void
+bna_ib_put(struct bna_ib_mod *ib_mod, struct bna_ib *ib)
+{
+ bna_intr_put(ib_mod, ib->intr);
+
+ ib->ref_count--;
+
+ if (ib->ref_count == 0) {
+ ib->intr = NULL;
+ ib->bna = NULL;
+ list_add_tail(&ib->qe, &ib_mod->ib_free_q);
+ }
+}
+
+/* Returns index offset - starting from 0 */
+static int
+bna_ib_reserve_idx(struct bna_ib *ib)
+{
+ struct bna_ib_mod *ib_mod = &ib->bna->ib_mod;
+ struct bna_ibidx_seg *idx_seg;
+ int idx;
+ int num_idx;
+ int q_idx;
+
+ /* Find the first free index position */
+ bna_ib_find_free_ibidx(ib->idx_mask, idx);
+ if (idx == BFI_IBIDX_MAX_SEGSIZE)
+ return -1;
+
+ /*
+ * Calculate the total number of indexes held by this IB,
+ * including the index newly reserved above.
+ */
+ bna_ib_count_ibidx((ib->idx_mask | (1 << idx)), num_idx);
+
+ /* See if there is a free space in the index segment held by this IB */
+ if (ib->idx_seg && (num_idx <= ib->idx_seg->ib_seg_size)) {
+ ib->idx_mask |= (1 << idx);
+ return idx;
+ }
+
+ if (ib->start_count)
+ return -1;
+
+ /* Allocate a new segment */
+ bna_ib_select_segpool(num_idx, q_idx);
+ while (1) {
+ if (q_idx == BFI_IBIDX_TOTAL_POOLS)
+ return -1;
+ if (!list_empty(&ib_mod->ibidx_seg_pool[q_idx]))
+ break;
+ q_idx++;
+ }
+ bfa_q_deq(&ib_mod->ibidx_seg_pool[q_idx], &idx_seg);
+ bfa_q_qe_init(&idx_seg->qe);
+
+ /* Free the old segment */
+ if (ib->idx_seg) {
+ bna_ib_select_segpool(ib->idx_seg->ib_seg_size, q_idx);
+ list_add_tail(&ib->idx_seg->qe, &ib_mod->ibidx_seg_pool[q_idx]);
+ }
+
+ ib->idx_seg = idx_seg;
+
+ ib->idx_mask |= (1 << idx);
+
+ return idx;
+}
+
+static void
+bna_ib_release_idx(struct bna_ib *ib, int idx)
+{
+ struct bna_ib_mod *ib_mod = &ib->bna->ib_mod;
+ struct bna_ibidx_seg *idx_seg;
+ int num_idx;
+ int cur_q_idx;
+ int new_q_idx;
+
+ ib->idx_mask &= ~(1 << idx);
+
+ if (ib->start_count)
+ return;
+
+ bna_ib_count_ibidx(ib->idx_mask, num_idx);
+
+ /*
+ * Free the segment, if there are no more indexes in the segment
+ * held by this IB
+ */
+ if (!num_idx) {
+ bna_ib_select_segpool(ib->idx_seg->ib_seg_size, cur_q_idx);
+ list_add_tail(&ib->idx_seg->qe,
+ &ib_mod->ibidx_seg_pool[cur_q_idx]);
+ ib->idx_seg = NULL;
+ return;
+ }
+
+ /* See if we can move to a smaller segment */
+ bna_ib_select_segpool(num_idx, new_q_idx);
+ bna_ib_select_segpool(ib->idx_seg->ib_seg_size, cur_q_idx);
+ while (new_q_idx < cur_q_idx) {
+ if (!list_empty(&ib_mod->ibidx_seg_pool[new_q_idx]))
+ break;
+ new_q_idx++;
+ }
+ if (new_q_idx < cur_q_idx) {
+ /* Select the new smaller segment */
+ bfa_q_deq(&ib_mod->ibidx_seg_pool[new_q_idx], &idx_seg);
+ bfa_q_qe_init(&idx_seg->qe);
+ /* Free the old segment */
+ list_add_tail(&ib->idx_seg->qe,
+ &ib_mod->ibidx_seg_pool[cur_q_idx]);
+ ib->idx_seg = idx_seg;
+ }
+}
+
+static int
+bna_ib_config(struct bna_ib *ib, struct bna_ib_config *ib_config)
+{
+ if (ib->start_count)
+ return -1;
+
+ ib->ib_config.coalescing_timeo = ib_config->coalescing_timeo;
+ ib->ib_config.interpkt_timeo = ib_config->interpkt_timeo;
+ ib->ib_config.interpkt_count = ib_config->interpkt_count;
+ ib->ib_config.ctrl_flags = ib_config->ctrl_flags;
+
+ ib->ib_config.ctrl_flags |= BFI_IB_CF_MASTER_ENABLE;
+ if (ib->intr->intr_type == BNA_INTR_T_MSIX)
+ ib->ib_config.ctrl_flags |= BFI_IB_CF_MSIX_MODE;
+
+ return 0;
+}
+
+static void
+bna_ib_start(struct bna_ib *ib)
+{
+ struct bna_ib_blk_mem ib_cfg;
+ struct bna_ib_blk_mem *ib_mem;
+ u32 pg_num;
+ u32 intx_mask;
+ int i;
+ void __iomem *base_addr;
+ unsigned long off;
+
+ ib->start_count++;
+
+ if (ib->start_count > 1)
+ return;
+
+ ib_cfg.host_addr_lo = (u32)(ib->ib_seg_host_addr.lsb);
+ ib_cfg.host_addr_hi = (u32)(ib->ib_seg_host_addr.msb);
+
+ ib_cfg.clsc_n_ctrl_n_msix = (((u32)
+ ib->ib_config.coalescing_timeo << 16) |
+ ((u32)ib->ib_config.ctrl_flags << 8) |
+ (ib->intr->vector));
+ ib_cfg.ipkt_n_ent_n_idxof =
+ ((u32)
+ (ib->ib_config.interpkt_timeo & 0xf) << 16) |
+ ((u32)ib->idx_seg->ib_seg_size << 8) |
+ (ib->idx_seg->ib_idx_tbl_offset);
+ ib_cfg.ipkt_cnt_cfg_n_unacked = ((u32)
+ ib->ib_config.interpkt_count << 24);
+
+ pg_num = BNA_GET_PAGE_NUM(HQM0_BLK_PG_NUM + ib->bna->port_num,
+ HQM_IB_RAM_BASE_OFFSET);
+ writel(pg_num, ib->bna->regs.page_addr);
+
+ base_addr = BNA_GET_MEM_BASE_ADDR(ib->bna->pcidev.pci_bar_kva,
+ HQM_IB_RAM_BASE_OFFSET);
+
+ ib_mem = (struct bna_ib_blk_mem *)0;
+ off = (unsigned long)&ib_mem[ib->ib_id].host_addr_lo;
+ writel(htonl(ib_cfg.host_addr_lo), base_addr + off);
+
+ off = (unsigned long)&ib_mem[ib->ib_id].host_addr_hi;
+ writel(htonl(ib_cfg.host_addr_hi), base_addr + off);
+
+ off = (unsigned long)&ib_mem[ib->ib_id].clsc_n_ctrl_n_msix;
+ writel(ib_cfg.clsc_n_ctrl_n_msix, base_addr + off);
+
+ off = (unsigned long)&ib_mem[ib->ib_id].ipkt_n_ent_n_idxof;
+ writel(ib_cfg.ipkt_n_ent_n_idxof, base_addr + off);
+
+ off = (unsigned long)&ib_mem[ib->ib_id].ipkt_cnt_cfg_n_unacked;
+ writel(ib_cfg.ipkt_cnt_cfg_n_unacked, base_addr + off);
+
+ ib->door_bell.doorbell_ack = BNA_DOORBELL_IB_INT_ACK(
+ (u32)ib->ib_config.coalescing_timeo, 0);
+
+ pg_num = BNA_GET_PAGE_NUM(HQM0_BLK_PG_NUM + ib->bna->port_num,
+ HQM_INDX_TBL_RAM_BASE_OFFSET);
+ writel(pg_num, ib->bna->regs.page_addr);
+
+ base_addr = BNA_GET_MEM_BASE_ADDR(ib->bna->pcidev.pci_bar_kva,
+ HQM_INDX_TBL_RAM_BASE_OFFSET);
+ for (i = 0; i < ib->idx_seg->ib_seg_size; i++) {
+ off = (unsigned long)
+ ((ib->idx_seg->ib_idx_tbl_offset + i) * BFI_IBIDX_SIZE);
+ writel(0, base_addr + off);
+ }
+
+ if (ib->intr->intr_type == BNA_INTR_T_INTX) {
+ bna_intx_disable(ib->bna, intx_mask);
+ intx_mask &= ~(ib->intr->vector);
+ bna_intx_enable(ib->bna, intx_mask);
+ }
+}
+
+static void
+bna_ib_stop(struct bna_ib *ib)
+{
+ u32 intx_mask;
+
+ ib->start_count--;
+
+ if (ib->start_count == 0) {
+ writel(BNA_DOORBELL_IB_INT_DISABLE,
+ ib->door_bell.doorbell_addr);
+ if (ib->intr->intr_type == BNA_INTR_T_INTX) {
+ bna_intx_disable(ib->bna, intx_mask);
+ intx_mask |= (ib->intr->vector);
+ bna_intx_enable(ib->bna, intx_mask);
+ }
+ }
+}
+
+static void
+bna_ib_fail(struct bna_ib *ib)
+{
+ ib->start_count = 0;
+}
+
+/**
+ * RXF
+ */
+static void rxf_enable(struct bna_rxf *rxf);
+static void rxf_disable(struct bna_rxf *rxf);
+static void __rxf_config_set(struct bna_rxf *rxf);
+static void __rxf_rit_set(struct bna_rxf *rxf);
+static void __bna_rxf_stat_clr(struct bna_rxf *rxf);
+static int rxf_process_packet_filter(struct bna_rxf *rxf);
+static int rxf_clear_packet_filter(struct bna_rxf *rxf);
+static void rxf_reset_packet_filter(struct bna_rxf *rxf);
+static void rxf_cb_enabled(void *arg, int status);
+static void rxf_cb_disabled(void *arg, int status);
+static void bna_rxf_cb_stats_cleared(void *arg, int status);
+static void __rxf_enable(struct bna_rxf *rxf);
+static void __rxf_disable(struct bna_rxf *rxf);
+
+bfa_fsm_state_decl(bna_rxf, stopped, struct bna_rxf,
+ enum bna_rxf_event);
+bfa_fsm_state_decl(bna_rxf, start_wait, struct bna_rxf,
+ enum bna_rxf_event);
+bfa_fsm_state_decl(bna_rxf, cam_fltr_mod_wait, struct bna_rxf,
+ enum bna_rxf_event);
+bfa_fsm_state_decl(bna_rxf, started, struct bna_rxf,
+ enum bna_rxf_event);
+bfa_fsm_state_decl(bna_rxf, cam_fltr_clr_wait, struct bna_rxf,
+ enum bna_rxf_event);
+bfa_fsm_state_decl(bna_rxf, stop_wait, struct bna_rxf,
+ enum bna_rxf_event);
+bfa_fsm_state_decl(bna_rxf, pause_wait, struct bna_rxf,
+ enum bna_rxf_event);
+bfa_fsm_state_decl(bna_rxf, resume_wait, struct bna_rxf,
+ enum bna_rxf_event);
+bfa_fsm_state_decl(bna_rxf, stat_clr_wait, struct bna_rxf,
+ enum bna_rxf_event);
+
+static struct bfa_sm_table rxf_sm_table[] = {
+ {BFA_SM(bna_rxf_sm_stopped), BNA_RXF_STOPPED},
+ {BFA_SM(bna_rxf_sm_start_wait), BNA_RXF_START_WAIT},
+ {BFA_SM(bna_rxf_sm_cam_fltr_mod_wait), BNA_RXF_CAM_FLTR_MOD_WAIT},
+ {BFA_SM(bna_rxf_sm_started), BNA_RXF_STARTED},
+ {BFA_SM(bna_rxf_sm_cam_fltr_clr_wait), BNA_RXF_CAM_FLTR_CLR_WAIT},
+ {BFA_SM(bna_rxf_sm_stop_wait), BNA_RXF_STOP_WAIT},
+ {BFA_SM(bna_rxf_sm_pause_wait), BNA_RXF_PAUSE_WAIT},
+ {BFA_SM(bna_rxf_sm_resume_wait), BNA_RXF_RESUME_WAIT},
+ {BFA_SM(bna_rxf_sm_stat_clr_wait), BNA_RXF_STAT_CLR_WAIT}
+};
+
+static void
+bna_rxf_sm_stopped_entry(struct bna_rxf *rxf)
+{
+ call_rxf_stop_cbfn(rxf, BNA_CB_SUCCESS);
+}
+
+static void
+bna_rxf_sm_stopped(struct bna_rxf *rxf, enum bna_rxf_event event)
+{
+ switch (event) {
+ case RXF_E_START:
+ bfa_fsm_set_state(rxf, bna_rxf_sm_start_wait);
+ break;
+
+ case RXF_E_STOP:
+ bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
+ break;
+
+ case RXF_E_FAIL:
+ /* No-op */
+ break;
+
+ case RXF_E_CAM_FLTR_MOD:
+ call_rxf_cam_fltr_cbfn(rxf, BNA_CB_SUCCESS);
+ break;
+
+ case RXF_E_STARTED:
+ case RXF_E_STOPPED:
+ case RXF_E_CAM_FLTR_RESP:
+ /**
+ * These events are received due to flushing of mbox
+ * when device fails
+ */
+ /* No-op */
+ break;
+
+ case RXF_E_PAUSE:
+ rxf->rxf_oper_state = BNA_RXF_OPER_STATE_PAUSED;
+ call_rxf_pause_cbfn(rxf, BNA_CB_SUCCESS);
+ break;
+
+ case RXF_E_RESUME:
+ rxf->rxf_oper_state = BNA_RXF_OPER_STATE_RUNNING;
+ call_rxf_resume_cbfn(rxf, BNA_CB_SUCCESS);
+ break;
+
+ default:
+ bfa_sm_fault(rxf->rx->bna, event);
+ }
+}
+
+static void
+bna_rxf_sm_start_wait_entry(struct bna_rxf *rxf)
+{
+ __rxf_config_set(rxf);
+ __rxf_rit_set(rxf);
+ rxf_enable(rxf);
+}
+
+static void
+bna_rxf_sm_start_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
+{
+ switch (event) {
+ case RXF_E_STOP:
+ /**
+ * STOP is originated from bnad. When this happens,
+ * it can not be waiting for filter update
+ */
+ call_rxf_start_cbfn(rxf, BNA_CB_INTERRUPT);
+ bfa_fsm_set_state(rxf, bna_rxf_sm_stop_wait);
+ break;
+
+ case RXF_E_FAIL:
+ call_rxf_cam_fltr_cbfn(rxf, BNA_CB_SUCCESS);
+ call_rxf_start_cbfn(rxf, BNA_CB_FAIL);
+ bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
+ break;
+
+ case RXF_E_CAM_FLTR_MOD:
+ /* No-op */
+ break;
+
+ case RXF_E_STARTED:
+ /**
+ * Force rxf_process_filter() to go through initial
+ * config
+ */
+ if ((rxf->ucast_active_mac != NULL) &&
+ (rxf->ucast_pending_set == 0))
+ rxf->ucast_pending_set = 1;
+
+ if (rxf->rss_status == BNA_STATUS_T_ENABLED)
+ rxf->rxf_flags |= BNA_RXF_FL_RSS_CONFIG_PENDING;
+
+ rxf->rxf_flags |= BNA_RXF_FL_VLAN_CONFIG_PENDING;
+
+ bfa_fsm_set_state(rxf, bna_rxf_sm_cam_fltr_mod_wait);
+ break;
+
+ case RXF_E_PAUSE:
+ case RXF_E_RESUME:
+ rxf->rxf_flags |= BNA_RXF_FL_OPERSTATE_CHANGED;
+ break;
+
+ default:
+ bfa_sm_fault(rxf->rx->bna, event);
+ }
+}
+
+static void
+bna_rxf_sm_cam_fltr_mod_wait_entry(struct bna_rxf *rxf)
+{
+ if (!rxf_process_packet_filter(rxf)) {
+ /* No more pending CAM entries to update */
+ bfa_fsm_set_state(rxf, bna_rxf_sm_started);
+ }
+}
+
+static void
+bna_rxf_sm_cam_fltr_mod_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
+{
+ switch (event) {
+ case RXF_E_STOP:
+ /**
+ * STOP is originated from bnad. When this happens,
+ * it can not be waiting for filter update
+ */
+ call_rxf_start_cbfn(rxf, BNA_CB_INTERRUPT);
+ bfa_fsm_set_state(rxf, bna_rxf_sm_cam_fltr_clr_wait);
+ break;
+
+ case RXF_E_FAIL:
+ rxf_reset_packet_filter(rxf);
+ call_rxf_cam_fltr_cbfn(rxf, BNA_CB_SUCCESS);
+ call_rxf_start_cbfn(rxf, BNA_CB_FAIL);
+ bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
+ break;
+
+ case RXF_E_CAM_FLTR_MOD:
+ /* No-op */
+ break;
+
+ case RXF_E_CAM_FLTR_RESP:
+ if (!rxf_process_packet_filter(rxf)) {
+ /* No more pending CAM entries to update */
+ call_rxf_cam_fltr_cbfn(rxf, BNA_CB_SUCCESS);
+ bfa_fsm_set_state(rxf, bna_rxf_sm_started);
+ }
+ break;
+
+ case RXF_E_PAUSE:
+ case RXF_E_RESUME:
+ rxf->rxf_flags |= BNA_RXF_FL_OPERSTATE_CHANGED;
+ break;
+
+ default:
+ bfa_sm_fault(rxf->rx->bna, event);
+ }
+}
+
+static void
+bna_rxf_sm_started_entry(struct bna_rxf *rxf)
+{
+ call_rxf_start_cbfn(rxf, BNA_CB_SUCCESS);
+
+ if (rxf->rxf_flags & BNA_RXF_FL_OPERSTATE_CHANGED) {
+ if (rxf->rxf_oper_state == BNA_RXF_OPER_STATE_PAUSED)
+ bfa_fsm_send_event(rxf, RXF_E_PAUSE);
+ else
+ bfa_fsm_send_event(rxf, RXF_E_RESUME);
+ }
+
+}
+
+static void
+bna_rxf_sm_started(struct bna_rxf *rxf, enum bna_rxf_event event)
+{
+ switch (event) {
+ case RXF_E_STOP:
+ bfa_fsm_set_state(rxf, bna_rxf_sm_cam_fltr_clr_wait);
+ /* Hack to get FSM start clearing CAM entries */
+ bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_RESP);
+ break;
+
+ case RXF_E_FAIL:
+ rxf_reset_packet_filter(rxf);
+ bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
+ break;
+
+ case RXF_E_CAM_FLTR_MOD:
+ bfa_fsm_set_state(rxf, bna_rxf_sm_cam_fltr_mod_wait);
+ break;
+
+ case RXF_E_PAUSE:
+ bfa_fsm_set_state(rxf, bna_rxf_sm_pause_wait);
+ break;
+
+ case RXF_E_RESUME:
+ bfa_fsm_set_state(rxf, bna_rxf_sm_resume_wait);
+ break;
+
+ default:
+ bfa_sm_fault(rxf->rx->bna, event);
+ }
+}
+
+static void
+bna_rxf_sm_cam_fltr_clr_wait_entry(struct bna_rxf *rxf)
+{
+ /**
+ * Note: Do not add rxf_clear_packet_filter here.
+ * It will overstep mbox when this transition happens:
+ * cam_fltr_mod_wait -> cam_fltr_clr_wait on RXF_E_STOP event
+ */
+}
+
+static void
+bna_rxf_sm_cam_fltr_clr_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
+{
+ switch (event) {
+ case RXF_E_FAIL:
+ /**
+ * FSM was in the process of stopping, initiated by
+ * bnad. When this happens, no one can be waiting for
+ * start or filter update
+ */
+ rxf_reset_packet_filter(rxf);
+ bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
+ break;
+
+ case RXF_E_CAM_FLTR_RESP:
+ if (!rxf_clear_packet_filter(rxf)) {
+ /* No more pending CAM entries to clear */
+ bfa_fsm_set_state(rxf, bna_rxf_sm_stop_wait);
+ rxf_disable(rxf);
+ }
+ break;
+
+ default:
+ bfa_sm_fault(rxf->rx->bna, event);
+ }
+}
+
+static void
+bna_rxf_sm_stop_wait_entry(struct bna_rxf *rxf)
+{
+ /**
+ * NOTE: Do not add rxf_disable here.
+ * It will overstep mbox when this transition happens:
+ * start_wait -> stop_wait on RXF_E_STOP event
+ */
+}
+
+static void
+bna_rxf_sm_stop_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
+{
+ switch (event) {
+ case RXF_E_FAIL:
+ /**
+ * FSM was in the process of stopping, initiated by
+ * bnad. When this happens, no one can be waiting for
+ * start or filter update
+ */
+ bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
+ break;
+
+ case RXF_E_STARTED:
+ /**
+ * This event is received due to abrupt transition from
+ * bna_rxf_sm_start_wait state on receiving
+ * RXF_E_STOP event
+ */
+ rxf_disable(rxf);
+ break;
+
+ case RXF_E_STOPPED:
+ /**
+ * FSM was in the process of stopping, initiated by
+ * bnad. When this happens, no one can be waiting for
+ * start or filter update
+ */
+ bfa_fsm_set_state(rxf, bna_rxf_sm_stat_clr_wait);
+ break;
+
+ case RXF_E_PAUSE:
+ rxf->rxf_oper_state = BNA_RXF_OPER_STATE_PAUSED;
+ break;
+
+ case RXF_E_RESUME:
+ rxf->rxf_oper_state = BNA_RXF_OPER_STATE_RUNNING;
+ break;
+
+ default:
+ bfa_sm_fault(rxf->rx->bna, event);
+ }
+}
+
+static void
+bna_rxf_sm_pause_wait_entry(struct bna_rxf *rxf)
+{
+ rxf->rxf_flags &=
+ ~(BNA_RXF_FL_OPERSTATE_CHANGED | BNA_RXF_FL_RXF_ENABLED);
+ __rxf_disable(rxf);
+}
+
+static void
+bna_rxf_sm_pause_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
+{
+ switch (event) {
+ case RXF_E_FAIL:
+ /**
+ * FSM was in the process of disabling rxf, initiated by
+ * bnad.
+ */
+ call_rxf_pause_cbfn(rxf, BNA_CB_FAIL);
+ bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
+ break;
+
+ case RXF_E_STOPPED:
+ rxf->rxf_oper_state = BNA_RXF_OPER_STATE_PAUSED;
+ call_rxf_pause_cbfn(rxf, BNA_CB_SUCCESS);
+ bfa_fsm_set_state(rxf, bna_rxf_sm_started);
+ break;
+
+ /*
+ * Since PAUSE/RESUME can only be sent by bnad, we don't expect
+ * any other event during these states
+ */
+ default:
+ bfa_sm_fault(rxf->rx->bna, event);
+ }
+}
+
+static void
+bna_rxf_sm_resume_wait_entry(struct bna_rxf *rxf)
+{
+ rxf->rxf_flags &= ~(BNA_RXF_FL_OPERSTATE_CHANGED);
+ rxf->rxf_flags |= BNA_RXF_FL_RXF_ENABLED;
+ __rxf_enable(rxf);
+}
+
+static void
+bna_rxf_sm_resume_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
+{
+ switch (event) {
+ case RXF_E_FAIL:
+ /**
+ * FSM was in the process of disabling rxf, initiated by
+ * bnad.
+ */
+ call_rxf_resume_cbfn(rxf, BNA_CB_FAIL);
+ bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
+ break;
+
+ case RXF_E_STARTED:
+ rxf->rxf_oper_state = BNA_RXF_OPER_STATE_RUNNING;
+ call_rxf_resume_cbfn(rxf, BNA_CB_SUCCESS);
+ bfa_fsm_set_state(rxf, bna_rxf_sm_started);
+ break;
+
+ /*
+ * Since PAUSE/RESUME can only be sent by bnad, we don't expect
+ * any other event during these states
+ */
+ default:
+ bfa_sm_fault(rxf->rx->bna, event);
+ }
+}
+
+static void
+bna_rxf_sm_stat_clr_wait_entry(struct bna_rxf *rxf)
+{
+ __bna_rxf_stat_clr(rxf);
+}
+
+static void
+bna_rxf_sm_stat_clr_wait(struct bna_rxf *rxf, enum bna_rxf_event event)
+{
+ switch (event) {
+ case RXF_E_FAIL:
+ case RXF_E_STAT_CLEARED:
+ bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
+ break;
+
+ default:
+ bfa_sm_fault(rxf->rx->bna, event);
+ }
+}
+
+static void
+__rxf_enable(struct bna_rxf *rxf)
+{
+ struct bfi_ll_rxf_multi_req ll_req;
+ u32 bm[2] = {0, 0};
+
+ if (rxf->rxf_id < 32)
+ bm[0] = 1 << rxf->rxf_id;
+ else
+ bm[1] = 1 << (rxf->rxf_id - 32);
+
+ bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_RX_REQ, 0);
+ ll_req.rxf_id_mask[0] = htonl(bm[0]);
+ ll_req.rxf_id_mask[1] = htonl(bm[1]);
+ ll_req.enable = 1;
+
+ bna_mbox_qe_fill(&rxf->mbox_qe, &ll_req, sizeof(ll_req),
+ rxf_cb_enabled, rxf);
+
+ bna_mbox_send(rxf->rx->bna, &rxf->mbox_qe);
+}
+
+static void
+__rxf_disable(struct bna_rxf *rxf)
+{
+ struct bfi_ll_rxf_multi_req ll_req;
+ u32 bm[2] = {0, 0};
+
+ if (rxf->rxf_id < 32)
+ bm[0] = 1 << rxf->rxf_id;
+ else
+ bm[1] = 1 << (rxf->rxf_id - 32);
+
+ bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_RX_REQ, 0);
+ ll_req.rxf_id_mask[0] = htonl(bm[0]);
+ ll_req.rxf_id_mask[1] = htonl(bm[1]);
+ ll_req.enable = 0;
+
+ bna_mbox_qe_fill(&rxf->mbox_qe, &ll_req, sizeof(ll_req),
+ rxf_cb_disabled, rxf);
+
+ bna_mbox_send(rxf->rx->bna, &rxf->mbox_qe);
+}
+
+static void
+__rxf_config_set(struct bna_rxf *rxf)
+{
+ u32 i;
+ struct bna_rss_mem *rss_mem;
+ struct bna_rx_fndb_ram *rx_fndb_ram;
+ struct bna *bna = rxf->rx->bna;
+ void __iomem *base_addr;
+ unsigned long off;
+
+ base_addr = BNA_GET_MEM_BASE_ADDR(bna->pcidev.pci_bar_kva,
+ RSS_TABLE_BASE_OFFSET);
+
+ rss_mem = (struct bna_rss_mem *)0;
+
+ /* Configure RSS if required */
+ if (rxf->ctrl_flags & BNA_RXF_CF_RSS_ENABLE) {
+ /* configure RSS Table */
+ writel(BNA_GET_PAGE_NUM(RAD0_MEM_BLK_BASE_PG_NUM +
+ bna->port_num, RSS_TABLE_BASE_OFFSET),
+ bna->regs.page_addr);
+
+ /* temporarily disable RSS, while hash value is written */
+ off = (unsigned long)&rss_mem[0].type_n_hash;
+ writel(0, base_addr + off);
+
+ for (i = 0; i < BFI_RSS_HASH_KEY_LEN; i++) {
+ off = (unsigned long)
+ &rss_mem[0].hash_key[(BFI_RSS_HASH_KEY_LEN - 1) - i];
+ writel(htonl(rxf->rss_cfg.toeplitz_hash_key[i]),
+ base_addr + off);
+ }
+
+ off = (unsigned long)&rss_mem[0].type_n_hash;
+ writel(rxf->rss_cfg.hash_type | rxf->rss_cfg.hash_mask,
+ base_addr + off);
+ }
+
+ /* Configure RxF */
+ writel(BNA_GET_PAGE_NUM(
+ LUT0_MEM_BLK_BASE_PG_NUM + (bna->port_num * 2),
+ RX_FNDB_RAM_BASE_OFFSET),
+ bna->regs.page_addr);
+
+ base_addr = BNA_GET_MEM_BASE_ADDR(bna->pcidev.pci_bar_kva,
+ RX_FNDB_RAM_BASE_OFFSET);
+
+ rx_fndb_ram = (struct bna_rx_fndb_ram *)0;
+
+ /* We always use RSS table 0 */
+ off = (unsigned long)&rx_fndb_ram[rxf->rxf_id].rss_prop;
+ writel(rxf->ctrl_flags & BNA_RXF_CF_RSS_ENABLE,
+ base_addr + off);
+
+ /* small large buffer enable/disable */
+ off = (unsigned long)&rx_fndb_ram[rxf->rxf_id].size_routing_props;
+ writel((rxf->ctrl_flags & BNA_RXF_CF_SM_LG_RXQ) | 0x80,
+ base_addr + off);
+
+ /* RIT offset, HDS forced offset, multicast RxQ Id */
+ off = (unsigned long)&rx_fndb_ram[rxf->rxf_id].rit_hds_mcastq;
+ writel((rxf->rit_segment->rit_offset << 16) |
+ (rxf->forced_offset << 8) |
+ (rxf->hds_cfg.hdr_type & BNA_HDS_FORCED) | rxf->mcast_rxq_id,
+ base_addr + off);
+
+ /*
+ * default vlan tag, default function enable, strip vlan bytes,
+ * HDS type, header size
+ */
+
+ off = (unsigned long)&rx_fndb_ram[rxf->rxf_id].control_flags;
+ writel(((u32)rxf->default_vlan_tag << 16) |
+ (rxf->ctrl_flags &
+ (BNA_RXF_CF_DEFAULT_VLAN |
+ BNA_RXF_CF_DEFAULT_FUNCTION_ENABLE |
+ BNA_RXF_CF_VLAN_STRIP)) |
+ (rxf->hds_cfg.hdr_type & ~BNA_HDS_FORCED) |
+ rxf->hds_cfg.header_size,
+ base_addr + off);
+}
+
+void
+__rxf_vlan_filter_set(struct bna_rxf *rxf, enum bna_status status)
+{
+ struct bna *bna = rxf->rx->bna;
+ int i;
+
+ writel(BNA_GET_PAGE_NUM(LUT0_MEM_BLK_BASE_PG_NUM +
+ (bna->port_num * 2), VLAN_RAM_BASE_OFFSET),
+ bna->regs.page_addr);
+
+ if (status == BNA_STATUS_T_ENABLED) {
+ /* enable VLAN filtering on this function */
+ for (i = 0; i <= BFI_MAX_VLAN / 32; i++) {
+ writel(rxf->vlan_filter_table[i],
+ BNA_GET_VLAN_MEM_ENTRY_ADDR
+ (bna->pcidev.pci_bar_kva, rxf->rxf_id,
+ i * 32));
+ }
+ } else {
+ /* disable VLAN filtering on this function */
+ for (i = 0; i <= BFI_MAX_VLAN / 32; i++) {
+ writel(0xffffffff,
+ BNA_GET_VLAN_MEM_ENTRY_ADDR
+ (bna->pcidev.pci_bar_kva, rxf->rxf_id,
+ i * 32));
+ }
+ }
+}
+
+static void
+__rxf_rit_set(struct bna_rxf *rxf)
+{
+ struct bna *bna = rxf->rx->bna;
+ struct bna_rit_mem *rit_mem;
+ int i;
+ void __iomem *base_addr;
+ unsigned long off;
+
+ base_addr = BNA_GET_MEM_BASE_ADDR(bna->pcidev.pci_bar_kva,
+ FUNCTION_TO_RXQ_TRANSLATE);
+
+ rit_mem = (struct bna_rit_mem *)0;
+
+ writel(BNA_GET_PAGE_NUM(RXA0_MEM_BLK_BASE_PG_NUM + bna->port_num,
+ FUNCTION_TO_RXQ_TRANSLATE),
+ bna->regs.page_addr);
+
+ for (i = 0; i < rxf->rit_segment->rit_size; i++) {
+ off = (unsigned long)&rit_mem[i + rxf->rit_segment->rit_offset];
+ writel(rxf->rit_segment->rit[i].large_rxq_id << 6 |
+ rxf->rit_segment->rit[i].small_rxq_id,
+ base_addr + off);
+ }
+}
+
+static void
+__bna_rxf_stat_clr(struct bna_rxf *rxf)
+{
+ struct bfi_ll_stats_req ll_req;
+ u32 bm[2] = {0, 0};
+
+ if (rxf->rxf_id < 32)
+ bm[0] = 1 << rxf->rxf_id;
+ else
+ bm[1] = 1 << (rxf->rxf_id - 32);
+
+ bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_STATS_CLEAR_REQ, 0);
+ ll_req.stats_mask = 0;
+ ll_req.txf_id_mask[0] = 0;
+ ll_req.txf_id_mask[1] = 0;
+
+ ll_req.rxf_id_mask[0] = htonl(bm[0]);
+ ll_req.rxf_id_mask[1] = htonl(bm[1]);
+
+ bna_mbox_qe_fill(&rxf->mbox_qe, &ll_req, sizeof(ll_req),
+ bna_rxf_cb_stats_cleared, rxf);
+ bna_mbox_send(rxf->rx->bna, &rxf->mbox_qe);
+}
+
+static void
+rxf_enable(struct bna_rxf *rxf)
+{
+ if (rxf->rxf_oper_state == BNA_RXF_OPER_STATE_PAUSED)
+ bfa_fsm_send_event(rxf, RXF_E_STARTED);
+ else {
+ rxf->rxf_flags |= BNA_RXF_FL_RXF_ENABLED;
+ __rxf_enable(rxf);
+ }
+}
+
+static void
+rxf_cb_enabled(void *arg, int status)
+{
+ struct bna_rxf *rxf = (struct bna_rxf *)arg;
+
+ bfa_q_qe_init(&rxf->mbox_qe.qe);
+ bfa_fsm_send_event(rxf, RXF_E_STARTED);
+}
+
+static void
+rxf_disable(struct bna_rxf *rxf)
+{
+ if (rxf->rxf_oper_state == BNA_RXF_OPER_STATE_PAUSED)
+ bfa_fsm_send_event(rxf, RXF_E_STOPPED);
+ else
+ rxf->rxf_flags &= ~BNA_RXF_FL_RXF_ENABLED;
+ __rxf_disable(rxf);
+}
+
+static void
+rxf_cb_disabled(void *arg, int status)
+{
+ struct bna_rxf *rxf = (struct bna_rxf *)arg;
+
+ bfa_q_qe_init(&rxf->mbox_qe.qe);
+ bfa_fsm_send_event(rxf, RXF_E_STOPPED);
+}
+
+void
+rxf_cb_cam_fltr_mbox_cmd(void *arg, int status)
+{
+ struct bna_rxf *rxf = (struct bna_rxf *)arg;
+
+ bfa_q_qe_init(&rxf->mbox_qe.qe);
+
+ bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_RESP);
+}
+
+static void
+bna_rxf_cb_stats_cleared(void *arg, int status)
+{
+ struct bna_rxf *rxf = (struct bna_rxf *)arg;
+
+ bfa_q_qe_init(&rxf->mbox_qe.qe);
+ bfa_fsm_send_event(rxf, RXF_E_STAT_CLEARED);
+}
+
+void
+rxf_cam_mbox_cmd(struct bna_rxf *rxf, u8 cmd,
+ const struct bna_mac *mac_addr)
+{
+ struct bfi_ll_mac_addr_req req;
+
+ bfi_h2i_set(req.mh, BFI_MC_LL, cmd, 0);
+
+ req.rxf_id = rxf->rxf_id;
+ memcpy(&req.mac_addr, (void *)&mac_addr->addr, ETH_ALEN);
+
+ bna_mbox_qe_fill(&rxf->mbox_qe, &req, sizeof(req),
+ rxf_cb_cam_fltr_mbox_cmd, rxf);
+
+ bna_mbox_send(rxf->rx->bna, &rxf->mbox_qe);
+}
+
+static int
+rxf_process_packet_filter_mcast(struct bna_rxf *rxf)
+{
+ struct bna_mac *mac = NULL;
+ struct list_head *qe;
+
+ /* Add multicast entries */
+ if (!list_empty(&rxf->mcast_pending_add_q)) {
+ bfa_q_deq(&rxf->mcast_pending_add_q, &qe);
+ bfa_q_qe_init(qe);
+ mac = (struct bna_mac *)qe;
+ rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_ADD_REQ, mac);
+ list_add_tail(&mac->qe, &rxf->mcast_active_q);
+ return 1;
+ }
+
+ /* Delete multicast entries previousely added */
+ if (!list_empty(&rxf->mcast_pending_del_q)) {
+ bfa_q_deq(&rxf->mcast_pending_del_q, &qe);
+ bfa_q_qe_init(qe);
+ mac = (struct bna_mac *)qe;
+ rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_DEL_REQ, mac);
+ bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int
+rxf_process_packet_filter_vlan(struct bna_rxf *rxf)
+{
+ /* Apply the VLAN filter */
+ if (rxf->rxf_flags & BNA_RXF_FL_VLAN_CONFIG_PENDING) {
+ rxf->rxf_flags &= ~BNA_RXF_FL_VLAN_CONFIG_PENDING;
+ if (!(rxf->rxmode_active & BNA_RXMODE_PROMISC) &&
+ !(rxf->rxmode_active & BNA_RXMODE_DEFAULT))
+ __rxf_vlan_filter_set(rxf, rxf->vlan_filter_status);
+ }
+
+ /* Apply RSS configuration */
+ if (rxf->rxf_flags & BNA_RXF_FL_RSS_CONFIG_PENDING) {
+ rxf->rxf_flags &= ~BNA_RXF_FL_RSS_CONFIG_PENDING;
+ if (rxf->rss_status == BNA_STATUS_T_DISABLED) {
+ /* RSS is being disabled */
+ rxf->ctrl_flags &= ~BNA_RXF_CF_RSS_ENABLE;
+ __rxf_rit_set(rxf);
+ __rxf_config_set(rxf);
+ } else {
+ /* RSS is being enabled or reconfigured */
+ rxf->ctrl_flags |= BNA_RXF_CF_RSS_ENABLE;
+ __rxf_rit_set(rxf);
+ __rxf_config_set(rxf);
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Processes pending ucast, mcast entry addition/deletion and issues mailbox
+ * command. Also processes pending filter configuration - promiscuous mode,
+ * default mode, allmutli mode and issues mailbox command or directly applies
+ * to h/w
+ */
+static int
+rxf_process_packet_filter(struct bna_rxf *rxf)
+{
+ /* Set the default MAC first */
+ if (rxf->ucast_pending_set > 0) {
+ rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_UCAST_SET_REQ,
+ rxf->ucast_active_mac);
+ rxf->ucast_pending_set--;
+ return 1;
+ }
+
+ if (rxf_process_packet_filter_ucast(rxf))
+ return 1;
+
+ if (rxf_process_packet_filter_mcast(rxf))
+ return 1;
+
+ if (rxf_process_packet_filter_promisc(rxf))
+ return 1;
+
+ if (rxf_process_packet_filter_default(rxf))
+ return 1;
+
+ if (rxf_process_packet_filter_allmulti(rxf))
+ return 1;
+
+ if (rxf_process_packet_filter_vlan(rxf))
+ return 1;
+
+ return 0;
+}
+
+static int
+rxf_clear_packet_filter_mcast(struct bna_rxf *rxf)
+{
+ struct bna_mac *mac = NULL;
+ struct list_head *qe;
+
+ /* 3. delete pending mcast entries */
+ if (!list_empty(&rxf->mcast_pending_del_q)) {
+ bfa_q_deq(&rxf->mcast_pending_del_q, &qe);
+ bfa_q_qe_init(qe);
+ mac = (struct bna_mac *)qe;
+ rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_DEL_REQ, mac);
+ bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
+ return 1;
+ }
+
+ /* 4. clear active mcast entries; move them to pending_add_q */
+ if (!list_empty(&rxf->mcast_active_q)) {
+ bfa_q_deq(&rxf->mcast_active_q, &qe);
+ bfa_q_qe_init(qe);
+ mac = (struct bna_mac *)qe;
+ rxf_cam_mbox_cmd(rxf, BFI_LL_H2I_MAC_MCAST_DEL_REQ, mac);
+ list_add_tail(&mac->qe, &rxf->mcast_pending_add_q);
+ return 1;
+ }
+
+ return 0;
+}
+
+/**
+ * In the rxf stop path, processes pending ucast/mcast delete queue and issues
+ * the mailbox command. Moves the active ucast/mcast entries to pending add q,
+ * so that they are added to CAM again in the rxf start path. Moves the current
+ * filter settings - promiscuous, default, allmutli - to pending filter
+ * configuration
+ */
+static int
+rxf_clear_packet_filter(struct bna_rxf *rxf)
+{
+ if (rxf_clear_packet_filter_ucast(rxf))
+ return 1;
+
+ if (rxf_clear_packet_filter_mcast(rxf))
+ return 1;
+
+ /* 5. clear active default MAC in the CAM */
+ if (rxf->ucast_pending_set > 0)
+ rxf->ucast_pending_set = 0;
+
+ if (rxf_clear_packet_filter_promisc(rxf))
+ return 1;
+
+ if (rxf_clear_packet_filter_default(rxf))
+ return 1;
+
+ if (rxf_clear_packet_filter_allmulti(rxf))
+ return 1;
+
+ return 0;
+}
+
+static void
+rxf_reset_packet_filter_mcast(struct bna_rxf *rxf)
+{
+ struct list_head *qe;
+ struct bna_mac *mac;
+
+ /* 3. Move active mcast entries to pending_add_q */
+ while (!list_empty(&rxf->mcast_active_q)) {
+ bfa_q_deq(&rxf->mcast_active_q, &qe);
+ bfa_q_qe_init(qe);
+ list_add_tail(qe, &rxf->mcast_pending_add_q);
+ }
+
+ /* 4. Throw away delete pending mcast entries */
+ while (!list_empty(&rxf->mcast_pending_del_q)) {
+ bfa_q_deq(&rxf->mcast_pending_del_q, &qe);
+ bfa_q_qe_init(qe);
+ mac = (struct bna_mac *)qe;
+ bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
+ }
+}
+
+/**
+ * In the rxf fail path, throws away the ucast/mcast entries pending for
+ * deletion, moves all active ucast/mcast entries to pending queue so that
+ * they are added back to CAM in the rxf start path. Also moves the current
+ * filter configuration to pending filter configuration.
+ */
+static void
+rxf_reset_packet_filter(struct bna_rxf *rxf)
+{
+ rxf_reset_packet_filter_ucast(rxf);
+
+ rxf_reset_packet_filter_mcast(rxf);
+
+ /* 5. Turn off ucast set flag */
+ rxf->ucast_pending_set = 0;
+
+ rxf_reset_packet_filter_promisc(rxf);
+
+ rxf_reset_packet_filter_default(rxf);
+
+ rxf_reset_packet_filter_allmulti(rxf);
+}
+
+static void
+bna_rxf_init(struct bna_rxf *rxf,
+ struct bna_rx *rx,
+ struct bna_rx_config *q_config)
+{
+ struct list_head *qe;
+ struct bna_rxp *rxp;
+
+ /* rxf_id is initialized during rx_mod init */
+ rxf->rx = rx;
+
+ INIT_LIST_HEAD(&rxf->ucast_pending_add_q);
+ INIT_LIST_HEAD(&rxf->ucast_pending_del_q);
+ rxf->ucast_pending_set = 0;
+ INIT_LIST_HEAD(&rxf->ucast_active_q);
+ rxf->ucast_active_mac = NULL;
+
+ INIT_LIST_HEAD(&rxf->mcast_pending_add_q);
+ INIT_LIST_HEAD(&rxf->mcast_pending_del_q);
+ INIT_LIST_HEAD(&rxf->mcast_active_q);
+
+ bfa_q_qe_init(&rxf->mbox_qe.qe);
+
+ if (q_config->vlan_strip_status == BNA_STATUS_T_ENABLED)
+ rxf->ctrl_flags |= BNA_RXF_CF_VLAN_STRIP;
+
+ rxf->rxf_oper_state = (q_config->paused) ?
+ BNA_RXF_OPER_STATE_PAUSED : BNA_RXF_OPER_STATE_RUNNING;
+
+ bna_rxf_adv_init(rxf, rx, q_config);
+
+ rxf->rit_segment = bna_rit_mod_seg_get(&rxf->rx->bna->rit_mod,
+ q_config->num_paths);
+
+ list_for_each(qe, &rx->rxp_q) {
+ rxp = (struct bna_rxp *)qe;
+ if (q_config->rxp_type == BNA_RXP_SINGLE)
+ rxf->mcast_rxq_id = rxp->rxq.single.only->rxq_id;
+ else
+ rxf->mcast_rxq_id = rxp->rxq.slr.large->rxq_id;
+ break;
+ }
+
+ rxf->vlan_filter_status = BNA_STATUS_T_DISABLED;
+ memset(rxf->vlan_filter_table, 0,
+ (sizeof(u32) * ((BFI_MAX_VLAN + 1) / 32)));
+
+ bfa_fsm_set_state(rxf, bna_rxf_sm_stopped);
+}
+
+static void
+bna_rxf_uninit(struct bna_rxf *rxf)
+{
+ struct bna_mac *mac;
+
+ bna_rit_mod_seg_put(&rxf->rx->bna->rit_mod, rxf->rit_segment);
+ rxf->rit_segment = NULL;
+
+ rxf->ucast_pending_set = 0;
+
+ while (!list_empty(&rxf->ucast_pending_add_q)) {
+ bfa_q_deq(&rxf->ucast_pending_add_q, &mac);
+ bfa_q_qe_init(&mac->qe);
+ bna_ucam_mod_mac_put(&rxf->rx->bna->ucam_mod, mac);
+ }
+
+ if (rxf->ucast_active_mac) {
+ bfa_q_qe_init(&rxf->ucast_active_mac->qe);
+ bna_ucam_mod_mac_put(&rxf->rx->bna->ucam_mod,
+ rxf->ucast_active_mac);
+ rxf->ucast_active_mac = NULL;
+ }
+
+ while (!list_empty(&rxf->mcast_pending_add_q)) {
+ bfa_q_deq(&rxf->mcast_pending_add_q, &mac);
+ bfa_q_qe_init(&mac->qe);
+ bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
+ }
+
+ rxf->rx = NULL;
+}
+
+static void
+bna_rx_cb_rxf_started(struct bna_rx *rx, enum bna_cb_status status)
+{
+ bfa_fsm_send_event(rx, RX_E_RXF_STARTED);
+ if (rx->rxf.rxf_id < 32)
+ rx->bna->rx_mod.rxf_bmap[0] |= ((u32)1 << rx->rxf.rxf_id);
+ else
+ rx->bna->rx_mod.rxf_bmap[1] |= ((u32)
+ 1 << (rx->rxf.rxf_id - 32));
+}
+
+static void
+bna_rxf_start(struct bna_rxf *rxf)
+{
+ rxf->start_cbfn = bna_rx_cb_rxf_started;
+ rxf->start_cbarg = rxf->rx;
+ rxf->rxf_flags &= ~BNA_RXF_FL_FAILED;
+ bfa_fsm_send_event(rxf, RXF_E_START);
+}
+
+static void
+bna_rx_cb_rxf_stopped(struct bna_rx *rx, enum bna_cb_status status)
+{
+ bfa_fsm_send_event(rx, RX_E_RXF_STOPPED);
+ if (rx->rxf.rxf_id < 32)
+ rx->bna->rx_mod.rxf_bmap[0] &= ~(u32)1 << rx->rxf.rxf_id;
+ else
+ rx->bna->rx_mod.rxf_bmap[1] &= ~(u32)
+ 1 << (rx->rxf.rxf_id - 32);
+}
+
+static void
+bna_rxf_stop(struct bna_rxf *rxf)
+{
+ rxf->stop_cbfn = bna_rx_cb_rxf_stopped;
+ rxf->stop_cbarg = rxf->rx;
+ bfa_fsm_send_event(rxf, RXF_E_STOP);
+}
+
+static void
+bna_rxf_fail(struct bna_rxf *rxf)
+{
+ rxf->rxf_flags |= BNA_RXF_FL_FAILED;
+ bfa_fsm_send_event(rxf, RXF_E_FAIL);
+}
+
+int
+bna_rxf_state_get(struct bna_rxf *rxf)
+{
+ return bfa_sm_to_state(rxf_sm_table, rxf->fsm);
+}
+
+enum bna_cb_status
+bna_rx_ucast_set(struct bna_rx *rx, u8 *ucmac,
+ void (*cbfn)(struct bnad *, struct bna_rx *,
+ enum bna_cb_status))
+{
+ struct bna_rxf *rxf = &rx->rxf;
+
+ if (rxf->ucast_active_mac == NULL) {
+ rxf->ucast_active_mac =
+ bna_ucam_mod_mac_get(&rxf->rx->bna->ucam_mod);
+ if (rxf->ucast_active_mac == NULL)
+ return BNA_CB_UCAST_CAM_FULL;
+ bfa_q_qe_init(&rxf->ucast_active_mac->qe);
+ }
+
+ memcpy(rxf->ucast_active_mac->addr, ucmac, ETH_ALEN);
+ rxf->ucast_pending_set++;
+ rxf->cam_fltr_cbfn = cbfn;
+ rxf->cam_fltr_cbarg = rx->bna->bnad;
+
+ bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD);
+
+ return BNA_CB_SUCCESS;
+}
+
+enum bna_cb_status
+bna_rx_mcast_add(struct bna_rx *rx, u8 *addr,
+ void (*cbfn)(struct bnad *, struct bna_rx *,
+ enum bna_cb_status))
+{
+ struct bna_rxf *rxf = &rx->rxf;
+ struct list_head *qe;
+ struct bna_mac *mac;
+
+ /* Check if already added */
+ list_for_each(qe, &rxf->mcast_active_q) {
+ mac = (struct bna_mac *)qe;
+ if (BNA_MAC_IS_EQUAL(mac->addr, addr)) {
+ if (cbfn)
+ (*cbfn)(rx->bna->bnad, rx, BNA_CB_SUCCESS);
+ return BNA_CB_SUCCESS;
+ }
+ }
+
+ /* Check if pending addition */
+ list_for_each(qe, &rxf->mcast_pending_add_q) {
+ mac = (struct bna_mac *)qe;
+ if (BNA_MAC_IS_EQUAL(mac->addr, addr)) {
+ if (cbfn)
+ (*cbfn)(rx->bna->bnad, rx, BNA_CB_SUCCESS);
+ return BNA_CB_SUCCESS;
+ }
+ }
+
+ mac = bna_mcam_mod_mac_get(&rxf->rx->bna->mcam_mod);
+ if (mac == NULL)
+ return BNA_CB_MCAST_LIST_FULL;
+ bfa_q_qe_init(&mac->qe);
+ memcpy(mac->addr, addr, ETH_ALEN);
+ list_add_tail(&mac->qe, &rxf->mcast_pending_add_q);
+
+ rxf->cam_fltr_cbfn = cbfn;
+ rxf->cam_fltr_cbarg = rx->bna->bnad;
+
+ bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD);
+
+ return BNA_CB_SUCCESS;
+}
+
+enum bna_cb_status
+bna_rx_mcast_listset(struct bna_rx *rx, int count, u8 *mclist,
+ void (*cbfn)(struct bnad *, struct bna_rx *,
+ enum bna_cb_status))
+{
+ struct bna_rxf *rxf = &rx->rxf;
+ struct list_head list_head;
+ struct list_head *qe;
+ u8 *mcaddr;
+ struct bna_mac *mac;
+ struct bna_mac *mac1;
+ int skip;
+ int delete;
+ int need_hw_config = 0;
+ int i;
+
+ /* Allocate nodes */
+ INIT_LIST_HEAD(&list_head);
+ for (i = 0, mcaddr = mclist; i < count; i++) {
+ mac = bna_mcam_mod_mac_get(&rxf->rx->bna->mcam_mod);
+ if (mac == NULL)
+ goto err_return;
+ bfa_q_qe_init(&mac->qe);
+ memcpy(mac->addr, mcaddr, ETH_ALEN);
+ list_add_tail(&mac->qe, &list_head);
+
+ mcaddr += ETH_ALEN;
+ }
+
+ /* Schedule for addition */
+ while (!list_empty(&list_head)) {
+ bfa_q_deq(&list_head, &qe);
+ mac = (struct bna_mac *)qe;
+ bfa_q_qe_init(&mac->qe);
+
+ skip = 0;
+
+ /* Skip if already added */
+ list_for_each(qe, &rxf->mcast_active_q) {
+ mac1 = (struct bna_mac *)qe;
+ if (BNA_MAC_IS_EQUAL(mac1->addr, mac->addr)) {
+ bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod,
+ mac);
+ skip = 1;
+ break;
+ }
+ }
+
+ if (skip)
+ continue;
+
+ /* Skip if pending addition */
+ list_for_each(qe, &rxf->mcast_pending_add_q) {
+ mac1 = (struct bna_mac *)qe;
+ if (BNA_MAC_IS_EQUAL(mac1->addr, mac->addr)) {
+ bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod,
+ mac);
+ skip = 1;
+ break;
+ }
+ }
+
+ if (skip)
+ continue;
+
+ need_hw_config = 1;
+ list_add_tail(&mac->qe, &rxf->mcast_pending_add_q);
+ }
+
+ /**
+ * Delete the entries that are in the pending_add_q but not
+ * in the new list
+ */
+ while (!list_empty(&rxf->mcast_pending_add_q)) {
+ bfa_q_deq(&rxf->mcast_pending_add_q, &qe);
+ mac = (struct bna_mac *)qe;
+ bfa_q_qe_init(&mac->qe);
+ for (i = 0, mcaddr = mclist, delete = 1; i < count; i++) {
+ if (BNA_MAC_IS_EQUAL(mcaddr, mac->addr)) {
+ delete = 0;
+ break;
+ }
+ mcaddr += ETH_ALEN;
+ }
+ if (delete)
+ bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
+ else
+ list_add_tail(&mac->qe, &list_head);
+ }
+ while (!list_empty(&list_head)) {
+ bfa_q_deq(&list_head, &qe);
+ mac = (struct bna_mac *)qe;
+ bfa_q_qe_init(&mac->qe);
+ list_add_tail(&mac->qe, &rxf->mcast_pending_add_q);
+ }
+
+ /**
+ * Schedule entries for deletion that are in the active_q but not
+ * in the new list
+ */
+ while (!list_empty(&rxf->mcast_active_q)) {
+ bfa_q_deq(&rxf->mcast_active_q, &qe);
+ mac = (struct bna_mac *)qe;
+ bfa_q_qe_init(&mac->qe);
+ for (i = 0, mcaddr = mclist, delete = 1; i < count; i++) {
+ if (BNA_MAC_IS_EQUAL(mcaddr, mac->addr)) {
+ delete = 0;
+ break;
+ }
+ mcaddr += ETH_ALEN;
+ }
+ if (delete) {
+ list_add_tail(&mac->qe, &rxf->mcast_pending_del_q);
+ need_hw_config = 1;
+ } else {
+ list_add_tail(&mac->qe, &list_head);
+ }
+ }
+ while (!list_empty(&list_head)) {
+ bfa_q_deq(&list_head, &qe);
+ mac = (struct bna_mac *)qe;
+ bfa_q_qe_init(&mac->qe);
+ list_add_tail(&mac->qe, &rxf->mcast_active_q);
+ }
+
+ if (need_hw_config) {
+ rxf->cam_fltr_cbfn = cbfn;
+ rxf->cam_fltr_cbarg = rx->bna->bnad;
+ bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD);
+ } else if (cbfn)
+ (*cbfn)(rx->bna->bnad, rx, BNA_CB_SUCCESS);
+
+ return BNA_CB_SUCCESS;
+
+err_return:
+ while (!list_empty(&list_head)) {
+ bfa_q_deq(&list_head, &qe);
+ mac = (struct bna_mac *)qe;
+ bfa_q_qe_init(&mac->qe);
+ bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
+ }
+
+ return BNA_CB_MCAST_LIST_FULL;
+}
+
+void
+bna_rx_vlan_add(struct bna_rx *rx, int vlan_id)
+{
+ struct bna_rxf *rxf = &rx->rxf;
+ int index = (vlan_id >> 5);
+ int bit = (1 << (vlan_id & 0x1F));
+
+ rxf->vlan_filter_table[index] |= bit;
+ if (rxf->vlan_filter_status == BNA_STATUS_T_ENABLED) {
+ rxf->rxf_flags |= BNA_RXF_FL_VLAN_CONFIG_PENDING;
+ bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD);
+ }
+}
+
+void
+bna_rx_vlan_del(struct bna_rx *rx, int vlan_id)
+{
+ struct bna_rxf *rxf = &rx->rxf;
+ int index = (vlan_id >> 5);
+ int bit = (1 << (vlan_id & 0x1F));
+
+ rxf->vlan_filter_table[index] &= ~bit;
+ if (rxf->vlan_filter_status == BNA_STATUS_T_ENABLED) {
+ rxf->rxf_flags |= BNA_RXF_FL_VLAN_CONFIG_PENDING;
+ bfa_fsm_send_event(rxf, RXF_E_CAM_FLTR_MOD);
+ }
+}
+
+/**
+ * RX
+ */
+#define RXQ_RCB_INIT(q, rxp, qdepth, bna, _id, unmapq_mem) do { \
+ struct bna_doorbell_qset *_qset; \
+ unsigned long off; \
+ (q)->rcb->producer_index = (q)->rcb->consumer_index = 0; \
+ (q)->rcb->q_depth = (qdepth); \
+ (q)->rcb->unmap_q = unmapq_mem; \
+ (q)->rcb->rxq = (q); \
+ (q)->rcb->cq = &(rxp)->cq; \
+ (q)->rcb->bnad = (bna)->bnad; \
+ _qset = (struct bna_doorbell_qset *)0; \
+ off = (unsigned long)&_qset[(q)->rxq_id].rxq[0]; \
+ (q)->rcb->q_dbell = off + \
+ BNA_GET_DOORBELL_BASE_ADDR((bna)->pcidev.pci_bar_kva); \
+ (q)->rcb->id = _id; \
+} while (0)
+
+#define BNA_GET_RXQS(qcfg) (((qcfg)->rxp_type == BNA_RXP_SINGLE) ? \
+ (qcfg)->num_paths : ((qcfg)->num_paths * 2))
+
+#define SIZE_TO_PAGES(size) (((size) >> PAGE_SHIFT) + ((((size) &\
+ (PAGE_SIZE - 1)) + (PAGE_SIZE - 1)) >> PAGE_SHIFT))
+
+#define call_rx_stop_callback(rx, status) \
+ if ((rx)->stop_cbfn) { \
+ (*(rx)->stop_cbfn)((rx)->stop_cbarg, rx, (status)); \
+ (rx)->stop_cbfn = NULL; \
+ (rx)->stop_cbarg = NULL; \
+ }
+
+/*
+ * Since rx_enable is synchronous callback, there is no start_cbfn required.
+ * Instead, we'll call bnad_rx_post(rxp) so that bnad can post the buffers
+ * for each rxpath.
+ */
+
+#define call_rx_disable_cbfn(rx, status) \
+ if ((rx)->disable_cbfn) { \
+ (*(rx)->disable_cbfn)((rx)->disable_cbarg, \
+ status); \
+ (rx)->disable_cbfn = NULL; \
+ (rx)->disable_cbarg = NULL; \
+ } \
+
+#define rxqs_reqd(type, num_rxqs) \
+ (((type) == BNA_RXP_SINGLE) ? (num_rxqs) : ((num_rxqs) * 2))
+
+#define rx_ib_fail(rx) \
+do { \
+ struct bna_rxp *rxp; \
+ struct list_head *qe; \
+ list_for_each(qe, &(rx)->rxp_q) { \
+ rxp = (struct bna_rxp *)qe; \
+ bna_ib_fail(rxp->cq.ib); \
+ } \
+} while (0)
+
+static void __bna_multi_rxq_stop(struct bna_rxp *, u32 *);
+static void __bna_rxq_start(struct bna_rxq *rxq);
+static void __bna_cq_start(struct bna_cq *cq);
+static void bna_rit_create(struct bna_rx *rx);
+static void bna_rx_cb_multi_rxq_stopped(void *arg, int status);
+static void bna_rx_cb_rxq_stopped_all(void *arg);
+
+bfa_fsm_state_decl(bna_rx, stopped,
+ struct bna_rx, enum bna_rx_event);
+bfa_fsm_state_decl(bna_rx, rxf_start_wait,
+ struct bna_rx, enum bna_rx_event);
+bfa_fsm_state_decl(bna_rx, started,
+ struct bna_rx, enum bna_rx_event);
+bfa_fsm_state_decl(bna_rx, rxf_stop_wait,
+ struct bna_rx, enum bna_rx_event);
+bfa_fsm_state_decl(bna_rx, rxq_stop_wait,
+ struct bna_rx, enum bna_rx_event);
+
+static const struct bfa_sm_table rx_sm_table[] = {
+ {BFA_SM(bna_rx_sm_stopped), BNA_RX_STOPPED},
+ {BFA_SM(bna_rx_sm_rxf_start_wait), BNA_RX_RXF_START_WAIT},
+ {BFA_SM(bna_rx_sm_started), BNA_RX_STARTED},
+ {BFA_SM(bna_rx_sm_rxf_stop_wait), BNA_RX_RXF_STOP_WAIT},
+ {BFA_SM(bna_rx_sm_rxq_stop_wait), BNA_RX_RXQ_STOP_WAIT},
+};
+
+static void bna_rx_sm_stopped_entry(struct bna_rx *rx)
+{
+ struct bna_rxp *rxp;
+ struct list_head *qe_rxp;
+
+ list_for_each(qe_rxp, &rx->rxp_q) {
+ rxp = (struct bna_rxp *)qe_rxp;
+ rx->rx_cleanup_cbfn(rx->bna->bnad, rxp->cq.ccb);
+ }
+
+ call_rx_stop_callback(rx, BNA_CB_SUCCESS);
+}
+
+static void bna_rx_sm_stopped(struct bna_rx *rx,
+ enum bna_rx_event event)
+{
+ switch (event) {
+ case RX_E_START:
+ bfa_fsm_set_state(rx, bna_rx_sm_rxf_start_wait);
+ break;
+ case RX_E_STOP:
+ call_rx_stop_callback(rx, BNA_CB_SUCCESS);
+ break;
+ case RX_E_FAIL:
+ /* no-op */
+ break;
+ default:
+ bfa_sm_fault(rx->bna, event);
+ break;
+ }
+
+}
+
+static void bna_rx_sm_rxf_start_wait_entry(struct bna_rx *rx)
+{
+ struct bna_rxp *rxp;
+ struct list_head *qe_rxp;
+ struct bna_rxq *q0 = NULL, *q1 = NULL;
+
+ /* Setup the RIT */
+ bna_rit_create(rx);
+
+ list_for_each(qe_rxp, &rx->rxp_q) {
+ rxp = (struct bna_rxp *)qe_rxp;
+ bna_ib_start(rxp->cq.ib);
+ GET_RXQS(rxp, q0, q1);
+ q0->buffer_size = bna_port_mtu_get(&rx->bna->port);
+ __bna_rxq_start(q0);
+ rx->rx_post_cbfn(rx->bna->bnad, q0->rcb);
+ if (q1) {
+ __bna_rxq_start(q1);
+ rx->rx_post_cbfn(rx->bna->bnad, q1->rcb);
+ }
+ __bna_cq_start(&rxp->cq);
+ }
+
+ bna_rxf_start(&rx->rxf);
+}
+
+static void bna_rx_sm_rxf_start_wait(struct bna_rx *rx,
+ enum bna_rx_event event)
+{
+ switch (event) {
+ case RX_E_STOP:
+ bfa_fsm_set_state(rx, bna_rx_sm_rxf_stop_wait);
+ break;
+ case RX_E_FAIL:
+ bfa_fsm_set_state(rx, bna_rx_sm_stopped);
+ rx_ib_fail(rx);
+ bna_rxf_fail(&rx->rxf);
+ break;
+ case RX_E_RXF_STARTED:
+ bfa_fsm_set_state(rx, bna_rx_sm_started);
+ break;
+ default:
+ bfa_sm_fault(rx->bna, event);
+ break;
+ }
+}
+
+void
+bna_rx_sm_started_entry(struct bna_rx *rx)
+{
+ struct bna_rxp *rxp;
+ struct list_head *qe_rxp;
+
+ /* Start IB */
+ list_for_each(qe_rxp, &rx->rxp_q) {
+ rxp = (struct bna_rxp *)qe_rxp;
+ bna_ib_ack(&rxp->cq.ib->door_bell, 0);
+ }
+
+ bna_llport_admin_up(&rx->bna->port.llport);
+}
+
+void
+bna_rx_sm_started(struct bna_rx *rx, enum bna_rx_event event)
+{
+ switch (event) {
+ case RX_E_FAIL:
+ bna_llport_admin_down(&rx->bna->port.llport);
+ bfa_fsm_set_state(rx, bna_rx_sm_stopped);
+ rx_ib_fail(rx);
+ bna_rxf_fail(&rx->rxf);
+ break;
+ case RX_E_STOP:
+ bna_llport_admin_down(&rx->bna->port.llport);
+ bfa_fsm_set_state(rx, bna_rx_sm_rxf_stop_wait);
+ break;
+ default:
+ bfa_sm_fault(rx->bna, event);
+ break;
+ }
+}
+
+void
+bna_rx_sm_rxf_stop_wait_entry(struct bna_rx *rx)
+{
+ bna_rxf_stop(&rx->rxf);
+}
+
+void
+bna_rx_sm_rxf_stop_wait(struct bna_rx *rx, enum bna_rx_event event)
+{
+ switch (event) {
+ case RX_E_RXF_STOPPED:
+ bfa_fsm_set_state(rx, bna_rx_sm_rxq_stop_wait);
+ break;
+ case RX_E_RXF_STARTED:
+ /**
+ * RxF was in the process of starting up when
+ * RXF_E_STOP was issued. Ignore this event
+ */
+ break;
+ case RX_E_FAIL:
+ bfa_fsm_set_state(rx, bna_rx_sm_stopped);
+ rx_ib_fail(rx);
+ bna_rxf_fail(&rx->rxf);
+ break;
+ default:
+ bfa_sm_fault(rx->bna, event);
+ break;
+ }
+
+}
+
+void
+bna_rx_sm_rxq_stop_wait_entry(struct bna_rx *rx)
+{
+ struct bna_rxp *rxp = NULL;
+ struct bna_rxq *q0 = NULL;
+ struct bna_rxq *q1 = NULL;
+ struct list_head *qe;
+ u32 rxq_mask[2] = {0, 0};
+
+ /* Only one call to multi-rxq-stop for all RXPs in this RX */
+ bfa_wc_up(&rx->rxq_stop_wc);
+ list_for_each(qe, &rx->rxp_q) {
+ rxp = (struct bna_rxp *)qe;
+ GET_RXQS(rxp, q0, q1);
+ if (q0->rxq_id < 32)
+ rxq_mask[0] |= ((u32)1 << q0->rxq_id);
+ else
+ rxq_mask[1] |= ((u32)1 << (q0->rxq_id - 32));
+ if (q1) {
+ if (q1->rxq_id < 32)
+ rxq_mask[0] |= ((u32)1 << q1->rxq_id);
+ else
+ rxq_mask[1] |= ((u32)
+ 1 << (q1->rxq_id - 32));
+ }
+ }
+
+ __bna_multi_rxq_stop(rxp, rxq_mask);
+}
+
+void
+bna_rx_sm_rxq_stop_wait(struct bna_rx *rx, enum bna_rx_event event)
+{
+ struct bna_rxp *rxp = NULL;
+ struct list_head *qe;
+
+ switch (event) {
+ case RX_E_RXQ_STOPPED:
+ list_for_each(qe, &rx->rxp_q) {
+ rxp = (struct bna_rxp *)qe;
+ bna_ib_stop(rxp->cq.ib);
+ }
+ /* Fall through */
+ case RX_E_FAIL:
+ bfa_fsm_set_state(rx, bna_rx_sm_stopped);
+ break;
+ default:
+ bfa_sm_fault(rx->bna, event);
+ break;
+ }
+}
+
+void
+__bna_multi_rxq_stop(struct bna_rxp *rxp, u32 * rxq_id_mask)
+{
+ struct bfi_ll_q_stop_req ll_req;
+
+ bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_RXQ_STOP_REQ, 0);
+ ll_req.q_id_mask[0] = htonl(rxq_id_mask[0]);
+ ll_req.q_id_mask[1] = htonl(rxq_id_mask[1]);
+ bna_mbox_qe_fill(&rxp->mbox_qe, &ll_req, sizeof(ll_req),
+ bna_rx_cb_multi_rxq_stopped, rxp);
+ bna_mbox_send(rxp->rx->bna, &rxp->mbox_qe);
+}
+
+void
+__bna_rxq_start(struct bna_rxq *rxq)
+{
+ struct bna_rxtx_q_mem *q_mem;
+ struct bna_rxq_mem rxq_cfg, *rxq_mem;
+ struct bna_dma_addr cur_q_addr;
+ /* struct bna_doorbell_qset *qset; */
+ struct bna_qpt *qpt;
+ u32 pg_num;
+ struct bna *bna = rxq->rx->bna;
+ void __iomem *base_addr;
+ unsigned long off;
+
+ qpt = &rxq->qpt;
+ cur_q_addr = *((struct bna_dma_addr *)(qpt->kv_qpt_ptr));
+
+ rxq_cfg.pg_tbl_addr_lo = qpt->hw_qpt_ptr.lsb;
+ rxq_cfg.pg_tbl_addr_hi = qpt->hw_qpt_ptr.msb;
+ rxq_cfg.cur_q_entry_lo = cur_q_addr.lsb;
+ rxq_cfg.cur_q_entry_hi = cur_q_addr.msb;
+
+ rxq_cfg.pg_cnt_n_prd_ptr = ((u32)qpt->page_count << 16) | 0x0;
+ rxq_cfg.entry_n_pg_size = ((u32)(BFI_RXQ_WI_SIZE >> 2) << 16) |
+ (qpt->page_size >> 2);
+ rxq_cfg.sg_n_cq_n_cns_ptr =
+ ((u32)(rxq->rxp->cq.cq_id & 0xff) << 16) | 0x0;
+ rxq_cfg.buf_sz_n_q_state = ((u32)rxq->buffer_size << 16) |
+ BNA_Q_IDLE_STATE;
+ rxq_cfg.next_qid = 0x0 | (0x3 << 8);
+
+ /* Write the page number register */
+ pg_num = BNA_GET_PAGE_NUM(HQM0_BLK_PG_NUM + bna->port_num,
+ HQM_RXTX_Q_RAM_BASE_OFFSET);
+ writel(pg_num, bna->regs.page_addr);
+
+ /* Write to h/w */
+ base_addr = BNA_GET_MEM_BASE_ADDR(bna->pcidev.pci_bar_kva,
+ HQM_RXTX_Q_RAM_BASE_OFFSET);
+
+ q_mem = (struct bna_rxtx_q_mem *)0;
+ rxq_mem = &q_mem[rxq->rxq_id].rxq;
+
+ off = (unsigned long)&rxq_mem->pg_tbl_addr_lo;
+ writel(htonl(rxq_cfg.pg_tbl_addr_lo), base_addr + off);
+
+ off = (unsigned long)&rxq_mem->pg_tbl_addr_hi;
+ writel(htonl(rxq_cfg.pg_tbl_addr_hi), base_addr + off);
+
+ off = (unsigned long)&rxq_mem->cur_q_entry_lo;
+ writel(htonl(rxq_cfg.cur_q_entry_lo), base_addr + off);
+
+ off = (unsigned long)&rxq_mem->cur_q_entry_hi;
+ writel(htonl(rxq_cfg.cur_q_entry_hi), base_addr + off);
+
+ off = (unsigned long)&rxq_mem->pg_cnt_n_prd_ptr;
+ writel(rxq_cfg.pg_cnt_n_prd_ptr, base_addr + off);
+
+ off = (unsigned long)&rxq_mem->entry_n_pg_size;
+ writel(rxq_cfg.entry_n_pg_size, base_addr + off);
+
+ off = (unsigned long)&rxq_mem->sg_n_cq_n_cns_ptr;
+ writel(rxq_cfg.sg_n_cq_n_cns_ptr, base_addr + off);
+
+ off = (unsigned long)&rxq_mem->buf_sz_n_q_state;
+ writel(rxq_cfg.buf_sz_n_q_state, base_addr + off);
+
+ off = (unsigned long)&rxq_mem->next_qid;
+ writel(rxq_cfg.next_qid, base_addr + off);
+
+ rxq->rcb->producer_index = 0;
+ rxq->rcb->consumer_index = 0;
+}
+
+void
+__bna_cq_start(struct bna_cq *cq)
+{
+ struct bna_cq_mem cq_cfg, *cq_mem;
+ const struct bna_qpt *qpt;
+ struct bna_dma_addr cur_q_addr;
+ u32 pg_num;
+ struct bna *bna = cq->rx->bna;
+ void __iomem *base_addr;
+ unsigned long off;
+
+ qpt = &cq->qpt;
+ cur_q_addr = *((struct bna_dma_addr *)(qpt->kv_qpt_ptr));
+
+ /*
+ * Fill out structure, to be subsequently written
+ * to hardware
+ */
+ cq_cfg.pg_tbl_addr_lo = qpt->hw_qpt_ptr.lsb;
+ cq_cfg.pg_tbl_addr_hi = qpt->hw_qpt_ptr.msb;
+ cq_cfg.cur_q_entry_lo = cur_q_addr.lsb;
+ cq_cfg.cur_q_entry_hi = cur_q_addr.msb;
+
+ cq_cfg.pg_cnt_n_prd_ptr = (qpt->page_count << 16) | 0x0;
+ cq_cfg.entry_n_pg_size =
+ ((u32)(BFI_CQ_WI_SIZE >> 2) << 16) | (qpt->page_size >> 2);
+ cq_cfg.int_blk_n_cns_ptr = ((((u32)cq->ib_seg_offset) << 24) |
+ ((u32)(cq->ib->ib_id & 0xff) << 16) | 0x0);
+ cq_cfg.q_state = BNA_Q_IDLE_STATE;
+
+ /* Write the page number register */
+ pg_num = BNA_GET_PAGE_NUM(HQM0_BLK_PG_NUM + bna->port_num,
+ HQM_CQ_RAM_BASE_OFFSET);
+
+ writel(pg_num, bna->regs.page_addr);
+
+ /* H/W write */
+ base_addr = BNA_GET_MEM_BASE_ADDR(bna->pcidev.pci_bar_kva,
+ HQM_CQ_RAM_BASE_OFFSET);
+
+ cq_mem = (struct bna_cq_mem *)0;
+
+ off = (unsigned long)&cq_mem[cq->cq_id].pg_tbl_addr_lo;
+ writel(htonl(cq_cfg.pg_tbl_addr_lo), base_addr + off);
+
+ off = (unsigned long)&cq_mem[cq->cq_id].pg_tbl_addr_hi;
+ writel(htonl(cq_cfg.pg_tbl_addr_hi), base_addr + off);
+
+ off = (unsigned long)&cq_mem[cq->cq_id].cur_q_entry_lo;
+ writel(htonl(cq_cfg.cur_q_entry_lo), base_addr + off);
+
+ off = (unsigned long)&cq_mem[cq->cq_id].cur_q_entry_hi;
+ writel(htonl(cq_cfg.cur_q_entry_hi), base_addr + off);
+
+ off = (unsigned long)&cq_mem[cq->cq_id].pg_cnt_n_prd_ptr;
+ writel(cq_cfg.pg_cnt_n_prd_ptr, base_addr + off);
+
+ off = (unsigned long)&cq_mem[cq->cq_id].entry_n_pg_size;
+ writel(cq_cfg.entry_n_pg_size, base_addr + off);
+
+ off = (unsigned long)&cq_mem[cq->cq_id].int_blk_n_cns_ptr;
+ writel(cq_cfg.int_blk_n_cns_ptr, base_addr + off);
+
+ off = (unsigned long)&cq_mem[cq->cq_id].q_state;
+ writel(cq_cfg.q_state, base_addr + off);
+
+ cq->ccb->producer_index = 0;
+ *(cq->ccb->hw_producer_index) = 0;
+}
+
+void
+bna_rit_create(struct bna_rx *rx)
+{
+ struct list_head *qe_rxp;
+ struct bna *bna;
+ struct bna_rxp *rxp;
+ struct bna_rxq *q0 = NULL;
+ struct bna_rxq *q1 = NULL;
+ int offset;
+
+ bna = rx->bna;
+
+ offset = 0;
+ list_for_each(qe_rxp, &rx->rxp_q) {
+ rxp = (struct bna_rxp *)qe_rxp;
+ GET_RXQS(rxp, q0, q1);
+ rx->rxf.rit_segment->rit[offset].large_rxq_id = q0->rxq_id;
+ rx->rxf.rit_segment->rit[offset].small_rxq_id =
+ (q1 ? q1->rxq_id : 0);
+ offset++;
+ }
+}
+
+static int
+_rx_can_satisfy(struct bna_rx_mod *rx_mod,
+ struct bna_rx_config *rx_cfg)
+{
+ if ((rx_mod->rx_free_count == 0) ||
+ (rx_mod->rxp_free_count == 0) ||
+ (rx_mod->rxq_free_count == 0))
+ return 0;
+
+ if (rx_cfg->rxp_type == BNA_RXP_SINGLE) {
+ if ((rx_mod->rxp_free_count < rx_cfg->num_paths) ||
+ (rx_mod->rxq_free_count < rx_cfg->num_paths))
+ return 0;
+ } else {
+ if ((rx_mod->rxp_free_count < rx_cfg->num_paths) ||
+ (rx_mod->rxq_free_count < (2 * rx_cfg->num_paths)))
+ return 0;
+ }
+
+ if (!bna_rit_mod_can_satisfy(&rx_mod->bna->rit_mod, rx_cfg->num_paths))
+ return 0;
+
+ return 1;
+}
+
+static struct bna_rxq *
+_get_free_rxq(struct bna_rx_mod *rx_mod)
+{
+ struct bna_rxq *rxq = NULL;
+ struct list_head *qe = NULL;
+
+ bfa_q_deq(&rx_mod->rxq_free_q, &qe);
+ if (qe) {
+ rx_mod->rxq_free_count--;
+ rxq = (struct bna_rxq *)qe;
+ }
+ return rxq;
+}
+
+static void
+_put_free_rxq(struct bna_rx_mod *rx_mod, struct bna_rxq *rxq)
+{
+ bfa_q_qe_init(&rxq->qe);
+ list_add_tail(&rxq->qe, &rx_mod->rxq_free_q);
+ rx_mod->rxq_free_count++;
+}
+
+static struct bna_rxp *
+_get_free_rxp(struct bna_rx_mod *rx_mod)
+{
+ struct list_head *qe = NULL;
+ struct bna_rxp *rxp = NULL;
+
+ bfa_q_deq(&rx_mod->rxp_free_q, &qe);
+ if (qe) {
+ rx_mod->rxp_free_count--;
+
+ rxp = (struct bna_rxp *)qe;
+ }
+
+ return rxp;
+}
+
+static void
+_put_free_rxp(struct bna_rx_mod *rx_mod, struct bna_rxp *rxp)
+{
+ bfa_q_qe_init(&rxp->qe);
+ list_add_tail(&rxp->qe, &rx_mod->rxp_free_q);
+ rx_mod->rxp_free_count++;
+}
+
+static struct bna_rx *
+_get_free_rx(struct bna_rx_mod *rx_mod)
+{
+ struct list_head *qe = NULL;
+ struct bna_rx *rx = NULL;
+
+ bfa_q_deq(&rx_mod->rx_free_q, &qe);
+ if (qe) {
+ rx_mod->rx_free_count--;
+
+ rx = (struct bna_rx *)qe;
+ bfa_q_qe_init(qe);
+ list_add_tail(&rx->qe, &rx_mod->rx_active_q);
+ }
+
+ return rx;
+}
+
+static void
+_put_free_rx(struct bna_rx_mod *rx_mod, struct bna_rx *rx)
+{
+ bfa_q_qe_init(&rx->qe);
+ list_add_tail(&rx->qe, &rx_mod->rx_free_q);
+ rx_mod->rx_free_count++;
+}
+
+static void
+_rx_init(struct bna_rx *rx, struct bna *bna)
+{
+ rx->bna = bna;
+ rx->rx_flags = 0;
+
+ INIT_LIST_HEAD(&rx->rxp_q);
+
+ rx->rxq_stop_wc.wc_resume = bna_rx_cb_rxq_stopped_all;
+ rx->rxq_stop_wc.wc_cbarg = rx;
+ rx->rxq_stop_wc.wc_count = 0;
+
+ rx->stop_cbfn = NULL;
+ rx->stop_cbarg = NULL;
+}
+
+static void
+_rxp_add_rxqs(struct bna_rxp *rxp,
+ struct bna_rxq *q0,
+ struct bna_rxq *q1)
+{
+ switch (rxp->type) {
+ case BNA_RXP_SINGLE:
+ rxp->rxq.single.only = q0;
+ rxp->rxq.single.reserved = NULL;
+ break;
+ case BNA_RXP_SLR:
+ rxp->rxq.slr.large = q0;
+ rxp->rxq.slr.small = q1;
+ break;
+ case BNA_RXP_HDS:
+ rxp->rxq.hds.data = q0;
+ rxp->rxq.hds.hdr = q1;
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+_rxq_qpt_init(struct bna_rxq *rxq,
+ struct bna_rxp *rxp,
+ u32 page_count,
+ u32 page_size,
+ struct bna_mem_descr *qpt_mem,
+ struct bna_mem_descr *swqpt_mem,
+ struct bna_mem_descr *page_mem)
+{
+ int i;
+
+ rxq->qpt.hw_qpt_ptr.lsb = qpt_mem->dma.lsb;
+ rxq->qpt.hw_qpt_ptr.msb = qpt_mem->dma.msb;
+ rxq->qpt.kv_qpt_ptr = qpt_mem->kva;
+ rxq->qpt.page_count = page_count;
+ rxq->qpt.page_size = page_size;
+
+ rxq->rcb->sw_qpt = (void **) swqpt_mem->kva;
+
+ for (i = 0; i < rxq->qpt.page_count; i++) {
+ rxq->rcb->sw_qpt[i] = page_mem[i].kva;
+ ((struct bna_dma_addr *)rxq->qpt.kv_qpt_ptr)[i].lsb =
+ page_mem[i].dma.lsb;
+ ((struct bna_dma_addr *)rxq->qpt.kv_qpt_ptr)[i].msb =
+ page_mem[i].dma.msb;
+
+ }
+}
+
+static void
+_rxp_cqpt_setup(struct bna_rxp *rxp,
+ u32 page_count,
+ u32 page_size,
+ struct bna_mem_descr *qpt_mem,
+ struct bna_mem_descr *swqpt_mem,
+ struct bna_mem_descr *page_mem)
+{
+ int i;
+
+ rxp->cq.qpt.hw_qpt_ptr.lsb = qpt_mem->dma.lsb;
+ rxp->cq.qpt.hw_qpt_ptr.msb = qpt_mem->dma.msb;
+ rxp->cq.qpt.kv_qpt_ptr = qpt_mem->kva;
+ rxp->cq.qpt.page_count = page_count;
+ rxp->cq.qpt.page_size = page_size;
+
+ rxp->cq.ccb->sw_qpt = (void **) swqpt_mem->kva;
+
+ for (i = 0; i < rxp->cq.qpt.page_count; i++) {
+ rxp->cq.ccb->sw_qpt[i] = page_mem[i].kva;
+
+ ((struct bna_dma_addr *)rxp->cq.qpt.kv_qpt_ptr)[i].lsb =
+ page_mem[i].dma.lsb;
+ ((struct bna_dma_addr *)rxp->cq.qpt.kv_qpt_ptr)[i].msb =
+ page_mem[i].dma.msb;
+
+ }
+}
+
+static void
+_rx_add_rxp(struct bna_rx *rx, struct bna_rxp *rxp)
+{
+ list_add_tail(&rxp->qe, &rx->rxp_q);
+}
+
+static void
+_init_rxmod_queues(struct bna_rx_mod *rx_mod)
+{
+ INIT_LIST_HEAD(&rx_mod->rx_free_q);
+ INIT_LIST_HEAD(&rx_mod->rxq_free_q);
+ INIT_LIST_HEAD(&rx_mod->rxp_free_q);
+ INIT_LIST_HEAD(&rx_mod->rx_active_q);
+
+ rx_mod->rx_free_count = 0;
+ rx_mod->rxq_free_count = 0;
+ rx_mod->rxp_free_count = 0;
+}
+
+static void
+_rx_ctor(struct bna_rx *rx, int id)
+{
+ bfa_q_qe_init(&rx->qe);
+ INIT_LIST_HEAD(&rx->rxp_q);
+ rx->bna = NULL;
+
+ rx->rxf.rxf_id = id;
+
+ /* FIXME: mbox_qe ctor()?? */
+ bfa_q_qe_init(&rx->mbox_qe.qe);
+
+ rx->stop_cbfn = NULL;
+ rx->stop_cbarg = NULL;
+}
+
+void
+bna_rx_cb_multi_rxq_stopped(void *arg, int status)
+{
+ struct bna_rxp *rxp = (struct bna_rxp *)arg;
+
+ bfa_wc_down(&rxp->rx->rxq_stop_wc);
+}
+
+void
+bna_rx_cb_rxq_stopped_all(void *arg)
+{
+ struct bna_rx *rx = (struct bna_rx *)arg;
+
+ bfa_fsm_send_event(rx, RX_E_RXQ_STOPPED);
+}
+
+static void
+bna_rx_mod_cb_rx_stopped(void *arg, struct bna_rx *rx,
+ enum bna_cb_status status)
+{
+ struct bna_rx_mod *rx_mod = (struct bna_rx_mod *)arg;
+
+ bfa_wc_down(&rx_mod->rx_stop_wc);
+}
+
+static void
+bna_rx_mod_cb_rx_stopped_all(void *arg)
+{
+ struct bna_rx_mod *rx_mod = (struct bna_rx_mod *)arg;
+
+ if (rx_mod->stop_cbfn)
+ rx_mod->stop_cbfn(&rx_mod->bna->port, BNA_CB_SUCCESS);
+ rx_mod->stop_cbfn = NULL;
+}
+
+static void
+bna_rx_start(struct bna_rx *rx)
+{
+ rx->rx_flags |= BNA_RX_F_PORT_ENABLED;
+ if (rx->rx_flags & BNA_RX_F_ENABLE)
+ bfa_fsm_send_event(rx, RX_E_START);
+}
+
+static void
+bna_rx_stop(struct bna_rx *rx)
+{
+ rx->rx_flags &= ~BNA_RX_F_PORT_ENABLED;
+ if (rx->fsm == (bfa_fsm_t) bna_rx_sm_stopped)
+ bna_rx_mod_cb_rx_stopped(&rx->bna->rx_mod, rx, BNA_CB_SUCCESS);
+ else {
+ rx->stop_cbfn = bna_rx_mod_cb_rx_stopped;
+ rx->stop_cbarg = &rx->bna->rx_mod;
+ bfa_fsm_send_event(rx, RX_E_STOP);
+ }
+}
+
+static void
+bna_rx_fail(struct bna_rx *rx)
+{
+ /* Indicate port is not enabled, and failed */
+ rx->rx_flags &= ~BNA_RX_F_PORT_ENABLED;
+ rx->rx_flags |= BNA_RX_F_PORT_FAILED;
+ bfa_fsm_send_event(rx, RX_E_FAIL);
+}
+
+void
+bna_rx_mod_start(struct bna_rx_mod *rx_mod, enum bna_rx_type type)
+{
+ struct bna_rx *rx;
+ struct list_head *qe;
+
+ rx_mod->flags |= BNA_RX_MOD_F_PORT_STARTED;
+ if (type == BNA_RX_T_LOOPBACK)
+ rx_mod->flags |= BNA_RX_MOD_F_PORT_LOOPBACK;
+
+ list_for_each(qe, &rx_mod->rx_active_q) {
+ rx = (struct bna_rx *)qe;
+ if (rx->type == type)
+ bna_rx_start(rx);
+ }
+}
+
+void
+bna_rx_mod_stop(struct bna_rx_mod *rx_mod, enum bna_rx_type type)
+{
+ struct bna_rx *rx;
+ struct list_head *qe;
+
+ rx_mod->flags &= ~BNA_RX_MOD_F_PORT_STARTED;
+ rx_mod->flags &= ~BNA_RX_MOD_F_PORT_LOOPBACK;
+
+ rx_mod->stop_cbfn = bna_port_cb_rx_stopped;
+
+ /**
+ * Before calling bna_rx_stop(), increment rx_stop_wc as many times
+ * as we are going to call bna_rx_stop
+ */
+ list_for_each(qe, &rx_mod->rx_active_q) {
+ rx = (struct bna_rx *)qe;
+ if (rx->type == type)
+ bfa_wc_up(&rx_mod->rx_stop_wc);
+ }
+
+ if (rx_mod->rx_stop_wc.wc_count == 0) {
+ rx_mod->stop_cbfn(&rx_mod->bna->port, BNA_CB_SUCCESS);
+ rx_mod->stop_cbfn = NULL;
+ return;
+ }
+
+ list_for_each(qe, &rx_mod->rx_active_q) {
+ rx = (struct bna_rx *)qe;
+ if (rx->type == type)
+ bna_rx_stop(rx);
+ }
+}
+
+void
+bna_rx_mod_fail(struct bna_rx_mod *rx_mod)
+{
+ struct bna_rx *rx;
+ struct list_head *qe;
+
+ rx_mod->flags &= ~BNA_RX_MOD_F_PORT_STARTED;
+ rx_mod->flags &= ~BNA_RX_MOD_F_PORT_LOOPBACK;
+
+ list_for_each(qe, &rx_mod->rx_active_q) {
+ rx = (struct bna_rx *)qe;
+ bna_rx_fail(rx);
+ }
+}
+
+void bna_rx_mod_init(struct bna_rx_mod *rx_mod, struct bna *bna,
+ struct bna_res_info *res_info)
+{
+ int index;
+ struct bna_rx *rx_ptr;
+ struct bna_rxp *rxp_ptr;
+ struct bna_rxq *rxq_ptr;
+
+ rx_mod->bna = bna;
+ rx_mod->flags = 0;
+
+ rx_mod->rx = (struct bna_rx *)
+ res_info[BNA_RES_MEM_T_RX_ARRAY].res_u.mem_info.mdl[0].kva;
+ rx_mod->rxp = (struct bna_rxp *)
+ res_info[BNA_RES_MEM_T_RXP_ARRAY].res_u.mem_info.mdl[0].kva;
+ rx_mod->rxq = (struct bna_rxq *)
+ res_info[BNA_RES_MEM_T_RXQ_ARRAY].res_u.mem_info.mdl[0].kva;
+
+ /* Initialize the queues */
+ _init_rxmod_queues(rx_mod);
+
+ /* Build RX queues */
+ for (index = 0; index < BFI_MAX_RXQ; index++) {
+ rx_ptr = &rx_mod->rx[index];
+ _rx_ctor(rx_ptr, index);
+ list_add_tail(&rx_ptr->qe, &rx_mod->rx_free_q);
+ rx_mod->rx_free_count++;
+ }
+
+ /* build RX-path queue */
+ for (index = 0; index < BFI_MAX_RXQ; index++) {
+ rxp_ptr = &rx_mod->rxp[index];
+ rxp_ptr->cq.cq_id = index;
+ bfa_q_qe_init(&rxp_ptr->qe);
+ list_add_tail(&rxp_ptr->qe, &rx_mod->rxp_free_q);
+ rx_mod->rxp_free_count++;
+ }
+
+ /* build RXQ queue */
+ for (index = 0; index < BFI_MAX_RXQ; index++) {
+ rxq_ptr = &rx_mod->rxq[index];
+ rxq_ptr->rxq_id = index;
+
+ bfa_q_qe_init(&rxq_ptr->qe);
+ list_add_tail(&rxq_ptr->qe, &rx_mod->rxq_free_q);
+ rx_mod->rxq_free_count++;
+ }
+
+ rx_mod->rx_stop_wc.wc_resume = bna_rx_mod_cb_rx_stopped_all;
+ rx_mod->rx_stop_wc.wc_cbarg = rx_mod;
+ rx_mod->rx_stop_wc.wc_count = 0;
+}
+
+void
+bna_rx_mod_uninit(struct bna_rx_mod *rx_mod)
+{
+ struct list_head *qe;
+ int i;
+
+ i = 0;
+ list_for_each(qe, &rx_mod->rx_free_q)
+ i++;
+
+ i = 0;
+ list_for_each(qe, &rx_mod->rxp_free_q)
+ i++;
+
+ i = 0;
+ list_for_each(qe, &rx_mod->rxq_free_q)
+ i++;
+
+ rx_mod->bna = NULL;
+}
+
+int
+bna_rx_state_get(struct bna_rx *rx)
+{
+ return bfa_sm_to_state(rx_sm_table, rx->fsm);
+}
+
+void
+bna_rx_res_req(struct bna_rx_config *q_cfg, struct bna_res_info *res_info)
+{
+ u32 cq_size, hq_size, dq_size;
+ u32 cpage_count, hpage_count, dpage_count;
+ struct bna_mem_info *mem_info;
+ u32 cq_depth;
+ u32 hq_depth;
+ u32 dq_depth;
+
+ dq_depth = q_cfg->q_depth;
+ hq_depth = ((q_cfg->rxp_type == BNA_RXP_SINGLE) ? 0 : q_cfg->q_depth);
+ cq_depth = dq_depth + hq_depth;
+
+ BNA_TO_POWER_OF_2_HIGH(cq_depth);
+ cq_size = cq_depth * BFI_CQ_WI_SIZE;
+ cq_size = ALIGN(cq_size, PAGE_SIZE);
+ cpage_count = SIZE_TO_PAGES(cq_size);
+
+ BNA_TO_POWER_OF_2_HIGH(dq_depth);
+ dq_size = dq_depth * BFI_RXQ_WI_SIZE;
+ dq_size = ALIGN(dq_size, PAGE_SIZE);
+ dpage_count = SIZE_TO_PAGES(dq_size);
+
+ if (BNA_RXP_SINGLE != q_cfg->rxp_type) {
+ BNA_TO_POWER_OF_2_HIGH(hq_depth);
+ hq_size = hq_depth * BFI_RXQ_WI_SIZE;
+ hq_size = ALIGN(hq_size, PAGE_SIZE);
+ hpage_count = SIZE_TO_PAGES(hq_size);
+ } else {
+ hpage_count = 0;
+ }
+
+ /* CCB structures */
+ res_info[BNA_RX_RES_MEM_T_CCB].res_type = BNA_RES_T_MEM;
+ mem_info = &res_info[BNA_RX_RES_MEM_T_CCB].res_u.mem_info;
+ mem_info->mem_type = BNA_MEM_T_KVA;
+ mem_info->len = sizeof(struct bna_ccb);
+ mem_info->num = q_cfg->num_paths;
+
+ /* RCB structures */
+ res_info[BNA_RX_RES_MEM_T_RCB].res_type = BNA_RES_T_MEM;
+ mem_info = &res_info[BNA_RX_RES_MEM_T_RCB].res_u.mem_info;
+ mem_info->mem_type = BNA_MEM_T_KVA;
+ mem_info->len = sizeof(struct bna_rcb);
+ mem_info->num = BNA_GET_RXQS(q_cfg);
+
+ /* Completion QPT */
+ res_info[BNA_RX_RES_MEM_T_CQPT].res_type = BNA_RES_T_MEM;
+ mem_info = &res_info[BNA_RX_RES_MEM_T_CQPT].res_u.mem_info;
+ mem_info->mem_type = BNA_MEM_T_DMA;
+ mem_info->len = cpage_count * sizeof(struct bna_dma_addr);
+ mem_info->num = q_cfg->num_paths;
+
+ /* Completion s/w QPT */
+ res_info[BNA_RX_RES_MEM_T_CSWQPT].res_type = BNA_RES_T_MEM;
+ mem_info = &res_info[BNA_RX_RES_MEM_T_CSWQPT].res_u.mem_info;
+ mem_info->mem_type = BNA_MEM_T_KVA;
+ mem_info->len = cpage_count * sizeof(void *);
+ mem_info->num = q_cfg->num_paths;
+
+ /* Completion QPT pages */
+ res_info[BNA_RX_RES_MEM_T_CQPT_PAGE].res_type = BNA_RES_T_MEM;
+ mem_info = &res_info[BNA_RX_RES_MEM_T_CQPT_PAGE].res_u.mem_info;
+ mem_info->mem_type = BNA_MEM_T_DMA;
+ mem_info->len = PAGE_SIZE;
+ mem_info->num = cpage_count * q_cfg->num_paths;
+
+ /* Data QPTs */
+ res_info[BNA_RX_RES_MEM_T_DQPT].res_type = BNA_RES_T_MEM;
+ mem_info = &res_info[BNA_RX_RES_MEM_T_DQPT].res_u.mem_info;
+ mem_info->mem_type = BNA_MEM_T_DMA;
+ mem_info->len = dpage_count * sizeof(struct bna_dma_addr);
+ mem_info->num = q_cfg->num_paths;
+
+ /* Data s/w QPTs */
+ res_info[BNA_RX_RES_MEM_T_DSWQPT].res_type = BNA_RES_T_MEM;
+ mem_info = &res_info[BNA_RX_RES_MEM_T_DSWQPT].res_u.mem_info;
+ mem_info->mem_type = BNA_MEM_T_KVA;
+ mem_info->len = dpage_count * sizeof(void *);
+ mem_info->num = q_cfg->num_paths;
+
+ /* Data QPT pages */
+ res_info[BNA_RX_RES_MEM_T_DPAGE].res_type = BNA_RES_T_MEM;
+ mem_info = &res_info[BNA_RX_RES_MEM_T_DPAGE].res_u.mem_info;
+ mem_info->mem_type = BNA_MEM_T_DMA;
+ mem_info->len = PAGE_SIZE;
+ mem_info->num = dpage_count * q_cfg->num_paths;
+
+ /* Hdr QPTs */
+ res_info[BNA_RX_RES_MEM_T_HQPT].res_type = BNA_RES_T_MEM;
+ mem_info = &res_info[BNA_RX_RES_MEM_T_HQPT].res_u.mem_info;
+ mem_info->mem_type = BNA_MEM_T_DMA;
+ mem_info->len = hpage_count * sizeof(struct bna_dma_addr);
+ mem_info->num = (hpage_count ? q_cfg->num_paths : 0);
+
+ /* Hdr s/w QPTs */
+ res_info[BNA_RX_RES_MEM_T_HSWQPT].res_type = BNA_RES_T_MEM;
+ mem_info = &res_info[BNA_RX_RES_MEM_T_HSWQPT].res_u.mem_info;
+ mem_info->mem_type = BNA_MEM_T_KVA;
+ mem_info->len = hpage_count * sizeof(void *);
+ mem_info->num = (hpage_count ? q_cfg->num_paths : 0);
+
+ /* Hdr QPT pages */
+ res_info[BNA_RX_RES_MEM_T_HPAGE].res_type = BNA_RES_T_MEM;
+ mem_info = &res_info[BNA_RX_RES_MEM_T_HPAGE].res_u.mem_info;
+ mem_info->mem_type = BNA_MEM_T_DMA;
+ mem_info->len = (hpage_count ? PAGE_SIZE : 0);
+ mem_info->num = (hpage_count ? (hpage_count * q_cfg->num_paths) : 0);
+
+ /* RX Interrupts */
+ res_info[BNA_RX_RES_T_INTR].res_type = BNA_RES_T_INTR;
+ res_info[BNA_RX_RES_T_INTR].res_u.intr_info.intr_type = BNA_INTR_T_MSIX;
+ res_info[BNA_RX_RES_T_INTR].res_u.intr_info.num = q_cfg->num_paths;
+}
+
+struct bna_rx *
+bna_rx_create(struct bna *bna, struct bnad *bnad,
+ struct bna_rx_config *rx_cfg,
+ struct bna_rx_event_cbfn *rx_cbfn,
+ struct bna_res_info *res_info,
+ void *priv)
+{
+ struct bna_rx_mod *rx_mod = &bna->rx_mod;
+ struct bna_rx *rx;
+ struct bna_rxp *rxp;
+ struct bna_rxq *q0;
+ struct bna_rxq *q1;
+ struct bna_intr_info *intr_info;
+ u32 page_count;
+ struct bna_mem_descr *ccb_mem;
+ struct bna_mem_descr *rcb_mem;
+ struct bna_mem_descr *unmapq_mem;
+ struct bna_mem_descr *cqpt_mem;
+ struct bna_mem_descr *cswqpt_mem;
+ struct bna_mem_descr *cpage_mem;
+ struct bna_mem_descr *hqpt_mem; /* Header/Small Q qpt */
+ struct bna_mem_descr *dqpt_mem; /* Data/Large Q qpt */
+ struct bna_mem_descr *hsqpt_mem; /* s/w qpt for hdr */
+ struct bna_mem_descr *dsqpt_mem; /* s/w qpt for data */
+ struct bna_mem_descr *hpage_mem; /* hdr page mem */
+ struct bna_mem_descr *dpage_mem; /* data page mem */
+ int i, cpage_idx = 0, dpage_idx = 0, hpage_idx = 0, ret;
+ int dpage_count, hpage_count, rcb_idx;
+ struct bna_ib_config ibcfg;
+ /* Fail if we don't have enough RXPs, RXQs */
+ if (!_rx_can_satisfy(rx_mod, rx_cfg))
+ return NULL;
+
+ /* Initialize resource pointers */
+ intr_info = &res_info[BNA_RX_RES_T_INTR].res_u.intr_info;
+ ccb_mem = &res_info[BNA_RX_RES_MEM_T_CCB].res_u.mem_info.mdl[0];
+ rcb_mem = &res_info[BNA_RX_RES_MEM_T_RCB].res_u.mem_info.mdl[0];
+ unmapq_mem = &res_info[BNA_RX_RES_MEM_T_UNMAPQ].res_u.mem_info.mdl[0];
+ cqpt_mem = &res_info[BNA_RX_RES_MEM_T_CQPT].res_u.mem_info.mdl[0];
+ cswqpt_mem = &res_info[BNA_RX_RES_MEM_T_CSWQPT].res_u.mem_info.mdl[0];
+ cpage_mem = &res_info[BNA_RX_RES_MEM_T_CQPT_PAGE].res_u.mem_info.mdl[0];
+ hqpt_mem = &res_info[BNA_RX_RES_MEM_T_HQPT].res_u.mem_info.mdl[0];
+ dqpt_mem = &res_info[BNA_RX_RES_MEM_T_DQPT].res_u.mem_info.mdl[0];
+ hsqpt_mem = &res_info[BNA_RX_RES_MEM_T_HSWQPT].res_u.mem_info.mdl[0];
+ dsqpt_mem = &res_info[BNA_RX_RES_MEM_T_DSWQPT].res_u.mem_info.mdl[0];
+ hpage_mem = &res_info[BNA_RX_RES_MEM_T_HPAGE].res_u.mem_info.mdl[0];
+ dpage_mem = &res_info[BNA_RX_RES_MEM_T_DPAGE].res_u.mem_info.mdl[0];
+
+ /* Compute q depth & page count */
+ page_count = res_info[BNA_RX_RES_MEM_T_CQPT_PAGE].res_u.mem_info.num /
+ rx_cfg->num_paths;
+
+ dpage_count = res_info[BNA_RX_RES_MEM_T_DPAGE].res_u.mem_info.num /
+ rx_cfg->num_paths;
+
+ hpage_count = res_info[BNA_RX_RES_MEM_T_HPAGE].res_u.mem_info.num /
+ rx_cfg->num_paths;
+ /* Get RX pointer */
+ rx = _get_free_rx(rx_mod);
+ _rx_init(rx, bna);
+ rx->priv = priv;
+ rx->type = rx_cfg->rx_type;
+
+ rx->rcb_setup_cbfn = rx_cbfn->rcb_setup_cbfn;
+ rx->rcb_destroy_cbfn = rx_cbfn->rcb_destroy_cbfn;
+ rx->ccb_setup_cbfn = rx_cbfn->ccb_setup_cbfn;
+ rx->ccb_destroy_cbfn = rx_cbfn->ccb_destroy_cbfn;
+ /* Following callbacks are mandatory */
+ rx->rx_cleanup_cbfn = rx_cbfn->rx_cleanup_cbfn;
+ rx->rx_post_cbfn = rx_cbfn->rx_post_cbfn;
+
+ if (rx->bna->rx_mod.flags & BNA_RX_MOD_F_PORT_STARTED) {
+ switch (rx->type) {
+ case BNA_RX_T_REGULAR:
+ if (!(rx->bna->rx_mod.flags &
+ BNA_RX_MOD_F_PORT_LOOPBACK))
+ rx->rx_flags |= BNA_RX_F_PORT_ENABLED;
+ break;
+ case BNA_RX_T_LOOPBACK:
+ if (rx->bna->rx_mod.flags & BNA_RX_MOD_F_PORT_LOOPBACK)
+ rx->rx_flags |= BNA_RX_F_PORT_ENABLED;
+ break;
+ }
+ }
+
+ for (i = 0, rcb_idx = 0; i < rx_cfg->num_paths; i++) {
+ rxp = _get_free_rxp(rx_mod);
+ rxp->type = rx_cfg->rxp_type;
+ rxp->rx = rx;
+ rxp->cq.rx = rx;
+
+ /* Get required RXQs, and queue them to rx-path */
+ q0 = _get_free_rxq(rx_mod);
+ if (BNA_RXP_SINGLE == rx_cfg->rxp_type)
+ q1 = NULL;
+ else
+ q1 = _get_free_rxq(rx_mod);
+
+ /* Initialize IB */
+ if (1 == intr_info->num) {
+ rxp->cq.ib = bna_ib_get(&bna->ib_mod,
+ intr_info->intr_type,
+ intr_info->idl[0].vector);
+ rxp->vector = intr_info->idl[0].vector;
+ } else {
+ rxp->cq.ib = bna_ib_get(&bna->ib_mod,
+ intr_info->intr_type,
+ intr_info->idl[i].vector);
+
+ /* Map the MSI-x vector used for this RXP */
+ rxp->vector = intr_info->idl[i].vector;
+ }
+
+ rxp->cq.ib_seg_offset = bna_ib_reserve_idx(rxp->cq.ib);
+
+ ibcfg.coalescing_timeo = BFI_RX_COALESCING_TIMEO;
+ ibcfg.interpkt_count = BFI_RX_INTERPKT_COUNT;
+ ibcfg.interpkt_timeo = BFI_RX_INTERPKT_TIMEO;
+ ibcfg.ctrl_flags = BFI_IB_CF_INT_ENABLE;
+
+ ret = bna_ib_config(rxp->cq.ib, &ibcfg);
+
+ /* Link rxqs to rxp */
+ _rxp_add_rxqs(rxp, q0, q1);
+
+ /* Link rxp to rx */
+ _rx_add_rxp(rx, rxp);
+
+ q0->rx = rx;
+ q0->rxp = rxp;
+
+ /* Initialize RCB for the large / data q */
+ q0->rcb = (struct bna_rcb *) rcb_mem[rcb_idx].kva;
+ RXQ_RCB_INIT(q0, rxp, rx_cfg->q_depth, bna, 0,
+ (void *)unmapq_mem[rcb_idx].kva);
+ rcb_idx++;
+ (q0)->rx_packets = (q0)->rx_bytes = 0;
+ (q0)->rx_packets_with_error = (q0)->rxbuf_alloc_failed = 0;
+
+ /* Initialize RXQs */
+ _rxq_qpt_init(q0, rxp, dpage_count, PAGE_SIZE,
+ &dqpt_mem[i], &dsqpt_mem[i], &dpage_mem[dpage_idx]);
+ q0->rcb->page_idx = dpage_idx;
+ q0->rcb->page_count = dpage_count;
+ dpage_idx += dpage_count;
+
+ /* Call bnad to complete rcb setup */
+ if (rx->rcb_setup_cbfn)
+ rx->rcb_setup_cbfn(bnad, q0->rcb);
+
+ if (q1) {
+ q1->rx = rx;
+ q1->rxp = rxp;
+
+ q1->rcb = (struct bna_rcb *) rcb_mem[rcb_idx].kva;
+ RXQ_RCB_INIT(q1, rxp, rx_cfg->q_depth, bna, 1,
+ (void *)unmapq_mem[rcb_idx].kva);
+ rcb_idx++;
+ (q1)->buffer_size = (rx_cfg)->small_buff_size;
+ (q1)->rx_packets = (q1)->rx_bytes = 0;
+ (q1)->rx_packets_with_error =
+ (q1)->rxbuf_alloc_failed = 0;
+
+ _rxq_qpt_init(q1, rxp, hpage_count, PAGE_SIZE,
+ &hqpt_mem[i], &hsqpt_mem[i],
+ &hpage_mem[hpage_idx]);
+ q1->rcb->page_idx = hpage_idx;
+ q1->rcb->page_count = hpage_count;
+ hpage_idx += hpage_count;
+
+ /* Call bnad to complete rcb setup */
+ if (rx->rcb_setup_cbfn)
+ rx->rcb_setup_cbfn(bnad, q1->rcb);
+ }
+ /* Setup RXP::CQ */
+ rxp->cq.ccb = (struct bna_ccb *) ccb_mem[i].kva;
+ _rxp_cqpt_setup(rxp, page_count, PAGE_SIZE,
+ &cqpt_mem[i], &cswqpt_mem[i], &cpage_mem[cpage_idx]);
+ rxp->cq.ccb->page_idx = cpage_idx;
+ rxp->cq.ccb->page_count = page_count;
+ cpage_idx += page_count;
+
+ rxp->cq.ccb->pkt_rate.small_pkt_cnt = 0;
+ rxp->cq.ccb->pkt_rate.large_pkt_cnt = 0;
+
+ rxp->cq.ccb->producer_index = 0;
+ rxp->cq.ccb->q_depth = rx_cfg->q_depth +
+ ((rx_cfg->rxp_type == BNA_RXP_SINGLE) ?
+ 0 : rx_cfg->q_depth);
+ rxp->cq.ccb->i_dbell = &rxp->cq.ib->door_bell;
+ rxp->cq.ccb->rcb[0] = q0->rcb;
+ if (q1)
+ rxp->cq.ccb->rcb[1] = q1->rcb;
+ rxp->cq.ccb->cq = &rxp->cq;
+ rxp->cq.ccb->bnad = bna->bnad;
+ rxp->cq.ccb->hw_producer_index =
+ ((volatile u32 *)rxp->cq.ib->ib_seg_host_addr_kva +
+ (rxp->cq.ib_seg_offset * BFI_IBIDX_SIZE));
+ *(rxp->cq.ccb->hw_producer_index) = 0;
+ rxp->cq.ccb->intr_type = intr_info->intr_type;
+ rxp->cq.ccb->intr_vector = (intr_info->num == 1) ?
+ intr_info->idl[0].vector :
+ intr_info->idl[i].vector;
+ rxp->cq.ccb->rx_coalescing_timeo =
+ rxp->cq.ib->ib_config.coalescing_timeo;
+ rxp->cq.ccb->id = i;
+
+ /* Call bnad to complete CCB setup */
+ if (rx->ccb_setup_cbfn)
+ rx->ccb_setup_cbfn(bnad, rxp->cq.ccb);
+
+ } /* for each rx-path */
+
+ bna_rxf_init(&rx->rxf, rx, rx_cfg);
+
+ bfa_fsm_set_state(rx, bna_rx_sm_stopped);
+
+ return rx;
+}
+
+void
+bna_rx_destroy(struct bna_rx *rx)
+{
+ struct bna_rx_mod *rx_mod = &rx->bna->rx_mod;
+ struct bna_ib_mod *ib_mod = &rx->bna->ib_mod;
+ struct bna_rxq *q0 = NULL;
+ struct bna_rxq *q1 = NULL;
+ struct bna_rxp *rxp;
+ struct list_head *qe;
+
+ bna_rxf_uninit(&rx->rxf);
+
+ while (!list_empty(&rx->rxp_q)) {
+ bfa_q_deq(&rx->rxp_q, &rxp);
+ GET_RXQS(rxp, q0, q1);
+ /* Callback to bnad for destroying RCB */
+ if (rx->rcb_destroy_cbfn)
+ rx->rcb_destroy_cbfn(rx->bna->bnad, q0->rcb);
+ q0->rcb = NULL;
+ q0->rxp = NULL;
+ q0->rx = NULL;
+ _put_free_rxq(rx_mod, q0);
+ if (q1) {
+ /* Callback to bnad for destroying RCB */
+ if (rx->rcb_destroy_cbfn)
+ rx->rcb_destroy_cbfn(rx->bna->bnad, q1->rcb);
+ q1->rcb = NULL;
+ q1->rxp = NULL;
+ q1->rx = NULL;
+ _put_free_rxq(rx_mod, q1);
+ }
+ rxp->rxq.slr.large = NULL;
+ rxp->rxq.slr.small = NULL;
+ if (rxp->cq.ib) {
+ if (rxp->cq.ib_seg_offset != 0xff)
+ bna_ib_release_idx(rxp->cq.ib,
+ rxp->cq.ib_seg_offset);
+ bna_ib_put(ib_mod, rxp->cq.ib);
+ rxp->cq.ib = NULL;
+ }
+ /* Callback to bnad for destroying CCB */
+ if (rx->ccb_destroy_cbfn)
+ rx->ccb_destroy_cbfn(rx->bna->bnad, rxp->cq.ccb);
+ rxp->cq.ccb = NULL;
+ rxp->rx = NULL;
+ _put_free_rxp(rx_mod, rxp);
+ }
+
+ list_for_each(qe, &rx_mod->rx_active_q) {
+ if (qe == &rx->qe) {
+ list_del(&rx->qe);
+ bfa_q_qe_init(&rx->qe);
+ break;
+ }
+ }
+
+ rx->bna = NULL;
+ rx->priv = NULL;
+ _put_free_rx(rx_mod, rx);
+}
+
+void
+bna_rx_enable(struct bna_rx *rx)
+{
+ if (rx->fsm != (bfa_sm_t)bna_rx_sm_stopped)
+ return;
+
+ rx->rx_flags |= BNA_RX_F_ENABLE;
+ if (rx->rx_flags & BNA_RX_F_PORT_ENABLED)
+ bfa_fsm_send_event(rx, RX_E_START);
+}
+
+void
+bna_rx_disable(struct bna_rx *rx, enum bna_cleanup_type type,
+ void (*cbfn)(void *, struct bna_rx *,
+ enum bna_cb_status))
+{
+ if (type == BNA_SOFT_CLEANUP) {
+ /* h/w should not be accessed. Treat we're stopped */
+ (*cbfn)(rx->bna->bnad, rx, BNA_CB_SUCCESS);
+ } else {
+ rx->stop_cbfn = cbfn;
+ rx->stop_cbarg = rx->bna->bnad;
+
+ rx->rx_flags &= ~BNA_RX_F_ENABLE;
+
+ bfa_fsm_send_event(rx, RX_E_STOP);
+ }
+}
+
+/**
+ * TX
+ */
+#define call_tx_stop_cbfn(tx, status)\
+do {\
+ if ((tx)->stop_cbfn)\
+ (tx)->stop_cbfn((tx)->stop_cbarg, (tx), status);\
+ (tx)->stop_cbfn = NULL;\
+ (tx)->stop_cbarg = NULL;\
+} while (0)
+
+#define call_tx_prio_change_cbfn(tx, status)\
+do {\
+ if ((tx)->prio_change_cbfn)\
+ (tx)->prio_change_cbfn((tx)->bna->bnad, (tx), status);\
+ (tx)->prio_change_cbfn = NULL;\
+} while (0)
+
+static void bna_tx_mod_cb_tx_stopped(void *tx_mod, struct bna_tx *tx,
+ enum bna_cb_status status);
+static void bna_tx_cb_txq_stopped(void *arg, int status);
+static void bna_tx_cb_stats_cleared(void *arg, int status);
+static void __bna_tx_stop(struct bna_tx *tx);
+static void __bna_tx_start(struct bna_tx *tx);
+static void __bna_txf_stat_clr(struct bna_tx *tx);
+
+enum bna_tx_event {
+ TX_E_START = 1,
+ TX_E_STOP = 2,
+ TX_E_FAIL = 3,
+ TX_E_TXQ_STOPPED = 4,
+ TX_E_PRIO_CHANGE = 5,
+ TX_E_STAT_CLEARED = 6,
+};
+
+enum bna_tx_state {
+ BNA_TX_STOPPED = 1,
+ BNA_TX_STARTED = 2,
+ BNA_TX_TXQ_STOP_WAIT = 3,
+ BNA_TX_PRIO_STOP_WAIT = 4,
+ BNA_TX_STAT_CLR_WAIT = 5,
+};
+
+bfa_fsm_state_decl(bna_tx, stopped, struct bna_tx,
+ enum bna_tx_event);
+bfa_fsm_state_decl(bna_tx, started, struct bna_tx,
+ enum bna_tx_event);
+bfa_fsm_state_decl(bna_tx, txq_stop_wait, struct bna_tx,
+ enum bna_tx_event);
+bfa_fsm_state_decl(bna_tx, prio_stop_wait, struct bna_tx,
+ enum bna_tx_event);
+bfa_fsm_state_decl(bna_tx, stat_clr_wait, struct bna_tx,
+ enum bna_tx_event);
+
+static struct bfa_sm_table tx_sm_table[] = {
+ {BFA_SM(bna_tx_sm_stopped), BNA_TX_STOPPED},
+ {BFA_SM(bna_tx_sm_started), BNA_TX_STARTED},
+ {BFA_SM(bna_tx_sm_txq_stop_wait), BNA_TX_TXQ_STOP_WAIT},
+ {BFA_SM(bna_tx_sm_prio_stop_wait), BNA_TX_PRIO_STOP_WAIT},
+ {BFA_SM(bna_tx_sm_stat_clr_wait), BNA_TX_STAT_CLR_WAIT},
+};
+
+static void
+bna_tx_sm_stopped_entry(struct bna_tx *tx)
+{
+ struct bna_txq *txq;
+ struct list_head *qe;
+
+ list_for_each(qe, &tx->txq_q) {
+ txq = (struct bna_txq *)qe;
+ (tx->tx_cleanup_cbfn)(tx->bna->bnad, txq->tcb);
+ }
+
+ call_tx_stop_cbfn(tx, BNA_CB_SUCCESS);
+}
+
+static void
+bna_tx_sm_stopped(struct bna_tx *tx, enum bna_tx_event event)
+{
+ switch (event) {
+ case TX_E_START:
+ bfa_fsm_set_state(tx, bna_tx_sm_started);
+ break;
+
+ case TX_E_STOP:
+ bfa_fsm_set_state(tx, bna_tx_sm_stopped);
+ break;
+
+ case TX_E_FAIL:
+ /* No-op */
+ break;
+
+ case TX_E_PRIO_CHANGE:
+ call_tx_prio_change_cbfn(tx, BNA_CB_SUCCESS);
+ break;
+
+ case TX_E_TXQ_STOPPED:
+ /**
+ * This event is received due to flushing of mbox when
+ * device fails
+ */
+ /* No-op */
+ break;
+
+ default:
+ bfa_sm_fault(tx->bna, event);
+ }
+}
+
+static void
+bna_tx_sm_started_entry(struct bna_tx *tx)
+{
+ struct bna_txq *txq;
+ struct list_head *qe;
+
+ __bna_tx_start(tx);
+
+ /* Start IB */
+ list_for_each(qe, &tx->txq_q) {
+ txq = (struct bna_txq *)qe;
+ bna_ib_ack(&txq->ib->door_bell, 0);
+ }
+}
+
+static void
+bna_tx_sm_started(struct bna_tx *tx, enum bna_tx_event event)
+{
+ struct bna_txq *txq;
+ struct list_head *qe;
+
+ switch (event) {
+ case TX_E_STOP:
+ bfa_fsm_set_state(tx, bna_tx_sm_txq_stop_wait);
+ __bna_tx_stop(tx);
+ break;
+
+ case TX_E_FAIL:
+ list_for_each(qe, &tx->txq_q) {
+ txq = (struct bna_txq *)qe;
+ bna_ib_fail(txq->ib);
+ (tx->tx_stall_cbfn)(tx->bna->bnad, txq->tcb);
+ }
+ bfa_fsm_set_state(tx, bna_tx_sm_stopped);
+ break;
+
+ case TX_E_PRIO_CHANGE:
+ bfa_fsm_set_state(tx, bna_tx_sm_prio_stop_wait);
+ break;
+
+ default:
+ bfa_sm_fault(tx->bna, event);
+ }
+}
+
+static void
+bna_tx_sm_txq_stop_wait_entry(struct bna_tx *tx)
+{
+}
+
+static void
+bna_tx_sm_txq_stop_wait(struct bna_tx *tx, enum bna_tx_event event)
+{
+ struct bna_txq *txq;
+ struct list_head *qe;
+
+ switch (event) {
+ case TX_E_FAIL:
+ bfa_fsm_set_state(tx, bna_tx_sm_stopped);
+ break;
+
+ case TX_E_TXQ_STOPPED:
+ list_for_each(qe, &tx->txq_q) {
+ txq = (struct bna_txq *)qe;
+ bna_ib_stop(txq->ib);
+ }
+ bfa_fsm_set_state(tx, bna_tx_sm_stat_clr_wait);
+ break;
+
+ case TX_E_PRIO_CHANGE:
+ /* No-op */
+ break;
+
+ default:
+ bfa_sm_fault(tx->bna, event);
+ }
+}
+
+static void
+bna_tx_sm_prio_stop_wait_entry(struct bna_tx *tx)
+{
+ __bna_tx_stop(tx);
+}
+
+static void
+bna_tx_sm_prio_stop_wait(struct bna_tx *tx, enum bna_tx_event event)
+{
+ struct bna_txq *txq;
+ struct list_head *qe;
+
+ switch (event) {
+ case TX_E_STOP:
+ bfa_fsm_set_state(tx, bna_tx_sm_txq_stop_wait);
+ break;
+
+ case TX_E_FAIL:
+ call_tx_prio_change_cbfn(tx, BNA_CB_FAIL);
+ bfa_fsm_set_state(tx, bna_tx_sm_stopped);
+ break;
+
+ case TX_E_TXQ_STOPPED:
+ list_for_each(qe, &tx->txq_q) {
+ txq = (struct bna_txq *)qe;
+ bna_ib_stop(txq->ib);
+ (tx->tx_cleanup_cbfn)(tx->bna->bnad, txq->tcb);
+ }
+ call_tx_prio_change_cbfn(tx, BNA_CB_SUCCESS);
+ bfa_fsm_set_state(tx, bna_tx_sm_started);
+ break;
+
+ case TX_E_PRIO_CHANGE:
+ /* No-op */
+ break;
+
+ default:
+ bfa_sm_fault(tx->bna, event);
+ }
+}
+
+static void
+bna_tx_sm_stat_clr_wait_entry(struct bna_tx *tx)
+{
+ __bna_txf_stat_clr(tx);
+}
+
+static void
+bna_tx_sm_stat_clr_wait(struct bna_tx *tx, enum bna_tx_event event)
+{
+ switch (event) {
+ case TX_E_FAIL:
+ case TX_E_STAT_CLEARED:
+ bfa_fsm_set_state(tx, bna_tx_sm_stopped);
+ break;
+
+ default:
+ bfa_sm_fault(tx->bna, event);
+ }
+}
+
+static void
+__bna_txq_start(struct bna_tx *tx, struct bna_txq *txq)
+{
+ struct bna_rxtx_q_mem *q_mem;
+ struct bna_txq_mem txq_cfg;
+ struct bna_txq_mem *txq_mem;
+ struct bna_dma_addr cur_q_addr;
+ u32 pg_num;
+ void __iomem *base_addr;
+ unsigned long off;
+
+ /* Fill out structure, to be subsequently written to hardware */
+ txq_cfg.pg_tbl_addr_lo = txq->qpt.hw_qpt_ptr.lsb;
+ txq_cfg.pg_tbl_addr_hi = txq->qpt.hw_qpt_ptr.msb;
+ cur_q_addr = *((struct bna_dma_addr *)(txq->qpt.kv_qpt_ptr));
+ txq_cfg.cur_q_entry_lo = cur_q_addr.lsb;
+ txq_cfg.cur_q_entry_hi = cur_q_addr.msb;
+
+ txq_cfg.pg_cnt_n_prd_ptr = (txq->qpt.page_count << 16) | 0x0;
+
+ txq_cfg.entry_n_pg_size = ((u32)(BFI_TXQ_WI_SIZE >> 2) << 16) |
+ (txq->qpt.page_size >> 2);
+ txq_cfg.int_blk_n_cns_ptr = ((((u32)txq->ib_seg_offset) << 24) |
+ ((u32)(txq->ib->ib_id & 0xff) << 16) | 0x0);
+
+ txq_cfg.cns_ptr2_n_q_state = BNA_Q_IDLE_STATE;
+ txq_cfg.nxt_qid_n_fid_n_pri = (((tx->txf.txf_id & 0x3f) << 3) |
+ (txq->priority & 0x3));
+ txq_cfg.wvc_n_cquota_n_rquota =
+ ((((u32)BFI_TX_MAX_WRR_QUOTA & 0xfff) << 12) |
+ (BFI_TX_MAX_WRR_QUOTA & 0xfff));
+
+ /* Setup the page and write to H/W */
+
+ pg_num = BNA_GET_PAGE_NUM(HQM0_BLK_PG_NUM + tx->bna->port_num,
+ HQM_RXTX_Q_RAM_BASE_OFFSET);
+ writel(pg_num, tx->bna->regs.page_addr);
+
+ base_addr = BNA_GET_MEM_BASE_ADDR(tx->bna->pcidev.pci_bar_kva,
+ HQM_RXTX_Q_RAM_BASE_OFFSET);
+ q_mem = (struct bna_rxtx_q_mem *)0;
+ txq_mem = &q_mem[txq->txq_id].txq;
+
+ /*
+ * The following 4 lines, is a hack b'cos the H/W needs to read
+ * these DMA addresses as little endian
+ */
+
+ off = (unsigned long)&txq_mem->pg_tbl_addr_lo;
+ writel(htonl(txq_cfg.pg_tbl_addr_lo), base_addr + off);
+
+ off = (unsigned long)&txq_mem->pg_tbl_addr_hi;
+ writel(htonl(txq_cfg.pg_tbl_addr_hi), base_addr + off);
+
+ off = (unsigned long)&txq_mem->cur_q_entry_lo;
+ writel(htonl(txq_cfg.cur_q_entry_lo), base_addr + off);
+
+ off = (unsigned long)&txq_mem->cur_q_entry_hi;
+ writel(htonl(txq_cfg.cur_q_entry_hi), base_addr + off);
+
+ off = (unsigned long)&txq_mem->pg_cnt_n_prd_ptr;
+ writel(txq_cfg.pg_cnt_n_prd_ptr, base_addr + off);
+
+ off = (unsigned long)&txq_mem->entry_n_pg_size;
+ writel(txq_cfg.entry_n_pg_size, base_addr + off);
+
+ off = (unsigned long)&txq_mem->int_blk_n_cns_ptr;
+ writel(txq_cfg.int_blk_n_cns_ptr, base_addr + off);
+
+ off = (unsigned long)&txq_mem->cns_ptr2_n_q_state;
+ writel(txq_cfg.cns_ptr2_n_q_state, base_addr + off);
+
+ off = (unsigned long)&txq_mem->nxt_qid_n_fid_n_pri;
+ writel(txq_cfg.nxt_qid_n_fid_n_pri, base_addr + off);
+
+ off = (unsigned long)&txq_mem->wvc_n_cquota_n_rquota;
+ writel(txq_cfg.wvc_n_cquota_n_rquota, base_addr + off);
+
+ txq->tcb->producer_index = 0;
+ txq->tcb->consumer_index = 0;
+ *(txq->tcb->hw_consumer_index) = 0;
+
+}
+
+static void
+__bna_txq_stop(struct bna_tx *tx, struct bna_txq *txq)
+{
+ struct bfi_ll_q_stop_req ll_req;
+ u32 bit_mask[2] = {0, 0};
+ if (txq->txq_id < 32)
+ bit_mask[0] = (u32)1 << txq->txq_id;
+ else
+ bit_mask[1] = (u32)1 << (txq->txq_id - 32);
+
+ memset(&ll_req, 0, sizeof(ll_req));
+ ll_req.mh.msg_class = BFI_MC_LL;
+ ll_req.mh.msg_id = BFI_LL_H2I_TXQ_STOP_REQ;
+ ll_req.mh.mtag.h2i.lpu_id = 0;
+ ll_req.q_id_mask[0] = htonl(bit_mask[0]);
+ ll_req.q_id_mask[1] = htonl(bit_mask[1]);
+
+ bna_mbox_qe_fill(&tx->mbox_qe, &ll_req, sizeof(ll_req),
+ bna_tx_cb_txq_stopped, tx);
+
+ bna_mbox_send(tx->bna, &tx->mbox_qe);
+}
+
+static void
+__bna_txf_start(struct bna_tx *tx)
+{
+ struct bna_tx_fndb_ram *tx_fndb;
+ struct bna_txf *txf = &tx->txf;
+ void __iomem *base_addr;
+ unsigned long off;
+
+ writel(BNA_GET_PAGE_NUM(LUT0_MEM_BLK_BASE_PG_NUM +
+ (tx->bna->port_num * 2), TX_FNDB_RAM_BASE_OFFSET),
+ tx->bna->regs.page_addr);
+
+ base_addr = BNA_GET_MEM_BASE_ADDR(tx->bna->pcidev.pci_bar_kva,
+ TX_FNDB_RAM_BASE_OFFSET);
+
+ tx_fndb = (struct bna_tx_fndb_ram *)0;
+ off = (unsigned long)&tx_fndb[txf->txf_id].vlan_n_ctrl_flags;
+
+ writel(((u32)txf->vlan << 16) | txf->ctrl_flags,
+ base_addr + off);
+
+ if (tx->txf.txf_id < 32)
+ tx->bna->tx_mod.txf_bmap[0] |= ((u32)1 << tx->txf.txf_id);
+ else
+ tx->bna->tx_mod.txf_bmap[1] |= ((u32)
+ 1 << (tx->txf.txf_id - 32));
+}
+
+static void
+__bna_txf_stop(struct bna_tx *tx)
+{
+ struct bna_tx_fndb_ram *tx_fndb;
+ u32 page_num;
+ u32 ctl_flags;
+ struct bna_txf *txf = &tx->txf;
+ void __iomem *base_addr;
+ unsigned long off;
+
+ /* retrieve the running txf_flags & turn off enable bit */
+ page_num = BNA_GET_PAGE_NUM(LUT0_MEM_BLK_BASE_PG_NUM +
+ (tx->bna->port_num * 2), TX_FNDB_RAM_BASE_OFFSET);
+ writel(page_num, tx->bna->regs.page_addr);
+
+ base_addr = BNA_GET_MEM_BASE_ADDR(tx->bna->pcidev.pci_bar_kva,
+ TX_FNDB_RAM_BASE_OFFSET);
+ tx_fndb = (struct bna_tx_fndb_ram *)0;
+ off = (unsigned long)&tx_fndb[txf->txf_id].vlan_n_ctrl_flags;
+
+ ctl_flags = readl(base_addr + off);
+ ctl_flags &= ~BFI_TXF_CF_ENABLE;
+
+ writel(ctl_flags, base_addr + off);
+
+ if (tx->txf.txf_id < 32)
+ tx->bna->tx_mod.txf_bmap[0] &= ~((u32)1 << tx->txf.txf_id);
+ else
+ tx->bna->tx_mod.txf_bmap[0] &= ~((u32)
+ 1 << (tx->txf.txf_id - 32));
+}
+
+static void
+__bna_txf_stat_clr(struct bna_tx *tx)
+{
+ struct bfi_ll_stats_req ll_req;
+ u32 txf_bmap[2] = {0, 0};
+ if (tx->txf.txf_id < 32)
+ txf_bmap[0] = ((u32)1 << tx->txf.txf_id);
+ else
+ txf_bmap[1] = ((u32)1 << (tx->txf.txf_id - 32));
+ bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_STATS_CLEAR_REQ, 0);
+ ll_req.stats_mask = 0;
+ ll_req.rxf_id_mask[0] = 0;
+ ll_req.rxf_id_mask[1] = 0;
+ ll_req.txf_id_mask[0] = htonl(txf_bmap[0]);
+ ll_req.txf_id_mask[1] = htonl(txf_bmap[1]);
+
+ bna_mbox_qe_fill(&tx->mbox_qe, &ll_req, sizeof(ll_req),
+ bna_tx_cb_stats_cleared, tx);
+ bna_mbox_send(tx->bna, &tx->mbox_qe);
+}
+
+static void
+__bna_tx_start(struct bna_tx *tx)
+{
+ struct bna_txq *txq;
+ struct list_head *qe;
+
+ list_for_each(qe, &tx->txq_q) {
+ txq = (struct bna_txq *)qe;
+ bna_ib_start(txq->ib);
+ __bna_txq_start(tx, txq);
+ }
+
+ __bna_txf_start(tx);
+
+ list_for_each(qe, &tx->txq_q) {
+ txq = (struct bna_txq *)qe;
+ txq->tcb->priority = txq->priority;
+ (tx->tx_resume_cbfn)(tx->bna->bnad, txq->tcb);
+ }
+}
+
+static void
+__bna_tx_stop(struct bna_tx *tx)
+{
+ struct bna_txq *txq;
+ struct list_head *qe;
+
+ list_for_each(qe, &tx->txq_q) {
+ txq = (struct bna_txq *)qe;
+ (tx->tx_stall_cbfn)(tx->bna->bnad, txq->tcb);
+ }
+
+ __bna_txf_stop(tx);
+
+ list_for_each(qe, &tx->txq_q) {
+ txq = (struct bna_txq *)qe;
+ bfa_wc_up(&tx->txq_stop_wc);
+ }
+
+ list_for_each(qe, &tx->txq_q) {
+ txq = (struct bna_txq *)qe;
+ __bna_txq_stop(tx, txq);
+ }
+}
+
+static void
+bna_txq_qpt_setup(struct bna_txq *txq, int page_count, int page_size,
+ struct bna_mem_descr *qpt_mem,
+ struct bna_mem_descr *swqpt_mem,
+ struct bna_mem_descr *page_mem)
+{
+ int i;
+
+ txq->qpt.hw_qpt_ptr.lsb = qpt_mem->dma.lsb;
+ txq->qpt.hw_qpt_ptr.msb = qpt_mem->dma.msb;
+ txq->qpt.kv_qpt_ptr = qpt_mem->kva;
+ txq->qpt.page_count = page_count;
+ txq->qpt.page_size = page_size;
+
+ txq->tcb->sw_qpt = (void **) swqpt_mem->kva;
+
+ for (i = 0; i < page_count; i++) {
+ txq->tcb->sw_qpt[i] = page_mem[i].kva;
+
+ ((struct bna_dma_addr *)txq->qpt.kv_qpt_ptr)[i].lsb =
+ page_mem[i].dma.lsb;
+ ((struct bna_dma_addr *)txq->qpt.kv_qpt_ptr)[i].msb =
+ page_mem[i].dma.msb;
+
+ }
+}
+
+static void
+bna_tx_free(struct bna_tx *tx)
+{
+ struct bna_tx_mod *tx_mod = &tx->bna->tx_mod;
+ struct bna_txq *txq;
+ struct bna_ib_mod *ib_mod = &tx->bna->ib_mod;
+ struct list_head *qe;
+
+ while (!list_empty(&tx->txq_q)) {
+ bfa_q_deq(&tx->txq_q, &txq);
+ bfa_q_qe_init(&txq->qe);
+ if (txq->ib) {
+ if (txq->ib_seg_offset != -1)
+ bna_ib_release_idx(txq->ib,
+ txq->ib_seg_offset);
+ bna_ib_put(ib_mod, txq->ib);
+ txq->ib = NULL;
+ }
+ txq->tcb = NULL;
+ txq->tx = NULL;
+ list_add_tail(&txq->qe, &tx_mod->txq_free_q);
+ }
+
+ list_for_each(qe, &tx_mod->tx_active_q) {
+ if (qe == &tx->qe) {
+ list_del(&tx->qe);
+ bfa_q_qe_init(&tx->qe);
+ break;
+ }
+ }
+
+ tx->bna = NULL;
+ tx->priv = NULL;
+ list_add_tail(&tx->qe, &tx_mod->tx_free_q);
+}
+
+static void
+bna_tx_cb_txq_stopped(void *arg, int status)
+{
+ struct bna_tx *tx = (struct bna_tx *)arg;
+
+ bfa_q_qe_init(&tx->mbox_qe.qe);
+ bfa_wc_down(&tx->txq_stop_wc);
+}
+
+static void
+bna_tx_cb_txq_stopped_all(void *arg)
+{
+ struct bna_tx *tx = (struct bna_tx *)arg;
+
+ bfa_fsm_send_event(tx, TX_E_TXQ_STOPPED);
+}
+
+static void
+bna_tx_cb_stats_cleared(void *arg, int status)
+{
+ struct bna_tx *tx = (struct bna_tx *)arg;
+
+ bfa_q_qe_init(&tx->mbox_qe.qe);
+
+ bfa_fsm_send_event(tx, TX_E_STAT_CLEARED);
+}
+
+static void
+bna_tx_start(struct bna_tx *tx)
+{
+ tx->flags |= BNA_TX_F_PORT_STARTED;
+ if (tx->flags & BNA_TX_F_ENABLED)
+ bfa_fsm_send_event(tx, TX_E_START);
+}
+
+static void
+bna_tx_stop(struct bna_tx *tx)
+{
+ tx->stop_cbfn = bna_tx_mod_cb_tx_stopped;
+ tx->stop_cbarg = &tx->bna->tx_mod;
+
+ tx->flags &= ~BNA_TX_F_PORT_STARTED;
+ bfa_fsm_send_event(tx, TX_E_STOP);
+}
+
+static void
+bna_tx_fail(struct bna_tx *tx)
+{
+ tx->flags &= ~BNA_TX_F_PORT_STARTED;
+ bfa_fsm_send_event(tx, TX_E_FAIL);
+}
+
+static void
+bna_tx_prio_changed(struct bna_tx *tx, int prio)
+{
+ struct bna_txq *txq;
+ struct list_head *qe;
+
+ list_for_each(qe, &tx->txq_q) {
+ txq = (struct bna_txq *)qe;
+ txq->priority = prio;
+ }
+
+ bfa_fsm_send_event(tx, TX_E_PRIO_CHANGE);
+}
+
+static void
+bna_tx_cee_link_status(struct bna_tx *tx, int cee_link)
+{
+ if (cee_link)
+ tx->flags |= BNA_TX_F_PRIO_LOCK;
+ else
+ tx->flags &= ~BNA_TX_F_PRIO_LOCK;
+}
+
+static void
+bna_tx_mod_cb_tx_stopped(void *arg, struct bna_tx *tx,
+ enum bna_cb_status status)
+{
+ struct bna_tx_mod *tx_mod = (struct bna_tx_mod *)arg;
+
+ bfa_wc_down(&tx_mod->tx_stop_wc);
+}
+
+static void
+bna_tx_mod_cb_tx_stopped_all(void *arg)
+{
+ struct bna_tx_mod *tx_mod = (struct bna_tx_mod *)arg;
+
+ if (tx_mod->stop_cbfn)
+ tx_mod->stop_cbfn(&tx_mod->bna->port, BNA_CB_SUCCESS);
+ tx_mod->stop_cbfn = NULL;
+}
+
+void
+bna_tx_res_req(int num_txq, int txq_depth, struct bna_res_info *res_info)
+{
+ u32 q_size;
+ u32 page_count;
+ struct bna_mem_info *mem_info;
+
+ res_info[BNA_TX_RES_MEM_T_TCB].res_type = BNA_RES_T_MEM;
+ mem_info = &res_info[BNA_TX_RES_MEM_T_TCB].res_u.mem_info;
+ mem_info->mem_type = BNA_MEM_T_KVA;
+ mem_info->len = sizeof(struct bna_tcb);
+ mem_info->num = num_txq;
+
+ q_size = txq_depth * BFI_TXQ_WI_SIZE;
+ q_size = ALIGN(q_size, PAGE_SIZE);
+ page_count = q_size >> PAGE_SHIFT;
+
+ res_info[BNA_TX_RES_MEM_T_QPT].res_type = BNA_RES_T_MEM;
+ mem_info = &res_info[BNA_TX_RES_MEM_T_QPT].res_u.mem_info;
+ mem_info->mem_type = BNA_MEM_T_DMA;
+ mem_info->len = page_count * sizeof(struct bna_dma_addr);
+ mem_info->num = num_txq;
+
+ res_info[BNA_TX_RES_MEM_T_SWQPT].res_type = BNA_RES_T_MEM;
+ mem_info = &res_info[BNA_TX_RES_MEM_T_SWQPT].res_u.mem_info;
+ mem_info->mem_type = BNA_MEM_T_KVA;
+ mem_info->len = page_count * sizeof(void *);
+ mem_info->num = num_txq;
+
+ res_info[BNA_TX_RES_MEM_T_PAGE].res_type = BNA_RES_T_MEM;
+ mem_info = &res_info[BNA_TX_RES_MEM_T_PAGE].res_u.mem_info;
+ mem_info->mem_type = BNA_MEM_T_DMA;
+ mem_info->len = PAGE_SIZE;
+ mem_info->num = num_txq * page_count;
+
+ res_info[BNA_TX_RES_INTR_T_TXCMPL].res_type = BNA_RES_T_INTR;
+ res_info[BNA_TX_RES_INTR_T_TXCMPL].res_u.intr_info.intr_type =
+ BNA_INTR_T_MSIX;
+ res_info[BNA_TX_RES_INTR_T_TXCMPL].res_u.intr_info.num = num_txq;
+}
+
+struct bna_tx *
+bna_tx_create(struct bna *bna, struct bnad *bnad,
+ struct bna_tx_config *tx_cfg,
+ struct bna_tx_event_cbfn *tx_cbfn,
+ struct bna_res_info *res_info, void *priv)
+{
+ struct bna_intr_info *intr_info;
+ struct bna_tx_mod *tx_mod = &bna->tx_mod;
+ struct bna_tx *tx;
+ struct bna_txq *txq;
+ struct list_head *qe;
+ struct bna_ib_mod *ib_mod = &bna->ib_mod;
+ struct bna_doorbell_qset *qset;
+ struct bna_ib_config ib_config;
+ int page_count;
+ int page_size;
+ int page_idx;
+ int i;
+ unsigned long off;
+
+ intr_info = &res_info[BNA_TX_RES_INTR_T_TXCMPL].res_u.intr_info;
+ page_count = (res_info[BNA_TX_RES_MEM_T_PAGE].res_u.mem_info.num) /
+ tx_cfg->num_txq;
+ page_size = res_info[BNA_TX_RES_MEM_T_PAGE].res_u.mem_info.len;
+
+ /**
+ * Get resources
+ */
+
+ if ((intr_info->num != 1) && (intr_info->num != tx_cfg->num_txq))
+ return NULL;
+
+ /* Tx */
+
+ if (list_empty(&tx_mod->tx_free_q))
+ return NULL;
+ bfa_q_deq(&tx_mod->tx_free_q, &tx);
+ bfa_q_qe_init(&tx->qe);
+
+ /* TxQs */
+
+ INIT_LIST_HEAD(&tx->txq_q);
+ for (i = 0; i < tx_cfg->num_txq; i++) {
+ if (list_empty(&tx_mod->txq_free_q))
+ goto err_return;
+
+ bfa_q_deq(&tx_mod->txq_free_q, &txq);
+ bfa_q_qe_init(&txq->qe);
+ list_add_tail(&txq->qe, &tx->txq_q);
+ txq->ib = NULL;
+ txq->ib_seg_offset = -1;
+ txq->tx = tx;
+ }
+
+ /* IBs */
+ i = 0;
+ list_for_each(qe, &tx->txq_q) {
+ txq = (struct bna_txq *)qe;
+
+ if (intr_info->num == 1)
+ txq->ib = bna_ib_get(ib_mod, intr_info->intr_type,
+ intr_info->idl[0].vector);
+ else
+ txq->ib = bna_ib_get(ib_mod, intr_info->intr_type,
+ intr_info->idl[i].vector);
+
+ if (txq->ib == NULL)
+ goto err_return;
+
+ txq->ib_seg_offset = bna_ib_reserve_idx(txq->ib);
+ if (txq->ib_seg_offset == -1)
+ goto err_return;
+
+ i++;
+ }
+
+ /*
+ * Initialize
+ */
+
+ /* Tx */
+
+ tx->tcb_setup_cbfn = tx_cbfn->tcb_setup_cbfn;
+ tx->tcb_destroy_cbfn = tx_cbfn->tcb_destroy_cbfn;
+ /* Following callbacks are mandatory */
+ tx->tx_stall_cbfn = tx_cbfn->tx_stall_cbfn;
+ tx->tx_resume_cbfn = tx_cbfn->tx_resume_cbfn;
+ tx->tx_cleanup_cbfn = tx_cbfn->tx_cleanup_cbfn;
+
+ list_add_tail(&tx->qe, &tx_mod->tx_active_q);
+ tx->bna = bna;
+ tx->priv = priv;
+ tx->txq_stop_wc.wc_resume = bna_tx_cb_txq_stopped_all;
+ tx->txq_stop_wc.wc_cbarg = tx;
+ tx->txq_stop_wc.wc_count = 0;
+
+ tx->type = tx_cfg->tx_type;
+
+ tx->flags = 0;
+ if (tx->bna->tx_mod.flags & BNA_TX_MOD_F_PORT_STARTED) {
+ switch (tx->type) {
+ case BNA_TX_T_REGULAR:
+ if (!(tx->bna->tx_mod.flags &
+ BNA_TX_MOD_F_PORT_LOOPBACK))
+ tx->flags |= BNA_TX_F_PORT_STARTED;
+ break;
+ case BNA_TX_T_LOOPBACK:
+ if (tx->bna->tx_mod.flags & BNA_TX_MOD_F_PORT_LOOPBACK)
+ tx->flags |= BNA_TX_F_PORT_STARTED;
+ break;
+ }
+ }
+ if (tx->bna->tx_mod.cee_link)
+ tx->flags |= BNA_TX_F_PRIO_LOCK;
+
+ /* TxQ */
+
+ i = 0;
+ page_idx = 0;
+ list_for_each(qe, &tx->txq_q) {
+ txq = (struct bna_txq *)qe;
+ txq->priority = tx_mod->priority;
+ txq->tcb = (struct bna_tcb *)
+ res_info[BNA_TX_RES_MEM_T_TCB].res_u.mem_info.mdl[i].kva;
+ txq->tx_packets = 0;
+ txq->tx_bytes = 0;
+
+ /* IB */
+
+ ib_config.coalescing_timeo = BFI_TX_COALESCING_TIMEO;
+ ib_config.interpkt_timeo = 0; /* Not used */
+ ib_config.interpkt_count = BFI_TX_INTERPKT_COUNT;
+ ib_config.ctrl_flags = (BFI_IB_CF_INTER_PKT_DMA |
+ BFI_IB_CF_INT_ENABLE |
+ BFI_IB_CF_COALESCING_MODE);
+ bna_ib_config(txq->ib, &ib_config);
+
+ /* TCB */
+
+ txq->tcb->producer_index = 0;
+ txq->tcb->consumer_index = 0;
+ txq->tcb->hw_consumer_index = (volatile u32 *)
+ ((volatile u8 *)txq->ib->ib_seg_host_addr_kva +
+ (txq->ib_seg_offset * BFI_IBIDX_SIZE));
+ *(txq->tcb->hw_consumer_index) = 0;
+ txq->tcb->q_depth = tx_cfg->txq_depth;
+ txq->tcb->unmap_q = (void *)
+ res_info[BNA_TX_RES_MEM_T_UNMAPQ].res_u.mem_info.mdl[i].kva;
+ qset = (struct bna_doorbell_qset *)0;
+ off = (unsigned long)&qset[txq->txq_id].txq[0];
+ txq->tcb->q_dbell = off +
+ BNA_GET_DOORBELL_BASE_ADDR(bna->pcidev.pci_bar_kva);
+ txq->tcb->i_dbell = &txq->ib->door_bell;
+ txq->tcb->intr_type = intr_info->intr_type;
+ txq->tcb->intr_vector = (intr_info->num == 1) ?
+ intr_info->idl[0].vector :
+ intr_info->idl[i].vector;
+ txq->tcb->txq = txq;
+ txq->tcb->bnad = bnad;
+ txq->tcb->id = i;
+
+ /* QPT, SWQPT, Pages */
+ bna_txq_qpt_setup(txq, page_count, page_size,
+ &res_info[BNA_TX_RES_MEM_T_QPT].res_u.mem_info.mdl[i],
+ &res_info[BNA_TX_RES_MEM_T_SWQPT].res_u.mem_info.mdl[i],
+ &res_info[BNA_TX_RES_MEM_T_PAGE].
+ res_u.mem_info.mdl[page_idx]);
+ txq->tcb->page_idx = page_idx;
+ txq->tcb->page_count = page_count;
+ page_idx += page_count;
+
+ /* Callback to bnad for setting up TCB */
+ if (tx->tcb_setup_cbfn)
+ (tx->tcb_setup_cbfn)(bna->bnad, txq->tcb);
+
+ i++;
+ }
+
+ /* TxF */
+
+ tx->txf.ctrl_flags = BFI_TXF_CF_ENABLE | BFI_TXF_CF_VLAN_WI_BASED;
+ tx->txf.vlan = 0;
+
+ /* Mbox element */
+ bfa_q_qe_init(&tx->mbox_qe.qe);
+
+ bfa_fsm_set_state(tx, bna_tx_sm_stopped);
+
+ return tx;
+
+err_return:
+ bna_tx_free(tx);
+ return NULL;
+}
+
+void
+bna_tx_destroy(struct bna_tx *tx)
+{
+ /* Callback to bnad for destroying TCB */
+ if (tx->tcb_destroy_cbfn) {
+ struct bna_txq *txq;
+ struct list_head *qe;
+
+ list_for_each(qe, &tx->txq_q) {
+ txq = (struct bna_txq *)qe;
+ (tx->tcb_destroy_cbfn)(tx->bna->bnad, txq->tcb);
+ }
+ }
+
+ bna_tx_free(tx);
+}
+
+void
+bna_tx_enable(struct bna_tx *tx)
+{
+ if (tx->fsm != (bfa_sm_t)bna_tx_sm_stopped)
+ return;
+
+ tx->flags |= BNA_TX_F_ENABLED;
+
+ if (tx->flags & BNA_TX_F_PORT_STARTED)
+ bfa_fsm_send_event(tx, TX_E_START);
+}
+
+void
+bna_tx_disable(struct bna_tx *tx, enum bna_cleanup_type type,
+ void (*cbfn)(void *, struct bna_tx *, enum bna_cb_status))
+{
+ if (type == BNA_SOFT_CLEANUP) {
+ (*cbfn)(tx->bna->bnad, tx, BNA_CB_SUCCESS);
+ return;
+ }
+
+ tx->stop_cbfn = cbfn;
+ tx->stop_cbarg = tx->bna->bnad;
+
+ tx->flags &= ~BNA_TX_F_ENABLED;
+
+ bfa_fsm_send_event(tx, TX_E_STOP);
+}
+
+int
+bna_tx_state_get(struct bna_tx *tx)
+{
+ return bfa_sm_to_state(tx_sm_table, tx->fsm);
+}
+
+void
+bna_tx_mod_init(struct bna_tx_mod *tx_mod, struct bna *bna,
+ struct bna_res_info *res_info)
+{
+ int i;
+
+ tx_mod->bna = bna;
+ tx_mod->flags = 0;
+
+ tx_mod->tx = (struct bna_tx *)
+ res_info[BNA_RES_MEM_T_TX_ARRAY].res_u.mem_info.mdl[0].kva;
+ tx_mod->txq = (struct bna_txq *)
+ res_info[BNA_RES_MEM_T_TXQ_ARRAY].res_u.mem_info.mdl[0].kva;
+
+ INIT_LIST_HEAD(&tx_mod->tx_free_q);
+ INIT_LIST_HEAD(&tx_mod->tx_active_q);
+
+ INIT_LIST_HEAD(&tx_mod->txq_free_q);
+
+ for (i = 0; i < BFI_MAX_TXQ; i++) {
+ tx_mod->tx[i].txf.txf_id = i;
+ bfa_q_qe_init(&tx_mod->tx[i].qe);
+ list_add_tail(&tx_mod->tx[i].qe, &tx_mod->tx_free_q);
+
+ tx_mod->txq[i].txq_id = i;
+ bfa_q_qe_init(&tx_mod->txq[i].qe);
+ list_add_tail(&tx_mod->txq[i].qe, &tx_mod->txq_free_q);
+ }
+
+ tx_mod->tx_stop_wc.wc_resume = bna_tx_mod_cb_tx_stopped_all;
+ tx_mod->tx_stop_wc.wc_cbarg = tx_mod;
+ tx_mod->tx_stop_wc.wc_count = 0;
+}
+
+void
+bna_tx_mod_uninit(struct bna_tx_mod *tx_mod)
+{
+ struct list_head *qe;
+ int i;
+
+ i = 0;
+ list_for_each(qe, &tx_mod->tx_free_q)
+ i++;
+
+ i = 0;
+ list_for_each(qe, &tx_mod->txq_free_q)
+ i++;
+
+ tx_mod->bna = NULL;
+}
+
+void
+bna_tx_mod_start(struct bna_tx_mod *tx_mod, enum bna_tx_type type)
+{
+ struct bna_tx *tx;
+ struct list_head *qe;
+
+ tx_mod->flags |= BNA_TX_MOD_F_PORT_STARTED;
+ if (type == BNA_TX_T_LOOPBACK)
+ tx_mod->flags |= BNA_TX_MOD_F_PORT_LOOPBACK;
+
+ list_for_each(qe, &tx_mod->tx_active_q) {
+ tx = (struct bna_tx *)qe;
+ if (tx->type == type)
+ bna_tx_start(tx);
+ }
+}
+
+void
+bna_tx_mod_stop(struct bna_tx_mod *tx_mod, enum bna_tx_type type)
+{
+ struct bna_tx *tx;
+ struct list_head *qe;
+
+ tx_mod->flags &= ~BNA_TX_MOD_F_PORT_STARTED;
+ tx_mod->flags &= ~BNA_TX_MOD_F_PORT_LOOPBACK;
+
+ tx_mod->stop_cbfn = bna_port_cb_tx_stopped;
+
+ /**
+ * Before calling bna_tx_stop(), increment tx_stop_wc as many times
+ * as we are going to call bna_tx_stop
+ */
+ list_for_each(qe, &tx_mod->tx_active_q) {
+ tx = (struct bna_tx *)qe;
+ if (tx->type == type)
+ bfa_wc_up(&tx_mod->tx_stop_wc);
+ }
+
+ if (tx_mod->tx_stop_wc.wc_count == 0) {
+ tx_mod->stop_cbfn(&tx_mod->bna->port, BNA_CB_SUCCESS);
+ tx_mod->stop_cbfn = NULL;
+ return;
+ }
+
+ list_for_each(qe, &tx_mod->tx_active_q) {
+ tx = (struct bna_tx *)qe;
+ if (tx->type == type)
+ bna_tx_stop(tx);
+ }
+}
+
+void
+bna_tx_mod_fail(struct bna_tx_mod *tx_mod)
+{
+ struct bna_tx *tx;
+ struct list_head *qe;
+
+ tx_mod->flags &= ~BNA_TX_MOD_F_PORT_STARTED;
+ tx_mod->flags &= ~BNA_TX_MOD_F_PORT_LOOPBACK;
+
+ list_for_each(qe, &tx_mod->tx_active_q) {
+ tx = (struct bna_tx *)qe;
+ bna_tx_fail(tx);
+ }
+}
+
+void
+bna_tx_mod_prio_changed(struct bna_tx_mod *tx_mod, int prio)
+{
+ struct bna_tx *tx;
+ struct list_head *qe;
+
+ if (prio != tx_mod->priority) {
+ tx_mod->priority = prio;
+
+ list_for_each(qe, &tx_mod->tx_active_q) {
+ tx = (struct bna_tx *)qe;
+ bna_tx_prio_changed(tx, prio);
+ }
+ }
+}
+
+void
+bna_tx_mod_cee_link_status(struct bna_tx_mod *tx_mod, int cee_link)
+{
+ struct bna_tx *tx;
+ struct list_head *qe;
+
+ tx_mod->cee_link = cee_link;
+
+ list_for_each(qe, &tx_mod->tx_active_q) {
+ tx = (struct bna_tx *)qe;
+ bna_tx_cee_link_status(tx, cee_link);
+ }
+}
diff --git a/drivers/net/bna/bna_types.h b/drivers/net/bna/bna_types.h
new file mode 100644
index 000000000000..6877310f6ef4
--- /dev/null
+++ b/drivers/net/bna/bna_types.h
@@ -0,0 +1,1128 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+#ifndef __BNA_TYPES_H__
+#define __BNA_TYPES_H__
+
+#include "cna.h"
+#include "bna_hw.h"
+#include "bfa_cee.h"
+
+/**
+ *
+ * Forward declarations
+ *
+ */
+
+struct bna_txq;
+struct bna_tx;
+struct bna_rxq;
+struct bna_cq;
+struct bna_rx;
+struct bna_rxf;
+struct bna_port;
+struct bna;
+struct bnad;
+
+/**
+ *
+ * Enums, primitive data types
+ *
+ */
+
+enum bna_status {
+ BNA_STATUS_T_DISABLED = 0,
+ BNA_STATUS_T_ENABLED = 1
+};
+
+enum bna_cleanup_type {
+ BNA_HARD_CLEANUP = 0,
+ BNA_SOFT_CLEANUP = 1
+};
+
+enum bna_cb_status {
+ BNA_CB_SUCCESS = 0,
+ BNA_CB_FAIL = 1,
+ BNA_CB_INTERRUPT = 2,
+ BNA_CB_BUSY = 3,
+ BNA_CB_INVALID_MAC = 4,
+ BNA_CB_MCAST_LIST_FULL = 5,
+ BNA_CB_UCAST_CAM_FULL = 6,
+ BNA_CB_WAITING = 7,
+ BNA_CB_NOT_EXEC = 8
+};
+
+enum bna_res_type {
+ BNA_RES_T_MEM = 1,
+ BNA_RES_T_INTR = 2
+};
+
+enum bna_mem_type {
+ BNA_MEM_T_KVA = 1,
+ BNA_MEM_T_DMA = 2
+};
+
+enum bna_intr_type {
+ BNA_INTR_T_INTX = 1,
+ BNA_INTR_T_MSIX = 2
+};
+
+enum bna_res_req_type {
+ BNA_RES_MEM_T_COM = 0,
+ BNA_RES_MEM_T_ATTR = 1,
+ BNA_RES_MEM_T_FWTRC = 2,
+ BNA_RES_MEM_T_STATS = 3,
+ BNA_RES_MEM_T_SWSTATS = 4,
+ BNA_RES_MEM_T_IBIDX = 5,
+ BNA_RES_MEM_T_IB_ARRAY = 6,
+ BNA_RES_MEM_T_INTR_ARRAY = 7,
+ BNA_RES_MEM_T_IDXSEG_ARRAY = 8,
+ BNA_RES_MEM_T_TX_ARRAY = 9,
+ BNA_RES_MEM_T_TXQ_ARRAY = 10,
+ BNA_RES_MEM_T_RX_ARRAY = 11,
+ BNA_RES_MEM_T_RXP_ARRAY = 12,
+ BNA_RES_MEM_T_RXQ_ARRAY = 13,
+ BNA_RES_MEM_T_UCMAC_ARRAY = 14,
+ BNA_RES_MEM_T_MCMAC_ARRAY = 15,
+ BNA_RES_MEM_T_RIT_ENTRY = 16,
+ BNA_RES_MEM_T_RIT_SEGMENT = 17,
+ BNA_RES_INTR_T_MBOX = 18,
+ BNA_RES_T_MAX
+};
+
+enum bna_tx_res_req_type {
+ BNA_TX_RES_MEM_T_TCB = 0,
+ BNA_TX_RES_MEM_T_UNMAPQ = 1,
+ BNA_TX_RES_MEM_T_QPT = 2,
+ BNA_TX_RES_MEM_T_SWQPT = 3,
+ BNA_TX_RES_MEM_T_PAGE = 4,
+ BNA_TX_RES_INTR_T_TXCMPL = 5,
+ BNA_TX_RES_T_MAX,
+};
+
+enum bna_rx_mem_type {
+ BNA_RX_RES_MEM_T_CCB = 0, /* CQ context */
+ BNA_RX_RES_MEM_T_RCB = 1, /* CQ context */
+ BNA_RX_RES_MEM_T_UNMAPQ = 2, /* UnmapQ for RxQs */
+ BNA_RX_RES_MEM_T_CQPT = 3, /* CQ QPT */
+ BNA_RX_RES_MEM_T_CSWQPT = 4, /* S/W QPT */
+ BNA_RX_RES_MEM_T_CQPT_PAGE = 5, /* CQPT page */
+ BNA_RX_RES_MEM_T_HQPT = 6, /* RX QPT */
+ BNA_RX_RES_MEM_T_DQPT = 7, /* RX QPT */
+ BNA_RX_RES_MEM_T_HSWQPT = 8, /* RX s/w QPT */
+ BNA_RX_RES_MEM_T_DSWQPT = 9, /* RX s/w QPT */
+ BNA_RX_RES_MEM_T_DPAGE = 10, /* RX s/w QPT */
+ BNA_RX_RES_MEM_T_HPAGE = 11, /* RX s/w QPT */
+ BNA_RX_RES_T_INTR = 12, /* Rx interrupts */
+ BNA_RX_RES_T_MAX = 13
+};
+
+enum bna_mbox_state {
+ BNA_MBOX_FREE = 0,
+ BNA_MBOX_POSTED = 1
+};
+
+enum bna_tx_type {
+ BNA_TX_T_REGULAR = 0,
+ BNA_TX_T_LOOPBACK = 1,
+};
+
+enum bna_tx_flags {
+ BNA_TX_F_PORT_STARTED = 1,
+ BNA_TX_F_ENABLED = 2,
+ BNA_TX_F_PRIO_LOCK = 4,
+};
+
+enum bna_tx_mod_flags {
+ BNA_TX_MOD_F_PORT_STARTED = 1,
+ BNA_TX_MOD_F_PORT_LOOPBACK = 2,
+};
+
+enum bna_rx_type {
+ BNA_RX_T_REGULAR = 0,
+ BNA_RX_T_LOOPBACK = 1,
+};
+
+enum bna_rxp_type {
+ BNA_RXP_SINGLE = 1,
+ BNA_RXP_SLR = 2,
+ BNA_RXP_HDS = 3
+};
+
+enum bna_rxmode {
+ BNA_RXMODE_PROMISC = 1,
+ BNA_RXMODE_DEFAULT = 2,
+ BNA_RXMODE_ALLMULTI = 4
+};
+
+enum bna_rx_event {
+ RX_E_START = 1,
+ RX_E_STOP = 2,
+ RX_E_FAIL = 3,
+ RX_E_RXF_STARTED = 4,
+ RX_E_RXF_STOPPED = 5,
+ RX_E_RXQ_STOPPED = 6,
+};
+
+enum bna_rx_state {
+ BNA_RX_STOPPED = 1,
+ BNA_RX_RXF_START_WAIT = 2,
+ BNA_RX_STARTED = 3,
+ BNA_RX_RXF_STOP_WAIT = 4,
+ BNA_RX_RXQ_STOP_WAIT = 5,
+};
+
+enum bna_rx_flags {
+ BNA_RX_F_ENABLE = 0x01, /* bnad enabled rxf */
+ BNA_RX_F_PORT_ENABLED = 0x02, /* Port object is enabled */
+ BNA_RX_F_PORT_FAILED = 0x04, /* Port in failed state */
+};
+
+enum bna_rx_mod_flags {
+ BNA_RX_MOD_F_PORT_STARTED = 1,
+ BNA_RX_MOD_F_PORT_LOOPBACK = 2,
+};
+
+enum bna_rxf_oper_state {
+ BNA_RXF_OPER_STATE_RUNNING = 0x01, /* rxf operational */
+ BNA_RXF_OPER_STATE_PAUSED = 0x02, /* rxf in PAUSED state */
+};
+
+enum bna_rxf_flags {
+ BNA_RXF_FL_STOP_PENDING = 0x01,
+ BNA_RXF_FL_FAILED = 0x02,
+ BNA_RXF_FL_RSS_CONFIG_PENDING = 0x04,
+ BNA_RXF_FL_OPERSTATE_CHANGED = 0x08,
+ BNA_RXF_FL_RXF_ENABLED = 0x10,
+ BNA_RXF_FL_VLAN_CONFIG_PENDING = 0x20,
+};
+
+enum bna_rxf_event {
+ RXF_E_START = 1,
+ RXF_E_STOP = 2,
+ RXF_E_FAIL = 3,
+ RXF_E_CAM_FLTR_MOD = 4,
+ RXF_E_STARTED = 5,
+ RXF_E_STOPPED = 6,
+ RXF_E_CAM_FLTR_RESP = 7,
+ RXF_E_PAUSE = 8,
+ RXF_E_RESUME = 9,
+ RXF_E_STAT_CLEARED = 10,
+};
+
+enum bna_rxf_state {
+ BNA_RXF_STOPPED = 1,
+ BNA_RXF_START_WAIT = 2,
+ BNA_RXF_CAM_FLTR_MOD_WAIT = 3,
+ BNA_RXF_STARTED = 4,
+ BNA_RXF_CAM_FLTR_CLR_WAIT = 5,
+ BNA_RXF_STOP_WAIT = 6,
+ BNA_RXF_PAUSE_WAIT = 7,
+ BNA_RXF_RESUME_WAIT = 8,
+ BNA_RXF_STAT_CLR_WAIT = 9,
+};
+
+enum bna_port_type {
+ BNA_PORT_T_REGULAR = 0,
+ BNA_PORT_T_LOOPBACK_INTERNAL = 1,
+ BNA_PORT_T_LOOPBACK_EXTERNAL = 2,
+};
+
+enum bna_link_status {
+ BNA_LINK_DOWN = 0,
+ BNA_LINK_UP = 1,
+ BNA_CEE_UP = 2
+};
+
+enum bna_llport_flags {
+ BNA_LLPORT_F_ENABLED = 1,
+ BNA_LLPORT_F_RX_ENABLED = 2
+};
+
+enum bna_port_flags {
+ BNA_PORT_F_DEVICE_READY = 1,
+ BNA_PORT_F_ENABLED = 2,
+ BNA_PORT_F_PAUSE_CHANGED = 4,
+ BNA_PORT_F_MTU_CHANGED = 8
+};
+
+enum bna_pkt_rates {
+ BNA_PKT_RATE_10K = 10000,
+ BNA_PKT_RATE_20K = 20000,
+ BNA_PKT_RATE_30K = 30000,
+ BNA_PKT_RATE_40K = 40000,
+ BNA_PKT_RATE_50K = 50000,
+ BNA_PKT_RATE_60K = 60000,
+ BNA_PKT_RATE_70K = 70000,
+ BNA_PKT_RATE_80K = 80000,
+};
+
+enum bna_dim_load_types {
+ BNA_LOAD_T_HIGH_4 = 0, /* 80K <= r */
+ BNA_LOAD_T_HIGH_3 = 1, /* 60K <= r < 80K */
+ BNA_LOAD_T_HIGH_2 = 2, /* 50K <= r < 60K */
+ BNA_LOAD_T_HIGH_1 = 3, /* 40K <= r < 50K */
+ BNA_LOAD_T_LOW_1 = 4, /* 30K <= r < 40K */
+ BNA_LOAD_T_LOW_2 = 5, /* 20K <= r < 30K */
+ BNA_LOAD_T_LOW_3 = 6, /* 10K <= r < 20K */
+ BNA_LOAD_T_LOW_4 = 7, /* r < 10K */
+ BNA_LOAD_T_MAX = 8
+};
+
+enum bna_dim_bias_types {
+ BNA_BIAS_T_SMALL = 0, /* small pkts > (large pkts * 2) */
+ BNA_BIAS_T_LARGE = 1, /* Not BNA_BIAS_T_SMALL */
+ BNA_BIAS_T_MAX = 2
+};
+
+struct bna_mac {
+ /* This should be the first one */
+ struct list_head qe;
+ u8 addr[ETH_ALEN];
+};
+
+struct bna_mem_descr {
+ u32 len;
+ void *kva;
+ struct bna_dma_addr dma;
+};
+
+struct bna_mem_info {
+ enum bna_mem_type mem_type;
+ u32 len;
+ u32 num;
+ u32 align_sz; /* 0/1 = no alignment */
+ struct bna_mem_descr *mdl;
+ void *cookie; /* For bnad to unmap dma later */
+};
+
+struct bna_intr_descr {
+ int vector;
+};
+
+struct bna_intr_info {
+ enum bna_intr_type intr_type;
+ int num;
+ struct bna_intr_descr *idl;
+};
+
+union bna_res_u {
+ struct bna_mem_info mem_info;
+ struct bna_intr_info intr_info;
+};
+
+struct bna_res_info {
+ enum bna_res_type res_type;
+ union bna_res_u res_u;
+};
+
+/* HW QPT */
+struct bna_qpt {
+ struct bna_dma_addr hw_qpt_ptr;
+ void *kv_qpt_ptr;
+ u32 page_count;
+ u32 page_size;
+};
+
+/**
+ *
+ * Device
+ *
+ */
+
+struct bna_device {
+ bfa_fsm_t fsm;
+ struct bfa_ioc ioc;
+
+ enum bna_intr_type intr_type;
+ int vector;
+
+ void (*ready_cbfn)(struct bnad *bnad, enum bna_cb_status status);
+ struct bnad *ready_cbarg;
+
+ void (*stop_cbfn)(struct bnad *bnad, enum bna_cb_status status);
+ struct bnad *stop_cbarg;
+
+ struct bna *bna;
+};
+
+/**
+ *
+ * Mail box
+ *
+ */
+
+struct bna_mbox_qe {
+ /* This should be the first one */
+ struct list_head qe;
+
+ struct bfa_mbox_cmd cmd;
+ u32 cmd_len;
+ /* Callback for port, tx, rx, rxf */
+ void (*cbfn)(void *arg, int status);
+ void *cbarg;
+};
+
+struct bna_mbox_mod {
+ enum bna_mbox_state state;
+ struct list_head posted_q;
+ u32 msg_pending;
+ u32 msg_ctr;
+ struct bna *bna;
+};
+
+/**
+ *
+ * Port
+ *
+ */
+
+/* Pause configuration */
+struct bna_pause_config {
+ enum bna_status tx_pause;
+ enum bna_status rx_pause;
+};
+
+struct bna_llport {
+ bfa_fsm_t fsm;
+ enum bna_llport_flags flags;
+
+ enum bna_port_type type;
+
+ enum bna_link_status link_status;
+
+ int admin_up_count;
+
+ void (*stop_cbfn)(struct bna_port *, enum bna_cb_status);
+
+ struct bna_mbox_qe mbox_qe;
+
+ struct bna *bna;
+};
+
+struct bna_port {
+ bfa_fsm_t fsm;
+ enum bna_port_flags flags;
+
+ enum bna_port_type type;
+
+ struct bna_llport llport;
+
+ struct bna_pause_config pause_config;
+ u8 priority;
+ int mtu;
+
+ /* Callback for bna_port_disable(), port_stop() */
+ void (*stop_cbfn)(void *, enum bna_cb_status);
+ void *stop_cbarg;
+
+ /* Callback for bna_port_pause_config() */
+ void (*pause_cbfn)(struct bnad *, enum bna_cb_status);
+
+ /* Callback for bna_port_mtu_set() */
+ void (*mtu_cbfn)(struct bnad *, enum bna_cb_status);
+
+ void (*link_cbfn)(struct bnad *, enum bna_link_status);
+
+ struct bfa_wc chld_stop_wc;
+
+ struct bna_mbox_qe mbox_qe;
+
+ struct bna *bna;
+};
+
+/**
+ *
+ * Interrupt Block
+ *
+ */
+
+/* IB index segment structure */
+struct bna_ibidx_seg {
+ /* This should be the first one */
+ struct list_head qe;
+
+ u8 ib_seg_size;
+ u8 ib_idx_tbl_offset;
+};
+
+/* Interrupt structure */
+struct bna_intr {
+ /* This should be the first one */
+ struct list_head qe;
+ int ref_count;
+
+ enum bna_intr_type intr_type;
+ int vector;
+
+ struct bna_ib *ib;
+};
+
+/* Doorbell structure */
+struct bna_ib_dbell {
+ void *__iomem doorbell_addr;
+ u32 doorbell_ack;
+};
+
+/* Interrupt timer configuration */
+struct bna_ib_config {
+ u8 coalescing_timeo; /* Unit is 5usec. */
+
+ int interpkt_count;
+ int interpkt_timeo;
+
+ enum ib_flags ctrl_flags;
+};
+
+/* IB structure */
+struct bna_ib {
+ /* This should be the first one */
+ struct list_head qe;
+
+ int ib_id;
+
+ int ref_count;
+ int start_count;
+
+ struct bna_dma_addr ib_seg_host_addr;
+ void *ib_seg_host_addr_kva;
+ u32 idx_mask; /* Size >= BNA_IBIDX_MAX_SEGSIZE */
+
+ struct bna_ibidx_seg *idx_seg;
+
+ struct bna_ib_dbell door_bell;
+
+ struct bna_intr *intr;
+
+ struct bna_ib_config ib_config;
+
+ struct bna *bna;
+};
+
+/* IB module - keeps track of IBs and interrupts */
+struct bna_ib_mod {
+ struct bna_ib *ib; /* BFI_MAX_IB entries */
+ struct bna_intr *intr; /* BFI_MAX_IB entries */
+ struct bna_ibidx_seg *idx_seg; /* BNA_IBIDX_TOTAL_SEGS */
+
+ struct list_head ib_free_q;
+
+ struct list_head ibidx_seg_pool[BFI_IBIDX_TOTAL_POOLS];
+
+ struct list_head intr_free_q;
+ struct list_head intr_active_q;
+
+ struct bna *bna;
+};
+
+/**
+ *
+ * Tx object
+ *
+ */
+
+/* Tx datapath control structure */
+#define BNA_Q_NAME_SIZE 16
+struct bna_tcb {
+ /* Fast path */
+ void **sw_qpt;
+ void *unmap_q;
+ u32 producer_index;
+ u32 consumer_index;
+ volatile u32 *hw_consumer_index;
+ u32 q_depth;
+ void *__iomem q_dbell;
+ struct bna_ib_dbell *i_dbell;
+ int page_idx;
+ int page_count;
+ /* Control path */
+ struct bna_txq *txq;
+ struct bnad *bnad;
+ enum bna_intr_type intr_type;
+ int intr_vector;
+ u8 priority; /* Current priority */
+ unsigned long flags; /* Used by bnad as required */
+ int id;
+ char name[BNA_Q_NAME_SIZE];
+};
+
+/* TxQ QPT and configuration */
+struct bna_txq {
+ /* This should be the first one */
+ struct list_head qe;
+
+ int txq_id;
+
+ u8 priority;
+
+ struct bna_qpt qpt;
+ struct bna_tcb *tcb;
+ struct bna_ib *ib;
+ int ib_seg_offset;
+
+ struct bna_tx *tx;
+
+ u64 tx_packets;
+ u64 tx_bytes;
+};
+
+/* TxF structure (hardware Tx Function) */
+struct bna_txf {
+ int txf_id;
+ enum txf_flags ctrl_flags;
+ u16 vlan;
+};
+
+/* Tx object */
+struct bna_tx {
+ /* This should be the first one */
+ struct list_head qe;
+
+ bfa_fsm_t fsm;
+ enum bna_tx_flags flags;
+
+ enum bna_tx_type type;
+
+ struct list_head txq_q;
+ struct bna_txf txf;
+
+ /* Tx event handlers */
+ void (*tcb_setup_cbfn)(struct bnad *, struct bna_tcb *);
+ void (*tcb_destroy_cbfn)(struct bnad *, struct bna_tcb *);
+ void (*tx_stall_cbfn)(struct bnad *, struct bna_tcb *);
+ void (*tx_resume_cbfn)(struct bnad *, struct bna_tcb *);
+ void (*tx_cleanup_cbfn)(struct bnad *, struct bna_tcb *);
+
+ /* callback for bna_tx_disable(), bna_tx_stop() */
+ void (*stop_cbfn)(void *arg, struct bna_tx *tx,
+ enum bna_cb_status status);
+ void *stop_cbarg;
+
+ /* callback for bna_tx_prio_set() */
+ void (*prio_change_cbfn)(struct bnad *bnad, struct bna_tx *tx,
+ enum bna_cb_status status);
+
+ struct bfa_wc txq_stop_wc;
+
+ struct bna_mbox_qe mbox_qe;
+
+ struct bna *bna;
+ void *priv; /* bnad's cookie */
+};
+
+struct bna_tx_config {
+ int num_txq;
+ int txq_depth;
+ enum bna_tx_type tx_type;
+};
+
+struct bna_tx_event_cbfn {
+ /* Optional */
+ void (*tcb_setup_cbfn)(struct bnad *, struct bna_tcb *);
+ void (*tcb_destroy_cbfn)(struct bnad *, struct bna_tcb *);
+ /* Mandatory */
+ void (*tx_stall_cbfn)(struct bnad *, struct bna_tcb *);
+ void (*tx_resume_cbfn)(struct bnad *, struct bna_tcb *);
+ void (*tx_cleanup_cbfn)(struct bnad *, struct bna_tcb *);
+};
+
+/* Tx module - keeps track of free, active tx objects */
+struct bna_tx_mod {
+ struct bna_tx *tx; /* BFI_MAX_TXQ entries */
+ struct bna_txq *txq; /* BFI_MAX_TXQ entries */
+
+ struct list_head tx_free_q;
+ struct list_head tx_active_q;
+
+ struct list_head txq_free_q;
+
+ /* callback for bna_tx_mod_stop() */
+ void (*stop_cbfn)(struct bna_port *port,
+ enum bna_cb_status status);
+
+ struct bfa_wc tx_stop_wc;
+
+ enum bna_tx_mod_flags flags;
+
+ int priority;
+ int cee_link;
+
+ u32 txf_bmap[2];
+
+ struct bna *bna;
+};
+
+/**
+ *
+ * Receive Indirection Table
+ *
+ */
+
+/* One row of RIT table */
+struct bna_rit_entry {
+ u8 large_rxq_id; /* used for either large or data buffers */
+ u8 small_rxq_id; /* used for either small or header buffers */
+};
+
+/* RIT segment */
+struct bna_rit_segment {
+ struct list_head qe;
+
+ u32 rit_offset;
+ u32 rit_size;
+ /**
+ * max_rit_size: Varies per RIT segment depending on how RIT is
+ * partitioned
+ */
+ u32 max_rit_size;
+
+ struct bna_rit_entry *rit;
+};
+
+struct bna_rit_mod {
+ struct bna_rit_entry *rit;
+ struct bna_rit_segment *rit_segment;
+
+ struct list_head rit_seg_pool[BFI_RIT_SEG_TOTAL_POOLS];
+};
+
+/**
+ *
+ * Rx object
+ *
+ */
+
+/* Rx datapath control structure */
+struct bna_rcb {
+ /* Fast path */
+ void **sw_qpt;
+ void *unmap_q;
+ u32 producer_index;
+ u32 consumer_index;
+ u32 q_depth;
+ void *__iomem q_dbell;
+ int page_idx;
+ int page_count;
+ /* Control path */
+ struct bna_rxq *rxq;
+ struct bna_cq *cq;
+ struct bnad *bnad;
+ unsigned long flags;
+ int id;
+};
+
+/* RxQ structure - QPT, configuration */
+struct bna_rxq {
+ struct list_head qe;
+ int rxq_id;
+
+ int buffer_size;
+ int q_depth;
+
+ struct bna_qpt qpt;
+ struct bna_rcb *rcb;
+
+ struct bna_rxp *rxp;
+ struct bna_rx *rx;
+
+ u64 rx_packets;
+ u64 rx_bytes;
+ u64 rx_packets_with_error;
+ u64 rxbuf_alloc_failed;
+};
+
+/* RxQ pair */
+union bna_rxq_u {
+ struct {
+ struct bna_rxq *hdr;
+ struct bna_rxq *data;
+ } hds;
+ struct {
+ struct bna_rxq *small;
+ struct bna_rxq *large;
+ } slr;
+ struct {
+ struct bna_rxq *only;
+ struct bna_rxq *reserved;
+ } single;
+};
+
+/* Packet rate for Dynamic Interrupt Moderation */
+struct bna_pkt_rate {
+ u32 small_pkt_cnt;
+ u32 large_pkt_cnt;
+};
+
+/* Completion control structure */
+struct bna_ccb {
+ /* Fast path */
+ void **sw_qpt;
+ u32 producer_index;
+ volatile u32 *hw_producer_index;
+ u32 q_depth;
+ struct bna_ib_dbell *i_dbell;
+ struct bna_rcb *rcb[2];
+ void *ctrl; /* For bnad */
+ struct bna_pkt_rate pkt_rate;
+ int page_idx;
+ int page_count;
+
+ /* Control path */
+ struct bna_cq *cq;
+ struct bnad *bnad;
+ enum bna_intr_type intr_type;
+ int intr_vector;
+ u8 rx_coalescing_timeo; /* For NAPI */
+ int id;
+ char name[BNA_Q_NAME_SIZE];
+};
+
+/* CQ QPT, configuration */
+struct bna_cq {
+ int cq_id;
+
+ struct bna_qpt qpt;
+ struct bna_ccb *ccb;
+
+ struct bna_ib *ib;
+ u8 ib_seg_offset;
+
+ struct bna_rx *rx;
+};
+
+struct bna_rss_config {
+ enum rss_hash_type hash_type;
+ u8 hash_mask;
+ u32 toeplitz_hash_key[BFI_RSS_HASH_KEY_LEN];
+};
+
+struct bna_hds_config {
+ enum hds_header_type hdr_type;
+ int header_size;
+};
+
+/* This structure is used during RX creation */
+struct bna_rx_config {
+ enum bna_rx_type rx_type;
+ int num_paths;
+ enum bna_rxp_type rxp_type;
+ int paused;
+ int q_depth;
+ /*
+ * Small/Large (or Header/Data) buffer size to be configured
+ * for SLR and HDS queue type. Large buffer size comes from
+ * port->mtu.
+ */
+ int small_buff_size;
+
+ enum bna_status rss_status;
+ struct bna_rss_config rss_config;
+
+ enum bna_status hds_status;
+ struct bna_hds_config hds_config;
+
+ enum bna_status vlan_strip_status;
+};
+
+/* Rx Path structure - one per MSIX vector/CPU */
+struct bna_rxp {
+ /* This should be the first one */
+ struct list_head qe;
+
+ enum bna_rxp_type type;
+ union bna_rxq_u rxq;
+ struct bna_cq cq;
+
+ struct bna_rx *rx;
+
+ /* MSI-x vector number for configuring RSS */
+ int vector;
+
+ struct bna_mbox_qe mbox_qe;
+};
+
+/* HDS configuration structure */
+struct bna_rxf_hds {
+ enum hds_header_type hdr_type;
+ int header_size;
+};
+
+/* RSS configuration structure */
+struct bna_rxf_rss {
+ enum rss_hash_type hash_type;
+ u8 hash_mask;
+ u32 toeplitz_hash_key[BFI_RSS_HASH_KEY_LEN];
+};
+
+/* RxF structure (hardware Rx Function) */
+struct bna_rxf {
+ bfa_fsm_t fsm;
+ int rxf_id;
+ enum rxf_flags ctrl_flags;
+ u16 default_vlan_tag;
+ enum bna_rxf_oper_state rxf_oper_state;
+ enum bna_status hds_status;
+ struct bna_rxf_hds hds_cfg;
+ enum bna_status rss_status;
+ struct bna_rxf_rss rss_cfg;
+ struct bna_rit_segment *rit_segment;
+ struct bna_rx *rx;
+ u32 forced_offset;
+ struct bna_mbox_qe mbox_qe;
+ int mcast_rxq_id;
+
+ /* callback for bna_rxf_start() */
+ void (*start_cbfn) (struct bna_rx *rx, enum bna_cb_status status);
+ struct bna_rx *start_cbarg;
+
+ /* callback for bna_rxf_stop() */
+ void (*stop_cbfn) (struct bna_rx *rx, enum bna_cb_status status);
+ struct bna_rx *stop_cbarg;
+
+ /* callback for bna_rxf_receive_enable() / bna_rxf_receive_disable() */
+ void (*oper_state_cbfn) (struct bnad *bnad, struct bna_rx *rx,
+ enum bna_cb_status status);
+ struct bnad *oper_state_cbarg;
+
+ /**
+ * callback for:
+ * bna_rxf_ucast_set()
+ * bna_rxf_{ucast/mcast}_add(),
+ * bna_rxf_{ucast/mcast}_del(),
+ * bna_rxf_mode_set()
+ */
+ void (*cam_fltr_cbfn)(struct bnad *bnad, struct bna_rx *rx,
+ enum bna_cb_status status);
+ struct bnad *cam_fltr_cbarg;
+
+ enum bna_rxf_flags rxf_flags;
+
+ /* List of unicast addresses yet to be applied to h/w */
+ struct list_head ucast_pending_add_q;
+ struct list_head ucast_pending_del_q;
+ int ucast_pending_set;
+ /* ucast addresses applied to the h/w */
+ struct list_head ucast_active_q;
+ struct bna_mac *ucast_active_mac;
+
+ /* List of multicast addresses yet to be applied to h/w */
+ struct list_head mcast_pending_add_q;
+ struct list_head mcast_pending_del_q;
+ /* multicast addresses applied to the h/w */
+ struct list_head mcast_active_q;
+
+ /* Rx modes yet to be applied to h/w */
+ enum bna_rxmode rxmode_pending;
+ enum bna_rxmode rxmode_pending_bitmask;
+ /* Rx modes applied to h/w */
+ enum bna_rxmode rxmode_active;
+
+ enum bna_status vlan_filter_status;
+ u32 vlan_filter_table[(BFI_MAX_VLAN + 1) / 32];
+};
+
+/* Rx object */
+struct bna_rx {
+ /* This should be the first one */
+ struct list_head qe;
+
+ bfa_fsm_t fsm;
+
+ enum bna_rx_type type;
+
+ /* list-head for RX path objects */
+ struct list_head rxp_q;
+
+ struct bna_rxf rxf;
+
+ enum bna_rx_flags rx_flags;
+
+ struct bna_mbox_qe mbox_qe;
+
+ struct bfa_wc rxq_stop_wc;
+
+ /* Rx event handlers */
+ void (*rcb_setup_cbfn)(struct bnad *, struct bna_rcb *);
+ void (*rcb_destroy_cbfn)(struct bnad *, struct bna_rcb *);
+ void (*ccb_setup_cbfn)(struct bnad *, struct bna_ccb *);
+ void (*ccb_destroy_cbfn)(struct bnad *, struct bna_ccb *);
+ void (*rx_cleanup_cbfn)(struct bnad *, struct bna_ccb *);
+ void (*rx_post_cbfn)(struct bnad *, struct bna_rcb *);
+
+ /* callback for bna_rx_disable(), bna_rx_stop() */
+ void (*stop_cbfn)(void *arg, struct bna_rx *rx,
+ enum bna_cb_status status);
+ void *stop_cbarg;
+
+ struct bna *bna;
+ void *priv; /* bnad's cookie */
+};
+
+struct bna_rx_event_cbfn {
+ /* Optional */
+ void (*rcb_setup_cbfn)(struct bnad *, struct bna_rcb *);
+ void (*rcb_destroy_cbfn)(struct bnad *, struct bna_rcb *);
+ void (*ccb_setup_cbfn)(struct bnad *, struct bna_ccb *);
+ void (*ccb_destroy_cbfn)(struct bnad *, struct bna_ccb *);
+ /* Mandatory */
+ void (*rx_cleanup_cbfn)(struct bnad *, struct bna_ccb *);
+ void (*rx_post_cbfn)(struct bnad *, struct bna_rcb *);
+};
+
+/* Rx module - keeps track of free, active rx objects */
+struct bna_rx_mod {
+ struct bna *bna; /* back pointer to parent */
+ struct bna_rx *rx; /* BFI_MAX_RXQ entries */
+ struct bna_rxp *rxp; /* BFI_MAX_RXQ entries */
+ struct bna_rxq *rxq; /* BFI_MAX_RXQ entries */
+
+ struct list_head rx_free_q;
+ struct list_head rx_active_q;
+ int rx_free_count;
+
+ struct list_head rxp_free_q;
+ int rxp_free_count;
+
+ struct list_head rxq_free_q;
+ int rxq_free_count;
+
+ enum bna_rx_mod_flags flags;
+
+ /* callback for bna_rx_mod_stop() */
+ void (*stop_cbfn)(struct bna_port *port,
+ enum bna_cb_status status);
+
+ struct bfa_wc rx_stop_wc;
+ u32 dim_vector[BNA_LOAD_T_MAX][BNA_BIAS_T_MAX];
+ u32 rxf_bmap[2];
+};
+
+/**
+ *
+ * CAM
+ *
+ */
+
+struct bna_ucam_mod {
+ struct bna_mac *ucmac; /* BFI_MAX_UCMAC entries */
+ struct list_head free_q;
+
+ struct bna *bna;
+};
+
+struct bna_mcam_mod {
+ struct bna_mac *mcmac; /* BFI_MAX_MCMAC entries */
+ struct list_head free_q;
+
+ struct bna *bna;
+};
+
+/**
+ *
+ * Statistics
+ *
+ */
+
+struct bna_tx_stats {
+ int tx_state;
+ int tx_flags;
+ int num_txqs;
+ u32 txq_bmap[2];
+ int txf_id;
+};
+
+struct bna_rx_stats {
+ int rx_state;
+ int rx_flags;
+ int num_rxps;
+ int num_rxqs;
+ u32 rxq_bmap[2];
+ u32 cq_bmap[2];
+ int rxf_id;
+ int rxf_state;
+ int rxf_oper_state;
+ int num_active_ucast;
+ int num_active_mcast;
+ int rxmode_active;
+ int vlan_filter_status;
+ u32 vlan_filter_table[(BFI_MAX_VLAN + 1) / 32];
+ int rss_status;
+ int hds_status;
+};
+
+struct bna_sw_stats {
+ int device_state;
+ int port_state;
+ int port_flags;
+ int llport_state;
+ int priority;
+ int num_active_tx;
+ int num_active_rx;
+ struct bna_tx_stats tx_stats[BFI_MAX_TXQ];
+ struct bna_rx_stats rx_stats[BFI_MAX_RXQ];
+};
+
+struct bna_stats {
+ u32 txf_bmap[2];
+ u32 rxf_bmap[2];
+ struct bfi_ll_stats *hw_stats;
+ struct bna_sw_stats *sw_stats;
+};
+
+/**
+ *
+ * BNA
+ *
+ */
+
+struct bna {
+ struct bfa_pcidev pcidev;
+
+ int port_num;
+
+ struct bna_chip_regs regs;
+
+ struct bna_dma_addr hw_stats_dma;
+ struct bna_stats stats;
+
+ struct bna_device device;
+ struct bfa_cee cee;
+
+ struct bna_mbox_mod mbox_mod;
+
+ struct bna_port port;
+
+ struct bna_tx_mod tx_mod;
+
+ struct bna_rx_mod rx_mod;
+
+ struct bna_ib_mod ib_mod;
+
+ struct bna_ucam_mod ucam_mod;
+ struct bna_mcam_mod mcam_mod;
+
+ struct bna_rit_mod rit_mod;
+
+ int rxf_default_id;
+ int rxf_promisc_id;
+
+ struct bna_mbox_qe mbox_qe;
+
+ struct bnad *bnad;
+};
+
+#endif /* __BNA_TYPES_H__ */
diff --git a/drivers/net/bna/bnad.c b/drivers/net/bna/bnad.c
new file mode 100644
index 000000000000..7e839b9cec22
--- /dev/null
+++ b/drivers/net/bna/bnad.c
@@ -0,0 +1,3264 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/etherdevice.h>
+#include <linux/in.h>
+#include <linux/ethtool.h>
+#include <linux/if_vlan.h>
+#include <linux/if_ether.h>
+#include <linux/ip.h>
+
+#include "bnad.h"
+#include "bna.h"
+#include "cna.h"
+
+static DEFINE_MUTEX(bnad_fwimg_mutex);
+
+/*
+ * Module params
+ */
+static uint bnad_msix_disable;
+module_param(bnad_msix_disable, uint, 0444);
+MODULE_PARM_DESC(bnad_msix_disable, "Disable MSIX mode");
+
+static uint bnad_ioc_auto_recover = 1;
+module_param(bnad_ioc_auto_recover, uint, 0444);
+MODULE_PARM_DESC(bnad_ioc_auto_recover, "Enable / Disable auto recovery");
+
+/*
+ * Global variables
+ */
+u32 bnad_rxqs_per_cq = 2;
+
+static const u8 bnad_bcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+/*
+ * Local MACROS
+ */
+#define BNAD_TX_UNMAPQ_DEPTH (bnad->txq_depth * 2)
+
+#define BNAD_RX_UNMAPQ_DEPTH (bnad->rxq_depth)
+
+#define BNAD_GET_MBOX_IRQ(_bnad) \
+ (((_bnad)->cfg_flags & BNAD_CF_MSIX) ? \
+ ((_bnad)->msix_table[(_bnad)->msix_num - 1].vector) : \
+ ((_bnad)->pcidev->irq))
+
+#define BNAD_FILL_UNMAPQ_MEM_REQ(_res_info, _num, _depth) \
+do { \
+ (_res_info)->res_type = BNA_RES_T_MEM; \
+ (_res_info)->res_u.mem_info.mem_type = BNA_MEM_T_KVA; \
+ (_res_info)->res_u.mem_info.num = (_num); \
+ (_res_info)->res_u.mem_info.len = \
+ sizeof(struct bnad_unmap_q) + \
+ (sizeof(struct bnad_skb_unmap) * ((_depth) - 1)); \
+} while (0)
+
+/*
+ * Reinitialize completions in CQ, once Rx is taken down
+ */
+static void
+bnad_cq_cmpl_init(struct bnad *bnad, struct bna_ccb *ccb)
+{
+ struct bna_cq_entry *cmpl, *next_cmpl;
+ unsigned int wi_range, wis = 0, ccb_prod = 0;
+ int i;
+
+ BNA_CQ_QPGE_PTR_GET(ccb_prod, ccb->sw_qpt, cmpl,
+ wi_range);
+
+ for (i = 0; i < ccb->q_depth; i++) {
+ wis++;
+ if (likely(--wi_range))
+ next_cmpl = cmpl + 1;
+ else {
+ BNA_QE_INDX_ADD(ccb_prod, wis, ccb->q_depth);
+ wis = 0;
+ BNA_CQ_QPGE_PTR_GET(ccb_prod, ccb->sw_qpt,
+ next_cmpl, wi_range);
+ }
+ cmpl->valid = 0;
+ cmpl = next_cmpl;
+ }
+}
+
+/*
+ * Frees all pending Tx Bufs
+ * At this point no activity is expected on the Q,
+ * so DMA unmap & freeing is fine.
+ */
+static void
+bnad_free_all_txbufs(struct bnad *bnad,
+ struct bna_tcb *tcb)
+{
+ u16 unmap_cons;
+ struct bnad_unmap_q *unmap_q = tcb->unmap_q;
+ struct bnad_skb_unmap *unmap_array;
+ struct sk_buff *skb = NULL;
+ int i;
+
+ unmap_array = unmap_q->unmap_array;
+
+ unmap_cons = 0;
+ while (unmap_cons < unmap_q->q_depth) {
+ skb = unmap_array[unmap_cons].skb;
+ if (!skb) {
+ unmap_cons++;
+ continue;
+ }
+ unmap_array[unmap_cons].skb = NULL;
+
+ pci_unmap_single(bnad->pcidev,
+ pci_unmap_addr(&unmap_array[unmap_cons],
+ dma_addr), skb_headlen(skb),
+ PCI_DMA_TODEVICE);
+
+ pci_unmap_addr_set(&unmap_array[unmap_cons], dma_addr, 0);
+ unmap_cons++;
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+ pci_unmap_page(bnad->pcidev,
+ pci_unmap_addr(&unmap_array[unmap_cons],
+ dma_addr),
+ skb_shinfo(skb)->frags[i].size,
+ PCI_DMA_TODEVICE);
+ pci_unmap_addr_set(&unmap_array[unmap_cons], dma_addr,
+ 0);
+ unmap_cons++;
+ }
+ dev_kfree_skb_any(skb);
+ }
+}
+
+/* Data Path Handlers */
+
+/*
+ * bnad_free_txbufs : Frees the Tx bufs on Tx completion
+ * Can be called in a) Interrupt context
+ * b) Sending context
+ * c) Tasklet context
+ */
+static u32
+bnad_free_txbufs(struct bnad *bnad,
+ struct bna_tcb *tcb)
+{
+ u32 sent_packets = 0, sent_bytes = 0;
+ u16 wis, unmap_cons, updated_hw_cons;
+ struct bnad_unmap_q *unmap_q = tcb->unmap_q;
+ struct bnad_skb_unmap *unmap_array;
+ struct sk_buff *skb;
+ int i;
+
+ /*
+ * Just return if TX is stopped. This check is useful
+ * when bnad_free_txbufs() runs out of a tasklet scheduled
+ * before bnad_cb_tx_cleanup() cleared BNAD_RF_TX_STARTED bit
+ * but this routine runs actually after the cleanup has been
+ * executed.
+ */
+ if (!test_bit(BNAD_RF_TX_STARTED, &bnad->run_flags))
+ return 0;
+
+ updated_hw_cons = *(tcb->hw_consumer_index);
+
+ wis = BNA_Q_INDEX_CHANGE(tcb->consumer_index,
+ updated_hw_cons, tcb->q_depth);
+
+ BUG_ON(!(wis <= BNA_QE_IN_USE_CNT(tcb, tcb->q_depth)));
+
+ unmap_array = unmap_q->unmap_array;
+ unmap_cons = unmap_q->consumer_index;
+
+ prefetch(&unmap_array[unmap_cons + 1]);
+ while (wis) {
+ skb = unmap_array[unmap_cons].skb;
+
+ unmap_array[unmap_cons].skb = NULL;
+
+ sent_packets++;
+ sent_bytes += skb->len;
+ wis -= BNA_TXQ_WI_NEEDED(1 + skb_shinfo(skb)->nr_frags);
+
+ pci_unmap_single(bnad->pcidev,
+ pci_unmap_addr(&unmap_array[unmap_cons],
+ dma_addr), skb_headlen(skb),
+ PCI_DMA_TODEVICE);
+ pci_unmap_addr_set(&unmap_array[unmap_cons], dma_addr, 0);
+ BNA_QE_INDX_ADD(unmap_cons, 1, unmap_q->q_depth);
+
+ prefetch(&unmap_array[unmap_cons + 1]);
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+ prefetch(&unmap_array[unmap_cons + 1]);
+
+ pci_unmap_page(bnad->pcidev,
+ pci_unmap_addr(&unmap_array[unmap_cons],
+ dma_addr),
+ skb_shinfo(skb)->frags[i].size,
+ PCI_DMA_TODEVICE);
+ pci_unmap_addr_set(&unmap_array[unmap_cons], dma_addr,
+ 0);
+ BNA_QE_INDX_ADD(unmap_cons, 1, unmap_q->q_depth);
+ }
+ dev_kfree_skb_any(skb);
+ }
+
+ /* Update consumer pointers. */
+ tcb->consumer_index = updated_hw_cons;
+ unmap_q->consumer_index = unmap_cons;
+
+ tcb->txq->tx_packets += sent_packets;
+ tcb->txq->tx_bytes += sent_bytes;
+
+ return sent_packets;
+}
+
+/* Tx Free Tasklet function */
+/* Frees for all the tcb's in all the Tx's */
+/*
+ * Scheduled from sending context, so that
+ * the fat Tx lock is not held for too long
+ * in the sending context.
+ */
+static void
+bnad_tx_free_tasklet(unsigned long bnad_ptr)
+{
+ struct bnad *bnad = (struct bnad *)bnad_ptr;
+ struct bna_tcb *tcb;
+ u32 acked;
+ int i, j;
+
+ for (i = 0; i < bnad->num_tx; i++) {
+ for (j = 0; j < bnad->num_txq_per_tx; j++) {
+ tcb = bnad->tx_info[i].tcb[j];
+ if (!tcb)
+ continue;
+ if (((u16) (*tcb->hw_consumer_index) !=
+ tcb->consumer_index) &&
+ (!test_and_set_bit(BNAD_TXQ_FREE_SENT,
+ &tcb->flags))) {
+ acked = bnad_free_txbufs(bnad, tcb);
+ bna_ib_ack(tcb->i_dbell, acked);
+ smp_mb__before_clear_bit();
+ clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
+ }
+ }
+ }
+}
+
+static u32
+bnad_tx(struct bnad *bnad, struct bna_tcb *tcb)
+{
+ struct net_device *netdev = bnad->netdev;
+ u32 sent;
+
+ if (test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags))
+ return 0;
+
+ sent = bnad_free_txbufs(bnad, tcb);
+ if (sent) {
+ if (netif_queue_stopped(netdev) &&
+ netif_carrier_ok(netdev) &&
+ BNA_QE_FREE_CNT(tcb, tcb->q_depth) >=
+ BNAD_NETIF_WAKE_THRESHOLD) {
+ netif_wake_queue(netdev);
+ BNAD_UPDATE_CTR(bnad, netif_queue_wakeup);
+ }
+ bna_ib_ack(tcb->i_dbell, sent);
+ } else
+ bna_ib_ack(tcb->i_dbell, 0);
+
+ smp_mb__before_clear_bit();
+ clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
+
+ return sent;
+}
+
+/* MSIX Tx Completion Handler */
+static irqreturn_t
+bnad_msix_tx(int irq, void *data)
+{
+ struct bna_tcb *tcb = (struct bna_tcb *)data;
+ struct bnad *bnad = tcb->bnad;
+
+ bnad_tx(bnad, tcb);
+
+ return IRQ_HANDLED;
+}
+
+static void
+bnad_reset_rcb(struct bnad *bnad, struct bna_rcb *rcb)
+{
+ struct bnad_unmap_q *unmap_q = rcb->unmap_q;
+
+ rcb->producer_index = 0;
+ rcb->consumer_index = 0;
+
+ unmap_q->producer_index = 0;
+ unmap_q->consumer_index = 0;
+}
+
+static void
+bnad_free_rxbufs(struct bnad *bnad, struct bna_rcb *rcb)
+{
+ struct bnad_unmap_q *unmap_q;
+ struct sk_buff *skb;
+
+ unmap_q = rcb->unmap_q;
+ while (BNA_QE_IN_USE_CNT(unmap_q, unmap_q->q_depth)) {
+ skb = unmap_q->unmap_array[unmap_q->consumer_index].skb;
+ BUG_ON(!(skb));
+ unmap_q->unmap_array[unmap_q->consumer_index].skb = NULL;
+ pci_unmap_single(bnad->pcidev, pci_unmap_addr(&unmap_q->
+ unmap_array[unmap_q->consumer_index],
+ dma_addr), rcb->rxq->buffer_size +
+ NET_IP_ALIGN, PCI_DMA_FROMDEVICE);
+ dev_kfree_skb(skb);
+ BNA_QE_INDX_ADD(unmap_q->consumer_index, 1, unmap_q->q_depth);
+ BNA_QE_INDX_ADD(rcb->consumer_index, 1, rcb->q_depth);
+ }
+
+ bnad_reset_rcb(bnad, rcb);
+}
+
+static void
+bnad_alloc_n_post_rxbufs(struct bnad *bnad, struct bna_rcb *rcb)
+{
+ u16 to_alloc, alloced, unmap_prod, wi_range;
+ struct bnad_unmap_q *unmap_q = rcb->unmap_q;
+ struct bnad_skb_unmap *unmap_array;
+ struct bna_rxq_entry *rxent;
+ struct sk_buff *skb;
+ dma_addr_t dma_addr;
+
+ alloced = 0;
+ to_alloc =
+ BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth);
+
+ unmap_array = unmap_q->unmap_array;
+ unmap_prod = unmap_q->producer_index;
+
+ BNA_RXQ_QPGE_PTR_GET(unmap_prod, rcb->sw_qpt, rxent, wi_range);
+
+ while (to_alloc--) {
+ if (!wi_range) {
+ BNA_RXQ_QPGE_PTR_GET(unmap_prod, rcb->sw_qpt, rxent,
+ wi_range);
+ }
+ skb = alloc_skb(rcb->rxq->buffer_size + NET_IP_ALIGN,
+ GFP_ATOMIC);
+ if (unlikely(!skb)) {
+ BNAD_UPDATE_CTR(bnad, rxbuf_alloc_failed);
+ goto finishing;
+ }
+ skb->dev = bnad->netdev;
+ skb_reserve(skb, NET_IP_ALIGN);
+ unmap_array[unmap_prod].skb = skb;
+ dma_addr = pci_map_single(bnad->pcidev, skb->data,
+ rcb->rxq->buffer_size, PCI_DMA_FROMDEVICE);
+ pci_unmap_addr_set(&unmap_array[unmap_prod], dma_addr,
+ dma_addr);
+ BNA_SET_DMA_ADDR(dma_addr, &rxent->host_addr);
+ BNA_QE_INDX_ADD(unmap_prod, 1, unmap_q->q_depth);
+
+ rxent++;
+ wi_range--;
+ alloced++;
+ }
+
+finishing:
+ if (likely(alloced)) {
+ unmap_q->producer_index = unmap_prod;
+ rcb->producer_index = unmap_prod;
+ smp_mb();
+ bna_rxq_prod_indx_doorbell(rcb);
+ }
+}
+
+/*
+ * Locking is required in the enable path
+ * because it is called from a napi poll
+ * context, where the bna_lock is not held
+ * unlike the IRQ context.
+ */
+static void
+bnad_enable_txrx_irqs(struct bnad *bnad)
+{
+ struct bna_tcb *tcb;
+ struct bna_ccb *ccb;
+ int i, j;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ for (i = 0; i < bnad->num_tx; i++) {
+ for (j = 0; j < bnad->num_txq_per_tx; j++) {
+ tcb = bnad->tx_info[i].tcb[j];
+ bna_ib_coalescing_timer_set(tcb->i_dbell,
+ tcb->txq->ib->ib_config.coalescing_timeo);
+ bna_ib_ack(tcb->i_dbell, 0);
+ }
+ }
+
+ for (i = 0; i < bnad->num_rx; i++) {
+ for (j = 0; j < bnad->num_rxp_per_rx; j++) {
+ ccb = bnad->rx_info[i].rx_ctrl[j].ccb;
+ bnad_enable_rx_irq_unsafe(ccb);
+ }
+ }
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+}
+
+static inline void
+bnad_refill_rxq(struct bnad *bnad, struct bna_rcb *rcb)
+{
+ struct bnad_unmap_q *unmap_q = rcb->unmap_q;
+
+ if (!test_and_set_bit(BNAD_RXQ_REFILL, &rcb->flags)) {
+ if (BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth)
+ >> BNAD_RXQ_REFILL_THRESHOLD_SHIFT)
+ bnad_alloc_n_post_rxbufs(bnad, rcb);
+ smp_mb__before_clear_bit();
+ clear_bit(BNAD_RXQ_REFILL, &rcb->flags);
+ }
+}
+
+static u32
+bnad_poll_cq(struct bnad *bnad, struct bna_ccb *ccb, int budget)
+{
+ struct bna_cq_entry *cmpl, *next_cmpl;
+ struct bna_rcb *rcb = NULL;
+ unsigned int wi_range, packets = 0, wis = 0;
+ struct bnad_unmap_q *unmap_q;
+ struct sk_buff *skb;
+ u32 flags;
+ u32 qid0 = ccb->rcb[0]->rxq->rxq_id;
+ struct bna_pkt_rate *pkt_rt = &ccb->pkt_rate;
+
+ prefetch(bnad->netdev);
+ BNA_CQ_QPGE_PTR_GET(ccb->producer_index, ccb->sw_qpt, cmpl,
+ wi_range);
+ BUG_ON(!(wi_range <= ccb->q_depth));
+ while (cmpl->valid && packets < budget) {
+ packets++;
+ BNA_UPDATE_PKT_CNT(pkt_rt, ntohs(cmpl->length));
+
+ if (qid0 == cmpl->rxq_id)
+ rcb = ccb->rcb[0];
+ else
+ rcb = ccb->rcb[1];
+
+ unmap_q = rcb->unmap_q;
+
+ skb = unmap_q->unmap_array[unmap_q->consumer_index].skb;
+ BUG_ON(!(skb));
+ unmap_q->unmap_array[unmap_q->consumer_index].skb = NULL;
+ pci_unmap_single(bnad->pcidev,
+ pci_unmap_addr(&unmap_q->
+ unmap_array[unmap_q->
+ consumer_index],
+ dma_addr),
+ rcb->rxq->buffer_size,
+ PCI_DMA_FROMDEVICE);
+ BNA_QE_INDX_ADD(unmap_q->consumer_index, 1, unmap_q->q_depth);
+
+ /* Should be more efficient ? Performance ? */
+ BNA_QE_INDX_ADD(rcb->consumer_index, 1, rcb->q_depth);
+
+ wis++;
+ if (likely(--wi_range))
+ next_cmpl = cmpl + 1;
+ else {
+ BNA_QE_INDX_ADD(ccb->producer_index, wis, ccb->q_depth);
+ wis = 0;
+ BNA_CQ_QPGE_PTR_GET(ccb->producer_index, ccb->sw_qpt,
+ next_cmpl, wi_range);
+ BUG_ON(!(wi_range <= ccb->q_depth));
+ }
+ prefetch(next_cmpl);
+
+ flags = ntohl(cmpl->flags);
+ if (unlikely
+ (flags &
+ (BNA_CQ_EF_MAC_ERROR | BNA_CQ_EF_FCS_ERROR |
+ BNA_CQ_EF_TOO_LONG))) {
+ dev_kfree_skb_any(skb);
+ rcb->rxq->rx_packets_with_error++;
+ goto next;
+ }
+
+ skb_put(skb, ntohs(cmpl->length));
+ if (likely
+ (bnad->rx_csum &&
+ (((flags & BNA_CQ_EF_IPV4) &&
+ (flags & BNA_CQ_EF_L3_CKSUM_OK)) ||
+ (flags & BNA_CQ_EF_IPV6)) &&
+ (flags & (BNA_CQ_EF_TCP | BNA_CQ_EF_UDP)) &&
+ (flags & BNA_CQ_EF_L4_CKSUM_OK)))
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ else
+ skb_checksum_none_assert(skb);
+
+ rcb->rxq->rx_packets++;
+ rcb->rxq->rx_bytes += skb->len;
+ skb->protocol = eth_type_trans(skb, bnad->netdev);
+
+ if (bnad->vlan_grp && (flags & BNA_CQ_EF_VLAN)) {
+ struct bnad_rx_ctrl *rx_ctrl =
+ (struct bnad_rx_ctrl *)ccb->ctrl;
+ if (skb->ip_summed == CHECKSUM_UNNECESSARY)
+ vlan_gro_receive(&rx_ctrl->napi, bnad->vlan_grp,
+ ntohs(cmpl->vlan_tag), skb);
+ else
+ vlan_hwaccel_receive_skb(skb,
+ bnad->vlan_grp,
+ ntohs(cmpl->vlan_tag));
+
+ } else { /* Not VLAN tagged/stripped */
+ struct bnad_rx_ctrl *rx_ctrl =
+ (struct bnad_rx_ctrl *)ccb->ctrl;
+ if (skb->ip_summed == CHECKSUM_UNNECESSARY)
+ napi_gro_receive(&rx_ctrl->napi, skb);
+ else
+ netif_receive_skb(skb);
+ }
+
+next:
+ cmpl->valid = 0;
+ cmpl = next_cmpl;
+ }
+
+ BNA_QE_INDX_ADD(ccb->producer_index, wis, ccb->q_depth);
+
+ if (likely(ccb)) {
+ bna_ib_ack(ccb->i_dbell, packets);
+ bnad_refill_rxq(bnad, ccb->rcb[0]);
+ if (ccb->rcb[1])
+ bnad_refill_rxq(bnad, ccb->rcb[1]);
+ } else
+ bna_ib_ack(ccb->i_dbell, 0);
+
+ return packets;
+}
+
+static void
+bnad_disable_rx_irq(struct bnad *bnad, struct bna_ccb *ccb)
+{
+ bna_ib_coalescing_timer_set(ccb->i_dbell, 0);
+ bna_ib_ack(ccb->i_dbell, 0);
+}
+
+static void
+bnad_enable_rx_irq(struct bnad *bnad, struct bna_ccb *ccb)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&bnad->bna_lock, flags); /* Because of polling context */
+ bnad_enable_rx_irq_unsafe(ccb);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+}
+
+static void
+bnad_netif_rx_schedule_poll(struct bnad *bnad, struct bna_ccb *ccb)
+{
+ struct bnad_rx_ctrl *rx_ctrl = (struct bnad_rx_ctrl *)(ccb->ctrl);
+ if (likely(napi_schedule_prep((&rx_ctrl->napi)))) {
+ bnad_disable_rx_irq(bnad, ccb);
+ __napi_schedule((&rx_ctrl->napi));
+ }
+ BNAD_UPDATE_CTR(bnad, netif_rx_schedule);
+}
+
+/* MSIX Rx Path Handler */
+static irqreturn_t
+bnad_msix_rx(int irq, void *data)
+{
+ struct bna_ccb *ccb = (struct bna_ccb *)data;
+ struct bnad *bnad = ccb->bnad;
+
+ bnad_netif_rx_schedule_poll(bnad, ccb);
+
+ return IRQ_HANDLED;
+}
+
+/* Interrupt handlers */
+
+/* Mbox Interrupt Handlers */
+static irqreturn_t
+bnad_msix_mbox_handler(int irq, void *data)
+{
+ u32 intr_status;
+ unsigned long flags;
+ struct net_device *netdev = data;
+ struct bnad *bnad;
+
+ bnad = netdev_priv(netdev);
+
+ /* BNA_ISR_GET(bnad); Inc Ref count */
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+
+ bna_intr_status_get(&bnad->bna, intr_status);
+
+ if (BNA_IS_MBOX_ERR_INTR(intr_status))
+ bna_mbox_handler(&bnad->bna, intr_status);
+
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+ /* BNAD_ISR_PUT(bnad); Dec Ref count */
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t
+bnad_isr(int irq, void *data)
+{
+ int i, j;
+ u32 intr_status;
+ unsigned long flags;
+ struct net_device *netdev = data;
+ struct bnad *bnad = netdev_priv(netdev);
+ struct bnad_rx_info *rx_info;
+ struct bnad_rx_ctrl *rx_ctrl;
+
+ if (unlikely(test_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags)))
+ return IRQ_NONE;
+
+ bna_intr_status_get(&bnad->bna, intr_status);
+
+ if (unlikely(!intr_status))
+ return IRQ_NONE;
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+
+ if (BNA_IS_MBOX_ERR_INTR(intr_status)) {
+ bna_mbox_handler(&bnad->bna, intr_status);
+ if (!BNA_IS_INTX_DATA_INTR(intr_status)) {
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+ goto done;
+ }
+ }
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+ /* Process data interrupts */
+ for (i = 0; i < bnad->num_rx; i++) {
+ rx_info = &bnad->rx_info[i];
+ if (!rx_info->rx)
+ continue;
+ for (j = 0; j < bnad->num_rxp_per_rx; j++) {
+ rx_ctrl = &rx_info->rx_ctrl[j];
+ if (rx_ctrl->ccb)
+ bnad_netif_rx_schedule_poll(bnad,
+ rx_ctrl->ccb);
+ }
+ }
+done:
+ return IRQ_HANDLED;
+}
+
+/*
+ * Called in interrupt / callback context
+ * with bna_lock held, so cfg_flags access is OK
+ */
+static void
+bnad_enable_mbox_irq(struct bnad *bnad)
+{
+ int irq = BNAD_GET_MBOX_IRQ(bnad);
+
+ if (test_and_clear_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags))
+ if (bnad->cfg_flags & BNAD_CF_MSIX)
+ enable_irq(irq);
+
+ BNAD_UPDATE_CTR(bnad, mbox_intr_enabled);
+}
+
+/*
+ * Called with bnad->bna_lock held b'cos of
+ * bnad->cfg_flags access.
+ */
+static void
+bnad_disable_mbox_irq(struct bnad *bnad)
+{
+ int irq = BNAD_GET_MBOX_IRQ(bnad);
+
+
+ if (!test_and_set_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags))
+ if (bnad->cfg_flags & BNAD_CF_MSIX)
+ disable_irq_nosync(irq);
+
+ BNAD_UPDATE_CTR(bnad, mbox_intr_disabled);
+}
+
+/* Control Path Handlers */
+
+/* Callbacks */
+void
+bnad_cb_device_enable_mbox_intr(struct bnad *bnad)
+{
+ bnad_enable_mbox_irq(bnad);
+}
+
+void
+bnad_cb_device_disable_mbox_intr(struct bnad *bnad)
+{
+ bnad_disable_mbox_irq(bnad);
+}
+
+void
+bnad_cb_device_enabled(struct bnad *bnad, enum bna_cb_status status)
+{
+ complete(&bnad->bnad_completions.ioc_comp);
+ bnad->bnad_completions.ioc_comp_status = status;
+}
+
+void
+bnad_cb_device_disabled(struct bnad *bnad, enum bna_cb_status status)
+{
+ complete(&bnad->bnad_completions.ioc_comp);
+ bnad->bnad_completions.ioc_comp_status = status;
+}
+
+static void
+bnad_cb_port_disabled(void *arg, enum bna_cb_status status)
+{
+ struct bnad *bnad = (struct bnad *)arg;
+
+ complete(&bnad->bnad_completions.port_comp);
+
+ netif_carrier_off(bnad->netdev);
+}
+
+void
+bnad_cb_port_link_status(struct bnad *bnad,
+ enum bna_link_status link_status)
+{
+ bool link_up = 0;
+
+ link_up = (link_status == BNA_LINK_UP) || (link_status == BNA_CEE_UP);
+
+ if (link_status == BNA_CEE_UP) {
+ set_bit(BNAD_RF_CEE_RUNNING, &bnad->run_flags);
+ BNAD_UPDATE_CTR(bnad, cee_up);
+ } else
+ clear_bit(BNAD_RF_CEE_RUNNING, &bnad->run_flags);
+
+ if (link_up) {
+ if (!netif_carrier_ok(bnad->netdev)) {
+ pr_warn("bna: %s link up\n",
+ bnad->netdev->name);
+ netif_carrier_on(bnad->netdev);
+ BNAD_UPDATE_CTR(bnad, link_toggle);
+ if (test_bit(BNAD_RF_TX_STARTED, &bnad->run_flags)) {
+ /* Force an immediate Transmit Schedule */
+ pr_info("bna: %s TX_STARTED\n",
+ bnad->netdev->name);
+ netif_wake_queue(bnad->netdev);
+ BNAD_UPDATE_CTR(bnad, netif_queue_wakeup);
+ } else {
+ netif_stop_queue(bnad->netdev);
+ BNAD_UPDATE_CTR(bnad, netif_queue_stop);
+ }
+ }
+ } else {
+ if (netif_carrier_ok(bnad->netdev)) {
+ pr_warn("bna: %s link down\n",
+ bnad->netdev->name);
+ netif_carrier_off(bnad->netdev);
+ BNAD_UPDATE_CTR(bnad, link_toggle);
+ }
+ }
+}
+
+static void
+bnad_cb_tx_disabled(void *arg, struct bna_tx *tx,
+ enum bna_cb_status status)
+{
+ struct bnad *bnad = (struct bnad *)arg;
+
+ complete(&bnad->bnad_completions.tx_comp);
+}
+
+static void
+bnad_cb_tcb_setup(struct bnad *bnad, struct bna_tcb *tcb)
+{
+ struct bnad_tx_info *tx_info =
+ (struct bnad_tx_info *)tcb->txq->tx->priv;
+ struct bnad_unmap_q *unmap_q = tcb->unmap_q;
+
+ tx_info->tcb[tcb->id] = tcb;
+ unmap_q->producer_index = 0;
+ unmap_q->consumer_index = 0;
+ unmap_q->q_depth = BNAD_TX_UNMAPQ_DEPTH;
+}
+
+static void
+bnad_cb_tcb_destroy(struct bnad *bnad, struct bna_tcb *tcb)
+{
+ struct bnad_tx_info *tx_info =
+ (struct bnad_tx_info *)tcb->txq->tx->priv;
+
+ tx_info->tcb[tcb->id] = NULL;
+}
+
+static void
+bnad_cb_rcb_setup(struct bnad *bnad, struct bna_rcb *rcb)
+{
+ struct bnad_unmap_q *unmap_q = rcb->unmap_q;
+
+ unmap_q->producer_index = 0;
+ unmap_q->consumer_index = 0;
+ unmap_q->q_depth = BNAD_RX_UNMAPQ_DEPTH;
+}
+
+static void
+bnad_cb_ccb_setup(struct bnad *bnad, struct bna_ccb *ccb)
+{
+ struct bnad_rx_info *rx_info =
+ (struct bnad_rx_info *)ccb->cq->rx->priv;
+
+ rx_info->rx_ctrl[ccb->id].ccb = ccb;
+ ccb->ctrl = &rx_info->rx_ctrl[ccb->id];
+}
+
+static void
+bnad_cb_ccb_destroy(struct bnad *bnad, struct bna_ccb *ccb)
+{
+ struct bnad_rx_info *rx_info =
+ (struct bnad_rx_info *)ccb->cq->rx->priv;
+
+ rx_info->rx_ctrl[ccb->id].ccb = NULL;
+}
+
+static void
+bnad_cb_tx_stall(struct bnad *bnad, struct bna_tcb *tcb)
+{
+ struct bnad_tx_info *tx_info =
+ (struct bnad_tx_info *)tcb->txq->tx->priv;
+
+ if (tx_info != &bnad->tx_info[0])
+ return;
+
+ clear_bit(BNAD_RF_TX_STARTED, &bnad->run_flags);
+ netif_stop_queue(bnad->netdev);
+ pr_info("bna: %s TX_STOPPED\n", bnad->netdev->name);
+}
+
+static void
+bnad_cb_tx_resume(struct bnad *bnad, struct bna_tcb *tcb)
+{
+ if (test_and_set_bit(BNAD_RF_TX_STARTED, &bnad->run_flags))
+ return;
+
+ if (netif_carrier_ok(bnad->netdev)) {
+ pr_info("bna: %s TX_STARTED\n", bnad->netdev->name);
+ netif_wake_queue(bnad->netdev);
+ BNAD_UPDATE_CTR(bnad, netif_queue_wakeup);
+ }
+}
+
+static void
+bnad_cb_tx_cleanup(struct bnad *bnad, struct bna_tcb *tcb)
+{
+ struct bnad_unmap_q *unmap_q;
+
+ if (!tcb || (!tcb->unmap_q))
+ return;
+
+ unmap_q = tcb->unmap_q;
+ if (!unmap_q->unmap_array)
+ return;
+
+ if (test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags))
+ return;
+
+ bnad_free_all_txbufs(bnad, tcb);
+
+ unmap_q->producer_index = 0;
+ unmap_q->consumer_index = 0;
+
+ smp_mb__before_clear_bit();
+ clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
+}
+
+static void
+bnad_cb_rx_cleanup(struct bnad *bnad,
+ struct bna_ccb *ccb)
+{
+ bnad_cq_cmpl_init(bnad, ccb);
+
+ bnad_free_rxbufs(bnad, ccb->rcb[0]);
+ clear_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags);
+
+ if (ccb->rcb[1]) {
+ bnad_free_rxbufs(bnad, ccb->rcb[1]);
+ clear_bit(BNAD_RXQ_STARTED, &ccb->rcb[1]->flags);
+ }
+}
+
+static void
+bnad_cb_rx_post(struct bnad *bnad, struct bna_rcb *rcb)
+{
+ struct bnad_unmap_q *unmap_q = rcb->unmap_q;
+
+ set_bit(BNAD_RXQ_STARTED, &rcb->flags);
+
+ /* Now allocate & post buffers for this RCB */
+ /* !!Allocation in callback context */
+ if (!test_and_set_bit(BNAD_RXQ_REFILL, &rcb->flags)) {
+ if (BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth)
+ >> BNAD_RXQ_REFILL_THRESHOLD_SHIFT)
+ bnad_alloc_n_post_rxbufs(bnad, rcb);
+ smp_mb__before_clear_bit();
+ clear_bit(BNAD_RXQ_REFILL, &rcb->flags);
+ }
+}
+
+static void
+bnad_cb_rx_disabled(void *arg, struct bna_rx *rx,
+ enum bna_cb_status status)
+{
+ struct bnad *bnad = (struct bnad *)arg;
+
+ complete(&bnad->bnad_completions.rx_comp);
+}
+
+static void
+bnad_cb_rx_mcast_add(struct bnad *bnad, struct bna_rx *rx,
+ enum bna_cb_status status)
+{
+ bnad->bnad_completions.mcast_comp_status = status;
+ complete(&bnad->bnad_completions.mcast_comp);
+}
+
+void
+bnad_cb_stats_get(struct bnad *bnad, enum bna_cb_status status,
+ struct bna_stats *stats)
+{
+ if (status == BNA_CB_SUCCESS)
+ BNAD_UPDATE_CTR(bnad, hw_stats_updates);
+
+ if (!netif_running(bnad->netdev) ||
+ !test_bit(BNAD_RF_STATS_TIMER_RUNNING, &bnad->run_flags))
+ return;
+
+ mod_timer(&bnad->stats_timer,
+ jiffies + msecs_to_jiffies(BNAD_STATS_TIMER_FREQ));
+}
+
+/* Resource allocation, free functions */
+
+static void
+bnad_mem_free(struct bnad *bnad,
+ struct bna_mem_info *mem_info)
+{
+ int i;
+ dma_addr_t dma_pa;
+
+ if (mem_info->mdl == NULL)
+ return;
+
+ for (i = 0; i < mem_info->num; i++) {
+ if (mem_info->mdl[i].kva != NULL) {
+ if (mem_info->mem_type == BNA_MEM_T_DMA) {
+ BNA_GET_DMA_ADDR(&(mem_info->mdl[i].dma),
+ dma_pa);
+ pci_free_consistent(bnad->pcidev,
+ mem_info->mdl[i].len,
+ mem_info->mdl[i].kva, dma_pa);
+ } else
+ kfree(mem_info->mdl[i].kva);
+ }
+ }
+ kfree(mem_info->mdl);
+ mem_info->mdl = NULL;
+}
+
+static int
+bnad_mem_alloc(struct bnad *bnad,
+ struct bna_mem_info *mem_info)
+{
+ int i;
+ dma_addr_t dma_pa;
+
+ if ((mem_info->num == 0) || (mem_info->len == 0)) {
+ mem_info->mdl = NULL;
+ return 0;
+ }
+
+ mem_info->mdl = kcalloc(mem_info->num, sizeof(struct bna_mem_descr),
+ GFP_KERNEL);
+ if (mem_info->mdl == NULL)
+ return -ENOMEM;
+
+ if (mem_info->mem_type == BNA_MEM_T_DMA) {
+ for (i = 0; i < mem_info->num; i++) {
+ mem_info->mdl[i].len = mem_info->len;
+ mem_info->mdl[i].kva =
+ pci_alloc_consistent(bnad->pcidev,
+ mem_info->len, &dma_pa);
+
+ if (mem_info->mdl[i].kva == NULL)
+ goto err_return;
+
+ BNA_SET_DMA_ADDR(dma_pa,
+ &(mem_info->mdl[i].dma));
+ }
+ } else {
+ for (i = 0; i < mem_info->num; i++) {
+ mem_info->mdl[i].len = mem_info->len;
+ mem_info->mdl[i].kva = kzalloc(mem_info->len,
+ GFP_KERNEL);
+ if (mem_info->mdl[i].kva == NULL)
+ goto err_return;
+ }
+ }
+
+ return 0;
+
+err_return:
+ bnad_mem_free(bnad, mem_info);
+ return -ENOMEM;
+}
+
+/* Free IRQ for Mailbox */
+static void
+bnad_mbox_irq_free(struct bnad *bnad,
+ struct bna_intr_info *intr_info)
+{
+ int irq;
+ unsigned long flags;
+
+ if (intr_info->idl == NULL)
+ return;
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ bnad_disable_mbox_irq(bnad);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+ irq = BNAD_GET_MBOX_IRQ(bnad);
+ free_irq(irq, bnad->netdev);
+
+ kfree(intr_info->idl);
+}
+
+/*
+ * Allocates IRQ for Mailbox, but keep it disabled
+ * This will be enabled once we get the mbox enable callback
+ * from bna
+ */
+static int
+bnad_mbox_irq_alloc(struct bnad *bnad,
+ struct bna_intr_info *intr_info)
+{
+ int err;
+ unsigned long flags;
+ u32 irq;
+ irq_handler_t irq_handler;
+
+ /* Mbox should use only 1 vector */
+
+ intr_info->idl = kzalloc(sizeof(*(intr_info->idl)), GFP_KERNEL);
+ if (!intr_info->idl)
+ return -ENOMEM;
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ if (bnad->cfg_flags & BNAD_CF_MSIX) {
+ irq_handler = (irq_handler_t)bnad_msix_mbox_handler;
+ irq = bnad->msix_table[bnad->msix_num - 1].vector;
+ flags = 0;
+ intr_info->intr_type = BNA_INTR_T_MSIX;
+ intr_info->idl[0].vector = bnad->msix_num - 1;
+ } else {
+ irq_handler = (irq_handler_t)bnad_isr;
+ irq = bnad->pcidev->irq;
+ flags = IRQF_SHARED;
+ intr_info->intr_type = BNA_INTR_T_INTX;
+ /* intr_info->idl.vector = 0 ? */
+ }
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+ sprintf(bnad->mbox_irq_name, "%s", BNAD_NAME);
+
+ /*
+ * Set the Mbox IRQ disable flag, so that the IRQ handler
+ * called from request_irq() for SHARED IRQs do not execute
+ */
+ set_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags);
+
+ err = request_irq(irq, irq_handler, flags,
+ bnad->mbox_irq_name, bnad->netdev);
+
+ if (err) {
+ kfree(intr_info->idl);
+ intr_info->idl = NULL;
+ return err;
+ }
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+
+ if (bnad->cfg_flags & BNAD_CF_MSIX)
+ disable_irq_nosync(irq);
+
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+ return 0;
+}
+
+static void
+bnad_txrx_irq_free(struct bnad *bnad, struct bna_intr_info *intr_info)
+{
+ kfree(intr_info->idl);
+ intr_info->idl = NULL;
+}
+
+/* Allocates Interrupt Descriptor List for MSIX/INT-X vectors */
+static int
+bnad_txrx_irq_alloc(struct bnad *bnad, enum bnad_intr_source src,
+ uint txrx_id, struct bna_intr_info *intr_info)
+{
+ int i, vector_start = 0;
+ u32 cfg_flags;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ cfg_flags = bnad->cfg_flags;
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+ if (cfg_flags & BNAD_CF_MSIX) {
+ intr_info->intr_type = BNA_INTR_T_MSIX;
+ intr_info->idl = kcalloc(intr_info->num,
+ sizeof(struct bna_intr_descr),
+ GFP_KERNEL);
+ if (!intr_info->idl)
+ return -ENOMEM;
+
+ switch (src) {
+ case BNAD_INTR_TX:
+ vector_start = txrx_id;
+ break;
+
+ case BNAD_INTR_RX:
+ vector_start = bnad->num_tx * bnad->num_txq_per_tx +
+ txrx_id;
+ break;
+
+ default:
+ BUG();
+ }
+
+ for (i = 0; i < intr_info->num; i++)
+ intr_info->idl[i].vector = vector_start + i;
+ } else {
+ intr_info->intr_type = BNA_INTR_T_INTX;
+ intr_info->num = 1;
+ intr_info->idl = kcalloc(intr_info->num,
+ sizeof(struct bna_intr_descr),
+ GFP_KERNEL);
+ if (!intr_info->idl)
+ return -ENOMEM;
+
+ switch (src) {
+ case BNAD_INTR_TX:
+ intr_info->idl[0].vector = 0x1; /* Bit mask : Tx IB */
+ break;
+
+ case BNAD_INTR_RX:
+ intr_info->idl[0].vector = 0x2; /* Bit mask : Rx IB */
+ break;
+ }
+ }
+ return 0;
+}
+
+/**
+ * NOTE: Should be called for MSIX only
+ * Unregisters Tx MSIX vector(s) from the kernel
+ */
+static void
+bnad_tx_msix_unregister(struct bnad *bnad, struct bnad_tx_info *tx_info,
+ int num_txqs)
+{
+ int i;
+ int vector_num;
+
+ for (i = 0; i < num_txqs; i++) {
+ if (tx_info->tcb[i] == NULL)
+ continue;
+
+ vector_num = tx_info->tcb[i]->intr_vector;
+ free_irq(bnad->msix_table[vector_num].vector, tx_info->tcb[i]);
+ }
+}
+
+/**
+ * NOTE: Should be called for MSIX only
+ * Registers Tx MSIX vector(s) and ISR(s), cookie with the kernel
+ */
+static int
+bnad_tx_msix_register(struct bnad *bnad, struct bnad_tx_info *tx_info,
+ uint tx_id, int num_txqs)
+{
+ int i;
+ int err;
+ int vector_num;
+
+ for (i = 0; i < num_txqs; i++) {
+ vector_num = tx_info->tcb[i]->intr_vector;
+ sprintf(tx_info->tcb[i]->name, "%s TXQ %d", bnad->netdev->name,
+ tx_id + tx_info->tcb[i]->id);
+ err = request_irq(bnad->msix_table[vector_num].vector,
+ (irq_handler_t)bnad_msix_tx, 0,
+ tx_info->tcb[i]->name,
+ tx_info->tcb[i]);
+ if (err)
+ goto err_return;
+ }
+
+ return 0;
+
+err_return:
+ if (i > 0)
+ bnad_tx_msix_unregister(bnad, tx_info, (i - 1));
+ return -1;
+}
+
+/**
+ * NOTE: Should be called for MSIX only
+ * Unregisters Rx MSIX vector(s) from the kernel
+ */
+static void
+bnad_rx_msix_unregister(struct bnad *bnad, struct bnad_rx_info *rx_info,
+ int num_rxps)
+{
+ int i;
+ int vector_num;
+
+ for (i = 0; i < num_rxps; i++) {
+ if (rx_info->rx_ctrl[i].ccb == NULL)
+ continue;
+
+ vector_num = rx_info->rx_ctrl[i].ccb->intr_vector;
+ free_irq(bnad->msix_table[vector_num].vector,
+ rx_info->rx_ctrl[i].ccb);
+ }
+}
+
+/**
+ * NOTE: Should be called for MSIX only
+ * Registers Tx MSIX vector(s) and ISR(s), cookie with the kernel
+ */
+static int
+bnad_rx_msix_register(struct bnad *bnad, struct bnad_rx_info *rx_info,
+ uint rx_id, int num_rxps)
+{
+ int i;
+ int err;
+ int vector_num;
+
+ for (i = 0; i < num_rxps; i++) {
+ vector_num = rx_info->rx_ctrl[i].ccb->intr_vector;
+ sprintf(rx_info->rx_ctrl[i].ccb->name, "%s CQ %d",
+ bnad->netdev->name,
+ rx_id + rx_info->rx_ctrl[i].ccb->id);
+ err = request_irq(bnad->msix_table[vector_num].vector,
+ (irq_handler_t)bnad_msix_rx, 0,
+ rx_info->rx_ctrl[i].ccb->name,
+ rx_info->rx_ctrl[i].ccb);
+ if (err)
+ goto err_return;
+ }
+
+ return 0;
+
+err_return:
+ if (i > 0)
+ bnad_rx_msix_unregister(bnad, rx_info, (i - 1));
+ return -1;
+}
+
+/* Free Tx object Resources */
+static void
+bnad_tx_res_free(struct bnad *bnad, struct bna_res_info *res_info)
+{
+ int i;
+
+ for (i = 0; i < BNA_TX_RES_T_MAX; i++) {
+ if (res_info[i].res_type == BNA_RES_T_MEM)
+ bnad_mem_free(bnad, &res_info[i].res_u.mem_info);
+ else if (res_info[i].res_type == BNA_RES_T_INTR)
+ bnad_txrx_irq_free(bnad, &res_info[i].res_u.intr_info);
+ }
+}
+
+/* Allocates memory and interrupt resources for Tx object */
+static int
+bnad_tx_res_alloc(struct bnad *bnad, struct bna_res_info *res_info,
+ uint tx_id)
+{
+ int i, err = 0;
+
+ for (i = 0; i < BNA_TX_RES_T_MAX; i++) {
+ if (res_info[i].res_type == BNA_RES_T_MEM)
+ err = bnad_mem_alloc(bnad,
+ &res_info[i].res_u.mem_info);
+ else if (res_info[i].res_type == BNA_RES_T_INTR)
+ err = bnad_txrx_irq_alloc(bnad, BNAD_INTR_TX, tx_id,
+ &res_info[i].res_u.intr_info);
+ if (err)
+ goto err_return;
+ }
+ return 0;
+
+err_return:
+ bnad_tx_res_free(bnad, res_info);
+ return err;
+}
+
+/* Free Rx object Resources */
+static void
+bnad_rx_res_free(struct bnad *bnad, struct bna_res_info *res_info)
+{
+ int i;
+
+ for (i = 0; i < BNA_RX_RES_T_MAX; i++) {
+ if (res_info[i].res_type == BNA_RES_T_MEM)
+ bnad_mem_free(bnad, &res_info[i].res_u.mem_info);
+ else if (res_info[i].res_type == BNA_RES_T_INTR)
+ bnad_txrx_irq_free(bnad, &res_info[i].res_u.intr_info);
+ }
+}
+
+/* Allocates memory and interrupt resources for Rx object */
+static int
+bnad_rx_res_alloc(struct bnad *bnad, struct bna_res_info *res_info,
+ uint rx_id)
+{
+ int i, err = 0;
+
+ /* All memory needs to be allocated before setup_ccbs */
+ for (i = 0; i < BNA_RX_RES_T_MAX; i++) {
+ if (res_info[i].res_type == BNA_RES_T_MEM)
+ err = bnad_mem_alloc(bnad,
+ &res_info[i].res_u.mem_info);
+ else if (res_info[i].res_type == BNA_RES_T_INTR)
+ err = bnad_txrx_irq_alloc(bnad, BNAD_INTR_RX, rx_id,
+ &res_info[i].res_u.intr_info);
+ if (err)
+ goto err_return;
+ }
+ return 0;
+
+err_return:
+ bnad_rx_res_free(bnad, res_info);
+ return err;
+}
+
+/* Timer callbacks */
+/* a) IOC timer */
+static void
+bnad_ioc_timeout(unsigned long data)
+{
+ struct bnad *bnad = (struct bnad *)data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ bfa_nw_ioc_timeout((void *) &bnad->bna.device.ioc);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+}
+
+static void
+bnad_ioc_hb_check(unsigned long data)
+{
+ struct bnad *bnad = (struct bnad *)data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ bfa_nw_ioc_hb_check((void *) &bnad->bna.device.ioc);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+}
+
+static void
+bnad_ioc_sem_timeout(unsigned long data)
+{
+ struct bnad *bnad = (struct bnad *)data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ bfa_nw_ioc_sem_timeout((void *) &bnad->bna.device.ioc);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+}
+
+/*
+ * All timer routines use bnad->bna_lock to protect against
+ * the following race, which may occur in case of no locking:
+ * Time CPU m CPU n
+ * 0 1 = test_bit
+ * 1 clear_bit
+ * 2 del_timer_sync
+ * 3 mod_timer
+ */
+
+/* b) Dynamic Interrupt Moderation Timer */
+static void
+bnad_dim_timeout(unsigned long data)
+{
+ struct bnad *bnad = (struct bnad *)data;
+ struct bnad_rx_info *rx_info;
+ struct bnad_rx_ctrl *rx_ctrl;
+ int i, j;
+ unsigned long flags;
+
+ if (!netif_carrier_ok(bnad->netdev))
+ return;
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ for (i = 0; i < bnad->num_rx; i++) {
+ rx_info = &bnad->rx_info[i];
+ if (!rx_info->rx)
+ continue;
+ for (j = 0; j < bnad->num_rxp_per_rx; j++) {
+ rx_ctrl = &rx_info->rx_ctrl[j];
+ if (!rx_ctrl->ccb)
+ continue;
+ bna_rx_dim_update(rx_ctrl->ccb);
+ }
+ }
+
+ /* Check for BNAD_CF_DIM_ENABLED, does not eleminate a race */
+ if (test_bit(BNAD_RF_DIM_TIMER_RUNNING, &bnad->run_flags))
+ mod_timer(&bnad->dim_timer,
+ jiffies + msecs_to_jiffies(BNAD_DIM_TIMER_FREQ));
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+}
+
+/* c) Statistics Timer */
+static void
+bnad_stats_timeout(unsigned long data)
+{
+ struct bnad *bnad = (struct bnad *)data;
+ unsigned long flags;
+
+ if (!netif_running(bnad->netdev) ||
+ !test_bit(BNAD_RF_STATS_TIMER_RUNNING, &bnad->run_flags))
+ return;
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ bna_stats_get(&bnad->bna);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+}
+
+/*
+ * Set up timer for DIM
+ * Called with bnad->bna_lock held
+ */
+void
+bnad_dim_timer_start(struct bnad *bnad)
+{
+ if (bnad->cfg_flags & BNAD_CF_DIM_ENABLED &&
+ !test_bit(BNAD_RF_DIM_TIMER_RUNNING, &bnad->run_flags)) {
+ setup_timer(&bnad->dim_timer, bnad_dim_timeout,
+ (unsigned long)bnad);
+ set_bit(BNAD_RF_DIM_TIMER_RUNNING, &bnad->run_flags);
+ mod_timer(&bnad->dim_timer,
+ jiffies + msecs_to_jiffies(BNAD_DIM_TIMER_FREQ));
+ }
+}
+
+/*
+ * Set up timer for statistics
+ * Called with mutex_lock(&bnad->conf_mutex) held
+ */
+static void
+bnad_stats_timer_start(struct bnad *bnad)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ if (!test_and_set_bit(BNAD_RF_STATS_TIMER_RUNNING, &bnad->run_flags)) {
+ setup_timer(&bnad->stats_timer, bnad_stats_timeout,
+ (unsigned long)bnad);
+ mod_timer(&bnad->stats_timer,
+ jiffies + msecs_to_jiffies(BNAD_STATS_TIMER_FREQ));
+ }
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+}
+
+/*
+ * Stops the stats timer
+ * Called with mutex_lock(&bnad->conf_mutex) held
+ */
+static void
+bnad_stats_timer_stop(struct bnad *bnad)
+{
+ int to_del = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ if (test_and_clear_bit(BNAD_RF_STATS_TIMER_RUNNING, &bnad->run_flags))
+ to_del = 1;
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+ if (to_del)
+ del_timer_sync(&bnad->stats_timer);
+}
+
+/* Utilities */
+
+static void
+bnad_netdev_mc_list_get(struct net_device *netdev, u8 *mc_list)
+{
+ int i = 1; /* Index 0 has broadcast address */
+ struct netdev_hw_addr *mc_addr;
+
+ netdev_for_each_mc_addr(mc_addr, netdev) {
+ memcpy(&mc_list[i * ETH_ALEN], &mc_addr->addr[0],
+ ETH_ALEN);
+ i++;
+ }
+}
+
+static int
+bnad_napi_poll_rx(struct napi_struct *napi, int budget)
+{
+ struct bnad_rx_ctrl *rx_ctrl =
+ container_of(napi, struct bnad_rx_ctrl, napi);
+ struct bna_ccb *ccb;
+ struct bnad *bnad;
+ int rcvd = 0;
+
+ ccb = rx_ctrl->ccb;
+
+ bnad = ccb->bnad;
+
+ if (!netif_carrier_ok(bnad->netdev))
+ goto poll_exit;
+
+ rcvd = bnad_poll_cq(bnad, ccb, budget);
+ if (rcvd == budget)
+ return rcvd;
+
+poll_exit:
+ napi_complete((napi));
+
+ BNAD_UPDATE_CTR(bnad, netif_rx_complete);
+
+ bnad_enable_rx_irq(bnad, ccb);
+ return rcvd;
+}
+
+static int
+bnad_napi_poll_txrx(struct napi_struct *napi, int budget)
+{
+ struct bnad_rx_ctrl *rx_ctrl =
+ container_of(napi, struct bnad_rx_ctrl, napi);
+ struct bna_ccb *ccb;
+ struct bnad *bnad;
+ int rcvd = 0;
+ int i, j;
+
+ ccb = rx_ctrl->ccb;
+
+ bnad = ccb->bnad;
+
+ if (!netif_carrier_ok(bnad->netdev))
+ goto poll_exit;
+
+ /* Handle Tx Completions, if any */
+ for (i = 0; i < bnad->num_tx; i++) {
+ for (j = 0; j < bnad->num_txq_per_tx; j++)
+ bnad_tx(bnad, bnad->tx_info[i].tcb[j]);
+ }
+
+ /* Handle Rx Completions */
+ rcvd = bnad_poll_cq(bnad, ccb, budget);
+ if (rcvd == budget)
+ return rcvd;
+poll_exit:
+ napi_complete((napi));
+
+ BNAD_UPDATE_CTR(bnad, netif_rx_complete);
+
+ bnad_enable_txrx_irqs(bnad);
+ return rcvd;
+}
+
+static void
+bnad_napi_enable(struct bnad *bnad, u32 rx_id)
+{
+ int (*napi_poll) (struct napi_struct *, int);
+ struct bnad_rx_ctrl *rx_ctrl;
+ int i;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ if (bnad->cfg_flags & BNAD_CF_MSIX)
+ napi_poll = bnad_napi_poll_rx;
+ else
+ napi_poll = bnad_napi_poll_txrx;
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+ /* Initialize & enable NAPI */
+ for (i = 0; i < bnad->num_rxp_per_rx; i++) {
+ rx_ctrl = &bnad->rx_info[rx_id].rx_ctrl[i];
+ netif_napi_add(bnad->netdev, &rx_ctrl->napi,
+ napi_poll, 64);
+ napi_enable(&rx_ctrl->napi);
+ }
+}
+
+static void
+bnad_napi_disable(struct bnad *bnad, u32 rx_id)
+{
+ int i;
+
+ /* First disable and then clean up */
+ for (i = 0; i < bnad->num_rxp_per_rx; i++) {
+ napi_disable(&bnad->rx_info[rx_id].rx_ctrl[i].napi);
+ netif_napi_del(&bnad->rx_info[rx_id].rx_ctrl[i].napi);
+ }
+}
+
+/* Should be held with conf_lock held */
+void
+bnad_cleanup_tx(struct bnad *bnad, uint tx_id)
+{
+ struct bnad_tx_info *tx_info = &bnad->tx_info[tx_id];
+ struct bna_res_info *res_info = &bnad->tx_res_info[tx_id].res_info[0];
+ unsigned long flags;
+
+ if (!tx_info->tx)
+ return;
+
+ init_completion(&bnad->bnad_completions.tx_comp);
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ bna_tx_disable(tx_info->tx, BNA_HARD_CLEANUP, bnad_cb_tx_disabled);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+ wait_for_completion(&bnad->bnad_completions.tx_comp);
+
+ if (tx_info->tcb[0]->intr_type == BNA_INTR_T_MSIX)
+ bnad_tx_msix_unregister(bnad, tx_info,
+ bnad->num_txq_per_tx);
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ bna_tx_destroy(tx_info->tx);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+ tx_info->tx = NULL;
+
+ if (0 == tx_id)
+ tasklet_kill(&bnad->tx_free_tasklet);
+
+ bnad_tx_res_free(bnad, res_info);
+}
+
+/* Should be held with conf_lock held */
+int
+bnad_setup_tx(struct bnad *bnad, uint tx_id)
+{
+ int err;
+ struct bnad_tx_info *tx_info = &bnad->tx_info[tx_id];
+ struct bna_res_info *res_info = &bnad->tx_res_info[tx_id].res_info[0];
+ struct bna_intr_info *intr_info =
+ &res_info[BNA_TX_RES_INTR_T_TXCMPL].res_u.intr_info;
+ struct bna_tx_config *tx_config = &bnad->tx_config[tx_id];
+ struct bna_tx_event_cbfn tx_cbfn;
+ struct bna_tx *tx;
+ unsigned long flags;
+
+ /* Initialize the Tx object configuration */
+ tx_config->num_txq = bnad->num_txq_per_tx;
+ tx_config->txq_depth = bnad->txq_depth;
+ tx_config->tx_type = BNA_TX_T_REGULAR;
+
+ /* Initialize the tx event handlers */
+ tx_cbfn.tcb_setup_cbfn = bnad_cb_tcb_setup;
+ tx_cbfn.tcb_destroy_cbfn = bnad_cb_tcb_destroy;
+ tx_cbfn.tx_stall_cbfn = bnad_cb_tx_stall;
+ tx_cbfn.tx_resume_cbfn = bnad_cb_tx_resume;
+ tx_cbfn.tx_cleanup_cbfn = bnad_cb_tx_cleanup;
+
+ /* Get BNA's resource requirement for one tx object */
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ bna_tx_res_req(bnad->num_txq_per_tx,
+ bnad->txq_depth, res_info);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+ /* Fill Unmap Q memory requirements */
+ BNAD_FILL_UNMAPQ_MEM_REQ(
+ &res_info[BNA_TX_RES_MEM_T_UNMAPQ],
+ bnad->num_txq_per_tx,
+ BNAD_TX_UNMAPQ_DEPTH);
+
+ /* Allocate resources */
+ err = bnad_tx_res_alloc(bnad, res_info, tx_id);
+ if (err)
+ return err;
+
+ /* Ask BNA to create one Tx object, supplying required resources */
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ tx = bna_tx_create(&bnad->bna, bnad, tx_config, &tx_cbfn, res_info,
+ tx_info);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+ if (!tx)
+ goto err_return;
+ tx_info->tx = tx;
+
+ /* Register ISR for the Tx object */
+ if (intr_info->intr_type == BNA_INTR_T_MSIX) {
+ err = bnad_tx_msix_register(bnad, tx_info,
+ tx_id, bnad->num_txq_per_tx);
+ if (err)
+ goto err_return;
+ }
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ bna_tx_enable(tx);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+ return 0;
+
+err_return:
+ bnad_tx_res_free(bnad, res_info);
+ return err;
+}
+
+/* Setup the rx config for bna_rx_create */
+/* bnad decides the configuration */
+static void
+bnad_init_rx_config(struct bnad *bnad, struct bna_rx_config *rx_config)
+{
+ rx_config->rx_type = BNA_RX_T_REGULAR;
+ rx_config->num_paths = bnad->num_rxp_per_rx;
+
+ if (bnad->num_rxp_per_rx > 1) {
+ rx_config->rss_status = BNA_STATUS_T_ENABLED;
+ rx_config->rss_config.hash_type =
+ (BFI_RSS_T_V4_TCP |
+ BFI_RSS_T_V6_TCP |
+ BFI_RSS_T_V4_IP |
+ BFI_RSS_T_V6_IP);
+ rx_config->rss_config.hash_mask =
+ bnad->num_rxp_per_rx - 1;
+ get_random_bytes(rx_config->rss_config.toeplitz_hash_key,
+ sizeof(rx_config->rss_config.toeplitz_hash_key));
+ } else {
+ rx_config->rss_status = BNA_STATUS_T_DISABLED;
+ memset(&rx_config->rss_config, 0,
+ sizeof(rx_config->rss_config));
+ }
+ rx_config->rxp_type = BNA_RXP_SLR;
+ rx_config->q_depth = bnad->rxq_depth;
+
+ rx_config->small_buff_size = BFI_SMALL_RXBUF_SIZE;
+
+ rx_config->vlan_strip_status = BNA_STATUS_T_ENABLED;
+}
+
+/* Called with mutex_lock(&bnad->conf_mutex) held */
+void
+bnad_cleanup_rx(struct bnad *bnad, uint rx_id)
+{
+ struct bnad_rx_info *rx_info = &bnad->rx_info[rx_id];
+ struct bna_rx_config *rx_config = &bnad->rx_config[rx_id];
+ struct bna_res_info *res_info = &bnad->rx_res_info[rx_id].res_info[0];
+ unsigned long flags;
+ int dim_timer_del = 0;
+
+ if (!rx_info->rx)
+ return;
+
+ if (0 == rx_id) {
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ dim_timer_del = bnad_dim_timer_running(bnad);
+ if (dim_timer_del)
+ clear_bit(BNAD_RF_DIM_TIMER_RUNNING, &bnad->run_flags);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+ if (dim_timer_del)
+ del_timer_sync(&bnad->dim_timer);
+ }
+
+ bnad_napi_disable(bnad, rx_id);
+
+ init_completion(&bnad->bnad_completions.rx_comp);
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ bna_rx_disable(rx_info->rx, BNA_HARD_CLEANUP, bnad_cb_rx_disabled);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+ wait_for_completion(&bnad->bnad_completions.rx_comp);
+
+ if (rx_info->rx_ctrl[0].ccb->intr_type == BNA_INTR_T_MSIX)
+ bnad_rx_msix_unregister(bnad, rx_info, rx_config->num_paths);
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ bna_rx_destroy(rx_info->rx);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+ rx_info->rx = NULL;
+
+ bnad_rx_res_free(bnad, res_info);
+}
+
+/* Called with mutex_lock(&bnad->conf_mutex) held */
+int
+bnad_setup_rx(struct bnad *bnad, uint rx_id)
+{
+ int err;
+ struct bnad_rx_info *rx_info = &bnad->rx_info[rx_id];
+ struct bna_res_info *res_info = &bnad->rx_res_info[rx_id].res_info[0];
+ struct bna_intr_info *intr_info =
+ &res_info[BNA_RX_RES_T_INTR].res_u.intr_info;
+ struct bna_rx_config *rx_config = &bnad->rx_config[rx_id];
+ struct bna_rx_event_cbfn rx_cbfn;
+ struct bna_rx *rx;
+ unsigned long flags;
+
+ /* Initialize the Rx object configuration */
+ bnad_init_rx_config(bnad, rx_config);
+
+ /* Initialize the Rx event handlers */
+ rx_cbfn.rcb_setup_cbfn = bnad_cb_rcb_setup;
+ rx_cbfn.rcb_destroy_cbfn = NULL;
+ rx_cbfn.ccb_setup_cbfn = bnad_cb_ccb_setup;
+ rx_cbfn.ccb_destroy_cbfn = bnad_cb_ccb_destroy;
+ rx_cbfn.rx_cleanup_cbfn = bnad_cb_rx_cleanup;
+ rx_cbfn.rx_post_cbfn = bnad_cb_rx_post;
+
+ /* Get BNA's resource requirement for one Rx object */
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ bna_rx_res_req(rx_config, res_info);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+ /* Fill Unmap Q memory requirements */
+ BNAD_FILL_UNMAPQ_MEM_REQ(
+ &res_info[BNA_RX_RES_MEM_T_UNMAPQ],
+ rx_config->num_paths +
+ ((rx_config->rxp_type == BNA_RXP_SINGLE) ? 0 :
+ rx_config->num_paths), BNAD_RX_UNMAPQ_DEPTH);
+
+ /* Allocate resource */
+ err = bnad_rx_res_alloc(bnad, res_info, rx_id);
+ if (err)
+ return err;
+
+ /* Ask BNA to create one Rx object, supplying required resources */
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ rx = bna_rx_create(&bnad->bna, bnad, rx_config, &rx_cbfn, res_info,
+ rx_info);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+ if (!rx)
+ goto err_return;
+ rx_info->rx = rx;
+
+ /* Register ISR for the Rx object */
+ if (intr_info->intr_type == BNA_INTR_T_MSIX) {
+ err = bnad_rx_msix_register(bnad, rx_info, rx_id,
+ rx_config->num_paths);
+ if (err)
+ goto err_return;
+ }
+
+ /* Enable NAPI */
+ bnad_napi_enable(bnad, rx_id);
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ if (0 == rx_id) {
+ /* Set up Dynamic Interrupt Moderation Vector */
+ if (bnad->cfg_flags & BNAD_CF_DIM_ENABLED)
+ bna_rx_dim_reconfig(&bnad->bna, bna_napi_dim_vector);
+
+ /* Enable VLAN filtering only on the default Rx */
+ bna_rx_vlanfilter_enable(rx);
+
+ /* Start the DIM timer */
+ bnad_dim_timer_start(bnad);
+ }
+
+ bna_rx_enable(rx);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+ return 0;
+
+err_return:
+ bnad_cleanup_rx(bnad, rx_id);
+ return err;
+}
+
+/* Called with conf_lock & bnad->bna_lock held */
+void
+bnad_tx_coalescing_timeo_set(struct bnad *bnad)
+{
+ struct bnad_tx_info *tx_info;
+
+ tx_info = &bnad->tx_info[0];
+ if (!tx_info->tx)
+ return;
+
+ bna_tx_coalescing_timeo_set(tx_info->tx, bnad->tx_coalescing_timeo);
+}
+
+/* Called with conf_lock & bnad->bna_lock held */
+void
+bnad_rx_coalescing_timeo_set(struct bnad *bnad)
+{
+ struct bnad_rx_info *rx_info;
+ int i;
+
+ for (i = 0; i < bnad->num_rx; i++) {
+ rx_info = &bnad->rx_info[i];
+ if (!rx_info->rx)
+ continue;
+ bna_rx_coalescing_timeo_set(rx_info->rx,
+ bnad->rx_coalescing_timeo);
+ }
+}
+
+/*
+ * Called with bnad->bna_lock held
+ */
+static int
+bnad_mac_addr_set_locked(struct bnad *bnad, u8 *mac_addr)
+{
+ int ret;
+
+ if (!is_valid_ether_addr(mac_addr))
+ return -EADDRNOTAVAIL;
+
+ /* If datapath is down, pretend everything went through */
+ if (!bnad->rx_info[0].rx)
+ return 0;
+
+ ret = bna_rx_ucast_set(bnad->rx_info[0].rx, mac_addr, NULL);
+ if (ret != BNA_CB_SUCCESS)
+ return -EADDRNOTAVAIL;
+
+ return 0;
+}
+
+/* Should be called with conf_lock held */
+static int
+bnad_enable_default_bcast(struct bnad *bnad)
+{
+ struct bnad_rx_info *rx_info = &bnad->rx_info[0];
+ int ret;
+ unsigned long flags;
+
+ init_completion(&bnad->bnad_completions.mcast_comp);
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ ret = bna_rx_mcast_add(rx_info->rx, (u8 *)bnad_bcast_addr,
+ bnad_cb_rx_mcast_add);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+ if (ret == BNA_CB_SUCCESS)
+ wait_for_completion(&bnad->bnad_completions.mcast_comp);
+ else
+ return -ENODEV;
+
+ if (bnad->bnad_completions.mcast_comp_status != BNA_CB_SUCCESS)
+ return -ENODEV;
+
+ return 0;
+}
+
+/* Statistics utilities */
+void
+bnad_netdev_qstats_fill(struct bnad *bnad, struct rtnl_link_stats64 *stats)
+{
+ int i, j;
+
+ for (i = 0; i < bnad->num_rx; i++) {
+ for (j = 0; j < bnad->num_rxp_per_rx; j++) {
+ if (bnad->rx_info[i].rx_ctrl[j].ccb) {
+ stats->rx_packets += bnad->rx_info[i].
+ rx_ctrl[j].ccb->rcb[0]->rxq->rx_packets;
+ stats->rx_bytes += bnad->rx_info[i].
+ rx_ctrl[j].ccb->rcb[0]->rxq->rx_bytes;
+ if (bnad->rx_info[i].rx_ctrl[j].ccb->rcb[1] &&
+ bnad->rx_info[i].rx_ctrl[j].ccb->
+ rcb[1]->rxq) {
+ stats->rx_packets +=
+ bnad->rx_info[i].rx_ctrl[j].
+ ccb->rcb[1]->rxq->rx_packets;
+ stats->rx_bytes +=
+ bnad->rx_info[i].rx_ctrl[j].
+ ccb->rcb[1]->rxq->rx_bytes;
+ }
+ }
+ }
+ }
+ for (i = 0; i < bnad->num_tx; i++) {
+ for (j = 0; j < bnad->num_txq_per_tx; j++) {
+ if (bnad->tx_info[i].tcb[j]) {
+ stats->tx_packets +=
+ bnad->tx_info[i].tcb[j]->txq->tx_packets;
+ stats->tx_bytes +=
+ bnad->tx_info[i].tcb[j]->txq->tx_bytes;
+ }
+ }
+ }
+}
+
+/*
+ * Must be called with the bna_lock held.
+ */
+void
+bnad_netdev_hwstats_fill(struct bnad *bnad, struct rtnl_link_stats64 *stats)
+{
+ struct bfi_ll_stats_mac *mac_stats;
+ u64 bmap;
+ int i;
+
+ mac_stats = &bnad->stats.bna_stats->hw_stats->mac_stats;
+ stats->rx_errors =
+ mac_stats->rx_fcs_error + mac_stats->rx_alignment_error +
+ mac_stats->rx_frame_length_error + mac_stats->rx_code_error +
+ mac_stats->rx_undersize;
+ stats->tx_errors = mac_stats->tx_fcs_error +
+ mac_stats->tx_undersize;
+ stats->rx_dropped = mac_stats->rx_drop;
+ stats->tx_dropped = mac_stats->tx_drop;
+ stats->multicast = mac_stats->rx_multicast;
+ stats->collisions = mac_stats->tx_total_collision;
+
+ stats->rx_length_errors = mac_stats->rx_frame_length_error;
+
+ /* receive ring buffer overflow ?? */
+
+ stats->rx_crc_errors = mac_stats->rx_fcs_error;
+ stats->rx_frame_errors = mac_stats->rx_alignment_error;
+ /* recv'r fifo overrun */
+ bmap = (u64)bnad->stats.bna_stats->rxf_bmap[0] |
+ ((u64)bnad->stats.bna_stats->rxf_bmap[1] << 32);
+ for (i = 0; bmap && (i < BFI_LL_RXF_ID_MAX); i++) {
+ if (bmap & 1) {
+ stats->rx_fifo_errors +=
+ bnad->stats.bna_stats->
+ hw_stats->rxf_stats[i].frame_drops;
+ break;
+ }
+ bmap >>= 1;
+ }
+}
+
+static void
+bnad_mbox_irq_sync(struct bnad *bnad)
+{
+ u32 irq;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ if (bnad->cfg_flags & BNAD_CF_MSIX)
+ irq = bnad->msix_table[bnad->msix_num - 1].vector;
+ else
+ irq = bnad->pcidev->irq;
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+ synchronize_irq(irq);
+}
+
+/* Utility used by bnad_start_xmit, for doing TSO */
+static int
+bnad_tso_prepare(struct bnad *bnad, struct sk_buff *skb)
+{
+ int err;
+
+ /* SKB_GSO_TCPV4 and SKB_GSO_TCPV6 is defined since 2.6.18. */
+ BUG_ON(!(skb_shinfo(skb)->gso_type == SKB_GSO_TCPV4 ||
+ skb_shinfo(skb)->gso_type == SKB_GSO_TCPV6));
+ if (skb_header_cloned(skb)) {
+ err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
+ if (err) {
+ BNAD_UPDATE_CTR(bnad, tso_err);
+ return err;
+ }
+ }
+
+ /*
+ * For TSO, the TCP checksum field is seeded with pseudo-header sum
+ * excluding the length field.
+ */
+ if (skb->protocol == htons(ETH_P_IP)) {
+ struct iphdr *iph = ip_hdr(skb);
+
+ /* Do we really need these? */
+ iph->tot_len = 0;
+ iph->check = 0;
+
+ tcp_hdr(skb)->check =
+ ~csum_tcpudp_magic(iph->saddr, iph->daddr, 0,
+ IPPROTO_TCP, 0);
+ BNAD_UPDATE_CTR(bnad, tso4);
+ } else {
+ struct ipv6hdr *ipv6h = ipv6_hdr(skb);
+
+ BUG_ON(!(skb->protocol == htons(ETH_P_IPV6)));
+ ipv6h->payload_len = 0;
+ tcp_hdr(skb)->check =
+ ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, 0,
+ IPPROTO_TCP, 0);
+ BNAD_UPDATE_CTR(bnad, tso6);
+ }
+
+ return 0;
+}
+
+/*
+ * Initialize Q numbers depending on Rx Paths
+ * Called with bnad->bna_lock held, because of cfg_flags
+ * access.
+ */
+static void
+bnad_q_num_init(struct bnad *bnad)
+{
+ int rxps;
+
+ rxps = min((uint)num_online_cpus(),
+ (uint)(BNAD_MAX_RXS * BNAD_MAX_RXPS_PER_RX));
+
+ if (!(bnad->cfg_flags & BNAD_CF_MSIX))
+ rxps = 1; /* INTx */
+
+ bnad->num_rx = 1;
+ bnad->num_tx = 1;
+ bnad->num_rxp_per_rx = rxps;
+ bnad->num_txq_per_tx = BNAD_TXQ_NUM;
+}
+
+/*
+ * Adjusts the Q numbers, given a number of msix vectors
+ * Give preference to RSS as opposed to Tx priority Queues,
+ * in such a case, just use 1 Tx Q
+ * Called with bnad->bna_lock held b'cos of cfg_flags access
+ */
+static void
+bnad_q_num_adjust(struct bnad *bnad, int msix_vectors)
+{
+ bnad->num_txq_per_tx = 1;
+ if ((msix_vectors >= (bnad->num_tx * bnad->num_txq_per_tx) +
+ bnad_rxqs_per_cq + BNAD_MAILBOX_MSIX_VECTORS) &&
+ (bnad->cfg_flags & BNAD_CF_MSIX)) {
+ bnad->num_rxp_per_rx = msix_vectors -
+ (bnad->num_tx * bnad->num_txq_per_tx) -
+ BNAD_MAILBOX_MSIX_VECTORS;
+ } else
+ bnad->num_rxp_per_rx = 1;
+}
+
+static void
+bnad_set_netdev_perm_addr(struct bnad *bnad)
+{
+ struct net_device *netdev = bnad->netdev;
+
+ memcpy(netdev->perm_addr, &bnad->perm_addr, netdev->addr_len);
+ if (is_zero_ether_addr(netdev->dev_addr))
+ memcpy(netdev->dev_addr, &bnad->perm_addr, netdev->addr_len);
+}
+
+/* Enable / disable device */
+static void
+bnad_device_disable(struct bnad *bnad)
+{
+ unsigned long flags;
+
+ init_completion(&bnad->bnad_completions.ioc_comp);
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ bna_device_disable(&bnad->bna.device, BNA_HARD_CLEANUP);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+ wait_for_completion(&bnad->bnad_completions.ioc_comp);
+}
+
+static int
+bnad_device_enable(struct bnad *bnad)
+{
+ int err = 0;
+ unsigned long flags;
+
+ init_completion(&bnad->bnad_completions.ioc_comp);
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ bna_device_enable(&bnad->bna.device);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+ wait_for_completion(&bnad->bnad_completions.ioc_comp);
+
+ if (bnad->bnad_completions.ioc_comp_status)
+ err = bnad->bnad_completions.ioc_comp_status;
+
+ return err;
+}
+
+/* Free BNA resources */
+static void
+bnad_res_free(struct bnad *bnad)
+{
+ int i;
+ struct bna_res_info *res_info = &bnad->res_info[0];
+
+ for (i = 0; i < BNA_RES_T_MAX; i++) {
+ if (res_info[i].res_type == BNA_RES_T_MEM)
+ bnad_mem_free(bnad, &res_info[i].res_u.mem_info);
+ else
+ bnad_mbox_irq_free(bnad, &res_info[i].res_u.intr_info);
+ }
+}
+
+/* Allocates memory and interrupt resources for BNA */
+static int
+bnad_res_alloc(struct bnad *bnad)
+{
+ int i, err;
+ struct bna_res_info *res_info = &bnad->res_info[0];
+
+ for (i = 0; i < BNA_RES_T_MAX; i++) {
+ if (res_info[i].res_type == BNA_RES_T_MEM)
+ err = bnad_mem_alloc(bnad, &res_info[i].res_u.mem_info);
+ else
+ err = bnad_mbox_irq_alloc(bnad,
+ &res_info[i].res_u.intr_info);
+ if (err)
+ goto err_return;
+ }
+ return 0;
+
+err_return:
+ bnad_res_free(bnad);
+ return err;
+}
+
+/* Interrupt enable / disable */
+static void
+bnad_enable_msix(struct bnad *bnad)
+{
+ int i, ret;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ if (!(bnad->cfg_flags & BNAD_CF_MSIX)) {
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+ return;
+ }
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+ if (bnad->msix_table)
+ return;
+
+ bnad->msix_table =
+ kcalloc(bnad->msix_num, sizeof(struct msix_entry), GFP_KERNEL);
+
+ if (!bnad->msix_table)
+ goto intx_mode;
+
+ for (i = 0; i < bnad->msix_num; i++)
+ bnad->msix_table[i].entry = i;
+
+ ret = pci_enable_msix(bnad->pcidev, bnad->msix_table, bnad->msix_num);
+ if (ret > 0) {
+ /* Not enough MSI-X vectors. */
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ /* ret = #of vectors that we got */
+ bnad_q_num_adjust(bnad, ret);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+ bnad->msix_num = (bnad->num_tx * bnad->num_txq_per_tx)
+ + (bnad->num_rx
+ * bnad->num_rxp_per_rx) +
+ BNAD_MAILBOX_MSIX_VECTORS;
+
+ /* Try once more with adjusted numbers */
+ /* If this fails, fall back to INTx */
+ ret = pci_enable_msix(bnad->pcidev, bnad->msix_table,
+ bnad->msix_num);
+ if (ret)
+ goto intx_mode;
+
+ } else if (ret < 0)
+ goto intx_mode;
+ return;
+
+intx_mode:
+
+ kfree(bnad->msix_table);
+ bnad->msix_table = NULL;
+ bnad->msix_num = 0;
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ bnad->cfg_flags &= ~BNAD_CF_MSIX;
+ bnad_q_num_init(bnad);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+}
+
+static void
+bnad_disable_msix(struct bnad *bnad)
+{
+ u32 cfg_flags;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ cfg_flags = bnad->cfg_flags;
+ if (bnad->cfg_flags & BNAD_CF_MSIX)
+ bnad->cfg_flags &= ~BNAD_CF_MSIX;
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+ if (cfg_flags & BNAD_CF_MSIX) {
+ pci_disable_msix(bnad->pcidev);
+ kfree(bnad->msix_table);
+ bnad->msix_table = NULL;
+ }
+}
+
+/* Netdev entry points */
+static int
+bnad_open(struct net_device *netdev)
+{
+ int err;
+ struct bnad *bnad = netdev_priv(netdev);
+ struct bna_pause_config pause_config;
+ int mtu;
+ unsigned long flags;
+
+ mutex_lock(&bnad->conf_mutex);
+
+ /* Tx */
+ err = bnad_setup_tx(bnad, 0);
+ if (err)
+ goto err_return;
+
+ /* Rx */
+ err = bnad_setup_rx(bnad, 0);
+ if (err)
+ goto cleanup_tx;
+
+ /* Port */
+ pause_config.tx_pause = 0;
+ pause_config.rx_pause = 0;
+
+ mtu = ETH_HLEN + bnad->netdev->mtu + ETH_FCS_LEN;
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ bna_port_mtu_set(&bnad->bna.port, mtu, NULL);
+ bna_port_pause_config(&bnad->bna.port, &pause_config, NULL);
+ bna_port_enable(&bnad->bna.port);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+ /* Enable broadcast */
+ bnad_enable_default_bcast(bnad);
+
+ /* Set the UCAST address */
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ bnad_mac_addr_set_locked(bnad, netdev->dev_addr);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+ /* Start the stats timer */
+ bnad_stats_timer_start(bnad);
+
+ mutex_unlock(&bnad->conf_mutex);
+
+ return 0;
+
+cleanup_tx:
+ bnad_cleanup_tx(bnad, 0);
+
+err_return:
+ mutex_unlock(&bnad->conf_mutex);
+ return err;
+}
+
+static int
+bnad_stop(struct net_device *netdev)
+{
+ struct bnad *bnad = netdev_priv(netdev);
+ unsigned long flags;
+
+ mutex_lock(&bnad->conf_mutex);
+
+ /* Stop the stats timer */
+ bnad_stats_timer_stop(bnad);
+
+ init_completion(&bnad->bnad_completions.port_comp);
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ bna_port_disable(&bnad->bna.port, BNA_HARD_CLEANUP,
+ bnad_cb_port_disabled);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+ wait_for_completion(&bnad->bnad_completions.port_comp);
+
+ bnad_cleanup_tx(bnad, 0);
+ bnad_cleanup_rx(bnad, 0);
+
+ /* Synchronize mailbox IRQ */
+ bnad_mbox_irq_sync(bnad);
+
+ mutex_unlock(&bnad->conf_mutex);
+
+ return 0;
+}
+
+/* TX */
+/*
+ * bnad_start_xmit : Netdev entry point for Transmit
+ * Called under lock held by net_device
+ */
+static netdev_tx_t
+bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
+{
+ struct bnad *bnad = netdev_priv(netdev);
+
+ u16 txq_prod, vlan_tag = 0;
+ u32 unmap_prod, wis, wis_used, wi_range;
+ u32 vectors, vect_id, i, acked;
+ u32 tx_id;
+ int err;
+
+ struct bnad_tx_info *tx_info;
+ struct bna_tcb *tcb;
+ struct bnad_unmap_q *unmap_q;
+ dma_addr_t dma_addr;
+ struct bna_txq_entry *txqent;
+ bna_txq_wi_ctrl_flag_t flags;
+
+ if (unlikely
+ (skb->len <= ETH_HLEN || skb->len > BFI_TX_MAX_DATA_PER_PKT)) {
+ dev_kfree_skb(skb);
+ return NETDEV_TX_OK;
+ }
+
+ /*
+ * Takes care of the Tx that is scheduled between clearing the flag
+ * and the netif_stop_queue() call.
+ */
+ if (unlikely(!test_bit(BNAD_RF_TX_STARTED, &bnad->run_flags))) {
+ dev_kfree_skb(skb);
+ return NETDEV_TX_OK;
+ }
+
+ tx_id = 0;
+
+ tx_info = &bnad->tx_info[tx_id];
+ tcb = tx_info->tcb[tx_id];
+ unmap_q = tcb->unmap_q;
+
+ vectors = 1 + skb_shinfo(skb)->nr_frags;
+ if (vectors > BFI_TX_MAX_VECTORS_PER_PKT) {
+ dev_kfree_skb(skb);
+ return NETDEV_TX_OK;
+ }
+ wis = BNA_TXQ_WI_NEEDED(vectors); /* 4 vectors per work item */
+ acked = 0;
+ if (unlikely
+ (wis > BNA_QE_FREE_CNT(tcb, tcb->q_depth) ||
+ vectors > BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth))) {
+ if ((u16) (*tcb->hw_consumer_index) !=
+ tcb->consumer_index &&
+ !test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags)) {
+ acked = bnad_free_txbufs(bnad, tcb);
+ bna_ib_ack(tcb->i_dbell, acked);
+ smp_mb__before_clear_bit();
+ clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
+ } else {
+ netif_stop_queue(netdev);
+ BNAD_UPDATE_CTR(bnad, netif_queue_stop);
+ }
+
+ smp_mb();
+ /*
+ * Check again to deal with race condition between
+ * netif_stop_queue here, and netif_wake_queue in
+ * interrupt handler which is not inside netif tx lock.
+ */
+ if (likely
+ (wis > BNA_QE_FREE_CNT(tcb, tcb->q_depth) ||
+ vectors > BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth))) {
+ BNAD_UPDATE_CTR(bnad, netif_queue_stop);
+ return NETDEV_TX_BUSY;
+ } else {
+ netif_wake_queue(netdev);
+ BNAD_UPDATE_CTR(bnad, netif_queue_wakeup);
+ }
+ }
+
+ unmap_prod = unmap_q->producer_index;
+ wis_used = 1;
+ vect_id = 0;
+ flags = 0;
+
+ txq_prod = tcb->producer_index;
+ BNA_TXQ_QPGE_PTR_GET(txq_prod, tcb->sw_qpt, txqent, wi_range);
+ BUG_ON(!(wi_range <= tcb->q_depth));
+ txqent->hdr.wi.reserved = 0;
+ txqent->hdr.wi.num_vectors = vectors;
+ txqent->hdr.wi.opcode =
+ htons((skb_is_gso(skb) ? BNA_TXQ_WI_SEND_LSO :
+ BNA_TXQ_WI_SEND));
+
+ if (vlan_tx_tag_present(skb)) {
+ vlan_tag = (u16) vlan_tx_tag_get(skb);
+ flags |= (BNA_TXQ_WI_CF_INS_PRIO | BNA_TXQ_WI_CF_INS_VLAN);
+ }
+ if (test_bit(BNAD_RF_CEE_RUNNING, &bnad->run_flags)) {
+ vlan_tag =
+ (tcb->priority & 0x7) << 13 | (vlan_tag & 0x1fff);
+ flags |= (BNA_TXQ_WI_CF_INS_PRIO | BNA_TXQ_WI_CF_INS_VLAN);
+ }
+
+ txqent->hdr.wi.vlan_tag = htons(vlan_tag);
+
+ if (skb_is_gso(skb)) {
+ err = bnad_tso_prepare(bnad, skb);
+ if (err) {
+ dev_kfree_skb(skb);
+ return NETDEV_TX_OK;
+ }
+ txqent->hdr.wi.lso_mss = htons(skb_is_gso(skb));
+ flags |= (BNA_TXQ_WI_CF_IP_CKSUM | BNA_TXQ_WI_CF_TCP_CKSUM);
+ txqent->hdr.wi.l4_hdr_size_n_offset =
+ htons(BNA_TXQ_WI_L4_HDR_N_OFFSET
+ (tcp_hdrlen(skb) >> 2,
+ skb_transport_offset(skb)));
+ } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ u8 proto = 0;
+
+ txqent->hdr.wi.lso_mss = 0;
+
+ if (skb->protocol == htons(ETH_P_IP))
+ proto = ip_hdr(skb)->protocol;
+ else if (skb->protocol == htons(ETH_P_IPV6)) {
+ /* nexthdr may not be TCP immediately. */
+ proto = ipv6_hdr(skb)->nexthdr;
+ }
+ if (proto == IPPROTO_TCP) {
+ flags |= BNA_TXQ_WI_CF_TCP_CKSUM;
+ txqent->hdr.wi.l4_hdr_size_n_offset =
+ htons(BNA_TXQ_WI_L4_HDR_N_OFFSET
+ (0, skb_transport_offset(skb)));
+
+ BNAD_UPDATE_CTR(bnad, tcpcsum_offload);
+
+ BUG_ON(!(skb_headlen(skb) >=
+ skb_transport_offset(skb) + tcp_hdrlen(skb)));
+
+ } else if (proto == IPPROTO_UDP) {
+ flags |= BNA_TXQ_WI_CF_UDP_CKSUM;
+ txqent->hdr.wi.l4_hdr_size_n_offset =
+ htons(BNA_TXQ_WI_L4_HDR_N_OFFSET
+ (0, skb_transport_offset(skb)));
+
+ BNAD_UPDATE_CTR(bnad, udpcsum_offload);
+
+ BUG_ON(!(skb_headlen(skb) >=
+ skb_transport_offset(skb) +
+ sizeof(struct udphdr)));
+ } else {
+ err = skb_checksum_help(skb);
+ BNAD_UPDATE_CTR(bnad, csum_help);
+ if (err) {
+ dev_kfree_skb(skb);
+ BNAD_UPDATE_CTR(bnad, csum_help_err);
+ return NETDEV_TX_OK;
+ }
+ }
+ } else {
+ txqent->hdr.wi.lso_mss = 0;
+ txqent->hdr.wi.l4_hdr_size_n_offset = 0;
+ }
+
+ txqent->hdr.wi.flags = htons(flags);
+
+ txqent->hdr.wi.frame_length = htonl(skb->len);
+
+ unmap_q->unmap_array[unmap_prod].skb = skb;
+ BUG_ON(!(skb_headlen(skb) <= BFI_TX_MAX_DATA_PER_VECTOR));
+ txqent->vector[vect_id].length = htons(skb_headlen(skb));
+ dma_addr = pci_map_single(bnad->pcidev, skb->data, skb_headlen(skb),
+ PCI_DMA_TODEVICE);
+ pci_unmap_addr_set(&unmap_q->unmap_array[unmap_prod], dma_addr,
+ dma_addr);
+
+ BNA_SET_DMA_ADDR(dma_addr, &txqent->vector[vect_id].host_addr);
+ BNA_QE_INDX_ADD(unmap_prod, 1, unmap_q->q_depth);
+
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+ struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
+ u32 size = frag->size;
+
+ if (++vect_id == BFI_TX_MAX_VECTORS_PER_WI) {
+ vect_id = 0;
+ if (--wi_range)
+ txqent++;
+ else {
+ BNA_QE_INDX_ADD(txq_prod, wis_used,
+ tcb->q_depth);
+ wis_used = 0;
+ BNA_TXQ_QPGE_PTR_GET(txq_prod, tcb->sw_qpt,
+ txqent, wi_range);
+ BUG_ON(!(wi_range <= tcb->q_depth));
+ }
+ wis_used++;
+ txqent->hdr.wi_ext.opcode = htons(BNA_TXQ_WI_EXTENSION);
+ }
+
+ BUG_ON(!(size <= BFI_TX_MAX_DATA_PER_VECTOR));
+ txqent->vector[vect_id].length = htons(size);
+ dma_addr =
+ pci_map_page(bnad->pcidev, frag->page,
+ frag->page_offset, size,
+ PCI_DMA_TODEVICE);
+ pci_unmap_addr_set(&unmap_q->unmap_array[unmap_prod], dma_addr,
+ dma_addr);
+ BNA_SET_DMA_ADDR(dma_addr, &txqent->vector[vect_id].host_addr);
+ BNA_QE_INDX_ADD(unmap_prod, 1, unmap_q->q_depth);
+ }
+
+ unmap_q->producer_index = unmap_prod;
+ BNA_QE_INDX_ADD(txq_prod, wis_used, tcb->q_depth);
+ tcb->producer_index = txq_prod;
+
+ smp_mb();
+ bna_txq_prod_indx_doorbell(tcb);
+
+ if ((u16) (*tcb->hw_consumer_index) != tcb->consumer_index)
+ tasklet_schedule(&bnad->tx_free_tasklet);
+
+ return NETDEV_TX_OK;
+}
+
+/*
+ * Used spin_lock to synchronize reading of stats structures, which
+ * is written by BNA under the same lock.
+ */
+static struct rtnl_link_stats64 *
+bnad_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats)
+{
+ struct bnad *bnad = netdev_priv(netdev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+
+ bnad_netdev_qstats_fill(bnad, stats);
+ bnad_netdev_hwstats_fill(bnad, stats);
+
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+ return stats;
+}
+
+static void
+bnad_set_rx_mode(struct net_device *netdev)
+{
+ struct bnad *bnad = netdev_priv(netdev);
+ u32 new_mask, valid_mask;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+
+ new_mask = valid_mask = 0;
+
+ if (netdev->flags & IFF_PROMISC) {
+ if (!(bnad->cfg_flags & BNAD_CF_PROMISC)) {
+ new_mask = BNAD_RXMODE_PROMISC_DEFAULT;
+ valid_mask = BNAD_RXMODE_PROMISC_DEFAULT;
+ bnad->cfg_flags |= BNAD_CF_PROMISC;
+ }
+ } else {
+ if (bnad->cfg_flags & BNAD_CF_PROMISC) {
+ new_mask = ~BNAD_RXMODE_PROMISC_DEFAULT;
+ valid_mask = BNAD_RXMODE_PROMISC_DEFAULT;
+ bnad->cfg_flags &= ~BNAD_CF_PROMISC;
+ }
+ }
+
+ if (netdev->flags & IFF_ALLMULTI) {
+ if (!(bnad->cfg_flags & BNAD_CF_ALLMULTI)) {
+ new_mask |= BNA_RXMODE_ALLMULTI;
+ valid_mask |= BNA_RXMODE_ALLMULTI;
+ bnad->cfg_flags |= BNAD_CF_ALLMULTI;
+ }
+ } else {
+ if (bnad->cfg_flags & BNAD_CF_ALLMULTI) {
+ new_mask &= ~BNA_RXMODE_ALLMULTI;
+ valid_mask |= BNA_RXMODE_ALLMULTI;
+ bnad->cfg_flags &= ~BNAD_CF_ALLMULTI;
+ }
+ }
+
+ bna_rx_mode_set(bnad->rx_info[0].rx, new_mask, valid_mask, NULL);
+
+ if (!netdev_mc_empty(netdev)) {
+ u8 *mcaddr_list;
+ int mc_count = netdev_mc_count(netdev);
+
+ /* Index 0 holds the broadcast address */
+ mcaddr_list =
+ kzalloc((mc_count + 1) * ETH_ALEN,
+ GFP_ATOMIC);
+ if (!mcaddr_list)
+ goto unlock;
+
+ memcpy(&mcaddr_list[0], &bnad_bcast_addr[0], ETH_ALEN);
+
+ /* Copy rest of the MC addresses */
+ bnad_netdev_mc_list_get(netdev, mcaddr_list);
+
+ bna_rx_mcast_listset(bnad->rx_info[0].rx, mc_count + 1,
+ mcaddr_list, NULL);
+
+ /* Should we enable BNAD_CF_ALLMULTI for err != 0 ? */
+ kfree(mcaddr_list);
+ }
+unlock:
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+}
+
+/*
+ * bna_lock is used to sync writes to netdev->addr
+ * conf_lock cannot be used since this call may be made
+ * in a non-blocking context.
+ */
+static int
+bnad_set_mac_address(struct net_device *netdev, void *mac_addr)
+{
+ int err;
+ struct bnad *bnad = netdev_priv(netdev);
+ struct sockaddr *sa = (struct sockaddr *)mac_addr;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+
+ err = bnad_mac_addr_set_locked(bnad, sa->sa_data);
+
+ if (!err)
+ memcpy(netdev->dev_addr, sa->sa_data, netdev->addr_len);
+
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+ return err;
+}
+
+static int
+bnad_change_mtu(struct net_device *netdev, int new_mtu)
+{
+ int mtu, err = 0;
+ unsigned long flags;
+
+ struct bnad *bnad = netdev_priv(netdev);
+
+ if (new_mtu + ETH_HLEN < ETH_ZLEN || new_mtu > BNAD_JUMBO_MTU)
+ return -EINVAL;
+
+ mutex_lock(&bnad->conf_mutex);
+
+ netdev->mtu = new_mtu;
+
+ mtu = ETH_HLEN + new_mtu + ETH_FCS_LEN;
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ bna_port_mtu_set(&bnad->bna.port, mtu, NULL);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+ mutex_unlock(&bnad->conf_mutex);
+ return err;
+}
+
+static void
+bnad_vlan_rx_register(struct net_device *netdev,
+ struct vlan_group *vlan_grp)
+{
+ struct bnad *bnad = netdev_priv(netdev);
+
+ mutex_lock(&bnad->conf_mutex);
+ bnad->vlan_grp = vlan_grp;
+ mutex_unlock(&bnad->conf_mutex);
+}
+
+static void
+bnad_vlan_rx_add_vid(struct net_device *netdev,
+ unsigned short vid)
+{
+ struct bnad *bnad = netdev_priv(netdev);
+ unsigned long flags;
+
+ if (!bnad->rx_info[0].rx)
+ return;
+
+ mutex_lock(&bnad->conf_mutex);
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ bna_rx_vlan_add(bnad->rx_info[0].rx, vid);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+ mutex_unlock(&bnad->conf_mutex);
+}
+
+static void
+bnad_vlan_rx_kill_vid(struct net_device *netdev,
+ unsigned short vid)
+{
+ struct bnad *bnad = netdev_priv(netdev);
+ unsigned long flags;
+
+ if (!bnad->rx_info[0].rx)
+ return;
+
+ mutex_lock(&bnad->conf_mutex);
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ bna_rx_vlan_del(bnad->rx_info[0].rx, vid);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+ mutex_unlock(&bnad->conf_mutex);
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void
+bnad_netpoll(struct net_device *netdev)
+{
+ struct bnad *bnad = netdev_priv(netdev);
+ struct bnad_rx_info *rx_info;
+ struct bnad_rx_ctrl *rx_ctrl;
+ u32 curr_mask;
+ int i, j;
+
+ if (!(bnad->cfg_flags & BNAD_CF_MSIX)) {
+ bna_intx_disable(&bnad->bna, curr_mask);
+ bnad_isr(bnad->pcidev->irq, netdev);
+ bna_intx_enable(&bnad->bna, curr_mask);
+ } else {
+ for (i = 0; i < bnad->num_rx; i++) {
+ rx_info = &bnad->rx_info[i];
+ if (!rx_info->rx)
+ continue;
+ for (j = 0; j < bnad->num_rxp_per_rx; j++) {
+ rx_ctrl = &rx_info->rx_ctrl[j];
+ if (rx_ctrl->ccb) {
+ bnad_disable_rx_irq(bnad,
+ rx_ctrl->ccb);
+ bnad_netif_rx_schedule_poll(bnad,
+ rx_ctrl->ccb);
+ }
+ }
+ }
+ }
+}
+#endif
+
+static const struct net_device_ops bnad_netdev_ops = {
+ .ndo_open = bnad_open,
+ .ndo_stop = bnad_stop,
+ .ndo_start_xmit = bnad_start_xmit,
+ .ndo_get_stats64 = bnad_get_stats64,
+ .ndo_set_rx_mode = bnad_set_rx_mode,
+ .ndo_set_multicast_list = bnad_set_rx_mode,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = bnad_set_mac_address,
+ .ndo_change_mtu = bnad_change_mtu,
+ .ndo_vlan_rx_register = bnad_vlan_rx_register,
+ .ndo_vlan_rx_add_vid = bnad_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = bnad_vlan_rx_kill_vid,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = bnad_netpoll
+#endif
+};
+
+static void
+bnad_netdev_init(struct bnad *bnad, bool using_dac)
+{
+ struct net_device *netdev = bnad->netdev;
+
+ netdev->features |= NETIF_F_IPV6_CSUM;
+ netdev->features |= NETIF_F_TSO;
+ netdev->features |= NETIF_F_TSO6;
+
+ netdev->features |= NETIF_F_GRO;
+ pr_warn("bna: GRO enabled, using kernel stack GRO\n");
+
+ netdev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
+
+ if (using_dac)
+ netdev->features |= NETIF_F_HIGHDMA;
+
+ netdev->features |=
+ NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX |
+ NETIF_F_HW_VLAN_FILTER;
+
+ netdev->vlan_features = netdev->features;
+ netdev->mem_start = bnad->mmio_start;
+ netdev->mem_end = bnad->mmio_start + bnad->mmio_len - 1;
+
+ netdev->netdev_ops = &bnad_netdev_ops;
+ bnad_set_ethtool_ops(netdev);
+}
+
+/*
+ * 1. Initialize the bnad structure
+ * 2. Setup netdev pointer in pci_dev
+ * 3. Initialze Tx free tasklet
+ * 4. Initialize no. of TxQ & CQs & MSIX vectors
+ */
+static int
+bnad_init(struct bnad *bnad,
+ struct pci_dev *pdev, struct net_device *netdev)
+{
+ unsigned long flags;
+
+ SET_NETDEV_DEV(netdev, &pdev->dev);
+ pci_set_drvdata(pdev, netdev);
+
+ bnad->netdev = netdev;
+ bnad->pcidev = pdev;
+ bnad->mmio_start = pci_resource_start(pdev, 0);
+ bnad->mmio_len = pci_resource_len(pdev, 0);
+ bnad->bar0 = ioremap_nocache(bnad->mmio_start, bnad->mmio_len);
+ if (!bnad->bar0) {
+ dev_err(&pdev->dev, "ioremap for bar0 failed\n");
+ pci_set_drvdata(pdev, NULL);
+ return -ENOMEM;
+ }
+ pr_info("bar0 mapped to %p, len %llu\n", bnad->bar0,
+ (unsigned long long) bnad->mmio_len);
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ if (!bnad_msix_disable)
+ bnad->cfg_flags = BNAD_CF_MSIX;
+
+ bnad->cfg_flags |= BNAD_CF_DIM_ENABLED;
+
+ bnad_q_num_init(bnad);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+ bnad->msix_num = (bnad->num_tx * bnad->num_txq_per_tx) +
+ (bnad->num_rx * bnad->num_rxp_per_rx) +
+ BNAD_MAILBOX_MSIX_VECTORS;
+
+ bnad->txq_depth = BNAD_TXQ_DEPTH;
+ bnad->rxq_depth = BNAD_RXQ_DEPTH;
+ bnad->rx_csum = true;
+
+ bnad->tx_coalescing_timeo = BFI_TX_COALESCING_TIMEO;
+ bnad->rx_coalescing_timeo = BFI_RX_COALESCING_TIMEO;
+
+ tasklet_init(&bnad->tx_free_tasklet, bnad_tx_free_tasklet,
+ (unsigned long)bnad);
+
+ return 0;
+}
+
+/*
+ * Must be called after bnad_pci_uninit()
+ * so that iounmap() and pci_set_drvdata(NULL)
+ * happens only after PCI uninitialization.
+ */
+static void
+bnad_uninit(struct bnad *bnad)
+{
+ if (bnad->bar0)
+ iounmap(bnad->bar0);
+ pci_set_drvdata(bnad->pcidev, NULL);
+}
+
+/*
+ * Initialize locks
+ a) Per device mutes used for serializing configuration
+ changes from OS interface
+ b) spin lock used to protect bna state machine
+ */
+static void
+bnad_lock_init(struct bnad *bnad)
+{
+ spin_lock_init(&bnad->bna_lock);
+ mutex_init(&bnad->conf_mutex);
+}
+
+static void
+bnad_lock_uninit(struct bnad *bnad)
+{
+ mutex_destroy(&bnad->conf_mutex);
+}
+
+/* PCI Initialization */
+static int
+bnad_pci_init(struct bnad *bnad,
+ struct pci_dev *pdev, bool *using_dac)
+{
+ int err;
+
+ err = pci_enable_device(pdev);
+ if (err)
+ return err;
+ err = pci_request_regions(pdev, BNAD_NAME);
+ if (err)
+ goto disable_device;
+ if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) &&
+ !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) {
+ *using_dac = 1;
+ } else {
+ err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+ if (err) {
+ err = pci_set_consistent_dma_mask(pdev,
+ DMA_BIT_MASK(32));
+ if (err)
+ goto release_regions;
+ }
+ *using_dac = 0;
+ }
+ pci_set_master(pdev);
+ return 0;
+
+release_regions:
+ pci_release_regions(pdev);
+disable_device:
+ pci_disable_device(pdev);
+
+ return err;
+}
+
+static void
+bnad_pci_uninit(struct pci_dev *pdev)
+{
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+}
+
+static int __devinit
+bnad_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *pcidev_id)
+{
+ bool using_dac;
+ int err;
+ struct bnad *bnad;
+ struct bna *bna;
+ struct net_device *netdev;
+ struct bfa_pcidev pcidev_info;
+ unsigned long flags;
+
+ pr_info("bnad_pci_probe : (0x%p, 0x%p) PCI Func : (%d)\n",
+ pdev, pcidev_id, PCI_FUNC(pdev->devfn));
+
+ mutex_lock(&bnad_fwimg_mutex);
+ if (!cna_get_firmware_buf(pdev)) {
+ mutex_unlock(&bnad_fwimg_mutex);
+ pr_warn("Failed to load Firmware Image!\n");
+ return -ENODEV;
+ }
+ mutex_unlock(&bnad_fwimg_mutex);
+
+ /*
+ * Allocates sizeof(struct net_device + struct bnad)
+ * bnad = netdev->priv
+ */
+ netdev = alloc_etherdev(sizeof(struct bnad));
+ if (!netdev) {
+ dev_err(&pdev->dev, "alloc_etherdev failed\n");
+ err = -ENOMEM;
+ return err;
+ }
+ bnad = netdev_priv(netdev);
+
+ /*
+ * PCI initialization
+ * Output : using_dac = 1 for 64 bit DMA
+ * = 0 for 32 bit DMA
+ */
+ err = bnad_pci_init(bnad, pdev, &using_dac);
+ if (err)
+ goto free_netdev;
+
+ bnad_lock_init(bnad);
+ /*
+ * Initialize bnad structure
+ * Setup relation between pci_dev & netdev
+ * Init Tx free tasklet
+ */
+ err = bnad_init(bnad, pdev, netdev);
+ if (err)
+ goto pci_uninit;
+ /* Initialize netdev structure, set up ethtool ops */
+ bnad_netdev_init(bnad, using_dac);
+
+ bnad_enable_msix(bnad);
+
+ /* Get resource requirement form bna */
+ bna_res_req(&bnad->res_info[0]);
+
+ /* Allocate resources from bna */
+ err = bnad_res_alloc(bnad);
+ if (err)
+ goto free_netdev;
+
+ bna = &bnad->bna;
+
+ /* Setup pcidev_info for bna_init() */
+ pcidev_info.pci_slot = PCI_SLOT(bnad->pcidev->devfn);
+ pcidev_info.pci_func = PCI_FUNC(bnad->pcidev->devfn);
+ pcidev_info.device_id = bnad->pcidev->device;
+ pcidev_info.pci_bar_kva = bnad->bar0;
+
+ mutex_lock(&bnad->conf_mutex);
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ bna_init(bna, bnad, &pcidev_info, &bnad->res_info[0]);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+ bnad->stats.bna_stats = &bna->stats;
+
+ /* Set up timers */
+ setup_timer(&bnad->bna.device.ioc.ioc_timer, bnad_ioc_timeout,
+ ((unsigned long)bnad));
+ setup_timer(&bnad->bna.device.ioc.hb_timer, bnad_ioc_hb_check,
+ ((unsigned long)bnad));
+ setup_timer(&bnad->bna.device.ioc.sem_timer, bnad_ioc_sem_timeout,
+ ((unsigned long)bnad));
+
+ /* Now start the timer before calling IOC */
+ mod_timer(&bnad->bna.device.ioc.ioc_timer,
+ jiffies + msecs_to_jiffies(BNA_IOC_TIMER_FREQ));
+
+ /*
+ * Start the chip
+ * Don't care even if err != 0, bna state machine will
+ * deal with it
+ */
+ err = bnad_device_enable(bnad);
+
+ /* Get the burnt-in mac */
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ bna_port_mac_get(&bna->port, &bnad->perm_addr);
+ bnad_set_netdev_perm_addr(bnad);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+ mutex_unlock(&bnad->conf_mutex);
+
+ /*
+ * Make sure the link appears down to the stack
+ */
+ netif_carrier_off(netdev);
+
+ /* Finally, reguister with net_device layer */
+ err = register_netdev(netdev);
+ if (err) {
+ pr_err("BNA : Registering with netdev failed\n");
+ goto disable_device;
+ }
+
+ return 0;
+
+disable_device:
+ mutex_lock(&bnad->conf_mutex);
+ bnad_device_disable(bnad);
+ del_timer_sync(&bnad->bna.device.ioc.ioc_timer);
+ del_timer_sync(&bnad->bna.device.ioc.sem_timer);
+ del_timer_sync(&bnad->bna.device.ioc.hb_timer);
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ bna_uninit(bna);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+ mutex_unlock(&bnad->conf_mutex);
+
+ bnad_res_free(bnad);
+ bnad_disable_msix(bnad);
+pci_uninit:
+ bnad_pci_uninit(pdev);
+ bnad_lock_uninit(bnad);
+ bnad_uninit(bnad);
+free_netdev:
+ free_netdev(netdev);
+ return err;
+}
+
+static void __devexit
+bnad_pci_remove(struct pci_dev *pdev)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct bnad *bnad;
+ struct bna *bna;
+ unsigned long flags;
+
+ if (!netdev)
+ return;
+
+ pr_info("%s bnad_pci_remove\n", netdev->name);
+ bnad = netdev_priv(netdev);
+ bna = &bnad->bna;
+
+ unregister_netdev(netdev);
+
+ mutex_lock(&bnad->conf_mutex);
+ bnad_device_disable(bnad);
+ del_timer_sync(&bnad->bna.device.ioc.ioc_timer);
+ del_timer_sync(&bnad->bna.device.ioc.sem_timer);
+ del_timer_sync(&bnad->bna.device.ioc.hb_timer);
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ bna_uninit(bna);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+ mutex_unlock(&bnad->conf_mutex);
+
+ bnad_res_free(bnad);
+ bnad_disable_msix(bnad);
+ bnad_pci_uninit(pdev);
+ bnad_lock_uninit(bnad);
+ bnad_uninit(bnad);
+ free_netdev(netdev);
+}
+
+static const struct pci_device_id bnad_pci_id_table[] = {
+ {
+ PCI_DEVICE(PCI_VENDOR_ID_BROCADE,
+ PCI_DEVICE_ID_BROCADE_CT),
+ .class = PCI_CLASS_NETWORK_ETHERNET << 8,
+ .class_mask = 0xffff00
+ }, {0, }
+};
+
+MODULE_DEVICE_TABLE(pci, bnad_pci_id_table);
+
+static struct pci_driver bnad_pci_driver = {
+ .name = BNAD_NAME,
+ .id_table = bnad_pci_id_table,
+ .probe = bnad_pci_probe,
+ .remove = __devexit_p(bnad_pci_remove),
+};
+
+static int __init
+bnad_module_init(void)
+{
+ int err;
+
+ pr_info("Brocade 10G Ethernet driver\n");
+
+ bfa_nw_ioc_auto_recover(bnad_ioc_auto_recover);
+
+ err = pci_register_driver(&bnad_pci_driver);
+ if (err < 0) {
+ pr_err("bna : PCI registration failed in module init "
+ "(%d)\n", err);
+ return err;
+ }
+
+ return 0;
+}
+
+static void __exit
+bnad_module_exit(void)
+{
+ pci_unregister_driver(&bnad_pci_driver);
+
+ if (bfi_fw)
+ release_firmware(bfi_fw);
+}
+
+module_init(bnad_module_init);
+module_exit(bnad_module_exit);
+
+MODULE_AUTHOR("Brocade");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Brocade 10G PCIe Ethernet driver");
+MODULE_VERSION(BNAD_VERSION);
+MODULE_FIRMWARE(CNA_FW_FILE_CT);
diff --git a/drivers/net/bna/bnad.h b/drivers/net/bna/bnad.h
new file mode 100644
index 000000000000..ebc3a9078642
--- /dev/null
+++ b/drivers/net/bna/bnad.h
@@ -0,0 +1,332 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+#ifndef __BNAD_H__
+#define __BNAD_H__
+
+#include <linux/rtnetlink.h>
+#include <linux/workqueue.h>
+#include <linux/ipv6.h>
+#include <linux/etherdevice.h>
+#include <linux/mutex.h>
+#include <linux/firmware.h>
+
+/* Fix for IA64 */
+#include <asm/checksum.h>
+#include <net/ip6_checksum.h>
+
+#include <net/ip.h>
+#include <net/tcp.h>
+
+#include "bna.h"
+
+#define BNAD_TXQ_DEPTH 2048
+#define BNAD_RXQ_DEPTH 2048
+
+#define BNAD_MAX_TXS 1
+#define BNAD_MAX_TXQ_PER_TX 8 /* 8 priority queues */
+#define BNAD_TXQ_NUM 1
+
+#define BNAD_MAX_RXS 1
+#define BNAD_MAX_RXPS_PER_RX 16
+
+/*
+ * Control structure pointed to ccb->ctrl, which
+ * determines the NAPI / LRO behavior CCB
+ * There is 1:1 corres. between ccb & ctrl
+ */
+struct bnad_rx_ctrl {
+ struct bna_ccb *ccb;
+ struct napi_struct napi;
+};
+
+#define BNAD_RXMODE_PROMISC_DEFAULT BNA_RXMODE_PROMISC
+
+#define BNAD_GET_TX_ID(_skb) (0)
+
+/*
+ * GLOBAL #defines (CONSTANTS)
+ */
+#define BNAD_NAME "bna"
+#define BNAD_NAME_LEN 64
+
+#define BNAD_VERSION "2.3.2.0"
+
+#define BNAD_MAILBOX_MSIX_VECTORS 1
+
+#define BNAD_STATS_TIMER_FREQ 1000 /* in msecs */
+#define BNAD_DIM_TIMER_FREQ 1000 /* in msecs */
+
+#define BNAD_MAX_Q_DEPTH 0x10000
+#define BNAD_MIN_Q_DEPTH 0x200
+
+#define BNAD_JUMBO_MTU 9000
+
+#define BNAD_NETIF_WAKE_THRESHOLD 8
+
+#define BNAD_RXQ_REFILL_THRESHOLD_SHIFT 3
+
+/* Bit positions for tcb->flags */
+#define BNAD_TXQ_FREE_SENT 0
+
+/* Bit positions for rcb->flags */
+#define BNAD_RXQ_REFILL 0
+#define BNAD_RXQ_STARTED 1
+
+/*
+ * DATA STRUCTURES
+ */
+
+/* enums */
+enum bnad_intr_source {
+ BNAD_INTR_TX = 1,
+ BNAD_INTR_RX = 2
+};
+
+enum bnad_link_state {
+ BNAD_LS_DOWN = 0,
+ BNAD_LS_UP = 1
+};
+
+struct bnad_completion {
+ struct completion ioc_comp;
+ struct completion ucast_comp;
+ struct completion mcast_comp;
+ struct completion tx_comp;
+ struct completion rx_comp;
+ struct completion stats_comp;
+ struct completion port_comp;
+
+ u8 ioc_comp_status;
+ u8 ucast_comp_status;
+ u8 mcast_comp_status;
+ u8 tx_comp_status;
+ u8 rx_comp_status;
+ u8 stats_comp_status;
+ u8 port_comp_status;
+};
+
+/* Tx Rx Control Stats */
+struct bnad_drv_stats {
+ u64 netif_queue_stop;
+ u64 netif_queue_wakeup;
+ u64 tso4;
+ u64 tso6;
+ u64 tso_err;
+ u64 tcpcsum_offload;
+ u64 udpcsum_offload;
+ u64 csum_help;
+ u64 csum_help_err;
+
+ u64 hw_stats_updates;
+ u64 netif_rx_schedule;
+ u64 netif_rx_complete;
+ u64 netif_rx_dropped;
+
+ u64 link_toggle;
+ u64 cee_up;
+
+ u64 rxp_info_alloc_failed;
+ u64 mbox_intr_disabled;
+ u64 mbox_intr_enabled;
+ u64 tx_unmap_q_alloc_failed;
+ u64 rx_unmap_q_alloc_failed;
+
+ u64 rxbuf_alloc_failed;
+};
+
+/* Complete driver stats */
+struct bnad_stats {
+ struct bnad_drv_stats drv_stats;
+ struct bna_stats *bna_stats;
+};
+
+/* Tx / Rx Resources */
+struct bnad_tx_res_info {
+ struct bna_res_info res_info[BNA_TX_RES_T_MAX];
+};
+
+struct bnad_rx_res_info {
+ struct bna_res_info res_info[BNA_RX_RES_T_MAX];
+};
+
+struct bnad_tx_info {
+ struct bna_tx *tx; /* 1:1 between tx_info & tx */
+ struct bna_tcb *tcb[BNAD_MAX_TXQ_PER_TX];
+} ____cacheline_aligned;
+
+struct bnad_rx_info {
+ struct bna_rx *rx; /* 1:1 between rx_info & rx */
+
+ struct bnad_rx_ctrl rx_ctrl[BNAD_MAX_RXPS_PER_RX];
+} ____cacheline_aligned;
+
+/* Unmap queues for Tx / Rx cleanup */
+struct bnad_skb_unmap {
+ struct sk_buff *skb;
+ DECLARE_PCI_UNMAP_ADDR(dma_addr)
+};
+
+struct bnad_unmap_q {
+ u32 producer_index;
+ u32 consumer_index;
+ u32 q_depth;
+ /* This should be the last one */
+ struct bnad_skb_unmap unmap_array[1];
+};
+
+/* Bit mask values for bnad->cfg_flags */
+#define BNAD_CF_DIM_ENABLED 0x01 /* DIM */
+#define BNAD_CF_PROMISC 0x02
+#define BNAD_CF_ALLMULTI 0x04
+#define BNAD_CF_MSIX 0x08 /* If in MSIx mode */
+
+/* Defines for run_flags bit-mask */
+/* Set, tested & cleared using xxx_bit() functions */
+/* Values indicated bit positions */
+#define BNAD_RF_CEE_RUNNING 1
+#define BNAD_RF_HW_ERROR 2
+#define BNAD_RF_MBOX_IRQ_DISABLED 3
+#define BNAD_RF_TX_STARTED 4
+#define BNAD_RF_RX_STARTED 5
+#define BNAD_RF_DIM_TIMER_RUNNING 6
+#define BNAD_RF_STATS_TIMER_RUNNING 7
+
+struct bnad {
+ struct net_device *netdev;
+
+ /* Data path */
+ struct bnad_tx_info tx_info[BNAD_MAX_TXS];
+ struct bnad_rx_info rx_info[BNAD_MAX_RXS];
+
+ struct vlan_group *vlan_grp;
+ /*
+ * These q numbers are global only because
+ * they are used to calculate MSIx vectors.
+ * Actually the exact # of queues are per Tx/Rx
+ * object.
+ */
+ u32 num_tx;
+ u32 num_rx;
+ u32 num_txq_per_tx;
+ u32 num_rxp_per_rx;
+
+ u32 txq_depth;
+ u32 rxq_depth;
+
+ u8 tx_coalescing_timeo;
+ u8 rx_coalescing_timeo;
+
+ struct bna_rx_config rx_config[BNAD_MAX_RXS];
+ struct bna_tx_config tx_config[BNAD_MAX_TXS];
+
+ u32 rx_csum;
+
+ void __iomem *bar0; /* BAR0 address */
+
+ struct bna bna;
+
+ u32 cfg_flags;
+ unsigned long run_flags;
+
+ struct pci_dev *pcidev;
+ u64 mmio_start;
+ u64 mmio_len;
+
+ u32 msix_num;
+ struct msix_entry *msix_table;
+
+ struct mutex conf_mutex;
+ spinlock_t bna_lock ____cacheline_aligned;
+
+ /* Timers */
+ struct timer_list ioc_timer;
+ struct timer_list dim_timer;
+ struct timer_list stats_timer;
+
+ /* Control path resources, memory & irq */
+ struct bna_res_info res_info[BNA_RES_T_MAX];
+ struct bnad_tx_res_info tx_res_info[BNAD_MAX_TXS];
+ struct bnad_rx_res_info rx_res_info[BNAD_MAX_RXS];
+
+ struct bnad_completion bnad_completions;
+
+ /* Burnt in MAC address */
+ mac_t perm_addr;
+
+ struct tasklet_struct tx_free_tasklet;
+
+ /* Statistics */
+ struct bnad_stats stats;
+
+ struct bnad_diag *diag;
+
+ char adapter_name[BNAD_NAME_LEN];
+ char port_name[BNAD_NAME_LEN];
+ char mbox_irq_name[BNAD_NAME_LEN];
+};
+
+/*
+ * EXTERN VARIABLES
+ */
+extern struct firmware *bfi_fw;
+extern u32 bnad_rxqs_per_cq;
+
+/*
+ * EXTERN PROTOTYPES
+ */
+extern u32 *cna_get_firmware_buf(struct pci_dev *pdev);
+/* Netdev entry point prototypes */
+extern void bnad_set_ethtool_ops(struct net_device *netdev);
+
+/* Configuration & setup */
+extern void bnad_tx_coalescing_timeo_set(struct bnad *bnad);
+extern void bnad_rx_coalescing_timeo_set(struct bnad *bnad);
+
+extern int bnad_setup_rx(struct bnad *bnad, uint rx_id);
+extern int bnad_setup_tx(struct bnad *bnad, uint tx_id);
+extern void bnad_cleanup_tx(struct bnad *bnad, uint tx_id);
+extern void bnad_cleanup_rx(struct bnad *bnad, uint rx_id);
+
+/* Timer start/stop protos */
+extern void bnad_dim_timer_start(struct bnad *bnad);
+
+/* Statistics */
+extern void bnad_netdev_qstats_fill(struct bnad *bnad, struct rtnl_link_stats64 *stats);
+extern void bnad_netdev_hwstats_fill(struct bnad *bnad, struct rtnl_link_stats64 *stats);
+
+/**
+ * MACROS
+ */
+/* To set & get the stats counters */
+#define BNAD_UPDATE_CTR(_bnad, _ctr) \
+ (((_bnad)->stats.drv_stats._ctr)++)
+
+#define BNAD_GET_CTR(_bnad, _ctr) ((_bnad)->stats.drv_stats._ctr)
+
+#define bnad_enable_rx_irq_unsafe(_ccb) \
+{ \
+ bna_ib_coalescing_timer_set((_ccb)->i_dbell, \
+ (_ccb)->rx_coalescing_timeo); \
+ bna_ib_ack((_ccb)->i_dbell, 0); \
+}
+
+#define bnad_dim_timer_running(_bnad) \
+ (((_bnad)->cfg_flags & BNAD_CF_DIM_ENABLED) && \
+ (test_bit(BNAD_RF_DIM_TIMER_RUNNING, &((_bnad)->run_flags))))
+
+#endif /* __BNAD_H__ */
diff --git a/drivers/net/bna/bnad_ethtool.c b/drivers/net/bna/bnad_ethtool.c
new file mode 100644
index 000000000000..11fa2ea842c1
--- /dev/null
+++ b/drivers/net/bna/bnad_ethtool.c
@@ -0,0 +1,1277 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+
+#include "cna.h"
+
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/ethtool.h>
+#include <linux/rtnetlink.h>
+
+#include "bna.h"
+
+#include "bnad.h"
+
+#define BNAD_NUM_TXF_COUNTERS 12
+#define BNAD_NUM_RXF_COUNTERS 10
+#define BNAD_NUM_CQ_COUNTERS 3
+#define BNAD_NUM_RXQ_COUNTERS 6
+#define BNAD_NUM_TXQ_COUNTERS 5
+
+#define BNAD_ETHTOOL_STATS_NUM \
+ (sizeof(struct rtnl_link_stats64) / sizeof(u64) + \
+ sizeof(struct bnad_drv_stats) / sizeof(u64) + \
+ offsetof(struct bfi_ll_stats, rxf_stats[0]) / sizeof(u64))
+
+static char *bnad_net_stats_strings[BNAD_ETHTOOL_STATS_NUM] = {
+ "rx_packets",
+ "tx_packets",
+ "rx_bytes",
+ "tx_bytes",
+ "rx_errors",
+ "tx_errors",
+ "rx_dropped",
+ "tx_dropped",
+ "multicast",
+ "collisions",
+
+ "rx_length_errors",
+ "rx_over_errors",
+ "rx_crc_errors",
+ "rx_frame_errors",
+ "rx_fifo_errors",
+ "rx_missed_errors",
+
+ "tx_aborted_errors",
+ "tx_carrier_errors",
+ "tx_fifo_errors",
+ "tx_heartbeat_errors",
+ "tx_window_errors",
+
+ "rx_compressed",
+ "tx_compressed",
+
+ "netif_queue_stop",
+ "netif_queue_wakeup",
+ "tso4",
+ "tso6",
+ "tso_err",
+ "tcpcsum_offload",
+ "udpcsum_offload",
+ "csum_help",
+ "csum_help_err",
+ "hw_stats_updates",
+ "netif_rx_schedule",
+ "netif_rx_complete",
+ "netif_rx_dropped",
+
+ "link_toggle",
+ "cee_up",
+
+ "rxp_info_alloc_failed",
+ "mbox_intr_disabled",
+ "mbox_intr_enabled",
+ "tx_unmap_q_alloc_failed",
+ "rx_unmap_q_alloc_failed",
+ "rxbuf_alloc_failed",
+
+ "mac_frame_64",
+ "mac_frame_65_127",
+ "mac_frame_128_255",
+ "mac_frame_256_511",
+ "mac_frame_512_1023",
+ "mac_frame_1024_1518",
+ "mac_frame_1518_1522",
+ "mac_rx_bytes",
+ "mac_rx_packets",
+ "mac_rx_fcs_error",
+ "mac_rx_multicast",
+ "mac_rx_broadcast",
+ "mac_rx_control_frames",
+ "mac_rx_pause",
+ "mac_rx_unknown_opcode",
+ "mac_rx_alignment_error",
+ "mac_rx_frame_length_error",
+ "mac_rx_code_error",
+ "mac_rx_carrier_sense_error",
+ "mac_rx_undersize",
+ "mac_rx_oversize",
+ "mac_rx_fragments",
+ "mac_rx_jabber",
+ "mac_rx_drop",
+
+ "mac_tx_bytes",
+ "mac_tx_packets",
+ "mac_tx_multicast",
+ "mac_tx_broadcast",
+ "mac_tx_pause",
+ "mac_tx_deferral",
+ "mac_tx_excessive_deferral",
+ "mac_tx_single_collision",
+ "mac_tx_muliple_collision",
+ "mac_tx_late_collision",
+ "mac_tx_excessive_collision",
+ "mac_tx_total_collision",
+ "mac_tx_pause_honored",
+ "mac_tx_drop",
+ "mac_tx_jabber",
+ "mac_tx_fcs_error",
+ "mac_tx_control_frame",
+ "mac_tx_oversize",
+ "mac_tx_undersize",
+ "mac_tx_fragments",
+
+ "bpc_tx_pause_0",
+ "bpc_tx_pause_1",
+ "bpc_tx_pause_2",
+ "bpc_tx_pause_3",
+ "bpc_tx_pause_4",
+ "bpc_tx_pause_5",
+ "bpc_tx_pause_6",
+ "bpc_tx_pause_7",
+ "bpc_tx_zero_pause_0",
+ "bpc_tx_zero_pause_1",
+ "bpc_tx_zero_pause_2",
+ "bpc_tx_zero_pause_3",
+ "bpc_tx_zero_pause_4",
+ "bpc_tx_zero_pause_5",
+ "bpc_tx_zero_pause_6",
+ "bpc_tx_zero_pause_7",
+ "bpc_tx_first_pause_0",
+ "bpc_tx_first_pause_1",
+ "bpc_tx_first_pause_2",
+ "bpc_tx_first_pause_3",
+ "bpc_tx_first_pause_4",
+ "bpc_tx_first_pause_5",
+ "bpc_tx_first_pause_6",
+ "bpc_tx_first_pause_7",
+
+ "bpc_rx_pause_0",
+ "bpc_rx_pause_1",
+ "bpc_rx_pause_2",
+ "bpc_rx_pause_3",
+ "bpc_rx_pause_4",
+ "bpc_rx_pause_5",
+ "bpc_rx_pause_6",
+ "bpc_rx_pause_7",
+ "bpc_rx_zero_pause_0",
+ "bpc_rx_zero_pause_1",
+ "bpc_rx_zero_pause_2",
+ "bpc_rx_zero_pause_3",
+ "bpc_rx_zero_pause_4",
+ "bpc_rx_zero_pause_5",
+ "bpc_rx_zero_pause_6",
+ "bpc_rx_zero_pause_7",
+ "bpc_rx_first_pause_0",
+ "bpc_rx_first_pause_1",
+ "bpc_rx_first_pause_2",
+ "bpc_rx_first_pause_3",
+ "bpc_rx_first_pause_4",
+ "bpc_rx_first_pause_5",
+ "bpc_rx_first_pause_6",
+ "bpc_rx_first_pause_7",
+
+ "rad_rx_frames",
+ "rad_rx_octets",
+ "rad_rx_vlan_frames",
+ "rad_rx_ucast",
+ "rad_rx_ucast_octets",
+ "rad_rx_ucast_vlan",
+ "rad_rx_mcast",
+ "rad_rx_mcast_octets",
+ "rad_rx_mcast_vlan",
+ "rad_rx_bcast",
+ "rad_rx_bcast_octets",
+ "rad_rx_bcast_vlan",
+ "rad_rx_drops",
+
+ "fc_rx_ucast_octets",
+ "fc_rx_ucast",
+ "fc_rx_ucast_vlan",
+ "fc_rx_mcast_octets",
+ "fc_rx_mcast",
+ "fc_rx_mcast_vlan",
+ "fc_rx_bcast_octets",
+ "fc_rx_bcast",
+ "fc_rx_bcast_vlan",
+
+ "fc_tx_ucast_octets",
+ "fc_tx_ucast",
+ "fc_tx_ucast_vlan",
+ "fc_tx_mcast_octets",
+ "fc_tx_mcast",
+ "fc_tx_mcast_vlan",
+ "fc_tx_bcast_octets",
+ "fc_tx_bcast",
+ "fc_tx_bcast_vlan",
+ "fc_tx_parity_errors",
+ "fc_tx_timeout",
+ "fc_tx_fid_parity_errors",
+};
+
+static int
+bnad_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
+{
+ cmd->supported = SUPPORTED_10000baseT_Full;
+ cmd->advertising = ADVERTISED_10000baseT_Full;
+ cmd->autoneg = AUTONEG_DISABLE;
+ cmd->supported |= SUPPORTED_FIBRE;
+ cmd->advertising |= ADVERTISED_FIBRE;
+ cmd->port = PORT_FIBRE;
+ cmd->phy_address = 0;
+
+ if (netif_carrier_ok(netdev)) {
+ cmd->speed = SPEED_10000;
+ cmd->duplex = DUPLEX_FULL;
+ } else {
+ cmd->speed = -1;
+ cmd->duplex = -1;
+ }
+ cmd->transceiver = XCVR_EXTERNAL;
+ cmd->maxtxpkt = 0;
+ cmd->maxrxpkt = 0;
+
+ return 0;
+}
+
+static int
+bnad_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
+{
+ /* 10G full duplex setting supported only */
+ if (cmd->autoneg == AUTONEG_ENABLE)
+ return -EOPNOTSUPP; else {
+ if ((cmd->speed == SPEED_10000) && (cmd->duplex == DUPLEX_FULL))
+ return 0;
+ }
+
+ return -EOPNOTSUPP;
+}
+
+static void
+bnad_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
+{
+ struct bnad *bnad = netdev_priv(netdev);
+ struct bfa_ioc_attr *ioc_attr;
+ unsigned long flags;
+
+ strcpy(drvinfo->driver, BNAD_NAME);
+ strcpy(drvinfo->version, BNAD_VERSION);
+
+ ioc_attr = kzalloc(sizeof(*ioc_attr), GFP_KERNEL);
+ if (ioc_attr) {
+ memset(ioc_attr, 0, sizeof(*ioc_attr));
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ bfa_nw_ioc_get_attr(&bnad->bna.device.ioc, ioc_attr);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+ strncpy(drvinfo->fw_version, ioc_attr->adapter_attr.fw_ver,
+ sizeof(drvinfo->fw_version) - 1);
+ kfree(ioc_attr);
+ }
+
+ strncpy(drvinfo->bus_info, pci_name(bnad->pcidev), ETHTOOL_BUSINFO_LEN);
+}
+
+static int
+get_regs(struct bnad *bnad, u32 * regs)
+{
+ int num = 0, i;
+ u32 reg_addr;
+ unsigned long flags;
+
+#define BNAD_GET_REG(addr) \
+do { \
+ if (regs) \
+ regs[num++] = readl(bnad->bar0 + (addr)); \
+ else \
+ num++; \
+} while (0)
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+
+ /* DMA Block Internal Registers */
+ BNAD_GET_REG(DMA_CTRL_REG0);
+ BNAD_GET_REG(DMA_CTRL_REG1);
+ BNAD_GET_REG(DMA_ERR_INT_STATUS);
+ BNAD_GET_REG(DMA_ERR_INT_ENABLE);
+ BNAD_GET_REG(DMA_ERR_INT_STATUS_SET);
+
+ /* APP Block Register Address Offset from BAR0 */
+ BNAD_GET_REG(HOSTFN0_INT_STATUS);
+ BNAD_GET_REG(HOSTFN0_INT_MASK);
+ BNAD_GET_REG(HOST_PAGE_NUM_FN0);
+ BNAD_GET_REG(HOST_MSIX_ERR_INDEX_FN0);
+ BNAD_GET_REG(FN0_PCIE_ERR_REG);
+ BNAD_GET_REG(FN0_ERR_TYPE_STATUS_REG);
+ BNAD_GET_REG(FN0_ERR_TYPE_MSK_STATUS_REG);
+
+ BNAD_GET_REG(HOSTFN1_INT_STATUS);
+ BNAD_GET_REG(HOSTFN1_INT_MASK);
+ BNAD_GET_REG(HOST_PAGE_NUM_FN1);
+ BNAD_GET_REG(HOST_MSIX_ERR_INDEX_FN1);
+ BNAD_GET_REG(FN1_PCIE_ERR_REG);
+ BNAD_GET_REG(FN1_ERR_TYPE_STATUS_REG);
+ BNAD_GET_REG(FN1_ERR_TYPE_MSK_STATUS_REG);
+
+ BNAD_GET_REG(PCIE_MISC_REG);
+
+ BNAD_GET_REG(HOST_SEM0_REG);
+ BNAD_GET_REG(HOST_SEM1_REG);
+ BNAD_GET_REG(HOST_SEM2_REG);
+ BNAD_GET_REG(HOST_SEM3_REG);
+ BNAD_GET_REG(HOST_SEM0_INFO_REG);
+ BNAD_GET_REG(HOST_SEM1_INFO_REG);
+ BNAD_GET_REG(HOST_SEM2_INFO_REG);
+ BNAD_GET_REG(HOST_SEM3_INFO_REG);
+
+ BNAD_GET_REG(TEMPSENSE_CNTL_REG);
+ BNAD_GET_REG(TEMPSENSE_STAT_REG);
+
+ BNAD_GET_REG(APP_LOCAL_ERR_STAT);
+ BNAD_GET_REG(APP_LOCAL_ERR_MSK);
+
+ BNAD_GET_REG(PCIE_LNK_ERR_STAT);
+ BNAD_GET_REG(PCIE_LNK_ERR_MSK);
+
+ BNAD_GET_REG(FCOE_FIP_ETH_TYPE);
+ BNAD_GET_REG(RESV_ETH_TYPE);
+
+ BNAD_GET_REG(HOSTFN2_INT_STATUS);
+ BNAD_GET_REG(HOSTFN2_INT_MASK);
+ BNAD_GET_REG(HOST_PAGE_NUM_FN2);
+ BNAD_GET_REG(HOST_MSIX_ERR_INDEX_FN2);
+ BNAD_GET_REG(FN2_PCIE_ERR_REG);
+ BNAD_GET_REG(FN2_ERR_TYPE_STATUS_REG);
+ BNAD_GET_REG(FN2_ERR_TYPE_MSK_STATUS_REG);
+
+ BNAD_GET_REG(HOSTFN3_INT_STATUS);
+ BNAD_GET_REG(HOSTFN3_INT_MASK);
+ BNAD_GET_REG(HOST_PAGE_NUM_FN3);
+ BNAD_GET_REG(HOST_MSIX_ERR_INDEX_FN3);
+ BNAD_GET_REG(FN3_PCIE_ERR_REG);
+ BNAD_GET_REG(FN3_ERR_TYPE_STATUS_REG);
+ BNAD_GET_REG(FN3_ERR_TYPE_MSK_STATUS_REG);
+
+ /* Host Command Status Registers */
+ reg_addr = HOST_CMDSTS0_CLR_REG;
+ for (i = 0; i < 16; i++) {
+ BNAD_GET_REG(reg_addr);
+ BNAD_GET_REG(reg_addr + 4);
+ BNAD_GET_REG(reg_addr + 8);
+ reg_addr += 0x10;
+ }
+
+ /* Function ID register */
+ BNAD_GET_REG(FNC_ID_REG);
+
+ /* Function personality register */
+ BNAD_GET_REG(FNC_PERS_REG);
+
+ /* Operation mode register */
+ BNAD_GET_REG(OP_MODE);
+
+ /* LPU0 Registers */
+ BNAD_GET_REG(LPU0_MBOX_CTL_REG);
+ BNAD_GET_REG(LPU0_MBOX_CMD_REG);
+ BNAD_GET_REG(LPU0_MBOX_LINK_0REG);
+ BNAD_GET_REG(LPU1_MBOX_LINK_0REG);
+ BNAD_GET_REG(LPU0_MBOX_STATUS_0REG);
+ BNAD_GET_REG(LPU1_MBOX_STATUS_0REG);
+ BNAD_GET_REG(LPU0_ERR_STATUS_REG);
+ BNAD_GET_REG(LPU0_ERR_SET_REG);
+
+ /* LPU1 Registers */
+ BNAD_GET_REG(LPU1_MBOX_CTL_REG);
+ BNAD_GET_REG(LPU1_MBOX_CMD_REG);
+ BNAD_GET_REG(LPU0_MBOX_LINK_1REG);
+ BNAD_GET_REG(LPU1_MBOX_LINK_1REG);
+ BNAD_GET_REG(LPU0_MBOX_STATUS_1REG);
+ BNAD_GET_REG(LPU1_MBOX_STATUS_1REG);
+ BNAD_GET_REG(LPU1_ERR_STATUS_REG);
+ BNAD_GET_REG(LPU1_ERR_SET_REG);
+
+ /* PSS Registers */
+ BNAD_GET_REG(PSS_CTL_REG);
+ BNAD_GET_REG(PSS_ERR_STATUS_REG);
+ BNAD_GET_REG(ERR_STATUS_SET);
+ BNAD_GET_REG(PSS_RAM_ERR_STATUS_REG);
+
+ /* Catapult CPQ Registers */
+ BNAD_GET_REG(HOSTFN0_LPU0_MBOX0_CMD_STAT);
+ BNAD_GET_REG(HOSTFN0_LPU1_MBOX0_CMD_STAT);
+ BNAD_GET_REG(LPU0_HOSTFN0_MBOX0_CMD_STAT);
+ BNAD_GET_REG(LPU1_HOSTFN0_MBOX0_CMD_STAT);
+
+ BNAD_GET_REG(HOSTFN0_LPU0_MBOX1_CMD_STAT);
+ BNAD_GET_REG(HOSTFN0_LPU1_MBOX1_CMD_STAT);
+ BNAD_GET_REG(LPU0_HOSTFN0_MBOX1_CMD_STAT);
+ BNAD_GET_REG(LPU1_HOSTFN0_MBOX1_CMD_STAT);
+
+ BNAD_GET_REG(HOSTFN1_LPU0_MBOX0_CMD_STAT);
+ BNAD_GET_REG(HOSTFN1_LPU1_MBOX0_CMD_STAT);
+ BNAD_GET_REG(LPU0_HOSTFN1_MBOX0_CMD_STAT);
+ BNAD_GET_REG(LPU1_HOSTFN1_MBOX0_CMD_STAT);
+
+ BNAD_GET_REG(HOSTFN1_LPU0_MBOX1_CMD_STAT);
+ BNAD_GET_REG(HOSTFN1_LPU1_MBOX1_CMD_STAT);
+ BNAD_GET_REG(LPU0_HOSTFN1_MBOX1_CMD_STAT);
+ BNAD_GET_REG(LPU1_HOSTFN1_MBOX1_CMD_STAT);
+
+ BNAD_GET_REG(HOSTFN2_LPU0_MBOX0_CMD_STAT);
+ BNAD_GET_REG(HOSTFN2_LPU1_MBOX0_CMD_STAT);
+ BNAD_GET_REG(LPU0_HOSTFN2_MBOX0_CMD_STAT);
+ BNAD_GET_REG(LPU1_HOSTFN2_MBOX0_CMD_STAT);
+
+ BNAD_GET_REG(HOSTFN2_LPU0_MBOX1_CMD_STAT);
+ BNAD_GET_REG(HOSTFN2_LPU1_MBOX1_CMD_STAT);
+ BNAD_GET_REG(LPU0_HOSTFN2_MBOX1_CMD_STAT);
+ BNAD_GET_REG(LPU1_HOSTFN2_MBOX1_CMD_STAT);
+
+ BNAD_GET_REG(HOSTFN3_LPU0_MBOX0_CMD_STAT);
+ BNAD_GET_REG(HOSTFN3_LPU1_MBOX0_CMD_STAT);
+ BNAD_GET_REG(LPU0_HOSTFN3_MBOX0_CMD_STAT);
+ BNAD_GET_REG(LPU1_HOSTFN3_MBOX0_CMD_STAT);
+
+ BNAD_GET_REG(HOSTFN3_LPU0_MBOX1_CMD_STAT);
+ BNAD_GET_REG(HOSTFN3_LPU1_MBOX1_CMD_STAT);
+ BNAD_GET_REG(LPU0_HOSTFN3_MBOX1_CMD_STAT);
+ BNAD_GET_REG(LPU1_HOSTFN3_MBOX1_CMD_STAT);
+
+ /* Host Function Force Parity Error Registers */
+ BNAD_GET_REG(HOSTFN0_LPU_FORCE_PERR);
+ BNAD_GET_REG(HOSTFN1_LPU_FORCE_PERR);
+ BNAD_GET_REG(HOSTFN2_LPU_FORCE_PERR);
+ BNAD_GET_REG(HOSTFN3_LPU_FORCE_PERR);
+
+ /* LL Port[0|1] Halt Mask Registers */
+ BNAD_GET_REG(LL_HALT_MSK_P0);
+ BNAD_GET_REG(LL_HALT_MSK_P1);
+
+ /* LL Port[0|1] Error Mask Registers */
+ BNAD_GET_REG(LL_ERR_MSK_P0);
+ BNAD_GET_REG(LL_ERR_MSK_P1);
+
+ /* EMC FLI Registers */
+ BNAD_GET_REG(FLI_CMD_REG);
+ BNAD_GET_REG(FLI_ADDR_REG);
+ BNAD_GET_REG(FLI_CTL_REG);
+ BNAD_GET_REG(FLI_WRDATA_REG);
+ BNAD_GET_REG(FLI_RDDATA_REG);
+ BNAD_GET_REG(FLI_DEV_STATUS_REG);
+ BNAD_GET_REG(FLI_SIG_WD_REG);
+
+ BNAD_GET_REG(FLI_DEV_VENDOR_REG);
+ BNAD_GET_REG(FLI_ERR_STATUS_REG);
+
+ /* RxAdm 0 Registers */
+ BNAD_GET_REG(RAD0_CTL_REG);
+ BNAD_GET_REG(RAD0_PE_PARM_REG);
+ BNAD_GET_REG(RAD0_BCN_REG);
+ BNAD_GET_REG(RAD0_DEFAULT_REG);
+ BNAD_GET_REG(RAD0_PROMISC_REG);
+ BNAD_GET_REG(RAD0_BCNQ_REG);
+ BNAD_GET_REG(RAD0_DEFAULTQ_REG);
+
+ BNAD_GET_REG(RAD0_ERR_STS);
+ BNAD_GET_REG(RAD0_SET_ERR_STS);
+ BNAD_GET_REG(RAD0_ERR_INT_EN);
+ BNAD_GET_REG(RAD0_FIRST_ERR);
+ BNAD_GET_REG(RAD0_FORCE_ERR);
+
+ BNAD_GET_REG(RAD0_MAC_MAN_1H);
+ BNAD_GET_REG(RAD0_MAC_MAN_1L);
+ BNAD_GET_REG(RAD0_MAC_MAN_2H);
+ BNAD_GET_REG(RAD0_MAC_MAN_2L);
+ BNAD_GET_REG(RAD0_MAC_MAN_3H);
+ BNAD_GET_REG(RAD0_MAC_MAN_3L);
+ BNAD_GET_REG(RAD0_MAC_MAN_4H);
+ BNAD_GET_REG(RAD0_MAC_MAN_4L);
+
+ BNAD_GET_REG(RAD0_LAST4_IP);
+
+ /* RxAdm 1 Registers */
+ BNAD_GET_REG(RAD1_CTL_REG);
+ BNAD_GET_REG(RAD1_PE_PARM_REG);
+ BNAD_GET_REG(RAD1_BCN_REG);
+ BNAD_GET_REG(RAD1_DEFAULT_REG);
+ BNAD_GET_REG(RAD1_PROMISC_REG);
+ BNAD_GET_REG(RAD1_BCNQ_REG);
+ BNAD_GET_REG(RAD1_DEFAULTQ_REG);
+
+ BNAD_GET_REG(RAD1_ERR_STS);
+ BNAD_GET_REG(RAD1_SET_ERR_STS);
+ BNAD_GET_REG(RAD1_ERR_INT_EN);
+
+ /* TxA0 Registers */
+ BNAD_GET_REG(TXA0_CTRL_REG);
+ /* TxA0 TSO Sequence # Registers (RO) */
+ for (i = 0; i < 8; i++) {
+ BNAD_GET_REG(TXA0_TSO_TCP_SEQ_REG(i));
+ BNAD_GET_REG(TXA0_TSO_IP_INFO_REG(i));
+ }
+
+ /* TxA1 Registers */
+ BNAD_GET_REG(TXA1_CTRL_REG);
+ /* TxA1 TSO Sequence # Registers (RO) */
+ for (i = 0; i < 8; i++) {
+ BNAD_GET_REG(TXA1_TSO_TCP_SEQ_REG(i));
+ BNAD_GET_REG(TXA1_TSO_IP_INFO_REG(i));
+ }
+
+ /* RxA Registers */
+ BNAD_GET_REG(RXA0_CTL_REG);
+ BNAD_GET_REG(RXA1_CTL_REG);
+
+ /* PLB0 Registers */
+ BNAD_GET_REG(PLB0_ECM_TIMER_REG);
+ BNAD_GET_REG(PLB0_RL_CTL);
+ for (i = 0; i < 8; i++)
+ BNAD_GET_REG(PLB0_RL_MAX_BC(i));
+ BNAD_GET_REG(PLB0_RL_TU_PRIO);
+ for (i = 0; i < 8; i++)
+ BNAD_GET_REG(PLB0_RL_BYTE_CNT(i));
+ BNAD_GET_REG(PLB0_RL_MIN_REG);
+ BNAD_GET_REG(PLB0_RL_MAX_REG);
+ BNAD_GET_REG(PLB0_EMS_ADD_REG);
+
+ /* PLB1 Registers */
+ BNAD_GET_REG(PLB1_ECM_TIMER_REG);
+ BNAD_GET_REG(PLB1_RL_CTL);
+ for (i = 0; i < 8; i++)
+ BNAD_GET_REG(PLB1_RL_MAX_BC(i));
+ BNAD_GET_REG(PLB1_RL_TU_PRIO);
+ for (i = 0; i < 8; i++)
+ BNAD_GET_REG(PLB1_RL_BYTE_CNT(i));
+ BNAD_GET_REG(PLB1_RL_MIN_REG);
+ BNAD_GET_REG(PLB1_RL_MAX_REG);
+ BNAD_GET_REG(PLB1_EMS_ADD_REG);
+
+ /* HQM Control Register */
+ BNAD_GET_REG(HQM0_CTL_REG);
+ BNAD_GET_REG(HQM0_RXQ_STOP_SEM);
+ BNAD_GET_REG(HQM0_TXQ_STOP_SEM);
+ BNAD_GET_REG(HQM1_CTL_REG);
+ BNAD_GET_REG(HQM1_RXQ_STOP_SEM);
+ BNAD_GET_REG(HQM1_TXQ_STOP_SEM);
+
+ /* LUT Registers */
+ BNAD_GET_REG(LUT0_ERR_STS);
+ BNAD_GET_REG(LUT0_SET_ERR_STS);
+ BNAD_GET_REG(LUT1_ERR_STS);
+ BNAD_GET_REG(LUT1_SET_ERR_STS);
+
+ /* TRC Registers */
+ BNAD_GET_REG(TRC_CTL_REG);
+ BNAD_GET_REG(TRC_MODS_REG);
+ BNAD_GET_REG(TRC_TRGC_REG);
+ BNAD_GET_REG(TRC_CNT1_REG);
+ BNAD_GET_REG(TRC_CNT2_REG);
+ BNAD_GET_REG(TRC_NXTS_REG);
+ BNAD_GET_REG(TRC_DIRR_REG);
+ for (i = 0; i < 10; i++)
+ BNAD_GET_REG(TRC_TRGM_REG(i));
+ for (i = 0; i < 10; i++)
+ BNAD_GET_REG(TRC_NXTM_REG(i));
+ for (i = 0; i < 10; i++)
+ BNAD_GET_REG(TRC_STRM_REG(i));
+
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+#undef BNAD_GET_REG
+ return num;
+}
+static int
+bnad_get_regs_len(struct net_device *netdev)
+{
+ int ret = get_regs(netdev_priv(netdev), NULL) * sizeof(u32);
+ return ret;
+}
+
+static void
+bnad_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *buf)
+{
+ memset(buf, 0, bnad_get_regs_len(netdev));
+ get_regs(netdev_priv(netdev), buf);
+}
+
+static void
+bnad_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wolinfo)
+{
+ wolinfo->supported = 0;
+ wolinfo->wolopts = 0;
+}
+
+static int
+bnad_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
+{
+ struct bnad *bnad = netdev_priv(netdev);
+ unsigned long flags;
+
+ /* Lock rqd. to access bnad->bna_lock */
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ coalesce->use_adaptive_rx_coalesce =
+ (bnad->cfg_flags & BNAD_CF_DIM_ENABLED) ? true : false;
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+ coalesce->rx_coalesce_usecs = bnad->rx_coalescing_timeo *
+ BFI_COALESCING_TIMER_UNIT;
+ coalesce->tx_coalesce_usecs = bnad->tx_coalescing_timeo *
+ BFI_COALESCING_TIMER_UNIT;
+ coalesce->tx_max_coalesced_frames = BFI_TX_INTERPKT_COUNT;
+
+ return 0;
+}
+
+static int
+bnad_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
+{
+ struct bnad *bnad = netdev_priv(netdev);
+ unsigned long flags;
+ int dim_timer_del = 0;
+
+ if (coalesce->rx_coalesce_usecs == 0 ||
+ coalesce->rx_coalesce_usecs >
+ BFI_MAX_COALESCING_TIMEO * BFI_COALESCING_TIMER_UNIT)
+ return -EINVAL;
+
+ if (coalesce->tx_coalesce_usecs == 0 ||
+ coalesce->tx_coalesce_usecs >
+ BFI_MAX_COALESCING_TIMEO * BFI_COALESCING_TIMER_UNIT)
+ return -EINVAL;
+
+ mutex_lock(&bnad->conf_mutex);
+ /*
+ * Do not need to store rx_coalesce_usecs here
+ * Every time DIM is disabled, we can get it from the
+ * stack.
+ */
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ if (coalesce->use_adaptive_rx_coalesce) {
+ if (!(bnad->cfg_flags & BNAD_CF_DIM_ENABLED)) {
+ bnad->cfg_flags |= BNAD_CF_DIM_ENABLED;
+ bnad_dim_timer_start(bnad);
+ }
+ } else {
+ if (bnad->cfg_flags & BNAD_CF_DIM_ENABLED) {
+ bnad->cfg_flags &= ~BNAD_CF_DIM_ENABLED;
+ dim_timer_del = bnad_dim_timer_running(bnad);
+ if (dim_timer_del) {
+ clear_bit(BNAD_RF_DIM_TIMER_RUNNING,
+ &bnad->run_flags);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+ del_timer_sync(&bnad->dim_timer);
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ }
+ bnad_rx_coalescing_timeo_set(bnad);
+ }
+ }
+ if (bnad->tx_coalescing_timeo != coalesce->tx_coalesce_usecs /
+ BFI_COALESCING_TIMER_UNIT) {
+ bnad->tx_coalescing_timeo = coalesce->tx_coalesce_usecs /
+ BFI_COALESCING_TIMER_UNIT;
+ bnad_tx_coalescing_timeo_set(bnad);
+ }
+
+ if (bnad->rx_coalescing_timeo != coalesce->rx_coalesce_usecs /
+ BFI_COALESCING_TIMER_UNIT) {
+ bnad->rx_coalescing_timeo = coalesce->rx_coalesce_usecs /
+ BFI_COALESCING_TIMER_UNIT;
+
+ if (!(bnad->cfg_flags & BNAD_CF_DIM_ENABLED))
+ bnad_rx_coalescing_timeo_set(bnad);
+
+ }
+
+ /* Add Tx Inter-pkt DMA count? */
+
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+ mutex_unlock(&bnad->conf_mutex);
+ return 0;
+}
+
+static void
+bnad_get_ringparam(struct net_device *netdev,
+ struct ethtool_ringparam *ringparam)
+{
+ struct bnad *bnad = netdev_priv(netdev);
+
+ ringparam->rx_max_pending = BNAD_MAX_Q_DEPTH / bnad_rxqs_per_cq;
+ ringparam->rx_mini_max_pending = 0;
+ ringparam->rx_jumbo_max_pending = 0;
+ ringparam->tx_max_pending = BNAD_MAX_Q_DEPTH;
+
+ ringparam->rx_pending = bnad->rxq_depth;
+ ringparam->rx_mini_max_pending = 0;
+ ringparam->rx_jumbo_max_pending = 0;
+ ringparam->tx_pending = bnad->txq_depth;
+}
+
+static int
+bnad_set_ringparam(struct net_device *netdev,
+ struct ethtool_ringparam *ringparam)
+{
+ int i, current_err, err = 0;
+ struct bnad *bnad = netdev_priv(netdev);
+
+ mutex_lock(&bnad->conf_mutex);
+ if (ringparam->rx_pending == bnad->rxq_depth &&
+ ringparam->tx_pending == bnad->txq_depth) {
+ mutex_unlock(&bnad->conf_mutex);
+ return 0;
+ }
+
+ if (ringparam->rx_pending < BNAD_MIN_Q_DEPTH ||
+ ringparam->rx_pending > BNAD_MAX_Q_DEPTH / bnad_rxqs_per_cq ||
+ !BNA_POWER_OF_2(ringparam->rx_pending)) {
+ mutex_unlock(&bnad->conf_mutex);
+ return -EINVAL;
+ }
+ if (ringparam->tx_pending < BNAD_MIN_Q_DEPTH ||
+ ringparam->tx_pending > BNAD_MAX_Q_DEPTH ||
+ !BNA_POWER_OF_2(ringparam->tx_pending)) {
+ mutex_unlock(&bnad->conf_mutex);
+ return -EINVAL;
+ }
+
+ if (ringparam->rx_pending != bnad->rxq_depth) {
+ bnad->rxq_depth = ringparam->rx_pending;
+ for (i = 0; i < bnad->num_rx; i++) {
+ if (!bnad->rx_info[i].rx)
+ continue;
+ bnad_cleanup_rx(bnad, i);
+ current_err = bnad_setup_rx(bnad, i);
+ if (current_err && !err)
+ err = current_err;
+ }
+ }
+ if (ringparam->tx_pending != bnad->txq_depth) {
+ bnad->txq_depth = ringparam->tx_pending;
+ for (i = 0; i < bnad->num_tx; i++) {
+ if (!bnad->tx_info[i].tx)
+ continue;
+ bnad_cleanup_tx(bnad, i);
+ current_err = bnad_setup_tx(bnad, i);
+ if (current_err && !err)
+ err = current_err;
+ }
+ }
+
+ mutex_unlock(&bnad->conf_mutex);
+ return err;
+}
+
+static void
+bnad_get_pauseparam(struct net_device *netdev,
+ struct ethtool_pauseparam *pauseparam)
+{
+ struct bnad *bnad = netdev_priv(netdev);
+
+ pauseparam->autoneg = 0;
+ pauseparam->rx_pause = bnad->bna.port.pause_config.rx_pause;
+ pauseparam->tx_pause = bnad->bna.port.pause_config.tx_pause;
+}
+
+static int
+bnad_set_pauseparam(struct net_device *netdev,
+ struct ethtool_pauseparam *pauseparam)
+{
+ struct bnad *bnad = netdev_priv(netdev);
+ struct bna_pause_config pause_config;
+ unsigned long flags;
+
+ if (pauseparam->autoneg == AUTONEG_ENABLE)
+ return -EINVAL;
+
+ mutex_lock(&bnad->conf_mutex);
+ if (pauseparam->rx_pause != bnad->bna.port.pause_config.rx_pause ||
+ pauseparam->tx_pause != bnad->bna.port.pause_config.tx_pause) {
+ pause_config.rx_pause = pauseparam->rx_pause;
+ pause_config.tx_pause = pauseparam->tx_pause;
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ bna_port_pause_config(&bnad->bna.port, &pause_config, NULL);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+ }
+ mutex_unlock(&bnad->conf_mutex);
+ return 0;
+}
+
+static u32
+bnad_get_rx_csum(struct net_device *netdev)
+{
+ u32 rx_csum;
+ struct bnad *bnad = netdev_priv(netdev);
+
+ rx_csum = bnad->rx_csum;
+ return rx_csum;
+}
+
+static int
+bnad_set_rx_csum(struct net_device *netdev, u32 rx_csum)
+{
+ struct bnad *bnad = netdev_priv(netdev);
+
+ mutex_lock(&bnad->conf_mutex);
+ bnad->rx_csum = rx_csum;
+ mutex_unlock(&bnad->conf_mutex);
+ return 0;
+}
+
+static int
+bnad_set_tx_csum(struct net_device *netdev, u32 tx_csum)
+{
+ struct bnad *bnad = netdev_priv(netdev);
+
+ mutex_lock(&bnad->conf_mutex);
+ if (tx_csum) {
+ netdev->features |= NETIF_F_IP_CSUM;
+ netdev->features |= NETIF_F_IPV6_CSUM;
+ } else {
+ netdev->features &= ~NETIF_F_IP_CSUM;
+ netdev->features &= ~NETIF_F_IPV6_CSUM;
+ }
+ mutex_unlock(&bnad->conf_mutex);
+ return 0;
+}
+
+static int
+bnad_set_tso(struct net_device *netdev, u32 tso)
+{
+ struct bnad *bnad = netdev_priv(netdev);
+
+ mutex_lock(&bnad->conf_mutex);
+ if (tso) {
+ netdev->features |= NETIF_F_TSO;
+ netdev->features |= NETIF_F_TSO6;
+ } else {
+ netdev->features &= ~NETIF_F_TSO;
+ netdev->features &= ~NETIF_F_TSO6;
+ }
+ mutex_unlock(&bnad->conf_mutex);
+ return 0;
+}
+
+static void
+bnad_get_strings(struct net_device *netdev, u32 stringset, u8 * string)
+{
+ struct bnad *bnad = netdev_priv(netdev);
+ int i, j, q_num;
+ u64 bmap;
+
+ mutex_lock(&bnad->conf_mutex);
+
+ switch (stringset) {
+ case ETH_SS_STATS:
+ for (i = 0; i < BNAD_ETHTOOL_STATS_NUM; i++) {
+ BUG_ON(!(strlen(bnad_net_stats_strings[i]) <
+ ETH_GSTRING_LEN));
+ memcpy(string, bnad_net_stats_strings[i],
+ ETH_GSTRING_LEN);
+ string += ETH_GSTRING_LEN;
+ }
+ bmap = (u64)bnad->bna.tx_mod.txf_bmap[0] |
+ ((u64)bnad->bna.tx_mod.txf_bmap[1] << 32);
+ for (i = 0; bmap && (i < BFI_LL_TXF_ID_MAX); i++) {
+ if (bmap & 1) {
+ sprintf(string, "txf%d_ucast_octets", i);
+ string += ETH_GSTRING_LEN;
+ sprintf(string, "txf%d_ucast", i);
+ string += ETH_GSTRING_LEN;
+ sprintf(string, "txf%d_ucast_vlan", i);
+ string += ETH_GSTRING_LEN;
+ sprintf(string, "txf%d_mcast_octets", i);
+ string += ETH_GSTRING_LEN;
+ sprintf(string, "txf%d_mcast", i);
+ string += ETH_GSTRING_LEN;
+ sprintf(string, "txf%d_mcast_vlan", i);
+ string += ETH_GSTRING_LEN;
+ sprintf(string, "txf%d_bcast_octets", i);
+ string += ETH_GSTRING_LEN;
+ sprintf(string, "txf%d_bcast", i);
+ string += ETH_GSTRING_LEN;
+ sprintf(string, "txf%d_bcast_vlan", i);
+ string += ETH_GSTRING_LEN;
+ sprintf(string, "txf%d_errors", i);
+ string += ETH_GSTRING_LEN;
+ sprintf(string, "txf%d_filter_vlan", i);
+ string += ETH_GSTRING_LEN;
+ sprintf(string, "txf%d_filter_mac_sa", i);
+ string += ETH_GSTRING_LEN;
+ }
+ bmap >>= 1;
+ }
+
+ bmap = (u64)bnad->bna.rx_mod.rxf_bmap[0] |
+ ((u64)bnad->bna.rx_mod.rxf_bmap[1] << 32);
+ for (i = 0; bmap && (i < BFI_LL_RXF_ID_MAX); i++) {
+ if (bmap & 1) {
+ sprintf(string, "rxf%d_ucast_octets", i);
+ string += ETH_GSTRING_LEN;
+ sprintf(string, "rxf%d_ucast", i);
+ string += ETH_GSTRING_LEN;
+ sprintf(string, "rxf%d_ucast_vlan", i);
+ string += ETH_GSTRING_LEN;
+ sprintf(string, "rxf%d_mcast_octets", i);
+ string += ETH_GSTRING_LEN;
+ sprintf(string, "rxf%d_mcast", i);
+ string += ETH_GSTRING_LEN;
+ sprintf(string, "rxf%d_mcast_vlan", i);
+ string += ETH_GSTRING_LEN;
+ sprintf(string, "rxf%d_bcast_octets", i);
+ string += ETH_GSTRING_LEN;
+ sprintf(string, "rxf%d_bcast", i);
+ string += ETH_GSTRING_LEN;
+ sprintf(string, "rxf%d_bcast_vlan", i);
+ string += ETH_GSTRING_LEN;
+ sprintf(string, "rxf%d_frame_drops", i);
+ string += ETH_GSTRING_LEN;
+ }
+ bmap >>= 1;
+ }
+
+ q_num = 0;
+ for (i = 0; i < bnad->num_rx; i++) {
+ if (!bnad->rx_info[i].rx)
+ continue;
+ for (j = 0; j < bnad->num_rxp_per_rx; j++) {
+ sprintf(string, "cq%d_producer_index", q_num);
+ string += ETH_GSTRING_LEN;
+ sprintf(string, "cq%d_consumer_index", q_num);
+ string += ETH_GSTRING_LEN;
+ sprintf(string, "cq%d_hw_producer_index",
+ q_num);
+ string += ETH_GSTRING_LEN;
+ q_num++;
+ }
+ }
+
+ q_num = 0;
+ for (i = 0; i < bnad->num_rx; i++) {
+ if (!bnad->rx_info[i].rx)
+ continue;
+ for (j = 0; j < bnad->num_rxp_per_rx; j++) {
+ sprintf(string, "rxq%d_packets", q_num);
+ string += ETH_GSTRING_LEN;
+ sprintf(string, "rxq%d_bytes", q_num);
+ string += ETH_GSTRING_LEN;
+ sprintf(string, "rxq%d_packets_with_error",
+ q_num);
+ string += ETH_GSTRING_LEN;
+ sprintf(string, "rxq%d_allocbuf_failed", q_num);
+ string += ETH_GSTRING_LEN;
+ sprintf(string, "rxq%d_producer_index", q_num);
+ string += ETH_GSTRING_LEN;
+ sprintf(string, "rxq%d_consumer_index", q_num);
+ string += ETH_GSTRING_LEN;
+ q_num++;
+ if (bnad->rx_info[i].rx_ctrl[j].ccb &&
+ bnad->rx_info[i].rx_ctrl[j].ccb->
+ rcb[1] &&
+ bnad->rx_info[i].rx_ctrl[j].ccb->
+ rcb[1]->rxq) {
+ sprintf(string, "rxq%d_packets", q_num);
+ string += ETH_GSTRING_LEN;
+ sprintf(string, "rxq%d_bytes", q_num);
+ string += ETH_GSTRING_LEN;
+ sprintf(string,
+ "rxq%d_packets_with_error", q_num);
+ string += ETH_GSTRING_LEN;
+ sprintf(string, "rxq%d_allocbuf_failed",
+ q_num);
+ string += ETH_GSTRING_LEN;
+ sprintf(string, "rxq%d_producer_index",
+ q_num);
+ string += ETH_GSTRING_LEN;
+ sprintf(string, "rxq%d_consumer_index",
+ q_num);
+ string += ETH_GSTRING_LEN;
+ q_num++;
+ }
+ }
+ }
+
+ q_num = 0;
+ for (i = 0; i < bnad->num_tx; i++) {
+ if (!bnad->tx_info[i].tx)
+ continue;
+ for (j = 0; j < bnad->num_txq_per_tx; j++) {
+ sprintf(string, "txq%d_packets", q_num);
+ string += ETH_GSTRING_LEN;
+ sprintf(string, "txq%d_bytes", q_num);
+ string += ETH_GSTRING_LEN;
+ sprintf(string, "txq%d_producer_index", q_num);
+ string += ETH_GSTRING_LEN;
+ sprintf(string, "txq%d_consumer_index", q_num);
+ string += ETH_GSTRING_LEN;
+ sprintf(string, "txq%d_hw_consumer_index",
+ q_num);
+ string += ETH_GSTRING_LEN;
+ q_num++;
+ }
+ }
+
+ break;
+
+ default:
+ break;
+ }
+
+ mutex_unlock(&bnad->conf_mutex);
+}
+
+static int
+bnad_get_stats_count_locked(struct net_device *netdev)
+{
+ struct bnad *bnad = netdev_priv(netdev);
+ int i, j, count, rxf_active_num = 0, txf_active_num = 0;
+ u64 bmap;
+
+ bmap = (u64)bnad->bna.tx_mod.txf_bmap[0] |
+ ((u64)bnad->bna.tx_mod.txf_bmap[1] << 32);
+ for (i = 0; bmap && (i < BFI_LL_TXF_ID_MAX); i++) {
+ if (bmap & 1)
+ txf_active_num++;
+ bmap >>= 1;
+ }
+ bmap = (u64)bnad->bna.rx_mod.rxf_bmap[0] |
+ ((u64)bnad->bna.rx_mod.rxf_bmap[1] << 32);
+ for (i = 0; bmap && (i < BFI_LL_RXF_ID_MAX); i++) {
+ if (bmap & 1)
+ rxf_active_num++;
+ bmap >>= 1;
+ }
+ count = BNAD_ETHTOOL_STATS_NUM +
+ txf_active_num * BNAD_NUM_TXF_COUNTERS +
+ rxf_active_num * BNAD_NUM_RXF_COUNTERS;
+
+ for (i = 0; i < bnad->num_rx; i++) {
+ if (!bnad->rx_info[i].rx)
+ continue;
+ count += bnad->num_rxp_per_rx * BNAD_NUM_CQ_COUNTERS;
+ count += bnad->num_rxp_per_rx * BNAD_NUM_RXQ_COUNTERS;
+ for (j = 0; j < bnad->num_rxp_per_rx; j++)
+ if (bnad->rx_info[i].rx_ctrl[j].ccb &&
+ bnad->rx_info[i].rx_ctrl[j].ccb->rcb[1] &&
+ bnad->rx_info[i].rx_ctrl[j].ccb->rcb[1]->rxq)
+ count += BNAD_NUM_RXQ_COUNTERS;
+ }
+
+ for (i = 0; i < bnad->num_tx; i++) {
+ if (!bnad->tx_info[i].tx)
+ continue;
+ count += bnad->num_txq_per_tx * BNAD_NUM_TXQ_COUNTERS;
+ }
+ return count;
+}
+
+static int
+bnad_per_q_stats_fill(struct bnad *bnad, u64 *buf, int bi)
+{
+ int i, j;
+ struct bna_rcb *rcb = NULL;
+ struct bna_tcb *tcb = NULL;
+
+ for (i = 0; i < bnad->num_rx; i++) {
+ if (!bnad->rx_info[i].rx)
+ continue;
+ for (j = 0; j < bnad->num_rxp_per_rx; j++)
+ if (bnad->rx_info[i].rx_ctrl[j].ccb &&
+ bnad->rx_info[i].rx_ctrl[j].ccb->rcb[0] &&
+ bnad->rx_info[i].rx_ctrl[j].ccb->rcb[0]->rxq) {
+ buf[bi++] = bnad->rx_info[i].rx_ctrl[j].
+ ccb->producer_index;
+ buf[bi++] = 0; /* ccb->consumer_index */
+ buf[bi++] = *(bnad->rx_info[i].rx_ctrl[j].
+ ccb->hw_producer_index);
+ }
+ }
+ for (i = 0; i < bnad->num_rx; i++) {
+ if (!bnad->rx_info[i].rx)
+ continue;
+ for (j = 0; j < bnad->num_rxp_per_rx; j++)
+ if (bnad->rx_info[i].rx_ctrl[j].ccb) {
+ if (bnad->rx_info[i].rx_ctrl[j].ccb->rcb[0] &&
+ bnad->rx_info[i].rx_ctrl[j].ccb->
+ rcb[0]->rxq) {
+ rcb = bnad->rx_info[i].rx_ctrl[j].
+ ccb->rcb[0];
+ buf[bi++] = rcb->rxq->rx_packets;
+ buf[bi++] = rcb->rxq->rx_bytes;
+ buf[bi++] = rcb->rxq->
+ rx_packets_with_error;
+ buf[bi++] = rcb->rxq->
+ rxbuf_alloc_failed;
+ buf[bi++] = rcb->producer_index;
+ buf[bi++] = rcb->consumer_index;
+ }
+ if (bnad->rx_info[i].rx_ctrl[j].ccb->rcb[1] &&
+ bnad->rx_info[i].rx_ctrl[j].ccb->
+ rcb[1]->rxq) {
+ rcb = bnad->rx_info[i].rx_ctrl[j].
+ ccb->rcb[1];
+ buf[bi++] = rcb->rxq->rx_packets;
+ buf[bi++] = rcb->rxq->rx_bytes;
+ buf[bi++] = rcb->rxq->
+ rx_packets_with_error;
+ buf[bi++] = rcb->rxq->
+ rxbuf_alloc_failed;
+ buf[bi++] = rcb->producer_index;
+ buf[bi++] = rcb->consumer_index;
+ }
+ }
+ }
+
+ for (i = 0; i < bnad->num_tx; i++) {
+ if (!bnad->tx_info[i].tx)
+ continue;
+ for (j = 0; j < bnad->num_txq_per_tx; j++)
+ if (bnad->tx_info[i].tcb[j] &&
+ bnad->tx_info[i].tcb[j]->txq) {
+ tcb = bnad->tx_info[i].tcb[j];
+ buf[bi++] = tcb->txq->tx_packets;
+ buf[bi++] = tcb->txq->tx_bytes;
+ buf[bi++] = tcb->producer_index;
+ buf[bi++] = tcb->consumer_index;
+ buf[bi++] = *(tcb->hw_consumer_index);
+ }
+ }
+
+ return bi;
+}
+
+static void
+bnad_get_ethtool_stats(struct net_device *netdev, struct ethtool_stats *stats,
+ u64 *buf)
+{
+ struct bnad *bnad = netdev_priv(netdev);
+ int i, j, bi;
+ unsigned long flags;
+ struct rtnl_link_stats64 *net_stats64;
+ u64 *stats64;
+ u64 bmap;
+
+ mutex_lock(&bnad->conf_mutex);
+ if (bnad_get_stats_count_locked(netdev) != stats->n_stats) {
+ mutex_unlock(&bnad->conf_mutex);
+ return;
+ }
+
+ /*
+ * Used bna_lock to sync reads from bna_stats, which is written
+ * under the same lock
+ */
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ bi = 0;
+ memset(buf, 0, stats->n_stats * sizeof(u64));
+
+ net_stats64 = (struct rtnl_link_stats64 *)buf;
+ bnad_netdev_qstats_fill(bnad, net_stats64);
+ bnad_netdev_hwstats_fill(bnad, net_stats64);
+
+ bi = sizeof(*net_stats64) / sizeof(u64);
+
+ /* Fill driver stats into ethtool buffers */
+ stats64 = (u64 *)&bnad->stats.drv_stats;
+ for (i = 0; i < sizeof(struct bnad_drv_stats) / sizeof(u64); i++)
+ buf[bi++] = stats64[i];
+
+ /* Fill hardware stats excluding the rxf/txf into ethtool bufs */
+ stats64 = (u64 *) bnad->stats.bna_stats->hw_stats;
+ for (i = 0;
+ i < offsetof(struct bfi_ll_stats, rxf_stats[0]) / sizeof(u64);
+ i++)
+ buf[bi++] = stats64[i];
+
+ /* Fill txf stats into ethtool buffers */
+ bmap = (u64)bnad->bna.tx_mod.txf_bmap[0] |
+ ((u64)bnad->bna.tx_mod.txf_bmap[1] << 32);
+ for (i = 0; bmap && (i < BFI_LL_TXF_ID_MAX); i++) {
+ if (bmap & 1) {
+ stats64 = (u64 *)&bnad->stats.bna_stats->
+ hw_stats->txf_stats[i];
+ for (j = 0; j < sizeof(struct bfi_ll_stats_txf) /
+ sizeof(u64); j++)
+ buf[bi++] = stats64[j];
+ }
+ bmap >>= 1;
+ }
+
+ /* Fill rxf stats into ethtool buffers */
+ bmap = (u64)bnad->bna.rx_mod.rxf_bmap[0] |
+ ((u64)bnad->bna.rx_mod.rxf_bmap[1] << 32);
+ for (i = 0; bmap && (i < BFI_LL_RXF_ID_MAX); i++) {
+ if (bmap & 1) {
+ stats64 = (u64 *)&bnad->stats.bna_stats->
+ hw_stats->rxf_stats[i];
+ for (j = 0; j < sizeof(struct bfi_ll_stats_rxf) /
+ sizeof(u64); j++)
+ buf[bi++] = stats64[j];
+ }
+ bmap >>= 1;
+ }
+
+ /* Fill per Q stats into ethtool buffers */
+ bi = bnad_per_q_stats_fill(bnad, buf, bi);
+
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+
+ mutex_unlock(&bnad->conf_mutex);
+}
+
+static int
+bnad_get_sset_count(struct net_device *netdev, int sset)
+{
+ switch (sset) {
+ case ETH_SS_STATS:
+ return bnad_get_stats_count_locked(netdev);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static struct ethtool_ops bnad_ethtool_ops = {
+ .get_settings = bnad_get_settings,
+ .set_settings = bnad_set_settings,
+ .get_drvinfo = bnad_get_drvinfo,
+ .get_regs_len = bnad_get_regs_len,
+ .get_regs = bnad_get_regs,
+ .get_wol = bnad_get_wol,
+ .get_link = ethtool_op_get_link,
+ .get_coalesce = bnad_get_coalesce,
+ .set_coalesce = bnad_set_coalesce,
+ .get_ringparam = bnad_get_ringparam,
+ .set_ringparam = bnad_set_ringparam,
+ .get_pauseparam = bnad_get_pauseparam,
+ .set_pauseparam = bnad_set_pauseparam,
+ .get_rx_csum = bnad_get_rx_csum,
+ .set_rx_csum = bnad_set_rx_csum,
+ .get_tx_csum = ethtool_op_get_tx_csum,
+ .set_tx_csum = bnad_set_tx_csum,
+ .get_sg = ethtool_op_get_sg,
+ .set_sg = ethtool_op_set_sg,
+ .get_tso = ethtool_op_get_tso,
+ .set_tso = bnad_set_tso,
+ .get_strings = bnad_get_strings,
+ .get_ethtool_stats = bnad_get_ethtool_stats,
+ .get_sset_count = bnad_get_sset_count
+};
+
+void
+bnad_set_ethtool_ops(struct net_device *netdev)
+{
+ SET_ETHTOOL_OPS(netdev, &bnad_ethtool_ops);
+}
diff --git a/drivers/scsi/bfa/include/cs/bfa_q.h b/drivers/net/bna/cna.h
index ea895facedbc..bbd39dc65972 100644
--- a/drivers/scsi/bfa/include/cs/bfa_q.h
+++ b/drivers/net/bna/cna.h
@@ -1,9 +1,5 @@
/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ * Linux network driver for Brocade Converged Network Adapter.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License (GPL) Version 2 as
@@ -14,13 +10,46 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
-
-/**
- * bfa_q.h Circular queue definitions.
+/*
+ * Copyright (c) 2006-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
*/
-#ifndef __BFA_Q_H__
-#define __BFA_Q_H__
+#ifndef __CNA_H__
+#define __CNA_H__
+
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/if_ether.h>
+#include <asm/page.h>
+#include <asm/io.h>
+#include <asm/string.h>
+
+#include <linux/list.h>
+
+#define bfa_sm_fault(__mod, __event) do { \
+ pr_err("SM Assertion failure: %s: %d: event = %d", __FILE__, __LINE__, \
+ __event); \
+} while (0)
+
+extern char bfa_version[];
+
+#define CNA_FW_FILE_CT "ctfw_cna.bin"
+#define FC_SYMNAME_MAX 256 /*!< max name server symbolic name size */
+
+#pragma pack(1)
+
+#define MAC_ADDRLEN (6)
+typedef struct mac { u8 mac[MAC_ADDRLEN]; } mac_t;
+
+#pragma pack()
#define bfa_q_first(_q) ((void *)(((struct list_head *) (_q))->next))
#define bfa_q_next(_qe) (((struct list_head *) (_qe))->next)
@@ -38,44 +67,15 @@
* bfa_q_deq - dequeue an element from head of the queue
*/
#define bfa_q_deq(_q, _qe) { \
- if (!list_empty(_q)) { \
+ if (!list_empty(_q)) { \
(*((struct list_head **) (_qe))) = bfa_q_next(_q); \
bfa_q_prev(bfa_q_next(*((struct list_head **) _qe))) = \
(struct list_head *) (_q); \
bfa_q_next(_q) = bfa_q_next(*((struct list_head **) _qe)); \
- BFA_Q_DBG_INIT(*((struct list_head **) _qe)); \
+ bfa_q_qe_init(*((struct list_head **) _qe)); \
} else { \
*((struct list_head **) (_qe)) = (struct list_head *) NULL; \
} \
}
-/*
- * bfa_q_deq_tail - dequeue an element from tail of the queue
- */
-#define bfa_q_deq_tail(_q, _qe) { \
- if (!list_empty(_q)) { \
- *((struct list_head **) (_qe)) = bfa_q_prev(_q); \
- bfa_q_next(bfa_q_prev(*((struct list_head **) _qe))) = \
- (struct list_head *) (_q); \
- bfa_q_prev(_q) = bfa_q_prev(*(struct list_head **) _qe); \
- BFA_Q_DBG_INIT(*((struct list_head **) _qe)); \
- } else { \
- *((struct list_head **) (_qe)) = (struct list_head *) NULL; \
- } \
-}
-
-/*
- * #ifdef BFA_DEBUG (Using bfa_assert to check for debug_build is not
- * consistent across modules)
- */
-#ifndef BFA_PERF_BUILD
-#define BFA_Q_DBG_INIT(_qe) bfa_q_qe_init(_qe)
-#else
-#define BFA_Q_DBG_INIT(_qe)
-#endif
-
-#define bfa_q_is_on_q(_q, _qe) \
- bfa_q_is_on_q_func(_q, (struct list_head *)(_qe))
-extern int bfa_q_is_on_q_func(struct list_head *q, struct list_head *qe);
-
-#endif
+#endif /* __CNA_H__ */
diff --git a/drivers/net/bna/cna_fwimg.c b/drivers/net/bna/cna_fwimg.c
new file mode 100644
index 000000000000..e8f4ecd9ebb5
--- /dev/null
+++ b/drivers/net/bna/cna_fwimg.c
@@ -0,0 +1,64 @@
+/*
+ * Linux network driver for Brocade Converged Network Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ */
+#include <linux/firmware.h>
+#include "cna.h"
+
+const struct firmware *bfi_fw;
+static u32 *bfi_image_ct_cna;
+static u32 bfi_image_ct_cna_size;
+
+static u32 *
+cna_read_firmware(struct pci_dev *pdev, u32 **bfi_image,
+ u32 *bfi_image_size, char *fw_name)
+{
+ const struct firmware *fw;
+
+ if (request_firmware(&fw, fw_name, &pdev->dev)) {
+ pr_alert("Can't locate firmware %s\n", fw_name);
+ goto error;
+ }
+
+ *bfi_image = (u32 *)fw->data;
+ *bfi_image_size = fw->size/sizeof(u32);
+ bfi_fw = fw;
+
+ return *bfi_image;
+error:
+ return NULL;
+}
+
+u32 *
+cna_get_firmware_buf(struct pci_dev *pdev)
+{
+ if (bfi_image_ct_cna_size == 0)
+ cna_read_firmware(pdev, &bfi_image_ct_cna,
+ &bfi_image_ct_cna_size, CNA_FW_FILE_CT);
+ return bfi_image_ct_cna;
+}
+
+u32 *
+bfa_cb_image_get_chunk(int type, u32 off)
+{
+ return (u32 *)(bfi_image_ct_cna + off);
+}
+
+u32
+bfa_cb_image_get_size(int type)
+{
+ return bfi_image_ct_cna_size;
+}
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index e6a803f1c507..062600be073b 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -37,9 +37,6 @@
#include <linux/ethtool.h>
#include <linux/mii.h>
#include <linux/if_vlan.h>
-#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
-#define BCM_VLAN 1
-#endif
#include <net/ip.h>
#include <net/tcp.h>
#include <net/checksum.h>
@@ -49,6 +46,7 @@
#include <linux/cache.h>
#include <linux/firmware.h>
#include <linux/log2.h>
+#include <linux/aer.h>
#if defined(CONFIG_CNIC) || defined(CONFIG_CNIC_MODULE)
#define BCM_CNIC 1
@@ -58,13 +56,13 @@
#include "bnx2_fw.h"
#define DRV_MODULE_NAME "bnx2"
-#define DRV_MODULE_VERSION "2.0.17"
-#define DRV_MODULE_RELDATE "July 18, 2010"
-#define FW_MIPS_FILE_06 "bnx2/bnx2-mips-06-5.0.0.j6.fw"
-#define FW_RV2P_FILE_06 "bnx2/bnx2-rv2p-06-5.0.0.j3.fw"
-#define FW_MIPS_FILE_09 "bnx2/bnx2-mips-09-5.0.0.j15.fw"
-#define FW_RV2P_FILE_09_Ax "bnx2/bnx2-rv2p-09ax-5.0.0.j10.fw"
-#define FW_RV2P_FILE_09 "bnx2/bnx2-rv2p-09-5.0.0.j10.fw"
+#define DRV_MODULE_VERSION "2.0.18"
+#define DRV_MODULE_RELDATE "Oct 7, 2010"
+#define FW_MIPS_FILE_06 "bnx2/bnx2-mips-06-6.0.15.fw"
+#define FW_RV2P_FILE_06 "bnx2/bnx2-rv2p-06-6.0.15.fw"
+#define FW_MIPS_FILE_09 "bnx2/bnx2-mips-09-6.0.17.fw"
+#define FW_RV2P_FILE_09_Ax "bnx2/bnx2-rv2p-09ax-6.0.17.fw"
+#define FW_RV2P_FILE_09 "bnx2/bnx2-rv2p-09-6.0.17.fw"
#define RUN_AT(x) (jiffies + (x))
@@ -265,7 +263,7 @@ static inline u32 bnx2_tx_avail(struct bnx2 *bp, struct bnx2_tx_ring_info *txr)
if (diff == TX_DESC_CNT)
diff = MAX_TX_DESC_CNT;
}
- return (bp->tx_ring_size - diff);
+ return bp->tx_ring_size - diff;
}
static u32
@@ -298,7 +296,7 @@ bnx2_shmem_wr(struct bnx2 *bp, u32 offset, u32 val)
static u32
bnx2_shmem_rd(struct bnx2 *bp, u32 offset)
{
- return (bnx2_reg_rd_ind(bp, bp->shmem_base + offset));
+ return bnx2_reg_rd_ind(bp, bp->shmem_base + offset);
}
static void
@@ -976,9 +974,9 @@ bnx2_report_fw_link(struct bnx2 *bp)
static char *
bnx2_xceiver_str(struct bnx2 *bp)
{
- return ((bp->phy_port == PORT_FIBRE) ? "SerDes" :
+ return (bp->phy_port == PORT_FIBRE) ? "SerDes" :
((bp->phy_flags & BNX2_PHY_FLAG_SERDES) ? "Remote Copper" :
- "Copper"));
+ "Copper");
}
static void
@@ -1268,30 +1266,9 @@ bnx2_init_rx_context(struct bnx2 *bp, u32 cid)
val |= BNX2_L2CTX_CTX_TYPE_SIZE_L2;
val |= 0x02 << 8;
- if (CHIP_NUM(bp) == CHIP_NUM_5709) {
- u32 lo_water, hi_water;
-
- if (bp->flow_ctrl & FLOW_CTRL_TX)
- lo_water = BNX2_L2CTX_LO_WATER_MARK_DEFAULT;
- else
- lo_water = BNX2_L2CTX_LO_WATER_MARK_DIS;
- if (lo_water >= bp->rx_ring_size)
- lo_water = 0;
-
- hi_water = min_t(int, bp->rx_ring_size / 4, lo_water + 16);
-
- if (hi_water <= lo_water)
- lo_water = 0;
-
- hi_water /= BNX2_L2CTX_HI_WATER_MARK_SCALE;
- lo_water /= BNX2_L2CTX_LO_WATER_MARK_SCALE;
+ if (bp->flow_ctrl & FLOW_CTRL_TX)
+ val |= BNX2_L2CTX_FLOW_CTRL_ENABLE;
- if (hi_water > 0xf)
- hi_water = 0xf;
- else if (hi_water == 0)
- lo_water = 0;
- val |= lo_water | (hi_water << BNX2_L2CTX_HI_WATER_MARK_SHIFT);
- }
bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_CTX_TYPE, val);
}
@@ -1372,8 +1349,7 @@ bnx2_set_mac_link(struct bnx2 *bp)
/* Acknowledge the interrupt. */
REG_WR(bp, BNX2_EMAC_STATUS, BNX2_EMAC_STATUS_LINK_CHANGE);
- if (CHIP_NUM(bp) == CHIP_NUM_5709)
- bnx2_init_all_rx_contexts(bp);
+ bnx2_init_all_rx_contexts(bp);
}
static void
@@ -1757,7 +1733,7 @@ __acquires(&bp->phy_lock)
u32 new_adv = 0;
if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP)
- return (bnx2_setup_remote_phy(bp, port));
+ return bnx2_setup_remote_phy(bp, port);
if (!(bp->autoneg & AUTONEG_SPEED)) {
u32 new_bmcr;
@@ -2170,10 +2146,10 @@ __acquires(&bp->phy_lock)
return 0;
if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) {
- return (bnx2_setup_serdes_phy(bp, port));
+ return bnx2_setup_serdes_phy(bp, port);
}
else {
- return (bnx2_setup_copper_phy(bp));
+ return bnx2_setup_copper_phy(bp);
}
}
@@ -3108,8 +3084,6 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
struct sw_bd *rx_buf, *next_rx_buf;
struct sk_buff *skb;
dma_addr_t dma_addr;
- u16 vtag = 0;
- int hw_vlan __maybe_unused = 0;
sw_ring_cons = RX_RING_IDX(sw_cons);
sw_ring_prod = RX_RING_IDX(sw_prod);
@@ -3189,23 +3163,8 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
goto next_rx;
if ((status & L2_FHDR_STATUS_L2_VLAN_TAG) &&
- !(bp->rx_mode & BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG)) {
- vtag = rx_hdr->l2_fhdr_vlan_tag;
-#ifdef BCM_VLAN
- if (bp->vlgrp)
- hw_vlan = 1;
- else
-#endif
- {
- struct vlan_ethhdr *ve = (struct vlan_ethhdr *)
- __skb_push(skb, 4);
-
- memmove(ve, skb->data + 4, ETH_ALEN * 2);
- ve->h_vlan_proto = htons(ETH_P_8021Q);
- ve->h_vlan_TCI = htons(vtag);
- len += 4;
- }
- }
+ !(bp->rx_mode & BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG))
+ __vlan_hwaccel_put_tag(skb, rx_hdr->l2_fhdr_vlan_tag);
skb->protocol = eth_type_trans(skb, bp->dev);
@@ -3217,7 +3176,7 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
}
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
if (bp->rx_csum &&
(status & (L2_FHDR_STATUS_TCP_SEGMENT |
L2_FHDR_STATUS_UDP_DATAGRAM))) {
@@ -3232,14 +3191,7 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
skb->rxhash = rx_hdr->l2_fhdr_hash;
skb_record_rx_queue(skb, bnapi - &bp->bnx2_napi[0]);
-
-#ifdef BCM_VLAN
- if (hw_vlan)
- vlan_gro_receive(&bnapi->napi, bp->vlgrp, vtag, skb);
- else
-#endif
- napi_gro_receive(&bnapi->napi, skb);
-
+ napi_gro_receive(&bnapi->napi, skb);
rx_pkt++;
next_rx:
@@ -3554,13 +3506,9 @@ bnx2_set_rx_mode(struct net_device *dev)
rx_mode = bp->rx_mode & ~(BNX2_EMAC_RX_MODE_PROMISCUOUS |
BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG);
sort_mode = 1 | BNX2_RPM_SORT_USER0_BC_EN;
-#ifdef BCM_VLAN
- if (!bp->vlgrp && (bp->flags & BNX2_FLAG_CAN_KEEP_VLAN))
+ if (!(dev->features & NETIF_F_HW_VLAN_RX) &&
+ (bp->flags & BNX2_FLAG_CAN_KEEP_VLAN))
rx_mode |= BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG;
-#else
- if (bp->flags & BNX2_FLAG_CAN_KEEP_VLAN)
- rx_mode |= BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG;
-#endif
if (dev->flags & IFF_PROMISC) {
/* Promiscuous mode. */
rx_mode |= BNX2_EMAC_RX_MODE_PROMISCUOUS;
@@ -4973,6 +4921,11 @@ bnx2_init_chip(struct bnx2 *bp)
REG_WR(bp, BNX2_HC_CONFIG, val);
+ if (bp->rx_ticks < 25)
+ bnx2_reg_wr_ind(bp, BNX2_FW_RX_LOW_LATENCY, 1);
+ else
+ bnx2_reg_wr_ind(bp, BNX2_FW_RX_LOW_LATENCY, 0);
+
for (i = 1; i < bp->irq_nvecs; i++) {
u32 base = ((i - 1) * BNX2_HC_SB_CONFIG_SIZE) +
BNX2_HC_SB_CONFIG_1;
@@ -5241,18 +5194,20 @@ bnx2_init_all_rings(struct bnx2 *bp)
bnx2_init_rx_ring(bp, i);
if (bp->num_rx_rings > 1) {
- u32 tbl_32;
- u8 *tbl = (u8 *) &tbl_32;
-
- bnx2_reg_wr_ind(bp, BNX2_RXP_SCRATCH_RSS_TBL_SZ,
- BNX2_RXP_SCRATCH_RSS_TBL_MAX_ENTRIES);
+ u32 tbl_32 = 0;
for (i = 0; i < BNX2_RXP_SCRATCH_RSS_TBL_MAX_ENTRIES; i++) {
- tbl[i % 4] = i % (bp->num_rx_rings - 1);
- if ((i % 4) == 3)
- bnx2_reg_wr_ind(bp,
- BNX2_RXP_SCRATCH_RSS_TBL + i,
- cpu_to_be32(tbl_32));
+ int shift = (i % 8) << 2;
+
+ tbl_32 |= (i % (bp->num_rx_rings - 1)) << shift;
+ if ((i % 8) == 7) {
+ REG_WR(bp, BNX2_RLUP_RSS_DATA, tbl_32);
+ REG_WR(bp, BNX2_RLUP_RSS_COMMAND, (i >> 3) |
+ BNX2_RLUP_RSS_COMMAND_RSS_WRITE_MASK |
+ BNX2_RLUP_RSS_COMMAND_WRITE |
+ BNX2_RLUP_RSS_COMMAND_HASH_MASK);
+ tbl_32 = 0;
+ }
}
val = BNX2_RLUP_RSS_CONFIG_IPV4_RSS_TYPE_ALL_XI |
@@ -6201,7 +6156,7 @@ bnx2_enable_msix(struct bnx2 *bp, int msix_vecs)
}
}
-static void
+static int
bnx2_setup_int_mode(struct bnx2 *bp, int dis_msi)
{
int cpus = num_online_cpus();
@@ -6230,9 +6185,10 @@ bnx2_setup_int_mode(struct bnx2 *bp, int dis_msi)
}
bp->num_tx_rings = rounddown_pow_of_two(bp->irq_nvecs);
- bp->dev->real_num_tx_queues = bp->num_tx_rings;
+ netif_set_real_num_tx_queues(bp->dev, bp->num_tx_rings);
bp->num_rx_rings = bp->irq_nvecs;
+ return netif_set_real_num_rx_queues(bp->dev, bp->num_rx_rings);
}
/* Called with rtnl_lock */
@@ -6247,7 +6203,9 @@ bnx2_open(struct net_device *dev)
bnx2_set_power_state(bp, PCI_D0);
bnx2_disable_int(bp);
- bnx2_setup_int_mode(bp, disable_msi);
+ rc = bnx2_setup_int_mode(bp, disable_msi);
+ if (rc)
+ goto open_err;
bnx2_init_napi(bp);
bnx2_napi_enable(bp);
rc = bnx2_alloc_mem(bp);
@@ -6376,29 +6334,6 @@ bnx2_tx_timeout(struct net_device *dev)
schedule_work(&bp->reset_task);
}
-#ifdef BCM_VLAN
-/* Called with rtnl_lock */
-static void
-bnx2_vlan_rx_register(struct net_device *dev, struct vlan_group *vlgrp)
-{
- struct bnx2 *bp = netdev_priv(dev);
-
- if (netif_running(dev))
- bnx2_netif_stop(bp, false);
-
- bp->vlgrp = vlgrp;
-
- if (!netif_running(dev))
- return;
-
- bnx2_set_rx_mode(dev);
- if (bp->flags & BNX2_FLAG_CAN_KEEP_VLAN)
- bnx2_fw_sync(bp, BNX2_DRV_MSG_CODE_KEEP_VLAN_UPDATE, 0, 1);
-
- bnx2_netif_start(bp, false);
-}
-#endif
-
/* Called with netif_tx_lock.
* bnx2_tx_int() runs without netif_tx_lock unless it needs to call
* netif_wake_queue().
@@ -6439,12 +6374,11 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
vlan_tag_flags |= TX_BD_FLAGS_TCP_UDP_CKSUM;
}
-#ifdef BCM_VLAN
- if (bp->vlgrp && vlan_tx_tag_present(skb)) {
+ if (vlan_tx_tag_present(skb)) {
vlan_tag_flags |=
(TX_BD_FLAGS_VLAN_TAG | (vlan_tx_tag_get(skb) << 16));
}
-#endif
+
if ((mss = skb_shinfo(skb)->gso_size)) {
u32 tcp_opt_len;
struct iphdr *iph;
@@ -7581,15 +7515,36 @@ bnx2_set_tx_csum(struct net_device *dev, u32 data)
struct bnx2 *bp = netdev_priv(dev);
if (CHIP_NUM(bp) == CHIP_NUM_5709)
- return (ethtool_op_set_tx_ipv6_csum(dev, data));
+ return ethtool_op_set_tx_ipv6_csum(dev, data);
else
- return (ethtool_op_set_tx_csum(dev, data));
+ return ethtool_op_set_tx_csum(dev, data);
}
static int
bnx2_set_flags(struct net_device *dev, u32 data)
{
- return ethtool_op_set_flags(dev, data, ETH_FLAG_RXHASH);
+ struct bnx2 *bp = netdev_priv(dev);
+ int rc;
+
+ if (!(bp->flags & BNX2_FLAG_CAN_KEEP_VLAN) &&
+ !(data & ETH_FLAG_RXVLAN))
+ return -EINVAL;
+
+ rc = ethtool_op_set_flags(dev, data, ETH_FLAG_RXHASH | ETH_FLAG_RXVLAN |
+ ETH_FLAG_TXVLAN);
+ if (rc)
+ return rc;
+
+ if ((!!(data & ETH_FLAG_RXVLAN) !=
+ !!(bp->rx_mode & BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG)) &&
+ netif_running(dev)) {
+ bnx2_netif_stop(bp, false);
+ bnx2_set_rx_mode(dev);
+ bnx2_fw_sync(bp, BNX2_DRV_MSG_CODE_KEEP_VLAN_UPDATE, 0, 1);
+ bnx2_netif_start(bp, false);
+ }
+
+ return 0;
}
static const struct ethtool_ops bnx2_ethtool_ops = {
@@ -7704,7 +7659,7 @@ bnx2_change_mtu(struct net_device *dev, int new_mtu)
return -EINVAL;
dev->mtu = new_mtu;
- return (bnx2_change_ring_size(bp, bp->rx_ring_size, bp->tx_ring_size));
+ return bnx2_change_ring_size(bp, bp->rx_ring_size, bp->tx_ring_size);
}
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -7890,6 +7845,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
int rc, i, j;
u32 reg;
u64 dma_mask, persist_dma_mask;
+ int err;
SET_NETDEV_DEV(dev, &pdev->dev);
bp = netdev_priv(dev);
@@ -7926,7 +7882,6 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
}
pci_set_master(pdev);
- pci_save_state(pdev);
bp->pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
if (bp->pm_cap == 0) {
@@ -7981,6 +7936,15 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
bp->flags |= BNX2_FLAG_PCIE;
if (CHIP_REV(bp) == CHIP_REV_Ax)
bp->flags |= BNX2_FLAG_JUMBO_BROKEN;
+
+ /* AER (Advanced Error Reporting) hooks */
+ err = pci_enable_pcie_error_reporting(pdev);
+ if (err) {
+ dev_err(&pdev->dev, "pci_enable_pcie_error_reporting "
+ "failed 0x%x\n", err);
+ /* non-fatal, continue */
+ }
+
} else {
bp->pcix_cap = pci_find_capability(pdev, PCI_CAP_ID_PCIX);
if (bp->pcix_cap == 0) {
@@ -8237,9 +8201,14 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
bp->timer.data = (unsigned long) bp;
bp->timer.function = bnx2_timer;
+ pci_save_state(pdev);
+
return 0;
err_out_unmap:
+ if (bp->flags & BNX2_FLAG_PCIE)
+ pci_disable_pcie_error_reporting(pdev);
+
if (bp->regview) {
iounmap(bp->regview);
bp->regview = NULL;
@@ -8315,9 +8284,6 @@ static const struct net_device_ops bnx2_netdev_ops = {
.ndo_set_mac_address = bnx2_change_mac_addr,
.ndo_change_mtu = bnx2_change_mtu,
.ndo_tx_timeout = bnx2_tx_timeout,
-#ifdef BCM_VLAN
- .ndo_vlan_rx_register = bnx2_vlan_rx_register,
-#endif
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = poll_bnx2,
#endif
@@ -8325,9 +8291,7 @@ static const struct net_device_ops bnx2_netdev_ops = {
static void inline vlan_features_add(struct net_device *dev, unsigned long flags)
{
-#ifdef BCM_VLAN
dev->vlan_features |= flags;
-#endif
}
static int __devinit
@@ -8376,9 +8340,7 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
dev->features |= NETIF_F_IPV6_CSUM;
vlan_features_add(dev, NETIF_F_IPV6_CSUM);
}
-#ifdef BCM_VLAN
dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
-#endif
dev->features |= NETIF_F_TSO | NETIF_F_TSO_ECN;
vlan_features_add(dev, NETIF_F_TSO | NETIF_F_TSO_ECN);
if (CHIP_NUM(bp) == CHIP_NUM_5709) {
@@ -8435,7 +8397,11 @@ bnx2_remove_one(struct pci_dev *pdev)
kfree(bp->temp_stats_blk);
+ if (bp->flags & BNX2_FLAG_PCIE)
+ pci_disable_pcie_error_reporting(pdev);
+
free_netdev(dev);
+
pci_release_regions(pdev);
pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL);
@@ -8527,25 +8493,38 @@ static pci_ers_result_t bnx2_io_slot_reset(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct bnx2 *bp = netdev_priv(dev);
+ pci_ers_result_t result;
+ int err;
rtnl_lock();
if (pci_enable_device(pdev)) {
dev_err(&pdev->dev,
"Cannot re-enable PCI device after reset\n");
- rtnl_unlock();
- return PCI_ERS_RESULT_DISCONNECT;
+ result = PCI_ERS_RESULT_DISCONNECT;
+ } else {
+ pci_set_master(pdev);
+ pci_restore_state(pdev);
+ pci_save_state(pdev);
+
+ if (netif_running(dev)) {
+ bnx2_set_power_state(bp, PCI_D0);
+ bnx2_init_nic(bp, 1);
+ }
+ result = PCI_ERS_RESULT_RECOVERED;
}
- pci_set_master(pdev);
- pci_restore_state(pdev);
- pci_save_state(pdev);
+ rtnl_unlock();
- if (netif_running(dev)) {
- bnx2_set_power_state(bp, PCI_D0);
- bnx2_init_nic(bp, 1);
+ if (!(bp->flags & BNX2_FLAG_PCIE))
+ return result;
+
+ err = pci_cleanup_aer_uncorrect_error_status(pdev);
+ if (err) {
+ dev_err(&pdev->dev,
+ "pci_cleanup_aer_uncorrect_error_status failed 0x%0x\n",
+ err); /* non-fatal, continue */
}
- rtnl_unlock();
- return PCI_ERS_RESULT_RECOVERED;
+ return result;
}
/**
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index 2104c1005d02..bf4c3421067d 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -352,12 +352,7 @@ struct l2_fhdr {
#define BNX2_L2CTX_BD_PRE_READ 0x00000000
#define BNX2_L2CTX_CTX_SIZE 0x00000000
#define BNX2_L2CTX_CTX_TYPE 0x00000000
-#define BNX2_L2CTX_LO_WATER_MARK_DEFAULT 4
-#define BNX2_L2CTX_LO_WATER_MARK_SCALE 4
-#define BNX2_L2CTX_LO_WATER_MARK_DIS 0
-#define BNX2_L2CTX_HI_WATER_MARK_SHIFT 4
-#define BNX2_L2CTX_HI_WATER_MARK_SCALE 16
-#define BNX2_L2CTX_WATER_MARKS_MSK 0x000000ff
+#define BNX2_L2CTX_FLOW_CTRL_ENABLE 0x000000ff
#define BNX2_L2CTX_CTX_TYPE_SIZE_L2 ((0x20/20)<<16)
#define BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE (0xf<<28)
#define BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_UNDEFINED (0<<28)
@@ -4185,6 +4180,15 @@ struct l2_fhdr {
#define BNX2_RLUP_RSS_CONFIG_IPV6_RSS_TYPE_IP_ONLY_XI (2L<<2)
#define BNX2_RLUP_RSS_CONFIG_IPV6_RSS_TYPE_RES_XI (3L<<2)
+#define BNX2_RLUP_RSS_COMMAND 0x00002048
+#define BNX2_RLUP_RSS_COMMAND_RSS_IND_TABLE_ADDR (0xfUL<<0)
+#define BNX2_RLUP_RSS_COMMAND_RSS_WRITE_MASK (0xffUL<<4)
+#define BNX2_RLUP_RSS_COMMAND_WRITE (1UL<<12)
+#define BNX2_RLUP_RSS_COMMAND_READ (1UL<<13)
+#define BNX2_RLUP_RSS_COMMAND_HASH_MASK (0x7UL<<14)
+
+#define BNX2_RLUP_RSS_DATA 0x0000204c
+
/*
* rbuf_reg definition
@@ -6077,6 +6081,7 @@ struct l2_fhdr {
#define BNX2_COM_SCRATCH 0x00120000
+#define BNX2_FW_RX_LOW_LATENCY 0x00120058
#define BNX2_FW_RX_DROP_COUNT 0x00120084
@@ -6497,8 +6502,8 @@ struct l2_fhdr {
#define TX_DESC_CNT (BCM_PAGE_SIZE / sizeof(struct tx_bd))
#define MAX_TX_DESC_CNT (TX_DESC_CNT - 1)
-#define MAX_RX_RINGS 4
-#define MAX_RX_PG_RINGS 16
+#define MAX_RX_RINGS 8
+#define MAX_RX_PG_RINGS 32
#define RX_DESC_CNT (BCM_PAGE_SIZE / sizeof(struct rx_bd))
#define MAX_RX_DESC_CNT (RX_DESC_CNT - 1)
#define MAX_TOTAL_RX_DESC_CNT (MAX_RX_DESC_CNT * MAX_RX_RINGS)
@@ -6737,10 +6742,6 @@ struct bnx2 {
struct bnx2_napi bnx2_napi[BNX2_MAX_MSIX_VEC];
-#ifdef BCM_VLAN
- struct vlan_group *vlgrp;
-#endif
-
u32 rx_buf_use_size; /* useable size */
u32 rx_buf_size; /* with alignment */
u32 rx_copy_thresh;
diff --git a/drivers/net/bnx2x/bnx2x.h b/drivers/net/bnx2x/bnx2x.h
index 0c2d96ed561c..9571ecf48f35 100644
--- a/drivers/net/bnx2x/bnx2x.h
+++ b/drivers/net/bnx2x/bnx2x.h
@@ -20,26 +20,20 @@
* (you will need to reboot afterwards) */
/* #define BNX2X_STOP_ON_ERROR */
-#define DRV_MODULE_VERSION "1.52.53-4"
-#define DRV_MODULE_RELDATE "2010/16/08"
+#define DRV_MODULE_VERSION "1.60.00-3"
+#define DRV_MODULE_RELDATE "2010/10/19"
#define BNX2X_BC_VER 0x040200
-#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
-#define BCM_VLAN 1
-#endif
-
#define BNX2X_MULTI_QUEUE
#define BNX2X_NEW_NAPI
-
#if defined(CONFIG_CNIC) || defined(CONFIG_CNIC_MODULE)
#define BCM_CNIC 1
#include "../cnic_if.h"
#endif
-
#ifdef BCM_CNIC
#define BNX2X_MIN_MSIX_VEC_CNT 3
#define BNX2X_MSIX_VEC_FP_START 2
@@ -129,16 +123,18 @@ void bnx2x_panic_dump(struct bnx2x *bp);
} while (0)
#endif
+#define bnx2x_mc_addr(ha) ((ha)->addr)
#define U64_LO(x) (u32)(((u64)(x)) & 0xffffffff)
#define U64_HI(x) (u32)(((u64)(x)) >> 32)
#define HILO_U64(hi, lo) ((((u64)(hi)) << 32) + (lo))
-#define REG_ADDR(bp, offset) (bp->regview + offset)
+#define REG_ADDR(bp, offset) ((bp->regview) + (offset))
#define REG_RD(bp, offset) readl(REG_ADDR(bp, offset))
#define REG_RD8(bp, offset) readb(REG_ADDR(bp, offset))
+#define REG_RD16(bp, offset) readw(REG_ADDR(bp, offset))
#define REG_WR(bp, offset, val) writel((u32)val, REG_ADDR(bp, offset))
#define REG_WR8(bp, offset, val) writeb((u8)val, REG_ADDR(bp, offset))
@@ -160,6 +156,9 @@ void bnx2x_panic_dump(struct bnx2x *bp);
offset, len32); \
} while (0)
+#define REG_WR_DMAE_LEN(bp, offset, valp, len32) \
+ REG_WR_DMAE(bp, offset, valp, len32)
+
#define VIRT_WR_DMAE_LEN(bp, data, addr, len32, le32_swap) \
do { \
memcpy(GUNZIP_BUF(bp), data, (len32) * 4); \
@@ -175,16 +174,59 @@ void bnx2x_panic_dump(struct bnx2x *bp);
offsetof(struct shmem2_region, field))
#define SHMEM2_RD(bp, field) REG_RD(bp, SHMEM2_ADDR(bp, field))
#define SHMEM2_WR(bp, field, val) REG_WR(bp, SHMEM2_ADDR(bp, field), val)
+#define MF_CFG_ADDR(bp, field) (bp->common.mf_cfg_base + \
+ offsetof(struct mf_cfg, field))
+#define MF2_CFG_ADDR(bp, field) (bp->common.mf2_cfg_base + \
+ offsetof(struct mf2_cfg, field))
-#define MF_CFG_RD(bp, field) SHMEM_RD(bp, mf_cfg.field)
-#define MF_CFG_WR(bp, field, val) SHMEM_WR(bp, mf_cfg.field, val)
+#define MF_CFG_RD(bp, field) REG_RD(bp, MF_CFG_ADDR(bp, field))
+#define MF_CFG_WR(bp, field, val) REG_WR(bp,\
+ MF_CFG_ADDR(bp, field), (val))
+#define MF2_CFG_RD(bp, field) REG_RD(bp, MF2_CFG_ADDR(bp, field))
+
+#define SHMEM2_HAS(bp, field) ((bp)->common.shmem2_base && \
+ (SHMEM2_RD((bp), size) > \
+ offsetof(struct shmem2_region, field)))
#define EMAC_RD(bp, reg) REG_RD(bp, emac_base + reg)
#define EMAC_WR(bp, reg, val) REG_WR(bp, emac_base + reg, val)
+/* SP SB indices */
+
+/* General SP events - stats query, cfc delete, etc */
+#define HC_SP_INDEX_ETH_DEF_CONS 3
+
+/* EQ completions */
+#define HC_SP_INDEX_EQ_CONS 7
+
+/* iSCSI L2 */
+#define HC_SP_INDEX_ETH_ISCSI_CQ_CONS 5
+#define HC_SP_INDEX_ETH_ISCSI_RX_CQ_CONS 1
+
+/**
+ * CIDs and CLIDs:
+ * CLIDs below is a CLID for func 0, then the CLID for other
+ * functions will be calculated by the formula:
+ *
+ * FUNC_N_CLID_X = N * NUM_SPECIAL_CLIENTS + FUNC_0_CLID_X
+ *
+ */
+/* iSCSI L2 */
+#define BNX2X_ISCSI_ETH_CL_ID 17
+#define BNX2X_ISCSI_ETH_CID 17
+
+/** Additional rings budgeting */
+#ifdef BCM_CNIC
+#define CNIC_CONTEXT_USE 1
+#else
+#define CNIC_CONTEXT_USE 0
+#endif /* BCM_CNIC */
+
#define AEU_IN_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR \
AEU_INPUTS_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR
+#define SM_RX_ID 0
+#define SM_TX_ID 1
/* fast path */
@@ -254,11 +296,24 @@ union db_prod {
#define RX_SGE_MASK_LEN_MASK (RX_SGE_MASK_LEN - 1)
#define NEXT_SGE_MASK_ELEM(el) (((el) + 1) & RX_SGE_MASK_LEN_MASK)
+union host_hc_status_block {
+ /* pointer to fp status block e1x */
+ struct host_hc_status_block_e1x *e1x_sb;
+ /* pointer to fp status block e2 */
+ struct host_hc_status_block_e2 *e2_sb;
+};
struct bnx2x_fastpath {
+#define BNX2X_NAPI_WEIGHT 128
struct napi_struct napi;
- struct host_status_block *status_blk;
+ union host_hc_status_block status_blk;
+ /* chip independed shortcuts into sb structure */
+ __le16 *sb_index_values;
+ __le16 *sb_running_index;
+ /* chip independed shortcut into rx_prods_offset memory */
+ u32 ustorm_rx_prods_offset;
+
dma_addr_t status_blk_mapping;
struct sw_tx_bd *tx_buf_ring;
@@ -288,10 +343,15 @@ struct bnx2x_fastpath {
#define BNX2X_FP_STATE_OPEN 0xa0000
#define BNX2X_FP_STATE_HALTING 0xb0000
#define BNX2X_FP_STATE_HALTED 0xc0000
+#define BNX2X_FP_STATE_TERMINATING 0xd0000
+#define BNX2X_FP_STATE_TERMINATED 0xe0000
- u8 index; /* number in fp array */
- u8 cl_id; /* eth client id */
- u8 sb_id; /* status block number in HW */
+ u8 index; /* number in fp array */
+ u8 cl_id; /* eth client id */
+ u8 cl_qzone_id;
+ u8 fw_sb_id; /* status block number in FW */
+ u8 igu_sb_id; /* status block number in HW */
+ u32 cid;
union db_prod tx_db;
@@ -301,8 +361,7 @@ struct bnx2x_fastpath {
u16 tx_bd_cons;
__le16 *tx_cons_sb;
- __le16 fp_c_idx;
- __le16 fp_u_idx;
+ __le16 fp_hc_idx;
u16 rx_bd_prod;
u16 rx_bd_cons;
@@ -312,8 +371,6 @@ struct bnx2x_fastpath {
/* The last maximal completed SGE */
u16 last_max_sge;
__le16 *rx_cons_sb;
- __le16 *rx_bd_cons_sb;
-
unsigned long tx_pkt,
rx_pkt,
@@ -356,6 +413,8 @@ struct bnx2x_fastpath {
#define NUM_TX_BD (TX_DESC_CNT * NUM_TX_RINGS)
#define MAX_TX_BD (NUM_TX_BD - 1)
#define MAX_TX_AVAIL (MAX_TX_DESC_CNT * NUM_TX_RINGS - 2)
+#define INIT_JUMBO_TX_RING_SIZE MAX_TX_AVAIL
+#define INIT_TX_RING_SIZE MAX_TX_AVAIL
#define NEXT_TX_IDX(x) ((((x) & MAX_TX_DESC_CNT) == \
(MAX_TX_DESC_CNT - 1)) ? (x) + 2 : (x) + 1)
#define TX_BD(x) ((x) & MAX_TX_BD)
@@ -369,6 +428,9 @@ struct bnx2x_fastpath {
#define NUM_RX_BD (RX_DESC_CNT * NUM_RX_RINGS)
#define MAX_RX_BD (NUM_RX_BD - 1)
#define MAX_RX_AVAIL (MAX_RX_DESC_CNT * NUM_RX_RINGS - 2)
+#define MIN_RX_AVAIL 128
+#define INIT_JUMBO_RX_RING_SIZE MAX_RX_AVAIL
+#define INIT_RX_RING_SIZE MAX_RX_AVAIL
#define NEXT_RX_IDX(x) ((((x) & RX_DESC_MASK) == \
(MAX_RX_DESC_CNT - 1)) ? (x) + 3 : (x) + 1)
#define RX_BD(x) ((x) & MAX_RX_BD)
@@ -419,11 +481,12 @@ struct bnx2x_fastpath {
le32_to_cpu((bd)->addr_lo))
#define BD_UNMAP_LEN(bd) (le16_to_cpu((bd)->nbytes))
-
+#define BNX2X_DB_MIN_SHIFT 3 /* 8 bytes */
+#define BNX2X_DB_SHIFT 7 /* 128 bytes*/
#define DPM_TRIGER_TYPE 0x40
#define DOORBELL(bp, cid, val) \
do { \
- writel((u32)(val), bp->doorbells + (BCM_PAGE_SIZE * (cid)) + \
+ writel((u32)(val), bp->doorbells + (bp->db_size * (cid)) + \
DPM_TRIGER_TYPE); \
} while (0)
@@ -481,31 +544,15 @@ struct bnx2x_fastpath {
#define BNX2X_RX_SUM_FIX(cqe) \
BNX2X_PRS_FLAG_OVERETH_IPV4(cqe->fast_path_cqe.pars_flags.flags)
-
-#define FP_USB_FUNC_OFF (2 + 2*HC_USTORM_SB_NUM_INDICES)
-#define FP_CSB_FUNC_OFF (2 + 2*HC_CSTORM_SB_NUM_INDICES)
-
-#define U_SB_ETH_RX_CQ_INDEX HC_INDEX_U_ETH_RX_CQ_CONS
-#define U_SB_ETH_RX_BD_INDEX HC_INDEX_U_ETH_RX_BD_CONS
-#define C_SB_ETH_TX_CQ_INDEX HC_INDEX_C_ETH_TX_CQ_CONS
+#define U_SB_ETH_RX_CQ_INDEX 1
+#define U_SB_ETH_RX_BD_INDEX 2
+#define C_SB_ETH_TX_CQ_INDEX 5
#define BNX2X_RX_SB_INDEX \
- (&fp->status_blk->u_status_block.index_values[U_SB_ETH_RX_CQ_INDEX])
-
-#define BNX2X_RX_SB_BD_INDEX \
- (&fp->status_blk->u_status_block.index_values[U_SB_ETH_RX_BD_INDEX])
-
-#define BNX2X_RX_SB_INDEX_NUM \
- (((U_SB_ETH_RX_CQ_INDEX << \
- USTORM_ETH_ST_CONTEXT_CONFIG_CQE_SB_INDEX_NUMBER_SHIFT) & \
- USTORM_ETH_ST_CONTEXT_CONFIG_CQE_SB_INDEX_NUMBER) | \
- ((U_SB_ETH_RX_BD_INDEX << \
- USTORM_ETH_ST_CONTEXT_CONFIG_BD_SB_INDEX_NUMBER_SHIFT) & \
- USTORM_ETH_ST_CONTEXT_CONFIG_BD_SB_INDEX_NUMBER))
+ (&fp->sb_index_values[U_SB_ETH_RX_CQ_INDEX])
#define BNX2X_TX_SB_INDEX \
- (&fp->status_blk->c_status_block.index_values[C_SB_ETH_TX_CQ_INDEX])
-
+ (&fp->sb_index_values[C_SB_ETH_TX_CQ_INDEX])
/* end of fast path */
@@ -521,12 +568,19 @@ struct bnx2x_common {
#define CHIP_NUM_57710 0x164e
#define CHIP_NUM_57711 0x164f
#define CHIP_NUM_57711E 0x1650
+#define CHIP_NUM_57712 0x1662
+#define CHIP_NUM_57712E 0x1663
#define CHIP_IS_E1(bp) (CHIP_NUM(bp) == CHIP_NUM_57710)
#define CHIP_IS_57711(bp) (CHIP_NUM(bp) == CHIP_NUM_57711)
#define CHIP_IS_57711E(bp) (CHIP_NUM(bp) == CHIP_NUM_57711E)
+#define CHIP_IS_57712(bp) (CHIP_NUM(bp) == CHIP_NUM_57712)
+#define CHIP_IS_57712E(bp) (CHIP_NUM(bp) == CHIP_NUM_57712E)
#define CHIP_IS_E1H(bp) (CHIP_IS_57711(bp) || \
CHIP_IS_57711E(bp))
-#define IS_E1H_OFFSET CHIP_IS_E1H(bp)
+#define CHIP_IS_E2(bp) (CHIP_IS_57712(bp) || \
+ CHIP_IS_57712E(bp))
+#define CHIP_IS_E1x(bp) (CHIP_IS_E1((bp)) || CHIP_IS_E1H((bp)))
+#define IS_E1H_OFFSET (CHIP_IS_E1H(bp) || CHIP_IS_E2(bp))
#define CHIP_REV(bp) (bp->common.chip_id & 0x0000f000)
#define CHIP_REV_Ax 0x00000000
@@ -552,12 +606,34 @@ struct bnx2x_common {
u32 shmem_base;
u32 shmem2_base;
+ u32 mf_cfg_base;
+ u32 mf2_cfg_base;
u32 hw_config;
u32 bc_ver;
+
+ u8 int_block;
+#define INT_BLOCK_HC 0
+#define INT_BLOCK_IGU 1
+#define INT_BLOCK_MODE_NORMAL 0
+#define INT_BLOCK_MODE_BW_COMP 2
+#define CHIP_INT_MODE_IS_NBC(bp) \
+ (CHIP_IS_E2(bp) && \
+ !((bp)->common.int_block & INT_BLOCK_MODE_BW_COMP))
+#define CHIP_INT_MODE_IS_BC(bp) (!CHIP_INT_MODE_IS_NBC(bp))
+
+ u8 chip_port_mode;
+#define CHIP_4_PORT_MODE 0x0
+#define CHIP_2_PORT_MODE 0x1
+#define CHIP_PORT_MODE_NONE 0x2
+#define CHIP_MODE(bp) (bp->common.chip_port_mode)
+#define CHIP_MODE_IS_4_PORT(bp) (CHIP_MODE(bp) == CHIP_4_PORT_MODE)
};
+/* IGU MSIX STATISTICS on 57712: 64 for VFs; 4 for PFs; 4 for Attentions */
+#define BNX2X_IGU_STAS_MSG_VF_CNT 64
+#define BNX2X_IGU_STAS_MSG_PF_CNT 4
/* end of common */
@@ -566,13 +642,13 @@ struct bnx2x_common {
struct bnx2x_port {
u32 pmf;
- u32 link_config;
+ u32 link_config[LINK_CONFIG_SIZE];
- u32 supported;
+ u32 supported[LINK_CONFIG_SIZE];
/* link settings - missing defines */
#define SUPPORTED_2500baseX_Full (1 << 15)
- u32 advertising;
+ u32 advertising[LINK_CONFIG_SIZE];
/* link settings - missing defines */
#define ADVERTISED_2500baseX_Full (1 << 15)
@@ -589,27 +665,98 @@ struct bnx2x_port {
/* end of port */
+/* e1h Classification CAM line allocations */
+enum {
+ CAM_ETH_LINE = 0,
+ CAM_ISCSI_ETH_LINE,
+ CAM_MAX_PF_LINE = CAM_ISCSI_ETH_LINE
+};
+#define BNX2X_VF_ID_INVALID 0xFF
-#ifdef BCM_CNIC
-#define MAX_CONTEXT 15
-#else
-#define MAX_CONTEXT 16
-#endif
+/*
+ * The total number of L2 queues, MSIX vectors and HW contexts (CIDs) is
+ * control by the number of fast-path status blocks supported by the
+ * device (HW/FW). Each fast-path status block (FP-SB) aka non-default
+ * status block represents an independent interrupts context that can
+ * serve a regular L2 networking queue. However special L2 queues such
+ * as the FCoE queue do not require a FP-SB and other components like
+ * the CNIC may consume FP-SB reducing the number of possible L2 queues
+ *
+ * If the maximum number of FP-SB available is X then:
+ * a. If CNIC is supported it consumes 1 FP-SB thus the max number of
+ * regular L2 queues is Y=X-1
+ * b. in MF mode the actual number of L2 queues is Y= (X-1/MF_factor)
+ * c. If the FCoE L2 queue is supported the actual number of L2 queues
+ * is Y+1
+ * d. The number of irqs (MSIX vectors) is either Y+1 (one extra for
+ * slow-path interrupts) or Y+2 if CNIC is supported (one additional
+ * FP interrupt context for the CNIC).
+ * e. The number of HW context (CID count) is always X or X+1 if FCoE
+ * L2 queue is supported. the cid for the FCoE L2 queue is always X.
+ */
+
+#define FP_SB_MAX_E1x 16 /* fast-path interrupt contexts E1x */
+#define FP_SB_MAX_E2 16 /* fast-path interrupt contexts E2 */
+
+/*
+ * cid_cnt paramter below refers to the value returned by
+ * 'bnx2x_get_l2_cid_count()' routine
+ */
+
+/*
+ * The number of FP context allocated by the driver == max number of regular
+ * L2 queues + 1 for the FCoE L2 queue
+ */
+#define L2_FP_COUNT(cid_cnt) ((cid_cnt) - CNIC_CONTEXT_USE)
union cdu_context {
struct eth_context eth;
char pad[1024];
};
+/* CDU host DB constants */
+#define CDU_ILT_PAGE_SZ_HW 3
+#define CDU_ILT_PAGE_SZ (4096 << CDU_ILT_PAGE_SZ_HW) /* 32K */
+#define ILT_PAGE_CIDS (CDU_ILT_PAGE_SZ / sizeof(union cdu_context))
+
+#ifdef BCM_CNIC
+#define CNIC_ISCSI_CID_MAX 256
+#define CNIC_CID_MAX (CNIC_ISCSI_CID_MAX)
+#define CNIC_ILT_LINES DIV_ROUND_UP(CNIC_CID_MAX, ILT_PAGE_CIDS)
+#endif
+
+#define QM_ILT_PAGE_SZ_HW 3
+#define QM_ILT_PAGE_SZ (4096 << QM_ILT_PAGE_SZ_HW) /* 32K */
+#define QM_CID_ROUND 1024
+
+#ifdef BCM_CNIC
+/* TM (timers) host DB constants */
+#define TM_ILT_PAGE_SZ_HW 2
+#define TM_ILT_PAGE_SZ (4096 << TM_ILT_PAGE_SZ_HW) /* 16K */
+/* #define TM_CONN_NUM (CNIC_STARTING_CID+CNIC_ISCSI_CXT_MAX) */
+#define TM_CONN_NUM 1024
+#define TM_ILT_SZ (8 * TM_CONN_NUM)
+#define TM_ILT_LINES DIV_ROUND_UP(TM_ILT_SZ, TM_ILT_PAGE_SZ)
+
+/* SRC (Searcher) host DB constants */
+#define SRC_ILT_PAGE_SZ_HW 3
+#define SRC_ILT_PAGE_SZ (4096 << SRC_ILT_PAGE_SZ_HW) /* 32K */
+#define SRC_HASH_BITS 10
+#define SRC_CONN_NUM (1 << SRC_HASH_BITS) /* 1024 */
+#define SRC_ILT_SZ (sizeof(struct src_ent) * SRC_CONN_NUM)
+#define SRC_T2_SZ SRC_ILT_SZ
+#define SRC_ILT_LINES DIV_ROUND_UP(SRC_ILT_SZ, SRC_ILT_PAGE_SZ)
+#endif
+
#define MAX_DMAE_C 8
/* DMA memory not used in fastpath */
struct bnx2x_slowpath {
- union cdu_context context[MAX_CONTEXT];
struct eth_stats_query fw_stats;
struct mac_configuration_cmd mac_config;
struct mac_configuration_cmd mcast_config;
+ struct client_init_ramrod_data client_init_data;
/* used by dmae command executer */
struct dmae_command dmae[MAX_DMAE_C];
@@ -634,52 +781,83 @@ struct bnx2x_slowpath {
#define MAX_DYNAMIC_ATTN_GRPS 8
struct attn_route {
- u32 sig[4];
+ u32 sig[5];
+};
+
+struct iro {
+ u32 base;
+ u16 m1;
+ u16 m2;
+ u16 m3;
+ u16 size;
};
+struct hw_context {
+ union cdu_context *vcxt;
+ dma_addr_t cxt_mapping;
+ size_t size;
+};
+
+/* forward */
+struct bnx2x_ilt;
+
typedef enum {
BNX2X_RECOVERY_DONE,
BNX2X_RECOVERY_INIT,
BNX2X_RECOVERY_WAIT,
} bnx2x_recovery_state_t;
+/**
+ * Event queue (EQ or event ring) MC hsi
+ * NUM_EQ_PAGES and EQ_DESC_CNT_PAGE must be power of 2
+ */
+#define NUM_EQ_PAGES 1
+#define EQ_DESC_CNT_PAGE (BCM_PAGE_SIZE / sizeof(union event_ring_elem))
+#define EQ_DESC_MAX_PAGE (EQ_DESC_CNT_PAGE - 1)
+#define NUM_EQ_DESC (EQ_DESC_CNT_PAGE * NUM_EQ_PAGES)
+#define EQ_DESC_MASK (NUM_EQ_DESC - 1)
+#define MAX_EQ_AVAIL (EQ_DESC_MAX_PAGE * NUM_EQ_PAGES - 2)
+
+/* depends on EQ_DESC_CNT_PAGE being a power of 2 */
+#define NEXT_EQ_IDX(x) ((((x) & EQ_DESC_MAX_PAGE) == \
+ (EQ_DESC_MAX_PAGE - 1)) ? (x) + 2 : (x) + 1)
+
+/* depends on the above and on NUM_EQ_PAGES being a power of 2 */
+#define EQ_DESC(x) ((x) & EQ_DESC_MASK)
+
+#define BNX2X_EQ_INDEX \
+ (&bp->def_status_blk->sp_sb.\
+ index_values[HC_SP_INDEX_EQ_CONS])
+
struct bnx2x {
/* Fields used in the tx and intr/napi performance paths
* are grouped together in the beginning of the structure
*/
- struct bnx2x_fastpath fp[MAX_CONTEXT];
+ struct bnx2x_fastpath *fp;
void __iomem *regview;
void __iomem *doorbells;
-#ifdef BCM_CNIC
-#define BNX2X_DB_SIZE (18*BCM_PAGE_SIZE)
-#else
-#define BNX2X_DB_SIZE (16*BCM_PAGE_SIZE)
-#endif
+ u16 db_size;
struct net_device *dev;
struct pci_dev *pdev;
+ struct iro *iro_arr;
+#define IRO (bp->iro_arr)
+
atomic_t intr_sem;
bnx2x_recovery_state_t recovery_state;
int is_leader;
-#ifdef BCM_CNIC
- struct msix_entry msix_table[MAX_CONTEXT+2];
-#else
- struct msix_entry msix_table[MAX_CONTEXT+1];
-#endif
+ struct msix_entry *msix_table;
#define INT_MODE_INTx 1
#define INT_MODE_MSI 2
int tx_ring_size;
-#ifdef BCM_VLAN
- struct vlan_group *vlgrp;
-#endif
-
u32 rx_csum;
u32 rx_buf_size;
-#define ETH_OVREHEAD (ETH_HLEN + 8) /* 8 for CRC + VLAN */
+/* L2 header size + 2*VLANs (8 bytes) + LLC SNAP (8 bytes) */
+#define ETH_OVREHEAD (ETH_HLEN + 8 + 8)
#define ETH_MIN_PACKET_SIZE 60
#define ETH_MAX_PACKET_SIZE 1500
#define ETH_MAX_JUMBO_PACKET_SIZE 9600
@@ -688,13 +866,12 @@ struct bnx2x {
#define BNX2X_RX_ALIGN_SHIFT ((L1_CACHE_SHIFT < 8) ? \
L1_CACHE_SHIFT : 8)
#define BNX2X_RX_ALIGN (1 << BNX2X_RX_ALIGN_SHIFT)
+#define BNX2X_PXP_DRAM_ALIGN (BNX2X_RX_ALIGN_SHIFT - 5)
- struct host_def_status_block *def_status_blk;
-#define DEF_SB_ID 16
- __le16 def_c_idx;
- __le16 def_u_idx;
- __le16 def_x_idx;
- __le16 def_t_idx;
+ struct host_sp_status_block *def_status_blk;
+#define DEF_SB_IGU_ID 16
+#define DEF_SB_ID HC_SP_SB_ID
+ __le16 def_idx;
__le16 def_att_idx;
u32 attn_state;
struct attn_route attn_group[MAX_DYNAMIC_ATTN_GRPS];
@@ -706,10 +883,17 @@ struct bnx2x {
struct eth_spe *spq_prod_bd;
struct eth_spe *spq_last_bd;
__le16 *dsb_sp_prod;
- u16 spq_left; /* serialize spq */
+ atomic_t spq_left; /* serialize spq */
/* used to synchronize spq accesses */
spinlock_t spq_lock;
+ /* event queue */
+ union event_ring_elem *eq_ring;
+ dma_addr_t eq_mapping;
+ u16 eq_prod;
+ u16 eq_cons;
+ __le16 *eq_cons_sb;
+
/* Flags for marking that there is a STAT_QUERY or
SET_MAC ramrod pending */
int stats_pending;
@@ -728,18 +912,27 @@ struct bnx2x {
#define USING_DAC_FLAG 0x10
#define USING_MSIX_FLAG 0x20
#define USING_MSI_FLAG 0x40
+
#define TPA_ENABLE_FLAG 0x80
#define NO_MCP_FLAG 0x100
+#define DISABLE_MSI_FLAG 0x200
#define BP_NOMCP(bp) (bp->flags & NO_MCP_FLAG)
-#define HW_VLAN_TX_FLAG 0x400
-#define HW_VLAN_RX_FLAG 0x800
#define MF_FUNC_DIS 0x1000
- int func;
-#define BP_PORT(bp) (bp->func % PORT_MAX)
-#define BP_FUNC(bp) (bp->func)
-#define BP_E1HVN(bp) (bp->func >> 1)
+ int pf_num; /* absolute PF number */
+ int pfid; /* per-path PF number */
+ int base_fw_ndsb;
+#define BP_PATH(bp) (!CHIP_IS_E2(bp) ? \
+ 0 : (bp->pf_num & 1))
+#define BP_PORT(bp) (bp->pfid & 1)
+#define BP_FUNC(bp) (bp->pfid)
+#define BP_ABS_FUNC(bp) (bp->pf_num)
+#define BP_E1HVN(bp) (bp->pfid >> 1)
+#define BP_VN(bp) (CHIP_MODE_IS_4_PORT(bp) ? \
+ 0 : BP_E1HVN(bp))
#define BP_L_ID(bp) (BP_E1HVN(bp) << 2)
+#define BP_FW_MB_IDX(bp) (BP_PORT(bp) +\
+ BP_VN(bp) * (CHIP_IS_E1x(bp) ? 2 : 1))
#ifdef BCM_CNIC
#define BCM_CNIC_CID_START 16
@@ -769,10 +962,11 @@ struct bnx2x {
struct cmng_struct_per_port cmng;
u32 vn_weight_sum;
- u32 mf_config;
- u16 e1hov;
- u8 e1hmf;
-#define IS_E1HMF(bp) (bp->e1hmf != 0)
+ u32 mf_config[E1HVN_MAX];
+ u32 mf2_config[E2_FUNC_MAX];
+ u16 mf_ov;
+ u8 mf_mode;
+#define IS_MF(bp) (bp->mf_mode != 0)
u8 wol;
@@ -800,6 +994,7 @@ struct bnx2x {
#define BNX2X_STATE_CLOSING_WAIT4_HALT 0x4000
#define BNX2X_STATE_CLOSING_WAIT4_DELETE 0x5000
#define BNX2X_STATE_CLOSING_WAIT4_UNLOAD 0x6000
+#define BNX2X_STATE_FUNC_STARTED 0x7000
#define BNX2X_STATE_DIAG 0xe000
#define BNX2X_STATE_ERROR 0xf000
@@ -808,6 +1003,15 @@ struct bnx2x {
int disable_tpa;
int int_mode;
+ struct tstorm_eth_mac_filter_config mac_filters;
+#define BNX2X_ACCEPT_NONE 0x0000
+#define BNX2X_ACCEPT_UNICAST 0x0001
+#define BNX2X_ACCEPT_MULTICAST 0x0002
+#define BNX2X_ACCEPT_ALL_UNICAST 0x0004
+#define BNX2X_ACCEPT_ALL_MULTICAST 0x0008
+#define BNX2X_ACCEPT_BROADCAST 0x0010
+#define BNX2X_PROMISCUOUS_MODE 0x10000
+
u32 rx_mode;
#define BNX2X_RX_MODE_NONE 0
#define BNX2X_RX_MODE_NORMAL 1
@@ -816,34 +1020,41 @@ struct bnx2x {
#define BNX2X_MAX_MULTICAST 64
#define BNX2X_MAX_EMUL_MULTI 16
- u32 rx_mode_cl_mask;
-
+ u8 igu_dsb_id;
+ u8 igu_base_sb;
+ u8 igu_sb_cnt;
dma_addr_t def_status_blk_mapping;
struct bnx2x_slowpath *slowpath;
dma_addr_t slowpath_mapping;
+ struct hw_context context;
+
+ struct bnx2x_ilt *ilt;
+#define BP_ILT(bp) ((bp)->ilt)
+#define ILT_MAX_LINES 128
+
+ int l2_cid_count;
+#define L2_ILT_LINES(bp) (DIV_ROUND_UP((bp)->l2_cid_count, \
+ ILT_PAGE_CIDS))
+#define BNX2X_DB_SIZE(bp) ((bp)->l2_cid_count * (1 << BNX2X_DB_SHIFT))
+
+ int qm_cid_count;
int dropless_fc;
#ifdef BCM_CNIC
u32 cnic_flags;
#define BNX2X_CNIC_FLAG_MAC_SET 1
-
- void *t1;
- dma_addr_t t1_mapping;
void *t2;
dma_addr_t t2_mapping;
- void *timers;
- dma_addr_t timers_mapping;
- void *qm;
- dma_addr_t qm_mapping;
struct cnic_ops *cnic_ops;
void *cnic_data;
u32 cnic_tag;
struct cnic_eth_dev cnic_eth_dev;
- struct host_status_block *cnic_sb;
+ union host_hc_status_block cnic_sb;
dma_addr_t cnic_sb_mapping;
-#define CNIC_SB_ID(bp) BP_L_ID(bp)
+#define CNIC_SB_ID(bp) ((bp)->base_fw_ndsb + BP_L_ID(bp))
+#define CNIC_IGU_SB_ID(bp) ((bp)->igu_base_sb)
struct eth_spe *cnic_kwq;
struct eth_spe *cnic_kwq_prod;
struct eth_spe *cnic_kwq_cons;
@@ -913,32 +1124,196 @@ struct bnx2x {
const struct firmware *firmware;
};
+/**
+ * Init queue/func interface
+ */
+/* queue init flags */
+#define QUEUE_FLG_TPA 0x0001
+#define QUEUE_FLG_CACHE_ALIGN 0x0002
+#define QUEUE_FLG_STATS 0x0004
+#define QUEUE_FLG_OV 0x0008
+#define QUEUE_FLG_VLAN 0x0010
+#define QUEUE_FLG_COS 0x0020
+#define QUEUE_FLG_HC 0x0040
+#define QUEUE_FLG_DHC 0x0080
+#define QUEUE_FLG_OOO 0x0100
+
+#define QUEUE_DROP_IP_CS_ERR TSTORM_ETH_CLIENT_CONFIG_DROP_IP_CS_ERR
+#define QUEUE_DROP_TCP_CS_ERR TSTORM_ETH_CLIENT_CONFIG_DROP_TCP_CS_ERR
+#define QUEUE_DROP_TTL0 TSTORM_ETH_CLIENT_CONFIG_DROP_TTL0
+#define QUEUE_DROP_UDP_CS_ERR TSTORM_ETH_CLIENT_CONFIG_DROP_UDP_CS_ERR
+
+
+
+/* rss capabilities */
+#define RSS_IPV4_CAP 0x0001
+#define RSS_IPV4_TCP_CAP 0x0002
+#define RSS_IPV6_CAP 0x0004
+#define RSS_IPV6_TCP_CAP 0x0008
-#define BNX2X_MAX_QUEUES(bp) (IS_E1HMF(bp) ? (MAX_CONTEXT/E1HVN_MAX) \
- : MAX_CONTEXT)
#define BNX2X_NUM_QUEUES(bp) (bp->num_queues)
#define is_multi(bp) (BNX2X_NUM_QUEUES(bp) > 1)
+#define BNX2X_MAX_QUEUES(bp) (bp->igu_sb_cnt - CNIC_CONTEXT_USE)
+#define is_eth_multi(bp) (BNX2X_NUM_ETH_QUEUES(bp) > 1)
+
+#define RSS_IPV4_CAP_MASK \
+ TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_CAPABILITY
+
+#define RSS_IPV4_TCP_CAP_MASK \
+ TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_TCP_CAPABILITY
+
+#define RSS_IPV6_CAP_MASK \
+ TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_CAPABILITY
+
+#define RSS_IPV6_TCP_CAP_MASK \
+ TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_TCP_CAPABILITY
+
+/* func init flags */
+#define FUNC_FLG_STATS 0x0001
+#define FUNC_FLG_TPA 0x0002
+#define FUNC_FLG_SPQ 0x0004
+#define FUNC_FLG_LEADING 0x0008 /* PF only */
+
+struct rxq_pause_params {
+ u16 bd_th_lo;
+ u16 bd_th_hi;
+ u16 rcq_th_lo;
+ u16 rcq_th_hi;
+ u16 sge_th_lo; /* valid iff QUEUE_FLG_TPA */
+ u16 sge_th_hi; /* valid iff QUEUE_FLG_TPA */
+ u16 pri_map;
+};
+
+struct bnx2x_rxq_init_params {
+ /* cxt*/
+ struct eth_context *cxt;
+
+ /* dma */
+ dma_addr_t dscr_map;
+ dma_addr_t sge_map;
+ dma_addr_t rcq_map;
+ dma_addr_t rcq_np_map;
+
+ u16 flags;
+ u16 drop_flags;
+ u16 mtu;
+ u16 buf_sz;
+ u16 fw_sb_id;
+ u16 cl_id;
+ u16 spcl_id;
+ u16 cl_qzone_id;
+
+ /* valid iff QUEUE_FLG_STATS */
+ u16 stat_id;
+
+ /* valid iff QUEUE_FLG_TPA */
+ u16 tpa_agg_sz;
+ u16 sge_buf_sz;
+ u16 max_sges_pkt;
+
+ /* valid iff QUEUE_FLG_CACHE_ALIGN */
+ u8 cache_line_log;
+
+ u8 sb_cq_index;
+ u32 cid;
+
+ /* desired interrupts per sec. valid iff QUEUE_FLG_HC */
+ u32 hc_rate;
+};
+
+struct bnx2x_txq_init_params {
+ /* cxt*/
+ struct eth_context *cxt;
+
+ /* dma */
+ dma_addr_t dscr_map;
+
+ u16 flags;
+ u16 fw_sb_id;
+ u8 sb_cq_index;
+ u8 cos; /* valid iff QUEUE_FLG_COS */
+ u16 stat_id; /* valid iff QUEUE_FLG_STATS */
+ u16 traffic_type;
+ u32 cid;
+ u16 hc_rate; /* desired interrupts per sec.*/
+ /* valid iff QUEUE_FLG_HC */
+
+};
+
+struct bnx2x_client_ramrod_params {
+ int *pstate;
+ int state;
+ u16 index;
+ u16 cl_id;
+ u32 cid;
+ u8 poll;
+#define CLIENT_IS_LEADING_RSS 0x02
+ u8 flags;
+};
+
+struct bnx2x_client_init_params {
+ struct rxq_pause_params pause;
+ struct bnx2x_rxq_init_params rxq_params;
+ struct bnx2x_txq_init_params txq_params;
+ struct bnx2x_client_ramrod_params ramrod_params;
+};
+
+struct bnx2x_rss_params {
+ int mode;
+ u16 cap;
+ u16 result_mask;
+};
+
+struct bnx2x_func_init_params {
+
+ /* rss */
+ struct bnx2x_rss_params *rss; /* valid iff FUNC_FLG_RSS */
+
+ /* dma */
+ dma_addr_t fw_stat_map; /* valid iff FUNC_FLG_STATS */
+ dma_addr_t spq_map; /* valid iff FUNC_FLG_SPQ */
+
+ u16 func_flgs;
+ u16 func_id; /* abs fid */
+ u16 pf_id;
+ u16 spq_prod; /* valid iff FUNC_FLG_SPQ */
+};
+
#define for_each_queue(bp, var) \
for (var = 0; var < BNX2X_NUM_QUEUES(bp); var++)
#define for_each_nondefault_queue(bp, var) \
for (var = 1; var < BNX2X_NUM_QUEUES(bp); var++)
+#define WAIT_RAMROD_POLL 0x01
+#define WAIT_RAMROD_COMMON 0x02
+int bnx2x_wait_ramrod(struct bnx2x *bp, int state, int idx,
+ int *state_p, int flags);
+
+/* dmae */
void bnx2x_read_dmae(struct bnx2x *bp, u32 src_addr, u32 len32);
void bnx2x_write_dmae(struct bnx2x *bp, dma_addr_t dma_addr, u32 dst_addr,
u32 len32);
+void bnx2x_write_dmae_phys_len(struct bnx2x *bp, dma_addr_t phys_addr,
+ u32 addr, u32 len);
+void bnx2x_post_dmae(struct bnx2x *bp, struct dmae_command *dmae, int idx);
+u32 bnx2x_dmae_opcode_add_comp(u32 opcode, u8 comp_type);
+u32 bnx2x_dmae_opcode_clr_src_reset(u32 opcode);
+u32 bnx2x_dmae_opcode(struct bnx2x *bp, u8 src_type, u8 dst_type,
+ bool with_comp, u8 comp_type);
+
int bnx2x_get_gpio(struct bnx2x *bp, int gpio_num, u8 port);
int bnx2x_set_gpio(struct bnx2x *bp, int gpio_num, u32 mode, u8 port);
int bnx2x_set_gpio_int(struct bnx2x *bp, int gpio_num, u32 mode, u8 port);
-u32 bnx2x_fw_command(struct bnx2x *bp, u32 command);
+u32 bnx2x_fw_command(struct bnx2x *bp, u32 command, u32 param);
void bnx2x_reg_wr_ind(struct bnx2x *bp, u32 addr, u32 val);
-void bnx2x_write_dmae_phys_len(struct bnx2x *bp, dma_addr_t phys_addr,
- u32 addr, u32 len);
+
void bnx2x_calc_fc_adv(struct bnx2x *bp);
int bnx2x_sp_post(struct bnx2x *bp, int command, int cid,
u32 data_hi, u32 data_lo, int common);
void bnx2x_update_coalesce(struct bnx2x *bp);
+int bnx2x_get_link_cfg_idx(struct bnx2x *bp);
static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
int wait)
@@ -957,6 +1332,40 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
return val;
}
+#define BNX2X_ILT_ZALLOC(x, y, size) \
+ do { \
+ x = pci_alloc_consistent(bp->pdev, size, y); \
+ if (x) \
+ memset(x, 0, size); \
+ } while (0)
+
+#define BNX2X_ILT_FREE(x, y, size) \
+ do { \
+ if (x) { \
+ pci_free_consistent(bp->pdev, size, x, y); \
+ x = NULL; \
+ y = 0; \
+ } \
+ } while (0)
+
+#define ILOG2(x) (ilog2((x)))
+
+#define ILT_NUM_PAGE_ENTRIES (3072)
+/* In 57710/11 we use whole table since we have 8 func
+ * In 57712 we have only 4 func, but use same size per func, then only half of
+ * the table in use
+ */
+#define ILT_PER_FUNC (ILT_NUM_PAGE_ENTRIES/8)
+
+#define FUNC_ILT_BASE(func) (func * ILT_PER_FUNC)
+/*
+ * the phys address is shifted right 12 bits and has an added
+ * 1=valid bit added to the 53rd bit
+ * then since this is a wide register(TM)
+ * we split it into two 32 bit writes
+ */
+#define ONCHIP_ADDR1(x) ((u32)(((u64)x >> 12) & 0xFFFFFFFF))
+#define ONCHIP_ADDR2(x) ((u32)((1 << 20) | ((u64)x >> 44)))
/* load/unload mode */
#define LOAD_NORMAL 0
@@ -964,18 +1373,44 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
#define LOAD_DIAG 2
#define UNLOAD_NORMAL 0
#define UNLOAD_CLOSE 1
-#define UNLOAD_RECOVERY 2
+#define UNLOAD_RECOVERY 2
/* DMAE command defines */
-#define DMAE_CMD_SRC_PCI 0
-#define DMAE_CMD_SRC_GRC DMAE_COMMAND_SRC
+#define DMAE_TIMEOUT -1
+#define DMAE_PCI_ERROR -2 /* E2 and onward */
+#define DMAE_NOT_RDY -3
+#define DMAE_PCI_ERR_FLAG 0x80000000
+
+#define DMAE_SRC_PCI 0
+#define DMAE_SRC_GRC 1
+
+#define DMAE_DST_NONE 0
+#define DMAE_DST_PCI 1
+#define DMAE_DST_GRC 2
+
+#define DMAE_COMP_PCI 0
+#define DMAE_COMP_GRC 1
+
+/* E2 and onward - PCI error handling in the completion */
-#define DMAE_CMD_DST_PCI (1 << DMAE_COMMAND_DST_SHIFT)
-#define DMAE_CMD_DST_GRC (2 << DMAE_COMMAND_DST_SHIFT)
+#define DMAE_COMP_REGULAR 0
+#define DMAE_COM_SET_ERR 1
-#define DMAE_CMD_C_DST_PCI 0
-#define DMAE_CMD_C_DST_GRC (1 << DMAE_COMMAND_C_DST_SHIFT)
+#define DMAE_CMD_SRC_PCI (DMAE_SRC_PCI << \
+ DMAE_COMMAND_SRC_SHIFT)
+#define DMAE_CMD_SRC_GRC (DMAE_SRC_GRC << \
+ DMAE_COMMAND_SRC_SHIFT)
+
+#define DMAE_CMD_DST_PCI (DMAE_DST_PCI << \
+ DMAE_COMMAND_DST_SHIFT)
+#define DMAE_CMD_DST_GRC (DMAE_DST_GRC << \
+ DMAE_COMMAND_DST_SHIFT)
+
+#define DMAE_CMD_C_DST_PCI (DMAE_COMP_PCI << \
+ DMAE_COMMAND_C_DST_SHIFT)
+#define DMAE_CMD_C_DST_GRC (DMAE_COMP_GRC << \
+ DMAE_COMMAND_C_DST_SHIFT)
#define DMAE_CMD_C_ENABLE DMAE_COMMAND_C_TYPE_ENABLE
@@ -991,10 +1426,20 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
#define DMAE_CMD_DST_RESET DMAE_COMMAND_DST_RESET
#define DMAE_CMD_E1HVN_SHIFT DMAE_COMMAND_E1HVN_SHIFT
+#define DMAE_SRC_PF 0
+#define DMAE_SRC_VF 1
+
+#define DMAE_DST_PF 0
+#define DMAE_DST_VF 1
+
+#define DMAE_C_SRC 0
+#define DMAE_C_DST 1
+
#define DMAE_LEN32_RD_MAX 0x80
#define DMAE_LEN32_WR_MAX(bp) (CHIP_IS_E1(bp) ? 0x400 : 0x2000)
-#define DMAE_COMP_VAL 0xe0d0d0ae
+#define DMAE_COMP_VAL 0x60d0d0ae /* E2 and on - upper bit
+ indicates eror */
#define MAX_DMAE_C_PER_PORT 8
#define INIT_DMAE_C(bp) (BP_PORT(bp) * MAX_DMAE_C_PER_PORT + \
@@ -1002,7 +1447,6 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
#define PMF_DMAE_C(bp) (BP_PORT(bp) * MAX_DMAE_C_PER_PORT + \
E1HVN_MAX)
-
/* PCIE link and speed */
#define PCICFG_LINK_WIDTH 0x1f00000
#define PCICFG_LINK_WIDTH_SHIFT 20
@@ -1031,7 +1475,7 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
#define MAX_SP_DESC_CNT (SP_DESC_CNT - 1)
-#define BNX2X_BTR 1
+#define BNX2X_BTR 4
#define MAX_SPQ_PENDING 8
@@ -1148,20 +1592,26 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_MODE_SHIFT))
#define MULTI_MASK 0x7f
+#define BNX2X_SP_DSB_INDEX \
+ (&bp->def_status_blk->sp_sb.\
+ index_values[HC_SP_INDEX_ETH_DEF_CONS])
-#define DEF_USB_FUNC_OFF (2 + 2*HC_USTORM_DEF_SB_NUM_INDICES)
-#define DEF_CSB_FUNC_OFF (2 + 2*HC_CSTORM_DEF_SB_NUM_INDICES)
-#define DEF_XSB_FUNC_OFF (2 + 2*HC_XSTORM_DEF_SB_NUM_INDICES)
-#define DEF_TSB_FUNC_OFF (2 + 2*HC_TSTORM_DEF_SB_NUM_INDICES)
+#define SET_FLAG(value, mask, flag) \
+ do {\
+ (value) &= ~(mask);\
+ (value) |= ((flag) << (mask##_SHIFT));\
+ } while (0)
-#define C_DEF_SB_SP_INDEX HC_INDEX_DEF_C_ETH_SLOW_PATH
-
-#define BNX2X_SP_DSB_INDEX \
-(&bp->def_status_blk->c_def_status_block.index_values[C_DEF_SB_SP_INDEX])
+#define GET_FLAG(value, mask) \
+ (((value) &= (mask)) >> (mask##_SHIFT))
+#define GET_FIELD(value, fname) \
+ (((value) & (fname##_MASK)) >> (fname##_SHIFT))
#define CAM_IS_INVALID(x) \
-(x.target_table_entry.flags == TSTORM_CAM_TARGET_TABLE_ENTRY_ACTION_TYPE)
+ (GET_FLAG(x.flags, \
+ MAC_CONFIGURATION_ENTRY_ACTION_TYPE) == \
+ (T_ETH_MAC_COMMAND_INVALIDATE))
#define CAM_INVALIDATE(x) \
(x.target_table_entry.flags = TSTORM_CAM_TARGET_TABLE_ENTRY_ACTION_TYPE)
@@ -1177,21 +1627,29 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
#define PXP2_REG_PXP2_INT_STS PXP2_REG_PXP2_INT_STS_0
#endif
+#ifndef ETH_MAX_RX_CLIENTS_E2
+#define ETH_MAX_RX_CLIENTS_E2 ETH_MAX_RX_CLIENTS_E1H
+#endif
+
#define BNX2X_VPD_LEN 128
#define VENDOR_ID_LEN 4
+/* Congestion management fairness mode */
+#define CMNG_FNS_NONE 0
+#define CMNG_FNS_MINMAX 1
+
+#define HC_SEG_ACCESS_DEF 0 /*Driver decision 0-3*/
+#define HC_SEG_ACCESS_ATTN 4
+#define HC_SEG_ACCESS_NORM 0 /*Driver decision 0-1*/
+
#ifdef BNX2X_MAIN
#define BNX2X_EXTERN
#else
#define BNX2X_EXTERN extern
#endif
-BNX2X_EXTERN int load_count[3]; /* 0-common, 1-port0, 2-port1 */
-
-/* MISC_REG_RESET_REG - this is here for the hsi to work don't touch */
+BNX2X_EXTERN int load_count[2][3]; /* per path: 0-common, 1-port0, 2-port1 */
extern void bnx2x_set_ethtool_ops(struct net_device *netdev);
-void bnx2x_post_dmae(struct bnx2x *bp, struct dmae_command *dmae, int idx);
-
#endif /* bnx2x.h */
diff --git a/drivers/net/bnx2x/bnx2x_cmn.c b/drivers/net/bnx2x/bnx2x_cmn.c
index 02bf710629a3..bc5837514074 100644
--- a/drivers/net/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/bnx2x/bnx2x_cmn.c
@@ -15,18 +15,16 @@
*
*/
-
#include <linux/etherdevice.h>
+#include <linux/if_vlan.h>
#include <linux/ip.h>
-#include <linux/ipv6.h>
+#include <net/ipv6.h>
#include <net/ip6_checksum.h>
+#include <linux/firmware.h>
#include "bnx2x_cmn.h"
-#ifdef BCM_VLAN
-#include <linux/if_vlan.h>
-#endif
+#include "bnx2x_init.h"
-static int bnx2x_poll(struct napi_struct *napi, int budget);
/* free skb in the packet ring at pos idx
* return idx of last bd freed
@@ -51,7 +49,7 @@ static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fastpath *fp,
DP(BNX2X_MSG_OFF, "free bd_idx %d\n", bd_idx);
tx_start_bd = &fp->tx_desc_ring[bd_idx].start_bd;
dma_unmap_single(&bp->pdev->dev, BD_UNMAP_ADDR(tx_start_bd),
- BD_UNMAP_LEN(tx_start_bd), PCI_DMA_TODEVICE);
+ BD_UNMAP_LEN(tx_start_bd), DMA_TO_DEVICE);
nbd = le16_to_cpu(tx_start_bd->nbd) - 1;
#ifdef BNX2X_STOP_ON_ERROR
@@ -115,16 +113,10 @@ int bnx2x_tx_int(struct bnx2x_fastpath *fp)
pkt_cons = TX_BD(sw_cons);
- /* prefetch(bp->tx_buf_ring[pkt_cons].skb); */
-
- DP(NETIF_MSG_TX_DONE, "hw_cons %u sw_cons %u pkt_cons %u\n",
- hw_cons, sw_cons, pkt_cons);
+ DP(NETIF_MSG_TX_DONE, "queue[%d]: hw_cons %u sw_cons %u "
+ " pkt_cons %u\n",
+ fp->index, hw_cons, sw_cons, pkt_cons);
-/* if (NEXT_TX_IDX(sw_cons) != hw_cons) {
- rmb();
- prefetch(fp->tx_buf_ring[NEXT_TX_IDX(sw_cons)].skb);
- }
-*/
bd_cons = bnx2x_free_tx_pkt(bp, fp, pkt_cons);
sw_cons++;
}
@@ -140,7 +132,6 @@ int bnx2x_tx_int(struct bnx2x_fastpath *fp)
*/
smp_mb();
- /* TBD need a thresh? */
if (unlikely(netif_tx_queue_stopped(txq))) {
/* Taking tx_lock() is needed to prevent reenabling the queue
* while it's empty. This could have happen if rx_action() gets
@@ -189,14 +180,16 @@ static void bnx2x_update_sge_prod(struct bnx2x_fastpath *fp,
/* First mark all used pages */
for (i = 0; i < sge_len; i++)
- SGE_MASK_CLEAR_BIT(fp, RX_SGE(le16_to_cpu(fp_cqe->sgl[i])));
+ SGE_MASK_CLEAR_BIT(fp,
+ RX_SGE(le16_to_cpu(fp_cqe->sgl_or_raw_data.sgl[i])));
DP(NETIF_MSG_RX_STATUS, "fp_cqe->sgl[%d] = %d\n",
- sge_len - 1, le16_to_cpu(fp_cqe->sgl[sge_len - 1]));
+ sge_len - 1, le16_to_cpu(fp_cqe->sgl_or_raw_data.sgl[sge_len - 1]));
/* Here we assume that the last SGE index is the biggest */
prefetch((void *)(fp->sge_mask));
- bnx2x_update_last_max_sge(fp, le16_to_cpu(fp_cqe->sgl[sge_len - 1]));
+ bnx2x_update_last_max_sge(fp,
+ le16_to_cpu(fp_cqe->sgl_or_raw_data.sgl[sge_len - 1]));
last_max = RX_SGE(fp->last_max_sge);
last_elem = last_max >> RX_SGE_MASK_ELEM_SHIFT;
@@ -297,7 +290,8 @@ static int bnx2x_fill_frag_skb(struct bnx2x *bp, struct bnx2x_fastpath *fp,
/* Run through the SGL and compose the fragmented skb */
for (i = 0, j = 0; i < pages; i += PAGES_PER_SGE, j++) {
- u16 sge_idx = RX_SGE(le16_to_cpu(fp_cqe->sgl[j]));
+ u16 sge_idx =
+ RX_SGE(le16_to_cpu(fp_cqe->sgl_or_raw_data.sgl[j]));
/* FW gives the indices of the SGE as if the ring is an array
(meaning that "next" element will consume 2 indices) */
@@ -349,16 +343,9 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
if (likely(new_skb)) {
/* fix ip xsum and give it to the stack */
/* (no need to map the new skb) */
-#ifdef BCM_VLAN
- int is_vlan_cqe =
- (le16_to_cpu(cqe->fast_path_cqe.pars_flags.flags) &
- PARSING_FLAGS_VLAN);
- int is_not_hwaccel_vlan_cqe =
- (is_vlan_cqe && (!(bp->flags & HW_VLAN_RX_FLAG)));
-#endif
prefetch(skb);
- prefetch(((char *)(skb)) + 128);
+ prefetch(((char *)(skb)) + L1_CACHE_BYTES);
#ifdef BNX2X_STOP_ON_ERROR
if (pad + len > bp->rx_buf_size) {
@@ -380,27 +367,18 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
struct iphdr *iph;
iph = (struct iphdr *)skb->data;
-#ifdef BCM_VLAN
- /* If there is no Rx VLAN offloading -
- take VLAN tag into an account */
- if (unlikely(is_not_hwaccel_vlan_cqe))
- iph = (struct iphdr *)((u8 *)iph + VLAN_HLEN);
-#endif
iph->check = 0;
iph->check = ip_fast_csum((u8 *)iph, iph->ihl);
}
if (!bnx2x_fill_frag_skb(bp, fp, skb,
&cqe->fast_path_cqe, cqe_idx)) {
-#ifdef BCM_VLAN
- if ((bp->vlgrp != NULL) && is_vlan_cqe &&
- (!is_not_hwaccel_vlan_cqe))
- vlan_gro_receive(&fp->napi, bp->vlgrp,
+ if ((le16_to_cpu(cqe->fast_path_cqe.
+ pars_flags.flags) & PARSING_FLAGS_VLAN))
+ __vlan_hwaccel_put_tag(skb,
le16_to_cpu(cqe->fast_path_cqe.
- vlan_tag), skb);
- else
-#endif
- napi_gro_receive(&fp->napi, skb);
+ vlan_tag));
+ napi_gro_receive(&fp->napi, skb);
} else {
DP(NETIF_MSG_RX_STATUS, "Failed to allocate new pages"
" - dropping packet!\n");
@@ -509,8 +487,11 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
len = le16_to_cpu(cqe->fast_path_cqe.pkt_len);
pad = cqe->fast_path_cqe.placement_offset;
- /* If CQE is marked both TPA_START and TPA_END
- it is a non-TPA CQE */
+ /* - If CQE is marked both TPA_START and TPA_END it is
+ * a non-TPA CQE.
+ * - FP CQE will always have either TPA_START or/and
+ * TPA_STOP flags set.
+ */
if ((!fp->disable_tpa) &&
(TPA_TYPE(cqe_fp_flags) !=
(TPA_TYPE_START | TPA_TYPE_END))) {
@@ -528,9 +509,7 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
bnx2x_set_skb_rxhash(bp, cqe, skb);
goto next_rx;
- }
-
- if (TPA_TYPE(cqe_fp_flags) == TPA_TYPE_END) {
+ } else { /* TPA_STOP */
DP(NETIF_MSG_RX_STATUS,
"calling tpa_stop on queue %d\n",
queue);
@@ -560,7 +539,7 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
dma_unmap_addr(rx_buf, mapping),
pad + RX_COPY_THRESH,
DMA_FROM_DEVICE);
- prefetch(((char *)(skb)) + 128);
+ prefetch(((char *)(skb)) + L1_CACHE_BYTES);
/* is this an error packet? */
if (unlikely(cqe_fp_flags & ETH_RX_ERROR_FALGS)) {
@@ -594,7 +573,7 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
skb_reserve(new_skb, pad);
skb_put(new_skb, len);
- bnx2x_reuse_rx_skb(fp, skb, bd_cons, bd_prod);
+ bnx2x_reuse_rx_skb(fp, bd_cons, bd_prod);
skb = new_skb;
@@ -613,7 +592,7 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
"of alloc failure\n");
fp->eth_q_stats.rx_skb_alloc_failed++;
reuse_rx:
- bnx2x_reuse_rx_skb(fp, skb, bd_cons, bd_prod);
+ bnx2x_reuse_rx_skb(fp, bd_cons, bd_prod);
goto next_rx;
}
@@ -622,7 +601,8 @@ reuse_rx:
/* Set Toeplitz hash for a none-LRO skb */
bnx2x_set_skb_rxhash(bp, cqe, skb);
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
+
if (bp->rx_csum) {
if (likely(BNX2X_RX_CSUM_OK(cqe)))
skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -633,15 +613,11 @@ reuse_rx:
skb_record_rx_queue(skb, fp->index);
-#ifdef BCM_VLAN
- if ((bp->vlgrp != NULL) && (bp->flags & HW_VLAN_RX_FLAG) &&
- (le16_to_cpu(cqe->fast_path_cqe.pars_flags.flags) &
- PARSING_FLAGS_VLAN))
- vlan_gro_receive(&fp->napi, bp->vlgrp,
- le16_to_cpu(cqe->fast_path_cqe.vlan_tag), skb);
- else
-#endif
- napi_gro_receive(&fp->napi, skb);
+ if (le16_to_cpu(cqe->fast_path_cqe.pars_flags.flags) &
+ PARSING_FLAGS_VLAN)
+ __vlan_hwaccel_put_tag(skb,
+ le16_to_cpu(cqe->fast_path_cqe.vlan_tag));
+ napi_gro_receive(&fp->napi, skb);
next_rx:
@@ -685,9 +661,10 @@ static irqreturn_t bnx2x_msix_fp_int(int irq, void *fp_cookie)
return IRQ_HANDLED;
}
- DP(BNX2X_MSG_FP, "got an MSI-X interrupt on IDX:SB [%d:%d]\n",
- fp->index, fp->sb_id);
- bnx2x_ack_sb(bp, fp->sb_id, USTORM_ID, 0, IGU_INT_DISABLE, 0);
+ DP(BNX2X_MSG_FP, "got an MSI-X interrupt on IDX:SB "
+ "[fp %d fw_sd %d igusb %d]\n",
+ fp->index, fp->fw_sb_id, fp->igu_sb_id);
+ bnx2x_ack_sb(bp, fp->igu_sb_id, USTORM_ID, 0, IGU_INT_DISABLE, 0);
#ifdef BNX2X_STOP_ON_ERROR
if (unlikely(bp->panic))
@@ -697,14 +674,12 @@ static irqreturn_t bnx2x_msix_fp_int(int irq, void *fp_cookie)
/* Handle Rx and Tx according to MSI-X vector */
prefetch(fp->rx_cons_sb);
prefetch(fp->tx_cons_sb);
- prefetch(&fp->status_blk->u_status_block.status_block_index);
- prefetch(&fp->status_blk->c_status_block.status_block_index);
+ prefetch(&fp->sb_running_index[SM_RX_ID]);
napi_schedule(&bnx2x_fp(bp, fp->index, napi));
return IRQ_HANDLED;
}
-
/* HW Lock for shared dual port PHYs */
void bnx2x_acquire_phy_lock(struct bnx2x *bp)
{
@@ -738,12 +713,13 @@ void bnx2x_link_report(struct bnx2x *bp)
netdev_info(bp->dev, "NIC Link is Up, ");
line_speed = bp->link_vars.line_speed;
- if (IS_E1HMF(bp)) {
+ if (IS_MF(bp)) {
u16 vn_max_rate;
vn_max_rate =
- ((bp->mf_config & FUNC_MF_CFG_MAX_BW_MASK) >>
- FUNC_MF_CFG_MAX_BW_SHIFT) * 100;
+ ((bp->mf_config[BP_VN(bp)] &
+ FUNC_MF_CFG_MAX_BW_MASK) >>
+ FUNC_MF_CFG_MAX_BW_SHIFT) * 100;
if (vn_max_rate < line_speed)
line_speed = vn_max_rate;
}
@@ -773,23 +749,73 @@ void bnx2x_link_report(struct bnx2x *bp)
}
}
+/* Returns the number of actually allocated BDs */
+static inline int bnx2x_alloc_rx_bds(struct bnx2x_fastpath *fp,
+ int rx_ring_size)
+{
+ struct bnx2x *bp = fp->bp;
+ u16 ring_prod, cqe_ring_prod;
+ int i;
+
+ fp->rx_comp_cons = 0;
+ cqe_ring_prod = ring_prod = 0;
+ for (i = 0; i < rx_ring_size; i++) {
+ if (bnx2x_alloc_rx_skb(bp, fp, ring_prod) < 0) {
+ BNX2X_ERR("was only able to allocate "
+ "%d rx skbs on queue[%d]\n", i, fp->index);
+ fp->eth_q_stats.rx_skb_alloc_failed++;
+ break;
+ }
+ ring_prod = NEXT_RX_IDX(ring_prod);
+ cqe_ring_prod = NEXT_RCQ_IDX(cqe_ring_prod);
+ WARN_ON(ring_prod <= i);
+ }
+
+ fp->rx_bd_prod = ring_prod;
+ /* Limit the CQE producer by the CQE ring size */
+ fp->rx_comp_prod = min_t(u16, NUM_RCQ_RINGS*RCQ_DESC_CNT,
+ cqe_ring_prod);
+ fp->rx_pkt = fp->rx_calls = 0;
+
+ return i;
+}
+
+static inline void bnx2x_alloc_rx_bd_ring(struct bnx2x_fastpath *fp)
+{
+ struct bnx2x *bp = fp->bp;
+ int rx_ring_size = bp->rx_ring_size ? bp->rx_ring_size :
+ MAX_RX_AVAIL/bp->num_queues;
+
+ rx_ring_size = max_t(int, MIN_RX_AVAIL, rx_ring_size);
+
+ bnx2x_alloc_rx_bds(fp, rx_ring_size);
+
+ /* Warning!
+ * this will generate an interrupt (to the TSTORM)
+ * must only be done after chip is initialized
+ */
+ bnx2x_update_rx_prod(bp, fp, fp->rx_bd_prod, fp->rx_comp_prod,
+ fp->rx_sge_prod);
+}
+
void bnx2x_init_rx_rings(struct bnx2x *bp)
{
int func = BP_FUNC(bp);
int max_agg_queues = CHIP_IS_E1(bp) ? ETH_MAX_AGGREGATION_QUEUES_E1 :
ETH_MAX_AGGREGATION_QUEUES_E1H;
- u16 ring_prod, cqe_ring_prod;
+ u16 ring_prod;
int i, j;
- bp->rx_buf_size = bp->dev->mtu + ETH_OVREHEAD + BNX2X_RX_ALIGN;
+ bp->rx_buf_size = bp->dev->mtu + ETH_OVREHEAD + BNX2X_RX_ALIGN +
+ IP_HEADER_ALIGNMENT_PADDING;
+
DP(NETIF_MSG_IFUP,
"mtu %d rx_buf_size %d\n", bp->dev->mtu, bp->rx_buf_size);
- if (bp->flags & TPA_ENABLE_FLAG) {
-
- for_each_queue(bp, j) {
- struct bnx2x_fastpath *fp = &bp->fp[j];
+ for_each_queue(bp, j) {
+ struct bnx2x_fastpath *fp = &bp->fp[j];
+ if (!fp->disable_tpa) {
for (i = 0; i < max_agg_queues; i++) {
fp->tpa_pool[i].skb =
netdev_alloc_skb(bp->dev, bp->rx_buf_size);
@@ -807,6 +833,35 @@ void bnx2x_init_rx_rings(struct bnx2x *bp)
mapping, 0);
fp->tpa_state[i] = BNX2X_TPA_STOP;
}
+
+ /* "next page" elements initialization */
+ bnx2x_set_next_page_sgl(fp);
+
+ /* set SGEs bit mask */
+ bnx2x_init_sge_ring_bit_mask(fp);
+
+ /* Allocate SGEs and initialize the ring elements */
+ for (i = 0, ring_prod = 0;
+ i < MAX_RX_SGE_CNT*NUM_RX_SGE_PAGES; i++) {
+
+ if (bnx2x_alloc_rx_sge(bp, fp, ring_prod) < 0) {
+ BNX2X_ERR("was only able to allocate "
+ "%d rx sges\n", i);
+ BNX2X_ERR("disabling TPA for"
+ " queue[%d]\n", j);
+ /* Cleanup already allocated elements */
+ bnx2x_free_rx_sge_range(bp,
+ fp, ring_prod);
+ bnx2x_free_tpa_pool(bp,
+ fp, max_agg_queues);
+ fp->disable_tpa = 1;
+ ring_prod = 0;
+ break;
+ }
+ ring_prod = NEXT_SGE_IDX(ring_prod);
+ }
+
+ fp->rx_sge_prod = ring_prod;
}
}
@@ -814,109 +869,29 @@ void bnx2x_init_rx_rings(struct bnx2x *bp)
struct bnx2x_fastpath *fp = &bp->fp[j];
fp->rx_bd_cons = 0;
- fp->rx_cons_sb = BNX2X_RX_SB_INDEX;
- fp->rx_bd_cons_sb = BNX2X_RX_SB_BD_INDEX;
-
- /* "next page" elements initialization */
- /* SGE ring */
- for (i = 1; i <= NUM_RX_SGE_PAGES; i++) {
- struct eth_rx_sge *sge;
-
- sge = &fp->rx_sge_ring[RX_SGE_CNT * i - 2];
- sge->addr_hi =
- cpu_to_le32(U64_HI(fp->rx_sge_mapping +
- BCM_PAGE_SIZE*(i % NUM_RX_SGE_PAGES)));
- sge->addr_lo =
- cpu_to_le32(U64_LO(fp->rx_sge_mapping +
- BCM_PAGE_SIZE*(i % NUM_RX_SGE_PAGES)));
- }
-
- bnx2x_init_sge_ring_bit_mask(fp);
- /* RX BD ring */
- for (i = 1; i <= NUM_RX_RINGS; i++) {
- struct eth_rx_bd *rx_bd;
-
- rx_bd = &fp->rx_desc_ring[RX_DESC_CNT * i - 2];
- rx_bd->addr_hi =
- cpu_to_le32(U64_HI(fp->rx_desc_mapping +
- BCM_PAGE_SIZE*(i % NUM_RX_RINGS)));
- rx_bd->addr_lo =
- cpu_to_le32(U64_LO(fp->rx_desc_mapping +
- BCM_PAGE_SIZE*(i % NUM_RX_RINGS)));
- }
+ bnx2x_set_next_page_rx_bd(fp);
/* CQ ring */
- for (i = 1; i <= NUM_RCQ_RINGS; i++) {
- struct eth_rx_cqe_next_page *nextpg;
-
- nextpg = (struct eth_rx_cqe_next_page *)
- &fp->rx_comp_ring[RCQ_DESC_CNT * i - 1];
- nextpg->addr_hi =
- cpu_to_le32(U64_HI(fp->rx_comp_mapping +
- BCM_PAGE_SIZE*(i % NUM_RCQ_RINGS)));
- nextpg->addr_lo =
- cpu_to_le32(U64_LO(fp->rx_comp_mapping +
- BCM_PAGE_SIZE*(i % NUM_RCQ_RINGS)));
- }
-
- /* Allocate SGEs and initialize the ring elements */
- for (i = 0, ring_prod = 0;
- i < MAX_RX_SGE_CNT*NUM_RX_SGE_PAGES; i++) {
-
- if (bnx2x_alloc_rx_sge(bp, fp, ring_prod) < 0) {
- BNX2X_ERR("was only able to allocate "
- "%d rx sges\n", i);
- BNX2X_ERR("disabling TPA for queue[%d]\n", j);
- /* Cleanup already allocated elements */
- bnx2x_free_rx_sge_range(bp, fp, ring_prod);
- bnx2x_free_tpa_pool(bp, fp, max_agg_queues);
- fp->disable_tpa = 1;
- ring_prod = 0;
- break;
- }
- ring_prod = NEXT_SGE_IDX(ring_prod);
- }
- fp->rx_sge_prod = ring_prod;
+ bnx2x_set_next_page_rx_cq(fp);
/* Allocate BDs and initialize BD ring */
- fp->rx_comp_cons = 0;
- cqe_ring_prod = ring_prod = 0;
- for (i = 0; i < bp->rx_ring_size; i++) {
- if (bnx2x_alloc_rx_skb(bp, fp, ring_prod) < 0) {
- BNX2X_ERR("was only able to allocate "
- "%d rx skbs on queue[%d]\n", i, j);
- fp->eth_q_stats.rx_skb_alloc_failed++;
- break;
- }
- ring_prod = NEXT_RX_IDX(ring_prod);
- cqe_ring_prod = NEXT_RCQ_IDX(cqe_ring_prod);
- WARN_ON(ring_prod <= i);
- }
+ bnx2x_alloc_rx_bd_ring(fp);
- fp->rx_bd_prod = ring_prod;
- /* must not have more available CQEs than BDs */
- fp->rx_comp_prod = min_t(u16, NUM_RCQ_RINGS*RCQ_DESC_CNT,
- cqe_ring_prod);
- fp->rx_pkt = fp->rx_calls = 0;
-
- /* Warning!
- * this will generate an interrupt (to the TSTORM)
- * must only be done after chip is initialized
- */
- bnx2x_update_rx_prod(bp, fp, ring_prod, fp->rx_comp_prod,
- fp->rx_sge_prod);
if (j != 0)
continue;
- REG_WR(bp, BAR_USTRORM_INTMEM +
- USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(func),
- U64_LO(fp->rx_comp_mapping));
- REG_WR(bp, BAR_USTRORM_INTMEM +
- USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(func) + 4,
- U64_HI(fp->rx_comp_mapping));
+ if (!CHIP_IS_E2(bp)) {
+ REG_WR(bp, BAR_USTRORM_INTMEM +
+ USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(func),
+ U64_LO(fp->rx_comp_mapping));
+ REG_WR(bp, BAR_USTRORM_INTMEM +
+ USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(func) + 4,
+ U64_HI(fp->rx_comp_mapping));
+ }
}
}
+
static void bnx2x_free_tx_skbs(struct bnx2x *bp)
{
int i;
@@ -989,55 +964,49 @@ static void bnx2x_free_msix_irqs(struct bnx2x *bp)
}
}
-void bnx2x_free_irq(struct bnx2x *bp, bool disable_only)
+void bnx2x_free_irq(struct bnx2x *bp)
{
- if (bp->flags & USING_MSIX_FLAG) {
- if (!disable_only)
- bnx2x_free_msix_irqs(bp);
- pci_disable_msix(bp->pdev);
- bp->flags &= ~USING_MSIX_FLAG;
-
- } else if (bp->flags & USING_MSI_FLAG) {
- if (!disable_only)
- free_irq(bp->pdev->irq, bp->dev);
- pci_disable_msi(bp->pdev);
- bp->flags &= ~USING_MSI_FLAG;
-
- } else if (!disable_only)
+ if (bp->flags & USING_MSIX_FLAG)
+ bnx2x_free_msix_irqs(bp);
+ else if (bp->flags & USING_MSI_FLAG)
+ free_irq(bp->pdev->irq, bp->dev);
+ else
free_irq(bp->pdev->irq, bp->dev);
}
-static int bnx2x_enable_msix(struct bnx2x *bp)
+int bnx2x_enable_msix(struct bnx2x *bp)
{
- int i, rc, offset = 1;
- int igu_vec = 0;
+ int msix_vec = 0, i, rc, req_cnt;
- bp->msix_table[0].entry = igu_vec;
- DP(NETIF_MSG_IFUP, "msix_table[0].entry = %d (slowpath)\n", igu_vec);
+ bp->msix_table[msix_vec].entry = msix_vec;
+ DP(NETIF_MSG_IFUP, "msix_table[0].entry = %d (slowpath)\n",
+ bp->msix_table[0].entry);
+ msix_vec++;
#ifdef BCM_CNIC
- igu_vec = BP_L_ID(bp) + offset;
- bp->msix_table[1].entry = igu_vec;
- DP(NETIF_MSG_IFUP, "msix_table[1].entry = %d (CNIC)\n", igu_vec);
- offset++;
+ bp->msix_table[msix_vec].entry = msix_vec;
+ DP(NETIF_MSG_IFUP, "msix_table[%d].entry = %d (CNIC)\n",
+ bp->msix_table[msix_vec].entry, bp->msix_table[msix_vec].entry);
+ msix_vec++;
#endif
for_each_queue(bp, i) {
- igu_vec = BP_L_ID(bp) + offset + i;
- bp->msix_table[i + offset].entry = igu_vec;
+ bp->msix_table[msix_vec].entry = msix_vec;
DP(NETIF_MSG_IFUP, "msix_table[%d].entry = %d "
- "(fastpath #%u)\n", i + offset, igu_vec, i);
+ "(fastpath #%u)\n", msix_vec, msix_vec, i);
+ msix_vec++;
}
- rc = pci_enable_msix(bp->pdev, &bp->msix_table[0],
- BNX2X_NUM_QUEUES(bp) + offset);
+ req_cnt = BNX2X_NUM_QUEUES(bp) + CNIC_CONTEXT_USE + 1;
+
+ rc = pci_enable_msix(bp->pdev, &bp->msix_table[0], req_cnt);
/*
* reconfigure number of tx/rx queues according to available
* MSI-X vectors
*/
if (rc >= BNX2X_MIN_MSIX_VEC_CNT) {
- /* vectors available for FP */
- int fp_vec = rc - BNX2X_MSIX_VEC_FP_START;
+ /* how less vectors we will have? */
+ int diff = req_cnt - rc;
DP(NETIF_MSG_IFUP,
"Trying to use less MSI-X vectors: %d\n", rc);
@@ -1049,12 +1018,17 @@ static int bnx2x_enable_msix(struct bnx2x *bp)
"MSI-X is not attainable rc %d\n", rc);
return rc;
}
-
- bp->num_queues = min(bp->num_queues, fp_vec);
+ /*
+ * decrease number of queues by number of unallocated entries
+ */
+ bp->num_queues -= diff;
DP(NETIF_MSG_IFUP, "New queue configuration set: %d\n",
bp->num_queues);
} else if (rc) {
+ /* fall to INTx if not enough memory */
+ if (rc == -ENOMEM)
+ bp->flags |= DISABLE_MSI_FLAG;
DP(NETIF_MSG_IFUP, "MSI-X is not attainable rc %d\n", rc);
return rc;
}
@@ -1083,7 +1057,7 @@ static int bnx2x_req_msix_irqs(struct bnx2x *bp)
snprintf(fp->name, sizeof(fp->name), "%s-fp-%d",
bp->dev->name, i);
- rc = request_irq(bp->msix_table[i + offset].vector,
+ rc = request_irq(bp->msix_table[offset].vector,
bnx2x_msix_fp_int, 0, fp->name, fp);
if (rc) {
BNX2X_ERR("request fp #%d irq failed rc %d\n", i, rc);
@@ -1091,10 +1065,12 @@ static int bnx2x_req_msix_irqs(struct bnx2x *bp)
return -EBUSY;
}
+ offset++;
fp->state = BNX2X_FP_STATE_IRQ;
}
i = BNX2X_NUM_QUEUES(bp);
+ offset = 1 + CNIC_CONTEXT_USE;
netdev_info(bp->dev, "using MSI-X IRQs: sp %d fp[%d] %d"
" ... fp[%d] %d\n",
bp->msix_table[0].vector,
@@ -1104,7 +1080,7 @@ static int bnx2x_req_msix_irqs(struct bnx2x *bp)
return 0;
}
-static int bnx2x_enable_msi(struct bnx2x *bp)
+int bnx2x_enable_msi(struct bnx2x *bp)
{
int rc;
@@ -1175,35 +1151,29 @@ void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw)
bnx2x_napi_disable(bp);
netif_tx_disable(bp->dev);
}
-static int bnx2x_set_num_queues(struct bnx2x *bp)
-{
- int rc = 0;
- switch (bp->int_mode) {
- case INT_MODE_INTx:
- case INT_MODE_MSI:
+void bnx2x_set_num_queues(struct bnx2x *bp)
+{
+ switch (bp->multi_mode) {
+ case ETH_RSS_MODE_DISABLED:
bp->num_queues = 1;
- DP(NETIF_MSG_IFUP, "set number of queues to 1\n");
break;
- default:
- /* Set number of queues according to bp->multi_mode value */
- bnx2x_set_num_queues_msix(bp);
-
- DP(NETIF_MSG_IFUP, "set number of queues to %d\n",
- bp->num_queues);
+ case ETH_RSS_MODE_REGULAR:
+ bp->num_queues = bnx2x_calc_num_queues(bp);
+ break;
- /* if we can't use MSI-X we only need one fp,
- * so try to enable MSI-X with the requested number of fp's
- * and fallback to MSI or legacy INTx with one fp
- */
- rc = bnx2x_enable_msix(bp);
- if (rc)
- /* failed to enable MSI-X */
- bp->num_queues = 1;
+ default:
+ bp->num_queues = 1;
break;
}
- bp->dev->real_num_tx_queues = bp->num_queues;
- return rc;
+}
+
+static void bnx2x_release_firmware(struct bnx2x *bp)
+{
+ kfree(bp->init_ops_offsets);
+ kfree(bp->init_ops);
+ kfree(bp->init_data);
+ release_firmware(bp->firmware);
}
/* must be called with rtnl_lock */
@@ -1212,6 +1182,13 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
u32 load_code;
int i, rc;
+ /* Set init arrays */
+ rc = bnx2x_init_firmware(bp);
+ if (rc) {
+ BNX2X_ERR("Error loading firmware\n");
+ return rc;
+ }
+
#ifdef BNX2X_STOP_ON_ERROR
if (unlikely(bp->panic))
return -EPERM;
@@ -1219,83 +1196,64 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
bp->state = BNX2X_STATE_OPENING_WAIT4_LOAD;
- rc = bnx2x_set_num_queues(bp);
+ /* must be called before memory allocation and HW init */
+ bnx2x_ilt_set_info(bp);
- if (bnx2x_alloc_mem(bp)) {
- bnx2x_free_irq(bp, true);
+ if (bnx2x_alloc_mem(bp))
return -ENOMEM;
+
+ netif_set_real_num_tx_queues(bp->dev, bp->num_queues);
+ rc = netif_set_real_num_rx_queues(bp->dev, bp->num_queues);
+ if (rc) {
+ BNX2X_ERR("Unable to update real_num_rx_queues\n");
+ goto load_error0;
}
for_each_queue(bp, i)
bnx2x_fp(bp, i, disable_tpa) =
((bp->flags & TPA_ENABLE_FLAG) == 0);
- for_each_queue(bp, i)
- netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi),
- bnx2x_poll, 128);
-
bnx2x_napi_enable(bp);
- if (bp->flags & USING_MSIX_FLAG) {
- rc = bnx2x_req_msix_irqs(bp);
- if (rc) {
- bnx2x_free_irq(bp, true);
- goto load_error1;
- }
- } else {
- /* Fall to INTx if failed to enable MSI-X due to lack of
- memory (in bnx2x_set_num_queues()) */
- if ((rc != -ENOMEM) && (bp->int_mode != INT_MODE_INTx))
- bnx2x_enable_msi(bp);
- bnx2x_ack_int(bp);
- rc = bnx2x_req_irq(bp);
- if (rc) {
- BNX2X_ERR("IRQ request failed rc %d, aborting\n", rc);
- bnx2x_free_irq(bp, true);
- goto load_error1;
- }
- if (bp->flags & USING_MSI_FLAG) {
- bp->dev->irq = bp->pdev->irq;
- netdev_info(bp->dev, "using MSI IRQ %d\n",
- bp->pdev->irq);
- }
- }
-
/* Send LOAD_REQUEST command to MCP
Returns the type of LOAD command:
if it is the first port to be initialized
common blocks should be initialized, otherwise - not
*/
if (!BP_NOMCP(bp)) {
- load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ);
+ load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ, 0);
if (!load_code) {
BNX2X_ERR("MCP response failure, aborting\n");
rc = -EBUSY;
- goto load_error2;
+ goto load_error1;
}
if (load_code == FW_MSG_CODE_DRV_LOAD_REFUSED) {
rc = -EBUSY; /* other port in diagnostic mode */
- goto load_error2;
+ goto load_error1;
}
} else {
+ int path = BP_PATH(bp);
int port = BP_PORT(bp);
- DP(NETIF_MSG_IFUP, "NO MCP - load counts %d, %d, %d\n",
- load_count[0], load_count[1], load_count[2]);
- load_count[0]++;
- load_count[1 + port]++;
- DP(NETIF_MSG_IFUP, "NO MCP - new load counts %d, %d, %d\n",
- load_count[0], load_count[1], load_count[2]);
- if (load_count[0] == 1)
+ DP(NETIF_MSG_IFUP, "NO MCP - load counts[%d] %d, %d, %d\n",
+ path, load_count[path][0], load_count[path][1],
+ load_count[path][2]);
+ load_count[path][0]++;
+ load_count[path][1 + port]++;
+ DP(NETIF_MSG_IFUP, "NO MCP - new load counts[%d] %d, %d, %d\n",
+ path, load_count[path][0], load_count[path][1],
+ load_count[path][2]);
+ if (load_count[path][0] == 1)
load_code = FW_MSG_CODE_DRV_LOAD_COMMON;
- else if (load_count[1 + port] == 1)
+ else if (load_count[path][1 + port] == 1)
load_code = FW_MSG_CODE_DRV_LOAD_PORT;
else
load_code = FW_MSG_CODE_DRV_LOAD_FUNCTION;
}
if ((load_code == FW_MSG_CODE_DRV_LOAD_COMMON) ||
+ (load_code == FW_MSG_CODE_DRV_LOAD_COMMON_CHIP) ||
(load_code == FW_MSG_CODE_DRV_LOAD_PORT))
bp->port.pmf = 1;
else
@@ -1306,16 +1264,22 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
rc = bnx2x_init_hw(bp, load_code);
if (rc) {
BNX2X_ERR("HW init failed, aborting\n");
- bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE);
- bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP);
- bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE);
+ bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE, 0);
+ goto load_error2;
+ }
+
+ /* Connect to IRQs */
+ rc = bnx2x_setup_irqs(bp);
+ if (rc) {
+ bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE, 0);
goto load_error2;
}
/* Setup NIC internals and enable interrupts */
bnx2x_nic_init(bp, load_code);
- if ((load_code == FW_MSG_CODE_DRV_LOAD_COMMON) &&
+ if (((load_code == FW_MSG_CODE_DRV_LOAD_COMMON) ||
+ (load_code == FW_MSG_CODE_DRV_LOAD_COMMON_CHIP)) &&
(bp->common.shmem2_base))
SHMEM2_WR(bp, dcc_support,
(SHMEM_DCC_SUPPORT_DISABLE_ENABLE_PF_TLV |
@@ -1323,7 +1287,7 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
/* Send LOAD_DONE command to MCP */
if (!BP_NOMCP(bp)) {
- load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE);
+ load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE, 0);
if (!load_code) {
BNX2X_ERR("MCP response failure, aborting\n");
rc = -EBUSY;
@@ -1333,7 +1297,18 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
bp->state = BNX2X_STATE_OPENING_WAIT4_PORT;
- rc = bnx2x_setup_leading(bp);
+ rc = bnx2x_func_start(bp);
+ if (rc) {
+ BNX2X_ERR("Function start failed!\n");
+#ifndef BNX2X_STOP_ON_ERROR
+ goto load_error3;
+#else
+ bp->panic = 1;
+ return -EBUSY;
+#endif
+ }
+
+ rc = bnx2x_setup_client(bp, &bp->fp[0], 1 /* Leading */);
if (rc) {
BNX2X_ERR("Setup leading failed!\n");
#ifndef BNX2X_STOP_ON_ERROR
@@ -1344,62 +1319,47 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
#endif
}
- if (CHIP_IS_E1H(bp))
- if (bp->mf_config & FUNC_MF_CFG_FUNC_DISABLED) {
- DP(NETIF_MSG_IFUP, "mf_cfg function disabled\n");
- bp->flags |= MF_FUNC_DIS;
- }
+ if (!CHIP_IS_E1(bp) &&
+ (bp->mf_config[BP_VN(bp)] & FUNC_MF_CFG_FUNC_DISABLED)) {
+ DP(NETIF_MSG_IFUP, "mf_cfg function disabled\n");
+ bp->flags |= MF_FUNC_DIS;
+ }
- if (bp->state == BNX2X_STATE_OPEN) {
-#ifdef BCM_CNIC
- /* Enable Timer scan */
- REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + BP_PORT(bp)*4, 1);
-#endif
- for_each_nondefault_queue(bp, i) {
- rc = bnx2x_setup_multi(bp, i);
- if (rc)
#ifdef BCM_CNIC
- goto load_error4;
-#else
- goto load_error3;
+ /* Enable Timer scan */
+ REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + BP_PORT(bp)*4, 1);
#endif
- }
- if (CHIP_IS_E1(bp))
- bnx2x_set_eth_mac_addr_e1(bp, 1);
- else
- bnx2x_set_eth_mac_addr_e1h(bp, 1);
+ for_each_nondefault_queue(bp, i) {
+ rc = bnx2x_setup_client(bp, &bp->fp[i], 0);
+ if (rc)
#ifdef BCM_CNIC
- /* Set iSCSI L2 MAC */
- mutex_lock(&bp->cnic_mutex);
- if (bp->cnic_eth_dev.drv_state & CNIC_DRV_STATE_REGD) {
- bnx2x_set_iscsi_eth_mac_addr(bp, 1);
- bp->cnic_flags |= BNX2X_CNIC_FLAG_MAC_SET;
- bnx2x_init_sb(bp, bp->cnic_sb, bp->cnic_sb_mapping,
- CNIC_SB_ID(bp));
- }
- mutex_unlock(&bp->cnic_mutex);
+ goto load_error4;
+#else
+ goto load_error3;
#endif
}
+ /* Now when Clients are configured we are ready to work */
+ bp->state = BNX2X_STATE_OPEN;
+
+ bnx2x_set_eth_mac(bp, 1);
+
if (bp->port.pmf)
bnx2x_initial_phy_init(bp, load_mode);
/* Start fast path */
switch (load_mode) {
case LOAD_NORMAL:
- if (bp->state == BNX2X_STATE_OPEN) {
- /* Tx queue should be only reenabled */
- netif_tx_wake_all_queues(bp->dev);
- }
+ /* Tx queue should be only reenabled */
+ netif_tx_wake_all_queues(bp->dev);
/* Initialize the receive filter. */
bnx2x_set_rx_mode(bp->dev);
break;
case LOAD_OPEN:
netif_tx_start_all_queues(bp->dev);
- if (bp->state != BNX2X_STATE_OPEN)
- netif_tx_disable(bp->dev);
+ smp_mb__after_clear_bit();
/* Initialize the receive filter. */
bnx2x_set_rx_mode(bp->dev);
break;
@@ -1427,6 +1387,8 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
#endif
bnx2x_inc_load_cnt(bp);
+ bnx2x_release_firmware(bp);
+
return 0;
#ifdef BCM_CNIC
@@ -1436,24 +1398,28 @@ load_error4:
#endif
load_error3:
bnx2x_int_disable_sync(bp, 1);
- if (!BP_NOMCP(bp)) {
- bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP);
- bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE);
- }
- bp->port.pmf = 0;
+
/* Free SKBs, SGEs, TPA pool and driver internals */
bnx2x_free_skbs(bp);
for_each_queue(bp, i)
bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE);
-load_error2:
+
/* Release IRQs */
- bnx2x_free_irq(bp, false);
+ bnx2x_free_irq(bp);
+load_error2:
+ if (!BP_NOMCP(bp)) {
+ bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP, 0);
+ bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, 0);
+ }
+
+ bp->port.pmf = 0;
load_error1:
bnx2x_napi_disable(bp);
- for_each_queue(bp, i)
- netif_napi_del(&bnx2x_fp(bp, i, napi));
+load_error0:
bnx2x_free_mem(bp);
+ bnx2x_release_firmware(bp);
+
return rc;
}
@@ -1481,21 +1447,26 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode)
bp->rx_mode = BNX2X_RX_MODE_NONE;
bnx2x_set_storm_rx_mode(bp);
- /* Disable HW interrupts, NAPI and Tx */
- bnx2x_netif_stop(bp, 1);
- netif_carrier_off(bp->dev);
+ /* Stop Tx */
+ bnx2x_tx_disable(bp);
del_timer_sync(&bp->timer);
- SHMEM_WR(bp, func_mb[BP_FUNC(bp)].drv_pulse_mb,
+
+ SHMEM_WR(bp, func_mb[BP_FW_MB_IDX(bp)].drv_pulse_mb,
(DRV_PULSE_ALWAYS_ALIVE | bp->fw_drv_pulse_wr_seq));
- bnx2x_stats_handle(bp, STATS_EVENT_STOP);
- /* Release IRQs */
- bnx2x_free_irq(bp, false);
+ bnx2x_stats_handle(bp, STATS_EVENT_STOP);
/* Cleanup the chip if needed */
if (unload_mode != UNLOAD_RECOVERY)
bnx2x_chip_cleanup(bp, unload_mode);
+ else {
+ /* Disable HW interrupts, NAPI and Tx */
+ bnx2x_netif_stop(bp, 1);
+
+ /* Release IRQs */
+ bnx2x_free_irq(bp);
+ }
bp->port.pmf = 0;
@@ -1503,8 +1474,7 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode)
bnx2x_free_skbs(bp);
for_each_queue(bp, i)
bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE);
- for_each_queue(bp, i)
- netif_napi_del(&bnx2x_fp(bp, i, napi));
+
bnx2x_free_mem(bp);
bp->state = BNX2X_STATE_CLOSED;
@@ -1522,10 +1492,17 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode)
return 0;
}
+
int bnx2x_set_power_state(struct bnx2x *bp, pci_power_t state)
{
u16 pmcsr;
+ /* If there is no power capability, silently succeed */
+ if (!bp->pm_cap) {
+ DP(NETIF_MSG_HW, "No power capability. Breaking.\n");
+ return 0;
+ }
+
pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL, &pmcsr);
switch (state) {
@@ -1568,13 +1545,10 @@ int bnx2x_set_power_state(struct bnx2x *bp, pci_power_t state)
return 0;
}
-
-
/*
* net_device service functions
*/
-
-static int bnx2x_poll(struct napi_struct *napi, int budget)
+int bnx2x_poll(struct napi_struct *napi, int budget)
{
int work_done = 0;
struct bnx2x_fastpath *fp = container_of(napi, struct bnx2x_fastpath,
@@ -1603,27 +1577,28 @@ static int bnx2x_poll(struct napi_struct *napi, int budget)
/* Fall out from the NAPI loop if needed */
if (!(bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp))) {
bnx2x_update_fpsb_idx(fp);
- /* bnx2x_has_rx_work() reads the status block, thus we need
- * to ensure that status block indices have been actually read
- * (bnx2x_update_fpsb_idx) prior to this check
- * (bnx2x_has_rx_work) so that we won't write the "newer"
- * value of the status block to IGU (if there was a DMA right
- * after bnx2x_has_rx_work and if there is no rmb, the memory
- * reading (bnx2x_update_fpsb_idx) may be postponed to right
- * before bnx2x_ack_sb). In this case there will never be
- * another interrupt until there is another update of the
- * status block, while there is still unhandled work.
- */
+ /* bnx2x_has_rx_work() reads the status block,
+ * thus we need to ensure that status block indices
+ * have been actually read (bnx2x_update_fpsb_idx)
+ * prior to this check (bnx2x_has_rx_work) so that
+ * we won't write the "newer" value of the status block
+ * to IGU (if there was a DMA right after
+ * bnx2x_has_rx_work and if there is no rmb, the memory
+ * reading (bnx2x_update_fpsb_idx) may be postponed
+ * to right before bnx2x_ack_sb). In this case there
+ * will never be another interrupt until there is
+ * another update of the status block, while there
+ * is still unhandled work.
+ */
rmb();
if (!(bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp))) {
napi_complete(napi);
/* Re-enable interrupts */
- bnx2x_ack_sb(bp, fp->sb_id, CSTORM_ID,
- le16_to_cpu(fp->fp_c_idx),
- IGU_INT_NOP, 1);
- bnx2x_ack_sb(bp, fp->sb_id, USTORM_ID,
- le16_to_cpu(fp->fp_u_idx),
+ DP(NETIF_MSG_HW,
+ "Update index to %d\n", fp->fp_hc_idx);
+ bnx2x_ack_sb(bp, fp->igu_sb_id, USTORM_ID,
+ le16_to_cpu(fp->fp_hc_idx),
IGU_INT_ENABLE, 1);
break;
}
@@ -1633,7 +1608,6 @@ static int bnx2x_poll(struct napi_struct *napi, int budget)
return work_done;
}
-
/* we split the first BD into headers and data BDs
* to ease the pain of our fellow microcode engineers
* we use one mapping for both BDs
@@ -1807,6 +1781,122 @@ exit_lbl:
}
#endif
+static inline void bnx2x_set_pbd_gso_e2(struct sk_buff *skb,
+ struct eth_tx_parse_bd_e2 *pbd,
+ u32 xmit_type)
+{
+ pbd->parsing_data |= cpu_to_le16(skb_shinfo(skb)->gso_size) <<
+ ETH_TX_PARSE_BD_E2_LSO_MSS_SHIFT;
+ if ((xmit_type & XMIT_GSO_V6) &&
+ (ipv6_hdr(skb)->nexthdr == NEXTHDR_IPV6))
+ pbd->parsing_data |= ETH_TX_PARSE_BD_E2_IPV6_WITH_EXT_HDR;
+}
+
+/**
+ * Update PBD in GSO case.
+ *
+ * @param skb
+ * @param tx_start_bd
+ * @param pbd
+ * @param xmit_type
+ */
+static inline void bnx2x_set_pbd_gso(struct sk_buff *skb,
+ struct eth_tx_parse_bd_e1x *pbd,
+ u32 xmit_type)
+{
+ pbd->lso_mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
+ pbd->tcp_send_seq = swab32(tcp_hdr(skb)->seq);
+ pbd->tcp_flags = pbd_tcp_flags(skb);
+
+ if (xmit_type & XMIT_GSO_V4) {
+ pbd->ip_id = swab16(ip_hdr(skb)->id);
+ pbd->tcp_pseudo_csum =
+ swab16(~csum_tcpudp_magic(ip_hdr(skb)->saddr,
+ ip_hdr(skb)->daddr,
+ 0, IPPROTO_TCP, 0));
+
+ } else
+ pbd->tcp_pseudo_csum =
+ swab16(~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
+ &ipv6_hdr(skb)->daddr,
+ 0, IPPROTO_TCP, 0));
+
+ pbd->global_data |= ETH_TX_PARSE_BD_E1X_PSEUDO_CS_WITHOUT_LEN;
+}
+
+/**
+ *
+ * @param skb
+ * @param tx_start_bd
+ * @param pbd_e2
+ * @param xmit_type
+ *
+ * @return header len
+ */
+static inline u8 bnx2x_set_pbd_csum_e2(struct bnx2x *bp, struct sk_buff *skb,
+ struct eth_tx_parse_bd_e2 *pbd,
+ u32 xmit_type)
+{
+ pbd->parsing_data |= cpu_to_le16(tcp_hdrlen(skb)/4) <<
+ ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW_SHIFT;
+
+ pbd->parsing_data |= cpu_to_le16(((unsigned char *)tcp_hdr(skb) -
+ skb->data) / 2) <<
+ ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W_SHIFT;
+
+ return skb_transport_header(skb) + tcp_hdrlen(skb) - skb->data;
+}
+
+/**
+ *
+ * @param skb
+ * @param tx_start_bd
+ * @param pbd
+ * @param xmit_type
+ *
+ * @return Header length
+ */
+static inline u8 bnx2x_set_pbd_csum(struct bnx2x *bp, struct sk_buff *skb,
+ struct eth_tx_parse_bd_e1x *pbd,
+ u32 xmit_type)
+{
+ u8 hlen = (skb_network_header(skb) - skb->data) / 2;
+
+ /* for now NS flag is not used in Linux */
+ pbd->global_data =
+ (hlen | ((skb->protocol == cpu_to_be16(ETH_P_8021Q)) <<
+ ETH_TX_PARSE_BD_E1X_LLC_SNAP_EN_SHIFT));
+
+ pbd->ip_hlen_w = (skb_transport_header(skb) -
+ skb_network_header(skb)) / 2;
+
+ hlen += pbd->ip_hlen_w + tcp_hdrlen(skb) / 2;
+
+ pbd->total_hlen_w = cpu_to_le16(hlen);
+ hlen = hlen*2;
+
+ if (xmit_type & XMIT_CSUM_TCP) {
+ pbd->tcp_pseudo_csum = swab16(tcp_hdr(skb)->check);
+
+ } else {
+ s8 fix = SKB_CS_OFF(skb); /* signed! */
+
+ DP(NETIF_MSG_TX_QUEUED,
+ "hlen %d fix %d csum before fix %x\n",
+ le16_to_cpu(pbd->total_hlen_w), fix, SKB_CS(skb));
+
+ /* HW bug: fixup the CSUM */
+ pbd->tcp_pseudo_csum =
+ bnx2x_csum_fix(skb_transport_header(skb),
+ SKB_CS(skb), fix);
+
+ DP(NETIF_MSG_TX_QUEUED, "csum after fix %x\n",
+ pbd->tcp_pseudo_csum);
+ }
+
+ return hlen;
+}
+
/* called with netif_tx_lock
* bnx2x_tx_int() runs without netif_tx_lock unless it needs to call
* netif_wake_queue()
@@ -1819,7 +1909,8 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
struct sw_tx_bd *tx_buf;
struct eth_tx_start_bd *tx_start_bd;
struct eth_tx_bd *tx_data_bd, *total_pkt_bd = NULL;
- struct eth_tx_parse_bd *pbd = NULL;
+ struct eth_tx_parse_bd_e1x *pbd_e1x = NULL;
+ struct eth_tx_parse_bd_e2 *pbd_e2 = NULL;
u16 pkt_prod, bd_prod;
int nbd, fp_index;
dma_addr_t mapping;
@@ -1847,9 +1938,9 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_BUSY;
}
- DP(NETIF_MSG_TX_QUEUED, "SKB: summed %x protocol %x protocol(%x,%x)"
- " gso type %x xmit_type %x\n",
- skb->ip_summed, skb->protocol, ipv6_hdr(skb)->nexthdr,
+ DP(NETIF_MSG_TX_QUEUED, "queue[%d]: SKB: summed %x protocol %x "
+ "protocol(%x,%x) gso type %x xmit_type %x\n",
+ fp_index, skb->ip_summed, skb->protocol, ipv6_hdr(skb)->nexthdr,
ip_hdr(skb)->protocol, skb_shinfo(skb)->gso_type, xmit_type);
eth = (struct ethhdr *)skb->data;
@@ -1895,10 +1986,11 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
tx_start_bd = &fp->tx_desc_ring[bd_prod].start_bd;
tx_start_bd->bd_flags.as_bitfield = ETH_TX_BD_FLAGS_START_BD;
- tx_start_bd->general_data = (mac_type <<
- ETH_TX_START_BD_ETH_ADDR_TYPE_SHIFT);
+ SET_FLAG(tx_start_bd->general_data, ETH_TX_START_BD_ETH_ADDR_TYPE,
+ mac_type);
+
/* header nbd */
- tx_start_bd->general_data |= (1 << ETH_TX_START_BD_HDR_NBDS_SHIFT);
+ SET_FLAG(tx_start_bd->general_data, ETH_TX_START_BD_HDR_NBDS, 1);
/* remember the first BD of the packet */
tx_buf->first_bd = fp->tx_bd_prod;
@@ -1909,37 +2001,18 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
"sending pkt %u @%p next_idx %u bd %u @%p\n",
pkt_prod, tx_buf, fp->tx_pkt_prod, bd_prod, tx_start_bd);
-#ifdef BCM_VLAN
- if ((bp->vlgrp != NULL) && vlan_tx_tag_present(skb) &&
- (bp->flags & HW_VLAN_TX_FLAG)) {
- tx_start_bd->vlan = cpu_to_le16(vlan_tx_tag_get(skb));
- tx_start_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_VLAN_TAG;
+ if (vlan_tx_tag_present(skb)) {
+ tx_start_bd->vlan_or_ethertype =
+ cpu_to_le16(vlan_tx_tag_get(skb));
+ tx_start_bd->bd_flags.as_bitfield |=
+ (X_ETH_OUTBAND_VLAN << ETH_TX_BD_FLAGS_VLAN_MODE_SHIFT);
} else
-#endif
- tx_start_bd->vlan = cpu_to_le16(pkt_prod);
+ tx_start_bd->vlan_or_ethertype = cpu_to_le16(pkt_prod);
/* turn on parsing and get a BD */
bd_prod = TX_BD(NEXT_TX_IDX(bd_prod));
- pbd = &fp->tx_desc_ring[bd_prod].parse_bd;
-
- memset(pbd, 0, sizeof(struct eth_tx_parse_bd));
if (xmit_type & XMIT_CSUM) {
- hlen = (skb_network_header(skb) - skb->data) / 2;
-
- /* for now NS flag is not used in Linux */
- pbd->global_data =
- (hlen | ((skb->protocol == cpu_to_be16(ETH_P_8021Q)) <<
- ETH_TX_PARSE_BD_LLC_SNAP_EN_SHIFT));
-
- pbd->ip_hlen = (skb_transport_header(skb) -
- skb_network_header(skb)) / 2;
-
- hlen += pbd->ip_hlen + tcp_hdrlen(skb) / 2;
-
- pbd->total_hlen = cpu_to_le16(hlen);
- hlen = hlen*2;
-
tx_start_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_L4_CSUM;
if (xmit_type & XMIT_CSUM_V4)
@@ -1949,31 +2022,32 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
tx_start_bd->bd_flags.as_bitfield |=
ETH_TX_BD_FLAGS_IPV6;
- if (xmit_type & XMIT_CSUM_TCP) {
- pbd->tcp_pseudo_csum = swab16(tcp_hdr(skb)->check);
-
- } else {
- s8 fix = SKB_CS_OFF(skb); /* signed! */
-
- pbd->global_data |= ETH_TX_PARSE_BD_UDP_CS_FLG;
-
- DP(NETIF_MSG_TX_QUEUED,
- "hlen %d fix %d csum before fix %x\n",
- le16_to_cpu(pbd->total_hlen), fix, SKB_CS(skb));
+ if (!(xmit_type & XMIT_CSUM_TCP))
+ tx_start_bd->bd_flags.as_bitfield |=
+ ETH_TX_BD_FLAGS_IS_UDP;
+ }
- /* HW bug: fixup the CSUM */
- pbd->tcp_pseudo_csum =
- bnx2x_csum_fix(skb_transport_header(skb),
- SKB_CS(skb), fix);
+ if (CHIP_IS_E2(bp)) {
+ pbd_e2 = &fp->tx_desc_ring[bd_prod].parse_bd_e2;
+ memset(pbd_e2, 0, sizeof(struct eth_tx_parse_bd_e2));
+ /* Set PBD in checksum offload case */
+ if (xmit_type & XMIT_CSUM)
+ hlen = bnx2x_set_pbd_csum_e2(bp,
+ skb, pbd_e2, xmit_type);
+ } else {
+ pbd_e1x = &fp->tx_desc_ring[bd_prod].parse_bd_e1x;
+ memset(pbd_e1x, 0, sizeof(struct eth_tx_parse_bd_e1x));
+ /* Set PBD in checksum offload case */
+ if (xmit_type & XMIT_CSUM)
+ hlen = bnx2x_set_pbd_csum(bp, skb, pbd_e1x, xmit_type);
- DP(NETIF_MSG_TX_QUEUED, "csum after fix %x\n",
- pbd->tcp_pseudo_csum);
- }
}
+ /* Map skb linear data for DMA */
mapping = dma_map_single(&bp->pdev->dev, skb->data,
skb_headlen(skb), DMA_TO_DEVICE);
+ /* Setup the data pointer of the first BD of the packet */
tx_start_bd->addr_hi = cpu_to_le32(U64_HI(mapping));
tx_start_bd->addr_lo = cpu_to_le32(U64_LO(mapping));
nbd = skb_shinfo(skb)->nr_frags + 2; /* start_bd + pbd + frags */
@@ -1985,7 +2059,8 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
" nbytes %d flags %x vlan %x\n",
tx_start_bd, tx_start_bd->addr_hi, tx_start_bd->addr_lo,
le16_to_cpu(tx_start_bd->nbd), le16_to_cpu(tx_start_bd->nbytes),
- tx_start_bd->bd_flags.as_bitfield, le16_to_cpu(tx_start_bd->vlan));
+ tx_start_bd->bd_flags.as_bitfield,
+ le16_to_cpu(tx_start_bd->vlan_or_ethertype));
if (xmit_type & XMIT_GSO) {
@@ -1999,28 +2074,14 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (unlikely(skb_headlen(skb) > hlen))
bd_prod = bnx2x_tx_split(bp, fp, tx_buf, &tx_start_bd,
hlen, bd_prod, ++nbd);
-
- pbd->lso_mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
- pbd->tcp_send_seq = swab32(tcp_hdr(skb)->seq);
- pbd->tcp_flags = pbd_tcp_flags(skb);
-
- if (xmit_type & XMIT_GSO_V4) {
- pbd->ip_id = swab16(ip_hdr(skb)->id);
- pbd->tcp_pseudo_csum =
- swab16(~csum_tcpudp_magic(ip_hdr(skb)->saddr,
- ip_hdr(skb)->daddr,
- 0, IPPROTO_TCP, 0));
-
- } else
- pbd->tcp_pseudo_csum =
- swab16(~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
- &ipv6_hdr(skb)->daddr,
- 0, IPPROTO_TCP, 0));
-
- pbd->global_data |= ETH_TX_PARSE_BD_PSEUDO_CS_WITHOUT_LEN;
+ if (CHIP_IS_E2(bp))
+ bnx2x_set_pbd_gso_e2(skb, pbd_e2, xmit_type);
+ else
+ bnx2x_set_pbd_gso(skb, pbd_e1x, xmit_type);
}
tx_data_bd = (struct eth_tx_bd *)tx_start_bd;
+ /* Handle fragmented skb */
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
@@ -2057,14 +2118,21 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (total_pkt_bd != NULL)
total_pkt_bd->total_pkt_bytes = pkt_size;
- if (pbd)
+ if (pbd_e1x)
DP(NETIF_MSG_TX_QUEUED,
- "PBD @%p ip_data %x ip_hlen %u ip_id %u lso_mss %u"
+ "PBD (E1X) @%p ip_data %x ip_hlen %u ip_id %u lso_mss %u"
" tcp_flags %x xsum %x seq %u hlen %u\n",
- pbd, pbd->global_data, pbd->ip_hlen, pbd->ip_id,
- pbd->lso_mss, pbd->tcp_flags, pbd->tcp_pseudo_csum,
- pbd->tcp_send_seq, le16_to_cpu(pbd->total_hlen));
-
+ pbd_e1x, pbd_e1x->global_data, pbd_e1x->ip_hlen_w,
+ pbd_e1x->ip_id, pbd_e1x->lso_mss, pbd_e1x->tcp_flags,
+ pbd_e1x->tcp_pseudo_csum, pbd_e1x->tcp_send_seq,
+ le16_to_cpu(pbd_e1x->total_hlen_w));
+ if (pbd_e2)
+ DP(NETIF_MSG_TX_QUEUED,
+ "PBD (E2) @%p dst %x %x %x src %x %x %x parsing_data %x\n",
+ pbd_e2, pbd_e2->dst_mac_addr_hi, pbd_e2->dst_mac_addr_mid,
+ pbd_e2->dst_mac_addr_lo, pbd_e2->src_mac_addr_hi,
+ pbd_e2->src_mac_addr_mid, pbd_e2->src_mac_addr_lo,
+ pbd_e2->parsing_data);
DP(NETIF_MSG_TX_QUEUED, "doorbell: nbd %d bd %u\n", nbd, bd_prod);
/*
@@ -2078,7 +2146,8 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
fp->tx_db.data.prod += nbd;
barrier();
- DOORBELL(bp, fp->index, fp->tx_db.raw);
+
+ DOORBELL(bp, fp->cid, fp->tx_db.raw);
mmiowb();
@@ -2100,6 +2169,7 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_OK;
}
+
/* called with rtnl_lock */
int bnx2x_change_mac_addr(struct net_device *dev, void *p)
{
@@ -2110,16 +2180,76 @@ int bnx2x_change_mac_addr(struct net_device *dev, void *p)
return -EINVAL;
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
- if (netif_running(dev)) {
- if (CHIP_IS_E1(bp))
- bnx2x_set_eth_mac_addr_e1(bp, 1);
- else
- bnx2x_set_eth_mac_addr_e1h(bp, 1);
+ if (netif_running(dev))
+ bnx2x_set_eth_mac(bp, 1);
+
+ return 0;
+}
+
+
+int bnx2x_setup_irqs(struct bnx2x *bp)
+{
+ int rc = 0;
+ if (bp->flags & USING_MSIX_FLAG) {
+ rc = bnx2x_req_msix_irqs(bp);
+ if (rc)
+ return rc;
+ } else {
+ bnx2x_ack_int(bp);
+ rc = bnx2x_req_irq(bp);
+ if (rc) {
+ BNX2X_ERR("IRQ request failed rc %d, aborting\n", rc);
+ return rc;
+ }
+ if (bp->flags & USING_MSI_FLAG) {
+ bp->dev->irq = bp->pdev->irq;
+ netdev_info(bp->dev, "using MSI IRQ %d\n",
+ bp->pdev->irq);
+ }
}
return 0;
}
+void bnx2x_free_mem_bp(struct bnx2x *bp)
+{
+ kfree(bp->fp);
+ kfree(bp->msix_table);
+ kfree(bp->ilt);
+}
+
+int __devinit bnx2x_alloc_mem_bp(struct bnx2x *bp)
+{
+ struct bnx2x_fastpath *fp;
+ struct msix_entry *tbl;
+ struct bnx2x_ilt *ilt;
+
+ /* fp array */
+ fp = kzalloc(L2_FP_COUNT(bp->l2_cid_count)*sizeof(*fp), GFP_KERNEL);
+ if (!fp)
+ goto alloc_err;
+ bp->fp = fp;
+
+ /* msix table */
+ tbl = kzalloc((bp->l2_cid_count + 1) * sizeof(*tbl),
+ GFP_KERNEL);
+ if (!tbl)
+ goto alloc_err;
+ bp->msix_table = tbl;
+
+ /* ilt */
+ ilt = kzalloc(sizeof(*ilt), GFP_KERNEL);
+ if (!ilt)
+ goto alloc_err;
+ bp->ilt = ilt;
+
+ return 0;
+alloc_err:
+ bnx2x_free_mem_bp(bp);
+ return -ENOMEM;
+
+}
+
/* called with rtnl_lock */
int bnx2x_change_mtu(struct net_device *dev, int new_mtu)
{
@@ -2161,29 +2291,6 @@ void bnx2x_tx_timeout(struct net_device *dev)
schedule_delayed_work(&bp->reset_task, 0);
}
-#ifdef BCM_VLAN
-/* called with rtnl_lock */
-void bnx2x_vlan_rx_register(struct net_device *dev,
- struct vlan_group *vlgrp)
-{
- struct bnx2x *bp = netdev_priv(dev);
-
- bp->vlgrp = vlgrp;
-
- /* Set flags according to the required capabilities */
- bp->flags &= ~(HW_VLAN_RX_FLAG | HW_VLAN_TX_FLAG);
-
- if (dev->features & NETIF_F_HW_VLAN_TX)
- bp->flags |= HW_VLAN_TX_FLAG;
-
- if (dev->features & NETIF_F_HW_VLAN_RX)
- bp->flags |= HW_VLAN_RX_FLAG;
-
- if (netif_running(dev))
- bnx2x_set_client_config(bp);
-}
-
-#endif
int bnx2x_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct net_device *dev = pci_get_drvdata(pdev);
@@ -2244,6 +2351,8 @@ int bnx2x_resume(struct pci_dev *pdev)
bnx2x_set_power_state(bp, PCI_D0);
netif_device_attach(dev);
+ /* Since the chip was reset, clear the FW sequence number */
+ bp->fw_seq = 0;
rc = bnx2x_nic_load(bp, LOAD_OPEN);
rtnl_unlock();
diff --git a/drivers/net/bnx2x/bnx2x_cmn.h b/drivers/net/bnx2x/bnx2x_cmn.h
index d1979b1a7ed2..5bfe0ab1d2d4 100644
--- a/drivers/net/bnx2x/bnx2x_cmn.h
+++ b/drivers/net/bnx2x/bnx2x_cmn.h
@@ -23,6 +23,7 @@
#include "bnx2x.h"
+extern int num_queues;
/*********************** Interfaces ****************************
* Functions that need to be implemented by each driver version
@@ -49,10 +50,11 @@ void bnx2x_link_set(struct bnx2x *bp);
* Query link status
*
* @param bp
+ * @param is_serdes
*
* @return 0 - link is UP
*/
-u8 bnx2x_link_test(struct bnx2x *bp);
+u8 bnx2x_link_test(struct bnx2x *bp, u8 is_serdes);
/**
* Handles link status change
@@ -62,6 +64,15 @@ u8 bnx2x_link_test(struct bnx2x *bp);
void bnx2x__link_status_update(struct bnx2x *bp);
/**
+ * Report link status to upper layer
+ *
+ * @param bp
+ *
+ * @return int
+ */
+void bnx2x_link_report(struct bnx2x *bp);
+
+/**
* MSI-X slowpath interrupt handler
*
* @param irq
@@ -106,6 +117,13 @@ void bnx2x_setup_cnic_irq_info(struct bnx2x *bp);
void bnx2x_int_enable(struct bnx2x *bp);
/**
+ * Disable HW interrupts.
+ *
+ * @param bp
+ */
+void bnx2x_int_disable(struct bnx2x *bp);
+
+/**
* Disable interrupts. This function ensures that there are no
* ISRs or SP DPCs (sp_task) are running after it returns.
*
@@ -115,6 +133,15 @@ void bnx2x_int_enable(struct bnx2x *bp);
void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw);
/**
+ * Loads device firmware
+ *
+ * @param bp
+ *
+ * @return int
+ */
+int bnx2x_init_firmware(struct bnx2x *bp);
+
+/**
* Init HW blocks according to current initialization stage:
* COMMON, PORT or FUNCTION.
*
@@ -153,32 +180,35 @@ int bnx2x_alloc_mem(struct bnx2x *bp);
void bnx2x_free_mem(struct bnx2x *bp);
/**
- * Bring up a leading (the first) eth Client.
+ * Setup eth Client.
*
* @param bp
+ * @param fp
+ * @param is_leading
*
* @return int
*/
-int bnx2x_setup_leading(struct bnx2x *bp);
+int bnx2x_setup_client(struct bnx2x *bp, struct bnx2x_fastpath *fp,
+ int is_leading);
/**
- * Setup non-leading eth Client.
+ * Bring down an eth client.
*
* @param bp
- * @param fp
+ * @param p
*
* @return int
*/
-int bnx2x_setup_multi(struct bnx2x *bp, int index);
+int bnx2x_stop_fw_client(struct bnx2x *bp,
+ struct bnx2x_client_ramrod_params *p);
/**
- * Set number of quueus according to mode and number of available
- * msi-x vectors
+ * Set number of queues according to mode
*
* @param bp
*
*/
-void bnx2x_set_num_queues_msix(struct bnx2x *bp);
+void bnx2x_set_num_queues(struct bnx2x *bp);
/**
* Cleanup chip internals:
@@ -213,21 +243,12 @@ int bnx2x_release_hw_lock(struct bnx2x *bp, u32 resource);
/**
* Configure eth MAC address in the HW according to the value in
- * netdev->dev_addr for 57711
- *
- * @param bp driver handle
- * @param set
- */
-void bnx2x_set_eth_mac_addr_e1h(struct bnx2x *bp, int set);
-
-/**
- * Configure eth MAC address in the HW according to the value in
- * netdev->dev_addr for 57710
+ * netdev->dev_addr.
*
* @param bp driver handle
* @param set
*/
-void bnx2x_set_eth_mac_addr_e1(struct bnx2x *bp, int set);
+void bnx2x_set_eth_mac(struct bnx2x *bp, int set);
#ifdef BCM_CNIC
/**
@@ -247,18 +268,22 @@ int bnx2x_set_iscsi_eth_mac_addr(struct bnx2x *bp, int set);
* Initialize status block in FW and HW
*
* @param bp driver handle
- * @param sb host_status_block
* @param dma_addr_t mapping
* @param int sb_id
+ * @param int vfid
+ * @param u8 vf_valid
+ * @param int fw_sb_id
+ * @param int igu_sb_id
*/
-void bnx2x_init_sb(struct bnx2x *bp, struct host_status_block *sb,
- dma_addr_t mapping, int sb_id);
+void bnx2x_init_sb(struct bnx2x *bp, dma_addr_t mapping, int vfid,
+ u8 vf_valid, int fw_sb_id, int igu_sb_id);
/**
- * Reconfigure FW/HW according to dev->flags rx mode
+ * Set MAC filtering configurations.
*
- * @param dev net_device
+ * @remarks called with netif_tx_lock from dev_mcast.c
*
+ * @param dev net_device
*/
void bnx2x_set_rx_mode(struct net_device *dev);
@@ -280,34 +305,162 @@ void bnx2x_disable_close_the_gate(struct bnx2x *bp);
* Perform statistics handling according to event
*
* @param bp driver handle
- * @param even tbnx2x_stats_event
+ * @param event bnx2x_stats_event
*/
void bnx2x_stats_handle(struct bnx2x *bp, enum bnx2x_stats_event event);
/**
- * Configures FW with client paramteres (like HW VLAN removal)
- * for each active client.
+ * Handle ramrods completion
+ *
+ * @param fp fastpath handle for the event
+ * @param rr_cqe eth_rx_cqe
+ */
+void bnx2x_sp_event(struct bnx2x_fastpath *fp, union eth_rx_cqe *rr_cqe);
+
+/**
+ * Init/halt function before/after sending
+ * CLIENT_SETUP/CFC_DEL for the first/last client.
*
* @param bp
+ *
+ * @return int
*/
-void bnx2x_set_client_config(struct bnx2x *bp);
+int bnx2x_func_start(struct bnx2x *bp);
+int bnx2x_func_stop(struct bnx2x *bp);
/**
- * Handle sp events
+ * Prepare ILT configurations according to current driver
+ * parameters.
*
- * @param fp fastpath handle for the event
- * @param rr_cqe eth_rx_cqe
+ * @param bp
+ */
+void bnx2x_ilt_set_info(struct bnx2x *bp);
+
+/**
+ * Set power state to the requested value. Currently only D0 and
+ * D3hot are supported.
+ *
+ * @param bp
+ * @param state D0 or D3hot
+ *
+ * @return int
*/
-void bnx2x_sp_event(struct bnx2x_fastpath *fp, union eth_rx_cqe *rr_cqe);
+int bnx2x_set_power_state(struct bnx2x *bp, pci_power_t state);
+
+/* dev_close main block */
+int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode);
+
+/* dev_open main block */
+int bnx2x_nic_load(struct bnx2x *bp, int load_mode);
+
+/* hard_xmit callback */
+netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev);
+
+int bnx2x_change_mac_addr(struct net_device *dev, void *p);
+
+/* NAPI poll Rx part */
+int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget);
+
+/* NAPI poll Tx part */
+int bnx2x_tx_int(struct bnx2x_fastpath *fp);
+
+/* suspend/resume callbacks */
+int bnx2x_suspend(struct pci_dev *pdev, pm_message_t state);
+int bnx2x_resume(struct pci_dev *pdev);
+
+/* Release IRQ vectors */
+void bnx2x_free_irq(struct bnx2x *bp);
+
+void bnx2x_init_rx_rings(struct bnx2x *bp);
+void bnx2x_free_skbs(struct bnx2x *bp);
+void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw);
+void bnx2x_netif_start(struct bnx2x *bp);
+/**
+ * Fill msix_table, request vectors, update num_queues according
+ * to number of available vectors
+ *
+ * @param bp
+ *
+ * @return int
+ */
+int bnx2x_enable_msix(struct bnx2x *bp);
+
+/**
+ * Request msi mode from OS, updated internals accordingly
+ *
+ * @param bp
+ *
+ * @return int
+ */
+int bnx2x_enable_msi(struct bnx2x *bp);
+
+/**
+ * Request IRQ vectors from OS.
+ *
+ * @param bp
+ *
+ * @return int
+ */
+int bnx2x_setup_irqs(struct bnx2x *bp);
+/**
+ * NAPI callback
+ *
+ * @param napi
+ * @param budget
+ *
+ * @return int
+ */
+int bnx2x_poll(struct napi_struct *napi, int budget);
+
+/**
+ * Allocate/release memories outsize main driver structure
+ *
+ * @param bp
+ *
+ * @return int
+ */
+int __devinit bnx2x_alloc_mem_bp(struct bnx2x *bp);
+void bnx2x_free_mem_bp(struct bnx2x *bp);
+
+/**
+ * Change mtu netdev callback
+ *
+ * @param dev
+ * @param new_mtu
+ *
+ * @return int
+ */
+int bnx2x_change_mtu(struct net_device *dev, int new_mtu);
+
+/**
+ * tx timeout netdev callback
+ *
+ * @param dev
+ * @param new_mtu
+ *
+ * @return int
+ */
+void bnx2x_tx_timeout(struct net_device *dev);
+
+#ifdef BCM_VLAN
+/**
+ * vlan rx register netdev callback
+ *
+ * @param dev
+ * @param new_mtu
+ *
+ * @return int
+ */
+void bnx2x_vlan_rx_register(struct net_device *dev,
+ struct vlan_group *vlgrp);
+
+#endif
static inline void bnx2x_update_fpsb_idx(struct bnx2x_fastpath *fp)
{
- struct host_status_block *fpsb = fp->status_blk;
-
barrier(); /* status block is written to by the chip */
- fp->fp_c_idx = fpsb->c_status_block.status_block_index;
- fp->fp_u_idx = fpsb->u_status_block.status_block_index;
+ fp->fp_hc_idx = fp->sb_running_index[SM_RX_ID];
}
static inline void bnx2x_update_rx_prod(struct bnx2x *bp,
@@ -334,8 +487,8 @@ static inline void bnx2x_update_rx_prod(struct bnx2x *bp,
wmb();
for (i = 0; i < sizeof(struct ustorm_eth_rx_producers)/4; i++)
- REG_WR(bp, BAR_USTRORM_INTMEM +
- USTORM_RX_PRODS_OFFSET(BP_PORT(bp), fp->cl_id) + i*4,
+ REG_WR(bp,
+ BAR_USTRORM_INTMEM + fp->ustorm_rx_prods_offset + i*4,
((u32 *)&rx_prods)[i]);
mmiowb(); /* keep prod updates ordered */
@@ -345,10 +498,77 @@ static inline void bnx2x_update_rx_prod(struct bnx2x *bp,
fp->index, bd_prod, rx_comp_prod, rx_sge_prod);
}
+static inline void bnx2x_igu_ack_sb_gen(struct bnx2x *bp, u8 igu_sb_id,
+ u8 segment, u16 index, u8 op,
+ u8 update, u32 igu_addr)
+{
+ struct igu_regular cmd_data = {0};
+
+ cmd_data.sb_id_and_flags =
+ ((index << IGU_REGULAR_SB_INDEX_SHIFT) |
+ (segment << IGU_REGULAR_SEGMENT_ACCESS_SHIFT) |
+ (update << IGU_REGULAR_BUPDATE_SHIFT) |
+ (op << IGU_REGULAR_ENABLE_INT_SHIFT));
+
+ DP(NETIF_MSG_HW, "write 0x%08x to IGU addr 0x%x\n",
+ cmd_data.sb_id_and_flags, igu_addr);
+ REG_WR(bp, igu_addr, cmd_data.sb_id_and_flags);
+
+ /* Make sure that ACK is written */
+ mmiowb();
+ barrier();
+}
+
+static inline void bnx2x_igu_clear_sb_gen(struct bnx2x *bp,
+ u8 idu_sb_id, bool is_Pf)
+{
+ u32 data, ctl, cnt = 100;
+ u32 igu_addr_data = IGU_REG_COMMAND_REG_32LSB_DATA;
+ u32 igu_addr_ctl = IGU_REG_COMMAND_REG_CTRL;
+ u32 igu_addr_ack = IGU_REG_CSTORM_TYPE_0_SB_CLEANUP + (idu_sb_id/32)*4;
+ u32 sb_bit = 1 << (idu_sb_id%32);
+ u32 func_encode = BP_FUNC(bp) |
+ ((is_Pf == true ? 1 : 0) << IGU_FID_ENCODE_IS_PF_SHIFT);
+ u32 addr_encode = IGU_CMD_E2_PROD_UPD_BASE + idu_sb_id;
+
+ /* Not supported in BC mode */
+ if (CHIP_INT_MODE_IS_BC(bp))
+ return;
+
+ data = (IGU_USE_REGISTER_cstorm_type_0_sb_cleanup
+ << IGU_REGULAR_CLEANUP_TYPE_SHIFT) |
+ IGU_REGULAR_CLEANUP_SET |
+ IGU_REGULAR_BCLEANUP;
+
+ ctl = addr_encode << IGU_CTRL_REG_ADDRESS_SHIFT |
+ func_encode << IGU_CTRL_REG_FID_SHIFT |
+ IGU_CTRL_CMD_TYPE_WR << IGU_CTRL_REG_TYPE_SHIFT;
+
+ DP(NETIF_MSG_HW, "write 0x%08x to IGU(via GRC) addr 0x%x\n",
+ data, igu_addr_data);
+ REG_WR(bp, igu_addr_data, data);
+ mmiowb();
+ barrier();
+ DP(NETIF_MSG_HW, "write 0x%08x to IGU(via GRC) addr 0x%x\n",
+ ctl, igu_addr_ctl);
+ REG_WR(bp, igu_addr_ctl, ctl);
+ mmiowb();
+ barrier();
+
+ /* wait for clean up to finish */
+ while (!(REG_RD(bp, igu_addr_ack) & sb_bit) && --cnt)
+ msleep(20);
+
+ if (!(REG_RD(bp, igu_addr_ack) & sb_bit)) {
+ DP(NETIF_MSG_HW, "Unable to finish IGU cleanup: "
+ "idu_sb_id %d offset %d bit %d (cnt %d)\n",
+ idu_sb_id, idu_sb_id/32, idu_sb_id%32, cnt);
+ }
+}
-static inline void bnx2x_ack_sb(struct bnx2x *bp, u8 sb_id,
- u8 storm, u16 index, u8 op, u8 update)
+static inline void bnx2x_hc_ack_sb(struct bnx2x *bp, u8 sb_id,
+ u8 storm, u16 index, u8 op, u8 update)
{
u32 hc_addr = (HC_REG_COMMAND_REG + BP_PORT(bp)*32 +
COMMAND_REG_INT_ACK);
@@ -369,7 +589,37 @@ static inline void bnx2x_ack_sb(struct bnx2x *bp, u8 sb_id,
mmiowb();
barrier();
}
-static inline u16 bnx2x_ack_int(struct bnx2x *bp)
+
+static inline void bnx2x_igu_ack_sb(struct bnx2x *bp, u8 igu_sb_id, u8 segment,
+ u16 index, u8 op, u8 update)
+{
+ u32 igu_addr = BAR_IGU_INTMEM + (IGU_CMD_INT_ACK_BASE + igu_sb_id)*8;
+
+ bnx2x_igu_ack_sb_gen(bp, igu_sb_id, segment, index, op, update,
+ igu_addr);
+}
+
+static inline void bnx2x_ack_sb(struct bnx2x *bp, u8 igu_sb_id, u8 storm,
+ u16 index, u8 op, u8 update)
+{
+ if (bp->common.int_block == INT_BLOCK_HC)
+ bnx2x_hc_ack_sb(bp, igu_sb_id, storm, index, op, update);
+ else {
+ u8 segment;
+
+ if (CHIP_INT_MODE_IS_BC(bp))
+ segment = storm;
+ else if (igu_sb_id != bp->igu_dsb_id)
+ segment = IGU_SEG_ACCESS_DEF;
+ else if (storm == ATTENTION_ID)
+ segment = IGU_SEG_ACCESS_ATTN;
+ else
+ segment = IGU_SEG_ACCESS_DEF;
+ bnx2x_igu_ack_sb(bp, igu_sb_id, segment, index, op, update);
+ }
+}
+
+static inline u16 bnx2x_hc_ack_int(struct bnx2x *bp)
{
u32 hc_addr = (HC_REG_COMMAND_REG + BP_PORT(bp)*32 +
COMMAND_REG_SIMD_MASK);
@@ -378,18 +628,36 @@ static inline u16 bnx2x_ack_int(struct bnx2x *bp)
DP(BNX2X_MSG_OFF, "read 0x%08x from HC addr 0x%x\n",
result, hc_addr);
+ barrier();
return result;
}
-/*
- * fast path service functions
- */
+static inline u16 bnx2x_igu_ack_int(struct bnx2x *bp)
+{
+ u32 igu_addr = (BAR_IGU_INTMEM + IGU_REG_SISR_MDPC_WMASK_LSB_UPPER*8);
+ u32 result = REG_RD(bp, igu_addr);
+
+ DP(NETIF_MSG_HW, "read 0x%08x from IGU addr 0x%x\n",
+ result, igu_addr);
+
+ barrier();
+ return result;
+}
+
+static inline u16 bnx2x_ack_int(struct bnx2x *bp)
+{
+ barrier();
+ if (bp->common.int_block == INT_BLOCK_HC)
+ return bnx2x_hc_ack_int(bp);
+ else
+ return bnx2x_igu_ack_int(bp);
+}
static inline int bnx2x_has_tx_work_unload(struct bnx2x_fastpath *fp)
{
/* Tell compiler that consumer and producer can change */
barrier();
- return (fp->tx_pkt_prod != fp->tx_pkt_cons);
+ return fp->tx_pkt_prod != fp->tx_pkt_cons;
}
static inline u16 bnx2x_tx_avail(struct bnx2x_fastpath *fp)
@@ -424,6 +692,29 @@ static inline int bnx2x_has_tx_work(struct bnx2x_fastpath *fp)
return hw_cons != fp->tx_pkt_cons;
}
+static inline int bnx2x_has_rx_work(struct bnx2x_fastpath *fp)
+{
+ u16 rx_cons_sb;
+
+ /* Tell compiler that status block fields can change */
+ barrier();
+ rx_cons_sb = le16_to_cpu(*fp->rx_cons_sb);
+ if ((rx_cons_sb & MAX_RCQ_DESC_CNT) == MAX_RCQ_DESC_CNT)
+ rx_cons_sb++;
+ return (fp->rx_comp_cons != rx_cons_sb);
+}
+
+/**
+ * disables tx from stack point of view
+ *
+ * @param bp
+ */
+static inline void bnx2x_tx_disable(struct bnx2x *bp)
+{
+ netif_tx_disable(bp->dev);
+ netif_carrier_off(bp->dev);
+}
+
static inline void bnx2x_free_rx_sge(struct bnx2x *bp,
struct bnx2x_fastpath *fp, u16 index)
{
@@ -436,7 +727,7 @@ static inline void bnx2x_free_rx_sge(struct bnx2x *bp,
return;
dma_unmap_page(&bp->pdev->dev, dma_unmap_addr(sw_buf, mapping),
- SGE_PAGE_SIZE*PAGES_PER_SGE, PCI_DMA_FROMDEVICE);
+ SGE_PAGE_SIZE*PAGES_PER_SGE, DMA_FROM_DEVICE);
__free_pages(page, PAGES_PER_SGE_SHIFT);
sw_buf->page = NULL;
@@ -444,13 +735,67 @@ static inline void bnx2x_free_rx_sge(struct bnx2x *bp,
sge->addr_lo = 0;
}
-static inline void bnx2x_free_rx_sge_range(struct bnx2x *bp,
- struct bnx2x_fastpath *fp, int last)
+static inline void bnx2x_add_all_napi(struct bnx2x *bp)
{
int i;
- for (i = 0; i < last; i++)
- bnx2x_free_rx_sge(bp, fp, i);
+ /* Add NAPI objects */
+ for_each_queue(bp, i)
+ netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi),
+ bnx2x_poll, BNX2X_NAPI_WEIGHT);
+}
+
+static inline void bnx2x_del_all_napi(struct bnx2x *bp)
+{
+ int i;
+
+ for_each_queue(bp, i)
+ netif_napi_del(&bnx2x_fp(bp, i, napi));
+}
+
+static inline void bnx2x_disable_msi(struct bnx2x *bp)
+{
+ if (bp->flags & USING_MSIX_FLAG) {
+ pci_disable_msix(bp->pdev);
+ bp->flags &= ~USING_MSIX_FLAG;
+ } else if (bp->flags & USING_MSI_FLAG) {
+ pci_disable_msi(bp->pdev);
+ bp->flags &= ~USING_MSI_FLAG;
+ }
+}
+
+static inline int bnx2x_calc_num_queues(struct bnx2x *bp)
+{
+ return num_queues ?
+ min_t(int, num_queues, BNX2X_MAX_QUEUES(bp)) :
+ min_t(int, num_online_cpus(), BNX2X_MAX_QUEUES(bp));
+}
+
+static inline void bnx2x_clear_sge_mask_next_elems(struct bnx2x_fastpath *fp)
+{
+ int i, j;
+
+ for (i = 1; i <= NUM_RX_SGE_PAGES; i++) {
+ int idx = RX_SGE_CNT * i - 1;
+
+ for (j = 0; j < 2; j++) {
+ SGE_MASK_CLEAR_BIT(fp, idx);
+ idx--;
+ }
+ }
+}
+
+static inline void bnx2x_init_sge_ring_bit_mask(struct bnx2x_fastpath *fp)
+{
+ /* Set the mask to all 1-s: it's faster to compare to 0 than to 0xf-s */
+ memset(fp->sge_mask, 0xff,
+ (NUM_RX_SGE >> RX_SGE_MASK_ELEM_SHIFT)*sizeof(u64));
+
+ /* Clear the two last indices in the page to 1:
+ these are the indices that correspond to the "next" element,
+ hence will never be indicated and should be removed from
+ the calculations. */
+ bnx2x_clear_sge_mask_next_elems(fp);
}
static inline int bnx2x_alloc_rx_sge(struct bnx2x *bp,
@@ -479,6 +824,7 @@ static inline int bnx2x_alloc_rx_sge(struct bnx2x *bp,
return 0;
}
+
static inline int bnx2x_alloc_rx_skb(struct bnx2x *bp,
struct bnx2x_fastpath *fp, u16 index)
{
@@ -513,7 +859,7 @@ static inline int bnx2x_alloc_rx_skb(struct bnx2x *bp,
* so there is no need to check for dma_mapping_error().
*/
static inline void bnx2x_reuse_rx_skb(struct bnx2x_fastpath *fp,
- struct sk_buff *skb, u16 cons, u16 prod)
+ u16 cons, u16 prod)
{
struct bnx2x *bp = fp->bp;
struct sw_rx_bd *cons_rx_buf = &fp->rx_buf_ring[cons];
@@ -531,32 +877,15 @@ static inline void bnx2x_reuse_rx_skb(struct bnx2x_fastpath *fp,
*prod_bd = *cons_bd;
}
-static inline void bnx2x_clear_sge_mask_next_elems(struct bnx2x_fastpath *fp)
+static inline void bnx2x_free_rx_sge_range(struct bnx2x *bp,
+ struct bnx2x_fastpath *fp, int last)
{
- int i, j;
-
- for (i = 1; i <= NUM_RX_SGE_PAGES; i++) {
- int idx = RX_SGE_CNT * i - 1;
+ int i;
- for (j = 0; j < 2; j++) {
- SGE_MASK_CLEAR_BIT(fp, idx);
- idx--;
- }
- }
+ for (i = 0; i < last; i++)
+ bnx2x_free_rx_sge(bp, fp, i);
}
-static inline void bnx2x_init_sge_ring_bit_mask(struct bnx2x_fastpath *fp)
-{
- /* Set the mask to all 1-s: it's faster to compare to 0 than to 0xf-s */
- memset(fp->sge_mask, 0xff,
- (NUM_RX_SGE >> RX_SGE_MASK_ELEM_SHIFT)*sizeof(u64));
-
- /* Clear the two last indices in the page to 1:
- these are the indices that correspond to the "next" element,
- hence will never be indicated and should be removed from
- the calculations. */
- bnx2x_clear_sge_mask_next_elems(fp);
-}
static inline void bnx2x_free_tpa_pool(struct bnx2x *bp,
struct bnx2x_fastpath *fp, int last)
{
@@ -582,7 +911,7 @@ static inline void bnx2x_free_tpa_pool(struct bnx2x *bp,
}
-static inline void bnx2x_init_tx_ring(struct bnx2x *bp)
+static inline void bnx2x_init_tx_rings(struct bnx2x *bp)
{
int i, j;
@@ -601,7 +930,7 @@ static inline void bnx2x_init_tx_ring(struct bnx2x *bp)
BCM_PAGE_SIZE*(i % NUM_TX_RINGS)));
}
- fp->tx_db.data.header.header = DOORBELL_HDR_DB_TYPE;
+ SET_FLAG(fp->tx_db.data.header.header, DOORBELL_HDR_DB_TYPE, 1);
fp->tx_db.data.zero_fill1 = 0;
fp->tx_db.data.prod = 0;
@@ -609,44 +938,98 @@ static inline void bnx2x_init_tx_ring(struct bnx2x *bp)
fp->tx_pkt_cons = 0;
fp->tx_bd_prod = 0;
fp->tx_bd_cons = 0;
- fp->tx_cons_sb = BNX2X_TX_SB_INDEX;
fp->tx_pkt = 0;
}
}
-static inline int bnx2x_has_rx_work(struct bnx2x_fastpath *fp)
+
+static inline void bnx2x_set_next_page_rx_bd(struct bnx2x_fastpath *fp)
{
- u16 rx_cons_sb;
+ int i;
- /* Tell compiler that status block fields can change */
- barrier();
- rx_cons_sb = le16_to_cpu(*fp->rx_cons_sb);
- if ((rx_cons_sb & MAX_RCQ_DESC_CNT) == MAX_RCQ_DESC_CNT)
- rx_cons_sb++;
- return (fp->rx_comp_cons != rx_cons_sb);
+ for (i = 1; i <= NUM_RX_RINGS; i++) {
+ struct eth_rx_bd *rx_bd;
+
+ rx_bd = &fp->rx_desc_ring[RX_DESC_CNT * i - 2];
+ rx_bd->addr_hi =
+ cpu_to_le32(U64_HI(fp->rx_desc_mapping +
+ BCM_PAGE_SIZE*(i % NUM_RX_RINGS)));
+ rx_bd->addr_lo =
+ cpu_to_le32(U64_LO(fp->rx_desc_mapping +
+ BCM_PAGE_SIZE*(i % NUM_RX_RINGS)));
+ }
+}
+
+static inline void bnx2x_set_next_page_sgl(struct bnx2x_fastpath *fp)
+{
+ int i;
+
+ for (i = 1; i <= NUM_RX_SGE_PAGES; i++) {
+ struct eth_rx_sge *sge;
+
+ sge = &fp->rx_sge_ring[RX_SGE_CNT * i - 2];
+ sge->addr_hi =
+ cpu_to_le32(U64_HI(fp->rx_sge_mapping +
+ BCM_PAGE_SIZE*(i % NUM_RX_SGE_PAGES)));
+
+ sge->addr_lo =
+ cpu_to_le32(U64_LO(fp->rx_sge_mapping +
+ BCM_PAGE_SIZE*(i % NUM_RX_SGE_PAGES)));
+ }
+}
+
+static inline void bnx2x_set_next_page_rx_cq(struct bnx2x_fastpath *fp)
+{
+ int i;
+ for (i = 1; i <= NUM_RCQ_RINGS; i++) {
+ struct eth_rx_cqe_next_page *nextpg;
+
+ nextpg = (struct eth_rx_cqe_next_page *)
+ &fp->rx_comp_ring[RCQ_DESC_CNT * i - 1];
+ nextpg->addr_hi =
+ cpu_to_le32(U64_HI(fp->rx_comp_mapping +
+ BCM_PAGE_SIZE*(i % NUM_RCQ_RINGS)));
+ nextpg->addr_lo =
+ cpu_to_le32(U64_LO(fp->rx_comp_mapping +
+ BCM_PAGE_SIZE*(i % NUM_RCQ_RINGS)));
+ }
+}
+
+
+
+static inline void __storm_memset_struct(struct bnx2x *bp,
+ u32 addr, size_t size, u32 *data)
+{
+ int i;
+ for (i = 0; i < size/4; i++)
+ REG_WR(bp, addr + (i * 4), data[i]);
+}
+
+static inline void storm_memset_mac_filters(struct bnx2x *bp,
+ struct tstorm_eth_mac_filter_config *mac_filters,
+ u16 abs_fid)
+{
+ size_t size = sizeof(struct tstorm_eth_mac_filter_config);
+
+ u32 addr = BAR_TSTRORM_INTMEM +
+ TSTORM_MAC_FILTER_CONFIG_OFFSET(abs_fid);
+
+ __storm_memset_struct(bp, addr, size, (u32 *)mac_filters);
+}
+
+static inline void storm_memset_cmng(struct bnx2x *bp,
+ struct cmng_struct_per_port *cmng,
+ u8 port)
+{
+ size_t size = sizeof(struct cmng_struct_per_port);
+
+ u32 addr = BAR_XSTRORM_INTMEM +
+ XSTORM_CMNG_PER_PORT_VARS_OFFSET(port);
+
+ __storm_memset_struct(bp, addr, size, (u32 *)cmng);
}
/* HW Lock for shared dual port PHYs */
void bnx2x_acquire_phy_lock(struct bnx2x *bp);
void bnx2x_release_phy_lock(struct bnx2x *bp);
-void bnx2x_link_report(struct bnx2x *bp);
-int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget);
-int bnx2x_tx_int(struct bnx2x_fastpath *fp);
-void bnx2x_init_rx_rings(struct bnx2x *bp);
-netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev);
-
-int bnx2x_change_mac_addr(struct net_device *dev, void *p);
-void bnx2x_tx_timeout(struct net_device *dev);
-void bnx2x_vlan_rx_register(struct net_device *dev, struct vlan_group *vlgrp);
-void bnx2x_netif_start(struct bnx2x *bp);
-void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw);
-void bnx2x_free_irq(struct bnx2x *bp, bool disable_only);
-int bnx2x_suspend(struct pci_dev *pdev, pm_message_t state);
-int bnx2x_resume(struct pci_dev *pdev);
-void bnx2x_free_skbs(struct bnx2x *bp);
-int bnx2x_change_mtu(struct net_device *dev, int new_mtu);
-int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode);
-int bnx2x_nic_load(struct bnx2x *bp, int load_mode);
-int bnx2x_set_power_state(struct bnx2x *bp, pci_power_t state);
-
#endif /* BNX2X_CMN_H */
diff --git a/drivers/net/bnx2x/bnx2x_dump.h b/drivers/net/bnx2x/bnx2x_dump.h
index 3bb9a91bb3f7..dc18c25ca9e5 100644
--- a/drivers/net/bnx2x/bnx2x_dump.h
+++ b/drivers/net/bnx2x/bnx2x_dump.h
@@ -31,14 +31,24 @@ struct dump_sign {
#define RI_E1 0x1
#define RI_E1H 0x2
+#define RI_E2 0x4
#define RI_ONLINE 0x100
-
+#define RI_PATH0_DUMP 0x200
+#define RI_PATH1_DUMP 0x400
#define RI_E1_OFFLINE (RI_E1)
#define RI_E1_ONLINE (RI_E1 | RI_ONLINE)
#define RI_E1H_OFFLINE (RI_E1H)
#define RI_E1H_ONLINE (RI_E1H | RI_ONLINE)
-#define RI_ALL_OFFLINE (RI_E1 | RI_E1H)
-#define RI_ALL_ONLINE (RI_E1 | RI_E1H | RI_ONLINE)
+#define RI_E2_OFFLINE (RI_E2)
+#define RI_E2_ONLINE (RI_E2 | RI_ONLINE)
+#define RI_E1E1H_OFFLINE (RI_E1 | RI_E1H)
+#define RI_E1E1H_ONLINE (RI_E1 | RI_E1H | RI_ONLINE)
+#define RI_E1HE2_OFFLINE (RI_E2 | RI_E1H)
+#define RI_E1HE2_ONLINE (RI_E2 | RI_E1H | RI_ONLINE)
+#define RI_E1E2_OFFLINE (RI_E2 | RI_E1)
+#define RI_E1E2_ONLINE (RI_E2 | RI_E1 | RI_ONLINE)
+#define RI_ALL_OFFLINE (RI_E1 | RI_E1H | RI_E2)
+#define RI_ALL_ONLINE (RI_E1 | RI_E1H | RI_E2 | RI_ONLINE)
#define MAX_TIMER_PENDING 200
#define TIMER_SCAN_DONT_CARE 0xFF
@@ -513,6 +523,12 @@ static const struct wreg_addr wreg_addrs_e1h[WREGS_COUNT_E1H] = {
{ 0x1b0c00, 256, 2, read_reg_e1h_0, RI_E1H_OFFLINE }
};
+#define WREGS_COUNT_E2 1
+static const u32 read_reg_e2_0[] = { 0x1b1040, 0x1b1000 };
+
+static const struct wreg_addr wreg_addrs_e2[WREGS_COUNT_E2] = {
+ { 0x1b0c00, 128, 2, read_reg_e2_0, RI_E2_OFFLINE }
+};
static const struct dump_sign dump_sign_all = { 0x49aa93ee, 0x40835, 0x22 };
@@ -531,4 +547,17 @@ static const u32 timer_scan_regs_e1h[TIMER_REGS_COUNT_E1H] =
{ 0x1640d0, 0x1640d4 };
+#define PAGE_MODE_VALUES_E2 2
+
+#define PAGE_READ_REGS_E2 1
+
+#define PAGE_WRITE_REGS_E2 1
+
+static const u32 page_vals_e2[PAGE_MODE_VALUES_E2] = { 0, 128 };
+
+static const u32 page_write_regs_e2[PAGE_WRITE_REGS_E2] = { 328476 };
+
+static const struct reg_addr page_read_regs_e2[PAGE_READ_REGS_E2] = {
+ { 0x58000, 4608, RI_E2_ONLINE } };
+
#endif /* BNX2X_DUMP_H */
diff --git a/drivers/net/bnx2x/bnx2x_ethtool.c b/drivers/net/bnx2x/bnx2x_ethtool.c
index 8b75b05e34c5..d02ffbdc9f0e 100644
--- a/drivers/net/bnx2x/bnx2x_ethtool.c
+++ b/drivers/net/bnx2x/bnx2x_ethtool.c
@@ -25,70 +25,46 @@
#include "bnx2x_cmn.h"
#include "bnx2x_dump.h"
-
static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct bnx2x *bp = netdev_priv(dev);
-
- cmd->supported = bp->port.supported;
- cmd->advertising = bp->port.advertising;
+ int cfg_idx = bnx2x_get_link_cfg_idx(bp);
+ /* Dual Media boards present all available port types */
+ cmd->supported = bp->port.supported[cfg_idx] |
+ (bp->port.supported[cfg_idx ^ 1] &
+ (SUPPORTED_TP | SUPPORTED_FIBRE));
+ cmd->advertising = bp->port.advertising[cfg_idx];
if ((bp->state == BNX2X_STATE_OPEN) &&
!(bp->flags & MF_FUNC_DIS) &&
(bp->link_vars.link_up)) {
cmd->speed = bp->link_vars.line_speed;
cmd->duplex = bp->link_vars.duplex;
- if (IS_E1HMF(bp)) {
- u16 vn_max_rate;
-
- vn_max_rate =
- ((bp->mf_config & FUNC_MF_CFG_MAX_BW_MASK) >>
- FUNC_MF_CFG_MAX_BW_SHIFT) * 100;
- if (vn_max_rate < cmd->speed)
- cmd->speed = vn_max_rate;
- }
} else {
- cmd->speed = -1;
- cmd->duplex = -1;
- }
-
- if (bp->link_params.switch_cfg == SWITCH_CFG_10G) {
- u32 ext_phy_type =
- XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config);
-
- switch (ext_phy_type) {
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
- cmd->port = PORT_FIBRE;
- break;
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481:
- cmd->port = PORT_TP;
- break;
+ cmd->speed = bp->link_params.req_line_speed[cfg_idx];
+ cmd->duplex = bp->link_params.req_duplex[cfg_idx];
+ }
+ if (IS_MF(bp)) {
+ u16 vn_max_rate = ((bp->mf_config[BP_VN(bp)] &
+ FUNC_MF_CFG_MAX_BW_MASK) >> FUNC_MF_CFG_MAX_BW_SHIFT) *
+ 100;
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
- BNX2X_ERR("XGXS PHY Failure detected 0x%x\n",
- bp->link_params.ext_phy_config);
- break;
+ if (vn_max_rate < cmd->speed)
+ cmd->speed = vn_max_rate;
+ }
- default:
- DP(NETIF_MSG_LINK, "BAD XGXS ext_phy_config 0x%x\n",
- bp->link_params.ext_phy_config);
- break;
- }
- } else
+ if (bp->port.supported[cfg_idx] & SUPPORTED_TP)
cmd->port = PORT_TP;
+ else if (bp->port.supported[cfg_idx] & SUPPORTED_FIBRE)
+ cmd->port = PORT_FIBRE;
+ else
+ BNX2X_ERR("XGXS PHY Failure detected\n");
cmd->phy_address = bp->mdio.prtad;
cmd->transceiver = XCVR_INTERNAL;
- if (bp->link_params.req_line_speed == SPEED_AUTO_NEG)
+ if (bp->link_params.req_line_speed[cfg_idx] == SPEED_AUTO_NEG)
cmd->autoneg = AUTONEG_ENABLE;
else
cmd->autoneg = AUTONEG_DISABLE;
@@ -110,9 +86,9 @@ static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct bnx2x *bp = netdev_priv(dev);
- u32 advertising;
+ u32 advertising, cfg_idx, old_multi_phy_config, new_multi_phy_config;
- if (IS_E1HMF(bp))
+ if (IS_MF(bp))
return 0;
DP(NETIF_MSG_LINK, "ethtool_cmd: cmd %d\n"
@@ -123,26 +99,81 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
cmd->duplex, cmd->port, cmd->phy_address, cmd->transceiver,
cmd->autoneg, cmd->maxtxpkt, cmd->maxrxpkt);
+ cfg_idx = bnx2x_get_link_cfg_idx(bp);
+ old_multi_phy_config = bp->link_params.multi_phy_config;
+ switch (cmd->port) {
+ case PORT_TP:
+ if (bp->port.supported[cfg_idx] & SUPPORTED_TP)
+ break; /* no port change */
+
+ if (!(bp->port.supported[0] & SUPPORTED_TP ||
+ bp->port.supported[1] & SUPPORTED_TP)) {
+ DP(NETIF_MSG_LINK, "Unsupported port type\n");
+ return -EINVAL;
+ }
+ bp->link_params.multi_phy_config &=
+ ~PORT_HW_CFG_PHY_SELECTION_MASK;
+ if (bp->link_params.multi_phy_config &
+ PORT_HW_CFG_PHY_SWAPPED_ENABLED)
+ bp->link_params.multi_phy_config |=
+ PORT_HW_CFG_PHY_SELECTION_SECOND_PHY;
+ else
+ bp->link_params.multi_phy_config |=
+ PORT_HW_CFG_PHY_SELECTION_FIRST_PHY;
+ break;
+ case PORT_FIBRE:
+ if (bp->port.supported[cfg_idx] & SUPPORTED_FIBRE)
+ break; /* no port change */
+
+ if (!(bp->port.supported[0] & SUPPORTED_FIBRE ||
+ bp->port.supported[1] & SUPPORTED_FIBRE)) {
+ DP(NETIF_MSG_LINK, "Unsupported port type\n");
+ return -EINVAL;
+ }
+ bp->link_params.multi_phy_config &=
+ ~PORT_HW_CFG_PHY_SELECTION_MASK;
+ if (bp->link_params.multi_phy_config &
+ PORT_HW_CFG_PHY_SWAPPED_ENABLED)
+ bp->link_params.multi_phy_config |=
+ PORT_HW_CFG_PHY_SELECTION_FIRST_PHY;
+ else
+ bp->link_params.multi_phy_config |=
+ PORT_HW_CFG_PHY_SELECTION_SECOND_PHY;
+ break;
+ default:
+ DP(NETIF_MSG_LINK, "Unsupported port type\n");
+ return -EINVAL;
+ }
+ /* Save new config in case command complete successuly */
+ new_multi_phy_config = bp->link_params.multi_phy_config;
+ /* Get the new cfg_idx */
+ cfg_idx = bnx2x_get_link_cfg_idx(bp);
+ /* Restore old config in case command failed */
+ bp->link_params.multi_phy_config = old_multi_phy_config;
+ DP(NETIF_MSG_LINK, "cfg_idx = %x\n", cfg_idx);
+
if (cmd->autoneg == AUTONEG_ENABLE) {
- if (!(bp->port.supported & SUPPORTED_Autoneg)) {
+ if (!(bp->port.supported[cfg_idx] & SUPPORTED_Autoneg)) {
DP(NETIF_MSG_LINK, "Autoneg not supported\n");
return -EINVAL;
}
/* advertise the requested speed and duplex if supported */
- cmd->advertising &= bp->port.supported;
+ cmd->advertising &= bp->port.supported[cfg_idx];
- bp->link_params.req_line_speed = SPEED_AUTO_NEG;
- bp->link_params.req_duplex = DUPLEX_FULL;
- bp->port.advertising |= (ADVERTISED_Autoneg |
+ bp->link_params.req_line_speed[cfg_idx] = SPEED_AUTO_NEG;
+ bp->link_params.req_duplex[cfg_idx] = DUPLEX_FULL;
+ bp->port.advertising[cfg_idx] |= (ADVERTISED_Autoneg |
cmd->advertising);
} else { /* forced speed */
/* advertise the requested speed and duplex if supported */
- switch (cmd->speed) {
+ u32 speed = cmd->speed;
+ speed |= (cmd->speed_hi << 16);
+ switch (speed) {
case SPEED_10:
if (cmd->duplex == DUPLEX_FULL) {
- if (!(bp->port.supported &
+ if (!(bp->port.supported[cfg_idx] &
SUPPORTED_10baseT_Full)) {
DP(NETIF_MSG_LINK,
"10M full not supported\n");
@@ -152,7 +183,7 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
advertising = (ADVERTISED_10baseT_Full |
ADVERTISED_TP);
} else {
- if (!(bp->port.supported &
+ if (!(bp->port.supported[cfg_idx] &
SUPPORTED_10baseT_Half)) {
DP(NETIF_MSG_LINK,
"10M half not supported\n");
@@ -166,7 +197,7 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
case SPEED_100:
if (cmd->duplex == DUPLEX_FULL) {
- if (!(bp->port.supported &
+ if (!(bp->port.supported[cfg_idx] &
SUPPORTED_100baseT_Full)) {
DP(NETIF_MSG_LINK,
"100M full not supported\n");
@@ -176,7 +207,7 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
advertising = (ADVERTISED_100baseT_Full |
ADVERTISED_TP);
} else {
- if (!(bp->port.supported &
+ if (!(bp->port.supported[cfg_idx] &
SUPPORTED_100baseT_Half)) {
DP(NETIF_MSG_LINK,
"100M half not supported\n");
@@ -194,7 +225,8 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
return -EINVAL;
}
- if (!(bp->port.supported & SUPPORTED_1000baseT_Full)) {
+ if (!(bp->port.supported[cfg_idx] &
+ SUPPORTED_1000baseT_Full)) {
DP(NETIF_MSG_LINK, "1G full not supported\n");
return -EINVAL;
}
@@ -210,7 +242,8 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
return -EINVAL;
}
- if (!(bp->port.supported & SUPPORTED_2500baseX_Full)) {
+ if (!(bp->port.supported[cfg_idx]
+ & SUPPORTED_2500baseX_Full)) {
DP(NETIF_MSG_LINK,
"2.5G full not supported\n");
return -EINVAL;
@@ -226,7 +259,8 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
return -EINVAL;
}
- if (!(bp->port.supported & SUPPORTED_10000baseT_Full)) {
+ if (!(bp->port.supported[cfg_idx]
+ & SUPPORTED_10000baseT_Full)) {
DP(NETIF_MSG_LINK, "10G full not supported\n");
return -EINVAL;
}
@@ -236,20 +270,23 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
break;
default:
- DP(NETIF_MSG_LINK, "Unsupported speed\n");
+ DP(NETIF_MSG_LINK, "Unsupported speed %d\n", speed);
return -EINVAL;
}
- bp->link_params.req_line_speed = cmd->speed;
- bp->link_params.req_duplex = cmd->duplex;
- bp->port.advertising = advertising;
+ bp->link_params.req_line_speed[cfg_idx] = speed;
+ bp->link_params.req_duplex[cfg_idx] = cmd->duplex;
+ bp->port.advertising[cfg_idx] = advertising;
}
DP(NETIF_MSG_LINK, "req_line_speed %d\n"
DP_LEVEL " req_duplex %d advertising 0x%x\n",
- bp->link_params.req_line_speed, bp->link_params.req_duplex,
- bp->port.advertising);
+ bp->link_params.req_line_speed[cfg_idx],
+ bp->link_params.req_duplex[cfg_idx],
+ bp->port.advertising[cfg_idx]);
+ /* Set new config */
+ bp->link_params.multi_phy_config = new_multi_phy_config;
if (netif_running(dev)) {
bnx2x_stats_handle(bp, STATS_EVENT_STOP);
bnx2x_link_set(bp);
@@ -260,6 +297,7 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
#define IS_E1_ONLINE(info) (((info) & RI_E1_ONLINE) == RI_E1_ONLINE)
#define IS_E1H_ONLINE(info) (((info) & RI_E1H_ONLINE) == RI_E1H_ONLINE)
+#define IS_E2_ONLINE(info) (((info) & RI_E2_ONLINE) == RI_E2_ONLINE)
static int bnx2x_get_regs_len(struct net_device *dev)
{
@@ -277,7 +315,7 @@ static int bnx2x_get_regs_len(struct net_device *dev)
regdump_len += wreg_addrs_e1[i].size *
(1 + wreg_addrs_e1[i].read_regs_count);
- } else { /* E1H */
+ } else if (CHIP_IS_E1H(bp)) {
for (i = 0; i < REGS_COUNT; i++)
if (IS_E1H_ONLINE(reg_addrs[i].info))
regdump_len += reg_addrs[i].size;
@@ -286,6 +324,15 @@ static int bnx2x_get_regs_len(struct net_device *dev)
if (IS_E1H_ONLINE(wreg_addrs_e1h[i].info))
regdump_len += wreg_addrs_e1h[i].size *
(1 + wreg_addrs_e1h[i].read_regs_count);
+ } else if (CHIP_IS_E2(bp)) {
+ for (i = 0; i < REGS_COUNT; i++)
+ if (IS_E2_ONLINE(reg_addrs[i].info))
+ regdump_len += reg_addrs[i].size;
+
+ for (i = 0; i < WREGS_COUNT_E2; i++)
+ if (IS_E2_ONLINE(wreg_addrs_e2[i].info))
+ regdump_len += wreg_addrs_e2[i].size *
+ (1 + wreg_addrs_e2[i].read_regs_count);
}
regdump_len *= 4;
regdump_len += sizeof(struct dump_hdr);
@@ -293,6 +340,23 @@ static int bnx2x_get_regs_len(struct net_device *dev)
return regdump_len;
}
+static inline void bnx2x_read_pages_regs_e2(struct bnx2x *bp, u32 *p)
+{
+ u32 i, j, k, n;
+
+ for (i = 0; i < PAGE_MODE_VALUES_E2; i++) {
+ for (j = 0; j < PAGE_WRITE_REGS_E2; j++) {
+ REG_WR(bp, page_write_regs_e2[j], page_vals_e2[i]);
+ for (k = 0; k < PAGE_READ_REGS_E2; k++)
+ if (IS_E2_ONLINE(page_read_regs_e2[k].info))
+ for (n = 0; n <
+ page_read_regs_e2[k].size; n++)
+ *p++ = REG_RD(bp,
+ page_read_regs_e2[k].addr + n*4);
+ }
+ }
+}
+
static void bnx2x_get_regs(struct net_device *dev,
struct ethtool_regs *regs, void *_p)
{
@@ -312,7 +376,14 @@ static void bnx2x_get_regs(struct net_device *dev,
dump_hdr.tstorm_waitp = REG_RD(bp, TSTORM_WAITP_ADDR);
dump_hdr.ustorm_waitp = REG_RD(bp, USTORM_WAITP_ADDR);
dump_hdr.cstorm_waitp = REG_RD(bp, CSTORM_WAITP_ADDR);
- dump_hdr.info = CHIP_IS_E1(bp) ? RI_E1_ONLINE : RI_E1H_ONLINE;
+
+ if (CHIP_IS_E1(bp))
+ dump_hdr.info = RI_E1_ONLINE;
+ else if (CHIP_IS_E1H(bp))
+ dump_hdr.info = RI_E1H_ONLINE;
+ else if (CHIP_IS_E2(bp))
+ dump_hdr.info = RI_E2_ONLINE |
+ (BP_PATH(bp) ? RI_PATH1_DUMP : RI_PATH0_DUMP);
memcpy(p, &dump_hdr, sizeof(struct dump_hdr));
p += dump_hdr.hdr_size + 1;
@@ -324,16 +395,25 @@ static void bnx2x_get_regs(struct net_device *dev,
*p++ = REG_RD(bp,
reg_addrs[i].addr + j*4);
- } else { /* E1H */
+ } else if (CHIP_IS_E1H(bp)) {
for (i = 0; i < REGS_COUNT; i++)
if (IS_E1H_ONLINE(reg_addrs[i].info))
for (j = 0; j < reg_addrs[i].size; j++)
*p++ = REG_RD(bp,
reg_addrs[i].addr + j*4);
+
+ } else if (CHIP_IS_E2(bp)) {
+ for (i = 0; i < REGS_COUNT; i++)
+ if (IS_E2_ONLINE(reg_addrs[i].info))
+ for (j = 0; j < reg_addrs[i].size; j++)
+ *p++ = REG_RD(bp,
+ reg_addrs[i].addr + j*4);
+
+ bnx2x_read_pages_regs_e2(bp, p);
}
}
-#define PHY_FW_VER_LEN 10
+#define PHY_FW_VER_LEN 20
static void bnx2x_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *info)
@@ -436,7 +516,7 @@ static u32 bnx2x_get_link(struct net_device *dev)
{
struct bnx2x *bp = netdev_priv(dev);
- if (bp->flags & MF_FUNC_DIS)
+ if (bp->flags & MF_FUNC_DIS || (bp->state != BNX2X_STATE_OPEN))
return 0;
return bp->link_vars.link_up;
@@ -811,7 +891,7 @@ static int bnx2x_set_eeprom(struct net_device *dev,
struct bnx2x *bp = netdev_priv(dev);
int port = BP_PORT(bp);
int rc = 0;
-
+ u32 ext_phy_config;
if (!netif_running(dev))
return -EAGAIN;
@@ -827,6 +907,10 @@ static int bnx2x_set_eeprom(struct net_device *dev,
!bp->port.pmf)
return -EINVAL;
+ ext_phy_config =
+ SHMEM_RD(bp,
+ dev_info.port_hw_config[port].external_phy_config);
+
if (eeprom->magic == 0x50485950) {
/* 'PHYP' (0x50485950): prepare phy for FW upgrade */
bnx2x_stats_handle(bp, STATS_EVENT_STOP);
@@ -834,7 +918,7 @@ static int bnx2x_set_eeprom(struct net_device *dev,
bnx2x_acquire_phy_lock(bp);
rc |= bnx2x_link_reset(&bp->link_params,
&bp->link_vars, 0);
- if (XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config) ==
+ if (XGXS_EXT_PHY_TYPE(ext_phy_config) ==
PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101)
bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
MISC_REGISTERS_GPIO_HIGH, port);
@@ -855,10 +939,8 @@ static int bnx2x_set_eeprom(struct net_device *dev,
}
} else if (eeprom->magic == 0x53985943) {
/* 'PHYC' (0x53985943): PHY FW upgrade completed */
- if (XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config) ==
+ if (XGXS_EXT_PHY_TYPE(ext_phy_config) ==
PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101) {
- u8 ext_phy_addr =
- XGXS_EXT_PHY_ADDR(bp->link_params.ext_phy_config);
/* DSP Remove Download Mode */
bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
@@ -866,7 +948,8 @@ static int bnx2x_set_eeprom(struct net_device *dev,
bnx2x_acquire_phy_lock(bp);
- bnx2x_sfx7101_sp_sw_reset(bp, port, ext_phy_addr);
+ bnx2x_sfx7101_sp_sw_reset(bp,
+ &bp->link_params.phy[EXT_PHY1]);
/* wait 0.5 sec to allow it to run */
msleep(500);
@@ -879,6 +962,7 @@ static int bnx2x_set_eeprom(struct net_device *dev,
return rc;
}
+
static int bnx2x_get_coalesce(struct net_device *dev,
struct ethtool_coalesce *coal)
{
@@ -920,7 +1004,14 @@ static void bnx2x_get_ringparam(struct net_device *dev,
ering->rx_mini_max_pending = 0;
ering->rx_jumbo_max_pending = 0;
- ering->rx_pending = bp->rx_ring_size;
+ if (bp->rx_ring_size)
+ ering->rx_pending = bp->rx_ring_size;
+ else
+ if (bp->state == BNX2X_STATE_OPEN && bp->num_queues)
+ ering->rx_pending = MAX_RX_AVAIL/bp->num_queues;
+ else
+ ering->rx_pending = MAX_RX_AVAIL;
+
ering->rx_mini_pending = 0;
ering->rx_jumbo_pending = 0;
@@ -940,6 +1031,7 @@ static int bnx2x_set_ringparam(struct net_device *dev,
}
if ((ering->rx_pending > MAX_RX_AVAIL) ||
+ (ering->rx_pending < MIN_RX_AVAIL) ||
(ering->tx_pending > MAX_TX_AVAIL) ||
(ering->tx_pending <= MAX_SKB_FRAGS + 4))
return -EINVAL;
@@ -959,10 +1051,9 @@ static void bnx2x_get_pauseparam(struct net_device *dev,
struct ethtool_pauseparam *epause)
{
struct bnx2x *bp = netdev_priv(dev);
-
- epause->autoneg = (bp->link_params.req_flow_ctrl ==
- BNX2X_FLOW_CTRL_AUTO) &&
- (bp->link_params.req_line_speed == SPEED_AUTO_NEG);
+ int cfg_idx = bnx2x_get_link_cfg_idx(bp);
+ epause->autoneg = (bp->link_params.req_flow_ctrl[cfg_idx] ==
+ BNX2X_FLOW_CTRL_AUTO);
epause->rx_pause = ((bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_RX) ==
BNX2X_FLOW_CTRL_RX);
@@ -978,37 +1069,39 @@ static int bnx2x_set_pauseparam(struct net_device *dev,
struct ethtool_pauseparam *epause)
{
struct bnx2x *bp = netdev_priv(dev);
-
- if (IS_E1HMF(bp))
+ u32 cfg_idx = bnx2x_get_link_cfg_idx(bp);
+ if (IS_MF(bp))
return 0;
DP(NETIF_MSG_LINK, "ethtool_pauseparam: cmd %d\n"
DP_LEVEL " autoneg %d rx_pause %d tx_pause %d\n",
epause->cmd, epause->autoneg, epause->rx_pause, epause->tx_pause);
- bp->link_params.req_flow_ctrl = BNX2X_FLOW_CTRL_AUTO;
+ bp->link_params.req_flow_ctrl[cfg_idx] = BNX2X_FLOW_CTRL_AUTO;
if (epause->rx_pause)
- bp->link_params.req_flow_ctrl |= BNX2X_FLOW_CTRL_RX;
+ bp->link_params.req_flow_ctrl[cfg_idx] |= BNX2X_FLOW_CTRL_RX;
if (epause->tx_pause)
- bp->link_params.req_flow_ctrl |= BNX2X_FLOW_CTRL_TX;
+ bp->link_params.req_flow_ctrl[cfg_idx] |= BNX2X_FLOW_CTRL_TX;
- if (bp->link_params.req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO)
- bp->link_params.req_flow_ctrl = BNX2X_FLOW_CTRL_NONE;
+ if (bp->link_params.req_flow_ctrl[cfg_idx] == BNX2X_FLOW_CTRL_AUTO)
+ bp->link_params.req_flow_ctrl[cfg_idx] = BNX2X_FLOW_CTRL_NONE;
if (epause->autoneg) {
- if (!(bp->port.supported & SUPPORTED_Autoneg)) {
+ if (!(bp->port.supported[cfg_idx] & SUPPORTED_Autoneg)) {
DP(NETIF_MSG_LINK, "autoneg not supported\n");
return -EINVAL;
}
- if (bp->link_params.req_line_speed == SPEED_AUTO_NEG)
- bp->link_params.req_flow_ctrl = BNX2X_FLOW_CTRL_AUTO;
+ if (bp->link_params.req_line_speed[cfg_idx] == SPEED_AUTO_NEG) {
+ bp->link_params.req_flow_ctrl[cfg_idx] =
+ BNX2X_FLOW_CTRL_AUTO;
+ }
}
DP(NETIF_MSG_LINK,
- "req_flow_ctrl 0x%x\n", bp->link_params.req_flow_ctrl);
+ "req_flow_ctrl 0x%x\n", bp->link_params.req_flow_ctrl[cfg_idx]);
if (netif_running(dev)) {
bnx2x_stats_handle(bp, STATS_EVENT_STOP);
@@ -1024,35 +1117,34 @@ static int bnx2x_set_flags(struct net_device *dev, u32 data)
int changed = 0;
int rc = 0;
- if (data & ~(ETH_FLAG_LRO | ETH_FLAG_RXHASH))
- return -EINVAL;
-
if (bp->recovery_state != BNX2X_RECOVERY_DONE) {
printk(KERN_ERR "Handling parity error recovery. Try again later\n");
return -EAGAIN;
}
+ if (!(data & ETH_FLAG_RXVLAN))
+ return -EINVAL;
+
+ if ((data & ETH_FLAG_LRO) && bp->rx_csum && bp->disable_tpa)
+ return -EINVAL;
+
+ rc = ethtool_op_set_flags(dev, data, ETH_FLAG_LRO | ETH_FLAG_RXVLAN |
+ ETH_FLAG_TXVLAN | ETH_FLAG_RXHASH);
+ if (rc)
+ return rc;
+
/* TPA requires Rx CSUM offloading */
if ((data & ETH_FLAG_LRO) && bp->rx_csum) {
- if (!bp->disable_tpa) {
- if (!(dev->features & NETIF_F_LRO)) {
- dev->features |= NETIF_F_LRO;
- bp->flags |= TPA_ENABLE_FLAG;
- changed = 1;
- }
- } else
- rc = -EINVAL;
- } else if (dev->features & NETIF_F_LRO) {
+ if (!(bp->flags & TPA_ENABLE_FLAG)) {
+ bp->flags |= TPA_ENABLE_FLAG;
+ changed = 1;
+ }
+ } else if (bp->flags & TPA_ENABLE_FLAG) {
dev->features &= ~NETIF_F_LRO;
bp->flags &= ~TPA_ENABLE_FLAG;
changed = 1;
}
- if (data & ETH_FLAG_RXHASH)
- dev->features |= NETIF_F_RXHASH;
- else
- dev->features &= ~NETIF_F_RXHASH;
-
if (changed && netif_running(dev)) {
bnx2x_nic_unload(bp, UNLOAD_NORMAL);
rc = bnx2x_nic_load(bp, LOAD_NORMAL);
@@ -1185,6 +1277,9 @@ static int bnx2x_test_registers(struct bnx2x *bp)
for (i = 0; reg_tbl[i].offset0 != 0xffffffff; i++) {
u32 offset, mask, save_val, val;
+ if (CHIP_IS_E2(bp) &&
+ reg_tbl[i].offset0 == HC_REG_AGG_INT_0)
+ continue;
offset = reg_tbl[i].offset0 + port*reg_tbl[i].offset1;
mask = reg_tbl[i].mask;
@@ -1192,6 +1287,7 @@ static int bnx2x_test_registers(struct bnx2x *bp)
save_val = REG_RD(bp, offset);
REG_WR(bp, offset, (wr_val & mask));
+
val = REG_RD(bp, offset);
/* Restore the original register's value */
@@ -1236,20 +1332,33 @@ static int bnx2x_test_memory(struct bnx2x *bp)
u32 offset;
u32 e1_mask;
u32 e1h_mask;
+ u32 e2_mask;
} prty_tbl[] = {
- { "CCM_PRTY_STS", CCM_REG_CCM_PRTY_STS, 0x3ffc0, 0 },
- { "CFC_PRTY_STS", CFC_REG_CFC_PRTY_STS, 0x2, 0x2 },
- { "DMAE_PRTY_STS", DMAE_REG_DMAE_PRTY_STS, 0, 0 },
- { "TCM_PRTY_STS", TCM_REG_TCM_PRTY_STS, 0x3ffc0, 0 },
- { "UCM_PRTY_STS", UCM_REG_UCM_PRTY_STS, 0x3ffc0, 0 },
- { "XCM_PRTY_STS", XCM_REG_XCM_PRTY_STS, 0x3ffc1, 0 },
-
- { NULL, 0xffffffff, 0, 0 }
+ { "CCM_PRTY_STS", CCM_REG_CCM_PRTY_STS, 0x3ffc0, 0, 0 },
+ { "CFC_PRTY_STS", CFC_REG_CFC_PRTY_STS, 0x2, 0x2, 0 },
+ { "DMAE_PRTY_STS", DMAE_REG_DMAE_PRTY_STS, 0, 0, 0 },
+ { "TCM_PRTY_STS", TCM_REG_TCM_PRTY_STS, 0x3ffc0, 0, 0 },
+ { "UCM_PRTY_STS", UCM_REG_UCM_PRTY_STS, 0x3ffc0, 0, 0 },
+ { "XCM_PRTY_STS", XCM_REG_XCM_PRTY_STS, 0x3ffc1, 0, 0 },
+
+ { NULL, 0xffffffff, 0, 0, 0 }
};
if (!netif_running(bp->dev))
return rc;
+ /* pre-Check the parity status */
+ for (i = 0; prty_tbl[i].offset != 0xffffffff; i++) {
+ val = REG_RD(bp, prty_tbl[i].offset);
+ if ((CHIP_IS_E1(bp) && (val & ~(prty_tbl[i].e1_mask))) ||
+ (CHIP_IS_E1H(bp) && (val & ~(prty_tbl[i].e1h_mask))) ||
+ (CHIP_IS_E2(bp) && (val & ~(prty_tbl[i].e2_mask)))) {
+ DP(NETIF_MSG_HW,
+ "%s is 0x%x\n", prty_tbl[i].name, val);
+ goto test_mem_exit;
+ }
+ }
+
/* Go through all the memories */
for (i = 0; mem_tbl[i].offset != 0xffffffff; i++)
for (j = 0; j < mem_tbl[i].size; j++)
@@ -1259,7 +1368,8 @@ static int bnx2x_test_memory(struct bnx2x *bp)
for (i = 0; prty_tbl[i].offset != 0xffffffff; i++) {
val = REG_RD(bp, prty_tbl[i].offset);
if ((CHIP_IS_E1(bp) && (val & ~(prty_tbl[i].e1_mask))) ||
- (CHIP_IS_E1H(bp) && (val & ~(prty_tbl[i].e1h_mask)))) {
+ (CHIP_IS_E1H(bp) && (val & ~(prty_tbl[i].e1h_mask))) ||
+ (CHIP_IS_E2(bp) && (val & ~(prty_tbl[i].e2_mask)))) {
DP(NETIF_MSG_HW,
"%s is 0x%x\n", prty_tbl[i].name, val);
goto test_mem_exit;
@@ -1272,12 +1382,12 @@ test_mem_exit:
return rc;
}
-static void bnx2x_wait_for_link(struct bnx2x *bp, u8 link_up)
+static void bnx2x_wait_for_link(struct bnx2x *bp, u8 link_up, u8 is_serdes)
{
- int cnt = 1000;
+ int cnt = 1400;
if (link_up)
- while (bnx2x_link_test(bp) && cnt--)
+ while (bnx2x_link_test(bp, is_serdes) && cnt--)
msleep(10);
}
@@ -1293,7 +1403,8 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up)
u16 pkt_prod, bd_prod;
struct sw_tx_bd *tx_buf;
struct eth_tx_start_bd *tx_start_bd;
- struct eth_tx_parse_bd *pbd = NULL;
+ struct eth_tx_parse_bd_e1x *pbd_e1x = NULL;
+ struct eth_tx_parse_bd_e2 *pbd_e2 = NULL;
dma_addr_t mapping;
union eth_rx_cqe *cqe;
u8 cqe_fp_flags;
@@ -1304,7 +1415,7 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up)
/* check the loopback mode */
switch (loopback_mode) {
case BNX2X_PHY_LOOPBACK:
- if (bp->link_params.loopback_mode != LOOPBACK_XGXS_10)
+ if (bp->link_params.loopback_mode != LOOPBACK_XGXS)
return -EINVAL;
break;
case BNX2X_MAC_LOOPBACK:
@@ -1349,16 +1460,23 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up)
tx_start_bd->addr_lo = cpu_to_le32(U64_LO(mapping));
tx_start_bd->nbd = cpu_to_le16(2); /* start + pbd */
tx_start_bd->nbytes = cpu_to_le16(skb_headlen(skb));
- tx_start_bd->vlan = cpu_to_le16(pkt_prod);
+ tx_start_bd->vlan_or_ethertype = cpu_to_le16(pkt_prod);
tx_start_bd->bd_flags.as_bitfield = ETH_TX_BD_FLAGS_START_BD;
- tx_start_bd->general_data = ((UNICAST_ADDRESS <<
- ETH_TX_START_BD_ETH_ADDR_TYPE_SHIFT) | 1);
+ SET_FLAG(tx_start_bd->general_data,
+ ETH_TX_START_BD_ETH_ADDR_TYPE,
+ UNICAST_ADDRESS);
+ SET_FLAG(tx_start_bd->general_data,
+ ETH_TX_START_BD_HDR_NBDS,
+ 1);
/* turn on parsing and get a BD */
bd_prod = TX_BD(NEXT_TX_IDX(bd_prod));
- pbd = &fp_tx->tx_desc_ring[bd_prod].parse_bd;
- memset(pbd, 0, sizeof(struct eth_tx_parse_bd));
+ pbd_e1x = &fp_tx->tx_desc_ring[bd_prod].parse_bd_e1x;
+ pbd_e2 = &fp_tx->tx_desc_ring[bd_prod].parse_bd_e2;
+
+ memset(pbd_e2, 0, sizeof(struct eth_tx_parse_bd_e2));
+ memset(pbd_e1x, 0, sizeof(struct eth_tx_parse_bd_e1x));
wmb();
@@ -1377,6 +1495,13 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up)
if (tx_idx != tx_start_idx + num_pkts)
goto test_loopback_exit;
+ /* Unlike HC IGU won't generate an interrupt for status block
+ * updates that have been performed while interrupts were
+ * disabled.
+ */
+ if (bp->common.int_block == INT_BLOCK_IGU)
+ bnx2x_tx_int(fp_tx);
+
rx_idx = le16_to_cpu(*fp_rx->rx_cons_sb);
if (rx_idx != rx_start_idx + num_pkts)
goto test_loopback_exit;
@@ -1519,8 +1644,7 @@ static int bnx2x_test_intr(struct bnx2x *bp)
config->hdr.length = 0;
if (CHIP_IS_E1(bp))
- /* use last unicast entries */
- config->hdr.offset = (BP_PORT(bp) ? 63 : 31);
+ config->hdr.offset = (BP_PORT(bp) ? 32 : 0);
else
config->hdr.offset = BP_FUNC(bp);
config->hdr.client_id = bp->fp->cl_id;
@@ -1528,9 +1652,9 @@ static int bnx2x_test_intr(struct bnx2x *bp)
bp->set_mac_pending++;
smp_wmb();
- rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_SET_MAC, 0,
+ rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
U64_HI(bnx2x_sp_mapping(bp, mac_config)),
- U64_LO(bnx2x_sp_mapping(bp, mac_config)), 0);
+ U64_LO(bnx2x_sp_mapping(bp, mac_config)), 1);
if (rc == 0) {
for (i = 0; i < 10; i++) {
if (!bp->set_mac_pending)
@@ -1549,7 +1673,7 @@ static void bnx2x_self_test(struct net_device *dev,
struct ethtool_test *etest, u64 *buf)
{
struct bnx2x *bp = netdev_priv(dev);
-
+ u8 is_serdes;
if (bp->recovery_state != BNX2X_RECOVERY_DONE) {
printk(KERN_ERR "Handling parity error recovery. Try again later\n");
etest->flags |= ETH_TEST_FL_FAILED;
@@ -1562,8 +1686,9 @@ static void bnx2x_self_test(struct net_device *dev,
return;
/* offline tests are not supported in MF mode */
- if (IS_E1HMF(bp))
+ if (IS_MF(bp))
etest->flags &= ~ETH_TEST_FL_OFFLINE;
+ is_serdes = (bp->link_vars.link_status & LINK_STATUS_SERDES_LINK) > 0;
if (etest->flags & ETH_TEST_FL_OFFLINE) {
int port = BP_PORT(bp);
@@ -1575,11 +1700,12 @@ static void bnx2x_self_test(struct net_device *dev,
/* disable input for TX port IF */
REG_WR(bp, NIG_REG_EGRESS_UMP0_IN_EN + port*4, 0);
- link_up = (bnx2x_link_test(bp) == 0);
+ link_up = bp->link_vars.link_up;
+
bnx2x_nic_unload(bp, UNLOAD_NORMAL);
bnx2x_nic_load(bp, LOAD_DIAG);
/* wait until link state is restored */
- bnx2x_wait_for_link(bp, link_up);
+ bnx2x_wait_for_link(bp, link_up, is_serdes);
if (bnx2x_test_registers(bp) != 0) {
buf[0] = 1;
@@ -1589,6 +1715,7 @@ static void bnx2x_self_test(struct net_device *dev,
buf[1] = 1;
etest->flags |= ETH_TEST_FL_FAILED;
}
+
buf[2] = bnx2x_test_loopback(bp, link_up);
if (buf[2] != 0)
etest->flags |= ETH_TEST_FL_FAILED;
@@ -1600,7 +1727,7 @@ static void bnx2x_self_test(struct net_device *dev,
bnx2x_nic_load(bp, LOAD_NORMAL);
/* wait until link state is restored */
- bnx2x_wait_for_link(bp, link_up);
+ bnx2x_wait_for_link(bp, link_up, is_serdes);
}
if (bnx2x_test_nvram(bp) != 0) {
buf[3] = 1;
@@ -1611,7 +1738,7 @@ static void bnx2x_self_test(struct net_device *dev,
etest->flags |= ETH_TEST_FL_FAILED;
}
if (bp->port.pmf)
- if (bnx2x_link_test(bp) != 0) {
+ if (bnx2x_link_test(bp, is_serdes) != 0) {
buf[5] = 1;
etest->flags |= ETH_TEST_FL_FAILED;
}
@@ -1752,8 +1879,8 @@ static const struct {
#define IS_PORT_STAT(i) \
((bnx2x_stats_arr[i].flags & STATS_FLAGS_BOTH) == STATS_FLAGS_PORT)
#define IS_FUNC_STAT(i) (bnx2x_stats_arr[i].flags & STATS_FLAGS_FUNC)
-#define IS_E1HMF_MODE_STAT(bp) \
- (IS_E1HMF(bp) && !(bp->msg_enable & BNX2X_MSG_STATS))
+#define IS_MF_MODE_STAT(bp) \
+ (IS_MF(bp) && !(bp->msg_enable & BNX2X_MSG_STATS))
static int bnx2x_get_sset_count(struct net_device *dev, int stringset)
{
@@ -1764,10 +1891,10 @@ static int bnx2x_get_sset_count(struct net_device *dev, int stringset)
case ETH_SS_STATS:
if (is_multi(bp)) {
num_stats = BNX2X_NUM_Q_STATS * bp->num_queues;
- if (!IS_E1HMF_MODE_STAT(bp))
+ if (!IS_MF_MODE_STAT(bp))
num_stats += BNX2X_NUM_STATS;
} else {
- if (IS_E1HMF_MODE_STAT(bp)) {
+ if (IS_MF_MODE_STAT(bp)) {
num_stats = 0;
for (i = 0; i < BNX2X_NUM_STATS; i++)
if (IS_FUNC_STAT(i))
@@ -1800,14 +1927,14 @@ static void bnx2x_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
bnx2x_q_stats_arr[j].string, i);
k += BNX2X_NUM_Q_STATS;
}
- if (IS_E1HMF_MODE_STAT(bp))
+ if (IS_MF_MODE_STAT(bp))
break;
for (j = 0; j < BNX2X_NUM_STATS; j++)
strcpy(buf + (k + j)*ETH_GSTRING_LEN,
bnx2x_stats_arr[j].string);
} else {
for (i = 0, j = 0; i < BNX2X_NUM_STATS; i++) {
- if (IS_E1HMF_MODE_STAT(bp) && IS_PORT_STAT(i))
+ if (IS_MF_MODE_STAT(bp) && IS_PORT_STAT(i))
continue;
strcpy(buf + j*ETH_GSTRING_LEN,
bnx2x_stats_arr[i].string);
@@ -1851,7 +1978,7 @@ static void bnx2x_get_ethtool_stats(struct net_device *dev,
}
k += BNX2X_NUM_Q_STATS;
}
- if (IS_E1HMF_MODE_STAT(bp))
+ if (IS_MF_MODE_STAT(bp))
return;
hw_stats = (u32 *)&bp->eth_stats;
for (j = 0; j < BNX2X_NUM_STATS; j++) {
@@ -1872,7 +1999,7 @@ static void bnx2x_get_ethtool_stats(struct net_device *dev,
} else {
hw_stats = (u32 *)&bp->eth_stats;
for (i = 0, j = 0; i < BNX2X_NUM_STATS; i++) {
- if (IS_E1HMF_MODE_STAT(bp) && IS_PORT_STAT(i))
+ if (IS_MF_MODE_STAT(bp) && IS_PORT_STAT(i))
continue;
if (bnx2x_stats_arr[i].size == 0) {
/* skip this counter */
@@ -1910,10 +2037,11 @@ static int bnx2x_phys_id(struct net_device *dev, u32 data)
for (i = 0; i < (data * 2); i++) {
if ((i % 2) == 0)
- bnx2x_set_led(&bp->link_params, LED_MODE_OPER,
- SPEED_1000);
+ bnx2x_set_led(&bp->link_params, &bp->link_vars,
+ LED_MODE_OPER, SPEED_1000);
else
- bnx2x_set_led(&bp->link_params, LED_MODE_OFF, 0);
+ bnx2x_set_led(&bp->link_params, &bp->link_vars,
+ LED_MODE_OFF, 0);
msleep_interruptible(500);
if (signal_pending(current))
@@ -1921,7 +2049,7 @@ static int bnx2x_phys_id(struct net_device *dev, u32 data)
}
if (bp->link_vars.link_up)
- bnx2x_set_led(&bp->link_params, LED_MODE_OPER,
+ bnx2x_set_led(&bp->link_params, &bp->link_vars, LED_MODE_OPER,
bp->link_vars.line_speed);
return 0;
diff --git a/drivers/net/bnx2x/bnx2x_fw_defs.h b/drivers/net/bnx2x/bnx2x_fw_defs.h
index 08d71bf438d6..f4e5b1ce8149 100644
--- a/drivers/net/bnx2x/bnx2x_fw_defs.h
+++ b/drivers/net/bnx2x/bnx2x_fw_defs.h
@@ -7,369 +7,272 @@
* the Free Software Foundation.
*/
-
-#define CSTORM_ASSERT_LIST_INDEX_OFFSET \
- (IS_E1H_OFFSET ? 0x7000 : 0x1000)
-#define CSTORM_ASSERT_LIST_OFFSET(idx) \
- (IS_E1H_OFFSET ? (0x7020 + (idx * 0x10)) : (0x1020 + (idx * 0x10)))
-#define CSTORM_DEF_SB_HC_DISABLE_C_OFFSET(function, index) \
- (IS_E1H_OFFSET ? (0x8622 + ((function>>1) * 0x40) + \
- ((function&1) * 0x100) + (index * 0x4)) : (0x3562 + (function * \
- 0x40) + (index * 0x4)))
-#define CSTORM_DEF_SB_HC_DISABLE_U_OFFSET(function, index) \
- (IS_E1H_OFFSET ? (0x8822 + ((function>>1) * 0x80) + \
- ((function&1) * 0x200) + (index * 0x4)) : (0x35e2 + (function * \
- 0x80) + (index * 0x4)))
-#define CSTORM_DEF_SB_HOST_SB_ADDR_C_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x8600 + ((function>>1) * 0x40) + \
- ((function&1) * 0x100)) : (0x3540 + (function * 0x40)))
-#define CSTORM_DEF_SB_HOST_SB_ADDR_U_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x8800 + ((function>>1) * 0x80) + \
- ((function&1) * 0x200)) : (0x35c0 + (function * 0x80)))
-#define CSTORM_DEF_SB_HOST_STATUS_BLOCK_C_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x8608 + ((function>>1) * 0x40) + \
- ((function&1) * 0x100)) : (0x3548 + (function * 0x40)))
-#define CSTORM_DEF_SB_HOST_STATUS_BLOCK_U_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x8808 + ((function>>1) * 0x80) + \
- ((function&1) * 0x200)) : (0x35c8 + (function * 0x80)))
-#define CSTORM_FUNCTION_MODE_OFFSET \
- (IS_E1H_OFFSET ? 0x11e8 : 0xffffffff)
-#define CSTORM_HC_BTR_C_OFFSET(port) \
- (IS_E1H_OFFSET ? (0x8c04 + (port * 0xf0)) : (0x36c4 + (port * 0xc0)))
-#define CSTORM_HC_BTR_U_OFFSET(port) \
- (IS_E1H_OFFSET ? (0x8de4 + (port * 0xf0)) : (0x3844 + (port * 0xc0)))
-#define CSTORM_ISCSI_CQ_SIZE_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x6680 + (function * 0x8)) : (0x25a0 + \
- (function * 0x8)))
-#define CSTORM_ISCSI_CQ_SQN_SIZE_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x66c0 + (function * 0x8)) : (0x25b0 + \
- (function * 0x8)))
-#define CSTORM_ISCSI_EQ_CONS_OFFSET(function, eqIdx) \
- (IS_E1H_OFFSET ? (0x6040 + (function * 0xc0) + (eqIdx * 0x18)) : \
- (0x2410 + (function * 0xc0) + (eqIdx * 0x18)))
-#define CSTORM_ISCSI_EQ_NEXT_EQE_ADDR_OFFSET(function, eqIdx) \
- (IS_E1H_OFFSET ? (0x6044 + (function * 0xc0) + (eqIdx * 0x18)) : \
- (0x2414 + (function * 0xc0) + (eqIdx * 0x18)))
-#define CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_OFFSET(function, eqIdx) \
- (IS_E1H_OFFSET ? (0x604c + (function * 0xc0) + (eqIdx * 0x18)) : \
- (0x241c + (function * 0xc0) + (eqIdx * 0x18)))
-#define CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_VALID_OFFSET(function, eqIdx) \
- (IS_E1H_OFFSET ? (0x6057 + (function * 0xc0) + (eqIdx * 0x18)) : \
- (0x2427 + (function * 0xc0) + (eqIdx * 0x18)))
-#define CSTORM_ISCSI_EQ_PROD_OFFSET(function, eqIdx) \
- (IS_E1H_OFFSET ? (0x6042 + (function * 0xc0) + (eqIdx * 0x18)) : \
- (0x2412 + (function * 0xc0) + (eqIdx * 0x18)))
-#define CSTORM_ISCSI_EQ_SB_INDEX_OFFSET(function, eqIdx) \
- (IS_E1H_OFFSET ? (0x6056 + (function * 0xc0) + (eqIdx * 0x18)) : \
- (0x2426 + (function * 0xc0) + (eqIdx * 0x18)))
-#define CSTORM_ISCSI_EQ_SB_NUM_OFFSET(function, eqIdx) \
- (IS_E1H_OFFSET ? (0x6054 + (function * 0xc0) + (eqIdx * 0x18)) : \
- (0x2424 + (function * 0xc0) + (eqIdx * 0x18)))
-#define CSTORM_ISCSI_HQ_SIZE_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x6640 + (function * 0x8)) : (0x2590 + \
- (function * 0x8)))
-#define CSTORM_ISCSI_NUM_OF_TASKS_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x6004 + (function * 0x8)) : (0x2404 + \
- (function * 0x8)))
-#define CSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x6002 + (function * 0x8)) : (0x2402 + \
- (function * 0x8)))
-#define CSTORM_ISCSI_PAGE_SIZE_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x6000 + (function * 0x8)) : (0x2400 + \
- (function * 0x8)))
-#define CSTORM_SB_HC_DISABLE_C_OFFSET(port, cpu_id, index) \
- (IS_E1H_OFFSET ? (0x811a + (port * 0x280) + (cpu_id * 0x28) + \
- (index * 0x4)) : (0x305a + (port * 0x280) + (cpu_id * 0x28) + \
- (index * 0x4)))
-#define CSTORM_SB_HC_DISABLE_U_OFFSET(port, cpu_id, index) \
- (IS_E1H_OFFSET ? (0xb01a + (port * 0x800) + (cpu_id * 0x80) + \
- (index * 0x4)) : (0x401a + (port * 0x800) + (cpu_id * 0x80) + \
- (index * 0x4)))
-#define CSTORM_SB_HC_TIMEOUT_C_OFFSET(port, cpu_id, index) \
- (IS_E1H_OFFSET ? (0x8118 + (port * 0x280) + (cpu_id * 0x28) + \
- (index * 0x4)) : (0x3058 + (port * 0x280) + (cpu_id * 0x28) + \
- (index * 0x4)))
-#define CSTORM_SB_HC_TIMEOUT_U_OFFSET(port, cpu_id, index) \
- (IS_E1H_OFFSET ? (0xb018 + (port * 0x800) + (cpu_id * 0x80) + \
- (index * 0x4)) : (0x4018 + (port * 0x800) + (cpu_id * 0x80) + \
- (index * 0x4)))
-#define CSTORM_SB_HOST_SB_ADDR_C_OFFSET(port, cpu_id) \
- (IS_E1H_OFFSET ? (0x8100 + (port * 0x280) + (cpu_id * 0x28)) : \
- (0x3040 + (port * 0x280) + (cpu_id * 0x28)))
-#define CSTORM_SB_HOST_SB_ADDR_U_OFFSET(port, cpu_id) \
- (IS_E1H_OFFSET ? (0xb000 + (port * 0x800) + (cpu_id * 0x80)) : \
- (0x4000 + (port * 0x800) + (cpu_id * 0x80)))
-#define CSTORM_SB_HOST_STATUS_BLOCK_C_OFFSET(port, cpu_id) \
- (IS_E1H_OFFSET ? (0x8108 + (port * 0x280) + (cpu_id * 0x28)) : \
- (0x3048 + (port * 0x280) + (cpu_id * 0x28)))
-#define CSTORM_SB_HOST_STATUS_BLOCK_U_OFFSET(port, cpu_id) \
- (IS_E1H_OFFSET ? (0xb008 + (port * 0x800) + (cpu_id * 0x80)) : \
- (0x4008 + (port * 0x800) + (cpu_id * 0x80)))
-#define CSTORM_SB_STATUS_BLOCK_C_SIZE 0x10
-#define CSTORM_SB_STATUS_BLOCK_U_SIZE 0x60
-#define CSTORM_STATS_FLAGS_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x1108 + (function * 0x8)) : (0x5108 + \
- (function * 0x8)))
-#define TSTORM_APPROXIMATE_MATCH_MULTICAST_FILTERING_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x3200 + (function * 0x20)) : 0xffffffff)
-#define TSTORM_ASSERT_LIST_INDEX_OFFSET \
- (IS_E1H_OFFSET ? 0xa000 : 0x1000)
-#define TSTORM_ASSERT_LIST_OFFSET(idx) \
- (IS_E1H_OFFSET ? (0xa020 + (idx * 0x10)) : (0x1020 + (idx * 0x10)))
-#define TSTORM_CLIENT_CONFIG_OFFSET(port, client_id) \
- (IS_E1H_OFFSET ? (0x33a0 + (port * 0x1a0) + (client_id * 0x10)) \
- : (0x9c0 + (port * 0x120) + (client_id * 0x10)))
-#define TSTORM_COMMON_SAFC_WORKAROUND_ENABLE_OFFSET \
- (IS_E1H_OFFSET ? 0x1ed8 : 0xffffffff)
+#ifndef BNX2X_FW_DEFS_H
+#define BNX2X_FW_DEFS_H
+
+#define CSTORM_ASSERT_LIST_INDEX_OFFSET (IRO[142].base)
+#define CSTORM_ASSERT_LIST_OFFSET(assertListEntry) \
+ (IRO[141].base + ((assertListEntry) * IRO[141].m1))
+#define CSTORM_ETH_STATS_QUERY_ADDR_OFFSET(pfId) \
+ (IRO[144].base + ((pfId) * IRO[144].m1))
+#define CSTORM_EVENT_RING_DATA_OFFSET(pfId) \
+ (IRO[149].base + (((pfId)>>1) * IRO[149].m1) + (((pfId)&1) * \
+ IRO[149].m2))
+#define CSTORM_EVENT_RING_PROD_OFFSET(pfId) \
+ (IRO[150].base + (((pfId)>>1) * IRO[150].m1) + (((pfId)&1) * \
+ IRO[150].m2))
+#define CSTORM_FINAL_CLEANUP_COMPLETE_OFFSET(funcId) \
+ (IRO[156].base + ((funcId) * IRO[156].m1))
+#define CSTORM_FUNC_EN_OFFSET(funcId) \
+ (IRO[146].base + ((funcId) * IRO[146].m1))
+#define CSTORM_FUNCTION_MODE_OFFSET (IRO[153].base)
+#define CSTORM_IGU_MODE_OFFSET (IRO[154].base)
+#define CSTORM_ISCSI_CQ_SIZE_OFFSET(pfId) \
+ (IRO[311].base + ((pfId) * IRO[311].m1))
+#define CSTORM_ISCSI_CQ_SQN_SIZE_OFFSET(pfId) \
+ (IRO[312].base + ((pfId) * IRO[312].m1))
+ #define CSTORM_ISCSI_EQ_CONS_OFFSET(pfId, iscsiEqId) \
+ (IRO[304].base + ((pfId) * IRO[304].m1) + ((iscsiEqId) * \
+ IRO[304].m2))
+ #define CSTORM_ISCSI_EQ_NEXT_EQE_ADDR_OFFSET(pfId, iscsiEqId) \
+ (IRO[306].base + ((pfId) * IRO[306].m1) + ((iscsiEqId) * \
+ IRO[306].m2))
+ #define CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_OFFSET(pfId, iscsiEqId) \
+ (IRO[305].base + ((pfId) * IRO[305].m1) + ((iscsiEqId) * \
+ IRO[305].m2))
+ #define \
+ CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_VALID_OFFSET(pfId, iscsiEqId) \
+ (IRO[307].base + ((pfId) * IRO[307].m1) + ((iscsiEqId) * \
+ IRO[307].m2))
+ #define CSTORM_ISCSI_EQ_PROD_OFFSET(pfId, iscsiEqId) \
+ (IRO[303].base + ((pfId) * IRO[303].m1) + ((iscsiEqId) * \
+ IRO[303].m2))
+ #define CSTORM_ISCSI_EQ_SB_INDEX_OFFSET(pfId, iscsiEqId) \
+ (IRO[309].base + ((pfId) * IRO[309].m1) + ((iscsiEqId) * \
+ IRO[309].m2))
+ #define CSTORM_ISCSI_EQ_SB_NUM_OFFSET(pfId, iscsiEqId) \
+ (IRO[308].base + ((pfId) * IRO[308].m1) + ((iscsiEqId) * \
+ IRO[308].m2))
+#define CSTORM_ISCSI_HQ_SIZE_OFFSET(pfId) \
+ (IRO[310].base + ((pfId) * IRO[310].m1))
+#define CSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \
+ (IRO[302].base + ((pfId) * IRO[302].m1))
+#define CSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \
+ (IRO[301].base + ((pfId) * IRO[301].m1))
+#define CSTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \
+ (IRO[300].base + ((pfId) * IRO[300].m1))
+#define CSTORM_PATH_ID_OFFSET (IRO[159].base)
+#define CSTORM_SP_STATUS_BLOCK_DATA_OFFSET(pfId) \
+ (IRO[137].base + ((pfId) * IRO[137].m1))
+#define CSTORM_SP_STATUS_BLOCK_OFFSET(pfId) \
+ (IRO[136].base + ((pfId) * IRO[136].m1))
+#define CSTORM_SP_STATUS_BLOCK_SIZE (IRO[136].size)
+#define CSTORM_SP_SYNC_BLOCK_OFFSET(pfId) \
+ (IRO[138].base + ((pfId) * IRO[138].m1))
+#define CSTORM_SP_SYNC_BLOCK_SIZE (IRO[138].size)
+#define CSTORM_STATS_FLAGS_OFFSET(pfId) \
+ (IRO[143].base + ((pfId) * IRO[143].m1))
+#define CSTORM_STATUS_BLOCK_DATA_OFFSET(sbId) \
+ (IRO[129].base + ((sbId) * IRO[129].m1))
+#define CSTORM_STATUS_BLOCK_OFFSET(sbId) \
+ (IRO[128].base + ((sbId) * IRO[128].m1))
+#define CSTORM_STATUS_BLOCK_SIZE (IRO[128].size)
+#define CSTORM_SYNC_BLOCK_OFFSET(sbId) \
+ (IRO[132].base + ((sbId) * IRO[132].m1))
+#define CSTORM_SYNC_BLOCK_SIZE (IRO[132].size)
+#define CSTORM_VF_PF_CHANNEL_STATE_OFFSET(vfId) \
+ (IRO[151].base + ((vfId) * IRO[151].m1))
+#define CSTORM_VF_PF_CHANNEL_VALID_OFFSET(vfId) \
+ (IRO[152].base + ((vfId) * IRO[152].m1))
+#define CSTORM_VF_TO_PF_OFFSET(funcId) \
+ (IRO[147].base + ((funcId) * IRO[147].m1))
+#define TSTORM_ACCEPT_CLASSIFY_FAILED_OFFSET (IRO[199].base)
+#define TSTORM_APPROXIMATE_MATCH_MULTICAST_FILTERING_OFFSET(pfId) \
+ (IRO[198].base + ((pfId) * IRO[198].m1))
+#define TSTORM_ASSERT_LIST_INDEX_OFFSET (IRO[99].base)
+#define TSTORM_ASSERT_LIST_OFFSET(assertListEntry) \
+ (IRO[98].base + ((assertListEntry) * IRO[98].m1))
+ #define TSTORM_CLIENT_CONFIG_OFFSET(portId, clientId) \
+ (IRO[197].base + ((portId) * IRO[197].m1) + ((clientId) * \
+ IRO[197].m2))
+#define TSTORM_COMMON_SAFC_WORKAROUND_ENABLE_OFFSET (IRO[104].base)
#define TSTORM_COMMON_SAFC_WORKAROUND_TIMEOUT_10USEC_OFFSET \
- (IS_E1H_OFFSET ? 0x1eda : 0xffffffff)
-#define TSTORM_DEF_SB_HC_DISABLE_OFFSET(function, index) \
- (IS_E1H_OFFSET ? (0xb01a + ((function>>1) * 0x28) + \
- ((function&1) * 0xa0) + (index * 0x4)) : (0x141a + (function * \
- 0x28) + (index * 0x4)))
-#define TSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(function) \
- (IS_E1H_OFFSET ? (0xb000 + ((function>>1) * 0x28) + \
- ((function&1) * 0xa0)) : (0x1400 + (function * 0x28)))
-#define TSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(function) \
- (IS_E1H_OFFSET ? (0xb008 + ((function>>1) * 0x28) + \
- ((function&1) * 0xa0)) : (0x1408 + (function * 0x28)))
-#define TSTORM_ETH_STATS_QUERY_ADDR_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x2940 + (function * 0x8)) : (0x4928 + \
- (function * 0x8)))
-#define TSTORM_FUNCTION_COMMON_CONFIG_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x3000 + (function * 0x40)) : (0x1500 + \
- (function * 0x40)))
-#define TSTORM_FUNCTION_MODE_OFFSET \
- (IS_E1H_OFFSET ? 0x1ed0 : 0xffffffff)
-#define TSTORM_HC_BTR_OFFSET(port) \
- (IS_E1H_OFFSET ? (0xb144 + (port * 0x30)) : (0x1454 + (port * 0x18)))
-#define TSTORM_INDIRECTION_TABLE_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x12c8 + (function * 0x80)) : (0x22c8 + \
- (function * 0x80)))
-#define TSTORM_INDIRECTION_TABLE_SIZE 0x80
-#define TSTORM_ISCSI_CONN_BUF_PBL_OFFSET(function, pblEntry) \
- (IS_E1H_OFFSET ? (0x60c0 + (function * 0x40) + (pblEntry * 0x8)) \
- : (0x4c30 + (function * 0x40) + (pblEntry * 0x8)))
-#define TSTORM_ISCSI_ERROR_BITMAP_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x6340 + (function * 0x8)) : (0x4cd0 + \
- (function * 0x8)))
-#define TSTORM_ISCSI_NUM_OF_TASKS_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x6004 + (function * 0x8)) : (0x4c04 + \
- (function * 0x8)))
-#define TSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x6002 + (function * 0x8)) : (0x4c02 + \
- (function * 0x8)))
-#define TSTORM_ISCSI_PAGE_SIZE_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x6000 + (function * 0x8)) : (0x4c00 + \
- (function * 0x8)))
-#define TSTORM_ISCSI_RQ_SIZE_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x6080 + (function * 0x8)) : (0x4c20 + \
- (function * 0x8)))
-#define TSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x6040 + (function * 0x8)) : (0x4c10 + \
- (function * 0x8)))
-#define TSTORM_ISCSI_TCP_VARS_LSB_LOCAL_MAC_ADDR_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x6042 + (function * 0x8)) : (0x4c12 + \
- (function * 0x8)))
-#define TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x6044 + (function * 0x8)) : (0x4c14 + \
- (function * 0x8)))
-#define TSTORM_MAC_FILTER_CONFIG_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x3008 + (function * 0x40)) : (0x1508 + \
- (function * 0x40)))
-#define TSTORM_PER_COUNTER_ID_STATS_OFFSET(port, stats_counter_id) \
- (IS_E1H_OFFSET ? (0x2010 + (port * 0x490) + (stats_counter_id * \
- 0x40)) : (0x4010 + (port * 0x490) + (stats_counter_id * 0x40)))
-#define TSTORM_STATS_FLAGS_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x29c0 + (function * 0x8)) : (0x4948 + \
- (function * 0x8)))
-#define TSTORM_TCP_MAX_CWND_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x4004 + (function * 0x8)) : (0x1fb4 + \
- (function * 0x8)))
-#define USTORM_AGG_DATA_OFFSET (IS_E1H_OFFSET ? 0xa000 : 0x3000)
-#define USTORM_AGG_DATA_SIZE (IS_E1H_OFFSET ? 0x2000 : 0x1000)
-#define USTORM_ASSERT_LIST_INDEX_OFFSET \
- (IS_E1H_OFFSET ? 0x8000 : 0x1000)
-#define USTORM_ASSERT_LIST_OFFSET(idx) \
- (IS_E1H_OFFSET ? (0x8020 + (idx * 0x10)) : (0x1020 + (idx * 0x10)))
-#define USTORM_CQE_PAGE_BASE_OFFSET(port, clientId) \
- (IS_E1H_OFFSET ? (0x1010 + (port * 0x680) + (clientId * 0x40)) : \
- (0x4010 + (port * 0x360) + (clientId * 0x30)))
-#define USTORM_CQE_PAGE_NEXT_OFFSET(port, clientId) \
- (IS_E1H_OFFSET ? (0x1028 + (port * 0x680) + (clientId * 0x40)) : \
- (0x4028 + (port * 0x360) + (clientId * 0x30)))
-#define USTORM_ETH_PAUSE_ENABLED_OFFSET(port) \
- (IS_E1H_OFFSET ? (0x2ad4 + (port * 0x8)) : 0xffffffff)
-#define USTORM_ETH_RING_PAUSE_DATA_OFFSET(port, clientId) \
- (IS_E1H_OFFSET ? (0x1030 + (port * 0x680) + (clientId * 0x40)) : \
- 0xffffffff)
-#define USTORM_ETH_STATS_QUERY_ADDR_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x2a50 + (function * 0x8)) : (0x1dd0 + \
- (function * 0x8)))
-#define USTORM_FUNCTION_MODE_OFFSET \
- (IS_E1H_OFFSET ? 0x2448 : 0xffffffff)
-#define USTORM_ISCSI_CQ_SIZE_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x7044 + (function * 0x8)) : (0x2414 + \
- (function * 0x8)))
-#define USTORM_ISCSI_CQ_SQN_SIZE_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x7046 + (function * 0x8)) : (0x2416 + \
- (function * 0x8)))
-#define USTORM_ISCSI_ERROR_BITMAP_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x7688 + (function * 0x8)) : (0x29c8 + \
- (function * 0x8)))
-#define USTORM_ISCSI_GLOBAL_BUF_PHYS_ADDR_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x7648 + (function * 0x8)) : (0x29b8 + \
- (function * 0x8)))
-#define USTORM_ISCSI_NUM_OF_TASKS_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x7004 + (function * 0x8)) : (0x2404 + \
- (function * 0x8)))
-#define USTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x7002 + (function * 0x8)) : (0x2402 + \
- (function * 0x8)))
-#define USTORM_ISCSI_PAGE_SIZE_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x7000 + (function * 0x8)) : (0x2400 + \
- (function * 0x8)))
-#define USTORM_ISCSI_R2TQ_SIZE_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x7040 + (function * 0x8)) : (0x2410 + \
- (function * 0x8)))
-#define USTORM_ISCSI_RQ_BUFFER_SIZE_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x7080 + (function * 0x8)) : (0x2420 + \
- (function * 0x8)))
-#define USTORM_ISCSI_RQ_SIZE_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x7084 + (function * 0x8)) : (0x2424 + \
- (function * 0x8)))
-#define USTORM_MAX_AGG_SIZE_OFFSET(port, clientId) \
- (IS_E1H_OFFSET ? (0x1018 + (port * 0x680) + (clientId * 0x40)) : \
- (0x4018 + (port * 0x360) + (clientId * 0x30)))
-#define USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x2408 + (function * 0x8)) : (0x1da8 + \
- (function * 0x8)))
-#define USTORM_PER_COUNTER_ID_STATS_OFFSET(port, stats_counter_id) \
- (IS_E1H_OFFSET ? (0x2450 + (port * 0x2d0) + (stats_counter_id * \
- 0x28)) : (0x1500 + (port * 0x2d0) + (stats_counter_id * 0x28)))
-#define USTORM_RX_PRODS_OFFSET(port, client_id) \
- (IS_E1H_OFFSET ? (0x1000 + (port * 0x680) + (client_id * 0x40)) \
- : (0x4000 + (port * 0x360) + (client_id * 0x30)))
-#define USTORM_STATS_FLAGS_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x29f0 + (function * 0x8)) : (0x1db8 + \
- (function * 0x8)))
-#define USTORM_TPA_BTR_OFFSET (IS_E1H_OFFSET ? 0x3da5 : 0x5095)
-#define USTORM_TPA_BTR_SIZE 0x1
-#define XSTORM_ASSERT_LIST_INDEX_OFFSET \
- (IS_E1H_OFFSET ? 0x9000 : 0x1000)
-#define XSTORM_ASSERT_LIST_OFFSET(idx) \
- (IS_E1H_OFFSET ? (0x9020 + (idx * 0x10)) : (0x1020 + (idx * 0x10)))
-#define XSTORM_CMNG_PER_PORT_VARS_OFFSET(port) \
- (IS_E1H_OFFSET ? (0x24a8 + (port * 0x50)) : (0x3a80 + (port * 0x50)))
-#define XSTORM_DEF_SB_HC_DISABLE_OFFSET(function, index) \
- (IS_E1H_OFFSET ? (0xa01a + ((function>>1) * 0x28) + \
- ((function&1) * 0xa0) + (index * 0x4)) : (0x141a + (function * \
- 0x28) + (index * 0x4)))
-#define XSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(function) \
- (IS_E1H_OFFSET ? (0xa000 + ((function>>1) * 0x28) + \
- ((function&1) * 0xa0)) : (0x1400 + (function * 0x28)))
-#define XSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(function) \
- (IS_E1H_OFFSET ? (0xa008 + ((function>>1) * 0x28) + \
- ((function&1) * 0xa0)) : (0x1408 + (function * 0x28)))
-#define XSTORM_E1HOV_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x2c10 + (function * 0x8)) : 0xffffffff)
-#define XSTORM_ETH_STATS_QUERY_ADDR_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x2418 + (function * 0x8)) : (0x3a50 + \
- (function * 0x8)))
-#define XSTORM_FAIRNESS_PER_VN_VARS_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x2588 + (function * 0x90)) : (0x3b60 + \
- (function * 0x90)))
-#define XSTORM_FUNCTION_MODE_OFFSET \
- (IS_E1H_OFFSET ? 0x2c50 : 0xffffffff)
-#define XSTORM_HC_BTR_OFFSET(port) \
- (IS_E1H_OFFSET ? (0xa144 + (port * 0x30)) : (0x1454 + (port * 0x18)))
-#define XSTORM_ISCSI_HQ_SIZE_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x80c0 + (function * 0x8)) : (0x1c30 + \
- (function * 0x8)))
-#define XSTORM_ISCSI_LOCAL_MAC_ADDR0_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x8080 + (function * 0x8)) : (0x1c20 + \
- (function * 0x8)))
-#define XSTORM_ISCSI_LOCAL_MAC_ADDR1_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x8081 + (function * 0x8)) : (0x1c21 + \
- (function * 0x8)))
-#define XSTORM_ISCSI_LOCAL_MAC_ADDR2_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x8082 + (function * 0x8)) : (0x1c22 + \
- (function * 0x8)))
-#define XSTORM_ISCSI_LOCAL_MAC_ADDR3_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x8083 + (function * 0x8)) : (0x1c23 + \
- (function * 0x8)))
-#define XSTORM_ISCSI_LOCAL_MAC_ADDR4_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x8084 + (function * 0x8)) : (0x1c24 + \
- (function * 0x8)))
-#define XSTORM_ISCSI_LOCAL_MAC_ADDR5_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x8085 + (function * 0x8)) : (0x1c25 + \
- (function * 0x8)))
-#define XSTORM_ISCSI_LOCAL_VLAN_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x8086 + (function * 0x8)) : (0x1c26 + \
- (function * 0x8)))
-#define XSTORM_ISCSI_NUM_OF_TASKS_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x8004 + (function * 0x8)) : (0x1c04 + \
- (function * 0x8)))
-#define XSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x8002 + (function * 0x8)) : (0x1c02 + \
- (function * 0x8)))
-#define XSTORM_ISCSI_PAGE_SIZE_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x8000 + (function * 0x8)) : (0x1c00 + \
- (function * 0x8)))
-#define XSTORM_ISCSI_R2TQ_SIZE_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x80c4 + (function * 0x8)) : (0x1c34 + \
- (function * 0x8)))
-#define XSTORM_ISCSI_SQ_SIZE_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x80c2 + (function * 0x8)) : (0x1c32 + \
- (function * 0x8)))
-#define XSTORM_ISCSI_TCP_VARS_ADV_WND_SCL_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x8043 + (function * 0x8)) : (0x1c13 + \
- (function * 0x8)))
-#define XSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x8042 + (function * 0x8)) : (0x1c12 + \
- (function * 0x8)))
-#define XSTORM_ISCSI_TCP_VARS_TOS_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x8041 + (function * 0x8)) : (0x1c11 + \
- (function * 0x8)))
-#define XSTORM_ISCSI_TCP_VARS_TTL_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x8040 + (function * 0x8)) : (0x1c10 + \
- (function * 0x8)))
-#define XSTORM_PER_COUNTER_ID_STATS_OFFSET(port, stats_counter_id) \
- (IS_E1H_OFFSET ? (0xc000 + (port * 0x360) + (stats_counter_id * \
- 0x30)) : (0x3378 + (port * 0x360) + (stats_counter_id * 0x30)))
-#define XSTORM_RATE_SHAPING_PER_VN_VARS_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x2548 + (function * 0x90)) : (0x3b20 + \
- (function * 0x90)))
-#define XSTORM_SPQ_PAGE_BASE_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x2000 + (function * 0x10)) : (0x3328 + \
- (function * 0x10)))
-#define XSTORM_SPQ_PROD_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x2008 + (function * 0x10)) : (0x3330 + \
- (function * 0x10)))
-#define XSTORM_STATS_FLAGS_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x23d8 + (function * 0x8)) : (0x3a40 + \
- (function * 0x8)))
-#define XSTORM_TCP_GLOBAL_DEL_ACK_COUNTER_ENABLED_OFFSET(port) \
- (IS_E1H_OFFSET ? (0x4000 + (port * 0x8)) : (0x1960 + (port * 0x8)))
-#define XSTORM_TCP_GLOBAL_DEL_ACK_COUNTER_MAX_COUNT_OFFSET(port) \
- (IS_E1H_OFFSET ? (0x4001 + (port * 0x8)) : (0x1961 + (port * 0x8)))
-#define XSTORM_TCP_TX_SWS_TIMER_VAL_OFFSET(function) \
- (IS_E1H_OFFSET ? (0x4060 + ((function>>1) * 0x8) + ((function&1) \
- * 0x4)) : (0x1978 + (function * 0x4)))
+ (IRO[105].base)
+#define TSTORM_ETH_STATS_QUERY_ADDR_OFFSET(pfId) \
+ (IRO[96].base + ((pfId) * IRO[96].m1))
+#define TSTORM_FUNC_EN_OFFSET(funcId) \
+ (IRO[101].base + ((funcId) * IRO[101].m1))
+#define TSTORM_FUNCTION_COMMON_CONFIG_OFFSET(pfId) \
+ (IRO[195].base + ((pfId) * IRO[195].m1))
+#define TSTORM_FUNCTION_MODE_OFFSET (IRO[103].base)
+#define TSTORM_INDIRECTION_TABLE_OFFSET(pfId) \
+ (IRO[91].base + ((pfId) * IRO[91].m1))
+#define TSTORM_INDIRECTION_TABLE_SIZE (IRO[91].size)
+ #define \
+ TSTORM_ISCSI_CONN_BUF_PBL_OFFSET(pfId, iscsiConBufPblEntry) \
+ (IRO[260].base + ((pfId) * IRO[260].m1) + ((iscsiConBufPblEntry) \
+ * IRO[260].m2))
+#define TSTORM_ISCSI_ERROR_BITMAP_OFFSET(pfId) \
+ (IRO[264].base + ((pfId) * IRO[264].m1))
+#define TSTORM_ISCSI_L2_ISCSI_OOO_CID_TABLE_OFFSET(pfId) \
+ (IRO[265].base + ((pfId) * IRO[265].m1))
+#define TSTORM_ISCSI_L2_ISCSI_OOO_CLIENT_ID_TABLE_OFFSET(pfId) \
+ (IRO[266].base + ((pfId) * IRO[266].m1))
+#define TSTORM_ISCSI_L2_ISCSI_OOO_PROD_OFFSET(pfId) \
+ (IRO[267].base + ((pfId) * IRO[267].m1))
+#define TSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \
+ (IRO[263].base + ((pfId) * IRO[263].m1))
+#define TSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \
+ (IRO[262].base + ((pfId) * IRO[262].m1))
+#define TSTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \
+ (IRO[261].base + ((pfId) * IRO[261].m1))
+#define TSTORM_ISCSI_RQ_SIZE_OFFSET(pfId) \
+ (IRO[259].base + ((pfId) * IRO[259].m1))
+#define TSTORM_ISCSI_TCP_LOCAL_ADV_WND_OFFSET(pfId) \
+ (IRO[269].base + ((pfId) * IRO[269].m1))
+#define TSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(pfId) \
+ (IRO[256].base + ((pfId) * IRO[256].m1))
+#define TSTORM_ISCSI_TCP_VARS_LSB_LOCAL_MAC_ADDR_OFFSET(pfId) \
+ (IRO[257].base + ((pfId) * IRO[257].m1))
+#define TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfId) \
+ (IRO[258].base + ((pfId) * IRO[258].m1))
+#define TSTORM_MAC_FILTER_CONFIG_OFFSET(pfId) \
+ (IRO[196].base + ((pfId) * IRO[196].m1))
+ #define TSTORM_PER_COUNTER_ID_STATS_OFFSET(portId, tStatCntId) \
+ (IRO[100].base + ((portId) * IRO[100].m1) + ((tStatCntId) * \
+ IRO[100].m2))
+#define TSTORM_STATS_FLAGS_OFFSET(pfId) \
+ (IRO[95].base + ((pfId) * IRO[95].m1))
+#define TSTORM_TCP_MAX_CWND_OFFSET(pfId) \
+ (IRO[211].base + ((pfId) * IRO[211].m1))
+#define TSTORM_VF_TO_PF_OFFSET(funcId) \
+ (IRO[102].base + ((funcId) * IRO[102].m1))
+#define USTORM_AGG_DATA_OFFSET (IRO[201].base)
+#define USTORM_AGG_DATA_SIZE (IRO[201].size)
+#define USTORM_ASSERT_LIST_INDEX_OFFSET (IRO[170].base)
+#define USTORM_ASSERT_LIST_OFFSET(assertListEntry) \
+ (IRO[169].base + ((assertListEntry) * IRO[169].m1))
+#define USTORM_ETH_PAUSE_ENABLED_OFFSET(portId) \
+ (IRO[178].base + ((portId) * IRO[178].m1))
+#define USTORM_ETH_STATS_QUERY_ADDR_OFFSET(pfId) \
+ (IRO[172].base + ((pfId) * IRO[172].m1))
+#define USTORM_FCOE_EQ_PROD_OFFSET(pfId) \
+ (IRO[313].base + ((pfId) * IRO[313].m1))
+#define USTORM_FUNC_EN_OFFSET(funcId) \
+ (IRO[174].base + ((funcId) * IRO[174].m1))
+#define USTORM_FUNCTION_MODE_OFFSET (IRO[177].base)
+#define USTORM_ISCSI_CQ_SIZE_OFFSET(pfId) \
+ (IRO[277].base + ((pfId) * IRO[277].m1))
+#define USTORM_ISCSI_CQ_SQN_SIZE_OFFSET(pfId) \
+ (IRO[278].base + ((pfId) * IRO[278].m1))
+#define USTORM_ISCSI_ERROR_BITMAP_OFFSET(pfId) \
+ (IRO[282].base + ((pfId) * IRO[282].m1))
+#define USTORM_ISCSI_GLOBAL_BUF_PHYS_ADDR_OFFSET(pfId) \
+ (IRO[279].base + ((pfId) * IRO[279].m1))
+#define USTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \
+ (IRO[275].base + ((pfId) * IRO[275].m1))
+#define USTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \
+ (IRO[274].base + ((pfId) * IRO[274].m1))
+#define USTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \
+ (IRO[273].base + ((pfId) * IRO[273].m1))
+#define USTORM_ISCSI_R2TQ_SIZE_OFFSET(pfId) \
+ (IRO[276].base + ((pfId) * IRO[276].m1))
+#define USTORM_ISCSI_RQ_BUFFER_SIZE_OFFSET(pfId) \
+ (IRO[280].base + ((pfId) * IRO[280].m1))
+#define USTORM_ISCSI_RQ_SIZE_OFFSET(pfId) \
+ (IRO[281].base + ((pfId) * IRO[281].m1))
+#define USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(pfId) \
+ (IRO[176].base + ((pfId) * IRO[176].m1))
+ #define USTORM_PER_COUNTER_ID_STATS_OFFSET(portId, uStatCntId) \
+ (IRO[173].base + ((portId) * IRO[173].m1) + ((uStatCntId) * \
+ IRO[173].m2))
+ #define USTORM_RX_PRODS_E1X_OFFSET(portId, clientId) \
+ (IRO[204].base + ((portId) * IRO[204].m1) + ((clientId) * \
+ IRO[204].m2))
+#define USTORM_RX_PRODS_E2_OFFSET(qzoneId) \
+ (IRO[205].base + ((qzoneId) * IRO[205].m1))
+#define USTORM_STATS_FLAGS_OFFSET(pfId) \
+ (IRO[171].base + ((pfId) * IRO[171].m1))
+#define USTORM_TPA_BTR_OFFSET (IRO[202].base)
+#define USTORM_TPA_BTR_SIZE (IRO[202].size)
+#define USTORM_VF_TO_PF_OFFSET(funcId) \
+ (IRO[175].base + ((funcId) * IRO[175].m1))
+#define XSTORM_AGG_INT_FINAL_CLEANUP_COMP_TYPE (IRO[59].base)
+#define XSTORM_AGG_INT_FINAL_CLEANUP_INDEX (IRO[58].base)
+#define XSTORM_ASSERT_LIST_INDEX_OFFSET (IRO[54].base)
+#define XSTORM_ASSERT_LIST_OFFSET(assertListEntry) \
+ (IRO[53].base + ((assertListEntry) * IRO[53].m1))
+#define XSTORM_CMNG_PER_PORT_VARS_OFFSET(portId) \
+ (IRO[47].base + ((portId) * IRO[47].m1))
+#define XSTORM_E1HOV_OFFSET(pfId) \
+ (IRO[55].base + ((pfId) * IRO[55].m1))
+#define XSTORM_ETH_STATS_QUERY_ADDR_OFFSET(pfId) \
+ (IRO[45].base + ((pfId) * IRO[45].m1))
+#define XSTORM_FAIRNESS_PER_VN_VARS_OFFSET(pfId) \
+ (IRO[49].base + ((pfId) * IRO[49].m1))
+#define XSTORM_FUNC_EN_OFFSET(funcId) \
+ (IRO[51].base + ((funcId) * IRO[51].m1))
+#define XSTORM_FUNCTION_MODE_OFFSET (IRO[56].base)
+#define XSTORM_ISCSI_HQ_SIZE_OFFSET(pfId) \
+ (IRO[290].base + ((pfId) * IRO[290].m1))
+#define XSTORM_ISCSI_LOCAL_MAC_ADDR0_OFFSET(pfId) \
+ (IRO[293].base + ((pfId) * IRO[293].m1))
+#define XSTORM_ISCSI_LOCAL_MAC_ADDR1_OFFSET(pfId) \
+ (IRO[294].base + ((pfId) * IRO[294].m1))
+#define XSTORM_ISCSI_LOCAL_MAC_ADDR2_OFFSET(pfId) \
+ (IRO[295].base + ((pfId) * IRO[295].m1))
+#define XSTORM_ISCSI_LOCAL_MAC_ADDR3_OFFSET(pfId) \
+ (IRO[296].base + ((pfId) * IRO[296].m1))
+#define XSTORM_ISCSI_LOCAL_MAC_ADDR4_OFFSET(pfId) \
+ (IRO[297].base + ((pfId) * IRO[297].m1))
+#define XSTORM_ISCSI_LOCAL_MAC_ADDR5_OFFSET(pfId) \
+ (IRO[298].base + ((pfId) * IRO[298].m1))
+#define XSTORM_ISCSI_LOCAL_VLAN_OFFSET(pfId) \
+ (IRO[299].base + ((pfId) * IRO[299].m1))
+#define XSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \
+ (IRO[289].base + ((pfId) * IRO[289].m1))
+#define XSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \
+ (IRO[288].base + ((pfId) * IRO[288].m1))
+#define XSTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \
+ (IRO[287].base + ((pfId) * IRO[287].m1))
+#define XSTORM_ISCSI_R2TQ_SIZE_OFFSET(pfId) \
+ (IRO[292].base + ((pfId) * IRO[292].m1))
+#define XSTORM_ISCSI_SQ_SIZE_OFFSET(pfId) \
+ (IRO[291].base + ((pfId) * IRO[291].m1))
+#define XSTORM_ISCSI_TCP_VARS_ADV_WND_SCL_OFFSET(pfId) \
+ (IRO[286].base + ((pfId) * IRO[286].m1))
+#define XSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(pfId) \
+ (IRO[285].base + ((pfId) * IRO[285].m1))
+#define XSTORM_ISCSI_TCP_VARS_TOS_OFFSET(pfId) \
+ (IRO[284].base + ((pfId) * IRO[284].m1))
+#define XSTORM_ISCSI_TCP_VARS_TTL_OFFSET(pfId) \
+ (IRO[283].base + ((pfId) * IRO[283].m1))
+#define XSTORM_PATH_ID_OFFSET (IRO[65].base)
+ #define XSTORM_PER_COUNTER_ID_STATS_OFFSET(portId, xStatCntId) \
+ (IRO[50].base + ((portId) * IRO[50].m1) + ((xStatCntId) * \
+ IRO[50].m2))
+#define XSTORM_RATE_SHAPING_PER_VN_VARS_OFFSET(pfId) \
+ (IRO[48].base + ((pfId) * IRO[48].m1))
+#define XSTORM_SPQ_DATA_OFFSET(funcId) \
+ (IRO[32].base + ((funcId) * IRO[32].m1))
+#define XSTORM_SPQ_DATA_SIZE (IRO[32].size)
+#define XSTORM_SPQ_PAGE_BASE_OFFSET(funcId) \
+ (IRO[30].base + ((funcId) * IRO[30].m1))
+#define XSTORM_SPQ_PROD_OFFSET(funcId) \
+ (IRO[31].base + ((funcId) * IRO[31].m1))
+#define XSTORM_STATS_FLAGS_OFFSET(pfId) \
+ (IRO[43].base + ((pfId) * IRO[43].m1))
+#define XSTORM_TCP_GLOBAL_DEL_ACK_COUNTER_ENABLED_OFFSET(portId) \
+ (IRO[206].base + ((portId) * IRO[206].m1))
+#define XSTORM_TCP_GLOBAL_DEL_ACK_COUNTER_MAX_COUNT_OFFSET(portId) \
+ (IRO[207].base + ((portId) * IRO[207].m1))
+#define XSTORM_TCP_TX_SWS_TIMER_VAL_OFFSET(pfId) \
+ (IRO[209].base + (((pfId)>>1) * IRO[209].m1) + (((pfId)&1) * \
+ IRO[209].m2))
+#define XSTORM_VF_TO_PF_OFFSET(funcId) \
+ (IRO[52].base + ((funcId) * IRO[52].m1))
#define COMMON_ASM_INVALID_ASSERT_OPCODE 0x0
-/**
-* This file defines HSI constants for the ETH flow
-*/
-#ifdef _EVEREST_MICROCODE
-#include "microcode_constants.h"
-#include "eth_rx_bd.h"
-#include "eth_tx_bd.h"
-#include "eth_rx_cqe.h"
-#include "eth_rx_sge.h"
-#include "eth_rx_cqe_next_page.h"
-#endif
-
/* RSS hash types */
#define DEFAULT_HASH_TYPE 0
#define IPV4_HASH_TYPE 1
@@ -389,11 +292,17 @@
#define U_ETH_NUM_OF_SGES_TO_FETCH 8
#define U_ETH_MAX_SGES_FOR_PACKET 3
+/*Tx params*/
+#define X_ETH_NO_VLAN 0
+#define X_ETH_OUTBAND_VLAN 1
+#define X_ETH_INBAND_VLAN 2
/* Rx ring params */
#define U_ETH_LOCAL_BD_RING_SIZE 8
#define U_ETH_LOCAL_SGE_RING_SIZE 10
#define U_ETH_SGL_SIZE 8
-
+ /* The fw will padd the buffer with this value, so the IP header \
+ will be align to 4 Byte */
+#define IP_HEADER_ALIGNMENT_PADDING 2
#define U_ETH_SGES_PER_PAGE_INVERSE_MASK \
(0xFFFF - ((PAGE_SIZE/((STRUCT_SIZE(eth_rx_sge))/8))-1))
@@ -409,16 +318,15 @@
#define U_ETH_UNDEFINED_Q 0xFF
/* values of command IDs in the ramrod message */
-#define RAMROD_CMD_ID_ETH_PORT_SETUP 80
-#define RAMROD_CMD_ID_ETH_CLIENT_SETUP 85
-#define RAMROD_CMD_ID_ETH_STAT_QUERY 90
-#define RAMROD_CMD_ID_ETH_UPDATE 100
-#define RAMROD_CMD_ID_ETH_HALT 105
-#define RAMROD_CMD_ID_ETH_SET_MAC 110
-#define RAMROD_CMD_ID_ETH_CFC_DEL 115
-#define RAMROD_CMD_ID_ETH_PORT_DEL 120
-#define RAMROD_CMD_ID_ETH_FORWARD_SETUP 125
-
+#define RAMROD_CMD_ID_ETH_UNUSED 0
+#define RAMROD_CMD_ID_ETH_CLIENT_SETUP 1
+#define RAMROD_CMD_ID_ETH_UPDATE 2
+#define RAMROD_CMD_ID_ETH_HALT 3
+#define RAMROD_CMD_ID_ETH_FORWARD_SETUP 4
+#define RAMROD_CMD_ID_ETH_ACTIVATE 5
+#define RAMROD_CMD_ID_ETH_DEACTIVATE 6
+#define RAMROD_CMD_ID_ETH_EMPTY 7
+#define RAMROD_CMD_ID_ETH_TERMINATE 8
/* command values for set mac command */
#define T_ETH_MAC_COMMAND_SET 0
@@ -431,7 +339,9 @@
/* Maximal L2 clients supported */
#define ETH_MAX_RX_CLIENTS_E1 18
-#define ETH_MAX_RX_CLIENTS_E1H 26
+#define ETH_MAX_RX_CLIENTS_E1H 28
+
+#define MAX_STAT_COUNTER_ID ETH_MAX_RX_CLIENTS_E1H
/* Maximal aggregation queues supported */
#define ETH_MAX_AGGREGATION_QUEUES_E1 32
@@ -443,6 +353,20 @@
#define ETH_RSS_MODE_VLAN_PRI 2
#define ETH_RSS_MODE_E1HOV_PRI 3
#define ETH_RSS_MODE_IP_DSCP 4
+#define ETH_RSS_MODE_E2_INTEG 5
+
+
+/* ETH vlan filtering modes */
+#define ETH_VLAN_FILTER_ANY_VLAN 0 /* Don't filter by vlan */
+#define ETH_VLAN_FILTER_SPECIFIC_VLAN \
+ 1 /* Only the vlan_id is allowed */
+#define ETH_VLAN_FILTER_CLASSIFY \
+ 2 /* vlan will be added to CAM for classification */
+
+/* Fast path CQE selection */
+#define ETH_FP_CQE_REGULAR 0
+#define ETH_FP_CQE_SGL 1
+#define ETH_FP_CQE_RAW 2
/**
@@ -458,6 +382,7 @@
#define RESERVED_CONNECTION_TYPE_0 5
#define RESERVED_CONNECTION_TYPE_1 6
#define RESERVED_CONNECTION_TYPE_2 7
+#define NONE_CONNECTION_TYPE 8
#define PROTOCOL_STATE_BIT_OFFSET 6
@@ -466,6 +391,16 @@
#define TOE_STATE (TOE_CONNECTION_TYPE << PROTOCOL_STATE_BIT_OFFSET)
#define RDMA_STATE (RDMA_CONNECTION_TYPE << PROTOCOL_STATE_BIT_OFFSET)
+/* values of command IDs in the ramrod message */
+#define RAMROD_CMD_ID_COMMON_FUNCTION_START 1
+#define RAMROD_CMD_ID_COMMON_FUNCTION_STOP 2
+#define RAMROD_CMD_ID_COMMON_CFC_DEL 3
+#define RAMROD_CMD_ID_COMMON_CFC_DEL_WB 4
+#define RAMROD_CMD_ID_COMMON_SET_MAC 5
+#define RAMROD_CMD_ID_COMMON_STAT_QUERY 6
+#define RAMROD_CMD_ID_COMMON_STOP_TRAFFIC 7
+#define RAMROD_CMD_ID_COMMON_START_TRAFFIC 8
+
/* microcode fixed page page size 4K (chains and ring segments) */
#define MC_PAGE_SIZE 4096
@@ -473,46 +408,26 @@
/* Host coalescing constants */
#define HC_IGU_BC_MODE 0
#define HC_IGU_NBC_MODE 1
+/* Host coalescing constants. E1 includes E1H as well */
+
+/* Number of indices per slow-path SB */
+#define HC_SP_SB_MAX_INDICES 16
+
+/* Number of indices per SB */
+#define HC_SB_MAX_INDICES_E1X 8
+#define HC_SB_MAX_INDICES_E2 8
+
+#define HC_SB_MAX_SB_E1X 32
+#define HC_SB_MAX_SB_E2 136
+
+#define HC_SP_SB_ID 0xde
#define HC_REGULAR_SEGMENT 0
#define HC_DEFAULT_SEGMENT 1
+#define HC_SB_MAX_SM 2
-/* index numbers */
-#define HC_USTORM_DEF_SB_NUM_INDICES 8
-#define HC_CSTORM_DEF_SB_NUM_INDICES 8
-#define HC_XSTORM_DEF_SB_NUM_INDICES 4
-#define HC_TSTORM_DEF_SB_NUM_INDICES 4
-#define HC_USTORM_SB_NUM_INDICES 4
-#define HC_CSTORM_SB_NUM_INDICES 4
-
-/* index values - which counter to update */
-
-#define HC_INDEX_U_TOE_RX_CQ_CONS 0
-#define HC_INDEX_U_ETH_RX_CQ_CONS 1
-#define HC_INDEX_U_ETH_RX_BD_CONS 2
-#define HC_INDEX_U_FCOE_EQ_CONS 3
-
-#define HC_INDEX_C_TOE_TX_CQ_CONS 0
-#define HC_INDEX_C_ETH_TX_CQ_CONS 1
-#define HC_INDEX_C_ISCSI_EQ_CONS 2
-
-#define HC_INDEX_DEF_X_SPQ_CONS 0
-
-#define HC_INDEX_DEF_C_RDMA_EQ_CONS 0
-#define HC_INDEX_DEF_C_RDMA_NAL_PROD 1
-#define HC_INDEX_DEF_C_ETH_FW_TX_CQ_CONS 2
-#define HC_INDEX_DEF_C_ETH_SLOW_PATH 3
-#define HC_INDEX_DEF_C_ETH_RDMA_CQ_CONS 4
-#define HC_INDEX_DEF_C_ETH_ISCSI_CQ_CONS 5
-#define HC_INDEX_DEF_C_ETH_FCOE_CQ_CONS 6
-
-#define HC_INDEX_DEF_U_ETH_RDMA_RX_CQ_CONS 0
-#define HC_INDEX_DEF_U_ETH_ISCSI_RX_CQ_CONS 1
-#define HC_INDEX_DEF_U_ETH_RDMA_RX_BD_CONS 2
-#define HC_INDEX_DEF_U_ETH_ISCSI_RX_BD_CONS 3
-#define HC_INDEX_DEF_U_ETH_FCOE_RX_CQ_CONS 4
-#define HC_INDEX_DEF_U_ETH_FCOE_RX_BD_CONS 5
-
+#define HC_SB_MAX_DYNAMIC_INDICES 4
+#define HC_FUNCTION_DISABLED 0xff
/* used by the driver to get the SB offset */
#define USTORM_ID 0
#define CSTORM_ID 1
@@ -529,45 +444,17 @@
/**** DEFINES FOR TIMERS/CLOCKS RESOLUTIONS ****/
-#define EMULATION_FREQUENCY_FACTOR 1600
-#define FPGA_FREQUENCY_FACTOR 100
#define TIMERS_TICK_SIZE_CHIP (1e-3)
-#define TIMERS_TICK_SIZE_EMUL \
- ((TIMERS_TICK_SIZE_CHIP)/((EMULATION_FREQUENCY_FACTOR)))
-#define TIMERS_TICK_SIZE_FPGA \
- ((TIMERS_TICK_SIZE_CHIP)/((FPGA_FREQUENCY_FACTOR)))
#define TSEMI_CLK1_RESUL_CHIP (1e-3)
-#define TSEMI_CLK1_RESUL_EMUL \
- ((TSEMI_CLK1_RESUL_CHIP)/(EMULATION_FREQUENCY_FACTOR))
-#define TSEMI_CLK1_RESUL_FPGA \
- ((TSEMI_CLK1_RESUL_CHIP)/(FPGA_FREQUENCY_FACTOR))
-
-#define USEMI_CLK1_RESUL_CHIP (TIMERS_TICK_SIZE_CHIP)
-#define USEMI_CLK1_RESUL_EMUL (TIMERS_TICK_SIZE_EMUL)
-#define USEMI_CLK1_RESUL_FPGA (TIMERS_TICK_SIZE_FPGA)
#define XSEMI_CLK1_RESUL_CHIP (1e-3)
-#define XSEMI_CLK1_RESUL_EMUL \
- ((XSEMI_CLK1_RESUL_CHIP)/(EMULATION_FREQUENCY_FACTOR))
-#define XSEMI_CLK1_RESUL_FPGA \
- ((XSEMI_CLK1_RESUL_CHIP)/(FPGA_FREQUENCY_FACTOR))
-
-#define XSEMI_CLK2_RESUL_CHIP (1e-6)
-#define XSEMI_CLK2_RESUL_EMUL \
- ((XSEMI_CLK2_RESUL_CHIP)/(EMULATION_FREQUENCY_FACTOR))
-#define XSEMI_CLK2_RESUL_FPGA \
- ((XSEMI_CLK2_RESUL_CHIP)/(FPGA_FREQUENCY_FACTOR))
#define SDM_TIMER_TICK_RESUL_CHIP (4*(1e-6))
-#define SDM_TIMER_TICK_RESUL_EMUL \
- ((SDM_TIMER_TICK_RESUL_CHIP)/(EMULATION_FREQUENCY_FACTOR))
-#define SDM_TIMER_TICK_RESUL_FPGA \
- ((SDM_TIMER_TICK_RESUL_CHIP)/(FPGA_FREQUENCY_FACTOR))
-
/**** END DEFINES FOR TIMERS/CLOCKS RESOLUTIONS ****/
+
#define XSTORM_IP_ID_ROLL_HALF 0x8000
#define XSTORM_IP_ID_ROLL_ALL 0
@@ -576,10 +463,36 @@
#define NUM_OF_PROTOCOLS 4
#define NUM_OF_SAFC_BITS 16
#define MAX_COS_NUMBER 4
-#define MAX_T_STAT_COUNTER_ID 18
-#define MAX_X_STAT_COUNTER_ID 18
-#define MAX_U_STAT_COUNTER_ID 18
+#define FAIRNESS_COS_WRR_MODE 0
+#define FAIRNESS_COS_ETS_MODE 1
+
+
+/* Priority Flow Control (PFC) */
+#define MAX_PFC_PRIORITIES 8
+#define MAX_PFC_TRAFFIC_TYPES 8
+
+/* Available Traffic Types for Link Layer Flow Control */
+#define LLFC_TRAFFIC_TYPE_NW 0
+#define LLFC_TRAFFIC_TYPE_FCOE 1
+#define LLFC_TRAFFIC_TYPE_ISCSI 2
+ /***************** START OF E2 INTEGRATION \
+ CODE***************************************/
+#define LLFC_TRAFFIC_TYPE_NW_COS1_E2INTEG 3
+ /***************** END OF E2 INTEGRATION \
+ CODE***************************************/
+#define LLFC_TRAFFIC_TYPE_MAX 4
+
+ /* used by array traffic_type_to_priority[] to mark traffic type \
+ that is not mapped to priority*/
+#define LLFC_TRAFFIC_TYPE_TO_PRIORITY_UNMAPPED 0xFF
+
+#define LLFC_MODE_NONE 0
+#define LLFC_MODE_PFC 1
+#define LLFC_MODE_SAFC 2
+
+#define DCB_DISABLED 0
+#define DCB_ENABLED 1
#define UNKNOWN_ADDRESS 0
#define UNICAST_ADDRESS 1
@@ -587,8 +500,32 @@
#define BROADCAST_ADDRESS 3
#define SINGLE_FUNCTION 0
-#define MULTI_FUNCTION 1
+#define MULTI_FUNCTION_SD 1
+#define MULTI_FUNCTION_SI 2
#define IP_V4 0
#define IP_V6 1
+
+#define C_ERES_PER_PAGE \
+ (PAGE_SIZE / BITS_TO_BYTES(STRUCT_SIZE(event_ring_elem)))
+#define C_ERE_PER_PAGE_MASK (C_ERES_PER_PAGE - 1)
+
+#define EVENT_RING_OPCODE_VF_PF_CHANNEL 0
+#define EVENT_RING_OPCODE_FUNCTION_START 1
+#define EVENT_RING_OPCODE_FUNCTION_STOP 2
+#define EVENT_RING_OPCODE_CFC_DEL 3
+#define EVENT_RING_OPCODE_CFC_DEL_WB 4
+#define EVENT_RING_OPCODE_SET_MAC 5
+#define EVENT_RING_OPCODE_STAT_QUERY 6
+#define EVENT_RING_OPCODE_STOP_TRAFFIC 7
+#define EVENT_RING_OPCODE_START_TRAFFIC 8
+#define EVENT_RING_OPCODE_FORWARD_SETUP 9
+
+#define VF_PF_CHANNEL_STATE_READY 0
+#define VF_PF_CHANNEL_STATE_WAITING_FOR_ACK 1
+
+#define VF_PF_CHANNEL_STATE_MAX_NUMBER 2
+
+
+#endif /* BNX2X_FW_DEFS_H */
diff --git a/drivers/net/bnx2x/bnx2x_fw_file_hdr.h b/drivers/net/bnx2x/bnx2x_fw_file_hdr.h
index 3f5ee5d7cc2a..f807262911e5 100644
--- a/drivers/net/bnx2x/bnx2x_fw_file_hdr.h
+++ b/drivers/net/bnx2x/bnx2x_fw_file_hdr.h
@@ -31,6 +31,7 @@ struct bnx2x_fw_file_hdr {
struct bnx2x_fw_file_section csem_pram_data;
struct bnx2x_fw_file_section xsem_int_table_data;
struct bnx2x_fw_file_section xsem_pram_data;
+ struct bnx2x_fw_file_section iro_arr;
struct bnx2x_fw_file_section fw_version;
};
diff --git a/drivers/net/bnx2x/bnx2x_hsi.h b/drivers/net/bnx2x/bnx2x_hsi.h
index fd1f29e0317d..18c8e23a0e82 100644
--- a/drivers/net/bnx2x/bnx2x_hsi.h
+++ b/drivers/net/bnx2x/bnx2x_hsi.h
@@ -6,6 +6,10 @@
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation.
*/
+#ifndef BNX2X_HSI_H
+#define BNX2X_HSI_H
+
+#include "bnx2x_fw_defs.h"
struct license_key {
u32 reserved[6];
@@ -78,6 +82,8 @@ struct shared_hw_cfg { /* NVRAM Offset */
#define SHARED_HW_CFG_LED_PHY11 0x000b0000
#define SHARED_HW_CFG_LED_MAC4 0x000c0000
#define SHARED_HW_CFG_LED_PHY8 0x000d0000
+#define SHARED_HW_CFG_LED_EXTPHY1 0x000e0000
+
#define SHARED_HW_CFG_AN_ENABLE_MASK 0x3f000000
#define SHARED_HW_CFG_AN_ENABLE_SHIFT 24
@@ -120,6 +126,23 @@ struct shared_hw_cfg { /* NVRAM Offset */
#define SHARED_HW_CFG_FAN_FAILURE_DISABLED 0x00080000
#define SHARED_HW_CFG_FAN_FAILURE_ENABLED 0x00100000
+ /* Set the MDC/MDIO access for the first external phy */
+#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_MASK 0x1C000000
+#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_SHIFT 26
+#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_PHY_TYPE 0x00000000
+#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC0 0x04000000
+#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC1 0x08000000
+#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH 0x0c000000
+#define SHARED_HW_CFG_MDC_MDIO_ACCESS1_SWAPPED 0x10000000
+
+ /* Set the MDC/MDIO access for the second external phy */
+#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_MASK 0xE0000000
+#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_SHIFT 29
+#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_PHY_TYPE 0x00000000
+#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_EMAC0 0x20000000
+#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_EMAC1 0x40000000
+#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_BOTH 0x60000000
+#define SHARED_HW_CFG_MDC_MDIO_ACCESS2_SWAPPED 0x80000000
u32 power_dissipated; /* 0x11c */
#define SHARED_HW_CFG_POWER_DIS_CMN_MASK 0xff000000
#define SHARED_HW_CFG_POWER_DIS_CMN_SHIFT 24
@@ -221,11 +244,93 @@ struct port_hw_cfg { /* port 0: 0x12c port 1: 0x2bc */
u16 xgxs_config_tx[4]; /* 0x1A0 */
- u32 Reserved1[64]; /* 0x1A8 */
+ u32 Reserved1[57]; /* 0x1A8 */
+ u32 speed_capability_mask2; /* 0x28C */
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_MASK 0x0000FFFF
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_SHIFT 0
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_10M_FULL 0x00000001
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D3__ 0x00000002
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D3___ 0x00000004
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_100M_FULL 0x00000008
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_1G 0x00000010
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_2_DOT_5G 0x00000020
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_10G 0x00000040
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_12G 0x00000080
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_12_DOT_5G 0x00000100
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_13G 0x00000200
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_15G 0x00000400
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D3_16G 0x00000800
+
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_MASK 0xFFFF0000
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_SHIFT 16
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_10M_FULL 0x00010000
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D0__ 0x00020000
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D0___ 0x00040000
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_100M_FULL 0x00080000
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_1G 0x00100000
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_2_DOT_5G 0x00200000
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_10G 0x00400000
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_12G 0x00800000
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_12_DOT_5G 0x01000000
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_13G 0x02000000
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_15G 0x04000000
+#define PORT_HW_CFG_SPEED_CAPABILITY2_D0_16G 0x08000000
+
+ /* In the case where two media types (e.g. copper and fiber) are
+ present and electrically active at the same time, PHY Selection
+ will determine which of the two PHYs will be designated as the
+ Active PHY and used for a connection to the network. */
+ u32 multi_phy_config; /* 0x290 */
+#define PORT_HW_CFG_PHY_SELECTION_MASK 0x00000007
+#define PORT_HW_CFG_PHY_SELECTION_SHIFT 0
+#define PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT 0x00000000
+#define PORT_HW_CFG_PHY_SELECTION_FIRST_PHY 0x00000001
+#define PORT_HW_CFG_PHY_SELECTION_SECOND_PHY 0x00000002
+#define PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY 0x00000003
+#define PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY 0x00000004
+
+ /* When enabled, all second phy nvram parameters will be swapped
+ with the first phy parameters */
+#define PORT_HW_CFG_PHY_SWAPPED_MASK 0x00000008
+#define PORT_HW_CFG_PHY_SWAPPED_SHIFT 3
+#define PORT_HW_CFG_PHY_SWAPPED_DISABLED 0x00000000
+#define PORT_HW_CFG_PHY_SWAPPED_ENABLED 0x00000008
+
+
+ /* Address of the second external phy */
+ u32 external_phy_config2; /* 0x294 */
+#define PORT_HW_CFG_XGXS_EXT_PHY2_ADDR_MASK 0x000000FF
+#define PORT_HW_CFG_XGXS_EXT_PHY2_ADDR_SHIFT 0
+
+ /* The second XGXS external PHY type */
+#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_MASK 0x0000FF00
+#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_SHIFT 8
+#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_DIRECT 0x00000000
+#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8071 0x00000100
+#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8072 0x00000200
+#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8073 0x00000300
+#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8705 0x00000400
+#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8706 0x00000500
+#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8726 0x00000600
+#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8481 0x00000700
+#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_SFX7101 0x00000800
+#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8727 0x00000900
+#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8727_NOC 0x00000a00
+#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM84823 0x00000b00
+#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM54640 0x00000c00
+#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM84833 0x00000d00
+#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_FAILURE 0x0000fd00
+#define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_NOT_CONN 0x0000ff00
+
+ /* 4 times 16 bits for all 4 lanes. For some external PHYs (such as
+ 8706, 8726 and 8727) not all 4 values are needed. */
+ u16 xgxs_config2_rx[4]; /* 0x296 */
+ u16 xgxs_config2_tx[4]; /* 0x2A0 */
u32 lane_config;
#define PORT_HW_CFG_LANE_SWAP_CFG_MASK 0x0000ffff
#define PORT_HW_CFG_LANE_SWAP_CFG_SHIFT 0
+
#define PORT_HW_CFG_LANE_SWAP_CFG_TX_MASK 0x000000ff
#define PORT_HW_CFG_LANE_SWAP_CFG_TX_SHIFT 0
#define PORT_HW_CFG_LANE_SWAP_CFG_RX_MASK 0x0000ff00
@@ -515,10 +620,17 @@ struct port_feat_cfg { /* port 0: 0x454 port 1: 0x4c8 */
#define PORT_FEATURE_FLOW_CONTROL_NONE 0x00000400
/* The default for MCP link configuration,
- uses the same defines as link_config */
+ uses the same defines as link_config */
u32 mfw_wol_link_cfg;
+ /* The default for the driver of the second external phy,
+ uses the same defines as link_config */
+ u32 link_config2; /* 0x47C */
- u32 reserved[19];
+ /* The default for MCP of the second external phy,
+ uses the same defines as link_config */
+ u32 mfw_wol_link_cfg2; /* 0x480 */
+
+ u32 Reserved2[17]; /* 0x484 */
};
@@ -551,6 +663,7 @@ struct shm_dev_info { /* size */
#define FUNC_7 7
#define E1_FUNC_MAX 2
#define E1H_FUNC_MAX 8
+#define E2_FUNC_MAX 4 /* per path */
#define VN_0 0
#define VN_1 1
@@ -686,8 +799,14 @@ struct drv_func_mb {
* The optic module verification commands require bootcode
* v5.0.6 or later
*/
-#define DRV_MSG_CODE_VRFY_OPT_MDL 0xa0000000
-#define REQ_BC_VER_4_VRFY_OPT_MDL 0x00050006
+#define DRV_MSG_CODE_VRFY_FIRST_PHY_OPT_MDL 0xa0000000
+#define REQ_BC_VER_4_VRFY_FIRST_PHY_OPT_MDL 0x00050006
+ /*
+ * The specific optic module verification command requires bootcode
+ * v5.2.12 or later
+ */
+#define DRV_MSG_CODE_VRFY_SPECIFIC_PHY_OPT_MDL 0xa1000000
+#define REQ_BC_VER_4_VRFY_SPECIFIC_PHY_OPT_MDL 0x00050234
#define BIOS_MSG_CODE_LIC_CHALLENGE 0xff010000
#define BIOS_MSG_CODE_LIC_RESPONSE 0xff020000
@@ -703,6 +822,9 @@ struct drv_func_mb {
#define FW_MSG_CODE_DRV_LOAD_COMMON 0x10100000
#define FW_MSG_CODE_DRV_LOAD_PORT 0x10110000
#define FW_MSG_CODE_DRV_LOAD_FUNCTION 0x10120000
+ /* Load common chip is supported from bc 6.0.0 */
+#define REQ_BC_VER_4_DRV_LOAD_COMMON_CHIP 0x00060000
+#define FW_MSG_CODE_DRV_LOAD_COMMON_CHIP 0x10130000
#define FW_MSG_CODE_DRV_LOAD_REFUSED 0x10200000
#define FW_MSG_CODE_DRV_LOAD_DONE 0x11100000
#define FW_MSG_CODE_DRV_UNLOAD_COMMON 0x20100000
@@ -903,11 +1025,22 @@ struct shmem_region { /* SharedMem Offset (size) */
struct mgmtfw_state mgmtfw_state; /* 0x4ac (0x1b8) */
struct drv_port_mb port_mb[PORT_MAX]; /* 0x664 (16*2=0x20) */
- struct drv_func_mb func_mb[E1H_FUNC_MAX];
+ struct drv_func_mb func_mb[]; /* 0x684
+ (44*2/4/8=0x58/0xb0/0x160) */
+
+}; /* 57710 = 0x6dc | 57711 = 0x7E4 | 57712 = 0x734 */
- struct mf_cfg mf_cfg;
+struct fw_flr_ack {
+ u32 pf_ack;
+ u32 vf_ack[1];
+ u32 iov_dis_ack;
+};
-}; /* 0x6dc */
+struct fw_flr_mb {
+ u32 aggint;
+ u32 opgen_addr;
+ struct fw_flr_ack ack;
+};
struct shmem2_region {
@@ -922,7 +1055,25 @@ struct shmem2_region {
#define SHMEM_DCC_SUPPORT_SET_PROTOCOL_TLV 0x00000040
#define SHMEM_DCC_SUPPORT_SET_PRIORITY_TLV 0x00000080
#define SHMEM_DCC_SUPPORT_DEFAULT SHMEM_DCC_SUPPORT_NONE
-
+ u32 ext_phy_fw_version2[PORT_MAX];
+ /*
+ * For backwards compatibility, if the mf_cfg_addr does not exist
+ * (the size filed is smaller than 0xc) the mf_cfg resides at the
+ * end of struct shmem_region
+ */
+ u32 mf_cfg_addr;
+#define SHMEM_MF_CFG_ADDR_NONE 0x00000000
+
+ struct fw_flr_mb flr_mb;
+ u32 reserved[3];
+ /*
+ * The other shmemX_base_addr holds the other path's shmem address
+ * required for example in case of common phy init, or for path1 to know
+ * the address of mcp debug trace which is located in offset from shmem
+ * of path0
+ */
+ u32 other_shmem_base_addr;
+ u32 other_shmem2_base_addr;
};
@@ -978,7 +1129,7 @@ struct emac_stats {
};
-struct bmac_stats {
+struct bmac1_stats {
u32 tx_stat_gtpkt_lo;
u32 tx_stat_gtpkt_hi;
u32 tx_stat_gtxpf_lo;
@@ -1082,10 +1233,126 @@ struct bmac_stats {
u32 rx_stat_gripj_hi;
};
+struct bmac2_stats {
+ u32 tx_stat_gtpk_lo; /* gtpok */
+ u32 tx_stat_gtpk_hi; /* gtpok */
+ u32 tx_stat_gtxpf_lo; /* gtpf */
+ u32 tx_stat_gtxpf_hi; /* gtpf */
+ u32 tx_stat_gtpp_lo; /* NEW BMAC2 */
+ u32 tx_stat_gtpp_hi; /* NEW BMAC2 */
+ u32 tx_stat_gtfcs_lo;
+ u32 tx_stat_gtfcs_hi;
+ u32 tx_stat_gtuca_lo; /* NEW BMAC2 */
+ u32 tx_stat_gtuca_hi; /* NEW BMAC2 */
+ u32 tx_stat_gtmca_lo;
+ u32 tx_stat_gtmca_hi;
+ u32 tx_stat_gtbca_lo;
+ u32 tx_stat_gtbca_hi;
+ u32 tx_stat_gtovr_lo;
+ u32 tx_stat_gtovr_hi;
+ u32 tx_stat_gtfrg_lo;
+ u32 tx_stat_gtfrg_hi;
+ u32 tx_stat_gtpkt1_lo; /* gtpkt */
+ u32 tx_stat_gtpkt1_hi; /* gtpkt */
+ u32 tx_stat_gt64_lo;
+ u32 tx_stat_gt64_hi;
+ u32 tx_stat_gt127_lo;
+ u32 tx_stat_gt127_hi;
+ u32 tx_stat_gt255_lo;
+ u32 tx_stat_gt255_hi;
+ u32 tx_stat_gt511_lo;
+ u32 tx_stat_gt511_hi;
+ u32 tx_stat_gt1023_lo;
+ u32 tx_stat_gt1023_hi;
+ u32 tx_stat_gt1518_lo;
+ u32 tx_stat_gt1518_hi;
+ u32 tx_stat_gt2047_lo;
+ u32 tx_stat_gt2047_hi;
+ u32 tx_stat_gt4095_lo;
+ u32 tx_stat_gt4095_hi;
+ u32 tx_stat_gt9216_lo;
+ u32 tx_stat_gt9216_hi;
+ u32 tx_stat_gt16383_lo;
+ u32 tx_stat_gt16383_hi;
+ u32 tx_stat_gtmax_lo;
+ u32 tx_stat_gtmax_hi;
+ u32 tx_stat_gtufl_lo;
+ u32 tx_stat_gtufl_hi;
+ u32 tx_stat_gterr_lo;
+ u32 tx_stat_gterr_hi;
+ u32 tx_stat_gtbyt_lo;
+ u32 tx_stat_gtbyt_hi;
+
+ u32 rx_stat_gr64_lo;
+ u32 rx_stat_gr64_hi;
+ u32 rx_stat_gr127_lo;
+ u32 rx_stat_gr127_hi;
+ u32 rx_stat_gr255_lo;
+ u32 rx_stat_gr255_hi;
+ u32 rx_stat_gr511_lo;
+ u32 rx_stat_gr511_hi;
+ u32 rx_stat_gr1023_lo;
+ u32 rx_stat_gr1023_hi;
+ u32 rx_stat_gr1518_lo;
+ u32 rx_stat_gr1518_hi;
+ u32 rx_stat_gr2047_lo;
+ u32 rx_stat_gr2047_hi;
+ u32 rx_stat_gr4095_lo;
+ u32 rx_stat_gr4095_hi;
+ u32 rx_stat_gr9216_lo;
+ u32 rx_stat_gr9216_hi;
+ u32 rx_stat_gr16383_lo;
+ u32 rx_stat_gr16383_hi;
+ u32 rx_stat_grmax_lo;
+ u32 rx_stat_grmax_hi;
+ u32 rx_stat_grpkt_lo;
+ u32 rx_stat_grpkt_hi;
+ u32 rx_stat_grfcs_lo;
+ u32 rx_stat_grfcs_hi;
+ u32 rx_stat_gruca_lo;
+ u32 rx_stat_gruca_hi;
+ u32 rx_stat_grmca_lo;
+ u32 rx_stat_grmca_hi;
+ u32 rx_stat_grbca_lo;
+ u32 rx_stat_grbca_hi;
+ u32 rx_stat_grxpf_lo; /* grpf */
+ u32 rx_stat_grxpf_hi; /* grpf */
+ u32 rx_stat_grpp_lo;
+ u32 rx_stat_grpp_hi;
+ u32 rx_stat_grxuo_lo; /* gruo */
+ u32 rx_stat_grxuo_hi; /* gruo */
+ u32 rx_stat_grjbr_lo;
+ u32 rx_stat_grjbr_hi;
+ u32 rx_stat_grovr_lo;
+ u32 rx_stat_grovr_hi;
+ u32 rx_stat_grxcf_lo; /* grcf */
+ u32 rx_stat_grxcf_hi; /* grcf */
+ u32 rx_stat_grflr_lo;
+ u32 rx_stat_grflr_hi;
+ u32 rx_stat_grpok_lo;
+ u32 rx_stat_grpok_hi;
+ u32 rx_stat_grmeg_lo;
+ u32 rx_stat_grmeg_hi;
+ u32 rx_stat_grmeb_lo;
+ u32 rx_stat_grmeb_hi;
+ u32 rx_stat_grbyt_lo;
+ u32 rx_stat_grbyt_hi;
+ u32 rx_stat_grund_lo;
+ u32 rx_stat_grund_hi;
+ u32 rx_stat_grfrg_lo;
+ u32 rx_stat_grfrg_hi;
+ u32 rx_stat_grerb_lo; /* grerrbyt */
+ u32 rx_stat_grerb_hi; /* grerrbyt */
+ u32 rx_stat_grfre_lo; /* grfrerr */
+ u32 rx_stat_grfre_hi; /* grfrerr */
+ u32 rx_stat_gripj_lo;
+ u32 rx_stat_gripj_hi;
+};
union mac_stats {
- struct emac_stats emac_stats;
- struct bmac_stats bmac_stats;
+ struct emac_stats emac_stats;
+ struct bmac1_stats bmac1_stats;
+ struct bmac2_stats bmac2_stats;
};
@@ -1259,17 +1526,17 @@ struct host_func_stats {
};
-#define BCM_5710_FW_MAJOR_VERSION 5
-#define BCM_5710_FW_MINOR_VERSION 2
-#define BCM_5710_FW_REVISION_VERSION 13
-#define BCM_5710_FW_ENGINEERING_VERSION 0
+#define BCM_5710_FW_MAJOR_VERSION 6
+#define BCM_5710_FW_MINOR_VERSION 0
+#define BCM_5710_FW_REVISION_VERSION 34
+#define BCM_5710_FW_ENGINEERING_VERSION 0
#define BCM_5710_FW_COMPILE_FLAGS 1
/*
* attention bits
*/
-struct atten_def_status_block {
+struct atten_sp_status_block {
__le32 attn_bits;
__le32 attn_bits_ack;
u8 status_block_id;
@@ -1327,7 +1594,60 @@ struct doorbell_set_prod {
/*
- * IGU driver acknowledgement register
+ * 3 lines. status block
+ */
+struct hc_status_block_e1x {
+ __le16 index_values[HC_SB_MAX_INDICES_E1X];
+ __le16 running_index[HC_SB_MAX_SM];
+ u32 rsrv;
+};
+
+/*
+ * host status block
+ */
+struct host_hc_status_block_e1x {
+ struct hc_status_block_e1x sb;
+};
+
+
+/*
+ * 3 lines. status block
+ */
+struct hc_status_block_e2 {
+ __le16 index_values[HC_SB_MAX_INDICES_E2];
+ __le16 running_index[HC_SB_MAX_SM];
+ u32 reserved;
+};
+
+/*
+ * host status block
+ */
+struct host_hc_status_block_e2 {
+ struct hc_status_block_e2 sb;
+};
+
+
+/*
+ * 5 lines. slow-path status block
+ */
+struct hc_sp_status_block {
+ __le16 index_values[HC_SP_SB_MAX_INDICES];
+ __le16 running_index;
+ __le16 rsrv;
+ u32 rsrv1;
+};
+
+/*
+ * host status block
+ */
+struct host_sp_status_block {
+ struct atten_sp_status_block atten_status_block;
+ struct hc_sp_status_block sp_sb;
+};
+
+
+/*
+ * IGU driver acknowledgment register
*/
struct igu_ack_register {
#if defined(__BIG_ENDIAN)
@@ -1417,6 +1737,24 @@ union igu_consprod_reg {
/*
+ * Control register for the IGU command register
+ */
+struct igu_ctrl_reg {
+ u32 ctrl_data;
+#define IGU_CTRL_REG_ADDRESS (0xFFF<<0)
+#define IGU_CTRL_REG_ADDRESS_SHIFT 0
+#define IGU_CTRL_REG_FID (0x7F<<12)
+#define IGU_CTRL_REG_FID_SHIFT 12
+#define IGU_CTRL_REG_RESERVED (0x1<<19)
+#define IGU_CTRL_REG_RESERVED_SHIFT 19
+#define IGU_CTRL_REG_TYPE (0x1<<20)
+#define IGU_CTRL_REG_TYPE_SHIFT 20
+#define IGU_CTRL_REG_UNUSED (0x7FF<<21)
+#define IGU_CTRL_REG_UNUSED_SHIFT 21
+};
+
+
+/*
* Parser parsing flags field
*/
struct parsing_flags {
@@ -1485,8 +1823,14 @@ struct dmae_command {
#define DMAE_COMMAND_DST_RESET_SHIFT 14
#define DMAE_COMMAND_E1HVN (0x3<<15)
#define DMAE_COMMAND_E1HVN_SHIFT 15
-#define DMAE_COMMAND_RESERVED0 (0x7FFF<<17)
-#define DMAE_COMMAND_RESERVED0_SHIFT 17
+#define DMAE_COMMAND_DST_VN (0x3<<17)
+#define DMAE_COMMAND_DST_VN_SHIFT 17
+#define DMAE_COMMAND_C_FUNC (0x1<<19)
+#define DMAE_COMMAND_C_FUNC_SHIFT 19
+#define DMAE_COMMAND_ERR_POLICY (0x3<<20)
+#define DMAE_COMMAND_ERR_POLICY_SHIFT 20
+#define DMAE_COMMAND_RESERVED0 (0x3FF<<22)
+#define DMAE_COMMAND_RESERVED0_SHIFT 22
u32 src_addr_lo;
u32 src_addr_hi;
u32 dst_addr_lo;
@@ -1511,11 +1855,11 @@ struct dmae_command {
u16 crc16_c;
#endif
#if defined(__BIG_ENDIAN)
- u16 reserved2;
+ u16 reserved3;
u16 crc_t10;
#elif defined(__LITTLE_ENDIAN)
u16 crc_t10;
- u16 reserved2;
+ u16 reserved3;
#endif
#if defined(__BIG_ENDIAN)
u16 xsum8;
@@ -1536,96 +1880,20 @@ struct double_regpair {
/*
- * The eth storm context of Ustorm (configuration part)
+ * SDM operation gen command (generate aggregative interrupt)
*/
-struct ustorm_eth_st_context_config {
-#if defined(__BIG_ENDIAN)
- u8 flags;
-#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_MC_ALIGNMENT (0x1<<0)
-#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_MC_ALIGNMENT_SHIFT 0
-#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_DYNAMIC_HC (0x1<<1)
-#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_DYNAMIC_HC_SHIFT 1
-#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_TPA (0x1<<2)
-#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_TPA_SHIFT 2
-#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_STATISTICS (0x1<<3)
-#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_STATISTICS_SHIFT 3
-#define __USTORM_ETH_ST_CONTEXT_CONFIG_RESERVED0 (0xF<<4)
-#define __USTORM_ETH_ST_CONTEXT_CONFIG_RESERVED0_SHIFT 4
- u8 status_block_id;
- u8 clientId;
- u8 sb_index_numbers;
-#define USTORM_ETH_ST_CONTEXT_CONFIG_CQE_SB_INDEX_NUMBER (0xF<<0)
-#define USTORM_ETH_ST_CONTEXT_CONFIG_CQE_SB_INDEX_NUMBER_SHIFT 0
-#define USTORM_ETH_ST_CONTEXT_CONFIG_BD_SB_INDEX_NUMBER (0xF<<4)
-#define USTORM_ETH_ST_CONTEXT_CONFIG_BD_SB_INDEX_NUMBER_SHIFT 4
-#elif defined(__LITTLE_ENDIAN)
- u8 sb_index_numbers;
-#define USTORM_ETH_ST_CONTEXT_CONFIG_CQE_SB_INDEX_NUMBER (0xF<<0)
-#define USTORM_ETH_ST_CONTEXT_CONFIG_CQE_SB_INDEX_NUMBER_SHIFT 0
-#define USTORM_ETH_ST_CONTEXT_CONFIG_BD_SB_INDEX_NUMBER (0xF<<4)
-#define USTORM_ETH_ST_CONTEXT_CONFIG_BD_SB_INDEX_NUMBER_SHIFT 4
- u8 clientId;
- u8 status_block_id;
- u8 flags;
-#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_MC_ALIGNMENT (0x1<<0)
-#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_MC_ALIGNMENT_SHIFT 0
-#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_DYNAMIC_HC (0x1<<1)
-#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_DYNAMIC_HC_SHIFT 1
-#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_TPA (0x1<<2)
-#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_TPA_SHIFT 2
-#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_STATISTICS (0x1<<3)
-#define USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_STATISTICS_SHIFT 3
-#define __USTORM_ETH_ST_CONTEXT_CONFIG_RESERVED0 (0xF<<4)
-#define __USTORM_ETH_ST_CONTEXT_CONFIG_RESERVED0_SHIFT 4
-#endif
-#if defined(__BIG_ENDIAN)
- u16 bd_buff_size;
- u8 statistics_counter_id;
- u8 mc_alignment_log_size;
-#elif defined(__LITTLE_ENDIAN)
- u8 mc_alignment_log_size;
- u8 statistics_counter_id;
- u16 bd_buff_size;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 __local_sge_prod;
- u8 __local_bd_prod;
- u16 sge_buff_size;
-#elif defined(__LITTLE_ENDIAN)
- u16 sge_buff_size;
- u8 __local_bd_prod;
- u8 __local_sge_prod;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 __sdm_bd_expected_counter;
- u8 cstorm_agg_int;
- u8 __expected_bds_on_ram;
-#elif defined(__LITTLE_ENDIAN)
- u8 __expected_bds_on_ram;
- u8 cstorm_agg_int;
- u16 __sdm_bd_expected_counter;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 __ring_data_ram_addr;
- u16 __hc_cstorm_ram_addr;
-#elif defined(__LITTLE_ENDIAN)
- u16 __hc_cstorm_ram_addr;
- u16 __ring_data_ram_addr;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 reserved1;
- u8 max_sges_for_packet;
- u16 __bd_ring_ram_addr;
-#elif defined(__LITTLE_ENDIAN)
- u16 __bd_ring_ram_addr;
- u8 max_sges_for_packet;
- u8 reserved1;
-#endif
- u32 bd_page_base_lo;
- u32 bd_page_base_hi;
- u32 sge_page_base_lo;
- u32 sge_page_base_hi;
- struct regpair reserved2;
+struct sdm_op_gen {
+ __le32 command;
+#define SDM_OP_GEN_COMP_PARAM (0x1F<<0)
+#define SDM_OP_GEN_COMP_PARAM_SHIFT 0
+#define SDM_OP_GEN_COMP_TYPE (0x7<<5)
+#define SDM_OP_GEN_COMP_TYPE_SHIFT 5
+#define SDM_OP_GEN_AGG_VECT_IDX (0xFF<<8)
+#define SDM_OP_GEN_AGG_VECT_IDX_SHIFT 8
+#define SDM_OP_GEN_AGG_VECT_IDX_VALID (0x1<<16)
+#define SDM_OP_GEN_AGG_VECT_IDX_VALID_SHIFT 16
+#define SDM_OP_GEN_RESERVED (0x7FFF<<17)
+#define SDM_OP_GEN_RESERVED_SHIFT 17
};
/*
@@ -1644,20 +1912,13 @@ struct eth_rx_sge {
__le32 addr_hi;
};
-/*
- * Local BDs and SGEs rings (in ETH)
- */
-struct eth_local_rx_rings {
- struct eth_rx_bd __local_bd_ring[8];
- struct eth_rx_sge __local_sge_ring[10];
-};
+
/*
* The eth storm context of Ustorm
*/
struct ustorm_eth_st_context {
- struct ustorm_eth_st_context_config common;
- struct eth_local_rx_rings __rings;
+ u32 reserved0[48];
};
/*
@@ -1668,337 +1929,53 @@ struct tstorm_eth_st_context {
};
/*
- * The eth aggregative context section of Xstorm
- */
-struct xstorm_eth_extra_ag_context_section {
-#if defined(__BIG_ENDIAN)
- u8 __tcp_agg_vars1;
- u8 __reserved50;
- u16 __mss;
-#elif defined(__LITTLE_ENDIAN)
- u16 __mss;
- u8 __reserved50;
- u8 __tcp_agg_vars1;
-#endif
- u32 __snd_nxt;
- u32 __tx_wnd;
- u32 __snd_una;
- u32 __reserved53;
-#if defined(__BIG_ENDIAN)
- u8 __agg_val8_th;
- u8 __agg_val8;
- u16 __tcp_agg_vars2;
-#elif defined(__LITTLE_ENDIAN)
- u16 __tcp_agg_vars2;
- u8 __agg_val8;
- u8 __agg_val8_th;
-#endif
- u32 __reserved58;
- u32 __reserved59;
- u32 __reserved60;
- u32 __reserved61;
-#if defined(__BIG_ENDIAN)
- u16 __agg_val7_th;
- u16 __agg_val7;
-#elif defined(__LITTLE_ENDIAN)
- u16 __agg_val7;
- u16 __agg_val7_th;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 __tcp_agg_vars5;
- u8 __tcp_agg_vars4;
- u8 __tcp_agg_vars3;
- u8 __reserved62;
-#elif defined(__LITTLE_ENDIAN)
- u8 __reserved62;
- u8 __tcp_agg_vars3;
- u8 __tcp_agg_vars4;
- u8 __tcp_agg_vars5;
-#endif
- u32 __tcp_agg_vars6;
-#if defined(__BIG_ENDIAN)
- u16 __agg_misc6;
- u16 __tcp_agg_vars7;
-#elif defined(__LITTLE_ENDIAN)
- u16 __tcp_agg_vars7;
- u16 __agg_misc6;
-#endif
- u32 __agg_val10;
- u32 __agg_val10_th;
-#if defined(__BIG_ENDIAN)
- u16 __reserved3;
- u8 __reserved2;
- u8 __da_only_cnt;
-#elif defined(__LITTLE_ENDIAN)
- u8 __da_only_cnt;
- u8 __reserved2;
- u16 __reserved3;
-#endif
-};
-
-/*
* The eth aggregative context of Xstorm
*/
struct xstorm_eth_ag_context {
-#if defined(__BIG_ENDIAN)
- u16 agg_val1;
- u8 __agg_vars1;
- u8 __state;
-#elif defined(__LITTLE_ENDIAN)
- u8 __state;
- u8 __agg_vars1;
- u16 agg_val1;
-#endif
+ u32 reserved0;
#if defined(__BIG_ENDIAN)
u8 cdu_reserved;
- u8 __agg_vars4;
- u8 __agg_vars3;
- u8 __agg_vars2;
+ u8 reserved2;
+ u16 reserved1;
#elif defined(__LITTLE_ENDIAN)
- u8 __agg_vars2;
- u8 __agg_vars3;
- u8 __agg_vars4;
+ u16 reserved1;
+ u8 reserved2;
u8 cdu_reserved;
#endif
- u32 __bd_prod;
-#if defined(__BIG_ENDIAN)
- u16 __agg_vars5;
- u16 __agg_val4_th;
-#elif defined(__LITTLE_ENDIAN)
- u16 __agg_val4_th;
- u16 __agg_vars5;
-#endif
- struct xstorm_eth_extra_ag_context_section __extra_section;
-#if defined(__BIG_ENDIAN)
- u16 __agg_vars7;
- u8 __agg_val3_th;
- u8 __agg_vars6;
-#elif defined(__LITTLE_ENDIAN)
- u8 __agg_vars6;
- u8 __agg_val3_th;
- u16 __agg_vars7;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 __agg_val11_th;
- u16 __agg_val11;
-#elif defined(__LITTLE_ENDIAN)
- u16 __agg_val11;
- u16 __agg_val11_th;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 __reserved1;
- u8 __agg_val6_th;
- u16 __agg_val9;
-#elif defined(__LITTLE_ENDIAN)
- u16 __agg_val9;
- u8 __agg_val6_th;
- u8 __reserved1;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 __agg_val2_th;
- u16 __agg_val2;
-#elif defined(__LITTLE_ENDIAN)
- u16 __agg_val2;
- u16 __agg_val2_th;
-#endif
- u32 __agg_vars8;
-#if defined(__BIG_ENDIAN)
- u16 __agg_misc0;
- u16 __agg_val4;
-#elif defined(__LITTLE_ENDIAN)
- u16 __agg_val4;
- u16 __agg_misc0;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 __agg_val3;
- u8 __agg_val6;
- u8 __agg_val5_th;
- u8 __agg_val5;
-#elif defined(__LITTLE_ENDIAN)
- u8 __agg_val5;
- u8 __agg_val5_th;
- u8 __agg_val6;
- u8 __agg_val3;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 __agg_misc1;
- u16 __bd_ind_max_val;
-#elif defined(__LITTLE_ENDIAN)
- u16 __bd_ind_max_val;
- u16 __agg_misc1;
-#endif
- u32 __reserved57;
- u32 __agg_misc4;
- u32 __agg_misc5;
-};
-
-/*
- * The eth extra aggregative context section of Tstorm
- */
-struct tstorm_eth_extra_ag_context_section {
- u32 __agg_val1;
-#if defined(__BIG_ENDIAN)
- u8 __tcp_agg_vars2;
- u8 __agg_val3;
- u16 __agg_val2;
-#elif defined(__LITTLE_ENDIAN)
- u16 __agg_val2;
- u8 __agg_val3;
- u8 __tcp_agg_vars2;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 __agg_val5;
- u8 __agg_val6;
- u8 __tcp_agg_vars3;
-#elif defined(__LITTLE_ENDIAN)
- u8 __tcp_agg_vars3;
- u8 __agg_val6;
- u16 __agg_val5;
-#endif
- u32 __reserved63;
- u32 __reserved64;
- u32 __reserved65;
- u32 __reserved66;
- u32 __reserved67;
- u32 __tcp_agg_vars1;
- u32 __reserved61;
- u32 __reserved62;
- u32 __reserved2;
+ u32 reserved3[30];
};
/*
* The eth aggregative context of Tstorm
*/
struct tstorm_eth_ag_context {
-#if defined(__BIG_ENDIAN)
- u16 __reserved54;
- u8 __agg_vars1;
- u8 __state;
-#elif defined(__LITTLE_ENDIAN)
- u8 __state;
- u8 __agg_vars1;
- u16 __reserved54;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 __agg_val4;
- u16 __agg_vars2;
-#elif defined(__LITTLE_ENDIAN)
- u16 __agg_vars2;
- u16 __agg_val4;
-#endif
- struct tstorm_eth_extra_ag_context_section __extra_section;
+ u32 __reserved0[14];
};
+
/*
* The eth aggregative context of Cstorm
*/
struct cstorm_eth_ag_context {
- u32 __agg_vars1;
-#if defined(__BIG_ENDIAN)
- u8 __aux1_th;
- u8 __aux1_val;
- u16 __agg_vars2;
-#elif defined(__LITTLE_ENDIAN)
- u16 __agg_vars2;
- u8 __aux1_val;
- u8 __aux1_th;
-#endif
- u32 __num_of_treated_packet;
- u32 __last_packet_treated;
-#if defined(__BIG_ENDIAN)
- u16 __reserved58;
- u16 __reserved57;
-#elif defined(__LITTLE_ENDIAN)
- u16 __reserved57;
- u16 __reserved58;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 __reserved62;
- u8 __reserved61;
- u8 __reserved60;
- u8 __reserved59;
-#elif defined(__LITTLE_ENDIAN)
- u8 __reserved59;
- u8 __reserved60;
- u8 __reserved61;
- u8 __reserved62;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 __reserved64;
- u16 __reserved63;
-#elif defined(__LITTLE_ENDIAN)
- u16 __reserved63;
- u16 __reserved64;
-#endif
- u32 __reserved65;
-#if defined(__BIG_ENDIAN)
- u16 __agg_vars3;
- u16 __rq_inv_cnt;
-#elif defined(__LITTLE_ENDIAN)
- u16 __rq_inv_cnt;
- u16 __agg_vars3;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 __packet_index_th;
- u16 __packet_index;
-#elif defined(__LITTLE_ENDIAN)
- u16 __packet_index;
- u16 __packet_index_th;
-#endif
+ u32 __reserved0[10];
};
+
/*
* The eth aggregative context of Ustorm
*/
struct ustorm_eth_ag_context {
-#if defined(__BIG_ENDIAN)
- u8 __aux_counter_flags;
- u8 __agg_vars2;
- u8 __agg_vars1;
- u8 __state;
-#elif defined(__LITTLE_ENDIAN)
- u8 __state;
- u8 __agg_vars1;
- u8 __agg_vars2;
- u8 __aux_counter_flags;
-#endif
+ u32 __reserved0;
#if defined(__BIG_ENDIAN)
u8 cdu_usage;
- u8 __agg_misc2;
- u16 __agg_misc1;
+ u8 __reserved2;
+ u16 __reserved1;
#elif defined(__LITTLE_ENDIAN)
- u16 __agg_misc1;
- u8 __agg_misc2;
+ u16 __reserved1;
+ u8 __reserved2;
u8 cdu_usage;
#endif
- u32 __agg_misc4;
-#if defined(__BIG_ENDIAN)
- u8 __agg_val3_th;
- u8 __agg_val3;
- u16 __agg_misc3;
-#elif defined(__LITTLE_ENDIAN)
- u16 __agg_misc3;
- u8 __agg_val3;
- u8 __agg_val3_th;
-#endif
- u32 __agg_val1;
- u32 __agg_misc4_th;
-#if defined(__BIG_ENDIAN)
- u16 __agg_val2_th;
- u16 __agg_val2;
-#elif defined(__LITTLE_ENDIAN)
- u16 __agg_val2;
- u16 __agg_val2_th;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 __reserved2;
- u8 __decision_rules;
- u8 __decision_rule_enable_bits;
-#elif defined(__LITTLE_ENDIAN)
- u8 __decision_rule_enable_bits;
- u8 __decision_rules;
- u16 __reserved2;
-#endif
+ u32 __reserved3[6];
};
/*
@@ -2022,18 +1999,16 @@ struct timers_block_context {
*/
struct eth_tx_bd_flags {
u8 as_bitfield;
-#define ETH_TX_BD_FLAGS_VLAN_TAG (0x1<<0)
-#define ETH_TX_BD_FLAGS_VLAN_TAG_SHIFT 0
-#define ETH_TX_BD_FLAGS_IP_CSUM (0x1<<1)
-#define ETH_TX_BD_FLAGS_IP_CSUM_SHIFT 1
-#define ETH_TX_BD_FLAGS_L4_CSUM (0x1<<2)
-#define ETH_TX_BD_FLAGS_L4_CSUM_SHIFT 2
-#define ETH_TX_BD_FLAGS_END_BD (0x1<<3)
-#define ETH_TX_BD_FLAGS_END_BD_SHIFT 3
+#define ETH_TX_BD_FLAGS_IP_CSUM (0x1<<0)
+#define ETH_TX_BD_FLAGS_IP_CSUM_SHIFT 0
+#define ETH_TX_BD_FLAGS_L4_CSUM (0x1<<1)
+#define ETH_TX_BD_FLAGS_L4_CSUM_SHIFT 1
+#define ETH_TX_BD_FLAGS_VLAN_MODE (0x3<<2)
+#define ETH_TX_BD_FLAGS_VLAN_MODE_SHIFT 2
#define ETH_TX_BD_FLAGS_START_BD (0x1<<4)
#define ETH_TX_BD_FLAGS_START_BD_SHIFT 4
-#define ETH_TX_BD_FLAGS_HDR_POOL (0x1<<5)
-#define ETH_TX_BD_FLAGS_HDR_POOL_SHIFT 5
+#define ETH_TX_BD_FLAGS_IS_UDP (0x1<<5)
+#define ETH_TX_BD_FLAGS_IS_UDP_SHIFT 5
#define ETH_TX_BD_FLAGS_SW_LSO (0x1<<6)
#define ETH_TX_BD_FLAGS_SW_LSO_SHIFT 6
#define ETH_TX_BD_FLAGS_IPV6 (0x1<<7)
@@ -2048,7 +2023,7 @@ struct eth_tx_start_bd {
__le32 addr_hi;
__le16 nbd;
__le16 nbytes;
- __le16 vlan;
+ __le16 vlan_or_ethertype;
struct eth_tx_bd_flags bd_flags;
u8 general_data;
#define ETH_TX_START_BD_HDR_NBDS (0x3F<<0)
@@ -2061,48 +2036,48 @@ struct eth_tx_start_bd {
* Tx regular BD structure
*/
struct eth_tx_bd {
- u32 addr_lo;
- u32 addr_hi;
- u16 total_pkt_bytes;
- u16 nbytes;
+ __le32 addr_lo;
+ __le32 addr_hi;
+ __le16 total_pkt_bytes;
+ __le16 nbytes;
u8 reserved[4];
};
/*
- * Tx parsing BD structure for ETH,Relevant in START
+ * Tx parsing BD structure for ETH E1/E1h
*/
-struct eth_tx_parse_bd {
+struct eth_tx_parse_bd_e1x {
u8 global_data;
-#define ETH_TX_PARSE_BD_IP_HDR_START_OFFSET (0xF<<0)
-#define ETH_TX_PARSE_BD_IP_HDR_START_OFFSET_SHIFT 0
-#define ETH_TX_PARSE_BD_UDP_CS_FLG (0x1<<4)
-#define ETH_TX_PARSE_BD_UDP_CS_FLG_SHIFT 4
-#define ETH_TX_PARSE_BD_PSEUDO_CS_WITHOUT_LEN (0x1<<5)
-#define ETH_TX_PARSE_BD_PSEUDO_CS_WITHOUT_LEN_SHIFT 5
-#define ETH_TX_PARSE_BD_LLC_SNAP_EN (0x1<<6)
-#define ETH_TX_PARSE_BD_LLC_SNAP_EN_SHIFT 6
-#define ETH_TX_PARSE_BD_NS_FLG (0x1<<7)
-#define ETH_TX_PARSE_BD_NS_FLG_SHIFT 7
+#define ETH_TX_PARSE_BD_E1X_IP_HDR_START_OFFSET_W (0xF<<0)
+#define ETH_TX_PARSE_BD_E1X_IP_HDR_START_OFFSET_W_SHIFT 0
+#define ETH_TX_PARSE_BD_E1X_RESERVED0 (0x1<<4)
+#define ETH_TX_PARSE_BD_E1X_RESERVED0_SHIFT 4
+#define ETH_TX_PARSE_BD_E1X_PSEUDO_CS_WITHOUT_LEN (0x1<<5)
+#define ETH_TX_PARSE_BD_E1X_PSEUDO_CS_WITHOUT_LEN_SHIFT 5
+#define ETH_TX_PARSE_BD_E1X_LLC_SNAP_EN (0x1<<6)
+#define ETH_TX_PARSE_BD_E1X_LLC_SNAP_EN_SHIFT 6
+#define ETH_TX_PARSE_BD_E1X_NS_FLG (0x1<<7)
+#define ETH_TX_PARSE_BD_E1X_NS_FLG_SHIFT 7
u8 tcp_flags;
-#define ETH_TX_PARSE_BD_FIN_FLG (0x1<<0)
-#define ETH_TX_PARSE_BD_FIN_FLG_SHIFT 0
-#define ETH_TX_PARSE_BD_SYN_FLG (0x1<<1)
-#define ETH_TX_PARSE_BD_SYN_FLG_SHIFT 1
-#define ETH_TX_PARSE_BD_RST_FLG (0x1<<2)
-#define ETH_TX_PARSE_BD_RST_FLG_SHIFT 2
-#define ETH_TX_PARSE_BD_PSH_FLG (0x1<<3)
-#define ETH_TX_PARSE_BD_PSH_FLG_SHIFT 3
-#define ETH_TX_PARSE_BD_ACK_FLG (0x1<<4)
-#define ETH_TX_PARSE_BD_ACK_FLG_SHIFT 4
-#define ETH_TX_PARSE_BD_URG_FLG (0x1<<5)
-#define ETH_TX_PARSE_BD_URG_FLG_SHIFT 5
-#define ETH_TX_PARSE_BD_ECE_FLG (0x1<<6)
-#define ETH_TX_PARSE_BD_ECE_FLG_SHIFT 6
-#define ETH_TX_PARSE_BD_CWR_FLG (0x1<<7)
-#define ETH_TX_PARSE_BD_CWR_FLG_SHIFT 7
- u8 ip_hlen;
+#define ETH_TX_PARSE_BD_E1X_FIN_FLG (0x1<<0)
+#define ETH_TX_PARSE_BD_E1X_FIN_FLG_SHIFT 0
+#define ETH_TX_PARSE_BD_E1X_SYN_FLG (0x1<<1)
+#define ETH_TX_PARSE_BD_E1X_SYN_FLG_SHIFT 1
+#define ETH_TX_PARSE_BD_E1X_RST_FLG (0x1<<2)
+#define ETH_TX_PARSE_BD_E1X_RST_FLG_SHIFT 2
+#define ETH_TX_PARSE_BD_E1X_PSH_FLG (0x1<<3)
+#define ETH_TX_PARSE_BD_E1X_PSH_FLG_SHIFT 3
+#define ETH_TX_PARSE_BD_E1X_ACK_FLG (0x1<<4)
+#define ETH_TX_PARSE_BD_E1X_ACK_FLG_SHIFT 4
+#define ETH_TX_PARSE_BD_E1X_URG_FLG (0x1<<5)
+#define ETH_TX_PARSE_BD_E1X_URG_FLG_SHIFT 5
+#define ETH_TX_PARSE_BD_E1X_ECE_FLG (0x1<<6)
+#define ETH_TX_PARSE_BD_E1X_ECE_FLG_SHIFT 6
+#define ETH_TX_PARSE_BD_E1X_CWR_FLG (0x1<<7)
+#define ETH_TX_PARSE_BD_E1X_CWR_FLG_SHIFT 7
+ u8 ip_hlen_w;
s8 reserved;
- __le16 total_hlen;
+ __le16 total_hlen_w;
__le16 tcp_pseudo_csum;
__le16 lso_mss;
__le16 ip_id;
@@ -2110,6 +2085,27 @@ struct eth_tx_parse_bd {
};
/*
+ * Tx parsing BD structure for ETH E2
+ */
+struct eth_tx_parse_bd_e2 {
+ __le16 dst_mac_addr_lo;
+ __le16 dst_mac_addr_mid;
+ __le16 dst_mac_addr_hi;
+ __le16 src_mac_addr_lo;
+ __le16 src_mac_addr_mid;
+ __le16 src_mac_addr_hi;
+ __le32 parsing_data;
+#define ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W (0x1FFF<<0)
+#define ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W_SHIFT 0
+#define ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW (0xF<<13)
+#define ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW_SHIFT 13
+#define ETH_TX_PARSE_BD_E2_LSO_MSS (0x3FFF<<17)
+#define ETH_TX_PARSE_BD_E2_LSO_MSS_SHIFT 17
+#define ETH_TX_PARSE_BD_E2_IPV6_WITH_EXT_HDR (0x1<<31)
+#define ETH_TX_PARSE_BD_E2_IPV6_WITH_EXT_HDR_SHIFT 31
+};
+
+/*
* The last BD in the BD memory will hold a pointer to the next BD memory
*/
struct eth_tx_next_bd {
@@ -2124,79 +2120,24 @@ struct eth_tx_next_bd {
union eth_tx_bd_types {
struct eth_tx_start_bd start_bd;
struct eth_tx_bd reg_bd;
- struct eth_tx_parse_bd parse_bd;
+ struct eth_tx_parse_bd_e1x parse_bd_e1x;
+ struct eth_tx_parse_bd_e2 parse_bd_e2;
struct eth_tx_next_bd next_bd;
};
+
/*
* The eth storm context of Xstorm
*/
struct xstorm_eth_st_context {
- u32 tx_bd_page_base_lo;
- u32 tx_bd_page_base_hi;
-#if defined(__BIG_ENDIAN)
- u16 tx_bd_cons;
- u8 statistics_data;
-#define XSTORM_ETH_ST_CONTEXT_STATISTICS_COUNTER_ID (0x7F<<0)
-#define XSTORM_ETH_ST_CONTEXT_STATISTICS_COUNTER_ID_SHIFT 0
-#define XSTORM_ETH_ST_CONTEXT_STATISTICS_ENABLE (0x1<<7)
-#define XSTORM_ETH_ST_CONTEXT_STATISTICS_ENABLE_SHIFT 7
- u8 __local_tx_bd_prod;
-#elif defined(__LITTLE_ENDIAN)
- u8 __local_tx_bd_prod;
- u8 statistics_data;
-#define XSTORM_ETH_ST_CONTEXT_STATISTICS_COUNTER_ID (0x7F<<0)
-#define XSTORM_ETH_ST_CONTEXT_STATISTICS_COUNTER_ID_SHIFT 0
-#define XSTORM_ETH_ST_CONTEXT_STATISTICS_ENABLE (0x1<<7)
-#define XSTORM_ETH_ST_CONTEXT_STATISTICS_ENABLE_SHIFT 7
- u16 tx_bd_cons;
-#endif
- u32 __reserved1;
- u32 __reserved2;
-#if defined(__BIG_ENDIAN)
- u8 __ram_cache_index;
- u8 __double_buffer_client;
- u16 __pkt_cons;
-#elif defined(__LITTLE_ENDIAN)
- u16 __pkt_cons;
- u8 __double_buffer_client;
- u8 __ram_cache_index;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 __statistics_address;
- u16 __gso_next;
-#elif defined(__LITTLE_ENDIAN)
- u16 __gso_next;
- u16 __statistics_address;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 __local_tx_bd_cons;
- u8 safc_group_num;
- u8 safc_group_en;
- u8 __is_eth_conn;
-#elif defined(__LITTLE_ENDIAN)
- u8 __is_eth_conn;
- u8 safc_group_en;
- u8 safc_group_num;
- u8 __local_tx_bd_cons;
-#endif
- union eth_tx_bd_types __bds[13];
+ u32 reserved0[60];
};
/*
* The eth storm context of Cstorm
*/
struct cstorm_eth_st_context {
-#if defined(__BIG_ENDIAN)
- u16 __reserved0;
- u8 sb_index_number;
- u8 status_block_id;
-#elif defined(__LITTLE_ENDIAN)
- u8 status_block_id;
- u8 sb_index_number;
- u16 __reserved0;
-#endif
- u32 __reserved1[3];
+ u32 __reserved0[4];
};
/*
@@ -2244,103 +2185,114 @@ struct eth_tx_doorbell {
/*
- * cstorm default status block, generated by ustorm
- */
-struct cstorm_def_status_block_u {
- __le16 index_values[HC_USTORM_DEF_SB_NUM_INDICES];
- __le16 status_block_index;
- u8 func;
- u8 status_block_id;
- __le32 __flags;
-};
-
-/*
- * cstorm default status block, generated by cstorm
- */
-struct cstorm_def_status_block_c {
- __le16 index_values[HC_CSTORM_DEF_SB_NUM_INDICES];
- __le16 status_block_index;
- u8 func;
- u8 status_block_id;
- __le32 __flags;
-};
-
-/*
- * xstorm status block
+ * client init fc data
*/
-struct xstorm_def_status_block {
- __le16 index_values[HC_XSTORM_DEF_SB_NUM_INDICES];
- __le16 status_block_index;
- u8 func;
- u8 status_block_id;
- __le32 __flags;
+struct client_init_fc_data {
+ __le16 cqe_pause_thr_low;
+ __le16 cqe_pause_thr_high;
+ __le16 bd_pause_thr_low;
+ __le16 bd_pause_thr_high;
+ __le16 sge_pause_thr_low;
+ __le16 sge_pause_thr_high;
+ __le16 rx_cos_mask;
+ u8 safc_group_num;
+ u8 safc_group_en_flg;
+ u8 traffic_type;
+ u8 reserved0;
+ __le16 reserved1;
+ __le32 reserved2;
};
-/*
- * tstorm status block
- */
-struct tstorm_def_status_block {
- __le16 index_values[HC_TSTORM_DEF_SB_NUM_INDICES];
- __le16 status_block_index;
- u8 func;
- u8 status_block_id;
- __le32 __flags;
-};
/*
- * host status block
+ * client init ramrod data
*/
-struct host_def_status_block {
- struct atten_def_status_block atten_status_block;
- struct cstorm_def_status_block_u u_def_status_block;
- struct cstorm_def_status_block_c c_def_status_block;
- struct xstorm_def_status_block x_def_status_block;
- struct tstorm_def_status_block t_def_status_block;
+struct client_init_general_data {
+ u8 client_id;
+ u8 statistics_counter_id;
+ u8 statistics_en_flg;
+ u8 is_fcoe_flg;
+ u8 activate_flg;
+ u8 sp_client_id;
+ __le16 reserved0;
+ __le32 reserved1[2];
};
/*
- * cstorm status block, generated by ustorm
+ * client init rx data
*/
-struct cstorm_status_block_u {
- __le16 index_values[HC_USTORM_SB_NUM_INDICES];
- __le16 status_block_index;
- u8 func;
+struct client_init_rx_data {
+ u8 tpa_en_flg;
+ u8 vmqueue_mode_en_flg;
+ u8 extra_data_over_sgl_en_flg;
+ u8 cache_line_alignment_log_size;
+ u8 enable_dynamic_hc;
+ u8 max_sges_for_packet;
+ u8 client_qzone_id;
+ u8 drop_ip_cs_err_flg;
+ u8 drop_tcp_cs_err_flg;
+ u8 drop_ttl0_flg;
+ u8 drop_udp_cs_err_flg;
+ u8 inner_vlan_removal_enable_flg;
+ u8 outer_vlan_removal_enable_flg;
u8 status_block_id;
- __le32 __flags;
+ u8 rx_sb_index_number;
+ u8 reserved0[3];
+ __le16 bd_buff_size;
+ __le16 sge_buff_size;
+ __le16 mtu;
+ struct regpair bd_page_base;
+ struct regpair sge_page_base;
+ struct regpair cqe_page_base;
+ u8 is_leading_rss;
+ u8 is_approx_mcast;
+ __le16 max_agg_size;
+ __le32 reserved2[3];
+};
+
+/*
+ * client init tx data
+ */
+struct client_init_tx_data {
+ u8 enforce_security_flg;
+ u8 tx_status_block_id;
+ u8 tx_sb_index_number;
+ u8 reserved0;
+ __le16 mtu;
+ __le16 reserved1;
+ struct regpair tx_bd_page_base;
+ __le32 reserved2[2];
};
/*
- * cstorm status block, generated by cstorm
+ * client init ramrod data
*/
-struct cstorm_status_block_c {
- __le16 index_values[HC_CSTORM_SB_NUM_INDICES];
- __le16 status_block_index;
- u8 func;
- u8 status_block_id;
- __le32 __flags;
+struct client_init_ramrod_data {
+ struct client_init_general_data general;
+ struct client_init_rx_data rx;
+ struct client_init_tx_data tx;
+ struct client_init_fc_data fc;
};
+
/*
- * host status block
+ * The data contain client ID need to the ramrod
*/
-struct host_status_block {
- struct cstorm_status_block_u u_status_block;
- struct cstorm_status_block_c c_status_block;
+struct eth_common_ramrod_data {
+ u32 client_id;
+ u32 reserved1;
};
/*
- * The data for RSS setup ramrod
+ * union for sgl and raw data.
*/
-struct eth_client_setup_ramrod_data {
- u32 client_id;
- u8 is_rdma;
- u8 is_fcoe;
- u16 reserved1;
+union eth_sgl_or_raw_data {
+ __le16 sgl[8];
+ u32 raw_data[4];
};
-
/*
* regular eth FP CQE parameters struct
*/
@@ -2358,8 +2310,8 @@ struct eth_fast_path_rx_cqe {
#define ETH_FAST_PATH_RX_CQE_START_FLG_SHIFT 4
#define ETH_FAST_PATH_RX_CQE_END_FLG (0x1<<5)
#define ETH_FAST_PATH_RX_CQE_END_FLG_SHIFT 5
-#define ETH_FAST_PATH_RX_CQE_RESERVED0 (0x3<<6)
-#define ETH_FAST_PATH_RX_CQE_RESERVED0_SHIFT 6
+#define ETH_FAST_PATH_RX_CQE_SGL_RAW_SEL (0x3<<6)
+#define ETH_FAST_PATH_RX_CQE_SGL_RAW_SEL_SHIFT 6
u8 status_flags;
#define ETH_FAST_PATH_RX_CQE_RSS_HASH_TYPE (0x7<<0)
#define ETH_FAST_PATH_RX_CQE_RSS_HASH_TYPE_SHIFT 0
@@ -2380,7 +2332,7 @@ struct eth_fast_path_rx_cqe {
__le16 pkt_len;
__le16 len_on_bd;
struct parsing_flags pars_flags;
- __le16 sgl[8];
+ union eth_sgl_or_raw_data sgl_or_raw_data;
};
@@ -2392,11 +2344,10 @@ struct eth_halt_ramrod_data {
u32 reserved0;
};
-
/*
* The data for statistics query ramrod
*/
-struct eth_query_ramrod_data {
+struct common_query_ramrod_data {
#if defined(__BIG_ENDIAN)
u8 reserved0;
u8 collect_port;
@@ -2479,9 +2430,9 @@ struct spe_hdr {
__le16 type;
#define SPE_HDR_CONN_TYPE (0xFF<<0)
#define SPE_HDR_CONN_TYPE_SHIFT 0
-#define SPE_HDR_COMMON_RAMROD (0xFF<<8)
-#define SPE_HDR_COMMON_RAMROD_SHIFT 8
- __le16 reserved;
+#define SPE_HDR_FUNCTION_ID (0xFF<<8)
+#define SPE_HDR_FUNCTION_ID_SHIFT 8
+ __le16 reserved1;
};
/*
@@ -2489,12 +2440,10 @@ struct spe_hdr {
*/
union eth_specific_data {
u8 protocol_data[8];
- struct regpair mac_config_addr;
- struct eth_client_setup_ramrod_data client_setup_ramrod_data;
+ struct regpair client_init_ramrod_init_data;
struct eth_halt_ramrod_data halt_ramrod_data;
- struct regpair leading_cqe_addr;
struct regpair update_data_addr;
- struct eth_query_ramrod_data query_ramrod_data;
+ struct eth_common_ramrod_data common_ramrod_data;
};
/*
@@ -2519,7 +2468,7 @@ struct eth_tx_bds_array {
*/
struct tstorm_eth_function_common_config {
#if defined(__BIG_ENDIAN)
- u8 leading_client_id;
+ u8 reserved1;
u8 rss_result_mask;
u16 config_flags;
#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_CAPABILITY (0x1<<0)
@@ -2532,16 +2481,12 @@ struct tstorm_eth_function_common_config {
#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_TCP_CAPABILITY_SHIFT 3
#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_MODE (0x7<<4)
#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_MODE_SHIFT 4
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_DEFAULT_ENABLE (0x1<<7)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_DEFAULT_ENABLE_SHIFT 7
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_VLAN_IN_CAM (0x1<<8)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_VLAN_IN_CAM_SHIFT 8
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_E1HOV_IN_CAM (0x1<<9)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_E1HOV_IN_CAM_SHIFT 9
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_ENABLE_TPA (0x1<<10)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_ENABLE_TPA_SHIFT 10
-#define __TSTORM_ETH_FUNCTION_COMMON_CONFIG_RESERVED0 (0x1F<<11)
-#define __TSTORM_ETH_FUNCTION_COMMON_CONFIG_RESERVED0_SHIFT 11
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_ENABLE_TPA (0x1<<7)
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_ENABLE_TPA_SHIFT 7
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_VLAN_FILTERING_ENABLE (0x1<<8)
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_VLAN_FILTERING_ENABLE_SHIFT 8
+#define __TSTORM_ETH_FUNCTION_COMMON_CONFIG_RESERVED0 (0x7F<<9)
+#define __TSTORM_ETH_FUNCTION_COMMON_CONFIG_RESERVED0_SHIFT 9
#elif defined(__LITTLE_ENDIAN)
u16 config_flags;
#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_CAPABILITY (0x1<<0)
@@ -2554,18 +2499,14 @@ struct tstorm_eth_function_common_config {
#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_TCP_CAPABILITY_SHIFT 3
#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_MODE (0x7<<4)
#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_MODE_SHIFT 4
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_DEFAULT_ENABLE (0x1<<7)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_DEFAULT_ENABLE_SHIFT 7
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_VLAN_IN_CAM (0x1<<8)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_VLAN_IN_CAM_SHIFT 8
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_E1HOV_IN_CAM (0x1<<9)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_E1HOV_IN_CAM_SHIFT 9
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_ENABLE_TPA (0x1<<10)
-#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_ENABLE_TPA_SHIFT 10
-#define __TSTORM_ETH_FUNCTION_COMMON_CONFIG_RESERVED0 (0x1F<<11)
-#define __TSTORM_ETH_FUNCTION_COMMON_CONFIG_RESERVED0_SHIFT 11
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_ENABLE_TPA (0x1<<7)
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_ENABLE_TPA_SHIFT 7
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_VLAN_FILTERING_ENABLE (0x1<<8)
+#define TSTORM_ETH_FUNCTION_COMMON_CONFIG_VLAN_FILTERING_ENABLE_SHIFT 8
+#define __TSTORM_ETH_FUNCTION_COMMON_CONFIG_RESERVED0 (0x7F<<9)
+#define __TSTORM_ETH_FUNCTION_COMMON_CONFIG_RESERVED0_SHIFT 9
u8 rss_result_mask;
- u8 leading_client_id;
+ u8 reserved1;
#endif
u16 vlan_id[2];
};
@@ -2613,90 +2554,42 @@ struct mac_configuration_hdr {
u8 length;
u8 offset;
u16 client_id;
- u32 reserved1;
-};
-
-/*
- * MAC address in list for ramrod
- */
-struct tstorm_cam_entry {
- __le16 lsb_mac_addr;
- __le16 middle_mac_addr;
- __le16 msb_mac_addr;
- __le16 flags;
-#define TSTORM_CAM_ENTRY_PORT_ID (0x1<<0)
-#define TSTORM_CAM_ENTRY_PORT_ID_SHIFT 0
-#define TSTORM_CAM_ENTRY_RSRVVAL0 (0x7<<1)
-#define TSTORM_CAM_ENTRY_RSRVVAL0_SHIFT 1
-#define TSTORM_CAM_ENTRY_RESERVED0 (0xFFF<<4)
-#define TSTORM_CAM_ENTRY_RESERVED0_SHIFT 4
-};
-
-/*
- * MAC filtering: CAM target table entry
- */
-struct tstorm_cam_target_table_entry {
- u8 flags;
-#define TSTORM_CAM_TARGET_TABLE_ENTRY_BROADCAST (0x1<<0)
-#define TSTORM_CAM_TARGET_TABLE_ENTRY_BROADCAST_SHIFT 0
-#define TSTORM_CAM_TARGET_TABLE_ENTRY_OVERRIDE_VLAN_REMOVAL (0x1<<1)
-#define TSTORM_CAM_TARGET_TABLE_ENTRY_OVERRIDE_VLAN_REMOVAL_SHIFT 1
-#define TSTORM_CAM_TARGET_TABLE_ENTRY_ACTION_TYPE (0x1<<2)
-#define TSTORM_CAM_TARGET_TABLE_ENTRY_ACTION_TYPE_SHIFT 2
-#define TSTORM_CAM_TARGET_TABLE_ENTRY_RDMA_MAC (0x1<<3)
-#define TSTORM_CAM_TARGET_TABLE_ENTRY_RDMA_MAC_SHIFT 3
-#define TSTORM_CAM_TARGET_TABLE_ENTRY_RESERVED0 (0xF<<4)
-#define TSTORM_CAM_TARGET_TABLE_ENTRY_RESERVED0_SHIFT 4
- u8 reserved1;
- u16 vlan_id;
- u32 clients_bit_vector;
+ u16 echo;
+ u16 reserved1;
};
/*
* MAC address in list for ramrod
*/
struct mac_configuration_entry {
- struct tstorm_cam_entry cam_entry;
- struct tstorm_cam_target_table_entry target_table_entry;
-};
-
-/*
- * MAC filtering configuration command
- */
-struct mac_configuration_cmd {
- struct mac_configuration_hdr hdr;
- struct mac_configuration_entry config_table[64];
-};
-
-
-/*
- * MAC address in list for ramrod
- */
-struct mac_configuration_entry_e1h {
__le16 lsb_mac_addr;
__le16 middle_mac_addr;
__le16 msb_mac_addr;
__le16 vlan_id;
- __le16 e1hov_id;
- u8 reserved0;
+ u8 pf_id;
u8 flags;
-#define MAC_CONFIGURATION_ENTRY_E1H_PORT (0x1<<0)
-#define MAC_CONFIGURATION_ENTRY_E1H_PORT_SHIFT 0
-#define MAC_CONFIGURATION_ENTRY_E1H_ACTION_TYPE (0x1<<1)
-#define MAC_CONFIGURATION_ENTRY_E1H_ACTION_TYPE_SHIFT 1
-#define MAC_CONFIGURATION_ENTRY_E1H_RDMA_MAC (0x1<<2)
-#define MAC_CONFIGURATION_ENTRY_E1H_RDMA_MAC_SHIFT 2
-#define MAC_CONFIGURATION_ENTRY_E1H_RESERVED1 (0x1F<<3)
-#define MAC_CONFIGURATION_ENTRY_E1H_RESERVED1_SHIFT 3
+#define MAC_CONFIGURATION_ENTRY_ACTION_TYPE (0x1<<0)
+#define MAC_CONFIGURATION_ENTRY_ACTION_TYPE_SHIFT 0
+#define MAC_CONFIGURATION_ENTRY_RDMA_MAC (0x1<<1)
+#define MAC_CONFIGURATION_ENTRY_RDMA_MAC_SHIFT 1
+#define MAC_CONFIGURATION_ENTRY_VLAN_FILTERING_MODE (0x3<<2)
+#define MAC_CONFIGURATION_ENTRY_VLAN_FILTERING_MODE_SHIFT 2
+#define MAC_CONFIGURATION_ENTRY_OVERRIDE_VLAN_REMOVAL (0x1<<4)
+#define MAC_CONFIGURATION_ENTRY_OVERRIDE_VLAN_REMOVAL_SHIFT 4
+#define MAC_CONFIGURATION_ENTRY_BROADCAST (0x1<<5)
+#define MAC_CONFIGURATION_ENTRY_BROADCAST_SHIFT 5
+#define MAC_CONFIGURATION_ENTRY_RESERVED1 (0x3<<6)
+#define MAC_CONFIGURATION_ENTRY_RESERVED1_SHIFT 6
+ u16 reserved0;
u32 clients_bit_vector;
};
/*
* MAC filtering configuration command
*/
-struct mac_configuration_cmd_e1h {
+struct mac_configuration_cmd {
struct mac_configuration_hdr hdr;
- struct mac_configuration_entry_e1h config_table[32];
+ struct mac_configuration_entry config_table[64];
};
@@ -2709,65 +2602,6 @@ struct tstorm_eth_approximate_match_multicast_filtering {
/*
- * Configuration parameters per client in Tstorm
- */
-struct tstorm_eth_client_config {
-#if defined(__BIG_ENDIAN)
- u8 reserved0;
- u8 statistics_counter_id;
- u16 mtu;
-#elif defined(__LITTLE_ENDIAN)
- u16 mtu;
- u8 statistics_counter_id;
- u8 reserved0;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 drop_flags;
-#define TSTORM_ETH_CLIENT_CONFIG_DROP_IP_CS_ERR (0x1<<0)
-#define TSTORM_ETH_CLIENT_CONFIG_DROP_IP_CS_ERR_SHIFT 0
-#define TSTORM_ETH_CLIENT_CONFIG_DROP_TCP_CS_ERR (0x1<<1)
-#define TSTORM_ETH_CLIENT_CONFIG_DROP_TCP_CS_ERR_SHIFT 1
-#define TSTORM_ETH_CLIENT_CONFIG_DROP_TTL0 (0x1<<2)
-#define TSTORM_ETH_CLIENT_CONFIG_DROP_TTL0_SHIFT 2
-#define TSTORM_ETH_CLIENT_CONFIG_DROP_UDP_CS_ERR (0x1<<3)
-#define TSTORM_ETH_CLIENT_CONFIG_DROP_UDP_CS_ERR_SHIFT 3
-#define __TSTORM_ETH_CLIENT_CONFIG_RESERVED2 (0xFFF<<4)
-#define __TSTORM_ETH_CLIENT_CONFIG_RESERVED2_SHIFT 4
- u16 config_flags;
-#define TSTORM_ETH_CLIENT_CONFIG_VLAN_REM_ENABLE (0x1<<0)
-#define TSTORM_ETH_CLIENT_CONFIG_VLAN_REM_ENABLE_SHIFT 0
-#define TSTORM_ETH_CLIENT_CONFIG_E1HOV_REM_ENABLE (0x1<<1)
-#define TSTORM_ETH_CLIENT_CONFIG_E1HOV_REM_ENABLE_SHIFT 1
-#define TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE (0x1<<2)
-#define TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE_SHIFT 2
-#define __TSTORM_ETH_CLIENT_CONFIG_RESERVED1 (0x1FFF<<3)
-#define __TSTORM_ETH_CLIENT_CONFIG_RESERVED1_SHIFT 3
-#elif defined(__LITTLE_ENDIAN)
- u16 config_flags;
-#define TSTORM_ETH_CLIENT_CONFIG_VLAN_REM_ENABLE (0x1<<0)
-#define TSTORM_ETH_CLIENT_CONFIG_VLAN_REM_ENABLE_SHIFT 0
-#define TSTORM_ETH_CLIENT_CONFIG_E1HOV_REM_ENABLE (0x1<<1)
-#define TSTORM_ETH_CLIENT_CONFIG_E1HOV_REM_ENABLE_SHIFT 1
-#define TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE (0x1<<2)
-#define TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE_SHIFT 2
-#define __TSTORM_ETH_CLIENT_CONFIG_RESERVED1 (0x1FFF<<3)
-#define __TSTORM_ETH_CLIENT_CONFIG_RESERVED1_SHIFT 3
- u16 drop_flags;
-#define TSTORM_ETH_CLIENT_CONFIG_DROP_IP_CS_ERR (0x1<<0)
-#define TSTORM_ETH_CLIENT_CONFIG_DROP_IP_CS_ERR_SHIFT 0
-#define TSTORM_ETH_CLIENT_CONFIG_DROP_TCP_CS_ERR (0x1<<1)
-#define TSTORM_ETH_CLIENT_CONFIG_DROP_TCP_CS_ERR_SHIFT 1
-#define TSTORM_ETH_CLIENT_CONFIG_DROP_TTL0 (0x1<<2)
-#define TSTORM_ETH_CLIENT_CONFIG_DROP_TTL0_SHIFT 2
-#define TSTORM_ETH_CLIENT_CONFIG_DROP_UDP_CS_ERR (0x1<<3)
-#define TSTORM_ETH_CLIENT_CONFIG_DROP_UDP_CS_ERR_SHIFT 3
-#define __TSTORM_ETH_CLIENT_CONFIG_RESERVED2 (0xFFF<<4)
-#define __TSTORM_ETH_CLIENT_CONFIG_RESERVED2_SHIFT 4
-#endif
-};
-
-
-/*
* MAC filtering configuration parameters per port in Tstorm
*/
struct tstorm_eth_mac_filter_config {
@@ -2777,8 +2611,8 @@ struct tstorm_eth_mac_filter_config {
u32 mcast_accept_all;
u32 bcast_drop_all;
u32 bcast_accept_all;
- u32 strict_vlan;
u32 vlan_filter[2];
+ u32 unmatched_unicast;
u32 reserved;
};
@@ -2801,41 +2635,6 @@ struct tstorm_eth_tpa_exist {
/*
- * rx rings pause data for E1h only
- */
-struct ustorm_eth_rx_pause_data_e1h {
-#if defined(__BIG_ENDIAN)
- u16 bd_thr_low;
- u16 cqe_thr_low;
-#elif defined(__LITTLE_ENDIAN)
- u16 cqe_thr_low;
- u16 bd_thr_low;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 cos;
- u16 sge_thr_low;
-#elif defined(__LITTLE_ENDIAN)
- u16 sge_thr_low;
- u16 cos;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 bd_thr_high;
- u16 cqe_thr_high;
-#elif defined(__LITTLE_ENDIAN)
- u16 cqe_thr_high;
- u16 bd_thr_high;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 reserved0;
- u16 sge_thr_high;
-#elif defined(__LITTLE_ENDIAN)
- u16 sge_thr_high;
- u16 reserved0;
-#endif
-};
-
-
-/*
* Three RX producers for ETH
*/
struct ustorm_eth_rx_producers {
@@ -2857,6 +2656,18 @@ struct ustorm_eth_rx_producers {
/*
+ * cfc delete event data
+ */
+struct cfc_del_event_data {
+ u32 cid;
+ u8 error;
+ u8 reserved0;
+ u16 reserved1;
+ u32 reserved2;
+};
+
+
+/*
* per-port SAFC demo variables
*/
struct cmng_flags_per_port {
@@ -2872,8 +2683,10 @@ struct cmng_flags_per_port {
#define CMNG_FLAGS_PER_PORT_RATE_SHAPING_PROTOCOL_SHIFT 3
#define CMNG_FLAGS_PER_PORT_FAIRNESS_COS (0x1<<4)
#define CMNG_FLAGS_PER_PORT_FAIRNESS_COS_SHIFT 4
-#define __CMNG_FLAGS_PER_PORT_RESERVED0 (0x7FFFFFF<<5)
-#define __CMNG_FLAGS_PER_PORT_RESERVED0_SHIFT 5
+#define CMNG_FLAGS_PER_PORT_FAIRNESS_COS_MODE (0x1<<5)
+#define CMNG_FLAGS_PER_PORT_FAIRNESS_COS_MODE_SHIFT 5
+#define __CMNG_FLAGS_PER_PORT_RESERVED0 (0x3FFFFFF<<6)
+#define __CMNG_FLAGS_PER_PORT_RESERVED0_SHIFT 6
};
@@ -2907,30 +2720,92 @@ struct safc_struct_per_port {
u8 __reserved0;
u16 __reserved1;
#endif
+ u8 cos_to_traffic_types[MAX_COS_NUMBER];
+ u32 __reserved2;
u16 cos_to_pause_mask[NUM_OF_SAFC_BITS];
};
/*
+ * per-port PFC variables
+ */
+struct pfc_struct_per_port {
+ u8 priority_to_traffic_types[MAX_PFC_PRIORITIES];
+#if defined(__BIG_ENDIAN)
+ u16 pfc_pause_quanta_in_nanosec;
+ u8 __reserved0;
+ u8 priority_non_pausable_mask;
+#elif defined(__LITTLE_ENDIAN)
+ u8 priority_non_pausable_mask;
+ u8 __reserved0;
+ u16 pfc_pause_quanta_in_nanosec;
+#endif
+};
+
+/*
+ * Priority and cos
+ */
+struct priority_cos {
+#if defined(__BIG_ENDIAN)
+ u16 reserved1;
+ u8 cos;
+ u8 priority;
+#elif defined(__LITTLE_ENDIAN)
+ u8 priority;
+ u8 cos;
+ u16 reserved1;
+#endif
+ u32 reserved2;
+};
+
+/*
* Per-port congestion management variables
*/
struct cmng_struct_per_port {
struct rate_shaping_vars_per_port rs_vars;
struct fairness_vars_per_port fair_vars;
struct safc_struct_per_port safc_vars;
+ struct pfc_struct_per_port pfc_vars;
+#if defined(__BIG_ENDIAN)
+ u16 __reserved1;
+ u8 dcb_enabled;
+ u8 llfc_mode;
+#elif defined(__LITTLE_ENDIAN)
+ u8 llfc_mode;
+ u8 dcb_enabled;
+ u16 __reserved1;
+#endif
+ struct priority_cos
+ traffic_type_to_priority_cos[MAX_PFC_TRAFFIC_TYPES];
struct cmng_flags_per_port flags;
};
+
+/*
+ * Dynamic HC counters set by the driver
+ */
+struct hc_dynamic_drv_counter {
+ u32 val[HC_SB_MAX_DYNAMIC_INDICES];
+};
+
+/*
+ * zone A per-queue data
+ */
+struct cstorm_queue_zone_data {
+ struct hc_dynamic_drv_counter hc_dyn_drv_cnt;
+ struct regpair reserved[2];
+};
+
/*
* Dynamic host coalescing init parameters
*/
struct dynamic_hc_config {
u32 threshold[3];
- u8 shift_per_protocol[HC_USTORM_SB_NUM_INDICES];
- u8 hc_timeout0[HC_USTORM_SB_NUM_INDICES];
- u8 hc_timeout1[HC_USTORM_SB_NUM_INDICES];
- u8 hc_timeout2[HC_USTORM_SB_NUM_INDICES];
- u8 hc_timeout3[HC_USTORM_SB_NUM_INDICES];
+ u8 shift_per_protocol[HC_SB_MAX_DYNAMIC_INDICES];
+ u8 hc_timeout0[HC_SB_MAX_DYNAMIC_INDICES];
+ u8 hc_timeout1[HC_SB_MAX_DYNAMIC_INDICES];
+ u8 hc_timeout2[HC_SB_MAX_DYNAMIC_INDICES];
+ u8 hc_timeout3[HC_SB_MAX_DYNAMIC_INDICES];
};
@@ -2954,7 +2829,7 @@ struct xstorm_per_client_stats {
* Common statistics collected by the Xstorm (per port)
*/
struct xstorm_common_stats {
- struct xstorm_per_client_stats client_statistics[MAX_X_STAT_COUNTER_ID];
+ struct xstorm_per_client_stats client_statistics[MAX_STAT_COUNTER_ID];
};
/*
@@ -2991,7 +2866,7 @@ struct tstorm_per_client_stats {
*/
struct tstorm_common_stats {
struct tstorm_per_port_stats port_statistics;
- struct tstorm_per_client_stats client_statistics[MAX_T_STAT_COUNTER_ID];
+ struct tstorm_per_client_stats client_statistics[MAX_STAT_COUNTER_ID];
};
/*
@@ -3012,7 +2887,7 @@ struct ustorm_per_client_stats {
* Protocol-common statistics collected by the Ustorm
*/
struct ustorm_common_stats {
- struct ustorm_per_client_stats client_statistics[MAX_U_STAT_COUNTER_ID];
+ struct ustorm_per_client_stats client_statistics[MAX_STAT_COUNTER_ID];
};
/*
@@ -3026,6 +2901,70 @@ struct eth_stats_query {
/*
+ * set mac event data
+ */
+struct set_mac_event_data {
+ u16 echo;
+ u16 reserved0;
+ u32 reserved1;
+ u32 reserved2;
+};
+
+/*
+ * union for all event ring message types
+ */
+union event_data {
+ struct set_mac_event_data set_mac_event;
+ struct cfc_del_event_data cfc_del_event;
+};
+
+
+/*
+ * per PF event ring data
+ */
+struct event_ring_data {
+ struct regpair base_addr;
+#if defined(__BIG_ENDIAN)
+ u8 index_id;
+ u8 sb_id;
+ u16 producer;
+#elif defined(__LITTLE_ENDIAN)
+ u16 producer;
+ u8 sb_id;
+ u8 index_id;
+#endif
+ u32 reserved0;
+};
+
+
+/*
+ * event ring message element (each element is 128 bits)
+ */
+struct event_ring_msg {
+ u8 opcode;
+ u8 reserved0;
+ u16 reserved1;
+ union event_data data;
+};
+
+/*
+ * event ring next page element (128 bits)
+ */
+struct event_ring_next {
+ struct regpair addr;
+ u32 reserved[2];
+};
+
+/*
+ * union for event ring element types (each element is 128 bits)
+ */
+union event_ring_elem {
+ struct event_ring_msg message;
+ struct event_ring_next next_page;
+};
+
+
+/*
* per-vnic fairness variables
*/
struct fairness_vars_per_vn {
@@ -3064,6 +3003,137 @@ struct fw_version {
/*
+ * Dynamic Host-Coalescing - Driver(host) counters
+ */
+struct hc_dynamic_sb_drv_counters {
+ u32 dynamic_hc_drv_counter[HC_SB_MAX_DYNAMIC_INDICES];
+};
+
+
+/*
+ * 2 bytes. configuration/state parameters for a single protocol index
+ */
+struct hc_index_data {
+#if defined(__BIG_ENDIAN)
+ u8 flags;
+#define HC_INDEX_DATA_SM_ID (0x1<<0)
+#define HC_INDEX_DATA_SM_ID_SHIFT 0
+#define HC_INDEX_DATA_HC_ENABLED (0x1<<1)
+#define HC_INDEX_DATA_HC_ENABLED_SHIFT 1
+#define HC_INDEX_DATA_DYNAMIC_HC_ENABLED (0x1<<2)
+#define HC_INDEX_DATA_DYNAMIC_HC_ENABLED_SHIFT 2
+#define HC_INDEX_DATA_RESERVE (0x1F<<3)
+#define HC_INDEX_DATA_RESERVE_SHIFT 3
+ u8 timeout;
+#elif defined(__LITTLE_ENDIAN)
+ u8 timeout;
+ u8 flags;
+#define HC_INDEX_DATA_SM_ID (0x1<<0)
+#define HC_INDEX_DATA_SM_ID_SHIFT 0
+#define HC_INDEX_DATA_HC_ENABLED (0x1<<1)
+#define HC_INDEX_DATA_HC_ENABLED_SHIFT 1
+#define HC_INDEX_DATA_DYNAMIC_HC_ENABLED (0x1<<2)
+#define HC_INDEX_DATA_DYNAMIC_HC_ENABLED_SHIFT 2
+#define HC_INDEX_DATA_RESERVE (0x1F<<3)
+#define HC_INDEX_DATA_RESERVE_SHIFT 3
+#endif
+};
+
+
+/*
+ * HC state-machine
+ */
+struct hc_status_block_sm {
+#if defined(__BIG_ENDIAN)
+ u8 igu_seg_id;
+ u8 igu_sb_id;
+ u8 timer_value;
+ u8 __flags;
+#elif defined(__LITTLE_ENDIAN)
+ u8 __flags;
+ u8 timer_value;
+ u8 igu_sb_id;
+ u8 igu_seg_id;
+#endif
+ u32 time_to_expire;
+};
+
+/*
+ * hold PCI identification variables- used in various places in firmware
+ */
+struct pci_entity {
+#if defined(__BIG_ENDIAN)
+ u8 vf_valid;
+ u8 vf_id;
+ u8 vnic_id;
+ u8 pf_id;
+#elif defined(__LITTLE_ENDIAN)
+ u8 pf_id;
+ u8 vnic_id;
+ u8 vf_id;
+ u8 vf_valid;
+#endif
+};
+
+/*
+ * The fast-path status block meta-data, common to all chips
+ */
+struct hc_sb_data {
+ struct regpair host_sb_addr;
+ struct hc_status_block_sm state_machine[HC_SB_MAX_SM];
+ struct pci_entity p_func;
+#if defined(__BIG_ENDIAN)
+ u8 rsrv0;
+ u8 dhc_qzone_id;
+ u8 __dynamic_hc_level;
+ u8 same_igu_sb_1b;
+#elif defined(__LITTLE_ENDIAN)
+ u8 same_igu_sb_1b;
+ u8 __dynamic_hc_level;
+ u8 dhc_qzone_id;
+ u8 rsrv0;
+#endif
+ struct regpair rsrv1[2];
+};
+
+
+/*
+ * The fast-path status block meta-data
+ */
+struct hc_sp_status_block_data {
+ struct regpair host_sb_addr;
+#if defined(__BIG_ENDIAN)
+ u16 rsrv;
+ u8 igu_seg_id;
+ u8 igu_sb_id;
+#elif defined(__LITTLE_ENDIAN)
+ u8 igu_sb_id;
+ u8 igu_seg_id;
+ u16 rsrv;
+#endif
+ struct pci_entity p_func;
+};
+
+
+/*
+ * The fast-path status block meta-data
+ */
+struct hc_status_block_data_e1x {
+ struct hc_index_data index_data[HC_SB_MAX_INDICES_E1X];
+ struct hc_sb_data common;
+};
+
+
+/*
+ * The fast-path status block meta-data
+ */
+struct hc_status_block_data_e2 {
+ struct hc_index_data index_data[HC_SB_MAX_INDICES_E2];
+ struct hc_sb_data common;
+};
+
+
+/*
* FW version stored in first line of pram
*/
struct pram_fw_version {
@@ -3086,11 +3156,21 @@ struct pram_fw_version {
/*
+ * Ethernet slow path element
+ */
+union protocol_common_specific_data {
+ u8 protocol_data[8];
+ struct regpair phy_address;
+ struct regpair mac_config_addr;
+ struct common_query_ramrod_data query_ramrod_data;
+};
+
+/*
* The send queue element
*/
struct protocol_common_spe {
struct spe_hdr hdr;
- struct regpair phy_address;
+ union protocol_common_specific_data data;
};
@@ -3123,7 +3203,7 @@ struct rate_shaping_vars_per_vn {
*/
struct slow_path_element {
struct spe_hdr hdr;
- u8 protocol_data[8];
+ struct regpair protocol_data;
};
@@ -3136,3 +3216,97 @@ struct stats_indication_flags {
};
+/*
+ * per-port PFC variables
+ */
+struct storm_pfc_struct_per_port {
+#if defined(__BIG_ENDIAN)
+ u16 mid_mac_addr;
+ u16 msb_mac_addr;
+#elif defined(__LITTLE_ENDIAN)
+ u16 msb_mac_addr;
+ u16 mid_mac_addr;
+#endif
+#if defined(__BIG_ENDIAN)
+ u16 pfc_pause_quanta_in_nanosec;
+ u16 lsb_mac_addr;
+#elif defined(__LITTLE_ENDIAN)
+ u16 lsb_mac_addr;
+ u16 pfc_pause_quanta_in_nanosec;
+#endif
+};
+
+/*
+ * Per-port congestion management variables
+ */
+struct storm_cmng_struct_per_port {
+ struct storm_pfc_struct_per_port pfc_vars;
+};
+
+
+/*
+ * zone A per-queue data
+ */
+struct tstorm_queue_zone_data {
+ struct regpair reserved[4];
+};
+
+
+/*
+ * zone B per-VF data
+ */
+struct tstorm_vf_zone_data {
+ struct regpair reserved;
+};
+
+
+/*
+ * zone A per-queue data
+ */
+struct ustorm_queue_zone_data {
+ struct ustorm_eth_rx_producers eth_rx_producers;
+ struct regpair reserved[3];
+};
+
+
+/*
+ * zone B per-VF data
+ */
+struct ustorm_vf_zone_data {
+ struct regpair reserved;
+};
+
+
+/*
+ * data per VF-PF channel
+ */
+struct vf_pf_channel_data {
+#if defined(__BIG_ENDIAN)
+ u16 reserved0;
+ u8 valid;
+ u8 state;
+#elif defined(__LITTLE_ENDIAN)
+ u8 state;
+ u8 valid;
+ u16 reserved0;
+#endif
+ u32 reserved1;
+};
+
+
+/*
+ * zone A per-queue data
+ */
+struct xstorm_queue_zone_data {
+ struct regpair reserved[4];
+};
+
+
+/*
+ * zone B per-VF data
+ */
+struct xstorm_vf_zone_data {
+ struct regpair reserved;
+};
+
+#endif /* BNX2X_HSI_H */
diff --git a/drivers/net/bnx2x/bnx2x_init.h b/drivers/net/bnx2x/bnx2x_init.h
index 65b26cbfe3e7..a9d54874a559 100644
--- a/drivers/net/bnx2x/bnx2x_init.h
+++ b/drivers/net/bnx2x/bnx2x_init.h
@@ -97,6 +97,9 @@
#define MISC_AEU_BLOCK 35
#define PGLUE_B_BLOCK 36
#define IGU_BLOCK 37
+#define ATC_BLOCK 38
+#define QM_4PORT_BLOCK 39
+#define XSEM_4PORT_BLOCK 40
/* Returns the index of start or end of a specific block stage in ops array*/
@@ -148,5 +151,46 @@ union init_op {
struct raw_op raw;
};
+#define INITOP_SET 0 /* set the HW directly */
+#define INITOP_CLEAR 1 /* clear the HW directly */
+#define INITOP_INIT 2 /* set the init-value array */
+
+/****************************************************************************
+* ILT management
+****************************************************************************/
+struct ilt_line {
+ dma_addr_t page_mapping;
+ void *page;
+ u32 size;
+};
+
+struct ilt_client_info {
+ u32 page_size;
+ u16 start;
+ u16 end;
+ u16 client_num;
+ u16 flags;
+#define ILT_CLIENT_SKIP_INIT 0x1
+#define ILT_CLIENT_SKIP_MEM 0x2
+};
+
+struct bnx2x_ilt {
+ u32 start_line;
+ struct ilt_line *lines;
+ struct ilt_client_info clients[4];
+#define ILT_CLIENT_CDU 0
+#define ILT_CLIENT_QM 1
+#define ILT_CLIENT_SRC 2
+#define ILT_CLIENT_TM 3
+};
+
+/****************************************************************************
+* SRC configuration
+****************************************************************************/
+struct src_ent {
+ u8 opaque[56];
+ u64 next;
+};
+
#endif /* BNX2X_INIT_H */
diff --git a/drivers/net/bnx2x/bnx2x_init_ops.h b/drivers/net/bnx2x/bnx2x_init_ops.h
index 2b1363a6fe78..e65de784182c 100644
--- a/drivers/net/bnx2x/bnx2x_init_ops.h
+++ b/drivers/net/bnx2x/bnx2x_init_ops.h
@@ -151,6 +151,15 @@ static void bnx2x_init_wr_wb(struct bnx2x *bp, u32 addr, const u32 *data,
bnx2x_init_ind_wr(bp, addr, data, len);
}
+static void bnx2x_wr_64(struct bnx2x *bp, u32 reg, u32 val_lo, u32 val_hi)
+{
+ u32 wb_write[2];
+
+ wb_write[0] = val_lo;
+ wb_write[1] = val_hi;
+ REG_WR_DMAE_LEN(bp, reg, wb_write, 2);
+}
+
static void bnx2x_init_wr_zp(struct bnx2x *bp, u32 addr, u32 len, u32 blob_off)
{
const u8 *data = NULL;
@@ -477,18 +486,30 @@ static void bnx2x_init_pxp_arb(struct bnx2x *bp, int r_order, int w_order)
REG_WR(bp, PXP2_REG_RQ_RD_MBS0, r_order);
REG_WR(bp, PXP2_REG_RQ_RD_MBS1, r_order);
- if (r_order == MAX_RD_ORD)
+ if ((CHIP_IS_E1(bp) || CHIP_IS_E1H(bp)) && (r_order == MAX_RD_ORD))
REG_WR(bp, PXP2_REG_RQ_PDR_LIMIT, 0xe00);
- REG_WR(bp, PXP2_REG_WR_USDMDP_TH, (0x18 << w_order));
+ if (CHIP_IS_E2(bp))
+ REG_WR(bp, PXP2_REG_WR_USDMDP_TH, (0x8 << w_order));
+ else
+ REG_WR(bp, PXP2_REG_WR_USDMDP_TH, (0x18 << w_order));
- if (CHIP_IS_E1H(bp)) {
+ if (CHIP_IS_E1H(bp) || CHIP_IS_E2(bp)) {
/* MPS w_order optimal TH presently TH
* 128 0 0 2
* 256 1 1 3
* >=512 2 2 3
*/
- val = ((w_order == 0) ? 2 : 3);
+ /* DMAE is special */
+ if (CHIP_IS_E2(bp)) {
+ /* E2 can use optimal TH */
+ val = w_order;
+ REG_WR(bp, PXP2_REG_WR_DMAE_MPS, val);
+ } else {
+ val = ((w_order == 0) ? 2 : 3);
+ REG_WR(bp, PXP2_REG_WR_DMAE_MPS, 2);
+ }
+
REG_WR(bp, PXP2_REG_WR_HC_MPS, val);
REG_WR(bp, PXP2_REG_WR_USDM_MPS, val);
REG_WR(bp, PXP2_REG_WR_CSDM_MPS, val);
@@ -498,9 +519,344 @@ static void bnx2x_init_pxp_arb(struct bnx2x *bp, int r_order, int w_order)
REG_WR(bp, PXP2_REG_WR_TM_MPS, val);
REG_WR(bp, PXP2_REG_WR_SRC_MPS, val);
REG_WR(bp, PXP2_REG_WR_DBG_MPS, val);
- REG_WR(bp, PXP2_REG_WR_DMAE_MPS, 2); /* DMAE is special */
REG_WR(bp, PXP2_REG_WR_CDU_MPS, val);
}
+
+ /* Validate number of tags suppoted by device */
+#define PCIE_REG_PCIER_TL_HDR_FC_ST 0x2980
+ val = REG_RD(bp, PCIE_REG_PCIER_TL_HDR_FC_ST);
+ val &= 0xFF;
+ if (val <= 0x20)
+ REG_WR(bp, PXP2_REG_PGL_TAGS_LIMIT, 0x20);
+}
+
+/****************************************************************************
+* ILT management
+****************************************************************************/
+/*
+ * This codes hides the low level HW interaction for ILT management and
+ * configuration. The API consists of a shadow ILT table which is set by the
+ * driver and a set of routines to use it to configure the HW.
+ *
+ */
+
+/* ILT HW init operations */
+
+/* ILT memory management operations */
+#define ILT_MEMOP_ALLOC 0
+#define ILT_MEMOP_FREE 1
+
+/* the phys address is shifted right 12 bits and has an added
+ * 1=valid bit added to the 53rd bit
+ * then since this is a wide register(TM)
+ * we split it into two 32 bit writes
+ */
+#define ILT_ADDR1(x) ((u32)(((u64)x >> 12) & 0xFFFFFFFF))
+#define ILT_ADDR2(x) ((u32)((1 << 20) | ((u64)x >> 44)))
+#define ILT_RANGE(f, l) (((l) << 10) | f)
+
+static int bnx2x_ilt_line_mem_op(struct bnx2x *bp, struct ilt_line *line,
+ u32 size, u8 memop)
+{
+ if (memop == ILT_MEMOP_FREE) {
+ BNX2X_ILT_FREE(line->page, line->page_mapping, line->size);
+ return 0;
+ }
+ BNX2X_ILT_ZALLOC(line->page, &line->page_mapping, size);
+ if (!line->page)
+ return -1;
+ line->size = size;
+ return 0;
+}
+
+
+static int bnx2x_ilt_client_mem_op(struct bnx2x *bp, int cli_num, u8 memop)
+{
+ int i, rc;
+ struct bnx2x_ilt *ilt = BP_ILT(bp);
+ struct ilt_client_info *ilt_cli = &ilt->clients[cli_num];
+
+ if (!ilt || !ilt->lines)
+ return -1;
+
+ if (ilt_cli->flags & (ILT_CLIENT_SKIP_INIT | ILT_CLIENT_SKIP_MEM))
+ return 0;
+
+ for (rc = 0, i = ilt_cli->start; i <= ilt_cli->end && !rc; i++) {
+ rc = bnx2x_ilt_line_mem_op(bp, &ilt->lines[i],
+ ilt_cli->page_size, memop);
+ }
+ return rc;
+}
+
+int bnx2x_ilt_mem_op(struct bnx2x *bp, u8 memop)
+{
+ int rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_CDU, memop);
+ if (!rc)
+ rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_QM, memop);
+ if (!rc)
+ rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_SRC, memop);
+ if (!rc)
+ rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_TM, memop);
+
+ return rc;
+}
+
+static void bnx2x_ilt_line_wr(struct bnx2x *bp, int abs_idx,
+ dma_addr_t page_mapping)
+{
+ u32 reg;
+
+ if (CHIP_IS_E1(bp))
+ reg = PXP2_REG_RQ_ONCHIP_AT + abs_idx*8;
+ else
+ reg = PXP2_REG_RQ_ONCHIP_AT_B0 + abs_idx*8;
+
+ bnx2x_wr_64(bp, reg, ILT_ADDR1(page_mapping), ILT_ADDR2(page_mapping));
+}
+
+static void bnx2x_ilt_line_init_op(struct bnx2x *bp, struct bnx2x_ilt *ilt,
+ int idx, u8 initop)
+{
+ dma_addr_t null_mapping;
+ int abs_idx = ilt->start_line + idx;
+
+
+ switch (initop) {
+ case INITOP_INIT:
+ /* set in the init-value array */
+ case INITOP_SET:
+ bnx2x_ilt_line_wr(bp, abs_idx, ilt->lines[idx].page_mapping);
+ break;
+ case INITOP_CLEAR:
+ null_mapping = 0;
+ bnx2x_ilt_line_wr(bp, abs_idx, null_mapping);
+ break;
+ }
+}
+
+void bnx2x_ilt_boundry_init_op(struct bnx2x *bp,
+ struct ilt_client_info *ilt_cli,
+ u32 ilt_start, u8 initop)
+{
+ u32 start_reg = 0;
+ u32 end_reg = 0;
+
+ /* The boundary is either SET or INIT,
+ CLEAR => SET and for now SET ~~ INIT */
+
+ /* find the appropriate regs */
+ if (CHIP_IS_E1(bp)) {
+ switch (ilt_cli->client_num) {
+ case ILT_CLIENT_CDU:
+ start_reg = PXP2_REG_PSWRQ_CDU0_L2P;
+ break;
+ case ILT_CLIENT_QM:
+ start_reg = PXP2_REG_PSWRQ_QM0_L2P;
+ break;
+ case ILT_CLIENT_SRC:
+ start_reg = PXP2_REG_PSWRQ_SRC0_L2P;
+ break;
+ case ILT_CLIENT_TM:
+ start_reg = PXP2_REG_PSWRQ_TM0_L2P;
+ break;
+ }
+ REG_WR(bp, start_reg + BP_FUNC(bp)*4,
+ ILT_RANGE((ilt_start + ilt_cli->start),
+ (ilt_start + ilt_cli->end)));
+ } else {
+ switch (ilt_cli->client_num) {
+ case ILT_CLIENT_CDU:
+ start_reg = PXP2_REG_RQ_CDU_FIRST_ILT;
+ end_reg = PXP2_REG_RQ_CDU_LAST_ILT;
+ break;
+ case ILT_CLIENT_QM:
+ start_reg = PXP2_REG_RQ_QM_FIRST_ILT;
+ end_reg = PXP2_REG_RQ_QM_LAST_ILT;
+ break;
+ case ILT_CLIENT_SRC:
+ start_reg = PXP2_REG_RQ_SRC_FIRST_ILT;
+ end_reg = PXP2_REG_RQ_SRC_LAST_ILT;
+ break;
+ case ILT_CLIENT_TM:
+ start_reg = PXP2_REG_RQ_TM_FIRST_ILT;
+ end_reg = PXP2_REG_RQ_TM_LAST_ILT;
+ break;
+ }
+ REG_WR(bp, start_reg, (ilt_start + ilt_cli->start));
+ REG_WR(bp, end_reg, (ilt_start + ilt_cli->end));
+ }
+}
+
+void bnx2x_ilt_client_init_op_ilt(struct bnx2x *bp, struct bnx2x_ilt *ilt,
+ struct ilt_client_info *ilt_cli, u8 initop)
+{
+ int i;
+
+ if (ilt_cli->flags & ILT_CLIENT_SKIP_INIT)
+ return;
+
+ for (i = ilt_cli->start; i <= ilt_cli->end; i++)
+ bnx2x_ilt_line_init_op(bp, ilt, i, initop);
+
+ /* init/clear the ILT boundries */
+ bnx2x_ilt_boundry_init_op(bp, ilt_cli, ilt->start_line, initop);
+}
+
+void bnx2x_ilt_client_init_op(struct bnx2x *bp,
+ struct ilt_client_info *ilt_cli, u8 initop)
+{
+ struct bnx2x_ilt *ilt = BP_ILT(bp);
+
+ bnx2x_ilt_client_init_op_ilt(bp, ilt, ilt_cli, initop);
+}
+
+static void bnx2x_ilt_client_id_init_op(struct bnx2x *bp,
+ int cli_num, u8 initop)
+{
+ struct bnx2x_ilt *ilt = BP_ILT(bp);
+ struct ilt_client_info *ilt_cli = &ilt->clients[cli_num];
+
+ bnx2x_ilt_client_init_op(bp, ilt_cli, initop);
+}
+
+void bnx2x_ilt_init_op(struct bnx2x *bp, u8 initop)
+{
+ bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_CDU, initop);
+ bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_QM, initop);
+ bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_SRC, initop);
+ bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_TM, initop);
+}
+
+static void bnx2x_ilt_init_client_psz(struct bnx2x *bp, int cli_num,
+ u32 psz_reg, u8 initop)
+{
+ struct bnx2x_ilt *ilt = BP_ILT(bp);
+ struct ilt_client_info *ilt_cli = &ilt->clients[cli_num];
+
+ if (ilt_cli->flags & ILT_CLIENT_SKIP_INIT)
+ return;
+
+ switch (initop) {
+ case INITOP_INIT:
+ /* set in the init-value array */
+ case INITOP_SET:
+ REG_WR(bp, psz_reg, ILOG2(ilt_cli->page_size >> 12));
+ break;
+ case INITOP_CLEAR:
+ break;
+ }
+}
+
+/*
+ * called during init common stage, ilt clients should be initialized
+ * prioir to calling this function
+ */
+void bnx2x_ilt_init_page_size(struct bnx2x *bp, u8 initop)
+{
+ bnx2x_ilt_init_client_psz(bp, ILT_CLIENT_CDU,
+ PXP2_REG_RQ_CDU_P_SIZE, initop);
+ bnx2x_ilt_init_client_psz(bp, ILT_CLIENT_QM,
+ PXP2_REG_RQ_QM_P_SIZE, initop);
+ bnx2x_ilt_init_client_psz(bp, ILT_CLIENT_SRC,
+ PXP2_REG_RQ_SRC_P_SIZE, initop);
+ bnx2x_ilt_init_client_psz(bp, ILT_CLIENT_TM,
+ PXP2_REG_RQ_TM_P_SIZE, initop);
+}
+
+/****************************************************************************
+* QM initializations
+****************************************************************************/
+#define QM_QUEUES_PER_FUNC 16 /* E1 has 32, but only 16 are used */
+#define QM_INIT_MIN_CID_COUNT 31
+#define QM_INIT(cid_cnt) (cid_cnt > QM_INIT_MIN_CID_COUNT)
+
+/* called during init port stage */
+void bnx2x_qm_init_cid_count(struct bnx2x *bp, int qm_cid_count,
+ u8 initop)
+{
+ int port = BP_PORT(bp);
+
+ if (QM_INIT(qm_cid_count)) {
+ switch (initop) {
+ case INITOP_INIT:
+ /* set in the init-value array */
+ case INITOP_SET:
+ REG_WR(bp, QM_REG_CONNNUM_0 + port*4,
+ qm_cid_count/16 - 1);
+ break;
+ case INITOP_CLEAR:
+ break;
+ }
+ }
+}
+
+static void bnx2x_qm_set_ptr_table(struct bnx2x *bp, int qm_cid_count)
+{
+ int i;
+ u32 wb_data[2];
+
+ wb_data[0] = wb_data[1] = 0;
+
+ for (i = 0; i < 4 * QM_QUEUES_PER_FUNC; i++) {
+ REG_WR(bp, QM_REG_BASEADDR + i*4,
+ qm_cid_count * 4 * (i % QM_QUEUES_PER_FUNC));
+ bnx2x_init_ind_wr(bp, QM_REG_PTRTBL + i*8,
+ wb_data, 2);
+
+ if (CHIP_IS_E1H(bp)) {
+ REG_WR(bp, QM_REG_BASEADDR_EXT_A + i*4,
+ qm_cid_count * 4 * (i % QM_QUEUES_PER_FUNC));
+ bnx2x_init_ind_wr(bp, QM_REG_PTRTBL_EXT_A + i*8,
+ wb_data, 2);
+ }
+ }
+}
+
+/* called during init common stage */
+void bnx2x_qm_init_ptr_table(struct bnx2x *bp, int qm_cid_count,
+ u8 initop)
+{
+ if (!QM_INIT(qm_cid_count))
+ return;
+
+ switch (initop) {
+ case INITOP_INIT:
+ /* set in the init-value array */
+ case INITOP_SET:
+ bnx2x_qm_set_ptr_table(bp, qm_cid_count);
+ break;
+ case INITOP_CLEAR:
+ break;
+ }
+}
+
+/****************************************************************************
+* SRC initializations
+****************************************************************************/
+
+/* called during init func stage */
+void bnx2x_src_init_t2(struct bnx2x *bp, struct src_ent *t2,
+ dma_addr_t t2_mapping, int src_cid_count)
+{
+ int i;
+ int port = BP_PORT(bp);
+
+ /* Initialize T2 */
+ for (i = 0; i < src_cid_count-1; i++)
+ t2[i].next = (u64)(t2_mapping + (i+1)*sizeof(struct src_ent));
+
+ /* tell the searcher where the T2 table is */
+ REG_WR(bp, SRC_REG_COUNTFREE0 + port*4, src_cid_count);
+
+ bnx2x_wr_64(bp, SRC_REG_FIRSTFREE0 + port*16,
+ U64_LO(t2_mapping), U64_HI(t2_mapping));
+
+ bnx2x_wr_64(bp, SRC_REG_LASTFREE0 + port*16,
+ U64_LO((u64)t2_mapping +
+ (src_cid_count-1) * sizeof(struct src_ent)),
+ U64_HI((u64)t2_mapping +
+ (src_cid_count-1) * sizeof(struct src_ent)));
}
#endif /* BNX2X_INIT_OPS_H */
diff --git a/drivers/net/bnx2x/bnx2x_link.c b/drivers/net/bnx2x/bnx2x_link.c
index 0383e3066313..3e99bf9c42b9 100644
--- a/drivers/net/bnx2x/bnx2x_link.c
+++ b/drivers/net/bnx2x/bnx2x_link.c
@@ -28,7 +28,7 @@
/********************************************************/
#define ETH_HLEN 14
-#define ETH_OVREHEAD (ETH_HLEN + 8)/* 8 for CRC + VLAN*/
+#define ETH_OVREHEAD (ETH_HLEN + 8 + 8)/* 16 for CRC + VLAN + LLC */
#define ETH_MIN_PACKET_SIZE 60
#define ETH_MAX_PACKET_SIZE 1500
#define ETH_MAX_JUMBO_PACKET_SIZE 9600
@@ -168,50 +168,19 @@
/**********************************************************/
/* INTERFACE */
/**********************************************************/
-#define CL45_WR_OVER_CL22(_bp, _port, _phy_addr, _bank, _addr, _val) \
- bnx2x_cl45_write(_bp, _port, 0, _phy_addr, \
- DEFAULT_PHY_DEV_ADDR, \
+
+#define CL45_WR_OVER_CL22(_bp, _phy, _bank, _addr, _val) \
+ bnx2x_cl45_write(_bp, _phy, \
+ (_phy)->def_md_devad, \
(_bank + (_addr & 0xf)), \
_val)
-#define CL45_RD_OVER_CL22(_bp, _port, _phy_addr, _bank, _addr, _val) \
- bnx2x_cl45_read(_bp, _port, 0, _phy_addr, \
- DEFAULT_PHY_DEV_ADDR, \
+#define CL45_RD_OVER_CL22(_bp, _phy, _bank, _addr, _val) \
+ bnx2x_cl45_read(_bp, _phy, \
+ (_phy)->def_md_devad, \
(_bank + (_addr & 0xf)), \
_val)
-static void bnx2x_set_serdes_access(struct link_params *params)
-{
- struct bnx2x *bp = params->bp;
- u32 emac_base = (params->port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
-
- /* Set Clause 22 */
- REG_WR(bp, NIG_REG_SERDES0_CTRL_MD_ST + params->port*0x10, 1);
- REG_WR(bp, emac_base + EMAC_REG_EMAC_MDIO_COMM, 0x245f8000);
- udelay(500);
- REG_WR(bp, emac_base + EMAC_REG_EMAC_MDIO_COMM, 0x245d000f);
- udelay(500);
- /* Set Clause 45 */
- REG_WR(bp, NIG_REG_SERDES0_CTRL_MD_ST + params->port*0x10, 0);
-}
-static void bnx2x_set_phy_mdio(struct link_params *params, u8 phy_flags)
-{
- struct bnx2x *bp = params->bp;
-
- if (phy_flags & PHY_XGXS_FLAG) {
- REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST +
- params->port*0x18, 0);
- REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + params->port*0x18,
- DEFAULT_PHY_DEV_ADDR);
- } else {
- bnx2x_set_serdes_access(params);
-
- REG_WR(bp, NIG_REG_SERDES0_CTRL_MD_DEVAD +
- params->port*0x10,
- DEFAULT_PHY_DEV_ADDR);
- }
-}
-
static u32 bnx2x_bits_en(struct bnx2x *bp, u32 reg, u32 bits)
{
u32 val = REG_RD(bp, reg);
@@ -408,9 +377,60 @@ static u8 bnx2x_emac_enable(struct link_params *params,
return 0;
}
+static void bnx2x_update_bmac2(struct link_params *params,
+ struct link_vars *vars,
+ u8 is_lb)
+{
+ /*
+ * Set rx control: Strip CRC and enable BigMAC to relay
+ * control packets to the system as well
+ */
+ u32 wb_data[2];
+ struct bnx2x *bp = params->bp;
+ u32 bmac_addr = params->port ? NIG_REG_INGRESS_BMAC1_MEM :
+ NIG_REG_INGRESS_BMAC0_MEM;
+ u32 val = 0x14;
+
+ if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
+ /* Enable BigMAC to react on received Pause packets */
+ val |= (1<<5);
+ wb_data[0] = val;
+ wb_data[1] = 0;
+ REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_RX_CONTROL,
+ wb_data, 2);
+ udelay(30);
+
+ /* Tx control */
+ val = 0xc0;
+ if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
+ val |= 0x800000;
+ wb_data[0] = val;
+ wb_data[1] = 0;
+ REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_TX_CONTROL,
+ wb_data, 2);
+
+ val = 0x8000;
+ wb_data[0] = val;
+ wb_data[1] = 0;
+ REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_TX_PAUSE_CONTROL,
+ wb_data, 2);
+
+ /* mac control */
+ val = 0x3; /* Enable RX and TX */
+ if (is_lb) {
+ val |= 0x4; /* Local loopback */
+ DP(NETIF_MSG_LINK, "enable bmac loopback\n");
+ }
+
+ wb_data[0] = val;
+ wb_data[1] = 0;
+ REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_BMAC_CONTROL,
+ wb_data, 2);
+}
-static u8 bnx2x_bmac_enable(struct link_params *params, struct link_vars *vars,
+static u8 bnx2x_bmac1_enable(struct link_params *params,
+ struct link_vars *vars,
u8 is_lb)
{
struct bnx2x *bp = params->bp;
@@ -420,17 +440,7 @@ static u8 bnx2x_bmac_enable(struct link_params *params, struct link_vars *vars,
u32 wb_data[2];
u32 val;
- DP(NETIF_MSG_LINK, "Enabling BigMAC\n");
- /* reset and unreset the BigMac */
- REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
- (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
- msleep(1);
-
- REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
- (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
-
- /* enable access for bmac registers */
- REG_WR(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4, 0x1);
+ DP(NETIF_MSG_LINK, "Enabling BigMAC1\n");
/* XGXS control */
wb_data[0] = 0x3c;
@@ -510,180 +520,121 @@ static u8 bnx2x_bmac_enable(struct link_params *params, struct link_vars *vars,
wb_data, 2);
}
- REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4, 0x1);
- REG_WR(bp, NIG_REG_XGXS_LANE_SEL_P0 + port*4, 0x0);
- REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + port*4, 0x0);
- val = 0;
- if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
- val = 1;
- REG_WR(bp, NIG_REG_BMAC0_PAUSE_OUT_EN + port*4, val);
- REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0x0);
- REG_WR(bp, NIG_REG_EMAC0_IN_EN + port*4, 0x0);
- REG_WR(bp, NIG_REG_EMAC0_PAUSE_OUT_EN + port*4, 0x0);
- REG_WR(bp, NIG_REG_BMAC0_IN_EN + port*4, 0x1);
- REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0x1);
- vars->mac_type = MAC_TYPE_BMAC;
return 0;
}
-static void bnx2x_phy_deassert(struct link_params *params, u8 phy_flags)
-{
- struct bnx2x *bp = params->bp;
- u32 val;
-
- if (phy_flags & PHY_XGXS_FLAG) {
- DP(NETIF_MSG_LINK, "bnx2x_phy_deassert:XGXS\n");
- val = XGXS_RESET_BITS;
-
- } else { /* SerDes */
- DP(NETIF_MSG_LINK, "bnx2x_phy_deassert:SerDes\n");
- val = SERDES_RESET_BITS;
- }
-
- val = val << (params->port*16);
-
- /* reset and unreset the SerDes/XGXS */
- REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR,
- val);
- udelay(500);
- REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET,
- val);
- bnx2x_set_phy_mdio(params, phy_flags);
-}
-
-void bnx2x_link_status_update(struct link_params *params,
- struct link_vars *vars)
+static u8 bnx2x_bmac2_enable(struct link_params *params,
+ struct link_vars *vars,
+ u8 is_lb)
{
struct bnx2x *bp = params->bp;
- u8 link_10g;
u8 port = params->port;
+ u32 bmac_addr = port ? NIG_REG_INGRESS_BMAC1_MEM :
+ NIG_REG_INGRESS_BMAC0_MEM;
+ u32 wb_data[2];
- if (params->switch_cfg == SWITCH_CFG_1G)
- vars->phy_flags = PHY_SERDES_FLAG;
- else
- vars->phy_flags = PHY_XGXS_FLAG;
- vars->link_status = REG_RD(bp, params->shmem_base +
- offsetof(struct shmem_region,
- port_mb[port].link_status));
-
- vars->link_up = (vars->link_status & LINK_STATUS_LINK_UP);
-
- if (vars->link_up) {
- DP(NETIF_MSG_LINK, "phy link up\n");
-
- vars->phy_link_up = 1;
- vars->duplex = DUPLEX_FULL;
- switch (vars->link_status &
- LINK_STATUS_SPEED_AND_DUPLEX_MASK) {
- case LINK_10THD:
- vars->duplex = DUPLEX_HALF;
- /* fall thru */
- case LINK_10TFD:
- vars->line_speed = SPEED_10;
- break;
-
- case LINK_100TXHD:
- vars->duplex = DUPLEX_HALF;
- /* fall thru */
- case LINK_100T4:
- case LINK_100TXFD:
- vars->line_speed = SPEED_100;
- break;
-
- case LINK_1000THD:
- vars->duplex = DUPLEX_HALF;
- /* fall thru */
- case LINK_1000TFD:
- vars->line_speed = SPEED_1000;
- break;
-
- case LINK_2500THD:
- vars->duplex = DUPLEX_HALF;
- /* fall thru */
- case LINK_2500TFD:
- vars->line_speed = SPEED_2500;
- break;
-
- case LINK_10GTFD:
- vars->line_speed = SPEED_10000;
- break;
-
- case LINK_12GTFD:
- vars->line_speed = SPEED_12000;
- break;
+ DP(NETIF_MSG_LINK, "Enabling BigMAC2\n");
- case LINK_12_5GTFD:
- vars->line_speed = SPEED_12500;
- break;
+ wb_data[0] = 0;
+ wb_data[1] = 0;
+ REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_BMAC_CONTROL,
+ wb_data, 2);
+ udelay(30);
- case LINK_13GTFD:
- vars->line_speed = SPEED_13000;
- break;
+ /* XGXS control: Reset phy HW, MDIO registers, PHY PLL and BMAC */
+ wb_data[0] = 0x3c;
+ wb_data[1] = 0;
+ REG_WR_DMAE(bp, bmac_addr +
+ BIGMAC2_REGISTER_BMAC_XGXS_CONTROL,
+ wb_data, 2);
- case LINK_15GTFD:
- vars->line_speed = SPEED_15000;
- break;
+ udelay(30);
- case LINK_16GTFD:
- vars->line_speed = SPEED_16000;
- break;
+ /* tx MAC SA */
+ wb_data[0] = ((params->mac_addr[2] << 24) |
+ (params->mac_addr[3] << 16) |
+ (params->mac_addr[4] << 8) |
+ params->mac_addr[5]);
+ wb_data[1] = ((params->mac_addr[0] << 8) |
+ params->mac_addr[1]);
+ REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_TX_SOURCE_ADDR,
+ wb_data, 2);
- default:
- break;
- }
+ udelay(30);
- if (vars->link_status & LINK_STATUS_TX_FLOW_CONTROL_ENABLED)
- vars->flow_ctrl |= BNX2X_FLOW_CTRL_TX;
- else
- vars->flow_ctrl &= ~BNX2X_FLOW_CTRL_TX;
+ /* Configure SAFC */
+ wb_data[0] = 0x1000200;
+ wb_data[1] = 0;
+ REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_RX_LLFC_MSG_FLDS,
+ wb_data, 2);
+ udelay(30);
- if (vars->link_status & LINK_STATUS_RX_FLOW_CONTROL_ENABLED)
- vars->flow_ctrl |= BNX2X_FLOW_CTRL_RX;
- else
- vars->flow_ctrl &= ~BNX2X_FLOW_CTRL_RX;
+ /* set rx mtu */
+ wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
+ wb_data[1] = 0;
+ REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_RX_MAX_SIZE,
+ wb_data, 2);
+ udelay(30);
- if (vars->phy_flags & PHY_XGXS_FLAG) {
- if (vars->line_speed &&
- ((vars->line_speed == SPEED_10) ||
- (vars->line_speed == SPEED_100))) {
- vars->phy_flags |= PHY_SGMII_FLAG;
- } else {
- vars->phy_flags &= ~PHY_SGMII_FLAG;
- }
- }
+ /* set tx mtu */
+ wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
+ wb_data[1] = 0;
+ REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_TX_MAX_SIZE,
+ wb_data, 2);
+ udelay(30);
+ /* set cnt max size */
+ wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD - 2;
+ wb_data[1] = 0;
+ REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_CNT_MAX_SIZE,
+ wb_data, 2);
+ udelay(30);
+ bnx2x_update_bmac2(params, vars, is_lb);
- /* anything 10 and over uses the bmac */
- link_10g = ((vars->line_speed == SPEED_10000) ||
- (vars->line_speed == SPEED_12000) ||
- (vars->line_speed == SPEED_12500) ||
- (vars->line_speed == SPEED_13000) ||
- (vars->line_speed == SPEED_15000) ||
- (vars->line_speed == SPEED_16000));
- if (link_10g)
- vars->mac_type = MAC_TYPE_BMAC;
- else
- vars->mac_type = MAC_TYPE_EMAC;
+ return 0;
+}
- } else { /* link down */
- DP(NETIF_MSG_LINK, "phy link down\n");
+u8 bnx2x_bmac_enable(struct link_params *params,
+ struct link_vars *vars,
+ u8 is_lb)
+{
+ u8 rc, port = params->port;
+ struct bnx2x *bp = params->bp;
+ u32 val;
+ /* reset and unreset the BigMac */
+ REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
+ (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
+ udelay(10);
- vars->phy_link_up = 0;
+ REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
+ (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
- vars->line_speed = 0;
- vars->duplex = DUPLEX_FULL;
- vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
+ /* enable access for bmac registers */
+ REG_WR(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4, 0x1);
- /* indicate no mac active */
- vars->mac_type = MAC_TYPE_NONE;
- }
+ /* Enable BMAC according to BMAC type*/
+ if (CHIP_IS_E2(bp))
+ rc = bnx2x_bmac2_enable(params, vars, is_lb);
+ else
+ rc = bnx2x_bmac1_enable(params, vars, is_lb);
+ REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4, 0x1);
+ REG_WR(bp, NIG_REG_XGXS_LANE_SEL_P0 + port*4, 0x0);
+ REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + port*4, 0x0);
+ val = 0;
+ if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
+ val = 1;
+ REG_WR(bp, NIG_REG_BMAC0_PAUSE_OUT_EN + port*4, val);
+ REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0x0);
+ REG_WR(bp, NIG_REG_EMAC0_IN_EN + port*4, 0x0);
+ REG_WR(bp, NIG_REG_EMAC0_PAUSE_OUT_EN + port*4, 0x0);
+ REG_WR(bp, NIG_REG_BMAC0_IN_EN + port*4, 0x1);
+ REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0x1);
- DP(NETIF_MSG_LINK, "link_status 0x%x phy_link_up %x\n",
- vars->link_status, vars->phy_link_up);
- DP(NETIF_MSG_LINK, "line_speed %x duplex %x flow_ctrl 0x%x\n",
- vars->line_speed, vars->duplex, vars->flow_ctrl);
+ vars->mac_type = MAC_TYPE_BMAC;
+ return rc;
}
+
static void bnx2x_update_mng(struct link_params *params, u32 link_status)
{
struct bnx2x *bp = params->bp;
@@ -706,13 +657,25 @@ static void bnx2x_bmac_rx_disable(struct bnx2x *bp, u8 port)
(MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port) &&
nig_bmac_enable) {
- /* Clear Rx Enable bit in BMAC_CONTROL register */
- REG_RD_DMAE(bp, bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL,
- wb_data, 2);
- wb_data[0] &= ~BMAC_CONTROL_RX_ENABLE;
- REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL,
- wb_data, 2);
-
+ if (CHIP_IS_E2(bp)) {
+ /* Clear Rx Enable bit in BMAC_CONTROL register */
+ REG_RD_DMAE(bp, bmac_addr +
+ BIGMAC2_REGISTER_BMAC_CONTROL,
+ wb_data, 2);
+ wb_data[0] &= ~BMAC_CONTROL_RX_ENABLE;
+ REG_WR_DMAE(bp, bmac_addr +
+ BIGMAC2_REGISTER_BMAC_CONTROL,
+ wb_data, 2);
+ } else {
+ /* Clear Rx Enable bit in BMAC_CONTROL register */
+ REG_RD_DMAE(bp, bmac_addr +
+ BIGMAC_REGISTER_BMAC_CONTROL,
+ wb_data, 2);
+ wb_data[0] &= ~BMAC_CONTROL_RX_ENABLE;
+ REG_WR_DMAE(bp, bmac_addr +
+ BIGMAC_REGISTER_BMAC_CONTROL,
+ wb_data, 2);
+ }
msleep(1);
}
}
@@ -800,62 +763,69 @@ static u8 bnx2x_pbf_update(struct link_params *params, u32 flow_ctrl,
return 0;
}
-static u32 bnx2x_get_emac_base(struct bnx2x *bp, u32 ext_phy_type, u8 port)
+static u32 bnx2x_get_emac_base(struct bnx2x *bp,
+ u32 mdc_mdio_access, u8 port)
{
- u32 emac_base;
-
- switch (ext_phy_type) {
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
- /* All MDC/MDIO is directed through single EMAC */
+ u32 emac_base = 0;
+ switch (mdc_mdio_access) {
+ case SHARED_HW_CFG_MDC_MDIO_ACCESS1_PHY_TYPE:
+ break;
+ case SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC0:
+ if (REG_RD(bp, NIG_REG_PORT_SWAP))
+ emac_base = GRCBASE_EMAC1;
+ else
+ emac_base = GRCBASE_EMAC0;
+ break;
+ case SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC1:
if (REG_RD(bp, NIG_REG_PORT_SWAP))
emac_base = GRCBASE_EMAC0;
else
emac_base = GRCBASE_EMAC1;
break;
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
+ case SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH:
+ emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
+ break;
+ case SHARED_HW_CFG_MDC_MDIO_ACCESS1_SWAPPED:
emac_base = (port) ? GRCBASE_EMAC0 : GRCBASE_EMAC1;
break;
default:
- emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
break;
}
return emac_base;
}
-u8 bnx2x_cl45_write(struct bnx2x *bp, u8 port, u32 ext_phy_type,
- u8 phy_addr, u8 devad, u16 reg, u16 val)
+u8 bnx2x_cl45_write(struct bnx2x *bp, struct bnx2x_phy *phy,
+ u8 devad, u16 reg, u16 val)
{
u32 tmp, saved_mode;
u8 i, rc = 0;
- u32 mdio_ctrl = bnx2x_get_emac_base(bp, ext_phy_type, port);
/* set clause 45 mode, slow down the MDIO clock to 2.5MHz
* (a value of 49==0x31) and make sure that the AUTO poll is off
*/
- saved_mode = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
+ saved_mode = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
tmp = saved_mode & ~(EMAC_MDIO_MODE_AUTO_POLL |
EMAC_MDIO_MODE_CLOCK_CNT);
tmp |= (EMAC_MDIO_MODE_CLAUSE_45 |
(49 << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT));
- REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, tmp);
- REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
+ REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, tmp);
+ REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
udelay(40);
/* address */
- tmp = ((phy_addr << 21) | (devad << 16) | reg |
+ tmp = ((phy->addr << 21) | (devad << 16) | reg |
EMAC_MDIO_COMM_COMMAND_ADDRESS |
EMAC_MDIO_COMM_START_BUSY);
- REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
+ REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
for (i = 0; i < 50; i++) {
udelay(10);
- tmp = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
+ tmp = REG_RD(bp, phy->mdio_ctrl +
+ EMAC_REG_EMAC_MDIO_COMM);
if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
udelay(5);
break;
@@ -866,15 +836,15 @@ u8 bnx2x_cl45_write(struct bnx2x *bp, u8 port, u32 ext_phy_type,
rc = -EFAULT;
} else {
/* data */
- tmp = ((phy_addr << 21) | (devad << 16) | val |
+ tmp = ((phy->addr << 21) | (devad << 16) | val |
EMAC_MDIO_COMM_COMMAND_WRITE_45 |
EMAC_MDIO_COMM_START_BUSY);
- REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
+ REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
for (i = 0; i < 50; i++) {
udelay(10);
- tmp = REG_RD(bp, mdio_ctrl +
+ tmp = REG_RD(bp, phy->mdio_ctrl +
EMAC_REG_EMAC_MDIO_COMM);
if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
udelay(5);
@@ -888,42 +858,41 @@ u8 bnx2x_cl45_write(struct bnx2x *bp, u8 port, u32 ext_phy_type,
}
/* Restore the saved mode */
- REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, saved_mode);
+ REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, saved_mode);
return rc;
}
-u8 bnx2x_cl45_read(struct bnx2x *bp, u8 port, u32 ext_phy_type,
- u8 phy_addr, u8 devad, u16 reg, u16 *ret_val)
+u8 bnx2x_cl45_read(struct bnx2x *bp, struct bnx2x_phy *phy,
+ u8 devad, u16 reg, u16 *ret_val)
{
u32 val, saved_mode;
u16 i;
u8 rc = 0;
- u32 mdio_ctrl = bnx2x_get_emac_base(bp, ext_phy_type, port);
/* set clause 45 mode, slow down the MDIO clock to 2.5MHz
* (a value of 49==0x31) and make sure that the AUTO poll is off
*/
- saved_mode = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
- val = saved_mode & ((EMAC_MDIO_MODE_AUTO_POLL |
+ saved_mode = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
+ val = saved_mode & ~((EMAC_MDIO_MODE_AUTO_POLL |
EMAC_MDIO_MODE_CLOCK_CNT));
val |= (EMAC_MDIO_MODE_CLAUSE_45 |
(49L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT));
- REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, val);
- REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
+ REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, val);
+ REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
udelay(40);
/* address */
- val = ((phy_addr << 21) | (devad << 16) | reg |
+ val = ((phy->addr << 21) | (devad << 16) | reg |
EMAC_MDIO_COMM_COMMAND_ADDRESS |
EMAC_MDIO_COMM_START_BUSY);
- REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val);
+ REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val);
for (i = 0; i < 50; i++) {
udelay(10);
- val = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
+ val = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
if (!(val & EMAC_MDIO_COMM_START_BUSY)) {
udelay(5);
break;
@@ -937,15 +906,15 @@ u8 bnx2x_cl45_read(struct bnx2x *bp, u8 port, u32 ext_phy_type,
} else {
/* data */
- val = ((phy_addr << 21) | (devad << 16) |
+ val = ((phy->addr << 21) | (devad << 16) |
EMAC_MDIO_COMM_COMMAND_READ_45 |
EMAC_MDIO_COMM_START_BUSY);
- REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val);
+ REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val);
for (i = 0; i < 50; i++) {
udelay(10);
- val = REG_RD(bp, mdio_ctrl +
+ val = REG_RD(bp, phy->mdio_ctrl +
EMAC_REG_EMAC_MDIO_COMM);
if (!(val & EMAC_MDIO_COMM_START_BUSY)) {
*ret_val = (u16)(val & EMAC_MDIO_COMM_DATA);
@@ -961,32 +930,262 @@ u8 bnx2x_cl45_read(struct bnx2x *bp, u8 port, u32 ext_phy_type,
}
/* Restore the saved mode */
- REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, saved_mode);
+ REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, saved_mode);
return rc;
}
-static void bnx2x_set_aer_mmd(struct link_params *params,
- struct link_vars *vars)
+u8 bnx2x_phy_read(struct link_params *params, u8 phy_addr,
+ u8 devad, u16 reg, u16 *ret_val)
{
- struct bnx2x *bp = params->bp;
- u32 ser_lane;
- u16 offset;
+ u8 phy_index;
+ /**
+ * Probe for the phy according to the given phy_addr, and execute
+ * the read request on it
+ */
+ for (phy_index = 0; phy_index < params->num_phys; phy_index++) {
+ if (params->phy[phy_index].addr == phy_addr) {
+ return bnx2x_cl45_read(params->bp,
+ &params->phy[phy_index], devad,
+ reg, ret_val);
+ }
+ }
+ return -EINVAL;
+}
+u8 bnx2x_phy_write(struct link_params *params, u8 phy_addr,
+ u8 devad, u16 reg, u16 val)
+{
+ u8 phy_index;
+ /**
+ * Probe for the phy according to the given phy_addr, and execute
+ * the write request on it
+ */
+ for (phy_index = 0; phy_index < params->num_phys; phy_index++) {
+ if (params->phy[phy_index].addr == phy_addr) {
+ return bnx2x_cl45_write(params->bp,
+ &params->phy[phy_index], devad,
+ reg, val);
+ }
+ }
+ return -EINVAL;
+}
+
+static void bnx2x_set_aer_mmd_xgxs(struct link_params *params,
+ struct bnx2x_phy *phy)
+{
+ u32 ser_lane;
+ u16 offset, aer_val;
+ struct bnx2x *bp = params->bp;
ser_lane = ((params->lane_config &
PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
- offset = (vars->phy_flags & PHY_XGXS_FLAG) ?
- (params->phy_addr + ser_lane) : 0;
+ offset = phy->addr + ser_lane;
+ if (CHIP_IS_E2(bp))
+ aer_val = 0x2800 + offset - 1;
+ else
+ aer_val = 0x3800 + offset;
+ CL45_WR_OVER_CL22(bp, phy,
+ MDIO_REG_BANK_AER_BLOCK,
+ MDIO_AER_BLOCK_AER_REG, aer_val);
+}
+static void bnx2x_set_aer_mmd_serdes(struct bnx2x *bp,
+ struct bnx2x_phy *phy)
+{
+ CL45_WR_OVER_CL22(bp, phy,
+ MDIO_REG_BANK_AER_BLOCK,
+ MDIO_AER_BLOCK_AER_REG, 0x3800);
+}
- CL45_WR_OVER_CL22(bp, params->port,
- params->phy_addr,
- MDIO_REG_BANK_AER_BLOCK,
- MDIO_AER_BLOCK_AER_REG, 0x3800 + offset);
+/******************************************************************/
+/* Internal phy section */
+/******************************************************************/
+
+static void bnx2x_set_serdes_access(struct bnx2x *bp, u8 port)
+{
+ u32 emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
+
+ /* Set Clause 22 */
+ REG_WR(bp, NIG_REG_SERDES0_CTRL_MD_ST + port*0x10, 1);
+ REG_WR(bp, emac_base + EMAC_REG_EMAC_MDIO_COMM, 0x245f8000);
+ udelay(500);
+ REG_WR(bp, emac_base + EMAC_REG_EMAC_MDIO_COMM, 0x245d000f);
+ udelay(500);
+ /* Set Clause 45 */
+ REG_WR(bp, NIG_REG_SERDES0_CTRL_MD_ST + port*0x10, 0);
+}
+
+static void bnx2x_serdes_deassert(struct bnx2x *bp, u8 port)
+{
+ u32 val;
+
+ DP(NETIF_MSG_LINK, "bnx2x_serdes_deassert\n");
+
+ val = SERDES_RESET_BITS << (port*16);
+
+ /* reset and unreset the SerDes/XGXS */
+ REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR, val);
+ udelay(500);
+ REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET, val);
+
+ bnx2x_set_serdes_access(bp, port);
+
+ REG_WR(bp, NIG_REG_SERDES0_CTRL_MD_DEVAD +
+ port*0x10,
+ DEFAULT_PHY_DEV_ADDR);
}
-static void bnx2x_set_master_ln(struct link_params *params)
+static void bnx2x_xgxs_deassert(struct link_params *params)
+{
+ struct bnx2x *bp = params->bp;
+ u8 port;
+ u32 val;
+ DP(NETIF_MSG_LINK, "bnx2x_xgxs_deassert\n");
+ port = params->port;
+
+ val = XGXS_RESET_BITS << (port*16);
+
+ /* reset and unreset the SerDes/XGXS */
+ REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR, val);
+ udelay(500);
+ REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET, val);
+
+ REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST +
+ port*0x18, 0);
+ REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18,
+ params->phy[INT_PHY].def_md_devad);
+}
+
+
+void bnx2x_link_status_update(struct link_params *params,
+ struct link_vars *vars)
+{
+ struct bnx2x *bp = params->bp;
+ u8 link_10g;
+ u8 port = params->port;
+
+ vars->link_status = REG_RD(bp, params->shmem_base +
+ offsetof(struct shmem_region,
+ port_mb[port].link_status));
+
+ vars->link_up = (vars->link_status & LINK_STATUS_LINK_UP);
+
+ if (vars->link_up) {
+ DP(NETIF_MSG_LINK, "phy link up\n");
+
+ vars->phy_link_up = 1;
+ vars->duplex = DUPLEX_FULL;
+ switch (vars->link_status &
+ LINK_STATUS_SPEED_AND_DUPLEX_MASK) {
+ case LINK_10THD:
+ vars->duplex = DUPLEX_HALF;
+ /* fall thru */
+ case LINK_10TFD:
+ vars->line_speed = SPEED_10;
+ break;
+
+ case LINK_100TXHD:
+ vars->duplex = DUPLEX_HALF;
+ /* fall thru */
+ case LINK_100T4:
+ case LINK_100TXFD:
+ vars->line_speed = SPEED_100;
+ break;
+
+ case LINK_1000THD:
+ vars->duplex = DUPLEX_HALF;
+ /* fall thru */
+ case LINK_1000TFD:
+ vars->line_speed = SPEED_1000;
+ break;
+
+ case LINK_2500THD:
+ vars->duplex = DUPLEX_HALF;
+ /* fall thru */
+ case LINK_2500TFD:
+ vars->line_speed = SPEED_2500;
+ break;
+
+ case LINK_10GTFD:
+ vars->line_speed = SPEED_10000;
+ break;
+
+ case LINK_12GTFD:
+ vars->line_speed = SPEED_12000;
+ break;
+
+ case LINK_12_5GTFD:
+ vars->line_speed = SPEED_12500;
+ break;
+
+ case LINK_13GTFD:
+ vars->line_speed = SPEED_13000;
+ break;
+
+ case LINK_15GTFD:
+ vars->line_speed = SPEED_15000;
+ break;
+
+ case LINK_16GTFD:
+ vars->line_speed = SPEED_16000;
+ break;
+
+ default:
+ break;
+ }
+ vars->flow_ctrl = 0;
+ if (vars->link_status & LINK_STATUS_TX_FLOW_CONTROL_ENABLED)
+ vars->flow_ctrl |= BNX2X_FLOW_CTRL_TX;
+
+ if (vars->link_status & LINK_STATUS_RX_FLOW_CONTROL_ENABLED)
+ vars->flow_ctrl |= BNX2X_FLOW_CTRL_RX;
+
+ if (!vars->flow_ctrl)
+ vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
+
+ if (vars->line_speed &&
+ ((vars->line_speed == SPEED_10) ||
+ (vars->line_speed == SPEED_100))) {
+ vars->phy_flags |= PHY_SGMII_FLAG;
+ } else {
+ vars->phy_flags &= ~PHY_SGMII_FLAG;
+ }
+
+ /* anything 10 and over uses the bmac */
+ link_10g = ((vars->line_speed == SPEED_10000) ||
+ (vars->line_speed == SPEED_12000) ||
+ (vars->line_speed == SPEED_12500) ||
+ (vars->line_speed == SPEED_13000) ||
+ (vars->line_speed == SPEED_15000) ||
+ (vars->line_speed == SPEED_16000));
+ if (link_10g)
+ vars->mac_type = MAC_TYPE_BMAC;
+ else
+ vars->mac_type = MAC_TYPE_EMAC;
+
+ } else { /* link down */
+ DP(NETIF_MSG_LINK, "phy link down\n");
+
+ vars->phy_link_up = 0;
+
+ vars->line_speed = 0;
+ vars->duplex = DUPLEX_FULL;
+ vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
+
+ /* indicate no mac active */
+ vars->mac_type = MAC_TYPE_NONE;
+ }
+
+ DP(NETIF_MSG_LINK, "link_status 0x%x phy_link_up %x\n",
+ vars->link_status, vars->phy_link_up);
+ DP(NETIF_MSG_LINK, "line_speed %x duplex %x flow_ctrl 0x%x\n",
+ vars->line_speed, vars->duplex, vars->flow_ctrl);
+}
+
+
+static void bnx2x_set_master_ln(struct link_params *params,
+ struct bnx2x_phy *phy)
{
struct bnx2x *bp = params->bp;
u16 new_master_ln, ser_lane;
@@ -995,47 +1194,44 @@ static void bnx2x_set_master_ln(struct link_params *params)
PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
/* set the master_ln for AN */
- CL45_RD_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_RD_OVER_CL22(bp, phy,
MDIO_REG_BANK_XGXS_BLOCK2,
MDIO_XGXS_BLOCK2_TEST_MODE_LANE,
&new_master_ln);
- CL45_WR_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_WR_OVER_CL22(bp, phy,
MDIO_REG_BANK_XGXS_BLOCK2 ,
MDIO_XGXS_BLOCK2_TEST_MODE_LANE,
(new_master_ln | ser_lane));
}
-static u8 bnx2x_reset_unicore(struct link_params *params)
+static u8 bnx2x_reset_unicore(struct link_params *params,
+ struct bnx2x_phy *phy,
+ u8 set_serdes)
{
struct bnx2x *bp = params->bp;
u16 mii_control;
u16 i;
- CL45_RD_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_RD_OVER_CL22(bp, phy,
MDIO_REG_BANK_COMBO_IEEE0,
MDIO_COMBO_IEEE0_MII_CONTROL, &mii_control);
/* reset the unicore */
- CL45_WR_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_WR_OVER_CL22(bp, phy,
MDIO_REG_BANK_COMBO_IEEE0,
MDIO_COMBO_IEEE0_MII_CONTROL,
(mii_control |
MDIO_COMBO_IEEO_MII_CONTROL_RESET));
- if (params->switch_cfg == SWITCH_CFG_1G)
- bnx2x_set_serdes_access(params);
+ if (set_serdes)
+ bnx2x_set_serdes_access(bp, params->port);
/* wait for the reset to self clear */
for (i = 0; i < MDIO_ACCESS_TIMEOUT; i++) {
udelay(5);
/* the reset erased the previous bank value */
- CL45_RD_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_RD_OVER_CL22(bp, phy,
MDIO_REG_BANK_COMBO_IEEE0,
MDIO_COMBO_IEEE0_MII_CONTROL,
&mii_control);
@@ -1051,7 +1247,8 @@ static u8 bnx2x_reset_unicore(struct link_params *params)
}
-static void bnx2x_set_swap_lanes(struct link_params *params)
+static void bnx2x_set_swap_lanes(struct link_params *params,
+ struct bnx2x_phy *phy)
{
struct bnx2x *bp = params->bp;
/* Each two bits represents a lane number:
@@ -1069,71 +1266,62 @@ static void bnx2x_set_swap_lanes(struct link_params *params)
PORT_HW_CFG_LANE_SWAP_CFG_TX_SHIFT);
if (rx_lane_swap != 0x1b) {
- CL45_WR_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_WR_OVER_CL22(bp, phy,
MDIO_REG_BANK_XGXS_BLOCK2,
MDIO_XGXS_BLOCK2_RX_LN_SWAP,
(rx_lane_swap |
MDIO_XGXS_BLOCK2_RX_LN_SWAP_ENABLE |
MDIO_XGXS_BLOCK2_RX_LN_SWAP_FORCE_ENABLE));
} else {
- CL45_WR_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_WR_OVER_CL22(bp, phy,
MDIO_REG_BANK_XGXS_BLOCK2,
MDIO_XGXS_BLOCK2_RX_LN_SWAP, 0);
}
if (tx_lane_swap != 0x1b) {
- CL45_WR_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_WR_OVER_CL22(bp, phy,
MDIO_REG_BANK_XGXS_BLOCK2,
MDIO_XGXS_BLOCK2_TX_LN_SWAP,
(tx_lane_swap |
MDIO_XGXS_BLOCK2_TX_LN_SWAP_ENABLE));
} else {
- CL45_WR_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_WR_OVER_CL22(bp, phy,
MDIO_REG_BANK_XGXS_BLOCK2,
MDIO_XGXS_BLOCK2_TX_LN_SWAP, 0);
}
}
-static void bnx2x_set_parallel_detection(struct link_params *params,
- u8 phy_flags)
+static void bnx2x_set_parallel_detection(struct bnx2x_phy *phy,
+ struct link_params *params)
{
struct bnx2x *bp = params->bp;
u16 control2;
-
- CL45_RD_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_RD_OVER_CL22(bp, phy,
MDIO_REG_BANK_SERDES_DIGITAL,
MDIO_SERDES_DIGITAL_A_1000X_CONTROL2,
&control2);
- if (params->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)
+ if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)
control2 |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_PRL_DT_EN;
else
control2 &= ~MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_PRL_DT_EN;
- DP(NETIF_MSG_LINK, "params->speed_cap_mask = 0x%x, control2 = 0x%x\n",
- params->speed_cap_mask, control2);
- CL45_WR_OVER_CL22(bp, params->port,
- params->phy_addr,
+ DP(NETIF_MSG_LINK, "phy->speed_cap_mask = 0x%x, control2 = 0x%x\n",
+ phy->speed_cap_mask, control2);
+ CL45_WR_OVER_CL22(bp, phy,
MDIO_REG_BANK_SERDES_DIGITAL,
MDIO_SERDES_DIGITAL_A_1000X_CONTROL2,
control2);
- if ((phy_flags & PHY_XGXS_FLAG) &&
- (params->speed_cap_mask &
+ if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) &&
+ (phy->speed_cap_mask &
PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) {
DP(NETIF_MSG_LINK, "XGXS\n");
- CL45_WR_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_WR_OVER_CL22(bp, phy,
MDIO_REG_BANK_10G_PARALLEL_DETECT,
MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK,
MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK_CNT);
- CL45_RD_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_RD_OVER_CL22(bp, phy,
MDIO_REG_BANK_10G_PARALLEL_DETECT,
MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL,
&control2);
@@ -1142,15 +1330,13 @@ static void bnx2x_set_parallel_detection(struct link_params *params,
control2 |=
MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL_PARDET10G_EN;
- CL45_WR_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_WR_OVER_CL22(bp, phy,
MDIO_REG_BANK_10G_PARALLEL_DETECT,
MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL,
control2);
/* Disable parallel detection of HiG */
- CL45_WR_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_WR_OVER_CL22(bp, phy,
MDIO_REG_BANK_XGXS_BLOCK2,
MDIO_XGXS_BLOCK2_UNICORE_MODE_10G,
MDIO_XGXS_BLOCK2_UNICORE_MODE_10G_CX4_XGXS |
@@ -1158,7 +1344,8 @@ static void bnx2x_set_parallel_detection(struct link_params *params,
}
}
-static void bnx2x_set_autoneg(struct link_params *params,
+static void bnx2x_set_autoneg(struct bnx2x_phy *phy,
+ struct link_params *params,
struct link_vars *vars,
u8 enable_cl73)
{
@@ -1166,9 +1353,7 @@ static void bnx2x_set_autoneg(struct link_params *params,
u16 reg_val;
/* CL37 Autoneg */
-
- CL45_RD_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_RD_OVER_CL22(bp, phy,
MDIO_REG_BANK_COMBO_IEEE0,
MDIO_COMBO_IEEE0_MII_CONTROL, &reg_val);
@@ -1179,15 +1364,13 @@ static void bnx2x_set_autoneg(struct link_params *params,
reg_val &= ~(MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
MDIO_COMBO_IEEO_MII_CONTROL_RESTART_AN);
- CL45_WR_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_WR_OVER_CL22(bp, phy,
MDIO_REG_BANK_COMBO_IEEE0,
MDIO_COMBO_IEEE0_MII_CONTROL, reg_val);
/* Enable/Disable Autodetection */
- CL45_RD_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_RD_OVER_CL22(bp, phy,
MDIO_REG_BANK_SERDES_DIGITAL,
MDIO_SERDES_DIGITAL_A_1000X_CONTROL1, &reg_val);
reg_val &= ~(MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_SIGNAL_DETECT_EN |
@@ -1198,14 +1381,12 @@ static void bnx2x_set_autoneg(struct link_params *params,
else
reg_val &= ~MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET;
- CL45_WR_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_WR_OVER_CL22(bp, phy,
MDIO_REG_BANK_SERDES_DIGITAL,
MDIO_SERDES_DIGITAL_A_1000X_CONTROL1, reg_val);
/* Enable TetonII and BAM autoneg */
- CL45_RD_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_RD_OVER_CL22(bp, phy,
MDIO_REG_BANK_BAM_NEXT_PAGE,
MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL,
&reg_val);
@@ -1218,23 +1399,20 @@ static void bnx2x_set_autoneg(struct link_params *params,
reg_val &= ~(MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_BAM_MODE |
MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_TETON_AN);
}
- CL45_WR_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_WR_OVER_CL22(bp, phy,
MDIO_REG_BANK_BAM_NEXT_PAGE,
MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL,
reg_val);
if (enable_cl73) {
/* Enable Cl73 FSM status bits */
- CL45_WR_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_WR_OVER_CL22(bp, phy,
MDIO_REG_BANK_CL73_USERB0,
MDIO_CL73_USERB0_CL73_UCTRL,
0xe);
/* Enable BAM Station Manager*/
- CL45_WR_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_WR_OVER_CL22(bp, phy,
MDIO_REG_BANK_CL73_USERB0,
MDIO_CL73_USERB0_CL73_BAM_CTRL1,
MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_EN |
@@ -1242,20 +1420,18 @@ static void bnx2x_set_autoneg(struct link_params *params,
MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_NP_AFTER_BP_EN);
/* Advertise CL73 link speeds */
- CL45_RD_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_RD_OVER_CL22(bp, phy,
MDIO_REG_BANK_CL73_IEEEB1,
MDIO_CL73_IEEEB1_AN_ADV2,
&reg_val);
- if (params->speed_cap_mask &
+ if (phy->speed_cap_mask &
PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KX4;
- if (params->speed_cap_mask &
+ if (phy->speed_cap_mask &
PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)
reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_1000M_KX;
- CL45_WR_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_WR_OVER_CL22(bp, phy,
MDIO_REG_BANK_CL73_IEEEB1,
MDIO_CL73_IEEEB1_AN_ADV2,
reg_val);
@@ -1266,38 +1442,35 @@ static void bnx2x_set_autoneg(struct link_params *params,
} else /* CL73 Autoneg Disabled */
reg_val = 0;
- CL45_WR_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_WR_OVER_CL22(bp, phy,
MDIO_REG_BANK_CL73_IEEEB0,
MDIO_CL73_IEEEB0_CL73_AN_CONTROL, reg_val);
}
/* program SerDes, forced speed */
-static void bnx2x_program_serdes(struct link_params *params,
+static void bnx2x_program_serdes(struct bnx2x_phy *phy,
+ struct link_params *params,
struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
u16 reg_val;
/* program duplex, disable autoneg and sgmii*/
- CL45_RD_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_RD_OVER_CL22(bp, phy,
MDIO_REG_BANK_COMBO_IEEE0,
MDIO_COMBO_IEEE0_MII_CONTROL, &reg_val);
reg_val &= ~(MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX |
MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_MASK);
- if (params->req_duplex == DUPLEX_FULL)
+ if (phy->req_duplex == DUPLEX_FULL)
reg_val |= MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX;
- CL45_WR_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_WR_OVER_CL22(bp, phy,
MDIO_REG_BANK_COMBO_IEEE0,
MDIO_COMBO_IEEE0_MII_CONTROL, reg_val);
/* program speed
- needed only if the speed is greater than 1G (2.5G or 10G) */
- CL45_RD_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_RD_OVER_CL22(bp, phy,
MDIO_REG_BANK_SERDES_DIGITAL,
MDIO_SERDES_DIGITAL_MISC1, &reg_val);
/* clearing the speed value before setting the right speed */
@@ -1320,14 +1493,14 @@ static void bnx2x_program_serdes(struct link_params *params,
MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_13G;
}
- CL45_WR_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_WR_OVER_CL22(bp, phy,
MDIO_REG_BANK_SERDES_DIGITAL,
MDIO_SERDES_DIGITAL_MISC1, reg_val);
}
-static void bnx2x_set_brcm_cl37_advertisment(struct link_params *params)
+static void bnx2x_set_brcm_cl37_advertisment(struct bnx2x_phy *phy,
+ struct link_params *params)
{
struct bnx2x *bp = params->bp;
u16 val = 0;
@@ -1335,29 +1508,28 @@ static void bnx2x_set_brcm_cl37_advertisment(struct link_params *params)
/* configure the 48 bits for BAM AN */
/* set extended capabilities */
- if (params->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G)
+ if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G)
val |= MDIO_OVER_1G_UP1_2_5G;
- if (params->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
+ if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
val |= MDIO_OVER_1G_UP1_10G;
- CL45_WR_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_WR_OVER_CL22(bp, phy,
MDIO_REG_BANK_OVER_1G,
MDIO_OVER_1G_UP1, val);
- CL45_WR_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_WR_OVER_CL22(bp, phy,
MDIO_REG_BANK_OVER_1G,
MDIO_OVER_1G_UP3, 0x400);
}
-static void bnx2x_calc_ieee_aneg_adv(struct link_params *params, u16 *ieee_fc)
+static void bnx2x_calc_ieee_aneg_adv(struct bnx2x_phy *phy,
+ struct link_params *params, u16 *ieee_fc)
{
struct bnx2x *bp = params->bp;
*ieee_fc = MDIO_COMBO_IEEE0_AUTO_NEG_ADV_FULL_DUPLEX;
/* resolve pause mode and advertisement
* Please refer to Table 28B-3 of the 802.3ab-1999 spec */
- switch (params->req_flow_ctrl) {
+ switch (phy->req_flow_ctrl) {
case BNX2X_FLOW_CTRL_AUTO:
if (params->req_fc_auto_adv == BNX2X_FLOW_CTRL_BOTH) {
*ieee_fc |=
@@ -1385,30 +1557,30 @@ static void bnx2x_calc_ieee_aneg_adv(struct link_params *params, u16 *ieee_fc)
DP(NETIF_MSG_LINK, "ieee_fc = 0x%x\n", *ieee_fc);
}
-static void bnx2x_set_ieee_aneg_advertisment(struct link_params *params,
+static void bnx2x_set_ieee_aneg_advertisment(struct bnx2x_phy *phy,
+ struct link_params *params,
u16 ieee_fc)
{
struct bnx2x *bp = params->bp;
u16 val;
/* for AN, we are always publishing full duplex */
- CL45_WR_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_WR_OVER_CL22(bp, phy,
MDIO_REG_BANK_COMBO_IEEE0,
MDIO_COMBO_IEEE0_AUTO_NEG_ADV, ieee_fc);
- CL45_RD_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_RD_OVER_CL22(bp, phy,
MDIO_REG_BANK_CL73_IEEEB1,
MDIO_CL73_IEEEB1_AN_ADV1, &val);
val &= ~MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_BOTH;
val |= ((ieee_fc<<3) & MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_MASK);
- CL45_WR_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_WR_OVER_CL22(bp, phy,
MDIO_REG_BANK_CL73_IEEEB1,
MDIO_CL73_IEEEB1_AN_ADV1, val);
}
-static void bnx2x_restart_autoneg(struct link_params *params, u8 enable_cl73)
+static void bnx2x_restart_autoneg(struct bnx2x_phy *phy,
+ struct link_params *params,
+ u8 enable_cl73)
{
struct bnx2x *bp = params->bp;
u16 mii_control;
@@ -1417,14 +1589,12 @@ static void bnx2x_restart_autoneg(struct link_params *params, u8 enable_cl73)
/* Enable and restart BAM/CL37 aneg */
if (enable_cl73) {
- CL45_RD_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_RD_OVER_CL22(bp, phy,
MDIO_REG_BANK_CL73_IEEEB0,
MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
&mii_control);
- CL45_WR_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_WR_OVER_CL22(bp, phy,
MDIO_REG_BANK_CL73_IEEEB0,
MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
(mii_control |
@@ -1432,16 +1602,14 @@ static void bnx2x_restart_autoneg(struct link_params *params, u8 enable_cl73)
MDIO_CL73_IEEEB0_CL73_AN_CONTROL_RESTART_AN));
} else {
- CL45_RD_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_RD_OVER_CL22(bp, phy,
MDIO_REG_BANK_COMBO_IEEE0,
MDIO_COMBO_IEEE0_MII_CONTROL,
&mii_control);
DP(NETIF_MSG_LINK,
"bnx2x_restart_autoneg mii_control before = 0x%x\n",
mii_control);
- CL45_WR_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_WR_OVER_CL22(bp, phy,
MDIO_REG_BANK_COMBO_IEEE0,
MDIO_COMBO_IEEE0_MII_CONTROL,
(mii_control |
@@ -1450,7 +1618,8 @@ static void bnx2x_restart_autoneg(struct link_params *params, u8 enable_cl73)
}
}
-static void bnx2x_initialize_sgmii_process(struct link_params *params,
+static void bnx2x_initialize_sgmii_process(struct bnx2x_phy *phy,
+ struct link_params *params,
struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
@@ -1458,8 +1627,7 @@ static void bnx2x_initialize_sgmii_process(struct link_params *params,
/* in SGMII mode, the unicore is always slave */
- CL45_RD_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_RD_OVER_CL22(bp, phy,
MDIO_REG_BANK_SERDES_DIGITAL,
MDIO_SERDES_DIGITAL_A_1000X_CONTROL1,
&control1);
@@ -1468,8 +1636,7 @@ static void bnx2x_initialize_sgmii_process(struct link_params *params,
control1 &= ~(MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_FIBER_MODE |
MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET |
MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_MSTR_MODE);
- CL45_WR_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_WR_OVER_CL22(bp, phy,
MDIO_REG_BANK_SERDES_DIGITAL,
MDIO_SERDES_DIGITAL_A_1000X_CONTROL1,
control1);
@@ -1479,8 +1646,7 @@ static void bnx2x_initialize_sgmii_process(struct link_params *params,
/* set speed, disable autoneg */
u16 mii_control;
- CL45_RD_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_RD_OVER_CL22(bp, phy,
MDIO_REG_BANK_COMBO_IEEE0,
MDIO_COMBO_IEEE0_MII_CONTROL,
&mii_control);
@@ -1508,18 +1674,17 @@ static void bnx2x_initialize_sgmii_process(struct link_params *params,
}
/* setting the full duplex */
- if (params->req_duplex == DUPLEX_FULL)
+ if (phy->req_duplex == DUPLEX_FULL)
mii_control |=
MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX;
- CL45_WR_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_WR_OVER_CL22(bp, phy,
MDIO_REG_BANK_COMBO_IEEE0,
MDIO_COMBO_IEEE0_MII_CONTROL,
mii_control);
} else { /* AN mode */
/* enable and restart AN */
- bnx2x_restart_autoneg(params, 0);
+ bnx2x_restart_autoneg(phy, params, 0);
}
}
@@ -1549,91 +1714,24 @@ static void bnx2x_pause_resolve(struct link_vars *vars, u32 pause_result)
default:
break;
}
+ if (pause_result & (1<<0))
+ vars->link_status |= LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE;
+ if (pause_result & (1<<1))
+ vars->link_status |= LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE;
}
-static u8 bnx2x_ext_phy_resolve_fc(struct link_params *params,
- struct link_vars *vars)
-{
- struct bnx2x *bp = params->bp;
- u8 ext_phy_addr;
- u16 ld_pause; /* local */
- u16 lp_pause; /* link partner */
- u16 an_complete; /* AN complete */
- u16 pause_result;
- u8 ret = 0;
- u32 ext_phy_type;
- u8 port = params->port;
- ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
- ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
- /* read twice */
-
- bnx2x_cl45_read(bp, port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_STATUS, &an_complete);
- bnx2x_cl45_read(bp, port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_STATUS, &an_complete);
-
- if (an_complete & MDIO_AN_REG_STATUS_AN_COMPLETE) {
- ret = 1;
- bnx2x_cl45_read(bp, port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_ADV_PAUSE, &ld_pause);
- bnx2x_cl45_read(bp, port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_LP_AUTO_NEG, &lp_pause);
- pause_result = (ld_pause &
- MDIO_AN_REG_ADV_PAUSE_MASK) >> 8;
- pause_result |= (lp_pause &
- MDIO_AN_REG_ADV_PAUSE_MASK) >> 10;
- DP(NETIF_MSG_LINK, "Ext PHY pause result 0x%x\n",
- pause_result);
- bnx2x_pause_resolve(vars, pause_result);
- if (vars->flow_ctrl == BNX2X_FLOW_CTRL_NONE &&
- ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
- bnx2x_cl45_read(bp, port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_CL37_FC_LD, &ld_pause);
-
- bnx2x_cl45_read(bp, port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_CL37_FC_LP, &lp_pause);
- pause_result = (ld_pause &
- MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 5;
- pause_result |= (lp_pause &
- MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 7;
-
- bnx2x_pause_resolve(vars, pause_result);
- DP(NETIF_MSG_LINK, "Ext PHY CL37 pause result 0x%x\n",
- pause_result);
- }
- }
- return ret;
-}
-
-static u8 bnx2x_direct_parallel_detect_used(struct link_params *params)
+static u8 bnx2x_direct_parallel_detect_used(struct bnx2x_phy *phy,
+ struct link_params *params)
{
struct bnx2x *bp = params->bp;
u16 pd_10g, status2_1000x;
- CL45_RD_OVER_CL22(bp, params->port,
- params->phy_addr,
+ if (phy->req_line_speed != SPEED_AUTO_NEG)
+ return 0;
+ CL45_RD_OVER_CL22(bp, phy,
MDIO_REG_BANK_SERDES_DIGITAL,
MDIO_SERDES_DIGITAL_A_1000X_STATUS2,
&status2_1000x);
- CL45_RD_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_RD_OVER_CL22(bp, phy,
MDIO_REG_BANK_SERDES_DIGITAL,
MDIO_SERDES_DIGITAL_A_1000X_STATUS2,
&status2_1000x);
@@ -1643,8 +1741,7 @@ static u8 bnx2x_direct_parallel_detect_used(struct link_params *params)
return 1;
}
- CL45_RD_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_RD_OVER_CL22(bp, phy,
MDIO_REG_BANK_10G_PARALLEL_DETECT,
MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_STATUS,
&pd_10g);
@@ -1657,9 +1754,10 @@ static u8 bnx2x_direct_parallel_detect_used(struct link_params *params)
return 0;
}
-static void bnx2x_flow_ctrl_resolve(struct link_params *params,
- struct link_vars *vars,
- u32 gp_status)
+static void bnx2x_flow_ctrl_resolve(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars,
+ u32 gp_status)
{
struct bnx2x *bp = params->bp;
u16 ld_pause; /* local driver */
@@ -1669,12 +1767,13 @@ static void bnx2x_flow_ctrl_resolve(struct link_params *params,
vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
/* resolve from gp_status in case of AN complete and not sgmii */
- if ((params->req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO) &&
- (gp_status & MDIO_AN_CL73_OR_37_COMPLETE) &&
- (!(vars->phy_flags & PHY_SGMII_FLAG)) &&
- (XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT)) {
- if (bnx2x_direct_parallel_detect_used(params)) {
+ if (phy->req_flow_ctrl != BNX2X_FLOW_CTRL_AUTO)
+ vars->flow_ctrl = phy->req_flow_ctrl;
+ else if (phy->req_line_speed != SPEED_AUTO_NEG)
+ vars->flow_ctrl = params->req_fc_auto_adv;
+ else if ((gp_status & MDIO_AN_CL73_OR_37_COMPLETE) &&
+ (!(vars->phy_flags & PHY_SGMII_FLAG))) {
+ if (bnx2x_direct_parallel_detect_used(phy, params)) {
vars->flow_ctrl = params->req_fc_auto_adv;
return;
}
@@ -1684,13 +1783,11 @@ static void bnx2x_flow_ctrl_resolve(struct link_params *params,
(MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE |
MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_MR_LP_NP_AN_ABLE)) {
- CL45_RD_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_RD_OVER_CL22(bp, phy,
MDIO_REG_BANK_CL73_IEEEB1,
MDIO_CL73_IEEEB1_AN_ADV1,
&ld_pause);
- CL45_RD_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_RD_OVER_CL22(bp, phy,
MDIO_REG_BANK_CL73_IEEEB1,
MDIO_CL73_IEEEB1_AN_LP_ADV1,
&lp_pause);
@@ -1703,14 +1800,11 @@ static void bnx2x_flow_ctrl_resolve(struct link_params *params,
DP(NETIF_MSG_LINK, "pause_result CL73 0x%x\n",
pause_result);
} else {
-
- CL45_RD_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_RD_OVER_CL22(bp, phy,
MDIO_REG_BANK_COMBO_IEEE0,
MDIO_COMBO_IEEE0_AUTO_NEG_ADV,
&ld_pause);
- CL45_RD_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_RD_OVER_CL22(bp, phy,
MDIO_REG_BANK_COMBO_IEEE0,
MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1,
&lp_pause);
@@ -1722,26 +1816,18 @@ static void bnx2x_flow_ctrl_resolve(struct link_params *params,
pause_result);
}
bnx2x_pause_resolve(vars, pause_result);
- } else if ((params->req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO) &&
- (bnx2x_ext_phy_resolve_fc(params, vars))) {
- return;
- } else {
- if (params->req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO)
- vars->flow_ctrl = params->req_fc_auto_adv;
- else
- vars->flow_ctrl = params->req_flow_ctrl;
}
DP(NETIF_MSG_LINK, "flow_ctrl 0x%x\n", vars->flow_ctrl);
}
-static void bnx2x_check_fallback_to_cl37(struct link_params *params)
+static void bnx2x_check_fallback_to_cl37(struct bnx2x_phy *phy,
+ struct link_params *params)
{
struct bnx2x *bp = params->bp;
u16 rx_status, ustat_val, cl37_fsm_recieved;
DP(NETIF_MSG_LINK, "bnx2x_check_fallback_to_cl37\n");
/* Step 1: Make sure signal is detected */
- CL45_RD_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_RD_OVER_CL22(bp, phy,
MDIO_REG_BANK_RX0,
MDIO_RX0_RX_STATUS,
&rx_status);
@@ -1749,16 +1835,14 @@ static void bnx2x_check_fallback_to_cl37(struct link_params *params)
(MDIO_RX0_RX_STATUS_SIGDET)) {
DP(NETIF_MSG_LINK, "Signal is not detected. Restoring CL73."
"rx_status(0x80b0) = 0x%x\n", rx_status);
- CL45_WR_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_WR_OVER_CL22(bp, phy,
MDIO_REG_BANK_CL73_IEEEB0,
MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN);
return;
}
/* Step 2: Check CL73 state machine */
- CL45_RD_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_RD_OVER_CL22(bp, phy,
MDIO_REG_BANK_CL73_USERB0,
MDIO_CL73_USERB0_CL73_USTAT1,
&ustat_val);
@@ -1773,8 +1857,7 @@ static void bnx2x_check_fallback_to_cl37(struct link_params *params)
}
/* Step 3: Check CL37 Message Pages received to indicate LP
supports only CL37 */
- CL45_RD_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_RD_OVER_CL22(bp, phy,
MDIO_REG_BANK_REMOTE_PHY,
MDIO_REMOTE_PHY_MISC_RX_STATUS,
&cl37_fsm_recieved);
@@ -1792,25 +1875,45 @@ static void bnx2x_check_fallback_to_cl37(struct link_params *params)
connected to a device which does not support cl73, but does support
cl37 BAM. In this case we disable cl73 and restart cl37 auto-neg */
/* Disable CL73 */
- CL45_WR_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_WR_OVER_CL22(bp, phy,
MDIO_REG_BANK_CL73_IEEEB0,
MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
0);
/* Restart CL37 autoneg */
- bnx2x_restart_autoneg(params, 0);
+ bnx2x_restart_autoneg(phy, params, 0);
DP(NETIF_MSG_LINK, "Disabling CL73, and restarting CL37 autoneg\n");
}
-static u8 bnx2x_link_settings_status(struct link_params *params,
- struct link_vars *vars,
- u32 gp_status,
- u8 ext_phy_link_up)
+
+static void bnx2x_xgxs_an_resolve(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars,
+ u32 gp_status)
+{
+ if (gp_status & MDIO_AN_CL73_OR_37_COMPLETE)
+ vars->link_status |=
+ LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
+
+ if (bnx2x_direct_parallel_detect_used(phy, params))
+ vars->link_status |=
+ LINK_STATUS_PARALLEL_DETECTION_USED;
+}
+
+static u8 bnx2x_link_settings_status(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
- u16 new_line_speed;
+ u16 new_line_speed , gp_status;
u8 rc = 0;
- vars->link_status = 0;
+ /* Read gp_status */
+ CL45_RD_OVER_CL22(bp, phy,
+ MDIO_REG_BANK_GP_STATUS,
+ MDIO_GP_STATUS_TOP_AN_STATUS1,
+ &gp_status);
+
+ if (phy->req_line_speed == SPEED_AUTO_NEG)
+ vars->link_status |= LINK_STATUS_AUTO_NEGOTIATE_ENABLED;
if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) {
DP(NETIF_MSG_LINK, "phy link up gp_status=0x%x\n",
gp_status);
@@ -1823,7 +1926,12 @@ static u8 bnx2x_link_settings_status(struct link_params *params,
else
vars->duplex = DUPLEX_HALF;
- bnx2x_flow_ctrl_resolve(params, vars, gp_status);
+ if (SINGLE_MEDIA_DIRECT(params)) {
+ bnx2x_flow_ctrl_resolve(phy, params, vars, gp_status);
+ if (phy->req_line_speed == SPEED_AUTO_NEG)
+ bnx2x_xgxs_an_resolve(phy, params, vars,
+ gp_status);
+ }
switch (gp_status & GP_STATUS_SPEED_MASK) {
case GP_STATUS_10M:
@@ -1905,56 +2013,7 @@ static u8 bnx2x_link_settings_status(struct link_params *params,
return -EINVAL;
}
- /* Upon link speed change set the NIG into drain mode.
- Comes to deals with possible FIFO glitch due to clk change
- when speed is decreased without link down indicator */
- if (new_line_speed != vars->line_speed) {
- if (XGXS_EXT_PHY_TYPE(params->ext_phy_config) !=
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT &&
- ext_phy_link_up) {
- DP(NETIF_MSG_LINK, "Internal link speed %d is"
- " different than the external"
- " link speed %d\n", new_line_speed,
- vars->line_speed);
- vars->phy_link_up = 0;
- return 0;
- }
- REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE
- + params->port*4, 0);
- msleep(1);
- }
vars->line_speed = new_line_speed;
- vars->link_status |= LINK_STATUS_SERDES_LINK;
-
- if ((params->req_line_speed == SPEED_AUTO_NEG) &&
- ((XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) ||
- (XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705) ||
- (XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706) ||
- (XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726))) {
- vars->autoneg = AUTO_NEG_ENABLED;
-
- if (gp_status & MDIO_AN_CL73_OR_37_COMPLETE) {
- vars->autoneg |= AUTO_NEG_COMPLETE;
- vars->link_status |=
- LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
- }
-
- vars->autoneg |= AUTO_NEG_PARALLEL_DETECTION_USED;
- vars->link_status |=
- LINK_STATUS_PARALLEL_DETECTION_USED;
-
- }
- if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
- vars->link_status |=
- LINK_STATUS_TX_FLOW_CONTROL_ENABLED;
-
- if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
- vars->link_status |=
- LINK_STATUS_RX_FLOW_CONTROL_ENABLED;
} else { /* link_down */
DP(NETIF_MSG_LINK, "phy link down\n");
@@ -1963,38 +2022,32 @@ static u8 bnx2x_link_settings_status(struct link_params *params,
vars->duplex = DUPLEX_FULL;
vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
- vars->autoneg = AUTO_NEG_DISABLED;
vars->mac_type = MAC_TYPE_NONE;
- if ((params->req_line_speed == SPEED_AUTO_NEG) &&
- ((XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT))) {
+ if ((phy->req_line_speed == SPEED_AUTO_NEG) &&
+ SINGLE_MEDIA_DIRECT(params)) {
/* Check signal is detected */
- bnx2x_check_fallback_to_cl37(params);
+ bnx2x_check_fallback_to_cl37(phy, params);
}
}
DP(NETIF_MSG_LINK, "gp_status 0x%x phy_link_up %x line_speed %x\n",
gp_status, vars->phy_link_up, vars->line_speed);
- DP(NETIF_MSG_LINK, "duplex %x flow_ctrl 0x%x"
- " autoneg 0x%x\n",
- vars->duplex,
- vars->flow_ctrl, vars->autoneg);
- DP(NETIF_MSG_LINK, "link_status 0x%x\n", vars->link_status);
-
+ DP(NETIF_MSG_LINK, "duplex %x flow_ctrl 0x%x link_status 0x%x\n",
+ vars->duplex, vars->flow_ctrl, vars->link_status);
return rc;
}
static void bnx2x_set_gmii_tx_driver(struct link_params *params)
{
struct bnx2x *bp = params->bp;
+ struct bnx2x_phy *phy = &params->phy[INT_PHY];
u16 lp_up2;
u16 tx_driver;
u16 bank;
/* read precomp */
- CL45_RD_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_RD_OVER_CL22(bp, phy,
MDIO_REG_BANK_OVER_1G,
MDIO_OVER_1G_LP_UP2, &lp_up2);
@@ -2008,8 +2061,7 @@ static void bnx2x_set_gmii_tx_driver(struct link_params *params)
for (bank = MDIO_REG_BANK_TX0; bank <= MDIO_REG_BANK_TX3;
bank += (MDIO_REG_BANK_TX1 - MDIO_REG_BANK_TX0)) {
- CL45_RD_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_RD_OVER_CL22(bp, phy,
bank,
MDIO_TX0_TX_DRIVER, &tx_driver);
@@ -2018,8 +2070,7 @@ static void bnx2x_set_gmii_tx_driver(struct link_params *params)
(tx_driver & MDIO_TX0_TX_DRIVER_PREEMPHASIS_MASK)) {
tx_driver &= ~MDIO_TX0_TX_DRIVER_PREEMPHASIS_MASK;
tx_driver |= lp_up2;
- CL45_WR_OVER_CL22(bp, params->port,
- params->phy_addr,
+ CL45_WR_OVER_CL22(bp, phy,
bank,
MDIO_TX0_TX_DRIVER, tx_driver);
}
@@ -2027,7 +2078,7 @@ static void bnx2x_set_gmii_tx_driver(struct link_params *params)
}
static u8 bnx2x_emac_program(struct link_params *params,
- u32 line_speed, u32 duplex)
+ struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
u8 port = params->port;
@@ -2039,7 +2090,7 @@ static u8 bnx2x_emac_program(struct link_params *params,
(EMAC_MODE_25G_MODE |
EMAC_MODE_PORT_MII_10M |
EMAC_MODE_HALF_DUPLEX));
- switch (line_speed) {
+ switch (vars->line_speed) {
case SPEED_10:
mode |= EMAC_MODE_PORT_MII_10M;
break;
@@ -2058,371 +2109,1373 @@ static u8 bnx2x_emac_program(struct link_params *params,
default:
/* 10G not valid for EMAC */
- DP(NETIF_MSG_LINK, "Invalid line_speed 0x%x\n", line_speed);
+ DP(NETIF_MSG_LINK, "Invalid line_speed 0x%x\n",
+ vars->line_speed);
return -EINVAL;
}
- if (duplex == DUPLEX_HALF)
+ if (vars->duplex == DUPLEX_HALF)
mode |= EMAC_MODE_HALF_DUPLEX;
bnx2x_bits_en(bp,
GRCBASE_EMAC0 + port*0x400 + EMAC_REG_EMAC_MODE,
mode);
- bnx2x_set_led(params, LED_MODE_OPER, line_speed);
+ bnx2x_set_led(params, vars, LED_MODE_OPER, vars->line_speed);
return 0;
}
-/*****************************************************************************/
-/* External Phy section */
-/*****************************************************************************/
-void bnx2x_ext_phy_hw_reset(struct bnx2x *bp, u8 port)
+static void bnx2x_set_preemphasis(struct bnx2x_phy *phy,
+ struct link_params *params)
{
- bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
- MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
- msleep(1);
- bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
- MISC_REGISTERS_GPIO_OUTPUT_HIGH, port);
+
+ u16 bank, i = 0;
+ struct bnx2x *bp = params->bp;
+
+ for (bank = MDIO_REG_BANK_RX0, i = 0; bank <= MDIO_REG_BANK_RX3;
+ bank += (MDIO_REG_BANK_RX1-MDIO_REG_BANK_RX0), i++) {
+ CL45_WR_OVER_CL22(bp, phy,
+ bank,
+ MDIO_RX0_RX_EQ_BOOST,
+ phy->rx_preemphasis[i]);
+ }
+
+ for (bank = MDIO_REG_BANK_TX0, i = 0; bank <= MDIO_REG_BANK_TX3;
+ bank += (MDIO_REG_BANK_TX1 - MDIO_REG_BANK_TX0), i++) {
+ CL45_WR_OVER_CL22(bp, phy,
+ bank,
+ MDIO_TX0_TX_DRIVER,
+ phy->tx_preemphasis[i]);
+ }
}
-static void bnx2x_ext_phy_reset(struct link_params *params,
- struct link_vars *vars)
+static void bnx2x_init_internal_phy(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
- u32 ext_phy_type;
- u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
+ u8 enable_cl73 = (SINGLE_MEDIA_DIRECT(params) ||
+ (params->loopback_mode == LOOPBACK_XGXS));
+ if (!(vars->phy_flags & PHY_SGMII_FLAG)) {
+ if (SINGLE_MEDIA_DIRECT(params) &&
+ (params->feature_config_flags &
+ FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED))
+ bnx2x_set_preemphasis(phy, params);
- DP(NETIF_MSG_LINK, "Port %x: bnx2x_ext_phy_reset\n", params->port);
- ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
- /* The PHY reset is controled by GPIO 1
- * Give it 1ms of reset pulse
- */
- if (vars->phy_flags & PHY_XGXS_FLAG) {
+ /* forced speed requested? */
+ if (vars->line_speed != SPEED_AUTO_NEG ||
+ (SINGLE_MEDIA_DIRECT(params) &&
+ params->loopback_mode == LOOPBACK_EXT)) {
+ DP(NETIF_MSG_LINK, "not SGMII, no AN\n");
- switch (ext_phy_type) {
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
- DP(NETIF_MSG_LINK, "XGXS Direct\n");
- break;
+ /* disable autoneg */
+ bnx2x_set_autoneg(phy, params, vars, 0);
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
- DP(NETIF_MSG_LINK, "XGXS 8705/8706\n");
+ /* program speed and duplex */
+ bnx2x_program_serdes(phy, params, vars);
- /* Restore normal power mode*/
- bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
- MISC_REGISTERS_GPIO_OUTPUT_HIGH,
- params->port);
+ } else { /* AN_mode */
+ DP(NETIF_MSG_LINK, "not SGMII, AN\n");
- /* HW reset */
- bnx2x_ext_phy_hw_reset(bp, params->port);
+ /* AN enabled */
+ bnx2x_set_brcm_cl37_advertisment(phy, params);
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_CTRL, 0xa040);
- break;
+ /* program duplex & pause advertisement (for aneg) */
+ bnx2x_set_ieee_aneg_advertisment(phy, params,
+ vars->ieee_fc);
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
- break;
+ /* enable autoneg */
+ bnx2x_set_autoneg(phy, params, vars, enable_cl73);
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
+ /* enable and restart AN */
+ bnx2x_restart_autoneg(phy, params, enable_cl73);
+ }
- /* Restore normal power mode*/
- bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
- MISC_REGISTERS_GPIO_OUTPUT_HIGH,
- params->port);
+ } else { /* SGMII mode */
+ DP(NETIF_MSG_LINK, "SGMII\n");
- bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
- MISC_REGISTERS_GPIO_OUTPUT_HIGH,
- params->port);
+ bnx2x_initialize_sgmii_process(phy, params, vars);
+ }
+}
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_CTRL,
- 1<<15);
- break;
+static u8 bnx2x_init_serdes(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
+{
+ u8 rc;
+ vars->phy_flags |= PHY_SGMII_FLAG;
+ bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
+ bnx2x_set_aer_mmd_serdes(params->bp, phy);
+ rc = bnx2x_reset_unicore(params, phy, 1);
+ /* reset the SerDes and wait for reset bit return low */
+ if (rc != 0)
+ return rc;
+ bnx2x_set_aer_mmd_serdes(params->bp, phy);
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
- DP(NETIF_MSG_LINK, "XGXS 8072\n");
+ return rc;
+}
- /* Unset Low Power Mode and SW reset */
- /* Restore normal power mode*/
- bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
- MISC_REGISTERS_GPIO_OUTPUT_HIGH,
- params->port);
+static u8 bnx2x_init_xgxs(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
+{
+ u8 rc;
+ vars->phy_flags = PHY_XGXS_FLAG;
+ if ((phy->req_line_speed &&
+ ((phy->req_line_speed == SPEED_100) ||
+ (phy->req_line_speed == SPEED_10))) ||
+ (!phy->req_line_speed &&
+ (phy->speed_cap_mask >=
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL) &&
+ (phy->speed_cap_mask <
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)
+ ))
+ vars->phy_flags |= PHY_SGMII_FLAG;
+ else
+ vars->phy_flags &= ~PHY_SGMII_FLAG;
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_CTRL,
- 1<<15);
- break;
+ bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
+ bnx2x_set_aer_mmd_xgxs(params, phy);
+ bnx2x_set_master_ln(params, phy);
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
- DP(NETIF_MSG_LINK, "XGXS 8073\n");
+ rc = bnx2x_reset_unicore(params, phy, 0);
+ /* reset the SerDes and wait for reset bit return low */
+ if (rc != 0)
+ return rc;
- /* Restore normal power mode*/
- bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
- MISC_REGISTERS_GPIO_OUTPUT_HIGH,
- params->port);
+ bnx2x_set_aer_mmd_xgxs(params, phy);
- bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
- MISC_REGISTERS_GPIO_OUTPUT_HIGH,
- params->port);
+ /* setting the masterLn_def again after the reset */
+ bnx2x_set_master_ln(params, phy);
+ bnx2x_set_swap_lanes(params, phy);
+
+ return rc;
+}
+
+static u16 bnx2x_wait_reset_complete(struct bnx2x *bp,
+ struct bnx2x_phy *phy)
+{
+ u16 cnt, ctrl;
+ /* Wait for soft reset to get cleared upto 1 sec */
+ for (cnt = 0; cnt < 1000; cnt++) {
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, &ctrl);
+ if (!(ctrl & (1<<15)))
break;
+ msleep(1);
+ }
+ DP(NETIF_MSG_LINK, "control reg 0x%x (after %d ms)\n", ctrl, cnt);
+ return cnt;
+}
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
- DP(NETIF_MSG_LINK, "XGXS SFX7101\n");
+static void bnx2x_link_int_enable(struct link_params *params)
+{
+ u8 port = params->port;
+ u32 mask;
+ struct bnx2x *bp = params->bp;
- /* Restore normal power mode*/
- bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
- MISC_REGISTERS_GPIO_OUTPUT_HIGH,
- params->port);
+ /* setting the status to report on link up
+ for either XGXS or SerDes */
- /* HW reset */
- bnx2x_ext_phy_hw_reset(bp, params->port);
- break;
+ if (params->switch_cfg == SWITCH_CFG_10G) {
+ mask = (NIG_MASK_XGXS0_LINK10G |
+ NIG_MASK_XGXS0_LINK_STATUS);
+ DP(NETIF_MSG_LINK, "enabled XGXS interrupt\n");
+ if (!(SINGLE_MEDIA_DIRECT(params)) &&
+ params->phy[INT_PHY].type !=
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE) {
+ mask |= NIG_MASK_MI_INT;
+ DP(NETIF_MSG_LINK, "enabled external phy int\n");
+ }
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481:
- /* Restore normal power mode*/
- bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
- MISC_REGISTERS_GPIO_OUTPUT_HIGH,
- params->port);
+ } else { /* SerDes */
+ mask = NIG_MASK_SERDES0_LINK_STATUS;
+ DP(NETIF_MSG_LINK, "enabled SerDes interrupt\n");
+ if (!(SINGLE_MEDIA_DIRECT(params)) &&
+ params->phy[INT_PHY].type !=
+ PORT_HW_CFG_SERDES_EXT_PHY_TYPE_NOT_CONN) {
+ mask |= NIG_MASK_MI_INT;
+ DP(NETIF_MSG_LINK, "enabled external phy int\n");
+ }
+ }
+ bnx2x_bits_en(bp,
+ NIG_REG_MASK_INTERRUPT_PORT0 + port*4,
+ mask);
+
+ DP(NETIF_MSG_LINK, "port %x, is_xgxs %x, int_status 0x%x\n", port,
+ (params->switch_cfg == SWITCH_CFG_10G),
+ REG_RD(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4));
+ DP(NETIF_MSG_LINK, " int_mask 0x%x, MI_INT %x, SERDES_LINK %x\n",
+ REG_RD(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4),
+ REG_RD(bp, NIG_REG_EMAC0_STATUS_MISC_MI_INT + port*0x18),
+ REG_RD(bp, NIG_REG_SERDES0_STATUS_LINK_STATUS+port*0x3c));
+ DP(NETIF_MSG_LINK, " 10G %x, XGXS_LINK %x\n",
+ REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK10G + port*0x68),
+ REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68));
+}
- /* HW reset */
- bnx2x_ext_phy_hw_reset(bp, params->port);
+static void bnx2x_rearm_latch_signal(struct bnx2x *bp, u8 port,
+ u8 exp_mi_int)
+{
+ u32 latch_status = 0;
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_CTRL,
- 1<<15);
- break;
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823:
- break;
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
- DP(NETIF_MSG_LINK, "XGXS PHY Failure detected\n");
- break;
+ /**
+ * Disable the MI INT ( external phy int ) by writing 1 to the
+ * status register. Link down indication is high-active-signal,
+ * so in this case we need to write the status to clear the XOR
+ */
+ /* Read Latched signals */
+ latch_status = REG_RD(bp,
+ NIG_REG_LATCH_STATUS_0 + port*8);
+ DP(NETIF_MSG_LINK, "latch_status = 0x%x\n", latch_status);
+ /* Handle only those with latched-signal=up.*/
+ if (exp_mi_int)
+ bnx2x_bits_en(bp,
+ NIG_REG_STATUS_INTERRUPT_PORT0
+ + port*4,
+ NIG_STATUS_EMAC0_MI_INT);
+ else
+ bnx2x_bits_dis(bp,
+ NIG_REG_STATUS_INTERRUPT_PORT0
+ + port*4,
+ NIG_STATUS_EMAC0_MI_INT);
- default:
- DP(NETIF_MSG_LINK, "BAD XGXS ext_phy_config 0x%x\n",
- params->ext_phy_config);
- break;
+ if (latch_status & 1) {
+
+ /* For all latched-signal=up : Re-Arm Latch signals */
+ REG_WR(bp, NIG_REG_LATCH_STATUS_0 + port*8,
+ (latch_status & 0xfffe) | (latch_status & 1));
+ }
+ /* For all latched-signal=up,Write original_signal to status */
+}
+
+static void bnx2x_link_int_ack(struct link_params *params,
+ struct link_vars *vars, u8 is_10g)
+{
+ struct bnx2x *bp = params->bp;
+ u8 port = params->port;
+
+ /* first reset all status
+ * we assume only one line will be change at a time */
+ bnx2x_bits_dis(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
+ (NIG_STATUS_XGXS0_LINK10G |
+ NIG_STATUS_XGXS0_LINK_STATUS |
+ NIG_STATUS_SERDES0_LINK_STATUS));
+ if (vars->phy_link_up) {
+ if (is_10g) {
+ /* Disable the 10G link interrupt
+ * by writing 1 to the status register
+ */
+ DP(NETIF_MSG_LINK, "10G XGXS phy link up\n");
+ bnx2x_bits_en(bp,
+ NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
+ NIG_STATUS_XGXS0_LINK10G);
+
+ } else if (params->switch_cfg == SWITCH_CFG_10G) {
+ /* Disable the link interrupt
+ * by writing 1 to the relevant lane
+ * in the status register
+ */
+ u32 ser_lane = ((params->lane_config &
+ PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
+ PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
+
+ DP(NETIF_MSG_LINK, "%d speed XGXS phy link up\n",
+ vars->line_speed);
+ bnx2x_bits_en(bp,
+ NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
+ ((1 << ser_lane) <<
+ NIG_STATUS_XGXS0_LINK_STATUS_SIZE));
+
+ } else { /* SerDes */
+ DP(NETIF_MSG_LINK, "SerDes phy link up\n");
+ /* Disable the link interrupt
+ * by writing 1 to the status register
+ */
+ bnx2x_bits_en(bp,
+ NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
+ NIG_STATUS_SERDES0_LINK_STATUS);
}
- } else { /* SerDes */
- ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
- switch (ext_phy_type) {
- case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT:
- DP(NETIF_MSG_LINK, "SerDes Direct\n");
- break;
+ }
+}
+
+static u8 bnx2x_format_ver(u32 num, u8 *str, u16 *len)
+{
+ u8 *str_ptr = str;
+ u32 mask = 0xf0000000;
+ u8 shift = 8*4;
+ u8 digit;
+ u8 remove_leading_zeros = 1;
+ if (*len < 10) {
+ /* Need more than 10chars for this format */
+ *str_ptr = '\0';
+ (*len)--;
+ return -EINVAL;
+ }
+ while (shift > 0) {
+
+ shift -= 4;
+ digit = ((num & mask) >> shift);
+ if (digit == 0 && remove_leading_zeros) {
+ mask = mask >> 4;
+ continue;
+ } else if (digit < 0xa)
+ *str_ptr = digit + '0';
+ else
+ *str_ptr = digit - 0xa + 'a';
+ remove_leading_zeros = 0;
+ str_ptr++;
+ (*len)--;
+ mask = mask >> 4;
+ if (shift == 4*4) {
+ *str_ptr = '.';
+ str_ptr++;
+ (*len)--;
+ remove_leading_zeros = 1;
+ }
+ }
+ return 0;
+}
+
+
+static u8 bnx2x_null_format_ver(u32 spirom_ver, u8 *str, u16 *len)
+{
+ str[0] = '\0';
+ (*len)--;
+ return 0;
+}
+
+u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded,
+ u8 *version, u16 len)
+{
+ struct bnx2x *bp;
+ u32 spirom_ver = 0;
+ u8 status = 0;
+ u8 *ver_p = version;
+ u16 remain_len = len;
+ if (version == NULL || params == NULL)
+ return -EINVAL;
+ bp = params->bp;
+
+ /* Extract first external phy*/
+ version[0] = '\0';
+ spirom_ver = REG_RD(bp, params->phy[EXT_PHY1].ver_addr);
+
+ if (params->phy[EXT_PHY1].format_fw_ver) {
+ status |= params->phy[EXT_PHY1].format_fw_ver(spirom_ver,
+ ver_p,
+ &remain_len);
+ ver_p += (len - remain_len);
+ }
+ if ((params->num_phys == MAX_PHYS) &&
+ (params->phy[EXT_PHY2].ver_addr != 0)) {
+ spirom_ver = REG_RD(bp,
+ params->phy[EXT_PHY2].ver_addr);
+ if (params->phy[EXT_PHY2].format_fw_ver) {
+ *ver_p = '/';
+ ver_p++;
+ remain_len--;
+ status |= params->phy[EXT_PHY2].format_fw_ver(
+ spirom_ver,
+ ver_p,
+ &remain_len);
+ ver_p = version + (len - remain_len);
+ }
+ }
+ *ver_p = '\0';
+ return status;
+}
+
+static void bnx2x_set_xgxs_loopback(struct bnx2x_phy *phy,
+ struct link_params *params)
+{
+ u8 port = params->port;
+ struct bnx2x *bp = params->bp;
+
+ if (phy->req_line_speed != SPEED_1000) {
+ u32 md_devad;
+
+ DP(NETIF_MSG_LINK, "XGXS 10G loopback enable\n");
+
+ /* change the uni_phy_addr in the nig */
+ md_devad = REG_RD(bp, (NIG_REG_XGXS0_CTRL_MD_DEVAD +
+ port*0x18));
+
+ REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18, 0x5);
+
+ bnx2x_cl45_write(bp, phy,
+ 5,
+ (MDIO_REG_BANK_AER_BLOCK +
+ (MDIO_AER_BLOCK_AER_REG & 0xf)),
+ 0x2800);
+
+ bnx2x_cl45_write(bp, phy,
+ 5,
+ (MDIO_REG_BANK_CL73_IEEEB0 +
+ (MDIO_CL73_IEEEB0_CL73_AN_CONTROL & 0xf)),
+ 0x6041);
+ msleep(200);
+ /* set aer mmd back */
+ bnx2x_set_aer_mmd_xgxs(params, phy);
+
+ /* and md_devad */
+ REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18,
+ md_devad);
+
+ } else {
+ u16 mii_ctrl;
+ DP(NETIF_MSG_LINK, "XGXS 1G loopback enable\n");
+ bnx2x_cl45_read(bp, phy, 5,
+ (MDIO_REG_BANK_COMBO_IEEE0 +
+ (MDIO_COMBO_IEEE0_MII_CONTROL & 0xf)),
+ &mii_ctrl);
+ bnx2x_cl45_write(bp, phy, 5,
+ (MDIO_REG_BANK_COMBO_IEEE0 +
+ (MDIO_COMBO_IEEE0_MII_CONTROL & 0xf)),
+ mii_ctrl |
+ MDIO_COMBO_IEEO_MII_CONTROL_LOOPBACK);
+ }
+}
+
+/*
+ *------------------------------------------------------------------------
+ * bnx2x_override_led_value -
+ *
+ * Override the led value of the requested led
+ *
+ *------------------------------------------------------------------------
+ */
+u8 bnx2x_override_led_value(struct bnx2x *bp, u8 port,
+ u32 led_idx, u32 value)
+{
+ u32 reg_val;
+
+ /* If port 0 then use EMAC0, else use EMAC1*/
+ u32 emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
+
+ DP(NETIF_MSG_LINK,
+ "bnx2x_override_led_value() port %x led_idx %d value %d\n",
+ port, led_idx, value);
+
+ switch (led_idx) {
+ case 0: /* 10MB led */
+ /* Read the current value of the LED register in
+ the EMAC block */
+ reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED);
+ /* Set the OVERRIDE bit to 1 */
+ reg_val |= EMAC_LED_OVERRIDE;
+ /* If value is 1, set the 10M_OVERRIDE bit,
+ otherwise reset it.*/
+ reg_val = (value == 1) ? (reg_val | EMAC_LED_10MB_OVERRIDE) :
+ (reg_val & ~EMAC_LED_10MB_OVERRIDE);
+ REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val);
+ break;
+ case 1: /*100MB led */
+ /*Read the current value of the LED register in
+ the EMAC block */
+ reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED);
+ /* Set the OVERRIDE bit to 1 */
+ reg_val |= EMAC_LED_OVERRIDE;
+ /* If value is 1, set the 100M_OVERRIDE bit,
+ otherwise reset it.*/
+ reg_val = (value == 1) ? (reg_val | EMAC_LED_100MB_OVERRIDE) :
+ (reg_val & ~EMAC_LED_100MB_OVERRIDE);
+ REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val);
+ break;
+ case 2: /* 1000MB led */
+ /* Read the current value of the LED register in the
+ EMAC block */
+ reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED);
+ /* Set the OVERRIDE bit to 1 */
+ reg_val |= EMAC_LED_OVERRIDE;
+ /* If value is 1, set the 1000M_OVERRIDE bit, otherwise
+ reset it. */
+ reg_val = (value == 1) ? (reg_val | EMAC_LED_1000MB_OVERRIDE) :
+ (reg_val & ~EMAC_LED_1000MB_OVERRIDE);
+ REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val);
+ break;
+ case 3: /* 2500MB led */
+ /* Read the current value of the LED register in the
+ EMAC block*/
+ reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED);
+ /* Set the OVERRIDE bit to 1 */
+ reg_val |= EMAC_LED_OVERRIDE;
+ /* If value is 1, set the 2500M_OVERRIDE bit, otherwise
+ reset it.*/
+ reg_val = (value == 1) ? (reg_val | EMAC_LED_2500MB_OVERRIDE) :
+ (reg_val & ~EMAC_LED_2500MB_OVERRIDE);
+ REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val);
+ break;
+ case 4: /*10G led */
+ if (port == 0) {
+ REG_WR(bp, NIG_REG_LED_10G_P0,
+ value);
+ } else {
+ REG_WR(bp, NIG_REG_LED_10G_P1,
+ value);
+ }
+ break;
+ case 5: /* TRAFFIC led */
+ /* Find if the traffic control is via BMAC or EMAC */
+ if (port == 0)
+ reg_val = REG_RD(bp, NIG_REG_NIG_EMAC0_EN);
+ else
+ reg_val = REG_RD(bp, NIG_REG_NIG_EMAC1_EN);
+
+ /* Override the traffic led in the EMAC:*/
+ if (reg_val == 1) {
+ /* Read the current value of the LED register in
+ the EMAC block */
+ reg_val = REG_RD(bp, emac_base +
+ EMAC_REG_EMAC_LED);
+ /* Set the TRAFFIC_OVERRIDE bit to 1 */
+ reg_val |= EMAC_LED_OVERRIDE;
+ /* If value is 1, set the TRAFFIC bit, otherwise
+ reset it.*/
+ reg_val = (value == 1) ? (reg_val | EMAC_LED_TRAFFIC) :
+ (reg_val & ~EMAC_LED_TRAFFIC);
+ REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val);
+ } else { /* Override the traffic led in the BMAC: */
+ REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0
+ + port*4, 1);
+ REG_WR(bp, NIG_REG_LED_CONTROL_TRAFFIC_P0 + port*4,
+ value);
+ }
+ break;
+ default:
+ DP(NETIF_MSG_LINK,
+ "bnx2x_override_led_value() unknown led index %d "
+ "(should be 0-5)\n", led_idx);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
- case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482:
- DP(NETIF_MSG_LINK, "SerDes 5482\n");
- bnx2x_ext_phy_hw_reset(bp, params->port);
+u8 bnx2x_set_led(struct link_params *params,
+ struct link_vars *vars, u8 mode, u32 speed)
+{
+ u8 port = params->port;
+ u16 hw_led_mode = params->hw_led_mode;
+ u8 rc = 0, phy_idx;
+ u32 tmp;
+ u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
+ struct bnx2x *bp = params->bp;
+ DP(NETIF_MSG_LINK, "bnx2x_set_led: port %x, mode %d\n", port, mode);
+ DP(NETIF_MSG_LINK, "speed 0x%x, hw_led_mode 0x%x\n",
+ speed, hw_led_mode);
+ /* In case */
+ for (phy_idx = EXT_PHY1; phy_idx < MAX_PHYS; phy_idx++) {
+ if (params->phy[phy_idx].set_link_led) {
+ params->phy[phy_idx].set_link_led(
+ &params->phy[phy_idx], params, mode);
+ }
+ }
+
+ switch (mode) {
+ case LED_MODE_FRONT_PANEL_OFF:
+ case LED_MODE_OFF:
+ REG_WR(bp, NIG_REG_LED_10G_P0 + port*4, 0);
+ REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4,
+ SHARED_HW_CFG_LED_MAC1);
+
+ tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED);
+ EMAC_WR(bp, EMAC_REG_EMAC_LED, (tmp | EMAC_LED_OVERRIDE));
+ break;
+
+ case LED_MODE_OPER:
+ /**
+ * For all other phys, OPER mode is same as ON, so in case
+ * link is down, do nothing
+ **/
+ if (!vars->link_up)
break;
+ case LED_MODE_ON:
+ if (SINGLE_MEDIA_DIRECT(params)) {
+ /**
+ * This is a work-around for HW issue found when link
+ * is up in CL73
+ */
+ REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, 0);
+ REG_WR(bp, NIG_REG_LED_10G_P0 + port*4, 1);
+ } else {
+ REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4,
+ hw_led_mode);
+ }
- default:
- DP(NETIF_MSG_LINK, "BAD SerDes ext_phy_config 0x%x\n",
- params->ext_phy_config);
+ REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0 +
+ port*4, 0);
+ /* Set blinking rate to ~15.9Hz */
+ REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_RATE_P0 + port*4,
+ LED_BLINK_RATE_VAL);
+ REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_RATE_ENA_P0 +
+ port*4, 1);
+ tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED);
+ EMAC_WR(bp, EMAC_REG_EMAC_LED,
+ (tmp & (~EMAC_LED_OVERRIDE)));
+
+ if (CHIP_IS_E1(bp) &&
+ ((speed == SPEED_2500) ||
+ (speed == SPEED_1000) ||
+ (speed == SPEED_100) ||
+ (speed == SPEED_10))) {
+ /* On Everest 1 Ax chip versions for speeds less than
+ 10G LED scheme is different */
+ REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0
+ + port*4, 1);
+ REG_WR(bp, NIG_REG_LED_CONTROL_TRAFFIC_P0 +
+ port*4, 0);
+ REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_TRAFFIC_P0 +
+ port*4, 1);
+ }
+ break;
+
+ default:
+ rc = -EINVAL;
+ DP(NETIF_MSG_LINK, "bnx2x_set_led: Invalid led mode %d\n",
+ mode);
+ break;
+ }
+ return rc;
+
+}
+
+/**
+ * This function comes to reflect the actual link state read DIRECTLY from the
+ * HW
+ */
+u8 bnx2x_test_link(struct link_params *params, struct link_vars *vars,
+ u8 is_serdes)
+{
+ struct bnx2x *bp = params->bp;
+ u16 gp_status = 0, phy_index = 0;
+ u8 ext_phy_link_up = 0, serdes_phy_type;
+ struct link_vars temp_vars;
+
+ CL45_RD_OVER_CL22(bp, &params->phy[INT_PHY],
+ MDIO_REG_BANK_GP_STATUS,
+ MDIO_GP_STATUS_TOP_AN_STATUS1,
+ &gp_status);
+ /* link is up only if both local phy and external phy are up */
+ if (!(gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS))
+ return -ESRCH;
+
+ switch (params->num_phys) {
+ case 1:
+ /* No external PHY */
+ return 0;
+ case 2:
+ ext_phy_link_up = params->phy[EXT_PHY1].read_status(
+ &params->phy[EXT_PHY1],
+ params, &temp_vars);
+ break;
+ case 3: /* Dual Media */
+ for (phy_index = EXT_PHY1; phy_index < params->num_phys;
+ phy_index++) {
+ serdes_phy_type = ((params->phy[phy_index].media_type ==
+ ETH_PHY_SFP_FIBER) ||
+ (params->phy[phy_index].media_type ==
+ ETH_PHY_XFP_FIBER));
+
+ if (is_serdes != serdes_phy_type)
+ continue;
+ if (params->phy[phy_index].read_status) {
+ ext_phy_link_up |=
+ params->phy[phy_index].read_status(
+ &params->phy[phy_index],
+ params, &temp_vars);
+ }
+ }
+ break;
+ }
+ if (ext_phy_link_up)
+ return 0;
+ return -ESRCH;
+}
+
+static u8 bnx2x_link_initialize(struct link_params *params,
+ struct link_vars *vars)
+{
+ u8 rc = 0;
+ u8 phy_index, non_ext_phy;
+ struct bnx2x *bp = params->bp;
+ /**
+ * In case of external phy existence, the line speed would be the
+ * line speed linked up by the external phy. In case it is direct
+ * only, then the line_speed during initialization will be
+ * equal to the req_line_speed
+ */
+ vars->line_speed = params->phy[INT_PHY].req_line_speed;
+
+ /**
+ * Initialize the internal phy in case this is a direct board
+ * (no external phys), or this board has external phy which requires
+ * to first.
+ */
+
+ if (params->phy[INT_PHY].config_init)
+ params->phy[INT_PHY].config_init(
+ &params->phy[INT_PHY],
+ params, vars);
+
+ /* init ext phy and enable link state int */
+ non_ext_phy = (SINGLE_MEDIA_DIRECT(params) ||
+ (params->loopback_mode == LOOPBACK_XGXS));
+
+ if (non_ext_phy ||
+ (params->phy[EXT_PHY1].flags & FLAGS_INIT_XGXS_FIRST) ||
+ (params->loopback_mode == LOOPBACK_EXT_PHY)) {
+ struct bnx2x_phy *phy = &params->phy[INT_PHY];
+ if (vars->line_speed == SPEED_AUTO_NEG)
+ bnx2x_set_parallel_detection(phy, params);
+ bnx2x_init_internal_phy(phy, params, vars);
+ }
+
+ /* Init external phy*/
+ if (!non_ext_phy)
+ for (phy_index = EXT_PHY1; phy_index < params->num_phys;
+ phy_index++) {
+ /**
+ * No need to initialize second phy in case of first
+ * phy only selection. In case of second phy, we do
+ * need to initialize the first phy, since they are
+ * connected.
+ **/
+ if (phy_index == EXT_PHY2 &&
+ (bnx2x_phy_selection(params) ==
+ PORT_HW_CFG_PHY_SELECTION_FIRST_PHY)) {
+ DP(NETIF_MSG_LINK, "Not initializing"
+ "second phy\n");
+ continue;
+ }
+ params->phy[phy_index].config_init(
+ &params->phy[phy_index],
+ params, vars);
+ }
+
+ /* Reset the interrupt indication after phy was initialized */
+ bnx2x_bits_dis(bp, NIG_REG_STATUS_INTERRUPT_PORT0 +
+ params->port*4,
+ (NIG_STATUS_XGXS0_LINK10G |
+ NIG_STATUS_XGXS0_LINK_STATUS |
+ NIG_STATUS_SERDES0_LINK_STATUS |
+ NIG_MASK_MI_INT));
+ return rc;
+}
+
+static void bnx2x_int_link_reset(struct bnx2x_phy *phy,
+ struct link_params *params)
+{
+ /* reset the SerDes/XGXS */
+ REG_WR(params->bp, GRCBASE_MISC +
+ MISC_REGISTERS_RESET_REG_3_CLEAR,
+ (0x1ff << (params->port*16)));
+}
+
+static void bnx2x_common_ext_link_reset(struct bnx2x_phy *phy,
+ struct link_params *params)
+{
+ struct bnx2x *bp = params->bp;
+ u8 gpio_port;
+ /* HW reset */
+ if (CHIP_IS_E2(bp))
+ gpio_port = BP_PATH(bp);
+ else
+ gpio_port = params->port;
+ bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
+ MISC_REGISTERS_GPIO_OUTPUT_LOW,
+ gpio_port);
+ bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
+ MISC_REGISTERS_GPIO_OUTPUT_LOW,
+ gpio_port);
+ DP(NETIF_MSG_LINK, "reset external PHY\n");
+}
+
+static u8 bnx2x_update_link_down(struct link_params *params,
+ struct link_vars *vars)
+{
+ struct bnx2x *bp = params->bp;
+ u8 port = params->port;
+
+ DP(NETIF_MSG_LINK, "Port %x: Link is down\n", port);
+ bnx2x_set_led(params, vars, LED_MODE_OFF, 0);
+
+ /* indicate no mac active */
+ vars->mac_type = MAC_TYPE_NONE;
+
+ /* update shared memory */
+ vars->link_status = 0;
+ vars->line_speed = 0;
+ bnx2x_update_mng(params, vars->link_status);
+
+ /* activate nig drain */
+ REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1);
+
+ /* disable emac */
+ REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
+
+ msleep(10);
+
+ /* reset BigMac */
+ bnx2x_bmac_rx_disable(bp, params->port);
+ REG_WR(bp, GRCBASE_MISC +
+ MISC_REGISTERS_RESET_REG_2_CLEAR,
+ (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
+ return 0;
+}
+
+static u8 bnx2x_update_link_up(struct link_params *params,
+ struct link_vars *vars,
+ u8 link_10g)
+{
+ struct bnx2x *bp = params->bp;
+ u8 port = params->port;
+ u8 rc = 0;
+
+ vars->link_status |= LINK_STATUS_LINK_UP;
+
+ if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
+ vars->link_status |=
+ LINK_STATUS_TX_FLOW_CONTROL_ENABLED;
+
+ if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
+ vars->link_status |=
+ LINK_STATUS_RX_FLOW_CONTROL_ENABLED;
+
+ if (link_10g) {
+ bnx2x_bmac_enable(params, vars, 0);
+ bnx2x_set_led(params, vars,
+ LED_MODE_OPER, SPEED_10000);
+ } else {
+ rc = bnx2x_emac_program(params, vars);
+
+ bnx2x_emac_enable(params, vars, 0);
+
+ /* AN complete? */
+ if ((vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE)
+ && (!(vars->phy_flags & PHY_SGMII_FLAG)) &&
+ SINGLE_MEDIA_DIRECT(params))
+ bnx2x_set_gmii_tx_driver(params);
+ }
+
+ /* PBF - link up */
+ if (!(CHIP_IS_E2(bp)))
+ rc |= bnx2x_pbf_update(params, vars->flow_ctrl,
+ vars->line_speed);
+
+ /* disable drain */
+ REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 0);
+
+ /* update shared memory */
+ bnx2x_update_mng(params, vars->link_status);
+ msleep(20);
+ return rc;
+}
+/**
+ * The bnx2x_link_update function should be called upon link
+ * interrupt.
+ * Link is considered up as follows:
+ * - DIRECT_SINGLE_MEDIA - Only XGXS link (internal link) needs
+ * to be up
+ * - SINGLE_MEDIA - The link between the 577xx and the external
+ * phy (XGXS) need to up as well as the external link of the
+ * phy (PHY_EXT1)
+ * - DUAL_MEDIA - The link between the 577xx and the first
+ * external phy needs to be up, and at least one of the 2
+ * external phy link must be up.
+ */
+u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
+{
+ struct bnx2x *bp = params->bp;
+ struct link_vars phy_vars[MAX_PHYS];
+ u8 port = params->port;
+ u8 link_10g, phy_index;
+ u8 ext_phy_link_up = 0, cur_link_up, rc = 0;
+ u8 is_mi_int = 0;
+ u16 ext_phy_line_speed = 0, prev_line_speed = vars->line_speed;
+ u8 active_external_phy = INT_PHY;
+ vars->link_status = 0;
+ for (phy_index = INT_PHY; phy_index < params->num_phys;
+ phy_index++) {
+ phy_vars[phy_index].flow_ctrl = 0;
+ phy_vars[phy_index].link_status = 0;
+ phy_vars[phy_index].line_speed = 0;
+ phy_vars[phy_index].duplex = DUPLEX_FULL;
+ phy_vars[phy_index].phy_link_up = 0;
+ phy_vars[phy_index].link_up = 0;
+ }
+
+ DP(NETIF_MSG_LINK, "port %x, XGXS?%x, int_status 0x%x\n",
+ port, (vars->phy_flags & PHY_XGXS_FLAG),
+ REG_RD(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4));
+
+ is_mi_int = (u8)(REG_RD(bp, NIG_REG_EMAC0_STATUS_MISC_MI_INT +
+ port*0x18) > 0);
+ DP(NETIF_MSG_LINK, "int_mask 0x%x MI_INT %x, SERDES_LINK %x\n",
+ REG_RD(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4),
+ is_mi_int,
+ REG_RD(bp,
+ NIG_REG_SERDES0_STATUS_LINK_STATUS + port*0x3c));
+
+ DP(NETIF_MSG_LINK, " 10G %x, XGXS_LINK %x\n",
+ REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK10G + port*0x68),
+ REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68));
+
+ /* disable emac */
+ REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
+
+ /**
+ * Step 1:
+ * Check external link change only for external phys, and apply
+ * priority selection between them in case the link on both phys
+ * is up. Note that the instead of the common vars, a temporary
+ * vars argument is used since each phy may have different link/
+ * speed/duplex result
+ */
+ for (phy_index = EXT_PHY1; phy_index < params->num_phys;
+ phy_index++) {
+ struct bnx2x_phy *phy = &params->phy[phy_index];
+ if (!phy->read_status)
+ continue;
+ /* Read link status and params of this ext phy */
+ cur_link_up = phy->read_status(phy, params,
+ &phy_vars[phy_index]);
+ if (cur_link_up) {
+ DP(NETIF_MSG_LINK, "phy in index %d link is up\n",
+ phy_index);
+ } else {
+ DP(NETIF_MSG_LINK, "phy in index %d link is down\n",
+ phy_index);
+ continue;
+ }
+
+ if (!ext_phy_link_up) {
+ ext_phy_link_up = 1;
+ active_external_phy = phy_index;
+ } else {
+ switch (bnx2x_phy_selection(params)) {
+ case PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT:
+ case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY:
+ /**
+ * In this option, the first PHY makes sure to pass the
+ * traffic through itself only.
+ * Its not clear how to reset the link on the second phy
+ **/
+ active_external_phy = EXT_PHY1;
+ break;
+ case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY:
+ /**
+ * In this option, the first PHY makes sure to pass the
+ * traffic through the second PHY.
+ **/
+ active_external_phy = EXT_PHY2;
+ break;
+ default:
+ /**
+ * Link indication on both PHYs with the following cases
+ * is invalid:
+ * - FIRST_PHY means that second phy wasn't initialized,
+ * hence its link is expected to be down
+ * - SECOND_PHY means that first phy should not be able
+ * to link up by itself (using configuration)
+ * - DEFAULT should be overriden during initialiazation
+ **/
+ DP(NETIF_MSG_LINK, "Invalid link indication"
+ "mpc=0x%x. DISABLING LINK !!!\n",
+ params->multi_phy_config);
+ ext_phy_link_up = 0;
+ break;
+ }
+ }
+ }
+ prev_line_speed = vars->line_speed;
+ /**
+ * Step 2:
+ * Read the status of the internal phy. In case of
+ * DIRECT_SINGLE_MEDIA board, this link is the external link,
+ * otherwise this is the link between the 577xx and the first
+ * external phy
+ */
+ if (params->phy[INT_PHY].read_status)
+ params->phy[INT_PHY].read_status(
+ &params->phy[INT_PHY],
+ params, vars);
+ /**
+ * The INT_PHY flow control reside in the vars. This include the
+ * case where the speed or flow control are not set to AUTO.
+ * Otherwise, the active external phy flow control result is set
+ * to the vars. The ext_phy_line_speed is needed to check if the
+ * speed is different between the internal phy and external phy.
+ * This case may be result of intermediate link speed change.
+ */
+ if (active_external_phy > INT_PHY) {
+ vars->flow_ctrl = phy_vars[active_external_phy].flow_ctrl;
+ /**
+ * Link speed is taken from the XGXS. AN and FC result from
+ * the external phy.
+ */
+ vars->link_status |= phy_vars[active_external_phy].link_status;
+
+ /**
+ * if active_external_phy is first PHY and link is up - disable
+ * disable TX on second external PHY
+ */
+ if (active_external_phy == EXT_PHY1) {
+ if (params->phy[EXT_PHY2].phy_specific_func) {
+ DP(NETIF_MSG_LINK, "Disabling TX on"
+ " EXT_PHY2\n");
+ params->phy[EXT_PHY2].phy_specific_func(
+ &params->phy[EXT_PHY2],
+ params, DISABLE_TX);
+ }
+ }
+
+ ext_phy_line_speed = phy_vars[active_external_phy].line_speed;
+ vars->duplex = phy_vars[active_external_phy].duplex;
+ if (params->phy[active_external_phy].supported &
+ SUPPORTED_FIBRE)
+ vars->link_status |= LINK_STATUS_SERDES_LINK;
+ DP(NETIF_MSG_LINK, "Active external phy selected: %x\n",
+ active_external_phy);
+ }
+
+ for (phy_index = EXT_PHY1; phy_index < params->num_phys;
+ phy_index++) {
+ if (params->phy[phy_index].flags &
+ FLAGS_REARM_LATCH_SIGNAL) {
+ bnx2x_rearm_latch_signal(bp, port,
+ phy_index ==
+ active_external_phy);
break;
}
}
+ DP(NETIF_MSG_LINK, "vars->flow_ctrl = 0x%x, vars->link_status = 0x%x,"
+ " ext_phy_line_speed = %d\n", vars->flow_ctrl,
+ vars->link_status, ext_phy_line_speed);
+ /**
+ * Upon link speed change set the NIG into drain mode. Comes to
+ * deals with possible FIFO glitch due to clk change when speed
+ * is decreased without link down indicator
+ */
+
+ if (vars->phy_link_up) {
+ if (!(SINGLE_MEDIA_DIRECT(params)) && ext_phy_link_up &&
+ (ext_phy_line_speed != vars->line_speed)) {
+ DP(NETIF_MSG_LINK, "Internal link speed %d is"
+ " different than the external"
+ " link speed %d\n", vars->line_speed,
+ ext_phy_line_speed);
+ vars->phy_link_up = 0;
+ } else if (prev_line_speed != vars->line_speed) {
+ REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE
+ + params->port*4, 0);
+ msleep(1);
+ }
+ }
+
+ /* anything 10 and over uses the bmac */
+ link_10g = ((vars->line_speed == SPEED_10000) ||
+ (vars->line_speed == SPEED_12000) ||
+ (vars->line_speed == SPEED_12500) ||
+ (vars->line_speed == SPEED_13000) ||
+ (vars->line_speed == SPEED_15000) ||
+ (vars->line_speed == SPEED_16000));
+
+ bnx2x_link_int_ack(params, vars, link_10g);
+
+ /**
+ * In case external phy link is up, and internal link is down
+ * (not initialized yet probably after link initialization, it
+ * needs to be initialized.
+ * Note that after link down-up as result of cable plug, the xgxs
+ * link would probably become up again without the need
+ * initialize it
+ */
+ if (!(SINGLE_MEDIA_DIRECT(params))) {
+ DP(NETIF_MSG_LINK, "ext_phy_link_up = %d, int_link_up = %d,"
+ " init_preceding = %d\n", ext_phy_link_up,
+ vars->phy_link_up,
+ params->phy[EXT_PHY1].flags &
+ FLAGS_INIT_XGXS_FIRST);
+ if (!(params->phy[EXT_PHY1].flags &
+ FLAGS_INIT_XGXS_FIRST)
+ && ext_phy_link_up && !vars->phy_link_up) {
+ vars->line_speed = ext_phy_line_speed;
+ if (vars->line_speed < SPEED_1000)
+ vars->phy_flags |= PHY_SGMII_FLAG;
+ else
+ vars->phy_flags &= ~PHY_SGMII_FLAG;
+ bnx2x_init_internal_phy(&params->phy[INT_PHY],
+ params,
+ vars);
+ }
+ }
+ /**
+ * Link is up only if both local phy and external phy (in case of
+ * non-direct board) are up
+ */
+ vars->link_up = (vars->phy_link_up &&
+ (ext_phy_link_up ||
+ SINGLE_MEDIA_DIRECT(params)));
+
+ if (vars->link_up)
+ rc = bnx2x_update_link_up(params, vars, link_10g);
+ else
+ rc = bnx2x_update_link_down(params, vars);
+
+ return rc;
+}
+
+
+/*****************************************************************************/
+/* External Phy section */
+/*****************************************************************************/
+void bnx2x_ext_phy_hw_reset(struct bnx2x *bp, u8 port)
+{
+ bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
+ MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
+ msleep(1);
+ bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
+ MISC_REGISTERS_GPIO_OUTPUT_HIGH, port);
}
static void bnx2x_save_spirom_version(struct bnx2x *bp, u8 port,
- u32 shmem_base, u32 spirom_ver)
+ u32 spirom_ver, u32 ver_addr)
{
DP(NETIF_MSG_LINK, "FW version 0x%x:0x%x for port %d\n",
(u16)(spirom_ver>>16), (u16)spirom_ver, port);
- REG_WR(bp, shmem_base +
- offsetof(struct shmem_region,
- port_mb[port].ext_phy_fw_version),
- spirom_ver);
+
+ if (ver_addr)
+ REG_WR(bp, ver_addr, spirom_ver);
}
-static void bnx2x_save_bcm_spirom_ver(struct bnx2x *bp, u8 port,
- u32 ext_phy_type, u8 ext_phy_addr,
- u32 shmem_base)
+static void bnx2x_save_bcm_spirom_ver(struct bnx2x *bp,
+ struct bnx2x_phy *phy,
+ u8 port)
{
u16 fw_ver1, fw_ver2;
- bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr, MDIO_PMA_DEVAD,
+ bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD,
MDIO_PMA_REG_ROM_VER1, &fw_ver1);
- bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr, MDIO_PMA_DEVAD,
+ bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD,
MDIO_PMA_REG_ROM_VER2, &fw_ver2);
- bnx2x_save_spirom_version(bp, port, shmem_base,
- (u32)(fw_ver1<<16 | fw_ver2));
+ bnx2x_save_spirom_version(bp, port, (u32)(fw_ver1<<16 | fw_ver2),
+ phy->ver_addr);
}
-
-static void bnx2x_save_8481_spirom_version(struct bnx2x *bp, u8 port,
- u8 ext_phy_addr, u32 shmem_base)
+static void bnx2x_ext_phy_set_pause(struct link_params *params,
+ struct bnx2x_phy *phy,
+ struct link_vars *vars)
{
- u16 val, fw_ver1, fw_ver2, cnt;
- /* For the 32 bits registers in 8481, access via MDIO2ARM interface.*/
- /* (1) set register 0xc200_0014(SPI_BRIDGE_CTRL_2) to 0x03000000 */
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
- ext_phy_addr, MDIO_PMA_DEVAD,
- 0xA819, 0x0014);
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- 0xA81A,
- 0xc200);
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- 0xA81B,
- 0x0000);
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- 0xA81C,
- 0x0300);
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- 0xA817,
- 0x0009);
+ u16 val;
+ struct bnx2x *bp = params->bp;
+ /* read modify write pause advertizing */
+ bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV_PAUSE, &val);
- for (cnt = 0; cnt < 100; cnt++) {
- bnx2x_cl45_read(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- 0xA818,
- &val);
- if (val & 1)
- break;
- udelay(5);
+ val &= ~MDIO_AN_REG_ADV_PAUSE_BOTH;
+
+ /* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
+ bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
+ if ((vars->ieee_fc &
+ MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) ==
+ MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) {
+ val |= MDIO_AN_REG_ADV_PAUSE_ASYMMETRIC;
}
- if (cnt == 100) {
- DP(NETIF_MSG_LINK, "Unable to read 8481 phy fw version(1)\n");
- bnx2x_save_spirom_version(bp, port,
- shmem_base, 0);
- return;
+ if ((vars->ieee_fc &
+ MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) ==
+ MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) {
+ val |= MDIO_AN_REG_ADV_PAUSE_PAUSE;
}
+ DP(NETIF_MSG_LINK, "Ext phy AN advertize 0x%x\n", val);
+ bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV_PAUSE, val);
+}
+static u8 bnx2x_ext_phy_resolve_fc(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
+{
+ struct bnx2x *bp = params->bp;
+ u16 ld_pause; /* local */
+ u16 lp_pause; /* link partner */
+ u16 pause_result;
+ u8 ret = 0;
+ /* read twice */
- /* 2) read register 0xc200_0000 (SPI_FW_STATUS) */
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
- ext_phy_addr, MDIO_PMA_DEVAD,
- 0xA819, 0x0000);
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
- ext_phy_addr, MDIO_PMA_DEVAD,
- 0xA81A, 0xc200);
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
- ext_phy_addr, MDIO_PMA_DEVAD,
- 0xA817, 0x000A);
- for (cnt = 0; cnt < 100; cnt++) {
- bnx2x_cl45_read(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- 0xA818,
- &val);
- if (val & 1)
- break;
- udelay(5);
+ vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
+
+ if (phy->req_flow_ctrl != BNX2X_FLOW_CTRL_AUTO)
+ vars->flow_ctrl = phy->req_flow_ctrl;
+ else if (phy->req_line_speed != SPEED_AUTO_NEG)
+ vars->flow_ctrl = params->req_fc_auto_adv;
+ else if (vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE) {
+ ret = 1;
+ bnx2x_cl45_read(bp, phy,
+ MDIO_AN_DEVAD,
+ MDIO_AN_REG_ADV_PAUSE, &ld_pause);
+ bnx2x_cl45_read(bp, phy,
+ MDIO_AN_DEVAD,
+ MDIO_AN_REG_LP_AUTO_NEG, &lp_pause);
+ pause_result = (ld_pause &
+ MDIO_AN_REG_ADV_PAUSE_MASK) >> 8;
+ pause_result |= (lp_pause &
+ MDIO_AN_REG_ADV_PAUSE_MASK) >> 10;
+ DP(NETIF_MSG_LINK, "Ext PHY pause result 0x%x\n",
+ pause_result);
+ bnx2x_pause_resolve(vars, pause_result);
}
- if (cnt == 100) {
- DP(NETIF_MSG_LINK, "Unable to read 8481 phy fw version(2)\n");
- bnx2x_save_spirom_version(bp, port,
- shmem_base, 0);
+ return ret;
+}
+
+static void bnx2x_ext_phy_10G_an_resolve(struct bnx2x *bp,
+ struct bnx2x_phy *phy,
+ struct link_vars *vars)
+{
+ u16 val;
+ bnx2x_cl45_read(bp, phy,
+ MDIO_AN_DEVAD,
+ MDIO_AN_REG_STATUS, &val);
+ bnx2x_cl45_read(bp, phy,
+ MDIO_AN_DEVAD,
+ MDIO_AN_REG_STATUS, &val);
+ if (val & (1<<5))
+ vars->link_status |= LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
+ if ((val & (1<<0)) == 0)
+ vars->link_status |= LINK_STATUS_PARALLEL_DETECTION_USED;
+}
+
+/******************************************************************/
+/* common BCM8073/BCM8727 PHY SECTION */
+/******************************************************************/
+static void bnx2x_8073_resolve_fc(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
+{
+ struct bnx2x *bp = params->bp;
+ if (phy->req_line_speed == SPEED_10 ||
+ phy->req_line_speed == SPEED_100) {
+ vars->flow_ctrl = phy->req_flow_ctrl;
return;
}
- /* lower 16 bits of the register SPI_FW_STATUS */
- bnx2x_cl45_read(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- 0xA81B,
- &fw_ver1);
- /* upper 16 bits of register SPI_FW_STATUS */
- bnx2x_cl45_read(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- 0xA81C,
- &fw_ver2);
+ if (bnx2x_ext_phy_resolve_fc(phy, params, vars) &&
+ (vars->flow_ctrl == BNX2X_FLOW_CTRL_NONE)) {
+ u16 pause_result;
+ u16 ld_pause; /* local */
+ u16 lp_pause; /* link partner */
+ bnx2x_cl45_read(bp, phy,
+ MDIO_AN_DEVAD,
+ MDIO_AN_REG_CL37_FC_LD, &ld_pause);
+
+ bnx2x_cl45_read(bp, phy,
+ MDIO_AN_DEVAD,
+ MDIO_AN_REG_CL37_FC_LP, &lp_pause);
+ pause_result = (ld_pause &
+ MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 5;
+ pause_result |= (lp_pause &
+ MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 7;
- bnx2x_save_spirom_version(bp, port,
- shmem_base, (fw_ver2<<16) | fw_ver1);
+ bnx2x_pause_resolve(vars, pause_result);
+ DP(NETIF_MSG_LINK, "Ext PHY CL37 pause result 0x%x\n",
+ pause_result);
+ }
}
-static void bnx2x_bcm8072_external_rom_boot(struct link_params *params)
+static void bnx2x_8073_8727_external_rom_boot(struct bnx2x *bp,
+ struct bnx2x_phy *phy,
+ u8 port)
{
- struct bnx2x *bp = params->bp;
- u8 port = params->port;
- u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
- u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
+ /* Boot port from external ROM */
+ /* EDC grst */
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_GEN_CTRL,
+ 0x0001);
- /* Need to wait 200ms after reset */
- msleep(200);
- /* Boot port from external ROM
- * Set ser_boot_ctl bit in the MISC_CTRL1 register
- */
- bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_MISC_CTRL1, 0x0001);
+ /* ucode reboot and rst */
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_GEN_CTRL,
+ 0x008c);
+
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_MISC_CTRL1, 0x0001);
/* Reset internal microprocessor */
- bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_GEN_CTRL,
- MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
- /* set micro reset = 0 */
- bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_GEN_CTRL,
- MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET);
- /* Reset internal microprocessor */
- bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_GEN_CTRL,
- MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
- /* wait for 100ms for code download via SPI port */
- msleep(100);
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_GEN_CTRL,
+ MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET);
+
+ /* Release srst bit */
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_GEN_CTRL,
+ MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
+
+ /* wait for 120ms for code download via SPI port */
+ msleep(120);
/* Clear ser_boot_ctl bit */
- bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_MISC_CTRL1, 0x0000);
- /* Wait 100ms */
- msleep(100);
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_MISC_CTRL1, 0x0000);
+ bnx2x_save_bcm_spirom_ver(bp, phy, port);
+}
+
+static void bnx2x_8073_set_xaui_low_power_mode(struct bnx2x *bp,
+ struct bnx2x_phy *phy)
+{
+ u16 val;
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_8073_CHIP_REV, &val);
+
+ if (val == 0) {
+ /* Mustn't set low power mode in 8073 A0 */
+ return;
+ }
+
+ /* Disable PLL sequencer (use read-modify-write to clear bit 13) */
+ bnx2x_cl45_read(bp, phy,
+ MDIO_XS_DEVAD, MDIO_XS_PLL_SEQUENCER, &val);
+ val &= ~(1<<13);
+ bnx2x_cl45_write(bp, phy,
+ MDIO_XS_DEVAD, MDIO_XS_PLL_SEQUENCER, val);
- bnx2x_save_bcm_spirom_ver(bp, port,
- ext_phy_type,
- ext_phy_addr,
- params->shmem_base);
+ /* PLL controls */
+ bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x805E, 0x1077);
+ bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x805D, 0x0000);
+ bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x805C, 0x030B);
+ bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x805B, 0x1240);
+ bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x805A, 0x2490);
+
+ /* Tx Controls */
+ bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x80A7, 0x0C74);
+ bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x80A6, 0x9041);
+ bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x80A5, 0x4640);
+
+ /* Rx Controls */
+ bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x80FE, 0x01C4);
+ bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x80FD, 0x9249);
+ bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x80FC, 0x2015);
+
+ /* Enable PLL sequencer (use read-modify-write to set bit 13) */
+ bnx2x_cl45_read(bp, phy, MDIO_XS_DEVAD, MDIO_XS_PLL_SEQUENCER, &val);
+ val |= (1<<13);
+ bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, MDIO_XS_PLL_SEQUENCER, val);
}
-static u8 bnx2x_8073_is_snr_needed(struct link_params *params)
+/******************************************************************/
+/* BCM8073 PHY SECTION */
+/******************************************************************/
+static u8 bnx2x_8073_is_snr_needed(struct bnx2x *bp, struct bnx2x_phy *phy)
{
/* This is only required for 8073A1, version 102 only */
-
- struct bnx2x *bp = params->bp;
- u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
u16 val;
/* Read 8073 HW revision*/
- bnx2x_cl45_read(bp, params->port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
- ext_phy_addr,
+ bnx2x_cl45_read(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_8073_CHIP_REV, &val);
@@ -2431,9 +3484,7 @@ static u8 bnx2x_8073_is_snr_needed(struct link_params *params)
return 0;
}
- bnx2x_cl45_read(bp, params->port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
- ext_phy_addr,
+ bnx2x_cl45_read(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_ROM_VER2, &val);
@@ -2444,15 +3495,11 @@ static u8 bnx2x_8073_is_snr_needed(struct link_params *params)
return 1;
}
-static u8 bnx2x_bcm8073_xaui_wa(struct link_params *params)
+static u8 bnx2x_8073_xaui_wa(struct bnx2x *bp, struct bnx2x_phy *phy)
{
- struct bnx2x *bp = params->bp;
- u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
u16 val, cnt, cnt1 ;
- bnx2x_cl45_read(bp, params->port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
- ext_phy_addr,
+ bnx2x_cl45_read(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_8073_CHIP_REV, &val);
@@ -2466,9 +3513,7 @@ static u8 bnx2x_bcm8073_xaui_wa(struct link_params *params)
poll Dev1, Reg $C820: */
for (cnt = 0; cnt < 1000; cnt++) {
- bnx2x_cl45_read(bp, params->port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
- ext_phy_addr,
+ bnx2x_cl45_read(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_8073_SPEED_LINK_STATUS,
&val);
@@ -2485,9 +3530,7 @@ static u8 bnx2x_bcm8073_xaui_wa(struct link_params *params)
XAUI workaround has completed),
then continue on with system initialization.*/
for (cnt1 = 0; cnt1 < 1000; cnt1++) {
- bnx2x_cl45_read(bp, params->port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
- ext_phy_addr,
+ bnx2x_cl45_read(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_8073_XAUI_WA, &val);
if (val & (1<<15)) {
@@ -2505,143 +3548,391 @@ static u8 bnx2x_bcm8073_xaui_wa(struct link_params *params)
return -EINVAL;
}
-static void bnx2x_bcm8073_bcm8727_external_rom_boot(struct bnx2x *bp, u8 port,
- u8 ext_phy_addr,
- u32 ext_phy_type,
- u32 shmem_base)
+static void bnx2x_807x_force_10G(struct bnx2x *bp, struct bnx2x_phy *phy)
{
- /* Boot port from external ROM */
- /* EDC grst */
- bnx2x_cl45_write(bp, port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_GEN_CTRL,
- 0x0001);
+ /* Force KR or KX */
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x2040);
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2, 0x000b);
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_BCM_CTRL, 0x0000);
+ bnx2x_cl45_write(bp, phy,
+ MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x0000);
+}
- /* ucode reboot and rst */
- bnx2x_cl45_write(bp, port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_GEN_CTRL,
- 0x008c);
+static void bnx2x_8073_set_pause_cl37(struct link_params *params,
+ struct bnx2x_phy *phy,
+ struct link_vars *vars)
+{
+ u16 cl37_val;
+ struct bnx2x *bp = params->bp;
+ bnx2x_cl45_read(bp, phy,
+ MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD, &cl37_val);
- bnx2x_cl45_write(bp, port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_MISC_CTRL1, 0x0001);
+ cl37_val &= ~MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
+ /* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
+ bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
+ if ((vars->ieee_fc &
+ MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC) ==
+ MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC) {
+ cl37_val |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC;
+ }
+ if ((vars->ieee_fc &
+ MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) ==
+ MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) {
+ cl37_val |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
+ }
+ if ((vars->ieee_fc &
+ MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) ==
+ MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) {
+ cl37_val |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
+ }
+ DP(NETIF_MSG_LINK,
+ "Ext phy AN advertize cl37 0x%x\n", cl37_val);
- /* Reset internal microprocessor */
- bnx2x_cl45_write(bp, port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_GEN_CTRL,
- MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET);
+ bnx2x_cl45_write(bp, phy,
+ MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD, cl37_val);
+ msleep(500);
+}
- /* Release srst bit */
- bnx2x_cl45_write(bp, port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_GEN_CTRL,
- MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
+static u8 bnx2x_8073_config_init(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
+{
+ struct bnx2x *bp = params->bp;
+ u16 val = 0, tmp1;
+ u8 gpio_port;
+ DP(NETIF_MSG_LINK, "Init 8073\n");
- /* wait for 100ms for code download via SPI port */
- msleep(100);
+ if (CHIP_IS_E2(bp))
+ gpio_port = BP_PATH(bp);
+ else
+ gpio_port = params->port;
+ /* Restore normal power mode*/
+ bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
+ MISC_REGISTERS_GPIO_OUTPUT_HIGH, gpio_port);
- /* Clear ser_boot_ctl bit */
- bnx2x_cl45_write(bp, port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_MISC_CTRL1, 0x0000);
+ bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
+ MISC_REGISTERS_GPIO_OUTPUT_HIGH, gpio_port);
- bnx2x_save_bcm_spirom_ver(bp, port,
- ext_phy_type,
- ext_phy_addr,
- shmem_base);
-}
+ /* enable LASI */
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM_CTRL, (1<<2));
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 0x0004);
-static void bnx2x_bcm8073_external_rom_boot(struct bnx2x *bp, u8 port,
- u8 ext_phy_addr,
- u32 shmem_base)
-{
- bnx2x_bcm8073_bcm8727_external_rom_boot(bp, port, ext_phy_addr,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
- shmem_base);
-}
+ bnx2x_8073_set_pause_cl37(params, phy, vars);
-static void bnx2x_bcm8727_external_rom_boot(struct bnx2x *bp, u8 port,
- u8 ext_phy_addr,
- u32 shmem_base)
-{
- bnx2x_bcm8073_bcm8727_external_rom_boot(bp, port, ext_phy_addr,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
- shmem_base);
+ bnx2x_8073_set_xaui_low_power_mode(bp, phy);
-}
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_M8051_MSGOUT_REG, &tmp1);
-static void bnx2x_bcm8726_external_rom_boot(struct link_params *params)
-{
- struct bnx2x *bp = params->bp;
- u8 port = params->port;
- u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
- u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM, &tmp1);
- /* Need to wait 100ms after reset */
- msleep(100);
+ DP(NETIF_MSG_LINK, "Before rom RX_ALARM(port1): 0x%x\n", tmp1);
- /* Micro controller re-boot */
- bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_GEN_CTRL,
- 0x018B);
+ /* Enable CL37 BAM */
+ bnx2x_cl45_read(bp, phy,
+ MDIO_AN_DEVAD,
+ MDIO_AN_REG_8073_BAM, &val);
+ bnx2x_cl45_write(bp, phy,
+ MDIO_AN_DEVAD,
+ MDIO_AN_REG_8073_BAM, val | 1);
- /* Set soft reset */
- bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_GEN_CTRL,
- MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET);
+ if (params->loopback_mode == LOOPBACK_EXT) {
+ bnx2x_807x_force_10G(bp, phy);
+ DP(NETIF_MSG_LINK, "Forced speed 10G on 807X\n");
+ return 0;
+ } else {
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_BCM_CTRL, 0x0002);
+ }
+ if (phy->req_line_speed != SPEED_AUTO_NEG) {
+ if (phy->req_line_speed == SPEED_10000) {
+ val = (1<<7);
+ } else if (phy->req_line_speed == SPEED_2500) {
+ val = (1<<5);
+ /* Note that 2.5G works only
+ when used with 1G advertisment */
+ } else
+ val = (1<<5);
+ } else {
+ val = 0;
+ if (phy->speed_cap_mask &
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
+ val |= (1<<7);
+
+ /* Note that 2.5G works only when
+ used with 1G advertisment */
+ if (phy->speed_cap_mask &
+ (PORT_HW_CFG_SPEED_CAPABILITY_D0_1G |
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G))
+ val |= (1<<5);
+ DP(NETIF_MSG_LINK, "807x autoneg val = 0x%x\n", val);
+ }
- bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_MISC_CTRL1, 0x0001);
+ bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV, val);
+ bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_8073_2_5G, &tmp1);
+
+ if (((phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G) &&
+ (phy->req_line_speed == SPEED_AUTO_NEG)) ||
+ (phy->req_line_speed == SPEED_2500)) {
+ u16 phy_ver;
+ /* Allow 2.5G for A1 and above */
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_8073_CHIP_REV,
+ &phy_ver);
+ DP(NETIF_MSG_LINK, "Add 2.5G\n");
+ if (phy_ver > 0)
+ tmp1 |= 1;
+ else
+ tmp1 &= 0xfffe;
+ } else {
+ DP(NETIF_MSG_LINK, "Disable 2.5G\n");
+ tmp1 &= 0xfffe;
+ }
- bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_GEN_CTRL,
- MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
+ bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_8073_2_5G, tmp1);
+ /* Add support for CL37 (passive mode) II */
- /* wait for 150ms for microcode load */
- msleep(150);
+ bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD, &tmp1);
+ bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD,
+ (tmp1 | ((phy->req_duplex == DUPLEX_FULL) ?
+ 0x20 : 0x40)));
- /* Disable serial boot control, tristates pins SS_N, SCK, MOSI, MISO */
- bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_MISC_CTRL1, 0x0000);
+ /* Add support for CL37 (passive mode) III */
+ bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_AN, 0x1000);
- msleep(200);
- bnx2x_save_bcm_spirom_ver(bp, port,
- ext_phy_type,
- ext_phy_addr,
- params->shmem_base);
+ /* The SNR will improve about 2db by changing
+ BW and FEE main tap. Rest commands are executed
+ after link is up*/
+ if (bnx2x_8073_is_snr_needed(bp, phy))
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_EDC_FFE_MAIN,
+ 0xFB0C);
+
+ /* Enable FEC (Forware Error Correction) Request in the AN */
+ bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV2, &tmp1);
+ tmp1 |= (1<<15);
+ bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV2, tmp1);
+
+ bnx2x_ext_phy_set_pause(params, phy, vars);
+
+ /* Restart autoneg */
+ msleep(500);
+ bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x1200);
+ DP(NETIF_MSG_LINK, "807x Autoneg Restart: Advertise 1G=%x, 10G=%x\n",
+ ((val & (1<<5)) > 0), ((val & (1<<7)) > 0));
+ return 0;
+}
+
+static u8 bnx2x_8073_read_status(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
+{
+ struct bnx2x *bp = params->bp;
+ u8 link_up = 0;
+ u16 val1, val2;
+ u16 link_status = 0;
+ u16 an1000_status = 0;
+
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, &val1);
+
+ DP(NETIF_MSG_LINK, "8703 LASI status 0x%x\n", val1);
+
+ /* clear the interrupt LASI status register */
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PCS_DEVAD, MDIO_PCS_REG_STATUS, &val2);
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PCS_DEVAD, MDIO_PCS_REG_STATUS, &val1);
+ DP(NETIF_MSG_LINK, "807x PCS status 0x%x->0x%x\n", val2, val1);
+ /* Clear MSG-OUT */
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_M8051_MSGOUT_REG, &val1);
+
+ /* Check the LASI */
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM, &val2);
+
+ DP(NETIF_MSG_LINK, "KR 0x9003 0x%x\n", val2);
+
+ /* Check the link status */
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PCS_DEVAD, MDIO_PCS_REG_STATUS, &val2);
+ DP(NETIF_MSG_LINK, "KR PCS status 0x%x\n", val2);
+
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val2);
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val1);
+ link_up = ((val1 & 4) == 4);
+ DP(NETIF_MSG_LINK, "PMA_REG_STATUS=0x%x\n", val1);
+
+ if (link_up &&
+ ((phy->req_line_speed != SPEED_10000))) {
+ if (bnx2x_8073_xaui_wa(bp, phy) != 0)
+ return 0;
+ }
+ bnx2x_cl45_read(bp, phy,
+ MDIO_AN_DEVAD, MDIO_AN_REG_LINK_STATUS, &an1000_status);
+ bnx2x_cl45_read(bp, phy,
+ MDIO_AN_DEVAD, MDIO_AN_REG_LINK_STATUS, &an1000_status);
+
+ /* Check the link status on 1.1.2 */
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val2);
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val1);
+ DP(NETIF_MSG_LINK, "KR PMA status 0x%x->0x%x,"
+ "an_link_status=0x%x\n", val2, val1, an1000_status);
+
+ link_up = (((val1 & 4) == 4) || (an1000_status & (1<<1)));
+ if (link_up && bnx2x_8073_is_snr_needed(bp, phy)) {
+ /* The SNR will improve about 2dbby
+ changing the BW and FEE main tap.*/
+ /* The 1st write to change FFE main
+ tap is set before restart AN */
+ /* Change PLL Bandwidth in EDC
+ register */
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_PLL_BANDWIDTH,
+ 0x26BC);
+
+ /* Change CDR Bandwidth in EDC register */
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_CDR_BANDWIDTH,
+ 0x0333);
+ }
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_8073_SPEED_LINK_STATUS,
+ &link_status);
+
+ /* Bits 0..2 --> speed detected, bits 13..15--> link is down */
+ if ((link_status & (1<<2)) && (!(link_status & (1<<15)))) {
+ link_up = 1;
+ vars->line_speed = SPEED_10000;
+ DP(NETIF_MSG_LINK, "port %x: External link up in 10G\n",
+ params->port);
+ } else if ((link_status & (1<<1)) && (!(link_status & (1<<14)))) {
+ link_up = 1;
+ vars->line_speed = SPEED_2500;
+ DP(NETIF_MSG_LINK, "port %x: External link up in 2.5G\n",
+ params->port);
+ } else if ((link_status & (1<<0)) && (!(link_status & (1<<13)))) {
+ link_up = 1;
+ vars->line_speed = SPEED_1000;
+ DP(NETIF_MSG_LINK, "port %x: External link up in 1G\n",
+ params->port);
+ } else {
+ link_up = 0;
+ DP(NETIF_MSG_LINK, "port %x: External link is down\n",
+ params->port);
+ }
+
+ if (link_up) {
+ bnx2x_ext_phy_10G_an_resolve(bp, phy, vars);
+ bnx2x_8073_resolve_fc(phy, params, vars);
+ }
+ return link_up;
+}
+
+static void bnx2x_8073_link_reset(struct bnx2x_phy *phy,
+ struct link_params *params)
+{
+ struct bnx2x *bp = params->bp;
+ u8 gpio_port;
+ if (CHIP_IS_E2(bp))
+ gpio_port = BP_PATH(bp);
+ else
+ gpio_port = params->port;
+ DP(NETIF_MSG_LINK, "Setting 8073 port %d into low power mode\n",
+ gpio_port);
+ bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
+ MISC_REGISTERS_GPIO_OUTPUT_LOW,
+ gpio_port);
+}
+
+/******************************************************************/
+/* BCM8705 PHY SECTION */
+/******************************************************************/
+static u8 bnx2x_8705_config_init(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
+{
+ struct bnx2x *bp = params->bp;
+ DP(NETIF_MSG_LINK, "init 8705\n");
+ /* Restore normal power mode*/
+ bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
+ MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
+ /* HW reset */
+ bnx2x_ext_phy_hw_reset(bp, params->port);
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0xa040);
+ bnx2x_wait_reset_complete(bp, phy);
+
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_MISC_CTRL, 0x8288);
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, 0x7fbf);
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_CMU_PLL_BYPASS, 0x0100);
+ bnx2x_cl45_write(bp, phy,
+ MDIO_WIS_DEVAD, MDIO_WIS_REG_LASI_CNTL, 0x1);
+ /* BCM8705 doesn't have microcode, hence the 0 */
+ bnx2x_save_spirom_version(bp, params->port, params->shmem_base, 0);
+ return 0;
+}
+
+static u8 bnx2x_8705_read_status(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
+{
+ u8 link_up = 0;
+ u16 val1, rx_sd;
+ struct bnx2x *bp = params->bp;
+ DP(NETIF_MSG_LINK, "read status 8705\n");
+ bnx2x_cl45_read(bp, phy,
+ MDIO_WIS_DEVAD, MDIO_WIS_REG_LASI_STATUS, &val1);
+ DP(NETIF_MSG_LINK, "8705 LASI status 0x%x\n", val1);
+
+ bnx2x_cl45_read(bp, phy,
+ MDIO_WIS_DEVAD, MDIO_WIS_REG_LASI_STATUS, &val1);
+ DP(NETIF_MSG_LINK, "8705 LASI status 0x%x\n", val1);
+
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_SD, &rx_sd);
+
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD, 0xc809, &val1);
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD, 0xc809, &val1);
+
+ DP(NETIF_MSG_LINK, "8705 1.c809 val=0x%x\n", val1);
+ link_up = ((rx_sd & 0x1) && (val1 & (1<<9)) && ((val1 & (1<<8)) == 0));
+ if (link_up) {
+ vars->line_speed = SPEED_10000;
+ bnx2x_ext_phy_resolve_fc(phy, params, vars);
+ }
+ return link_up;
}
-static void bnx2x_sfp_set_transmitter(struct bnx2x *bp, u8 port,
- u32 ext_phy_type, u8 ext_phy_addr,
- u8 tx_en)
+/******************************************************************/
+/* SFP+ module Section */
+/******************************************************************/
+static void bnx2x_sfp_set_transmitter(struct bnx2x *bp,
+ struct bnx2x_phy *phy,
+ u8 port,
+ u8 tx_en)
{
u16 val;
DP(NETIF_MSG_LINK, "Setting transmitter tx_en=%x for port %x\n",
tx_en, port);
/* Disable/Enable transmitter ( TX laser of the SFP+ module.)*/
- bnx2x_cl45_read(bp, port,
- ext_phy_type,
- ext_phy_addr,
+ bnx2x_cl45_read(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_PHY_IDENTIFIER,
&val);
@@ -2651,58 +3942,42 @@ static void bnx2x_sfp_set_transmitter(struct bnx2x *bp, u8 port,
else
val |= (1<<15);
- bnx2x_cl45_write(bp, port,
- ext_phy_type,
- ext_phy_addr,
+ bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_PHY_IDENTIFIER,
val);
}
-static u8 bnx2x_8726_read_sfp_module_eeprom(struct link_params *params,
+static u8 bnx2x_8726_read_sfp_module_eeprom(struct bnx2x_phy *phy,
+ struct link_params *params,
u16 addr, u8 byte_cnt, u8 *o_buf)
{
struct bnx2x *bp = params->bp;
u16 val = 0;
u16 i;
- u8 port = params->port;
- u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
- u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
-
if (byte_cnt > 16) {
DP(NETIF_MSG_LINK, "Reading from eeprom is"
" is limited to 0xf\n");
return -EINVAL;
}
/* Set the read command byte count */
- bnx2x_cl45_write(bp, port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_SFP_TWO_WIRE_BYTE_CNT,
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_SFP_TWO_WIRE_BYTE_CNT,
(byte_cnt | 0xa000));
/* Set the read command address */
- bnx2x_cl45_write(bp, port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_SFP_TWO_WIRE_MEM_ADDR,
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_SFP_TWO_WIRE_MEM_ADDR,
addr);
/* Activate read command */
- bnx2x_cl45_write(bp, port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_SFP_TWO_WIRE_CTRL,
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_SFP_TWO_WIRE_CTRL,
0x2c0f);
/* Wait up to 500us for command complete status */
for (i = 0; i < 100; i++) {
- bnx2x_cl45_read(bp, port,
- ext_phy_type,
- ext_phy_addr,
+ bnx2x_cl45_read(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val);
if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
@@ -2721,18 +3996,14 @@ static u8 bnx2x_8726_read_sfp_module_eeprom(struct link_params *params,
/* Read the buffer */
for (i = 0; i < byte_cnt; i++) {
- bnx2x_cl45_read(bp, port,
- ext_phy_type,
- ext_phy_addr,
+ bnx2x_cl45_read(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_8726_TWO_WIRE_DATA_BUF + i, &val);
o_buf[i] = (u8)(val & MDIO_PMA_REG_8726_TWO_WIRE_DATA_MASK);
}
for (i = 0; i < 100; i++) {
- bnx2x_cl45_read(bp, port,
- ext_phy_type,
- ext_phy_addr,
+ bnx2x_cl45_read(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val);
if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
@@ -2743,14 +4014,12 @@ static u8 bnx2x_8726_read_sfp_module_eeprom(struct link_params *params,
return -EINVAL;
}
-static u8 bnx2x_8727_read_sfp_module_eeprom(struct link_params *params,
+static u8 bnx2x_8727_read_sfp_module_eeprom(struct bnx2x_phy *phy,
+ struct link_params *params,
u16 addr, u8 byte_cnt, u8 *o_buf)
{
struct bnx2x *bp = params->bp;
u16 val, i;
- u8 port = params->port;
- u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
- u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
if (byte_cnt > 16) {
DP(NETIF_MSG_LINK, "Reading from eeprom is"
@@ -2759,40 +4028,30 @@ static u8 bnx2x_8727_read_sfp_module_eeprom(struct link_params *params,
}
/* Need to read from 1.8000 to clear it */
- bnx2x_cl45_read(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
- ext_phy_addr,
+ bnx2x_cl45_read(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_SFP_TWO_WIRE_CTRL,
&val);
/* Set the read command byte count */
- bnx2x_cl45_write(bp, port,
- ext_phy_type,
- ext_phy_addr,
+ bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_SFP_TWO_WIRE_BYTE_CNT,
((byte_cnt < 2) ? 2 : byte_cnt));
/* Set the read command address */
- bnx2x_cl45_write(bp, port,
- ext_phy_type,
- ext_phy_addr,
+ bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_SFP_TWO_WIRE_MEM_ADDR,
addr);
/* Set the destination address */
- bnx2x_cl45_write(bp, port,
- ext_phy_type,
- ext_phy_addr,
+ bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD,
0x8004,
MDIO_PMA_REG_8727_TWO_WIRE_DATA_BUF);
/* Activate read command */
- bnx2x_cl45_write(bp, port,
- ext_phy_type,
- ext_phy_addr,
+ bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_SFP_TWO_WIRE_CTRL,
0x8002);
@@ -2802,9 +4061,7 @@ static u8 bnx2x_8727_read_sfp_module_eeprom(struct link_params *params,
/* Wait up to 500us for command complete status */
for (i = 0; i < 100; i++) {
- bnx2x_cl45_read(bp, port,
- ext_phy_type,
- ext_phy_addr,
+ bnx2x_cl45_read(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val);
if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
@@ -2823,18 +4080,14 @@ static u8 bnx2x_8727_read_sfp_module_eeprom(struct link_params *params,
/* Read the buffer */
for (i = 0; i < byte_cnt; i++) {
- bnx2x_cl45_read(bp, port,
- ext_phy_type,
- ext_phy_addr,
+ bnx2x_cl45_read(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_8727_TWO_WIRE_DATA_BUF + i, &val);
o_buf[i] = (u8)(val & MDIO_PMA_REG_8727_TWO_WIRE_DATA_MASK);
}
for (i = 0; i < 100; i++) {
- bnx2x_cl45_read(bp, port,
- ext_phy_type,
- ext_phy_addr,
+ bnx2x_cl45_read(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val);
if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
@@ -2846,21 +4099,21 @@ static u8 bnx2x_8727_read_sfp_module_eeprom(struct link_params *params,
return -EINVAL;
}
-u8 bnx2x_read_sfp_module_eeprom(struct link_params *params, u16 addr,
+u8 bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy,
+ struct link_params *params, u16 addr,
u8 byte_cnt, u8 *o_buf)
{
- u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
-
- if (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726)
- return bnx2x_8726_read_sfp_module_eeprom(params, addr,
+ if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726)
+ return bnx2x_8726_read_sfp_module_eeprom(phy, params, addr,
byte_cnt, o_buf);
- else if (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727)
- return bnx2x_8727_read_sfp_module_eeprom(params, addr,
+ else if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727)
+ return bnx2x_8727_read_sfp_module_eeprom(phy, params, addr,
byte_cnt, o_buf);
return -EINVAL;
}
-static u8 bnx2x_get_edc_mode(struct link_params *params,
+static u8 bnx2x_get_edc_mode(struct bnx2x_phy *phy,
+ struct link_params *params,
u16 *edc_mode)
{
struct bnx2x *bp = params->bp;
@@ -2868,10 +4121,11 @@ static u8 bnx2x_get_edc_mode(struct link_params *params,
*edc_mode = EDC_MODE_LIMITING;
/* First check for copper cable */
- if (bnx2x_read_sfp_module_eeprom(params,
- SFP_EEPROM_CON_TYPE_ADDR,
- 1,
- &val) != 0) {
+ if (bnx2x_read_sfp_module_eeprom(phy,
+ params,
+ SFP_EEPROM_CON_TYPE_ADDR,
+ 1,
+ &val) != 0) {
DP(NETIF_MSG_LINK, "Failed to read from SFP+ module EEPROM\n");
return -EINVAL;
}
@@ -2883,7 +4137,8 @@ static u8 bnx2x_get_edc_mode(struct link_params *params,
/* Check if its active cable( includes SFP+ module)
of passive cable*/
- if (bnx2x_read_sfp_module_eeprom(params,
+ if (bnx2x_read_sfp_module_eeprom(phy,
+ params,
SFP_EEPROM_FC_TX_TECH_ADDR,
1,
&copper_module_type) !=
@@ -2923,10 +4178,11 @@ static u8 bnx2x_get_edc_mode(struct link_params *params,
if (check_limiting_mode) {
u8 options[SFP_EEPROM_OPTIONS_SIZE];
- if (bnx2x_read_sfp_module_eeprom(params,
- SFP_EEPROM_OPTIONS_ADDR,
- SFP_EEPROM_OPTIONS_SIZE,
- options) != 0) {
+ if (bnx2x_read_sfp_module_eeprom(phy,
+ params,
+ SFP_EEPROM_OPTIONS_ADDR,
+ SFP_EEPROM_OPTIONS_SIZE,
+ options) != 0) {
DP(NETIF_MSG_LINK, "Failed to read Option"
" field from module EEPROM\n");
return -EINVAL;
@@ -2939,17 +4195,17 @@ static u8 bnx2x_get_edc_mode(struct link_params *params,
DP(NETIF_MSG_LINK, "EDC mode is set to 0x%x\n", *edc_mode);
return 0;
}
-
/* This function read the relevant field from the module ( SFP+ ),
and verify it is compliant with this board */
-static u8 bnx2x_verify_sfp_module(struct link_params *params)
+static u8 bnx2x_verify_sfp_module(struct bnx2x_phy *phy,
+ struct link_params *params)
{
struct bnx2x *bp = params->bp;
- u32 val;
- u32 fw_resp;
+ u32 val, cmd;
+ u32 fw_resp, fw_cmd_param;
char vendor_name[SFP_EEPROM_VENDOR_NAME_SIZE+1];
char vendor_pn[SFP_EEPROM_PART_NO_SIZE+1];
-
+ phy->flags &= ~FLAGS_SFP_NOT_APPROVED;
val = REG_RD(bp, params->shmem_base +
offsetof(struct shmem_region, dev_info.
port_feature_config[params->port].config));
@@ -2959,29 +4215,44 @@ static u8 bnx2x_verify_sfp_module(struct link_params *params)
return 0;
}
- /* Ask the FW to validate the module */
- if (!(params->feature_config_flags &
- FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY)) {
+ if (params->feature_config_flags &
+ FEATURE_CONFIG_BC_SUPPORTS_DUAL_PHY_OPT_MDL_VRFY) {
+ /* Use specific phy request */
+ cmd = DRV_MSG_CODE_VRFY_SPECIFIC_PHY_OPT_MDL;
+ } else if (params->feature_config_flags &
+ FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY) {
+ /* Use first phy request only in case of non-dual media*/
+ if (DUAL_MEDIA(params)) {
+ DP(NETIF_MSG_LINK, "FW does not support OPT MDL "
+ "verification\n");
+ return -EINVAL;
+ }
+ cmd = DRV_MSG_CODE_VRFY_FIRST_PHY_OPT_MDL;
+ } else {
+ /* No support in OPT MDL detection */
DP(NETIF_MSG_LINK, "FW does not support OPT MDL "
- "verification\n");
+ "verification\n");
return -EINVAL;
}
- fw_resp = bnx2x_fw_command(bp, DRV_MSG_CODE_VRFY_OPT_MDL);
+ fw_cmd_param = FW_PARAM_SET(phy->addr, phy->type, phy->mdio_ctrl);
+ fw_resp = bnx2x_fw_command(bp, cmd, fw_cmd_param);
if (fw_resp == FW_MSG_CODE_VRFY_OPT_MDL_SUCCESS) {
DP(NETIF_MSG_LINK, "Approved module\n");
return 0;
}
/* format the warning message */
- if (bnx2x_read_sfp_module_eeprom(params,
+ if (bnx2x_read_sfp_module_eeprom(phy,
+ params,
SFP_EEPROM_VENDOR_NAME_ADDR,
SFP_EEPROM_VENDOR_NAME_SIZE,
(u8 *)vendor_name))
vendor_name[0] = '\0';
else
vendor_name[SFP_EEPROM_VENDOR_NAME_SIZE] = '\0';
- if (bnx2x_read_sfp_module_eeprom(params,
+ if (bnx2x_read_sfp_module_eeprom(phy,
+ params,
SFP_EEPROM_PART_NO_ADDR,
SFP_EEPROM_PART_NO_SIZE,
(u8 *)vendor_pn))
@@ -2989,22 +4260,78 @@ static u8 bnx2x_verify_sfp_module(struct link_params *params)
else
vendor_pn[SFP_EEPROM_PART_NO_SIZE] = '\0';
- netdev_info(bp->dev, "Warning: Unqualified SFP+ module detected, Port %d from %s part number %s\n",
+ netdev_info(bp->dev, "Warning: Unqualified SFP+ module detected,"
+ " Port %d from %s part number %s\n",
params->port, vendor_name, vendor_pn);
+ phy->flags |= FLAGS_SFP_NOT_APPROVED;
return -EINVAL;
}
-static u8 bnx2x_bcm8726_set_limiting_mode(struct link_params *params,
- u16 edc_mode)
+static u8 bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy,
+ struct link_params *params)
+
{
+ u8 val;
struct bnx2x *bp = params->bp;
- u8 port = params->port;
- u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
+ u16 timeout;
+ /* Initialization time after hot-plug may take up to 300ms for some
+ phys type ( e.g. JDSU ) */
+ for (timeout = 0; timeout < 60; timeout++) {
+ if (bnx2x_read_sfp_module_eeprom(phy, params, 1, 1, &val)
+ == 0) {
+ DP(NETIF_MSG_LINK, "SFP+ module initialization "
+ "took %d ms\n", timeout * 5);
+ return 0;
+ }
+ msleep(5);
+ }
+ return -EINVAL;
+}
+
+static void bnx2x_8727_power_module(struct bnx2x *bp,
+ struct bnx2x_phy *phy,
+ u8 is_power_up) {
+ /* Make sure GPIOs are not using for LED mode */
+ u16 val;
+ /*
+ * In the GPIO register, bit 4 is use to detemine if the GPIOs are
+ * operating as INPUT or as OUTPUT. Bit 1 is for input, and 0 for
+ * output
+ * Bits 0-1 determine the gpios value for OUTPUT in case bit 4 val is 0
+ * Bits 8-9 determine the gpios value for INPUT in case bit 4 val is 1
+ * where the 1st bit is the over-current(only input), and 2nd bit is
+ * for power( only output )
+ */
+
+ /*
+ * In case of NOC feature is disabled and power is up, set GPIO control
+ * as input to enable listening of over-current indication
+ */
+ if (phy->flags & FLAGS_NOC)
+ return;
+ if (!(phy->flags &
+ FLAGS_NOC) && is_power_up)
+ val = (1<<4);
+ else
+ /*
+ * Set GPIO control to OUTPUT, and set the power bit
+ * to according to the is_power_up
+ */
+ val = ((!(is_power_up)) << 1);
+
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8727_GPIO_CTRL,
+ val);
+}
+
+static u8 bnx2x_8726_set_limiting_mode(struct bnx2x *bp,
+ struct bnx2x_phy *phy,
+ u16 edc_mode)
+{
u16 cur_limiting_mode;
- bnx2x_cl45_read(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726,
- ext_phy_addr,
+ bnx2x_cl45_read(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_ROM_VER2,
&cur_limiting_mode);
@@ -3014,12 +4341,10 @@ static u8 bnx2x_bcm8726_set_limiting_mode(struct link_params *params,
if (edc_mode == EDC_MODE_LIMITING) {
DP(NETIF_MSG_LINK,
"Setting LIMITING MODE\n");
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_ROM_VER2,
- EDC_MODE_LIMITING);
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_ROM_VER2,
+ EDC_MODE_LIMITING);
} else { /* LRM mode ( default )*/
DP(NETIF_MSG_LINK, "Setting LRM MODE\n");
@@ -3030,27 +4355,19 @@ static u8 bnx2x_bcm8726_set_limiting_mode(struct link_params *params,
if (cur_limiting_mode != EDC_MODE_LIMITING)
return 0;
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726,
- ext_phy_addr,
+ bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_LRM_MODE,
0);
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726,
- ext_phy_addr,
+ bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_ROM_VER2,
0x128);
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726,
- ext_phy_addr,
+ bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_MISC_CTRL0,
0x4008);
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726,
- ext_phy_addr,
+ bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_LRM_MODE,
0xaaaa);
@@ -3058,46 +4375,33 @@ static u8 bnx2x_bcm8726_set_limiting_mode(struct link_params *params,
return 0;
}
-static u8 bnx2x_bcm8727_set_limiting_mode(struct link_params *params,
+static u8 bnx2x_8727_set_limiting_mode(struct bnx2x *bp,
+ struct bnx2x_phy *phy,
u16 edc_mode)
{
- struct bnx2x *bp = params->bp;
- u8 port = params->port;
u16 phy_identifier;
u16 rom_ver2_val;
- u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
-
- bnx2x_cl45_read(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
- ext_phy_addr,
+ bnx2x_cl45_read(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_PHY_IDENTIFIER,
&phy_identifier);
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
- ext_phy_addr,
+ bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_PHY_IDENTIFIER,
(phy_identifier & ~(1<<9)));
- bnx2x_cl45_read(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
- ext_phy_addr,
+ bnx2x_cl45_read(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_ROM_VER2,
&rom_ver2_val);
/* Keep the MSB 8-bits, and set the LSB 8-bits with the edc_mode */
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
- ext_phy_addr,
+ bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_ROM_VER2,
(rom_ver2_val & 0xff00) | (edc_mode & 0x00ff));
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
- ext_phy_addr,
+ bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_PHY_IDENTIFIER,
(phy_identifier | (1<<9)));
@@ -3105,72 +4409,34 @@ static u8 bnx2x_bcm8727_set_limiting_mode(struct link_params *params,
return 0;
}
-
-static u8 bnx2x_wait_for_sfp_module_initialized(struct link_params *params)
+static void bnx2x_8727_specific_func(struct bnx2x_phy *phy,
+ struct link_params *params,
+ u32 action)
{
- u8 val;
struct bnx2x *bp = params->bp;
- u16 timeout;
- /* Initialization time after hot-plug may take up to 300ms for some
- phys type ( e.g. JDSU ) */
- for (timeout = 0; timeout < 60; timeout++) {
- if (bnx2x_read_sfp_module_eeprom(params, 1, 1, &val)
- == 0) {
- DP(NETIF_MSG_LINK, "SFP+ module initialization "
- "took %d ms\n", timeout * 5);
- return 0;
- }
- msleep(5);
- }
- return -EINVAL;
-}
-static void bnx2x_8727_power_module(struct bnx2x *bp,
- struct link_params *params,
- u8 ext_phy_addr, u8 is_power_up) {
- /* Make sure GPIOs are not using for LED mode */
- u16 val;
- u8 port = params->port;
- /*
- * In the GPIO register, bit 4 is use to detemine if the GPIOs are
- * operating as INPUT or as OUTPUT. Bit 1 is for input, and 0 for
- * output
- * Bits 0-1 determine the gpios value for OUTPUT in case bit 4 val is 0
- * Bits 8-9 determine the gpios value for INPUT in case bit 4 val is 1
- * where the 1st bit is the over-current(only input), and 2nd bit is
- * for power( only output )
- */
-
- /*
- * In case of NOC feature is disabled and power is up, set GPIO control
- * as input to enable listening of over-current indication
- */
-
- if (!(params->feature_config_flags &
- FEATURE_CONFIG_BCM8727_NOC) && is_power_up)
- val = (1<<4);
- else
- /*
- * Set GPIO control to OUTPUT, and set the power bit
- * to according to the is_power_up
- */
- val = ((!(is_power_up)) << 1);
-
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_8727_GPIO_CTRL,
- val);
+ switch (action) {
+ case DISABLE_TX:
+ bnx2x_sfp_set_transmitter(bp, phy, params->port, 0);
+ break;
+ case ENABLE_TX:
+ if (!(phy->flags & FLAGS_SFP_NOT_APPROVED))
+ bnx2x_sfp_set_transmitter(bp, phy, params->port, 1);
+ break;
+ default:
+ DP(NETIF_MSG_LINK, "Function 0x%x not supported by 8727\n",
+ action);
+ return;
+ }
}
-static u8 bnx2x_sfp_module_detection(struct link_params *params)
+static u8 bnx2x_sfp_module_detection(struct bnx2x_phy *phy,
+ struct link_params *params)
{
struct bnx2x *bp = params->bp;
u16 edc_mode;
u8 rc = 0;
- u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
- u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
+
u32 val = REG_RD(bp, params->shmem_base +
offsetof(struct shmem_region, dev_info.
port_feature_config[params->port].config));
@@ -3178,10 +4444,10 @@ static u8 bnx2x_sfp_module_detection(struct link_params *params)
DP(NETIF_MSG_LINK, "SFP+ module plugged in/out detected on port %d\n",
params->port);
- if (bnx2x_get_edc_mode(params, &edc_mode) != 0) {
+ if (bnx2x_get_edc_mode(phy, params, &edc_mode) != 0) {
DP(NETIF_MSG_LINK, "Failed to get valid module type\n");
return -EINVAL;
- } else if (bnx2x_verify_sfp_module(params) !=
+ } else if (bnx2x_verify_sfp_module(phy, params) !=
0) {
/* check SFP+ module compatibility */
DP(NETIF_MSG_LINK, "Module verification failed!!\n");
@@ -3190,13 +4456,12 @@ static u8 bnx2x_sfp_module_detection(struct link_params *params)
bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
MISC_REGISTERS_GPIO_HIGH,
params->port);
- if ((ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727) &&
+ if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727) &&
((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_POWER_DOWN)) {
/* Shutdown SFP+ module */
DP(NETIF_MSG_LINK, "Shutdown SFP+ module!!\n");
- bnx2x_8727_power_module(bp, params,
- ext_phy_addr, 0);
+ bnx2x_8727_power_module(bp, phy, 0);
return rc;
}
} else {
@@ -3208,15 +4473,15 @@ static u8 bnx2x_sfp_module_detection(struct link_params *params)
}
/* power up the SFP module */
- if (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727)
- bnx2x_8727_power_module(bp, params, ext_phy_addr, 1);
+ if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727)
+ bnx2x_8727_power_module(bp, phy, 1);
/* Check and set limiting mode / LRM mode on 8726.
On 8727 it is done automatically */
- if (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726)
- bnx2x_bcm8726_set_limiting_mode(params, edc_mode);
+ if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726)
+ bnx2x_8726_set_limiting_mode(bp, phy, edc_mode);
else
- bnx2x_bcm8727_set_limiting_mode(params, edc_mode);
+ bnx2x_8727_set_limiting_mode(bp, phy, edc_mode);
/*
* Enable transmit for this module if the module is approved, or
* if unapproved modules should also enable the Tx laser
@@ -3224,11 +4489,9 @@ static u8 bnx2x_sfp_module_detection(struct link_params *params)
if (rc == 0 ||
(val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) !=
PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)
- bnx2x_sfp_set_transmitter(bp, params->port,
- ext_phy_type, ext_phy_addr, 1);
+ bnx2x_sfp_set_transmitter(bp, phy, params->port, 1);
else
- bnx2x_sfp_set_transmitter(bp, params->port,
- ext_phy_type, ext_phy_addr, 0);
+ bnx2x_sfp_set_transmitter(bp, phy, params->port, 0);
return rc;
}
@@ -3236,6 +4499,7 @@ static u8 bnx2x_sfp_module_detection(struct link_params *params)
void bnx2x_handle_module_detect_int(struct link_params *params)
{
struct bnx2x *bp = params->bp;
+ struct bnx2x_phy *phy = &params->phy[EXT_PHY1];
u32 gpio_val;
u8 port = params->port;
@@ -3245,1349 +4509,587 @@ void bnx2x_handle_module_detect_int(struct link_params *params)
params->port);
/* Get current gpio val refelecting module plugged in / out*/
- gpio_val = bnx2x_get_gpio(bp, MISC_REGISTERS_GPIO_3, port);
+ gpio_val = bnx2x_get_gpio(bp, MISC_REGISTERS_GPIO_3, port);
/* Call the handling function in case module is detected */
if (gpio_val == 0) {
bnx2x_set_gpio_int(bp, MISC_REGISTERS_GPIO_3,
- MISC_REGISTERS_GPIO_INT_OUTPUT_CLR,
- port);
+ MISC_REGISTERS_GPIO_INT_OUTPUT_CLR,
+ port);
- if (bnx2x_wait_for_sfp_module_initialized(params) ==
- 0)
- bnx2x_sfp_module_detection(params);
+ if (bnx2x_wait_for_sfp_module_initialized(phy, params) == 0)
+ bnx2x_sfp_module_detection(phy, params);
else
DP(NETIF_MSG_LINK, "SFP+ module is not initialized\n");
} else {
- u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
-
- u32 ext_phy_type =
- XGXS_EXT_PHY_TYPE(params->ext_phy_config);
u32 val = REG_RD(bp, params->shmem_base +
offsetof(struct shmem_region, dev_info.
port_feature_config[params->port].
config));
bnx2x_set_gpio_int(bp, MISC_REGISTERS_GPIO_3,
- MISC_REGISTERS_GPIO_INT_OUTPUT_SET,
- port);
+ MISC_REGISTERS_GPIO_INT_OUTPUT_SET,
+ port);
/* Module was plugged out. */
/* Disable transmit for this module */
if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)
- bnx2x_sfp_set_transmitter(bp, params->port,
- ext_phy_type, ext_phy_addr, 0);
+ bnx2x_sfp_set_transmitter(bp, phy, params->port, 0);
}
}
-static void bnx2x_bcm807x_force_10G(struct link_params *params)
-{
- struct bnx2x *bp = params->bp;
- u8 port = params->port;
- u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
- u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
-
- /* Force KR or KX */
- bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_CTRL,
- 0x2040);
- bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_10G_CTRL2,
- 0x000b);
- bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_BCM_CTRL,
- 0x0000);
- bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_CTRL,
- 0x0000);
-}
-
-static void bnx2x_bcm8073_set_xaui_low_power_mode(struct link_params *params)
+/******************************************************************/
+/* common BCM8706/BCM8726 PHY SECTION */
+/******************************************************************/
+static u8 bnx2x_8706_8726_read_status(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
{
+ u8 link_up = 0;
+ u16 val1, val2, rx_sd, pcs_status;
struct bnx2x *bp = params->bp;
- u8 port = params->port;
- u16 val;
- u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
- u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
-
- bnx2x_cl45_read(bp, params->port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_8073_CHIP_REV, &val);
-
- if (val == 0) {
- /* Mustn't set low power mode in 8073 A0 */
- return;
+ DP(NETIF_MSG_LINK, "XGXS 8706/8726\n");
+ /* Clear RX Alarm*/
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM, &val2);
+ /* clear LASI indication*/
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, &val1);
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, &val2);
+ DP(NETIF_MSG_LINK, "8706/8726 LASI status 0x%x--> 0x%x\n", val1, val2);
+
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_SD, &rx_sd);
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PCS_DEVAD, MDIO_PCS_REG_STATUS, &pcs_status);
+ bnx2x_cl45_read(bp, phy,
+ MDIO_AN_DEVAD, MDIO_AN_REG_LINK_STATUS, &val2);
+ bnx2x_cl45_read(bp, phy,
+ MDIO_AN_DEVAD, MDIO_AN_REG_LINK_STATUS, &val2);
+
+ DP(NETIF_MSG_LINK, "8706/8726 rx_sd 0x%x pcs_status 0x%x 1Gbps"
+ " link_status 0x%x\n", rx_sd, pcs_status, val2);
+ /* link is up if both bit 0 of pmd_rx_sd and
+ * bit 0 of pcs_status are set, or if the autoneg bit
+ * 1 is set
+ */
+ link_up = ((rx_sd & pcs_status & 0x1) || (val2 & (1<<1)));
+ if (link_up) {
+ if (val2 & (1<<1))
+ vars->line_speed = SPEED_1000;
+ else
+ vars->line_speed = SPEED_10000;
+ bnx2x_ext_phy_resolve_fc(phy, params, vars);
}
-
- /* Disable PLL sequencer (use read-modify-write to clear bit 13) */
- bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr,
- MDIO_XS_DEVAD,
- MDIO_XS_PLL_SEQUENCER, &val);
- val &= ~(1<<13);
- bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
- MDIO_XS_DEVAD, MDIO_XS_PLL_SEQUENCER, val);
-
- /* PLL controls */
- bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
- MDIO_XS_DEVAD, 0x805E, 0x1077);
- bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
- MDIO_XS_DEVAD, 0x805D, 0x0000);
- bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
- MDIO_XS_DEVAD, 0x805C, 0x030B);
- bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
- MDIO_XS_DEVAD, 0x805B, 0x1240);
- bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
- MDIO_XS_DEVAD, 0x805A, 0x2490);
-
- /* Tx Controls */
- bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
- MDIO_XS_DEVAD, 0x80A7, 0x0C74);
- bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
- MDIO_XS_DEVAD, 0x80A6, 0x9041);
- bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
- MDIO_XS_DEVAD, 0x80A5, 0x4640);
-
- /* Rx Controls */
- bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
- MDIO_XS_DEVAD, 0x80FE, 0x01C4);
- bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
- MDIO_XS_DEVAD, 0x80FD, 0x9249);
- bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
- MDIO_XS_DEVAD, 0x80FC, 0x2015);
-
- /* Enable PLL sequencer (use read-modify-write to set bit 13) */
- bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr,
- MDIO_XS_DEVAD,
- MDIO_XS_PLL_SEQUENCER, &val);
- val |= (1<<13);
- bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
- MDIO_XS_DEVAD, MDIO_XS_PLL_SEQUENCER, val);
+ return link_up;
}
-static void bnx2x_8073_set_pause_cl37(struct link_params *params,
- struct link_vars *vars)
+/******************************************************************/
+/* BCM8706 PHY SECTION */
+/******************************************************************/
+static u8 bnx2x_8706_config_init(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
{
+ u16 cnt, val;
struct bnx2x *bp = params->bp;
- u16 cl37_val;
- u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
- u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
-
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_CL37_FC_LD, &cl37_val);
-
- cl37_val &= ~MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
- /* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
+ bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
+ MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
+ /* HW reset */
+ bnx2x_ext_phy_hw_reset(bp, params->port);
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0xa040);
+ bnx2x_wait_reset_complete(bp, phy);
- if ((vars->ieee_fc &
- MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC) ==
- MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC) {
- cl37_val |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC;
+ /* Wait until fw is loaded */
+ for (cnt = 0; cnt < 100; cnt++) {
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_ROM_VER1, &val);
+ if (val)
+ break;
+ msleep(10);
}
- if ((vars->ieee_fc &
- MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) ==
- MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) {
- cl37_val |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
+ DP(NETIF_MSG_LINK, "XGXS 8706 is initialized after %d ms\n", cnt);
+ if ((params->feature_config_flags &
+ FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED)) {
+ u8 i;
+ u16 reg;
+ for (i = 0; i < 4; i++) {
+ reg = MDIO_XS_8706_REG_BANK_RX0 +
+ i*(MDIO_XS_8706_REG_BANK_RX1 -
+ MDIO_XS_8706_REG_BANK_RX0);
+ bnx2x_cl45_read(bp, phy, MDIO_XS_DEVAD, reg, &val);
+ /* Clear first 3 bits of the control */
+ val &= ~0x7;
+ /* Set control bits according to configuration */
+ val |= (phy->rx_preemphasis[i] & 0x7);
+ DP(NETIF_MSG_LINK, "Setting RX Equalizer to BCM8706"
+ " reg 0x%x <-- val 0x%x\n", reg, val);
+ bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, reg, val);
+ }
}
- if ((vars->ieee_fc &
- MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) ==
- MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) {
- cl37_val |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
+ /* Force speed */
+ if (phy->req_line_speed == SPEED_10000) {
+ DP(NETIF_MSG_LINK, "XGXS 8706 force 10Gbps\n");
+
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_DIGITAL_CTRL, 0x400);
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 1);
+ } else {
+ /* Force 1Gbps using autoneg with 1G advertisment */
+
+ /* Allow CL37 through CL73 */
+ DP(NETIF_MSG_LINK, "XGXS 8706 AutoNeg\n");
+ bnx2x_cl45_write(bp, phy,
+ MDIO_AN_DEVAD, MDIO_AN_REG_CL37_CL73, 0x040c);
+
+ /* Enable Full-Duplex advertisment on CL37 */
+ bnx2x_cl45_write(bp, phy,
+ MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LP, 0x0020);
+ /* Enable CL37 AN */
+ bnx2x_cl45_write(bp, phy,
+ MDIO_AN_DEVAD, MDIO_AN_REG_CL37_AN, 0x1000);
+ /* 1G support */
+ bnx2x_cl45_write(bp, phy,
+ MDIO_AN_DEVAD, MDIO_AN_REG_ADV, (1<<5));
+
+ /* Enable clause 73 AN */
+ bnx2x_cl45_write(bp, phy,
+ MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x1200);
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM_CTRL,
+ 0x0400);
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL,
+ 0x0004);
}
- DP(NETIF_MSG_LINK,
- "Ext phy AN advertize cl37 0x%x\n", cl37_val);
+ bnx2x_save_bcm_spirom_ver(bp, phy, params->port);
+ return 0;
+}
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_CL37_FC_LD, cl37_val);
- msleep(500);
+static u8 bnx2x_8706_read_status(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
+{
+ return bnx2x_8706_8726_read_status(phy, params, vars);
}
-static void bnx2x_ext_phy_set_pause(struct link_params *params,
- struct link_vars *vars)
+/******************************************************************/
+/* BCM8726 PHY SECTION */
+/******************************************************************/
+static void bnx2x_8726_config_loopback(struct bnx2x_phy *phy,
+ struct link_params *params)
{
struct bnx2x *bp = params->bp;
- u16 val;
- u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
- u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
-
- /* read modify write pause advertizing */
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_ADV_PAUSE, &val);
-
- val &= ~MDIO_AN_REG_ADV_PAUSE_BOTH;
-
- /* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
-
- if ((vars->ieee_fc &
- MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) ==
- MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) {
- val |= MDIO_AN_REG_ADV_PAUSE_ASYMMETRIC;
- }
- if ((vars->ieee_fc &
- MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) ==
- MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) {
- val |=
- MDIO_AN_REG_ADV_PAUSE_PAUSE;
- }
- DP(NETIF_MSG_LINK,
- "Ext phy AN advertize 0x%x\n", val);
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_ADV_PAUSE, val);
+ DP(NETIF_MSG_LINK, "PMA/PMD ext_phy_loopback: 8726\n");
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x0001);
}
-static void bnx2x_set_preemphasis(struct link_params *params)
+
+static void bnx2x_8726_external_rom_boot(struct bnx2x_phy *phy,
+ struct link_params *params)
{
- u16 bank, i = 0;
struct bnx2x *bp = params->bp;
+ /* Need to wait 100ms after reset */
+ msleep(100);
- for (bank = MDIO_REG_BANK_RX0, i = 0; bank <= MDIO_REG_BANK_RX3;
- bank += (MDIO_REG_BANK_RX1-MDIO_REG_BANK_RX0), i++) {
- CL45_WR_OVER_CL22(bp, params->port,
- params->phy_addr,
- bank,
- MDIO_RX0_RX_EQ_BOOST,
- params->xgxs_config_rx[i]);
- }
-
- for (bank = MDIO_REG_BANK_TX0, i = 0; bank <= MDIO_REG_BANK_TX3;
- bank += (MDIO_REG_BANK_TX1 - MDIO_REG_BANK_TX0), i++) {
- CL45_WR_OVER_CL22(bp, params->port,
- params->phy_addr,
- bank,
- MDIO_TX0_TX_DRIVER,
- params->xgxs_config_tx[i]);
- }
-}
+ /* Micro controller re-boot */
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_GEN_CTRL, 0x018B);
+ /* Set soft reset */
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_GEN_CTRL,
+ MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET);
-static void bnx2x_8481_set_led4(struct link_params *params,
- u32 ext_phy_type, u8 ext_phy_addr)
-{
- struct bnx2x *bp = params->bp;
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_MISC_CTRL1, 0x0001);
- /* PHYC_CTL_LED_CTL */
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
+ bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD,
- MDIO_PMA_REG_8481_LINK_SIGNAL, 0xa482);
+ MDIO_PMA_REG_GEN_CTRL,
+ MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
+
+ /* wait for 150ms for microcode load */
+ msleep(150);
- /* Unmask LED4 for 10G link */
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
+ /* Disable serial boot control, tristates pins SS_N, SCK, MOSI, MISO */
+ bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD,
- MDIO_PMA_REG_8481_SIGNAL_MASK, (1<<6));
- /* 'Interrupt Mask' */
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- 0xFFFB, 0xFFFD);
-}
-static void bnx2x_8481_set_legacy_led_mode(struct link_params *params,
- u32 ext_phy_type, u8 ext_phy_addr)
-{
- struct bnx2x *bp = params->bp;
+ MDIO_PMA_REG_MISC_CTRL1, 0x0000);
- /* LED1 (10G Link): Disable LED1 when 10/100/1000 link */
- /* LED2 (1G/100/10 Link): Enable LED2 when 10/100/1000 link) */
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_8481_LEGACY_SHADOW,
- (1<<15) | (0xd << 10) | (0xc<<4) | 0xe);
+ msleep(200);
+ bnx2x_save_bcm_spirom_ver(bp, phy, params->port);
}
-static void bnx2x_8481_set_10G_led_mode(struct link_params *params,
- u32 ext_phy_type, u8 ext_phy_addr)
+static u8 bnx2x_8726_read_status(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
u16 val1;
-
- /* LED1 (10G Link) */
- /* Enable continuse based on source 7(10G-link) */
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_8481_LINK_SIGNAL,
- &val1);
- /* Set bit 2 to 0, and bits [1:0] to 10 */
- val1 &= ~((1<<0) | (1<<2) | (1<<7)); /* Clear bits 0,2,7*/
- val1 |= ((1<<1) | (1<<6)); /* Set bit 1, 6 */
-
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_8481_LINK_SIGNAL,
- val1);
-
- /* Unmask LED1 for 10G link */
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_8481_LED1_MASK,
- &val1);
- /* Set bit 2 to 0, and bits [1:0] to 10 */
- val1 |= (1<<7);
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_8481_LED1_MASK,
- val1);
-
- /* LED2 (1G/100/10G Link) */
- /* Mask LED2 for 10G link */
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_8481_LED2_MASK,
- 0);
-
- /* Unmask LED3 for 10G link */
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_8481_LED3_MASK,
- 0x6);
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_8481_LED3_BLINK,
- 0);
+ u8 link_up = bnx2x_8706_8726_read_status(phy, params, vars);
+ if (link_up) {
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER,
+ &val1);
+ if (val1 & (1<<15)) {
+ DP(NETIF_MSG_LINK, "Tx is disabled\n");
+ link_up = 0;
+ vars->line_speed = 0;
+ }
+ }
+ return link_up;
}
-static void bnx2x_init_internal_phy(struct link_params *params,
- struct link_vars *vars,
- u8 enable_cl73)
+static u8 bnx2x_8726_config_init(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
+ u32 val;
+ u32 swap_val, swap_override, aeu_gpio_mask, offset;
+ DP(NETIF_MSG_LINK, "Initializing BCM8726\n");
+ /* Restore normal power mode*/
+ bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
+ MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
- if (!(vars->phy_flags & PHY_SGMII_FLAG)) {
- if ((XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) &&
- (params->feature_config_flags &
- FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED))
- bnx2x_set_preemphasis(params);
-
- /* forced speed requested? */
- if (vars->line_speed != SPEED_AUTO_NEG ||
- ((XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) &&
- params->loopback_mode == LOOPBACK_EXT)) {
- DP(NETIF_MSG_LINK, "not SGMII, no AN\n");
-
- /* disable autoneg */
- bnx2x_set_autoneg(params, vars, 0);
+ bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
+ MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
+
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15);
+ bnx2x_wait_reset_complete(bp, phy);
+
+ bnx2x_8726_external_rom_boot(phy, params);
+
+ /* Need to call module detected on initialization since
+ the module detection triggered by actual module
+ insertion might occur before driver is loaded, and when
+ driver is loaded, it reset all registers, including the
+ transmitter */
+ bnx2x_sfp_module_detection(phy, params);
+
+ if (phy->req_line_speed == SPEED_1000) {
+ DP(NETIF_MSG_LINK, "Setting 1G force\n");
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x40);
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2, 0xD);
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 0x5);
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM_CTRL,
+ 0x400);
+ } else if ((phy->req_line_speed == SPEED_AUTO_NEG) &&
+ (phy->speed_cap_mask &
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_1G) &&
+ ((phy->speed_cap_mask &
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_10G) !=
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) {
+ DP(NETIF_MSG_LINK, "Setting 1G clause37\n");
+ /* Set Flow control */
+ bnx2x_ext_phy_set_pause(params, phy, vars);
+ bnx2x_cl45_write(bp, phy,
+ MDIO_AN_DEVAD, MDIO_AN_REG_ADV, 0x20);
+ bnx2x_cl45_write(bp, phy,
+ MDIO_AN_DEVAD, MDIO_AN_REG_CL37_CL73, 0x040c);
+ bnx2x_cl45_write(bp, phy,
+ MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD, 0x0020);
+ bnx2x_cl45_write(bp, phy,
+ MDIO_AN_DEVAD, MDIO_AN_REG_CL37_AN, 0x1000);
+ bnx2x_cl45_write(bp, phy,
+ MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x1200);
+ /* Enable RX-ALARM control to receive
+ interrupt for 1G speed change */
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 0x4);
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM_CTRL,
+ 0x400);
+
+ } else { /* Default 10G. Set only LASI control */
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 1);
+ }
- /* program speed and duplex */
- bnx2x_program_serdes(params, vars);
+ /* Set TX PreEmphasis if needed */
+ if ((params->feature_config_flags &
+ FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED)) {
+ DP(NETIF_MSG_LINK, "Setting TX_CTRL1 0x%x,"
+ "TX_CTRL2 0x%x\n",
+ phy->tx_preemphasis[0],
+ phy->tx_preemphasis[1]);
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8726_TX_CTRL1,
+ phy->tx_preemphasis[0]);
+
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8726_TX_CTRL2,
+ phy->tx_preemphasis[1]);
+ }
- } else { /* AN_mode */
- DP(NETIF_MSG_LINK, "not SGMII, AN\n");
+ /* Set GPIO3 to trigger SFP+ module insertion/removal */
+ bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3,
+ MISC_REGISTERS_GPIO_INPUT_HI_Z, params->port);
- /* AN enabled */
- bnx2x_set_brcm_cl37_advertisment(params);
+ /* The GPIO should be swapped if the swap register is set and active */
+ swap_val = REG_RD(bp, NIG_REG_PORT_SWAP);
+ swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE);
- /* program duplex & pause advertisement (for aneg) */
- bnx2x_set_ieee_aneg_advertisment(params,
- vars->ieee_fc);
+ /* Select function upon port-swap configuration */
+ if (params->port == 0) {
+ offset = MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0;
+ aeu_gpio_mask = (swap_val && swap_override) ?
+ AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_1 :
+ AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_0;
+ } else {
+ offset = MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0;
+ aeu_gpio_mask = (swap_val && swap_override) ?
+ AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_0 :
+ AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_1;
+ }
+ val = REG_RD(bp, offset);
+ /* add GPIO3 to group */
+ val |= aeu_gpio_mask;
+ REG_WR(bp, offset, val);
+ return 0;
- /* enable autoneg */
- bnx2x_set_autoneg(params, vars, enable_cl73);
+}
- /* enable and restart AN */
- bnx2x_restart_autoneg(params, enable_cl73);
- }
+static void bnx2x_8726_link_reset(struct bnx2x_phy *phy,
+ struct link_params *params)
+{
+ struct bnx2x *bp = params->bp;
+ DP(NETIF_MSG_LINK, "bnx2x_8726_link_reset port %d\n", params->port);
+ /* Set serial boot control for external load */
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_GEN_CTRL, 0x0001);
+}
- } else { /* SGMII mode */
- DP(NETIF_MSG_LINK, "SGMII\n");
+/******************************************************************/
+/* BCM8727 PHY SECTION */
+/******************************************************************/
- bnx2x_initialize_sgmii_process(params, vars);
+static void bnx2x_8727_set_link_led(struct bnx2x_phy *phy,
+ struct link_params *params, u8 mode)
+{
+ struct bnx2x *bp = params->bp;
+ u16 led_mode_bitmask = 0;
+ u16 gpio_pins_bitmask = 0;
+ u16 val;
+ /* Only NOC flavor requires to set the LED specifically */
+ if (!(phy->flags & FLAGS_NOC))
+ return;
+ switch (mode) {
+ case LED_MODE_FRONT_PANEL_OFF:
+ case LED_MODE_OFF:
+ led_mode_bitmask = 0;
+ gpio_pins_bitmask = 0x03;
+ break;
+ case LED_MODE_ON:
+ led_mode_bitmask = 0;
+ gpio_pins_bitmask = 0x02;
+ break;
+ case LED_MODE_OPER:
+ led_mode_bitmask = 0x60;
+ gpio_pins_bitmask = 0x11;
+ break;
}
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8727_PCS_OPT_CTRL,
+ &val);
+ val &= 0xff8f;
+ val |= led_mode_bitmask;
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8727_PCS_OPT_CTRL,
+ val);
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8727_GPIO_CTRL,
+ &val);
+ val &= 0xffe0;
+ val |= gpio_pins_bitmask;
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8727_GPIO_CTRL,
+ val);
+}
+static void bnx2x_8727_hw_reset(struct bnx2x_phy *phy,
+ struct link_params *params) {
+ u32 swap_val, swap_override;
+ u8 port;
+ /**
+ * The PHY reset is controlled by GPIO 1. Fake the port number
+ * to cancel the swap done in set_gpio()
+ */
+ struct bnx2x *bp = params->bp;
+ swap_val = REG_RD(bp, NIG_REG_PORT_SWAP);
+ swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE);
+ port = (swap_val && swap_override) ^ 1;
+ bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
+ MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
}
-static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars)
+static u8 bnx2x_8727_config_init(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
{
+ u16 tmp1, val, mod_abs;
+ u16 rx_alarm_ctrl_val;
+ u16 lasi_ctrl_val;
struct bnx2x *bp = params->bp;
- u32 ext_phy_type;
- u8 ext_phy_addr;
- u16 cnt;
- u16 ctrl = 0;
- u16 val = 0;
- u8 rc = 0;
-
- if (vars->phy_flags & PHY_XGXS_FLAG) {
- ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
-
- ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
- /* Make sure that the soft reset is off (expect for the 8072:
- * due to the lock, it will be done inside the specific
- * handling)
+ /* Enable PMD link, MOD_ABS_FLT, and 1G link alarm */
+
+ bnx2x_wait_reset_complete(bp, phy);
+ rx_alarm_ctrl_val = (1<<2) | (1<<5) ;
+ lasi_ctrl_val = 0x0004;
+
+ DP(NETIF_MSG_LINK, "Initializing BCM8727\n");
+ /* enable LASI */
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM_CTRL,
+ rx_alarm_ctrl_val);
+
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, lasi_ctrl_val);
+
+ /* Initially configure MOD_ABS to interrupt when
+ module is presence( bit 8) */
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, &mod_abs);
+ /* Set EDC off by setting OPTXLOS signal input to low
+ (bit 9).
+ When the EDC is off it locks onto a reference clock and
+ avoids becoming 'lost'.*/
+ mod_abs &= ~(1<<8);
+ if (!(phy->flags & FLAGS_NOC))
+ mod_abs &= ~(1<<9);
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, mod_abs);
+
+
+ /* Make MOD_ABS give interrupt on change */
+ bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_PCS_OPT_CTRL,
+ &val);
+ val |= (1<<12);
+ if (phy->flags & FLAGS_NOC)
+ val |= (3<<5);
+
+ /**
+ * Set 8727 GPIOs to input to allow reading from the 8727 GPIO0
+ * status which reflect SFP+ module over-current
+ */
+ if (!(phy->flags & FLAGS_NOC))
+ val &= 0xff8f; /* Reset bits 4-6 */
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_PCS_OPT_CTRL, val);
+
+ bnx2x_8727_power_module(bp, phy, 1);
+
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_M8051_MSGOUT_REG, &tmp1);
+
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM, &tmp1);
+
+ /* Set option 1G speed */
+ if (phy->req_line_speed == SPEED_1000) {
+ DP(NETIF_MSG_LINK, "Setting 1G force\n");
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x40);
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2, 0xD);
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2, &tmp1);
+ DP(NETIF_MSG_LINK, "1.7 = 0x%x\n", tmp1);
+ /**
+ * Power down the XAUI until link is up in case of dual-media
+ * and 1G
*/
- if ((ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) &&
- (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE) &&
- (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN) &&
- (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072) &&
- (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073)) {
- /* Wait for soft reset to get cleared upto 1 sec */
- for (cnt = 0; cnt < 1000; cnt++) {
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_CTRL, &ctrl);
- if (!(ctrl & (1<<15)))
- break;
- msleep(1);
- }
- DP(NETIF_MSG_LINK, "control reg 0x%x (after %d ms)\n",
- ctrl, cnt);
- }
-
- switch (ext_phy_type) {
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
- break;
-
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
- DP(NETIF_MSG_LINK, "XGXS 8705\n");
-
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_MISC_CTRL,
- 0x8288);
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_PHY_IDENTIFIER,
- 0x7fbf);
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_CMU_PLL_BYPASS,
- 0x0100);
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_WIS_DEVAD,
- MDIO_WIS_REG_LASI_CNTL, 0x1);
-
- /* BCM8705 doesn't have microcode, hence the 0 */
- bnx2x_save_spirom_version(bp, params->port,
- params->shmem_base, 0);
- break;
-
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
- /* Wait until fw is loaded */
- for (cnt = 0; cnt < 100; cnt++) {
- bnx2x_cl45_read(bp, params->port, ext_phy_type,
- ext_phy_addr, MDIO_PMA_DEVAD,
- MDIO_PMA_REG_ROM_VER1, &val);
- if (val)
- break;
- msleep(10);
- }
- DP(NETIF_MSG_LINK, "XGXS 8706 is initialized "
- "after %d ms\n", cnt);
- if ((params->feature_config_flags &
- FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED)) {
- u8 i;
- u16 reg;
- for (i = 0; i < 4; i++) {
- reg = MDIO_XS_8706_REG_BANK_RX0 +
- i*(MDIO_XS_8706_REG_BANK_RX1 -
- MDIO_XS_8706_REG_BANK_RX0);
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_XS_DEVAD,
- reg, &val);
- /* Clear first 3 bits of the control */
- val &= ~0x7;
- /* Set control bits according to
- configuation */
- val |= (params->xgxs_config_rx[i] &
- 0x7);
- DP(NETIF_MSG_LINK, "Setting RX"
- "Equalizer to BCM8706 reg 0x%x"
- " <-- val 0x%x\n", reg, val);
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_XS_DEVAD,
- reg, val);
- }
- }
- /* Force speed */
- if (params->req_line_speed == SPEED_10000) {
- DP(NETIF_MSG_LINK, "XGXS 8706 force 10Gbps\n");
-
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_DIGITAL_CTRL,
- 0x400);
- bnx2x_cl45_write(bp, params->port, ext_phy_type,
- ext_phy_addr, MDIO_PMA_DEVAD,
- MDIO_PMA_REG_LASI_CTRL, 1);
- } else {
- /* Force 1Gbps using autoneg with 1G
- advertisment */
-
- /* Allow CL37 through CL73 */
- DP(NETIF_MSG_LINK, "XGXS 8706 AutoNeg\n");
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_CL37_CL73,
- 0x040c);
-
- /* Enable Full-Duplex advertisment on CL37 */
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_CL37_FC_LP,
- 0x0020);
- /* Enable CL37 AN */
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_CL37_AN,
- 0x1000);
- /* 1G support */
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_ADV, (1<<5));
-
- /* Enable clause 73 AN */
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_CTRL,
- 0x1200);
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_RX_ALARM_CTRL,
- 0x0400);
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_LASI_CTRL, 0x0004);
-
- }
- bnx2x_save_bcm_spirom_ver(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- params->shmem_base);
- break;
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
- DP(NETIF_MSG_LINK, "Initializing BCM8726\n");
- bnx2x_bcm8726_external_rom_boot(params);
-
- /* Need to call module detected on initialization since
- the module detection triggered by actual module
- insertion might occur before driver is loaded, and when
- driver is loaded, it reset all registers, including the
- transmitter */
- bnx2x_sfp_module_detection(params);
-
- /* Set Flow control */
- bnx2x_ext_phy_set_pause(params, vars);
- if (params->req_line_speed == SPEED_1000) {
- DP(NETIF_MSG_LINK, "Setting 1G force\n");
- bnx2x_cl45_write(bp, params->port, ext_phy_type,
- ext_phy_addr, MDIO_PMA_DEVAD,
- MDIO_PMA_REG_CTRL, 0x40);
- bnx2x_cl45_write(bp, params->port, ext_phy_type,
- ext_phy_addr, MDIO_PMA_DEVAD,
- MDIO_PMA_REG_10G_CTRL2, 0xD);
- bnx2x_cl45_write(bp, params->port, ext_phy_type,
- ext_phy_addr, MDIO_PMA_DEVAD,
- MDIO_PMA_REG_LASI_CTRL, 0x5);
- bnx2x_cl45_write(bp, params->port, ext_phy_type,
- ext_phy_addr, MDIO_PMA_DEVAD,
- MDIO_PMA_REG_RX_ALARM_CTRL,
- 0x400);
- } else if ((params->req_line_speed ==
- SPEED_AUTO_NEG) &&
- ((params->speed_cap_mask &
- PORT_HW_CFG_SPEED_CAPABILITY_D0_1G))) {
- DP(NETIF_MSG_LINK, "Setting 1G clause37\n");
- bnx2x_cl45_write(bp, params->port, ext_phy_type,
- ext_phy_addr, MDIO_AN_DEVAD,
- MDIO_AN_REG_ADV, 0x20);
- bnx2x_cl45_write(bp, params->port, ext_phy_type,
- ext_phy_addr, MDIO_AN_DEVAD,
- MDIO_AN_REG_CL37_CL73, 0x040c);
- bnx2x_cl45_write(bp, params->port, ext_phy_type,
- ext_phy_addr, MDIO_AN_DEVAD,
- MDIO_AN_REG_CL37_FC_LD, 0x0020);
- bnx2x_cl45_write(bp, params->port, ext_phy_type,
- ext_phy_addr, MDIO_AN_DEVAD,
- MDIO_AN_REG_CL37_AN, 0x1000);
- bnx2x_cl45_write(bp, params->port, ext_phy_type,
- ext_phy_addr, MDIO_AN_DEVAD,
- MDIO_AN_REG_CTRL, 0x1200);
-
- /* Enable RX-ALARM control to receive
- interrupt for 1G speed change */
- bnx2x_cl45_write(bp, params->port, ext_phy_type,
- ext_phy_addr, MDIO_PMA_DEVAD,
- MDIO_PMA_REG_LASI_CTRL, 0x4);
- bnx2x_cl45_write(bp, params->port, ext_phy_type,
- ext_phy_addr, MDIO_PMA_DEVAD,
- MDIO_PMA_REG_RX_ALARM_CTRL,
- 0x400);
-
- } else { /* Default 10G. Set only LASI control */
- bnx2x_cl45_write(bp, params->port, ext_phy_type,
- ext_phy_addr, MDIO_PMA_DEVAD,
- MDIO_PMA_REG_LASI_CTRL, 1);
- }
-
- /* Set TX PreEmphasis if needed */
- if ((params->feature_config_flags &
- FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED)) {
- DP(NETIF_MSG_LINK, "Setting TX_CTRL1 0x%x,"
- "TX_CTRL2 0x%x\n",
- params->xgxs_config_tx[0],
- params->xgxs_config_tx[1]);
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_8726_TX_CTRL1,
- params->xgxs_config_tx[0]);
-
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_8726_TX_CTRL2,
- params->xgxs_config_tx[1]);
- }
- break;
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
- {
- u16 tmp1;
- u16 rx_alarm_ctrl_val;
- u16 lasi_ctrl_val;
- if (ext_phy_type ==
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072) {
- rx_alarm_ctrl_val = 0x400;
- lasi_ctrl_val = 0x0004;
- } else {
- rx_alarm_ctrl_val = (1<<2);
- lasi_ctrl_val = 0x0004;
- }
-
- /* enable LASI */
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_RX_ALARM_CTRL,
- rx_alarm_ctrl_val);
-
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_LASI_CTRL,
- lasi_ctrl_val);
-
- bnx2x_8073_set_pause_cl37(params, vars);
-
- if (ext_phy_type ==
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072)
- bnx2x_bcm8072_external_rom_boot(params);
- else
- /* In case of 8073 with long xaui lines,
- don't set the 8073 xaui low power*/
- bnx2x_bcm8073_set_xaui_low_power_mode(params);
-
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_M8051_MSGOUT_REG,
- &tmp1);
-
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_RX_ALARM, &tmp1);
-
- DP(NETIF_MSG_LINK, "Before rom RX_ALARM(port1):"
- "0x%x\n", tmp1);
-
- /* If this is forced speed, set to KR or KX
- * (all other are not supported)
- */
- if (params->loopback_mode == LOOPBACK_EXT) {
- bnx2x_bcm807x_force_10G(params);
- DP(NETIF_MSG_LINK,
- "Forced speed 10G on 807X\n");
- break;
- } else {
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type, ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_BCM_CTRL,
- 0x0002);
- }
- if (params->req_line_speed != SPEED_AUTO_NEG) {
- if (params->req_line_speed == SPEED_10000) {
- val = (1<<7);
- } else if (params->req_line_speed ==
- SPEED_2500) {
- val = (1<<5);
- /* Note that 2.5G works only
- when used with 1G advertisment */
- } else
- val = (1<<5);
- } else {
-
- val = 0;
- if (params->speed_cap_mask &
- PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
- val |= (1<<7);
-
- /* Note that 2.5G works only when
- used with 1G advertisment */
- if (params->speed_cap_mask &
- (PORT_HW_CFG_SPEED_CAPABILITY_D0_1G |
- PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G))
- val |= (1<<5);
- DP(NETIF_MSG_LINK,
- "807x autoneg val = 0x%x\n", val);
- }
-
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_ADV, val);
- if (ext_phy_type ==
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_8073_2_5G, &tmp1);
-
- if (((params->speed_cap_mask &
- PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G) &&
- (params->req_line_speed ==
- SPEED_AUTO_NEG)) ||
- (params->req_line_speed ==
- SPEED_2500)) {
- u16 phy_ver;
- /* Allow 2.5G for A1 and above */
- bnx2x_cl45_read(bp, params->port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
- ext_phy_addr,
+ if (DUAL_MEDIA(params)) {
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8727_PCS_GP, &val);
+ val |= (3<<10);
+ bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD,
- MDIO_PMA_REG_8073_CHIP_REV, &phy_ver);
- DP(NETIF_MSG_LINK, "Add 2.5G\n");
- if (phy_ver > 0)
- tmp1 |= 1;
- else
- tmp1 &= 0xfffe;
- } else {
- DP(NETIF_MSG_LINK, "Disable 2.5G\n");
- tmp1 &= 0xfffe;
- }
-
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_8073_2_5G, tmp1);
- }
-
- /* Add support for CL37 (passive mode) II */
-
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_CL37_FC_LD,
- &tmp1);
-
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_CL37_FC_LD, (tmp1 |
- ((params->req_duplex == DUPLEX_FULL) ?
- 0x20 : 0x40)));
-
- /* Add support for CL37 (passive mode) III */
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_CL37_AN, 0x1000);
-
- if (ext_phy_type ==
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
- /* The SNR will improve about 2db by changing
- BW and FEE main tap. Rest commands are executed
- after link is up*/
- /*Change FFE main cursor to 5 in EDC register*/
- if (bnx2x_8073_is_snr_needed(params))
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_EDC_FFE_MAIN,
- 0xFB0C);
-
- /* Enable FEC (Forware Error Correction)
- Request in the AN */
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_ADV2, &tmp1);
-
- tmp1 |= (1<<15);
-
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_ADV2, tmp1);
-
- }
-
- bnx2x_ext_phy_set_pause(params, vars);
-
- /* Restart autoneg */
- msleep(500);
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_CTRL, 0x1200);
- DP(NETIF_MSG_LINK, "807x Autoneg Restart: "
- "Advertise 1G=%x, 10G=%x\n",
- ((val & (1<<5)) > 0),
- ((val & (1<<7)) > 0));
- break;
+ MDIO_PMA_REG_8727_PCS_GP, val);
}
+ } else if ((phy->req_line_speed == SPEED_AUTO_NEG) &&
+ ((phy->speed_cap_mask &
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) &&
+ ((phy->speed_cap_mask &
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_10G) !=
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) {
+
+ DP(NETIF_MSG_LINK, "Setting 1G clause37\n");
+ bnx2x_cl45_write(bp, phy,
+ MDIO_AN_DEVAD, MDIO_AN_REG_8727_MISC_CTRL, 0);
+ bnx2x_cl45_write(bp, phy,
+ MDIO_AN_DEVAD, MDIO_AN_REG_CL37_AN, 0x1300);
+ } else {
+ /**
+ * Since the 8727 has only single reset pin, need to set the 10G
+ * registers although it is default
+ */
+ bnx2x_cl45_write(bp, phy,
+ MDIO_AN_DEVAD, MDIO_AN_REG_8727_MISC_CTRL,
+ 0x0020);
+ bnx2x_cl45_write(bp, phy,
+ MDIO_AN_DEVAD, MDIO_AN_REG_CL37_AN, 0x0100);
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x2040);
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2,
+ 0x0008);
+ }
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
- {
- u16 tmp1;
- u16 rx_alarm_ctrl_val;
- u16 lasi_ctrl_val;
-
- /* Enable PMD link, MOD_ABS_FLT, and 1G link alarm */
-
- u16 mod_abs;
- rx_alarm_ctrl_val = (1<<2) | (1<<5) ;
- lasi_ctrl_val = 0x0004;
-
- DP(NETIF_MSG_LINK, "Initializing BCM8727\n");
- /* enable LASI */
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_RX_ALARM_CTRL,
- rx_alarm_ctrl_val);
-
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_LASI_CTRL,
- lasi_ctrl_val);
-
- /* Initially configure MOD_ABS to interrupt when
- module is presence( bit 8) */
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_PHY_IDENTIFIER, &mod_abs);
- /* Set EDC off by setting OPTXLOS signal input to low
- (bit 9).
- When the EDC is off it locks onto a reference clock and
- avoids becoming 'lost'.*/
- mod_abs &= ~((1<<8) | (1<<9));
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_PHY_IDENTIFIER, mod_abs);
-
- /* Make MOD_ABS give interrupt on change */
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_8727_PCS_OPT_CTRL,
- &val);
- val |= (1<<12);
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_8727_PCS_OPT_CTRL,
- val);
-
- /* Set 8727 GPIOs to input to allow reading from the
- 8727 GPIO0 status which reflect SFP+ module
- over-current */
-
- bnx2x_cl45_read(bp, params->port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_8727_PCS_OPT_CTRL,
- &val);
- val &= 0xff8f; /* Reset bits 4-6 */
- bnx2x_cl45_write(bp, params->port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_8727_PCS_OPT_CTRL,
- val);
-
- bnx2x_8727_power_module(bp, params, ext_phy_addr, 1);
- bnx2x_bcm8073_set_xaui_low_power_mode(params);
-
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_M8051_MSGOUT_REG,
- &tmp1);
-
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_RX_ALARM, &tmp1);
-
- /* Set option 1G speed */
- if (params->req_line_speed == SPEED_1000) {
-
- DP(NETIF_MSG_LINK, "Setting 1G force\n");
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_CTRL, 0x40);
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_10G_CTRL2, 0xD);
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_10G_CTRL2, &tmp1);
- DP(NETIF_MSG_LINK, "1.7 = 0x%x\n", tmp1);
-
- } else if ((params->req_line_speed ==
- SPEED_AUTO_NEG) &&
- ((params->speed_cap_mask &
- PORT_HW_CFG_SPEED_CAPABILITY_D0_1G))) {
-
- DP(NETIF_MSG_LINK, "Setting 1G clause37\n");
- bnx2x_cl45_write(bp, params->port, ext_phy_type,
- ext_phy_addr, MDIO_AN_DEVAD,
- MDIO_PMA_REG_8727_MISC_CTRL, 0);
- bnx2x_cl45_write(bp, params->port, ext_phy_type,
- ext_phy_addr, MDIO_AN_DEVAD,
- MDIO_AN_REG_CL37_AN, 0x1300);
- } else {
- /* Since the 8727 has only single reset pin,
- need to set the 10G registers although it is
- default */
- bnx2x_cl45_write(bp, params->port, ext_phy_type,
- ext_phy_addr, MDIO_AN_DEVAD,
- MDIO_AN_REG_CTRL, 0x0020);
- bnx2x_cl45_write(bp, params->port, ext_phy_type,
- ext_phy_addr, MDIO_AN_DEVAD,
- 0x7, 0x0100);
- bnx2x_cl45_write(bp, params->port, ext_phy_type,
- ext_phy_addr, MDIO_PMA_DEVAD,
- MDIO_PMA_REG_CTRL, 0x2040);
- bnx2x_cl45_write(bp, params->port, ext_phy_type,
- ext_phy_addr, MDIO_PMA_DEVAD,
- MDIO_PMA_REG_10G_CTRL2, 0x0008);
- }
-
- /* Set 2-wire transfer rate of SFP+ module EEPROM
- * to 100Khz since some DACs(direct attached cables) do
- * not work at 400Khz.
- */
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_8727_TWO_WIRE_SLAVE_ADDR,
- 0xa001);
-
- /* Set TX PreEmphasis if needed */
- if ((params->feature_config_flags &
- FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED)) {
- DP(NETIF_MSG_LINK, "Setting TX_CTRL1 0x%x,"
- "TX_CTRL2 0x%x\n",
- params->xgxs_config_tx[0],
- params->xgxs_config_tx[1]);
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_8727_TX_CTRL1,
- params->xgxs_config_tx[0]);
-
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_8727_TX_CTRL2,
- params->xgxs_config_tx[1]);
- }
-
- break;
- }
-
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
- {
- u16 fw_ver1, fw_ver2;
- DP(NETIF_MSG_LINK,
- "Setting the SFX7101 LASI indication\n");
-
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_LASI_CTRL, 0x1);
- DP(NETIF_MSG_LINK,
- "Setting the SFX7101 LED to blink on traffic\n");
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_7107_LED_CNTL, (1<<3));
-
- bnx2x_ext_phy_set_pause(params, vars);
- /* Restart autoneg */
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_CTRL, &val);
- val |= 0x200;
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_CTRL, val);
-
- /* Save spirom version */
- bnx2x_cl45_read(bp, params->port, ext_phy_type,
- ext_phy_addr, MDIO_PMA_DEVAD,
- MDIO_PMA_REG_7101_VER1, &fw_ver1);
-
- bnx2x_cl45_read(bp, params->port, ext_phy_type,
- ext_phy_addr, MDIO_PMA_DEVAD,
- MDIO_PMA_REG_7101_VER2, &fw_ver2);
-
- bnx2x_save_spirom_version(params->bp, params->port,
- params->shmem_base,
- (u32)(fw_ver1<<16 | fw_ver2));
- break;
- }
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481:
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823:
- /* This phy uses the NIG latch mechanism since link
- indication arrives through its LED4 and not via
- its LASI signal, so we get steady signal
- instead of clear on read */
- bnx2x_bits_en(bp, NIG_REG_LATCH_BC_0 + params->port*4,
- 1 << NIG_LATCH_BC_ENABLE_MI_INT);
-
- bnx2x_cl45_write(bp, params->port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_CTRL, 0x0000);
-
- bnx2x_8481_set_led4(params, ext_phy_type, ext_phy_addr);
- if (params->req_line_speed == SPEED_AUTO_NEG) {
-
- u16 autoneg_val, an_1000_val, an_10_100_val;
- /* set 1000 speed advertisement */
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_8481_1000T_CTRL,
- &an_1000_val);
-
- if (params->speed_cap_mask &
- PORT_HW_CFG_SPEED_CAPABILITY_D0_1G) {
- an_1000_val |= (1<<8);
- if (params->req_duplex == DUPLEX_FULL)
- an_1000_val |= (1<<9);
- DP(NETIF_MSG_LINK, "Advertising 1G\n");
- } else
- an_1000_val &= ~((1<<8) | (1<<9));
-
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_8481_1000T_CTRL,
- an_1000_val);
-
- /* set 100 speed advertisement */
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_8481_LEGACY_AN_ADV,
- &an_10_100_val);
-
- if (params->speed_cap_mask &
- (PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL |
- PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF)) {
- an_10_100_val |= (1<<7);
- if (params->req_duplex == DUPLEX_FULL)
- an_10_100_val |= (1<<8);
- DP(NETIF_MSG_LINK,
- "Advertising 100M\n");
- } else
- an_10_100_val &= ~((1<<7) | (1<<8));
-
- /* set 10 speed advertisement */
- if (params->speed_cap_mask &
- (PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL |
- PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF)) {
- an_10_100_val |= (1<<5);
- if (params->req_duplex == DUPLEX_FULL)
- an_10_100_val |= (1<<6);
- DP(NETIF_MSG_LINK, "Advertising 10M\n");
- }
- else
- an_10_100_val &= ~((1<<5) | (1<<6));
-
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_8481_LEGACY_AN_ADV,
- an_10_100_val);
-
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_8481_LEGACY_MII_CTRL,
- &autoneg_val);
-
- /* Disable forced speed */
- autoneg_val &= ~(1<<6|1<<13);
-
- /* Enable autoneg and restart autoneg
- for legacy speeds */
- autoneg_val |= (1<<9|1<<12);
-
- if (params->req_duplex == DUPLEX_FULL)
- autoneg_val |= (1<<8);
- else
- autoneg_val &= ~(1<<8);
-
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_8481_LEGACY_MII_CTRL,
- autoneg_val);
-
- if (params->speed_cap_mask &
- PORT_HW_CFG_SPEED_CAPABILITY_D0_10G) {
- DP(NETIF_MSG_LINK, "Advertising 10G\n");
- /* Restart autoneg for 10G*/
-
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_CTRL, 0x3200);
- }
- } else {
- /* Force speed */
- u16 autoneg_ctrl, pma_ctrl;
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_8481_LEGACY_MII_CTRL,
- &autoneg_ctrl);
-
- /* Disable autoneg */
- autoneg_ctrl &= ~(1<<12);
-
- /* Set 1000 force */
- switch (params->req_line_speed) {
- case SPEED_10000:
- DP(NETIF_MSG_LINK,
- "Unable to set 10G force !\n");
- break;
- case SPEED_1000:
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_CTRL,
- &pma_ctrl);
- autoneg_ctrl &= ~(1<<13);
- autoneg_ctrl |= (1<<6);
- pma_ctrl &= ~(1<<13);
- pma_ctrl |= (1<<6);
- DP(NETIF_MSG_LINK,
- "Setting 1000M force\n");
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_CTRL,
- pma_ctrl);
- break;
- case SPEED_100:
- autoneg_ctrl |= (1<<13);
- autoneg_ctrl &= ~(1<<6);
- DP(NETIF_MSG_LINK,
- "Setting 100M force\n");
- break;
- case SPEED_10:
- autoneg_ctrl &= ~(1<<13);
- autoneg_ctrl &= ~(1<<6);
- DP(NETIF_MSG_LINK,
- "Setting 10M force\n");
- break;
- }
-
- /* Duplex mode */
- if (params->req_duplex == DUPLEX_FULL) {
- autoneg_ctrl |= (1<<8);
- DP(NETIF_MSG_LINK,
- "Setting full duplex\n");
- } else
- autoneg_ctrl &= ~(1<<8);
-
- /* Update autoneg ctrl and pma ctrl */
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_8481_LEGACY_MII_CTRL,
- autoneg_ctrl);
- }
-
- /* Save spirom version */
- bnx2x_save_8481_spirom_version(bp, params->port,
- ext_phy_addr,
- params->shmem_base);
- break;
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
- DP(NETIF_MSG_LINK,
- "XGXS PHY Failure detected 0x%x\n",
- params->ext_phy_config);
- rc = -EINVAL;
- break;
- default:
- DP(NETIF_MSG_LINK, "BAD XGXS ext_phy_config 0x%x\n",
- params->ext_phy_config);
- rc = -EINVAL;
- break;
- }
-
- } else { /* SerDes */
-
- ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
- switch (ext_phy_type) {
- case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT:
- DP(NETIF_MSG_LINK, "SerDes Direct\n");
- break;
-
- case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482:
- DP(NETIF_MSG_LINK, "SerDes 5482\n");
- break;
-
- default:
- DP(NETIF_MSG_LINK, "BAD SerDes ext_phy_config 0x%x\n",
- params->ext_phy_config);
- break;
- }
+ /* Set 2-wire transfer rate of SFP+ module EEPROM
+ * to 100Khz since some DACs(direct attached cables) do
+ * not work at 400Khz.
+ */
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_TWO_WIRE_SLAVE_ADDR,
+ 0xa001);
+
+ /* Set TX PreEmphasis if needed */
+ if ((params->feature_config_flags &
+ FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED)) {
+ DP(NETIF_MSG_LINK, "Setting TX_CTRL1 0x%x, TX_CTRL2 0x%x\n",
+ phy->tx_preemphasis[0],
+ phy->tx_preemphasis[1]);
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_TX_CTRL1,
+ phy->tx_preemphasis[0]);
+
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_TX_CTRL2,
+ phy->tx_preemphasis[1]);
}
- return rc;
+
+ return 0;
}
-static void bnx2x_8727_handle_mod_abs(struct link_params *params)
+static void bnx2x_8727_handle_mod_abs(struct bnx2x_phy *phy,
+ struct link_params *params)
{
struct bnx2x *bp = params->bp;
u16 mod_abs, rx_alarm_status;
- u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
u32 val = REG_RD(bp, params->shmem_base +
offsetof(struct shmem_region, dev_info.
port_feature_config[params->port].
config));
- bnx2x_cl45_read(bp, params->port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
- ext_phy_addr,
+ bnx2x_cl45_read(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_PHY_IDENTIFIER, &mod_abs);
if (mod_abs & (1<<8)) {
@@ -4602,18 +5104,16 @@ static void bnx2x_8727_handle_mod_abs(struct link_params *params)
(bit 9).
When the EDC is off it locks onto a reference clock and
avoids becoming 'lost'.*/
- mod_abs &= ~((1<<8)|(1<<9));
- bnx2x_cl45_write(bp, params->port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
- ext_phy_addr,
+ mod_abs &= ~(1<<8);
+ if (!(phy->flags & FLAGS_NOC))
+ mod_abs &= ~(1<<9);
+ bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_PHY_IDENTIFIER, mod_abs);
/* Clear RX alarm since it stays up as long as
the mod_abs wasn't changed */
- bnx2x_cl45_read(bp, params->port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
- ext_phy_addr,
+ bnx2x_cl45_read(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_RX_ALARM, &rx_alarm_status);
@@ -4630,33 +5130,28 @@ static void bnx2x_8727_handle_mod_abs(struct link_params *params)
2. Restore the default polarity of the OPRXLOS signal and
this signal will then correctly indicate the presence or
absence of the Rx signal. (bit 9) */
- mod_abs |= ((1<<8)|(1<<9));
- bnx2x_cl45_write(bp, params->port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_PHY_IDENTIFIER, mod_abs);
+ mod_abs |= (1<<8);
+ if (!(phy->flags & FLAGS_NOC))
+ mod_abs |= (1<<9);
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_PHY_IDENTIFIER, mod_abs);
/* Clear RX alarm since it stays up as long as
the mod_abs wasn't changed. This is need to be done
before calling the module detection, otherwise it will clear
the link update alarm */
- bnx2x_cl45_read(bp, params->port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_RX_ALARM, &rx_alarm_status);
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_RX_ALARM, &rx_alarm_status);
if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)
- bnx2x_sfp_set_transmitter(bp, params->port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
- ext_phy_addr, 0);
+ bnx2x_sfp_set_transmitter(bp, phy, params->port, 0);
- if (bnx2x_wait_for_sfp_module_initialized(params)
- == 0)
- bnx2x_sfp_module_detection(params);
+ if (bnx2x_wait_for_sfp_module_initialized(phy, params) == 0)
+ bnx2x_sfp_module_detection(phy, params);
else
DP(NETIF_MSG_LINK, "SFP+ module is not initialized\n");
}
@@ -4667,1298 +5162,1714 @@ static void bnx2x_8727_handle_mod_abs(struct link_params *params)
module plugged in/out */
}
+static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
-static u8 bnx2x_ext_phy_is_link_up(struct link_params *params,
- struct link_vars *vars,
- u8 is_mi_int)
{
struct bnx2x *bp = params->bp;
- u32 ext_phy_type;
- u8 ext_phy_addr;
- u16 val1 = 0, val2;
- u16 rx_sd, pcs_status;
- u8 ext_phy_link_up = 0;
- u8 port = params->port;
-
- if (vars->phy_flags & PHY_XGXS_FLAG) {
- ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
- ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
- switch (ext_phy_type) {
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
- DP(NETIF_MSG_LINK, "XGXS Direct\n");
- ext_phy_link_up = 1;
- break;
+ u8 link_up = 0;
+ u16 link_status = 0;
+ u16 rx_alarm_status, lasi_ctrl, val1;
+
+ /* If PHY is not initialized, do not check link status */
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL,
+ &lasi_ctrl);
+ if (!lasi_ctrl)
+ return 0;
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
- DP(NETIF_MSG_LINK, "XGXS 8705\n");
- bnx2x_cl45_read(bp, params->port, ext_phy_type,
- ext_phy_addr,
- MDIO_WIS_DEVAD,
- MDIO_WIS_REG_LASI_STATUS, &val1);
- DP(NETIF_MSG_LINK, "8705 LASI status 0x%x\n", val1);
-
- bnx2x_cl45_read(bp, params->port, ext_phy_type,
- ext_phy_addr,
- MDIO_WIS_DEVAD,
- MDIO_WIS_REG_LASI_STATUS, &val1);
- DP(NETIF_MSG_LINK, "8705 LASI status 0x%x\n", val1);
-
- bnx2x_cl45_read(bp, params->port, ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_RX_SD, &rx_sd);
-
- bnx2x_cl45_read(bp, params->port, ext_phy_type,
- ext_phy_addr,
- 1,
- 0xc809, &val1);
- bnx2x_cl45_read(bp, params->port, ext_phy_type,
- ext_phy_addr,
- 1,
- 0xc809, &val1);
-
- DP(NETIF_MSG_LINK, "8705 1.c809 val=0x%x\n", val1);
- ext_phy_link_up = ((rx_sd & 0x1) && (val1 & (1<<9)) &&
- ((val1 & (1<<8)) == 0));
- if (ext_phy_link_up)
- vars->line_speed = SPEED_10000;
- break;
+ /* Check the LASI */
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM,
+ &rx_alarm_status);
+ vars->line_speed = 0;
+ DP(NETIF_MSG_LINK, "8727 RX_ALARM_STATUS 0x%x\n", rx_alarm_status);
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
- DP(NETIF_MSG_LINK, "XGXS 8706/8726\n");
- /* Clear RX Alarm*/
- bnx2x_cl45_read(bp, params->port, ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM,
- &val2);
- /* clear LASI indication*/
- bnx2x_cl45_read(bp, params->port, ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS,
- &val1);
- bnx2x_cl45_read(bp, params->port, ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS,
- &val2);
- DP(NETIF_MSG_LINK, "8706/8726 LASI status 0x%x-->"
- "0x%x\n", val1, val2);
-
- bnx2x_cl45_read(bp, params->port, ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_SD,
- &rx_sd);
- bnx2x_cl45_read(bp, params->port, ext_phy_type,
- ext_phy_addr,
- MDIO_PCS_DEVAD, MDIO_PCS_REG_STATUS,
- &pcs_status);
- bnx2x_cl45_read(bp, params->port, ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD, MDIO_AN_REG_LINK_STATUS,
- &val2);
- bnx2x_cl45_read(bp, params->port, ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD, MDIO_AN_REG_LINK_STATUS,
- &val2);
-
- DP(NETIF_MSG_LINK, "8706/8726 rx_sd 0x%x"
- " pcs_status 0x%x 1Gbps link_status 0x%x\n",
- rx_sd, pcs_status, val2);
- /* link is up if both bit 0 of pmd_rx_sd and
- * bit 0 of pcs_status are set, or if the autoneg bit
- 1 is set
- */
- ext_phy_link_up = ((rx_sd & pcs_status & 0x1) ||
- (val2 & (1<<1)));
- if (ext_phy_link_up) {
- if (ext_phy_type ==
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726) {
- /* If transmitter is disabled,
- ignore false link up indication */
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_PHY_IDENTIFIER,
- &val1);
- if (val1 & (1<<15)) {
- DP(NETIF_MSG_LINK, "Tx is "
- "disabled\n");
- ext_phy_link_up = 0;
- break;
- }
- }
- if (val2 & (1<<1))
- vars->line_speed = SPEED_1000;
- else
- vars->line_speed = SPEED_10000;
- }
- break;
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, &val1);
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
- {
- u16 link_status = 0;
- u16 rx_alarm_status;
- /* Check the LASI */
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_RX_ALARM, &rx_alarm_status);
-
- DP(NETIF_MSG_LINK, "8727 RX_ALARM_STATUS 0x%x\n",
- rx_alarm_status);
-
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_LASI_STATUS, &val1);
+ DP(NETIF_MSG_LINK, "8727 LASI status 0x%x\n", val1);
- DP(NETIF_MSG_LINK,
- "8727 LASI status 0x%x\n",
- val1);
+ /* Clear MSG-OUT */
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_M8051_MSGOUT_REG, &val1);
- /* Clear MSG-OUT */
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_M8051_MSGOUT_REG,
- &val1);
+ /**
+ * If a module is present and there is need to check
+ * for over current
+ */
+ if (!(phy->flags & FLAGS_NOC) && !(rx_alarm_status & (1<<5))) {
+ /* Check over-current using 8727 GPIO0 input*/
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_GPIO_CTRL,
+ &val1);
+
+ if ((val1 & (1<<8)) == 0) {
+ DP(NETIF_MSG_LINK, "8727 Power fault has been detected"
+ " on port %d\n", params->port);
+ netdev_err(bp->dev, "Error: Power fault on Port %d has"
+ " been detected and the power to "
+ "that SFP+ module has been removed"
+ " to prevent failure of the card."
+ " Please remove the SFP+ module and"
+ " restart the system to clear this"
+ " error.\n",
+ params->port);
/*
- * If a module is present and there is need to check
- * for over current
+ * Disable all RX_ALARMs except for
+ * mod_abs
*/
- if (!(params->feature_config_flags &
- FEATURE_CONFIG_BCM8727_NOC) &&
- !(rx_alarm_status & (1<<5))) {
- /* Check over-current using 8727 GPIO0 input*/
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_8727_GPIO_CTRL,
- &val1);
-
- if ((val1 & (1<<8)) == 0) {
- DP(NETIF_MSG_LINK, "8727 Power fault"
- " has been detected on "
- "port %d\n",
- params->port);
- netdev_err(bp->dev, "Error: Power fault on Port %d has been detected and the power to that SFP+ module has been removed to prevent failure of the card. Please remove the SFP+ module and restart the system to clear this error.\n",
- params->port);
- /*
- * Disable all RX_ALARMs except for
- * mod_abs
- */
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_RX_ALARM_CTRL,
- (1<<5));
-
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_PHY_IDENTIFIER,
- &val1);
- /* Wait for module_absent_event */
- val1 |= (1<<8);
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_PHY_IDENTIFIER,
- val1);
- /* Clear RX alarm */
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_RX_ALARM,
- &rx_alarm_status);
- break;
- }
- } /* Over current check */
-
- /* When module absent bit is set, check module */
- if (rx_alarm_status & (1<<5)) {
- bnx2x_8727_handle_mod_abs(params);
- /* Enable all mod_abs and link detection bits */
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_RX_ALARM_CTRL,
- ((1<<5) | (1<<2)));
- }
-
- /* If transmitter is disabled,
- ignore false link up indication */
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_PHY_IDENTIFIER,
- &val1);
- if (val1 & (1<<15)) {
- DP(NETIF_MSG_LINK, "Tx is disabled\n");
- ext_phy_link_up = 0;
- break;
- }
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_RX_ALARM_CTRL, (1<<5));
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_8073_SPEED_LINK_STATUS,
- &link_status);
-
- /* Bits 0..2 --> speed detected,
- bits 13..15--> link is down */
- if ((link_status & (1<<2)) &&
- (!(link_status & (1<<15)))) {
- ext_phy_link_up = 1;
- vars->line_speed = SPEED_10000;
- } else if ((link_status & (1<<0)) &&
- (!(link_status & (1<<13)))) {
- ext_phy_link_up = 1;
- vars->line_speed = SPEED_1000;
- DP(NETIF_MSG_LINK,
- "port %x: External link"
- " up in 1G\n", params->port);
- } else {
- ext_phy_link_up = 0;
- DP(NETIF_MSG_LINK,
- "port %x: External link"
- " is down\n", params->port);
- }
- break;
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_PHY_IDENTIFIER, &val1);
+ /* Wait for module_absent_event */
+ val1 |= (1<<8);
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_PHY_IDENTIFIER, val1);
+ /* Clear RX alarm */
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_RX_ALARM, &rx_alarm_status);
+ return 0;
}
+ } /* Over current check */
+
+ /* When module absent bit is set, check module */
+ if (rx_alarm_status & (1<<5)) {
+ bnx2x_8727_handle_mod_abs(phy, params);
+ /* Enable all mod_abs and link detection bits */
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM_CTRL,
+ ((1<<5) | (1<<2)));
+ }
+ DP(NETIF_MSG_LINK, "Enabling 8727 TX laser if SFP is approved\n");
+ bnx2x_8727_specific_func(phy, params, ENABLE_TX);
+ /* If transmitter is disabled, ignore false link up indication */
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, &val1);
+ if (val1 & (1<<15)) {
+ DP(NETIF_MSG_LINK, "Tx is disabled\n");
+ return 0;
+ }
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
- {
- u16 link_status = 0;
- u16 an1000_status = 0;
-
- if (ext_phy_type ==
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072) {
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PCS_DEVAD,
- MDIO_PCS_REG_LASI_STATUS, &val1);
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PCS_DEVAD,
- MDIO_PCS_REG_LASI_STATUS, &val2);
- DP(NETIF_MSG_LINK,
- "870x LASI status 0x%x->0x%x\n",
- val1, val2);
- } else {
- /* In 8073, port1 is directed through emac0 and
- * port0 is directed through emac1
- */
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_LASI_STATUS, &val1);
-
- DP(NETIF_MSG_LINK,
- "8703 LASI status 0x%x\n",
- val1);
- }
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8073_SPEED_LINK_STATUS, &link_status);
- /* clear the interrupt LASI status register */
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PCS_DEVAD,
- MDIO_PCS_REG_STATUS, &val2);
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PCS_DEVAD,
- MDIO_PCS_REG_STATUS, &val1);
- DP(NETIF_MSG_LINK, "807x PCS status 0x%x->0x%x\n",
- val2, val1);
- /* Clear MSG-OUT */
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_M8051_MSGOUT_REG,
- &val1);
-
- /* Check the LASI */
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_RX_ALARM, &val2);
-
- DP(NETIF_MSG_LINK, "KR 0x9003 0x%x\n", val2);
-
- /* Check the link status */
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PCS_DEVAD,
- MDIO_PCS_REG_STATUS, &val2);
- DP(NETIF_MSG_LINK, "KR PCS status 0x%x\n", val2);
-
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_STATUS, &val2);
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_STATUS, &val1);
- ext_phy_link_up = ((val1 & 4) == 4);
- DP(NETIF_MSG_LINK, "PMA_REG_STATUS=0x%x\n", val1);
- if (ext_phy_type ==
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
-
- if (ext_phy_link_up &&
- ((params->req_line_speed !=
- SPEED_10000))) {
- if (bnx2x_bcm8073_xaui_wa(params)
- != 0) {
- ext_phy_link_up = 0;
- break;
- }
- }
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_LINK_STATUS,
- &an1000_status);
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_LINK_STATUS,
- &an1000_status);
-
- /* Check the link status on 1.1.2 */
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_STATUS, &val2);
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_STATUS, &val1);
- DP(NETIF_MSG_LINK, "KR PMA status 0x%x->0x%x,"
- "an_link_status=0x%x\n",
- val2, val1, an1000_status);
-
- ext_phy_link_up = (((val1 & 4) == 4) ||
- (an1000_status & (1<<1)));
- if (ext_phy_link_up &&
- bnx2x_8073_is_snr_needed(params)) {
- /* The SNR will improve about 2dbby
- changing the BW and FEE main tap.*/
-
- /* The 1st write to change FFE main
- tap is set before restart AN */
- /* Change PLL Bandwidth in EDC
- register */
- bnx2x_cl45_write(bp, port, ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_PLL_BANDWIDTH,
- 0x26BC);
-
- /* Change CDR Bandwidth in EDC
- register */
- bnx2x_cl45_write(bp, port, ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_CDR_BANDWIDTH,
- 0x0333);
- }
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_8073_SPEED_LINK_STATUS,
- &link_status);
-
- /* Bits 0..2 --> speed detected,
- bits 13..15--> link is down */
- if ((link_status & (1<<2)) &&
- (!(link_status & (1<<15)))) {
- ext_phy_link_up = 1;
- vars->line_speed = SPEED_10000;
- DP(NETIF_MSG_LINK,
- "port %x: External link"
- " up in 10G\n", params->port);
- } else if ((link_status & (1<<1)) &&
- (!(link_status & (1<<14)))) {
- ext_phy_link_up = 1;
- vars->line_speed = SPEED_2500;
- DP(NETIF_MSG_LINK,
- "port %x: External link"
- " up in 2.5G\n", params->port);
- } else if ((link_status & (1<<0)) &&
- (!(link_status & (1<<13)))) {
- ext_phy_link_up = 1;
- vars->line_speed = SPEED_1000;
- DP(NETIF_MSG_LINK,
- "port %x: External link"
- " up in 1G\n", params->port);
- } else {
- ext_phy_link_up = 0;
- DP(NETIF_MSG_LINK,
- "port %x: External link"
- " is down\n", params->port);
- }
- } else {
- /* See if 1G link is up for the 8072 */
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_LINK_STATUS,
- &an1000_status);
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_LINK_STATUS,
- &an1000_status);
- if (an1000_status & (1<<1)) {
- ext_phy_link_up = 1;
- vars->line_speed = SPEED_1000;
- DP(NETIF_MSG_LINK,
- "port %x: External link"
- " up in 1G\n", params->port);
- } else if (ext_phy_link_up) {
- ext_phy_link_up = 1;
- vars->line_speed = SPEED_10000;
- DP(NETIF_MSG_LINK,
- "port %x: External link"
- " up in 10G\n", params->port);
- }
- }
+ /* Bits 0..2 --> speed detected,
+ bits 13..15--> link is down */
+ if ((link_status & (1<<2)) && (!(link_status & (1<<15)))) {
+ link_up = 1;
+ vars->line_speed = SPEED_10000;
+ } else if ((link_status & (1<<0)) && (!(link_status & (1<<13)))) {
+ link_up = 1;
+ vars->line_speed = SPEED_1000;
+ DP(NETIF_MSG_LINK, "port %x: External link up in 1G\n",
+ params->port);
+ } else {
+ link_up = 0;
+ DP(NETIF_MSG_LINK, "port %x: External link is down\n",
+ params->port);
+ }
+ if (link_up)
+ bnx2x_ext_phy_resolve_fc(phy, params, vars);
+
+ if ((DUAL_MEDIA(params)) &&
+ (phy->req_line_speed == SPEED_1000)) {
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8727_PCS_GP, &val1);
+ /**
+ * In case of dual-media board and 1G, power up the XAUI side,
+ * otherwise power it down. For 10G it is done automatically
+ */
+ if (link_up)
+ val1 &= ~(3<<10);
+ else
+ val1 |= (3<<10);
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8727_PCS_GP, val1);
+ }
+ return link_up;
+}
+static void bnx2x_8727_link_reset(struct bnx2x_phy *phy,
+ struct link_params *params)
+{
+ struct bnx2x *bp = params->bp;
+ /* Disable Transmitter */
+ bnx2x_sfp_set_transmitter(bp, phy, params->port, 0);
+ /* Clear LASI */
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 0);
- break;
- }
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
- bnx2x_cl45_read(bp, params->port, ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_LASI_STATUS, &val2);
- bnx2x_cl45_read(bp, params->port, ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_LASI_STATUS, &val1);
- DP(NETIF_MSG_LINK,
- "10G-base-T LASI status 0x%x->0x%x\n",
- val2, val1);
- bnx2x_cl45_read(bp, params->port, ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_STATUS, &val2);
- bnx2x_cl45_read(bp, params->port, ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_STATUS, &val1);
- DP(NETIF_MSG_LINK,
- "10G-base-T PMA status 0x%x->0x%x\n",
- val2, val1);
- ext_phy_link_up = ((val1 & 4) == 4);
- /* if link is up
- * print the AN outcome of the SFX7101 PHY
- */
- if (ext_phy_link_up) {
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_MASTER_STATUS,
- &val2);
- vars->line_speed = SPEED_10000;
- DP(NETIF_MSG_LINK,
- "SFX7101 AN status 0x%x->Master=%x\n",
- val2,
- (val2 & (1<<14)));
- }
- break;
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481:
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823:
- /* Check 10G-BaseT link status */
- /* Check PMD signal ok */
- bnx2x_cl45_read(bp, params->port, ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- 0xFFFA,
- &val1);
- bnx2x_cl45_read(bp, params->port, ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_8481_PMD_SIGNAL,
- &val2);
- DP(NETIF_MSG_LINK, "PMD_SIGNAL 1.a811 = 0x%x\n", val2);
-
- /* Check link 10G */
- if (val2 & (1<<11)) {
- vars->line_speed = SPEED_10000;
- ext_phy_link_up = 1;
- bnx2x_8481_set_10G_led_mode(params,
- ext_phy_type,
- ext_phy_addr);
- } else { /* Check Legacy speed link */
- u16 legacy_status, legacy_speed;
-
- /* Enable expansion register 0x42
- (Operation mode status) */
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_8481_EXPANSION_REG_ACCESS,
- 0xf42);
-
- /* Get legacy speed operation status */
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_8481_EXPANSION_REG_RD_RW,
- &legacy_status);
-
- DP(NETIF_MSG_LINK, "Legacy speed status"
- " = 0x%x\n", legacy_status);
- ext_phy_link_up = ((legacy_status & (1<<11))
- == (1<<11));
- if (ext_phy_link_up) {
- legacy_speed = (legacy_status & (3<<9));
- if (legacy_speed == (0<<9))
- vars->line_speed = SPEED_10;
- else if (legacy_speed == (1<<9))
- vars->line_speed =
- SPEED_100;
- else if (legacy_speed == (2<<9))
- vars->line_speed =
- SPEED_1000;
- else /* Should not happen */
- vars->line_speed = 0;
-
- if (legacy_status & (1<<8))
- vars->duplex = DUPLEX_FULL;
- else
- vars->duplex = DUPLEX_HALF;
-
- DP(NETIF_MSG_LINK, "Link is up "
- "in %dMbps, is_duplex_full"
- "= %d\n",
- vars->line_speed,
- (vars->duplex == DUPLEX_FULL));
- bnx2x_8481_set_legacy_led_mode(params,
- ext_phy_type,
- ext_phy_addr);
- }
- }
- break;
- default:
- DP(NETIF_MSG_LINK, "BAD XGXS ext_phy_config 0x%x\n",
- params->ext_phy_config);
- ext_phy_link_up = 0;
- break;
- }
- /* Set SGMII mode for external phy */
- if (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) {
- if (vars->line_speed < SPEED_1000)
- vars->phy_flags |= PHY_SGMII_FLAG;
- else
- vars->phy_flags &= ~PHY_SGMII_FLAG;
- }
+}
- } else { /* SerDes */
- ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
- switch (ext_phy_type) {
- case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT:
- DP(NETIF_MSG_LINK, "SerDes Direct\n");
- ext_phy_link_up = 1;
- break;
+/******************************************************************/
+/* BCM8481/BCM84823/BCM84833 PHY SECTION */
+/******************************************************************/
+static void bnx2x_save_848xx_spirom_version(struct bnx2x_phy *phy,
+ struct link_params *params)
+{
+ u16 val, fw_ver1, fw_ver2, cnt;
+ struct bnx2x *bp = params->bp;
- case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482:
- DP(NETIF_MSG_LINK, "SerDes 5482\n");
- ext_phy_link_up = 1;
+ /* For the 32 bits registers in 848xx, access via MDIO2ARM interface.*/
+ /* (1) set register 0xc200_0014(SPI_BRIDGE_CTRL_2) to 0x03000000 */
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA819, 0x0014);
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81A, 0xc200);
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81B, 0x0000);
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81C, 0x0300);
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA817, 0x0009);
+
+ for (cnt = 0; cnt < 100; cnt++) {
+ bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA818, &val);
+ if (val & 1)
break;
+ udelay(5);
+ }
+ if (cnt == 100) {
+ DP(NETIF_MSG_LINK, "Unable to read 848xx phy fw version(1)\n");
+ bnx2x_save_spirom_version(bp, params->port, 0,
+ phy->ver_addr);
+ return;
+ }
- default:
- DP(NETIF_MSG_LINK,
- "BAD SerDes ext_phy_config 0x%x\n",
- params->ext_phy_config);
- ext_phy_link_up = 0;
+
+ /* 2) read register 0xc200_0000 (SPI_FW_STATUS) */
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA819, 0x0000);
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81A, 0xc200);
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA817, 0x000A);
+ for (cnt = 0; cnt < 100; cnt++) {
+ bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA818, &val);
+ if (val & 1)
break;
- }
+ udelay(5);
+ }
+ if (cnt == 100) {
+ DP(NETIF_MSG_LINK, "Unable to read 848xx phy fw version(2)\n");
+ bnx2x_save_spirom_version(bp, params->port, 0,
+ phy->ver_addr);
+ return;
}
- return ext_phy_link_up;
+ /* lower 16 bits of the register SPI_FW_STATUS */
+ bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA81B, &fw_ver1);
+ /* upper 16 bits of register SPI_FW_STATUS */
+ bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA81C, &fw_ver2);
+
+ bnx2x_save_spirom_version(bp, params->port, (fw_ver2<<16) | fw_ver1,
+ phy->ver_addr);
}
-static void bnx2x_link_int_enable(struct link_params *params)
+static void bnx2x_848xx_set_led(struct bnx2x *bp,
+ struct bnx2x_phy *phy)
{
- u8 port = params->port;
- u32 ext_phy_type;
- u32 mask;
- struct bnx2x *bp = params->bp;
+ u16 val;
- /* setting the status to report on link up
- for either XGXS or SerDes */
+ /* PHYC_CTL_LED_CTL */
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8481_LINK_SIGNAL, &val);
+ val &= 0xFE00;
+ val |= 0x0092;
+
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8481_LINK_SIGNAL, val);
+
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8481_LED1_MASK,
+ 0x80);
+
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8481_LED2_MASK,
+ 0x18);
+
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8481_LED3_MASK,
+ 0x0040);
- if (params->switch_cfg == SWITCH_CFG_10G) {
- mask = (NIG_MASK_XGXS0_LINK10G |
- NIG_MASK_XGXS0_LINK_STATUS);
- DP(NETIF_MSG_LINK, "enabled XGXS interrupt\n");
- ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
- if ((ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) &&
- (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE) &&
- (ext_phy_type !=
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN)) {
- mask |= NIG_MASK_MI_INT;
- DP(NETIF_MSG_LINK, "enabled external phy int\n");
- }
+ /* 'Interrupt Mask' */
+ bnx2x_cl45_write(bp, phy,
+ MDIO_AN_DEVAD,
+ 0xFFFB, 0xFFFD);
+}
- } else { /* SerDes */
- mask = NIG_MASK_SERDES0_LINK_STATUS;
- DP(NETIF_MSG_LINK, "enabled SerDes interrupt\n");
- ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
- if ((ext_phy_type !=
- PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT) &&
- (ext_phy_type !=
- PORT_HW_CFG_SERDES_EXT_PHY_TYPE_NOT_CONN)) {
- mask |= NIG_MASK_MI_INT;
- DP(NETIF_MSG_LINK, "enabled external phy int\n");
- }
+static u8 bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
+{
+ struct bnx2x *bp = params->bp;
+ u16 autoneg_val, an_1000_val, an_10_100_val;
+ bnx2x_wait_reset_complete(bp, phy);
+ bnx2x_bits_en(bp, NIG_REG_LATCH_BC_0 + params->port*4,
+ 1 << NIG_LATCH_BC_ENABLE_MI_INT);
+
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x0000);
+
+ bnx2x_848xx_set_led(bp, phy);
+
+ /* set 1000 speed advertisement */
+ bnx2x_cl45_read(bp, phy,
+ MDIO_AN_DEVAD, MDIO_AN_REG_8481_1000T_CTRL,
+ &an_1000_val);
+
+ bnx2x_ext_phy_set_pause(params, phy, vars);
+ bnx2x_cl45_read(bp, phy,
+ MDIO_AN_DEVAD,
+ MDIO_AN_REG_8481_LEGACY_AN_ADV,
+ &an_10_100_val);
+ bnx2x_cl45_read(bp, phy,
+ MDIO_AN_DEVAD, MDIO_AN_REG_8481_LEGACY_MII_CTRL,
+ &autoneg_val);
+ /* Disable forced speed */
+ autoneg_val &= ~((1<<6) | (1<<8) | (1<<9) | (1<<12) | (1<<13));
+ an_10_100_val &= ~((1<<5) | (1<<6) | (1<<7) | (1<<8));
+
+ if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
+ (phy->speed_cap_mask &
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) ||
+ (phy->req_line_speed == SPEED_1000)) {
+ an_1000_val |= (1<<8);
+ autoneg_val |= (1<<9 | 1<<12);
+ if (phy->req_duplex == DUPLEX_FULL)
+ an_1000_val |= (1<<9);
+ DP(NETIF_MSG_LINK, "Advertising 1G\n");
+ } else
+ an_1000_val &= ~((1<<8) | (1<<9));
+
+ bnx2x_cl45_write(bp, phy,
+ MDIO_AN_DEVAD, MDIO_AN_REG_8481_1000T_CTRL,
+ an_1000_val);
+
+ /* set 10 speed advertisement */
+ if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
+ (phy->speed_cap_mask &
+ (PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL |
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF)))) {
+ an_10_100_val |= (1<<7);
+ /* Enable autoneg and restart autoneg for legacy speeds */
+ autoneg_val |= (1<<9 | 1<<12);
+
+ if (phy->req_duplex == DUPLEX_FULL)
+ an_10_100_val |= (1<<8);
+ DP(NETIF_MSG_LINK, "Advertising 100M\n");
+ }
+ /* set 10 speed advertisement */
+ if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
+ (phy->speed_cap_mask &
+ (PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL |
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF)))) {
+ an_10_100_val |= (1<<5);
+ autoneg_val |= (1<<9 | 1<<12);
+ if (phy->req_duplex == DUPLEX_FULL)
+ an_10_100_val |= (1<<6);
+ DP(NETIF_MSG_LINK, "Advertising 10M\n");
}
- bnx2x_bits_en(bp,
- NIG_REG_MASK_INTERRUPT_PORT0 + port*4,
- mask);
- DP(NETIF_MSG_LINK, "port %x, is_xgxs %x, int_status 0x%x\n", port,
- (params->switch_cfg == SWITCH_CFG_10G),
- REG_RD(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4));
- DP(NETIF_MSG_LINK, " int_mask 0x%x, MI_INT %x, SERDES_LINK %x\n",
- REG_RD(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4),
- REG_RD(bp, NIG_REG_EMAC0_STATUS_MISC_MI_INT + port*0x18),
- REG_RD(bp, NIG_REG_SERDES0_STATUS_LINK_STATUS+port*0x3c));
- DP(NETIF_MSG_LINK, " 10G %x, XGXS_LINK %x\n",
- REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK10G + port*0x68),
- REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68));
-}
+ /* Only 10/100 are allowed to work in FORCE mode */
+ if (phy->req_line_speed == SPEED_100) {
+ autoneg_val |= (1<<13);
+ /* Enabled AUTO-MDIX when autoneg is disabled */
+ bnx2x_cl45_write(bp, phy,
+ MDIO_AN_DEVAD, MDIO_AN_REG_8481_AUX_CTRL,
+ (1<<15 | 1<<9 | 7<<0));
+ DP(NETIF_MSG_LINK, "Setting 100M force\n");
+ }
+ if (phy->req_line_speed == SPEED_10) {
+ /* Enabled AUTO-MDIX when autoneg is disabled */
+ bnx2x_cl45_write(bp, phy,
+ MDIO_AN_DEVAD, MDIO_AN_REG_8481_AUX_CTRL,
+ (1<<15 | 1<<9 | 7<<0));
+ DP(NETIF_MSG_LINK, "Setting 10M force\n");
+ }
-static void bnx2x_8481_rearm_latch_signal(struct bnx2x *bp, u8 port,
- u8 is_mi_int)
-{
- u32 latch_status = 0, is_mi_int_status;
- /* Disable the MI INT ( external phy int )
- * by writing 1 to the status register. Link down indication
- * is high-active-signal, so in this case we need to write the
- * status to clear the XOR
- */
- /* Read Latched signals */
- latch_status = REG_RD(bp,
- NIG_REG_LATCH_STATUS_0 + port*8);
- is_mi_int_status = REG_RD(bp,
- NIG_REG_STATUS_INTERRUPT_PORT0 + port*4);
- DP(NETIF_MSG_LINK, "original_signal = 0x%x, nig_status = 0x%x,"
- "latch_status = 0x%x\n",
- is_mi_int, is_mi_int_status, latch_status);
- /* Handle only those with latched-signal=up.*/
- if (latch_status & 1) {
- /* For all latched-signal=up,Write original_signal to status */
- if (is_mi_int)
- bnx2x_bits_en(bp,
- NIG_REG_STATUS_INTERRUPT_PORT0
- + port*4,
- NIG_STATUS_EMAC0_MI_INT);
- else
- bnx2x_bits_dis(bp,
- NIG_REG_STATUS_INTERRUPT_PORT0
- + port*4,
- NIG_STATUS_EMAC0_MI_INT);
- /* For all latched-signal=up : Re-Arm Latch signals */
- REG_WR(bp, NIG_REG_LATCH_STATUS_0 + port*8,
- (latch_status & 0xfffe) | (latch_status & 1));
+ bnx2x_cl45_write(bp, phy,
+ MDIO_AN_DEVAD, MDIO_AN_REG_8481_LEGACY_AN_ADV,
+ an_10_100_val);
+
+ if (phy->req_duplex == DUPLEX_FULL)
+ autoneg_val |= (1<<8);
+
+ bnx2x_cl45_write(bp, phy,
+ MDIO_AN_DEVAD,
+ MDIO_AN_REG_8481_LEGACY_MII_CTRL, autoneg_val);
+
+ if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
+ (phy->speed_cap_mask &
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) ||
+ (phy->req_line_speed == SPEED_10000)) {
+ DP(NETIF_MSG_LINK, "Advertising 10G\n");
+ /* Restart autoneg for 10G*/
+
+ bnx2x_cl45_write(bp, phy,
+ MDIO_AN_DEVAD, MDIO_AN_REG_CTRL,
+ 0x3200);
+ } else if (phy->req_line_speed != SPEED_10 &&
+ phy->req_line_speed != SPEED_100) {
+ bnx2x_cl45_write(bp, phy,
+ MDIO_AN_DEVAD,
+ MDIO_AN_REG_8481_10GBASE_T_AN_CTRL,
+ 1);
}
+ /* Save spirom version */
+ bnx2x_save_848xx_spirom_version(phy, params);
+
+ return 0;
}
-/*
- * link management
- */
-static void bnx2x_link_int_ack(struct link_params *params,
- struct link_vars *vars, u8 is_10g,
- u8 is_mi_int)
+
+static u8 bnx2x_8481_config_init(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
- u8 port = params->port;
+ /* Restore normal power mode*/
+ bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
+ MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
- /* first reset all status
- * we assume only one line will be change at a time */
- bnx2x_bits_dis(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
- (NIG_STATUS_XGXS0_LINK10G |
- NIG_STATUS_XGXS0_LINK_STATUS |
- NIG_STATUS_SERDES0_LINK_STATUS));
- if ((XGXS_EXT_PHY_TYPE(params->ext_phy_config)
- == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481) ||
- (XGXS_EXT_PHY_TYPE(params->ext_phy_config)
- == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823)) {
- bnx2x_8481_rearm_latch_signal(bp, port, is_mi_int);
- }
- if (vars->phy_link_up) {
- if (is_10g) {
- /* Disable the 10G link interrupt
- * by writing 1 to the status register
- */
- DP(NETIF_MSG_LINK, "10G XGXS phy link up\n");
- bnx2x_bits_en(bp,
- NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
- NIG_STATUS_XGXS0_LINK10G);
+ /* HW reset */
+ bnx2x_ext_phy_hw_reset(bp, params->port);
- } else if (params->switch_cfg == SWITCH_CFG_10G) {
- /* Disable the link interrupt
- * by writing 1 to the relevant lane
- * in the status register
- */
- u32 ser_lane = ((params->lane_config &
- PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
- PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15);
+ return bnx2x_848xx_cmn_config_init(phy, params, vars);
+}
- DP(NETIF_MSG_LINK, "%d speed XGXS phy link up\n",
- vars->line_speed);
- bnx2x_bits_en(bp,
- NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
- ((1 << ser_lane) <<
- NIG_STATUS_XGXS0_LINK_STATUS_SIZE));
+static u8 bnx2x_848x3_config_init(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
+{
+ struct bnx2x *bp = params->bp;
+ u8 port = params->port, initialize = 1;
+ u16 val;
+ u16 temp;
+ u32 actual_phy_selection;
+ u8 rc = 0;
- } else { /* SerDes */
- DP(NETIF_MSG_LINK, "SerDes phy link up\n");
- /* Disable the link interrupt
- * by writing 1 to the status register
- */
- bnx2x_bits_en(bp,
- NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
- NIG_STATUS_SERDES0_LINK_STATUS);
- }
+ /* This is just for MDIO_CTL_REG_84823_MEDIA register. */
- } else { /* link_down */
+ msleep(1);
+ bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3,
+ MISC_REGISTERS_GPIO_OUTPUT_HIGH,
+ port);
+ msleep(200); /* 100 is not enough */
+
+ /* BCM84823 requires that XGXS links up first @ 10G for normal
+ behavior */
+ temp = vars->line_speed;
+ vars->line_speed = SPEED_10000;
+ bnx2x_set_autoneg(&params->phy[INT_PHY], params, vars, 0);
+ bnx2x_program_serdes(&params->phy[INT_PHY], params, vars);
+ vars->line_speed = temp;
+
+ /* Set dual-media configuration according to configuration */
+
+ bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
+ MDIO_CTL_REG_84823_MEDIA, &val);
+ val &= ~(MDIO_CTL_REG_84823_MEDIA_MAC_MASK |
+ MDIO_CTL_REG_84823_MEDIA_LINE_MASK |
+ MDIO_CTL_REG_84823_MEDIA_COPPER_CORE_DOWN |
+ MDIO_CTL_REG_84823_MEDIA_PRIORITY_MASK |
+ MDIO_CTL_REG_84823_MEDIA_FIBER_1G);
+ val |= MDIO_CTL_REG_84823_CTRL_MAC_XFI |
+ MDIO_CTL_REG_84823_MEDIA_LINE_XAUI_L;
+
+ actual_phy_selection = bnx2x_phy_selection(params);
+
+ switch (actual_phy_selection) {
+ case PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT:
+ /* Do nothing. Essentialy this is like the priority copper */
+ break;
+ case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY:
+ val |= MDIO_CTL_REG_84823_MEDIA_PRIORITY_COPPER;
+ break;
+ case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY:
+ val |= MDIO_CTL_REG_84823_MEDIA_PRIORITY_FIBER;
+ break;
+ case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY:
+ /* Do nothing here. The first PHY won't be initialized at all */
+ break;
+ case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY:
+ val |= MDIO_CTL_REG_84823_MEDIA_COPPER_CORE_DOWN;
+ initialize = 0;
+ break;
}
+ if (params->phy[EXT_PHY2].req_line_speed == SPEED_1000)
+ val |= MDIO_CTL_REG_84823_MEDIA_FIBER_1G;
+
+ bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
+ MDIO_CTL_REG_84823_MEDIA, val);
+ DP(NETIF_MSG_LINK, "Multi_phy config = 0x%x, Media control = 0x%x\n",
+ params->multi_phy_config, val);
+
+ if (initialize)
+ rc = bnx2x_848xx_cmn_config_init(phy, params, vars);
+ else
+ bnx2x_save_848xx_spirom_version(phy, params);
+ return rc;
}
-static u8 bnx2x_format_ver(u32 num, u8 *str, u16 len)
+static u8 bnx2x_848xx_read_status(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
{
- u8 *str_ptr = str;
- u32 mask = 0xf0000000;
- u8 shift = 8*4;
- u8 digit;
- if (len < 10) {
- /* Need more than 10chars for this format */
- *str_ptr = '\0';
- return -EINVAL;
- }
- while (shift > 0) {
+ struct bnx2x *bp = params->bp;
+ u16 val, val1, val2;
+ u8 link_up = 0;
+
+ /* Check 10G-BaseT link status */
+ /* Check PMD signal ok */
+ bnx2x_cl45_read(bp, phy,
+ MDIO_AN_DEVAD, 0xFFFA, &val1);
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_PMD_SIGNAL,
+ &val2);
+ DP(NETIF_MSG_LINK, "BCM848xx: PMD_SIGNAL 1.a811 = 0x%x\n", val2);
+
+ /* Check link 10G */
+ if (val2 & (1<<11)) {
+ vars->line_speed = SPEED_10000;
+ link_up = 1;
+ bnx2x_ext_phy_10G_an_resolve(bp, phy, vars);
+ } else { /* Check Legacy speed link */
+ u16 legacy_status, legacy_speed;
+
+ /* Enable expansion register 0x42 (Operation mode status) */
+ bnx2x_cl45_write(bp, phy,
+ MDIO_AN_DEVAD,
+ MDIO_AN_REG_8481_EXPANSION_REG_ACCESS, 0xf42);
+
+ /* Get legacy speed operation status */
+ bnx2x_cl45_read(bp, phy,
+ MDIO_AN_DEVAD,
+ MDIO_AN_REG_8481_EXPANSION_REG_RD_RW,
+ &legacy_status);
+
+ DP(NETIF_MSG_LINK, "Legacy speed status"
+ " = 0x%x\n", legacy_status);
+ link_up = ((legacy_status & (1<<11)) == (1<<11));
+ if (link_up) {
+ legacy_speed = (legacy_status & (3<<9));
+ if (legacy_speed == (0<<9))
+ vars->line_speed = SPEED_10;
+ else if (legacy_speed == (1<<9))
+ vars->line_speed = SPEED_100;
+ else if (legacy_speed == (2<<9))
+ vars->line_speed = SPEED_1000;
+ else /* Should not happen */
+ vars->line_speed = 0;
- shift -= 4;
- digit = ((num & mask) >> shift);
- if (digit < 0xa)
- *str_ptr = digit + '0';
- else
- *str_ptr = digit - 0xa + 'a';
- str_ptr++;
- mask = mask >> 4;
- if (shift == 4*4) {
- *str_ptr = ':';
- str_ptr++;
+ if (legacy_status & (1<<8))
+ vars->duplex = DUPLEX_FULL;
+ else
+ vars->duplex = DUPLEX_HALF;
+
+ DP(NETIF_MSG_LINK, "Link is up in %dMbps,"
+ " is_duplex_full= %d\n", vars->line_speed,
+ (vars->duplex == DUPLEX_FULL));
+ /* Check legacy speed AN resolution */
+ bnx2x_cl45_read(bp, phy,
+ MDIO_AN_DEVAD,
+ MDIO_AN_REG_8481_LEGACY_MII_STATUS,
+ &val);
+ if (val & (1<<5))
+ vars->link_status |=
+ LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
+ bnx2x_cl45_read(bp, phy,
+ MDIO_AN_DEVAD,
+ MDIO_AN_REG_8481_LEGACY_AN_EXPANSION,
+ &val);
+ if ((val & (1<<0)) == 0)
+ vars->link_status |=
+ LINK_STATUS_PARALLEL_DETECTION_USED;
}
}
- *str_ptr = '\0';
- return 0;
+ if (link_up) {
+ DP(NETIF_MSG_LINK, "BCM84823: link speed is %d\n",
+ vars->line_speed);
+ bnx2x_ext_phy_resolve_fc(phy, params, vars);
+ }
+
+ return link_up;
}
-u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded,
- u8 *version, u16 len)
+static u8 bnx2x_848xx_format_ver(u32 raw_ver, u8 *str, u16 *len)
{
- struct bnx2x *bp;
- u32 ext_phy_type = 0;
- u32 spirom_ver = 0;
- u8 status;
+ u8 status = 0;
+ u32 spirom_ver;
+ spirom_ver = ((raw_ver & 0xF80) >> 7) << 16 | (raw_ver & 0x7F);
+ status = bnx2x_format_ver(spirom_ver, str, len);
+ return status;
+}
- if (version == NULL || params == NULL)
- return -EINVAL;
- bp = params->bp;
+static void bnx2x_8481_hw_reset(struct bnx2x_phy *phy,
+ struct link_params *params)
+{
+ bnx2x_set_gpio(params->bp, MISC_REGISTERS_GPIO_1,
+ MISC_REGISTERS_GPIO_OUTPUT_LOW, 0);
+ bnx2x_set_gpio(params->bp, MISC_REGISTERS_GPIO_1,
+ MISC_REGISTERS_GPIO_OUTPUT_LOW, 1);
+}
- spirom_ver = REG_RD(bp, params->shmem_base +
- offsetof(struct shmem_region,
- port_mb[params->port].ext_phy_fw_version));
+static void bnx2x_8481_link_reset(struct bnx2x_phy *phy,
+ struct link_params *params)
+{
+ bnx2x_cl45_write(params->bp, phy,
+ MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x0000);
+ bnx2x_cl45_write(params->bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1);
+}
- status = 0;
- /* reset the returned value to zero */
- ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
- switch (ext_phy_type) {
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
+static void bnx2x_848x3_link_reset(struct bnx2x_phy *phy,
+ struct link_params *params)
+{
+ struct bnx2x *bp = params->bp;
+ u8 port = params->port;
+ bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3,
+ MISC_REGISTERS_GPIO_OUTPUT_LOW,
+ port);
+}
- if (len < 5)
- return -EINVAL;
+static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy,
+ struct link_params *params, u8 mode)
+{
+ struct bnx2x *bp = params->bp;
+ u16 val;
- version[0] = (spirom_ver & 0xFF);
- version[1] = (spirom_ver & 0xFF00) >> 8;
- version[2] = (spirom_ver & 0xFF0000) >> 16;
- version[3] = (spirom_ver & 0xFF000000) >> 24;
- version[4] = '\0';
+ switch (mode) {
+ case LED_MODE_OFF:
- break;
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
- status = bnx2x_format_ver(spirom_ver, version, len);
- break;
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481:
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823:
- spirom_ver = ((spirom_ver & 0xF80) >> 7) << 16 |
- (spirom_ver & 0x7F);
- status = bnx2x_format_ver(spirom_ver, version, len);
- break;
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
- version[0] = '\0';
- break;
+ DP(NETIF_MSG_LINK, "Port 0x%x: LED MODE OFF\n", params->port);
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
- DP(NETIF_MSG_LINK, "bnx2x_get_ext_phy_fw_version:"
- " type is FAILURE!\n");
- status = -EINVAL;
+ if ((params->hw_led_mode << SHARED_HW_CFG_LED_MODE_SHIFT) ==
+ SHARED_HW_CFG_LED_EXTPHY1) {
+
+ /* Set LED masks */
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8481_LED1_MASK,
+ 0x0);
+
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8481_LED2_MASK,
+ 0x0);
+
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8481_LED3_MASK,
+ 0x0);
+
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8481_LED5_MASK,
+ 0x0);
+
+ } else {
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8481_LED1_MASK,
+ 0x0);
+ }
break;
+ case LED_MODE_FRONT_PANEL_OFF:
- default:
+ DP(NETIF_MSG_LINK, "Port 0x%x: LED MODE FRONT PANEL OFF\n",
+ params->port);
+
+ if ((params->hw_led_mode << SHARED_HW_CFG_LED_MODE_SHIFT) ==
+ SHARED_HW_CFG_LED_EXTPHY1) {
+
+ /* Set LED masks */
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8481_LED1_MASK,
+ 0x0);
+
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8481_LED2_MASK,
+ 0x0);
+
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8481_LED3_MASK,
+ 0x0);
+
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8481_LED5_MASK,
+ 0x20);
+
+ } else {
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8481_LED1_MASK,
+ 0x0);
+ }
break;
- }
- return status;
-}
+ case LED_MODE_ON:
-static void bnx2x_set_xgxs_loopback(struct link_params *params,
- struct link_vars *vars,
- u8 is_10g)
-{
- u8 port = params->port;
- struct bnx2x *bp = params->bp;
+ DP(NETIF_MSG_LINK, "Port 0x%x: LED MODE ON\n", params->port);
- if (is_10g) {
- u32 md_devad;
+ if ((params->hw_led_mode << SHARED_HW_CFG_LED_MODE_SHIFT) ==
+ SHARED_HW_CFG_LED_EXTPHY1) {
+ /* Set control reg */
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8481_LINK_SIGNAL,
+ &val);
+ val &= 0x8000;
+ val |= 0x2492;
- DP(NETIF_MSG_LINK, "XGXS 10G loopback enable\n");
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8481_LINK_SIGNAL,
+ val);
- /* change the uni_phy_addr in the nig */
- md_devad = REG_RD(bp, (NIG_REG_XGXS0_CTRL_MD_DEVAD +
- port*0x18));
+ /* Set LED masks */
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8481_LED1_MASK,
+ 0x0);
- REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18, 0x5);
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8481_LED2_MASK,
+ 0x20);
- bnx2x_cl45_write(bp, port, 0,
- params->phy_addr,
- 5,
- (MDIO_REG_BANK_AER_BLOCK +
- (MDIO_AER_BLOCK_AER_REG & 0xf)),
- 0x2800);
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8481_LED3_MASK,
+ 0x20);
- bnx2x_cl45_write(bp, port, 0,
- params->phy_addr,
- 5,
- (MDIO_REG_BANK_CL73_IEEEB0 +
- (MDIO_CL73_IEEEB0_CL73_AN_CONTROL & 0xf)),
- 0x6041);
- msleep(200);
- /* set aer mmd back */
- bnx2x_set_aer_mmd(params, vars);
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8481_LED5_MASK,
+ 0x0);
+ } else {
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8481_LED1_MASK,
+ 0x20);
+ }
+ break;
- /* and md_devad */
- REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18,
- md_devad);
+ case LED_MODE_OPER:
- } else {
- u16 mii_control;
+ DP(NETIF_MSG_LINK, "Port 0x%x: LED MODE OPER\n", params->port);
- DP(NETIF_MSG_LINK, "XGXS 1G loopback enable\n");
+ if ((params->hw_led_mode << SHARED_HW_CFG_LED_MODE_SHIFT) ==
+ SHARED_HW_CFG_LED_EXTPHY1) {
- CL45_RD_OVER_CL22(bp, port,
- params->phy_addr,
- MDIO_REG_BANK_COMBO_IEEE0,
- MDIO_COMBO_IEEE0_MII_CONTROL,
- &mii_control);
+ /* Set control reg */
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8481_LINK_SIGNAL,
+ &val);
+
+ if (!((val &
+ MDIO_PMA_REG_8481_LINK_SIGNAL_LED4_ENABLE_MASK)
+ >> MDIO_PMA_REG_8481_LINK_SIGNAL_LED4_ENABLE_SHIFT)){
+ DP(NETIF_MSG_LINK, "Seting LINK_SIGNAL\n");
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8481_LINK_SIGNAL,
+ 0xa492);
+ }
- CL45_WR_OVER_CL22(bp, port,
- params->phy_addr,
- MDIO_REG_BANK_COMBO_IEEE0,
- MDIO_COMBO_IEEE0_MII_CONTROL,
- (mii_control |
- MDIO_COMBO_IEEO_MII_CONTROL_LOOPBACK));
+ /* Set LED masks */
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8481_LED1_MASK,
+ 0x10);
+
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8481_LED2_MASK,
+ 0x80);
+
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8481_LED3_MASK,
+ 0x98);
+
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8481_LED5_MASK,
+ 0x40);
+
+ } else {
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_8481_LED1_MASK,
+ 0x80);
+ }
+ break;
}
}
+/******************************************************************/
+/* SFX7101 PHY SECTION */
+/******************************************************************/
+static void bnx2x_7101_config_loopback(struct bnx2x_phy *phy,
+ struct link_params *params)
+{
+ struct bnx2x *bp = params->bp;
+ /* SFX7101_XGXS_TEST1 */
+ bnx2x_cl45_write(bp, phy,
+ MDIO_XS_DEVAD, MDIO_XS_SFX7101_XGXS_TEST1, 0x100);
+}
-
-static void bnx2x_ext_phy_loopback(struct link_params *params)
+static u8 bnx2x_7101_config_init(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
{
+ u16 fw_ver1, fw_ver2, val;
struct bnx2x *bp = params->bp;
- u8 ext_phy_addr;
- u32 ext_phy_type;
+ DP(NETIF_MSG_LINK, "Setting the SFX7101 LASI indication\n");
- if (params->switch_cfg == SWITCH_CFG_10G) {
- ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
- ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
- /* CL37 Autoneg Enabled */
- switch (ext_phy_type) {
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN:
- DP(NETIF_MSG_LINK,
- "ext_phy_loopback: We should not get here\n");
- break;
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
- DP(NETIF_MSG_LINK, "ext_phy_loopback: 8705\n");
- break;
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
- DP(NETIF_MSG_LINK, "ext_phy_loopback: 8706\n");
- break;
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
- DP(NETIF_MSG_LINK, "PMA/PMD ext_phy_loopback: 8726\n");
- bnx2x_cl45_write(bp, params->port, ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_CTRL,
- 0x0001);
- break;
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
- /* SFX7101_XGXS_TEST1 */
- bnx2x_cl45_write(bp, params->port, ext_phy_type,
- ext_phy_addr,
- MDIO_XS_DEVAD,
- MDIO_XS_SFX7101_XGXS_TEST1,
- 0x100);
- DP(NETIF_MSG_LINK,
- "ext_phy_loopback: set ext phy loopback\n");
- break;
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
+ /* Restore normal power mode*/
+ bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
+ MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
+ /* HW reset */
+ bnx2x_ext_phy_hw_reset(bp, params->port);
+ bnx2x_wait_reset_complete(bp, phy);
+
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 0x1);
+ DP(NETIF_MSG_LINK, "Setting the SFX7101 LED to blink on traffic\n");
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_7107_LED_CNTL, (1<<3));
+
+ bnx2x_ext_phy_set_pause(params, phy, vars);
+ /* Restart autoneg */
+ bnx2x_cl45_read(bp, phy,
+ MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, &val);
+ val |= 0x200;
+ bnx2x_cl45_write(bp, phy,
+ MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, val);
+
+ /* Save spirom version */
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_7101_VER1, &fw_ver1);
+
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_7101_VER2, &fw_ver2);
+ bnx2x_save_spirom_version(bp, params->port,
+ (u32)(fw_ver1<<16 | fw_ver2), phy->ver_addr);
+ return 0;
+}
- break;
- } /* switch external PHY type */
- } else {
- /* serdes */
- ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
- ext_phy_addr = (params->ext_phy_config &
- PORT_HW_CFG_SERDES_EXT_PHY_ADDR_MASK)
- >> PORT_HW_CFG_SERDES_EXT_PHY_ADDR_SHIFT;
+static u8 bnx2x_7101_read_status(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
+{
+ struct bnx2x *bp = params->bp;
+ u8 link_up;
+ u16 val1, val2;
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, &val2);
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, &val1);
+ DP(NETIF_MSG_LINK, "10G-base-T LASI status 0x%x->0x%x\n",
+ val2, val1);
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val2);
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val1);
+ DP(NETIF_MSG_LINK, "10G-base-T PMA status 0x%x->0x%x\n",
+ val2, val1);
+ link_up = ((val1 & 4) == 4);
+ /* if link is up
+ * print the AN outcome of the SFX7101 PHY
+ */
+ if (link_up) {
+ bnx2x_cl45_read(bp, phy,
+ MDIO_AN_DEVAD, MDIO_AN_REG_MASTER_STATUS,
+ &val2);
+ vars->line_speed = SPEED_10000;
+ DP(NETIF_MSG_LINK, "SFX7101 AN status 0x%x->Master=%x\n",
+ val2, (val2 & (1<<14)));
+ bnx2x_ext_phy_10G_an_resolve(bp, phy, vars);
+ bnx2x_ext_phy_resolve_fc(phy, params, vars);
}
+ return link_up;
}
-/*
- *------------------------------------------------------------------------
- * bnx2x_override_led_value -
- *
- * Override the led value of the requsted led
- *
- *------------------------------------------------------------------------
- */
-u8 bnx2x_override_led_value(struct bnx2x *bp, u8 port,
- u32 led_idx, u32 value)
+static u8 bnx2x_7101_format_ver(u32 spirom_ver, u8 *str, u16 *len)
{
- u32 reg_val;
+ if (*len < 5)
+ return -EINVAL;
+ str[0] = (spirom_ver & 0xFF);
+ str[1] = (spirom_ver & 0xFF00) >> 8;
+ str[2] = (spirom_ver & 0xFF0000) >> 16;
+ str[3] = (spirom_ver & 0xFF000000) >> 24;
+ str[4] = '\0';
+ *len -= 5;
+ return 0;
+}
- /* If port 0 then use EMAC0, else use EMAC1*/
- u32 emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
+void bnx2x_sfx7101_sp_sw_reset(struct bnx2x *bp, struct bnx2x_phy *phy)
+{
+ u16 val, cnt;
- DP(NETIF_MSG_LINK,
- "bnx2x_override_led_value() port %x led_idx %d value %d\n",
- port, led_idx, value);
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_7101_RESET, &val);
- switch (led_idx) {
- case 0: /* 10MB led */
- /* Read the current value of the LED register in
- the EMAC block */
- reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED);
- /* Set the OVERRIDE bit to 1 */
- reg_val |= EMAC_LED_OVERRIDE;
- /* If value is 1, set the 10M_OVERRIDE bit,
- otherwise reset it.*/
- reg_val = (value == 1) ? (reg_val | EMAC_LED_10MB_OVERRIDE) :
- (reg_val & ~EMAC_LED_10MB_OVERRIDE);
- REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val);
- break;
- case 1: /*100MB led */
- /*Read the current value of the LED register in
- the EMAC block */
- reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED);
- /* Set the OVERRIDE bit to 1 */
- reg_val |= EMAC_LED_OVERRIDE;
- /* If value is 1, set the 100M_OVERRIDE bit,
- otherwise reset it.*/
- reg_val = (value == 1) ? (reg_val | EMAC_LED_100MB_OVERRIDE) :
- (reg_val & ~EMAC_LED_100MB_OVERRIDE);
- REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val);
+ for (cnt = 0; cnt < 10; cnt++) {
+ msleep(50);
+ /* Writes a self-clearing reset */
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_7101_RESET,
+ (val | (1<<15)));
+ /* Wait for clear */
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_7101_RESET, &val);
+
+ if ((val & (1<<15)) == 0)
+ break;
+ }
+}
+
+static void bnx2x_7101_hw_reset(struct bnx2x_phy *phy,
+ struct link_params *params) {
+ /* Low power mode is controlled by GPIO 2 */
+ bnx2x_set_gpio(params->bp, MISC_REGISTERS_GPIO_2,
+ MISC_REGISTERS_GPIO_OUTPUT_LOW, params->port);
+ /* The PHY reset is controlled by GPIO 1 */
+ bnx2x_set_gpio(params->bp, MISC_REGISTERS_GPIO_1,
+ MISC_REGISTERS_GPIO_OUTPUT_LOW, params->port);
+}
+
+static void bnx2x_7101_set_link_led(struct bnx2x_phy *phy,
+ struct link_params *params, u8 mode)
+{
+ u16 val = 0;
+ struct bnx2x *bp = params->bp;
+ switch (mode) {
+ case LED_MODE_FRONT_PANEL_OFF:
+ case LED_MODE_OFF:
+ val = 2;
break;
- case 2: /* 1000MB led */
- /* Read the current value of the LED register in the
- EMAC block */
- reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED);
- /* Set the OVERRIDE bit to 1 */
- reg_val |= EMAC_LED_OVERRIDE;
- /* If value is 1, set the 1000M_OVERRIDE bit, otherwise
- reset it. */
- reg_val = (value == 1) ? (reg_val | EMAC_LED_1000MB_OVERRIDE) :
- (reg_val & ~EMAC_LED_1000MB_OVERRIDE);
- REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val);
+ case LED_MODE_ON:
+ val = 1;
break;
- case 3: /* 2500MB led */
- /* Read the current value of the LED register in the
- EMAC block*/
- reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED);
- /* Set the OVERRIDE bit to 1 */
- reg_val |= EMAC_LED_OVERRIDE;
- /* If value is 1, set the 2500M_OVERRIDE bit, otherwise
- reset it.*/
- reg_val = (value == 1) ? (reg_val | EMAC_LED_2500MB_OVERRIDE) :
- (reg_val & ~EMAC_LED_2500MB_OVERRIDE);
- REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val);
+ case LED_MODE_OPER:
+ val = 0;
break;
- case 4: /*10G led */
- if (port == 0) {
- REG_WR(bp, NIG_REG_LED_10G_P0,
- value);
+ }
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_7107_LINK_LED_CNTL,
+ val);
+}
+
+/******************************************************************/
+/* STATIC PHY DECLARATION */
+/******************************************************************/
+
+static struct bnx2x_phy phy_null = {
+ .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN,
+ .addr = 0,
+ .flags = FLAGS_INIT_XGXS_FIRST,
+ .def_md_devad = 0,
+ .reserved = 0,
+ .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+ .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+ .mdio_ctrl = 0,
+ .supported = 0,
+ .media_type = ETH_PHY_NOT_PRESENT,
+ .ver_addr = 0,
+ .req_flow_ctrl = 0,
+ .req_line_speed = 0,
+ .speed_cap_mask = 0,
+ .req_duplex = 0,
+ .rsrv = 0,
+ .config_init = (config_init_t)NULL,
+ .read_status = (read_status_t)NULL,
+ .link_reset = (link_reset_t)NULL,
+ .config_loopback = (config_loopback_t)NULL,
+ .format_fw_ver = (format_fw_ver_t)NULL,
+ .hw_reset = (hw_reset_t)NULL,
+ .set_link_led = (set_link_led_t)NULL,
+ .phy_specific_func = (phy_specific_func_t)NULL
+};
+
+static struct bnx2x_phy phy_serdes = {
+ .type = PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT,
+ .addr = 0xff,
+ .flags = 0,
+ .def_md_devad = 0,
+ .reserved = 0,
+ .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+ .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+ .mdio_ctrl = 0,
+ .supported = (SUPPORTED_10baseT_Half |
+ SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full |
+ SUPPORTED_1000baseT_Full |
+ SUPPORTED_2500baseX_Full |
+ SUPPORTED_TP |
+ SUPPORTED_Autoneg |
+ SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause),
+ .media_type = ETH_PHY_UNSPECIFIED,
+ .ver_addr = 0,
+ .req_flow_ctrl = 0,
+ .req_line_speed = 0,
+ .speed_cap_mask = 0,
+ .req_duplex = 0,
+ .rsrv = 0,
+ .config_init = (config_init_t)bnx2x_init_serdes,
+ .read_status = (read_status_t)bnx2x_link_settings_status,
+ .link_reset = (link_reset_t)bnx2x_int_link_reset,
+ .config_loopback = (config_loopback_t)NULL,
+ .format_fw_ver = (format_fw_ver_t)NULL,
+ .hw_reset = (hw_reset_t)NULL,
+ .set_link_led = (set_link_led_t)NULL,
+ .phy_specific_func = (phy_specific_func_t)NULL
+};
+
+static struct bnx2x_phy phy_xgxs = {
+ .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT,
+ .addr = 0xff,
+ .flags = 0,
+ .def_md_devad = 0,
+ .reserved = 0,
+ .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+ .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+ .mdio_ctrl = 0,
+ .supported = (SUPPORTED_10baseT_Half |
+ SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full |
+ SUPPORTED_1000baseT_Full |
+ SUPPORTED_2500baseX_Full |
+ SUPPORTED_10000baseT_Full |
+ SUPPORTED_FIBRE |
+ SUPPORTED_Autoneg |
+ SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause),
+ .media_type = ETH_PHY_UNSPECIFIED,
+ .ver_addr = 0,
+ .req_flow_ctrl = 0,
+ .req_line_speed = 0,
+ .speed_cap_mask = 0,
+ .req_duplex = 0,
+ .rsrv = 0,
+ .config_init = (config_init_t)bnx2x_init_xgxs,
+ .read_status = (read_status_t)bnx2x_link_settings_status,
+ .link_reset = (link_reset_t)bnx2x_int_link_reset,
+ .config_loopback = (config_loopback_t)bnx2x_set_xgxs_loopback,
+ .format_fw_ver = (format_fw_ver_t)NULL,
+ .hw_reset = (hw_reset_t)NULL,
+ .set_link_led = (set_link_led_t)NULL,
+ .phy_specific_func = (phy_specific_func_t)NULL
+};
+
+static struct bnx2x_phy phy_7101 = {
+ .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
+ .addr = 0xff,
+ .flags = FLAGS_FAN_FAILURE_DET_REQ,
+ .def_md_devad = 0,
+ .reserved = 0,
+ .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+ .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+ .mdio_ctrl = 0,
+ .supported = (SUPPORTED_10000baseT_Full |
+ SUPPORTED_TP |
+ SUPPORTED_Autoneg |
+ SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause),
+ .media_type = ETH_PHY_BASE_T,
+ .ver_addr = 0,
+ .req_flow_ctrl = 0,
+ .req_line_speed = 0,
+ .speed_cap_mask = 0,
+ .req_duplex = 0,
+ .rsrv = 0,
+ .config_init = (config_init_t)bnx2x_7101_config_init,
+ .read_status = (read_status_t)bnx2x_7101_read_status,
+ .link_reset = (link_reset_t)bnx2x_common_ext_link_reset,
+ .config_loopback = (config_loopback_t)bnx2x_7101_config_loopback,
+ .format_fw_ver = (format_fw_ver_t)bnx2x_7101_format_ver,
+ .hw_reset = (hw_reset_t)bnx2x_7101_hw_reset,
+ .set_link_led = (set_link_led_t)bnx2x_7101_set_link_led,
+ .phy_specific_func = (phy_specific_func_t)NULL
+};
+static struct bnx2x_phy phy_8073 = {
+ .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
+ .addr = 0xff,
+ .flags = FLAGS_HW_LOCK_REQUIRED,
+ .def_md_devad = 0,
+ .reserved = 0,
+ .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+ .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+ .mdio_ctrl = 0,
+ .supported = (SUPPORTED_10000baseT_Full |
+ SUPPORTED_2500baseX_Full |
+ SUPPORTED_1000baseT_Full |
+ SUPPORTED_FIBRE |
+ SUPPORTED_Autoneg |
+ SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause),
+ .media_type = ETH_PHY_UNSPECIFIED,
+ .ver_addr = 0,
+ .req_flow_ctrl = 0,
+ .req_line_speed = 0,
+ .speed_cap_mask = 0,
+ .req_duplex = 0,
+ .rsrv = 0,
+ .config_init = (config_init_t)bnx2x_8073_config_init,
+ .read_status = (read_status_t)bnx2x_8073_read_status,
+ .link_reset = (link_reset_t)bnx2x_8073_link_reset,
+ .config_loopback = (config_loopback_t)NULL,
+ .format_fw_ver = (format_fw_ver_t)bnx2x_format_ver,
+ .hw_reset = (hw_reset_t)NULL,
+ .set_link_led = (set_link_led_t)NULL,
+ .phy_specific_func = (phy_specific_func_t)NULL
+};
+static struct bnx2x_phy phy_8705 = {
+ .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705,
+ .addr = 0xff,
+ .flags = FLAGS_INIT_XGXS_FIRST,
+ .def_md_devad = 0,
+ .reserved = 0,
+ .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+ .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+ .mdio_ctrl = 0,
+ .supported = (SUPPORTED_10000baseT_Full |
+ SUPPORTED_FIBRE |
+ SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause),
+ .media_type = ETH_PHY_XFP_FIBER,
+ .ver_addr = 0,
+ .req_flow_ctrl = 0,
+ .req_line_speed = 0,
+ .speed_cap_mask = 0,
+ .req_duplex = 0,
+ .rsrv = 0,
+ .config_init = (config_init_t)bnx2x_8705_config_init,
+ .read_status = (read_status_t)bnx2x_8705_read_status,
+ .link_reset = (link_reset_t)bnx2x_common_ext_link_reset,
+ .config_loopback = (config_loopback_t)NULL,
+ .format_fw_ver = (format_fw_ver_t)bnx2x_null_format_ver,
+ .hw_reset = (hw_reset_t)NULL,
+ .set_link_led = (set_link_led_t)NULL,
+ .phy_specific_func = (phy_specific_func_t)NULL
+};
+static struct bnx2x_phy phy_8706 = {
+ .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706,
+ .addr = 0xff,
+ .flags = FLAGS_INIT_XGXS_FIRST,
+ .def_md_devad = 0,
+ .reserved = 0,
+ .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+ .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+ .mdio_ctrl = 0,
+ .supported = (SUPPORTED_10000baseT_Full |
+ SUPPORTED_1000baseT_Full |
+ SUPPORTED_FIBRE |
+ SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause),
+ .media_type = ETH_PHY_SFP_FIBER,
+ .ver_addr = 0,
+ .req_flow_ctrl = 0,
+ .req_line_speed = 0,
+ .speed_cap_mask = 0,
+ .req_duplex = 0,
+ .rsrv = 0,
+ .config_init = (config_init_t)bnx2x_8706_config_init,
+ .read_status = (read_status_t)bnx2x_8706_read_status,
+ .link_reset = (link_reset_t)bnx2x_common_ext_link_reset,
+ .config_loopback = (config_loopback_t)NULL,
+ .format_fw_ver = (format_fw_ver_t)bnx2x_format_ver,
+ .hw_reset = (hw_reset_t)NULL,
+ .set_link_led = (set_link_led_t)NULL,
+ .phy_specific_func = (phy_specific_func_t)NULL
+};
+
+static struct bnx2x_phy phy_8726 = {
+ .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726,
+ .addr = 0xff,
+ .flags = (FLAGS_HW_LOCK_REQUIRED |
+ FLAGS_INIT_XGXS_FIRST),
+ .def_md_devad = 0,
+ .reserved = 0,
+ .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+ .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+ .mdio_ctrl = 0,
+ .supported = (SUPPORTED_10000baseT_Full |
+ SUPPORTED_1000baseT_Full |
+ SUPPORTED_Autoneg |
+ SUPPORTED_FIBRE |
+ SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause),
+ .media_type = ETH_PHY_SFP_FIBER,
+ .ver_addr = 0,
+ .req_flow_ctrl = 0,
+ .req_line_speed = 0,
+ .speed_cap_mask = 0,
+ .req_duplex = 0,
+ .rsrv = 0,
+ .config_init = (config_init_t)bnx2x_8726_config_init,
+ .read_status = (read_status_t)bnx2x_8726_read_status,
+ .link_reset = (link_reset_t)bnx2x_8726_link_reset,
+ .config_loopback = (config_loopback_t)bnx2x_8726_config_loopback,
+ .format_fw_ver = (format_fw_ver_t)bnx2x_format_ver,
+ .hw_reset = (hw_reset_t)NULL,
+ .set_link_led = (set_link_led_t)NULL,
+ .phy_specific_func = (phy_specific_func_t)NULL
+};
+
+static struct bnx2x_phy phy_8727 = {
+ .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
+ .addr = 0xff,
+ .flags = FLAGS_FAN_FAILURE_DET_REQ,
+ .def_md_devad = 0,
+ .reserved = 0,
+ .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+ .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+ .mdio_ctrl = 0,
+ .supported = (SUPPORTED_10000baseT_Full |
+ SUPPORTED_1000baseT_Full |
+ SUPPORTED_FIBRE |
+ SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause),
+ .media_type = ETH_PHY_SFP_FIBER,
+ .ver_addr = 0,
+ .req_flow_ctrl = 0,
+ .req_line_speed = 0,
+ .speed_cap_mask = 0,
+ .req_duplex = 0,
+ .rsrv = 0,
+ .config_init = (config_init_t)bnx2x_8727_config_init,
+ .read_status = (read_status_t)bnx2x_8727_read_status,
+ .link_reset = (link_reset_t)bnx2x_8727_link_reset,
+ .config_loopback = (config_loopback_t)NULL,
+ .format_fw_ver = (format_fw_ver_t)bnx2x_format_ver,
+ .hw_reset = (hw_reset_t)bnx2x_8727_hw_reset,
+ .set_link_led = (set_link_led_t)bnx2x_8727_set_link_led,
+ .phy_specific_func = (phy_specific_func_t)bnx2x_8727_specific_func
+};
+static struct bnx2x_phy phy_8481 = {
+ .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
+ .addr = 0xff,
+ .flags = FLAGS_FAN_FAILURE_DET_REQ |
+ FLAGS_REARM_LATCH_SIGNAL,
+ .def_md_devad = 0,
+ .reserved = 0,
+ .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+ .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+ .mdio_ctrl = 0,
+ .supported = (SUPPORTED_10baseT_Half |
+ SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full |
+ SUPPORTED_1000baseT_Full |
+ SUPPORTED_10000baseT_Full |
+ SUPPORTED_TP |
+ SUPPORTED_Autoneg |
+ SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause),
+ .media_type = ETH_PHY_BASE_T,
+ .ver_addr = 0,
+ .req_flow_ctrl = 0,
+ .req_line_speed = 0,
+ .speed_cap_mask = 0,
+ .req_duplex = 0,
+ .rsrv = 0,
+ .config_init = (config_init_t)bnx2x_8481_config_init,
+ .read_status = (read_status_t)bnx2x_848xx_read_status,
+ .link_reset = (link_reset_t)bnx2x_8481_link_reset,
+ .config_loopback = (config_loopback_t)NULL,
+ .format_fw_ver = (format_fw_ver_t)bnx2x_848xx_format_ver,
+ .hw_reset = (hw_reset_t)bnx2x_8481_hw_reset,
+ .set_link_led = (set_link_led_t)bnx2x_848xx_set_link_led,
+ .phy_specific_func = (phy_specific_func_t)NULL
+};
+
+static struct bnx2x_phy phy_84823 = {
+ .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823,
+ .addr = 0xff,
+ .flags = FLAGS_FAN_FAILURE_DET_REQ |
+ FLAGS_REARM_LATCH_SIGNAL,
+ .def_md_devad = 0,
+ .reserved = 0,
+ .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+ .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+ .mdio_ctrl = 0,
+ .supported = (SUPPORTED_10baseT_Half |
+ SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full |
+ SUPPORTED_1000baseT_Full |
+ SUPPORTED_10000baseT_Full |
+ SUPPORTED_TP |
+ SUPPORTED_Autoneg |
+ SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause),
+ .media_type = ETH_PHY_BASE_T,
+ .ver_addr = 0,
+ .req_flow_ctrl = 0,
+ .req_line_speed = 0,
+ .speed_cap_mask = 0,
+ .req_duplex = 0,
+ .rsrv = 0,
+ .config_init = (config_init_t)bnx2x_848x3_config_init,
+ .read_status = (read_status_t)bnx2x_848xx_read_status,
+ .link_reset = (link_reset_t)bnx2x_848x3_link_reset,
+ .config_loopback = (config_loopback_t)NULL,
+ .format_fw_ver = (format_fw_ver_t)bnx2x_848xx_format_ver,
+ .hw_reset = (hw_reset_t)NULL,
+ .set_link_led = (set_link_led_t)bnx2x_848xx_set_link_led,
+ .phy_specific_func = (phy_specific_func_t)NULL
+};
+
+/*****************************************************************/
+/* */
+/* Populate the phy according. Main function: bnx2x_populate_phy */
+/* */
+/*****************************************************************/
+
+static void bnx2x_populate_preemphasis(struct bnx2x *bp, u32 shmem_base,
+ struct bnx2x_phy *phy, u8 port,
+ u8 phy_index)
+{
+ /* Get the 4 lanes xgxs config rx and tx */
+ u32 rx = 0, tx = 0, i;
+ for (i = 0; i < 2; i++) {
+ /**
+ * INT_PHY and EXT_PHY1 share the same value location in the
+ * shmem. When num_phys is greater than 1, than this value
+ * applies only to EXT_PHY1
+ */
+ if (phy_index == INT_PHY || phy_index == EXT_PHY1) {
+ rx = REG_RD(bp, shmem_base +
+ offsetof(struct shmem_region,
+ dev_info.port_hw_config[port].xgxs_config_rx[i<<1]));
+
+ tx = REG_RD(bp, shmem_base +
+ offsetof(struct shmem_region,
+ dev_info.port_hw_config[port].xgxs_config_tx[i<<1]));
} else {
- REG_WR(bp, NIG_REG_LED_10G_P1,
- value);
+ rx = REG_RD(bp, shmem_base +
+ offsetof(struct shmem_region,
+ dev_info.port_hw_config[port].xgxs_config2_rx[i<<1]));
+
+ tx = REG_RD(bp, shmem_base +
+ offsetof(struct shmem_region,
+ dev_info.port_hw_config[port].xgxs_config2_rx[i<<1]));
}
+
+ phy->rx_preemphasis[i << 1] = ((rx>>16) & 0xffff);
+ phy->rx_preemphasis[(i << 1) + 1] = (rx & 0xffff);
+
+ phy->tx_preemphasis[i << 1] = ((tx>>16) & 0xffff);
+ phy->tx_preemphasis[(i << 1) + 1] = (tx & 0xffff);
+ }
+}
+
+static u32 bnx2x_get_ext_phy_config(struct bnx2x *bp, u32 shmem_base,
+ u8 phy_index, u8 port)
+{
+ u32 ext_phy_config = 0;
+ switch (phy_index) {
+ case EXT_PHY1:
+ ext_phy_config = REG_RD(bp, shmem_base +
+ offsetof(struct shmem_region,
+ dev_info.port_hw_config[port].external_phy_config));
break;
- case 5: /* TRAFFIC led */
- /* Find if the traffic control is via BMAC or EMAC */
- if (port == 0)
- reg_val = REG_RD(bp, NIG_REG_NIG_EMAC0_EN);
- else
- reg_val = REG_RD(bp, NIG_REG_NIG_EMAC1_EN);
+ case EXT_PHY2:
+ ext_phy_config = REG_RD(bp, shmem_base +
+ offsetof(struct shmem_region,
+ dev_info.port_hw_config[port].external_phy_config2));
+ break;
+ default:
+ DP(NETIF_MSG_LINK, "Invalid phy_index %d\n", phy_index);
+ return -EINVAL;
+ }
- /* Override the traffic led in the EMAC:*/
- if (reg_val == 1) {
- /* Read the current value of the LED register in
- the EMAC block */
- reg_val = REG_RD(bp, emac_base +
- EMAC_REG_EMAC_LED);
- /* Set the TRAFFIC_OVERRIDE bit to 1 */
- reg_val |= EMAC_LED_OVERRIDE;
- /* If value is 1, set the TRAFFIC bit, otherwise
- reset it.*/
- reg_val = (value == 1) ? (reg_val | EMAC_LED_TRAFFIC) :
- (reg_val & ~EMAC_LED_TRAFFIC);
- REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val);
- } else { /* Override the traffic led in the BMAC: */
- REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0
- + port*4, 1);
- REG_WR(bp, NIG_REG_LED_CONTROL_TRAFFIC_P0 + port*4,
- value);
- }
+ return ext_phy_config;
+}
+static u8 bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port,
+ struct bnx2x_phy *phy)
+{
+ u32 phy_addr;
+ u32 chip_id;
+ u32 switch_cfg = (REG_RD(bp, shmem_base +
+ offsetof(struct shmem_region,
+ dev_info.port_feature_config[port].link_config)) &
+ PORT_FEATURE_CONNECTED_SWITCH_MASK);
+ chip_id = REG_RD(bp, MISC_REG_CHIP_NUM) << 16;
+ switch (switch_cfg) {
+ case SWITCH_CFG_1G:
+ phy_addr = REG_RD(bp,
+ NIG_REG_SERDES0_CTRL_PHY_ADDR +
+ port * 0x10);
+ *phy = phy_serdes;
+ break;
+ case SWITCH_CFG_10G:
+ phy_addr = REG_RD(bp,
+ NIG_REG_XGXS0_CTRL_PHY_ADDR +
+ port * 0x18);
+ *phy = phy_xgxs;
break;
default:
- DP(NETIF_MSG_LINK,
- "bnx2x_override_led_value() unknown led index %d "
- "(should be 0-5)\n", led_idx);
+ DP(NETIF_MSG_LINK, "Invalid switch_cfg\n");
return -EINVAL;
}
+ phy->addr = (u8)phy_addr;
+ phy->mdio_ctrl = bnx2x_get_emac_base(bp,
+ SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH,
+ port);
+ if (CHIP_IS_E2(bp))
+ phy->def_md_devad = E2_DEFAULT_PHY_DEV_ADDR;
+ else
+ phy->def_md_devad = DEFAULT_PHY_DEV_ADDR;
+ DP(NETIF_MSG_LINK, "Internal phy port=%d, addr=0x%x, mdio_ctl=0x%x\n",
+ port, phy->addr, phy->mdio_ctrl);
+
+ bnx2x_populate_preemphasis(bp, shmem_base, phy, port, INT_PHY);
return 0;
}
-
-u8 bnx2x_set_led(struct link_params *params, u8 mode, u32 speed)
+static u8 bnx2x_populate_ext_phy(struct bnx2x *bp,
+ u8 phy_index,
+ u32 shmem_base,
+ u32 shmem2_base,
+ u8 port,
+ struct bnx2x_phy *phy)
{
- u8 port = params->port;
- u16 hw_led_mode = params->hw_led_mode;
- u8 rc = 0;
- u32 tmp;
- u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
- u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
- struct bnx2x *bp = params->bp;
- DP(NETIF_MSG_LINK, "bnx2x_set_led: port %x, mode %d\n", port, mode);
- DP(NETIF_MSG_LINK, "speed 0x%x, hw_led_mode 0x%x\n",
- speed, hw_led_mode);
- switch (mode) {
- case LED_MODE_OFF:
- REG_WR(bp, NIG_REG_LED_10G_P0 + port*4, 0);
- REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4,
- SHARED_HW_CFG_LED_MAC1);
-
- tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED);
- EMAC_WR(bp, EMAC_REG_EMAC_LED, (tmp | EMAC_LED_OVERRIDE));
+ u32 ext_phy_config, phy_type, config2;
+ u32 mdc_mdio_access = SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH;
+ ext_phy_config = bnx2x_get_ext_phy_config(bp, shmem_base,
+ phy_index, port);
+ phy_type = XGXS_EXT_PHY_TYPE(ext_phy_config);
+ /* Select the phy type */
+ switch (phy_type) {
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
+ mdc_mdio_access = SHARED_HW_CFG_MDC_MDIO_ACCESS1_SWAPPED;
+ *phy = phy_8073;
+ break;
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
+ *phy = phy_8705;
+ break;
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
+ *phy = phy_8706;
+ break;
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
+ mdc_mdio_access = SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC1;
+ *phy = phy_8726;
+ break;
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727_NOC:
+ /* BCM8727_NOC => BCM8727 no over current */
+ mdc_mdio_access = SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC1;
+ *phy = phy_8727;
+ phy->flags |= FLAGS_NOC;
+ break;
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
+ mdc_mdio_access = SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC1;
+ *phy = phy_8727;
break;
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481:
+ *phy = phy_8481;
+ break;
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823:
+ *phy = phy_84823;
+ break;
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
+ *phy = phy_7101;
+ break;
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
+ *phy = phy_null;
+ return -EINVAL;
+ default:
+ *phy = phy_null;
+ return 0;
+ }
- case LED_MODE_OPER:
- if (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) {
- REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, 0);
- REG_WR(bp, NIG_REG_LED_10G_P0 + port*4, 1);
- } else {
- REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4,
- hw_led_mode);
- }
+ phy->addr = XGXS_EXT_PHY_ADDR(ext_phy_config);
+ bnx2x_populate_preemphasis(bp, shmem_base, phy, port, phy_index);
- REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0 +
- port*4, 0);
- /* Set blinking rate to ~15.9Hz */
- REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_RATE_P0 + port*4,
- LED_BLINK_RATE_VAL);
- REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_RATE_ENA_P0 +
- port*4, 1);
- tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED);
- EMAC_WR(bp, EMAC_REG_EMAC_LED,
- (tmp & (~EMAC_LED_OVERRIDE)));
+ /**
+ * The shmem address of the phy version is located on different
+ * structures. In case this structure is too old, do not set
+ * the address
+ */
+ config2 = REG_RD(bp, shmem_base + offsetof(struct shmem_region,
+ dev_info.shared_hw_config.config2));
+ if (phy_index == EXT_PHY1) {
+ phy->ver_addr = shmem_base + offsetof(struct shmem_region,
+ port_mb[port].ext_phy_fw_version);
+
+ /* Check specific mdc mdio settings */
+ if (config2 & SHARED_HW_CFG_MDC_MDIO_ACCESS1_MASK)
+ mdc_mdio_access = config2 &
+ SHARED_HW_CFG_MDC_MDIO_ACCESS1_MASK;
+ } else {
+ u32 size = REG_RD(bp, shmem2_base);
- if (CHIP_IS_E1(bp) &&
- ((speed == SPEED_2500) ||
- (speed == SPEED_1000) ||
- (speed == SPEED_100) ||
- (speed == SPEED_10))) {
- /* On Everest 1 Ax chip versions for speeds less than
- 10G LED scheme is different */
- REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0
- + port*4, 1);
- REG_WR(bp, NIG_REG_LED_CONTROL_TRAFFIC_P0 +
- port*4, 0);
- REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_TRAFFIC_P0 +
- port*4, 1);
+ if (size >
+ offsetof(struct shmem2_region, ext_phy_fw_version2)) {
+ phy->ver_addr = shmem2_base +
+ offsetof(struct shmem2_region,
+ ext_phy_fw_version2[port]);
}
- break;
-
- default:
- rc = -EINVAL;
- DP(NETIF_MSG_LINK, "bnx2x_set_led: Invalid led mode %d\n",
- mode);
- break;
+ /* Check specific mdc mdio settings */
+ if (config2 & SHARED_HW_CFG_MDC_MDIO_ACCESS2_MASK)
+ mdc_mdio_access = (config2 &
+ SHARED_HW_CFG_MDC_MDIO_ACCESS2_MASK) >>
+ (SHARED_HW_CFG_MDC_MDIO_ACCESS2_SHIFT -
+ SHARED_HW_CFG_MDC_MDIO_ACCESS1_SHIFT);
}
- return rc;
+ phy->mdio_ctrl = bnx2x_get_emac_base(bp, mdc_mdio_access, port);
+ /**
+ * In case mdc/mdio_access of the external phy is different than the
+ * mdc/mdio access of the XGXS, a HW lock must be taken in each access
+ * to prevent one port interfere with another port's CL45 operations.
+ */
+ if (mdc_mdio_access != SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH)
+ phy->flags |= FLAGS_HW_LOCK_REQUIRED;
+ DP(NETIF_MSG_LINK, "phy_type 0x%x port %d found in index %d\n",
+ phy_type, port, phy_index);
+ DP(NETIF_MSG_LINK, " addr=0x%x, mdio_ctl=0x%x\n",
+ phy->addr, phy->mdio_ctrl);
+ return 0;
}
-u8 bnx2x_test_link(struct link_params *params, struct link_vars *vars)
+static u8 bnx2x_populate_phy(struct bnx2x *bp, u8 phy_index, u32 shmem_base,
+ u32 shmem2_base, u8 port, struct bnx2x_phy *phy)
{
- struct bnx2x *bp = params->bp;
- u16 gp_status = 0;
-
- CL45_RD_OVER_CL22(bp, params->port,
- params->phy_addr,
- MDIO_REG_BANK_GP_STATUS,
- MDIO_GP_STATUS_TOP_AN_STATUS1,
- &gp_status);
- /* link is up only if both local phy and external phy are up */
- if ((gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) &&
- bnx2x_ext_phy_is_link_up(params, vars, 1))
- return 0;
-
- return -ESRCH;
+ u8 status = 0;
+ phy->type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN;
+ if (phy_index == INT_PHY)
+ return bnx2x_populate_int_phy(bp, shmem_base, port, phy);
+ status = bnx2x_populate_ext_phy(bp, phy_index, shmem_base, shmem2_base,
+ port, phy);
+ return status;
}
-static u8 bnx2x_link_initialize(struct link_params *params,
- struct link_vars *vars)
+static void bnx2x_phy_def_cfg(struct link_params *params,
+ struct bnx2x_phy *phy,
+ u8 phy_index)
{
struct bnx2x *bp = params->bp;
- u8 port = params->port;
- u8 rc = 0;
- u8 non_ext_phy;
- u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
-
- /* Activate the external PHY */
- bnx2x_ext_phy_reset(params, vars);
-
- bnx2x_set_aer_mmd(params, vars);
+ u32 link_config;
+ /* Populate the default phy configuration for MF mode */
+ if (phy_index == EXT_PHY2) {
+ link_config = REG_RD(bp, params->shmem_base +
+ offsetof(struct shmem_region, dev_info.
+ port_feature_config[params->port].link_config2));
+ phy->speed_cap_mask = REG_RD(bp, params->shmem_base +
+ offsetof(struct shmem_region, dev_info.
+ port_hw_config[params->port].speed_capability_mask2));
+ } else {
+ link_config = REG_RD(bp, params->shmem_base +
+ offsetof(struct shmem_region, dev_info.
+ port_feature_config[params->port].link_config));
+ phy->speed_cap_mask = REG_RD(bp, params->shmem_base +
+ offsetof(struct shmem_region, dev_info.
+ port_hw_config[params->port].speed_capability_mask));
+ }
+ DP(NETIF_MSG_LINK, "Default config phy idx %x cfg 0x%x speed_cap_mask"
+ " 0x%x\n", phy_index, link_config, phy->speed_cap_mask);
+
+ phy->req_duplex = DUPLEX_FULL;
+ switch (link_config & PORT_FEATURE_LINK_SPEED_MASK) {
+ case PORT_FEATURE_LINK_SPEED_10M_HALF:
+ phy->req_duplex = DUPLEX_HALF;
+ case PORT_FEATURE_LINK_SPEED_10M_FULL:
+ phy->req_line_speed = SPEED_10;
+ break;
+ case PORT_FEATURE_LINK_SPEED_100M_HALF:
+ phy->req_duplex = DUPLEX_HALF;
+ case PORT_FEATURE_LINK_SPEED_100M_FULL:
+ phy->req_line_speed = SPEED_100;
+ break;
+ case PORT_FEATURE_LINK_SPEED_1G:
+ phy->req_line_speed = SPEED_1000;
+ break;
+ case PORT_FEATURE_LINK_SPEED_2_5G:
+ phy->req_line_speed = SPEED_2500;
+ break;
+ case PORT_FEATURE_LINK_SPEED_10G_CX4:
+ phy->req_line_speed = SPEED_10000;
+ break;
+ default:
+ phy->req_line_speed = SPEED_AUTO_NEG;
+ break;
+ }
- if (vars->phy_flags & PHY_XGXS_FLAG)
- bnx2x_set_master_ln(params);
+ switch (link_config & PORT_FEATURE_FLOW_CONTROL_MASK) {
+ case PORT_FEATURE_FLOW_CONTROL_AUTO:
+ phy->req_flow_ctrl = BNX2X_FLOW_CTRL_AUTO;
+ break;
+ case PORT_FEATURE_FLOW_CONTROL_TX:
+ phy->req_flow_ctrl = BNX2X_FLOW_CTRL_TX;
+ break;
+ case PORT_FEATURE_FLOW_CONTROL_RX:
+ phy->req_flow_ctrl = BNX2X_FLOW_CTRL_RX;
+ break;
+ case PORT_FEATURE_FLOW_CONTROL_BOTH:
+ phy->req_flow_ctrl = BNX2X_FLOW_CTRL_BOTH;
+ break;
+ default:
+ phy->req_flow_ctrl = BNX2X_FLOW_CTRL_NONE;
+ break;
+ }
+}
- rc = bnx2x_reset_unicore(params);
- /* reset the SerDes and wait for reset bit return low */
- if (rc != 0)
- return rc;
+u32 bnx2x_phy_selection(struct link_params *params)
+{
+ u32 phy_config_swapped, prio_cfg;
+ u32 return_cfg = PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT;
+
+ phy_config_swapped = params->multi_phy_config &
+ PORT_HW_CFG_PHY_SWAPPED_ENABLED;
+
+ prio_cfg = params->multi_phy_config &
+ PORT_HW_CFG_PHY_SELECTION_MASK;
+
+ if (phy_config_swapped) {
+ switch (prio_cfg) {
+ case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY:
+ return_cfg = PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY;
+ break;
+ case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY:
+ return_cfg = PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY;
+ break;
+ case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY:
+ return_cfg = PORT_HW_CFG_PHY_SELECTION_FIRST_PHY;
+ break;
+ case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY:
+ return_cfg = PORT_HW_CFG_PHY_SELECTION_SECOND_PHY;
+ break;
+ }
+ } else
+ return_cfg = prio_cfg;
- bnx2x_set_aer_mmd(params, vars);
+ return return_cfg;
+}
- /* setting the masterLn_def again after the reset */
- if (vars->phy_flags & PHY_XGXS_FLAG) {
- bnx2x_set_master_ln(params);
- bnx2x_set_swap_lanes(params);
- }
- if (vars->phy_flags & PHY_XGXS_FLAG) {
- if ((params->req_line_speed &&
- ((params->req_line_speed == SPEED_100) ||
- (params->req_line_speed == SPEED_10))) ||
- (!params->req_line_speed &&
- (params->speed_cap_mask >=
- PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL) &&
- (params->speed_cap_mask <
- PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)
- )) {
- vars->phy_flags |= PHY_SGMII_FLAG;
- } else {
- vars->phy_flags &= ~PHY_SGMII_FLAG;
+u8 bnx2x_phy_probe(struct link_params *params)
+{
+ u8 phy_index, actual_phy_idx, link_cfg_idx;
+ u32 phy_config_swapped;
+ struct bnx2x *bp = params->bp;
+ struct bnx2x_phy *phy;
+ params->num_phys = 0;
+ DP(NETIF_MSG_LINK, "Begin phy probe\n");
+ phy_config_swapped = params->multi_phy_config &
+ PORT_HW_CFG_PHY_SWAPPED_ENABLED;
+
+ for (phy_index = INT_PHY; phy_index < MAX_PHYS;
+ phy_index++) {
+ link_cfg_idx = LINK_CONFIG_IDX(phy_index);
+ actual_phy_idx = phy_index;
+ if (phy_config_swapped) {
+ if (phy_index == EXT_PHY1)
+ actual_phy_idx = EXT_PHY2;
+ else if (phy_index == EXT_PHY2)
+ actual_phy_idx = EXT_PHY1;
+ }
+ DP(NETIF_MSG_LINK, "phy_config_swapped %x, phy_index %x,"
+ " actual_phy_idx %x\n", phy_config_swapped,
+ phy_index, actual_phy_idx);
+ phy = &params->phy[actual_phy_idx];
+ if (bnx2x_populate_phy(bp, phy_index, params->shmem_base,
+ params->shmem2_base, params->port,
+ phy) != 0) {
+ params->num_phys = 0;
+ DP(NETIF_MSG_LINK, "phy probe failed in phy index %d\n",
+ phy_index);
+ for (phy_index = INT_PHY;
+ phy_index < MAX_PHYS;
+ phy_index++)
+ *phy = phy_null;
+ return -EINVAL;
}
+ if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN)
+ break;
+
+ bnx2x_phy_def_cfg(params, phy, phy_index);
+ params->num_phys++;
}
- /* In case of external phy existance, the line speed would be the
- line speed linked up by the external phy. In case it is direct only,
- then the line_speed during initialization will be equal to the
- req_line_speed*/
- vars->line_speed = params->req_line_speed;
- bnx2x_calc_ieee_aneg_adv(params, &vars->ieee_fc);
+ DP(NETIF_MSG_LINK, "End phy probe. #phys found %x\n", params->num_phys);
+ return 0;
+}
- /* init ext phy and enable link state int */
- non_ext_phy = ((ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) ||
- (params->loopback_mode == LOOPBACK_XGXS_10));
+u32 bnx2x_supported_attr(struct link_params *params, u8 phy_idx)
+{
+ if (phy_idx < params->num_phys)
+ return params->phy[phy_idx].supported;
+ return 0;
+}
- if (non_ext_phy ||
- (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705) ||
- (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706) ||
- (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726) ||
- (params->loopback_mode == LOOPBACK_EXT_PHY)) {
- if (params->req_line_speed == SPEED_AUTO_NEG)
- bnx2x_set_parallel_detection(params, vars->phy_flags);
- bnx2x_init_internal_phy(params, vars, non_ext_phy);
- }
+static void set_phy_vars(struct link_params *params)
+{
+ struct bnx2x *bp = params->bp;
+ u8 actual_phy_idx, phy_index, link_cfg_idx;
+ u8 phy_config_swapped = params->multi_phy_config &
+ PORT_HW_CFG_PHY_SWAPPED_ENABLED;
+ for (phy_index = INT_PHY; phy_index < params->num_phys;
+ phy_index++) {
+ link_cfg_idx = LINK_CONFIG_IDX(phy_index);
+ actual_phy_idx = phy_index;
+ if (phy_config_swapped) {
+ if (phy_index == EXT_PHY1)
+ actual_phy_idx = EXT_PHY2;
+ else if (phy_index == EXT_PHY2)
+ actual_phy_idx = EXT_PHY1;
+ }
+ params->phy[actual_phy_idx].req_flow_ctrl =
+ params->req_flow_ctrl[link_cfg_idx];
- if (!non_ext_phy)
- rc |= bnx2x_ext_phy_init(params, vars);
+ params->phy[actual_phy_idx].req_line_speed =
+ params->req_line_speed[link_cfg_idx];
- bnx2x_bits_dis(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
- (NIG_STATUS_XGXS0_LINK10G |
- NIG_STATUS_XGXS0_LINK_STATUS |
- NIG_STATUS_SERDES0_LINK_STATUS));
+ params->phy[actual_phy_idx].speed_cap_mask =
+ params->speed_cap_mask[link_cfg_idx];
- return rc;
+ params->phy[actual_phy_idx].req_duplex =
+ params->req_duplex[link_cfg_idx];
+ DP(NETIF_MSG_LINK, "req_flow_ctrl %x, req_line_speed %x,"
+ " speed_cap_mask %x\n",
+ params->phy[actual_phy_idx].req_flow_ctrl,
+ params->phy[actual_phy_idx].req_line_speed,
+ params->phy[actual_phy_idx].speed_cap_mask);
+ }
}
-
u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
- u32 val;
-
DP(NETIF_MSG_LINK, "Phy Initialization started\n");
- DP(NETIF_MSG_LINK, "req_speed %d, req_flowctrl %d\n",
- params->req_line_speed, params->req_flow_ctrl);
+ DP(NETIF_MSG_LINK, "(1) req_speed %d, req_flowctrl %d\n",
+ params->req_line_speed[0], params->req_flow_ctrl[0]);
+ DP(NETIF_MSG_LINK, "(2) req_speed %d, req_flowctrl %d\n",
+ params->req_line_speed[1], params->req_flow_ctrl[1]);
vars->link_status = 0;
vars->phy_link_up = 0;
vars->link_up = 0;
@@ -5966,11 +6877,7 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
vars->duplex = DUPLEX_FULL;
vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
vars->mac_type = MAC_TYPE_NONE;
-
- if (params->switch_cfg == SWITCH_CFG_1G)
- vars->phy_flags = PHY_SERDES_FLAG;
- else
- vars->phy_flags = PHY_XGXS_FLAG;
+ vars->phy_flags = 0;
/* disable attentions */
bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + params->port*4,
@@ -5981,6 +6888,13 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
bnx2x_emac_init(params, vars);
+ if (params->num_phys == 0) {
+ DP(NETIF_MSG_LINK, "No phy found for initialization !!\n");
+ return -EINVAL;
+ }
+ set_phy_vars(params);
+
+ DP(NETIF_MSG_LINK, "Num of phys on board: %d\n", params->num_phys);
if (CHIP_REV_IS_FPGA(bp)) {
vars->link_up = 1;
@@ -5999,7 +6913,9 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
}
bnx2x_emac_enable(params, vars, 0);
- bnx2x_pbf_update(params, vars->flow_ctrl, vars->line_speed);
+ if (!(CHIP_IS_E2(bp)))
+ bnx2x_pbf_update(params, vars->flow_ctrl,
+ vars->line_speed);
/* disable drain */
REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
@@ -6040,7 +6956,8 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
vars->phy_flags = PHY_XGXS_FLAG;
- bnx2x_phy_deassert(params, vars->phy_flags);
+ bnx2x_xgxs_deassert(params);
+
/* set bmac loopback */
bnx2x_bmac_enable(params, vars, 1);
@@ -6057,80 +6974,66 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
vars->phy_flags = PHY_XGXS_FLAG;
- bnx2x_phy_deassert(params, vars->phy_flags);
+ bnx2x_xgxs_deassert(params);
/* set bmac loopback */
bnx2x_emac_enable(params, vars, 1);
- bnx2x_emac_program(params, vars->line_speed,
- vars->duplex);
+ bnx2x_emac_program(params, vars);
REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE +
params->port*4, 0);
- } else if ((params->loopback_mode == LOOPBACK_XGXS_10) ||
+ } else if ((params->loopback_mode == LOOPBACK_XGXS) ||
(params->loopback_mode == LOOPBACK_EXT_PHY)) {
vars->link_up = 1;
- vars->line_speed = SPEED_10000;
- vars->duplex = DUPLEX_FULL;
vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
+ vars->duplex = DUPLEX_FULL;
+ if (params->req_line_speed[0] == SPEED_1000) {
+ vars->line_speed = SPEED_1000;
+ vars->mac_type = MAC_TYPE_EMAC;
+ } else {
+ vars->line_speed = SPEED_10000;
+ vars->mac_type = MAC_TYPE_BMAC;
+ }
- vars->phy_flags = PHY_XGXS_FLAG;
-
- val = REG_RD(bp,
- NIG_REG_XGXS0_CTRL_PHY_ADDR+
- params->port*0x18);
- params->phy_addr = (u8)val;
-
- bnx2x_phy_deassert(params, vars->phy_flags);
+ bnx2x_xgxs_deassert(params);
bnx2x_link_initialize(params, vars);
- vars->mac_type = MAC_TYPE_BMAC;
-
+ if (params->req_line_speed[0] == SPEED_1000) {
+ bnx2x_emac_program(params, vars);
+ bnx2x_emac_enable(params, vars, 0);
+ } else
bnx2x_bmac_enable(params, vars, 0);
- if (params->loopback_mode == LOOPBACK_XGXS_10) {
+ if (params->loopback_mode == LOOPBACK_XGXS) {
/* set 10G XGXS loopback */
- bnx2x_set_xgxs_loopback(params, vars, 1);
+ params->phy[INT_PHY].config_loopback(
+ &params->phy[INT_PHY],
+ params);
+
} else {
/* set external phy loopback */
- bnx2x_ext_phy_loopback(params);
+ u8 phy_index;
+ for (phy_index = EXT_PHY1;
+ phy_index < params->num_phys; phy_index++) {
+ if (params->phy[phy_index].config_loopback)
+ params->phy[phy_index].config_loopback(
+ &params->phy[phy_index],
+ params);
+ }
}
+
REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE +
params->port*4, 0);
- bnx2x_set_led(params, LED_MODE_OPER, vars->line_speed);
+ bnx2x_set_led(params, vars,
+ LED_MODE_OPER, vars->line_speed);
} else
/* No loopback */
{
- bnx2x_phy_deassert(params, vars->phy_flags);
- switch (params->switch_cfg) {
- case SWITCH_CFG_1G:
- vars->phy_flags |= PHY_SERDES_FLAG;
- if ((params->ext_phy_config &
- PORT_HW_CFG_SERDES_EXT_PHY_TYPE_MASK) ==
- PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482) {
- vars->phy_flags |= PHY_SGMII_FLAG;
- }
-
- val = REG_RD(bp,
- NIG_REG_SERDES0_CTRL_PHY_ADDR+
- params->port*0x10);
-
- params->phy_addr = (u8)val;
-
- break;
- case SWITCH_CFG_10G:
- vars->phy_flags |= PHY_XGXS_FLAG;
- val = REG_RD(bp,
- NIG_REG_XGXS0_CTRL_PHY_ADDR+
- params->port*0x18);
- params->phy_addr = (u8)val;
-
- break;
- default:
- DP(NETIF_MSG_LINK, "Invalid switch_cfg\n");
- return -EINVAL;
- }
- DP(NETIF_MSG_LINK, "Phy address = 0x%x\n", params->phy_addr);
+ if (params->switch_cfg == SWITCH_CFG_10G)
+ bnx2x_xgxs_deassert(params);
+ else
+ bnx2x_serdes_deassert(bp, params->port);
bnx2x_link_initialize(params, vars);
msleep(30);
@@ -6138,29 +7041,11 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
}
return 0;
}
-
-static void bnx2x_8726_reset_phy(struct bnx2x *bp, u8 port, u8 ext_phy_addr)
-{
- DP(NETIF_MSG_LINK, "bnx2x_8726_reset_phy port %d\n", port);
-
- /* Set serial boot control for external load */
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726, ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_GEN_CTRL, 0x0001);
-}
-
u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
u8 reset_ext_phy)
{
struct bnx2x *bp = params->bp;
- u32 ext_phy_config = params->ext_phy_config;
- u8 port = params->port;
- u32 ext_phy_type = XGXS_EXT_PHY_TYPE(ext_phy_config);
- u32 val = REG_RD(bp, params->shmem_base +
- offsetof(struct shmem_region, dev_info.
- port_feature_config[params->port].
- config));
+ u8 phy_index, port = params->port;
DP(NETIF_MSG_LINK, "Resetting the link of port %d\n", port);
/* disable attentions */
vars->link_status = 0;
@@ -6189,73 +7074,21 @@ u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
* Hold it as vars low
*/
/* clear link led */
- bnx2x_set_led(params, LED_MODE_OFF, 0);
- if (reset_ext_phy) {
- switch (ext_phy_type) {
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
- break;
+ bnx2x_set_led(params, vars, LED_MODE_OFF, 0);
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
- {
-
- /* Disable Transmitter */
- u8 ext_phy_addr =
- XGXS_EXT_PHY_ADDR(params->ext_phy_config);
- if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
- PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)
- bnx2x_sfp_set_transmitter(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
- ext_phy_addr, 0);
- break;
- }
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
- DP(NETIF_MSG_LINK, "Setting 8073 port %d into "
- "low power mode\n",
- port);
- bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
- MISC_REGISTERS_GPIO_OUTPUT_LOW,
- port);
- break;
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
- {
- u8 ext_phy_addr =
- XGXS_EXT_PHY_ADDR(params->ext_phy_config);
- /* Set soft reset */
- bnx2x_8726_reset_phy(bp, params->port, ext_phy_addr);
- break;
- }
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823:
- {
- u8 ext_phy_addr =
- XGXS_EXT_PHY_ADDR(params->ext_phy_config);
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_CTRL, 0x0000);
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_CTRL, 1);
- break;
- }
- default:
- /* HW reset */
- bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
- MISC_REGISTERS_GPIO_OUTPUT_LOW,
- port);
- bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
- MISC_REGISTERS_GPIO_OUTPUT_LOW,
- port);
- DP(NETIF_MSG_LINK, "reset external PHY\n");
+ if (reset_ext_phy) {
+ for (phy_index = EXT_PHY1; phy_index < params->num_phys;
+ phy_index++) {
+ if (params->phy[phy_index].link_reset)
+ params->phy[phy_index].link_reset(
+ &params->phy[phy_index],
+ params);
}
}
- /* reset the SerDes/XGXS */
- REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR,
- (0x1ff << (port*16)));
+ if (params->phy[INT_PHY].link_reset)
+ params->phy[INT_PHY].link_reset(
+ &params->phy[INT_PHY], params);
/* reset BigMac */
REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
(MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
@@ -6269,183 +7102,41 @@ u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
return 0;
}
-static u8 bnx2x_update_link_down(struct link_params *params,
- struct link_vars *vars)
-{
- struct bnx2x *bp = params->bp;
- u8 port = params->port;
-
- DP(NETIF_MSG_LINK, "Port %x: Link is down\n", port);
- bnx2x_set_led(params, LED_MODE_OFF, 0);
-
- /* indicate no mac active */
- vars->mac_type = MAC_TYPE_NONE;
-
- /* update shared memory */
- vars->link_status = 0;
- vars->line_speed = 0;
- bnx2x_update_mng(params, vars->link_status);
-
- /* activate nig drain */
- REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1);
-
- /* disable emac */
- REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
-
- msleep(10);
-
- /* reset BigMac */
- bnx2x_bmac_rx_disable(bp, params->port);
- REG_WR(bp, GRCBASE_MISC +
- MISC_REGISTERS_RESET_REG_2_CLEAR,
- (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
- return 0;
-}
-
-static u8 bnx2x_update_link_up(struct link_params *params,
- struct link_vars *vars,
- u8 link_10g, u32 gp_status)
-{
- struct bnx2x *bp = params->bp;
- u8 port = params->port;
- u8 rc = 0;
-
- vars->link_status |= LINK_STATUS_LINK_UP;
- if (link_10g) {
- bnx2x_bmac_enable(params, vars, 0);
- bnx2x_set_led(params, LED_MODE_OPER, SPEED_10000);
- } else {
- rc = bnx2x_emac_program(params, vars->line_speed,
- vars->duplex);
-
- bnx2x_emac_enable(params, vars, 0);
-
- /* AN complete? */
- if (gp_status & MDIO_AN_CL73_OR_37_COMPLETE) {
- if (!(vars->phy_flags &
- PHY_SGMII_FLAG))
- bnx2x_set_gmii_tx_driver(params);
- }
- }
-
- /* PBF - link up */
- rc |= bnx2x_pbf_update(params, vars->flow_ctrl,
- vars->line_speed);
-
- /* disable drain */
- REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 0);
-
- /* update shared memory */
- bnx2x_update_mng(params, vars->link_status);
- msleep(20);
- return rc;
-}
-/* This function should called upon link interrupt */
-/* In case vars->link_up, driver needs to
- 1. Update the pbf
- 2. Disable drain
- 3. Update the shared memory
- 4. Indicate link up
- 5. Set LEDs
- Otherwise,
- 1. Update shared memory
- 2. Reset BigMac
- 3. Report link down
- 4. Unset LEDs
-*/
-u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
-{
- struct bnx2x *bp = params->bp;
- u8 port = params->port;
- u16 gp_status;
- u8 link_10g;
- u8 ext_phy_link_up, rc = 0;
- u32 ext_phy_type;
- u8 is_mi_int = 0;
-
- DP(NETIF_MSG_LINK, "port %x, XGXS?%x, int_status 0x%x\n",
- port, (vars->phy_flags & PHY_XGXS_FLAG),
- REG_RD(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4));
-
- is_mi_int = (u8)(REG_RD(bp, NIG_REG_EMAC0_STATUS_MISC_MI_INT +
- port*0x18) > 0);
- DP(NETIF_MSG_LINK, "int_mask 0x%x MI_INT %x, SERDES_LINK %x\n",
- REG_RD(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4),
- is_mi_int,
- REG_RD(bp,
- NIG_REG_SERDES0_STATUS_LINK_STATUS + port*0x3c));
-
- DP(NETIF_MSG_LINK, " 10G %x, XGXS_LINK %x\n",
- REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK10G + port*0x68),
- REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68));
-
- /* disable emac */
- REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
-
- ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
-
- /* Check external link change only for non-direct */
- ext_phy_link_up = bnx2x_ext_phy_is_link_up(params, vars, is_mi_int);
-
- /* Read gp_status */
- CL45_RD_OVER_CL22(bp, port, params->phy_addr,
- MDIO_REG_BANK_GP_STATUS,
- MDIO_GP_STATUS_TOP_AN_STATUS1,
- &gp_status);
-
- rc = bnx2x_link_settings_status(params, vars, gp_status,
- ext_phy_link_up);
- if (rc != 0)
- return rc;
-
- /* anything 10 and over uses the bmac */
- link_10g = ((vars->line_speed == SPEED_10000) ||
- (vars->line_speed == SPEED_12000) ||
- (vars->line_speed == SPEED_12500) ||
- (vars->line_speed == SPEED_13000) ||
- (vars->line_speed == SPEED_15000) ||
- (vars->line_speed == SPEED_16000));
-
- bnx2x_link_int_ack(params, vars, link_10g, is_mi_int);
-
- /* In case external phy link is up, and internal link is down
- ( not initialized yet probably after link initialization, it needs
- to be initialized.
- Note that after link down-up as result of cable plug,
- the xgxs link would probably become up again without the need to
- initialize it*/
-
- if ((ext_phy_type != PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT) &&
- (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705) &&
- (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706) &&
- (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726) &&
- (ext_phy_link_up && !vars->phy_link_up))
- bnx2x_init_internal_phy(params, vars, 0);
-
- /* link is up only if both local phy and external phy are up */
- vars->link_up = (ext_phy_link_up && vars->phy_link_up);
-
- if (vars->link_up)
- rc = bnx2x_update_link_up(params, vars, link_10g, gp_status);
- else
- rc = bnx2x_update_link_down(params, vars);
-
- return rc;
-}
-
-static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, u32 shmem_base)
+/****************************************************************************/
+/* Common function */
+/****************************************************************************/
+static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp,
+ u32 shmem_base_path[],
+ u32 shmem2_base_path[], u8 phy_index,
+ u32 chip_id)
{
- u8 ext_phy_addr[PORT_MAX];
+ struct bnx2x_phy phy[PORT_MAX];
+ struct bnx2x_phy *phy_blk[PORT_MAX];
u16 val;
s8 port;
+ s8 port_of_path = 0;
/* PART1 - Reset both phys */
for (port = PORT_MAX - 1; port >= PORT_0; port--) {
- /* Extract the ext phy address for the port */
- u32 ext_phy_config = REG_RD(bp, shmem_base +
- offsetof(struct shmem_region,
- dev_info.port_hw_config[port].external_phy_config));
+ u32 shmem_base, shmem2_base;
+ /* In E2, same phy is using for port0 of the two paths */
+ if (CHIP_IS_E2(bp)) {
+ shmem_base = shmem_base_path[port];
+ shmem2_base = shmem2_base_path[port];
+ port_of_path = 0;
+ } else {
+ shmem_base = shmem_base_path[0];
+ shmem2_base = shmem2_base_path[0];
+ port_of_path = port;
+ }
+ /* Extract the ext phy address for the port */
+ if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base,
+ port_of_path, &phy[port]) !=
+ 0) {
+ DP(NETIF_MSG_LINK, "populate_phy failed\n");
+ return -EINVAL;
+ }
/* disable attentions */
bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4,
(NIG_MASK_XGXS0_LINK_STATUS |
@@ -6453,17 +7144,13 @@ static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, u32 shmem_base)
NIG_MASK_SERDES0_LINK_STATUS |
NIG_MASK_MI_INT));
- ext_phy_addr[port] = XGXS_EXT_PHY_ADDR(ext_phy_config);
-
/* Need to take the phy out of low power mode in order
to write to access its registers */
bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
MISC_REGISTERS_GPIO_OUTPUT_HIGH, port);
/* Reset the phy */
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
- ext_phy_addr[port],
+ bnx2x_cl45_write(bp, &phy[port],
MDIO_PMA_DEVAD,
MDIO_PMA_REG_CTRL,
1<<15);
@@ -6472,15 +7159,28 @@ static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, u32 shmem_base)
/* Add delay of 150ms after reset */
msleep(150);
+ if (phy[PORT_0].addr & 0x1) {
+ phy_blk[PORT_0] = &(phy[PORT_1]);
+ phy_blk[PORT_1] = &(phy[PORT_0]);
+ } else {
+ phy_blk[PORT_0] = &(phy[PORT_0]);
+ phy_blk[PORT_1] = &(phy[PORT_1]);
+ }
+
/* PART2 - Download firmware to both phys */
for (port = PORT_MAX - 1; port >= PORT_0; port--) {
u16 fw_ver1;
+ if (CHIP_IS_E2(bp))
+ port_of_path = 0;
+ else
+ port_of_path = port;
- bnx2x_bcm8073_external_rom_boot(bp, port,
- ext_phy_addr[port], shmem_base);
+ DP(NETIF_MSG_LINK, "Loading spirom for phy address 0x%x\n",
+ phy_blk[port]->addr);
+ bnx2x_8073_8727_external_rom_boot(bp, phy_blk[port],
+ port_of_path);
- bnx2x_cl45_read(bp, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
- ext_phy_addr[port],
+ bnx2x_cl45_read(bp, phy_blk[port],
MDIO_PMA_DEVAD,
MDIO_PMA_REG_ROM_VER1, &fw_ver1);
if (fw_ver1 == 0 || fw_ver1 == 0x4321) {
@@ -6492,16 +7192,12 @@ static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, u32 shmem_base)
}
/* Only set bit 10 = 1 (Tx power down) */
- bnx2x_cl45_read(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
- ext_phy_addr[port],
+ bnx2x_cl45_read(bp, phy_blk[port],
MDIO_PMA_DEVAD,
MDIO_PMA_REG_TX_POWER_DOWN, &val);
/* Phase1 of TX_POWER_DOWN reset */
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
- ext_phy_addr[port],
+ bnx2x_cl45_write(bp, phy_blk[port],
MDIO_PMA_DEVAD,
MDIO_PMA_REG_TX_POWER_DOWN,
(val | 1<<10));
@@ -6515,28 +7211,20 @@ static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, u32 shmem_base)
for (port = PORT_MAX - 1; port >= PORT_0; port--) {
/* Phase2 of POWER_DOWN_RESET */
/* Release bit 10 (Release Tx power down) */
- bnx2x_cl45_read(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
- ext_phy_addr[port],
+ bnx2x_cl45_read(bp, phy_blk[port],
MDIO_PMA_DEVAD,
MDIO_PMA_REG_TX_POWER_DOWN, &val);
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
- ext_phy_addr[port],
+ bnx2x_cl45_write(bp, phy_blk[port],
MDIO_PMA_DEVAD,
MDIO_PMA_REG_TX_POWER_DOWN, (val & (~(1<<10))));
msleep(15);
/* Read modify write the SPI-ROM version select register */
- bnx2x_cl45_read(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
- ext_phy_addr[port],
+ bnx2x_cl45_read(bp, phy_blk[port],
MDIO_PMA_DEVAD,
MDIO_PMA_REG_EDC_FFE_MAIN, &val);
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
- ext_phy_addr[port],
+ bnx2x_cl45_write(bp, phy_blk[port],
MDIO_PMA_DEVAD,
MDIO_PMA_REG_EDC_FFE_MAIN, (val | (1<<12)));
@@ -6545,46 +7233,111 @@ static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, u32 shmem_base)
MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
}
return 0;
-
}
+static u8 bnx2x_8726_common_init_phy(struct bnx2x *bp,
+ u32 shmem_base_path[],
+ u32 shmem2_base_path[], u8 phy_index,
+ u32 chip_id)
+{
+ u32 val;
+ s8 port;
+ struct bnx2x_phy phy;
+ /* Use port1 because of the static port-swap */
+ /* Enable the module detection interrupt */
+ val = REG_RD(bp, MISC_REG_GPIO_EVENT_EN);
+ val |= ((1<<MISC_REGISTERS_GPIO_3)|
+ (1<<(MISC_REGISTERS_GPIO_3 + MISC_REGISTERS_GPIO_PORT_SHIFT)));
+ REG_WR(bp, MISC_REG_GPIO_EVENT_EN, val);
+
+ bnx2x_ext_phy_hw_reset(bp, 1);
+ msleep(5);
+ for (port = 0; port < PORT_MAX; port++) {
+ u32 shmem_base, shmem2_base;
+
+ /* In E2, same phy is using for port0 of the two paths */
+ if (CHIP_IS_E2(bp)) {
+ shmem_base = shmem_base_path[port];
+ shmem2_base = shmem2_base_path[port];
+ } else {
+ shmem_base = shmem_base_path[0];
+ shmem2_base = shmem2_base_path[0];
+ }
+ /* Extract the ext phy address for the port */
+ if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base,
+ port, &phy) !=
+ 0) {
+ DP(NETIF_MSG_LINK, "populate phy failed\n");
+ return -EINVAL;
+ }
+
+ /* Reset phy*/
+ bnx2x_cl45_write(bp, &phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_GEN_CTRL, 0x0001);
+
+
+ /* Set fault module detected LED on */
+ bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
+ MISC_REGISTERS_GPIO_HIGH,
+ port);
+ }
-static u8 bnx2x_8727_common_init_phy(struct bnx2x *bp, u32 shmem_base)
+ return 0;
+}
+static u8 bnx2x_8727_common_init_phy(struct bnx2x *bp,
+ u32 shmem_base_path[],
+ u32 shmem2_base_path[], u8 phy_index,
+ u32 chip_id)
{
- u8 ext_phy_addr[PORT_MAX];
- s8 port, first_port, i;
+ s8 port;
u32 swap_val, swap_override;
- DP(NETIF_MSG_LINK, "Executing BCM8727 common init\n");
+ struct bnx2x_phy phy[PORT_MAX];
+ struct bnx2x_phy *phy_blk[PORT_MAX];
+ s8 port_of_path;
swap_val = REG_RD(bp, NIG_REG_PORT_SWAP);
swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE);
- bnx2x_ext_phy_hw_reset(bp, 1 ^ (swap_val && swap_override));
- msleep(5);
+ port = 1;
- if (swap_val && swap_override)
- first_port = PORT_0;
- else
- first_port = PORT_1;
+ bnx2x_ext_phy_hw_reset(bp, port ^ (swap_val && swap_override));
+
+ /* Calculate the port based on port swap */
+ port ^= (swap_val && swap_override);
+
+ msleep(5);
/* PART1 - Reset both phys */
- for (i = 0, port = first_port; i < PORT_MAX; i++, port = !port) {
- /* Extract the ext phy address for the port */
- u32 ext_phy_config = REG_RD(bp, shmem_base +
- offsetof(struct shmem_region,
- dev_info.port_hw_config[port].external_phy_config));
+ for (port = PORT_MAX - 1; port >= PORT_0; port--) {
+ u32 shmem_base, shmem2_base;
+
+ /* In E2, same phy is using for port0 of the two paths */
+ if (CHIP_IS_E2(bp)) {
+ shmem_base = shmem_base_path[port];
+ shmem2_base = shmem2_base_path[port];
+ port_of_path = 0;
+ } else {
+ shmem_base = shmem_base_path[0];
+ shmem2_base = shmem2_base_path[0];
+ port_of_path = port;
+ }
+ /* Extract the ext phy address for the port */
+ if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base,
+ port_of_path, &phy[port]) !=
+ 0) {
+ DP(NETIF_MSG_LINK, "populate phy failed\n");
+ return -EINVAL;
+ }
/* disable attentions */
- bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4,
- (NIG_MASK_XGXS0_LINK_STATUS |
- NIG_MASK_XGXS0_LINK10G |
- NIG_MASK_SERDES0_LINK_STATUS |
- NIG_MASK_MI_INT));
+ bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 +
+ port_of_path*4,
+ (NIG_MASK_XGXS0_LINK_STATUS |
+ NIG_MASK_XGXS0_LINK10G |
+ NIG_MASK_SERDES0_LINK_STATUS |
+ NIG_MASK_MI_INT));
- ext_phy_addr[port] = XGXS_EXT_PHY_ADDR(ext_phy_config);
/* Reset the phy */
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
- ext_phy_addr[port],
+ bnx2x_cl45_write(bp, &phy[port],
MDIO_PMA_DEVAD,
MDIO_PMA_REG_CTRL,
1<<15);
@@ -6592,16 +7345,25 @@ static u8 bnx2x_8727_common_init_phy(struct bnx2x *bp, u32 shmem_base)
/* Add delay of 150ms after reset */
msleep(150);
-
+ if (phy[PORT_0].addr & 0x1) {
+ phy_blk[PORT_0] = &(phy[PORT_1]);
+ phy_blk[PORT_1] = &(phy[PORT_0]);
+ } else {
+ phy_blk[PORT_0] = &(phy[PORT_0]);
+ phy_blk[PORT_1] = &(phy[PORT_1]);
+ }
/* PART2 - Download firmware to both phys */
- for (i = 0, port = first_port; i < PORT_MAX; i++, port = !port) {
+ for (port = PORT_MAX - 1; port >= PORT_0; port--) {
u16 fw_ver1;
-
- bnx2x_bcm8727_external_rom_boot(bp, port,
- ext_phy_addr[port], shmem_base);
-
- bnx2x_cl45_read(bp, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
- ext_phy_addr[port],
+ if (CHIP_IS_E2(bp))
+ port_of_path = 0;
+ else
+ port_of_path = port;
+ DP(NETIF_MSG_LINK, "Loading spirom for phy address 0x%x\n",
+ phy_blk[port]->addr);
+ bnx2x_8073_8727_external_rom_boot(bp, phy_blk[port],
+ port_of_path);
+ bnx2x_cl45_read(bp, phy_blk[port],
MDIO_PMA_DEVAD,
MDIO_PMA_REG_ROM_VER1, &fw_ver1);
if (fw_ver1 == 0 || fw_ver1 == 0x4321) {
@@ -6616,82 +7378,35 @@ static u8 bnx2x_8727_common_init_phy(struct bnx2x *bp, u32 shmem_base)
return 0;
}
-
-static u8 bnx2x_8726_common_init_phy(struct bnx2x *bp, u32 shmem_base)
-{
- u8 ext_phy_addr;
- u32 val;
- s8 port;
-
- /* Use port1 because of the static port-swap */
- /* Enable the module detection interrupt */
- val = REG_RD(bp, MISC_REG_GPIO_EVENT_EN);
- val |= ((1<<MISC_REGISTERS_GPIO_3)|
- (1<<(MISC_REGISTERS_GPIO_3 + MISC_REGISTERS_GPIO_PORT_SHIFT)));
- REG_WR(bp, MISC_REG_GPIO_EVENT_EN, val);
-
- bnx2x_ext_phy_hw_reset(bp, 1);
- msleep(5);
- for (port = 0; port < PORT_MAX; port++) {
- /* Extract the ext phy address for the port */
- u32 ext_phy_config = REG_RD(bp, shmem_base +
- offsetof(struct shmem_region,
- dev_info.port_hw_config[port].external_phy_config));
-
- ext_phy_addr = XGXS_EXT_PHY_ADDR(ext_phy_config);
- DP(NETIF_MSG_LINK, "8726_common_init : ext_phy_addr = 0x%x\n",
- ext_phy_addr);
-
- bnx2x_8726_reset_phy(bp, port, ext_phy_addr);
-
- /* Set fault module detected LED on */
- bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
- MISC_REGISTERS_GPIO_HIGH,
- port);
- }
-
- return 0;
-}
-
-
-static u8 bnx2x_84823_common_init_phy(struct bnx2x *bp, u32 shmem_base)
-{
- /* HW reset */
- bnx2x_ext_phy_hw_reset(bp, 1);
- return 0;
-}
-u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base)
+static u8 bnx2x_ext_phy_common_init(struct bnx2x *bp, u32 shmem_base_path[],
+ u32 shmem2_base_path[], u8 phy_index,
+ u32 ext_phy_type, u32 chip_id)
{
u8 rc = 0;
- u32 ext_phy_type;
-
- DP(NETIF_MSG_LINK, "Begin common phy init\n");
-
- /* Read the ext_phy_type for arbitrary port(0) */
- ext_phy_type = XGXS_EXT_PHY_TYPE(
- REG_RD(bp, shmem_base +
- offsetof(struct shmem_region,
- dev_info.port_hw_config[0].external_phy_config)));
switch (ext_phy_type) {
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
- {
- rc = bnx2x_8073_common_init_phy(bp, shmem_base);
+ rc = bnx2x_8073_common_init_phy(bp, shmem_base_path,
+ shmem2_base_path,
+ phy_index, chip_id);
break;
- }
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727_NOC:
- rc = bnx2x_8727_common_init_phy(bp, shmem_base);
+ rc = bnx2x_8727_common_init_phy(bp, shmem_base_path,
+ shmem2_base_path,
+ phy_index, chip_id);
break;
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
/* GPIO1 affects both ports, so there's need to pull
it for single port alone */
- rc = bnx2x_8726_common_init_phy(bp, shmem_base);
+ rc = bnx2x_8726_common_init_phy(bp, shmem_base_path,
+ shmem2_base_path,
+ phy_index, chip_id);
break;
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823:
- rc = bnx2x_84823_common_init_phy(bp, shmem_base);
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
+ rc = -EINVAL;
break;
default:
DP(NETIF_MSG_LINK,
@@ -6703,33 +7418,81 @@ u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base)
return rc;
}
-void bnx2x_sfx7101_sp_sw_reset(struct bnx2x *bp, u8 port, u8 phy_addr)
+u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base_path[],
+ u32 shmem2_base_path[], u32 chip_id)
{
- u16 val, cnt;
+ u8 rc = 0;
+ u8 phy_index;
+ u32 ext_phy_type, ext_phy_config;
+ DP(NETIF_MSG_LINK, "Begin common phy init\n");
- bnx2x_cl45_read(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
- phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_7101_RESET, &val);
+ if (CHIP_REV_IS_EMUL(bp))
+ return 0;
- for (cnt = 0; cnt < 10; cnt++) {
- msleep(50);
- /* Writes a self-clearing reset */
- bnx2x_cl45_write(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
- phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_7101_RESET,
- (val | (1<<15)));
- /* Wait for clear */
- bnx2x_cl45_read(bp, port,
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
- phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_7101_RESET, &val);
+ /* Read the ext_phy_type for arbitrary port(0) */
+ for (phy_index = EXT_PHY1; phy_index < MAX_PHYS;
+ phy_index++) {
+ ext_phy_config = bnx2x_get_ext_phy_config(bp,
+ shmem_base_path[0],
+ phy_index, 0);
+ ext_phy_type = XGXS_EXT_PHY_TYPE(ext_phy_config);
+ rc |= bnx2x_ext_phy_common_init(bp, shmem_base_path,
+ shmem2_base_path,
+ phy_index, ext_phy_type,
+ chip_id);
+ }
+ return rc;
+}
- if ((val & (1<<15)) == 0)
- break;
+u8 bnx2x_hw_lock_required(struct bnx2x *bp, u32 shmem_base, u32 shmem2_base)
+{
+ u8 phy_index;
+ struct bnx2x_phy phy;
+ for (phy_index = INT_PHY; phy_index < MAX_PHYS;
+ phy_index++) {
+ if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base,
+ 0, &phy) != 0) {
+ DP(NETIF_MSG_LINK, "populate phy failed\n");
+ return 0;
+ }
+
+ if (phy.flags & FLAGS_HW_LOCK_REQUIRED)
+ return 1;
+ }
+ return 0;
+}
+
+u8 bnx2x_fan_failure_det_req(struct bnx2x *bp,
+ u32 shmem_base,
+ u32 shmem2_base,
+ u8 port)
+{
+ u8 phy_index, fan_failure_det_req = 0;
+ struct bnx2x_phy phy;
+ for (phy_index = EXT_PHY1; phy_index < MAX_PHYS;
+ phy_index++) {
+ if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base,
+ port, &phy)
+ != 0) {
+ DP(NETIF_MSG_LINK, "populate phy failed\n");
+ return 0;
+ }
+ fan_failure_det_req |= (phy.flags &
+ FLAGS_FAN_FAILURE_DET_REQ);
+ }
+ return fan_failure_det_req;
+}
+
+void bnx2x_hw_reset_phy(struct link_params *params)
+{
+ u8 phy_index;
+ for (phy_index = EXT_PHY1; phy_index < MAX_PHYS;
+ phy_index++) {
+ if (params->phy[phy_index].hw_reset) {
+ params->phy[phy_index].hw_reset(
+ &params->phy[phy_index],
+ params);
+ params->phy[phy_index] = phy_null;
+ }
}
}
diff --git a/drivers/net/bnx2x/bnx2x_link.h b/drivers/net/bnx2x/bnx2x_link.h
index 40c2981de8ed..58a4c7199276 100644
--- a/drivers/net/bnx2x/bnx2x_link.h
+++ b/drivers/net/bnx2x/bnx2x_link.h
@@ -1,4 +1,4 @@
-/* Copyright 2008-2009 Broadcom Corporation
+/* Copyright 2008-2010 Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
@@ -22,7 +22,8 @@
/***********************************************************/
/* Defines */
/***********************************************************/
-#define DEFAULT_PHY_DEV_ADDR 3
+#define DEFAULT_PHY_DEV_ADDR 3
+#define E2_DEFAULT_PHY_DEV_ADDR 5
@@ -46,9 +47,137 @@
#define SFP_EEPROM_PART_NO_ADDR 0x28
#define SFP_EEPROM_PART_NO_SIZE 16
#define PWR_FLT_ERR_MSG_LEN 250
+
+#define XGXS_EXT_PHY_TYPE(ext_phy_config) \
+ ((ext_phy_config) & PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK)
+#define XGXS_EXT_PHY_ADDR(ext_phy_config) \
+ (((ext_phy_config) & PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >> \
+ PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT)
+#define SERDES_EXT_PHY_TYPE(ext_phy_config) \
+ ((ext_phy_config) & PORT_HW_CFG_SERDES_EXT_PHY_TYPE_MASK)
+
+/* Single Media Direct board is the plain 577xx board with CX4/RJ45 jacks */
+#define SINGLE_MEDIA_DIRECT(params) (params->num_phys == 1)
+/* Single Media board contains single external phy */
+#define SINGLE_MEDIA(params) (params->num_phys == 2)
+/* Dual Media board contains two external phy with different media */
+#define DUAL_MEDIA(params) (params->num_phys == 3)
+#define FW_PARAM_MDIO_CTRL_OFFSET 16
+#define FW_PARAM_SET(phy_addr, phy_type, mdio_access) \
+ (phy_addr | phy_type | mdio_access << FW_PARAM_MDIO_CTRL_OFFSET)
/***********************************************************/
/* Structs */
/***********************************************************/
+#define INT_PHY 0
+#define EXT_PHY1 1
+#define EXT_PHY2 2
+#define MAX_PHYS 3
+
+/* Same configuration is shared between the XGXS and the first external phy */
+#define LINK_CONFIG_SIZE (MAX_PHYS - 1)
+#define LINK_CONFIG_IDX(_phy_idx) ((_phy_idx == INT_PHY) ? \
+ 0 : (_phy_idx - 1))
+/***********************************************************/
+/* bnx2x_phy struct */
+/* Defines the required arguments and function per phy */
+/***********************************************************/
+struct link_vars;
+struct link_params;
+struct bnx2x_phy;
+
+typedef u8 (*config_init_t)(struct bnx2x_phy *phy, struct link_params *params,
+ struct link_vars *vars);
+typedef u8 (*read_status_t)(struct bnx2x_phy *phy, struct link_params *params,
+ struct link_vars *vars);
+typedef void (*link_reset_t)(struct bnx2x_phy *phy,
+ struct link_params *params);
+typedef void (*config_loopback_t)(struct bnx2x_phy *phy,
+ struct link_params *params);
+typedef u8 (*format_fw_ver_t)(u32 raw, u8 *str, u16 *len);
+typedef void (*hw_reset_t)(struct bnx2x_phy *phy, struct link_params *params);
+typedef void (*set_link_led_t)(struct bnx2x_phy *phy,
+ struct link_params *params, u8 mode);
+typedef void (*phy_specific_func_t)(struct bnx2x_phy *phy,
+ struct link_params *params, u32 action);
+
+struct bnx2x_phy {
+ u32 type;
+
+ /* Loaded during init */
+ u8 addr;
+
+ u8 flags;
+ /* Require HW lock */
+#define FLAGS_HW_LOCK_REQUIRED (1<<0)
+ /* No Over-Current detection */
+#define FLAGS_NOC (1<<1)
+ /* Fan failure detection required */
+#define FLAGS_FAN_FAILURE_DET_REQ (1<<2)
+ /* Initialize first the XGXS and only then the phy itself */
+#define FLAGS_INIT_XGXS_FIRST (1<<3)
+#define FLAGS_REARM_LATCH_SIGNAL (1<<6)
+#define FLAGS_SFP_NOT_APPROVED (1<<7)
+
+ u8 def_md_devad;
+ u8 reserved;
+ /* preemphasis values for the rx side */
+ u16 rx_preemphasis[4];
+
+ /* preemphasis values for the tx side */
+ u16 tx_preemphasis[4];
+
+ /* EMAC address for access MDIO */
+ u32 mdio_ctrl;
+
+ u32 supported;
+
+ u32 media_type;
+#define ETH_PHY_UNSPECIFIED 0x0
+#define ETH_PHY_SFP_FIBER 0x1
+#define ETH_PHY_XFP_FIBER 0x2
+#define ETH_PHY_DA_TWINAX 0x3
+#define ETH_PHY_BASE_T 0x4
+#define ETH_PHY_NOT_PRESENT 0xff
+
+ /* The address in which version is located*/
+ u32 ver_addr;
+
+ u16 req_flow_ctrl;
+
+ u16 req_line_speed;
+
+ u32 speed_cap_mask;
+
+ u16 req_duplex;
+ u16 rsrv;
+ /* Called per phy/port init, and it configures LASI, speed, autoneg,
+ duplex, flow control negotiation, etc. */
+ config_init_t config_init;
+
+ /* Called due to interrupt. It determines the link, speed */
+ read_status_t read_status;
+
+ /* Called when driver is unloading. Should reset the phy */
+ link_reset_t link_reset;
+
+ /* Set the loopback configuration for the phy */
+ config_loopback_t config_loopback;
+
+ /* Format the given raw number into str up to len */
+ format_fw_ver_t format_fw_ver;
+
+ /* Reset the phy (both ports) */
+ hw_reset_t hw_reset;
+
+ /* Set link led mode (on/off/oper)*/
+ set_link_led_t set_link_led;
+
+ /* PHY Specific tasks */
+ phy_specific_func_t phy_specific_func;
+#define DISABLE_TX 1
+#define ENABLE_TX 2
+};
+
/* Inputs parameters to the CLC */
struct link_params {
@@ -59,56 +188,50 @@ struct link_params {
#define LOOPBACK_NONE 0
#define LOOPBACK_EMAC 1
#define LOOPBACK_BMAC 2
-#define LOOPBACK_XGXS_10 3
+#define LOOPBACK_XGXS 3
#define LOOPBACK_EXT_PHY 4
#define LOOPBACK_EXT 5
- u16 req_duplex;
- u16 req_flow_ctrl;
- u16 req_fc_auto_adv; /* Should be set to TX / BOTH when
- req_flow_ctrl is set to AUTO */
- u16 req_line_speed; /* Also determine AutoNeg */
-
/* Device parameters */
u8 mac_addr[6];
+ u16 req_duplex[LINK_CONFIG_SIZE];
+ u16 req_flow_ctrl[LINK_CONFIG_SIZE];
+
+ u16 req_line_speed[LINK_CONFIG_SIZE]; /* Also determine AutoNeg */
+
/* shmem parameters */
u32 shmem_base;
- u32 speed_cap_mask;
+ u32 shmem2_base;
+ u32 speed_cap_mask[LINK_CONFIG_SIZE];
u32 switch_cfg;
#define SWITCH_CFG_1G PORT_FEATURE_CON_SWITCH_1G_SWITCH
#define SWITCH_CFG_10G PORT_FEATURE_CON_SWITCH_10G_SWITCH
#define SWITCH_CFG_AUTO_DETECT PORT_FEATURE_CON_SWITCH_AUTO_DETECT
- u16 hw_led_mode; /* part of the hw_config read from the shmem */
-
- /* phy_addr populated by the phy_init function */
- u8 phy_addr;
- /*u8 reserved1;*/
-
u32 lane_config;
- u32 ext_phy_config;
-#define XGXS_EXT_PHY_TYPE(ext_phy_config) \
- ((ext_phy_config) & PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK)
-#define XGXS_EXT_PHY_ADDR(ext_phy_config) \
- (((ext_phy_config) & PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >> \
- PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT)
-#define SERDES_EXT_PHY_TYPE(ext_phy_config) \
- ((ext_phy_config) & PORT_HW_CFG_SERDES_EXT_PHY_TYPE_MASK)
/* Phy register parameter */
u32 chip_id;
- u16 xgxs_config_rx[4]; /* preemphasis values for the rx side */
- u16 xgxs_config_tx[4]; /* preemphasis values for the tx side */
-
u32 feature_config_flags;
#define FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED (1<<0)
#define FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY (1<<2)
-#define FEATURE_CONFIG_BCM8727_NOC (1<<3)
+#define FEATURE_CONFIG_BC_SUPPORTS_DUAL_PHY_OPT_MDL_VRFY (1<<3)
+ /* Will be populated during common init */
+ struct bnx2x_phy phy[MAX_PHYS];
+
+ /* Will be populated during common init */
+ u8 num_phys;
+
+ u8 rsrv;
+ u16 hw_led_mode; /* part of the hw_config read from the shmem */
+ u32 multi_phy_config;
/* Device pointer passed to all callback functions */
struct bnx2x *bp;
+ u16 req_fc_auto_adv; /* Should be set to TX / BOTH when
+ req_flow_ctrl is set to AUTO */
};
/* Output parameters */
@@ -129,12 +252,6 @@ struct link_vars {
u16 flow_ctrl;
u16 ieee_fc;
- u32 autoneg;
-#define AUTO_NEG_DISABLED 0x0
-#define AUTO_NEG_ENABLED 0x1
-#define AUTO_NEG_COMPLETE 0x2
-#define AUTO_NEG_PARALLEL_DETECTION_USED 0x3
-
/* The same definitions as the shmem parameter */
u32 link_status;
};
@@ -142,8 +259,6 @@ struct link_vars {
/***********************************************************/
/* Functions */
/***********************************************************/
-
-/* Initialize the phy */
u8 bnx2x_phy_init(struct link_params *input, struct link_vars *output);
/* Reset the link. Should be called when driver or interface goes down
@@ -155,17 +270,21 @@ u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
/* bnx2x_link_update should be called upon link interrupt */
u8 bnx2x_link_update(struct link_params *input, struct link_vars *output);
-/* use the following cl45 functions to read/write from external_phy
+/* use the following phy functions to read/write from external_phy
In order to use it to read/write internal phy registers, use
DEFAULT_PHY_DEV_ADDR as devad, and (_bank + (_addr & 0xf)) as
- Use ext_phy_type of 0 in case of cl22 over cl45
the register */
-u8 bnx2x_cl45_read(struct bnx2x *bp, u8 port, u32 ext_phy_type,
- u8 phy_addr, u8 devad, u16 reg, u16 *ret_val);
+u8 bnx2x_phy_read(struct link_params *params, u8 phy_addr,
+ u8 devad, u16 reg, u16 *ret_val);
+
+u8 bnx2x_phy_write(struct link_params *params, u8 phy_addr,
+ u8 devad, u16 reg, u16 val);
-u8 bnx2x_cl45_write(struct bnx2x *bp, u8 port, u32 ext_phy_type,
- u8 phy_addr, u8 devad, u16 reg, u16 val);
+u8 bnx2x_cl45_read(struct bnx2x *bp, struct bnx2x_phy *phy,
+ u8 devad, u16 reg, u16 *ret_val);
+u8 bnx2x_cl45_write(struct bnx2x *bp, struct bnx2x_phy *phy,
+ u8 devad, u16 reg, u16 val);
/* Reads the link_status from the shmem,
and update the link vars accordingly */
void bnx2x_link_status_update(struct link_params *input,
@@ -178,9 +297,12 @@ u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded,
Basically, the CLC takes care of the led for the link, but in case one needs
to set/unset the led unnaturally, set the "mode" to LED_MODE_OPER to
blink the led, and LED_MODE_OFF to set the led off.*/
-u8 bnx2x_set_led(struct link_params *params, u8 mode, u32 speed);
-#define LED_MODE_OFF 0
-#define LED_MODE_OPER 2
+u8 bnx2x_set_led(struct link_params *params, struct link_vars *vars,
+ u8 mode, u32 speed);
+#define LED_MODE_OFF 0
+#define LED_MODE_ON 1
+#define LED_MODE_OPER 2
+#define LED_MODE_FRONT_PANEL_OFF 3
u8 bnx2x_override_led_value(struct bnx2x *bp, u8 port, u32 led_idx, u32 value);
@@ -190,17 +312,39 @@ void bnx2x_handle_module_detect_int(struct link_params *params);
/* Get the actual link status. In case it returns 0, link is up,
otherwise link is down*/
-u8 bnx2x_test_link(struct link_params *input, struct link_vars *vars);
+u8 bnx2x_test_link(struct link_params *input, struct link_vars *vars,
+ u8 is_serdes);
/* One-time initialization for external phy after power up */
-u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base);
+u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base_path[],
+ u32 shmem2_base_path[], u32 chip_id);
/* Reset the external PHY using GPIO */
void bnx2x_ext_phy_hw_reset(struct bnx2x *bp, u8 port);
-void bnx2x_sfx7101_sp_sw_reset(struct bnx2x *bp, u8 port, u8 phy_addr);
+/* Reset the external of SFX7101 */
+void bnx2x_sfx7101_sp_sw_reset(struct bnx2x *bp, struct bnx2x_phy *phy);
-u8 bnx2x_read_sfp_module_eeprom(struct link_params *params, u16 addr,
+u8 bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy,
+ struct link_params *params, u16 addr,
u8 byte_cnt, u8 *o_buf);
+void bnx2x_hw_reset_phy(struct link_params *params);
+
+/* Checks if HW lock is required for this phy/board type */
+u8 bnx2x_hw_lock_required(struct bnx2x *bp, u32 shmem_base,
+ u32 shmem2_base);
+
+/* Returns the aggregative supported attributes of the phys on board */
+u32 bnx2x_supported_attr(struct link_params *params, u8 phy_idx);
+
+/* Check swap bit and adjust PHY order */
+u32 bnx2x_phy_selection(struct link_params *params);
+
+/* Probe the phys on board, and populate them in "params" */
+u8 bnx2x_phy_probe(struct link_params *params);
+/* Checks if fan failure detection is required on one of the phys on board */
+u8 bnx2x_fan_failure_det_req(struct bnx2x *bp, u32 shmem_base,
+ u32 shmem2_base, u8 port);
+
#endif /* BNX2X_LINK_H */
diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c
index f8c3f08e4ce7..ff99a2fc0426 100644
--- a/drivers/net/bnx2x/bnx2x_main.c
+++ b/drivers/net/bnx2x/bnx2x_main.c
@@ -23,7 +23,6 @@
#include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/slab.h>
-#include <linux/vmalloc.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/init.h>
@@ -57,7 +56,6 @@
#include "bnx2x_init_ops.h"
#include "bnx2x_cmn.h"
-
#include <linux/firmware.h>
#include "bnx2x_fw_file_hdr.h"
/* FW files */
@@ -66,8 +64,9 @@
__stringify(BCM_5710_FW_MINOR_VERSION) "." \
__stringify(BCM_5710_FW_REVISION_VERSION) "." \
__stringify(BCM_5710_FW_ENGINEERING_VERSION)
-#define FW_FILE_NAME_E1 "bnx2x-e1-" FW_FILE_VERSION ".fw"
-#define FW_FILE_NAME_E1H "bnx2x-e1h-" FW_FILE_VERSION ".fw"
+#define FW_FILE_NAME_E1 "bnx2x/bnx2x-e1-" FW_FILE_VERSION ".fw"
+#define FW_FILE_NAME_E1H "bnx2x/bnx2x-e1h-" FW_FILE_VERSION ".fw"
+#define FW_FILE_NAME_E2 "bnx2x/bnx2x-e2-" FW_FILE_VERSION ".fw"
/* Time in jiffies before concluding the transmitter is hung */
#define TX_TIMEOUT (5*HZ)
@@ -77,18 +76,20 @@ static char version[] __devinitdata =
DRV_MODULE_NAME " " DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
MODULE_AUTHOR("Eliezer Tamir");
-MODULE_DESCRIPTION("Broadcom NetXtreme II BCM57710/57711/57711E Driver");
+MODULE_DESCRIPTION("Broadcom NetXtreme II "
+ "BCM57710/57711/57711E/57712/57712E Driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_MODULE_VERSION);
MODULE_FIRMWARE(FW_FILE_NAME_E1);
MODULE_FIRMWARE(FW_FILE_NAME_E1H);
+MODULE_FIRMWARE(FW_FILE_NAME_E2);
static int multi_mode = 1;
module_param(multi_mode, int, 0);
MODULE_PARM_DESC(multi_mode, " Multi queue mode "
"(0 Disable; 1 Enable (default))");
-static int num_queues;
+int num_queues;
module_param(num_queues, int, 0);
MODULE_PARM_DESC(num_queues, " Number of queues for multi_mode=1"
" (default is as a number of CPUs)");
@@ -124,6 +125,8 @@ enum bnx2x_board_type {
BCM57710 = 0,
BCM57711 = 1,
BCM57711E = 2,
+ BCM57712 = 3,
+ BCM57712E = 4
};
/* indexed by board_type, above */
@@ -132,14 +135,24 @@ static struct {
} board_info[] __devinitdata = {
{ "Broadcom NetXtreme II BCM57710 XGb" },
{ "Broadcom NetXtreme II BCM57711 XGb" },
- { "Broadcom NetXtreme II BCM57711E XGb" }
+ { "Broadcom NetXtreme II BCM57711E XGb" },
+ { "Broadcom NetXtreme II BCM57712 XGb" },
+ { "Broadcom NetXtreme II BCM57712E XGb" }
};
+#ifndef PCI_DEVICE_ID_NX2_57712
+#define PCI_DEVICE_ID_NX2_57712 0x1662
+#endif
+#ifndef PCI_DEVICE_ID_NX2_57712E
+#define PCI_DEVICE_ID_NX2_57712E 0x1663
+#endif
static DEFINE_PCI_DEVICE_TABLE(bnx2x_pci_tbl) = {
{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57710), BCM57710 },
{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57711), BCM57711 },
{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57711E), BCM57711E },
+ { PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57712), BCM57712 },
+ { PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57712E), BCM57712E },
{ 0 }
};
@@ -149,6 +162,244 @@ MODULE_DEVICE_TABLE(pci, bnx2x_pci_tbl);
* General service functions
****************************************************************************/
+static inline void __storm_memset_dma_mapping(struct bnx2x *bp,
+ u32 addr, dma_addr_t mapping)
+{
+ REG_WR(bp, addr, U64_LO(mapping));
+ REG_WR(bp, addr + 4, U64_HI(mapping));
+}
+
+static inline void __storm_memset_fill(struct bnx2x *bp,
+ u32 addr, size_t size, u32 val)
+{
+ int i;
+ for (i = 0; i < size/4; i++)
+ REG_WR(bp, addr + (i * 4), val);
+}
+
+static inline void storm_memset_ustats_zero(struct bnx2x *bp,
+ u8 port, u16 stat_id)
+{
+ size_t size = sizeof(struct ustorm_per_client_stats);
+
+ u32 addr = BAR_USTRORM_INTMEM +
+ USTORM_PER_COUNTER_ID_STATS_OFFSET(port, stat_id);
+
+ __storm_memset_fill(bp, addr, size, 0);
+}
+
+static inline void storm_memset_tstats_zero(struct bnx2x *bp,
+ u8 port, u16 stat_id)
+{
+ size_t size = sizeof(struct tstorm_per_client_stats);
+
+ u32 addr = BAR_TSTRORM_INTMEM +
+ TSTORM_PER_COUNTER_ID_STATS_OFFSET(port, stat_id);
+
+ __storm_memset_fill(bp, addr, size, 0);
+}
+
+static inline void storm_memset_xstats_zero(struct bnx2x *bp,
+ u8 port, u16 stat_id)
+{
+ size_t size = sizeof(struct xstorm_per_client_stats);
+
+ u32 addr = BAR_XSTRORM_INTMEM +
+ XSTORM_PER_COUNTER_ID_STATS_OFFSET(port, stat_id);
+
+ __storm_memset_fill(bp, addr, size, 0);
+}
+
+
+static inline void storm_memset_spq_addr(struct bnx2x *bp,
+ dma_addr_t mapping, u16 abs_fid)
+{
+ u32 addr = XSEM_REG_FAST_MEMORY +
+ XSTORM_SPQ_PAGE_BASE_OFFSET(abs_fid);
+
+ __storm_memset_dma_mapping(bp, addr, mapping);
+}
+
+static inline void storm_memset_ov(struct bnx2x *bp, u16 ov, u16 abs_fid)
+{
+ REG_WR16(bp, BAR_XSTRORM_INTMEM + XSTORM_E1HOV_OFFSET(abs_fid), ov);
+}
+
+static inline void storm_memset_func_cfg(struct bnx2x *bp,
+ struct tstorm_eth_function_common_config *tcfg,
+ u16 abs_fid)
+{
+ size_t size = sizeof(struct tstorm_eth_function_common_config);
+
+ u32 addr = BAR_TSTRORM_INTMEM +
+ TSTORM_FUNCTION_COMMON_CONFIG_OFFSET(abs_fid);
+
+ __storm_memset_struct(bp, addr, size, (u32 *)tcfg);
+}
+
+static inline void storm_memset_xstats_flags(struct bnx2x *bp,
+ struct stats_indication_flags *flags,
+ u16 abs_fid)
+{
+ size_t size = sizeof(struct stats_indication_flags);
+
+ u32 addr = BAR_XSTRORM_INTMEM + XSTORM_STATS_FLAGS_OFFSET(abs_fid);
+
+ __storm_memset_struct(bp, addr, size, (u32 *)flags);
+}
+
+static inline void storm_memset_tstats_flags(struct bnx2x *bp,
+ struct stats_indication_flags *flags,
+ u16 abs_fid)
+{
+ size_t size = sizeof(struct stats_indication_flags);
+
+ u32 addr = BAR_TSTRORM_INTMEM + TSTORM_STATS_FLAGS_OFFSET(abs_fid);
+
+ __storm_memset_struct(bp, addr, size, (u32 *)flags);
+}
+
+static inline void storm_memset_ustats_flags(struct bnx2x *bp,
+ struct stats_indication_flags *flags,
+ u16 abs_fid)
+{
+ size_t size = sizeof(struct stats_indication_flags);
+
+ u32 addr = BAR_USTRORM_INTMEM + USTORM_STATS_FLAGS_OFFSET(abs_fid);
+
+ __storm_memset_struct(bp, addr, size, (u32 *)flags);
+}
+
+static inline void storm_memset_cstats_flags(struct bnx2x *bp,
+ struct stats_indication_flags *flags,
+ u16 abs_fid)
+{
+ size_t size = sizeof(struct stats_indication_flags);
+
+ u32 addr = BAR_CSTRORM_INTMEM + CSTORM_STATS_FLAGS_OFFSET(abs_fid);
+
+ __storm_memset_struct(bp, addr, size, (u32 *)flags);
+}
+
+static inline void storm_memset_xstats_addr(struct bnx2x *bp,
+ dma_addr_t mapping, u16 abs_fid)
+{
+ u32 addr = BAR_XSTRORM_INTMEM +
+ XSTORM_ETH_STATS_QUERY_ADDR_OFFSET(abs_fid);
+
+ __storm_memset_dma_mapping(bp, addr, mapping);
+}
+
+static inline void storm_memset_tstats_addr(struct bnx2x *bp,
+ dma_addr_t mapping, u16 abs_fid)
+{
+ u32 addr = BAR_TSTRORM_INTMEM +
+ TSTORM_ETH_STATS_QUERY_ADDR_OFFSET(abs_fid);
+
+ __storm_memset_dma_mapping(bp, addr, mapping);
+}
+
+static inline void storm_memset_ustats_addr(struct bnx2x *bp,
+ dma_addr_t mapping, u16 abs_fid)
+{
+ u32 addr = BAR_USTRORM_INTMEM +
+ USTORM_ETH_STATS_QUERY_ADDR_OFFSET(abs_fid);
+
+ __storm_memset_dma_mapping(bp, addr, mapping);
+}
+
+static inline void storm_memset_cstats_addr(struct bnx2x *bp,
+ dma_addr_t mapping, u16 abs_fid)
+{
+ u32 addr = BAR_CSTRORM_INTMEM +
+ CSTORM_ETH_STATS_QUERY_ADDR_OFFSET(abs_fid);
+
+ __storm_memset_dma_mapping(bp, addr, mapping);
+}
+
+static inline void storm_memset_vf_to_pf(struct bnx2x *bp, u16 abs_fid,
+ u16 pf_id)
+{
+ REG_WR8(bp, BAR_XSTRORM_INTMEM + XSTORM_VF_TO_PF_OFFSET(abs_fid),
+ pf_id);
+ REG_WR8(bp, BAR_CSTRORM_INTMEM + CSTORM_VF_TO_PF_OFFSET(abs_fid),
+ pf_id);
+ REG_WR8(bp, BAR_TSTRORM_INTMEM + TSTORM_VF_TO_PF_OFFSET(abs_fid),
+ pf_id);
+ REG_WR8(bp, BAR_USTRORM_INTMEM + USTORM_VF_TO_PF_OFFSET(abs_fid),
+ pf_id);
+}
+
+static inline void storm_memset_func_en(struct bnx2x *bp, u16 abs_fid,
+ u8 enable)
+{
+ REG_WR8(bp, BAR_XSTRORM_INTMEM + XSTORM_FUNC_EN_OFFSET(abs_fid),
+ enable);
+ REG_WR8(bp, BAR_CSTRORM_INTMEM + CSTORM_FUNC_EN_OFFSET(abs_fid),
+ enable);
+ REG_WR8(bp, BAR_TSTRORM_INTMEM + TSTORM_FUNC_EN_OFFSET(abs_fid),
+ enable);
+ REG_WR8(bp, BAR_USTRORM_INTMEM + USTORM_FUNC_EN_OFFSET(abs_fid),
+ enable);
+}
+
+static inline void storm_memset_eq_data(struct bnx2x *bp,
+ struct event_ring_data *eq_data,
+ u16 pfid)
+{
+ size_t size = sizeof(struct event_ring_data);
+
+ u32 addr = BAR_CSTRORM_INTMEM + CSTORM_EVENT_RING_DATA_OFFSET(pfid);
+
+ __storm_memset_struct(bp, addr, size, (u32 *)eq_data);
+}
+
+static inline void storm_memset_eq_prod(struct bnx2x *bp, u16 eq_prod,
+ u16 pfid)
+{
+ u32 addr = BAR_CSTRORM_INTMEM + CSTORM_EVENT_RING_PROD_OFFSET(pfid);
+ REG_WR16(bp, addr, eq_prod);
+}
+
+static inline void storm_memset_hc_timeout(struct bnx2x *bp, u8 port,
+ u16 fw_sb_id, u8 sb_index,
+ u8 ticks)
+{
+
+ int index_offset = CHIP_IS_E2(bp) ?
+ offsetof(struct hc_status_block_data_e2, index_data) :
+ offsetof(struct hc_status_block_data_e1x, index_data);
+ u32 addr = BAR_CSTRORM_INTMEM +
+ CSTORM_STATUS_BLOCK_DATA_OFFSET(fw_sb_id) +
+ index_offset +
+ sizeof(struct hc_index_data)*sb_index +
+ offsetof(struct hc_index_data, timeout);
+ REG_WR8(bp, addr, ticks);
+ DP(NETIF_MSG_HW, "port %x fw_sb_id %d sb_index %d ticks %d\n",
+ port, fw_sb_id, sb_index, ticks);
+}
+static inline void storm_memset_hc_disable(struct bnx2x *bp, u8 port,
+ u16 fw_sb_id, u8 sb_index,
+ u8 disable)
+{
+ u32 enable_flag = disable ? 0 : (1 << HC_INDEX_DATA_HC_ENABLED_SHIFT);
+ int index_offset = CHIP_IS_E2(bp) ?
+ offsetof(struct hc_status_block_data_e2, index_data) :
+ offsetof(struct hc_status_block_data_e1x, index_data);
+ u32 addr = BAR_CSTRORM_INTMEM +
+ CSTORM_STATUS_BLOCK_DATA_OFFSET(fw_sb_id) +
+ index_offset +
+ sizeof(struct hc_index_data)*sb_index +
+ offsetof(struct hc_index_data, flags);
+ u16 flags = REG_RD16(bp, addr);
+ /* clear and set */
+ flags &= ~HC_INDEX_DATA_HC_ENABLED;
+ flags |= enable_flag;
+ REG_WR16(bp, addr, flags);
+ DP(NETIF_MSG_HW, "port %x fw_sb_id %d sb_index %d disable %d\n",
+ port, fw_sb_id, sb_index, disable);
+}
+
/* used only at init
* locking is done by mcp
*/
@@ -172,6 +423,75 @@ static u32 bnx2x_reg_rd_ind(struct bnx2x *bp, u32 addr)
return val;
}
+#define DMAE_DP_SRC_GRC "grc src_addr [%08x]"
+#define DMAE_DP_SRC_PCI "pci src_addr [%x:%08x]"
+#define DMAE_DP_DST_GRC "grc dst_addr [%08x]"
+#define DMAE_DP_DST_PCI "pci dst_addr [%x:%08x]"
+#define DMAE_DP_DST_NONE "dst_addr [none]"
+
+void bnx2x_dp_dmae(struct bnx2x *bp, struct dmae_command *dmae, int msglvl)
+{
+ u32 src_type = dmae->opcode & DMAE_COMMAND_SRC;
+
+ switch (dmae->opcode & DMAE_COMMAND_DST) {
+ case DMAE_CMD_DST_PCI:
+ if (src_type == DMAE_CMD_SRC_PCI)
+ DP(msglvl, "DMAE: opcode 0x%08x\n"
+ "src [%x:%08x], len [%d*4], dst [%x:%08x]\n"
+ "comp_addr [%x:%08x], comp_val 0x%08x\n",
+ dmae->opcode, dmae->src_addr_hi, dmae->src_addr_lo,
+ dmae->len, dmae->dst_addr_hi, dmae->dst_addr_lo,
+ dmae->comp_addr_hi, dmae->comp_addr_lo,
+ dmae->comp_val);
+ else
+ DP(msglvl, "DMAE: opcode 0x%08x\n"
+ "src [%08x], len [%d*4], dst [%x:%08x]\n"
+ "comp_addr [%x:%08x], comp_val 0x%08x\n",
+ dmae->opcode, dmae->src_addr_lo >> 2,
+ dmae->len, dmae->dst_addr_hi, dmae->dst_addr_lo,
+ dmae->comp_addr_hi, dmae->comp_addr_lo,
+ dmae->comp_val);
+ break;
+ case DMAE_CMD_DST_GRC:
+ if (src_type == DMAE_CMD_SRC_PCI)
+ DP(msglvl, "DMAE: opcode 0x%08x\n"
+ "src [%x:%08x], len [%d*4], dst_addr [%08x]\n"
+ "comp_addr [%x:%08x], comp_val 0x%08x\n",
+ dmae->opcode, dmae->src_addr_hi, dmae->src_addr_lo,
+ dmae->len, dmae->dst_addr_lo >> 2,
+ dmae->comp_addr_hi, dmae->comp_addr_lo,
+ dmae->comp_val);
+ else
+ DP(msglvl, "DMAE: opcode 0x%08x\n"
+ "src [%08x], len [%d*4], dst [%08x]\n"
+ "comp_addr [%x:%08x], comp_val 0x%08x\n",
+ dmae->opcode, dmae->src_addr_lo >> 2,
+ dmae->len, dmae->dst_addr_lo >> 2,
+ dmae->comp_addr_hi, dmae->comp_addr_lo,
+ dmae->comp_val);
+ break;
+ default:
+ if (src_type == DMAE_CMD_SRC_PCI)
+ DP(msglvl, "DMAE: opcode 0x%08x\n"
+ DP_LEVEL "src_addr [%x:%08x] len [%d * 4] "
+ "dst_addr [none]\n"
+ DP_LEVEL "comp_addr [%x:%08x] comp_val 0x%08x\n",
+ dmae->opcode, dmae->src_addr_hi, dmae->src_addr_lo,
+ dmae->len, dmae->comp_addr_hi, dmae->comp_addr_lo,
+ dmae->comp_val);
+ else
+ DP(msglvl, "DMAE: opcode 0x%08x\n"
+ DP_LEVEL "src_addr [%08x] len [%d * 4] "
+ "dst_addr [none]\n"
+ DP_LEVEL "comp_addr [%x:%08x] comp_val 0x%08x\n",
+ dmae->opcode, dmae->src_addr_lo >> 2,
+ dmae->len, dmae->comp_addr_hi, dmae->comp_addr_lo,
+ dmae->comp_val);
+ break;
+ }
+
+}
+
const u32 dmae_reg_go_c[] = {
DMAE_REG_GO_C0, DMAE_REG_GO_C1, DMAE_REG_GO_C2, DMAE_REG_GO_C3,
DMAE_REG_GO_C4, DMAE_REG_GO_C5, DMAE_REG_GO_C6, DMAE_REG_GO_C7,
@@ -195,85 +515,137 @@ void bnx2x_post_dmae(struct bnx2x *bp, struct dmae_command *dmae, int idx)
REG_WR(bp, dmae_reg_go_c[idx], 1);
}
-void bnx2x_write_dmae(struct bnx2x *bp, dma_addr_t dma_addr, u32 dst_addr,
- u32 len32)
+u32 bnx2x_dmae_opcode_add_comp(u32 opcode, u8 comp_type)
{
- struct dmae_command dmae;
- u32 *wb_comp = bnx2x_sp(bp, wb_comp);
- int cnt = 200;
+ return opcode | ((comp_type << DMAE_COMMAND_C_DST_SHIFT) |
+ DMAE_CMD_C_ENABLE);
+}
- if (!bp->dmae_ready) {
- u32 *data = bnx2x_sp(bp, wb_data[0]);
+u32 bnx2x_dmae_opcode_clr_src_reset(u32 opcode)
+{
+ return opcode & ~DMAE_CMD_SRC_RESET;
+}
- DP(BNX2X_MSG_OFF, "DMAE is not ready (dst_addr %08x len32 %d)"
- " using indirect\n", dst_addr, len32);
- bnx2x_init_ind_wr(bp, dst_addr, data, len32);
- return;
- }
+u32 bnx2x_dmae_opcode(struct bnx2x *bp, u8 src_type, u8 dst_type,
+ bool with_comp, u8 comp_type)
+{
+ u32 opcode = 0;
+
+ opcode |= ((src_type << DMAE_COMMAND_SRC_SHIFT) |
+ (dst_type << DMAE_COMMAND_DST_SHIFT));
+
+ opcode |= (DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET);
- memset(&dmae, 0, sizeof(struct dmae_command));
+ opcode |= (BP_PORT(bp) ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0);
+ opcode |= ((BP_E1HVN(bp) << DMAE_CMD_E1HVN_SHIFT) |
+ (BP_E1HVN(bp) << DMAE_COMMAND_DST_VN_SHIFT));
+ opcode |= (DMAE_COM_SET_ERR << DMAE_COMMAND_ERR_POLICY_SHIFT);
- dmae.opcode = (DMAE_CMD_SRC_PCI | DMAE_CMD_DST_GRC |
- DMAE_CMD_C_DST_PCI | DMAE_CMD_C_ENABLE |
- DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET |
#ifdef __BIG_ENDIAN
- DMAE_CMD_ENDIANITY_B_DW_SWAP |
+ opcode |= DMAE_CMD_ENDIANITY_B_DW_SWAP;
#else
- DMAE_CMD_ENDIANITY_DW_SWAP |
+ opcode |= DMAE_CMD_ENDIANITY_DW_SWAP;
#endif
- (BP_PORT(bp) ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0) |
- (BP_E1HVN(bp) << DMAE_CMD_E1HVN_SHIFT));
- dmae.src_addr_lo = U64_LO(dma_addr);
- dmae.src_addr_hi = U64_HI(dma_addr);
- dmae.dst_addr_lo = dst_addr >> 2;
- dmae.dst_addr_hi = 0;
- dmae.len = len32;
- dmae.comp_addr_lo = U64_LO(bnx2x_sp_mapping(bp, wb_comp));
- dmae.comp_addr_hi = U64_HI(bnx2x_sp_mapping(bp, wb_comp));
- dmae.comp_val = DMAE_COMP_VAL;
-
- DP(BNX2X_MSG_OFF, "DMAE: opcode 0x%08x\n"
- DP_LEVEL "src_addr [%x:%08x] len [%d *4] "
- "dst_addr [%x:%08x (%08x)]\n"
- DP_LEVEL "comp_addr [%x:%08x] comp_val 0x%08x\n",
- dmae.opcode, dmae.src_addr_hi, dmae.src_addr_lo,
- dmae.len, dmae.dst_addr_hi, dmae.dst_addr_lo, dst_addr,
- dmae.comp_addr_hi, dmae.comp_addr_lo, dmae.comp_val);
- DP(BNX2X_MSG_OFF, "data [0x%08x 0x%08x 0x%08x 0x%08x]\n",
+ if (with_comp)
+ opcode = bnx2x_dmae_opcode_add_comp(opcode, comp_type);
+ return opcode;
+}
+
+void bnx2x_prep_dmae_with_comp(struct bnx2x *bp, struct dmae_command *dmae,
+ u8 src_type, u8 dst_type)
+{
+ memset(dmae, 0, sizeof(struct dmae_command));
+
+ /* set the opcode */
+ dmae->opcode = bnx2x_dmae_opcode(bp, src_type, dst_type,
+ true, DMAE_COMP_PCI);
+
+ /* fill in the completion parameters */
+ dmae->comp_addr_lo = U64_LO(bnx2x_sp_mapping(bp, wb_comp));
+ dmae->comp_addr_hi = U64_HI(bnx2x_sp_mapping(bp, wb_comp));
+ dmae->comp_val = DMAE_COMP_VAL;
+}
+
+/* issue a dmae command over the init-channel and wailt for completion */
+int bnx2x_issue_dmae_with_comp(struct bnx2x *bp, struct dmae_command *dmae)
+{
+ u32 *wb_comp = bnx2x_sp(bp, wb_comp);
+ int cnt = CHIP_REV_IS_SLOW(bp) ? (400000) : 40;
+ int rc = 0;
+
+ DP(BNX2X_MSG_OFF, "data before [0x%08x 0x%08x 0x%08x 0x%08x]\n",
bp->slowpath->wb_data[0], bp->slowpath->wb_data[1],
bp->slowpath->wb_data[2], bp->slowpath->wb_data[3]);
+ /* lock the dmae channel */
mutex_lock(&bp->dmae_mutex);
+ /* reset completion */
*wb_comp = 0;
- bnx2x_post_dmae(bp, &dmae, INIT_DMAE_C(bp));
+ /* post the command on the channel used for initializations */
+ bnx2x_post_dmae(bp, dmae, INIT_DMAE_C(bp));
+ /* wait for completion */
udelay(5);
-
- while (*wb_comp != DMAE_COMP_VAL) {
+ while ((*wb_comp & ~DMAE_PCI_ERR_FLAG) != DMAE_COMP_VAL) {
DP(BNX2X_MSG_OFF, "wb_comp 0x%08x\n", *wb_comp);
if (!cnt) {
BNX2X_ERR("DMAE timeout!\n");
- break;
+ rc = DMAE_TIMEOUT;
+ goto unlock;
}
cnt--;
- /* adjust delay for emulation/FPGA */
- if (CHIP_REV_IS_SLOW(bp))
- msleep(100);
- else
- udelay(5);
+ udelay(50);
+ }
+ if (*wb_comp & DMAE_PCI_ERR_FLAG) {
+ BNX2X_ERR("DMAE PCI error!\n");
+ rc = DMAE_PCI_ERROR;
}
+ DP(BNX2X_MSG_OFF, "data after [0x%08x 0x%08x 0x%08x 0x%08x]\n",
+ bp->slowpath->wb_data[0], bp->slowpath->wb_data[1],
+ bp->slowpath->wb_data[2], bp->slowpath->wb_data[3]);
+
+unlock:
mutex_unlock(&bp->dmae_mutex);
+ return rc;
+}
+
+void bnx2x_write_dmae(struct bnx2x *bp, dma_addr_t dma_addr, u32 dst_addr,
+ u32 len32)
+{
+ struct dmae_command dmae;
+
+ if (!bp->dmae_ready) {
+ u32 *data = bnx2x_sp(bp, wb_data[0]);
+
+ DP(BNX2X_MSG_OFF, "DMAE is not ready (dst_addr %08x len32 %d)"
+ " using indirect\n", dst_addr, len32);
+ bnx2x_init_ind_wr(bp, dst_addr, data, len32);
+ return;
+ }
+
+ /* set opcode and fixed command fields */
+ bnx2x_prep_dmae_with_comp(bp, &dmae, DMAE_SRC_PCI, DMAE_DST_GRC);
+
+ /* fill in addresses and len */
+ dmae.src_addr_lo = U64_LO(dma_addr);
+ dmae.src_addr_hi = U64_HI(dma_addr);
+ dmae.dst_addr_lo = dst_addr >> 2;
+ dmae.dst_addr_hi = 0;
+ dmae.len = len32;
+
+ bnx2x_dp_dmae(bp, &dmae, BNX2X_MSG_OFF);
+
+ /* issue the command and wait for completion */
+ bnx2x_issue_dmae_with_comp(bp, &dmae);
}
void bnx2x_read_dmae(struct bnx2x *bp, u32 src_addr, u32 len32)
{
struct dmae_command dmae;
- u32 *wb_comp = bnx2x_sp(bp, wb_comp);
- int cnt = 200;
if (!bp->dmae_ready) {
u32 *data = bnx2x_sp(bp, wb_data[0]);
@@ -286,62 +658,20 @@ void bnx2x_read_dmae(struct bnx2x *bp, u32 src_addr, u32 len32)
return;
}
- memset(&dmae, 0, sizeof(struct dmae_command));
+ /* set opcode and fixed command fields */
+ bnx2x_prep_dmae_with_comp(bp, &dmae, DMAE_SRC_GRC, DMAE_DST_PCI);
- dmae.opcode = (DMAE_CMD_SRC_GRC | DMAE_CMD_DST_PCI |
- DMAE_CMD_C_DST_PCI | DMAE_CMD_C_ENABLE |
- DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET |
-#ifdef __BIG_ENDIAN
- DMAE_CMD_ENDIANITY_B_DW_SWAP |
-#else
- DMAE_CMD_ENDIANITY_DW_SWAP |
-#endif
- (BP_PORT(bp) ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0) |
- (BP_E1HVN(bp) << DMAE_CMD_E1HVN_SHIFT));
+ /* fill in addresses and len */
dmae.src_addr_lo = src_addr >> 2;
dmae.src_addr_hi = 0;
dmae.dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, wb_data));
dmae.dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, wb_data));
dmae.len = len32;
- dmae.comp_addr_lo = U64_LO(bnx2x_sp_mapping(bp, wb_comp));
- dmae.comp_addr_hi = U64_HI(bnx2x_sp_mapping(bp, wb_comp));
- dmae.comp_val = DMAE_COMP_VAL;
-
- DP(BNX2X_MSG_OFF, "DMAE: opcode 0x%08x\n"
- DP_LEVEL "src_addr [%x:%08x] len [%d *4] "
- "dst_addr [%x:%08x (%08x)]\n"
- DP_LEVEL "comp_addr [%x:%08x] comp_val 0x%08x\n",
- dmae.opcode, dmae.src_addr_hi, dmae.src_addr_lo,
- dmae.len, dmae.dst_addr_hi, dmae.dst_addr_lo, src_addr,
- dmae.comp_addr_hi, dmae.comp_addr_lo, dmae.comp_val);
- mutex_lock(&bp->dmae_mutex);
+ bnx2x_dp_dmae(bp, &dmae, BNX2X_MSG_OFF);
- memset(bnx2x_sp(bp, wb_data[0]), 0, sizeof(u32) * 4);
- *wb_comp = 0;
-
- bnx2x_post_dmae(bp, &dmae, INIT_DMAE_C(bp));
-
- udelay(5);
-
- while (*wb_comp != DMAE_COMP_VAL) {
-
- if (!cnt) {
- BNX2X_ERR("DMAE timeout!\n");
- break;
- }
- cnt--;
- /* adjust delay for emulation/FPGA */
- if (CHIP_REV_IS_SLOW(bp))
- msleep(100);
- else
- udelay(5);
- }
- DP(BNX2X_MSG_OFF, "data [0x%08x 0x%08x 0x%08x 0x%08x]\n",
- bp->slowpath->wb_data[0], bp->slowpath->wb_data[1],
- bp->slowpath->wb_data[2], bp->slowpath->wb_data[3]);
-
- mutex_unlock(&bp->dmae_mutex);
+ /* issue the command and wait for completion */
+ bnx2x_issue_dmae_with_comp(bp, &dmae);
}
void bnx2x_write_dmae_phys_len(struct bnx2x *bp, dma_addr_t phys_addr,
@@ -508,19 +838,24 @@ static void bnx2x_fw_dump(struct bnx2x *bp)
u32 mark, offset;
__be32 data[9];
int word;
-
+ u32 trace_shmem_base;
if (BP_NOMCP(bp)) {
BNX2X_ERR("NO MCP - can not dump\n");
return;
}
- addr = bp->common.shmem_base - 0x0800 + 4;
+ if (BP_PATH(bp) == 0)
+ trace_shmem_base = bp->common.shmem_base;
+ else
+ trace_shmem_base = SHMEM2_RD(bp, other_shmem_base_addr);
+ addr = trace_shmem_base - 0x0800 + 4;
mark = REG_RD(bp, addr);
- mark = MCP_REG_MCPR_SCRATCH + ((mark + 0x3) & ~0x3) - 0x08000000;
+ mark = (CHIP_IS_E1x(bp) ? MCP_REG_MCPR_SCRATCH : MCP_A_REG_MCPR_SCRATCH)
+ + ((mark + 0x3) & ~0x3) - 0x08000000;
pr_err("begin fw dump (mark 0x%x)\n", mark);
pr_err("");
- for (offset = mark; offset <= bp->common.shmem_base; offset += 0x8*4) {
+ for (offset = mark; offset <= trace_shmem_base; offset += 0x8*4) {
for (word = 0; word < 8; word++)
data[word] = htonl(REG_RD(bp, offset + 4*word));
data[8] = 0x0;
@@ -538,7 +873,12 @@ static void bnx2x_fw_dump(struct bnx2x *bp)
void bnx2x_panic_dump(struct bnx2x *bp)
{
int i;
- u16 j, start, end;
+ u16 j;
+ struct hc_sp_status_block_data sp_sb_data;
+ int func = BP_FUNC(bp);
+#ifdef BNX2X_STOP_ON_ERROR
+ u16 start = 0, end = 0;
+#endif
bp->stats_state = STATS_STATE_DISABLED;
DP(BNX2X_MSG_STATS, "stats_state - DISABLED\n");
@@ -547,44 +887,143 @@ void bnx2x_panic_dump(struct bnx2x *bp)
/* Indices */
/* Common */
- BNX2X_ERR("def_c_idx(0x%x) def_u_idx(0x%x) def_x_idx(0x%x)"
- " def_t_idx(0x%x) def_att_idx(0x%x) attn_state(0x%x)"
+ BNX2X_ERR("def_idx(0x%x) def_att_idx(0x%x) attn_state(0x%x)"
" spq_prod_idx(0x%x)\n",
- bp->def_c_idx, bp->def_u_idx, bp->def_x_idx, bp->def_t_idx,
- bp->def_att_idx, bp->attn_state, bp->spq_prod_idx);
+ bp->def_idx, bp->def_att_idx,
+ bp->attn_state, bp->spq_prod_idx);
+ BNX2X_ERR("DSB: attn bits(0x%x) ack(0x%x) id(0x%x) idx(0x%x)\n",
+ bp->def_status_blk->atten_status_block.attn_bits,
+ bp->def_status_blk->atten_status_block.attn_bits_ack,
+ bp->def_status_blk->atten_status_block.status_block_id,
+ bp->def_status_blk->atten_status_block.attn_bits_index);
+ BNX2X_ERR(" def (");
+ for (i = 0; i < HC_SP_SB_MAX_INDICES; i++)
+ pr_cont("0x%x%s",
+ bp->def_status_blk->sp_sb.index_values[i],
+ (i == HC_SP_SB_MAX_INDICES - 1) ? ") " : " ");
+
+ for (i = 0; i < sizeof(struct hc_sp_status_block_data)/sizeof(u32); i++)
+ *((u32 *)&sp_sb_data + i) = REG_RD(bp, BAR_CSTRORM_INTMEM +
+ CSTORM_SP_STATUS_BLOCK_DATA_OFFSET(func) +
+ i*sizeof(u32));
+
+ pr_cont("igu_sb_id(0x%x) igu_seg_id (0x%x) "
+ "pf_id(0x%x) vnic_id(0x%x) "
+ "vf_id(0x%x) vf_valid (0x%x)\n",
+ sp_sb_data.igu_sb_id,
+ sp_sb_data.igu_seg_id,
+ sp_sb_data.p_func.pf_id,
+ sp_sb_data.p_func.vnic_id,
+ sp_sb_data.p_func.vf_id,
+ sp_sb_data.p_func.vf_valid);
+
- /* Rx */
for_each_queue(bp, i) {
struct bnx2x_fastpath *fp = &bp->fp[i];
-
+ int loop;
+ struct hc_status_block_data_e2 sb_data_e2;
+ struct hc_status_block_data_e1x sb_data_e1x;
+ struct hc_status_block_sm *hc_sm_p =
+ CHIP_IS_E2(bp) ?
+ sb_data_e2.common.state_machine :
+ sb_data_e1x.common.state_machine;
+ struct hc_index_data *hc_index_p =
+ CHIP_IS_E2(bp) ?
+ sb_data_e2.index_data :
+ sb_data_e1x.index_data;
+ int data_size;
+ u32 *sb_data_p;
+
+ /* Rx */
BNX2X_ERR("fp%d: rx_bd_prod(0x%x) rx_bd_cons(0x%x)"
- " *rx_bd_cons_sb(0x%x) rx_comp_prod(0x%x)"
+ " rx_comp_prod(0x%x)"
" rx_comp_cons(0x%x) *rx_cons_sb(0x%x)\n",
i, fp->rx_bd_prod, fp->rx_bd_cons,
- le16_to_cpu(*fp->rx_bd_cons_sb), fp->rx_comp_prod,
+ fp->rx_comp_prod,
fp->rx_comp_cons, le16_to_cpu(*fp->rx_cons_sb));
BNX2X_ERR(" rx_sge_prod(0x%x) last_max_sge(0x%x)"
- " fp_u_idx(0x%x) *sb_u_idx(0x%x)\n",
+ " fp_hc_idx(0x%x)\n",
fp->rx_sge_prod, fp->last_max_sge,
- le16_to_cpu(fp->fp_u_idx),
- fp->status_blk->u_status_block.status_block_index);
- }
-
- /* Tx */
- for_each_queue(bp, i) {
- struct bnx2x_fastpath *fp = &bp->fp[i];
+ le16_to_cpu(fp->fp_hc_idx));
+ /* Tx */
BNX2X_ERR("fp%d: tx_pkt_prod(0x%x) tx_pkt_cons(0x%x)"
" tx_bd_prod(0x%x) tx_bd_cons(0x%x)"
" *tx_cons_sb(0x%x)\n",
i, fp->tx_pkt_prod, fp->tx_pkt_cons, fp->tx_bd_prod,
fp->tx_bd_cons, le16_to_cpu(*fp->tx_cons_sb));
- BNX2X_ERR(" fp_c_idx(0x%x) *sb_c_idx(0x%x)"
- " tx_db_prod(0x%x)\n", le16_to_cpu(fp->fp_c_idx),
- fp->status_blk->c_status_block.status_block_index,
- fp->tx_db.data.prod);
+
+ loop = CHIP_IS_E2(bp) ?
+ HC_SB_MAX_INDICES_E2 : HC_SB_MAX_INDICES_E1X;
+
+ /* host sb data */
+
+ BNX2X_ERR(" run indexes (");
+ for (j = 0; j < HC_SB_MAX_SM; j++)
+ pr_cont("0x%x%s",
+ fp->sb_running_index[j],
+ (j == HC_SB_MAX_SM - 1) ? ")" : " ");
+
+ BNX2X_ERR(" indexes (");
+ for (j = 0; j < loop; j++)
+ pr_cont("0x%x%s",
+ fp->sb_index_values[j],
+ (j == loop - 1) ? ")" : " ");
+ /* fw sb data */
+ data_size = CHIP_IS_E2(bp) ?
+ sizeof(struct hc_status_block_data_e2) :
+ sizeof(struct hc_status_block_data_e1x);
+ data_size /= sizeof(u32);
+ sb_data_p = CHIP_IS_E2(bp) ?
+ (u32 *)&sb_data_e2 :
+ (u32 *)&sb_data_e1x;
+ /* copy sb data in here */
+ for (j = 0; j < data_size; j++)
+ *(sb_data_p + j) = REG_RD(bp, BAR_CSTRORM_INTMEM +
+ CSTORM_STATUS_BLOCK_DATA_OFFSET(fp->fw_sb_id) +
+ j * sizeof(u32));
+
+ if (CHIP_IS_E2(bp)) {
+ pr_cont("pf_id(0x%x) vf_id (0x%x) vf_valid(0x%x) "
+ "vnic_id(0x%x) same_igu_sb_1b(0x%x)\n",
+ sb_data_e2.common.p_func.pf_id,
+ sb_data_e2.common.p_func.vf_id,
+ sb_data_e2.common.p_func.vf_valid,
+ sb_data_e2.common.p_func.vnic_id,
+ sb_data_e2.common.same_igu_sb_1b);
+ } else {
+ pr_cont("pf_id(0x%x) vf_id (0x%x) vf_valid(0x%x) "
+ "vnic_id(0x%x) same_igu_sb_1b(0x%x)\n",
+ sb_data_e1x.common.p_func.pf_id,
+ sb_data_e1x.common.p_func.vf_id,
+ sb_data_e1x.common.p_func.vf_valid,
+ sb_data_e1x.common.p_func.vnic_id,
+ sb_data_e1x.common.same_igu_sb_1b);
+ }
+
+ /* SB_SMs data */
+ for (j = 0; j < HC_SB_MAX_SM; j++) {
+ pr_cont("SM[%d] __flags (0x%x) "
+ "igu_sb_id (0x%x) igu_seg_id(0x%x) "
+ "time_to_expire (0x%x) "
+ "timer_value(0x%x)\n", j,
+ hc_sm_p[j].__flags,
+ hc_sm_p[j].igu_sb_id,
+ hc_sm_p[j].igu_seg_id,
+ hc_sm_p[j].time_to_expire,
+ hc_sm_p[j].timer_value);
+ }
+
+ /* Indecies data */
+ for (j = 0; j < loop; j++) {
+ pr_cont("INDEX[%d] flags (0x%x) "
+ "timeout (0x%x)\n", j,
+ hc_index_p[j].flags,
+ hc_index_p[j].timeout);
+ }
}
+#ifdef BNX2X_STOP_ON_ERROR
/* Rings */
/* Rx */
for_each_queue(bp, i) {
@@ -642,13 +1081,13 @@ void bnx2x_panic_dump(struct bnx2x *bp)
i, j, tx_bd[0], tx_bd[1], tx_bd[2], tx_bd[3]);
}
}
-
+#endif
bnx2x_fw_dump(bp);
bnx2x_mc_assert(bp);
BNX2X_ERR("end crash dump -----------------\n");
}
-void bnx2x_int_enable(struct bnx2x *bp)
+static void bnx2x_hc_int_enable(struct bnx2x *bp)
{
int port = BP_PORT(bp);
u32 addr = port ? HC_REG_CONFIG_1 : HC_REG_CONFIG_0;
@@ -672,14 +1111,19 @@ void bnx2x_int_enable(struct bnx2x *bp)
HC_CONFIG_0_REG_INT_LINE_EN_0 |
HC_CONFIG_0_REG_ATTN_BIT_EN_0);
- DP(NETIF_MSG_INTR, "write %x to HC %d (addr 0x%x)\n",
- val, port, addr);
+ if (!CHIP_IS_E1(bp)) {
+ DP(NETIF_MSG_INTR, "write %x to HC %d (addr 0x%x)\n",
+ val, port, addr);
- REG_WR(bp, addr, val);
+ REG_WR(bp, addr, val);
- val &= ~HC_CONFIG_0_REG_MSI_MSIX_INT_EN_0;
+ val &= ~HC_CONFIG_0_REG_MSI_MSIX_INT_EN_0;
+ }
}
+ if (CHIP_IS_E1(bp))
+ REG_WR(bp, HC_REG_INT_MASK + port*4, 0x1FFFF);
+
DP(NETIF_MSG_INTR, "write %x to HC %d (addr 0x%x) mode %s\n",
val, port, addr, (msix ? "MSI-X" : (msi ? "MSI" : "INTx")));
@@ -690,9 +1134,9 @@ void bnx2x_int_enable(struct bnx2x *bp)
mmiowb();
barrier();
- if (CHIP_IS_E1H(bp)) {
+ if (!CHIP_IS_E1(bp)) {
/* init leading/trailing edge */
- if (IS_E1HMF(bp)) {
+ if (IS_MF(bp)) {
val = (0xee0f | (1 << (BP_E1HVN(bp) + 4)));
if (bp->port.pmf)
/* enable nig and gpio3 attention */
@@ -708,16 +1152,91 @@ void bnx2x_int_enable(struct bnx2x *bp)
mmiowb();
}
-static void bnx2x_int_disable(struct bnx2x *bp)
+static void bnx2x_igu_int_enable(struct bnx2x *bp)
+{
+ u32 val;
+ int msix = (bp->flags & USING_MSIX_FLAG) ? 1 : 0;
+ int msi = (bp->flags & USING_MSI_FLAG) ? 1 : 0;
+
+ val = REG_RD(bp, IGU_REG_PF_CONFIGURATION);
+
+ if (msix) {
+ val &= ~(IGU_PF_CONF_INT_LINE_EN |
+ IGU_PF_CONF_SINGLE_ISR_EN);
+ val |= (IGU_PF_CONF_FUNC_EN |
+ IGU_PF_CONF_MSI_MSIX_EN |
+ IGU_PF_CONF_ATTN_BIT_EN);
+ } else if (msi) {
+ val &= ~IGU_PF_CONF_INT_LINE_EN;
+ val |= (IGU_PF_CONF_FUNC_EN |
+ IGU_PF_CONF_MSI_MSIX_EN |
+ IGU_PF_CONF_ATTN_BIT_EN |
+ IGU_PF_CONF_SINGLE_ISR_EN);
+ } else {
+ val &= ~IGU_PF_CONF_MSI_MSIX_EN;
+ val |= (IGU_PF_CONF_FUNC_EN |
+ IGU_PF_CONF_INT_LINE_EN |
+ IGU_PF_CONF_ATTN_BIT_EN |
+ IGU_PF_CONF_SINGLE_ISR_EN);
+ }
+
+ DP(NETIF_MSG_INTR, "write 0x%x to IGU mode %s\n",
+ val, (msix ? "MSI-X" : (msi ? "MSI" : "INTx")));
+
+ REG_WR(bp, IGU_REG_PF_CONFIGURATION, val);
+
+ barrier();
+
+ /* init leading/trailing edge */
+ if (IS_MF(bp)) {
+ val = (0xee0f | (1 << (BP_E1HVN(bp) + 4)));
+ if (bp->port.pmf)
+ /* enable nig and gpio3 attention */
+ val |= 0x1100;
+ } else
+ val = 0xffff;
+
+ REG_WR(bp, IGU_REG_TRAILING_EDGE_LATCH, val);
+ REG_WR(bp, IGU_REG_LEADING_EDGE_LATCH, val);
+
+ /* Make sure that interrupts are indeed enabled from here on */
+ mmiowb();
+}
+
+void bnx2x_int_enable(struct bnx2x *bp)
+{
+ if (bp->common.int_block == INT_BLOCK_HC)
+ bnx2x_hc_int_enable(bp);
+ else
+ bnx2x_igu_int_enable(bp);
+}
+
+static void bnx2x_hc_int_disable(struct bnx2x *bp)
{
int port = BP_PORT(bp);
u32 addr = port ? HC_REG_CONFIG_1 : HC_REG_CONFIG_0;
u32 val = REG_RD(bp, addr);
- val &= ~(HC_CONFIG_0_REG_SINGLE_ISR_EN_0 |
- HC_CONFIG_0_REG_MSI_MSIX_INT_EN_0 |
- HC_CONFIG_0_REG_INT_LINE_EN_0 |
- HC_CONFIG_0_REG_ATTN_BIT_EN_0);
+ /*
+ * in E1 we must use only PCI configuration space to disable
+ * MSI/MSIX capablility
+ * It's forbitten to disable IGU_PF_CONF_MSI_MSIX_EN in HC block
+ */
+ if (CHIP_IS_E1(bp)) {
+ /* Since IGU_PF_CONF_MSI_MSIX_EN still always on
+ * Use mask register to prevent from HC sending interrupts
+ * after we exit the function
+ */
+ REG_WR(bp, HC_REG_INT_MASK + port*4, 0);
+
+ val &= ~(HC_CONFIG_0_REG_SINGLE_ISR_EN_0 |
+ HC_CONFIG_0_REG_INT_LINE_EN_0 |
+ HC_CONFIG_0_REG_ATTN_BIT_EN_0);
+ } else
+ val &= ~(HC_CONFIG_0_REG_SINGLE_ISR_EN_0 |
+ HC_CONFIG_0_REG_MSI_MSIX_INT_EN_0 |
+ HC_CONFIG_0_REG_INT_LINE_EN_0 |
+ HC_CONFIG_0_REG_ATTN_BIT_EN_0);
DP(NETIF_MSG_INTR, "write %x to HC %d (addr 0x%x)\n",
val, port, addr);
@@ -730,6 +1249,32 @@ static void bnx2x_int_disable(struct bnx2x *bp)
BNX2X_ERR("BUG! proper val not read from IGU!\n");
}
+static void bnx2x_igu_int_disable(struct bnx2x *bp)
+{
+ u32 val = REG_RD(bp, IGU_REG_PF_CONFIGURATION);
+
+ val &= ~(IGU_PF_CONF_MSI_MSIX_EN |
+ IGU_PF_CONF_INT_LINE_EN |
+ IGU_PF_CONF_ATTN_BIT_EN);
+
+ DP(NETIF_MSG_INTR, "write %x to IGU\n", val);
+
+ /* flush all outstanding writes */
+ mmiowb();
+
+ REG_WR(bp, IGU_REG_PF_CONFIGURATION, val);
+ if (REG_RD(bp, IGU_REG_PF_CONFIGURATION) != val)
+ BNX2X_ERR("BUG! proper val not read from IGU!\n");
+}
+
+void bnx2x_int_disable(struct bnx2x *bp)
+{
+ if (bp->common.int_block == INT_BLOCK_HC)
+ bnx2x_hc_int_disable(bp);
+ else
+ bnx2x_igu_int_disable(bp);
+}
+
void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw)
{
int msix = (bp->flags & USING_MSIX_FLAG) ? 1 : 0;
@@ -781,7 +1326,7 @@ static bool bnx2x_trylock_hw_lock(struct bnx2x *bp, u32 resource)
DP(NETIF_MSG_HW,
"resource(0x%x) > HW_LOCK_MAX_RESOURCE_VALUE(0x%x)\n",
resource, HW_LOCK_MAX_RESOURCE_VALUE);
- return -EINVAL;
+ return false;
}
if (func <= 5)
@@ -800,7 +1345,6 @@ static bool bnx2x_trylock_hw_lock(struct bnx2x *bp, u32 resource)
return false;
}
-
#ifdef BCM_CNIC
static void bnx2x_cnic_cfc_comp(struct bnx2x *bp, int cid);
#endif
@@ -817,76 +1361,35 @@ void bnx2x_sp_event(struct bnx2x_fastpath *fp,
fp->index, cid, command, bp->state,
rr_cqe->ramrod_cqe.ramrod_type);
- bp->spq_left++;
-
- if (fp->index) {
- switch (command | fp->state) {
- case (RAMROD_CMD_ID_ETH_CLIENT_SETUP |
- BNX2X_FP_STATE_OPENING):
- DP(NETIF_MSG_IFUP, "got MULTI[%d] setup ramrod\n",
- cid);
- fp->state = BNX2X_FP_STATE_OPEN;
- break;
-
- case (RAMROD_CMD_ID_ETH_HALT | BNX2X_FP_STATE_HALTING):
- DP(NETIF_MSG_IFDOWN, "got MULTI[%d] halt ramrod\n",
- cid);
- fp->state = BNX2X_FP_STATE_HALTED;
- break;
-
- default:
- BNX2X_ERR("unexpected MC reply (%d) "
- "fp[%d] state is %x\n",
- command, fp->index, fp->state);
- break;
- }
- mb(); /* force bnx2x_wait_ramrod() to see the change */
- return;
- }
-
- switch (command | bp->state) {
- case (RAMROD_CMD_ID_ETH_PORT_SETUP | BNX2X_STATE_OPENING_WAIT4_PORT):
- DP(NETIF_MSG_IFUP, "got setup ramrod\n");
- bp->state = BNX2X_STATE_OPEN;
+ switch (command | fp->state) {
+ case (RAMROD_CMD_ID_ETH_CLIENT_SETUP | BNX2X_FP_STATE_OPENING):
+ DP(NETIF_MSG_IFUP, "got MULTI[%d] setup ramrod\n", cid);
+ fp->state = BNX2X_FP_STATE_OPEN;
break;
- case (RAMROD_CMD_ID_ETH_HALT | BNX2X_STATE_CLOSING_WAIT4_HALT):
- DP(NETIF_MSG_IFDOWN, "got halt ramrod\n");
- bp->state = BNX2X_STATE_CLOSING_WAIT4_DELETE;
+ case (RAMROD_CMD_ID_ETH_HALT | BNX2X_FP_STATE_HALTING):
+ DP(NETIF_MSG_IFDOWN, "got MULTI[%d] halt ramrod\n", cid);
fp->state = BNX2X_FP_STATE_HALTED;
break;
- case (RAMROD_CMD_ID_ETH_CFC_DEL | BNX2X_STATE_CLOSING_WAIT4_HALT):
- DP(NETIF_MSG_IFDOWN, "got delete ramrod for MULTI[%d]\n", cid);
- bnx2x_fp(bp, cid, state) = BNX2X_FP_STATE_CLOSED;
- break;
-
-#ifdef BCM_CNIC
- case (RAMROD_CMD_ID_ETH_CFC_DEL | BNX2X_STATE_OPEN):
- DP(NETIF_MSG_IFDOWN, "got delete ramrod for CID %d\n", cid);
- bnx2x_cnic_cfc_comp(bp, cid);
- break;
-#endif
-
- case (RAMROD_CMD_ID_ETH_SET_MAC | BNX2X_STATE_OPEN):
- case (RAMROD_CMD_ID_ETH_SET_MAC | BNX2X_STATE_DIAG):
- DP(NETIF_MSG_IFUP, "got set mac ramrod\n");
- bp->set_mac_pending--;
- smp_wmb();
- break;
-
- case (RAMROD_CMD_ID_ETH_SET_MAC | BNX2X_STATE_CLOSING_WAIT4_HALT):
- DP(NETIF_MSG_IFDOWN, "got (un)set mac ramrod\n");
- bp->set_mac_pending--;
- smp_wmb();
+ case (RAMROD_CMD_ID_ETH_TERMINATE | BNX2X_FP_STATE_TERMINATING):
+ DP(NETIF_MSG_IFDOWN, "got MULTI[%d] teminate ramrod\n", cid);
+ fp->state = BNX2X_FP_STATE_TERMINATED;
break;
default:
- BNX2X_ERR("unexpected MC reply (%d) bp->state is %x\n",
- command, bp->state);
+ BNX2X_ERR("unexpected MC reply (%d) "
+ "fp[%d] state is %x\n",
+ command, fp->index, fp->state);
break;
}
- mb(); /* force bnx2x_wait_ramrod() to see the change */
+
+ smp_mb__before_atomic_inc();
+ atomic_inc(&bp->spq_left);
+ /* push the change in fp->state and towards the memory */
+ smp_wmb();
+
+ return;
}
irqreturn_t bnx2x_interrupt(int irq, void *dev_instance)
@@ -914,25 +1417,22 @@ irqreturn_t bnx2x_interrupt(int irq, void *dev_instance)
return IRQ_HANDLED;
#endif
- for (i = 0; i < BNX2X_NUM_QUEUES(bp); i++) {
+ for_each_queue(bp, i) {
struct bnx2x_fastpath *fp = &bp->fp[i];
- mask = 0x2 << fp->sb_id;
+ mask = 0x2 << (fp->index + CNIC_CONTEXT_USE);
if (status & mask) {
/* Handle Rx and Tx according to SB id */
prefetch(fp->rx_cons_sb);
- prefetch(&fp->status_blk->u_status_block.
- status_block_index);
prefetch(fp->tx_cons_sb);
- prefetch(&fp->status_blk->c_status_block.
- status_block_index);
+ prefetch(&fp->sb_running_index[SM_RX_ID]);
napi_schedule(&bnx2x_fp(bp, fp->index, napi));
status &= ~mask;
}
}
#ifdef BCM_CNIC
- mask = 0x2 << CNIC_SB_ID(bp);
+ mask = 0x2;
if (status & (mask | 0x1)) {
struct cnic_ops *c_ops = NULL;
@@ -1227,49 +1727,91 @@ static int bnx2x_set_spio(struct bnx2x *bp, int spio_num, u32 mode)
return 0;
}
+int bnx2x_get_link_cfg_idx(struct bnx2x *bp)
+{
+ u32 sel_phy_idx = 0;
+ if (bp->link_vars.link_up) {
+ sel_phy_idx = EXT_PHY1;
+ /* In case link is SERDES, check if the EXT_PHY2 is the one */
+ if ((bp->link_vars.link_status & LINK_STATUS_SERDES_LINK) &&
+ (bp->link_params.phy[EXT_PHY2].supported & SUPPORTED_FIBRE))
+ sel_phy_idx = EXT_PHY2;
+ } else {
+
+ switch (bnx2x_phy_selection(&bp->link_params)) {
+ case PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT:
+ case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY:
+ case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY:
+ sel_phy_idx = EXT_PHY1;
+ break;
+ case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY:
+ case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY:
+ sel_phy_idx = EXT_PHY2;
+ break;
+ }
+ }
+ /*
+ * The selected actived PHY is always after swapping (in case PHY
+ * swapping is enabled). So when swapping is enabled, we need to reverse
+ * the configuration
+ */
+
+ if (bp->link_params.multi_phy_config &
+ PORT_HW_CFG_PHY_SWAPPED_ENABLED) {
+ if (sel_phy_idx == EXT_PHY1)
+ sel_phy_idx = EXT_PHY2;
+ else if (sel_phy_idx == EXT_PHY2)
+ sel_phy_idx = EXT_PHY1;
+ }
+ return LINK_CONFIG_IDX(sel_phy_idx);
+}
+
void bnx2x_calc_fc_adv(struct bnx2x *bp)
{
+ u8 cfg_idx = bnx2x_get_link_cfg_idx(bp);
switch (bp->link_vars.ieee_fc &
MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK) {
case MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE:
- bp->port.advertising &= ~(ADVERTISED_Asym_Pause |
- ADVERTISED_Pause);
+ bp->port.advertising[cfg_idx] &= ~(ADVERTISED_Asym_Pause |
+ ADVERTISED_Pause);
break;
case MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH:
- bp->port.advertising |= (ADVERTISED_Asym_Pause |
- ADVERTISED_Pause);
+ bp->port.advertising[cfg_idx] |= (ADVERTISED_Asym_Pause |
+ ADVERTISED_Pause);
break;
case MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC:
- bp->port.advertising |= ADVERTISED_Asym_Pause;
+ bp->port.advertising[cfg_idx] |= ADVERTISED_Asym_Pause;
break;
default:
- bp->port.advertising &= ~(ADVERTISED_Asym_Pause |
- ADVERTISED_Pause);
+ bp->port.advertising[cfg_idx] &= ~(ADVERTISED_Asym_Pause |
+ ADVERTISED_Pause);
break;
}
}
-
u8 bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode)
{
if (!BP_NOMCP(bp)) {
u8 rc;
-
+ int cfx_idx = bnx2x_get_link_cfg_idx(bp);
+ u16 req_line_speed = bp->link_params.req_line_speed[cfx_idx];
/* Initialize link parameters structure variables */
/* It is recommended to turn off RX FC for jumbo frames
for better performance */
- if (bp->dev->mtu > 5000)
+ if ((CHIP_IS_E1x(bp)) && (bp->dev->mtu > 5000))
bp->link_params.req_fc_auto_adv = BNX2X_FLOW_CTRL_TX;
else
bp->link_params.req_fc_auto_adv = BNX2X_FLOW_CTRL_BOTH;
bnx2x_acquire_phy_lock(bp);
- if (load_mode == LOAD_DIAG)
- bp->link_params.loopback_mode = LOOPBACK_XGXS_10;
+ if (load_mode == LOAD_DIAG) {
+ bp->link_params.loopback_mode = LOOPBACK_XGXS;
+ bp->link_params.req_line_speed[cfx_idx] = SPEED_10000;
+ }
rc = bnx2x_phy_init(&bp->link_params, &bp->link_vars);
@@ -1281,7 +1823,7 @@ u8 bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode)
bnx2x_stats_handle(bp, STATS_EVENT_LINK_UP);
bnx2x_link_report(bp);
}
-
+ bp->link_params.req_line_speed[cfx_idx] = req_line_speed;
return rc;
}
BNX2X_ERR("Bootcode is missing - can not initialize link\n");
@@ -1292,6 +1834,7 @@ void bnx2x_link_set(struct bnx2x *bp)
{
if (!BP_NOMCP(bp)) {
bnx2x_acquire_phy_lock(bp);
+ bnx2x_link_reset(&bp->link_params, &bp->link_vars, 1);
bnx2x_phy_init(&bp->link_params, &bp->link_vars);
bnx2x_release_phy_lock(bp);
@@ -1310,13 +1853,14 @@ static void bnx2x__link_reset(struct bnx2x *bp)
BNX2X_ERR("Bootcode is missing - can not reset link\n");
}
-u8 bnx2x_link_test(struct bnx2x *bp)
+u8 bnx2x_link_test(struct bnx2x *bp, u8 is_serdes)
{
u8 rc = 0;
if (!BP_NOMCP(bp)) {
bnx2x_acquire_phy_lock(bp);
- rc = bnx2x_test_link(&bp->link_params, &bp->link_vars);
+ rc = bnx2x_test_link(&bp->link_params, &bp->link_vars,
+ is_serdes);
bnx2x_release_phy_lock(bp);
} else
BNX2X_ERR("Bootcode is missing - can not test link\n");
@@ -1371,13 +1915,11 @@ static void bnx2x_init_port_minmax(struct bnx2x *bp)
static void bnx2x_calc_vn_weight_sum(struct bnx2x *bp)
{
int all_zero = 1;
- int port = BP_PORT(bp);
int vn;
bp->vn_weight_sum = 0;
for (vn = VN_0; vn < E1HVN_MAX; vn++) {
- int func = 2*vn + port;
- u32 vn_cfg = SHMEM_RD(bp, mf_cfg.func_mf_config[func].config);
+ u32 vn_cfg = bp->mf_config[vn];
u32 vn_min_rate = ((vn_cfg & FUNC_MF_CFG_MIN_BW_MASK) >>
FUNC_MF_CFG_MIN_BW_SHIFT) * 100;
@@ -1405,11 +1947,12 @@ static void bnx2x_calc_vn_weight_sum(struct bnx2x *bp)
CMNG_FLAGS_PER_PORT_FAIRNESS_VN;
}
-static void bnx2x_init_vn_minmax(struct bnx2x *bp, int func)
+static void bnx2x_init_vn_minmax(struct bnx2x *bp, int vn)
{
struct rate_shaping_vars_per_vn m_rs_vn;
struct fairness_vars_per_vn m_fair_vn;
- u32 vn_cfg = SHMEM_RD(bp, mf_cfg.func_mf_config[func].config);
+ u32 vn_cfg = bp->mf_config[vn];
+ int func = 2*vn + BP_PORT(bp);
u16 vn_min_rate, vn_max_rate;
int i;
@@ -1422,11 +1965,12 @@ static void bnx2x_init_vn_minmax(struct bnx2x *bp, int func)
vn_min_rate = ((vn_cfg & FUNC_MF_CFG_MIN_BW_MASK) >>
FUNC_MF_CFG_MIN_BW_SHIFT) * 100;
/* If min rate is zero - set it to 1 */
- if (!vn_min_rate)
+ if (bp->vn_weight_sum && (vn_min_rate == 0))
vn_min_rate = DEF_MIN_RATE;
vn_max_rate = ((vn_cfg & FUNC_MF_CFG_MAX_BW_MASK) >>
FUNC_MF_CFG_MAX_BW_SHIFT) * 100;
}
+
DP(NETIF_MSG_IFUP,
"func %d: vn_min_rate %d vn_max_rate %d vn_weight_sum %d\n",
func, vn_min_rate, vn_max_rate, bp->vn_weight_sum);
@@ -1467,6 +2011,83 @@ static void bnx2x_init_vn_minmax(struct bnx2x *bp, int func)
((u32 *)(&m_fair_vn))[i]);
}
+static int bnx2x_get_cmng_fns_mode(struct bnx2x *bp)
+{
+ if (CHIP_REV_IS_SLOW(bp))
+ return CMNG_FNS_NONE;
+ if (IS_MF(bp))
+ return CMNG_FNS_MINMAX;
+
+ return CMNG_FNS_NONE;
+}
+
+static void bnx2x_read_mf_cfg(struct bnx2x *bp)
+{
+ int vn;
+
+ if (BP_NOMCP(bp))
+ return; /* what should be the default bvalue in this case */
+
+ for (vn = VN_0; vn < E1HVN_MAX; vn++) {
+ int /*abs*/func = 2*vn + BP_PORT(bp);
+ bp->mf_config[vn] =
+ MF_CFG_RD(bp, func_mf_config[func].config);
+ }
+}
+
+static void bnx2x_cmng_fns_init(struct bnx2x *bp, u8 read_cfg, u8 cmng_type)
+{
+
+ if (cmng_type == CMNG_FNS_MINMAX) {
+ int vn;
+
+ /* clear cmng_enables */
+ bp->cmng.flags.cmng_enables = 0;
+
+ /* read mf conf from shmem */
+ if (read_cfg)
+ bnx2x_read_mf_cfg(bp);
+
+ /* Init rate shaping and fairness contexts */
+ bnx2x_init_port_minmax(bp);
+
+ /* vn_weight_sum and enable fairness if not 0 */
+ bnx2x_calc_vn_weight_sum(bp);
+
+ /* calculate and set min-max rate for each vn */
+ for (vn = VN_0; vn < E1HVN_MAX; vn++)
+ bnx2x_init_vn_minmax(bp, vn);
+
+ /* always enable rate shaping and fairness */
+ bp->cmng.flags.cmng_enables |=
+ CMNG_FLAGS_PER_PORT_RATE_SHAPING_VN;
+ if (!bp->vn_weight_sum)
+ DP(NETIF_MSG_IFUP, "All MIN values are zeroes"
+ " fairness will be disabled\n");
+ return;
+ }
+
+ /* rate shaping and fairness are disabled */
+ DP(NETIF_MSG_IFUP,
+ "rate shaping and fairness are disabled\n");
+}
+
+static inline void bnx2x_link_sync_notify(struct bnx2x *bp)
+{
+ int port = BP_PORT(bp);
+ int func;
+ int vn;
+
+ /* Set the attention towards other drivers on the same port */
+ for (vn = VN_0; vn < E1HVN_MAX; vn++) {
+ if (vn == BP_E1HVN(bp))
+ continue;
+
+ func = ((vn << 1) | port);
+ REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_0 +
+ (LINK_SYNC_ATTENTION_BIT_FUNC_0 + func)*4, 1);
+ }
+}
/* This function is called upon link interrupt */
static void bnx2x_link_attn(struct bnx2x *bp)
@@ -1480,7 +2101,7 @@ static void bnx2x_link_attn(struct bnx2x *bp)
if (bp->link_vars.link_up) {
/* dropless flow control */
- if (CHIP_IS_E1H(bp) && bp->dropless_fc) {
+ if (!CHIP_IS_E1(bp) && bp->dropless_fc) {
int port = BP_PORT(bp);
u32 pause_enabled = 0;
@@ -1508,37 +2129,19 @@ static void bnx2x_link_attn(struct bnx2x *bp)
if (prev_link_status != bp->link_vars.link_status)
bnx2x_link_report(bp);
- if (IS_E1HMF(bp)) {
- int port = BP_PORT(bp);
- int func;
- int vn;
-
- /* Set the attention towards other drivers on the same port */
- for (vn = VN_0; vn < E1HVN_MAX; vn++) {
- if (vn == BP_E1HVN(bp))
- continue;
+ if (IS_MF(bp))
+ bnx2x_link_sync_notify(bp);
- func = ((vn << 1) | port);
- REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_0 +
- (LINK_SYNC_ATTENTION_BIT_FUNC_0 + func)*4, 1);
- }
+ if (bp->link_vars.link_up && bp->link_vars.line_speed) {
+ int cmng_fns = bnx2x_get_cmng_fns_mode(bp);
- if (bp->link_vars.link_up) {
- int i;
-
- /* Init rate shaping and fairness contexts */
- bnx2x_init_port_minmax(bp);
-
- for (vn = VN_0; vn < E1HVN_MAX; vn++)
- bnx2x_init_vn_minmax(bp, 2*vn + port);
-
- /* Store it to internal memory */
- for (i = 0;
- i < sizeof(struct cmng_struct_per_port) / 4; i++)
- REG_WR(bp, BAR_XSTRORM_INTMEM +
- XSTORM_CMNG_PER_PORT_VARS_OFFSET(port) + i*4,
- ((u32 *)(&bp->cmng))[i]);
- }
+ if (cmng_fns != CMNG_FNS_NONE) {
+ bnx2x_cmng_fns_init(bp, false, cmng_fns);
+ storm_memset_cmng(bp, &bp->cmng, BP_PORT(bp));
+ } else
+ /* rate shaping and fairness are disabled */
+ DP(NETIF_MSG_IFUP,
+ "single function mode without fairness\n");
}
}
@@ -1554,7 +2157,9 @@ void bnx2x__link_status_update(struct bnx2x *bp)
else
bnx2x_stats_handle(bp, STATS_EVENT_STOP);
- bnx2x_calc_vn_weight_sum(bp);
+ /* the link status update could be the result of a DCC event
+ hence re-read the shmem mf configuration */
+ bnx2x_read_mf_cfg(bp);
/* indicate link status */
bnx2x_link_report(bp);
@@ -1570,8 +2175,13 @@ static void bnx2x_pmf_update(struct bnx2x *bp)
/* enable nig attention */
val = (0xff0f | (1 << (BP_E1HVN(bp) + 4)));
- REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, val);
- REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, val);
+ if (bp->common.int_block == INT_BLOCK_HC) {
+ REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, val);
+ REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, val);
+ } else if (CHIP_IS_E2(bp)) {
+ REG_WR(bp, IGU_REG_TRAILING_EDGE_LATCH, val);
+ REG_WR(bp, IGU_REG_LEADING_EDGE_LATCH, val);
+ }
bnx2x_stats_handle(bp, STATS_EVENT_PMF);
}
@@ -1585,23 +2195,25 @@ static void bnx2x_pmf_update(struct bnx2x *bp)
*/
/* send the MCP a request, block until there is a reply */
-u32 bnx2x_fw_command(struct bnx2x *bp, u32 command)
+u32 bnx2x_fw_command(struct bnx2x *bp, u32 command, u32 param)
{
- int func = BP_FUNC(bp);
+ int mb_idx = BP_FW_MB_IDX(bp);
u32 seq = ++bp->fw_seq;
u32 rc = 0;
u32 cnt = 1;
u8 delay = CHIP_REV_IS_SLOW(bp) ? 100 : 10;
mutex_lock(&bp->fw_mb_mutex);
- SHMEM_WR(bp, func_mb[func].drv_mb_header, (command | seq));
+ SHMEM_WR(bp, func_mb[mb_idx].drv_mb_param, param);
+ SHMEM_WR(bp, func_mb[mb_idx].drv_mb_header, (command | seq));
+
DP(BNX2X_MSG_MCP, "wrote command (%x) to FW MB\n", (command | seq));
do {
/* let the FW do it's magic ... */
msleep(delay);
- rc = SHMEM_RD(bp, func_mb[func].fw_mb_header);
+ rc = SHMEM_RD(bp, func_mb[mb_idx].fw_mb_header);
/* Give the FW up to 5 second (500*10ms) */
} while ((seq != (rc & FW_MSG_SEQ_NUMBER_MASK)) && (cnt++ < 500));
@@ -1623,6 +2235,315 @@ u32 bnx2x_fw_command(struct bnx2x *bp, u32 command)
return rc;
}
+/* must be called under rtnl_lock */
+void bnx2x_rxq_set_mac_filters(struct bnx2x *bp, u16 cl_id, u32 filters)
+{
+ u32 mask = (1 << cl_id);
+
+ /* initial seeting is BNX2X_ACCEPT_NONE */
+ u8 drop_all_ucast = 1, drop_all_bcast = 1, drop_all_mcast = 1;
+ u8 accp_all_ucast = 0, accp_all_bcast = 0, accp_all_mcast = 0;
+ u8 unmatched_unicast = 0;
+
+ if (filters & BNX2X_PROMISCUOUS_MODE) {
+ /* promiscious - accept all, drop none */
+ drop_all_ucast = drop_all_bcast = drop_all_mcast = 0;
+ accp_all_ucast = accp_all_bcast = accp_all_mcast = 1;
+ }
+ if (filters & BNX2X_ACCEPT_UNICAST) {
+ /* accept matched ucast */
+ drop_all_ucast = 0;
+ }
+ if (filters & BNX2X_ACCEPT_MULTICAST) {
+ /* accept matched mcast */
+ drop_all_mcast = 0;
+ }
+ if (filters & BNX2X_ACCEPT_ALL_UNICAST) {
+ /* accept all mcast */
+ drop_all_ucast = 0;
+ accp_all_ucast = 1;
+ }
+ if (filters & BNX2X_ACCEPT_ALL_MULTICAST) {
+ /* accept all mcast */
+ drop_all_mcast = 0;
+ accp_all_mcast = 1;
+ }
+ if (filters & BNX2X_ACCEPT_BROADCAST) {
+ /* accept (all) bcast */
+ drop_all_bcast = 0;
+ accp_all_bcast = 1;
+ }
+
+ bp->mac_filters.ucast_drop_all = drop_all_ucast ?
+ bp->mac_filters.ucast_drop_all | mask :
+ bp->mac_filters.ucast_drop_all & ~mask;
+
+ bp->mac_filters.mcast_drop_all = drop_all_mcast ?
+ bp->mac_filters.mcast_drop_all | mask :
+ bp->mac_filters.mcast_drop_all & ~mask;
+
+ bp->mac_filters.bcast_drop_all = drop_all_bcast ?
+ bp->mac_filters.bcast_drop_all | mask :
+ bp->mac_filters.bcast_drop_all & ~mask;
+
+ bp->mac_filters.ucast_accept_all = accp_all_ucast ?
+ bp->mac_filters.ucast_accept_all | mask :
+ bp->mac_filters.ucast_accept_all & ~mask;
+
+ bp->mac_filters.mcast_accept_all = accp_all_mcast ?
+ bp->mac_filters.mcast_accept_all | mask :
+ bp->mac_filters.mcast_accept_all & ~mask;
+
+ bp->mac_filters.bcast_accept_all = accp_all_bcast ?
+ bp->mac_filters.bcast_accept_all | mask :
+ bp->mac_filters.bcast_accept_all & ~mask;
+
+ bp->mac_filters.unmatched_unicast = unmatched_unicast ?
+ bp->mac_filters.unmatched_unicast | mask :
+ bp->mac_filters.unmatched_unicast & ~mask;
+}
+
+void bnx2x_func_init(struct bnx2x *bp, struct bnx2x_func_init_params *p)
+{
+ struct tstorm_eth_function_common_config tcfg = {0};
+ u16 rss_flgs;
+
+ /* tpa */
+ if (p->func_flgs & FUNC_FLG_TPA)
+ tcfg.config_flags |=
+ TSTORM_ETH_FUNCTION_COMMON_CONFIG_ENABLE_TPA;
+
+ /* set rss flags */
+ rss_flgs = (p->rss->mode <<
+ TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_MODE_SHIFT);
+
+ if (p->rss->cap & RSS_IPV4_CAP)
+ rss_flgs |= RSS_IPV4_CAP_MASK;
+ if (p->rss->cap & RSS_IPV4_TCP_CAP)
+ rss_flgs |= RSS_IPV4_TCP_CAP_MASK;
+ if (p->rss->cap & RSS_IPV6_CAP)
+ rss_flgs |= RSS_IPV6_CAP_MASK;
+ if (p->rss->cap & RSS_IPV6_TCP_CAP)
+ rss_flgs |= RSS_IPV6_TCP_CAP_MASK;
+
+ tcfg.config_flags |= rss_flgs;
+ tcfg.rss_result_mask = p->rss->result_mask;
+
+ storm_memset_func_cfg(bp, &tcfg, p->func_id);
+
+ /* Enable the function in the FW */
+ storm_memset_vf_to_pf(bp, p->func_id, p->pf_id);
+ storm_memset_func_en(bp, p->func_id, 1);
+
+ /* statistics */
+ if (p->func_flgs & FUNC_FLG_STATS) {
+ struct stats_indication_flags stats_flags = {0};
+ stats_flags.collect_eth = 1;
+
+ storm_memset_xstats_flags(bp, &stats_flags, p->func_id);
+ storm_memset_xstats_addr(bp, p->fw_stat_map, p->func_id);
+
+ storm_memset_tstats_flags(bp, &stats_flags, p->func_id);
+ storm_memset_tstats_addr(bp, p->fw_stat_map, p->func_id);
+
+ storm_memset_ustats_flags(bp, &stats_flags, p->func_id);
+ storm_memset_ustats_addr(bp, p->fw_stat_map, p->func_id);
+
+ storm_memset_cstats_flags(bp, &stats_flags, p->func_id);
+ storm_memset_cstats_addr(bp, p->fw_stat_map, p->func_id);
+ }
+
+ /* spq */
+ if (p->func_flgs & FUNC_FLG_SPQ) {
+ storm_memset_spq_addr(bp, p->spq_map, p->func_id);
+ REG_WR(bp, XSEM_REG_FAST_MEMORY +
+ XSTORM_SPQ_PROD_OFFSET(p->func_id), p->spq_prod);
+ }
+}
+
+static inline u16 bnx2x_get_cl_flags(struct bnx2x *bp,
+ struct bnx2x_fastpath *fp)
+{
+ u16 flags = 0;
+
+ /* calculate queue flags */
+ flags |= QUEUE_FLG_CACHE_ALIGN;
+ flags |= QUEUE_FLG_HC;
+ flags |= IS_MF(bp) ? QUEUE_FLG_OV : 0;
+
+ flags |= QUEUE_FLG_VLAN;
+ DP(NETIF_MSG_IFUP, "vlan removal enabled\n");
+
+ if (!fp->disable_tpa)
+ flags |= QUEUE_FLG_TPA;
+
+ flags |= QUEUE_FLG_STATS;
+
+ return flags;
+}
+
+static void bnx2x_pf_rx_cl_prep(struct bnx2x *bp,
+ struct bnx2x_fastpath *fp, struct rxq_pause_params *pause,
+ struct bnx2x_rxq_init_params *rxq_init)
+{
+ u16 max_sge = 0;
+ u16 sge_sz = 0;
+ u16 tpa_agg_size = 0;
+
+ /* calculate queue flags */
+ u16 flags = bnx2x_get_cl_flags(bp, fp);
+
+ if (!fp->disable_tpa) {
+ pause->sge_th_hi = 250;
+ pause->sge_th_lo = 150;
+ tpa_agg_size = min_t(u32,
+ (min_t(u32, 8, MAX_SKB_FRAGS) *
+ SGE_PAGE_SIZE * PAGES_PER_SGE), 0xffff);
+ max_sge = SGE_PAGE_ALIGN(bp->dev->mtu) >>
+ SGE_PAGE_SHIFT;
+ max_sge = ((max_sge + PAGES_PER_SGE - 1) &
+ (~(PAGES_PER_SGE-1))) >> PAGES_PER_SGE_SHIFT;
+ sge_sz = (u16)min_t(u32, SGE_PAGE_SIZE * PAGES_PER_SGE,
+ 0xffff);
+ }
+
+ /* pause - not for e1 */
+ if (!CHIP_IS_E1(bp)) {
+ pause->bd_th_hi = 350;
+ pause->bd_th_lo = 250;
+ pause->rcq_th_hi = 350;
+ pause->rcq_th_lo = 250;
+ pause->sge_th_hi = 0;
+ pause->sge_th_lo = 0;
+ pause->pri_map = 1;
+ }
+
+ /* rxq setup */
+ rxq_init->flags = flags;
+ rxq_init->cxt = &bp->context.vcxt[fp->cid].eth;
+ rxq_init->dscr_map = fp->rx_desc_mapping;
+ rxq_init->sge_map = fp->rx_sge_mapping;
+ rxq_init->rcq_map = fp->rx_comp_mapping;
+ rxq_init->rcq_np_map = fp->rx_comp_mapping + BCM_PAGE_SIZE;
+ rxq_init->mtu = bp->dev->mtu;
+ rxq_init->buf_sz = bp->rx_buf_size;
+ rxq_init->cl_qzone_id = fp->cl_qzone_id;
+ rxq_init->cl_id = fp->cl_id;
+ rxq_init->spcl_id = fp->cl_id;
+ rxq_init->stat_id = fp->cl_id;
+ rxq_init->tpa_agg_sz = tpa_agg_size;
+ rxq_init->sge_buf_sz = sge_sz;
+ rxq_init->max_sges_pkt = max_sge;
+ rxq_init->cache_line_log = BNX2X_RX_ALIGN_SHIFT;
+ rxq_init->fw_sb_id = fp->fw_sb_id;
+
+ rxq_init->sb_cq_index = U_SB_ETH_RX_CQ_INDEX;
+
+ rxq_init->cid = HW_CID(bp, fp->cid);
+
+ rxq_init->hc_rate = bp->rx_ticks ? (1000000 / bp->rx_ticks) : 0;
+}
+
+static void bnx2x_pf_tx_cl_prep(struct bnx2x *bp,
+ struct bnx2x_fastpath *fp, struct bnx2x_txq_init_params *txq_init)
+{
+ u16 flags = bnx2x_get_cl_flags(bp, fp);
+
+ txq_init->flags = flags;
+ txq_init->cxt = &bp->context.vcxt[fp->cid].eth;
+ txq_init->dscr_map = fp->tx_desc_mapping;
+ txq_init->stat_id = fp->cl_id;
+ txq_init->cid = HW_CID(bp, fp->cid);
+ txq_init->sb_cq_index = C_SB_ETH_TX_CQ_INDEX;
+ txq_init->traffic_type = LLFC_TRAFFIC_TYPE_NW;
+ txq_init->fw_sb_id = fp->fw_sb_id;
+ txq_init->hc_rate = bp->tx_ticks ? (1000000 / bp->tx_ticks) : 0;
+}
+
+void bnx2x_pf_init(struct bnx2x *bp)
+{
+ struct bnx2x_func_init_params func_init = {0};
+ struct bnx2x_rss_params rss = {0};
+ struct event_ring_data eq_data = { {0} };
+ u16 flags;
+
+ /* pf specific setups */
+ if (!CHIP_IS_E1(bp))
+ storm_memset_ov(bp, bp->mf_ov, BP_FUNC(bp));
+
+ if (CHIP_IS_E2(bp)) {
+ /* reset IGU PF statistics: MSIX + ATTN */
+ /* PF */
+ REG_WR(bp, IGU_REG_STATISTIC_NUM_MESSAGE_SENT +
+ BNX2X_IGU_STAS_MSG_VF_CNT*4 +
+ (CHIP_MODE_IS_4_PORT(bp) ?
+ BP_FUNC(bp) : BP_VN(bp))*4, 0);
+ /* ATTN */
+ REG_WR(bp, IGU_REG_STATISTIC_NUM_MESSAGE_SENT +
+ BNX2X_IGU_STAS_MSG_VF_CNT*4 +
+ BNX2X_IGU_STAS_MSG_PF_CNT*4 +
+ (CHIP_MODE_IS_4_PORT(bp) ?
+ BP_FUNC(bp) : BP_VN(bp))*4, 0);
+ }
+
+ /* function setup flags */
+ flags = (FUNC_FLG_STATS | FUNC_FLG_LEADING | FUNC_FLG_SPQ);
+
+ if (CHIP_IS_E1x(bp))
+ flags |= (bp->flags & TPA_ENABLE_FLAG) ? FUNC_FLG_TPA : 0;
+ else
+ flags |= FUNC_FLG_TPA;
+
+ /* function setup */
+
+ /**
+ * Although RSS is meaningless when there is a single HW queue we
+ * still need it enabled in order to have HW Rx hash generated.
+ */
+ rss.cap = (RSS_IPV4_CAP | RSS_IPV4_TCP_CAP |
+ RSS_IPV6_CAP | RSS_IPV6_TCP_CAP);
+ rss.mode = bp->multi_mode;
+ rss.result_mask = MULTI_MASK;
+ func_init.rss = &rss;
+
+ func_init.func_flgs = flags;
+ func_init.pf_id = BP_FUNC(bp);
+ func_init.func_id = BP_FUNC(bp);
+ func_init.fw_stat_map = bnx2x_sp_mapping(bp, fw_stats);
+ func_init.spq_map = bp->spq_mapping;
+ func_init.spq_prod = bp->spq_prod_idx;
+
+ bnx2x_func_init(bp, &func_init);
+
+ memset(&(bp->cmng), 0, sizeof(struct cmng_struct_per_port));
+
+ /*
+ Congestion management values depend on the link rate
+ There is no active link so initial link rate is set to 10 Gbps.
+ When the link comes up The congestion management values are
+ re-calculated according to the actual link rate.
+ */
+ bp->link_vars.line_speed = SPEED_10000;
+ bnx2x_cmng_fns_init(bp, true, bnx2x_get_cmng_fns_mode(bp));
+
+ /* Only the PMF sets the HW */
+ if (bp->port.pmf)
+ storm_memset_cmng(bp, &bp->cmng, BP_PORT(bp));
+
+ /* no rx until link is up */
+ bp->rx_mode = BNX2X_RX_MODE_NONE;
+ bnx2x_set_storm_rx_mode(bp);
+
+ /* init Event Queue */
+ eq_data.base_addr.hi = U64_HI(bp->eq_mapping);
+ eq_data.base_addr.lo = U64_LO(bp->eq_mapping);
+ eq_data.producer = bp->eq_prod;
+ eq_data.index_id = HC_SP_INDEX_EQ_CONS;
+ eq_data.sb_id = DEF_SB_ID;
+ storm_memset_eq_data(bp, &eq_data, BP_FUNC(bp));
+}
+
+
static void bnx2x_e1h_disable(struct bnx2x *bp)
{
int port = BP_PORT(bp);
@@ -1649,40 +2570,6 @@ static void bnx2x_e1h_enable(struct bnx2x *bp)
*/
}
-static void bnx2x_update_min_max(struct bnx2x *bp)
-{
- int port = BP_PORT(bp);
- int vn, i;
-
- /* Init rate shaping and fairness contexts */
- bnx2x_init_port_minmax(bp);
-
- bnx2x_calc_vn_weight_sum(bp);
-
- for (vn = VN_0; vn < E1HVN_MAX; vn++)
- bnx2x_init_vn_minmax(bp, 2*vn + port);
-
- if (bp->port.pmf) {
- int func;
-
- /* Set the attention towards other drivers on the same port */
- for (vn = VN_0; vn < E1HVN_MAX; vn++) {
- if (vn == BP_E1HVN(bp))
- continue;
-
- func = ((vn << 1) | port);
- REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_0 +
- (LINK_SYNC_ATTENTION_BIT_FUNC_0 + func)*4, 1);
- }
-
- /* Store it to internal memory */
- for (i = 0; i < sizeof(struct cmng_struct_per_port) / 4; i++)
- REG_WR(bp, BAR_XSTRORM_INTMEM +
- XSTORM_CMNG_PER_PORT_VARS_OFFSET(port) + i*4,
- ((u32 *)(&bp->cmng))[i]);
- }
-}
-
static void bnx2x_dcc_event(struct bnx2x *bp, u32 dcc_event)
{
DP(BNX2X_MSG_MCP, "dcc_event 0x%x\n", dcc_event);
@@ -1694,7 +2581,7 @@ static void bnx2x_dcc_event(struct bnx2x *bp, u32 dcc_event)
* where the bp->flags can change so it is done without any
* locks
*/
- if (bp->mf_config & FUNC_MF_CFG_FUNC_DISABLED) {
+ if (bp->mf_config[BP_VN(bp)] & FUNC_MF_CFG_FUNC_DISABLED) {
DP(NETIF_MSG_IFDOWN, "mf_cfg function disabled\n");
bp->flags |= MF_FUNC_DIS;
@@ -1709,15 +2596,17 @@ static void bnx2x_dcc_event(struct bnx2x *bp, u32 dcc_event)
}
if (dcc_event & DRV_STATUS_DCC_BANDWIDTH_ALLOCATION) {
- bnx2x_update_min_max(bp);
+ bnx2x_cmng_fns_init(bp, true, CMNG_FNS_MINMAX);
+ bnx2x_link_sync_notify(bp);
+ storm_memset_cmng(bp, &bp->cmng, BP_PORT(bp));
dcc_event &= ~DRV_STATUS_DCC_BANDWIDTH_ALLOCATION;
}
/* Report results to MCP */
if (dcc_event)
- bnx2x_fw_command(bp, DRV_MSG_CODE_DCC_FAILURE);
+ bnx2x_fw_command(bp, DRV_MSG_CODE_DCC_FAILURE, 0);
else
- bnx2x_fw_command(bp, DRV_MSG_CODE_DCC_OK);
+ bnx2x_fw_command(bp, DRV_MSG_CODE_DCC_OK, 0);
}
/* must be called under the spq lock */
@@ -1744,16 +2633,17 @@ static inline void bnx2x_sp_prod_update(struct bnx2x *bp)
/* Make sure that BD data is updated before writing the producer */
wmb();
- REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_SPQ_PROD_OFFSET(func),
- bp->spq_prod_idx);
+ REG_WR16(bp, BAR_XSTRORM_INTMEM + XSTORM_SPQ_PROD_OFFSET(func),
+ bp->spq_prod_idx);
mmiowb();
}
/* the slow path queue is odd since completions arrive on the fastpath ring */
int bnx2x_sp_post(struct bnx2x *bp, int command, int cid,
- u32 data_hi, u32 data_lo, int common)
+ u32 data_hi, u32 data_lo, int common)
{
struct eth_spe *spe;
+ u16 type;
#ifdef BNX2X_STOP_ON_ERROR
if (unlikely(bp->panic))
@@ -1762,7 +2652,7 @@ int bnx2x_sp_post(struct bnx2x *bp, int command, int cid,
spin_lock_bh(&bp->spq_lock);
- if (!bp->spq_left) {
+ if (!atomic_read(&bp->spq_left)) {
BNX2X_ERR("BUG! SPQ ring full!\n");
spin_unlock_bh(&bp->spq_lock);
bnx2x_panic();
@@ -1775,22 +2665,42 @@ int bnx2x_sp_post(struct bnx2x *bp, int command, int cid,
spe->hdr.conn_and_cmd_data =
cpu_to_le32((command << SPE_HDR_CMD_ID_SHIFT) |
HW_CID(bp, cid));
- spe->hdr.type = cpu_to_le16(ETH_CONNECTION_TYPE);
+
if (common)
- spe->hdr.type |=
- cpu_to_le16((1 << SPE_HDR_COMMON_RAMROD_SHIFT));
+ /* Common ramrods:
+ * FUNC_START, FUNC_STOP, CFC_DEL, STATS, SET_MAC
+ * TRAFFIC_STOP, TRAFFIC_START
+ */
+ type = (NONE_CONNECTION_TYPE << SPE_HDR_CONN_TYPE_SHIFT)
+ & SPE_HDR_CONN_TYPE;
+ else
+ /* ETH ramrods: SETUP, HALT */
+ type = (ETH_CONNECTION_TYPE << SPE_HDR_CONN_TYPE_SHIFT)
+ & SPE_HDR_CONN_TYPE;
- spe->data.mac_config_addr.hi = cpu_to_le32(data_hi);
- spe->data.mac_config_addr.lo = cpu_to_le32(data_lo);
+ type |= ((BP_FUNC(bp) << SPE_HDR_FUNCTION_ID_SHIFT) &
+ SPE_HDR_FUNCTION_ID);
- bp->spq_left--;
+ spe->hdr.type = cpu_to_le16(type);
+
+ spe->data.update_data_addr.hi = cpu_to_le32(data_hi);
+ spe->data.update_data_addr.lo = cpu_to_le32(data_lo);
+
+ /* stats ramrod has it's own slot on the spq */
+ if (command != RAMROD_CMD_ID_COMMON_STAT_QUERY)
+ /* It's ok if the actual decrement is issued towards the memory
+ * somewhere between the spin_lock and spin_unlock. Thus no
+ * more explict memory barrier is needed.
+ */
+ atomic_dec(&bp->spq_left);
DP(BNX2X_MSG_SP/*NETIF_MSG_TIMER*/,
- "SPQE[%x] (%x:%x) command %d hw_cid %x data (%x:%x) left %x\n",
+ "SPQE[%x] (%x:%x) command %d hw_cid %x data (%x:%x) "
+ "type(0x%x) left %x\n",
bp->spq_prod_idx, (u32)U64_HI(bp->spq_mapping),
(u32)(U64_LO(bp->spq_mapping) +
(void *)bp->spq_prod_bd - (void *)bp->spq), command,
- HW_CID(bp, cid), data_hi, data_lo, bp->spq_left);
+ HW_CID(bp, cid), data_hi, data_lo, type, atomic_read(&bp->spq_left));
bnx2x_sp_prod_update(bp);
spin_unlock_bh(&bp->spq_lock);
@@ -1827,32 +2737,27 @@ static void bnx2x_release_alr(struct bnx2x *bp)
REG_WR(bp, GRCBASE_MCP + 0x9c, 0);
}
+#define BNX2X_DEF_SB_ATT_IDX 0x0001
+#define BNX2X_DEF_SB_IDX 0x0002
+
static inline u16 bnx2x_update_dsb_idx(struct bnx2x *bp)
{
- struct host_def_status_block *def_sb = bp->def_status_blk;
+ struct host_sp_status_block *def_sb = bp->def_status_blk;
u16 rc = 0;
barrier(); /* status block is written to by the chip */
if (bp->def_att_idx != def_sb->atten_status_block.attn_bits_index) {
bp->def_att_idx = def_sb->atten_status_block.attn_bits_index;
- rc |= 1;
- }
- if (bp->def_c_idx != def_sb->c_def_status_block.status_block_index) {
- bp->def_c_idx = def_sb->c_def_status_block.status_block_index;
- rc |= 2;
- }
- if (bp->def_u_idx != def_sb->u_def_status_block.status_block_index) {
- bp->def_u_idx = def_sb->u_def_status_block.status_block_index;
- rc |= 4;
+ rc |= BNX2X_DEF_SB_ATT_IDX;
}
- if (bp->def_x_idx != def_sb->x_def_status_block.status_block_index) {
- bp->def_x_idx = def_sb->x_def_status_block.status_block_index;
- rc |= 8;
- }
- if (bp->def_t_idx != def_sb->t_def_status_block.status_block_index) {
- bp->def_t_idx = def_sb->t_def_status_block.status_block_index;
- rc |= 16;
+
+ if (bp->def_idx != def_sb->sp_sb.running_index) {
+ bp->def_idx = def_sb->sp_sb.running_index;
+ rc |= BNX2X_DEF_SB_IDX;
}
+
+ /* Do not reorder: indecies reading should complete before handling */
+ barrier();
return rc;
}
@@ -1863,14 +2768,13 @@ static inline u16 bnx2x_update_dsb_idx(struct bnx2x *bp)
static void bnx2x_attn_int_asserted(struct bnx2x *bp, u32 asserted)
{
int port = BP_PORT(bp);
- u32 hc_addr = (HC_REG_COMMAND_REG + port*32 +
- COMMAND_REG_ATTN_BITS_SET);
u32 aeu_addr = port ? MISC_REG_AEU_MASK_ATTN_FUNC_1 :
MISC_REG_AEU_MASK_ATTN_FUNC_0;
u32 nig_int_mask_addr = port ? NIG_REG_MASK_INTERRUPT_PORT1 :
NIG_REG_MASK_INTERRUPT_PORT0;
u32 aeu_mask;
u32 nig_mask = 0;
+ u32 reg_addr;
if (bp->attn_state & asserted)
BNX2X_ERR("IGU ERROR\n");
@@ -1945,9 +2849,15 @@ static void bnx2x_attn_int_asserted(struct bnx2x *bp, u32 asserted)
} /* if hardwired */
- DP(NETIF_MSG_HW, "about to mask 0x%08x at HC addr 0x%x\n",
- asserted, hc_addr);
- REG_WR(bp, hc_addr, asserted);
+ if (bp->common.int_block == INT_BLOCK_HC)
+ reg_addr = (HC_REG_COMMAND_REG + port*32 +
+ COMMAND_REG_ATTN_BITS_SET);
+ else
+ reg_addr = (BAR_IGU_INTMEM + IGU_CMD_ATTN_BIT_SET_UPPER*8);
+
+ DP(NETIF_MSG_HW, "about to mask 0x%08x at %s addr 0x%x\n", asserted,
+ (bp->common.int_block == INT_BLOCK_HC) ? "HC" : "IGU", reg_addr);
+ REG_WR(bp, reg_addr, asserted);
/* now set back the mask */
if (asserted & ATTN_NIG_FOR_FUNC) {
@@ -1959,12 +2869,16 @@ static void bnx2x_attn_int_asserted(struct bnx2x *bp, u32 asserted)
static inline void bnx2x_fan_failure(struct bnx2x *bp)
{
int port = BP_PORT(bp);
-
+ u32 ext_phy_config;
/* mark the failure */
- bp->link_params.ext_phy_config &= ~PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK;
- bp->link_params.ext_phy_config |= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE;
+ ext_phy_config =
+ SHMEM_RD(bp,
+ dev_info.port_hw_config[port].external_phy_config);
+
+ ext_phy_config &= ~PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK;
+ ext_phy_config |= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE;
SHMEM_WR(bp, dev_info.port_hw_config[port].external_phy_config,
- bp->link_params.ext_phy_config);
+ ext_phy_config);
/* log the failure */
netdev_err(bp->dev, "Fan Failure on Network Controller has caused"
@@ -1976,7 +2890,7 @@ static inline void bnx2x_attn_int_deasserted0(struct bnx2x *bp, u32 attn)
{
int port = BP_PORT(bp);
int reg_offset;
- u32 val, swap_val, swap_override;
+ u32 val;
reg_offset = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 :
MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0);
@@ -1990,30 +2904,7 @@ static inline void bnx2x_attn_int_deasserted0(struct bnx2x *bp, u32 attn)
BNX2X_ERR("SPIO5 hw attention\n");
/* Fan failure attention */
- switch (XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config)) {
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
- /* Low power mode is controlled by GPIO 2 */
- bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
- MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
- /* The PHY reset is controlled by GPIO 1 */
- bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
- MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
- break;
-
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
- /* The PHY reset is controlled by GPIO 1 */
- /* fake the port number to cancel the swap done in
- set_gpio() */
- swap_val = REG_RD(bp, NIG_REG_PORT_SWAP);
- swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE);
- port = (swap_val && swap_override) ^ 1;
- bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
- MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
- break;
-
- default:
- break;
- }
+ bnx2x_hw_reset_phy(&bp->link_params);
bnx2x_fan_failure(bp);
}
@@ -2087,6 +2978,10 @@ static inline void bnx2x_attn_int_deasserted2(struct bnx2x *bp, u32 attn)
/* RQ_USDMDP_FIFO_OVERFLOW */
if (val & 0x18000)
BNX2X_ERR("FATAL error from PXP\n");
+ if (CHIP_IS_E2(bp)) {
+ val = REG_RD(bp, PXP_REG_PXP_INT_STS_CLR_1);
+ BNX2X_ERR("PXP hw attention-1 0x%x\n", val);
+ }
}
if (attn & HW_INTERRUT_ASSERT_SET_2) {
@@ -2117,9 +3012,10 @@ static inline void bnx2x_attn_int_deasserted3(struct bnx2x *bp, u32 attn)
int func = BP_FUNC(bp);
REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_12 + func*4, 0);
- bp->mf_config = SHMEM_RD(bp,
- mf_cfg.func_mf_config[func].config);
- val = SHMEM_RD(bp, func_mb[func].drv_status);
+ bp->mf_config[BP_VN(bp)] = MF_CFG_RD(bp,
+ func_mf_config[BP_ABS_FUNC(bp)].config);
+ val = SHMEM_RD(bp,
+ func_mb[BP_FW_MB_IDX(bp)].drv_status);
if (val & DRV_STATUS_DCC_EVENT_MASK)
bnx2x_dcc_event(bp,
(val & DRV_STATUS_DCC_EVENT_MASK));
@@ -2149,13 +3045,13 @@ static inline void bnx2x_attn_int_deasserted3(struct bnx2x *bp, u32 attn)
if (attn & EVEREST_LATCHED_ATTN_IN_USE_MASK) {
BNX2X_ERR("LATCHED attention 0x%08x (masked)\n", attn);
if (attn & BNX2X_GRC_TIMEOUT) {
- val = CHIP_IS_E1H(bp) ?
- REG_RD(bp, MISC_REG_GRC_TIMEOUT_ATTN) : 0;
+ val = CHIP_IS_E1(bp) ? 0 :
+ REG_RD(bp, MISC_REG_GRC_TIMEOUT_ATTN);
BNX2X_ERR("GRC time-out 0x%08x\n", val);
}
if (attn & BNX2X_GRC_RSV) {
- val = CHIP_IS_E1H(bp) ?
- REG_RD(bp, MISC_REG_GRC_RSV_ATTN) : 0;
+ val = CHIP_IS_E1(bp) ? 0 :
+ REG_RD(bp, MISC_REG_GRC_RSV_ATTN);
BNX2X_ERR("GRC reserved 0x%08x\n", val);
}
REG_WR(bp, MISC_REG_AEU_CLR_LATCH_SIGNAL, 0x7ff);
@@ -2168,6 +3064,7 @@ static inline void bnx2x_attn_int_deasserted3(struct bnx2x *bp, u32 attn)
#define RESET_DONE_FLAG_MASK (~LOAD_COUNTER_MASK)
#define RESET_DONE_FLAG_SHIFT LOAD_COUNTER_BITS
#define CHIP_PARITY_SUPPORTED(bp) (CHIP_IS_E1(bp) || CHIP_IS_E1H(bp))
+
/*
* should be run under rtnl lock
*/
@@ -2460,6 +3357,74 @@ bool bnx2x_chk_parity_attn(struct bnx2x *bp)
attn.sig[3]);
}
+
+static inline void bnx2x_attn_int_deasserted4(struct bnx2x *bp, u32 attn)
+{
+ u32 val;
+ if (attn & AEU_INPUTS_ATTN_BITS_PGLUE_HW_INTERRUPT) {
+
+ val = REG_RD(bp, PGLUE_B_REG_PGLUE_B_INT_STS_CLR);
+ BNX2X_ERR("PGLUE hw attention 0x%x\n", val);
+ if (val & PGLUE_B_PGLUE_B_INT_STS_REG_ADDRESS_ERROR)
+ BNX2X_ERR("PGLUE_B_PGLUE_B_INT_STS_REG_"
+ "ADDRESS_ERROR\n");
+ if (val & PGLUE_B_PGLUE_B_INT_STS_REG_INCORRECT_RCV_BEHAVIOR)
+ BNX2X_ERR("PGLUE_B_PGLUE_B_INT_STS_REG_"
+ "INCORRECT_RCV_BEHAVIOR\n");
+ if (val & PGLUE_B_PGLUE_B_INT_STS_REG_WAS_ERROR_ATTN)
+ BNX2X_ERR("PGLUE_B_PGLUE_B_INT_STS_REG_"
+ "WAS_ERROR_ATTN\n");
+ if (val & PGLUE_B_PGLUE_B_INT_STS_REG_VF_LENGTH_VIOLATION_ATTN)
+ BNX2X_ERR("PGLUE_B_PGLUE_B_INT_STS_REG_"
+ "VF_LENGTH_VIOLATION_ATTN\n");
+ if (val &
+ PGLUE_B_PGLUE_B_INT_STS_REG_VF_GRC_SPACE_VIOLATION_ATTN)
+ BNX2X_ERR("PGLUE_B_PGLUE_B_INT_STS_REG_"
+ "VF_GRC_SPACE_VIOLATION_ATTN\n");
+ if (val &
+ PGLUE_B_PGLUE_B_INT_STS_REG_VF_MSIX_BAR_VIOLATION_ATTN)
+ BNX2X_ERR("PGLUE_B_PGLUE_B_INT_STS_REG_"
+ "VF_MSIX_BAR_VIOLATION_ATTN\n");
+ if (val & PGLUE_B_PGLUE_B_INT_STS_REG_TCPL_ERROR_ATTN)
+ BNX2X_ERR("PGLUE_B_PGLUE_B_INT_STS_REG_"
+ "TCPL_ERROR_ATTN\n");
+ if (val & PGLUE_B_PGLUE_B_INT_STS_REG_TCPL_IN_TWO_RCBS_ATTN)
+ BNX2X_ERR("PGLUE_B_PGLUE_B_INT_STS_REG_"
+ "TCPL_IN_TWO_RCBS_ATTN\n");
+ if (val & PGLUE_B_PGLUE_B_INT_STS_REG_CSSNOOP_FIFO_OVERFLOW)
+ BNX2X_ERR("PGLUE_B_PGLUE_B_INT_STS_REG_"
+ "CSSNOOP_FIFO_OVERFLOW\n");
+ }
+ if (attn & AEU_INPUTS_ATTN_BITS_ATC_HW_INTERRUPT) {
+ val = REG_RD(bp, ATC_REG_ATC_INT_STS_CLR);
+ BNX2X_ERR("ATC hw attention 0x%x\n", val);
+ if (val & ATC_ATC_INT_STS_REG_ADDRESS_ERROR)
+ BNX2X_ERR("ATC_ATC_INT_STS_REG_ADDRESS_ERROR\n");
+ if (val & ATC_ATC_INT_STS_REG_ATC_TCPL_TO_NOT_PEND)
+ BNX2X_ERR("ATC_ATC_INT_STS_REG"
+ "_ATC_TCPL_TO_NOT_PEND\n");
+ if (val & ATC_ATC_INT_STS_REG_ATC_GPA_MULTIPLE_HITS)
+ BNX2X_ERR("ATC_ATC_INT_STS_REG_"
+ "ATC_GPA_MULTIPLE_HITS\n");
+ if (val & ATC_ATC_INT_STS_REG_ATC_RCPL_TO_EMPTY_CNT)
+ BNX2X_ERR("ATC_ATC_INT_STS_REG_"
+ "ATC_RCPL_TO_EMPTY_CNT\n");
+ if (val & ATC_ATC_INT_STS_REG_ATC_TCPL_ERROR)
+ BNX2X_ERR("ATC_ATC_INT_STS_REG_ATC_TCPL_ERROR\n");
+ if (val & ATC_ATC_INT_STS_REG_ATC_IREQ_LESS_THAN_STU)
+ BNX2X_ERR("ATC_ATC_INT_STS_REG_"
+ "ATC_IREQ_LESS_THAN_STU\n");
+ }
+
+ if (attn & (AEU_INPUTS_ATTN_BITS_PGLUE_PARITY_ERROR |
+ AEU_INPUTS_ATTN_BITS_ATC_PARITY_ERROR)) {
+ BNX2X_ERR("FATAL parity attention set4 0x%x\n",
+ (u32)(attn & (AEU_INPUTS_ATTN_BITS_PGLUE_PARITY_ERROR |
+ AEU_INPUTS_ATTN_BITS_ATC_PARITY_ERROR)));
+ }
+
+}
+
static void bnx2x_attn_int_deasserted(struct bnx2x *bp, u32 deasserted)
{
struct attn_route attn, *group_mask;
@@ -2490,17 +3455,28 @@ static void bnx2x_attn_int_deasserted(struct bnx2x *bp, u32 deasserted)
attn.sig[1] = REG_RD(bp, MISC_REG_AEU_AFTER_INVERT_2_FUNC_0 + port*4);
attn.sig[2] = REG_RD(bp, MISC_REG_AEU_AFTER_INVERT_3_FUNC_0 + port*4);
attn.sig[3] = REG_RD(bp, MISC_REG_AEU_AFTER_INVERT_4_FUNC_0 + port*4);
- DP(NETIF_MSG_HW, "attn: %08x %08x %08x %08x\n",
- attn.sig[0], attn.sig[1], attn.sig[2], attn.sig[3]);
+ if (CHIP_IS_E2(bp))
+ attn.sig[4] =
+ REG_RD(bp, MISC_REG_AEU_AFTER_INVERT_5_FUNC_0 + port*4);
+ else
+ attn.sig[4] = 0;
+
+ DP(NETIF_MSG_HW, "attn: %08x %08x %08x %08x %08x\n",
+ attn.sig[0], attn.sig[1], attn.sig[2], attn.sig[3], attn.sig[4]);
for (index = 0; index < MAX_DYNAMIC_ATTN_GRPS; index++) {
if (deasserted & (1 << index)) {
group_mask = &bp->attn_group[index];
- DP(NETIF_MSG_HW, "group[%d]: %08x %08x %08x %08x\n",
- index, group_mask->sig[0], group_mask->sig[1],
- group_mask->sig[2], group_mask->sig[3]);
+ DP(NETIF_MSG_HW, "group[%d]: %08x %08x "
+ "%08x %08x %08x\n",
+ index,
+ group_mask->sig[0], group_mask->sig[1],
+ group_mask->sig[2], group_mask->sig[3],
+ group_mask->sig[4]);
+ bnx2x_attn_int_deasserted4(bp,
+ attn.sig[4] & group_mask->sig[4]);
bnx2x_attn_int_deasserted3(bp,
attn.sig[3] & group_mask->sig[3]);
bnx2x_attn_int_deasserted1(bp,
@@ -2514,11 +3490,15 @@ static void bnx2x_attn_int_deasserted(struct bnx2x *bp, u32 deasserted)
bnx2x_release_alr(bp);
- reg_addr = (HC_REG_COMMAND_REG + port*32 + COMMAND_REG_ATTN_BITS_CLR);
+ if (bp->common.int_block == INT_BLOCK_HC)
+ reg_addr = (HC_REG_COMMAND_REG + port*32 +
+ COMMAND_REG_ATTN_BITS_CLR);
+ else
+ reg_addr = (BAR_IGU_INTMEM + IGU_CMD_ATTN_BIT_CLR_UPPER*8);
val = ~deasserted;
- DP(NETIF_MSG_HW, "about to mask 0x%08x at HC addr 0x%x\n",
- val, reg_addr);
+ DP(NETIF_MSG_HW, "about to mask 0x%08x at %s addr 0x%x\n", val,
+ (bp->common.int_block == INT_BLOCK_HC) ? "HC" : "IGU", reg_addr);
REG_WR(bp, reg_addr, val);
if (~bp->attn_state & deasserted)
@@ -2571,6 +3551,141 @@ static void bnx2x_attn_int(struct bnx2x *bp)
bnx2x_attn_int_deasserted(bp, deasserted);
}
+static inline void bnx2x_update_eq_prod(struct bnx2x *bp, u16 prod)
+{
+ /* No memory barriers */
+ storm_memset_eq_prod(bp, prod, BP_FUNC(bp));
+ mmiowb(); /* keep prod updates ordered */
+}
+
+#ifdef BCM_CNIC
+static int bnx2x_cnic_handle_cfc_del(struct bnx2x *bp, u32 cid,
+ union event_ring_elem *elem)
+{
+ if (!bp->cnic_eth_dev.starting_cid ||
+ cid < bp->cnic_eth_dev.starting_cid)
+ return 1;
+
+ DP(BNX2X_MSG_SP, "got delete ramrod for CNIC CID %d\n", cid);
+
+ if (unlikely(elem->message.data.cfc_del_event.error)) {
+ BNX2X_ERR("got delete ramrod for CNIC CID %d with error!\n",
+ cid);
+ bnx2x_panic_dump(bp);
+ }
+ bnx2x_cnic_cfc_comp(bp, cid);
+ return 0;
+}
+#endif
+
+static void bnx2x_eq_int(struct bnx2x *bp)
+{
+ u16 hw_cons, sw_cons, sw_prod;
+ union event_ring_elem *elem;
+ u32 cid;
+ u8 opcode;
+ int spqe_cnt = 0;
+
+ hw_cons = le16_to_cpu(*bp->eq_cons_sb);
+
+ /* The hw_cos range is 1-255, 257 - the sw_cons range is 0-254, 256.
+ * when we get the the next-page we nned to adjust so the loop
+ * condition below will be met. The next element is the size of a
+ * regular element and hence incrementing by 1
+ */
+ if ((hw_cons & EQ_DESC_MAX_PAGE) == EQ_DESC_MAX_PAGE)
+ hw_cons++;
+
+ /* This function may never run in parralel with itself for a
+ * specific bp, thus there is no need in "paired" read memory
+ * barrier here.
+ */
+ sw_cons = bp->eq_cons;
+ sw_prod = bp->eq_prod;
+
+ DP(BNX2X_MSG_SP, "EQ: hw_cons %u sw_cons %u bp->spq_left %u\n",
+ hw_cons, sw_cons, atomic_read(&bp->spq_left));
+
+ for (; sw_cons != hw_cons;
+ sw_prod = NEXT_EQ_IDX(sw_prod), sw_cons = NEXT_EQ_IDX(sw_cons)) {
+
+
+ elem = &bp->eq_ring[EQ_DESC(sw_cons)];
+
+ cid = SW_CID(elem->message.data.cfc_del_event.cid);
+ opcode = elem->message.opcode;
+
+
+ /* handle eq element */
+ switch (opcode) {
+ case EVENT_RING_OPCODE_STAT_QUERY:
+ DP(NETIF_MSG_TIMER, "got statistics comp event\n");
+ /* nothing to do with stats comp */
+ continue;
+
+ case EVENT_RING_OPCODE_CFC_DEL:
+ /* handle according to cid range */
+ /*
+ * we may want to verify here that the bp state is
+ * HALTING
+ */
+ DP(NETIF_MSG_IFDOWN,
+ "got delete ramrod for MULTI[%d]\n", cid);
+#ifdef BCM_CNIC
+ if (!bnx2x_cnic_handle_cfc_del(bp, cid, elem))
+ goto next_spqe;
+#endif
+ bnx2x_fp(bp, cid, state) =
+ BNX2X_FP_STATE_CLOSED;
+
+ goto next_spqe;
+ }
+
+ switch (opcode | bp->state) {
+ case (EVENT_RING_OPCODE_FUNCTION_START |
+ BNX2X_STATE_OPENING_WAIT4_PORT):
+ DP(NETIF_MSG_IFUP, "got setup ramrod\n");
+ bp->state = BNX2X_STATE_FUNC_STARTED;
+ break;
+
+ case (EVENT_RING_OPCODE_FUNCTION_STOP |
+ BNX2X_STATE_CLOSING_WAIT4_HALT):
+ DP(NETIF_MSG_IFDOWN, "got halt ramrod\n");
+ bp->state = BNX2X_STATE_CLOSING_WAIT4_UNLOAD;
+ break;
+
+ case (EVENT_RING_OPCODE_SET_MAC | BNX2X_STATE_OPEN):
+ case (EVENT_RING_OPCODE_SET_MAC | BNX2X_STATE_DIAG):
+ DP(NETIF_MSG_IFUP, "got set mac ramrod\n");
+ bp->set_mac_pending = 0;
+ break;
+
+ case (EVENT_RING_OPCODE_SET_MAC |
+ BNX2X_STATE_CLOSING_WAIT4_HALT):
+ DP(NETIF_MSG_IFDOWN, "got (un)set mac ramrod\n");
+ bp->set_mac_pending = 0;
+ break;
+ default:
+ /* unknown event log error and continue */
+ BNX2X_ERR("Unknown EQ event %d\n",
+ elem->message.opcode);
+ }
+next_spqe:
+ spqe_cnt++;
+ } /* for */
+
+ smp_mb__before_atomic_inc();
+ atomic_add(spqe_cnt, &bp->spq_left);
+
+ bp->eq_cons = sw_cons;
+ bp->eq_prod = sw_prod;
+ /* Make sure that above mem writes were issued towards the memory */
+ smp_wmb();
+
+ /* update producer */
+ bnx2x_update_eq_prod(bp, bp->eq_prod);
+}
+
static void bnx2x_sp_task(struct work_struct *work)
{
struct bnx2x *bp = container_of(work, struct bnx2x, sp_task.work);
@@ -2589,31 +3704,29 @@ static void bnx2x_sp_task(struct work_struct *work)
DP(NETIF_MSG_INTR, "got a slowpath interrupt (status 0x%x)\n", status);
/* HW attentions */
- if (status & 0x1) {
+ if (status & BNX2X_DEF_SB_ATT_IDX) {
bnx2x_attn_int(bp);
- status &= ~0x1;
+ status &= ~BNX2X_DEF_SB_ATT_IDX;
}
- /* CStorm events: STAT_QUERY */
- if (status & 0x2) {
- DP(BNX2X_MSG_SP, "CStorm events: STAT_QUERY\n");
- status &= ~0x2;
+ /* SP events: STAT_QUERY and others */
+ if (status & BNX2X_DEF_SB_IDX) {
+
+ /* Handle EQ completions */
+ bnx2x_eq_int(bp);
+
+ bnx2x_ack_sb(bp, bp->igu_dsb_id, USTORM_ID,
+ le16_to_cpu(bp->def_idx), IGU_INT_NOP, 1);
+
+ status &= ~BNX2X_DEF_SB_IDX;
}
if (unlikely(status))
DP(NETIF_MSG_INTR, "got an unknown interrupt! (status 0x%x)\n",
status);
- bnx2x_ack_sb(bp, DEF_SB_ID, ATTENTION_ID, le16_to_cpu(bp->def_att_idx),
- IGU_INT_NOP, 1);
- bnx2x_ack_sb(bp, DEF_SB_ID, USTORM_ID, le16_to_cpu(bp->def_u_idx),
- IGU_INT_NOP, 1);
- bnx2x_ack_sb(bp, DEF_SB_ID, CSTORM_ID, le16_to_cpu(bp->def_c_idx),
- IGU_INT_NOP, 1);
- bnx2x_ack_sb(bp, DEF_SB_ID, XSTORM_ID, le16_to_cpu(bp->def_x_idx),
- IGU_INT_NOP, 1);
- bnx2x_ack_sb(bp, DEF_SB_ID, TSTORM_ID, le16_to_cpu(bp->def_t_idx),
- IGU_INT_ENABLE, 1);
+ bnx2x_ack_sb(bp, bp->igu_dsb_id, ATTENTION_ID,
+ le16_to_cpu(bp->def_att_idx), IGU_INT_ENABLE, 1);
}
irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance)
@@ -2627,7 +3740,8 @@ irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance)
return IRQ_HANDLED;
}
- bnx2x_ack_sb(bp, DEF_SB_ID, TSTORM_ID, 0, IGU_INT_DISABLE, 0);
+ bnx2x_ack_sb(bp, bp->igu_dsb_id, USTORM_ID, 0,
+ IGU_INT_DISABLE, 0);
#ifdef BNX2X_STOP_ON_ERROR
if (unlikely(bp->panic))
@@ -2671,7 +3785,7 @@ static void bnx2x_timer(unsigned long data)
}
if (!BP_NOMCP(bp)) {
- int func = BP_FUNC(bp);
+ int mb_idx = BP_FW_MB_IDX(bp);
u32 drv_pulse;
u32 mcp_pulse;
@@ -2679,9 +3793,9 @@ static void bnx2x_timer(unsigned long data)
bp->fw_drv_pulse_wr_seq &= DRV_PULSE_SEQ_MASK;
/* TBD - add SYSTEM_TIME */
drv_pulse = bp->fw_drv_pulse_wr_seq;
- SHMEM_WR(bp, func_mb[func].drv_pulse_mb, drv_pulse);
+ SHMEM_WR(bp, func_mb[mb_idx].drv_pulse_mb, drv_pulse);
- mcp_pulse = (SHMEM_RD(bp, func_mb[func].mcp_pulse_mb) &
+ mcp_pulse = (SHMEM_RD(bp, func_mb[mb_idx].mcp_pulse_mb) &
MCP_PULSE_SEQ_MASK);
/* The delta between driver pulse and mcp response
* should be 1 (before mcp response) or 0 (after mcp response)
@@ -2709,324 +3823,310 @@ timer_restart:
* nic init service functions
*/
-static void bnx2x_zero_sb(struct bnx2x *bp, int sb_id)
+static inline void bnx2x_fill(struct bnx2x *bp, u32 addr, int fill, u32 len)
{
- int port = BP_PORT(bp);
+ u32 i;
+ if (!(len%4) && !(addr%4))
+ for (i = 0; i < len; i += 4)
+ REG_WR(bp, addr + i, fill);
+ else
+ for (i = 0; i < len; i++)
+ REG_WR8(bp, addr + i, fill);
- /* "CSTORM" */
- bnx2x_init_fill(bp, CSEM_REG_FAST_MEMORY +
- CSTORM_SB_HOST_STATUS_BLOCK_U_OFFSET(port, sb_id), 0,
- CSTORM_SB_STATUS_BLOCK_U_SIZE / 4);
- bnx2x_init_fill(bp, CSEM_REG_FAST_MEMORY +
- CSTORM_SB_HOST_STATUS_BLOCK_C_OFFSET(port, sb_id), 0,
- CSTORM_SB_STATUS_BLOCK_C_SIZE / 4);
}
-void bnx2x_init_sb(struct bnx2x *bp, struct host_status_block *sb,
- dma_addr_t mapping, int sb_id)
+/* helper: writes FP SP data to FW - data_size in dwords */
+static inline void bnx2x_wr_fp_sb_data(struct bnx2x *bp,
+ int fw_sb_id,
+ u32 *sb_data_p,
+ u32 data_size)
{
- int port = BP_PORT(bp);
- int func = BP_FUNC(bp);
int index;
- u64 section;
+ for (index = 0; index < data_size; index++)
+ REG_WR(bp, BAR_CSTRORM_INTMEM +
+ CSTORM_STATUS_BLOCK_DATA_OFFSET(fw_sb_id) +
+ sizeof(u32)*index,
+ *(sb_data_p + index));
+}
+
+static inline void bnx2x_zero_fp_sb(struct bnx2x *bp, int fw_sb_id)
+{
+ u32 *sb_data_p;
+ u32 data_size = 0;
+ struct hc_status_block_data_e2 sb_data_e2;
+ struct hc_status_block_data_e1x sb_data_e1x;
+
+ /* disable the function first */
+ if (CHIP_IS_E2(bp)) {
+ memset(&sb_data_e2, 0, sizeof(struct hc_status_block_data_e2));
+ sb_data_e2.common.p_func.pf_id = HC_FUNCTION_DISABLED;
+ sb_data_e2.common.p_func.vf_id = HC_FUNCTION_DISABLED;
+ sb_data_e2.common.p_func.vf_valid = false;
+ sb_data_p = (u32 *)&sb_data_e2;
+ data_size = sizeof(struct hc_status_block_data_e2)/sizeof(u32);
+ } else {
+ memset(&sb_data_e1x, 0,
+ sizeof(struct hc_status_block_data_e1x));
+ sb_data_e1x.common.p_func.pf_id = HC_FUNCTION_DISABLED;
+ sb_data_e1x.common.p_func.vf_id = HC_FUNCTION_DISABLED;
+ sb_data_e1x.common.p_func.vf_valid = false;
+ sb_data_p = (u32 *)&sb_data_e1x;
+ data_size = sizeof(struct hc_status_block_data_e1x)/sizeof(u32);
+ }
+ bnx2x_wr_fp_sb_data(bp, fw_sb_id, sb_data_p, data_size);
- /* USTORM */
- section = ((u64)mapping) + offsetof(struct host_status_block,
- u_status_block);
- sb->u_status_block.status_block_id = sb_id;
-
- REG_WR(bp, BAR_CSTRORM_INTMEM +
- CSTORM_SB_HOST_SB_ADDR_U_OFFSET(port, sb_id), U64_LO(section));
- REG_WR(bp, BAR_CSTRORM_INTMEM +
- ((CSTORM_SB_HOST_SB_ADDR_U_OFFSET(port, sb_id)) + 4),
- U64_HI(section));
- REG_WR8(bp, BAR_CSTRORM_INTMEM + FP_USB_FUNC_OFF +
- CSTORM_SB_HOST_STATUS_BLOCK_U_OFFSET(port, sb_id), func);
-
- for (index = 0; index < HC_USTORM_SB_NUM_INDICES; index++)
- REG_WR16(bp, BAR_CSTRORM_INTMEM +
- CSTORM_SB_HC_DISABLE_U_OFFSET(port, sb_id, index), 1);
+ bnx2x_fill(bp, BAR_CSTRORM_INTMEM +
+ CSTORM_STATUS_BLOCK_OFFSET(fw_sb_id), 0,
+ CSTORM_STATUS_BLOCK_SIZE);
+ bnx2x_fill(bp, BAR_CSTRORM_INTMEM +
+ CSTORM_SYNC_BLOCK_OFFSET(fw_sb_id), 0,
+ CSTORM_SYNC_BLOCK_SIZE);
+}
- /* CSTORM */
- section = ((u64)mapping) + offsetof(struct host_status_block,
- c_status_block);
- sb->c_status_block.status_block_id = sb_id;
+/* helper: writes SP SB data to FW */
+static inline void bnx2x_wr_sp_sb_data(struct bnx2x *bp,
+ struct hc_sp_status_block_data *sp_sb_data)
+{
+ int func = BP_FUNC(bp);
+ int i;
+ for (i = 0; i < sizeof(struct hc_sp_status_block_data)/sizeof(u32); i++)
+ REG_WR(bp, BAR_CSTRORM_INTMEM +
+ CSTORM_SP_STATUS_BLOCK_DATA_OFFSET(func) +
+ i*sizeof(u32),
+ *((u32 *)sp_sb_data + i));
+}
- REG_WR(bp, BAR_CSTRORM_INTMEM +
- CSTORM_SB_HOST_SB_ADDR_C_OFFSET(port, sb_id), U64_LO(section));
- REG_WR(bp, BAR_CSTRORM_INTMEM +
- ((CSTORM_SB_HOST_SB_ADDR_C_OFFSET(port, sb_id)) + 4),
- U64_HI(section));
- REG_WR8(bp, BAR_CSTRORM_INTMEM + FP_CSB_FUNC_OFF +
- CSTORM_SB_HOST_STATUS_BLOCK_C_OFFSET(port, sb_id), func);
+static inline void bnx2x_zero_sp_sb(struct bnx2x *bp)
+{
+ int func = BP_FUNC(bp);
+ struct hc_sp_status_block_data sp_sb_data;
+ memset(&sp_sb_data, 0, sizeof(struct hc_sp_status_block_data));
+
+ sp_sb_data.p_func.pf_id = HC_FUNCTION_DISABLED;
+ sp_sb_data.p_func.vf_id = HC_FUNCTION_DISABLED;
+ sp_sb_data.p_func.vf_valid = false;
+
+ bnx2x_wr_sp_sb_data(bp, &sp_sb_data);
- for (index = 0; index < HC_CSTORM_SB_NUM_INDICES; index++)
- REG_WR16(bp, BAR_CSTRORM_INTMEM +
- CSTORM_SB_HC_DISABLE_C_OFFSET(port, sb_id, index), 1);
+ bnx2x_fill(bp, BAR_CSTRORM_INTMEM +
+ CSTORM_SP_STATUS_BLOCK_OFFSET(func), 0,
+ CSTORM_SP_STATUS_BLOCK_SIZE);
+ bnx2x_fill(bp, BAR_CSTRORM_INTMEM +
+ CSTORM_SP_SYNC_BLOCK_OFFSET(func), 0,
+ CSTORM_SP_SYNC_BLOCK_SIZE);
- bnx2x_ack_sb(bp, sb_id, CSTORM_ID, 0, IGU_INT_ENABLE, 0);
}
-static void bnx2x_zero_def_sb(struct bnx2x *bp)
+
+static inline
+void bnx2x_setup_ndsb_state_machine(struct hc_status_block_sm *hc_sm,
+ int igu_sb_id, int igu_seg_id)
{
- int func = BP_FUNC(bp);
+ hc_sm->igu_sb_id = igu_sb_id;
+ hc_sm->igu_seg_id = igu_seg_id;
+ hc_sm->timer_value = 0xFF;
+ hc_sm->time_to_expire = 0xFFFFFFFF;
+}
+
+void bnx2x_init_sb(struct bnx2x *bp, dma_addr_t mapping, int vfid,
+ u8 vf_valid, int fw_sb_id, int igu_sb_id)
+{
+ int igu_seg_id;
+
+ struct hc_status_block_data_e2 sb_data_e2;
+ struct hc_status_block_data_e1x sb_data_e1x;
+ struct hc_status_block_sm *hc_sm_p;
+ struct hc_index_data *hc_index_p;
+ int data_size;
+ u32 *sb_data_p;
+
+ if (CHIP_INT_MODE_IS_BC(bp))
+ igu_seg_id = HC_SEG_ACCESS_NORM;
+ else
+ igu_seg_id = IGU_SEG_ACCESS_NORM;
+
+ bnx2x_zero_fp_sb(bp, fw_sb_id);
+
+ if (CHIP_IS_E2(bp)) {
+ memset(&sb_data_e2, 0, sizeof(struct hc_status_block_data_e2));
+ sb_data_e2.common.p_func.pf_id = BP_FUNC(bp);
+ sb_data_e2.common.p_func.vf_id = vfid;
+ sb_data_e2.common.p_func.vf_valid = vf_valid;
+ sb_data_e2.common.p_func.vnic_id = BP_VN(bp);
+ sb_data_e2.common.same_igu_sb_1b = true;
+ sb_data_e2.common.host_sb_addr.hi = U64_HI(mapping);
+ sb_data_e2.common.host_sb_addr.lo = U64_LO(mapping);
+ hc_sm_p = sb_data_e2.common.state_machine;
+ hc_index_p = sb_data_e2.index_data;
+ sb_data_p = (u32 *)&sb_data_e2;
+ data_size = sizeof(struct hc_status_block_data_e2)/sizeof(u32);
+ } else {
+ memset(&sb_data_e1x, 0,
+ sizeof(struct hc_status_block_data_e1x));
+ sb_data_e1x.common.p_func.pf_id = BP_FUNC(bp);
+ sb_data_e1x.common.p_func.vf_id = 0xff;
+ sb_data_e1x.common.p_func.vf_valid = false;
+ sb_data_e1x.common.p_func.vnic_id = BP_VN(bp);
+ sb_data_e1x.common.same_igu_sb_1b = true;
+ sb_data_e1x.common.host_sb_addr.hi = U64_HI(mapping);
+ sb_data_e1x.common.host_sb_addr.lo = U64_LO(mapping);
+ hc_sm_p = sb_data_e1x.common.state_machine;
+ hc_index_p = sb_data_e1x.index_data;
+ sb_data_p = (u32 *)&sb_data_e1x;
+ data_size = sizeof(struct hc_status_block_data_e1x)/sizeof(u32);
+ }
+
+ bnx2x_setup_ndsb_state_machine(&hc_sm_p[SM_RX_ID],
+ igu_sb_id, igu_seg_id);
+ bnx2x_setup_ndsb_state_machine(&hc_sm_p[SM_TX_ID],
+ igu_sb_id, igu_seg_id);
+
+ DP(NETIF_MSG_HW, "Init FW SB %d\n", fw_sb_id);
+
+ /* write indecies to HW */
+ bnx2x_wr_fp_sb_data(bp, fw_sb_id, sb_data_p, data_size);
+}
+
+static void bnx2x_update_coalesce_sb_index(struct bnx2x *bp, u16 fw_sb_id,
+ u8 sb_index, u8 disable, u16 usec)
+{
+ int port = BP_PORT(bp);
+ u8 ticks = usec / BNX2X_BTR;
+
+ storm_memset_hc_timeout(bp, port, fw_sb_id, sb_index, ticks);
- bnx2x_init_fill(bp, TSEM_REG_FAST_MEMORY +
- TSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), 0,
- sizeof(struct tstorm_def_status_block)/4);
- bnx2x_init_fill(bp, CSEM_REG_FAST_MEMORY +
- CSTORM_DEF_SB_HOST_STATUS_BLOCK_U_OFFSET(func), 0,
- sizeof(struct cstorm_def_status_block_u)/4);
- bnx2x_init_fill(bp, CSEM_REG_FAST_MEMORY +
- CSTORM_DEF_SB_HOST_STATUS_BLOCK_C_OFFSET(func), 0,
- sizeof(struct cstorm_def_status_block_c)/4);
- bnx2x_init_fill(bp, XSEM_REG_FAST_MEMORY +
- XSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), 0,
- sizeof(struct xstorm_def_status_block)/4);
+ disable = disable ? 1 : (usec ? 0 : 1);
+ storm_memset_hc_disable(bp, port, fw_sb_id, sb_index, disable);
+}
+
+static void bnx2x_update_coalesce_sb(struct bnx2x *bp, u16 fw_sb_id,
+ u16 tx_usec, u16 rx_usec)
+{
+ bnx2x_update_coalesce_sb_index(bp, fw_sb_id, U_SB_ETH_RX_CQ_INDEX,
+ false, rx_usec);
+ bnx2x_update_coalesce_sb_index(bp, fw_sb_id, C_SB_ETH_TX_CQ_INDEX,
+ false, tx_usec);
}
-static void bnx2x_init_def_sb(struct bnx2x *bp,
- struct host_def_status_block *def_sb,
- dma_addr_t mapping, int sb_id)
+static void bnx2x_init_def_sb(struct bnx2x *bp)
{
+ struct host_sp_status_block *def_sb = bp->def_status_blk;
+ dma_addr_t mapping = bp->def_status_blk_mapping;
+ int igu_sp_sb_index;
+ int igu_seg_id;
int port = BP_PORT(bp);
int func = BP_FUNC(bp);
- int index, val, reg_offset;
+ int reg_offset;
u64 section;
+ int index;
+ struct hc_sp_status_block_data sp_sb_data;
+ memset(&sp_sb_data, 0, sizeof(struct hc_sp_status_block_data));
+
+ if (CHIP_INT_MODE_IS_BC(bp)) {
+ igu_sp_sb_index = DEF_SB_IGU_ID;
+ igu_seg_id = HC_SEG_ACCESS_DEF;
+ } else {
+ igu_sp_sb_index = bp->igu_dsb_id;
+ igu_seg_id = IGU_SEG_ACCESS_DEF;
+ }
/* ATTN */
- section = ((u64)mapping) + offsetof(struct host_def_status_block,
+ section = ((u64)mapping) + offsetof(struct host_sp_status_block,
atten_status_block);
- def_sb->atten_status_block.status_block_id = sb_id;
+ def_sb->atten_status_block.status_block_id = igu_sp_sb_index;
bp->attn_state = 0;
reg_offset = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 :
MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0);
-
for (index = 0; index < MAX_DYNAMIC_ATTN_GRPS; index++) {
- bp->attn_group[index].sig[0] = REG_RD(bp,
- reg_offset + 0x10*index);
- bp->attn_group[index].sig[1] = REG_RD(bp,
- reg_offset + 0x4 + 0x10*index);
- bp->attn_group[index].sig[2] = REG_RD(bp,
- reg_offset + 0x8 + 0x10*index);
- bp->attn_group[index].sig[3] = REG_RD(bp,
- reg_offset + 0xc + 0x10*index);
+ int sindex;
+ /* take care of sig[0]..sig[4] */
+ for (sindex = 0; sindex < 4; sindex++)
+ bp->attn_group[index].sig[sindex] =
+ REG_RD(bp, reg_offset + sindex*0x4 + 0x10*index);
+
+ if (CHIP_IS_E2(bp))
+ /*
+ * enable5 is separate from the rest of the registers,
+ * and therefore the address skip is 4
+ * and not 16 between the different groups
+ */
+ bp->attn_group[index].sig[4] = REG_RD(bp,
+ reg_offset + 0x10 + 0x4*index);
+ else
+ bp->attn_group[index].sig[4] = 0;
}
- reg_offset = (port ? HC_REG_ATTN_MSG1_ADDR_L :
- HC_REG_ATTN_MSG0_ADDR_L);
-
- REG_WR(bp, reg_offset, U64_LO(section));
- REG_WR(bp, reg_offset + 4, U64_HI(section));
+ if (bp->common.int_block == INT_BLOCK_HC) {
+ reg_offset = (port ? HC_REG_ATTN_MSG1_ADDR_L :
+ HC_REG_ATTN_MSG0_ADDR_L);
- reg_offset = (port ? HC_REG_ATTN_NUM_P1 : HC_REG_ATTN_NUM_P0);
-
- val = REG_RD(bp, reg_offset);
- val |= sb_id;
- REG_WR(bp, reg_offset, val);
+ REG_WR(bp, reg_offset, U64_LO(section));
+ REG_WR(bp, reg_offset + 4, U64_HI(section));
+ } else if (CHIP_IS_E2(bp)) {
+ REG_WR(bp, IGU_REG_ATTN_MSG_ADDR_L, U64_LO(section));
+ REG_WR(bp, IGU_REG_ATTN_MSG_ADDR_H, U64_HI(section));
+ }
- /* USTORM */
- section = ((u64)mapping) + offsetof(struct host_def_status_block,
- u_def_status_block);
- def_sb->u_def_status_block.status_block_id = sb_id;
-
- REG_WR(bp, BAR_CSTRORM_INTMEM +
- CSTORM_DEF_SB_HOST_SB_ADDR_U_OFFSET(func), U64_LO(section));
- REG_WR(bp, BAR_CSTRORM_INTMEM +
- ((CSTORM_DEF_SB_HOST_SB_ADDR_U_OFFSET(func)) + 4),
- U64_HI(section));
- REG_WR8(bp, BAR_CSTRORM_INTMEM + DEF_USB_FUNC_OFF +
- CSTORM_DEF_SB_HOST_STATUS_BLOCK_U_OFFSET(func), func);
-
- for (index = 0; index < HC_USTORM_DEF_SB_NUM_INDICES; index++)
- REG_WR16(bp, BAR_CSTRORM_INTMEM +
- CSTORM_DEF_SB_HC_DISABLE_U_OFFSET(func, index), 1);
+ section = ((u64)mapping) + offsetof(struct host_sp_status_block,
+ sp_sb);
- /* CSTORM */
- section = ((u64)mapping) + offsetof(struct host_def_status_block,
- c_def_status_block);
- def_sb->c_def_status_block.status_block_id = sb_id;
-
- REG_WR(bp, BAR_CSTRORM_INTMEM +
- CSTORM_DEF_SB_HOST_SB_ADDR_C_OFFSET(func), U64_LO(section));
- REG_WR(bp, BAR_CSTRORM_INTMEM +
- ((CSTORM_DEF_SB_HOST_SB_ADDR_C_OFFSET(func)) + 4),
- U64_HI(section));
- REG_WR8(bp, BAR_CSTRORM_INTMEM + DEF_CSB_FUNC_OFF +
- CSTORM_DEF_SB_HOST_STATUS_BLOCK_C_OFFSET(func), func);
-
- for (index = 0; index < HC_CSTORM_DEF_SB_NUM_INDICES; index++)
- REG_WR16(bp, BAR_CSTRORM_INTMEM +
- CSTORM_DEF_SB_HC_DISABLE_C_OFFSET(func, index), 1);
+ bnx2x_zero_sp_sb(bp);
- /* TSTORM */
- section = ((u64)mapping) + offsetof(struct host_def_status_block,
- t_def_status_block);
- def_sb->t_def_status_block.status_block_id = sb_id;
-
- REG_WR(bp, BAR_TSTRORM_INTMEM +
- TSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(func), U64_LO(section));
- REG_WR(bp, BAR_TSTRORM_INTMEM +
- ((TSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(func)) + 4),
- U64_HI(section));
- REG_WR8(bp, BAR_TSTRORM_INTMEM + DEF_TSB_FUNC_OFF +
- TSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), func);
-
- for (index = 0; index < HC_TSTORM_DEF_SB_NUM_INDICES; index++)
- REG_WR16(bp, BAR_TSTRORM_INTMEM +
- TSTORM_DEF_SB_HC_DISABLE_OFFSET(func, index), 1);
+ sp_sb_data.host_sb_addr.lo = U64_LO(section);
+ sp_sb_data.host_sb_addr.hi = U64_HI(section);
+ sp_sb_data.igu_sb_id = igu_sp_sb_index;
+ sp_sb_data.igu_seg_id = igu_seg_id;
+ sp_sb_data.p_func.pf_id = func;
+ sp_sb_data.p_func.vnic_id = BP_VN(bp);
+ sp_sb_data.p_func.vf_id = 0xff;
- /* XSTORM */
- section = ((u64)mapping) + offsetof(struct host_def_status_block,
- x_def_status_block);
- def_sb->x_def_status_block.status_block_id = sb_id;
-
- REG_WR(bp, BAR_XSTRORM_INTMEM +
- XSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(func), U64_LO(section));
- REG_WR(bp, BAR_XSTRORM_INTMEM +
- ((XSTORM_DEF_SB_HOST_SB_ADDR_OFFSET(func)) + 4),
- U64_HI(section));
- REG_WR8(bp, BAR_XSTRORM_INTMEM + DEF_XSB_FUNC_OFF +
- XSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), func);
-
- for (index = 0; index < HC_XSTORM_DEF_SB_NUM_INDICES; index++)
- REG_WR16(bp, BAR_XSTRORM_INTMEM +
- XSTORM_DEF_SB_HC_DISABLE_OFFSET(func, index), 1);
+ bnx2x_wr_sp_sb_data(bp, &sp_sb_data);
bp->stats_pending = 0;
bp->set_mac_pending = 0;
- bnx2x_ack_sb(bp, sb_id, CSTORM_ID, 0, IGU_INT_ENABLE, 0);
+ bnx2x_ack_sb(bp, bp->igu_dsb_id, USTORM_ID, 0, IGU_INT_ENABLE, 0);
}
void bnx2x_update_coalesce(struct bnx2x *bp)
{
- int port = BP_PORT(bp);
int i;
- for_each_queue(bp, i) {
- int sb_id = bp->fp[i].sb_id;
-
- /* HC_INDEX_U_ETH_RX_CQ_CONS */
- REG_WR8(bp, BAR_CSTRORM_INTMEM +
- CSTORM_SB_HC_TIMEOUT_U_OFFSET(port, sb_id,
- U_SB_ETH_RX_CQ_INDEX),
- bp->rx_ticks/(4 * BNX2X_BTR));
- REG_WR16(bp, BAR_CSTRORM_INTMEM +
- CSTORM_SB_HC_DISABLE_U_OFFSET(port, sb_id,
- U_SB_ETH_RX_CQ_INDEX),
- (bp->rx_ticks/(4 * BNX2X_BTR)) ? 0 : 1);
-
- /* HC_INDEX_C_ETH_TX_CQ_CONS */
- REG_WR8(bp, BAR_CSTRORM_INTMEM +
- CSTORM_SB_HC_TIMEOUT_C_OFFSET(port, sb_id,
- C_SB_ETH_TX_CQ_INDEX),
- bp->tx_ticks/(4 * BNX2X_BTR));
- REG_WR16(bp, BAR_CSTRORM_INTMEM +
- CSTORM_SB_HC_DISABLE_C_OFFSET(port, sb_id,
- C_SB_ETH_TX_CQ_INDEX),
- (bp->tx_ticks/(4 * BNX2X_BTR)) ? 0 : 1);
- }
+ for_each_queue(bp, i)
+ bnx2x_update_coalesce_sb(bp, bp->fp[i].fw_sb_id,
+ bp->rx_ticks, bp->tx_ticks);
}
static void bnx2x_init_sp_ring(struct bnx2x *bp)
{
- int func = BP_FUNC(bp);
-
spin_lock_init(&bp->spq_lock);
+ atomic_set(&bp->spq_left, MAX_SPQ_PENDING);
- bp->spq_left = MAX_SPQ_PENDING;
bp->spq_prod_idx = 0;
bp->dsb_sp_prod = BNX2X_SP_DSB_INDEX;
bp->spq_prod_bd = bp->spq;
bp->spq_last_bd = bp->spq_prod_bd + MAX_SP_DESC_CNT;
-
- REG_WR(bp, XSEM_REG_FAST_MEMORY + XSTORM_SPQ_PAGE_BASE_OFFSET(func),
- U64_LO(bp->spq_mapping));
- REG_WR(bp,
- XSEM_REG_FAST_MEMORY + XSTORM_SPQ_PAGE_BASE_OFFSET(func) + 4,
- U64_HI(bp->spq_mapping));
-
- REG_WR(bp, XSEM_REG_FAST_MEMORY + XSTORM_SPQ_PROD_OFFSET(func),
- bp->spq_prod_idx);
}
-static void bnx2x_init_context(struct bnx2x *bp)
+static void bnx2x_init_eq_ring(struct bnx2x *bp)
{
int i;
+ for (i = 1; i <= NUM_EQ_PAGES; i++) {
+ union event_ring_elem *elem =
+ &bp->eq_ring[EQ_DESC_CNT_PAGE * i - 1];
- /* Rx */
- for_each_queue(bp, i) {
- struct eth_context *context = bnx2x_sp(bp, context[i].eth);
- struct bnx2x_fastpath *fp = &bp->fp[i];
- u8 cl_id = fp->cl_id;
-
- context->ustorm_st_context.common.sb_index_numbers =
- BNX2X_RX_SB_INDEX_NUM;
- context->ustorm_st_context.common.clientId = cl_id;
- context->ustorm_st_context.common.status_block_id = fp->sb_id;
- context->ustorm_st_context.common.flags =
- (USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_MC_ALIGNMENT |
- USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_STATISTICS);
- context->ustorm_st_context.common.statistics_counter_id =
- cl_id;
- context->ustorm_st_context.common.mc_alignment_log_size =
- BNX2X_RX_ALIGN_SHIFT;
- context->ustorm_st_context.common.bd_buff_size =
- bp->rx_buf_size;
- context->ustorm_st_context.common.bd_page_base_hi =
- U64_HI(fp->rx_desc_mapping);
- context->ustorm_st_context.common.bd_page_base_lo =
- U64_LO(fp->rx_desc_mapping);
- if (!fp->disable_tpa) {
- context->ustorm_st_context.common.flags |=
- USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_TPA;
- context->ustorm_st_context.common.sge_buff_size =
- (u16)min_t(u32, SGE_PAGE_SIZE*PAGES_PER_SGE,
- 0xffff);
- context->ustorm_st_context.common.sge_page_base_hi =
- U64_HI(fp->rx_sge_mapping);
- context->ustorm_st_context.common.sge_page_base_lo =
- U64_LO(fp->rx_sge_mapping);
-
- context->ustorm_st_context.common.max_sges_for_packet =
- SGE_PAGE_ALIGN(bp->dev->mtu) >> SGE_PAGE_SHIFT;
- context->ustorm_st_context.common.max_sges_for_packet =
- ((context->ustorm_st_context.common.
- max_sges_for_packet + PAGES_PER_SGE - 1) &
- (~(PAGES_PER_SGE - 1))) >> PAGES_PER_SGE_SHIFT;
- }
-
- context->ustorm_ag_context.cdu_usage =
- CDU_RSRVD_VALUE_TYPE_A(HW_CID(bp, i),
- CDU_REGION_NUMBER_UCM_AG,
- ETH_CONNECTION_TYPE);
-
- context->xstorm_ag_context.cdu_reserved =
- CDU_RSRVD_VALUE_TYPE_A(HW_CID(bp, i),
- CDU_REGION_NUMBER_XCM_AG,
- ETH_CONNECTION_TYPE);
- }
-
- /* Tx */
- for_each_queue(bp, i) {
- struct bnx2x_fastpath *fp = &bp->fp[i];
- struct eth_context *context =
- bnx2x_sp(bp, context[i].eth);
-
- context->cstorm_st_context.sb_index_number =
- C_SB_ETH_TX_CQ_INDEX;
- context->cstorm_st_context.status_block_id = fp->sb_id;
-
- context->xstorm_st_context.tx_bd_page_base_hi =
- U64_HI(fp->tx_desc_mapping);
- context->xstorm_st_context.tx_bd_page_base_lo =
- U64_LO(fp->tx_desc_mapping);
- context->xstorm_st_context.statistics_data = (fp->cl_id |
- XSTORM_ETH_ST_CONTEXT_STATISTICS_ENABLE);
+ elem->next_page.addr.hi =
+ cpu_to_le32(U64_HI(bp->eq_mapping +
+ BCM_PAGE_SIZE * (i % NUM_EQ_PAGES)));
+ elem->next_page.addr.lo =
+ cpu_to_le32(U64_LO(bp->eq_mapping +
+ BCM_PAGE_SIZE*(i % NUM_EQ_PAGES)));
}
+ bp->eq_cons = 0;
+ bp->eq_prod = NUM_EQ_DESC;
+ bp->eq_cons_sb = BNX2X_EQ_INDEX;
}
static void bnx2x_init_ind_table(struct bnx2x *bp)
@@ -3045,47 +4145,11 @@ static void bnx2x_init_ind_table(struct bnx2x *bp)
bp->fp->cl_id + (i % bp->num_queues));
}
-void bnx2x_set_client_config(struct bnx2x *bp)
-{
- struct tstorm_eth_client_config tstorm_client = {0};
- int port = BP_PORT(bp);
- int i;
-
- tstorm_client.mtu = bp->dev->mtu;
- tstorm_client.config_flags =
- (TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE |
- TSTORM_ETH_CLIENT_CONFIG_E1HOV_REM_ENABLE);
-#ifdef BCM_VLAN
- if (bp->rx_mode && bp->vlgrp && (bp->flags & HW_VLAN_RX_FLAG)) {
- tstorm_client.config_flags |=
- TSTORM_ETH_CLIENT_CONFIG_VLAN_REM_ENABLE;
- DP(NETIF_MSG_IFUP, "vlan removal enabled\n");
- }
-#endif
-
- for_each_queue(bp, i) {
- tstorm_client.statistics_counter_id = bp->fp[i].cl_id;
-
- REG_WR(bp, BAR_TSTRORM_INTMEM +
- TSTORM_CLIENT_CONFIG_OFFSET(port, bp->fp[i].cl_id),
- ((u32 *)&tstorm_client)[0]);
- REG_WR(bp, BAR_TSTRORM_INTMEM +
- TSTORM_CLIENT_CONFIG_OFFSET(port, bp->fp[i].cl_id) + 4,
- ((u32 *)&tstorm_client)[1]);
- }
-
- DP(BNX2X_MSG_OFF, "tstorm_client: 0x%08x 0x%08x\n",
- ((u32 *)&tstorm_client)[0], ((u32 *)&tstorm_client)[1]);
-}
-
void bnx2x_set_storm_rx_mode(struct bnx2x *bp)
{
- struct tstorm_eth_mac_filter_config tstorm_mac_filter = {0};
int mode = bp->rx_mode;
- int mask = bp->rx_mode_cl_mask;
- int func = BP_FUNC(bp);
- int port = BP_PORT(bp);
- int i;
+ u16 cl_id;
+
/* All but management unicast packets should pass to the host as well */
u32 llh_mask =
NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_BRCST |
@@ -3093,28 +4157,32 @@ void bnx2x_set_storm_rx_mode(struct bnx2x *bp)
NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_VLAN |
NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_NO_VLAN;
- DP(NETIF_MSG_IFUP, "rx mode %d mask 0x%x\n", mode, mask);
-
switch (mode) {
case BNX2X_RX_MODE_NONE: /* no Rx */
- tstorm_mac_filter.ucast_drop_all = mask;
- tstorm_mac_filter.mcast_drop_all = mask;
- tstorm_mac_filter.bcast_drop_all = mask;
+ cl_id = BP_L_ID(bp);
+ bnx2x_rxq_set_mac_filters(bp, cl_id, BNX2X_ACCEPT_NONE);
break;
case BNX2X_RX_MODE_NORMAL:
- tstorm_mac_filter.bcast_accept_all = mask;
+ cl_id = BP_L_ID(bp);
+ bnx2x_rxq_set_mac_filters(bp, cl_id,
+ BNX2X_ACCEPT_UNICAST |
+ BNX2X_ACCEPT_BROADCAST |
+ BNX2X_ACCEPT_MULTICAST);
break;
case BNX2X_RX_MODE_ALLMULTI:
- tstorm_mac_filter.mcast_accept_all = mask;
- tstorm_mac_filter.bcast_accept_all = mask;
+ cl_id = BP_L_ID(bp);
+ bnx2x_rxq_set_mac_filters(bp, cl_id,
+ BNX2X_ACCEPT_UNICAST |
+ BNX2X_ACCEPT_BROADCAST |
+ BNX2X_ACCEPT_ALL_MULTICAST);
break;
case BNX2X_RX_MODE_PROMISC:
- tstorm_mac_filter.ucast_accept_all = mask;
- tstorm_mac_filter.mcast_accept_all = mask;
- tstorm_mac_filter.bcast_accept_all = mask;
+ cl_id = BP_L_ID(bp);
+ bnx2x_rxq_set_mac_filters(bp, cl_id, BNX2X_PROMISCUOUS_MODE);
+
/* pass management unicast packets as well */
llh_mask |= NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_UNCST;
break;
@@ -3125,262 +4193,64 @@ void bnx2x_set_storm_rx_mode(struct bnx2x *bp)
}
REG_WR(bp,
- (port ? NIG_REG_LLH1_BRB1_DRV_MASK : NIG_REG_LLH0_BRB1_DRV_MASK),
+ BP_PORT(bp) ? NIG_REG_LLH1_BRB1_DRV_MASK :
+ NIG_REG_LLH0_BRB1_DRV_MASK,
llh_mask);
- for (i = 0; i < sizeof(struct tstorm_eth_mac_filter_config)/4; i++) {
- REG_WR(bp, BAR_TSTRORM_INTMEM +
- TSTORM_MAC_FILTER_CONFIG_OFFSET(func) + i * 4,
- ((u32 *)&tstorm_mac_filter)[i]);
-
-/* DP(NETIF_MSG_IFUP, "tstorm_mac_filter[%d]: 0x%08x\n", i,
- ((u32 *)&tstorm_mac_filter)[i]); */
- }
+ DP(NETIF_MSG_IFUP, "rx mode %d\n"
+ "drop_ucast 0x%x\ndrop_mcast 0x%x\ndrop_bcast 0x%x\n"
+ "accp_ucast 0x%x\naccp_mcast 0x%x\naccp_bcast 0x%x\n", mode,
+ bp->mac_filters.ucast_drop_all,
+ bp->mac_filters.mcast_drop_all,
+ bp->mac_filters.bcast_drop_all,
+ bp->mac_filters.ucast_accept_all,
+ bp->mac_filters.mcast_accept_all,
+ bp->mac_filters.bcast_accept_all
+ );
- if (mode != BNX2X_RX_MODE_NONE)
- bnx2x_set_client_config(bp);
+ storm_memset_mac_filters(bp, &bp->mac_filters, BP_FUNC(bp));
}
static void bnx2x_init_internal_common(struct bnx2x *bp)
{
int i;
- /* Zero this manually as its initialization is
- currently missing in the initTool */
- for (i = 0; i < (USTORM_AGG_DATA_SIZE >> 2); i++)
- REG_WR(bp, BAR_USTRORM_INTMEM +
- USTORM_AGG_DATA_OFFSET + i * 4, 0);
-}
-
-static void bnx2x_init_internal_port(struct bnx2x *bp)
-{
- int port = BP_PORT(bp);
-
- REG_WR(bp,
- BAR_CSTRORM_INTMEM + CSTORM_HC_BTR_U_OFFSET(port), BNX2X_BTR);
- REG_WR(bp,
- BAR_CSTRORM_INTMEM + CSTORM_HC_BTR_C_OFFSET(port), BNX2X_BTR);
- REG_WR(bp, BAR_TSTRORM_INTMEM + TSTORM_HC_BTR_OFFSET(port), BNX2X_BTR);
- REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_HC_BTR_OFFSET(port), BNX2X_BTR);
-}
-
-static void bnx2x_init_internal_func(struct bnx2x *bp)
-{
- struct tstorm_eth_function_common_config tstorm_config = {0};
- struct stats_indication_flags stats_flags = {0};
- int port = BP_PORT(bp);
- int func = BP_FUNC(bp);
- int i, j;
- u32 offset;
- u16 max_agg_size;
-
- tstorm_config.config_flags = RSS_FLAGS(bp);
-
- if (is_multi(bp))
- tstorm_config.rss_result_mask = MULTI_MASK;
-
- /* Enable TPA if needed */
- if (bp->flags & TPA_ENABLE_FLAG)
- tstorm_config.config_flags |=
- TSTORM_ETH_FUNCTION_COMMON_CONFIG_ENABLE_TPA;
-
- if (IS_E1HMF(bp))
- tstorm_config.config_flags |=
- TSTORM_ETH_FUNCTION_COMMON_CONFIG_E1HOV_IN_CAM;
-
- tstorm_config.leading_client_id = BP_L_ID(bp);
-
- REG_WR(bp, BAR_TSTRORM_INTMEM +
- TSTORM_FUNCTION_COMMON_CONFIG_OFFSET(func),
- (*(u32 *)&tstorm_config));
-
- bp->rx_mode = BNX2X_RX_MODE_NONE; /* no rx until link is up */
- bp->rx_mode_cl_mask = (1 << BP_L_ID(bp));
- bnx2x_set_storm_rx_mode(bp);
+ if (!CHIP_IS_E1(bp)) {
- for_each_queue(bp, i) {
- u8 cl_id = bp->fp[i].cl_id;
-
- /* reset xstorm per client statistics */
- offset = BAR_XSTRORM_INTMEM +
- XSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cl_id);
- for (j = 0;
- j < sizeof(struct xstorm_per_client_stats) / 4; j++)
- REG_WR(bp, offset + j*4, 0);
-
- /* reset tstorm per client statistics */
- offset = BAR_TSTRORM_INTMEM +
- TSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cl_id);
- for (j = 0;
- j < sizeof(struct tstorm_per_client_stats) / 4; j++)
- REG_WR(bp, offset + j*4, 0);
-
- /* reset ustorm per client statistics */
- offset = BAR_USTRORM_INTMEM +
- USTORM_PER_COUNTER_ID_STATS_OFFSET(port, cl_id);
- for (j = 0;
- j < sizeof(struct ustorm_per_client_stats) / 4; j++)
- REG_WR(bp, offset + j*4, 0);
- }
-
- /* Init statistics related context */
- stats_flags.collect_eth = 1;
-
- REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_STATS_FLAGS_OFFSET(func),
- ((u32 *)&stats_flags)[0]);
- REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_STATS_FLAGS_OFFSET(func) + 4,
- ((u32 *)&stats_flags)[1]);
-
- REG_WR(bp, BAR_TSTRORM_INTMEM + TSTORM_STATS_FLAGS_OFFSET(func),
- ((u32 *)&stats_flags)[0]);
- REG_WR(bp, BAR_TSTRORM_INTMEM + TSTORM_STATS_FLAGS_OFFSET(func) + 4,
- ((u32 *)&stats_flags)[1]);
-
- REG_WR(bp, BAR_USTRORM_INTMEM + USTORM_STATS_FLAGS_OFFSET(func),
- ((u32 *)&stats_flags)[0]);
- REG_WR(bp, BAR_USTRORM_INTMEM + USTORM_STATS_FLAGS_OFFSET(func) + 4,
- ((u32 *)&stats_flags)[1]);
-
- REG_WR(bp, BAR_CSTRORM_INTMEM + CSTORM_STATS_FLAGS_OFFSET(func),
- ((u32 *)&stats_flags)[0]);
- REG_WR(bp, BAR_CSTRORM_INTMEM + CSTORM_STATS_FLAGS_OFFSET(func) + 4,
- ((u32 *)&stats_flags)[1]);
-
- REG_WR(bp, BAR_XSTRORM_INTMEM +
- XSTORM_ETH_STATS_QUERY_ADDR_OFFSET(func),
- U64_LO(bnx2x_sp_mapping(bp, fw_stats)));
- REG_WR(bp, BAR_XSTRORM_INTMEM +
- XSTORM_ETH_STATS_QUERY_ADDR_OFFSET(func) + 4,
- U64_HI(bnx2x_sp_mapping(bp, fw_stats)));
-
- REG_WR(bp, BAR_TSTRORM_INTMEM +
- TSTORM_ETH_STATS_QUERY_ADDR_OFFSET(func),
- U64_LO(bnx2x_sp_mapping(bp, fw_stats)));
- REG_WR(bp, BAR_TSTRORM_INTMEM +
- TSTORM_ETH_STATS_QUERY_ADDR_OFFSET(func) + 4,
- U64_HI(bnx2x_sp_mapping(bp, fw_stats)));
-
- REG_WR(bp, BAR_USTRORM_INTMEM +
- USTORM_ETH_STATS_QUERY_ADDR_OFFSET(func),
- U64_LO(bnx2x_sp_mapping(bp, fw_stats)));
- REG_WR(bp, BAR_USTRORM_INTMEM +
- USTORM_ETH_STATS_QUERY_ADDR_OFFSET(func) + 4,
- U64_HI(bnx2x_sp_mapping(bp, fw_stats)));
-
- if (CHIP_IS_E1H(bp)) {
+ /* xstorm needs to know whether to add ovlan to packets or not,
+ * in switch-independent we'll write 0 to here... */
REG_WR8(bp, BAR_XSTRORM_INTMEM + XSTORM_FUNCTION_MODE_OFFSET,
- IS_E1HMF(bp));
+ bp->mf_mode);
REG_WR8(bp, BAR_TSTRORM_INTMEM + TSTORM_FUNCTION_MODE_OFFSET,
- IS_E1HMF(bp));
+ bp->mf_mode);
REG_WR8(bp, BAR_CSTRORM_INTMEM + CSTORM_FUNCTION_MODE_OFFSET,
- IS_E1HMF(bp));
+ bp->mf_mode);
REG_WR8(bp, BAR_USTRORM_INTMEM + USTORM_FUNCTION_MODE_OFFSET,
- IS_E1HMF(bp));
-
- REG_WR16(bp, BAR_XSTRORM_INTMEM + XSTORM_E1HOV_OFFSET(func),
- bp->e1hov);
+ bp->mf_mode);
}
- /* Init CQ ring mapping and aggregation size, the FW limit is 8 frags */
- max_agg_size = min_t(u32, (min_t(u32, 8, MAX_SKB_FRAGS) *
- SGE_PAGE_SIZE * PAGES_PER_SGE), 0xffff);
- for_each_queue(bp, i) {
- struct bnx2x_fastpath *fp = &bp->fp[i];
-
- REG_WR(bp, BAR_USTRORM_INTMEM +
- USTORM_CQE_PAGE_BASE_OFFSET(port, fp->cl_id),
- U64_LO(fp->rx_comp_mapping));
- REG_WR(bp, BAR_USTRORM_INTMEM +
- USTORM_CQE_PAGE_BASE_OFFSET(port, fp->cl_id) + 4,
- U64_HI(fp->rx_comp_mapping));
-
- /* Next page */
- REG_WR(bp, BAR_USTRORM_INTMEM +
- USTORM_CQE_PAGE_NEXT_OFFSET(port, fp->cl_id),
- U64_LO(fp->rx_comp_mapping + BCM_PAGE_SIZE));
+ /* Zero this manually as its initialization is
+ currently missing in the initTool */
+ for (i = 0; i < (USTORM_AGG_DATA_SIZE >> 2); i++)
REG_WR(bp, BAR_USTRORM_INTMEM +
- USTORM_CQE_PAGE_NEXT_OFFSET(port, fp->cl_id) + 4,
- U64_HI(fp->rx_comp_mapping + BCM_PAGE_SIZE));
-
- REG_WR16(bp, BAR_USTRORM_INTMEM +
- USTORM_MAX_AGG_SIZE_OFFSET(port, fp->cl_id),
- max_agg_size);
- }
-
- /* dropless flow control */
- if (CHIP_IS_E1H(bp)) {
- struct ustorm_eth_rx_pause_data_e1h rx_pause = {0};
-
- rx_pause.bd_thr_low = 250;
- rx_pause.cqe_thr_low = 250;
- rx_pause.cos = 1;
- rx_pause.sge_thr_low = 0;
- rx_pause.bd_thr_high = 350;
- rx_pause.cqe_thr_high = 350;
- rx_pause.sge_thr_high = 0;
-
- for_each_queue(bp, i) {
- struct bnx2x_fastpath *fp = &bp->fp[i];
-
- if (!fp->disable_tpa) {
- rx_pause.sge_thr_low = 150;
- rx_pause.sge_thr_high = 250;
- }
-
-
- offset = BAR_USTRORM_INTMEM +
- USTORM_ETH_RING_PAUSE_DATA_OFFSET(port,
- fp->cl_id);
- for (j = 0;
- j < sizeof(struct ustorm_eth_rx_pause_data_e1h)/4;
- j++)
- REG_WR(bp, offset + j*4,
- ((u32 *)&rx_pause)[j]);
- }
- }
-
- memset(&(bp->cmng), 0, sizeof(struct cmng_struct_per_port));
-
- /* Init rate shaping and fairness contexts */
- if (IS_E1HMF(bp)) {
- int vn;
-
- /* During init there is no active link
- Until link is up, set link rate to 10Gbps */
- bp->link_vars.line_speed = SPEED_10000;
- bnx2x_init_port_minmax(bp);
-
- if (!BP_NOMCP(bp))
- bp->mf_config =
- SHMEM_RD(bp, mf_cfg.func_mf_config[func].config);
- bnx2x_calc_vn_weight_sum(bp);
-
- for (vn = VN_0; vn < E1HVN_MAX; vn++)
- bnx2x_init_vn_minmax(bp, 2*vn + port);
-
- /* Enable rate shaping and fairness */
- bp->cmng.flags.cmng_enables |=
- CMNG_FLAGS_PER_PORT_RATE_SHAPING_VN;
-
- } else {
- /* rate shaping and fairness are disabled */
- DP(NETIF_MSG_IFUP,
- "single function mode minmax will be disabled\n");
+ USTORM_AGG_DATA_OFFSET + i * 4, 0);
+ if (CHIP_IS_E2(bp)) {
+ REG_WR8(bp, BAR_CSTRORM_INTMEM + CSTORM_IGU_MODE_OFFSET,
+ CHIP_INT_MODE_IS_BC(bp) ?
+ HC_IGU_BC_MODE : HC_IGU_NBC_MODE);
}
+}
-
- /* Store cmng structures to internal memory */
- if (bp->port.pmf)
- for (i = 0; i < sizeof(struct cmng_struct_per_port) / 4; i++)
- REG_WR(bp, BAR_XSTRORM_INTMEM +
- XSTORM_CMNG_PER_PORT_VARS_OFFSET(port) + i * 4,
- ((u32 *)(&bp->cmng))[i]);
+static void bnx2x_init_internal_port(struct bnx2x *bp)
+{
+ /* port */
}
static void bnx2x_init_internal(struct bnx2x *bp, u32 load_code)
{
switch (load_code) {
case FW_MSG_CODE_DRV_LOAD_COMMON:
+ case FW_MSG_CODE_DRV_LOAD_COMMON_CHIP:
bnx2x_init_internal_common(bp);
/* no break */
@@ -3389,7 +4259,8 @@ static void bnx2x_init_internal(struct bnx2x *bp, u32 load_code)
/* no break */
case FW_MSG_CODE_DRV_LOAD_FUNCTION:
- bnx2x_init_internal_func(bp);
+ /* internal memory per function is
+ initialized inside bnx2x_pf_init */
break;
default:
@@ -3398,43 +4269,63 @@ static void bnx2x_init_internal(struct bnx2x *bp, u32 load_code)
}
}
+static void bnx2x_init_fp_sb(struct bnx2x *bp, int fp_idx)
+{
+ struct bnx2x_fastpath *fp = &bp->fp[fp_idx];
+
+ fp->state = BNX2X_FP_STATE_CLOSED;
+
+ fp->index = fp->cid = fp_idx;
+ fp->cl_id = BP_L_ID(bp) + fp_idx;
+ fp->fw_sb_id = bp->base_fw_ndsb + fp->cl_id + CNIC_CONTEXT_USE;
+ fp->igu_sb_id = bp->igu_base_sb + fp_idx + CNIC_CONTEXT_USE;
+ /* qZone id equals to FW (per path) client id */
+ fp->cl_qzone_id = fp->cl_id +
+ BP_PORT(bp)*(CHIP_IS_E2(bp) ? ETH_MAX_RX_CLIENTS_E2 :
+ ETH_MAX_RX_CLIENTS_E1H);
+ /* init shortcut */
+ fp->ustorm_rx_prods_offset = CHIP_IS_E2(bp) ?
+ USTORM_RX_PRODS_E2_OFFSET(fp->cl_qzone_id) :
+ USTORM_RX_PRODS_E1X_OFFSET(BP_PORT(bp), fp->cl_id);
+ /* Setup SB indicies */
+ fp->rx_cons_sb = BNX2X_RX_SB_INDEX;
+ fp->tx_cons_sb = BNX2X_TX_SB_INDEX;
+
+ DP(NETIF_MSG_IFUP, "queue[%d]: bnx2x_init_sb(%p,%p) "
+ "cl_id %d fw_sb %d igu_sb %d\n",
+ fp_idx, bp, fp->status_blk.e1x_sb, fp->cl_id, fp->fw_sb_id,
+ fp->igu_sb_id);
+ bnx2x_init_sb(bp, fp->status_blk_mapping, BNX2X_VF_ID_INVALID, false,
+ fp->fw_sb_id, fp->igu_sb_id);
+
+ bnx2x_update_fpsb_idx(fp);
+}
+
void bnx2x_nic_init(struct bnx2x *bp, u32 load_code)
{
int i;
- for_each_queue(bp, i) {
- struct bnx2x_fastpath *fp = &bp->fp[i];
-
- fp->bp = bp;
- fp->state = BNX2X_FP_STATE_CLOSED;
- fp->index = i;
- fp->cl_id = BP_L_ID(bp) + i;
+ for_each_queue(bp, i)
+ bnx2x_init_fp_sb(bp, i);
#ifdef BCM_CNIC
- fp->sb_id = fp->cl_id + 1;
-#else
- fp->sb_id = fp->cl_id;
+
+ bnx2x_init_sb(bp, bp->cnic_sb_mapping,
+ BNX2X_VF_ID_INVALID, false,
+ CNIC_SB_ID(bp), CNIC_IGU_SB_ID(bp));
+
#endif
- DP(NETIF_MSG_IFUP,
- "queue[%d]: bnx2x_init_sb(%p,%p) cl_id %d sb %d\n",
- i, bp, fp->status_blk, fp->cl_id, fp->sb_id);
- bnx2x_init_sb(bp, fp->status_blk, fp->status_blk_mapping,
- fp->sb_id);
- bnx2x_update_fpsb_idx(fp);
- }
/* ensure status block indices were read */
rmb();
-
- bnx2x_init_def_sb(bp, bp->def_status_blk, bp->def_status_blk_mapping,
- DEF_SB_ID);
+ bnx2x_init_def_sb(bp);
bnx2x_update_dsb_idx(bp);
- bnx2x_update_coalesce(bp);
bnx2x_init_rx_rings(bp);
- bnx2x_init_tx_ring(bp);
+ bnx2x_init_tx_rings(bp);
bnx2x_init_sp_ring(bp);
- bnx2x_init_context(bp);
+ bnx2x_init_eq_ring(bp);
bnx2x_init_internal(bp, load_code);
+ bnx2x_pf_init(bp);
bnx2x_init_ind_table(bp);
bnx2x_stats_init(bp);
@@ -3495,7 +4386,6 @@ gunzip_nomem1:
static void bnx2x_gunzip_end(struct bnx2x *bp)
{
kfree(bp->strm->workspace);
-
kfree(bp->strm);
bp->strm = NULL;
@@ -3593,8 +4483,6 @@ static int bnx2x_int_mem_test(struct bnx2x *bp)
else
factor = 1;
- DP(NETIF_MSG_HW, "start part1\n");
-
/* Disable inputs of parser neighbor blocks */
REG_WR(bp, TSDM_REG_ENABLE_IN1, 0x0);
REG_WR(bp, TCM_REG_PRS_IFEN, 0x0);
@@ -3731,9 +4619,19 @@ static int bnx2x_int_mem_test(struct bnx2x *bp)
static void enable_blocks_attention(struct bnx2x *bp)
{
REG_WR(bp, PXP_REG_PXP_INT_MASK_0, 0);
- REG_WR(bp, PXP_REG_PXP_INT_MASK_1, 0);
+ if (CHIP_IS_E2(bp))
+ REG_WR(bp, PXP_REG_PXP_INT_MASK_1, 0x40);
+ else
+ REG_WR(bp, PXP_REG_PXP_INT_MASK_1, 0);
REG_WR(bp, DORQ_REG_DORQ_INT_MASK, 0);
REG_WR(bp, CFC_REG_CFC_INT_MASK, 0);
+ /*
+ * mask read length error interrupts in brb for parser
+ * (parsing unit and 'checksum and crc' unit)
+ * these errors are legal (PU reads fixed length and CAC can cause
+ * read length error on truncated packets)
+ */
+ REG_WR(bp, BRB1_REG_BRB1_INT_MASK, 0xFC00);
REG_WR(bp, QM_REG_QM_INT_MASK, 0);
REG_WR(bp, TM_REG_TM_INT_MASK, 0);
REG_WR(bp, XSDM_REG_XSDM_INT_MASK_0, 0);
@@ -3752,8 +4650,16 @@ static void enable_blocks_attention(struct bnx2x *bp)
REG_WR(bp, CCM_REG_CCM_INT_MASK, 0);
/* REG_WR(bp, CSEM_REG_CSEM_INT_MASK_0, 0); */
/* REG_WR(bp, CSEM_REG_CSEM_INT_MASK_1, 0); */
+
if (CHIP_REV_IS_FPGA(bp))
REG_WR(bp, PXP2_REG_PXP2_INT_MASK_0, 0x580000);
+ else if (CHIP_IS_E2(bp))
+ REG_WR(bp, PXP2_REG_PXP2_INT_MASK_0,
+ (PXP2_PXP2_INT_MASK_0_REG_PGL_CPL_OF
+ | PXP2_PXP2_INT_MASK_0_REG_PGL_CPL_AFT
+ | PXP2_PXP2_INT_MASK_0_REG_PGL_PCIE_ATTN
+ | PXP2_PXP2_INT_MASK_0_REG_PGL_READ_BLOCKED
+ | PXP2_PXP2_INT_MASK_0_REG_PGL_WRITE_BLOCKED));
else
REG_WR(bp, PXP2_REG_PXP2_INT_MASK_0, 0x480000);
REG_WR(bp, TSDM_REG_TSDM_INT_MASK_0, 0);
@@ -3771,42 +4677,41 @@ static const struct {
u32 addr;
u32 mask;
} bnx2x_parity_mask[] = {
- {PXP_REG_PXP_PRTY_MASK, 0xffffffff},
- {PXP2_REG_PXP2_PRTY_MASK_0, 0xffffffff},
- {PXP2_REG_PXP2_PRTY_MASK_1, 0xffffffff},
- {HC_REG_HC_PRTY_MASK, 0xffffffff},
- {MISC_REG_MISC_PRTY_MASK, 0xffffffff},
- {QM_REG_QM_PRTY_MASK, 0x0},
- {DORQ_REG_DORQ_PRTY_MASK, 0x0},
+ {PXP_REG_PXP_PRTY_MASK, 0x3ffffff},
+ {PXP2_REG_PXP2_PRTY_MASK_0, 0xffffffff},
+ {PXP2_REG_PXP2_PRTY_MASK_1, 0x7f},
+ {HC_REG_HC_PRTY_MASK, 0x7},
+ {MISC_REG_MISC_PRTY_MASK, 0x1},
+ {QM_REG_QM_PRTY_MASK, 0x0},
+ {DORQ_REG_DORQ_PRTY_MASK, 0x0},
{GRCBASE_UPB + PB_REG_PB_PRTY_MASK, 0x0},
{GRCBASE_XPB + PB_REG_PB_PRTY_MASK, 0x0},
- {SRC_REG_SRC_PRTY_MASK, 0x4}, /* bit 2 */
- {CDU_REG_CDU_PRTY_MASK, 0x0},
- {CFC_REG_CFC_PRTY_MASK, 0x0},
- {DBG_REG_DBG_PRTY_MASK, 0x0},
- {DMAE_REG_DMAE_PRTY_MASK, 0x0},
- {BRB1_REG_BRB1_PRTY_MASK, 0x0},
- {PRS_REG_PRS_PRTY_MASK, (1<<6)},/* bit 6 */
- {TSDM_REG_TSDM_PRTY_MASK, 0x18},/* bit 3,4 */
- {CSDM_REG_CSDM_PRTY_MASK, 0x8}, /* bit 3 */
- {USDM_REG_USDM_PRTY_MASK, 0x38},/* bit 3,4,5 */
- {XSDM_REG_XSDM_PRTY_MASK, 0x8}, /* bit 3 */
- {TSEM_REG_TSEM_PRTY_MASK_0, 0x0},
- {TSEM_REG_TSEM_PRTY_MASK_1, 0x0},
- {USEM_REG_USEM_PRTY_MASK_0, 0x0},
- {USEM_REG_USEM_PRTY_MASK_1, 0x0},
- {CSEM_REG_CSEM_PRTY_MASK_0, 0x0},
- {CSEM_REG_CSEM_PRTY_MASK_1, 0x0},
- {XSEM_REG_XSEM_PRTY_MASK_0, 0x0},
- {XSEM_REG_XSEM_PRTY_MASK_1, 0x0}
+ {SRC_REG_SRC_PRTY_MASK, 0x4}, /* bit 2 */
+ {CDU_REG_CDU_PRTY_MASK, 0x0},
+ {CFC_REG_CFC_PRTY_MASK, 0x0},
+ {DBG_REG_DBG_PRTY_MASK, 0x0},
+ {DMAE_REG_DMAE_PRTY_MASK, 0x0},
+ {BRB1_REG_BRB1_PRTY_MASK, 0x0},
+ {PRS_REG_PRS_PRTY_MASK, (1<<6)},/* bit 6 */
+ {TSDM_REG_TSDM_PRTY_MASK, 0x18}, /* bit 3,4 */
+ {CSDM_REG_CSDM_PRTY_MASK, 0x8}, /* bit 3 */
+ {USDM_REG_USDM_PRTY_MASK, 0x38}, /* bit 3,4,5 */
+ {XSDM_REG_XSDM_PRTY_MASK, 0x8}, /* bit 3 */
+ {TSEM_REG_TSEM_PRTY_MASK_0, 0x0},
+ {TSEM_REG_TSEM_PRTY_MASK_1, 0x0},
+ {USEM_REG_USEM_PRTY_MASK_0, 0x0},
+ {USEM_REG_USEM_PRTY_MASK_1, 0x0},
+ {CSEM_REG_CSEM_PRTY_MASK_0, 0x0},
+ {CSEM_REG_CSEM_PRTY_MASK_1, 0x0},
+ {XSEM_REG_XSEM_PRTY_MASK_0, 0x0},
+ {XSEM_REG_XSEM_PRTY_MASK_1, 0x0}
};
static void enable_blocks_parity(struct bnx2x *bp)
{
- int i, mask_arr_len =
- sizeof(bnx2x_parity_mask)/(sizeof(bnx2x_parity_mask[0]));
+ int i;
- for (i = 0; i < mask_arr_len; i++)
+ for (i = 0; i < ARRAY_SIZE(bnx2x_parity_mask); i++)
REG_WR(bp, bnx2x_parity_mask[i].addr,
bnx2x_parity_mask[i].mask);
}
@@ -3862,17 +4767,12 @@ static void bnx2x_setup_fan_failure_detection(struct bnx2x *bp)
*/
else if (val == SHARED_HW_CFG_FAN_FAILURE_PHY_TYPE)
for (port = PORT_0; port < PORT_MAX; port++) {
- u32 phy_type =
- SHMEM_RD(bp, dev_info.port_hw_config[port].
- external_phy_config) &
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK;
is_required |=
- ((phy_type ==
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101) ||
- (phy_type ==
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727) ||
- (phy_type ==
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481));
+ bnx2x_fan_failure_det_req(
+ bp,
+ bp->common.shmem_base,
+ bp->common.shmem2_base,
+ port);
}
DP(NETIF_MSG_HW, "fan detection setting: %d\n", is_required);
@@ -3896,26 +4796,97 @@ static void bnx2x_setup_fan_failure_detection(struct bnx2x *bp)
REG_WR(bp, MISC_REG_SPIO_EVENT_EN, val);
}
-static int bnx2x_init_common(struct bnx2x *bp)
+static void bnx2x_pretend_func(struct bnx2x *bp, u8 pretend_func_num)
+{
+ u32 offset = 0;
+
+ if (CHIP_IS_E1(bp))
+ return;
+ if (CHIP_IS_E1H(bp) && (pretend_func_num >= E1H_FUNC_MAX))
+ return;
+
+ switch (BP_ABS_FUNC(bp)) {
+ case 0:
+ offset = PXP2_REG_PGL_PRETEND_FUNC_F0;
+ break;
+ case 1:
+ offset = PXP2_REG_PGL_PRETEND_FUNC_F1;
+ break;
+ case 2:
+ offset = PXP2_REG_PGL_PRETEND_FUNC_F2;
+ break;
+ case 3:
+ offset = PXP2_REG_PGL_PRETEND_FUNC_F3;
+ break;
+ case 4:
+ offset = PXP2_REG_PGL_PRETEND_FUNC_F4;
+ break;
+ case 5:
+ offset = PXP2_REG_PGL_PRETEND_FUNC_F5;
+ break;
+ case 6:
+ offset = PXP2_REG_PGL_PRETEND_FUNC_F6;
+ break;
+ case 7:
+ offset = PXP2_REG_PGL_PRETEND_FUNC_F7;
+ break;
+ default:
+ return;
+ }
+
+ REG_WR(bp, offset, pretend_func_num);
+ REG_RD(bp, offset);
+ DP(NETIF_MSG_HW, "Pretending to func %d\n", pretend_func_num);
+}
+
+static void bnx2x_pf_disable(struct bnx2x *bp)
+{
+ u32 val = REG_RD(bp, IGU_REG_PF_CONFIGURATION);
+ val &= ~IGU_PF_CONF_FUNC_EN;
+
+ REG_WR(bp, IGU_REG_PF_CONFIGURATION, val);
+ REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER, 0);
+ REG_WR(bp, CFC_REG_WEAK_ENABLE_PF, 0);
+}
+
+static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code)
{
u32 val, i;
-#ifdef BCM_CNIC
- u32 wb_write[2];
-#endif
- DP(BNX2X_MSG_MCP, "starting common init func %d\n", BP_FUNC(bp));
+ DP(BNX2X_MSG_MCP, "starting common init func %d\n", BP_ABS_FUNC(bp));
bnx2x_reset_common(bp);
REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0xffffffff);
REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET, 0xfffc);
bnx2x_init_block(bp, MISC_BLOCK, COMMON_STAGE);
- if (CHIP_IS_E1H(bp))
- REG_WR(bp, MISC_REG_E1HMF_MODE, IS_E1HMF(bp));
+ if (!CHIP_IS_E1(bp))
+ REG_WR(bp, MISC_REG_E1HMF_MODE, IS_MF(bp));
- REG_WR(bp, MISC_REG_LCPLL_CTRL_REG_2, 0x100);
- msleep(30);
- REG_WR(bp, MISC_REG_LCPLL_CTRL_REG_2, 0x0);
+ if (CHIP_IS_E2(bp)) {
+ u8 fid;
+
+ /**
+ * 4-port mode or 2-port mode we need to turn of master-enable
+ * for everyone, after that, turn it back on for self.
+ * so, we disregard multi-function or not, and always disable
+ * for all functions on the given path, this means 0,2,4,6 for
+ * path 0 and 1,3,5,7 for path 1
+ */
+ for (fid = BP_PATH(bp); fid < E2_FUNC_MAX*2; fid += 2) {
+ if (fid == BP_ABS_FUNC(bp)) {
+ REG_WR(bp,
+ PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER,
+ 1);
+ continue;
+ }
+
+ bnx2x_pretend_func(bp, fid);
+ /* clear pf enable */
+ bnx2x_pf_disable(bp);
+ bnx2x_pretend_func(bp, BP_ABS_FUNC(bp));
+ }
+ }
bnx2x_init_block(bp, PXP_BLOCK, COMMON_STAGE);
if (CHIP_IS_E1(bp)) {
@@ -3943,12 +4914,7 @@ static int bnx2x_init_common(struct bnx2x *bp)
REG_WR(bp, PXP2_REG_RD_CDURD_SWAP_MODE, 1);
#endif
- REG_WR(bp, PXP2_REG_RQ_CDU_P_SIZE, 2);
-#ifdef BCM_CNIC
- REG_WR(bp, PXP2_REG_RQ_TM_P_SIZE, 5);
- REG_WR(bp, PXP2_REG_RQ_QM_P_SIZE, 5);
- REG_WR(bp, PXP2_REG_RQ_SRC_P_SIZE, 5);
-#endif
+ bnx2x_ilt_init_page_size(bp, INITOP_SET);
if (CHIP_REV_IS_FPGA(bp) && CHIP_IS_E1H(bp))
REG_WR(bp, PXP2_REG_PGL_TAGS_LIMIT, 0x1);
@@ -3967,9 +4933,65 @@ static int bnx2x_init_common(struct bnx2x *bp)
return -EBUSY;
}
+ /* Timers bug workaround E2 only. We need to set the entire ILT to
+ * have entries with value "0" and valid bit on.
+ * This needs to be done by the first PF that is loaded in a path
+ * (i.e. common phase)
+ */
+ if (CHIP_IS_E2(bp)) {
+ struct ilt_client_info ilt_cli;
+ struct bnx2x_ilt ilt;
+ memset(&ilt_cli, 0, sizeof(struct ilt_client_info));
+ memset(&ilt, 0, sizeof(struct bnx2x_ilt));
+
+ /* initalize dummy TM client */
+ ilt_cli.start = 0;
+ ilt_cli.end = ILT_NUM_PAGE_ENTRIES - 1;
+ ilt_cli.client_num = ILT_CLIENT_TM;
+
+ /* Step 1: set zeroes to all ilt page entries with valid bit on
+ * Step 2: set the timers first/last ilt entry to point
+ * to the entire range to prevent ILT range error for 3rd/4th
+ * vnic (this code assumes existance of the vnic)
+ *
+ * both steps performed by call to bnx2x_ilt_client_init_op()
+ * with dummy TM client
+ *
+ * we must use pretend since PXP2_REG_RQ_##blk##_FIRST_ILT
+ * and his brother are split registers
+ */
+ bnx2x_pretend_func(bp, (BP_PATH(bp) + 6));
+ bnx2x_ilt_client_init_op_ilt(bp, &ilt, &ilt_cli, INITOP_CLEAR);
+ bnx2x_pretend_func(bp, BP_ABS_FUNC(bp));
+
+ REG_WR(bp, PXP2_REG_RQ_DRAM_ALIGN, BNX2X_PXP_DRAM_ALIGN);
+ REG_WR(bp, PXP2_REG_RQ_DRAM_ALIGN_RD, BNX2X_PXP_DRAM_ALIGN);
+ REG_WR(bp, PXP2_REG_RQ_DRAM_ALIGN_SEL, 1);
+ }
+
+
REG_WR(bp, PXP2_REG_RQ_DISABLE_INPUTS, 0);
REG_WR(bp, PXP2_REG_RD_DISABLE_INPUTS, 0);
+ if (CHIP_IS_E2(bp)) {
+ int factor = CHIP_REV_IS_EMUL(bp) ? 1000 :
+ (CHIP_REV_IS_FPGA(bp) ? 400 : 0);
+ bnx2x_init_block(bp, PGLUE_B_BLOCK, COMMON_STAGE);
+
+ bnx2x_init_block(bp, ATC_BLOCK, COMMON_STAGE);
+
+ /* let the HW do it's magic ... */
+ do {
+ msleep(200);
+ val = REG_RD(bp, ATC_REG_ATC_INIT_DONE);
+ } while (factor-- && (val != 1));
+
+ if (val != 1) {
+ BNX2X_ERR("ATC_INIT failed\n");
+ return -EBUSY;
+ }
+ }
+
bnx2x_init_block(bp, DMAE_BLOCK, COMMON_STAGE);
/* clean the DMAE memory */
@@ -3988,20 +5010,12 @@ static int bnx2x_init_common(struct bnx2x *bp)
bnx2x_init_block(bp, QM_BLOCK, COMMON_STAGE);
-#ifdef BCM_CNIC
- wb_write[0] = 0;
- wb_write[1] = 0;
- for (i = 0; i < 64; i++) {
- REG_WR(bp, QM_REG_BASEADDR + i*4, 1024 * 4 * (i%16));
- bnx2x_init_ind_wr(bp, QM_REG_PTRTBL + i*8, wb_write, 2);
+ if (CHIP_MODE_IS_4_PORT(bp))
+ bnx2x_init_block(bp, QM_4PORT_BLOCK, COMMON_STAGE);
+
+ /* QM queues pointers table */
+ bnx2x_qm_init_ptr_table(bp, bp->qm_cid_count, INITOP_SET);
- if (CHIP_IS_E1H(bp)) {
- REG_WR(bp, QM_REG_BASEADDR_EXT_A + i*4, 1024*4*(i%16));
- bnx2x_init_ind_wr(bp, QM_REG_PTRTBL_EXT_A + i*8,
- wb_write, 2);
- }
- }
-#endif
/* soft reset pulse */
REG_WR(bp, QM_REG_SOFT_RESET, 1);
REG_WR(bp, QM_REG_SOFT_RESET, 0);
@@ -4011,21 +5025,35 @@ static int bnx2x_init_common(struct bnx2x *bp)
#endif
bnx2x_init_block(bp, DQ_BLOCK, COMMON_STAGE);
- REG_WR(bp, DORQ_REG_DPM_CID_OFST, BCM_PAGE_SHIFT);
+ REG_WR(bp, DORQ_REG_DPM_CID_OFST, BNX2X_DB_SHIFT);
+
if (!CHIP_REV_IS_SLOW(bp)) {
/* enable hw interrupt from doorbell Q */
REG_WR(bp, DORQ_REG_DORQ_INT_MASK, 0);
}
bnx2x_init_block(bp, BRB1_BLOCK, COMMON_STAGE);
+ if (CHIP_MODE_IS_4_PORT(bp)) {
+ REG_WR(bp, BRB1_REG_FULL_LB_XOFF_THRESHOLD, 248);
+ REG_WR(bp, BRB1_REG_FULL_LB_XON_THRESHOLD, 328);
+ }
+
bnx2x_init_block(bp, PRS_BLOCK, COMMON_STAGE);
REG_WR(bp, PRS_REG_A_PRSU_20, 0xf);
#ifndef BCM_CNIC
/* set NIC mode */
REG_WR(bp, PRS_REG_NIC_MODE, 1);
#endif
- if (CHIP_IS_E1H(bp))
- REG_WR(bp, PRS_REG_E1HOV_MODE, IS_E1HMF(bp));
+ if (!CHIP_IS_E1(bp))
+ REG_WR(bp, PRS_REG_E1HOV_MODE, IS_MF(bp));
+
+ if (CHIP_IS_E2(bp)) {
+ /* Bit-map indicating which L2 hdrs may appear after the
+ basic Ethernet header */
+ int has_ovlan = IS_MF(bp);
+ REG_WR(bp, PRS_REG_HDRS_AFTER_BASIC, (has_ovlan ? 7 : 6));
+ REG_WR(bp, PRS_REG_MUST_HAVE_HDRS, (has_ovlan ? 1 : 0));
+ }
bnx2x_init_block(bp, TSDM_BLOCK, COMMON_STAGE);
bnx2x_init_block(bp, CSDM_BLOCK, COMMON_STAGE);
@@ -4042,6 +5070,9 @@ static int bnx2x_init_common(struct bnx2x *bp)
bnx2x_init_block(bp, CSEM_BLOCK, COMMON_STAGE);
bnx2x_init_block(bp, XSEM_BLOCK, COMMON_STAGE);
+ if (CHIP_MODE_IS_4_PORT(bp))
+ bnx2x_init_block(bp, XSEM_4PORT_BLOCK, COMMON_STAGE);
+
/* sync semi rtc */
REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR,
0x80000000);
@@ -4052,9 +5083,16 @@ static int bnx2x_init_common(struct bnx2x *bp)
bnx2x_init_block(bp, XPB_BLOCK, COMMON_STAGE);
bnx2x_init_block(bp, PBF_BLOCK, COMMON_STAGE);
+ if (CHIP_IS_E2(bp)) {
+ int has_ovlan = IS_MF(bp);
+ REG_WR(bp, PBF_REG_HDRS_AFTER_BASIC, (has_ovlan ? 7 : 6));
+ REG_WR(bp, PBF_REG_MUST_HAVE_HDRS, (has_ovlan ? 1 : 0));
+ }
+
REG_WR(bp, SRC_REG_SOFT_RST, 1);
for (i = SRC_REG_KEYRSS0_0; i <= SRC_REG_KEYRSS1_9; i += 4)
REG_WR(bp, i, random32());
+
bnx2x_init_block(bp, SRCH_BLOCK, COMMON_STAGE);
#ifdef BCM_CNIC
REG_WR(bp, SRC_REG_KEYSEARCH_0, 0x63285672);
@@ -4089,6 +5127,11 @@ static int bnx2x_init_common(struct bnx2x *bp)
REG_WR(bp, CFC_REG_DEBUG0, 0x20020000);
bnx2x_init_block(bp, HC_BLOCK, COMMON_STAGE);
+
+ if (CHIP_IS_E2(bp) && BP_NOMCP(bp))
+ REG_WR(bp, IGU_REG_RESET_MEMORIES, 0x36);
+
+ bnx2x_init_block(bp, IGU_BLOCK, COMMON_STAGE);
bnx2x_init_block(bp, MISC_AEU_BLOCK, COMMON_STAGE);
bnx2x_init_block(bp, PXPCS_BLOCK, COMMON_STAGE);
@@ -4096,15 +5139,34 @@ static int bnx2x_init_common(struct bnx2x *bp)
REG_WR(bp, 0x2814, 0xffffffff);
REG_WR(bp, 0x3820, 0xffffffff);
+ if (CHIP_IS_E2(bp)) {
+ REG_WR(bp, PCICFG_OFFSET + PXPCS_TL_CONTROL_5,
+ (PXPCS_TL_CONTROL_5_ERR_UNSPPORT1 |
+ PXPCS_TL_CONTROL_5_ERR_UNSPPORT));
+ REG_WR(bp, PCICFG_OFFSET + PXPCS_TL_FUNC345_STAT,
+ (PXPCS_TL_FUNC345_STAT_ERR_UNSPPORT4 |
+ PXPCS_TL_FUNC345_STAT_ERR_UNSPPORT3 |
+ PXPCS_TL_FUNC345_STAT_ERR_UNSPPORT2));
+ REG_WR(bp, PCICFG_OFFSET + PXPCS_TL_FUNC678_STAT,
+ (PXPCS_TL_FUNC678_STAT_ERR_UNSPPORT7 |
+ PXPCS_TL_FUNC678_STAT_ERR_UNSPPORT6 |
+ PXPCS_TL_FUNC678_STAT_ERR_UNSPPORT5));
+ }
+
bnx2x_init_block(bp, EMAC0_BLOCK, COMMON_STAGE);
bnx2x_init_block(bp, EMAC1_BLOCK, COMMON_STAGE);
bnx2x_init_block(bp, DBU_BLOCK, COMMON_STAGE);
bnx2x_init_block(bp, DBG_BLOCK, COMMON_STAGE);
bnx2x_init_block(bp, NIG_BLOCK, COMMON_STAGE);
- if (CHIP_IS_E1H(bp)) {
- REG_WR(bp, NIG_REG_LLH_MF_MODE, IS_E1HMF(bp));
- REG_WR(bp, NIG_REG_LLH_E1HOV_MODE, IS_E1HMF(bp));
+ if (!CHIP_IS_E1(bp)) {
+ REG_WR(bp, NIG_REG_LLH_MF_MODE, IS_MF(bp));
+ REG_WR(bp, NIG_REG_LLH_E1HOV_MODE, IS_MF(bp));
+ }
+ if (CHIP_IS_E2(bp)) {
+ /* Bit-map indicating which L2 hdrs may appear after the
+ basic Ethernet header */
+ REG_WR(bp, NIG_REG_P0_HDRS_AFTER_BASIC, (IS_MF(bp) ? 7 : 6));
}
if (CHIP_REV_IS_SLOW(bp))
@@ -4128,28 +5190,22 @@ static int bnx2x_init_common(struct bnx2x *bp)
}
REG_WR(bp, CFC_REG_DEBUG0, 0);
- /* read NIG statistic
- to see if this is our first up since powerup */
- bnx2x_read_dmae(bp, NIG_REG_STAT2_BRB_OCTET, 2);
- val = *bnx2x_sp(bp, wb_data[0]);
+ if (CHIP_IS_E1(bp)) {
+ /* read NIG statistic
+ to see if this is our first up since powerup */
+ bnx2x_read_dmae(bp, NIG_REG_STAT2_BRB_OCTET, 2);
+ val = *bnx2x_sp(bp, wb_data[0]);
- /* do internal memory self test */
- if ((CHIP_IS_E1(bp)) && (val == 0) && bnx2x_int_mem_test(bp)) {
- BNX2X_ERR("internal mem self test failed\n");
- return -EBUSY;
+ /* do internal memory self test */
+ if ((val == 0) && bnx2x_int_mem_test(bp)) {
+ BNX2X_ERR("internal mem self test failed\n");
+ return -EBUSY;
+ }
}
- switch (XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config)) {
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
- bp->port.need_hw_lock = 1;
- break;
-
- default:
- break;
- }
+ bp->port.need_hw_lock = bnx2x_hw_lock_required(bp,
+ bp->common.shmem_base,
+ bp->common.shmem2_base);
bnx2x_setup_fan_failure_detection(bp);
@@ -4161,16 +5217,30 @@ static int bnx2x_init_common(struct bnx2x *bp)
enable_blocks_parity(bp);
if (!BP_NOMCP(bp)) {
- bnx2x_acquire_phy_lock(bp);
- bnx2x_common_init_phy(bp, bp->common.shmem_base);
- bnx2x_release_phy_lock(bp);
+ /* In E2 2-PORT mode, same ext phy is used for the two paths */
+ if ((load_code == FW_MSG_CODE_DRV_LOAD_COMMON_CHIP) ||
+ CHIP_IS_E1x(bp)) {
+ u32 shmem_base[2], shmem2_base[2];
+ shmem_base[0] = bp->common.shmem_base;
+ shmem2_base[0] = bp->common.shmem2_base;
+ if (CHIP_IS_E2(bp)) {
+ shmem_base[1] =
+ SHMEM2_RD(bp, other_shmem_base_addr);
+ shmem2_base[1] =
+ SHMEM2_RD(bp, other_shmem2_base_addr);
+ }
+ bnx2x_acquire_phy_lock(bp);
+ bnx2x_common_init_phy(bp, shmem_base, shmem2_base,
+ bp->common.chip_id);
+ bnx2x_release_phy_lock(bp);
+ }
} else
BNX2X_ERR("Bootcode is missing - can not initialize link\n");
return 0;
}
-static int bnx2x_init_port(struct bnx2x *bp)
+static int bnx2x_init_hw_port(struct bnx2x *bp)
{
int port = BP_PORT(bp);
int init_stage = port ? PORT1_STAGE : PORT0_STAGE;
@@ -4184,14 +5254,23 @@ static int bnx2x_init_port(struct bnx2x *bp)
bnx2x_init_block(bp, PXP_BLOCK, init_stage);
bnx2x_init_block(bp, PXP2_BLOCK, init_stage);
+ /* Timers bug workaround: disables the pf_master bit in pglue at
+ * common phase, we need to enable it here before any dmae access are
+ * attempted. Therefore we manually added the enable-master to the
+ * port phase (it also happens in the function phase)
+ */
+ if (CHIP_IS_E2(bp))
+ REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER, 1);
+
bnx2x_init_block(bp, TCM_BLOCK, init_stage);
bnx2x_init_block(bp, UCM_BLOCK, init_stage);
bnx2x_init_block(bp, CCM_BLOCK, init_stage);
bnx2x_init_block(bp, XCM_BLOCK, init_stage);
-#ifdef BCM_CNIC
- REG_WR(bp, QM_REG_CONNNUM_0 + port*4, 1024/16 - 1);
+ /* QM cid (connection) count */
+ bnx2x_qm_init_cid_count(bp, bp->qm_cid_count, INITOP_SET);
+#ifdef BCM_CNIC
bnx2x_init_block(bp, TIMERS_BLOCK, init_stage);
REG_WR(bp, TM_REG_LIN0_SCAN_TIME + port*4, 20);
REG_WR(bp, TM_REG_LIN0_MAX_ACTIVE_CID + port*4, 31);
@@ -4199,29 +5278,41 @@ static int bnx2x_init_port(struct bnx2x *bp)
bnx2x_init_block(bp, DQ_BLOCK, init_stage);
- bnx2x_init_block(bp, BRB1_BLOCK, init_stage);
- if (CHIP_REV_IS_SLOW(bp) && !CHIP_IS_E1H(bp)) {
- /* no pause for emulation and FPGA */
- low = 0;
- high = 513;
- } else {
- if (IS_E1HMF(bp))
- low = ((bp->flags & ONE_PORT_FLAG) ? 160 : 246);
- else if (bp->dev->mtu > 4096) {
- if (bp->flags & ONE_PORT_FLAG)
- low = 160;
- else {
- val = bp->dev->mtu;
- /* (24*1024 + val*4)/256 */
- low = 96 + (val/64) + ((val % 64) ? 1 : 0);
- }
- } else
- low = ((bp->flags & ONE_PORT_FLAG) ? 80 : 160);
- high = low + 56; /* 14*1024/256 */
+ if (CHIP_MODE_IS_4_PORT(bp))
+ bnx2x_init_block(bp, QM_4PORT_BLOCK, init_stage);
+
+ if (CHIP_IS_E1(bp) || CHIP_IS_E1H(bp)) {
+ bnx2x_init_block(bp, BRB1_BLOCK, init_stage);
+ if (CHIP_REV_IS_SLOW(bp) && CHIP_IS_E1(bp)) {
+ /* no pause for emulation and FPGA */
+ low = 0;
+ high = 513;
+ } else {
+ if (IS_MF(bp))
+ low = ((bp->flags & ONE_PORT_FLAG) ? 160 : 246);
+ else if (bp->dev->mtu > 4096) {
+ if (bp->flags & ONE_PORT_FLAG)
+ low = 160;
+ else {
+ val = bp->dev->mtu;
+ /* (24*1024 + val*4)/256 */
+ low = 96 + (val/64) +
+ ((val % 64) ? 1 : 0);
+ }
+ } else
+ low = ((bp->flags & ONE_PORT_FLAG) ? 80 : 160);
+ high = low + 56; /* 14*1024/256 */
+ }
+ REG_WR(bp, BRB1_REG_PAUSE_LOW_THRESHOLD_0 + port*4, low);
+ REG_WR(bp, BRB1_REG_PAUSE_HIGH_THRESHOLD_0 + port*4, high);
}
- REG_WR(bp, BRB1_REG_PAUSE_LOW_THRESHOLD_0 + port*4, low);
- REG_WR(bp, BRB1_REG_PAUSE_HIGH_THRESHOLD_0 + port*4, high);
+ if (CHIP_MODE_IS_4_PORT(bp)) {
+ REG_WR(bp, BRB1_REG_PAUSE_0_XOFF_THRESHOLD_0 + port*8, 248);
+ REG_WR(bp, BRB1_REG_PAUSE_0_XON_THRESHOLD_0 + port*8, 328);
+ REG_WR(bp, (BP_PORT(bp) ? BRB1_REG_MAC_GUARANTIED_1 :
+ BRB1_REG_MAC_GUARANTIED_0), 40);
+ }
bnx2x_init_block(bp, PRS_BLOCK, init_stage);
@@ -4234,24 +5325,28 @@ static int bnx2x_init_port(struct bnx2x *bp)
bnx2x_init_block(bp, USEM_BLOCK, init_stage);
bnx2x_init_block(bp, CSEM_BLOCK, init_stage);
bnx2x_init_block(bp, XSEM_BLOCK, init_stage);
+ if (CHIP_MODE_IS_4_PORT(bp))
+ bnx2x_init_block(bp, XSEM_4PORT_BLOCK, init_stage);
bnx2x_init_block(bp, UPB_BLOCK, init_stage);
bnx2x_init_block(bp, XPB_BLOCK, init_stage);
bnx2x_init_block(bp, PBF_BLOCK, init_stage);
- /* configure PBF to work without PAUSE mtu 9000 */
- REG_WR(bp, PBF_REG_P0_PAUSE_ENABLE + port*4, 0);
+ if (!CHIP_IS_E2(bp)) {
+ /* configure PBF to work without PAUSE mtu 9000 */
+ REG_WR(bp, PBF_REG_P0_PAUSE_ENABLE + port*4, 0);
- /* update threshold */
- REG_WR(bp, PBF_REG_P0_ARB_THRSH + port*4, (9040/16));
- /* update init credit */
- REG_WR(bp, PBF_REG_P0_INIT_CRD + port*4, (9040/16) + 553 - 22);
+ /* update threshold */
+ REG_WR(bp, PBF_REG_P0_ARB_THRSH + port*4, (9040/16));
+ /* update init credit */
+ REG_WR(bp, PBF_REG_P0_INIT_CRD + port*4, (9040/16) + 553 - 22);
- /* probe changes */
- REG_WR(bp, PBF_REG_INIT_P0 + port*4, 1);
- msleep(5);
- REG_WR(bp, PBF_REG_INIT_P0 + port*4, 0);
+ /* probe changes */
+ REG_WR(bp, PBF_REG_INIT_P0 + port*4, 1);
+ udelay(50);
+ REG_WR(bp, PBF_REG_INIT_P0 + port*4, 0);
+ }
#ifdef BCM_CNIC
bnx2x_init_block(bp, SRCH_BLOCK, init_stage);
@@ -4265,13 +5360,15 @@ static int bnx2x_init_port(struct bnx2x *bp)
}
bnx2x_init_block(bp, HC_BLOCK, init_stage);
+ bnx2x_init_block(bp, IGU_BLOCK, init_stage);
+
bnx2x_init_block(bp, MISC_AEU_BLOCK, init_stage);
/* init aeu_mask_attn_func_0/1:
* - SF mode: bits 3-7 are masked. only bits 0-2 are in use
* - MF mode: bit 3 is masked. bits 0-2 are in use as in SF
* bits 4-7 are used for "per vn group attention" */
REG_WR(bp, MISC_REG_AEU_MASK_ATTN_FUNC_0 + port*4,
- (IS_E1HMF(bp) ? 0xF7 : 0x7));
+ (IS_MF(bp) ? 0xF7 : 0x7));
bnx2x_init_block(bp, PXPCS_BLOCK, init_stage);
bnx2x_init_block(bp, EMAC0_BLOCK, init_stage);
@@ -4283,11 +5380,25 @@ static int bnx2x_init_port(struct bnx2x *bp)
REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4, 1);
- if (CHIP_IS_E1H(bp)) {
- /* 0x2 disable e1hov, 0x1 enable */
+ if (!CHIP_IS_E1(bp)) {
+ /* 0x2 disable mf_ov, 0x1 enable */
REG_WR(bp, NIG_REG_LLH0_BRB1_DRV_MASK_MF + port*4,
- (IS_E1HMF(bp) ? 0x1 : 0x2));
+ (IS_MF(bp) ? 0x1 : 0x2));
+
+ if (CHIP_IS_E2(bp)) {
+ val = 0;
+ switch (bp->mf_mode) {
+ case MULTI_FUNCTION_SD:
+ val = 1;
+ break;
+ case MULTI_FUNCTION_SI:
+ val = 2;
+ break;
+ }
+ REG_WR(bp, (BP_PORT(bp) ? NIG_REG_LLH1_CLS_TYPE :
+ NIG_REG_LLH0_CLS_TYPE), val);
+ }
{
REG_WR(bp, NIG_REG_LLFC_ENABLE_0 + port*4, 0);
REG_WR(bp, NIG_REG_LLFC_OUT_EN_0 + port*4, 0);
@@ -4297,199 +5408,339 @@ static int bnx2x_init_port(struct bnx2x *bp)
bnx2x_init_block(bp, MCP_BLOCK, init_stage);
bnx2x_init_block(bp, DMAE_BLOCK, init_stage);
-
- switch (XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config)) {
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
- {
- u32 swap_val, swap_override, aeu_gpio_mask, offset;
-
- bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3,
- MISC_REGISTERS_GPIO_INPUT_HI_Z, port);
-
- /* The GPIO should be swapped if the swap register is
- set and active */
- swap_val = REG_RD(bp, NIG_REG_PORT_SWAP);
- swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE);
-
- /* Select function upon port-swap configuration */
- if (port == 0) {
- offset = MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0;
- aeu_gpio_mask = (swap_val && swap_override) ?
- AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_1 :
- AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_0;
- } else {
- offset = MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0;
- aeu_gpio_mask = (swap_val && swap_override) ?
- AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_0 :
- AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_1;
- }
- val = REG_RD(bp, offset);
- /* add GPIO3 to group */
- val |= aeu_gpio_mask;
- REG_WR(bp, offset, val);
- }
- bp->port.need_hw_lock = 1;
- break;
-
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
- bp->port.need_hw_lock = 1;
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
- /* add SPIO 5 to group 0 */
- {
+ bp->port.need_hw_lock = bnx2x_hw_lock_required(bp,
+ bp->common.shmem_base,
+ bp->common.shmem2_base);
+ if (bnx2x_fan_failure_det_req(bp, bp->common.shmem_base,
+ bp->common.shmem2_base, port)) {
u32 reg_addr = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 :
MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0);
val = REG_RD(bp, reg_addr);
val |= AEU_INPUTS_ATTN_BITS_SPIO5;
REG_WR(bp, reg_addr, val);
- }
- break;
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
- bp->port.need_hw_lock = 1;
- break;
- default:
- break;
}
-
bnx2x__link_reset(bp);
return 0;
}
-#define ILT_PER_FUNC (768/2)
-#define FUNC_ILT_BASE(func) (func * ILT_PER_FUNC)
-/* the phys address is shifted right 12 bits and has an added
- 1=valid bit added to the 53rd bit
- then since this is a wide register(TM)
- we split it into two 32 bit writes
- */
-#define ONCHIP_ADDR1(x) ((u32)(((u64)x >> 12) & 0xFFFFFFFF))
-#define ONCHIP_ADDR2(x) ((u32)((1 << 20) | ((u64)x >> 44)))
-#define PXP_ONE_ILT(x) (((x) << 10) | x)
-#define PXP_ILT_RANGE(f, l) (((l) << 10) | f)
-
-#ifdef BCM_CNIC
-#define CNIC_ILT_LINES 127
-#define CNIC_CTX_PER_ILT 16
-#else
-#define CNIC_ILT_LINES 0
-#endif
-
static void bnx2x_ilt_wr(struct bnx2x *bp, u32 index, dma_addr_t addr)
{
int reg;
- if (CHIP_IS_E1H(bp))
- reg = PXP2_REG_RQ_ONCHIP_AT_B0 + index*8;
- else /* E1 */
+ if (CHIP_IS_E1(bp))
reg = PXP2_REG_RQ_ONCHIP_AT + index*8;
+ else
+ reg = PXP2_REG_RQ_ONCHIP_AT_B0 + index*8;
bnx2x_wb_wr(bp, reg, ONCHIP_ADDR1(addr), ONCHIP_ADDR2(addr));
}
-static int bnx2x_init_func(struct bnx2x *bp)
+static inline void bnx2x_igu_clear_sb(struct bnx2x *bp, u8 idu_sb_id)
+{
+ bnx2x_igu_clear_sb_gen(bp, idu_sb_id, true /*PF*/);
+}
+
+static inline void bnx2x_clear_func_ilt(struct bnx2x *bp, u32 func)
+{
+ u32 i, base = FUNC_ILT_BASE(func);
+ for (i = base; i < base + ILT_PER_FUNC; i++)
+ bnx2x_ilt_wr(bp, i, 0);
+}
+
+static int bnx2x_init_hw_func(struct bnx2x *bp)
{
int port = BP_PORT(bp);
int func = BP_FUNC(bp);
+ struct bnx2x_ilt *ilt = BP_ILT(bp);
+ u16 cdu_ilt_start;
u32 addr, val;
- int i;
+ u32 main_mem_base, main_mem_size, main_mem_prty_clr;
+ int i, main_mem_width;
DP(BNX2X_MSG_MCP, "starting func init func %d\n", func);
/* set MSI reconfigure capability */
- addr = (port ? HC_REG_CONFIG_1 : HC_REG_CONFIG_0);
- val = REG_RD(bp, addr);
- val |= HC_CONFIG_0_REG_MSI_ATTN_EN_0;
- REG_WR(bp, addr, val);
+ if (bp->common.int_block == INT_BLOCK_HC) {
+ addr = (port ? HC_REG_CONFIG_1 : HC_REG_CONFIG_0);
+ val = REG_RD(bp, addr);
+ val |= HC_CONFIG_0_REG_MSI_ATTN_EN_0;
+ REG_WR(bp, addr, val);
+ }
- i = FUNC_ILT_BASE(func);
+ ilt = BP_ILT(bp);
+ cdu_ilt_start = ilt->clients[ILT_CLIENT_CDU].start;
- bnx2x_ilt_wr(bp, i, bnx2x_sp_mapping(bp, context));
- if (CHIP_IS_E1H(bp)) {
- REG_WR(bp, PXP2_REG_RQ_CDU_FIRST_ILT, i);
- REG_WR(bp, PXP2_REG_RQ_CDU_LAST_ILT, i + CNIC_ILT_LINES);
- } else /* E1 */
- REG_WR(bp, PXP2_REG_PSWRQ_CDU0_L2P + func*4,
- PXP_ILT_RANGE(i, i + CNIC_ILT_LINES));
+ for (i = 0; i < L2_ILT_LINES(bp); i++) {
+ ilt->lines[cdu_ilt_start + i].page =
+ bp->context.vcxt + (ILT_PAGE_CIDS * i);
+ ilt->lines[cdu_ilt_start + i].page_mapping =
+ bp->context.cxt_mapping + (CDU_ILT_PAGE_SZ * i);
+ /* cdu ilt pages are allocated manually so there's no need to
+ set the size */
+ }
+ bnx2x_ilt_init_op(bp, INITOP_SET);
#ifdef BCM_CNIC
- i += 1 + CNIC_ILT_LINES;
- bnx2x_ilt_wr(bp, i, bp->timers_mapping);
- if (CHIP_IS_E1(bp))
- REG_WR(bp, PXP2_REG_PSWRQ_TM0_L2P + func*4, PXP_ONE_ILT(i));
- else {
- REG_WR(bp, PXP2_REG_RQ_TM_FIRST_ILT, i);
- REG_WR(bp, PXP2_REG_RQ_TM_LAST_ILT, i);
- }
+ bnx2x_src_init_t2(bp, bp->t2, bp->t2_mapping, SRC_CONN_NUM);
- i++;
- bnx2x_ilt_wr(bp, i, bp->qm_mapping);
- if (CHIP_IS_E1(bp))
- REG_WR(bp, PXP2_REG_PSWRQ_QM0_L2P + func*4, PXP_ONE_ILT(i));
- else {
- REG_WR(bp, PXP2_REG_RQ_QM_FIRST_ILT, i);
- REG_WR(bp, PXP2_REG_RQ_QM_LAST_ILT, i);
+ /* T1 hash bits value determines the T1 number of entries */
+ REG_WR(bp, SRC_REG_NUMBER_HASH_BITS0 + port*4, SRC_HASH_BITS);
+#endif
+
+#ifndef BCM_CNIC
+ /* set NIC mode */
+ REG_WR(bp, PRS_REG_NIC_MODE, 1);
+#endif /* BCM_CNIC */
+
+ if (CHIP_IS_E2(bp)) {
+ u32 pf_conf = IGU_PF_CONF_FUNC_EN;
+
+ /* Turn on a single ISR mode in IGU if driver is going to use
+ * INT#x or MSI
+ */
+ if (!(bp->flags & USING_MSIX_FLAG))
+ pf_conf |= IGU_PF_CONF_SINGLE_ISR_EN;
+ /*
+ * Timers workaround bug: function init part.
+ * Need to wait 20msec after initializing ILT,
+ * needed to make sure there are no requests in
+ * one of the PXP internal queues with "old" ILT addresses
+ */
+ msleep(20);
+ /*
+ * Master enable - Due to WB DMAE writes performed before this
+ * register is re-initialized as part of the regular function
+ * init
+ */
+ REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER, 1);
+ /* Enable the function in IGU */
+ REG_WR(bp, IGU_REG_PF_CONFIGURATION, pf_conf);
}
- i++;
- bnx2x_ilt_wr(bp, i, bp->t1_mapping);
- if (CHIP_IS_E1(bp))
- REG_WR(bp, PXP2_REG_PSWRQ_SRC0_L2P + func*4, PXP_ONE_ILT(i));
- else {
- REG_WR(bp, PXP2_REG_RQ_SRC_FIRST_ILT, i);
- REG_WR(bp, PXP2_REG_RQ_SRC_LAST_ILT, i);
+ bp->dmae_ready = 1;
+
+ bnx2x_init_block(bp, PGLUE_B_BLOCK, FUNC0_STAGE + func);
+
+ if (CHIP_IS_E2(bp))
+ REG_WR(bp, PGLUE_B_REG_WAS_ERROR_PF_7_0_CLR, func);
+
+ bnx2x_init_block(bp, MISC_BLOCK, FUNC0_STAGE + func);
+ bnx2x_init_block(bp, TCM_BLOCK, FUNC0_STAGE + func);
+ bnx2x_init_block(bp, UCM_BLOCK, FUNC0_STAGE + func);
+ bnx2x_init_block(bp, CCM_BLOCK, FUNC0_STAGE + func);
+ bnx2x_init_block(bp, XCM_BLOCK, FUNC0_STAGE + func);
+ bnx2x_init_block(bp, TSEM_BLOCK, FUNC0_STAGE + func);
+ bnx2x_init_block(bp, USEM_BLOCK, FUNC0_STAGE + func);
+ bnx2x_init_block(bp, CSEM_BLOCK, FUNC0_STAGE + func);
+ bnx2x_init_block(bp, XSEM_BLOCK, FUNC0_STAGE + func);
+
+ if (CHIP_IS_E2(bp)) {
+ REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_PATH_ID_OFFSET,
+ BP_PATH(bp));
+ REG_WR(bp, BAR_CSTRORM_INTMEM + CSTORM_PATH_ID_OFFSET,
+ BP_PATH(bp));
}
- /* tell the searcher where the T2 table is */
- REG_WR(bp, SRC_REG_COUNTFREE0 + port*4, 16*1024/64);
+ if (CHIP_MODE_IS_4_PORT(bp))
+ bnx2x_init_block(bp, XSEM_4PORT_BLOCK, FUNC0_STAGE + func);
- bnx2x_wb_wr(bp, SRC_REG_FIRSTFREE0 + port*16,
- U64_LO(bp->t2_mapping), U64_HI(bp->t2_mapping));
+ if (CHIP_IS_E2(bp))
+ REG_WR(bp, QM_REG_PF_EN, 1);
- bnx2x_wb_wr(bp, SRC_REG_LASTFREE0 + port*16,
- U64_LO((u64)bp->t2_mapping + 16*1024 - 64),
- U64_HI((u64)bp->t2_mapping + 16*1024 - 64));
+ bnx2x_init_block(bp, QM_BLOCK, FUNC0_STAGE + func);
- REG_WR(bp, SRC_REG_NUMBER_HASH_BITS0 + port*4, 10);
-#endif
+ if (CHIP_MODE_IS_4_PORT(bp))
+ bnx2x_init_block(bp, QM_4PORT_BLOCK, FUNC0_STAGE + func);
+
+ bnx2x_init_block(bp, TIMERS_BLOCK, FUNC0_STAGE + func);
+ bnx2x_init_block(bp, DQ_BLOCK, FUNC0_STAGE + func);
+ bnx2x_init_block(bp, BRB1_BLOCK, FUNC0_STAGE + func);
+ bnx2x_init_block(bp, PRS_BLOCK, FUNC0_STAGE + func);
+ bnx2x_init_block(bp, TSDM_BLOCK, FUNC0_STAGE + func);
+ bnx2x_init_block(bp, CSDM_BLOCK, FUNC0_STAGE + func);
+ bnx2x_init_block(bp, USDM_BLOCK, FUNC0_STAGE + func);
+ bnx2x_init_block(bp, XSDM_BLOCK, FUNC0_STAGE + func);
+ bnx2x_init_block(bp, UPB_BLOCK, FUNC0_STAGE + func);
+ bnx2x_init_block(bp, XPB_BLOCK, FUNC0_STAGE + func);
+ bnx2x_init_block(bp, PBF_BLOCK, FUNC0_STAGE + func);
+ if (CHIP_IS_E2(bp))
+ REG_WR(bp, PBF_REG_DISABLE_PF, 0);
+
+ bnx2x_init_block(bp, CDU_BLOCK, FUNC0_STAGE + func);
- if (CHIP_IS_E1H(bp)) {
- bnx2x_init_block(bp, MISC_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, TCM_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, UCM_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, CCM_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, XCM_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, TSEM_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, USEM_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, CSEM_BLOCK, FUNC0_STAGE + func);
- bnx2x_init_block(bp, XSEM_BLOCK, FUNC0_STAGE + func);
+ bnx2x_init_block(bp, CFC_BLOCK, FUNC0_STAGE + func);
+ if (CHIP_IS_E2(bp))
+ REG_WR(bp, CFC_REG_WEAK_ENABLE_PF, 1);
+
+ if (IS_MF(bp)) {
REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 1);
- REG_WR(bp, NIG_REG_LLH0_FUNC_VLAN_ID + port*8, bp->e1hov);
+ REG_WR(bp, NIG_REG_LLH0_FUNC_VLAN_ID + port*8, bp->mf_ov);
}
+ bnx2x_init_block(bp, MISC_AEU_BLOCK, FUNC0_STAGE + func);
+
/* HC init per function */
- if (CHIP_IS_E1H(bp)) {
+ if (bp->common.int_block == INT_BLOCK_HC) {
+ if (CHIP_IS_E1H(bp)) {
+ REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_12 + func*4, 0);
+
+ REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, 0);
+ REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, 0);
+ }
+ bnx2x_init_block(bp, HC_BLOCK, FUNC0_STAGE + func);
+
+ } else {
+ int num_segs, sb_idx, prod_offset;
+
REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_12 + func*4, 0);
- REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, 0);
- REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, 0);
+ if (CHIP_IS_E2(bp)) {
+ REG_WR(bp, IGU_REG_LEADING_EDGE_LATCH, 0);
+ REG_WR(bp, IGU_REG_TRAILING_EDGE_LATCH, 0);
+ }
+
+ bnx2x_init_block(bp, IGU_BLOCK, FUNC0_STAGE + func);
+
+ if (CHIP_IS_E2(bp)) {
+ int dsb_idx = 0;
+ /**
+ * Producer memory:
+ * E2 mode: address 0-135 match to the mapping memory;
+ * 136 - PF0 default prod; 137 - PF1 default prod;
+ * 138 - PF2 default prod; 139 - PF3 default prod;
+ * 140 - PF0 attn prod; 141 - PF1 attn prod;
+ * 142 - PF2 attn prod; 143 - PF3 attn prod;
+ * 144-147 reserved.
+ *
+ * E1.5 mode - In backward compatible mode;
+ * for non default SB; each even line in the memory
+ * holds the U producer and each odd line hold
+ * the C producer. The first 128 producers are for
+ * NDSB (PF0 - 0-31; PF1 - 32-63 and so on). The last 20
+ * producers are for the DSB for each PF.
+ * Each PF has five segments: (the order inside each
+ * segment is PF0; PF1; PF2; PF3) - 128-131 U prods;
+ * 132-135 C prods; 136-139 X prods; 140-143 T prods;
+ * 144-147 attn prods;
+ */
+ /* non-default-status-blocks */
+ num_segs = CHIP_INT_MODE_IS_BC(bp) ?
+ IGU_BC_NDSB_NUM_SEGS : IGU_NORM_NDSB_NUM_SEGS;
+ for (sb_idx = 0; sb_idx < bp->igu_sb_cnt; sb_idx++) {
+ prod_offset = (bp->igu_base_sb + sb_idx) *
+ num_segs;
+
+ for (i = 0; i < num_segs; i++) {
+ addr = IGU_REG_PROD_CONS_MEMORY +
+ (prod_offset + i) * 4;
+ REG_WR(bp, addr, 0);
+ }
+ /* send consumer update with value 0 */
+ bnx2x_ack_sb(bp, bp->igu_base_sb + sb_idx,
+ USTORM_ID, 0, IGU_INT_NOP, 1);
+ bnx2x_igu_clear_sb(bp,
+ bp->igu_base_sb + sb_idx);
+ }
+
+ /* default-status-blocks */
+ num_segs = CHIP_INT_MODE_IS_BC(bp) ?
+ IGU_BC_DSB_NUM_SEGS : IGU_NORM_DSB_NUM_SEGS;
+
+ if (CHIP_MODE_IS_4_PORT(bp))
+ dsb_idx = BP_FUNC(bp);
+ else
+ dsb_idx = BP_E1HVN(bp);
+
+ prod_offset = (CHIP_INT_MODE_IS_BC(bp) ?
+ IGU_BC_BASE_DSB_PROD + dsb_idx :
+ IGU_NORM_BASE_DSB_PROD + dsb_idx);
+
+ for (i = 0; i < (num_segs * E1HVN_MAX);
+ i += E1HVN_MAX) {
+ addr = IGU_REG_PROD_CONS_MEMORY +
+ (prod_offset + i)*4;
+ REG_WR(bp, addr, 0);
+ }
+ /* send consumer update with 0 */
+ if (CHIP_INT_MODE_IS_BC(bp)) {
+ bnx2x_ack_sb(bp, bp->igu_dsb_id,
+ USTORM_ID, 0, IGU_INT_NOP, 1);
+ bnx2x_ack_sb(bp, bp->igu_dsb_id,
+ CSTORM_ID, 0, IGU_INT_NOP, 1);
+ bnx2x_ack_sb(bp, bp->igu_dsb_id,
+ XSTORM_ID, 0, IGU_INT_NOP, 1);
+ bnx2x_ack_sb(bp, bp->igu_dsb_id,
+ TSTORM_ID, 0, IGU_INT_NOP, 1);
+ bnx2x_ack_sb(bp, bp->igu_dsb_id,
+ ATTENTION_ID, 0, IGU_INT_NOP, 1);
+ } else {
+ bnx2x_ack_sb(bp, bp->igu_dsb_id,
+ USTORM_ID, 0, IGU_INT_NOP, 1);
+ bnx2x_ack_sb(bp, bp->igu_dsb_id,
+ ATTENTION_ID, 0, IGU_INT_NOP, 1);
+ }
+ bnx2x_igu_clear_sb(bp, bp->igu_dsb_id);
+
+ /* !!! these should become driver const once
+ rf-tool supports split-68 const */
+ REG_WR(bp, IGU_REG_SB_INT_BEFORE_MASK_LSB, 0);
+ REG_WR(bp, IGU_REG_SB_INT_BEFORE_MASK_MSB, 0);
+ REG_WR(bp, IGU_REG_SB_MASK_LSB, 0);
+ REG_WR(bp, IGU_REG_SB_MASK_MSB, 0);
+ REG_WR(bp, IGU_REG_PBA_STATUS_LSB, 0);
+ REG_WR(bp, IGU_REG_PBA_STATUS_MSB, 0);
+ }
}
- bnx2x_init_block(bp, HC_BLOCK, FUNC0_STAGE + func);
/* Reset PCIE errors for debug */
REG_WR(bp, 0x2114, 0xffffffff);
REG_WR(bp, 0x2120, 0xffffffff);
+ bnx2x_init_block(bp, EMAC0_BLOCK, FUNC0_STAGE + func);
+ bnx2x_init_block(bp, EMAC1_BLOCK, FUNC0_STAGE + func);
+ bnx2x_init_block(bp, DBU_BLOCK, FUNC0_STAGE + func);
+ bnx2x_init_block(bp, DBG_BLOCK, FUNC0_STAGE + func);
+ bnx2x_init_block(bp, MCP_BLOCK, FUNC0_STAGE + func);
+ bnx2x_init_block(bp, DMAE_BLOCK, FUNC0_STAGE + func);
+
+ if (CHIP_IS_E1x(bp)) {
+ main_mem_size = HC_REG_MAIN_MEMORY_SIZE / 2; /*dwords*/
+ main_mem_base = HC_REG_MAIN_MEMORY +
+ BP_PORT(bp) * (main_mem_size * 4);
+ main_mem_prty_clr = HC_REG_HC_PRTY_STS_CLR;
+ main_mem_width = 8;
+
+ val = REG_RD(bp, main_mem_prty_clr);
+ if (val)
+ DP(BNX2X_MSG_MCP, "Hmmm... Parity errors in HC "
+ "block during "
+ "function init (0x%x)!\n", val);
+
+ /* Clear "false" parity errors in MSI-X table */
+ for (i = main_mem_base;
+ i < main_mem_base + main_mem_size * 4;
+ i += main_mem_width) {
+ bnx2x_read_dmae(bp, i, main_mem_width / 4);
+ bnx2x_write_dmae(bp, bnx2x_sp_mapping(bp, wb_data),
+ i, main_mem_width / 4);
+ }
+ /* Clear HC parity attention */
+ REG_RD(bp, main_mem_prty_clr);
+ }
+
+ bnx2x_phy_probe(&bp->link_params);
+
return 0;
}
int bnx2x_init_hw(struct bnx2x *bp, u32 load_code)
{
- int i, rc = 0;
+ int rc = 0;
DP(BNX2X_MSG_MCP, "function %d load_code %x\n",
- BP_FUNC(bp), load_code);
+ BP_ABS_FUNC(bp), load_code);
bp->dmae_ready = 0;
mutex_init(&bp->dmae_mutex);
@@ -4499,21 +5750,20 @@ int bnx2x_init_hw(struct bnx2x *bp, u32 load_code)
switch (load_code) {
case FW_MSG_CODE_DRV_LOAD_COMMON:
- rc = bnx2x_init_common(bp);
+ case FW_MSG_CODE_DRV_LOAD_COMMON_CHIP:
+ rc = bnx2x_init_hw_common(bp, load_code);
if (rc)
goto init_hw_err;
/* no break */
case FW_MSG_CODE_DRV_LOAD_PORT:
- bp->dmae_ready = 1;
- rc = bnx2x_init_port(bp);
+ rc = bnx2x_init_hw_port(bp);
if (rc)
goto init_hw_err;
/* no break */
case FW_MSG_CODE_DRV_LOAD_FUNCTION:
- bp->dmae_ready = 1;
- rc = bnx2x_init_func(bp);
+ rc = bnx2x_init_hw_func(bp);
if (rc)
goto init_hw_err;
break;
@@ -4524,22 +5774,14 @@ int bnx2x_init_hw(struct bnx2x *bp, u32 load_code)
}
if (!BP_NOMCP(bp)) {
- int func = BP_FUNC(bp);
+ int mb_idx = BP_FW_MB_IDX(bp);
bp->fw_drv_pulse_wr_seq =
- (SHMEM_RD(bp, func_mb[func].drv_pulse_mb) &
+ (SHMEM_RD(bp, func_mb[mb_idx].drv_pulse_mb) &
DRV_PULSE_SEQ_MASK);
DP(BNX2X_MSG_MCP, "drv_pulse 0x%x\n", bp->fw_drv_pulse_wr_seq);
}
- /* this needs to be done before gunzip end */
- bnx2x_zero_def_sb(bp);
- for_each_queue(bp, i)
- bnx2x_zero_sb(bp, BP_L_ID(bp) + i);
-#ifdef BCM_CNIC
- bnx2x_zero_sb(bp, BP_L_ID(bp) + i);
-#endif
-
init_hw_err:
bnx2x_gunzip_end(bp);
@@ -4552,7 +5794,7 @@ void bnx2x_free_mem(struct bnx2x *bp)
#define BNX2X_PCI_FREE(x, y, size) \
do { \
if (x) { \
- dma_free_coherent(&bp->pdev->dev, size, x, y); \
+ dma_free_coherent(&bp->pdev->dev, size, (void *)x, y); \
x = NULL; \
y = 0; \
} \
@@ -4561,7 +5803,7 @@ void bnx2x_free_mem(struct bnx2x *bp)
#define BNX2X_FREE(x) \
do { \
if (x) { \
- vfree(x); \
+ kfree((void *)x); \
x = NULL; \
} \
} while (0)
@@ -4571,11 +5813,15 @@ void bnx2x_free_mem(struct bnx2x *bp)
/* fastpath */
/* Common */
for_each_queue(bp, i) {
-
/* status blocks */
- BNX2X_PCI_FREE(bnx2x_fp(bp, i, status_blk),
- bnx2x_fp(bp, i, status_blk_mapping),
- sizeof(struct host_status_block));
+ if (CHIP_IS_E2(bp))
+ BNX2X_PCI_FREE(bnx2x_fp(bp, i, status_blk.e2_sb),
+ bnx2x_fp(bp, i, status_blk_mapping),
+ sizeof(struct host_hc_status_block_e2));
+ else
+ BNX2X_PCI_FREE(bnx2x_fp(bp, i, status_blk.e1x_sb),
+ bnx2x_fp(bp, i, status_blk_mapping),
+ sizeof(struct host_hc_status_block_e1x));
}
/* Rx */
for_each_queue(bp, i) {
@@ -4609,28 +5855,56 @@ void bnx2x_free_mem(struct bnx2x *bp)
/* end of fastpath */
BNX2X_PCI_FREE(bp->def_status_blk, bp->def_status_blk_mapping,
- sizeof(struct host_def_status_block));
+ sizeof(struct host_sp_status_block));
BNX2X_PCI_FREE(bp->slowpath, bp->slowpath_mapping,
sizeof(struct bnx2x_slowpath));
+ BNX2X_PCI_FREE(bp->context.vcxt, bp->context.cxt_mapping,
+ bp->context.size);
+
+ bnx2x_ilt_mem_op(bp, ILT_MEMOP_FREE);
+
+ BNX2X_FREE(bp->ilt->lines);
+
#ifdef BCM_CNIC
- BNX2X_PCI_FREE(bp->t1, bp->t1_mapping, 64*1024);
- BNX2X_PCI_FREE(bp->t2, bp->t2_mapping, 16*1024);
- BNX2X_PCI_FREE(bp->timers, bp->timers_mapping, 8*1024);
- BNX2X_PCI_FREE(bp->qm, bp->qm_mapping, 128*1024);
- BNX2X_PCI_FREE(bp->cnic_sb, bp->cnic_sb_mapping,
- sizeof(struct host_status_block));
+ if (CHIP_IS_E2(bp))
+ BNX2X_PCI_FREE(bp->cnic_sb.e2_sb, bp->cnic_sb_mapping,
+ sizeof(struct host_hc_status_block_e2));
+ else
+ BNX2X_PCI_FREE(bp->cnic_sb.e1x_sb, bp->cnic_sb_mapping,
+ sizeof(struct host_hc_status_block_e1x));
+
+ BNX2X_PCI_FREE(bp->t2, bp->t2_mapping, SRC_T2_SZ);
#endif
+
BNX2X_PCI_FREE(bp->spq, bp->spq_mapping, BCM_PAGE_SIZE);
+ BNX2X_PCI_FREE(bp->eq_ring, bp->eq_mapping,
+ BCM_PAGE_SIZE * NUM_EQ_PAGES);
+
#undef BNX2X_PCI_FREE
#undef BNX2X_KFREE
}
-int bnx2x_alloc_mem(struct bnx2x *bp)
+static inline void set_sb_shortcuts(struct bnx2x *bp, int index)
{
+ union host_hc_status_block status_blk = bnx2x_fp(bp, index, status_blk);
+ if (CHIP_IS_E2(bp)) {
+ bnx2x_fp(bp, index, sb_index_values) =
+ (__le16 *)status_blk.e2_sb->sb.index_values;
+ bnx2x_fp(bp, index, sb_running_index) =
+ (__le16 *)status_blk.e2_sb->sb.running_index;
+ } else {
+ bnx2x_fp(bp, index, sb_index_values) =
+ (__le16 *)status_blk.e1x_sb->sb.index_values;
+ bnx2x_fp(bp, index, sb_running_index) =
+ (__le16 *)status_blk.e1x_sb->sb.running_index;
+ }
+}
+int bnx2x_alloc_mem(struct bnx2x *bp)
+{
#define BNX2X_PCI_ALLOC(x, y, size) \
do { \
x = dma_alloc_coherent(&bp->pdev->dev, size, y, GFP_KERNEL); \
@@ -4641,10 +5915,9 @@ int bnx2x_alloc_mem(struct bnx2x *bp)
#define BNX2X_ALLOC(x, size) \
do { \
- x = vmalloc(size); \
+ x = kzalloc(size, GFP_KERNEL); \
if (x == NULL) \
goto alloc_mem_err; \
- memset(x, 0, size); \
} while (0)
int i;
@@ -4652,12 +5925,19 @@ int bnx2x_alloc_mem(struct bnx2x *bp)
/* fastpath */
/* Common */
for_each_queue(bp, i) {
+ union host_hc_status_block *sb = &bnx2x_fp(bp, i, status_blk);
bnx2x_fp(bp, i, bp) = bp;
-
/* status blocks */
- BNX2X_PCI_ALLOC(bnx2x_fp(bp, i, status_blk),
+ if (CHIP_IS_E2(bp))
+ BNX2X_PCI_ALLOC(sb->e2_sb,
+ &bnx2x_fp(bp, i, status_blk_mapping),
+ sizeof(struct host_hc_status_block_e2));
+ else
+ BNX2X_PCI_ALLOC(sb->e1x_sb,
&bnx2x_fp(bp, i, status_blk_mapping),
- sizeof(struct host_status_block));
+ sizeof(struct host_hc_status_block_e1x));
+
+ set_sb_shortcuts(bp, i);
}
/* Rx */
for_each_queue(bp, i) {
@@ -4693,37 +5973,41 @@ int bnx2x_alloc_mem(struct bnx2x *bp)
}
/* end of fastpath */
+#ifdef BCM_CNIC
+ if (CHIP_IS_E2(bp))
+ BNX2X_PCI_ALLOC(bp->cnic_sb.e2_sb, &bp->cnic_sb_mapping,
+ sizeof(struct host_hc_status_block_e2));
+ else
+ BNX2X_PCI_ALLOC(bp->cnic_sb.e1x_sb, &bp->cnic_sb_mapping,
+ sizeof(struct host_hc_status_block_e1x));
+
+ /* allocate searcher T2 table */
+ BNX2X_PCI_ALLOC(bp->t2, &bp->t2_mapping, SRC_T2_SZ);
+#endif
+
+
BNX2X_PCI_ALLOC(bp->def_status_blk, &bp->def_status_blk_mapping,
- sizeof(struct host_def_status_block));
+ sizeof(struct host_sp_status_block));
BNX2X_PCI_ALLOC(bp->slowpath, &bp->slowpath_mapping,
sizeof(struct bnx2x_slowpath));
-#ifdef BCM_CNIC
- BNX2X_PCI_ALLOC(bp->t1, &bp->t1_mapping, 64*1024);
-
- /* allocate searcher T2 table
- we allocate 1/4 of alloc num for T2
- (which is not entered into the ILT) */
- BNX2X_PCI_ALLOC(bp->t2, &bp->t2_mapping, 16*1024);
-
- /* Initialize T2 (for 1024 connections) */
- for (i = 0; i < 16*1024; i += 64)
- *(u64 *)((char *)bp->t2 + i + 56) = bp->t2_mapping + i + 64;
+ bp->context.size = sizeof(union cdu_context) * bp->l2_cid_count;
- /* Timer block array (8*MAX_CONN) phys uncached for now 1024 conns */
- BNX2X_PCI_ALLOC(bp->timers, &bp->timers_mapping, 8*1024);
+ BNX2X_PCI_ALLOC(bp->context.vcxt, &bp->context.cxt_mapping,
+ bp->context.size);
- /* QM queues (128*MAX_CONN) */
- BNX2X_PCI_ALLOC(bp->qm, &bp->qm_mapping, 128*1024);
+ BNX2X_ALLOC(bp->ilt->lines, sizeof(struct ilt_line) * ILT_MAX_LINES);
- BNX2X_PCI_ALLOC(bp->cnic_sb, &bp->cnic_sb_mapping,
- sizeof(struct host_status_block));
-#endif
+ if (bnx2x_ilt_mem_op(bp, ILT_MEMOP_ALLOC))
+ goto alloc_mem_err;
/* Slow path ring */
BNX2X_PCI_ALLOC(bp->spq, &bp->spq_mapping, BCM_PAGE_SIZE);
+ /* EQ */
+ BNX2X_PCI_ALLOC(bp->eq_ring, &bp->eq_mapping,
+ BCM_PAGE_SIZE * NUM_EQ_PAGES);
return 0;
alloc_mem_err:
@@ -4734,97 +6018,47 @@ alloc_mem_err:
#undef BNX2X_ALLOC
}
-
/*
* Init service functions
*/
-
-/**
- * Sets a MAC in a CAM for a few L2 Clients for E1 chip
- *
- * @param bp driver descriptor
- * @param set set or clear an entry (1 or 0)
- * @param mac pointer to a buffer containing a MAC
- * @param cl_bit_vec bit vector of clients to register a MAC for
- * @param cam_offset offset in a CAM to use
- * @param with_bcast set broadcast MAC as well
- */
-static void bnx2x_set_mac_addr_e1_gen(struct bnx2x *bp, int set, u8 *mac,
- u32 cl_bit_vec, u8 cam_offset,
- u8 with_bcast)
+int bnx2x_func_start(struct bnx2x *bp)
{
- struct mac_configuration_cmd *config = bnx2x_sp(bp, mac_config);
- int port = BP_PORT(bp);
-
- /* CAM allocation
- * unicasts 0-31:port0 32-63:port1
- * multicast 64-127:port0 128-191:port1
- */
- config->hdr.length = 1 + (with_bcast ? 1 : 0);
- config->hdr.offset = cam_offset;
- config->hdr.client_id = 0xff;
- config->hdr.reserved1 = 0;
+ bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_FUNCTION_START, 0, 0, 0, 1);
- /* primary MAC */
- config->config_table[0].cam_entry.msb_mac_addr =
- swab16(*(u16 *)&mac[0]);
- config->config_table[0].cam_entry.middle_mac_addr =
- swab16(*(u16 *)&mac[2]);
- config->config_table[0].cam_entry.lsb_mac_addr =
- swab16(*(u16 *)&mac[4]);
- config->config_table[0].cam_entry.flags = cpu_to_le16(port);
- if (set)
- config->config_table[0].target_table_entry.flags = 0;
- else
- CAM_INVALIDATE(config->config_table[0]);
- config->config_table[0].target_table_entry.clients_bit_vector =
- cpu_to_le32(cl_bit_vec);
- config->config_table[0].target_table_entry.vlan_id = 0;
+ /* Wait for completion */
+ return bnx2x_wait_ramrod(bp, BNX2X_STATE_FUNC_STARTED, 0, &(bp->state),
+ WAIT_RAMROD_COMMON);
+}
- DP(NETIF_MSG_IFUP, "%s MAC (%04x:%04x:%04x)\n",
- (set ? "setting" : "clearing"),
- config->config_table[0].cam_entry.msb_mac_addr,
- config->config_table[0].cam_entry.middle_mac_addr,
- config->config_table[0].cam_entry.lsb_mac_addr);
-
- /* broadcast */
- if (with_bcast) {
- config->config_table[1].cam_entry.msb_mac_addr =
- cpu_to_le16(0xffff);
- config->config_table[1].cam_entry.middle_mac_addr =
- cpu_to_le16(0xffff);
- config->config_table[1].cam_entry.lsb_mac_addr =
- cpu_to_le16(0xffff);
- config->config_table[1].cam_entry.flags = cpu_to_le16(port);
- if (set)
- config->config_table[1].target_table_entry.flags =
- TSTORM_CAM_TARGET_TABLE_ENTRY_BROADCAST;
- else
- CAM_INVALIDATE(config->config_table[1]);
- config->config_table[1].target_table_entry.clients_bit_vector =
- cpu_to_le32(cl_bit_vec);
- config->config_table[1].target_table_entry.vlan_id = 0;
- }
+int bnx2x_func_stop(struct bnx2x *bp)
+{
+ bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_FUNCTION_STOP, 0, 0, 0, 1);
- bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_SET_MAC, 0,
- U64_HI(bnx2x_sp_mapping(bp, mac_config)),
- U64_LO(bnx2x_sp_mapping(bp, mac_config)), 0);
+ /* Wait for completion */
+ return bnx2x_wait_ramrod(bp, BNX2X_STATE_CLOSING_WAIT4_UNLOAD,
+ 0, &(bp->state), WAIT_RAMROD_COMMON);
}
/**
- * Sets a MAC in a CAM for a few L2 Clients for E1H chip
+ * Sets a MAC in a CAM for a few L2 Clients for E1x chips
*
* @param bp driver descriptor
* @param set set or clear an entry (1 or 0)
* @param mac pointer to a buffer containing a MAC
* @param cl_bit_vec bit vector of clients to register a MAC for
* @param cam_offset offset in a CAM to use
+ * @param is_bcast is the set MAC a broadcast address (for E1 only)
*/
-static void bnx2x_set_mac_addr_e1h_gen(struct bnx2x *bp, int set, u8 *mac,
- u32 cl_bit_vec, u8 cam_offset)
+static void bnx2x_set_mac_addr_gen(struct bnx2x *bp, int set, u8 *mac,
+ u32 cl_bit_vec, u8 cam_offset,
+ u8 is_bcast)
{
- struct mac_configuration_cmd_e1h *config =
- (struct mac_configuration_cmd_e1h *)bnx2x_sp(bp, mac_config);
+ struct mac_configuration_cmd *config =
+ (struct mac_configuration_cmd *)bnx2x_sp(bp, mac_config);
+ int ramrod_flags = WAIT_RAMROD_COMMON;
+
+ bp->set_mac_pending = 1;
+ smp_wmb();
config->hdr.length = 1;
config->hdr.offset = cam_offset;
@@ -4841,29 +6075,41 @@ static void bnx2x_set_mac_addr_e1h_gen(struct bnx2x *bp, int set, u8 *mac,
config->config_table[0].clients_bit_vector =
cpu_to_le32(cl_bit_vec);
config->config_table[0].vlan_id = 0;
- config->config_table[0].e1hov_id = cpu_to_le16(bp->e1hov);
+ config->config_table[0].pf_id = BP_FUNC(bp);
if (set)
- config->config_table[0].flags = BP_PORT(bp);
+ SET_FLAG(config->config_table[0].flags,
+ MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
+ T_ETH_MAC_COMMAND_SET);
else
- config->config_table[0].flags =
- MAC_CONFIGURATION_ENTRY_E1H_ACTION_TYPE;
+ SET_FLAG(config->config_table[0].flags,
+ MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
+ T_ETH_MAC_COMMAND_INVALIDATE);
+
+ if (is_bcast)
+ SET_FLAG(config->config_table[0].flags,
+ MAC_CONFIGURATION_ENTRY_BROADCAST, 1);
- DP(NETIF_MSG_IFUP, "%s MAC (%04x:%04x:%04x) E1HOV %d CLID mask %d\n",
+ DP(NETIF_MSG_IFUP, "%s MAC (%04x:%04x:%04x) PF_ID %d CLID mask %d\n",
(set ? "setting" : "clearing"),
config->config_table[0].msb_mac_addr,
config->config_table[0].middle_mac_addr,
- config->config_table[0].lsb_mac_addr, bp->e1hov, cl_bit_vec);
+ config->config_table[0].lsb_mac_addr, BP_FUNC(bp), cl_bit_vec);
- bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_SET_MAC, 0,
+ bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
U64_HI(bnx2x_sp_mapping(bp, mac_config)),
- U64_LO(bnx2x_sp_mapping(bp, mac_config)), 0);
+ U64_LO(bnx2x_sp_mapping(bp, mac_config)), 1);
+
+ /* Wait for a completion */
+ bnx2x_wait_ramrod(bp, 0, 0, &bp->set_mac_pending, ramrod_flags);
}
-static int bnx2x_wait_ramrod(struct bnx2x *bp, int state, int idx,
- int *state_p, int poll)
+int bnx2x_wait_ramrod(struct bnx2x *bp, int state, int idx,
+ int *state_p, int flags)
{
/* can take a while if any port is running */
int cnt = 5000;
+ u8 poll = flags & WAIT_RAMROD_POLL;
+ u8 common = flags & WAIT_RAMROD_COMMON;
DP(NETIF_MSG_IFUP, "%s for state to become %x on IDX [%d]\n",
poll ? "polling" : "waiting", state, idx);
@@ -4871,13 +6117,17 @@ static int bnx2x_wait_ramrod(struct bnx2x *bp, int state, int idx,
might_sleep();
while (cnt--) {
if (poll) {
- bnx2x_rx_int(bp->fp, 10);
- /* if index is different from 0
- * the reply for some commands will
- * be on the non default queue
- */
- if (idx)
- bnx2x_rx_int(&bp->fp[idx], 10);
+ if (common)
+ bnx2x_eq_int(bp);
+ else {
+ bnx2x_rx_int(bp->fp, 10);
+ /* if index is different from 0
+ * the reply for some commands will
+ * be on the non default queue
+ */
+ if (idx)
+ bnx2x_rx_int(&bp->fp[idx], 10);
+ }
}
mb(); /* state is changed by bnx2x_sp_event() */
@@ -4904,29 +6154,112 @@ static int bnx2x_wait_ramrod(struct bnx2x *bp, int state, int idx,
return -EBUSY;
}
-void bnx2x_set_eth_mac_addr_e1h(struct bnx2x *bp, int set)
+u8 bnx2x_e1h_cam_offset(struct bnx2x *bp, u8 rel_offset)
{
- bp->set_mac_pending++;
- smp_wmb();
+ if (CHIP_IS_E1H(bp))
+ return E1H_FUNC_MAX * rel_offset + BP_FUNC(bp);
+ else if (CHIP_MODE_IS_4_PORT(bp))
+ return BP_FUNC(bp) * 32 + rel_offset;
+ else
+ return BP_VN(bp) * 32 + rel_offset;
+}
- bnx2x_set_mac_addr_e1h_gen(bp, set, bp->dev->dev_addr,
- (1 << bp->fp->cl_id), BP_FUNC(bp));
+void bnx2x_set_eth_mac(struct bnx2x *bp, int set)
+{
+ u8 cam_offset = (CHIP_IS_E1(bp) ? (BP_PORT(bp) ? 32 : 0) :
+ bnx2x_e1h_cam_offset(bp, CAM_ETH_LINE));
- /* Wait for a completion */
- bnx2x_wait_ramrod(bp, 0, 0, &bp->set_mac_pending, set ? 0 : 1);
+ /* networking MAC */
+ bnx2x_set_mac_addr_gen(bp, set, bp->dev->dev_addr,
+ (1 << bp->fp->cl_id), cam_offset , 0);
+
+ if (CHIP_IS_E1(bp)) {
+ /* broadcast MAC */
+ u8 bcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+ bnx2x_set_mac_addr_gen(bp, set, bcast, 0, cam_offset + 1, 1);
+ }
}
+static void bnx2x_set_e1_mc_list(struct bnx2x *bp, u8 offset)
+{
+ int i = 0, old;
+ struct net_device *dev = bp->dev;
+ struct netdev_hw_addr *ha;
+ struct mac_configuration_cmd *config_cmd = bnx2x_sp(bp, mcast_config);
+ dma_addr_t config_cmd_map = bnx2x_sp_mapping(bp, mcast_config);
+
+ netdev_for_each_mc_addr(ha, dev) {
+ /* copy mac */
+ config_cmd->config_table[i].msb_mac_addr =
+ swab16(*(u16 *)&bnx2x_mc_addr(ha)[0]);
+ config_cmd->config_table[i].middle_mac_addr =
+ swab16(*(u16 *)&bnx2x_mc_addr(ha)[2]);
+ config_cmd->config_table[i].lsb_mac_addr =
+ swab16(*(u16 *)&bnx2x_mc_addr(ha)[4]);
+
+ config_cmd->config_table[i].vlan_id = 0;
+ config_cmd->config_table[i].pf_id = BP_FUNC(bp);
+ config_cmd->config_table[i].clients_bit_vector =
+ cpu_to_le32(1 << BP_L_ID(bp));
-void bnx2x_set_eth_mac_addr_e1(struct bnx2x *bp, int set)
+ SET_FLAG(config_cmd->config_table[i].flags,
+ MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
+ T_ETH_MAC_COMMAND_SET);
+
+ DP(NETIF_MSG_IFUP,
+ "setting MCAST[%d] (%04x:%04x:%04x)\n", i,
+ config_cmd->config_table[i].msb_mac_addr,
+ config_cmd->config_table[i].middle_mac_addr,
+ config_cmd->config_table[i].lsb_mac_addr);
+ i++;
+ }
+ old = config_cmd->hdr.length;
+ if (old > i) {
+ for (; i < old; i++) {
+ if (CAM_IS_INVALID(config_cmd->
+ config_table[i])) {
+ /* already invalidated */
+ break;
+ }
+ /* invalidate */
+ SET_FLAG(config_cmd->config_table[i].flags,
+ MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
+ T_ETH_MAC_COMMAND_INVALIDATE);
+ }
+ }
+
+ config_cmd->hdr.length = i;
+ config_cmd->hdr.offset = offset;
+ config_cmd->hdr.client_id = 0xff;
+ config_cmd->hdr.reserved1 = 0;
+
+ bp->set_mac_pending = 1;
+ smp_wmb();
+
+ bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
+ U64_HI(config_cmd_map), U64_LO(config_cmd_map), 1);
+}
+static void bnx2x_invlidate_e1_mc_list(struct bnx2x *bp)
{
- bp->set_mac_pending++;
+ int i;
+ struct mac_configuration_cmd *config_cmd = bnx2x_sp(bp, mcast_config);
+ dma_addr_t config_cmd_map = bnx2x_sp_mapping(bp, mcast_config);
+ int ramrod_flags = WAIT_RAMROD_COMMON;
+
+ bp->set_mac_pending = 1;
smp_wmb();
- bnx2x_set_mac_addr_e1_gen(bp, set, bp->dev->dev_addr,
- (1 << bp->fp->cl_id), (BP_PORT(bp) ? 32 : 0),
- 1);
+ for (i = 0; i < config_cmd->hdr.length; i++)
+ SET_FLAG(config_cmd->config_table[i].flags,
+ MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
+ T_ETH_MAC_COMMAND_INVALIDATE);
+
+ bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
+ U64_HI(config_cmd_map), U64_LO(config_cmd_map), 1);
/* Wait for a completion */
- bnx2x_wait_ramrod(bp, 0, 0, &bp->set_mac_pending, set ? 0 : 1);
+ bnx2x_wait_ramrod(bp, 0, 0, &bp->set_mac_pending,
+ ramrod_flags);
+
}
#ifdef BCM_CNIC
@@ -4942,174 +6275,463 @@ void bnx2x_set_eth_mac_addr_e1(struct bnx2x *bp, int set)
*/
int bnx2x_set_iscsi_eth_mac_addr(struct bnx2x *bp, int set)
{
- u32 cl_bit_vec = (1 << BCM_ISCSI_ETH_CL_ID);
-
- bp->set_mac_pending++;
- smp_wmb();
+ u8 cam_offset = (CHIP_IS_E1(bp) ? ((BP_PORT(bp) ? 32 : 0) + 2) :
+ bnx2x_e1h_cam_offset(bp, CAM_ISCSI_ETH_LINE));
+ u32 iscsi_l2_cl_id = BNX2X_ISCSI_ETH_CL_ID;
+ u32 cl_bit_vec = (1 << iscsi_l2_cl_id);
/* Send a SET_MAC ramrod */
- if (CHIP_IS_E1(bp))
- bnx2x_set_mac_addr_e1_gen(bp, set, bp->iscsi_mac,
- cl_bit_vec, (BP_PORT(bp) ? 32 : 0) + 2,
- 1);
- else
- /* CAM allocation for E1H
- * unicasts: by func number
- * multicast: 20+FUNC*20, 20 each
- */
- bnx2x_set_mac_addr_e1h_gen(bp, set, bp->iscsi_mac,
- cl_bit_vec, E1H_FUNC_MAX + BP_FUNC(bp));
-
- /* Wait for a completion when setting */
- bnx2x_wait_ramrod(bp, 0, 0, &bp->set_mac_pending, set ? 0 : 1);
-
+ bnx2x_set_mac_addr_gen(bp, set, bp->iscsi_mac, cl_bit_vec,
+ cam_offset, 0);
return 0;
}
#endif
-int bnx2x_setup_leading(struct bnx2x *bp)
-{
- int rc;
+static void bnx2x_fill_cl_init_data(struct bnx2x *bp,
+ struct bnx2x_client_init_params *params,
+ u8 activate,
+ struct client_init_ramrod_data *data)
+{
+ /* Clear the buffer */
+ memset(data, 0, sizeof(*data));
+
+ /* general */
+ data->general.client_id = params->rxq_params.cl_id;
+ data->general.statistics_counter_id = params->rxq_params.stat_id;
+ data->general.statistics_en_flg =
+ (params->rxq_params.flags & QUEUE_FLG_STATS) ? 1 : 0;
+ data->general.activate_flg = activate;
+ data->general.sp_client_id = params->rxq_params.spcl_id;
+
+ /* Rx data */
+ data->rx.tpa_en_flg =
+ (params->rxq_params.flags & QUEUE_FLG_TPA) ? 1 : 0;
+ data->rx.vmqueue_mode_en_flg = 0;
+ data->rx.cache_line_alignment_log_size =
+ params->rxq_params.cache_line_log;
+ data->rx.enable_dynamic_hc =
+ (params->rxq_params.flags & QUEUE_FLG_DHC) ? 1 : 0;
+ data->rx.max_sges_for_packet = params->rxq_params.max_sges_pkt;
+ data->rx.client_qzone_id = params->rxq_params.cl_qzone_id;
+ data->rx.max_agg_size = params->rxq_params.tpa_agg_sz;
+
+ /* We don't set drop flags */
+ data->rx.drop_ip_cs_err_flg = 0;
+ data->rx.drop_tcp_cs_err_flg = 0;
+ data->rx.drop_ttl0_flg = 0;
+ data->rx.drop_udp_cs_err_flg = 0;
+
+ data->rx.inner_vlan_removal_enable_flg =
+ (params->rxq_params.flags & QUEUE_FLG_VLAN) ? 1 : 0;
+ data->rx.outer_vlan_removal_enable_flg =
+ (params->rxq_params.flags & QUEUE_FLG_OV) ? 1 : 0;
+ data->rx.status_block_id = params->rxq_params.fw_sb_id;
+ data->rx.rx_sb_index_number = params->rxq_params.sb_cq_index;
+ data->rx.bd_buff_size = cpu_to_le16(params->rxq_params.buf_sz);
+ data->rx.sge_buff_size = cpu_to_le16(params->rxq_params.sge_buf_sz);
+ data->rx.mtu = cpu_to_le16(params->rxq_params.mtu);
+ data->rx.bd_page_base.lo =
+ cpu_to_le32(U64_LO(params->rxq_params.dscr_map));
+ data->rx.bd_page_base.hi =
+ cpu_to_le32(U64_HI(params->rxq_params.dscr_map));
+ data->rx.sge_page_base.lo =
+ cpu_to_le32(U64_LO(params->rxq_params.sge_map));
+ data->rx.sge_page_base.hi =
+ cpu_to_le32(U64_HI(params->rxq_params.sge_map));
+ data->rx.cqe_page_base.lo =
+ cpu_to_le32(U64_LO(params->rxq_params.rcq_map));
+ data->rx.cqe_page_base.hi =
+ cpu_to_le32(U64_HI(params->rxq_params.rcq_map));
+ data->rx.is_leading_rss =
+ (params->ramrod_params.flags & CLIENT_IS_LEADING_RSS) ? 1 : 0;
+ data->rx.is_approx_mcast = data->rx.is_leading_rss;
+
+ /* Tx data */
+ data->tx.enforce_security_flg = 0; /* VF specific */
+ data->tx.tx_status_block_id = params->txq_params.fw_sb_id;
+ data->tx.tx_sb_index_number = params->txq_params.sb_cq_index;
+ data->tx.mtu = 0; /* VF specific */
+ data->tx.tx_bd_page_base.lo =
+ cpu_to_le32(U64_LO(params->txq_params.dscr_map));
+ data->tx.tx_bd_page_base.hi =
+ cpu_to_le32(U64_HI(params->txq_params.dscr_map));
+
+ /* flow control data */
+ data->fc.cqe_pause_thr_low = cpu_to_le16(params->pause.rcq_th_lo);
+ data->fc.cqe_pause_thr_high = cpu_to_le16(params->pause.rcq_th_hi);
+ data->fc.bd_pause_thr_low = cpu_to_le16(params->pause.bd_th_lo);
+ data->fc.bd_pause_thr_high = cpu_to_le16(params->pause.bd_th_hi);
+ data->fc.sge_pause_thr_low = cpu_to_le16(params->pause.sge_th_lo);
+ data->fc.sge_pause_thr_high = cpu_to_le16(params->pause.sge_th_hi);
+ data->fc.rx_cos_mask = cpu_to_le16(params->pause.pri_map);
+
+ data->fc.safc_group_num = params->txq_params.cos;
+ data->fc.safc_group_en_flg =
+ (params->txq_params.flags & QUEUE_FLG_COS) ? 1 : 0;
+ data->fc.traffic_type = LLFC_TRAFFIC_TYPE_NW;
+}
+
+static inline void bnx2x_set_ctx_validation(struct eth_context *cxt, u32 cid)
+{
+ /* ustorm cxt validation */
+ cxt->ustorm_ag_context.cdu_usage =
+ CDU_RSRVD_VALUE_TYPE_A(cid, CDU_REGION_NUMBER_UCM_AG,
+ ETH_CONNECTION_TYPE);
+ /* xcontext validation */
+ cxt->xstorm_ag_context.cdu_reserved =
+ CDU_RSRVD_VALUE_TYPE_A(cid, CDU_REGION_NUMBER_XCM_AG,
+ ETH_CONNECTION_TYPE);
+}
+
+int bnx2x_setup_fw_client(struct bnx2x *bp,
+ struct bnx2x_client_init_params *params,
+ u8 activate,
+ struct client_init_ramrod_data *data,
+ dma_addr_t data_mapping)
+{
+ u16 hc_usec;
+ int ramrod = RAMROD_CMD_ID_ETH_CLIENT_SETUP;
+ int ramrod_flags = 0, rc;
+
+ /* HC and context validation values */
+ hc_usec = params->txq_params.hc_rate ?
+ 1000000 / params->txq_params.hc_rate : 0;
+ bnx2x_update_coalesce_sb_index(bp,
+ params->txq_params.fw_sb_id,
+ params->txq_params.sb_cq_index,
+ !(params->txq_params.flags & QUEUE_FLG_HC),
+ hc_usec);
+
+ *(params->ramrod_params.pstate) = BNX2X_FP_STATE_OPENING;
+
+ hc_usec = params->rxq_params.hc_rate ?
+ 1000000 / params->rxq_params.hc_rate : 0;
+ bnx2x_update_coalesce_sb_index(bp,
+ params->rxq_params.fw_sb_id,
+ params->rxq_params.sb_cq_index,
+ !(params->rxq_params.flags & QUEUE_FLG_HC),
+ hc_usec);
+
+ bnx2x_set_ctx_validation(params->rxq_params.cxt,
+ params->rxq_params.cid);
+
+ /* zero stats */
+ if (params->txq_params.flags & QUEUE_FLG_STATS)
+ storm_memset_xstats_zero(bp, BP_PORT(bp),
+ params->txq_params.stat_id);
+
+ if (params->rxq_params.flags & QUEUE_FLG_STATS) {
+ storm_memset_ustats_zero(bp, BP_PORT(bp),
+ params->rxq_params.stat_id);
+ storm_memset_tstats_zero(bp, BP_PORT(bp),
+ params->rxq_params.stat_id);
+ }
+
+ /* Fill the ramrod data */
+ bnx2x_fill_cl_init_data(bp, params, activate, data);
+
+ /* SETUP ramrod.
+ *
+ * bnx2x_sp_post() takes a spin_lock thus no other explict memory
+ * barrier except from mmiowb() is needed to impose a
+ * proper ordering of memory operations.
+ */
+ mmiowb();
- /* reset IGU state */
- bnx2x_ack_sb(bp, bp->fp[0].sb_id, CSTORM_ID, 0, IGU_INT_ENABLE, 0);
- /* SETUP ramrod */
- bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_PORT_SETUP, 0, 0, 0, 0);
+ bnx2x_sp_post(bp, ramrod, params->ramrod_params.cid,
+ U64_HI(data_mapping), U64_LO(data_mapping), 0);
/* Wait for completion */
- rc = bnx2x_wait_ramrod(bp, BNX2X_STATE_OPEN, 0, &(bp->state), 0);
-
+ rc = bnx2x_wait_ramrod(bp, params->ramrod_params.state,
+ params->ramrod_params.index,
+ params->ramrod_params.pstate,
+ ramrod_flags);
return rc;
}
-int bnx2x_setup_multi(struct bnx2x *bp, int index)
+/**
+ * Configure interrupt mode according to current configuration.
+ * In case of MSI-X it will also try to enable MSI-X.
+ *
+ * @param bp
+ *
+ * @return int
+ */
+static int __devinit bnx2x_set_int_mode(struct bnx2x *bp)
{
- struct bnx2x_fastpath *fp = &bp->fp[index];
+ int rc = 0;
- /* reset IGU state */
- bnx2x_ack_sb(bp, fp->sb_id, CSTORM_ID, 0, IGU_INT_ENABLE, 0);
+ switch (bp->int_mode) {
+ case INT_MODE_MSI:
+ bnx2x_enable_msi(bp);
+ /* falling through... */
+ case INT_MODE_INTx:
+ bp->num_queues = 1;
+ DP(NETIF_MSG_IFUP, "set number of queues to 1\n");
+ break;
+ default:
+ /* Set number of queues according to bp->multi_mode value */
+ bnx2x_set_num_queues(bp);
- /* SETUP ramrod */
- fp->state = BNX2X_FP_STATE_OPENING;
- bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_CLIENT_SETUP, index, 0,
- fp->cl_id, 0);
+ DP(NETIF_MSG_IFUP, "set number of queues to %d\n",
+ bp->num_queues);
- /* Wait for completion */
- return bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_OPEN, index,
- &(fp->state), 0);
-}
+ /* if we can't use MSI-X we only need one fp,
+ * so try to enable MSI-X with the requested number of fp's
+ * and fallback to MSI or legacy INTx with one fp
+ */
+ rc = bnx2x_enable_msix(bp);
+ if (rc) {
+ /* failed to enable MSI-X */
+ if (bp->multi_mode)
+ DP(NETIF_MSG_IFUP,
+ "Multi requested but failed to "
+ "enable MSI-X (%d), "
+ "set number of queues to %d\n",
+ bp->num_queues,
+ 1);
+ bp->num_queues = 1;
+
+ if (!(bp->flags & DISABLE_MSI_FLAG))
+ bnx2x_enable_msi(bp);
+ }
+ break;
+ }
+
+ return rc;
+}
-void bnx2x_set_num_queues_msix(struct bnx2x *bp)
+/* must be called prioir to any HW initializations */
+static inline u16 bnx2x_cid_ilt_lines(struct bnx2x *bp)
{
+ return L2_ILT_LINES(bp);
+}
- switch (bp->multi_mode) {
- case ETH_RSS_MODE_DISABLED:
- bp->num_queues = 1;
- break;
+void bnx2x_ilt_set_info(struct bnx2x *bp)
+{
+ struct ilt_client_info *ilt_client;
+ struct bnx2x_ilt *ilt = BP_ILT(bp);
+ u16 line = 0;
- case ETH_RSS_MODE_REGULAR:
- if (num_queues)
- bp->num_queues = min_t(u32, num_queues,
- BNX2X_MAX_QUEUES(bp));
- else
- bp->num_queues = min_t(u32, num_online_cpus(),
- BNX2X_MAX_QUEUES(bp));
- break;
+ ilt->start_line = FUNC_ILT_BASE(BP_FUNC(bp));
+ DP(BNX2X_MSG_SP, "ilt starts at line %d\n", ilt->start_line);
+ /* CDU */
+ ilt_client = &ilt->clients[ILT_CLIENT_CDU];
+ ilt_client->client_num = ILT_CLIENT_CDU;
+ ilt_client->page_size = CDU_ILT_PAGE_SZ;
+ ilt_client->flags = ILT_CLIENT_SKIP_MEM;
+ ilt_client->start = line;
+ line += L2_ILT_LINES(bp);
+#ifdef BCM_CNIC
+ line += CNIC_ILT_LINES;
+#endif
+ ilt_client->end = line - 1;
+
+ DP(BNX2X_MSG_SP, "ilt client[CDU]: start %d, end %d, psz 0x%x, "
+ "flags 0x%x, hw psz %d\n",
+ ilt_client->start,
+ ilt_client->end,
+ ilt_client->page_size,
+ ilt_client->flags,
+ ilog2(ilt_client->page_size >> 12));
+
+ /* QM */
+ if (QM_INIT(bp->qm_cid_count)) {
+ ilt_client = &ilt->clients[ILT_CLIENT_QM];
+ ilt_client->client_num = ILT_CLIENT_QM;
+ ilt_client->page_size = QM_ILT_PAGE_SZ;
+ ilt_client->flags = 0;
+ ilt_client->start = line;
+
+ /* 4 bytes for each cid */
+ line += DIV_ROUND_UP(bp->qm_cid_count * QM_QUEUES_PER_FUNC * 4,
+ QM_ILT_PAGE_SZ);
+
+ ilt_client->end = line - 1;
+
+ DP(BNX2X_MSG_SP, "ilt client[QM]: start %d, end %d, psz 0x%x, "
+ "flags 0x%x, hw psz %d\n",
+ ilt_client->start,
+ ilt_client->end,
+ ilt_client->page_size,
+ ilt_client->flags,
+ ilog2(ilt_client->page_size >> 12));
+
+ }
+ /* SRC */
+ ilt_client = &ilt->clients[ILT_CLIENT_SRC];
+#ifdef BCM_CNIC
+ ilt_client->client_num = ILT_CLIENT_SRC;
+ ilt_client->page_size = SRC_ILT_PAGE_SZ;
+ ilt_client->flags = 0;
+ ilt_client->start = line;
+ line += SRC_ILT_LINES;
+ ilt_client->end = line - 1;
+
+ DP(BNX2X_MSG_SP, "ilt client[SRC]: start %d, end %d, psz 0x%x, "
+ "flags 0x%x, hw psz %d\n",
+ ilt_client->start,
+ ilt_client->end,
+ ilt_client->page_size,
+ ilt_client->flags,
+ ilog2(ilt_client->page_size >> 12));
- default:
- bp->num_queues = 1;
- break;
- }
-}
+#else
+ ilt_client->flags = (ILT_CLIENT_SKIP_INIT | ILT_CLIENT_SKIP_MEM);
+#endif
+ /* TM */
+ ilt_client = &ilt->clients[ILT_CLIENT_TM];
+#ifdef BCM_CNIC
+ ilt_client->client_num = ILT_CLIENT_TM;
+ ilt_client->page_size = TM_ILT_PAGE_SZ;
+ ilt_client->flags = 0;
+ ilt_client->start = line;
+ line += TM_ILT_LINES;
+ ilt_client->end = line - 1;
+
+ DP(BNX2X_MSG_SP, "ilt client[TM]: start %d, end %d, psz 0x%x, "
+ "flags 0x%x, hw psz %d\n",
+ ilt_client->start,
+ ilt_client->end,
+ ilt_client->page_size,
+ ilt_client->flags,
+ ilog2(ilt_client->page_size >> 12));
+#else
+ ilt_client->flags = (ILT_CLIENT_SKIP_INIT | ILT_CLIENT_SKIP_MEM);
+#endif
+}
-static int bnx2x_stop_multi(struct bnx2x *bp, int index)
+int bnx2x_setup_client(struct bnx2x *bp, struct bnx2x_fastpath *fp,
+ int is_leading)
{
- struct bnx2x_fastpath *fp = &bp->fp[index];
+ struct bnx2x_client_init_params params = { {0} };
int rc;
- /* halt the connection */
- fp->state = BNX2X_FP_STATE_HALTING;
- bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_HALT, index, 0, fp->cl_id, 0);
+ bnx2x_ack_sb(bp, fp->igu_sb_id, USTORM_ID, 0,
+ IGU_INT_ENABLE, 0);
- /* Wait for completion */
- rc = bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_HALTED, index,
- &(fp->state), 1);
- if (rc) /* timeout */
- return rc;
+ params.ramrod_params.pstate = &fp->state;
+ params.ramrod_params.state = BNX2X_FP_STATE_OPEN;
+ params.ramrod_params.index = fp->index;
+ params.ramrod_params.cid = fp->cid;
- /* delete cfc entry */
- bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_CFC_DEL, index, 0, 0, 1);
+ if (is_leading)
+ params.ramrod_params.flags |= CLIENT_IS_LEADING_RSS;
- /* Wait for completion */
- rc = bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_CLOSED, index,
- &(fp->state), 1);
+ bnx2x_pf_rx_cl_prep(bp, fp, &params.pause, &params.rxq_params);
+
+ bnx2x_pf_tx_cl_prep(bp, fp, &params.txq_params);
+
+ rc = bnx2x_setup_fw_client(bp, &params, 1,
+ bnx2x_sp(bp, client_init_data),
+ bnx2x_sp_mapping(bp, client_init_data));
return rc;
}
-static int bnx2x_stop_leading(struct bnx2x *bp)
+int bnx2x_stop_fw_client(struct bnx2x *bp, struct bnx2x_client_ramrod_params *p)
{
- __le16 dsb_sp_prod_idx;
- /* if the other port is handling traffic,
- this can take a lot of time */
- int cnt = 500;
int rc;
- might_sleep();
+ int poll_flag = p->poll ? WAIT_RAMROD_POLL : 0;
- /* Send HALT ramrod */
- bp->fp[0].state = BNX2X_FP_STATE_HALTING;
- bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_HALT, 0, 0, bp->fp->cl_id, 0);
+ /* halt the connection */
+ *p->pstate = BNX2X_FP_STATE_HALTING;
+ bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_HALT, p->cid, 0,
+ p->cl_id, 0);
/* Wait for completion */
- rc = bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_HALTED, 0,
- &(bp->fp[0].state), 1);
+ rc = bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_HALTED, p->index,
+ p->pstate, poll_flag);
if (rc) /* timeout */
return rc;
- dsb_sp_prod_idx = *bp->dsb_sp_prod;
+ *p->pstate = BNX2X_FP_STATE_TERMINATING;
+ bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_TERMINATE, p->cid, 0,
+ p->cl_id, 0);
+ /* Wait for completion */
+ rc = bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_TERMINATED, p->index,
+ p->pstate, poll_flag);
+ if (rc) /* timeout */
+ return rc;
- /* Send PORT_DELETE ramrod */
- bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_PORT_DEL, 0, 0, 0, 1);
- /* Wait for completion to arrive on default status block
- we are going to reset the chip anyway
- so there is not much to do if this times out
- */
- while (dsb_sp_prod_idx == *bp->dsb_sp_prod) {
- if (!cnt) {
- DP(NETIF_MSG_IFDOWN, "timeout waiting for port del "
- "dsb_sp_prod 0x%x != dsb_sp_prod_idx 0x%x\n",
- *bp->dsb_sp_prod, dsb_sp_prod_idx);
-#ifdef BNX2X_STOP_ON_ERROR
- bnx2x_panic();
-#endif
- rc = -EBUSY;
- break;
- }
- cnt--;
- msleep(1);
- rmb(); /* Refresh the dsb_sp_prod */
- }
- bp->state = BNX2X_STATE_CLOSING_WAIT4_UNLOAD;
- bp->fp[0].state = BNX2X_FP_STATE_CLOSED;
+ /* delete cfc entry */
+ bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_CFC_DEL, p->cid, 0, 0, 1);
+ /* Wait for completion */
+ rc = bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_CLOSED, p->index,
+ p->pstate, WAIT_RAMROD_COMMON);
return rc;
}
+static int bnx2x_stop_client(struct bnx2x *bp, int index)
+{
+ struct bnx2x_client_ramrod_params client_stop = {0};
+ struct bnx2x_fastpath *fp = &bp->fp[index];
+
+ client_stop.index = index;
+ client_stop.cid = fp->cid;
+ client_stop.cl_id = fp->cl_id;
+ client_stop.pstate = &(fp->state);
+ client_stop.poll = 0;
+
+ return bnx2x_stop_fw_client(bp, &client_stop);
+}
+
+
static void bnx2x_reset_func(struct bnx2x *bp)
{
int port = BP_PORT(bp);
int func = BP_FUNC(bp);
- int base, i;
+ int i;
+ int pfunc_offset_fp = offsetof(struct hc_sb_data, p_func) +
+ (CHIP_IS_E2(bp) ?
+ offsetof(struct hc_status_block_data_e2, common) :
+ offsetof(struct hc_status_block_data_e1x, common));
+ int pfunc_offset_sp = offsetof(struct hc_sp_status_block_data, p_func);
+ int pfid_offset = offsetof(struct pci_entity, pf_id);
+
+ /* Disable the function in the FW */
+ REG_WR8(bp, BAR_XSTRORM_INTMEM + XSTORM_FUNC_EN_OFFSET(func), 0);
+ REG_WR8(bp, BAR_CSTRORM_INTMEM + CSTORM_FUNC_EN_OFFSET(func), 0);
+ REG_WR8(bp, BAR_TSTRORM_INTMEM + TSTORM_FUNC_EN_OFFSET(func), 0);
+ REG_WR8(bp, BAR_USTRORM_INTMEM + USTORM_FUNC_EN_OFFSET(func), 0);
+
+ /* FP SBs */
+ for_each_queue(bp, i) {
+ struct bnx2x_fastpath *fp = &bp->fp[i];
+ REG_WR8(bp,
+ BAR_CSTRORM_INTMEM +
+ CSTORM_STATUS_BLOCK_DATA_OFFSET(fp->fw_sb_id)
+ + pfunc_offset_fp + pfid_offset,
+ HC_FUNCTION_DISABLED);
+ }
+
+ /* SP SB */
+ REG_WR8(bp,
+ BAR_CSTRORM_INTMEM +
+ CSTORM_SP_STATUS_BLOCK_DATA_OFFSET(func) +
+ pfunc_offset_sp + pfid_offset,
+ HC_FUNCTION_DISABLED);
+
+
+ for (i = 0; i < XSTORM_SPQ_DATA_SIZE / 4; i++)
+ REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_SPQ_DATA_OFFSET(func),
+ 0);
/* Configure IGU */
- REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, 0);
- REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, 0);
+ if (bp->common.int_block == INT_BLOCK_HC) {
+ REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, 0);
+ REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, 0);
+ } else {
+ REG_WR(bp, IGU_REG_LEADING_EDGE_LATCH, 0);
+ REG_WR(bp, IGU_REG_TRAILING_EDGE_LATCH, 0);
+ }
#ifdef BCM_CNIC
/* Disable Timer scan */
@@ -5125,9 +6747,27 @@ static void bnx2x_reset_func(struct bnx2x *bp)
}
#endif
/* Clear ILT */
- base = FUNC_ILT_BASE(func);
- for (i = base; i < base + ILT_PER_FUNC; i++)
- bnx2x_ilt_wr(bp, i, 0);
+ bnx2x_clear_func_ilt(bp, func);
+
+ /* Timers workaround bug for E2: if this is vnic-3,
+ * we need to set the entire ilt range for this timers.
+ */
+ if (CHIP_IS_E2(bp) && BP_VN(bp) == 3) {
+ struct ilt_client_info ilt_cli;
+ /* use dummy TM client */
+ memset(&ilt_cli, 0, sizeof(struct ilt_client_info));
+ ilt_cli.start = 0;
+ ilt_cli.end = ILT_NUM_PAGE_ENTRIES - 1;
+ ilt_cli.client_num = ILT_CLIENT_TM;
+
+ bnx2x_ilt_boundry_init_op(bp, &ilt_cli, 0, INITOP_CLEAR);
+ }
+
+ /* this assumes that reset_port() called before reset_func()*/
+ if (CHIP_IS_E2(bp))
+ bnx2x_pf_disable(bp);
+
+ bp->dmae_ready = 0;
}
static void bnx2x_reset_port(struct bnx2x *bp)
@@ -5159,7 +6799,7 @@ static void bnx2x_reset_port(struct bnx2x *bp)
static void bnx2x_reset_chip(struct bnx2x *bp, u32 reset_code)
{
DP(BNX2X_MSG_MCP, "function %d reset_code %x\n",
- BP_FUNC(bp), reset_code);
+ BP_ABS_FUNC(bp), reset_code);
switch (reset_code) {
case FW_MSG_CODE_DRV_UNLOAD_COMMON:
@@ -5196,7 +6836,6 @@ void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode)
cnt = 1000;
while (bnx2x_has_tx_work_unload(fp)) {
- bnx2x_tx_int(fp);
if (!cnt) {
BNX2X_ERR("timeout waiting for queue[%d]\n",
i);
@@ -5215,39 +6854,21 @@ void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode)
msleep(1);
if (CHIP_IS_E1(bp)) {
- struct mac_configuration_cmd *config =
- bnx2x_sp(bp, mcast_config);
-
- bnx2x_set_eth_mac_addr_e1(bp, 0);
-
- for (i = 0; i < config->hdr.length; i++)
- CAM_INVALIDATE(config->config_table[i]);
-
- config->hdr.length = i;
- if (CHIP_REV_IS_SLOW(bp))
- config->hdr.offset = BNX2X_MAX_EMUL_MULTI*(1 + port);
- else
- config->hdr.offset = BNX2X_MAX_MULTICAST*(1 + port);
- config->hdr.client_id = bp->fp->cl_id;
- config->hdr.reserved1 = 0;
-
- bp->set_mac_pending++;
- smp_wmb();
-
- bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_SET_MAC, 0,
- U64_HI(bnx2x_sp_mapping(bp, mcast_config)),
- U64_LO(bnx2x_sp_mapping(bp, mcast_config)), 0);
+ /* invalidate mc list,
+ * wait and poll (interrupts are off)
+ */
+ bnx2x_invlidate_e1_mc_list(bp);
+ bnx2x_set_eth_mac(bp, 0);
- } else { /* E1H */
+ } else {
REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 0);
- bnx2x_set_eth_mac_addr_e1h(bp, 0);
+ bnx2x_set_eth_mac(bp, 0);
for (i = 0; i < MC_HASH_SIZE; i++)
REG_WR(bp, MC_HASH_OFFSET(bp, i), 0);
-
- REG_WR(bp, MISC_REG_E1HMF_MODE, 0);
}
+
#ifdef BCM_CNIC
/* Clear iSCSI L2 MAC */
mutex_lock(&bp->cnic_mutex);
@@ -5286,33 +6907,44 @@ void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode)
/* Close multi and leading connections
Completions for ramrods are collected in a synchronous way */
- for_each_nondefault_queue(bp, i)
- if (bnx2x_stop_multi(bp, i))
+ for_each_queue(bp, i)
+
+ if (bnx2x_stop_client(bp, i))
+#ifdef BNX2X_STOP_ON_ERROR
+ return;
+#else
goto unload_error;
+#endif
- rc = bnx2x_stop_leading(bp);
+ rc = bnx2x_func_stop(bp);
if (rc) {
- BNX2X_ERR("Stop leading failed!\n");
+ BNX2X_ERR("Function stop failed!\n");
#ifdef BNX2X_STOP_ON_ERROR
- return -EBUSY;
+ return;
#else
goto unload_error;
#endif
}
-
+#ifndef BNX2X_STOP_ON_ERROR
unload_error:
+#endif
if (!BP_NOMCP(bp))
- reset_code = bnx2x_fw_command(bp, reset_code);
+ reset_code = bnx2x_fw_command(bp, reset_code, 0);
else {
- DP(NETIF_MSG_IFDOWN, "NO MCP - load counts %d, %d, %d\n",
- load_count[0], load_count[1], load_count[2]);
- load_count[0]--;
- load_count[1 + port]--;
- DP(NETIF_MSG_IFDOWN, "NO MCP - new load counts %d, %d, %d\n",
- load_count[0], load_count[1], load_count[2]);
- if (load_count[0] == 0)
+ DP(NETIF_MSG_IFDOWN, "NO MCP - load counts[%d] "
+ "%d, %d, %d\n", BP_PATH(bp),
+ load_count[BP_PATH(bp)][0],
+ load_count[BP_PATH(bp)][1],
+ load_count[BP_PATH(bp)][2]);
+ load_count[BP_PATH(bp)][0]--;
+ load_count[BP_PATH(bp)][1 + port]--;
+ DP(NETIF_MSG_IFDOWN, "NO MCP - new load counts[%d] "
+ "%d, %d, %d\n", BP_PATH(bp),
+ load_count[BP_PATH(bp)][0], load_count[BP_PATH(bp)][1],
+ load_count[BP_PATH(bp)][2]);
+ if (load_count[BP_PATH(bp)][0] == 0)
reset_code = FW_MSG_CODE_DRV_UNLOAD_COMMON;
- else if (load_count[1 + port] == 0)
+ else if (load_count[BP_PATH(bp)][1 + port] == 0)
reset_code = FW_MSG_CODE_DRV_UNLOAD_PORT;
else
reset_code = FW_MSG_CODE_DRV_UNLOAD_FUNCTION;
@@ -5322,12 +6954,18 @@ unload_error:
(reset_code == FW_MSG_CODE_DRV_UNLOAD_PORT))
bnx2x__link_reset(bp);
+ /* Disable HW interrupts, NAPI */
+ bnx2x_netif_stop(bp, 1);
+
+ /* Release IRQs */
+ bnx2x_free_irq(bp);
+
/* Reset the chip */
bnx2x_reset_chip(bp, reset_code);
/* Report UNLOAD_DONE to MCP */
if (!BP_NOMCP(bp))
- bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE);
+ bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, 0);
}
@@ -5353,7 +6991,6 @@ void bnx2x_disable_close_the_gate(struct bnx2x *bp)
}
}
-
/* Close gates #2, #3 and #4: */
static void bnx2x_set_234_gates(struct bnx2x *bp, bool close)
{
@@ -5399,15 +7036,13 @@ static void bnx2x_clp_reset_prep(struct bnx2x *bp, u32 *magic_val)
static void bnx2x_clp_reset_done(struct bnx2x *bp, u32 magic_val)
{
/* Restore the `magic' bit value... */
- /* u32 val = SHMEM_RD(bp, mf_cfg.shared_mf_config.clp_mb);
- SHMEM_WR(bp, mf_cfg.shared_mf_config.clp_mb,
- (val & (~SHARED_MF_CLP_MAGIC)) | magic_val); */
u32 val = MF_CFG_RD(bp, shared_mf_config.clp_mb);
MF_CFG_WR(bp, shared_mf_config.clp_mb,
(val & (~SHARED_MF_CLP_MAGIC)) | magic_val);
}
-/* Prepares for MCP reset: takes care of CLP configurations.
+/**
+ * Prepares for MCP reset: takes care of CLP configurations.
*
* @param bp
* @param magic_val Old value of 'magic' bit.
@@ -5805,39 +7440,23 @@ reset_task_exit:
* Init service functions
*/
-static inline u32 bnx2x_get_pretend_reg(struct bnx2x *bp, int func)
-{
- switch (func) {
- case 0: return PXP2_REG_PGL_PRETEND_FUNC_F0;
- case 1: return PXP2_REG_PGL_PRETEND_FUNC_F1;
- case 2: return PXP2_REG_PGL_PRETEND_FUNC_F2;
- case 3: return PXP2_REG_PGL_PRETEND_FUNC_F3;
- case 4: return PXP2_REG_PGL_PRETEND_FUNC_F4;
- case 5: return PXP2_REG_PGL_PRETEND_FUNC_F5;
- case 6: return PXP2_REG_PGL_PRETEND_FUNC_F6;
- case 7: return PXP2_REG_PGL_PRETEND_FUNC_F7;
- default:
- BNX2X_ERR("Unsupported function index: %d\n", func);
- return (u32)(-1);
- }
+u32 bnx2x_get_pretend_reg(struct bnx2x *bp)
+{
+ u32 base = PXP2_REG_PGL_PRETEND_FUNC_F0;
+ u32 stride = PXP2_REG_PGL_PRETEND_FUNC_F1 - base;
+ return base + (BP_ABS_FUNC(bp)) * stride;
}
-static void bnx2x_undi_int_disable_e1h(struct bnx2x *bp, int orig_func)
+static void bnx2x_undi_int_disable_e1h(struct bnx2x *bp)
{
- u32 reg = bnx2x_get_pretend_reg(bp, orig_func), new_val;
+ u32 reg = bnx2x_get_pretend_reg(bp);
/* Flush all outstanding writes */
mmiowb();
/* Pretend to be function 0 */
REG_WR(bp, reg, 0);
- /* Flush the GRC transaction (in the chip) */
- new_val = REG_RD(bp, reg);
- if (new_val != 0) {
- BNX2X_ERR("Hmmm... Pretend register wasn't updated: (0,%d)!\n",
- new_val);
- BUG();
- }
+ REG_RD(bp, reg); /* Flush the GRC transaction (in the chip) */
/* From now we are in the "like-E1" mode */
bnx2x_int_disable(bp);
@@ -5845,22 +7464,17 @@ static void bnx2x_undi_int_disable_e1h(struct bnx2x *bp, int orig_func)
/* Flush all outstanding writes */
mmiowb();
- /* Restore the original funtion settings */
- REG_WR(bp, reg, orig_func);
- new_val = REG_RD(bp, reg);
- if (new_val != orig_func) {
- BNX2X_ERR("Hmmm... Pretend register wasn't updated: (%d,%d)!\n",
- orig_func, new_val);
- BUG();
- }
+ /* Restore the original function */
+ REG_WR(bp, reg, BP_ABS_FUNC(bp));
+ REG_RD(bp, reg);
}
-static inline void bnx2x_undi_int_disable(struct bnx2x *bp, int func)
+static inline void bnx2x_undi_int_disable(struct bnx2x *bp)
{
- if (CHIP_IS_E1H(bp))
- bnx2x_undi_int_disable_e1h(bp, func);
- else
+ if (CHIP_IS_E1(bp))
bnx2x_int_disable(bp);
+ else
+ bnx2x_undi_int_disable_e1h(bp);
}
static void __devinit bnx2x_undi_unload(struct bnx2x *bp)
@@ -5877,8 +7491,8 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp)
val = REG_RD(bp, DORQ_REG_NORM_CID_OFST);
if (val == 0x7) {
u32 reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS;
- /* save our func */
- int func = BP_FUNC(bp);
+ /* save our pf_num */
+ int orig_pf_num = bp->pf_num;
u32 swap_en;
u32 swap_val;
@@ -5888,32 +7502,33 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp)
BNX2X_DEV_INFO("UNDI is active! reset device\n");
/* try unload UNDI on port 0 */
- bp->func = 0;
+ bp->pf_num = 0;
bp->fw_seq =
- (SHMEM_RD(bp, func_mb[bp->func].drv_mb_header) &
+ (SHMEM_RD(bp, func_mb[bp->pf_num].drv_mb_header) &
DRV_MSG_SEQ_NUMBER_MASK);
- reset_code = bnx2x_fw_command(bp, reset_code);
+ reset_code = bnx2x_fw_command(bp, reset_code, 0);
/* if UNDI is loaded on the other port */
if (reset_code != FW_MSG_CODE_DRV_UNLOAD_COMMON) {
/* send "DONE" for previous unload */
- bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE);
+ bnx2x_fw_command(bp,
+ DRV_MSG_CODE_UNLOAD_DONE, 0);
/* unload UNDI on port 1 */
- bp->func = 1;
+ bp->pf_num = 1;
bp->fw_seq =
- (SHMEM_RD(bp, func_mb[bp->func].drv_mb_header) &
+ (SHMEM_RD(bp, func_mb[bp->pf_num].drv_mb_header) &
DRV_MSG_SEQ_NUMBER_MASK);
reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS;
- bnx2x_fw_command(bp, reset_code);
+ bnx2x_fw_command(bp, reset_code, 0);
}
/* now it's safe to release the lock */
bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_UNDI);
- bnx2x_undi_int_disable(bp, func);
+ bnx2x_undi_int_disable(bp);
/* close input traffic and wait for it */
/* Do not rcv packets to BRB */
@@ -5949,14 +7564,13 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp)
REG_WR(bp, NIG_REG_STRAP_OVERRIDE, swap_en);
/* send unload done to the MCP */
- bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE);
+ bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, 0);
/* restore our func and fw_seq */
- bp->func = func;
+ bp->pf_num = orig_pf_num;
bp->fw_seq =
- (SHMEM_RD(bp, func_mb[bp->func].drv_mb_header) &
+ (SHMEM_RD(bp, func_mb[bp->pf_num].drv_mb_header) &
DRV_MSG_SEQ_NUMBER_MASK);
-
} else
bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_UNDI);
}
@@ -5978,6 +7592,40 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp)
val = REG_RD(bp, MISC_REG_BOND_ID);
id |= (val & 0xf);
bp->common.chip_id = id;
+
+ /* Set doorbell size */
+ bp->db_size = (1 << BNX2X_DB_SHIFT);
+
+ if (CHIP_IS_E2(bp)) {
+ val = REG_RD(bp, MISC_REG_PORT4MODE_EN_OVWR);
+ if ((val & 1) == 0)
+ val = REG_RD(bp, MISC_REG_PORT4MODE_EN);
+ else
+ val = (val >> 1) & 1;
+ BNX2X_DEV_INFO("chip is in %s\n", val ? "4_PORT_MODE" :
+ "2_PORT_MODE");
+ bp->common.chip_port_mode = val ? CHIP_4_PORT_MODE :
+ CHIP_2_PORT_MODE;
+
+ if (CHIP_MODE_IS_4_PORT(bp))
+ bp->pfid = (bp->pf_num >> 1); /* 0..3 */
+ else
+ bp->pfid = (bp->pf_num & 0x6); /* 0, 2, 4, 6 */
+ } else {
+ bp->common.chip_port_mode = CHIP_PORT_MODE_NONE; /* N/A */
+ bp->pfid = bp->pf_num; /* 0..7 */
+ }
+
+ /*
+ * set base FW non-default (fast path) status block id, this value is
+ * used to initialize the fw_sb_id saved on the fp/queue structure to
+ * determine the id used by the FW.
+ */
+ if (CHIP_IS_E1x(bp))
+ bp->base_fw_ndsb = BP_PORT(bp) * FP_SB_MAX_E1x;
+ else /* E2 */
+ bp->base_fw_ndsb = BP_PORT(bp) * FP_SB_MAX_E2;
+
bp->link_params.chip_id = bp->common.chip_id;
BNX2X_DEV_INFO("chip ID is 0x%x\n", id);
@@ -5995,14 +7643,15 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp)
bp->common.flash_size, bp->common.flash_size);
bp->common.shmem_base = REG_RD(bp, MISC_REG_SHARED_MEM_ADDR);
- bp->common.shmem2_base = REG_RD(bp, MISC_REG_GENERIC_CR_0);
+ bp->common.shmem2_base = REG_RD(bp, (BP_PATH(bp) ?
+ MISC_REG_GENERIC_CR_1 :
+ MISC_REG_GENERIC_CR_0));
bp->link_params.shmem_base = bp->common.shmem_base;
+ bp->link_params.shmem2_base = bp->common.shmem2_base;
BNX2X_DEV_INFO("shmem offset 0x%x shmem2 offset 0x%x\n",
bp->common.shmem_base, bp->common.shmem2_base);
- if (!bp->common.shmem_base ||
- (bp->common.shmem_base < 0xA0000) ||
- (bp->common.shmem_base >= 0xC0000)) {
+ if (!bp->common.shmem_base) {
BNX2X_DEV_INFO("MCP not active\n");
bp->flags |= NO_MCP_FLAG;
return;
@@ -6011,7 +7660,7 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp)
val = SHMEM_RD(bp, validity_map[BP_PORT(bp)]);
if ((val & (SHR_MEM_VALIDITY_DEV_INFO | SHR_MEM_VALIDITY_MB))
!= (SHR_MEM_VALIDITY_DEV_INFO | SHR_MEM_VALIDITY_MB))
- BNX2X_ERROR("BAD MCP validity signature\n");
+ BNX2X_ERR("BAD MCP validity signature\n");
bp->common.hw_config = SHMEM_RD(bp, dev_info.shared_hw_config.config);
BNX2X_DEV_INFO("hw_config 0x%08x\n", bp->common.hw_config);
@@ -6035,12 +7684,16 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp)
if (val < BNX2X_BC_VER) {
/* for now only warn
* later we might need to enforce this */
- BNX2X_ERROR("This driver needs bc_ver %X but found %X, "
- "please upgrade BC\n", BNX2X_BC_VER, val);
+ BNX2X_ERR("This driver needs bc_ver %X but found %X, "
+ "please upgrade BC\n", BNX2X_BC_VER, val);
}
bp->link_params.feature_config_flags |=
- (val >= REQ_BC_VER_4_VRFY_OPT_MDL) ?
- FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY : 0;
+ (val >= REQ_BC_VER_4_VRFY_FIRST_PHY_OPT_MDL) ?
+ FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY : 0;
+
+ bp->link_params.feature_config_flags |=
+ (val >= REQ_BC_VER_4_VRFY_SPECIFIC_PHY_OPT_MDL) ?
+ FEATURE_CONFIG_BC_SUPPORTS_DUAL_PHY_OPT_MDL_VRFY : 0;
if (BP_E1HVN(bp) == 0) {
pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_PMC, &pmc);
@@ -6061,404 +7714,348 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp)
val, val2, val3, val4);
}
+#define IGU_FID(val) GET_FIELD((val), IGU_REG_MAPPING_MEMORY_FID)
+#define IGU_VEC(val) GET_FIELD((val), IGU_REG_MAPPING_MEMORY_VECTOR)
+
+static void __devinit bnx2x_get_igu_cam_info(struct bnx2x *bp)
+{
+ int pfid = BP_FUNC(bp);
+ int vn = BP_E1HVN(bp);
+ int igu_sb_id;
+ u32 val;
+ u8 fid;
+
+ bp->igu_base_sb = 0xff;
+ bp->igu_sb_cnt = 0;
+ if (CHIP_INT_MODE_IS_BC(bp)) {
+ bp->igu_sb_cnt = min_t(u8, FP_SB_MAX_E1x,
+ bp->l2_cid_count);
+
+ bp->igu_base_sb = (CHIP_MODE_IS_4_PORT(bp) ? pfid : vn) *
+ FP_SB_MAX_E1x;
+
+ bp->igu_dsb_id = E1HVN_MAX * FP_SB_MAX_E1x +
+ (CHIP_MODE_IS_4_PORT(bp) ? pfid : vn);
+
+ return;
+ }
+
+ /* IGU in normal mode - read CAM */
+ for (igu_sb_id = 0; igu_sb_id < IGU_REG_MAPPING_MEMORY_SIZE;
+ igu_sb_id++) {
+ val = REG_RD(bp, IGU_REG_MAPPING_MEMORY + igu_sb_id * 4);
+ if (!(val & IGU_REG_MAPPING_MEMORY_VALID))
+ continue;
+ fid = IGU_FID(val);
+ if ((fid & IGU_FID_ENCODE_IS_PF)) {
+ if ((fid & IGU_FID_PF_NUM_MASK) != pfid)
+ continue;
+ if (IGU_VEC(val) == 0)
+ /* default status block */
+ bp->igu_dsb_id = igu_sb_id;
+ else {
+ if (bp->igu_base_sb == 0xff)
+ bp->igu_base_sb = igu_sb_id;
+ bp->igu_sb_cnt++;
+ }
+ }
+ }
+ bp->igu_sb_cnt = min_t(u8, bp->igu_sb_cnt, bp->l2_cid_count);
+ if (bp->igu_sb_cnt == 0)
+ BNX2X_ERR("CAM configuration error\n");
+}
+
static void __devinit bnx2x_link_settings_supported(struct bnx2x *bp,
u32 switch_cfg)
{
- int port = BP_PORT(bp);
- u32 ext_phy_type;
-
- switch (switch_cfg) {
- case SWITCH_CFG_1G:
- BNX2X_DEV_INFO("switch_cfg 0x%x (1G)\n", switch_cfg);
-
- ext_phy_type =
- SERDES_EXT_PHY_TYPE(bp->link_params.ext_phy_config);
- switch (ext_phy_type) {
- case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT:
- BNX2X_DEV_INFO("ext_phy_type 0x%x (Direct)\n",
- ext_phy_type);
-
- bp->port.supported |= (SUPPORTED_10baseT_Half |
- SUPPORTED_10baseT_Full |
- SUPPORTED_100baseT_Half |
- SUPPORTED_100baseT_Full |
- SUPPORTED_1000baseT_Full |
- SUPPORTED_2500baseX_Full |
- SUPPORTED_TP |
- SUPPORTED_FIBRE |
- SUPPORTED_Autoneg |
- SUPPORTED_Pause |
- SUPPORTED_Asym_Pause);
- break;
+ int cfg_size = 0, idx, port = BP_PORT(bp);
- case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482:
- BNX2X_DEV_INFO("ext_phy_type 0x%x (5482)\n",
- ext_phy_type);
-
- bp->port.supported |= (SUPPORTED_10baseT_Half |
- SUPPORTED_10baseT_Full |
- SUPPORTED_100baseT_Half |
- SUPPORTED_100baseT_Full |
- SUPPORTED_1000baseT_Full |
- SUPPORTED_TP |
- SUPPORTED_FIBRE |
- SUPPORTED_Autoneg |
- SUPPORTED_Pause |
- SUPPORTED_Asym_Pause);
- break;
+ /* Aggregation of supported attributes of all external phys */
+ bp->port.supported[0] = 0;
+ bp->port.supported[1] = 0;
+ switch (bp->link_params.num_phys) {
+ case 1:
+ bp->port.supported[0] = bp->link_params.phy[INT_PHY].supported;
+ cfg_size = 1;
+ break;
+ case 2:
+ bp->port.supported[0] = bp->link_params.phy[EXT_PHY1].supported;
+ cfg_size = 1;
+ break;
+ case 3:
+ if (bp->link_params.multi_phy_config &
+ PORT_HW_CFG_PHY_SWAPPED_ENABLED) {
+ bp->port.supported[1] =
+ bp->link_params.phy[EXT_PHY1].supported;
+ bp->port.supported[0] =
+ bp->link_params.phy[EXT_PHY2].supported;
+ } else {
+ bp->port.supported[0] =
+ bp->link_params.phy[EXT_PHY1].supported;
+ bp->port.supported[1] =
+ bp->link_params.phy[EXT_PHY2].supported;
+ }
+ cfg_size = 2;
+ break;
+ }
- default:
- BNX2X_ERR("NVRAM config error. "
- "BAD SerDes ext_phy_config 0x%x\n",
- bp->link_params.ext_phy_config);
+ if (!(bp->port.supported[0] || bp->port.supported[1])) {
+ BNX2X_ERR("NVRAM config error. BAD phy config."
+ "PHY1 config 0x%x, PHY2 config 0x%x\n",
+ SHMEM_RD(bp,
+ dev_info.port_hw_config[port].external_phy_config),
+ SHMEM_RD(bp,
+ dev_info.port_hw_config[port].external_phy_config2));
return;
- }
+ }
+ switch (switch_cfg) {
+ case SWITCH_CFG_1G:
bp->port.phy_addr = REG_RD(bp, NIG_REG_SERDES0_CTRL_PHY_ADDR +
port*0x10);
BNX2X_DEV_INFO("phy_addr 0x%x\n", bp->port.phy_addr);
break;
case SWITCH_CFG_10G:
- BNX2X_DEV_INFO("switch_cfg 0x%x (10G)\n", switch_cfg);
-
- ext_phy_type =
- XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config);
- switch (ext_phy_type) {
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
- BNX2X_DEV_INFO("ext_phy_type 0x%x (Direct)\n",
- ext_phy_type);
-
- bp->port.supported |= (SUPPORTED_10baseT_Half |
- SUPPORTED_10baseT_Full |
- SUPPORTED_100baseT_Half |
- SUPPORTED_100baseT_Full |
- SUPPORTED_1000baseT_Full |
- SUPPORTED_2500baseX_Full |
- SUPPORTED_10000baseT_Full |
- SUPPORTED_TP |
- SUPPORTED_FIBRE |
- SUPPORTED_Autoneg |
- SUPPORTED_Pause |
- SUPPORTED_Asym_Pause);
- break;
-
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
- BNX2X_DEV_INFO("ext_phy_type 0x%x (8072)\n",
- ext_phy_type);
-
- bp->port.supported |= (SUPPORTED_10000baseT_Full |
- SUPPORTED_1000baseT_Full |
- SUPPORTED_FIBRE |
- SUPPORTED_Autoneg |
- SUPPORTED_Pause |
- SUPPORTED_Asym_Pause);
- break;
-
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
- BNX2X_DEV_INFO("ext_phy_type 0x%x (8073)\n",
- ext_phy_type);
-
- bp->port.supported |= (SUPPORTED_10000baseT_Full |
- SUPPORTED_2500baseX_Full |
- SUPPORTED_1000baseT_Full |
- SUPPORTED_FIBRE |
- SUPPORTED_Autoneg |
- SUPPORTED_Pause |
- SUPPORTED_Asym_Pause);
- break;
-
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
- BNX2X_DEV_INFO("ext_phy_type 0x%x (8705)\n",
- ext_phy_type);
-
- bp->port.supported |= (SUPPORTED_10000baseT_Full |
- SUPPORTED_FIBRE |
- SUPPORTED_Pause |
- SUPPORTED_Asym_Pause);
- break;
-
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
- BNX2X_DEV_INFO("ext_phy_type 0x%x (8706)\n",
- ext_phy_type);
-
- bp->port.supported |= (SUPPORTED_10000baseT_Full |
- SUPPORTED_1000baseT_Full |
- SUPPORTED_FIBRE |
- SUPPORTED_Pause |
- SUPPORTED_Asym_Pause);
- break;
-
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
- BNX2X_DEV_INFO("ext_phy_type 0x%x (8726)\n",
- ext_phy_type);
-
- bp->port.supported |= (SUPPORTED_10000baseT_Full |
- SUPPORTED_1000baseT_Full |
- SUPPORTED_Autoneg |
- SUPPORTED_FIBRE |
- SUPPORTED_Pause |
- SUPPORTED_Asym_Pause);
- break;
-
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
- BNX2X_DEV_INFO("ext_phy_type 0x%x (8727)\n",
- ext_phy_type);
-
- bp->port.supported |= (SUPPORTED_10000baseT_Full |
- SUPPORTED_1000baseT_Full |
- SUPPORTED_Autoneg |
- SUPPORTED_FIBRE |
- SUPPORTED_Pause |
- SUPPORTED_Asym_Pause);
- break;
-
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
- BNX2X_DEV_INFO("ext_phy_type 0x%x (SFX7101)\n",
- ext_phy_type);
-
- bp->port.supported |= (SUPPORTED_10000baseT_Full |
- SUPPORTED_TP |
- SUPPORTED_Autoneg |
- SUPPORTED_Pause |
- SUPPORTED_Asym_Pause);
- break;
-
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481:
- BNX2X_DEV_INFO("ext_phy_type 0x%x (BCM8481)\n",
- ext_phy_type);
-
- bp->port.supported |= (SUPPORTED_10baseT_Half |
- SUPPORTED_10baseT_Full |
- SUPPORTED_100baseT_Half |
- SUPPORTED_100baseT_Full |
- SUPPORTED_1000baseT_Full |
- SUPPORTED_10000baseT_Full |
- SUPPORTED_TP |
- SUPPORTED_Autoneg |
- SUPPORTED_Pause |
- SUPPORTED_Asym_Pause);
- break;
-
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
- BNX2X_ERR("XGXS PHY Failure detected 0x%x\n",
- bp->link_params.ext_phy_config);
- break;
-
- default:
- BNX2X_ERR("NVRAM config error. "
- "BAD XGXS ext_phy_config 0x%x\n",
- bp->link_params.ext_phy_config);
- return;
- }
-
bp->port.phy_addr = REG_RD(bp, NIG_REG_XGXS0_CTRL_PHY_ADDR +
port*0x18);
BNX2X_DEV_INFO("phy_addr 0x%x\n", bp->port.phy_addr);
-
break;
default:
BNX2X_ERR("BAD switch_cfg link_config 0x%x\n",
- bp->port.link_config);
+ bp->port.link_config[0]);
return;
}
- bp->link_params.phy_addr = bp->port.phy_addr;
-
- /* mask what we support according to speed_cap_mask */
- if (!(bp->link_params.speed_cap_mask &
+ /* mask what we support according to speed_cap_mask per configuration */
+ for (idx = 0; idx < cfg_size; idx++) {
+ if (!(bp->link_params.speed_cap_mask[idx] &
PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF))
- bp->port.supported &= ~SUPPORTED_10baseT_Half;
+ bp->port.supported[idx] &= ~SUPPORTED_10baseT_Half;
- if (!(bp->link_params.speed_cap_mask &
+ if (!(bp->link_params.speed_cap_mask[idx] &
PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL))
- bp->port.supported &= ~SUPPORTED_10baseT_Full;
+ bp->port.supported[idx] &= ~SUPPORTED_10baseT_Full;
- if (!(bp->link_params.speed_cap_mask &
+ if (!(bp->link_params.speed_cap_mask[idx] &
PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF))
- bp->port.supported &= ~SUPPORTED_100baseT_Half;
+ bp->port.supported[idx] &= ~SUPPORTED_100baseT_Half;
- if (!(bp->link_params.speed_cap_mask &
+ if (!(bp->link_params.speed_cap_mask[idx] &
PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL))
- bp->port.supported &= ~SUPPORTED_100baseT_Full;
+ bp->port.supported[idx] &= ~SUPPORTED_100baseT_Full;
- if (!(bp->link_params.speed_cap_mask &
+ if (!(bp->link_params.speed_cap_mask[idx] &
PORT_HW_CFG_SPEED_CAPABILITY_D0_1G))
- bp->port.supported &= ~(SUPPORTED_1000baseT_Half |
- SUPPORTED_1000baseT_Full);
+ bp->port.supported[idx] &= ~(SUPPORTED_1000baseT_Half |
+ SUPPORTED_1000baseT_Full);
- if (!(bp->link_params.speed_cap_mask &
+ if (!(bp->link_params.speed_cap_mask[idx] &
PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G))
- bp->port.supported &= ~SUPPORTED_2500baseX_Full;
+ bp->port.supported[idx] &= ~SUPPORTED_2500baseX_Full;
- if (!(bp->link_params.speed_cap_mask &
+ if (!(bp->link_params.speed_cap_mask[idx] &
PORT_HW_CFG_SPEED_CAPABILITY_D0_10G))
- bp->port.supported &= ~SUPPORTED_10000baseT_Full;
+ bp->port.supported[idx] &= ~SUPPORTED_10000baseT_Full;
+
+ }
- BNX2X_DEV_INFO("supported 0x%x\n", bp->port.supported);
+ BNX2X_DEV_INFO("supported 0x%x 0x%x\n", bp->port.supported[0],
+ bp->port.supported[1]);
}
static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp)
{
- bp->link_params.req_duplex = DUPLEX_FULL;
+ u32 link_config, idx, cfg_size = 0;
+ bp->port.advertising[0] = 0;
+ bp->port.advertising[1] = 0;
+ switch (bp->link_params.num_phys) {
+ case 1:
+ case 2:
+ cfg_size = 1;
+ break;
+ case 3:
+ cfg_size = 2;
+ break;
+ }
+ for (idx = 0; idx < cfg_size; idx++) {
+ bp->link_params.req_duplex[idx] = DUPLEX_FULL;
+ link_config = bp->port.link_config[idx];
+ switch (link_config & PORT_FEATURE_LINK_SPEED_MASK) {
+ case PORT_FEATURE_LINK_SPEED_AUTO:
+ if (bp->port.supported[idx] & SUPPORTED_Autoneg) {
+ bp->link_params.req_line_speed[idx] =
+ SPEED_AUTO_NEG;
+ bp->port.advertising[idx] |=
+ bp->port.supported[idx];
+ } else {
+ /* force 10G, no AN */
+ bp->link_params.req_line_speed[idx] =
+ SPEED_10000;
+ bp->port.advertising[idx] |=
+ (ADVERTISED_10000baseT_Full |
+ ADVERTISED_FIBRE);
+ continue;
+ }
+ break;
- switch (bp->port.link_config & PORT_FEATURE_LINK_SPEED_MASK) {
- case PORT_FEATURE_LINK_SPEED_AUTO:
- if (bp->port.supported & SUPPORTED_Autoneg) {
- bp->link_params.req_line_speed = SPEED_AUTO_NEG;
- bp->port.advertising = bp->port.supported;
- } else {
- u32 ext_phy_type =
- XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config);
+ case PORT_FEATURE_LINK_SPEED_10M_FULL:
+ if (bp->port.supported[idx] & SUPPORTED_10baseT_Full) {
+ bp->link_params.req_line_speed[idx] =
+ SPEED_10;
+ bp->port.advertising[idx] |=
+ (ADVERTISED_10baseT_Full |
+ ADVERTISED_TP);
+ } else {
+ BNX2X_ERROR("NVRAM config error. "
+ "Invalid link_config 0x%x"
+ " speed_cap_mask 0x%x\n",
+ link_config,
+ bp->link_params.speed_cap_mask[idx]);
+ return;
+ }
+ break;
- if ((ext_phy_type ==
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705) ||
- (ext_phy_type ==
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706)) {
- /* force 10G, no AN */
- bp->link_params.req_line_speed = SPEED_10000;
- bp->port.advertising =
- (ADVERTISED_10000baseT_Full |
- ADVERTISED_FIBRE);
- break;
+ case PORT_FEATURE_LINK_SPEED_10M_HALF:
+ if (bp->port.supported[idx] & SUPPORTED_10baseT_Half) {
+ bp->link_params.req_line_speed[idx] =
+ SPEED_10;
+ bp->link_params.req_duplex[idx] =
+ DUPLEX_HALF;
+ bp->port.advertising[idx] |=
+ (ADVERTISED_10baseT_Half |
+ ADVERTISED_TP);
+ } else {
+ BNX2X_ERROR("NVRAM config error. "
+ "Invalid link_config 0x%x"
+ " speed_cap_mask 0x%x\n",
+ link_config,
+ bp->link_params.speed_cap_mask[idx]);
+ return;
}
- BNX2X_ERR("NVRAM config error. "
- "Invalid link_config 0x%x"
- " Autoneg not supported\n",
- bp->port.link_config);
- return;
- }
- break;
+ break;
- case PORT_FEATURE_LINK_SPEED_10M_FULL:
- if (bp->port.supported & SUPPORTED_10baseT_Full) {
- bp->link_params.req_line_speed = SPEED_10;
- bp->port.advertising = (ADVERTISED_10baseT_Full |
- ADVERTISED_TP);
- } else {
- BNX2X_ERROR("NVRAM config error. "
- "Invalid link_config 0x%x"
- " speed_cap_mask 0x%x\n",
- bp->port.link_config,
- bp->link_params.speed_cap_mask);
- return;
- }
- break;
+ case PORT_FEATURE_LINK_SPEED_100M_FULL:
+ if (bp->port.supported[idx] &
+ SUPPORTED_100baseT_Full) {
+ bp->link_params.req_line_speed[idx] =
+ SPEED_100;
+ bp->port.advertising[idx] |=
+ (ADVERTISED_100baseT_Full |
+ ADVERTISED_TP);
+ } else {
+ BNX2X_ERROR("NVRAM config error. "
+ "Invalid link_config 0x%x"
+ " speed_cap_mask 0x%x\n",
+ link_config,
+ bp->link_params.speed_cap_mask[idx]);
+ return;
+ }
+ break;
- case PORT_FEATURE_LINK_SPEED_10M_HALF:
- if (bp->port.supported & SUPPORTED_10baseT_Half) {
- bp->link_params.req_line_speed = SPEED_10;
- bp->link_params.req_duplex = DUPLEX_HALF;
- bp->port.advertising = (ADVERTISED_10baseT_Half |
- ADVERTISED_TP);
- } else {
- BNX2X_ERROR("NVRAM config error. "
+ case PORT_FEATURE_LINK_SPEED_100M_HALF:
+ if (bp->port.supported[idx] &
+ SUPPORTED_100baseT_Half) {
+ bp->link_params.req_line_speed[idx] =
+ SPEED_100;
+ bp->link_params.req_duplex[idx] =
+ DUPLEX_HALF;
+ bp->port.advertising[idx] |=
+ (ADVERTISED_100baseT_Half |
+ ADVERTISED_TP);
+ } else {
+ BNX2X_ERROR("NVRAM config error. "
"Invalid link_config 0x%x"
" speed_cap_mask 0x%x\n",
- bp->port.link_config,
- bp->link_params.speed_cap_mask);
- return;
- }
- break;
+ link_config,
+ bp->link_params.speed_cap_mask[idx]);
+ return;
+ }
+ break;
- case PORT_FEATURE_LINK_SPEED_100M_FULL:
- if (bp->port.supported & SUPPORTED_100baseT_Full) {
- bp->link_params.req_line_speed = SPEED_100;
- bp->port.advertising = (ADVERTISED_100baseT_Full |
- ADVERTISED_TP);
- } else {
- BNX2X_ERROR("NVRAM config error. "
+ case PORT_FEATURE_LINK_SPEED_1G:
+ if (bp->port.supported[idx] &
+ SUPPORTED_1000baseT_Full) {
+ bp->link_params.req_line_speed[idx] =
+ SPEED_1000;
+ bp->port.advertising[idx] |=
+ (ADVERTISED_1000baseT_Full |
+ ADVERTISED_TP);
+ } else {
+ BNX2X_ERROR("NVRAM config error. "
"Invalid link_config 0x%x"
" speed_cap_mask 0x%x\n",
- bp->port.link_config,
- bp->link_params.speed_cap_mask);
- return;
- }
- break;
+ link_config,
+ bp->link_params.speed_cap_mask[idx]);
+ return;
+ }
+ break;
- case PORT_FEATURE_LINK_SPEED_100M_HALF:
- if (bp->port.supported & SUPPORTED_100baseT_Half) {
- bp->link_params.req_line_speed = SPEED_100;
- bp->link_params.req_duplex = DUPLEX_HALF;
- bp->port.advertising = (ADVERTISED_100baseT_Half |
+ case PORT_FEATURE_LINK_SPEED_2_5G:
+ if (bp->port.supported[idx] &
+ SUPPORTED_2500baseX_Full) {
+ bp->link_params.req_line_speed[idx] =
+ SPEED_2500;
+ bp->port.advertising[idx] |=
+ (ADVERTISED_2500baseX_Full |
ADVERTISED_TP);
- } else {
- BNX2X_ERROR("NVRAM config error. "
+ } else {
+ BNX2X_ERROR("NVRAM config error. "
"Invalid link_config 0x%x"
" speed_cap_mask 0x%x\n",
- bp->port.link_config,
- bp->link_params.speed_cap_mask);
- return;
- }
- break;
+ link_config,
+ bp->link_params.speed_cap_mask[idx]);
+ return;
+ }
+ break;
- case PORT_FEATURE_LINK_SPEED_1G:
- if (bp->port.supported & SUPPORTED_1000baseT_Full) {
- bp->link_params.req_line_speed = SPEED_1000;
- bp->port.advertising = (ADVERTISED_1000baseT_Full |
- ADVERTISED_TP);
- } else {
- BNX2X_ERROR("NVRAM config error. "
+ case PORT_FEATURE_LINK_SPEED_10G_CX4:
+ case PORT_FEATURE_LINK_SPEED_10G_KX4:
+ case PORT_FEATURE_LINK_SPEED_10G_KR:
+ if (bp->port.supported[idx] &
+ SUPPORTED_10000baseT_Full) {
+ bp->link_params.req_line_speed[idx] =
+ SPEED_10000;
+ bp->port.advertising[idx] |=
+ (ADVERTISED_10000baseT_Full |
+ ADVERTISED_FIBRE);
+ } else {
+ BNX2X_ERROR("NVRAM config error. "
"Invalid link_config 0x%x"
" speed_cap_mask 0x%x\n",
- bp->port.link_config,
- bp->link_params.speed_cap_mask);
- return;
- }
- break;
+ link_config,
+ bp->link_params.speed_cap_mask[idx]);
+ return;
+ }
+ break;
- case PORT_FEATURE_LINK_SPEED_2_5G:
- if (bp->port.supported & SUPPORTED_2500baseX_Full) {
- bp->link_params.req_line_speed = SPEED_2500;
- bp->port.advertising = (ADVERTISED_2500baseX_Full |
- ADVERTISED_TP);
- } else {
+ default:
BNX2X_ERROR("NVRAM config error. "
- "Invalid link_config 0x%x"
- " speed_cap_mask 0x%x\n",
- bp->port.link_config,
- bp->link_params.speed_cap_mask);
- return;
+ "BAD link speed link_config 0x%x\n",
+ link_config);
+ bp->link_params.req_line_speed[idx] =
+ SPEED_AUTO_NEG;
+ bp->port.advertising[idx] =
+ bp->port.supported[idx];
+ break;
}
- break;
- case PORT_FEATURE_LINK_SPEED_10G_CX4:
- case PORT_FEATURE_LINK_SPEED_10G_KX4:
- case PORT_FEATURE_LINK_SPEED_10G_KR:
- if (bp->port.supported & SUPPORTED_10000baseT_Full) {
- bp->link_params.req_line_speed = SPEED_10000;
- bp->port.advertising = (ADVERTISED_10000baseT_Full |
- ADVERTISED_FIBRE);
- } else {
- BNX2X_ERROR("NVRAM config error. "
- "Invalid link_config 0x%x"
- " speed_cap_mask 0x%x\n",
- bp->port.link_config,
- bp->link_params.speed_cap_mask);
- return;
+ bp->link_params.req_flow_ctrl[idx] = (link_config &
+ PORT_FEATURE_FLOW_CONTROL_MASK);
+ if ((bp->link_params.req_flow_ctrl[idx] ==
+ BNX2X_FLOW_CTRL_AUTO) &&
+ !(bp->port.supported[idx] & SUPPORTED_Autoneg)) {
+ bp->link_params.req_flow_ctrl[idx] =
+ BNX2X_FLOW_CTRL_NONE;
}
- break;
- default:
- BNX2X_ERROR("NVRAM config error. "
- "BAD link speed link_config 0x%x\n",
- bp->port.link_config);
- bp->link_params.req_line_speed = SPEED_AUTO_NEG;
- bp->port.advertising = bp->port.supported;
- break;
+ BNX2X_DEV_INFO("req_line_speed %d req_duplex %d req_flow_ctrl"
+ " 0x%x advertising 0x%x\n",
+ bp->link_params.req_line_speed[idx],
+ bp->link_params.req_duplex[idx],
+ bp->link_params.req_flow_ctrl[idx],
+ bp->port.advertising[idx]);
}
-
- bp->link_params.req_flow_ctrl = (bp->port.link_config &
- PORT_FEATURE_FLOW_CONTROL_MASK);
- if ((bp->link_params.req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO) &&
- !(bp->port.supported & SUPPORTED_Autoneg))
- bp->link_params.req_flow_ctrl = BNX2X_FLOW_CTRL_NONE;
-
- BNX2X_DEV_INFO("req_line_speed %d req_duplex %d req_flow_ctrl 0x%x"
- " advertising 0x%x\n",
- bp->link_params.req_line_speed,
- bp->link_params.req_duplex,
- bp->link_params.req_flow_ctrl, bp->port.advertising);
}
static void __devinit bnx2x_set_mac_buf(u8 *mac_buf, u32 mac_lo, u16 mac_hi)
@@ -6474,48 +8071,28 @@ static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp)
int port = BP_PORT(bp);
u32 val, val2;
u32 config;
- u16 i;
- u32 ext_phy_type;
+ u32 ext_phy_type, ext_phy_config;;
bp->link_params.bp = bp;
bp->link_params.port = port;
bp->link_params.lane_config =
SHMEM_RD(bp, dev_info.port_hw_config[port].lane_config);
- bp->link_params.ext_phy_config =
- SHMEM_RD(bp,
- dev_info.port_hw_config[port].external_phy_config);
- /* BCM8727_NOC => BCM8727 no over current */
- if (XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config) ==
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727_NOC) {
- bp->link_params.ext_phy_config &=
- ~PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK;
- bp->link_params.ext_phy_config |=
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727;
- bp->link_params.feature_config_flags |=
- FEATURE_CONFIG_BCM8727_NOC;
- }
- bp->link_params.speed_cap_mask =
+ bp->link_params.speed_cap_mask[0] =
SHMEM_RD(bp,
dev_info.port_hw_config[port].speed_capability_mask);
-
- bp->port.link_config =
+ bp->link_params.speed_cap_mask[1] =
+ SHMEM_RD(bp,
+ dev_info.port_hw_config[port].speed_capability_mask2);
+ bp->port.link_config[0] =
SHMEM_RD(bp, dev_info.port_feature_config[port].link_config);
- /* Get the 4 lanes xgxs config rx and tx */
- for (i = 0; i < 2; i++) {
- val = SHMEM_RD(bp,
- dev_info.port_hw_config[port].xgxs_config_rx[i<<1]);
- bp->link_params.xgxs_config_rx[i << 1] = ((val>>16) & 0xffff);
- bp->link_params.xgxs_config_rx[(i << 1) + 1] = (val & 0xffff);
-
- val = SHMEM_RD(bp,
- dev_info.port_hw_config[port].xgxs_config_tx[i<<1]);
- bp->link_params.xgxs_config_tx[i << 1] = ((val>>16) & 0xffff);
- bp->link_params.xgxs_config_tx[(i << 1) + 1] = (val & 0xffff);
- }
+ bp->port.link_config[1] =
+ SHMEM_RD(bp, dev_info.port_feature_config[port].link_config2);
+ bp->link_params.multi_phy_config =
+ SHMEM_RD(bp, dev_info.port_hw_config[port].multi_phy_config);
/* If the device is capable of WoL, set the default state according
* to the HW
*/
@@ -6523,14 +8100,15 @@ static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp)
bp->wol = (!(bp->flags & NO_WOL_FLAG) &&
(config & PORT_FEATURE_WOL_ENABLED));
- BNX2X_DEV_INFO("lane_config 0x%08x ext_phy_config 0x%08x"
- " speed_cap_mask 0x%08x link_config 0x%08x\n",
+ BNX2X_DEV_INFO("lane_config 0x%08x "
+ "speed_cap_mask0 0x%08x link_config0 0x%08x\n",
bp->link_params.lane_config,
- bp->link_params.ext_phy_config,
- bp->link_params.speed_cap_mask, bp->port.link_config);
+ bp->link_params.speed_cap_mask[0],
+ bp->port.link_config[0]);
- bp->link_params.switch_cfg |= (bp->port.link_config &
- PORT_FEATURE_CONNECTED_SWITCH_MASK);
+ bp->link_params.switch_cfg = (bp->port.link_config[0] &
+ PORT_FEATURE_CONNECTED_SWITCH_MASK);
+ bnx2x_phy_probe(&bp->link_params);
bnx2x_link_settings_supported(bp, bp->link_params.switch_cfg);
bnx2x_link_settings_requested(bp);
@@ -6539,14 +8117,17 @@ static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp)
* If connected directly, work with the internal PHY, otherwise, work
* with the external PHY
*/
- ext_phy_type = XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config);
+ ext_phy_config =
+ SHMEM_RD(bp,
+ dev_info.port_hw_config[port].external_phy_config);
+ ext_phy_type = XGXS_EXT_PHY_TYPE(ext_phy_config);
if (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT)
- bp->mdio.prtad = bp->link_params.phy_addr;
+ bp->mdio.prtad = bp->port.phy_addr;
else if ((ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE) &&
(ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN))
bp->mdio.prtad =
- XGXS_EXT_PHY_ADDR(bp->link_params.ext_phy_config);
+ XGXS_EXT_PHY_ADDR(ext_phy_config);
val2 = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_upper);
val = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_lower);
@@ -6563,41 +8144,74 @@ static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp)
static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
{
- int func = BP_FUNC(bp);
+ int func = BP_ABS_FUNC(bp);
+ int vn;
u32 val, val2;
int rc = 0;
bnx2x_get_common_hwinfo(bp);
- bp->e1hov = 0;
- bp->e1hmf = 0;
- if (CHIP_IS_E1H(bp) && !BP_NOMCP(bp)) {
- bp->mf_config =
- SHMEM_RD(bp, mf_cfg.func_mf_config[func].config);
+ if (CHIP_IS_E1x(bp)) {
+ bp->common.int_block = INT_BLOCK_HC;
+
+ bp->igu_dsb_id = DEF_SB_IGU_ID;
+ bp->igu_base_sb = 0;
+ bp->igu_sb_cnt = min_t(u8, FP_SB_MAX_E1x, bp->l2_cid_count);
+ } else {
+ bp->common.int_block = INT_BLOCK_IGU;
+ val = REG_RD(bp, IGU_REG_BLOCK_CONFIGURATION);
+ if (val & IGU_BLOCK_CONFIGURATION_REG_BACKWARD_COMP_EN) {
+ DP(NETIF_MSG_PROBE, "IGU Backward Compatible Mode\n");
+ bp->common.int_block |= INT_BLOCK_MODE_BW_COMP;
+ } else
+ DP(NETIF_MSG_PROBE, "IGU Normal Mode\n");
+
+ bnx2x_get_igu_cam_info(bp);
+
+ }
+ DP(NETIF_MSG_PROBE, "igu_dsb_id %d igu_base_sb %d igu_sb_cnt %d\n",
+ bp->igu_dsb_id, bp->igu_base_sb, bp->igu_sb_cnt);
+
+ /*
+ * Initialize MF configuration
+ */
- val = (SHMEM_RD(bp, mf_cfg.func_mf_config[FUNC_0].e1hov_tag) &
+ bp->mf_ov = 0;
+ bp->mf_mode = 0;
+ vn = BP_E1HVN(bp);
+ if (!CHIP_IS_E1(bp) && !BP_NOMCP(bp)) {
+ if (SHMEM2_HAS(bp, mf_cfg_addr))
+ bp->common.mf_cfg_base = SHMEM2_RD(bp, mf_cfg_addr);
+ else
+ bp->common.mf_cfg_base = bp->common.shmem_base +
+ offsetof(struct shmem_region, func_mb) +
+ E1H_FUNC_MAX * sizeof(struct drv_func_mb);
+ bp->mf_config[vn] =
+ MF_CFG_RD(bp, func_mf_config[func].config);
+
+ val = (MF_CFG_RD(bp, func_mf_config[FUNC_0].e1hov_tag) &
FUNC_MF_CFG_E1HOV_TAG_MASK);
if (val != FUNC_MF_CFG_E1HOV_TAG_DEFAULT)
- bp->e1hmf = 1;
+ bp->mf_mode = 1;
BNX2X_DEV_INFO("%s function mode\n",
- IS_E1HMF(bp) ? "multi" : "single");
+ IS_MF(bp) ? "multi" : "single");
- if (IS_E1HMF(bp)) {
- val = (SHMEM_RD(bp, mf_cfg.func_mf_config[func].
+ if (IS_MF(bp)) {
+ val = (MF_CFG_RD(bp, func_mf_config[func].
e1hov_tag) &
FUNC_MF_CFG_E1HOV_TAG_MASK);
if (val != FUNC_MF_CFG_E1HOV_TAG_DEFAULT) {
- bp->e1hov = val;
- BNX2X_DEV_INFO("E1HOV for func %d is %d "
+ bp->mf_ov = val;
+ BNX2X_DEV_INFO("MF OV for func %d is %d "
"(0x%04x)\n",
- func, bp->e1hov, bp->e1hov);
+ func, bp->mf_ov, bp->mf_ov);
} else {
- BNX2X_ERROR("No valid E1HOV for func %d,"
+ BNX2X_ERROR("No valid MF OV for func %d,"
" aborting\n", func);
rc = -EPERM;
}
} else {
- if (BP_E1HVN(bp)) {
+ if (BP_VN(bp)) {
BNX2X_ERROR("VN %d in single function mode,"
" aborting\n", BP_E1HVN(bp));
rc = -EPERM;
@@ -6605,17 +8219,31 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
}
}
+ /* adjust igu_sb_cnt to MF for E1x */
+ if (CHIP_IS_E1x(bp) && IS_MF(bp))
+ bp->igu_sb_cnt /= E1HVN_MAX;
+
+ /*
+ * adjust E2 sb count: to be removed when FW will support
+ * more then 16 L2 clients
+ */
+#define MAX_L2_CLIENTS 16
+ if (CHIP_IS_E2(bp))
+ bp->igu_sb_cnt = min_t(u8, bp->igu_sb_cnt,
+ MAX_L2_CLIENTS / (IS_MF(bp) ? 4 : 1));
+
if (!BP_NOMCP(bp)) {
bnx2x_get_port_hwinfo(bp);
- bp->fw_seq = (SHMEM_RD(bp, func_mb[func].drv_mb_header) &
- DRV_MSG_SEQ_NUMBER_MASK);
+ bp->fw_seq =
+ (SHMEM_RD(bp, func_mb[BP_FW_MB_IDX(bp)].drv_mb_header) &
+ DRV_MSG_SEQ_NUMBER_MASK);
BNX2X_DEV_INFO("fw_seq 0x%08x\n", bp->fw_seq);
}
- if (IS_E1HMF(bp)) {
- val2 = SHMEM_RD(bp, mf_cfg.func_mf_config[func].mac_upper);
- val = SHMEM_RD(bp, mf_cfg.func_mf_config[func].mac_lower);
+ if (IS_MF(bp)) {
+ val2 = MF_CFG_RD(bp, func_mf_config[func].mac_upper);
+ val = MF_CFG_RD(bp, func_mf_config[func].mac_lower);
if ((val2 != FUNC_MF_CFG_UPPERMAC_DEFAULT) &&
(val != FUNC_MF_CFG_LOWERMAC_DEFAULT)) {
bp->dev->dev_addr[0] = (u8)(val2 >> 8 & 0xff);
@@ -6709,7 +8337,7 @@ out_not_found:
static int __devinit bnx2x_init_bp(struct bnx2x *bp)
{
- int func = BP_FUNC(bp);
+ int func;
int timer_interval;
int rc;
@@ -6729,7 +8357,13 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
rc = bnx2x_get_hwinfo(bp);
+ if (!rc)
+ rc = bnx2x_alloc_mem_bp(bp);
+
bnx2x_read_fwinfo(bp);
+
+ func = BP_FUNC(bp);
+
/* need to reset chip if undi was active */
if (!BP_NOMCP(bp))
bnx2x_undi_unload(bp);
@@ -6771,13 +8405,12 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
bp->mrrs = mrrs;
bp->tx_ring_size = MAX_TX_AVAIL;
- bp->rx_ring_size = MAX_RX_AVAIL;
bp->rx_csum = 1;
/* make sure that the numbers are in the right granularity */
- bp->tx_ticks = (50 / (4 * BNX2X_BTR)) * (4 * BNX2X_BTR);
- bp->rx_ticks = (25 / (4 * BNX2X_BTR)) * (4 * BNX2X_BTR);
+ bp->tx_ticks = (50 / BNX2X_BTR) * BNX2X_BTR;
+ bp->rx_ticks = (25 / BNX2X_BTR) * BNX2X_BTR;
timer_interval = (CHIP_REV_IS_SLOW(bp) ? 5*HZ : HZ);
bp->current_interval = (poll ? poll : timer_interval);
@@ -6869,81 +8502,22 @@ void bnx2x_set_rx_mode(struct net_device *dev)
if (dev->flags & IFF_PROMISC)
rx_mode = BNX2X_RX_MODE_PROMISC;
-
else if ((dev->flags & IFF_ALLMULTI) ||
((netdev_mc_count(dev) > BNX2X_MAX_MULTICAST) &&
CHIP_IS_E1(bp)))
rx_mode = BNX2X_RX_MODE_ALLMULTI;
-
else { /* some multicasts */
if (CHIP_IS_E1(bp)) {
- int i, old, offset;
- struct netdev_hw_addr *ha;
- struct mac_configuration_cmd *config =
- bnx2x_sp(bp, mcast_config);
-
- i = 0;
- netdev_for_each_mc_addr(ha, dev) {
- config->config_table[i].
- cam_entry.msb_mac_addr =
- swab16(*(u16 *)&ha->addr[0]);
- config->config_table[i].
- cam_entry.middle_mac_addr =
- swab16(*(u16 *)&ha->addr[2]);
- config->config_table[i].
- cam_entry.lsb_mac_addr =
- swab16(*(u16 *)&ha->addr[4]);
- config->config_table[i].cam_entry.flags =
- cpu_to_le16(port);
- config->config_table[i].
- target_table_entry.flags = 0;
- config->config_table[i].target_table_entry.
- clients_bit_vector =
- cpu_to_le32(1 << BP_L_ID(bp));
- config->config_table[i].
- target_table_entry.vlan_id = 0;
-
- DP(NETIF_MSG_IFUP,
- "setting MCAST[%d] (%04x:%04x:%04x)\n", i,
- config->config_table[i].
- cam_entry.msb_mac_addr,
- config->config_table[i].
- cam_entry.middle_mac_addr,
- config->config_table[i].
- cam_entry.lsb_mac_addr);
- i++;
- }
- old = config->hdr.length;
- if (old > i) {
- for (; i < old; i++) {
- if (CAM_IS_INVALID(config->
- config_table[i])) {
- /* already invalidated */
- break;
- }
- /* invalidate */
- CAM_INVALIDATE(config->
- config_table[i]);
- }
- }
-
- if (CHIP_REV_IS_SLOW(bp))
- offset = BNX2X_MAX_EMUL_MULTI*(1 + port);
- else
- offset = BNX2X_MAX_MULTICAST*(1 + port);
-
- config->hdr.length = i;
- config->hdr.offset = offset;
- config->hdr.client_id = bp->fp->cl_id;
- config->hdr.reserved1 = 0;
-
- bp->set_mac_pending++;
- smp_wmb();
+ /*
+ * set mc list, do not wait as wait implies sleep
+ * and set_rx_mode can be invoked from non-sleepable
+ * context
+ */
+ u8 offset = (CHIP_REV_IS_SLOW(bp) ?
+ BNX2X_MAX_EMUL_MULTI*(1 + port) :
+ BNX2X_MAX_MULTICAST*(1 + port));
- bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_SET_MAC, 0,
- U64_HI(bnx2x_sp_mapping(bp, mcast_config)),
- U64_LO(bnx2x_sp_mapping(bp, mcast_config)),
- 0);
+ bnx2x_set_e1_mc_list(bp, offset);
} else { /* E1H */
/* Accept one or more multicasts */
struct netdev_hw_addr *ha;
@@ -6955,9 +8529,10 @@ void bnx2x_set_rx_mode(struct net_device *dev)
netdev_for_each_mc_addr(ha, dev) {
DP(NETIF_MSG_IFUP, "Adding mcast MAC: %pM\n",
- ha->addr);
+ bnx2x_mc_addr(ha));
- crc = crc32c_le(0, ha->addr, ETH_ALEN);
+ crc = crc32c_le(0, bnx2x_mc_addr(ha),
+ ETH_ALEN);
bit = (crc >> 24) & 0xff;
regidx = bit >> 5;
bit &= 0x1f;
@@ -6974,7 +8549,6 @@ void bnx2x_set_rx_mode(struct net_device *dev)
bnx2x_set_storm_rx_mode(bp);
}
-
/* called with rtnl_lock */
static int bnx2x_mdio_read(struct net_device *netdev, int prtad,
int devad, u16 addr)
@@ -6982,23 +8556,15 @@ static int bnx2x_mdio_read(struct net_device *netdev, int prtad,
struct bnx2x *bp = netdev_priv(netdev);
u16 value;
int rc;
- u32 phy_type = XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config);
DP(NETIF_MSG_LINK, "mdio_read: prtad 0x%x, devad 0x%x, addr 0x%x\n",
prtad, devad, addr);
- if (prtad != bp->mdio.prtad) {
- DP(NETIF_MSG_LINK, "prtad missmatch (cmd:0x%x != bp:0x%x)\n",
- prtad, bp->mdio.prtad);
- return -EINVAL;
- }
-
/* The HW expects different devad if CL22 is used */
devad = (devad == MDIO_DEVAD_NONE) ? DEFAULT_PHY_DEV_ADDR : devad;
bnx2x_acquire_phy_lock(bp);
- rc = bnx2x_cl45_read(bp, BP_PORT(bp), phy_type, prtad,
- devad, addr, &value);
+ rc = bnx2x_phy_read(&bp->link_params, prtad, devad, addr, &value);
bnx2x_release_phy_lock(bp);
DP(NETIF_MSG_LINK, "mdio_read_val 0x%x rc = 0x%x\n", value, rc);
@@ -7012,24 +8578,16 @@ static int bnx2x_mdio_write(struct net_device *netdev, int prtad, int devad,
u16 addr, u16 value)
{
struct bnx2x *bp = netdev_priv(netdev);
- u32 ext_phy_type = XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config);
int rc;
DP(NETIF_MSG_LINK, "mdio_write: prtad 0x%x, devad 0x%x, addr 0x%x,"
" value 0x%x\n", prtad, devad, addr, value);
- if (prtad != bp->mdio.prtad) {
- DP(NETIF_MSG_LINK, "prtad missmatch (cmd:0x%x != bp:0x%x)\n",
- prtad, bp->mdio.prtad);
- return -EINVAL;
- }
-
/* The HW expects different devad if CL22 is used */
devad = (devad == MDIO_DEVAD_NONE) ? DEFAULT_PHY_DEV_ADDR : devad;
bnx2x_acquire_phy_lock(bp);
- rc = bnx2x_cl45_write(bp, BP_PORT(bp), ext_phy_type, prtad,
- devad, addr, value);
+ rc = bnx2x_phy_write(&bp->link_params, prtad, devad, addr, value);
bnx2x_release_phy_lock(bp);
return rc;
}
@@ -7070,9 +8628,6 @@ static const struct net_device_ops bnx2x_netdev_ops = {
.ndo_do_ioctl = bnx2x_ioctl,
.ndo_change_mtu = bnx2x_change_mtu,
.ndo_tx_timeout = bnx2x_tx_timeout,
-#ifdef BCM_VLAN
- .ndo_vlan_rx_register = bnx2x_vlan_rx_register,
-#endif
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = poll_bnx2x,
#endif
@@ -7090,7 +8645,7 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
bp->dev = dev;
bp->pdev = pdev;
bp->flags = 0;
- bp->func = PCI_FUNC(pdev->devfn);
+ bp->pf_num = PCI_FUNC(pdev->devfn);
rc = pci_enable_device(pdev);
if (rc) {
@@ -7172,7 +8727,7 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
}
bp->doorbells = ioremap_nocache(pci_resource_start(pdev, 2),
- min_t(u64, BNX2X_DB_SIZE,
+ min_t(u64, BNX2X_DB_SIZE(bp),
pci_resource_len(pdev, 2)));
if (!bp->doorbells) {
dev_err(&bp->pdev->dev,
@@ -7204,9 +8759,7 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
dev->features |= NETIF_F_HIGHDMA;
dev->features |= (NETIF_F_TSO | NETIF_F_TSO_ECN);
dev->features |= NETIF_F_TSO6;
-#ifdef BCM_VLAN
dev->features |= (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX);
- bp->flags |= (HW_VLAN_RX_FLAG | HW_VLAN_TX_FLAG);
dev->vlan_features |= NETIF_F_SG;
dev->vlan_features |= NETIF_F_HW_CSUM;
@@ -7214,7 +8767,6 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
dev->vlan_features |= NETIF_F_HIGHDMA;
dev->vlan_features |= (NETIF_F_TSO | NETIF_F_TSO_ECN);
dev->vlan_features |= NETIF_F_TSO6;
-#endif
/* get_port_hwinfo() will set prtad and mmds properly */
bp->mdio.prtad = MDIO_PRTAD_NONE;
@@ -7259,7 +8811,7 @@ static void __devinit bnx2x_get_pcie_width_speed(struct bnx2x *bp,
*speed = (val & PCICFG_LINK_SPEED) >> PCICFG_LINK_SPEED_SHIFT;
}
-static int __devinit bnx2x_check_firmware(struct bnx2x *bp)
+static int bnx2x_check_firmware(struct bnx2x *bp)
{
const struct firmware *firmware = bp->firmware;
struct bnx2x_fw_file_hdr *fw_hdr;
@@ -7348,6 +8900,30 @@ static inline void bnx2x_prep_ops(const u8 *_source, u8 *_target, u32 n)
}
}
+/**
+ * IRO array is stored in the following format:
+ * {base(24bit), m1(16bit), m2(16bit), m3(16bit), size(16bit) }
+ */
+static inline void bnx2x_prep_iro(const u8 *_source, u8 *_target, u32 n)
+{
+ const __be32 *source = (const __be32 *)_source;
+ struct iro *target = (struct iro *)_target;
+ u32 i, j, tmp;
+
+ for (i = 0, j = 0; i < n/sizeof(struct iro); i++) {
+ target[i].base = be32_to_cpu(source[j]);
+ j++;
+ tmp = be32_to_cpu(source[j]);
+ target[i].m1 = (tmp >> 16) & 0xffff;
+ target[i].m2 = tmp & 0xffff;
+ j++;
+ tmp = be32_to_cpu(source[j]);
+ target[i].m3 = (tmp >> 16) & 0xffff;
+ target[i].size = tmp & 0xffff;
+ j++;
+ }
+}
+
static inline void be16_to_cpu_n(const u8 *_source, u8 *_target, u32 n)
{
const __be16 *source = (const __be16 *)_source;
@@ -7370,7 +8946,7 @@ do { \
(u8 *)bp->arr, len); \
} while (0)
-static int __devinit bnx2x_init_firmware(struct bnx2x *bp, struct device *dev)
+int bnx2x_init_firmware(struct bnx2x *bp)
{
const char *fw_file_name;
struct bnx2x_fw_file_hdr *fw_hdr;
@@ -7380,22 +8956,24 @@ static int __devinit bnx2x_init_firmware(struct bnx2x *bp, struct device *dev)
fw_file_name = FW_FILE_NAME_E1;
else if (CHIP_IS_E1H(bp))
fw_file_name = FW_FILE_NAME_E1H;
+ else if (CHIP_IS_E2(bp))
+ fw_file_name = FW_FILE_NAME_E2;
else {
- dev_err(dev, "Unsupported chip revision\n");
+ BNX2X_ERR("Unsupported chip revision\n");
return -EINVAL;
}
- dev_info(dev, "Loading %s\n", fw_file_name);
+ BNX2X_DEV_INFO("Loading %s\n", fw_file_name);
- rc = request_firmware(&bp->firmware, fw_file_name, dev);
+ rc = request_firmware(&bp->firmware, fw_file_name, &bp->pdev->dev);
if (rc) {
- dev_err(dev, "Can't load firmware file %s\n", fw_file_name);
+ BNX2X_ERR("Can't load firmware file %s\n", fw_file_name);
goto request_firmware_exit;
}
rc = bnx2x_check_firmware(bp);
if (rc) {
- dev_err(dev, "Corrupt firmware file %s\n", fw_file_name);
+ BNX2X_ERR("Corrupt firmware file %s\n", fw_file_name);
goto request_firmware_exit;
}
@@ -7429,9 +9007,13 @@ static int __devinit bnx2x_init_firmware(struct bnx2x *bp, struct device *dev)
be32_to_cpu(fw_hdr->csem_int_table_data.offset);
INIT_CSEM_PRAM_DATA(bp) = bp->firmware->data +
be32_to_cpu(fw_hdr->csem_pram_data.offset);
+ /* IRO */
+ BNX2X_ALLOC_AND_SET(iro_arr, iro_alloc_err, bnx2x_prep_iro);
return 0;
+iro_alloc_err:
+ kfree(bp->init_ops_offsets);
init_offsets_alloc_err:
kfree(bp->init_ops);
init_ops_alloc_err:
@@ -7442,6 +9024,15 @@ request_firmware_exit:
return rc;
}
+static inline int bnx2x_set_qm_cid_count(struct bnx2x *bp, int l2_cid_count)
+{
+ int cid_count = L2_FP_COUNT(l2_cid_count);
+
+#ifdef BCM_CNIC
+ cid_count += CNIC_CID_MAX;
+#endif
+ return roundup(cid_count, QM_CID_ROUND);
+}
static int __devinit bnx2x_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
@@ -7449,10 +9040,30 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
struct net_device *dev = NULL;
struct bnx2x *bp;
int pcie_width, pcie_speed;
- int rc;
+ int rc, cid_count;
+
+ switch (ent->driver_data) {
+ case BCM57710:
+ case BCM57711:
+ case BCM57711E:
+ cid_count = FP_SB_MAX_E1x;
+ break;
+
+ case BCM57712:
+ case BCM57712E:
+ cid_count = FP_SB_MAX_E2;
+ break;
+
+ default:
+ pr_err("Unknown board_type (%ld), aborting\n",
+ ent->driver_data);
+ return ENODEV;
+ }
+
+ cid_count += CNIC_CONTEXT_USE;
/* dev zeroed in init_etherdev */
- dev = alloc_etherdev_mq(sizeof(*bp), MAX_CONTEXT);
+ dev = alloc_etherdev_mq(sizeof(*bp), cid_count);
if (!dev) {
dev_err(&pdev->dev, "Cannot allocate net device\n");
return -ENOMEM;
@@ -7463,6 +9074,8 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
pci_set_drvdata(pdev, dev);
+ bp->l2_cid_count = cid_count;
+
rc = bnx2x_init_dev(pdev, dev);
if (rc < 0) {
free_netdev(dev);
@@ -7473,12 +9086,8 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
if (rc)
goto init_one_exit;
- /* Set init arrays */
- rc = bnx2x_init_firmware(bp, &pdev->dev);
- if (rc) {
- dev_err(&pdev->dev, "Error loading firmware\n");
- goto init_one_exit;
- }
+ /* calc qm_cid_count */
+ bp->qm_cid_count = bnx2x_set_qm_cid_count(bp, cid_count);
rc = register_netdev(dev);
if (rc) {
@@ -7486,11 +9095,23 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
goto init_one_exit;
}
+ /* Configure interupt mode: try to enable MSI-X/MSI if
+ * needed, set bp->num_queues appropriately.
+ */
+ bnx2x_set_int_mode(bp);
+
+ /* Add all NAPI objects */
+ bnx2x_add_all_napi(bp);
+
bnx2x_get_pcie_width_speed(bp, &pcie_width, &pcie_speed);
+
netdev_info(dev, "%s (%c%d) PCI-E x%d %s found at mem %lx,"
" IRQ %d, ", board_info[ent->driver_data].name,
(CHIP_REV(bp) >> 12) + 'A', (CHIP_METAL(bp) >> 4),
- pcie_width, (pcie_speed == 2) ? "5GHz (Gen2)" : "2.5GHz",
+ pcie_width,
+ ((!CHIP_IS_E2(bp) && pcie_speed == 2) ||
+ (CHIP_IS_E2(bp) && pcie_speed == 1)) ?
+ "5GHz (Gen2)" : "2.5GHz",
dev->base_addr, bp->pdev->irq);
pr_cont("node addr %pM\n", dev->dev_addr);
@@ -7527,20 +9148,23 @@ static void __devexit bnx2x_remove_one(struct pci_dev *pdev)
unregister_netdev(dev);
+ /* Delete all NAPI objects */
+ bnx2x_del_all_napi(bp);
+
+ /* Disable MSI/MSI-X */
+ bnx2x_disable_msi(bp);
+
/* Make sure RESET task is not scheduled before continuing */
cancel_delayed_work_sync(&bp->reset_task);
- kfree(bp->init_ops_offsets);
- kfree(bp->init_ops);
- kfree(bp->init_data);
- release_firmware(bp->firmware);
-
if (bp->regview)
iounmap(bp->regview);
if (bp->doorbells)
iounmap(bp->doorbells);
+ bnx2x_free_mem_bp(bp);
+
free_netdev(dev);
if (atomic_read(&pdev->enable_cnt) == 1)
@@ -7566,22 +9190,14 @@ static int bnx2x_eeh_nic_unload(struct bnx2x *bp)
DP(BNX2X_MSG_STATS, "stats_state - DISABLED\n");
/* Release IRQs */
- bnx2x_free_irq(bp, false);
-
- if (CHIP_IS_E1(bp)) {
- struct mac_configuration_cmd *config =
- bnx2x_sp(bp, mcast_config);
-
- for (i = 0; i < config->hdr.length; i++)
- CAM_INVALIDATE(config->config_table[i]);
- }
+ bnx2x_free_irq(bp);
/* Free SKBs, SGEs, TPA pool and driver internals */
bnx2x_free_skbs(bp);
+
for_each_queue(bp, i)
bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE);
- for_each_queue(bp, i)
- netif_napi_del(&bnx2x_fp(bp, i, napi));
+
bnx2x_free_mem(bp);
bp->state = BNX2X_STATE_CLOSED;
@@ -7613,8 +9229,9 @@ static void bnx2x_eeh_recover(struct bnx2x *bp)
BNX2X_ERR("BAD MCP validity signature\n");
if (!BP_NOMCP(bp)) {
- bp->fw_seq = (SHMEM_RD(bp, func_mb[BP_FUNC(bp)].drv_mb_header)
- & DRV_MSG_SEQ_NUMBER_MASK);
+ bp->fw_seq =
+ (SHMEM_RD(bp, func_mb[BP_FW_MB_IDX(bp)].drv_mb_header) &
+ DRV_MSG_SEQ_NUMBER_MASK);
BNX2X_DEV_INFO("fw_seq 0x%08x\n", bp->fw_seq);
}
}
@@ -7697,7 +9314,8 @@ static void bnx2x_io_resume(struct pci_dev *pdev)
struct bnx2x *bp = netdev_priv(dev);
if (bp->recovery_state != BNX2X_RECOVERY_DONE) {
- printk(KERN_ERR "Handling parity error recovery. Try again later\n");
+ printk(KERN_ERR "Handling parity error recovery. "
+ "Try again later\n");
return;
}
@@ -7772,19 +9390,53 @@ static void bnx2x_cnic_sp_post(struct bnx2x *bp, int count)
#endif
spin_lock_bh(&bp->spq_lock);
+ BUG_ON(bp->cnic_spq_pending < count);
bp->cnic_spq_pending -= count;
- for (; bp->cnic_spq_pending < bp->cnic_eth_dev.max_kwqe_pending;
- bp->cnic_spq_pending++) {
- if (!bp->cnic_kwq_pending)
+ for (; bp->cnic_kwq_pending; bp->cnic_kwq_pending--) {
+ u16 type = (le16_to_cpu(bp->cnic_kwq_cons->hdr.type)
+ & SPE_HDR_CONN_TYPE) >>
+ SPE_HDR_CONN_TYPE_SHIFT;
+
+ /* Set validation for iSCSI L2 client before sending SETUP
+ * ramrod
+ */
+ if (type == ETH_CONNECTION_TYPE) {
+ u8 cmd = (le32_to_cpu(bp->cnic_kwq_cons->
+ hdr.conn_and_cmd_data) >>
+ SPE_HDR_CMD_ID_SHIFT) & 0xff;
+
+ if (cmd == RAMROD_CMD_ID_ETH_CLIENT_SETUP)
+ bnx2x_set_ctx_validation(&bp->context.
+ vcxt[BNX2X_ISCSI_ETH_CID].eth,
+ HW_CID(bp, BNX2X_ISCSI_ETH_CID));
+ }
+
+ /* There may be not more than 8 L2 and COMMON SPEs and not more
+ * than 8 L5 SPEs in the air.
+ */
+ if ((type == NONE_CONNECTION_TYPE) ||
+ (type == ETH_CONNECTION_TYPE)) {
+ if (!atomic_read(&bp->spq_left))
+ break;
+ else
+ atomic_dec(&bp->spq_left);
+ } else if (type == ISCSI_CONNECTION_TYPE) {
+ if (bp->cnic_spq_pending >=
+ bp->cnic_eth_dev.max_kwqe_pending)
+ break;
+ else
+ bp->cnic_spq_pending++;
+ } else {
+ BNX2X_ERR("Unknown SPE type: %d\n", type);
+ bnx2x_panic();
break;
+ }
spe = bnx2x_sp_get_next(bp);
*spe = *bp->cnic_kwq_cons;
- bp->cnic_kwq_pending--;
-
DP(NETIF_MSG_TIMER, "pending on SPQ %d, on KWQ %d count %d\n",
bp->cnic_spq_pending, bp->cnic_kwq_pending, count);
@@ -7822,8 +9474,8 @@ static int bnx2x_cnic_sp_queue(struct net_device *dev,
DP(NETIF_MSG_TIMER, "L5 SPQE %x %x %x:%x pos %d\n",
spe->hdr.conn_and_cmd_data, spe->hdr.type,
- spe->data.mac_config_addr.hi,
- spe->data.mac_config_addr.lo,
+ spe->data.update_data_addr.hi,
+ spe->data.update_data_addr.lo,
bp->cnic_kwq_pending);
if (bp->cnic_kwq_prod == bp->cnic_kwq_last)
@@ -7889,7 +9541,7 @@ static void bnx2x_cnic_cfc_comp(struct bnx2x *bp, int cid)
ctl.data.comp.cid = cid;
bnx2x_cnic_ctl_send_bh(bp, &ctl);
- bnx2x_cnic_sp_post(bp, 1);
+ bnx2x_cnic_sp_post(bp, 0);
}
static int bnx2x_drv_ctl(struct net_device *dev, struct drv_ctl_info *ctl)
@@ -7906,8 +9558,8 @@ static int bnx2x_drv_ctl(struct net_device *dev, struct drv_ctl_info *ctl)
break;
}
- case DRV_CTL_COMPLETION_CMD: {
- int count = ctl->data.comp.comp_count;
+ case DRV_CTL_RET_L5_SPQ_CREDIT_CMD: {
+ int count = ctl->data.credit.credit_count;
bnx2x_cnic_sp_post(bp, count);
break;
@@ -7917,8 +9569,24 @@ static int bnx2x_drv_ctl(struct net_device *dev, struct drv_ctl_info *ctl)
case DRV_CTL_START_L2_CMD: {
u32 cli = ctl->data.ring.client_id;
- bp->rx_mode_cl_mask |= (1 << cli);
- bnx2x_set_storm_rx_mode(bp);
+ /* Set iSCSI MAC address */
+ bnx2x_set_iscsi_eth_mac_addr(bp, 1);
+
+ mmiowb();
+ barrier();
+
+ /* Start accepting on iSCSI L2 ring. Accept all multicasts
+ * because it's the only way for UIO Client to accept
+ * multicasts (in non-promiscuous mode only one Client per
+ * function will receive multicast packets (leading in our
+ * case).
+ */
+ bnx2x_rxq_set_mac_filters(bp, cli,
+ BNX2X_ACCEPT_UNICAST |
+ BNX2X_ACCEPT_BROADCAST |
+ BNX2X_ACCEPT_ALL_MULTICAST);
+ storm_memset_mac_filters(bp, &bp->mac_filters, BP_FUNC(bp));
+
break;
}
@@ -7926,8 +9594,23 @@ static int bnx2x_drv_ctl(struct net_device *dev, struct drv_ctl_info *ctl)
case DRV_CTL_STOP_L2_CMD: {
u32 cli = ctl->data.ring.client_id;
- bp->rx_mode_cl_mask &= ~(1 << cli);
- bnx2x_set_storm_rx_mode(bp);
+ /* Stop accepting on iSCSI L2 ring */
+ bnx2x_rxq_set_mac_filters(bp, cli, BNX2X_ACCEPT_NONE);
+ storm_memset_mac_filters(bp, &bp->mac_filters, BP_FUNC(bp));
+
+ mmiowb();
+ barrier();
+
+ /* Unset iSCSI L2 MAC */
+ bnx2x_set_iscsi_eth_mac_addr(bp, 0);
+ break;
+ }
+ case DRV_CTL_RET_L2_SPQ_CREDIT_CMD: {
+ int count = ctl->data.credit.credit_count;
+
+ smp_mb__before_atomic_inc();
+ atomic_add(count, &bp->spq_left);
+ smp_mb__after_atomic_inc();
break;
}
@@ -7951,10 +9634,16 @@ void bnx2x_setup_cnic_irq_info(struct bnx2x *bp)
cp->drv_state &= ~CNIC_DRV_STATE_USING_MSIX;
cp->irq_arr[0].irq_flags &= ~CNIC_IRQ_FL_MSIX;
}
- cp->irq_arr[0].status_blk = bp->cnic_sb;
+ if (CHIP_IS_E2(bp))
+ cp->irq_arr[0].status_blk = (void *)bp->cnic_sb.e2_sb;
+ else
+ cp->irq_arr[0].status_blk = (void *)bp->cnic_sb.e1x_sb;
+
cp->irq_arr[0].status_blk_num = CNIC_SB_ID(bp);
+ cp->irq_arr[0].status_blk_num2 = CNIC_IGU_SB_ID(bp);
cp->irq_arr[1].status_blk = bp->def_status_blk;
cp->irq_arr[1].status_blk_num = DEF_SB_ID;
+ cp->irq_arr[1].status_blk_num2 = DEF_SB_IGU_ID;
cp->num_irq = 2;
}
@@ -7986,12 +9675,10 @@ static int bnx2x_register_cnic(struct net_device *dev, struct cnic_ops *ops,
cp->num_irq = 0;
cp->drv_state = CNIC_DRV_STATE_REGD;
-
- bnx2x_init_sb(bp, bp->cnic_sb, bp->cnic_sb_mapping, CNIC_SB_ID(bp));
+ cp->iro_arr = bp->iro_arr;
bnx2x_setup_cnic_irq_info(bp);
- bnx2x_set_iscsi_eth_mac_addr(bp, 1);
- bp->cnic_flags |= BNX2X_CNIC_FLAG_MAC_SET;
+
rcu_assign_pointer(bp->cnic_ops, ops);
return 0;
@@ -8028,15 +9715,24 @@ struct cnic_eth_dev *bnx2x_cnic_probe(struct net_device *dev)
cp->io_base = bp->regview;
cp->io_base2 = bp->doorbells;
cp->max_kwqe_pending = 8;
- cp->ctx_blk_size = CNIC_CTX_PER_ILT * sizeof(union cdu_context);
- cp->ctx_tbl_offset = FUNC_ILT_BASE(BP_FUNC(bp)) + 1;
+ cp->ctx_blk_size = CDU_ILT_PAGE_SZ;
+ cp->ctx_tbl_offset = FUNC_ILT_BASE(BP_FUNC(bp)) +
+ bnx2x_cid_ilt_lines(bp);
cp->ctx_tbl_len = CNIC_ILT_LINES;
- cp->starting_cid = BCM_CNIC_CID_START;
+ cp->starting_cid = bnx2x_cid_ilt_lines(bp) * ILT_PAGE_CIDS;
cp->drv_submit_kwqes_16 = bnx2x_cnic_sp_queue;
cp->drv_ctl = bnx2x_drv_ctl;
cp->drv_register_cnic = bnx2x_register_cnic;
cp->drv_unregister_cnic = bnx2x_unregister_cnic;
-
+ cp->iscsi_l2_client_id = BNX2X_ISCSI_ETH_CL_ID;
+ cp->iscsi_l2_cid = BNX2X_ISCSI_ETH_CID;
+
+ DP(BNX2X_MSG_SP, "page_size %d, tbl_offset %d, tbl_lines %d, "
+ "starting cid %d\n",
+ cp->ctx_blk_size,
+ cp->ctx_tbl_offset,
+ cp->ctx_tbl_len,
+ cp->starting_cid);
return cp;
}
EXPORT_SYMBOL(bnx2x_cnic_probe);
diff --git a/drivers/net/bnx2x/bnx2x_reg.h b/drivers/net/bnx2x/bnx2x_reg.h
index a1f3bf0cd630..1cefe489a955 100644
--- a/drivers/net/bnx2x/bnx2x_reg.h
+++ b/drivers/net/bnx2x/bnx2x_reg.h
@@ -1,6 +1,6 @@
/* bnx2x_reg.h: Broadcom Everest network driver.
*
- * Copyright (c) 2007-2009 Broadcom Corporation
+ * Copyright (c) 2007-2010 Broadcom Corporation
*
* 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
@@ -19,7 +19,20 @@
*
*/
-
+#define ATC_ATC_INT_STS_REG_ADDRESS_ERROR (0x1<<0)
+#define ATC_ATC_INT_STS_REG_ATC_GPA_MULTIPLE_HITS (0x1<<2)
+#define ATC_ATC_INT_STS_REG_ATC_IREQ_LESS_THAN_STU (0x1<<5)
+#define ATC_ATC_INT_STS_REG_ATC_RCPL_TO_EMPTY_CNT (0x1<<3)
+#define ATC_ATC_INT_STS_REG_ATC_TCPL_ERROR (0x1<<4)
+#define ATC_ATC_INT_STS_REG_ATC_TCPL_TO_NOT_PEND (0x1<<1)
+/* [RW 1] Initiate the ATC array - reset all the valid bits */
+#define ATC_REG_ATC_INIT_ARRAY 0x1100b8
+/* [R 1] ATC initalization done */
+#define ATC_REG_ATC_INIT_DONE 0x1100bc
+/* [RC 6] Interrupt register #0 read clear */
+#define ATC_REG_ATC_INT_STS_CLR 0x1101c0
+/* [RW 19] Interrupt mask register #0 read/write */
+#define BRB1_REG_BRB1_INT_MASK 0x60128
/* [R 19] Interrupt register #0 read */
#define BRB1_REG_BRB1_INT_STS 0x6011c
/* [RW 4] Parity mask register #0 read/write */
@@ -27,9 +40,31 @@
/* [R 4] Parity register #0 read */
#define BRB1_REG_BRB1_PRTY_STS 0x6012c
/* [RW 10] At address BRB1_IND_FREE_LIST_PRS_CRDT initialize free head. At
- address BRB1_IND_FREE_LIST_PRS_CRDT+1 initialize free tail. At address
- BRB1_IND_FREE_LIST_PRS_CRDT+2 initialize parser initial credit. */
+ * address BRB1_IND_FREE_LIST_PRS_CRDT+1 initialize free tail. At address
+ * BRB1_IND_FREE_LIST_PRS_CRDT+2 initialize parser initial credit. Warning -
+ * following reset the first rbc access to this reg must be write; there can
+ * be no more rbc writes after the first one; there can be any number of rbc
+ * read following the first write; rbc access not following these rules will
+ * result in hang condition. */
#define BRB1_REG_FREE_LIST_PRS_CRDT 0x60200
+/* [RW 10] The number of free blocks below which the full signal to class 0
+ * is asserted */
+#define BRB1_REG_FULL_0_XOFF_THRESHOLD_0 0x601d0
+/* [RW 10] The number of free blocks above which the full signal to class 0
+ * is de-asserted */
+#define BRB1_REG_FULL_0_XON_THRESHOLD_0 0x601d4
+/* [RW 10] The number of free blocks below which the full signal to class 1
+ * is asserted */
+#define BRB1_REG_FULL_1_XOFF_THRESHOLD_0 0x601d8
+/* [RW 10] The number of free blocks above which the full signal to class 1
+ * is de-asserted */
+#define BRB1_REG_FULL_1_XON_THRESHOLD_0 0x601dc
+/* [RW 10] The number of free blocks below which the full signal to the LB
+ * port is asserted */
+#define BRB1_REG_FULL_LB_XOFF_THRESHOLD 0x601e0
+/* [RW 10] The number of free blocks above which the full signal to the LB
+ * port is de-asserted */
+#define BRB1_REG_FULL_LB_XON_THRESHOLD 0x601e4
/* [RW 10] The number of free blocks above which the High_llfc signal to
interface #n is de-asserted. */
#define BRB1_REG_HIGH_LLFC_HIGH_THRESHOLD_0 0x6014c
@@ -44,6 +79,9 @@
/* [RW 10] The number of free blocks below which the Low_llfc signal to
interface #n is asserted. */
#define BRB1_REG_LOW_LLFC_LOW_THRESHOLD_0 0x6015c
+/* [RW 10] The number of blocks guarantied for the MAC port */
+#define BRB1_REG_MAC_GUARANTIED_0 0x601e8
+#define BRB1_REG_MAC_GUARANTIED_1 0x60240
/* [R 24] The number of full blocks. */
#define BRB1_REG_NUM_OF_FULL_BLOCKS 0x60090
/* [ST 32] The number of cycles that the write_full signal towards MAC #0
@@ -55,7 +93,19 @@
asserted. */
#define BRB1_REG_NUM_OF_PAUSE_CYCLES_0 0x600b8
#define BRB1_REG_NUM_OF_PAUSE_CYCLES_1 0x600bc
-/* [RW 10] Write client 0: De-assert pause threshold. */
+/* [RW 10] The number of free blocks below which the pause signal to class 0
+ * is asserted */
+#define BRB1_REG_PAUSE_0_XOFF_THRESHOLD_0 0x601c0
+/* [RW 10] The number of free blocks above which the pause signal to class 0
+ * is de-asserted */
+#define BRB1_REG_PAUSE_0_XON_THRESHOLD_0 0x601c4
+/* [RW 10] The number of free blocks below which the pause signal to class 1
+ * is asserted */
+#define BRB1_REG_PAUSE_1_XOFF_THRESHOLD_0 0x601c8
+/* [RW 10] The number of free blocks above which the pause signal to class 1
+ * is de-asserted */
+#define BRB1_REG_PAUSE_1_XON_THRESHOLD_0 0x601cc
+/* [RW 10] Write client 0: De-assert pause threshold. Not Functional */
#define BRB1_REG_PAUSE_HIGH_THRESHOLD_0 0x60078
#define BRB1_REG_PAUSE_HIGH_THRESHOLD_1 0x6007c
/* [RW 10] Write client 0: Assert pause threshold. */
@@ -362,6 +412,7 @@
#define CFC_REG_NUM_LCIDS_ARRIVING 0x104004
/* [R 9] Number of Leaving LCIDs in Link List Block */
#define CFC_REG_NUM_LCIDS_LEAVING 0x104018
+#define CFC_REG_WEAK_ENABLE_PF 0x104124
/* [RW 8] The event id for aggregated interrupt 0 */
#define CSDM_REG_AGG_INT_EVENT_0 0xc2038
#define CSDM_REG_AGG_INT_EVENT_10 0xc2060
@@ -590,10 +641,17 @@
#define CSEM_REG_TS_8_AS 0x200058
/* [RW 3] The arbitration scheme of time_slot 9 */
#define CSEM_REG_TS_9_AS 0x20005c
+/* [W 7] VF or PF ID for reset error bit. Values 0-63 reset error bit for 64
+ * VF; values 64-67 reset error for 4 PF; values 68-127 are not valid. */
+#define CSEM_REG_VFPF_ERR_NUM 0x200380
/* [RW 1] Parity mask register #0 read/write */
#define DBG_REG_DBG_PRTY_MASK 0xc0a8
/* [R 1] Parity register #0 read */
#define DBG_REG_DBG_PRTY_STS 0xc09c
+/* [RW 1] When set the DMAE will process the commands as in E1.5. 1.The
+ * function that is used is always SRC-PCI; 2.VF_Valid = 0; 3.VFID=0;
+ * 4.Completion function=0; 5.Error handling=0 */
+#define DMAE_REG_BACKWARD_COMP_EN 0x10207c
/* [RW 32] Commands memory. The address to command X; row Y is to calculated
as 14*X+Y. */
#define DMAE_REG_CMD_MEM 0x102400
@@ -742,9 +800,13 @@
#define HC_REG_HC_PRTY_MASK 0x1080a0
/* [R 3] Parity register #0 read */
#define HC_REG_HC_PRTY_STS 0x108094
-#define HC_REG_INT_MASK 0x108108
+/* [RC 3] Parity register #0 read clear */
+#define HC_REG_HC_PRTY_STS_CLR 0x108098
+#define HC_REG_INT_MASK 0x108108
#define HC_REG_LEADING_EDGE_0 0x108040
#define HC_REG_LEADING_EDGE_1 0x108048
+#define HC_REG_MAIN_MEMORY 0x108800
+#define HC_REG_MAIN_MEMORY_SIZE 152
#define HC_REG_P0_PROD_CONS 0x108200
#define HC_REG_P1_PROD_CONS 0x108400
#define HC_REG_PBA_COMMAND 0x108140
@@ -758,6 +820,92 @@
#define HC_REG_USTORM_ADDR_FOR_COALESCE 0x108068
#define HC_REG_VQID_0 0x108008
#define HC_REG_VQID_1 0x10800c
+#define IGU_BLOCK_CONFIGURATION_REG_BACKWARD_COMP_EN (0x1<<1)
+#define IGU_REG_ATTENTION_ACK_BITS 0x130108
+/* [R 4] Debug: attn_fsm */
+#define IGU_REG_ATTN_FSM 0x130054
+#define IGU_REG_ATTN_MSG_ADDR_H 0x13011c
+#define IGU_REG_ATTN_MSG_ADDR_L 0x130120
+/* [R 4] Debug: [3] - attention write done message is pending (0-no pending;
+ * 1-pending). [2:0] = PFID. Pending means attention message was sent; but
+ * write done didnt receive. */
+#define IGU_REG_ATTN_WRITE_DONE_PENDING 0x130030
+#define IGU_REG_BLOCK_CONFIGURATION 0x130000
+#define IGU_REG_COMMAND_REG_32LSB_DATA 0x130124
+#define IGU_REG_COMMAND_REG_CTRL 0x13012c
+/* [WB_R 32] Cleanup bit status per SB. 1 = cleanup is set. 0 = cleanup bit
+ * is clear. The bits in this registers are set and clear via the producer
+ * command. Data valid only in addresses 0-4. all the rest are zero. */
+#define IGU_REG_CSTORM_TYPE_0_SB_CLEANUP 0x130200
+/* [R 5] Debug: ctrl_fsm */
+#define IGU_REG_CTRL_FSM 0x130064
+/* [R 1] data availble for error memory. If this bit is clear do not red
+ * from error_handling_memory. */
+#define IGU_REG_ERROR_HANDLING_DATA_VALID 0x130130
+/* [R 11] Parity register #0 read */
+#define IGU_REG_IGU_PRTY_STS 0x13009c
+/* [R 4] Debug: int_handle_fsm */
+#define IGU_REG_INT_HANDLE_FSM 0x130050
+#define IGU_REG_LEADING_EDGE_LATCH 0x130134
+/* [RW 14] mapping CAM; relevant for E2 operating mode only. [0] - valid.
+ * [6:1] - vector number; [13:7] - FID (if VF - [13] = 0; [12:7] = VF
+ * number; if PF - [13] = 1; [12:10] = 0; [9:7] = PF number); */
+#define IGU_REG_MAPPING_MEMORY 0x131000
+#define IGU_REG_MAPPING_MEMORY_SIZE 136
+#define IGU_REG_PBA_STATUS_LSB 0x130138
+#define IGU_REG_PBA_STATUS_MSB 0x13013c
+#define IGU_REG_PCI_PF_MSI_EN 0x130140
+#define IGU_REG_PCI_PF_MSIX_EN 0x130144
+#define IGU_REG_PCI_PF_MSIX_FUNC_MASK 0x130148
+/* [WB_R 32] Each bit represent the pending bits status for that SB. 0 = no
+ * pending; 1 = pending. Pendings means interrupt was asserted; and write
+ * done was not received. Data valid only in addresses 0-4. all the rest are
+ * zero. */
+#define IGU_REG_PENDING_BITS_STATUS 0x130300
+#define IGU_REG_PF_CONFIGURATION 0x130154
+/* [RW 20] producers only. E2 mode: address 0-135 match to the mapping
+ * memory; 136 - PF0 default prod; 137 PF1 default prod; 138 - PF2 default
+ * prod; 139 PF3 default prod; 140 - PF0 - ATTN prod; 141 - PF1 - ATTN prod;
+ * 142 - PF2 - ATTN prod; 143 - PF3 - ATTN prod; 144-147 reserved. E1.5 mode
+ * - In backward compatible mode; for non default SB; each even line in the
+ * memory holds the U producer and each odd line hold the C producer. The
+ * first 128 producer are for NDSB (PF0 - 0-31; PF1 - 32-63 and so on). The
+ * last 20 producers are for the DSB for each PF. each PF has five segments
+ * (the order inside each segment is PF0; PF1; PF2; PF3) - 128-131 U prods;
+ * 132-135 C prods; 136-139 X prods; 140-143 T prods; 144-147 ATTN prods; */
+#define IGU_REG_PROD_CONS_MEMORY 0x132000
+/* [R 3] Debug: pxp_arb_fsm */
+#define IGU_REG_PXP_ARB_FSM 0x130068
+/* [RW 6] Write one for each bit will reset the appropriate memory. When the
+ * memory reset finished the appropriate bit will be clear. Bit 0 - mapping
+ * memory; Bit 1 - SB memory; Bit 2 - SB interrupt and mask register; Bit 3
+ * - MSIX memory; Bit 4 - PBA memory; Bit 5 - statistics; */
+#define IGU_REG_RESET_MEMORIES 0x130158
+/* [R 4] Debug: sb_ctrl_fsm */
+#define IGU_REG_SB_CTRL_FSM 0x13004c
+#define IGU_REG_SB_INT_BEFORE_MASK_LSB 0x13015c
+#define IGU_REG_SB_INT_BEFORE_MASK_MSB 0x130160
+#define IGU_REG_SB_MASK_LSB 0x130164
+#define IGU_REG_SB_MASK_MSB 0x130168
+/* [RW 16] Number of command that were dropped without causing an interrupt
+ * due to: read access for WO BAR address; or write access for RO BAR
+ * address or any access for reserved address or PCI function error is set
+ * and address is not MSIX; PBA or cleanup */
+#define IGU_REG_SILENT_DROP 0x13016c
+/* [RW 10] Number of MSI/MSIX/ATTN messages sent for the function: 0-63 -
+ * number of MSIX messages per VF; 64-67 - number of MSI/MSIX messages per
+ * PF; 68-71 number of ATTN messages per PF */
+#define IGU_REG_STATISTIC_NUM_MESSAGE_SENT 0x130800
+/* [RW 32] Number of cycles the timer mask masking the IGU interrupt when a
+ * timer mask command arrives. Value must be bigger than 100. */
+#define IGU_REG_TIMER_MASKING_VALUE 0x13003c
+#define IGU_REG_TRAILING_EDGE_LATCH 0x130104
+#define IGU_REG_VF_CONFIGURATION 0x130170
+/* [WB_R 32] Each bit represent write done pending bits status for that SB
+ * (MSI/MSIX message was sent and write done was not received yet). 0 =
+ * clear; 1 = set. Data valid only in addresses 0-4. all the rest are zero. */
+#define IGU_REG_WRITE_DONE_PENDING 0x130480
+#define MCP_A_REG_MCPR_SCRATCH 0x3a0000
#define MCP_REG_MCPR_NVM_ACCESS_ENABLE 0x86424
#define MCP_REG_MCPR_NVM_ADDR 0x8640c
#define MCP_REG_MCPR_NVM_CFG4 0x8642c
@@ -880,6 +1028,11 @@
rom_parity; [29] MCP Latched ump_rx_parity; [30] MCP Latched
ump_tx_parity; [31] MCP Latched scpad_parity; */
#define MISC_REG_AEU_AFTER_INVERT_4_MCP 0xa458
+/* [R 32] Read fifth 32 bit after inversion of function 0. Mapped as
+ * follows: [0] PGLUE config_space; [1] PGLUE misc_flr; [2] PGLUE B RBC
+ * attention [3] PGLUE B RBC parity; [4] ATC attention; [5] ATC parity; [6]
+ * CNIG attention (reserved); [7] CNIG parity (reserved); [31-8] Reserved; */
+#define MISC_REG_AEU_AFTER_INVERT_5_FUNC_0 0xa700
/* [W 14] write to this register results with the clear of the latched
signals; one in d0 clears RBCR latch; one in d1 clears RBCT latch; one in
d2 clears RBCN latch; one in d3 clears RBCU latch; one in d4 clears RBCP
@@ -1251,6 +1404,7 @@
#define MISC_REG_E1HMF_MODE 0xa5f8
/* [RW 32] Debug only: spare RW register reset by core reset */
#define MISC_REG_GENERIC_CR_0 0xa460
+#define MISC_REG_GENERIC_CR_1 0xa464
/* [RW 32] Debug only: spare RW register reset by por reset */
#define MISC_REG_GENERIC_POR_1 0xa474
/* [RW 32] GPIO. [31-28] FLOAT port 0; [27-24] FLOAT port 0; When any of
@@ -1373,6 +1527,14 @@
#define MISC_REG_PLL_STORM_CTRL_2 0xa298
#define MISC_REG_PLL_STORM_CTRL_3 0xa29c
#define MISC_REG_PLL_STORM_CTRL_4 0xa2a0
+/* [R 1] Status of 4 port mode enable input pin. */
+#define MISC_REG_PORT4MODE_EN 0xa750
+/* [RW 2] 4 port mode enable overwrite.[0] - Overwrite control; if it is 0 -
+ * the port4mode_en output is equal to 4 port mode input pin; if it is 1 -
+ * the port4mode_en output is equal to bit[1] of this register; [1] -
+ * Overwrite value. If bit[0] of this register is 1 this is the value that
+ * receives the port4mode_en output . */
+#define MISC_REG_PORT4MODE_EN_OVWR 0xa720
/* [RW 32] reset reg#2; rite/read one = the specific block is out of reset;
write/read zero = the specific block is in reset; addr 0-wr- the write
value will be written to the register; addr 1-set - one will be written
@@ -1656,8 +1818,91 @@
/* [R 32] Interrupt register #0 read */
#define NIG_REG_NIG_INT_STS_0 0x103b0
#define NIG_REG_NIG_INT_STS_1 0x103c0
-/* [R 32] Parity register #0 read */
+/* [R 32] Legacy E1 and E1H location for parity error status register. */
#define NIG_REG_NIG_PRTY_STS 0x103d0
+/* [R 32] Parity register #0 read */
+#define NIG_REG_NIG_PRTY_STS_0 0x183bc
+#define NIG_REG_NIG_PRTY_STS_1 0x183cc
+/* [RW 6] Bit-map indicating which L2 hdrs may appear after the basic
+ * Ethernet header. */
+#define NIG_REG_P0_HDRS_AFTER_BASIC 0x18038
+/* [RW 1] HW PFC enable bit. Set this bit to enable the PFC functionality in
+ * the NIG. Other flow control modes such as PAUSE and SAFC/LLFC should be
+ * disabled when this bit is set. */
+#define NIG_REG_P0_HWPFC_ENABLE 0x18078
+#define NIG_REG_P0_LLH_FUNC_MEM2 0x18480
+#define NIG_REG_P0_LLH_FUNC_MEM2_ENABLE 0x18440
+/* [RW 32] Eight 4-bit configurations for specifying which COS (0-15 for
+ * future expansion) each priorty is to be mapped to. Bits 3:0 specify the
+ * COS for priority 0. Bits 31:28 specify the COS for priority 7. The 3-bit
+ * priority field is extracted from the outer-most VLAN in receive packet.
+ * Only COS 0 and COS 1 are supported in E2. */
+#define NIG_REG_P0_PKT_PRIORITY_TO_COS 0x18054
+/* [RW 16] Bit-map indicating which SAFC/PFC priorities to map to COS 0. A
+ * priority is mapped to COS 0 when the corresponding mask bit is 1. More
+ * than one bit may be set; allowing multiple priorities to be mapped to one
+ * COS. */
+#define NIG_REG_P0_RX_COS0_PRIORITY_MASK 0x18058
+/* [RW 16] Bit-map indicating which SAFC/PFC priorities to map to COS 1. A
+ * priority is mapped to COS 1 when the corresponding mask bit is 1. More
+ * than one bit may be set; allowing multiple priorities to be mapped to one
+ * COS. */
+#define NIG_REG_P0_RX_COS1_PRIORITY_MASK 0x1805c
+/* [RW 15] Specify which of the credit registers the client is to be mapped
+ * to. Bits[2:0] are for client 0; bits [14:12] are for client 4. For
+ * clients that are not subject to WFQ credit blocking - their
+ * specifications here are not used. */
+#define NIG_REG_P0_TX_ARB_CLIENT_CREDIT_MAP 0x180f0
+/* [RW 5] Specify whether the client competes directly in the strict
+ * priority arbiter. The bits are mapped according to client ID (client IDs
+ * are defined in tx_arb_priority_client). Default value is set to enable
+ * strict priorities for clients 0-2 -- management and debug traffic. */
+#define NIG_REG_P0_TX_ARB_CLIENT_IS_STRICT 0x180e8
+/* [RW 5] Specify whether the client is subject to WFQ credit blocking. The
+ * bits are mapped according to client ID (client IDs are defined in
+ * tx_arb_priority_client). Default value is 0 for not using WFQ credit
+ * blocking. */
+#define NIG_REG_P0_TX_ARB_CLIENT_IS_SUBJECT2WFQ 0x180ec
+/* [RW 32] Specify the upper bound that credit register 0 is allowed to
+ * reach. */
+#define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_0 0x1810c
+#define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_1 0x18110
+/* [RW 32] Specify the weight (in bytes) to be added to credit register 0
+ * when it is time to increment. */
+#define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_0 0x180f8
+#define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_1 0x180fc
+/* [RW 12] Specify the number of strict priority arbitration slots between
+ * two round-robin arbitration slots to avoid starvation. A value of 0 means
+ * no strict priority cycles - the strict priority with anti-starvation
+ * arbiter becomes a round-robin arbiter. */
+#define NIG_REG_P0_TX_ARB_NUM_STRICT_ARB_SLOTS 0x180f4
+/* [RW 15] Specify the client number to be assigned to each priority of the
+ * strict priority arbiter. Priority 0 is the highest priority. Bits [2:0]
+ * are for priority 0 client; bits [14:12] are for priority 4 client. The
+ * clients are assigned the following IDs: 0-management; 1-debug traffic
+ * from this port; 2-debug traffic from other port; 3-COS0 traffic; 4-COS1
+ * traffic. The reset value[14:0] is set to 0x4688 (15'b100_011_010_001_000)
+ * for management at priority 0; debug traffic at priorities 1 and 2; COS0
+ * traffic at priority 3; and COS1 traffic at priority 4. */
+#define NIG_REG_P0_TX_ARB_PRIORITY_CLIENT 0x180e4
+#define NIG_REG_P1_LLH_FUNC_MEM2 0x184c0
+#define NIG_REG_P1_LLH_FUNC_MEM2_ENABLE 0x18460
+/* [RW 32] Eight 4-bit configurations for specifying which COS (0-15 for
+ * future expansion) each priorty is to be mapped to. Bits 3:0 specify the
+ * COS for priority 0. Bits 31:28 specify the COS for priority 7. The 3-bit
+ * priority field is extracted from the outer-most VLAN in receive packet.
+ * Only COS 0 and COS 1 are supported in E2. */
+#define NIG_REG_P1_PKT_PRIORITY_TO_COS 0x181a8
+/* [RW 16] Bit-map indicating which SAFC/PFC priorities to map to COS 0. A
+ * priority is mapped to COS 0 when the corresponding mask bit is 1. More
+ * than one bit may be set; allowing multiple priorities to be mapped to one
+ * COS. */
+#define NIG_REG_P1_RX_COS0_PRIORITY_MASK 0x181ac
+/* [RW 16] Bit-map indicating which SAFC/PFC priorities to map to COS 1. A
+ * priority is mapped to COS 1 when the corresponding mask bit is 1. More
+ * than one bit may be set; allowing multiple priorities to be mapped to one
+ * COS. */
+#define NIG_REG_P1_RX_COS1_PRIORITY_MASK 0x181b0
/* [RW 1] Pause enable for port0. This register may get 1 only when
~safc_enable.safc_enable = 0 and ppp_enable.ppp_enable =0 for the same
port */
@@ -1742,6 +1987,10 @@
/* [RW 1] Disable processing further tasks from port 4 (after ending the
current task in process). */
#define PBF_REG_DISABLE_NEW_TASK_PROC_P4 0x14006c
+#define PBF_REG_DISABLE_PF 0x1402e8
+/* [RW 6] Bit-map indicating which L2 hdrs may appear after the basic
+ * Ethernet header. */
+#define PBF_REG_HDRS_AFTER_BASIC 0x15c0a8
#define PBF_REG_IF_ENABLE_REG 0x140044
/* [RW 1] Init bit. When set the initial credits are copied to the credit
registers (except the port credits). Should be set and then reset after
@@ -1765,6 +2014,8 @@
#define PBF_REG_MAC_IF1_ENABLE 0x140034
/* [RW 1] Enable for the loopback interface. */
#define PBF_REG_MAC_LB_ENABLE 0x140040
+/* [RW 6] Bit-map indicating which headers must appear in the packet */
+#define PBF_REG_MUST_HAVE_HDRS 0x15c0c4
/* [RW 10] Port 0 threshold used by arbiter in 16 byte lines used when pause
not suppoterd. */
#define PBF_REG_P0_ARB_THRSH 0x1400e4
@@ -1804,6 +2055,259 @@
#define PB_REG_PB_PRTY_MASK 0x38
/* [R 4] Parity register #0 read */
#define PB_REG_PB_PRTY_STS 0x2c
+#define PGLUE_B_PGLUE_B_INT_STS_REG_ADDRESS_ERROR (0x1<<0)
+#define PGLUE_B_PGLUE_B_INT_STS_REG_CSSNOOP_FIFO_OVERFLOW (0x1<<8)
+#define PGLUE_B_PGLUE_B_INT_STS_REG_INCORRECT_RCV_BEHAVIOR (0x1<<1)
+#define PGLUE_B_PGLUE_B_INT_STS_REG_TCPL_ERROR_ATTN (0x1<<6)
+#define PGLUE_B_PGLUE_B_INT_STS_REG_TCPL_IN_TWO_RCBS_ATTN (0x1<<7)
+#define PGLUE_B_PGLUE_B_INT_STS_REG_VF_GRC_SPACE_VIOLATION_ATTN (0x1<<4)
+#define PGLUE_B_PGLUE_B_INT_STS_REG_VF_LENGTH_VIOLATION_ATTN (0x1<<3)
+#define PGLUE_B_PGLUE_B_INT_STS_REG_VF_MSIX_BAR_VIOLATION_ATTN (0x1<<5)
+#define PGLUE_B_PGLUE_B_INT_STS_REG_WAS_ERROR_ATTN (0x1<<2)
+/* [R 8] Config space A attention dirty bits. Each bit indicates that the
+ * corresponding PF generates config space A attention. Set by PXP. Reset by
+ * MCP writing 1 to icfg_space_a_request_clr. Note: register contains bits
+ * from both paths. */
+#define PGLUE_B_REG_CFG_SPACE_A_REQUEST 0x9010
+/* [R 8] Config space B attention dirty bits. Each bit indicates that the
+ * corresponding PF generates config space B attention. Set by PXP. Reset by
+ * MCP writing 1 to icfg_space_b_request_clr. Note: register contains bits
+ * from both paths. */
+#define PGLUE_B_REG_CFG_SPACE_B_REQUEST 0x9014
+/* [RW 1] Type A PF enable inbound interrupt table for CSDM. 0 - disable; 1
+ * - enable. */
+#define PGLUE_B_REG_CSDM_INB_INT_A_PF_ENABLE 0x9194
+/* [RW 18] Type B VF inbound interrupt table for CSDM: bits[17:9]-mask;
+ * its[8:0]-address. Bits [1:0] must be zero (DW resolution address). */
+#define PGLUE_B_REG_CSDM_INB_INT_B_VF 0x916c
+/* [RW 1] Type B VF enable inbound interrupt table for CSDM. 0 - disable; 1
+ * - enable. */
+#define PGLUE_B_REG_CSDM_INB_INT_B_VF_ENABLE 0x919c
+/* [RW 16] Start offset of CSDM zone A (queue zone) in the internal RAM */
+#define PGLUE_B_REG_CSDM_START_OFFSET_A 0x9100
+/* [RW 16] Start offset of CSDM zone B (legacy zone) in the internal RAM */
+#define PGLUE_B_REG_CSDM_START_OFFSET_B 0x9108
+/* [RW 5] VF Shift of CSDM zone B (legacy zone) in the internal RAM */
+#define PGLUE_B_REG_CSDM_VF_SHIFT_B 0x9110
+/* [RW 1] 0 - Zone A size is 136x32B; 1 - Zone A size is 152x32B. */
+#define PGLUE_B_REG_CSDM_ZONE_A_SIZE_PF 0x91ac
+/* [R 8] FLR request attention dirty bits for PFs 0 to 7. Each bit indicates
+ * that the FLR register of the corresponding PF was set. Set by PXP. Reset
+ * by MCP writing 1 to flr_request_pf_7_0_clr. Note: register contains bits
+ * from both paths. */
+#define PGLUE_B_REG_FLR_REQUEST_PF_7_0 0x9028
+/* [W 8] FLR request attention dirty bits clear for PFs 0 to 7. MCP writes 1
+ * to a bit in this register in order to clear the corresponding bit in
+ * flr_request_pf_7_0 register. Note: register contains bits from both
+ * paths. */
+#define PGLUE_B_REG_FLR_REQUEST_PF_7_0_CLR 0x9418
+/* [R 32] FLR request attention dirty bits for VFs 96 to 127. Each bit
+ * indicates that the FLR register of the corresponding VF was set. Set by
+ * PXP. Reset by MCP writing 1 to flr_request_vf_127_96_clr. */
+#define PGLUE_B_REG_FLR_REQUEST_VF_127_96 0x9024
+/* [R 32] FLR request attention dirty bits for VFs 0 to 31. Each bit
+ * indicates that the FLR register of the corresponding VF was set. Set by
+ * PXP. Reset by MCP writing 1 to flr_request_vf_31_0_clr. */
+#define PGLUE_B_REG_FLR_REQUEST_VF_31_0 0x9018
+/* [R 32] FLR request attention dirty bits for VFs 32 to 63. Each bit
+ * indicates that the FLR register of the corresponding VF was set. Set by
+ * PXP. Reset by MCP writing 1 to flr_request_vf_63_32_clr. */
+#define PGLUE_B_REG_FLR_REQUEST_VF_63_32 0x901c
+/* [R 32] FLR request attention dirty bits for VFs 64 to 95. Each bit
+ * indicates that the FLR register of the corresponding VF was set. Set by
+ * PXP. Reset by MCP writing 1 to flr_request_vf_95_64_clr. */
+#define PGLUE_B_REG_FLR_REQUEST_VF_95_64 0x9020
+/* [R 8] Each bit indicates an incorrect behavior in user RX interface. Bit
+ * 0 - Target memory read arrived with a correctable error. Bit 1 - Target
+ * memory read arrived with an uncorrectable error. Bit 2 - Configuration RW
+ * arrived with a correctable error. Bit 3 - Configuration RW arrived with
+ * an uncorrectable error. Bit 4 - Completion with Configuration Request
+ * Retry Status. Bit 5 - Expansion ROM access received with a write request.
+ * Bit 6 - Completion with pcie_rx_err of 0000; CMPL_STATUS of non-zero; and
+ * pcie_rx_last not asserted. Bit 7 - Completion with pcie_rx_err of 1010;
+ * and pcie_rx_last not asserted. */
+#define PGLUE_B_REG_INCORRECT_RCV_DETAILS 0x9068
+#define PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER 0x942c
+#define PGLUE_B_REG_INTERNAL_PFID_ENABLE_TARGET_READ 0x9430
+#define PGLUE_B_REG_INTERNAL_PFID_ENABLE_TARGET_WRITE 0x9434
+#define PGLUE_B_REG_INTERNAL_VFID_ENABLE 0x9438
+/* [R 9] Interrupt register #0 read */
+#define PGLUE_B_REG_PGLUE_B_INT_STS 0x9298
+/* [RC 9] Interrupt register #0 read clear */
+#define PGLUE_B_REG_PGLUE_B_INT_STS_CLR 0x929c
+/* [R 2] Parity register #0 read */
+#define PGLUE_B_REG_PGLUE_B_PRTY_STS 0x92a8
+/* [R 13] Details of first request received with error. [2:0] - PFID. [3] -
+ * VF_VALID. [9:4] - VFID. [11:10] - Error Code - 0 - Indicates Completion
+ * Timeout of a User Tx non-posted request. 1 - unsupported request. 2 -
+ * completer abort. 3 - Illegal value for this field. [12] valid - indicates
+ * if there was a completion error since the last time this register was
+ * cleared. */
+#define PGLUE_B_REG_RX_ERR_DETAILS 0x9080
+/* [R 18] Details of first ATS Translation Completion request received with
+ * error. [2:0] - PFID. [3] - VF_VALID. [9:4] - VFID. [11:10] - Error Code -
+ * 0 - Indicates Completion Timeout of a User Tx non-posted request. 1 -
+ * unsupported request. 2 - completer abort. 3 - Illegal value for this
+ * field. [16:12] - ATC OTB EntryID. [17] valid - indicates if there was a
+ * completion error since the last time this register was cleared. */
+#define PGLUE_B_REG_RX_TCPL_ERR_DETAILS 0x9084
+/* [W 8] Debug only - Shadow BME bits clear for PFs 0 to 7. MCP writes 1 to
+ * a bit in this register in order to clear the corresponding bit in
+ * shadow_bme_pf_7_0 register. MCP should never use this unless a
+ * work-around is needed. Note: register contains bits from both paths. */
+#define PGLUE_B_REG_SHADOW_BME_PF_7_0_CLR 0x9458
+/* [R 8] SR IOV disabled attention dirty bits. Each bit indicates that the
+ * VF enable register of the corresponding PF is written to 0 and was
+ * previously 1. Set by PXP. Reset by MCP writing 1 to
+ * sr_iov_disabled_request_clr. Note: register contains bits from both
+ * paths. */
+#define PGLUE_B_REG_SR_IOV_DISABLED_REQUEST 0x9030
+/* [R 32] Indicates the status of tags 32-63. 0 - tags is used - read
+ * completion did not return yet. 1 - tag is unused. Same functionality as
+ * pxp2_registers_pgl_exp_rom_data2 for tags 0-31. */
+#define PGLUE_B_REG_TAGS_63_32 0x9244
+/* [RW 1] Type A PF enable inbound interrupt table for TSDM. 0 - disable; 1
+ * - enable. */
+#define PGLUE_B_REG_TSDM_INB_INT_A_PF_ENABLE 0x9170
+/* [RW 16] Start offset of TSDM zone A (queue zone) in the internal RAM */
+#define PGLUE_B_REG_TSDM_START_OFFSET_A 0x90c4
+/* [RW 16] Start offset of TSDM zone B (legacy zone) in the internal RAM */
+#define PGLUE_B_REG_TSDM_START_OFFSET_B 0x90cc
+/* [RW 5] VF Shift of TSDM zone B (legacy zone) in the internal RAM */
+#define PGLUE_B_REG_TSDM_VF_SHIFT_B 0x90d4
+/* [RW 1] 0 - Zone A size is 136x32B; 1 - Zone A size is 152x32B. */
+#define PGLUE_B_REG_TSDM_ZONE_A_SIZE_PF 0x91a0
+/* [R 32] Address [31:0] of first read request not submitted due to error */
+#define PGLUE_B_REG_TX_ERR_RD_ADD_31_0 0x9098
+/* [R 32] Address [63:32] of first read request not submitted due to error */
+#define PGLUE_B_REG_TX_ERR_RD_ADD_63_32 0x909c
+/* [R 31] Details of first read request not submitted due to error. [4:0]
+ * VQID. [5] TREQ. 1 - Indicates the request is a Translation Request.
+ * [20:8] - Length in bytes. [23:21] - PFID. [24] - VF_VALID. [30:25] -
+ * VFID. */
+#define PGLUE_B_REG_TX_ERR_RD_DETAILS 0x90a0
+/* [R 26] Details of first read request not submitted due to error. [15:0]
+ * Request ID. [19:16] client ID. [20] - last SR. [24:21] - Error type -
+ * [21] - Indicates was_error was set; [22] - Indicates BME was cleared;
+ * [23] - Indicates FID_enable was cleared; [24] - Indicates VF with parent
+ * PF FLR_request or IOV_disable_request dirty bit is set. [25] valid -
+ * indicates if there was a request not submitted due to error since the
+ * last time this register was cleared. */
+#define PGLUE_B_REG_TX_ERR_RD_DETAILS2 0x90a4
+/* [R 32] Address [31:0] of first write request not submitted due to error */
+#define PGLUE_B_REG_TX_ERR_WR_ADD_31_0 0x9088
+/* [R 32] Address [63:32] of first write request not submitted due to error */
+#define PGLUE_B_REG_TX_ERR_WR_ADD_63_32 0x908c
+/* [R 31] Details of first write request not submitted due to error. [4:0]
+ * VQID. [20:8] - Length in bytes. [23:21] - PFID. [24] - VF_VALID. [30:25]
+ * - VFID. */
+#define PGLUE_B_REG_TX_ERR_WR_DETAILS 0x9090
+/* [R 26] Details of first write request not submitted due to error. [15:0]
+ * Request ID. [19:16] client ID. [20] - last SR. [24:21] - Error type -
+ * [21] - Indicates was_error was set; [22] - Indicates BME was cleared;
+ * [23] - Indicates FID_enable was cleared; [24] - Indicates VF with parent
+ * PF FLR_request or IOV_disable_request dirty bit is set. [25] valid -
+ * indicates if there was a request not submitted due to error since the
+ * last time this register was cleared. */
+#define PGLUE_B_REG_TX_ERR_WR_DETAILS2 0x9094
+/* [RW 10] Type A PF/VF inbound interrupt table for USDM: bits[9:5]-mask;
+ * its[4:0]-address relative to start_offset_a. Bits [1:0] can have any
+ * value (Byte resolution address). */
+#define PGLUE_B_REG_USDM_INB_INT_A_0 0x9128
+#define PGLUE_B_REG_USDM_INB_INT_A_1 0x912c
+#define PGLUE_B_REG_USDM_INB_INT_A_2 0x9130
+#define PGLUE_B_REG_USDM_INB_INT_A_3 0x9134
+#define PGLUE_B_REG_USDM_INB_INT_A_4 0x9138
+#define PGLUE_B_REG_USDM_INB_INT_A_5 0x913c
+#define PGLUE_B_REG_USDM_INB_INT_A_6 0x9140
+/* [RW 1] Type A PF enable inbound interrupt table for USDM. 0 - disable; 1
+ * - enable. */
+#define PGLUE_B_REG_USDM_INB_INT_A_PF_ENABLE 0x917c
+/* [RW 1] Type A VF enable inbound interrupt table for USDM. 0 - disable; 1
+ * - enable. */
+#define PGLUE_B_REG_USDM_INB_INT_A_VF_ENABLE 0x9180
+/* [RW 1] Type B VF enable inbound interrupt table for USDM. 0 - disable; 1
+ * - enable. */
+#define PGLUE_B_REG_USDM_INB_INT_B_VF_ENABLE 0x9184
+/* [RW 16] Start offset of USDM zone A (queue zone) in the internal RAM */
+#define PGLUE_B_REG_USDM_START_OFFSET_A 0x90d8
+/* [RW 16] Start offset of USDM zone B (legacy zone) in the internal RAM */
+#define PGLUE_B_REG_USDM_START_OFFSET_B 0x90e0
+/* [RW 5] VF Shift of USDM zone B (legacy zone) in the internal RAM */
+#define PGLUE_B_REG_USDM_VF_SHIFT_B 0x90e8
+/* [RW 1] 0 - Zone A size is 136x32B; 1 - Zone A size is 152x32B. */
+#define PGLUE_B_REG_USDM_ZONE_A_SIZE_PF 0x91a4
+/* [R 26] Details of first target VF request accessing VF GRC space that
+ * failed permission check. [14:0] Address. [15] w_nr: 0 - Read; 1 - Write.
+ * [21:16] VFID. [24:22] - PFID. [25] valid - indicates if there was a
+ * request accessing VF GRC space that failed permission check since the
+ * last time this register was cleared. Permission checks are: function
+ * permission; R/W permission; address range permission. */
+#define PGLUE_B_REG_VF_GRC_SPACE_VIOLATION_DETAILS 0x9234
+/* [R 31] Details of first target VF request with length violation (too many
+ * DWs) accessing BAR0. [12:0] Address in DWs (bits [14:2] of byte address).
+ * [14:13] BAR. [20:15] VFID. [23:21] - PFID. [29:24] - Length in DWs. [30]
+ * valid - indicates if there was a request with length violation since the
+ * last time this register was cleared. Length violations: length of more
+ * than 2DWs; length of 2DWs and address not QW aligned; window is GRC and
+ * length is more than 1 DW. */
+#define PGLUE_B_REG_VF_LENGTH_VIOLATION_DETAILS 0x9230
+/* [R 8] Was_error indication dirty bits for PFs 0 to 7. Each bit indicates
+ * that there was a completion with uncorrectable error for the
+ * corresponding PF. Set by PXP. Reset by MCP writing 1 to
+ * was_error_pf_7_0_clr. */
+#define PGLUE_B_REG_WAS_ERROR_PF_7_0 0x907c
+/* [W 8] Was_error indication dirty bits clear for PFs 0 to 7. MCP writes 1
+ * to a bit in this register in order to clear the corresponding bit in
+ * flr_request_pf_7_0 register. */
+#define PGLUE_B_REG_WAS_ERROR_PF_7_0_CLR 0x9470
+/* [R 32] Was_error indication dirty bits for VFs 96 to 127. Each bit
+ * indicates that there was a completion with uncorrectable error for the
+ * corresponding VF. Set by PXP. Reset by MCP writing 1 to
+ * was_error_vf_127_96_clr. */
+#define PGLUE_B_REG_WAS_ERROR_VF_127_96 0x9078
+/* [W 32] Was_error indication dirty bits clear for VFs 96 to 127. MCP
+ * writes 1 to a bit in this register in order to clear the corresponding
+ * bit in was_error_vf_127_96 register. */
+#define PGLUE_B_REG_WAS_ERROR_VF_127_96_CLR 0x9474
+/* [R 32] Was_error indication dirty bits for VFs 0 to 31. Each bit
+ * indicates that there was a completion with uncorrectable error for the
+ * corresponding VF. Set by PXP. Reset by MCP writing 1 to
+ * was_error_vf_31_0_clr. */
+#define PGLUE_B_REG_WAS_ERROR_VF_31_0 0x906c
+/* [W 32] Was_error indication dirty bits clear for VFs 0 to 31. MCP writes
+ * 1 to a bit in this register in order to clear the corresponding bit in
+ * was_error_vf_31_0 register. */
+#define PGLUE_B_REG_WAS_ERROR_VF_31_0_CLR 0x9478
+/* [R 32] Was_error indication dirty bits for VFs 32 to 63. Each bit
+ * indicates that there was a completion with uncorrectable error for the
+ * corresponding VF. Set by PXP. Reset by MCP writing 1 to
+ * was_error_vf_63_32_clr. */
+#define PGLUE_B_REG_WAS_ERROR_VF_63_32 0x9070
+/* [W 32] Was_error indication dirty bits clear for VFs 32 to 63. MCP writes
+ * 1 to a bit in this register in order to clear the corresponding bit in
+ * was_error_vf_63_32 register. */
+#define PGLUE_B_REG_WAS_ERROR_VF_63_32_CLR 0x947c
+/* [R 32] Was_error indication dirty bits for VFs 64 to 95. Each bit
+ * indicates that there was a completion with uncorrectable error for the
+ * corresponding VF. Set by PXP. Reset by MCP writing 1 to
+ * was_error_vf_95_64_clr. */
+#define PGLUE_B_REG_WAS_ERROR_VF_95_64 0x9074
+/* [W 32] Was_error indication dirty bits clear for VFs 64 to 95. MCP writes
+ * 1 to a bit in this register in order to clear the corresponding bit in
+ * was_error_vf_95_64 register. */
+#define PGLUE_B_REG_WAS_ERROR_VF_95_64_CLR 0x9480
+/* [RW 1] Type A PF enable inbound interrupt table for XSDM. 0 - disable; 1
+ * - enable. */
+#define PGLUE_B_REG_XSDM_INB_INT_A_PF_ENABLE 0x9188
+/* [RW 16] Start offset of XSDM zone A (queue zone) in the internal RAM */
+#define PGLUE_B_REG_XSDM_START_OFFSET_A 0x90ec
+/* [RW 16] Start offset of XSDM zone B (legacy zone) in the internal RAM */
+#define PGLUE_B_REG_XSDM_START_OFFSET_B 0x90f4
+/* [RW 5] VF Shift of XSDM zone B (legacy zone) in the internal RAM */
+#define PGLUE_B_REG_XSDM_VF_SHIFT_B 0x90fc
+/* [RW 1] 0 - Zone A size is 136x32B; 1 - Zone A size is 152x32B. */
+#define PGLUE_B_REG_XSDM_ZONE_A_SIZE_PF 0x91a8
#define PRS_REG_A_PRSU_20 0x40134
/* [R 8] debug only: CFC load request current credit. Transaction based. */
#define PRS_REG_CFC_LD_CURRENT_CREDIT 0x40164
@@ -1866,9 +2370,13 @@
#define PRS_REG_FLUSH_REGIONS_TYPE_5 0x40018
#define PRS_REG_FLUSH_REGIONS_TYPE_6 0x4001c
#define PRS_REG_FLUSH_REGIONS_TYPE_7 0x40020
+/* [RW 6] Bit-map indicating which L2 hdrs may appear after the basic
+ * Ethernet header. */
+#define PRS_REG_HDRS_AFTER_BASIC 0x40238
/* [RW 4] The increment value to send in the CFC load request message */
#define PRS_REG_INC_VALUE 0x40048
-/* [RW 1] If set indicates not to send messages to CFC on received packets */
+/* [RW 6] Bit-map indicating which headers must appear in the packet */
+#define PRS_REG_MUST_HAVE_HDRS 0x40254
#define PRS_REG_NIC_MODE 0x40138
/* [RW 8] The 8-bit event ID for cases where there is no match on the
connection. Used in packet start message to TCM. */
@@ -1919,6 +2427,13 @@
#define PRS_REG_TCM_CURRENT_CREDIT 0x40160
/* [R 8] debug only: TSDM current credit. Transaction based. */
#define PRS_REG_TSDM_CURRENT_CREDIT 0x4015c
+#define PXP2_PXP2_INT_MASK_0_REG_PGL_CPL_AFT (0x1<<19)
+#define PXP2_PXP2_INT_MASK_0_REG_PGL_CPL_OF (0x1<<20)
+#define PXP2_PXP2_INT_MASK_0_REG_PGL_PCIE_ATTN (0x1<<22)
+#define PXP2_PXP2_INT_MASK_0_REG_PGL_READ_BLOCKED (0x1<<23)
+#define PXP2_PXP2_INT_MASK_0_REG_PGL_WRITE_BLOCKED (0x1<<24)
+#define PXP2_PXP2_INT_STS_0_REG_WR_PGLUE_EOP_ERROR (0x1<<7)
+#define PXP2_PXP2_INT_STS_CLR_0_REG_WR_PGLUE_EOP_ERROR (0x1<<7)
/* [R 6] Debug only: Number of used entries in the data FIFO */
#define PXP2_REG_HST_DATA_FIFO_STATUS 0x12047c
/* [R 7] Debug only: Number of used entries in the header FIFO */
@@ -2244,8 +2759,17 @@
/* [RW 1] When '1'; requests will enter input buffers but wont get out
towards the glue */
#define PXP2_REG_RQ_DISABLE_INPUTS 0x120330
-/* [RW 1] 1 - SR will be aligned by 64B; 0 - SR will be aligned by 8B */
+/* [RW 4] Determines alignment of write SRs when a request is split into
+ * several SRs. 0 - 8B aligned. 1 - 64B aligned. 2 - 128B aligned. 3 - 256B
+ * aligned. 4 - 512B aligned. */
#define PXP2_REG_RQ_DRAM_ALIGN 0x1205b0
+/* [RW 4] Determines alignment of read SRs when a request is split into
+ * several SRs. 0 - 8B aligned. 1 - 64B aligned. 2 - 128B aligned. 3 - 256B
+ * aligned. 4 - 512B aligned. */
+#define PXP2_REG_RQ_DRAM_ALIGN_RD 0x12092c
+/* [RW 1] when set the new alignment method (E2) will be applied; when reset
+ * the original alignment method (E1 E1H) will be applied */
+#define PXP2_REG_RQ_DRAM_ALIGN_SEL 0x120930
/* [RW 1] If 1 ILT failiue will not result in ELT access; An interrupt will
be asserted */
#define PXP2_REG_RQ_ELT_DISABLE 0x12066c
@@ -2436,7 +2960,8 @@
#define PXP_REG_PXP_INT_STS_1 0x103078
/* [RC 32] Interrupt register #0 read clear */
#define PXP_REG_PXP_INT_STS_CLR_0 0x10306c
-/* [RW 26] Parity mask register #0 read/write */
+#define PXP_REG_PXP_INT_STS_CLR_1 0x10307c
+/* [RW 27] Parity mask register #0 read/write */
#define PXP_REG_PXP_PRTY_MASK 0x103094
/* [R 26] Parity register #0 read */
#define PXP_REG_PXP_PRTY_STS 0x103088
@@ -2566,6 +3091,7 @@
#define QM_REG_PAUSESTATE7 0x16e698
/* [RW 2] The PCI attributes field used in the PCI request. */
#define QM_REG_PCIREQAT 0x168054
+#define QM_REG_PF_EN 0x16e70c
/* [R 16] The byte credit of port 0 */
#define QM_REG_PORT0BYTECRD 0x168300
/* [R 16] The byte credit of port 1 */
@@ -3402,6 +3928,14 @@
/* [R 32] Parity register #0 read */
#define TSEM_REG_TSEM_PRTY_STS_0 0x180114
#define TSEM_REG_TSEM_PRTY_STS_1 0x180124
+/* [W 7] VF or PF ID for reset error bit. Values 0-63 reset error bit for 64
+ * VF; values 64-67 reset error for 4 PF; values 68-127 are not valid. */
+#define TSEM_REG_VFPF_ERR_NUM 0x180380
+/* [RW 32] Indirect access to AG context with 32-bits granularity. The bits
+ * [10:8] of the address should be the offset within the accessed LCID
+ * context; the bits [7:0] are the accessed LCID.Example: to write to REG10
+ * LCID100. The RBC address should be 12'ha64. */
+#define UCM_REG_AG_CTX 0xe2000
/* [R 5] Used to read the XX protection CAM occupancy counter. */
#define UCM_REG_CAM_OCCUP 0xe0170
/* [RW 1] CDU AG read Interface enable. If 0 - the request input is
@@ -3851,6 +4385,17 @@
/* [R 32] Parity register #0 read */
#define USEM_REG_USEM_PRTY_STS_0 0x300124
#define USEM_REG_USEM_PRTY_STS_1 0x300134
+/* [W 7] VF or PF ID for reset error bit. Values 0-63 reset error bit for 64
+ * VF; values 64-67 reset error for 4 PF; values 68-127 are not valid. */
+#define USEM_REG_VFPF_ERR_NUM 0x300380
+#define VFC_MEMORIES_RST_REG_CAM_RST (0x1<<0)
+#define VFC_MEMORIES_RST_REG_RAM_RST (0x1<<1)
+#define VFC_REG_MEMORIES_RST 0x1943c
+/* [RW 32] Indirect access to AG context with 32-bits granularity. The bits
+ * [12:8] of the address should be the offset within the accessed LCID
+ * context; the bits [7:0] are the accessed LCID.Example: to write to REG10
+ * LCID100. The RBC address should be 13'ha64. */
+#define XCM_REG_AG_CTX 0x28000
/* [RW 2] The queue index for registration on Aux1 counter flag. */
#define XCM_REG_AUX1_Q 0x20134
/* [RW 2] Per each decision rule the queue index to register to. */
@@ -4333,6 +4878,9 @@
#define XSEM_REG_TS_8_AS 0x280058
/* [RW 3] The arbitration scheme of time_slot 9 */
#define XSEM_REG_TS_9_AS 0x28005c
+/* [W 7] VF or PF ID for reset error bit. Values 0-63 reset error bit for 64
+ * VF; values 64-67 reset error for 4 PF; values 68-127 are not valid. */
+#define XSEM_REG_VFPF_ERR_NUM 0x280380
/* [RW 32] Interrupt mask register #0 read/write */
#define XSEM_REG_XSEM_INT_MASK_0 0x280110
#define XSEM_REG_XSEM_INT_MASK_1 0x280120
@@ -4371,6 +4919,23 @@
#define BIGMAC_REGISTER_TX_SOURCE_ADDR (0x08<<3)
#define BIGMAC_REGISTER_TX_STAT_GTBYT (0x20<<3)
#define BIGMAC_REGISTER_TX_STAT_GTPKT (0x0C<<3)
+#define BIGMAC2_REGISTER_BMAC_CONTROL (0x00<<3)
+#define BIGMAC2_REGISTER_BMAC_XGXS_CONTROL (0x01<<3)
+#define BIGMAC2_REGISTER_CNT_MAX_SIZE (0x05<<3)
+#define BIGMAC2_REGISTER_PFC_CONTROL (0x06<<3)
+#define BIGMAC2_REGISTER_RX_CONTROL (0x3A<<3)
+#define BIGMAC2_REGISTER_RX_LLFC_MSG_FLDS (0x62<<3)
+#define BIGMAC2_REGISTER_RX_MAX_SIZE (0x3C<<3)
+#define BIGMAC2_REGISTER_RX_STAT_GR64 (0x40<<3)
+#define BIGMAC2_REGISTER_RX_STAT_GRIPJ (0x5f<<3)
+#define BIGMAC2_REGISTER_RX_STAT_GRPP (0x51<<3)
+#define BIGMAC2_REGISTER_TX_CONTROL (0x1C<<3)
+#define BIGMAC2_REGISTER_TX_MAX_SIZE (0x1E<<3)
+#define BIGMAC2_REGISTER_TX_PAUSE_CONTROL (0x20<<3)
+#define BIGMAC2_REGISTER_TX_SOURCE_ADDR (0x1D<<3)
+#define BIGMAC2_REGISTER_TX_STAT_GTBYT (0x39<<3)
+#define BIGMAC2_REGISTER_TX_STAT_GTPOK (0x22<<3)
+#define BIGMAC2_REGISTER_TX_STAT_GTPP (0x24<<3)
#define EMAC_LED_1000MB_OVERRIDE (1L<<1)
#define EMAC_LED_100MB_OVERRIDE (1L<<2)
#define EMAC_LED_10MB_OVERRIDE (1L<<3)
@@ -4478,6 +5043,8 @@
#define HW_LOCK_RESOURCE_SPIO 2
#define HW_LOCK_RESOURCE_UNDI 5
#define PRS_FLAG_OVERETH_IPV4 1
+#define AEU_INPUTS_ATTN_BITS_ATC_HW_INTERRUPT (0x1<<4)
+#define AEU_INPUTS_ATTN_BITS_ATC_PARITY_ERROR (0x1<<5)
#define AEU_INPUTS_ATTN_BITS_BRB_PARITY_ERROR (1<<18)
#define AEU_INPUTS_ATTN_BITS_CCM_HW_INTERRUPT (1<<31)
#define AEU_INPUTS_ATTN_BITS_CDU_HW_INTERRUPT (1<<9)
@@ -4504,6 +5071,8 @@
#define AEU_INPUTS_ATTN_BITS_PARSER_PARITY_ERROR (1<<20)
#define AEU_INPUTS_ATTN_BITS_PBCLIENT_PARITY_ERROR (1<<0)
#define AEU_INPUTS_ATTN_BITS_PBF_HW_INTERRUPT (1<<31)
+#define AEU_INPUTS_ATTN_BITS_PGLUE_HW_INTERRUPT (0x1<<2)
+#define AEU_INPUTS_ATTN_BITS_PGLUE_PARITY_ERROR (0x1<<3)
#define AEU_INPUTS_ATTN_BITS_PXP_HW_INTERRUPT (1<<3)
#define AEU_INPUTS_ATTN_BITS_PXP_PARITY_ERROR (1<<2)
#define AEU_INPUTS_ATTN_BITS_PXPPCICLOCKCLIENT_HW_INTERRUPT (1<<5)
@@ -4796,6 +5365,253 @@
#define PCI_ID_VAL1 0x434
#define PCI_ID_VAL2 0x438
+#define PXPCS_TL_CONTROL_5 0x814
+#define PXPCS_TL_CONTROL_5_UNKNOWNTYPE_ERR_ATTN (1 << 29) /*WC*/
+#define PXPCS_TL_CONTROL_5_BOUNDARY4K_ERR_ATTN (1 << 28) /*WC*/
+#define PXPCS_TL_CONTROL_5_MRRS_ERR_ATTN (1 << 27) /*WC*/
+#define PXPCS_TL_CONTROL_5_MPS_ERR_ATTN (1 << 26) /*WC*/
+#define PXPCS_TL_CONTROL_5_TTX_BRIDGE_FORWARD_ERR (1 << 25) /*WC*/
+#define PXPCS_TL_CONTROL_5_TTX_TXINTF_OVERFLOW (1 << 24) /*WC*/
+#define PXPCS_TL_CONTROL_5_PHY_ERR_ATTN (1 << 23) /*RO*/
+#define PXPCS_TL_CONTROL_5_DL_ERR_ATTN (1 << 22) /*RO*/
+#define PXPCS_TL_CONTROL_5_TTX_ERR_NP_TAG_IN_USE (1 << 21) /*WC*/
+#define PXPCS_TL_CONTROL_5_TRX_ERR_UNEXP_RTAG (1 << 20) /*WC*/
+#define PXPCS_TL_CONTROL_5_PRI_SIG_TARGET_ABORT1 (1 << 19) /*WC*/
+#define PXPCS_TL_CONTROL_5_ERR_UNSPPORT1 (1 << 18) /*WC*/
+#define PXPCS_TL_CONTROL_5_ERR_ECRC1 (1 << 17) /*WC*/
+#define PXPCS_TL_CONTROL_5_ERR_MALF_TLP1 (1 << 16) /*WC*/
+#define PXPCS_TL_CONTROL_5_ERR_RX_OFLOW1 (1 << 15) /*WC*/
+#define PXPCS_TL_CONTROL_5_ERR_UNEXP_CPL1 (1 << 14) /*WC*/
+#define PXPCS_TL_CONTROL_5_ERR_MASTER_ABRT1 (1 << 13) /*WC*/
+#define PXPCS_TL_CONTROL_5_ERR_CPL_TIMEOUT1 (1 << 12) /*WC*/
+#define PXPCS_TL_CONTROL_5_ERR_FC_PRTL1 (1 << 11) /*WC*/
+#define PXPCS_TL_CONTROL_5_ERR_PSND_TLP1 (1 << 10) /*WC*/
+#define PXPCS_TL_CONTROL_5_PRI_SIG_TARGET_ABORT (1 << 9) /*WC*/
+#define PXPCS_TL_CONTROL_5_ERR_UNSPPORT (1 << 8) /*WC*/
+#define PXPCS_TL_CONTROL_5_ERR_ECRC (1 << 7) /*WC*/
+#define PXPCS_TL_CONTROL_5_ERR_MALF_TLP (1 << 6) /*WC*/
+#define PXPCS_TL_CONTROL_5_ERR_RX_OFLOW (1 << 5) /*WC*/
+#define PXPCS_TL_CONTROL_5_ERR_UNEXP_CPL (1 << 4) /*WC*/
+#define PXPCS_TL_CONTROL_5_ERR_MASTER_ABRT (1 << 3) /*WC*/
+#define PXPCS_TL_CONTROL_5_ERR_CPL_TIMEOUT (1 << 2) /*WC*/
+#define PXPCS_TL_CONTROL_5_ERR_FC_PRTL (1 << 1) /*WC*/
+#define PXPCS_TL_CONTROL_5_ERR_PSND_TLP (1 << 0) /*WC*/
+
+
+#define PXPCS_TL_FUNC345_STAT 0x854
+#define PXPCS_TL_FUNC345_STAT_PRI_SIG_TARGET_ABORT4 (1 << 29) /* WC */
+#define PXPCS_TL_FUNC345_STAT_ERR_UNSPPORT4\
+ (1 << 28) /* Unsupported Request Error Status in function4, if \
+ set, generate pcie_err_attn output when this error is seen. WC */
+#define PXPCS_TL_FUNC345_STAT_ERR_ECRC4\
+ (1 << 27) /* ECRC Error TLP Status Status in function 4, if set, \
+ generate pcie_err_attn output when this error is seen.. WC */
+#define PXPCS_TL_FUNC345_STAT_ERR_MALF_TLP4\
+ (1 << 26) /* Malformed TLP Status Status in function 4, if set, \
+ generate pcie_err_attn output when this error is seen.. WC */
+#define PXPCS_TL_FUNC345_STAT_ERR_RX_OFLOW4\
+ (1 << 25) /* Receiver Overflow Status Status in function 4, if \
+ set, generate pcie_err_attn output when this error is seen.. WC \
+ */
+#define PXPCS_TL_FUNC345_STAT_ERR_UNEXP_CPL4\
+ (1 << 24) /* Unexpected Completion Status Status in function 4, \
+ if set, generate pcie_err_attn output when this error is seen. WC \
+ */
+#define PXPCS_TL_FUNC345_STAT_ERR_MASTER_ABRT4\
+ (1 << 23) /* Receive UR Statusin function 4. If set, generate \
+ pcie_err_attn output when this error is seen. WC */
+#define PXPCS_TL_FUNC345_STAT_ERR_CPL_TIMEOUT4\
+ (1 << 22) /* Completer Timeout Status Status in function 4, if \
+ set, generate pcie_err_attn output when this error is seen. WC */
+#define PXPCS_TL_FUNC345_STAT_ERR_FC_PRTL4\
+ (1 << 21) /* Flow Control Protocol Error Status Status in \
+ function 4, if set, generate pcie_err_attn output when this error \
+ is seen. WC */
+#define PXPCS_TL_FUNC345_STAT_ERR_PSND_TLP4\
+ (1 << 20) /* Poisoned Error Status Status in function 4, if set, \
+ generate pcie_err_attn output when this error is seen.. WC */
+#define PXPCS_TL_FUNC345_STAT_PRI_SIG_TARGET_ABORT3 (1 << 19) /* WC */
+#define PXPCS_TL_FUNC345_STAT_ERR_UNSPPORT3\
+ (1 << 18) /* Unsupported Request Error Status in function3, if \
+ set, generate pcie_err_attn output when this error is seen. WC */
+#define PXPCS_TL_FUNC345_STAT_ERR_ECRC3\
+ (1 << 17) /* ECRC Error TLP Status Status in function 3, if set, \
+ generate pcie_err_attn output when this error is seen.. WC */
+#define PXPCS_TL_FUNC345_STAT_ERR_MALF_TLP3\
+ (1 << 16) /* Malformed TLP Status Status in function 3, if set, \
+ generate pcie_err_attn output when this error is seen.. WC */
+#define PXPCS_TL_FUNC345_STAT_ERR_RX_OFLOW3\
+ (1 << 15) /* Receiver Overflow Status Status in function 3, if \
+ set, generate pcie_err_attn output when this error is seen.. WC \
+ */
+#define PXPCS_TL_FUNC345_STAT_ERR_UNEXP_CPL3\
+ (1 << 14) /* Unexpected Completion Status Status in function 3, \
+ if set, generate pcie_err_attn output when this error is seen. WC \
+ */
+#define PXPCS_TL_FUNC345_STAT_ERR_MASTER_ABRT3\
+ (1 << 13) /* Receive UR Statusin function 3. If set, generate \
+ pcie_err_attn output when this error is seen. WC */
+#define PXPCS_TL_FUNC345_STAT_ERR_CPL_TIMEOUT3\
+ (1 << 12) /* Completer Timeout Status Status in function 3, if \
+ set, generate pcie_err_attn output when this error is seen. WC */
+#define PXPCS_TL_FUNC345_STAT_ERR_FC_PRTL3\
+ (1 << 11) /* Flow Control Protocol Error Status Status in \
+ function 3, if set, generate pcie_err_attn output when this error \
+ is seen. WC */
+#define PXPCS_TL_FUNC345_STAT_ERR_PSND_TLP3\
+ (1 << 10) /* Poisoned Error Status Status in function 3, if set, \
+ generate pcie_err_attn output when this error is seen.. WC */
+#define PXPCS_TL_FUNC345_STAT_PRI_SIG_TARGET_ABORT2 (1 << 9) /* WC */
+#define PXPCS_TL_FUNC345_STAT_ERR_UNSPPORT2\
+ (1 << 8) /* Unsupported Request Error Status for Function 2, if \
+ set, generate pcie_err_attn output when this error is seen. WC */
+#define PXPCS_TL_FUNC345_STAT_ERR_ECRC2\
+ (1 << 7) /* ECRC Error TLP Status Status for Function 2, if set, \
+ generate pcie_err_attn output when this error is seen.. WC */
+#define PXPCS_TL_FUNC345_STAT_ERR_MALF_TLP2\
+ (1 << 6) /* Malformed TLP Status Status for Function 2, if set, \
+ generate pcie_err_attn output when this error is seen.. WC */
+#define PXPCS_TL_FUNC345_STAT_ERR_RX_OFLOW2\
+ (1 << 5) /* Receiver Overflow Status Status for Function 2, if \
+ set, generate pcie_err_attn output when this error is seen.. WC \
+ */
+#define PXPCS_TL_FUNC345_STAT_ERR_UNEXP_CPL2\
+ (1 << 4) /* Unexpected Completion Status Status for Function 2, \
+ if set, generate pcie_err_attn output when this error is seen. WC \
+ */
+#define PXPCS_TL_FUNC345_STAT_ERR_MASTER_ABRT2\
+ (1 << 3) /* Receive UR Statusfor Function 2. If set, generate \
+ pcie_err_attn output when this error is seen. WC */
+#define PXPCS_TL_FUNC345_STAT_ERR_CPL_TIMEOUT2\
+ (1 << 2) /* Completer Timeout Status Status for Function 2, if \
+ set, generate pcie_err_attn output when this error is seen. WC */
+#define PXPCS_TL_FUNC345_STAT_ERR_FC_PRTL2\
+ (1 << 1) /* Flow Control Protocol Error Status Status for \
+ Function 2, if set, generate pcie_err_attn output when this error \
+ is seen. WC */
+#define PXPCS_TL_FUNC345_STAT_ERR_PSND_TLP2\
+ (1 << 0) /* Poisoned Error Status Status for Function 2, if set, \
+ generate pcie_err_attn output when this error is seen.. WC */
+
+
+#define PXPCS_TL_FUNC678_STAT 0x85C
+#define PXPCS_TL_FUNC678_STAT_PRI_SIG_TARGET_ABORT7 (1 << 29) /* WC */
+#define PXPCS_TL_FUNC678_STAT_ERR_UNSPPORT7\
+ (1 << 28) /* Unsupported Request Error Status in function7, if \
+ set, generate pcie_err_attn output when this error is seen. WC */
+#define PXPCS_TL_FUNC678_STAT_ERR_ECRC7\
+ (1 << 27) /* ECRC Error TLP Status Status in function 7, if set, \
+ generate pcie_err_attn output when this error is seen.. WC */
+#define PXPCS_TL_FUNC678_STAT_ERR_MALF_TLP7\
+ (1 << 26) /* Malformed TLP Status Status in function 7, if set, \
+ generate pcie_err_attn output when this error is seen.. WC */
+#define PXPCS_TL_FUNC678_STAT_ERR_RX_OFLOW7\
+ (1 << 25) /* Receiver Overflow Status Status in function 7, if \
+ set, generate pcie_err_attn output when this error is seen.. WC \
+ */
+#define PXPCS_TL_FUNC678_STAT_ERR_UNEXP_CPL7\
+ (1 << 24) /* Unexpected Completion Status Status in function 7, \
+ if set, generate pcie_err_attn output when this error is seen. WC \
+ */
+#define PXPCS_TL_FUNC678_STAT_ERR_MASTER_ABRT7\
+ (1 << 23) /* Receive UR Statusin function 7. If set, generate \
+ pcie_err_attn output when this error is seen. WC */
+#define PXPCS_TL_FUNC678_STAT_ERR_CPL_TIMEOUT7\
+ (1 << 22) /* Completer Timeout Status Status in function 7, if \
+ set, generate pcie_err_attn output when this error is seen. WC */
+#define PXPCS_TL_FUNC678_STAT_ERR_FC_PRTL7\
+ (1 << 21) /* Flow Control Protocol Error Status Status in \
+ function 7, if set, generate pcie_err_attn output when this error \
+ is seen. WC */
+#define PXPCS_TL_FUNC678_STAT_ERR_PSND_TLP7\
+ (1 << 20) /* Poisoned Error Status Status in function 7, if set, \
+ generate pcie_err_attn output when this error is seen.. WC */
+#define PXPCS_TL_FUNC678_STAT_PRI_SIG_TARGET_ABORT6 (1 << 19) /* WC */
+#define PXPCS_TL_FUNC678_STAT_ERR_UNSPPORT6\
+ (1 << 18) /* Unsupported Request Error Status in function6, if \
+ set, generate pcie_err_attn output when this error is seen. WC */
+#define PXPCS_TL_FUNC678_STAT_ERR_ECRC6\
+ (1 << 17) /* ECRC Error TLP Status Status in function 6, if set, \
+ generate pcie_err_attn output when this error is seen.. WC */
+#define PXPCS_TL_FUNC678_STAT_ERR_MALF_TLP6\
+ (1 << 16) /* Malformed TLP Status Status in function 6, if set, \
+ generate pcie_err_attn output when this error is seen.. WC */
+#define PXPCS_TL_FUNC678_STAT_ERR_RX_OFLOW6\
+ (1 << 15) /* Receiver Overflow Status Status in function 6, if \
+ set, generate pcie_err_attn output when this error is seen.. WC \
+ */
+#define PXPCS_TL_FUNC678_STAT_ERR_UNEXP_CPL6\
+ (1 << 14) /* Unexpected Completion Status Status in function 6, \
+ if set, generate pcie_err_attn output when this error is seen. WC \
+ */
+#define PXPCS_TL_FUNC678_STAT_ERR_MASTER_ABRT6\
+ (1 << 13) /* Receive UR Statusin function 6. If set, generate \
+ pcie_err_attn output when this error is seen. WC */
+#define PXPCS_TL_FUNC678_STAT_ERR_CPL_TIMEOUT6\
+ (1 << 12) /* Completer Timeout Status Status in function 6, if \
+ set, generate pcie_err_attn output when this error is seen. WC */
+#define PXPCS_TL_FUNC678_STAT_ERR_FC_PRTL6\
+ (1 << 11) /* Flow Control Protocol Error Status Status in \
+ function 6, if set, generate pcie_err_attn output when this error \
+ is seen. WC */
+#define PXPCS_TL_FUNC678_STAT_ERR_PSND_TLP6\
+ (1 << 10) /* Poisoned Error Status Status in function 6, if set, \
+ generate pcie_err_attn output when this error is seen.. WC */
+#define PXPCS_TL_FUNC678_STAT_PRI_SIG_TARGET_ABORT5 (1 << 9) /* WC */
+#define PXPCS_TL_FUNC678_STAT_ERR_UNSPPORT5\
+ (1 << 8) /* Unsupported Request Error Status for Function 5, if \
+ set, generate pcie_err_attn output when this error is seen. WC */
+#define PXPCS_TL_FUNC678_STAT_ERR_ECRC5\
+ (1 << 7) /* ECRC Error TLP Status Status for Function 5, if set, \
+ generate pcie_err_attn output when this error is seen.. WC */
+#define PXPCS_TL_FUNC678_STAT_ERR_MALF_TLP5\
+ (1 << 6) /* Malformed TLP Status Status for Function 5, if set, \
+ generate pcie_err_attn output when this error is seen.. WC */
+#define PXPCS_TL_FUNC678_STAT_ERR_RX_OFLOW5\
+ (1 << 5) /* Receiver Overflow Status Status for Function 5, if \
+ set, generate pcie_err_attn output when this error is seen.. WC \
+ */
+#define PXPCS_TL_FUNC678_STAT_ERR_UNEXP_CPL5\
+ (1 << 4) /* Unexpected Completion Status Status for Function 5, \
+ if set, generate pcie_err_attn output when this error is seen. WC \
+ */
+#define PXPCS_TL_FUNC678_STAT_ERR_MASTER_ABRT5\
+ (1 << 3) /* Receive UR Statusfor Function 5. If set, generate \
+ pcie_err_attn output when this error is seen. WC */
+#define PXPCS_TL_FUNC678_STAT_ERR_CPL_TIMEOUT5\
+ (1 << 2) /* Completer Timeout Status Status for Function 5, if \
+ set, generate pcie_err_attn output when this error is seen. WC */
+#define PXPCS_TL_FUNC678_STAT_ERR_FC_PRTL5\
+ (1 << 1) /* Flow Control Protocol Error Status Status for \
+ Function 5, if set, generate pcie_err_attn output when this error \
+ is seen. WC */
+#define PXPCS_TL_FUNC678_STAT_ERR_PSND_TLP5\
+ (1 << 0) /* Poisoned Error Status Status for Function 5, if set, \
+ generate pcie_err_attn output when this error is seen.. WC */
+
+
+#define BAR_USTRORM_INTMEM 0x400000
+#define BAR_CSTRORM_INTMEM 0x410000
+#define BAR_XSTRORM_INTMEM 0x420000
+#define BAR_TSTRORM_INTMEM 0x430000
+
+/* for accessing the IGU in case of status block ACK */
+#define BAR_IGU_INTMEM 0x440000
+
+#define BAR_DOORBELL_OFFSET 0x800000
+
+#define BAR_ME_REGISTER 0x450000
+#define ME_REG_PF_NUM_SHIFT 0
+#define ME_REG_PF_NUM\
+ (7L<<ME_REG_PF_NUM_SHIFT) /* Relative PF Num */
+#define ME_REG_VF_VALID (1<<8)
+#define ME_REG_VF_NUM_SHIFT 9
+#define ME_REG_VF_NUM_MASK (0x3f<<ME_REG_VF_NUM_SHIFT)
+#define ME_REG_VF_ERR (0x1<<3)
+#define ME_REG_ABS_PF_NUM_SHIFT 16
+#define ME_REG_ABS_PF_NUM\
+ (7L<<ME_REG_ABS_PF_NUM_SHIFT) /* Absolute PF Num */
+
#define MDIO_REG_BANK_CL73_IEEEB0 0x0
#define MDIO_CL73_IEEEB0_CL73_AN_CONTROL 0x0
@@ -4964,6 +5780,8 @@
#define MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_PRL_DT_EN 0x0001
#define MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_AN_FST_TMR 0x0040
#define MDIO_SERDES_DIGITAL_A_1000X_STATUS1 0x14
+#define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_SGMII 0x0001
+#define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_LINK 0x0002
#define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_DUPLEX 0x0004
#define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_SPEED_MASK 0x0018
#define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_SPEED_SHIFT 3
@@ -5135,28 +5953,35 @@ Theotherbitsarereservedandshouldbezero*/
#define MDIO_PMA_REG_8727_TWO_WIRE_SLAVE_ADDR 0x8005
#define MDIO_PMA_REG_8727_TWO_WIRE_DATA_BUF 0x8007
#define MDIO_PMA_REG_8727_TWO_WIRE_DATA_MASK 0xff
-#define MDIO_PMA_REG_8727_MISC_CTRL 0x8309
#define MDIO_PMA_REG_8727_TX_CTRL1 0xca02
#define MDIO_PMA_REG_8727_TX_CTRL2 0xca05
#define MDIO_PMA_REG_8727_PCS_OPT_CTRL 0xc808
#define MDIO_PMA_REG_8727_GPIO_CTRL 0xc80e
+#define MDIO_PMA_REG_8727_PCS_GP 0xc842
+
+#define MDIO_AN_REG_8727_MISC_CTRL 0x8309
#define MDIO_PMA_REG_8073_CHIP_REV 0xc801
#define MDIO_PMA_REG_8073_SPEED_LINK_STATUS 0xc820
#define MDIO_PMA_REG_8073_XAUI_WA 0xc841
+#define MDIO_PMA_REG_8073_OPT_DIGITAL_CTRL 0xcd08
#define MDIO_PMA_REG_7101_RESET 0xc000
#define MDIO_PMA_REG_7107_LED_CNTL 0xc007
+#define MDIO_PMA_REG_7107_LINK_LED_CNTL 0xc009
#define MDIO_PMA_REG_7101_VER1 0xc026
#define MDIO_PMA_REG_7101_VER2 0xc027
-#define MDIO_PMA_REG_8481_PMD_SIGNAL 0xa811
-#define MDIO_PMA_REG_8481_LED1_MASK 0xa82c
-#define MDIO_PMA_REG_8481_LED2_MASK 0xa82f
-#define MDIO_PMA_REG_8481_LED3_MASK 0xa832
-#define MDIO_PMA_REG_8481_LED3_BLINK 0xa834
-#define MDIO_PMA_REG_8481_SIGNAL_MASK 0xa835
-#define MDIO_PMA_REG_8481_LINK_SIGNAL 0xa83b
+#define MDIO_PMA_REG_8481_PMD_SIGNAL 0xa811
+#define MDIO_PMA_REG_8481_LED1_MASK 0xa82c
+#define MDIO_PMA_REG_8481_LED2_MASK 0xa82f
+#define MDIO_PMA_REG_8481_LED3_MASK 0xa832
+#define MDIO_PMA_REG_8481_LED3_BLINK 0xa834
+#define MDIO_PMA_REG_8481_LED5_MASK 0xa838
+#define MDIO_PMA_REG_8481_SIGNAL_MASK 0xa835
+#define MDIO_PMA_REG_8481_LINK_SIGNAL 0xa83b
+#define MDIO_PMA_REG_8481_LINK_SIGNAL_LED4_ENABLE_MASK 0x800
+#define MDIO_PMA_REG_8481_LINK_SIGNAL_LED4_ENABLE_SHIFT 11
#define MDIO_WIS_DEVAD 0x2
@@ -5188,6 +6013,8 @@ Theotherbitsarereservedandshouldbezero*/
#define MDIO_XS_8706_REG_BANK_RX3 0x80ec
#define MDIO_XS_8706_REG_BANK_RXA 0x80fc
+#define MDIO_XS_REG_8073_RX_CTRL_PCIE 0x80FA
+
#define MDIO_AN_DEVAD 0x7
/*ieee*/
#define MDIO_AN_REG_CTRL 0x0000
@@ -5210,14 +6037,40 @@ Theotherbitsarereservedandshouldbezero*/
#define MDIO_AN_REG_CL37_FC_LP 0xffe5
#define MDIO_AN_REG_8073_2_5G 0x8329
+#define MDIO_AN_REG_8073_BAM 0x8350
+#define MDIO_AN_REG_8481_10GBASE_T_AN_CTRL 0x0020
#define MDIO_AN_REG_8481_LEGACY_MII_CTRL 0xffe0
+#define MDIO_AN_REG_8481_LEGACY_MII_STATUS 0xffe1
#define MDIO_AN_REG_8481_LEGACY_AN_ADV 0xffe4
+#define MDIO_AN_REG_8481_LEGACY_AN_EXPANSION 0xffe6
#define MDIO_AN_REG_8481_1000T_CTRL 0xffe9
#define MDIO_AN_REG_8481_EXPANSION_REG_RD_RW 0xfff5
#define MDIO_AN_REG_8481_EXPANSION_REG_ACCESS 0xfff7
+#define MDIO_AN_REG_8481_AUX_CTRL 0xfff8
#define MDIO_AN_REG_8481_LEGACY_SHADOW 0xfffc
+/* BCM84823 only */
+#define MDIO_CTL_DEVAD 0x1e
+#define MDIO_CTL_REG_84823_MEDIA 0x401a
+#define MDIO_CTL_REG_84823_MEDIA_MAC_MASK 0x0018
+ /* These pins configure the BCM84823 interface to MAC after reset. */
+#define MDIO_CTL_REG_84823_CTRL_MAC_XFI 0x0008
+#define MDIO_CTL_REG_84823_MEDIA_MAC_XAUI_M 0x0010
+ /* These pins configure the BCM84823 interface to Line after reset. */
+#define MDIO_CTL_REG_84823_MEDIA_LINE_MASK 0x0060
+#define MDIO_CTL_REG_84823_MEDIA_LINE_XAUI_L 0x0020
+#define MDIO_CTL_REG_84823_MEDIA_LINE_XFI 0x0040
+ /* When this pin is active high during reset, 10GBASE-T core is power
+ * down, When it is active low the 10GBASE-T is power up
+ */
+#define MDIO_CTL_REG_84823_MEDIA_COPPER_CORE_DOWN 0x0080
+#define MDIO_CTL_REG_84823_MEDIA_PRIORITY_MASK 0x0100
+#define MDIO_CTL_REG_84823_MEDIA_PRIORITY_COPPER 0x0000
+#define MDIO_CTL_REG_84823_MEDIA_PRIORITY_FIBER 0x0100
+#define MDIO_CTL_REG_84823_MEDIA_FIBER_1G 0x1000
+
+
#define IGU_FUNC_BASE 0x0400
#define IGU_ADDR_MSIX 0x0000
@@ -5239,6 +6092,11 @@ Theotherbitsarereservedandshouldbezero*/
#define IGU_INT_NOP 2
#define IGU_INT_NOP2 3
+#define IGU_USE_REGISTER_ustorm_type_0_sb_cleanup 0
+#define IGU_USE_REGISTER_ustorm_type_1_sb_cleanup 1
+#define IGU_USE_REGISTER_cstorm_type_0_sb_cleanup 2
+#define IGU_USE_REGISTER_cstorm_type_1_sb_cleanup 3
+
#define COMMAND_REG_INT_ACK 0x0
#define COMMAND_REG_PROD_UPD 0x4
#define COMMAND_REG_ATTN_BITS_UPD 0x8
@@ -5281,6 +6139,50 @@ Theotherbitsarereservedandshouldbezero*/
#define IGU_REG_SISR_MDPC_WOMASK_UPPER 0x05a6
#define IGU_REG_RESERVED_UPPER 0x05ff
+/* Fields of IGU PF CONFIGRATION REGISTER */
+#define IGU_PF_CONF_FUNC_EN (0x1<<0) /* function enable */
+#define IGU_PF_CONF_MSI_MSIX_EN (0x1<<1) /* MSI/MSIX enable */
+#define IGU_PF_CONF_INT_LINE_EN (0x1<<2) /* INT enable */
+#define IGU_PF_CONF_ATTN_BIT_EN (0x1<<3) /* attention enable */
+#define IGU_PF_CONF_SINGLE_ISR_EN (0x1<<4) /* single ISR mode enable */
+#define IGU_PF_CONF_SIMD_MODE (0x1<<5) /* simd all ones mode */
+
+/* Fields of IGU VF CONFIGRATION REGISTER */
+#define IGU_VF_CONF_FUNC_EN (0x1<<0) /* function enable */
+#define IGU_VF_CONF_MSI_MSIX_EN (0x1<<1) /* MSI/MSIX enable */
+#define IGU_VF_CONF_PARENT_MASK (0x3<<2) /* Parent PF */
+#define IGU_VF_CONF_PARENT_SHIFT 2 /* Parent PF */
+#define IGU_VF_CONF_SINGLE_ISR_EN (0x1<<4) /* single ISR mode enable */
+
+
+#define IGU_BC_DSB_NUM_SEGS 5
+#define IGU_BC_NDSB_NUM_SEGS 2
+#define IGU_NORM_DSB_NUM_SEGS 2
+#define IGU_NORM_NDSB_NUM_SEGS 1
+#define IGU_BC_BASE_DSB_PROD 128
+#define IGU_NORM_BASE_DSB_PROD 136
+
+#define IGU_CTRL_CMD_TYPE_WR\
+ 1
+#define IGU_CTRL_CMD_TYPE_RD\
+ 0
+
+#define IGU_SEG_ACCESS_NORM 0
+#define IGU_SEG_ACCESS_DEF 1
+#define IGU_SEG_ACCESS_ATTN 2
+
+ /* FID (if VF - [6] = 0; [5:0] = VF number; if PF - [6] = 1; \
+ [5:2] = 0; [1:0] = PF number) */
+#define IGU_FID_ENCODE_IS_PF (0x1<<6)
+#define IGU_FID_ENCODE_IS_PF_SHIFT 6
+#define IGU_FID_VF_NUM_MASK (0x3f)
+#define IGU_FID_PF_NUM_MASK (0x7)
+
+#define IGU_REG_MAPPING_MEMORY_VALID (1<<0)
+#define IGU_REG_MAPPING_MEMORY_VECTOR_MASK (0x3F<<1)
+#define IGU_REG_MAPPING_MEMORY_VECTOR_SHIFT 1
+#define IGU_REG_MAPPING_MEMORY_FID_MASK (0x7F<<7)
+#define IGU_REG_MAPPING_MEMORY_FID_SHIFT 7
#define CDU_REGION_NUMBER_XCM_AG 2
diff --git a/drivers/net/bnx2x/bnx2x_stats.c b/drivers/net/bnx2x/bnx2x_stats.c
index c74724461020..4733c835dad9 100644
--- a/drivers/net/bnx2x/bnx2x_stats.c
+++ b/drivers/net/bnx2x/bnx2x_stats.c
@@ -14,8 +14,8 @@
* Statistics and Link management by Yitchak Gertner
*
*/
- #include "bnx2x_cmn.h"
- #include "bnx2x_stats.h"
+#include "bnx2x_cmn.h"
+#include "bnx2x_stats.h"
/* Statistics */
@@ -153,7 +153,7 @@ static inline long bnx2x_hilo(u32 *hiref)
static void bnx2x_storm_stats_post(struct bnx2x *bp)
{
if (!bp->stats_pending) {
- struct eth_query_ramrod_data ramrod_data = {0};
+ struct common_query_ramrod_data ramrod_data = {0};
int i, rc;
spin_lock_bh(&bp->stats_lock);
@@ -163,14 +163,11 @@ static void bnx2x_storm_stats_post(struct bnx2x *bp)
for_each_queue(bp, i)
ramrod_data.ctr_id_vector |= (1 << bp->fp[i].cl_id);
- rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_STAT_QUERY, 0,
+ rc = bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_STAT_QUERY, 0,
((u32 *)&ramrod_data)[1],
- ((u32 *)&ramrod_data)[0], 0);
- if (rc == 0) {
- /* stats ramrod has it's own slot on the spq */
- bp->spq_left++;
+ ((u32 *)&ramrod_data)[0], 1);
+ if (rc == 0)
bp->stats_pending = 1;
- }
spin_unlock_bh(&bp->stats_lock);
}
@@ -188,20 +185,12 @@ static void bnx2x_hw_stats_post(struct bnx2x *bp)
/* loader */
if (bp->executer_idx) {
int loader_idx = PMF_DMAE_C(bp);
+ u32 opcode = bnx2x_dmae_opcode(bp, DMAE_SRC_PCI, DMAE_DST_GRC,
+ true, DMAE_COMP_GRC);
+ opcode = bnx2x_dmae_opcode_clr_src_reset(opcode);
memset(dmae, 0, sizeof(struct dmae_command));
-
- dmae->opcode = (DMAE_CMD_SRC_PCI | DMAE_CMD_DST_GRC |
- DMAE_CMD_C_DST_GRC | DMAE_CMD_C_ENABLE |
- DMAE_CMD_DST_RESET |
-#ifdef __BIG_ENDIAN
- DMAE_CMD_ENDIANITY_B_DW_SWAP |
-#else
- DMAE_CMD_ENDIANITY_DW_SWAP |
-#endif
- (BP_PORT(bp) ? DMAE_CMD_PORT_1 :
- DMAE_CMD_PORT_0) |
- (BP_E1HVN(bp) << DMAE_CMD_E1HVN_SHIFT));
+ dmae->opcode = opcode;
dmae->src_addr_lo = U64_LO(bnx2x_sp_mapping(bp, dmae[0]));
dmae->src_addr_hi = U64_HI(bnx2x_sp_mapping(bp, dmae[0]));
dmae->dst_addr_lo = (DMAE_REG_CMD_MEM +
@@ -253,26 +242,17 @@ static void bnx2x_stats_pmf_update(struct bnx2x *bp)
u32 *stats_comp = bnx2x_sp(bp, stats_comp);
/* sanity */
- if (!IS_E1HMF(bp) || !bp->port.pmf || !bp->port.port_stx) {
+ if (!IS_MF(bp) || !bp->port.pmf || !bp->port.port_stx) {
BNX2X_ERR("BUG!\n");
return;
}
bp->executer_idx = 0;
- opcode = (DMAE_CMD_SRC_GRC | DMAE_CMD_DST_PCI |
- DMAE_CMD_C_ENABLE |
- DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET |
-#ifdef __BIG_ENDIAN
- DMAE_CMD_ENDIANITY_B_DW_SWAP |
-#else
- DMAE_CMD_ENDIANITY_DW_SWAP |
-#endif
- (BP_PORT(bp) ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0) |
- (BP_E1HVN(bp) << DMAE_CMD_E1HVN_SHIFT));
+ opcode = bnx2x_dmae_opcode(bp, DMAE_SRC_GRC, DMAE_DST_PCI, false, 0);
dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
- dmae->opcode = (opcode | DMAE_CMD_C_DST_GRC);
+ dmae->opcode = bnx2x_dmae_opcode_add_comp(opcode, DMAE_COMP_GRC);
dmae->src_addr_lo = bp->port.port_stx >> 2;
dmae->src_addr_hi = 0;
dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, port_stats));
@@ -283,7 +263,7 @@ static void bnx2x_stats_pmf_update(struct bnx2x *bp)
dmae->comp_val = 1;
dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
- dmae->opcode = (opcode | DMAE_CMD_C_DST_PCI);
+ dmae->opcode = bnx2x_dmae_opcode_add_comp(opcode, DMAE_COMP_PCI);
dmae->src_addr_lo = (bp->port.port_stx >> 2) + DMAE_LEN32_RD_MAX;
dmae->src_addr_hi = 0;
dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, port_stats) +
@@ -304,7 +284,6 @@ static void bnx2x_port_stats_init(struct bnx2x *bp)
{
struct dmae_command *dmae;
int port = BP_PORT(bp);
- int vn = BP_E1HVN(bp);
u32 opcode;
int loader_idx = PMF_DMAE_C(bp);
u32 mac_addr;
@@ -319,16 +298,8 @@ static void bnx2x_port_stats_init(struct bnx2x *bp)
bp->executer_idx = 0;
/* MCP */
- opcode = (DMAE_CMD_SRC_PCI | DMAE_CMD_DST_GRC |
- DMAE_CMD_C_DST_GRC | DMAE_CMD_C_ENABLE |
- DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET |
-#ifdef __BIG_ENDIAN
- DMAE_CMD_ENDIANITY_B_DW_SWAP |
-#else
- DMAE_CMD_ENDIANITY_DW_SWAP |
-#endif
- (port ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0) |
- (vn << DMAE_CMD_E1HVN_SHIFT));
+ opcode = bnx2x_dmae_opcode(bp, DMAE_SRC_PCI, DMAE_DST_GRC,
+ true, DMAE_COMP_GRC);
if (bp->port.port_stx) {
@@ -359,16 +330,8 @@ static void bnx2x_port_stats_init(struct bnx2x *bp)
}
/* MAC */
- opcode = (DMAE_CMD_SRC_GRC | DMAE_CMD_DST_PCI |
- DMAE_CMD_C_DST_GRC | DMAE_CMD_C_ENABLE |
- DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET |
-#ifdef __BIG_ENDIAN
- DMAE_CMD_ENDIANITY_B_DW_SWAP |
-#else
- DMAE_CMD_ENDIANITY_DW_SWAP |
-#endif
- (port ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0) |
- (vn << DMAE_CMD_E1HVN_SHIFT));
+ opcode = bnx2x_dmae_opcode(bp, DMAE_SRC_GRC, DMAE_DST_PCI,
+ true, DMAE_COMP_GRC);
if (bp->link_vars.mac_type == MAC_TYPE_BMAC) {
@@ -379,13 +342,21 @@ static void bnx2x_port_stats_init(struct bnx2x *bp)
BIGMAC_REGISTER_TX_STAT_GTBYT */
dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
dmae->opcode = opcode;
- dmae->src_addr_lo = (mac_addr +
+ if (CHIP_IS_E1x(bp)) {
+ dmae->src_addr_lo = (mac_addr +
BIGMAC_REGISTER_TX_STAT_GTPKT) >> 2;
+ dmae->len = (8 + BIGMAC_REGISTER_TX_STAT_GTBYT -
+ BIGMAC_REGISTER_TX_STAT_GTPKT) >> 2;
+ } else {
+ dmae->src_addr_lo = (mac_addr +
+ BIGMAC2_REGISTER_TX_STAT_GTPOK) >> 2;
+ dmae->len = (8 + BIGMAC2_REGISTER_TX_STAT_GTBYT -
+ BIGMAC2_REGISTER_TX_STAT_GTPOK) >> 2;
+ }
+
dmae->src_addr_hi = 0;
dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, mac_stats));
dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, mac_stats));
- dmae->len = (8 + BIGMAC_REGISTER_TX_STAT_GTBYT -
- BIGMAC_REGISTER_TX_STAT_GTPKT) >> 2;
dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2;
dmae->comp_addr_hi = 0;
dmae->comp_val = 1;
@@ -394,15 +365,31 @@ static void bnx2x_port_stats_init(struct bnx2x *bp)
BIGMAC_REGISTER_RX_STAT_GRIPJ */
dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
dmae->opcode = opcode;
- dmae->src_addr_lo = (mac_addr +
- BIGMAC_REGISTER_RX_STAT_GR64) >> 2;
dmae->src_addr_hi = 0;
- dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, mac_stats) +
- offsetof(struct bmac_stats, rx_stat_gr64_lo));
- dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, mac_stats) +
- offsetof(struct bmac_stats, rx_stat_gr64_lo));
- dmae->len = (8 + BIGMAC_REGISTER_RX_STAT_GRIPJ -
- BIGMAC_REGISTER_RX_STAT_GR64) >> 2;
+ if (CHIP_IS_E1x(bp)) {
+ dmae->src_addr_lo = (mac_addr +
+ BIGMAC_REGISTER_RX_STAT_GR64) >> 2;
+ dmae->dst_addr_lo =
+ U64_LO(bnx2x_sp_mapping(bp, mac_stats) +
+ offsetof(struct bmac1_stats, rx_stat_gr64_lo));
+ dmae->dst_addr_hi =
+ U64_HI(bnx2x_sp_mapping(bp, mac_stats) +
+ offsetof(struct bmac1_stats, rx_stat_gr64_lo));
+ dmae->len = (8 + BIGMAC_REGISTER_RX_STAT_GRIPJ -
+ BIGMAC_REGISTER_RX_STAT_GR64) >> 2;
+ } else {
+ dmae->src_addr_lo =
+ (mac_addr + BIGMAC2_REGISTER_RX_STAT_GR64) >> 2;
+ dmae->dst_addr_lo =
+ U64_LO(bnx2x_sp_mapping(bp, mac_stats) +
+ offsetof(struct bmac2_stats, rx_stat_gr64_lo));
+ dmae->dst_addr_hi =
+ U64_HI(bnx2x_sp_mapping(bp, mac_stats) +
+ offsetof(struct bmac2_stats, rx_stat_gr64_lo));
+ dmae->len = (8 + BIGMAC2_REGISTER_RX_STAT_GRIPJ -
+ BIGMAC2_REGISTER_RX_STAT_GR64) >> 2;
+ }
+
dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2;
dmae->comp_addr_hi = 0;
dmae->comp_val = 1;
@@ -483,16 +470,8 @@ static void bnx2x_port_stats_init(struct bnx2x *bp)
dmae->comp_val = 1;
dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
- dmae->opcode = (DMAE_CMD_SRC_GRC | DMAE_CMD_DST_PCI |
- DMAE_CMD_C_DST_PCI | DMAE_CMD_C_ENABLE |
- DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET |
-#ifdef __BIG_ENDIAN
- DMAE_CMD_ENDIANITY_B_DW_SWAP |
-#else
- DMAE_CMD_ENDIANITY_DW_SWAP |
-#endif
- (port ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0) |
- (vn << DMAE_CMD_E1HVN_SHIFT));
+ dmae->opcode = bnx2x_dmae_opcode(bp, DMAE_SRC_GRC, DMAE_DST_PCI,
+ true, DMAE_COMP_PCI);
dmae->src_addr_lo = (port ? NIG_REG_STAT1_EGRESS_MAC_PKT1 :
NIG_REG_STAT0_EGRESS_MAC_PKT1) >> 2;
dmae->src_addr_hi = 0;
@@ -522,16 +501,8 @@ static void bnx2x_func_stats_init(struct bnx2x *bp)
bp->executer_idx = 0;
memset(dmae, 0, sizeof(struct dmae_command));
- dmae->opcode = (DMAE_CMD_SRC_PCI | DMAE_CMD_DST_GRC |
- DMAE_CMD_C_DST_PCI | DMAE_CMD_C_ENABLE |
- DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET |
-#ifdef __BIG_ENDIAN
- DMAE_CMD_ENDIANITY_B_DW_SWAP |
-#else
- DMAE_CMD_ENDIANITY_DW_SWAP |
-#endif
- (BP_PORT(bp) ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0) |
- (BP_E1HVN(bp) << DMAE_CMD_E1HVN_SHIFT));
+ dmae->opcode = bnx2x_dmae_opcode(bp, DMAE_SRC_PCI, DMAE_DST_GRC,
+ true, DMAE_COMP_PCI);
dmae->src_addr_lo = U64_LO(bnx2x_sp_mapping(bp, func_stats));
dmae->src_addr_hi = U64_HI(bnx2x_sp_mapping(bp, func_stats));
dmae->dst_addr_lo = bp->func_stx >> 2;
@@ -571,7 +542,6 @@ static void bnx2x_stats_restart(struct bnx2x *bp)
static void bnx2x_bmac_stats_update(struct bnx2x *bp)
{
- struct bmac_stats *new = bnx2x_sp(bp, mac_stats.bmac_stats);
struct host_port_stats *pstats = bnx2x_sp(bp, port_stats);
struct bnx2x_eth_stats *estats = &bp->eth_stats;
struct {
@@ -579,35 +549,74 @@ static void bnx2x_bmac_stats_update(struct bnx2x *bp)
u32 hi;
} diff;
- UPDATE_STAT64(rx_stat_grerb, rx_stat_ifhcinbadoctets);
- UPDATE_STAT64(rx_stat_grfcs, rx_stat_dot3statsfcserrors);
- UPDATE_STAT64(rx_stat_grund, rx_stat_etherstatsundersizepkts);
- UPDATE_STAT64(rx_stat_grovr, rx_stat_dot3statsframestoolong);
- UPDATE_STAT64(rx_stat_grfrg, rx_stat_etherstatsfragments);
- UPDATE_STAT64(rx_stat_grjbr, rx_stat_etherstatsjabbers);
- UPDATE_STAT64(rx_stat_grxcf, rx_stat_maccontrolframesreceived);
- UPDATE_STAT64(rx_stat_grxpf, rx_stat_xoffstateentered);
- UPDATE_STAT64(rx_stat_grxpf, rx_stat_bmac_xpf);
- UPDATE_STAT64(tx_stat_gtxpf, tx_stat_outxoffsent);
- UPDATE_STAT64(tx_stat_gtxpf, tx_stat_flowcontroldone);
- UPDATE_STAT64(tx_stat_gt64, tx_stat_etherstatspkts64octets);
- UPDATE_STAT64(tx_stat_gt127,
+ if (CHIP_IS_E1x(bp)) {
+ struct bmac1_stats *new = bnx2x_sp(bp, mac_stats.bmac1_stats);
+
+ /* the macros below will use "bmac1_stats" type */
+ UPDATE_STAT64(rx_stat_grerb, rx_stat_ifhcinbadoctets);
+ UPDATE_STAT64(rx_stat_grfcs, rx_stat_dot3statsfcserrors);
+ UPDATE_STAT64(rx_stat_grund, rx_stat_etherstatsundersizepkts);
+ UPDATE_STAT64(rx_stat_grovr, rx_stat_dot3statsframestoolong);
+ UPDATE_STAT64(rx_stat_grfrg, rx_stat_etherstatsfragments);
+ UPDATE_STAT64(rx_stat_grjbr, rx_stat_etherstatsjabbers);
+ UPDATE_STAT64(rx_stat_grxcf, rx_stat_maccontrolframesreceived);
+ UPDATE_STAT64(rx_stat_grxpf, rx_stat_xoffstateentered);
+ UPDATE_STAT64(rx_stat_grxpf, rx_stat_bmac_xpf);
+ UPDATE_STAT64(tx_stat_gtxpf, tx_stat_outxoffsent);
+ UPDATE_STAT64(tx_stat_gtxpf, tx_stat_flowcontroldone);
+ UPDATE_STAT64(tx_stat_gt64, tx_stat_etherstatspkts64octets);
+ UPDATE_STAT64(tx_stat_gt127,
+ tx_stat_etherstatspkts65octetsto127octets);
+ UPDATE_STAT64(tx_stat_gt255,
+ tx_stat_etherstatspkts128octetsto255octets);
+ UPDATE_STAT64(tx_stat_gt511,
+ tx_stat_etherstatspkts256octetsto511octets);
+ UPDATE_STAT64(tx_stat_gt1023,
+ tx_stat_etherstatspkts512octetsto1023octets);
+ UPDATE_STAT64(tx_stat_gt1518,
+ tx_stat_etherstatspkts1024octetsto1522octets);
+ UPDATE_STAT64(tx_stat_gt2047, tx_stat_bmac_2047);
+ UPDATE_STAT64(tx_stat_gt4095, tx_stat_bmac_4095);
+ UPDATE_STAT64(tx_stat_gt9216, tx_stat_bmac_9216);
+ UPDATE_STAT64(tx_stat_gt16383, tx_stat_bmac_16383);
+ UPDATE_STAT64(tx_stat_gterr,
+ tx_stat_dot3statsinternalmactransmiterrors);
+ UPDATE_STAT64(tx_stat_gtufl, tx_stat_bmac_ufl);
+
+ } else {
+ struct bmac2_stats *new = bnx2x_sp(bp, mac_stats.bmac2_stats);
+
+ /* the macros below will use "bmac2_stats" type */
+ UPDATE_STAT64(rx_stat_grerb, rx_stat_ifhcinbadoctets);
+ UPDATE_STAT64(rx_stat_grfcs, rx_stat_dot3statsfcserrors);
+ UPDATE_STAT64(rx_stat_grund, rx_stat_etherstatsundersizepkts);
+ UPDATE_STAT64(rx_stat_grovr, rx_stat_dot3statsframestoolong);
+ UPDATE_STAT64(rx_stat_grfrg, rx_stat_etherstatsfragments);
+ UPDATE_STAT64(rx_stat_grjbr, rx_stat_etherstatsjabbers);
+ UPDATE_STAT64(rx_stat_grxcf, rx_stat_maccontrolframesreceived);
+ UPDATE_STAT64(rx_stat_grxpf, rx_stat_xoffstateentered);
+ UPDATE_STAT64(rx_stat_grxpf, rx_stat_bmac_xpf);
+ UPDATE_STAT64(tx_stat_gtxpf, tx_stat_outxoffsent);
+ UPDATE_STAT64(tx_stat_gtxpf, tx_stat_flowcontroldone);
+ UPDATE_STAT64(tx_stat_gt64, tx_stat_etherstatspkts64octets);
+ UPDATE_STAT64(tx_stat_gt127,
tx_stat_etherstatspkts65octetsto127octets);
- UPDATE_STAT64(tx_stat_gt255,
+ UPDATE_STAT64(tx_stat_gt255,
tx_stat_etherstatspkts128octetsto255octets);
- UPDATE_STAT64(tx_stat_gt511,
+ UPDATE_STAT64(tx_stat_gt511,
tx_stat_etherstatspkts256octetsto511octets);
- UPDATE_STAT64(tx_stat_gt1023,
+ UPDATE_STAT64(tx_stat_gt1023,
tx_stat_etherstatspkts512octetsto1023octets);
- UPDATE_STAT64(tx_stat_gt1518,
+ UPDATE_STAT64(tx_stat_gt1518,
tx_stat_etherstatspkts1024octetsto1522octets);
- UPDATE_STAT64(tx_stat_gt2047, tx_stat_bmac_2047);
- UPDATE_STAT64(tx_stat_gt4095, tx_stat_bmac_4095);
- UPDATE_STAT64(tx_stat_gt9216, tx_stat_bmac_9216);
- UPDATE_STAT64(tx_stat_gt16383, tx_stat_bmac_16383);
- UPDATE_STAT64(tx_stat_gterr,
+ UPDATE_STAT64(tx_stat_gt2047, tx_stat_bmac_2047);
+ UPDATE_STAT64(tx_stat_gt4095, tx_stat_bmac_4095);
+ UPDATE_STAT64(tx_stat_gt9216, tx_stat_bmac_9216);
+ UPDATE_STAT64(tx_stat_gt16383, tx_stat_bmac_16383);
+ UPDATE_STAT64(tx_stat_gterr,
tx_stat_dot3statsinternalmactransmiterrors);
- UPDATE_STAT64(tx_stat_gtufl, tx_stat_bmac_ufl);
+ UPDATE_STAT64(tx_stat_gtufl, tx_stat_bmac_ufl);
+ }
estats->pause_frames_received_hi =
pstats->mac_stx[1].rx_stat_bmac_xpf_hi;
@@ -969,6 +978,7 @@ static void bnx2x_net_stats_update(struct bnx2x *bp)
{
struct bnx2x_eth_stats *estats = &bp->eth_stats;
struct net_device_stats *nstats = &bp->dev->stats;
+ unsigned long tmp;
int i;
nstats->rx_packets =
@@ -985,10 +995,10 @@ static void bnx2x_net_stats_update(struct bnx2x *bp)
nstats->tx_bytes = bnx2x_hilo(&estats->total_bytes_transmitted_hi);
- nstats->rx_dropped = estats->mac_discard;
+ tmp = estats->mac_discard;
for_each_queue(bp, i)
- nstats->rx_dropped +=
- le32_to_cpu(bp->fp[i].old_tclient.checksum_discard);
+ tmp += le32_to_cpu(bp->fp[i].old_tclient.checksum_discard);
+ nstats->rx_dropped = tmp;
nstats->tx_dropped = 0;
@@ -1123,24 +1133,17 @@ static void bnx2x_port_stats_stop(struct bnx2x *bp)
bp->executer_idx = 0;
- opcode = (DMAE_CMD_SRC_PCI | DMAE_CMD_DST_GRC |
- DMAE_CMD_C_ENABLE |
- DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET |
-#ifdef __BIG_ENDIAN
- DMAE_CMD_ENDIANITY_B_DW_SWAP |
-#else
- DMAE_CMD_ENDIANITY_DW_SWAP |
-#endif
- (BP_PORT(bp) ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0) |
- (BP_E1HVN(bp) << DMAE_CMD_E1HVN_SHIFT));
+ opcode = bnx2x_dmae_opcode(bp, DMAE_SRC_PCI, DMAE_DST_GRC, false, 0);
if (bp->port.port_stx) {
dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
if (bp->func_stx)
- dmae->opcode = (opcode | DMAE_CMD_C_DST_GRC);
+ dmae->opcode = bnx2x_dmae_opcode_add_comp(
+ opcode, DMAE_COMP_GRC);
else
- dmae->opcode = (opcode | DMAE_CMD_C_DST_PCI);
+ dmae->opcode = bnx2x_dmae_opcode_add_comp(
+ opcode, DMAE_COMP_PCI);
dmae->src_addr_lo = U64_LO(bnx2x_sp_mapping(bp, port_stats));
dmae->src_addr_hi = U64_HI(bnx2x_sp_mapping(bp, port_stats));
dmae->dst_addr_lo = bp->port.port_stx >> 2;
@@ -1164,7 +1167,8 @@ static void bnx2x_port_stats_stop(struct bnx2x *bp)
if (bp->func_stx) {
dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
- dmae->opcode = (opcode | DMAE_CMD_C_DST_PCI);
+ dmae->opcode =
+ bnx2x_dmae_opcode_add_comp(opcode, DMAE_COMP_PCI);
dmae->src_addr_lo = U64_LO(bnx2x_sp_mapping(bp, func_stats));
dmae->src_addr_hi = U64_HI(bnx2x_sp_mapping(bp, func_stats));
dmae->dst_addr_lo = bp->func_stx >> 2;
@@ -1257,16 +1261,8 @@ static void bnx2x_port_stats_base_init(struct bnx2x *bp)
bp->executer_idx = 0;
dmae = bnx2x_sp(bp, dmae[bp->executer_idx++]);
- dmae->opcode = (DMAE_CMD_SRC_PCI | DMAE_CMD_DST_GRC |
- DMAE_CMD_C_DST_PCI | DMAE_CMD_C_ENABLE |
- DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET |
-#ifdef __BIG_ENDIAN
- DMAE_CMD_ENDIANITY_B_DW_SWAP |
-#else
- DMAE_CMD_ENDIANITY_DW_SWAP |
-#endif
- (BP_PORT(bp) ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0) |
- (BP_E1HVN(bp) << DMAE_CMD_E1HVN_SHIFT));
+ dmae->opcode = bnx2x_dmae_opcode(bp, DMAE_SRC_PCI, DMAE_DST_GRC,
+ true, DMAE_COMP_PCI);
dmae->src_addr_lo = U64_LO(bnx2x_sp_mapping(bp, port_stats));
dmae->src_addr_hi = U64_HI(bnx2x_sp_mapping(bp, port_stats));
dmae->dst_addr_lo = bp->port.port_stx >> 2;
@@ -1283,9 +1279,7 @@ static void bnx2x_port_stats_base_init(struct bnx2x *bp)
static void bnx2x_func_stats_base_init(struct bnx2x *bp)
{
- int vn, vn_max = IS_E1HMF(bp) ? E1HVN_MAX : E1VN_MAX;
- int port = BP_PORT(bp);
- int func;
+ int vn, vn_max = IS_MF(bp) ? E1HVN_MAX : E1VN_MAX;
u32 func_stx;
/* sanity */
@@ -1298,9 +1292,9 @@ static void bnx2x_func_stats_base_init(struct bnx2x *bp)
func_stx = bp->func_stx;
for (vn = VN_0; vn < vn_max; vn++) {
- func = 2*vn + port;
+ int mb_idx = !CHIP_IS_E2(bp) ? 2*vn + BP_PORT(bp) : vn;
- bp->func_stx = SHMEM_RD(bp, func_mb[func].fw_mb_param);
+ bp->func_stx = SHMEM_RD(bp, func_mb[mb_idx].fw_mb_param);
bnx2x_func_stats_init(bp);
bnx2x_hw_stats_post(bp);
bnx2x_stats_comp(bp);
@@ -1324,16 +1318,8 @@ static void bnx2x_func_stats_base_update(struct bnx2x *bp)
bp->executer_idx = 0;
memset(dmae, 0, sizeof(struct dmae_command));
- dmae->opcode = (DMAE_CMD_SRC_GRC | DMAE_CMD_DST_PCI |
- DMAE_CMD_C_DST_PCI | DMAE_CMD_C_ENABLE |
- DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET |
-#ifdef __BIG_ENDIAN
- DMAE_CMD_ENDIANITY_B_DW_SWAP |
-#else
- DMAE_CMD_ENDIANITY_DW_SWAP |
-#endif
- (BP_PORT(bp) ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0) |
- (BP_E1HVN(bp) << DMAE_CMD_E1HVN_SHIFT));
+ dmae->opcode = bnx2x_dmae_opcode(bp, DMAE_SRC_GRC, DMAE_DST_PCI,
+ true, DMAE_COMP_PCI);
dmae->src_addr_lo = bp->func_stx >> 2;
dmae->src_addr_hi = 0;
dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, func_stats_base));
@@ -1351,8 +1337,9 @@ static void bnx2x_func_stats_base_update(struct bnx2x *bp)
void bnx2x_stats_init(struct bnx2x *bp)
{
int port = BP_PORT(bp);
- int func = BP_FUNC(bp);
+ int mb_idx = BP_FW_MB_IDX(bp);
int i;
+ struct eth_stats_query *stats = bnx2x_sp(bp, fw_stats);
bp->stats_pending = 0;
bp->executer_idx = 0;
@@ -1361,7 +1348,7 @@ void bnx2x_stats_init(struct bnx2x *bp)
/* port and func stats for management */
if (!BP_NOMCP(bp)) {
bp->port.port_stx = SHMEM_RD(bp, port_mb[port].port_stx);
- bp->func_stx = SHMEM_RD(bp, func_mb[func].fw_mb_param);
+ bp->func_stx = SHMEM_RD(bp, func_mb[mb_idx].fw_mb_param);
} else {
bp->port.port_stx = 0;
@@ -1394,6 +1381,18 @@ void bnx2x_stats_init(struct bnx2x *bp)
memset(&fp->eth_q_stats, 0, sizeof(struct bnx2x_eth_q_stats));
}
+ for_each_queue(bp, i) {
+ /* Set initial stats counter in the stats ramrod data to -1 */
+ int cl_id = bp->fp[i].cl_id;
+
+ stats->xstorm_common.client_statistics[cl_id].
+ stats_counter = 0xffff;
+ stats->ustorm_common.client_statistics[cl_id].
+ stats_counter = 0xffff;
+ stats->tstorm_common.client_statistics[cl_id].
+ stats_counter = 0xffff;
+ }
+
memset(&bp->dev->stats, 0, sizeof(struct net_device_stats));
memset(&bp->eth_stats, 0, sizeof(struct bnx2x_eth_stats));
diff --git a/drivers/net/bnx2x/bnx2x_stats.h b/drivers/net/bnx2x/bnx2x_stats.h
index 38a4e908f4fb..afd15efa429a 100644
--- a/drivers/net/bnx2x/bnx2x_stats.h
+++ b/drivers/net/bnx2x/bnx2x_stats.h
@@ -9,6 +9,10 @@
* Maintained by: Eilon Greenstein <eilong@broadcom.com>
* Written by: Eliezer Tamir
* Based on code from Michael Chan's bnx2 driver
+ * UDP CSUM errata workaround by Arik Gendelman
+ * Slowpath and fastpath rework by Vladislav Zolotarov
+ * Statistics and Link management by Yitchak Gertner
+ *
*/
#ifndef BNX2X_STATS_H
@@ -228,12 +232,8 @@ struct bnx2x_eth_stats {
/* Forward declaration */
struct bnx2x;
-
void bnx2x_stats_init(struct bnx2x *bp);
extern const u32 dmae_reg_go_c[];
-extern int bnx2x_sp_post(struct bnx2x *bp, int command, int cid,
- u32 data_hi, u32 data_lo, int common);
-
#endif /* BNX2X_STATS_H */
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index 0ddf4c66afe2..881914bc4e9c 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -93,7 +93,7 @@
// compare MAC addresses
#define MAC_ADDRESS_COMPARE(A, B) memcmp(A, B, ETH_ALEN)
-static struct mac_addr null_mac_addr = {{0, 0, 0, 0, 0, 0}};
+static struct mac_addr null_mac_addr = { { 0, 0, 0, 0, 0, 0 } };
static u16 ad_ticks_per_sec;
static const int ad_delta_in_ticks = (AD_TIMER_INTERVAL * HZ) / 1000;
@@ -129,9 +129,8 @@ static void ad_marker_response_received(struct bond_marker *marker, struct port
*/
static inline struct bonding *__get_bond_by_port(struct port *port)
{
- if (port->slave == NULL) {
+ if (port->slave == NULL)
return NULL;
- }
return bond_get_bond_by_slave(port->slave);
}
@@ -144,9 +143,8 @@ static inline struct bonding *__get_bond_by_port(struct port *port)
*/
static inline struct port *__get_first_port(struct bonding *bond)
{
- if (bond->slave_cnt == 0) {
+ if (bond->slave_cnt == 0)
return NULL;
- }
return &(SLAVE_AD_INFO(bond->first_slave).port);
}
@@ -164,9 +162,8 @@ static inline struct port *__get_next_port(struct port *port)
struct slave *slave = port->slave;
// If there's no bond for this port, or this is the last slave
- if ((bond == NULL) || (slave->next == bond->first_slave)) {
+ if ((bond == NULL) || (slave->next == bond->first_slave))
return NULL;
- }
return &(SLAVE_AD_INFO(slave->next).port);
}
@@ -183,9 +180,8 @@ static inline struct aggregator *__get_first_agg(struct port *port)
struct bonding *bond = __get_bond_by_port(port);
// If there's no bond for this port, or bond has no slaves
- if ((bond == NULL) || (bond->slave_cnt == 0)) {
+ if ((bond == NULL) || (bond->slave_cnt == 0))
return NULL;
- }
return &(SLAVE_AD_INFO(bond->first_slave).aggregator);
}
@@ -203,9 +199,8 @@ static inline struct aggregator *__get_next_agg(struct aggregator *aggregator)
struct bonding *bond = bond_get_bond_by_slave(slave);
// If there's no bond for this aggregator, or this is the last slave
- if ((bond == NULL) || (slave->next == bond->first_slave)) {
+ if ((bond == NULL) || (slave->next == bond->first_slave))
return NULL;
- }
return &(SLAVE_AD_INFO(slave->next).aggregator);
}
@@ -240,9 +235,8 @@ static inline void __enable_port(struct port *port)
{
struct slave *slave = port->slave;
- if ((slave->link == BOND_LINK_UP) && IS_UP(slave->dev)) {
+ if ((slave->link == BOND_LINK_UP) && IS_UP(slave->dev))
bond_set_slave_active_flags(slave);
- }
}
/**
@@ -252,7 +246,7 @@ static inline void __enable_port(struct port *port)
*/
static inline int __port_is_enabled(struct port *port)
{
- return(port->slave->state == BOND_STATE_ACTIVE);
+ return port->slave->state == BOND_STATE_ACTIVE;
}
/**
@@ -265,9 +259,8 @@ static inline u32 __get_agg_selection_mode(struct port *port)
{
struct bonding *bond = __get_bond_by_port(port);
- if (bond == NULL) {
+ if (bond == NULL)
return BOND_AD_STABLE;
- }
return BOND_AD_INFO(bond).agg_select_mode;
}
@@ -281,9 +274,8 @@ static inline int __check_agg_selection_timer(struct port *port)
{
struct bonding *bond = __get_bond_by_port(port);
- if (bond == NULL) {
+ if (bond == NULL)
return 0;
- }
return BOND_AD_INFO(bond).agg_select_timer ? 1 : 0;
}
@@ -328,9 +320,9 @@ static u16 __get_link_speed(struct port *port)
* link down, it sets the speed to 0.
* This is done in spite of the fact that the e100 driver reports 0 to be
* compatible with MVT in the future.*/
- if (slave->link != BOND_LINK_UP) {
- speed=0;
- } else {
+ if (slave->link != BOND_LINK_UP)
+ speed = 0;
+ else {
switch (slave->speed) {
case SPEED_10:
speed = AD_LINK_SPEED_BITMASK_10MBPS;
@@ -375,18 +367,18 @@ static u8 __get_duplex(struct port *port)
// handling a special case: when the configuration starts with
// link down, it sets the duplex to 0.
- if (slave->link != BOND_LINK_UP) {
- retval=0x0;
- } else {
+ if (slave->link != BOND_LINK_UP)
+ retval = 0x0;
+ else {
switch (slave->duplex) {
case DUPLEX_FULL:
- retval=0x1;
+ retval = 0x1;
pr_debug("Port %d Received status full duplex update from adapter\n",
port->actor_port_number);
break;
case DUPLEX_HALF:
default:
- retval=0x0;
+ retval = 0x0;
pr_debug("Port %d Received status NOT full duplex update from adapter\n",
port->actor_port_number);
break;
@@ -419,15 +411,14 @@ static inline void __initialize_port_locks(struct port *port)
*/
static u16 __ad_timer_to_ticks(u16 timer_type, u16 par)
{
- u16 retval=0; //to silence the compiler
+ u16 retval = 0; /* to silence the compiler */
switch (timer_type) {
case AD_CURRENT_WHILE_TIMER: // for rx machine usage
- if (par) { // for short or long timeout
+ if (par)
retval = (AD_SHORT_TIMEOUT_TIME*ad_ticks_per_sec); // short timeout
- } else {
+ else
retval = (AD_LONG_TIMEOUT_TIME*ad_ticks_per_sec); // long timeout
- }
break;
case AD_ACTOR_CHURN_TIMER: // for local churn machine
retval = (AD_CHURN_DETECTION_TIME*ad_ticks_per_sec);
@@ -519,11 +510,11 @@ static void __record_pdu(struct lacpdu *lacpdu, struct port *port)
port->actor_oper_port_state &= ~AD_STATE_DEFAULTED;
// set the partner sync. to on if the partner is sync. and the port is matched
- if ((port->sm_vars & AD_PORT_MATCHED) && (lacpdu->actor_state & AD_STATE_SYNCHRONIZATION)) {
+ if ((port->sm_vars & AD_PORT_MATCHED)
+ && (lacpdu->actor_state & AD_STATE_SYNCHRONIZATION))
partner->port_state |= AD_STATE_SYNCHRONIZATION;
- } else {
+ else
partner->port_state &= ~AD_STATE_SYNCHRONIZATION;
- }
}
}
@@ -653,7 +644,7 @@ static void __update_ntt(struct lacpdu *lacpdu, struct port *port)
*/
static void __attach_bond_to_agg(struct port *port)
{
- port=NULL; // just to satisfy the compiler
+ port = NULL; /* just to satisfy the compiler */
// This function does nothing since the parser/multiplexer of the receive
// and the parser/multiplexer of the aggregator are already combined
}
@@ -668,7 +659,7 @@ static void __attach_bond_to_agg(struct port *port)
*/
static void __detach_bond_from_agg(struct port *port)
{
- port=NULL; // just to satisfy the compiler
+ port = NULL; /* just to satisfy the compiler */
// This function does nothing sience the parser/multiplexer of the receive
// and the parser/multiplexer of the aggregator are already combined
}
@@ -685,7 +676,9 @@ static int __agg_ports_are_ready(struct aggregator *aggregator)
if (aggregator) {
// scan all ports in this aggregator to verfy if they are all ready
- for (port=aggregator->lag_ports; port; port=port->next_port_in_aggregator) {
+ for (port = aggregator->lag_ports;
+ port;
+ port = port->next_port_in_aggregator) {
if (!(port->sm_vars & AD_PORT_READY_N)) {
retval = 0;
break;
@@ -706,12 +699,12 @@ static void __set_agg_ports_ready(struct aggregator *aggregator, int val)
{
struct port *port;
- for (port=aggregator->lag_ports; port; port=port->next_port_in_aggregator) {
- if (val) {
+ for (port = aggregator->lag_ports; port;
+ port = port->next_port_in_aggregator) {
+ if (val)
port->sm_vars |= AD_PORT_READY;
- } else {
+ else
port->sm_vars &= ~AD_PORT_READY;
- }
}
}
@@ -722,7 +715,7 @@ static void __set_agg_ports_ready(struct aggregator *aggregator, int val)
*/
static u32 __get_agg_bandwidth(struct aggregator *aggregator)
{
- u32 bandwidth=0;
+ u32 bandwidth = 0;
u32 basic_speed;
if (aggregator->num_of_ports) {
@@ -744,7 +737,7 @@ static u32 __get_agg_bandwidth(struct aggregator *aggregator)
bandwidth = aggregator->num_of_ports * 10000;
break;
default:
- bandwidth=0; // to silent the compilor ....
+ bandwidth = 0; /*to silence the compiler ....*/
}
}
return bandwidth;
@@ -835,9 +828,8 @@ static int ad_lacpdu_send(struct port *port)
int length = sizeof(struct lacpdu_header);
skb = dev_alloc_skb(length);
- if (!skb) {
+ if (!skb)
return -ENOMEM;
- }
skb->dev = slave->dev;
skb_reset_mac_header(skb);
@@ -876,9 +868,8 @@ static int ad_marker_send(struct port *port, struct bond_marker *marker)
int length = sizeof(struct bond_marker_header);
skb = dev_alloc_skb(length + 16);
- if (!skb) {
+ if (!skb)
return -ENOMEM;
- }
skb_reserve(skb, 16);
@@ -919,9 +910,10 @@ static void ad_mux_machine(struct port *port)
} else {
switch (port->sm_mux_state) {
case AD_MUX_DETACHED:
- if ((port->sm_vars & AD_PORT_SELECTED) || (port->sm_vars & AD_PORT_STANDBY)) { // if SELECTED or STANDBY
+ if ((port->sm_vars & AD_PORT_SELECTED)
+ || (port->sm_vars & AD_PORT_STANDBY))
+ /* if SELECTED or STANDBY */
port->sm_mux_state = AD_MUX_WAITING; // next state
- }
break;
case AD_MUX_WAITING:
// if SELECTED == FALSE return to DETACH state
@@ -935,18 +927,18 @@ static void ad_mux_machine(struct port *port)
}
// check if the wait_while_timer expired
- if (port->sm_mux_timer_counter && !(--port->sm_mux_timer_counter)) {
+ if (port->sm_mux_timer_counter
+ && !(--port->sm_mux_timer_counter))
port->sm_vars |= AD_PORT_READY_N;
- }
// in order to withhold the selection logic to check all ports READY_N value
// every callback cycle to update ready variable, we check READY_N and update READY here
__set_agg_ports_ready(port->aggregator, __agg_ports_are_ready(port->aggregator));
// if the wait_while_timer expired, and the port is in READY state, move to ATTACHED state
- if ((port->sm_vars & AD_PORT_READY) && !port->sm_mux_timer_counter) {
+ if ((port->sm_vars & AD_PORT_READY)
+ && !port->sm_mux_timer_counter)
port->sm_mux_state = AD_MUX_ATTACHED; // next state
- }
break;
case AD_MUX_ATTACHED:
// check also if agg_select_timer expired(so the edable port will take place only after this timer)
@@ -1041,13 +1033,14 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
// check if state machine should change state
// first, check if port was reinitialized
- if (port->sm_vars & AD_PORT_BEGIN) {
- port->sm_rx_state = AD_RX_INITIALIZE; // next state
- }
+ if (port->sm_vars & AD_PORT_BEGIN)
+ /* next state */
+ port->sm_rx_state = AD_RX_INITIALIZE;
// check if port is not enabled
- else if (!(port->sm_vars & AD_PORT_BEGIN) && !port->is_enabled && !(port->sm_vars & AD_PORT_MOVED)) {
- port->sm_rx_state = AD_RX_PORT_DISABLED; // next state
- }
+ else if (!(port->sm_vars & AD_PORT_BEGIN)
+ && !port->is_enabled && !(port->sm_vars & AD_PORT_MOVED))
+ /* next state */
+ port->sm_rx_state = AD_RX_PORT_DISABLED;
// check if new lacpdu arrived
else if (lacpdu && ((port->sm_rx_state == AD_RX_EXPIRED) || (port->sm_rx_state == AD_RX_DEFAULTED) || (port->sm_rx_state == AD_RX_CURRENT))) {
port->sm_rx_timer_counter = 0; // zero timer
@@ -1069,13 +1062,16 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
// if no lacpdu arrived and no timer is on
switch (port->sm_rx_state) {
case AD_RX_PORT_DISABLED:
- if (port->sm_vars & AD_PORT_MOVED) {
+ if (port->sm_vars & AD_PORT_MOVED)
port->sm_rx_state = AD_RX_INITIALIZE; // next state
- } else if (port->is_enabled && (port->sm_vars & AD_PORT_LACP_ENABLED)) {
+ else if (port->is_enabled
+ && (port->sm_vars
+ & AD_PORT_LACP_ENABLED))
port->sm_rx_state = AD_RX_EXPIRED; // next state
- } else if (port->is_enabled && ((port->sm_vars & AD_PORT_LACP_ENABLED) == 0)) {
+ else if (port->is_enabled
+ && ((port->sm_vars
+ & AD_PORT_LACP_ENABLED) == 0))
port->sm_rx_state = AD_RX_LACP_DISABLED; // next state
- }
break;
default: //to silence the compiler
break;
@@ -1091,11 +1087,10 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
port->sm_rx_state);
switch (port->sm_rx_state) {
case AD_RX_INITIALIZE:
- if (!(port->actor_oper_port_key & AD_DUPLEX_KEY_BITS)) {
+ if (!(port->actor_oper_port_key & AD_DUPLEX_KEY_BITS))
port->sm_vars &= ~AD_PORT_LACP_ENABLED;
- } else {
+ else
port->sm_vars |= AD_PORT_LACP_ENABLED;
- }
port->sm_vars &= ~AD_PORT_SELECTED;
__record_default(port);
port->actor_oper_port_state &= ~AD_STATE_EXPIRED;
@@ -1149,9 +1144,10 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
// verify that if the aggregator is enabled, the port is enabled too.
//(because if the link goes down for a short time, the 802.3ad will not
// catch it, and the port will continue to be disabled)
- if (port->aggregator && port->aggregator->is_active && !__port_is_enabled(port)) {
+ if (port->aggregator
+ && port->aggregator->is_active
+ && !__port_is_enabled(port))
__enable_port(port);
- }
break;
default: //to silence the compiler
break;
@@ -1183,7 +1179,8 @@ static void ad_tx_machine(struct port *port)
}
}
// restart tx timer(to verify that we will not exceed AD_MAX_TX_IN_SECOND
- port->sm_tx_timer_counter=ad_ticks_per_sec/AD_MAX_TX_IN_SECOND;
+ port->sm_tx_timer_counter =
+ ad_ticks_per_sec/AD_MAX_TX_IN_SECOND;
}
}
@@ -1216,9 +1213,9 @@ static void ad_periodic_machine(struct port *port)
// If not expired, check if there is some new timeout parameter from the partner state
switch (port->sm_periodic_state) {
case AD_FAST_PERIODIC:
- if (!(port->partner_oper.port_state & AD_STATE_LACP_TIMEOUT)) {
+ if (!(port->partner_oper.port_state
+ & AD_STATE_LACP_TIMEOUT))
port->sm_periodic_state = AD_SLOW_PERIODIC; // next state
- }
break;
case AD_SLOW_PERIODIC:
if ((port->partner_oper.port_state & AD_STATE_LACP_TIMEOUT)) {
@@ -1237,11 +1234,11 @@ static void ad_periodic_machine(struct port *port)
port->sm_periodic_state = AD_FAST_PERIODIC; // next state
break;
case AD_PERIODIC_TX:
- if (!(port->partner_oper.port_state & AD_STATE_LACP_TIMEOUT)) {
+ if (!(port->partner_oper.port_state
+ & AD_STATE_LACP_TIMEOUT))
port->sm_periodic_state = AD_SLOW_PERIODIC; // next state
- } else {
+ else
port->sm_periodic_state = AD_FAST_PERIODIC; // next state
- }
break;
default: //to silence the compiler
break;
@@ -1287,35 +1284,37 @@ static void ad_port_selection_logic(struct port *port)
int found = 0;
// if the port is already Selected, do nothing
- if (port->sm_vars & AD_PORT_SELECTED) {
+ if (port->sm_vars & AD_PORT_SELECTED)
return;
- }
// if the port is connected to other aggregator, detach it
if (port->aggregator) {
// detach the port from its former aggregator
- temp_aggregator=port->aggregator;
- for (curr_port=temp_aggregator->lag_ports; curr_port; last_port=curr_port, curr_port=curr_port->next_port_in_aggregator) {
+ temp_aggregator = port->aggregator;
+ for (curr_port = temp_aggregator->lag_ports; curr_port;
+ last_port = curr_port,
+ curr_port = curr_port->next_port_in_aggregator) {
if (curr_port == port) {
temp_aggregator->num_of_ports--;
if (!last_port) {// if it is the first port attached to the aggregator
- temp_aggregator->lag_ports=port->next_port_in_aggregator;
+ temp_aggregator->lag_ports =
+ port->next_port_in_aggregator;
} else {// not the first port attached to the aggregator
- last_port->next_port_in_aggregator=port->next_port_in_aggregator;
+ last_port->next_port_in_aggregator =
+ port->next_port_in_aggregator;
}
// clear the port's relations to this aggregator
port->aggregator = NULL;
- port->next_port_in_aggregator=NULL;
- port->actor_port_aggregator_identifier=0;
+ port->next_port_in_aggregator = NULL;
+ port->actor_port_aggregator_identifier = 0;
pr_debug("Port %d left LAG %d\n",
port->actor_port_number,
temp_aggregator->aggregator_identifier);
// if the aggregator is empty, clear its parameters, and set it ready to be attached
- if (!temp_aggregator->lag_ports) {
+ if (!temp_aggregator->lag_ports)
ad_clear_agg(temp_aggregator);
- }
break;
}
}
@@ -1333,9 +1332,8 @@ static void ad_port_selection_logic(struct port *port)
// keep a free aggregator for later use(if needed)
if (!aggregator->lag_ports) {
- if (!free_aggregator) {
- free_aggregator=aggregator;
- }
+ if (!free_aggregator)
+ free_aggregator = aggregator;
continue;
}
// check if current aggregator suits us
@@ -1350,10 +1348,11 @@ static void ad_port_selection_logic(struct port *port)
) {
// attach to the founded aggregator
port->aggregator = aggregator;
- port->actor_port_aggregator_identifier=port->aggregator->aggregator_identifier;
- port->next_port_in_aggregator=aggregator->lag_ports;
+ port->actor_port_aggregator_identifier =
+ port->aggregator->aggregator_identifier;
+ port->next_port_in_aggregator = aggregator->lag_ports;
port->aggregator->num_of_ports++;
- aggregator->lag_ports=port;
+ aggregator->lag_ports = port;
pr_debug("Port %d joined LAG %d(existing LAG)\n",
port->actor_port_number,
port->aggregator->aggregator_identifier);
@@ -1370,20 +1369,23 @@ static void ad_port_selection_logic(struct port *port)
if (free_aggregator) {
// assign port a new aggregator
port->aggregator = free_aggregator;
- port->actor_port_aggregator_identifier=port->aggregator->aggregator_identifier;
+ port->actor_port_aggregator_identifier =
+ port->aggregator->aggregator_identifier;
// update the new aggregator's parameters
// if port was responsed from the end-user
- if (port->actor_oper_port_key & AD_DUPLEX_KEY_BITS) {// if port is full duplex
+ if (port->actor_oper_port_key & AD_DUPLEX_KEY_BITS)
+ /* if port is full duplex */
port->aggregator->is_individual = false;
- } else {
+ else
port->aggregator->is_individual = true;
- }
port->aggregator->actor_admin_aggregator_key = port->actor_admin_port_key;
port->aggregator->actor_oper_aggregator_key = port->actor_oper_port_key;
- port->aggregator->partner_system=port->partner_oper.system;
- port->aggregator->partner_system_priority = port->partner_oper.system_priority;
+ port->aggregator->partner_system =
+ port->partner_oper.system;
+ port->aggregator->partner_system_priority =
+ port->partner_oper.system_priority;
port->aggregator->partner_oper_aggregator_key = port->partner_oper.key;
port->aggregator->receive_state = 1;
port->aggregator->transmit_state = 1;
@@ -1704,9 +1706,8 @@ static void ad_initialize_port(struct port *port, int lacp_fast)
port->actor_admin_port_state = AD_STATE_AGGREGATION | AD_STATE_LACP_ACTIVITY;
port->actor_oper_port_state = AD_STATE_AGGREGATION | AD_STATE_LACP_ACTIVITY;
- if (lacp_fast) {
+ if (lacp_fast)
port->actor_oper_port_state |= AD_STATE_LACP_TIMEOUT;
- }
memcpy(&port->partner_admin, &tmpl, sizeof(tmpl));
memcpy(&port->partner_oper, &tmpl, sizeof(tmpl));
@@ -1785,13 +1786,16 @@ static void ad_marker_info_send(struct port *port)
marker.requester_port = (((port->actor_port_number & 0xFF) << 8) |((u16)(port->actor_port_number & 0xFF00) >> 8));
marker.requester_system = port->actor_system;
// convert requester_port(u32) to Big Endian
- marker.requester_transaction_id = (((++port->transaction_id & 0xFF) << 24) |((port->transaction_id & 0xFF00) << 8) |((port->transaction_id & 0xFF0000) >> 8) |((port->transaction_id & 0xFF000000) >> 24));
+ marker.requester_transaction_id =
+ (((++port->transaction_id & 0xFF) << 24)
+ | ((port->transaction_id & 0xFF00) << 8)
+ | ((port->transaction_id & 0xFF0000) >> 8)
+ | ((port->transaction_id & 0xFF000000) >> 24));
marker.pad = 0;
marker.tlv_type_terminator = 0x00;
marker.terminator_length = 0x00;
- for (index=0; index<90; index++) {
- marker.reserved_90[index]=0;
- }
+ for (index = 0; index < 90; index++)
+ marker.reserved_90[index] = 0;
// send the marker information
if (ad_marker_send(port, &marker) >= 0) {
@@ -1816,7 +1820,7 @@ static void ad_marker_info_received(struct bond_marker *marker_info,
//marker = *marker_info;
memcpy(&marker, marker_info, sizeof(struct bond_marker));
// change the marker subtype to marker response
- marker.tlv_type=AD_MARKER_RESPONSE_SUBTYPE;
+ marker.tlv_type = AD_MARKER_RESPONSE_SUBTYPE;
// send the marker response
if (ad_marker_send(port, &marker) >= 0) {
@@ -1837,8 +1841,8 @@ static void ad_marker_info_received(struct bond_marker *marker_info,
static void ad_marker_response_received(struct bond_marker *marker,
struct port *port)
{
- marker=NULL; // just to satisfy the compiler
- port=NULL; // just to satisfy the compiler
+ marker = NULL; /* just to satisfy the compiler */
+ port = NULL; /* just to satisfy the compiler */
// DO NOTHING, SINCE WE DECIDED NOT TO IMPLEMENT THIS FEATURE FOR NOW
}
@@ -1932,9 +1936,8 @@ int bond_3ad_bind_slave(struct slave *slave)
port->actor_admin_port_key |= (__get_link_speed(port) << 1);
port->actor_oper_port_key = port->actor_admin_port_key;
// if the port is not full duplex, then the port should be not lacp Enabled
- if (!(port->actor_oper_port_key & AD_DUPLEX_KEY_BITS)) {
+ if (!(port->actor_oper_port_key & AD_DUPLEX_KEY_BITS))
port->sm_vars &= ~AD_PORT_LACP_ENABLED;
- }
// actor system is the bond's system
port->actor_system = BOND_AD_INFO(bond).system.sys_mac_addr;
// tx timer(to verify that no more than MAX_TX_IN_SECOND lacpdu's are sent in one second)
@@ -2006,9 +2009,10 @@ void bond_3ad_unbind_slave(struct slave *slave)
new_aggregator = __get_first_agg(port);
for (; new_aggregator; new_aggregator = __get_next_agg(new_aggregator)) {
// if the new aggregator is empty, or it is connected to our port only
- if (!new_aggregator->lag_ports || ((new_aggregator->lag_ports == port) && !new_aggregator->lag_ports->next_port_in_aggregator)) {
+ if (!new_aggregator->lag_ports
+ || ((new_aggregator->lag_ports == port)
+ && !new_aggregator->lag_ports->next_port_in_aggregator))
break;
- }
}
// if new aggregator found, copy the aggregator's parameters
// and connect the related lag_ports to the new aggregator
@@ -2037,17 +2041,17 @@ void bond_3ad_unbind_slave(struct slave *slave)
new_aggregator->num_of_ports = aggregator->num_of_ports;
// update the information that is written on the ports about the aggregator
- for (temp_port=aggregator->lag_ports; temp_port; temp_port=temp_port->next_port_in_aggregator) {
- temp_port->aggregator=new_aggregator;
+ for (temp_port = aggregator->lag_ports; temp_port;
+ temp_port = temp_port->next_port_in_aggregator) {
+ temp_port->aggregator = new_aggregator;
temp_port->actor_port_aggregator_identifier = new_aggregator->aggregator_identifier;
}
// clear the aggregator
ad_clear_agg(aggregator);
- if (select_new_active_agg) {
+ if (select_new_active_agg)
ad_agg_selection_logic(__get_first_agg(port));
- }
} else {
pr_warning("%s: Warning: unbinding aggregator, and could not find a new aggregator for its ports\n",
slave->dev->master->name);
@@ -2071,15 +2075,16 @@ void bond_3ad_unbind_slave(struct slave *slave)
for (; temp_aggregator; temp_aggregator = __get_next_agg(temp_aggregator)) {
prev_port = NULL;
// search the port in the aggregator's related ports
- for (temp_port=temp_aggregator->lag_ports; temp_port; prev_port=temp_port, temp_port=temp_port->next_port_in_aggregator) {
+ for (temp_port = temp_aggregator->lag_ports; temp_port;
+ prev_port = temp_port,
+ temp_port = temp_port->next_port_in_aggregator) {
if (temp_port == port) { // the aggregator found - detach the port from this aggregator
- if (prev_port) {
+ if (prev_port)
prev_port->next_port_in_aggregator = temp_port->next_port_in_aggregator;
- } else {
+ else
temp_aggregator->lag_ports = temp_port->next_port_in_aggregator;
- }
temp_aggregator->num_of_ports--;
- if (temp_aggregator->num_of_ports==0) {
+ if (temp_aggregator->num_of_ports == 0) {
select_new_active_agg = temp_aggregator->is_active;
// clear the aggregator
ad_clear_agg(temp_aggregator);
@@ -2094,7 +2099,7 @@ void bond_3ad_unbind_slave(struct slave *slave)
}
}
}
- port->slave=NULL;
+ port->slave = NULL;
}
/**
@@ -2119,14 +2124,12 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
read_lock(&bond->lock);
- if (bond->kill_timers) {
+ if (bond->kill_timers)
goto out;
- }
//check if there are any slaves
- if (bond->slave_cnt == 0) {
+ if (bond->slave_cnt == 0)
goto re_arm;
- }
// check if agg_select_timer timer after initialize is timed out
if (BOND_AD_INFO(bond).agg_select_timer && !(--BOND_AD_INFO(bond).agg_select_timer)) {
@@ -2159,9 +2162,8 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
ad_tx_machine(port);
// turn off the BEGIN bit, since we already handled it
- if (port->sm_vars & AD_PORT_BEGIN) {
+ if (port->sm_vars & AD_PORT_BEGIN)
port->sm_vars &= ~AD_PORT_BEGIN;
- }
}
re_arm:
@@ -2245,7 +2247,8 @@ void bond_3ad_adapter_speed_changed(struct slave *slave)
}
port->actor_admin_port_key &= ~AD_SPEED_KEY_BITS;
- port->actor_oper_port_key=port->actor_admin_port_key |= (__get_link_speed(port) << 1);
+ port->actor_oper_port_key = port->actor_admin_port_key |=
+ (__get_link_speed(port) << 1);
pr_debug("Port %d changed speed\n", port->actor_port_number);
// there is no need to reselect a new aggregator, just signal the
// state machines to reinitialize
@@ -2262,7 +2265,7 @@ void bond_3ad_adapter_duplex_changed(struct slave *slave)
{
struct port *port;
- port=&(SLAVE_AD_INFO(slave).port);
+ port = &(SLAVE_AD_INFO(slave).port);
// if slave is null, the whole port is not initialized
if (!port->slave) {
@@ -2272,7 +2275,8 @@ void bond_3ad_adapter_duplex_changed(struct slave *slave)
}
port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS;
- port->actor_oper_port_key=port->actor_admin_port_key |= __get_duplex(port);
+ port->actor_oper_port_key = port->actor_admin_port_key |=
+ __get_duplex(port);
pr_debug("Port %d changed duplex\n", port->actor_port_number);
// there is no need to reselect a new aggregator, just signal the
// state machines to reinitialize
@@ -2304,14 +2308,17 @@ void bond_3ad_handle_link_change(struct slave *slave, char link)
if (link == BOND_LINK_UP) {
port->is_enabled = true;
port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS;
- port->actor_oper_port_key=port->actor_admin_port_key |= __get_duplex(port);
+ port->actor_oper_port_key = port->actor_admin_port_key |=
+ __get_duplex(port);
port->actor_admin_port_key &= ~AD_SPEED_KEY_BITS;
- port->actor_oper_port_key=port->actor_admin_port_key |= (__get_link_speed(port) << 1);
+ port->actor_oper_port_key = port->actor_admin_port_key |=
+ (__get_link_speed(port) << 1);
} else {
/* link has failed */
port->is_enabled = false;
port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS;
- port->actor_oper_port_key= (port->actor_admin_port_key &= ~AD_SPEED_KEY_BITS);
+ port->actor_oper_port_key = (port->actor_admin_port_key &=
+ ~AD_SPEED_KEY_BITS);
}
//BOND_PRINT_DBG(("Port %d changed link status to %s", port->actor_port_number, ((link == BOND_LINK_UP)?"UP":"DOWN")));
// there is no need to reselect a new aggregator, just signal the
@@ -2394,9 +2401,8 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
*/
read_lock(&bond->lock);
- if (!BOND_IS_OK(bond)) {
+ if (!BOND_IS_OK(bond))
goto out;
- }
if (bond_3ad_get_active_agg_info(bond, &ad_info)) {
pr_debug("%s: Error: bond_3ad_get_active_agg_info failed\n",
@@ -2420,9 +2426,8 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
if (agg && (agg->aggregator_identifier == agg_id)) {
slave_agg_no--;
- if (slave_agg_no < 0) {
+ if (slave_agg_no < 0)
break;
- }
}
}
@@ -2438,9 +2443,8 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
int slave_agg_id = 0;
struct aggregator *agg = SLAVE_AD_INFO(slave).port.aggregator;
- if (agg) {
+ if (agg)
slave_agg_id = agg->aggregator_identifier;
- }
if (SLAVE_IS_OK(slave) && agg && (slave_agg_id == agg_id)) {
res = bond_dev_queue_xmit(bond, skb, slave->dev);
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 3b16f62d5606..beb3b7cecd52 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -76,6 +76,7 @@
#include <linux/if_vlan.h>
#include <linux/if_bonding.h>
#include <linux/jiffies.h>
+#include <linux/preempt.h>
#include <net/route.h>
#include <net/net_namespace.h>
#include <net/netns/generic.h>
@@ -109,6 +110,7 @@ static char *arp_validate;
static char *fail_over_mac;
static int all_slaves_active = 0;
static struct bond_params bonding_defaults;
+static int resend_igmp = BOND_DEFAULT_RESEND_IGMP;
module_param(max_bonds, int, 0);
MODULE_PARM_DESC(max_bonds, "Max number of bonded devices");
@@ -163,9 +165,15 @@ module_param(all_slaves_active, int, 0);
MODULE_PARM_DESC(all_slaves_active, "Keep all frames received on an interface"
"by setting active flag for all slaves. "
"0 for never (default), 1 for always.");
+module_param(resend_igmp, int, 0);
+MODULE_PARM_DESC(resend_igmp, "Number of IGMP membership reports to send on link failure");
/*----------------------------- Global variables ----------------------------*/
+#ifdef CONFIG_NET_POLL_CONTROLLER
+cpumask_var_t netpoll_block_tx;
+#endif
+
static const char * const version =
DRV_DESCRIPTION ": v" DRV_VERSION " (" DRV_RELDATE ")\n";
@@ -176,9 +184,6 @@ static int arp_ip_count;
static int bond_mode = BOND_MODE_ROUNDROBIN;
static int xmit_hashtype = BOND_XMIT_POLICY_LAYER2;
static int lacp_fast;
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static int disable_netpoll = 1;
-#endif
const struct bond_parm_tbl bond_lacp_tbl[] = {
{ "slow", AD_LACP_SLOW},
@@ -307,6 +312,7 @@ static int bond_del_vlan(struct bonding *bond, unsigned short vlan_id)
pr_debug("bond: %s, vlan id %d\n", bond->dev->name, vlan_id);
+ block_netpoll_tx();
write_lock_bh(&bond->lock);
list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
@@ -341,6 +347,7 @@ static int bond_del_vlan(struct bonding *bond, unsigned short vlan_id)
out:
write_unlock_bh(&bond->lock);
+ unblock_netpoll_tx();
return res;
}
@@ -446,11 +453,9 @@ int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb,
if (unlikely(bond->dev->priv_flags & IFF_IN_NETPOLL)) {
struct netpoll *np = bond->dev->npinfo->netpoll;
slave_dev->npinfo = bond->dev->npinfo;
- np->real_dev = np->dev = skb->dev;
slave_dev->priv_flags |= IFF_IN_NETPOLL;
- netpoll_send_skb(np, skb);
+ netpoll_send_skb_on_dev(np, skb, slave_dev);
slave_dev->priv_flags &= ~IFF_IN_NETPOLL;
- np->dev = bond->dev;
} else
#endif
dev_queue_xmit(skb);
@@ -865,18 +870,13 @@ static void bond_mc_del(struct bonding *bond, void *addr)
}
-/*
- * Retrieve the list of registered multicast addresses for the bonding
- * device and retransmit an IGMP JOIN request to the current active
- * slave.
- */
-static void bond_resend_igmp_join_requests(struct bonding *bond)
+static void __bond_resend_igmp_join_requests(struct net_device *dev)
{
struct in_device *in_dev;
struct ip_mc_list *im;
rcu_read_lock();
- in_dev = __in_dev_get_rcu(bond->dev);
+ in_dev = __in_dev_get_rcu(dev);
if (in_dev) {
for (im = in_dev->mc_list; im; im = im->next)
ip_mc_rejoin_group(im);
@@ -886,6 +886,44 @@ static void bond_resend_igmp_join_requests(struct bonding *bond)
}
/*
+ * Retrieve the list of registered multicast addresses for the bonding
+ * device and retransmit an IGMP JOIN request to the current active
+ * slave.
+ */
+static void bond_resend_igmp_join_requests(struct bonding *bond)
+{
+ struct net_device *vlan_dev;
+ struct vlan_entry *vlan;
+
+ read_lock(&bond->lock);
+
+ /* rejoin all groups on bond device */
+ __bond_resend_igmp_join_requests(bond->dev);
+
+ /* rejoin all groups on vlan devices */
+ if (bond->vlgrp) {
+ list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
+ vlan_dev = vlan_group_get_device(bond->vlgrp,
+ vlan->vlan_id);
+ if (vlan_dev)
+ __bond_resend_igmp_join_requests(vlan_dev);
+ }
+ }
+
+ if (--bond->igmp_retrans > 0)
+ queue_delayed_work(bond->wq, &bond->mcast_work, HZ/5);
+
+ read_unlock(&bond->lock);
+}
+
+static void bond_resend_igmp_join_requests_delayed(struct work_struct *work)
+{
+ struct bonding *bond = container_of(work, struct bonding,
+ mcast_work.work);
+ bond_resend_igmp_join_requests(bond);
+}
+
+/*
* flush all members of flush->mc_list from device dev->mc_list
*/
static void bond_mc_list_flush(struct net_device *bond_dev,
@@ -944,7 +982,6 @@ static void bond_mc_swap(struct bonding *bond, struct slave *new_active,
netdev_for_each_mc_addr(ha, bond->dev)
dev_mc_add(new_active->dev, ha->addr);
- bond_resend_igmp_join_requests(bond);
}
}
@@ -1180,9 +1217,12 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
}
}
- /* resend IGMP joins since all were sent on curr_active_slave */
- if (bond->params.mode == BOND_MODE_ROUNDROBIN) {
- bond_resend_igmp_join_requests(bond);
+ /* resend IGMP joins since active slave has changed or
+ * all were sent on curr_active_slave */
+ if ((USES_PRIMARY(bond->params.mode) && new_active) ||
+ bond->params.mode == BOND_MODE_ROUNDROBIN) {
+ bond->igmp_retrans = bond->params.resend_igmp;
+ queue_delayed_work(bond->wq, &bond->mcast_work, 0);
}
}
@@ -1294,9 +1334,14 @@ static bool slaves_support_netpoll(struct net_device *bond_dev)
static void bond_poll_controller(struct net_device *bond_dev)
{
- struct net_device *dev = bond_dev->npinfo->netpoll->real_dev;
- if (dev != bond_dev)
- netpoll_poll_dev(dev);
+ struct bonding *bond = netdev_priv(bond_dev);
+ struct slave *slave;
+ int i;
+
+ bond_for_each_slave(bond, slave, i) {
+ if (slave->dev && IS_UP(slave->dev))
+ netpoll_poll_dev(slave->dev);
+ }
}
static void bond_netpoll_cleanup(struct net_device *bond_dev)
@@ -1763,23 +1808,15 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
bond_set_carrier(bond);
#ifdef CONFIG_NET_POLL_CONTROLLER
- /*
- * Netpoll and bonding is broken, make sure it is not initialized
- * until it is fixed.
- */
- if (disable_netpoll) {
+ if (slaves_support_netpoll(bond_dev)) {
+ bond_dev->priv_flags &= ~IFF_DISABLE_NETPOLL;
+ if (bond_dev->npinfo)
+ slave_dev->npinfo = bond_dev->npinfo;
+ } else if (!(bond_dev->priv_flags & IFF_DISABLE_NETPOLL)) {
bond_dev->priv_flags |= IFF_DISABLE_NETPOLL;
- } else {
- if (slaves_support_netpoll(bond_dev)) {
- bond_dev->priv_flags &= ~IFF_DISABLE_NETPOLL;
- if (bond_dev->npinfo)
- slave_dev->npinfo = bond_dev->npinfo;
- } else if (!(bond_dev->priv_flags & IFF_DISABLE_NETPOLL)) {
- bond_dev->priv_flags |= IFF_DISABLE_NETPOLL;
- pr_info("New slave device %s does not support netpoll\n",
- slave_dev->name);
- pr_info("Disabling netpoll support for %s\n", bond_dev->name);
- }
+ pr_info("New slave device %s does not support netpoll\n",
+ slave_dev->name);
+ pr_info("Disabling netpoll support for %s\n", bond_dev->name);
}
#endif
read_unlock(&bond->lock);
@@ -1851,6 +1888,7 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
return -EINVAL;
}
+ block_netpoll_tx();
netdev_bonding_change(bond_dev, NETDEV_BONDING_DESLAVE);
write_lock_bh(&bond->lock);
@@ -1860,6 +1898,7 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
pr_info("%s: %s not enslaved\n",
bond_dev->name, slave_dev->name);
write_unlock_bh(&bond->lock);
+ unblock_netpoll_tx();
return -EINVAL;
}
@@ -1953,6 +1992,7 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
}
write_unlock_bh(&bond->lock);
+ unblock_netpoll_tx();
/* must do this from outside any spinlocks */
bond_destroy_slave_symlinks(bond_dev, slave_dev);
@@ -1983,10 +2023,8 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
#ifdef CONFIG_NET_POLL_CONTROLLER
read_lock_bh(&bond->lock);
- /* Make sure netpoll over stays disabled until fixed. */
- if (!disable_netpoll)
- if (slaves_support_netpoll(bond_dev))
- bond_dev->priv_flags &= ~IFF_DISABLE_NETPOLL;
+ if (slaves_support_netpoll(bond_dev))
+ bond_dev->priv_flags &= ~IFF_DISABLE_NETPOLL;
read_unlock_bh(&bond->lock);
if (slave_dev->netdev_ops->ndo_netpoll_cleanup)
slave_dev->netdev_ops->ndo_netpoll_cleanup(slave_dev);
@@ -2019,8 +2057,8 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
* First release a slave and than destroy the bond if no more slaves are left.
* Must be under rtnl_lock when this function is called.
*/
-int bond_release_and_destroy(struct net_device *bond_dev,
- struct net_device *slave_dev)
+static int bond_release_and_destroy(struct net_device *bond_dev,
+ struct net_device *slave_dev)
{
struct bonding *bond = netdev_priv(bond_dev);
int ret;
@@ -2142,7 +2180,6 @@ static int bond_release_all(struct net_device *bond_dev)
out:
write_unlock_bh(&bond->lock);
-
return 0;
}
@@ -2191,9 +2228,11 @@ static int bond_ioctl_change_active(struct net_device *bond_dev, struct net_devi
(old_active) &&
(new_active->link == BOND_LINK_UP) &&
IS_UP(new_active->dev)) {
+ block_netpoll_tx();
write_lock_bh(&bond->curr_slave_lock);
bond_change_active_slave(bond, new_active);
write_unlock_bh(&bond->curr_slave_lock);
+ unblock_netpoll_tx();
} else
res = -EINVAL;
@@ -2368,8 +2407,11 @@ static void bond_miimon_commit(struct bonding *bond)
slave->state = BOND_STATE_BACKUP;
}
- pr_info("%s: link status definitely up for interface %s.\n",
- bond->dev->name, slave->dev->name);
+ bond_update_speed_duplex(slave);
+
+ pr_info("%s: link status definitely up for interface %s, %d Mbps %s duplex.\n",
+ bond->dev->name, slave->dev->name,
+ slave->speed, slave->duplex ? "full" : "half");
/* notify ad that the link status has changed */
if (bond->params.mode == BOND_MODE_8023AD)
@@ -2422,9 +2464,11 @@ static void bond_miimon_commit(struct bonding *bond)
do_failover:
ASSERT_RTNL();
+ block_netpoll_tx();
write_lock_bh(&bond->curr_slave_lock);
bond_select_active_slave(bond);
write_unlock_bh(&bond->curr_slave_lock);
+ unblock_netpoll_tx();
}
bond_set_carrier(bond);
@@ -2867,11 +2911,13 @@ void bond_loadbalance_arp_mon(struct work_struct *work)
}
if (do_failover) {
+ block_netpoll_tx();
write_lock_bh(&bond->curr_slave_lock);
bond_select_active_slave(bond);
write_unlock_bh(&bond->curr_slave_lock);
+ unblock_netpoll_tx();
}
re_arm:
@@ -3030,9 +3076,11 @@ static void bond_ab_arp_commit(struct bonding *bond, int delta_in_ticks)
do_failover:
ASSERT_RTNL();
+ block_netpoll_tx();
write_lock_bh(&bond->curr_slave_lock);
bond_select_active_slave(bond);
write_unlock_bh(&bond->curr_slave_lock);
+ unblock_netpoll_tx();
}
bond_set_carrier(bond);
@@ -3312,6 +3360,8 @@ static void bond_info_show_slave(struct seq_file *seq,
seq_printf(seq, "\nSlave Interface: %s\n", slave->dev->name);
seq_printf(seq, "MII Status: %s\n",
(slave->link == BOND_LINK_UP) ? "up" : "down");
+ seq_printf(seq, "Speed: %d Mbps\n", slave->speed);
+ seq_printf(seq, "Duplex: %s\n", slave->duplex ? "full" : "half");
seq_printf(seq, "Link Failure Count: %u\n",
slave->link_failure_count);
@@ -3744,6 +3794,8 @@ static int bond_open(struct net_device *bond_dev)
bond->kill_timers = 0;
+ INIT_DELAYED_WORK(&bond->mcast_work, bond_resend_igmp_join_requests_delayed);
+
if (bond_is_lb(bond)) {
/* bond_alb_initialize must be called before the timer
* is started.
@@ -3828,6 +3880,8 @@ static int bond_close(struct net_device *bond_dev)
break;
}
+ if (delayed_work_pending(&bond->mcast_work))
+ cancel_delayed_work(&bond->mcast_work);
if (bond_is_lb(bond)) {
/* Must be called only after all
@@ -4514,6 +4568,13 @@ static netdev_tx_t bond_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct bonding *bond = netdev_priv(dev);
+ /*
+ * If we risk deadlock from transmitting this in the
+ * netpoll path, tell netpoll to queue the frame for later tx
+ */
+ if (is_netpoll_tx_blocked(dev))
+ return NETDEV_TX_BUSY;
+
if (TX_QUEUE_OVERRIDE(bond->params.mode)) {
if (!bond_slave_override(bond, skb))
return NETDEV_TX_OK;
@@ -4678,6 +4739,10 @@ static void bond_setup(struct net_device *bond_dev)
NETIF_F_HW_VLAN_RX |
NETIF_F_HW_VLAN_FILTER);
+ /* By default, we enable GRO on bonding devices.
+ * Actual support requires lowlevel drivers are GRO ready.
+ */
+ bond_dev->features |= NETIF_F_GRO;
}
static void bond_work_cancel_all(struct bonding *bond)
@@ -4699,6 +4764,9 @@ static void bond_work_cancel_all(struct bonding *bond)
if (bond->params.mode == BOND_MODE_8023AD &&
delayed_work_pending(&bond->ad_work))
cancel_delayed_work(&bond->ad_work);
+
+ if (delayed_work_pending(&bond->mcast_work))
+ cancel_delayed_work(&bond->mcast_work);
}
/*
@@ -4891,6 +4959,13 @@ static int bond_check_params(struct bond_params *params)
all_slaves_active = 0;
}
+ if (resend_igmp < 0 || resend_igmp > 255) {
+ pr_warning("Warning: resend_igmp (%d) should be between "
+ "0 and 255, resetting to %d\n",
+ resend_igmp, BOND_DEFAULT_RESEND_IGMP);
+ resend_igmp = BOND_DEFAULT_RESEND_IGMP;
+ }
+
/* reset values for TLB/ALB */
if ((bond_mode == BOND_MODE_TLB) ||
(bond_mode == BOND_MODE_ALB)) {
@@ -5063,6 +5138,7 @@ static int bond_check_params(struct bond_params *params)
params->fail_over_mac = fail_over_mac_value;
params->tx_queues = tx_queues;
params->all_slaves_active = all_slaves_active;
+ params->resend_igmp = resend_igmp;
if (primary) {
strncpy(params->primary, primary, IFNAMSIZ);
@@ -5164,6 +5240,15 @@ int bond_create(struct net *net, const char *name)
res = dev_alloc_name(bond_dev, "bond%d");
if (res < 0)
goto out;
+ } else {
+ /*
+ * If we're given a name to register
+ * we need to ensure that its not already
+ * registered
+ */
+ res = -EEXIST;
+ if (__dev_get_by_name(net, name) != NULL)
+ goto out;
}
res = register_netdevice(bond_dev);
@@ -5212,6 +5297,13 @@ static int __init bonding_init(void)
if (res)
goto out;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ if (!alloc_cpumask_var(&netpoll_block_tx, GFP_KERNEL)) {
+ res = -ENOMEM;
+ goto out;
+ }
+#endif
+
res = register_pernet_subsys(&bond_net_ops);
if (res)
goto out;
@@ -5230,6 +5322,7 @@ static int __init bonding_init(void)
if (res)
goto err;
+
register_netdevice_notifier(&bond_netdev_notifier);
register_inetaddr_notifier(&bond_inetaddr_notifier);
bond_register_ipv6_notifier();
@@ -5239,6 +5332,9 @@ err:
rtnl_link_unregister(&bond_link_ops);
err_link:
unregister_pernet_subsys(&bond_net_ops);
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ free_cpumask_var(netpoll_block_tx);
+#endif
goto out;
}
@@ -5253,6 +5349,10 @@ static void __exit bonding_exit(void)
rtnl_link_unregister(&bond_link_ops);
unregister_pernet_subsys(&bond_net_ops);
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ free_cpumask_var(netpoll_block_tx);
+#endif
}
module_init(bonding_init);
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index c311aed9bd02..8fd0174c5380 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -1066,6 +1066,7 @@ static ssize_t bonding_store_primary(struct device *d,
if (!rtnl_trylock())
return restart_syscall();
+ block_netpoll_tx();
read_lock(&bond->lock);
write_lock_bh(&bond->curr_slave_lock);
@@ -1101,6 +1102,7 @@ static ssize_t bonding_store_primary(struct device *d,
out:
write_unlock_bh(&bond->curr_slave_lock);
read_unlock(&bond->lock);
+ unblock_netpoll_tx();
rtnl_unlock();
return count;
@@ -1146,11 +1148,13 @@ static ssize_t bonding_store_primary_reselect(struct device *d,
bond->dev->name, pri_reselect_tbl[new_value].modename,
new_value);
+ block_netpoll_tx();
read_lock(&bond->lock);
write_lock_bh(&bond->curr_slave_lock);
bond_select_active_slave(bond);
write_unlock_bh(&bond->curr_slave_lock);
read_unlock(&bond->lock);
+ unblock_netpoll_tx();
out:
rtnl_unlock();
return ret;
@@ -1232,6 +1236,8 @@ static ssize_t bonding_store_active_slave(struct device *d,
if (!rtnl_trylock())
return restart_syscall();
+
+ block_netpoll_tx();
read_lock(&bond->lock);
write_lock_bh(&bond->curr_slave_lock);
@@ -1288,6 +1294,8 @@ static ssize_t bonding_store_active_slave(struct device *d,
out:
write_unlock_bh(&bond->curr_slave_lock);
read_unlock(&bond->lock);
+ unblock_netpoll_tx();
+
rtnl_unlock();
return count;
@@ -1592,6 +1600,49 @@ out:
static DEVICE_ATTR(all_slaves_active, S_IRUGO | S_IWUSR,
bonding_show_slaves_active, bonding_store_slaves_active);
+/*
+ * Show and set the number of IGMP membership reports to send on link failure
+ */
+static ssize_t bonding_show_resend_igmp(struct device *d,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct bonding *bond = to_bond(d);
+
+ return sprintf(buf, "%d\n", bond->params.resend_igmp);
+}
+
+static ssize_t bonding_store_resend_igmp(struct device *d,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int new_value, ret = count;
+ struct bonding *bond = to_bond(d);
+
+ if (sscanf(buf, "%d", &new_value) != 1) {
+ pr_err("%s: no resend_igmp value specified.\n",
+ bond->dev->name);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (new_value < 0) {
+ pr_err("%s: Invalid resend_igmp value %d not in range 0-255; rejected.\n",
+ bond->dev->name, new_value);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ pr_info("%s: Setting resend_igmp to %d.\n",
+ bond->dev->name, new_value);
+ bond->params.resend_igmp = new_value;
+out:
+ return ret;
+}
+
+static DEVICE_ATTR(resend_igmp, S_IRUGO | S_IWUSR,
+ bonding_show_resend_igmp, bonding_store_resend_igmp);
+
static struct attribute *per_bond_attrs[] = {
&dev_attr_slaves.attr,
&dev_attr_mode.attr,
@@ -1619,6 +1670,7 @@ static struct attribute *per_bond_attrs[] = {
&dev_attr_ad_partner_mac.attr,
&dev_attr_queue_id.attr,
&dev_attr_all_slaves_active.attr,
+ &dev_attr_resend_igmp.attr,
NULL,
};
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index c6fdd851579a..4eedb12df6ca 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -19,6 +19,7 @@
#include <linux/proc_fs.h>
#include <linux/if_bonding.h>
#include <linux/kobject.h>
+#include <linux/cpumask.h>
#include <linux/in6.h>
#include "bond_3ad.h"
#include "bond_alb.h"
@@ -117,6 +118,35 @@
bond_for_each_slave_from(bond, pos, cnt, (bond)->first_slave)
+#ifdef CONFIG_NET_POLL_CONTROLLER
+extern cpumask_var_t netpoll_block_tx;
+
+static inline void block_netpoll_tx(void)
+{
+ preempt_disable();
+ BUG_ON(cpumask_test_and_set_cpu(smp_processor_id(),
+ netpoll_block_tx));
+}
+
+static inline void unblock_netpoll_tx(void)
+{
+ BUG_ON(!cpumask_test_and_clear_cpu(smp_processor_id(),
+ netpoll_block_tx));
+ preempt_enable();
+}
+
+static inline int is_netpoll_tx_blocked(struct net_device *dev)
+{
+ if (unlikely(dev->priv_flags & IFF_IN_NETPOLL))
+ return cpumask_test_cpu(smp_processor_id(), netpoll_block_tx);
+ return 0;
+}
+#else
+#define block_netpoll_tx()
+#define unblock_netpoll_tx()
+#define is_netpoll_tx_blocked(dev) (0)
+#endif
+
struct bond_params {
int mode;
int xmit_policy;
@@ -136,6 +166,7 @@ struct bond_params {
__be32 arp_targets[BOND_MAX_ARP_TARGETS];
int tx_queues;
int all_slaves_active;
+ int resend_igmp;
};
struct bond_parm_tbl {
@@ -202,6 +233,7 @@ struct bonding {
s8 send_grat_arp;
s8 send_unsol_na;
s8 setup_by_slave;
+ s8 igmp_retrans;
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc_entry;
char proc_file_name[IFNAMSIZ];
@@ -223,6 +255,7 @@ struct bonding {
struct delayed_work arp_work;
struct delayed_work alb_work;
struct delayed_work ad_work;
+ struct delayed_work mcast_work;
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
struct in6_addr master_ipv6;
#endif
@@ -331,7 +364,6 @@ static inline void bond_unset_master_alb_flags(struct bonding *bond)
struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr);
int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev);
int bond_create(struct net *net, const char *name);
-int bond_release_and_destroy(struct net_device *bond_dev, struct net_device *slave_dev);
int bond_create_sysfs(void);
void bond_destroy_sysfs(void);
void bond_prepare_sysfs_group(struct bonding *bond);
diff --git a/drivers/net/bsd_comp.c b/drivers/net/bsd_comp.c
index 88edb986691a..6e99d80ec409 100644
--- a/drivers/net/bsd_comp.c
+++ b/drivers/net/bsd_comp.c
@@ -429,7 +429,7 @@ static void *bsd_alloc (unsigned char *options, int opt_len, int decomp)
if (!db->lens)
{
bsd_free (db);
- return (NULL);
+ return NULL;
}
}
/*
diff --git a/drivers/net/caif/caif_spi.c b/drivers/net/caif/caif_spi.c
index f5058ff2b210..8427533fe313 100644
--- a/drivers/net/caif/caif_spi.c
+++ b/drivers/net/caif/caif_spi.c
@@ -240,13 +240,15 @@ static ssize_t dbgfs_frame(struct file *file, char __user *user_buf,
static const struct file_operations dbgfs_state_fops = {
.open = dbgfs_open,
.read = dbgfs_state,
- .owner = THIS_MODULE
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
};
static const struct file_operations dbgfs_frame_fops = {
.open = dbgfs_open,
.read = dbgfs_frame,
- .owner = THIS_MODULE
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
};
static inline void dev_debugfs_add(struct cfspi *cfspi)
diff --git a/drivers/net/can/mcp251x.c b/drivers/net/can/mcp251x.c
index b11a0cb5ed81..6aadc3e32bd5 100644
--- a/drivers/net/can/mcp251x.c
+++ b/drivers/net/can/mcp251x.c
@@ -38,14 +38,14 @@
* static struct mcp251x_platform_data mcp251x_info = {
* .oscillator_frequency = 8000000,
* .board_specific_setup = &mcp251x_setup,
- * .model = CAN_MCP251X_MCP2510,
* .power_enable = mcp251x_power_enable,
* .transceiver_enable = NULL,
* };
*
* static struct spi_board_info spi_board_info[] = {
* {
- * .modalias = "mcp251x",
+ * .modalias = "mcp2510",
+ * // or "mcp2515" depending on your controller
* .platform_data = &mcp251x_info,
* .irq = IRQ_EINT13,
* .max_speed_hz = 2*1000*1000,
@@ -125,6 +125,9 @@
# define CANINTF_TX0IF 0x04
# define CANINTF_RX1IF 0x02
# define CANINTF_RX0IF 0x01
+# define CANINTF_RX (CANINTF_RX0IF | CANINTF_RX1IF)
+# define CANINTF_TX (CANINTF_TX2IF | CANINTF_TX1IF | CANINTF_TX0IF)
+# define CANINTF_ERR (CANINTF_ERRIF)
#define EFLG 0x2d
# define EFLG_EWARN 0x01
# define EFLG_RXWAR 0x02
@@ -222,10 +225,16 @@ static struct can_bittiming_const mcp251x_bittiming_const = {
.brp_inc = 1,
};
+enum mcp251x_model {
+ CAN_MCP251X_MCP2510 = 0x2510,
+ CAN_MCP251X_MCP2515 = 0x2515,
+};
+
struct mcp251x_priv {
struct can_priv can;
struct net_device *net;
struct spi_device *spi;
+ enum mcp251x_model model;
struct mutex mcp_lock; /* SPI device lock */
@@ -250,6 +259,16 @@ struct mcp251x_priv {
int restart_tx;
};
+#define MCP251X_IS(_model) \
+static inline int mcp251x_is_##_model(struct spi_device *spi) \
+{ \
+ struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); \
+ return priv->model == CAN_MCP251X_MCP##_model; \
+}
+
+MCP251X_IS(2510);
+MCP251X_IS(2515);
+
static void mcp251x_clean(struct net_device *net)
{
struct mcp251x_priv *priv = netdev_priv(net);
@@ -319,6 +338,20 @@ static u8 mcp251x_read_reg(struct spi_device *spi, uint8_t reg)
return val;
}
+static void mcp251x_read_2regs(struct spi_device *spi, uint8_t reg,
+ uint8_t *v1, uint8_t *v2)
+{
+ struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
+
+ priv->spi_tx_buf[0] = INSTRUCTION_READ;
+ priv->spi_tx_buf[1] = reg;
+
+ mcp251x_spi_trans(spi, 4);
+
+ *v1 = priv->spi_rx_buf[2];
+ *v2 = priv->spi_rx_buf[3];
+}
+
static void mcp251x_write_reg(struct spi_device *spi, u8 reg, uint8_t val)
{
struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
@@ -346,10 +379,9 @@ static void mcp251x_write_bits(struct spi_device *spi, u8 reg,
static void mcp251x_hw_tx_frame(struct spi_device *spi, u8 *buf,
int len, int tx_buf_idx)
{
- struct mcp251x_platform_data *pdata = spi->dev.platform_data;
struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
- if (pdata->model == CAN_MCP251X_MCP2510) {
+ if (mcp251x_is_2510(spi)) {
int i;
for (i = 1; i < TXBDAT_OFF + len; i++)
@@ -392,9 +424,8 @@ static void mcp251x_hw_rx_frame(struct spi_device *spi, u8 *buf,
int buf_idx)
{
struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
- struct mcp251x_platform_data *pdata = spi->dev.platform_data;
- if (pdata->model == CAN_MCP251X_MCP2510) {
+ if (mcp251x_is_2510(spi)) {
int i, len;
for (i = 1; i < RXBDAT_OFF; i++)
@@ -451,7 +482,7 @@ static void mcp251x_hw_rx(struct spi_device *spi, int buf_idx)
priv->net->stats.rx_packets++;
priv->net->stats.rx_bytes += frame->can_dlc;
- netif_rx(skb);
+ netif_rx_ni(skb);
}
static void mcp251x_hw_sleep(struct spi_device *spi)
@@ -674,9 +705,9 @@ static void mcp251x_error_skb(struct net_device *net, int can_id, int data1)
skb = alloc_can_err_skb(net, &frame);
if (skb) {
- frame->can_id = can_id;
+ frame->can_id |= can_id;
frame->data[1] = data1;
- netif_rx(skb);
+ netif_rx_ni(skb);
} else {
dev_err(&net->dev,
"cannot allocate error skb\n");
@@ -754,24 +785,42 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id)
mutex_lock(&priv->mcp_lock);
while (!priv->force_quit) {
enum can_state new_state;
- u8 intf = mcp251x_read_reg(spi, CANINTF);
- u8 eflag;
+ u8 intf, eflag;
+ u8 clear_intf = 0;
int can_id = 0, data1 = 0;
+ mcp251x_read_2regs(spi, CANINTF, &intf, &eflag);
+
+ /* mask out flags we don't care about */
+ intf &= CANINTF_RX | CANINTF_TX | CANINTF_ERR;
+
+ /* receive buffer 0 */
if (intf & CANINTF_RX0IF) {
mcp251x_hw_rx(spi, 0);
- /* Free one buffer ASAP */
- mcp251x_write_bits(spi, CANINTF, intf & CANINTF_RX0IF,
- 0x00);
+ /*
+ * Free one buffer ASAP
+ * (The MCP2515 does this automatically.)
+ */
+ if (mcp251x_is_2510(spi))
+ mcp251x_write_bits(spi, CANINTF, CANINTF_RX0IF, 0x00);
}
- if (intf & CANINTF_RX1IF)
+ /* receive buffer 1 */
+ if (intf & CANINTF_RX1IF) {
mcp251x_hw_rx(spi, 1);
+ /* the MCP2515 does this automatically */
+ if (mcp251x_is_2510(spi))
+ clear_intf |= CANINTF_RX1IF;
+ }
- mcp251x_write_bits(spi, CANINTF, intf, 0x00);
+ /* any error or tx interrupt we need to clear? */
+ if (intf & (CANINTF_ERR | CANINTF_TX))
+ clear_intf |= intf & (CANINTF_ERR | CANINTF_TX);
+ if (clear_intf)
+ mcp251x_write_bits(spi, CANINTF, clear_intf, 0x00);
- eflag = mcp251x_read_reg(spi, EFLG);
- mcp251x_write_reg(spi, EFLG, 0x00);
+ if (eflag)
+ mcp251x_write_bits(spi, EFLG, eflag, 0x00);
/* Update can state */
if (eflag & EFLG_TXBO) {
@@ -816,10 +865,14 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id)
if (intf & CANINTF_ERRIF) {
/* Handle overflow counters */
if (eflag & (EFLG_RX0OVR | EFLG_RX1OVR)) {
- if (eflag & EFLG_RX0OVR)
+ if (eflag & EFLG_RX0OVR) {
net->stats.rx_over_errors++;
- if (eflag & EFLG_RX1OVR)
+ net->stats.rx_errors++;
+ }
+ if (eflag & EFLG_RX1OVR) {
net->stats.rx_over_errors++;
+ net->stats.rx_errors++;
+ }
can_id |= CAN_ERR_CRTL;
data1 |= CAN_ERR_CRTL_RX_OVERFLOW;
}
@@ -838,7 +891,7 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id)
if (intf == 0)
break;
- if (intf & (CANINTF_TX2IF | CANINTF_TX1IF | CANINTF_TX0IF)) {
+ if (intf & CANINTF_TX) {
net->stats.tx_packets++;
net->stats.tx_bytes += priv->tx_len - 1;
if (priv->tx_len) {
@@ -921,16 +974,12 @@ static int __devinit mcp251x_can_probe(struct spi_device *spi)
struct net_device *net;
struct mcp251x_priv *priv;
struct mcp251x_platform_data *pdata = spi->dev.platform_data;
- int model = spi_get_device_id(spi)->driver_data;
int ret = -ENODEV;
if (!pdata)
/* Platform data is required for osc freq */
goto error_out;
- if (model)
- pdata->model = model;
-
/* Allocate can/net device */
net = alloc_candev(sizeof(struct mcp251x_priv), TX_ECHO_SKB_MAX);
if (!net) {
@@ -947,6 +996,7 @@ static int __devinit mcp251x_can_probe(struct spi_device *spi)
priv->can.clock.freq = pdata->oscillator_frequency / 2;
priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES |
CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY;
+ priv->model = spi_get_device_id(spi)->driver_data;
priv->net = net;
dev_set_drvdata(&spi->dev, priv);
@@ -1120,8 +1170,7 @@ static int mcp251x_can_resume(struct spi_device *spi)
#define mcp251x_can_resume NULL
#endif
-static struct spi_device_id mcp251x_id_table[] = {
- { "mcp251x", 0 /* Use pdata.model */ },
+static const struct spi_device_id mcp251x_id_table[] = {
{ "mcp2510", CAN_MCP251X_MCP2510 },
{ "mcp2515", CAN_MCP251X_MCP2515 },
{ },
diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index b1bdc909090f..312b9c8f4f3b 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -143,12 +143,12 @@ static u32 __devinit mpc512x_can_get_clock(struct platform_device *ofdev,
np_clock = of_find_matching_node(NULL, mpc512x_clock_ids);
if (!np_clock) {
dev_err(&ofdev->dev, "couldn't find clock node\n");
- return -ENODEV;
+ return 0;
}
clockctl = of_iomap(np_clock, 0);
if (!clockctl) {
dev_err(&ofdev->dev, "couldn't map clock registers\n");
- return 0;
+ goto exit_put;
}
/* Determine the MSCAN device index from the physical address */
@@ -233,9 +233,9 @@ static u32 __devinit mpc512x_can_get_clock(struct platform_device *ofdev,
clocksrc == 1 ? "ref_clk" : "sys_clk", clockdiv);
exit_unmap:
- of_node_put(np_clock);
iounmap(clockctl);
-
+exit_put:
+ of_node_put(np_clock);
return freq;
}
#else /* !CONFIG_PPC_MPC512x */
diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c
index 28c88eeec757..d6b6d6aa565a 100644
--- a/drivers/net/cassini.c
+++ b/drivers/net/cassini.c
@@ -419,7 +419,7 @@ static u16 cas_phy_read(struct cas *cp, int reg)
udelay(10);
cmd = readl(cp->regs + REG_MIF_FRAME);
if (cmd & MIF_FRAME_TURN_AROUND_LSB)
- return (cmd & MIF_FRAME_DATA_MASK);
+ return cmd & MIF_FRAME_DATA_MASK;
}
return 0xFFFF; /* -1 */
}
@@ -804,7 +804,7 @@ static int cas_reset_mii_phy(struct cas *cp)
break;
udelay(10);
}
- return (limit <= 0);
+ return limit <= 0;
}
static int cas_saturn_firmware_init(struct cas *cp)
@@ -2149,7 +2149,7 @@ end_copy_pkt:
skb->csum = csum_unfold(~csum);
skb->ip_summed = CHECKSUM_COMPLETE;
} else
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
return len;
}
diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c
index f01cfdb995de..70221ca32683 100644
--- a/drivers/net/chelsio/sge.c
+++ b/drivers/net/chelsio/sge.c
@@ -1388,7 +1388,7 @@ static void sge_rx(struct sge *sge, struct freelQ *fl, unsigned int len)
++st->rx_cso_good;
skb->ip_summed = CHECKSUM_UNNECESSARY;
} else
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
if (unlikely(adapter->vlan_grp && p->vlan_valid)) {
st->vlan_xtract++;
@@ -1551,7 +1551,7 @@ static inline int responses_pending(const struct adapter *adapter)
const struct respQ *Q = &adapter->sge->respQ;
const struct respQ_e *e = &Q->entries[Q->cidx];
- return (e->GenerationBit == Q->genbit);
+ return e->GenerationBit == Q->genbit;
}
/*
@@ -1870,7 +1870,7 @@ netdev_tx_t t1_start_xmit(struct sk_buff *skb, struct net_device *dev)
cpl->iff = dev->if_port;
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
- if (adapter->vlan_grp && vlan_tx_tag_present(skb)) {
+ if (vlan_tx_tag_present(skb)) {
cpl->vlan_valid = 1;
cpl->vlan = htons(vlan_tx_tag_get(skb));
st->vlan_insert++;
diff --git a/drivers/net/chelsio/subr.c b/drivers/net/chelsio/subr.c
index 599d178df62d..63ebf76d2390 100644
--- a/drivers/net/chelsio/subr.c
+++ b/drivers/net/chelsio/subr.c
@@ -314,14 +314,12 @@ static int mi1_mdio_write(struct net_device *dev, int phy_addr, int mmd_addr,
return 0;
}
-#if defined(CONFIG_CHELSIO_T1_1G)
static const struct mdio_ops mi1_mdio_ops = {
.init = mi1_mdio_init,
.read = mi1_mdio_read,
.write = mi1_mdio_write,
.mode_support = MDIO_SUPPORTS_C22
};
-#endif
#endif
diff --git a/drivers/net/chelsio/vsc7326.c b/drivers/net/chelsio/vsc7326.c
index c844111cffeb..106a590f0d9a 100644
--- a/drivers/net/chelsio/vsc7326.c
+++ b/drivers/net/chelsio/vsc7326.c
@@ -255,7 +255,7 @@ static int bist_rd(adapter_t *adapter, int moduleid, int address)
else if ((result & (1 << 8)) != 0x0)
pr_err("bist read error: 0x%x\n", result);
- return (result & 0xff);
+ return result & 0xff;
}
static int bist_wr(adapter_t *adapter, int moduleid, int address, int value)
diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c
index 09610323a948..92bac19ad60a 100644
--- a/drivers/net/cnic.c
+++ b/drivers/net/cnic.c
@@ -60,6 +60,7 @@ MODULE_LICENSE("GPL");
MODULE_VERSION(CNIC_MODULE_VERSION);
static LIST_HEAD(cnic_dev_list);
+static LIST_HEAD(cnic_udev_list);
static DEFINE_RWLOCK(cnic_dev_lock);
static DEFINE_MUTEX(cnic_lock);
@@ -81,29 +82,34 @@ static struct cnic_ops cnic_bnx2x_ops = {
.cnic_ctl = cnic_ctl,
};
+static struct workqueue_struct *cnic_wq;
+
static void cnic_shutdown_rings(struct cnic_dev *);
static void cnic_init_rings(struct cnic_dev *);
static int cnic_cm_set_pg(struct cnic_sock *);
static int cnic_uio_open(struct uio_info *uinfo, struct inode *inode)
{
- struct cnic_dev *dev = uinfo->priv;
- struct cnic_local *cp = dev->cnic_priv;
+ struct cnic_uio_dev *udev = uinfo->priv;
+ struct cnic_dev *dev;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
- if (cp->uio_dev != -1)
+ if (udev->uio_dev != -1)
return -EBUSY;
rtnl_lock();
- if (!test_bit(CNIC_F_CNIC_UP, &dev->flags)) {
+ dev = udev->dev;
+
+ if (!dev || !test_bit(CNIC_F_CNIC_UP, &dev->flags)) {
rtnl_unlock();
return -ENODEV;
}
- cp->uio_dev = iminor(inode);
+ udev->uio_dev = iminor(inode);
+ cnic_shutdown_rings(dev);
cnic_init_rings(dev);
rtnl_unlock();
@@ -112,12 +118,9 @@ static int cnic_uio_open(struct uio_info *uinfo, struct inode *inode)
static int cnic_uio_close(struct uio_info *uinfo, struct inode *inode)
{
- struct cnic_dev *dev = uinfo->priv;
- struct cnic_local *cp = dev->cnic_priv;
-
- cnic_shutdown_rings(dev);
+ struct cnic_uio_dev *udev = uinfo->priv;
- cp->uio_dev = -1;
+ udev->uio_dev = -1;
return 0;
}
@@ -242,14 +245,14 @@ static int cnic_in_use(struct cnic_sock *csk)
return test_bit(SK_F_INUSE, &csk->flags);
}
-static void cnic_kwq_completion(struct cnic_dev *dev, u32 count)
+static void cnic_spq_completion(struct cnic_dev *dev, int cmd, u32 count)
{
struct cnic_local *cp = dev->cnic_priv;
struct cnic_eth_dev *ethdev = cp->ethdev;
struct drv_ctl_info info;
- info.cmd = DRV_CTL_COMPLETION_CMD;
- info.data.comp.comp_count = count;
+ info.cmd = cmd;
+ info.data.credit.credit_count = count;
ethdev->drv_ctl(dev->netdev, &info);
}
@@ -274,8 +277,9 @@ static int cnic_send_nlmsg(struct cnic_local *cp, u32 type,
u16 len = 0;
u32 msg_type = ISCSI_KEVENT_IF_DOWN;
struct cnic_ulp_ops *ulp_ops;
+ struct cnic_uio_dev *udev = cp->udev;
- if (cp->uio_dev == -1)
+ if (!udev || udev->uio_dev == -1)
return -ENODEV;
if (csk) {
@@ -406,8 +410,7 @@ static void cnic_uio_stop(void)
list_for_each_entry(dev, &cnic_dev_list, list) {
struct cnic_local *cp = dev->cnic_priv;
- if (cp->cnic_uinfo)
- cnic_send_nlmsg(cp, ISCSI_KEVENT_IF_DOWN, NULL);
+ cnic_send_nlmsg(cp, ISCSI_KEVENT_IF_DOWN, NULL);
}
read_unlock(&cnic_dev_lock);
}
@@ -768,31 +771,45 @@ static void cnic_free_context(struct cnic_dev *dev)
}
}
-static void cnic_free_resc(struct cnic_dev *dev)
+static void __cnic_free_uio(struct cnic_uio_dev *udev)
{
- struct cnic_local *cp = dev->cnic_priv;
- int i = 0;
+ uio_unregister_device(&udev->cnic_uinfo);
- if (cp->cnic_uinfo) {
- while (cp->uio_dev != -1 && i < 15) {
- msleep(100);
- i++;
- }
- uio_unregister_device(cp->cnic_uinfo);
- kfree(cp->cnic_uinfo);
- cp->cnic_uinfo = NULL;
+ if (udev->l2_buf) {
+ dma_free_coherent(&udev->pdev->dev, udev->l2_buf_size,
+ udev->l2_buf, udev->l2_buf_map);
+ udev->l2_buf = NULL;
}
- if (cp->l2_buf) {
- dma_free_coherent(&dev->pcidev->dev, cp->l2_buf_size,
- cp->l2_buf, cp->l2_buf_map);
- cp->l2_buf = NULL;
+ if (udev->l2_ring) {
+ dma_free_coherent(&udev->pdev->dev, udev->l2_ring_size,
+ udev->l2_ring, udev->l2_ring_map);
+ udev->l2_ring = NULL;
}
- if (cp->l2_ring) {
- dma_free_coherent(&dev->pcidev->dev, cp->l2_ring_size,
- cp->l2_ring, cp->l2_ring_map);
- cp->l2_ring = NULL;
+ pci_dev_put(udev->pdev);
+ kfree(udev);
+}
+
+static void cnic_free_uio(struct cnic_uio_dev *udev)
+{
+ if (!udev)
+ return;
+
+ write_lock(&cnic_dev_lock);
+ list_del_init(&udev->list);
+ write_unlock(&cnic_dev_lock);
+ __cnic_free_uio(udev);
+}
+
+static void cnic_free_resc(struct cnic_dev *dev)
+{
+ struct cnic_local *cp = dev->cnic_priv;
+ struct cnic_uio_dev *udev = cp->udev;
+
+ if (udev) {
+ udev->dev = NULL;
+ cp->udev = NULL;
}
cnic_free_context(dev);
@@ -894,37 +911,68 @@ static int cnic_alloc_kcq(struct cnic_dev *dev, struct kcq_info *info)
return 0;
}
-static int cnic_alloc_l2_rings(struct cnic_dev *dev, int pages)
+static int cnic_alloc_uio_rings(struct cnic_dev *dev, int pages)
{
struct cnic_local *cp = dev->cnic_priv;
+ struct cnic_uio_dev *udev;
+
+ read_lock(&cnic_dev_lock);
+ list_for_each_entry(udev, &cnic_udev_list, list) {
+ if (udev->pdev == dev->pcidev) {
+ udev->dev = dev;
+ cp->udev = udev;
+ read_unlock(&cnic_dev_lock);
+ return 0;
+ }
+ }
+ read_unlock(&cnic_dev_lock);
+
+ udev = kzalloc(sizeof(struct cnic_uio_dev), GFP_ATOMIC);
+ if (!udev)
+ return -ENOMEM;
- cp->l2_ring_size = pages * BCM_PAGE_SIZE;
- cp->l2_ring = dma_alloc_coherent(&dev->pcidev->dev, cp->l2_ring_size,
- &cp->l2_ring_map,
- GFP_KERNEL | __GFP_COMP);
- if (!cp->l2_ring)
+ udev->uio_dev = -1;
+
+ udev->dev = dev;
+ udev->pdev = dev->pcidev;
+ udev->l2_ring_size = pages * BCM_PAGE_SIZE;
+ udev->l2_ring = dma_alloc_coherent(&udev->pdev->dev, udev->l2_ring_size,
+ &udev->l2_ring_map,
+ GFP_KERNEL | __GFP_COMP);
+ if (!udev->l2_ring)
return -ENOMEM;
- cp->l2_buf_size = (cp->l2_rx_ring_size + 1) * cp->l2_single_buf_size;
- cp->l2_buf_size = PAGE_ALIGN(cp->l2_buf_size);
- cp->l2_buf = dma_alloc_coherent(&dev->pcidev->dev, cp->l2_buf_size,
- &cp->l2_buf_map,
- GFP_KERNEL | __GFP_COMP);
- if (!cp->l2_buf)
+ udev->l2_buf_size = (cp->l2_rx_ring_size + 1) * cp->l2_single_buf_size;
+ udev->l2_buf_size = PAGE_ALIGN(udev->l2_buf_size);
+ udev->l2_buf = dma_alloc_coherent(&udev->pdev->dev, udev->l2_buf_size,
+ &udev->l2_buf_map,
+ GFP_KERNEL | __GFP_COMP);
+ if (!udev->l2_buf)
return -ENOMEM;
+ write_lock(&cnic_dev_lock);
+ list_add(&udev->list, &cnic_udev_list);
+ write_unlock(&cnic_dev_lock);
+
+ pci_dev_get(udev->pdev);
+
+ cp->udev = udev;
+
return 0;
}
-static int cnic_alloc_uio(struct cnic_dev *dev) {
+static int cnic_init_uio(struct cnic_dev *dev)
+{
struct cnic_local *cp = dev->cnic_priv;
+ struct cnic_uio_dev *udev = cp->udev;
struct uio_info *uinfo;
- int ret;
+ int ret = 0;
- uinfo = kzalloc(sizeof(*uinfo), GFP_ATOMIC);
- if (!uinfo)
+ if (!udev)
return -ENOMEM;
+ uinfo = &udev->cnic_uinfo;
+
uinfo->mem[0].addr = dev->netdev->base_addr;
uinfo->mem[0].internal_addr = dev->regview;
uinfo->mem[0].size = dev->netdev->mem_end - dev->netdev->mem_start;
@@ -932,7 +980,7 @@ static int cnic_alloc_uio(struct cnic_dev *dev) {
if (test_bit(CNIC_F_BNX2_CLASS, &dev->flags)) {
uinfo->mem[1].addr = (unsigned long) cp->status_blk.gen &
- PAGE_MASK;
+ PAGE_MASK;
if (cp->ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX)
uinfo->mem[1].size = BNX2_SBLK_MSIX_ALIGN_SIZE * 9;
else
@@ -942,19 +990,19 @@ static int cnic_alloc_uio(struct cnic_dev *dev) {
} else if (test_bit(CNIC_F_BNX2X_CLASS, &dev->flags)) {
uinfo->mem[1].addr = (unsigned long) cp->bnx2x_def_status_blk &
PAGE_MASK;
- uinfo->mem[1].size = sizeof(struct host_def_status_block);
+ uinfo->mem[1].size = sizeof(*cp->bnx2x_def_status_blk);
uinfo->name = "bnx2x_cnic";
}
uinfo->mem[1].memtype = UIO_MEM_LOGICAL;
- uinfo->mem[2].addr = (unsigned long) cp->l2_ring;
- uinfo->mem[2].size = cp->l2_ring_size;
+ uinfo->mem[2].addr = (unsigned long) udev->l2_ring;
+ uinfo->mem[2].size = udev->l2_ring_size;
uinfo->mem[2].memtype = UIO_MEM_LOGICAL;
- uinfo->mem[3].addr = (unsigned long) cp->l2_buf;
- uinfo->mem[3].size = cp->l2_buf_size;
+ uinfo->mem[3].addr = (unsigned long) udev->l2_buf;
+ uinfo->mem[3].size = udev->l2_buf_size;
uinfo->mem[3].memtype = UIO_MEM_LOGICAL;
uinfo->version = CNIC_MODULE_VERSION;
@@ -963,16 +1011,17 @@ static int cnic_alloc_uio(struct cnic_dev *dev) {
uinfo->open = cnic_uio_open;
uinfo->release = cnic_uio_close;
- uinfo->priv = dev;
+ if (udev->uio_dev == -1) {
+ if (!uinfo->priv) {
+ uinfo->priv = udev;
- ret = uio_register_device(&dev->pcidev->dev, uinfo);
- if (ret) {
- kfree(uinfo);
- return ret;
+ ret = uio_register_device(&udev->pdev->dev, uinfo);
+ }
+ } else {
+ cnic_init_rings(dev);
}
- cp->cnic_uinfo = uinfo;
- return 0;
+ return ret;
}
static int cnic_alloc_bnx2_resc(struct cnic_dev *dev)
@@ -993,11 +1042,11 @@ static int cnic_alloc_bnx2_resc(struct cnic_dev *dev)
if (ret)
goto error;
- ret = cnic_alloc_l2_rings(dev, 2);
+ ret = cnic_alloc_uio_rings(dev, 2);
if (ret)
goto error;
- ret = cnic_alloc_uio(dev);
+ ret = cnic_init_uio(dev);
if (ret)
goto error;
@@ -1022,13 +1071,13 @@ static int cnic_alloc_bnx2x_context(struct cnic_dev *dev)
if (blks > cp->ethdev->ctx_tbl_len)
return -ENOMEM;
- cp->ctx_arr = kzalloc(blks * sizeof(struct cnic_ctx), GFP_KERNEL);
+ cp->ctx_arr = kcalloc(blks, sizeof(struct cnic_ctx), GFP_KERNEL);
if (cp->ctx_arr == NULL)
return -ENOMEM;
cp->ctx_blks = blks;
cp->ctx_blk_size = ctx_blk_size;
- if (BNX2X_CHIP_IS_E1H(cp->chip_id))
+ if (!BNX2X_CHIP_IS_57710(cp->chip_id))
cp->ctx_align = 0;
else
cp->ctx_align = ctx_blk_size;
@@ -1063,6 +1112,8 @@ static int cnic_alloc_bnx2x_resc(struct cnic_dev *dev)
int i, j, n, ret, pages;
struct cnic_dma *kwq_16_dma = &cp->kwq_16_data_info;
+ cp->iro_arr = ethdev->iro_arr;
+
cp->max_cid_space = MAX_ISCSI_TBL_SZ;
cp->iscsi_start_cid = start_cid;
if (start_cid < BNX2X_ISCSI_START_CID) {
@@ -1127,15 +1178,13 @@ static int cnic_alloc_bnx2x_resc(struct cnic_dev *dev)
cp->bnx2x_def_status_blk = cp->ethdev->irq_arr[1].status_blk;
- memset(cp->status_blk.bnx2x, 0, sizeof(*cp->status_blk.bnx2x));
-
cp->l2_rx_ring_size = 15;
- ret = cnic_alloc_l2_rings(dev, 4);
+ ret = cnic_alloc_uio_rings(dev, 4);
if (ret)
goto error;
- ret = cnic_alloc_uio(dev);
+ ret = cnic_init_uio(dev);
if (ret)
goto error;
@@ -1209,9 +1258,9 @@ static int cnic_submit_kwqe_16(struct cnic_dev *dev, u32 cmd, u32 cid,
kwqe.hdr.conn_and_cmd_data =
cpu_to_le32(((cmd << SPE_HDR_CMD_ID_SHIFT) |
- BNX2X_HW_CID(cid, cp->func)));
+ BNX2X_HW_CID(cp, cid)));
kwqe.hdr.type = cpu_to_le16(type);
- kwqe.hdr.reserved = 0;
+ kwqe.hdr.reserved1 = 0;
kwqe.data.phy_address.lo = cpu_to_le32(l5_data->phy_address.lo);
kwqe.data.phy_address.hi = cpu_to_le32(l5_data->phy_address.hi);
@@ -1246,8 +1295,8 @@ static int cnic_bnx2x_iscsi_init1(struct cnic_dev *dev, struct kwqe *kwqe)
{
struct cnic_local *cp = dev->cnic_priv;
struct iscsi_kwqe_init1 *req1 = (struct iscsi_kwqe_init1 *) kwqe;
- int func = cp->func, pages;
- int hq_bds;
+ int hq_bds, pages;
+ u32 pfid = cp->pfid;
cp->num_iscsi_tasks = req1->num_tasks_per_conn;
cp->num_ccells = req1->num_ccells_per_conn;
@@ -1264,60 +1313,60 @@ static int cnic_bnx2x_iscsi_init1(struct cnic_dev *dev, struct kwqe *kwqe)
return 0;
/* init Tstorm RAM */
- CNIC_WR16(dev, BAR_TSTRORM_INTMEM + TSTORM_ISCSI_RQ_SIZE_OFFSET(func),
+ CNIC_WR16(dev, BAR_TSTRORM_INTMEM + TSTORM_ISCSI_RQ_SIZE_OFFSET(pfid),
req1->rq_num_wqes);
- CNIC_WR16(dev, BAR_TSTRORM_INTMEM + TSTORM_ISCSI_PAGE_SIZE_OFFSET(func),
+ CNIC_WR16(dev, BAR_TSTRORM_INTMEM + TSTORM_ISCSI_PAGE_SIZE_OFFSET(pfid),
PAGE_SIZE);
CNIC_WR8(dev, BAR_TSTRORM_INTMEM +
- TSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(func), PAGE_SHIFT);
+ TSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfid), PAGE_SHIFT);
CNIC_WR16(dev, BAR_TSTRORM_INTMEM +
- TSTORM_ISCSI_NUM_OF_TASKS_OFFSET(func),
+ TSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfid),
req1->num_tasks_per_conn);
/* init Ustorm RAM */
CNIC_WR16(dev, BAR_USTRORM_INTMEM +
- USTORM_ISCSI_RQ_BUFFER_SIZE_OFFSET(func),
+ USTORM_ISCSI_RQ_BUFFER_SIZE_OFFSET(pfid),
req1->rq_buffer_size);
- CNIC_WR16(dev, BAR_USTRORM_INTMEM + USTORM_ISCSI_PAGE_SIZE_OFFSET(func),
+ CNIC_WR16(dev, BAR_USTRORM_INTMEM + USTORM_ISCSI_PAGE_SIZE_OFFSET(pfid),
PAGE_SIZE);
CNIC_WR8(dev, BAR_USTRORM_INTMEM +
- USTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(func), PAGE_SHIFT);
+ USTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfid), PAGE_SHIFT);
CNIC_WR16(dev, BAR_USTRORM_INTMEM +
- USTORM_ISCSI_NUM_OF_TASKS_OFFSET(func),
+ USTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfid),
req1->num_tasks_per_conn);
- CNIC_WR16(dev, BAR_USTRORM_INTMEM + USTORM_ISCSI_RQ_SIZE_OFFSET(func),
+ CNIC_WR16(dev, BAR_USTRORM_INTMEM + USTORM_ISCSI_RQ_SIZE_OFFSET(pfid),
req1->rq_num_wqes);
- CNIC_WR16(dev, BAR_USTRORM_INTMEM + USTORM_ISCSI_CQ_SIZE_OFFSET(func),
+ CNIC_WR16(dev, BAR_USTRORM_INTMEM + USTORM_ISCSI_CQ_SIZE_OFFSET(pfid),
req1->cq_num_wqes);
- CNIC_WR16(dev, BAR_USTRORM_INTMEM + USTORM_ISCSI_R2TQ_SIZE_OFFSET(func),
+ CNIC_WR16(dev, BAR_USTRORM_INTMEM + USTORM_ISCSI_R2TQ_SIZE_OFFSET(pfid),
cp->num_iscsi_tasks * BNX2X_ISCSI_MAX_PENDING_R2TS);
/* init Xstorm RAM */
- CNIC_WR16(dev, BAR_XSTRORM_INTMEM + XSTORM_ISCSI_PAGE_SIZE_OFFSET(func),
+ CNIC_WR16(dev, BAR_XSTRORM_INTMEM + XSTORM_ISCSI_PAGE_SIZE_OFFSET(pfid),
PAGE_SIZE);
CNIC_WR8(dev, BAR_XSTRORM_INTMEM +
- XSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(func), PAGE_SHIFT);
+ XSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfid), PAGE_SHIFT);
CNIC_WR16(dev, BAR_XSTRORM_INTMEM +
- XSTORM_ISCSI_NUM_OF_TASKS_OFFSET(func),
+ XSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfid),
req1->num_tasks_per_conn);
- CNIC_WR16(dev, BAR_XSTRORM_INTMEM + XSTORM_ISCSI_HQ_SIZE_OFFSET(func),
+ CNIC_WR16(dev, BAR_XSTRORM_INTMEM + XSTORM_ISCSI_HQ_SIZE_OFFSET(pfid),
hq_bds);
- CNIC_WR16(dev, BAR_XSTRORM_INTMEM + XSTORM_ISCSI_SQ_SIZE_OFFSET(func),
+ CNIC_WR16(dev, BAR_XSTRORM_INTMEM + XSTORM_ISCSI_SQ_SIZE_OFFSET(pfid),
req1->num_tasks_per_conn);
- CNIC_WR16(dev, BAR_XSTRORM_INTMEM + XSTORM_ISCSI_R2TQ_SIZE_OFFSET(func),
+ CNIC_WR16(dev, BAR_XSTRORM_INTMEM + XSTORM_ISCSI_R2TQ_SIZE_OFFSET(pfid),
cp->num_iscsi_tasks * BNX2X_ISCSI_MAX_PENDING_R2TS);
/* init Cstorm RAM */
- CNIC_WR16(dev, BAR_CSTRORM_INTMEM + CSTORM_ISCSI_PAGE_SIZE_OFFSET(func),
+ CNIC_WR16(dev, BAR_CSTRORM_INTMEM + CSTORM_ISCSI_PAGE_SIZE_OFFSET(pfid),
PAGE_SIZE);
CNIC_WR8(dev, BAR_CSTRORM_INTMEM +
- CSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(func), PAGE_SHIFT);
+ CSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfid), PAGE_SHIFT);
CNIC_WR16(dev, BAR_CSTRORM_INTMEM +
- CSTORM_ISCSI_NUM_OF_TASKS_OFFSET(func),
+ CSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfid),
req1->num_tasks_per_conn);
- CNIC_WR16(dev, BAR_CSTRORM_INTMEM + CSTORM_ISCSI_CQ_SIZE_OFFSET(func),
+ CNIC_WR16(dev, BAR_CSTRORM_INTMEM + CSTORM_ISCSI_CQ_SIZE_OFFSET(pfid),
req1->cq_num_wqes);
- CNIC_WR16(dev, BAR_CSTRORM_INTMEM + CSTORM_ISCSI_HQ_SIZE_OFFSET(func),
+ CNIC_WR16(dev, BAR_CSTRORM_INTMEM + CSTORM_ISCSI_HQ_SIZE_OFFSET(pfid),
hq_bds);
return 0;
@@ -1327,7 +1376,7 @@ static int cnic_bnx2x_iscsi_init2(struct cnic_dev *dev, struct kwqe *kwqe)
{
struct iscsi_kwqe_init2 *req2 = (struct iscsi_kwqe_init2 *) kwqe;
struct cnic_local *cp = dev->cnic_priv;
- int func = cp->func;
+ u32 pfid = cp->pfid;
struct iscsi_kcqe kcqe;
struct kcqe *cqes[1];
@@ -1339,21 +1388,21 @@ static int cnic_bnx2x_iscsi_init2(struct cnic_dev *dev, struct kwqe *kwqe)
}
CNIC_WR(dev, BAR_TSTRORM_INTMEM +
- TSTORM_ISCSI_ERROR_BITMAP_OFFSET(func), req2->error_bit_map[0]);
+ TSTORM_ISCSI_ERROR_BITMAP_OFFSET(pfid), req2->error_bit_map[0]);
CNIC_WR(dev, BAR_TSTRORM_INTMEM +
- TSTORM_ISCSI_ERROR_BITMAP_OFFSET(func) + 4,
+ TSTORM_ISCSI_ERROR_BITMAP_OFFSET(pfid) + 4,
req2->error_bit_map[1]);
CNIC_WR16(dev, BAR_USTRORM_INTMEM +
- USTORM_ISCSI_CQ_SQN_SIZE_OFFSET(func), req2->max_cq_sqn);
+ USTORM_ISCSI_CQ_SQN_SIZE_OFFSET(pfid), req2->max_cq_sqn);
CNIC_WR(dev, BAR_USTRORM_INTMEM +
- USTORM_ISCSI_ERROR_BITMAP_OFFSET(func), req2->error_bit_map[0]);
+ USTORM_ISCSI_ERROR_BITMAP_OFFSET(pfid), req2->error_bit_map[0]);
CNIC_WR(dev, BAR_USTRORM_INTMEM +
- USTORM_ISCSI_ERROR_BITMAP_OFFSET(func) + 4,
+ USTORM_ISCSI_ERROR_BITMAP_OFFSET(pfid) + 4,
req2->error_bit_map[1]);
CNIC_WR16(dev, BAR_CSTRORM_INTMEM +
- CSTORM_ISCSI_CQ_SQN_SIZE_OFFSET(func), req2->max_cq_sqn);
+ CSTORM_ISCSI_CQ_SQN_SIZE_OFFSET(pfid), req2->max_cq_sqn);
kcqe.completion_status = ISCSI_KCQE_COMPLETION_STATUS_SUCCESS;
@@ -1461,7 +1510,7 @@ static int cnic_setup_bnx2x_ctx(struct cnic_dev *dev, struct kwqe *wqes[],
struct cnic_context *ctx = &cp->ctx_tbl[req1->iscsi_conn_id];
struct cnic_iscsi *iscsi = ctx->proto.iscsi;
u32 cid = ctx->cid;
- u32 hw_cid = BNX2X_HW_CID(cid, cp->func);
+ u32 hw_cid = BNX2X_HW_CID(cp, cid);
struct iscsi_context *ictx;
struct regpair context_addr;
int i, j, n = 2, n_max;
@@ -1527,8 +1576,10 @@ static int cnic_setup_bnx2x_ctx(struct cnic_dev *dev, struct kwqe *wqes[],
ictx->tstorm_st_context.tcp.cwnd = 0x5A8;
ictx->tstorm_st_context.tcp.flags2 |=
TSTORM_TCP_ST_CONTEXT_SECTION_DA_EN;
+ ictx->tstorm_st_context.tcp.ooo_support_mode =
+ TCP_TSTORM_OOO_DROP_AND_PROC_ACK;
- ictx->timers_context.flags |= ISCSI_TIMERS_BLOCK_CONTEXT_CONN_VALID_FLG;
+ ictx->timers_context.flags |= TIMERS_BLOCK_CONTEXT_CONN_VALID_FLG;
ictx->ustorm_st_context.ring.rq.pbl_base.lo =
req2->rq_page_table_addr_lo;
@@ -1627,10 +1678,11 @@ static int cnic_bnx2x_iscsi_ofld1(struct cnic_dev *dev, struct kwqe *wqes[],
struct iscsi_kwqe_conn_offload1 *req1;
struct iscsi_kwqe_conn_offload2 *req2;
struct cnic_local *cp = dev->cnic_priv;
+ struct cnic_context *ctx;
struct iscsi_kcqe kcqe;
struct kcqe *cqes[1];
u32 l5_cid;
- int ret;
+ int ret = 0;
if (num < 2) {
*work = num;
@@ -1654,9 +1706,15 @@ static int cnic_bnx2x_iscsi_ofld1(struct cnic_dev *dev, struct kwqe *wqes[],
kcqe.iscsi_conn_id = l5_cid;
kcqe.completion_status = ISCSI_KCQE_COMPLETION_STATUS_CTX_ALLOC_FAILURE;
+ ctx = &cp->ctx_tbl[l5_cid];
+ if (test_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags)) {
+ kcqe.completion_status =
+ ISCSI_KCQE_COMPLETION_STATUS_CID_BUSY;
+ goto done;
+ }
+
if (atomic_inc_return(&cp->iscsi_conn) > dev->max_iscsi_conn) {
atomic_dec(&cp->iscsi_conn);
- ret = 0;
goto done;
}
ret = cnic_alloc_bnx2x_conn_resc(dev, l5_cid);
@@ -1673,8 +1731,7 @@ static int cnic_bnx2x_iscsi_ofld1(struct cnic_dev *dev, struct kwqe *wqes[],
}
kcqe.completion_status = ISCSI_KCQE_COMPLETION_STATUS_SUCCESS;
- kcqe.iscsi_conn_context_id = BNX2X_HW_CID(cp->ctx_tbl[l5_cid].cid,
- cp->func);
+ kcqe.iscsi_conn_context_id = BNX2X_HW_CID(cp, cp->ctx_tbl[l5_cid].cid);
done:
cqes[0] = (struct kcqe *) &kcqe;
@@ -1707,40 +1764,66 @@ static int cnic_bnx2x_iscsi_update(struct cnic_dev *dev, struct kwqe *kwqe)
return ret;
}
+static int cnic_bnx2x_destroy_ramrod(struct cnic_dev *dev, u32 l5_cid)
+{
+ struct cnic_local *cp = dev->cnic_priv;
+ struct cnic_context *ctx = &cp->ctx_tbl[l5_cid];
+ union l5cm_specific_data l5_data;
+ int ret;
+ u32 hw_cid, type;
+
+ init_waitqueue_head(&ctx->waitq);
+ ctx->wait_cond = 0;
+ memset(&l5_data, 0, sizeof(l5_data));
+ hw_cid = BNX2X_HW_CID(cp, ctx->cid);
+ type = (NONE_CONNECTION_TYPE << SPE_HDR_CONN_TYPE_SHIFT)
+ & SPE_HDR_CONN_TYPE;
+ type |= ((cp->pfid << SPE_HDR_FUNCTION_ID_SHIFT) &
+ SPE_HDR_FUNCTION_ID);
+
+ ret = cnic_submit_kwqe_16(dev, RAMROD_CMD_ID_COMMON_CFC_DEL,
+ hw_cid, type, &l5_data);
+
+ if (ret == 0)
+ wait_event(ctx->waitq, ctx->wait_cond);
+
+ return ret;
+}
+
static int cnic_bnx2x_iscsi_destroy(struct cnic_dev *dev, struct kwqe *kwqe)
{
struct cnic_local *cp = dev->cnic_priv;
struct iscsi_kwqe_conn_destroy *req =
(struct iscsi_kwqe_conn_destroy *) kwqe;
- union l5cm_specific_data l5_data;
u32 l5_cid = req->reserved0;
struct cnic_context *ctx = &cp->ctx_tbl[l5_cid];
int ret = 0;
struct iscsi_kcqe kcqe;
struct kcqe *cqes[1];
- if (!(ctx->ctx_flags & CTX_FL_OFFLD_START))
+ if (!test_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags))
goto skip_cfc_delete;
- while (!time_after(jiffies, ctx->timestamp + (2 * HZ)))
- msleep(250);
+ if (!time_after(jiffies, ctx->timestamp + (2 * HZ))) {
+ unsigned long delta = ctx->timestamp + (2 * HZ) - jiffies;
- init_waitqueue_head(&ctx->waitq);
- ctx->wait_cond = 0;
- memset(&l5_data, 0, sizeof(l5_data));
- ret = cnic_submit_kwqe_16(dev, RAMROD_CMD_ID_ETH_CFC_DEL,
- req->context_id,
- ETH_CONNECTION_TYPE |
- (1 << SPE_HDR_COMMON_RAMROD_SHIFT),
- &l5_data);
- if (ret == 0)
- wait_event(ctx->waitq, ctx->wait_cond);
+ if (delta > (2 * HZ))
+ delta = 0;
+
+ set_bit(CTX_FL_DELETE_WAIT, &ctx->ctx_flags);
+ queue_delayed_work(cnic_wq, &cp->delete_task, delta);
+ goto destroy_reply;
+ }
+
+ ret = cnic_bnx2x_destroy_ramrod(dev, l5_cid);
skip_cfc_delete:
cnic_free_bnx2x_conn_resc(dev, l5_cid);
atomic_dec(&cp->iscsi_conn);
+ clear_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags);
+destroy_reply:
memset(&kcqe, 0, sizeof(kcqe));
kcqe.op_code = ISCSI_KCQE_OPCODE_DESTROY_CONN;
kcqe.iscsi_conn_id = l5_cid;
@@ -1805,37 +1888,37 @@ static void cnic_init_storm_conn_bufs(struct cnic_dev *dev,
static void cnic_init_bnx2x_mac(struct cnic_dev *dev)
{
struct cnic_local *cp = dev->cnic_priv;
- int func = CNIC_FUNC(cp);
+ u32 pfid = cp->pfid;
u8 *mac = dev->mac_addr;
CNIC_WR8(dev, BAR_XSTRORM_INTMEM +
- XSTORM_ISCSI_LOCAL_MAC_ADDR0_OFFSET(func), mac[0]);
+ XSTORM_ISCSI_LOCAL_MAC_ADDR0_OFFSET(pfid), mac[0]);
CNIC_WR8(dev, BAR_XSTRORM_INTMEM +
- XSTORM_ISCSI_LOCAL_MAC_ADDR1_OFFSET(func), mac[1]);
+ XSTORM_ISCSI_LOCAL_MAC_ADDR1_OFFSET(pfid), mac[1]);
CNIC_WR8(dev, BAR_XSTRORM_INTMEM +
- XSTORM_ISCSI_LOCAL_MAC_ADDR2_OFFSET(func), mac[2]);
+ XSTORM_ISCSI_LOCAL_MAC_ADDR2_OFFSET(pfid), mac[2]);
CNIC_WR8(dev, BAR_XSTRORM_INTMEM +
- XSTORM_ISCSI_LOCAL_MAC_ADDR3_OFFSET(func), mac[3]);
+ XSTORM_ISCSI_LOCAL_MAC_ADDR3_OFFSET(pfid), mac[3]);
CNIC_WR8(dev, BAR_XSTRORM_INTMEM +
- XSTORM_ISCSI_LOCAL_MAC_ADDR4_OFFSET(func), mac[4]);
+ XSTORM_ISCSI_LOCAL_MAC_ADDR4_OFFSET(pfid), mac[4]);
CNIC_WR8(dev, BAR_XSTRORM_INTMEM +
- XSTORM_ISCSI_LOCAL_MAC_ADDR5_OFFSET(func), mac[5]);
+ XSTORM_ISCSI_LOCAL_MAC_ADDR5_OFFSET(pfid), mac[5]);
CNIC_WR8(dev, BAR_TSTRORM_INTMEM +
- TSTORM_ISCSI_TCP_VARS_LSB_LOCAL_MAC_ADDR_OFFSET(func), mac[5]);
+ TSTORM_ISCSI_TCP_VARS_LSB_LOCAL_MAC_ADDR_OFFSET(pfid), mac[5]);
CNIC_WR8(dev, BAR_TSTRORM_INTMEM +
- TSTORM_ISCSI_TCP_VARS_LSB_LOCAL_MAC_ADDR_OFFSET(func) + 1,
+ TSTORM_ISCSI_TCP_VARS_LSB_LOCAL_MAC_ADDR_OFFSET(pfid) + 1,
mac[4]);
CNIC_WR8(dev, BAR_TSTRORM_INTMEM +
- TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(func), mac[3]);
+ TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfid), mac[3]);
CNIC_WR8(dev, BAR_TSTRORM_INTMEM +
- TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(func) + 1,
+ TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfid) + 1,
mac[2]);
CNIC_WR8(dev, BAR_TSTRORM_INTMEM +
- TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(func) + 2,
+ TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfid) + 2,
mac[1]);
CNIC_WR8(dev, BAR_TSTRORM_INTMEM +
- TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(func) + 3,
+ TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfid) + 3,
mac[0]);
}
@@ -1851,10 +1934,10 @@ static void cnic_bnx2x_set_tcp_timestamp(struct cnic_dev *dev, int tcp_ts)
}
CNIC_WR8(dev, BAR_XSTRORM_INTMEM +
- XSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(cp->func), xstorm_flags);
+ XSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(cp->pfid), xstorm_flags);
CNIC_WR16(dev, BAR_TSTRORM_INTMEM +
- TSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(cp->func), tstorm_flags);
+ TSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(cp->pfid), tstorm_flags);
}
static int cnic_bnx2x_connect(struct cnic_dev *dev, struct kwqe *wqes[],
@@ -1929,7 +2012,7 @@ static int cnic_bnx2x_connect(struct cnic_dev *dev, struct kwqe *wqes[],
cnic_init_storm_conn_bufs(dev, kwqe1, kwqe3, conn_buf);
CNIC_WR16(dev, BAR_XSTRORM_INTMEM +
- XSTORM_ISCSI_LOCAL_VLAN_OFFSET(cp->func), csk->vlan_id);
+ XSTORM_ISCSI_LOCAL_VLAN_OFFSET(cp->pfid), csk->vlan_id);
cnic_bnx2x_set_tcp_timestamp(dev,
kwqe1->tcp_flags & L4_KWQ_CONNECT_REQ1_TIME_STAMP);
@@ -1937,7 +2020,7 @@ static int cnic_bnx2x_connect(struct cnic_dev *dev, struct kwqe *wqes[],
ret = cnic_submit_kwqe_16(dev, L5CM_RAMROD_CMD_ID_TCP_CONNECT,
kwqe1->cid, ISCSI_CONNECTION_TYPE, &l5_data);
if (!ret)
- ctx->ctx_flags |= CTX_FL_OFFLD_START;
+ set_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags);
return ret;
}
@@ -2063,7 +2146,7 @@ static int cnic_submit_bnx2x_kwqes(struct cnic_dev *dev, struct kwqe *wqes[],
static void service_kcqes(struct cnic_dev *dev, int num_cqes)
{
struct cnic_local *cp = dev->cnic_priv;
- int i, j;
+ int i, j, comp = 0;
i = 0;
j = 1;
@@ -2074,7 +2157,7 @@ static void service_kcqes(struct cnic_dev *dev, int num_cqes)
u32 kcqe_layer = kcqe_op_flag & KCQE_FLAGS_LAYER_MASK;
if (unlikely(kcqe_op_flag & KCQE_RAMROD_COMPLETION))
- cnic_kwq_completion(dev, 1);
+ comp++;
while (j < num_cqes) {
u32 next_op = cp->completed_kcq[i + j]->kcqe_op_flag;
@@ -2083,7 +2166,7 @@ static void service_kcqes(struct cnic_dev *dev, int num_cqes)
break;
if (unlikely(next_op & KCQE_RAMROD_COMPLETION))
- cnic_kwq_completion(dev, 1);
+ comp++;
j++;
}
@@ -2113,6 +2196,8 @@ end:
i += j;
j = 1;
}
+ if (unlikely(comp))
+ cnic_spq_completion(dev, DRV_CTL_RET_L5_SPQ_CREDIT_CMD, comp);
}
static u16 cnic_bnx2_next_idx(u16 idx)
@@ -2171,8 +2256,9 @@ static int cnic_get_kcqes(struct cnic_dev *dev, struct kcq_info *info)
static int cnic_l2_completion(struct cnic_local *cp)
{
u16 hw_cons, sw_cons;
+ struct cnic_uio_dev *udev = cp->udev;
union eth_rx_cqe *cqe, *cqe_ring = (union eth_rx_cqe *)
- (cp->l2_ring + (2 * BCM_PAGE_SIZE));
+ (udev->l2_ring + (2 * BCM_PAGE_SIZE));
u32 cmd;
int comp = 0;
@@ -2203,13 +2289,14 @@ static int cnic_l2_completion(struct cnic_local *cp)
static void cnic_chk_pkt_rings(struct cnic_local *cp)
{
- u16 rx_cons = *cp->rx_cons_ptr;
- u16 tx_cons = *cp->tx_cons_ptr;
+ u16 rx_cons, tx_cons;
int comp = 0;
- if (!test_bit(CNIC_F_CNIC_UP, &cp->dev->flags))
+ if (!test_bit(CNIC_LCL_FL_RINGS_INITED, &cp->cnic_local_flags))
return;
+ rx_cons = *cp->rx_cons_ptr;
+ tx_cons = *cp->tx_cons_ptr;
if (cp->tx_cons != tx_cons || cp->rx_cons != rx_cons) {
if (test_bit(CNIC_LCL_FL_L2_WAIT, &cp->cnic_local_flags))
comp = cnic_l2_completion(cp);
@@ -2217,7 +2304,8 @@ static void cnic_chk_pkt_rings(struct cnic_local *cp)
cp->tx_cons = tx_cons;
cp->rx_cons = rx_cons;
- uio_event_notify(cp->cnic_uinfo);
+ if (cp->udev)
+ uio_event_notify(&cp->udev->cnic_uinfo);
}
if (comp)
clear_bit(CNIC_LCL_FL_L2_WAIT, &cp->cnic_local_flags);
@@ -2318,14 +2406,38 @@ static inline void cnic_ack_bnx2x_int(struct cnic_dev *dev, u8 id, u8 storm,
CNIC_WR(dev, hc_addr, (*(u32 *)&igu_ack));
}
+static void cnic_ack_igu_sb(struct cnic_dev *dev, u8 igu_sb_id, u8 segment,
+ u16 index, u8 op, u8 update)
+{
+ struct igu_regular cmd_data;
+ u32 igu_addr = BAR_IGU_INTMEM + (IGU_CMD_INT_ACK_BASE + igu_sb_id) * 8;
+
+ cmd_data.sb_id_and_flags =
+ (index << IGU_REGULAR_SB_INDEX_SHIFT) |
+ (segment << IGU_REGULAR_SEGMENT_ACCESS_SHIFT) |
+ (update << IGU_REGULAR_BUPDATE_SHIFT) |
+ (op << IGU_REGULAR_ENABLE_INT_SHIFT);
+
+
+ CNIC_WR(dev, igu_addr, cmd_data.sb_id_and_flags);
+}
+
static void cnic_ack_bnx2x_msix(struct cnic_dev *dev)
{
struct cnic_local *cp = dev->cnic_priv;
- cnic_ack_bnx2x_int(dev, cp->status_blk_num, CSTORM_ID, 0,
+ cnic_ack_bnx2x_int(dev, cp->bnx2x_igu_sb_id, CSTORM_ID, 0,
IGU_INT_DISABLE, 0);
}
+static void cnic_ack_bnx2x_e2_msix(struct cnic_dev *dev)
+{
+ struct cnic_local *cp = dev->cnic_priv;
+
+ cnic_ack_igu_sb(dev, cp->bnx2x_igu_sb_id, IGU_SEG_ACCESS_DEF, 0,
+ IGU_INT_DISABLE, 0);
+}
+
static u32 cnic_service_bnx2x_kcq(struct cnic_dev *dev, struct kcq_info *info)
{
u32 last_status = *info->status_idx_ptr;
@@ -2357,8 +2469,12 @@ static void cnic_service_bnx2x_bh(unsigned long data)
status_idx = cnic_service_bnx2x_kcq(dev, &cp->kcq1);
CNIC_WR16(dev, cp->kcq1.io_addr, cp->kcq1.sw_prod_idx + MAX_KCQ_IDX);
- cnic_ack_bnx2x_int(dev, cp->status_blk_num, CSTORM_ID,
- status_idx, IGU_INT_ENABLE, 1);
+ if (BNX2X_CHIP_IS_E2(cp->chip_id))
+ cnic_ack_igu_sb(dev, cp->bnx2x_igu_sb_id, IGU_SEG_ACCESS_DEF,
+ status_idx, IGU_INT_ENABLE, 1);
+ else
+ cnic_ack_bnx2x_int(dev, cp->bnx2x_igu_sb_id, USTORM_ID,
+ status_idx, IGU_INT_ENABLE, 1);
}
static int cnic_service_bnx2x(void *data, void *status_blk)
@@ -2379,8 +2495,7 @@ static void cnic_ulp_stop(struct cnic_dev *dev)
struct cnic_local *cp = dev->cnic_priv;
int if_type;
- if (cp->cnic_uinfo)
- cnic_send_nlmsg(cp, ISCSI_KEVENT_IF_DOWN, NULL);
+ cnic_send_nlmsg(cp, ISCSI_KEVENT_IF_DOWN, NULL);
for (if_type = 0; if_type < MAX_CNIC_ULP_TYPE; if_type++) {
struct cnic_ulp_ops *ulp_ops;
@@ -2728,6 +2843,13 @@ static int cnic_cm_create(struct cnic_dev *dev, int ulp_type, u32 cid,
if (l5_cid >= MAX_CM_SK_TBL_SZ)
return -EINVAL;
+ if (cp->ctx_tbl) {
+ struct cnic_context *ctx = &cp->ctx_tbl[l5_cid];
+
+ if (test_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags))
+ return -EAGAIN;
+ }
+
csk1 = &cp->csk_tbl[l5_cid];
if (atomic_read(&csk1->ref_count))
return -EAGAIN;
@@ -3279,39 +3401,106 @@ static void cnic_close_bnx2x_conn(struct cnic_sock *csk, u32 opcode)
static void cnic_cm_stop_bnx2x_hw(struct cnic_dev *dev)
{
+ struct cnic_local *cp = dev->cnic_priv;
+ int i;
+
+ if (!cp->ctx_tbl)
+ return;
+
+ if (!netif_running(dev->netdev))
+ return;
+
+ for (i = 0; i < cp->max_cid_space; i++) {
+ struct cnic_context *ctx = &cp->ctx_tbl[i];
+
+ while (test_bit(CTX_FL_DELETE_WAIT, &ctx->ctx_flags))
+ msleep(10);
+
+ if (test_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags))
+ netdev_warn(dev->netdev, "CID %x not deleted\n",
+ ctx->cid);
+ }
+
+ cancel_delayed_work(&cp->delete_task);
+ flush_workqueue(cnic_wq);
+
+ if (atomic_read(&cp->iscsi_conn) != 0)
+ netdev_warn(dev->netdev, "%d iSCSI connections not destroyed\n",
+ atomic_read(&cp->iscsi_conn));
}
static int cnic_cm_init_bnx2x_hw(struct cnic_dev *dev)
{
struct cnic_local *cp = dev->cnic_priv;
- int func = CNIC_FUNC(cp);
+ u32 pfid = cp->pfid;
+ u32 port = CNIC_PORT(cp);
cnic_init_bnx2x_mac(dev);
cnic_bnx2x_set_tcp_timestamp(dev, 1);
CNIC_WR16(dev, BAR_XSTRORM_INTMEM +
- XSTORM_ISCSI_LOCAL_VLAN_OFFSET(func), 0);
+ XSTORM_ISCSI_LOCAL_VLAN_OFFSET(pfid), 0);
CNIC_WR(dev, BAR_XSTRORM_INTMEM +
- XSTORM_TCP_GLOBAL_DEL_ACK_COUNTER_ENABLED_OFFSET(func), 1);
+ XSTORM_TCP_GLOBAL_DEL_ACK_COUNTER_ENABLED_OFFSET(port), 1);
CNIC_WR(dev, BAR_XSTRORM_INTMEM +
- XSTORM_TCP_GLOBAL_DEL_ACK_COUNTER_MAX_COUNT_OFFSET(func),
+ XSTORM_TCP_GLOBAL_DEL_ACK_COUNTER_MAX_COUNT_OFFSET(port),
DEF_MAX_DA_COUNT);
CNIC_WR8(dev, BAR_XSTRORM_INTMEM +
- XSTORM_ISCSI_TCP_VARS_TTL_OFFSET(func), DEF_TTL);
+ XSTORM_ISCSI_TCP_VARS_TTL_OFFSET(pfid), DEF_TTL);
CNIC_WR8(dev, BAR_XSTRORM_INTMEM +
- XSTORM_ISCSI_TCP_VARS_TOS_OFFSET(func), DEF_TOS);
+ XSTORM_ISCSI_TCP_VARS_TOS_OFFSET(pfid), DEF_TOS);
CNIC_WR8(dev, BAR_XSTRORM_INTMEM +
- XSTORM_ISCSI_TCP_VARS_ADV_WND_SCL_OFFSET(func), 2);
+ XSTORM_ISCSI_TCP_VARS_ADV_WND_SCL_OFFSET(pfid), 2);
CNIC_WR(dev, BAR_XSTRORM_INTMEM +
- XSTORM_TCP_TX_SWS_TIMER_VAL_OFFSET(func), DEF_SWS_TIMER);
+ XSTORM_TCP_TX_SWS_TIMER_VAL_OFFSET(pfid), DEF_SWS_TIMER);
- CNIC_WR(dev, BAR_TSTRORM_INTMEM + TSTORM_TCP_MAX_CWND_OFFSET(func),
+ CNIC_WR(dev, BAR_TSTRORM_INTMEM + TSTORM_TCP_MAX_CWND_OFFSET(pfid),
DEF_MAX_CWND);
return 0;
}
+static void cnic_delete_task(struct work_struct *work)
+{
+ struct cnic_local *cp;
+ struct cnic_dev *dev;
+ u32 i;
+ int need_resched = 0;
+
+ cp = container_of(work, struct cnic_local, delete_task.work);
+ dev = cp->dev;
+
+ for (i = 0; i < cp->max_cid_space; i++) {
+ struct cnic_context *ctx = &cp->ctx_tbl[i];
+
+ if (!test_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags) ||
+ !test_bit(CTX_FL_DELETE_WAIT, &ctx->ctx_flags))
+ continue;
+
+ if (!time_after(jiffies, ctx->timestamp + (2 * HZ))) {
+ need_resched = 1;
+ continue;
+ }
+
+ if (!test_and_clear_bit(CTX_FL_DELETE_WAIT, &ctx->ctx_flags))
+ continue;
+
+ cnic_bnx2x_destroy_ramrod(dev, i);
+
+ cnic_free_bnx2x_conn_resc(dev, i);
+ if (ctx->ulp_proto_id == CNIC_ULP_ISCSI)
+ atomic_dec(&cp->iscsi_conn);
+
+ clear_bit(CTX_FL_OFFLD_START, &ctx->ctx_flags);
+ }
+
+ if (need_resched)
+ queue_delayed_work(cnic_wq, &cp->delete_task,
+ msecs_to_jiffies(10));
+
+}
+
static int cnic_cm_open(struct cnic_dev *dev)
{
struct cnic_local *cp = dev->cnic_priv;
@@ -3326,6 +3515,8 @@ static int cnic_cm_open(struct cnic_dev *dev)
if (err)
goto err_out;
+ INIT_DELAYED_WORK(&cp->delete_task, cnic_delete_task);
+
dev->cm_create = cnic_cm_create;
dev->cm_destroy = cnic_cm_destroy;
dev->cm_connect = cnic_cm_connect;
@@ -3418,11 +3609,24 @@ static void cnic_free_irq(struct cnic_dev *dev)
if (ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX) {
cp->disable_int_sync(dev);
- tasklet_disable(&cp->cnic_irq_task);
+ tasklet_kill(&cp->cnic_irq_task);
free_irq(ethdev->irq_arr[0].vector, dev);
}
}
+static int cnic_request_irq(struct cnic_dev *dev)
+{
+ struct cnic_local *cp = dev->cnic_priv;
+ struct cnic_eth_dev *ethdev = cp->ethdev;
+ int err;
+
+ err = request_irq(ethdev->irq_arr[0].vector, cnic_irq, 0, "cnic", dev);
+ if (err)
+ tasklet_disable(&cp->cnic_irq_task);
+
+ return err;
+}
+
static int cnic_init_bnx2_irq(struct cnic_dev *dev)
{
struct cnic_local *cp = dev->cnic_priv;
@@ -3443,12 +3647,10 @@ static int cnic_init_bnx2_irq(struct cnic_dev *dev)
cp->last_status_idx = cp->status_blk.bnx2->status_idx;
tasklet_init(&cp->cnic_irq_task, cnic_service_bnx2_msix,
(unsigned long) dev);
- err = request_irq(ethdev->irq_arr[0].vector, cnic_irq, 0,
- "cnic", dev);
- if (err) {
- tasklet_disable(&cp->cnic_irq_task);
+ err = cnic_request_irq(dev);
+ if (err)
return err;
- }
+
while (cp->status_blk.bnx2->status_completion_producer_index &&
i < 10) {
CNIC_WR(dev, BNX2_HC_COALESCE_NOW,
@@ -3515,11 +3717,12 @@ static void cnic_init_bnx2_tx_ring(struct cnic_dev *dev)
{
struct cnic_local *cp = dev->cnic_priv;
struct cnic_eth_dev *ethdev = cp->ethdev;
+ struct cnic_uio_dev *udev = cp->udev;
u32 cid_addr, tx_cid, sb_id;
u32 val, offset0, offset1, offset2, offset3;
int i;
struct tx_bd *txbd;
- dma_addr_t buf_map;
+ dma_addr_t buf_map, ring_map = udev->l2_ring_map;
struct status_block *s_blk = cp->status_blk.gen;
sb_id = cp->status_blk_num;
@@ -3561,18 +3764,18 @@ static void cnic_init_bnx2_tx_ring(struct cnic_dev *dev)
val = BNX2_L2CTX_CMD_TYPE_TYPE_L2 | (8 << 16);
cnic_ctx_wr(dev, cid_addr, offset1, val);
- txbd = (struct tx_bd *) cp->l2_ring;
+ txbd = (struct tx_bd *) udev->l2_ring;
- buf_map = cp->l2_buf_map;
+ buf_map = udev->l2_buf_map;
for (i = 0; i < MAX_TX_DESC_CNT; i++, txbd++) {
txbd->tx_bd_haddr_hi = (u64) buf_map >> 32;
txbd->tx_bd_haddr_lo = (u64) buf_map & 0xffffffff;
}
- val = (u64) cp->l2_ring_map >> 32;
+ val = (u64) ring_map >> 32;
cnic_ctx_wr(dev, cid_addr, offset2, val);
txbd->tx_bd_haddr_hi = val;
- val = (u64) cp->l2_ring_map & 0xffffffff;
+ val = (u64) ring_map & 0xffffffff;
cnic_ctx_wr(dev, cid_addr, offset3, val);
txbd->tx_bd_haddr_lo = val;
}
@@ -3581,10 +3784,12 @@ static void cnic_init_bnx2_rx_ring(struct cnic_dev *dev)
{
struct cnic_local *cp = dev->cnic_priv;
struct cnic_eth_dev *ethdev = cp->ethdev;
+ struct cnic_uio_dev *udev = cp->udev;
u32 cid_addr, sb_id, val, coal_reg, coal_val;
int i;
struct rx_bd *rxbd;
struct status_block *s_blk = cp->status_blk.gen;
+ dma_addr_t ring_map = udev->l2_ring_map;
sb_id = cp->status_blk_num;
cnic_init_context(dev, 2);
@@ -3618,22 +3823,22 @@ static void cnic_init_bnx2_rx_ring(struct cnic_dev *dev)
val = BNX2_L2CTX_L2_STATUSB_NUM(sb_id);
cnic_ctx_wr(dev, cid_addr, BNX2_L2CTX_HOST_BDIDX, val);
- rxbd = (struct rx_bd *) (cp->l2_ring + BCM_PAGE_SIZE);
+ rxbd = (struct rx_bd *) (udev->l2_ring + BCM_PAGE_SIZE);
for (i = 0; i < MAX_RX_DESC_CNT; i++, rxbd++) {
dma_addr_t buf_map;
int n = (i % cp->l2_rx_ring_size) + 1;
- buf_map = cp->l2_buf_map + (n * cp->l2_single_buf_size);
+ buf_map = udev->l2_buf_map + (n * cp->l2_single_buf_size);
rxbd->rx_bd_len = cp->l2_single_buf_size;
rxbd->rx_bd_flags = RX_BD_FLAGS_START | RX_BD_FLAGS_END;
rxbd->rx_bd_haddr_hi = (u64) buf_map >> 32;
rxbd->rx_bd_haddr_lo = (u64) buf_map & 0xffffffff;
}
- val = (u64) (cp->l2_ring_map + BCM_PAGE_SIZE) >> 32;
+ val = (u64) (ring_map + BCM_PAGE_SIZE) >> 32;
cnic_ctx_wr(dev, cid_addr, BNX2_L2CTX_NX_BDHADDR_HI, val);
rxbd->rx_bd_haddr_hi = val;
- val = (u64) (cp->l2_ring_map + BCM_PAGE_SIZE) & 0xffffffff;
+ val = (u64) (ring_map + BCM_PAGE_SIZE) & 0xffffffff;
cnic_ctx_wr(dev, cid_addr, BNX2_L2CTX_NX_BDHADDR_LO, val);
rxbd->rx_bd_haddr_lo = val;
@@ -3850,42 +4055,55 @@ static int cnic_init_bnx2x_irq(struct cnic_dev *dev)
tasklet_init(&cp->cnic_irq_task, cnic_service_bnx2x_bh,
(unsigned long) dev);
- if (ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX) {
- err = request_irq(ethdev->irq_arr[0].vector, cnic_irq, 0,
- "cnic", dev);
- if (err)
- tasklet_disable(&cp->cnic_irq_task);
- }
+ if (ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX)
+ err = cnic_request_irq(dev);
+
return err;
}
+static inline void cnic_storm_memset_hc_disable(struct cnic_dev *dev,
+ u16 sb_id, u8 sb_index,
+ u8 disable)
+{
+
+ u32 addr = BAR_CSTRORM_INTMEM +
+ CSTORM_STATUS_BLOCK_DATA_OFFSET(sb_id) +
+ offsetof(struct hc_status_block_data_e1x, index_data) +
+ sizeof(struct hc_index_data)*sb_index +
+ offsetof(struct hc_index_data, flags);
+ u16 flags = CNIC_RD16(dev, addr);
+ /* clear and set */
+ flags &= ~HC_INDEX_DATA_HC_ENABLED;
+ flags |= (((~disable) << HC_INDEX_DATA_HC_ENABLED_SHIFT) &
+ HC_INDEX_DATA_HC_ENABLED);
+ CNIC_WR16(dev, addr, flags);
+}
+
static void cnic_enable_bnx2x_int(struct cnic_dev *dev)
{
struct cnic_local *cp = dev->cnic_priv;
u8 sb_id = cp->status_blk_num;
- int port = CNIC_PORT(cp);
CNIC_WR8(dev, BAR_CSTRORM_INTMEM +
- CSTORM_SB_HC_TIMEOUT_C_OFFSET(port, sb_id,
- HC_INDEX_C_ISCSI_EQ_CONS),
- 64 / 12);
- CNIC_WR16(dev, BAR_CSTRORM_INTMEM +
- CSTORM_SB_HC_DISABLE_C_OFFSET(port, sb_id,
- HC_INDEX_C_ISCSI_EQ_CONS), 0);
+ CSTORM_STATUS_BLOCK_DATA_OFFSET(sb_id) +
+ offsetof(struct hc_status_block_data_e1x, index_data) +
+ sizeof(struct hc_index_data)*HC_INDEX_ISCSI_EQ_CONS +
+ offsetof(struct hc_index_data, timeout), 64 / 12);
+ cnic_storm_memset_hc_disable(dev, sb_id, HC_INDEX_ISCSI_EQ_CONS, 0);
}
static void cnic_disable_bnx2x_int_sync(struct cnic_dev *dev)
{
}
-static void cnic_init_bnx2x_tx_ring(struct cnic_dev *dev)
+static void cnic_init_bnx2x_tx_ring(struct cnic_dev *dev,
+ struct client_init_ramrod_data *data)
{
struct cnic_local *cp = dev->cnic_priv;
- union eth_tx_bd_types *txbd = (union eth_tx_bd_types *) cp->l2_ring;
- struct eth_context *context;
- struct regpair context_addr;
- dma_addr_t buf_map;
- int func = CNIC_FUNC(cp);
+ struct cnic_uio_dev *udev = cp->udev;
+ union eth_tx_bd_types *txbd = (union eth_tx_bd_types *) udev->l2_ring;
+ dma_addr_t buf_map, ring_map = udev->l2_ring_map;
+ struct host_sp_status_block *sb = cp->bnx2x_def_status_blk;
int port = CNIC_PORT(cp);
int i;
int cli = BNX2X_ISCSI_CL_ID(CNIC_E1HVN(cp));
@@ -3893,7 +4111,7 @@ static void cnic_init_bnx2x_tx_ring(struct cnic_dev *dev)
memset(txbd, 0, BCM_PAGE_SIZE);
- buf_map = cp->l2_buf_map;
+ buf_map = udev->l2_buf_map;
for (i = 0; i < MAX_TX_DESC_CNT; i += 3, txbd += 3) {
struct eth_tx_start_bd *start_bd = &txbd->start_bd;
struct eth_tx_bd *reg_bd = &((txbd + 2)->reg_bd);
@@ -3910,33 +4128,23 @@ static void cnic_init_bnx2x_tx_ring(struct cnic_dev *dev)
start_bd->general_data |= (1 << ETH_TX_START_BD_HDR_NBDS_SHIFT);
}
- context = cnic_get_bnx2x_ctx(dev, BNX2X_ISCSI_L2_CID, 1, &context_addr);
- val = (u64) cp->l2_ring_map >> 32;
+ val = (u64) ring_map >> 32;
txbd->next_bd.addr_hi = cpu_to_le32(val);
- context->xstorm_st_context.tx_bd_page_base_hi = val;
+ data->tx.tx_bd_page_base.hi = cpu_to_le32(val);
- val = (u64) cp->l2_ring_map & 0xffffffff;
+ val = (u64) ring_map & 0xffffffff;
txbd->next_bd.addr_lo = cpu_to_le32(val);
- context->xstorm_st_context.tx_bd_page_base_lo = val;
-
- context->cstorm_st_context.sb_index_number =
- HC_INDEX_DEF_C_ETH_ISCSI_CQ_CONS;
- context->cstorm_st_context.status_block_id = BNX2X_DEF_SB_ID;
+ data->tx.tx_bd_page_base.lo = cpu_to_le32(val);
- if (cli < MAX_X_STAT_COUNTER_ID)
- context->xstorm_st_context.statistics_data = cli |
- XSTORM_ETH_ST_CONTEXT_STATISTICS_ENABLE;
-
- context->xstorm_ag_context.cdu_reserved =
- CDU_RSRVD_VALUE_TYPE_A(BNX2X_HW_CID(BNX2X_ISCSI_L2_CID, func),
- CDU_REGION_NUMBER_XCM_AG,
- ETH_CONNECTION_TYPE);
+ /* Other ramrod params */
+ data->tx.tx_sb_index_number = HC_SP_INDEX_ETH_ISCSI_CQ_CONS;
+ data->tx.tx_status_block_id = BNX2X_DEF_SB_ID;
/* reset xstorm per client statistics */
- if (cli < MAX_X_STAT_COUNTER_ID) {
+ if (cli < MAX_STAT_COUNTER_ID) {
val = BAR_XSTRORM_INTMEM +
XSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
for (i = 0; i < sizeof(struct xstorm_per_client_stats) / 4; i++)
@@ -3944,111 +4152,77 @@ static void cnic_init_bnx2x_tx_ring(struct cnic_dev *dev)
}
cp->tx_cons_ptr =
- &cp->bnx2x_def_status_blk->c_def_status_block.index_values[
- HC_INDEX_DEF_C_ETH_ISCSI_CQ_CONS];
+ &sb->sp_sb.index_values[HC_SP_INDEX_ETH_ISCSI_CQ_CONS];
}
-static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev)
+static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev,
+ struct client_init_ramrod_data *data)
{
struct cnic_local *cp = dev->cnic_priv;
- struct eth_rx_bd *rxbd = (struct eth_rx_bd *) (cp->l2_ring +
+ struct cnic_uio_dev *udev = cp->udev;
+ struct eth_rx_bd *rxbd = (struct eth_rx_bd *) (udev->l2_ring +
BCM_PAGE_SIZE);
struct eth_rx_cqe_next_page *rxcqe = (struct eth_rx_cqe_next_page *)
- (cp->l2_ring + (2 * BCM_PAGE_SIZE));
- struct eth_context *context;
- struct regpair context_addr;
+ (udev->l2_ring + (2 * BCM_PAGE_SIZE));
+ struct host_sp_status_block *sb = cp->bnx2x_def_status_blk;
int i;
int port = CNIC_PORT(cp);
- int func = CNIC_FUNC(cp);
int cli = BNX2X_ISCSI_CL_ID(CNIC_E1HVN(cp));
+ int cl_qzone_id = BNX2X_CL_QZONE_ID(cp, cli);
u32 val;
- struct tstorm_eth_client_config tstorm_client = {0};
+ dma_addr_t ring_map = udev->l2_ring_map;
+
+ /* General data */
+ data->general.client_id = cli;
+ data->general.statistics_en_flg = 1;
+ data->general.statistics_counter_id = cli;
+ data->general.activate_flg = 1;
+ data->general.sp_client_id = cli;
for (i = 0; i < BNX2X_MAX_RX_DESC_CNT; i++, rxbd++) {
dma_addr_t buf_map;
int n = (i % cp->l2_rx_ring_size) + 1;
- buf_map = cp->l2_buf_map + (n * cp->l2_single_buf_size);
+ buf_map = udev->l2_buf_map + (n * cp->l2_single_buf_size);
rxbd->addr_hi = cpu_to_le32((u64) buf_map >> 32);
rxbd->addr_lo = cpu_to_le32(buf_map & 0xffffffff);
}
- context = cnic_get_bnx2x_ctx(dev, BNX2X_ISCSI_L2_CID, 0, &context_addr);
- val = (u64) (cp->l2_ring_map + BCM_PAGE_SIZE) >> 32;
+ val = (u64) (ring_map + BCM_PAGE_SIZE) >> 32;
rxbd->addr_hi = cpu_to_le32(val);
+ data->rx.bd_page_base.hi = cpu_to_le32(val);
- context->ustorm_st_context.common.bd_page_base_hi = val;
-
- val = (u64) (cp->l2_ring_map + BCM_PAGE_SIZE) & 0xffffffff;
+ val = (u64) (ring_map + BCM_PAGE_SIZE) & 0xffffffff;
rxbd->addr_lo = cpu_to_le32(val);
-
- context->ustorm_st_context.common.bd_page_base_lo = val;
-
- context->ustorm_st_context.common.sb_index_numbers =
- BNX2X_ISCSI_RX_SB_INDEX_NUM;
- context->ustorm_st_context.common.clientId = cli;
- context->ustorm_st_context.common.status_block_id = BNX2X_DEF_SB_ID;
- if (cli < MAX_U_STAT_COUNTER_ID) {
- context->ustorm_st_context.common.flags =
- USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_STATISTICS;
- context->ustorm_st_context.common.statistics_counter_id = cli;
- }
- context->ustorm_st_context.common.mc_alignment_log_size = 0;
- context->ustorm_st_context.common.bd_buff_size =
- cp->l2_single_buf_size;
-
- context->ustorm_ag_context.cdu_usage =
- CDU_RSRVD_VALUE_TYPE_A(BNX2X_HW_CID(BNX2X_ISCSI_L2_CID, func),
- CDU_REGION_NUMBER_UCM_AG,
- ETH_CONNECTION_TYPE);
+ data->rx.bd_page_base.lo = cpu_to_le32(val);
rxcqe += BNX2X_MAX_RCQ_DESC_CNT;
- val = (u64) (cp->l2_ring_map + (2 * BCM_PAGE_SIZE)) >> 32;
+ val = (u64) (ring_map + (2 * BCM_PAGE_SIZE)) >> 32;
rxcqe->addr_hi = cpu_to_le32(val);
+ data->rx.cqe_page_base.hi = cpu_to_le32(val);
- CNIC_WR(dev, BAR_USTRORM_INTMEM +
- USTORM_CQE_PAGE_BASE_OFFSET(port, cli) + 4, val);
-
- CNIC_WR(dev, BAR_USTRORM_INTMEM +
- USTORM_CQE_PAGE_NEXT_OFFSET(port, cli) + 4, val);
-
- val = (u64) (cp->l2_ring_map + (2 * BCM_PAGE_SIZE)) & 0xffffffff;
+ val = (u64) (ring_map + (2 * BCM_PAGE_SIZE)) & 0xffffffff;
rxcqe->addr_lo = cpu_to_le32(val);
+ data->rx.cqe_page_base.lo = cpu_to_le32(val);
- CNIC_WR(dev, BAR_USTRORM_INTMEM +
- USTORM_CQE_PAGE_BASE_OFFSET(port, cli), val);
-
- CNIC_WR(dev, BAR_USTRORM_INTMEM +
- USTORM_CQE_PAGE_NEXT_OFFSET(port, cli), val);
-
- /* client tstorm info */
- tstorm_client.mtu = cp->l2_single_buf_size - 14;
- tstorm_client.config_flags = TSTORM_ETH_CLIENT_CONFIG_E1HOV_REM_ENABLE;
-
- if (cli < MAX_T_STAT_COUNTER_ID) {
- tstorm_client.config_flags |=
- TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE;
- tstorm_client.statistics_counter_id = cli;
- }
+ /* Other ramrod params */
+ data->rx.client_qzone_id = cl_qzone_id;
+ data->rx.rx_sb_index_number = HC_SP_INDEX_ETH_ISCSI_RX_CQ_CONS;
+ data->rx.status_block_id = BNX2X_DEF_SB_ID;
- CNIC_WR(dev, BAR_TSTRORM_INTMEM +
- TSTORM_CLIENT_CONFIG_OFFSET(port, cli),
- ((u32 *)&tstorm_client)[0]);
- CNIC_WR(dev, BAR_TSTRORM_INTMEM +
- TSTORM_CLIENT_CONFIG_OFFSET(port, cli) + 4,
- ((u32 *)&tstorm_client)[1]);
+ data->rx.cache_line_alignment_log_size = L1_CACHE_SHIFT;
+ data->rx.bd_buff_size = cpu_to_le16(cp->l2_single_buf_size);
- /* reset tstorm per client statistics */
- if (cli < MAX_T_STAT_COUNTER_ID) {
+ data->rx.mtu = cpu_to_le16(cp->l2_single_buf_size - 14);
+ data->rx.outer_vlan_removal_enable_flg = 1;
+ /* reset tstorm and ustorm per client statistics */
+ if (cli < MAX_STAT_COUNTER_ID) {
val = BAR_TSTRORM_INTMEM +
TSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
for (i = 0; i < sizeof(struct tstorm_per_client_stats) / 4; i++)
CNIC_WR(dev, val + i * 4, 0);
- }
- /* reset ustorm per client statistics */
- if (cli < MAX_U_STAT_COUNTER_ID) {
val = BAR_USTRORM_INTMEM +
USTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
for (i = 0; i < sizeof(struct ustorm_per_client_stats) / 4; i++)
@@ -4056,21 +4230,22 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev)
}
cp->rx_cons_ptr =
- &cp->bnx2x_def_status_blk->u_def_status_block.index_values[
- HC_INDEX_DEF_U_ETH_ISCSI_RX_CQ_CONS];
+ &sb->sp_sb.index_values[HC_SP_INDEX_ETH_ISCSI_RX_CQ_CONS];
}
static void cnic_get_bnx2x_iscsi_info(struct cnic_dev *dev)
{
struct cnic_local *cp = dev->cnic_priv;
- u32 base, addr, val;
+ u32 base, base2, addr, val;
int port = CNIC_PORT(cp);
dev->max_iscsi_conn = 0;
base = CNIC_RD(dev, MISC_REG_SHARED_MEM_ADDR);
- if (base < 0xa0000 || base >= 0xc0000)
+ if (base == 0)
return;
+ base2 = CNIC_RD(dev, (CNIC_PATH(cp) ? MISC_REG_GENERIC_CR_1 :
+ MISC_REG_GENERIC_CR_0));
addr = BNX2X_SHMEM_ADDR(base,
dev_info.port_hw_config[port].iscsi_mac_upper);
@@ -4103,16 +4278,25 @@ static void cnic_get_bnx2x_iscsi_info(struct cnic_dev *dev)
val16 ^= 0x1e1e;
dev->max_iscsi_conn = val16;
}
- if (BNX2X_CHIP_IS_E1H(cp->chip_id)) {
+ if (BNX2X_CHIP_IS_E1H(cp->chip_id) || BNX2X_CHIP_IS_E2(cp->chip_id)) {
int func = CNIC_FUNC(cp);
+ u32 mf_cfg_addr;
+
+ if (BNX2X_SHMEM2_HAS(base2, mf_cfg_addr))
+ mf_cfg_addr = CNIC_RD(dev, BNX2X_SHMEM2_ADDR(base2,
+ mf_cfg_addr));
+ else
+ mf_cfg_addr = base + BNX2X_SHMEM_MF_BLK_OFFSET;
+
+ addr = mf_cfg_addr +
+ offsetof(struct mf_cfg, func_mf_config[func].e1hov_tag);
- addr = BNX2X_SHMEM_ADDR(base,
- mf_cfg.func_mf_config[func].e1hov_tag);
val = CNIC_RD(dev, addr);
val &= FUNC_MF_CFG_E1HOV_TAG_MASK;
if (val != FUNC_MF_CFG_E1HOV_TAG_DEFAULT) {
- addr = BNX2X_SHMEM_ADDR(base,
- mf_cfg.func_mf_config[func].config);
+ addr = mf_cfg_addr +
+ offsetof(struct mf_cfg,
+ func_mf_config[func].config);
val = CNIC_RD(dev, addr);
val &= FUNC_MF_CFG_PROTOCOL_MASK;
if (val != FUNC_MF_CFG_PROTOCOL_ISCSI)
@@ -4124,10 +4308,26 @@ static void cnic_get_bnx2x_iscsi_info(struct cnic_dev *dev)
static int cnic_start_bnx2x_hw(struct cnic_dev *dev)
{
struct cnic_local *cp = dev->cnic_priv;
+ struct cnic_eth_dev *ethdev = cp->ethdev;
int func = CNIC_FUNC(cp), ret, i;
- int port = CNIC_PORT(cp);
- u16 eq_idx;
- u8 sb_id = cp->status_blk_num;
+ u32 pfid;
+
+ if (BNX2X_CHIP_IS_E2(cp->chip_id)) {
+ u32 val = CNIC_RD(dev, MISC_REG_PORT4MODE_EN_OVWR);
+
+ if (!(val & 1))
+ val = CNIC_RD(dev, MISC_REG_PORT4MODE_EN);
+ else
+ val = (val >> 1) & 1;
+
+ if (val)
+ cp->pfid = func >> 1;
+ else
+ cp->pfid = func & 0x6;
+ } else {
+ cp->pfid = func;
+ }
+ pfid = cp->pfid;
ret = cnic_init_id_tbl(&cp->cid_tbl, MAX_ISCSI_TBL_SZ,
cp->iscsi_start_cid);
@@ -4135,86 +4335,98 @@ static int cnic_start_bnx2x_hw(struct cnic_dev *dev)
if (ret)
return -ENOMEM;
+ cp->bnx2x_igu_sb_id = ethdev->irq_arr[0].status_blk_num2;
+
cp->kcq1.io_addr = BAR_CSTRORM_INTMEM +
- CSTORM_ISCSI_EQ_PROD_OFFSET(func, 0);
+ CSTORM_ISCSI_EQ_PROD_OFFSET(pfid, 0);
cp->kcq1.sw_prod_idx = 0;
- cp->kcq1.hw_prod_idx_ptr =
- &cp->status_blk.bnx2x->c_status_block.index_values[
- HC_INDEX_C_ISCSI_EQ_CONS];
- cp->kcq1.status_idx_ptr =
- &cp->status_blk.bnx2x->c_status_block.status_block_index;
+ if (BNX2X_CHIP_IS_E2(cp->chip_id)) {
+ struct host_hc_status_block_e2 *sb = cp->status_blk.gen;
+
+ cp->kcq1.hw_prod_idx_ptr =
+ &sb->sb.index_values[HC_INDEX_ISCSI_EQ_CONS];
+ cp->kcq1.status_idx_ptr =
+ &sb->sb.running_index[SM_RX_ID];
+ } else {
+ struct host_hc_status_block_e1x *sb = cp->status_blk.gen;
+
+ cp->kcq1.hw_prod_idx_ptr =
+ &sb->sb.index_values[HC_INDEX_ISCSI_EQ_CONS];
+ cp->kcq1.status_idx_ptr =
+ &sb->sb.running_index[SM_RX_ID];
+ }
cnic_get_bnx2x_iscsi_info(dev);
/* Only 1 EQ */
CNIC_WR16(dev, cp->kcq1.io_addr, MAX_KCQ_IDX);
CNIC_WR(dev, BAR_CSTRORM_INTMEM +
- CSTORM_ISCSI_EQ_CONS_OFFSET(func, 0), 0);
+ CSTORM_ISCSI_EQ_CONS_OFFSET(pfid, 0), 0);
CNIC_WR(dev, BAR_CSTRORM_INTMEM +
- CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_OFFSET(func, 0),
+ CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_OFFSET(pfid, 0),
cp->kcq1.dma.pg_map_arr[1] & 0xffffffff);
CNIC_WR(dev, BAR_CSTRORM_INTMEM +
- CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_OFFSET(func, 0) + 4,
+ CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_OFFSET(pfid, 0) + 4,
(u64) cp->kcq1.dma.pg_map_arr[1] >> 32);
CNIC_WR(dev, BAR_CSTRORM_INTMEM +
- CSTORM_ISCSI_EQ_NEXT_EQE_ADDR_OFFSET(func, 0),
+ CSTORM_ISCSI_EQ_NEXT_EQE_ADDR_OFFSET(pfid, 0),
cp->kcq1.dma.pg_map_arr[0] & 0xffffffff);
CNIC_WR(dev, BAR_CSTRORM_INTMEM +
- CSTORM_ISCSI_EQ_NEXT_EQE_ADDR_OFFSET(func, 0) + 4,
+ CSTORM_ISCSI_EQ_NEXT_EQE_ADDR_OFFSET(pfid, 0) + 4,
(u64) cp->kcq1.dma.pg_map_arr[0] >> 32);
CNIC_WR8(dev, BAR_CSTRORM_INTMEM +
- CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_VALID_OFFSET(func, 0), 1);
+ CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_VALID_OFFSET(pfid, 0), 1);
CNIC_WR16(dev, BAR_CSTRORM_INTMEM +
- CSTORM_ISCSI_EQ_SB_NUM_OFFSET(func, 0), cp->status_blk_num);
+ CSTORM_ISCSI_EQ_SB_NUM_OFFSET(pfid, 0), cp->status_blk_num);
CNIC_WR8(dev, BAR_CSTRORM_INTMEM +
- CSTORM_ISCSI_EQ_SB_INDEX_OFFSET(func, 0),
- HC_INDEX_C_ISCSI_EQ_CONS);
+ CSTORM_ISCSI_EQ_SB_INDEX_OFFSET(pfid, 0),
+ HC_INDEX_ISCSI_EQ_CONS);
for (i = 0; i < cp->conn_buf_info.num_pages; i++) {
CNIC_WR(dev, BAR_TSTRORM_INTMEM +
- TSTORM_ISCSI_CONN_BUF_PBL_OFFSET(func, i),
+ TSTORM_ISCSI_CONN_BUF_PBL_OFFSET(pfid, i),
cp->conn_buf_info.pgtbl[2 * i]);
CNIC_WR(dev, BAR_TSTRORM_INTMEM +
- TSTORM_ISCSI_CONN_BUF_PBL_OFFSET(func, i) + 4,
+ TSTORM_ISCSI_CONN_BUF_PBL_OFFSET(pfid, i) + 4,
cp->conn_buf_info.pgtbl[(2 * i) + 1]);
}
CNIC_WR(dev, BAR_USTRORM_INTMEM +
- USTORM_ISCSI_GLOBAL_BUF_PHYS_ADDR_OFFSET(func),
+ USTORM_ISCSI_GLOBAL_BUF_PHYS_ADDR_OFFSET(pfid),
cp->gbl_buf_info.pg_map_arr[0] & 0xffffffff);
CNIC_WR(dev, BAR_USTRORM_INTMEM +
- USTORM_ISCSI_GLOBAL_BUF_PHYS_ADDR_OFFSET(func) + 4,
+ USTORM_ISCSI_GLOBAL_BUF_PHYS_ADDR_OFFSET(pfid) + 4,
(u64) cp->gbl_buf_info.pg_map_arr[0] >> 32);
+ CNIC_WR(dev, BAR_TSTRORM_INTMEM +
+ TSTORM_ISCSI_TCP_LOCAL_ADV_WND_OFFSET(pfid), DEF_RCV_BUF);
+
cnic_setup_bnx2x_context(dev);
- eq_idx = CNIC_RD16(dev, BAR_CSTRORM_INTMEM +
- CSTORM_SB_HOST_STATUS_BLOCK_C_OFFSET(port, sb_id) +
- offsetof(struct cstorm_status_block_c,
- index_values[HC_INDEX_C_ISCSI_EQ_CONS]));
- if (eq_idx != 0) {
- netdev_err(dev->netdev, "EQ cons index %x != 0\n", eq_idx);
- return -EBUSY;
- }
ret = cnic_init_bnx2x_irq(dev);
if (ret)
return ret;
- cnic_init_bnx2x_tx_ring(dev);
- cnic_init_bnx2x_rx_ring(dev);
-
return 0;
}
static void cnic_init_rings(struct cnic_dev *dev)
{
+ struct cnic_local *cp = dev->cnic_priv;
+ struct cnic_uio_dev *udev = cp->udev;
+
+ if (test_bit(CNIC_LCL_FL_RINGS_INITED, &cp->cnic_local_flags))
+ return;
+
if (test_bit(CNIC_F_BNX2_CLASS, &dev->flags)) {
cnic_init_bnx2_tx_ring(dev);
cnic_init_bnx2_rx_ring(dev);
+ set_bit(CNIC_LCL_FL_RINGS_INITED, &cp->cnic_local_flags);
} else if (test_bit(CNIC_F_BNX2X_CLASS, &dev->flags)) {
- struct cnic_local *cp = dev->cnic_priv;
u32 cli = BNX2X_ISCSI_CL_ID(CNIC_E1HVN(cp));
+ u32 cl_qzone_id, type;
+ struct client_init_ramrod_data *data;
union l5cm_specific_data l5_data;
struct ustorm_eth_rx_producers rx_prods = {0};
u32 off, i;
@@ -4223,21 +4435,38 @@ static void cnic_init_rings(struct cnic_dev *dev)
rx_prods.cqe_prod = BNX2X_MAX_RCQ_DESC_CNT;
barrier();
+ cl_qzone_id = BNX2X_CL_QZONE_ID(cp, cli);
+
off = BAR_USTRORM_INTMEM +
- USTORM_RX_PRODS_OFFSET(CNIC_PORT(cp), cli);
+ (BNX2X_CHIP_IS_E2(cp->chip_id) ?
+ USTORM_RX_PRODS_E2_OFFSET(cl_qzone_id) :
+ USTORM_RX_PRODS_E1X_OFFSET(CNIC_PORT(cp), cli));
for (i = 0; i < sizeof(struct ustorm_eth_rx_producers) / 4; i++)
CNIC_WR(dev, off + i * 4, ((u32 *) &rx_prods)[i]);
set_bit(CNIC_LCL_FL_L2_WAIT, &cp->cnic_local_flags);
- cnic_init_bnx2x_tx_ring(dev);
- cnic_init_bnx2x_rx_ring(dev);
+ data = udev->l2_buf;
+
+ memset(data, 0, sizeof(*data));
+
+ cnic_init_bnx2x_tx_ring(dev, data);
+ cnic_init_bnx2x_rx_ring(dev, data);
+
+ l5_data.phy_address.lo = udev->l2_buf_map & 0xffffffff;
+ l5_data.phy_address.hi = (u64) udev->l2_buf_map >> 32;
+
+ type = (ETH_CONNECTION_TYPE << SPE_HDR_CONN_TYPE_SHIFT)
+ & SPE_HDR_CONN_TYPE;
+ type |= ((cp->pfid << SPE_HDR_FUNCTION_ID_SHIFT) &
+ SPE_HDR_FUNCTION_ID);
+
+ set_bit(CNIC_LCL_FL_RINGS_INITED, &cp->cnic_local_flags);
- l5_data.phy_address.lo = cli;
- l5_data.phy_address.hi = 0;
cnic_submit_kwqe_16(dev, RAMROD_CMD_ID_ETH_CLIENT_SETUP,
- BNX2X_ISCSI_L2_CID, ETH_CONNECTION_TYPE, &l5_data);
+ BNX2X_ISCSI_L2_CID, type, &l5_data);
+
i = 0;
while (test_bit(CNIC_LCL_FL_L2_WAIT, &cp->cnic_local_flags) &&
++i < 10)
@@ -4246,13 +4475,18 @@ static void cnic_init_rings(struct cnic_dev *dev)
if (test_bit(CNIC_LCL_FL_L2_WAIT, &cp->cnic_local_flags))
netdev_err(dev->netdev,
"iSCSI CLIENT_SETUP did not complete\n");
- cnic_kwq_completion(dev, 1);
+ cnic_spq_completion(dev, DRV_CTL_RET_L2_SPQ_CREDIT_CMD, 1);
cnic_ring_ctl(dev, BNX2X_ISCSI_L2_CID, cli, 1);
}
}
static void cnic_shutdown_rings(struct cnic_dev *dev)
{
+ struct cnic_local *cp = dev->cnic_priv;
+
+ if (!test_bit(CNIC_LCL_FL_RINGS_INITED, &cp->cnic_local_flags))
+ return;
+
if (test_bit(CNIC_F_BNX2_CLASS, &dev->flags)) {
cnic_shutdown_bnx2_rx_ring(dev);
} else if (test_bit(CNIC_F_BNX2X_CLASS, &dev->flags)) {
@@ -4260,6 +4494,7 @@ static void cnic_shutdown_rings(struct cnic_dev *dev)
u32 cli = BNX2X_ISCSI_CL_ID(CNIC_E1HVN(cp));
union l5cm_specific_data l5_data;
int i;
+ u32 type;
cnic_ring_ctl(dev, BNX2X_ISCSI_L2_CID, cli, 0);
@@ -4277,14 +4512,18 @@ static void cnic_shutdown_rings(struct cnic_dev *dev)
if (test_bit(CNIC_LCL_FL_L2_WAIT, &cp->cnic_local_flags))
netdev_err(dev->netdev,
"iSCSI CLIENT_HALT did not complete\n");
- cnic_kwq_completion(dev, 1);
+ cnic_spq_completion(dev, DRV_CTL_RET_L2_SPQ_CREDIT_CMD, 1);
memset(&l5_data, 0, sizeof(l5_data));
- cnic_submit_kwqe_16(dev, RAMROD_CMD_ID_ETH_CFC_DEL,
- BNX2X_ISCSI_L2_CID, ETH_CONNECTION_TYPE |
- (1 << SPE_HDR_COMMON_RAMROD_SHIFT), &l5_data);
+ type = (NONE_CONNECTION_TYPE << SPE_HDR_CONN_TYPE_SHIFT)
+ & SPE_HDR_CONN_TYPE;
+ type |= ((cp->pfid << SPE_HDR_FUNCTION_ID_SHIFT) &
+ SPE_HDR_FUNCTION_ID);
+ cnic_submit_kwqe_16(dev, RAMROD_CMD_ID_COMMON_CFC_DEL,
+ BNX2X_ISCSI_L2_CID, type, &l5_data);
msleep(10);
}
+ clear_bit(CNIC_LCL_FL_RINGS_INITED, &cp->cnic_local_flags);
}
static int cnic_register_netdev(struct cnic_dev *dev)
@@ -4327,7 +4566,6 @@ static int cnic_start_hw(struct cnic_dev *dev)
return -EALREADY;
dev->regview = ethdev->io_base;
- cp->chip_id = ethdev->chip_id;
pci_dev_get(dev->pcidev);
cp->func = PCI_FUNC(dev->pcidev->devfn);
cp->status_blk.gen = ethdev->irq_arr[0].status_blk;
@@ -4379,17 +4617,11 @@ static void cnic_stop_bnx2_hw(struct cnic_dev *dev)
static void cnic_stop_bnx2x_hw(struct cnic_dev *dev)
{
struct cnic_local *cp = dev->cnic_priv;
- u8 sb_id = cp->status_blk_num;
- int port = CNIC_PORT(cp);
cnic_free_irq(dev);
- CNIC_WR16(dev, BAR_CSTRORM_INTMEM +
- CSTORM_SB_HOST_STATUS_BLOCK_C_OFFSET(port, sb_id) +
- offsetof(struct cstorm_status_block_c,
- index_values[HC_INDEX_C_ISCSI_EQ_CONS]),
- 0);
+ *cp->kcq1.hw_prod_idx_ptr = 0;
CNIC_WR(dev, BAR_CSTRORM_INTMEM +
- CSTORM_ISCSI_EQ_CONS_OFFSET(cp->func, 0), 0);
+ CSTORM_ISCSI_EQ_CONS_OFFSET(cp->pfid, 0), 0);
CNIC_WR16(dev, cp->kcq1.io_addr, 0);
cnic_free_resc(dev);
}
@@ -4403,10 +4635,11 @@ static void cnic_stop_hw(struct cnic_dev *dev)
/* Need to wait for the ring shutdown event to complete
* before clearing the CNIC_UP flag.
*/
- while (cp->uio_dev != -1 && i < 15) {
+ while (cp->udev->uio_dev != -1 && i < 15) {
msleep(100);
i++;
}
+ cnic_shutdown_rings(dev);
clear_bit(CNIC_F_CNIC_UP, &dev->flags);
rcu_assign_pointer(cp->ulp_ops[CNIC_ULP_L4], NULL);
synchronize_rcu();
@@ -4455,7 +4688,6 @@ static struct cnic_dev *cnic_alloc_dev(struct net_device *dev,
cp = cdev->cnic_priv;
cp->dev = cdev;
- cp->uio_dev = -1;
cp->l2_single_buf_size = 0x400;
cp->l2_rx_ring_size = 3;
@@ -4510,6 +4742,7 @@ static struct cnic_dev *init_bnx2_cnic(struct net_device *dev)
cp = cdev->cnic_priv;
cp->ethdev = ethdev;
cdev->pcidev = pdev;
+ cp->chip_id = ethdev->chip_id;
cp->cnic_ops = &cnic_bnx2_ops;
cp->start_hw = cnic_start_bnx2_hw;
@@ -4564,6 +4797,7 @@ static struct cnic_dev *init_bnx2x_cnic(struct net_device *dev)
cp = cdev->cnic_priv;
cp->ethdev = ethdev;
cdev->pcidev = pdev;
+ cp->chip_id = ethdev->chip_id;
cp->cnic_ops = &cnic_bnx2x_ops;
cp->start_hw = cnic_start_bnx2x_hw;
@@ -4575,7 +4809,10 @@ static struct cnic_dev *init_bnx2x_cnic(struct net_device *dev)
cp->stop_cm = cnic_cm_stop_bnx2x_hw;
cp->enable_int = cnic_enable_bnx2x_int;
cp->disable_int_sync = cnic_disable_bnx2x_int_sync;
- cp->ack_int = cnic_ack_bnx2x_msix;
+ if (BNX2X_CHIP_IS_E2(cp->chip_id))
+ cp->ack_int = cnic_ack_bnx2x_e2_msix;
+ else
+ cp->ack_int = cnic_ack_bnx2x_msix;
cp->close_conn = cnic_close_bnx2x_conn;
cp->next_idx = cnic_bnx2x_next_idx;
cp->hw_idx = cnic_bnx2x_hw_idx;
@@ -4683,6 +4920,7 @@ static struct notifier_block cnic_netdev_notifier = {
static void cnic_release(void)
{
struct cnic_dev *dev;
+ struct cnic_uio_dev *udev;
while (!list_empty(&cnic_dev_list)) {
dev = list_entry(cnic_dev_list.next, struct cnic_dev, list);
@@ -4696,6 +4934,11 @@ static void cnic_release(void)
list_del_init(&dev->list);
cnic_free_dev(dev);
}
+ while (!list_empty(&cnic_udev_list)) {
+ udev = list_entry(cnic_udev_list.next, struct cnic_uio_dev,
+ list);
+ cnic_free_uio(udev);
+ }
}
static int __init cnic_init(void)
@@ -4710,6 +4953,13 @@ static int __init cnic_init(void)
return rc;
}
+ cnic_wq = create_singlethread_workqueue("cnic_wq");
+ if (!cnic_wq) {
+ cnic_release();
+ unregister_netdevice_notifier(&cnic_netdev_notifier);
+ return -ENOMEM;
+ }
+
return 0;
}
@@ -4717,6 +4967,7 @@ static void __exit cnic_exit(void)
{
unregister_netdevice_notifier(&cnic_netdev_notifier);
cnic_release();
+ destroy_workqueue(cnic_wq);
}
module_init(cnic_init);
diff --git a/drivers/net/cnic.h b/drivers/net/cnic.h
index 275c36114d85..6a4a0ae5cfe3 100644
--- a/drivers/net/cnic.h
+++ b/drivers/net/cnic.h
@@ -12,6 +12,13 @@
#ifndef CNIC_H
#define CNIC_H
+#define HC_INDEX_ISCSI_EQ_CONS 6
+
+#define HC_INDEX_FCOE_EQ_CONS 3
+
+#define HC_SP_INDEX_ETH_ISCSI_CQ_CONS 5
+#define HC_SP_INDEX_ETH_ISCSI_RX_CQ_CONS 1
+
#define KWQ_PAGE_CNT 4
#define KCQ_PAGE_CNT 16
@@ -161,8 +168,9 @@ struct cnic_context {
wait_queue_head_t waitq;
int wait_cond;
unsigned long timestamp;
- u32 ctx_flags;
-#define CTX_FL_OFFLD_START 0x00000001
+ unsigned long ctx_flags;
+#define CTX_FL_OFFLD_START 0
+#define CTX_FL_DELETE_WAIT 1
u8 ulp_proto_id;
union {
struct cnic_iscsi *iscsi;
@@ -179,6 +187,31 @@ struct kcq_info {
u32 io_addr;
};
+struct iro {
+ u32 base;
+ u16 m1;
+ u16 m2;
+ u16 m3;
+ u16 size;
+};
+
+struct cnic_uio_dev {
+ struct uio_info cnic_uinfo;
+ u32 uio_dev;
+
+ int l2_ring_size;
+ void *l2_ring;
+ dma_addr_t l2_ring_map;
+
+ int l2_buf_size;
+ void *l2_buf;
+ dma_addr_t l2_buf_map;
+
+ struct cnic_dev *dev;
+ struct pci_dev *pdev;
+ struct list_head list;
+};
+
struct cnic_local {
spinlock_t cnic_ulp_lock;
@@ -192,19 +225,15 @@ struct cnic_local {
unsigned long cnic_local_flags;
#define CNIC_LCL_FL_KWQ_INIT 0x0
#define CNIC_LCL_FL_L2_WAIT 0x1
+#define CNIC_LCL_FL_RINGS_INITED 0x2
struct cnic_dev *dev;
struct cnic_eth_dev *ethdev;
- void *l2_ring;
- dma_addr_t l2_ring_map;
- int l2_ring_size;
- int l2_rx_ring_size;
+ struct cnic_uio_dev *udev;
- void *l2_buf;
- dma_addr_t l2_buf_map;
- int l2_buf_size;
+ int l2_rx_ring_size;
int l2_single_buf_size;
u16 *rx_cons_ptr;
@@ -212,6 +241,9 @@ struct cnic_local {
u16 rx_cons;
u16 tx_cons;
+ struct iro *iro_arr;
+#define IRO (((struct cnic_local *) dev->cnic_priv)->iro_arr)
+
struct cnic_dma kwq_info;
struct kwqe **kwq;
@@ -230,12 +262,16 @@ struct cnic_local {
union {
void *gen;
struct status_block_msix *bnx2;
- struct host_status_block *bnx2x;
+ struct host_hc_status_block_e1x *bnx2x_e1x;
+ /* index values - which counter to update */
+ #define SM_RX_ID 0
+ #define SM_TX_ID 1
} status_blk;
- struct host_def_status_block *bnx2x_def_status_blk;
+ struct host_sp_status_block *bnx2x_def_status_blk;
u32 status_blk_num;
+ u32 bnx2x_igu_sb_id;
u32 int_num;
u32 last_status_idx;
struct tasklet_struct cnic_irq_task;
@@ -264,6 +300,8 @@ struct cnic_local {
int hq_size;
int num_cqs;
+ struct delayed_work delete_task;
+
struct cnic_ctx *ctx_arr;
int ctx_blks;
int ctx_blk_size;
@@ -272,11 +310,9 @@ struct cnic_local {
u32 chip_id;
int func;
+ u32 pfid;
u32 shmem_base;
- u32 uio_dev;
- struct uio_info *cnic_uinfo;
-
struct cnic_ops *cnic_ops;
int (*start_hw)(struct cnic_dev *);
void (*stop_hw)(struct cnic_dev *);
@@ -335,18 +371,36 @@ struct bnx2x_bd_chain_next {
#define BNX2X_ISCSI_GLB_BUF_SIZE 64
#define BNX2X_ISCSI_PBL_NOT_CACHED 0xff
#define BNX2X_ISCSI_PDU_HEADER_NOT_CACHED 0xff
-#define BNX2X_HW_CID(x, func) ((x) | (((func) % PORT_MAX) << 23) | \
- (((func) >> 1) << 17))
-#define BNX2X_SW_CID(x) (x & 0x1ffff)
+
+#define BNX2X_CHIP_NUM_57710 0x164e
#define BNX2X_CHIP_NUM_57711 0x164f
#define BNX2X_CHIP_NUM_57711E 0x1650
+#define BNX2X_CHIP_NUM_57712 0x1662
+#define BNX2X_CHIP_NUM_57712E 0x1663
+#define BNX2X_CHIP_NUM_57713 0x1651
+#define BNX2X_CHIP_NUM_57713E 0x1652
+
#define BNX2X_CHIP_NUM(x) (x >> 16)
+#define BNX2X_CHIP_IS_57710(x) \
+ (BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57710)
#define BNX2X_CHIP_IS_57711(x) \
(BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57711)
#define BNX2X_CHIP_IS_57711E(x) \
(BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57711E)
#define BNX2X_CHIP_IS_E1H(x) \
(BNX2X_CHIP_IS_57711(x) || BNX2X_CHIP_IS_57711E(x))
+#define BNX2X_CHIP_IS_57712(x) \
+ (BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57712)
+#define BNX2X_CHIP_IS_57712E(x) \
+ (BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57712E)
+#define BNX2X_CHIP_IS_57713(x) \
+ (BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57713)
+#define BNX2X_CHIP_IS_57713E(x) \
+ (BNX2X_CHIP_NUM(x) == BNX2X_CHIP_NUM_57713E)
+#define BNX2X_CHIP_IS_E2(x) \
+ (BNX2X_CHIP_IS_57712(x) || BNX2X_CHIP_IS_57712E(x) || \
+ BNX2X_CHIP_IS_57713(x) || BNX2X_CHIP_IS_57713E(x))
+
#define IS_E1H_OFFSET BNX2X_CHIP_IS_E1H(cp->chip_id)
#define BNX2X_RX_DESC_CNT (BCM_PAGE_SIZE / sizeof(struct eth_rx_bd))
@@ -358,19 +412,35 @@ struct bnx2x_bd_chain_next {
(BNX2X_MAX_RCQ_DESC_CNT - 1)) ? \
((x) + 2) : ((x) + 1)
-#define BNX2X_DEF_SB_ID 16
+#define BNX2X_DEF_SB_ID HC_SP_SB_ID
-#define BNX2X_ISCSI_RX_SB_INDEX_NUM \
- ((HC_INDEX_DEF_U_ETH_ISCSI_RX_CQ_CONS << \
- USTORM_ETH_ST_CONTEXT_CONFIG_CQE_SB_INDEX_NUMBER_SHIFT) & \
- USTORM_ETH_ST_CONTEXT_CONFIG_CQE_SB_INDEX_NUMBER)
+#define BNX2X_SHMEM_MF_BLK_OFFSET 0x7e4
#define BNX2X_SHMEM_ADDR(base, field) (base + \
offsetof(struct shmem_region, field))
-#define CNIC_PORT(cp) ((cp)->func % PORT_MAX)
+#define BNX2X_SHMEM2_ADDR(base, field) (base + \
+ offsetof(struct shmem2_region, field))
+
+#define BNX2X_SHMEM2_HAS(base, field) \
+ ((base) && \
+ (CNIC_RD(dev, BNX2X_SHMEM2_ADDR(base, size)) > \
+ offsetof(struct shmem2_region, field)))
+
+#define CNIC_PORT(cp) ((cp)->pfid & 1)
#define CNIC_FUNC(cp) ((cp)->func)
-#define CNIC_E1HVN(cp) ((cp)->func >> 1)
+#define CNIC_PATH(cp) (!BNX2X_CHIP_IS_E2(cp->chip_id) ? 0 :\
+ (CNIC_FUNC(cp) & 1))
+#define CNIC_E1HVN(cp) ((cp)->pfid >> 1)
+
+#define BNX2X_HW_CID(cp, x) ((CNIC_PORT(cp) << 23) | \
+ (CNIC_E1HVN(cp) << 17) | (x))
+
+#define BNX2X_SW_CID(x) (x & 0x1ffff)
+
+#define BNX2X_CL_QZONE_ID(cp, cli) \
+ (cli + (CNIC_PORT(cp) * ETH_MAX_RX_CLIENTS_E1H))
+#define TCP_TSTORM_OOO_DROP_AND_PROC_ACK (0<<4)
#endif
diff --git a/drivers/net/cnic_defs.h b/drivers/net/cnic_defs.h
index 7ce694d41b6b..328e8b2765a3 100644
--- a/drivers/net/cnic_defs.h
+++ b/drivers/net/cnic_defs.h
@@ -14,6 +14,7 @@
/* KWQ (kernel work queue) request op codes */
#define L2_KWQE_OPCODE_VALUE_FLUSH (4)
+#define L2_KWQE_OPCODE_VALUE_VM_FREE_RX_QUEUE (8)
#define L4_KWQE_OPCODE_VALUE_CONNECT1 (50)
#define L4_KWQE_OPCODE_VALUE_CONNECT2 (51)
@@ -48,11 +49,14 @@
#define L4_KCQE_OPCODE_VALUE_UPLOAD_PG (14)
/* KCQ (kernel completion queue) completion status */
-#define L4_KCQE_COMPLETION_STATUS_SUCCESS (0)
-#define L4_KCQE_COMPLETION_STATUS_TIMEOUT (0x93)
+#define L4_KCQE_COMPLETION_STATUS_SUCCESS (0)
+#define L4_KCQE_COMPLETION_STATUS_TIMEOUT (0x93)
-#define L4_KCQE_COMPLETION_STATUS_CTX_ALLOC_FAIL (0x83)
-#define L4_KCQE_COMPLETION_STATUS_OFFLOADED_PG (0x89)
+#define L4_KCQE_COMPLETION_STATUS_CTX_ALLOC_FAIL (0x83)
+#define L4_KCQE_COMPLETION_STATUS_OFFLOADED_PG (0x89)
+
+#define L4_KCQE_OPCODE_VALUE_OOO_EVENT_NOTIFICATION (0xa0)
+#define L4_KCQE_OPCODE_VALUE_OOO_FLUSH (0xa1)
#define L4_LAYER_CODE (4)
#define L2_LAYER_CODE (2)
@@ -585,6 +589,100 @@ struct l4_kwq_upload {
*/
/*
+ * The iscsi aggregative context of Cstorm
+ */
+struct cstorm_iscsi_ag_context {
+ u32 agg_vars1;
+#define CSTORM_ISCSI_AG_CONTEXT_STATE (0xFF<<0)
+#define CSTORM_ISCSI_AG_CONTEXT_STATE_SHIFT 0
+#define __CSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<8)
+#define __CSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 8
+#define __CSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<9)
+#define __CSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 9
+#define __CSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<10)
+#define __CSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 10
+#define __CSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<11)
+#define __CSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 11
+#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED_ULP_RX_SE_CF_EN (0x1<<12)
+#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED_ULP_RX_SE_CF_EN_SHIFT 12
+#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED_ULP_RX_INV_CF_EN (0x1<<13)
+#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED_ULP_RX_INV_CF_EN_SHIFT 13
+#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION3_CF (0x3<<14)
+#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION3_CF_SHIFT 14
+#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED66 (0x3<<16)
+#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED66_SHIFT 16
+#define __CSTORM_ISCSI_AG_CONTEXT_FIN_RECEIVED_CF_EN (0x1<<18)
+#define __CSTORM_ISCSI_AG_CONTEXT_FIN_RECEIVED_CF_EN_SHIFT 18
+#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION0_CF_EN (0x1<<19)
+#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION0_CF_EN_SHIFT 19
+#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION1_CF_EN (0x1<<20)
+#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION1_CF_EN_SHIFT 20
+#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION2_CF_EN (0x1<<21)
+#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION2_CF_EN_SHIFT 21
+#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION3_CF_EN (0x1<<22)
+#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION3_CF_EN_SHIFT 22
+#define __CSTORM_ISCSI_AG_CONTEXT_REL_SEQ_RULE (0x7<<23)
+#define __CSTORM_ISCSI_AG_CONTEXT_REL_SEQ_RULE_SHIFT 23
+#define CSTORM_ISCSI_AG_CONTEXT_HQ_PROD_RULE (0x3<<26)
+#define CSTORM_ISCSI_AG_CONTEXT_HQ_PROD_RULE_SHIFT 26
+#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED52 (0x3<<28)
+#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED52_SHIFT 28
+#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED53 (0x3<<30)
+#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED53_SHIFT 30
+#if defined(__BIG_ENDIAN)
+ u8 __aux1_th;
+ u8 __aux1_val;
+ u16 __agg_vars2;
+#elif defined(__LITTLE_ENDIAN)
+ u16 __agg_vars2;
+ u8 __aux1_val;
+ u8 __aux1_th;
+#endif
+ u32 rel_seq;
+ u32 rel_seq_th;
+#if defined(__BIG_ENDIAN)
+ u16 hq_cons;
+ u16 hq_prod;
+#elif defined(__LITTLE_ENDIAN)
+ u16 hq_prod;
+ u16 hq_cons;
+#endif
+#if defined(__BIG_ENDIAN)
+ u8 __reserved62;
+ u8 __reserved61;
+ u8 __reserved60;
+ u8 __reserved59;
+#elif defined(__LITTLE_ENDIAN)
+ u8 __reserved59;
+ u8 __reserved60;
+ u8 __reserved61;
+ u8 __reserved62;
+#endif
+#if defined(__BIG_ENDIAN)
+ u16 __reserved64;
+ u16 __cq_u_prod0;
+#elif defined(__LITTLE_ENDIAN)
+ u16 __cq_u_prod0;
+ u16 __reserved64;
+#endif
+ u32 __cq_u_prod1;
+#if defined(__BIG_ENDIAN)
+ u16 __agg_vars3;
+ u16 __cq_u_prod2;
+#elif defined(__LITTLE_ENDIAN)
+ u16 __cq_u_prod2;
+ u16 __agg_vars3;
+#endif
+#if defined(__BIG_ENDIAN)
+ u16 __aux2_th;
+ u16 __cq_u_prod3;
+#elif defined(__LITTLE_ENDIAN)
+ u16 __cq_u_prod3;
+ u16 __aux2_th;
+#endif
+};
+
+/*
* iSCSI context region, used only in iSCSI
*/
struct ustorm_iscsi_rq_db {
@@ -696,7 +794,7 @@ struct ustorm_iscsi_st_context {
struct regpair task_pbl_base;
struct regpair tce_phy_addr;
struct ustorm_iscsi_placement_db place_db;
- u32 data_rcv_seq;
+ u32 reserved8;
u32 rem_rcv_len;
#if defined(__BIG_ENDIAN)
u16 hdr_itt;
@@ -713,8 +811,10 @@ struct ustorm_iscsi_st_context {
#define USTORM_ISCSI_ST_CONTEXT_BMIDDLEOFPDU_SHIFT 0
#define USTORM_ISCSI_ST_CONTEXT_BFENCECQE (0x1<<1)
#define USTORM_ISCSI_ST_CONTEXT_BFENCECQE_SHIFT 1
-#define USTORM_ISCSI_ST_CONTEXT_RESERVED1 (0x3F<<2)
-#define USTORM_ISCSI_ST_CONTEXT_RESERVED1_SHIFT 2
+#define USTORM_ISCSI_ST_CONTEXT_BRESETCRC (0x1<<2)
+#define USTORM_ISCSI_ST_CONTEXT_BRESETCRC_SHIFT 2
+#define USTORM_ISCSI_ST_CONTEXT_RESERVED1 (0x1F<<3)
+#define USTORM_ISCSI_ST_CONTEXT_RESERVED1_SHIFT 3
u8 task_pdu_cache_index;
u8 task_pbe_cache_index;
#elif defined(__LITTLE_ENDIAN)
@@ -725,8 +825,10 @@ struct ustorm_iscsi_st_context {
#define USTORM_ISCSI_ST_CONTEXT_BMIDDLEOFPDU_SHIFT 0
#define USTORM_ISCSI_ST_CONTEXT_BFENCECQE (0x1<<1)
#define USTORM_ISCSI_ST_CONTEXT_BFENCECQE_SHIFT 1
-#define USTORM_ISCSI_ST_CONTEXT_RESERVED1 (0x3F<<2)
-#define USTORM_ISCSI_ST_CONTEXT_RESERVED1_SHIFT 2
+#define USTORM_ISCSI_ST_CONTEXT_BRESETCRC (0x1<<2)
+#define USTORM_ISCSI_ST_CONTEXT_BRESETCRC_SHIFT 2
+#define USTORM_ISCSI_ST_CONTEXT_RESERVED1 (0x1F<<3)
+#define USTORM_ISCSI_ST_CONTEXT_RESERVED1_SHIFT 3
u8 hdr_second_byte_union;
#endif
#if defined(__BIG_ENDIAN)
@@ -777,14 +879,14 @@ struct ustorm_iscsi_st_context {
*/
struct tstorm_tcp_st_context_section {
u32 flags1;
-#define TSTORM_TCP_ST_CONTEXT_SECTION_RTT_SRTT_20B (0xFFFFFF<<0)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_RTT_SRTT_20B_SHIFT 0
+#define TSTORM_TCP_ST_CONTEXT_SECTION_RTT_SRTT (0xFFFFFF<<0)
+#define TSTORM_TCP_ST_CONTEXT_SECTION_RTT_SRTT_SHIFT 0
#define TSTORM_TCP_ST_CONTEXT_SECTION_PAWS_INVALID (0x1<<24)
#define TSTORM_TCP_ST_CONTEXT_SECTION_PAWS_INVALID_SHIFT 24
#define TSTORM_TCP_ST_CONTEXT_SECTION_TIMESTAMP_EXISTS (0x1<<25)
#define TSTORM_TCP_ST_CONTEXT_SECTION_TIMESTAMP_EXISTS_SHIFT 25
-#define TSTORM_TCP_ST_CONTEXT_SECTION_ISLE_EXISTS (0x1<<26)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_ISLE_EXISTS_SHIFT 26
+#define TSTORM_TCP_ST_CONTEXT_SECTION_RESERVED0 (0x1<<26)
+#define TSTORM_TCP_ST_CONTEXT_SECTION_RESERVED0_SHIFT 26
#define TSTORM_TCP_ST_CONTEXT_SECTION_STOP_RX_PAYLOAD (0x1<<27)
#define TSTORM_TCP_ST_CONTEXT_SECTION_STOP_RX_PAYLOAD_SHIFT 27
#define TSTORM_TCP_ST_CONTEXT_SECTION_KA_ENABLED (0x1<<28)
@@ -793,11 +895,11 @@ struct tstorm_tcp_st_context_section {
#define TSTORM_TCP_ST_CONTEXT_SECTION_FIRST_RTO_ESTIMATE_SHIFT 29
#define TSTORM_TCP_ST_CONTEXT_SECTION_MAX_SEG_RETRANSMIT_EN (0x1<<30)
#define TSTORM_TCP_ST_CONTEXT_SECTION_MAX_SEG_RETRANSMIT_EN_SHIFT 30
-#define TSTORM_TCP_ST_CONTEXT_SECTION_RESERVED3 (0x1<<31)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_RESERVED3_SHIFT 31
+#define TSTORM_TCP_ST_CONTEXT_SECTION_LAST_ISLE_HAS_FIN (0x1<<31)
+#define TSTORM_TCP_ST_CONTEXT_SECTION_LAST_ISLE_HAS_FIN_SHIFT 31
u32 flags2;
-#define TSTORM_TCP_ST_CONTEXT_SECTION_RTT_VARIATION_20B (0xFFFFFF<<0)
-#define TSTORM_TCP_ST_CONTEXT_SECTION_RTT_VARIATION_20B_SHIFT 0
+#define TSTORM_TCP_ST_CONTEXT_SECTION_RTT_VARIATION (0xFFFFFF<<0)
+#define TSTORM_TCP_ST_CONTEXT_SECTION_RTT_VARIATION_SHIFT 0
#define TSTORM_TCP_ST_CONTEXT_SECTION_DA_EN (0x1<<24)
#define TSTORM_TCP_ST_CONTEXT_SECTION_DA_EN_SHIFT 24
#define TSTORM_TCP_ST_CONTEXT_SECTION_DA_COUNTER_EN (0x1<<25)
@@ -810,18 +912,18 @@ struct tstorm_tcp_st_context_section {
#define TSTORM_TCP_ST_CONTEXT_SECTION_UPDATE_L2_STATSTICS_SHIFT 28
#define TSTORM_TCP_ST_CONTEXT_SECTION_UPDATE_L4_STATSTICS (0x1<<29)
#define TSTORM_TCP_ST_CONTEXT_SECTION_UPDATE_L4_STATSTICS_SHIFT 29
-#define __TSTORM_TCP_ST_CONTEXT_SECTION_SECOND_ISLE_DROPPED (0x1<<30)
-#define __TSTORM_TCP_ST_CONTEXT_SECTION_SECOND_ISLE_DROPPED_SHIFT 30
-#define __TSTORM_TCP_ST_CONTEXT_SECTION_DONT_SUPPORT_OOO (0x1<<31)
-#define __TSTORM_TCP_ST_CONTEXT_SECTION_DONT_SUPPORT_OOO_SHIFT 31
+#define __TSTORM_TCP_ST_CONTEXT_SECTION_IN_WINDOW_RST_ATTACK (0x1<<30)
+#define __TSTORM_TCP_ST_CONTEXT_SECTION_IN_WINDOW_RST_ATTACK_SHIFT 30
+#define __TSTORM_TCP_ST_CONTEXT_SECTION_IN_WINDOW_SYN_ATTACK (0x1<<31)
+#define __TSTORM_TCP_ST_CONTEXT_SECTION_IN_WINDOW_SYN_ATTACK_SHIFT 31
#if defined(__BIG_ENDIAN)
- u16 reserved_slowpath;
- u8 tcp_sm_state_3b;
- u8 rto_exp_3b;
+ u16 mss;
+ u8 tcp_sm_state;
+ u8 rto_exp;
#elif defined(__LITTLE_ENDIAN)
- u8 rto_exp_3b;
- u8 tcp_sm_state_3b;
- u16 reserved_slowpath;
+ u8 rto_exp;
+ u8 tcp_sm_state;
+ u16 mss;
#endif
u32 rcv_nxt;
u32 timestamp_recent;
@@ -846,11 +948,11 @@ struct tstorm_tcp_st_context_section {
#if defined(__BIG_ENDIAN)
u8 statistics_counter_id;
u8 ooo_support_mode;
- u8 snd_wnd_scale_4b;
+ u8 snd_wnd_scale;
u8 dup_ack_count;
#elif defined(__LITTLE_ENDIAN)
u8 dup_ack_count;
- u8 snd_wnd_scale_4b;
+ u8 snd_wnd_scale;
u8 ooo_support_mode;
u8 statistics_counter_id;
#endif
@@ -860,13 +962,21 @@ struct tstorm_tcp_st_context_section {
u32 isle_start_seq;
u32 isle_end_seq;
#if defined(__BIG_ENDIAN)
- u16 mss;
+ u16 second_isle_address;
u16 recent_seg_wnd;
#elif defined(__LITTLE_ENDIAN)
u16 recent_seg_wnd;
- u16 mss;
+ u16 second_isle_address;
+#endif
+#if defined(__BIG_ENDIAN)
+ u8 max_isles_ever_happened;
+ u8 isles_number;
+ u16 last_isle_address;
+#elif defined(__LITTLE_ENDIAN)
+ u16 last_isle_address;
+ u8 isles_number;
+ u8 max_isles_ever_happened;
#endif
- u32 reserved4;
u32 max_rt_time;
#if defined(__BIG_ENDIAN)
u16 lsb_mac_address;
@@ -876,7 +986,7 @@ struct tstorm_tcp_st_context_section {
u16 lsb_mac_address;
#endif
u32 msb_mac_address;
- u32 reserved2;
+ u32 rightmost_received_seq;
};
/*
@@ -951,7 +1061,7 @@ struct tstorm_iscsi_st_context_section {
u8 scratchpad_idx;
struct iscsi_term_vars term_vars;
#endif
- u32 reserved2;
+ u32 process_nxt;
};
/*
@@ -1174,24 +1284,12 @@ struct xstorm_iscsi_ag_context {
#endif
#if defined(__BIG_ENDIAN)
u8 cdu_reserved;
- u8 agg_vars4;
-#define XSTORM_ISCSI_AG_CONTEXT_R2TQ_PROD_CF (0x3<<0)
-#define XSTORM_ISCSI_AG_CONTEXT_R2TQ_PROD_CF_SHIFT 0
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX21_CF (0x3<<2)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX21_CF_SHIFT 2
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX18_CF_EN (0x1<<4)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX18_CF_EN_SHIFT 4
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX19_CF_EN (0x1<<5)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX19_CF_EN_SHIFT 5
-#define __XSTORM_ISCSI_AG_CONTEXT_R2TQ_PROD_CF_EN (0x1<<6)
-#define __XSTORM_ISCSI_AG_CONTEXT_R2TQ_PROD_CF_EN_SHIFT 6
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX21_CF_EN (0x1<<7)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX21_CF_EN_SHIFT 7
+ u8 __agg_vars4;
u8 agg_vars3;
#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM2 (0x3F<<0)
#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM2_SHIFT 0
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX19_CF (0x3<<6)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX19_CF_SHIFT 6
+#define __XSTORM_ISCSI_AG_CONTEXT_RX_TS_EN_CF (0x3<<6)
+#define __XSTORM_ISCSI_AG_CONTEXT_RX_TS_EN_CF_SHIFT 6
u8 agg_vars2;
#define __XSTORM_ISCSI_AG_CONTEXT_DQ_CF (0x3<<0)
#define __XSTORM_ISCSI_AG_CONTEXT_DQ_CF_SHIFT 0
@@ -1222,21 +1320,9 @@ struct xstorm_iscsi_ag_context {
u8 agg_vars3;
#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM2 (0x3F<<0)
#define XSTORM_ISCSI_AG_CONTEXT_PHYSICAL_QUEUE_NUM2_SHIFT 0
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX19_CF (0x3<<6)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX19_CF_SHIFT 6
- u8 agg_vars4;
-#define XSTORM_ISCSI_AG_CONTEXT_R2TQ_PROD_CF (0x3<<0)
-#define XSTORM_ISCSI_AG_CONTEXT_R2TQ_PROD_CF_SHIFT 0
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX21_CF (0x3<<2)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX21_CF_SHIFT 2
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX18_CF_EN (0x1<<4)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX18_CF_EN_SHIFT 4
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX19_CF_EN (0x1<<5)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX19_CF_EN_SHIFT 5
-#define __XSTORM_ISCSI_AG_CONTEXT_R2TQ_PROD_CF_EN (0x1<<6)
-#define __XSTORM_ISCSI_AG_CONTEXT_R2TQ_PROD_CF_EN_SHIFT 6
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX21_CF_EN (0x1<<7)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX21_CF_EN_SHIFT 7
+#define __XSTORM_ISCSI_AG_CONTEXT_RX_TS_EN_CF (0x3<<6)
+#define __XSTORM_ISCSI_AG_CONTEXT_RX_TS_EN_CF_SHIFT 6
+ u8 __agg_vars4;
u8 cdu_reserved;
#endif
u32 more_to_send;
@@ -1270,8 +1356,8 @@ struct xstorm_iscsi_ag_context {
#define __XSTORM_ISCSI_AG_CONTEXT_AGG_VAL11_DECISION_RULE_SHIFT 0
#define __XSTORM_ISCSI_AG_CONTEXT_AUX13_FLAG (0x1<<3)
#define __XSTORM_ISCSI_AG_CONTEXT_AUX13_FLAG_SHIFT 3
-#define XSTORM_ISCSI_AG_CONTEXT_AUX18_CF (0x3<<4)
-#define XSTORM_ISCSI_AG_CONTEXT_AUX18_CF_SHIFT 4
+#define __XSTORM_ISCSI_AG_CONTEXT_STORMS_SYNC_CF (0x3<<4)
+#define __XSTORM_ISCSI_AG_CONTEXT_STORMS_SYNC_CF_SHIFT 4
#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE3 (0x3<<6)
#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE3_SHIFT 6
#define XSTORM_ISCSI_AG_CONTEXT_AUX1_CF (0x3<<8)
@@ -1286,8 +1372,8 @@ struct xstorm_iscsi_ag_context {
#define __XSTORM_ISCSI_AG_CONTEXT_AUX11_FLAG_SHIFT 13
#define __XSTORM_ISCSI_AG_CONTEXT_AUX12_FLAG (0x1<<14)
#define __XSTORM_ISCSI_AG_CONTEXT_AUX12_FLAG_SHIFT 14
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX2_FLAG (0x1<<15)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX2_FLAG_SHIFT 15
+#define __XSTORM_ISCSI_AG_CONTEXT_RX_WND_SCL_EN (0x1<<15)
+#define __XSTORM_ISCSI_AG_CONTEXT_RX_WND_SCL_EN_SHIFT 15
u8 agg_val3_th;
u8 agg_vars6;
#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE6 (0x7<<0)
@@ -1310,8 +1396,8 @@ struct xstorm_iscsi_ag_context {
#define __XSTORM_ISCSI_AG_CONTEXT_AGG_VAL11_DECISION_RULE_SHIFT 0
#define __XSTORM_ISCSI_AG_CONTEXT_AUX13_FLAG (0x1<<3)
#define __XSTORM_ISCSI_AG_CONTEXT_AUX13_FLAG_SHIFT 3
-#define XSTORM_ISCSI_AG_CONTEXT_AUX18_CF (0x3<<4)
-#define XSTORM_ISCSI_AG_CONTEXT_AUX18_CF_SHIFT 4
+#define __XSTORM_ISCSI_AG_CONTEXT_STORMS_SYNC_CF (0x3<<4)
+#define __XSTORM_ISCSI_AG_CONTEXT_STORMS_SYNC_CF_SHIFT 4
#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE3 (0x3<<6)
#define XSTORM_ISCSI_AG_CONTEXT_DECISION_RULE3_SHIFT 6
#define XSTORM_ISCSI_AG_CONTEXT_AUX1_CF (0x3<<8)
@@ -1326,14 +1412,14 @@ struct xstorm_iscsi_ag_context {
#define __XSTORM_ISCSI_AG_CONTEXT_AUX11_FLAG_SHIFT 13
#define __XSTORM_ISCSI_AG_CONTEXT_AUX12_FLAG (0x1<<14)
#define __XSTORM_ISCSI_AG_CONTEXT_AUX12_FLAG_SHIFT 14
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX2_FLAG (0x1<<15)
-#define __XSTORM_ISCSI_AG_CONTEXT_AUX2_FLAG_SHIFT 15
+#define __XSTORM_ISCSI_AG_CONTEXT_RX_WND_SCL_EN (0x1<<15)
+#define __XSTORM_ISCSI_AG_CONTEXT_RX_WND_SCL_EN_SHIFT 15
#endif
#if defined(__BIG_ENDIAN)
u16 __agg_val11_th;
- u16 __agg_val11;
+ u16 __gen_data;
#elif defined(__LITTLE_ENDIAN)
- u16 __agg_val11;
+ u16 __gen_data;
u16 __agg_val11_th;
#endif
#if defined(__BIG_ENDIAN)
@@ -1384,7 +1470,7 @@ struct xstorm_iscsi_ag_context {
#endif
u32 hq_cons_tcp_seq;
u32 exp_stat_sn;
- u32 agg_misc5;
+ u32 rst_seq_num;
};
/*
@@ -1478,12 +1564,12 @@ struct tstorm_iscsi_ag_context {
#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX3_CF (0x3<<4)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX3_CF_SHIFT 4
+#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF (0x3<<4)
+#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_SHIFT 4
#define __TSTORM_ISCSI_AG_CONTEXT_AUX3_FLAG (0x1<<6)
#define __TSTORM_ISCSI_AG_CONTEXT_AUX3_FLAG_SHIFT 6
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX4_FLAG (0x1<<7)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX4_FLAG_SHIFT 7
+#define __TSTORM_ISCSI_AG_CONTEXT_ACK_ON_FIN_SENT_FLAG (0x1<<7)
+#define __TSTORM_ISCSI_AG_CONTEXT_ACK_ON_FIN_SENT_FLAG_SHIFT 7
u8 state;
#elif defined(__LITTLE_ENDIAN)
u8 state;
@@ -1496,63 +1582,63 @@ struct tstorm_iscsi_ag_context {
#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 2
#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<3)
#define TSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 3
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX3_CF (0x3<<4)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX3_CF_SHIFT 4
+#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF (0x3<<4)
+#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_SHIFT 4
#define __TSTORM_ISCSI_AG_CONTEXT_AUX3_FLAG (0x1<<6)
#define __TSTORM_ISCSI_AG_CONTEXT_AUX3_FLAG_SHIFT 6
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX4_FLAG (0x1<<7)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX4_FLAG_SHIFT 7
+#define __TSTORM_ISCSI_AG_CONTEXT_ACK_ON_FIN_SENT_FLAG (0x1<<7)
+#define __TSTORM_ISCSI_AG_CONTEXT_ACK_ON_FIN_SENT_FLAG_SHIFT 7
u16 ulp_credit;
#endif
#if defined(__BIG_ENDIAN)
u16 __agg_val4;
u16 agg_vars2;
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX5_FLAG (0x1<<0)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX5_FLAG_SHIFT 0
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX6_FLAG (0x1<<1)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX6_FLAG_SHIFT 1
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX4_CF (0x3<<2)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX4_CF_SHIFT 2
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX5_CF (0x3<<4)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX5_CF_SHIFT 4
+#define __TSTORM_ISCSI_AG_CONTEXT_MSL_TIMER_SET_FLAG (0x1<<0)
+#define __TSTORM_ISCSI_AG_CONTEXT_MSL_TIMER_SET_FLAG_SHIFT 0
+#define __TSTORM_ISCSI_AG_CONTEXT_FIN_SENT_FIRST_FLAG (0x1<<1)
+#define __TSTORM_ISCSI_AG_CONTEXT_FIN_SENT_FIRST_FLAG_SHIFT 1
+#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF (0x3<<2)
+#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_SHIFT 2
+#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF (0x3<<4)
+#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_SHIFT 4
#define __TSTORM_ISCSI_AG_CONTEXT_AUX6_CF (0x3<<6)
#define __TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_SHIFT 6
#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_CF (0x3<<8)
#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_SHIFT 8
#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_FLAG (0x1<<10)
#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_FLAG_SHIFT 10
-#define TSTORM_ISCSI_AG_CONTEXT_AUX3_CF_EN (0x1<<11)
-#define TSTORM_ISCSI_AG_CONTEXT_AUX3_CF_EN_SHIFT 11
-#define TSTORM_ISCSI_AG_CONTEXT_AUX4_CF_EN (0x1<<12)
-#define TSTORM_ISCSI_AG_CONTEXT_AUX4_CF_EN_SHIFT 12
-#define TSTORM_ISCSI_AG_CONTEXT_AUX5_CF_EN (0x1<<13)
-#define TSTORM_ISCSI_AG_CONTEXT_AUX5_CF_EN_SHIFT 13
+#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN (0x1<<11)
+#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN_SHIFT 11
+#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_EN (0x1<<12)
+#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_EN_SHIFT 12
+#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_EN (0x1<<13)
+#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_EN_SHIFT 13
#define TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_EN (0x1<<14)
#define TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_EN_SHIFT 14
#define TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_EN (0x1<<15)
#define TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_EN_SHIFT 15
#elif defined(__LITTLE_ENDIAN)
u16 agg_vars2;
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX5_FLAG (0x1<<0)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX5_FLAG_SHIFT 0
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX6_FLAG (0x1<<1)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX6_FLAG_SHIFT 1
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX4_CF (0x3<<2)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX4_CF_SHIFT 2
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX5_CF (0x3<<4)
-#define __TSTORM_ISCSI_AG_CONTEXT_AUX5_CF_SHIFT 4
+#define __TSTORM_ISCSI_AG_CONTEXT_MSL_TIMER_SET_FLAG (0x1<<0)
+#define __TSTORM_ISCSI_AG_CONTEXT_MSL_TIMER_SET_FLAG_SHIFT 0
+#define __TSTORM_ISCSI_AG_CONTEXT_FIN_SENT_FIRST_FLAG (0x1<<1)
+#define __TSTORM_ISCSI_AG_CONTEXT_FIN_SENT_FIRST_FLAG_SHIFT 1
+#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF (0x3<<2)
+#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_SHIFT 2
+#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF (0x3<<4)
+#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_SHIFT 4
#define __TSTORM_ISCSI_AG_CONTEXT_AUX6_CF (0x3<<6)
#define __TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_SHIFT 6
#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_CF (0x3<<8)
#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_SHIFT 8
#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_FLAG (0x1<<10)
#define __TSTORM_ISCSI_AG_CONTEXT_AUX7_FLAG_SHIFT 10
-#define TSTORM_ISCSI_AG_CONTEXT_AUX3_CF_EN (0x1<<11)
-#define TSTORM_ISCSI_AG_CONTEXT_AUX3_CF_EN_SHIFT 11
-#define TSTORM_ISCSI_AG_CONTEXT_AUX4_CF_EN (0x1<<12)
-#define TSTORM_ISCSI_AG_CONTEXT_AUX4_CF_EN_SHIFT 12
-#define TSTORM_ISCSI_AG_CONTEXT_AUX5_CF_EN (0x1<<13)
-#define TSTORM_ISCSI_AG_CONTEXT_AUX5_CF_EN_SHIFT 13
+#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN (0x1<<11)
+#define __TSTORM_ISCSI_AG_CONTEXT_QUEUES_FLUSH_Q0_CF_EN_SHIFT 11
+#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_EN (0x1<<12)
+#define __TSTORM_ISCSI_AG_CONTEXT_RST_SENT_CF_EN_SHIFT 12
+#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_EN (0x1<<13)
+#define __TSTORM_ISCSI_AG_CONTEXT_WAKEUP_CALL_CF_EN_SHIFT 13
#define TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_EN (0x1<<14)
#define TSTORM_ISCSI_AG_CONTEXT_AUX6_CF_EN_SHIFT 14
#define TSTORM_ISCSI_AG_CONTEXT_AUX7_CF_EN (0x1<<15)
@@ -1563,100 +1649,6 @@ struct tstorm_iscsi_ag_context {
};
/*
- * The iscsi aggregative context of Cstorm
- */
-struct cstorm_iscsi_ag_context {
- u32 agg_vars1;
-#define CSTORM_ISCSI_AG_CONTEXT_STATE (0xFF<<0)
-#define CSTORM_ISCSI_AG_CONTEXT_STATE_SHIFT 0
-#define __CSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0 (0x1<<8)
-#define __CSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM0_SHIFT 8
-#define __CSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1 (0x1<<9)
-#define __CSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM1_SHIFT 9
-#define __CSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2 (0x1<<10)
-#define __CSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM2_SHIFT 10
-#define __CSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3 (0x1<<11)
-#define __CSTORM_ISCSI_AG_CONTEXT_EXISTS_IN_QM3_SHIFT 11
-#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED_ULP_RX_SE_CF_EN (0x1<<12)
-#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED_ULP_RX_SE_CF_EN_SHIFT 12
-#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED_ULP_RX_INV_CF_EN (0x1<<13)
-#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED_ULP_RX_INV_CF_EN_SHIFT 13
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION3_CF (0x3<<14)
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION3_CF_SHIFT 14
-#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED66 (0x3<<16)
-#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED66_SHIFT 16
-#define __CSTORM_ISCSI_AG_CONTEXT_FIN_RECEIVED_CF_EN (0x1<<18)
-#define __CSTORM_ISCSI_AG_CONTEXT_FIN_RECEIVED_CF_EN_SHIFT 18
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION0_CF_EN (0x1<<19)
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION0_CF_EN_SHIFT 19
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION1_CF_EN (0x1<<20)
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION1_CF_EN_SHIFT 20
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION2_CF_EN (0x1<<21)
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION2_CF_EN_SHIFT 21
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION3_CF_EN (0x1<<22)
-#define __CSTORM_ISCSI_AG_CONTEXT_PENDING_COMPLETION3_CF_EN_SHIFT 22
-#define __CSTORM_ISCSI_AG_CONTEXT_REL_SEQ_RULE (0x7<<23)
-#define __CSTORM_ISCSI_AG_CONTEXT_REL_SEQ_RULE_SHIFT 23
-#define CSTORM_ISCSI_AG_CONTEXT_HQ_PROD_RULE (0x3<<26)
-#define CSTORM_ISCSI_AG_CONTEXT_HQ_PROD_RULE_SHIFT 26
-#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED52 (0x3<<28)
-#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED52_SHIFT 28
-#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED53 (0x3<<30)
-#define __CSTORM_ISCSI_AG_CONTEXT_RESERVED53_SHIFT 30
-#if defined(__BIG_ENDIAN)
- u8 __aux1_th;
- u8 __aux1_val;
- u16 __agg_vars2;
-#elif defined(__LITTLE_ENDIAN)
- u16 __agg_vars2;
- u8 __aux1_val;
- u8 __aux1_th;
-#endif
- u32 rel_seq;
- u32 rel_seq_th;
-#if defined(__BIG_ENDIAN)
- u16 hq_cons;
- u16 hq_prod;
-#elif defined(__LITTLE_ENDIAN)
- u16 hq_prod;
- u16 hq_cons;
-#endif
-#if defined(__BIG_ENDIAN)
- u8 __reserved62;
- u8 __reserved61;
- u8 __reserved60;
- u8 __reserved59;
-#elif defined(__LITTLE_ENDIAN)
- u8 __reserved59;
- u8 __reserved60;
- u8 __reserved61;
- u8 __reserved62;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 __reserved64;
- u16 __cq_u_prod0;
-#elif defined(__LITTLE_ENDIAN)
- u16 __cq_u_prod0;
- u16 __reserved64;
-#endif
- u32 __cq_u_prod1;
-#if defined(__BIG_ENDIAN)
- u16 __agg_vars3;
- u16 __cq_u_prod2;
-#elif defined(__LITTLE_ENDIAN)
- u16 __cq_u_prod2;
- u16 __agg_vars3;
-#endif
-#if defined(__BIG_ENDIAN)
- u16 __aux2_th;
- u16 __cq_u_prod3;
-#elif defined(__LITTLE_ENDIAN)
- u16 __cq_u_prod3;
- u16 __aux2_th;
-#endif
-};
-
-/*
* The iscsi aggregative context of Ustorm
*/
struct ustorm_iscsi_ag_context {
@@ -1746,8 +1738,8 @@ struct ustorm_iscsi_ag_context {
#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_RULE_SHIFT 0
#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL3_RULE (0x7<<3)
#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL3_RULE_SHIFT 3
-#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_ARM_N_FLAG (0x1<<6)
-#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_ARM_N_FLAG_SHIFT 6
+#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_ARM_N_FLAG (0x1<<6)
+#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_ARM_N_FLAG_SHIFT 6
#define __USTORM_ISCSI_AG_CONTEXT_RESERVED1 (0x1<<7)
#define __USTORM_ISCSI_AG_CONTEXT_RESERVED1_SHIFT 7
u8 decision_rule_enable_bits;
@@ -1790,8 +1782,8 @@ struct ustorm_iscsi_ag_context {
#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_RULE_SHIFT 0
#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL3_RULE (0x7<<3)
#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL3_RULE_SHIFT 3
-#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_ARM_N_FLAG (0x1<<6)
-#define __USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_ARM_N_FLAG_SHIFT 6
+#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_ARM_N_FLAG (0x1<<6)
+#define USTORM_ISCSI_AG_CONTEXT_AGG_VAL2_ARM_N_FLAG_SHIFT 6
#define __USTORM_ISCSI_AG_CONTEXT_RESERVED1 (0x1<<7)
#define __USTORM_ISCSI_AG_CONTEXT_RESERVED1_SHIFT 7
u16 __reserved2;
@@ -1799,22 +1791,6 @@ struct ustorm_iscsi_ag_context {
};
/*
- * Timers connection context
- */
-struct iscsi_timers_block_context {
- u32 __reserved_0;
- u32 __reserved_1;
- u32 __reserved_2;
- u32 flags;
-#define __ISCSI_TIMERS_BLOCK_CONTEXT_NUM_OF_ACTIVE_TIMERS (0x3<<0)
-#define __ISCSI_TIMERS_BLOCK_CONTEXT_NUM_OF_ACTIVE_TIMERS_SHIFT 0
-#define ISCSI_TIMERS_BLOCK_CONTEXT_CONN_VALID_FLG (0x1<<2)
-#define ISCSI_TIMERS_BLOCK_CONTEXT_CONN_VALID_FLG_SHIFT 2
-#define __ISCSI_TIMERS_BLOCK_CONTEXT_RESERVED0 (0x1FFFFFFF<<3)
-#define __ISCSI_TIMERS_BLOCK_CONTEXT_RESERVED0_SHIFT 3
-};
-
-/*
* Ethernet context section, shared in TOE, RDMA and ISCSI
*/
struct xstorm_eth_context_section {
@@ -1963,7 +1939,7 @@ struct xstorm_tcp_context_section {
#endif
#if defined(__BIG_ENDIAN)
u8 original_nagle_1b;
- u8 ts_enabled_1b;
+ u8 ts_enabled;
u16 tcp_params;
#define XSTORM_TCP_CONTEXT_SECTION_TOTAL_HEADER_SIZE (0xFF<<0)
#define XSTORM_TCP_CONTEXT_SECTION_TOTAL_HEADER_SIZE_SHIFT 0
@@ -1973,8 +1949,8 @@ struct xstorm_tcp_context_section {
#define __XSTORM_TCP_CONTEXT_SECTION_ECN_ENABLED_SHIFT 9
#define XSTORM_TCP_CONTEXT_SECTION_SACK_ENABLED (0x1<<10)
#define XSTORM_TCP_CONTEXT_SECTION_SACK_ENABLED_SHIFT 10
-#define XSTORM_TCP_CONTEXT_SECTION_KA_STATE (0x1<<11)
-#define XSTORM_TCP_CONTEXT_SECTION_KA_STATE_SHIFT 11
+#define XSTORM_TCP_CONTEXT_SECTION_SMALL_WIN_ADV (0x1<<11)
+#define XSTORM_TCP_CONTEXT_SECTION_SMALL_WIN_ADV_SHIFT 11
#define XSTORM_TCP_CONTEXT_SECTION_FIN_SENT_FLAG (0x1<<12)
#define XSTORM_TCP_CONTEXT_SECTION_FIN_SENT_FLAG_SHIFT 12
#define XSTORM_TCP_CONTEXT_SECTION_WINDOW_SATURATED (0x1<<13)
@@ -1991,15 +1967,15 @@ struct xstorm_tcp_context_section {
#define __XSTORM_TCP_CONTEXT_SECTION_ECN_ENABLED_SHIFT 9
#define XSTORM_TCP_CONTEXT_SECTION_SACK_ENABLED (0x1<<10)
#define XSTORM_TCP_CONTEXT_SECTION_SACK_ENABLED_SHIFT 10
-#define XSTORM_TCP_CONTEXT_SECTION_KA_STATE (0x1<<11)
-#define XSTORM_TCP_CONTEXT_SECTION_KA_STATE_SHIFT 11
+#define XSTORM_TCP_CONTEXT_SECTION_SMALL_WIN_ADV (0x1<<11)
+#define XSTORM_TCP_CONTEXT_SECTION_SMALL_WIN_ADV_SHIFT 11
#define XSTORM_TCP_CONTEXT_SECTION_FIN_SENT_FLAG (0x1<<12)
#define XSTORM_TCP_CONTEXT_SECTION_FIN_SENT_FLAG_SHIFT 12
#define XSTORM_TCP_CONTEXT_SECTION_WINDOW_SATURATED (0x1<<13)
#define XSTORM_TCP_CONTEXT_SECTION_WINDOW_SATURATED_SHIFT 13
#define XSTORM_TCP_CONTEXT_SECTION_SLOWPATH_QUEUES_FLUSH_COUNTER (0x3<<14)
#define XSTORM_TCP_CONTEXT_SECTION_SLOWPATH_QUEUES_FLUSH_COUNTER_SHIFT 14
- u8 ts_enabled_1b;
+ u8 ts_enabled;
u8 original_nagle_1b;
#endif
#if defined(__BIG_ENDIAN)
@@ -2030,8 +2006,8 @@ struct xstorm_common_context_section {
#define XSTORM_COMMON_CONTEXT_SECTION_UPDATE_L4_STATSTICS_SHIFT 1
#define XSTORM_COMMON_CONTEXT_SECTION_STATISTICS_COUNTER_ID (0x1F<<2)
#define XSTORM_COMMON_CONTEXT_SECTION_STATISTICS_COUNTER_ID_SHIFT 2
-#define XSTORM_COMMON_CONTEXT_SECTION_RESERVED0 (0x1<<7)
-#define XSTORM_COMMON_CONTEXT_SECTION_RESERVED0_SHIFT 7
+#define XSTORM_COMMON_CONTEXT_SECTION_DCB_EXISTS (0x1<<7)
+#define XSTORM_COMMON_CONTEXT_SECTION_DCB_EXISTS_SHIFT 7
u8 ip_version_1b;
#elif defined(__LITTLE_ENDIAN)
u8 ip_version_1b;
@@ -2042,8 +2018,8 @@ struct xstorm_common_context_section {
#define XSTORM_COMMON_CONTEXT_SECTION_UPDATE_L4_STATSTICS_SHIFT 1
#define XSTORM_COMMON_CONTEXT_SECTION_STATISTICS_COUNTER_ID (0x1F<<2)
#define XSTORM_COMMON_CONTEXT_SECTION_STATISTICS_COUNTER_ID_SHIFT 2
-#define XSTORM_COMMON_CONTEXT_SECTION_RESERVED0 (0x1<<7)
-#define XSTORM_COMMON_CONTEXT_SECTION_RESERVED0_SHIFT 7
+#define XSTORM_COMMON_CONTEXT_SECTION_DCB_EXISTS (0x1<<7)
+#define XSTORM_COMMON_CONTEXT_SECTION_DCB_EXISTS_SHIFT 7
u16 reserved;
#endif
};
@@ -2284,7 +2260,7 @@ struct iscsi_context {
struct tstorm_iscsi_ag_context tstorm_ag_context;
struct cstorm_iscsi_ag_context cstorm_ag_context;
struct ustorm_iscsi_ag_context ustorm_ag_context;
- struct iscsi_timers_block_context timers_context;
+ struct timers_block_context timers_context;
struct regpair upb_context;
struct xstorm_iscsi_st_context xstorm_st_context;
struct regpair xpb_context;
@@ -2434,16 +2410,16 @@ struct l5cm_packet_size {
* l5cm connection parameters
*/
union l5cm_reduce_param_union {
- u32 passive_side_scramble_key;
- u32 pcs_id;
+ u32 opaque1;
+ u32 opaque2;
};
/*
* l5cm connection parameters
*/
struct l5cm_reduce_conn {
- union l5cm_reduce_param_union param;
- u32 isn;
+ union l5cm_reduce_param_union opaque1;
+ u32 opaque2;
};
/*
diff --git a/drivers/net/cnic_if.h b/drivers/net/cnic_if.h
index 344c842d55ab..0dbeaec4f03a 100644
--- a/drivers/net/cnic_if.h
+++ b/drivers/net/cnic_if.h
@@ -12,8 +12,8 @@
#ifndef CNIC_IF_H
#define CNIC_IF_H
-#define CNIC_MODULE_VERSION "2.1.3"
-#define CNIC_MODULE_RELDATE "June 24, 2010"
+#define CNIC_MODULE_VERSION "2.2.6"
+#define CNIC_MODULE_RELDATE "Oct 12, 2010"
#define CNIC_ULP_RDMA 0
#define CNIC_ULP_ISCSI 1
@@ -80,18 +80,15 @@ struct kcqe {
#define DRV_CTL_IO_RD_CMD 0x102
#define DRV_CTL_CTX_WR_CMD 0x103
#define DRV_CTL_CTXTBL_WR_CMD 0x104
-#define DRV_CTL_COMPLETION_CMD 0x105
+#define DRV_CTL_RET_L5_SPQ_CREDIT_CMD 0x105
#define DRV_CTL_START_L2_CMD 0x106
#define DRV_CTL_STOP_L2_CMD 0x107
+#define DRV_CTL_RET_L2_SPQ_CREDIT_CMD 0x10c
struct cnic_ctl_completion {
u32 cid;
};
-struct drv_ctl_completion {
- u32 comp_count;
-};
-
struct cnic_ctl_info {
int cmd;
union {
@@ -100,6 +97,10 @@ struct cnic_ctl_info {
} data;
};
+struct drv_ctl_spq_credit {
+ u32 credit_count;
+};
+
struct drv_ctl_io {
u32 cid_addr;
u32 offset;
@@ -115,7 +116,7 @@ struct drv_ctl_l2_ring {
struct drv_ctl_info {
int cmd;
union {
- struct drv_ctl_completion comp;
+ struct drv_ctl_spq_credit credit;
struct drv_ctl_io io;
struct drv_ctl_l2_ring ring;
char bytes[MAX_DRV_CTL_DATA];
@@ -138,6 +139,7 @@ struct cnic_irq {
unsigned int vector;
void *status_blk;
u32 status_blk_num;
+ u32 status_blk_num2;
u32 irq_flags;
#define CNIC_IRQ_FL_MSIX 0x00000001
};
@@ -152,6 +154,7 @@ struct cnic_eth_dev {
struct pci_dev *pdev;
void __iomem *io_base;
void __iomem *io_base2;
+ void *iro_arr;
u32 ctx_tbl_offset;
u32 ctx_tbl_len;
@@ -160,7 +163,9 @@ struct cnic_eth_dev {
u32 max_iscsi_conn;
u32 max_fcoe_conn;
u32 max_rdma_conn;
- u32 reserved0[2];
+ u32 fcoe_init_cid;
+ u16 iscsi_l2_client_id;
+ u16 iscsi_l2_cid;
int num_irq;
struct cnic_irq irq_arr[MAX_CNIC_VEC];
diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c
index e1f6156b3710..fec939f8f65f 100644
--- a/drivers/net/cpmac.c
+++ b/drivers/net/cpmac.c
@@ -38,7 +38,7 @@
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/clk.h>
-#include <asm/gpio.h>
+#include <linux/gpio.h>
#include <asm/atomic.h>
MODULE_AUTHOR("Eugene Konev <ejka@imfi.kspu.ru>");
@@ -108,7 +108,7 @@ MODULE_PARM_DESC(dumb_switch, "Assume switch is not connected to MDIO bus");
#define CPMAC_RX_INT_CLEAR 0x019c
#define CPMAC_MAC_INT_ENABLE 0x01a8
#define CPMAC_MAC_INT_CLEAR 0x01ac
-#define CPMAC_MAC_ADDR_LO(channel) (0x01b0 + (channel) * 4)
+#define CPMAC_MAC_ADDR_LO(channel) (0x01b0 + (channel) * 4)
#define CPMAC_MAC_ADDR_MID 0x01d0
#define CPMAC_MAC_ADDR_HI 0x01d4
#define CPMAC_MAC_HASH_LO 0x01d8
@@ -227,7 +227,7 @@ static void cpmac_dump_regs(struct net_device *dev)
for (i = 0; i < CPMAC_REG_END; i += 4) {
if (i % 16 == 0) {
if (i)
- printk("\n");
+ pr_cont("\n");
printk(KERN_DEBUG "%s: reg[%p]:", dev->name,
priv->regs + i);
}
@@ -262,7 +262,7 @@ static void cpmac_dump_skb(struct net_device *dev, struct sk_buff *skb)
for (i = 0; i < skb->len; i++) {
if (i % 16 == 0) {
if (i)
- printk("\n");
+ pr_cont("\n");
printk(KERN_DEBUG "%s: data[%p]:", dev->name,
skb->data + i);
}
@@ -391,7 +391,7 @@ static struct sk_buff *cpmac_rx_one(struct cpmac_priv *priv,
if (likely(skb)) {
skb_put(desc->skb, desc->datalen);
desc->skb->protocol = eth_type_trans(desc->skb, priv->dev);
- desc->skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(desc->skb);
priv->dev->stats.rx_packets++;
priv->dev->stats.rx_bytes += desc->datalen;
result = desc->skb;
@@ -506,7 +506,7 @@ static int cpmac_poll(struct napi_struct *napi, int budget)
"restart rx from a descriptor that's "
"not free: %p\n",
priv->dev->name, restart);
- goto fatal_error;
+ goto fatal_error;
}
cpmac_write(priv->regs, CPMAC_RX_PTR(0), restart->mapping);
@@ -873,7 +873,8 @@ static int cpmac_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
return -EINVAL;
}
-static void cpmac_get_ringparam(struct net_device *dev, struct ethtool_ringparam* ring)
+static void cpmac_get_ringparam(struct net_device *dev,
+ struct ethtool_ringparam *ring)
{
struct cpmac_priv *priv = netdev_priv(dev);
@@ -888,7 +889,8 @@ static void cpmac_get_ringparam(struct net_device *dev, struct ethtool_ringparam
ring->tx_pending = 1;
}
-static int cpmac_set_ringparam(struct net_device *dev, struct ethtool_ringparam* ring)
+static int cpmac_set_ringparam(struct net_device *dev,
+ struct ethtool_ringparam *ring)
{
struct cpmac_priv *priv = netdev_priv(dev);
@@ -1012,8 +1014,8 @@ static int cpmac_open(struct net_device *dev)
priv->rx_head->prev->hw_next = (u32)0;
- if ((res = request_irq(dev->irq, cpmac_irq, IRQF_SHARED,
- dev->name, dev))) {
+ res = request_irq(dev->irq, cpmac_irq, IRQF_SHARED, dev->name, dev);
+ if (res) {
if (netif_msg_drv(priv))
printk(KERN_ERR "%s: failed to obtain irq\n",
dev->name);
@@ -1133,7 +1135,8 @@ static int __devinit cpmac_probe(struct platform_device *pdev)
}
if (phy_id == PHY_MAX_ADDR) {
- dev_err(&pdev->dev, "no PHY present, falling back to switch on MDIO bus 0\n");
+ dev_err(&pdev->dev, "no PHY present, falling back "
+ "to switch on MDIO bus 0\n");
strncpy(mdio_bus_id, "0", MII_BUS_ID_SIZE); /* fixed phys bus */
phy_id = pdev->id;
}
@@ -1169,9 +1172,10 @@ static int __devinit cpmac_probe(struct platform_device *pdev)
priv->msg_enable = netif_msg_init(debug_level, 0xff);
memcpy(dev->dev_addr, pdata->dev_addr, sizeof(pdata->dev_addr));
- snprintf(priv->phy_name, MII_BUS_ID_SIZE, PHY_ID_FMT, mdio_bus_id, phy_id);
+ snprintf(priv->phy_name, MII_BUS_ID_SIZE, PHY_ID_FMT,
+ mdio_bus_id, phy_id);
- priv->phy = phy_connect(dev, priv->phy_name, &cpmac_adjust_link, 0,
+ priv->phy = phy_connect(dev, priv->phy_name, cpmac_adjust_link, 0,
PHY_INTERFACE_MODE_MII);
if (IS_ERR(priv->phy)) {
@@ -1182,7 +1186,8 @@ static int __devinit cpmac_probe(struct platform_device *pdev)
goto fail;
}
- if ((rc = register_netdev(dev))) {
+ rc = register_netdev(dev);
+ if (rc) {
printk(KERN_ERR "cpmac: error %i registering device %s\n", rc,
dev->name);
goto fail;
@@ -1248,11 +1253,13 @@ int __devinit cpmac_init(void)
cpmac_mii->reset(cpmac_mii);
- for (i = 0; i < 300; i++)
- if ((mask = cpmac_read(cpmac_mii->priv, CPMAC_MDIO_ALIVE)))
+ for (i = 0; i < 300; i++) {
+ mask = cpmac_read(cpmac_mii->priv, CPMAC_MDIO_ALIVE);
+ if (mask)
break;
else
msleep(10);
+ }
mask &= 0x7fffffff;
if (mask & (mask - 1)) {
diff --git a/drivers/net/cxgb3/adapter.h b/drivers/net/cxgb3/adapter.h
index 4cd7f420766a..ef67be59680f 100644
--- a/drivers/net/cxgb3/adapter.h
+++ b/drivers/net/cxgb3/adapter.h
@@ -336,9 +336,6 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports,
int irq_vec_idx, const struct qset_params *p,
int ntxq, struct net_device *dev,
struct netdev_queue *netdevq);
-int t3_get_desc(const struct sge_qset *qs, unsigned int qnum, unsigned int idx,
- unsigned char *data);
-irqreturn_t t3_sge_intr_msix(int irq, void *cookie);
extern struct workqueue_struct *cxgb3_wq;
int t3_get_edc_fw(struct cphy *phy, int edc_idx, int size);
diff --git a/drivers/net/cxgb3/common.h b/drivers/net/cxgb3/common.h
index fe08a004b0dd..5ccb77d078aa 100644
--- a/drivers/net/cxgb3/common.h
+++ b/drivers/net/cxgb3/common.h
@@ -673,7 +673,6 @@ void t3_xgm_intr_enable(struct adapter *adapter, int idx);
void t3_xgm_intr_disable(struct adapter *adapter, int idx);
void t3_port_intr_enable(struct adapter *adapter, int idx);
void t3_port_intr_disable(struct adapter *adapter, int idx);
-void t3_port_intr_clear(struct adapter *adapter, int idx);
int t3_slow_intr_handler(struct adapter *adapter);
int t3_phy_intr_handler(struct adapter *adapter);
@@ -689,14 +688,10 @@ int t3_check_tpsram_version(struct adapter *adapter);
int t3_check_tpsram(struct adapter *adapter, const u8 *tp_ram,
unsigned int size);
int t3_set_proto_sram(struct adapter *adap, const u8 *data);
-int t3_read_flash(struct adapter *adapter, unsigned int addr,
- unsigned int nwords, u32 *data, int byte_oriented);
int t3_load_fw(struct adapter *adapter, const u8 * fw_data, unsigned int size);
int t3_get_fw_version(struct adapter *adapter, u32 *vers);
int t3_check_fw_version(struct adapter *adapter);
int t3_init_hw(struct adapter *adapter, u32 fw_params);
-void mac_prep(struct cmac *mac, struct adapter *adapter, int index);
-void early_hw_init(struct adapter *adapter, const struct adapter_info *ai);
int t3_reset_adapter(struct adapter *adapter);
int t3_prep_adapter(struct adapter *adapter, const struct adapter_info *ai,
int reset);
@@ -706,8 +701,6 @@ void t3_fatal_err(struct adapter *adapter);
void t3_set_vlan_accel(struct adapter *adapter, unsigned int ports, int on);
void t3_config_rss(struct adapter *adapter, unsigned int rss_config,
const u8 * cpus, const u16 *rspq);
-int t3_read_rss(struct adapter *adapter, u8 * lkup, u16 *map);
-int t3_mps_set_active_ports(struct adapter *adap, unsigned int port_mask);
int t3_cim_ctl_blk_read(struct adapter *adap, unsigned int addr,
unsigned int n, unsigned int *valp);
int t3_mc7_bd_read(struct mc7 *mc7, unsigned int start, unsigned int n,
@@ -731,19 +724,12 @@ void t3_mc5_prep(struct adapter *adapter, struct mc5 *mc5, int mode);
int t3_mc5_init(struct mc5 *mc5, unsigned int nservers, unsigned int nfilters,
unsigned int nroutes);
void t3_mc5_intr_handler(struct mc5 *mc5);
-int t3_read_mc5_range(const struct mc5 *mc5, unsigned int start, unsigned int n,
- u32 *buf);
-int t3_tp_set_coalescing_size(struct adapter *adap, unsigned int size, int psh);
-void t3_tp_set_max_rxsize(struct adapter *adap, unsigned int size);
void t3_tp_set_offload_mode(struct adapter *adap, int enable);
void t3_tp_get_mib_stats(struct adapter *adap, struct tp_mib_stats *tps);
void t3_load_mtus(struct adapter *adap, unsigned short mtus[NMTUS],
unsigned short alpha[NCCTRL_WIN],
unsigned short beta[NCCTRL_WIN], unsigned short mtu_cap);
-void t3_read_hw_mtus(struct adapter *adap, unsigned short mtus[NMTUS]);
-void t3_get_cong_cntl_tab(struct adapter *adap,
- unsigned short incr[NMTUS][NCCTRL_WIN]);
void t3_config_trace_filter(struct adapter *adapter,
const struct trace_params *tp, int filter_index,
int invert, int enable);
@@ -769,10 +755,6 @@ int t3_sge_enable_ecntxt(struct adapter *adapter, unsigned int id, int enable);
int t3_sge_disable_fl(struct adapter *adapter, unsigned int id);
int t3_sge_disable_rspcntxt(struct adapter *adapter, unsigned int id);
int t3_sge_disable_cqcntxt(struct adapter *adapter, unsigned int id);
-int t3_sge_read_ecntxt(struct adapter *adapter, unsigned int id, u32 data[4]);
-int t3_sge_read_fl(struct adapter *adapter, unsigned int id, u32 data[4]);
-int t3_sge_read_cq(struct adapter *adapter, unsigned int id, u32 data[4]);
-int t3_sge_read_rspq(struct adapter *adapter, unsigned int id, u32 data[4]);
int t3_sge_cqcntxt_op(struct adapter *adapter, unsigned int id, unsigned int op,
unsigned int credits);
diff --git a/drivers/net/cxgb3/cxgb3_defs.h b/drivers/net/cxgb3/cxgb3_defs.h
index 47e53769af5b..920d918ed193 100644
--- a/drivers/net/cxgb3/cxgb3_defs.h
+++ b/drivers/net/cxgb3/cxgb3_defs.h
@@ -43,8 +43,6 @@
void *cxgb_alloc_mem(unsigned long size);
void cxgb_free_mem(void *addr);
-void cxgb_neigh_update(struct neighbour *neigh);
-void cxgb_redirect(struct dst_entry *old, struct dst_entry *new);
/*
* Map an ATID or STID to their entries in the corresponding TID tables.
@@ -111,7 +109,6 @@ static inline struct t3c_tid_entry *lookup_atid(const struct tid_info *t,
return &e->t3c_tid;
}
-int process_rx(struct t3cdev *dev, struct sk_buff **skbs, int n);
int attach_t3cdev(struct t3cdev *dev);
void detach_t3cdev(struct t3cdev *dev);
#endif
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c
index f208712c0b90..a04ce6a5f637 100644
--- a/drivers/net/cxgb3/cxgb3_main.c
+++ b/drivers/net/cxgb3/cxgb3_main.c
@@ -1286,7 +1286,7 @@ irq_err:
/*
* Release resources when all the ports and offloading have been stopped.
*/
-static void cxgb_down(struct adapter *adapter)
+static void cxgb_down(struct adapter *adapter, int on_wq)
{
t3_sge_stop(adapter);
spin_lock_irq(&adapter->work_lock); /* sync with PHY intr task */
@@ -1296,7 +1296,8 @@ static void cxgb_down(struct adapter *adapter)
free_irq_resources(adapter);
quiesce_rx(adapter);
t3_sge_stop(adapter);
- flush_workqueue(cxgb3_wq); /* wait for external IRQ handler */
+ if (!on_wq)
+ flush_workqueue(cxgb3_wq);/* wait for external IRQ handler */
}
static void schedule_chk_task(struct adapter *adap)
@@ -1374,7 +1375,7 @@ static int offload_close(struct t3cdev *tdev)
clear_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map);
if (!adapter->open_device_map)
- cxgb_down(adapter);
+ cxgb_down(adapter, 0);
cxgb3_offload_deactivate(adapter);
return 0;
@@ -1398,7 +1399,10 @@ static int cxgb_open(struct net_device *dev)
"Could not initialize offload capabilities\n");
}
- dev->real_num_tx_queues = pi->nqsets;
+ netif_set_real_num_tx_queues(dev, pi->nqsets);
+ err = netif_set_real_num_rx_queues(dev, pi->nqsets);
+ if (err)
+ return err;
link_start(dev);
t3_port_intr_enable(adapter, pi->port_id);
netif_tx_start_all_queues(dev);
@@ -1409,7 +1413,7 @@ static int cxgb_open(struct net_device *dev)
return 0;
}
-static int cxgb_close(struct net_device *dev)
+static int __cxgb_close(struct net_device *dev, int on_wq)
{
struct port_info *pi = netdev_priv(dev);
struct adapter *adapter = pi->adapter;
@@ -1436,12 +1440,17 @@ static int cxgb_close(struct net_device *dev)
cancel_delayed_work_sync(&adapter->adap_check_task);
if (!adapter->open_device_map)
- cxgb_down(adapter);
+ cxgb_down(adapter, on_wq);
cxgb3_event_notify(&adapter->tdev, OFFLOAD_PORT_DOWN, pi->port_id);
return 0;
}
+static int cxgb_close(struct net_device *dev)
+{
+ return __cxgb_close(dev, 0);
+}
+
static struct net_device_stats *cxgb_get_stats(struct net_device *dev)
{
struct port_info *pi = netdev_priv(dev);
@@ -2864,7 +2873,7 @@ void t3_os_link_fault_handler(struct adapter *adapter, int port_id)
spin_unlock(&adapter->work_lock);
}
-static int t3_adapter_error(struct adapter *adapter, int reset)
+static int t3_adapter_error(struct adapter *adapter, int reset, int on_wq)
{
int i, ret = 0;
@@ -2879,7 +2888,7 @@ static int t3_adapter_error(struct adapter *adapter, int reset)
struct net_device *netdev = adapter->port[i];
if (netif_running(netdev))
- cxgb_close(netdev);
+ __cxgb_close(netdev, on_wq);
}
/* Stop SGE timers */
@@ -2950,7 +2959,7 @@ static void fatal_error_task(struct work_struct *work)
int err = 0;
rtnl_lock();
- err = t3_adapter_error(adapter, 1);
+ err = t3_adapter_error(adapter, 1, 1);
if (!err)
err = t3_reenable_adapter(adapter);
if (!err)
@@ -3000,7 +3009,7 @@ static pci_ers_result_t t3_io_error_detected(struct pci_dev *pdev,
if (state == pci_channel_io_perm_failure)
return PCI_ERS_RESULT_DISCONNECT;
- ret = t3_adapter_error(adapter, 0);
+ ret = t3_adapter_error(adapter, 0, 0);
/* Request a slot reset. */
return PCI_ERS_RESULT_NEED_RESET;
diff --git a/drivers/net/cxgb3/cxgb3_offload.c b/drivers/net/cxgb3/cxgb3_offload.c
index c6485b39eb0e..bcf07532953d 100644
--- a/drivers/net/cxgb3/cxgb3_offload.c
+++ b/drivers/net/cxgb3/cxgb3_offload.c
@@ -60,11 +60,14 @@ static LIST_HEAD(adapter_list);
static const unsigned int MAX_ATIDS = 64 * 1024;
static const unsigned int ATID_BASE = 0x10000;
+static void cxgb_neigh_update(struct neighbour *neigh);
+static void cxgb_redirect(struct dst_entry *old, struct dst_entry *new);
+
static inline int offload_activated(struct t3cdev *tdev)
{
const struct adapter *adapter = tdev2adap(tdev);
- return (test_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map));
+ return test_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map);
}
/**
@@ -1015,7 +1018,7 @@ EXPORT_SYMBOL(t3_register_cpl_handler);
/*
* T3CDEV's receive method.
*/
-int process_rx(struct t3cdev *dev, struct sk_buff **skbs, int n)
+static int process_rx(struct t3cdev *dev, struct sk_buff **skbs, int n)
{
while (n--) {
struct sk_buff *skb = *skbs++;
@@ -1070,7 +1073,7 @@ static int is_offloading(struct net_device *dev)
return 0;
}
-void cxgb_neigh_update(struct neighbour *neigh)
+static void cxgb_neigh_update(struct neighbour *neigh)
{
struct net_device *dev = neigh->dev;
@@ -1104,7 +1107,7 @@ static void set_l2t_ix(struct t3cdev *tdev, u32 tid, struct l2t_entry *e)
tdev->send(tdev, skb);
}
-void cxgb_redirect(struct dst_entry *old, struct dst_entry *new)
+static void cxgb_redirect(struct dst_entry *old, struct dst_entry *new)
{
struct net_device *olddev, *newdev;
struct tid_info *ti;
diff --git a/drivers/net/cxgb3/mc5.c b/drivers/net/cxgb3/mc5.c
index 3b5517b8fbde..a8766fb2f9ab 100644
--- a/drivers/net/cxgb3/mc5.c
+++ b/drivers/net/cxgb3/mc5.c
@@ -374,44 +374,6 @@ int t3_mc5_init(struct mc5 *mc5, unsigned int nservers, unsigned int nfilters,
return err;
}
-/*
- * read_mc5_range - dump a part of the memory managed by MC5
- * @mc5: the MC5 handle
- * @start: the start address for the dump
- * @n: number of 72-bit words to read
- * @buf: result buffer
- *
- * Read n 72-bit words from MC5 memory from the given start location.
- */
-int t3_read_mc5_range(const struct mc5 *mc5, unsigned int start,
- unsigned int n, u32 *buf)
-{
- u32 read_cmd;
- int err = 0;
- struct adapter *adap = mc5->adapter;
-
- if (mc5->part_type == IDT75P52100)
- read_cmd = IDT_CMD_READ;
- else if (mc5->part_type == IDT75N43102)
- read_cmd = IDT4_CMD_READ;
- else
- return -EINVAL;
-
- mc5_dbgi_mode_enable(mc5);
-
- while (n--) {
- t3_write_reg(adap, A_MC5_DB_DBGI_REQ_ADDR0, start++);
- if (mc5_cmd_write(adap, read_cmd)) {
- err = -EIO;
- break;
- }
- dbgi_rd_rsp3(adap, buf + 2, buf + 1, buf);
- buf += 3;
- }
-
- mc5_dbgi_mode_disable(mc5);
- return 0;
-}
#define MC5_INT_FATAL (F_PARITYERR | F_REQQPARERR | F_DISPQPARERR)
diff --git a/drivers/net/cxgb3/regs.h b/drivers/net/cxgb3/regs.h
index cb42353c9fdd..6990f6c65221 100644
--- a/drivers/net/cxgb3/regs.h
+++ b/drivers/net/cxgb3/regs.h
@@ -1997,6 +1997,10 @@
#define A_PL_RST 0x6f0
+#define S_FATALPERREN 4
+#define V_FATALPERREN(x) ((x) << S_FATALPERREN)
+#define F_FATALPERREN V_FATALPERREN(1U)
+
#define S_CRSTWRM 1
#define V_CRSTWRM(x) ((x) << S_CRSTWRM)
#define F_CRSTWRM V_CRSTWRM(1U)
diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c
index 8ff96c6f6de5..5d72bda54389 100644
--- a/drivers/net/cxgb3/sge.c
+++ b/drivers/net/cxgb3/sge.c
@@ -1145,7 +1145,7 @@ static void write_tx_pkt_wr(struct adapter *adap, struct sk_buff *skb,
cpl->len = htonl(skb->len);
cntrl = V_TXPKT_INTF(pi->port_id);
- if (vlan_tx_tag_present(skb) && pi->vlan_grp)
+ if (vlan_tx_tag_present(skb))
cntrl |= F_TXPKT_VLAN_VLD | V_TXPKT_VLAN(vlan_tx_tag_get(skb));
tso_info = V_LSO_MSS(skb_shinfo(skb)->gso_size);
@@ -1279,7 +1279,7 @@ netdev_tx_t t3_eth_xmit(struct sk_buff *skb, struct net_device *dev)
qs->port_stats[SGE_PSTAT_TX_CSUM]++;
if (skb_shinfo(skb)->gso_size)
qs->port_stats[SGE_PSTAT_TSO]++;
- if (vlan_tx_tag_present(skb) && pi->vlan_grp)
+ if (vlan_tx_tag_present(skb))
qs->port_stats[SGE_PSTAT_VLANINS]++;
/*
@@ -2022,7 +2022,7 @@ static void rx_eth(struct adapter *adap, struct sge_rspq *rq,
qs->port_stats[SGE_PSTAT_RX_CSUM_GOOD]++;
skb->ip_summed = CHECKSUM_UNNECESSARY;
} else
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
skb_record_rx_queue(skb, qs - &adap->sge.qs[0]);
if (unlikely(p->vlan_valid)) {
@@ -2554,7 +2554,7 @@ static inline int handle_responses(struct adapter *adap, struct sge_rspq *q)
* The MSI-X interrupt handler for an SGE response queue for the non-NAPI case
* (i.e., response queue serviced in hard interrupt).
*/
-irqreturn_t t3_sge_intr_msix(int irq, void *cookie)
+static irqreturn_t t3_sge_intr_msix(int irq, void *cookie)
{
struct sge_qset *qs = cookie;
struct adapter *adap = qs->adap;
@@ -3320,40 +3320,3 @@ void t3_sge_prep(struct adapter *adap, struct sge_params *p)
spin_lock_init(&adap->sge.reg_lock);
}
-
-/**
- * t3_get_desc - dump an SGE descriptor for debugging purposes
- * @qs: the queue set
- * @qnum: identifies the specific queue (0..2: Tx, 3:response, 4..5: Rx)
- * @idx: the descriptor index in the queue
- * @data: where to dump the descriptor contents
- *
- * Dumps the contents of a HW descriptor of an SGE queue. Returns the
- * size of the descriptor.
- */
-int t3_get_desc(const struct sge_qset *qs, unsigned int qnum, unsigned int idx,
- unsigned char *data)
-{
- if (qnum >= 6)
- return -EINVAL;
-
- if (qnum < 3) {
- if (!qs->txq[qnum].desc || idx >= qs->txq[qnum].size)
- return -EINVAL;
- memcpy(data, &qs->txq[qnum].desc[idx], sizeof(struct tx_desc));
- return sizeof(struct tx_desc);
- }
-
- if (qnum == 3) {
- if (!qs->rspq.desc || idx >= qs->rspq.size)
- return -EINVAL;
- memcpy(data, &qs->rspq.desc[idx], sizeof(struct rsp_desc));
- return sizeof(struct rsp_desc);
- }
-
- qnum -= 4;
- if (!qs->fl[qnum].desc || idx >= qs->fl[qnum].size)
- return -EINVAL;
- memcpy(data, &qs->fl[qnum].desc[idx], sizeof(struct rx_desc));
- return sizeof(struct rx_desc);
-}
diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c
index 427c451be1a7..3a6adf0b3e9d 100644
--- a/drivers/net/cxgb3/t3_hw.c
+++ b/drivers/net/cxgb3/t3_hw.c
@@ -34,6 +34,8 @@
#include "sge_defs.h"
#include "firmware_exports.h"
+static void t3_port_intr_clear(struct adapter *adapter, int idx);
+
/**
* t3_wait_op_done_val - wait until an operation is completed
* @adapter: the adapter performing the operation
@@ -840,8 +842,8 @@ static int flash_wait_op(struct adapter *adapter, int attempts, int delay)
* (i.e., big-endian), otherwise as 32-bit words in the platform's
* natural endianess.
*/
-int t3_read_flash(struct adapter *adapter, unsigned int addr,
- unsigned int nwords, u32 *data, int byte_oriented)
+static int t3_read_flash(struct adapter *adapter, unsigned int addr,
+ unsigned int nwords, u32 *data, int byte_oriented)
{
int ret;
@@ -1408,6 +1410,7 @@ static int t3_handle_intr_status(struct adapter *adapter, unsigned int reg,
fatal++;
CH_ALERT(adapter, "%s (0x%x)\n",
acts->msg, status & acts->mask);
+ status &= ~acts->mask;
} else if (acts->msg)
CH_WARN(adapter, "%s (0x%x)\n",
acts->msg, status & acts->mask);
@@ -1843,11 +1846,10 @@ static int mac_intr_handler(struct adapter *adap, unsigned int idx)
t3_os_link_fault_handler(adap, idx);
}
- t3_write_reg(adap, A_XGM_INT_CAUSE + mac->offset, cause);
-
if (cause & XGM_INTR_FATAL)
t3_fatal_err(adap);
+ t3_write_reg(adap, A_XGM_INT_CAUSE + mac->offset, cause);
return cause != 0;
}
@@ -2111,7 +2113,7 @@ void t3_port_intr_disable(struct adapter *adapter, int idx)
* Clear port-specific (i.e., MAC and PHY) interrupts for the given
* adapter port.
*/
-void t3_port_intr_clear(struct adapter *adapter, int idx)
+static void t3_port_intr_clear(struct adapter *adapter, int idx)
{
struct cphy *phy = &adap2pinfo(adapter, idx)->phy;
@@ -2484,98 +2486,6 @@ int t3_sge_cqcntxt_op(struct adapter *adapter, unsigned int id, unsigned int op,
}
/**
- * t3_sge_read_context - read an SGE context
- * @type: the context type
- * @adapter: the adapter
- * @id: the context id
- * @data: holds the retrieved context
- *
- * Read an SGE egress context. The caller is responsible for ensuring
- * only one context operation occurs at a time.
- */
-static int t3_sge_read_context(unsigned int type, struct adapter *adapter,
- unsigned int id, u32 data[4])
-{
- if (t3_read_reg(adapter, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY)
- return -EBUSY;
-
- t3_write_reg(adapter, A_SG_CONTEXT_CMD,
- V_CONTEXT_CMD_OPCODE(0) | type | V_CONTEXT(id));
- if (t3_wait_op_done(adapter, A_SG_CONTEXT_CMD, F_CONTEXT_CMD_BUSY, 0,
- SG_CONTEXT_CMD_ATTEMPTS, 1))
- return -EIO;
- data[0] = t3_read_reg(adapter, A_SG_CONTEXT_DATA0);
- data[1] = t3_read_reg(adapter, A_SG_CONTEXT_DATA1);
- data[2] = t3_read_reg(adapter, A_SG_CONTEXT_DATA2);
- data[3] = t3_read_reg(adapter, A_SG_CONTEXT_DATA3);
- return 0;
-}
-
-/**
- * t3_sge_read_ecntxt - read an SGE egress context
- * @adapter: the adapter
- * @id: the context id
- * @data: holds the retrieved context
- *
- * Read an SGE egress context. The caller is responsible for ensuring
- * only one context operation occurs at a time.
- */
-int t3_sge_read_ecntxt(struct adapter *adapter, unsigned int id, u32 data[4])
-{
- if (id >= 65536)
- return -EINVAL;
- return t3_sge_read_context(F_EGRESS, adapter, id, data);
-}
-
-/**
- * t3_sge_read_cq - read an SGE CQ context
- * @adapter: the adapter
- * @id: the context id
- * @data: holds the retrieved context
- *
- * Read an SGE CQ context. The caller is responsible for ensuring
- * only one context operation occurs at a time.
- */
-int t3_sge_read_cq(struct adapter *adapter, unsigned int id, u32 data[4])
-{
- if (id >= 65536)
- return -EINVAL;
- return t3_sge_read_context(F_CQ, adapter, id, data);
-}
-
-/**
- * t3_sge_read_fl - read an SGE free-list context
- * @adapter: the adapter
- * @id: the context id
- * @data: holds the retrieved context
- *
- * Read an SGE free-list context. The caller is responsible for ensuring
- * only one context operation occurs at a time.
- */
-int t3_sge_read_fl(struct adapter *adapter, unsigned int id, u32 data[4])
-{
- if (id >= SGE_QSETS * 2)
- return -EINVAL;
- return t3_sge_read_context(F_FREELIST, adapter, id, data);
-}
-
-/**
- * t3_sge_read_rspq - read an SGE response queue context
- * @adapter: the adapter
- * @id: the context id
- * @data: holds the retrieved context
- *
- * Read an SGE response queue context. The caller is responsible for
- * ensuring only one context operation occurs at a time.
- */
-int t3_sge_read_rspq(struct adapter *adapter, unsigned int id, u32 data[4])
-{
- if (id >= SGE_QSETS)
- return -EINVAL;
- return t3_sge_read_context(F_RESPONSEQ, adapter, id, data);
-}
-
-/**
* t3_config_rss - configure Rx packet steering
* @adapter: the adapter
* @rss_config: RSS settings (written to TP_RSS_CONFIG)
@@ -2616,42 +2526,6 @@ void t3_config_rss(struct adapter *adapter, unsigned int rss_config,
}
/**
- * t3_read_rss - read the contents of the RSS tables
- * @adapter: the adapter
- * @lkup: holds the contents of the RSS lookup table
- * @map: holds the contents of the RSS map table
- *
- * Reads the contents of the receive packet steering tables.
- */
-int t3_read_rss(struct adapter *adapter, u8 * lkup, u16 *map)
-{
- int i;
- u32 val;
-
- if (lkup)
- for (i = 0; i < RSS_TABLE_SIZE; ++i) {
- t3_write_reg(adapter, A_TP_RSS_LKP_TABLE,
- 0xffff0000 | i);
- val = t3_read_reg(adapter, A_TP_RSS_LKP_TABLE);
- if (!(val & 0x80000000))
- return -EAGAIN;
- *lkup++ = val;
- *lkup++ = (val >> 8);
- }
-
- if (map)
- for (i = 0; i < RSS_TABLE_SIZE; ++i) {
- t3_write_reg(adapter, A_TP_RSS_MAP_TABLE,
- 0xffff0000 | i);
- val = t3_read_reg(adapter, A_TP_RSS_MAP_TABLE);
- if (!(val & 0x80000000))
- return -EAGAIN;
- *map++ = val;
- }
- return 0;
-}
-
-/**
* t3_tp_set_offload_mode - put TP in NIC/offload mode
* @adap: the adapter
* @enable: 1 to select offload mode, 0 for regular NIC
@@ -2868,7 +2742,8 @@ static void tp_set_timers(struct adapter *adap, unsigned int core_clk)
*
* Set the receive coalescing size and PSH bit handling.
*/
-int t3_tp_set_coalescing_size(struct adapter *adap, unsigned int size, int psh)
+static int t3_tp_set_coalescing_size(struct adapter *adap,
+ unsigned int size, int psh)
{
u32 val;
@@ -2898,7 +2773,7 @@ int t3_tp_set_coalescing_size(struct adapter *adap, unsigned int size, int psh)
* Set TP's max receive size. This is the limit that applies when
* receive coalescing is disabled.
*/
-void t3_tp_set_max_rxsize(struct adapter *adap, unsigned int size)
+static void t3_tp_set_max_rxsize(struct adapter *adap, unsigned int size)
{
t3_write_reg(adap, A_TP_PARA_REG7,
V_PMMAXXFERLEN0(size) | V_PMMAXXFERLEN1(size));
@@ -3018,48 +2893,6 @@ void t3_load_mtus(struct adapter *adap, unsigned short mtus[NMTUS],
}
/**
- * t3_read_hw_mtus - returns the values in the HW MTU table
- * @adap: the adapter
- * @mtus: where to store the HW MTU values
- *
- * Reads the HW MTU table.
- */
-void t3_read_hw_mtus(struct adapter *adap, unsigned short mtus[NMTUS])
-{
- int i;
-
- for (i = 0; i < NMTUS; ++i) {
- unsigned int val;
-
- t3_write_reg(adap, A_TP_MTU_TABLE, 0xff000000 | i);
- val = t3_read_reg(adap, A_TP_MTU_TABLE);
- mtus[i] = val & 0x3fff;
- }
-}
-
-/**
- * t3_get_cong_cntl_tab - reads the congestion control table
- * @adap: the adapter
- * @incr: where to store the alpha values
- *
- * Reads the additive increments programmed into the HW congestion
- * control table.
- */
-void t3_get_cong_cntl_tab(struct adapter *adap,
- unsigned short incr[NMTUS][NCCTRL_WIN])
-{
- unsigned int mtu, w;
-
- for (mtu = 0; mtu < NMTUS; ++mtu)
- for (w = 0; w < NCCTRL_WIN; ++w) {
- t3_write_reg(adap, A_TP_CCTRL_TABLE,
- 0xffff0000 | (mtu << 5) | w);
- incr[mtu][w] = t3_read_reg(adap, A_TP_CCTRL_TABLE) &
- 0x1fff;
- }
-}
-
-/**
* t3_tp_get_mib_stats - read TP's MIB counters
* @adap: the adapter
* @tps: holds the returned counter values
@@ -3223,15 +3056,6 @@ static int tp_init(struct adapter *adap, const struct tp_params *p)
return busy;
}
-int t3_mps_set_active_ports(struct adapter *adap, unsigned int port_mask)
-{
- if (port_mask & ~((1 << adap->params.nports) - 1))
- return -EINVAL;
- t3_set_reg_field(adap, A_MPS_CFG, F_PORT1ACTIVE | F_PORT0ACTIVE,
- port_mask << S_PORT0ACTIVE);
- return 0;
-}
-
/*
* Perform the bits of HW initialization that are dependent on the Tx
* channels being used.
@@ -3569,6 +3393,7 @@ int t3_init_hw(struct adapter *adapter, u32 fw_params)
t3_write_reg(adapter, A_PM1_TX_MODE, 0);
chan_init_hw(adapter, adapter->params.chan_map);
t3_sge_init(adapter, &adapter->params.sge);
+ t3_set_reg_field(adapter, A_PL_RST, 0, F_FATALPERREN);
t3_write_reg(adapter, A_T3DBG_GPIO_ACT_LOW, calc_gpio_intr(adapter));
@@ -3682,11 +3507,11 @@ static void mc7_prep(struct adapter *adapter, struct mc7 *mc7,
mc7->name = name;
mc7->offset = base_addr - MC7_PMRX_BASE_ADDR;
cfg = t3_read_reg(adapter, mc7->offset + A_MC7_CFG);
- mc7->size = mc7->size = G_DEN(cfg) == M_DEN ? 0 : mc7_calc_size(cfg);
+ mc7->size = G_DEN(cfg) == M_DEN ? 0 : mc7_calc_size(cfg);
mc7->width = G_WIDTH(cfg);
}
-void mac_prep(struct cmac *mac, struct adapter *adapter, int index)
+static void mac_prep(struct cmac *mac, struct adapter *adapter, int index)
{
u16 devid;
@@ -3706,7 +3531,8 @@ void mac_prep(struct cmac *mac, struct adapter *adapter, int index)
}
}
-void early_hw_init(struct adapter *adapter, const struct adapter_info *ai)
+static void early_hw_init(struct adapter *adapter,
+ const struct adapter_info *ai)
{
u32 val = V_PORTSPEED(is_10G(adapter) ? 3 : 2);
diff --git a/drivers/net/cxgb4/cxgb4.h b/drivers/net/cxgb4/cxgb4.h
index 6e562c0dad7d..eaa49e4119f1 100644
--- a/drivers/net/cxgb4/cxgb4.h
+++ b/drivers/net/cxgb4/cxgb4.h
@@ -463,6 +463,8 @@ struct sge {
u8 counter_val[SGE_NCOUNTERS];
unsigned int starve_thres;
u8 idma_state[2];
+ unsigned int egr_start;
+ unsigned int ingr_start;
void *egr_map[MAX_EGRQ]; /* qid->queue egress queue map */
struct sge_rspq *ingr_map[MAX_INGQ]; /* qid->queue ingress queue map */
DECLARE_BITMAP(starving_fl, MAX_EGRQ);
@@ -590,7 +592,6 @@ void t4_os_portmod_changed(const struct adapter *adap, int port_id);
void t4_os_link_changed(struct adapter *adap, int port_id, int link_stat);
void *t4_alloc_mem(size_t size);
-void t4_free_mem(void *addr);
void t4_free_sge_resources(struct adapter *adap);
irq_handler_t t4_intr_handler(struct adapter *adap);
@@ -649,7 +650,6 @@ static inline int t4_wr_mbox_ns(struct adapter *adap, int mbox, const void *cmd,
void t4_intr_enable(struct adapter *adapter);
void t4_intr_disable(struct adapter *adapter);
-void t4_intr_clear(struct adapter *adapter);
int t4_slow_intr_handler(struct adapter *adapter);
int t4_wait_dev_ready(struct adapter *adap);
@@ -662,24 +662,16 @@ int t4_check_fw_version(struct adapter *adapter);
int t4_prep_adapter(struct adapter *adapter);
int t4_port_init(struct adapter *adap, int mbox, int pf, int vf);
void t4_fatal_err(struct adapter *adapter);
-int t4_set_trace_filter(struct adapter *adapter, const struct trace_params *tp,
- int filter_index, int enable);
-void t4_get_trace_filter(struct adapter *adapter, struct trace_params *tp,
- int filter_index, int *enabled);
int t4_config_rss_range(struct adapter *adapter, int mbox, unsigned int viid,
int start, int n, const u16 *rspq, unsigned int nrspq);
int t4_config_glbl_rss(struct adapter *adapter, int mbox, unsigned int mode,
unsigned int flags);
-int t4_read_rss(struct adapter *adapter, u16 *entries);
int t4_mc_read(struct adapter *adap, u32 addr, __be32 *data, u64 *parity);
int t4_edc_read(struct adapter *adap, int idx, u32 addr, __be32 *data,
u64 *parity);
void t4_get_port_stats(struct adapter *adap, int idx, struct port_stats *p);
-void t4_get_lb_stats(struct adapter *adap, int idx, struct lb_port_stats *p);
-
void t4_read_mtu_tbl(struct adapter *adap, u16 *mtus, u8 *mtu_log);
-void t4_tp_get_err_stats(struct adapter *adap, struct tp_err_stats *st);
void t4_tp_get_tcp_stats(struct adapter *adap, struct tp_tcp_stats *v4,
struct tp_tcp_stats *v6);
void t4_load_mtus(struct adapter *adap, const unsigned short *mtus,
@@ -709,8 +701,6 @@ int t4_cfg_pfvf(struct adapter *adap, unsigned int mbox, unsigned int pf,
int t4_alloc_vi(struct adapter *adap, unsigned int mbox, unsigned int port,
unsigned int pf, unsigned int vf, unsigned int nmac, u8 *mac,
unsigned int *rss_size);
-int t4_free_vi(struct adapter *adap, unsigned int mbox, unsigned int pf,
- unsigned int vf, unsigned int viid);
int t4_set_rxmode(struct adapter *adap, unsigned int mbox, unsigned int viid,
int mtu, int promisc, int all_multi, int bcast, int vlanex,
bool sleep_ok);
@@ -729,9 +719,6 @@ int t4_mdio_rd(struct adapter *adap, unsigned int mbox, unsigned int phy_addr,
unsigned int mmd, unsigned int reg, u16 *valp);
int t4_mdio_wr(struct adapter *adap, unsigned int mbox, unsigned int phy_addr,
unsigned int mmd, unsigned int reg, u16 val);
-int t4_iq_start_stop(struct adapter *adap, unsigned int mbox, bool start,
- unsigned int pf, unsigned int vf, unsigned int iqid,
- unsigned int fl0id, unsigned int fl1id);
int t4_iq_free(struct adapter *adap, unsigned int mbox, unsigned int pf,
unsigned int vf, unsigned int iqtype, unsigned int iqid,
unsigned int fl0id, unsigned int fl1id);
diff --git a/drivers/net/cxgb4/cxgb4_main.c b/drivers/net/cxgb4/cxgb4_main.c
index c327527fbbc8..87054e0a5746 100644
--- a/drivers/net/cxgb4/cxgb4_main.c
+++ b/drivers/net/cxgb4/cxgb4_main.c
@@ -175,16 +175,26 @@ enum {
static DEFINE_PCI_DEVICE_TABLE(cxgb4_pci_tbl) = {
CH_DEVICE(0xa000, 0), /* PE10K */
- CH_DEVICE(0x4001, 0),
- CH_DEVICE(0x4002, 0),
- CH_DEVICE(0x4003, 0),
- CH_DEVICE(0x4004, 0),
- CH_DEVICE(0x4005, 0),
- CH_DEVICE(0x4006, 0),
- CH_DEVICE(0x4007, 0),
- CH_DEVICE(0x4008, 0),
- CH_DEVICE(0x4009, 0),
- CH_DEVICE(0x400a, 0),
+ CH_DEVICE(0x4001, -1),
+ CH_DEVICE(0x4002, -1),
+ CH_DEVICE(0x4003, -1),
+ CH_DEVICE(0x4004, -1),
+ CH_DEVICE(0x4005, -1),
+ CH_DEVICE(0x4006, -1),
+ CH_DEVICE(0x4007, -1),
+ CH_DEVICE(0x4008, -1),
+ CH_DEVICE(0x4009, -1),
+ CH_DEVICE(0x400a, -1),
+ CH_DEVICE(0x4401, 4),
+ CH_DEVICE(0x4402, 4),
+ CH_DEVICE(0x4403, 4),
+ CH_DEVICE(0x4404, 4),
+ CH_DEVICE(0x4405, 4),
+ CH_DEVICE(0x4406, 4),
+ CH_DEVICE(0x4407, 4),
+ CH_DEVICE(0x4408, 4),
+ CH_DEVICE(0x4409, 4),
+ CH_DEVICE(0x440a, 4),
{ 0, }
};
@@ -423,10 +433,11 @@ static int fwevtq_handler(struct sge_rspq *q, const __be64 *rsp,
if (likely(opcode == CPL_SGE_EGR_UPDATE)) {
const struct cpl_sge_egr_update *p = (void *)rsp;
unsigned int qid = EGR_QID(ntohl(p->opcode_qid));
- struct sge_txq *txq = q->adap->sge.egr_map[qid];
+ struct sge_txq *txq;
+ txq = q->adap->sge.egr_map[qid - q->adap->sge.egr_start];
txq->restarts++;
- if ((u8 *)txq < (u8 *)q->adap->sge.ethrxq) {
+ if ((u8 *)txq < (u8 *)q->adap->sge.ofldtxq) {
struct sge_eth_txq *eq;
eq = container_of(txq, struct sge_eth_txq, q);
@@ -658,6 +669,15 @@ static int setup_rss(struct adapter *adap)
}
/*
+ * Return the channel of the ingress queue with the given qid.
+ */
+static unsigned int rxq_to_chan(const struct sge *p, unsigned int qid)
+{
+ qid -= p->ingr_start;
+ return netdev2pinfo(p->ingr_map[qid]->netdev)->tx_chan;
+}
+
+/*
* Wait until all NAPI handlers are descheduled.
*/
static void quiesce_rx(struct adapter *adap)
@@ -860,7 +880,7 @@ void *t4_alloc_mem(size_t size)
/*
* Free memory allocated through alloc_mem().
*/
-void t4_free_mem(void *addr)
+static void t4_free_mem(void *addr)
{
if (is_vmalloc_addr(addr))
vfree(addr);
@@ -1671,27 +1691,41 @@ static int get_coalesce(struct net_device *dev, struct ethtool_coalesce *c)
return 0;
}
-/*
- * Translate a physical EEPROM address to virtual. The first 1K is accessed
- * through virtual addresses starting at 31K, the rest is accessed through
- * virtual addresses starting at 0. This mapping is correct only for PF0.
+/**
+ * eeprom_ptov - translate a physical EEPROM address to virtual
+ * @phys_addr: the physical EEPROM address
+ * @fn: the PCI function number
+ * @sz: size of function-specific area
+ *
+ * Translate a physical EEPROM address to virtual. The first 1K is
+ * accessed through virtual addresses starting at 31K, the rest is
+ * accessed through virtual addresses starting at 0.
+ *
+ * The mapping is as follows:
+ * [0..1K) -> [31K..32K)
+ * [1K..1K+A) -> [31K-A..31K)
+ * [1K+A..ES) -> [0..ES-A-1K)
+ *
+ * where A = @fn * @sz, and ES = EEPROM size.
*/
-static int eeprom_ptov(unsigned int phys_addr)
+static int eeprom_ptov(unsigned int phys_addr, unsigned int fn, unsigned int sz)
{
+ fn *= sz;
if (phys_addr < 1024)
return phys_addr + (31 << 10);
+ if (phys_addr < 1024 + fn)
+ return 31744 - fn + phys_addr - 1024;
if (phys_addr < EEPROMSIZE)
- return phys_addr - 1024;
+ return phys_addr - 1024 - fn;
return -EINVAL;
}
/*
* The next two routines implement eeprom read/write from physical addresses.
- * The physical->virtual translation is correct only for PF0.
*/
static int eeprom_rd_phys(struct adapter *adap, unsigned int phys_addr, u32 *v)
{
- int vaddr = eeprom_ptov(phys_addr);
+ int vaddr = eeprom_ptov(phys_addr, adap->fn, EEPROMPFSIZE);
if (vaddr >= 0)
vaddr = pci_read_vpd(adap->pdev, vaddr, sizeof(u32), v);
@@ -1700,7 +1734,7 @@ static int eeprom_rd_phys(struct adapter *adap, unsigned int phys_addr, u32 *v)
static int eeprom_wr_phys(struct adapter *adap, unsigned int phys_addr, u32 v)
{
- int vaddr = eeprom_ptov(phys_addr);
+ int vaddr = eeprom_ptov(phys_addr, adap->fn, EEPROMPFSIZE);
if (vaddr >= 0)
vaddr = pci_write_vpd(adap->pdev, vaddr, sizeof(u32), &v);
@@ -1743,6 +1777,14 @@ static int set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
aligned_offset = eeprom->offset & ~3;
aligned_len = (eeprom->len + (eeprom->offset & 3) + 3) & ~3;
+ if (adapter->fn > 0) {
+ u32 start = 1024 + adapter->fn * EEPROMPFSIZE;
+
+ if (aligned_offset < start ||
+ aligned_offset + aligned_len > start + EEPROMPFSIZE)
+ return -EPERM;
+ }
+
if (aligned_offset != eeprom->offset || aligned_len != eeprom->len) {
/*
* RMW possibly needed for first or last words.
@@ -2026,6 +2068,7 @@ static const struct file_operations mem_debugfs_fops = {
.owner = THIS_MODULE,
.open = mem_open,
.read = mem_read,
+ .llseek = default_llseek,
};
static void __devinit add_debugfs_mem(struct adapter *adap, const char *name,
@@ -2164,8 +2207,8 @@ static void mk_tid_release(struct sk_buff *skb, unsigned int chan,
* Queue a TID release request and if necessary schedule a work queue to
* process it.
*/
-void cxgb4_queue_tid_release(struct tid_info *t, unsigned int chan,
- unsigned int tid)
+static void cxgb4_queue_tid_release(struct tid_info *t, unsigned int chan,
+ unsigned int tid)
{
void **p = &t->tid_tab[tid];
struct adapter *adap = container_of(t, struct adapter, tids);
@@ -2180,7 +2223,6 @@ void cxgb4_queue_tid_release(struct tid_info *t, unsigned int chan,
}
spin_unlock_bh(&adap->tid_release_lock);
}
-EXPORT_SYMBOL(cxgb4_queue_tid_release);
/*
* Process the list of pending TID release requests.
@@ -2304,7 +2346,7 @@ int cxgb4_create_server(const struct net_device *dev, unsigned int stid,
req->peer_port = htons(0);
req->local_ip = sip;
req->peer_ip = htonl(0);
- chan = netdev2pinfo(adap->sge.ingr_map[queue]->netdev)->tx_chan;
+ chan = rxq_to_chan(&adap->sge, queue);
req->opt0 = cpu_to_be64(TX_CHAN(chan));
req->opt1 = cpu_to_be64(CONN_POLICY_ASK |
SYN_RSS_ENABLE | SYN_RSS_QUEUE(queue));
@@ -2313,48 +2355,6 @@ int cxgb4_create_server(const struct net_device *dev, unsigned int stid,
EXPORT_SYMBOL(cxgb4_create_server);
/**
- * cxgb4_create_server6 - create an IPv6 server
- * @dev: the device
- * @stid: the server TID
- * @sip: local IPv6 address to bind server to
- * @sport: the server's TCP port
- * @queue: queue to direct messages from this server to
- *
- * Create an IPv6 server for the given port and address.
- * Returns <0 on error and one of the %NET_XMIT_* values on success.
- */
-int cxgb4_create_server6(const struct net_device *dev, unsigned int stid,
- const struct in6_addr *sip, __be16 sport,
- unsigned int queue)
-{
- unsigned int chan;
- struct sk_buff *skb;
- struct adapter *adap;
- struct cpl_pass_open_req6 *req;
-
- skb = alloc_skb(sizeof(*req), GFP_KERNEL);
- if (!skb)
- return -ENOMEM;
-
- adap = netdev2adap(dev);
- req = (struct cpl_pass_open_req6 *)__skb_put(skb, sizeof(*req));
- INIT_TP_WR(req, 0);
- OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_PASS_OPEN_REQ6, stid));
- req->local_port = sport;
- req->peer_port = htons(0);
- req->local_ip_hi = *(__be64 *)(sip->s6_addr);
- req->local_ip_lo = *(__be64 *)(sip->s6_addr + 8);
- req->peer_ip_hi = cpu_to_be64(0);
- req->peer_ip_lo = cpu_to_be64(0);
- chan = netdev2pinfo(adap->sge.ingr_map[queue]->netdev)->tx_chan;
- req->opt0 = cpu_to_be64(TX_CHAN(chan));
- req->opt1 = cpu_to_be64(CONN_POLICY_ASK |
- SYN_RSS_ENABLE | SYN_RSS_QUEUE(queue));
- return t4_mgmt_tx(adap, skb);
-}
-EXPORT_SYMBOL(cxgb4_create_server6);
-
-/**
* cxgb4_best_mtu - find the entry in the MTU table closest to an MTU
* @mtus: the HW MTU table
* @mtu: the target MTU
@@ -2413,25 +2413,6 @@ unsigned int cxgb4_port_idx(const struct net_device *dev)
}
EXPORT_SYMBOL(cxgb4_port_idx);
-/**
- * cxgb4_netdev_by_hwid - return the net device of a HW port
- * @pdev: identifies the adapter
- * @id: the HW port id
- *
- * Return the net device associated with the interface with the given HW
- * id.
- */
-struct net_device *cxgb4_netdev_by_hwid(struct pci_dev *pdev, unsigned int id)
-{
- const struct adapter *adap = pci_get_drvdata(pdev);
-
- if (!adap || id >= NCHAN)
- return NULL;
- id = adap->chan_map[id];
- return id < MAX_NPORTS ? adap->port[id] : NULL;
-}
-EXPORT_SYMBOL(cxgb4_netdev_by_hwid);
-
void cxgb4_get_tcp_stats(struct pci_dev *pdev, struct tp_tcp_stats *v4,
struct tp_tcp_stats *v6)
{
@@ -2721,7 +2702,10 @@ static int cxgb_open(struct net_device *dev)
return err;
}
- dev->real_num_tx_queues = pi->nqsets;
+ netif_set_real_num_tx_queues(dev, pi->nqsets);
+ err = netif_set_real_num_rx_queues(dev, pi->nqsets);
+ if (err)
+ return err;
err = link_start(dev);
if (!err)
netif_tx_start_all_queues(dev);
@@ -3061,12 +3045,16 @@ static int adap_init0(struct adapter *adap)
params[2] = FW_PARAM_PFVF(L2T_END);
params[3] = FW_PARAM_PFVF(FILTER_START);
params[4] = FW_PARAM_PFVF(FILTER_END);
- ret = t4_query_params(adap, adap->fn, adap->fn, 0, 5, params, val);
+ params[5] = FW_PARAM_PFVF(IQFLINT_START);
+ params[6] = FW_PARAM_PFVF(EQ_START);
+ ret = t4_query_params(adap, adap->fn, adap->fn, 0, 7, params, val);
if (ret < 0)
goto bye;
port_vec = val[0];
adap->tids.ftid_base = val[3];
adap->tids.nftids = val[4] - val[3] + 1;
+ adap->sge.ingr_start = val[5];
+ adap->sge.egr_start = val[6];
if (c.ofldcaps) {
/* query offload-related parameters */
@@ -3814,7 +3802,7 @@ static void __devexit remove_one(struct pci_dev *pdev)
pci_disable_device(pdev);
pci_release_regions(pdev);
pci_set_drvdata(pdev, NULL);
- } else if (PCI_FUNC(pdev->devfn) > 0)
+ } else
pci_release_regions(pdev);
}
diff --git a/drivers/net/cxgb4/cxgb4_uld.h b/drivers/net/cxgb4/cxgb4_uld.h
index 85d74e751ce0..1b48c0170145 100644
--- a/drivers/net/cxgb4/cxgb4_uld.h
+++ b/drivers/net/cxgb4/cxgb4_uld.h
@@ -139,16 +139,11 @@ int cxgb4_alloc_stid(struct tid_info *t, int family, void *data);
void cxgb4_free_atid(struct tid_info *t, unsigned int atid);
void cxgb4_free_stid(struct tid_info *t, unsigned int stid, int family);
void cxgb4_remove_tid(struct tid_info *t, unsigned int qid, unsigned int tid);
-void cxgb4_queue_tid_release(struct tid_info *t, unsigned int chan,
- unsigned int tid);
struct in6_addr;
int cxgb4_create_server(const struct net_device *dev, unsigned int stid,
__be32 sip, __be16 sport, unsigned int queue);
-int cxgb4_create_server6(const struct net_device *dev, unsigned int stid,
- const struct in6_addr *sip, __be16 sport,
- unsigned int queue);
static inline void set_wr_txq(struct sk_buff *skb, int prio, int queue)
{
@@ -233,7 +228,6 @@ int cxgb4_ofld_send(struct net_device *dev, struct sk_buff *skb);
unsigned int cxgb4_port_chan(const struct net_device *dev);
unsigned int cxgb4_port_viid(const struct net_device *dev);
unsigned int cxgb4_port_idx(const struct net_device *dev);
-struct net_device *cxgb4_netdev_by_hwid(struct pci_dev *pdev, unsigned int id);
unsigned int cxgb4_best_mtu(const unsigned short *mtus, unsigned short mtu,
unsigned int *idx);
void cxgb4_get_tcp_stats(struct pci_dev *pdev, struct tp_tcp_stats *v4,
diff --git a/drivers/net/cxgb4/l2t.c b/drivers/net/cxgb4/l2t.c
index e8f0f55e9d08..a2d323c473f8 100644
--- a/drivers/net/cxgb4/l2t.c
+++ b/drivers/net/cxgb4/l2t.c
@@ -481,40 +481,6 @@ void t4_l2t_update(struct adapter *adap, struct neighbour *neigh)
handle_failed_resolution(adap, arpq);
}
-/*
- * Allocate an L2T entry for use by a switching rule. Such entries need to be
- * explicitly freed and while busy they are not on any hash chain, so normal
- * address resolution updates do not see them.
- */
-struct l2t_entry *t4_l2t_alloc_switching(struct l2t_data *d)
-{
- struct l2t_entry *e;
-
- write_lock_bh(&d->lock);
- e = alloc_l2e(d);
- if (e) {
- spin_lock(&e->lock); /* avoid race with t4_l2t_free */
- e->state = L2T_STATE_SWITCHING;
- atomic_set(&e->refcnt, 1);
- spin_unlock(&e->lock);
- }
- write_unlock_bh(&d->lock);
- return e;
-}
-
-/*
- * Sets/updates the contents of a switching L2T entry that has been allocated
- * with an earlier call to @t4_l2t_alloc_switching.
- */
-int t4_l2t_set_switching(struct adapter *adap, struct l2t_entry *e, u16 vlan,
- u8 port, u8 *eth_addr)
-{
- e->vlan = vlan;
- e->lport = port;
- memcpy(e->dmac, eth_addr, ETH_ALEN);
- return write_l2e(adap, e, 0);
-}
-
struct l2t_data *t4_init_l2t(void)
{
int i;
diff --git a/drivers/net/cxgb4/l2t.h b/drivers/net/cxgb4/l2t.h
index 643f27ed3cf4..7bd8f42378ff 100644
--- a/drivers/net/cxgb4/l2t.h
+++ b/drivers/net/cxgb4/l2t.h
@@ -100,9 +100,6 @@ struct l2t_entry *cxgb4_l2t_get(struct l2t_data *d, struct neighbour *neigh,
unsigned int priority);
void t4_l2t_update(struct adapter *adap, struct neighbour *neigh);
-struct l2t_entry *t4_l2t_alloc_switching(struct l2t_data *d);
-int t4_l2t_set_switching(struct adapter *adap, struct l2t_entry *e, u16 vlan,
- u8 port, u8 *eth_addr);
struct l2t_data *t4_init_l2t(void);
void do_l2t_write_rpl(struct adapter *p, const struct cpl_l2t_write_rpl *rpl);
diff --git a/drivers/net/cxgb4/sge.c b/drivers/net/cxgb4/sge.c
index bf38cfc57565..9967f3debce7 100644
--- a/drivers/net/cxgb4/sge.c
+++ b/drivers/net/cxgb4/sge.c
@@ -557,7 +557,8 @@ out: cred = q->avail - cred;
if (unlikely(fl_starving(q))) {
smp_wmb();
- set_bit(q->cntxt_id, adap->sge.starving_fl);
+ set_bit(q->cntxt_id - adap->sge.egr_start,
+ adap->sge.starving_fl);
}
return cred;
@@ -974,7 +975,7 @@ out_free: dev_kfree_skb(skb);
}
cpl->ctrl0 = htonl(TXPKT_OPCODE(CPL_TX_PKT_XT) |
- TXPKT_INTF(pi->tx_chan) | TXPKT_PF(0));
+ TXPKT_INTF(pi->tx_chan) | TXPKT_PF(adap->fn));
cpl->pack = htons(0);
cpl->len = htons(skb->len);
cpl->ctrl1 = cpu_to_be64(cntrl);
@@ -1213,7 +1214,8 @@ static void txq_stop_maperr(struct sge_ofld_txq *q)
{
q->mapping_err++;
q->q.stops++;
- set_bit(q->q.cntxt_id, q->adap->sge.txq_maperr);
+ set_bit(q->q.cntxt_id - q->adap->sge.egr_start,
+ q->adap->sge.txq_maperr);
}
/**
@@ -1603,7 +1605,7 @@ int t4_ethrx_handler(struct sge_rspq *q, const __be64 *rsp,
rxq->stats.rx_cso++;
}
} else
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
if (unlikely(pkt->vlan_ex)) {
struct vlan_group *grp = pi->vlan_grp;
@@ -1835,6 +1837,7 @@ static unsigned int process_intrq(struct adapter *adap)
if (RSPD_TYPE(rc->type_gen) == RSP_TYPE_INTR) {
unsigned int qid = ntohl(rc->pldbuflen_qid);
+ qid -= adap->sge.ingr_start;
napi_schedule(&adap->sge.ingr_map[qid]->napi);
}
@@ -2050,14 +2053,14 @@ int t4_sge_alloc_rxq(struct adapter *adap, struct sge_rspq *iq, bool fwevtq,
/* set offset to -1 to distinguish ingress queues without FL */
iq->offset = fl ? 0 : -1;
- adap->sge.ingr_map[iq->cntxt_id] = iq;
+ adap->sge.ingr_map[iq->cntxt_id - adap->sge.ingr_start] = iq;
if (fl) {
fl->cntxt_id = ntohs(c.fl0id);
fl->avail = fl->pend_cred = 0;
fl->pidx = fl->cidx = 0;
fl->alloc_failed = fl->large_alloc_failed = fl->starving = 0;
- adap->sge.egr_map[fl->cntxt_id] = fl;
+ adap->sge.egr_map[fl->cntxt_id - adap->sge.egr_start] = fl;
refill_fl(adap, fl, fl_cap(fl), GFP_KERNEL);
}
return 0;
@@ -2087,7 +2090,7 @@ static void init_txq(struct adapter *adap, struct sge_txq *q, unsigned int id)
q->stops = q->restarts = 0;
q->stat = (void *)&q->desc[q->size];
q->cntxt_id = id;
- adap->sge.egr_map[id] = q;
+ adap->sge.egr_map[id - adap->sge.egr_start] = q;
}
int t4_sge_alloc_eth_txq(struct adapter *adap, struct sge_eth_txq *txq,
@@ -2259,7 +2262,7 @@ static void free_rspq_fl(struct adapter *adap, struct sge_rspq *rq,
{
unsigned int fl_id = fl ? fl->cntxt_id : 0xffff;
- adap->sge.ingr_map[rq->cntxt_id] = NULL;
+ adap->sge.ingr_map[rq->cntxt_id - adap->sge.ingr_start] = NULL;
t4_iq_free(adap, adap->fn, adap->fn, 0, FW_IQ_TYPE_FL_INT_CAP,
rq->cntxt_id, fl_id, 0xffff);
dma_free_coherent(adap->pdev_dev, (rq->size + 1) * rq->iqe_len,
diff --git a/drivers/net/cxgb4/t4_hw.c b/drivers/net/cxgb4/t4_hw.c
index 9e1a4b49b47a..bb813d94aea8 100644
--- a/drivers/net/cxgb4/t4_hw.c
+++ b/drivers/net/cxgb4/t4_hw.c
@@ -120,30 +120,6 @@ static void t4_read_indirect(struct adapter *adap, unsigned int addr_reg,
}
}
-#if 0
-/**
- * t4_write_indirect - write indirectly addressed registers
- * @adap: the adapter
- * @addr_reg: register holding the indirect addresses
- * @data_reg: register holding the value for the indirect registers
- * @vals: values to write
- * @nregs: how many indirect registers to write
- * @start_idx: address of first indirect register to write
- *
- * Writes a sequential block of registers that are accessed indirectly
- * through an address/data register pair.
- */
-static void t4_write_indirect(struct adapter *adap, unsigned int addr_reg,
- unsigned int data_reg, const u32 *vals,
- unsigned int nregs, unsigned int start_idx)
-{
- while (nregs--) {
- t4_write_reg(adap, addr_reg, start_idx++);
- t4_write_reg(adap, data_reg, *vals++);
- }
-}
-#endif
-
/*
* Get the reply to a mailbox command and store it in @rpl in big-endian order.
*/
@@ -1560,44 +1536,6 @@ void t4_intr_disable(struct adapter *adapter)
}
/**
- * t4_intr_clear - clear all interrupts
- * @adapter: the adapter whose interrupts should be cleared
- *
- * Clears all interrupts. The caller must be a PCI function managing
- * global interrupts.
- */
-void t4_intr_clear(struct adapter *adapter)
-{
- static const unsigned int cause_reg[] = {
- SGE_INT_CAUSE1, SGE_INT_CAUSE2, SGE_INT_CAUSE3,
- PCIE_CORE_UTL_SYSTEM_BUS_AGENT_STATUS,
- PCIE_CORE_UTL_PCI_EXPRESS_PORT_STATUS,
- PCIE_NONFAT_ERR, PCIE_INT_CAUSE,
- MC_INT_CAUSE,
- MA_INT_WRAP_STATUS, MA_PARITY_ERROR_STATUS, MA_INT_CAUSE,
- EDC_INT_CAUSE, EDC_REG(EDC_INT_CAUSE, 1),
- CIM_HOST_INT_CAUSE, CIM_HOST_UPACC_INT_CAUSE,
- MYPF_REG(CIM_PF_HOST_INT_CAUSE),
- TP_INT_CAUSE,
- ULP_RX_INT_CAUSE, ULP_TX_INT_CAUSE,
- PM_RX_INT_CAUSE, PM_TX_INT_CAUSE,
- MPS_RX_PERR_INT_CAUSE,
- CPL_INTR_CAUSE,
- MYPF_REG(PL_PF_INT_CAUSE),
- PL_PL_INT_CAUSE,
- LE_DB_INT_CAUSE,
- };
-
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(cause_reg); ++i)
- t4_write_reg(adapter, cause_reg[i], 0xffffffff);
-
- t4_write_reg(adapter, PL_INT_CAUSE, GLBL_INTR_MASK);
- (void) t4_read_reg(adapter, PL_INT_CAUSE); /* flush */
-}
-
-/**
* hash_mac_addr - return the hash value of a MAC address
* @addr: the 48-bit Ethernet MAC address
*
@@ -1709,36 +1647,6 @@ int t4_config_glbl_rss(struct adapter *adapter, int mbox, unsigned int mode,
return t4_wr_mbox(adapter, mbox, &c, sizeof(c), NULL);
}
-/* Read an RSS table row */
-static int rd_rss_row(struct adapter *adap, int row, u32 *val)
-{
- t4_write_reg(adap, TP_RSS_LKP_TABLE, 0xfff00000 | row);
- return t4_wait_op_done_val(adap, TP_RSS_LKP_TABLE, LKPTBLROWVLD, 1,
- 5, 0, val);
-}
-
-/**
- * t4_read_rss - read the contents of the RSS mapping table
- * @adapter: the adapter
- * @map: holds the contents of the RSS mapping table
- *
- * Reads the contents of the RSS hash->queue mapping table.
- */
-int t4_read_rss(struct adapter *adapter, u16 *map)
-{
- u32 val;
- int i, ret;
-
- for (i = 0; i < RSS_NENTRIES / 2; ++i) {
- ret = rd_rss_row(adapter, i, &val);
- if (ret)
- return ret;
- *map++ = LKPTBLQUEUE0_GET(val);
- *map++ = LKPTBLQUEUE1_GET(val);
- }
- return 0;
-}
-
/**
* t4_tp_get_tcp_stats - read TP's TCP MIB counters
* @adap: the adapter
@@ -1779,29 +1687,6 @@ void t4_tp_get_tcp_stats(struct adapter *adap, struct tp_tcp_stats *v4,
}
/**
- * t4_tp_get_err_stats - read TP's error MIB counters
- * @adap: the adapter
- * @st: holds the counter values
- *
- * Returns the values of TP's error counters.
- */
-void t4_tp_get_err_stats(struct adapter *adap, struct tp_err_stats *st)
-{
- t4_read_indirect(adap, TP_MIB_INDEX, TP_MIB_DATA, st->macInErrs,
- 12, TP_MIB_MAC_IN_ERR_0);
- t4_read_indirect(adap, TP_MIB_INDEX, TP_MIB_DATA, st->tnlCongDrops,
- 8, TP_MIB_TNL_CNG_DROP_0);
- t4_read_indirect(adap, TP_MIB_INDEX, TP_MIB_DATA, st->tnlTxDrops,
- 4, TP_MIB_TNL_DROP_0);
- t4_read_indirect(adap, TP_MIB_INDEX, TP_MIB_DATA, st->ofldVlanDrops,
- 4, TP_MIB_OFD_VLN_DROP_0);
- t4_read_indirect(adap, TP_MIB_INDEX, TP_MIB_DATA, st->tcp6InErrs,
- 4, TP_MIB_TCP_V6IN_ERR_0);
- t4_read_indirect(adap, TP_MIB_INDEX, TP_MIB_DATA, &st->ofldNoNeigh,
- 2, TP_MIB_OFD_ARP_DROP);
-}
-
-/**
* t4_read_mtu_tbl - returns the values in the HW path MTU table
* @adap: the adapter
* @mtus: where to store the MTU values
@@ -1916,122 +1801,6 @@ void t4_load_mtus(struct adapter *adap, const unsigned short *mtus,
}
/**
- * t4_set_trace_filter - configure one of the tracing filters
- * @adap: the adapter
- * @tp: the desired trace filter parameters
- * @idx: which filter to configure
- * @enable: whether to enable or disable the filter
- *
- * Configures one of the tracing filters available in HW. If @enable is
- * %0 @tp is not examined and may be %NULL.
- */
-int t4_set_trace_filter(struct adapter *adap, const struct trace_params *tp,
- int idx, int enable)
-{
- int i, ofst = idx * 4;
- u32 data_reg, mask_reg, cfg;
- u32 multitrc = TRCMULTIFILTER;
-
- if (!enable) {
- t4_write_reg(adap, MPS_TRC_FILTER_MATCH_CTL_A + ofst, 0);
- goto out;
- }
-
- if (tp->port > 11 || tp->invert > 1 || tp->skip_len > 0x1f ||
- tp->skip_ofst > 0x1f || tp->min_len > 0x1ff ||
- tp->snap_len > 9600 || (idx && tp->snap_len > 256))
- return -EINVAL;
-
- if (tp->snap_len > 256) { /* must be tracer 0 */
- if ((t4_read_reg(adap, MPS_TRC_FILTER_MATCH_CTL_A + 4) |
- t4_read_reg(adap, MPS_TRC_FILTER_MATCH_CTL_A + 8) |
- t4_read_reg(adap, MPS_TRC_FILTER_MATCH_CTL_A + 12)) & TFEN)
- return -EINVAL; /* other tracers are enabled */
- multitrc = 0;
- } else if (idx) {
- i = t4_read_reg(adap, MPS_TRC_FILTER_MATCH_CTL_B);
- if (TFCAPTUREMAX_GET(i) > 256 &&
- (t4_read_reg(adap, MPS_TRC_FILTER_MATCH_CTL_A) & TFEN))
- return -EINVAL;
- }
-
- /* stop the tracer we'll be changing */
- t4_write_reg(adap, MPS_TRC_FILTER_MATCH_CTL_A + ofst, 0);
-
- /* disable tracing globally if running in the wrong single/multi mode */
- cfg = t4_read_reg(adap, MPS_TRC_CFG);
- if ((cfg & TRCEN) && multitrc != (cfg & TRCMULTIFILTER)) {
- t4_write_reg(adap, MPS_TRC_CFG, cfg ^ TRCEN);
- t4_read_reg(adap, MPS_TRC_CFG); /* flush */
- msleep(1);
- if (!(t4_read_reg(adap, MPS_TRC_CFG) & TRCFIFOEMPTY))
- return -ETIMEDOUT;
- }
- /*
- * At this point either the tracing is enabled and in the right mode or
- * disabled.
- */
-
- idx *= (MPS_TRC_FILTER1_MATCH - MPS_TRC_FILTER0_MATCH);
- data_reg = MPS_TRC_FILTER0_MATCH + idx;
- mask_reg = MPS_TRC_FILTER0_DONT_CARE + idx;
-
- for (i = 0; i < TRACE_LEN / 4; i++, data_reg += 4, mask_reg += 4) {
- t4_write_reg(adap, data_reg, tp->data[i]);
- t4_write_reg(adap, mask_reg, ~tp->mask[i]);
- }
- t4_write_reg(adap, MPS_TRC_FILTER_MATCH_CTL_B + ofst,
- TFCAPTUREMAX(tp->snap_len) |
- TFMINPKTSIZE(tp->min_len));
- t4_write_reg(adap, MPS_TRC_FILTER_MATCH_CTL_A + ofst,
- TFOFFSET(tp->skip_ofst) | TFLENGTH(tp->skip_len) |
- TFPORT(tp->port) | TFEN |
- (tp->invert ? TFINVERTMATCH : 0));
-
- cfg &= ~TRCMULTIFILTER;
- t4_write_reg(adap, MPS_TRC_CFG, cfg | TRCEN | multitrc);
-out: t4_read_reg(adap, MPS_TRC_CFG); /* flush */
- return 0;
-}
-
-/**
- * t4_get_trace_filter - query one of the tracing filters
- * @adap: the adapter
- * @tp: the current trace filter parameters
- * @idx: which trace filter to query
- * @enabled: non-zero if the filter is enabled
- *
- * Returns the current settings of one of the HW tracing filters.
- */
-void t4_get_trace_filter(struct adapter *adap, struct trace_params *tp, int idx,
- int *enabled)
-{
- u32 ctla, ctlb;
- int i, ofst = idx * 4;
- u32 data_reg, mask_reg;
-
- ctla = t4_read_reg(adap, MPS_TRC_FILTER_MATCH_CTL_A + ofst);
- ctlb = t4_read_reg(adap, MPS_TRC_FILTER_MATCH_CTL_B + ofst);
-
- *enabled = !!(ctla & TFEN);
- tp->snap_len = TFCAPTUREMAX_GET(ctlb);
- tp->min_len = TFMINPKTSIZE_GET(ctlb);
- tp->skip_ofst = TFOFFSET_GET(ctla);
- tp->skip_len = TFLENGTH_GET(ctla);
- tp->invert = !!(ctla & TFINVERTMATCH);
- tp->port = TFPORT_GET(ctla);
-
- ofst = (MPS_TRC_FILTER1_MATCH - MPS_TRC_FILTER0_MATCH) * idx;
- data_reg = MPS_TRC_FILTER0_MATCH + ofst;
- mask_reg = MPS_TRC_FILTER0_DONT_CARE + ofst;
-
- for (i = 0; i < TRACE_LEN / 4; i++, data_reg += 4, mask_reg += 4) {
- tp->mask[i] = ~t4_read_reg(adap, mask_reg);
- tp->data[i] = t4_read_reg(adap, data_reg) & tp->mask[i];
- }
-}
-
-/**
* get_mps_bg_map - return the buffer groups associated with a port
* @adap: the adapter
* @idx: the port index
@@ -2133,52 +1902,6 @@ void t4_get_port_stats(struct adapter *adap, int idx, struct port_stats *p)
}
/**
- * t4_get_lb_stats - collect loopback port statistics
- * @adap: the adapter
- * @idx: the loopback port index
- * @p: the stats structure to fill
- *
- * Return HW statistics for the given loopback port.
- */
-void t4_get_lb_stats(struct adapter *adap, int idx, struct lb_port_stats *p)
-{
- u32 bgmap = get_mps_bg_map(adap, idx);
-
-#define GET_STAT(name) \
- t4_read_reg64(adap, PORT_REG(idx, MPS_PORT_STAT_LB_PORT_##name##_L))
-#define GET_STAT_COM(name) t4_read_reg64(adap, MPS_STAT_##name##_L)
-
- p->octets = GET_STAT(BYTES);
- p->frames = GET_STAT(FRAMES);
- p->bcast_frames = GET_STAT(BCAST);
- p->mcast_frames = GET_STAT(MCAST);
- p->ucast_frames = GET_STAT(UCAST);
- p->error_frames = GET_STAT(ERROR);
-
- p->frames_64 = GET_STAT(64B);
- p->frames_65_127 = GET_STAT(65B_127B);
- p->frames_128_255 = GET_STAT(128B_255B);
- p->frames_256_511 = GET_STAT(256B_511B);
- p->frames_512_1023 = GET_STAT(512B_1023B);
- p->frames_1024_1518 = GET_STAT(1024B_1518B);
- p->frames_1519_max = GET_STAT(1519B_MAX);
- p->drop = t4_read_reg(adap, PORT_REG(idx,
- MPS_PORT_STAT_LB_PORT_DROP_FRAMES));
-
- p->ovflow0 = (bgmap & 1) ? GET_STAT_COM(RX_BG_0_LB_DROP_FRAME) : 0;
- p->ovflow1 = (bgmap & 2) ? GET_STAT_COM(RX_BG_1_LB_DROP_FRAME) : 0;
- p->ovflow2 = (bgmap & 4) ? GET_STAT_COM(RX_BG_2_LB_DROP_FRAME) : 0;
- p->ovflow3 = (bgmap & 8) ? GET_STAT_COM(RX_BG_3_LB_DROP_FRAME) : 0;
- p->trunc0 = (bgmap & 1) ? GET_STAT_COM(RX_BG_0_LB_TRUNC_FRAME) : 0;
- p->trunc1 = (bgmap & 2) ? GET_STAT_COM(RX_BG_1_LB_TRUNC_FRAME) : 0;
- p->trunc2 = (bgmap & 4) ? GET_STAT_COM(RX_BG_2_LB_TRUNC_FRAME) : 0;
- p->trunc3 = (bgmap & 8) ? GET_STAT_COM(RX_BG_3_LB_TRUNC_FRAME) : 0;
-
-#undef GET_STAT
-#undef GET_STAT_COM
-}
-
-/**
* t4_wol_magic_enable - enable/disable magic packet WoL
* @adap: the adapter
* @port: the physical port index
@@ -2584,30 +2307,6 @@ int t4_alloc_vi(struct adapter *adap, unsigned int mbox, unsigned int port,
}
/**
- * t4_free_vi - free a virtual interface
- * @adap: the adapter
- * @mbox: mailbox to use for the FW command
- * @pf: the PF owning the VI
- * @vf: the VF owning the VI
- * @viid: virtual interface identifiler
- *
- * Free a previously allocated virtual interface.
- */
-int t4_free_vi(struct adapter *adap, unsigned int mbox, unsigned int pf,
- unsigned int vf, unsigned int viid)
-{
- struct fw_vi_cmd c;
-
- memset(&c, 0, sizeof(c));
- c.op_to_vfn = htonl(FW_CMD_OP(FW_VI_CMD) | FW_CMD_REQUEST |
- FW_CMD_EXEC | FW_VI_CMD_PFN(pf) |
- FW_VI_CMD_VFN(vf));
- c.alloc_to_len16 = htonl(FW_VI_CMD_FREE | FW_LEN16(c));
- c.type_viid = htons(FW_VI_CMD_VIID(viid));
- return t4_wr_mbox(adap, mbox, &c, sizeof(c), &c);
-}
-
-/**
* t4_set_rxmode - set Rx properties of a virtual interface
* @adap: the adapter
* @mbox: mailbox to use for the FW command
@@ -2833,37 +2532,6 @@ int t4_identify_port(struct adapter *adap, unsigned int mbox, unsigned int viid,
}
/**
- * t4_iq_start_stop - enable/disable an ingress queue and its FLs
- * @adap: the adapter
- * @mbox: mailbox to use for the FW command
- * @start: %true to enable the queues, %false to disable them
- * @pf: the PF owning the queues
- * @vf: the VF owning the queues
- * @iqid: ingress queue id
- * @fl0id: FL0 queue id or 0xffff if no attached FL0
- * @fl1id: FL1 queue id or 0xffff if no attached FL1
- *
- * Starts or stops an ingress queue and its associated FLs, if any.
- */
-int t4_iq_start_stop(struct adapter *adap, unsigned int mbox, bool start,
- unsigned int pf, unsigned int vf, unsigned int iqid,
- unsigned int fl0id, unsigned int fl1id)
-{
- struct fw_iq_cmd c;
-
- memset(&c, 0, sizeof(c));
- c.op_to_vfn = htonl(FW_CMD_OP(FW_IQ_CMD) | FW_CMD_REQUEST |
- FW_CMD_EXEC | FW_IQ_CMD_PFN(pf) |
- FW_IQ_CMD_VFN(vf));
- c.alloc_to_len16 = htonl(FW_IQ_CMD_IQSTART(start) |
- FW_IQ_CMD_IQSTOP(!start) | FW_LEN16(c));
- c.iqid = htons(iqid);
- c.fl0id = htons(fl0id);
- c.fl1id = htons(fl1id);
- return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
-}
-
-/**
* t4_iq_free - free an ingress queue and its FLs
* @adap: the adapter
* @mbox: mailbox to use for the FW command
diff --git a/drivers/net/cxgb4/t4_hw.h b/drivers/net/cxgb4/t4_hw.h
index 10a055565776..c26b455f37de 100644
--- a/drivers/net/cxgb4/t4_hw.h
+++ b/drivers/net/cxgb4/t4_hw.h
@@ -42,6 +42,7 @@ enum {
MAX_MTU = 9600, /* max MAC MTU, excluding header + FCS */
EEPROMSIZE = 17408, /* Serial EEPROM physical size */
EEPROMVSIZE = 32768, /* Serial EEPROM virtual address space size */
+ EEPROMPFSIZE = 1024, /* EEPROM writable area size for PFn, n>0 */
RSS_NENTRIES = 2048, /* # of entries in RSS mapping table */
TCB_SIZE = 128, /* TCB size */
NMTUS = 16, /* size of MTU table */
diff --git a/drivers/net/cxgb4/t4fw_api.h b/drivers/net/cxgb4/t4fw_api.h
index 0969f2fbc1b0..940584a8a640 100644
--- a/drivers/net/cxgb4/t4fw_api.h
+++ b/drivers/net/cxgb4/t4fw_api.h
@@ -487,6 +487,11 @@ enum fw_params_param_pfvf {
FW_PARAMS_PARAM_PFVF_CPMASK = 0x25,
FW_PARAMS_PARAM_PFVF_OCQ_START = 0x26,
FW_PARAMS_PARAM_PFVF_OCQ_END = 0x27,
+ FW_PARAMS_PARAM_PFVF_CONM_MAP = 0x28,
+ FW_PARAMS_PARAM_PFVF_IQFLINT_START = 0x29,
+ FW_PARAMS_PARAM_PFVF_IQFLINT_END = 0x2A,
+ FW_PARAMS_PARAM_PFVF_EQ_START = 0x2B,
+ FW_PARAMS_PARAM_PFVF_EQ_END = 0x2C,
};
/*
diff --git a/drivers/net/cxgb4vf/cxgb4vf_main.c b/drivers/net/cxgb4vf/cxgb4vf_main.c
index 7b6d07f50c71..555ecc5a2e93 100644
--- a/drivers/net/cxgb4vf/cxgb4vf_main.c
+++ b/drivers/net/cxgb4vf/cxgb4vf_main.c
@@ -748,7 +748,10 @@ static int cxgb4vf_open(struct net_device *dev)
/*
* Note that this interface is up and start everything up ...
*/
- dev->real_num_tx_queues = pi->nqsets;
+ netif_set_real_num_tx_queues(dev, pi->nqsets);
+ err = netif_set_real_num_rx_queues(dev, pi->nqsets);
+ if (err)
+ return err;
set_bit(pi->port_id, &adapter->open_device_map);
link_start(dev);
netif_tx_start_all_queues(dev);
diff --git a/drivers/net/cxgb4vf/sge.c b/drivers/net/cxgb4vf/sge.c
index eb5a1c9cb2d3..f10864ddafbe 100644
--- a/drivers/net/cxgb4vf/sge.c
+++ b/drivers/net/cxgb4vf/sge.c
@@ -1520,7 +1520,6 @@ int t4vf_ethrx_handler(struct sge_rspq *rspq, const __be64 *rsp,
__skb_pull(skb, PKTSHIFT);
skb->protocol = eth_type_trans(skb, rspq->netdev);
skb_record_rx_queue(skb, rspq->idx);
- skb->dev->last_rx = jiffies; /* XXX removed 2.6.29 */
pi = netdev_priv(skb->dev);
rxq->stats.pkts++;
@@ -1535,7 +1534,7 @@ int t4vf_ethrx_handler(struct sge_rspq *rspq, const __be64 *rsp,
}
rxq->stats.rx_cso++;
} else
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
if (unlikely(pkt->vlan_ex)) {
struct vlan_group *grp = pi->vlan_grp;
diff --git a/drivers/net/cxgb4vf/t4vf_common.h b/drivers/net/cxgb4vf/t4vf_common.h
index 5c7bde7f9bae..873cb7d86c57 100644
--- a/drivers/net/cxgb4vf/t4vf_common.h
+++ b/drivers/net/cxgb4vf/t4vf_common.h
@@ -132,15 +132,15 @@ struct rss_params {
unsigned int mode; /* RSS mode */
union {
struct {
- int synmapen:1; /* SYN Map Enable */
- int syn4tupenipv6:1; /* enable hashing 4-tuple IPv6 SYNs */
- int syn2tupenipv6:1; /* enable hashing 2-tuple IPv6 SYNs */
- int syn4tupenipv4:1; /* enable hashing 4-tuple IPv4 SYNs */
- int syn2tupenipv4:1; /* enable hashing 2-tuple IPv4 SYNs */
- int ofdmapen:1; /* Offload Map Enable */
- int tnlmapen:1; /* Tunnel Map Enable */
- int tnlalllookup:1; /* Tunnel All Lookup */
- int hashtoeplitz:1; /* use Toeplitz hash */
+ unsigned int synmapen:1; /* SYN Map Enable */
+ unsigned int syn4tupenipv6:1; /* enable hashing 4-tuple IPv6 SYNs */
+ unsigned int syn2tupenipv6:1; /* enable hashing 2-tuple IPv6 SYNs */
+ unsigned int syn4tupenipv4:1; /* enable hashing 4-tuple IPv4 SYNs */
+ unsigned int syn2tupenipv4:1; /* enable hashing 2-tuple IPv4 SYNs */
+ unsigned int ofdmapen:1; /* Offload Map Enable */
+ unsigned int tnlmapen:1; /* Tunnel Map Enable */
+ unsigned int tnlalllookup:1; /* Tunnel All Lookup */
+ unsigned int hashtoeplitz:1; /* use Toeplitz hash */
} basicvirtual;
} u;
};
@@ -151,10 +151,10 @@ struct rss_params {
union rss_vi_config {
struct {
u16 defaultq; /* Ingress Queue ID for !tnlalllookup */
- int ip6fourtupen:1; /* hash 4-tuple IPv6 ingress packets */
- int ip6twotupen:1; /* hash 2-tuple IPv6 ingress packets */
- int ip4fourtupen:1; /* hash 4-tuple IPv4 ingress packets */
- int ip4twotupen:1; /* hash 2-tuple IPv4 ingress packets */
+ unsigned int ip6fourtupen:1; /* hash 4-tuple IPv6 ingress packets */
+ unsigned int ip6twotupen:1; /* hash 2-tuple IPv6 ingress packets */
+ unsigned int ip4fourtupen:1; /* hash 4-tuple IPv4 ingress packets */
+ unsigned int ip4twotupen:1; /* hash 2-tuple IPv4 ingress packets */
int udpen; /* hash 4-tuple UDP ingress packets */
} basicvirtual;
};
diff --git a/drivers/net/de620.c b/drivers/net/de620.c
index f3650fd096f4..1c51a7576119 100644
--- a/drivers/net/de620.c
+++ b/drivers/net/de620.c
@@ -676,7 +676,7 @@ static int de620_rx_intr(struct net_device *dev)
de620_set_register(dev, W_NPRF, next_rx_page);
pr_debug("next_rx_page=%d CPR=%d\n", next_rx_page, curr_page);
- return (next_rx_page != curr_page); /* That was slightly tricky... */
+ return next_rx_page != curr_page; /* That was slightly tricky... */
}
/*********************************************
diff --git a/drivers/net/declance.c b/drivers/net/declance.c
index d7de376d7178..219eb5ad5c12 100644
--- a/drivers/net/declance.c
+++ b/drivers/net/declance.c
@@ -1255,7 +1255,7 @@ static int __devinit dec_lance_probe(struct device *bdev, const int type)
*/
init_timer(&lp->multicast_timer);
lp->multicast_timer.data = (unsigned long) dev;
- lp->multicast_timer.function = &lance_set_multicast_retry;
+ lp->multicast_timer.function = lance_set_multicast_retry;
ret = register_netdev(dev);
if (ret) {
diff --git a/drivers/net/defxx.c b/drivers/net/defxx.c
index e5667c55844e..417e14385623 100644
--- a/drivers/net/defxx.c
+++ b/drivers/net/defxx.c
@@ -1024,7 +1024,7 @@ static int __devinit dfx_driver_init(struct net_device *dev,
&data) != DFX_K_SUCCESS) {
printk("%s: Could not read adapter factory MAC address!\n",
print_name);
- return(DFX_K_FAILURE);
+ return DFX_K_FAILURE;
}
le32 = cpu_to_le32(data);
memcpy(&bp->factory_mac_addr[0], &le32, sizeof(u32));
@@ -1033,7 +1033,7 @@ static int __devinit dfx_driver_init(struct net_device *dev,
&data) != DFX_K_SUCCESS) {
printk("%s: Could not read adapter factory MAC address!\n",
print_name);
- return(DFX_K_FAILURE);
+ return DFX_K_FAILURE;
}
le32 = cpu_to_le32(data);
memcpy(&bp->factory_mac_addr[4], &le32, sizeof(u16));
@@ -1075,7 +1075,7 @@ static int __devinit dfx_driver_init(struct net_device *dev,
if (top_v == NULL) {
printk("%s: Could not allocate memory for host buffers "
"and structures!\n", print_name);
- return(DFX_K_FAILURE);
+ return DFX_K_FAILURE;
}
memset(top_v, 0, alloc_size); /* zero out memory before continuing */
top_p = bp->kmalloced_dma; /* get physical address of buffer */
@@ -1145,7 +1145,7 @@ static int __devinit dfx_driver_init(struct net_device *dev,
DBG_printk("%s: Consumer block virt = %0lX, phys = %0X\n",
print_name, (long)bp->cons_block_virt, bp->cons_block_phys);
- return(DFX_K_SUCCESS);
+ return DFX_K_SUCCESS;
}
@@ -1195,7 +1195,7 @@ static int dfx_adap_init(DFX_board_t *bp, int get_buffers)
if (dfx_hw_dma_uninit(bp, bp->reset_type) != DFX_K_SUCCESS)
{
printk("%s: Could not uninitialize/reset adapter!\n", bp->dev->name);
- return(DFX_K_FAILURE);
+ return DFX_K_FAILURE;
}
/*
@@ -1229,7 +1229,7 @@ static int dfx_adap_init(DFX_board_t *bp, int get_buffers)
NULL) != DFX_K_SUCCESS)
{
printk("%s: Could not set adapter burst size!\n", bp->dev->name);
- return(DFX_K_FAILURE);
+ return DFX_K_FAILURE;
}
/*
@@ -1246,7 +1246,7 @@ static int dfx_adap_init(DFX_board_t *bp, int get_buffers)
NULL) != DFX_K_SUCCESS)
{
printk("%s: Could not set consumer block address!\n", bp->dev->name);
- return(DFX_K_FAILURE);
+ return DFX_K_FAILURE;
}
/*
@@ -1278,7 +1278,7 @@ static int dfx_adap_init(DFX_board_t *bp, int get_buffers)
if (dfx_hw_dma_cmd_req(bp) != DFX_K_SUCCESS)
{
printk("%s: DMA command request failed!\n", bp->dev->name);
- return(DFX_K_FAILURE);
+ return DFX_K_FAILURE;
}
/* Set the initial values for eFDXEnable and MACTReq MIB objects */
@@ -1294,7 +1294,7 @@ static int dfx_adap_init(DFX_board_t *bp, int get_buffers)
if (dfx_hw_dma_cmd_req(bp) != DFX_K_SUCCESS)
{
printk("%s: DMA command request failed!\n", bp->dev->name);
- return(DFX_K_FAILURE);
+ return DFX_K_FAILURE;
}
/* Initialize adapter CAM */
@@ -1302,7 +1302,7 @@ static int dfx_adap_init(DFX_board_t *bp, int get_buffers)
if (dfx_ctl_update_cam(bp) != DFX_K_SUCCESS)
{
printk("%s: Adapter CAM update failed!\n", bp->dev->name);
- return(DFX_K_FAILURE);
+ return DFX_K_FAILURE;
}
/* Initialize adapter filters */
@@ -1310,7 +1310,7 @@ static int dfx_adap_init(DFX_board_t *bp, int get_buffers)
if (dfx_ctl_update_filters(bp) != DFX_K_SUCCESS)
{
printk("%s: Adapter filters update failed!\n", bp->dev->name);
- return(DFX_K_FAILURE);
+ return DFX_K_FAILURE;
}
/*
@@ -1328,7 +1328,7 @@ static int dfx_adap_init(DFX_board_t *bp, int get_buffers)
printk("%s: Receive buffer allocation failed\n", bp->dev->name);
if (get_buffers)
dfx_rcv_flush(bp);
- return(DFX_K_FAILURE);
+ return DFX_K_FAILURE;
}
/* Issue START command and bring adapter to LINK_(UN)AVAILABLE state */
@@ -1339,13 +1339,13 @@ static int dfx_adap_init(DFX_board_t *bp, int get_buffers)
printk("%s: Start command failed\n", bp->dev->name);
if (get_buffers)
dfx_rcv_flush(bp);
- return(DFX_K_FAILURE);
+ return DFX_K_FAILURE;
}
/* Initialization succeeded, reenable PDQ interrupts */
dfx_port_write_long(bp, PI_PDQ_K_REG_HOST_INT_ENB, PI_HOST_INT_K_ENABLE_DEF_INTS);
- return(DFX_K_SUCCESS);
+ return DFX_K_SUCCESS;
}
@@ -1434,7 +1434,7 @@ static int dfx_open(struct net_device *dev)
/* Set device structure info */
netif_start_queue(dev);
- return(0);
+ return 0;
}
@@ -1526,7 +1526,7 @@ static int dfx_close(struct net_device *dev)
free_irq(dev->irq, dev);
- return(0);
+ return 0;
}
@@ -2027,7 +2027,7 @@ static struct net_device_stats *dfx_ctl_get_stats(struct net_device *dev)
bp->cmd_req_virt->cmd_type = PI_CMD_K_SMT_MIB_GET;
if (dfx_hw_dma_cmd_req(bp) != DFX_K_SUCCESS)
- return((struct net_device_stats *) &bp->stats);
+ return (struct net_device_stats *)&bp->stats;
/* Fill the bp->stats structure with the SMT MIB object values */
@@ -2128,7 +2128,7 @@ static struct net_device_stats *dfx_ctl_get_stats(struct net_device *dev)
bp->cmd_req_virt->cmd_type = PI_CMD_K_CNTRS_GET;
if (dfx_hw_dma_cmd_req(bp) != DFX_K_SUCCESS)
- return((struct net_device_stats *) &bp->stats);
+ return (struct net_device_stats *)&bp->stats;
/* Fill the bp->stats structure with the FDDI counter values */
@@ -2144,7 +2144,7 @@ static struct net_device_stats *dfx_ctl_get_stats(struct net_device *dev)
bp->stats.port_lem_cts[0] = bp->cmd_rsp_virt->cntrs_get.cntrs.link_errors[0].ls;
bp->stats.port_lem_cts[1] = bp->cmd_rsp_virt->cntrs_get.cntrs.link_errors[1].ls;
- return((struct net_device_stats *) &bp->stats);
+ return (struct net_device_stats *)&bp->stats;
}
@@ -2354,7 +2354,7 @@ static int dfx_ctl_set_mac_address(struct net_device *dev, void *addr)
{
DBG_printk("%s: Adapter CAM updated with new MAC address\n", dev->name);
}
- return(0); /* always return zero */
+ return 0; /* always return zero */
}
@@ -2438,8 +2438,8 @@ static int dfx_ctl_update_cam(DFX_board_t *bp)
/* Issue command to update adapter CAM, then return */
if (dfx_hw_dma_cmd_req(bp) != DFX_K_SUCCESS)
- return(DFX_K_FAILURE);
- return(DFX_K_SUCCESS);
+ return DFX_K_FAILURE;
+ return DFX_K_SUCCESS;
}
@@ -2504,8 +2504,8 @@ static int dfx_ctl_update_filters(DFX_board_t *bp)
/* Issue command to update adapter filters, then return */
if (dfx_hw_dma_cmd_req(bp) != DFX_K_SUCCESS)
- return(DFX_K_FAILURE);
- return(DFX_K_SUCCESS);
+ return DFX_K_FAILURE;
+ return DFX_K_SUCCESS;
}
@@ -2561,7 +2561,7 @@ static int dfx_hw_dma_cmd_req(DFX_board_t *bp)
(status == PI_STATE_K_HALTED) ||
(status == PI_STATE_K_DMA_UNAVAIL) ||
(status == PI_STATE_K_UPGRADE))
- return(DFX_K_OUTSTATE);
+ return DFX_K_OUTSTATE;
/* Put response buffer on the command response queue */
@@ -2599,7 +2599,7 @@ static int dfx_hw_dma_cmd_req(DFX_board_t *bp)
udelay(100); /* wait for 100 microseconds */
}
if (timeout_cnt == 0)
- return(DFX_K_HW_TIMEOUT);
+ return DFX_K_HW_TIMEOUT;
/* Bump (and wrap) the completion index and write out to register */
@@ -2619,14 +2619,14 @@ static int dfx_hw_dma_cmd_req(DFX_board_t *bp)
udelay(100); /* wait for 100 microseconds */
}
if (timeout_cnt == 0)
- return(DFX_K_HW_TIMEOUT);
+ return DFX_K_HW_TIMEOUT;
/* Bump (and wrap) the completion index and write out to register */
bp->cmd_rsp_reg.index.comp += 1;
bp->cmd_rsp_reg.index.comp &= PI_CMD_RSP_K_NUM_ENTRIES-1;
dfx_port_write_long(bp, PI_PDQ_K_REG_CMD_RSP_PROD, bp->cmd_rsp_reg.lword);
- return(DFX_K_SUCCESS);
+ return DFX_K_SUCCESS;
}
@@ -2700,7 +2700,7 @@ static int dfx_hw_port_ctrl_req(
udelay(100); /* wait for 100 microseconds */
}
if (timeout_cnt == 0)
- return(DFX_K_HW_TIMEOUT);
+ return DFX_K_HW_TIMEOUT;
/*
* If the address of host_data is non-zero, assume caller has supplied a
@@ -2710,7 +2710,7 @@ static int dfx_hw_port_ctrl_req(
if (host_data != NULL)
dfx_port_read_long(bp, PI_PDQ_K_REG_HOST_DATA, host_data);
- return(DFX_K_SUCCESS);
+ return DFX_K_SUCCESS;
}
@@ -2800,7 +2800,7 @@ static int dfx_hw_adap_state_rd(DFX_board_t *bp)
PI_UINT32 port_status; /* Port Status register value */
dfx_port_read_long(bp, PI_PDQ_K_REG_PORT_STATUS, &port_status);
- return((port_status & PI_PSTATUS_M_STATE) >> PI_PSTATUS_V_STATE);
+ return (port_status & PI_PSTATUS_M_STATE) >> PI_PSTATUS_V_STATE;
}
@@ -2852,8 +2852,8 @@ static int dfx_hw_dma_uninit(DFX_board_t *bp, PI_UINT32 type)
udelay(100); /* wait for 100 microseconds */
}
if (timeout_cnt == 0)
- return(DFX_K_HW_TIMEOUT);
- return(DFX_K_SUCCESS);
+ return DFX_K_HW_TIMEOUT;
+ return DFX_K_SUCCESS;
}
/*
diff --git a/drivers/net/dl2k.c b/drivers/net/dl2k.c
index a2f238d20caa..e1a8216ff692 100644
--- a/drivers/net/dl2k.c
+++ b/drivers/net/dl2k.c
@@ -465,7 +465,7 @@ rio_open (struct net_device *dev)
init_timer (&np->timer);
np->timer.expires = jiffies + 1*HZ;
np->timer.data = (unsigned long) dev;
- np->timer.function = &rio_timer;
+ np->timer.function = rio_timer;
add_timer (&np->timer);
/* Start Tx/Rx */
diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
index 4fd6b2b4554b..9f6aeefa06bf 100644
--- a/drivers/net/dm9000.c
+++ b/drivers/net/dm9000.c
@@ -1056,7 +1056,7 @@ dm9000_rx(struct net_device *dev)
if ((((rxbyte & 0x1c) << 3) & rxbyte) == 0)
skb->ip_summed = CHECKSUM_UNNECESSARY;
else
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
}
netif_rx(skb);
dev->stats.rx_packets++;
diff --git a/drivers/net/dnet.c b/drivers/net/dnet.c
index 7c075756611a..9d8a20b72fa9 100644
--- a/drivers/net/dnet.c
+++ b/drivers/net/dnet.c
@@ -27,7 +27,7 @@
#undef DEBUG
/* function for reading internal MAC register */
-u16 dnet_readw_mac(struct dnet *bp, u16 reg)
+static u16 dnet_readw_mac(struct dnet *bp, u16 reg)
{
u16 data_read;
@@ -46,7 +46,7 @@ u16 dnet_readw_mac(struct dnet *bp, u16 reg)
}
/* function for writing internal MAC register */
-void dnet_writew_mac(struct dnet *bp, u16 reg, u16 val)
+static void dnet_writew_mac(struct dnet *bp, u16 reg, u16 val)
{
/* load data to write */
dnet_writel(bp, val, MACREG_DATA);
@@ -63,11 +63,11 @@ static void __dnet_set_hwaddr(struct dnet *bp)
{
u16 tmp;
- tmp = cpu_to_be16(*((u16 *) bp->dev->dev_addr));
+ tmp = be16_to_cpup((__be16 *)bp->dev->dev_addr);
dnet_writew_mac(bp, DNET_INTERNAL_MAC_ADDR_0_REG, tmp);
- tmp = cpu_to_be16(*((u16 *) (bp->dev->dev_addr + 2)));
+ tmp = be16_to_cpup((__be16 *)(bp->dev->dev_addr + 2));
dnet_writew_mac(bp, DNET_INTERNAL_MAC_ADDR_1_REG, tmp);
- tmp = cpu_to_be16(*((u16 *) (bp->dev->dev_addr + 4)));
+ tmp = be16_to_cpup((__be16 *)(bp->dev->dev_addr + 4));
dnet_writew_mac(bp, DNET_INTERNAL_MAC_ADDR_2_REG, tmp);
}
@@ -89,11 +89,11 @@ static void __devinit dnet_get_hwaddr(struct dnet *bp)
* Mac_addr[15:0]).
*/
tmp = dnet_readw_mac(bp, DNET_INTERNAL_MAC_ADDR_0_REG);
- *((u16 *) addr) = be16_to_cpu(tmp);
+ *((__be16 *)addr) = cpu_to_be16(tmp);
tmp = dnet_readw_mac(bp, DNET_INTERNAL_MAC_ADDR_1_REG);
- *((u16 *) (addr + 2)) = be16_to_cpu(tmp);
+ *((__be16 *)(addr + 2)) = cpu_to_be16(tmp);
tmp = dnet_readw_mac(bp, DNET_INTERNAL_MAC_ADDR_2_REG);
- *((u16 *) (addr + 4)) = be16_to_cpu(tmp);
+ *((__be16 *)(addr + 4)) = cpu_to_be16(tmp);
if (is_valid_ether_addr(addr))
memcpy(bp->dev->dev_addr, addr, sizeof(addr));
@@ -361,7 +361,7 @@ err_out:
}
/* For Neptune board: LINK1000 as Link LED and TX as activity LED */
-int dnet_phy_marvell_fixup(struct phy_device *phydev)
+static int dnet_phy_marvell_fixup(struct phy_device *phydev)
{
return phy_write(phydev, 0x18, 0x4148);
}
diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c
index 37dcfdc63456..ff2d29b17858 100644
--- a/drivers/net/dummy.c
+++ b/drivers/net/dummy.c
@@ -36,6 +36,7 @@
#include <linux/moduleparam.h>
#include <linux/rtnetlink.h>
#include <net/rtnetlink.h>
+#include <linux/u64_stats_sync.h>
static int numdummies = 1;
@@ -55,21 +56,69 @@ static void set_multicast_list(struct net_device *dev)
{
}
+struct pcpu_dstats {
+ u64 tx_packets;
+ u64 tx_bytes;
+ struct u64_stats_sync syncp;
+};
+
+static struct rtnl_link_stats64 *dummy_get_stats64(struct net_device *dev,
+ struct rtnl_link_stats64 *stats)
+{
+ int i;
+
+ for_each_possible_cpu(i) {
+ const struct pcpu_dstats *dstats;
+ u64 tbytes, tpackets;
+ unsigned int start;
+
+ dstats = per_cpu_ptr(dev->dstats, i);
+ do {
+ start = u64_stats_fetch_begin(&dstats->syncp);
+ tbytes = dstats->tx_bytes;
+ tpackets = dstats->tx_packets;
+ } while (u64_stats_fetch_retry(&dstats->syncp, start));
+ stats->tx_bytes += tbytes;
+ stats->tx_packets += tpackets;
+ }
+ return stats;
+}
static netdev_tx_t dummy_xmit(struct sk_buff *skb, struct net_device *dev)
{
- dev->stats.tx_packets++;
- dev->stats.tx_bytes += skb->len;
+ struct pcpu_dstats *dstats = this_cpu_ptr(dev->dstats);
+
+ u64_stats_update_begin(&dstats->syncp);
+ dstats->tx_packets++;
+ dstats->tx_bytes += skb->len;
+ u64_stats_update_end(&dstats->syncp);
dev_kfree_skb(skb);
return NETDEV_TX_OK;
}
+static int dummy_dev_init(struct net_device *dev)
+{
+ dev->dstats = alloc_percpu(struct pcpu_dstats);
+ if (!dev->dstats)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static void dummy_dev_free(struct net_device *dev)
+{
+ free_percpu(dev->dstats);
+ free_netdev(dev);
+}
+
static const struct net_device_ops dummy_netdev_ops = {
+ .ndo_init = dummy_dev_init,
.ndo_start_xmit = dummy_xmit,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_multicast_list = set_multicast_list,
.ndo_set_mac_address = dummy_set_address,
+ .ndo_get_stats64 = dummy_get_stats64,
};
static void dummy_setup(struct net_device *dev)
@@ -78,14 +127,17 @@ static void dummy_setup(struct net_device *dev)
/* Initialize the device structure. */
dev->netdev_ops = &dummy_netdev_ops;
- dev->destructor = free_netdev;
+ dev->destructor = dummy_dev_free;
/* Fill in device structure with ethernet-generic values. */
dev->tx_queue_len = 0;
dev->flags |= IFF_NOARP;
dev->flags &= ~IFF_MULTICAST;
+ dev->features |= NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_TSO;
+ dev->features |= NETIF_F_NO_CSUM | NETIF_F_HIGHDMA | NETIF_F_LLTX;
random_ether_addr(dev->dev_addr);
}
+
static int dummy_validate(struct nlattr *tb[], struct nlattr *data[])
{
if (tb[IFLA_ADDRESS]) {
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index 8e2eab4e7c75..b0aa9e68990a 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -2215,10 +2215,10 @@ static int e100_change_mtu(struct net_device *netdev, int new_mtu)
static int e100_asf(struct nic *nic)
{
/* ASF can be enabled from eeprom */
- return((nic->pdev->device >= 0x1050) && (nic->pdev->device <= 0x1057) &&
+ return (nic->pdev->device >= 0x1050) && (nic->pdev->device <= 0x1057) &&
(nic->eeprom[eeprom_config_asf] & eeprom_asf) &&
!(nic->eeprom[eeprom_config_asf] & eeprom_gcl) &&
- ((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE));
+ ((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE);
}
static int e100_up(struct nic *nic)
diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
index 99288b95aead..a881dd0093bd 100644
--- a/drivers/net/e1000/e1000.h
+++ b/drivers/net/e1000/e1000.h
@@ -310,6 +310,9 @@ struct e1000_adapter {
int need_ioport;
bool discarding;
+
+ struct work_struct fifo_stall_task;
+ struct work_struct phy_info_task;
};
enum e1000_state_t {
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 5cc39ed289c6..a117f2a0252e 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -123,8 +123,10 @@ static void e1000_clean_rx_ring(struct e1000_adapter *adapter,
struct e1000_rx_ring *rx_ring);
static void e1000_set_rx_mode(struct net_device *netdev);
static void e1000_update_phy_info(unsigned long data);
+static void e1000_update_phy_info_task(struct work_struct *work);
static void e1000_watchdog(unsigned long data);
static void e1000_82547_tx_fifo_stall(unsigned long data);
+static void e1000_82547_tx_fifo_stall_task(struct work_struct *work);
static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
struct net_device *netdev);
static struct net_device_stats * e1000_get_stats(struct net_device *netdev);
@@ -519,8 +521,21 @@ void e1000_down(struct e1000_adapter *adapter)
e1000_clean_all_rx_rings(adapter);
}
+void e1000_reinit_safe(struct e1000_adapter *adapter)
+{
+ while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
+ msleep(1);
+ rtnl_lock();
+ e1000_down(adapter);
+ e1000_up(adapter);
+ rtnl_unlock();
+ clear_bit(__E1000_RESETTING, &adapter->flags);
+}
+
void e1000_reinit_locked(struct e1000_adapter *adapter)
{
+ /* if rtnl_lock is not held the call path is bogus */
+ ASSERT_RTNL();
WARN_ON(in_interrupt());
while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
msleep(1);
@@ -790,6 +805,70 @@ static const struct net_device_ops e1000_netdev_ops = {
};
/**
+ * e1000_init_hw_struct - initialize members of hw struct
+ * @adapter: board private struct
+ * @hw: structure used by e1000_hw.c
+ *
+ * Factors out initialization of the e1000_hw struct to its own function
+ * that can be called very early at init (just after struct allocation).
+ * Fields are initialized based on PCI device information and
+ * OS network device settings (MTU size).
+ * Returns negative error codes if MAC type setup fails.
+ */
+static int e1000_init_hw_struct(struct e1000_adapter *adapter,
+ struct e1000_hw *hw)
+{
+ struct pci_dev *pdev = adapter->pdev;
+
+ /* PCI config space info */
+ hw->vendor_id = pdev->vendor;
+ hw->device_id = pdev->device;
+ hw->subsystem_vendor_id = pdev->subsystem_vendor;
+ hw->subsystem_id = pdev->subsystem_device;
+ hw->revision_id = pdev->revision;
+
+ pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word);
+
+ hw->max_frame_size = adapter->netdev->mtu +
+ ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
+ hw->min_frame_size = MINIMUM_ETHERNET_FRAME_SIZE;
+
+ /* identify the MAC */
+ if (e1000_set_mac_type(hw)) {
+ e_err(probe, "Unknown MAC Type\n");
+ return -EIO;
+ }
+
+ switch (hw->mac_type) {
+ default:
+ break;
+ case e1000_82541:
+ case e1000_82547:
+ case e1000_82541_rev_2:
+ case e1000_82547_rev_2:
+ hw->phy_init_script = 1;
+ break;
+ }
+
+ e1000_set_media_type(hw);
+ e1000_get_bus_info(hw);
+
+ hw->wait_autoneg_complete = false;
+ hw->tbi_compatibility_en = true;
+ hw->adaptive_ifs = true;
+
+ /* Copper options */
+
+ if (hw->media_type == e1000_media_type_copper) {
+ hw->mdix = AUTO_ALL_MODES;
+ hw->disable_polarity_correction = false;
+ hw->master_slave = E1000_MASTER_SLAVE;
+ }
+
+ return 0;
+}
+
+/**
* e1000_probe - Device Initialization Routine
* @pdev: PCI device information struct
* @ent: entry in e1000_pci_tbl
@@ -826,22 +905,6 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
if (err)
return err;
- if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)) &&
- !dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64))) {
- pci_using_dac = 1;
- } else {
- err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
- if (err) {
- err = dma_set_coherent_mask(&pdev->dev,
- DMA_BIT_MASK(32));
- if (err) {
- pr_err("No usable DMA config, aborting\n");
- goto err_dma;
- }
- }
- pci_using_dac = 0;
- }
-
err = pci_request_selected_regions(pdev, bars, e1000_driver_name);
if (err)
goto err_pci_reg;
@@ -885,6 +948,32 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
}
}
+ /* make ready for any if (hw->...) below */
+ err = e1000_init_hw_struct(adapter, hw);
+ if (err)
+ goto err_sw_init;
+
+ /*
+ * there is a workaround being applied below that limits
+ * 64-bit DMA addresses to 64-bit hardware. There are some
+ * 32-bit adapters that Tx hang when given 64-bit DMA addresses
+ */
+ pci_using_dac = 0;
+ if ((hw->bus_type == e1000_bus_type_pcix) &&
+ !dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) {
+ /*
+ * according to DMA-API-HOWTO, coherent calls will always
+ * succeed if the set call did
+ */
+ dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64));
+ pci_using_dac = 1;
+ } else if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(32))) {
+ dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
+ } else {
+ pr_err("No usable DMA config, aborting\n");
+ goto err_dma;
+ }
+
netdev->netdev_ops = &e1000_netdev_ops;
e1000_set_ethtool_ops(netdev);
netdev->watchdog_timeo = 5 * HZ;
@@ -914,8 +1003,10 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
(hw->mac_type != e1000_82547))
netdev->features |= NETIF_F_TSO;
- if (pci_using_dac)
+ if (pci_using_dac) {
netdev->features |= NETIF_F_HIGHDMA;
+ netdev->vlan_features |= NETIF_F_HIGHDMA;
+ }
netdev->vlan_features |= NETIF_F_TSO;
netdev->vlan_features |= NETIF_F_HW_CSUM;
@@ -959,21 +1050,21 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
if (!is_valid_ether_addr(netdev->perm_addr))
e_err(probe, "Invalid MAC Address\n");
- e1000_get_bus_info(hw);
-
init_timer(&adapter->tx_fifo_stall_timer);
- adapter->tx_fifo_stall_timer.function = &e1000_82547_tx_fifo_stall;
+ adapter->tx_fifo_stall_timer.function = e1000_82547_tx_fifo_stall;
adapter->tx_fifo_stall_timer.data = (unsigned long)adapter;
init_timer(&adapter->watchdog_timer);
- adapter->watchdog_timer.function = &e1000_watchdog;
+ adapter->watchdog_timer.function = e1000_watchdog;
adapter->watchdog_timer.data = (unsigned long) adapter;
init_timer(&adapter->phy_info_timer);
- adapter->phy_info_timer.function = &e1000_update_phy_info;
+ adapter->phy_info_timer.function = e1000_update_phy_info;
adapter->phy_info_timer.data = (unsigned long)adapter;
+ INIT_WORK(&adapter->fifo_stall_task, e1000_82547_tx_fifo_stall_task);
INIT_WORK(&adapter->reset_task, e1000_reset_task);
+ INIT_WORK(&adapter->phy_info_task, e1000_update_phy_info_task);
e1000_check_options(adapter);
@@ -1072,6 +1163,7 @@ err_eeprom:
iounmap(hw->flash_address);
kfree(adapter->tx_ring);
kfree(adapter->rx_ring);
+err_dma:
err_sw_init:
iounmap(hw->hw_addr);
err_ioremap:
@@ -1079,7 +1171,6 @@ err_ioremap:
err_alloc_etherdev:
pci_release_selected_regions(pdev, bars);
err_pci_reg:
-err_dma:
pci_disable_device(pdev);
return err;
}
@@ -1131,62 +1222,12 @@ static void __devexit e1000_remove(struct pci_dev *pdev)
* @adapter: board private structure to initialize
*
* e1000_sw_init initializes the Adapter private data structure.
- * Fields are initialized based on PCI device information and
- * OS network device settings (MTU size).
+ * e1000_init_hw_struct MUST be called before this function
**/
static int __devinit e1000_sw_init(struct e1000_adapter *adapter)
{
- struct e1000_hw *hw = &adapter->hw;
- struct net_device *netdev = adapter->netdev;
- struct pci_dev *pdev = adapter->pdev;
-
- /* PCI config space info */
-
- hw->vendor_id = pdev->vendor;
- hw->device_id = pdev->device;
- hw->subsystem_vendor_id = pdev->subsystem_vendor;
- hw->subsystem_id = pdev->subsystem_device;
- hw->revision_id = pdev->revision;
-
- pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word);
-
adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
- hw->max_frame_size = netdev->mtu +
- ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
- hw->min_frame_size = MINIMUM_ETHERNET_FRAME_SIZE;
-
- /* identify the MAC */
-
- if (e1000_set_mac_type(hw)) {
- e_err(probe, "Unknown MAC Type\n");
- return -EIO;
- }
-
- switch (hw->mac_type) {
- default:
- break;
- case e1000_82541:
- case e1000_82547:
- case e1000_82541_rev_2:
- case e1000_82547_rev_2:
- hw->phy_init_script = 1;
- break;
- }
-
- e1000_set_media_type(hw);
-
- hw->wait_autoneg_complete = false;
- hw->tbi_compatibility_en = true;
- hw->adaptive_ifs = true;
-
- /* Copper options */
-
- if (hw->media_type == e1000_media_type_copper) {
- hw->mdix = AUTO_ALL_MODES;
- hw->disable_polarity_correction = false;
- hw->master_slave = E1000_MASTER_SLAVE;
- }
adapter->num_tx_queues = 1;
adapter->num_rx_queues = 1;
@@ -2210,22 +2251,45 @@ static void e1000_set_rx_mode(struct net_device *netdev)
static void e1000_update_phy_info(unsigned long data)
{
struct e1000_adapter *adapter = (struct e1000_adapter *)data;
+ schedule_work(&adapter->phy_info_task);
+}
+
+static void e1000_update_phy_info_task(struct work_struct *work)
+{
+ struct e1000_adapter *adapter = container_of(work,
+ struct e1000_adapter,
+ phy_info_task);
struct e1000_hw *hw = &adapter->hw;
+
+ rtnl_lock();
e1000_phy_get_info(hw, &adapter->phy_info);
+ rtnl_unlock();
}
/**
* e1000_82547_tx_fifo_stall - Timer Call-back
* @data: pointer to adapter cast into an unsigned long
**/
-
static void e1000_82547_tx_fifo_stall(unsigned long data)
{
struct e1000_adapter *adapter = (struct e1000_adapter *)data;
+ schedule_work(&adapter->fifo_stall_task);
+}
+
+/**
+ * e1000_82547_tx_fifo_stall_task - task to complete work
+ * @work: work struct contained inside adapter struct
+ **/
+static void e1000_82547_tx_fifo_stall_task(struct work_struct *work)
+{
+ struct e1000_adapter *adapter = container_of(work,
+ struct e1000_adapter,
+ fifo_stall_task);
struct e1000_hw *hw = &adapter->hw;
struct net_device *netdev = adapter->netdev;
u32 tctl;
+ rtnl_lock();
if (atomic_read(&adapter->tx_fifo_stall)) {
if ((er32(TDT) == er32(TDH)) &&
(er32(TDFT) == er32(TDFH)) &&
@@ -2246,6 +2310,7 @@ static void e1000_82547_tx_fifo_stall(unsigned long data)
mod_timer(&adapter->tx_fifo_stall_timer, jiffies + 1);
}
}
+ rtnl_unlock();
}
bool e1000_has_link(struct e1000_adapter *adapter)
@@ -3054,7 +3119,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
}
}
- if (unlikely(adapter->vlgrp && vlan_tx_tag_present(skb))) {
+ if (unlikely(vlan_tx_tag_present(skb))) {
tx_flags |= E1000_TX_FLAGS_VLAN;
tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT);
}
@@ -3113,7 +3178,7 @@ static void e1000_reset_task(struct work_struct *work)
struct e1000_adapter *adapter =
container_of(work, struct e1000_adapter, reset_task);
- e1000_reinit_locked(adapter);
+ e1000_reinit_safe(adapter);
}
/**
@@ -3535,7 +3600,7 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter,
adapter->total_tx_packets += total_tx_packets;
netdev->stats.tx_bytes += total_tx_bytes;
netdev->stats.tx_packets += total_tx_packets;
- return (count < tx_ring->count);
+ return count < tx_ring->count;
}
/**
@@ -3552,7 +3617,8 @@ static void e1000_rx_checksum(struct e1000_adapter *adapter, u32 status_err,
struct e1000_hw *hw = &adapter->hw;
u16 status = (u16)status_err;
u8 errors = (u8)(status_err >> 24);
- skb->ip_summed = CHECKSUM_NONE;
+
+ skb_checksum_none_assert(skb);
/* 82543 or newer only */
if (unlikely(hw->mac_type < e1000_82543)) return;
@@ -3598,13 +3664,14 @@ static void e1000_consume_page(struct e1000_buffer *bi, struct sk_buff *skb,
static void e1000_receive_skb(struct e1000_adapter *adapter, u8 status,
__le16 vlan, struct sk_buff *skb)
{
- if (unlikely(adapter->vlgrp && (status & E1000_RXD_STAT_VP))) {
- vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
- le16_to_cpu(vlan) &
- E1000_RXD_SPC_VLAN_MASK);
- } else {
- netif_receive_skb(skb);
- }
+ skb->protocol = eth_type_trans(skb, adapter->netdev);
+
+ if ((unlikely(adapter->vlgrp && (status & E1000_RXD_STAT_VP))))
+ vlan_gro_receive(&adapter->napi, adapter->vlgrp,
+ le16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK,
+ skb);
+ else
+ napi_gro_receive(&adapter->napi, skb);
}
/**
@@ -3762,8 +3829,6 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter,
goto next_desc;
}
- skb->protocol = eth_type_trans(skb, netdev);
-
e1000_receive_skb(adapter, status, rx_desc->special, skb);
next_desc:
@@ -3926,8 +3991,6 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
((u32)(rx_desc->errors) << 24),
le16_to_cpu(rx_desc->csum), skb);
- skb->protocol = eth_type_trans(skb, netdev);
-
e1000_receive_skb(adapter, status, rx_desc->special, skb);
next_desc:
@@ -4478,7 +4541,7 @@ static void e1000_restore_vlan(struct e1000_adapter *adapter)
if (adapter->vlgrp) {
u16 vid;
- for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
+ for (vid = 0; vid < VLAN_N_VID; vid++) {
if (!vlan_group_get_device(adapter->vlgrp, vid))
continue;
e1000_vlan_rx_add_vid(adapter->netdev, vid);
diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c
index d3d4a57e2450..ca663f19d7df 100644
--- a/drivers/net/e1000e/82571.c
+++ b/drivers/net/e1000e/82571.c
@@ -1801,7 +1801,8 @@ struct e1000_info e1000_82571_info = {
| FLAG_RESET_OVERWRITES_LAA /* errata */
| FLAG_TARC_SPEED_MODE_BIT /* errata */
| FLAG_APME_CHECK_PORT_B,
- .flags2 = FLAG2_DISABLE_ASPM_L1, /* errata 13 */
+ .flags2 = FLAG2_DISABLE_ASPM_L1 /* errata 13 */
+ | FLAG2_DMA_BURST,
.pba = 38,
.max_hw_frame_size = DEFAULT_JUMBO,
.get_variants = e1000_get_variants_82571,
@@ -1819,7 +1820,8 @@ struct e1000_info e1000_82572_info = {
| FLAG_RX_CSUM_ENABLED
| FLAG_HAS_CTRLEXT_ON_LOAD
| FLAG_TARC_SPEED_MODE_BIT, /* errata */
- .flags2 = FLAG2_DISABLE_ASPM_L1, /* errata 13 */
+ .flags2 = FLAG2_DISABLE_ASPM_L1 /* errata 13 */
+ | FLAG2_DMA_BURST,
.pba = 38,
.max_hw_frame_size = DEFAULT_JUMBO,
.get_variants = e1000_get_variants_82571,
diff --git a/drivers/net/e1000e/defines.h b/drivers/net/e1000e/defines.h
index 93b3bedae8d2..d3f7a9c3f973 100644
--- a/drivers/net/e1000e/defines.h
+++ b/drivers/net/e1000e/defines.h
@@ -446,7 +446,9 @@
/* Transmit Descriptor Control */
#define E1000_TXDCTL_PTHRESH 0x0000003F /* TXDCTL Prefetch Threshold */
+#define E1000_TXDCTL_HTHRESH 0x00003F00 /* TXDCTL Host Threshold */
#define E1000_TXDCTL_WTHRESH 0x003F0000 /* TXDCTL Writeback Threshold */
+#define E1000_TXDCTL_GRAN 0x01000000 /* TXDCTL Granularity */
#define E1000_TXDCTL_FULL_TX_DESC_WB 0x01010000 /* GRAN=1, WTHRESH=1 */
#define E1000_TXDCTL_MAX_TX_DESC_PREFETCH 0x0100001F /* GRAN=1, PTHRESH=31 */
/* Enable the counting of desc. still to be processed. */
diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h
index f9a31c82f871..cee882dd67bf 100644
--- a/drivers/net/e1000e/e1000.h
+++ b/drivers/net/e1000e/e1000.h
@@ -153,6 +153,33 @@ struct e1000_info;
/* Time to wait before putting the device into D3 if there's no link (in ms). */
#define LINK_TIMEOUT 100
+#define DEFAULT_RDTR 0
+#define DEFAULT_RADV 8
+#define BURST_RDTR 0x20
+#define BURST_RADV 0x20
+
+/*
+ * in the case of WTHRESH, it appears at least the 82571/2 hardware
+ * writes back 4 descriptors when WTHRESH=5, and 3 descriptors when
+ * WTHRESH=4, and since we want 64 bytes at a time written back, set
+ * it to 5
+ */
+#define E1000_TXDCTL_DMA_BURST_ENABLE \
+ (E1000_TXDCTL_GRAN | /* set descriptor granularity */ \
+ E1000_TXDCTL_COUNT_DESC | \
+ (5 << 16) | /* wthresh must be +1 more than desired */\
+ (1 << 8) | /* hthresh */ \
+ 0x1f) /* pthresh */
+
+#define E1000_RXDCTL_DMA_BURST_ENABLE \
+ (0x01000000 | /* set descriptor granularity */ \
+ (4 << 16) | /* set writeback threshold */ \
+ (4 << 8) | /* set prefetch threshold */ \
+ 0x20) /* set hthresh */
+
+#define E1000_TIDV_FPD (1 << 31)
+#define E1000_RDTR_FPD (1 << 31)
+
enum e1000_boards {
board_82571,
board_82572,
@@ -425,6 +452,8 @@ struct e1000_info {
#define FLAG2_DISABLE_ASPM_L1 (1 << 3)
#define FLAG2_HAS_PHY_STATS (1 << 4)
#define FLAG2_HAS_EEE (1 << 5)
+#define FLAG2_DMA_BURST (1 << 6)
+#define FLAG2_DISABLE_AIM (1 << 8)
#define E1000_RX_DESC_PS(R, i) \
(&(((union e1000_rx_desc_packet_split *)((R).desc))[i]))
diff --git a/drivers/net/e1000e/es2lan.c b/drivers/net/e1000e/es2lan.c
index 45aebb4a6fe1..24f8ac9cf703 100644
--- a/drivers/net/e1000e/es2lan.c
+++ b/drivers/net/e1000e/es2lan.c
@@ -1494,6 +1494,7 @@ struct e1000_info e1000_es2_info = {
| FLAG_APME_CHECK_PORT_B
| FLAG_DISABLE_FC_PAUSE_TIME /* errata */
| FLAG_TIPG_MEDIUM_FOR_80003ESLAN,
+ .flags2 = FLAG2_DMA_BURST,
.pba = 38,
.max_hw_frame_size = DEFAULT_JUMBO,
.get_variants = e1000_get_variants_80003es2lan,
diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c
index 6355a1b779d3..8984d165a39b 100644
--- a/drivers/net/e1000e/ethtool.c
+++ b/drivers/net/e1000e/ethtool.c
@@ -368,7 +368,7 @@ out:
static u32 e1000_get_rx_csum(struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
- return (adapter->flags & FLAG_RX_CSUM_ENABLED);
+ return adapter->flags & FLAG_RX_CSUM_ENABLED;
}
static int e1000_set_rx_csum(struct net_device *netdev, u32 data)
@@ -389,7 +389,7 @@ static int e1000_set_rx_csum(struct net_device *netdev, u32 data)
static u32 e1000_get_tx_csum(struct net_device *netdev)
{
- return ((netdev->features & NETIF_F_HW_CSUM) != 0);
+ return (netdev->features & NETIF_F_HW_CSUM) != 0;
}
static int e1000_set_tx_csum(struct net_device *netdev, u32 data)
@@ -1717,13 +1717,6 @@ static void e1000_diag_test(struct net_device *netdev,
e_info("offline testing starting\n");
- /*
- * Link test performed before hardware reset so autoneg doesn't
- * interfere with test result
- */
- if (e1000_link_test(adapter, &data[4]))
- eth_test->flags |= ETH_TEST_FL_FAILED;
-
if (if_running)
/* indicate we're in test mode */
dev_close(netdev);
@@ -1747,15 +1740,19 @@ static void e1000_diag_test(struct net_device *netdev,
if (e1000_loopback_test(adapter, &data[3]))
eth_test->flags |= ETH_TEST_FL_FAILED;
+ /* force this routine to wait until autoneg complete/timeout */
+ adapter->hw.phy.autoneg_wait_to_complete = 1;
+ e1000e_reset(adapter);
+ adapter->hw.phy.autoneg_wait_to_complete = 0;
+
+ if (e1000_link_test(adapter, &data[4]))
+ eth_test->flags |= ETH_TEST_FL_FAILED;
+
/* restore speed, duplex, autoneg settings */
adapter->hw.phy.autoneg_advertised = autoneg_advertised;
adapter->hw.mac.forced_speed_duplex = forced_speed_duplex;
adapter->hw.mac.autoneg = autoneg;
-
- /* force this routine to wait until autoneg complete/timeout */
- adapter->hw.phy.autoneg_wait_to_complete = 1;
e1000e_reset(adapter);
- adapter->hw.phy.autoneg_wait_to_complete = 0;
clear_bit(__E1000_TESTING, &adapter->state);
if (if_running)
diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c
index 57b5435599ab..e3374d9a2472 100644
--- a/drivers/net/e1000e/ich8lan.c
+++ b/drivers/net/e1000e/ich8lan.c
@@ -3986,7 +3986,7 @@ struct e1000_info e1000_pch2_info = {
| FLAG_APME_IN_WUC,
.flags2 = FLAG2_HAS_PHY_STATS
| FLAG2_HAS_EEE,
- .pba = 18,
+ .pba = 26,
.max_hw_frame_size = DEFAULT_JUMBO,
.get_variants = e1000_get_variants_ich8lan,
.mac_ops = &ich8_mac_ops,
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index e561d15c3eb1..ec8cf3f51423 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -475,7 +475,8 @@ static void e1000_rx_checksum(struct e1000_adapter *adapter, u32 status_err,
{
u16 status = (u16)status_err;
u8 errors = (u8)(status_err >> 24);
- skb->ip_summed = CHECKSUM_NONE;
+
+ skb_checksum_none_assert(skb);
/* Ignore Checksum bit is set */
if (status & E1000_RXD_STAT_IXSM)
@@ -1052,7 +1053,7 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter)
adapter->total_tx_packets += total_tx_packets;
netdev->stats.tx_bytes += total_tx_bytes;
netdev->stats.tx_packets += total_tx_packets;
- return (count < tx_ring->count);
+ return count < tx_ring->count;
}
/**
@@ -2289,6 +2290,11 @@ static void e1000_set_itr(struct e1000_adapter *adapter)
goto set_itr_now;
}
+ if (adapter->flags2 & FLAG2_DISABLE_AIM) {
+ new_itr = 0;
+ goto set_itr_now;
+ }
+
adapter->tx_itr = e1000_update_itr(adapter,
adapter->tx_itr,
adapter->total_tx_packets,
@@ -2337,7 +2343,10 @@ set_itr_now:
if (adapter->msix_entries)
adapter->rx_ring->set_itr = 1;
else
- ew32(ITR, 1000000000 / (new_itr * 256));
+ if (new_itr)
+ ew32(ITR, 1000000000 / (new_itr * 256));
+ else
+ ew32(ITR, 0);
}
}
@@ -2536,7 +2545,7 @@ static void e1000_restore_vlan(struct e1000_adapter *adapter)
if (!adapter->vlgrp)
return;
- for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
+ for (vid = 0; vid < VLAN_N_VID; vid++) {
if (!vlan_group_get_device(adapter->vlgrp, vid))
continue;
e1000_vlan_rx_add_vid(adapter->netdev, vid);
@@ -2649,6 +2658,26 @@ static void e1000_configure_tx(struct e1000_adapter *adapter)
/* Tx irq moderation */
ew32(TADV, adapter->tx_abs_int_delay);
+ if (adapter->flags2 & FLAG2_DMA_BURST) {
+ u32 txdctl = er32(TXDCTL(0));
+ txdctl &= ~(E1000_TXDCTL_PTHRESH | E1000_TXDCTL_HTHRESH |
+ E1000_TXDCTL_WTHRESH);
+ /*
+ * set up some performance related parameters to encourage the
+ * hardware to use the bus more efficiently in bursts, depends
+ * on the tx_int_delay to be enabled,
+ * wthresh = 5 ==> burst write a cacheline (64 bytes) at a time
+ * hthresh = 1 ==> prefetch when one or more available
+ * pthresh = 0x1f ==> prefetch if internal cache 31 or less
+ * BEWARE: this seems to work but should be considered first if
+ * there are tx hangs or other tx related bugs
+ */
+ txdctl |= E1000_TXDCTL_DMA_BURST_ENABLE;
+ ew32(TXDCTL(0), txdctl);
+ /* erratum work around: set txdctl the same for both queues */
+ ew32(TXDCTL(1), txdctl);
+ }
+
/* Program the Transmit Control Register */
tctl = er32(TCTL);
tctl &= ~E1000_TCTL_CT;
@@ -2871,12 +2900,35 @@ static void e1000_configure_rx(struct e1000_adapter *adapter)
e1e_flush();
msleep(10);
+ if (adapter->flags2 & FLAG2_DMA_BURST) {
+ /*
+ * set the writeback threshold (only takes effect if the RDTR
+ * is set). set GRAN=1 and write back up to 0x4 worth, and
+ * enable prefetching of 0x20 rx descriptors
+ * granularity = 01
+ * wthresh = 04,
+ * hthresh = 04,
+ * pthresh = 0x20
+ */
+ ew32(RXDCTL(0), E1000_RXDCTL_DMA_BURST_ENABLE);
+ ew32(RXDCTL(1), E1000_RXDCTL_DMA_BURST_ENABLE);
+
+ /*
+ * override the delay timers for enabling bursting, only if
+ * the value was not set by the user via module options
+ */
+ if (adapter->rx_int_delay == DEFAULT_RDTR)
+ adapter->rx_int_delay = BURST_RDTR;
+ if (adapter->rx_abs_int_delay == DEFAULT_RADV)
+ adapter->rx_abs_int_delay = BURST_RADV;
+ }
+
/* set the Receive Delay Timer Register */
ew32(RDTR, adapter->rx_int_delay);
/* irq moderation */
ew32(RADV, adapter->rx_abs_int_delay);
- if (adapter->itr_setting != 0)
+ if ((adapter->itr_setting != 0) && (adapter->itr != 0))
ew32(ITR, 1000000000 / (adapter->itr * 256));
ctrl_ext = er32(CTRL_EXT);
@@ -2921,11 +2973,13 @@ static void e1000_configure_rx(struct e1000_adapter *adapter)
* packet size is equal or larger than the specified value (in 8 byte
* units), e.g. using jumbo frames when setting to E1000_ERT_2048
*/
- if (adapter->flags & FLAG_HAS_ERT) {
+ if ((adapter->flags & FLAG_HAS_ERT) ||
+ (adapter->hw.mac.type == e1000_pch2lan)) {
if (adapter->netdev->mtu > ETH_DATA_LEN) {
u32 rxdctl = er32(RXDCTL(0));
ew32(RXDCTL(0), rxdctl | 0x3);
- ew32(ERT, E1000_ERT_2048 | (1 << 13));
+ if (adapter->flags & FLAG_HAS_ERT)
+ ew32(ERT, E1000_ERT_2048 | (1 << 13));
/*
* With jumbo frames and early-receive enabled,
* excessive C-state transition latencies result in
@@ -3188,9 +3242,35 @@ void e1000e_reset(struct e1000_adapter *adapter)
fc->low_water = 0x05048;
fc->pause_time = 0x0650;
fc->refresh_time = 0x0400;
+ if (adapter->netdev->mtu > ETH_DATA_LEN) {
+ pba = 14;
+ ew32(PBA, pba);
+ }
break;
}
+ /*
+ * Disable Adaptive Interrupt Moderation if 2 full packets cannot
+ * fit in receive buffer and early-receive not supported.
+ */
+ if (adapter->itr_setting & 0x3) {
+ if (((adapter->max_frame_size * 2) > (pba << 10)) &&
+ !(adapter->flags & FLAG_HAS_ERT)) {
+ if (!(adapter->flags2 & FLAG2_DISABLE_AIM)) {
+ dev_info(&adapter->pdev->dev,
+ "Interrupt Throttle Rate turned off\n");
+ adapter->flags2 |= FLAG2_DISABLE_AIM;
+ ew32(ITR, 0);
+ }
+ } else if (adapter->flags2 & FLAG2_DISABLE_AIM) {
+ dev_info(&adapter->pdev->dev,
+ "Interrupt Throttle Rate turned on\n");
+ adapter->flags2 &= ~FLAG2_DISABLE_AIM;
+ adapter->itr = 20000;
+ ew32(ITR, 1000000000 / (adapter->itr * 256));
+ }
+ }
+
/* Allow time for pending master requests to run */
mac->ops.reset_hw(hw);
@@ -3411,22 +3491,16 @@ static int e1000_test_msi_interrupt(struct e1000_adapter *adapter)
if (adapter->flags & FLAG_MSI_TEST_FAILED) {
adapter->int_mode = E1000E_INT_MODE_LEGACY;
- err = -EIO;
- e_info("MSI interrupt test failed!\n");
- }
+ e_info("MSI interrupt test failed, using legacy interrupt.\n");
+ } else
+ e_dbg("MSI interrupt test succeeded!\n");
free_irq(adapter->pdev->irq, netdev);
pci_disable_msi(adapter->pdev);
- if (err == -EIO)
- goto msi_test_failed;
-
- /* okay so the test worked, restore settings */
- e_dbg("MSI interrupt test succeeded!\n");
msi_test_failed:
e1000e_set_interrupt_capability(adapter);
- e1000_request_irq(adapter);
- return err;
+ return e1000_request_irq(adapter);
}
/**
@@ -3458,21 +3532,6 @@ static int e1000_test_msi(struct e1000_adapter *adapter)
pci_write_config_word(adapter->pdev, PCI_COMMAND, pci_cmd);
}
- /* success ! */
- if (!err)
- return 0;
-
- /* EIO means MSI test failed */
- if (err != -EIO)
- return err;
-
- /* back to INTx mode */
- e_warn("MSI interrupt test failed, using legacy interrupt.\n");
-
- e1000_free_irq(adapter);
-
- err = e1000_request_irq(adapter);
-
return err;
}
@@ -3530,7 +3589,8 @@ static int e1000_open(struct net_device *netdev)
e1000_update_mng_vlan(adapter);
/* DMA latency requirement to workaround early-receive/jumbo issue */
- if (adapter->flags & FLAG_HAS_ERT)
+ if ((adapter->flags & FLAG_HAS_ERT) ||
+ (adapter->hw.mac.type == e1000_pch2lan))
pm_qos_add_request(&adapter->netdev->pm_qos_req,
PM_QOS_CPU_DMA_LATENCY,
PM_QOS_DEFAULT_VALUE);
@@ -3639,7 +3699,8 @@ static int e1000_close(struct net_device *netdev)
if (adapter->flags & FLAG_HAS_AMT)
e1000_release_hw_control(adapter);
- if (adapter->flags & FLAG_HAS_ERT)
+ if ((adapter->flags & FLAG_HAS_ERT) ||
+ (adapter->hw.mac.type == e1000_pch2lan))
pm_qos_remove_request(&adapter->netdev->pm_qos_req);
pm_runtime_put_sync(&pdev->dev);
@@ -4255,6 +4316,16 @@ link_up:
/* Force detection of hung controller every watchdog period */
adapter->detect_tx_hung = 1;
+ /* flush partial descriptors to memory before detecting tx hang */
+ if (adapter->flags2 & FLAG2_DMA_BURST) {
+ ew32(TIDV, adapter->tx_int_delay | E1000_TIDV_FPD);
+ ew32(RDTR, adapter->rx_int_delay | E1000_RDTR_FPD);
+ /*
+ * no need to flush the writes because the timeout code does
+ * an er32 first thing
+ */
+ }
+
/*
* With 82571 controllers, LAA may be overwritten due to controller
* reset from the other port. Set the appropriate LAA in RAR[0]
@@ -4729,7 +4800,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
if (e1000_maybe_stop_tx(netdev, count + 2))
return NETDEV_TX_BUSY;
- if (adapter->vlgrp && vlan_tx_tag_present(skb)) {
+ if (vlan_tx_tag_present(skb)) {
tx_flags |= E1000_TX_FLAGS_VLAN;
tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT);
}
@@ -5712,8 +5783,10 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
netdev->vlan_features |= NETIF_F_HW_CSUM;
netdev->vlan_features |= NETIF_F_SG;
- if (pci_using_dac)
+ if (pci_using_dac) {
netdev->features |= NETIF_F_HIGHDMA;
+ netdev->vlan_features |= NETIF_F_HIGHDMA;
+ }
if (e1000e_enable_mng_pass_thru(&adapter->hw))
adapter->flags |= FLAG_MNG_PT_ENABLED;
@@ -5754,11 +5827,11 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
}
init_timer(&adapter->watchdog_timer);
- adapter->watchdog_timer.function = &e1000_watchdog;
+ adapter->watchdog_timer.function = e1000_watchdog;
adapter->watchdog_timer.data = (unsigned long) adapter;
init_timer(&adapter->phy_info_timer);
- adapter->phy_info_timer.function = &e1000_update_phy_info;
+ adapter->phy_info_timer.function = e1000_update_phy_info;
adapter->phy_info_timer.data = (unsigned long) adapter;
INIT_WORK(&adapter->reset_task, e1000_reset_task);
diff --git a/drivers/net/e1000e/param.c b/drivers/net/e1000e/param.c
index 34aeec13bb16..3d36911f77f3 100644
--- a/drivers/net/e1000e/param.c
+++ b/drivers/net/e1000e/param.c
@@ -91,7 +91,6 @@ E1000_PARAM(TxAbsIntDelay, "Transmit Absolute Interrupt Delay");
* Valid Range: 0-65535
*/
E1000_PARAM(RxIntDelay, "Receive Interrupt Delay");
-#define DEFAULT_RDTR 0
#define MAX_RXDELAY 0xFFFF
#define MIN_RXDELAY 0
@@ -101,7 +100,6 @@ E1000_PARAM(RxIntDelay, "Receive Interrupt Delay");
* Valid Range: 0-65535
*/
E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay");
-#define DEFAULT_RADV 8
#define MAX_RXABSDELAY 0xFFFF
#define MIN_RXABSDELAY 0
diff --git a/drivers/net/eepro.c b/drivers/net/eepro.c
index 8d97f168f018..7c826319ee5a 100644
--- a/drivers/net/eepro.c
+++ b/drivers/net/eepro.c
@@ -1457,11 +1457,11 @@ hardware_send_packet(struct net_device *dev, void *buf, short length)
if (net_debug > 5)
printk(KERN_DEBUG "%s: entering hardware_send_packet routine.\n", dev->name);
- /* determine how much of the transmit buffer space is available */
- if (lp->tx_end > lp->tx_start)
+ /* determine how much of the transmit buffer space is available */
+ if (lp->tx_end > lp->tx_start)
tx_available = lp->xmt_ram - (lp->tx_end - lp->tx_start);
- else if (lp->tx_end < lp->tx_start)
- tx_available = lp->tx_start - lp->tx_end;
+ else if (lp->tx_end < lp->tx_start)
+ tx_available = lp->tx_start - lp->tx_end;
else tx_available = lp->xmt_ram;
if (((((length + 3) >> 1) << 1) + 2*XMT_HEADER) >= tx_available) {
diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h
index 1846623c6ae6..1321cb6401cf 100644
--- a/drivers/net/ehea/ehea.h
+++ b/drivers/net/ehea/ehea.h
@@ -491,6 +491,8 @@ struct ehea_port {
u8 full_duplex;
u8 autoneg;
u8 num_def_qps;
+ wait_queue_head_t swqe_avail_wq;
+ wait_queue_head_t restart_wq;
};
struct port_res_cfg {
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
index a333b42111b8..bb7d306fb446 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -180,7 +180,7 @@ static void ehea_update_firmware_handles(void)
num_portres * EHEA_NUM_PORTRES_FW_HANDLES;
if (num_fw_handles) {
- arr = kzalloc(num_fw_handles * sizeof(*arr), GFP_KERNEL);
+ arr = kcalloc(num_fw_handles, sizeof(*arr), GFP_KERNEL);
if (!arr)
goto out; /* Keep the existing array */
} else
@@ -265,7 +265,7 @@ static void ehea_update_bcmc_registrations(void)
}
if (num_registrations) {
- arr = kzalloc(num_registrations * sizeof(*arr), GFP_ATOMIC);
+ arr = kcalloc(num_registrations, sizeof(*arr), GFP_ATOMIC);
if (!arr)
goto out; /* Keep the existing array */
} else
@@ -533,8 +533,15 @@ static inline void ehea_fill_skb(struct net_device *dev,
int length = cqe->num_bytes_transfered - 4; /*remove CRC */
skb_put(skb, length);
- skb->ip_summed = CHECKSUM_UNNECESSARY;
skb->protocol = eth_type_trans(skb, dev);
+
+ /* The packet was not an IPV4 packet so a complemented checksum was
+ calculated. The value is found in the Internet Checksum field. */
+ if (cqe->status & EHEA_CQE_BLIND_CKSUM) {
+ skb->ip_summed = CHECKSUM_COMPLETE;
+ skb->csum = csum_unfold(~cqe->inet_checksum_value);
+ } else
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
}
static inline struct sk_buff *get_skb_by_index(struct sk_buff **skb_array,
@@ -786,6 +793,7 @@ static void reset_sq_restart_flag(struct ehea_port *port)
struct ehea_port_res *pr = &port->port_res[i];
pr->sq_restart_flag = 0;
}
+ wake_up(&port->restart_wq);
}
static void check_sqs(struct ehea_port *port)
@@ -796,6 +804,7 @@ static void check_sqs(struct ehea_port *port)
for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) {
struct ehea_port_res *pr = &port->port_res[i];
+ int ret;
k = 0;
swqe = ehea_get_swqe(pr->qp, &swqe_index);
memset(swqe, 0, SWQE_HEADER_SIZE);
@@ -809,17 +818,16 @@ static void check_sqs(struct ehea_port *port)
ehea_post_swqe(pr->qp, swqe);
- while (pr->sq_restart_flag == 0) {
- msleep(5);
- if (++k == 100) {
- ehea_error("HW/SW queues out of sync");
- ehea_schedule_port_reset(pr->port);
- return;
- }
+ ret = wait_event_timeout(port->restart_wq,
+ pr->sq_restart_flag == 0,
+ msecs_to_jiffies(100));
+
+ if (!ret) {
+ ehea_error("HW/SW queues out of sync");
+ ehea_schedule_port_reset(pr->port);
+ return;
}
}
-
- return;
}
@@ -890,6 +898,7 @@ static struct ehea_cqe *ehea_proc_cqes(struct ehea_port_res *pr, int my_quota)
pr->queue_stopped = 0;
}
spin_unlock_irqrestore(&pr->netif_queue, flags);
+ wake_up(&pr->port->swqe_avail_wq);
return cqe;
}
@@ -1916,7 +1925,7 @@ static void ehea_promiscuous(struct net_device *dev, int enable)
struct hcp_ehea_port_cb7 *cb7;
u64 hret;
- if ((enable && port->promisc) || (!enable && !port->promisc))
+ if (enable == port->promisc)
return;
cb7 = (void *)get_zeroed_page(GFP_ATOMIC);
@@ -2270,7 +2279,7 @@ static int ehea_start_xmit(struct sk_buff *skb, struct net_device *dev)
}
pr->swqe_id_counter += 1;
- if (port->vgrp && vlan_tx_tag_present(skb)) {
+ if (vlan_tx_tag_present(skb)) {
swqe->tx_control |= EHEA_SWQE_VLAN_INSERT;
swqe->vlan_tag = vlan_tx_tag_get(skb);
}
@@ -2654,6 +2663,9 @@ static int ehea_open(struct net_device *dev)
netif_start_queue(dev);
}
+ init_waitqueue_head(&port->swqe_avail_wq);
+ init_waitqueue_head(&port->restart_wq);
+
mutex_unlock(&port->port_lock);
return ret;
@@ -2726,13 +2738,15 @@ static void ehea_flush_sq(struct ehea_port *port)
for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) {
struct ehea_port_res *pr = &port->port_res[i];
int swqe_max = pr->sq_skba_size - 2 - pr->swqe_ll_count;
- int k = 0;
- while (atomic_read(&pr->swqe_avail) < swqe_max) {
- msleep(5);
- if (++k == 20) {
- ehea_error("WARNING: sq not flushed completely");
- break;
- }
+ int ret;
+
+ ret = wait_event_timeout(port->swqe_avail_wq,
+ atomic_read(&pr->swqe_avail) >= swqe_max,
+ msecs_to_jiffies(100));
+
+ if (!ret) {
+ ehea_error("WARNING: sq not flushed completely");
+ break;
}
}
}
@@ -3721,7 +3735,7 @@ int __init ehea_module_init(void)
if (ret)
ehea_info("failed registering memory remove notifier");
- ret = crash_shutdown_register(&ehea_crash_handler);
+ ret = crash_shutdown_register(ehea_crash_handler);
if (ret)
ehea_info("failed registering crash handler");
@@ -3746,7 +3760,7 @@ out3:
out2:
unregister_memory_notifier(&ehea_mem_nb);
unregister_reboot_notifier(&ehea_reboot_nb);
- crash_shutdown_unregister(&ehea_crash_handler);
+ crash_shutdown_unregister(ehea_crash_handler);
out:
return ret;
}
@@ -3759,7 +3773,7 @@ static void __exit ehea_module_exit(void)
driver_remove_file(&ehea_driver.driver, &driver_attr_capabilities);
ibmebus_unregister_driver(&ehea_driver);
unregister_reboot_notifier(&ehea_reboot_nb);
- ret = crash_shutdown_unregister(&ehea_crash_handler);
+ ret = crash_shutdown_unregister(ehea_crash_handler);
if (ret)
ehea_info("failed unregistering crash handler");
unregister_memory_notifier(&ehea_mem_nb);
diff --git a/drivers/net/ehea/ehea_qmr.h b/drivers/net/ehea/ehea_qmr.h
index f608a6c54af5..38104734a3be 100644
--- a/drivers/net/ehea/ehea_qmr.h
+++ b/drivers/net/ehea/ehea_qmr.h
@@ -150,6 +150,7 @@ struct ehea_rwqe {
#define EHEA_CQE_TYPE_RQ 0x60
#define EHEA_CQE_STAT_ERR_MASK 0x700F
#define EHEA_CQE_STAT_FAT_ERR_MASK 0xF
+#define EHEA_CQE_BLIND_CKSUM 0x8000
#define EHEA_CQE_STAT_ERR_TCP 0x4000
#define EHEA_CQE_STAT_ERR_IP 0x2000
#define EHEA_CQE_STAT_ERR_CRC 0x1000
diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h
index f239aa8c6f4c..c91d364c5527 100644
--- a/drivers/net/enic/enic.h
+++ b/drivers/net/enic/enic.h
@@ -32,7 +32,7 @@
#define DRV_NAME "enic"
#define DRV_DESCRIPTION "Cisco VIC Ethernet NIC Driver"
-#define DRV_VERSION "1.4.1.1"
+#define DRV_VERSION "1.4.1.6"
#define DRV_COPYRIGHT "Copyright 2008-2010 Cisco Systems, Inc"
#define ENIC_BARS_MAX 6
@@ -42,25 +42,6 @@
#define ENIC_CQ_MAX (ENIC_WQ_MAX + ENIC_RQ_MAX)
#define ENIC_INTR_MAX (ENIC_CQ_MAX + 2)
-enum enic_cq_index {
- ENIC_CQ_RQ,
- ENIC_CQ_WQ,
-};
-
-enum enic_intx_intr_index {
- ENIC_INTX_WQ_RQ,
- ENIC_INTX_ERR,
- ENIC_INTX_NOTIFY,
-};
-
-enum enic_msix_intr_index {
- ENIC_MSIX_RQ,
- ENIC_MSIX_WQ,
- ENIC_MSIX_ERR,
- ENIC_MSIX_NOTIFY,
- ENIC_MSIX_MAX,
-};
-
struct enic_msix_entry {
int requested;
char devname[IFNAMSIZ];
@@ -91,8 +72,8 @@ struct enic {
struct vnic_dev *vdev;
struct timer_list notify_timer;
struct work_struct reset;
- struct msix_entry msix_entry[ENIC_MSIX_MAX];
- struct enic_msix_entry msix[ENIC_MSIX_MAX];
+ struct msix_entry msix_entry[ENIC_INTR_MAX];
+ struct enic_msix_entry msix[ENIC_INTR_MAX];
u32 msg_enable;
spinlock_t devcmd_lock;
u8 mac_addr[ETH_ALEN];
@@ -119,7 +100,7 @@ struct enic {
int (*rq_alloc_buf)(struct vnic_rq *rq);
u64 rq_truncated_pkts;
u64 rq_bad_fcs;
- struct napi_struct napi;
+ struct napi_struct napi[ENIC_RQ_MAX];
/* interrupt resource cache line section */
____cacheline_aligned struct vnic_intr intr[ENIC_INTR_MAX];
diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c
index 9aab85366d21..a466ef91dd43 100644
--- a/drivers/net/enic/enic_main.c
+++ b/drivers/net/enic/enic_main.c
@@ -122,6 +122,51 @@ static int enic_is_dynamic(struct enic *enic)
return enic->pdev->device == PCI_DEVICE_ID_CISCO_VIC_ENET_DYN;
}
+static inline unsigned int enic_cq_rq(struct enic *enic, unsigned int rq)
+{
+ return rq;
+}
+
+static inline unsigned int enic_cq_wq(struct enic *enic, unsigned int wq)
+{
+ return enic->rq_count + wq;
+}
+
+static inline unsigned int enic_legacy_io_intr(void)
+{
+ return 0;
+}
+
+static inline unsigned int enic_legacy_err_intr(void)
+{
+ return 1;
+}
+
+static inline unsigned int enic_legacy_notify_intr(void)
+{
+ return 2;
+}
+
+static inline unsigned int enic_msix_rq_intr(struct enic *enic, unsigned int rq)
+{
+ return rq;
+}
+
+static inline unsigned int enic_msix_wq_intr(struct enic *enic, unsigned int wq)
+{
+ return enic->rq_count + wq;
+}
+
+static inline unsigned int enic_msix_err_intr(struct enic *enic)
+{
+ return enic->rq_count + enic->wq_count;
+}
+
+static inline unsigned int enic_msix_notify_intr(struct enic *enic)
+{
+ return enic->rq_count + enic->wq_count + 1;
+}
+
static int enic_get_settings(struct net_device *netdev,
struct ethtool_cmd *ecmd)
{
@@ -306,6 +351,7 @@ static int enic_set_coalesce(struct net_device *netdev,
struct enic *enic = netdev_priv(netdev);
u32 tx_coalesce_usecs;
u32 rx_coalesce_usecs;
+ unsigned int i, intr;
tx_coalesce_usecs = min_t(u32,
INTR_COALESCE_HW_TO_USEC(VNIC_INTR_TIMER_MAX),
@@ -319,7 +365,8 @@ static int enic_set_coalesce(struct net_device *netdev,
if (tx_coalesce_usecs != rx_coalesce_usecs)
return -EINVAL;
- vnic_intr_coalescing_timer_set(&enic->intr[ENIC_INTX_WQ_RQ],
+ intr = enic_legacy_io_intr();
+ vnic_intr_coalescing_timer_set(&enic->intr[intr],
INTR_COALESCE_USEC_TO_HW(tx_coalesce_usecs));
break;
case VNIC_DEV_INTR_MODE_MSI:
@@ -330,10 +377,18 @@ static int enic_set_coalesce(struct net_device *netdev,
INTR_COALESCE_USEC_TO_HW(tx_coalesce_usecs));
break;
case VNIC_DEV_INTR_MODE_MSIX:
- vnic_intr_coalescing_timer_set(&enic->intr[ENIC_MSIX_WQ],
- INTR_COALESCE_USEC_TO_HW(tx_coalesce_usecs));
- vnic_intr_coalescing_timer_set(&enic->intr[ENIC_MSIX_RQ],
- INTR_COALESCE_USEC_TO_HW(rx_coalesce_usecs));
+ for (i = 0; i < enic->wq_count; i++) {
+ intr = enic_msix_wq_intr(enic, i);
+ vnic_intr_coalescing_timer_set(&enic->intr[intr],
+ INTR_COALESCE_USEC_TO_HW(tx_coalesce_usecs));
+ }
+
+ for (i = 0; i < enic->rq_count; i++) {
+ intr = enic_msix_rq_intr(enic, i);
+ vnic_intr_coalescing_timer_set(&enic->intr[intr],
+ INTR_COALESCE_USEC_TO_HW(rx_coalesce_usecs));
+ }
+
break;
default:
break;
@@ -482,34 +537,37 @@ static irqreturn_t enic_isr_legacy(int irq, void *data)
{
struct net_device *netdev = data;
struct enic *enic = netdev_priv(netdev);
+ unsigned int io_intr = enic_legacy_io_intr();
+ unsigned int err_intr = enic_legacy_err_intr();
+ unsigned int notify_intr = enic_legacy_notify_intr();
u32 pba;
- vnic_intr_mask(&enic->intr[ENIC_INTX_WQ_RQ]);
+ vnic_intr_mask(&enic->intr[io_intr]);
pba = vnic_intr_legacy_pba(enic->legacy_pba);
if (!pba) {
- vnic_intr_unmask(&enic->intr[ENIC_INTX_WQ_RQ]);
+ vnic_intr_unmask(&enic->intr[io_intr]);
return IRQ_NONE; /* not our interrupt */
}
- if (ENIC_TEST_INTR(pba, ENIC_INTX_NOTIFY)) {
- vnic_intr_return_all_credits(&enic->intr[ENIC_INTX_NOTIFY]);
+ if (ENIC_TEST_INTR(pba, notify_intr)) {
+ vnic_intr_return_all_credits(&enic->intr[notify_intr]);
enic_notify_check(enic);
}
- if (ENIC_TEST_INTR(pba, ENIC_INTX_ERR)) {
- vnic_intr_return_all_credits(&enic->intr[ENIC_INTX_ERR]);
+ if (ENIC_TEST_INTR(pba, err_intr)) {
+ vnic_intr_return_all_credits(&enic->intr[err_intr]);
enic_log_q_error(enic);
/* schedule recovery from WQ/RQ error */
schedule_work(&enic->reset);
return IRQ_HANDLED;
}
- if (ENIC_TEST_INTR(pba, ENIC_INTX_WQ_RQ)) {
- if (napi_schedule_prep(&enic->napi))
- __napi_schedule(&enic->napi);
+ if (ENIC_TEST_INTR(pba, io_intr)) {
+ if (napi_schedule_prep(&enic->napi[0]))
+ __napi_schedule(&enic->napi[0]);
} else {
- vnic_intr_unmask(&enic->intr[ENIC_INTX_WQ_RQ]);
+ vnic_intr_unmask(&enic->intr[io_intr]);
}
return IRQ_HANDLED;
@@ -535,17 +593,17 @@ static irqreturn_t enic_isr_msi(int irq, void *data)
* writes).
*/
- napi_schedule(&enic->napi);
+ napi_schedule(&enic->napi[0]);
return IRQ_HANDLED;
}
static irqreturn_t enic_isr_msix_rq(int irq, void *data)
{
- struct enic *enic = data;
+ struct napi_struct *napi = data;
/* schedule NAPI polling for RQ cleanup */
- napi_schedule(&enic->napi);
+ napi_schedule(napi);
return IRQ_HANDLED;
}
@@ -553,13 +611,15 @@ static irqreturn_t enic_isr_msix_rq(int irq, void *data)
static irqreturn_t enic_isr_msix_wq(int irq, void *data)
{
struct enic *enic = data;
+ unsigned int cq = enic_cq_wq(enic, 0);
+ unsigned int intr = enic_msix_wq_intr(enic, 0);
unsigned int wq_work_to_do = -1; /* no limit */
unsigned int wq_work_done;
- wq_work_done = vnic_cq_service(&enic->cq[ENIC_CQ_WQ],
+ wq_work_done = vnic_cq_service(&enic->cq[cq],
wq_work_to_do, enic_wq_service, NULL);
- vnic_intr_return_credits(&enic->intr[ENIC_MSIX_WQ],
+ vnic_intr_return_credits(&enic->intr[intr],
wq_work_done,
1 /* unmask intr */,
1 /* reset intr timer */);
@@ -570,8 +630,9 @@ static irqreturn_t enic_isr_msix_wq(int irq, void *data)
static irqreturn_t enic_isr_msix_err(int irq, void *data)
{
struct enic *enic = data;
+ unsigned int intr = enic_msix_err_intr(enic);
- vnic_intr_return_all_credits(&enic->intr[ENIC_MSIX_ERR]);
+ vnic_intr_return_all_credits(&enic->intr[intr]);
enic_log_q_error(enic);
@@ -584,8 +645,9 @@ static irqreturn_t enic_isr_msix_err(int irq, void *data)
static irqreturn_t enic_isr_msix_notify(int irq, void *data)
{
struct enic *enic = data;
+ unsigned int intr = enic_msix_notify_intr(enic);
- vnic_intr_return_all_credits(&enic->intr[ENIC_MSIX_NOTIFY]);
+ vnic_intr_return_all_credits(&enic->intr[intr]);
enic_notify_check(enic);
return IRQ_HANDLED;
@@ -743,7 +805,7 @@ static inline void enic_queue_wq_skb(struct enic *enic,
int vlan_tag_insert = 0;
int loopback = 0;
- if (enic->vlan_group && vlan_tx_tag_present(skb)) {
+ if (vlan_tx_tag_present(skb)) {
/* VLAN tag from trunking driver */
vlan_tag_insert = 1;
vlan_tag = vlan_tx_tag_get(skb);
@@ -911,7 +973,20 @@ static int enic_set_mac_address_dynamic(struct net_device *netdev, void *p)
static int enic_set_mac_address(struct net_device *netdev, void *p)
{
- return -EOPNOTSUPP;
+ struct sockaddr *saddr = p;
+ char *addr = saddr->sa_data;
+ struct enic *enic = netdev_priv(netdev);
+ int err;
+
+ err = enic_dev_del_station_addr(enic);
+ if (err)
+ return err;
+
+ err = enic_set_mac_addr(netdev, addr);
+ if (err)
+ return err;
+
+ return enic_dev_add_station_addr(enic);
}
static int enic_dev_packet_filter(struct enic *enic, int directed,
@@ -1407,8 +1482,8 @@ static void enic_rq_indicate_buf(struct vnic_rq *rq,
(vlan_tci & CQ_ENET_RQ_DESC_VLAN_TCI_VLAN_MASK)) {
if (netdev->features & NETIF_F_GRO)
- vlan_gro_receive(&enic->napi, enic->vlan_group,
- vlan_tci, skb);
+ vlan_gro_receive(&enic->napi[q_number],
+ enic->vlan_group, vlan_tci, skb);
else
vlan_hwaccel_receive_skb(skb,
enic->vlan_group, vlan_tci);
@@ -1416,12 +1491,11 @@ static void enic_rq_indicate_buf(struct vnic_rq *rq,
} else {
if (netdev->features & NETIF_F_GRO)
- napi_gro_receive(&enic->napi, skb);
+ napi_gro_receive(&enic->napi[q_number], skb);
else
netif_receive_skb(skb);
}
-
} else {
/* Buffer overflow
@@ -1445,7 +1519,11 @@ static int enic_rq_service(struct vnic_dev *vdev, struct cq_desc *cq_desc,
static int enic_poll(struct napi_struct *napi, int budget)
{
- struct enic *enic = container_of(napi, struct enic, napi);
+ struct net_device *netdev = napi->dev;
+ struct enic *enic = netdev_priv(netdev);
+ unsigned int cq_rq = enic_cq_rq(enic, 0);
+ unsigned int cq_wq = enic_cq_wq(enic, 0);
+ unsigned int intr = enic_legacy_io_intr();
unsigned int rq_work_to_do = budget;
unsigned int wq_work_to_do = -1; /* no limit */
unsigned int work_done, rq_work_done, wq_work_done;
@@ -1454,10 +1532,10 @@ static int enic_poll(struct napi_struct *napi, int budget)
/* Service RQ (first) and WQ
*/
- rq_work_done = vnic_cq_service(&enic->cq[ENIC_CQ_RQ],
+ rq_work_done = vnic_cq_service(&enic->cq[cq_rq],
rq_work_to_do, enic_rq_service, NULL);
- wq_work_done = vnic_cq_service(&enic->cq[ENIC_CQ_WQ],
+ wq_work_done = vnic_cq_service(&enic->cq[cq_wq],
wq_work_to_do, enic_wq_service, NULL);
/* Accumulate intr event credits for this polling
@@ -1468,7 +1546,7 @@ static int enic_poll(struct napi_struct *napi, int budget)
work_done = rq_work_done + wq_work_done;
if (work_done > 0)
- vnic_intr_return_credits(&enic->intr[ENIC_INTX_WQ_RQ],
+ vnic_intr_return_credits(&enic->intr[intr],
work_done,
0 /* don't unmask intr */,
0 /* don't reset intr timer */);
@@ -1489,7 +1567,7 @@ static int enic_poll(struct napi_struct *napi, int budget)
*/
napi_complete(napi);
- vnic_intr_unmask(&enic->intr[ENIC_INTX_WQ_RQ]);
+ vnic_intr_unmask(&enic->intr[intr]);
}
return rq_work_done;
@@ -1497,7 +1575,11 @@ static int enic_poll(struct napi_struct *napi, int budget)
static int enic_poll_msix(struct napi_struct *napi, int budget)
{
- struct enic *enic = container_of(napi, struct enic, napi);
+ struct net_device *netdev = napi->dev;
+ struct enic *enic = netdev_priv(netdev);
+ unsigned int rq = (napi - &enic->napi[0]);
+ unsigned int cq = enic_cq_rq(enic, rq);
+ unsigned int intr = enic_msix_rq_intr(enic, rq);
unsigned int work_to_do = budget;
unsigned int work_done;
int err;
@@ -1505,7 +1587,7 @@ static int enic_poll_msix(struct napi_struct *napi, int budget)
/* Service RQ
*/
- work_done = vnic_cq_service(&enic->cq[ENIC_CQ_RQ],
+ work_done = vnic_cq_service(&enic->cq[cq],
work_to_do, enic_rq_service, NULL);
/* Return intr event credits for this polling
@@ -1514,12 +1596,12 @@ static int enic_poll_msix(struct napi_struct *napi, int budget)
*/
if (work_done > 0)
- vnic_intr_return_credits(&enic->intr[ENIC_MSIX_RQ],
+ vnic_intr_return_credits(&enic->intr[intr],
work_done,
0 /* don't unmask intr */,
0 /* don't reset intr timer */);
- err = vnic_rq_fill(&enic->rq[0], enic->rq_alloc_buf);
+ err = vnic_rq_fill(&enic->rq[rq], enic->rq_alloc_buf);
/* Buffer allocation failed. Stay in polling mode
* so we can try to fill the ring again.
@@ -1535,7 +1617,7 @@ static int enic_poll_msix(struct napi_struct *napi, int budget)
*/
napi_complete(napi);
- vnic_intr_unmask(&enic->intr[ENIC_MSIX_RQ]);
+ vnic_intr_unmask(&enic->intr[intr]);
}
return work_done;
@@ -1577,7 +1659,7 @@ static void enic_free_intr(struct enic *enic)
static int enic_request_intr(struct enic *enic)
{
struct net_device *netdev = enic->netdev;
- unsigned int i;
+ unsigned int i, intr;
int err = 0;
switch (vnic_dev_get_intr_mode(enic->vdev)) {
@@ -1596,27 +1678,38 @@ static int enic_request_intr(struct enic *enic)
case VNIC_DEV_INTR_MODE_MSIX:
- sprintf(enic->msix[ENIC_MSIX_RQ].devname,
- "%.11s-rx-0", netdev->name);
- enic->msix[ENIC_MSIX_RQ].isr = enic_isr_msix_rq;
- enic->msix[ENIC_MSIX_RQ].devid = enic;
+ for (i = 0; i < enic->rq_count; i++) {
+ intr = enic_msix_rq_intr(enic, i);
+ sprintf(enic->msix[intr].devname,
+ "%.11s-rx-%d", netdev->name, i);
+ enic->msix[intr].isr = enic_isr_msix_rq;
+ enic->msix[intr].devid = &enic->napi[i];
+ }
- sprintf(enic->msix[ENIC_MSIX_WQ].devname,
- "%.11s-tx-0", netdev->name);
- enic->msix[ENIC_MSIX_WQ].isr = enic_isr_msix_wq;
- enic->msix[ENIC_MSIX_WQ].devid = enic;
+ for (i = 0; i < enic->wq_count; i++) {
+ intr = enic_msix_wq_intr(enic, i);
+ sprintf(enic->msix[intr].devname,
+ "%.11s-tx-%d", netdev->name, i);
+ enic->msix[intr].isr = enic_isr_msix_wq;
+ enic->msix[intr].devid = enic;
+ }
- sprintf(enic->msix[ENIC_MSIX_ERR].devname,
+ intr = enic_msix_err_intr(enic);
+ sprintf(enic->msix[intr].devname,
"%.11s-err", netdev->name);
- enic->msix[ENIC_MSIX_ERR].isr = enic_isr_msix_err;
- enic->msix[ENIC_MSIX_ERR].devid = enic;
+ enic->msix[intr].isr = enic_isr_msix_err;
+ enic->msix[intr].devid = enic;
- sprintf(enic->msix[ENIC_MSIX_NOTIFY].devname,
+ intr = enic_msix_notify_intr(enic);
+ sprintf(enic->msix[intr].devname,
"%.11s-notify", netdev->name);
- enic->msix[ENIC_MSIX_NOTIFY].isr = enic_isr_msix_notify;
- enic->msix[ENIC_MSIX_NOTIFY].devid = enic;
+ enic->msix[intr].isr = enic_isr_msix_notify;
+ enic->msix[intr].devid = enic;
+
+ for (i = 0; i < ARRAY_SIZE(enic->msix); i++)
+ enic->msix[i].requested = 0;
- for (i = 0; i < ARRAY_SIZE(enic->msix); i++) {
+ for (i = 0; i < enic->intr_count; i++) {
err = request_irq(enic->msix_entry[i].vector,
enic->msix[i].isr, 0,
enic->msix[i].devname,
@@ -1662,10 +1755,12 @@ static int enic_dev_notify_set(struct enic *enic)
spin_lock(&enic->devcmd_lock);
switch (vnic_dev_get_intr_mode(enic->vdev)) {
case VNIC_DEV_INTR_MODE_INTX:
- err = vnic_dev_notify_set(enic->vdev, ENIC_INTX_NOTIFY);
+ err = vnic_dev_notify_set(enic->vdev,
+ enic_legacy_notify_intr());
break;
case VNIC_DEV_INTR_MODE_MSIX:
- err = vnic_dev_notify_set(enic->vdev, ENIC_MSIX_NOTIFY);
+ err = vnic_dev_notify_set(enic->vdev,
+ enic_msix_notify_intr(enic));
break;
default:
err = vnic_dev_notify_set(enic->vdev, -1 /* no intr */);
@@ -1692,7 +1787,7 @@ static int enic_dev_enable(struct enic *enic)
int err;
spin_lock(&enic->devcmd_lock);
- err = vnic_dev_enable(enic->vdev);
+ err = vnic_dev_enable_wait(enic->vdev);
spin_unlock(&enic->devcmd_lock);
return err;
@@ -1760,7 +1855,10 @@ static int enic_open(struct net_device *netdev)
enic_set_multicast_list(netdev);
netif_wake_queue(netdev);
- napi_enable(&enic->napi);
+
+ for (i = 0; i < enic->rq_count; i++)
+ napi_enable(&enic->napi[i]);
+
enic_dev_enable(enic);
for (i = 0; i < enic->intr_count; i++)
@@ -1795,7 +1893,10 @@ static int enic_stop(struct net_device *netdev)
del_timer_sync(&enic->notify_timer);
enic_dev_disable(enic);
- napi_disable(&enic->napi);
+
+ for (i = 0; i < enic->rq_count; i++)
+ napi_disable(&enic->napi[i]);
+
netif_carrier_off(netdev);
netif_tx_disable(netdev);
enic_dev_del_station_addr(enic);
@@ -1855,11 +1956,16 @@ static void enic_poll_controller(struct net_device *netdev)
{
struct enic *enic = netdev_priv(netdev);
struct vnic_dev *vdev = enic->vdev;
+ unsigned int i, intr;
switch (vnic_dev_get_intr_mode(vdev)) {
case VNIC_DEV_INTR_MODE_MSIX:
- enic_isr_msix_rq(enic->pdev->irq, enic);
- enic_isr_msix_wq(enic->pdev->irq, enic);
+ for (i = 0; i < enic->rq_count; i++) {
+ intr = enic_msix_rq_intr(enic, i);
+ enic_isr_msix_rq(enic->msix_entry[intr].vector, enic);
+ }
+ intr = enic_msix_wq_intr(enic, i);
+ enic_isr_msix_wq(enic->msix_entry[intr].vector, enic);
break;
case VNIC_DEV_INTR_MODE_MSI:
enic_isr_msi(enic->pdev->irq, enic);
@@ -1934,19 +2040,73 @@ static int enic_dev_hang_reset(struct enic *enic)
return err;
}
-static int enic_set_niccfg(struct enic *enic)
+static int enic_set_rsskey(struct enic *enic)
+{
+ u64 rss_key_buf_pa;
+ union vnic_rss_key *rss_key_buf_va = NULL;
+ union vnic_rss_key rss_key = {
+ .key[0].b = {85, 67, 83, 97, 119, 101, 115, 111, 109, 101},
+ .key[1].b = {80, 65, 76, 79, 117, 110, 105, 113, 117, 101},
+ .key[2].b = {76, 73, 78, 85, 88, 114, 111, 99, 107, 115},
+ .key[3].b = {69, 78, 73, 67, 105, 115, 99, 111, 111, 108},
+ };
+ int err;
+
+ rss_key_buf_va = pci_alloc_consistent(enic->pdev,
+ sizeof(union vnic_rss_key), &rss_key_buf_pa);
+ if (!rss_key_buf_va)
+ return -ENOMEM;
+
+ memcpy(rss_key_buf_va, &rss_key, sizeof(union vnic_rss_key));
+
+ spin_lock(&enic->devcmd_lock);
+ err = enic_set_rss_key(enic,
+ rss_key_buf_pa,
+ sizeof(union vnic_rss_key));
+ spin_unlock(&enic->devcmd_lock);
+
+ pci_free_consistent(enic->pdev, sizeof(union vnic_rss_key),
+ rss_key_buf_va, rss_key_buf_pa);
+
+ return err;
+}
+
+static int enic_set_rsscpu(struct enic *enic, u8 rss_hash_bits)
+{
+ u64 rss_cpu_buf_pa;
+ union vnic_rss_cpu *rss_cpu_buf_va = NULL;
+ unsigned int i;
+ int err;
+
+ rss_cpu_buf_va = pci_alloc_consistent(enic->pdev,
+ sizeof(union vnic_rss_cpu), &rss_cpu_buf_pa);
+ if (!rss_cpu_buf_va)
+ return -ENOMEM;
+
+ for (i = 0; i < (1 << rss_hash_bits); i++)
+ (*rss_cpu_buf_va).cpu[i/4].b[i%4] = i % enic->rq_count;
+
+ spin_lock(&enic->devcmd_lock);
+ err = enic_set_rss_cpu(enic,
+ rss_cpu_buf_pa,
+ sizeof(union vnic_rss_cpu));
+ spin_unlock(&enic->devcmd_lock);
+
+ pci_free_consistent(enic->pdev, sizeof(union vnic_rss_cpu),
+ rss_cpu_buf_va, rss_cpu_buf_pa);
+
+ return err;
+}
+
+static int enic_set_niccfg(struct enic *enic, u8 rss_default_cpu,
+ u8 rss_hash_type, u8 rss_hash_bits, u8 rss_base_cpu, u8 rss_enable)
{
- const u8 rss_default_cpu = 0;
- const u8 rss_hash_type = 0;
- const u8 rss_hash_bits = 0;
- const u8 rss_base_cpu = 0;
- const u8 rss_enable = 0;
const u8 tso_ipid_split_en = 0;
const u8 ig_vlan_strip_en = 1;
int err;
- /* Enable VLAN tag stripping. RSS not enabled (yet).
- */
+ /* Enable VLAN tag stripping.
+ */
spin_lock(&enic->devcmd_lock);
err = enic_set_nic_cfg(enic,
@@ -1959,6 +2119,35 @@ static int enic_set_niccfg(struct enic *enic)
return err;
}
+static int enic_set_rss_nic_cfg(struct enic *enic)
+{
+ struct device *dev = enic_get_dev(enic);
+ const u8 rss_default_cpu = 0;
+ const u8 rss_hash_type = NIC_CFG_RSS_HASH_TYPE_IPV4 |
+ NIC_CFG_RSS_HASH_TYPE_TCP_IPV4 |
+ NIC_CFG_RSS_HASH_TYPE_IPV6 |
+ NIC_CFG_RSS_HASH_TYPE_TCP_IPV6;
+ const u8 rss_hash_bits = 7;
+ const u8 rss_base_cpu = 0;
+ u8 rss_enable = ENIC_SETTING(enic, RSS) && (enic->rq_count > 1);
+
+ if (rss_enable) {
+ if (!enic_set_rsskey(enic)) {
+ if (enic_set_rsscpu(enic, rss_hash_bits)) {
+ rss_enable = 0;
+ dev_warn(dev, "RSS disabled, "
+ "Failed to set RSS cpu indirection table.");
+ }
+ } else {
+ rss_enable = 0;
+ dev_warn(dev, "RSS disabled, Failed to set RSS key.\n");
+ }
+ }
+
+ return enic_set_niccfg(enic, rss_default_cpu, rss_hash_type,
+ rss_hash_bits, rss_base_cpu, rss_enable);
+}
+
static int enic_dev_hang_notify(struct enic *enic)
{
int err;
@@ -1970,7 +2159,7 @@ static int enic_dev_hang_notify(struct enic *enic)
return err;
}
-int enic_dev_set_ig_vlan_rewrite_mode(struct enic *enic)
+static int enic_dev_set_ig_vlan_rewrite_mode(struct enic *enic)
{
int err;
@@ -1996,7 +2185,7 @@ static void enic_reset(struct work_struct *work)
enic_dev_hang_reset(enic);
enic_reset_multicast_list(enic);
enic_init_vnic_resources(enic);
- enic_set_niccfg(enic);
+ enic_set_rss_nic_cfg(enic);
enic_dev_set_ig_vlan_rewrite_mode(enic);
enic_open(enic->netdev);
@@ -2005,12 +2194,12 @@ static void enic_reset(struct work_struct *work)
static int enic_set_intr_mode(struct enic *enic)
{
- unsigned int n = 1;
+ unsigned int n = min_t(unsigned int, enic->rq_count, ENIC_RQ_MAX);
unsigned int m = 1;
unsigned int i;
/* Set interrupt mode (INTx, MSI, MSI-X) depending
- * system capabilities.
+ * on system capabilities.
*
* Try MSI-X first
*
@@ -2023,21 +2212,47 @@ static int enic_set_intr_mode(struct enic *enic)
for (i = 0; i < n + m + 2; i++)
enic->msix_entry[i].entry = i;
- if (enic->config.intr_mode < 1 &&
+ /* Use multiple RQs if RSS is enabled
+ */
+
+ if (ENIC_SETTING(enic, RSS) &&
+ enic->config.intr_mode < 1 &&
enic->rq_count >= n &&
enic->wq_count >= m &&
enic->cq_count >= n + m &&
- enic->intr_count >= n + m + 2 &&
- !pci_enable_msix(enic->pdev, enic->msix_entry, n + m + 2)) {
+ enic->intr_count >= n + m + 2) {
- enic->rq_count = n;
- enic->wq_count = m;
- enic->cq_count = n + m;
- enic->intr_count = n + m + 2;
+ if (!pci_enable_msix(enic->pdev, enic->msix_entry, n + m + 2)) {
- vnic_dev_set_intr_mode(enic->vdev, VNIC_DEV_INTR_MODE_MSIX);
+ enic->rq_count = n;
+ enic->wq_count = m;
+ enic->cq_count = n + m;
+ enic->intr_count = n + m + 2;
- return 0;
+ vnic_dev_set_intr_mode(enic->vdev,
+ VNIC_DEV_INTR_MODE_MSIX);
+
+ return 0;
+ }
+ }
+
+ if (enic->config.intr_mode < 1 &&
+ enic->rq_count >= 1 &&
+ enic->wq_count >= m &&
+ enic->cq_count >= 1 + m &&
+ enic->intr_count >= 1 + m + 2) {
+ if (!pci_enable_msix(enic->pdev, enic->msix_entry, 1 + m + 2)) {
+
+ enic->rq_count = 1;
+ enic->wq_count = m;
+ enic->cq_count = 1 + m;
+ enic->intr_count = 1 + m + 2;
+
+ vnic_dev_set_intr_mode(enic->vdev,
+ VNIC_DEV_INTR_MODE_MSIX);
+
+ return 0;
+ }
}
/* Next try MSI
@@ -2145,28 +2360,22 @@ static const struct net_device_ops enic_netdev_ops = {
#endif
};
-void enic_dev_deinit(struct enic *enic)
+static void enic_dev_deinit(struct enic *enic)
{
- netif_napi_del(&enic->napi);
- enic_free_vnic_resources(enic);
- enic_clear_intr_mode(enic);
-}
-
-static int enic_dev_stats_clear(struct enic *enic)
-{
- int err;
+ unsigned int i;
- spin_lock(&enic->devcmd_lock);
- err = vnic_dev_stats_clear(enic->vdev);
- spin_unlock(&enic->devcmd_lock);
+ for (i = 0; i < enic->rq_count; i++)
+ netif_napi_del(&enic->napi[i]);
- return err;
+ enic_free_vnic_resources(enic);
+ enic_clear_intr_mode(enic);
}
-int enic_dev_init(struct enic *enic)
+static int enic_dev_init(struct enic *enic)
{
struct device *dev = enic_get_dev(enic);
struct net_device *netdev = enic->netdev;
+ unsigned int i;
int err;
/* Get vNIC configuration
@@ -2205,17 +2414,13 @@ int enic_dev_init(struct enic *enic)
enic_init_vnic_resources(enic);
- /* Clear LIF stats
- */
- enic_dev_stats_clear(enic);
-
err = enic_set_rq_alloc_buf(enic);
if (err) {
dev_err(dev, "Failed to set RQ buffer allocator, aborting\n");
goto err_out_free_vnic_resources;
}
- err = enic_set_niccfg(enic);
+ err = enic_set_rss_nic_cfg(enic);
if (err) {
dev_err(dev, "Failed to config nic, aborting\n");
goto err_out_free_vnic_resources;
@@ -2223,17 +2428,19 @@ int enic_dev_init(struct enic *enic)
err = enic_dev_set_ig_vlan_rewrite_mode(enic);
if (err) {
- netdev_err(netdev,
+ dev_err(dev,
"Failed to set ingress vlan rewrite mode, aborting.\n");
goto err_out_free_vnic_resources;
}
switch (vnic_dev_get_intr_mode(enic->vdev)) {
default:
- netif_napi_add(netdev, &enic->napi, enic_poll, 64);
+ netif_napi_add(netdev, &enic->napi[0], enic_poll, 64);
break;
case VNIC_DEV_INTR_MODE_MSIX:
- netif_napi_add(netdev, &enic->napi, enic_poll_msix, 64);
+ for (i = 0; i < enic->rq_count; i++)
+ netif_napi_add(netdev, &enic->napi[i],
+ enic_poll_msix, 64);
break;
}
diff --git a/drivers/net/enic/enic_res.c b/drivers/net/enic/enic_res.c
index 29ede8a17a2c..f111a37419ce 100644
--- a/drivers/net/enic/enic_res.c
+++ b/drivers/net/enic/enic_res.c
@@ -94,13 +94,14 @@ int enic_get_vnic_config(struct enic *enic)
INTR_COALESCE_HW_TO_USEC(VNIC_INTR_TIMER_MAX),
c->intr_timer_usec);
- dev_info(enic_get_dev(enic), "vNIC MAC addr %pM wq/rq %d/%d\n",
- enic->mac_addr, c->wq_desc_count, c->rq_desc_count);
- dev_info(enic_get_dev(enic), "vNIC mtu %d csum tx/rx %d/%d "
- "tso/lro %d/%d intr timer %d usec\n",
- c->mtu, ENIC_SETTING(enic, TXCSUM),
- ENIC_SETTING(enic, RXCSUM), ENIC_SETTING(enic, TSO),
- ENIC_SETTING(enic, LRO), c->intr_timer_usec);
+ dev_info(enic_get_dev(enic),
+ "vNIC MAC addr %pM wq/rq %d/%d mtu %d\n",
+ enic->mac_addr, c->wq_desc_count, c->rq_desc_count, c->mtu);
+ dev_info(enic_get_dev(enic), "vNIC csum tx/rx %d/%d "
+ "tso/lro %d/%d intr timer %d usec rss %d\n",
+ ENIC_SETTING(enic, TXCSUM), ENIC_SETTING(enic, RXCSUM),
+ ENIC_SETTING(enic, TSO), ENIC_SETTING(enic, LRO),
+ c->intr_timer_usec, ENIC_SETTING(enic, RSS));
return 0;
}
@@ -181,18 +182,11 @@ void enic_free_vnic_resources(struct enic *enic)
void enic_get_res_counts(struct enic *enic)
{
- enic->wq_count = min_t(int,
- vnic_dev_get_res_count(enic->vdev, RES_TYPE_WQ),
- ENIC_WQ_MAX);
- enic->rq_count = min_t(int,
- vnic_dev_get_res_count(enic->vdev, RES_TYPE_RQ),
- ENIC_RQ_MAX);
- enic->cq_count = min_t(int,
- vnic_dev_get_res_count(enic->vdev, RES_TYPE_CQ),
- ENIC_CQ_MAX);
- enic->intr_count = min_t(int,
- vnic_dev_get_res_count(enic->vdev, RES_TYPE_INTR_CTRL),
- ENIC_INTR_MAX);
+ enic->wq_count = vnic_dev_get_res_count(enic->vdev, RES_TYPE_WQ);
+ enic->rq_count = vnic_dev_get_res_count(enic->vdev, RES_TYPE_RQ);
+ enic->cq_count = vnic_dev_get_res_count(enic->vdev, RES_TYPE_CQ);
+ enic->intr_count = vnic_dev_get_res_count(enic->vdev,
+ RES_TYPE_INTR_CTRL);
dev_info(enic_get_dev(enic),
"vNIC resources avail: wq %d rq %d cq %d intr %d\n",
diff --git a/drivers/net/enic/enic_res.h b/drivers/net/enic/enic_res.h
index 83bd172c356c..9a103d9ef9e2 100644
--- a/drivers/net/enic/enic_res.h
+++ b/drivers/net/enic/enic_res.h
@@ -30,7 +30,7 @@
#define ENIC_MIN_RQ_DESCS 64
#define ENIC_MAX_RQ_DESCS 4096
-#define ENIC_MIN_MTU 576 /* minimum for IPv4 */
+#define ENIC_MIN_MTU 68
#define ENIC_MAX_MTU 9000
#define ENIC_MULTICAST_PERFECT_FILTERS 32
diff --git a/drivers/net/enic/vnic_dev.c b/drivers/net/enic/vnic_dev.c
index 6a5b578a69e1..fb35d8b17668 100644
--- a/drivers/net/enic/vnic_dev.c
+++ b/drivers/net/enic/vnic_dev.c
@@ -74,6 +74,7 @@ static int vnic_dev_discover_res(struct vnic_dev *vdev,
struct vnic_dev_bar *bar, unsigned int num_bars)
{
struct vnic_resource_header __iomem *rh;
+ struct mgmt_barmap_hdr __iomem *mrh;
struct vnic_resource __iomem *r;
u8 type;
@@ -85,22 +86,32 @@ static int vnic_dev_discover_res(struct vnic_dev *vdev,
return -EINVAL;
}
- rh = bar->vaddr;
+ rh = bar->vaddr;
+ mrh = bar->vaddr;
if (!rh) {
pr_err("vNIC BAR0 res hdr not mem-mapped\n");
return -EINVAL;
}
- if (ioread32(&rh->magic) != VNIC_RES_MAGIC ||
- ioread32(&rh->version) != VNIC_RES_VERSION) {
- pr_err("vNIC BAR0 res magic/version error "
- "exp (%lx/%lx) curr (%x/%x)\n",
+ /* Check for mgmt vnic in addition to normal vnic */
+ if ((ioread32(&rh->magic) != VNIC_RES_MAGIC) ||
+ (ioread32(&rh->version) != VNIC_RES_VERSION)) {
+ if ((ioread32(&mrh->magic) != MGMTVNIC_MAGIC) ||
+ (ioread32(&mrh->version) != MGMTVNIC_VERSION)) {
+ pr_err("vNIC BAR0 res magic/version error "
+ "exp (%lx/%lx) or (%lx/%lx), curr (%x/%x)\n",
VNIC_RES_MAGIC, VNIC_RES_VERSION,
+ MGMTVNIC_MAGIC, MGMTVNIC_VERSION,
ioread32(&rh->magic), ioread32(&rh->version));
- return -EINVAL;
+ return -EINVAL;
+ }
}
- r = (struct vnic_resource __iomem *)(rh + 1);
+ if (ioread32(&mrh->magic) == MGMTVNIC_MAGIC)
+ r = (struct vnic_resource __iomem *)(mrh + 1);
+ else
+ r = (struct vnic_resource __iomem *)(rh + 1);
+
while ((type = ioread8(&r->type)) != RES_TYPE_EOL) {
@@ -175,22 +186,7 @@ void __iomem *vnic_dev_get_res(struct vnic_dev *vdev, enum vnic_res_type type,
}
}
-dma_addr_t vnic_dev_get_res_bus_addr(struct vnic_dev *vdev,
- enum vnic_res_type type, unsigned int index)
-{
- switch (type) {
- case RES_TYPE_WQ:
- case RES_TYPE_RQ:
- case RES_TYPE_CQ:
- case RES_TYPE_INTR_CTRL:
- return vdev->res[type].bus_addr +
- index * VNIC_RES_STRIDE;
- default:
- return vdev->res[type].bus_addr;
- }
-}
-
-unsigned int vnic_dev_desc_ring_size(struct vnic_dev_ring *ring,
+static unsigned int vnic_dev_desc_ring_size(struct vnic_dev_ring *ring,
unsigned int desc_count, unsigned int desc_size)
{
/* The base address of the desc rings must be 512 byte aligned.
@@ -373,18 +369,6 @@ static int vnic_dev_cmd_no_proxy(struct vnic_dev *vdev,
return err;
}
-void vnic_dev_cmd_proxy_by_bdf_start(struct vnic_dev *vdev, u16 bdf)
-{
- vdev->proxy = PROXY_BY_BDF;
- vdev->proxy_index = bdf;
-}
-
-void vnic_dev_cmd_proxy_end(struct vnic_dev *vdev)
-{
- vdev->proxy = PROXY_NONE;
- vdev->proxy_index = 0;
-}
-
int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
u64 *a0, u64 *a1, int wait)
{
@@ -477,13 +461,6 @@ int vnic_dev_spec(struct vnic_dev *vdev, unsigned int offset, unsigned int size,
return err;
}
-int vnic_dev_stats_clear(struct vnic_dev *vdev)
-{
- u64 a0 = 0, a1 = 0;
- int wait = 1000;
- return vnic_dev_cmd(vdev, CMD_STATS_CLEAR, &a0, &a1, wait);
-}
-
int vnic_dev_stats_dump(struct vnic_dev *vdev, struct vnic_stats **stats)
{
u64 a0, a1;
@@ -510,13 +487,6 @@ int vnic_dev_close(struct vnic_dev *vdev)
return vnic_dev_cmd(vdev, CMD_CLOSE, &a0, &a1, wait);
}
-int vnic_dev_enable(struct vnic_dev *vdev)
-{
- u64 a0 = 0, a1 = 0;
- int wait = 1000;
- return vnic_dev_cmd(vdev, CMD_ENABLE, &a0, &a1, wait);
-}
-
int vnic_dev_enable_wait(struct vnic_dev *vdev)
{
u64 a0 = 0, a1 = 0;
@@ -561,14 +531,14 @@ int vnic_dev_open_done(struct vnic_dev *vdev, int *done)
return 0;
}
-int vnic_dev_soft_reset(struct vnic_dev *vdev, int arg)
+static int vnic_dev_soft_reset(struct vnic_dev *vdev, int arg)
{
u64 a0 = (u32)arg, a1 = 0;
int wait = 1000;
return vnic_dev_cmd(vdev, CMD_SOFT_RESET, &a0, &a1, wait);
}
-int vnic_dev_soft_reset_done(struct vnic_dev *vdev, int *done)
+static int vnic_dev_soft_reset_done(struct vnic_dev *vdev, int *done)
{
u64 a0 = 0, a1 = 0;
int wait = 1000;
@@ -669,26 +639,6 @@ int vnic_dev_packet_filter(struct vnic_dev *vdev, int directed, int multicast,
return err;
}
-int vnic_dev_packet_filter_all(struct vnic_dev *vdev, int directed,
- int multicast, int broadcast, int promisc, int allmulti)
-{
- u64 a0, a1 = 0;
- int wait = 1000;
- int err;
-
- a0 = (directed ? CMD_PFILTER_DIRECTED : 0) |
- (multicast ? CMD_PFILTER_MULTICAST : 0) |
- (broadcast ? CMD_PFILTER_BROADCAST : 0) |
- (promisc ? CMD_PFILTER_PROMISCUOUS : 0) |
- (allmulti ? CMD_PFILTER_ALL_MULTICAST : 0);
-
- err = vnic_dev_cmd(vdev, CMD_PACKET_FILTER_ALL, &a0, &a1, wait);
- if (err)
- pr_err("Can't set packet filter\n");
-
- return err;
-}
-
int vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr)
{
u64 a0 = 0, a1 = 0;
@@ -737,20 +687,7 @@ int vnic_dev_set_ig_vlan_rewrite_mode(struct vnic_dev *vdev,
return err;
}
-int vnic_dev_raise_intr(struct vnic_dev *vdev, u16 intr)
-{
- u64 a0 = intr, a1 = 0;
- int wait = 1000;
- int err;
-
- err = vnic_dev_cmd(vdev, CMD_IAR, &a0, &a1, wait);
- if (err)
- pr_err("Failed to raise INTR[%d], err %d\n", intr, err);
-
- return err;
-}
-
-int vnic_dev_notify_setcmd(struct vnic_dev *vdev,
+static int vnic_dev_notify_setcmd(struct vnic_dev *vdev,
void *notify_addr, dma_addr_t notify_pa, u16 intr)
{
u64 a0, a1;
@@ -789,7 +726,7 @@ int vnic_dev_notify_set(struct vnic_dev *vdev, u16 intr)
return vnic_dev_notify_setcmd(vdev, notify_addr, notify_pa, intr);
}
-int vnic_dev_notify_unsetcmd(struct vnic_dev *vdev)
+static int vnic_dev_notify_unsetcmd(struct vnic_dev *vdev)
{
u64 a0, a1;
int wait = 1000;
@@ -943,30 +880,6 @@ u32 vnic_dev_mtu(struct vnic_dev *vdev)
return vdev->notify_copy.mtu;
}
-u32 vnic_dev_link_down_cnt(struct vnic_dev *vdev)
-{
- if (!vnic_dev_notify_ready(vdev))
- return 0;
-
- return vdev->notify_copy.link_down_cnt;
-}
-
-u32 vnic_dev_notify_status(struct vnic_dev *vdev)
-{
- if (!vnic_dev_notify_ready(vdev))
- return 0;
-
- return vdev->notify_copy.status;
-}
-
-u32 vnic_dev_uif(struct vnic_dev *vdev)
-{
- if (!vnic_dev_notify_ready(vdev))
- return 0;
-
- return vdev->notify_copy.uif;
-}
-
void vnic_dev_set_intr_mode(struct vnic_dev *vdev,
enum vnic_dev_intr_mode intr_mode)
{
diff --git a/drivers/net/enic/vnic_dev.h b/drivers/net/enic/vnic_dev.h
index 3a61873138b6..05f9a24cd459 100644
--- a/drivers/net/enic/vnic_dev.h
+++ b/drivers/net/enic/vnic_dev.h
@@ -84,10 +84,6 @@ unsigned int vnic_dev_get_res_count(struct vnic_dev *vdev,
enum vnic_res_type type);
void __iomem *vnic_dev_get_res(struct vnic_dev *vdev, enum vnic_res_type type,
unsigned int index);
-dma_addr_t vnic_dev_get_res_bus_addr(struct vnic_dev *vdev,
- enum vnic_res_type type, unsigned int index);
-unsigned int vnic_dev_desc_ring_size(struct vnic_dev_ring *ring,
- unsigned int desc_count, unsigned int desc_size);
void vnic_dev_clear_desc_ring(struct vnic_dev_ring *ring);
int vnic_dev_alloc_desc_ring(struct vnic_dev *vdev, struct vnic_dev_ring *ring,
unsigned int desc_count, unsigned int desc_size);
@@ -95,39 +91,26 @@ void vnic_dev_free_desc_ring(struct vnic_dev *vdev,
struct vnic_dev_ring *ring);
int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
u64 *a0, u64 *a1, int wait);
-void vnic_dev_cmd_proxy_by_bdf_start(struct vnic_dev *vdev, u16 bdf);
-void vnic_dev_cmd_proxy_end(struct vnic_dev *vdev);
int vnic_dev_fw_info(struct vnic_dev *vdev,
struct vnic_devcmd_fw_info **fw_info);
int vnic_dev_hw_version(struct vnic_dev *vdev,
enum vnic_dev_hw_version *hw_ver);
int vnic_dev_spec(struct vnic_dev *vdev, unsigned int offset, unsigned int size,
void *value);
-int vnic_dev_stats_clear(struct vnic_dev *vdev);
int vnic_dev_stats_dump(struct vnic_dev *vdev, struct vnic_stats **stats);
int vnic_dev_hang_notify(struct vnic_dev *vdev);
int vnic_dev_packet_filter(struct vnic_dev *vdev, int directed, int multicast,
int broadcast, int promisc, int allmulti);
-int vnic_dev_packet_filter_all(struct vnic_dev *vdev, int directed,
- int multicast, int broadcast, int promisc, int allmulti);
int vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr);
int vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr);
int vnic_dev_mac_addr(struct vnic_dev *vdev, u8 *mac_addr);
-int vnic_dev_raise_intr(struct vnic_dev *vdev, u16 intr);
-int vnic_dev_notify_setcmd(struct vnic_dev *vdev,
- void *notify_addr, dma_addr_t notify_pa, u16 intr);
int vnic_dev_notify_set(struct vnic_dev *vdev, u16 intr);
-int vnic_dev_notify_unsetcmd(struct vnic_dev *vdev);
int vnic_dev_notify_unset(struct vnic_dev *vdev);
int vnic_dev_link_status(struct vnic_dev *vdev);
u32 vnic_dev_port_speed(struct vnic_dev *vdev);
u32 vnic_dev_msg_lvl(struct vnic_dev *vdev);
u32 vnic_dev_mtu(struct vnic_dev *vdev);
-u32 vnic_dev_link_down_cnt(struct vnic_dev *vdev);
-u32 vnic_dev_notify_status(struct vnic_dev *vdev);
-u32 vnic_dev_uif(struct vnic_dev *vdev);
int vnic_dev_close(struct vnic_dev *vdev);
-int vnic_dev_enable(struct vnic_dev *vdev);
int vnic_dev_enable_wait(struct vnic_dev *vdev);
int vnic_dev_disable(struct vnic_dev *vdev);
int vnic_dev_open(struct vnic_dev *vdev, int arg);
@@ -136,8 +119,6 @@ int vnic_dev_init(struct vnic_dev *vdev, int arg);
int vnic_dev_init_done(struct vnic_dev *vdev, int *done, int *err);
int vnic_dev_init_prov(struct vnic_dev *vdev, u8 *buf, u32 len);
int vnic_dev_deinit(struct vnic_dev *vdev);
-int vnic_dev_soft_reset(struct vnic_dev *vdev, int arg);
-int vnic_dev_soft_reset_done(struct vnic_dev *vdev, int *done);
int vnic_dev_hang_reset(struct vnic_dev *vdev, int arg);
int vnic_dev_hang_reset_done(struct vnic_dev *vdev, int *done);
void vnic_dev_set_intr_mode(struct vnic_dev *vdev,
diff --git a/drivers/net/enic/vnic_devcmd.h b/drivers/net/enic/vnic_devcmd.h
index 20661755df6b..9abb3d51dea1 100644
--- a/drivers/net/enic/vnic_devcmd.h
+++ b/drivers/net/enic/vnic_devcmd.h
@@ -238,6 +238,18 @@ enum vnic_devcmd_cmd {
* out: (u32)a0=status of proxied cmd
* a1-a15=out args of proxied cmd */
CMD_PROXY_BY_BDF = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 42),
+
+ /*
+ * As for BY_BDF except a0 is index of hvnlink subordinate vnic
+ * or SR-IOV virtual vnic */
+ CMD_PROXY_BY_INDEX = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 43),
+
+ /*
+ * in: (u64)a0=paddr of buffer to put latest VIC VIF-CONFIG-INFO TLV in
+ * (u32)a1=length of buffer in a0
+ * out: (u64)a0=paddr of buffer with latest VIC VIF-CONFIG-INFO TLV
+ * (u32)a1=actual length of latest VIC VIF-CONFIG-INFO TLV */
+ CMD_CONFIG_INFO_GET = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 44),
};
/* flags for CMD_OPEN */
diff --git a/drivers/net/enic/vnic_enet.h b/drivers/net/enic/vnic_enet.h
index 3b3291248956..e8740e3704e4 100644
--- a/drivers/net/enic/vnic_enet.h
+++ b/drivers/net/enic/vnic_enet.h
@@ -30,7 +30,7 @@ struct vnic_enet_config {
u32 wq_desc_count;
u32 rq_desc_count;
u16 mtu;
- u16 intr_timer;
+ u16 intr_timer_deprecated;
u8 intr_timer_type;
u8 intr_mode;
char devname[16];
diff --git a/drivers/net/enic/vnic_intr.c b/drivers/net/enic/vnic_intr.c
index 52ab61af2750..3873771d75cc 100644
--- a/drivers/net/enic/vnic_intr.c
+++ b/drivers/net/enic/vnic_intr.c
@@ -65,8 +65,3 @@ void vnic_intr_clean(struct vnic_intr *intr)
{
iowrite32(0, &intr->ctrl->int_credits);
}
-
-void vnic_intr_raise(struct vnic_intr *intr)
-{
- vnic_dev_raise_intr(intr->vdev, (u16)intr->index);
-}
diff --git a/drivers/net/enic/vnic_resource.h b/drivers/net/enic/vnic_resource.h
index 810287beff14..e0a73f1ca6f4 100644
--- a/drivers/net/enic/vnic_resource.h
+++ b/drivers/net/enic/vnic_resource.h
@@ -22,6 +22,11 @@
#define VNIC_RES_MAGIC 0x766E6963L /* 'vnic' */
#define VNIC_RES_VERSION 0x00000000L
+#define MGMTVNIC_MAGIC 0x544d474dL /* 'MGMT' */
+#define MGMTVNIC_VERSION 0x00000000L
+
+/* The MAC address assigned to the CFG vNIC is fixed. */
+#define MGMTVNIC_MAC { 0x02, 0x00, 0x54, 0x4d, 0x47, 0x4d }
/* vNIC resource types */
enum vnic_res_type {
@@ -52,6 +57,14 @@ struct vnic_resource_header {
u32 version;
};
+struct mgmt_barmap_hdr {
+ u32 magic; /* magic number */
+ u32 version; /* header format version */
+ u16 lif; /* loopback lif for mgmt frames */
+ u16 pci_slot; /* installed pci slot */
+ char serial[16]; /* card serial number */
+};
+
struct vnic_resource {
u8 type;
u8 bar;
diff --git a/drivers/net/enic/vnic_rq.c b/drivers/net/enic/vnic_rq.c
index dbb2aca258b9..34105e0951a5 100644
--- a/drivers/net/enic/vnic_rq.c
+++ b/drivers/net/enic/vnic_rq.c
@@ -77,8 +77,10 @@ void vnic_rq_free(struct vnic_rq *rq)
vnic_dev_free_desc_ring(vdev, &rq->ring);
for (i = 0; i < VNIC_RQ_BUF_BLKS_MAX; i++) {
- kfree(rq->bufs[i]);
- rq->bufs[i] = NULL;
+ if (rq->bufs[i]) {
+ kfree(rq->bufs[i]);
+ rq->bufs[i] = NULL;
+ }
}
rq->ctrl = NULL;
@@ -113,7 +115,7 @@ int vnic_rq_alloc(struct vnic_dev *vdev, struct vnic_rq *rq, unsigned int index,
return 0;
}
-void vnic_rq_init_start(struct vnic_rq *rq, unsigned int cq_index,
+static void vnic_rq_init_start(struct vnic_rq *rq, unsigned int cq_index,
unsigned int fetch_index, unsigned int posted_index,
unsigned int error_interrupt_enable,
unsigned int error_interrupt_offset)
diff --git a/drivers/net/enic/vnic_rq.h b/drivers/net/enic/vnic_rq.h
index 2dc48f91abf7..37f08de2454a 100644
--- a/drivers/net/enic/vnic_rq.h
+++ b/drivers/net/enic/vnic_rq.h
@@ -143,7 +143,7 @@ static inline void vnic_rq_post(struct vnic_rq *rq,
static inline int vnic_rq_posting_soon(struct vnic_rq *rq)
{
- return ((rq->to_use->index & VNIC_RQ_RETURN_RATE) == 0);
+ return (rq->to_use->index & VNIC_RQ_RETURN_RATE) == 0;
}
static inline void vnic_rq_return_descs(struct vnic_rq *rq, unsigned int count)
@@ -202,10 +202,6 @@ static inline int vnic_rq_fill(struct vnic_rq *rq,
void vnic_rq_free(struct vnic_rq *rq);
int vnic_rq_alloc(struct vnic_dev *vdev, struct vnic_rq *rq, unsigned int index,
unsigned int desc_count, unsigned int desc_size);
-void vnic_rq_init_start(struct vnic_rq *rq, unsigned int cq_index,
- unsigned int fetch_index, unsigned int posted_index,
- unsigned int error_interrupt_enable,
- unsigned int error_interrupt_offset);
void vnic_rq_init(struct vnic_rq *rq, unsigned int cq_index,
unsigned int error_interrupt_enable,
unsigned int error_interrupt_offset);
diff --git a/drivers/net/enic/vnic_rss.h b/drivers/net/enic/vnic_rss.h
index f62d18719629..fa421baf45b8 100644
--- a/drivers/net/enic/vnic_rss.h
+++ b/drivers/net/enic/vnic_rss.h
@@ -37,9 +37,4 @@ union vnic_rss_cpu {
u64 raw[32];
};
-void vnic_set_rss_key(union vnic_rss_key *rss_key, u8 *key);
-void vnic_set_rss_cpu(union vnic_rss_cpu *rss_cpu, u8 *cpu);
-void vnic_get_rss_key(union vnic_rss_key *rss_key, u8 *key);
-void vnic_get_rss_cpu(union vnic_rss_cpu *rss_cpu, u8 *cpu);
-
#endif /* _VNIC_RSS_H_ */
diff --git a/drivers/net/enic/vnic_vic.c b/drivers/net/enic/vnic_vic.c
index 197c9d24af82..4725b79de0ef 100644
--- a/drivers/net/enic/vnic_vic.c
+++ b/drivers/net/enic/vnic_vic.c
@@ -54,8 +54,8 @@ int vic_provinfo_add_tlv(struct vic_provinfo *vp, u16 type, u16 length,
if (!vp || !value)
return -EINVAL;
- if (ntohl(vp->length) + sizeof(*tlv) + length >
- VIC_PROVINFO_MAX_TLV_DATA)
+ if (ntohl(vp->length) + offsetof(struct vic_provinfo_tlv, value) +
+ length > VIC_PROVINFO_MAX_TLV_DATA)
return -ENOMEM;
tlv = (struct vic_provinfo_tlv *)((u8 *)vp->tlv +
@@ -66,7 +66,8 @@ int vic_provinfo_add_tlv(struct vic_provinfo *vp, u16 type, u16 length,
memcpy(tlv->value, value, length);
vp->num_tlvs = htonl(ntohl(vp->num_tlvs) + 1);
- vp->length = htonl(ntohl(vp->length) + sizeof(*tlv) + length);
+ vp->length = htonl(ntohl(vp->length) +
+ offsetof(struct vic_provinfo_tlv, value) + length);
return 0;
}
diff --git a/drivers/net/enic/vnic_wq.c b/drivers/net/enic/vnic_wq.c
index 122e33bcc578..df61bd932ea6 100644
--- a/drivers/net/enic/vnic_wq.c
+++ b/drivers/net/enic/vnic_wq.c
@@ -77,8 +77,10 @@ void vnic_wq_free(struct vnic_wq *wq)
vnic_dev_free_desc_ring(vdev, &wq->ring);
for (i = 0; i < VNIC_WQ_BUF_BLKS_MAX; i++) {
- kfree(wq->bufs[i]);
- wq->bufs[i] = NULL;
+ if (wq->bufs[i]) {
+ kfree(wq->bufs[i]);
+ wq->bufs[i] = NULL;
+ }
}
wq->ctrl = NULL;
@@ -113,7 +115,7 @@ int vnic_wq_alloc(struct vnic_dev *vdev, struct vnic_wq *wq, unsigned int index,
return 0;
}
-void vnic_wq_init_start(struct vnic_wq *wq, unsigned int cq_index,
+static void vnic_wq_init_start(struct vnic_wq *wq, unsigned int cq_index,
unsigned int fetch_index, unsigned int posted_index,
unsigned int error_interrupt_enable,
unsigned int error_interrupt_offset)
diff --git a/drivers/net/enic/vnic_wq.h b/drivers/net/enic/vnic_wq.h
index 94ac4621acc5..7dd937ac11c2 100644
--- a/drivers/net/enic/vnic_wq.h
+++ b/drivers/net/enic/vnic_wq.h
@@ -153,10 +153,6 @@ static inline void vnic_wq_service(struct vnic_wq *wq,
void vnic_wq_free(struct vnic_wq *wq);
int vnic_wq_alloc(struct vnic_dev *vdev, struct vnic_wq *wq, unsigned int index,
unsigned int desc_count, unsigned int desc_size);
-void vnic_wq_init_start(struct vnic_wq *wq, unsigned int cq_index,
- unsigned int fetch_index, unsigned int posted_index,
- unsigned int error_interrupt_enable,
- unsigned int error_interrupt_offset);
void vnic_wq_init(struct vnic_wq *wq, unsigned int cq_index,
unsigned int error_interrupt_enable,
unsigned int error_interrupt_offset);
diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c
index 57c8ac0ef3f1..32543a300b81 100644
--- a/drivers/net/epic100.c
+++ b/drivers/net/epic100.c
@@ -758,7 +758,7 @@ static int epic_open(struct net_device *dev)
init_timer(&ep->timer);
ep->timer.expires = jiffies + 3*HZ;
ep->timer.data = (unsigned long)dev;
- ep->timer.function = &epic_timer; /* timer handler */
+ ep->timer.function = epic_timer; /* timer handler */
add_timer(&ep->timer);
return 0;
diff --git a/drivers/net/eth16i.c b/drivers/net/eth16i.c
index 10e39f2b31c3..fb717be511f6 100644
--- a/drivers/net/eth16i.c
+++ b/drivers/net/eth16i.c
@@ -637,7 +637,9 @@ static void eth16i_initialize(struct net_device *dev, int boot)
/* Set interface port type */
if(boot) {
- char *porttype[] = {"BNC", "DIX", "TP", "AUTO", "FROM_EPROM" };
+ static const char * const porttype[] = {
+ "BNC", "DIX", "TP", "AUTO", "FROM_EPROM"
+ };
switch(dev->if_port)
{
@@ -794,7 +796,7 @@ static int eth16i_receive_probe_packet(int ioaddr)
if(eth16i_debug > 1)
printk(KERN_DEBUG "RECEIVE_PACKET\n");
- return(0); /* Found receive packet */
+ return 0; /* Found receive packet */
}
}
@@ -803,7 +805,7 @@ static int eth16i_receive_probe_packet(int ioaddr)
printk(KERN_DEBUG "RX_STATUS_REG = %x\n", inb(ioaddr + RX_STATUS_REG));
}
- return(0); /* Return success */
+ return 0; /* Return success */
}
#if 0
@@ -839,7 +841,7 @@ static int __init eth16i_get_irq(int ioaddr)
if( ioaddr < 0x1000) {
cbyte = inb(ioaddr + JUMPERLESS_CONFIG);
- return( eth16i_irqmap[ ((cbyte & 0xC0) >> 6) ] );
+ return eth16i_irqmap[((cbyte & 0xC0) >> 6)];
} else { /* Oh..the card is EISA so method getting IRQ different */
unsigned short index = 0;
cbyte = inb(ioaddr + EISA_IRQ_REG);
@@ -847,7 +849,7 @@ static int __init eth16i_get_irq(int ioaddr)
cbyte = cbyte >> 1;
index++;
}
- return( eth32i_irqmap[ index ] );
+ return eth32i_irqmap[index];
}
}
@@ -907,7 +909,7 @@ static int eth16i_read_eeprom(int ioaddr, int offset)
data = eth16i_read_eeprom_word(ioaddr);
outb(CS_0 | SK_0, ioaddr + EEPROM_CTRL_REG);
- return(data);
+ return data;
}
static int eth16i_read_eeprom_word(int ioaddr)
@@ -926,7 +928,7 @@ static int eth16i_read_eeprom_word(int ioaddr)
eeprom_slow_io();
}
- return(data);
+ return data;
}
static void eth16i_eeprom_cmd(int ioaddr, unsigned char command)
diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
index 6d653c459c1f..c5a2fe099a8d 100644
--- a/drivers/net/ethoc.c
+++ b/drivers/net/ethoc.c
@@ -806,11 +806,6 @@ static void ethoc_tx_timeout(struct net_device *dev)
ethoc_interrupt(dev->irq, dev);
}
-static struct net_device_stats *ethoc_stats(struct net_device *dev)
-{
- return &dev->stats;
-}
-
static netdev_tx_t ethoc_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct ethoc *priv = netdev_priv(dev);
@@ -863,7 +858,6 @@ static const struct net_device_ops ethoc_netdev_ops = {
.ndo_set_multicast_list = ethoc_set_multicast_list,
.ndo_change_mtu = ethoc_change_mtu,
.ndo_tx_timeout = ethoc_tx_timeout,
- .ndo_get_stats = ethoc_stats,
.ndo_start_xmit = ethoc_start_xmit,
};
diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c
index d7e8f6b8f4cf..dd54abe2f710 100644
--- a/drivers/net/fealnx.c
+++ b/drivers/net/fealnx.c
@@ -915,14 +915,14 @@ static int netdev_open(struct net_device *dev)
init_timer(&np->timer);
np->timer.expires = RUN_AT(3 * HZ);
np->timer.data = (unsigned long) dev;
- np->timer.function = &netdev_timer;
+ np->timer.function = netdev_timer;
/* timer handler */
add_timer(&np->timer);
init_timer(&np->reset_timer);
np->reset_timer.data = (unsigned long) dev;
- np->reset_timer.function = &reset_timer;
+ np->reset_timer.function = reset_timer;
np->reset_timer_armed = 0;
return 0;
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index 768b840aeb6b..cce32d43175f 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -678,24 +678,37 @@ static int fec_enet_mii_probe(struct net_device *dev)
{
struct fec_enet_private *fep = netdev_priv(dev);
struct phy_device *phy_dev = NULL;
- int ret;
+ char mdio_bus_id[MII_BUS_ID_SIZE];
+ char phy_name[MII_BUS_ID_SIZE + 3];
+ int phy_id;
fep->phy_dev = NULL;
- /* find the first phy */
- phy_dev = phy_find_first(fep->mii_bus);
- if (!phy_dev) {
- printk(KERN_ERR "%s: no PHY found\n", dev->name);
- return -ENODEV;
+ /* check for attached phy */
+ for (phy_id = 0; (phy_id < PHY_MAX_ADDR); phy_id++) {
+ if ((fep->mii_bus->phy_mask & (1 << phy_id)))
+ continue;
+ if (fep->mii_bus->phy_map[phy_id] == NULL)
+ continue;
+ if (fep->mii_bus->phy_map[phy_id]->phy_id == 0)
+ continue;
+ strncpy(mdio_bus_id, fep->mii_bus->id, MII_BUS_ID_SIZE);
+ break;
}
- /* attach the mac to the phy */
- ret = phy_connect_direct(dev, phy_dev,
- &fec_enet_adjust_link, 0,
- PHY_INTERFACE_MODE_MII);
- if (ret) {
- printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
- return ret;
+ if (phy_id >= PHY_MAX_ADDR) {
+ printk(KERN_INFO "%s: no PHY, assuming direct connection "
+ "to switch\n", dev->name);
+ strncpy(mdio_bus_id, "0", MII_BUS_ID_SIZE);
+ phy_id = 0;
+ }
+
+ snprintf(phy_name, MII_BUS_ID_SIZE, PHY_ID_FMT, mdio_bus_id, phy_id);
+ phy_dev = phy_connect(dev, phy_name, &fec_enet_adjust_link, 0,
+ PHY_INTERFACE_MODE_MII);
+ if (IS_ERR(phy_dev)) {
+ printk(KERN_ERR "%s: could not attach to PHY\n", dev->name);
+ return PTR_ERR(phy_dev);
}
/* mask with MAC supported features */
@@ -738,7 +751,7 @@ static int fec_enet_mii_init(struct platform_device *pdev)
fep->mii_bus->read = fec_enet_mdio_read;
fep->mii_bus->write = fec_enet_mdio_write;
fep->mii_bus->reset = fec_enet_mdio_reset;
- snprintf(fep->mii_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id);
+ snprintf(fep->mii_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id + 1);
fep->mii_bus->priv = fep;
fep->mii_bus->parent = &pdev->dev;
@@ -1311,6 +1324,9 @@ fec_probe(struct platform_device *pdev)
if (ret)
goto failed_mii_init;
+ /* Carrier starts down, phylib will bring it up */
+ netif_carrier_off(ndev);
+
ret = register_netdev(ndev);
if (ret)
goto failed_register;
diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c
index e3e10b4add9c..e9f5d030bc26 100644
--- a/drivers/net/fec_mpc52xx.c
+++ b/drivers/net/fec_mpc52xx.c
@@ -771,11 +771,6 @@ static void mpc52xx_fec_reset(struct net_device *dev)
/* ethtool interface */
-static void mpc52xx_fec_get_drvinfo(struct net_device *dev,
- struct ethtool_drvinfo *info)
-{
- strcpy(info->driver, DRIVER_NAME);
-}
static int mpc52xx_fec_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
@@ -810,7 +805,6 @@ static void mpc52xx_fec_set_msglevel(struct net_device *dev, u32 level)
}
static const struct ethtool_ops mpc52xx_fec_ethtool_ops = {
- .get_drvinfo = mpc52xx_fec_get_drvinfo,
.get_settings = mpc52xx_fec_get_settings,
.set_settings = mpc52xx_fec_set_settings,
.get_link = ethtool_op_get_link,
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index 4da05b1b445c..0fa1776563a3 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -2321,14 +2321,11 @@ static netdev_tx_t nv_start_xmit_optimized(struct sk_buff *skb,
NV_TX2_CHECKSUM_L3 | NV_TX2_CHECKSUM_L4 : 0;
/* vlan tag */
- if (likely(!np->vlangrp)) {
+ if (vlan_tx_tag_present(skb))
+ start_tx->txvlan = cpu_to_le32(NV_TX3_VLAN_TAG_PRESENT |
+ vlan_tx_tag_get(skb));
+ else
start_tx->txvlan = 0;
- } else {
- if (vlan_tx_tag_present(skb))
- start_tx->txvlan = cpu_to_le32(NV_TX3_VLAN_TAG_PRESENT | vlan_tx_tag_get(skb));
- else
- start_tx->txvlan = 0;
- }
spin_lock_irqsave(&np->lock, flags);
@@ -4620,7 +4617,7 @@ static int nv_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam*
static u32 nv_get_rx_csum(struct net_device *dev)
{
struct fe_priv *np = netdev_priv(dev);
- return (np->rx_csum) != 0;
+ return np->rx_csum != 0;
}
static int nv_set_rx_csum(struct net_device *dev, u32 data)
@@ -5440,13 +5437,13 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
init_timer(&np->oom_kick);
np->oom_kick.data = (unsigned long) dev;
- np->oom_kick.function = &nv_do_rx_refill; /* timer handler */
+ np->oom_kick.function = nv_do_rx_refill; /* timer handler */
init_timer(&np->nic_poll);
np->nic_poll.data = (unsigned long) dev;
- np->nic_poll.function = &nv_do_nic_poll; /* timer handler */
+ np->nic_poll.function = nv_do_nic_poll; /* timer handler */
init_timer(&np->stats_poll);
np->stats_poll.data = (unsigned long) dev;
- np->stats_poll.function = &nv_do_stats_poll; /* timer handler */
+ np->stats_poll.function = nv_do_stats_poll; /* timer handler */
err = pci_enable_device(pci_dev);
if (err)
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
index d6e3111959ab..d684f187de57 100644
--- a/drivers/net/fs_enet/fs_enet-main.c
+++ b/drivers/net/fs_enet/fs_enet-main.c
@@ -1036,7 +1036,7 @@ static int __devinit fs_enet_probe(struct platform_device *ofdev,
ndev = alloc_etherdev(privsize);
if (!ndev) {
ret = -ENOMEM;
- goto out_free_fpi;
+ goto out_put;
}
SET_NETDEV_DEV(ndev, &ofdev->dev);
@@ -1099,6 +1099,7 @@ out_cleanup_data:
out_free_dev:
free_netdev(ndev);
dev_set_drvdata(&ofdev->dev, NULL);
+out_put:
of_node_put(fpi->phy_node);
out_free_fpi:
kfree(fpi);
diff --git a/drivers/net/fsl_pq_mdio.c b/drivers/net/fsl_pq_mdio.c
index d4bf91aac25f..8d3a2ccbc953 100644
--- a/drivers/net/fsl_pq_mdio.c
+++ b/drivers/net/fsl_pq_mdio.c
@@ -125,7 +125,7 @@ int fsl_pq_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value)
struct fsl_pq_mdio __iomem *regs = fsl_pq_mdio_get_regs(bus);
/* Write to the local MII regs */
- return(fsl_pq_local_mdio_write(regs, mii_id, regnum, value));
+ return fsl_pq_local_mdio_write(regs, mii_id, regnum, value);
}
/*
@@ -137,7 +137,7 @@ int fsl_pq_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
struct fsl_pq_mdio __iomem *regs = fsl_pq_mdio_get_regs(bus);
/* Read the local MII regs */
- return(fsl_pq_local_mdio_read(regs, mii_id, regnum));
+ return fsl_pq_local_mdio_read(regs, mii_id, regnum);
}
/* Reset the MIIM registers, and wait for the bus to free */
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 4f7c3f3ca234..4c4cc80ec0a1 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -654,9 +654,8 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)
priv->node = ofdev->dev.of_node;
priv->ndev = dev;
- dev->num_tx_queues = num_tx_qs;
- dev->real_num_tx_queues = num_tx_qs;
priv->num_tx_queues = num_tx_qs;
+ netif_set_real_num_rx_queues(dev, num_rx_qs);
priv->num_rx_queues = num_rx_qs;
priv->num_grps = 0x0;
@@ -1859,7 +1858,7 @@ static int register_grp_irqs(struct gfar_priv_grp *grp)
printk(KERN_ERR "%s: Can't get IRQ %d\n",
dev->name, grp->interruptError);
- goto err_irq_fail;
+ goto err_irq_fail;
}
if ((err = request_irq(grp->interruptTransmit, gfar_transmit,
@@ -2048,7 +2047,6 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
u32 bufaddr;
unsigned long flags;
unsigned int nr_frags, nr_txbds, length;
- union skb_shared_tx *shtx;
/*
* TOE=1 frames larger than 2500 bytes may see excess delays
@@ -2069,15 +2067,15 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
txq = netdev_get_tx_queue(dev, rq);
base = tx_queue->tx_bd_base;
regs = tx_queue->grp->regs;
- shtx = skb_tx(skb);
/* check if time stamp should be generated */
- if (unlikely(shtx->hardware && priv->hwts_tx_en))
+ if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP &&
+ priv->hwts_tx_en))
do_tstamp = 1;
/* make space for additional header when fcb is needed */
if (((skb->ip_summed == CHECKSUM_PARTIAL) ||
- (priv->vlgrp && vlan_tx_tag_present(skb)) ||
+ vlan_tx_tag_present(skb) ||
unlikely(do_tstamp)) &&
(skb_headroom(skb) < GMAC_FCB_LEN)) {
struct sk_buff *skb_new;
@@ -2163,7 +2161,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
gfar_tx_checksum(skb, fcb);
}
- if (priv->vlgrp && vlan_tx_tag_present(skb)) {
+ if (vlan_tx_tag_present(skb)) {
if (unlikely(NULL == fcb)) {
fcb = gfar_add_fcb(skb);
lstatus |= BD_LFLAG(TXBD_TOE);
@@ -2174,7 +2172,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* Setup tx hardware time stamping if requested */
if (unlikely(do_tstamp)) {
- shtx->in_progress = 1;
+ skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
if (fcb == NULL)
fcb = gfar_add_fcb(skb);
fcb->ptp = 1;
@@ -2446,7 +2444,6 @@ static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue)
int howmany = 0;
u32 lstatus;
size_t buflen;
- union skb_shared_tx *shtx;
rx_queue = priv->rx_queue[tx_queue->qindex];
bdp = tx_queue->dirty_tx;
@@ -2461,8 +2458,7 @@ static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue)
* When time stamping, one additional TxBD must be freed.
* Also, we need to dma_unmap_single() the TxPAL.
*/
- shtx = skb_tx(skb);
- if (unlikely(shtx->in_progress))
+ if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS))
nr_txbds = frags + 2;
else
nr_txbds = frags + 1;
@@ -2476,7 +2472,7 @@ static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue)
(lstatus & BD_LENGTH_MASK))
break;
- if (unlikely(shtx->in_progress)) {
+ if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) {
next = next_txbd(bdp, base, tx_ring_size);
buflen = next->length + GMAC_FCB_LEN;
} else
@@ -2485,7 +2481,7 @@ static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue)
dma_unmap_single(&priv->ofdev->dev, bdp->bufPtr,
buflen, DMA_TO_DEVICE);
- if (unlikely(shtx->in_progress)) {
+ if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) {
struct skb_shared_hwtstamps shhwtstamps;
u64 *ns = (u64*) (((u32)skb->data + 0x10) & ~0x7);
memset(&shhwtstamps, 0, sizeof(shhwtstamps));
@@ -2657,7 +2653,7 @@ static inline void gfar_rx_checksum(struct sk_buff *skb, struct rxfcb *fcb)
if ((fcb->flags & RXFCB_CSUM_MASK) == (RXFCB_CIP | RXFCB_CTU))
skb->ip_summed = CHECKSUM_UNNECESSARY;
else
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
}
diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c
index 9bda023c0235..5c566ebc54b8 100644
--- a/drivers/net/gianfar_ethtool.c
+++ b/drivers/net/gianfar_ethtool.c
@@ -254,7 +254,7 @@ static unsigned int gfar_usecs2ticks(struct gfar_private *priv, unsigned int use
/* Make sure we return a number greater than 0
* if usecs > 0 */
- return ((usecs * 1000 + count - 1) / count);
+ return (usecs * 1000 + count - 1) / count;
}
/* Convert ethernet clock ticks to microseconds */
@@ -278,7 +278,7 @@ static unsigned int gfar_ticks2usecs(struct gfar_private *priv, unsigned int tic
/* Make sure we return a number greater than 0 */
/* if ticks is > 0 */
- return ((ticks * count) / 1000);
+ return (ticks * count) / 1000;
}
/* Get the coalescing parameters, and put them in the cvals
@@ -538,7 +538,7 @@ static int gfar_set_rx_csum(struct net_device *dev, uint32_t data)
unlock_tx_qs(priv);
unlock_rx_qs(priv);
- local_irq_save(flags);
+ local_irq_restore(flags);
for (i = 0; i < priv->num_rx_queues; i++)
gfar_clean_rx_ring(priv->rx_queue[i],
diff --git a/drivers/net/greth.c b/drivers/net/greth.c
index f15c64f1cd38..27d6960ce09e 100644
--- a/drivers/net/greth.c
+++ b/drivers/net/greth.c
@@ -893,7 +893,7 @@ static int greth_rx_gbit(struct net_device *dev, int limit)
if (greth->flags & GRETH_FLAG_RX_CSUM && hw_checksummed(status))
skb->ip_summed = CHECKSUM_UNNECESSARY;
else
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
skb->protocol = eth_type_trans(skb, dev);
dev->stats.rx_packets++;
@@ -1547,10 +1547,10 @@ static int __devinit greth_of_probe(struct platform_device *ofdev, const struct
dev->netdev_ops = &greth_netdev_ops;
dev->ethtool_ops = &greth_ethtool_ops;
- if (register_netdev(dev)) {
+ err = register_netdev(dev);
+ if (err) {
if (netif_msg_probe(greth))
dev_err(greth->dev, "netdevice registration failed.\n");
- err = -ENOMEM;
goto error5;
}
diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c
index 49aac7027fbb..9a6485892b3d 100644
--- a/drivers/net/hamachi.c
+++ b/drivers/net/hamachi.c
@@ -1004,7 +1004,7 @@ static int hamachi_open(struct net_device *dev)
init_timer(&hmp->timer);
hmp->timer.expires = RUN_AT((24*HZ)/10); /* 2.4 sec. */
hmp->timer.data = (unsigned long)dev;
- hmp->timer.function = &hamachi_timer; /* timer handler */
+ hmp->timer.function = hamachi_timer; /* timer handler */
add_timer(&hmp->timer);
return 0;
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
index 4b52c767ad05..3e5d0b6b6516 100644
--- a/drivers/net/hamradio/6pack.c
+++ b/drivers/net/hamradio/6pack.c
@@ -608,7 +608,7 @@ static int sixpack_open(struct tty_struct *tty)
spin_lock_init(&sp->lock);
atomic_set(&sp->refcnt, 1);
- init_MUTEX_LOCKED(&sp->dead_sem);
+ sema_init(&sp->dead_sem, 0);
/* !!! length of the buffers. MTU is IP MTU, not PACLEN! */
diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c
index 14f01d156db9..ac1d323c5eb5 100644
--- a/drivers/net/hamradio/bpqether.c
+++ b/drivers/net/hamradio/bpqether.c
@@ -168,7 +168,7 @@ static inline struct net_device *bpq_get_ax25_dev(struct net_device *dev)
static inline int dev_is_ethdev(struct net_device *dev)
{
- return (dev->type == ARPHRD_ETHER && strncmp(dev->name, "dummy", 5));
+ return dev->type == ARPHRD_ETHER && strncmp(dev->name, "dummy", 5);
}
/* ------------------------------------------------------------------------ */
diff --git a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c
index b8bdf9d51cd4..5b37579e84b7 100644
--- a/drivers/net/hamradio/hdlcdrv.c
+++ b/drivers/net/hamradio/hdlcdrv.c
@@ -110,7 +110,7 @@ static int calc_crc_ccitt(const unsigned char *buf, int cnt)
for (; cnt > 0; cnt--)
crc = (crc >> 8) ^ crc_ccitt_table[(crc ^ *buf++) & 0xff];
crc ^= 0xffff;
- return (crc & 0xffff);
+ return crc & 0xffff;
}
#endif
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
index 66e88bd59caa..4c628393c8b1 100644
--- a/drivers/net/hamradio/mkiss.c
+++ b/drivers/net/hamradio/mkiss.c
@@ -747,7 +747,7 @@ static int mkiss_open(struct tty_struct *tty)
spin_lock_init(&ax->buflock);
atomic_set(&ax->refcnt, 1);
- init_MUTEX_LOCKED(&ax->dead_sem);
+ sema_init(&ax->dead_sem, 0);
ax->tty = tty;
tty->disc_data = ax;
diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c
index 9f64c8637208..33655814448e 100644
--- a/drivers/net/hamradio/scc.c
+++ b/drivers/net/hamradio/scc.c
@@ -1069,7 +1069,8 @@ static void scc_tx_done(struct scc_channel *scc)
case KISS_DUPLEX_LINK:
scc->stat.tx_state = TXS_IDLE2;
if (scc->kiss.idletime != TIMER_OFF)
- scc_start_tx_timer(scc, t_idle, scc->kiss.idletime*100);
+ scc_start_tx_timer(scc, t_idle,
+ scc->kiss.idletime*100);
break;
case KISS_DUPLEX_OPTIMA:
scc_notify(scc, HWEV_ALL_SENT);
diff --git a/drivers/net/hp.c b/drivers/net/hp.c
index 86ececd3c658..d15d2f2ba78e 100644
--- a/drivers/net/hp.c
+++ b/drivers/net/hp.c
@@ -204,10 +204,10 @@ static int __init hp_probe1(struct net_device *dev, int ioaddr)
ei_status.rx_start_page = HP_START_PG + TX_PAGES;
ei_status.stop_page = wordmode ? HP_16BSTOP_PG : HP_8BSTOP_PG;
- ei_status.reset_8390 = &hp_reset_8390;
- ei_status.get_8390_hdr = &hp_get_8390_hdr;
- ei_status.block_input = &hp_block_input;
- ei_status.block_output = &hp_block_output;
+ ei_status.reset_8390 = hp_reset_8390;
+ ei_status.get_8390_hdr = hp_get_8390_hdr;
+ ei_status.block_input = hp_block_input;
+ ei_status.block_output = hp_block_output;
hp_init_card(dev);
retval = register_netdev(dev);
diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c
index 095b17ecf609..8e2c4601b5f5 100644
--- a/drivers/net/hp100.c
+++ b/drivers/net/hp100.c
@@ -1312,7 +1312,7 @@ static int hp100_build_rx_pdl(hp100_ring_t * ringptr,
for (p = (ringptr->pdl); p < (ringptr->pdl + 5); p++)
printk("hp100: %s: Adr 0x%.8x = 0x%.8x\n", dev->name, (u_int) p, (u_int) * p);
#endif
- return (1);
+ return 1;
}
/* else: */
/* alloc_skb failed (no memory) -> still can receive the header
@@ -1325,7 +1325,7 @@ static int hp100_build_rx_pdl(hp100_ring_t * ringptr,
ringptr->pdl[0] = 0x00010000; /* PDH: Count=1 Fragment */
- return (0);
+ return 0;
}
/*
@@ -2752,7 +2752,7 @@ static int hp100_login_to_vg_hub(struct net_device *dev, u_short force_relogin)
hp100_outw(HP100_MISC_ERROR, IRQ_STATUS);
if (val & HP100_LINK_UP_ST)
- return (0); /* login was ok */
+ return 0; /* login was ok */
else {
printk("hp100: %s: Training failed.\n", dev->name);
hp100_down_vg_link(dev);
diff --git a/drivers/net/hydra.c b/drivers/net/hydra.c
index 07d8e5b634f3..c5ef62ceb840 100644
--- a/drivers/net/hydra.c
+++ b/drivers/net/hydra.c
@@ -155,10 +155,10 @@ static int __devinit hydra_init(struct zorro_dev *z)
ei_status.rx_start_page = start_page + TX_PAGES;
- ei_status.reset_8390 = &hydra_reset_8390;
- ei_status.block_input = &hydra_block_input;
- ei_status.block_output = &hydra_block_output;
- ei_status.get_8390_hdr = &hydra_get_8390_hdr;
+ ei_status.reset_8390 = hydra_reset_8390;
+ ei_status.block_input = hydra_block_input;
+ ei_status.block_output = hydra_block_output;
+ ei_status.get_8390_hdr = hydra_get_8390_hdr;
ei_status.reg_offset = hydra_offsets;
dev->netdev_ops = &hydra_netdev_ops;
@@ -173,9 +173,8 @@ static int __devinit hydra_init(struct zorro_dev *z)
zorro_set_drvdata(z, dev);
- printk(KERN_INFO "%s: Hydra at 0x%08llx, address "
- "%pM (hydra.c " HYDRA_VERSION ")\n",
- dev->name, (unsigned long long)z->resource.start, dev->dev_addr);
+ pr_info("%s: Hydra at %pR, address %pM (hydra.c " HYDRA_VERSION ")\n",
+ dev->name, &z->resource, dev->dev_addr);
return 0;
}
diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c
index 519e19e23955..385dc3204cb7 100644
--- a/drivers/net/ibm_newemac/core.c
+++ b/drivers/net/ibm_newemac/core.c
@@ -2095,11 +2095,11 @@ static void *emac_dump_regs(struct emac_instance *dev, void *buf)
if (emac_has_feature(dev, EMAC_FTR_EMAC4)) {
hdr->version = EMAC4_ETHTOOL_REGS_VER;
memcpy_fromio(hdr + 1, dev->emacp, EMAC4_ETHTOOL_REGS_SIZE(dev));
- return ((void *)(hdr + 1) + EMAC4_ETHTOOL_REGS_SIZE(dev));
+ return (void *)(hdr + 1) + EMAC4_ETHTOOL_REGS_SIZE(dev);
} else {
hdr->version = EMAC_ETHTOOL_REGS_VER;
memcpy_fromio(hdr + 1, dev->emacp, EMAC_ETHTOOL_REGS_SIZE(dev));
- return ((void *)(hdr + 1) + EMAC_ETHTOOL_REGS_SIZE(dev));
+ return (void *)(hdr + 1) + EMAC_ETHTOOL_REGS_SIZE(dev);
}
}
@@ -2293,7 +2293,7 @@ static int __devinit emac_check_deps(struct emac_instance *dev,
if (deps[i].drvdata != NULL)
there++;
}
- return (there == EMAC_DEP_COUNT);
+ return there == EMAC_DEP_COUNT;
}
static void emac_put_deps(struct emac_instance *dev)
diff --git a/drivers/net/ibm_newemac/core.h b/drivers/net/ibm_newemac/core.h
index 9e37e3d9c51d..4fec0844d59d 100644
--- a/drivers/net/ibm_newemac/core.h
+++ b/drivers/net/ibm_newemac/core.h
@@ -410,7 +410,7 @@ static inline u32 *emac_xaht_base(struct emac_instance *dev)
else
offset = offsetof(struct emac_regs, u0.emac4.iaht1);
- return ((u32 *)((ptrdiff_t)p + offset));
+ return (u32 *)((ptrdiff_t)p + offset);
}
static inline u32 *emac_gaht_base(struct emac_instance *dev)
@@ -418,7 +418,7 @@ static inline u32 *emac_gaht_base(struct emac_instance *dev)
/* GAHT registers always come after an identical number of
* IAHT registers.
*/
- return (emac_xaht_base(dev) + EMAC_XAHT_REGS(dev));
+ return emac_xaht_base(dev) + EMAC_XAHT_REGS(dev);
}
static inline u32 *emac_iaht_base(struct emac_instance *dev)
@@ -426,7 +426,7 @@ static inline u32 *emac_iaht_base(struct emac_instance *dev)
/* IAHT registers always come before an identical number of
* GAHT registers.
*/
- return (emac_xaht_base(dev));
+ return emac_xaht_base(dev);
}
/* Ethtool get_regs complex data.
diff --git a/drivers/net/ibmlana.c b/drivers/net/ibmlana.c
index 294ccfb427cf..0037a696cd0a 100644
--- a/drivers/net/ibmlana.c
+++ b/drivers/net/ibmlana.c
@@ -602,7 +602,7 @@ static void irqrx_handler(struct net_device *dev)
/* set up skb fields */
skb->protocol = eth_type_trans(skb, dev);
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
/* bookkeeping */
dev->stats.rx_packets++;
diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c
index 4734c939ad03..c454b45ca7ec 100644
--- a/drivers/net/ibmveth.c
+++ b/drivers/net/ibmveth.c
@@ -1,122 +1,84 @@
-/**************************************************************************/
-/* */
-/* IBM eServer i/pSeries Virtual Ethernet Device Driver */
-/* Copyright (C) 2003 IBM Corp. */
-/* Originally written by Dave Larson (larson1@us.ibm.com) */
-/* Maintained by Santiago Leon (santil@us.ibm.com) */
-/* */
-/* This program is free software; you can redistribute it and/or modify */
-/* it under the terms of the GNU General Public License as published by */
-/* the Free Software Foundation; either version 2 of the License, or */
-/* (at your option) any later version. */
-/* */
-/* This program is distributed in the hope that it will be useful, */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
-/* GNU General Public License for more details. */
-/* */
-/* You should have received a copy of the GNU General Public License */
-/* along with this program; if not, write to the Free Software */
-/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 */
-/* USA */
-/* */
-/* This module contains the implementation of a virtual ethernet device */
-/* for use with IBM i/pSeries LPAR Linux. It utilizes the logical LAN */
-/* option of the RS/6000 Platform Architechture to interface with virtual */
-/* ethernet NICs that are presented to the partition by the hypervisor. */
-/* */
-/**************************************************************************/
/*
- TODO:
- - add support for sysfs
- - possibly remove procfs support
-*/
+ * IBM Power Virtual Ethernet Device Driver
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) IBM Corporation, 2003, 2010
+ *
+ * Authors: Dave Larson <larson1@us.ibm.com>
+ * Santiago Leon <santil@linux.vnet.ibm.com>
+ * Brian King <brking@linux.vnet.ibm.com>
+ * Robert Jennings <rcj@linux.vnet.ibm.com>
+ * Anton Blanchard <anton@au.ibm.com>
+ */
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/types.h>
#include <linux/errno.h>
-#include <linux/ioport.h>
#include <linux/dma-mapping.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/init.h>
-#include <linux/delay.h>
#include <linux/mm.h>
#include <linux/pm.h>
#include <linux/ethtool.h>
-#include <linux/proc_fs.h>
#include <linux/in.h>
#include <linux/ip.h>
+#include <linux/ipv6.h>
#include <linux/slab.h>
-#include <net/net_namespace.h>
#include <asm/hvcall.h>
#include <asm/atomic.h>
#include <asm/vio.h>
#include <asm/iommu.h>
-#include <asm/uaccess.h>
#include <asm/firmware.h>
-#include <linux/seq_file.h>
#include "ibmveth.h"
-#undef DEBUG
-
-#define ibmveth_printk(fmt, args...) \
- printk(KERN_DEBUG "%s: " fmt, __FILE__, ## args)
-
-#define ibmveth_error_printk(fmt, args...) \
- printk(KERN_ERR "(%s:%3.3d ua:%x) ERROR: " fmt, __FILE__, __LINE__ , adapter->vdev->unit_address, ## args)
-
-#ifdef DEBUG
-#define ibmveth_debug_printk_no_adapter(fmt, args...) \
- printk(KERN_DEBUG "(%s:%3.3d): " fmt, __FILE__, __LINE__ , ## args)
-#define ibmveth_debug_printk(fmt, args...) \
- printk(KERN_DEBUG "(%s:%3.3d ua:%x): " fmt, __FILE__, __LINE__ , adapter->vdev->unit_address, ## args)
-#define ibmveth_assert(expr) \
- if(!(expr)) { \
- printk(KERN_DEBUG "assertion failed (%s:%3.3d ua:%x): %s\n", __FILE__, __LINE__, adapter->vdev->unit_address, #expr); \
- BUG(); \
- }
-#else
-#define ibmveth_debug_printk_no_adapter(fmt, args...)
-#define ibmveth_debug_printk(fmt, args...)
-#define ibmveth_assert(expr)
-#endif
-
-static int ibmveth_open(struct net_device *dev);
-static int ibmveth_close(struct net_device *dev);
-static int ibmveth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
-static int ibmveth_poll(struct napi_struct *napi, int budget);
-static int ibmveth_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static void ibmveth_set_multicast_list(struct net_device *dev);
-static int ibmveth_change_mtu(struct net_device *dev, int new_mtu);
-static void ibmveth_proc_register_driver(void);
-static void ibmveth_proc_unregister_driver(void);
-static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter);
-static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter);
static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance);
static void ibmveth_rxq_harvest_buffer(struct ibmveth_adapter *adapter);
static unsigned long ibmveth_get_desired_dma(struct vio_dev *vdev);
-static struct kobj_type ktype_veth_pool;
+static struct kobj_type ktype_veth_pool;
-#ifdef CONFIG_PROC_FS
-#define IBMVETH_PROC_DIR "ibmveth"
-static struct proc_dir_entry *ibmveth_proc_dir;
-#endif
static const char ibmveth_driver_name[] = "ibmveth";
-static const char ibmveth_driver_string[] = "IBM i/pSeries Virtual Ethernet Driver";
-#define ibmveth_driver_version "1.03"
+static const char ibmveth_driver_string[] = "IBM Power Virtual Ethernet Driver";
+#define ibmveth_driver_version "1.04"
-MODULE_AUTHOR("Santiago Leon <santil@us.ibm.com>");
-MODULE_DESCRIPTION("IBM i/pSeries Virtual Ethernet Driver");
+MODULE_AUTHOR("Santiago Leon <santil@linux.vnet.ibm.com>");
+MODULE_DESCRIPTION("IBM Power Virtual Ethernet Driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(ibmveth_driver_version);
+static unsigned int tx_copybreak __read_mostly = 128;
+module_param(tx_copybreak, uint, 0644);
+MODULE_PARM_DESC(tx_copybreak,
+ "Maximum size of packet that is copied to a new buffer on transmit");
+
+static unsigned int rx_copybreak __read_mostly = 128;
+module_param(rx_copybreak, uint, 0644);
+MODULE_PARM_DESC(rx_copybreak,
+ "Maximum size of packet that is copied to a new buffer on receive");
+
+static unsigned int rx_flush __read_mostly = 0;
+module_param(rx_flush, uint, 0644);
+MODULE_PARM_DESC(rx_flush, "Flush receive buffers before use");
+
struct ibmveth_stat {
char name[ETH_GSTRING_LEN];
int offset;
@@ -128,12 +90,16 @@ struct ibmveth_stat {
struct ibmveth_stat ibmveth_stats[] = {
{ "replenish_task_cycles", IBMVETH_STAT_OFF(replenish_task_cycles) },
{ "replenish_no_mem", IBMVETH_STAT_OFF(replenish_no_mem) },
- { "replenish_add_buff_failure", IBMVETH_STAT_OFF(replenish_add_buff_failure) },
- { "replenish_add_buff_success", IBMVETH_STAT_OFF(replenish_add_buff_success) },
+ { "replenish_add_buff_failure",
+ IBMVETH_STAT_OFF(replenish_add_buff_failure) },
+ { "replenish_add_buff_success",
+ IBMVETH_STAT_OFF(replenish_add_buff_success) },
{ "rx_invalid_buffer", IBMVETH_STAT_OFF(rx_invalid_buffer) },
{ "rx_no_buffer", IBMVETH_STAT_OFF(rx_no_buffer) },
{ "tx_map_failed", IBMVETH_STAT_OFF(tx_map_failed) },
{ "tx_send_failed", IBMVETH_STAT_OFF(tx_send_failed) },
+ { "fw_enabled_ipv4_csum", IBMVETH_STAT_OFF(fw_ipv4_csum_support) },
+ { "fw_enabled_ipv6_csum", IBMVETH_STAT_OFF(fw_ipv6_csum_support) },
};
/* simple methods of getting data from the current rxq entry */
@@ -144,41 +110,44 @@ static inline u32 ibmveth_rxq_flags(struct ibmveth_adapter *adapter)
static inline int ibmveth_rxq_toggle(struct ibmveth_adapter *adapter)
{
- return (ibmveth_rxq_flags(adapter) & IBMVETH_RXQ_TOGGLE) >> IBMVETH_RXQ_TOGGLE_SHIFT;
+ return (ibmveth_rxq_flags(adapter) & IBMVETH_RXQ_TOGGLE) >>
+ IBMVETH_RXQ_TOGGLE_SHIFT;
}
static inline int ibmveth_rxq_pending_buffer(struct ibmveth_adapter *adapter)
{
- return (ibmveth_rxq_toggle(adapter) == adapter->rx_queue.toggle);
+ return ibmveth_rxq_toggle(adapter) == adapter->rx_queue.toggle;
}
static inline int ibmveth_rxq_buffer_valid(struct ibmveth_adapter *adapter)
{
- return (ibmveth_rxq_flags(adapter) & IBMVETH_RXQ_VALID);
+ return ibmveth_rxq_flags(adapter) & IBMVETH_RXQ_VALID;
}
static inline int ibmveth_rxq_frame_offset(struct ibmveth_adapter *adapter)
{
- return (ibmveth_rxq_flags(adapter) & IBMVETH_RXQ_OFF_MASK);
+ return ibmveth_rxq_flags(adapter) & IBMVETH_RXQ_OFF_MASK;
}
static inline int ibmveth_rxq_frame_length(struct ibmveth_adapter *adapter)
{
- return (adapter->rx_queue.queue_addr[adapter->rx_queue.index].length);
+ return adapter->rx_queue.queue_addr[adapter->rx_queue.index].length;
}
static inline int ibmveth_rxq_csum_good(struct ibmveth_adapter *adapter)
{
- return (ibmveth_rxq_flags(adapter) & IBMVETH_RXQ_CSUM_GOOD);
+ return ibmveth_rxq_flags(adapter) & IBMVETH_RXQ_CSUM_GOOD;
}
/* setup the initial settings for a buffer pool */
-static void ibmveth_init_buffer_pool(struct ibmveth_buff_pool *pool, u32 pool_index, u32 pool_size, u32 buff_size, u32 pool_active)
+static void ibmveth_init_buffer_pool(struct ibmveth_buff_pool *pool,
+ u32 pool_index, u32 pool_size,
+ u32 buff_size, u32 pool_active)
{
pool->size = pool_size;
pool->index = pool_index;
pool->buff_size = buff_size;
- pool->threshold = pool_size / 2;
+ pool->threshold = pool_size * 7 / 8;
pool->active = pool_active;
}
@@ -189,12 +158,11 @@ static int ibmveth_alloc_buffer_pool(struct ibmveth_buff_pool *pool)
pool->free_map = kmalloc(sizeof(u16) * pool->size, GFP_KERNEL);
- if(!pool->free_map) {
+ if (!pool->free_map)
return -1;
- }
pool->dma_addr = kmalloc(sizeof(dma_addr_t) * pool->size, GFP_KERNEL);
- if(!pool->dma_addr) {
+ if (!pool->dma_addr) {
kfree(pool->free_map);
pool->free_map = NULL;
return -1;
@@ -202,7 +170,7 @@ static int ibmveth_alloc_buffer_pool(struct ibmveth_buff_pool *pool)
pool->skbuff = kcalloc(pool->size, sizeof(void *), GFP_KERNEL);
- if(!pool->skbuff) {
+ if (!pool->skbuff) {
kfree(pool->dma_addr);
pool->dma_addr = NULL;
@@ -213,9 +181,8 @@ static int ibmveth_alloc_buffer_pool(struct ibmveth_buff_pool *pool)
memset(pool->dma_addr, 0, sizeof(dma_addr_t) * pool->size);
- for(i = 0; i < pool->size; ++i) {
+ for (i = 0; i < pool->size; ++i)
pool->free_map[i] = i;
- }
atomic_set(&pool->available, 0);
pool->producer_index = 0;
@@ -224,10 +191,19 @@ static int ibmveth_alloc_buffer_pool(struct ibmveth_buff_pool *pool)
return 0;
}
+static inline void ibmveth_flush_buffer(void *addr, unsigned long length)
+{
+ unsigned long offset;
+
+ for (offset = 0; offset < length; offset += SMP_CACHE_BYTES)
+ asm("dcbfl %0,%1" :: "b" (addr), "r" (offset));
+}
+
/* replenish the buffers for a pool. note that we don't need to
* skb_reserve these since they are used for incoming...
*/
-static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struct ibmveth_buff_pool *pool)
+static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter,
+ struct ibmveth_buff_pool *pool)
{
u32 i;
u32 count = pool->size - atomic_read(&pool->available);
@@ -240,23 +216,26 @@ static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struc
mb();
- for(i = 0; i < count; ++i) {
+ for (i = 0; i < count; ++i) {
union ibmveth_buf_desc desc;
- skb = alloc_skb(pool->buff_size, GFP_ATOMIC);
+ skb = netdev_alloc_skb(adapter->netdev, pool->buff_size);
- if(!skb) {
- ibmveth_debug_printk("replenish: unable to allocate skb\n");
+ if (!skb) {
+ netdev_dbg(adapter->netdev,
+ "replenish: unable to allocate skb\n");
adapter->replenish_no_mem++;
break;
}
free_index = pool->consumer_index;
- pool->consumer_index = (pool->consumer_index + 1) % pool->size;
+ pool->consumer_index++;
+ if (pool->consumer_index >= pool->size)
+ pool->consumer_index = 0;
index = pool->free_map[free_index];
- ibmveth_assert(index != IBM_VETH_INVALID_MAP);
- ibmveth_assert(pool->skbuff[index] == NULL);
+ BUG_ON(index == IBM_VETH_INVALID_MAP);
+ BUG_ON(pool->skbuff[index] != NULL);
dma_addr = dma_map_single(&adapter->vdev->dev, skb->data,
pool->buff_size, DMA_FROM_DEVICE);
@@ -269,16 +248,23 @@ static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struc
pool->skbuff[index] = skb;
correlator = ((u64)pool->index << 32) | index;
- *(u64*)skb->data = correlator;
+ *(u64 *)skb->data = correlator;
desc.fields.flags_len = IBMVETH_BUF_VALID | pool->buff_size;
desc.fields.address = dma_addr;
- lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc);
+ if (rx_flush) {
+ unsigned int len = min(pool->buff_size,
+ adapter->netdev->mtu +
+ IBMVETH_BUFF_OH);
+ ibmveth_flush_buffer(skb->data, len);
+ }
+ lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address,
+ desc.desc);
- if (lpar_rc != H_SUCCESS)
+ if (lpar_rc != H_SUCCESS) {
goto failure;
- else {
+ } else {
buffers_added++;
adapter->replenish_add_buff_success++;
}
@@ -313,26 +299,31 @@ static void ibmveth_replenish_task(struct ibmveth_adapter *adapter)
adapter->replenish_task_cycles++;
- for (i = (IbmVethNumBufferPools - 1); i >= 0; i--)
- if(adapter->rx_buff_pool[i].active)
- ibmveth_replenish_buffer_pool(adapter,
- &adapter->rx_buff_pool[i]);
+ for (i = (IBMVETH_NUM_BUFF_POOLS - 1); i >= 0; i--) {
+ struct ibmveth_buff_pool *pool = &adapter->rx_buff_pool[i];
- adapter->rx_no_buffer = *(u64*)(((char*)adapter->buffer_list_addr) + 4096 - 8);
+ if (pool->active &&
+ (atomic_read(&pool->available) < pool->threshold))
+ ibmveth_replenish_buffer_pool(adapter, pool);
+ }
+
+ adapter->rx_no_buffer = *(u64 *)(((char*)adapter->buffer_list_addr) +
+ 4096 - 8);
}
/* empty and free ana buffer pool - also used to do cleanup in error paths */
-static void ibmveth_free_buffer_pool(struct ibmveth_adapter *adapter, struct ibmveth_buff_pool *pool)
+static void ibmveth_free_buffer_pool(struct ibmveth_adapter *adapter,
+ struct ibmveth_buff_pool *pool)
{
int i;
kfree(pool->free_map);
pool->free_map = NULL;
- if(pool->skbuff && pool->dma_addr) {
- for(i = 0; i < pool->size; ++i) {
+ if (pool->skbuff && pool->dma_addr) {
+ for (i = 0; i < pool->size; ++i) {
struct sk_buff *skb = pool->skbuff[i];
- if(skb) {
+ if (skb) {
dma_unmap_single(&adapter->vdev->dev,
pool->dma_addr[i],
pool->buff_size,
@@ -343,31 +334,32 @@ static void ibmveth_free_buffer_pool(struct ibmveth_adapter *adapter, struct ibm
}
}
- if(pool->dma_addr) {
+ if (pool->dma_addr) {
kfree(pool->dma_addr);
pool->dma_addr = NULL;
}
- if(pool->skbuff) {
+ if (pool->skbuff) {
kfree(pool->skbuff);
pool->skbuff = NULL;
}
}
/* remove a buffer from a pool */
-static void ibmveth_remove_buffer_from_pool(struct ibmveth_adapter *adapter, u64 correlator)
+static void ibmveth_remove_buffer_from_pool(struct ibmveth_adapter *adapter,
+ u64 correlator)
{
unsigned int pool = correlator >> 32;
unsigned int index = correlator & 0xffffffffUL;
unsigned int free_index;
struct sk_buff *skb;
- ibmveth_assert(pool < IbmVethNumBufferPools);
- ibmveth_assert(index < adapter->rx_buff_pool[pool].size);
+ BUG_ON(pool >= IBMVETH_NUM_BUFF_POOLS);
+ BUG_ON(index >= adapter->rx_buff_pool[pool].size);
skb = adapter->rx_buff_pool[pool].skbuff[index];
- ibmveth_assert(skb != NULL);
+ BUG_ON(skb == NULL);
adapter->rx_buff_pool[pool].skbuff[index] = NULL;
@@ -377,9 +369,10 @@ static void ibmveth_remove_buffer_from_pool(struct ibmveth_adapter *adapter, u64
DMA_FROM_DEVICE);
free_index = adapter->rx_buff_pool[pool].producer_index;
- adapter->rx_buff_pool[pool].producer_index
- = (adapter->rx_buff_pool[pool].producer_index + 1)
- % adapter->rx_buff_pool[pool].size;
+ adapter->rx_buff_pool[pool].producer_index++;
+ if (adapter->rx_buff_pool[pool].producer_index >=
+ adapter->rx_buff_pool[pool].size)
+ adapter->rx_buff_pool[pool].producer_index = 0;
adapter->rx_buff_pool[pool].free_map[free_index] = index;
mb();
@@ -394,8 +387,8 @@ static inline struct sk_buff *ibmveth_rxq_get_buffer(struct ibmveth_adapter *ada
unsigned int pool = correlator >> 32;
unsigned int index = correlator & 0xffffffffUL;
- ibmveth_assert(pool < IbmVethNumBufferPools);
- ibmveth_assert(index < adapter->rx_buff_pool[pool].size);
+ BUG_ON(pool >= IBMVETH_NUM_BUFF_POOLS);
+ BUG_ON(index >= adapter->rx_buff_pool[pool].size);
return adapter->rx_buff_pool[pool].skbuff[index];
}
@@ -410,10 +403,10 @@ static void ibmveth_rxq_recycle_buffer(struct ibmveth_adapter *adapter)
union ibmveth_buf_desc desc;
unsigned long lpar_rc;
- ibmveth_assert(pool < IbmVethNumBufferPools);
- ibmveth_assert(index < adapter->rx_buff_pool[pool].size);
+ BUG_ON(pool >= IBMVETH_NUM_BUFF_POOLS);
+ BUG_ON(index >= adapter->rx_buff_pool[pool].size);
- if(!adapter->rx_buff_pool[pool].active) {
+ if (!adapter->rx_buff_pool[pool].active) {
ibmveth_rxq_harvest_buffer(adapter);
ibmveth_free_buffer_pool(adapter, &adapter->rx_buff_pool[pool]);
return;
@@ -425,12 +418,13 @@ static void ibmveth_rxq_recycle_buffer(struct ibmveth_adapter *adapter)
lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc);
- if(lpar_rc != H_SUCCESS) {
- ibmveth_debug_printk("h_add_logical_lan_buffer failed during recycle rc=%ld", lpar_rc);
+ if (lpar_rc != H_SUCCESS) {
+ netdev_dbg(adapter->netdev, "h_add_logical_lan_buffer failed "
+ "during recycle rc=%ld", lpar_rc);
ibmveth_remove_buffer_from_pool(adapter, adapter->rx_queue.queue_addr[adapter->rx_queue.index].correlator);
}
- if(++adapter->rx_queue.index == adapter->rx_queue.num_slots) {
+ if (++adapter->rx_queue.index == adapter->rx_queue.num_slots) {
adapter->rx_queue.index = 0;
adapter->rx_queue.toggle = !adapter->rx_queue.toggle;
}
@@ -440,7 +434,7 @@ static void ibmveth_rxq_harvest_buffer(struct ibmveth_adapter *adapter)
{
ibmveth_remove_buffer_from_pool(adapter, adapter->rx_queue.queue_addr[adapter->rx_queue.index].correlator);
- if(++adapter->rx_queue.index == adapter->rx_queue.num_slots) {
+ if (++adapter->rx_queue.index == adapter->rx_queue.num_slots) {
adapter->rx_queue.index = 0;
adapter->rx_queue.toggle = !adapter->rx_queue.toggle;
}
@@ -451,7 +445,7 @@ static void ibmveth_cleanup(struct ibmveth_adapter *adapter)
int i;
struct device *dev = &adapter->vdev->dev;
- if(adapter->buffer_list_addr != NULL) {
+ if (adapter->buffer_list_addr != NULL) {
if (!dma_mapping_error(dev, adapter->buffer_list_dma)) {
dma_unmap_single(dev, adapter->buffer_list_dma, 4096,
DMA_BIDIRECTIONAL);
@@ -461,7 +455,7 @@ static void ibmveth_cleanup(struct ibmveth_adapter *adapter)
adapter->buffer_list_addr = NULL;
}
- if(adapter->filter_list_addr != NULL) {
+ if (adapter->filter_list_addr != NULL) {
if (!dma_mapping_error(dev, adapter->filter_list_dma)) {
dma_unmap_single(dev, adapter->filter_list_dma, 4096,
DMA_BIDIRECTIONAL);
@@ -471,7 +465,7 @@ static void ibmveth_cleanup(struct ibmveth_adapter *adapter)
adapter->filter_list_addr = NULL;
}
- if(adapter->rx_queue.queue_addr != NULL) {
+ if (adapter->rx_queue.queue_addr != NULL) {
if (!dma_mapping_error(dev, adapter->rx_queue.queue_dma)) {
dma_unmap_single(dev,
adapter->rx_queue.queue_dma,
@@ -483,7 +477,7 @@ static void ibmveth_cleanup(struct ibmveth_adapter *adapter)
adapter->rx_queue.queue_addr = NULL;
}
- for(i = 0; i<IbmVethNumBufferPools; i++)
+ for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++)
if (adapter->rx_buff_pool[i].active)
ibmveth_free_buffer_pool(adapter,
&adapter->rx_buff_pool[i]);
@@ -506,9 +500,11 @@ static int ibmveth_register_logical_lan(struct ibmveth_adapter *adapter,
{
int rc, try_again = 1;
- /* After a kexec the adapter will still be open, so our attempt to
- * open it will fail. So if we get a failure we free the adapter and
- * try again, but only once. */
+ /*
+ * After a kexec the adapter will still be open, so our attempt to
+ * open it will fail. So if we get a failure we free the adapter and
+ * try again, but only once.
+ */
retry:
rc = h_register_logical_lan(adapter->vdev->unit_address,
adapter->buffer_list_dma, rxq_desc.desc,
@@ -537,31 +533,32 @@ static int ibmveth_open(struct net_device *netdev)
int i;
struct device *dev;
- ibmveth_debug_printk("open starting\n");
+ netdev_dbg(netdev, "open starting\n");
napi_enable(&adapter->napi);
- for(i = 0; i<IbmVethNumBufferPools; i++)
+ for(i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++)
rxq_entries += adapter->rx_buff_pool[i].size;
adapter->buffer_list_addr = (void*) get_zeroed_page(GFP_KERNEL);
adapter->filter_list_addr = (void*) get_zeroed_page(GFP_KERNEL);
- if(!adapter->buffer_list_addr || !adapter->filter_list_addr) {
- ibmveth_error_printk("unable to allocate filter or buffer list pages\n");
- ibmveth_cleanup(adapter);
- napi_disable(&adapter->napi);
- return -ENOMEM;
+ if (!adapter->buffer_list_addr || !adapter->filter_list_addr) {
+ netdev_err(netdev, "unable to allocate filter or buffer list "
+ "pages\n");
+ rc = -ENOMEM;
+ goto err_out;
}
- adapter->rx_queue.queue_len = sizeof(struct ibmveth_rx_q_entry) * rxq_entries;
- adapter->rx_queue.queue_addr = kmalloc(adapter->rx_queue.queue_len, GFP_KERNEL);
+ adapter->rx_queue.queue_len = sizeof(struct ibmveth_rx_q_entry) *
+ rxq_entries;
+ adapter->rx_queue.queue_addr = kmalloc(adapter->rx_queue.queue_len,
+ GFP_KERNEL);
- if(!adapter->rx_queue.queue_addr) {
- ibmveth_error_printk("unable to allocate rx queue pages\n");
- ibmveth_cleanup(adapter);
- napi_disable(&adapter->napi);
- return -ENOMEM;
+ if (!adapter->rx_queue.queue_addr) {
+ netdev_err(netdev, "unable to allocate rx queue pages\n");
+ rc = -ENOMEM;
+ goto err_out;
}
dev = &adapter->vdev->dev;
@@ -577,10 +574,10 @@ static int ibmveth_open(struct net_device *netdev)
if ((dma_mapping_error(dev, adapter->buffer_list_dma)) ||
(dma_mapping_error(dev, adapter->filter_list_dma)) ||
(dma_mapping_error(dev, adapter->rx_queue.queue_dma))) {
- ibmveth_error_printk("unable to map filter or buffer list pages\n");
- ibmveth_cleanup(adapter);
- napi_disable(&adapter->napi);
- return -ENOMEM;
+ netdev_err(netdev, "unable to map filter or buffer list "
+ "pages\n");
+ rc = -ENOMEM;
+ goto err_out;
}
adapter->rx_queue.index = 0;
@@ -590,79 +587,86 @@ static int ibmveth_open(struct net_device *netdev)
memcpy(&mac_address, netdev->dev_addr, netdev->addr_len);
mac_address = mac_address >> 16;
- rxq_desc.fields.flags_len = IBMVETH_BUF_VALID | adapter->rx_queue.queue_len;
+ rxq_desc.fields.flags_len = IBMVETH_BUF_VALID |
+ adapter->rx_queue.queue_len;
rxq_desc.fields.address = adapter->rx_queue.queue_dma;
- ibmveth_debug_printk("buffer list @ 0x%p\n", adapter->buffer_list_addr);
- ibmveth_debug_printk("filter list @ 0x%p\n", adapter->filter_list_addr);
- ibmveth_debug_printk("receive q @ 0x%p\n", adapter->rx_queue.queue_addr);
+ netdev_dbg(netdev, "buffer list @ 0x%p\n", adapter->buffer_list_addr);
+ netdev_dbg(netdev, "filter list @ 0x%p\n", adapter->filter_list_addr);
+ netdev_dbg(netdev, "receive q @ 0x%p\n", adapter->rx_queue.queue_addr);
h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_DISABLE);
lpar_rc = ibmveth_register_logical_lan(adapter, rxq_desc, mac_address);
- if(lpar_rc != H_SUCCESS) {
- ibmveth_error_printk("h_register_logical_lan failed with %ld\n", lpar_rc);
- ibmveth_error_printk("buffer TCE:0x%llx filter TCE:0x%llx rxq desc:0x%llx MAC:0x%llx\n",
+ if (lpar_rc != H_SUCCESS) {
+ netdev_err(netdev, "h_register_logical_lan failed with %ld\n",
+ lpar_rc);
+ netdev_err(netdev, "buffer TCE:0x%llx filter TCE:0x%llx rxq "
+ "desc:0x%llx MAC:0x%llx\n",
adapter->buffer_list_dma,
adapter->filter_list_dma,
rxq_desc.desc,
mac_address);
- ibmveth_cleanup(adapter);
- napi_disable(&adapter->napi);
- return -ENONET;
+ rc = -ENONET;
+ goto err_out;
}
- for(i = 0; i<IbmVethNumBufferPools; i++) {
- if(!adapter->rx_buff_pool[i].active)
+ for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++) {
+ if (!adapter->rx_buff_pool[i].active)
continue;
if (ibmveth_alloc_buffer_pool(&adapter->rx_buff_pool[i])) {
- ibmveth_error_printk("unable to alloc pool\n");
+ netdev_err(netdev, "unable to alloc pool\n");
adapter->rx_buff_pool[i].active = 0;
- ibmveth_cleanup(adapter);
- napi_disable(&adapter->napi);
- return -ENOMEM ;
+ rc = -ENOMEM;
+ goto err_out;
}
}
- ibmveth_debug_printk("registering irq 0x%x\n", netdev->irq);
- if((rc = request_irq(netdev->irq, ibmveth_interrupt, 0, netdev->name, netdev)) != 0) {
- ibmveth_error_printk("unable to request irq 0x%x, rc %d\n", netdev->irq, rc);
+ netdev_dbg(netdev, "registering irq 0x%x\n", netdev->irq);
+ rc = request_irq(netdev->irq, ibmveth_interrupt, 0, netdev->name,
+ netdev);
+ if (rc != 0) {
+ netdev_err(netdev, "unable to request irq 0x%x, rc %d\n",
+ netdev->irq, rc);
do {
rc = h_free_logical_lan(adapter->vdev->unit_address);
} while (H_IS_LONG_BUSY(rc) || (rc == H_BUSY));
- ibmveth_cleanup(adapter);
- napi_disable(&adapter->napi);
- return rc;
+ goto err_out;
}
adapter->bounce_buffer =
kmalloc(netdev->mtu + IBMVETH_BUFF_OH, GFP_KERNEL);
if (!adapter->bounce_buffer) {
- ibmveth_error_printk("unable to allocate bounce buffer\n");
- ibmveth_cleanup(adapter);
- napi_disable(&adapter->napi);
- return -ENOMEM;
+ netdev_err(netdev, "unable to allocate bounce buffer\n");
+ rc = -ENOMEM;
+ goto err_out_free_irq;
}
adapter->bounce_buffer_dma =
dma_map_single(&adapter->vdev->dev, adapter->bounce_buffer,
netdev->mtu + IBMVETH_BUFF_OH, DMA_BIDIRECTIONAL);
if (dma_mapping_error(dev, adapter->bounce_buffer_dma)) {
- ibmveth_error_printk("unable to map bounce buffer\n");
- ibmveth_cleanup(adapter);
- napi_disable(&adapter->napi);
- return -ENOMEM;
+ netdev_err(netdev, "unable to map bounce buffer\n");
+ rc = -ENOMEM;
+ goto err_out_free_irq;
}
- ibmveth_debug_printk("initial replenish cycle\n");
+ netdev_dbg(netdev, "initial replenish cycle\n");
ibmveth_interrupt(netdev->irq, netdev);
netif_start_queue(netdev);
- ibmveth_debug_printk("open complete\n");
+ netdev_dbg(netdev, "open complete\n");
return 0;
+
+err_out_free_irq:
+ free_irq(netdev->irq, netdev);
+err_out:
+ ibmveth_cleanup(adapter);
+ napi_disable(&adapter->napi);
+ return rc;
}
static int ibmveth_close(struct net_device *netdev)
@@ -670,7 +674,7 @@ static int ibmveth_close(struct net_device *netdev)
struct ibmveth_adapter *adapter = netdev_priv(netdev);
long lpar_rc;
- ibmveth_debug_printk("close starting\n");
+ netdev_dbg(netdev, "close starting\n");
napi_disable(&adapter->napi);
@@ -683,26 +687,29 @@ static int ibmveth_close(struct net_device *netdev)
lpar_rc = h_free_logical_lan(adapter->vdev->unit_address);
} while (H_IS_LONG_BUSY(lpar_rc) || (lpar_rc == H_BUSY));
- if(lpar_rc != H_SUCCESS)
- {
- ibmveth_error_printk("h_free_logical_lan failed with %lx, continuing with close\n",
- lpar_rc);
+ if (lpar_rc != H_SUCCESS) {
+ netdev_err(netdev, "h_free_logical_lan failed with %lx, "
+ "continuing with close\n", lpar_rc);
}
free_irq(netdev->irq, netdev);
- adapter->rx_no_buffer = *(u64*)(((char*)adapter->buffer_list_addr) + 4096 - 8);
+ adapter->rx_no_buffer = *(u64 *)(((char *)adapter->buffer_list_addr) +
+ 4096 - 8);
ibmveth_cleanup(adapter);
- ibmveth_debug_printk("close complete\n");
+ netdev_dbg(netdev, "close complete\n");
return 0;
}
-static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) {
- cmd->supported = (SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE);
- cmd->advertising = (ADVERTISED_1000baseT_Full | ADVERTISED_Autoneg | ADVERTISED_FIBRE);
+static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ cmd->supported = (SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg |
+ SUPPORTED_FIBRE);
+ cmd->advertising = (ADVERTISED_1000baseT_Full | ADVERTISED_Autoneg |
+ ADVERTISED_FIBRE);
cmd->speed = SPEED_1000;
cmd->duplex = DUPLEX_FULL;
cmd->port = PORT_FIBRE;
@@ -714,12 +721,16 @@ static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
return 0;
}
-static void netdev_get_drvinfo (struct net_device *dev, struct ethtool_drvinfo *info) {
+static void netdev_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *info)
+{
strncpy(info->driver, ibmveth_driver_name, sizeof(info->driver) - 1);
- strncpy(info->version, ibmveth_driver_version, sizeof(info->version) - 1);
+ strncpy(info->version, ibmveth_driver_version,
+ sizeof(info->version) - 1);
}
-static u32 netdev_get_link(struct net_device *dev) {
+static u32 netdev_get_link(struct net_device *dev)
+{
return 1;
}
@@ -727,18 +738,20 @@ static void ibmveth_set_rx_csum_flags(struct net_device *dev, u32 data)
{
struct ibmveth_adapter *adapter = netdev_priv(dev);
- if (data)
+ if (data) {
adapter->rx_csum = 1;
- else {
+ } else {
/*
- * Since the ibmveth firmware interface does not have the concept of
- * separate tx/rx checksum offload enable, if rx checksum is disabled
- * we also have to disable tx checksum offload. Once we disable rx
- * checksum offload, we are no longer allowed to send tx buffers that
- * are not properly checksummed.
+ * Since the ibmveth firmware interface does not have the
+ * concept of separate tx/rx checksum offload enable, if rx
+ * checksum is disabled we also have to disable tx checksum
+ * offload. Once we disable rx checksum offload, we are no
+ * longer allowed to send tx buffers that are not properly
+ * checksummed.
*/
adapter->rx_csum = 0;
dev->features &= ~NETIF_F_IP_CSUM;
+ dev->features &= ~NETIF_F_IPV6_CSUM;
}
}
@@ -747,10 +760,15 @@ static void ibmveth_set_tx_csum_flags(struct net_device *dev, u32 data)
struct ibmveth_adapter *adapter = netdev_priv(dev);
if (data) {
- dev->features |= NETIF_F_IP_CSUM;
+ if (adapter->fw_ipv4_csum_support)
+ dev->features |= NETIF_F_IP_CSUM;
+ if (adapter->fw_ipv6_csum_support)
+ dev->features |= NETIF_F_IPV6_CSUM;
adapter->rx_csum = 1;
- } else
+ } else {
dev->features &= ~NETIF_F_IP_CSUM;
+ dev->features &= ~NETIF_F_IPV6_CSUM;
+ }
}
static int ibmveth_set_csum_offload(struct net_device *dev, u32 data,
@@ -758,7 +776,8 @@ static int ibmveth_set_csum_offload(struct net_device *dev, u32 data,
{
struct ibmveth_adapter *adapter = netdev_priv(dev);
unsigned long set_attr, clr_attr, ret_attr;
- long ret;
+ unsigned long set_attr6, clr_attr6;
+ long ret, ret6;
int rc1 = 0, rc2 = 0;
int restart = 0;
@@ -772,10 +791,13 @@ static int ibmveth_set_csum_offload(struct net_device *dev, u32 data,
set_attr = 0;
clr_attr = 0;
- if (data)
+ if (data) {
set_attr = IBMVETH_ILLAN_IPV4_TCP_CSUM;
- else
+ set_attr6 = IBMVETH_ILLAN_IPV6_TCP_CSUM;
+ } else {
clr_attr = IBMVETH_ILLAN_IPV4_TCP_CSUM;
+ clr_attr6 = IBMVETH_ILLAN_IPV6_TCP_CSUM;
+ }
ret = h_illan_attributes(adapter->vdev->unit_address, 0, 0, &ret_attr);
@@ -786,18 +808,39 @@ static int ibmveth_set_csum_offload(struct net_device *dev, u32 data,
set_attr, &ret_attr);
if (ret != H_SUCCESS) {
- rc1 = -EIO;
- ibmveth_error_printk("unable to change checksum offload settings."
- " %d rc=%ld\n", data, ret);
+ netdev_err(dev, "unable to change IPv4 checksum "
+ "offload settings. %d rc=%ld\n",
+ data, ret);
ret = h_illan_attributes(adapter->vdev->unit_address,
set_attr, clr_attr, &ret_attr);
+ } else {
+ adapter->fw_ipv4_csum_support = data;
+ }
+
+ ret6 = h_illan_attributes(adapter->vdev->unit_address,
+ clr_attr6, set_attr6, &ret_attr);
+
+ if (ret6 != H_SUCCESS) {
+ netdev_err(dev, "unable to change IPv6 checksum "
+ "offload settings. %d rc=%ld\n",
+ data, ret);
+
+ ret = h_illan_attributes(adapter->vdev->unit_address,
+ set_attr6, clr_attr6,
+ &ret_attr);
} else
+ adapter->fw_ipv6_csum_support = data;
+
+ if (ret == H_SUCCESS || ret6 == H_SUCCESS)
done(dev, data);
+ else
+ rc1 = -EIO;
} else {
rc1 = -EIO;
- ibmveth_error_printk("unable to change checksum offload settings."
- " %d rc=%ld ret_attr=%lx\n", data, ret, ret_attr);
+ netdev_err(dev, "unable to change checksum offload settings."
+ " %d rc=%ld ret_attr=%lx\n", data, ret,
+ ret_attr);
}
if (restart)
@@ -821,13 +864,14 @@ static int ibmveth_set_tx_csum(struct net_device *dev, u32 data)
struct ibmveth_adapter *adapter = netdev_priv(dev);
int rc = 0;
- if (data && (dev->features & NETIF_F_IP_CSUM))
+ if (data && (dev->features & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM)))
return 0;
- if (!data && !(dev->features & NETIF_F_IP_CSUM))
+ if (!data && !(dev->features & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM)))
return 0;
if (data && !adapter->rx_csum)
- rc = ibmveth_set_csum_offload(dev, data, ibmveth_set_tx_csum_flags);
+ rc = ibmveth_set_csum_offload(dev, data,
+ ibmveth_set_tx_csum_flags);
else
ibmveth_set_tx_csum_flags(dev, data);
@@ -881,6 +925,7 @@ static const struct ethtool_ops netdev_ethtool_ops = {
.get_strings = ibmveth_get_strings,
.get_sset_count = ibmveth_get_sset_count,
.get_ethtool_stats = ibmveth_get_ethtool_stats,
+ .set_sg = ethtool_op_set_sg,
};
static int ibmveth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
@@ -890,129 +935,216 @@ static int ibmveth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
#define page_offset(v) ((unsigned long)(v) & ((1 << 12) - 1))
-static netdev_tx_t ibmveth_start_xmit(struct sk_buff *skb,
- struct net_device *netdev)
+static int ibmveth_send(struct ibmveth_adapter *adapter,
+ union ibmveth_buf_desc *descs)
{
- struct ibmveth_adapter *adapter = netdev_priv(netdev);
- union ibmveth_buf_desc desc;
- unsigned long lpar_rc;
unsigned long correlator;
- unsigned long flags;
unsigned int retry_count;
- unsigned int tx_dropped = 0;
- unsigned int tx_bytes = 0;
- unsigned int tx_packets = 0;
- unsigned int tx_send_failed = 0;
- unsigned int tx_map_failed = 0;
- int used_bounce = 0;
- unsigned long data_dma_addr;
+ unsigned long ret;
- desc.fields.flags_len = IBMVETH_BUF_VALID | skb->len;
+ /*
+ * The retry count sets a maximum for the number of broadcast and
+ * multicast destinations within the system.
+ */
+ retry_count = 1024;
+ correlator = 0;
+ do {
+ ret = h_send_logical_lan(adapter->vdev->unit_address,
+ descs[0].desc, descs[1].desc,
+ descs[2].desc, descs[3].desc,
+ descs[4].desc, descs[5].desc,
+ correlator, &correlator);
+ } while ((ret == H_BUSY) && (retry_count--));
+ if (ret != H_SUCCESS && ret != H_DROPPED) {
+ netdev_err(adapter->netdev, "tx: h_send_logical_lan failed "
+ "with rc=%ld\n", ret);
+ return 1;
+ }
+
+ return 0;
+}
+
+static netdev_tx_t ibmveth_start_xmit(struct sk_buff *skb,
+ struct net_device *netdev)
+{
+ struct ibmveth_adapter *adapter = netdev_priv(netdev);
+ unsigned int desc_flags;
+ union ibmveth_buf_desc descs[6];
+ int last, i;
+ int force_bounce = 0;
+
+ /*
+ * veth handles a maximum of 6 segments including the header, so
+ * we have to linearize the skb if there are more than this.
+ */
+ if (skb_shinfo(skb)->nr_frags > 5 && __skb_linearize(skb)) {
+ netdev->stats.tx_dropped++;
+ goto out;
+ }
+
+ /* veth can't checksum offload UDP */
if (skb->ip_summed == CHECKSUM_PARTIAL &&
- ip_hdr(skb)->protocol != IPPROTO_TCP && skb_checksum_help(skb)) {
- ibmveth_error_printk("tx: failed to checksum packet\n");
- tx_dropped++;
+ ((skb->protocol == htons(ETH_P_IP) &&
+ ip_hdr(skb)->protocol != IPPROTO_TCP) ||
+ (skb->protocol == htons(ETH_P_IPV6) &&
+ ipv6_hdr(skb)->nexthdr != IPPROTO_TCP)) &&
+ skb_checksum_help(skb)) {
+
+ netdev_err(netdev, "tx: failed to checksum packet\n");
+ netdev->stats.tx_dropped++;
goto out;
}
+ desc_flags = IBMVETH_BUF_VALID;
+
if (skb->ip_summed == CHECKSUM_PARTIAL) {
- unsigned char *buf = skb_transport_header(skb) + skb->csum_offset;
+ unsigned char *buf = skb_transport_header(skb) +
+ skb->csum_offset;
- desc.fields.flags_len |= (IBMVETH_BUF_NO_CSUM | IBMVETH_BUF_CSUM_GOOD);
+ desc_flags |= (IBMVETH_BUF_NO_CSUM | IBMVETH_BUF_CSUM_GOOD);
/* Need to zero out the checksum */
buf[0] = 0;
buf[1] = 0;
}
- data_dma_addr = dma_map_single(&adapter->vdev->dev, skb->data,
- skb->len, DMA_TO_DEVICE);
- if (dma_mapping_error(&adapter->vdev->dev, data_dma_addr)) {
- if (!firmware_has_feature(FW_FEATURE_CMO))
- ibmveth_error_printk("tx: unable to map xmit buffer\n");
+retry_bounce:
+ memset(descs, 0, sizeof(descs));
+
+ /*
+ * If a linear packet is below the rx threshold then
+ * copy it into the static bounce buffer. This avoids the
+ * cost of a TCE insert and remove.
+ */
+ if (force_bounce || (!skb_is_nonlinear(skb) &&
+ (skb->len < tx_copybreak))) {
skb_copy_from_linear_data(skb, adapter->bounce_buffer,
skb->len);
- desc.fields.address = adapter->bounce_buffer_dma;
- tx_map_failed++;
- used_bounce = 1;
- wmb();
- } else
- desc.fields.address = data_dma_addr;
-
- /* send the frame. Arbitrarily set retrycount to 1024 */
- correlator = 0;
- retry_count = 1024;
- do {
- lpar_rc = h_send_logical_lan(adapter->vdev->unit_address,
- desc.desc, 0, 0, 0, 0, 0,
- correlator, &correlator);
- } while ((lpar_rc == H_BUSY) && (retry_count--));
-
- if(lpar_rc != H_SUCCESS && lpar_rc != H_DROPPED) {
- ibmveth_error_printk("tx: h_send_logical_lan failed with rc=%ld\n", lpar_rc);
- ibmveth_error_printk("tx: valid=%d, len=%d, address=0x%08x\n",
- (desc.fields.flags_len & IBMVETH_BUF_VALID) ? 1 : 0,
- skb->len, desc.fields.address);
- tx_send_failed++;
- tx_dropped++;
- } else {
- tx_packets++;
- tx_bytes += skb->len;
- netdev->trans_start = jiffies; /* NETIF_F_LLTX driver :( */
+
+ descs[0].fields.flags_len = desc_flags | skb->len;
+ descs[0].fields.address = adapter->bounce_buffer_dma;
+
+ if (ibmveth_send(adapter, descs)) {
+ adapter->tx_send_failed++;
+ netdev->stats.tx_dropped++;
+ } else {
+ netdev->stats.tx_packets++;
+ netdev->stats.tx_bytes += skb->len;
+ }
+
+ goto out;
+ }
+
+ /* Map the header */
+ descs[0].fields.address = dma_map_single(&adapter->vdev->dev, skb->data,
+ skb_headlen(skb),
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(&adapter->vdev->dev, descs[0].fields.address))
+ goto map_failed;
+
+ descs[0].fields.flags_len = desc_flags | skb_headlen(skb);
+
+ /* Map the frags */
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+ unsigned long dma_addr;
+ skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+
+ dma_addr = dma_map_page(&adapter->vdev->dev, frag->page,
+ frag->page_offset, frag->size,
+ DMA_TO_DEVICE);
+
+ if (dma_mapping_error(&adapter->vdev->dev, dma_addr))
+ goto map_failed_frags;
+
+ descs[i+1].fields.flags_len = desc_flags | frag->size;
+ descs[i+1].fields.address = dma_addr;
}
- if (!used_bounce)
- dma_unmap_single(&adapter->vdev->dev, data_dma_addr,
- skb->len, DMA_TO_DEVICE);
+ if (ibmveth_send(adapter, descs)) {
+ adapter->tx_send_failed++;
+ netdev->stats.tx_dropped++;
+ } else {
+ netdev->stats.tx_packets++;
+ netdev->stats.tx_bytes += skb->len;
+ }
-out: spin_lock_irqsave(&adapter->stats_lock, flags);
- netdev->stats.tx_dropped += tx_dropped;
- netdev->stats.tx_bytes += tx_bytes;
- netdev->stats.tx_packets += tx_packets;
- adapter->tx_send_failed += tx_send_failed;
- adapter->tx_map_failed += tx_map_failed;
- spin_unlock_irqrestore(&adapter->stats_lock, flags);
+ for (i = 0; i < skb_shinfo(skb)->nr_frags + 1; i++)
+ dma_unmap_page(&adapter->vdev->dev, descs[i].fields.address,
+ descs[i].fields.flags_len & IBMVETH_BUF_LEN_MASK,
+ DMA_TO_DEVICE);
+out:
dev_kfree_skb(skb);
return NETDEV_TX_OK;
+
+map_failed_frags:
+ last = i+1;
+ for (i = 0; i < last; i++)
+ dma_unmap_page(&adapter->vdev->dev, descs[i].fields.address,
+ descs[i].fields.flags_len & IBMVETH_BUF_LEN_MASK,
+ DMA_TO_DEVICE);
+
+map_failed:
+ if (!firmware_has_feature(FW_FEATURE_CMO))
+ netdev_err(netdev, "tx: unable to map xmit buffer\n");
+ adapter->tx_map_failed++;
+ skb_linearize(skb);
+ force_bounce = 1;
+ goto retry_bounce;
}
static int ibmveth_poll(struct napi_struct *napi, int budget)
{
- struct ibmveth_adapter *adapter = container_of(napi, struct ibmveth_adapter, napi);
+ struct ibmveth_adapter *adapter =
+ container_of(napi, struct ibmveth_adapter, napi);
struct net_device *netdev = adapter->netdev;
int frames_processed = 0;
unsigned long lpar_rc;
- restart_poll:
+restart_poll:
do {
- struct sk_buff *skb;
-
if (!ibmveth_rxq_pending_buffer(adapter))
break;
- rmb();
+ smp_rmb();
if (!ibmveth_rxq_buffer_valid(adapter)) {
wmb(); /* suggested by larson1 */
adapter->rx_invalid_buffer++;
- ibmveth_debug_printk("recycling invalid buffer\n");
+ netdev_dbg(netdev, "recycling invalid buffer\n");
ibmveth_rxq_recycle_buffer(adapter);
} else {
+ struct sk_buff *skb, *new_skb;
int length = ibmveth_rxq_frame_length(adapter);
int offset = ibmveth_rxq_frame_offset(adapter);
int csum_good = ibmveth_rxq_csum_good(adapter);
skb = ibmveth_rxq_get_buffer(adapter);
- if (csum_good)
- skb->ip_summed = CHECKSUM_UNNECESSARY;
- ibmveth_rxq_harvest_buffer(adapter);
+ new_skb = NULL;
+ if (length < rx_copybreak)
+ new_skb = netdev_alloc_skb(netdev, length);
+
+ if (new_skb) {
+ skb_copy_to_linear_data(new_skb,
+ skb->data + offset,
+ length);
+ if (rx_flush)
+ ibmveth_flush_buffer(skb->data,
+ length + offset);
+ skb = new_skb;
+ ibmveth_rxq_recycle_buffer(adapter);
+ } else {
+ ibmveth_rxq_harvest_buffer(adapter);
+ skb_reserve(skb, offset);
+ }
- skb_reserve(skb, offset);
skb_put(skb, length);
skb->protocol = eth_type_trans(skb, netdev);
+ if (csum_good)
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+
netif_receive_skb(skb); /* send it up */
netdev->stats.rx_packets++;
@@ -1030,7 +1162,7 @@ static int ibmveth_poll(struct napi_struct *napi, int budget)
lpar_rc = h_vio_signal(adapter->vdev->unit_address,
VIO_IRQ_ENABLE);
- ibmveth_assert(lpar_rc == H_SUCCESS);
+ BUG_ON(lpar_rc != H_SUCCESS);
napi_complete(napi);
@@ -1054,7 +1186,7 @@ static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance)
if (napi_schedule_prep(&adapter->napi)) {
lpar_rc = h_vio_signal(adapter->vdev->unit_address,
VIO_IRQ_DISABLE);
- ibmveth_assert(lpar_rc == H_SUCCESS);
+ BUG_ON(lpar_rc != H_SUCCESS);
__napi_schedule(&adapter->napi);
}
return IRQ_HANDLED;
@@ -1071,8 +1203,9 @@ static void ibmveth_set_multicast_list(struct net_device *netdev)
IbmVethMcastEnableRecv |
IbmVethMcastDisableFiltering,
0);
- if(lpar_rc != H_SUCCESS) {
- ibmveth_error_printk("h_multicast_ctrl rc=%ld when entering promisc mode\n", lpar_rc);
+ if (lpar_rc != H_SUCCESS) {
+ netdev_err(netdev, "h_multicast_ctrl rc=%ld when "
+ "entering promisc mode\n", lpar_rc);
}
} else {
struct netdev_hw_addr *ha;
@@ -1082,19 +1215,23 @@ static void ibmveth_set_multicast_list(struct net_device *netdev)
IbmVethMcastDisableFiltering |
IbmVethMcastClearFilterTable,
0);
- if(lpar_rc != H_SUCCESS) {
- ibmveth_error_printk("h_multicast_ctrl rc=%ld when attempting to clear filter table\n", lpar_rc);
+ if (lpar_rc != H_SUCCESS) {
+ netdev_err(netdev, "h_multicast_ctrl rc=%ld when "
+ "attempting to clear filter table\n",
+ lpar_rc);
}
/* add the addresses to the filter table */
netdev_for_each_mc_addr(ha, netdev) {
- // add the multicast address to the filter table
+ /* add the multicast address to the filter table */
unsigned long mcast_addr = 0;
memcpy(((char *)&mcast_addr)+2, ha->addr, 6);
lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address,
IbmVethMcastAddFilter,
mcast_addr);
- if(lpar_rc != H_SUCCESS) {
- ibmveth_error_printk("h_multicast_ctrl rc=%ld when adding an entry to the filter table\n", lpar_rc);
+ if (lpar_rc != H_SUCCESS) {
+ netdev_err(netdev, "h_multicast_ctrl rc=%ld "
+ "when adding an entry to the filter "
+ "table\n", lpar_rc);
}
}
@@ -1102,8 +1239,9 @@ static void ibmveth_set_multicast_list(struct net_device *netdev)
lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address,
IbmVethMcastEnableFiltering,
0);
- if(lpar_rc != H_SUCCESS) {
- ibmveth_error_printk("h_multicast_ctrl rc=%ld when enabling filtering\n", lpar_rc);
+ if (lpar_rc != H_SUCCESS) {
+ netdev_err(netdev, "h_multicast_ctrl rc=%ld when "
+ "enabling filtering\n", lpar_rc);
}
}
}
@@ -1116,14 +1254,14 @@ static int ibmveth_change_mtu(struct net_device *dev, int new_mtu)
int i, rc;
int need_restart = 0;
- if (new_mtu < IBMVETH_MAX_MTU)
+ if (new_mtu < IBMVETH_MIN_MTU)
return -EINVAL;
- for (i = 0; i < IbmVethNumBufferPools; i++)
+ for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++)
if (new_mtu_oh < adapter->rx_buff_pool[i].buff_size)
break;
- if (i == IbmVethNumBufferPools)
+ if (i == IBMVETH_NUM_BUFF_POOLS)
return -EINVAL;
/* Deactivate all the buffer pools so that the next loop can activate
@@ -1136,7 +1274,7 @@ static int ibmveth_change_mtu(struct net_device *dev, int new_mtu)
}
/* Look for an active buffer pool that can hold the new MTU */
- for(i = 0; i<IbmVethNumBufferPools; i++) {
+ for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++) {
adapter->rx_buff_pool[i].active = 1;
if (new_mtu_oh < adapter->rx_buff_pool[i].buff_size) {
@@ -1190,7 +1328,7 @@ static unsigned long ibmveth_get_desired_dma(struct vio_dev *vdev)
ret = IBMVETH_BUFF_LIST_SIZE + IBMVETH_FILT_LIST_SIZE;
ret += IOMMU_PAGE_ALIGN(netdev->mtu);
- for (i = 0; i < IbmVethNumBufferPools; i++) {
+ for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++) {
/* add the size of the active receive buffers */
if (adapter->rx_buff_pool[i].active)
ret +=
@@ -1219,41 +1357,36 @@ static const struct net_device_ops ibmveth_netdev_ops = {
#endif
};
-static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
+static int __devinit ibmveth_probe(struct vio_dev *dev,
+ const struct vio_device_id *id)
{
int rc, i;
- long ret;
struct net_device *netdev;
struct ibmveth_adapter *adapter;
- unsigned long set_attr, ret_attr;
-
unsigned char *mac_addr_p;
unsigned int *mcastFilterSize_p;
+ dev_dbg(&dev->dev, "entering ibmveth_probe for UA 0x%x\n",
+ dev->unit_address);
- ibmveth_debug_printk_no_adapter("entering ibmveth_probe for UA 0x%x\n",
- dev->unit_address);
-
- mac_addr_p = (unsigned char *) vio_get_attribute(dev,
- VETH_MAC_ADDR, NULL);
- if(!mac_addr_p) {
- printk(KERN_ERR "(%s:%3.3d) ERROR: Can't find VETH_MAC_ADDR "
- "attribute\n", __FILE__, __LINE__);
- return 0;
+ mac_addr_p = (unsigned char *)vio_get_attribute(dev, VETH_MAC_ADDR,
+ NULL);
+ if (!mac_addr_p) {
+ dev_err(&dev->dev, "Can't find VETH_MAC_ADDR attribute\n");
+ return -EINVAL;
}
- mcastFilterSize_p = (unsigned int *) vio_get_attribute(dev,
+ mcastFilterSize_p = (unsigned int *)vio_get_attribute(dev,
VETH_MCAST_FILTER_SIZE, NULL);
- if(!mcastFilterSize_p) {
- printk(KERN_ERR "(%s:%3.3d) ERROR: Can't find "
- "VETH_MCAST_FILTER_SIZE attribute\n",
- __FILE__, __LINE__);
- return 0;
+ if (!mcastFilterSize_p) {
+ dev_err(&dev->dev, "Can't find VETH_MCAST_FILTER_SIZE "
+ "attribute\n");
+ return -EINVAL;
}
netdev = alloc_etherdev(sizeof(struct ibmveth_adapter));
- if(!netdev)
+ if (!netdev)
return -ENOMEM;
adapter = netdev_priv(netdev);
@@ -1261,19 +1394,19 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_
adapter->vdev = dev;
adapter->netdev = netdev;
- adapter->mcastFilterSize= *mcastFilterSize_p;
+ adapter->mcastFilterSize = *mcastFilterSize_p;
adapter->pool_config = 0;
netif_napi_add(netdev, &adapter->napi, ibmveth_poll, 16);
- /* Some older boxes running PHYP non-natively have an OF that
- returns a 8-byte local-mac-address field (and the first
- 2 bytes have to be ignored) while newer boxes' OF return
- a 6-byte field. Note that IEEE 1275 specifies that
- local-mac-address must be a 6-byte field.
- The RPA doc specifies that the first byte must be 10b, so
- we'll just look for it to solve this 8 vs. 6 byte field issue */
-
+ /*
+ * Some older boxes running PHYP non-natively have an OF that returns
+ * a 8-byte local-mac-address field (and the first 2 bytes have to be
+ * ignored) while newer boxes' OF return a 6-byte field. Note that
+ * IEEE 1275 specifies that local-mac-address must be a 6-byte field.
+ * The RPA doc specifies that the first byte must be 10b, so we'll
+ * just look for it to solve this 8 vs. 6 byte field issue
+ */
if ((*mac_addr_p & 0x3) != 0x02)
mac_addr_p += 2;
@@ -1284,12 +1417,11 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_
netdev->netdev_ops = &ibmveth_netdev_ops;
netdev->ethtool_ops = &netdev_ethtool_ops;
SET_NETDEV_DEV(netdev, &dev->dev);
- netdev->features |= NETIF_F_LLTX;
- spin_lock_init(&adapter->stats_lock);
+ netdev->features |= NETIF_F_SG;
memcpy(netdev->dev_addr, &adapter->mac_addr, netdev->addr_len);
- for(i = 0; i<IbmVethNumBufferPools; i++) {
+ for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++) {
struct kobject *kobj = &adapter->rx_buff_pool[i].kobj;
int error;
@@ -1302,41 +1434,25 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_
kobject_uevent(kobj, KOBJ_ADD);
}
- ibmveth_debug_printk("adapter @ 0x%p\n", adapter);
+ netdev_dbg(netdev, "adapter @ 0x%p\n", adapter);
adapter->buffer_list_dma = DMA_ERROR_CODE;
adapter->filter_list_dma = DMA_ERROR_CODE;
adapter->rx_queue.queue_dma = DMA_ERROR_CODE;
- ibmveth_debug_printk("registering netdev...\n");
+ netdev_dbg(netdev, "registering netdev...\n");
- ret = h_illan_attributes(dev->unit_address, 0, 0, &ret_attr);
-
- if (ret == H_SUCCESS && !(ret_attr & IBMVETH_ILLAN_ACTIVE_TRUNK) &&
- !(ret_attr & IBMVETH_ILLAN_TRUNK_PRI_MASK) &&
- (ret_attr & IBMVETH_ILLAN_PADDED_PKT_CSUM)) {
- set_attr = IBMVETH_ILLAN_IPV4_TCP_CSUM;
-
- ret = h_illan_attributes(dev->unit_address, 0, set_attr, &ret_attr);
-
- if (ret == H_SUCCESS) {
- adapter->rx_csum = 1;
- netdev->features |= NETIF_F_IP_CSUM;
- } else
- ret = h_illan_attributes(dev->unit_address, set_attr, 0, &ret_attr);
- }
+ ibmveth_set_csum_offload(netdev, 1, ibmveth_set_tx_csum_flags);
rc = register_netdev(netdev);
- if(rc) {
- ibmveth_debug_printk("failed to register netdev rc=%d\n", rc);
+ if (rc) {
+ netdev_dbg(netdev, "failed to register netdev rc=%d\n", rc);
free_netdev(netdev);
return rc;
}
- ibmveth_debug_printk("registered\n");
-
- ibmveth_proc_register_adapter(adapter);
+ netdev_dbg(netdev, "registered\n");
return 0;
}
@@ -1347,114 +1463,23 @@ static int __devexit ibmveth_remove(struct vio_dev *dev)
struct ibmveth_adapter *adapter = netdev_priv(netdev);
int i;
- for(i = 0; i<IbmVethNumBufferPools; i++)
+ for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++)
kobject_put(&adapter->rx_buff_pool[i].kobj);
unregister_netdev(netdev);
- ibmveth_proc_unregister_adapter(adapter);
-
free_netdev(netdev);
dev_set_drvdata(&dev->dev, NULL);
return 0;
}
-#ifdef CONFIG_PROC_FS
-static void ibmveth_proc_register_driver(void)
-{
- ibmveth_proc_dir = proc_mkdir(IBMVETH_PROC_DIR, init_net.proc_net);
- if (ibmveth_proc_dir) {
- }
-}
-
-static void ibmveth_proc_unregister_driver(void)
-{
- remove_proc_entry(IBMVETH_PROC_DIR, init_net.proc_net);
-}
-
-static int ibmveth_show(struct seq_file *seq, void *v)
-{
- struct ibmveth_adapter *adapter = seq->private;
- char *current_mac = (char *) adapter->netdev->dev_addr;
- char *firmware_mac = (char *) &adapter->mac_addr;
-
- seq_printf(seq, "%s %s\n\n", ibmveth_driver_string, ibmveth_driver_version);
-
- seq_printf(seq, "Unit Address: 0x%x\n", adapter->vdev->unit_address);
- seq_printf(seq, "Current MAC: %pM\n", current_mac);
- seq_printf(seq, "Firmware MAC: %pM\n", firmware_mac);
-
- seq_printf(seq, "\nAdapter Statistics:\n");
- seq_printf(seq, " TX: vio_map_single failres: %lld\n", adapter->tx_map_failed);
- seq_printf(seq, " send failures: %lld\n", adapter->tx_send_failed);
- seq_printf(seq, " RX: replenish task cycles: %lld\n", adapter->replenish_task_cycles);
- seq_printf(seq, " alloc_skb_failures: %lld\n", adapter->replenish_no_mem);
- seq_printf(seq, " add buffer failures: %lld\n", adapter->replenish_add_buff_failure);
- seq_printf(seq, " invalid buffers: %lld\n", adapter->rx_invalid_buffer);
- seq_printf(seq, " no buffers: %lld\n", adapter->rx_no_buffer);
-
- return 0;
-}
-
-static int ibmveth_proc_open(struct inode *inode, struct file *file)
-{
- return single_open(file, ibmveth_show, PDE(inode)->data);
-}
-
-static const struct file_operations ibmveth_proc_fops = {
- .owner = THIS_MODULE,
- .open = ibmveth_proc_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter)
-{
- struct proc_dir_entry *entry;
- if (ibmveth_proc_dir) {
- char u_addr[10];
- sprintf(u_addr, "%x", adapter->vdev->unit_address);
- entry = proc_create_data(u_addr, S_IFREG, ibmveth_proc_dir,
- &ibmveth_proc_fops, adapter);
- if (!entry)
- ibmveth_error_printk("Cannot create adapter proc entry");
- }
-}
-
-static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter)
-{
- if (ibmveth_proc_dir) {
- char u_addr[10];
- sprintf(u_addr, "%x", adapter->vdev->unit_address);
- remove_proc_entry(u_addr, ibmveth_proc_dir);
- }
-}
-
-#else /* CONFIG_PROC_FS */
-static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter)
-{
-}
-
-static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter)
-{
-}
-static void ibmveth_proc_register_driver(void)
-{
-}
-
-static void ibmveth_proc_unregister_driver(void)
-{
-}
-#endif /* CONFIG_PROC_FS */
-
static struct attribute veth_active_attr;
static struct attribute veth_num_attr;
static struct attribute veth_size_attr;
-static ssize_t veth_pool_show(struct kobject * kobj,
- struct attribute * attr, char * buf)
+static ssize_t veth_pool_show(struct kobject *kobj,
+ struct attribute *attr, char *buf)
{
struct ibmveth_buff_pool *pool = container_of(kobj,
struct ibmveth_buff_pool,
@@ -1469,8 +1494,8 @@ static ssize_t veth_pool_show(struct kobject * kobj,
return 0;
}
-static ssize_t veth_pool_store(struct kobject * kobj, struct attribute * attr,
-const char * buf, size_t count)
+static ssize_t veth_pool_store(struct kobject *kobj, struct attribute *attr,
+ const char *buf, size_t count)
{
struct ibmveth_buff_pool *pool = container_of(kobj,
struct ibmveth_buff_pool,
@@ -1484,8 +1509,9 @@ const char * buf, size_t count)
if (attr == &veth_active_attr) {
if (value && !pool->active) {
if (netif_running(netdev)) {
- if(ibmveth_alloc_buffer_pool(pool)) {
- ibmveth_error_printk("unable to alloc pool\n");
+ if (ibmveth_alloc_buffer_pool(pool)) {
+ netdev_err(netdev,
+ "unable to alloc pool\n");
return -ENOMEM;
}
pool->active = 1;
@@ -1494,14 +1520,15 @@ const char * buf, size_t count)
adapter->pool_config = 0;
if ((rc = ibmveth_open(netdev)))
return rc;
- } else
+ } else {
pool->active = 1;
+ }
} else if (!value && pool->active) {
int mtu = netdev->mtu + IBMVETH_BUFF_OH;
int i;
/* Make sure there is a buffer pool with buffers that
can hold a packet of the size of the MTU */
- for (i = 0; i < IbmVethNumBufferPools; i++) {
+ for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++) {
if (pool == &adapter->rx_buff_pool[i])
continue;
if (!adapter->rx_buff_pool[i].active)
@@ -1510,8 +1537,8 @@ const char * buf, size_t count)
break;
}
- if (i == IbmVethNumBufferPools) {
- ibmveth_error_printk("no active pool >= MTU\n");
+ if (i == IBMVETH_NUM_BUFF_POOLS) {
+ netdev_err(netdev, "no active pool >= MTU\n");
return -EPERM;
}
@@ -1526,9 +1553,9 @@ const char * buf, size_t count)
pool->active = 0;
}
} else if (attr == &veth_num_attr) {
- if (value <= 0 || value > IBMVETH_MAX_POOL_COUNT)
+ if (value <= 0 || value > IBMVETH_MAX_POOL_COUNT) {
return -EINVAL;
- else {
+ } else {
if (netif_running(netdev)) {
adapter->pool_config = 1;
ibmveth_close(netdev);
@@ -1536,13 +1563,14 @@ const char * buf, size_t count)
pool->size = value;
if ((rc = ibmveth_open(netdev)))
return rc;
- } else
+ } else {
pool->size = value;
+ }
}
} else if (attr == &veth_size_attr) {
- if (value <= IBMVETH_BUFF_OH || value > IBMVETH_MAX_BUF_SIZE)
+ if (value <= IBMVETH_BUFF_OH || value > IBMVETH_MAX_BUF_SIZE) {
return -EINVAL;
- else {
+ } else {
if (netif_running(netdev)) {
adapter->pool_config = 1;
ibmveth_close(netdev);
@@ -1550,8 +1578,9 @@ const char * buf, size_t count)
pool->buff_size = value;
if ((rc = ibmveth_open(netdev)))
return rc;
- } else
+ } else {
pool->buff_size = value;
+ }
}
}
@@ -1561,16 +1590,16 @@ const char * buf, size_t count)
}
-#define ATTR(_name, _mode) \
- struct attribute veth_##_name##_attr = { \
- .name = __stringify(_name), .mode = _mode, \
- };
+#define ATTR(_name, _mode) \
+ struct attribute veth_##_name##_attr = { \
+ .name = __stringify(_name), .mode = _mode, \
+ };
static ATTR(active, 0644);
static ATTR(num, 0644);
static ATTR(size, 0644);
-static struct attribute * veth_pool_attrs[] = {
+static struct attribute *veth_pool_attrs[] = {
&veth_active_attr,
&veth_num_attr,
&veth_size_attr,
@@ -1595,7 +1624,7 @@ static int ibmveth_resume(struct device *dev)
return 0;
}
-static struct vio_device_id ibmveth_device_table[] __devinitdata= {
+static struct vio_device_id ibmveth_device_table[] __devinitdata = {
{ "network", "IBM,l-lan"},
{ "", "" }
};
@@ -1619,9 +1648,8 @@ static struct vio_driver ibmveth_driver = {
static int __init ibmveth_module_init(void)
{
- ibmveth_printk("%s: %s %s\n", ibmveth_driver_name, ibmveth_driver_string, ibmveth_driver_version);
-
- ibmveth_proc_register_driver();
+ printk(KERN_DEBUG "%s: %s %s\n", ibmveth_driver_name,
+ ibmveth_driver_string, ibmveth_driver_version);
return vio_register_driver(&ibmveth_driver);
}
@@ -1629,7 +1657,6 @@ static int __init ibmveth_module_init(void)
static void __exit ibmveth_module_exit(void)
{
vio_unregister_driver(&ibmveth_driver);
- ibmveth_proc_unregister_driver();
}
module_init(ibmveth_module_init);
diff --git a/drivers/net/ibmveth.h b/drivers/net/ibmveth.h
index ec76ace66c6b..43a794fab9ff 100644
--- a/drivers/net/ibmveth.h
+++ b/drivers/net/ibmveth.h
@@ -1,26 +1,28 @@
-/**************************************************************************/
-/* */
-/* IBM eServer i/[Series Virtual Ethernet Device Driver */
-/* Copyright (C) 2003 IBM Corp. */
-/* Dave Larson (larson1@us.ibm.com) */
-/* Santiago Leon (santil@us.ibm.com) */
-/* */
-/* This program is free software; you can redistribute it and/or modify */
-/* it under the terms of the GNU General Public License as published by */
-/* the Free Software Foundation; either version 2 of the License, or */
-/* (at your option) any later version. */
-/* */
-/* This program is distributed in the hope that it will be useful, */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
-/* GNU General Public License for more details. */
-/* */
-/* You should have received a copy of the GNU General Public License */
-/* along with this program; if not, write to the Free Software */
-/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 */
-/* USA */
-/* */
-/**************************************************************************/
+/*
+ * IBM Power Virtual Ethernet Device Driver
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) IBM Corporation, 2003, 2010
+ *
+ * Authors: Dave Larson <larson1@us.ibm.com>
+ * Santiago Leon <santil@linux.vnet.ibm.com>
+ * Brian King <brking@linux.vnet.ibm.com>
+ * Robert Jennings <rcj@linux.vnet.ibm.com>
+ * Anton Blanchard <anton@au.ibm.com>
+ */
#ifndef _IBMVETH_H
#define _IBMVETH_H
@@ -92,17 +94,17 @@ static inline long h_illan_attributes(unsigned long unit_address,
#define h_change_logical_lan_mac(ua, mac) \
plpar_hcall_norets(H_CHANGE_LOGICAL_LAN_MAC, ua, mac)
-#define IbmVethNumBufferPools 5
+#define IBMVETH_NUM_BUFF_POOLS 5
#define IBMVETH_IO_ENTITLEMENT_DEFAULT 4243456 /* MTU of 1500 needs 4.2Mb */
#define IBMVETH_BUFF_OH 22 /* Overhead: 14 ethernet header + 8 opaque handle */
-#define IBMVETH_MAX_MTU 68
+#define IBMVETH_MIN_MTU 68
#define IBMVETH_MAX_POOL_COUNT 4096
#define IBMVETH_BUFF_LIST_SIZE 4096
#define IBMVETH_FILT_LIST_SIZE 4096
#define IBMVETH_MAX_BUF_SIZE (1024 * 128)
static int pool_size[] = { 512, 1024 * 2, 1024 * 16, 1024 * 32, 1024 * 64 };
-static int pool_count[] = { 256, 768, 256, 256, 256 };
+static int pool_count[] = { 256, 512, 256, 256, 256 };
static int pool_active[] = { 1, 1, 0, 0, 0};
#define IBM_VETH_INVALID_MAP ((u16)0xffff)
@@ -142,13 +144,15 @@ struct ibmveth_adapter {
void * filter_list_addr;
dma_addr_t buffer_list_dma;
dma_addr_t filter_list_dma;
- struct ibmveth_buff_pool rx_buff_pool[IbmVethNumBufferPools];
+ struct ibmveth_buff_pool rx_buff_pool[IBMVETH_NUM_BUFF_POOLS];
struct ibmveth_rx_q rx_queue;
int pool_config;
int rx_csum;
void *bounce_buffer;
dma_addr_t bounce_buffer_dma;
+ u64 fw_ipv6_csum_support;
+ u64 fw_ipv4_csum_support;
/* adapter specific stats */
u64 replenish_task_cycles;
u64 replenish_no_mem;
@@ -158,7 +162,6 @@ struct ibmveth_adapter {
u64 rx_no_buffer;
u64 tx_map_failed;
u64 tx_send_failed;
- spinlock_t stats_lock;
};
struct ibmveth_buf_desc_fields {
diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c
index 187622f1c816..bc183f5487cb 100644
--- a/drivers/net/igb/e1000_82575.c
+++ b/drivers/net/igb/e1000_82575.c
@@ -132,6 +132,8 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
case E1000_DEV_ID_82580_SERDES:
case E1000_DEV_ID_82580_SGMII:
case E1000_DEV_ID_82580_COPPER_DUAL:
+ case E1000_DEV_ID_DH89XXCC_SGMII:
+ case E1000_DEV_ID_DH89XXCC_SERDES:
mac->type = e1000_82580;
break;
case E1000_DEV_ID_I350_COPPER:
@@ -282,10 +284,18 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
/* Verify phy id and set remaining function pointers */
switch (phy->id) {
+ case I347AT4_E_PHY_ID:
+ case M88E1112_E_PHY_ID:
case M88E1111_I_PHY_ID:
phy->type = e1000_phy_m88;
phy->ops.get_phy_info = igb_get_phy_info_m88;
- phy->ops.get_cable_length = igb_get_cable_length_m88;
+
+ if (phy->id == I347AT4_E_PHY_ID ||
+ phy->id == M88E1112_E_PHY_ID)
+ phy->ops.get_cable_length = igb_get_cable_length_m88_gen2;
+ else
+ phy->ops.get_cable_length = igb_get_cable_length_m88;
+
phy->ops.force_speed_duplex = igb_phy_force_speed_duplex_m88;
break;
case IGP03E1000_E_PHY_ID:
@@ -1058,7 +1068,11 @@ static s32 igb_setup_copper_link_82575(struct e1000_hw *hw)
}
switch (hw->phy.type) {
case e1000_phy_m88:
- ret_val = igb_copper_link_setup_m88(hw);
+ if (hw->phy.id == I347AT4_E_PHY_ID ||
+ hw->phy.id == M88E1112_E_PHY_ID)
+ ret_val = igb_copper_link_setup_m88_gen2(hw);
+ else
+ ret_val = igb_copper_link_setup_m88(hw);
break;
case e1000_phy_igp_3:
ret_val = igb_copper_link_setup_igp(hw);
diff --git a/drivers/net/igb/e1000_defines.h b/drivers/net/igb/e1000_defines.h
index bbd2ec308eb0..62222796a8b3 100644
--- a/drivers/net/igb/e1000_defines.h
+++ b/drivers/net/igb/e1000_defines.h
@@ -634,6 +634,8 @@
* E = External
*/
#define M88E1111_I_PHY_ID 0x01410CC0
+#define M88E1112_E_PHY_ID 0x01410C90
+#define I347AT4_E_PHY_ID 0x01410DC0
#define IGP03E1000_E_PHY_ID 0x02A80390
#define I82580_I_PHY_ID 0x015403A0
#define I350_I_PHY_ID 0x015403B0
@@ -702,6 +704,35 @@
#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X 0x0100
#define M88E1000_EPSCR_TX_CLK_25 0x0070 /* 25 MHz TX_CLK */
+/* Intel i347-AT4 Registers */
+
+#define I347AT4_PCDL 0x10 /* PHY Cable Diagnostics Length */
+#define I347AT4_PCDC 0x15 /* PHY Cable Diagnostics Control */
+#define I347AT4_PAGE_SELECT 0x16
+
+/* i347-AT4 Extended PHY Specific Control Register */
+
+/*
+ * Number of times we will attempt to autonegotiate before downshifting if we
+ * are the master
+ */
+#define I347AT4_PSCR_DOWNSHIFT_ENABLE 0x0800
+#define I347AT4_PSCR_DOWNSHIFT_MASK 0x7000
+#define I347AT4_PSCR_DOWNSHIFT_1X 0x0000
+#define I347AT4_PSCR_DOWNSHIFT_2X 0x1000
+#define I347AT4_PSCR_DOWNSHIFT_3X 0x2000
+#define I347AT4_PSCR_DOWNSHIFT_4X 0x3000
+#define I347AT4_PSCR_DOWNSHIFT_5X 0x4000
+#define I347AT4_PSCR_DOWNSHIFT_6X 0x5000
+#define I347AT4_PSCR_DOWNSHIFT_7X 0x6000
+#define I347AT4_PSCR_DOWNSHIFT_8X 0x7000
+
+/* i347-AT4 PHY Cable Diagnostics Control */
+#define I347AT4_PCDC_CABLE_LENGTH_UNIT 0x0400 /* 0=cm 1=meters */
+
+/* Marvell 1112 only registers */
+#define M88E1112_VCT_DSP_DISTANCE 0x001A
+
/* M88EC018 Rev 2 specific DownShift settings */
#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK 0x0E00
#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X 0x0800
diff --git a/drivers/net/igb/e1000_hw.h b/drivers/net/igb/e1000_hw.h
index cb8db78b1a05..c0b017f8d782 100644
--- a/drivers/net/igb/e1000_hw.h
+++ b/drivers/net/igb/e1000_hw.h
@@ -54,6 +54,8 @@ struct e1000_hw;
#define E1000_DEV_ID_82580_SERDES 0x1510
#define E1000_DEV_ID_82580_SGMII 0x1511
#define E1000_DEV_ID_82580_COPPER_DUAL 0x1516
+#define E1000_DEV_ID_DH89XXCC_SGMII 0x0436
+#define E1000_DEV_ID_DH89XXCC_SERDES 0x0438
#define E1000_DEV_ID_I350_COPPER 0x1521
#define E1000_DEV_ID_I350_FIBER 0x1522
#define E1000_DEV_ID_I350_SERDES 0x1523
diff --git a/drivers/net/igb/e1000_phy.c b/drivers/net/igb/e1000_phy.c
index cf1f32300923..ddd036a78999 100644
--- a/drivers/net/igb/e1000_phy.c
+++ b/drivers/net/igb/e1000_phy.c
@@ -570,6 +570,89 @@ out:
}
/**
+ * igb_copper_link_setup_m88_gen2 - Setup m88 PHY's for copper link
+ * @hw: pointer to the HW structure
+ *
+ * Sets up MDI/MDI-X and polarity for i347-AT4, m88e1322 and m88e1112 PHY's.
+ * Also enables and sets the downshift parameters.
+ **/
+s32 igb_copper_link_setup_m88_gen2(struct e1000_hw *hw)
+{
+ struct e1000_phy_info *phy = &hw->phy;
+ s32 ret_val;
+ u16 phy_data;
+
+ if (phy->reset_disable) {
+ ret_val = 0;
+ goto out;
+ }
+
+ /* Enable CRS on Tx. This must be set for half-duplex operation. */
+ ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
+ if (ret_val)
+ goto out;
+
+ /*
+ * Options:
+ * MDI/MDI-X = 0 (default)
+ * 0 - Auto for all speeds
+ * 1 - MDI mode
+ * 2 - MDI-X mode
+ * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes)
+ */
+ phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
+
+ switch (phy->mdix) {
+ case 1:
+ phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE;
+ break;
+ case 2:
+ phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE;
+ break;
+ case 3:
+ /* M88E1112 does not support this mode) */
+ if (phy->id != M88E1112_E_PHY_ID) {
+ phy_data |= M88E1000_PSCR_AUTO_X_1000T;
+ break;
+ }
+ case 0:
+ default:
+ phy_data |= M88E1000_PSCR_AUTO_X_MODE;
+ break;
+ }
+
+ /*
+ * Options:
+ * disable_polarity_correction = 0 (default)
+ * Automatic Correction for Reversed Cable Polarity
+ * 0 - Disabled
+ * 1 - Enabled
+ */
+ phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL;
+ if (phy->disable_polarity_correction == 1)
+ phy_data |= M88E1000_PSCR_POLARITY_REVERSAL;
+
+ /* Enable downshift and setting it to X6 */
+ phy_data &= ~I347AT4_PSCR_DOWNSHIFT_MASK;
+ phy_data |= I347AT4_PSCR_DOWNSHIFT_6X;
+ phy_data |= I347AT4_PSCR_DOWNSHIFT_ENABLE;
+
+ ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
+ if (ret_val)
+ goto out;
+
+ /* Commit the changes. */
+ ret_val = igb_phy_sw_reset(hw);
+ if (ret_val) {
+ hw_dbg("Error committing the PHY changes\n");
+ goto out;
+ }
+
+out:
+ return ret_val;
+}
+
+/**
* igb_copper_link_setup_igp - Setup igp PHY's for copper link
* @hw: pointer to the HW structure
*
@@ -1124,18 +1207,25 @@ s32 igb_phy_force_speed_duplex_m88(struct e1000_hw *hw)
goto out;
if (!link) {
- /*
- * We didn't get link.
- * Reset the DSP and cross our fingers.
- */
- ret_val = phy->ops.write_reg(hw,
- M88E1000_PHY_PAGE_SELECT,
- 0x001d);
- if (ret_val)
- goto out;
- ret_val = igb_phy_reset_dsp(hw);
- if (ret_val)
- goto out;
+ if (hw->phy.type != e1000_phy_m88 ||
+ hw->phy.id == I347AT4_E_PHY_ID ||
+ hw->phy.id == M88E1112_E_PHY_ID) {
+ hw_dbg("Link taking longer than expected.\n");
+ } else {
+
+ /*
+ * We didn't get link.
+ * Reset the DSP and cross our fingers.
+ */
+ ret_val = phy->ops.write_reg(hw,
+ M88E1000_PHY_PAGE_SELECT,
+ 0x001d);
+ if (ret_val)
+ goto out;
+ ret_val = igb_phy_reset_dsp(hw);
+ if (ret_val)
+ goto out;
+ }
}
/* Try once more */
@@ -1145,6 +1235,11 @@ s32 igb_phy_force_speed_duplex_m88(struct e1000_hw *hw)
goto out;
}
+ if (hw->phy.type != e1000_phy_m88 ||
+ hw->phy.id == I347AT4_E_PHY_ID ||
+ hw->phy.id == M88E1112_E_PHY_ID)
+ goto out;
+
ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data);
if (ret_val)
goto out;
@@ -1557,6 +1652,93 @@ out:
return ret_val;
}
+s32 igb_get_cable_length_m88_gen2(struct e1000_hw *hw)
+{
+ struct e1000_phy_info *phy = &hw->phy;
+ s32 ret_val;
+ u16 phy_data, phy_data2, index, default_page, is_cm;
+
+ switch (hw->phy.id) {
+ case I347AT4_E_PHY_ID:
+ /* Remember the original page select and set it to 7 */
+ ret_val = phy->ops.read_reg(hw, I347AT4_PAGE_SELECT,
+ &default_page);
+ if (ret_val)
+ goto out;
+
+ ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT, 0x07);
+ if (ret_val)
+ goto out;
+
+ /* Get cable length from PHY Cable Diagnostics Control Reg */
+ ret_val = phy->ops.read_reg(hw, (I347AT4_PCDL + phy->addr),
+ &phy_data);
+ if (ret_val)
+ goto out;
+
+ /* Check if the unit of cable length is meters or cm */
+ ret_val = phy->ops.read_reg(hw, I347AT4_PCDC, &phy_data2);
+ if (ret_val)
+ goto out;
+
+ is_cm = !(phy_data & I347AT4_PCDC_CABLE_LENGTH_UNIT);
+
+ /* Populate the phy structure with cable length in meters */
+ phy->min_cable_length = phy_data / (is_cm ? 100 : 1);
+ phy->max_cable_length = phy_data / (is_cm ? 100 : 1);
+ phy->cable_length = phy_data / (is_cm ? 100 : 1);
+
+ /* Reset the page selec to its original value */
+ ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT,
+ default_page);
+ if (ret_val)
+ goto out;
+ break;
+ case M88E1112_E_PHY_ID:
+ /* Remember the original page select and set it to 5 */
+ ret_val = phy->ops.read_reg(hw, I347AT4_PAGE_SELECT,
+ &default_page);
+ if (ret_val)
+ goto out;
+
+ ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT, 0x05);
+ if (ret_val)
+ goto out;
+
+ ret_val = phy->ops.read_reg(hw, M88E1112_VCT_DSP_DISTANCE,
+ &phy_data);
+ if (ret_val)
+ goto out;
+
+ index = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
+ M88E1000_PSSR_CABLE_LENGTH_SHIFT;
+ if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE - 1) {
+ ret_val = -E1000_ERR_PHY;
+ goto out;
+ }
+
+ phy->min_cable_length = e1000_m88_cable_length_table[index];
+ phy->max_cable_length = e1000_m88_cable_length_table[index + 1];
+
+ phy->cable_length = (phy->min_cable_length +
+ phy->max_cable_length) / 2;
+
+ /* Reset the page select to its original value */
+ ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT,
+ default_page);
+ if (ret_val)
+ goto out;
+
+ break;
+ default:
+ ret_val = -E1000_ERR_PHY;
+ goto out;
+ }
+
+out:
+ return ret_val;
+}
+
/**
* igb_get_cable_length_igp_2 - Determine cable length for igp2 PHY
* @hw: pointer to the HW structure
diff --git a/drivers/net/igb/e1000_phy.h b/drivers/net/igb/e1000_phy.h
index 565a6dbb3714..2cc117705a31 100644
--- a/drivers/net/igb/e1000_phy.h
+++ b/drivers/net/igb/e1000_phy.h
@@ -45,9 +45,11 @@ s32 igb_check_downshift(struct e1000_hw *hw);
s32 igb_check_reset_block(struct e1000_hw *hw);
s32 igb_copper_link_setup_igp(struct e1000_hw *hw);
s32 igb_copper_link_setup_m88(struct e1000_hw *hw);
+s32 igb_copper_link_setup_m88_gen2(struct e1000_hw *hw);
s32 igb_phy_force_speed_duplex_igp(struct e1000_hw *hw);
s32 igb_phy_force_speed_duplex_m88(struct e1000_hw *hw);
s32 igb_get_cable_length_m88(struct e1000_hw *hw);
+s32 igb_get_cable_length_m88_gen2(struct e1000_hw *hw);
s32 igb_get_cable_length_igp_2(struct e1000_hw *hw);
s32 igb_get_phy_id(struct e1000_hw *hw);
s32 igb_get_phy_info_igp(struct e1000_hw *hw);
diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h
index 6e63d9a7fc75..edab9c442399 100644
--- a/drivers/net/igb/igb.h
+++ b/drivers/net/igb/igb.h
@@ -143,7 +143,7 @@ struct igb_buffer {
u16 next_to_watch;
unsigned int bytecount;
u16 gso_segs;
- union skb_shared_tx shtx;
+ u8 tx_flags;
u8 mapped_as_page;
};
/* RX */
@@ -159,6 +159,7 @@ struct igb_tx_queue_stats {
u64 packets;
u64 bytes;
u64 restart_queue;
+ u64 restart_queue2;
};
struct igb_rx_queue_stats {
@@ -210,11 +211,14 @@ struct igb_ring {
/* TX */
struct {
struct igb_tx_queue_stats tx_stats;
+ struct u64_stats_sync tx_syncp;
+ struct u64_stats_sync tx_syncp2;
bool detect_tx_hung;
};
/* RX */
struct {
struct igb_rx_queue_stats rx_stats;
+ struct u64_stats_sync rx_syncp;
u32 rx_buffer_len;
};
};
@@ -288,6 +292,9 @@ struct igb_adapter {
struct timecompare compare;
struct hwtstamp_config hwtstamp_config;
+ spinlock_t stats64_lock;
+ struct rtnl_link_stats64 stats64;
+
/* structs defined in e1000_hw.h */
struct e1000_hw hw;
struct e1000_hw_stats stats;
@@ -357,7 +364,7 @@ extern netdev_tx_t igb_xmit_frame_ring_adv(struct sk_buff *, struct igb_ring *);
extern void igb_unmap_and_free_tx_resource(struct igb_ring *,
struct igb_buffer *);
extern void igb_alloc_rx_buffers_adv(struct igb_ring *, int);
-extern void igb_update_stats(struct igb_adapter *);
+extern void igb_update_stats(struct igb_adapter *, struct rtnl_link_stats64 *);
extern bool igb_has_link(struct igb_adapter *adapter);
extern void igb_set_ethtool_ops(struct net_device *);
extern void igb_power_up_link(struct igb_adapter *);
diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c
index 26bf6a13d1c1..a70e16bcfa7e 100644
--- a/drivers/net/igb/igb_ethtool.c
+++ b/drivers/net/igb/igb_ethtool.c
@@ -90,8 +90,8 @@ static const struct igb_stats igb_gstrings_stats[] = {
#define IGB_NETDEV_STAT(_net_stat) { \
.stat_string = __stringify(_net_stat), \
- .sizeof_stat = FIELD_SIZEOF(struct net_device_stats, _net_stat), \
- .stat_offset = offsetof(struct net_device_stats, _net_stat) \
+ .sizeof_stat = FIELD_SIZEOF(struct rtnl_link_stats64, _net_stat), \
+ .stat_offset = offsetof(struct rtnl_link_stats64, _net_stat) \
}
static const struct igb_stats igb_gstrings_net_stats[] = {
IGB_NETDEV_STAT(rx_errors),
@@ -111,8 +111,9 @@ static const struct igb_stats igb_gstrings_net_stats[] = {
(sizeof(igb_gstrings_net_stats) / sizeof(struct igb_stats))
#define IGB_RX_QUEUE_STATS_LEN \
(sizeof(struct igb_rx_queue_stats) / sizeof(u64))
-#define IGB_TX_QUEUE_STATS_LEN \
- (sizeof(struct igb_tx_queue_stats) / sizeof(u64))
+
+#define IGB_TX_QUEUE_STATS_LEN 3 /* packets, bytes, restart_queue */
+
#define IGB_QUEUE_STATS_LEN \
((((struct igb_adapter *)netdev_priv(netdev))->num_rx_queues * \
IGB_RX_QUEUE_STATS_LEN) + \
@@ -2070,12 +2071,14 @@ static void igb_get_ethtool_stats(struct net_device *netdev,
struct ethtool_stats *stats, u64 *data)
{
struct igb_adapter *adapter = netdev_priv(netdev);
- struct net_device_stats *net_stats = &netdev->stats;
- u64 *queue_stat;
- int i, j, k;
+ struct rtnl_link_stats64 *net_stats = &adapter->stats64;
+ unsigned int start;
+ struct igb_ring *ring;
+ int i, j;
char *p;
- igb_update_stats(adapter);
+ spin_lock(&adapter->stats64_lock);
+ igb_update_stats(adapter, net_stats);
for (i = 0; i < IGB_GLOBAL_STATS_LEN; i++) {
p = (char *)adapter + igb_gstrings_stats[i].stat_offset;
@@ -2088,15 +2091,36 @@ static void igb_get_ethtool_stats(struct net_device *netdev,
sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
}
for (j = 0; j < adapter->num_tx_queues; j++) {
- queue_stat = (u64 *)&adapter->tx_ring[j]->tx_stats;
- for (k = 0; k < IGB_TX_QUEUE_STATS_LEN; k++, i++)
- data[i] = queue_stat[k];
+ u64 restart2;
+
+ ring = adapter->tx_ring[j];
+ do {
+ start = u64_stats_fetch_begin_bh(&ring->tx_syncp);
+ data[i] = ring->tx_stats.packets;
+ data[i+1] = ring->tx_stats.bytes;
+ data[i+2] = ring->tx_stats.restart_queue;
+ } while (u64_stats_fetch_retry_bh(&ring->tx_syncp, start));
+ do {
+ start = u64_stats_fetch_begin_bh(&ring->tx_syncp2);
+ restart2 = ring->tx_stats.restart_queue2;
+ } while (u64_stats_fetch_retry_bh(&ring->tx_syncp2, start));
+ data[i+2] += restart2;
+
+ i += IGB_TX_QUEUE_STATS_LEN;
}
for (j = 0; j < adapter->num_rx_queues; j++) {
- queue_stat = (u64 *)&adapter->rx_ring[j]->rx_stats;
- for (k = 0; k < IGB_RX_QUEUE_STATS_LEN; k++, i++)
- data[i] = queue_stat[k];
+ ring = adapter->rx_ring[j];
+ do {
+ start = u64_stats_fetch_begin_bh(&ring->rx_syncp);
+ data[i] = ring->rx_stats.packets;
+ data[i+1] = ring->rx_stats.bytes;
+ data[i+2] = ring->rx_stats.drops;
+ data[i+3] = ring->rx_stats.csum_err;
+ data[i+4] = ring->rx_stats.alloc_failed;
+ } while (u64_stats_fetch_retry_bh(&ring->rx_syncp, start));
+ i += IGB_RX_QUEUE_STATS_LEN;
}
+ spin_unlock(&adapter->stats64_lock);
}
static void igb_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index 9b4e5895f5f9..75155a27fdde 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -71,6 +71,8 @@ static DEFINE_PCI_DEVICE_TABLE(igb_pci_tbl) = {
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_SERDES), board_82575 },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_SGMII), board_82575 },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_COPPER_DUAL), board_82575 },
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_DH89XXCC_SGMII), board_82575 },
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_DH89XXCC_SERDES), board_82575 },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82576), board_82575 },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_NS), board_82575 },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_NS_SERDES), board_82575 },
@@ -94,7 +96,6 @@ static int igb_setup_all_rx_resources(struct igb_adapter *);
static void igb_free_all_tx_resources(struct igb_adapter *);
static void igb_free_all_rx_resources(struct igb_adapter *);
static void igb_setup_mrqc(struct igb_adapter *);
-void igb_update_stats(struct igb_adapter *);
static int igb_probe(struct pci_dev *, const struct pci_device_id *);
static void __devexit igb_remove(struct pci_dev *pdev);
static int igb_sw_init(struct igb_adapter *);
@@ -111,7 +112,8 @@ static void igb_update_phy_info(unsigned long);
static void igb_watchdog(unsigned long);
static void igb_watchdog_task(struct work_struct *);
static netdev_tx_t igb_xmit_frame_adv(struct sk_buff *skb, struct net_device *);
-static struct net_device_stats *igb_get_stats(struct net_device *);
+static struct rtnl_link_stats64 *igb_get_stats64(struct net_device *dev,
+ struct rtnl_link_stats64 *stats);
static int igb_change_mtu(struct net_device *, int);
static int igb_set_mac(struct net_device *, void *);
static void igb_set_uta(struct igb_adapter *adapter);
@@ -986,7 +988,7 @@ static void igb_clear_interrupt_scheme(struct igb_adapter *adapter)
* Attempt to configure interrupts using the best available
* capabilities of the hardware and kernel.
**/
-static void igb_set_interrupt_capability(struct igb_adapter *adapter)
+static int igb_set_interrupt_capability(struct igb_adapter *adapter)
{
int err;
int numvecs, i;
@@ -1052,8 +1054,10 @@ msi_only:
if (!pci_enable_msi(adapter->pdev))
adapter->flags |= IGB_FLAG_HAS_MSI;
out:
- /* Notify the stack of the (possibly) reduced Tx Queue count. */
- adapter->netdev->real_num_tx_queues = adapter->num_tx_queues;
+ /* Notify the stack of the (possibly) reduced queue counts. */
+ netif_set_real_num_tx_queues(adapter->netdev, adapter->num_tx_queues);
+ return netif_set_real_num_rx_queues(adapter->netdev,
+ adapter->num_rx_queues);
}
/**
@@ -1152,7 +1156,9 @@ static int igb_init_interrupt_scheme(struct igb_adapter *adapter)
struct pci_dev *pdev = adapter->pdev;
int err;
- igb_set_interrupt_capability(adapter);
+ err = igb_set_interrupt_capability(adapter);
+ if (err)
+ return err;
err = igb_alloc_q_vectors(adapter);
if (err) {
@@ -1530,7 +1536,9 @@ void igb_down(struct igb_adapter *adapter)
netif_carrier_off(netdev);
/* record the stats before reset*/
- igb_update_stats(adapter);
+ spin_lock(&adapter->stats64_lock);
+ igb_update_stats(adapter, &adapter->stats64);
+ spin_unlock(&adapter->stats64_lock);
adapter->link_speed = 0;
adapter->link_duplex = 0;
@@ -1683,7 +1691,7 @@ static const struct net_device_ops igb_netdev_ops = {
.ndo_open = igb_open,
.ndo_stop = igb_close,
.ndo_start_xmit = igb_xmit_frame_adv,
- .ndo_get_stats = igb_get_stats,
+ .ndo_get_stats64 = igb_get_stats64,
.ndo_set_rx_mode = igb_set_rx_mode,
.ndo_set_multicast_list = igb_set_rx_mode,
.ndo_set_mac_address = igb_set_mac,
@@ -1856,8 +1864,10 @@ static int __devinit igb_probe(struct pci_dev *pdev,
netdev->vlan_features |= NETIF_F_IPV6_CSUM;
netdev->vlan_features |= NETIF_F_SG;
- if (pci_using_dac)
+ if (pci_using_dac) {
netdev->features |= NETIF_F_HIGHDMA;
+ netdev->vlan_features |= NETIF_F_HIGHDMA;
+ }
if (hw->mac.type >= e1000_82576)
netdev->features |= NETIF_F_SCTP_CSUM;
@@ -1888,9 +1898,9 @@ static int __devinit igb_probe(struct pci_dev *pdev,
goto err_eeprom;
}
- setup_timer(&adapter->watchdog_timer, &igb_watchdog,
+ setup_timer(&adapter->watchdog_timer, igb_watchdog,
(unsigned long) adapter);
- setup_timer(&adapter->phy_info_timer, &igb_update_phy_info,
+ setup_timer(&adapter->phy_info_timer, igb_update_phy_info,
(unsigned long) adapter);
INIT_WORK(&adapter->reset_task, igb_reset_task);
@@ -2268,6 +2278,7 @@ static int __devinit igb_sw_init(struct igb_adapter *adapter)
adapter->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN;
+ spin_lock_init(&adapter->stats64_lock);
#ifdef CONFIG_PCI_IOV
if (hw->mac.type == e1000_82576)
adapter->vfs_allocated_count = (max_vfs > 7) ? 7 : max_vfs;
@@ -3475,7 +3486,9 @@ static void igb_watchdog_task(struct work_struct *work)
}
}
- igb_update_stats(adapter);
+ spin_lock(&adapter->stats64_lock);
+ igb_update_stats(adapter, &adapter->stats64);
+ spin_unlock(&adapter->stats64_lock);
for (i = 0; i < adapter->num_tx_queues; i++) {
struct igb_ring *tx_ring = adapter->tx_ring[i];
@@ -3542,6 +3555,8 @@ static void igb_update_ring_itr(struct igb_q_vector *q_vector)
int new_val = q_vector->itr_val;
int avg_wire_size = 0;
struct igb_adapter *adapter = q_vector->adapter;
+ struct igb_ring *ring;
+ unsigned int packets;
/* For non-gigabit speeds, just fix the interrupt rate at 4000
* ints/sec - ITR timer value of 120 ticks.
@@ -3551,16 +3566,21 @@ static void igb_update_ring_itr(struct igb_q_vector *q_vector)
goto set_itr_val;
}
- if (q_vector->rx_ring && q_vector->rx_ring->total_packets) {
- struct igb_ring *ring = q_vector->rx_ring;
- avg_wire_size = ring->total_bytes / ring->total_packets;
+ ring = q_vector->rx_ring;
+ if (ring) {
+ packets = ACCESS_ONCE(ring->total_packets);
+
+ if (packets)
+ avg_wire_size = ring->total_bytes / packets;
}
- if (q_vector->tx_ring && q_vector->tx_ring->total_packets) {
- struct igb_ring *ring = q_vector->tx_ring;
- avg_wire_size = max_t(u32, avg_wire_size,
- (ring->total_bytes /
- ring->total_packets));
+ ring = q_vector->tx_ring;
+ if (ring) {
+ packets = ACCESS_ONCE(ring->total_packets);
+
+ if (packets)
+ avg_wire_size = max_t(u32, avg_wire_size,
+ ring->total_bytes / packets);
}
/* if avg_wire_size isn't set no work was done */
@@ -3954,7 +3974,7 @@ static inline int igb_tx_map_adv(struct igb_ring *tx_ring, struct sk_buff *skb,
}
tx_ring->buffer_info[i].skb = skb;
- tx_ring->buffer_info[i].shtx = skb_shinfo(skb)->tx_flags;
+ tx_ring->buffer_info[i].tx_flags = skb_shinfo(skb)->tx_flags;
/* multiply data chunks by size of headers */
tx_ring->buffer_info[i].bytecount = ((gso_segs - 1) * hlen) + skb->len;
tx_ring->buffer_info[i].gso_segs = gso_segs;
@@ -4069,7 +4089,11 @@ static int __igb_maybe_stop_tx(struct igb_ring *tx_ring, int size)
/* A reprieve! */
netif_wake_subqueue(netdev, tx_ring->queue_index);
- tx_ring->tx_stats.restart_queue++;
+
+ u64_stats_update_begin(&tx_ring->tx_syncp2);
+ tx_ring->tx_stats.restart_queue2++;
+ u64_stats_update_end(&tx_ring->tx_syncp2);
+
return 0;
}
@@ -4088,7 +4112,6 @@ netdev_tx_t igb_xmit_frame_ring_adv(struct sk_buff *skb,
u32 tx_flags = 0;
u16 first;
u8 hdr_len = 0;
- union skb_shared_tx *shtx = skb_tx(skb);
/* need: 1 descriptor per page,
* + 2 desc gap to keep tail from touching head,
@@ -4100,12 +4123,12 @@ netdev_tx_t igb_xmit_frame_ring_adv(struct sk_buff *skb,
return NETDEV_TX_BUSY;
}
- if (unlikely(shtx->hardware)) {
- shtx->in_progress = 1;
+ if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
+ skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
tx_flags |= IGB_TX_FLAGS_TSTAMP;
}
- if (vlan_tx_tag_present(skb) && adapter->vlgrp) {
+ if (vlan_tx_tag_present(skb)) {
tx_flags |= IGB_TX_FLAGS_VLAN;
tx_flags |= (vlan_tx_tag_get(skb) << IGB_TX_FLAGS_VLAN_SHIFT);
}
@@ -4207,16 +4230,22 @@ static void igb_reset_task(struct work_struct *work)
}
/**
- * igb_get_stats - Get System Network Statistics
+ * igb_get_stats64 - Get System Network Statistics
* @netdev: network interface device structure
+ * @stats: rtnl_link_stats64 pointer
*
- * Returns the address of the device statistics structure.
- * The statistics are actually updated from the timer callback.
**/
-static struct net_device_stats *igb_get_stats(struct net_device *netdev)
+static struct rtnl_link_stats64 *igb_get_stats64(struct net_device *netdev,
+ struct rtnl_link_stats64 *stats)
{
- /* only return the current stats */
- return &netdev->stats;
+ struct igb_adapter *adapter = netdev_priv(netdev);
+
+ spin_lock(&adapter->stats64_lock);
+ igb_update_stats(adapter, &adapter->stats64);
+ memcpy(stats, &adapter->stats64, sizeof(*stats));
+ spin_unlock(&adapter->stats64_lock);
+
+ return stats;
}
/**
@@ -4298,15 +4327,17 @@ static int igb_change_mtu(struct net_device *netdev, int new_mtu)
* @adapter: board private structure
**/
-void igb_update_stats(struct igb_adapter *adapter)
+void igb_update_stats(struct igb_adapter *adapter,
+ struct rtnl_link_stats64 *net_stats)
{
- struct net_device_stats *net_stats = igb_get_stats(adapter->netdev);
struct e1000_hw *hw = &adapter->hw;
struct pci_dev *pdev = adapter->pdev;
u32 reg, mpc;
u16 phy_tmp;
int i;
u64 bytes, packets;
+ unsigned int start;
+ u64 _bytes, _packets;
#define PHY_IDLE_ERROR_COUNT_MASK 0x00FF
@@ -4324,10 +4355,17 @@ void igb_update_stats(struct igb_adapter *adapter)
for (i = 0; i < adapter->num_rx_queues; i++) {
u32 rqdpc_tmp = rd32(E1000_RQDPC(i)) & 0x0FFF;
struct igb_ring *ring = adapter->rx_ring[i];
+
ring->rx_stats.drops += rqdpc_tmp;
net_stats->rx_fifo_errors += rqdpc_tmp;
- bytes += ring->rx_stats.bytes;
- packets += ring->rx_stats.packets;
+
+ do {
+ start = u64_stats_fetch_begin_bh(&ring->rx_syncp);
+ _bytes = ring->rx_stats.bytes;
+ _packets = ring->rx_stats.packets;
+ } while (u64_stats_fetch_retry_bh(&ring->rx_syncp, start));
+ bytes += _bytes;
+ packets += _packets;
}
net_stats->rx_bytes = bytes;
@@ -4337,8 +4375,13 @@ void igb_update_stats(struct igb_adapter *adapter)
packets = 0;
for (i = 0; i < adapter->num_tx_queues; i++) {
struct igb_ring *ring = adapter->tx_ring[i];
- bytes += ring->tx_stats.bytes;
- packets += ring->tx_stats.packets;
+ do {
+ start = u64_stats_fetch_begin_bh(&ring->tx_syncp);
+ _bytes = ring->tx_stats.bytes;
+ _packets = ring->tx_stats.packets;
+ } while (u64_stats_fetch_retry_bh(&ring->tx_syncp, start));
+ bytes += _bytes;
+ packets += _packets;
}
net_stats->tx_bytes = bytes;
net_stats->tx_packets = packets;
@@ -4660,12 +4703,13 @@ static int igb_set_vf_promisc(struct igb_adapter *adapter, u32 *msgbuf, u32 vf)
u32 vmolr = rd32(E1000_VMOLR(vf));
struct vf_data_storage *vf_data = &adapter->vf_data[vf];
- vf_data->flags |= ~(IGB_VF_FLAG_UNI_PROMISC |
+ vf_data->flags &= ~(IGB_VF_FLAG_UNI_PROMISC |
IGB_VF_FLAG_MULTI_PROMISC);
vmolr &= ~(E1000_VMOLR_ROPE | E1000_VMOLR_ROMPE | E1000_VMOLR_MPME);
if (*msgbuf & E1000_VF_SET_PROMISC_MULTICAST) {
vmolr |= E1000_VMOLR_MPME;
+ vf_data->flags |= IGB_VF_FLAG_MULTI_PROMISC;
*msgbuf &= ~E1000_VF_SET_PROMISC_MULTICAST;
} else {
/*
@@ -5319,7 +5363,7 @@ static void igb_tx_hwtstamp(struct igb_q_vector *q_vector, struct igb_buffer *bu
u64 regval;
/* if skb does not support hw timestamp or TX stamp not valid exit */
- if (likely(!buffer_info->shtx.hardware) ||
+ if (likely(!(buffer_info->tx_flags & SKBTX_HW_TSTAMP)) ||
!(rd32(E1000_TSYNCTXCTL) & E1000_TSYNCTXCTL_VALID))
return;
@@ -5389,7 +5433,10 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector)
if (__netif_subqueue_stopped(netdev, tx_ring->queue_index) &&
!(test_bit(__IGB_DOWN, &adapter->state))) {
netif_wake_subqueue(netdev, tx_ring->queue_index);
+
+ u64_stats_update_begin(&tx_ring->tx_syncp);
tx_ring->tx_stats.restart_queue++;
+ u64_stats_update_end(&tx_ring->tx_syncp);
}
}
@@ -5429,9 +5476,11 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector)
}
tx_ring->total_bytes += total_bytes;
tx_ring->total_packets += total_packets;
+ u64_stats_update_begin(&tx_ring->tx_syncp);
tx_ring->tx_stats.bytes += total_bytes;
tx_ring->tx_stats.packets += total_packets;
- return (count < tx_ring->count);
+ u64_stats_update_end(&tx_ring->tx_syncp);
+ return count < tx_ring->count;
}
/**
@@ -5456,7 +5505,7 @@ static void igb_receive_skb(struct igb_q_vector *q_vector,
static inline void igb_rx_checksum_adv(struct igb_ring *ring,
u32 status_err, struct sk_buff *skb)
{
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
/* Ignore Checksum bit is set or checksum is disabled through ethtool */
if (!(ring->flags & IGB_RING_FLAG_RX_CSUM) ||
@@ -5472,9 +5521,11 @@ static inline void igb_rx_checksum_adv(struct igb_ring *ring,
* packets, (aka let the stack check the crc32c)
*/
if ((skb->len == 60) &&
- (ring->flags & IGB_RING_FLAG_RX_SCTP_CSUM))
+ (ring->flags & IGB_RING_FLAG_RX_SCTP_CSUM)) {
+ u64_stats_update_begin(&ring->rx_syncp);
ring->rx_stats.csum_err++;
-
+ u64_stats_update_end(&ring->rx_syncp);
+ }
/* let the stack verify checksum errors */
return;
}
@@ -5500,7 +5551,7 @@ static void igb_rx_hwtstamp(struct igb_q_vector *q_vector, u32 staterr,
* values must belong to this one here and therefore we don't need to
* compare any of the additional attributes stored for it.
*
- * If nothing went wrong, then it should have a skb_shared_tx that we
+ * If nothing went wrong, then it should have a shared tx_flags that we
* can turn into a skb_shared_hwtstamps.
*/
if (staterr & E1000_RXDADV_STAT_TSIP) {
@@ -5661,8 +5712,10 @@ next_desc:
rx_ring->total_packets += total_packets;
rx_ring->total_bytes += total_bytes;
+ u64_stats_update_begin(&rx_ring->rx_syncp);
rx_ring->rx_stats.packets += total_packets;
rx_ring->rx_stats.bytes += total_bytes;
+ u64_stats_update_end(&rx_ring->rx_syncp);
return cleaned;
}
@@ -5690,8 +5743,10 @@ void igb_alloc_rx_buffers_adv(struct igb_ring *rx_ring, int cleaned_count)
if ((bufsz < IGB_RXBUFFER_1024) && !buffer_info->page_dma) {
if (!buffer_info->page) {
buffer_info->page = netdev_alloc_page(netdev);
- if (!buffer_info->page) {
+ if (unlikely(!buffer_info->page)) {
+ u64_stats_update_begin(&rx_ring->rx_syncp);
rx_ring->rx_stats.alloc_failed++;
+ u64_stats_update_end(&rx_ring->rx_syncp);
goto no_buffers;
}
buffer_info->page_offset = 0;
@@ -5706,7 +5761,9 @@ void igb_alloc_rx_buffers_adv(struct igb_ring *rx_ring, int cleaned_count)
if (dma_mapping_error(rx_ring->dev,
buffer_info->page_dma)) {
buffer_info->page_dma = 0;
+ u64_stats_update_begin(&rx_ring->rx_syncp);
rx_ring->rx_stats.alloc_failed++;
+ u64_stats_update_end(&rx_ring->rx_syncp);
goto no_buffers;
}
}
@@ -5714,8 +5771,10 @@ void igb_alloc_rx_buffers_adv(struct igb_ring *rx_ring, int cleaned_count)
skb = buffer_info->skb;
if (!skb) {
skb = netdev_alloc_skb_ip_align(netdev, bufsz);
- if (!skb) {
+ if (unlikely(!skb)) {
+ u64_stats_update_begin(&rx_ring->rx_syncp);
rx_ring->rx_stats.alloc_failed++;
+ u64_stats_update_end(&rx_ring->rx_syncp);
goto no_buffers;
}
@@ -5729,7 +5788,9 @@ void igb_alloc_rx_buffers_adv(struct igb_ring *rx_ring, int cleaned_count)
if (dma_mapping_error(rx_ring->dev,
buffer_info->dma)) {
buffer_info->dma = 0;
+ u64_stats_update_begin(&rx_ring->rx_syncp);
rx_ring->rx_stats.alloc_failed++;
+ u64_stats_update_end(&rx_ring->rx_syncp);
goto no_buffers;
}
}
@@ -6092,7 +6153,7 @@ static void igb_restore_vlan(struct igb_adapter *adapter)
if (adapter->vlgrp) {
u16 vid;
- for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
+ for (vid = 0; vid < VLAN_N_VID; vid++) {
if (!vlan_group_get_device(adapter->vlgrp, vid))
continue;
igb_vlan_rx_add_vid(adapter->netdev, vid);
@@ -6107,6 +6168,13 @@ int igb_set_spd_dplx(struct igb_adapter *adapter, u16 spddplx)
mac->autoneg = 0;
+ /* Fiber NIC's only allow 1000 Gbps Full duplex */
+ if ((adapter->hw.phy.media_type == e1000_media_type_internal_serdes) &&
+ spddplx != (SPEED_1000 + DUPLEX_FULL)) {
+ dev_err(&pdev->dev, "Unsupported Speed/Duplex configuration\n");
+ return -EINVAL;
+ }
+
switch (spddplx) {
case SPEED_10 + DUPLEX_HALF:
mac->forced_speed_duplex = ADVERTISE_10_HALF;
diff --git a/drivers/net/igbvf/ethtool.c b/drivers/net/igbvf/ethtool.c
index 103b3aa1afc2..33add708bcbe 100644
--- a/drivers/net/igbvf/ethtool.c
+++ b/drivers/net/igbvf/ethtool.c
@@ -153,7 +153,7 @@ static int igbvf_set_rx_csum(struct net_device *netdev, u32 data)
static u32 igbvf_get_tx_csum(struct net_device *netdev)
{
- return ((netdev->features & NETIF_F_IP_CSUM) != 0);
+ return (netdev->features & NETIF_F_IP_CSUM) != 0;
}
static int igbvf_set_tx_csum(struct net_device *netdev, u32 data)
diff --git a/drivers/net/igbvf/netdev.c b/drivers/net/igbvf/netdev.c
index c539f7c9c3e0..ebfaa68ee630 100644
--- a/drivers/net/igbvf/netdev.c
+++ b/drivers/net/igbvf/netdev.c
@@ -41,14 +41,12 @@
#include <linux/mii.h>
#include <linux/ethtool.h>
#include <linux/if_vlan.h>
-#include <linux/pm_qos_params.h>
#include "igbvf.h"
#define DRV_VERSION "1.0.0-k0"
char igbvf_driver_name[] = "igbvf";
const char igbvf_driver_version[] = DRV_VERSION;
-static struct pm_qos_request_list igbvf_driver_pm_qos_req;
static const char igbvf_driver_string[] =
"Intel(R) Virtual Function Network Driver";
static const char igbvf_copyright[] = "Copyright (c) 2009 Intel Corporation.";
@@ -103,7 +101,7 @@ static void igbvf_receive_skb(struct igbvf_adapter *adapter,
static inline void igbvf_rx_checksum_adv(struct igbvf_adapter *adapter,
u32 status_err, struct sk_buff *skb)
{
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
/* Ignore Checksum bit is set or checksum is disabled through ethtool */
if ((status_err & E1000_RXD_STAT_IXSM) ||
@@ -845,7 +843,7 @@ static bool igbvf_clean_tx_irq(struct igbvf_ring *tx_ring)
}
adapter->net_stats.tx_bytes += total_bytes;
adapter->net_stats.tx_packets += total_packets;
- return (count < tx_ring->count);
+ return count < tx_ring->count;
}
static irqreturn_t igbvf_msix_other(int irq, void *data)
@@ -1256,7 +1254,7 @@ static void igbvf_restore_vlan(struct igbvf_adapter *adapter)
if (!adapter->vlgrp)
return;
- for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
+ for (vid = 0; vid < VLAN_N_VID; vid++) {
if (!vlan_group_get_device(adapter->vlgrp, vid))
continue;
igbvf_vlan_rx_add_vid(adapter->netdev, vid);
@@ -2904,8 +2902,6 @@ static int __init igbvf_init_module(void)
printk(KERN_INFO "%s\n", igbvf_copyright);
ret = pci_register_driver(&igbvf_driver);
- pm_qos_add_request(&igbvf_driver_pm_qos_req, PM_QOS_CPU_DMA_LATENCY,
- PM_QOS_DEFAULT_VALUE);
return ret;
}
@@ -2920,7 +2916,6 @@ module_init(igbvf_init_module);
static void __exit igbvf_exit_module(void)
{
pci_unregister_driver(&igbvf_driver);
- pm_qos_remove_request(&igbvf_driver_pm_qos_req);
}
module_exit(igbvf_exit_module);
diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c
index 0b3f6df5cff7..c8ee8d28767b 100644
--- a/drivers/net/ioc3-eth.c
+++ b/drivers/net/ioc3-eth.c
@@ -827,7 +827,7 @@ static void ioc3_mii_start(struct ioc3_private *ip)
{
ip->ioc3_timer.expires = jiffies + (12 * HZ)/10; /* 1.2 sec. */
ip->ioc3_timer.data = (unsigned long) ip;
- ip->ioc3_timer.function = &ioc3_timer;
+ ip->ioc3_timer.function = ioc3_timer;
add_timer(&ip->ioc3_timer);
}
diff --git a/drivers/net/ipg.c b/drivers/net/ipg.c
index 72e3d2da9e9f..dc0198092343 100644
--- a/drivers/net/ipg.c
+++ b/drivers/net/ipg.c
@@ -1213,7 +1213,7 @@ static void ipg_nic_rx_with_start_and_end(struct net_device *dev,
skb_put(skb, framelen);
skb->protocol = eth_type_trans(skb, dev);
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
netif_rx(skb);
sp->rx_buff[entry] = NULL;
}
@@ -1278,7 +1278,7 @@ static void ipg_nic_rx_with_end(struct net_device *dev,
jumbo->skb->protocol =
eth_type_trans(jumbo->skb, dev);
- jumbo->skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(jumbo->skb);
netif_rx(jumbo->skb);
}
}
@@ -1476,7 +1476,7 @@ static int ipg_nic_rx(struct net_device *dev)
* IP/TCP/UDP frame was received. Let the
* upper layer decide.
*/
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
/* Hand off frame for higher layer processing.
* The function netif_rx() releases the sk_buff
diff --git a/drivers/net/irda/donauboe.c b/drivers/net/irda/donauboe.c
index 48bd5ec9f29b..b626cccbccd1 100644
--- a/drivers/net/irda/donauboe.c
+++ b/drivers/net/irda/donauboe.c
@@ -217,7 +217,7 @@ toshoboe_checkfcs (unsigned char *buf, int len)
for (i = 0; i < len; ++i)
fcs.value = irda_fcs (fcs.value, *(buf++));
- return (fcs.value == GOOD_FCS);
+ return fcs.value == GOOD_FCS;
}
/***********************************************************************/
@@ -759,7 +759,7 @@ toshoboe_maketestpacket (unsigned char *buf, int badcrc, int fir)
if (fir)
{
memset (buf, 0, TT_LEN);
- return (TT_LEN);
+ return TT_LEN;
}
fcs.value = INIT_FCS;
diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
index 4441fa3389c2..e4ea61944c22 100644
--- a/drivers/net/irda/irda-usb.c
+++ b/drivers/net/irda/irda-usb.c
@@ -1124,11 +1124,11 @@ static int stir421x_patch_device(struct irda_usb_cb *self)
* The actual image starts after the "STMP" keyword
* so forward to the firmware header tag
*/
- for (i = 0; (fw->data[i] != STIR421X_PATCH_END_OF_HDR_TAG) &&
- (i < fw->size); i++) ;
+ for (i = 0; i < fw->size && fw->data[i] !=
+ STIR421X_PATCH_END_OF_HDR_TAG; i++) ;
/* here we check for the out of buffer case */
- if ((STIR421X_PATCH_END_OF_HDR_TAG == fw->data[i]) &&
- (i < STIR421X_PATCH_CODE_OFFSET)) {
+ if (i < STIR421X_PATCH_CODE_OFFSET && i < fw->size &&
+ STIR421X_PATCH_END_OF_HDR_TAG == fw->data[i]) {
if (!memcmp(fw->data + i + 1, STIR421X_PATCH_STMP_TAG,
sizeof(STIR421X_PATCH_STMP_TAG) - 1)) {
@@ -1514,7 +1514,7 @@ static inline int irda_usb_parse_endpoints(struct irda_usb_cb *self, struct usb_
IRDA_DEBUG(0, "%s(), And our endpoints are : in=%02X, out=%02X (%d), int=%02X\n",
__func__, self->bulk_in_ep, self->bulk_out_ep, self->bulk_out_mtu, self->bulk_int_ep);
- return((self->bulk_in_ep != 0) && (self->bulk_out_ep != 0));
+ return (self->bulk_in_ep != 0) && (self->bulk_out_ep != 0);
}
#ifdef IU_DUMP_CLASS_DESC
diff --git a/drivers/net/irda/mcs7780.c b/drivers/net/irda/mcs7780.c
index 5b1036ac38d7..74b20f179cea 100644
--- a/drivers/net/irda/mcs7780.c
+++ b/drivers/net/irda/mcs7780.c
@@ -734,7 +734,7 @@ static int mcs_net_open(struct net_device *netdev)
}
if (!mcs_setup_urbs(mcs))
- goto error3;
+ goto error3;
ret = mcs_receive_start(mcs);
if (ret)
diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c
index e30cdbb14745..559fe854d76d 100644
--- a/drivers/net/irda/nsc-ircc.c
+++ b/drivers/net/irda/nsc-ircc.c
@@ -1348,7 +1348,7 @@ static __u8 nsc_ircc_change_speed(struct nsc_ircc_cb *self, __u32 speed)
outb(bank, iobase+BSR);
/* Make sure interrupt handlers keep the proper interrupt mask */
- return(ier);
+ return ier;
}
/*
diff --git a/drivers/net/irda/sir_dev.c b/drivers/net/irda/sir_dev.c
index 1b051dab7b29..efe05bb34dd8 100644
--- a/drivers/net/irda/sir_dev.c
+++ b/drivers/net/irda/sir_dev.c
@@ -336,7 +336,7 @@ static int sirdev_is_receiving(struct sir_dev *dev)
if (!atomic_read(&dev->enable_rx))
return 0;
- return (dev->rx_buff.state != OUTSIDE_FRAME);
+ return dev->rx_buff.state != OUTSIDE_FRAME;
}
int sirdev_set_dongle(struct sir_dev *dev, IRDA_DONGLE type)
@@ -909,7 +909,7 @@ struct sir_dev * sirdev_get_instance(const struct sir_driver *drv, const char *n
dev->tx_skb = NULL;
spin_lock_init(&dev->tx_lock);
- init_MUTEX(&dev->fsm.sem);
+ sema_init(&dev->fsm.sem, 1);
dev->drv = drv;
dev->netdev = ndev;
diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c
index 850ca1c5ee19..8c57bfb5f098 100644
--- a/drivers/net/irda/smsc-ircc2.c
+++ b/drivers/net/irda/smsc-ircc2.c
@@ -2051,7 +2051,7 @@ static int smsc_ircc_sir_write(int iobase, int fifo_size, __u8 *buf, int len)
*/
static int smsc_ircc_is_receiving(struct smsc_ircc_cb *self)
{
- return (self->rx_buff.state != OUTSIDE_FRAME);
+ return self->rx_buff.state != OUTSIDE_FRAME;
}
diff --git a/drivers/net/irda/stir4200.c b/drivers/net/irda/stir4200.c
index e5698fa30a4f..41c96b3d8152 100644
--- a/drivers/net/irda/stir4200.c
+++ b/drivers/net/irda/stir4200.c
@@ -219,7 +219,7 @@ static inline int read_reg(struct stir_cb *stir, __u16 reg,
static inline int isfir(u32 speed)
{
- return (speed == 4000000);
+ return speed == 4000000;
}
/*
diff --git a/drivers/net/irda/via-ircc.c b/drivers/net/irda/via-ircc.c
index b0a6cd815be1..67c0ad42d818 100644
--- a/drivers/net/irda/via-ircc.c
+++ b/drivers/net/irda/via-ircc.c
@@ -1182,12 +1182,13 @@ F01_E */
skb = dev_alloc_skb(len + 1 - 4);
/*
- * if frame size,data ptr,or skb ptr are wrong ,the get next
+ * if frame size, data ptr, or skb ptr are wrong, then get next
* entry.
*/
if ((skb == NULL) || (skb->data == NULL) ||
(self->rx_buff.data == NULL) || (len < 6)) {
self->netdev->stats.rx_dropped++;
+ kfree_skb(skb);
return TRUE;
}
skb_reserve(skb, 1);
diff --git a/drivers/net/irda/via-ircc.h b/drivers/net/irda/via-ircc.h
index 5a84822b5a43..c6f58482b769 100644
--- a/drivers/net/irda/via-ircc.h
+++ b/drivers/net/irda/via-ircc.h
@@ -238,7 +238,7 @@ static void WriteLPCReg(int iRegNum, unsigned char iVal)
static __u8 ReadReg(unsigned int BaseAddr, int iRegNum)
{
- return ((__u8) inb(BaseAddr + iRegNum));
+ return (__u8) inb(BaseAddr + iRegNum);
}
static void WriteReg(unsigned int BaseAddr, int iRegNum, unsigned char iVal)
diff --git a/drivers/net/irda/vlsi_ir.h b/drivers/net/irda/vlsi_ir.h
index 3f24a1f33022..d66fab854bf1 100644
--- a/drivers/net/irda/vlsi_ir.h
+++ b/drivers/net/irda/vlsi_ir.h
@@ -595,7 +595,7 @@ struct ring_descr {
static inline int rd_is_active(struct ring_descr *rd)
{
- return ((rd->hw->rd_status & RD_ACTIVE) != 0);
+ return (rd->hw->rd_status & RD_ACTIVE) != 0;
}
static inline void rd_activate(struct ring_descr *rd)
diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c
index ba1de5973fb2..8df645e78f2e 100644
--- a/drivers/net/iseries_veth.c
+++ b/drivers/net/iseries_veth.c
@@ -1524,7 +1524,7 @@ static void veth_receive(struct veth_lpar_connection *cnx,
skb_put(skb, length);
skb->protocol = eth_type_trans(skb, dev);
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
netif_rx(skb); /* send it up */
dev->stats.rx_packets++;
dev->stats.rx_bytes += length;
diff --git a/drivers/net/ixgb/ixgb_ee.c b/drivers/net/ixgb/ixgb_ee.c
index 813993f9c65c..c982ab9f9005 100644
--- a/drivers/net/ixgb/ixgb_ee.c
+++ b/drivers/net/ixgb/ixgb_ee.c
@@ -296,12 +296,12 @@ ixgb_wait_eeprom_command(struct ixgb_hw *hw)
eecd_reg = IXGB_READ_REG(hw, EECD);
if (eecd_reg & IXGB_EECD_DO)
- return (true);
+ return true;
udelay(50);
}
ASSERT(0);
- return (false);
+ return false;
}
/******************************************************************************
@@ -327,9 +327,9 @@ ixgb_validate_eeprom_checksum(struct ixgb_hw *hw)
checksum += ixgb_read_eeprom(hw, i);
if (checksum == (u16) EEPROM_SUM)
- return (true);
+ return true;
else
- return (false);
+ return false;
}
/******************************************************************************
@@ -439,7 +439,7 @@ ixgb_read_eeprom(struct ixgb_hw *hw,
/* End this read operation */
ixgb_standby_eeprom(hw);
- return (data);
+ return data;
}
/******************************************************************************
@@ -476,16 +476,16 @@ ixgb_get_eeprom_data(struct ixgb_hw *hw)
/* clear the init_ctrl_reg_1 to signify that the cache is
* invalidated */
ee_map->init_ctrl_reg_1 = cpu_to_le16(EEPROM_ICW1_SIGNATURE_CLEAR);
- return (false);
+ return false;
}
if ((ee_map->init_ctrl_reg_1 & cpu_to_le16(EEPROM_ICW1_SIGNATURE_MASK))
!= cpu_to_le16(EEPROM_ICW1_SIGNATURE_VALID)) {
pr_debug("Signature invalid\n");
- return(false);
+ return false;
}
- return(true);
+ return true;
}
/******************************************************************************
@@ -505,7 +505,7 @@ ixgb_check_and_get_eeprom_data (struct ixgb_hw* hw)
if ((ee_map->init_ctrl_reg_1 & cpu_to_le16(EEPROM_ICW1_SIGNATURE_MASK))
== cpu_to_le16(EEPROM_ICW1_SIGNATURE_VALID)) {
- return (true);
+ return true;
} else {
return ixgb_get_eeprom_data(hw);
}
@@ -526,10 +526,10 @@ ixgb_get_eeprom_word(struct ixgb_hw *hw, u16 index)
if ((index < IXGB_EEPROM_SIZE) &&
(ixgb_check_and_get_eeprom_data(hw) == true)) {
- return(hw->eeprom[index]);
+ return hw->eeprom[index];
}
- return(0);
+ return 0;
}
/******************************************************************************
@@ -570,10 +570,10 @@ u32
ixgb_get_ee_pba_number(struct ixgb_hw *hw)
{
if (ixgb_check_and_get_eeprom_data(hw) == true)
- return (le16_to_cpu(hw->eeprom[EEPROM_PBA_1_2_REG])
- | (le16_to_cpu(hw->eeprom[EEPROM_PBA_3_4_REG])<<16));
+ return le16_to_cpu(hw->eeprom[EEPROM_PBA_1_2_REG])
+ | (le16_to_cpu(hw->eeprom[EEPROM_PBA_3_4_REG])<<16);
- return(0);
+ return 0;
}
@@ -591,8 +591,8 @@ ixgb_get_ee_device_id(struct ixgb_hw *hw)
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
if (ixgb_check_and_get_eeprom_data(hw) == true)
- return (le16_to_cpu(ee_map->device_id));
+ return le16_to_cpu(ee_map->device_id);
- return (0);
+ return 0;
}
diff --git a/drivers/net/ixgb/ixgb_ethtool.c b/drivers/net/ixgb/ixgb_ethtool.c
index a4ed96caae69..43994c199991 100644
--- a/drivers/net/ixgb/ixgb_ethtool.c
+++ b/drivers/net/ixgb/ixgb_ethtool.c
@@ -410,7 +410,7 @@ static int
ixgb_get_eeprom_len(struct net_device *netdev)
{
/* return size in bytes */
- return (IXGB_EEPROM_SIZE << 1);
+ return IXGB_EEPROM_SIZE << 1;
}
static int
diff --git a/drivers/net/ixgb/ixgb_hw.c b/drivers/net/ixgb/ixgb_hw.c
index 397acabccab6..6cb2e42ff4c1 100644
--- a/drivers/net/ixgb/ixgb_hw.c
+++ b/drivers/net/ixgb/ixgb_hw.c
@@ -167,7 +167,7 @@ ixgb_adapter_stop(struct ixgb_hw *hw)
/* Clear any pending interrupt events. */
icr_reg = IXGB_READ_REG(hw, ICR);
- return (ctrl_reg & IXGB_CTRL0_RST);
+ return ctrl_reg & IXGB_CTRL0_RST;
}
@@ -209,7 +209,7 @@ ixgb_identify_xpak_vendor(struct ixgb_hw *hw)
xpak_vendor = ixgb_xpak_vendor_infineon;
}
- return (xpak_vendor);
+ return xpak_vendor;
}
/******************************************************************************
@@ -273,7 +273,7 @@ ixgb_identify_phy(struct ixgb_hw *hw)
if (hw->subsystem_vendor_id == SUN_SUBVENDOR_ID)
phy_type = ixgb_phy_type_bcm;
- return (phy_type);
+ return phy_type;
}
/******************************************************************************
@@ -366,7 +366,7 @@ ixgb_init_hw(struct ixgb_hw *hw)
/* 82597EX errata: Call check-for-link in case lane deskew is locked */
ixgb_check_for_link(hw);
- return (status);
+ return status;
}
/******************************************************************************
@@ -531,7 +531,7 @@ ixgb_hash_mc_addr(struct ixgb_hw *hw,
}
hash_value &= 0xFFF;
- return (hash_value);
+ return hash_value;
}
/******************************************************************************
@@ -715,7 +715,7 @@ ixgb_setup_fc(struct ixgb_hw *hw)
}
IXGB_WRITE_REG(hw, FCRTH, hw->fc.high_water);
}
- return (status);
+ return status;
}
/******************************************************************************
@@ -1140,7 +1140,7 @@ mac_addr_valid(u8 *mac_addr)
pr_debug("MAC address is all zeros\n");
is_valid = false;
}
- return (is_valid);
+ return is_valid;
}
/******************************************************************************
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
index 45fc89b9ba64..666207a9c039 100644
--- a/drivers/net/ixgb/ixgb_main.c
+++ b/drivers/net/ixgb/ixgb_main.c
@@ -446,8 +446,10 @@ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
NETIF_F_HW_VLAN_FILTER;
netdev->features |= NETIF_F_TSO;
- if (pci_using_dac)
+ if (pci_using_dac) {
netdev->features |= NETIF_F_HIGHDMA;
+ netdev->vlan_features |= NETIF_F_HIGHDMA;
+ }
/* make sure the EEPROM is good */
@@ -470,7 +472,7 @@ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
adapter->part_num = ixgb_get_ee_pba_number(&adapter->hw);
init_timer(&adapter->watchdog_timer);
- adapter->watchdog_timer.function = &ixgb_watchdog;
+ adapter->watchdog_timer.function = ixgb_watchdog;
adapter->watchdog_timer.data = (unsigned long)adapter;
INIT_WORK(&adapter->tx_timeout_task, ixgb_tx_timeout_task);
@@ -1905,7 +1907,7 @@ ixgb_rx_checksum(struct ixgb_adapter *adapter,
*/
if ((rx_desc->status & IXGB_RX_DESC_STATUS_IXSM) ||
(!(rx_desc->status & IXGB_RX_DESC_STATUS_TCPCS))) {
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
return;
}
@@ -1913,7 +1915,7 @@ ixgb_rx_checksum(struct ixgb_adapter *adapter,
/* now look at the TCP checksum error bit */
if (rx_desc->errors & IXGB_RX_DESC_ERRORS_TCPE) {
/* let the stack verify checksum errors */
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
adapter->hw_csum_rx_error++;
} else {
/* TCP checksum is good */
@@ -2221,7 +2223,7 @@ ixgb_restore_vlan(struct ixgb_adapter *adapter)
if (adapter->vlgrp) {
u16 vid;
- for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
+ for (vid = 0; vid < VLAN_N_VID; vid++) {
if (!vlan_group_get_device(adapter->vlgrp, vid))
continue;
ixgb_vlan_rx_add_vid(adapter->netdev, vid);
diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h
index 9e15eb93860e..ed8703cfffb7 100644
--- a/drivers/net/ixgbe/ixgbe.h
+++ b/drivers/net/ixgbe/ixgbe.h
@@ -28,10 +28,13 @@
#ifndef _IXGBE_H_
#define _IXGBE_H_
+#include <linux/bitops.h>
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/netdevice.h>
+#include <linux/cpumask.h>
#include <linux/aer.h>
+#include <linux/if_vlan.h>
#include "ixgbe_type.h"
#include "ixgbe_common.h"
@@ -69,15 +72,20 @@
#define IXGBE_MAX_FCPAUSE 0xFFFF
/* Supported Rx Buffer Sizes */
-#define IXGBE_RXBUFFER_64 64 /* Used for packet split */
-#define IXGBE_RXBUFFER_128 128 /* Used for packet split */
-#define IXGBE_RXBUFFER_256 256 /* Used for packet split */
+#define IXGBE_RXBUFFER_512 512 /* Used for packet split */
#define IXGBE_RXBUFFER_2048 2048
#define IXGBE_RXBUFFER_4096 4096
#define IXGBE_RXBUFFER_8192 8192
#define IXGBE_MAX_RXBUFFER 16384 /* largest size for a single descriptor */
-#define IXGBE_RX_HDR_SIZE IXGBE_RXBUFFER_256
+/*
+ * NOTE: netdev_alloc_skb reserves up to 64 bytes, NET_IP_ALIGN mans we
+ * reserve 2 more, and skb_shared_info adds an additional 384 bytes more,
+ * this adds up to 512 bytes of extra data meaning the smallest allocation
+ * we could have is 1K.
+ * i.e. RXBUFFER_512 --> size-1024 slab
+ */
+#define IXGBE_RX_HDR_SIZE IXGBE_RXBUFFER_512
#define MAXIMUM_ETHERNET_VLAN_SIZE (ETH_FRAME_LEN + ETH_FCS_LEN + VLAN_HLEN)
@@ -174,8 +182,9 @@ struct ixgbe_ring {
*/
struct ixgbe_queue_stats stats;
- unsigned long reinit_state;
+ struct u64_stats_sync syncp;
int numa_node;
+ unsigned long reinit_state;
u64 rsc_count; /* stat for coalesced packets */
u64 rsc_flush; /* stats for flushed packets */
u32 restart_queue; /* track tx queue restarts */
@@ -236,6 +245,7 @@ struct ixgbe_q_vector {
u8 tx_itr;
u8 rx_itr;
u32 eitr;
+ cpumask_var_t affinity_mask;
};
/* Helper macros to switch between ints/sec and what the register uses.
@@ -251,11 +261,11 @@ struct ixgbe_q_vector {
(R)->next_to_clean - (R)->next_to_use - 1)
#define IXGBE_RX_DESC_ADV(R, i) \
- (&(((union ixgbe_adv_rx_desc *)((R).desc))[i]))
+ (&(((union ixgbe_adv_rx_desc *)((R)->desc))[i]))
#define IXGBE_TX_DESC_ADV(R, i) \
- (&(((union ixgbe_adv_tx_desc *)((R).desc))[i]))
+ (&(((union ixgbe_adv_tx_desc *)((R)->desc))[i]))
#define IXGBE_TX_CTXTDESC_ADV(R, i) \
- (&(((struct ixgbe_adv_tx_context_desc *)((R).desc))[i]))
+ (&(((struct ixgbe_adv_tx_context_desc *)((R)->desc))[i]))
#define IXGBE_MAX_JUMBO_FRAME_SIZE 16128
#ifdef IXGBE_FCOE
@@ -280,7 +290,7 @@ struct ixgbe_q_vector {
/* board specific private data structure */
struct ixgbe_adapter {
struct timer_list watchdog_timer;
- struct vlan_group *vlgrp;
+ unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
u16 bd_number;
struct work_struct reset_task;
struct ixgbe_q_vector *q_vector[MAX_MSIX_Q_VECTORS];
@@ -448,9 +458,20 @@ extern int ixgbe_setup_rx_resources(struct ixgbe_adapter *, struct ixgbe_ring *)
extern int ixgbe_setup_tx_resources(struct ixgbe_adapter *, struct ixgbe_ring *);
extern void ixgbe_free_rx_resources(struct ixgbe_adapter *, struct ixgbe_ring *);
extern void ixgbe_free_tx_resources(struct ixgbe_adapter *, struct ixgbe_ring *);
+extern void ixgbe_configure_rx_ring(struct ixgbe_adapter *,struct ixgbe_ring *);
+extern void ixgbe_configure_tx_ring(struct ixgbe_adapter *,struct ixgbe_ring *);
extern void ixgbe_update_stats(struct ixgbe_adapter *adapter);
extern int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter);
extern void ixgbe_clear_interrupt_scheme(struct ixgbe_adapter *adapter);
+extern netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *,
+ struct net_device *,
+ struct ixgbe_adapter *,
+ struct ixgbe_ring *);
+extern void ixgbe_unmap_and_free_tx_resource(struct ixgbe_adapter *,
+ struct ixgbe_tx_buffer *);
+extern void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter,
+ struct ixgbe_ring *rx_ring,
+ int cleaned_count);
extern void ixgbe_write_eitr(struct ixgbe_q_vector *);
extern int ethtool_ioctl(struct ifreq *ifr);
extern s32 ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw);
diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c
index 3e06a61da921..0bd8fbb5bfd0 100644
--- a/drivers/net/ixgbe/ixgbe_82599.c
+++ b/drivers/net/ixgbe/ixgbe_82599.c
@@ -39,20 +39,20 @@
#define IXGBE_82599_MC_TBL_SIZE 128
#define IXGBE_82599_VFT_TBL_SIZE 128
-void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
-void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
-void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
-s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
- ixgbe_link_speed speed,
- bool autoneg,
- bool autoneg_wait_to_complete);
+static void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
+static void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
+static void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
+static s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
+ ixgbe_link_speed speed,
+ bool autoneg,
+ bool autoneg_wait_to_complete);
static s32 ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw *hw,
ixgbe_link_speed speed,
bool autoneg,
bool autoneg_wait_to_complete);
-s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw,
- bool autoneg_wait_to_complete);
-s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,
+static s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw,
+ bool autoneg_wait_to_complete);
+static s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,
ixgbe_link_speed speed,
bool autoneg,
bool autoneg_wait_to_complete);
@@ -369,7 +369,7 @@ out:
* Configures link settings based on values in the ixgbe_hw struct.
* Restarts the link. Performs autonegotiation if needed.
**/
-s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw,
+static s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw,
bool autoneg_wait_to_complete)
{
u32 autoc_reg;
@@ -418,7 +418,7 @@ s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw,
* PHY states. This includes selectively shutting down the Tx
* laser on the PHY, effectively halting physical link.
**/
-void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
+static void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
{
u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
@@ -437,7 +437,7 @@ void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
* PHY states. This includes selectively turning on the Tx
* laser on the PHY, effectively starting physical link.
**/
-void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
+static void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
{
u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
@@ -460,7 +460,7 @@ void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
* end. This is consistent with true clause 37 autoneg, which also
* involves a loss of signal.
**/
-void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
+static void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
{
hw_dbg(hw, "ixgbe_flap_tx_laser_multispeed_fiber\n");
@@ -729,7 +729,7 @@ out:
*
* Set the link speed in the AUTOC register and restarts link.
**/
-s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,
+static s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,
ixgbe_link_speed speed, bool autoneg,
bool autoneg_wait_to_complete)
{
@@ -1415,92 +1415,6 @@ s32 ixgbe_atr_set_dst_ipv4_82599(struct ixgbe_atr_input *input, u32 dst_addr)
}
/**
- * ixgbe_atr_set_src_ipv6_82599 - Sets the source IPv6 address
- * @input: input stream to modify
- * @src_addr_1: the first 4 bytes of the IP address to load
- * @src_addr_2: the second 4 bytes of the IP address to load
- * @src_addr_3: the third 4 bytes of the IP address to load
- * @src_addr_4: the fourth 4 bytes of the IP address to load
- **/
-s32 ixgbe_atr_set_src_ipv6_82599(struct ixgbe_atr_input *input,
- u32 src_addr_1, u32 src_addr_2,
- u32 src_addr_3, u32 src_addr_4)
-{
- input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET] = src_addr_4 & 0xff;
- input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 1] =
- (src_addr_4 >> 8) & 0xff;
- input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 2] =
- (src_addr_4 >> 16) & 0xff;
- input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 3] = src_addr_4 >> 24;
-
- input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 4] = src_addr_3 & 0xff;
- input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 5] =
- (src_addr_3 >> 8) & 0xff;
- input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 6] =
- (src_addr_3 >> 16) & 0xff;
- input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 7] = src_addr_3 >> 24;
-
- input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 8] = src_addr_2 & 0xff;
- input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 9] =
- (src_addr_2 >> 8) & 0xff;
- input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 10] =
- (src_addr_2 >> 16) & 0xff;
- input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 11] = src_addr_2 >> 24;
-
- input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 12] = src_addr_1 & 0xff;
- input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 13] =
- (src_addr_1 >> 8) & 0xff;
- input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 14] =
- (src_addr_1 >> 16) & 0xff;
- input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 15] = src_addr_1 >> 24;
-
- return 0;
-}
-
-/**
- * ixgbe_atr_set_dst_ipv6_82599 - Sets the destination IPv6 address
- * @input: input stream to modify
- * @dst_addr_1: the first 4 bytes of the IP address to load
- * @dst_addr_2: the second 4 bytes of the IP address to load
- * @dst_addr_3: the third 4 bytes of the IP address to load
- * @dst_addr_4: the fourth 4 bytes of the IP address to load
- **/
-s32 ixgbe_atr_set_dst_ipv6_82599(struct ixgbe_atr_input *input,
- u32 dst_addr_1, u32 dst_addr_2,
- u32 dst_addr_3, u32 dst_addr_4)
-{
- input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET] = dst_addr_4 & 0xff;
- input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 1] =
- (dst_addr_4 >> 8) & 0xff;
- input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 2] =
- (dst_addr_4 >> 16) & 0xff;
- input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 3] = dst_addr_4 >> 24;
-
- input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 4] = dst_addr_3 & 0xff;
- input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 5] =
- (dst_addr_3 >> 8) & 0xff;
- input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 6] =
- (dst_addr_3 >> 16) & 0xff;
- input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 7] = dst_addr_3 >> 24;
-
- input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 8] = dst_addr_2 & 0xff;
- input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 9] =
- (dst_addr_2 >> 8) & 0xff;
- input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 10] =
- (dst_addr_2 >> 16) & 0xff;
- input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 11] = dst_addr_2 >> 24;
-
- input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 12] = dst_addr_1 & 0xff;
- input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 13] =
- (dst_addr_1 >> 8) & 0xff;
- input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 14] =
- (dst_addr_1 >> 16) & 0xff;
- input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 15] = dst_addr_1 >> 24;
-
- return 0;
-}
-
-/**
* ixgbe_atr_set_src_port_82599 - Sets the source port
* @input: input stream to modify
* @src_port: the source port to load
@@ -1540,19 +1454,6 @@ s32 ixgbe_atr_set_flex_byte_82599(struct ixgbe_atr_input *input, u16 flex_byte)
}
/**
- * ixgbe_atr_set_vm_pool_82599 - Sets the Virtual Machine pool
- * @input: input stream to modify
- * @vm_pool: the Virtual Machine pool to load
- **/
-s32 ixgbe_atr_set_vm_pool_82599(struct ixgbe_atr_input *input,
- u8 vm_pool)
-{
- input->byte_stream[IXGBE_ATR_VM_POOL_OFFSET] = vm_pool;
-
- return 0;
-}
-
-/**
* ixgbe_atr_set_l4type_82599 - Sets the layer 4 packet type
* @input: input stream to modify
* @l4type: the layer 4 type value to load
@@ -1645,41 +1546,6 @@ static s32 ixgbe_atr_get_src_ipv6_82599(struct ixgbe_atr_input *input,
}
/**
- * ixgbe_atr_get_dst_ipv6_82599 - Gets the destination IPv6 address
- * @input: input stream to search
- * @dst_addr_1: the first 4 bytes of the IP address to load
- * @dst_addr_2: the second 4 bytes of the IP address to load
- * @dst_addr_3: the third 4 bytes of the IP address to load
- * @dst_addr_4: the fourth 4 bytes of the IP address to load
- **/
-s32 ixgbe_atr_get_dst_ipv6_82599(struct ixgbe_atr_input *input,
- u32 *dst_addr_1, u32 *dst_addr_2,
- u32 *dst_addr_3, u32 *dst_addr_4)
-{
- *dst_addr_1 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 12];
- *dst_addr_1 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 13] << 8;
- *dst_addr_1 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 14] << 16;
- *dst_addr_1 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 15] << 24;
-
- *dst_addr_2 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 8];
- *dst_addr_2 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 9] << 8;
- *dst_addr_2 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 10] << 16;
- *dst_addr_2 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 11] << 24;
-
- *dst_addr_3 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 4];
- *dst_addr_3 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 5] << 8;
- *dst_addr_3 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 6] << 16;
- *dst_addr_3 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 7] << 24;
-
- *dst_addr_4 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET];
- *dst_addr_4 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 1] << 8;
- *dst_addr_4 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 2] << 16;
- *dst_addr_4 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 3] << 24;
-
- return 0;
-}
-
-/**
* ixgbe_atr_get_src_port_82599 - Gets the source port
* @input: input stream to modify
* @src_port: the source port to load
@@ -1732,19 +1598,6 @@ static s32 ixgbe_atr_get_flex_byte_82599(struct ixgbe_atr_input *input,
}
/**
- * ixgbe_atr_get_vm_pool_82599 - Gets the Virtual Machine pool
- * @input: input stream to modify
- * @vm_pool: the Virtual Machine pool to load
- **/
-s32 ixgbe_atr_get_vm_pool_82599(struct ixgbe_atr_input *input,
- u8 *vm_pool)
-{
- *vm_pool = input->byte_stream[IXGBE_ATR_VM_POOL_OFFSET];
-
- return 0;
-}
-
-/**
* ixgbe_atr_get_l4type_82599 - Gets the layer 4 packet type
* @input: input stream to modify
* @l4type: the layer 4 type value to load
@@ -1910,56 +1763,27 @@ s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw,
(dst_port << IXGBE_FDIRPORT_DESTINATION_SHIFT)));
/*
- * Program the relevant mask registers. If src/dst_port or src/dst_addr
- * are zero, then assume a full mask for that field. Also assume that
- * a VLAN of 0 is unspecified, so mask that out as well. L4type
- * cannot be masked out in this implementation.
+ * Program the relevant mask registers. L4type cannot be
+ * masked out in this implementation.
*
* This also assumes IPv4 only. IPv6 masking isn't supported at this
* point in time.
*/
- if (src_ipv4 == 0)
- IXGBE_WRITE_REG(hw, IXGBE_FDIRSIP4M, 0xffffffff);
- else
- IXGBE_WRITE_REG(hw, IXGBE_FDIRSIP4M, input_masks->src_ip_mask);
-
- if (dst_ipv4 == 0)
- IXGBE_WRITE_REG(hw, IXGBE_FDIRDIP4M, 0xffffffff);
- else
- IXGBE_WRITE_REG(hw, IXGBE_FDIRDIP4M, input_masks->dst_ip_mask);
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRSIP4M, input_masks->src_ip_mask);
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRDIP4M, input_masks->dst_ip_mask);
switch (l4type & IXGBE_ATR_L4TYPE_MASK) {
case IXGBE_ATR_L4TYPE_TCP:
- if (src_port == 0)
- IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, 0xffff);
- else
- IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM,
- input_masks->src_port_mask);
-
- if (dst_port == 0)
- IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM,
- (IXGBE_READ_REG(hw, IXGBE_FDIRTCPM) |
- (0xffff << 16)));
- else
- IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM,
- (IXGBE_READ_REG(hw, IXGBE_FDIRTCPM) |
- (input_masks->dst_port_mask << 16)));
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, input_masks->src_port_mask);
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM,
+ (IXGBE_READ_REG(hw, IXGBE_FDIRTCPM) |
+ (input_masks->dst_port_mask << 16)));
break;
case IXGBE_ATR_L4TYPE_UDP:
- if (src_port == 0)
- IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM, 0xffff);
- else
- IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM,
- input_masks->src_port_mask);
-
- if (dst_port == 0)
- IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM,
- (IXGBE_READ_REG(hw, IXGBE_FDIRUDPM) |
- (0xffff << 16)));
- else
- IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM,
- (IXGBE_READ_REG(hw, IXGBE_FDIRUDPM) |
- (input_masks->src_port_mask << 16)));
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM, input_masks->src_port_mask);
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM,
+ (IXGBE_READ_REG(hw, IXGBE_FDIRUDPM) |
+ (input_masks->src_port_mask << 16)));
break;
default:
/* this already would have failed above */
@@ -1967,11 +1791,11 @@ s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw,
}
/* Program the last mask register, FDIRM */
- if (input_masks->vlan_id_mask || !vlan_id)
+ if (input_masks->vlan_id_mask)
/* Mask both VLAN and VLANP - bits 0 and 1 */
fdirm |= 0x3;
- if (input_masks->data_mask || !flex_bytes)
+ if (input_masks->data_mask)
/* Flex bytes need masking, so mask the whole thing - bit 4 */
fdirm |= 0x10;
diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c
index 9595b1bfb8dd..e3eca1316389 100644
--- a/drivers/net/ixgbe/ixgbe_common.c
+++ b/drivers/net/ixgbe/ixgbe_common.c
@@ -52,6 +52,7 @@ static void ixgbe_disable_rar(struct ixgbe_hw *hw, u32 index);
static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr);
static void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq);
static s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num);
+static s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg);
/**
* ixgbe_start_hw_generic - Prepare hardware for Tx/Rx
@@ -637,7 +638,7 @@ out:
* Polls the status bit (bit 1) of the EERD or EEWR to determine when the
* read or write is done respectively.
**/
-s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg)
+static s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg)
{
u32 i;
u32 reg;
@@ -2449,7 +2450,7 @@ s32 ixgbe_init_uta_tables_generic(struct ixgbe_hw *hw)
* return the VLVF index where this VLAN id should be placed
*
**/
-s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan)
+static s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan)
{
u32 bits = 0;
u32 first_empty_slot = 0;
@@ -2704,48 +2705,3 @@ s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
return 0;
}
-
-/**
- * ixgbe_get_wwn_prefix_generic - Get alternative WWNN/WWPN prefix from
- * the EEPROM
- * @hw: pointer to hardware structure
- * @wwnn_prefix: the alternative WWNN prefix
- * @wwpn_prefix: the alternative WWPN prefix
- *
- * This function will read the EEPROM from the alternative SAN MAC address
- * block to check the support for the alternative WWNN/WWPN prefix support.
- **/
-s32 ixgbe_get_wwn_prefix_generic(struct ixgbe_hw *hw, u16 *wwnn_prefix,
- u16 *wwpn_prefix)
-{
- u16 offset, caps;
- u16 alt_san_mac_blk_offset;
-
- /* clear output first */
- *wwnn_prefix = 0xFFFF;
- *wwpn_prefix = 0xFFFF;
-
- /* check if alternative SAN MAC is supported */
- hw->eeprom.ops.read(hw, IXGBE_ALT_SAN_MAC_ADDR_BLK_PTR,
- &alt_san_mac_blk_offset);
-
- if ((alt_san_mac_blk_offset == 0) ||
- (alt_san_mac_blk_offset == 0xFFFF))
- goto wwn_prefix_out;
-
- /* check capability in alternative san mac address block */
- offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_CAPS_OFFSET;
- hw->eeprom.ops.read(hw, offset, &caps);
- if (!(caps & IXGBE_ALT_SAN_MAC_ADDR_CAPS_ALTWWN))
- goto wwn_prefix_out;
-
- /* get the corresponding prefix for WWNN/WWPN */
- offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWNN_OFFSET;
- hw->eeprom.ops.read(hw, offset, wwnn_prefix);
-
- offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWPN_OFFSET;
- hw->eeprom.ops.read(hw, offset, wwpn_prefix);
-
-wwn_prefix_out:
- return 0;
-}
diff --git a/drivers/net/ixgbe/ixgbe_common.h b/drivers/net/ixgbe/ixgbe_common.h
index 5cf15aa11cac..424c223437dc 100644
--- a/drivers/net/ixgbe/ixgbe_common.h
+++ b/drivers/net/ixgbe/ixgbe_common.h
@@ -52,7 +52,6 @@ s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw,
u16 *checksum_val);
s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw);
-s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg);
s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq,
u32 enable_addr);
diff --git a/drivers/net/ixgbe/ixgbe_dcb.c b/drivers/net/ixgbe/ixgbe_dcb.c
index 9aea4f04bbd2..8bb9ddb6dffe 100644
--- a/drivers/net/ixgbe/ixgbe_dcb.c
+++ b/drivers/net/ixgbe/ixgbe_dcb.c
@@ -34,98 +34,6 @@
#include "ixgbe_dcb_82599.h"
/**
- * ixgbe_dcb_config - Struct containing DCB settings.
- * @dcb_config: Pointer to DCB config structure
- *
- * This function checks DCB rules for DCB settings.
- * The following rules are checked:
- * 1. The sum of bandwidth percentages of all Bandwidth Groups must total 100%.
- * 2. The sum of bandwidth percentages of all Traffic Classes within a Bandwidth
- * Group must total 100.
- * 3. A Traffic Class should not be set to both Link Strict Priority
- * and Group Strict Priority.
- * 4. Link strict Bandwidth Groups can only have link strict traffic classes
- * with zero bandwidth.
- */
-s32 ixgbe_dcb_check_config(struct ixgbe_dcb_config *dcb_config)
-{
- struct tc_bw_alloc *p;
- s32 ret_val = 0;
- u8 i, j, bw = 0, bw_id;
- u8 bw_sum[2][MAX_BW_GROUP];
- bool link_strict[2][MAX_BW_GROUP];
-
- memset(bw_sum, 0, sizeof(bw_sum));
- memset(link_strict, 0, sizeof(link_strict));
-
- /* First Tx, then Rx */
- for (i = 0; i < 2; i++) {
- /* Check each traffic class for rule violation */
- for (j = 0; j < MAX_TRAFFIC_CLASS; j++) {
- p = &dcb_config->tc_config[j].path[i];
-
- bw = p->bwg_percent;
- bw_id = p->bwg_id;
-
- if (bw_id >= MAX_BW_GROUP) {
- ret_val = DCB_ERR_CONFIG;
- goto err_config;
- }
- if (p->prio_type == prio_link) {
- link_strict[i][bw_id] = true;
- /* Link strict should have zero bandwidth */
- if (bw) {
- ret_val = DCB_ERR_LS_BW_NONZERO;
- goto err_config;
- }
- } else if (!bw) {
- /*
- * Traffic classes without link strict
- * should have non-zero bandwidth.
- */
- ret_val = DCB_ERR_TC_BW_ZERO;
- goto err_config;
- }
- bw_sum[i][bw_id] += bw;
- }
-
- bw = 0;
-
- /* Check each bandwidth group for rule violation */
- for (j = 0; j < MAX_BW_GROUP; j++) {
- bw += dcb_config->bw_percentage[i][j];
- /*
- * Sum of bandwidth percentages of all traffic classes
- * within a Bandwidth Group must total 100 except for
- * link strict group (zero bandwidth).
- */
- if (link_strict[i][j]) {
- if (bw_sum[i][j]) {
- /*
- * Link strict group should have zero
- * bandwidth.
- */
- ret_val = DCB_ERR_LS_BWG_NONZERO;
- goto err_config;
- }
- } else if (bw_sum[i][j] != BW_PERCENT &&
- bw_sum[i][j] != 0) {
- ret_val = DCB_ERR_TC_BW;
- goto err_config;
- }
- }
-
- if (bw != BW_PERCENT) {
- ret_val = DCB_ERR_BW_GROUP;
- goto err_config;
- }
- }
-
-err_config:
- return ret_val;
-}
-
-/**
* ixgbe_dcb_calculate_tc_credits - Calculates traffic class credits
* @ixgbe_dcb_config: Struct containing DCB settings.
* @direction: Configuring either Tx or Rx.
@@ -203,133 +111,6 @@ out:
}
/**
- * ixgbe_dcb_get_tc_stats - Returns status of each traffic class
- * @hw: pointer to hardware structure
- * @stats: pointer to statistics structure
- * @tc_count: Number of elements in bwg_array.
- *
- * This function returns the status data for each of the Traffic Classes in use.
- */
-s32 ixgbe_dcb_get_tc_stats(struct ixgbe_hw *hw, struct ixgbe_hw_stats *stats,
- u8 tc_count)
-{
- s32 ret = 0;
- if (hw->mac.type == ixgbe_mac_82598EB)
- ret = ixgbe_dcb_get_tc_stats_82598(hw, stats, tc_count);
- else if (hw->mac.type == ixgbe_mac_82599EB)
- ret = ixgbe_dcb_get_tc_stats_82599(hw, stats, tc_count);
- return ret;
-}
-
-/**
- * ixgbe_dcb_get_pfc_stats - Returns CBFC status of each traffic class
- * hw - pointer to hardware structure
- * stats - pointer to statistics structure
- * tc_count - Number of elements in bwg_array.
- *
- * This function returns the CBFC status data for each of the Traffic Classes.
- */
-s32 ixgbe_dcb_get_pfc_stats(struct ixgbe_hw *hw, struct ixgbe_hw_stats *stats,
- u8 tc_count)
-{
- s32 ret = 0;
- if (hw->mac.type == ixgbe_mac_82598EB)
- ret = ixgbe_dcb_get_pfc_stats_82598(hw, stats, tc_count);
- else if (hw->mac.type == ixgbe_mac_82599EB)
- ret = ixgbe_dcb_get_pfc_stats_82599(hw, stats, tc_count);
- return ret;
-}
-
-/**
- * ixgbe_dcb_config_rx_arbiter - Config Rx arbiter
- * @hw: pointer to hardware structure
- * @dcb_config: pointer to ixgbe_dcb_config structure
- *
- * Configure Rx Data Arbiter and credits for each traffic class.
- */
-s32 ixgbe_dcb_config_rx_arbiter(struct ixgbe_hw *hw,
- struct ixgbe_dcb_config *dcb_config)
-{
- s32 ret = 0;
- if (hw->mac.type == ixgbe_mac_82598EB)
- ret = ixgbe_dcb_config_rx_arbiter_82598(hw, dcb_config);
- else if (hw->mac.type == ixgbe_mac_82599EB)
- ret = ixgbe_dcb_config_rx_arbiter_82599(hw, dcb_config);
- return ret;
-}
-
-/**
- * ixgbe_dcb_config_tx_desc_arbiter - Config Tx Desc arbiter
- * @hw: pointer to hardware structure
- * @dcb_config: pointer to ixgbe_dcb_config structure
- *
- * Configure Tx Descriptor Arbiter and credits for each traffic class.
- */
-s32 ixgbe_dcb_config_tx_desc_arbiter(struct ixgbe_hw *hw,
- struct ixgbe_dcb_config *dcb_config)
-{
- s32 ret = 0;
- if (hw->mac.type == ixgbe_mac_82598EB)
- ret = ixgbe_dcb_config_tx_desc_arbiter_82598(hw, dcb_config);
- else if (hw->mac.type == ixgbe_mac_82599EB)
- ret = ixgbe_dcb_config_tx_desc_arbiter_82599(hw, dcb_config);
- return ret;
-}
-
-/**
- * ixgbe_dcb_config_tx_data_arbiter - Config Tx data arbiter
- * @hw: pointer to hardware structure
- * @dcb_config: pointer to ixgbe_dcb_config structure
- *
- * Configure Tx Data Arbiter and credits for each traffic class.
- */
-s32 ixgbe_dcb_config_tx_data_arbiter(struct ixgbe_hw *hw,
- struct ixgbe_dcb_config *dcb_config)
-{
- s32 ret = 0;
- if (hw->mac.type == ixgbe_mac_82598EB)
- ret = ixgbe_dcb_config_tx_data_arbiter_82598(hw, dcb_config);
- else if (hw->mac.type == ixgbe_mac_82599EB)
- ret = ixgbe_dcb_config_tx_data_arbiter_82599(hw, dcb_config);
- return ret;
-}
-
-/**
- * ixgbe_dcb_config_pfc - Config priority flow control
- * @hw: pointer to hardware structure
- * @dcb_config: pointer to ixgbe_dcb_config structure
- *
- * Configure Priority Flow Control for each traffic class.
- */
-s32 ixgbe_dcb_config_pfc(struct ixgbe_hw *hw,
- struct ixgbe_dcb_config *dcb_config)
-{
- s32 ret = 0;
- if (hw->mac.type == ixgbe_mac_82598EB)
- ret = ixgbe_dcb_config_pfc_82598(hw, dcb_config);
- else if (hw->mac.type == ixgbe_mac_82599EB)
- ret = ixgbe_dcb_config_pfc_82599(hw, dcb_config);
- return ret;
-}
-
-/**
- * ixgbe_dcb_config_tc_stats - Config traffic class statistics
- * @hw: pointer to hardware structure
- *
- * Configure queue statistics registers, all queues belonging to same traffic
- * class uses a single set of queue statistics counters.
- */
-s32 ixgbe_dcb_config_tc_stats(struct ixgbe_hw *hw)
-{
- s32 ret = 0;
- if (hw->mac.type == ixgbe_mac_82598EB)
- ret = ixgbe_dcb_config_tc_stats_82598(hw);
- else if (hw->mac.type == ixgbe_mac_82599EB)
- ret = ixgbe_dcb_config_tc_stats_82599(hw);
- return ret;
-}
-
-/**
* ixgbe_dcb_hw_config - Config and enable DCB
* @hw: pointer to hardware structure
* @dcb_config: pointer to ixgbe_dcb_config structure
diff --git a/drivers/net/ixgbe/ixgbe_dcb.h b/drivers/net/ixgbe/ixgbe_dcb.h
index 5caafd4afbc3..eb1059f09da0 100644
--- a/drivers/net/ixgbe/ixgbe_dcb.h
+++ b/drivers/net/ixgbe/ixgbe_dcb.h
@@ -149,27 +149,9 @@ struct ixgbe_dcb_config {
/* DCB driver APIs */
-/* DCB rule checking function.*/
-s32 ixgbe_dcb_check_config(struct ixgbe_dcb_config *config);
-
/* DCB credits calculation */
s32 ixgbe_dcb_calculate_tc_credits(struct ixgbe_dcb_config *, u8);
-/* DCB PFC functions */
-s32 ixgbe_dcb_config_pfc(struct ixgbe_hw *, struct ixgbe_dcb_config *g);
-s32 ixgbe_dcb_get_pfc_stats(struct ixgbe_hw *, struct ixgbe_hw_stats *, u8);
-
-/* DCB traffic class stats */
-s32 ixgbe_dcb_config_tc_stats(struct ixgbe_hw *);
-s32 ixgbe_dcb_get_tc_stats(struct ixgbe_hw *, struct ixgbe_hw_stats *, u8);
-
-/* DCB config arbiters */
-s32 ixgbe_dcb_config_tx_desc_arbiter(struct ixgbe_hw *,
- struct ixgbe_dcb_config *);
-s32 ixgbe_dcb_config_tx_data_arbiter(struct ixgbe_hw *,
- struct ixgbe_dcb_config *);
-s32 ixgbe_dcb_config_rx_arbiter(struct ixgbe_hw *, struct ixgbe_dcb_config *);
-
/* DCB hw initialization */
s32 ixgbe_dcb_hw_config(struct ixgbe_hw *, struct ixgbe_dcb_config *);
diff --git a/drivers/net/ixgbe/ixgbe_dcb_82598.c b/drivers/net/ixgbe/ixgbe_dcb_82598.c
index f0e9279d4669..50288bcadc59 100644
--- a/drivers/net/ixgbe/ixgbe_dcb_82598.c
+++ b/drivers/net/ixgbe/ixgbe_dcb_82598.c
@@ -32,65 +32,6 @@
#include "ixgbe_dcb_82598.h"
/**
- * ixgbe_dcb_get_tc_stats_82598 - Return status data for each traffic class
- * @hw: pointer to hardware structure
- * @stats: pointer to statistics structure
- * @tc_count: Number of elements in bwg_array.
- *
- * This function returns the status data for each of the Traffic Classes in use.
- */
-s32 ixgbe_dcb_get_tc_stats_82598(struct ixgbe_hw *hw,
- struct ixgbe_hw_stats *stats,
- u8 tc_count)
-{
- int tc;
-
- if (tc_count > MAX_TRAFFIC_CLASS)
- return DCB_ERR_PARAM;
-
- /* Statistics pertaining to each traffic class */
- for (tc = 0; tc < tc_count; tc++) {
- /* Transmitted Packets */
- stats->qptc[tc] += IXGBE_READ_REG(hw, IXGBE_QPTC(tc));
- /* Transmitted Bytes */
- stats->qbtc[tc] += IXGBE_READ_REG(hw, IXGBE_QBTC(tc));
- /* Received Packets */
- stats->qprc[tc] += IXGBE_READ_REG(hw, IXGBE_QPRC(tc));
- /* Received Bytes */
- stats->qbrc[tc] += IXGBE_READ_REG(hw, IXGBE_QBRC(tc));
- }
-
- return 0;
-}
-
-/**
- * ixgbe_dcb_get_pfc_stats_82598 - Returns CBFC status data
- * @hw: pointer to hardware structure
- * @stats: pointer to statistics structure
- * @tc_count: Number of elements in bwg_array.
- *
- * This function returns the CBFC status data for each of the Traffic Classes.
- */
-s32 ixgbe_dcb_get_pfc_stats_82598(struct ixgbe_hw *hw,
- struct ixgbe_hw_stats *stats,
- u8 tc_count)
-{
- int tc;
-
- if (tc_count > MAX_TRAFFIC_CLASS)
- return DCB_ERR_PARAM;
-
- for (tc = 0; tc < tc_count; tc++) {
- /* Priority XOFF Transmitted */
- stats->pxofftxc[tc] += IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(tc));
- /* Priority XOFF Received */
- stats->pxoffrxc[tc] += IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(tc));
- }
-
- return 0;
-}
-
-/**
* ixgbe_dcb_config_packet_buffers_82598 - Configure packet buffers
* @hw: pointer to hardware structure
* @dcb_config: pointer to ixgbe_dcb_config structure
@@ -137,7 +78,7 @@ static s32 ixgbe_dcb_config_packet_buffers_82598(struct ixgbe_hw *hw,
*
* Configure Rx Data Arbiter and credits for each traffic class.
*/
-s32 ixgbe_dcb_config_rx_arbiter_82598(struct ixgbe_hw *hw,
+static s32 ixgbe_dcb_config_rx_arbiter_82598(struct ixgbe_hw *hw,
struct ixgbe_dcb_config *dcb_config)
{
struct tc_bw_alloc *p;
@@ -194,7 +135,7 @@ s32 ixgbe_dcb_config_rx_arbiter_82598(struct ixgbe_hw *hw,
*
* Configure Tx Descriptor Arbiter and credits for each traffic class.
*/
-s32 ixgbe_dcb_config_tx_desc_arbiter_82598(struct ixgbe_hw *hw,
+static s32 ixgbe_dcb_config_tx_desc_arbiter_82598(struct ixgbe_hw *hw,
struct ixgbe_dcb_config *dcb_config)
{
struct tc_bw_alloc *p;
@@ -242,7 +183,7 @@ s32 ixgbe_dcb_config_tx_desc_arbiter_82598(struct ixgbe_hw *hw,
*
* Configure Tx Data Arbiter and credits for each traffic class.
*/
-s32 ixgbe_dcb_config_tx_data_arbiter_82598(struct ixgbe_hw *hw,
+static s32 ixgbe_dcb_config_tx_data_arbiter_82598(struct ixgbe_hw *hw,
struct ixgbe_dcb_config *dcb_config)
{
struct tc_bw_alloc *p;
@@ -355,7 +296,7 @@ out:
* Configure queue statistics registers, all queues belonging to same traffic
* class uses a single set of queue statistics counters.
*/
-s32 ixgbe_dcb_config_tc_stats_82598(struct ixgbe_hw *hw)
+static s32 ixgbe_dcb_config_tc_stats_82598(struct ixgbe_hw *hw)
{
u32 reg = 0;
u8 i = 0;
diff --git a/drivers/net/ixgbe/ixgbe_dcb_82598.h b/drivers/net/ixgbe/ixgbe_dcb_82598.h
index cc728fa092e2..abc03ccfa088 100644
--- a/drivers/net/ixgbe/ixgbe_dcb_82598.h
+++ b/drivers/net/ixgbe/ixgbe_dcb_82598.h
@@ -72,21 +72,6 @@
/* DCB PFC functions */
s32 ixgbe_dcb_config_pfc_82598(struct ixgbe_hw *, struct ixgbe_dcb_config *);
-s32 ixgbe_dcb_get_pfc_stats_82598(struct ixgbe_hw *, struct ixgbe_hw_stats *,
- u8);
-
-/* DCB traffic class stats */
-s32 ixgbe_dcb_config_tc_stats_82598(struct ixgbe_hw *);
-s32 ixgbe_dcb_get_tc_stats_82598(struct ixgbe_hw *, struct ixgbe_hw_stats *,
- u8);
-
-/* DCB config arbiters */
-s32 ixgbe_dcb_config_tx_desc_arbiter_82598(struct ixgbe_hw *,
- struct ixgbe_dcb_config *);
-s32 ixgbe_dcb_config_tx_data_arbiter_82598(struct ixgbe_hw *,
- struct ixgbe_dcb_config *);
-s32 ixgbe_dcb_config_rx_arbiter_82598(struct ixgbe_hw *,
- struct ixgbe_dcb_config *);
/* DCB hw initialization */
s32 ixgbe_dcb_hw_config_82598(struct ixgbe_hw *, struct ixgbe_dcb_config *);
diff --git a/drivers/net/ixgbe/ixgbe_dcb_82599.c b/drivers/net/ixgbe/ixgbe_dcb_82599.c
index 25b02fb425ac..67c219f86c3a 100644
--- a/drivers/net/ixgbe/ixgbe_dcb_82599.c
+++ b/drivers/net/ixgbe/ixgbe_dcb_82599.c
@@ -31,70 +31,13 @@
#include "ixgbe_dcb_82599.h"
/**
- * ixgbe_dcb_get_tc_stats_82599 - Returns status for each traffic class
- * @hw: pointer to hardware structure
- * @stats: pointer to statistics structure
- * @tc_count: Number of elements in bwg_array.
- *
- * This function returns the status data for each of the Traffic Classes in use.
- */
-s32 ixgbe_dcb_get_tc_stats_82599(struct ixgbe_hw *hw,
- struct ixgbe_hw_stats *stats,
- u8 tc_count)
-{
- int tc;
-
- if (tc_count > MAX_TRAFFIC_CLASS)
- return DCB_ERR_PARAM;
- /* Statistics pertaining to each traffic class */
- for (tc = 0; tc < tc_count; tc++) {
- /* Transmitted Packets */
- stats->qptc[tc] += IXGBE_READ_REG(hw, IXGBE_QPTC(tc));
- /* Transmitted Bytes */
- stats->qbtc[tc] += IXGBE_READ_REG(hw, IXGBE_QBTC(tc));
- /* Received Packets */
- stats->qprc[tc] += IXGBE_READ_REG(hw, IXGBE_QPRC(tc));
- /* Received Bytes */
- stats->qbrc[tc] += IXGBE_READ_REG(hw, IXGBE_QBRC(tc));
- }
-
- return 0;
-}
-
-/**
- * ixgbe_dcb_get_pfc_stats_82599 - Return CBFC status data
- * @hw: pointer to hardware structure
- * @stats: pointer to statistics structure
- * @tc_count: Number of elements in bwg_array.
- *
- * This function returns the CBFC status data for each of the Traffic Classes.
- */
-s32 ixgbe_dcb_get_pfc_stats_82599(struct ixgbe_hw *hw,
- struct ixgbe_hw_stats *stats,
- u8 tc_count)
-{
- int tc;
-
- if (tc_count > MAX_TRAFFIC_CLASS)
- return DCB_ERR_PARAM;
- for (tc = 0; tc < tc_count; tc++) {
- /* Priority XOFF Transmitted */
- stats->pxofftxc[tc] += IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(tc));
- /* Priority XOFF Received */
- stats->pxoffrxc[tc] += IXGBE_READ_REG(hw, IXGBE_PXOFFRXCNT(tc));
- }
-
- return 0;
-}
-
-/**
* ixgbe_dcb_config_packet_buffers_82599 - Configure DCB packet buffers
* @hw: pointer to hardware structure
* @dcb_config: pointer to ixgbe_dcb_config structure
*
* Configure packet buffers for DCB mode.
*/
-s32 ixgbe_dcb_config_packet_buffers_82599(struct ixgbe_hw *hw,
+static s32 ixgbe_dcb_config_packet_buffers_82599(struct ixgbe_hw *hw,
struct ixgbe_dcb_config *dcb_config)
{
s32 ret_val = 0;
@@ -136,7 +79,7 @@ s32 ixgbe_dcb_config_packet_buffers_82599(struct ixgbe_hw *hw,
*
* Configure Rx Packet Arbiter and credits for each traffic class.
*/
-s32 ixgbe_dcb_config_rx_arbiter_82599(struct ixgbe_hw *hw,
+static s32 ixgbe_dcb_config_rx_arbiter_82599(struct ixgbe_hw *hw,
struct ixgbe_dcb_config *dcb_config)
{
struct tc_bw_alloc *p;
@@ -191,7 +134,7 @@ s32 ixgbe_dcb_config_rx_arbiter_82599(struct ixgbe_hw *hw,
*
* Configure Tx Descriptor Arbiter and credits for each traffic class.
*/
-s32 ixgbe_dcb_config_tx_desc_arbiter_82599(struct ixgbe_hw *hw,
+static s32 ixgbe_dcb_config_tx_desc_arbiter_82599(struct ixgbe_hw *hw,
struct ixgbe_dcb_config *dcb_config)
{
struct tc_bw_alloc *p;
@@ -238,7 +181,7 @@ s32 ixgbe_dcb_config_tx_desc_arbiter_82599(struct ixgbe_hw *hw,
*
* Configure Tx Packet Arbiter and credits for each traffic class.
*/
-s32 ixgbe_dcb_config_tx_data_arbiter_82599(struct ixgbe_hw *hw,
+static s32 ixgbe_dcb_config_tx_data_arbiter_82599(struct ixgbe_hw *hw,
struct ixgbe_dcb_config *dcb_config)
{
struct tc_bw_alloc *p;
@@ -359,7 +302,7 @@ out:
* Configure queue statistics registers, all queues belonging to same traffic
* class uses a single set of queue statistics counters.
*/
-s32 ixgbe_dcb_config_tc_stats_82599(struct ixgbe_hw *hw)
+static s32 ixgbe_dcb_config_tc_stats_82599(struct ixgbe_hw *hw)
{
u32 reg = 0;
u8 i = 0;
@@ -412,7 +355,7 @@ s32 ixgbe_dcb_config_tc_stats_82599(struct ixgbe_hw *hw)
*
* Configure general DCB parameters.
*/
-s32 ixgbe_dcb_config_82599(struct ixgbe_hw *hw)
+static s32 ixgbe_dcb_config_82599(struct ixgbe_hw *hw)
{
u32 reg;
u32 q;
diff --git a/drivers/net/ixgbe/ixgbe_dcb_82599.h b/drivers/net/ixgbe/ixgbe_dcb_82599.h
index 0f3f791e1e1d..18d7fbf6c292 100644
--- a/drivers/net/ixgbe/ixgbe_dcb_82599.h
+++ b/drivers/net/ixgbe/ixgbe_dcb_82599.h
@@ -101,24 +101,6 @@
/* DCB PFC functions */
s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw,
struct ixgbe_dcb_config *dcb_config);
-s32 ixgbe_dcb_get_pfc_stats_82599(struct ixgbe_hw *hw,
- struct ixgbe_hw_stats *stats,
- u8 tc_count);
-
-/* DCB traffic class stats */
-s32 ixgbe_dcb_config_tc_stats_82599(struct ixgbe_hw *hw);
-s32 ixgbe_dcb_get_tc_stats_82599(struct ixgbe_hw *hw,
- struct ixgbe_hw_stats *stats,
- u8 tc_count);
-
-/* DCB config arbiters */
-s32 ixgbe_dcb_config_tx_desc_arbiter_82599(struct ixgbe_hw *hw,
- struct ixgbe_dcb_config *dcb_config);
-s32 ixgbe_dcb_config_tx_data_arbiter_82599(struct ixgbe_hw *hw,
- struct ixgbe_dcb_config *dcb_config);
-s32 ixgbe_dcb_config_rx_arbiter_82599(struct ixgbe_hw *hw,
- struct ixgbe_dcb_config *dcb_config);
-
/* DCB hw initialization */
s32 ixgbe_dcb_hw_config_82599(struct ixgbe_hw *hw,
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
index dcebc82c6f4d..3dc731c22ff2 100644
--- a/drivers/net/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ixgbe/ixgbe_ethtool.c
@@ -401,7 +401,7 @@ static int ixgbe_set_pauseparam(struct net_device *netdev,
static u32 ixgbe_get_rx_csum(struct net_device *netdev)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
- return (adapter->flags & IXGBE_FLAG_RX_CSUM_ENABLED);
+ return adapter->flags & IXGBE_FLAG_RX_CSUM_ENABLED;
}
static int ixgbe_set_rx_csum(struct net_device *netdev, u32 data)
@@ -820,16 +820,19 @@ static void ixgbe_get_drvinfo(struct net_device *netdev,
struct ixgbe_adapter *adapter = netdev_priv(netdev);
char firmware_version[32];
- strncpy(drvinfo->driver, ixgbe_driver_name, 32);
- strncpy(drvinfo->version, ixgbe_driver_version, 32);
+ strncpy(drvinfo->driver, ixgbe_driver_name, sizeof(drvinfo->driver));
+ strncpy(drvinfo->version, ixgbe_driver_version,
+ sizeof(drvinfo->version));
- sprintf(firmware_version, "%d.%d-%d",
- (adapter->eeprom_version & 0xF000) >> 12,
- (adapter->eeprom_version & 0x0FF0) >> 4,
- adapter->eeprom_version & 0x000F);
+ snprintf(firmware_version, sizeof(firmware_version), "%d.%d-%d",
+ (adapter->eeprom_version & 0xF000) >> 12,
+ (adapter->eeprom_version & 0x0FF0) >> 4,
+ adapter->eeprom_version & 0x000F);
- strncpy(drvinfo->fw_version, firmware_version, 32);
- strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
+ strncpy(drvinfo->fw_version, firmware_version,
+ sizeof(drvinfo->fw_version));
+ strncpy(drvinfo->bus_info, pci_name(adapter->pdev),
+ sizeof(drvinfo->bus_info));
drvinfo->n_stats = IXGBE_STATS_LEN;
drvinfo->testinfo_len = IXGBE_TEST_LEN;
drvinfo->regdump_len = ixgbe_get_regs_len(netdev);
@@ -985,8 +988,8 @@ static int ixgbe_get_sset_count(struct net_device *netdev, int sset)
case ETH_SS_STATS:
return IXGBE_STATS_LEN;
case ETH_SS_NTUPLE_FILTERS:
- return (ETHTOOL_MAX_NTUPLE_LIST_ENTRY *
- ETHTOOL_MAX_NTUPLE_STRING_PER_ENTRY);
+ return ETHTOOL_MAX_NTUPLE_LIST_ENTRY *
+ ETHTOOL_MAX_NTUPLE_STRING_PER_ENTRY;
default:
return -EOPNOTSUPP;
}
@@ -996,12 +999,11 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev,
struct ethtool_stats *stats, u64 *data)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
- u64 *queue_stat;
- int stat_count = sizeof(struct ixgbe_queue_stats) / sizeof(u64);
struct rtnl_link_stats64 temp;
const struct rtnl_link_stats64 *net_stats;
- int j, k;
- int i;
+ unsigned int start;
+ struct ixgbe_ring *ring;
+ int i, j;
char *p = NULL;
ixgbe_update_stats(adapter);
@@ -1022,16 +1024,22 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev,
sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
}
for (j = 0; j < adapter->num_tx_queues; j++) {
- queue_stat = (u64 *)&adapter->tx_ring[j]->stats;
- for (k = 0; k < stat_count; k++)
- data[i + k] = queue_stat[k];
- i += k;
+ ring = adapter->tx_ring[j];
+ do {
+ start = u64_stats_fetch_begin_bh(&ring->syncp);
+ data[i] = ring->stats.packets;
+ data[i+1] = ring->stats.bytes;
+ } while (u64_stats_fetch_retry_bh(&ring->syncp, start));
+ i += 2;
}
for (j = 0; j < adapter->num_rx_queues; j++) {
- queue_stat = (u64 *)&adapter->rx_ring[j]->stats;
- for (k = 0; k < stat_count; k++)
- data[i + k] = queue_stat[k];
- i += k;
+ ring = adapter->rx_ring[j];
+ do {
+ start = u64_stats_fetch_begin_bh(&ring->syncp);
+ data[i] = ring->stats.packets;
+ data[i+1] = ring->stats.bytes;
+ } while (u64_stats_fetch_retry_bh(&ring->syncp, start));
+ i += 2;
}
if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
for (j = 0; j < MAX_TX_PACKET_BUFFERS; j++) {
@@ -1435,9 +1443,7 @@ static void ixgbe_free_desc_rings(struct ixgbe_adapter *adapter)
struct ixgbe_ring *tx_ring = &adapter->test_tx_ring;
struct ixgbe_ring *rx_ring = &adapter->test_rx_ring;
struct ixgbe_hw *hw = &adapter->hw;
- struct pci_dev *pdev = adapter->pdev;
u32 reg_ctl;
- int i;
/* shut down the DMA engines now so they can be reinitialized later */
@@ -1445,14 +1451,15 @@ static void ixgbe_free_desc_rings(struct ixgbe_adapter *adapter)
reg_ctl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
reg_ctl &= ~IXGBE_RXCTRL_RXEN;
IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, reg_ctl);
- reg_ctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(0));
+ reg_ctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(rx_ring->reg_idx));
reg_ctl &= ~IXGBE_RXDCTL_ENABLE;
- IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(0), reg_ctl);
+ IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(rx_ring->reg_idx), reg_ctl);
/* now Tx */
- reg_ctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(0));
+ reg_ctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(tx_ring->reg_idx));
reg_ctl &= ~IXGBE_TXDCTL_ENABLE;
- IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(0), reg_ctl);
+ IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(tx_ring->reg_idx), reg_ctl);
+
if (hw->mac.type == ixgbe_mac_82599EB) {
reg_ctl = IXGBE_READ_REG(hw, IXGBE_DMATXCTL);
reg_ctl &= ~IXGBE_DMATXCTL_TE;
@@ -1461,221 +1468,57 @@ static void ixgbe_free_desc_rings(struct ixgbe_adapter *adapter)
ixgbe_reset(adapter);
- if (tx_ring->desc && tx_ring->tx_buffer_info) {
- for (i = 0; i < tx_ring->count; i++) {
- struct ixgbe_tx_buffer *buf =
- &(tx_ring->tx_buffer_info[i]);
- if (buf->dma)
- dma_unmap_single(&pdev->dev, buf->dma,
- buf->length, DMA_TO_DEVICE);
- if (buf->skb)
- dev_kfree_skb(buf->skb);
- }
- }
-
- if (rx_ring->desc && rx_ring->rx_buffer_info) {
- for (i = 0; i < rx_ring->count; i++) {
- struct ixgbe_rx_buffer *buf =
- &(rx_ring->rx_buffer_info[i]);
- if (buf->dma)
- dma_unmap_single(&pdev->dev, buf->dma,
- IXGBE_RXBUFFER_2048,
- DMA_FROM_DEVICE);
- if (buf->skb)
- dev_kfree_skb(buf->skb);
- }
- }
-
- if (tx_ring->desc) {
- dma_free_coherent(&pdev->dev, tx_ring->size, tx_ring->desc,
- tx_ring->dma);
- tx_ring->desc = NULL;
- }
- if (rx_ring->desc) {
- dma_free_coherent(&pdev->dev, rx_ring->size, rx_ring->desc,
- rx_ring->dma);
- rx_ring->desc = NULL;
- }
-
- kfree(tx_ring->tx_buffer_info);
- tx_ring->tx_buffer_info = NULL;
- kfree(rx_ring->rx_buffer_info);
- rx_ring->rx_buffer_info = NULL;
+ ixgbe_free_tx_resources(adapter, &adapter->test_tx_ring);
+ ixgbe_free_rx_resources(adapter, &adapter->test_rx_ring);
}
static int ixgbe_setup_desc_rings(struct ixgbe_adapter *adapter)
{
struct ixgbe_ring *tx_ring = &adapter->test_tx_ring;
struct ixgbe_ring *rx_ring = &adapter->test_rx_ring;
- struct pci_dev *pdev = adapter->pdev;
u32 rctl, reg_data;
- int i, ret_val;
+ int ret_val;
+ int err;
/* Setup Tx descriptor ring and Tx buffers */
+ tx_ring->count = IXGBE_DEFAULT_TXD;
+ tx_ring->queue_index = 0;
+ tx_ring->reg_idx = adapter->tx_ring[0]->reg_idx;
+ tx_ring->numa_node = adapter->node;
- if (!tx_ring->count)
- tx_ring->count = IXGBE_DEFAULT_TXD;
-
- tx_ring->tx_buffer_info = kcalloc(tx_ring->count,
- sizeof(struct ixgbe_tx_buffer),
- GFP_KERNEL);
- if (!(tx_ring->tx_buffer_info)) {
- ret_val = 1;
- goto err_nomem;
- }
-
- tx_ring->size = tx_ring->count * sizeof(union ixgbe_adv_tx_desc);
- tx_ring->size = ALIGN(tx_ring->size, 4096);
- tx_ring->desc = dma_alloc_coherent(&pdev->dev, tx_ring->size,
- &tx_ring->dma, GFP_KERNEL);
- if (!(tx_ring->desc)) {
- ret_val = 2;
- goto err_nomem;
- }
- tx_ring->next_to_use = tx_ring->next_to_clean = 0;
-
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_TDBAL(0),
- ((u64) tx_ring->dma & 0x00000000FFFFFFFF));
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_TDBAH(0),
- ((u64) tx_ring->dma >> 32));
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_TDLEN(0),
- tx_ring->count * sizeof(union ixgbe_adv_tx_desc));
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_TDH(0), 0);
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_TDT(0), 0);
-
- reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_HLREG0);
- reg_data |= IXGBE_HLREG0_TXPADEN;
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_HLREG0, reg_data);
+ err = ixgbe_setup_tx_resources(adapter, tx_ring);
+ if (err)
+ return 1;
if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_DMATXCTL);
reg_data |= IXGBE_DMATXCTL_TE;
IXGBE_WRITE_REG(&adapter->hw, IXGBE_DMATXCTL, reg_data);
}
- reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_TXDCTL(0));
- reg_data |= IXGBE_TXDCTL_ENABLE;
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_TXDCTL(0), reg_data);
-
- for (i = 0; i < tx_ring->count; i++) {
- union ixgbe_adv_tx_desc *desc = IXGBE_TX_DESC_ADV(*tx_ring, i);
- struct sk_buff *skb;
- unsigned int size = 1024;
-
- skb = alloc_skb(size, GFP_KERNEL);
- if (!skb) {
- ret_val = 3;
- goto err_nomem;
- }
- skb_put(skb, size);
- tx_ring->tx_buffer_info[i].skb = skb;
- tx_ring->tx_buffer_info[i].length = skb->len;
- tx_ring->tx_buffer_info[i].dma =
- dma_map_single(&pdev->dev, skb->data, skb->len,
- DMA_TO_DEVICE);
- desc->read.buffer_addr =
- cpu_to_le64(tx_ring->tx_buffer_info[i].dma);
- desc->read.cmd_type_len = cpu_to_le32(skb->len);
- desc->read.cmd_type_len |= cpu_to_le32(IXGBE_TXD_CMD_EOP |
- IXGBE_TXD_CMD_IFCS |
- IXGBE_TXD_CMD_RS);
- desc->read.olinfo_status = 0;
- if (adapter->hw.mac.type == ixgbe_mac_82599EB)
- desc->read.olinfo_status |=
- (skb->len << IXGBE_ADVTXD_PAYLEN_SHIFT);
- }
+ ixgbe_configure_tx_ring(adapter, tx_ring);
/* Setup Rx Descriptor ring and Rx buffers */
-
- if (!rx_ring->count)
- rx_ring->count = IXGBE_DEFAULT_RXD;
-
- rx_ring->rx_buffer_info = kcalloc(rx_ring->count,
- sizeof(struct ixgbe_rx_buffer),
- GFP_KERNEL);
- if (!(rx_ring->rx_buffer_info)) {
+ rx_ring->count = IXGBE_DEFAULT_RXD;
+ rx_ring->queue_index = 0;
+ rx_ring->reg_idx = adapter->rx_ring[0]->reg_idx;
+ rx_ring->rx_buf_len = IXGBE_RXBUFFER_2048;
+ rx_ring->numa_node = adapter->node;
+
+ err = ixgbe_setup_rx_resources(adapter, rx_ring);
+ if (err) {
ret_val = 4;
goto err_nomem;
}
- rx_ring->size = rx_ring->count * sizeof(union ixgbe_adv_rx_desc);
- rx_ring->size = ALIGN(rx_ring->size, 4096);
- rx_ring->desc = dma_alloc_coherent(&pdev->dev, rx_ring->size,
- &rx_ring->dma, GFP_KERNEL);
- if (!(rx_ring->desc)) {
- ret_val = 5;
- goto err_nomem;
- }
- rx_ring->next_to_use = rx_ring->next_to_clean = 0;
-
rctl = IXGBE_READ_REG(&adapter->hw, IXGBE_RXCTRL);
IXGBE_WRITE_REG(&adapter->hw, IXGBE_RXCTRL, rctl & ~IXGBE_RXCTRL_RXEN);
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDBAL(0),
- ((u64)rx_ring->dma & 0xFFFFFFFF));
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDBAH(0),
- ((u64) rx_ring->dma >> 32));
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDLEN(0), rx_ring->size);
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDH(0), 0);
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDT(0), 0);
- reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL);
- reg_data |= IXGBE_FCTRL_BAM | IXGBE_FCTRL_SBP | IXGBE_FCTRL_MPE;
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, reg_data);
-
- reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_HLREG0);
- reg_data &= ~IXGBE_HLREG0_LPBK;
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_HLREG0, reg_data);
-
- reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_RDRXCTL);
-#define IXGBE_RDRXCTL_RDMTS_MASK 0x00000003 /* Receive Descriptor Minimum
- Threshold Size mask */
- reg_data &= ~IXGBE_RDRXCTL_RDMTS_MASK;
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDRXCTL, reg_data);
-
- reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_MCSTCTRL);
-#define IXGBE_MCSTCTRL_MO_MASK 0x00000003 /* Multicast Offset mask */
- reg_data &= ~IXGBE_MCSTCTRL_MO_MASK;
- reg_data |= adapter->hw.mac.mc_filter_type;
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_MCSTCTRL, reg_data);
-
- reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_RXDCTL(0));
- reg_data |= IXGBE_RXDCTL_ENABLE;
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_RXDCTL(0), reg_data);
- if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
- int j = adapter->rx_ring[0]->reg_idx;
- u32 k;
- for (k = 0; k < 10; k++) {
- if (IXGBE_READ_REG(&adapter->hw,
- IXGBE_RXDCTL(j)) & IXGBE_RXDCTL_ENABLE)
- break;
- else
- msleep(1);
- }
- }
+ ixgbe_configure_rx_ring(adapter, rx_ring);
rctl |= IXGBE_RXCTRL_RXEN | IXGBE_RXCTRL_DMBYPS;
IXGBE_WRITE_REG(&adapter->hw, IXGBE_RXCTRL, rctl);
- for (i = 0; i < rx_ring->count; i++) {
- union ixgbe_adv_rx_desc *rx_desc =
- IXGBE_RX_DESC_ADV(*rx_ring, i);
- struct sk_buff *skb;
-
- skb = alloc_skb(IXGBE_RXBUFFER_2048 + NET_IP_ALIGN, GFP_KERNEL);
- if (!skb) {
- ret_val = 6;
- goto err_nomem;
- }
- skb_reserve(skb, NET_IP_ALIGN);
- rx_ring->rx_buffer_info[i].skb = skb;
- rx_ring->rx_buffer_info[i].dma =
- dma_map_single(&pdev->dev, skb->data,
- IXGBE_RXBUFFER_2048, DMA_FROM_DEVICE);
- rx_desc->read.pkt_addr =
- cpu_to_le64(rx_ring->rx_buffer_info[i].dma);
- memset(skb->data, 0x00, skb->len);
- }
-
return 0;
err_nomem:
@@ -1689,16 +1532,21 @@ static int ixgbe_setup_loopback_test(struct ixgbe_adapter *adapter)
u32 reg_data;
/* right now we only support MAC loopback in the driver */
-
- /* Setup MAC loopback */
reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_HLREG0);
+ /* Setup MAC loopback */
reg_data |= IXGBE_HLREG0_LPBK;
IXGBE_WRITE_REG(&adapter->hw, IXGBE_HLREG0, reg_data);
+ reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL);
+ reg_data |= IXGBE_FCTRL_BAM | IXGBE_FCTRL_SBP | IXGBE_FCTRL_MPE;
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, reg_data);
+
reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_AUTOC);
reg_data &= ~IXGBE_AUTOC_LMS_MASK;
reg_data |= IXGBE_AUTOC_LMS_10G_LINK_NO_AN | IXGBE_AUTOC_FLU;
IXGBE_WRITE_REG(&adapter->hw, IXGBE_AUTOC, reg_data);
+ IXGBE_WRITE_FLUSH(&adapter->hw);
+ msleep(10);
/* Disable Atlas Tx lanes; re-enabled in reset path */
if (hw->mac.type == ixgbe_mac_82598EB) {
@@ -1756,15 +1604,81 @@ static int ixgbe_check_lbtest_frame(struct sk_buff *skb,
return 13;
}
+static u16 ixgbe_clean_test_rings(struct ixgbe_adapter *adapter,
+ struct ixgbe_ring *rx_ring,
+ struct ixgbe_ring *tx_ring,
+ unsigned int size)
+{
+ union ixgbe_adv_rx_desc *rx_desc;
+ struct ixgbe_rx_buffer *rx_buffer_info;
+ struct ixgbe_tx_buffer *tx_buffer_info;
+ const int bufsz = rx_ring->rx_buf_len;
+ u32 staterr;
+ u16 rx_ntc, tx_ntc, count = 0;
+
+ /* initialize next to clean and descriptor values */
+ rx_ntc = rx_ring->next_to_clean;
+ tx_ntc = tx_ring->next_to_clean;
+ rx_desc = IXGBE_RX_DESC_ADV(rx_ring, rx_ntc);
+ staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
+
+ while (staterr & IXGBE_RXD_STAT_DD) {
+ /* check Rx buffer */
+ rx_buffer_info = &rx_ring->rx_buffer_info[rx_ntc];
+
+ /* unmap Rx buffer, will be remapped by alloc_rx_buffers */
+ dma_unmap_single(&adapter->pdev->dev,
+ rx_buffer_info->dma,
+ bufsz,
+ DMA_FROM_DEVICE);
+ rx_buffer_info->dma = 0;
+
+ /* verify contents of skb */
+ if (!ixgbe_check_lbtest_frame(rx_buffer_info->skb, size))
+ count++;
+
+ /* unmap buffer on Tx side */
+ tx_buffer_info = &tx_ring->tx_buffer_info[tx_ntc];
+ ixgbe_unmap_and_free_tx_resource(adapter, tx_buffer_info);
+
+ /* increment Rx/Tx next to clean counters */
+ rx_ntc++;
+ if (rx_ntc == rx_ring->count)
+ rx_ntc = 0;
+ tx_ntc++;
+ if (tx_ntc == tx_ring->count)
+ tx_ntc = 0;
+
+ /* fetch next descriptor */
+ rx_desc = IXGBE_RX_DESC_ADV(rx_ring, rx_ntc);
+ staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
+ }
+
+ /* re-map buffers to ring, store next to clean values */
+ ixgbe_alloc_rx_buffers(adapter, rx_ring, count);
+ rx_ring->next_to_clean = rx_ntc;
+ tx_ring->next_to_clean = tx_ntc;
+
+ return count;
+}
+
static int ixgbe_run_loopback_test(struct ixgbe_adapter *adapter)
{
struct ixgbe_ring *tx_ring = &adapter->test_tx_ring;
struct ixgbe_ring *rx_ring = &adapter->test_rx_ring;
- struct pci_dev *pdev = adapter->pdev;
- int i, j, k, l, lc, good_cnt, ret_val = 0;
- unsigned long time;
+ int i, j, lc, good_cnt, ret_val = 0;
+ unsigned int size = 1024;
+ netdev_tx_t tx_ret_val;
+ struct sk_buff *skb;
+
+ /* allocate test skb */
+ skb = alloc_skb(size, GFP_KERNEL);
+ if (!skb)
+ return 11;
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDT(0), rx_ring->count - 1);
+ /* place data into test skb */
+ ixgbe_create_lbtest_frame(skb, size);
+ skb_put(skb, size);
/*
* Calculate the loop count based on the largest descriptor ring
@@ -1777,54 +1691,40 @@ static int ixgbe_run_loopback_test(struct ixgbe_adapter *adapter)
else
lc = ((rx_ring->count / 64) * 2) + 1;
- k = l = 0;
for (j = 0; j <= lc; j++) {
- for (i = 0; i < 64; i++) {
- ixgbe_create_lbtest_frame(
- tx_ring->tx_buffer_info[k].skb,
- 1024);
- dma_sync_single_for_device(&pdev->dev,
- tx_ring->tx_buffer_info[k].dma,
- tx_ring->tx_buffer_info[k].length,
- DMA_TO_DEVICE);
- if (unlikely(++k == tx_ring->count))
- k = 0;
- }
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_TDT(0), k);
- msleep(200);
- /* set the start time for the receive */
- time = jiffies;
+ /* reset count of good packets */
good_cnt = 0;
- do {
- /* receive the sent packets */
- dma_sync_single_for_cpu(&pdev->dev,
- rx_ring->rx_buffer_info[l].dma,
- IXGBE_RXBUFFER_2048,
- DMA_FROM_DEVICE);
- ret_val = ixgbe_check_lbtest_frame(
- rx_ring->rx_buffer_info[l].skb, 1024);
- if (!ret_val)
+
+ /* place 64 packets on the transmit queue*/
+ for (i = 0; i < 64; i++) {
+ skb_get(skb);
+ tx_ret_val = ixgbe_xmit_frame_ring(skb,
+ adapter->netdev,
+ adapter,
+ tx_ring);
+ if (tx_ret_val == NETDEV_TX_OK)
good_cnt++;
- if (++l == rx_ring->count)
- l = 0;
- /*
- * time + 20 msecs (200 msecs on 2.4) is more than
- * enough time to complete the receives, if it's
- * exceeded, break and error off
- */
- } while (good_cnt < 64 && jiffies < (time + 20));
+ }
+
if (good_cnt != 64) {
- /* ret_val is the same as mis-compare */
- ret_val = 13;
+ ret_val = 12;
break;
}
- if (jiffies >= (time + 20)) {
- /* Error code for time out error */
- ret_val = 14;
+
+ /* allow 200 milliseconds for packets to go from Tx to Rx */
+ msleep(200);
+
+ good_cnt = ixgbe_clean_test_rings(adapter, rx_ring,
+ tx_ring, size);
+ if (good_cnt != 64) {
+ ret_val = 13;
break;
}
}
+ /* free the original skb */
+ kfree_skb(skb);
+
return ret_val;
}
@@ -2218,7 +2118,17 @@ static int ixgbe_set_flags(struct net_device *netdev, u32 data)
bool need_reset = false;
int rc;
- rc = ethtool_op_set_flags(netdev, data, ETH_FLAG_LRO | ETH_FLAG_NTUPLE);
+#ifdef CONFIG_IXGBE_DCB
+ if ((adapter->flags & IXGBE_FLAG_DCB_ENABLED) &&
+ !(data & ETH_FLAG_RXVLAN))
+ return -EINVAL;
+#endif
+
+ need_reset = (data & ETH_FLAG_RXVLAN) !=
+ (netdev->features & NETIF_F_HW_VLAN_RX);
+
+ rc = ethtool_op_set_flags(netdev, data, ETH_FLAG_LRO |
+ ETH_FLAG_RXVLAN | ETH_FLAG_TXVLAN);
if (rc)
return rc;
diff --git a/drivers/net/ixgbe/ixgbe_fcoe.c b/drivers/net/ixgbe/ixgbe_fcoe.c
index 072327c5e41a..05efa6a8ce8e 100644
--- a/drivers/net/ixgbe/ixgbe_fcoe.c
+++ b/drivers/net/ixgbe/ixgbe_fcoe.c
@@ -304,12 +304,13 @@ int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter,
if (!ixgbe_rx_is_fcoe(rx_desc))
goto ddp_out;
- skb->ip_summed = CHECKSUM_UNNECESSARY;
sterr = le32_to_cpu(rx_desc->wb.upper.status_error);
fcerr = (sterr & IXGBE_RXDADV_ERR_FCERR);
fceofe = (sterr & IXGBE_RXDADV_ERR_FCEOFE);
if (fcerr == IXGBE_FCERR_BADCRC)
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
+ else
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
if (eth_hdr(skb)->h_proto == htons(ETH_P_8021Q))
fh = (struct fc_frame_header *)(skb->data +
@@ -471,7 +472,7 @@ int ixgbe_fso(struct ixgbe_adapter *adapter,
/* write context desc */
i = tx_ring->next_to_use;
- context_desc = IXGBE_TX_CTXTDESC_ADV(*tx_ring, i);
+ context_desc = IXGBE_TX_CTXTDESC_ADV(tx_ring, i);
context_desc->vlan_macip_lens = cpu_to_le32(vlan_macip_lens);
context_desc->seqnum_seed = cpu_to_le32(fcoe_sof_eof);
context_desc->type_tucmd_mlhl = cpu_to_le32(type_tucmd);
@@ -603,11 +604,13 @@ int ixgbe_fcoe_enable(struct net_device *netdev)
{
int rc = -EINVAL;
struct ixgbe_adapter *adapter = netdev_priv(netdev);
+ struct ixgbe_fcoe *fcoe = &adapter->fcoe;
if (!(adapter->flags & IXGBE_FLAG_FCOE_CAPABLE))
goto out_enable;
+ atomic_inc(&fcoe->refcnt);
if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED)
goto out_enable;
@@ -647,6 +650,7 @@ int ixgbe_fcoe_disable(struct net_device *netdev)
{
int rc = -EINVAL;
struct ixgbe_adapter *adapter = netdev_priv(netdev);
+ struct ixgbe_fcoe *fcoe = &adapter->fcoe;
if (!(adapter->flags & IXGBE_FLAG_FCOE_CAPABLE))
goto out_disable;
@@ -654,6 +658,9 @@ int ixgbe_fcoe_disable(struct net_device *netdev)
if (!(adapter->flags & IXGBE_FLAG_FCOE_ENABLED))
goto out_disable;
+ if (!atomic_dec_and_test(&fcoe->refcnt))
+ goto out_disable;
+
e_info(drv, "Disabling FCoE offload features.\n");
netdev->features &= ~NETIF_F_FCOE_CRC;
netdev->features &= ~NETIF_F_FSO;
diff --git a/drivers/net/ixgbe/ixgbe_fcoe.h b/drivers/net/ixgbe/ixgbe_fcoe.h
index abf4b2b3f252..4bc2c551c8db 100644
--- a/drivers/net/ixgbe/ixgbe_fcoe.h
+++ b/drivers/net/ixgbe/ixgbe_fcoe.h
@@ -66,6 +66,7 @@ struct ixgbe_fcoe {
u8 tc;
u8 up;
#endif
+ atomic_t refcnt;
spinlock_t lock;
struct pci_pool *pool;
struct ixgbe_fcoe_ddp ddp[IXGBE_FCOE_DDP_MAX];
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index e32af434cc9d..f85631263af8 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -50,7 +50,7 @@
char ixgbe_driver_name[] = "ixgbe";
static const char ixgbe_driver_string[] =
- "Intel(R) 10 Gigabit PCI Express Network Driver";
+ "Intel(R) 10 Gigabit PCI Express Network Driver";
#define DRV_VERSION "2.0.84-k2"
const char ixgbe_driver_version[] = DRV_VERSION;
@@ -120,7 +120,7 @@ MODULE_DEVICE_TABLE(pci, ixgbe_pci_tbl);
#ifdef CONFIG_IXGBE_DCA
static int ixgbe_notify_dca(struct notifier_block *, unsigned long event,
- void *p);
+ void *p);
static struct notifier_block dca_notifier = {
.notifier_call = ixgbe_notify_dca,
.next = NULL,
@@ -131,8 +131,8 @@ static struct notifier_block dca_notifier = {
#ifdef CONFIG_PCI_IOV
static unsigned int max_vfs;
module_param(max_vfs, uint, 0);
-MODULE_PARM_DESC(max_vfs, "Maximum number of virtual functions to allocate "
- "per physical function");
+MODULE_PARM_DESC(max_vfs,
+ "Maximum number of virtual functions to allocate per physical function");
#endif /* CONFIG_PCI_IOV */
MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
@@ -169,8 +169,8 @@ static inline void ixgbe_disable_sriov(struct ixgbe_adapter *adapter)
/* take a breather then clean up driver data */
msleep(100);
- if (adapter->vfinfo)
- kfree(adapter->vfinfo);
+
+ kfree(adapter->vfinfo);
adapter->vfinfo = NULL;
adapter->num_vfs = 0;
@@ -282,17 +282,17 @@ static void ixgbe_regdump(struct ixgbe_hw *hw, struct ixgbe_reg_info *reginfo)
regs[i] = IXGBE_READ_REG(hw, IXGBE_TXDCTL(i));
break;
default:
- printk(KERN_INFO "%-15s %08x\n", reginfo->name,
+ pr_info("%-15s %08x\n", reginfo->name,
IXGBE_READ_REG(hw, reginfo->ofs));
return;
}
for (i = 0; i < 8; i++) {
snprintf(rname, 16, "%s[%d-%d]", reginfo->name, i*8, i*8+7);
- printk(KERN_ERR "%-15s ", rname);
+ pr_err("%-15s", rname);
for (j = 0; j < 8; j++)
- printk(KERN_CONT "%08x ", regs[i*8+j]);
- printk(KERN_CONT "\n");
+ pr_cont(" %08x", regs[i*8+j]);
+ pr_cont("\n");
}
}
@@ -322,18 +322,18 @@ static void ixgbe_dump(struct ixgbe_adapter *adapter)
/* Print netdevice Info */
if (netdev) {
dev_info(&adapter->pdev->dev, "Net device Info\n");
- printk(KERN_INFO "Device Name state "
+ pr_info("Device Name state "
"trans_start last_rx\n");
- printk(KERN_INFO "%-15s %016lX %016lX %016lX\n",
- netdev->name,
- netdev->state,
- netdev->trans_start,
- netdev->last_rx);
+ pr_info("%-15s %016lX %016lX %016lX\n",
+ netdev->name,
+ netdev->state,
+ netdev->trans_start,
+ netdev->last_rx);
}
/* Print Registers */
dev_info(&adapter->pdev->dev, "Register Dump\n");
- printk(KERN_INFO " Register Name Value\n");
+ pr_info(" Register Name Value\n");
for (reginfo = (struct ixgbe_reg_info *)ixgbe_reg_info_tbl;
reginfo->name; reginfo++) {
ixgbe_regdump(hw, reginfo);
@@ -344,13 +344,12 @@ static void ixgbe_dump(struct ixgbe_adapter *adapter)
goto exit;
dev_info(&adapter->pdev->dev, "TX Rings Summary\n");
- printk(KERN_INFO "Queue [NTU] [NTC] [bi(ntc)->dma ] "
- "leng ntw timestamp\n");
+ pr_info("Queue [NTU] [NTC] [bi(ntc)->dma ] leng ntw timestamp\n");
for (n = 0; n < adapter->num_tx_queues; n++) {
tx_ring = adapter->tx_ring[n];
tx_buffer_info =
&tx_ring->tx_buffer_info[tx_ring->next_to_clean];
- printk(KERN_INFO " %5d %5X %5X %016llX %04X %3X %016llX\n",
+ pr_info(" %5d %5X %5X %016llX %04X %3X %016llX\n",
n, tx_ring->next_to_use, tx_ring->next_to_clean,
(u64)tx_buffer_info->dma,
tx_buffer_info->length,
@@ -377,18 +376,18 @@ static void ixgbe_dump(struct ixgbe_adapter *adapter)
for (n = 0; n < adapter->num_tx_queues; n++) {
tx_ring = adapter->tx_ring[n];
- printk(KERN_INFO "------------------------------------\n");
- printk(KERN_INFO "TX QUEUE INDEX = %d\n", tx_ring->queue_index);
- printk(KERN_INFO "------------------------------------\n");
- printk(KERN_INFO "T [desc] [address 63:0 ] "
+ pr_info("------------------------------------\n");
+ pr_info("TX QUEUE INDEX = %d\n", tx_ring->queue_index);
+ pr_info("------------------------------------\n");
+ pr_info("T [desc] [address 63:0 ] "
"[PlPOIdStDDt Ln] [bi->dma ] "
"leng ntw timestamp bi->skb\n");
for (i = 0; tx_ring->desc && (i < tx_ring->count); i++) {
- tx_desc = IXGBE_TX_DESC_ADV(*tx_ring, i);
+ tx_desc = IXGBE_TX_DESC_ADV(tx_ring, i);
tx_buffer_info = &tx_ring->tx_buffer_info[i];
u0 = (struct my_u0 *)tx_desc;
- printk(KERN_INFO "T [0x%03X] %016llX %016llX %016llX"
+ pr_info("T [0x%03X] %016llX %016llX %016llX"
" %04X %3X %016llX %p", i,
le64_to_cpu(u0->a),
le64_to_cpu(u0->b),
@@ -399,13 +398,13 @@ static void ixgbe_dump(struct ixgbe_adapter *adapter)
tx_buffer_info->skb);
if (i == tx_ring->next_to_use &&
i == tx_ring->next_to_clean)
- printk(KERN_CONT " NTC/U\n");
+ pr_cont(" NTC/U\n");
else if (i == tx_ring->next_to_use)
- printk(KERN_CONT " NTU\n");
+ pr_cont(" NTU\n");
else if (i == tx_ring->next_to_clean)
- printk(KERN_CONT " NTC\n");
+ pr_cont(" NTC\n");
else
- printk(KERN_CONT "\n");
+ pr_cont("\n");
if (netif_msg_pktdata(adapter) &&
tx_buffer_info->dma != 0)
@@ -419,11 +418,11 @@ static void ixgbe_dump(struct ixgbe_adapter *adapter)
/* Print RX Rings Summary */
rx_ring_summary:
dev_info(&adapter->pdev->dev, "RX Rings Summary\n");
- printk(KERN_INFO "Queue [NTU] [NTC]\n");
+ pr_info("Queue [NTU] [NTC]\n");
for (n = 0; n < adapter->num_rx_queues; n++) {
rx_ring = adapter->rx_ring[n];
- printk(KERN_INFO "%5d %5X %5X\n", n,
- rx_ring->next_to_use, rx_ring->next_to_clean);
+ pr_info("%5d %5X %5X\n",
+ n, rx_ring->next_to_use, rx_ring->next_to_clean);
}
/* Print RX Rings */
@@ -454,30 +453,30 @@ rx_ring_summary:
*/
for (n = 0; n < adapter->num_rx_queues; n++) {
rx_ring = adapter->rx_ring[n];
- printk(KERN_INFO "------------------------------------\n");
- printk(KERN_INFO "RX QUEUE INDEX = %d\n", rx_ring->queue_index);
- printk(KERN_INFO "------------------------------------\n");
- printk(KERN_INFO "R [desc] [ PktBuf A0] "
+ pr_info("------------------------------------\n");
+ pr_info("RX QUEUE INDEX = %d\n", rx_ring->queue_index);
+ pr_info("------------------------------------\n");
+ pr_info("R [desc] [ PktBuf A0] "
"[ HeadBuf DD] [bi->dma ] [bi->skb] "
"<-- Adv Rx Read format\n");
- printk(KERN_INFO "RWB[desc] [PcsmIpSHl PtRs] "
+ pr_info("RWB[desc] [PcsmIpSHl PtRs] "
"[vl er S cks ln] ---------------- [bi->skb] "
"<-- Adv Rx Write-Back format\n");
for (i = 0; i < rx_ring->count; i++) {
rx_buffer_info = &rx_ring->rx_buffer_info[i];
- rx_desc = IXGBE_RX_DESC_ADV(*rx_ring, i);
+ rx_desc = IXGBE_RX_DESC_ADV(rx_ring, i);
u0 = (struct my_u0 *)rx_desc;
staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
if (staterr & IXGBE_RXD_STAT_DD) {
/* Descriptor Done */
- printk(KERN_INFO "RWB[0x%03X] %016llX "
+ pr_info("RWB[0x%03X] %016llX "
"%016llX ---------------- %p", i,
le64_to_cpu(u0->a),
le64_to_cpu(u0->b),
rx_buffer_info->skb);
} else {
- printk(KERN_INFO "R [0x%03X] %016llX "
+ pr_info("R [0x%03X] %016llX "
"%016llX %016llX %p", i,
le64_to_cpu(u0->a),
le64_to_cpu(u0->b),
@@ -503,11 +502,11 @@ rx_ring_summary:
}
if (i == rx_ring->next_to_use)
- printk(KERN_CONT " NTU\n");
+ pr_cont(" NTU\n");
else if (i == rx_ring->next_to_clean)
- printk(KERN_CONT " NTC\n");
+ pr_cont(" NTC\n");
else
- printk(KERN_CONT "\n");
+ pr_cont("\n");
}
}
@@ -523,7 +522,7 @@ static void ixgbe_release_hw_control(struct ixgbe_adapter *adapter)
/* Let firmware take over control of h/w */
ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT);
IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT,
- ctrl_ext & ~IXGBE_CTRL_EXT_DRV_LOAD);
+ ctrl_ext & ~IXGBE_CTRL_EXT_DRV_LOAD);
}
static void ixgbe_get_hw_control(struct ixgbe_adapter *adapter)
@@ -533,7 +532,7 @@ static void ixgbe_get_hw_control(struct ixgbe_adapter *adapter)
/* Let firmware know the driver has taken over */
ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT);
IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT,
- ctrl_ext | IXGBE_CTRL_EXT_DRV_LOAD);
+ ctrl_ext | IXGBE_CTRL_EXT_DRV_LOAD);
}
/*
@@ -545,7 +544,7 @@ static void ixgbe_get_hw_control(struct ixgbe_adapter *adapter)
*
*/
static void ixgbe_set_ivar(struct ixgbe_adapter *adapter, s8 direction,
- u8 queue, u8 msix_vector)
+ u8 queue, u8 msix_vector)
{
u32 ivar, index;
struct ixgbe_hw *hw = &adapter->hw;
@@ -586,7 +585,7 @@ static void ixgbe_set_ivar(struct ixgbe_adapter *adapter, s8 direction,
}
static inline void ixgbe_irq_rearm_queues(struct ixgbe_adapter *adapter,
- u64 qmask)
+ u64 qmask)
{
u32 mask;
@@ -601,9 +600,9 @@ static inline void ixgbe_irq_rearm_queues(struct ixgbe_adapter *adapter,
}
}
-static void ixgbe_unmap_and_free_tx_resource(struct ixgbe_adapter *adapter,
- struct ixgbe_tx_buffer
- *tx_buffer_info)
+void ixgbe_unmap_and_free_tx_resource(struct ixgbe_adapter *adapter,
+ struct ixgbe_tx_buffer
+ *tx_buffer_info)
{
if (tx_buffer_info->dma) {
if (tx_buffer_info->mapped_as_page)
@@ -637,7 +636,7 @@ static void ixgbe_unmap_and_free_tx_resource(struct ixgbe_adapter *adapter,
* Returns : true if in xon state (currently not paused)
*/
static inline bool ixgbe_tx_xon_state(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *tx_ring)
+ struct ixgbe_ring *tx_ring)
{
u32 txoff = IXGBE_TFCS_TXOFF;
@@ -682,8 +681,8 @@ static inline bool ixgbe_tx_xon_state(struct ixgbe_adapter *adapter,
}
static inline bool ixgbe_check_tx_hang(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *tx_ring,
- unsigned int eop)
+ struct ixgbe_ring *tx_ring,
+ unsigned int eop)
{
struct ixgbe_hw *hw = &adapter->hw;
@@ -695,7 +694,7 @@ static inline bool ixgbe_check_tx_hang(struct ixgbe_adapter *adapter,
ixgbe_tx_xon_state(adapter, tx_ring)) {
/* detected Tx unit hang */
union ixgbe_adv_tx_desc *tx_desc;
- tx_desc = IXGBE_TX_DESC_ADV(*tx_ring, eop);
+ tx_desc = IXGBE_TX_DESC_ADV(tx_ring, eop);
e_err(drv, "Detected Tx Unit Hang\n"
" Tx Queue <%d>\n"
" TDH, TDT <%x>, <%x>\n"
@@ -732,7 +731,7 @@ static void ixgbe_tx_timeout(struct net_device *netdev);
* @tx_ring: tx ring to clean
**/
static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
- struct ixgbe_ring *tx_ring)
+ struct ixgbe_ring *tx_ring)
{
struct ixgbe_adapter *adapter = q_vector->adapter;
struct net_device *netdev = adapter->netdev;
@@ -743,7 +742,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
i = tx_ring->next_to_clean;
eop = tx_ring->tx_buffer_info[i].next_to_watch;
- eop_desc = IXGBE_TX_DESC_ADV(*tx_ring, eop);
+ eop_desc = IXGBE_TX_DESC_ADV(tx_ring, eop);
while ((eop_desc->wb.status & cpu_to_le32(IXGBE_TXD_STAT_DD)) &&
(count < tx_ring->work_limit)) {
@@ -751,7 +750,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
rmb(); /* read buffer_info after eop_desc */
for ( ; !cleaned; count++) {
struct sk_buff *skb;
- tx_desc = IXGBE_TX_DESC_ADV(*tx_ring, i);
+ tx_desc = IXGBE_TX_DESC_ADV(tx_ring, i);
tx_buffer_info = &tx_ring->tx_buffer_info[i];
cleaned = (i == eop);
skb = tx_buffer_info->skb;
@@ -781,7 +780,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
}
ixgbe_unmap_and_free_tx_resource(adapter,
- tx_buffer_info);
+ tx_buffer_info);
tx_desc->wb.status = 0;
@@ -791,14 +790,14 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
}
eop = tx_ring->tx_buffer_info[i].next_to_watch;
- eop_desc = IXGBE_TX_DESC_ADV(*tx_ring, eop);
+ eop_desc = IXGBE_TX_DESC_ADV(tx_ring, eop);
}
tx_ring->next_to_clean = i;
#define TX_WAKE_THRESHOLD (DESC_NEEDED * 2)
if (unlikely(count && netif_carrier_ok(netdev) &&
- (IXGBE_DESC_UNUSED(tx_ring) >= TX_WAKE_THRESHOLD))) {
+ (IXGBE_DESC_UNUSED(tx_ring) >= TX_WAKE_THRESHOLD))) {
/* Make sure that anybody stopping the queue after this
* sees the new next_to_clean.
*/
@@ -825,14 +824,16 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
tx_ring->total_bytes += total_bytes;
tx_ring->total_packets += total_packets;
+ u64_stats_update_begin(&tx_ring->syncp);
tx_ring->stats.packets += total_packets;
tx_ring->stats.bytes += total_bytes;
- return (count < tx_ring->work_limit);
+ u64_stats_update_end(&tx_ring->syncp);
+ return count < tx_ring->work_limit;
}
#ifdef CONFIG_IXGBE_DCA
static void ixgbe_update_rx_dca(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *rx_ring)
+ struct ixgbe_ring *rx_ring)
{
u32 rxctrl;
int cpu = get_cpu();
@@ -846,13 +847,13 @@ static void ixgbe_update_rx_dca(struct ixgbe_adapter *adapter,
} else if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
rxctrl &= ~IXGBE_DCA_RXCTRL_CPUID_MASK_82599;
rxctrl |= (dca3_get_tag(&adapter->pdev->dev, cpu) <<
- IXGBE_DCA_RXCTRL_CPUID_SHIFT_82599);
+ IXGBE_DCA_RXCTRL_CPUID_SHIFT_82599);
}
rxctrl |= IXGBE_DCA_RXCTRL_DESC_DCA_EN;
rxctrl |= IXGBE_DCA_RXCTRL_HEAD_DCA_EN;
rxctrl &= ~(IXGBE_DCA_RXCTRL_DESC_RRO_EN);
rxctrl &= ~(IXGBE_DCA_RXCTRL_DESC_WRO_EN |
- IXGBE_DCA_RXCTRL_DESC_HSRO_EN);
+ IXGBE_DCA_RXCTRL_DESC_HSRO_EN);
IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_RXCTRL(q), rxctrl);
rx_ring->cpu = cpu;
}
@@ -860,7 +861,7 @@ static void ixgbe_update_rx_dca(struct ixgbe_adapter *adapter,
}
static void ixgbe_update_tx_dca(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *tx_ring)
+ struct ixgbe_ring *tx_ring)
{
u32 txctrl;
int cpu = get_cpu();
@@ -878,7 +879,7 @@ static void ixgbe_update_tx_dca(struct ixgbe_adapter *adapter,
txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(q));
txctrl &= ~IXGBE_DCA_TXCTRL_CPUID_MASK_82599;
txctrl |= (dca3_get_tag(&adapter->pdev->dev, cpu) <<
- IXGBE_DCA_TXCTRL_CPUID_SHIFT_82599);
+ IXGBE_DCA_TXCTRL_CPUID_SHIFT_82599);
txctrl |= IXGBE_DCA_TXCTRL_DESC_DCA_EN;
IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(q), txctrl);
}
@@ -946,27 +947,22 @@ static int __ixgbe_notify_dca(struct device *dev, void *data)
* @rx_desc: rx descriptor
**/
static void ixgbe_receive_skb(struct ixgbe_q_vector *q_vector,
- struct sk_buff *skb, u8 status,
- struct ixgbe_ring *ring,
- union ixgbe_adv_rx_desc *rx_desc)
+ struct sk_buff *skb, u8 status,
+ struct ixgbe_ring *ring,
+ union ixgbe_adv_rx_desc *rx_desc)
{
struct ixgbe_adapter *adapter = q_vector->adapter;
struct napi_struct *napi = &q_vector->napi;
bool is_vlan = (status & IXGBE_RXD_STAT_VP);
u16 tag = le16_to_cpu(rx_desc->wb.upper.vlan);
- skb_record_rx_queue(skb, ring->queue_index);
- if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL)) {
- if (adapter->vlgrp && is_vlan && (tag & VLAN_VID_MASK))
- vlan_gro_receive(napi, adapter->vlgrp, tag, skb);
- else
- napi_gro_receive(napi, skb);
- } else {
- if (adapter->vlgrp && is_vlan && (tag & VLAN_VID_MASK))
- vlan_hwaccel_rx(skb, adapter->vlgrp, tag);
- else
- netif_rx(skb);
- }
+ if (is_vlan && (tag & VLAN_VID_MASK))
+ __vlan_hwaccel_put_tag(skb, tag);
+
+ if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL))
+ napi_gro_receive(napi, skb);
+ else
+ netif_rx(skb);
}
/**
@@ -981,7 +977,7 @@ static inline void ixgbe_rx_checksum(struct ixgbe_adapter *adapter,
{
u32 status_err = le32_to_cpu(rx_desc->wb.upper.status_error);
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
/* Rx csum disabled */
if (!(adapter->flags & IXGBE_FLAG_RX_CSUM_ENABLED))
@@ -1017,7 +1013,7 @@ static inline void ixgbe_rx_checksum(struct ixgbe_adapter *adapter,
}
static inline void ixgbe_release_rx_desc(struct ixgbe_hw *hw,
- struct ixgbe_ring *rx_ring, u32 val)
+ struct ixgbe_ring *rx_ring, u32 val)
{
/*
* Force memory writes to complete before letting h/w
@@ -1033,25 +1029,27 @@ static inline void ixgbe_release_rx_desc(struct ixgbe_hw *hw,
* ixgbe_alloc_rx_buffers - Replace used receive buffers; packet split
* @adapter: address of board private structure
**/
-static void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *rx_ring,
- int cleaned_count)
+void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter,
+ struct ixgbe_ring *rx_ring,
+ int cleaned_count)
{
+ struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
union ixgbe_adv_rx_desc *rx_desc;
struct ixgbe_rx_buffer *bi;
unsigned int i;
+ unsigned int bufsz = rx_ring->rx_buf_len;
i = rx_ring->next_to_use;
bi = &rx_ring->rx_buffer_info[i];
while (cleaned_count--) {
- rx_desc = IXGBE_RX_DESC_ADV(*rx_ring, i);
+ rx_desc = IXGBE_RX_DESC_ADV(rx_ring, i);
if (!bi->page_dma &&
(rx_ring->flags & IXGBE_RING_RX_PS_ENABLED)) {
if (!bi->page) {
- bi->page = alloc_page(GFP_ATOMIC);
+ bi->page = netdev_alloc_page(netdev);
if (!bi->page) {
adapter->alloc_rx_page_failed++;
goto no_buffers;
@@ -1063,29 +1061,28 @@ static void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter,
}
bi->page_dma = dma_map_page(&pdev->dev, bi->page,
- bi->page_offset,
- (PAGE_SIZE / 2),
+ bi->page_offset,
+ (PAGE_SIZE / 2),
DMA_FROM_DEVICE);
}
if (!bi->skb) {
- struct sk_buff *skb;
- /* netdev_alloc_skb reserves 32 bytes up front!! */
- uint bufsz = rx_ring->rx_buf_len + SMP_CACHE_BYTES;
- skb = netdev_alloc_skb(adapter->netdev, bufsz);
+ struct sk_buff *skb = netdev_alloc_skb_ip_align(netdev,
+ bufsz);
+ bi->skb = skb;
if (!skb) {
adapter->alloc_rx_buff_failed++;
goto no_buffers;
}
+ /* initialize queue mapping */
+ skb_record_rx_queue(skb, rx_ring->queue_index);
+ }
- /* advance the data pointer to the next cache line */
- skb_reserve(skb, (PTR_ALIGN(skb->data, SMP_CACHE_BYTES)
- - skb->data));
-
- bi->skb = skb;
- bi->dma = dma_map_single(&pdev->dev, skb->data,
- rx_ring->rx_buf_len,
+ if (!bi->dma) {
+ bi->dma = dma_map_single(&pdev->dev,
+ bi->skb->data,
+ rx_ring->rx_buf_len,
DMA_FROM_DEVICE);
}
/* Refresh the desc even if buffer_addrs didn't change because
@@ -1095,6 +1092,7 @@ static void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter,
rx_desc->read.hdr_addr = cpu_to_le64(bi->dma);
} else {
rx_desc->read.pkt_addr = cpu_to_le64(bi->dma);
+ rx_desc->read.hdr_addr = 0;
}
i++;
@@ -1126,8 +1124,8 @@ static inline u16 ixgbe_get_pkt_info(union ixgbe_adv_rx_desc *rx_desc)
static inline u32 ixgbe_get_rsc_count(union ixgbe_adv_rx_desc *rx_desc)
{
return (le32_to_cpu(rx_desc->wb.lower.lo_dword.data) &
- IXGBE_RXDADV_RSCCNT_MASK) >>
- IXGBE_RXDADV_RSCCNT_SHIFT;
+ IXGBE_RXDADV_RSCCNT_MASK) >>
+ IXGBE_RXDADV_RSCCNT_SHIFT;
}
/**
@@ -1140,7 +1138,7 @@ static inline u32 ixgbe_get_rsc_count(union ixgbe_adv_rx_desc *rx_desc)
* turns it into the frag list owner.
**/
static inline struct sk_buff *ixgbe_transform_rsc_queue(struct sk_buff *skb,
- u64 *count)
+ u64 *count)
{
unsigned int frag_list_size = 0;
@@ -1168,11 +1166,10 @@ struct ixgbe_rsc_cb {
#define IXGBE_RSC_CB(skb) ((struct ixgbe_rsc_cb *)(skb)->cb)
static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
- struct ixgbe_ring *rx_ring,
- int *work_done, int work_to_do)
+ struct ixgbe_ring *rx_ring,
+ int *work_done, int work_to_do)
{
struct ixgbe_adapter *adapter = q_vector->adapter;
- struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
union ixgbe_adv_rx_desc *rx_desc, *next_rxd;
struct ixgbe_rx_buffer *rx_buffer_info, *next_buffer;
@@ -1188,7 +1185,7 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
#endif /* IXGBE_FCOE */
i = rx_ring->next_to_clean;
- rx_desc = IXGBE_RX_DESC_ADV(*rx_ring, i);
+ rx_desc = IXGBE_RX_DESC_ADV(rx_ring, i);
staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
rx_buffer_info = &rx_ring->rx_buffer_info[i];
@@ -1231,9 +1228,9 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
IXGBE_RSC_CB(skb)->dma = rx_buffer_info->dma;
} else {
dma_unmap_single(&pdev->dev,
- rx_buffer_info->dma,
- rx_ring->rx_buf_len,
- DMA_FROM_DEVICE);
+ rx_buffer_info->dma,
+ rx_ring->rx_buf_len,
+ DMA_FROM_DEVICE);
}
rx_buffer_info->dma = 0;
skb_put(skb, len);
@@ -1244,9 +1241,9 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
PAGE_SIZE / 2, DMA_FROM_DEVICE);
rx_buffer_info->page_dma = 0;
skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags,
- rx_buffer_info->page,
- rx_buffer_info->page_offset,
- upper_len);
+ rx_buffer_info->page,
+ rx_buffer_info->page_offset,
+ upper_len);
if ((rx_ring->rx_buf_len > (PAGE_SIZE / 2)) ||
(page_count(rx_buffer_info->page) != 1))
@@ -1263,7 +1260,7 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
if (i == rx_ring->count)
i = 0;
- next_rxd = IXGBE_RX_DESC_ADV(*rx_ring, i);
+ next_rxd = IXGBE_RX_DESC_ADV(rx_ring, i);
prefetch(next_rxd);
cleaned_count++;
@@ -1280,24 +1277,28 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
if (staterr & IXGBE_RXD_STAT_EOP) {
if (skb->prev)
- skb = ixgbe_transform_rsc_queue(skb, &(rx_ring->rsc_count));
+ skb = ixgbe_transform_rsc_queue(skb,
+ &(rx_ring->rsc_count));
if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) {
if (IXGBE_RSC_CB(skb)->delay_unmap) {
dma_unmap_single(&pdev->dev,
IXGBE_RSC_CB(skb)->dma,
- rx_ring->rx_buf_len,
+ rx_ring->rx_buf_len,
DMA_FROM_DEVICE);
IXGBE_RSC_CB(skb)->dma = 0;
IXGBE_RSC_CB(skb)->delay_unmap = false;
}
if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED)
- rx_ring->rsc_count += skb_shinfo(skb)->nr_frags;
+ rx_ring->rsc_count +=
+ skb_shinfo(skb)->nr_frags;
else
rx_ring->rsc_count++;
rx_ring->rsc_flush++;
}
+ u64_stats_update_begin(&rx_ring->syncp);
rx_ring->stats.packets++;
rx_ring->stats.bytes += skb->len;
+ u64_stats_update_end(&rx_ring->syncp);
} else {
if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) {
rx_buffer_info->skb = next_buffer->skb;
@@ -1373,8 +1374,6 @@ next_desc:
rx_ring->total_packets += total_rx_packets;
rx_ring->total_bytes += total_rx_bytes;
- netdev->stats.rx_bytes += total_rx_bytes;
- netdev->stats.rx_packets += total_rx_packets;
return cleaned;
}
@@ -1403,24 +1402,24 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter)
q_vector = adapter->q_vector[v_idx];
/* XXX for_each_set_bit(...) */
r_idx = find_first_bit(q_vector->rxr_idx,
- adapter->num_rx_queues);
+ adapter->num_rx_queues);
for (i = 0; i < q_vector->rxr_count; i++) {
j = adapter->rx_ring[r_idx]->reg_idx;
ixgbe_set_ivar(adapter, 0, j, v_idx);
r_idx = find_next_bit(q_vector->rxr_idx,
- adapter->num_rx_queues,
- r_idx + 1);
+ adapter->num_rx_queues,
+ r_idx + 1);
}
r_idx = find_first_bit(q_vector->txr_idx,
- adapter->num_tx_queues);
+ adapter->num_tx_queues);
for (i = 0; i < q_vector->txr_count; i++) {
j = adapter->tx_ring[r_idx]->reg_idx;
ixgbe_set_ivar(adapter, 1, j, v_idx);
r_idx = find_next_bit(q_vector->txr_idx,
- adapter->num_tx_queues,
- r_idx + 1);
+ adapter->num_tx_queues,
+ r_idx + 1);
}
if (q_vector->txr_count && !q_vector->rxr_count)
@@ -1431,11 +1430,26 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter)
q_vector->eitr = adapter->rx_eitr_param;
ixgbe_write_eitr(q_vector);
+ /* If Flow Director is enabled, set interrupt affinity */
+ if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) ||
+ (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)) {
+ /*
+ * Allocate the affinity_hint cpumask, assign the mask
+ * for this vector, and set our affinity_hint for
+ * this irq.
+ */
+ if (!alloc_cpumask_var(&q_vector->affinity_mask,
+ GFP_KERNEL))
+ return;
+ cpumask_set_cpu(v_idx, q_vector->affinity_mask);
+ irq_set_affinity_hint(adapter->msix_entries[v_idx].vector,
+ q_vector->affinity_mask);
+ }
}
if (adapter->hw.mac.type == ixgbe_mac_82598EB)
ixgbe_set_ivar(adapter, -1, IXGBE_IVAR_OTHER_CAUSES_INDEX,
- v_idx);
+ v_idx);
else if (adapter->hw.mac.type == ixgbe_mac_82599EB)
ixgbe_set_ivar(adapter, -1, 1, v_idx);
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(v_idx), 1950);
@@ -1477,8 +1491,8 @@ enum latency_range {
* parameter (see ixgbe_param.c)
**/
static u8 ixgbe_update_itr(struct ixgbe_adapter *adapter,
- u32 eitr, u8 itr_setting,
- int packets, int bytes)
+ u32 eitr, u8 itr_setting,
+ int packets, int bytes)
{
unsigned int retval = itr_setting;
u32 timepassed_us;
@@ -1567,30 +1581,30 @@ static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector)
for (i = 0; i < q_vector->txr_count; i++) {
tx_ring = adapter->tx_ring[r_idx];
ret_itr = ixgbe_update_itr(adapter, q_vector->eitr,
- q_vector->tx_itr,
- tx_ring->total_packets,
- tx_ring->total_bytes);
+ q_vector->tx_itr,
+ tx_ring->total_packets,
+ tx_ring->total_bytes);
/* if the result for this queue would decrease interrupt
* rate for this vector then use that result */
q_vector->tx_itr = ((q_vector->tx_itr > ret_itr) ?
- q_vector->tx_itr - 1 : ret_itr);
+ q_vector->tx_itr - 1 : ret_itr);
r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues,
- r_idx + 1);
+ r_idx + 1);
}
r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
for (i = 0; i < q_vector->rxr_count; i++) {
rx_ring = adapter->rx_ring[r_idx];
ret_itr = ixgbe_update_itr(adapter, q_vector->eitr,
- q_vector->rx_itr,
- rx_ring->total_packets,
- rx_ring->total_bytes);
+ q_vector->rx_itr,
+ rx_ring->total_packets,
+ rx_ring->total_bytes);
/* if the result for this queue would decrease interrupt
* rate for this vector then use that result */
q_vector->rx_itr = ((q_vector->rx_itr > ret_itr) ?
- q_vector->rx_itr - 1 : ret_itr);
+ q_vector->rx_itr - 1 : ret_itr);
r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues,
- r_idx + 1);
+ r_idx + 1);
}
current_itr = max(q_vector->rx_itr, q_vector->tx_itr);
@@ -1627,39 +1641,40 @@ static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector)
static void ixgbe_check_overtemp_task(struct work_struct *work)
{
struct ixgbe_adapter *adapter = container_of(work,
- struct ixgbe_adapter,
- check_overtemp_task);
+ struct ixgbe_adapter,
+ check_overtemp_task);
struct ixgbe_hw *hw = &adapter->hw;
u32 eicr = adapter->interrupt_event;
- if (adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE) {
- switch (hw->device_id) {
- case IXGBE_DEV_ID_82599_T3_LOM: {
- u32 autoneg;
- bool link_up = false;
+ if (!(adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE))
+ return;
- if (hw->mac.ops.check_link)
- hw->mac.ops.check_link(hw, &autoneg, &link_up, false);
+ switch (hw->device_id) {
+ case IXGBE_DEV_ID_82599_T3_LOM: {
+ u32 autoneg;
+ bool link_up = false;
- if (((eicr & IXGBE_EICR_GPI_SDP0) && (!link_up)) ||
- (eicr & IXGBE_EICR_LSC))
- /* Check if this is due to overtemp */
- if (hw->phy.ops.check_overtemp(hw) == IXGBE_ERR_OVERTEMP)
- break;
- }
+ if (hw->mac.ops.check_link)
+ hw->mac.ops.check_link(hw, &autoneg, &link_up, false);
+
+ if (((eicr & IXGBE_EICR_GPI_SDP0) && (!link_up)) ||
+ (eicr & IXGBE_EICR_LSC))
+ /* Check if this is due to overtemp */
+ if (hw->phy.ops.check_overtemp(hw) == IXGBE_ERR_OVERTEMP)
+ break;
+ return;
+ }
+ default:
+ if (!(eicr & IXGBE_EICR_GPI_SDP0))
return;
- default:
- if (!(eicr & IXGBE_EICR_GPI_SDP0))
- return;
- break;
- }
- e_crit(drv, "Network adapter has been stopped because it has "
- "over heated. Restart the computer. If the problem "
- "persists, power off the system and replace the "
- "adapter\n");
- /* write to clear the interrupt */
- IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP0);
+ break;
}
+ e_crit(drv,
+ "Network adapter has been stopped because it has over heated. "
+ "Restart the computer. If the problem persists, "
+ "power off the system and replace the adapter\n");
+ /* write to clear the interrupt */
+ IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP0);
}
static void ixgbe_check_fan_failure(struct ixgbe_adapter *adapter, u32 eicr)
@@ -1746,9 +1761,9 @@ static irqreturn_t ixgbe_msix_lsc(int irq, void *data)
netif_tx_stop_all_queues(netdev);
for (i = 0; i < adapter->num_tx_queues; i++) {
struct ixgbe_ring *tx_ring =
- adapter->tx_ring[i];
+ adapter->tx_ring[i];
if (test_and_clear_bit(__IXGBE_FDIR_INIT_DONE,
- &tx_ring->reinit_state))
+ &tx_ring->reinit_state))
schedule_work(&adapter->fdir_reinit_task);
}
}
@@ -1777,7 +1792,7 @@ static inline void ixgbe_irq_enable_queues(struct ixgbe_adapter *adapter,
}
static inline void ixgbe_irq_disable_queues(struct ixgbe_adapter *adapter,
- u64 qmask)
+ u64 qmask)
{
u32 mask;
@@ -1809,7 +1824,7 @@ static irqreturn_t ixgbe_msix_clean_tx(int irq, void *data)
tx_ring->total_bytes = 0;
tx_ring->total_packets = 0;
r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues,
- r_idx + 1);
+ r_idx + 1);
}
/* EIAM disabled interrupts (on this vector) for us */
@@ -1837,7 +1852,7 @@ static irqreturn_t ixgbe_msix_clean_rx(int irq, void *data)
rx_ring->total_bytes = 0;
rx_ring->total_packets = 0;
r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues,
- r_idx + 1);
+ r_idx + 1);
}
if (!q_vector->rxr_count)
@@ -1867,7 +1882,7 @@ static irqreturn_t ixgbe_msix_clean_many(int irq, void *data)
ring->total_bytes = 0;
ring->total_packets = 0;
r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues,
- r_idx + 1);
+ r_idx + 1);
}
r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
@@ -1876,7 +1891,7 @@ static irqreturn_t ixgbe_msix_clean_many(int irq, void *data)
ring->total_bytes = 0;
ring->total_packets = 0;
r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues,
- r_idx + 1);
+ r_idx + 1);
}
/* EIAM disabled interrupts (on this vector) for us */
@@ -1896,7 +1911,7 @@ static irqreturn_t ixgbe_msix_clean_many(int irq, void *data)
static int ixgbe_clean_rxonly(struct napi_struct *napi, int budget)
{
struct ixgbe_q_vector *q_vector =
- container_of(napi, struct ixgbe_q_vector, napi);
+ container_of(napi, struct ixgbe_q_vector, napi);
struct ixgbe_adapter *adapter = q_vector->adapter;
struct ixgbe_ring *rx_ring = NULL;
int work_done = 0;
@@ -1918,7 +1933,7 @@ static int ixgbe_clean_rxonly(struct napi_struct *napi, int budget)
ixgbe_set_itr_msix(q_vector);
if (!test_bit(__IXGBE_DOWN, &adapter->state))
ixgbe_irq_enable_queues(adapter,
- ((u64)1 << q_vector->v_idx));
+ ((u64)1 << q_vector->v_idx));
}
return work_done;
@@ -1935,7 +1950,7 @@ static int ixgbe_clean_rxonly(struct napi_struct *napi, int budget)
static int ixgbe_clean_rxtx_many(struct napi_struct *napi, int budget)
{
struct ixgbe_q_vector *q_vector =
- container_of(napi, struct ixgbe_q_vector, napi);
+ container_of(napi, struct ixgbe_q_vector, napi);
struct ixgbe_adapter *adapter = q_vector->adapter;
struct ixgbe_ring *ring = NULL;
int work_done = 0, i;
@@ -1951,7 +1966,7 @@ static int ixgbe_clean_rxtx_many(struct napi_struct *napi, int budget)
#endif
tx_clean_complete &= ixgbe_clean_tx_irq(q_vector, ring);
r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues,
- r_idx + 1);
+ r_idx + 1);
}
/* attempt to distribute budget to each queue fairly, but don't allow
@@ -1967,7 +1982,7 @@ static int ixgbe_clean_rxtx_many(struct napi_struct *napi, int budget)
#endif
ixgbe_clean_rx_irq(q_vector, ring, &work_done, budget);
r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues,
- r_idx + 1);
+ r_idx + 1);
}
r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
@@ -1979,7 +1994,7 @@ static int ixgbe_clean_rxtx_many(struct napi_struct *napi, int budget)
ixgbe_set_itr_msix(q_vector);
if (!test_bit(__IXGBE_DOWN, &adapter->state))
ixgbe_irq_enable_queues(adapter,
- ((u64)1 << q_vector->v_idx));
+ ((u64)1 << q_vector->v_idx));
return 0;
}
@@ -1997,7 +2012,7 @@ static int ixgbe_clean_rxtx_many(struct napi_struct *napi, int budget)
static int ixgbe_clean_txonly(struct napi_struct *napi, int budget)
{
struct ixgbe_q_vector *q_vector =
- container_of(napi, struct ixgbe_q_vector, napi);
+ container_of(napi, struct ixgbe_q_vector, napi);
struct ixgbe_adapter *adapter = q_vector->adapter;
struct ixgbe_ring *tx_ring = NULL;
int work_done = 0;
@@ -2019,14 +2034,15 @@ static int ixgbe_clean_txonly(struct napi_struct *napi, int budget)
if (adapter->tx_itr_setting & 1)
ixgbe_set_itr_msix(q_vector);
if (!test_bit(__IXGBE_DOWN, &adapter->state))
- ixgbe_irq_enable_queues(adapter, ((u64)1 << q_vector->v_idx));
+ ixgbe_irq_enable_queues(adapter,
+ ((u64)1 << q_vector->v_idx));
}
return work_done;
}
static inline void map_vector_to_rxq(struct ixgbe_adapter *a, int v_idx,
- int r_idx)
+ int r_idx)
{
struct ixgbe_q_vector *q_vector = a->q_vector[v_idx];
@@ -2035,7 +2051,7 @@ static inline void map_vector_to_rxq(struct ixgbe_adapter *a, int v_idx,
}
static inline void map_vector_to_txq(struct ixgbe_adapter *a, int v_idx,
- int t_idx)
+ int t_idx)
{
struct ixgbe_q_vector *q_vector = a->q_vector[v_idx];
@@ -2055,7 +2071,7 @@ static inline void map_vector_to_txq(struct ixgbe_adapter *a, int v_idx,
* mapping configurations in here.
**/
static int ixgbe_map_rings_to_vectors(struct ixgbe_adapter *adapter,
- int vectors)
+ int vectors)
{
int v_start = 0;
int rxr_idx = 0, txr_idx = 0;
@@ -2122,7 +2138,7 @@ static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter)
struct net_device *netdev = adapter->netdev;
irqreturn_t (*handler)(int, void *);
int i, vector, q_vectors, err;
- int ri=0, ti=0;
+ int ri = 0, ti = 0;
/* Decrement for Other and TCP Timer vectors */
q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
@@ -2133,26 +2149,24 @@ static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter)
goto out;
#define SET_HANDLER(_v) ((!(_v)->rxr_count) ? &ixgbe_msix_clean_tx : \
- (!(_v)->txr_count) ? &ixgbe_msix_clean_rx : \
- &ixgbe_msix_clean_many)
+ (!(_v)->txr_count) ? &ixgbe_msix_clean_rx : \
+ &ixgbe_msix_clean_many)
for (vector = 0; vector < q_vectors; vector++) {
handler = SET_HANDLER(adapter->q_vector[vector]);
- if(handler == &ixgbe_msix_clean_rx) {
+ if (handler == &ixgbe_msix_clean_rx) {
sprintf(adapter->name[vector], "%s-%s-%d",
netdev->name, "rx", ri++);
- }
- else if(handler == &ixgbe_msix_clean_tx) {
+ } else if (handler == &ixgbe_msix_clean_tx) {
sprintf(adapter->name[vector], "%s-%s-%d",
netdev->name, "tx", ti++);
- }
- else
+ } else
sprintf(adapter->name[vector], "%s-%s-%d",
netdev->name, "TxRx", vector);
err = request_irq(adapter->msix_entries[vector].vector,
- handler, 0, adapter->name[vector],
- adapter->q_vector[vector]);
+ handler, 0, adapter->name[vector],
+ adapter->q_vector[vector]);
if (err) {
e_err(probe, "request_irq failed for MSIX interrupt "
"Error: %d\n", err);
@@ -2162,7 +2176,7 @@ static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter)
sprintf(adapter->name[vector], "%s:lsc", netdev->name);
err = request_irq(adapter->msix_entries[vector].vector,
- ixgbe_msix_lsc, 0, adapter->name[vector], netdev);
+ ixgbe_msix_lsc, 0, adapter->name[vector], netdev);
if (err) {
e_err(probe, "request_irq for msix_lsc failed: %d\n", err);
goto free_queue_irqs;
@@ -2173,7 +2187,7 @@ static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter)
free_queue_irqs:
for (i = vector - 1; i >= 0; i--)
free_irq(adapter->msix_entries[--vector].vector,
- adapter->q_vector[i]);
+ adapter->q_vector[i]);
adapter->flags &= ~IXGBE_FLAG_MSIX_ENABLED;
pci_disable_msix(adapter->pdev);
kfree(adapter->msix_entries);
@@ -2191,13 +2205,13 @@ static void ixgbe_set_itr(struct ixgbe_adapter *adapter)
struct ixgbe_ring *tx_ring = adapter->tx_ring[0];
q_vector->tx_itr = ixgbe_update_itr(adapter, new_itr,
- q_vector->tx_itr,
- tx_ring->total_packets,
- tx_ring->total_bytes);
+ q_vector->tx_itr,
+ tx_ring->total_packets,
+ tx_ring->total_bytes);
q_vector->rx_itr = ixgbe_update_itr(adapter, new_itr,
- q_vector->rx_itr,
- rx_ring->total_packets,
- rx_ring->total_bytes);
+ q_vector->rx_itr,
+ rx_ring->total_packets,
+ rx_ring->total_bytes);
current_itr = max(q_vector->rx_itr, q_vector->tx_itr);
@@ -2231,7 +2245,8 @@ static void ixgbe_set_itr(struct ixgbe_adapter *adapter)
* ixgbe_irq_enable - Enable default interrupt generation settings
* @adapter: board private structure
**/
-static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter)
+static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter, bool queues,
+ bool flush)
{
u32 mask;
@@ -2252,8 +2267,10 @@ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter)
mask |= IXGBE_EIMS_FLOW_DIR;
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask);
- ixgbe_irq_enable_queues(adapter, ~0);
- IXGBE_WRITE_FLUSH(&adapter->hw);
+ if (queues)
+ ixgbe_irq_enable_queues(adapter, ~0);
+ if (flush)
+ IXGBE_WRITE_FLUSH(&adapter->hw);
if (adapter->num_vfs > 32) {
u32 eitrsel = (1 << (adapter->num_vfs - 32)) - 1;
@@ -2275,7 +2292,7 @@ static irqreturn_t ixgbe_intr(int irq, void *data)
u32 eicr;
/*
- * Workaround for silicon errata. Mask the interrupts
+ * Workaround for silicon errata on 82598. Mask the interrupts
* before the read of EICR.
*/
IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_IRQ_CLEAR_MASK);
@@ -2284,10 +2301,15 @@ static irqreturn_t ixgbe_intr(int irq, void *data)
* therefore no explict interrupt disable is necessary */
eicr = IXGBE_READ_REG(hw, IXGBE_EICR);
if (!eicr) {
- /* shared interrupt alert!
+ /*
+ * shared interrupt alert!
* make sure interrupts are enabled because the read will
- * have disabled interrupts due to EIAM */
- ixgbe_irq_enable(adapter);
+ * have disabled interrupts due to EIAM
+ * finish the workaround of silicon errata on 82598. Unmask
+ * the interrupt that we masked before the EICR read.
+ */
+ if (!test_bit(__IXGBE_DOWN, &adapter->state))
+ ixgbe_irq_enable(adapter, true, true);
return IRQ_NONE; /* Not our interrupt */
}
@@ -2311,6 +2333,14 @@ static irqreturn_t ixgbe_intr(int irq, void *data)
__napi_schedule(&(q_vector->napi));
}
+ /*
+ * re-enable link(maybe) and non-queue interrupts, no flush.
+ * ixgbe_poll will re-enable the queue interrupts
+ */
+
+ if (!test_bit(__IXGBE_DOWN, &adapter->state))
+ ixgbe_irq_enable(adapter, false, false);
+
return IRQ_HANDLED;
}
@@ -2343,10 +2373,10 @@ static int ixgbe_request_irq(struct ixgbe_adapter *adapter)
err = ixgbe_request_msix_irqs(adapter);
} else if (adapter->flags & IXGBE_FLAG_MSI_ENABLED) {
err = request_irq(adapter->pdev->irq, ixgbe_intr, 0,
- netdev->name, netdev);
+ netdev->name, netdev);
} else {
err = request_irq(adapter->pdev->irq, ixgbe_intr, IRQF_SHARED,
- netdev->name, netdev);
+ netdev->name, netdev);
}
if (err)
@@ -2370,7 +2400,7 @@ static void ixgbe_free_irq(struct ixgbe_adapter *adapter)
i--;
for (; i >= 0; i--) {
free_irq(adapter->msix_entries[i].vector,
- adapter->q_vector[i]);
+ adapter->q_vector[i]);
}
ixgbe_reset_q_vectors(adapter);
@@ -2413,7 +2443,7 @@ static void ixgbe_configure_msi_and_legacy(struct ixgbe_adapter *adapter)
struct ixgbe_hw *hw = &adapter->hw;
IXGBE_WRITE_REG(hw, IXGBE_EITR(0),
- EITR_INTS_PER_SEC_TO_REG(adapter->rx_eitr_param));
+ EITR_INTS_PER_SEC_TO_REG(adapter->rx_eitr_param));
ixgbe_set_ivar(adapter, 0, 0, 0);
ixgbe_set_ivar(adapter, 1, 0, 0);
@@ -2425,95 +2455,140 @@ static void ixgbe_configure_msi_and_legacy(struct ixgbe_adapter *adapter)
}
/**
- * ixgbe_configure_tx - Configure 8259x Transmit Unit after Reset
+ * ixgbe_configure_tx_ring - Configure 8259x Tx ring after Reset
* @adapter: board private structure
+ * @ring: structure containing ring specific data
*
- * Configure the Tx unit of the MAC after a reset.
+ * Configure the Tx descriptor ring after a reset.
**/
-static void ixgbe_configure_tx(struct ixgbe_adapter *adapter)
+void ixgbe_configure_tx_ring(struct ixgbe_adapter *adapter,
+ struct ixgbe_ring *ring)
{
- u64 tdba;
struct ixgbe_hw *hw = &adapter->hw;
- u32 i, j, tdlen, txctrl;
+ u64 tdba = ring->dma;
+ int wait_loop = 10;
+ u32 txdctl;
+ u16 reg_idx = ring->reg_idx;
- /* Setup the HW Tx Head and Tail descriptor pointers */
- for (i = 0; i < adapter->num_tx_queues; i++) {
- struct ixgbe_ring *ring = adapter->tx_ring[i];
- j = ring->reg_idx;
- tdba = ring->dma;
- tdlen = ring->count * sizeof(union ixgbe_adv_tx_desc);
- IXGBE_WRITE_REG(hw, IXGBE_TDBAL(j),
- (tdba & DMA_BIT_MASK(32)));
- IXGBE_WRITE_REG(hw, IXGBE_TDBAH(j), (tdba >> 32));
- IXGBE_WRITE_REG(hw, IXGBE_TDLEN(j), tdlen);
- IXGBE_WRITE_REG(hw, IXGBE_TDH(j), 0);
- IXGBE_WRITE_REG(hw, IXGBE_TDT(j), 0);
- adapter->tx_ring[i]->head = IXGBE_TDH(j);
- adapter->tx_ring[i]->tail = IXGBE_TDT(j);
- /*
- * Disable Tx Head Writeback RO bit, since this hoses
- * bookkeeping if things aren't delivered in order.
- */
- switch (hw->mac.type) {
- case ixgbe_mac_82598EB:
- txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(j));
- break;
- case ixgbe_mac_82599EB:
- default:
- txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(j));
- break;
- }
- txctrl &= ~IXGBE_DCA_TXCTRL_TX_WB_RO_EN;
- switch (hw->mac.type) {
- case ixgbe_mac_82598EB:
- IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(j), txctrl);
- break;
- case ixgbe_mac_82599EB:
- default:
- IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(j), txctrl);
- break;
- }
+ /* disable queue to avoid issues while updating state */
+ txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(reg_idx));
+ IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(reg_idx),
+ txdctl & ~IXGBE_TXDCTL_ENABLE);
+ IXGBE_WRITE_FLUSH(hw);
+
+ IXGBE_WRITE_REG(hw, IXGBE_TDBAL(reg_idx),
+ (tdba & DMA_BIT_MASK(32)));
+ IXGBE_WRITE_REG(hw, IXGBE_TDBAH(reg_idx), (tdba >> 32));
+ IXGBE_WRITE_REG(hw, IXGBE_TDLEN(reg_idx),
+ ring->count * sizeof(union ixgbe_adv_tx_desc));
+ IXGBE_WRITE_REG(hw, IXGBE_TDH(reg_idx), 0);
+ IXGBE_WRITE_REG(hw, IXGBE_TDT(reg_idx), 0);
+ ring->head = IXGBE_TDH(reg_idx);
+ ring->tail = IXGBE_TDT(reg_idx);
+
+ /* configure fetching thresholds */
+ if (adapter->rx_itr_setting == 0) {
+ /* cannot set wthresh when itr==0 */
+ txdctl &= ~0x007F0000;
+ } else {
+ /* enable WTHRESH=8 descriptors, to encourage burst writeback */
+ txdctl |= (8 << 16);
+ }
+ if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
+ /* PThresh workaround for Tx hang with DFP enabled. */
+ txdctl |= 32;
}
- if (hw->mac.type == ixgbe_mac_82599EB) {
- u32 rttdcs;
- u32 mask;
+ /* reinitialize flowdirector state */
+ set_bit(__IXGBE_FDIR_INIT_DONE, &ring->reinit_state);
- /* disable the arbiter while setting MTQC */
- rttdcs = IXGBE_READ_REG(hw, IXGBE_RTTDCS);
- rttdcs |= IXGBE_RTTDCS_ARBDIS;
- IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs);
+ /* enable queue */
+ txdctl |= IXGBE_TXDCTL_ENABLE;
+ IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(reg_idx), txdctl);
- /* set transmit pool layout */
- mask = (IXGBE_FLAG_SRIOV_ENABLED | IXGBE_FLAG_DCB_ENABLED);
- switch (adapter->flags & mask) {
+ /* TXDCTL.EN will return 0 on 82598 if link is down, so skip it */
+ if (hw->mac.type == ixgbe_mac_82598EB &&
+ !(IXGBE_READ_REG(hw, IXGBE_LINKS) & IXGBE_LINKS_UP))
+ return;
- case (IXGBE_FLAG_SRIOV_ENABLED):
- IXGBE_WRITE_REG(hw, IXGBE_MTQC,
- (IXGBE_MTQC_VT_ENA | IXGBE_MTQC_64VF));
- break;
+ /* poll to verify queue is enabled */
+ do {
+ msleep(1);
+ txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(reg_idx));
+ } while (--wait_loop && !(txdctl & IXGBE_TXDCTL_ENABLE));
+ if (!wait_loop)
+ e_err(drv, "Could not enable Tx Queue %d\n", reg_idx);
+}
- case (IXGBE_FLAG_DCB_ENABLED):
- /* We enable 8 traffic classes, DCB only */
- IXGBE_WRITE_REG(hw, IXGBE_MTQC,
- (IXGBE_MTQC_RT_ENA | IXGBE_MTQC_8TC_8TQ));
- break;
+static void ixgbe_setup_mtqc(struct ixgbe_adapter *adapter)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ u32 rttdcs;
+ u32 mask;
- default:
- IXGBE_WRITE_REG(hw, IXGBE_MTQC, IXGBE_MTQC_64Q_1PB);
- break;
- }
+ if (hw->mac.type == ixgbe_mac_82598EB)
+ return;
+
+ /* disable the arbiter while setting MTQC */
+ rttdcs = IXGBE_READ_REG(hw, IXGBE_RTTDCS);
+ rttdcs |= IXGBE_RTTDCS_ARBDIS;
+ IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs);
+
+ /* set transmit pool layout */
+ mask = (IXGBE_FLAG_SRIOV_ENABLED | IXGBE_FLAG_DCB_ENABLED);
+ switch (adapter->flags & mask) {
+
+ case (IXGBE_FLAG_SRIOV_ENABLED):
+ IXGBE_WRITE_REG(hw, IXGBE_MTQC,
+ (IXGBE_MTQC_VT_ENA | IXGBE_MTQC_64VF));
+ break;
+
+ case (IXGBE_FLAG_DCB_ENABLED):
+ /* We enable 8 traffic classes, DCB only */
+ IXGBE_WRITE_REG(hw, IXGBE_MTQC,
+ (IXGBE_MTQC_RT_ENA | IXGBE_MTQC_8TC_8TQ));
+ break;
+
+ default:
+ IXGBE_WRITE_REG(hw, IXGBE_MTQC, IXGBE_MTQC_64Q_1PB);
+ break;
+ }
+
+ /* re-enable the arbiter */
+ rttdcs &= ~IXGBE_RTTDCS_ARBDIS;
+ IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs);
+}
- /* re-eable the arbiter */
- rttdcs &= ~IXGBE_RTTDCS_ARBDIS;
- IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs);
+/**
+ * ixgbe_configure_tx - Configure 8259x Transmit Unit after Reset
+ * @adapter: board private structure
+ *
+ * Configure the Tx unit of the MAC after a reset.
+ **/
+static void ixgbe_configure_tx(struct ixgbe_adapter *adapter)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ u32 dmatxctl;
+ u32 i;
+
+ ixgbe_setup_mtqc(adapter);
+
+ if (hw->mac.type != ixgbe_mac_82598EB) {
+ /* DMATXCTL.EN must be before Tx queues are enabled */
+ dmatxctl = IXGBE_READ_REG(hw, IXGBE_DMATXCTL);
+ dmatxctl |= IXGBE_DMATXCTL_TE;
+ IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, dmatxctl);
}
+
+ /* Setup the HW Tx Head and Tail descriptor pointers */
+ for (i = 0; i < adapter->num_tx_queues; i++)
+ ixgbe_configure_tx_ring(adapter, adapter->tx_ring[i]);
}
#define IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT 2
static void ixgbe_configure_srrctl(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *rx_ring)
+ struct ixgbe_ring *rx_ring)
{
u32 srrctl;
int index;
@@ -2529,6 +2604,8 @@ static void ixgbe_configure_srrctl(struct ixgbe_adapter *adapter,
srrctl &= ~IXGBE_SRRCTL_BSIZEHDR_MASK;
srrctl &= ~IXGBE_SRRCTL_BSIZEPKT_MASK;
+ if (adapter->num_vfs)
+ srrctl |= IXGBE_SRRCTL_DROP_EN;
srrctl |= (IXGBE_RX_HDR_SIZE << IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT) &
IXGBE_SRRCTL_BSIZEHDR_MASK;
@@ -2549,20 +2626,46 @@ static void ixgbe_configure_srrctl(struct ixgbe_adapter *adapter,
IXGBE_WRITE_REG(&adapter->hw, IXGBE_SRRCTL(index), srrctl);
}
-static u32 ixgbe_setup_mrqc(struct ixgbe_adapter *adapter)
+static void ixgbe_setup_mrqc(struct ixgbe_adapter *adapter)
{
- u32 mrqc = 0;
+ struct ixgbe_hw *hw = &adapter->hw;
+ static const u32 seed[10] = { 0xE291D73D, 0x1805EC6C, 0x2A94B30D,
+ 0xA54F2BEC, 0xEA49AF7C, 0xE214AD3D, 0xB855AABE,
+ 0x6A3E67EA, 0x14364D17, 0x3BED200D};
+ u32 mrqc = 0, reta = 0;
+ u32 rxcsum;
+ int i, j;
int mask;
- if (!(adapter->hw.mac.type == ixgbe_mac_82599EB))
- return mrqc;
+ /* Fill out hash function seeds */
+ for (i = 0; i < 10; i++)
+ IXGBE_WRITE_REG(hw, IXGBE_RSSRK(i), seed[i]);
- mask = adapter->flags & (IXGBE_FLAG_RSS_ENABLED
+ /* Fill out redirection table */
+ for (i = 0, j = 0; i < 128; i++, j++) {
+ if (j == adapter->ring_feature[RING_F_RSS].indices)
+ j = 0;
+ /* reta = 4-byte sliding window of
+ * 0x00..(indices-1)(indices-1)00..etc. */
+ reta = (reta << 8) | (j * 0x11);
+ if ((i & 3) == 3)
+ IXGBE_WRITE_REG(hw, IXGBE_RETA(i >> 2), reta);
+ }
+
+ /* Disable indicating checksum in descriptor, enables RSS hash */
+ rxcsum = IXGBE_READ_REG(hw, IXGBE_RXCSUM);
+ rxcsum |= IXGBE_RXCSUM_PCSD;
+ IXGBE_WRITE_REG(hw, IXGBE_RXCSUM, rxcsum);
+
+ if (adapter->hw.mac.type == ixgbe_mac_82598EB)
+ mask = adapter->flags & IXGBE_FLAG_RSS_ENABLED;
+ else
+ mask = adapter->flags & (IXGBE_FLAG_RSS_ENABLED
#ifdef CONFIG_IXGBE_DCB
- | IXGBE_FLAG_DCB_ENABLED
+ | IXGBE_FLAG_DCB_ENABLED
#endif
- | IXGBE_FLAG_SRIOV_ENABLED
- );
+ | IXGBE_FLAG_SRIOV_ENABLED
+ );
switch (mask) {
case (IXGBE_FLAG_RSS_ENABLED):
@@ -2580,7 +2683,13 @@ static u32 ixgbe_setup_mrqc(struct ixgbe_adapter *adapter)
break;
}
- return mrqc;
+ /* Perform hash on these packet types */
+ mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4
+ | IXGBE_MRQC_RSS_FIELD_IPV4_TCP
+ | IXGBE_MRQC_RSS_FIELD_IPV6
+ | IXGBE_MRQC_RSS_FIELD_IPV6_TCP;
+
+ IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc);
}
/**
@@ -2588,25 +2697,26 @@ static u32 ixgbe_setup_mrqc(struct ixgbe_adapter *adapter)
* @adapter: address of board private structure
* @index: index of ring to set
**/
-static void ixgbe_configure_rscctl(struct ixgbe_adapter *adapter, int index)
+static void ixgbe_configure_rscctl(struct ixgbe_adapter *adapter,
+ struct ixgbe_ring *ring)
{
- struct ixgbe_ring *rx_ring;
struct ixgbe_hw *hw = &adapter->hw;
- int j;
u32 rscctrl;
int rx_buf_len;
+ u16 reg_idx = ring->reg_idx;
+
+ if (!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED))
+ return;
- rx_ring = adapter->rx_ring[index];
- j = rx_ring->reg_idx;
- rx_buf_len = rx_ring->rx_buf_len;
- rscctrl = IXGBE_READ_REG(hw, IXGBE_RSCCTL(j));
+ rx_buf_len = ring->rx_buf_len;
+ rscctrl = IXGBE_READ_REG(hw, IXGBE_RSCCTL(reg_idx));
rscctrl |= IXGBE_RSCCTL_RSCEN;
/*
* we must limit the number of descriptors so that the
* total size of max desc * buf_len is not greater
* than 65535
*/
- if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) {
+ if (ring->flags & IXGBE_RING_RX_PS_ENABLED) {
#if (MAX_SKB_FRAGS > 16)
rscctrl |= IXGBE_RSCCTL_MAXDESC_16;
#elif (MAX_SKB_FRAGS > 8)
@@ -2624,31 +2734,181 @@ static void ixgbe_configure_rscctl(struct ixgbe_adapter *adapter, int index)
else
rscctrl |= IXGBE_RSCCTL_MAXDESC_4;
}
- IXGBE_WRITE_REG(hw, IXGBE_RSCCTL(j), rscctrl);
+ IXGBE_WRITE_REG(hw, IXGBE_RSCCTL(reg_idx), rscctrl);
}
/**
- * ixgbe_configure_rx - Configure 8259x Receive Unit after Reset
- * @adapter: board private structure
+ * ixgbe_set_uta - Set unicast filter table address
+ * @adapter: board private structure
*
- * Configure the Rx unit of the MAC after a reset.
+ * The unicast table address is a register array of 32-bit registers.
+ * The table is meant to be used in a way similar to how the MTA is used
+ * however due to certain limitations in the hardware it is necessary to
+ * set all the hash bits to 1 and use the VMOLR ROPE bit as a promiscuous
+ * enable bit to allow vlan tag stripping when promiscuous mode is enabled
**/
-static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
+static void ixgbe_set_uta(struct ixgbe_adapter *adapter)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ int i;
+
+ /* The UTA table only exists on 82599 hardware and newer */
+ if (hw->mac.type < ixgbe_mac_82599EB)
+ return;
+
+ /* we only need to do this if VMDq is enabled */
+ if (!(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED))
+ return;
+
+ for (i = 0; i < 128; i++)
+ IXGBE_WRITE_REG(hw, IXGBE_UTA(i), ~0);
+}
+
+#define IXGBE_MAX_RX_DESC_POLL 10
+static void ixgbe_rx_desc_queue_enable(struct ixgbe_adapter *adapter,
+ struct ixgbe_ring *ring)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ int reg_idx = ring->reg_idx;
+ int wait_loop = IXGBE_MAX_RX_DESC_POLL;
+ u32 rxdctl;
+
+ /* RXDCTL.EN will return 0 on 82598 if link is down, so skip it */
+ if (hw->mac.type == ixgbe_mac_82598EB &&
+ !(IXGBE_READ_REG(hw, IXGBE_LINKS) & IXGBE_LINKS_UP))
+ return;
+
+ do {
+ msleep(1);
+ rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(reg_idx));
+ } while (--wait_loop && !(rxdctl & IXGBE_RXDCTL_ENABLE));
+
+ if (!wait_loop) {
+ e_err(drv, "RXDCTL.ENABLE on Rx queue %d not set within "
+ "the polling period\n", reg_idx);
+ }
+}
+
+void ixgbe_configure_rx_ring(struct ixgbe_adapter *adapter,
+ struct ixgbe_ring *ring)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ u64 rdba = ring->dma;
+ u32 rxdctl;
+ u16 reg_idx = ring->reg_idx;
+
+ /* disable queue to avoid issues while updating state */
+ rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(reg_idx));
+ IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(reg_idx),
+ rxdctl & ~IXGBE_RXDCTL_ENABLE);
+ IXGBE_WRITE_FLUSH(hw);
+
+ IXGBE_WRITE_REG(hw, IXGBE_RDBAL(reg_idx), (rdba & DMA_BIT_MASK(32)));
+ IXGBE_WRITE_REG(hw, IXGBE_RDBAH(reg_idx), (rdba >> 32));
+ IXGBE_WRITE_REG(hw, IXGBE_RDLEN(reg_idx),
+ ring->count * sizeof(union ixgbe_adv_rx_desc));
+ IXGBE_WRITE_REG(hw, IXGBE_RDH(reg_idx), 0);
+ IXGBE_WRITE_REG(hw, IXGBE_RDT(reg_idx), 0);
+ ring->head = IXGBE_RDH(reg_idx);
+ ring->tail = IXGBE_RDT(reg_idx);
+
+ ixgbe_configure_srrctl(adapter, ring);
+ ixgbe_configure_rscctl(adapter, ring);
+
+ if (hw->mac.type == ixgbe_mac_82598EB) {
+ /*
+ * enable cache line friendly hardware writes:
+ * PTHRESH=32 descriptors (half the internal cache),
+ * this also removes ugly rx_no_buffer_count increment
+ * HTHRESH=4 descriptors (to minimize latency on fetch)
+ * WTHRESH=8 burst writeback up to two cache lines
+ */
+ rxdctl &= ~0x3FFFFF;
+ rxdctl |= 0x080420;
+ }
+
+ /* enable receive descriptor ring */
+ rxdctl |= IXGBE_RXDCTL_ENABLE;
+ IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(reg_idx), rxdctl);
+
+ ixgbe_rx_desc_queue_enable(adapter, ring);
+ ixgbe_alloc_rx_buffers(adapter, ring, IXGBE_DESC_UNUSED(ring));
+}
+
+static void ixgbe_setup_psrtype(struct ixgbe_adapter *adapter)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ int p;
+
+ /* PSRTYPE must be initialized in non 82598 adapters */
+ u32 psrtype = IXGBE_PSRTYPE_TCPHDR |
+ IXGBE_PSRTYPE_UDPHDR |
+ IXGBE_PSRTYPE_IPV4HDR |
+ IXGBE_PSRTYPE_L2HDR |
+ IXGBE_PSRTYPE_IPV6HDR;
+
+ if (hw->mac.type == ixgbe_mac_82598EB)
+ return;
+
+ if (adapter->flags & IXGBE_FLAG_RSS_ENABLED)
+ psrtype |= (adapter->num_rx_queues_per_pool << 29);
+
+ for (p = 0; p < adapter->num_rx_pools; p++)
+ IXGBE_WRITE_REG(hw, IXGBE_PSRTYPE(adapter->num_vfs + p),
+ psrtype);
+}
+
+static void ixgbe_configure_virtualization(struct ixgbe_adapter *adapter)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ u32 gcr_ext;
+ u32 vt_reg_bits;
+ u32 reg_offset, vf_shift;
+ u32 vmdctl;
+
+ if (!(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED))
+ return;
+
+ vmdctl = IXGBE_READ_REG(hw, IXGBE_VT_CTL);
+ vt_reg_bits = IXGBE_VMD_CTL_VMDQ_EN | IXGBE_VT_CTL_REPLEN;
+ vt_reg_bits |= (adapter->num_vfs << IXGBE_VT_CTL_POOL_SHIFT);
+ IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, vmdctl | vt_reg_bits);
+
+ vf_shift = adapter->num_vfs % 32;
+ reg_offset = (adapter->num_vfs > 32) ? 1 : 0;
+
+ /* Enable only the PF's pool for Tx/Rx */
+ IXGBE_WRITE_REG(hw, IXGBE_VFRE(reg_offset), (1 << vf_shift));
+ IXGBE_WRITE_REG(hw, IXGBE_VFRE(reg_offset ^ 1), 0);
+ IXGBE_WRITE_REG(hw, IXGBE_VFTE(reg_offset), (1 << vf_shift));
+ IXGBE_WRITE_REG(hw, IXGBE_VFTE(reg_offset ^ 1), 0);
+ IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN);
+
+ /* Map PF MAC address in RAR Entry 0 to first pool following VFs */
+ hw->mac.ops.set_vmdq(hw, 0, adapter->num_vfs);
+
+ /*
+ * Set up VF register offsets for selected VT Mode,
+ * i.e. 32 or 64 VFs for SR-IOV
+ */
+ gcr_ext = IXGBE_READ_REG(hw, IXGBE_GCR_EXT);
+ gcr_ext |= IXGBE_GCR_EXT_MSIX_EN;
+ gcr_ext |= IXGBE_GCR_EXT_VT_MODE_64;
+ IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, gcr_ext);
+
+ /* enable Tx loopback for VF/PF communication */
+ IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN);
+}
+
+static void ixgbe_set_rx_buffer_len(struct ixgbe_adapter *adapter)
{
- u64 rdba;
struct ixgbe_hw *hw = &adapter->hw;
- struct ixgbe_ring *rx_ring;
struct net_device *netdev = adapter->netdev;
int max_frame = netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
- int i, j;
- u32 rdlen, rxctrl, rxcsum;
- static const u32 seed[10] = { 0xE291D73D, 0x1805EC6C, 0x2A94B30D,
- 0xA54F2BEC, 0xEA49AF7C, 0xE214AD3D, 0xB855AABE,
- 0x6A3E67EA, 0x14364D17, 0x3BED200D};
- u32 fctrl, hlreg0;
- u32 reta = 0, mrqc = 0;
- u32 rdrxctl;
int rx_buf_len;
+ struct ixgbe_ring *rx_ring;
+ int i;
+ u32 mhadd, hlreg0;
/* Decide whether to use packet split mode or not */
/* Do not use packet split if we're in SR-IOV Mode */
@@ -2658,62 +2918,40 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
/* Set the RX buffer length according to the mode */
if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) {
rx_buf_len = IXGBE_RX_HDR_SIZE;
- if (hw->mac.type == ixgbe_mac_82599EB) {
- /* PSRTYPE must be initialized in 82599 */
- u32 psrtype = IXGBE_PSRTYPE_TCPHDR |
- IXGBE_PSRTYPE_UDPHDR |
- IXGBE_PSRTYPE_IPV4HDR |
- IXGBE_PSRTYPE_IPV6HDR |
- IXGBE_PSRTYPE_L2HDR;
- IXGBE_WRITE_REG(hw,
- IXGBE_PSRTYPE(adapter->num_vfs),
- psrtype);
- }
} else {
if (!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) &&
(netdev->mtu <= ETH_DATA_LEN))
rx_buf_len = MAXIMUM_ETHERNET_VLAN_SIZE;
else
- rx_buf_len = ALIGN(max_frame, 1024);
+ rx_buf_len = ALIGN(max_frame + VLAN_HLEN, 1024);
}
- fctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL);
- fctrl |= IXGBE_FCTRL_BAM;
- fctrl |= IXGBE_FCTRL_DPF; /* discard pause frames when FC enabled */
- fctrl |= IXGBE_FCTRL_PMCF;
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, fctrl);
+#ifdef IXGBE_FCOE
+ /* adjust max frame to be able to do baby jumbo for FCoE */
+ if ((adapter->flags & IXGBE_FLAG_FCOE_ENABLED) &&
+ (max_frame < IXGBE_FCOE_JUMBO_FRAME_SIZE))
+ max_frame = IXGBE_FCOE_JUMBO_FRAME_SIZE;
+
+#endif /* IXGBE_FCOE */
+ mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD);
+ if (max_frame != (mhadd >> IXGBE_MHADD_MFS_SHIFT)) {
+ mhadd &= ~IXGBE_MHADD_MFS_MASK;
+ mhadd |= max_frame << IXGBE_MHADD_MFS_SHIFT;
+
+ IXGBE_WRITE_REG(hw, IXGBE_MHADD, mhadd);
+ }
hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0);
- if (adapter->netdev->mtu <= ETH_DATA_LEN)
- hlreg0 &= ~IXGBE_HLREG0_JUMBOEN;
- else
- hlreg0 |= IXGBE_HLREG0_JUMBOEN;
-#ifdef IXGBE_FCOE
- if (netdev->features & NETIF_F_FCOE_MTU)
- hlreg0 |= IXGBE_HLREG0_JUMBOEN;
-#endif
+ /* set jumbo enable since MHADD.MFS is keeping size locked at max_frame */
+ hlreg0 |= IXGBE_HLREG0_JUMBOEN;
IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0);
- rdlen = adapter->rx_ring[0]->count * sizeof(union ixgbe_adv_rx_desc);
- /* disable receives while setting up the descriptors */
- rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
- IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl & ~IXGBE_RXCTRL_RXEN);
-
/*
* Setup the HW Rx Head and Tail Descriptor Pointers and
* the Base and Length of the Rx Descriptor Ring
*/
for (i = 0; i < adapter->num_rx_queues; i++) {
rx_ring = adapter->rx_ring[i];
- rdba = rx_ring->dma;
- j = rx_ring->reg_idx;
- IXGBE_WRITE_REG(hw, IXGBE_RDBAL(j), (rdba & DMA_BIT_MASK(32)));
- IXGBE_WRITE_REG(hw, IXGBE_RDBAH(j), (rdba >> 32));
- IXGBE_WRITE_REG(hw, IXGBE_RDLEN(j), rdlen);
- IXGBE_WRITE_REG(hw, IXGBE_RDH(j), 0);
- IXGBE_WRITE_REG(hw, IXGBE_RDT(j), 0);
- rx_ring->head = IXGBE_RDH(j);
- rx_ring->tail = IXGBE_RDT(j);
rx_ring->rx_buf_len = rx_buf_len;
if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED)
@@ -2729,15 +2967,21 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
rx_ring->flags &= ~IXGBE_RING_RX_PS_ENABLED;
if (rx_buf_len < IXGBE_FCOE_JUMBO_FRAME_SIZE)
rx_ring->rx_buf_len =
- IXGBE_FCOE_JUMBO_FRAME_SIZE;
+ IXGBE_FCOE_JUMBO_FRAME_SIZE;
}
}
-
#endif /* IXGBE_FCOE */
- ixgbe_configure_srrctl(adapter, rx_ring);
}
- if (hw->mac.type == ixgbe_mac_82598EB) {
+}
+
+static void ixgbe_setup_rdrxctl(struct ixgbe_adapter *adapter)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ u32 rdrxctl = IXGBE_READ_REG(hw, IXGBE_RDRXCTL);
+
+ switch (hw->mac.type) {
+ case ixgbe_mac_82598EB:
/*
* For VMDq support of different descriptor types or
* buffer sizes through the use of multiple SRRCTL
@@ -2748,110 +2992,66 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
* effects of setting this bit are only that SRRCTL must be
* fully programmed [0..15]
*/
- rdrxctl = IXGBE_READ_REG(hw, IXGBE_RDRXCTL);
rdrxctl |= IXGBE_RDRXCTL_MVMEN;
- IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, rdrxctl);
+ break;
+ case ixgbe_mac_82599EB:
+ /* Disable RSC for ACK packets */
+ IXGBE_WRITE_REG(hw, IXGBE_RSCDBU,
+ (IXGBE_RSCDBU_RSCACKDIS | IXGBE_READ_REG(hw, IXGBE_RSCDBU)));
+ rdrxctl &= ~IXGBE_RDRXCTL_RSCFRSTSIZE;
+ /* hardware requires some bits to be set by default */
+ rdrxctl |= (IXGBE_RDRXCTL_RSCACKC | IXGBE_RDRXCTL_FCOE_WRFIX);
+ rdrxctl |= IXGBE_RDRXCTL_CRCSTRIP;
+ break;
+ default:
+ /* We should do nothing since we don't know this hardware */
+ return;
}
- if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) {
- u32 vt_reg_bits;
- u32 reg_offset, vf_shift;
- u32 vmdctl = IXGBE_READ_REG(hw, IXGBE_VT_CTL);
- vt_reg_bits = IXGBE_VMD_CTL_VMDQ_EN
- | IXGBE_VT_CTL_REPLEN;
- vt_reg_bits |= (adapter->num_vfs <<
- IXGBE_VT_CTL_POOL_SHIFT);
- IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, vmdctl | vt_reg_bits);
- IXGBE_WRITE_REG(hw, IXGBE_MRQC, 0);
-
- vf_shift = adapter->num_vfs % 32;
- reg_offset = adapter->num_vfs / 32;
- IXGBE_WRITE_REG(hw, IXGBE_VFRE(0), 0);
- IXGBE_WRITE_REG(hw, IXGBE_VFRE(1), 0);
- IXGBE_WRITE_REG(hw, IXGBE_VFTE(0), 0);
- IXGBE_WRITE_REG(hw, IXGBE_VFTE(1), 0);
- /* Enable only the PF's pool for Tx/Rx */
- IXGBE_WRITE_REG(hw, IXGBE_VFRE(reg_offset), (1 << vf_shift));
- IXGBE_WRITE_REG(hw, IXGBE_VFTE(reg_offset), (1 << vf_shift));
- IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN);
- ixgbe_set_vmolr(hw, adapter->num_vfs, true);
- }
-
- /* Program MRQC for the distribution of queues */
- mrqc = ixgbe_setup_mrqc(adapter);
-
- if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) {
- /* Fill out redirection table */
- for (i = 0, j = 0; i < 128; i++, j++) {
- if (j == adapter->ring_feature[RING_F_RSS].indices)
- j = 0;
- /* reta = 4-byte sliding window of
- * 0x00..(indices-1)(indices-1)00..etc. */
- reta = (reta << 8) | (j * 0x11);
- if ((i & 3) == 3)
- IXGBE_WRITE_REG(hw, IXGBE_RETA(i >> 2), reta);
- }
-
- /* Fill out hash function seeds */
- for (i = 0; i < 10; i++)
- IXGBE_WRITE_REG(hw, IXGBE_RSSRK(i), seed[i]);
-
- if (hw->mac.type == ixgbe_mac_82598EB)
- mrqc |= IXGBE_MRQC_RSSEN;
- /* Perform hash on these packet types */
- mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4
- | IXGBE_MRQC_RSS_FIELD_IPV4_TCP
- | IXGBE_MRQC_RSS_FIELD_IPV6
- | IXGBE_MRQC_RSS_FIELD_IPV6_TCP;
- }
- IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc);
+ IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, rdrxctl);
+}
- if (adapter->num_vfs) {
- u32 reg;
+/**
+ * ixgbe_configure_rx - Configure 8259x Receive Unit after Reset
+ * @adapter: board private structure
+ *
+ * Configure the Rx unit of the MAC after a reset.
+ **/
+static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ int i;
+ u32 rxctrl;
- /* Map PF MAC address in RAR Entry 0 to first pool
- * following VFs */
- hw->mac.ops.set_vmdq(hw, 0, adapter->num_vfs);
+ /* disable receives while setting up the descriptors */
+ rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
+ IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl & ~IXGBE_RXCTRL_RXEN);
- /* Set up VF register offsets for selected VT Mode, i.e.
- * 64 VFs for SR-IOV */
- reg = IXGBE_READ_REG(hw, IXGBE_GCR_EXT);
- reg |= IXGBE_GCR_EXT_SRIOV;
- IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, reg);
- }
+ ixgbe_setup_psrtype(adapter);
+ ixgbe_setup_rdrxctl(adapter);
- rxcsum = IXGBE_READ_REG(hw, IXGBE_RXCSUM);
+ /* Program registers for the distribution of queues */
+ ixgbe_setup_mrqc(adapter);
- if (adapter->flags & IXGBE_FLAG_RSS_ENABLED ||
- adapter->flags & IXGBE_FLAG_RX_CSUM_ENABLED) {
- /* Disable indicating checksum in descriptor, enables
- * RSS hash */
- rxcsum |= IXGBE_RXCSUM_PCSD;
- }
- if (!(rxcsum & IXGBE_RXCSUM_PCSD)) {
- /* Enable IPv4 payload checksum for UDP fragments
- * if PCSD is not set */
- rxcsum |= IXGBE_RXCSUM_IPPCSE;
- }
+ ixgbe_set_uta(adapter);
- IXGBE_WRITE_REG(hw, IXGBE_RXCSUM, rxcsum);
+ /* set_rx_buffer_len must be called before ring initialization */
+ ixgbe_set_rx_buffer_len(adapter);
- if (hw->mac.type == ixgbe_mac_82599EB) {
- rdrxctl = IXGBE_READ_REG(hw, IXGBE_RDRXCTL);
- rdrxctl |= IXGBE_RDRXCTL_CRCSTRIP;
- rdrxctl &= ~IXGBE_RDRXCTL_RSCFRSTSIZE;
- IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, rdrxctl);
- }
+ /*
+ * Setup the HW Rx Head and Tail Descriptor Pointers and
+ * the Base and Length of the Rx Descriptor Ring
+ */
+ for (i = 0; i < adapter->num_rx_queues; i++)
+ ixgbe_configure_rx_ring(adapter, adapter->rx_ring[i]);
- if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) {
- /* Enable 82599 HW-RSC */
- for (i = 0; i < adapter->num_rx_queues; i++)
- ixgbe_configure_rscctl(adapter, i);
+ /* disable drop enable for 82598 parts */
+ if (hw->mac.type == ixgbe_mac_82598EB)
+ rxctrl |= IXGBE_RXCTRL_DMBYPS;
- /* Disable RSC for ACK packets */
- IXGBE_WRITE_REG(hw, IXGBE_RSCDBU,
- (IXGBE_RSCDBU_RSCACKDIS | IXGBE_READ_REG(hw, IXGBE_RSCDBU)));
- }
+ /* enable all receives */
+ rxctrl |= IXGBE_RXCTRL_RXEN;
+ hw->mac.ops.enable_rx_dma(hw, rxctrl);
}
static void ixgbe_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
@@ -2862,6 +3062,7 @@ static void ixgbe_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
/* add VID to filter table */
hw->mac.ops.set_vfta(&adapter->hw, vid, pool_ndx, true);
+ set_bit(vid, adapter->active_vlans);
}
static void ixgbe_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
@@ -2870,16 +3071,9 @@ static void ixgbe_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
struct ixgbe_hw *hw = &adapter->hw;
int pool_ndx = adapter->num_vfs;
- if (!test_bit(__IXGBE_DOWN, &adapter->state))
- ixgbe_irq_disable(adapter);
-
- vlan_group_set_device(adapter->vlgrp, vid, NULL);
-
- if (!test_bit(__IXGBE_DOWN, &adapter->state))
- ixgbe_irq_enable(adapter);
-
/* remove VID from filter table */
hw->mac.ops.set_vfta(&adapter->hw, vid, pool_ndx, false);
+ clear_bit(vid, adapter->active_vlans);
}
/**
@@ -2889,27 +3083,45 @@ static void ixgbe_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
static void ixgbe_vlan_filter_disable(struct ixgbe_adapter *adapter)
{
struct ixgbe_hw *hw = &adapter->hw;
- u32 vlnctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
+ u32 vlnctrl;
+
+ vlnctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
+ vlnctrl &= ~(IXGBE_VLNCTRL_VFE | IXGBE_VLNCTRL_CFIEN);
+ IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl);
+}
+
+/**
+ * ixgbe_vlan_filter_enable - helper to enable hw vlan filtering
+ * @adapter: driver data
+ */
+static void ixgbe_vlan_filter_enable(struct ixgbe_adapter *adapter)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ u32 vlnctrl;
+
+ vlnctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
+ vlnctrl |= IXGBE_VLNCTRL_VFE;
+ vlnctrl &= ~IXGBE_VLNCTRL_CFIEN;
+ IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl);
+}
+
+/**
+ * ixgbe_vlan_strip_disable - helper to disable hw vlan stripping
+ * @adapter: driver data
+ */
+static void ixgbe_vlan_strip_disable(struct ixgbe_adapter *adapter)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ u32 vlnctrl;
int i, j;
switch (hw->mac.type) {
case ixgbe_mac_82598EB:
- vlnctrl &= ~IXGBE_VLNCTRL_VFE;
-#ifdef CONFIG_IXGBE_DCB
- if (!(adapter->flags & IXGBE_FLAG_DCB_ENABLED))
- vlnctrl &= ~IXGBE_VLNCTRL_VME;
-#endif
- vlnctrl &= ~IXGBE_VLNCTRL_CFIEN;
+ vlnctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
+ vlnctrl &= ~IXGBE_VLNCTRL_VME;
IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl);
break;
case ixgbe_mac_82599EB:
- vlnctrl &= ~IXGBE_VLNCTRL_VFE;
- vlnctrl &= ~IXGBE_VLNCTRL_CFIEN;
- IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl);
-#ifdef CONFIG_IXGBE_DCB
- if (adapter->flags & IXGBE_FLAG_DCB_ENABLED)
- break;
-#endif
for (i = 0; i < adapter->num_rx_queues; i++) {
j = adapter->rx_ring[i]->reg_idx;
vlnctrl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(j));
@@ -2923,25 +3135,22 @@ static void ixgbe_vlan_filter_disable(struct ixgbe_adapter *adapter)
}
/**
- * ixgbe_vlan_filter_enable - helper to enable hw vlan filtering
+ * ixgbe_vlan_strip_enable - helper to enable hw vlan stripping
* @adapter: driver data
*/
-static void ixgbe_vlan_filter_enable(struct ixgbe_adapter *adapter)
+static void ixgbe_vlan_strip_enable(struct ixgbe_adapter *adapter)
{
struct ixgbe_hw *hw = &adapter->hw;
- u32 vlnctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
+ u32 vlnctrl;
int i, j;
switch (hw->mac.type) {
case ixgbe_mac_82598EB:
- vlnctrl |= IXGBE_VLNCTRL_VME | IXGBE_VLNCTRL_VFE;
- vlnctrl &= ~IXGBE_VLNCTRL_CFIEN;
+ vlnctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
+ vlnctrl |= IXGBE_VLNCTRL_VME;
IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl);
break;
case ixgbe_mac_82599EB:
- vlnctrl |= IXGBE_VLNCTRL_VFE;
- vlnctrl &= ~IXGBE_VLNCTRL_CFIEN;
- IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl);
for (i = 0; i < adapter->num_rx_queues; i++) {
j = adapter->rx_ring[i]->reg_idx;
vlnctrl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(j));
@@ -2954,40 +3163,14 @@ static void ixgbe_vlan_filter_enable(struct ixgbe_adapter *adapter)
}
}
-static void ixgbe_vlan_rx_register(struct net_device *netdev,
- struct vlan_group *grp)
-{
- struct ixgbe_adapter *adapter = netdev_priv(netdev);
-
- if (!test_bit(__IXGBE_DOWN, &adapter->state))
- ixgbe_irq_disable(adapter);
- adapter->vlgrp = grp;
-
- /*
- * For a DCB driver, always enable VLAN tag stripping so we can
- * still receive traffic from a DCB-enabled host even if we're
- * not in DCB mode.
- */
- ixgbe_vlan_filter_enable(adapter);
-
- ixgbe_vlan_rx_add_vid(netdev, 0);
-
- if (!test_bit(__IXGBE_DOWN, &adapter->state))
- ixgbe_irq_enable(adapter);
-}
-
static void ixgbe_restore_vlan(struct ixgbe_adapter *adapter)
{
- ixgbe_vlan_rx_register(adapter->netdev, adapter->vlgrp);
+ u16 vid;
- if (adapter->vlgrp) {
- u16 vid;
- for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
- if (!vlan_group_get_device(adapter->vlgrp, vid))
- continue;
- ixgbe_vlan_rx_add_vid(adapter->netdev, vid);
- }
- }
+ ixgbe_vlan_rx_add_vid(adapter->netdev, 0);
+
+ for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID)
+ ixgbe_vlan_rx_add_vid(adapter->netdev, vid);
}
/**
@@ -3052,6 +3235,11 @@ void ixgbe_set_rx_mode(struct net_device *netdev)
fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL);
+ /* set all bits that we expect to always be set */
+ fctrl |= IXGBE_FCTRL_BAM;
+ fctrl |= IXGBE_FCTRL_DPF; /* discard pause frames when FC enabled */
+ fctrl |= IXGBE_FCTRL_PMCF;
+
/* clear the bits we are changing the status of */
fctrl &= ~(IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
@@ -3097,6 +3285,11 @@ void ixgbe_set_rx_mode(struct net_device *netdev)
}
IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl);
+
+ if (netdev->features & NETIF_F_HW_VLAN_RX)
+ ixgbe_vlan_strip_enable(adapter);
+ else
+ ixgbe_vlan_strip_disable(adapter);
}
static void ixgbe_napi_enable_all(struct ixgbe_adapter *adapter)
@@ -3157,7 +3350,15 @@ static void ixgbe_configure_dcb(struct ixgbe_adapter *adapter)
u32 txdctl;
int i, j;
- ixgbe_dcb_check_config(&adapter->dcb_cfg);
+ if (!(adapter->flags & IXGBE_FLAG_DCB_ENABLED)) {
+ if (hw->mac.type == ixgbe_mac_82598EB)
+ netif_set_gso_max_size(adapter->netdev, 65536);
+ return;
+ }
+
+ if (hw->mac.type == ixgbe_mac_82598EB)
+ netif_set_gso_max_size(adapter->netdev, 32768);
+
ixgbe_dcb_calculate_tc_credits(&adapter->dcb_cfg, DCB_TX_CONFIG);
ixgbe_dcb_calculate_tc_credits(&adapter->dcb_cfg, DCB_RX_CONFIG);
@@ -3172,7 +3373,7 @@ static void ixgbe_configure_dcb(struct ixgbe_adapter *adapter)
IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(j), txdctl);
}
/* Enable VLAN tag insert/strip */
- ixgbe_vlan_filter_enable(adapter);
+ adapter->netdev->features |= NETIF_F_HW_VLAN_RX;
hw->mac.ops.set_vfta(&adapter->hw, 0, 0, true);
}
@@ -3184,23 +3385,13 @@ static void ixgbe_configure(struct ixgbe_adapter *adapter)
struct ixgbe_hw *hw = &adapter->hw;
int i;
- ixgbe_set_rx_mode(netdev);
-
- ixgbe_restore_vlan(adapter);
#ifdef CONFIG_IXGBE_DCB
- if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
- if (hw->mac.type == ixgbe_mac_82598EB)
- netif_set_gso_max_size(netdev, 32768);
- else
- netif_set_gso_max_size(netdev, 65536);
- ixgbe_configure_dcb(adapter);
- } else {
- netif_set_gso_max_size(netdev, 65536);
- }
-#else
- netif_set_gso_max_size(netdev, 65536);
+ ixgbe_configure_dcb(adapter);
#endif
+ ixgbe_set_rx_mode(netdev);
+ ixgbe_restore_vlan(adapter);
+
#ifdef IXGBE_FCOE
if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED)
ixgbe_configure_fcoe(adapter);
@@ -3209,17 +3400,15 @@ static void ixgbe_configure(struct ixgbe_adapter *adapter)
if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) {
for (i = 0; i < adapter->num_tx_queues; i++)
adapter->tx_ring[i]->atr_sample_rate =
- adapter->atr_sample_rate;
+ adapter->atr_sample_rate;
ixgbe_init_fdir_signature_82599(hw, adapter->fdir_pballoc);
} else if (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE) {
ixgbe_init_fdir_perfect_82599(hw, adapter->fdir_pballoc);
}
+ ixgbe_configure_virtualization(adapter);
ixgbe_configure_tx(adapter);
ixgbe_configure_rx(adapter);
- for (i = 0; i < adapter->num_rx_queues; i++)
- ixgbe_alloc_rx_buffers(adapter, adapter->rx_ring[i],
- (adapter->rx_ring[i]->count - 1));
}
static inline bool ixgbe_is_sfp(struct ixgbe_hw *hw)
@@ -3290,7 +3479,8 @@ static int ixgbe_non_sfp_link_config(struct ixgbe_hw *hw)
goto link_cfg_out;
if (hw->mac.ops.get_link_capabilities)
- ret = hw->mac.ops.get_link_capabilities(hw, &autoneg, &negotiation);
+ ret = hw->mac.ops.get_link_capabilities(hw, &autoneg,
+ &negotiation);
if (ret)
goto link_cfg_out;
@@ -3300,62 +3490,15 @@ link_cfg_out:
return ret;
}
-#define IXGBE_MAX_RX_DESC_POLL 10
-static inline void ixgbe_rx_desc_queue_enable(struct ixgbe_adapter *adapter,
- int rxr)
+static void ixgbe_setup_gpie(struct ixgbe_adapter *adapter)
{
- int j = adapter->rx_ring[rxr]->reg_idx;
- int k;
-
- for (k = 0; k < IXGBE_MAX_RX_DESC_POLL; k++) {
- if (IXGBE_READ_REG(&adapter->hw,
- IXGBE_RXDCTL(j)) & IXGBE_RXDCTL_ENABLE)
- break;
- else
- msleep(1);
- }
- if (k >= IXGBE_MAX_RX_DESC_POLL) {
- e_err(drv, "RXDCTL.ENABLE on Rx queue %d not set within "
- "the polling period\n", rxr);
- }
- ixgbe_release_rx_desc(&adapter->hw, adapter->rx_ring[rxr],
- (adapter->rx_ring[rxr]->count - 1));
-}
-
-static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
-{
- struct net_device *netdev = adapter->netdev;
struct ixgbe_hw *hw = &adapter->hw;
- int i, j = 0;
- int num_rx_rings = adapter->num_rx_queues;
- int err;
- int max_frame = netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
- u32 txdctl, rxdctl, mhadd;
- u32 dmatxctl;
- u32 gpie;
- u32 ctrl_ext;
-
- ixgbe_get_hw_control(adapter);
-
- if ((adapter->flags & IXGBE_FLAG_MSIX_ENABLED) ||
- (adapter->flags & IXGBE_FLAG_MSI_ENABLED)) {
- if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
- gpie = (IXGBE_GPIE_MSIX_MODE | IXGBE_GPIE_EIAME |
- IXGBE_GPIE_PBA_SUPPORT | IXGBE_GPIE_OCD);
- } else {
- /* MSI only */
- gpie = 0;
- }
- if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) {
- gpie &= ~IXGBE_GPIE_VTMODE_MASK;
- gpie |= IXGBE_GPIE_VTMODE_64;
- }
- /* XXX: to interrupt immediately for EICS writes, enable this */
- /* gpie |= IXGBE_GPIE_EIMEN; */
- IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie);
- }
+ u32 gpie = 0;
if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
+ gpie = IXGBE_GPIE_MSIX_MODE | IXGBE_GPIE_PBA_SUPPORT |
+ IXGBE_GPIE_OCD;
+ gpie |= IXGBE_GPIE_EIAME;
/*
* use EIAM to auto-mask when MSI-X interrupt is asserted
* this saves a register write for every interrupt
@@ -3376,98 +3519,33 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
IXGBE_WRITE_REG(hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE);
}
- /* Enable Thermal over heat sensor interrupt */
- if (adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE) {
- gpie = IXGBE_READ_REG(hw, IXGBE_GPIE);
- gpie |= IXGBE_SDP0_GPIEN;
- IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie);
+ /* XXX: to interrupt immediately for EICS writes, enable this */
+ /* gpie |= IXGBE_GPIE_EIMEN; */
+
+ if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) {
+ gpie &= ~IXGBE_GPIE_VTMODE_MASK;
+ gpie |= IXGBE_GPIE_VTMODE_64;
}
- /* Enable fan failure interrupt if media type is copper */
- if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE) {
- gpie = IXGBE_READ_REG(hw, IXGBE_GPIE);
+ /* Enable fan failure interrupt */
+ if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE)
gpie |= IXGBE_SDP1_GPIEN;
- IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie);
- }
- if (hw->mac.type == ixgbe_mac_82599EB) {
- gpie = IXGBE_READ_REG(hw, IXGBE_GPIE);
+ if (hw->mac.type == ixgbe_mac_82599EB)
gpie |= IXGBE_SDP1_GPIEN;
gpie |= IXGBE_SDP2_GPIEN;
- IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie);
- }
-#ifdef IXGBE_FCOE
- /* adjust max frame to be able to do baby jumbo for FCoE */
- if ((netdev->features & NETIF_F_FCOE_MTU) &&
- (max_frame < IXGBE_FCOE_JUMBO_FRAME_SIZE))
- max_frame = IXGBE_FCOE_JUMBO_FRAME_SIZE;
-
-#endif /* IXGBE_FCOE */
- mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD);
- if (max_frame != (mhadd >> IXGBE_MHADD_MFS_SHIFT)) {
- mhadd &= ~IXGBE_MHADD_MFS_MASK;
- mhadd |= max_frame << IXGBE_MHADD_MFS_SHIFT;
-
- IXGBE_WRITE_REG(hw, IXGBE_MHADD, mhadd);
- }
-
- for (i = 0; i < adapter->num_tx_queues; i++) {
- j = adapter->tx_ring[i]->reg_idx;
- txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(j));
- if (adapter->rx_itr_setting == 0) {
- /* cannot set wthresh when itr==0 */
- txdctl &= ~0x007F0000;
- } else {
- /* enable WTHRESH=8 descriptors, to encourage burst writeback */
- txdctl |= (8 << 16);
- }
- IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(j), txdctl);
- }
+ IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie);
+}
- if (hw->mac.type == ixgbe_mac_82599EB) {
- /* DMATXCTL.EN must be set after all Tx queue config is done */
- dmatxctl = IXGBE_READ_REG(hw, IXGBE_DMATXCTL);
- dmatxctl |= IXGBE_DMATXCTL_TE;
- IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, dmatxctl);
- }
- for (i = 0; i < adapter->num_tx_queues; i++) {
- j = adapter->tx_ring[i]->reg_idx;
- txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(j));
- txdctl |= IXGBE_TXDCTL_ENABLE;
- IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(j), txdctl);
- if (hw->mac.type == ixgbe_mac_82599EB) {
- int wait_loop = 10;
- /* poll for Tx Enable ready */
- do {
- msleep(1);
- txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(j));
- } while (--wait_loop &&
- !(txdctl & IXGBE_TXDCTL_ENABLE));
- if (!wait_loop)
- e_err(drv, "Could not enable Tx Queue %d\n", j);
- }
- }
+static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ int err;
+ u32 ctrl_ext;
- for (i = 0; i < num_rx_rings; i++) {
- j = adapter->rx_ring[i]->reg_idx;
- rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(j));
- /* enable PTHRESH=32 descriptors (half the internal cache)
- * and HTHRESH=0 descriptors (to minimize latency on fetch),
- * this also removes a pesky rx_no_buffer_count increment */
- rxdctl |= 0x0020;
- rxdctl |= IXGBE_RXDCTL_ENABLE;
- IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(j), rxdctl);
- if (hw->mac.type == ixgbe_mac_82599EB)
- ixgbe_rx_desc_queue_enable(adapter, i);
- }
- /* enable all receives */
- rxdctl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
- if (hw->mac.type == ixgbe_mac_82598EB)
- rxdctl |= (IXGBE_RXCTRL_DMBYPS | IXGBE_RXCTRL_RXEN);
- else
- rxdctl |= IXGBE_RXCTRL_RXEN;
- hw->mac.ops.enable_rx_dma(hw, rxdctl);
+ ixgbe_get_hw_control(adapter);
+ ixgbe_setup_gpie(adapter);
if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED)
ixgbe_configure_msix(adapter);
@@ -3483,8 +3561,7 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
/* clear any pending interrupts, may auto mask */
IXGBE_READ_REG(hw, IXGBE_EICR);
-
- ixgbe_irq_enable(adapter);
+ ixgbe_irq_enable(adapter, true, true);
/*
* If this adapter has a fan, check to see if we had a failure
@@ -3525,12 +3602,8 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
e_err(probe, "link_config FAILED %d\n", err);
}
- for (i = 0; i < adapter->num_tx_queues; i++)
- set_bit(__IXGBE_FDIR_INIT_DONE,
- &(adapter->tx_ring[i]->reinit_state));
-
/* enable transmits */
- netif_tx_start_all_queues(netdev);
+ netif_tx_start_all_queues(adapter->netdev);
/* bring the link up in the watchdog, this could race with our first
* link up interrupt but shouldn't be a problem */
@@ -3609,21 +3682,24 @@ void ixgbe_reset(struct ixgbe_adapter *adapter)
* @rx_ring: ring to free buffers from
**/
static void ixgbe_clean_rx_ring(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *rx_ring)
+ struct ixgbe_ring *rx_ring)
{
struct pci_dev *pdev = adapter->pdev;
unsigned long size;
unsigned int i;
- /* Free all the Rx ring sk_buffs */
+ /* ring already cleared, nothing to do */
+ if (!rx_ring->rx_buffer_info)
+ return;
+ /* Free all the Rx ring sk_buffs */
for (i = 0; i < rx_ring->count; i++) {
struct ixgbe_rx_buffer *rx_buffer_info;
rx_buffer_info = &rx_ring->rx_buffer_info[i];
if (rx_buffer_info->dma) {
dma_unmap_single(&pdev->dev, rx_buffer_info->dma,
- rx_ring->rx_buf_len,
+ rx_ring->rx_buf_len,
DMA_FROM_DEVICE);
rx_buffer_info->dma = 0;
}
@@ -3635,7 +3711,7 @@ static void ixgbe_clean_rx_ring(struct ixgbe_adapter *adapter,
if (IXGBE_RSC_CB(this)->delay_unmap) {
dma_unmap_single(&pdev->dev,
IXGBE_RSC_CB(this)->dma,
- rx_ring->rx_buf_len,
+ rx_ring->rx_buf_len,
DMA_FROM_DEVICE);
IXGBE_RSC_CB(this)->dma = 0;
IXGBE_RSC_CB(skb)->delay_unmap = false;
@@ -3677,14 +3753,17 @@ static void ixgbe_clean_rx_ring(struct ixgbe_adapter *adapter,
* @tx_ring: ring to be cleaned
**/
static void ixgbe_clean_tx_ring(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *tx_ring)
+ struct ixgbe_ring *tx_ring)
{
struct ixgbe_tx_buffer *tx_buffer_info;
unsigned long size;
unsigned int i;
- /* Free all the Tx ring sk_buffs */
+ /* ring already cleared, nothing to do */
+ if (!tx_ring->tx_buffer_info)
+ return;
+ /* Free all the Tx ring sk_buffs */
for (i = 0; i < tx_ring->count; i++) {
tx_buffer_info = &tx_ring->tx_buffer_info[i];
ixgbe_unmap_and_free_tx_resource(adapter, tx_buffer_info);
@@ -3736,6 +3815,7 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
u32 rxctrl;
u32 txdctl;
int i, j;
+ int num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
/* signal that we are down to the interrupt handler */
set_bit(__IXGBE_DOWN, &adapter->state);
@@ -3774,6 +3854,15 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
ixgbe_napi_disable_all(adapter);
+ /* Cleanup the affinity_hint CPU mask memory and callback */
+ for (i = 0; i < num_q_vectors; i++) {
+ struct ixgbe_q_vector *q_vector = adapter->q_vector[i];
+ /* clear the affinity_mask in the IRQ descriptor */
+ irq_set_affinity_hint(adapter->msix_entries[i]. vector, NULL);
+ /* release the CPU mask memory */
+ free_cpumask_var(q_vector->affinity_mask);
+ }
+
if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE ||
adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)
cancel_work_sync(&adapter->fdir_reinit_task);
@@ -3786,13 +3875,13 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
j = adapter->tx_ring[i]->reg_idx;
txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(j));
IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(j),
- (txdctl & ~IXGBE_TXDCTL_ENABLE));
+ (txdctl & ~IXGBE_TXDCTL_ENABLE));
}
/* Disable the Tx DMA engine on 82599 */
if (hw->mac.type == ixgbe_mac_82599EB)
IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL,
- (IXGBE_READ_REG(hw, IXGBE_DMATXCTL) &
- ~IXGBE_DMATXCTL_TE));
+ (IXGBE_READ_REG(hw, IXGBE_DMATXCTL) &
+ ~IXGBE_DMATXCTL_TE));
/* power down the optics */
if (hw->phy.multispeed_fiber)
@@ -3822,7 +3911,7 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
static int ixgbe_poll(struct napi_struct *napi, int budget)
{
struct ixgbe_q_vector *q_vector =
- container_of(napi, struct ixgbe_q_vector, napi);
+ container_of(napi, struct ixgbe_q_vector, napi);
struct ixgbe_adapter *adapter = q_vector->adapter;
int tx_clean_complete, work_done = 0;
@@ -3932,7 +4021,7 @@ static inline bool ixgbe_set_rss_queues(struct ixgbe_adapter *adapter)
* Rx load across CPUs using RSS.
*
**/
-static bool inline ixgbe_set_fdir_queues(struct ixgbe_adapter *adapter)
+static inline bool ixgbe_set_fdir_queues(struct ixgbe_adapter *adapter)
{
bool ret = false;
struct ixgbe_ring_feature *f_fdir = &adapter->ring_feature[RING_F_FDIR];
@@ -4024,7 +4113,7 @@ static inline bool ixgbe_set_sriov_queues(struct ixgbe_adapter *adapter)
* fallthrough conditions.
*
**/
-static void ixgbe_set_num_queues(struct ixgbe_adapter *adapter)
+static int ixgbe_set_num_queues(struct ixgbe_adapter *adapter)
{
/* Start with base case */
adapter->num_rx_queues = 1;
@@ -4033,7 +4122,7 @@ static void ixgbe_set_num_queues(struct ixgbe_adapter *adapter)
adapter->num_rx_queues_per_pool = 1;
if (ixgbe_set_sriov_queues(adapter))
- return;
+ goto done;
#ifdef IXGBE_FCOE
if (ixgbe_set_fcoe_queues(adapter))
@@ -4056,12 +4145,14 @@ static void ixgbe_set_num_queues(struct ixgbe_adapter *adapter)
adapter->num_tx_queues = 1;
done:
- /* Notify the stack of the (possibly) reduced Tx Queue count. */
+ /* Notify the stack of the (possibly) reduced queue counts. */
netif_set_real_num_tx_queues(adapter->netdev, adapter->num_tx_queues);
+ return netif_set_real_num_rx_queues(adapter->netdev,
+ adapter->num_rx_queues);
}
static void ixgbe_acquire_msix_vectors(struct ixgbe_adapter *adapter,
- int vectors)
+ int vectors)
{
int err, vector_threshold;
@@ -4080,7 +4171,7 @@ static void ixgbe_acquire_msix_vectors(struct ixgbe_adapter *adapter,
*/
while (vectors >= vector_threshold) {
err = pci_enable_msix(adapter->pdev, adapter->msix_entries,
- vectors);
+ vectors);
if (!err) /* Success in acquiring all requested vectors. */
break;
else if (err < 0)
@@ -4107,7 +4198,7 @@ static void ixgbe_acquire_msix_vectors(struct ixgbe_adapter *adapter,
* vectors we were allocated.
*/
adapter->num_msix_vectors = min(vectors,
- adapter->max_msix_q_vectors + NON_Q_VECTORS);
+ adapter->max_msix_q_vectors + NON_Q_VECTORS);
}
}
@@ -4178,12 +4269,12 @@ static inline bool ixgbe_cache_ring_dcb(struct ixgbe_adapter *adapter)
}
for ( ; i < 5; i++) {
adapter->tx_ring[i]->reg_idx =
- ((i + 2) << 4);
+ ((i + 2) << 4);
adapter->rx_ring[i]->reg_idx = i << 4;
}
for ( ; i < dcb_i; i++) {
adapter->tx_ring[i]->reg_idx =
- ((i + 8) << 3);
+ ((i + 8) << 3);
adapter->rx_ring[i]->reg_idx = i << 4;
}
@@ -4226,7 +4317,7 @@ static inline bool ixgbe_cache_ring_dcb(struct ixgbe_adapter *adapter)
* Cache the descriptor ring offsets for Flow Director to the assigned rings.
*
**/
-static bool inline ixgbe_cache_ring_fdir(struct ixgbe_adapter *adapter)
+static inline bool ixgbe_cache_ring_fdir(struct ixgbe_adapter *adapter)
{
int i;
bool ret = false;
@@ -4383,7 +4474,7 @@ static int ixgbe_alloc_queues(struct ixgbe_adapter *adapter)
adapter->node = cur_node;
}
ring = kzalloc_node(sizeof(struct ixgbe_ring), GFP_KERNEL,
- adapter->node);
+ adapter->node);
if (!ring)
ring = kzalloc(sizeof(struct ixgbe_ring), GFP_KERNEL);
if (!ring)
@@ -4407,7 +4498,7 @@ static int ixgbe_alloc_queues(struct ixgbe_adapter *adapter)
adapter->node = cur_node;
}
ring = kzalloc_node(sizeof(struct ixgbe_ring), GFP_KERNEL,
- adapter->node);
+ adapter->node);
if (!ring)
ring = kzalloc(sizeof(struct ixgbe_ring), GFP_KERNEL);
if (!ring)
@@ -4453,7 +4544,7 @@ static int ixgbe_set_interrupt_capability(struct ixgbe_adapter *adapter)
* (roughly) the same number of vectors as there are CPU's.
*/
v_budget = min(adapter->num_rx_queues + adapter->num_tx_queues,
- (int)num_online_cpus()) + NON_Q_VECTORS;
+ (int)num_online_cpus()) + NON_Q_VECTORS;
/*
* At the same time, hardware can only support a maximum of
@@ -4467,7 +4558,7 @@ static int ixgbe_set_interrupt_capability(struct ixgbe_adapter *adapter)
/* A failure in MSI-X entry allocation isn't fatal, but it does
* mean we disable MSI-X capabilities of the adapter. */
adapter->msix_entries = kcalloc(v_budget,
- sizeof(struct msix_entry), GFP_KERNEL);
+ sizeof(struct msix_entry), GFP_KERNEL);
if (adapter->msix_entries) {
for (vector = 0; vector < v_budget; vector++)
adapter->msix_entries[vector].entry = vector;
@@ -4486,7 +4577,9 @@ static int ixgbe_set_interrupt_capability(struct ixgbe_adapter *adapter)
if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)
ixgbe_disable_sriov(adapter);
- ixgbe_set_num_queues(adapter);
+ err = ixgbe_set_num_queues(adapter);
+ if (err)
+ return err;
err = pci_enable_msi(adapter->pdev);
if (!err) {
@@ -4529,10 +4622,10 @@ static int ixgbe_alloc_q_vectors(struct ixgbe_adapter *adapter)
for (q_idx = 0; q_idx < num_q_vectors; q_idx++) {
q_vector = kzalloc_node(sizeof(struct ixgbe_q_vector),
- GFP_KERNEL, adapter->node);
+ GFP_KERNEL, adapter->node);
if (!q_vector)
q_vector = kzalloc(sizeof(struct ixgbe_q_vector),
- GFP_KERNEL);
+ GFP_KERNEL);
if (!q_vector)
goto err_out;
q_vector->adapter = adapter;
@@ -4611,7 +4704,9 @@ int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter)
int err;
/* Number of supported queues */
- ixgbe_set_num_queues(adapter);
+ err = ixgbe_set_num_queues(adapter);
+ if (err)
+ return err;
err = ixgbe_set_interrupt_capability(adapter);
if (err) {
@@ -4693,8 +4788,8 @@ static void ixgbe_sfp_timer(unsigned long data)
static void ixgbe_sfp_task(struct work_struct *work)
{
struct ixgbe_adapter *adapter = container_of(work,
- struct ixgbe_adapter,
- sfp_task);
+ struct ixgbe_adapter,
+ sfp_task);
struct ixgbe_hw *hw = &adapter->hw;
if ((hw->phy.type == ixgbe_phy_nl) &&
@@ -4719,7 +4814,7 @@ static void ixgbe_sfp_task(struct work_struct *work)
reschedule:
if (test_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state))
mod_timer(&adapter->sfp_timer,
- round_jiffies(jiffies + (2 * HZ)));
+ round_jiffies(jiffies + (2 * HZ)));
}
/**
@@ -4775,7 +4870,7 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
adapter->atr_sample_rate = 20;
}
adapter->ring_feature[RING_F_FDIR].indices =
- IXGBE_MAX_FDIR_INDICES;
+ IXGBE_MAX_FDIR_INDICES;
adapter->fdir_pballoc = 0;
#ifdef IXGBE_FCOE
adapter->flags |= IXGBE_FLAG_FCOE_CAPABLE;
@@ -4806,7 +4901,7 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
adapter->dcb_cfg.round_robin_enable = false;
adapter->dcb_set_bitmap = 0x00;
ixgbe_copy_dcb_cfg(&adapter->dcb_cfg, &adapter->temp_dcb_cfg,
- adapter->ring_feature[RING_F_DCB].indices);
+ adapter->ring_feature[RING_F_DCB].indices);
#endif
@@ -4861,7 +4956,7 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
* Return 0 on success, negative on failure
**/
int ixgbe_setup_tx_resources(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *tx_ring)
+ struct ixgbe_ring *tx_ring)
{
struct pci_dev *pdev = adapter->pdev;
int size;
@@ -4928,7 +5023,7 @@ static int ixgbe_setup_all_tx_resources(struct ixgbe_adapter *adapter)
* Returns 0 on success, negative on failure
**/
int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *rx_ring)
+ struct ixgbe_ring *rx_ring)
{
struct pci_dev *pdev = adapter->pdev;
int size;
@@ -5001,7 +5096,7 @@ static int ixgbe_setup_all_rx_resources(struct ixgbe_adapter *adapter)
* Free all transmit software resources
**/
void ixgbe_free_tx_resources(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *tx_ring)
+ struct ixgbe_ring *tx_ring)
{
struct pci_dev *pdev = adapter->pdev;
@@ -5039,7 +5134,7 @@ static void ixgbe_free_all_tx_resources(struct ixgbe_adapter *adapter)
* Free all receive software resources
**/
void ixgbe_free_rx_resources(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *rx_ring)
+ struct ixgbe_ring *rx_ring)
{
struct pci_dev *pdev = adapter->pdev;
@@ -5333,6 +5428,7 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter)
u64 total_mpc = 0;
u32 i, missed_rx = 0, mpc, bprc, lxon, lxoff, xon_off_tot;
u64 non_eop_descs = 0, restart_queue = 0;
+ struct ixgbe_hw_stats *hwstats = &adapter->stats;
if (test_bit(__IXGBE_DOWN, &adapter->state) ||
test_bit(__IXGBE_RESETTING, &adapter->state))
@@ -5343,7 +5439,7 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter)
u64 rsc_flush = 0;
for (i = 0; i < 16; i++)
adapter->hw_rx_no_dma_resources +=
- IXGBE_READ_REG(hw, IXGBE_QPRDC(i));
+ IXGBE_READ_REG(hw, IXGBE_QPRDC(i));
for (i = 0; i < adapter->num_rx_queues; i++) {
rsc_count += adapter->rx_ring[i]->rsc_count;
rsc_flush += adapter->rx_ring[i]->rsc_flush;
@@ -5361,119 +5457,118 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter)
non_eop_descs += adapter->rx_ring[i]->non_eop_descs;
adapter->non_eop_descs = non_eop_descs;
- adapter->stats.crcerrs += IXGBE_READ_REG(hw, IXGBE_CRCERRS);
+ hwstats->crcerrs += IXGBE_READ_REG(hw, IXGBE_CRCERRS);
for (i = 0; i < 8; i++) {
/* for packet buffers not used, the register should read 0 */
mpc = IXGBE_READ_REG(hw, IXGBE_MPC(i));
missed_rx += mpc;
- adapter->stats.mpc[i] += mpc;
- total_mpc += adapter->stats.mpc[i];
+ hwstats->mpc[i] += mpc;
+ total_mpc += hwstats->mpc[i];
if (hw->mac.type == ixgbe_mac_82598EB)
- adapter->stats.rnbc[i] += IXGBE_READ_REG(hw, IXGBE_RNBC(i));
- adapter->stats.qptc[i] += IXGBE_READ_REG(hw, IXGBE_QPTC(i));
- adapter->stats.qbtc[i] += IXGBE_READ_REG(hw, IXGBE_QBTC(i));
- adapter->stats.qprc[i] += IXGBE_READ_REG(hw, IXGBE_QPRC(i));
- adapter->stats.qbrc[i] += IXGBE_READ_REG(hw, IXGBE_QBRC(i));
+ hwstats->rnbc[i] += IXGBE_READ_REG(hw, IXGBE_RNBC(i));
+ hwstats->qptc[i] += IXGBE_READ_REG(hw, IXGBE_QPTC(i));
+ hwstats->qbtc[i] += IXGBE_READ_REG(hw, IXGBE_QBTC(i));
+ hwstats->qprc[i] += IXGBE_READ_REG(hw, IXGBE_QPRC(i));
+ hwstats->qbrc[i] += IXGBE_READ_REG(hw, IXGBE_QBRC(i));
if (hw->mac.type == ixgbe_mac_82599EB) {
- adapter->stats.pxonrxc[i] += IXGBE_READ_REG(hw,
- IXGBE_PXONRXCNT(i));
- adapter->stats.pxoffrxc[i] += IXGBE_READ_REG(hw,
- IXGBE_PXOFFRXCNT(i));
- adapter->stats.qprdc[i] += IXGBE_READ_REG(hw, IXGBE_QPRDC(i));
+ hwstats->pxonrxc[i] +=
+ IXGBE_READ_REG(hw, IXGBE_PXONRXCNT(i));
+ hwstats->pxoffrxc[i] +=
+ IXGBE_READ_REG(hw, IXGBE_PXOFFRXCNT(i));
+ hwstats->qprdc[i] += IXGBE_READ_REG(hw, IXGBE_QPRDC(i));
} else {
- adapter->stats.pxonrxc[i] += IXGBE_READ_REG(hw,
- IXGBE_PXONRXC(i));
- adapter->stats.pxoffrxc[i] += IXGBE_READ_REG(hw,
- IXGBE_PXOFFRXC(i));
+ hwstats->pxonrxc[i] +=
+ IXGBE_READ_REG(hw, IXGBE_PXONRXC(i));
+ hwstats->pxoffrxc[i] +=
+ IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(i));
}
- adapter->stats.pxontxc[i] += IXGBE_READ_REG(hw,
- IXGBE_PXONTXC(i));
- adapter->stats.pxofftxc[i] += IXGBE_READ_REG(hw,
- IXGBE_PXOFFTXC(i));
+ hwstats->pxontxc[i] += IXGBE_READ_REG(hw, IXGBE_PXONTXC(i));
+ hwstats->pxofftxc[i] += IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(i));
}
- adapter->stats.gprc += IXGBE_READ_REG(hw, IXGBE_GPRC);
+ hwstats->gprc += IXGBE_READ_REG(hw, IXGBE_GPRC);
/* work around hardware counting issue */
- adapter->stats.gprc -= missed_rx;
+ hwstats->gprc -= missed_rx;
/* 82598 hardware only has a 32 bit counter in the high register */
if (hw->mac.type == ixgbe_mac_82599EB) {
u64 tmp;
- adapter->stats.gorc += IXGBE_READ_REG(hw, IXGBE_GORCL);
- tmp = IXGBE_READ_REG(hw, IXGBE_GORCH) & 0xF; /* 4 high bits of GORC */
- adapter->stats.gorc += (tmp << 32);
- adapter->stats.gotc += IXGBE_READ_REG(hw, IXGBE_GOTCL);
- tmp = IXGBE_READ_REG(hw, IXGBE_GOTCH) & 0xF; /* 4 high bits of GOTC */
- adapter->stats.gotc += (tmp << 32);
- adapter->stats.tor += IXGBE_READ_REG(hw, IXGBE_TORL);
- IXGBE_READ_REG(hw, IXGBE_TORH); /* to clear */
- adapter->stats.lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXCNT);
- adapter->stats.lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT);
- adapter->stats.fdirmatch += IXGBE_READ_REG(hw, IXGBE_FDIRMATCH);
- adapter->stats.fdirmiss += IXGBE_READ_REG(hw, IXGBE_FDIRMISS);
+ hwstats->gorc += IXGBE_READ_REG(hw, IXGBE_GORCL);
+ tmp = IXGBE_READ_REG(hw, IXGBE_GORCH) & 0xF;
+ /* 4 high bits of GORC */
+ hwstats->gorc += (tmp << 32);
+ hwstats->gotc += IXGBE_READ_REG(hw, IXGBE_GOTCL);
+ tmp = IXGBE_READ_REG(hw, IXGBE_GOTCH) & 0xF;
+ /* 4 high bits of GOTC */
+ hwstats->gotc += (tmp << 32);
+ hwstats->tor += IXGBE_READ_REG(hw, IXGBE_TORL);
+ IXGBE_READ_REG(hw, IXGBE_TORH); /* to clear */
+ hwstats->lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXCNT);
+ hwstats->lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT);
+ hwstats->fdirmatch += IXGBE_READ_REG(hw, IXGBE_FDIRMATCH);
+ hwstats->fdirmiss += IXGBE_READ_REG(hw, IXGBE_FDIRMISS);
#ifdef IXGBE_FCOE
- adapter->stats.fccrc += IXGBE_READ_REG(hw, IXGBE_FCCRC);
- adapter->stats.fcoerpdc += IXGBE_READ_REG(hw, IXGBE_FCOERPDC);
- adapter->stats.fcoeprc += IXGBE_READ_REG(hw, IXGBE_FCOEPRC);
- adapter->stats.fcoeptc += IXGBE_READ_REG(hw, IXGBE_FCOEPTC);
- adapter->stats.fcoedwrc += IXGBE_READ_REG(hw, IXGBE_FCOEDWRC);
- adapter->stats.fcoedwtc += IXGBE_READ_REG(hw, IXGBE_FCOEDWTC);
+ hwstats->fccrc += IXGBE_READ_REG(hw, IXGBE_FCCRC);
+ hwstats->fcoerpdc += IXGBE_READ_REG(hw, IXGBE_FCOERPDC);
+ hwstats->fcoeprc += IXGBE_READ_REG(hw, IXGBE_FCOEPRC);
+ hwstats->fcoeptc += IXGBE_READ_REG(hw, IXGBE_FCOEPTC);
+ hwstats->fcoedwrc += IXGBE_READ_REG(hw, IXGBE_FCOEDWRC);
+ hwstats->fcoedwtc += IXGBE_READ_REG(hw, IXGBE_FCOEDWTC);
#endif /* IXGBE_FCOE */
} else {
- adapter->stats.lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXC);
- adapter->stats.lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXC);
- adapter->stats.gorc += IXGBE_READ_REG(hw, IXGBE_GORCH);
- adapter->stats.gotc += IXGBE_READ_REG(hw, IXGBE_GOTCH);
- adapter->stats.tor += IXGBE_READ_REG(hw, IXGBE_TORH);
+ hwstats->lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXC);
+ hwstats->lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXC);
+ hwstats->gorc += IXGBE_READ_REG(hw, IXGBE_GORCH);
+ hwstats->gotc += IXGBE_READ_REG(hw, IXGBE_GOTCH);
+ hwstats->tor += IXGBE_READ_REG(hw, IXGBE_TORH);
}
bprc = IXGBE_READ_REG(hw, IXGBE_BPRC);
- adapter->stats.bprc += bprc;
- adapter->stats.mprc += IXGBE_READ_REG(hw, IXGBE_MPRC);
+ hwstats->bprc += bprc;
+ hwstats->mprc += IXGBE_READ_REG(hw, IXGBE_MPRC);
if (hw->mac.type == ixgbe_mac_82598EB)
- adapter->stats.mprc -= bprc;
- adapter->stats.roc += IXGBE_READ_REG(hw, IXGBE_ROC);
- adapter->stats.prc64 += IXGBE_READ_REG(hw, IXGBE_PRC64);
- adapter->stats.prc127 += IXGBE_READ_REG(hw, IXGBE_PRC127);
- adapter->stats.prc255 += IXGBE_READ_REG(hw, IXGBE_PRC255);
- adapter->stats.prc511 += IXGBE_READ_REG(hw, IXGBE_PRC511);
- adapter->stats.prc1023 += IXGBE_READ_REG(hw, IXGBE_PRC1023);
- adapter->stats.prc1522 += IXGBE_READ_REG(hw, IXGBE_PRC1522);
- adapter->stats.rlec += IXGBE_READ_REG(hw, IXGBE_RLEC);
+ hwstats->mprc -= bprc;
+ hwstats->roc += IXGBE_READ_REG(hw, IXGBE_ROC);
+ hwstats->prc64 += IXGBE_READ_REG(hw, IXGBE_PRC64);
+ hwstats->prc127 += IXGBE_READ_REG(hw, IXGBE_PRC127);
+ hwstats->prc255 += IXGBE_READ_REG(hw, IXGBE_PRC255);
+ hwstats->prc511 += IXGBE_READ_REG(hw, IXGBE_PRC511);
+ hwstats->prc1023 += IXGBE_READ_REG(hw, IXGBE_PRC1023);
+ hwstats->prc1522 += IXGBE_READ_REG(hw, IXGBE_PRC1522);
+ hwstats->rlec += IXGBE_READ_REG(hw, IXGBE_RLEC);
lxon = IXGBE_READ_REG(hw, IXGBE_LXONTXC);
- adapter->stats.lxontxc += lxon;
+ hwstats->lxontxc += lxon;
lxoff = IXGBE_READ_REG(hw, IXGBE_LXOFFTXC);
- adapter->stats.lxofftxc += lxoff;
- adapter->stats.ruc += IXGBE_READ_REG(hw, IXGBE_RUC);
- adapter->stats.gptc += IXGBE_READ_REG(hw, IXGBE_GPTC);
- adapter->stats.mptc += IXGBE_READ_REG(hw, IXGBE_MPTC);
+ hwstats->lxofftxc += lxoff;
+ hwstats->ruc += IXGBE_READ_REG(hw, IXGBE_RUC);
+ hwstats->gptc += IXGBE_READ_REG(hw, IXGBE_GPTC);
+ hwstats->mptc += IXGBE_READ_REG(hw, IXGBE_MPTC);
/*
* 82598 errata - tx of flow control packets is included in tx counters
*/
xon_off_tot = lxon + lxoff;
- adapter->stats.gptc -= xon_off_tot;
- adapter->stats.mptc -= xon_off_tot;
- adapter->stats.gotc -= (xon_off_tot * (ETH_ZLEN + ETH_FCS_LEN));
- adapter->stats.ruc += IXGBE_READ_REG(hw, IXGBE_RUC);
- adapter->stats.rfc += IXGBE_READ_REG(hw, IXGBE_RFC);
- adapter->stats.rjc += IXGBE_READ_REG(hw, IXGBE_RJC);
- adapter->stats.tpr += IXGBE_READ_REG(hw, IXGBE_TPR);
- adapter->stats.ptc64 += IXGBE_READ_REG(hw, IXGBE_PTC64);
- adapter->stats.ptc64 -= xon_off_tot;
- adapter->stats.ptc127 += IXGBE_READ_REG(hw, IXGBE_PTC127);
- adapter->stats.ptc255 += IXGBE_READ_REG(hw, IXGBE_PTC255);
- adapter->stats.ptc511 += IXGBE_READ_REG(hw, IXGBE_PTC511);
- adapter->stats.ptc1023 += IXGBE_READ_REG(hw, IXGBE_PTC1023);
- adapter->stats.ptc1522 += IXGBE_READ_REG(hw, IXGBE_PTC1522);
- adapter->stats.bptc += IXGBE_READ_REG(hw, IXGBE_BPTC);
+ hwstats->gptc -= xon_off_tot;
+ hwstats->mptc -= xon_off_tot;
+ hwstats->gotc -= (xon_off_tot * (ETH_ZLEN + ETH_FCS_LEN));
+ hwstats->ruc += IXGBE_READ_REG(hw, IXGBE_RUC);
+ hwstats->rfc += IXGBE_READ_REG(hw, IXGBE_RFC);
+ hwstats->rjc += IXGBE_READ_REG(hw, IXGBE_RJC);
+ hwstats->tpr += IXGBE_READ_REG(hw, IXGBE_TPR);
+ hwstats->ptc64 += IXGBE_READ_REG(hw, IXGBE_PTC64);
+ hwstats->ptc64 -= xon_off_tot;
+ hwstats->ptc127 += IXGBE_READ_REG(hw, IXGBE_PTC127);
+ hwstats->ptc255 += IXGBE_READ_REG(hw, IXGBE_PTC255);
+ hwstats->ptc511 += IXGBE_READ_REG(hw, IXGBE_PTC511);
+ hwstats->ptc1023 += IXGBE_READ_REG(hw, IXGBE_PTC1023);
+ hwstats->ptc1522 += IXGBE_READ_REG(hw, IXGBE_PTC1522);
+ hwstats->bptc += IXGBE_READ_REG(hw, IXGBE_BPTC);
/* Fill out the OS statistics structure */
- netdev->stats.multicast = adapter->stats.mprc;
+ netdev->stats.multicast = hwstats->mprc;
/* Rx Errors */
- netdev->stats.rx_errors = adapter->stats.crcerrs +
- adapter->stats.rlec;
+ netdev->stats.rx_errors = hwstats->crcerrs + hwstats->rlec;
netdev->stats.rx_dropped = 0;
- netdev->stats.rx_length_errors = adapter->stats.rlec;
- netdev->stats.rx_crc_errors = adapter->stats.crcerrs;
+ netdev->stats.rx_length_errors = hwstats->rlec;
+ netdev->stats.rx_crc_errors = hwstats->crcerrs;
netdev->stats.rx_missed_errors = total_mpc;
}
@@ -5532,8 +5627,8 @@ watchdog_short_circuit:
static void ixgbe_multispeed_fiber_task(struct work_struct *work)
{
struct ixgbe_adapter *adapter = container_of(work,
- struct ixgbe_adapter,
- multispeed_fiber_task);
+ struct ixgbe_adapter,
+ multispeed_fiber_task);
struct ixgbe_hw *hw = &adapter->hw;
u32 autoneg;
bool negotiation;
@@ -5556,8 +5651,8 @@ static void ixgbe_multispeed_fiber_task(struct work_struct *work)
static void ixgbe_sfp_config_module_task(struct work_struct *work)
{
struct ixgbe_adapter *adapter = container_of(work,
- struct ixgbe_adapter,
- sfp_config_module_task);
+ struct ixgbe_adapter,
+ sfp_config_module_task);
struct ixgbe_hw *hw = &adapter->hw;
u32 err;
@@ -5590,15 +5685,15 @@ static void ixgbe_sfp_config_module_task(struct work_struct *work)
static void ixgbe_fdir_reinit_task(struct work_struct *work)
{
struct ixgbe_adapter *adapter = container_of(work,
- struct ixgbe_adapter,
- fdir_reinit_task);
+ struct ixgbe_adapter,
+ fdir_reinit_task);
struct ixgbe_hw *hw = &adapter->hw;
int i;
if (ixgbe_reinit_fdir_tables_82599(hw) == 0) {
for (i = 0; i < adapter->num_tx_queues; i++)
set_bit(__IXGBE_FDIR_INIT_DONE,
- &(adapter->tx_ring[i]->reinit_state));
+ &(adapter->tx_ring[i]->reinit_state));
} else {
e_err(probe, "failed to finish FDIR re-initialization, "
"ignored adding FDIR ATR filters\n");
@@ -5616,8 +5711,8 @@ static DEFINE_MUTEX(ixgbe_watchdog_lock);
static void ixgbe_watchdog_task(struct work_struct *work)
{
struct ixgbe_adapter *adapter = container_of(work,
- struct ixgbe_adapter,
- watchdog_task);
+ struct ixgbe_adapter,
+ watchdog_task);
struct net_device *netdev = adapter->netdev;
struct ixgbe_hw *hw = &adapter->hw;
u32 link_speed;
@@ -5648,7 +5743,7 @@ static void ixgbe_watchdog_task(struct work_struct *work)
if (link_up ||
time_after(jiffies, (adapter->link_check_timeout +
- IXGBE_TRY_LINK_TIMEOUT))) {
+ IXGBE_TRY_LINK_TIMEOUT))) {
adapter->flags &= ~IXGBE_FLAG_NEED_LINK_UPDATE;
IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMC_LSC);
}
@@ -5719,8 +5814,8 @@ static void ixgbe_watchdog_task(struct work_struct *work)
}
static int ixgbe_tso(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *tx_ring, struct sk_buff *skb,
- u32 tx_flags, u8 *hdr_len)
+ struct ixgbe_ring *tx_ring, struct sk_buff *skb,
+ u32 tx_flags, u8 *hdr_len)
{
struct ixgbe_adv_tx_context_desc *context_desc;
unsigned int i;
@@ -5743,28 +5838,28 @@ static int ixgbe_tso(struct ixgbe_adapter *adapter,
iph->tot_len = 0;
iph->check = 0;
tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr,
- iph->daddr, 0,
- IPPROTO_TCP,
- 0);
+ iph->daddr, 0,
+ IPPROTO_TCP,
+ 0);
} else if (skb_is_gso_v6(skb)) {
ipv6_hdr(skb)->payload_len = 0;
tcp_hdr(skb)->check =
~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
- &ipv6_hdr(skb)->daddr,
- 0, IPPROTO_TCP, 0);
+ &ipv6_hdr(skb)->daddr,
+ 0, IPPROTO_TCP, 0);
}
i = tx_ring->next_to_use;
tx_buffer_info = &tx_ring->tx_buffer_info[i];
- context_desc = IXGBE_TX_CTXTDESC_ADV(*tx_ring, i);
+ context_desc = IXGBE_TX_CTXTDESC_ADV(tx_ring, i);
/* VLAN MACLEN IPLEN */
if (tx_flags & IXGBE_TX_FLAGS_VLAN)
vlan_macip_lens |=
(tx_flags & IXGBE_TX_FLAGS_VLAN_MASK);
vlan_macip_lens |= ((skb_network_offset(skb)) <<
- IXGBE_ADVTXD_MACLEN_SHIFT);
+ IXGBE_ADVTXD_MACLEN_SHIFT);
*hdr_len += skb_network_offset(skb);
vlan_macip_lens |=
(skb_transport_header(skb) - skb_network_header(skb));
@@ -5775,7 +5870,7 @@ static int ixgbe_tso(struct ixgbe_adapter *adapter,
/* ADV DTYP TUCMD MKRLOC/ISCSIHEDLEN */
type_tucmd_mlhl = (IXGBE_TXD_CMD_DEXT |
- IXGBE_ADVTXD_DTYP_CTXT);
+ IXGBE_ADVTXD_DTYP_CTXT);
if (skb->protocol == htons(ETH_P_IP))
type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV4;
@@ -5803,9 +5898,53 @@ static int ixgbe_tso(struct ixgbe_adapter *adapter,
return false;
}
+static u32 ixgbe_psum(struct ixgbe_adapter *adapter, struct sk_buff *skb)
+{
+ u32 rtn = 0;
+ __be16 protocol;
+
+ if (skb->protocol == cpu_to_be16(ETH_P_8021Q))
+ protocol = ((const struct vlan_ethhdr *)skb->data)->
+ h_vlan_encapsulated_proto;
+ else
+ protocol = skb->protocol;
+
+ switch (protocol) {
+ case cpu_to_be16(ETH_P_IP):
+ rtn |= IXGBE_ADVTXD_TUCMD_IPV4;
+ switch (ip_hdr(skb)->protocol) {
+ case IPPROTO_TCP:
+ rtn |= IXGBE_ADVTXD_TUCMD_L4T_TCP;
+ break;
+ case IPPROTO_SCTP:
+ rtn |= IXGBE_ADVTXD_TUCMD_L4T_SCTP;
+ break;
+ }
+ break;
+ case cpu_to_be16(ETH_P_IPV6):
+ /* XXX what about other V6 headers?? */
+ switch (ipv6_hdr(skb)->nexthdr) {
+ case IPPROTO_TCP:
+ rtn |= IXGBE_ADVTXD_TUCMD_L4T_TCP;
+ break;
+ case IPPROTO_SCTP:
+ rtn |= IXGBE_ADVTXD_TUCMD_L4T_SCTP;
+ break;
+ }
+ break;
+ default:
+ if (unlikely(net_ratelimit()))
+ e_warn(probe, "partial checksum but proto=%x!\n",
+ skb->protocol);
+ break;
+ }
+
+ return rtn;
+}
+
static bool ixgbe_tx_csum(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *tx_ring,
- struct sk_buff *skb, u32 tx_flags)
+ struct ixgbe_ring *tx_ring,
+ struct sk_buff *skb, u32 tx_flags)
{
struct ixgbe_adv_tx_context_desc *context_desc;
unsigned int i;
@@ -5816,63 +5955,25 @@ static bool ixgbe_tx_csum(struct ixgbe_adapter *adapter,
(tx_flags & IXGBE_TX_FLAGS_VLAN)) {
i = tx_ring->next_to_use;
tx_buffer_info = &tx_ring->tx_buffer_info[i];
- context_desc = IXGBE_TX_CTXTDESC_ADV(*tx_ring, i);
+ context_desc = IXGBE_TX_CTXTDESC_ADV(tx_ring, i);
if (tx_flags & IXGBE_TX_FLAGS_VLAN)
vlan_macip_lens |=
(tx_flags & IXGBE_TX_FLAGS_VLAN_MASK);
vlan_macip_lens |= (skb_network_offset(skb) <<
- IXGBE_ADVTXD_MACLEN_SHIFT);
+ IXGBE_ADVTXD_MACLEN_SHIFT);
if (skb->ip_summed == CHECKSUM_PARTIAL)
vlan_macip_lens |= (skb_transport_header(skb) -
- skb_network_header(skb));
+ skb_network_header(skb));
context_desc->vlan_macip_lens = cpu_to_le32(vlan_macip_lens);
context_desc->seqnum_seed = 0;
type_tucmd_mlhl |= (IXGBE_TXD_CMD_DEXT |
- IXGBE_ADVTXD_DTYP_CTXT);
-
- if (skb->ip_summed == CHECKSUM_PARTIAL) {
- __be16 protocol;
-
- if (skb->protocol == cpu_to_be16(ETH_P_8021Q)) {
- const struct vlan_ethhdr *vhdr =
- (const struct vlan_ethhdr *)skb->data;
-
- protocol = vhdr->h_vlan_encapsulated_proto;
- } else {
- protocol = skb->protocol;
- }
+ IXGBE_ADVTXD_DTYP_CTXT);
- switch (protocol) {
- case cpu_to_be16(ETH_P_IP):
- type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV4;
- if (ip_hdr(skb)->protocol == IPPROTO_TCP)
- type_tucmd_mlhl |=
- IXGBE_ADVTXD_TUCMD_L4T_TCP;
- else if (ip_hdr(skb)->protocol == IPPROTO_SCTP)
- type_tucmd_mlhl |=
- IXGBE_ADVTXD_TUCMD_L4T_SCTP;
- break;
- case cpu_to_be16(ETH_P_IPV6):
- /* XXX what about other V6 headers?? */
- if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP)
- type_tucmd_mlhl |=
- IXGBE_ADVTXD_TUCMD_L4T_TCP;
- else if (ipv6_hdr(skb)->nexthdr == IPPROTO_SCTP)
- type_tucmd_mlhl |=
- IXGBE_ADVTXD_TUCMD_L4T_SCTP;
- break;
- default:
- if (unlikely(net_ratelimit())) {
- e_warn(probe, "partial checksum "
- "but proto=%x!\n",
- skb->protocol);
- }
- break;
- }
- }
+ if (skb->ip_summed == CHECKSUM_PARTIAL)
+ type_tucmd_mlhl |= ixgbe_psum(adapter, skb);
context_desc->type_tucmd_mlhl = cpu_to_le32(type_tucmd_mlhl);
/* use index zero for tx checksum offload */
@@ -5893,9 +5994,9 @@ static bool ixgbe_tx_csum(struct ixgbe_adapter *adapter,
}
static int ixgbe_tx_map(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *tx_ring,
- struct sk_buff *skb, u32 tx_flags,
- unsigned int first)
+ struct ixgbe_ring *tx_ring,
+ struct sk_buff *skb, u32 tx_flags,
+ unsigned int first)
{
struct pci_dev *pdev = adapter->pdev;
struct ixgbe_tx_buffer *tx_buffer_info;
@@ -5990,7 +6091,7 @@ dma_error:
/* clear timestamp and dma mappings for remaining portion of packet */
while (count--) {
- if (i==0)
+ if (i == 0)
i += tx_ring->count;
i--;
tx_buffer_info = &tx_ring->tx_buffer_info[i];
@@ -6001,8 +6102,8 @@ dma_error:
}
static void ixgbe_tx_queue(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *tx_ring,
- int tx_flags, int count, u32 paylen, u8 hdr_len)
+ struct ixgbe_ring *tx_ring,
+ int tx_flags, int count, u32 paylen, u8 hdr_len)
{
union ixgbe_adv_tx_desc *tx_desc = NULL;
struct ixgbe_tx_buffer *tx_buffer_info;
@@ -6021,17 +6122,17 @@ static void ixgbe_tx_queue(struct ixgbe_adapter *adapter,
cmd_type_len |= IXGBE_ADVTXD_DCMD_TSE;
olinfo_status |= IXGBE_TXD_POPTS_TXSM <<
- IXGBE_ADVTXD_POPTS_SHIFT;
+ IXGBE_ADVTXD_POPTS_SHIFT;
/* use index 1 context for tso */
olinfo_status |= (1 << IXGBE_ADVTXD_IDX_SHIFT);
if (tx_flags & IXGBE_TX_FLAGS_IPV4)
olinfo_status |= IXGBE_TXD_POPTS_IXSM <<
- IXGBE_ADVTXD_POPTS_SHIFT;
+ IXGBE_ADVTXD_POPTS_SHIFT;
} else if (tx_flags & IXGBE_TX_FLAGS_CSUM)
olinfo_status |= IXGBE_TXD_POPTS_TXSM <<
- IXGBE_ADVTXD_POPTS_SHIFT;
+ IXGBE_ADVTXD_POPTS_SHIFT;
if (tx_flags & IXGBE_TX_FLAGS_FCOE) {
olinfo_status |= IXGBE_ADVTXD_CC;
@@ -6045,10 +6146,10 @@ static void ixgbe_tx_queue(struct ixgbe_adapter *adapter,
i = tx_ring->next_to_use;
while (count--) {
tx_buffer_info = &tx_ring->tx_buffer_info[i];
- tx_desc = IXGBE_TX_DESC_ADV(*tx_ring, i);
+ tx_desc = IXGBE_TX_DESC_ADV(tx_ring, i);
tx_desc->read.buffer_addr = cpu_to_le64(tx_buffer_info->dma);
tx_desc->read.cmd_type_len =
- cpu_to_le32(cmd_type_len | tx_buffer_info->length);
+ cpu_to_le32(cmd_type_len | tx_buffer_info->length);
tx_desc->read.olinfo_status = cpu_to_le32(olinfo_status);
i++;
if (i == tx_ring->count)
@@ -6070,7 +6171,7 @@ static void ixgbe_tx_queue(struct ixgbe_adapter *adapter,
}
static void ixgbe_atr(struct ixgbe_adapter *adapter, struct sk_buff *skb,
- int queue, u32 tx_flags)
+ int queue, u32 tx_flags)
{
struct ixgbe_atr_input atr_input;
struct tcphdr *th;
@@ -6098,7 +6199,7 @@ static void ixgbe_atr(struct ixgbe_adapter *adapter, struct sk_buff *skb,
memset(&atr_input, 0, sizeof(struct ixgbe_atr_input));
vlan_id = (tx_flags & IXGBE_TX_FLAGS_VLAN_MASK) >>
- IXGBE_TX_FLAGS_VLAN_SHIFT;
+ IXGBE_TX_FLAGS_VLAN_SHIFT;
src_ipv4_addr = iph->saddr;
dst_ipv4_addr = iph->daddr;
flex_bytes = eth->h_proto;
@@ -6117,7 +6218,7 @@ static void ixgbe_atr(struct ixgbe_adapter *adapter, struct sk_buff *skb,
}
static int __ixgbe_maybe_stop_tx(struct net_device *netdev,
- struct ixgbe_ring *tx_ring, int size)
+ struct ixgbe_ring *tx_ring, int size)
{
netif_stop_subqueue(netdev, tx_ring->queue_index);
/* Herbert's original patch had:
@@ -6137,7 +6238,7 @@ static int __ixgbe_maybe_stop_tx(struct net_device *netdev,
}
static int ixgbe_maybe_stop_tx(struct net_device *netdev,
- struct ixgbe_ring *tx_ring, int size)
+ struct ixgbe_ring *tx_ring, int size)
{
if (likely(IXGBE_DESC_UNUSED(tx_ring) >= size))
return 0;
@@ -6183,11 +6284,10 @@ static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb)
return skb_tx_hash(dev, skb);
}
-static netdev_tx_t ixgbe_xmit_frame(struct sk_buff *skb,
- struct net_device *netdev)
+netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb, struct net_device *netdev,
+ struct ixgbe_adapter *adapter,
+ struct ixgbe_ring *tx_ring)
{
- struct ixgbe_adapter *adapter = netdev_priv(netdev);
- struct ixgbe_ring *tx_ring;
struct netdev_queue *txq;
unsigned int first;
unsigned int tx_flags = 0;
@@ -6196,7 +6296,7 @@ static netdev_tx_t ixgbe_xmit_frame(struct sk_buff *skb,
int count = 0;
unsigned int f;
- if (adapter->vlgrp && vlan_tx_tag_present(skb)) {
+ if (vlan_tx_tag_present(skb)) {
tx_flags |= vlan_tx_tag_get(skb);
if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
tx_flags &= ~IXGBE_TX_FLAGS_VLAN_PRIO_MASK;
@@ -6211,8 +6311,6 @@ static netdev_tx_t ixgbe_xmit_frame(struct sk_buff *skb,
tx_flags |= IXGBE_TX_FLAGS_VLAN;
}
- tx_ring = adapter->tx_ring[skb->queue_mapping];
-
#ifdef IXGBE_FCOE
/* for FCoE with DCB, we force the priority to what
* was specified by the switch */
@@ -6283,10 +6381,10 @@ static netdev_tx_t ixgbe_xmit_frame(struct sk_buff *skb,
if (tx_ring->atr_sample_rate) {
++tx_ring->atr_count;
if ((tx_ring->atr_count >= tx_ring->atr_sample_rate) &&
- test_bit(__IXGBE_FDIR_INIT_DONE,
- &tx_ring->reinit_state)) {
+ test_bit(__IXGBE_FDIR_INIT_DONE,
+ &tx_ring->reinit_state)) {
ixgbe_atr(adapter, skb, tx_ring->queue_index,
- tx_flags);
+ tx_flags);
tx_ring->atr_count = 0;
}
}
@@ -6294,7 +6392,7 @@ static netdev_tx_t ixgbe_xmit_frame(struct sk_buff *skb,
txq->tx_bytes += skb->len;
txq->tx_packets++;
ixgbe_tx_queue(adapter, tx_ring, tx_flags, count, skb->len,
- hdr_len);
+ hdr_len);
ixgbe_maybe_stop_tx(netdev, tx_ring, DESC_NEEDED);
} else {
@@ -6306,6 +6404,15 @@ static netdev_tx_t ixgbe_xmit_frame(struct sk_buff *skb,
return NETDEV_TX_OK;
}
+static netdev_tx_t ixgbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
+ struct ixgbe_ring *tx_ring;
+
+ tx_ring = adapter->tx_ring[skb->queue_mapping];
+ return ixgbe_xmit_frame_ring(skb, netdev, adapter, tx_ring);
+}
+
/**
* ixgbe_set_mac - Change the Ethernet Address of the NIC
* @netdev: network interface device structure
@@ -6436,8 +6543,40 @@ static void ixgbe_netpoll(struct net_device *netdev)
}
#endif
+static struct rtnl_link_stats64 *ixgbe_get_stats64(struct net_device *netdev,
+ struct rtnl_link_stats64 *stats)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
+ int i;
+
+ /* accurate rx/tx bytes/packets stats */
+ dev_txq_stats_fold(netdev, stats);
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ struct ixgbe_ring *ring = adapter->rx_ring[i];
+ u64 bytes, packets;
+ unsigned int start;
+
+ do {
+ start = u64_stats_fetch_begin_bh(&ring->syncp);
+ packets = ring->stats.packets;
+ bytes = ring->stats.bytes;
+ } while (u64_stats_fetch_retry_bh(&ring->syncp, start));
+ stats->rx_packets += packets;
+ stats->rx_bytes += bytes;
+ }
+
+ /* following stats updated by ixgbe_watchdog_task() */
+ stats->multicast = netdev->stats.multicast;
+ stats->rx_errors = netdev->stats.rx_errors;
+ stats->rx_length_errors = netdev->stats.rx_length_errors;
+ stats->rx_crc_errors = netdev->stats.rx_crc_errors;
+ stats->rx_missed_errors = netdev->stats.rx_missed_errors;
+ return stats;
+}
+
+
static const struct net_device_ops ixgbe_netdev_ops = {
- .ndo_open = ixgbe_open,
+ .ndo_open = ixgbe_open,
.ndo_stop = ixgbe_close,
.ndo_start_xmit = ixgbe_xmit_frame,
.ndo_select_queue = ixgbe_select_queue,
@@ -6447,7 +6586,6 @@ static const struct net_device_ops ixgbe_netdev_ops = {
.ndo_set_mac_address = ixgbe_set_mac,
.ndo_change_mtu = ixgbe_change_mtu,
.ndo_tx_timeout = ixgbe_tx_timeout,
- .ndo_vlan_rx_register = ixgbe_vlan_rx_register,
.ndo_vlan_rx_add_vid = ixgbe_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = ixgbe_vlan_rx_kill_vid,
.ndo_do_ioctl = ixgbe_ioctl,
@@ -6455,6 +6593,7 @@ static const struct net_device_ops ixgbe_netdev_ops = {
.ndo_set_vf_vlan = ixgbe_ndo_set_vf_vlan,
.ndo_set_vf_tx_rate = ixgbe_ndo_set_vf_bw,
.ndo_get_vf_config = ixgbe_ndo_get_vf_config,
+ .ndo_get_stats64 = ixgbe_get_stats64,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = ixgbe_netpoll,
#endif
@@ -6532,7 +6671,7 @@ err_novfs:
* and a hardware reset occur.
**/
static int __devinit ixgbe_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+ const struct pci_device_id *ent)
{
struct net_device *netdev;
struct ixgbe_adapter *adapter = NULL;
@@ -6577,7 +6716,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
}
err = pci_request_selected_regions(pdev, pci_select_bars(pdev,
- IORESOURCE_MEM), ixgbe_driver_name);
+ IORESOURCE_MEM), ixgbe_driver_name);
if (err) {
dev_err(&pdev->dev,
"pci_request_selected_regions failed 0x%x\n", err);
@@ -6617,7 +6756,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
adapter->msg_enable = (1 << DEFAULT_DEBUG_LEVEL_SHIFT) - 1;
hw->hw_addr = ioremap(pci_resource_start(pdev, 0),
- pci_resource_len(pdev, 0));
+ pci_resource_len(pdev, 0));
if (!hw->hw_addr) {
err = -EIO;
goto err_ioremap;
@@ -6661,7 +6800,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
* which might start the timer
*/
init_timer(&adapter->sfp_timer);
- adapter->sfp_timer.function = &ixgbe_sfp_timer;
+ adapter->sfp_timer.function = ixgbe_sfp_timer;
adapter->sfp_timer.data = (unsigned long) adapter;
INIT_WORK(&adapter->sfp_task, ixgbe_sfp_task);
@@ -6671,7 +6810,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
/* a new SFP+ module arrival, called from GPI SDP2 context */
INIT_WORK(&adapter->sfp_config_module_task,
- ixgbe_sfp_config_module_task);
+ ixgbe_sfp_config_module_task);
ii->get_invariants(hw);
@@ -6723,10 +6862,10 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
ixgbe_probe_vf(adapter, ii);
netdev->features = NETIF_F_SG |
- NETIF_F_IP_CSUM |
- NETIF_F_HW_VLAN_TX |
- NETIF_F_HW_VLAN_RX |
- NETIF_F_HW_VLAN_FILTER;
+ NETIF_F_IP_CSUM |
+ NETIF_F_HW_VLAN_TX |
+ NETIF_F_HW_VLAN_RX |
+ NETIF_F_HW_VLAN_FILTER;
netdev->features |= NETIF_F_IPV6_CSUM;
netdev->features |= NETIF_F_TSO;
@@ -6766,8 +6905,10 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
netdev->vlan_features |= NETIF_F_FCOE_MTU;
}
#endif /* IXGBE_FCOE */
- if (pci_using_dac)
+ if (pci_using_dac) {
netdev->features |= NETIF_F_HIGHDMA;
+ netdev->vlan_features |= NETIF_F_HIGHDMA;
+ }
if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED)
netdev->features |= NETIF_F_LRO;
@@ -6793,7 +6934,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
hw->mac.ops.disable_tx_laser(hw);
init_timer(&adapter->watchdog_timer);
- adapter->watchdog_timer.function = &ixgbe_watchdog;
+ adapter->watchdog_timer.function = ixgbe_watchdog;
adapter->watchdog_timer.data = (unsigned long)adapter;
INIT_WORK(&adapter->reset_task, ixgbe_reset_task);
@@ -6806,7 +6947,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
switch (pdev->device) {
case IXGBE_DEV_ID_82599_KX4:
adapter->wol = (IXGBE_WUFC_MAG | IXGBE_WUFC_EX |
- IXGBE_WUFC_MC | IXGBE_WUFC_BC);
+ IXGBE_WUFC_MC | IXGBE_WUFC_BC);
break;
default:
adapter->wol = 0;
@@ -6819,13 +6960,14 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
/* print bus type/speed/width info */
e_dev_info("(PCI Express:%s:%s) %pM\n",
- ((hw->bus.speed == ixgbe_bus_speed_5000) ? "5.0Gb/s":
- (hw->bus.speed == ixgbe_bus_speed_2500) ? "2.5Gb/s":"Unknown"),
- ((hw->bus.width == ixgbe_bus_width_pcie_x8) ? "Width x8" :
- (hw->bus.width == ixgbe_bus_width_pcie_x4) ? "Width x4" :
- (hw->bus.width == ixgbe_bus_width_pcie_x1) ? "Width x1" :
- "Unknown"),
- netdev->dev_addr);
+ (hw->bus.speed == ixgbe_bus_speed_5000 ? "5.0Gb/s" :
+ hw->bus.speed == ixgbe_bus_speed_2500 ? "2.5Gb/s" :
+ "Unknown"),
+ (hw->bus.width == ixgbe_bus_width_pcie_x8 ? "Width x8" :
+ hw->bus.width == ixgbe_bus_width_pcie_x4 ? "Width x4" :
+ hw->bus.width == ixgbe_bus_width_pcie_x1 ? "Width x1" :
+ "Unknown"),
+ netdev->dev_addr);
ixgbe_read_pba_num_generic(hw, &part_num);
if (ixgbe_is_sfp(hw) && hw->phy.sfp_type != ixgbe_sfp_type_not_present)
e_dev_info("MAC: %d, PHY: %d, SFP+: %d, "
@@ -6872,7 +7014,8 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
INIT_WORK(&adapter->fdir_reinit_task, ixgbe_fdir_reinit_task);
if (adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE)
- INIT_WORK(&adapter->check_overtemp_task, ixgbe_check_overtemp_task);
+ INIT_WORK(&adapter->check_overtemp_task,
+ ixgbe_check_overtemp_task);
#ifdef CONFIG_IXGBE_DCA
if (dca_add_requester(&pdev->dev) == 0) {
adapter->flags |= IXGBE_FLAG_DCA_ENABLED;
@@ -6908,8 +7051,8 @@ err_eeprom:
err_ioremap:
free_netdev(netdev);
err_alloc_etherdev:
- pci_release_selected_regions(pdev, pci_select_bars(pdev,
- IORESOURCE_MEM));
+ pci_release_selected_regions(pdev,
+ pci_select_bars(pdev, IORESOURCE_MEM));
err_pci_reg:
err_dma:
pci_disable_device(pdev);
@@ -6976,7 +7119,7 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev)
iounmap(adapter->hw.hw_addr);
pci_release_selected_regions(pdev, pci_select_bars(pdev,
- IORESOURCE_MEM));
+ IORESOURCE_MEM));
e_dev_info("complete\n");
@@ -6996,7 +7139,7 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev)
* this device has been detected.
*/
static pci_ers_result_t ixgbe_io_error_detected(struct pci_dev *pdev,
- pci_channel_state_t state)
+ pci_channel_state_t state)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct ixgbe_adapter *adapter = netdev_priv(netdev);
@@ -7102,8 +7245,7 @@ static struct pci_driver ixgbe_driver = {
static int __init ixgbe_init_module(void)
{
int ret;
- pr_info("%s - version %s\n", ixgbe_driver_string,
- ixgbe_driver_version);
+ pr_info("%s - version %s\n", ixgbe_driver_string, ixgbe_driver_version);
pr_info("%s\n", ixgbe_copyright);
#ifdef CONFIG_IXGBE_DCA
@@ -7132,12 +7274,12 @@ static void __exit ixgbe_exit_module(void)
#ifdef CONFIG_IXGBE_DCA
static int ixgbe_notify_dca(struct notifier_block *nb, unsigned long event,
- void *p)
+ void *p)
{
int ret_val;
ret_val = driver_for_each_device(&ixgbe_driver.driver, NULL, &event,
- __ixgbe_notify_dca);
+ __ixgbe_notify_dca);
return ret_val ? NOTIFY_BAD : NOTIFY_DONE;
}
diff --git a/drivers/net/ixgbe/ixgbe_mbx.c b/drivers/net/ixgbe/ixgbe_mbx.c
index d75f9148eb1f..471f0f2cdb98 100644
--- a/drivers/net/ixgbe/ixgbe_mbx.c
+++ b/drivers/net/ixgbe/ixgbe_mbx.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
- Copyright(c) 1999 - 2009 Intel Corporation.
+ Copyright(c) 1999 - 2010 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -200,7 +200,8 @@ out:
* returns SUCCESS if it successfully received a message notification and
* copied it into the receive buffer.
**/
-s32 ixgbe_read_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id)
+static s32 ixgbe_read_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size,
+ u16 mbx_id)
{
struct ixgbe_mbx_info *mbx = &hw->mbx;
s32 ret_val = IXGBE_ERR_MBX;
@@ -227,7 +228,7 @@ out:
* returns SUCCESS if it successfully copied message into the buffer and
* received an ack to that message within delay * timeout period
**/
-s32 ixgbe_write_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size,
+static s32 ixgbe_write_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size,
u16 mbx_id)
{
struct ixgbe_mbx_info *mbx = &hw->mbx;
@@ -247,20 +248,6 @@ out:
return ret_val;
}
-/**
- * ixgbe_init_mbx_ops_generic - Initialize MB function pointers
- * @hw: pointer to the HW structure
- *
- * Setup the mailbox read and write message function pointers
- **/
-void ixgbe_init_mbx_ops_generic(struct ixgbe_hw *hw)
-{
- struct ixgbe_mbx_info *mbx = &hw->mbx;
-
- mbx->ops.read_posted = ixgbe_read_posted_mbx;
- mbx->ops.write_posted = ixgbe_write_posted_mbx;
-}
-
static s32 ixgbe_check_for_bit_pf(struct ixgbe_hw *hw, u32 mask, s32 index)
{
u32 mbvficr = IXGBE_READ_REG(hw, IXGBE_MBVFICR(index));
diff --git a/drivers/net/ixgbe/ixgbe_mbx.h b/drivers/net/ixgbe/ixgbe_mbx.h
index be7ab3309ab7..7e0d08ff5b53 100644
--- a/drivers/net/ixgbe/ixgbe_mbx.h
+++ b/drivers/net/ixgbe/ixgbe_mbx.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
- Copyright(c) 1999 - 2009 Intel Corporation.
+ Copyright(c) 1999 - 2010 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -83,12 +83,9 @@
s32 ixgbe_read_mbx(struct ixgbe_hw *, u32 *, u16, u16);
s32 ixgbe_write_mbx(struct ixgbe_hw *, u32 *, u16, u16);
-s32 ixgbe_read_posted_mbx(struct ixgbe_hw *, u32 *, u16, u16);
-s32 ixgbe_write_posted_mbx(struct ixgbe_hw *, u32 *, u16, u16);
s32 ixgbe_check_for_msg(struct ixgbe_hw *, u16);
s32 ixgbe_check_for_ack(struct ixgbe_hw *, u16);
s32 ixgbe_check_for_rst(struct ixgbe_hw *, u16);
-void ixgbe_init_mbx_ops_generic(struct ixgbe_hw *hw);
void ixgbe_init_mbx_params_pf(struct ixgbe_hw *);
extern struct ixgbe_mbx_operations mbx_ops_82599;
diff --git a/drivers/net/ixgbe/ixgbe_sriov.c b/drivers/net/ixgbe/ixgbe_sriov.c
index 49661a138e22..5428153af8f3 100644
--- a/drivers/net/ixgbe/ixgbe_sriov.c
+++ b/drivers/net/ixgbe/ixgbe_sriov.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
- Copyright(c) 1999 - 2009 Intel Corporation.
+ Copyright(c) 1999 - 2010 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -43,8 +43,8 @@
#include "ixgbe_sriov.h"
-int ixgbe_set_vf_multicasts(struct ixgbe_adapter *adapter,
- int entries, u16 *hash_list, u32 vf)
+static int ixgbe_set_vf_multicasts(struct ixgbe_adapter *adapter,
+ int entries, u16 *hash_list, u32 vf)
{
struct vf_data_storage *vfinfo = &adapter->vfinfo[vf];
struct ixgbe_hw *hw = &adapter->hw;
@@ -104,13 +104,14 @@ void ixgbe_restore_vf_multicasts(struct ixgbe_adapter *adapter)
}
}
-int ixgbe_set_vf_vlan(struct ixgbe_adapter *adapter, int add, int vid, u32 vf)
+static int ixgbe_set_vf_vlan(struct ixgbe_adapter *adapter, int add, int vid,
+ u32 vf)
{
return adapter->hw.mac.ops.set_vfta(&adapter->hw, vid, vf, (bool)add);
}
-void ixgbe_set_vmolr(struct ixgbe_hw *hw, u32 vf, bool aupe)
+static void ixgbe_set_vmolr(struct ixgbe_hw *hw, u32 vf, bool aupe)
{
u32 vmolr = IXGBE_READ_REG(hw, IXGBE_VMOLR(vf));
vmolr |= (IXGBE_VMOLR_ROMPE |
@@ -134,7 +135,7 @@ static void ixgbe_set_vmvir(struct ixgbe_adapter *adapter, u32 vid, u32 vf)
IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf), 0);
}
-inline void ixgbe_vf_reset_event(struct ixgbe_adapter *adapter, u32 vf)
+static inline void ixgbe_vf_reset_event(struct ixgbe_adapter *adapter, u32 vf)
{
struct ixgbe_hw *hw = &adapter->hw;
int rar_entry = hw->mac.num_rar_entries - (vf + 1);
@@ -162,8 +163,8 @@ inline void ixgbe_vf_reset_event(struct ixgbe_adapter *adapter, u32 vf)
hw->mac.ops.clear_rar(hw, rar_entry);
}
-int ixgbe_set_vf_mac(struct ixgbe_adapter *adapter,
- int vf, unsigned char *mac_addr)
+static int ixgbe_set_vf_mac(struct ixgbe_adapter *adapter,
+ int vf, unsigned char *mac_addr)
{
struct ixgbe_hw *hw = &adapter->hw;
int rar_entry = hw->mac.num_rar_entries - (vf + 1);
@@ -197,7 +198,7 @@ int ixgbe_vf_configuration(struct pci_dev *pdev, unsigned int event_mask)
return 0;
}
-inline void ixgbe_vf_reset_msg(struct ixgbe_adapter *adapter, u32 vf)
+static inline void ixgbe_vf_reset_msg(struct ixgbe_adapter *adapter, u32 vf)
{
struct ixgbe_hw *hw = &adapter->hw;
u32 reg;
diff --git a/drivers/net/ixgbe/ixgbe_sriov.h b/drivers/net/ixgbe/ixgbe_sriov.h
index 184730ecdfb6..49dc14debef7 100644
--- a/drivers/net/ixgbe/ixgbe_sriov.h
+++ b/drivers/net/ixgbe/ixgbe_sriov.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
- Copyright(c) 1999 - 2009 Intel Corporation.
+ Copyright(c) 1999 - 2010 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -28,16 +28,8 @@
#ifndef _IXGBE_SRIOV_H_
#define _IXGBE_SRIOV_H_
-int ixgbe_set_vf_multicasts(struct ixgbe_adapter *adapter,
- int entries, u16 *hash_list, u32 vf);
void ixgbe_restore_vf_multicasts(struct ixgbe_adapter *adapter);
-int ixgbe_set_vf_vlan(struct ixgbe_adapter *adapter, int add, int vid, u32 vf);
-void ixgbe_set_vmolr(struct ixgbe_hw *hw, u32 vf, bool aupe);
-void ixgbe_vf_reset_event(struct ixgbe_adapter *adapter, u32 vf);
-void ixgbe_vf_reset_msg(struct ixgbe_adapter *adapter, u32 vf);
void ixgbe_msg_task(struct ixgbe_adapter *adapter);
-int ixgbe_set_vf_mac(struct ixgbe_adapter *adapter,
- int vf, unsigned char *mac_addr);
int ixgbe_vf_configuration(struct pci_dev *pdev, unsigned int event_mask);
void ixgbe_disable_tx_rx(struct ixgbe_adapter *adapter);
void ixgbe_ping_all_vfs(struct ixgbe_adapter *adapter);
diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h
index 9587d975d66c..d3cc6ce7c973 100644
--- a/drivers/net/ixgbe/ixgbe_type.h
+++ b/drivers/net/ixgbe/ixgbe_type.h
@@ -871,6 +871,8 @@
#define IXGBE_RDRXCTL_MVMEN 0x00000020
#define IXGBE_RDRXCTL_DMAIDONE 0x00000008 /* DMA init cycle done */
#define IXGBE_RDRXCTL_AGGDIS 0x00010000 /* Aggregation disable */
+#define IXGBE_RDRXCTL_RSCACKC 0x02000000 /* must set 1 when RSC enabled */
+#define IXGBE_RDRXCTL_FCOE_WRFIX 0x04000000 /* must set 1 when RSC enabled */
/* RQTC Bit Masks and Shifts */
#define IXGBE_RQTC_SHIFT_TC(_i) ((_i) * 4)
diff --git a/drivers/net/ixgbevf/ethtool.c b/drivers/net/ixgbevf/ethtool.c
index 4680b069b84f..4cc817acfb62 100644
--- a/drivers/net/ixgbevf/ethtool.c
+++ b/drivers/net/ixgbevf/ethtool.c
@@ -330,10 +330,8 @@ static int ixgbevf_set_ringparam(struct net_device *netdev,
{
struct ixgbevf_adapter *adapter = netdev_priv(netdev);
struct ixgbevf_ring *tx_ring = NULL, *rx_ring = NULL;
- int i, err;
+ int i, err = 0;
u32 new_rx_count, new_tx_count;
- bool need_tx_update = false;
- bool need_rx_update = false;
if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
return -EINVAL;
@@ -355,89 +353,96 @@ static int ixgbevf_set_ringparam(struct net_device *netdev,
while (test_and_set_bit(__IXGBEVF_RESETTING, &adapter->state))
msleep(1);
- if (new_tx_count != adapter->tx_ring_count) {
- tx_ring = kcalloc(adapter->num_tx_queues,
- sizeof(struct ixgbevf_ring), GFP_KERNEL);
- if (!tx_ring) {
- err = -ENOMEM;
- goto err_setup;
- }
- memcpy(tx_ring, adapter->tx_ring,
- adapter->num_tx_queues * sizeof(struct ixgbevf_ring));
- for (i = 0; i < adapter->num_tx_queues; i++) {
- tx_ring[i].count = new_tx_count;
- err = ixgbevf_setup_tx_resources(adapter,
- &tx_ring[i]);
- if (err) {
- while (i) {
- i--;
- ixgbevf_free_tx_resources(adapter,
- &tx_ring[i]);
- }
- kfree(tx_ring);
- goto err_setup;
- }
- tx_ring[i].v_idx = adapter->tx_ring[i].v_idx;
- }
- need_tx_update = true;
+ /*
+ * If the adapter isn't up and running then just set the
+ * new parameters and scurry for the exits.
+ */
+ if (!netif_running(adapter->netdev)) {
+ for (i = 0; i < adapter->num_tx_queues; i++)
+ adapter->tx_ring[i].count = new_tx_count;
+ for (i = 0; i < adapter->num_rx_queues; i++)
+ adapter->rx_ring[i].count = new_rx_count;
+ adapter->tx_ring_count = new_tx_count;
+ adapter->rx_ring_count = new_rx_count;
+ goto clear_reset;
}
- if (new_rx_count != adapter->rx_ring_count) {
- rx_ring = kcalloc(adapter->num_rx_queues,
- sizeof(struct ixgbevf_ring), GFP_KERNEL);
- if ((!rx_ring) && (need_tx_update)) {
- err = -ENOMEM;
- goto err_rx_setup;
- }
- memcpy(rx_ring, adapter->rx_ring,
- adapter->num_rx_queues * sizeof(struct ixgbevf_ring));
- for (i = 0; i < adapter->num_rx_queues; i++) {
- rx_ring[i].count = new_rx_count;
- err = ixgbevf_setup_rx_resources(adapter,
- &rx_ring[i]);
- if (err) {
- while (i) {
- i--;
- ixgbevf_free_rx_resources(adapter,
- &rx_ring[i]);
- }
- kfree(rx_ring);
- goto err_rx_setup;
- }
- rx_ring[i].v_idx = adapter->rx_ring[i].v_idx;
- }
- need_rx_update = true;
+ tx_ring = kcalloc(adapter->num_tx_queues,
+ sizeof(struct ixgbevf_ring), GFP_KERNEL);
+ if (!tx_ring) {
+ err = -ENOMEM;
+ goto clear_reset;
}
-err_rx_setup:
- /* if rings need to be updated, here's the place to do it in one shot */
- if (need_tx_update || need_rx_update) {
- if (netif_running(netdev))
- ixgbevf_down(adapter);
+ rx_ring = kcalloc(adapter->num_rx_queues,
+ sizeof(struct ixgbevf_ring), GFP_KERNEL);
+ if (!rx_ring) {
+ err = -ENOMEM;
+ goto err_rx_setup;
}
- /* tx */
- if (need_tx_update) {
- kfree(adapter->tx_ring);
- adapter->tx_ring = tx_ring;
- tx_ring = NULL;
- adapter->tx_ring_count = new_tx_count;
+ ixgbevf_down(adapter);
+
+ memcpy(tx_ring, adapter->tx_ring,
+ adapter->num_tx_queues * sizeof(struct ixgbevf_ring));
+ for (i = 0; i < adapter->num_tx_queues; i++) {
+ tx_ring[i].count = new_tx_count;
+ err = ixgbevf_setup_tx_resources(adapter, &tx_ring[i]);
+ if (err) {
+ while (i) {
+ i--;
+ ixgbevf_free_tx_resources(adapter,
+ &tx_ring[i]);
+ }
+ goto err_tx_ring_setup;
+ }
+ tx_ring[i].v_idx = adapter->tx_ring[i].v_idx;
}
- /* rx */
- if (need_rx_update) {
- kfree(adapter->rx_ring);
- adapter->rx_ring = rx_ring;
- rx_ring = NULL;
- adapter->rx_ring_count = new_rx_count;
+ memcpy(rx_ring, adapter->rx_ring,
+ adapter->num_rx_queues * sizeof(struct ixgbevf_ring));
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ rx_ring[i].count = new_rx_count;
+ err = ixgbevf_setup_rx_resources(adapter, &rx_ring[i]);
+ if (err) {
+ while (i) {
+ i--;
+ ixgbevf_free_rx_resources(adapter,
+ &rx_ring[i]);
+ }
+ goto err_rx_ring_setup;
+ }
+ rx_ring[i].v_idx = adapter->rx_ring[i].v_idx;
}
+ /*
+ * Only switch to new rings if all the prior allocations
+ * and ring setups have succeeded.
+ */
+ kfree(adapter->tx_ring);
+ adapter->tx_ring = tx_ring;
+ adapter->tx_ring_count = new_tx_count;
+
+ kfree(adapter->rx_ring);
+ adapter->rx_ring = rx_ring;
+ adapter->rx_ring_count = new_rx_count;
+
/* success! */
- err = 0;
- if (netif_running(netdev))
- ixgbevf_up(adapter);
+ ixgbevf_up(adapter);
+
+ goto clear_reset;
+
+err_rx_ring_setup:
+ for(i = 0; i < adapter->num_tx_queues; i++)
+ ixgbevf_free_tx_resources(adapter, &tx_ring[i]);
+
+err_tx_ring_setup:
+ kfree(rx_ring);
+
+err_rx_setup:
+ kfree(tx_ring);
-err_setup:
+clear_reset:
clear_bit(__IXGBEVF_RESETTING, &adapter->state);
return err;
}
diff --git a/drivers/net/ixgbevf/ixgbevf.h b/drivers/net/ixgbevf/ixgbevf.h
index f7015efbff05..da4033c6efa2 100644
--- a/drivers/net/ixgbevf/ixgbevf.h
+++ b/drivers/net/ixgbevf/ixgbevf.h
@@ -243,7 +243,6 @@ struct ixgbevf_adapter {
/* OS defined structs */
struct net_device *netdev;
struct pci_dev *pdev;
- struct net_device_stats net_stats;
/* structs defined in ixgbe_vf.h */
struct ixgbe_hw hw;
diff --git a/drivers/net/ixgbevf/ixgbevf_main.c b/drivers/net/ixgbevf/ixgbevf_main.c
index 918c00359b0a..dc03c9652389 100644
--- a/drivers/net/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ixgbevf/ixgbevf_main.c
@@ -308,10 +308,10 @@ static bool ixgbevf_clean_tx_irq(struct ixgbevf_adapter *adapter,
tx_ring->total_bytes += total_bytes;
tx_ring->total_packets += total_packets;
- adapter->net_stats.tx_bytes += total_bytes;
- adapter->net_stats.tx_packets += total_packets;
+ netdev->stats.tx_bytes += total_bytes;
+ netdev->stats.tx_packets += total_packets;
- return (count < tx_ring->work_limit);
+ return count < tx_ring->work_limit;
}
/**
@@ -356,7 +356,7 @@ static void ixgbevf_receive_skb(struct ixgbevf_q_vector *q_vector,
static inline void ixgbevf_rx_checksum(struct ixgbevf_adapter *adapter,
u32 status_err, struct sk_buff *skb)
{
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
/* Rx csum disabled */
if (!(adapter->flags & IXGBE_FLAG_RX_CSUM_ENABLED))
@@ -639,8 +639,8 @@ next_desc:
rx_ring->total_packets += total_rx_packets;
rx_ring->total_bytes += total_rx_bytes;
- adapter->net_stats.rx_bytes += total_rx_bytes;
- adapter->net_stats.rx_packets += total_rx_packets;
+ adapter->netdev->stats.rx_bytes += total_rx_bytes;
+ adapter->netdev->stats.rx_packets += total_rx_packets;
return cleaned;
}
@@ -1495,7 +1495,7 @@ static void ixgbevf_restore_vlan(struct ixgbevf_adapter *adapter)
if (adapter->vlgrp) {
u16 vid;
- for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
+ for (vid = 0; vid < VLAN_N_VID; vid++) {
if (!vlan_group_get_device(adapter->vlgrp, vid))
continue;
ixgbevf_vlan_rx_add_vid(adapter->netdev, vid);
@@ -2297,7 +2297,7 @@ void ixgbevf_update_stats(struct ixgbevf_adapter *adapter)
adapter->stats.vfmprc);
/* Fill out the OS statistics structure */
- adapter->net_stats.multicast = adapter->stats.vfmprc -
+ adapter->netdev->stats.multicast = adapter->stats.vfmprc -
adapter->stats.base_vfmprc;
}
@@ -3134,7 +3134,7 @@ static int ixgbevf_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
tx_ring = &adapter->tx_ring[r_idx];
- if (adapter->vlgrp && vlan_tx_tag_present(skb)) {
+ if (vlan_tx_tag_present(skb)) {
tx_flags |= vlan_tx_tag_get(skb);
tx_flags <<= IXGBE_TX_FLAGS_VLAN_SHIFT;
tx_flags |= IXGBE_TX_FLAGS_VLAN;
@@ -3181,21 +3181,6 @@ static int ixgbevf_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
}
/**
- * ixgbevf_get_stats - Get System Network Statistics
- * @netdev: network interface device structure
- *
- * Returns the address of the device statistics structure.
- * The statistics are actually updated from the timer callback.
- **/
-static struct net_device_stats *ixgbevf_get_stats(struct net_device *netdev)
-{
- struct ixgbevf_adapter *adapter = netdev_priv(netdev);
-
- /* only return the current stats */
- return &adapter->net_stats;
-}
-
-/**
* ixgbevf_set_mac - Change the Ethernet Address of the NIC
* @netdev: network interface device structure
* @p: pointer to an address structure
@@ -3272,7 +3257,6 @@ static const struct net_device_ops ixgbe_netdev_ops = {
.ndo_open = &ixgbevf_open,
.ndo_stop = &ixgbevf_close,
.ndo_start_xmit = &ixgbevf_xmit_frame,
- .ndo_get_stats = &ixgbevf_get_stats,
.ndo_set_rx_mode = &ixgbevf_set_rx_mode,
.ndo_set_multicast_list = &ixgbevf_set_rx_mode,
.ndo_validate_addr = eth_validate_addr,
@@ -3426,7 +3410,7 @@ static int __devinit ixgbevf_probe(struct pci_dev *pdev,
}
init_timer(&adapter->watchdog_timer);
- adapter->watchdog_timer.function = &ixgbevf_watchdog;
+ adapter->watchdog_timer.function = ixgbevf_watchdog;
adapter->watchdog_timer.data = (unsigned long)adapter;
INIT_WORK(&adapter->reset_task, ixgbevf_reset_task);
diff --git a/drivers/net/ixgbevf/mbx.c b/drivers/net/ixgbevf/mbx.c
index b8143501e6fc..84ac486f4a65 100644
--- a/drivers/net/ixgbevf/mbx.c
+++ b/drivers/net/ixgbevf/mbx.c
@@ -308,7 +308,7 @@ out_no_read:
*
* Initializes the hw->mbx struct to correct values for vf mailbox
*/
-s32 ixgbevf_init_mbx_params_vf(struct ixgbe_hw *hw)
+static s32 ixgbevf_init_mbx_params_vf(struct ixgbe_hw *hw)
{
struct ixgbe_mbx_info *mbx = &hw->mbx;
diff --git a/drivers/net/ixgbevf/mbx.h b/drivers/net/ixgbevf/mbx.h
index 1b0e0bf4c0f5..8c063bebee7f 100644
--- a/drivers/net/ixgbevf/mbx.h
+++ b/drivers/net/ixgbevf/mbx.h
@@ -95,6 +95,4 @@
/* forward declaration of the HW struct */
struct ixgbe_hw;
-s32 ixgbevf_init_mbx_params_vf(struct ixgbe_hw *);
-
#endif /* _IXGBE_MBX_H_ */
diff --git a/drivers/net/ixgbevf/vf.c b/drivers/net/ixgbevf/vf.c
index f6f929958ba0..bfe42c1fcfaf 100644
--- a/drivers/net/ixgbevf/vf.c
+++ b/drivers/net/ixgbevf/vf.c
@@ -368,7 +368,7 @@ static s32 ixgbevf_check_mac_link_vf(struct ixgbe_hw *hw,
return 0;
}
-struct ixgbe_mac_operations ixgbevf_mac_ops = {
+static struct ixgbe_mac_operations ixgbevf_mac_ops = {
.init_hw = ixgbevf_init_hw_vf,
.reset_hw = ixgbevf_reset_hw_vf,
.start_hw = ixgbevf_start_hw_vf,
diff --git a/drivers/net/ixgbevf/vf.h b/drivers/net/ixgbevf/vf.h
index 94b750b8874f..61f9dc831424 100644
--- a/drivers/net/ixgbevf/vf.h
+++ b/drivers/net/ixgbevf/vf.h
@@ -124,8 +124,6 @@ struct ixgbe_hw {
void *back;
u8 __iomem *hw_addr;
- u8 *flash_address;
- unsigned long io_base;
struct ixgbe_mac_info mac;
struct ixgbe_mbx_info mbx;
diff --git a/drivers/net/jme.c b/drivers/net/jme.c
index 99f24f5cac53..d7a975ee2add 100644
--- a/drivers/net/jme.c
+++ b/drivers/net/jme.c
@@ -3,6 +3,7 @@
*
* Copyright 2008 JMicron Technology Corporation
* http://www.jmicron.com/
+ * Copyright (c) 2009 - 2010 Guo-Fu Tseng <cooldavid@cooldavid.org>
*
* Author: Guo-Fu Tseng <cooldavid@cooldavid.org>
*
@@ -21,6 +22,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/pci.h>
@@ -73,7 +76,7 @@ read_again:
}
if (i == 0) {
- jeprintk(jme->pdev, "phy(%d) read timeout : %d\n", phy, reg);
+ pr_err("phy(%d) read timeout : %d\n", phy, reg);
return 0;
}
@@ -102,7 +105,7 @@ jme_mdio_write(struct net_device *netdev,
}
if (i == 0)
- jeprintk(jme->pdev, "phy(%d) write timeout : %d\n", phy, reg);
+ pr_err("phy(%d) write timeout : %d\n", phy, reg);
}
static inline void
@@ -227,7 +230,7 @@ jme_reload_eeprom(struct jme_adapter *jme)
}
if (i == 0) {
- jeprintk(jme->pdev, "eeprom reload timeout\n");
+ pr_err("eeprom reload timeout\n");
return -EIO;
}
}
@@ -397,8 +400,7 @@ jme_check_link(struct net_device *netdev, int testonly)
phylink = jread32(jme, JME_PHY_LINK);
}
if (!cnt)
- jeprintk(jme->pdev,
- "Waiting speed resolve timeout.\n");
+ pr_err("Waiting speed resolve timeout\n");
strcat(linkmsg, "ANed: ");
}
@@ -480,13 +482,13 @@ jme_check_link(struct net_device *netdev, int testonly)
strcat(linkmsg, (phylink & PHY_LINK_MDI_STAT) ?
"MDI-X" :
"MDI");
- netif_info(jme, link, jme->dev, "Link is up at %s.\n", linkmsg);
+ netif_info(jme, link, jme->dev, "Link is up at %s\n", linkmsg);
netif_carrier_on(netdev);
} else {
if (testonly)
goto out;
- netif_info(jme, link, jme->dev, "Link is down.\n");
+ netif_info(jme, link, jme->dev, "Link is down\n");
jme->phylink = 0;
netif_carrier_off(netdev);
}
@@ -648,7 +650,7 @@ jme_disable_tx_engine(struct jme_adapter *jme)
}
if (!i)
- jeprintk(jme->pdev, "Disable TX engine timeout.\n");
+ pr_err("Disable TX engine timeout\n");
}
static void
@@ -867,7 +869,7 @@ jme_disable_rx_engine(struct jme_adapter *jme)
}
if (!i)
- jeprintk(jme->pdev, "Disable RX engine timeout.\n");
+ pr_err("Disable RX engine timeout\n");
}
@@ -887,13 +889,13 @@ jme_rxsum_ok(struct jme_adapter *jme, u16 flags)
if (unlikely((flags & (RXWBFLAG_MF | RXWBFLAG_UDPON | RXWBFLAG_UDPCS))
== RXWBFLAG_UDPON)) {
if (flags & RXWBFLAG_IPV4)
- netif_err(jme, rx_err, jme->dev, "UDP Checksum error.\n");
+ netif_err(jme, rx_err, jme->dev, "UDP Checksum error\n");
return false;
}
if (unlikely((flags & (RXWBFLAG_IPV4 | RXWBFLAG_IPCS))
== RXWBFLAG_IPV4)) {
- netif_err(jme, rx_err, jme->dev, "IPv4 Checksum error.\n");
+ netif_err(jme, rx_err, jme->dev, "IPv4 Checksum error\n");
return false;
}
@@ -936,7 +938,7 @@ jme_alloc_and_feed_skb(struct jme_adapter *jme, int idx)
if (jme_rxsum_ok(jme, le16_to_cpu(rxdesc->descwb.flags)))
skb->ip_summed = CHECKSUM_UNNECESSARY;
else
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
if (rxdesc->descwb.flags & cpu_to_le16(RXWBFLAG_TAGON)) {
if (jme->vlgrp) {
@@ -988,6 +990,7 @@ jme_process_receive(struct jme_adapter *jme, int limit)
goto out;
--limit;
+ rmb();
desccnt = rxdesc->descwb.desccnt & RXWBDCNT_DCNT;
if (unlikely(desccnt > 1 ||
@@ -1185,9 +1188,9 @@ jme_link_change_tasklet(unsigned long arg)
while (!atomic_dec_and_test(&jme->link_changing)) {
atomic_inc(&jme->link_changing);
- netif_info(jme, intr, jme->dev, "Get link change lock failed.\n");
+ netif_info(jme, intr, jme->dev, "Get link change lock failed\n");
while (atomic_read(&jme->link_changing) != 1)
- netif_info(jme, intr, jme->dev, "Waiting link change lock.\n");
+ netif_info(jme, intr, jme->dev, "Waiting link change lock\n");
}
if (jme_check_link(netdev, 1) && jme->old_mtu == netdev->mtu)
@@ -1221,15 +1224,13 @@ jme_link_change_tasklet(unsigned long arg)
if (netif_carrier_ok(netdev)) {
rc = jme_setup_rx_resources(jme);
if (rc) {
- jeprintk(jme->pdev, "Allocating resources for RX error"
- ", Device STOPPED!\n");
+ pr_err("Allocating resources for RX error, Device STOPPED!\n");
goto out_enable_tasklet;
}
rc = jme_setup_tx_resources(jme);
if (rc) {
- jeprintk(jme->pdev, "Allocating resources for TX error"
- ", Device STOPPED!\n");
+ pr_err("Allocating resources for TX error, Device STOPPED!\n");
goto err_out_free_rx_resources;
}
@@ -1324,7 +1325,7 @@ jme_wake_queue_if_stopped(struct jme_adapter *jme)
smp_wmb();
if (unlikely(netif_queue_stopped(jme->dev) &&
atomic_read(&txring->nr_free) >= (jme->tx_wake_threshold))) {
- netif_info(jme, tx_done, jme->dev, "TX Queue Waked.\n");
+ netif_info(jme, tx_done, jme->dev, "TX Queue Waked\n");
netif_wake_queue(jme->dev);
}
@@ -1339,7 +1340,7 @@ jme_tx_clean_tasklet(unsigned long arg)
struct jme_buffer_info *txbi = txring->bufinf, *ctxbi, *ttxbi;
int i, j, cnt = 0, max, err, mask;
- tx_dbg(jme, "Into txclean.\n");
+ tx_dbg(jme, "Into txclean\n");
if (unlikely(!atomic_dec_and_test(&jme->tx_cleaning)))
goto out;
@@ -1361,7 +1362,7 @@ jme_tx_clean_tasklet(unsigned long arg)
!(txdesc[i].descwb.flags & TXWBFLAG_OWN))) {
tx_dbg(jme, "txclean: %d+%d@%lu\n",
- i, ctxbi->nr_desc, jiffies);
+ i, ctxbi->nr_desc, jiffies);
err = txdesc[i].descwb.flags & TXWBFLAG_ALLERR;
@@ -1402,7 +1403,7 @@ jme_tx_clean_tasklet(unsigned long arg)
ctxbi->nr_desc = 0;
}
- tx_dbg(jme, "txclean: done %d@%lu.\n", i, jiffies);
+ tx_dbg(jme, "txclean: done %d@%lu\n", i, jiffies);
atomic_set(&txring->next_to_clean, i);
atomic_add(cnt, &txring->nr_free);
@@ -1548,10 +1549,10 @@ jme_request_irq(struct jme_adapter *jme)
rc = request_irq(jme->pdev->irq, handler, irq_flags, netdev->name,
netdev);
if (rc) {
- jeprintk(jme->pdev,
- "Unable to request %s interrupt (return: %d)\n",
- test_bit(JME_FLAG_MSI, &jme->flags) ? "MSI" : "INTx",
- rc);
+ netdev_err(netdev,
+ "Unable to request %s interrupt (return: %d)\n",
+ test_bit(JME_FLAG_MSI, &jme->flags) ? "MSI" : "INTx",
+ rc);
if (test_bit(JME_FLAG_MSI, &jme->flags)) {
pci_disable_msi(jme->pdev);
@@ -1575,6 +1576,16 @@ jme_free_irq(struct jme_adapter *jme)
}
}
+static inline void
+jme_phy_on(struct jme_adapter *jme)
+{
+ u32 bmcr;
+
+ bmcr = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_BMCR);
+ bmcr &= ~BMCR_PDOWN;
+ jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, bmcr);
+}
+
static int
jme_open(struct net_device *netdev)
{
@@ -1595,10 +1606,12 @@ jme_open(struct net_device *netdev)
jme_start_irq(jme);
- if (test_bit(JME_FLAG_SSET, &jme->flags))
+ if (test_bit(JME_FLAG_SSET, &jme->flags)) {
+ jme_phy_on(jme);
jme_set_settings(netdev, &jme->old_ecmd);
- else
+ } else {
jme_reset_phy_processor(jme);
+ }
jme_reset_link(jme);
@@ -1834,7 +1847,7 @@ jme_tx_csum(struct jme_adapter *jme, struct sk_buff *skb, u8 *flags)
*flags |= TXFLAG_UDPCS;
break;
default:
- netif_err(jme, tx_err, jme->dev, "Error upper layer protocol.\n");
+ netif_err(jme, tx_err, jme->dev, "Error upper layer protocol\n");
break;
}
}
@@ -1909,12 +1922,12 @@ jme_stop_queue_if_full(struct jme_adapter *jme)
smp_wmb();
if (unlikely(atomic_read(&txring->nr_free) < (MAX_SKB_FRAGS+2))) {
netif_stop_queue(jme->dev);
- netif_info(jme, tx_queued, jme->dev, "TX Queue Paused.\n");
+ netif_info(jme, tx_queued, jme->dev, "TX Queue Paused\n");
smp_wmb();
if (atomic_read(&txring->nr_free)
>= (jme->tx_wake_threshold)) {
netif_wake_queue(jme->dev);
- netif_info(jme, tx_queued, jme->dev, "TX Queue Fast Waked.\n");
+ netif_info(jme, tx_queued, jme->dev, "TX Queue Fast Waked\n");
}
}
@@ -1922,7 +1935,8 @@ jme_stop_queue_if_full(struct jme_adapter *jme)
(jiffies - txbi->start_xmit) >= TX_TIMEOUT &&
txbi->skb)) {
netif_stop_queue(jme->dev);
- netif_info(jme, tx_queued, jme->dev, "TX Queue Stopped %d@%lu.\n", idx, jiffies);
+ netif_info(jme, tx_queued, jme->dev,
+ "TX Queue Stopped %d@%lu\n", idx, jiffies);
}
}
@@ -1945,7 +1959,8 @@ jme_start_xmit(struct sk_buff *skb, struct net_device *netdev)
if (unlikely(idx < 0)) {
netif_stop_queue(netdev);
- netif_err(jme, tx_err, jme->dev, "BUG! Tx ring full when queue awake!\n");
+ netif_err(jme, tx_err, jme->dev,
+ "BUG! Tx ring full when queue awake!\n");
return NETDEV_TX_BUSY;
}
@@ -1957,9 +1972,8 @@ jme_start_xmit(struct sk_buff *skb, struct net_device *netdev)
TXCS_QUEUE0S |
TXCS_ENABLE);
- tx_dbg(jme, "xmit: %d+%d@%lu\n", idx,
- skb_shinfo(skb)->nr_frags + 2,
- jiffies);
+ tx_dbg(jme, "xmit: %d+%d@%lu\n",
+ idx, skb_shinfo(skb)->nr_frags + 2, jiffies);
jme_stop_queue_if_full(jme);
return NETDEV_TX_OK;
@@ -2382,6 +2396,10 @@ jme_set_settings(struct net_device *netdev,
if (ecmd->speed == SPEED_1000 && ecmd->autoneg != AUTONEG_ENABLE)
return -EINVAL;
+ /*
+ * Check If user changed duplex only while force_media.
+ * Hardware would not generate link change interrupt.
+ */
if (jme->mii_if.force_media &&
ecmd->autoneg != AUTONEG_ENABLE &&
(jme->mii_if.full_duplex != ecmd->duplex))
@@ -2391,12 +2409,40 @@ jme_set_settings(struct net_device *netdev,
rc = mii_ethtool_sset(&(jme->mii_if), ecmd);
spin_unlock_bh(&jme->phy_lock);
- if (!rc && fdc)
- jme_reset_link(jme);
-
if (!rc) {
- set_bit(JME_FLAG_SSET, &jme->flags);
+ if (fdc)
+ jme_reset_link(jme);
jme->old_ecmd = *ecmd;
+ set_bit(JME_FLAG_SSET, &jme->flags);
+ }
+
+ return rc;
+}
+
+static int
+jme_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
+{
+ int rc;
+ struct jme_adapter *jme = netdev_priv(netdev);
+ struct mii_ioctl_data *mii_data = if_mii(rq);
+ unsigned int duplex_chg;
+
+ if (cmd == SIOCSMIIREG) {
+ u16 val = mii_data->val_in;
+ if (!(val & (BMCR_RESET|BMCR_ANENABLE)) &&
+ (val & BMCR_SPEED1000))
+ return -EINVAL;
+ }
+
+ spin_lock_bh(&jme->phy_lock);
+ rc = generic_mii_ioctl(&jme->mii_if, mii_data, cmd, &duplex_chg);
+ spin_unlock_bh(&jme->phy_lock);
+
+ if (!rc && (cmd == SIOCSMIIREG)) {
+ if (duplex_chg)
+ jme_reset_link(jme);
+ jme_get_settings(netdev, &jme->old_ecmd);
+ set_bit(JME_FLAG_SSET, &jme->flags);
}
return rc;
@@ -2501,7 +2547,7 @@ jme_smb_read(struct jme_adapter *jme, unsigned int addr)
val = jread32(jme, JME_SMBCSR);
}
if (!to) {
- netif_err(jme, hw, jme->dev, "SMB Bus Busy.\n");
+ netif_err(jme, hw, jme->dev, "SMB Bus Busy\n");
return 0xFF;
}
@@ -2517,7 +2563,7 @@ jme_smb_read(struct jme_adapter *jme, unsigned int addr)
val = jread32(jme, JME_SMBINTF);
}
if (!to) {
- netif_err(jme, hw, jme->dev, "SMB Bus Busy.\n");
+ netif_err(jme, hw, jme->dev, "SMB Bus Busy\n");
return 0xFF;
}
@@ -2537,7 +2583,7 @@ jme_smb_write(struct jme_adapter *jme, unsigned int addr, u8 data)
val = jread32(jme, JME_SMBCSR);
}
if (!to) {
- netif_err(jme, hw, jme->dev, "SMB Bus Busy.\n");
+ netif_err(jme, hw, jme->dev, "SMB Bus Busy\n");
return;
}
@@ -2554,7 +2600,7 @@ jme_smb_write(struct jme_adapter *jme, unsigned int addr, u8 data)
val = jread32(jme, JME_SMBINTF);
}
if (!to) {
- netif_err(jme, hw, jme->dev, "SMB Bus Busy.\n");
+ netif_err(jme, hw, jme->dev, "SMB Bus Busy\n");
return;
}
@@ -2676,6 +2722,7 @@ static const struct net_device_ops jme_netdev_ops = {
.ndo_open = jme_open,
.ndo_stop = jme_close,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_do_ioctl = jme_ioctl,
.ndo_start_xmit = jme_start_xmit,
.ndo_set_mac_address = jme_set_macaddr,
.ndo_set_multicast_list = jme_set_multi,
@@ -2699,26 +2746,26 @@ jme_init_one(struct pci_dev *pdev,
*/
rc = pci_enable_device(pdev);
if (rc) {
- jeprintk(pdev, "Cannot enable PCI device.\n");
+ pr_err("Cannot enable PCI device\n");
goto err_out;
}
using_dac = jme_pci_dma64(pdev);
if (using_dac < 0) {
- jeprintk(pdev, "Cannot set PCI DMA Mask.\n");
+ pr_err("Cannot set PCI DMA Mask\n");
rc = -EIO;
goto err_out_disable_pdev;
}
if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
- jeprintk(pdev, "No PCI resource region found.\n");
+ pr_err("No PCI resource region found\n");
rc = -ENOMEM;
goto err_out_disable_pdev;
}
rc = pci_request_regions(pdev, DRV_NAME);
if (rc) {
- jeprintk(pdev, "Cannot obtain PCI resource region.\n");
+ pr_err("Cannot obtain PCI resource region\n");
goto err_out_disable_pdev;
}
@@ -2729,7 +2776,7 @@ jme_init_one(struct pci_dev *pdev,
*/
netdev = alloc_etherdev(sizeof(*jme));
if (!netdev) {
- jeprintk(pdev, "Cannot allocate netdev structure.\n");
+ pr_err("Cannot allocate netdev structure\n");
rc = -ENOMEM;
goto err_out_release_regions;
}
@@ -2767,7 +2814,7 @@ jme_init_one(struct pci_dev *pdev,
jme->regs = ioremap(pci_resource_start(pdev, 0),
pci_resource_len(pdev, 0));
if (!(jme->regs)) {
- jeprintk(pdev, "Mapping PCI resource region error.\n");
+ pr_err("Mapping PCI resource region error\n");
rc = -ENOMEM;
goto err_out_free_netdev;
}
@@ -2855,8 +2902,8 @@ jme_init_one(struct pci_dev *pdev,
if (!jme->mii_if.phy_id) {
rc = -EIO;
- jeprintk(pdev, "Can not find phy_id.\n");
- goto err_out_unmap;
+ pr_err("Can not find phy_id\n");
+ goto err_out_unmap;
}
jme->reg_ghc |= GHC_LINK_POLL;
@@ -2867,6 +2914,8 @@ jme_init_one(struct pci_dev *pdev,
jme->mii_if.supports_gmii = true;
else
jme->mii_if.supports_gmii = false;
+ jme->mii_if.phy_id_mask = 0x1F;
+ jme->mii_if.reg_num_mask = 0x1F;
jme->mii_if.mdio_read = jme_mdio_read;
jme->mii_if.mdio_write = jme_mdio_write;
@@ -2883,8 +2932,7 @@ jme_init_one(struct pci_dev *pdev,
jme_reset_mac_processor(jme);
rc = jme_reload_eeprom(jme);
if (rc) {
- jeprintk(pdev,
- "Reload eeprom for reading MAC Address error.\n");
+ pr_err("Reload eeprom for reading MAC Address error\n");
goto err_out_unmap;
}
jme_load_macaddr(netdev);
@@ -2900,7 +2948,7 @@ jme_init_one(struct pci_dev *pdev,
*/
rc = register_netdev(netdev);
if (rc) {
- jeprintk(pdev, "Cannot register net device.\n");
+ pr_err("Cannot register net device\n");
goto err_out_unmap;
}
@@ -3006,10 +3054,12 @@ jme_resume(struct pci_dev *pdev)
jme_clear_pm(jme);
pci_restore_state(pdev);
- if (test_bit(JME_FLAG_SSET, &jme->flags))
+ if (test_bit(JME_FLAG_SSET, &jme->flags)) {
+ jme_phy_on(jme);
jme_set_settings(netdev, &jme->old_ecmd);
- else
+ } else {
jme_reset_phy_processor(jme);
+ }
jme_start_irq(jme);
netif_device_attach(netdev);
@@ -3042,8 +3092,7 @@ static struct pci_driver jme_driver = {
static int __init
jme_init_module(void)
{
- printk(KERN_INFO PFX "JMicron JMC2XX ethernet "
- "driver version %s\n", DRV_VERSION);
+ pr_info("JMicron JMC2XX ethernet driver version %s\n", DRV_VERSION);
return pci_register_driver(&jme_driver);
}
diff --git a/drivers/net/jme.h b/drivers/net/jme.h
index 07ad3a457185..eac09264bf2a 100644
--- a/drivers/net/jme.h
+++ b/drivers/net/jme.h
@@ -3,6 +3,7 @@
*
* Copyright 2008 JMicron Technology Corporation
* http://www.jmicron.com/
+ * Copyright (c) 2009 - 2010 Guo-Fu Tseng <cooldavid@cooldavid.org>
*
* Author: Guo-Fu Tseng <cooldavid@cooldavid.org>
*
@@ -25,7 +26,7 @@
#define __JME_H_INCLUDED__
#define DRV_NAME "jme"
-#define DRV_VERSION "1.0.6"
+#define DRV_VERSION "1.0.7"
#define PFX DRV_NAME ": "
#define PCI_DEVICE_ID_JMICRON_JMC250 0x0250
@@ -41,9 +42,6 @@
NETIF_MSG_TX_ERR | \
NETIF_MSG_HW)
-#define jeprintk(pdev, fmt, args...) \
- printk(KERN_ERR PFX fmt, ## args)
-
#ifdef TX_DEBUG
#define tx_dbg(priv, fmt, args...) \
printk(KERN_DEBUG "%s: " fmt, (priv)->dev->name, ##args)
diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c
index 87f0a93b165c..9f8e7027b0b3 100644
--- a/drivers/net/ll_temac_main.c
+++ b/drivers/net/ll_temac_main.c
@@ -495,7 +495,7 @@ static u32 temac_setoptions(struct net_device *ndev, u32 options)
lp->options |= options;
mutex_unlock(&lp->indirect_mutex);
- return (0);
+ return 0;
}
/* Initialize temac */
@@ -761,7 +761,7 @@ static void ll_temac_recv(struct net_device *ndev)
skb_put(skb, length);
skb->dev = ndev;
skb->protocol = eth_type_trans(skb, ndev);
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
/* if we're doing rx csum offload, set it up */
if (((lp->temac_features & TEMAC_FEATURE_RX_CSUM) != 0) &&
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index 9a0996795321..2d9663a1c54d 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -64,7 +64,6 @@ struct pcpu_lstats {
u64 packets;
u64 bytes;
struct u64_stats_sync syncp;
- unsigned long drops;
};
/*
@@ -74,7 +73,6 @@ struct pcpu_lstats {
static netdev_tx_t loopback_xmit(struct sk_buff *skb,
struct net_device *dev)
{
- struct pcpu_lstats __percpu *pcpu_lstats;
struct pcpu_lstats *lb_stats;
int len;
@@ -83,8 +81,7 @@ static netdev_tx_t loopback_xmit(struct sk_buff *skb,
skb->protocol = eth_type_trans(skb, dev);
/* it's OK to use per_cpu_ptr() because BHs are off */
- pcpu_lstats = (void __percpu __force *)dev->ml_priv;
- lb_stats = this_cpu_ptr(pcpu_lstats);
+ lb_stats = this_cpu_ptr(dev->lstats);
len = skb->len;
if (likely(netif_rx(skb) == NET_RX_SUCCESS)) {
@@ -92,8 +89,7 @@ static netdev_tx_t loopback_xmit(struct sk_buff *skb,
lb_stats->bytes += len;
lb_stats->packets++;
u64_stats_update_end(&lb_stats->syncp);
- } else
- lb_stats->drops++;
+ }
return NETDEV_TX_OK;
}
@@ -101,32 +97,26 @@ static netdev_tx_t loopback_xmit(struct sk_buff *skb,
static struct rtnl_link_stats64 *loopback_get_stats64(struct net_device *dev,
struct rtnl_link_stats64 *stats)
{
- const struct pcpu_lstats __percpu *pcpu_lstats;
u64 bytes = 0;
u64 packets = 0;
- u64 drops = 0;
int i;
- pcpu_lstats = (void __percpu __force *)dev->ml_priv;
for_each_possible_cpu(i) {
const struct pcpu_lstats *lb_stats;
u64 tbytes, tpackets;
unsigned int start;
- lb_stats = per_cpu_ptr(pcpu_lstats, i);
+ lb_stats = per_cpu_ptr(dev->lstats, i);
do {
start = u64_stats_fetch_begin(&lb_stats->syncp);
tbytes = lb_stats->bytes;
tpackets = lb_stats->packets;
} while (u64_stats_fetch_retry(&lb_stats->syncp, start));
- drops += lb_stats->drops;
bytes += tbytes;
packets += tpackets;
}
stats->rx_packets = packets;
stats->tx_packets = packets;
- stats->rx_dropped = drops;
- stats->rx_errors = drops;
stats->rx_bytes = bytes;
stats->tx_bytes = bytes;
return stats;
@@ -147,22 +137,16 @@ static const struct ethtool_ops loopback_ethtool_ops = {
static int loopback_dev_init(struct net_device *dev)
{
- struct pcpu_lstats __percpu *lstats;
-
- lstats = alloc_percpu(struct pcpu_lstats);
- if (!lstats)
+ dev->lstats = alloc_percpu(struct pcpu_lstats);
+ if (!dev->lstats)
return -ENOMEM;
- dev->ml_priv = (void __force *)lstats;
return 0;
}
static void loopback_dev_free(struct net_device *dev)
{
- struct pcpu_lstats __percpu *lstats =
- (void __percpu __force *)dev->ml_priv;
-
- free_percpu(lstats);
+ free_percpu(dev->lstats);
free_netdev(dev);
}
diff --git a/drivers/net/lp486e.c b/drivers/net/lp486e.c
index 3df046a58b1d..3698824744cb 100644
--- a/drivers/net/lp486e.c
+++ b/drivers/net/lp486e.c
@@ -460,7 +460,7 @@ init_rx_bufs(struct net_device *dev, int num) {
}
lp->rbd_tail->next = rfd->rbd;
#endif
- return (i);
+ return i;
}
static inline void
diff --git a/drivers/net/mac8390.c b/drivers/net/mac8390.c
index 3832fa4961dd..f84f5e6ededb 100644
--- a/drivers/net/mac8390.c
+++ b/drivers/net/mac8390.c
@@ -562,19 +562,19 @@ static int __init mac8390_initdev(struct net_device *dev,
case ACCESS_16:
/* 16 bit card, register map is reversed */
- ei_status.reset_8390 = &mac8390_no_reset;
- ei_status.block_input = &slow_sane_block_input;
- ei_status.block_output = &slow_sane_block_output;
- ei_status.get_8390_hdr = &slow_sane_get_8390_hdr;
+ ei_status.reset_8390 = mac8390_no_reset;
+ ei_status.block_input = slow_sane_block_input;
+ ei_status.block_output = slow_sane_block_output;
+ ei_status.get_8390_hdr = slow_sane_get_8390_hdr;
ei_status.reg_offset = back4_offsets;
break;
case ACCESS_32:
/* 32 bit card, register map is reversed */
- ei_status.reset_8390 = &mac8390_no_reset;
- ei_status.block_input = &sane_block_input;
- ei_status.block_output = &sane_block_output;
- ei_status.get_8390_hdr = &sane_get_8390_hdr;
+ ei_status.reset_8390 = mac8390_no_reset;
+ ei_status.block_input = sane_block_input;
+ ei_status.block_output = sane_block_output;
+ ei_status.get_8390_hdr = sane_get_8390_hdr;
ei_status.reg_offset = back4_offsets;
access_bitmode = 1;
break;
@@ -586,19 +586,19 @@ static int __init mac8390_initdev(struct net_device *dev,
* but overwrite system memory when run at 32 bit.
* so we run them all at 16 bit.
*/
- ei_status.reset_8390 = &mac8390_no_reset;
- ei_status.block_input = &slow_sane_block_input;
- ei_status.block_output = &slow_sane_block_output;
- ei_status.get_8390_hdr = &slow_sane_get_8390_hdr;
+ ei_status.reset_8390 = mac8390_no_reset;
+ ei_status.block_input = slow_sane_block_input;
+ ei_status.block_output = slow_sane_block_output;
+ ei_status.get_8390_hdr = slow_sane_get_8390_hdr;
ei_status.reg_offset = back4_offsets;
break;
case MAC8390_CABLETRON:
/* 16 bit card, register map is short forward */
- ei_status.reset_8390 = &mac8390_no_reset;
- ei_status.block_input = &slow_sane_block_input;
- ei_status.block_output = &slow_sane_block_output;
- ei_status.get_8390_hdr = &slow_sane_get_8390_hdr;
+ ei_status.reset_8390 = mac8390_no_reset;
+ ei_status.block_input = slow_sane_block_input;
+ ei_status.block_output = slow_sane_block_output;
+ ei_status.get_8390_hdr = slow_sane_get_8390_hdr;
ei_status.reg_offset = fwrd2_offsets;
break;
@@ -606,19 +606,19 @@ static int __init mac8390_initdev(struct net_device *dev,
case MAC8390_KINETICS:
/* 16 bit memory, register map is forward */
/* dayna and similar */
- ei_status.reset_8390 = &mac8390_no_reset;
- ei_status.block_input = &dayna_block_input;
- ei_status.block_output = &dayna_block_output;
- ei_status.get_8390_hdr = &dayna_get_8390_hdr;
+ ei_status.reset_8390 = mac8390_no_reset;
+ ei_status.block_input = dayna_block_input;
+ ei_status.block_output = dayna_block_output;
+ ei_status.get_8390_hdr = dayna_get_8390_hdr;
ei_status.reg_offset = fwrd4_offsets;
break;
case MAC8390_INTERLAN:
/* 16 bit memory, register map is forward */
- ei_status.reset_8390 = &interlan_reset;
- ei_status.block_input = &slow_sane_block_input;
- ei_status.block_output = &slow_sane_block_output;
- ei_status.get_8390_hdr = &slow_sane_get_8390_hdr;
+ ei_status.reset_8390 = interlan_reset;
+ ei_status.block_input = slow_sane_block_input;
+ ei_status.block_output = slow_sane_block_output;
+ ei_status.get_8390_hdr = slow_sane_get_8390_hdr;
ei_status.reg_offset = fwrd4_offsets;
break;
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index ff2f158ab0b9..4297f6e8c4bc 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -407,7 +407,7 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag,
}
skb_reserve(skb, RX_OFFSET);
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
skb_put(skb, len);
for (frag = first_frag; ; frag = NEXT_RX(frag)) {
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 0ef0eb0db945..0fc9dc7f20db 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -788,6 +788,10 @@ static int macvlan_device_event(struct notifier_block *unused,
}
break;
case NETDEV_UNREGISTER:
+ /* twiddle thumbs on netns device moves */
+ if (dev->reg_state != NETREG_UNREGISTERING)
+ break;
+
list_for_each_entry_safe(vlan, next, &port->vlans, list)
vlan->dev->rtnl_link_ops->dellink(vlan->dev, NULL);
break;
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index 3b1c54a9c6ef..42567279843e 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -84,26 +84,45 @@ static const struct proto_ops macvtap_socket_ops;
static DEFINE_SPINLOCK(macvtap_lock);
/*
- * Choose the next free queue, for now there is only one
+ * get_slot: return a [unused/occupied] slot in vlan->taps[]:
+ * - if 'q' is NULL, return the first empty slot;
+ * - otherwise, return the slot this pointer occupies.
*/
+static int get_slot(struct macvlan_dev *vlan, struct macvtap_queue *q)
+{
+ int i;
+
+ for (i = 0; i < MAX_MACVTAP_QUEUES; i++) {
+ if (rcu_dereference(vlan->taps[i]) == q)
+ return i;
+ }
+
+ /* Should never happen */
+ BUG_ON(1);
+}
+
static int macvtap_set_queue(struct net_device *dev, struct file *file,
struct macvtap_queue *q)
{
struct macvlan_dev *vlan = netdev_priv(dev);
+ int index;
int err = -EBUSY;
spin_lock(&macvtap_lock);
- if (rcu_dereference(vlan->tap))
+ if (vlan->numvtaps == MAX_MACVTAP_QUEUES)
goto out;
err = 0;
+ index = get_slot(vlan, NULL);
rcu_assign_pointer(q->vlan, vlan);
- rcu_assign_pointer(vlan->tap, q);
+ rcu_assign_pointer(vlan->taps[index], q);
sock_hold(&q->sk);
q->file = file;
file->private_data = q;
+ vlan->numvtaps++;
+
out:
spin_unlock(&macvtap_lock);
return err;
@@ -124,9 +143,12 @@ static void macvtap_put_queue(struct macvtap_queue *q)
spin_lock(&macvtap_lock);
vlan = rcu_dereference(q->vlan);
if (vlan) {
- rcu_assign_pointer(vlan->tap, NULL);
+ int index = get_slot(vlan, q);
+
+ rcu_assign_pointer(vlan->taps[index], NULL);
rcu_assign_pointer(q->vlan, NULL);
sock_put(&q->sk);
+ --vlan->numvtaps;
}
spin_unlock(&macvtap_lock);
@@ -136,39 +158,82 @@ static void macvtap_put_queue(struct macvtap_queue *q)
}
/*
- * Since we only support one queue, just dereference the pointer.
+ * Select a queue based on the rxq of the device on which this packet
+ * arrived. If the incoming device is not mq, calculate a flow hash
+ * to select a queue. If all fails, find the first available queue.
+ * Cache vlan->numvtaps since it can become zero during the execution
+ * of this function.
*/
static struct macvtap_queue *macvtap_get_queue(struct net_device *dev,
struct sk_buff *skb)
{
struct macvlan_dev *vlan = netdev_priv(dev);
+ struct macvtap_queue *tap = NULL;
+ int numvtaps = vlan->numvtaps;
+ __u32 rxq;
+
+ if (!numvtaps)
+ goto out;
+
+ if (likely(skb_rx_queue_recorded(skb))) {
+ rxq = skb_get_rx_queue(skb);
+
+ while (unlikely(rxq >= numvtaps))
+ rxq -= numvtaps;
+
+ tap = rcu_dereference(vlan->taps[rxq]);
+ if (tap)
+ goto out;
+ }
+
+ /* Check if we can use flow to select a queue */
+ rxq = skb_get_rxhash(skb);
+ if (rxq) {
+ tap = rcu_dereference(vlan->taps[rxq % numvtaps]);
+ if (tap)
+ goto out;
+ }
- return rcu_dereference(vlan->tap);
+ /* Everything failed - find first available queue */
+ for (rxq = 0; rxq < MAX_MACVTAP_QUEUES; rxq++) {
+ tap = rcu_dereference(vlan->taps[rxq]);
+ if (tap)
+ break;
+ }
+
+out:
+ return tap;
}
/*
* The net_device is going away, give up the reference
- * that it holds on the queue (all the queues one day)
- * and safely set the pointer from the queues to NULL.
+ * that it holds on all queues and safely set the pointer
+ * from the queues to NULL.
*/
static void macvtap_del_queues(struct net_device *dev)
{
struct macvlan_dev *vlan = netdev_priv(dev);
- struct macvtap_queue *q;
+ struct macvtap_queue *q, *qlist[MAX_MACVTAP_QUEUES];
+ int i, j = 0;
+ /* macvtap_put_queue can free some slots, so go through all slots */
spin_lock(&macvtap_lock);
- q = rcu_dereference(vlan->tap);
- if (!q) {
- spin_unlock(&macvtap_lock);
- return;
+ for (i = 0; i < MAX_MACVTAP_QUEUES && vlan->numvtaps; i++) {
+ q = rcu_dereference(vlan->taps[i]);
+ if (q) {
+ qlist[j++] = q;
+ rcu_assign_pointer(vlan->taps[i], NULL);
+ rcu_assign_pointer(q->vlan, NULL);
+ vlan->numvtaps--;
+ }
}
-
- rcu_assign_pointer(vlan->tap, NULL);
- rcu_assign_pointer(q->vlan, NULL);
+ BUG_ON(vlan->numvtaps != 0);
spin_unlock(&macvtap_lock);
synchronize_rcu();
- sock_put(&q->sk);
+
+ for (--j; j >= 0; j--)
+ sock_put(&qlist[j]->sk);
}
/*
diff --git a/drivers/net/meth.c b/drivers/net/meth.c
index 42e3294671d7..60135aa55802 100644
--- a/drivers/net/meth.c
+++ b/drivers/net/meth.c
@@ -461,7 +461,7 @@ static int meth_tx_full(struct net_device *dev)
{
struct meth_private *priv = netdev_priv(dev);
- return (priv->tx_count >= TX_RING_ENTRIES - 1);
+ return priv->tx_count >= TX_RING_ENTRIES - 1;
}
static void meth_tx_cleanup(struct net_device* dev, unsigned long int_status)
diff --git a/drivers/net/mlx4/Makefile b/drivers/net/mlx4/Makefile
index 1fd068e1d930..d1aa45a15854 100644
--- a/drivers/net/mlx4/Makefile
+++ b/drivers/net/mlx4/Makefile
@@ -6,4 +6,4 @@ mlx4_core-y := alloc.o catas.o cmd.o cq.o eq.o fw.o icm.o intf.o main.o mcg.o \
obj-$(CONFIG_MLX4_EN) += mlx4_en.o
mlx4_en-y := en_main.o en_tx.o en_rx.o en_ethtool.o en_port.o en_cq.o \
- en_resources.o en_netdev.o
+ en_resources.o en_netdev.o en_selftest.o
diff --git a/drivers/net/mlx4/alloc.c b/drivers/net/mlx4/alloc.c
index 8c8515619b8e..8f4bf1f07c11 100644
--- a/drivers/net/mlx4/alloc.c
+++ b/drivers/net/mlx4/alloc.c
@@ -74,7 +74,7 @@ void mlx4_bitmap_free(struct mlx4_bitmap *bitmap, u32 obj)
u32 mlx4_bitmap_alloc_range(struct mlx4_bitmap *bitmap, int cnt, int align)
{
- u32 obj, i;
+ u32 obj;
if (likely(cnt == 1 && align == 1))
return mlx4_bitmap_alloc(bitmap);
@@ -91,8 +91,7 @@ u32 mlx4_bitmap_alloc_range(struct mlx4_bitmap *bitmap, int cnt, int align)
}
if (obj < bitmap->max) {
- for (i = 0; i < cnt; i++)
- set_bit(obj + i, bitmap->table);
+ bitmap_set(bitmap->table, obj, cnt);
if (obj == bitmap->last) {
bitmap->last = (obj + cnt);
if (bitmap->last >= bitmap->max)
@@ -109,13 +108,10 @@ u32 mlx4_bitmap_alloc_range(struct mlx4_bitmap *bitmap, int cnt, int align)
void mlx4_bitmap_free_range(struct mlx4_bitmap *bitmap, u32 obj, int cnt)
{
- u32 i;
-
obj &= bitmap->max + bitmap->reserved_top - 1;
spin_lock(&bitmap->lock);
- for (i = 0; i < cnt; i++)
- clear_bit(obj + i, bitmap->table);
+ bitmap_clear(bitmap->table, obj, cnt);
bitmap->last = min(bitmap->last, obj);
bitmap->top = (bitmap->top + bitmap->max + bitmap->reserved_top)
& bitmap->mask;
@@ -125,8 +121,6 @@ void mlx4_bitmap_free_range(struct mlx4_bitmap *bitmap, u32 obj, int cnt)
int mlx4_bitmap_init(struct mlx4_bitmap *bitmap, u32 num, u32 mask,
u32 reserved_bot, u32 reserved_top)
{
- int i;
-
/* num must be a power of 2 */
if (num != roundup_pow_of_two(num))
return -EINVAL;
@@ -142,8 +136,7 @@ int mlx4_bitmap_init(struct mlx4_bitmap *bitmap, u32 num, u32 mask,
if (!bitmap->table)
return -ENOMEM;
- for (i = 0; i < reserved_bot; ++i)
- set_bit(i, bitmap->table);
+ bitmap_set(bitmap->table, 0, reserved_bot);
return 0;
}
@@ -188,7 +181,7 @@ int mlx4_buf_alloc(struct mlx4_dev *dev, int size, int max_direct,
buf->nbufs = (size + PAGE_SIZE - 1) / PAGE_SIZE;
buf->npages = buf->nbufs;
buf->page_shift = PAGE_SHIFT;
- buf->page_list = kzalloc(buf->nbufs * sizeof *buf->page_list,
+ buf->page_list = kcalloc(buf->nbufs, sizeof(*buf->page_list),
GFP_KERNEL);
if (!buf->page_list)
return -ENOMEM;
diff --git a/drivers/net/mlx4/en_ethtool.c b/drivers/net/mlx4/en_ethtool.c
index b275238fe70d..056152b3ff58 100644
--- a/drivers/net/mlx4/en_ethtool.c
+++ b/drivers/net/mlx4/en_ethtool.c
@@ -39,21 +39,6 @@
#include "en_port.h"
-static void mlx4_en_update_lro_stats(struct mlx4_en_priv *priv)
-{
- int i;
-
- priv->port_stats.lro_aggregated = 0;
- priv->port_stats.lro_flushed = 0;
- priv->port_stats.lro_no_desc = 0;
-
- for (i = 0; i < priv->rx_ring_num; i++) {
- priv->port_stats.lro_aggregated += priv->rx_ring[i].lro.stats.aggregated;
- priv->port_stats.lro_flushed += priv->rx_ring[i].lro.stats.flushed;
- priv->port_stats.lro_no_desc += priv->rx_ring[i].lro.stats.no_desc;
- }
-}
-
static void
mlx4_en_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
{
@@ -112,7 +97,7 @@ static const char main_strings[][ETH_GSTRING_LEN] = {
"tx_heartbeat_errors", "tx_window_errors",
/* port statistics */
- "lro_aggregated", "lro_flushed", "lro_no_desc", "tso_packets",
+ "tso_packets",
"queue_stopped", "wake_queue", "tx_timeout", "rx_alloc_failed",
"rx_csum_good", "rx_csum_none", "tx_chksum_offload",
@@ -125,6 +110,14 @@ static const char main_strings[][ETH_GSTRING_LEN] = {
#define NUM_MAIN_STATS 21
#define NUM_ALL_STATS (NUM_MAIN_STATS + NUM_PORT_STATS + NUM_PKT_STATS + NUM_PERF_STATS)
+static const char mlx4_en_test_names[][ETH_GSTRING_LEN]= {
+ "Interupt Test",
+ "Link Test",
+ "Speed Test",
+ "Register Test",
+ "Loopback Test",
+};
+
static u32 mlx4_en_get_msglevel(struct net_device *dev)
{
return ((struct mlx4_en_priv *) netdev_priv(dev))->msg_enable;
@@ -146,10 +139,15 @@ static int mlx4_en_get_sset_count(struct net_device *dev, int sset)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
- if (sset != ETH_SS_STATS)
+ switch (sset) {
+ case ETH_SS_STATS:
+ return NUM_ALL_STATS +
+ (priv->tx_ring_num + priv->rx_ring_num) * 2;
+ case ETH_SS_TEST:
+ return MLX4_EN_NUM_SELF_TEST - !(priv->mdev->dev->caps.loopback_support) * 2;
+ default:
return -EOPNOTSUPP;
-
- return NUM_ALL_STATS + (priv->tx_ring_num + priv->rx_ring_num) * 2;
+ }
}
static void mlx4_en_get_ethtool_stats(struct net_device *dev,
@@ -161,8 +159,6 @@ static void mlx4_en_get_ethtool_stats(struct net_device *dev,
spin_lock_bh(&priv->stats_lock);
- mlx4_en_update_lro_stats(priv);
-
for (i = 0; i < NUM_MAIN_STATS; i++)
data[index++] = ((unsigned long *) &priv->stats)[i];
for (i = 0; i < NUM_PORT_STATS; i++)
@@ -181,6 +177,12 @@ static void mlx4_en_get_ethtool_stats(struct net_device *dev,
}
+static void mlx4_en_self_test(struct net_device *dev,
+ struct ethtool_test *etest, u64 *buf)
+{
+ mlx4_en_ex_selftest(dev, &etest->flags, buf);
+}
+
static void mlx4_en_get_strings(struct net_device *dev,
uint32_t stringset, uint8_t *data)
{
@@ -188,44 +190,76 @@ static void mlx4_en_get_strings(struct net_device *dev,
int index = 0;
int i;
- if (stringset != ETH_SS_STATS)
- return;
-
- /* Add main counters */
- for (i = 0; i < NUM_MAIN_STATS; i++)
- strcpy(data + (index++) * ETH_GSTRING_LEN, main_strings[i]);
- for (i = 0; i < NUM_PORT_STATS; i++)
- strcpy(data + (index++) * ETH_GSTRING_LEN,
+ switch (stringset) {
+ case ETH_SS_TEST:
+ for (i = 0; i < MLX4_EN_NUM_SELF_TEST - 2; i++)
+ strcpy(data + i * ETH_GSTRING_LEN, mlx4_en_test_names[i]);
+ if (priv->mdev->dev->caps.loopback_support)
+ for (; i < MLX4_EN_NUM_SELF_TEST; i++)
+ strcpy(data + i * ETH_GSTRING_LEN, mlx4_en_test_names[i]);
+ break;
+
+ case ETH_SS_STATS:
+ /* Add main counters */
+ for (i = 0; i < NUM_MAIN_STATS; i++)
+ strcpy(data + (index++) * ETH_GSTRING_LEN, main_strings[i]);
+ for (i = 0; i< NUM_PORT_STATS; i++)
+ strcpy(data + (index++) * ETH_GSTRING_LEN,
main_strings[i + NUM_MAIN_STATS]);
- for (i = 0; i < priv->tx_ring_num; i++) {
- sprintf(data + (index++) * ETH_GSTRING_LEN,
- "tx%d_packets", i);
- sprintf(data + (index++) * ETH_GSTRING_LEN,
- "tx%d_bytes", i);
- }
- for (i = 0; i < priv->rx_ring_num; i++) {
- sprintf(data + (index++) * ETH_GSTRING_LEN,
- "rx%d_packets", i);
- sprintf(data + (index++) * ETH_GSTRING_LEN,
- "rx%d_bytes", i);
- }
- for (i = 0; i < NUM_PKT_STATS; i++)
- strcpy(data + (index++) * ETH_GSTRING_LEN,
+ for (i = 0; i < priv->tx_ring_num; i++) {
+ sprintf(data + (index++) * ETH_GSTRING_LEN,
+ "tx%d_packets", i);
+ sprintf(data + (index++) * ETH_GSTRING_LEN,
+ "tx%d_bytes", i);
+ }
+ for (i = 0; i < priv->rx_ring_num; i++) {
+ sprintf(data + (index++) * ETH_GSTRING_LEN,
+ "rx%d_packets", i);
+ sprintf(data + (index++) * ETH_GSTRING_LEN,
+ "rx%d_bytes", i);
+ }
+ for (i = 0; i< NUM_PKT_STATS; i++)
+ strcpy(data + (index++) * ETH_GSTRING_LEN,
main_strings[i + NUM_MAIN_STATS + NUM_PORT_STATS]);
+ break;
+ }
}
static int mlx4_en_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ int trans_type;
+
cmd->autoneg = AUTONEG_DISABLE;
cmd->supported = SUPPORTED_10000baseT_Full;
- cmd->advertising = ADVERTISED_1000baseT_Full;
+ cmd->advertising = ADVERTISED_10000baseT_Full;
+
+ if (mlx4_en_QUERY_PORT(priv->mdev, priv->port))
+ return -ENOMEM;
+
+ trans_type = priv->port_state.transciver;
if (netif_carrier_ok(dev)) {
- cmd->speed = SPEED_10000;
+ cmd->speed = priv->port_state.link_speed;
cmd->duplex = DUPLEX_FULL;
} else {
cmd->speed = -1;
cmd->duplex = -1;
}
+
+ if (trans_type > 0 && trans_type <= 0xC) {
+ cmd->port = PORT_FIBRE;
+ cmd->transceiver = XCVR_EXTERNAL;
+ cmd->supported |= SUPPORTED_FIBRE;
+ cmd->advertising |= ADVERTISED_FIBRE;
+ } else if (trans_type == 0x80 || trans_type == 0) {
+ cmd->port = PORT_TP;
+ cmd->transceiver = XCVR_INTERNAL;
+ cmd->supported |= SUPPORTED_TP;
+ cmd->advertising |= ADVERTISED_TP;
+ } else {
+ cmd->port = -1;
+ cmd->transceiver = -1;
+ }
return 0;
}
@@ -343,8 +377,9 @@ static int mlx4_en_set_ringparam(struct net_device *dev,
tx_size = max_t(u32, tx_size, MLX4_EN_MIN_TX_SIZE);
tx_size = min_t(u32, tx_size, MLX4_EN_MAX_TX_SIZE);
- if (rx_size == priv->prof->rx_ring_size &&
- tx_size == priv->prof->tx_ring_size)
+ if (rx_size == (priv->port_up ? priv->rx_ring[0].actual_size :
+ priv->rx_ring[0].size) &&
+ tx_size == priv->tx_ring[0].size)
return 0;
mutex_lock(&mdev->state_lock);
@@ -378,49 +413,13 @@ static void mlx4_en_get_ringparam(struct net_device *dev,
struct ethtool_ringparam *param)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_en_dev *mdev = priv->mdev;
memset(param, 0, sizeof(*param));
param->rx_max_pending = MLX4_EN_MAX_RX_SIZE;
param->tx_max_pending = MLX4_EN_MAX_TX_SIZE;
- param->rx_pending = mdev->profile.prof[priv->port].rx_ring_size;
- param->tx_pending = mdev->profile.prof[priv->port].tx_ring_size;
-}
-
-static int mlx4_ethtool_op_set_flags(struct net_device *dev, u32 data)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_en_dev *mdev = priv->mdev;
- int rc = 0;
- int changed = 0;
-
- if (data & ~ETH_FLAG_LRO)
- return -EOPNOTSUPP;
-
- if (data & ETH_FLAG_LRO) {
- if (mdev->profile.num_lro == 0)
- return -EOPNOTSUPP;
- if (!(dev->features & NETIF_F_LRO))
- changed = 1;
- } else if (dev->features & NETIF_F_LRO) {
- changed = 1;
- }
-
- if (changed) {
- if (netif_running(dev)) {
- mutex_lock(&mdev->state_lock);
- mlx4_en_stop_port(dev);
- }
- dev->features ^= NETIF_F_LRO;
- if (netif_running(dev)) {
- rc = mlx4_en_start_port(dev);
- if (rc)
- en_err(priv, "Failed to restart port\n");
- mutex_unlock(&mdev->state_lock);
- }
- }
-
- return rc;
+ param->rx_pending = priv->port_up ?
+ priv->rx_ring[0].actual_size : priv->rx_ring[0].size;
+ param->tx_pending = priv->tx_ring[0].size;
}
const struct ethtool_ops mlx4_en_ethtool_ops = {
@@ -441,6 +440,7 @@ const struct ethtool_ops mlx4_en_ethtool_ops = {
.get_strings = mlx4_en_get_strings,
.get_sset_count = mlx4_en_get_sset_count,
.get_ethtool_stats = mlx4_en_get_ethtool_stats,
+ .self_test = mlx4_en_self_test,
.get_wol = mlx4_en_get_wol,
.get_msglevel = mlx4_en_get_msglevel,
.set_msglevel = mlx4_en_set_msglevel,
@@ -451,7 +451,6 @@ const struct ethtool_ops mlx4_en_ethtool_ops = {
.get_ringparam = mlx4_en_get_ringparam,
.set_ringparam = mlx4_en_set_ringparam,
.get_flags = ethtool_op_get_flags,
- .set_flags = mlx4_ethtool_op_set_flags,
};
diff --git a/drivers/net/mlx4/en_main.c b/drivers/net/mlx4/en_main.c
index 97934f1ec53a..143906417048 100644
--- a/drivers/net/mlx4/en_main.c
+++ b/drivers/net/mlx4/en_main.c
@@ -63,15 +63,12 @@ static const char mlx4_en_version[] =
*/
-/* Use a XOR rathern than Toeplitz hash function for RSS */
-MLX4_EN_PARM_INT(rss_xor, 0, "Use XOR hash function for RSS");
-
-/* RSS hash type mask - default to <saddr, daddr, sport, dport> */
-MLX4_EN_PARM_INT(rss_mask, 0xf, "RSS hash type bitmask");
-
-/* Number of LRO sessions per Rx ring (rounded up to a power of two) */
-MLX4_EN_PARM_INT(num_lro, MLX4_EN_MAX_LRO_DESCRIPTORS,
- "Number of LRO sessions per ring or disabled (0)");
+/* Enable RSS TCP traffic */
+MLX4_EN_PARM_INT(tcp_rss, 1,
+ "Enable RSS for incomming TCP traffic or disabled (0)");
+/* Enable RSS UDP traffic */
+MLX4_EN_PARM_INT(udp_rss, 1,
+ "Enable RSS for incomming UDP traffic or disabled (0)");
/* Priority pausing */
MLX4_EN_PARM_INT(pfctx, 0, "Priority based Flow Control policy on TX[7:0]."
@@ -107,9 +104,12 @@ static int mlx4_en_get_profile(struct mlx4_en_dev *mdev)
struct mlx4_en_profile *params = &mdev->profile;
int i;
- params->rss_xor = (rss_xor != 0);
- params->rss_mask = rss_mask & 0x1f;
- params->num_lro = min_t(int, num_lro , MLX4_EN_MAX_LRO_DESCRIPTORS);
+ params->tcp_rss = tcp_rss;
+ params->udp_rss = udp_rss;
+ if (params->udp_rss && !mdev->dev->caps.udp_rss) {
+ mlx4_warn(mdev, "UDP RSS is not supported on this device.\n");
+ params->udp_rss = 0;
+ }
for (i = 1; i <= MLX4_MAX_PORTS; i++) {
params->prof[i].rx_pause = 1;
params->prof[i].rx_ppp = pfcrx;
diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c
index a0d8a26f5a02..79478bd4211a 100644
--- a/drivers/net/mlx4/en_netdev.c
+++ b/drivers/net/mlx4/en_netdev.c
@@ -109,7 +109,7 @@ static void mlx4_en_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
mutex_unlock(&mdev->state_lock);
}
-static u64 mlx4_en_mac_to_u64(u8 *addr)
+u64 mlx4_en_mac_to_u64(u8 *addr)
{
u64 mac = 0;
int i;
@@ -513,6 +513,10 @@ static void mlx4_en_do_get_stats(struct work_struct *work)
queue_delayed_work(mdev->workqueue, &priv->stats_task, STATS_DELAY);
}
+ if (mdev->mac_removed[MLX4_MAX_PORTS + 1 - priv->port]) {
+ queue_work(mdev->workqueue, &priv->mac_task);
+ mdev->mac_removed[MLX4_MAX_PORTS + 1 - priv->port] = 0;
+ }
mutex_unlock(&mdev->state_lock);
}
@@ -528,10 +532,10 @@ static void mlx4_en_linkstate(struct work_struct *work)
* report to system log */
if (priv->last_link_state != linkstate) {
if (linkstate == MLX4_DEV_EVENT_PORT_DOWN) {
- en_dbg(LINK, priv, "Link Down\n");
+ en_info(priv, "Link Down\n");
netif_carrier_off(priv->dev);
} else {
- en_dbg(LINK, priv, "Link Up\n");
+ en_info(priv, "Link Up\n");
netif_carrier_on(priv->dev);
}
}
@@ -653,6 +657,7 @@ int mlx4_en_start_port(struct net_device *dev)
en_err(priv, "Failed setting port mac\n");
goto tx_err;
}
+ mdev->mac_removed[priv->port] = 0;
/* Init port */
en_dbg(HW, priv, "Initializing port\n");
@@ -704,12 +709,12 @@ void mlx4_en_stop_port(struct net_device *dev)
netif_tx_stop_all_queues(dev);
netif_tx_unlock_bh(dev);
- /* close port*/
+ /* Set port as not active */
priv->port_up = false;
- mlx4_CLOSE_PORT(mdev->dev, priv->port);
/* Unregister Mac address for the port */
mlx4_unregister_mac(mdev->dev, priv->port, priv->mac_index);
+ mdev->mac_removed[priv->port] = 1;
/* Free TX Rings */
for (i = 0; i < priv->tx_ring_num; i++) {
@@ -731,6 +736,9 @@ void mlx4_en_stop_port(struct net_device *dev)
msleep(1);
mlx4_en_deactivate_cq(priv, &priv->rx_cq[i]);
}
+
+ /* close port*/
+ mlx4_CLOSE_PORT(mdev->dev, priv->port);
}
static void mlx4_en_restart(struct work_struct *work)
@@ -1017,15 +1025,17 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
*/
dev->netdev_ops = &mlx4_netdev_ops;
dev->watchdog_timeo = MLX4_EN_WATCHDOG_TIMEOUT;
- dev->real_num_tx_queues = MLX4_EN_NUM_TX_RINGS;
+ netif_set_real_num_tx_queues(dev, priv->tx_ring_num);
+ netif_set_real_num_rx_queues(dev, priv->rx_ring_num);
SET_ETHTOOL_OPS(dev, &mlx4_en_ethtool_ops);
/* Set defualt MAC */
dev->addr_len = ETH_ALEN;
- for (i = 0; i < ETH_ALEN; i++)
- dev->dev_addr[ETH_ALEN - 1 - i] =
- (u8) (priv->mac >> (8 * i));
+ for (i = 0; i < ETH_ALEN; i++) {
+ dev->dev_addr[ETH_ALEN - 1 - i] = (u8) (priv->mac >> (8 * i));
+ dev->perm_addr[ETH_ALEN - 1 - i] = (u8) (priv->mac >> (8 * i));
+ }
/*
* Set driver features
@@ -1038,8 +1048,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
dev->features |= NETIF_F_HW_VLAN_TX |
NETIF_F_HW_VLAN_RX |
NETIF_F_HW_VLAN_FILTER;
- if (mdev->profile.num_lro)
- dev->features |= NETIF_F_LRO;
+ dev->features |= NETIF_F_GRO;
if (mdev->LSO_support) {
dev->features |= NETIF_F_TSO;
dev->features |= NETIF_F_TSO6;
diff --git a/drivers/net/mlx4/en_port.c b/drivers/net/mlx4/en_port.c
index a29abe845d2e..aa3ef2aee5bf 100644
--- a/drivers/net/mlx4/en_port.c
+++ b/drivers/net/mlx4/en_port.c
@@ -142,6 +142,38 @@ int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn,
return err;
}
+int mlx4_en_QUERY_PORT(struct mlx4_en_dev *mdev, u8 port)
+{
+ struct mlx4_en_query_port_context *qport_context;
+ struct mlx4_en_priv *priv = netdev_priv(mdev->pndev[port]);
+ struct mlx4_en_port_state *state = &priv->port_state;
+ struct mlx4_cmd_mailbox *mailbox;
+ int err;
+
+ mailbox = mlx4_alloc_cmd_mailbox(mdev->dev);
+ if (IS_ERR(mailbox))
+ return PTR_ERR(mailbox);
+ memset(mailbox->buf, 0, sizeof(*qport_context));
+ err = mlx4_cmd_box(mdev->dev, 0, mailbox->dma, port, 0,
+ MLX4_CMD_QUERY_PORT, MLX4_CMD_TIME_CLASS_B);
+ if (err)
+ goto out;
+ qport_context = mailbox->buf;
+
+ /* This command is always accessed from Ethtool context
+ * already synchronized, no need in locking */
+ state->link_state = !!(qport_context->link_up & MLX4_EN_LINK_UP_MASK);
+ if ((qport_context->link_speed & MLX4_EN_SPEED_MASK) ==
+ MLX4_EN_1G_SPEED)
+ state->link_speed = 1000;
+ else
+ state->link_speed = 10000;
+ state->transciver = qport_context->transceiver;
+
+out:
+ mlx4_free_cmd_mailbox(mdev->dev, mailbox);
+ return err;
+}
int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset)
{
diff --git a/drivers/net/mlx4/en_port.h b/drivers/net/mlx4/en_port.h
index e6477f12beb5..f6511aa2b7df 100644
--- a/drivers/net/mlx4/en_port.h
+++ b/drivers/net/mlx4/en_port.h
@@ -84,6 +84,20 @@ enum {
MLX4_MCAST_ENABLE = 2,
};
+struct mlx4_en_query_port_context {
+ u8 link_up;
+#define MLX4_EN_LINK_UP_MASK 0x80
+ u8 reserved;
+ __be16 mtu;
+ u8 reserved2;
+ u8 link_speed;
+#define MLX4_EN_SPEED_MASK 0x3
+#define MLX4_EN_1G_SPEED 0x2
+ u16 reserved3[5];
+ __be64 mac;
+ u8 transceiver;
+};
+
struct mlx4_en_stat_out_mbox {
/* Received frames with a length of 64 octets */
diff --git a/drivers/net/mlx4/en_rx.c b/drivers/net/mlx4/en_rx.c
index 8e2fcb7103c3..570f2508fb30 100644
--- a/drivers/net/mlx4/en_rx.c
+++ b/drivers/net/mlx4/en_rx.c
@@ -42,18 +42,6 @@
#include "mlx4_en.h"
-static int mlx4_en_get_frag_header(struct skb_frag_struct *frags, void **mac_hdr,
- void **ip_hdr, void **tcpudp_hdr,
- u64 *hdr_flags, void *priv)
-{
- *mac_hdr = page_address(frags->page) + frags->page_offset;
- *ip_hdr = *mac_hdr + ETH_HLEN;
- *tcpudp_hdr = (struct tcphdr *)(*ip_hdr + sizeof(struct iphdr));
- *hdr_flags = LRO_IPV4 | LRO_TCP;
-
- return 0;
-}
-
static int mlx4_en_alloc_frag(struct mlx4_en_priv *priv,
struct mlx4_en_rx_desc *rx_desc,
struct skb_frag_struct *skb_frags,
@@ -251,7 +239,6 @@ reduce_rings:
ring->prod--;
mlx4_en_free_rx_desc(priv, ring, ring->actual_size);
}
- ring->size_mask = ring->actual_size - 1;
}
return 0;
@@ -313,28 +300,8 @@ int mlx4_en_create_rx_ring(struct mlx4_en_priv *priv,
}
ring->buf = ring->wqres.buf.direct.buf;
- /* Configure lro mngr */
- memset(&ring->lro, 0, sizeof(struct net_lro_mgr));
- ring->lro.dev = priv->dev;
- ring->lro.features = LRO_F_NAPI;
- ring->lro.frag_align_pad = NET_IP_ALIGN;
- ring->lro.ip_summed = CHECKSUM_UNNECESSARY;
- ring->lro.ip_summed_aggr = CHECKSUM_UNNECESSARY;
- ring->lro.max_desc = mdev->profile.num_lro;
- ring->lro.max_aggr = MAX_SKB_FRAGS;
- ring->lro.lro_arr = kzalloc(mdev->profile.num_lro *
- sizeof(struct net_lro_desc),
- GFP_KERNEL);
- if (!ring->lro.lro_arr) {
- en_err(priv, "Failed to allocate lro array\n");
- goto err_map;
- }
- ring->lro.get_frag_header = mlx4_en_get_frag_header;
-
return 0;
-err_map:
- mlx4_en_unmap_buffer(&ring->wqres.buf);
err_hwq:
mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size);
err_ring:
@@ -389,6 +356,7 @@ int mlx4_en_activate_rx_rings(struct mlx4_en_priv *priv)
for (ring_ind = 0; ring_ind < priv->rx_ring_num; ring_ind++) {
ring = &priv->rx_ring[ring_ind];
+ ring->size_mask = ring->actual_size - 1;
mlx4_en_update_rx_prod_db(ring);
}
@@ -412,7 +380,6 @@ void mlx4_en_destroy_rx_ring(struct mlx4_en_priv *priv,
{
struct mlx4_en_dev *mdev = priv->mdev;
- kfree(ring->lro.lro_arr);
mlx4_en_unmap_buffer(&ring->wqres.buf);
mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size + TXBB_SIZE);
vfree(ring->rx_info);
@@ -459,7 +426,7 @@ static int mlx4_en_complete_rx_desc(struct mlx4_en_priv *priv,
goto fail;
/* Unmap buffer */
- pci_unmap_single(mdev->pdev, dma, skb_frags[nr].size,
+ pci_unmap_single(mdev->pdev, dma, skb_frags_rx[nr].size,
PCI_DMA_FROMDEVICE);
}
/* Adjust size of last fragment to match actual length */
@@ -541,6 +508,21 @@ static struct sk_buff *mlx4_en_rx_skb(struct mlx4_en_priv *priv,
return skb;
}
+static void validate_loopback(struct mlx4_en_priv *priv, struct sk_buff *skb)
+{
+ int i;
+ int offset = ETH_HLEN;
+
+ for (i = 0; i < MLX4_LOOPBACK_TEST_PAYLOAD; i++, offset++) {
+ if (*(skb->data + offset) != (unsigned char) (i & 0xff))
+ goto out_loopback;
+ }
+ /* Loopback found */
+ priv->loopback_ok = 1;
+
+out_loopback:
+ dev_kfree_skb_any(skb);
+}
int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int budget)
{
@@ -548,7 +530,6 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
struct mlx4_cqe *cqe;
struct mlx4_en_rx_ring *ring = &priv->rx_ring[cq->ring];
struct skb_frag_struct *skb_frags;
- struct skb_frag_struct lro_frags[MLX4_EN_MAX_RX_FRAGS];
struct mlx4_en_rx_desc *rx_desc;
struct sk_buff *skb;
int index;
@@ -608,37 +589,35 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
* - TCP/IP (v4)
* - without IP options
* - not an IP fragment */
- if (mlx4_en_can_lro(cqe->status) &&
- dev->features & NETIF_F_LRO) {
+ if (dev->features & NETIF_F_GRO) {
+ struct sk_buff *gro_skb = napi_get_frags(&cq->napi);
+ if (!gro_skb)
+ goto next;
nr = mlx4_en_complete_rx_desc(
priv, rx_desc,
- skb_frags, lro_frags,
+ skb_frags, skb_shinfo(gro_skb)->frags,
ring->page_alloc, length);
if (!nr)
goto next;
+ skb_shinfo(gro_skb)->nr_frags = nr;
+ gro_skb->len = length;
+ gro_skb->data_len = length;
+ gro_skb->truesize += length;
+ gro_skb->ip_summed = CHECKSUM_UNNECESSARY;
+
if (priv->vlgrp && (cqe->vlan_my_qpn &
- cpu_to_be32(MLX4_CQE_VLAN_PRESENT_MASK))) {
- lro_vlan_hwaccel_receive_frags(
- &ring->lro, lro_frags,
- length, length,
- priv->vlgrp,
- be16_to_cpu(cqe->sl_vid),
- NULL, 0);
- } else
- lro_receive_frags(&ring->lro,
- lro_frags,
- length,
- length,
- NULL, 0);
+ cpu_to_be32(MLX4_CQE_VLAN_PRESENT_MASK)))
+ vlan_gro_frags(&cq->napi, priv->vlgrp, be16_to_cpu(cqe->sl_vid));
+ else
+ napi_gro_frags(&cq->napi);
goto next;
}
/* LRO not possible, complete processing here */
ip_summed = CHECKSUM_UNNECESSARY;
- INC_PERF_COUNTER(priv->pstats.lro_misses);
} else {
ip_summed = CHECKSUM_NONE;
priv->port_stats.rx_chksum_none++;
@@ -655,6 +634,11 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
goto next;
}
+ if (unlikely(priv->validate_loopback)) {
+ validate_loopback(priv, skb);
+ goto next;
+ }
+
skb->ip_summed = ip_summed;
skb->protocol = eth_type_trans(skb, dev);
skb_record_rx_queue(skb, cq->ring);
@@ -674,14 +658,10 @@ next:
if (++polled == budget) {
/* We are here because we reached the NAPI budget -
* flush only pending LRO sessions */
- lro_flush_all(&ring->lro);
goto out;
}
}
- /* If CQ is empty flush all LRO sessions unconditionally */
- lro_flush_all(&ring->lro);
-
out:
AVG_PERF_COUNTER(priv->pstats.rx_coal_avg, polled);
mlx4_cq_set_ci(&cq->mcq);
@@ -816,7 +796,7 @@ static int mlx4_en_config_rss_qp(struct mlx4_en_priv *priv, int qpn,
qp->event = mlx4_en_sqp_event;
memset(context, 0, sizeof *context);
- mlx4_en_fill_qp_context(priv, ring->size, ring->stride, 0, 0,
+ mlx4_en_fill_qp_context(priv, ring->actual_size, ring->stride, 0, 0,
qpn, ring->cqn, context);
context->db_rec_addr = cpu_to_be64(ring->wqres.db.dma);
@@ -839,8 +819,7 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv)
struct mlx4_qp_context context;
struct mlx4_en_rss_context *rss_context;
void *ptr;
- int rss_xor = mdev->profile.rss_xor;
- u8 rss_mask = mdev->profile.rss_mask;
+ u8 rss_mask = 0x3f;
int i, qpn;
int err = 0;
int good_qps = 0;
@@ -886,9 +865,10 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv)
rss_context->base_qpn = cpu_to_be32(ilog2(priv->rx_ring_num) << 24 |
(rss_map->base_qpn));
rss_context->default_qpn = cpu_to_be32(rss_map->base_qpn);
- rss_context->hash_fn = rss_xor & 0x3;
- rss_context->flags = rss_mask << 2;
+ rss_context->flags = rss_mask;
+ if (priv->mdev->profile.udp_rss)
+ rss_context->base_qpn_udp = rss_context->default_qpn;
err = mlx4_qp_to_ready(mdev->dev, &priv->res.mtt, &context,
&rss_map->indir_qp, &rss_map->indir_state);
if (err)
diff --git a/drivers/net/mlx4/en_selftest.c b/drivers/net/mlx4/en_selftest.c
new file mode 100644
index 000000000000..9c91a92da705
--- /dev/null
+++ b/drivers/net/mlx4/en_selftest.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2007 Mellanox Technologies. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/ethtool.h>
+#include <linux/netdevice.h>
+#include <linux/delay.h>
+#include <linux/mlx4/driver.h>
+
+#include "mlx4_en.h"
+
+
+static int mlx4_en_test_registers(struct mlx4_en_priv *priv)
+{
+ return mlx4_cmd(priv->mdev->dev, 0, 0, 0, MLX4_CMD_HW_HEALTH_CHECK,
+ MLX4_CMD_TIME_CLASS_A);
+}
+
+static int mlx4_en_test_loopback_xmit(struct mlx4_en_priv *priv)
+{
+ struct sk_buff *skb;
+ struct ethhdr *ethh;
+ unsigned char *packet;
+ unsigned int packet_size = MLX4_LOOPBACK_TEST_PAYLOAD;
+ unsigned int i;
+ int err;
+
+
+ /* build the pkt before xmit */
+ skb = netdev_alloc_skb(priv->dev, MLX4_LOOPBACK_TEST_PAYLOAD + ETH_HLEN + NET_IP_ALIGN);
+ if (!skb) {
+ en_err(priv, "-LOOPBACK_TEST_XMIT- failed to create skb for xmit\n");
+ return -ENOMEM;
+ }
+ skb_reserve(skb, NET_IP_ALIGN);
+
+ ethh = (struct ethhdr *)skb_put(skb, sizeof(struct ethhdr));
+ packet = (unsigned char *)skb_put(skb, packet_size);
+ memcpy(ethh->h_dest, priv->dev->dev_addr, ETH_ALEN);
+ memset(ethh->h_source, 0, ETH_ALEN);
+ ethh->h_proto = htons(ETH_P_ARP);
+ skb_set_mac_header(skb, 0);
+ for (i = 0; i < packet_size; ++i) /* fill our packet */
+ packet[i] = (unsigned char)(i & 0xff);
+
+ /* xmit the pkt */
+ err = mlx4_en_xmit(skb, priv->dev);
+ return err;
+}
+
+static int mlx4_en_test_loopback(struct mlx4_en_priv *priv)
+{
+ u32 loopback_ok = 0;
+ int i;
+
+
+ priv->loopback_ok = 0;
+ priv->validate_loopback = 1;
+
+ /* xmit */
+ if (mlx4_en_test_loopback_xmit(priv)) {
+ en_err(priv, "Transmitting loopback packet failed\n");
+ goto mlx4_en_test_loopback_exit;
+ }
+
+ /* polling for result */
+ for (i = 0; i < MLX4_EN_LOOPBACK_RETRIES; ++i) {
+ msleep(MLX4_EN_LOOPBACK_TIMEOUT);
+ if (priv->loopback_ok) {
+ loopback_ok = 1;
+ break;
+ }
+ }
+ if (!loopback_ok)
+ en_err(priv, "Loopback packet didn't arrive\n");
+
+mlx4_en_test_loopback_exit:
+
+ priv->validate_loopback = 0;
+ return !loopback_ok;
+}
+
+
+static int mlx4_en_test_link(struct mlx4_en_priv *priv)
+{
+ if (mlx4_en_QUERY_PORT(priv->mdev, priv->port))
+ return -ENOMEM;
+ if (priv->port_state.link_state == 1)
+ return 0;
+ else
+ return 1;
+}
+
+static int mlx4_en_test_speed(struct mlx4_en_priv *priv)
+{
+
+ if (mlx4_en_QUERY_PORT(priv->mdev, priv->port))
+ return -ENOMEM;
+
+ /* The device currently only supports 10G speed */
+ if (priv->port_state.link_speed != SPEED_10000)
+ return priv->port_state.link_speed;
+ return 0;
+}
+
+
+void mlx4_en_ex_selftest(struct net_device *dev, u32 *flags, u64 *buf)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_dev *mdev = priv->mdev;
+ struct mlx4_en_tx_ring *tx_ring;
+ int i, carrier_ok;
+
+ memset(buf, 0, sizeof(u64) * MLX4_EN_NUM_SELF_TEST);
+
+ if (*flags & ETH_TEST_FL_OFFLINE) {
+ /* disable the interface */
+ carrier_ok = netif_carrier_ok(dev);
+
+ netif_carrier_off(dev);
+retry_tx:
+ /* Wait untill all tx queues are empty.
+ * there should not be any additional incoming traffic
+ * since we turned the carrier off */
+ msleep(200);
+ for (i = 0; i < priv->tx_ring_num && carrier_ok; i++) {
+ tx_ring = &priv->tx_ring[i];
+ if (tx_ring->prod != (tx_ring->cons + tx_ring->last_nr_txbb))
+ goto retry_tx;
+ }
+
+ if (priv->mdev->dev->caps.loopback_support){
+ buf[3] = mlx4_en_test_registers(priv);
+ buf[4] = mlx4_en_test_loopback(priv);
+ }
+
+ if (carrier_ok)
+ netif_carrier_on(dev);
+
+ }
+ buf[0] = mlx4_test_interrupts(mdev->dev);
+ buf[1] = mlx4_en_test_link(priv);
+ buf[2] = mlx4_en_test_speed(priv);
+
+ for (i = 0; i < MLX4_EN_NUM_SELF_TEST; i++) {
+ if (buf[i])
+ *flags |= ETH_TEST_FL_FAILED;
+ }
+}
diff --git a/drivers/net/mlx4/en_tx.c b/drivers/net/mlx4/en_tx.c
index 580968f304eb..a680cd4a5ab6 100644
--- a/drivers/net/mlx4/en_tx.c
+++ b/drivers/net/mlx4/en_tx.c
@@ -38,6 +38,7 @@
#include <linux/skbuff.h>
#include <linux/if_vlan.h>
#include <linux/vmalloc.h>
+#include <linux/tcp.h>
#include "mlx4_en.h"
@@ -582,7 +583,7 @@ u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb)
/* If we support per priority flow control and the packet contains
* a vlan tag, send the packet to the TX ring assigned to that priority
*/
- if (priv->prof->rx_ppp && priv->vlgrp && vlan_tx_tag_present(skb)) {
+ if (priv->prof->rx_ppp && vlan_tx_tag_present(skb)) {
vlan_tag = vlan_tx_tag_get(skb);
return MLX4_EN_NUM_TX_RINGS + (vlan_tag >> 13);
}
@@ -600,6 +601,9 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
struct mlx4_wqe_data_seg *data;
struct skb_frag_struct *frag;
struct mlx4_en_tx_info *tx_info;
+ struct ethhdr *ethh;
+ u64 mac;
+ u32 mac_l, mac_h;
int tx_ind = 0;
int nr_txbb;
int desc_size;
@@ -612,6 +616,9 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
int lso_header_size;
void *fragptr;
+ if (!priv->port_up)
+ goto tx_drop;
+
real_size = get_real_size(skb, dev, &lso_header_size);
if (unlikely(!real_size))
goto tx_drop;
@@ -627,7 +634,7 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
tx_ind = skb->queue_mapping;
ring = &priv->tx_ring[tx_ind];
- if (priv->vlgrp && vlan_tx_tag_present(skb))
+ if (vlan_tx_tag_present(skb))
vlan_tag = vlan_tx_tag_get(skb);
/* Check available TXBBs And 2K spare for prefetch */
@@ -676,6 +683,19 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
priv->port_stats.tx_chksum_offload++;
}
+ if (unlikely(priv->validate_loopback)) {
+ /* Copy dst mac address to wqe */
+ skb_reset_mac_header(skb);
+ ethh = eth_hdr(skb);
+ if (ethh && ethh->h_dest) {
+ mac = mlx4_en_mac_to_u64(ethh->h_dest);
+ mac_h = (u32) ((mac & 0xffff00000000ULL) >> 16);
+ mac_l = (u32) (mac & 0xffffffff);
+ tx_desc->ctrl.srcrb_flags |= cpu_to_be32(mac_h);
+ tx_desc->ctrl.imm = cpu_to_be32(mac_l);
+ }
+ }
+
/* Handle LSO (TSO) packets */
if (lso_header_size) {
/* Mark opcode as LSO */
diff --git a/drivers/net/mlx4/eq.c b/drivers/net/mlx4/eq.c
index 6d7b2bf210ce..552d0fce6f67 100644
--- a/drivers/net/mlx4/eq.c
+++ b/drivers/net/mlx4/eq.c
@@ -699,3 +699,47 @@ void mlx4_cleanup_eq_table(struct mlx4_dev *dev)
kfree(priv->eq_table.uar_map);
}
+
+/* A test that verifies that we can accept interrupts on all
+ * the irq vectors of the device.
+ * Interrupts are checked using the NOP command.
+ */
+int mlx4_test_interrupts(struct mlx4_dev *dev)
+{
+ struct mlx4_priv *priv = mlx4_priv(dev);
+ int i;
+ int err;
+
+ err = mlx4_NOP(dev);
+ /* When not in MSI_X, there is only one irq to check */
+ if (!(dev->flags & MLX4_FLAG_MSI_X))
+ return err;
+
+ /* A loop over all completion vectors, for each vector we will check
+ * whether it works by mapping command completions to that vector
+ * and performing a NOP command
+ */
+ for(i = 0; !err && (i < dev->caps.num_comp_vectors); ++i) {
+ /* Temporary use polling for command completions */
+ mlx4_cmd_use_polling(dev);
+
+ /* Map the new eq to handle all asyncronous events */
+ err = mlx4_MAP_EQ(dev, MLX4_ASYNC_EVENT_MASK, 0,
+ priv->eq_table.eq[i].eqn);
+ if (err) {
+ mlx4_warn(dev, "Failed mapping eq for interrupt test\n");
+ mlx4_cmd_use_events(dev);
+ break;
+ }
+
+ /* Go back to using events */
+ mlx4_cmd_use_events(dev);
+ err = mlx4_NOP(dev);
+ }
+
+ /* Return to default */
+ mlx4_MAP_EQ(dev, MLX4_ASYNC_EVENT_MASK, 0,
+ priv->eq_table.eq[dev->caps.num_comp_vectors].eqn);
+ return err;
+}
+EXPORT_SYMBOL(mlx4_test_interrupts);
diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c
index 04f42ae1eda0..b716e1a1b298 100644
--- a/drivers/net/mlx4/fw.c
+++ b/drivers/net/mlx4/fw.c
@@ -141,6 +141,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
struct mlx4_cmd_mailbox *mailbox;
u32 *outbox;
u8 field;
+ u32 field32;
u16 size;
u16 stat_rate;
int err;
@@ -178,6 +179,8 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
#define QUERY_DEV_CAP_MAX_GID_OFFSET 0x3b
#define QUERY_DEV_CAP_RATE_SUPPORT_OFFSET 0x3c
#define QUERY_DEV_CAP_MAX_PKEY_OFFSET 0x3f
+#define QUERY_DEV_CAP_UDP_RSS_OFFSET 0x42
+#define QUERY_DEV_CAP_ETH_UC_LOOPBACK_OFFSET 0x43
#define QUERY_DEV_CAP_FLAGS_OFFSET 0x44
#define QUERY_DEV_CAP_RSVD_UAR_OFFSET 0x48
#define QUERY_DEV_CAP_UAR_SZ_OFFSET 0x49
@@ -268,6 +271,10 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
dev_cap->max_msg_sz = 1 << (field & 0x1f);
MLX4_GET(stat_rate, outbox, QUERY_DEV_CAP_RATE_SUPPORT_OFFSET);
dev_cap->stat_rate_support = stat_rate;
+ MLX4_GET(field, outbox, QUERY_DEV_CAP_UDP_RSS_OFFSET);
+ dev_cap->udp_rss = field & 0x1;
+ MLX4_GET(field, outbox, QUERY_DEV_CAP_ETH_UC_LOOPBACK_OFFSET);
+ dev_cap->loopback_support = field & 0x1;
MLX4_GET(dev_cap->flags, outbox, QUERY_DEV_CAP_FLAGS_OFFSET);
MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_UAR_OFFSET);
dev_cap->reserved_uars = field >> 4;
@@ -365,6 +372,9 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
#define QUERY_PORT_MAX_MACVLAN_OFFSET 0x0a
#define QUERY_PORT_MAX_VL_OFFSET 0x0b
#define QUERY_PORT_MAC_OFFSET 0x10
+#define QUERY_PORT_TRANS_VENDOR_OFFSET 0x18
+#define QUERY_PORT_WAVELENGTH_OFFSET 0x1c
+#define QUERY_PORT_TRANS_CODE_OFFSET 0x20
for (i = 1; i <= dev_cap->num_ports; ++i) {
err = mlx4_cmd_box(dev, 0, mailbox->dma, i, 0, MLX4_CMD_QUERY_PORT,
@@ -388,6 +398,11 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
dev_cap->log_max_vlans[i] = field >> 4;
MLX4_GET(dev_cap->eth_mtu[i], outbox, QUERY_PORT_ETH_MTU_OFFSET);
MLX4_GET(dev_cap->def_mac[i], outbox, QUERY_PORT_MAC_OFFSET);
+ MLX4_GET(field32, outbox, QUERY_PORT_TRANS_VENDOR_OFFSET);
+ dev_cap->trans_type[i] = field32 >> 24;
+ dev_cap->vendor_oui[i] = field32 & 0xffffff;
+ MLX4_GET(dev_cap->wavelength[i], outbox, QUERY_PORT_WAVELENGTH_OFFSET);
+ MLX4_GET(dev_cap->trans_code[i], outbox, QUERY_PORT_TRANS_CODE_OFFSET);
}
}
diff --git a/drivers/net/mlx4/fw.h b/drivers/net/mlx4/fw.h
index 526d7f30c041..65cc72eb899d 100644
--- a/drivers/net/mlx4/fw.h
+++ b/drivers/net/mlx4/fw.h
@@ -73,7 +73,13 @@ struct mlx4_dev_cap {
int max_pkeys[MLX4_MAX_PORTS + 1];
u64 def_mac[MLX4_MAX_PORTS + 1];
u16 eth_mtu[MLX4_MAX_PORTS + 1];
+ int trans_type[MLX4_MAX_PORTS + 1];
+ int vendor_oui[MLX4_MAX_PORTS + 1];
+ u16 wavelength[MLX4_MAX_PORTS + 1];
+ u64 trans_code[MLX4_MAX_PORTS + 1];
u16 stat_rate_support;
+ int udp_rss;
+ int loopback_support;
u32 flags;
int reserved_uars;
int uar_size;
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
index 5102ab1ac561..569fa3df381f 100644
--- a/drivers/net/mlx4/main.c
+++ b/drivers/net/mlx4/main.c
@@ -184,6 +184,10 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
dev->caps.eth_mtu_cap[i] = dev_cap->eth_mtu[i];
dev->caps.def_mac[i] = dev_cap->def_mac[i];
dev->caps.supported_type[i] = dev_cap->supported_port_types[i];
+ dev->caps.trans_type[i] = dev_cap->trans_type[i];
+ dev->caps.vendor_oui[i] = dev_cap->vendor_oui[i];
+ dev->caps.wavelength[i] = dev_cap->wavelength[i];
+ dev->caps.trans_code[i] = dev_cap->trans_code[i];
}
dev->caps.num_uars = dev_cap->uar_size / PAGE_SIZE;
@@ -221,6 +225,8 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
dev->caps.bmme_flags = dev_cap->bmme_flags;
dev->caps.reserved_lkey = dev_cap->reserved_lkey;
dev->caps.stat_rate_support = dev_cap->stat_rate_support;
+ dev->caps.udp_rss = dev_cap->udp_rss;
+ dev->caps.loopback_support = dev_cap->loopback_support;
dev->caps.max_gso_sz = dev_cap->max_gso_sz;
dev->caps.log_num_macs = log_num_mac;
diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h
index 449210994ee9..1fc16ab7ad2f 100644
--- a/drivers/net/mlx4/mlx4_en.h
+++ b/drivers/net/mlx4/mlx4_en.h
@@ -38,19 +38,19 @@
#include <linux/list.h>
#include <linux/mutex.h>
#include <linux/netdevice.h>
-#include <linux/inet_lro.h>
#include <linux/mlx4/device.h>
#include <linux/mlx4/qp.h>
#include <linux/mlx4/cq.h>
#include <linux/mlx4/srq.h>
#include <linux/mlx4/doorbell.h>
+#include <linux/mlx4/cmd.h>
#include "en_port.h"
#define DRV_NAME "mlx4_en"
-#define DRV_VERSION "1.4.1.1"
-#define DRV_RELDATE "June 2009"
+#define DRV_VERSION "1.5.1.6"
+#define DRV_RELDATE "August 2010"
#define MLX4_EN_MSG_LEVEL (NETIF_MSG_LINK | NETIF_MSG_IFDOWN)
@@ -61,7 +61,6 @@
#define MLX4_EN_PAGE_SHIFT 12
#define MLX4_EN_PAGE_SIZE (1 << MLX4_EN_PAGE_SHIFT)
-#define MAX_TX_RINGS 16
#define MAX_RX_RINGS 16
#define TXBB_SIZE 64
#define HEADROOM (2048 / TXBB_SIZE + 1)
@@ -107,6 +106,7 @@ enum {
#define MLX4_EN_SMALL_PKT_SIZE 64
#define MLX4_EN_NUM_TX_RINGS 8
#define MLX4_EN_NUM_PPP_RINGS 8
+#define MAX_TX_RINGS (MLX4_EN_NUM_TX_RINGS + MLX4_EN_NUM_PPP_RINGS)
#define MLX4_EN_DEF_TX_RING_SIZE 512
#define MLX4_EN_DEF_RX_RING_SIZE 1024
@@ -139,10 +139,14 @@ enum {
#define SMALL_PACKET_SIZE (256 - NET_IP_ALIGN)
#define HEADER_COPY_SIZE (128 - NET_IP_ALIGN)
+#define MLX4_LOOPBACK_TEST_PAYLOAD (HEADER_COPY_SIZE - ETH_HLEN)
#define MLX4_EN_MIN_MTU 46
#define ETH_BCAST 0xffffffffffffULL
+#define MLX4_EN_LOOPBACK_RETRIES 5
+#define MLX4_EN_LOOPBACK_TIMEOUT 100
+
#ifdef MLX4_EN_PERF_STAT
/* Number of samples to 'average' */
#define AVG_SIZE 128
@@ -249,7 +253,6 @@ struct mlx4_en_rx_desc {
struct mlx4_en_rx_ring {
struct mlx4_hwq_resources wqres;
struct mlx4_en_rx_alloc page_alloc[MLX4_EN_MAX_RX_FRAGS];
- struct net_lro_mgr lro;
u32 size ; /* number of Rx descs*/
u32 actual_size;
u32 size_mask;
@@ -313,7 +316,8 @@ struct mlx4_en_port_profile {
struct mlx4_en_profile {
int rss_xor;
- int num_lro;
+ int tcp_rss;
+ int udp_rss;
u8 rss_mask;
u32 active_ports;
u32 small_pkt_int;
@@ -337,6 +341,7 @@ struct mlx4_en_dev {
struct mlx4_mr mr;
u32 priv_pdn;
spinlock_t uar_lock;
+ u8 mac_removed[MLX4_MAX_PORTS + 1];
};
@@ -355,6 +360,13 @@ struct mlx4_en_rss_context {
u8 hash_fn;
u8 flags;
__be32 rss_key[10];
+ __be32 base_qpn_udp;
+};
+
+struct mlx4_en_port_state {
+ int link_state;
+ int link_speed;
+ int transciver;
};
struct mlx4_en_pkt_stats {
@@ -365,9 +377,6 @@ struct mlx4_en_pkt_stats {
};
struct mlx4_en_port_stats {
- unsigned long lro_aggregated;
- unsigned long lro_flushed;
- unsigned long lro_no_desc;
unsigned long tso_packets;
unsigned long queue_stopped;
unsigned long wake_queue;
@@ -376,7 +385,7 @@ struct mlx4_en_port_stats {
unsigned long rx_chksum_good;
unsigned long rx_chksum_none;
unsigned long tx_chksum_offload;
-#define NUM_PORT_STATS 11
+#define NUM_PORT_STATS 8
};
struct mlx4_en_perf_stats {
@@ -405,6 +414,7 @@ struct mlx4_en_priv {
struct vlan_group *vlgrp;
struct net_device_stats stats;
struct net_device_stats ret_stats;
+ struct mlx4_en_port_state port_state;
spinlock_t stats_lock;
unsigned long last_moder_packets;
@@ -423,6 +433,8 @@ struct mlx4_en_priv {
u16 sample_interval;
u16 adaptive_rx_coal;
u32 msg_enable;
+ u32 loopback_ok;
+ u32 validate_loopback;
struct mlx4_hwq_resources res;
int link_state;
@@ -531,6 +543,11 @@ int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn,
u8 promisc);
int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset);
+int mlx4_en_QUERY_PORT(struct mlx4_en_dev *mdev, u8 port);
+
+#define MLX4_EN_NUM_SELF_TEST 5
+void mlx4_en_ex_selftest(struct net_device *dev, u32 *flags, u64 *buf);
+u64 mlx4_en_mac_to_u64(u8 *addr);
/*
* Globals
@@ -555,6 +572,8 @@ do { \
en_print(KERN_WARNING, priv, format, ##arg)
#define en_err(priv, format, arg...) \
en_print(KERN_ERR, priv, format, ##arg)
+#define en_info(priv, format, arg...) \
+ en_print(KERN_INFO, priv, format, ## arg)
#define mlx4_err(mdev, format, arg...) \
pr_err("%s %s: " format, DRV_NAME, \
diff --git a/drivers/net/mlx4/profile.c b/drivers/net/mlx4/profile.c
index 5caf0115fa5b..e749f82865fe 100644
--- a/drivers/net/mlx4/profile.c
+++ b/drivers/net/mlx4/profile.c
@@ -85,7 +85,7 @@ u64 mlx4_make_profile(struct mlx4_dev *dev,
struct mlx4_resource tmp;
int i, j;
- profile = kzalloc(MLX4_RES_NUM * sizeof *profile, GFP_KERNEL);
+ profile = kcalloc(MLX4_RES_NUM, sizeof(*profile), GFP_KERNEL);
if (!profile)
return -ENOMEM;
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index 2d488abcf62d..dd2b6a71c6d7 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -2901,7 +2901,8 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
mp->dev = dev;
set_params(mp, pd);
- dev->real_num_tx_queues = mp->txq_count;
+ netif_set_real_num_tx_queues(dev, mp->txq_count);
+ netif_set_real_num_rx_queues(dev, mp->rxq_count);
if (pd->phy_addr != MV643XX_ETH_PHY_NONE)
mp->phy = phy_scan(mp, pd->phy_addr);
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
index fb2c0927d3cc..8524cc40ec57 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/drivers/net/myri10ge/myri10ge.c
@@ -225,6 +225,7 @@ struct myri10ge_priv {
struct msix_entry *msix_vectors;
#ifdef CONFIG_MYRI10GE_DCA
int dca_enabled;
+ int relaxed_order;
#endif
u32 link_state;
unsigned int rdma_tags_available;
@@ -990,7 +991,7 @@ static int myri10ge_reset(struct myri10ge_priv *mgp)
* RX queues, so if we get an error, first retry using a
* single TX queue before giving up */
if (status != 0 && mgp->dev->real_num_tx_queues > 1) {
- mgp->dev->real_num_tx_queues = 1;
+ netif_set_real_num_tx_queues(mgp->dev, 1);
cmd.data0 = mgp->num_slices;
cmd.data1 = MXGEFW_SLICE_INTR_MODE_ONE_PER_SLICE;
status = myri10ge_send_cmd(mgp,
@@ -1074,10 +1075,28 @@ static int myri10ge_reset(struct myri10ge_priv *mgp)
}
#ifdef CONFIG_MYRI10GE_DCA
+static int myri10ge_toggle_relaxed(struct pci_dev *pdev, int on)
+{
+ int ret, cap, err;
+ u16 ctl;
+
+ cap = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+ if (!cap)
+ return 0;
+
+ err = pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl);
+ ret = (ctl & PCI_EXP_DEVCTL_RELAX_EN) >> 4;
+ if (ret != on) {
+ ctl &= ~PCI_EXP_DEVCTL_RELAX_EN;
+ ctl |= (on << 4);
+ pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl);
+ }
+ return ret;
+}
+
static void
myri10ge_write_dca(struct myri10ge_slice_state *ss, int cpu, int tag)
{
- ss->cpu = cpu;
ss->cached_dca_tag = tag;
put_be32(htonl(tag), ss->dca_tag);
}
@@ -1088,9 +1107,10 @@ static inline void myri10ge_update_dca(struct myri10ge_slice_state *ss)
int tag;
if (cpu != ss->cpu) {
- tag = dca_get_tag(cpu);
+ tag = dca3_get_tag(&ss->mgp->pdev->dev, cpu);
if (ss->cached_dca_tag != tag)
myri10ge_write_dca(ss, cpu, tag);
+ ss->cpu = cpu;
}
put_cpu();
}
@@ -1113,9 +1133,13 @@ static void myri10ge_setup_dca(struct myri10ge_priv *mgp)
"dca_add_requester() failed, err=%d\n", err);
return;
}
+ mgp->relaxed_order = myri10ge_toggle_relaxed(pdev, 0);
mgp->dca_enabled = 1;
- for (i = 0; i < mgp->num_slices; i++)
- myri10ge_write_dca(&mgp->ss[i], -1, 0);
+ for (i = 0; i < mgp->num_slices; i++) {
+ mgp->ss[i].cpu = -1;
+ mgp->ss[i].cached_dca_tag = -1;
+ myri10ge_update_dca(&mgp->ss[i]);
+ }
}
static void myri10ge_teardown_dca(struct myri10ge_priv *mgp)
@@ -1126,6 +1150,8 @@ static void myri10ge_teardown_dca(struct myri10ge_priv *mgp)
if (!mgp->dca_enabled)
return;
mgp->dca_enabled = 0;
+ if (mgp->relaxed_order)
+ myri10ge_toggle_relaxed(pdev, 1);
err = dca_remove_requester(&pdev->dev);
}
@@ -1555,12 +1581,12 @@ static irqreturn_t myri10ge_intr(int irq, void *arg)
* valid since MSI-X irqs are not shared */
if ((mgp->dev->real_num_tx_queues == 1) && (ss != mgp->ss)) {
napi_schedule(&ss->napi);
- return (IRQ_HANDLED);
+ return IRQ_HANDLED;
}
/* make sure it is our IRQ, and that the DMA has finished */
if (unlikely(!stats->valid))
- return (IRQ_NONE);
+ return IRQ_NONE;
/* low bit indicates receives are present, so schedule
* napi poll handler */
@@ -1599,7 +1625,7 @@ static irqreturn_t myri10ge_intr(int irq, void *arg)
myri10ge_check_statblock(mgp);
put_be32(htonl(3), ss->irq_claim + 1);
- return (IRQ_HANDLED);
+ return IRQ_HANDLED;
}
static int
@@ -3753,8 +3779,8 @@ static void myri10ge_probe_slices(struct myri10ge_priv *mgp)
* slices. We give up on MSI-X if we can only get a single
* vector. */
- mgp->msix_vectors = kzalloc(mgp->num_slices *
- sizeof(*mgp->msix_vectors), GFP_KERNEL);
+ mgp->msix_vectors = kcalloc(mgp->num_slices, sizeof(*mgp->msix_vectors),
+ GFP_KERNEL);
if (mgp->msix_vectors == NULL)
goto disable_msix;
for (i = 0; i < mgp->num_slices; i++) {
@@ -3923,7 +3949,8 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
dev_err(&pdev->dev, "failed to alloc slice state\n");
goto abort_with_firmware;
}
- netdev->real_num_tx_queues = mgp->num_slices;
+ netif_set_real_num_tx_queues(netdev, mgp->num_slices);
+ netif_set_real_num_rx_queues(netdev, mgp->num_slices);
status = myri10ge_reset(mgp);
if (status != 0) {
dev_err(&pdev->dev, "failed reset\n");
diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c
index 617f898ba5f0..4846e131a04e 100644
--- a/drivers/net/myri_sbus.c
+++ b/drivers/net/myri_sbus.c
@@ -735,7 +735,7 @@ static int myri_header(struct sk_buff *skb, struct net_device *dev,
int i;
for (i = 0; i < dev->addr_len; i++)
eth->h_dest[i] = 0;
- return(dev->hard_header_len);
+ return dev->hard_header_len;
}
if (daddr) {
diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c
index a6033d48b5cc..2fd39630b1e5 100644
--- a/drivers/net/natsemi.c
+++ b/drivers/net/natsemi.c
@@ -1570,7 +1570,7 @@ static int netdev_open(struct net_device *dev)
init_timer(&np->timer);
np->timer.expires = round_jiffies(jiffies + NATSEMI_TIMER_FREQ);
np->timer.data = (unsigned long)dev;
- np->timer.function = &netdev_timer; /* timer handler */
+ np->timer.function = netdev_timer; /* timer handler */
add_timer(&np->timer);
return 0;
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index ca142c47b2e4..94255f09093d 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -678,7 +678,14 @@ static int netconsole_netdev_event(struct notifier_block *this,
strlcpy(nt->np.dev_name, dev->name, IFNAMSIZ);
break;
case NETDEV_UNREGISTER:
- netpoll_cleanup(&nt->np);
+ /*
+ * rtnl_lock already held
+ */
+ if (nt->np.dev) {
+ __netpoll_cleanup(&nt->np);
+ dev_put(nt->np.dev);
+ nt->np.dev = NULL;
+ }
/* Fall through */
case NETDEV_GOING_DOWN:
case NETDEV_BONDING_DESLAVE:
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h
index 6dca3574e355..8e8a97839cb0 100644
--- a/drivers/net/netxen/netxen_nic.h
+++ b/drivers/net/netxen/netxen_nic.h
@@ -175,7 +175,10 @@
#define MAX_NUM_CARDS 4
#define MAX_BUFFERS_PER_CMD 32
-#define TX_STOP_THRESH ((MAX_SKB_FRAGS >> 2) + 4)
+#define MAX_TSO_HEADER_DESC 2
+#define MGMT_CMD_DESC_RESV 4
+#define TX_STOP_THRESH ((MAX_SKB_FRAGS >> 2) + MAX_TSO_HEADER_DESC \
+ + MGMT_CMD_DESC_RESV)
#define NX_MAX_TX_TIMEOUTS 2
/*
@@ -1253,19 +1256,9 @@ struct netxen_adapter {
const struct firmware *fw;
};
-int netxen_niu_xg_init_port(struct netxen_adapter *adapter, int port);
-int netxen_niu_disable_xg_port(struct netxen_adapter *adapter);
-
int nx_fw_cmd_query_phy(struct netxen_adapter *adapter, u32 reg, u32 *val);
int nx_fw_cmd_set_phy(struct netxen_adapter *adapter, u32 reg, u32 val);
-/* Functions available from netxen_nic_hw.c */
-int netxen_nic_set_mtu_xgb(struct netxen_adapter *adapter, int new_mtu);
-int netxen_nic_set_mtu_gb(struct netxen_adapter *adapter, int new_mtu);
-
-int netxen_p2_nic_set_mac_addr(struct netxen_adapter *adapter, u8 *addr);
-int netxen_p3_nic_set_mac_addr(struct netxen_adapter *adapter, u8 *addr);
-
#define NXRD32(adapter, off) \
(adapter->crb_read(adapter, off))
#define NXWR32(adapter, off, val) \
@@ -1345,11 +1338,8 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid,
struct nx_host_rds_ring *rds_ring);
int netxen_process_cmd_ring(struct netxen_adapter *adapter);
int netxen_process_rcv_ring(struct nx_host_sds_ring *sds_ring, int max);
-void netxen_p2_nic_set_multi(struct net_device *netdev);
-void netxen_p3_nic_set_multi(struct net_device *netdev);
+
void netxen_p3_free_mac_list(struct netxen_adapter *adapter);
-int netxen_p2_nic_set_promisc(struct netxen_adapter *adapter, u32 mode);
-int netxen_p3_nic_set_promisc(struct netxen_adapter *adapter, u32);
int netxen_config_intr_coalesce(struct netxen_adapter *adapter);
int netxen_config_rss(struct netxen_adapter *adapter, int enable);
int netxen_config_ipaddr(struct netxen_adapter *adapter, u32 ip, int cmd);
@@ -1364,9 +1354,6 @@ int netxen_config_hw_lro(struct netxen_adapter *adapter, int enable);
int netxen_config_bridged_mode(struct netxen_adapter *adapter, int enable);
int netxen_send_lro_cleanup(struct netxen_adapter *adapter);
-int netxen_nic_set_mac(struct net_device *netdev, void *p);
-struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev);
-
void netxen_nic_update_cmd_producer(struct netxen_adapter *adapter,
struct nx_host_tx_ring *tx_ring);
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c
index 29d7b93d0493..37d3ebd65be8 100644
--- a/drivers/net/netxen/netxen_nic_hw.c
+++ b/drivers/net/netxen/netxen_nic_hw.c
@@ -319,6 +319,8 @@ static unsigned crb_hub_agt[64] =
#define NETXEN_PCIE_SEM_TIMEOUT 10000
+static int netxen_nic_set_mtu_xgb(struct netxen_adapter *adapter, int new_mtu);
+
int
netxen_pcie_sem_lock(struct netxen_adapter *adapter, int sem, u32 id_reg)
{
@@ -345,7 +347,7 @@ netxen_pcie_sem_unlock(struct netxen_adapter *adapter, int sem)
NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM_UNLOCK(sem)));
}
-int netxen_niu_xg_init_port(struct netxen_adapter *adapter, int port)
+static int netxen_niu_xg_init_port(struct netxen_adapter *adapter, int port)
{
if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
NXWR32(adapter, NETXEN_NIU_XGE_CONFIG_1+(0x10000*port), 0x1447);
@@ -356,7 +358,7 @@ int netxen_niu_xg_init_port(struct netxen_adapter *adapter, int port)
}
/* Disable an XG interface */
-int netxen_niu_disable_xg_port(struct netxen_adapter *adapter)
+static int netxen_niu_disable_xg_port(struct netxen_adapter *adapter)
{
__u32 mac_cfg;
u32 port = adapter->physical_port;
@@ -383,7 +385,7 @@ int netxen_niu_disable_xg_port(struct netxen_adapter *adapter)
#define MAC_LO(addr) \
((addr[5] << 16) | (addr[4] << 8) | (addr[3]))
-int netxen_p2_nic_set_promisc(struct netxen_adapter *adapter, u32 mode)
+static int netxen_p2_nic_set_promisc(struct netxen_adapter *adapter, u32 mode)
{
u32 mac_cfg;
u32 cnt = 0;
@@ -434,7 +436,7 @@ int netxen_p2_nic_set_promisc(struct netxen_adapter *adapter, u32 mode)
return 0;
}
-int netxen_p2_nic_set_mac_addr(struct netxen_adapter *adapter, u8 *addr)
+static int netxen_p2_nic_set_mac_addr(struct netxen_adapter *adapter, u8 *addr)
{
u32 mac_hi, mac_lo;
u32 reg_hi, reg_lo;
@@ -531,7 +533,7 @@ netxen_nic_set_mcast_addr(struct netxen_adapter *adapter,
return 0;
}
-void netxen_p2_nic_set_multi(struct net_device *netdev)
+static void netxen_p2_nic_set_multi(struct net_device *netdev)
{
struct netxen_adapter *adapter = netdev_priv(netdev);
struct netdev_hw_addr *ha;
@@ -598,8 +600,14 @@ netxen_send_cmd_descs(struct netxen_adapter *adapter,
if (nr_desc >= netxen_tx_avail(tx_ring)) {
netif_tx_stop_queue(tx_ring->txq);
- __netif_tx_unlock_bh(tx_ring->txq);
- return -EBUSY;
+ smp_mb();
+ if (netxen_tx_avail(tx_ring) > nr_desc) {
+ if (netxen_tx_avail(tx_ring) > TX_STOP_THRESH)
+ netif_tx_wake_queue(tx_ring->txq);
+ } else {
+ __netif_tx_unlock_bh(tx_ring->txq);
+ return -EBUSY;
+ }
}
do {
@@ -674,7 +682,7 @@ static int nx_p3_nic_add_mac(struct netxen_adapter *adapter,
cur->mac_addr, NETXEN_MAC_ADD);
}
-void netxen_p3_nic_set_multi(struct net_device *netdev)
+static void netxen_p3_nic_set_multi(struct net_device *netdev)
{
struct netxen_adapter *adapter = netdev_priv(netdev);
struct netdev_hw_addr *ha;
@@ -721,7 +729,7 @@ send_fw_cmd:
}
}
-int netxen_p3_nic_set_promisc(struct netxen_adapter *adapter, u32 mode)
+static int netxen_p3_nic_set_promisc(struct netxen_adapter *adapter, u32 mode)
{
nx_nic_req_t req;
u64 word;
@@ -754,7 +762,7 @@ void netxen_p3_free_mac_list(struct netxen_adapter *adapter)
}
}
-int netxen_p3_nic_set_mac_addr(struct netxen_adapter *adapter, u8 *addr)
+static int netxen_p3_nic_set_mac_addr(struct netxen_adapter *adapter, u8 *addr)
{
/* assuming caller has already copied new addr to netdev */
netxen_p3_nic_set_multi(adapter->netdev);
@@ -1816,14 +1824,14 @@ int netxen_nic_get_board_info(struct netxen_adapter *adapter)
if (netxen_rom_fast_read(adapter, offset, &board_type))
return -EIO;
- adapter->ahw.board_type = board_type;
-
if (board_type == NETXEN_BRDTYPE_P3_4_GB_MM) {
u32 gpio = NXRD32(adapter, NETXEN_ROMUSB_GLB_PAD_GPIO_I);
if ((gpio & 0x8000) == 0)
board_type = NETXEN_BRDTYPE_P3_10G_TP;
}
+ adapter->ahw.board_type = board_type;
+
switch (board_type) {
case NETXEN_BRDTYPE_P2_SB35_4G:
adapter->ahw.port_type = NETXEN_NIC_GBE;
@@ -1867,16 +1875,7 @@ int netxen_nic_get_board_info(struct netxen_adapter *adapter)
}
/* NIU access sections */
-
-int netxen_nic_set_mtu_gb(struct netxen_adapter *adapter, int new_mtu)
-{
- new_mtu += MTU_FUDGE_FACTOR;
- NXWR32(adapter, NETXEN_NIU_GB_MAX_FRAME_SIZE(adapter->physical_port),
- new_mtu);
- return 0;
-}
-
-int netxen_nic_set_mtu_xgb(struct netxen_adapter *adapter, int new_mtu)
+static int netxen_nic_set_mtu_xgb(struct netxen_adapter *adapter, int new_mtu)
{
new_mtu += MTU_FUDGE_FACTOR;
if (adapter->physical_port == 0)
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c
index b075a35b85d4..95fe552aa279 100644
--- a/drivers/net/netxen/netxen_nic_init.c
+++ b/drivers/net/netxen/netxen_nic_init.c
@@ -346,7 +346,7 @@ static u32 netxen_decode_crb_addr(u32 addr)
if (pci_base == NETXEN_ADDR_ERROR)
return pci_base;
else
- return (pci_base + offset);
+ return pci_base + offset;
}
#define NETXEN_MAX_ROM_WAIT_USEC 100
@@ -1763,14 +1763,10 @@ int netxen_process_cmd_ring(struct netxen_adapter *adapter)
smp_mb();
- if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) {
- __netif_tx_lock(tx_ring->txq, smp_processor_id());
- if (netxen_tx_avail(tx_ring) > TX_STOP_THRESH) {
+ if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev))
+ if (netxen_tx_avail(tx_ring) > TX_STOP_THRESH)
netif_wake_queue(netdev);
- adapter->tx_timeo_cnt = 0;
- }
- __netif_tx_unlock(tx_ring->txq);
- }
+ adapter->tx_timeo_cnt = 0;
}
/*
* If everything is freed up to consumer then check if the ring is full
@@ -1789,7 +1785,7 @@ int netxen_process_cmd_ring(struct netxen_adapter *adapter)
done = (sw_consumer == hw_consumer);
spin_unlock(&adapter->tx_clean_lock);
- return (done);
+ return done;
}
void
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index 73d314592230..50820beac3aa 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -95,6 +95,8 @@ static irqreturn_t netxen_msi_intr(int irq, void *data);
static irqreturn_t netxen_msix_intr(int irq, void *data);
static void netxen_config_indev_addr(struct net_device *dev, unsigned long);
+static struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev);
+static int netxen_nic_set_mac(struct net_device *netdev, void *p);
/* PCI Device ID Table */
#define ENTRY(device) \
@@ -125,11 +127,6 @@ netxen_nic_update_cmd_producer(struct netxen_adapter *adapter,
struct nx_host_tx_ring *tx_ring)
{
NXWRIO(adapter, tx_ring->crb_cmd_producer, tx_ring->producer);
-
- if (netxen_tx_avail(tx_ring) <= TX_STOP_THRESH) {
- netif_stop_queue(adapter->netdev);
- smp_mb();
- }
}
static uint32_t crb_cmd_consumer[4] = {
@@ -177,7 +174,7 @@ netxen_alloc_sds_rings(struct netxen_recv_context *recv_ctx, int count)
recv_ctx->sds_rings = kzalloc(size, GFP_KERNEL);
- return (recv_ctx->sds_rings == NULL);
+ return recv_ctx->sds_rings == NULL;
}
static void
@@ -460,7 +457,7 @@ netxen_read_mac_addr(struct netxen_adapter *adapter)
return 0;
}
-int netxen_nic_set_mac(struct net_device *netdev, void *p)
+static int netxen_nic_set_mac(struct net_device *netdev, void *p)
{
struct netxen_adapter *adapter = netdev_priv(netdev);
struct sockaddr *addr = p;
@@ -1209,7 +1206,7 @@ netxen_setup_netdev(struct netxen_adapter *adapter,
adapter->max_mc_count = 16;
netdev->netdev_ops = &netxen_netdev_ops;
- netdev->watchdog_timeo = 2*HZ;
+ netdev->watchdog_timeo = 5*HZ;
netxen_nic_change_mtu(netdev, netdev->mtu);
@@ -1254,6 +1251,28 @@ netxen_setup_netdev(struct netxen_adapter *adapter,
return 0;
}
+#ifdef CONFIG_PCIEAER
+static void netxen_mask_aer_correctable(struct netxen_adapter *adapter)
+{
+ struct pci_dev *pdev = adapter->pdev;
+ struct pci_dev *root = pdev->bus->self;
+ u32 aer_pos;
+
+ if (adapter->ahw.board_type != NETXEN_BRDTYPE_P3_4_GB_MM &&
+ adapter->ahw.board_type != NETXEN_BRDTYPE_P3_10G_TP)
+ return;
+
+ if (root->pcie_type != PCI_EXP_TYPE_ROOT_PORT)
+ return;
+
+ aer_pos = pci_find_ext_capability(root, PCI_EXT_CAP_ID_ERR);
+ if (!aer_pos)
+ return;
+
+ pci_write_config_dword(root, aer_pos + PCI_ERR_COR_MASK, 0xffff);
+}
+#endif
+
static int __devinit
netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
@@ -1322,6 +1341,10 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_out_iounmap;
}
+#ifdef CONFIG_PCIEAER
+ netxen_mask_aer_correctable(adapter);
+#endif
+
/* Mezz cards have PCI function 0,2,3 enabled */
switch (adapter->ahw.board_type) {
case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ:
@@ -1825,9 +1848,13 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
/* 4 fragments per cmd des */
no_of_desc = (frag_count + 3) >> 2;
- if (unlikely(no_of_desc + 2 > netxen_tx_avail(tx_ring))) {
+ if (unlikely(netxen_tx_avail(tx_ring) <= TX_STOP_THRESH)) {
netif_stop_queue(netdev);
- return NETDEV_TX_BUSY;
+ smp_mb();
+ if (netxen_tx_avail(tx_ring) > TX_STOP_THRESH)
+ netif_start_queue(netdev);
+ else
+ return NETDEV_TX_BUSY;
}
producer = tx_ring->producer;
@@ -2027,7 +2054,7 @@ request_reset:
clear_bit(__NX_RESETTING, &adapter->state);
}
-struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev)
+static struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev)
{
struct netxen_adapter *adapter = netdev_priv(netdev);
struct net_device_stats *stats = &netdev->stats;
diff --git a/drivers/net/niu.c b/drivers/net/niu.c
index fe6983af6918..781e368329f9 100644
--- a/drivers/net/niu.c
+++ b/drivers/net/niu.c
@@ -283,7 +283,7 @@ static int niu_enable_interrupts(struct niu *np, int on)
static u32 phy_encode(u32 type, int port)
{
- return (type << (port * 2));
+ return type << (port * 2);
}
static u32 phy_decode(u32 val, int port)
@@ -3043,8 +3043,7 @@ static int tcam_flush_all(struct niu *np)
static u64 hash_addr_regval(unsigned long index, unsigned long num_entries)
{
- return ((u64)index | (num_entries == 1 ?
- HASH_TBL_ADDR_AUTOINC : 0));
+ return (u64)index | (num_entries == 1 ? HASH_TBL_ADDR_AUTOINC : 0);
}
#if 0
@@ -3276,7 +3275,7 @@ static u16 tcam_get_index(struct niu *np, u16 idx)
/* One entry reserved for IP fragment rule */
if (idx >= (np->clas.tcam_sz - 1))
idx = 0;
- return (np->clas.tcam_top + ((idx+1) * np->parent->num_ports));
+ return np->clas.tcam_top + ((idx+1) * np->parent->num_ports);
}
static u16 tcam_get_size(struct niu *np)
@@ -3313,7 +3312,7 @@ static unsigned int niu_hash_rxaddr(struct rx_ring_info *rp, u64 a)
a >>= PAGE_SHIFT;
a ^= (a >> ilog2(MAX_RBR_RING_SIZE));
- return (a & (MAX_RBR_RING_SIZE - 1));
+ return a & (MAX_RBR_RING_SIZE - 1);
}
static struct page *niu_find_rxpage(struct rx_ring_info *rp, u64 addr,
@@ -3484,7 +3483,7 @@ static int niu_process_rx_pkt(struct napi_struct *napi, struct niu *np,
RCR_ENTRY_ERROR)))
skb->ip_summed = CHECKSUM_UNNECESSARY;
else
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
} else if (!(val & RCR_ENTRY_MULTI))
append_size = len - skb->len;
@@ -4502,9 +4501,10 @@ static int niu_alloc_channels(struct niu *np)
np->num_rx_rings = parent->rxchan_per_port[port];
np->num_tx_rings = parent->txchan_per_port[port];
- np->dev->real_num_tx_queues = np->num_tx_rings;
+ netif_set_real_num_rx_queues(np->dev, np->num_rx_rings);
+ netif_set_real_num_tx_queues(np->dev, np->num_tx_rings);
- np->rx_rings = kzalloc(np->num_rx_rings * sizeof(struct rx_ring_info),
+ np->rx_rings = kcalloc(np->num_rx_rings, sizeof(struct rx_ring_info),
GFP_KERNEL);
err = -ENOMEM;
if (!np->rx_rings)
@@ -4538,7 +4538,7 @@ static int niu_alloc_channels(struct niu *np)
return err;
}
- np->tx_rings = kzalloc(np->num_tx_rings * sizeof(struct tx_ring_info),
+ np->tx_rings = kcalloc(np->num_tx_rings, sizeof(struct tx_ring_info),
GFP_KERNEL);
err = -ENOMEM;
if (!np->tx_rings)
@@ -7090,24 +7090,20 @@ static int niu_get_hash_opts(struct niu *np, struct ethtool_rxnfc *nfc)
static void niu_get_ip4fs_from_tcam_key(struct niu_tcam_entry *tp,
struct ethtool_rx_flow_spec *fsp)
{
+ u32 tmp;
+ u16 prt;
- fsp->h_u.tcp_ip4_spec.ip4src = (tp->key[3] & TCAM_V4KEY3_SADDR) >>
- TCAM_V4KEY3_SADDR_SHIFT;
- fsp->h_u.tcp_ip4_spec.ip4dst = (tp->key[3] & TCAM_V4KEY3_DADDR) >>
- TCAM_V4KEY3_DADDR_SHIFT;
- fsp->m_u.tcp_ip4_spec.ip4src = (tp->key_mask[3] & TCAM_V4KEY3_SADDR) >>
- TCAM_V4KEY3_SADDR_SHIFT;
- fsp->m_u.tcp_ip4_spec.ip4dst = (tp->key_mask[3] & TCAM_V4KEY3_DADDR) >>
- TCAM_V4KEY3_DADDR_SHIFT;
-
- fsp->h_u.tcp_ip4_spec.ip4src =
- cpu_to_be32(fsp->h_u.tcp_ip4_spec.ip4src);
- fsp->m_u.tcp_ip4_spec.ip4src =
- cpu_to_be32(fsp->m_u.tcp_ip4_spec.ip4src);
- fsp->h_u.tcp_ip4_spec.ip4dst =
- cpu_to_be32(fsp->h_u.tcp_ip4_spec.ip4dst);
- fsp->m_u.tcp_ip4_spec.ip4dst =
- cpu_to_be32(fsp->m_u.tcp_ip4_spec.ip4dst);
+ tmp = (tp->key[3] & TCAM_V4KEY3_SADDR) >> TCAM_V4KEY3_SADDR_SHIFT;
+ fsp->h_u.tcp_ip4_spec.ip4src = cpu_to_be32(tmp);
+
+ tmp = (tp->key[3] & TCAM_V4KEY3_DADDR) >> TCAM_V4KEY3_DADDR_SHIFT;
+ fsp->h_u.tcp_ip4_spec.ip4dst = cpu_to_be32(tmp);
+
+ tmp = (tp->key_mask[3] & TCAM_V4KEY3_SADDR) >> TCAM_V4KEY3_SADDR_SHIFT;
+ fsp->m_u.tcp_ip4_spec.ip4src = cpu_to_be32(tmp);
+
+ tmp = (tp->key_mask[3] & TCAM_V4KEY3_DADDR) >> TCAM_V4KEY3_DADDR_SHIFT;
+ fsp->m_u.tcp_ip4_spec.ip4dst = cpu_to_be32(tmp);
fsp->h_u.tcp_ip4_spec.tos = (tp->key[2] & TCAM_V4KEY2_TOS) >>
TCAM_V4KEY2_TOS_SHIFT;
@@ -7118,54 +7114,40 @@ static void niu_get_ip4fs_from_tcam_key(struct niu_tcam_entry *tp,
case TCP_V4_FLOW:
case UDP_V4_FLOW:
case SCTP_V4_FLOW:
- fsp->h_u.tcp_ip4_spec.psrc =
- ((tp->key[2] & TCAM_V4KEY2_PORT_SPI) >>
- TCAM_V4KEY2_PORT_SPI_SHIFT) >> 16;
- fsp->h_u.tcp_ip4_spec.pdst =
- ((tp->key[2] & TCAM_V4KEY2_PORT_SPI) >>
- TCAM_V4KEY2_PORT_SPI_SHIFT) & 0xffff;
- fsp->m_u.tcp_ip4_spec.psrc =
- ((tp->key_mask[2] & TCAM_V4KEY2_PORT_SPI) >>
- TCAM_V4KEY2_PORT_SPI_SHIFT) >> 16;
- fsp->m_u.tcp_ip4_spec.pdst =
- ((tp->key_mask[2] & TCAM_V4KEY2_PORT_SPI) >>
- TCAM_V4KEY2_PORT_SPI_SHIFT) & 0xffff;
+ prt = ((tp->key[2] & TCAM_V4KEY2_PORT_SPI) >>
+ TCAM_V4KEY2_PORT_SPI_SHIFT) >> 16;
+ fsp->h_u.tcp_ip4_spec.psrc = cpu_to_be16(prt);
- fsp->h_u.tcp_ip4_spec.psrc =
- cpu_to_be16(fsp->h_u.tcp_ip4_spec.psrc);
- fsp->h_u.tcp_ip4_spec.pdst =
- cpu_to_be16(fsp->h_u.tcp_ip4_spec.pdst);
- fsp->m_u.tcp_ip4_spec.psrc =
- cpu_to_be16(fsp->m_u.tcp_ip4_spec.psrc);
- fsp->m_u.tcp_ip4_spec.pdst =
- cpu_to_be16(fsp->m_u.tcp_ip4_spec.pdst);
+ prt = ((tp->key[2] & TCAM_V4KEY2_PORT_SPI) >>
+ TCAM_V4KEY2_PORT_SPI_SHIFT) & 0xffff;
+ fsp->h_u.tcp_ip4_spec.pdst = cpu_to_be16(prt);
+
+ prt = ((tp->key_mask[2] & TCAM_V4KEY2_PORT_SPI) >>
+ TCAM_V4KEY2_PORT_SPI_SHIFT) >> 16;
+ fsp->m_u.tcp_ip4_spec.psrc = cpu_to_be16(prt);
+
+ prt = ((tp->key_mask[2] & TCAM_V4KEY2_PORT_SPI) >>
+ TCAM_V4KEY2_PORT_SPI_SHIFT) & 0xffff;
+ fsp->m_u.tcp_ip4_spec.pdst = cpu_to_be16(prt);
break;
case AH_V4_FLOW:
case ESP_V4_FLOW:
- fsp->h_u.ah_ip4_spec.spi =
- (tp->key[2] & TCAM_V4KEY2_PORT_SPI) >>
- TCAM_V4KEY2_PORT_SPI_SHIFT;
- fsp->m_u.ah_ip4_spec.spi =
- (tp->key_mask[2] & TCAM_V4KEY2_PORT_SPI) >>
+ tmp = (tp->key[2] & TCAM_V4KEY2_PORT_SPI) >>
TCAM_V4KEY2_PORT_SPI_SHIFT;
+ fsp->h_u.ah_ip4_spec.spi = cpu_to_be32(tmp);
- fsp->h_u.ah_ip4_spec.spi =
- cpu_to_be32(fsp->h_u.ah_ip4_spec.spi);
- fsp->m_u.ah_ip4_spec.spi =
- cpu_to_be32(fsp->m_u.ah_ip4_spec.spi);
+ tmp = (tp->key_mask[2] & TCAM_V4KEY2_PORT_SPI) >>
+ TCAM_V4KEY2_PORT_SPI_SHIFT;
+ fsp->m_u.ah_ip4_spec.spi = cpu_to_be32(tmp);
break;
case IP_USER_FLOW:
- fsp->h_u.usr_ip4_spec.l4_4_bytes =
- (tp->key[2] & TCAM_V4KEY2_PORT_SPI) >>
- TCAM_V4KEY2_PORT_SPI_SHIFT;
- fsp->m_u.usr_ip4_spec.l4_4_bytes =
- (tp->key_mask[2] & TCAM_V4KEY2_PORT_SPI) >>
+ tmp = (tp->key[2] & TCAM_V4KEY2_PORT_SPI) >>
TCAM_V4KEY2_PORT_SPI_SHIFT;
+ fsp->h_u.usr_ip4_spec.l4_4_bytes = cpu_to_be32(tmp);
- fsp->h_u.usr_ip4_spec.l4_4_bytes =
- cpu_to_be32(fsp->h_u.usr_ip4_spec.l4_4_bytes);
- fsp->m_u.usr_ip4_spec.l4_4_bytes =
- cpu_to_be32(fsp->m_u.usr_ip4_spec.l4_4_bytes);
+ tmp = (tp->key_mask[2] & TCAM_V4KEY2_PORT_SPI) >>
+ TCAM_V4KEY2_PORT_SPI_SHIFT;
+ fsp->m_u.usr_ip4_spec.l4_4_bytes = cpu_to_be32(tmp);
fsp->h_u.usr_ip4_spec.proto =
(tp->key[2] & TCAM_V4KEY2_PROTO) >>
@@ -7462,10 +7444,12 @@ static int niu_add_ethtool_tcam_entry(struct niu *np,
if (fsp->flow_type == IP_USER_FLOW) {
int i;
int add_usr_cls = 0;
- int ipv6 = 0;
struct ethtool_usrip4_spec *uspec = &fsp->h_u.usr_ip4_spec;
struct ethtool_usrip4_spec *umask = &fsp->m_u.usr_ip4_spec;
+ if (uspec->ip_ver != ETH_RX_NFC_IP4)
+ return -EINVAL;
+
niu_lock_parent(np, flags);
for (i = 0; i < NIU_L3_PROG_CLS; i++) {
@@ -7494,9 +7478,7 @@ static int niu_add_ethtool_tcam_entry(struct niu *np,
default:
break;
}
- if (uspec->ip_ver == ETH_RX_NFC_IP6)
- ipv6 = 1;
- ret = tcam_user_ip_class_set(np, class, ipv6,
+ ret = tcam_user_ip_class_set(np, class, 0,
uspec->proto,
uspec->tos,
umask->tos);
@@ -7553,16 +7535,7 @@ static int niu_add_ethtool_tcam_entry(struct niu *np,
ret = -EINVAL;
goto out;
case IP_USER_FLOW:
- if (fsp->h_u.usr_ip4_spec.ip_ver == ETH_RX_NFC_IP4) {
- niu_get_tcamkey_from_ip4fs(fsp, tp, l2_rdc_table,
- class);
- } else {
- /* Not yet implemented */
- netdev_info(np->dev, "niu%d: In %s(): usr flow for IPv6 not implemented\n",
- parent->index, __func__);
- ret = -EINVAL;
- goto out;
- }
+ niu_get_tcamkey_from_ip4fs(fsp, tp, l2_rdc_table, class);
break;
default:
netdev_info(np->dev, "niu%d: In %s(): Unknown flow type %d\n",
@@ -7805,11 +7778,11 @@ static int niu_get_sset_count(struct net_device *dev, int stringset)
if (stringset != ETH_SS_STATS)
return -EINVAL;
- return ((np->flags & NIU_FLAGS_XMAC ?
+ return (np->flags & NIU_FLAGS_XMAC ?
NUM_XMAC_STAT_KEYS :
NUM_BMAC_STAT_KEYS) +
(np->num_rx_rings * NUM_RXCHAN_STAT_KEYS) +
- (np->num_tx_rings * NUM_TXCHAN_STAT_KEYS));
+ (np->num_tx_rings * NUM_TXCHAN_STAT_KEYS);
}
static void niu_get_ethtool_stats(struct net_device *dev,
diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c
index 5a3488f76b38..84134c766f3a 100644
--- a/drivers/net/ns83820.c
+++ b/drivers/net/ns83820.c
@@ -772,7 +772,7 @@ static int ns83820_setup_rx(struct net_device *ndev)
phy_intr(ndev);
/* Okay, let it rip */
- spin_lock_irq(&dev->misc_lock);
+ spin_lock(&dev->misc_lock);
dev->IMR_cache |= ISR_PHY;
dev->IMR_cache |= ISR_RXRCMP;
//dev->IMR_cache |= ISR_RXERR;
@@ -923,7 +923,7 @@ static void rx_irq(struct net_device *ndev)
if ((extsts & 0x002a0000) && !(extsts & 0x00540000)) {
skb->ip_summed = CHECKSUM_UNNECESSARY;
} else {
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
}
skb->protocol = eth_type_trans(skb, ndev);
#ifdef NS83820_VLAN_ACCEL_SUPPORT
@@ -1246,7 +1246,6 @@ static int ns83820_get_settings(struct net_device *ndev,
{
struct ns83820 *dev = PRIV(ndev);
u32 cfg, tanar, tbicr;
- int have_optical = 0;
int fullduplex = 0;
/*
@@ -1267,25 +1266,25 @@ static int ns83820_get_settings(struct net_device *ndev,
tanar = readl(dev->base + TANAR);
tbicr = readl(dev->base + TBICR);
- if (dev->CFG_cache & CFG_TBI_EN) {
- /* we have an optical interface */
- have_optical = 1;
- fullduplex = (cfg & CFG_DUPSTS) ? 1 : 0;
-
- } else {
- /* We have copper */
- fullduplex = (cfg & CFG_DUPSTS) ? 1 : 0;
- }
+ fullduplex = (cfg & CFG_DUPSTS) ? 1 : 0;
cmd->supported = SUPPORTED_Autoneg;
- /* we have optical interface */
if (dev->CFG_cache & CFG_TBI_EN) {
+ /* we have optical interface */
cmd->supported |= SUPPORTED_1000baseT_Half |
SUPPORTED_1000baseT_Full |
SUPPORTED_FIBRE;
cmd->port = PORT_FIBRE;
- } /* TODO: else copper related support */
+ } else {
+ /* we have copper */
+ cmd->supported |= SUPPORTED_10baseT_Half |
+ SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Half |
+ SUPPORTED_1000baseT_Full |
+ SUPPORTED_MII;
+ cmd->port = PORT_MII;
+ }
cmd->duplex = fullduplex ? DUPLEX_FULL : DUPLEX_HALF;
switch (cfg / CFG_SPDSTS0 & 3) {
@@ -1299,7 +1298,8 @@ static int ns83820_get_settings(struct net_device *ndev,
cmd->speed = SPEED_10;
break;
}
- cmd->autoneg = (tbicr & TBICR_MR_AN_ENABLE) ? 1: 0;
+ cmd->autoneg = (tbicr & TBICR_MR_AN_ENABLE)
+ ? AUTONEG_ENABLE : AUTONEG_DISABLE;
return 0;
}
@@ -1405,6 +1405,13 @@ static const struct ethtool_ops ops = {
.get_link = ns83820_get_link
};
+static inline void ns83820_disable_interrupts(struct ns83820 *dev)
+{
+ writel(0, dev->base + IMR);
+ writel(0, dev->base + IER);
+ readl(dev->base + IER);
+}
+
/* this function is called in irq context from the ISR */
static void ns83820_mib_isr(struct ns83820 *dev)
{
@@ -1557,10 +1564,7 @@ static int ns83820_stop(struct net_device *ndev)
/* FIXME: protect against interrupt handler? */
del_timer_sync(&dev->tx_watchdog);
- /* disable interrupts */
- writel(0, dev->base + IMR);
- writel(0, dev->base + IER);
- readl(dev->base + IER);
+ ns83820_disable_interrupts(dev);
dev->rx_info.up = 0;
synchronize_irq(dev->pci_dev->irq);
@@ -2023,10 +2027,7 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev,
dev->tx_descs, (long)dev->tx_phy_descs,
dev->rx_info.descs, (long)dev->rx_info.phy_descs);
- /* disable interrupts */
- writel(0, dev->base + IMR);
- writel(0, dev->base + IER);
- readl(dev->base + IER);
+ ns83820_disable_interrupts(dev);
dev->IMR_cache = 0;
@@ -2250,9 +2251,7 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev,
return 0;
out_cleanup:
- writel(0, dev->base + IMR); /* paranoia */
- writel(0, dev->base + IER);
- readl(dev->base + IER);
+ ns83820_disable_interrupts(dev); /* paranoia */
out_free_irq:
rtnl_unlock();
free_irq(pci_dev->irq, ndev);
@@ -2277,9 +2276,7 @@ static void __devexit ns83820_remove_one(struct pci_dev *pci_dev)
if (!ndev) /* paranoia */
return;
- writel(0, dev->base + IMR); /* paranoia */
- writel(0, dev->base + IER);
- readl(dev->base + IER);
+ ns83820_disable_interrupts(dev); /* paranoia */
unregister_netdev(ndev);
free_irq(dev->pci_dev->irq, ndev);
diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c
index 8ab6ae0a6107..828e97cacdbf 100644
--- a/drivers/net/pasemi_mac.c
+++ b/drivers/net/pasemi_mac.c
@@ -808,7 +808,7 @@ static int pasemi_mac_clean_rx(struct pasemi_mac_rxring *rx,
skb->csum = (macrx & XCT_MACRX_CSUM_M) >>
XCT_MACRX_CSUM_S;
} else
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
packets++;
tot_bytes += len;
diff --git a/drivers/net/pasemi_mac_ethtool.c b/drivers/net/pasemi_mac_ethtool.c
index fefa79e34b95..4825959a0efe 100644
--- a/drivers/net/pasemi_mac_ethtool.c
+++ b/drivers/net/pasemi_mac_ethtool.c
@@ -90,21 +90,6 @@ pasemi_mac_ethtool_set_settings(struct net_device *netdev,
return phy_ethtool_sset(phydev, cmd);
}
-static void
-pasemi_mac_ethtool_get_drvinfo(struct net_device *netdev,
- struct ethtool_drvinfo *drvinfo)
-{
- struct pasemi_mac *mac;
- mac = netdev_priv(netdev);
-
- /* clear and fill out info */
- memset(drvinfo, 0, sizeof(struct ethtool_drvinfo));
- strncpy(drvinfo->driver, "pasemi_mac", 12);
- strcpy(drvinfo->version, "N/A");
- strcpy(drvinfo->fw_version, "N/A");
- strncpy(drvinfo->bus_info, pci_name(mac->pdev), 32);
-}
-
static u32
pasemi_mac_ethtool_get_msglevel(struct net_device *netdev)
{
@@ -164,7 +149,6 @@ static void pasemi_mac_get_strings(struct net_device *netdev, u32 stringset,
const struct ethtool_ops pasemi_mac_ethtool_ops = {
.get_settings = pasemi_mac_ethtool_get_settings,
.set_settings = pasemi_mac_ethtool_set_settings,
- .get_drvinfo = pasemi_mac_ethtool_get_drvinfo,
.get_msglevel = pasemi_mac_ethtool_get_msglevel,
.set_msglevel = pasemi_mac_ethtool_set_msglevel,
.get_link = ethtool_op_get_link,
diff --git a/drivers/net/pch_gbe/Makefile b/drivers/net/pch_gbe/Makefile
new file mode 100644
index 000000000000..31288d4ad248
--- /dev/null
+++ b/drivers/net/pch_gbe/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_PCH_GBE) += pch_gbe.o
+
+pch_gbe-y := pch_gbe_phy.o pch_gbe_ethtool.o pch_gbe_param.o
+pch_gbe-y += pch_gbe_api.o pch_gbe_main.o
diff --git a/drivers/net/pch_gbe/pch_gbe.h b/drivers/net/pch_gbe/pch_gbe.h
new file mode 100644
index 000000000000..a0c26a99520f
--- /dev/null
+++ b/drivers/net/pch_gbe/pch_gbe.h
@@ -0,0 +1,659 @@
+/*
+ * Copyright (C) 1999 - 2010 Intel Corporation.
+ * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ *
+ * This code was derived from the Intel e1000e Linux driver.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _PCH_GBE_H_
+#define _PCH_GBE_H_
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/mii.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/vmalloc.h>
+#include <net/ip.h>
+#include <net/tcp.h>
+#include <net/udp.h>
+
+/**
+ * pch_gbe_regs_mac_adr - Structure holding values of mac address registers
+ * @high Denotes the 1st to 4th byte from the initial of MAC address
+ * @low Denotes the 5th to 6th byte from the initial of MAC address
+ */
+struct pch_gbe_regs_mac_adr {
+ u32 high;
+ u32 low;
+};
+/**
+ * pch_udc_regs - Structure holding values of MAC registers
+ */
+struct pch_gbe_regs {
+ u32 INT_ST;
+ u32 INT_EN;
+ u32 MODE;
+ u32 RESET;
+ u32 TCPIP_ACC;
+ u32 EX_LIST;
+ u32 INT_ST_HOLD;
+ u32 PHY_INT_CTRL;
+ u32 MAC_RX_EN;
+ u32 RX_FCTRL;
+ u32 PAUSE_REQ;
+ u32 RX_MODE;
+ u32 TX_MODE;
+ u32 RX_FIFO_ST;
+ u32 TX_FIFO_ST;
+ u32 TX_FID;
+ u32 TX_RESULT;
+ u32 PAUSE_PKT1;
+ u32 PAUSE_PKT2;
+ u32 PAUSE_PKT3;
+ u32 PAUSE_PKT4;
+ u32 PAUSE_PKT5;
+ u32 reserve[2];
+ struct pch_gbe_regs_mac_adr mac_adr[16];
+ u32 ADDR_MASK;
+ u32 MIIM;
+ u32 reserve2;
+ u32 RGMII_ST;
+ u32 RGMII_CTRL;
+ u32 reserve3[3];
+ u32 DMA_CTRL;
+ u32 reserve4[3];
+ u32 RX_DSC_BASE;
+ u32 RX_DSC_SIZE;
+ u32 RX_DSC_HW_P;
+ u32 RX_DSC_HW_P_HLD;
+ u32 RX_DSC_SW_P;
+ u32 reserve5[3];
+ u32 TX_DSC_BASE;
+ u32 TX_DSC_SIZE;
+ u32 TX_DSC_HW_P;
+ u32 TX_DSC_HW_P_HLD;
+ u32 TX_DSC_SW_P;
+ u32 reserve6[3];
+ u32 RX_DMA_ST;
+ u32 TX_DMA_ST;
+ u32 reserve7[2];
+ u32 WOL_ST;
+ u32 WOL_CTRL;
+ u32 WOL_ADDR_MASK;
+};
+
+/* Interrupt Status */
+/* Interrupt Status Hold */
+/* Interrupt Enable */
+#define PCH_GBE_INT_RX_DMA_CMPLT 0x00000001 /* Receive DMA Transfer Complete */
+#define PCH_GBE_INT_RX_VALID 0x00000002 /* MAC Normal Receive Complete */
+#define PCH_GBE_INT_RX_FRAME_ERR 0x00000004 /* Receive frame error */
+#define PCH_GBE_INT_RX_FIFO_ERR 0x00000008 /* Receive FIFO Overflow */
+#define PCH_GBE_INT_RX_DMA_ERR 0x00000010 /* Receive DMA Transfer Error */
+#define PCH_GBE_INT_RX_DSC_EMP 0x00000020 /* Receive Descriptor Empty */
+#define PCH_GBE_INT_TX_CMPLT 0x00000100 /* MAC Transmission Complete */
+#define PCH_GBE_INT_TX_DMA_CMPLT 0x00000200 /* DMA Transfer Complete */
+#define PCH_GBE_INT_TX_FIFO_ERR 0x00000400 /* Transmission FIFO underflow. */
+#define PCH_GBE_INT_TX_DMA_ERR 0x00000800 /* Transmission DMA Error */
+#define PCH_GBE_INT_PAUSE_CMPLT 0x00001000 /* Pause Transmission complete */
+#define PCH_GBE_INT_MIIM_CMPLT 0x00010000 /* MIIM I/F Read completion */
+#define PCH_GBE_INT_PHY_INT 0x00100000 /* Interruption from PHY */
+#define PCH_GBE_INT_WOL_DET 0x01000000 /* Wake On LAN Event detection. */
+#define PCH_GBE_INT_TCPIP_ERR 0x10000000 /* TCP/IP Accelerator Error */
+
+/* Mode */
+#define PCH_GBE_MODE_MII_ETHER 0x00000000 /* GIGA Ethernet Mode [MII] */
+#define PCH_GBE_MODE_GMII_ETHER 0x80000000 /* GIGA Ethernet Mode [GMII] */
+#define PCH_GBE_MODE_HALF_DUPLEX 0x00000000 /* Duplex Mode [half duplex] */
+#define PCH_GBE_MODE_FULL_DUPLEX 0x40000000 /* Duplex Mode [full duplex] */
+#define PCH_GBE_MODE_FR_BST 0x04000000 /* Frame bursting is done */
+
+/* Reset */
+#define PCH_GBE_ALL_RST 0x80000000 /* All reset */
+#define PCH_GBE_TX_RST 0x40000000 /* TX MAC, TX FIFO, TX DMA reset */
+#define PCH_GBE_RX_RST 0x04000000 /* RX MAC, RX FIFO, RX DMA reset */
+
+/* TCP/IP Accelerator Control */
+#define PCH_GBE_EX_LIST_EN 0x00000008 /* External List Enable */
+#define PCH_GBE_RX_TCPIPACC_OFF 0x00000004 /* RX TCP/IP ACC Disabled */
+#define PCH_GBE_TX_TCPIPACC_EN 0x00000002 /* TX TCP/IP ACC Enable */
+#define PCH_GBE_RX_TCPIPACC_EN 0x00000001 /* RX TCP/IP ACC Enable */
+
+/* MAC RX Enable */
+#define PCH_GBE_MRE_MAC_RX_EN 0x00000001 /* MAC Receive Enable */
+
+/* RX Flow Control */
+#define PCH_GBE_FL_CTRL_EN 0x80000000 /* Pause packet is enabled */
+
+/* Pause Packet Request */
+#define PCH_GBE_PS_PKT_RQ 0x80000000 /* Pause packet Request */
+
+/* RX Mode */
+#define PCH_GBE_ADD_FIL_EN 0x80000000 /* Address Filtering Enable */
+/* Multicast Filtering Enable */
+#define PCH_GBE_MLT_FIL_EN 0x40000000
+/* Receive Almost Empty Threshold */
+#define PCH_GBE_RH_ALM_EMP_4 0x00000000 /* 4 words */
+#define PCH_GBE_RH_ALM_EMP_8 0x00004000 /* 8 words */
+#define PCH_GBE_RH_ALM_EMP_16 0x00008000 /* 16 words */
+#define PCH_GBE_RH_ALM_EMP_32 0x0000C000 /* 32 words */
+/* Receive Almost Full Threshold */
+#define PCH_GBE_RH_ALM_FULL_4 0x00000000 /* 4 words */
+#define PCH_GBE_RH_ALM_FULL_8 0x00001000 /* 8 words */
+#define PCH_GBE_RH_ALM_FULL_16 0x00002000 /* 16 words */
+#define PCH_GBE_RH_ALM_FULL_32 0x00003000 /* 32 words */
+/* RX FIFO Read Triger Threshold */
+#define PCH_GBE_RH_RD_TRG_4 0x00000000 /* 4 words */
+#define PCH_GBE_RH_RD_TRG_8 0x00000200 /* 8 words */
+#define PCH_GBE_RH_RD_TRG_16 0x00000400 /* 16 words */
+#define PCH_GBE_RH_RD_TRG_32 0x00000600 /* 32 words */
+#define PCH_GBE_RH_RD_TRG_64 0x00000800 /* 64 words */
+#define PCH_GBE_RH_RD_TRG_128 0x00000A00 /* 128 words */
+#define PCH_GBE_RH_RD_TRG_256 0x00000C00 /* 256 words */
+#define PCH_GBE_RH_RD_TRG_512 0x00000E00 /* 512 words */
+
+/* Receive Descriptor bit definitions */
+#define PCH_GBE_RXD_ACC_STAT_BCAST 0x00000400
+#define PCH_GBE_RXD_ACC_STAT_MCAST 0x00000200
+#define PCH_GBE_RXD_ACC_STAT_UCAST 0x00000100
+#define PCH_GBE_RXD_ACC_STAT_TCPIPOK 0x000000C0
+#define PCH_GBE_RXD_ACC_STAT_IPOK 0x00000080
+#define PCH_GBE_RXD_ACC_STAT_TCPOK 0x00000040
+#define PCH_GBE_RXD_ACC_STAT_IP6ERR 0x00000020
+#define PCH_GBE_RXD_ACC_STAT_OFLIST 0x00000010
+#define PCH_GBE_RXD_ACC_STAT_TYPEIP 0x00000008
+#define PCH_GBE_RXD_ACC_STAT_MACL 0x00000004
+#define PCH_GBE_RXD_ACC_STAT_PPPOE 0x00000002
+#define PCH_GBE_RXD_ACC_STAT_VTAGT 0x00000001
+#define PCH_GBE_RXD_GMAC_STAT_PAUSE 0x0200
+#define PCH_GBE_RXD_GMAC_STAT_MARBR 0x0100
+#define PCH_GBE_RXD_GMAC_STAT_MARMLT 0x0080
+#define PCH_GBE_RXD_GMAC_STAT_MARIND 0x0040
+#define PCH_GBE_RXD_GMAC_STAT_MARNOTMT 0x0020
+#define PCH_GBE_RXD_GMAC_STAT_TLONG 0x0010
+#define PCH_GBE_RXD_GMAC_STAT_TSHRT 0x0008
+#define PCH_GBE_RXD_GMAC_STAT_NOTOCTAL 0x0004
+#define PCH_GBE_RXD_GMAC_STAT_NBLERR 0x0002
+#define PCH_GBE_RXD_GMAC_STAT_CRCERR 0x0001
+
+/* Transmit Descriptor bit definitions */
+#define PCH_GBE_TXD_CTRL_TCPIP_ACC_OFF 0x0008
+#define PCH_GBE_TXD_CTRL_ITAG 0x0004
+#define PCH_GBE_TXD_CTRL_ICRC 0x0002
+#define PCH_GBE_TXD_CTRL_APAD 0x0001
+#define PCH_GBE_TXD_WORDS_SHIFT 2
+#define PCH_GBE_TXD_GMAC_STAT_CMPLT 0x2000
+#define PCH_GBE_TXD_GMAC_STAT_ABT 0x1000
+#define PCH_GBE_TXD_GMAC_STAT_EXCOL 0x0800
+#define PCH_GBE_TXD_GMAC_STAT_SNGCOL 0x0400
+#define PCH_GBE_TXD_GMAC_STAT_MLTCOL 0x0200
+#define PCH_GBE_TXD_GMAC_STAT_CRSER 0x0100
+#define PCH_GBE_TXD_GMAC_STAT_TLNG 0x0080
+#define PCH_GBE_TXD_GMAC_STAT_TSHRT 0x0040
+#define PCH_GBE_TXD_GMAC_STAT_LTCOL 0x0020
+#define PCH_GBE_TXD_GMAC_STAT_TFUNDFLW 0x0010
+#define PCH_GBE_TXD_GMAC_STAT_RTYCNT_MASK 0x000F
+
+/* TX Mode */
+#define PCH_GBE_TM_NO_RTRY 0x80000000 /* No Retransmission */
+#define PCH_GBE_TM_LONG_PKT 0x40000000 /* Long Packt TX Enable */
+#define PCH_GBE_TM_ST_AND_FD 0x20000000 /* Stare and Forward */
+#define PCH_GBE_TM_SHORT_PKT 0x10000000 /* Short Packet TX Enable */
+#define PCH_GBE_TM_LTCOL_RETX 0x08000000 /* Retransmission at Late Collision */
+/* Frame Start Threshold */
+#define PCH_GBE_TM_TH_TX_STRT_4 0x00000000 /* 4 words */
+#define PCH_GBE_TM_TH_TX_STRT_8 0x00004000 /* 8 words */
+#define PCH_GBE_TM_TH_TX_STRT_16 0x00008000 /* 16 words */
+#define PCH_GBE_TM_TH_TX_STRT_32 0x0000C000 /* 32 words */
+/* Transmit Almost Empty Threshold */
+#define PCH_GBE_TM_TH_ALM_EMP_4 0x00000000 /* 4 words */
+#define PCH_GBE_TM_TH_ALM_EMP_8 0x00000800 /* 8 words */
+#define PCH_GBE_TM_TH_ALM_EMP_16 0x00001000 /* 16 words */
+#define PCH_GBE_TM_TH_ALM_EMP_32 0x00001800 /* 32 words */
+#define PCH_GBE_TM_TH_ALM_EMP_64 0x00002000 /* 64 words */
+#define PCH_GBE_TM_TH_ALM_EMP_128 0x00002800 /* 128 words */
+#define PCH_GBE_TM_TH_ALM_EMP_256 0x00003000 /* 256 words */
+#define PCH_GBE_TM_TH_ALM_EMP_512 0x00003800 /* 512 words */
+/* Transmit Almost Full Threshold */
+#define PCH_GBE_TM_TH_ALM_FULL_4 0x00000000 /* 4 words */
+#define PCH_GBE_TM_TH_ALM_FULL_8 0x00000200 /* 8 words */
+#define PCH_GBE_TM_TH_ALM_FULL_16 0x00000400 /* 16 words */
+#define PCH_GBE_TM_TH_ALM_FULL_32 0x00000600 /* 32 words */
+
+/* RX FIFO Status */
+#define PCH_GBE_RF_ALM_FULL 0x80000000 /* RX FIFO is almost full. */
+#define PCH_GBE_RF_ALM_EMP 0x40000000 /* RX FIFO is almost empty. */
+#define PCH_GBE_RF_RD_TRG 0x20000000 /* Become more than RH_RD_TRG. */
+#define PCH_GBE_RF_STRWD 0x1FFE0000 /* The word count of RX FIFO. */
+#define PCH_GBE_RF_RCVING 0x00010000 /* Stored in RX FIFO. */
+
+/* MAC Address Mask */
+#define PCH_GBE_BUSY 0x80000000
+
+/* MIIM */
+#define PCH_GBE_MIIM_OPER_WRITE 0x04000000
+#define PCH_GBE_MIIM_OPER_READ 0x00000000
+#define PCH_GBE_MIIM_OPER_READY 0x04000000
+#define PCH_GBE_MIIM_PHY_ADDR_SHIFT 21
+#define PCH_GBE_MIIM_REG_ADDR_SHIFT 16
+
+/* RGMII Status */
+#define PCH_GBE_LINK_UP 0x80000008
+#define PCH_GBE_RXC_SPEED_MSK 0x00000006
+#define PCH_GBE_RXC_SPEED_2_5M 0x00000000 /* 2.5MHz */
+#define PCH_GBE_RXC_SPEED_25M 0x00000002 /* 25MHz */
+#define PCH_GBE_RXC_SPEED_125M 0x00000004 /* 100MHz */
+#define PCH_GBE_DUPLEX_FULL 0x00000001
+
+/* RGMII Control */
+#define PCH_GBE_CRS_SEL 0x00000010
+#define PCH_GBE_RGMII_RATE_125M 0x00000000
+#define PCH_GBE_RGMII_RATE_25M 0x00000008
+#define PCH_GBE_RGMII_RATE_2_5M 0x0000000C
+#define PCH_GBE_RGMII_MODE_GMII 0x00000000
+#define PCH_GBE_RGMII_MODE_RGMII 0x00000002
+#define PCH_GBE_CHIP_TYPE_EXTERNAL 0x00000000
+#define PCH_GBE_CHIP_TYPE_INTERNAL 0x00000001
+
+/* DMA Control */
+#define PCH_GBE_RX_DMA_EN 0x00000002 /* Enables Receive DMA */
+#define PCH_GBE_TX_DMA_EN 0x00000001 /* Enables Transmission DMA */
+
+/* Wake On LAN Status */
+#define PCH_GBE_WLS_BR 0x00000008 /* Broadcas Address */
+#define PCH_GBE_WLS_MLT 0x00000004 /* Multicast Address */
+
+/* The Frame registered in Address Recognizer */
+#define PCH_GBE_WLS_IND 0x00000002
+#define PCH_GBE_WLS_MP 0x00000001 /* Magic packet Address */
+
+/* Wake On LAN Control */
+#define PCH_GBE_WLC_WOL_MODE 0x00010000
+#define PCH_GBE_WLC_IGN_TLONG 0x00000100
+#define PCH_GBE_WLC_IGN_TSHRT 0x00000080
+#define PCH_GBE_WLC_IGN_OCTER 0x00000040
+#define PCH_GBE_WLC_IGN_NBLER 0x00000020
+#define PCH_GBE_WLC_IGN_CRCER 0x00000010
+#define PCH_GBE_WLC_BR 0x00000008
+#define PCH_GBE_WLC_MLT 0x00000004
+#define PCH_GBE_WLC_IND 0x00000002
+#define PCH_GBE_WLC_MP 0x00000001
+
+/* Wake On LAN Address Mask */
+#define PCH_GBE_WLA_BUSY 0x80000000
+
+
+
+/* TX/RX descriptor defines */
+#define PCH_GBE_MAX_TXD 4096
+#define PCH_GBE_DEFAULT_TXD 256
+#define PCH_GBE_MIN_TXD 8
+#define PCH_GBE_MAX_RXD 4096
+#define PCH_GBE_DEFAULT_RXD 256
+#define PCH_GBE_MIN_RXD 8
+
+/* Number of Transmit and Receive Descriptors must be a multiple of 8 */
+#define PCH_GBE_TX_DESC_MULTIPLE 8
+#define PCH_GBE_RX_DESC_MULTIPLE 8
+
+/* Read/Write operation is done through MII Management IF */
+#define PCH_GBE_HAL_MIIM_READ ((u32)0x00000000)
+#define PCH_GBE_HAL_MIIM_WRITE ((u32)0x04000000)
+
+/* flow control values */
+#define PCH_GBE_FC_NONE 0
+#define PCH_GBE_FC_RX_PAUSE 1
+#define PCH_GBE_FC_TX_PAUSE 2
+#define PCH_GBE_FC_FULL 3
+#define PCH_GBE_FC_DEFAULT PCH_GBE_FC_FULL
+
+
+struct pch_gbe_hw;
+/**
+ * struct pch_gbe_functions - HAL APi function pointer
+ * @get_bus_info: for pch_gbe_hal_get_bus_info
+ * @init_hw: for pch_gbe_hal_init_hw
+ * @read_phy_reg: for pch_gbe_hal_read_phy_reg
+ * @write_phy_reg: for pch_gbe_hal_write_phy_reg
+ * @reset_phy: for pch_gbe_hal_phy_hw_reset
+ * @sw_reset_phy: for pch_gbe_hal_phy_sw_reset
+ * @power_up_phy: for pch_gbe_hal_power_up_phy
+ * @power_down_phy: for pch_gbe_hal_power_down_phy
+ * @read_mac_addr: for pch_gbe_hal_read_mac_addr
+ */
+struct pch_gbe_functions {
+ void (*get_bus_info) (struct pch_gbe_hw *);
+ s32 (*init_hw) (struct pch_gbe_hw *);
+ s32 (*read_phy_reg) (struct pch_gbe_hw *, u32, u16 *);
+ s32 (*write_phy_reg) (struct pch_gbe_hw *, u32, u16);
+ void (*reset_phy) (struct pch_gbe_hw *);
+ void (*sw_reset_phy) (struct pch_gbe_hw *);
+ void (*power_up_phy) (struct pch_gbe_hw *hw);
+ void (*power_down_phy) (struct pch_gbe_hw *hw);
+ s32 (*read_mac_addr) (struct pch_gbe_hw *);
+};
+
+/**
+ * struct pch_gbe_mac_info - MAC infomation
+ * @addr[6]: Store the MAC address
+ * @fc: Mode of flow control
+ * @fc_autoneg: Auto negotiation enable for flow control setting
+ * @tx_fc_enable: Enable flag of Transmit flow control
+ * @max_frame_size: Max transmit frame size
+ * @min_frame_size: Min transmit frame size
+ * @autoneg: Auto negotiation enable
+ * @link_speed: Link speed
+ * @link_duplex: Link duplex
+ */
+struct pch_gbe_mac_info {
+ u8 addr[6];
+ u8 fc;
+ u8 fc_autoneg;
+ u8 tx_fc_enable;
+ u32 max_frame_size;
+ u32 min_frame_size;
+ u8 autoneg;
+ u16 link_speed;
+ u16 link_duplex;
+};
+
+/**
+ * struct pch_gbe_phy_info - PHY infomation
+ * @addr: PHY address
+ * @id: PHY's identifier
+ * @revision: PHY's revision
+ * @reset_delay_us: HW reset delay time[us]
+ * @autoneg_advertised: Autoneg advertised
+ */
+struct pch_gbe_phy_info {
+ u32 addr;
+ u32 id;
+ u32 revision;
+ u32 reset_delay_us;
+ u16 autoneg_advertised;
+};
+
+/*!
+ * @ingroup Gigabit Ether driver Layer
+ * @struct pch_gbe_bus_info
+ * @brief Bus infomation
+ */
+struct pch_gbe_bus_info {
+ u8 type;
+ u8 speed;
+ u8 width;
+};
+
+/*!
+ * @ingroup Gigabit Ether driver Layer
+ * @struct pch_gbe_hw
+ * @brief Hardware infomation
+ */
+struct pch_gbe_hw {
+ void *back;
+
+ struct pch_gbe_regs __iomem *reg;
+ spinlock_t miim_lock;
+
+ const struct pch_gbe_functions *func;
+ struct pch_gbe_mac_info mac;
+ struct pch_gbe_phy_info phy;
+ struct pch_gbe_bus_info bus;
+};
+
+/**
+ * struct pch_gbe_rx_desc - Receive Descriptor
+ * @buffer_addr: RX Frame Buffer Address
+ * @tcp_ip_status: TCP/IP Accelerator Status
+ * @rx_words_eob: RX word count and Byte position
+ * @gbec_status: GMAC Status
+ * @dma_status: DMA Status
+ * @reserved1: Reserved
+ * @reserved2: Reserved
+ */
+struct pch_gbe_rx_desc {
+ u32 buffer_addr;
+ u32 tcp_ip_status;
+ u16 rx_words_eob;
+ u16 gbec_status;
+ u8 dma_status;
+ u8 reserved1;
+ u16 reserved2;
+};
+
+/**
+ * struct pch_gbe_tx_desc - Transmit Descriptor
+ * @buffer_addr: TX Frame Buffer Address
+ * @length: Data buffer length
+ * @reserved1: Reserved
+ * @tx_words_eob: TX word count and Byte position
+ * @tx_frame_ctrl: TX Frame Control
+ * @dma_status: DMA Status
+ * @reserved2: Reserved
+ * @gbec_status: GMAC Status
+ */
+struct pch_gbe_tx_desc {
+ u32 buffer_addr;
+ u16 length;
+ u16 reserved1;
+ u16 tx_words_eob;
+ u16 tx_frame_ctrl;
+ u8 dma_status;
+ u8 reserved2;
+ u16 gbec_status;
+};
+
+
+/**
+ * struct pch_gbe_buffer - Buffer infomation
+ * @skb: pointer to a socket buffer
+ * @dma: DMA address
+ * @time_stamp: time stamp
+ * @length: data size
+ */
+struct pch_gbe_buffer {
+ struct sk_buff *skb;
+ dma_addr_t dma;
+ unsigned long time_stamp;
+ u16 length;
+ bool mapped;
+};
+
+/**
+ * struct pch_gbe_tx_ring - tx ring infomation
+ * @tx_lock: spinlock structs
+ * @desc: pointer to the descriptor ring memory
+ * @dma: physical address of the descriptor ring
+ * @size: length of descriptor ring in bytes
+ * @count: number of descriptors in the ring
+ * @next_to_use: next descriptor to associate a buffer with
+ * @next_to_clean: next descriptor to check for DD status bit
+ * @buffer_info: array of buffer information structs
+ */
+struct pch_gbe_tx_ring {
+ spinlock_t tx_lock;
+ struct pch_gbe_tx_desc *desc;
+ dma_addr_t dma;
+ unsigned int size;
+ unsigned int count;
+ unsigned int next_to_use;
+ unsigned int next_to_clean;
+ struct pch_gbe_buffer *buffer_info;
+};
+
+/**
+ * struct pch_gbe_rx_ring - rx ring infomation
+ * @desc: pointer to the descriptor ring memory
+ * @dma: physical address of the descriptor ring
+ * @size: length of descriptor ring in bytes
+ * @count: number of descriptors in the ring
+ * @next_to_use: next descriptor to associate a buffer with
+ * @next_to_clean: next descriptor to check for DD status bit
+ * @buffer_info: array of buffer information structs
+ */
+struct pch_gbe_rx_ring {
+ struct pch_gbe_rx_desc *desc;
+ dma_addr_t dma;
+ unsigned int size;
+ unsigned int count;
+ unsigned int next_to_use;
+ unsigned int next_to_clean;
+ struct pch_gbe_buffer *buffer_info;
+};
+
+/**
+ * struct pch_gbe_hw_stats - Statistics counters collected by the MAC
+ * @rx_packets: total packets received
+ * @tx_packets: total packets transmitted
+ * @rx_bytes: total bytes received
+ * @tx_bytes: total bytes transmitted
+ * @rx_errors: bad packets received
+ * @tx_errors: packet transmit problems
+ * @rx_dropped: no space in Linux buffers
+ * @tx_dropped: no space available in Linux
+ * @multicast: multicast packets received
+ * @collisions: collisions
+ * @rx_crc_errors: received packet with crc error
+ * @rx_frame_errors: received frame alignment error
+ * @rx_alloc_buff_failed: allocate failure of a receive buffer
+ * @tx_length_errors: transmit length error
+ * @tx_aborted_errors: transmit aborted error
+ * @tx_carrier_errors: transmit carrier error
+ * @tx_timeout_count: Number of transmit timeout
+ * @tx_restart_count: Number of transmit restert
+ * @intr_rx_dsc_empty_count: Interrupt count of receive descriptor empty
+ * @intr_rx_frame_err_count: Interrupt count of receive frame error
+ * @intr_rx_fifo_err_count: Interrupt count of receive FIFO error
+ * @intr_rx_dma_err_count: Interrupt count of receive DMA error
+ * @intr_tx_fifo_err_count: Interrupt count of transmit FIFO error
+ * @intr_tx_dma_err_count: Interrupt count of transmit DMA error
+ * @intr_tcpip_err_count: Interrupt count of TCP/IP Accelerator
+ */
+struct pch_gbe_hw_stats {
+ u32 rx_packets;
+ u32 tx_packets;
+ u32 rx_bytes;
+ u32 tx_bytes;
+ u32 rx_errors;
+ u32 tx_errors;
+ u32 rx_dropped;
+ u32 tx_dropped;
+ u32 multicast;
+ u32 collisions;
+ u32 rx_crc_errors;
+ u32 rx_frame_errors;
+ u32 rx_alloc_buff_failed;
+ u32 tx_length_errors;
+ u32 tx_aborted_errors;
+ u32 tx_carrier_errors;
+ u32 tx_timeout_count;
+ u32 tx_restart_count;
+ u32 intr_rx_dsc_empty_count;
+ u32 intr_rx_frame_err_count;
+ u32 intr_rx_fifo_err_count;
+ u32 intr_rx_dma_err_count;
+ u32 intr_tx_fifo_err_count;
+ u32 intr_tx_dma_err_count;
+ u32 intr_tcpip_err_count;
+};
+
+/**
+ * struct pch_gbe_adapter - board specific private data structure
+ * @stats_lock: Spinlock structure for status
+ * @tx_queue_lock: Spinlock structure for transmit
+ * @ethtool_lock: Spinlock structure for ethtool
+ * @irq_sem: Semaphore for interrupt
+ * @netdev: Pointer of network device structure
+ * @pdev: Pointer of pci device structure
+ * @polling_netdev: Pointer of polling network device structure
+ * @napi: NAPI structure
+ * @hw: Pointer of hardware structure
+ * @stats: Hardware status
+ * @reset_task: Reset task
+ * @mii: MII information structure
+ * @watchdog_timer: Watchdog timer list
+ * @wake_up_evt: Wake up event
+ * @config_space: Configuration space
+ * @msg_enable: Driver message level
+ * @led_status: LED status
+ * @tx_ring: Pointer of Tx descriptor ring structure
+ * @rx_ring: Pointer of Rx descriptor ring structure
+ * @rx_buffer_len: Receive buffer length
+ * @tx_queue_len: Transmit queue length
+ * @rx_csum: Receive TCP/IP checksum enable/disable
+ * @tx_csum: Transmit TCP/IP checksum enable/disable
+ * @have_msi: PCI MSI mode flag
+ */
+
+struct pch_gbe_adapter {
+ spinlock_t stats_lock;
+ spinlock_t tx_queue_lock;
+ spinlock_t ethtool_lock;
+ atomic_t irq_sem;
+ struct net_device *netdev;
+ struct pci_dev *pdev;
+ struct net_device *polling_netdev;
+ struct napi_struct napi;
+ struct pch_gbe_hw hw;
+ struct pch_gbe_hw_stats stats;
+ struct work_struct reset_task;
+ struct mii_if_info mii;
+ struct timer_list watchdog_timer;
+ u32 wake_up_evt;
+ u32 *config_space;
+ unsigned long led_status;
+ struct pch_gbe_tx_ring *tx_ring;
+ struct pch_gbe_rx_ring *rx_ring;
+ unsigned long rx_buffer_len;
+ unsigned long tx_queue_len;
+ bool rx_csum;
+ bool tx_csum;
+ bool have_msi;
+};
+
+extern const char pch_driver_version[];
+
+/* pch_gbe_main.c */
+extern int pch_gbe_up(struct pch_gbe_adapter *adapter);
+extern void pch_gbe_down(struct pch_gbe_adapter *adapter);
+extern void pch_gbe_reinit_locked(struct pch_gbe_adapter *adapter);
+extern void pch_gbe_reset(struct pch_gbe_adapter *adapter);
+extern int pch_gbe_setup_tx_resources(struct pch_gbe_adapter *adapter,
+ struct pch_gbe_tx_ring *txdr);
+extern int pch_gbe_setup_rx_resources(struct pch_gbe_adapter *adapter,
+ struct pch_gbe_rx_ring *rxdr);
+extern void pch_gbe_free_tx_resources(struct pch_gbe_adapter *adapter,
+ struct pch_gbe_tx_ring *tx_ring);
+extern void pch_gbe_free_rx_resources(struct pch_gbe_adapter *adapter,
+ struct pch_gbe_rx_ring *rx_ring);
+extern void pch_gbe_update_stats(struct pch_gbe_adapter *adapter);
+
+/* pch_gbe_param.c */
+extern void pch_gbe_check_options(struct pch_gbe_adapter *adapter);
+
+/* pch_gbe_ethtool.c */
+extern void pch_gbe_set_ethtool_ops(struct net_device *netdev);
+
+/* pch_gbe_mac.c */
+extern s32 pch_gbe_mac_force_mac_fc(struct pch_gbe_hw *hw);
+extern s32 pch_gbe_mac_read_mac_addr(struct pch_gbe_hw *hw);
+extern u16 pch_gbe_mac_ctrl_miim(struct pch_gbe_hw *hw,
+ u32 addr, u32 dir, u32 reg, u16 data);
+#endif /* _PCH_GBE_H_ */
diff --git a/drivers/net/pch_gbe/pch_gbe_api.c b/drivers/net/pch_gbe/pch_gbe_api.c
new file mode 100644
index 000000000000..e48f084ad226
--- /dev/null
+++ b/drivers/net/pch_gbe/pch_gbe_api.c
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 1999 - 2010 Intel Corporation.
+ * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ *
+ * This code was derived from the Intel e1000e Linux driver.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include "pch_gbe.h"
+#include "pch_gbe_phy.h"
+
+/* bus type values */
+#define pch_gbe_bus_type_unknown 0
+#define pch_gbe_bus_type_pci 1
+#define pch_gbe_bus_type_pcix 2
+#define pch_gbe_bus_type_pci_express 3
+#define pch_gbe_bus_type_reserved 4
+
+/* bus speed values */
+#define pch_gbe_bus_speed_unknown 0
+#define pch_gbe_bus_speed_33 1
+#define pch_gbe_bus_speed_66 2
+#define pch_gbe_bus_speed_100 3
+#define pch_gbe_bus_speed_120 4
+#define pch_gbe_bus_speed_133 5
+#define pch_gbe_bus_speed_2500 6
+#define pch_gbe_bus_speed_reserved 7
+
+/* bus width values */
+#define pch_gbe_bus_width_unknown 0
+#define pch_gbe_bus_width_pcie_x1 1
+#define pch_gbe_bus_width_pcie_x2 2
+#define pch_gbe_bus_width_pcie_x4 4
+#define pch_gbe_bus_width_32 5
+#define pch_gbe_bus_width_64 6
+#define pch_gbe_bus_width_reserved 7
+
+/**
+ * pch_gbe_plat_get_bus_info - Obtain bus information for adapter
+ * @hw: Pointer to the HW structure
+ */
+static void pch_gbe_plat_get_bus_info(struct pch_gbe_hw *hw)
+{
+ hw->bus.type = pch_gbe_bus_type_pci_express;
+ hw->bus.speed = pch_gbe_bus_speed_2500;
+ hw->bus.width = pch_gbe_bus_width_pcie_x1;
+}
+
+/**
+ * pch_gbe_plat_init_hw - Initialize hardware
+ * @hw: Pointer to the HW structure
+ * Returns
+ * 0: Successfully
+ * Negative value: Failed-EBUSY
+ */
+static s32 pch_gbe_plat_init_hw(struct pch_gbe_hw *hw)
+{
+ s32 ret_val;
+
+ ret_val = pch_gbe_phy_get_id(hw);
+ if (ret_val) {
+ pr_err("pch_gbe_phy_get_id error\n");
+ return ret_val;
+ }
+ pch_gbe_phy_init_setting(hw);
+ /* Setup Mac interface option RGMII */
+#ifdef PCH_GBE_MAC_IFOP_RGMII
+ pch_gbe_phy_set_rgmii(hw);
+#endif
+ return ret_val;
+}
+
+static const struct pch_gbe_functions pch_gbe_ops = {
+ .get_bus_info = pch_gbe_plat_get_bus_info,
+ .init_hw = pch_gbe_plat_init_hw,
+ .read_phy_reg = pch_gbe_phy_read_reg_miic,
+ .write_phy_reg = pch_gbe_phy_write_reg_miic,
+ .reset_phy = pch_gbe_phy_hw_reset,
+ .sw_reset_phy = pch_gbe_phy_sw_reset,
+ .power_up_phy = pch_gbe_phy_power_up,
+ .power_down_phy = pch_gbe_phy_power_down,
+ .read_mac_addr = pch_gbe_mac_read_mac_addr
+};
+
+/**
+ * pch_gbe_plat_init_function_pointers - Init func ptrs
+ * @hw: Pointer to the HW structure
+ */
+static void pch_gbe_plat_init_function_pointers(struct pch_gbe_hw *hw)
+{
+ /* Set PHY parameter */
+ hw->phy.reset_delay_us = PCH_GBE_PHY_RESET_DELAY_US;
+ /* Set function pointers */
+ hw->func = &pch_gbe_ops;
+}
+
+/**
+ * pch_gbe_hal_setup_init_funcs - Initializes function pointers
+ * @hw: Pointer to the HW structure
+ * Returns
+ * 0: Successfully
+ * ENOSYS: Function is not registered
+ */
+inline s32 pch_gbe_hal_setup_init_funcs(struct pch_gbe_hw *hw)
+{
+ if (!hw->reg) {
+ pr_err("ERROR: Registers not mapped\n");
+ return -ENOSYS;
+ }
+ pch_gbe_plat_init_function_pointers(hw);
+ return 0;
+}
+
+/**
+ * pch_gbe_hal_get_bus_info - Obtain bus information for adapter
+ * @hw: Pointer to the HW structure
+ */
+inline void pch_gbe_hal_get_bus_info(struct pch_gbe_hw *hw)
+{
+ if (!hw->func->get_bus_info)
+ pr_err("ERROR: configuration\n");
+ else
+ hw->func->get_bus_info(hw);
+}
+
+/**
+ * pch_gbe_hal_init_hw - Initialize hardware
+ * @hw: Pointer to the HW structure
+ * Returns
+ * 0: Successfully
+ * ENOSYS: Function is not registered
+ */
+inline s32 pch_gbe_hal_init_hw(struct pch_gbe_hw *hw)
+{
+ if (!hw->func->init_hw) {
+ pr_err("ERROR: configuration\n");
+ return -ENOSYS;
+ }
+ return hw->func->init_hw(hw);
+}
+
+/**
+ * pch_gbe_hal_read_phy_reg - Reads PHY register
+ * @hw: Pointer to the HW structure
+ * @offset: The register to read
+ * @data: The buffer to store the 16-bit read.
+ * Returns
+ * 0: Successfully
+ * Negative value: Failed
+ */
+inline s32 pch_gbe_hal_read_phy_reg(struct pch_gbe_hw *hw, u32 offset,
+ u16 *data)
+{
+ if (!hw->func->read_phy_reg)
+ return 0;
+ return hw->func->read_phy_reg(hw, offset, data);
+}
+
+/**
+ * pch_gbe_hal_write_phy_reg - Writes PHY register
+ * @hw: Pointer to the HW structure
+ * @offset: The register to read
+ * @data: The value to write.
+ * Returns
+ * 0: Successfully
+ * Negative value: Failed
+ */
+inline s32 pch_gbe_hal_write_phy_reg(struct pch_gbe_hw *hw, u32 offset,
+ u16 data)
+{
+ if (!hw->func->write_phy_reg)
+ return 0;
+ return hw->func->write_phy_reg(hw, offset, data);
+}
+
+/**
+ * pch_gbe_hal_phy_hw_reset - Hard PHY reset
+ * @hw: Pointer to the HW structure
+ */
+inline void pch_gbe_hal_phy_hw_reset(struct pch_gbe_hw *hw)
+{
+ if (!hw->func->reset_phy)
+ pr_err("ERROR: configuration\n");
+ else
+ hw->func->reset_phy(hw);
+}
+
+/**
+ * pch_gbe_hal_phy_sw_reset - Soft PHY reset
+ * @hw: Pointer to the HW structure
+ */
+inline void pch_gbe_hal_phy_sw_reset(struct pch_gbe_hw *hw)
+{
+ if (!hw->func->sw_reset_phy)
+ pr_err("ERROR: configuration\n");
+ else
+ hw->func->sw_reset_phy(hw);
+}
+
+/**
+ * pch_gbe_hal_read_mac_addr - Reads MAC address
+ * @hw: Pointer to the HW structure
+ * Returns
+ * 0: Successfully
+ * ENOSYS: Function is not registered
+ */
+inline s32 pch_gbe_hal_read_mac_addr(struct pch_gbe_hw *hw)
+{
+ if (!hw->func->read_mac_addr) {
+ pr_err("ERROR: configuration\n");
+ return -ENOSYS;
+ }
+ return hw->func->read_mac_addr(hw);
+}
+
+/**
+ * pch_gbe_hal_power_up_phy - Power up PHY
+ * @hw: Pointer to the HW structure
+ */
+inline void pch_gbe_hal_power_up_phy(struct pch_gbe_hw *hw)
+{
+ if (hw->func->power_up_phy)
+ hw->func->power_up_phy(hw);
+}
+
+/**
+ * pch_gbe_hal_power_down_phy - Power down PHY
+ * @hw: Pointer to the HW structure
+ */
+inline void pch_gbe_hal_power_down_phy(struct pch_gbe_hw *hw)
+{
+ if (hw->func->power_down_phy)
+ hw->func->power_down_phy(hw);
+}
diff --git a/drivers/net/pch_gbe/pch_gbe_api.h b/drivers/net/pch_gbe/pch_gbe_api.h
new file mode 100644
index 000000000000..94aaac5b057b
--- /dev/null
+++ b/drivers/net/pch_gbe/pch_gbe_api.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 1999 - 2010 Intel Corporation.
+ * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ *
+ * This code was derived from the Intel e1000e Linux driver.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+#ifndef _PCH_GBE_API_H_
+#define _PCH_GBE_API_H_
+
+#include "pch_gbe_phy.h"
+
+s32 pch_gbe_hal_setup_init_funcs(struct pch_gbe_hw *hw);
+void pch_gbe_hal_get_bus_info(struct pch_gbe_hw *hw);
+s32 pch_gbe_hal_init_hw(struct pch_gbe_hw *hw);
+s32 pch_gbe_hal_read_phy_reg(struct pch_gbe_hw *hw, u32 offset, u16 *data);
+s32 pch_gbe_hal_write_phy_reg(struct pch_gbe_hw *hw, u32 offset, u16 data);
+void pch_gbe_hal_phy_hw_reset(struct pch_gbe_hw *hw);
+void pch_gbe_hal_phy_sw_reset(struct pch_gbe_hw *hw);
+s32 pch_gbe_hal_read_mac_addr(struct pch_gbe_hw *hw);
+void pch_gbe_hal_power_up_phy(struct pch_gbe_hw *hw);
+void pch_gbe_hal_power_down_phy(struct pch_gbe_hw *hw);
+
+#endif
diff --git a/drivers/net/pch_gbe/pch_gbe_ethtool.c b/drivers/net/pch_gbe/pch_gbe_ethtool.c
new file mode 100644
index 000000000000..c8cc32c0edc9
--- /dev/null
+++ b/drivers/net/pch_gbe/pch_gbe_ethtool.c
@@ -0,0 +1,585 @@
+/*
+ * Copyright (C) 1999 - 2010 Intel Corporation.
+ * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ *
+ * This code was derived from the Intel e1000e Linux driver.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include "pch_gbe.h"
+#include "pch_gbe_api.h"
+
+/**
+ * pch_gbe_stats - Stats item infomation
+ */
+struct pch_gbe_stats {
+ char string[ETH_GSTRING_LEN];
+ size_t size;
+ size_t offset;
+};
+
+#define PCH_GBE_STAT(m) \
+{ \
+ .string = #m, \
+ .size = FIELD_SIZEOF(struct pch_gbe_hw_stats, m), \
+ .offset = offsetof(struct pch_gbe_hw_stats, m), \
+}
+
+/**
+ * pch_gbe_gstrings_stats - ethtool information status name list
+ */
+static const struct pch_gbe_stats pch_gbe_gstrings_stats[] = {
+ PCH_GBE_STAT(rx_packets),
+ PCH_GBE_STAT(tx_packets),
+ PCH_GBE_STAT(rx_bytes),
+ PCH_GBE_STAT(tx_bytes),
+ PCH_GBE_STAT(rx_errors),
+ PCH_GBE_STAT(tx_errors),
+ PCH_GBE_STAT(rx_dropped),
+ PCH_GBE_STAT(tx_dropped),
+ PCH_GBE_STAT(multicast),
+ PCH_GBE_STAT(collisions),
+ PCH_GBE_STAT(rx_crc_errors),
+ PCH_GBE_STAT(rx_frame_errors),
+ PCH_GBE_STAT(rx_alloc_buff_failed),
+ PCH_GBE_STAT(tx_length_errors),
+ PCH_GBE_STAT(tx_aborted_errors),
+ PCH_GBE_STAT(tx_carrier_errors),
+ PCH_GBE_STAT(tx_timeout_count),
+ PCH_GBE_STAT(tx_restart_count),
+ PCH_GBE_STAT(intr_rx_dsc_empty_count),
+ PCH_GBE_STAT(intr_rx_frame_err_count),
+ PCH_GBE_STAT(intr_rx_fifo_err_count),
+ PCH_GBE_STAT(intr_rx_dma_err_count),
+ PCH_GBE_STAT(intr_tx_fifo_err_count),
+ PCH_GBE_STAT(intr_tx_dma_err_count),
+ PCH_GBE_STAT(intr_tcpip_err_count)
+};
+
+#define PCH_GBE_QUEUE_STATS_LEN 0
+#define PCH_GBE_GLOBAL_STATS_LEN ARRAY_SIZE(pch_gbe_gstrings_stats)
+#define PCH_GBE_STATS_LEN (PCH_GBE_GLOBAL_STATS_LEN + PCH_GBE_QUEUE_STATS_LEN)
+
+#define PCH_GBE_MAC_REGS_LEN (sizeof(struct pch_gbe_regs) / 4)
+#define PCH_GBE_REGS_LEN (PCH_GBE_MAC_REGS_LEN + PCH_GBE_PHY_REGS_LEN)
+/**
+ * pch_gbe_get_settings - Get device-specific settings
+ * @netdev: Network interface device structure
+ * @ecmd: Ethtool command
+ * Returns
+ * 0: Successful.
+ * Negative value: Failed.
+ */
+static int pch_gbe_get_settings(struct net_device *netdev,
+ struct ethtool_cmd *ecmd)
+{
+ struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+ int ret;
+
+ ret = mii_ethtool_gset(&adapter->mii, ecmd);
+ ecmd->supported &= ~(SUPPORTED_TP | SUPPORTED_1000baseT_Half);
+ ecmd->advertising &= ~(ADVERTISED_TP | ADVERTISED_1000baseT_Half);
+
+ if (!netif_carrier_ok(adapter->netdev))
+ ecmd->speed = -1;
+ return ret;
+}
+
+/**
+ * pch_gbe_set_settings - Set device-specific settings
+ * @netdev: Network interface device structure
+ * @ecmd: Ethtool command
+ * Returns
+ * 0: Successful.
+ * Negative value: Failed.
+ */
+static int pch_gbe_set_settings(struct net_device *netdev,
+ struct ethtool_cmd *ecmd)
+{
+ struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+ struct pch_gbe_hw *hw = &adapter->hw;
+ int ret;
+
+ pch_gbe_hal_write_phy_reg(hw, MII_BMCR, BMCR_RESET);
+
+ if (ecmd->speed == USHRT_MAX) {
+ ecmd->speed = SPEED_1000;
+ ecmd->duplex = DUPLEX_FULL;
+ }
+ ret = mii_ethtool_sset(&adapter->mii, ecmd);
+ if (ret) {
+ pr_err("Error: mii_ethtool_sset\n");
+ return ret;
+ }
+ hw->mac.link_speed = ecmd->speed;
+ hw->mac.link_duplex = ecmd->duplex;
+ hw->phy.autoneg_advertised = ecmd->advertising;
+ hw->mac.autoneg = ecmd->autoneg;
+ pch_gbe_hal_phy_sw_reset(hw);
+
+ /* reset the link */
+ if (netif_running(adapter->netdev)) {
+ pch_gbe_down(adapter);
+ ret = pch_gbe_up(adapter);
+ } else {
+ pch_gbe_reset(adapter);
+ }
+ return ret;
+}
+
+/**
+ * pch_gbe_get_regs_len - Report the size of device registers
+ * @netdev: Network interface device structure
+ * Returns: the size of device registers.
+ */
+static int pch_gbe_get_regs_len(struct net_device *netdev)
+{
+ return PCH_GBE_REGS_LEN * (int)sizeof(u32);
+}
+
+/**
+ * pch_gbe_get_drvinfo - Report driver information
+ * @netdev: Network interface device structure
+ * @drvinfo: Driver information structure
+ */
+static void pch_gbe_get_drvinfo(struct net_device *netdev,
+ struct ethtool_drvinfo *drvinfo)
+{
+ struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+
+ strcpy(drvinfo->driver, KBUILD_MODNAME);
+ strcpy(drvinfo->version, pch_driver_version);
+ strcpy(drvinfo->fw_version, "N/A");
+ strcpy(drvinfo->bus_info, pci_name(adapter->pdev));
+ drvinfo->regdump_len = pch_gbe_get_regs_len(netdev);
+}
+
+/**
+ * pch_gbe_get_regs - Get device registers
+ * @netdev: Network interface device structure
+ * @regs: Ethtool register structure
+ * @p: Buffer pointer of read device register date
+ */
+static void pch_gbe_get_regs(struct net_device *netdev,
+ struct ethtool_regs *regs, void *p)
+{
+ struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+ struct pch_gbe_hw *hw = &adapter->hw;
+ struct pci_dev *pdev = adapter->pdev;
+ u32 *regs_buff = p;
+ u16 i, tmp;
+
+ regs->version = 0x1000000 | (__u32)pdev->revision << 16 | pdev->device;
+ for (i = 0; i < PCH_GBE_MAC_REGS_LEN; i++)
+ *regs_buff++ = ioread32(&hw->reg->INT_ST + i);
+ /* PHY register */
+ for (i = 0; i < PCH_GBE_PHY_REGS_LEN; i++) {
+ pch_gbe_hal_read_phy_reg(&adapter->hw, i, &tmp);
+ *regs_buff++ = tmp;
+ }
+}
+
+/**
+ * pch_gbe_get_wol - Report whether Wake-on-Lan is enabled
+ * @netdev: Network interface device structure
+ * @wol: Wake-on-Lan information
+ */
+static void pch_gbe_get_wol(struct net_device *netdev,
+ struct ethtool_wolinfo *wol)
+{
+ struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+
+ wol->supported = WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC;
+ wol->wolopts = 0;
+
+ if ((adapter->wake_up_evt & PCH_GBE_WLC_IND))
+ wol->wolopts |= WAKE_UCAST;
+ if ((adapter->wake_up_evt & PCH_GBE_WLC_MLT))
+ wol->wolopts |= WAKE_MCAST;
+ if ((adapter->wake_up_evt & PCH_GBE_WLC_BR))
+ wol->wolopts |= WAKE_BCAST;
+ if ((adapter->wake_up_evt & PCH_GBE_WLC_MP))
+ wol->wolopts |= WAKE_MAGIC;
+}
+
+/**
+ * pch_gbe_set_wol - Turn Wake-on-Lan on or off
+ * @netdev: Network interface device structure
+ * @wol: Pointer of wake-on-Lan information straucture
+ * Returns
+ * 0: Successful.
+ * Negative value: Failed.
+ */
+static int pch_gbe_set_wol(struct net_device *netdev,
+ struct ethtool_wolinfo *wol)
+{
+ struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+
+ if ((wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE)))
+ return -EOPNOTSUPP;
+ /* these settings will always override what we currently have */
+ adapter->wake_up_evt = 0;
+
+ if ((wol->wolopts & WAKE_UCAST))
+ adapter->wake_up_evt |= PCH_GBE_WLC_IND;
+ if ((wol->wolopts & WAKE_MCAST))
+ adapter->wake_up_evt |= PCH_GBE_WLC_MLT;
+ if ((wol->wolopts & WAKE_BCAST))
+ adapter->wake_up_evt |= PCH_GBE_WLC_BR;
+ if ((wol->wolopts & WAKE_MAGIC))
+ adapter->wake_up_evt |= PCH_GBE_WLC_MP;
+ return 0;
+}
+
+/**
+ * pch_gbe_nway_reset - Restart autonegotiation
+ * @netdev: Network interface device structure
+ * Returns
+ * 0: Successful.
+ * Negative value: Failed.
+ */
+static int pch_gbe_nway_reset(struct net_device *netdev)
+{
+ struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+
+ return mii_nway_restart(&adapter->mii);
+}
+
+/**
+ * pch_gbe_get_ringparam - Report ring sizes
+ * @netdev: Network interface device structure
+ * @ring: Ring param structure
+ */
+static void pch_gbe_get_ringparam(struct net_device *netdev,
+ struct ethtool_ringparam *ring)
+{
+ struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+ struct pch_gbe_tx_ring *txdr = adapter->tx_ring;
+ struct pch_gbe_rx_ring *rxdr = adapter->rx_ring;
+
+ ring->rx_max_pending = PCH_GBE_MAX_RXD;
+ ring->tx_max_pending = PCH_GBE_MAX_TXD;
+ ring->rx_mini_max_pending = 0;
+ ring->rx_jumbo_max_pending = 0;
+ ring->rx_pending = rxdr->count;
+ ring->tx_pending = txdr->count;
+ ring->rx_mini_pending = 0;
+ ring->rx_jumbo_pending = 0;
+}
+
+/**
+ * pch_gbe_set_ringparam - Set ring sizes
+ * @netdev: Network interface device structure
+ * @ring: Ring param structure
+ * Returns
+ * 0: Successful.
+ * Negative value: Failed.
+ */
+static int pch_gbe_set_ringparam(struct net_device *netdev,
+ struct ethtool_ringparam *ring)
+{
+ struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+ struct pch_gbe_tx_ring *txdr, *tx_old;
+ struct pch_gbe_rx_ring *rxdr, *rx_old;
+ int tx_ring_size, rx_ring_size;
+ int err = 0;
+
+ if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
+ return -EINVAL;
+ tx_ring_size = (int)sizeof(struct pch_gbe_tx_ring);
+ rx_ring_size = (int)sizeof(struct pch_gbe_rx_ring);
+
+ if ((netif_running(adapter->netdev)))
+ pch_gbe_down(adapter);
+ tx_old = adapter->tx_ring;
+ rx_old = adapter->rx_ring;
+
+ txdr = kzalloc(tx_ring_size, GFP_KERNEL);
+ if (!txdr) {
+ err = -ENOMEM;
+ goto err_alloc_tx;
+ }
+ rxdr = kzalloc(rx_ring_size, GFP_KERNEL);
+ if (!rxdr) {
+ err = -ENOMEM;
+ goto err_alloc_rx;
+ }
+ adapter->tx_ring = txdr;
+ adapter->rx_ring = rxdr;
+
+ rxdr->count =
+ clamp_val(ring->rx_pending, PCH_GBE_MIN_RXD, PCH_GBE_MAX_RXD);
+ rxdr->count = roundup(rxdr->count, PCH_GBE_RX_DESC_MULTIPLE);
+
+ txdr->count =
+ clamp_val(ring->tx_pending, PCH_GBE_MIN_RXD, PCH_GBE_MAX_RXD);
+ txdr->count = roundup(txdr->count, PCH_GBE_TX_DESC_MULTIPLE);
+
+ if ((netif_running(adapter->netdev))) {
+ /* Try to get new resources before deleting old */
+ err = pch_gbe_setup_rx_resources(adapter, adapter->rx_ring);
+ if (err)
+ goto err_setup_rx;
+ err = pch_gbe_setup_tx_resources(adapter, adapter->tx_ring);
+ if (err)
+ goto err_setup_tx;
+ /* save the new, restore the old in order to free it,
+ * then restore the new back again */
+#ifdef RINGFREE
+ adapter->rx_ring = rx_old;
+ adapter->tx_ring = tx_old;
+ pch_gbe_free_rx_resources(adapter, adapter->rx_ring);
+ pch_gbe_free_tx_resources(adapter, adapter->tx_ring);
+ kfree(tx_old);
+ kfree(rx_old);
+ adapter->rx_ring = rxdr;
+ adapter->tx_ring = txdr;
+#else
+ pch_gbe_free_rx_resources(adapter, rx_old);
+ pch_gbe_free_tx_resources(adapter, tx_old);
+ kfree(tx_old);
+ kfree(rx_old);
+ adapter->rx_ring = rxdr;
+ adapter->tx_ring = txdr;
+#endif
+ err = pch_gbe_up(adapter);
+ }
+ return err;
+
+err_setup_tx:
+ pch_gbe_free_rx_resources(adapter, adapter->rx_ring);
+err_setup_rx:
+ adapter->rx_ring = rx_old;
+ adapter->tx_ring = tx_old;
+ kfree(rxdr);
+err_alloc_rx:
+ kfree(txdr);
+err_alloc_tx:
+ if (netif_running(adapter->netdev))
+ pch_gbe_up(adapter);
+ return err;
+}
+
+/**
+ * pch_gbe_get_pauseparam - Report pause parameters
+ * @netdev: Network interface device structure
+ * @pause: Pause parameters structure
+ */
+static void pch_gbe_get_pauseparam(struct net_device *netdev,
+ struct ethtool_pauseparam *pause)
+{
+ struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+ struct pch_gbe_hw *hw = &adapter->hw;
+
+ pause->autoneg =
+ ((hw->mac.fc_autoneg) ? AUTONEG_ENABLE : AUTONEG_DISABLE);
+
+ if (hw->mac.fc == PCH_GBE_FC_RX_PAUSE) {
+ pause->rx_pause = 1;
+ } else if (hw->mac.fc == PCH_GBE_FC_TX_PAUSE) {
+ pause->tx_pause = 1;
+ } else if (hw->mac.fc == PCH_GBE_FC_FULL) {
+ pause->rx_pause = 1;
+ pause->tx_pause = 1;
+ }
+}
+
+/**
+ * pch_gbe_set_pauseparam - Set pause paramters
+ * @netdev: Network interface device structure
+ * @pause: Pause parameters structure
+ * Returns
+ * 0: Successful.
+ * Negative value: Failed.
+ */
+static int pch_gbe_set_pauseparam(struct net_device *netdev,
+ struct ethtool_pauseparam *pause)
+{
+ struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+ struct pch_gbe_hw *hw = &adapter->hw;
+ int ret = 0;
+
+ hw->mac.fc_autoneg = pause->autoneg;
+ if ((pause->rx_pause) && (pause->tx_pause))
+ hw->mac.fc = PCH_GBE_FC_FULL;
+ else if ((pause->rx_pause) && (!pause->tx_pause))
+ hw->mac.fc = PCH_GBE_FC_RX_PAUSE;
+ else if ((!pause->rx_pause) && (pause->tx_pause))
+ hw->mac.fc = PCH_GBE_FC_TX_PAUSE;
+ else if ((!pause->rx_pause) && (!pause->tx_pause))
+ hw->mac.fc = PCH_GBE_FC_NONE;
+
+ if (hw->mac.fc_autoneg == AUTONEG_ENABLE) {
+ if ((netif_running(adapter->netdev))) {
+ pch_gbe_down(adapter);
+ ret = pch_gbe_up(adapter);
+ } else {
+ pch_gbe_reset(adapter);
+ }
+ } else {
+ ret = pch_gbe_mac_force_mac_fc(hw);
+ }
+ return ret;
+}
+
+/**
+ * pch_gbe_get_rx_csum - Report whether receive checksums are turned on or off
+ * @netdev: Network interface device structure
+ * Returns
+ * true(1): Checksum On
+ * false(0): Checksum Off
+ */
+static u32 pch_gbe_get_rx_csum(struct net_device *netdev)
+{
+ struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+
+ return adapter->rx_csum;
+}
+
+/**
+ * pch_gbe_set_rx_csum - Turn receive checksum on or off
+ * @netdev: Network interface device structure
+ * @data: Checksum On[true] or Off[false]
+ * Returns
+ * 0: Successful.
+ * Negative value: Failed.
+ */
+static int pch_gbe_set_rx_csum(struct net_device *netdev, u32 data)
+{
+ struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+
+ adapter->rx_csum = data;
+ if ((netif_running(netdev)))
+ pch_gbe_reinit_locked(adapter);
+ else
+ pch_gbe_reset(adapter);
+
+ return 0;
+}
+
+/**
+ * pch_gbe_get_tx_csum - Report whether transmit checksums are turned on or off
+ * @netdev: Network interface device structure
+ * Returns
+ * true(1): Checksum On
+ * false(0): Checksum Off
+ */
+static u32 pch_gbe_get_tx_csum(struct net_device *netdev)
+{
+ return (netdev->features & NETIF_F_HW_CSUM) != 0;
+}
+
+/**
+ * pch_gbe_set_tx_csum - Turn transmit checksums on or off
+ * @netdev: Network interface device structure
+ * @data: Checksum on[true] or off[false]
+ * Returns
+ * 0: Successful.
+ * Negative value: Failed.
+ */
+static int pch_gbe_set_tx_csum(struct net_device *netdev, u32 data)
+{
+ struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+
+ adapter->tx_csum = data;
+ if (data)
+ netdev->features |= NETIF_F_HW_CSUM;
+ else
+ netdev->features &= ~NETIF_F_HW_CSUM;
+ return 0;
+}
+
+/**
+ * pch_gbe_get_strings - Return a set of strings that describe the requested
+ * objects
+ * @netdev: Network interface device structure
+ * @stringset: Select the stringset. [ETH_SS_TEST] [ETH_SS_STATS]
+ * @data: Pointer of read string data.
+ */
+static void pch_gbe_get_strings(struct net_device *netdev, u32 stringset,
+ u8 *data)
+{
+ u8 *p = data;
+ int i;
+
+ switch (stringset) {
+ case (u32) ETH_SS_STATS:
+ for (i = 0; i < PCH_GBE_GLOBAL_STATS_LEN; i++) {
+ memcpy(p, pch_gbe_gstrings_stats[i].string,
+ ETH_GSTRING_LEN);
+ p += ETH_GSTRING_LEN;
+ }
+ break;
+ }
+}
+
+/**
+ * pch_gbe_get_ethtool_stats - Return statistics about the device
+ * @netdev: Network interface device structure
+ * @stats: Ethtool statue structure
+ * @data: Pointer of read status area
+ */
+static void pch_gbe_get_ethtool_stats(struct net_device *netdev,
+ struct ethtool_stats *stats, u64 *data)
+{
+ struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+ int i;
+ const struct pch_gbe_stats *gstats = pch_gbe_gstrings_stats;
+ char *hw_stats = (char *)&adapter->stats;
+
+ pch_gbe_update_stats(adapter);
+ for (i = 0; i < PCH_GBE_GLOBAL_STATS_LEN; i++) {
+ char *p = hw_stats + gstats->offset;
+ data[i] = gstats->size == sizeof(u64) ? *(u64 *)p:(*(u32 *)p);
+ gstats++;
+ }
+}
+
+static int pch_gbe_get_sset_count(struct net_device *netdev, int sset)
+{
+ switch (sset) {
+ case ETH_SS_STATS:
+ return PCH_GBE_STATS_LEN;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static const struct ethtool_ops pch_gbe_ethtool_ops = {
+ .get_settings = pch_gbe_get_settings,
+ .set_settings = pch_gbe_set_settings,
+ .get_drvinfo = pch_gbe_get_drvinfo,
+ .get_regs_len = pch_gbe_get_regs_len,
+ .get_regs = pch_gbe_get_regs,
+ .get_wol = pch_gbe_get_wol,
+ .set_wol = pch_gbe_set_wol,
+ .nway_reset = pch_gbe_nway_reset,
+ .get_link = ethtool_op_get_link,
+ .get_ringparam = pch_gbe_get_ringparam,
+ .set_ringparam = pch_gbe_set_ringparam,
+ .get_pauseparam = pch_gbe_get_pauseparam,
+ .set_pauseparam = pch_gbe_set_pauseparam,
+ .get_rx_csum = pch_gbe_get_rx_csum,
+ .set_rx_csum = pch_gbe_set_rx_csum,
+ .get_tx_csum = pch_gbe_get_tx_csum,
+ .set_tx_csum = pch_gbe_set_tx_csum,
+ .get_strings = pch_gbe_get_strings,
+ .get_ethtool_stats = pch_gbe_get_ethtool_stats,
+ .get_sset_count = pch_gbe_get_sset_count,
+};
+
+void pch_gbe_set_ethtool_ops(struct net_device *netdev)
+{
+ SET_ETHTOOL_OPS(netdev, &pch_gbe_ethtool_ops);
+}
diff --git a/drivers/net/pch_gbe/pch_gbe_main.c b/drivers/net/pch_gbe/pch_gbe_main.c
new file mode 100644
index 000000000000..472056b47440
--- /dev/null
+++ b/drivers/net/pch_gbe/pch_gbe_main.c
@@ -0,0 +1,2477 @@
+/*
+ * Copyright (C) 1999 - 2010 Intel Corporation.
+ * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ *
+ * This code was derived from the Intel e1000e Linux driver.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "pch_gbe.h"
+#include "pch_gbe_api.h"
+
+#define DRV_VERSION "1.00"
+const char pch_driver_version[] = DRV_VERSION;
+
+#define PCI_DEVICE_ID_INTEL_IOH1_GBE 0x8802 /* Pci device ID */
+#define PCH_GBE_MAR_ENTRIES 16
+#define PCH_GBE_SHORT_PKT 64
+#define DSC_INIT16 0xC000
+#define PCH_GBE_DMA_ALIGN 0
+#define PCH_GBE_WATCHDOG_PERIOD (1 * HZ) /* watchdog time */
+#define PCH_GBE_COPYBREAK_DEFAULT 256
+#define PCH_GBE_PCI_BAR 1
+
+#define PCH_GBE_TX_WEIGHT 64
+#define PCH_GBE_RX_WEIGHT 64
+#define PCH_GBE_RX_BUFFER_WRITE 16
+
+/* Initialize the wake-on-LAN settings */
+#define PCH_GBE_WL_INIT_SETTING (PCH_GBE_WLC_MP)
+
+#define PCH_GBE_MAC_RGMII_CTRL_SETTING ( \
+ PCH_GBE_CHIP_TYPE_INTERNAL | \
+ PCH_GBE_RGMII_MODE_RGMII | \
+ PCH_GBE_CRS_SEL \
+ )
+
+/* Ethertype field values */
+#define PCH_GBE_MAX_JUMBO_FRAME_SIZE 10318
+#define PCH_GBE_FRAME_SIZE_2048 2048
+#define PCH_GBE_FRAME_SIZE_4096 4096
+#define PCH_GBE_FRAME_SIZE_8192 8192
+
+#define PCH_GBE_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i]))
+#define PCH_GBE_RX_DESC(R, i) PCH_GBE_GET_DESC(R, i, pch_gbe_rx_desc)
+#define PCH_GBE_TX_DESC(R, i) PCH_GBE_GET_DESC(R, i, pch_gbe_tx_desc)
+#define PCH_GBE_DESC_UNUSED(R) \
+ ((((R)->next_to_clean > (R)->next_to_use) ? 0 : (R)->count) + \
+ (R)->next_to_clean - (R)->next_to_use - 1)
+
+/* Pause packet value */
+#define PCH_GBE_PAUSE_PKT1_VALUE 0x00C28001
+#define PCH_GBE_PAUSE_PKT2_VALUE 0x00000100
+#define PCH_GBE_PAUSE_PKT4_VALUE 0x01000888
+#define PCH_GBE_PAUSE_PKT5_VALUE 0x0000FFFF
+
+#define PCH_GBE_ETH_ALEN 6
+
+/* This defines the bits that are set in the Interrupt Mask
+ * Set/Read Register. Each bit is documented below:
+ * o RXT0 = Receiver Timer Interrupt (ring 0)
+ * o TXDW = Transmit Descriptor Written Back
+ * o RXDMT0 = Receive Descriptor Minimum Threshold hit (ring 0)
+ * o RXSEQ = Receive Sequence Error
+ * o LSC = Link Status Change
+ */
+#define PCH_GBE_INT_ENABLE_MASK ( \
+ PCH_GBE_INT_RX_DMA_CMPLT | \
+ PCH_GBE_INT_RX_DSC_EMP | \
+ PCH_GBE_INT_WOL_DET | \
+ PCH_GBE_INT_TX_CMPLT \
+ )
+
+
+static unsigned int copybreak __read_mostly = PCH_GBE_COPYBREAK_DEFAULT;
+
+static int pch_gbe_mdio_read(struct net_device *netdev, int addr, int reg);
+static void pch_gbe_mdio_write(struct net_device *netdev, int addr, int reg,
+ int data);
+/**
+ * pch_gbe_mac_read_mac_addr - Read MAC address
+ * @hw: Pointer to the HW structure
+ * Returns
+ * 0: Successful.
+ */
+s32 pch_gbe_mac_read_mac_addr(struct pch_gbe_hw *hw)
+{
+ u32 adr1a, adr1b;
+
+ adr1a = ioread32(&hw->reg->mac_adr[0].high);
+ adr1b = ioread32(&hw->reg->mac_adr[0].low);
+
+ hw->mac.addr[0] = (u8)(adr1a & 0xFF);
+ hw->mac.addr[1] = (u8)((adr1a >> 8) & 0xFF);
+ hw->mac.addr[2] = (u8)((adr1a >> 16) & 0xFF);
+ hw->mac.addr[3] = (u8)((adr1a >> 24) & 0xFF);
+ hw->mac.addr[4] = (u8)(adr1b & 0xFF);
+ hw->mac.addr[5] = (u8)((adr1b >> 8) & 0xFF);
+
+ pr_debug("hw->mac.addr : %pM\n", hw->mac.addr);
+ return 0;
+}
+
+/**
+ * pch_gbe_wait_clr_bit - Wait to clear a bit
+ * @reg: Pointer of register
+ * @busy: Busy bit
+ */
+static void pch_gbe_wait_clr_bit(void *reg, u32 bit)
+{
+ u32 tmp;
+ /* wait busy */
+ tmp = 1000;
+ while ((ioread32(reg) & bit) && --tmp)
+ cpu_relax();
+ if (!tmp)
+ pr_err("Error: busy bit is not cleared\n");
+}
+/**
+ * pch_gbe_mac_mar_set - Set MAC address register
+ * @hw: Pointer to the HW structure
+ * @addr: Pointer to the MAC address
+ * @index: MAC address array register
+ */
+static void pch_gbe_mac_mar_set(struct pch_gbe_hw *hw, u8 * addr, u32 index)
+{
+ u32 mar_low, mar_high, adrmask;
+
+ pr_debug("index : 0x%x\n", index);
+
+ /*
+ * HW expects these in little endian so we reverse the byte order
+ * from network order (big endian) to little endian
+ */
+ mar_high = ((u32) addr[0] | ((u32) addr[1] << 8) |
+ ((u32) addr[2] << 16) | ((u32) addr[3] << 24));
+ mar_low = ((u32) addr[4] | ((u32) addr[5] << 8));
+ /* Stop the MAC Address of index. */
+ adrmask = ioread32(&hw->reg->ADDR_MASK);
+ iowrite32((adrmask | (0x0001 << index)), &hw->reg->ADDR_MASK);
+ /* wait busy */
+ pch_gbe_wait_clr_bit(&hw->reg->ADDR_MASK, PCH_GBE_BUSY);
+ /* Set the MAC address to the MAC address 1A/1B register */
+ iowrite32(mar_high, &hw->reg->mac_adr[index].high);
+ iowrite32(mar_low, &hw->reg->mac_adr[index].low);
+ /* Start the MAC address of index */
+ iowrite32((adrmask & ~(0x0001 << index)), &hw->reg->ADDR_MASK);
+ /* wait busy */
+ pch_gbe_wait_clr_bit(&hw->reg->ADDR_MASK, PCH_GBE_BUSY);
+}
+
+/**
+ * pch_gbe_mac_reset_hw - Reset hardware
+ * @hw: Pointer to the HW structure
+ */
+static void pch_gbe_mac_reset_hw(struct pch_gbe_hw *hw)
+{
+ /* Read the MAC address. and store to the private data */
+ pch_gbe_mac_read_mac_addr(hw);
+ iowrite32(PCH_GBE_ALL_RST, &hw->reg->RESET);
+#ifdef PCH_GBE_MAC_IFOP_RGMII
+ iowrite32(PCH_GBE_MODE_GMII_ETHER, &hw->reg->MODE);
+#endif
+ pch_gbe_wait_clr_bit(&hw->reg->RESET, PCH_GBE_ALL_RST);
+ /* Setup the receive address */
+ pch_gbe_mac_mar_set(hw, hw->mac.addr, 0);
+ return;
+}
+
+/**
+ * pch_gbe_mac_init_rx_addrs - Initialize receive address's
+ * @hw: Pointer to the HW structure
+ * @mar_count: Receive address registers
+ */
+static void pch_gbe_mac_init_rx_addrs(struct pch_gbe_hw *hw, u16 mar_count)
+{
+ u32 i;
+
+ /* Setup the receive address */
+ pch_gbe_mac_mar_set(hw, hw->mac.addr, 0);
+
+ /* Zero out the other receive addresses */
+ for (i = 1; i < mar_count; i++) {
+ iowrite32(0, &hw->reg->mac_adr[i].high);
+ iowrite32(0, &hw->reg->mac_adr[i].low);
+ }
+ iowrite32(0xFFFE, &hw->reg->ADDR_MASK);
+ /* wait busy */
+ pch_gbe_wait_clr_bit(&hw->reg->ADDR_MASK, PCH_GBE_BUSY);
+}
+
+
+/**
+ * pch_gbe_mac_mc_addr_list_update - Update Multicast addresses
+ * @hw: Pointer to the HW structure
+ * @mc_addr_list: Array of multicast addresses to program
+ * @mc_addr_count: Number of multicast addresses to program
+ * @mar_used_count: The first MAC Address register free to program
+ * @mar_total_num: Total number of supported MAC Address Registers
+ */
+static void pch_gbe_mac_mc_addr_list_update(struct pch_gbe_hw *hw,
+ u8 *mc_addr_list, u32 mc_addr_count,
+ u32 mar_used_count, u32 mar_total_num)
+{
+ u32 i, adrmask;
+
+ /* Load the first set of multicast addresses into the exact
+ * filters (RAR). If there are not enough to fill the RAR
+ * array, clear the filters.
+ */
+ for (i = mar_used_count; i < mar_total_num; i++) {
+ if (mc_addr_count) {
+ pch_gbe_mac_mar_set(hw, mc_addr_list, i);
+ mc_addr_count--;
+ mc_addr_list += PCH_GBE_ETH_ALEN;
+ } else {
+ /* Clear MAC address mask */
+ adrmask = ioread32(&hw->reg->ADDR_MASK);
+ iowrite32((adrmask | (0x0001 << i)),
+ &hw->reg->ADDR_MASK);
+ /* wait busy */
+ pch_gbe_wait_clr_bit(&hw->reg->ADDR_MASK, PCH_GBE_BUSY);
+ /* Clear MAC address */
+ iowrite32(0, &hw->reg->mac_adr[i].high);
+ iowrite32(0, &hw->reg->mac_adr[i].low);
+ }
+ }
+}
+
+/**
+ * pch_gbe_mac_force_mac_fc - Force the MAC's flow control settings
+ * @hw: Pointer to the HW structure
+ * Returns
+ * 0: Successful.
+ * Negative value: Failed.
+ */
+s32 pch_gbe_mac_force_mac_fc(struct pch_gbe_hw *hw)
+{
+ struct pch_gbe_mac_info *mac = &hw->mac;
+ u32 rx_fctrl;
+
+ pr_debug("mac->fc = %u\n", mac->fc);
+
+ rx_fctrl = ioread32(&hw->reg->RX_FCTRL);
+
+ switch (mac->fc) {
+ case PCH_GBE_FC_NONE:
+ rx_fctrl &= ~PCH_GBE_FL_CTRL_EN;
+ mac->tx_fc_enable = false;
+ break;
+ case PCH_GBE_FC_RX_PAUSE:
+ rx_fctrl |= PCH_GBE_FL_CTRL_EN;
+ mac->tx_fc_enable = false;
+ break;
+ case PCH_GBE_FC_TX_PAUSE:
+ rx_fctrl &= ~PCH_GBE_FL_CTRL_EN;
+ mac->tx_fc_enable = true;
+ break;
+ case PCH_GBE_FC_FULL:
+ rx_fctrl |= PCH_GBE_FL_CTRL_EN;
+ mac->tx_fc_enable = true;
+ break;
+ default:
+ pr_err("Flow control param set incorrectly\n");
+ return -EINVAL;
+ }
+ if (mac->link_duplex == DUPLEX_HALF)
+ rx_fctrl &= ~PCH_GBE_FL_CTRL_EN;
+ iowrite32(rx_fctrl, &hw->reg->RX_FCTRL);
+ pr_debug("RX_FCTRL reg : 0x%08x mac->tx_fc_enable : %d\n",
+ ioread32(&hw->reg->RX_FCTRL), mac->tx_fc_enable);
+ return 0;
+}
+
+/**
+ * pch_gbe_mac_set_wol_event - Set wake-on-lan event
+ * @hw: Pointer to the HW structure
+ * @wu_evt: Wake up event
+ */
+static void pch_gbe_mac_set_wol_event(struct pch_gbe_hw *hw, u32 wu_evt)
+{
+ u32 addr_mask;
+
+ pr_debug("wu_evt : 0x%08x ADDR_MASK reg : 0x%08x\n",
+ wu_evt, ioread32(&hw->reg->ADDR_MASK));
+
+ if (wu_evt) {
+ /* Set Wake-On-Lan address mask */
+ addr_mask = ioread32(&hw->reg->ADDR_MASK);
+ iowrite32(addr_mask, &hw->reg->WOL_ADDR_MASK);
+ /* wait busy */
+ pch_gbe_wait_clr_bit(&hw->reg->WOL_ADDR_MASK, PCH_GBE_WLA_BUSY);
+ iowrite32(0, &hw->reg->WOL_ST);
+ iowrite32((wu_evt | PCH_GBE_WLC_WOL_MODE), &hw->reg->WOL_CTRL);
+ iowrite32(0x02, &hw->reg->TCPIP_ACC);
+ iowrite32(PCH_GBE_INT_ENABLE_MASK, &hw->reg->INT_EN);
+ } else {
+ iowrite32(0, &hw->reg->WOL_CTRL);
+ iowrite32(0, &hw->reg->WOL_ST);
+ }
+ return;
+}
+
+/**
+ * pch_gbe_mac_ctrl_miim - Control MIIM interface
+ * @hw: Pointer to the HW structure
+ * @addr: Address of PHY
+ * @dir: Operetion. (Write or Read)
+ * @reg: Access register of PHY
+ * @data: Write data.
+ *
+ * Returns: Read date.
+ */
+u16 pch_gbe_mac_ctrl_miim(struct pch_gbe_hw *hw, u32 addr, u32 dir, u32 reg,
+ u16 data)
+{
+ u32 data_out = 0;
+ unsigned int i;
+ unsigned long flags;
+
+ spin_lock_irqsave(&hw->miim_lock, flags);
+
+ for (i = 100; i; --i) {
+ if ((ioread32(&hw->reg->MIIM) & PCH_GBE_MIIM_OPER_READY))
+ break;
+ udelay(20);
+ }
+ if (i == 0) {
+ pr_err("pch-gbe.miim won't go Ready\n");
+ spin_unlock_irqrestore(&hw->miim_lock, flags);
+ return 0; /* No way to indicate timeout error */
+ }
+ iowrite32(((reg << PCH_GBE_MIIM_REG_ADDR_SHIFT) |
+ (addr << PCH_GBE_MIIM_PHY_ADDR_SHIFT) |
+ dir | data), &hw->reg->MIIM);
+ for (i = 0; i < 100; i++) {
+ udelay(20);
+ data_out = ioread32(&hw->reg->MIIM);
+ if ((data_out & PCH_GBE_MIIM_OPER_READY))
+ break;
+ }
+ spin_unlock_irqrestore(&hw->miim_lock, flags);
+
+ pr_debug("PHY %s: reg=%d, data=0x%04X\n",
+ dir == PCH_GBE_MIIM_OPER_READ ? "READ" : "WRITE", reg,
+ dir == PCH_GBE_MIIM_OPER_READ ? data_out : data);
+ return (u16) data_out;
+}
+
+/**
+ * pch_gbe_mac_set_pause_packet - Set pause packet
+ * @hw: Pointer to the HW structure
+ */
+static void pch_gbe_mac_set_pause_packet(struct pch_gbe_hw *hw)
+{
+ unsigned long tmp2, tmp3;
+
+ /* Set Pause packet */
+ tmp2 = hw->mac.addr[1];
+ tmp2 = (tmp2 << 8) | hw->mac.addr[0];
+ tmp2 = PCH_GBE_PAUSE_PKT2_VALUE | (tmp2 << 16);
+
+ tmp3 = hw->mac.addr[5];
+ tmp3 = (tmp3 << 8) | hw->mac.addr[4];
+ tmp3 = (tmp3 << 8) | hw->mac.addr[3];
+ tmp3 = (tmp3 << 8) | hw->mac.addr[2];
+
+ iowrite32(PCH_GBE_PAUSE_PKT1_VALUE, &hw->reg->PAUSE_PKT1);
+ iowrite32(tmp2, &hw->reg->PAUSE_PKT2);
+ iowrite32(tmp3, &hw->reg->PAUSE_PKT3);
+ iowrite32(PCH_GBE_PAUSE_PKT4_VALUE, &hw->reg->PAUSE_PKT4);
+ iowrite32(PCH_GBE_PAUSE_PKT5_VALUE, &hw->reg->PAUSE_PKT5);
+
+ /* Transmit Pause Packet */
+ iowrite32(PCH_GBE_PS_PKT_RQ, &hw->reg->PAUSE_REQ);
+
+ pr_debug("PAUSE_PKT1-5 reg : 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
+ ioread32(&hw->reg->PAUSE_PKT1), ioread32(&hw->reg->PAUSE_PKT2),
+ ioread32(&hw->reg->PAUSE_PKT3), ioread32(&hw->reg->PAUSE_PKT4),
+ ioread32(&hw->reg->PAUSE_PKT5));
+
+ return;
+}
+
+
+/**
+ * pch_gbe_alloc_queues - Allocate memory for all rings
+ * @adapter: Board private structure to initialize
+ * Returns
+ * 0: Successfully
+ * Negative value: Failed
+ */
+static int pch_gbe_alloc_queues(struct pch_gbe_adapter *adapter)
+{
+ int size;
+
+ size = (int)sizeof(struct pch_gbe_tx_ring);
+ adapter->tx_ring = kzalloc(size, GFP_KERNEL);
+ if (!adapter->tx_ring)
+ return -ENOMEM;
+ size = (int)sizeof(struct pch_gbe_rx_ring);
+ adapter->rx_ring = kzalloc(size, GFP_KERNEL);
+ if (!adapter->rx_ring) {
+ kfree(adapter->tx_ring);
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+/**
+ * pch_gbe_init_stats - Initialize status
+ * @adapter: Board private structure to initialize
+ */
+static void pch_gbe_init_stats(struct pch_gbe_adapter *adapter)
+{
+ memset(&adapter->stats, 0, sizeof(adapter->stats));
+ return;
+}
+
+/**
+ * pch_gbe_init_phy - Initialize PHY
+ * @adapter: Board private structure to initialize
+ * Returns
+ * 0: Successfully
+ * Negative value: Failed
+ */
+static int pch_gbe_init_phy(struct pch_gbe_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+ u32 addr;
+ u16 bmcr, stat;
+
+ /* Discover phy addr by searching addrs in order {1,0,2,..., 31} */
+ for (addr = 0; addr < PCH_GBE_PHY_REGS_LEN; addr++) {
+ adapter->mii.phy_id = (addr == 0) ? 1 : (addr == 1) ? 0 : addr;
+ bmcr = pch_gbe_mdio_read(netdev, adapter->mii.phy_id, MII_BMCR);
+ stat = pch_gbe_mdio_read(netdev, adapter->mii.phy_id, MII_BMSR);
+ stat = pch_gbe_mdio_read(netdev, adapter->mii.phy_id, MII_BMSR);
+ if (!((bmcr == 0xFFFF) || ((stat == 0) && (bmcr == 0))))
+ break;
+ }
+ adapter->hw.phy.addr = adapter->mii.phy_id;
+ pr_debug("phy_addr = %d\n", adapter->mii.phy_id);
+ if (addr == 32)
+ return -EAGAIN;
+ /* Selected the phy and isolate the rest */
+ for (addr = 0; addr < PCH_GBE_PHY_REGS_LEN; addr++) {
+ if (addr != adapter->mii.phy_id) {
+ pch_gbe_mdio_write(netdev, addr, MII_BMCR,
+ BMCR_ISOLATE);
+ } else {
+ bmcr = pch_gbe_mdio_read(netdev, addr, MII_BMCR);
+ pch_gbe_mdio_write(netdev, addr, MII_BMCR,
+ bmcr & ~BMCR_ISOLATE);
+ }
+ }
+
+ /* MII setup */
+ adapter->mii.phy_id_mask = 0x1F;
+ adapter->mii.reg_num_mask = 0x1F;
+ adapter->mii.dev = adapter->netdev;
+ adapter->mii.mdio_read = pch_gbe_mdio_read;
+ adapter->mii.mdio_write = pch_gbe_mdio_write;
+ adapter->mii.supports_gmii = mii_check_gmii_support(&adapter->mii);
+ return 0;
+}
+
+/**
+ * pch_gbe_mdio_read - The read function for mii
+ * @netdev: Network interface device structure
+ * @addr: Phy ID
+ * @reg: Access location
+ * Returns
+ * 0: Successfully
+ * Negative value: Failed
+ */
+static int pch_gbe_mdio_read(struct net_device *netdev, int addr, int reg)
+{
+ struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+ struct pch_gbe_hw *hw = &adapter->hw;
+
+ return pch_gbe_mac_ctrl_miim(hw, addr, PCH_GBE_HAL_MIIM_READ, reg,
+ (u16) 0);
+}
+
+/**
+ * pch_gbe_mdio_write - The write function for mii
+ * @netdev: Network interface device structure
+ * @addr: Phy ID (not used)
+ * @reg: Access location
+ * @data: Write data
+ */
+static void pch_gbe_mdio_write(struct net_device *netdev,
+ int addr, int reg, int data)
+{
+ struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+ struct pch_gbe_hw *hw = &adapter->hw;
+
+ pch_gbe_mac_ctrl_miim(hw, addr, PCH_GBE_HAL_MIIM_WRITE, reg, data);
+}
+
+/**
+ * pch_gbe_reset_task - Reset processing at the time of transmission timeout
+ * @work: Pointer of board private structure
+ */
+static void pch_gbe_reset_task(struct work_struct *work)
+{
+ struct pch_gbe_adapter *adapter;
+ adapter = container_of(work, struct pch_gbe_adapter, reset_task);
+
+ pch_gbe_reinit_locked(adapter);
+}
+
+/**
+ * pch_gbe_reinit_locked- Re-initialization
+ * @adapter: Board private structure
+ */
+void pch_gbe_reinit_locked(struct pch_gbe_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+
+ rtnl_lock();
+ if (netif_running(netdev)) {
+ pch_gbe_down(adapter);
+ pch_gbe_up(adapter);
+ }
+ rtnl_unlock();
+}
+
+/**
+ * pch_gbe_reset - Reset GbE
+ * @adapter: Board private structure
+ */
+void pch_gbe_reset(struct pch_gbe_adapter *adapter)
+{
+ pch_gbe_mac_reset_hw(&adapter->hw);
+ /* Setup the receive address. */
+ pch_gbe_mac_init_rx_addrs(&adapter->hw, PCH_GBE_MAR_ENTRIES);
+ if (pch_gbe_hal_init_hw(&adapter->hw))
+ pr_err("Hardware Error\n");
+}
+
+/**
+ * pch_gbe_free_irq - Free an interrupt
+ * @adapter: Board private structure
+ */
+static void pch_gbe_free_irq(struct pch_gbe_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+
+ free_irq(adapter->pdev->irq, netdev);
+ if (adapter->have_msi) {
+ pci_disable_msi(adapter->pdev);
+ pr_debug("call pci_disable_msi\n");
+ }
+}
+
+/**
+ * pch_gbe_irq_disable - Mask off interrupt generation on the NIC
+ * @adapter: Board private structure
+ */
+static void pch_gbe_irq_disable(struct pch_gbe_adapter *adapter)
+{
+ struct pch_gbe_hw *hw = &adapter->hw;
+
+ atomic_inc(&adapter->irq_sem);
+ iowrite32(0, &hw->reg->INT_EN);
+ ioread32(&hw->reg->INT_ST);
+ synchronize_irq(adapter->pdev->irq);
+
+ pr_debug("INT_EN reg : 0x%08x\n", ioread32(&hw->reg->INT_EN));
+}
+
+/**
+ * pch_gbe_irq_enable - Enable default interrupt generation settings
+ * @adapter: Board private structure
+ */
+static void pch_gbe_irq_enable(struct pch_gbe_adapter *adapter)
+{
+ struct pch_gbe_hw *hw = &adapter->hw;
+
+ if (likely(atomic_dec_and_test(&adapter->irq_sem)))
+ iowrite32(PCH_GBE_INT_ENABLE_MASK, &hw->reg->INT_EN);
+ ioread32(&hw->reg->INT_ST);
+ pr_debug("INT_EN reg : 0x%08x\n", ioread32(&hw->reg->INT_EN));
+}
+
+
+
+/**
+ * pch_gbe_setup_tctl - configure the Transmit control registers
+ * @adapter: Board private structure
+ */
+static void pch_gbe_setup_tctl(struct pch_gbe_adapter *adapter)
+{
+ struct pch_gbe_hw *hw = &adapter->hw;
+ u32 tx_mode, tcpip;
+
+ tx_mode = PCH_GBE_TM_LONG_PKT |
+ PCH_GBE_TM_ST_AND_FD |
+ PCH_GBE_TM_SHORT_PKT |
+ PCH_GBE_TM_TH_TX_STRT_8 |
+ PCH_GBE_TM_TH_ALM_EMP_4 | PCH_GBE_TM_TH_ALM_FULL_8;
+
+ iowrite32(tx_mode, &hw->reg->TX_MODE);
+
+ tcpip = ioread32(&hw->reg->TCPIP_ACC);
+ tcpip |= PCH_GBE_TX_TCPIPACC_EN;
+ iowrite32(tcpip, &hw->reg->TCPIP_ACC);
+ return;
+}
+
+/**
+ * pch_gbe_configure_tx - Configure Transmit Unit after Reset
+ * @adapter: Board private structure
+ */
+static void pch_gbe_configure_tx(struct pch_gbe_adapter *adapter)
+{
+ struct pch_gbe_hw *hw = &adapter->hw;
+ u32 tdba, tdlen, dctrl;
+
+ pr_debug("dma addr = 0x%08llx size = 0x%08x\n",
+ (unsigned long long)adapter->tx_ring->dma,
+ adapter->tx_ring->size);
+
+ /* Setup the HW Tx Head and Tail descriptor pointers */
+ tdba = adapter->tx_ring->dma;
+ tdlen = adapter->tx_ring->size - 0x10;
+ iowrite32(tdba, &hw->reg->TX_DSC_BASE);
+ iowrite32(tdlen, &hw->reg->TX_DSC_SIZE);
+ iowrite32(tdba, &hw->reg->TX_DSC_SW_P);
+
+ /* Enables Transmission DMA */
+ dctrl = ioread32(&hw->reg->DMA_CTRL);
+ dctrl |= PCH_GBE_TX_DMA_EN;
+ iowrite32(dctrl, &hw->reg->DMA_CTRL);
+}
+
+/**
+ * pch_gbe_setup_rctl - Configure the receive control registers
+ * @adapter: Board private structure
+ */
+static void pch_gbe_setup_rctl(struct pch_gbe_adapter *adapter)
+{
+ struct pch_gbe_hw *hw = &adapter->hw;
+ u32 rx_mode, tcpip;
+
+ rx_mode = PCH_GBE_ADD_FIL_EN | PCH_GBE_MLT_FIL_EN |
+ PCH_GBE_RH_ALM_EMP_4 | PCH_GBE_RH_ALM_FULL_4 | PCH_GBE_RH_RD_TRG_8;
+
+ iowrite32(rx_mode, &hw->reg->RX_MODE);
+
+ tcpip = ioread32(&hw->reg->TCPIP_ACC);
+
+ if (adapter->rx_csum) {
+ tcpip &= ~PCH_GBE_RX_TCPIPACC_OFF;
+ tcpip |= PCH_GBE_RX_TCPIPACC_EN;
+ } else {
+ tcpip |= PCH_GBE_RX_TCPIPACC_OFF;
+ tcpip &= ~PCH_GBE_RX_TCPIPACC_EN;
+ }
+ iowrite32(tcpip, &hw->reg->TCPIP_ACC);
+ return;
+}
+
+/**
+ * pch_gbe_configure_rx - Configure Receive Unit after Reset
+ * @adapter: Board private structure
+ */
+static void pch_gbe_configure_rx(struct pch_gbe_adapter *adapter)
+{
+ struct pch_gbe_hw *hw = &adapter->hw;
+ u32 rdba, rdlen, rctl, rxdma;
+
+ pr_debug("dma adr = 0x%08llx size = 0x%08x\n",
+ (unsigned long long)adapter->rx_ring->dma,
+ adapter->rx_ring->size);
+
+ pch_gbe_mac_force_mac_fc(hw);
+
+ /* Disables Receive MAC */
+ rctl = ioread32(&hw->reg->MAC_RX_EN);
+ iowrite32((rctl & ~PCH_GBE_MRE_MAC_RX_EN), &hw->reg->MAC_RX_EN);
+
+ /* Disables Receive DMA */
+ rxdma = ioread32(&hw->reg->DMA_CTRL);
+ rxdma &= ~PCH_GBE_RX_DMA_EN;
+ iowrite32(rxdma, &hw->reg->DMA_CTRL);
+
+ pr_debug("MAC_RX_EN reg = 0x%08x DMA_CTRL reg = 0x%08x\n",
+ ioread32(&hw->reg->MAC_RX_EN),
+ ioread32(&hw->reg->DMA_CTRL));
+
+ /* Setup the HW Rx Head and Tail Descriptor Pointers and
+ * the Base and Length of the Rx Descriptor Ring */
+ rdba = adapter->rx_ring->dma;
+ rdlen = adapter->rx_ring->size - 0x10;
+ iowrite32(rdba, &hw->reg->RX_DSC_BASE);
+ iowrite32(rdlen, &hw->reg->RX_DSC_SIZE);
+ iowrite32((rdba + rdlen), &hw->reg->RX_DSC_SW_P);
+
+ /* Enables Receive DMA */
+ rxdma = ioread32(&hw->reg->DMA_CTRL);
+ rxdma |= PCH_GBE_RX_DMA_EN;
+ iowrite32(rxdma, &hw->reg->DMA_CTRL);
+ /* Enables Receive */
+ iowrite32(PCH_GBE_MRE_MAC_RX_EN, &hw->reg->MAC_RX_EN);
+}
+
+/**
+ * pch_gbe_unmap_and_free_tx_resource - Unmap and free tx socket buffer
+ * @adapter: Board private structure
+ * @buffer_info: Buffer information structure
+ */
+static void pch_gbe_unmap_and_free_tx_resource(
+ struct pch_gbe_adapter *adapter, struct pch_gbe_buffer *buffer_info)
+{
+ if (buffer_info->mapped) {
+ dma_unmap_single(&adapter->pdev->dev, buffer_info->dma,
+ buffer_info->length, DMA_TO_DEVICE);
+ buffer_info->mapped = false;
+ }
+ if (buffer_info->skb) {
+ dev_kfree_skb_any(buffer_info->skb);
+ buffer_info->skb = NULL;
+ }
+}
+
+/**
+ * pch_gbe_unmap_and_free_rx_resource - Unmap and free rx socket buffer
+ * @adapter: Board private structure
+ * @buffer_info: Buffer information structure
+ */
+static void pch_gbe_unmap_and_free_rx_resource(
+ struct pch_gbe_adapter *adapter,
+ struct pch_gbe_buffer *buffer_info)
+{
+ if (buffer_info->mapped) {
+ dma_unmap_single(&adapter->pdev->dev, buffer_info->dma,
+ buffer_info->length, DMA_FROM_DEVICE);
+ buffer_info->mapped = false;
+ }
+ if (buffer_info->skb) {
+ dev_kfree_skb_any(buffer_info->skb);
+ buffer_info->skb = NULL;
+ }
+}
+
+/**
+ * pch_gbe_clean_tx_ring - Free Tx Buffers
+ * @adapter: Board private structure
+ * @tx_ring: Ring to be cleaned
+ */
+static void pch_gbe_clean_tx_ring(struct pch_gbe_adapter *adapter,
+ struct pch_gbe_tx_ring *tx_ring)
+{
+ struct pch_gbe_hw *hw = &adapter->hw;
+ struct pch_gbe_buffer *buffer_info;
+ unsigned long size;
+ unsigned int i;
+
+ /* Free all the Tx ring sk_buffs */
+ for (i = 0; i < tx_ring->count; i++) {
+ buffer_info = &tx_ring->buffer_info[i];
+ pch_gbe_unmap_and_free_tx_resource(adapter, buffer_info);
+ }
+ pr_debug("call pch_gbe_unmap_and_free_tx_resource() %d count\n", i);
+
+ size = (unsigned long)sizeof(struct pch_gbe_buffer) * tx_ring->count;
+ memset(tx_ring->buffer_info, 0, size);
+
+ /* Zero out the descriptor ring */
+ memset(tx_ring->desc, 0, tx_ring->size);
+ tx_ring->next_to_use = 0;
+ tx_ring->next_to_clean = 0;
+ iowrite32(tx_ring->dma, &hw->reg->TX_DSC_HW_P);
+ iowrite32((tx_ring->size - 0x10), &hw->reg->TX_DSC_SIZE);
+}
+
+/**
+ * pch_gbe_clean_rx_ring - Free Rx Buffers
+ * @adapter: Board private structure
+ * @rx_ring: Ring to free buffers from
+ */
+static void
+pch_gbe_clean_rx_ring(struct pch_gbe_adapter *adapter,
+ struct pch_gbe_rx_ring *rx_ring)
+{
+ struct pch_gbe_hw *hw = &adapter->hw;
+ struct pch_gbe_buffer *buffer_info;
+ unsigned long size;
+ unsigned int i;
+
+ /* Free all the Rx ring sk_buffs */
+ for (i = 0; i < rx_ring->count; i++) {
+ buffer_info = &rx_ring->buffer_info[i];
+ pch_gbe_unmap_and_free_rx_resource(adapter, buffer_info);
+ }
+ pr_debug("call pch_gbe_unmap_and_free_rx_resource() %d count\n", i);
+ size = (unsigned long)sizeof(struct pch_gbe_buffer) * rx_ring->count;
+ memset(rx_ring->buffer_info, 0, size);
+
+ /* Zero out the descriptor ring */
+ memset(rx_ring->desc, 0, rx_ring->size);
+ rx_ring->next_to_clean = 0;
+ rx_ring->next_to_use = 0;
+ iowrite32(rx_ring->dma, &hw->reg->RX_DSC_HW_P);
+ iowrite32((rx_ring->size - 0x10), &hw->reg->RX_DSC_SIZE);
+}
+
+static void pch_gbe_set_rgmii_ctrl(struct pch_gbe_adapter *adapter, u16 speed,
+ u16 duplex)
+{
+ struct pch_gbe_hw *hw = &adapter->hw;
+ unsigned long rgmii = 0;
+
+ /* Set the RGMII control. */
+#ifdef PCH_GBE_MAC_IFOP_RGMII
+ switch (speed) {
+ case SPEED_10:
+ rgmii = (PCH_GBE_RGMII_RATE_2_5M |
+ PCH_GBE_MAC_RGMII_CTRL_SETTING);
+ break;
+ case SPEED_100:
+ rgmii = (PCH_GBE_RGMII_RATE_25M |
+ PCH_GBE_MAC_RGMII_CTRL_SETTING);
+ break;
+ case SPEED_1000:
+ rgmii = (PCH_GBE_RGMII_RATE_125M |
+ PCH_GBE_MAC_RGMII_CTRL_SETTING);
+ break;
+ }
+ iowrite32(rgmii, &hw->reg->RGMII_CTRL);
+#else /* GMII */
+ rgmii = 0;
+ iowrite32(rgmii, &hw->reg->RGMII_CTRL);
+#endif
+}
+static void pch_gbe_set_mode(struct pch_gbe_adapter *adapter, u16 speed,
+ u16 duplex)
+{
+ struct net_device *netdev = adapter->netdev;
+ struct pch_gbe_hw *hw = &adapter->hw;
+ unsigned long mode = 0;
+
+ /* Set the communication mode */
+ switch (speed) {
+ case SPEED_10:
+ mode = PCH_GBE_MODE_MII_ETHER;
+ netdev->tx_queue_len = 10;
+ break;
+ case SPEED_100:
+ mode = PCH_GBE_MODE_MII_ETHER;
+ netdev->tx_queue_len = 100;
+ break;
+ case SPEED_1000:
+ mode = PCH_GBE_MODE_GMII_ETHER;
+ break;
+ }
+ if (duplex == DUPLEX_FULL)
+ mode |= PCH_GBE_MODE_FULL_DUPLEX;
+ else
+ mode |= PCH_GBE_MODE_HALF_DUPLEX;
+ iowrite32(mode, &hw->reg->MODE);
+}
+
+/**
+ * pch_gbe_watchdog - Watchdog process
+ * @data: Board private structure
+ */
+static void pch_gbe_watchdog(unsigned long data)
+{
+ struct pch_gbe_adapter *adapter = (struct pch_gbe_adapter *)data;
+ struct net_device *netdev = adapter->netdev;
+ struct pch_gbe_hw *hw = &adapter->hw;
+ struct ethtool_cmd cmd;
+
+ pr_debug("right now = %ld\n", jiffies);
+
+ pch_gbe_update_stats(adapter);
+ if ((mii_link_ok(&adapter->mii)) && (!netif_carrier_ok(netdev))) {
+ netdev->tx_queue_len = adapter->tx_queue_len;
+ /* mii library handles link maintenance tasks */
+ if (mii_ethtool_gset(&adapter->mii, &cmd)) {
+ pr_err("ethtool get setting Error\n");
+ mod_timer(&adapter->watchdog_timer,
+ round_jiffies(jiffies +
+ PCH_GBE_WATCHDOG_PERIOD));
+ return;
+ }
+ hw->mac.link_speed = cmd.speed;
+ hw->mac.link_duplex = cmd.duplex;
+ /* Set the RGMII control. */
+ pch_gbe_set_rgmii_ctrl(adapter, hw->mac.link_speed,
+ hw->mac.link_duplex);
+ /* Set the communication mode */
+ pch_gbe_set_mode(adapter, hw->mac.link_speed,
+ hw->mac.link_duplex);
+ netdev_dbg(netdev,
+ "Link is Up %d Mbps %s-Duplex\n",
+ cmd.speed,
+ cmd.duplex == DUPLEX_FULL ? "Full" : "Half");
+ netif_carrier_on(netdev);
+ netif_wake_queue(netdev);
+ } else if ((!mii_link_ok(&adapter->mii)) &&
+ (netif_carrier_ok(netdev))) {
+ netdev_dbg(netdev, "NIC Link is Down\n");
+ hw->mac.link_speed = SPEED_10;
+ hw->mac.link_duplex = DUPLEX_HALF;
+ netif_carrier_off(netdev);
+ netif_stop_queue(netdev);
+ }
+ mod_timer(&adapter->watchdog_timer,
+ round_jiffies(jiffies + PCH_GBE_WATCHDOG_PERIOD));
+}
+
+/**
+ * pch_gbe_tx_queue - Carry out queuing of the transmission data
+ * @adapter: Board private structure
+ * @tx_ring: Tx descriptor ring structure
+ * @skb: Sockt buffer structure
+ */
+static void pch_gbe_tx_queue(struct pch_gbe_adapter *adapter,
+ struct pch_gbe_tx_ring *tx_ring,
+ struct sk_buff *skb)
+{
+ struct pch_gbe_hw *hw = &adapter->hw;
+ struct pch_gbe_tx_desc *tx_desc;
+ struct pch_gbe_buffer *buffer_info;
+ struct sk_buff *tmp_skb;
+ unsigned int frame_ctrl;
+ unsigned int ring_num;
+ unsigned long flags;
+
+ /*-- Set frame control --*/
+ frame_ctrl = 0;
+ if (unlikely(skb->len < PCH_GBE_SHORT_PKT))
+ frame_ctrl |= PCH_GBE_TXD_CTRL_APAD;
+ if (unlikely(!adapter->tx_csum))
+ frame_ctrl |= PCH_GBE_TXD_CTRL_TCPIP_ACC_OFF;
+
+ /* Performs checksum processing */
+ /*
+ * It is because the hardware accelerator does not support a checksum,
+ * when the received data size is less than 64 bytes.
+ */
+ if ((skb->len < PCH_GBE_SHORT_PKT) && (adapter->tx_csum)) {
+ frame_ctrl |= PCH_GBE_TXD_CTRL_APAD |
+ PCH_GBE_TXD_CTRL_TCPIP_ACC_OFF;
+ if (skb->protocol == htons(ETH_P_IP)) {
+ struct iphdr *iph = ip_hdr(skb);
+ unsigned int offset;
+ iph->check = 0;
+ iph->check = ip_fast_csum((u8 *) iph, iph->ihl);
+ offset = skb_transport_offset(skb);
+ if (iph->protocol == IPPROTO_TCP) {
+ skb->csum = 0;
+ tcp_hdr(skb)->check = 0;
+ skb->csum = skb_checksum(skb, offset,
+ skb->len - offset, 0);
+ tcp_hdr(skb)->check =
+ csum_tcpudp_magic(iph->saddr,
+ iph->daddr,
+ skb->len - offset,
+ IPPROTO_TCP,
+ skb->csum);
+ } else if (iph->protocol == IPPROTO_UDP) {
+ skb->csum = 0;
+ udp_hdr(skb)->check = 0;
+ skb->csum =
+ skb_checksum(skb, offset,
+ skb->len - offset, 0);
+ udp_hdr(skb)->check =
+ csum_tcpudp_magic(iph->saddr,
+ iph->daddr,
+ skb->len - offset,
+ IPPROTO_UDP,
+ skb->csum);
+ }
+ }
+ }
+ spin_lock_irqsave(&tx_ring->tx_lock, flags);
+ ring_num = tx_ring->next_to_use;
+ if (unlikely((ring_num + 1) == tx_ring->count))
+ tx_ring->next_to_use = 0;
+ else
+ tx_ring->next_to_use = ring_num + 1;
+
+ spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
+ buffer_info = &tx_ring->buffer_info[ring_num];
+ tmp_skb = buffer_info->skb;
+
+ /* [Header:14][payload] ---> [Header:14][paddong:2][payload] */
+ memcpy(tmp_skb->data, skb->data, ETH_HLEN);
+ tmp_skb->data[ETH_HLEN] = 0x00;
+ tmp_skb->data[ETH_HLEN + 1] = 0x00;
+ tmp_skb->len = skb->len;
+ memcpy(&tmp_skb->data[ETH_HLEN + 2], &skb->data[ETH_HLEN],
+ (skb->len - ETH_HLEN));
+ /*-- Set Buffer infomation --*/
+ buffer_info->length = tmp_skb->len;
+ buffer_info->dma = dma_map_single(&adapter->pdev->dev, tmp_skb->data,
+ buffer_info->length,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(&adapter->pdev->dev, buffer_info->dma)) {
+ pr_err("TX DMA map failed\n");
+ buffer_info->dma = 0;
+ buffer_info->time_stamp = 0;
+ tx_ring->next_to_use = ring_num;
+ return;
+ }
+ buffer_info->mapped = true;
+ buffer_info->time_stamp = jiffies;
+
+ /*-- Set Tx descriptor --*/
+ tx_desc = PCH_GBE_TX_DESC(*tx_ring, ring_num);
+ tx_desc->buffer_addr = (buffer_info->dma);
+ tx_desc->length = (tmp_skb->len);
+ tx_desc->tx_words_eob = ((tmp_skb->len + 3));
+ tx_desc->tx_frame_ctrl = (frame_ctrl);
+ tx_desc->gbec_status = (DSC_INIT16);
+
+ if (unlikely(++ring_num == tx_ring->count))
+ ring_num = 0;
+
+ /* Update software pointer of TX descriptor */
+ iowrite32(tx_ring->dma +
+ (int)sizeof(struct pch_gbe_tx_desc) * ring_num,
+ &hw->reg->TX_DSC_SW_P);
+ dev_kfree_skb_any(skb);
+}
+
+/**
+ * pch_gbe_update_stats - Update the board statistics counters
+ * @adapter: Board private structure
+ */
+void pch_gbe_update_stats(struct pch_gbe_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+ struct pci_dev *pdev = adapter->pdev;
+ struct pch_gbe_hw_stats *stats = &adapter->stats;
+ unsigned long flags;
+
+ /*
+ * Prevent stats update while adapter is being reset, or if the pci
+ * connection is down.
+ */
+ if ((pdev->error_state) && (pdev->error_state != pci_channel_io_normal))
+ return;
+
+ spin_lock_irqsave(&adapter->stats_lock, flags);
+
+ /* Update device status "adapter->stats" */
+ stats->rx_errors = stats->rx_crc_errors + stats->rx_frame_errors;
+ stats->tx_errors = stats->tx_length_errors +
+ stats->tx_aborted_errors +
+ stats->tx_carrier_errors + stats->tx_timeout_count;
+
+ /* Update network device status "adapter->net_stats" */
+ netdev->stats.rx_packets = stats->rx_packets;
+ netdev->stats.rx_bytes = stats->rx_bytes;
+ netdev->stats.rx_dropped = stats->rx_dropped;
+ netdev->stats.tx_packets = stats->tx_packets;
+ netdev->stats.tx_bytes = stats->tx_bytes;
+ netdev->stats.tx_dropped = stats->tx_dropped;
+ /* Fill out the OS statistics structure */
+ netdev->stats.multicast = stats->multicast;
+ netdev->stats.collisions = stats->collisions;
+ /* Rx Errors */
+ netdev->stats.rx_errors = stats->rx_errors;
+ netdev->stats.rx_crc_errors = stats->rx_crc_errors;
+ netdev->stats.rx_frame_errors = stats->rx_frame_errors;
+ /* Tx Errors */
+ netdev->stats.tx_errors = stats->tx_errors;
+ netdev->stats.tx_aborted_errors = stats->tx_aborted_errors;
+ netdev->stats.tx_carrier_errors = stats->tx_carrier_errors;
+
+ spin_unlock_irqrestore(&adapter->stats_lock, flags);
+}
+
+/**
+ * pch_gbe_intr - Interrupt Handler
+ * @irq: Interrupt number
+ * @data: Pointer to a network interface device structure
+ * Returns
+ * - IRQ_HANDLED: Our interrupt
+ * - IRQ_NONE: Not our interrupt
+ */
+static irqreturn_t pch_gbe_intr(int irq, void *data)
+{
+ struct net_device *netdev = data;
+ struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+ struct pch_gbe_hw *hw = &adapter->hw;
+ u32 int_st;
+ u32 int_en;
+
+ /* Check request status */
+ int_st = ioread32(&hw->reg->INT_ST);
+ int_st = int_st & ioread32(&hw->reg->INT_EN);
+ /* When request status is no interruption factor */
+ if (unlikely(!int_st))
+ return IRQ_NONE; /* Not our interrupt. End processing. */
+ pr_debug("%s occur int_st = 0x%08x\n", __func__, int_st);
+ if (int_st & PCH_GBE_INT_RX_FRAME_ERR)
+ adapter->stats.intr_rx_frame_err_count++;
+ if (int_st & PCH_GBE_INT_RX_FIFO_ERR)
+ adapter->stats.intr_rx_fifo_err_count++;
+ if (int_st & PCH_GBE_INT_RX_DMA_ERR)
+ adapter->stats.intr_rx_dma_err_count++;
+ if (int_st & PCH_GBE_INT_TX_FIFO_ERR)
+ adapter->stats.intr_tx_fifo_err_count++;
+ if (int_st & PCH_GBE_INT_TX_DMA_ERR)
+ adapter->stats.intr_tx_dma_err_count++;
+ if (int_st & PCH_GBE_INT_TCPIP_ERR)
+ adapter->stats.intr_tcpip_err_count++;
+ /* When Rx descriptor is empty */
+ if ((int_st & PCH_GBE_INT_RX_DSC_EMP)) {
+ adapter->stats.intr_rx_dsc_empty_count++;
+ pr_err("Rx descriptor is empty\n");
+ int_en = ioread32(&hw->reg->INT_EN);
+ iowrite32((int_en & ~PCH_GBE_INT_RX_DSC_EMP), &hw->reg->INT_EN);
+ if (hw->mac.tx_fc_enable) {
+ /* Set Pause packet */
+ pch_gbe_mac_set_pause_packet(hw);
+ }
+ if ((int_en & (PCH_GBE_INT_RX_DMA_CMPLT | PCH_GBE_INT_TX_CMPLT))
+ == 0) {
+ return IRQ_HANDLED;
+ }
+ }
+
+ /* When request status is Receive interruption */
+ if ((int_st & (PCH_GBE_INT_RX_DMA_CMPLT | PCH_GBE_INT_TX_CMPLT))) {
+ if (likely(napi_schedule_prep(&adapter->napi))) {
+ /* Enable only Rx Descriptor empty */
+ atomic_inc(&adapter->irq_sem);
+ int_en = ioread32(&hw->reg->INT_EN);
+ int_en &=
+ ~(PCH_GBE_INT_RX_DMA_CMPLT | PCH_GBE_INT_TX_CMPLT);
+ iowrite32(int_en, &hw->reg->INT_EN);
+ /* Start polling for NAPI */
+ __napi_schedule(&adapter->napi);
+ }
+ }
+ pr_debug("return = 0x%08x INT_EN reg = 0x%08x\n",
+ IRQ_HANDLED, ioread32(&hw->reg->INT_EN));
+ return IRQ_HANDLED;
+}
+
+/**
+ * pch_gbe_alloc_rx_buffers - Replace used receive buffers; legacy & extended
+ * @adapter: Board private structure
+ * @rx_ring: Rx descriptor ring
+ * @cleaned_count: Cleaned count
+ */
+static void
+pch_gbe_alloc_rx_buffers(struct pch_gbe_adapter *adapter,
+ struct pch_gbe_rx_ring *rx_ring, int cleaned_count)
+{
+ struct net_device *netdev = adapter->netdev;
+ struct pci_dev *pdev = adapter->pdev;
+ struct pch_gbe_hw *hw = &adapter->hw;
+ struct pch_gbe_rx_desc *rx_desc;
+ struct pch_gbe_buffer *buffer_info;
+ struct sk_buff *skb;
+ unsigned int i;
+ unsigned int bufsz;
+
+ bufsz = adapter->rx_buffer_len + PCH_GBE_DMA_ALIGN;
+ i = rx_ring->next_to_use;
+
+ while ((cleaned_count--)) {
+ buffer_info = &rx_ring->buffer_info[i];
+ skb = buffer_info->skb;
+ if (skb) {
+ skb_trim(skb, 0);
+ } else {
+ skb = netdev_alloc_skb(netdev, bufsz);
+ if (unlikely(!skb)) {
+ /* Better luck next round */
+ adapter->stats.rx_alloc_buff_failed++;
+ break;
+ }
+ /* 64byte align */
+ skb_reserve(skb, PCH_GBE_DMA_ALIGN);
+
+ buffer_info->skb = skb;
+ buffer_info->length = adapter->rx_buffer_len;
+ }
+ buffer_info->dma = dma_map_single(&pdev->dev,
+ skb->data,
+ buffer_info->length,
+ DMA_FROM_DEVICE);
+ if (dma_mapping_error(&adapter->pdev->dev, buffer_info->dma)) {
+ dev_kfree_skb(skb);
+ buffer_info->skb = NULL;
+ buffer_info->dma = 0;
+ adapter->stats.rx_alloc_buff_failed++;
+ break; /* while !buffer_info->skb */
+ }
+ buffer_info->mapped = true;
+ rx_desc = PCH_GBE_RX_DESC(*rx_ring, i);
+ rx_desc->buffer_addr = (buffer_info->dma);
+ rx_desc->gbec_status = DSC_INIT16;
+
+ pr_debug("i = %d buffer_info->dma = 0x08%llx buffer_info->length = 0x%x\n",
+ i, (unsigned long long)buffer_info->dma,
+ buffer_info->length);
+
+ if (unlikely(++i == rx_ring->count))
+ i = 0;
+ }
+ if (likely(rx_ring->next_to_use != i)) {
+ rx_ring->next_to_use = i;
+ if (unlikely(i-- == 0))
+ i = (rx_ring->count - 1);
+ iowrite32(rx_ring->dma +
+ (int)sizeof(struct pch_gbe_rx_desc) * i,
+ &hw->reg->RX_DSC_SW_P);
+ }
+ return;
+}
+
+/**
+ * pch_gbe_alloc_tx_buffers - Allocate transmit buffers
+ * @adapter: Board private structure
+ * @tx_ring: Tx descriptor ring
+ */
+static void pch_gbe_alloc_tx_buffers(struct pch_gbe_adapter *adapter,
+ struct pch_gbe_tx_ring *tx_ring)
+{
+ struct pch_gbe_buffer *buffer_info;
+ struct sk_buff *skb;
+ unsigned int i;
+ unsigned int bufsz;
+ struct pch_gbe_tx_desc *tx_desc;
+
+ bufsz =
+ adapter->hw.mac.max_frame_size + PCH_GBE_DMA_ALIGN + NET_IP_ALIGN;
+
+ for (i = 0; i < tx_ring->count; i++) {
+ buffer_info = &tx_ring->buffer_info[i];
+ skb = netdev_alloc_skb(adapter->netdev, bufsz);
+ skb_reserve(skb, PCH_GBE_DMA_ALIGN);
+ buffer_info->skb = skb;
+ tx_desc = PCH_GBE_TX_DESC(*tx_ring, i);
+ tx_desc->gbec_status = (DSC_INIT16);
+ }
+ return;
+}
+
+/**
+ * pch_gbe_clean_tx - Reclaim resources after transmit completes
+ * @adapter: Board private structure
+ * @tx_ring: Tx descriptor ring
+ * Returns
+ * true: Cleaned the descriptor
+ * false: Not cleaned the descriptor
+ */
+static bool
+pch_gbe_clean_tx(struct pch_gbe_adapter *adapter,
+ struct pch_gbe_tx_ring *tx_ring)
+{
+ struct pch_gbe_tx_desc *tx_desc;
+ struct pch_gbe_buffer *buffer_info;
+ struct sk_buff *skb;
+ unsigned int i;
+ unsigned int cleaned_count = 0;
+ bool cleaned = false;
+
+ pr_debug("next_to_clean : %d\n", tx_ring->next_to_clean);
+
+ i = tx_ring->next_to_clean;
+ tx_desc = PCH_GBE_TX_DESC(*tx_ring, i);
+ pr_debug("gbec_status:0x%04x dma_status:0x%04x\n",
+ tx_desc->gbec_status, tx_desc->dma_status);
+
+ while ((tx_desc->gbec_status & DSC_INIT16) == 0x0000) {
+ pr_debug("gbec_status:0x%04x\n", tx_desc->gbec_status);
+ cleaned = true;
+ buffer_info = &tx_ring->buffer_info[i];
+ skb = buffer_info->skb;
+
+ if ((tx_desc->gbec_status & PCH_GBE_TXD_GMAC_STAT_ABT)) {
+ adapter->stats.tx_aborted_errors++;
+ pr_err("Transfer Abort Error\n");
+ } else if ((tx_desc->gbec_status & PCH_GBE_TXD_GMAC_STAT_CRSER)
+ ) {
+ adapter->stats.tx_carrier_errors++;
+ pr_err("Transfer Carrier Sense Error\n");
+ } else if ((tx_desc->gbec_status & PCH_GBE_TXD_GMAC_STAT_EXCOL)
+ ) {
+ adapter->stats.tx_aborted_errors++;
+ pr_err("Transfer Collision Abort Error\n");
+ } else if ((tx_desc->gbec_status &
+ (PCH_GBE_TXD_GMAC_STAT_SNGCOL |
+ PCH_GBE_TXD_GMAC_STAT_MLTCOL))) {
+ adapter->stats.collisions++;
+ adapter->stats.tx_packets++;
+ adapter->stats.tx_bytes += skb->len;
+ pr_debug("Transfer Collision\n");
+ } else if ((tx_desc->gbec_status & PCH_GBE_TXD_GMAC_STAT_CMPLT)
+ ) {
+ adapter->stats.tx_packets++;
+ adapter->stats.tx_bytes += skb->len;
+ }
+ if (buffer_info->mapped) {
+ pr_debug("unmap buffer_info->dma : %d\n", i);
+ dma_unmap_single(&adapter->pdev->dev, buffer_info->dma,
+ buffer_info->length, DMA_TO_DEVICE);
+ buffer_info->mapped = false;
+ }
+ if (buffer_info->skb) {
+ pr_debug("trim buffer_info->skb : %d\n", i);
+ skb_trim(buffer_info->skb, 0);
+ }
+ tx_desc->gbec_status = DSC_INIT16;
+ if (unlikely(++i == tx_ring->count))
+ i = 0;
+ tx_desc = PCH_GBE_TX_DESC(*tx_ring, i);
+
+ /* weight of a sort for tx, to avoid endless transmit cleanup */
+ if (cleaned_count++ == PCH_GBE_TX_WEIGHT)
+ break;
+ }
+ pr_debug("called pch_gbe_unmap_and_free_tx_resource() %d count\n",
+ cleaned_count);
+ /* Recover from running out of Tx resources in xmit_frame */
+ if (unlikely(cleaned && (netif_queue_stopped(adapter->netdev)))) {
+ netif_wake_queue(adapter->netdev);
+ adapter->stats.tx_restart_count++;
+ pr_debug("Tx wake queue\n");
+ }
+ spin_lock(&adapter->tx_queue_lock);
+ tx_ring->next_to_clean = i;
+ spin_unlock(&adapter->tx_queue_lock);
+ pr_debug("next_to_clean : %d\n", tx_ring->next_to_clean);
+ return cleaned;
+}
+
+/**
+ * pch_gbe_clean_rx - Send received data up the network stack; legacy
+ * @adapter: Board private structure
+ * @rx_ring: Rx descriptor ring
+ * @work_done: Completed count
+ * @work_to_do: Request count
+ * Returns
+ * true: Cleaned the descriptor
+ * false: Not cleaned the descriptor
+ */
+static bool
+pch_gbe_clean_rx(struct pch_gbe_adapter *adapter,
+ struct pch_gbe_rx_ring *rx_ring,
+ int *work_done, int work_to_do)
+{
+ struct net_device *netdev = adapter->netdev;
+ struct pci_dev *pdev = adapter->pdev;
+ struct pch_gbe_buffer *buffer_info;
+ struct pch_gbe_rx_desc *rx_desc;
+ u32 length;
+ unsigned char tmp_packet[ETH_HLEN];
+ unsigned int i;
+ unsigned int cleaned_count = 0;
+ bool cleaned = false;
+ struct sk_buff *skb;
+ u8 dma_status;
+ u16 gbec_status;
+ u32 tcp_ip_status;
+ u8 skb_copy_flag = 0;
+ u8 skb_padding_flag = 0;
+
+ i = rx_ring->next_to_clean;
+
+ while (*work_done < work_to_do) {
+ /* Check Rx descriptor status */
+ rx_desc = PCH_GBE_RX_DESC(*rx_ring, i);
+ if (rx_desc->gbec_status == DSC_INIT16)
+ break;
+ cleaned = true;
+ cleaned_count++;
+
+ dma_status = rx_desc->dma_status;
+ gbec_status = rx_desc->gbec_status;
+ tcp_ip_status = rx_desc->tcp_ip_status;
+ rx_desc->gbec_status = DSC_INIT16;
+ buffer_info = &rx_ring->buffer_info[i];
+ skb = buffer_info->skb;
+
+ /* unmap dma */
+ dma_unmap_single(&pdev->dev, buffer_info->dma,
+ buffer_info->length, DMA_FROM_DEVICE);
+ buffer_info->mapped = false;
+ /* Prefetch the packet */
+ prefetch(skb->data);
+
+ pr_debug("RxDecNo = 0x%04x Status[DMA:0x%02x GBE:0x%04x "
+ "TCP:0x%08x] BufInf = 0x%p\n",
+ i, dma_status, gbec_status, tcp_ip_status,
+ buffer_info);
+ /* Error check */
+ if (unlikely(gbec_status & PCH_GBE_RXD_GMAC_STAT_NOTOCTAL)) {
+ adapter->stats.rx_frame_errors++;
+ pr_err("Receive Not Octal Error\n");
+ } else if (unlikely(gbec_status &
+ PCH_GBE_RXD_GMAC_STAT_NBLERR)) {
+ adapter->stats.rx_frame_errors++;
+ pr_err("Receive Nibble Error\n");
+ } else if (unlikely(gbec_status &
+ PCH_GBE_RXD_GMAC_STAT_CRCERR)) {
+ adapter->stats.rx_crc_errors++;
+ pr_err("Receive CRC Error\n");
+ } else {
+ /* get receive length */
+ /* length convert[-3], padding[-2] */
+ length = (rx_desc->rx_words_eob) - 3 - 2;
+
+ /* Decide the data conversion method */
+ if (!adapter->rx_csum) {
+ /* [Header:14][payload] */
+ skb_padding_flag = 0;
+ skb_copy_flag = 1;
+ } else {
+ /* [Header:14][padding:2][payload] */
+ skb_padding_flag = 1;
+ if (length < copybreak)
+ skb_copy_flag = 1;
+ else
+ skb_copy_flag = 0;
+ }
+
+ /* Data conversion */
+ if (skb_copy_flag) { /* recycle skb */
+ struct sk_buff *new_skb;
+ new_skb =
+ netdev_alloc_skb(netdev,
+ length + NET_IP_ALIGN);
+ if (new_skb) {
+ if (!skb_padding_flag) {
+ skb_reserve(new_skb,
+ NET_IP_ALIGN);
+ }
+ memcpy(new_skb->data, skb->data,
+ length);
+ /* save the skb
+ * in buffer_info as good */
+ skb = new_skb;
+ } else if (!skb_padding_flag) {
+ /* dorrop error */
+ pr_err("New skb allocation Error\n");
+ goto dorrop;
+ }
+ } else {
+ buffer_info->skb = NULL;
+ }
+ if (skb_padding_flag) {
+ memcpy(&tmp_packet[0], &skb->data[0], ETH_HLEN);
+ memcpy(&skb->data[NET_IP_ALIGN], &tmp_packet[0],
+ ETH_HLEN);
+ skb_reserve(skb, NET_IP_ALIGN);
+
+ }
+
+ /* update status of driver */
+ adapter->stats.rx_bytes += length;
+ adapter->stats.rx_packets++;
+ if ((gbec_status & PCH_GBE_RXD_GMAC_STAT_MARMLT))
+ adapter->stats.multicast++;
+ /* Write meta date of skb */
+ skb_put(skb, length);
+ skb->protocol = eth_type_trans(skb, netdev);
+ if ((tcp_ip_status & PCH_GBE_RXD_ACC_STAT_TCPIPOK) ==
+ PCH_GBE_RXD_ACC_STAT_TCPIPOK) {
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ } else {
+ skb->ip_summed = CHECKSUM_NONE;
+ }
+ napi_gro_receive(&adapter->napi, skb);
+ (*work_done)++;
+ pr_debug("Receive skb->ip_summed: %d length: %d\n",
+ skb->ip_summed, length);
+ }
+dorrop:
+ /* return some buffers to hardware, one at a time is too slow */
+ if (unlikely(cleaned_count >= PCH_GBE_RX_BUFFER_WRITE)) {
+ pch_gbe_alloc_rx_buffers(adapter, rx_ring,
+ cleaned_count);
+ cleaned_count = 0;
+ }
+ if (++i == rx_ring->count)
+ i = 0;
+ }
+ rx_ring->next_to_clean = i;
+ if (cleaned_count)
+ pch_gbe_alloc_rx_buffers(adapter, rx_ring, cleaned_count);
+ return cleaned;
+}
+
+/**
+ * pch_gbe_setup_tx_resources - Allocate Tx resources (Descriptors)
+ * @adapter: Board private structure
+ * @tx_ring: Tx descriptor ring (for a specific queue) to setup
+ * Returns
+ * 0: Successfully
+ * Negative value: Failed
+ */
+int pch_gbe_setup_tx_resources(struct pch_gbe_adapter *adapter,
+ struct pch_gbe_tx_ring *tx_ring)
+{
+ struct pci_dev *pdev = adapter->pdev;
+ struct pch_gbe_tx_desc *tx_desc;
+ int size;
+ int desNo;
+
+ size = (int)sizeof(struct pch_gbe_buffer) * tx_ring->count;
+ tx_ring->buffer_info = vmalloc(size);
+ if (!tx_ring->buffer_info) {
+ pr_err("Unable to allocate memory for the buffer infomation\n");
+ return -ENOMEM;
+ }
+ memset(tx_ring->buffer_info, 0, size);
+
+ tx_ring->size = tx_ring->count * (int)sizeof(struct pch_gbe_tx_desc);
+
+ tx_ring->desc = dma_alloc_coherent(&pdev->dev, tx_ring->size,
+ &tx_ring->dma, GFP_KERNEL);
+ if (!tx_ring->desc) {
+ vfree(tx_ring->buffer_info);
+ pr_err("Unable to allocate memory for the transmit descriptor ring\n");
+ return -ENOMEM;
+ }
+ memset(tx_ring->desc, 0, tx_ring->size);
+
+ tx_ring->next_to_use = 0;
+ tx_ring->next_to_clean = 0;
+ spin_lock_init(&tx_ring->tx_lock);
+
+ for (desNo = 0; desNo < tx_ring->count; desNo++) {
+ tx_desc = PCH_GBE_TX_DESC(*tx_ring, desNo);
+ tx_desc->gbec_status = DSC_INIT16;
+ }
+ pr_debug("tx_ring->desc = 0x%p tx_ring->dma = 0x%08llx\n"
+ "next_to_clean = 0x%08x next_to_use = 0x%08x\n",
+ tx_ring->desc, (unsigned long long)tx_ring->dma,
+ tx_ring->next_to_clean, tx_ring->next_to_use);
+ return 0;
+}
+
+/**
+ * pch_gbe_setup_rx_resources - Allocate Rx resources (Descriptors)
+ * @adapter: Board private structure
+ * @rx_ring: Rx descriptor ring (for a specific queue) to setup
+ * Returns
+ * 0: Successfully
+ * Negative value: Failed
+ */
+int pch_gbe_setup_rx_resources(struct pch_gbe_adapter *adapter,
+ struct pch_gbe_rx_ring *rx_ring)
+{
+ struct pci_dev *pdev = adapter->pdev;
+ struct pch_gbe_rx_desc *rx_desc;
+ int size;
+ int desNo;
+
+ size = (int)sizeof(struct pch_gbe_buffer) * rx_ring->count;
+ rx_ring->buffer_info = vmalloc(size);
+ if (!rx_ring->buffer_info) {
+ pr_err("Unable to allocate memory for the receive descriptor ring\n");
+ return -ENOMEM;
+ }
+ memset(rx_ring->buffer_info, 0, size);
+ rx_ring->size = rx_ring->count * (int)sizeof(struct pch_gbe_rx_desc);
+ rx_ring->desc = dma_alloc_coherent(&pdev->dev, rx_ring->size,
+ &rx_ring->dma, GFP_KERNEL);
+
+ if (!rx_ring->desc) {
+ pr_err("Unable to allocate memory for the receive descriptor ring\n");
+ vfree(rx_ring->buffer_info);
+ return -ENOMEM;
+ }
+ memset(rx_ring->desc, 0, rx_ring->size);
+ rx_ring->next_to_clean = 0;
+ rx_ring->next_to_use = 0;
+ for (desNo = 0; desNo < rx_ring->count; desNo++) {
+ rx_desc = PCH_GBE_RX_DESC(*rx_ring, desNo);
+ rx_desc->gbec_status = DSC_INIT16;
+ }
+ pr_debug("rx_ring->desc = 0x%p rx_ring->dma = 0x%08llx "
+ "next_to_clean = 0x%08x next_to_use = 0x%08x\n",
+ rx_ring->desc, (unsigned long long)rx_ring->dma,
+ rx_ring->next_to_clean, rx_ring->next_to_use);
+ return 0;
+}
+
+/**
+ * pch_gbe_free_tx_resources - Free Tx Resources
+ * @adapter: Board private structure
+ * @tx_ring: Tx descriptor ring for a specific queue
+ */
+void pch_gbe_free_tx_resources(struct pch_gbe_adapter *adapter,
+ struct pch_gbe_tx_ring *tx_ring)
+{
+ struct pci_dev *pdev = adapter->pdev;
+
+ pch_gbe_clean_tx_ring(adapter, tx_ring);
+ vfree(tx_ring->buffer_info);
+ tx_ring->buffer_info = NULL;
+ pci_free_consistent(pdev, tx_ring->size, tx_ring->desc, tx_ring->dma);
+ tx_ring->desc = NULL;
+}
+
+/**
+ * pch_gbe_free_rx_resources - Free Rx Resources
+ * @adapter: Board private structure
+ * @rx_ring: Ring to clean the resources from
+ */
+void pch_gbe_free_rx_resources(struct pch_gbe_adapter *adapter,
+ struct pch_gbe_rx_ring *rx_ring)
+{
+ struct pci_dev *pdev = adapter->pdev;
+
+ pch_gbe_clean_rx_ring(adapter, rx_ring);
+ vfree(rx_ring->buffer_info);
+ rx_ring->buffer_info = NULL;
+ pci_free_consistent(pdev, rx_ring->size, rx_ring->desc, rx_ring->dma);
+ rx_ring->desc = NULL;
+}
+
+/**
+ * pch_gbe_request_irq - Allocate an interrupt line
+ * @adapter: Board private structure
+ * Returns
+ * 0: Successfully
+ * Negative value: Failed
+ */
+static int pch_gbe_request_irq(struct pch_gbe_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+ int err;
+ int flags;
+
+ flags = IRQF_SHARED;
+ adapter->have_msi = false;
+ err = pci_enable_msi(adapter->pdev);
+ pr_debug("call pci_enable_msi\n");
+ if (err) {
+ pr_debug("call pci_enable_msi - Error: %d\n", err);
+ } else {
+ flags = 0;
+ adapter->have_msi = true;
+ }
+ err = request_irq(adapter->pdev->irq, &pch_gbe_intr,
+ flags, netdev->name, netdev);
+ if (err)
+ pr_err("Unable to allocate interrupt Error: %d\n", err);
+ pr_debug("adapter->have_msi : %d flags : 0x%04x return : 0x%04x\n",
+ adapter->have_msi, flags, err);
+ return err;
+}
+
+
+static void pch_gbe_set_multi(struct net_device *netdev);
+/**
+ * pch_gbe_up - Up GbE network device
+ * @adapter: Board private structure
+ * Returns
+ * 0: Successfully
+ * Negative value: Failed
+ */
+int pch_gbe_up(struct pch_gbe_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+ struct pch_gbe_tx_ring *tx_ring = adapter->tx_ring;
+ struct pch_gbe_rx_ring *rx_ring = adapter->rx_ring;
+ int err;
+
+ /* hardware has been reset, we need to reload some things */
+ pch_gbe_set_multi(netdev);
+
+ pch_gbe_setup_tctl(adapter);
+ pch_gbe_configure_tx(adapter);
+ pch_gbe_setup_rctl(adapter);
+ pch_gbe_configure_rx(adapter);
+
+ err = pch_gbe_request_irq(adapter);
+ if (err) {
+ pr_err("Error: can't bring device up\n");
+ return err;
+ }
+ pch_gbe_alloc_tx_buffers(adapter, tx_ring);
+ pch_gbe_alloc_rx_buffers(adapter, rx_ring, rx_ring->count);
+ adapter->tx_queue_len = netdev->tx_queue_len;
+
+ mod_timer(&adapter->watchdog_timer, jiffies);
+
+ napi_enable(&adapter->napi);
+ pch_gbe_irq_enable(adapter);
+ netif_start_queue(adapter->netdev);
+
+ return 0;
+}
+
+/**
+ * pch_gbe_down - Down GbE network device
+ * @adapter: Board private structure
+ */
+void pch_gbe_down(struct pch_gbe_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+
+ /* signal that we're down so the interrupt handler does not
+ * reschedule our watchdog timer */
+ napi_disable(&adapter->napi);
+ atomic_set(&adapter->irq_sem, 0);
+
+ pch_gbe_irq_disable(adapter);
+ pch_gbe_free_irq(adapter);
+
+ del_timer_sync(&adapter->watchdog_timer);
+
+ netdev->tx_queue_len = adapter->tx_queue_len;
+ netif_carrier_off(netdev);
+ netif_stop_queue(netdev);
+
+ pch_gbe_reset(adapter);
+ pch_gbe_clean_tx_ring(adapter, adapter->tx_ring);
+ pch_gbe_clean_rx_ring(adapter, adapter->rx_ring);
+}
+
+/**
+ * pch_gbe_sw_init - Initialize general software structures (struct pch_gbe_adapter)
+ * @adapter: Board private structure to initialize
+ * Returns
+ * 0: Successfully
+ * Negative value: Failed
+ */
+static int pch_gbe_sw_init(struct pch_gbe_adapter *adapter)
+{
+ struct pch_gbe_hw *hw = &adapter->hw;
+ struct net_device *netdev = adapter->netdev;
+
+ adapter->rx_buffer_len = PCH_GBE_FRAME_SIZE_2048;
+ hw->mac.max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
+ hw->mac.min_frame_size = ETH_ZLEN + ETH_FCS_LEN;
+
+ /* Initialize the hardware-specific values */
+ if (pch_gbe_hal_setup_init_funcs(hw)) {
+ pr_err("Hardware Initialization Failure\n");
+ return -EIO;
+ }
+ if (pch_gbe_alloc_queues(adapter)) {
+ pr_err("Unable to allocate memory for queues\n");
+ return -ENOMEM;
+ }
+ spin_lock_init(&adapter->hw.miim_lock);
+ spin_lock_init(&adapter->tx_queue_lock);
+ spin_lock_init(&adapter->stats_lock);
+ spin_lock_init(&adapter->ethtool_lock);
+ atomic_set(&adapter->irq_sem, 0);
+ pch_gbe_irq_disable(adapter);
+
+ pch_gbe_init_stats(adapter);
+
+ pr_debug("rx_buffer_len : %d mac.min_frame_size : %d mac.max_frame_size : %d\n",
+ (u32) adapter->rx_buffer_len,
+ hw->mac.min_frame_size, hw->mac.max_frame_size);
+ return 0;
+}
+
+/**
+ * pch_gbe_open - Called when a network interface is made active
+ * @netdev: Network interface device structure
+ * Returns
+ * 0: Successfully
+ * Negative value: Failed
+ */
+static int pch_gbe_open(struct net_device *netdev)
+{
+ struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+ struct pch_gbe_hw *hw = &adapter->hw;
+ int err;
+
+ /* allocate transmit descriptors */
+ err = pch_gbe_setup_tx_resources(adapter, adapter->tx_ring);
+ if (err)
+ goto err_setup_tx;
+ /* allocate receive descriptors */
+ err = pch_gbe_setup_rx_resources(adapter, adapter->rx_ring);
+ if (err)
+ goto err_setup_rx;
+ pch_gbe_hal_power_up_phy(hw);
+ err = pch_gbe_up(adapter);
+ if (err)
+ goto err_up;
+ pr_debug("Success End\n");
+ return 0;
+
+err_up:
+ if (!adapter->wake_up_evt)
+ pch_gbe_hal_power_down_phy(hw);
+ pch_gbe_free_rx_resources(adapter, adapter->rx_ring);
+err_setup_rx:
+ pch_gbe_free_tx_resources(adapter, adapter->tx_ring);
+err_setup_tx:
+ pch_gbe_reset(adapter);
+ pr_err("Error End\n");
+ return err;
+}
+
+/**
+ * pch_gbe_stop - Disables a network interface
+ * @netdev: Network interface device structure
+ * Returns
+ * 0: Successfully
+ */
+static int pch_gbe_stop(struct net_device *netdev)
+{
+ struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+ struct pch_gbe_hw *hw = &adapter->hw;
+
+ pch_gbe_down(adapter);
+ if (!adapter->wake_up_evt)
+ pch_gbe_hal_power_down_phy(hw);
+ pch_gbe_free_tx_resources(adapter, adapter->tx_ring);
+ pch_gbe_free_rx_resources(adapter, adapter->rx_ring);
+ return 0;
+}
+
+/**
+ * pch_gbe_xmit_frame - Packet transmitting start
+ * @skb: Socket buffer structure
+ * @netdev: Network interface device structure
+ * Returns
+ * - NETDEV_TX_OK: Normal end
+ * - NETDEV_TX_BUSY: Error end
+ */
+static int pch_gbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+{
+ struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+ struct pch_gbe_tx_ring *tx_ring = adapter->tx_ring;
+ unsigned long flags;
+
+ if (unlikely(skb->len > (adapter->hw.mac.max_frame_size - 4))) {
+ pr_err("Transfer length Error: skb len: %d > max: %d\n",
+ skb->len, adapter->hw.mac.max_frame_size);
+ dev_kfree_skb_any(skb);
+ adapter->stats.tx_length_errors++;
+ return NETDEV_TX_OK;
+ }
+ if (!spin_trylock_irqsave(&tx_ring->tx_lock, flags)) {
+ /* Collision - tell upper layer to requeue */
+ return NETDEV_TX_LOCKED;
+ }
+ if (unlikely(!PCH_GBE_DESC_UNUSED(tx_ring))) {
+ netif_stop_queue(netdev);
+ spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
+ pr_debug("Return : BUSY next_to use : 0x%08x next_to clean : 0x%08x\n",
+ tx_ring->next_to_use, tx_ring->next_to_clean);
+ return NETDEV_TX_BUSY;
+ }
+ spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
+
+ /* CRC,ITAG no support */
+ pch_gbe_tx_queue(adapter, tx_ring, skb);
+ return NETDEV_TX_OK;
+}
+
+/**
+ * pch_gbe_get_stats - Get System Network Statistics
+ * @netdev: Network interface device structure
+ * Returns: The current stats
+ */
+static struct net_device_stats *pch_gbe_get_stats(struct net_device *netdev)
+{
+ /* only return the current stats */
+ return &netdev->stats;
+}
+
+/**
+ * pch_gbe_set_multi - Multicast and Promiscuous mode set
+ * @netdev: Network interface device structure
+ */
+static void pch_gbe_set_multi(struct net_device *netdev)
+{
+ struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+ struct pch_gbe_hw *hw = &adapter->hw;
+ struct netdev_hw_addr *ha;
+ u8 *mta_list;
+ u32 rctl;
+ int i;
+ int mc_count;
+
+ pr_debug("netdev->flags : 0x%08x\n", netdev->flags);
+
+ /* Check for Promiscuous and All Multicast modes */
+ rctl = ioread32(&hw->reg->RX_MODE);
+ mc_count = netdev_mc_count(netdev);
+ if ((netdev->flags & IFF_PROMISC)) {
+ rctl &= ~PCH_GBE_ADD_FIL_EN;
+ rctl &= ~PCH_GBE_MLT_FIL_EN;
+ } else if ((netdev->flags & IFF_ALLMULTI)) {
+ /* all the multicasting receive permissions */
+ rctl |= PCH_GBE_ADD_FIL_EN;
+ rctl &= ~PCH_GBE_MLT_FIL_EN;
+ } else {
+ if (mc_count >= PCH_GBE_MAR_ENTRIES) {
+ /* all the multicasting receive permissions */
+ rctl |= PCH_GBE_ADD_FIL_EN;
+ rctl &= ~PCH_GBE_MLT_FIL_EN;
+ } else {
+ rctl |= (PCH_GBE_ADD_FIL_EN | PCH_GBE_MLT_FIL_EN);
+ }
+ }
+ iowrite32(rctl, &hw->reg->RX_MODE);
+
+ if (mc_count >= PCH_GBE_MAR_ENTRIES)
+ return;
+ mta_list = kmalloc(mc_count * ETH_ALEN, GFP_ATOMIC);
+ if (!mta_list)
+ return;
+
+ /* The shared function expects a packed array of only addresses. */
+ i = 0;
+ netdev_for_each_mc_addr(ha, netdev) {
+ if (i == mc_count)
+ break;
+ memcpy(mta_list + (i++ * ETH_ALEN), &ha->addr, ETH_ALEN);
+ }
+ pch_gbe_mac_mc_addr_list_update(hw, mta_list, i, 1,
+ PCH_GBE_MAR_ENTRIES);
+ kfree(mta_list);
+
+ pr_debug("RX_MODE reg(check bit31,30 ADD,MLT) : 0x%08x netdev->mc_count : 0x%08x\n",
+ ioread32(&hw->reg->RX_MODE), mc_count);
+}
+
+/**
+ * pch_gbe_set_mac - Change the Ethernet Address of the NIC
+ * @netdev: Network interface device structure
+ * @addr: Pointer to an address structure
+ * Returns
+ * 0: Successfully
+ * -EADDRNOTAVAIL: Failed
+ */
+static int pch_gbe_set_mac(struct net_device *netdev, void *addr)
+{
+ struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+ struct sockaddr *skaddr = addr;
+ int ret_val;
+
+ if (!is_valid_ether_addr(skaddr->sa_data)) {
+ ret_val = -EADDRNOTAVAIL;
+ } else {
+ memcpy(netdev->dev_addr, skaddr->sa_data, netdev->addr_len);
+ memcpy(adapter->hw.mac.addr, skaddr->sa_data, netdev->addr_len);
+ pch_gbe_mac_mar_set(&adapter->hw, adapter->hw.mac.addr, 0);
+ ret_val = 0;
+ }
+ pr_debug("ret_val : 0x%08x\n", ret_val);
+ pr_debug("dev_addr : %pM\n", netdev->dev_addr);
+ pr_debug("mac_addr : %pM\n", adapter->hw.mac.addr);
+ pr_debug("MAC_ADR1AB reg : 0x%08x 0x%08x\n",
+ ioread32(&adapter->hw.reg->mac_adr[0].high),
+ ioread32(&adapter->hw.reg->mac_adr[0].low));
+ return ret_val;
+}
+
+/**
+ * pch_gbe_change_mtu - Change the Maximum Transfer Unit
+ * @netdev: Network interface device structure
+ * @new_mtu: New value for maximum frame size
+ * Returns
+ * 0: Successfully
+ * -EINVAL: Failed
+ */
+static int pch_gbe_change_mtu(struct net_device *netdev, int new_mtu)
+{
+ struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+ int max_frame;
+
+ max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
+ if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) ||
+ (max_frame > PCH_GBE_MAX_JUMBO_FRAME_SIZE)) {
+ pr_err("Invalid MTU setting\n");
+ return -EINVAL;
+ }
+ if (max_frame <= PCH_GBE_FRAME_SIZE_2048)
+ adapter->rx_buffer_len = PCH_GBE_FRAME_SIZE_2048;
+ else if (max_frame <= PCH_GBE_FRAME_SIZE_4096)
+ adapter->rx_buffer_len = PCH_GBE_FRAME_SIZE_4096;
+ else if (max_frame <= PCH_GBE_FRAME_SIZE_8192)
+ adapter->rx_buffer_len = PCH_GBE_FRAME_SIZE_8192;
+ else
+ adapter->rx_buffer_len = PCH_GBE_MAX_JUMBO_FRAME_SIZE;
+ netdev->mtu = new_mtu;
+ adapter->hw.mac.max_frame_size = max_frame;
+
+ if (netif_running(netdev))
+ pch_gbe_reinit_locked(adapter);
+ else
+ pch_gbe_reset(adapter);
+
+ pr_debug("max_frame : %d rx_buffer_len : %d mtu : %d max_frame_size : %d\n",
+ max_frame, (u32) adapter->rx_buffer_len, netdev->mtu,
+ adapter->hw.mac.max_frame_size);
+ return 0;
+}
+
+/**
+ * pch_gbe_ioctl - Controls register through a MII interface
+ * @netdev: Network interface device structure
+ * @ifr: Pointer to ifr structure
+ * @cmd: Control command
+ * Returns
+ * 0: Successfully
+ * Negative value: Failed
+ */
+static int pch_gbe_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+ struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+
+ pr_debug("cmd : 0x%04x\n", cmd);
+
+ return generic_mii_ioctl(&adapter->mii, if_mii(ifr), cmd, NULL);
+}
+
+/**
+ * pch_gbe_tx_timeout - Respond to a Tx Hang
+ * @netdev: Network interface device structure
+ */
+static void pch_gbe_tx_timeout(struct net_device *netdev)
+{
+ struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+
+ /* Do the reset outside of interrupt context */
+ adapter->stats.tx_timeout_count++;
+ schedule_work(&adapter->reset_task);
+}
+
+/**
+ * pch_gbe_napi_poll - NAPI receive and transfer polling callback
+ * @napi: Pointer of polling device struct
+ * @budget: The maximum number of a packet
+ * Returns
+ * false: Exit the polling mode
+ * true: Continue the polling mode
+ */
+static int pch_gbe_napi_poll(struct napi_struct *napi, int budget)
+{
+ struct pch_gbe_adapter *adapter =
+ container_of(napi, struct pch_gbe_adapter, napi);
+ struct net_device *netdev = adapter->netdev;
+ int work_done = 0;
+ bool poll_end_flag = false;
+ bool cleaned = false;
+
+ pr_debug("budget : %d\n", budget);
+
+ /* Keep link state information with original netdev */
+ if (!netif_carrier_ok(netdev)) {
+ poll_end_flag = true;
+ } else {
+ cleaned = pch_gbe_clean_tx(adapter, adapter->tx_ring);
+ pch_gbe_clean_rx(adapter, adapter->rx_ring, &work_done, budget);
+
+ if (cleaned)
+ work_done = budget;
+ /* If no Tx and not enough Rx work done,
+ * exit the polling mode
+ */
+ if ((work_done < budget) || !netif_running(netdev))
+ poll_end_flag = true;
+ }
+
+ if (poll_end_flag) {
+ napi_complete(napi);
+ pch_gbe_irq_enable(adapter);
+ }
+
+ pr_debug("poll_end_flag : %d work_done : %d budget : %d\n",
+ poll_end_flag, work_done, budget);
+
+ return work_done;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/**
+ * pch_gbe_netpoll - Used by things like netconsole to send skbs
+ * @netdev: Network interface device structure
+ */
+static void pch_gbe_netpoll(struct net_device *netdev)
+{
+ struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+
+ disable_irq(adapter->pdev->irq);
+ pch_gbe_intr(adapter->pdev->irq, netdev);
+ enable_irq(adapter->pdev->irq);
+}
+#endif
+
+static const struct net_device_ops pch_gbe_netdev_ops = {
+ .ndo_open = pch_gbe_open,
+ .ndo_stop = pch_gbe_stop,
+ .ndo_start_xmit = pch_gbe_xmit_frame,
+ .ndo_get_stats = pch_gbe_get_stats,
+ .ndo_set_mac_address = pch_gbe_set_mac,
+ .ndo_tx_timeout = pch_gbe_tx_timeout,
+ .ndo_change_mtu = pch_gbe_change_mtu,
+ .ndo_do_ioctl = pch_gbe_ioctl,
+ .ndo_set_multicast_list = &pch_gbe_set_multi,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = pch_gbe_netpoll,
+#endif
+};
+
+static pci_ers_result_t pch_gbe_io_error_detected(struct pci_dev *pdev,
+ pci_channel_state_t state)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+
+ netif_device_detach(netdev);
+ if (netif_running(netdev))
+ pch_gbe_down(adapter);
+ pci_disable_device(pdev);
+ /* Request a slot slot reset. */
+ return PCI_ERS_RESULT_NEED_RESET;
+}
+
+static pci_ers_result_t pch_gbe_io_slot_reset(struct pci_dev *pdev)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+ struct pch_gbe_hw *hw = &adapter->hw;
+
+ if (pci_enable_device(pdev)) {
+ pr_err("Cannot re-enable PCI device after reset\n");
+ return PCI_ERS_RESULT_DISCONNECT;
+ }
+ pci_set_master(pdev);
+ pci_enable_wake(pdev, PCI_D0, 0);
+ pch_gbe_hal_power_up_phy(hw);
+ pch_gbe_reset(adapter);
+ /* Clear wake up status */
+ pch_gbe_mac_set_wol_event(hw, 0);
+
+ return PCI_ERS_RESULT_RECOVERED;
+}
+
+static void pch_gbe_io_resume(struct pci_dev *pdev)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+
+ if (netif_running(netdev)) {
+ if (pch_gbe_up(adapter)) {
+ pr_debug("can't bring device back up after reset\n");
+ return;
+ }
+ }
+ netif_device_attach(netdev);
+}
+
+static int __pch_gbe_suspend(struct pci_dev *pdev)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+ struct pch_gbe_hw *hw = &adapter->hw;
+ u32 wufc = adapter->wake_up_evt;
+ int retval = 0;
+
+ netif_device_detach(netdev);
+ if (netif_running(netdev))
+ pch_gbe_down(adapter);
+ if (wufc) {
+ pch_gbe_set_multi(netdev);
+ pch_gbe_setup_rctl(adapter);
+ pch_gbe_configure_rx(adapter);
+ pch_gbe_set_rgmii_ctrl(adapter, hw->mac.link_speed,
+ hw->mac.link_duplex);
+ pch_gbe_set_mode(adapter, hw->mac.link_speed,
+ hw->mac.link_duplex);
+ pch_gbe_mac_set_wol_event(hw, wufc);
+ pci_disable_device(pdev);
+ } else {
+ pch_gbe_hal_power_down_phy(hw);
+ pch_gbe_mac_set_wol_event(hw, wufc);
+ pci_disable_device(pdev);
+ }
+ return retval;
+}
+
+#ifdef CONFIG_PM
+static int pch_gbe_suspend(struct device *device)
+{
+ struct pci_dev *pdev = to_pci_dev(device);
+
+ return __pch_gbe_suspend(pdev);
+}
+
+static int pch_gbe_resume(struct device *device)
+{
+ struct pci_dev *pdev = to_pci_dev(device);
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+ struct pch_gbe_hw *hw = &adapter->hw;
+ u32 err;
+
+ err = pci_enable_device(pdev);
+ if (err) {
+ pr_err("Cannot enable PCI device from suspend\n");
+ return err;
+ }
+ pci_set_master(pdev);
+ pch_gbe_hal_power_up_phy(hw);
+ pch_gbe_reset(adapter);
+ /* Clear wake on lan control and status */
+ pch_gbe_mac_set_wol_event(hw, 0);
+
+ if (netif_running(netdev))
+ pch_gbe_up(adapter);
+ netif_device_attach(netdev);
+
+ return 0;
+}
+#endif /* CONFIG_PM */
+
+static void pch_gbe_shutdown(struct pci_dev *pdev)
+{
+ __pch_gbe_suspend(pdev);
+ if (system_state == SYSTEM_POWER_OFF) {
+ pci_wake_from_d3(pdev, true);
+ pci_set_power_state(pdev, PCI_D3hot);
+ }
+}
+
+static void pch_gbe_remove(struct pci_dev *pdev)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct pch_gbe_adapter *adapter = netdev_priv(netdev);
+
+ flush_scheduled_work();
+ unregister_netdev(netdev);
+
+ pch_gbe_hal_phy_hw_reset(&adapter->hw);
+
+ kfree(adapter->tx_ring);
+ kfree(adapter->rx_ring);
+
+ iounmap(adapter->hw.reg);
+ pci_release_regions(pdev);
+ free_netdev(netdev);
+ pci_disable_device(pdev);
+}
+
+static int pch_gbe_probe(struct pci_dev *pdev,
+ const struct pci_device_id *pci_id)
+{
+ struct net_device *netdev;
+ struct pch_gbe_adapter *adapter;
+ int ret;
+
+ ret = pci_enable_device(pdev);
+ if (ret)
+ return ret;
+
+ if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64))
+ || pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) {
+ ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+ if (ret) {
+ ret = pci_set_consistent_dma_mask(pdev,
+ DMA_BIT_MASK(32));
+ if (ret) {
+ dev_err(&pdev->dev, "ERR: No usable DMA "
+ "configuration, aborting\n");
+ goto err_disable_device;
+ }
+ }
+ }
+
+ ret = pci_request_regions(pdev, KBUILD_MODNAME);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "ERR: Can't reserve PCI I/O and memory resources\n");
+ goto err_disable_device;
+ }
+ pci_set_master(pdev);
+
+ netdev = alloc_etherdev((int)sizeof(struct pch_gbe_adapter));
+ if (!netdev) {
+ ret = -ENOMEM;
+ dev_err(&pdev->dev,
+ "ERR: Can't allocate and set up an Ethernet device\n");
+ goto err_release_pci;
+ }
+ SET_NETDEV_DEV(netdev, &pdev->dev);
+
+ pci_set_drvdata(pdev, netdev);
+ adapter = netdev_priv(netdev);
+ adapter->netdev = netdev;
+ adapter->pdev = pdev;
+ adapter->hw.back = adapter;
+ adapter->hw.reg = pci_iomap(pdev, PCH_GBE_PCI_BAR, 0);
+ if (!adapter->hw.reg) {
+ ret = -EIO;
+ dev_err(&pdev->dev, "Can't ioremap\n");
+ goto err_free_netdev;
+ }
+
+ netdev->netdev_ops = &pch_gbe_netdev_ops;
+ netdev->watchdog_timeo = PCH_GBE_WATCHDOG_PERIOD;
+ netif_napi_add(netdev, &adapter->napi,
+ pch_gbe_napi_poll, PCH_GBE_RX_WEIGHT);
+ netdev->features = NETIF_F_HW_CSUM | NETIF_F_GRO;
+ pch_gbe_set_ethtool_ops(netdev);
+
+ pch_gbe_mac_reset_hw(&adapter->hw);
+
+ /* setup the private structure */
+ ret = pch_gbe_sw_init(adapter);
+ if (ret)
+ goto err_iounmap;
+
+ /* Initialize PHY */
+ ret = pch_gbe_init_phy(adapter);
+ if (ret) {
+ dev_err(&pdev->dev, "PHY initialize error\n");
+ goto err_free_adapter;
+ }
+ pch_gbe_hal_get_bus_info(&adapter->hw);
+
+ /* Read the MAC address. and store to the private data */
+ ret = pch_gbe_hal_read_mac_addr(&adapter->hw);
+ if (ret) {
+ dev_err(&pdev->dev, "MAC address Read Error\n");
+ goto err_free_adapter;
+ }
+
+ memcpy(netdev->dev_addr, adapter->hw.mac.addr, netdev->addr_len);
+ if (!is_valid_ether_addr(netdev->dev_addr)) {
+ dev_err(&pdev->dev, "Invalid MAC Address\n");
+ ret = -EIO;
+ goto err_free_adapter;
+ }
+ setup_timer(&adapter->watchdog_timer, pch_gbe_watchdog,
+ (unsigned long)adapter);
+
+ INIT_WORK(&adapter->reset_task, pch_gbe_reset_task);
+
+ pch_gbe_check_options(adapter);
+
+ if (adapter->tx_csum)
+ netdev->features |= NETIF_F_HW_CSUM;
+ else
+ netdev->features &= ~NETIF_F_HW_CSUM;
+
+ /* initialize the wol settings based on the eeprom settings */
+ adapter->wake_up_evt = PCH_GBE_WL_INIT_SETTING;
+ dev_info(&pdev->dev, "MAC address : %pM\n", netdev->dev_addr);
+
+ /* reset the hardware with the new settings */
+ pch_gbe_reset(adapter);
+
+ ret = register_netdev(netdev);
+ if (ret)
+ goto err_free_adapter;
+ /* tell the stack to leave us alone until pch_gbe_open() is called */
+ netif_carrier_off(netdev);
+ netif_stop_queue(netdev);
+
+ dev_dbg(&pdev->dev, "OKIsemi(R) PCH Network Connection\n");
+
+ device_set_wakeup_enable(&pdev->dev, 1);
+ return 0;
+
+err_free_adapter:
+ pch_gbe_hal_phy_hw_reset(&adapter->hw);
+ kfree(adapter->tx_ring);
+ kfree(adapter->rx_ring);
+err_iounmap:
+ iounmap(adapter->hw.reg);
+err_free_netdev:
+ free_netdev(netdev);
+err_release_pci:
+ pci_release_regions(pdev);
+err_disable_device:
+ pci_disable_device(pdev);
+ return ret;
+}
+
+static DEFINE_PCI_DEVICE_TABLE(pch_gbe_pcidev_id) = {
+ {.vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_IOH1_GBE,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .class = (PCI_CLASS_NETWORK_ETHERNET << 8),
+ .class_mask = (0xFFFF00)
+ },
+ /* required last entry */
+ {0}
+};
+
+#ifdef CONFIG_PM
+static const struct dev_pm_ops pch_gbe_pm_ops = {
+ .suspend = pch_gbe_suspend,
+ .resume = pch_gbe_resume,
+ .freeze = pch_gbe_suspend,
+ .thaw = pch_gbe_resume,
+ .poweroff = pch_gbe_suspend,
+ .restore = pch_gbe_resume,
+};
+#endif
+
+static struct pci_error_handlers pch_gbe_err_handler = {
+ .error_detected = pch_gbe_io_error_detected,
+ .slot_reset = pch_gbe_io_slot_reset,
+ .resume = pch_gbe_io_resume
+};
+
+static struct pci_driver pch_gbe_pcidev = {
+ .name = KBUILD_MODNAME,
+ .id_table = pch_gbe_pcidev_id,
+ .probe = pch_gbe_probe,
+ .remove = pch_gbe_remove,
+#ifdef CONFIG_PM_OPS
+ .driver.pm = &pch_gbe_pm_ops,
+#endif
+ .shutdown = pch_gbe_shutdown,
+ .err_handler = &pch_gbe_err_handler
+};
+
+
+static int __init pch_gbe_init_module(void)
+{
+ int ret;
+
+ ret = pci_register_driver(&pch_gbe_pcidev);
+ if (copybreak != PCH_GBE_COPYBREAK_DEFAULT) {
+ if (copybreak == 0) {
+ pr_info("copybreak disabled\n");
+ } else {
+ pr_info("copybreak enabled for packets <= %u bytes\n",
+ copybreak);
+ }
+ }
+ return ret;
+}
+
+static void __exit pch_gbe_exit_module(void)
+{
+ pci_unregister_driver(&pch_gbe_pcidev);
+}
+
+module_init(pch_gbe_init_module);
+module_exit(pch_gbe_exit_module);
+
+MODULE_DESCRIPTION("OKI semiconductor PCH Gigabit ethernet Driver");
+MODULE_AUTHOR("OKI semiconductor, <masa-korg@dsn.okisemi.com>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+MODULE_DEVICE_TABLE(pci, pch_gbe_pcidev_id);
+
+module_param(copybreak, uint, 0644);
+MODULE_PARM_DESC(copybreak,
+ "Maximum size of packet that is copied to a new buffer on receive");
+
+/* pch_gbe_main.c */
diff --git a/drivers/net/pch_gbe/pch_gbe_param.c b/drivers/net/pch_gbe/pch_gbe_param.c
new file mode 100644
index 000000000000..2510146fc560
--- /dev/null
+++ b/drivers/net/pch_gbe/pch_gbe_param.c
@@ -0,0 +1,499 @@
+/*
+ * Copyright (C) 1999 - 2010 Intel Corporation.
+ * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ *
+ * This code was derived from the Intel e1000e Linux driver.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "pch_gbe.h"
+
+#define OPTION_UNSET -1
+#define OPTION_DISABLED 0
+#define OPTION_ENABLED 1
+
+/**
+ * TxDescriptors - Transmit Descriptor Count
+ * @Valid Range: PCH_GBE_MIN_TXD - PCH_GBE_MAX_TXD
+ * @Default Value: PCH_GBE_DEFAULT_TXD
+ */
+static int TxDescriptors = OPTION_UNSET;
+module_param(TxDescriptors, int, 0);
+MODULE_PARM_DESC(TxDescriptors, "Number of transmit descriptors");
+
+/**
+ * RxDescriptors -Receive Descriptor Count
+ * @Valid Range: PCH_GBE_MIN_RXD - PCH_GBE_MAX_RXD
+ * @Default Value: PCH_GBE_DEFAULT_RXD
+ */
+static int RxDescriptors = OPTION_UNSET;
+module_param(RxDescriptors, int, 0);
+MODULE_PARM_DESC(RxDescriptors, "Number of receive descriptors");
+
+/**
+ * Speed - User Specified Speed Override
+ * @Valid Range: 0, 10, 100, 1000
+ * - 0: auto-negotiate at all supported speeds
+ * - 10: only link at 10 Mbps
+ * - 100: only link at 100 Mbps
+ * - 1000: only link at 1000 Mbps
+ * @Default Value: 0
+ */
+static int Speed = OPTION_UNSET;
+module_param(Speed, int, 0);
+MODULE_PARM_DESC(Speed, "Speed setting");
+
+/**
+ * Duplex - User Specified Duplex Override
+ * @Valid Range: 0-2
+ * - 0: auto-negotiate for duplex
+ * - 1: only link at half duplex
+ * - 2: only link at full duplex
+ * @Default Value: 0
+ */
+static int Duplex = OPTION_UNSET;
+module_param(Duplex, int, 0);
+MODULE_PARM_DESC(Duplex, "Duplex setting");
+
+#define HALF_DUPLEX 1
+#define FULL_DUPLEX 2
+
+/**
+ * AutoNeg - Auto-negotiation Advertisement Override
+ * @Valid Range: 0x01-0x0F, 0x20-0x2F
+ *
+ * The AutoNeg value is a bit mask describing which speed and duplex
+ * combinations should be advertised during auto-negotiation.
+ * The supported speed and duplex modes are listed below
+ *
+ * Bit 7 6 5 4 3 2 1 0
+ * Speed (Mbps) N/A N/A 1000 N/A 100 100 10 10
+ * Duplex Full Full Half Full Half
+ *
+ * @Default Value: 0x2F (copper)
+ */
+static int AutoNeg = OPTION_UNSET;
+module_param(AutoNeg, int, 0);
+MODULE_PARM_DESC(AutoNeg, "Advertised auto-negotiation setting");
+
+#define PHY_ADVERTISE_10_HALF 0x0001
+#define PHY_ADVERTISE_10_FULL 0x0002
+#define PHY_ADVERTISE_100_HALF 0x0004
+#define PHY_ADVERTISE_100_FULL 0x0008
+#define PHY_ADVERTISE_1000_HALF 0x0010 /* Not used, just FYI */
+#define PHY_ADVERTISE_1000_FULL 0x0020
+#define PCH_AUTONEG_ADVERTISE_DEFAULT 0x2F
+
+/**
+ * FlowControl - User Specified Flow Control Override
+ * @Valid Range: 0-3
+ * - 0: No Flow Control
+ * - 1: Rx only, respond to PAUSE frames but do not generate them
+ * - 2: Tx only, generate PAUSE frames but ignore them on receive
+ * - 3: Full Flow Control Support
+ * @Default Value: Read flow control settings from the EEPROM
+ */
+static int FlowControl = OPTION_UNSET;
+module_param(FlowControl, int, 0);
+MODULE_PARM_DESC(FlowControl, "Flow Control setting");
+
+/*
+ * XsumRX - Receive Checksum Offload Enable/Disable
+ * @Valid Range: 0, 1
+ * - 0: disables all checksum offload
+ * - 1: enables receive IP/TCP/UDP checksum offload
+ * @Default Value: PCH_GBE_DEFAULT_RX_CSUM
+ */
+static int XsumRX = OPTION_UNSET;
+module_param(XsumRX, int, 0);
+MODULE_PARM_DESC(XsumRX, "Disable or enable Receive Checksum offload");
+
+#define PCH_GBE_DEFAULT_RX_CSUM true /* trueorfalse */
+
+/*
+ * XsumTX - Transmit Checksum Offload Enable/Disable
+ * @Valid Range: 0, 1
+ * - 0: disables all checksum offload
+ * - 1: enables transmit IP/TCP/UDP checksum offload
+ * @Default Value: PCH_GBE_DEFAULT_TX_CSUM
+ */
+static int XsumTX = OPTION_UNSET;
+module_param(XsumTX, int, 0);
+MODULE_PARM_DESC(XsumTX, "Disable or enable Transmit Checksum offload");
+
+#define PCH_GBE_DEFAULT_TX_CSUM true /* trueorfalse */
+
+/**
+ * pch_gbe_option - Force the MAC's flow control settings
+ * @hw: Pointer to the HW structure
+ * Returns
+ * 0: Successful.
+ * Negative value: Failed.
+ */
+struct pch_gbe_option {
+ enum { enable_option, range_option, list_option } type;
+ char *name;
+ char *err;
+ int def;
+ union {
+ struct { /* range_option info */
+ int min;
+ int max;
+ } r;
+ struct { /* list_option info */
+ int nr;
+ const struct pch_gbe_opt_list { int i; char *str; } *p;
+ } l;
+ } arg;
+};
+
+static const struct pch_gbe_opt_list speed_list[] = {
+ { 0, "" },
+ { SPEED_10, "" },
+ { SPEED_100, "" },
+ { SPEED_1000, "" }
+};
+
+static const struct pch_gbe_opt_list dplx_list[] = {
+ { 0, "" },
+ { HALF_DUPLEX, "" },
+ { FULL_DUPLEX, "" }
+};
+
+static const struct pch_gbe_opt_list an_list[] =
+ #define AA "AutoNeg advertising "
+ {{ 0x01, AA "10/HD" },
+ { 0x02, AA "10/FD" },
+ { 0x03, AA "10/FD, 10/HD" },
+ { 0x04, AA "100/HD" },
+ { 0x05, AA "100/HD, 10/HD" },
+ { 0x06, AA "100/HD, 10/FD" },
+ { 0x07, AA "100/HD, 10/FD, 10/HD" },
+ { 0x08, AA "100/FD" },
+ { 0x09, AA "100/FD, 10/HD" },
+ { 0x0a, AA "100/FD, 10/FD" },
+ { 0x0b, AA "100/FD, 10/FD, 10/HD" },
+ { 0x0c, AA "100/FD, 100/HD" },
+ { 0x0d, AA "100/FD, 100/HD, 10/HD" },
+ { 0x0e, AA "100/FD, 100/HD, 10/FD" },
+ { 0x0f, AA "100/FD, 100/HD, 10/FD, 10/HD" },
+ { 0x20, AA "1000/FD" },
+ { 0x21, AA "1000/FD, 10/HD" },
+ { 0x22, AA "1000/FD, 10/FD" },
+ { 0x23, AA "1000/FD, 10/FD, 10/HD" },
+ { 0x24, AA "1000/FD, 100/HD" },
+ { 0x25, AA "1000/FD, 100/HD, 10/HD" },
+ { 0x26, AA "1000/FD, 100/HD, 10/FD" },
+ { 0x27, AA "1000/FD, 100/HD, 10/FD, 10/HD" },
+ { 0x28, AA "1000/FD, 100/FD" },
+ { 0x29, AA "1000/FD, 100/FD, 10/HD" },
+ { 0x2a, AA "1000/FD, 100/FD, 10/FD" },
+ { 0x2b, AA "1000/FD, 100/FD, 10/FD, 10/HD" },
+ { 0x2c, AA "1000/FD, 100/FD, 100/HD" },
+ { 0x2d, AA "1000/FD, 100/FD, 100/HD, 10/HD" },
+ { 0x2e, AA "1000/FD, 100/FD, 100/HD, 10/FD" },
+ { 0x2f, AA "1000/FD, 100/FD, 100/HD, 10/FD, 10/HD" }
+};
+
+static const struct pch_gbe_opt_list fc_list[] = {
+ { PCH_GBE_FC_NONE, "Flow Control Disabled" },
+ { PCH_GBE_FC_RX_PAUSE, "Flow Control Receive Only" },
+ { PCH_GBE_FC_TX_PAUSE, "Flow Control Transmit Only" },
+ { PCH_GBE_FC_FULL, "Flow Control Enabled" }
+};
+
+/**
+ * pch_gbe_validate_option - Validate option
+ * @value: value
+ * @opt: option
+ * @adapter: Board private structure
+ * Returns
+ * 0: Successful.
+ * Negative value: Failed.
+ */
+static int pch_gbe_validate_option(int *value,
+ const struct pch_gbe_option *opt,
+ struct pch_gbe_adapter *adapter)
+{
+ if (*value == OPTION_UNSET) {
+ *value = opt->def;
+ return 0;
+ }
+
+ switch (opt->type) {
+ case enable_option:
+ switch (*value) {
+ case OPTION_ENABLED:
+ pr_debug("%s Enabled\n", opt->name);
+ return 0;
+ case OPTION_DISABLED:
+ pr_debug("%s Disabled\n", opt->name);
+ return 0;
+ }
+ break;
+ case range_option:
+ if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
+ pr_debug("%s set to %i\n", opt->name, *value);
+ return 0;
+ }
+ break;
+ case list_option: {
+ int i;
+ const struct pch_gbe_opt_list *ent;
+
+ for (i = 0; i < opt->arg.l.nr; i++) {
+ ent = &opt->arg.l.p[i];
+ if (*value == ent->i) {
+ if (ent->str[0] != '\0')
+ pr_debug("%s\n", ent->str);
+ return 0;
+ }
+ }
+ }
+ break;
+ default:
+ BUG();
+ }
+
+ pr_debug("Invalid %s value specified (%i) %s\n",
+ opt->name, *value, opt->err);
+ *value = opt->def;
+ return -1;
+}
+
+/**
+ * pch_gbe_check_copper_options - Range Checking for Link Options, Copper Version
+ * @adapter: Board private structure
+ */
+static void pch_gbe_check_copper_options(struct pch_gbe_adapter *adapter)
+{
+ struct pch_gbe_hw *hw = &adapter->hw;
+ int speed, dplx;
+
+ { /* Speed */
+ static const struct pch_gbe_option opt = {
+ .type = list_option,
+ .name = "Speed",
+ .err = "parameter ignored",
+ .def = 0,
+ .arg = { .l = { .nr = (int)ARRAY_SIZE(speed_list),
+ .p = speed_list } }
+ };
+ speed = Speed;
+ pch_gbe_validate_option(&speed, &opt, adapter);
+ }
+ { /* Duplex */
+ static const struct pch_gbe_option opt = {
+ .type = list_option,
+ .name = "Duplex",
+ .err = "parameter ignored",
+ .def = 0,
+ .arg = { .l = { .nr = (int)ARRAY_SIZE(dplx_list),
+ .p = dplx_list } }
+ };
+ dplx = Duplex;
+ pch_gbe_validate_option(&dplx, &opt, adapter);
+ }
+
+ { /* Autoneg */
+ static const struct pch_gbe_option opt = {
+ .type = list_option,
+ .name = "AutoNeg",
+ .err = "parameter ignored",
+ .def = PCH_AUTONEG_ADVERTISE_DEFAULT,
+ .arg = { .l = { .nr = (int)ARRAY_SIZE(an_list),
+ .p = an_list} }
+ };
+ if (speed || dplx) {
+ pr_debug("AutoNeg specified along with Speed or Duplex, AutoNeg parameter ignored\n");
+ hw->phy.autoneg_advertised = opt.def;
+ } else {
+ hw->phy.autoneg_advertised = AutoNeg;
+ pch_gbe_validate_option(
+ (int *)(&hw->phy.autoneg_advertised),
+ &opt, adapter);
+ }
+ }
+
+ switch (speed + dplx) {
+ case 0:
+ hw->mac.autoneg = hw->mac.fc_autoneg = 1;
+ if ((speed || dplx))
+ pr_debug("Speed and duplex autonegotiation enabled\n");
+ hw->mac.link_speed = SPEED_10;
+ hw->mac.link_duplex = DUPLEX_HALF;
+ break;
+ case HALF_DUPLEX:
+ pr_debug("Half Duplex specified without Speed\n");
+ pr_debug("Using Autonegotiation at Half Duplex only\n");
+ hw->mac.autoneg = hw->mac.fc_autoneg = 1;
+ hw->phy.autoneg_advertised = PHY_ADVERTISE_10_HALF |
+ PHY_ADVERTISE_100_HALF;
+ hw->mac.link_speed = SPEED_10;
+ hw->mac.link_duplex = DUPLEX_HALF;
+ break;
+ case FULL_DUPLEX:
+ pr_debug("Full Duplex specified without Speed\n");
+ pr_debug("Using Autonegotiation at Full Duplex only\n");
+ hw->mac.autoneg = hw->mac.fc_autoneg = 1;
+ hw->phy.autoneg_advertised = PHY_ADVERTISE_10_FULL |
+ PHY_ADVERTISE_100_FULL |
+ PHY_ADVERTISE_1000_FULL;
+ hw->mac.link_speed = SPEED_10;
+ hw->mac.link_duplex = DUPLEX_FULL;
+ break;
+ case SPEED_10:
+ pr_debug("10 Mbps Speed specified without Duplex\n");
+ pr_debug("Using Autonegotiation at 10 Mbps only\n");
+ hw->mac.autoneg = hw->mac.fc_autoneg = 1;
+ hw->phy.autoneg_advertised = PHY_ADVERTISE_10_HALF |
+ PHY_ADVERTISE_10_FULL;
+ hw->mac.link_speed = SPEED_10;
+ hw->mac.link_duplex = DUPLEX_HALF;
+ break;
+ case SPEED_10 + HALF_DUPLEX:
+ pr_debug("Forcing to 10 Mbps Half Duplex\n");
+ hw->mac.autoneg = hw->mac.fc_autoneg = 0;
+ hw->phy.autoneg_advertised = 0;
+ hw->mac.link_speed = SPEED_10;
+ hw->mac.link_duplex = DUPLEX_HALF;
+ break;
+ case SPEED_10 + FULL_DUPLEX:
+ pr_debug("Forcing to 10 Mbps Full Duplex\n");
+ hw->mac.autoneg = hw->mac.fc_autoneg = 0;
+ hw->phy.autoneg_advertised = 0;
+ hw->mac.link_speed = SPEED_10;
+ hw->mac.link_duplex = DUPLEX_FULL;
+ break;
+ case SPEED_100:
+ pr_debug("100 Mbps Speed specified without Duplex\n");
+ pr_debug("Using Autonegotiation at 100 Mbps only\n");
+ hw->mac.autoneg = hw->mac.fc_autoneg = 1;
+ hw->phy.autoneg_advertised = PHY_ADVERTISE_100_HALF |
+ PHY_ADVERTISE_100_FULL;
+ hw->mac.link_speed = SPEED_100;
+ hw->mac.link_duplex = DUPLEX_HALF;
+ break;
+ case SPEED_100 + HALF_DUPLEX:
+ pr_debug("Forcing to 100 Mbps Half Duplex\n");
+ hw->mac.autoneg = hw->mac.fc_autoneg = 0;
+ hw->phy.autoneg_advertised = 0;
+ hw->mac.link_speed = SPEED_100;
+ hw->mac.link_duplex = DUPLEX_HALF;
+ break;
+ case SPEED_100 + FULL_DUPLEX:
+ pr_debug("Forcing to 100 Mbps Full Duplex\n");
+ hw->mac.autoneg = hw->mac.fc_autoneg = 0;
+ hw->phy.autoneg_advertised = 0;
+ hw->mac.link_speed = SPEED_100;
+ hw->mac.link_duplex = DUPLEX_FULL;
+ break;
+ case SPEED_1000:
+ pr_debug("1000 Mbps Speed specified without Duplex\n");
+ goto full_duplex_only;
+ case SPEED_1000 + HALF_DUPLEX:
+ pr_debug("Half Duplex is not supported at 1000 Mbps\n");
+ /* fall through */
+ case SPEED_1000 + FULL_DUPLEX:
+full_duplex_only:
+ pr_debug("Using Autonegotiation at 1000 Mbps Full Duplex only\n");
+ hw->mac.autoneg = hw->mac.fc_autoneg = 1;
+ hw->phy.autoneg_advertised = PHY_ADVERTISE_1000_FULL;
+ hw->mac.link_speed = SPEED_1000;
+ hw->mac.link_duplex = DUPLEX_FULL;
+ break;
+ default:
+ BUG();
+ }
+}
+
+/**
+ * pch_gbe_check_options - Range Checking for Command Line Parameters
+ * @adapter: Board private structure
+ */
+void pch_gbe_check_options(struct pch_gbe_adapter *adapter)
+{
+ struct pch_gbe_hw *hw = &adapter->hw;
+
+ { /* Transmit Descriptor Count */
+ static const struct pch_gbe_option opt = {
+ .type = range_option,
+ .name = "Transmit Descriptors",
+ .err = "using default of "
+ __MODULE_STRING(PCH_GBE_DEFAULT_TXD),
+ .def = PCH_GBE_DEFAULT_TXD,
+ .arg = { .r = { .min = PCH_GBE_MIN_TXD } },
+ .arg = { .r = { .max = PCH_GBE_MAX_TXD } }
+ };
+ struct pch_gbe_tx_ring *tx_ring = adapter->tx_ring;
+ tx_ring->count = TxDescriptors;
+ pch_gbe_validate_option(&tx_ring->count, &opt, adapter);
+ tx_ring->count = roundup(tx_ring->count,
+ PCH_GBE_TX_DESC_MULTIPLE);
+ }
+ { /* Receive Descriptor Count */
+ static const struct pch_gbe_option opt = {
+ .type = range_option,
+ .name = "Receive Descriptors",
+ .err = "using default of "
+ __MODULE_STRING(PCH_GBE_DEFAULT_RXD),
+ .def = PCH_GBE_DEFAULT_RXD,
+ .arg = { .r = { .min = PCH_GBE_MIN_RXD } },
+ .arg = { .r = { .max = PCH_GBE_MAX_RXD } }
+ };
+ struct pch_gbe_rx_ring *rx_ring = adapter->rx_ring;
+ rx_ring->count = RxDescriptors;
+ pch_gbe_validate_option(&rx_ring->count, &opt, adapter);
+ rx_ring->count = roundup(rx_ring->count,
+ PCH_GBE_RX_DESC_MULTIPLE);
+ }
+ { /* Checksum Offload Enable/Disable */
+ static const struct pch_gbe_option opt = {
+ .type = enable_option,
+ .name = "Checksum Offload",
+ .err = "defaulting to Enabled",
+ .def = PCH_GBE_DEFAULT_RX_CSUM
+ };
+ adapter->rx_csum = XsumRX;
+ pch_gbe_validate_option((int *)(&adapter->rx_csum),
+ &opt, adapter);
+ }
+ { /* Checksum Offload Enable/Disable */
+ static const struct pch_gbe_option opt = {
+ .type = enable_option,
+ .name = "Checksum Offload",
+ .err = "defaulting to Enabled",
+ .def = PCH_GBE_DEFAULT_TX_CSUM
+ };
+ adapter->tx_csum = XsumTX;
+ pch_gbe_validate_option((int *)(&adapter->tx_csum),
+ &opt, adapter);
+ }
+ { /* Flow Control */
+ static const struct pch_gbe_option opt = {
+ .type = list_option,
+ .name = "Flow Control",
+ .err = "reading default settings from EEPROM",
+ .def = PCH_GBE_FC_DEFAULT,
+ .arg = { .l = { .nr = (int)ARRAY_SIZE(fc_list),
+ .p = fc_list } }
+ };
+ hw->mac.fc = FlowControl;
+ pch_gbe_validate_option((int *)(&hw->mac.fc),
+ &opt, adapter);
+ }
+
+ pch_gbe_check_copper_options(adapter);
+}
diff --git a/drivers/net/pch_gbe/pch_gbe_phy.c b/drivers/net/pch_gbe/pch_gbe_phy.c
new file mode 100644
index 000000000000..923a687acd30
--- /dev/null
+++ b/drivers/net/pch_gbe/pch_gbe_phy.c
@@ -0,0 +1,274 @@
+/*
+ * Copyright (C) 1999 - 2010 Intel Corporation.
+ * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ *
+ * This code was derived from the Intel e1000e Linux driver.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "pch_gbe.h"
+#include "pch_gbe_phy.h"
+
+#define PHY_MAX_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */
+
+/* PHY 1000 MII Register/Bit Definitions */
+/* PHY Registers defined by IEEE */
+#define PHY_CONTROL 0x00 /* Control Register */
+#define PHY_STATUS 0x01 /* Status Regiser */
+#define PHY_ID1 0x02 /* Phy Id Register (word 1) */
+#define PHY_ID2 0x03 /* Phy Id Register (word 2) */
+#define PHY_AUTONEG_ADV 0x04 /* Autoneg Advertisement */
+#define PHY_LP_ABILITY 0x05 /* Link Partner Ability (Base Page) */
+#define PHY_AUTONEG_EXP 0x06 /* Autoneg Expansion Register */
+#define PHY_NEXT_PAGE_TX 0x07 /* Next Page TX */
+#define PHY_LP_NEXT_PAGE 0x08 /* Link Partner Next Page */
+#define PHY_1000T_CTRL 0x09 /* 1000Base-T Control Register */
+#define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Register */
+#define PHY_EXT_STATUS 0x0F /* Extended Status Register */
+#define PHY_PHYSP_CONTROL 0x10 /* PHY Specific Control Register */
+#define PHY_EXT_PHYSP_CONTROL 0x14 /* Extended PHY Specific Control Register */
+#define PHY_LED_CONTROL 0x18 /* LED Control Register */
+#define PHY_EXT_PHYSP_STATUS 0x1B /* Extended PHY Specific Status Register */
+
+/* PHY Control Register */
+#define MII_CR_SPEED_SELECT_MSB 0x0040 /* bits 6,13: 10=1000, 01=100, 00=10 */
+#define MII_CR_COLL_TEST_ENABLE 0x0080 /* Collision test enable */
+#define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */
+#define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */
+#define MII_CR_ISOLATE 0x0400 /* Isolate PHY from MII */
+#define MII_CR_POWER_DOWN 0x0800 /* Power down */
+#define MII_CR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */
+#define MII_CR_SPEED_SELECT_LSB 0x2000 /* bits 6,13: 10=1000, 01=100, 00=10 */
+#define MII_CR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */
+#define MII_CR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */
+#define MII_CR_SPEED_1000 0x0040
+#define MII_CR_SPEED_100 0x2000
+#define MII_CR_SPEED_10 0x0000
+
+/* PHY Status Register */
+#define MII_SR_EXTENDED_CAPS 0x0001 /* Extended register capabilities */
+#define MII_SR_JABBER_DETECT 0x0002 /* Jabber Detected */
+#define MII_SR_LINK_STATUS 0x0004 /* Link Status 1 = link */
+#define MII_SR_AUTONEG_CAPS 0x0008 /* Auto Neg Capable */
+#define MII_SR_REMOTE_FAULT 0x0010 /* Remote Fault Detect */
+#define MII_SR_AUTONEG_COMPLETE 0x0020 /* Auto Neg Complete */
+#define MII_SR_PREAMBLE_SUPPRESS 0x0040 /* Preamble may be suppressed */
+#define MII_SR_EXTENDED_STATUS 0x0100 /* Ext. status info in Reg 0x0F */
+#define MII_SR_100T2_HD_CAPS 0x0200 /* 100T2 Half Duplex Capable */
+#define MII_SR_100T2_FD_CAPS 0x0400 /* 100T2 Full Duplex Capable */
+#define MII_SR_10T_HD_CAPS 0x0800 /* 10T Half Duplex Capable */
+#define MII_SR_10T_FD_CAPS 0x1000 /* 10T Full Duplex Capable */
+#define MII_SR_100X_HD_CAPS 0x2000 /* 100X Half Duplex Capable */
+#define MII_SR_100X_FD_CAPS 0x4000 /* 100X Full Duplex Capable */
+#define MII_SR_100T4_CAPS 0x8000 /* 100T4 Capable */
+
+/* Phy Id Register (word 2) */
+#define PHY_REVISION_MASK 0x000F
+
+/* PHY Specific Control Register */
+#define PHYSP_CTRL_ASSERT_CRS_TX 0x0800
+
+
+/* Default value of PHY register */
+#define PHY_CONTROL_DEFAULT 0x1140 /* Control Register */
+#define PHY_AUTONEG_ADV_DEFAULT 0x01e0 /* Autoneg Advertisement */
+#define PHY_NEXT_PAGE_TX_DEFAULT 0x2001 /* Next Page TX */
+#define PHY_1000T_CTRL_DEFAULT 0x0300 /* 1000Base-T Control Register */
+#define PHY_PHYSP_CONTROL_DEFAULT 0x01EE /* PHY Specific Control Register */
+
+/**
+ * pch_gbe_phy_get_id - Retrieve the PHY ID and revision
+ * @hw: Pointer to the HW structure
+ * Returns
+ * 0: Successful.
+ * Negative value: Failed.
+ */
+s32 pch_gbe_phy_get_id(struct pch_gbe_hw *hw)
+{
+ struct pch_gbe_phy_info *phy = &hw->phy;
+ s32 ret;
+ u16 phy_id1;
+ u16 phy_id2;
+
+ ret = pch_gbe_phy_read_reg_miic(hw, PHY_ID1, &phy_id1);
+ if (ret)
+ return ret;
+ ret = pch_gbe_phy_read_reg_miic(hw, PHY_ID2, &phy_id2);
+ if (ret)
+ return ret;
+ /*
+ * PHY_ID1: [bit15-0:ID(21-6)]
+ * PHY_ID2: [bit15-10:ID(5-0)][bit9-4:Model][bit3-0:revision]
+ */
+ phy->id = (u32)phy_id1;
+ phy->id = ((phy->id << 6) | ((phy_id2 & 0xFC00) >> 10));
+ phy->revision = (u32) (phy_id2 & 0x000F);
+ pr_debug("phy->id : 0x%08x phy->revision : 0x%08x\n",
+ phy->id, phy->revision);
+ return 0;
+}
+
+/**
+ * pch_gbe_phy_read_reg_miic - Read MII control register
+ * @hw: Pointer to the HW structure
+ * @offset: Register offset to be read
+ * @data: Pointer to the read data
+ * Returns
+ * 0: Successful.
+ * -EINVAL: Invalid argument.
+ */
+s32 pch_gbe_phy_read_reg_miic(struct pch_gbe_hw *hw, u32 offset, u16 *data)
+{
+ struct pch_gbe_phy_info *phy = &hw->phy;
+
+ if (offset > PHY_MAX_REG_ADDRESS) {
+ pr_err("PHY Address %d is out of range\n", offset);
+ return -EINVAL;
+ }
+ *data = pch_gbe_mac_ctrl_miim(hw, phy->addr, PCH_GBE_HAL_MIIM_READ,
+ offset, (u16)0);
+ return 0;
+}
+
+/**
+ * pch_gbe_phy_write_reg_miic - Write MII control register
+ * @hw: Pointer to the HW structure
+ * @offset: Register offset to be read
+ * @data: data to write to register at offset
+ * Returns
+ * 0: Successful.
+ * -EINVAL: Invalid argument.
+ */
+s32 pch_gbe_phy_write_reg_miic(struct pch_gbe_hw *hw, u32 offset, u16 data)
+{
+ struct pch_gbe_phy_info *phy = &hw->phy;
+
+ if (offset > PHY_MAX_REG_ADDRESS) {
+ pr_err("PHY Address %d is out of range\n", offset);
+ return -EINVAL;
+ }
+ pch_gbe_mac_ctrl_miim(hw, phy->addr, PCH_GBE_HAL_MIIM_WRITE,
+ offset, data);
+ return 0;
+}
+
+/**
+ * pch_gbe_phy_sw_reset - PHY software reset
+ * @hw: Pointer to the HW structure
+ */
+void pch_gbe_phy_sw_reset(struct pch_gbe_hw *hw)
+{
+ u16 phy_ctrl;
+
+ pch_gbe_phy_read_reg_miic(hw, PHY_CONTROL, &phy_ctrl);
+ phy_ctrl |= MII_CR_RESET;
+ pch_gbe_phy_write_reg_miic(hw, PHY_CONTROL, phy_ctrl);
+ udelay(1);
+}
+
+/**
+ * pch_gbe_phy_hw_reset - PHY hardware reset
+ * @hw: Pointer to the HW structure
+ */
+void pch_gbe_phy_hw_reset(struct pch_gbe_hw *hw)
+{
+ pch_gbe_phy_write_reg_miic(hw, PHY_CONTROL, PHY_CONTROL_DEFAULT);
+ pch_gbe_phy_write_reg_miic(hw, PHY_AUTONEG_ADV,
+ PHY_AUTONEG_ADV_DEFAULT);
+ pch_gbe_phy_write_reg_miic(hw, PHY_NEXT_PAGE_TX,
+ PHY_NEXT_PAGE_TX_DEFAULT);
+ pch_gbe_phy_write_reg_miic(hw, PHY_1000T_CTRL, PHY_1000T_CTRL_DEFAULT);
+ pch_gbe_phy_write_reg_miic(hw, PHY_PHYSP_CONTROL,
+ PHY_PHYSP_CONTROL_DEFAULT);
+}
+
+/**
+ * pch_gbe_phy_power_up - restore link in case the phy was powered down
+ * @hw: Pointer to the HW structure
+ */
+void pch_gbe_phy_power_up(struct pch_gbe_hw *hw)
+{
+ u16 mii_reg;
+
+ mii_reg = 0;
+ /* Just clear the power down bit to wake the phy back up */
+ /* according to the manual, the phy will retain its
+ * settings across a power-down/up cycle */
+ pch_gbe_phy_read_reg_miic(hw, PHY_CONTROL, &mii_reg);
+ mii_reg &= ~MII_CR_POWER_DOWN;
+ pch_gbe_phy_write_reg_miic(hw, PHY_CONTROL, mii_reg);
+}
+
+/**
+ * pch_gbe_phy_power_down - Power down PHY
+ * @hw: Pointer to the HW structure
+ */
+void pch_gbe_phy_power_down(struct pch_gbe_hw *hw)
+{
+ u16 mii_reg;
+
+ mii_reg = 0;
+ /* Power down the PHY so no link is implied when interface is down *
+ * The PHY cannot be powered down if any of the following is TRUE *
+ * (a) WoL is enabled
+ * (b) AMT is active
+ */
+ pch_gbe_phy_read_reg_miic(hw, PHY_CONTROL, &mii_reg);
+ mii_reg |= MII_CR_POWER_DOWN;
+ pch_gbe_phy_write_reg_miic(hw, PHY_CONTROL, mii_reg);
+ mdelay(1);
+}
+
+/**
+ * pch_gbe_phy_set_rgmii - RGMII interface setting
+ * @hw: Pointer to the HW structure
+ */
+inline void pch_gbe_phy_set_rgmii(struct pch_gbe_hw *hw)
+{
+ pch_gbe_phy_sw_reset(hw);
+}
+
+/**
+ * pch_gbe_phy_init_setting - PHY initial setting
+ * @hw: Pointer to the HW structure
+ */
+void pch_gbe_phy_init_setting(struct pch_gbe_hw *hw)
+{
+ struct pch_gbe_adapter *adapter;
+ struct ethtool_cmd cmd;
+ int ret;
+ u16 mii_reg;
+
+ adapter = container_of(hw, struct pch_gbe_adapter, hw);
+ ret = mii_ethtool_gset(&adapter->mii, &cmd);
+ if (ret)
+ pr_err("Error: mii_ethtool_gset\n");
+
+ cmd.speed = hw->mac.link_speed;
+ cmd.duplex = hw->mac.link_duplex;
+ cmd.advertising = hw->phy.autoneg_advertised;
+ cmd.autoneg = hw->mac.autoneg;
+ pch_gbe_phy_write_reg_miic(hw, MII_BMCR, BMCR_RESET);
+ ret = mii_ethtool_sset(&adapter->mii, &cmd);
+ if (ret)
+ pr_err("Error: mii_ethtool_sset\n");
+
+ pch_gbe_phy_sw_reset(hw);
+
+ pch_gbe_phy_read_reg_miic(hw, PHY_PHYSP_CONTROL, &mii_reg);
+ mii_reg |= PHYSP_CTRL_ASSERT_CRS_TX;
+ pch_gbe_phy_write_reg_miic(hw, PHY_PHYSP_CONTROL, mii_reg);
+
+}
diff --git a/drivers/net/pch_gbe/pch_gbe_phy.h b/drivers/net/pch_gbe/pch_gbe_phy.h
new file mode 100644
index 000000000000..03264dc7b5ec
--- /dev/null
+++ b/drivers/net/pch_gbe/pch_gbe_phy.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 1999 - 2010 Intel Corporation.
+ * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ *
+ * This code was derived from the Intel e1000e Linux driver.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+#ifndef _PCH_GBE_PHY_H_
+#define _PCH_GBE_PHY_H_
+
+#define PCH_GBE_PHY_REGS_LEN 32
+#define PCH_GBE_PHY_RESET_DELAY_US 10
+#define PCH_GBE_MAC_IFOP_RGMII
+
+s32 pch_gbe_phy_get_id(struct pch_gbe_hw *hw);
+s32 pch_gbe_phy_read_reg_miic(struct pch_gbe_hw *hw, u32 offset, u16 *data);
+s32 pch_gbe_phy_write_reg_miic(struct pch_gbe_hw *hw, u32 offset, u16 data);
+void pch_gbe_phy_sw_reset(struct pch_gbe_hw *hw);
+void pch_gbe_phy_hw_reset(struct pch_gbe_hw *hw);
+void pch_gbe_phy_power_up(struct pch_gbe_hw *hw);
+void pch_gbe_phy_power_down(struct pch_gbe_hw *hw);
+void pch_gbe_phy_set_rgmii(struct pch_gbe_hw *hw);
+void pch_gbe_phy_init_setting(struct pch_gbe_hw *hw);
+
+#endif /* _PCH_GBE_PHY_H_ */
diff --git a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c
index 56f3fc45dbaa..8dd03439d994 100644
--- a/drivers/net/pci-skeleton.c
+++ b/drivers/net/pci-skeleton.c
@@ -1125,7 +1125,7 @@ static int netdrv_open(struct net_device *dev)
init_timer(&tp->timer);
tp->timer.expires = jiffies + 3 * HZ;
tp->timer.data = (unsigned long) dev;
- tp->timer.function = &netdrv_timer;
+ tp->timer.function = netdrv_timer;
add_timer(&tp->timer);
DPRINTK("EXIT, returning 0\n");
diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c
index c683f77c6f42..2807a0fcadc4 100644
--- a/drivers/net/pcmcia/3c574_cs.c
+++ b/drivers/net/pcmcia/3c574_cs.c
@@ -69,6 +69,8 @@ earlier 3Com products.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -83,11 +85,9 @@ earlier 3Com products.
#include <linux/skbuff.h>
#include <linux/if_arp.h>
#include <linux/ioport.h>
-#include <linux/ethtool.h>
#include <linux/bitops.h>
#include <linux/mii.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/ciscode.h>
@@ -238,7 +238,6 @@ static int el3_rx(struct net_device *dev, int worklimit);
static int el3_close(struct net_device *dev);
static void el3_tx_timeout(struct net_device *dev);
static int el3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-static const struct ethtool_ops netdev_ethtool_ops;
static void set_rx_mode(struct net_device *dev);
static void set_multicast_list(struct net_device *dev);
@@ -280,25 +279,14 @@ static int tc574_probe(struct pcmcia_device *link)
spin_lock_init(&lp->window_lock);
link->resource[0]->end = 32;
link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
- link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.IntType = INT_MEMORY_AND_IO;
- link->conf.ConfigIndex = 1;
+ link->config_flags |= CONF_ENABLE_IRQ;
+ link->config_index = 1;
dev->netdev_ops = &el3_netdev_ops;
- SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
dev->watchdog_timeo = TX_TIMEOUT;
return tc574_config(link);
-} /* tc574_attach */
-
-/*
-
- This deletes a driver "instance". The device is de-registered
- with Card Services. If it has been released, all local data
- structures are freed. Otherwise, the structures will be freed
- when the device is released.
-
-*/
+}
static void tc574_detach(struct pcmcia_device *link)
{
@@ -313,12 +301,6 @@ static void tc574_detach(struct pcmcia_device *link)
free_netdev(dev);
} /* tc574_detach */
-/*
- tc574_config() is scheduled to run after a CARD_INSERTION event
- is received, to configure the PCMCIA socket, and to make the
- ethernet device available to the system.
-*/
-
static const char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
static int tc574_config(struct pcmcia_device *link)
@@ -352,7 +334,7 @@ static int tc574_config(struct pcmcia_device *link)
if (ret)
goto failed;
- ret = pcmcia_request_configuration(link, &link->conf);
+ ret = pcmcia_enable_device(link);
if (ret)
goto failed;
@@ -376,8 +358,8 @@ static int tc574_config(struct pcmcia_device *link)
for (i = 0; i < 3; i++)
phys_addr[i] = htons(read_eeprom(ioaddr, i + 10));
if (phys_addr[0] == htons(0x6060)) {
- printk(KERN_NOTICE "3c574_cs: IO port conflict at 0x%03lx"
- "-0x%03lx\n", dev->base_addr, dev->base_addr+15);
+ pr_notice("IO port conflict at 0x%03lx-0x%03lx\n",
+ dev->base_addr, dev->base_addr+15);
goto failed;
}
}
@@ -391,7 +373,7 @@ static int tc574_config(struct pcmcia_device *link)
outw(2<<11, ioaddr + RunnerRdCtrl);
mcr = inb(ioaddr + 2);
outw(0<<11, ioaddr + RunnerRdCtrl);
- printk(KERN_INFO " ASIC rev %d,", mcr>>3);
+ pr_info(" ASIC rev %d,", mcr>>3);
EL3WINDOW(3);
config = inl(ioaddr + Wn3_Config);
lp->default_media = (config & Xcvr) >> Xcvr_shift;
@@ -428,7 +410,7 @@ static int tc574_config(struct pcmcia_device *link)
}
}
if (phy > 32) {
- printk(KERN_NOTICE " No MII transceivers found!\n");
+ pr_notice(" No MII transceivers found!\n");
goto failed;
}
i = mdio_read(ioaddr, lp->phys, 16) | 0x40;
@@ -444,18 +426,16 @@ static int tc574_config(struct pcmcia_device *link)
SET_NETDEV_DEV(dev, &link->dev);
if (register_netdev(dev) != 0) {
- printk(KERN_NOTICE "3c574_cs: register_netdev() failed\n");
+ pr_notice("register_netdev() failed\n");
goto failed;
}
- printk(KERN_INFO "%s: %s at io %#3lx, irq %d, "
- "hw_addr %pM.\n",
- dev->name, cardname, dev->base_addr, dev->irq,
- dev->dev_addr);
- printk(" %dK FIFO split %s Rx:Tx, %sMII interface.\n",
- 8 << config & Ram_size,
- ram_split[(config & Ram_split) >> Ram_split_shift],
- config & Autoselect ? "autoselect " : "");
+ netdev_info(dev, "%s at io %#3lx, irq %d, hw_addr %pM\n",
+ cardname, dev->base_addr, dev->irq, dev->dev_addr);
+ netdev_info(dev, " %dK FIFO split %s Rx:Tx, %sMII interface.\n",
+ 8 << config & Ram_size,
+ ram_split[(config & Ram_split) >> Ram_split_shift],
+ config & Autoselect ? "autoselect " : "");
return 0;
@@ -465,12 +445,6 @@ failed:
} /* tc574_config */
-/*
- After a card is removed, tc574_release() will unregister the net
- device, and release the PCMCIA configuration. If the device is
- still open, this will be postponed until it is closed.
-*/
-
static void tc574_release(struct pcmcia_device *link)
{
pcmcia_disable_device(link);
@@ -502,14 +476,14 @@ static void dump_status(struct net_device *dev)
{
unsigned int ioaddr = dev->base_addr;
EL3WINDOW(1);
- printk(KERN_INFO " irq status %04x, rx status %04x, tx status "
- "%02x, tx free %04x\n", inw(ioaddr+EL3_STATUS),
- inw(ioaddr+RxStatus), inb(ioaddr+TxStatus),
- inw(ioaddr+TxFree));
+ netdev_info(dev, " irq status %04x, rx status %04x, tx status %02x, tx free %04x\n",
+ inw(ioaddr+EL3_STATUS),
+ inw(ioaddr+RxStatus), inb(ioaddr+TxStatus),
+ inw(ioaddr+TxFree));
EL3WINDOW(4);
- printk(KERN_INFO " diagnostics: fifo %04x net %04x ethernet %04x"
- " media %04x\n", inw(ioaddr+0x04), inw(ioaddr+0x06),
- inw(ioaddr+0x08), inw(ioaddr+0x0a));
+ netdev_info(dev, " diagnostics: fifo %04x net %04x ethernet %04x media %04x\n",
+ inw(ioaddr+0x04), inw(ioaddr+0x06),
+ inw(ioaddr+0x08), inw(ioaddr+0x0a));
EL3WINDOW(1);
}
@@ -523,7 +497,7 @@ static void tc574_wait_for_completion(struct net_device *dev, int cmd)
while (--i > 0)
if (!(inw(dev->base_addr + EL3_STATUS) & 0x1000)) break;
if (i == 0)
- printk(KERN_NOTICE "%s: command 0x%04x did not complete!\n", dev->name, cmd);
+ netdev_notice(dev, "command 0x%04x did not complete!\n", cmd);
}
/* Read a word from the EEPROM using the regular EEPROM access register.
@@ -710,7 +684,7 @@ static int el3_open(struct net_device *dev)
netif_start_queue(dev);
tc574_reset(dev);
- lp->media.function = &media_check;
+ lp->media.function = media_check;
lp->media.data = (unsigned long) dev;
lp->media.expires = jiffies + HZ;
add_timer(&lp->media);
@@ -725,7 +699,7 @@ static void el3_tx_timeout(struct net_device *dev)
{
unsigned int ioaddr = dev->base_addr;
- printk(KERN_NOTICE "%s: Transmit timed out!\n", dev->name);
+ netdev_notice(dev, "Transmit timed out!\n");
dump_status(dev);
dev->stats.tx_errors++;
dev->trans_start = jiffies; /* prevent tx timeout */
@@ -848,8 +822,8 @@ static irqreturn_t el3_interrupt(int irq, void *dev_id)
EL3WINDOW(4);
fifo_diag = inw(ioaddr + Wn4_FIFODiag);
EL3WINDOW(1);
- printk(KERN_NOTICE "%s: adapter failure, FIFO diagnostic"
- " register %04x.\n", dev->name, fifo_diag);
+ netdev_notice(dev, "adapter failure, FIFO diagnostic register %04x\n",
+ fifo_diag);
if (fifo_diag & 0x0400) {
/* Tx overrun */
tc574_wait_for_completion(dev, TxReset);
@@ -903,7 +877,7 @@ static void media_check(unsigned long arg)
this, we can limp along even if the interrupt is blocked */
if ((inw(ioaddr + EL3_STATUS) & IntLatch) && (inb(ioaddr + Timer) == 0xff)) {
if (!lp->fast_poll)
- printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name);
+ netdev_info(dev, "interrupt(s) dropped!\n");
local_irq_save(flags);
el3_interrupt(dev->irq, dev);
@@ -926,23 +900,21 @@ static void media_check(unsigned long arg)
if (media != lp->media_status) {
if ((media ^ lp->media_status) & 0x0004)
- printk(KERN_INFO "%s: %s link beat\n", dev->name,
- (lp->media_status & 0x0004) ? "lost" : "found");
+ netdev_info(dev, "%s link beat\n",
+ (lp->media_status & 0x0004) ? "lost" : "found");
if ((media ^ lp->media_status) & 0x0020) {
lp->partner = 0;
if (lp->media_status & 0x0020) {
- printk(KERN_INFO "%s: autonegotiation restarted\n",
- dev->name);
+ netdev_info(dev, "autonegotiation restarted\n");
} else if (partner) {
partner &= lp->advertising;
lp->partner = partner;
- printk(KERN_INFO "%s: autonegotiation complete: "
- "%sbaseT-%cD selected\n", dev->name,
- ((partner & 0x0180) ? "100" : "10"),
- ((partner & 0x0140) ? 'F' : 'H'));
+ netdev_info(dev, "autonegotiation complete: "
+ "%dbaseT-%cD selected\n",
+ (partner & 0x0180) ? 100 : 10,
+ (partner & 0x0140) ? 'F' : 'H');
} else {
- printk(KERN_INFO "%s: link partner did not autonegotiate\n",
- dev->name);
+ netdev_info(dev, "link partner did not autonegotiate\n");
}
EL3WINDOW(3);
@@ -952,10 +924,9 @@ static void media_check(unsigned long arg)
}
if (media & 0x0010)
- printk(KERN_INFO "%s: remote fault detected\n",
- dev->name);
+ netdev_info(dev, "remote fault detected\n");
if (media & 0x0002)
- printk(KERN_INFO "%s: jabber detected\n", dev->name);
+ netdev_info(dev, "jabber detected\n");
lp->media_status = media;
}
spin_unlock_irqrestore(&lp->window_lock, flags);
@@ -1065,16 +1036,6 @@ static int el3_rx(struct net_device *dev, int worklimit)
return worklimit;
}
-static void netdev_get_drvinfo(struct net_device *dev,
- struct ethtool_drvinfo *info)
-{
- strcpy(info->driver, "3c574_cs");
-}
-
-static const struct ethtool_ops netdev_ethtool_ops = {
- .get_drvinfo = netdev_get_drvinfo,
-};
-
/* Provide ioctl() calls to examine the MII xcvr state. */
static int el3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
@@ -1198,9 +1159,7 @@ MODULE_DEVICE_TABLE(pcmcia, tc574_ids);
static struct pcmcia_driver tc574_driver = {
.owner = THIS_MODULE,
- .drv = {
- .name = "3c574_cs",
- },
+ .name = "3c574_cs",
.probe = tc574_probe,
.remove = tc574_detach,
.id_table = tc574_ids,
diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c
index 61f9cf2100ff..79b9ca0dbdb4 100644
--- a/drivers/net/pcmcia/3c589_cs.c
+++ b/drivers/net/pcmcia/3c589_cs.c
@@ -19,6 +19,8 @@
======================================================================*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define DRV_NAME "3c589_cs"
#define DRV_VERSION "1.162-ac"
@@ -41,7 +43,6 @@
#include <linux/bitops.h>
#include <linux/jiffies.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/ciscode.h>
@@ -176,14 +177,6 @@ static const struct ethtool_ops netdev_ethtool_ops;
static void tc589_detach(struct pcmcia_device *p_dev);
-/*======================================================================
-
- tc589_attach() creates an "instance" of the driver, allocating
- local data structures for one device. The device is registered
- with Card Services.
-
-======================================================================*/
-
static const struct net_device_ops el3_netdev_ops = {
.ndo_open = el3_open,
.ndo_stop = el3_close,
@@ -216,9 +209,8 @@ static int tc589_probe(struct pcmcia_device *link)
link->resource[0]->end = 16;
link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
- link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.IntType = INT_MEMORY_AND_IO;
- link->conf.ConfigIndex = 1;
+ link->config_flags |= CONF_ENABLE_IRQ;
+ link->config_index = 1;
dev->netdev_ops = &el3_netdev_ops;
dev->watchdog_timeo = TX_TIMEOUT;
@@ -226,16 +218,7 @@ static int tc589_probe(struct pcmcia_device *link)
SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
return tc589_config(link);
-} /* tc589_attach */
-
-/*======================================================================
-
- This deletes a driver "instance". The device is de-registered
- with Card Services. If it has been released, all local data
- structures are freed. Otherwise, the structures will be freed
- when the device is released.
-
-======================================================================*/
+}
static void tc589_detach(struct pcmcia_device *link)
{
@@ -250,21 +233,13 @@ static void tc589_detach(struct pcmcia_device *link)
free_netdev(dev);
} /* tc589_detach */
-/*======================================================================
-
- tc589_config() is scheduled to run after a CARD_INSERTION event
- is received, to configure the PCMCIA socket, and to make the
- ethernet device available to the system.
-
-======================================================================*/
-
static int tc589_config(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
__be16 *phys_addr;
int ret, i, j, multi = 0, fifo;
unsigned int ioaddr;
- char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
+ static const char * const ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
u8 *buf;
size_t len;
@@ -273,8 +248,7 @@ static int tc589_config(struct pcmcia_device *link)
phys_addr = (__be16 *)dev->dev_addr;
/* Is this a 3c562? */
if (link->manf_id != MANFID_3COM)
- printk(KERN_INFO "3c589_cs: hmmm, is this really a "
- "3Com card??\n");
+ dev_info(&link->dev, "hmmm, is this really a 3Com card??\n");
multi = (link->card_id == PRODID_3COM_3C562);
link->io_lines = 16;
@@ -294,7 +268,7 @@ static int tc589_config(struct pcmcia_device *link)
if (ret)
goto failed;
- ret = pcmcia_request_configuration(link, &link->conf);
+ ret = pcmcia_enable_device(link);
if (ret)
goto failed;
@@ -315,8 +289,8 @@ static int tc589_config(struct pcmcia_device *link)
for (i = 0; i < 3; i++)
phys_addr[i] = htons(read_eeprom(ioaddr, i));
if (phys_addr[0] == htons(0x6060)) {
- printk(KERN_ERR "3c589_cs: IO port conflict at 0x%03lx"
- "-0x%03lx\n", dev->base_addr, dev->base_addr+15);
+ dev_err(&link->dev, "IO port conflict at 0x%03lx-0x%03lx\n",
+ dev->base_addr, dev->base_addr+15);
goto failed;
}
}
@@ -330,12 +304,12 @@ static int tc589_config(struct pcmcia_device *link)
if ((if_port >= 0) && (if_port <= 3))
dev->if_port = if_port;
else
- printk(KERN_ERR "3c589_cs: invalid if_port requested\n");
+ dev_err(&link->dev, "invalid if_port requested\n");
SET_NETDEV_DEV(dev, &link->dev);
if (register_netdev(dev) != 0) {
- printk(KERN_ERR "3c589_cs: register_netdev() failed\n");
+ dev_err(&link->dev, "register_netdev() failed\n");
goto failed;
}
@@ -352,14 +326,6 @@ failed:
return -ENODEV;
} /* tc589_config */
-/*======================================================================
-
- After a card is removed, tc589_release() will unregister the net
- device, and release the PCMCIA configuration. If the device is
- still open, this will be postponed until it is closed.
-
-======================================================================*/
-
static void tc589_release(struct pcmcia_device *link)
{
pcmcia_disable_device(link);
@@ -537,7 +503,7 @@ static int el3_open(struct net_device *dev)
tc589_reset(dev);
init_timer(&lp->media);
- lp->media.function = &media_check;
+ lp->media.function = media_check;
lp->media.data = (unsigned long) dev;
lp->media.expires = jiffies + HZ;
add_timer(&lp->media);
@@ -955,9 +921,7 @@ MODULE_DEVICE_TABLE(pcmcia, tc589_ids);
static struct pcmcia_driver tc589_driver = {
.owner = THIS_MODULE,
- .drv = {
- .name = "3c589_cs",
- },
+ .name = "3c589_cs",
.probe = tc589_probe,
.remove = tc589_detach,
.id_table = tc589_ids,
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c
index 5f05ffb240cc..d2e166e29dda 100644
--- a/drivers/net/pcmcia/axnet_cs.c
+++ b/drivers/net/pcmcia/axnet_cs.c
@@ -24,6 +24,8 @@
======================================================================*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -32,14 +34,12 @@
#include <linux/timer.h>
#include <linux/delay.h>
#include <linux/spinlock.h>
-#include <linux/ethtool.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/crc32.h>
#include <linux/mii.h>
#include "../8390.h"
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ciscode.h>
#include <pcmcia/ds.h>
@@ -86,7 +86,6 @@ static netdev_tx_t axnet_start_xmit(struct sk_buff *skb,
static struct net_device_stats *get_stats(struct net_device *dev);
static void set_multicast_list(struct net_device *dev);
static void axnet_tx_timeout(struct net_device *dev);
-static const struct ethtool_ops netdev_ethtool_ops;
static irqreturn_t ei_irq_wrapper(int irq, void *dev_id);
static void ei_watchdog(u_long arg);
static void axnet_reset_8390(struct net_device *dev);
@@ -140,14 +139,6 @@ static const struct net_device_ops axnet_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
};
-/*======================================================================
-
- axnet_attach() creates an "instance" of the driver, allocating
- local data structures for one device. The device is registered
- with Card Services.
-
-======================================================================*/
-
static int axnet_probe(struct pcmcia_device *link)
{
axnet_dev_t *info;
@@ -166,26 +157,15 @@ static int axnet_probe(struct pcmcia_device *link)
info = PRIV(dev);
info->p_dev = link;
link->priv = dev;
- link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.IntType = INT_MEMORY_AND_IO;
+ link->config_flags |= CONF_ENABLE_IRQ;
dev->netdev_ops = &axnet_netdev_ops;
- SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
dev->watchdog_timeo = TX_TIMEOUT;
return axnet_config(link);
} /* axnet_attach */
-/*======================================================================
-
- This deletes a driver "instance". The device is de-registered
- with Card Services. If it has been released, all local data
- structures are freed. Otherwise, the structures will be freed
- when the device is released.
-
-======================================================================*/
-
static void axnet_detach(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
@@ -231,7 +211,7 @@ static int get_prom(struct pcmcia_device *link)
};
/* Not much of a test, but the alternatives are messy */
- if (link->conf.ConfigBase != 0x03c0)
+ if (link->config_base != 0x03c0)
return 0;
axnet_reset_8390(dev);
@@ -248,14 +228,6 @@ static int get_prom(struct pcmcia_device *link)
return 1;
} /* get_prom */
-/*======================================================================
-
- axnet_config() is scheduled to run after a CARD_INSERTION event
- is received, to configure the PCMCIA socket, and to make the
- ethernet device available to the system.
-
-======================================================================*/
-
static int try_io_port(struct pcmcia_device *link)
{
int j, ret;
@@ -286,35 +258,16 @@ static int try_io_port(struct pcmcia_device *link)
}
}
-static int axnet_configcheck(struct pcmcia_device *p_dev,
- cistpl_cftable_entry_t *cfg,
- cistpl_cftable_entry_t *dflt,
- unsigned int vcc,
- void *priv_data)
+static int axnet_configcheck(struct pcmcia_device *p_dev, void *priv_data)
{
- int i;
- cistpl_io_t *io = &cfg->io;
+ if (p_dev->config_index == 0)
+ return -EINVAL;
- if (cfg->index == 0 || cfg->io.nwin == 0)
+ p_dev->config_index = 0x05;
+ if (p_dev->resource[0]->end + p_dev->resource[1]->end < 32)
return -ENODEV;
- p_dev->conf.ConfigIndex = 0x05;
- /* For multifunction cards, by convention, we configure the
- network function with window 0, and serial with window 1 */
- if (io->nwin > 1) {
- i = (io->win[1].len > io->win[0].len);
- p_dev->resource[1]->start = io->win[1-i].base;
- p_dev->resource[1]->end = io->win[1-i].len;
- } else {
- i = p_dev->resource[1]->end = 0;
- }
- p_dev->resource[0]->start = io->win[i].base;
- p_dev->resource[0]->end = io->win[i].len;
- p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
- if (p_dev->resource[0]->end + p_dev->resource[1]->end >= 32)
- return try_io_port(p_dev);
-
- return -ENODEV;
+ return try_io_port(p_dev);
}
static int axnet_config(struct pcmcia_device *link)
@@ -326,20 +279,19 @@ static int axnet_config(struct pcmcia_device *link)
dev_dbg(&link->dev, "axnet_config(0x%p)\n", link);
/* don't trust the CIS on this; Linksys got it wrong */
- link->conf.Present = 0x63;
+ link->config_regs = 0x63;
+ link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
ret = pcmcia_loop_config(link, axnet_configcheck, NULL);
if (ret != 0)
goto failed;
if (!link->irq)
goto failed;
+
+ if (resource_size(link->resource[1]) == 8)
+ link->config_flags |= CONF_ENABLE_SPKR;
- if (resource_size(link->resource[1]) == 8) {
- link->conf.Attributes |= CONF_ENABLE_SPKR;
- link->conf.Status = CCSR_AUDIO_ENA;
- }
-
- ret = pcmcia_request_configuration(link, &link->conf);
+ ret = pcmcia_enable_device(link);
if (ret)
goto failed;
@@ -347,8 +299,8 @@ static int axnet_config(struct pcmcia_device *link)
dev->base_addr = link->resource[0]->start;
if (!get_prom(link)) {
- printk(KERN_NOTICE "axnet_cs: this is not an AX88190 card!\n");
- printk(KERN_NOTICE "axnet_cs: use pcnet_cs instead.\n");
+ pr_notice("this is not an AX88190 card!\n");
+ pr_notice("use pcnet_cs instead.\n");
goto failed;
}
@@ -357,10 +309,10 @@ static int axnet_config(struct pcmcia_device *link)
ei_status.tx_start_page = AXNET_START_PG;
ei_status.rx_start_page = AXNET_START_PG + TX_PAGES;
ei_status.stop_page = AXNET_STOP_PG;
- ei_status.reset_8390 = &axnet_reset_8390;
- ei_status.get_8390_hdr = &get_8390_hdr;
- ei_status.block_input = &block_input;
- ei_status.block_output = &block_output;
+ ei_status.reset_8390 = axnet_reset_8390;
+ ei_status.get_8390_hdr = get_8390_hdr;
+ ei_status.block_input = block_input;
+ ei_status.block_output = block_output;
if (inb(dev->base_addr + AXNET_TEST) != 0)
info->flags |= IS_AX88790;
@@ -393,19 +345,18 @@ static int axnet_config(struct pcmcia_device *link)
SET_NETDEV_DEV(dev, &link->dev);
if (register_netdev(dev) != 0) {
- printk(KERN_NOTICE "axnet_cs: register_netdev() failed\n");
+ pr_notice("register_netdev() failed\n");
goto failed;
}
- printk(KERN_INFO "%s: Asix AX88%d90: io %#3lx, irq %d, "
- "hw_addr %pM\n",
- dev->name, ((info->flags & IS_AX88790) ? 7 : 1),
- dev->base_addr, dev->irq,
- dev->dev_addr);
+ netdev_info(dev, "Asix AX88%d90: io %#3lx, irq %d, hw_addr %pM\n",
+ ((info->flags & IS_AX88790) ? 7 : 1),
+ dev->base_addr, dev->irq, dev->dev_addr);
if (info->phy_id != -1) {
- dev_dbg(&link->dev, " MII transceiver at index %d, status %x.\n", info->phy_id, j);
+ netdev_dbg(dev, " MII transceiver at index %d, status %x\n",
+ info->phy_id, j);
} else {
- printk(KERN_NOTICE " No MII transceivers found!\n");
+ netdev_notice(dev, " No MII transceivers found!\n");
}
return 0;
@@ -414,14 +365,6 @@ failed:
return -ENODEV;
} /* axnet_config */
-/*======================================================================
-
- After a card is removed, axnet_release() will unregister the net
- device, and release the PCMCIA configuration. If the device is
- still open, this will be postponed until it is closed.
-
-======================================================================*/
-
static void axnet_release(struct pcmcia_device *link)
{
pcmcia_disable_device(link);
@@ -532,7 +475,7 @@ static int axnet_open(struct net_device *dev)
info->link_status = 0x00;
init_timer(&info->watchdog);
- info->watchdog.function = &ei_watchdog;
+ info->watchdog.function = ei_watchdog;
info->watchdog.data = (u_long)dev;
info->watchdog.expires = jiffies + HZ;
add_timer(&info->watchdog);
@@ -585,8 +528,7 @@ static void axnet_reset_8390(struct net_device *dev)
outb_p(ENISR_RESET, nic_base + EN0_ISR); /* Ack intr. */
if (i == 100)
- printk(KERN_ERR "%s: axnet_reset_8390() did not complete.\n",
- dev->name);
+ netdev_err(dev, "axnet_reset_8390() did not complete\n");
} /* axnet_reset_8390 */
@@ -613,7 +555,7 @@ static void ei_watchdog(u_long arg)
this, we can limp along even if the interrupt is blocked */
if (info->stale++ && (inb_p(nic_base + EN0_ISR) & ENISR_ALL)) {
if (!info->fast_poll)
- printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name);
+ netdev_info(dev, "interrupt(s) dropped!\n");
ei_irq_wrapper(dev->irq, dev);
info->fast_poll = HZ;
}
@@ -628,7 +570,7 @@ static void ei_watchdog(u_long arg)
goto reschedule;
link = mdio_read(mii_addr, info->phy_id, 1);
if (!link || (link == 0xffff)) {
- printk(KERN_INFO "%s: MII is missing!\n", dev->name);
+ netdev_info(dev, "MII is missing!\n");
info->phy_id = -1;
goto reschedule;
}
@@ -636,18 +578,14 @@ static void ei_watchdog(u_long arg)
link &= 0x0004;
if (link != info->link_status) {
u_short p = mdio_read(mii_addr, info->phy_id, 5);
- printk(KERN_INFO "%s: %s link beat\n", dev->name,
- (link) ? "found" : "lost");
+ netdev_info(dev, "%s link beat\n", link ? "found" : "lost");
if (link) {
info->duplex_flag = (p & 0x0140) ? 0x80 : 0x00;
if (p)
- printk(KERN_INFO "%s: autonegotiation complete: "
- "%sbaseT-%cD selected\n", dev->name,
- ((p & 0x0180) ? "100" : "10"),
- ((p & 0x0140) ? 'F' : 'H'));
+ netdev_info(dev, "autonegotiation complete: %dbaseT-%cD selected\n",
+ (p & 0x0180) ? 100 : 10, (p & 0x0140) ? 'F' : 'H');
else
- printk(KERN_INFO "%s: link partner did not autonegotiate\n",
- dev->name);
+ netdev_info(dev, "link partner did not autonegotiate\n");
AX88190_init(dev, 1);
}
info->link_status = link;
@@ -658,16 +596,6 @@ reschedule:
add_timer(&info->watchdog);
}
-static void netdev_get_drvinfo(struct net_device *dev,
- struct ethtool_drvinfo *info)
-{
- strcpy(info->driver, "axnet_cs");
-}
-
-static const struct ethtool_ops netdev_ethtool_ops = {
- .get_drvinfo = netdev_get_drvinfo,
-};
-
/*====================================================================*/
static int axnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
@@ -783,9 +711,7 @@ MODULE_DEVICE_TABLE(pcmcia, axnet_ids);
static struct pcmcia_driver axnet_cs_driver = {
.owner = THIS_MODULE,
- .drv = {
- .name = "axnet_cs",
- },
+ .name = "axnet_cs",
.probe = axnet_probe,
.remove = axnet_detach,
.id_table = axnet_ids,
@@ -855,9 +781,6 @@ module_exit(exit_axnet_cs);
*/
-static const char version_8390[] = KERN_INFO \
- "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@scyld.com)\n";
-
#include <linux/bitops.h>
#include <asm/irq.h>
#include <linux/fcntl.h>
@@ -1004,9 +927,11 @@ static void axnet_tx_timeout(struct net_device *dev)
isr = inb(e8390_base+EN0_ISR);
spin_unlock_irqrestore(&ei_local->page_lock, flags);
- printk(KERN_DEBUG "%s: Tx timed out, %s TSR=%#2x, ISR=%#2x, t=%d.\n",
- dev->name, (txsr & ENTSR_ABT) ? "excess collisions." :
- (isr) ? "lost interrupt?" : "cable problem?", txsr, isr, tickssofar);
+ netdev_printk(KERN_DEBUG, dev,
+ "Tx timed out, %s TSR=%#2x, ISR=%#2x, t=%d.\n",
+ (txsr & ENTSR_ABT) ? "excess collisions." :
+ (isr) ? "lost interrupt?" : "cable problem?",
+ txsr, isr, tickssofar);
if (!isr && !dev->stats.tx_packets)
{
@@ -1076,22 +1001,28 @@ static netdev_tx_t axnet_start_xmit(struct sk_buff *skb,
output_page = ei_local->tx_start_page;
ei_local->tx1 = send_length;
if (ei_debug && ei_local->tx2 > 0)
- printk(KERN_DEBUG "%s: idle transmitter tx2=%d, lasttx=%d, txing=%d.\n",
- dev->name, ei_local->tx2, ei_local->lasttx, ei_local->txing);
+ netdev_printk(KERN_DEBUG, dev,
+ "idle transmitter tx2=%d, lasttx=%d, txing=%d\n",
+ ei_local->tx2, ei_local->lasttx,
+ ei_local->txing);
}
else if (ei_local->tx2 == 0)
{
output_page = ei_local->tx_start_page + TX_PAGES/2;
ei_local->tx2 = send_length;
if (ei_debug && ei_local->tx1 > 0)
- printk(KERN_DEBUG "%s: idle transmitter, tx1=%d, lasttx=%d, txing=%d.\n",
- dev->name, ei_local->tx1, ei_local->lasttx, ei_local->txing);
+ netdev_printk(KERN_DEBUG, dev,
+ "idle transmitter, tx1=%d, lasttx=%d, txing=%d\n",
+ ei_local->tx1, ei_local->lasttx,
+ ei_local->txing);
}
else
{ /* We should never get here. */
if (ei_debug)
- printk(KERN_DEBUG "%s: No Tx buffers free! tx1=%d tx2=%d last=%d\n",
- dev->name, ei_local->tx1, ei_local->tx2, ei_local->lasttx);
+ netdev_printk(KERN_DEBUG, dev,
+ "No Tx buffers free! tx1=%d tx2=%d last=%d\n",
+ ei_local->tx1, ei_local->tx2,
+ ei_local->lasttx);
ei_local->irqlock = 0;
netif_stop_queue(dev);
outb_p(ENISR_ALL, e8390_base + EN0_IMR);
@@ -1179,23 +1110,26 @@ static irqreturn_t ax_interrupt(int irq, void *dev_id)
spin_lock_irqsave(&ei_local->page_lock, flags);
- if (ei_local->irqlock)
- {
+ if (ei_local->irqlock) {
#if 1 /* This might just be an interrupt for a PCI device sharing this line */
+ const char *msg;
/* The "irqlock" check is only for testing. */
- printk(ei_local->irqlock
- ? "%s: Interrupted while interrupts are masked! isr=%#2x imr=%#2x.\n"
- : "%s: Reentering the interrupt handler! isr=%#2x imr=%#2x.\n",
- dev->name, inb_p(e8390_base + EN0_ISR),
- inb_p(e8390_base + EN0_IMR));
+ if (ei_local->irqlock)
+ msg = "Interrupted while interrupts are masked!";
+ else
+ msg = "Reentering the interrupt handler!";
+ netdev_info(dev, "%s, isr=%#2x imr=%#2x\n",
+ msg,
+ inb_p(e8390_base + EN0_ISR),
+ inb_p(e8390_base + EN0_IMR));
#endif
spin_unlock_irqrestore(&ei_local->page_lock, flags);
return IRQ_NONE;
}
if (ei_debug > 3)
- printk(KERN_DEBUG "%s: interrupt(isr=%#2.2x).\n", dev->name,
- inb_p(e8390_base + EN0_ISR));
+ netdev_printk(KERN_DEBUG, dev, "interrupt(isr=%#2.2x)\n",
+ inb_p(e8390_base + EN0_ISR));
outb_p(0x00, e8390_base + EN0_ISR);
ei_local->irqlock = 1;
@@ -1206,7 +1140,8 @@ static irqreturn_t ax_interrupt(int irq, void *dev_id)
{
if (!netif_running(dev) || (interrupts == 0xff)) {
if (ei_debug > 1)
- printk(KERN_WARNING "%s: interrupt from stopped card\n", dev->name);
+ netdev_warn(dev,
+ "interrupt from stopped card\n");
outb_p(interrupts, e8390_base + EN0_ISR);
interrupts = 0;
break;
@@ -1249,11 +1184,12 @@ static irqreturn_t ax_interrupt(int irq, void *dev_id)
{
/* 0xFF is valid for a card removal */
if(interrupts!=0xFF)
- printk(KERN_WARNING "%s: Too much work at interrupt, status %#2.2x\n",
- dev->name, interrupts);
+ netdev_warn(dev, "Too much work at interrupt, status %#2.2x\n",
+ interrupts);
outb_p(ENISR_ALL, e8390_base + EN0_ISR); /* Ack. most intrs. */
} else {
- printk(KERN_WARNING "%s: unknown interrupt %#2x\n", dev->name, interrupts);
+ netdev_warn(dev, "unknown interrupt %#2x\n",
+ interrupts);
outb_p(0xff, e8390_base + EN0_ISR); /* Ack. all intrs. */
}
}
@@ -1287,18 +1223,19 @@ static void ei_tx_err(struct net_device *dev)
unsigned char tx_was_aborted = txsr & (ENTSR_ABT+ENTSR_FU);
#ifdef VERBOSE_ERROR_DUMP
- printk(KERN_DEBUG "%s: transmitter error (%#2x): ", dev->name, txsr);
+ netdev_printk(KERN_DEBUG, dev,
+ "transmitter error (%#2x):", txsr);
if (txsr & ENTSR_ABT)
- printk("excess-collisions ");
+ pr_cont(" excess-collisions");
if (txsr & ENTSR_ND)
- printk("non-deferral ");
+ pr_cont(" non-deferral");
if (txsr & ENTSR_CRS)
- printk("lost-carrier ");
+ pr_cont(" lost-carrier");
if (txsr & ENTSR_FU)
- printk("FIFO-underrun ");
+ pr_cont(" FIFO-underrun");
if (txsr & ENTSR_CDH)
- printk("lost-heartbeat ");
- printk("\n");
+ pr_cont(" lost-heartbeat");
+ pr_cont("\n");
#endif
if (tx_was_aborted)
@@ -1335,8 +1272,9 @@ static void ei_tx_intr(struct net_device *dev)
if (ei_local->tx1 < 0)
{
if (ei_local->lasttx != 1 && ei_local->lasttx != -1)
- printk(KERN_ERR "%s: bogus last_tx_buffer %d, tx1=%d.\n",
- ei_local->name, ei_local->lasttx, ei_local->tx1);
+ netdev_err(dev, "%s: bogus last_tx_buffer %d, tx1=%d\n",
+ ei_local->name, ei_local->lasttx,
+ ei_local->tx1);
ei_local->tx1 = 0;
if (ei_local->tx2 > 0)
{
@@ -1351,8 +1289,9 @@ static void ei_tx_intr(struct net_device *dev)
else if (ei_local->tx2 < 0)
{
if (ei_local->lasttx != 2 && ei_local->lasttx != -2)
- printk("%s: bogus last_tx_buffer %d, tx2=%d.\n",
- ei_local->name, ei_local->lasttx, ei_local->tx2);
+ netdev_info(dev, "%s: bogus last_tx_buffer %d, tx2=%d\n",
+ ei_local->name, ei_local->lasttx,
+ ei_local->tx2);
ei_local->tx2 = 0;
if (ei_local->tx1 > 0)
{
@@ -1365,8 +1304,9 @@ static void ei_tx_intr(struct net_device *dev)
else
ei_local->lasttx = 10, ei_local->txing = 0;
}
-// else printk(KERN_WARNING "%s: unexpected TX-done interrupt, lasttx=%d.\n",
-// dev->name, ei_local->lasttx);
+// else
+// netdev_warn(dev, "unexpected TX-done interrupt, lasttx=%d\n",
+// ei_local->lasttx);
/* Minimize Tx latency: update the statistics after we restart TXing. */
if (status & ENTSR_COL)
@@ -1429,8 +1369,8 @@ static void ei_receive(struct net_device *dev)
is that some clones crash in roughly the same way.
*/
if (ei_debug > 0 && this_frame != ei_local->current_page && (this_frame!=0x0 || rxing_page!=0xFF))
- printk(KERN_ERR "%s: mismatched read page pointers %2x vs %2x.\n",
- dev->name, this_frame, ei_local->current_page);
+ netdev_err(dev, "mismatched read page pointers %2x vs %2x\n",
+ this_frame, ei_local->current_page);
if (this_frame == rxing_page) /* Read all the frames? */
break; /* Done for now */
@@ -1446,9 +1386,10 @@ static void ei_receive(struct net_device *dev)
if (pkt_len < 60 || pkt_len > 1518)
{
if (ei_debug)
- printk(KERN_DEBUG "%s: bogus packet size: %d, status=%#2x nxpg=%#2x.\n",
- dev->name, rx_frame.count, rx_frame.status,
- rx_frame.next);
+ netdev_printk(KERN_DEBUG, dev,
+ "bogus packet size: %d, status=%#2x nxpg=%#2x\n",
+ rx_frame.count, rx_frame.status,
+ rx_frame.next);
dev->stats.rx_errors++;
dev->stats.rx_length_errors++;
}
@@ -1460,8 +1401,9 @@ static void ei_receive(struct net_device *dev)
if (skb == NULL)
{
if (ei_debug > 1)
- printk(KERN_DEBUG "%s: Couldn't allocate a sk_buff of size %d.\n",
- dev->name, pkt_len);
+ netdev_printk(KERN_DEBUG, dev,
+ "Couldn't allocate a sk_buff of size %d\n",
+ pkt_len);
dev->stats.rx_dropped++;
break;
}
@@ -1481,9 +1423,10 @@ static void ei_receive(struct net_device *dev)
else
{
if (ei_debug)
- printk(KERN_DEBUG "%s: bogus packet: status=%#2x nxpg=%#2x size=%d\n",
- dev->name, rx_frame.status, rx_frame.next,
- rx_frame.count);
+ netdev_printk(KERN_DEBUG, dev,
+ "bogus packet: status=%#2x nxpg=%#2x size=%d\n",
+ rx_frame.status, rx_frame.next,
+ rx_frame.count);
dev->stats.rx_errors++;
/* NB: The NIC counts CRC, frame and missed errors. */
if (pkt_stat & ENRSR_FO)
@@ -1493,8 +1436,8 @@ static void ei_receive(struct net_device *dev)
/* This _should_ never happen: it's here for avoiding bad clones. */
if (next_frame >= ei_local->stop_page) {
- printk("%s: next frame inconsistency, %#2x\n", dev->name,
- next_frame);
+ netdev_info(dev, "next frame inconsistency, %#2x\n",
+ next_frame);
next_frame = ei_local->rx_start_page;
}
ei_local->current_page = next_frame;
@@ -1529,7 +1472,7 @@ static void ei_rx_overrun(struct net_device *dev)
outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD);
if (ei_debug > 1)
- printk(KERN_DEBUG "%s: Receiver overrun.\n", dev->name);
+ netdev_printk(KERN_DEBUG, dev, "Receiver overrun\n");
dev->stats.rx_over_errors++;
/*
@@ -1726,7 +1669,7 @@ static void AX88190_init(struct net_device *dev, int startp)
{
outb_p(dev->dev_addr[i], e8390_base + EN1_PHYS_SHIFT(i));
if(inb_p(e8390_base + EN1_PHYS_SHIFT(i))!=dev->dev_addr[i])
- printk(KERN_ERR "Hw. address read/write mismap %d\n",i);
+ netdev_err(dev, "Hw. address read/write mismap %d\n", i);
}
outb_p(ei_local->rx_start_page, e8390_base + EN1_CURPAG);
@@ -1763,8 +1706,7 @@ static void NS8390_trigger_send(struct net_device *dev, unsigned int length,
if (inb_p(e8390_base) & E8390_TRANS)
{
- printk(KERN_WARNING "%s: trigger_send() called with the transmitter busy.\n",
- dev->name);
+ netdev_warn(dev, "trigger_send() called with the transmitter busy\n");
return;
}
outb_p(length & 0xff, e8390_base + EN0_TCNTLO);
diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c
index 3c400cfa82ae..27bfad76fc40 100644
--- a/drivers/net/pcmcia/com20020_cs.c
+++ b/drivers/net/pcmcia/com20020_cs.c
@@ -43,7 +43,6 @@
#include <linux/arcdevice.h>
#include <linux/com20020.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
@@ -52,23 +51,23 @@
#define VERSION "arcnet: COM20020 PCMCIA support loaded.\n"
-#ifdef DEBUG
static void regdump(struct net_device *dev)
{
+#ifdef DEBUG
int ioaddr = dev->base_addr;
int count;
- printk("com20020 register dump:\n");
+ netdev_dbg(dev, "register dump:\n");
for (count = ioaddr; count < ioaddr + 16; count++)
{
if (!(count % 16))
- printk("\n%04X: ", count);
- printk("%02X ", inb(count));
+ pr_cont("%04X:", count);
+ pr_cont(" %02X", inb(count));
}
- printk("\n");
+ pr_cont("\n");
- printk("buffer0 dump:\n");
+ netdev_dbg(dev, "buffer0 dump:\n");
/* set up the address register */
count = 0;
outb((count >> 8) | RDDATAflag | AUTOINCflag, _ADDR_HI);
@@ -77,19 +76,15 @@ static void regdump(struct net_device *dev)
for (count = 0; count < 256+32; count++)
{
if (!(count % 16))
- printk("\n%04X: ", count);
+ pr_cont("%04X:", count);
/* copy the data */
- printk("%02X ", inb(_MEMDATA));
+ pr_cont(" %02X", inb(_MEMDATA));
}
- printk("\n");
+ pr_cont("\n");
+#endif
}
-#else
-
-static inline void regdump(struct net_device *dev) { }
-
-#endif
/*====================================================================*/
@@ -123,14 +118,6 @@ typedef struct com20020_dev_t {
struct net_device *dev;
} com20020_dev_t;
-/*======================================================================
-
- com20020_attach() creates an "instance" of the driver, allocating
- local data structures for one device. The device is registered
- with Card Services.
-
-======================================================================*/
-
static int com20020_probe(struct pcmcia_device *p_dev)
{
com20020_dev_t *info;
@@ -160,8 +147,7 @@ static int com20020_probe(struct pcmcia_device *p_dev)
p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
p_dev->resource[0]->end = 16;
- p_dev->conf.Attributes = CONF_ENABLE_IRQ;
- p_dev->conf.IntType = INT_MEMORY_AND_IO;
+ p_dev->config_flags |= CONF_ENABLE_IRQ;
info->dev = dev;
p_dev->priv = info;
@@ -174,15 +160,6 @@ fail_alloc_info:
return -ENOMEM;
} /* com20020_attach */
-/*======================================================================
-
- This deletes a driver "instance". The device is de-registered
- with Card Services. If it has been released, all local data
- structures are freed. Otherwise, the structures will be freed
- when the device is released.
-
-======================================================================*/
-
static void com20020_detach(struct pcmcia_device *link)
{
struct com20020_dev_t *info = link->priv;
@@ -221,14 +198,6 @@ static void com20020_detach(struct pcmcia_device *link)
} /* com20020_detach */
-/*======================================================================
-
- com20020_config() is scheduled to run after a CARD_INSERTION event
- is received, to configure the PCMCIA socket, and to make the
- device available to the system.
-
-======================================================================*/
-
static int com20020_config(struct pcmcia_device *link)
{
struct arcnet_local *lp;
@@ -282,7 +251,7 @@ static int com20020_config(struct pcmcia_device *link)
dev->irq = link->irq;
- ret = pcmcia_request_configuration(link, &link->conf);
+ ret = pcmcia_enable_device(link);
if (ret)
goto failed;
@@ -301,13 +270,13 @@ static int com20020_config(struct pcmcia_device *link)
i = com20020_found(dev, 0); /* calls register_netdev */
if (i != 0) {
- dev_printk(KERN_NOTICE, &link->dev,
- "com20020_cs: com20020_found() failed\n");
+ dev_notice(&link->dev,
+ "com20020_found() failed\n");
goto failed;
}
- dev_dbg(&link->dev,KERN_INFO "%s: port %#3lx, irq %d\n",
- dev->name, dev->base_addr, dev->irq);
+ netdev_dbg(dev, "port %#3lx, irq %d\n",
+ dev->base_addr, dev->irq);
return 0;
failed:
@@ -316,14 +285,6 @@ failed:
return -ENODEV;
} /* com20020_config */
-/*======================================================================
-
- After a card is removed, com20020_release() will unregister the net
- device, and release the PCMCIA configuration. If the device is
- still open, this will be postponed until it is closed.
-
-======================================================================*/
-
static void com20020_release(struct pcmcia_device *link)
{
dev_dbg(&link->dev, "com20020_release\n");
@@ -366,9 +327,7 @@ MODULE_DEVICE_TABLE(pcmcia, com20020_ids);
static struct pcmcia_driver com20020_cs_driver = {
.owner = THIS_MODULE,
- .drv = {
- .name = "com20020_cs",
- },
+ .name = "com20020_cs",
.probe = com20020_probe,
.remove = com20020_detach,
.id_table = com20020_ids,
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
index 98fffb03ecd7..9226cda4d054 100644
--- a/drivers/net/pcmcia/fmvj18x_cs.c
+++ b/drivers/net/pcmcia/fmvj18x_cs.c
@@ -28,6 +28,8 @@
======================================================================*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define DRV_NAME "fmvj18x_cs"
#define DRV_VERSION "2.9"
@@ -49,7 +51,6 @@
#include <linux/ioport.h>
#include <linux/crc32.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ciscode.h>
#include <pcmcia/ds.h>
@@ -252,8 +253,7 @@ static int fmvj18x_probe(struct pcmcia_device *link)
link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
/* General socket configuration */
- link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.IntType = INT_MEMORY_AND_IO;
+ link->config_flags |= CONF_ENABLE_IRQ;
dev->netdev_ops = &fjn_netdev_ops;
dev->watchdog_timeo = TX_TIMEOUT;
@@ -291,7 +291,7 @@ static int mfc_try_io_port(struct pcmcia_device *link)
link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
if (link->resource[1]->start == 0) {
link->resource[1]->end = 0;
- printk(KERN_NOTICE "fmvj18x_cs: out of resource for serial\n");
+ pr_notice("out of resource for serial\n");
}
ret = pcmcia_request_io(link);
if (ret == 0)
@@ -313,7 +313,7 @@ static int ungermann_try_io_port(struct pcmcia_device *link)
ret = pcmcia_request_io(link);
if (ret == 0) {
/* calculate ConfigIndex value */
- link->conf.ConfigIndex =
+ link->config_index =
((link->resource[0]->start & 0x0f0) >> 3) | 0x22;
return ret;
}
@@ -321,11 +321,7 @@ static int ungermann_try_io_port(struct pcmcia_device *link)
return ret; /* RequestIO failed */
}
-static int fmvj18x_ioprobe(struct pcmcia_device *p_dev,
- cistpl_cftable_entry_t *cfg,
- cistpl_cftable_entry_t *dflt,
- unsigned int vcc,
- void *priv_data)
+static int fmvj18x_ioprobe(struct pcmcia_device *p_dev, void *priv_data)
{
return 0; /* strange, but that's what the code did already before... */
}
@@ -362,28 +358,28 @@ static int fmvj18x_config(struct pcmcia_device *link)
link->card_id == PRODID_TDK_NP9610 ||
link->card_id == PRODID_TDK_MN3200) {
/* MultiFunction Card */
- link->conf.ConfigBase = 0x800;
- link->conf.ConfigIndex = 0x47;
+ link->config_base = 0x800;
+ link->config_index = 0x47;
link->resource[1]->end = 8;
}
break;
case MANFID_NEC:
cardtype = NEC; /* MultiFunction Card */
- link->conf.ConfigBase = 0x800;
- link->conf.ConfigIndex = 0x47;
+ link->config_base = 0x800;
+ link->config_index = 0x47;
link->resource[1]->end = 8;
break;
case MANFID_KME:
cardtype = KME; /* MultiFunction Card */
- link->conf.ConfigBase = 0x800;
- link->conf.ConfigIndex = 0x47;
+ link->config_base = 0x800;
+ link->config_index = 0x47;
link->resource[1]->end = 8;
break;
case MANFID_CONTEC:
cardtype = CONTEC;
break;
case MANFID_FUJITSU:
- if (link->conf.ConfigBase == 0x0fe0)
+ if (link->config_base == 0x0fe0)
cardtype = MBH10302;
else if (link->card_id == PRODID_FUJITSU_MBH10302)
/* RATOC REX-5588/9822/4886's PRODID are 0004(=MBH10302),
@@ -403,10 +399,10 @@ static int fmvj18x_config(struct pcmcia_device *link)
case MANFID_FUJITSU:
if (link->card_id == PRODID_FUJITSU_MBH10304) {
cardtype = XXX10304; /* MBH10304 with buggy CIS */
- link->conf.ConfigIndex = 0x20;
+ link->config_index = 0x20;
} else {
cardtype = MBH10302; /* NextCom NC5310, etc. */
- link->conf.ConfigIndex = 1;
+ link->config_index = 1;
}
break;
case MANFID_UNGERMANN:
@@ -414,7 +410,7 @@ static int fmvj18x_config(struct pcmcia_device *link)
break;
default:
cardtype = MBH10302;
- link->conf.ConfigIndex = 1;
+ link->config_index = 1;
}
}
@@ -432,7 +428,7 @@ static int fmvj18x_config(struct pcmcia_device *link)
ret = pcmcia_request_irq(link, fjn_interrupt);
if (ret)
goto failed;
- ret = pcmcia_request_configuration(link, &link->conf);
+ ret = pcmcia_enable_device(link);
if (ret)
goto failed;
@@ -503,7 +499,7 @@ static int fmvj18x_config(struct pcmcia_device *link)
case XXX10304:
/* Read MACID from Buggy CIS */
if (fmvj18x_get_hwinfo(link, buggybuf) == -1) {
- printk(KERN_NOTICE "fmvj18x_cs: unable to read hardware net address.\n");
+ pr_notice("unable to read hardware net address\n");
goto failed;
}
for (i = 0 ; i < 6; i++) {
@@ -524,15 +520,14 @@ static int fmvj18x_config(struct pcmcia_device *link)
SET_NETDEV_DEV(dev, &link->dev);
if (register_netdev(dev) != 0) {
- printk(KERN_NOTICE "fmvj18x_cs: register_netdev() failed\n");
+ pr_notice("register_netdev() failed\n");
goto failed;
}
/* print current configuration */
- printk(KERN_INFO "%s: %s, sram %s, port %#3lx, irq %d, "
- "hw_addr %pM\n",
- dev->name, card_name, sram_config == 0 ? "4K TX*2" : "8K TX*2",
- dev->base_addr, dev->irq, dev->dev_addr);
+ netdev_info(dev, "%s, sram %s, port %#3lx, irq %d, hw_addr %pM\n",
+ card_name, sram_config == 0 ? "4K TX*2" : "8K TX*2",
+ dev->base_addr, dev->irq, dev->dev_addr);
return 0;
@@ -544,20 +539,18 @@ failed:
static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id)
{
- win_req_t req;
u_char __iomem *base;
int i, j;
/* Allocate a small memory window */
- req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
- req.Base = 0; req.Size = 0;
- req.AccessSpeed = 0;
- i = pcmcia_request_window(link, &req, &link->win);
+ link->resource[2]->flags |= WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
+ link->resource[2]->start = 0; link->resource[2]->end = 0;
+ i = pcmcia_request_window(link, link->resource[2], 0);
if (i != 0)
return -1;
- base = ioremap(req.Base, req.Size);
- pcmcia_map_mem_page(link, link->win, 0);
+ base = ioremap(link->resource[2]->start, resource_size(link->resource[2]));
+ pcmcia_map_mem_page(link, link->resource[2], 0);
/*
* MBH10304 CISTPL_FUNCE_LAN_NODE_ID format
@@ -582,7 +575,7 @@ static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id)
}
iounmap(base);
- j = pcmcia_release_window(link, link->win);
+ j = pcmcia_release_window(link, link->resource[2]);
return (i != 0x200) ? 0 : -1;
} /* fmvj18x_get_hwinfo */
@@ -590,27 +583,26 @@ static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id)
static int fmvj18x_setup_mfc(struct pcmcia_device *link)
{
- win_req_t req;
int i;
struct net_device *dev = link->priv;
unsigned int ioaddr;
local_info_t *lp = netdev_priv(dev);
/* Allocate a small memory window */
- req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
- req.Base = 0; req.Size = 0;
- req.AccessSpeed = 0;
- i = pcmcia_request_window(link, &req, &link->win);
+ link->resource[3]->flags = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
+ link->resource[3]->start = link->resource[3]->end = 0;
+ i = pcmcia_request_window(link, link->resource[3], 0);
if (i != 0)
return -1;
- lp->base = ioremap(req.Base, req.Size);
+ lp->base = ioremap(link->resource[3]->start,
+ resource_size(link->resource[3]));
if (lp->base == NULL) {
- printk(KERN_NOTICE "fmvj18x_cs: ioremap failed\n");
+ netdev_notice(dev, "ioremap failed\n");
return -1;
}
- i = pcmcia_map_mem_page(link, link->win, 0);
+ i = pcmcia_map_mem_page(link, link->resource[3], 0);
if (i != 0) {
iounmap(lp->base);
lp->base = NULL;
@@ -638,7 +630,6 @@ static void fmvj18x_release(struct pcmcia_device *link)
struct net_device *dev = link->priv;
local_info_t *lp = netdev_priv(dev);
u_char __iomem *tmp;
- int j;
dev_dbg(&link->dev, "fmvj18x_release\n");
@@ -646,7 +637,6 @@ static void fmvj18x_release(struct pcmcia_device *link)
tmp = lp->base;
lp->base = NULL; /* set NULL before iounmap */
iounmap(tmp);
- j = pcmcia_release_window(link, link->win);
}
pcmcia_disable_device(link);
@@ -708,9 +698,7 @@ MODULE_DEVICE_TABLE(pcmcia, fmvj18x_ids);
static struct pcmcia_driver fmvj18x_cs_driver = {
.owner = THIS_MODULE,
- .drv = {
- .name = "fmvj18x_cs",
- },
+ .name = "fmvj18x_cs",
.probe = fmvj18x_probe,
.remove = fmvj18x_detach,
.id_table = fmvj18x_ids,
@@ -800,17 +788,16 @@ static void fjn_tx_timeout(struct net_device *dev)
struct local_info_t *lp = netdev_priv(dev);
unsigned int ioaddr = dev->base_addr;
- printk(KERN_NOTICE "%s: transmit timed out with status %04x, %s?\n",
- dev->name, htons(inw(ioaddr + TX_STATUS)),
- inb(ioaddr + TX_STATUS) & F_TMT_RDY
- ? "IRQ conflict" : "network cable problem");
- printk(KERN_NOTICE "%s: timeout registers: %04x %04x %04x "
- "%04x %04x %04x %04x %04x.\n",
- dev->name, htons(inw(ioaddr + 0)),
- htons(inw(ioaddr + 2)), htons(inw(ioaddr + 4)),
- htons(inw(ioaddr + 6)), htons(inw(ioaddr + 8)),
- htons(inw(ioaddr +10)), htons(inw(ioaddr +12)),
- htons(inw(ioaddr +14)));
+ netdev_notice(dev, "transmit timed out with status %04x, %s?\n",
+ htons(inw(ioaddr + TX_STATUS)),
+ inb(ioaddr + TX_STATUS) & F_TMT_RDY
+ ? "IRQ conflict" : "network cable problem");
+ netdev_notice(dev, "timeout registers: %04x %04x %04x "
+ "%04x %04x %04x %04x %04x.\n",
+ htons(inw(ioaddr + 0)), htons(inw(ioaddr + 2)),
+ htons(inw(ioaddr + 4)), htons(inw(ioaddr + 6)),
+ htons(inw(ioaddr + 8)), htons(inw(ioaddr + 10)),
+ htons(inw(ioaddr + 12)), htons(inw(ioaddr + 14)));
dev->stats.tx_errors++;
/* ToDo: We should try to restart the adaptor... */
local_irq_disable();
@@ -845,13 +832,13 @@ static netdev_tx_t fjn_start_xmit(struct sk_buff *skb,
unsigned char *buf = skb->data;
if (length > ETH_FRAME_LEN) {
- printk(KERN_NOTICE "%s: Attempting to send a large packet"
- " (%d bytes).\n", dev->name, length);
+ netdev_notice(dev, "Attempting to send a large packet (%d bytes)\n",
+ length);
return NETDEV_TX_BUSY;
}
- pr_debug("%s: Transmitting a packet of length %lu.\n",
- dev->name, (unsigned long)skb->len);
+ netdev_dbg(dev, "Transmitting a packet of length %lu\n",
+ (unsigned long)skb->len);
dev->stats.tx_bytes += skb->len;
/* Disable both interrupts. */
@@ -904,7 +891,7 @@ static void fjn_reset(struct net_device *dev)
unsigned int ioaddr = dev->base_addr;
int i;
- pr_debug("fjn_reset(%s) called.\n",dev->name);
+ netdev_dbg(dev, "fjn_reset() called\n");
/* Reset controller */
if( sram_config == 0 )
@@ -988,8 +975,8 @@ static void fjn_rx(struct net_device *dev)
while ((inb(ioaddr + RX_MODE) & F_BUF_EMP) == 0) {
u_short status = inw(ioaddr + DATAPORT);
- pr_debug("%s: Rxing packet mode %02x status %04x.\n",
- dev->name, inb(ioaddr + RX_MODE), status);
+ netdev_dbg(dev, "Rxing packet mode %02x status %04x.\n",
+ inb(ioaddr + RX_MODE), status);
#ifndef final_version
if (status == 0) {
outb(F_SKP_PKT, ioaddr + RX_SKIP);
@@ -1008,16 +995,16 @@ static void fjn_rx(struct net_device *dev)
struct sk_buff *skb;
if (pkt_len > 1550) {
- printk(KERN_NOTICE "%s: The FMV-18x claimed a very "
- "large packet, size %d.\n", dev->name, pkt_len);
+ netdev_notice(dev, "The FMV-18x claimed a very large packet, size %d\n",
+ pkt_len);
outb(F_SKP_PKT, ioaddr + RX_SKIP);
dev->stats.rx_errors++;
break;
}
skb = dev_alloc_skb(pkt_len+2);
if (skb == NULL) {
- printk(KERN_NOTICE "%s: Memory squeeze, dropping "
- "packet (len %d).\n", dev->name, pkt_len);
+ netdev_notice(dev, "Memory squeeze, dropping packet (len %d)\n",
+ pkt_len);
outb(F_SKP_PKT, ioaddr + RX_SKIP);
dev->stats.rx_dropped++;
break;
diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c
index b0d06a3d962f..15d57f5b6f29 100644
--- a/drivers/net/pcmcia/ibmtr_cs.c
+++ b/drivers/net/pcmcia/ibmtr_cs.c
@@ -45,6 +45,8 @@
======================================================================*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/ptrace.h>
@@ -52,12 +54,10 @@
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/module.h>
-#include <linux/ethtool.h>
#include <linux/netdevice.h>
#include <linux/trdevice.h>
#include <linux/ibmtr.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
@@ -102,35 +102,16 @@ static void ibmtr_detach(struct pcmcia_device *p_dev);
typedef struct ibmtr_dev_t {
struct pcmcia_device *p_dev;
- struct net_device *dev;
- window_handle_t sram_win_handle;
- struct tok_info *ti;
+ struct net_device *dev;
+ struct tok_info *ti;
} ibmtr_dev_t;
-static void netdev_get_drvinfo(struct net_device *dev,
- struct ethtool_drvinfo *info)
-{
- strcpy(info->driver, "ibmtr_cs");
-}
-
-static const struct ethtool_ops netdev_ethtool_ops = {
- .get_drvinfo = netdev_get_drvinfo,
-};
-
static irqreturn_t ibmtr_interrupt(int irq, void *dev_id) {
ibmtr_dev_t *info = dev_id;
struct net_device *dev = info->dev;
return tok_interrupt(irq, dev);
};
-/*======================================================================
-
- ibmtr_attach() creates an "instance" of the driver, allocating
- local data structures for one device. The device is registered
- with Card Services.
-
-======================================================================*/
-
static int __devinit ibmtr_attach(struct pcmcia_device *link)
{
ibmtr_dev_t *info;
@@ -153,26 +134,14 @@ static int __devinit ibmtr_attach(struct pcmcia_device *link)
link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
link->resource[0]->end = 4;
- link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.IntType = INT_MEMORY_AND_IO;
- link->conf.Present = PRESENT_OPTION;
+ link->config_flags |= CONF_ENABLE_IRQ;
+ link->config_regs = PRESENT_OPTION;
info->dev = dev;
- SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
-
return ibmtr_config(link);
} /* ibmtr_attach */
-/*======================================================================
-
- This deletes a driver "instance". The device is de-registered
- with Card Services. If it has been released, all local data
- structures are freed. Otherwise, the structures will be freed
- when the device is released.
-
-======================================================================*/
-
static void ibmtr_detach(struct pcmcia_device *link)
{
struct ibmtr_dev_t *info = link->priv;
@@ -197,26 +166,17 @@ static void ibmtr_detach(struct pcmcia_device *link)
kfree(info);
} /* ibmtr_detach */
-/*======================================================================
-
- ibmtr_config() is scheduled to run after a CARD_INSERTION event
- is received, to configure the PCMCIA socket, and to make the
- token-ring device available to the system.
-
-======================================================================*/
-
static int __devinit ibmtr_config(struct pcmcia_device *link)
{
ibmtr_dev_t *info = link->priv;
struct net_device *dev = info->dev;
struct tok_info *ti = netdev_priv(dev);
- win_req_t req;
int i, ret;
dev_dbg(&link->dev, "ibmtr_config\n");
- link->conf.ConfigIndex = 0x61;
link->io_lines = 16;
+ link->config_index = 0x61;
/* Determine if this is PRIMARY or ALTERNATE. */
@@ -240,39 +200,39 @@ static int __devinit ibmtr_config(struct pcmcia_device *link)
ti->global_int_enable=GLOBAL_INT_ENABLE+((dev->irq==9) ? 2 : dev->irq);
/* Allocate the MMIO memory window */
- req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
- req.Attributes |= WIN_USE_WAIT;
- req.Base = 0;
- req.Size = 0x2000;
- req.AccessSpeed = 250;
- ret = pcmcia_request_window(link, &req, &link->win);
+ link->resource[2]->flags |= WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
+ link->resource[2]->flags |= WIN_USE_WAIT;
+ link->resource[2]->start = 0;
+ link->resource[2]->end = 0x2000;
+ ret = pcmcia_request_window(link, link->resource[2], 250);
if (ret)
goto failed;
- ret = pcmcia_map_mem_page(link, link->win, mmiobase);
+ ret = pcmcia_map_mem_page(link, link->resource[2], mmiobase);
if (ret)
goto failed;
- ti->mmio = ioremap(req.Base, req.Size);
+ ti->mmio = ioremap(link->resource[2]->start,
+ resource_size(link->resource[2]));
/* Allocate the SRAM memory window */
- req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
- req.Attributes |= WIN_USE_WAIT;
- req.Base = 0;
- req.Size = sramsize * 1024;
- req.AccessSpeed = 250;
- ret = pcmcia_request_window(link, &req, &info->sram_win_handle);
+ link->resource[3]->flags = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
+ link->resource[3]->flags |= WIN_USE_WAIT;
+ link->resource[3]->start = 0;
+ link->resource[3]->end = sramsize * 1024;
+ ret = pcmcia_request_window(link, link->resource[3], 250);
if (ret)
goto failed;
- ret = pcmcia_map_mem_page(link, info->sram_win_handle, srambase);
+ ret = pcmcia_map_mem_page(link, link->resource[3], srambase);
if (ret)
goto failed;
ti->sram_base = srambase >> 12;
- ti->sram_virt = ioremap(req.Base, req.Size);
- ti->sram_phys = req.Base;
+ ti->sram_virt = ioremap(link->resource[3]->start,
+ resource_size(link->resource[3]));
+ ti->sram_phys = link->resource[3]->start;
- ret = pcmcia_request_configuration(link, &link->conf);
+ ret = pcmcia_enable_device(link);
if (ret)
goto failed;
@@ -285,15 +245,14 @@ static int __devinit ibmtr_config(struct pcmcia_device *link)
i = ibmtr_probe_card(dev);
if (i != 0) {
- printk(KERN_NOTICE "ibmtr_cs: register_netdev() failed\n");
+ pr_notice("register_netdev() failed\n");
goto failed;
}
- printk(KERN_INFO
- "%s: port %#3lx, irq %d, mmio %#5lx, sram %#5lx, hwaddr=%pM\n",
- dev->name, dev->base_addr, dev->irq,
- (u_long)ti->mmio, (u_long)(ti->sram_base << 12),
- dev->dev_addr);
+ netdev_info(dev, "port %#3lx, irq %d, mmio %#5lx, sram %#5lx, hwaddr=%pM\n",
+ dev->base_addr, dev->irq,
+ (u_long)ti->mmio, (u_long)(ti->sram_base << 12),
+ dev->dev_addr);
return 0;
failed:
@@ -301,14 +260,6 @@ failed:
return -ENODEV;
} /* ibmtr_config */
-/*======================================================================
-
- After a card is removed, ibmtr_release() will unregister the net
- device, and release the PCMCIA configuration. If the device is
- still open, this will be postponed until it is closed.
-
-======================================================================*/
-
static void ibmtr_release(struct pcmcia_device *link)
{
ibmtr_dev_t *info = link->priv;
@@ -316,7 +267,7 @@ static void ibmtr_release(struct pcmcia_device *link)
dev_dbg(&link->dev, "ibmtr_release\n");
- if (link->win) {
+ if (link->resource[2]->end) {
struct tok_info *ti = netdev_priv(dev);
iounmap(ti->mmio);
}
@@ -398,9 +349,7 @@ MODULE_DEVICE_TABLE(pcmcia, ibmtr_ids);
static struct pcmcia_driver ibmtr_cs_driver = {
.owner = THIS_MODULE,
- .drv = {
- .name = "ibmtr_cs",
- },
+ .name = "ibmtr_cs",
.probe = ibmtr_attach,
.remove = ibmtr_detach,
.id_table = ibmtr_ids,
diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c
index 68f2deeb3ade..0a2b0f9cdf33 100644
--- a/drivers/net/pcmcia/nmclan_cs.c
+++ b/drivers/net/pcmcia/nmclan_cs.c
@@ -111,6 +111,8 @@ Log: nmclan_cs.c,v
---------------------------------------------------------------------------- */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#define DRV_NAME "nmclan_cs"
#define DRV_VERSION "0.16"
@@ -146,7 +148,6 @@ Include Files
#include <linux/ioport.h>
#include <linux/bitops.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
@@ -435,13 +436,6 @@ static const struct net_device_ops mace_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
};
-/* ----------------------------------------------------------------------------
-nmclan_attach
- Creates an "instance" of the driver, allocating local data
- structures for one device. The device is registered with Card
- Services.
----------------------------------------------------------------------------- */
-
static int nmclan_probe(struct pcmcia_device *link)
{
mace_private *lp;
@@ -460,10 +454,9 @@ static int nmclan_probe(struct pcmcia_device *link)
spin_lock_init(&lp->bank_lock);
link->resource[0]->end = 32;
link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
- link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.IntType = INT_MEMORY_AND_IO;
- link->conf.ConfigIndex = 1;
- link->conf.Present = PRESENT_OPTION;
+ link->config_flags |= CONF_ENABLE_IRQ;
+ link->config_index = 1;
+ link->config_regs = PRESENT_OPTION;
lp->tx_free_frames=AM2150_MAX_TX_FRAMES;
@@ -474,14 +467,6 @@ static int nmclan_probe(struct pcmcia_device *link)
return nmclan_config(link);
} /* nmclan_attach */
-/* ----------------------------------------------------------------------------
-nmclan_detach
- This deletes a driver "instance". The device is de-registered
- with Card Services. If it has been released, all local data
- structures are freed. Otherwise, the structures will be freed
- when the device is released.
----------------------------------------------------------------------------- */
-
static void nmclan_detach(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
@@ -519,7 +504,7 @@ static int mace_read(mace_private *lp, unsigned int ioaddr, int reg)
spin_unlock_irqrestore(&lp->bank_lock, flags);
break;
}
- return (data & 0xFF);
+ return data & 0xFF;
} /* mace_read */
/* ----------------------------------------------------------------------------
@@ -563,7 +548,7 @@ static int mace_init(mace_private *lp, unsigned int ioaddr, char *enet_addr)
/* Wait for reset bit to be cleared automatically after <= 200ns */;
if(++ct > 500)
{
- printk(KERN_ERR "mace: reset failed, card removed ?\n");
+ pr_err("reset failed, card removed?\n");
return -1;
}
udelay(1);
@@ -610,7 +595,7 @@ static int mace_init(mace_private *lp, unsigned int ioaddr, char *enet_addr)
{
if(++ ct > 500)
{
- printk(KERN_ERR "mace: ADDRCHG timeout, card removed ?\n");
+ pr_err("ADDRCHG timeout, card removed?\n");
return -1;
}
}
@@ -625,13 +610,6 @@ static int mace_init(mace_private *lp, unsigned int ioaddr, char *enet_addr)
return 0;
} /* mace_init */
-/* ----------------------------------------------------------------------------
-nmclan_config
- This routine is scheduled to run after a CARD_INSERTION event
- is received, to configure the PCMCIA socket, and to make the
- ethernet device available to the system.
----------------------------------------------------------------------------- */
-
static int nmclan_config(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
@@ -650,7 +628,7 @@ static int nmclan_config(struct pcmcia_device *link)
ret = pcmcia_request_exclusive_irq(link, mace_interrupt);
if (ret)
goto failed;
- ret = pcmcia_request_configuration(link, &link->conf);
+ ret = pcmcia_enable_device(link);
if (ret)
goto failed;
@@ -678,8 +656,8 @@ static int nmclan_config(struct pcmcia_device *link)
dev_dbg(&link->dev, "nmclan_cs configured: mace id=%x %x\n",
sig[0], sig[1]);
} else {
- printk(KERN_NOTICE "nmclan_cs: mace id not found: %x %x should"
- " be 0x40 0x?9\n", sig[0], sig[1]);
+ pr_notice("mace id not found: %x %x should be 0x40 0x?9\n",
+ sig[0], sig[1]);
return -ENODEV;
}
}
@@ -691,20 +669,18 @@ static int nmclan_config(struct pcmcia_device *link)
if (if_port <= 2)
dev->if_port = if_port;
else
- printk(KERN_NOTICE "nmclan_cs: invalid if_port requested\n");
+ pr_notice("invalid if_port requested\n");
SET_NETDEV_DEV(dev, &link->dev);
i = register_netdev(dev);
if (i != 0) {
- printk(KERN_NOTICE "nmclan_cs: register_netdev() failed\n");
+ pr_notice("register_netdev() failed\n");
goto failed;
}
- printk(KERN_INFO "%s: nmclan: port %#3lx, irq %d, %s port,"
- " hw_addr %pM\n",
- dev->name, dev->base_addr, dev->irq, if_names[dev->if_port],
- dev->dev_addr);
+ netdev_info(dev, "nmclan: port %#3lx, irq %d, %s port, hw_addr %pM\n",
+ dev->base_addr, dev->irq, if_names[dev->if_port], dev->dev_addr);
return 0;
failed:
@@ -712,12 +688,6 @@ failed:
return -ENODEV;
} /* nmclan_config */
-/* ----------------------------------------------------------------------------
-nmclan_release
- After a card is removed, nmclan_release() will unregister the
- net device, and release the PCMCIA configuration. If the device
- is still open, this will be postponed until it is closed.
----------------------------------------------------------------------------- */
static void nmclan_release(struct pcmcia_device *link)
{
dev_dbg(&link->dev, "nmclan_release\n");
@@ -798,8 +768,7 @@ static int mace_config(struct net_device *dev, struct ifmap *map)
if ((map->port != (u_char)(-1)) && (map->port != dev->if_port)) {
if (map->port <= 2) {
dev->if_port = map->port;
- printk(KERN_INFO "%s: switched to %s port\n", dev->name,
- if_names[dev->if_port]);
+ netdev_info(dev, "switched to %s port\n", if_names[dev->if_port]);
} else
return -EINVAL;
}
@@ -878,12 +847,12 @@ static void mace_tx_timeout(struct net_device *dev)
mace_private *lp = netdev_priv(dev);
struct pcmcia_device *link = lp->p_dev;
- printk(KERN_NOTICE "%s: transmit timed out -- ", dev->name);
+ netdev_notice(dev, "transmit timed out -- ");
#if RESET_ON_TIMEOUT
- printk("resetting card\n");
+ pr_cont("resetting card\n");
pcmcia_reset_card(link->socket);
#else /* #if RESET_ON_TIMEOUT */
- printk("NOT resetting card\n");
+ pr_cont("NOT resetting card\n");
#endif /* #if RESET_ON_TIMEOUT */
dev->trans_start = jiffies; /* prevent tx timeout */
netif_wake_queue(dev);
@@ -965,22 +934,21 @@ static irqreturn_t mace_interrupt(int irq, void *dev_id)
ioaddr = dev->base_addr;
if (lp->tx_irq_disabled) {
- printk(
- (lp->tx_irq_disabled?
- KERN_NOTICE "%s: Interrupt with tx_irq_disabled "
- "[isr=%02X, imr=%02X]\n":
- KERN_NOTICE "%s: Re-entering the interrupt handler "
- "[isr=%02X, imr=%02X]\n"),
- dev->name,
- inb(ioaddr + AM2150_MACE_BASE + MACE_IR),
- inb(ioaddr + AM2150_MACE_BASE + MACE_IMR)
- );
+ const char *msg;
+ if (lp->tx_irq_disabled)
+ msg = "Interrupt with tx_irq_disabled";
+ else
+ msg = "Re-entering the interrupt handler";
+ netdev_notice(dev, "%s [isr=%02X, imr=%02X]\n",
+ msg,
+ inb(ioaddr + AM2150_MACE_BASE + MACE_IR),
+ inb(ioaddr + AM2150_MACE_BASE + MACE_IMR));
/* WARNING: MACE_IR has been read! */
return IRQ_NONE;
}
if (!netif_device_present(dev)) {
- pr_debug("%s: interrupt from dead card\n", dev->name);
+ netdev_dbg(dev, "interrupt from dead card\n");
return IRQ_NONE;
}
@@ -1378,8 +1346,8 @@ static void BuildLAF(int *ladrf, int *adr)
printk(KERN_DEBUG " adr =%pM\n", adr);
printk(KERN_DEBUG " hashcode = %d(decimal), ladrf[0:63] =", hashcode);
for (i = 0; i < 8; i++)
- printk(KERN_CONT " %02X", ladrf[i]);
- printk(KERN_CONT "\n");
+ pr_cont(" %02X", ladrf[i]);
+ pr_cont("\n");
#endif
} /* BuildLAF */
@@ -1535,9 +1503,7 @@ MODULE_DEVICE_TABLE(pcmcia, nmclan_ids);
static struct pcmcia_driver nmclan_cs_driver = {
.owner = THIS_MODULE,
- .drv = {
- .name = "nmclan_cs",
- },
+ .name = "nmclan_cs",
.probe = nmclan_probe,
.remove = nmclan_detach,
.id_table = nmclan_ids,
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index f9b509a6b09a..03096c80103d 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -28,6 +28,8 @@
======================================================================*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -35,14 +37,12 @@
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/delay.h>
-#include <linux/ethtool.h>
#include <linux/netdevice.h>
#include <linux/log2.h>
#include <linux/etherdevice.h>
#include <linux/mii.h>
#include "../8390.h"
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ciscode.h>
#include <pcmcia/ds.h>
@@ -100,7 +100,6 @@ static void pcnet_release(struct pcmcia_device *link);
static int pcnet_open(struct net_device *dev);
static int pcnet_close(struct net_device *dev);
static int ei_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-static const struct ethtool_ops netdev_ethtool_ops;
static irqreturn_t ei_irq_wrapper(int irq, void *dev_id);
static void ei_watchdog(u_long arg);
static void pcnet_reset_8390(struct net_device *dev);
@@ -238,14 +237,6 @@ static const struct net_device_ops pcnet_netdev_ops = {
#endif
};
-/*======================================================================
-
- pcnet_attach() creates an "instance" of the driver, allocating
- local data structures for one device. The device is registered
- with Card Services.
-
-======================================================================*/
-
static int pcnet_probe(struct pcmcia_device *link)
{
pcnet_dev_t *info;
@@ -260,23 +251,13 @@ static int pcnet_probe(struct pcmcia_device *link)
info->p_dev = link;
link->priv = dev;
- link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.IntType = INT_MEMORY_AND_IO;
+ link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
dev->netdev_ops = &pcnet_netdev_ops;
return pcnet_config(link);
} /* pcnet_attach */
-/*======================================================================
-
- This deletes a driver "instance". The device is de-registered
- with Card Services. If it has been released, all local data
- structures are freed. Otherwise, the structures will be freed
- when the device is released.
-
-======================================================================*/
-
static void pcnet_detach(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
@@ -300,22 +281,22 @@ static void pcnet_detach(struct pcmcia_device *link)
static hw_info_t *get_hwinfo(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
- win_req_t req;
u_char __iomem *base, *virt;
int i, j;
/* Allocate a small memory window */
- req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
- req.Base = 0; req.Size = 0;
- req.AccessSpeed = 0;
- i = pcmcia_request_window(link, &req, &link->win);
+ link->resource[2]->flags |= WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
+ link->resource[2]->start = 0; link->resource[2]->end = 0;
+ i = pcmcia_request_window(link, link->resource[2], 0);
if (i != 0)
return NULL;
- virt = ioremap(req.Base, req.Size);
+ virt = ioremap(link->resource[2]->start,
+ resource_size(link->resource[2]));
for (i = 0; i < NR_INFO; i++) {
- pcmcia_map_mem_page(link, link->win, hw_info[i].offset & ~(req.Size-1));
- base = &virt[hw_info[i].offset & (req.Size-1)];
+ pcmcia_map_mem_page(link, link->resource[2],
+ hw_info[i].offset & ~(resource_size(link->resource[2])-1));
+ base = &virt[hw_info[i].offset & (resource_size(link->resource[2])-1)];
if ((readb(base+0) == hw_info[i].a0) &&
(readb(base+2) == hw_info[i].a1) &&
(readb(base+4) == hw_info[i].a2)) {
@@ -326,7 +307,7 @@ static hw_info_t *get_hwinfo(struct pcmcia_device *link)
}
iounmap(virt);
- j = pcmcia_release_window(link, link->win);
+ j = pcmcia_release_window(link, link->resource[2]);
return (i < NR_INFO) ? hw_info+i : NULL;
} /* get_hwinfo */
@@ -421,7 +402,7 @@ static hw_info_t *get_ax88190(struct pcmcia_device *link)
int i, j;
/* Not much of a test, but the alternatives are messy */
- if (link->conf.ConfigBase != 0x03c0)
+ if (link->config_base != 0x03c0)
return NULL;
outb_p(0x01, ioaddr + EN0_DCFG); /* Set word-wide access. */
@@ -434,8 +415,6 @@ static hw_info_t *get_ax88190(struct pcmcia_device *link)
dev->dev_addr[i] = j & 0xff;
dev->dev_addr[i+1] = j >> 8;
}
- printk(KERN_NOTICE "pcnet_cs: this is an AX88190 card!\n");
- printk(KERN_NOTICE "pcnet_cs: use axnet_cs instead.\n");
return NULL;
}
@@ -463,14 +442,6 @@ static hw_info_t *get_hwired(struct pcmcia_device *link)
return &default_info;
} /* get_hwired */
-/*======================================================================
-
- pcnet_config() is scheduled to run after a CARD_INSERTION event
- is received, to configure the PCMCIA socket, and to make the
- ethernet device available to the system.
-
-======================================================================*/
-
static int try_io_port(struct pcmcia_device *link)
{
int j, ret;
@@ -502,43 +473,22 @@ static int try_io_port(struct pcmcia_device *link)
}
}
-static int pcnet_confcheck(struct pcmcia_device *p_dev,
- cistpl_cftable_entry_t *cfg,
- cistpl_cftable_entry_t *dflt,
- unsigned int vcc,
- void *priv_data)
+static int pcnet_confcheck(struct pcmcia_device *p_dev, void *priv_data)
{
int *priv = priv_data;
int try = (*priv & 0x1);
- int i;
- cistpl_io_t *io = &cfg->io;
- if (cfg->index == 0 || cfg->io.nwin == 0)
- return -EINVAL;
+ *priv &= (p_dev->resource[2]->end >= 0x4000) ? 0x10 : ~0x10;
- /* For multifunction cards, by convention, we configure the
- network function with window 0, and serial with window 1 */
- if (io->nwin > 1) {
- i = (io->win[1].len > io->win[0].len);
- p_dev->resource[1]->start = io->win[1-i].base;
- p_dev->resource[1]->end = io->win[1-i].len;
- } else {
- i = p_dev->resource[1]->end = 0;
- }
+ if (p_dev->config_index == 0)
+ return -EINVAL;
- *priv &= ((cfg->mem.nwin == 1) &&
- (cfg->mem.win[0].len >= 0x4000)) ? 0x10 : ~0x10;
+ if (p_dev->resource[0]->end + p_dev->resource[1]->end < 32)
+ return -EINVAL;
- p_dev->resource[0]->start = io->win[i].base;
- p_dev->resource[0]->end = io->win[i].len;
- if (!try)
- p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
- else
+ if (try)
p_dev->io_lines = 16;
- if (p_dev->resource[0]->end + p_dev->resource[1]->end >= 32)
- return try_io_port(p_dev);
-
- return -EINVAL;
+ return try_io_port(p_dev);
}
static hw_info_t *pcnet_try_config(struct pcmcia_device *link,
@@ -560,15 +510,14 @@ static hw_info_t *pcnet_try_config(struct pcmcia_device *link,
if (!link->irq)
return NULL;
- if (resource_size(link->resource[1]) == 8) {
- link->conf.Attributes |= CONF_ENABLE_SPKR;
- link->conf.Status = CCSR_AUDIO_ENA;
- }
+ if (resource_size(link->resource[1]) == 8)
+ link->config_flags |= CONF_ENABLE_SPKR;
+
if ((link->manf_id == MANFID_IBM) &&
(link->card_id == PRODID_IBM_HOME_AND_AWAY))
- link->conf.ConfigIndex |= 0x10;
+ link->config_index |= 0x10;
- ret = pcmcia_request_configuration(link, &link->conf);
+ ret = pcmcia_enable_device(link);
if (ret)
return NULL;
@@ -583,7 +532,7 @@ static hw_info_t *pcnet_try_config(struct pcmcia_device *link,
} else
dev->if_port = 0;
- if ((link->conf.ConfigBase == 0x03c0) &&
+ if ((link->config_base == 0x03c0) &&
(link->manf_id == 0x149) && (link->card_id == 0xc1ab)) {
dev_info(&link->dev,
"this is an AX88190 card - use axnet_cs instead.\n");
@@ -653,9 +602,7 @@ static int pcnet_config(struct pcmcia_device *link)
ei_status.name = "NE2000";
ei_status.word16 = 1;
- ei_status.reset_8390 = &pcnet_reset_8390;
-
- SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
+ ei_status.reset_8390 = pcnet_reset_8390;
if (info->flags & (IS_DL10019|IS_DL10022))
mii_phy_probe(dev);
@@ -663,25 +610,25 @@ static int pcnet_config(struct pcmcia_device *link)
SET_NETDEV_DEV(dev, &link->dev);
if (register_netdev(dev) != 0) {
- printk(KERN_NOTICE "pcnet_cs: register_netdev() failed\n");
+ pr_notice("register_netdev() failed\n");
goto failed;
}
if (info->flags & (IS_DL10019|IS_DL10022)) {
u_char id = inb(dev->base_addr + 0x1a);
- printk(KERN_INFO "%s: NE2000 (DL100%d rev %02x): ",
- dev->name, ((info->flags & IS_DL10022) ? 22 : 19), id);
+ netdev_info(dev, "NE2000 (DL100%d rev %02x): ",
+ (info->flags & IS_DL10022) ? 22 : 19, id);
if (info->pna_phy)
- printk("PNA, ");
+ pr_cont("PNA, ");
} else {
- printk(KERN_INFO "%s: NE2000 Compatible: ", dev->name);
+ netdev_info(dev, "NE2000 Compatible: ");
}
- printk("io %#3lx, irq %d,", dev->base_addr, dev->irq);
+ pr_cont("io %#3lx, irq %d,", dev->base_addr, dev->irq);
if (info->flags & USE_SHMEM)
- printk (" mem %#5lx,", dev->mem_start);
+ pr_cont(" mem %#5lx,", dev->mem_start);
if (info->flags & HAS_MISC_REG)
- printk(" %s xcvr,", if_names[dev->if_port]);
- printk(" hw_addr %pM\n", dev->dev_addr);
+ pr_cont(" %s xcvr,", if_names[dev->if_port]);
+ pr_cont(" hw_addr %pM\n", dev->dev_addr);
return 0;
failed:
@@ -689,14 +636,6 @@ failed:
return -ENODEV;
} /* pcnet_config */
-/*======================================================================
-
- After a card is removed, pcnet_release() will unregister the net
- device, and release the PCMCIA configuration. If the device is
- still open, this will be postponed until it is closed.
-
-======================================================================*/
-
static void pcnet_release(struct pcmcia_device *link)
{
pcnet_dev_t *info = PRIV(link->priv);
@@ -709,15 +648,6 @@ static void pcnet_release(struct pcmcia_device *link)
pcmcia_disable_device(link);
}
-/*======================================================================
-
- The card status event handler. Mostly, this schedules other
- stuff to run after an event is received. A CARD_REMOVAL event
- also sets some flags to discourage the net drivers from trying
- to talk to the card any more.
-
-======================================================================*/
-
static int pcnet_suspend(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
@@ -955,7 +885,7 @@ static void mii_phy_probe(struct net_device *dev)
phyid = tmp << 16;
phyid |= mdio_read(mii_addr, i, MII_PHYID_REG2);
phyid &= MII_PHYID_REV_MASK;
- pr_debug("%s: MII at %d is 0x%08x\n", dev->name, i, phyid);
+ netdev_dbg(dev, "MII at %d is 0x%08x\n", i, phyid);
if (phyid == AM79C9XX_HOME_PHY) {
info->pna_phy = i;
} else if (phyid != AM79C9XX_ETH_PHY) {
@@ -988,7 +918,7 @@ static int pcnet_open(struct net_device *dev)
info->phy_id = info->eth_phy;
info->link_status = 0x00;
init_timer(&info->watchdog);
- info->watchdog.function = &ei_watchdog;
+ info->watchdog.function = ei_watchdog;
info->watchdog.data = (u_long)dev;
info->watchdog.expires = jiffies + HZ;
add_timer(&info->watchdog);
@@ -1041,8 +971,8 @@ static void pcnet_reset_8390(struct net_device *dev)
outb_p(ENISR_RESET, nic_base + EN0_ISR); /* Ack intr. */
if (i == 100)
- printk(KERN_ERR "%s: pcnet_reset_8390() did not complete.\n",
- dev->name);
+ netdev_err(dev, "pcnet_reset_8390() did not complete.\n");
+
set_misc_reg(dev);
} /* pcnet_reset_8390 */
@@ -1058,8 +988,7 @@ static int set_config(struct net_device *dev, struct ifmap *map)
else if ((map->port < 1) || (map->port > 2))
return -EINVAL;
dev->if_port = map->port;
- printk(KERN_INFO "%s: switched to %s port\n",
- dev->name, if_names[dev->if_port]);
+ netdev_info(dev, "switched to %s port\n", if_names[dev->if_port]);
NS8390_init(dev, 1);
}
return 0;
@@ -1094,7 +1023,7 @@ static void ei_watchdog(u_long arg)
this, we can limp along even if the interrupt is blocked */
if (info->stale++ && (inb_p(nic_base + EN0_ISR) & ENISR_ALL)) {
if (!info->fast_poll)
- printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name);
+ netdev_info(dev, "interrupt(s) dropped!\n");
ei_irq_wrapper(dev->irq, dev);
info->fast_poll = HZ;
}
@@ -1114,7 +1043,7 @@ static void ei_watchdog(u_long arg)
if (info->eth_phy) {
info->phy_id = info->eth_phy = 0;
} else {
- printk(KERN_INFO "%s: MII is missing!\n", dev->name);
+ netdev_info(dev, "MII is missing!\n");
info->flags &= ~HAS_MII;
}
goto reschedule;
@@ -1123,8 +1052,7 @@ static void ei_watchdog(u_long arg)
link &= 0x0004;
if (link != info->link_status) {
u_short p = mdio_read(mii_addr, info->phy_id, 5);
- printk(KERN_INFO "%s: %s link beat\n", dev->name,
- (link) ? "found" : "lost");
+ netdev_info(dev, "%s link beat\n", link ? "found" : "lost");
if (link && (info->flags & IS_DL10022)) {
/* Disable collision detection on full duplex links */
outb((p & 0x0140) ? 4 : 0, nic_base + DLINK_DIAG);
@@ -1135,13 +1063,12 @@ static void ei_watchdog(u_long arg)
if (link) {
if (info->phy_id == info->eth_phy) {
if (p)
- printk(KERN_INFO "%s: autonegotiation complete: "
- "%sbaseT-%cD selected\n", dev->name,
+ netdev_info(dev, "autonegotiation complete: "
+ "%sbaseT-%cD selected\n",
((p & 0x0180) ? "100" : "10"),
((p & 0x0140) ? 'F' : 'H'));
else
- printk(KERN_INFO "%s: link partner did not "
- "autonegotiate\n", dev->name);
+ netdev_info(dev, "link partner did not autonegotiate\n");
}
NS8390_init(dev, 1);
}
@@ -1154,7 +1081,7 @@ static void ei_watchdog(u_long arg)
/* isolate this MII and try flipping to the other one */
mdio_write(mii_addr, info->phy_id, 0, 0x0400);
info->phy_id ^= info->pna_phy ^ info->eth_phy;
- printk(KERN_INFO "%s: switched to %s transceiver\n", dev->name,
+ netdev_info(dev, "switched to %s transceiver\n",
(info->phy_id == info->eth_phy) ? "ethernet" : "PNA");
mdio_write(mii_addr, info->phy_id, 0,
(info->phy_id == info->eth_phy) ? 0x1000 : 0);
@@ -1170,18 +1097,6 @@ reschedule:
/*====================================================================*/
-static void netdev_get_drvinfo(struct net_device *dev,
- struct ethtool_drvinfo *info)
-{
- strcpy(info->driver, "pcnet_cs");
-}
-
-static const struct ethtool_ops netdev_ethtool_ops = {
- .get_drvinfo = netdev_get_drvinfo,
-};
-
-/*====================================================================*/
-
static int ei_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
@@ -1214,9 +1129,9 @@ static void dma_get_8390_hdr(struct net_device *dev,
unsigned int nic_base = dev->base_addr;
if (ei_status.dmaing) {
- printk(KERN_NOTICE "%s: DMAing conflict in dma_block_input."
+ netdev_notice(dev, "DMAing conflict in dma_block_input."
"[DMAstat:%1x][irqlock:%1x]\n",
- dev->name, ei_status.dmaing, ei_status.irqlock);
+ ei_status.dmaing, ei_status.irqlock);
return;
}
@@ -1247,11 +1162,11 @@ static void dma_block_input(struct net_device *dev, int count,
char *buf = skb->data;
if ((ei_debug > 4) && (count != 4))
- pr_debug("%s: [bi=%d]\n", dev->name, count+4);
+ netdev_dbg(dev, "[bi=%d]\n", count+4);
if (ei_status.dmaing) {
- printk(KERN_NOTICE "%s: DMAing conflict in dma_block_input."
+ netdev_notice(dev, "DMAing conflict in dma_block_input."
"[DMAstat:%1x][irqlock:%1x]\n",
- dev->name, ei_status.dmaing, ei_status.irqlock);
+ ei_status.dmaing, ei_status.irqlock);
return;
}
ei_status.dmaing |= 0x01;
@@ -1281,9 +1196,9 @@ static void dma_block_input(struct net_device *dev, int count,
break;
} while (--tries > 0);
if (tries <= 0)
- printk(KERN_NOTICE "%s: RX transfer address mismatch,"
+ netdev_notice(dev, "RX transfer address mismatch,"
"%#4.4x (expected) vs. %#4.4x (actual).\n",
- dev->name, ring_offset + xfer_count, addr);
+ ring_offset + xfer_count, addr);
}
#endif
outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
@@ -1304,7 +1219,7 @@ static void dma_block_output(struct net_device *dev, int count,
#ifdef PCMCIA_DEBUG
if (ei_debug > 4)
- printk(KERN_DEBUG "%s: [bo=%d]\n", dev->name, count);
+ netdev_dbg(dev, "[bo=%d]\n", count);
#endif
/* Round the count up for word writes. Do we need to do this?
@@ -1313,9 +1228,9 @@ static void dma_block_output(struct net_device *dev, int count,
if (count & 0x01)
count++;
if (ei_status.dmaing) {
- printk(KERN_NOTICE "%s: DMAing conflict in dma_block_output."
+ netdev_notice(dev, "DMAing conflict in dma_block_output."
"[DMAstat:%1x][irqlock:%1x]\n",
- dev->name, ei_status.dmaing, ei_status.irqlock);
+ ei_status.dmaing, ei_status.irqlock);
return;
}
ei_status.dmaing |= 0x01;
@@ -1352,9 +1267,9 @@ static void dma_block_output(struct net_device *dev, int count,
break;
} while (--tries > 0);
if (tries <= 0) {
- printk(KERN_NOTICE "%s: Tx packet transfer address mismatch,"
+ netdev_notice(dev, "Tx packet transfer address mismatch,"
"%#4.4x (expected) vs. %#4.4x (actual).\n",
- dev->name, (start_page << 8) + count, addr);
+ (start_page << 8) + count, addr);
if (retries++ == 0)
goto retry;
}
@@ -1363,8 +1278,7 @@ static void dma_block_output(struct net_device *dev, int count,
while ((inb_p(nic_base + EN0_ISR) & ENISR_RDC) == 0)
if (time_after(jiffies, dma_start + PCNET_RDC_TIMEOUT)) {
- printk(KERN_NOTICE "%s: timeout waiting for Tx RDC.\n",
- dev->name);
+ netdev_notice(dev, "timeout waiting for Tx RDC.\n");
pcnet_reset_8390(dev);
NS8390_init(dev, 1);
break;
@@ -1388,9 +1302,9 @@ static int setup_dma_config(struct pcmcia_device *link, int start_pg,
ei_status.stop_page = stop_pg;
/* set up block i/o functions */
- ei_status.get_8390_hdr = &dma_get_8390_hdr;
- ei_status.block_input = &dma_block_input;
- ei_status.block_output = &dma_block_output;
+ ei_status.get_8390_hdr = dma_get_8390_hdr;
+ ei_status.block_input = dma_block_input;
+ ei_status.block_output = dma_block_output;
return 0;
}
@@ -1486,7 +1400,6 @@ static int setup_shmem_window(struct pcmcia_device *link, int start_pg,
{
struct net_device *dev = link->priv;
pcnet_dev_t *info = PRIV(dev);
- win_req_t req;
int i, window_size, offset, ret;
window_size = (stop_pg - start_pg) << 8;
@@ -1497,22 +1410,22 @@ static int setup_shmem_window(struct pcmcia_device *link, int start_pg,
window_size = roundup_pow_of_two(window_size);
/* Allocate a memory window */
- req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
- req.Attributes |= WIN_USE_WAIT;
- req.Base = 0; req.Size = window_size;
- req.AccessSpeed = mem_speed;
- ret = pcmcia_request_window(link, &req, &link->win);
+ link->resource[3]->flags |= WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
+ link->resource[3]->flags |= WIN_USE_WAIT;
+ link->resource[3]->start = 0; link->resource[3]->end = window_size;
+ ret = pcmcia_request_window(link, link->resource[3], mem_speed);
if (ret)
goto failed;
offset = (start_pg << 8) + cm_offset;
offset -= offset % window_size;
- ret = pcmcia_map_mem_page(link, link->win, offset);
+ ret = pcmcia_map_mem_page(link, link->resource[3], offset);
if (ret)
goto failed;
/* Try scribbling on the buffer */
- info->base = ioremap(req.Base, window_size);
+ info->base = ioremap(link->resource[3]->start,
+ resource_size(link->resource[3]));
for (i = 0; i < (TX_PAGES<<8); i += 2)
__raw_writew((i>>1), info->base+offset+i);
udelay(100);
@@ -1521,24 +1434,25 @@ static int setup_shmem_window(struct pcmcia_device *link, int start_pg,
pcnet_reset_8390(dev);
if (i != (TX_PAGES<<8)) {
iounmap(info->base);
- pcmcia_release_window(link, link->win);
- info->base = NULL; link->win = 0;
+ pcmcia_release_window(link, link->resource[3]);
+ info->base = NULL;
goto failed;
}
ei_status.mem = info->base + offset;
- ei_status.priv = req.Size;
+ ei_status.priv = resource_size(link->resource[3]);
dev->mem_start = (u_long)ei_status.mem;
- dev->mem_end = dev->mem_start + req.Size;
+ dev->mem_end = dev->mem_start + resource_size(link->resource[3]);
ei_status.tx_start_page = start_pg;
ei_status.rx_start_page = start_pg + TX_PAGES;
- ei_status.stop_page = start_pg + ((req.Size - offset) >> 8);
+ ei_status.stop_page = start_pg + (
+ (resource_size(link->resource[3]) - offset) >> 8);
/* set up block i/o functions */
- ei_status.get_8390_hdr = &shmem_get_8390_hdr;
- ei_status.block_input = &shmem_block_input;
- ei_status.block_output = &shmem_block_output;
+ ei_status.get_8390_hdr = shmem_get_8390_hdr;
+ ei_status.block_input = shmem_block_input;
+ ei_status.block_output = shmem_block_output;
info->flags |= USE_SHMEM;
return 0;
@@ -1772,9 +1686,7 @@ MODULE_FIRMWARE("cis/PE-200.cis");
MODULE_FIRMWARE("cis/tamarack.cis");
static struct pcmcia_driver pcnet_driver = {
- .drv = {
- .name = "pcnet_cs",
- },
+ .name = "pcnet_cs",
.probe = pcnet_probe,
.remove = pcnet_detach,
.owner = THIS_MODULE,
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
index 377367d03b41..8a9ff5318923 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/pcmcia/smc91c92_cs.c
@@ -25,6 +25,8 @@
======================================================================*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -44,7 +46,6 @@
#include <linux/jiffies.h>
#include <linux/firmware.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/ciscode.h>
@@ -294,20 +295,12 @@ static const struct net_device_ops smc_netdev_ops = {
.ndo_tx_timeout = smc_tx_timeout,
.ndo_set_config = s9k_config,
.ndo_set_multicast_list = set_rx_mode,
- .ndo_do_ioctl = &smc_ioctl,
+ .ndo_do_ioctl = smc_ioctl,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
-/*======================================================================
-
- smc91c92_attach() creates an "instance" of the driver, allocating
- local data structures for one device. The device is registered
- with Card Services.
-
-======================================================================*/
-
static int smc91c92_probe(struct pcmcia_device *link)
{
struct smc_private *smc;
@@ -324,10 +317,6 @@ static int smc91c92_probe(struct pcmcia_device *link)
link->priv = dev;
spin_lock_init(&smc->lock);
- link->resource[0]->end = 16;
- link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
- link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.IntType = INT_MEMORY_AND_IO;
/* The SMC91c92-specific entries in the device structure. */
dev->netdev_ops = &smc_netdev_ops;
@@ -343,15 +332,6 @@ static int smc91c92_probe(struct pcmcia_device *link)
return smc91c92_config(link);
} /* smc91c92_attach */
-/*======================================================================
-
- This deletes a driver "instance". The device is de-registered
- with Card Services. If it has been released, all local data
- structures are freed. Otherwise, the structures will be freed
- when the device is released.
-
-======================================================================*/
-
static void smc91c92_detach(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
@@ -412,26 +392,28 @@ static int mhz_3288_power(struct pcmcia_device *link)
mdelay(200);
/* Now read and write the COR... */
- tmp = readb(smc->base + link->conf.ConfigBase + CISREG_COR);
+ tmp = readb(smc->base + link->config_base + CISREG_COR);
udelay(5);
- writeb(tmp, smc->base + link->conf.ConfigBase + CISREG_COR);
+ writeb(tmp, smc->base + link->config_base + CISREG_COR);
return 0;
}
-static int mhz_mfc_config_check(struct pcmcia_device *p_dev,
- cistpl_cftable_entry_t *cf,
- cistpl_cftable_entry_t *dflt,
- unsigned int vcc,
- void *priv_data)
+static int mhz_mfc_config_check(struct pcmcia_device *p_dev, void *priv_data)
{
int k;
- p_dev->resource[1]->start = cf->io.win[0].base;
+ p_dev->io_lines = 16;
+ p_dev->resource[1]->start = p_dev->resource[0]->start;
+ p_dev->resource[1]->end = 8;
+ p_dev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
+ p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
+ p_dev->resource[0]->end = 16;
+ p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+ p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
for (k = 0; k < 0x400; k += 0x10) {
if (k & 0x80)
continue;
p_dev->resource[0]->start = k ^ 0x300;
- p_dev->io_lines = 16;
if (!pcmcia_request_io(p_dev))
return 0;
}
@@ -442,14 +424,11 @@ static int mhz_mfc_config(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
struct smc_private *smc = netdev_priv(dev);
- win_req_t req;
unsigned int offset;
int i;
- link->conf.Attributes |= CONF_ENABLE_SPKR;
- link->conf.Status = CCSR_AUDIO_ENA;
- link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
- link->resource[1]->end = 8;
+ link->config_flags |= CONF_ENABLE_SPKR | CONF_ENABLE_IRQ |
+ CONF_AUTO_SET_IO;
/* The Megahertz combo cards have modem-like CIS entries, so
we have to explicitly try a bunch of port combinations. */
@@ -459,16 +438,16 @@ static int mhz_mfc_config(struct pcmcia_device *link)
dev->base_addr = link->resource[0]->start;
/* Allocate a memory window, for accessing the ISR */
- req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
- req.Base = req.Size = 0;
- req.AccessSpeed = 0;
- i = pcmcia_request_window(link, &req, &link->win);
+ link->resource[2]->flags = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
+ link->resource[2]->start = link->resource[2]->end = 0;
+ i = pcmcia_request_window(link, link->resource[2], 0);
if (i != 0)
return -ENODEV;
- smc->base = ioremap(req.Base, req.Size);
- offset = (smc->manfid == MANFID_MOTOROLA) ? link->conf.ConfigBase : 0;
- i = pcmcia_map_mem_page(link, link->win, offset);
+ smc->base = ioremap(link->resource[2]->start,
+ resource_size(link->resource[2]));
+ offset = (smc->manfid == MANFID_MOTOROLA) ? link->config_base : 0;
+ i = pcmcia_map_mem_page(link, link->resource[2], offset);
if ((i == 0) &&
(smc->manfid == MANFID_MEGAHERTZ) &&
(smc->cardid == PRODID_MEGAHERTZ_EM3288))
@@ -591,14 +570,12 @@ static int mot_setup(struct pcmcia_device *link)
/*====================================================================*/
-static int smc_configcheck(struct pcmcia_device *p_dev,
- cistpl_cftable_entry_t *cf,
- cistpl_cftable_entry_t *dflt,
- unsigned int vcc,
- void *priv_data)
+static int smc_configcheck(struct pcmcia_device *p_dev, void *priv_data)
{
- p_dev->resource[0]->start = cf->io.win[0].base;
- p_dev->io_lines = cf->io.flags & CISTPL_IO_LINES_MASK;
+ p_dev->resource[0]->end = 16;
+ p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+ p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
+
return pcmcia_request_io(p_dev);
}
@@ -607,7 +584,8 @@ static int smc_config(struct pcmcia_device *link)
struct net_device *dev = link->priv;
int i;
- link->resource[0]->end = 16;
+ link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+
i = pcmcia_loop_config(link, smc_configcheck, NULL);
if (!i)
dev->base_addr = link->resource[0]->start;
@@ -640,15 +618,14 @@ static int osi_config(struct pcmcia_device *link)
static const unsigned int com[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
int i, j;
- link->conf.Attributes |= CONF_ENABLE_SPKR;
- link->conf.Status = CCSR_AUDIO_ENA;
+ link->config_flags |= CONF_ENABLE_SPKR | CONF_ENABLE_IRQ;
link->resource[0]->end = 64;
link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
link->resource[1]->end = 8;
/* Enable Hard Decode, LAN, Modem */
- link->conf.ConfigIndex = 0x23;
link->io_lines = 16;
+ link->config_index = 0x23;
for (i = j = 0; j < 4; j++) {
link->resource[1]->start = com[j];
@@ -658,7 +635,7 @@ static int osi_config(struct pcmcia_device *link)
}
if (i != 0) {
/* Fallback: turn off hard decode */
- link->conf.ConfigIndex = 0x03;
+ link->config_index = 0x03;
link->resource[1]->end = 0;
i = pcmcia_request_io(link);
}
@@ -813,31 +790,20 @@ static int check_sig(struct pcmcia_device *link)
((s >> 8) != (s & 0xff))) {
SMC_SELECT_BANK(3);
s = inw(ioaddr + REVISION);
- return (s & 0xff);
+ return s & 0xff;
}
if (width) {
- modconf_t mod = {
- .Attributes = CONF_IO_CHANGE_WIDTH,
- };
- printk(KERN_INFO "smc91c92_cs: using 8-bit IO window.\n");
+ pr_info("using 8-bit IO window\n");
smc91c92_suspend(link);
- pcmcia_modify_configuration(link, &mod);
+ pcmcia_fixup_iowidth(link);
smc91c92_resume(link);
return check_sig(link);
}
return -ENODEV;
}
-/*======================================================================
-
- smc91c92_config() is scheduled to run after a CARD_INSERTION event
- is received, to configure the PCMCIA socket, and to make the
- ethernet device available to the system.
-
-======================================================================*/
-
static int smc91c92_config(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
@@ -869,7 +835,7 @@ static int smc91c92_config(struct pcmcia_device *link)
i = pcmcia_request_irq(link, smc_interrupt);
if (i)
goto config_failed;
- i = pcmcia_request_configuration(link, &link->conf);
+ i = pcmcia_enable_device(link);
if (i)
goto config_failed;
@@ -881,7 +847,7 @@ static int smc91c92_config(struct pcmcia_device *link)
if ((if_port >= 0) && (if_port <= 2))
dev->if_port = if_port;
else
- printk(KERN_NOTICE "smc91c92_cs: invalid if_port requested\n");
+ dev_notice(&link->dev, "invalid if_port requested\n");
switch (smc->manfid) {
case MANFID_OSITECH:
@@ -899,7 +865,7 @@ static int smc91c92_config(struct pcmcia_device *link)
}
if (i != 0) {
- printk(KERN_NOTICE "smc91c92_cs: Unable to find hardware address.\n");
+ dev_notice(&link->dev, "Unable to find hardware address.\n");
goto config_failed;
}
@@ -952,30 +918,28 @@ static int smc91c92_config(struct pcmcia_device *link)
SET_NETDEV_DEV(dev, &link->dev);
if (register_netdev(dev) != 0) {
- printk(KERN_ERR "smc91c92_cs: register_netdev() failed\n");
+ dev_err(&link->dev, "register_netdev() failed\n");
goto config_undo;
}
- printk(KERN_INFO "%s: smc91c%s rev %d: io %#3lx, irq %d, "
- "hw_addr %pM\n",
- dev->name, name, (rev & 0x0f), dev->base_addr, dev->irq,
- dev->dev_addr);
+ netdev_info(dev, "smc91c%s rev %d: io %#3lx, irq %d, hw_addr %pM\n",
+ name, (rev & 0x0f), dev->base_addr, dev->irq, dev->dev_addr);
if (rev > 0) {
if (mir & 0x3ff)
- printk(KERN_INFO " %lu byte", mir);
+ netdev_info(dev, " %lu byte", mir);
else
- printk(KERN_INFO " %lu kb", mir>>10);
- printk(" buffer, %s xcvr\n", (smc->cfg & CFG_MII_SELECT) ?
- "MII" : if_names[dev->if_port]);
+ netdev_info(dev, " %lu kb", mir>>10);
+ pr_cont(" buffer, %s xcvr\n",
+ (smc->cfg & CFG_MII_SELECT) ? "MII" : if_names[dev->if_port]);
}
if (smc->cfg & CFG_MII_SELECT) {
if (smc->mii_if.phy_id != -1) {
- dev_dbg(&link->dev, " MII transceiver at index %d, status %x.\n",
- smc->mii_if.phy_id, j);
+ netdev_dbg(dev, " MII transceiver at index %d, status %x\n",
+ smc->mii_if.phy_id, j);
} else {
- printk(KERN_NOTICE " No MII transceivers found!\n");
+ netdev_notice(dev, " No MII transceivers found!\n");
}
}
return 0;
@@ -988,18 +952,10 @@ config_failed:
return -ENODEV;
} /* smc91c92_config */
-/*======================================================================
-
- After a card is removed, smc91c92_release() will unregister the net
- device, and release the PCMCIA configuration. If the device is
- still open, this will be postponed until it is closed.
-
-======================================================================*/
-
static void smc91c92_release(struct pcmcia_device *link)
{
dev_dbg(&link->dev, "smc91c92_release\n");
- if (link->win) {
+ if (link->resource[2]->end) {
struct net_device *dev = link->priv;
struct smc_private *smc = netdev_priv(dev);
iounmap(smc->base);
@@ -1081,10 +1037,10 @@ static void smc_dump(struct net_device *dev)
save = inw(ioaddr + BANK_SELECT);
for (w = 0; w < 4; w++) {
SMC_SELECT_BANK(w);
- printk(KERN_DEBUG "bank %d: ", w);
+ netdev_printk(KERN_DEBUG, dev, "bank %d: ", w);
for (i = 0; i < 14; i += 2)
- printk(" %04x", inw(ioaddr + i));
- printk("\n");
+ pr_cont(" %04x", inw(ioaddr + i));
+ pr_cont("\n");
}
outw(save, ioaddr + BANK_SELECT);
}
@@ -1106,7 +1062,7 @@ static int smc_open(struct net_device *dev)
return -ENODEV;
/* Physical device present signature. */
if (check_sig(link) < 0) {
- printk("smc91c92_cs: Yikes! Bad chip signature!\n");
+ netdev_info(dev, "Yikes! Bad chip signature!\n");
return -ENODEV;
}
link->open++;
@@ -1117,7 +1073,7 @@ static int smc_open(struct net_device *dev)
smc_reset(dev);
init_timer(&smc->media);
- smc->media.function = &media_check;
+ smc->media.function = media_check;
smc->media.data = (u_long) dev;
smc->media.expires = jiffies + HZ;
add_timer(&smc->media);
@@ -1172,7 +1128,7 @@ static void smc_hardware_send_packet(struct net_device * dev)
u_char packet_no;
if (!skb) {
- printk(KERN_ERR "%s: In XMIT with no packet to send.\n", dev->name);
+ netdev_err(dev, "In XMIT with no packet to send\n");
return;
}
@@ -1180,8 +1136,8 @@ static void smc_hardware_send_packet(struct net_device * dev)
packet_no = inw(ioaddr + PNR_ARR) >> 8;
if (packet_no & 0x80) {
/* If not, there is a hardware problem! Likely an ejected card. */
- printk(KERN_WARNING "%s: 91c92 hardware Tx buffer allocation"
- " failed, status %#2.2x.\n", dev->name, packet_no);
+ netdev_warn(dev, "hardware Tx buffer allocation failed, status %#2.2x\n",
+ packet_no);
dev_kfree_skb_irq(skb);
smc->saved_skb = NULL;
netif_start_queue(dev);
@@ -1200,8 +1156,7 @@ static void smc_hardware_send_packet(struct net_device * dev)
u_char *buf = skb->data;
u_int length = skb->len; /* The chip will pad to ethernet min. */
- pr_debug("%s: Trying to xmit packet of length %d.\n",
- dev->name, length);
+ netdev_dbg(dev, "Trying to xmit packet of length %d\n", length);
/* send the packet length: +6 for status word, length, and ctl */
outw(0, ioaddr + DATA_1);
@@ -1233,9 +1188,8 @@ static void smc_tx_timeout(struct net_device *dev)
struct smc_private *smc = netdev_priv(dev);
unsigned int ioaddr = dev->base_addr;
- printk(KERN_NOTICE "%s: SMC91c92 transmit timed out, "
- "Tx_status %2.2x status %4.4x.\n",
- dev->name, inw(ioaddr)&0xff, inw(ioaddr + 2));
+ netdev_notice(dev, "transmit timed out, Tx_status %2.2x status %4.4x.\n",
+ inw(ioaddr)&0xff, inw(ioaddr + 2));
dev->stats.tx_errors++;
smc_reset(dev);
dev->trans_start = jiffies; /* prevent tx timeout */
@@ -1254,14 +1208,14 @@ static netdev_tx_t smc_start_xmit(struct sk_buff *skb,
netif_stop_queue(dev);
- pr_debug("%s: smc_start_xmit(length = %d) called,"
- " status %4.4x.\n", dev->name, skb->len, inw(ioaddr + 2));
+ netdev_dbg(dev, "smc_start_xmit(length = %d) called, status %04x\n",
+ skb->len, inw(ioaddr + 2));
if (smc->saved_skb) {
/* THIS SHOULD NEVER HAPPEN. */
dev->stats.tx_aborted_errors++;
- printk(KERN_DEBUG "%s: Internal error -- sent packet while busy.\n",
- dev->name);
+ netdev_printk(KERN_DEBUG, dev,
+ "Internal error -- sent packet while busy\n");
return NETDEV_TX_BUSY;
}
smc->saved_skb = skb;
@@ -1269,7 +1223,7 @@ static netdev_tx_t smc_start_xmit(struct sk_buff *skb,
num_pages = skb->len >> 8;
if (num_pages > 7) {
- printk(KERN_ERR "%s: Far too big packet error.\n", dev->name);
+ netdev_err(dev, "Far too big packet error: %d pages\n", num_pages);
dev_kfree_skb (skb);
smc->saved_skb = NULL;
dev->stats.tx_dropped++;
@@ -1339,8 +1293,7 @@ static void smc_tx_err(struct net_device * dev)
}
if (tx_status & TS_SUCCESS) {
- printk(KERN_NOTICE "%s: Successful packet caused error "
- "interrupt?\n", dev->name);
+ netdev_notice(dev, "Successful packet caused error interrupt?\n");
}
/* re-enable transmit */
SMC_SELECT_BANK(0);
@@ -1530,8 +1483,7 @@ static void smc_rx(struct net_device *dev)
/* Assertion: we are in Window 2. */
if (inw(ioaddr + FIFO_PORTS) & FP_RXEMPTY) {
- printk(KERN_ERR "%s: smc_rx() with nothing on Rx FIFO.\n",
- dev->name);
+ netdev_err(dev, "smc_rx() with nothing on Rx FIFO\n");
return;
}
@@ -1646,8 +1598,7 @@ static int s9k_config(struct net_device *dev, struct ifmap *map)
else if (map->port > 2)
return -EINVAL;
dev->if_port = map->port;
- printk(KERN_INFO "%s: switched to %s port\n",
- dev->name, if_names[dev->if_port]);
+ netdev_info(dev, "switched to %s port\n", if_names[dev->if_port]);
smc_reset(dev);
}
return 0;
@@ -1798,7 +1749,7 @@ static void media_check(u_long arg)
this, we can limp along even if the interrupt is blocked */
if (smc->watchdog++ && ((i>>8) & i)) {
if (!smc->fast_poll)
- printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name);
+ netdev_info(dev, "interrupt(s) dropped!\n");
local_irq_save(flags);
smc_interrupt(dev->irq, dev);
local_irq_restore(flags);
@@ -1822,7 +1773,7 @@ static void media_check(u_long arg)
SMC_SELECT_BANK(3);
link = mdio_read(dev, smc->mii_if.phy_id, 1);
if (!link || (link == 0xffff)) {
- printk(KERN_INFO "%s: MII is missing!\n", dev->name);
+ netdev_info(dev, "MII is missing!\n");
smc->mii_if.phy_id = -1;
goto reschedule;
}
@@ -1830,15 +1781,13 @@ static void media_check(u_long arg)
link &= 0x0004;
if (link != smc->link_status) {
u_short p = mdio_read(dev, smc->mii_if.phy_id, 5);
- printk(KERN_INFO "%s: %s link beat\n", dev->name,
- (link) ? "found" : "lost");
+ netdev_info(dev, "%s link beat\n", link ? "found" : "lost");
smc->duplex = (((p & 0x0100) || ((p & 0x1c0) == 0x40))
? TCR_FDUPLX : 0);
if (link) {
- printk(KERN_INFO "%s: autonegotiation complete: "
- "%sbaseT-%cD selected\n", dev->name,
- ((p & 0x0180) ? "100" : "10"),
- (smc->duplex ? 'F' : 'H'));
+ netdev_info(dev, "autonegotiation complete: "
+ "%dbaseT-%cD selected\n",
+ (p & 0x0180) ? 100 : 10, smc->duplex ? 'F' : 'H');
}
SMC_SELECT_BANK(0);
outw(inw(ioaddr + TCR) | smc->duplex, ioaddr + TCR);
@@ -1857,25 +1806,23 @@ static void media_check(u_long arg)
if (media != smc->media_status) {
if ((media & smc->media_status & 1) &&
((smc->media_status ^ media) & EPH_LINK_OK))
- printk(KERN_INFO "%s: %s link beat\n", dev->name,
- (smc->media_status & EPH_LINK_OK ? "lost" : "found"));
+ netdev_info(dev, "%s link beat\n",
+ smc->media_status & EPH_LINK_OK ? "lost" : "found");
else if ((media & smc->media_status & 2) &&
((smc->media_status ^ media) & EPH_16COL))
- printk(KERN_INFO "%s: coax cable %s\n", dev->name,
- (media & EPH_16COL ? "problem" : "ok"));
+ netdev_info(dev, "coax cable %s\n",
+ media & EPH_16COL ? "problem" : "ok");
if (dev->if_port == 0) {
if (media & 1) {
if (media & EPH_LINK_OK)
- printk(KERN_INFO "%s: flipped to 10baseT\n",
- dev->name);
+ netdev_info(dev, "flipped to 10baseT\n");
else
smc_set_xcvr(dev, 2);
} else {
if (media & EPH_16COL)
smc_set_xcvr(dev, 1);
else
- printk(KERN_INFO "%s: flipped to 10base2\n",
- dev->name);
+ netdev_info(dev, "flipped to 10base2\n");
}
}
smc->media_status = media;
@@ -2101,9 +2048,7 @@ MODULE_DEVICE_TABLE(pcmcia, smc91c92_ids);
static struct pcmcia_driver smc91c92_cs_driver = {
.owner = THIS_MODULE,
- .drv = {
- .name = "smc91c92_cs",
- },
+ .name = "smc91c92_cs",
.probe = smc91c92_probe,
.remove = smc91c92_detach,
.id_table = smc91c92_ids,
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c
index f5819526b5ee..a46b7fd6c0f5 100644
--- a/drivers/net/pcmcia/xirc2ps_cs.c
+++ b/drivers/net/pcmcia/xirc2ps_cs.c
@@ -63,6 +63,8 @@
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -82,7 +84,6 @@
#include <linux/bitops.h>
#include <linux/mii.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/ciscode.h>
@@ -210,13 +211,6 @@ enum xirc_cmd { /* Commands */
static const char *if_names[] = { "Auto", "10BaseT", "10Base2", "AUI", "100BaseT" };
-
-#define KDBG_XIRC KERN_DEBUG "xirc2ps_cs: "
-#define KERR_XIRC KERN_ERR "xirc2ps_cs: "
-#define KWRN_XIRC KERN_WARNING "xirc2ps_cs: "
-#define KNOT_XIRC KERN_NOTICE "xirc2ps_cs: "
-#define KINF_XIRC KERN_INFO "xirc2ps_cs: "
-
/* card types */
#define XIR_UNKNOWN 0 /* unknown: not supported */
#define XIR_CE 1 /* (prodid 1) different hardware: not supported */
@@ -267,33 +261,11 @@ static unsigned mii_rd(unsigned int ioaddr, u_char phyaddr, u_char phyreg);
static void mii_wr(unsigned int ioaddr, u_char phyaddr, u_char phyreg,
unsigned data, int len);
-/*
- * The event() function is this driver's Card Services event handler.
- * It will be called by Card Services when an appropriate card status
- * event is received. The config() and release() entry points are
- * used to configure or release a socket, in response to card insertion
- * and ejection events. They are invoked from the event handler.
- */
-
static int has_ce2_string(struct pcmcia_device * link);
static int xirc2ps_config(struct pcmcia_device * link);
static void xirc2ps_release(struct pcmcia_device * link);
-
-/****************
- * The attach() and detach() entry points are used to create and destroy
- * "instances" of the driver, where each instance represents everything
- * needed to manage one actual PCMCIA card.
- */
-
static void xirc2ps_detach(struct pcmcia_device *p_dev);
-/****************
- * You'll also need to prototype all the functions that will actually
- * be used to talk to your device. See 'pcmem_cs' for a good example
- * of a fully self-sufficient driver; the other drivers rely more or
- * less on other parts of the kernel.
- */
-
static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id);
typedef struct local_info_t {
@@ -350,26 +322,26 @@ PrintRegisters(struct net_device *dev)
if (pc_debug > 1) {
int i, page;
- printk(KDBG_XIRC "Register common: ");
+ printk(KERN_DEBUG pr_fmt("Register common: "));
for (i = 0; i < 8; i++)
- printk(" %2.2x", GetByte(i));
- printk("\n");
+ pr_cont(" %2.2x", GetByte(i));
+ pr_cont("\n");
for (page = 0; page <= 8; page++) {
- printk(KDBG_XIRC "Register page %2x: ", page);
+ printk(KERN_DEBUG pr_fmt("Register page %2x: "), page);
SelectPage(page);
for (i = 8; i < 16; i++)
- printk(" %2.2x", GetByte(i));
- printk("\n");
+ pr_cont(" %2.2x", GetByte(i));
+ pr_cont("\n");
}
for (page=0x40 ; page <= 0x5f; page++) {
if (page == 0x43 || (page >= 0x46 && page <= 0x4f) ||
(page >= 0x51 && page <=0x5e))
continue;
- printk(KDBG_XIRC "Register page %2x: ", page);
+ printk(KERN_DEBUG pr_fmt("Register page %2x: "), page);
SelectPage(page);
for (i = 8; i < 16; i++)
- printk(" %2.2x", GetByte(i));
- printk("\n");
+ pr_cont(" %2.2x", GetByte(i));
+ pr_cont("\n");
}
}
}
@@ -501,16 +473,6 @@ static const struct net_device_ops netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
};
-/****************
- * xirc2ps_attach() creates an "instance" of the driver, allocating
- * local data structures for one device. The device is registered
- * with Card Services.
- *
- * The dev_link structure is initialized, but we don't actually
- * configure the card at this point -- we wait until we receive a
- * card insertion event.
- */
-
static int
xirc2ps_probe(struct pcmcia_device *link)
{
@@ -529,9 +491,7 @@ xirc2ps_probe(struct pcmcia_device *link)
link->priv = dev;
/* General socket configuration */
- link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.IntType = INT_MEMORY_AND_IO;
- link->conf.ConfigIndex = 1;
+ link->config_index = 1;
/* Fill in card specific entries */
dev->netdev_ops = &netdev_ops;
@@ -542,13 +502,6 @@ xirc2ps_probe(struct pcmcia_device *link)
return xirc2ps_config(link);
} /* xirc2ps_attach */
-/****************
- * This deletes a driver "instance". The device is de-registered
- * with Card Services. If it has been released, all local data
- * structures are freed. Otherwise, the structures will be freed
- * when the device is released.
- */
-
static void
xirc2ps_detach(struct pcmcia_device *link)
{
@@ -608,11 +561,11 @@ set_card_type(struct pcmcia_device *link)
local->modem = 0;
local->card_type = XIR_UNKNOWN;
if (!(prodid & 0x40)) {
- printk(KNOT_XIRC "Ooops: Not a creditcard\n");
+ pr_notice("Oops: Not a creditcard\n");
return 0;
}
if (!(mediaid & 0x01)) {
- printk(KNOT_XIRC "Not an Ethernet card\n");
+ pr_notice("Not an Ethernet card\n");
return 0;
}
if (mediaid & 0x10) {
@@ -643,12 +596,11 @@ set_card_type(struct pcmcia_device *link)
}
}
if (local->card_type == XIR_CE || local->card_type == XIR_CEM) {
- printk(KNOT_XIRC "Sorry, this is an old CE card\n");
+ pr_notice("Sorry, this is an old CE card\n");
return 0;
}
if (local->card_type == XIR_UNKNOWN)
- printk(KNOT_XIRC "unknown card (mediaid=%02x prodid=%02x)\n",
- mediaid, prodid);
+ pr_notice("unknown card (mediaid=%02x prodid=%02x)\n", mediaid, prodid);
return 1;
}
@@ -667,44 +619,53 @@ has_ce2_string(struct pcmcia_device * p_dev)
}
static int
-xirc2ps_config_modem(struct pcmcia_device *p_dev,
- cistpl_cftable_entry_t *cf,
- cistpl_cftable_entry_t *dflt,
- unsigned int vcc,
- void *priv_data)
+xirc2ps_config_modem(struct pcmcia_device *p_dev, void *priv_data)
{
unsigned int ioaddr;
- if (cf->io.nwin > 0 && (cf->io.win[0].base & 0xf) == 8) {
- for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) {
- p_dev->resource[1]->start = cf->io.win[0].base;
- p_dev->resource[0]->start = ioaddr;
- if (!pcmcia_request_io(p_dev))
- return 0;
- }
+ if ((p_dev->resource[0]->start & 0xf) == 8)
+ return -ENODEV;
+
+ p_dev->resource[0]->end = 16;
+ p_dev->resource[1]->end = 8;
+ p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+ p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
+ p_dev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
+ p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
+ p_dev->io_lines = 10;
+
+ p_dev->resource[1]->start = p_dev->resource[0]->start;
+ for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) {
+ p_dev->resource[0]->start = ioaddr;
+ if (!pcmcia_request_io(p_dev))
+ return 0;
}
return -ENODEV;
}
static int
-xirc2ps_config_check(struct pcmcia_device *p_dev,
- cistpl_cftable_entry_t *cf,
- cistpl_cftable_entry_t *dflt,
- unsigned int vcc,
- void *priv_data)
+xirc2ps_config_check(struct pcmcia_device *p_dev, void *priv_data)
{
int *pass = priv_data;
+ resource_size_t tmp = p_dev->resource[1]->start;
- if (cf->io.nwin > 0 && (cf->io.win[0].base & 0xf) == 8) {
- p_dev->resource[1]->start = cf->io.win[0].base;
- p_dev->resource[0]->start = p_dev->resource[1]->start
- + (*pass ? (cf->index & 0x20 ? -24:8)
- : (cf->index & 0x20 ? 8:-24));
- if (!pcmcia_request_io(p_dev))
- return 0;
- }
- return -ENODEV;
+ tmp += (*pass ? (p_dev->config_index & 0x20 ? -24 : 8)
+ : (p_dev->config_index & 0x20 ? 8 : -24));
+
+ if ((p_dev->resource[0]->start & 0xf) == 8)
+ return -ENODEV;
+ p_dev->resource[0]->end = 18;
+ p_dev->resource[1]->end = 8;
+ p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+ p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
+ p_dev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
+ p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
+ p_dev->io_lines = 10;
+
+ p_dev->resource[1]->start = p_dev->resource[0]->start;
+ p_dev->resource[0]->start = tmp;
+ return pcmcia_request_io(p_dev);
}
@@ -727,11 +688,6 @@ static int pcmcia_get_mac_ce(struct pcmcia_device *p_dev,
};
-/****************
- * xirc2ps_config() is scheduled to run after a CARD_INSERTION event
- * is received, to configure the PCMCIA socket, and to make the
- * ethernet device available to the system.
- */
static int
xirc2ps_config(struct pcmcia_device * link)
{
@@ -748,7 +704,7 @@ xirc2ps_config(struct pcmcia_device * link)
/* Is this a valid card */
if (link->has_manf_id == 0) {
- printk(KNOT_XIRC "manfid not found in CIS\n");
+ pr_notice("manfid not found in CIS\n");
goto failure;
}
@@ -770,14 +726,14 @@ xirc2ps_config(struct pcmcia_device * link)
local->manf_str = "Toshiba";
break;
default:
- printk(KNOT_XIRC "Unknown Card Manufacturer ID: 0x%04x\n",
- (unsigned)link->manf_id);
+ pr_notice("Unknown Card Manufacturer ID: 0x%04x\n",
+ (unsigned)link->manf_id);
goto failure;
}
dev_dbg(&link->dev, "found %s card\n", local->manf_str);
if (!set_card_type(link)) {
- printk(KNOT_XIRC "this card is not supported\n");
+ pr_notice("this card is not supported\n");
goto failure;
}
@@ -803,44 +759,38 @@ xirc2ps_config(struct pcmcia_device * link)
err = pcmcia_loop_tuple(link, CISTPL_FUNCE, pcmcia_get_mac_ce, dev);
if (err) {
- printk(KNOT_XIRC "node-id not found in CIS\n");
+ pr_notice("node-id not found in CIS\n");
goto failure;
}
- link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
- link->io_lines = 10;
if (local->modem) {
int pass;
+ link->config_flags |= CONF_AUTO_SET_IO;
- if (do_sound) {
- link->conf.Attributes |= CONF_ENABLE_SPKR;
- link->conf.Status |= CCSR_AUDIO_ENA;
- }
- link->resource[1]->end = 8;
- link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
if (local->dingo) {
/* Take the Modem IO port from the CIS and scan for a free
* Ethernet port */
- link->resource[0]->end = 16; /* no Mako stuff anymore */
if (!pcmcia_loop_config(link, xirc2ps_config_modem, NULL))
goto port_found;
} else {
- link->resource[0]->end = 18;
/* We do 2 passes here: The first one uses the regular mapping and
* the second tries again, thereby considering that the 32 ports are
* mirrored every 32 bytes. Actually we use a mirrored port for
* the Mako if (on the first pass) the COR bit 5 is set.
*/
for (pass=0; pass < 2; pass++)
- if (!pcmcia_loop_config(link, xirc2ps_config_check, &pass))
+ if (!pcmcia_loop_config(link, xirc2ps_config_check,
+ &pass))
goto port_found;
/* if special option:
* try to configure as Ethernet only.
* .... */
}
- printk(KNOT_XIRC "no ports available\n");
+ pr_notice("no ports available\n");
} else {
+ link->io_lines = 10;
link->resource[0]->end = 16;
+ link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) {
link->resource[0]->start = ioaddr;
if (!(err = pcmcia_request_io(link)))
@@ -861,16 +811,14 @@ xirc2ps_config(struct pcmcia_device * link)
if ((err=pcmcia_request_irq(link, xirc2ps_interrupt)))
goto config_error;
- /****************
- * This actually configures the PCMCIA socket -- setting up
- * the I/O windows and the interrupt mapping.
- */
- if ((err=pcmcia_request_configuration(link, &link->conf)))
+ link->config_flags |= CONF_ENABLE_IRQ;
+ if (do_sound)
+ link->config_flags |= CONF_ENABLE_SPKR;
+
+ if ((err = pcmcia_enable_device(link)))
goto config_error;
if (local->dingo) {
- win_req_t req;
-
/* Reset the modem's BAR to the correct value
* This is necessary because in the RequestConfiguration call,
* the base address of the ethernet port (BasePort1) is written
@@ -890,14 +838,14 @@ xirc2ps_config(struct pcmcia_device * link)
* is at 0x0800. So we allocate a window into the attribute
* memory and write direct to the CIS registers
*/
- req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
- req.Base = req.Size = 0;
- req.AccessSpeed = 0;
- if ((err = pcmcia_request_window(link, &req, &link->win)))
+ link->resource[2]->flags = WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_AM |
+ WIN_ENABLE;
+ link->resource[2]->start = link->resource[2]->end = 0;
+ if ((err = pcmcia_request_window(link, link->resource[2], 0)))
goto config_error;
- local->dingo_ccr = ioremap(req.Base,0x1000) + 0x0800;
- if ((err = pcmcia_map_mem_page(link, link->win, 0)))
+ local->dingo_ccr = ioremap(link->resource[2]->start, 0x1000) + 0x0800;
+ if ((err = pcmcia_map_mem_page(link, link->resource[2], 0)))
goto config_error;
/* Setup the CCRs; there are no infos in the CIS about the Ethernet
@@ -911,24 +859,24 @@ xirc2ps_config(struct pcmcia_device * link)
#if 0
{
u_char tmp;
- printk(KERN_INFO "ECOR:");
+ pr_info("ECOR:");
for (i=0; i < 7; i++) {
tmp = readb(local->dingo_ccr + i*2);
- printk(" %02x", tmp);
+ pr_cont(" %02x", tmp);
}
- printk("\n");
- printk(KERN_INFO "DCOR:");
+ pr_cont("\n");
+ pr_info("DCOR:");
for (i=0; i < 4; i++) {
tmp = readb(local->dingo_ccr + 0x20 + i*2);
- printk(" %02x", tmp);
+ pr_cont(" %02x", tmp);
}
- printk("\n");
- printk(KERN_INFO "SCOR:");
+ pr_cont("\n");
+ pr_info("SCOR:");
for (i=0; i < 10; i++) {
tmp = readb(local->dingo_ccr + 0x40 + i*2);
- printk(" %02x", tmp);
+ pr_cont(" %02x", tmp);
}
- printk("\n");
+ pr_cont("\n");
}
#endif
@@ -947,7 +895,7 @@ xirc2ps_config(struct pcmcia_device * link)
(local->mohawk && if_port==4))
dev->if_port = if_port;
else
- printk(KNOT_XIRC "invalid if_port requested\n");
+ pr_notice("invalid if_port requested\n");
/* we can now register the device with the net subsystem */
dev->irq = link->irq;
@@ -959,14 +907,14 @@ xirc2ps_config(struct pcmcia_device * link)
SET_NETDEV_DEV(dev, &link->dev);
if ((err=register_netdev(dev))) {
- printk(KNOT_XIRC "register_netdev() failed\n");
+ pr_notice("register_netdev() failed\n");
goto config_error;
}
/* give some infos about the hardware */
- printk(KERN_INFO "%s: %s: port %#3lx, irq %d, hwaddr %pM\n",
- dev->name, local->manf_str,(u_long)dev->base_addr, (int)dev->irq,
- dev->dev_addr);
+ netdev_info(dev, "%s: port %#3lx, irq %d, hwaddr %pM\n",
+ local->manf_str, (u_long)dev->base_addr, (int)dev->irq,
+ dev->dev_addr);
return 0;
@@ -978,17 +926,12 @@ xirc2ps_config(struct pcmcia_device * link)
return -ENODEV;
} /* xirc2ps_config */
-/****************
- * After a card is removed, xirc2ps_release() will unregister the net
- * device, and release the PCMCIA configuration. If the device is
- * still open, this will be postponed until it is closed.
- */
static void
xirc2ps_release(struct pcmcia_device *link)
{
dev_dbg(&link->dev, "release\n");
- if (link->win) {
+ if (link->resource[2]->end) {
struct net_device *dev = link->priv;
local_info_t *local = netdev_priv(dev);
if (local->dingo)
@@ -1098,8 +1041,7 @@ xirc2ps_interrupt(int irq, void *dev_id)
skb = dev_alloc_skb(pktlen+3); /* 1 extra so we can use insw */
if (!skb) {
- printk(KNOT_XIRC "low memory, packet dropped (size=%u)\n",
- pktlen);
+ pr_notice("low memory, packet dropped (size=%u)\n", pktlen);
dev->stats.rx_dropped++;
} else { /* okay get the packet */
skb_reserve(skb, 2);
@@ -1268,7 +1210,7 @@ xirc_tx_timeout(struct net_device *dev)
{
local_info_t *lp = netdev_priv(dev);
dev->stats.tx_errors++;
- printk(KERN_NOTICE "%s: transmit timed out\n", dev->name);
+ netdev_notice(dev, "transmit timed out\n");
schedule_work(&lp->tx_timeout_task);
}
@@ -1435,8 +1377,7 @@ do_config(struct net_device *dev, struct ifmap *map)
local->probe_port = 0;
dev->if_port = map->port;
}
- printk(KERN_INFO "%s: switching to %s port\n",
- dev->name, if_names[dev->if_port]);
+ netdev_info(dev, "switching to %s port\n", if_names[dev->if_port]);
do_reset(dev,1); /* not the fine way :-) */
}
return 0;
@@ -1576,7 +1517,7 @@ do_reset(struct net_device *dev, int full)
{
SelectPage(0);
value = GetByte(XIRCREG_ESR); /* read the ESR */
- printk(KERN_DEBUG "%s: ESR is: %#02x\n", dev->name, value);
+ pr_debug("%s: ESR is: %#02x\n", dev->name, value);
}
#endif
@@ -1626,13 +1567,12 @@ do_reset(struct net_device *dev, int full)
if (full && local->mohawk && init_mii(dev)) {
if (dev->if_port == 4 || local->dingo || local->new_mii) {
- printk(KERN_INFO "%s: MII selected\n", dev->name);
+ netdev_info(dev, "MII selected\n");
SelectPage(2);
PutByte(XIRCREG2_MSR, GetByte(XIRCREG2_MSR) | 0x08);
msleep(20);
} else {
- printk(KERN_INFO "%s: MII detected; using 10mbs\n",
- dev->name);
+ netdev_info(dev, "MII detected; using 10mbs\n");
SelectPage(0x42);
if (dev->if_port == 2) /* enable 10Base2 */
PutByte(XIRCREG42_SWC1, 0xC0);
@@ -1677,8 +1617,8 @@ do_reset(struct net_device *dev, int full)
}
if (full)
- printk(KERN_INFO "%s: media %s, silicon revision %d\n",
- dev->name, if_names[dev->if_port], local->silicon);
+ netdev_info(dev, "media %s, silicon revision %d\n",
+ if_names[dev->if_port], local->silicon);
/* We should switch back to page 0 to avoid a bug in revision 0
* where regs with offset below 8 can't be read after an access
* to the MAC registers */
@@ -1720,8 +1660,7 @@ init_mii(struct net_device *dev)
control = mii_rd(ioaddr, 0, 0);
if (control & 0x0400) {
- printk(KERN_NOTICE "%s can't take PHY out of isolation mode\n",
- dev->name);
+ netdev_notice(dev, "can't take PHY out of isolation mode\n");
local->probe_port = 0;
return 0;
}
@@ -1739,8 +1678,7 @@ init_mii(struct net_device *dev)
}
if (!(status & 0x0020)) {
- printk(KERN_INFO "%s: autonegotiation failed;"
- " using 10mbs\n", dev->name);
+ netdev_info(dev, "autonegotiation failed; using 10mbs\n");
if (!local->new_mii) {
control = 0x0000;
mii_wr(ioaddr, 0, 0, control, 16);
@@ -1750,8 +1688,7 @@ init_mii(struct net_device *dev)
}
} else {
linkpartner = mii_rd(ioaddr, 0, 5);
- printk(KERN_INFO "%s: MII link partner: %04x\n",
- dev->name, linkpartner);
+ netdev_info(dev, "MII link partner: %04x\n", linkpartner);
if (linkpartner & 0x0080) {
dev->if_port = 4;
} else
@@ -1830,9 +1767,7 @@ MODULE_DEVICE_TABLE(pcmcia, xirc2ps_ids);
static struct pcmcia_driver xirc2ps_cs_driver = {
.owner = THIS_MODULE,
- .drv = {
- .name = "xirc2ps_cs",
- },
+ .name = "xirc2ps_cs",
.probe = xirc2ps_probe,
.remove = xirc2ps_detach,
.id_table = xirc2ps_ids,
diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c
index c200c2821730..aee3bb0358bf 100644
--- a/drivers/net/pcnet32.c
+++ b/drivers/net/pcnet32.c
@@ -376,7 +376,7 @@ static void pcnet32_wio_reset(unsigned long addr)
static int pcnet32_wio_check(unsigned long addr)
{
outw(88, addr + PCNET32_WIO_RAP);
- return (inw(addr + PCNET32_WIO_RAP) == 88);
+ return inw(addr + PCNET32_WIO_RAP) == 88;
}
static struct pcnet32_access pcnet32_wio = {
@@ -431,7 +431,7 @@ static void pcnet32_dwio_reset(unsigned long addr)
static int pcnet32_dwio_check(unsigned long addr)
{
outl(88, addr + PCNET32_DWIO_RAP);
- return ((inl(addr + PCNET32_DWIO_RAP) & 0xffff) == 88);
+ return (inl(addr + PCNET32_DWIO_RAP) & 0xffff) == 88;
}
static struct pcnet32_access pcnet32_dwio = {
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index eb799b36c86a..cb3d13e4e074 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -58,7 +58,6 @@ config BROADCOM_PHY
config BCM63XX_PHY
tristate "Drivers for Broadcom 63xx SOCs internal PHY"
- depends on BCM63XX
---help---
Currently supports the 6348 and 6358 PHYs.
diff --git a/drivers/net/phy/bcm63xx.c b/drivers/net/phy/bcm63xx.c
index c12815679837..e16f98cb4f04 100644
--- a/drivers/net/phy/bcm63xx.c
+++ b/drivers/net/phy/bcm63xx.c
@@ -131,7 +131,7 @@ static void __exit bcm63xx_phy_exit(void)
module_init(bcm63xx_phy_init);
module_exit(bcm63xx_phy_exit);
-static struct mdio_device_id bcm63xx_tbl[] = {
+static struct mdio_device_id __maybe_unused bcm63xx_tbl[] = {
{ 0x00406000, 0xfffffc00 },
{ 0x002bdc00, 0xfffffc00 },
{ }
diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
index 4accd83d3dfe..d84c4224dd12 100644
--- a/drivers/net/phy/broadcom.c
+++ b/drivers/net/phy/broadcom.c
@@ -930,7 +930,7 @@ static void __exit broadcom_exit(void)
module_init(broadcom_init);
module_exit(broadcom_exit);
-static struct mdio_device_id broadcom_tbl[] = {
+static struct mdio_device_id __maybe_unused broadcom_tbl[] = {
{ PHY_ID_BCM5411, 0xfffffff0 },
{ PHY_ID_BCM5421, 0xfffffff0 },
{ PHY_ID_BCM5461, 0xfffffff0 },
diff --git a/drivers/net/phy/cicada.c b/drivers/net/phy/cicada.c
index 1a325d63756b..d28173161c21 100644
--- a/drivers/net/phy/cicada.c
+++ b/drivers/net/phy/cicada.c
@@ -159,7 +159,7 @@ static void __exit cicada_exit(void)
module_init(cicada_init);
module_exit(cicada_exit);
-static struct mdio_device_id cicada_tbl[] = {
+static struct mdio_device_id __maybe_unused cicada_tbl[] = {
{ 0x000fc410, 0x000ffff0 },
{ 0x000fc440, 0x000fffc0 },
{ }
diff --git a/drivers/net/phy/davicom.c b/drivers/net/phy/davicom.c
index 29c17617a2ec..2f774acdb551 100644
--- a/drivers/net/phy/davicom.c
+++ b/drivers/net/phy/davicom.c
@@ -219,7 +219,7 @@ static void __exit davicom_exit(void)
module_init(davicom_init);
module_exit(davicom_exit);
-static struct mdio_device_id davicom_tbl[] = {
+static struct mdio_device_id __maybe_unused davicom_tbl[] = {
{ 0x0181b880, 0x0ffffff0 },
{ 0x0181b8a0, 0x0ffffff0 },
{ 0x00181b80, 0x0ffffff0 },
diff --git a/drivers/net/phy/et1011c.c b/drivers/net/phy/et1011c.c
index 13995f52d6af..a8eb19ec3183 100644
--- a/drivers/net/phy/et1011c.c
+++ b/drivers/net/phy/et1011c.c
@@ -111,7 +111,7 @@ static void __exit et1011c_exit(void)
module_init(et1011c_init);
module_exit(et1011c_exit);
-static struct mdio_device_id et1011c_tbl[] = {
+static struct mdio_device_id __maybe_unused et1011c_tbl[] = {
{ 0x0282f014, 0xfffffff0 },
{ }
};
diff --git a/drivers/net/phy/icplus.c b/drivers/net/phy/icplus.c
index 3f2583f18a39..c1d2d251fe8b 100644
--- a/drivers/net/phy/icplus.c
+++ b/drivers/net/phy/icplus.c
@@ -134,7 +134,7 @@ static void __exit ip175c_exit(void)
module_init(ip175c_init);
module_exit(ip175c_exit);
-static struct mdio_device_id icplus_tbl[] = {
+static struct mdio_device_id __maybe_unused icplus_tbl[] = {
{ 0x02430d80, 0x0ffffff0 },
{ }
};
diff --git a/drivers/net/phy/lxt.c b/drivers/net/phy/lxt.c
index 29c39ff85de5..6f6e8b616a62 100644
--- a/drivers/net/phy/lxt.c
+++ b/drivers/net/phy/lxt.c
@@ -223,7 +223,7 @@ static void __exit lxt_exit(void)
module_init(lxt_init);
module_exit(lxt_exit);
-static struct mdio_device_id lxt_tbl[] = {
+static struct mdio_device_id __maybe_unused lxt_tbl[] = {
{ 0x78100000, 0xfffffff0 },
{ 0x001378e0, 0xfffffff0 },
{ 0x00137a10, 0xfffffff0 },
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index 0101f2bdf400..e2afdce0a437 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -196,20 +196,27 @@ static int m88e1121_config_aneg(struct phy_device *phydev)
MII_88E1121_PHY_MSCR_PAGE);
if (err < 0)
return err;
- mscr = phy_read(phydev, MII_88E1121_PHY_MSCR_REG) &
- MII_88E1121_PHY_MSCR_DELAY_MASK;
- if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
- mscr |= (MII_88E1121_PHY_MSCR_RX_DELAY |
- MII_88E1121_PHY_MSCR_TX_DELAY);
- else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
- mscr |= MII_88E1121_PHY_MSCR_RX_DELAY;
- else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
- mscr |= MII_88E1121_PHY_MSCR_TX_DELAY;
+ if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) ||
+ (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) ||
+ (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
+ (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)) {
- err = phy_write(phydev, MII_88E1121_PHY_MSCR_REG, mscr);
- if (err < 0)
- return err;
+ mscr = phy_read(phydev, MII_88E1121_PHY_MSCR_REG) &
+ MII_88E1121_PHY_MSCR_DELAY_MASK;
+
+ if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
+ mscr |= (MII_88E1121_PHY_MSCR_RX_DELAY |
+ MII_88E1121_PHY_MSCR_TX_DELAY);
+ else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
+ mscr |= MII_88E1121_PHY_MSCR_RX_DELAY;
+ else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
+ mscr |= MII_88E1121_PHY_MSCR_TX_DELAY;
+
+ err = phy_write(phydev, MII_88E1121_PHY_MSCR_REG, mscr);
+ if (err < 0)
+ return err;
+ }
phy_write(phydev, MII_88E1121_PHY_PAGE, oldpage);
@@ -721,7 +728,7 @@ static void __exit marvell_exit(void)
module_init(marvell_init);
module_exit(marvell_exit);
-static struct mdio_device_id marvell_tbl[] = {
+static struct mdio_device_id __maybe_unused marvell_tbl[] = {
{ 0x01410c60, 0xfffffff0 },
{ 0x01410c90, 0xfffffff0 },
{ 0x01410cc0, 0xfffffff0 },
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index 8bb7db676a5c..0fd1678bc5a9 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -231,7 +231,7 @@ MODULE_DESCRIPTION("Micrel PHY driver");
MODULE_AUTHOR("David J. Choi");
MODULE_LICENSE("GPL");
-static struct mdio_device_id micrel_tbl[] = {
+static struct mdio_device_id __maybe_unused micrel_tbl[] = {
{ PHY_ID_KSZ9021, 0x000fff10 },
{ PHY_ID_KS8001, 0x00fffff0 },
{ PHY_ID_KS8737, 0x00fffff0 },
diff --git a/drivers/net/phy/national.c b/drivers/net/phy/national.c
index a73ba0bcc0ce..0620ba963508 100644
--- a/drivers/net/phy/national.c
+++ b/drivers/net/phy/national.c
@@ -151,7 +151,7 @@ MODULE_LICENSE("GPL");
module_init(ns_init);
module_exit(ns_exit);
-static struct mdio_device_id ns_tbl[] = {
+static struct mdio_device_id __maybe_unused ns_tbl[] = {
{ DP83865_PHY_ID, 0xfffffff0 },
{ }
};
diff --git a/drivers/net/phy/qsemi.c b/drivers/net/phy/qsemi.c
index 6736b23f1b28..fe0d0a15d5e1 100644
--- a/drivers/net/phy/qsemi.c
+++ b/drivers/net/phy/qsemi.c
@@ -138,7 +138,7 @@ static void __exit qs6612_exit(void)
module_init(qs6612_init);
module_exit(qs6612_exit);
-static struct mdio_device_id qs6612_tbl[] = {
+static struct mdio_device_id __maybe_unused qs6612_tbl[] = {
{ 0x00181440, 0xfffffff0 },
{ }
};
diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
index f567c0e1aaa1..a4eae750a414 100644
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -79,7 +79,7 @@ static void __exit realtek_exit(void)
module_init(realtek_init);
module_exit(realtek_exit);
-static struct mdio_device_id realtek_tbl[] = {
+static struct mdio_device_id __maybe_unused realtek_tbl[] = {
{ 0x001cc912, 0x001fffff },
{ }
};
diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c
index 78fa988256fc..342505c976d6 100644
--- a/drivers/net/phy/smsc.c
+++ b/drivers/net/phy/smsc.c
@@ -254,7 +254,7 @@ MODULE_LICENSE("GPL");
module_init(smsc_init);
module_exit(smsc_exit);
-static struct mdio_device_id smsc_tbl[] = {
+static struct mdio_device_id __maybe_unused smsc_tbl[] = {
{ 0x0007c0a0, 0xfffffff0 },
{ 0x0007c0b0, 0xfffffff0 },
{ 0x0007c0c0, 0xfffffff0 },
diff --git a/drivers/net/phy/ste10Xp.c b/drivers/net/phy/ste10Xp.c
index 72290099e5e1..187a2fa814f2 100644
--- a/drivers/net/phy/ste10Xp.c
+++ b/drivers/net/phy/ste10Xp.c
@@ -132,7 +132,7 @@ static void __exit ste10Xp_exit(void)
module_init(ste10Xp_init);
module_exit(ste10Xp_exit);
-static struct mdio_device_id ste10Xp_tbl[] = {
+static struct mdio_device_id __maybe_unused ste10Xp_tbl[] = {
{ STE101P_PHY_ID, 0xfffffff0 },
{ STE100P_PHY_ID, 0xffffffff },
{ }
diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c
index 45cce50a2799..5d8f6e17bd55 100644
--- a/drivers/net/phy/vitesse.c
+++ b/drivers/net/phy/vitesse.c
@@ -192,7 +192,7 @@ static void __exit vsc82xx_exit(void)
module_init(vsc82xx_init);
module_exit(vsc82xx_exit);
-static struct mdio_device_id vitesse_tbl[] = {
+static struct mdio_device_id __maybe_unused vitesse_tbl[] = {
{ PHY_ID_VSC8244, 0x000fffc0 },
{ PHY_ID_VSC8221, 0x000ffff0 },
{ }
diff --git a/drivers/net/plip.c b/drivers/net/plip.c
index ec0349e84a8a..ca4df7f4cf21 100644
--- a/drivers/net/plip.c
+++ b/drivers/net/plip.c
@@ -995,8 +995,10 @@ plip_tx_packet(struct sk_buff *skb, struct net_device *dev)
static void
plip_rewrite_address(const struct net_device *dev, struct ethhdr *eth)
{
- const struct in_device *in_dev = dev->ip_ptr;
+ const struct in_device *in_dev;
+ rcu_read_lock();
+ in_dev = __in_dev_get_rcu(dev);
if (in_dev) {
/* Any address will do - we take the first */
const struct in_ifaddr *ifa = in_dev->ifa_list;
@@ -1006,6 +1008,7 @@ plip_rewrite_address(const struct net_device *dev, struct ethhdr *eth)
memcpy(eth->h_dest+2, &ifa->ifa_address, 4);
}
}
+ rcu_read_unlock();
}
static int
@@ -1088,7 +1091,8 @@ plip_open(struct net_device *dev)
when the device address isn't identical to the address of a
received frame, the kernel incorrectly drops it). */
- if ((in_dev=dev->ip_ptr) != NULL) {
+ in_dev=__in_dev_get_rtnl(dev);
+ if (in_dev) {
/* Any address will do - we take the first. We already
have the first two bytes filled with 0xfc, from
plip_init_dev(). */
@@ -1279,7 +1283,6 @@ static void plip_attach (struct parport *port)
if (!nl->pardev) {
printk(KERN_ERR "%s: parport_register failed\n", name);
goto err_free_dev;
- return;
}
plip_init_netdev(dev);
diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c
index af50a530daee..78d70a6481bf 100644
--- a/drivers/net/ppp_async.c
+++ b/drivers/net/ppp_async.c
@@ -184,7 +184,7 @@ ppp_asynctty_open(struct tty_struct *tty)
tasklet_init(&ap->tsk, ppp_async_process, (unsigned long) ap);
atomic_set(&ap->refcnt, 1);
- init_MUTEX_LOCKED(&ap->dead_sem);
+ sema_init(&ap->dead_sem, 0);
ap->chan.private = ap;
ap->chan.ops = &async_ops;
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index 736b91703b3e..09cf56d0416a 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -856,7 +856,8 @@ static const struct file_operations ppp_device_fops = {
.poll = ppp_poll,
.unlocked_ioctl = ppp_ioctl,
.open = ppp_open,
- .release = ppp_release
+ .release = ppp_release,
+ .llseek = noop_llseek,
};
static __net_init int ppp_init_net(struct net *net)
@@ -1547,9 +1548,11 @@ ppp_channel_push(struct channel *pch)
* Receive-side routines.
*/
-/* misuse a few fields of the skb for MP reconstruction */
-#define sequence priority
-#define BEbits cb[0]
+struct ppp_mp_skb_parm {
+ u32 sequence;
+ u8 BEbits;
+};
+#define PPP_MP_CB(skb) ((struct ppp_mp_skb_parm *)((skb)->cb))
static inline void
ppp_do_recv(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
@@ -1878,13 +1881,13 @@ ppp_receive_mp_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
seq = (skb->data[3] << 16) | (skb->data[4] << 8)| skb->data[5];
mask = 0xffffff;
}
- skb->BEbits = skb->data[2];
+ PPP_MP_CB(skb)->BEbits = skb->data[2];
skb_pull(skb, mphdrlen); /* pull off PPP and MP headers */
/*
* Do protocol ID decompression on the first fragment of each packet.
*/
- if ((skb->BEbits & B) && (skb->data[0] & 1))
+ if ((PPP_MP_CB(skb)->BEbits & B) && (skb->data[0] & 1))
*skb_push(skb, 1) = 0;
/*
@@ -1896,7 +1899,7 @@ ppp_receive_mp_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
seq += mask + 1;
else if ((int)(seq - ppp->minseq) > (int)(mask >> 1))
seq -= mask + 1; /* should never happen */
- skb->sequence = seq;
+ PPP_MP_CB(skb)->sequence = seq;
pch->lastseq = seq;
/*
@@ -1932,8 +1935,8 @@ ppp_receive_mp_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
before the start of the queue. */
if (skb_queue_len(&ppp->mrq) >= PPP_MP_MAX_QLEN) {
struct sk_buff *mskb = skb_peek(&ppp->mrq);
- if (seq_before(ppp->minseq, mskb->sequence))
- ppp->minseq = mskb->sequence;
+ if (seq_before(ppp->minseq, PPP_MP_CB(mskb)->sequence))
+ ppp->minseq = PPP_MP_CB(mskb)->sequence;
}
/* Pull completed packets off the queue and receive them. */
@@ -1963,12 +1966,12 @@ ppp_mp_insert(struct ppp *ppp, struct sk_buff *skb)
{
struct sk_buff *p;
struct sk_buff_head *list = &ppp->mrq;
- u32 seq = skb->sequence;
+ u32 seq = PPP_MP_CB(skb)->sequence;
/* N.B. we don't need to lock the list lock because we have the
ppp unit receive-side lock. */
skb_queue_walk(list, p) {
- if (seq_before(seq, p->sequence))
+ if (seq_before(seq, PPP_MP_CB(p)->sequence))
break;
}
__skb_queue_before(list, p, skb);
@@ -1997,22 +2000,22 @@ ppp_mp_reconstruct(struct ppp *ppp)
tail = NULL;
for (p = head; p != (struct sk_buff *) list; p = next) {
next = p->next;
- if (seq_before(p->sequence, seq)) {
+ if (seq_before(PPP_MP_CB(p)->sequence, seq)) {
/* this can't happen, anyway ignore the skb */
printk(KERN_ERR "ppp_mp_reconstruct bad seq %u < %u\n",
- p->sequence, seq);
+ PPP_MP_CB(p)->sequence, seq);
head = next;
continue;
}
- if (p->sequence != seq) {
+ if (PPP_MP_CB(p)->sequence != seq) {
/* Fragment `seq' is missing. If it is after
minseq, it might arrive later, so stop here. */
if (seq_after(seq, minseq))
break;
/* Fragment `seq' is lost, keep going. */
lost = 1;
- seq = seq_before(minseq, p->sequence)?
- minseq + 1: p->sequence;
+ seq = seq_before(minseq, PPP_MP_CB(p)->sequence)?
+ minseq + 1: PPP_MP_CB(p)->sequence;
next = p;
continue;
}
@@ -2026,7 +2029,7 @@ ppp_mp_reconstruct(struct ppp *ppp)
*/
/* B bit set indicates this fragment starts a packet */
- if (p->BEbits & B) {
+ if (PPP_MP_CB(p)->BEbits & B) {
head = p;
lost = 0;
len = 0;
@@ -2035,7 +2038,8 @@ ppp_mp_reconstruct(struct ppp *ppp)
len += p->len;
/* Got a complete packet yet? */
- if (lost == 0 && (p->BEbits & E) && (head->BEbits & B)) {
+ if (lost == 0 && (PPP_MP_CB(p)->BEbits & E) &&
+ (PPP_MP_CB(head)->BEbits & B)) {
if (len > ppp->mrru + 2) {
++ppp->dev->stats.rx_length_errors;
printk(KERN_DEBUG "PPP: reconstructed packet"
@@ -2061,7 +2065,7 @@ ppp_mp_reconstruct(struct ppp *ppp)
* and we haven't found a complete valid packet yet,
* we can discard up to and including this fragment.
*/
- if (p->BEbits & E)
+ if (PPP_MP_CB(p)->BEbits & E)
head = next;
++seq;
@@ -2071,10 +2075,11 @@ ppp_mp_reconstruct(struct ppp *ppp)
if (tail != NULL) {
/* If we have discarded any fragments,
signal a receive error. */
- if (head->sequence != ppp->nextseq) {
+ if (PPP_MP_CB(head)->sequence != ppp->nextseq) {
if (ppp->debug & 1)
printk(KERN_DEBUG " missed pkts %u..%u\n",
- ppp->nextseq, head->sequence-1);
+ ppp->nextseq,
+ PPP_MP_CB(head)->sequence-1);
++ppp->dev->stats.rx_dropped;
ppp_receive_error(ppp);
}
@@ -2083,7 +2088,7 @@ ppp_mp_reconstruct(struct ppp *ppp)
/* copy to a single skb */
for (p = head; p != tail->next; p = p->next)
skb_copy_bits(p, 0, skb_put(skb, p->len), p->len);
- ppp->nextseq = tail->sequence + 1;
+ ppp->nextseq = PPP_MP_CB(tail)->sequence + 1;
head = tail->next;
}
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c
index c07de359dc07..d72fb0519a2a 100644
--- a/drivers/net/pppoe.c
+++ b/drivers/net/pppoe.c
@@ -1124,7 +1124,7 @@ static const struct proto_ops pppoe_ops = {
.ioctl = pppox_ioctl,
};
-static struct pppox_proto pppoe_proto = {
+static const struct pppox_proto pppoe_proto = {
.create = pppoe_create,
.ioctl = pppoe_ioctl,
.owner = THIS_MODULE,
diff --git a/drivers/net/pppox.c b/drivers/net/pppox.c
index d4191ef9cad1..8c0d170dabcd 100644
--- a/drivers/net/pppox.c
+++ b/drivers/net/pppox.c
@@ -36,9 +36,9 @@
#include <asm/uaccess.h>
-static struct pppox_proto *pppox_protos[PX_MAX_PROTO + 1];
+static const struct pppox_proto *pppox_protos[PX_MAX_PROTO + 1];
-int register_pppox_proto(int proto_num, struct pppox_proto *pp)
+int register_pppox_proto(int proto_num, const struct pppox_proto *pp)
{
if (proto_num < 0 || proto_num > PX_MAX_PROTO)
return -EINVAL;
diff --git a/drivers/net/pptp.c b/drivers/net/pptp.c
new file mode 100644
index 000000000000..ccbc91326bfa
--- /dev/null
+++ b/drivers/net/pptp.c
@@ -0,0 +1,726 @@
+/*
+ * Point-to-Point Tunneling Protocol for Linux
+ *
+ * Authors: Dmitry Kozlov <xeb@mail.ru>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+
+#include <linux/string.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/net.h>
+#include <linux/skbuff.h>
+#include <linux/vmalloc.h>
+#include <linux/init.h>
+#include <linux/ppp_channel.h>
+#include <linux/ppp_defs.h>
+#include <linux/if_pppox.h>
+#include <linux/if_ppp.h>
+#include <linux/notifier.h>
+#include <linux/file.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv4.h>
+#include <linux/version.h>
+#include <linux/rcupdate.h>
+#include <linux/spinlock.h>
+
+#include <net/sock.h>
+#include <net/protocol.h>
+#include <net/ip.h>
+#include <net/icmp.h>
+#include <net/route.h>
+#include <net/gre.h>
+
+#include <linux/uaccess.h>
+
+#define PPTP_DRIVER_VERSION "0.8.5"
+
+#define MAX_CALLID 65535
+
+static DECLARE_BITMAP(callid_bitmap, MAX_CALLID + 1);
+static struct pppox_sock **callid_sock;
+
+static DEFINE_SPINLOCK(chan_lock);
+
+static struct proto pptp_sk_proto __read_mostly;
+static const struct ppp_channel_ops pptp_chan_ops;
+static const struct proto_ops pptp_ops;
+
+#define PPP_LCP_ECHOREQ 0x09
+#define PPP_LCP_ECHOREP 0x0A
+#define SC_RCV_BITS (SC_RCV_B7_1|SC_RCV_B7_0|SC_RCV_ODDP|SC_RCV_EVNP)
+
+#define MISSING_WINDOW 20
+#define WRAPPED(curseq, lastseq)\
+ ((((curseq) & 0xffffff00) == 0) &&\
+ (((lastseq) & 0xffffff00) == 0xffffff00))
+
+#define PPTP_GRE_PROTO 0x880B
+#define PPTP_GRE_VER 0x1
+
+#define PPTP_GRE_FLAG_C 0x80
+#define PPTP_GRE_FLAG_R 0x40
+#define PPTP_GRE_FLAG_K 0x20
+#define PPTP_GRE_FLAG_S 0x10
+#define PPTP_GRE_FLAG_A 0x80
+
+#define PPTP_GRE_IS_C(f) ((f)&PPTP_GRE_FLAG_C)
+#define PPTP_GRE_IS_R(f) ((f)&PPTP_GRE_FLAG_R)
+#define PPTP_GRE_IS_K(f) ((f)&PPTP_GRE_FLAG_K)
+#define PPTP_GRE_IS_S(f) ((f)&PPTP_GRE_FLAG_S)
+#define PPTP_GRE_IS_A(f) ((f)&PPTP_GRE_FLAG_A)
+
+#define PPTP_HEADER_OVERHEAD (2+sizeof(struct pptp_gre_header))
+struct pptp_gre_header {
+ u8 flags;
+ u8 ver;
+ u16 protocol;
+ u16 payload_len;
+ u16 call_id;
+ u32 seq;
+ u32 ack;
+} __packed;
+
+static struct pppox_sock *lookup_chan(u16 call_id, __be32 s_addr)
+{
+ struct pppox_sock *sock;
+ struct pptp_opt *opt;
+
+ rcu_read_lock();
+ sock = rcu_dereference(callid_sock[call_id]);
+ if (sock) {
+ opt = &sock->proto.pptp;
+ if (opt->dst_addr.sin_addr.s_addr != s_addr)
+ sock = NULL;
+ else
+ sock_hold(sk_pppox(sock));
+ }
+ rcu_read_unlock();
+
+ return sock;
+}
+
+static int lookup_chan_dst(u16 call_id, __be32 d_addr)
+{
+ struct pppox_sock *sock;
+ struct pptp_opt *opt;
+ int i;
+
+ rcu_read_lock();
+ for (i = find_next_bit(callid_bitmap, MAX_CALLID, 1); i < MAX_CALLID;
+ i = find_next_bit(callid_bitmap, MAX_CALLID, i + 1)) {
+ sock = rcu_dereference(callid_sock[i]);
+ if (!sock)
+ continue;
+ opt = &sock->proto.pptp;
+ if (opt->dst_addr.call_id == call_id &&
+ opt->dst_addr.sin_addr.s_addr == d_addr)
+ break;
+ }
+ rcu_read_unlock();
+
+ return i < MAX_CALLID;
+}
+
+static int add_chan(struct pppox_sock *sock)
+{
+ static int call_id;
+
+ spin_lock(&chan_lock);
+ if (!sock->proto.pptp.src_addr.call_id) {
+ call_id = find_next_zero_bit(callid_bitmap, MAX_CALLID, call_id + 1);
+ if (call_id == MAX_CALLID) {
+ call_id = find_next_zero_bit(callid_bitmap, MAX_CALLID, 1);
+ if (call_id == MAX_CALLID)
+ goto out_err;
+ }
+ sock->proto.pptp.src_addr.call_id = call_id;
+ } else if (test_bit(sock->proto.pptp.src_addr.call_id, callid_bitmap))
+ goto out_err;
+
+ set_bit(sock->proto.pptp.src_addr.call_id, callid_bitmap);
+ rcu_assign_pointer(callid_sock[sock->proto.pptp.src_addr.call_id], sock);
+ spin_unlock(&chan_lock);
+
+ return 0;
+
+out_err:
+ spin_unlock(&chan_lock);
+ return -1;
+}
+
+static void del_chan(struct pppox_sock *sock)
+{
+ spin_lock(&chan_lock);
+ clear_bit(sock->proto.pptp.src_addr.call_id, callid_bitmap);
+ rcu_assign_pointer(callid_sock[sock->proto.pptp.src_addr.call_id], NULL);
+ spin_unlock(&chan_lock);
+ synchronize_rcu();
+}
+
+static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
+{
+ struct sock *sk = (struct sock *) chan->private;
+ struct pppox_sock *po = pppox_sk(sk);
+ struct pptp_opt *opt = &po->proto.pptp;
+ struct pptp_gre_header *hdr;
+ unsigned int header_len = sizeof(*hdr);
+ int err = 0;
+ int islcp;
+ int len;
+ unsigned char *data;
+ __u32 seq_recv;
+
+
+ struct rtable *rt;
+ struct net_device *tdev;
+ struct iphdr *iph;
+ int max_headroom;
+
+ if (sk_pppox(po)->sk_state & PPPOX_DEAD)
+ goto tx_error;
+
+ {
+ struct flowi fl = { .oif = 0,
+ .nl_u = {
+ .ip4_u = {
+ .daddr = opt->dst_addr.sin_addr.s_addr,
+ .saddr = opt->src_addr.sin_addr.s_addr,
+ .tos = RT_TOS(0) } },
+ .proto = IPPROTO_GRE };
+ err = ip_route_output_key(&init_net, &rt, &fl);
+ if (err)
+ goto tx_error;
+ }
+ tdev = rt->dst.dev;
+
+ max_headroom = LL_RESERVED_SPACE(tdev) + sizeof(*iph) + sizeof(*hdr) + 2;
+
+ if (skb_headroom(skb) < max_headroom || skb_cloned(skb) || skb_shared(skb)) {
+ struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom);
+ if (!new_skb) {
+ ip_rt_put(rt);
+ goto tx_error;
+ }
+ if (skb->sk)
+ skb_set_owner_w(new_skb, skb->sk);
+ kfree_skb(skb);
+ skb = new_skb;
+ }
+
+ data = skb->data;
+ islcp = ((data[0] << 8) + data[1]) == PPP_LCP && 1 <= data[2] && data[2] <= 7;
+
+ /* compress protocol field */
+ if ((opt->ppp_flags & SC_COMP_PROT) && data[0] == 0 && !islcp)
+ skb_pull(skb, 1);
+
+ /* Put in the address/control bytes if necessary */
+ if ((opt->ppp_flags & SC_COMP_AC) == 0 || islcp) {
+ data = skb_push(skb, 2);
+ data[0] = PPP_ALLSTATIONS;
+ data[1] = PPP_UI;
+ }
+
+ len = skb->len;
+
+ seq_recv = opt->seq_recv;
+
+ if (opt->ack_sent == seq_recv)
+ header_len -= sizeof(hdr->ack);
+
+ /* Push down and install GRE header */
+ skb_push(skb, header_len);
+ hdr = (struct pptp_gre_header *)(skb->data);
+
+ hdr->flags = PPTP_GRE_FLAG_K;
+ hdr->ver = PPTP_GRE_VER;
+ hdr->protocol = htons(PPTP_GRE_PROTO);
+ hdr->call_id = htons(opt->dst_addr.call_id);
+
+ hdr->flags |= PPTP_GRE_FLAG_S;
+ hdr->seq = htonl(++opt->seq_sent);
+ if (opt->ack_sent != seq_recv) {
+ /* send ack with this message */
+ hdr->ver |= PPTP_GRE_FLAG_A;
+ hdr->ack = htonl(seq_recv);
+ opt->ack_sent = seq_recv;
+ }
+ hdr->payload_len = htons(len);
+
+ /* Push down and install the IP header. */
+
+ skb_reset_transport_header(skb);
+ skb_push(skb, sizeof(*iph));
+ skb_reset_network_header(skb);
+ memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
+ IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | IPSKB_REROUTED);
+
+ iph = ip_hdr(skb);
+ iph->version = 4;
+ iph->ihl = sizeof(struct iphdr) >> 2;
+ if (ip_dont_fragment(sk, &rt->dst))
+ iph->frag_off = htons(IP_DF);
+ else
+ iph->frag_off = 0;
+ iph->protocol = IPPROTO_GRE;
+ iph->tos = 0;
+ iph->daddr = rt->rt_dst;
+ iph->saddr = rt->rt_src;
+ iph->ttl = dst_metric(&rt->dst, RTAX_HOPLIMIT);
+ iph->tot_len = htons(skb->len);
+
+ skb_dst_drop(skb);
+ skb_dst_set(skb, &rt->dst);
+
+ nf_reset(skb);
+
+ skb->ip_summed = CHECKSUM_NONE;
+ ip_select_ident(iph, &rt->dst, NULL);
+ ip_send_check(iph);
+
+ ip_local_out(skb);
+
+tx_error:
+ return 1;
+}
+
+static int pptp_rcv_core(struct sock *sk, struct sk_buff *skb)
+{
+ struct pppox_sock *po = pppox_sk(sk);
+ struct pptp_opt *opt = &po->proto.pptp;
+ int headersize, payload_len, seq;
+ __u8 *payload;
+ struct pptp_gre_header *header;
+
+ if (!(sk->sk_state & PPPOX_CONNECTED)) {
+ if (sock_queue_rcv_skb(sk, skb))
+ goto drop;
+ return NET_RX_SUCCESS;
+ }
+
+ header = (struct pptp_gre_header *)(skb->data);
+
+ /* test if acknowledgement present */
+ if (PPTP_GRE_IS_A(header->ver)) {
+ __u32 ack = (PPTP_GRE_IS_S(header->flags)) ?
+ header->ack : header->seq; /* ack in different place if S = 0 */
+
+ ack = ntohl(ack);
+
+ if (ack > opt->ack_recv)
+ opt->ack_recv = ack;
+ /* also handle sequence number wrap-around */
+ if (WRAPPED(ack, opt->ack_recv))
+ opt->ack_recv = ack;
+ }
+
+ /* test if payload present */
+ if (!PPTP_GRE_IS_S(header->flags))
+ goto drop;
+
+ headersize = sizeof(*header);
+ payload_len = ntohs(header->payload_len);
+ seq = ntohl(header->seq);
+
+ /* no ack present? */
+ if (!PPTP_GRE_IS_A(header->ver))
+ headersize -= sizeof(header->ack);
+ /* check for incomplete packet (length smaller than expected) */
+ if (skb->len - headersize < payload_len)
+ goto drop;
+
+ payload = skb->data + headersize;
+ /* check for expected sequence number */
+ if (seq < opt->seq_recv + 1 || WRAPPED(opt->seq_recv, seq)) {
+ if ((payload[0] == PPP_ALLSTATIONS) && (payload[1] == PPP_UI) &&
+ (PPP_PROTOCOL(payload) == PPP_LCP) &&
+ ((payload[4] == PPP_LCP_ECHOREQ) || (payload[4] == PPP_LCP_ECHOREP)))
+ goto allow_packet;
+ } else {
+ opt->seq_recv = seq;
+allow_packet:
+ skb_pull(skb, headersize);
+
+ if (payload[0] == PPP_ALLSTATIONS && payload[1] == PPP_UI) {
+ /* chop off address/control */
+ if (skb->len < 3)
+ goto drop;
+ skb_pull(skb, 2);
+ }
+
+ if ((*skb->data) & 1) {
+ /* protocol is compressed */
+ skb_push(skb, 1)[0] = 0;
+ }
+
+ skb->ip_summed = CHECKSUM_NONE;
+ skb_set_network_header(skb, skb->head-skb->data);
+ ppp_input(&po->chan, skb);
+
+ return NET_RX_SUCCESS;
+ }
+drop:
+ kfree_skb(skb);
+ return NET_RX_DROP;
+}
+
+static int pptp_rcv(struct sk_buff *skb)
+{
+ struct pppox_sock *po;
+ struct pptp_gre_header *header;
+ struct iphdr *iph;
+
+ if (skb->pkt_type != PACKET_HOST)
+ goto drop;
+
+ if (!pskb_may_pull(skb, 12))
+ goto drop;
+
+ iph = ip_hdr(skb);
+
+ header = (struct pptp_gre_header *)skb->data;
+
+ if (ntohs(header->protocol) != PPTP_GRE_PROTO || /* PPTP-GRE protocol for PPTP */
+ PPTP_GRE_IS_C(header->flags) || /* flag C should be clear */
+ PPTP_GRE_IS_R(header->flags) || /* flag R should be clear */
+ !PPTP_GRE_IS_K(header->flags) || /* flag K should be set */
+ (header->flags&0xF) != 0) /* routing and recursion ctrl = 0 */
+ /* if invalid, discard this packet */
+ goto drop;
+
+ po = lookup_chan(htons(header->call_id), iph->saddr);
+ if (po) {
+ skb_dst_drop(skb);
+ nf_reset(skb);
+ return sk_receive_skb(sk_pppox(po), skb, 0);
+ }
+drop:
+ kfree_skb(skb);
+ return NET_RX_DROP;
+}
+
+static int pptp_bind(struct socket *sock, struct sockaddr *uservaddr,
+ int sockaddr_len)
+{
+ struct sock *sk = sock->sk;
+ struct sockaddr_pppox *sp = (struct sockaddr_pppox *) uservaddr;
+ struct pppox_sock *po = pppox_sk(sk);
+ struct pptp_opt *opt = &po->proto.pptp;
+ int error = 0;
+
+ lock_sock(sk);
+
+ opt->src_addr = sp->sa_addr.pptp;
+ if (add_chan(po)) {
+ release_sock(sk);
+ error = -EBUSY;
+ }
+
+ release_sock(sk);
+ return error;
+}
+
+static int pptp_connect(struct socket *sock, struct sockaddr *uservaddr,
+ int sockaddr_len, int flags)
+{
+ struct sock *sk = sock->sk;
+ struct sockaddr_pppox *sp = (struct sockaddr_pppox *) uservaddr;
+ struct pppox_sock *po = pppox_sk(sk);
+ struct pptp_opt *opt = &po->proto.pptp;
+ struct rtable *rt;
+ int error = 0;
+
+ if (sp->sa_protocol != PX_PROTO_PPTP)
+ return -EINVAL;
+
+ if (lookup_chan_dst(sp->sa_addr.pptp.call_id, sp->sa_addr.pptp.sin_addr.s_addr))
+ return -EALREADY;
+
+ lock_sock(sk);
+ /* Check for already bound sockets */
+ if (sk->sk_state & PPPOX_CONNECTED) {
+ error = -EBUSY;
+ goto end;
+ }
+
+ /* Check for already disconnected sockets, on attempts to disconnect */
+ if (sk->sk_state & PPPOX_DEAD) {
+ error = -EALREADY;
+ goto end;
+ }
+
+ if (!opt->src_addr.sin_addr.s_addr || !sp->sa_addr.pptp.sin_addr.s_addr) {
+ error = -EINVAL;
+ goto end;
+ }
+
+ po->chan.private = sk;
+ po->chan.ops = &pptp_chan_ops;
+
+ {
+ struct flowi fl = {
+ .nl_u = {
+ .ip4_u = {
+ .daddr = opt->dst_addr.sin_addr.s_addr,
+ .saddr = opt->src_addr.sin_addr.s_addr,
+ .tos = RT_CONN_FLAGS(sk) } },
+ .proto = IPPROTO_GRE };
+ security_sk_classify_flow(sk, &fl);
+ if (ip_route_output_key(&init_net, &rt, &fl)) {
+ error = -EHOSTUNREACH;
+ goto end;
+ }
+ sk_setup_caps(sk, &rt->dst);
+ }
+ po->chan.mtu = dst_mtu(&rt->dst);
+ if (!po->chan.mtu)
+ po->chan.mtu = PPP_MTU;
+ ip_rt_put(rt);
+ po->chan.mtu -= PPTP_HEADER_OVERHEAD;
+
+ po->chan.hdrlen = 2 + sizeof(struct pptp_gre_header);
+ error = ppp_register_channel(&po->chan);
+ if (error) {
+ pr_err("PPTP: failed to register PPP channel (%d)\n", error);
+ goto end;
+ }
+
+ opt->dst_addr = sp->sa_addr.pptp;
+ sk->sk_state = PPPOX_CONNECTED;
+
+ end:
+ release_sock(sk);
+ return error;
+}
+
+static int pptp_getname(struct socket *sock, struct sockaddr *uaddr,
+ int *usockaddr_len, int peer)
+{
+ int len = sizeof(struct sockaddr_pppox);
+ struct sockaddr_pppox sp;
+
+ sp.sa_family = AF_PPPOX;
+ sp.sa_protocol = PX_PROTO_PPTP;
+ sp.sa_addr.pptp = pppox_sk(sock->sk)->proto.pptp.src_addr;
+
+ memcpy(uaddr, &sp, len);
+
+ *usockaddr_len = len;
+
+ return 0;
+}
+
+static int pptp_release(struct socket *sock)
+{
+ struct sock *sk = sock->sk;
+ struct pppox_sock *po;
+ struct pptp_opt *opt;
+ int error = 0;
+
+ if (!sk)
+ return 0;
+
+ lock_sock(sk);
+
+ if (sock_flag(sk, SOCK_DEAD)) {
+ release_sock(sk);
+ return -EBADF;
+ }
+
+ po = pppox_sk(sk);
+ opt = &po->proto.pptp;
+ del_chan(po);
+
+ pppox_unbind_sock(sk);
+ sk->sk_state = PPPOX_DEAD;
+
+ sock_orphan(sk);
+ sock->sk = NULL;
+
+ release_sock(sk);
+ sock_put(sk);
+
+ return error;
+}
+
+static void pptp_sock_destruct(struct sock *sk)
+{
+ if (!(sk->sk_state & PPPOX_DEAD)) {
+ del_chan(pppox_sk(sk));
+ pppox_unbind_sock(sk);
+ }
+ skb_queue_purge(&sk->sk_receive_queue);
+}
+
+static int pptp_create(struct net *net, struct socket *sock)
+{
+ int error = -ENOMEM;
+ struct sock *sk;
+ struct pppox_sock *po;
+ struct pptp_opt *opt;
+
+ sk = sk_alloc(net, PF_PPPOX, GFP_KERNEL, &pptp_sk_proto);
+ if (!sk)
+ goto out;
+
+ sock_init_data(sock, sk);
+
+ sock->state = SS_UNCONNECTED;
+ sock->ops = &pptp_ops;
+
+ sk->sk_backlog_rcv = pptp_rcv_core;
+ sk->sk_state = PPPOX_NONE;
+ sk->sk_type = SOCK_STREAM;
+ sk->sk_family = PF_PPPOX;
+ sk->sk_protocol = PX_PROTO_PPTP;
+ sk->sk_destruct = pptp_sock_destruct;
+
+ po = pppox_sk(sk);
+ opt = &po->proto.pptp;
+
+ opt->seq_sent = 0; opt->seq_recv = 0;
+ opt->ack_recv = 0; opt->ack_sent = 0;
+
+ error = 0;
+out:
+ return error;
+}
+
+static int pptp_ppp_ioctl(struct ppp_channel *chan, unsigned int cmd,
+ unsigned long arg)
+{
+ struct sock *sk = (struct sock *) chan->private;
+ struct pppox_sock *po = pppox_sk(sk);
+ struct pptp_opt *opt = &po->proto.pptp;
+ void __user *argp = (void __user *)arg;
+ int __user *p = argp;
+ int err, val;
+
+ err = -EFAULT;
+ switch (cmd) {
+ case PPPIOCGFLAGS:
+ val = opt->ppp_flags;
+ if (put_user(val, p))
+ break;
+ err = 0;
+ break;
+ case PPPIOCSFLAGS:
+ if (get_user(val, p))
+ break;
+ opt->ppp_flags = val & ~SC_RCV_BITS;
+ err = 0;
+ break;
+ default:
+ err = -ENOTTY;
+ }
+
+ return err;
+}
+
+static const struct ppp_channel_ops pptp_chan_ops = {
+ .start_xmit = pptp_xmit,
+ .ioctl = pptp_ppp_ioctl,
+};
+
+static struct proto pptp_sk_proto __read_mostly = {
+ .name = "PPTP",
+ .owner = THIS_MODULE,
+ .obj_size = sizeof(struct pppox_sock),
+};
+
+static const struct proto_ops pptp_ops = {
+ .family = AF_PPPOX,
+ .owner = THIS_MODULE,
+ .release = pptp_release,
+ .bind = pptp_bind,
+ .connect = pptp_connect,
+ .socketpair = sock_no_socketpair,
+ .accept = sock_no_accept,
+ .getname = pptp_getname,
+ .poll = sock_no_poll,
+ .listen = sock_no_listen,
+ .shutdown = sock_no_shutdown,
+ .setsockopt = sock_no_setsockopt,
+ .getsockopt = sock_no_getsockopt,
+ .sendmsg = sock_no_sendmsg,
+ .recvmsg = sock_no_recvmsg,
+ .mmap = sock_no_mmap,
+ .ioctl = pppox_ioctl,
+};
+
+static const struct pppox_proto pppox_pptp_proto = {
+ .create = pptp_create,
+ .owner = THIS_MODULE,
+};
+
+static const struct gre_protocol gre_pptp_protocol = {
+ .handler = pptp_rcv,
+};
+
+static int __init pptp_init_module(void)
+{
+ int err = 0;
+ pr_info("PPTP driver version " PPTP_DRIVER_VERSION "\n");
+
+ callid_sock = __vmalloc((MAX_CALLID + 1) * sizeof(void *),
+ GFP_KERNEL | __GFP_ZERO, PAGE_KERNEL);
+ if (!callid_sock) {
+ pr_err("PPTP: cann't allocate memory\n");
+ return -ENOMEM;
+ }
+
+ err = gre_add_protocol(&gre_pptp_protocol, GREPROTO_PPTP);
+ if (err) {
+ pr_err("PPTP: can't add gre protocol\n");
+ goto out_mem_free;
+ }
+
+ err = proto_register(&pptp_sk_proto, 0);
+ if (err) {
+ pr_err("PPTP: can't register sk_proto\n");
+ goto out_gre_del_protocol;
+ }
+
+ err = register_pppox_proto(PX_PROTO_PPTP, &pppox_pptp_proto);
+ if (err) {
+ pr_err("PPTP: can't register pppox_proto\n");
+ goto out_unregister_sk_proto;
+ }
+
+ return 0;
+
+out_unregister_sk_proto:
+ proto_unregister(&pptp_sk_proto);
+out_gre_del_protocol:
+ gre_del_protocol(&gre_pptp_protocol, GREPROTO_PPTP);
+out_mem_free:
+ vfree(callid_sock);
+
+ return err;
+}
+
+static void __exit pptp_exit_module(void)
+{
+ unregister_pppox_proto(PX_PROTO_PPTP);
+ proto_unregister(&pptp_sk_proto);
+ gre_del_protocol(&gre_pptp_protocol, GREPROTO_PPTP);
+ vfree(callid_sock);
+}
+
+module_init(pptp_init_module);
+module_exit(pptp_exit_module);
+
+MODULE_DESCRIPTION("Point-to-Point Tunneling Protocol");
+MODULE_AUTHOR("D. Kozlov (xeb@mail.ru)");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/ps3_gelic_net.c b/drivers/net/ps3_gelic_net.c
index 87d6b8f36304..5526ab4895e6 100644
--- a/drivers/net/ps3_gelic_net.c
+++ b/drivers/net/ps3_gelic_net.c
@@ -956,9 +956,9 @@ static void gelic_net_pass_skb_up(struct gelic_descr *descr,
(!(data_error & GELIC_DESCR_DATA_ERROR_CHK_MASK)))
skb->ip_summed = CHECKSUM_UNNECESSARY;
else
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
} else
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
/* update netdevice statistics */
netdev->stats.rx_packets++;
diff --git a/drivers/net/ps3_gelic_wireless.c b/drivers/net/ps3_gelic_wireless.c
index 43b8d7797f0a..4a624a29393f 100644
--- a/drivers/net/ps3_gelic_wireless.c
+++ b/drivers/net/ps3_gelic_wireless.c
@@ -85,12 +85,12 @@ static const int bitrate_list[] = {
*/
static inline int wpa2_capable(void)
{
- return (0 <= ps3_compare_firmware_version(2, 0, 0));
+ return 0 <= ps3_compare_firmware_version(2, 0, 0);
}
static inline int precise_ie(void)
{
- return (0 <= ps3_compare_firmware_version(2, 2, 0));
+ return 0 <= ps3_compare_firmware_version(2, 2, 0);
}
/*
* post_eurus_cmd helpers
@@ -506,7 +506,7 @@ static size_t gelic_wl_synthesize_ie(u8 *buf,
start[1] = (buf - start - 2);
pr_debug("%s: ->\n", __func__);
- return (buf - start);
+ return buf - start;
}
struct ie_item {
diff --git a/drivers/net/pxa168_eth.c b/drivers/net/pxa168_eth.c
index 85eddda276bd..18c0297743f1 100644
--- a/drivers/net/pxa168_eth.c
+++ b/drivers/net/pxa168_eth.c
@@ -4,6 +4,7 @@
*
* Copyright (C) 2010 Marvell International Ltd.
* Sachin Sanap <ssanap@marvell.com>
+ * Zhangfei Gao <zgao6@marvell.com>
* Philip Rakity <prakity@marvell.com>
* Mark Brown <markb@marvell.com>
*
@@ -42,8 +43,6 @@
#include <linux/types.h>
#include <asm/pgtable.h>
#include <asm/system.h>
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
#include <asm/cacheflush.h>
#include <linux/pxa168_eth.h>
@@ -850,7 +849,6 @@ static int rxq_process(struct net_device *dev, int budget)
skb->protocol = eth_type_trans(skb, dev);
netif_receive_skb(skb);
}
- dev->last_rx = jiffies;
}
/* Fill RX ring with skb's */
rxq_refill(dev);
diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c
index 6168a130f33f..7496ed2c34ab 100644
--- a/drivers/net/qla3xxx.c
+++ b/drivers/net/qla3xxx.c
@@ -2029,7 +2029,7 @@ static void ql_process_mac_rx_intr(struct ql3_adapter *qdev,
dma_unmap_len(lrg_buf_cb2, maplen),
PCI_DMA_FROMDEVICE);
prefetch(skb->data);
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
skb->protocol = eth_type_trans(skb, qdev->ndev);
netif_receive_skb(skb);
@@ -2076,7 +2076,7 @@ static void ql_process_macip_rx_intr(struct ql3_adapter *qdev,
PCI_DMA_FROMDEVICE);
prefetch(skb2->data);
- skb2->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb2);
if (qdev->device_id == QL3022_DEVICE_ID) {
/*
* Copy the ethhdr from first buffer to second. This
diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index 970389331bbc..26c37d3a5868 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -51,9 +51,11 @@
#define _QLCNIC_LINUX_MAJOR 5
#define _QLCNIC_LINUX_MINOR 0
-#define _QLCNIC_LINUX_SUBVERSION 7
-#define QLCNIC_LINUX_VERSIONID "5.0.7"
+#define _QLCNIC_LINUX_SUBVERSION 11
+#define QLCNIC_LINUX_VERSIONID "5.0.11"
#define QLCNIC_DRV_IDC_VER 0x01
+#define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\
+ (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION))
#define QLCNIC_VERSION_CODE(a, b, c) (((a) << 24) + ((b) << 16) + (c))
#define _major(v) (((v) >> 24) & 0xff)
@@ -92,11 +94,12 @@
#define FIRST_PAGE_GROUP_START 0
#define FIRST_PAGE_GROUP_END 0x100000
-#define P3_MAX_MTU (9600)
+#define P3P_MAX_MTU (9600)
+#define P3P_MIN_MTU (68)
#define QLCNIC_MAX_ETHERHDR 32 /* This contains some padding */
-#define QLCNIC_P3_RX_BUF_MAX_LEN (QLCNIC_MAX_ETHERHDR + ETH_DATA_LEN)
-#define QLCNIC_P3_RX_JUMBO_BUF_MAX_LEN (QLCNIC_MAX_ETHERHDR + P3_MAX_MTU)
+#define QLCNIC_P3P_RX_BUF_MAX_LEN (QLCNIC_MAX_ETHERHDR + ETH_DATA_LEN)
+#define QLCNIC_P3P_RX_JUMBO_BUF_MAX_LEN (QLCNIC_MAX_ETHERHDR + P3P_MAX_MTU)
#define QLCNIC_CT_DEFAULT_RX_BUF_LEN 2048
#define QLCNIC_LRO_BUFFER_EXTRA 2048
@@ -148,6 +151,7 @@
#define DEFAULT_RCV_DESCRIPTORS_1G 2048
#define DEFAULT_RCV_DESCRIPTORS_10G 4096
+#define MAX_RDS_RINGS 2
#define get_next_index(index, length) \
(((index) + 1) & ((length) - 1))
@@ -172,7 +176,7 @@
((_desc)->port_ctxid = ((_port) & 0xf) | (((_port) << 4) & 0xf0))
#define qlcnic_set_tx_flags_opcode(_desc, _flags, _opcode) \
- ((_desc)->flags_opcode = \
+ ((_desc)->flags_opcode |= \
cpu_to_le16(((_flags) & 0x7f) | (((_opcode) & 0x3f) << 7)))
#define qlcnic_set_tx_frags_len(_desc, _frags, _len) \
@@ -221,7 +225,8 @@ struct rcv_desc {
#define QLCNIC_LRO_DESC 0x12
/* for status field in status_desc */
-#define STATUS_CKSUM_OK (2)
+#define STATUS_CKSUM_LOOP 0
+#define STATUS_CKSUM_OK 2
/* owner bits of status_desc */
#define STATUS_OWNER_HOST (0x1ULL << 56)
@@ -302,20 +307,20 @@ struct uni_data_desc{
/* Magic number to let user know flash is programmed */
#define QLCNIC_BDINFO_MAGIC 0x12345678
-#define QLCNIC_BRDTYPE_P3_REF_QG 0x0021
-#define QLCNIC_BRDTYPE_P3_HMEZ 0x0022
-#define QLCNIC_BRDTYPE_P3_10G_CX4_LP 0x0023
-#define QLCNIC_BRDTYPE_P3_4_GB 0x0024
-#define QLCNIC_BRDTYPE_P3_IMEZ 0x0025
-#define QLCNIC_BRDTYPE_P3_10G_SFP_PLUS 0x0026
-#define QLCNIC_BRDTYPE_P3_10000_BASE_T 0x0027
-#define QLCNIC_BRDTYPE_P3_XG_LOM 0x0028
-#define QLCNIC_BRDTYPE_P3_4_GB_MM 0x0029
-#define QLCNIC_BRDTYPE_P3_10G_SFP_CT 0x002a
-#define QLCNIC_BRDTYPE_P3_10G_SFP_QT 0x002b
-#define QLCNIC_BRDTYPE_P3_10G_CX4 0x0031
-#define QLCNIC_BRDTYPE_P3_10G_XFP 0x0032
-#define QLCNIC_BRDTYPE_P3_10G_TP 0x0080
+#define QLCNIC_BRDTYPE_P3P_REF_QG 0x0021
+#define QLCNIC_BRDTYPE_P3P_HMEZ 0x0022
+#define QLCNIC_BRDTYPE_P3P_10G_CX4_LP 0x0023
+#define QLCNIC_BRDTYPE_P3P_4_GB 0x0024
+#define QLCNIC_BRDTYPE_P3P_IMEZ 0x0025
+#define QLCNIC_BRDTYPE_P3P_10G_SFP_PLUS 0x0026
+#define QLCNIC_BRDTYPE_P3P_10000_BASE_T 0x0027
+#define QLCNIC_BRDTYPE_P3P_XG_LOM 0x0028
+#define QLCNIC_BRDTYPE_P3P_4_GB_MM 0x0029
+#define QLCNIC_BRDTYPE_P3P_10G_SFP_CT 0x002a
+#define QLCNIC_BRDTYPE_P3P_10G_SFP_QT 0x002b
+#define QLCNIC_BRDTYPE_P3P_10G_CX4 0x0031
+#define QLCNIC_BRDTYPE_P3P_10G_XFP 0x0032
+#define QLCNIC_BRDTYPE_P3P_10G_TP 0x0080
#define QLCNIC_MSIX_TABLE_OFFSET 0x44
@@ -555,6 +560,8 @@ struct qlcnic_recv_context {
#define QLCNIC_CDRP_CMD_GET_ESWITCH_STATUS 0x00000026
#define QLCNIC_CDRP_CMD_SET_PORTMIRRORING 0x00000027
#define QLCNIC_CDRP_CMD_CONFIGURE_ESWITCH 0x00000028
+#define QLCNIC_CDRP_CMD_GET_ESWITCH_PORT_CONFIG 0x00000029
+#define QLCNIC_CDRP_CMD_GET_ESWITCH_STATS 0x0000002a
#define QLCNIC_RCODE_SUCCESS 0
#define QLCNIC_RCODE_TIMEOUT 17
@@ -712,11 +719,13 @@ struct qlcnic_cardrsp_tx_ctx {
/* MAC */
-#define MC_COUNT_P3 38
+#define MC_COUNT_P3P 38
#define QLCNIC_MAC_NOOP 0
#define QLCNIC_MAC_ADD 1
#define QLCNIC_MAC_DEL 2
+#define QLCNIC_MAC_VLAN_ADD 3
+#define QLCNIC_MAC_VLAN_DEL 4
struct qlcnic_mac_list_s {
struct list_head list;
@@ -890,12 +899,28 @@ struct qlcnic_mac_req {
u8 mac_addr[6];
};
+struct qlcnic_vlan_req {
+ __le16 vlan_id;
+ __le16 rsvd[3];
+};
+
+struct qlcnic_ipaddr {
+ __be32 ipv4;
+ __be32 ipv6[4];
+};
+
#define QLCNIC_MSI_ENABLED 0x02
#define QLCNIC_MSIX_ENABLED 0x04
#define QLCNIC_LRO_ENABLED 0x08
+#define QLCNIC_LRO_DISABLED 0x00
#define QLCNIC_BRIDGE_ENABLED 0X10
#define QLCNIC_DIAG_ENABLED 0x20
#define QLCNIC_ESWITCH_ENABLED 0x40
+#define QLCNIC_ADAPTER_INITIALIZED 0x80
+#define QLCNIC_TAGGING_ENABLED 0x100
+#define QLCNIC_MACSPOOF 0x200
+#define QLCNIC_MAC_OVERRIDE_DISABLED 0x400
+#define QLCNIC_PROMISC_DISABLED 0x800
#define QLCNIC_IS_MSI_FAMILY(adapter) \
((adapter)->flags & (QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED))
@@ -916,6 +941,22 @@ struct qlcnic_mac_req {
#define QLCNIC_INTERRUPT_TEST 1
#define QLCNIC_LOOPBACK_TEST 2
+#define QLCNIC_FILTER_AGE 80
+#define QLCNIC_LB_MAX_FILTERS 64
+
+struct qlcnic_filter {
+ struct hlist_node fnode;
+ u8 faddr[ETH_ALEN];
+ __le16 vlan_id;
+ unsigned long ftime;
+};
+
+struct qlcnic_filter_hash {
+ struct hlist_head *fhead;
+ u8 fnum;
+ u8 fmax;
+};
+
struct qlcnic_adapter {
struct qlcnic_hardware_context ahw;
@@ -924,6 +965,7 @@ struct qlcnic_adapter {
struct list_head mac_list;
spinlock_t tx_clean_lock;
+ spinlock_t mac_learn_lock;
u16 num_txd;
u16 num_rxd;
@@ -931,7 +973,6 @@ struct qlcnic_adapter {
u8 max_rds_rings;
u8 max_sds_rings;
- u8 driver_mismatch;
u8 msix_supported;
u8 rx_csum;
u8 portnum;
@@ -961,6 +1002,7 @@ struct qlcnic_adapter {
u16 max_tx_ques;
u16 max_rx_ques;
u16 max_mtu;
+ u16 pvid;
u32 fw_hal_version;
u32 capabilities;
@@ -969,7 +1011,7 @@ struct qlcnic_adapter {
u32 temp;
u32 int_vec_bit;
- u32 heartbit;
+ u32 heartbeat;
u8 max_mac_filters;
u8 dev_state;
@@ -983,6 +1025,7 @@ struct qlcnic_adapter {
u64 dev_rst_time;
+ struct vlan_group *vlgrp;
struct qlcnic_npar_info *npars;
struct qlcnic_eswitch *eswitch;
struct qlcnic_nic_template *nic_ops;
@@ -1003,6 +1046,8 @@ struct qlcnic_adapter {
struct qlcnic_nic_intr_coalesce coal;
+ struct qlcnic_filter_hash fhash;
+
unsigned long state;
__le32 file_prd_off; /*File fw product offset*/
u32 fw_version;
@@ -1042,7 +1087,7 @@ struct qlcnic_pci_info {
};
struct qlcnic_npar_info {
- u16 vlan_id;
+ u16 pvid;
u16 min_bw;
u16 max_bw;
u8 phy_port;
@@ -1050,11 +1095,13 @@ struct qlcnic_npar_info {
u8 active;
u8 enable_pm;
u8 dest_npar;
- u8 host_vlan_tag;
- u8 promisc_mode;
u8 discard_tagged;
- u8 mac_learning;
+ u8 mac_override;
+ u8 mac_anti_spoof;
+ u8 promisc_mode;
+ u8 offload_flags;
};
+
struct qlcnic_eswitch {
u8 port;
u8 active_vports;
@@ -1086,7 +1133,6 @@ struct qlcnic_eswitch {
#define IS_VALID_BW(bw) (bw >= MIN_BW && bw <= MAX_BW)
#define IS_VALID_TX_QUEUES(que) (que > 0 && que <= MAX_TX_QUEUES)
#define IS_VALID_RX_QUEUES(que) (que > 0 && que <= MAX_RX_QUEUES)
-#define IS_VALID_MODE(mode) (mode == 0 || mode == 1)
struct qlcnic_pci_func_cfg {
u16 func_type;
@@ -1118,12 +1164,53 @@ struct qlcnic_pm_func_cfg {
struct qlcnic_esw_func_cfg {
u16 vlan_id;
+ u8 op_mode;
+ u8 op_type;
u8 pci_func;
u8 host_vlan_tag;
u8 promisc_mode;
u8 discard_tagged;
- u8 mac_learning;
- u8 reserved;
+ u8 mac_override;
+ u8 mac_anti_spoof;
+ u8 offload_flags;
+ u8 reserved[5];
+};
+
+#define QLCNIC_STATS_VERSION 1
+#define QLCNIC_STATS_PORT 1
+#define QLCNIC_STATS_ESWITCH 2
+#define QLCNIC_QUERY_RX_COUNTER 0
+#define QLCNIC_QUERY_TX_COUNTER 1
+#define QLCNIC_ESW_STATS_NOT_AVAIL 0xffffffffffffffffULL
+
+#define QLCNIC_ADD_ESW_STATS(VAL1, VAL2)\
+do { \
+ if (((VAL1) == QLCNIC_ESW_STATS_NOT_AVAIL) && \
+ ((VAL2) != QLCNIC_ESW_STATS_NOT_AVAIL)) \
+ (VAL1) = (VAL2); \
+ else if (((VAL1) != QLCNIC_ESW_STATS_NOT_AVAIL) && \
+ ((VAL2) != QLCNIC_ESW_STATS_NOT_AVAIL)) \
+ (VAL1) += (VAL2); \
+} while (0)
+
+struct __qlcnic_esw_statistics {
+ __le16 context_id;
+ __le16 version;
+ __le16 size;
+ __le16 unused;
+ __le64 unicast_frames;
+ __le64 multicast_frames;
+ __le64 broadcast_frames;
+ __le64 dropped_frames;
+ __le64 errors;
+ __le64 local_frames;
+ __le64 numbytes;
+ __le64 rsvd[3];
+};
+
+struct qlcnic_esw_statistics {
+ struct __qlcnic_esw_statistics rx;
+ struct __qlcnic_esw_statistics tx;
};
int qlcnic_fw_cmd_query_phy(struct qlcnic_adapter *adapter, u32 reg, u32 *val);
@@ -1171,6 +1258,8 @@ void qlcnic_pcie_sem_unlock(struct qlcnic_adapter *, int);
int qlcnic_get_board_info(struct qlcnic_adapter *adapter);
int qlcnic_wol_supported(struct qlcnic_adapter *adapter);
int qlcnic_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate);
+void qlcnic_prune_lb_filters(struct qlcnic_adapter *adapter);
+void qlcnic_delete_lb_filters(struct qlcnic_adapter *adapter);
/* Functions from qlcnic_init.c */
int qlcnic_load_firmware(struct qlcnic_adapter *adapter);
@@ -1199,7 +1288,7 @@ void qlcnic_reset_rx_buffers_list(struct qlcnic_adapter *adapter);
void qlcnic_release_rx_buffers(struct qlcnic_adapter *adapter);
void qlcnic_release_tx_buffers(struct qlcnic_adapter *adapter);
-int qlcnic_init_firmware(struct qlcnic_adapter *adapter);
+int qlcnic_check_fw_status(struct qlcnic_adapter *adapter);
void qlcnic_watchdog_task(struct work_struct *work);
void qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter, u32 ringid,
struct qlcnic_host_rds_ring *rds_ring);
@@ -1209,7 +1298,7 @@ void qlcnic_free_mac_list(struct qlcnic_adapter *adapter);
int qlcnic_nic_set_promisc(struct qlcnic_adapter *adapter, u32);
int qlcnic_config_intr_coalesce(struct qlcnic_adapter *adapter);
int qlcnic_config_rss(struct qlcnic_adapter *adapter, int enable);
-int qlcnic_config_ipaddr(struct qlcnic_adapter *adapter, u32 ip, int cmd);
+int qlcnic_config_ipaddr(struct qlcnic_adapter *adapter, __be32 ip, int cmd);
int qlcnic_linkevent_request(struct qlcnic_adapter *adapter, int enable);
void qlcnic_advert_link_change(struct qlcnic_adapter *adapter, int linkup);
@@ -1220,12 +1309,13 @@ int qlcnic_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable);
int qlcnic_send_lro_cleanup(struct qlcnic_adapter *adapter);
void qlcnic_update_cmd_producer(struct qlcnic_adapter *adapter,
struct qlcnic_host_tx_ring *tx_ring);
-int qlcnic_get_mac_addr(struct qlcnic_adapter *adapter, u8 *mac);
void qlcnic_clear_ilb_mode(struct qlcnic_adapter *adapter);
int qlcnic_set_ilb_mode(struct qlcnic_adapter *adapter);
void qlcnic_fetch_mac(struct qlcnic_adapter *, u32, u32, u8, u8 *);
/* Functions from qlcnic_main.c */
+int qlcnic_request_quiscent_mode(struct qlcnic_adapter *adapter);
+void qlcnic_clear_quiscent_mode(struct qlcnic_adapter *adapter);
int qlcnic_reset_context(struct qlcnic_adapter *);
u32 qlcnic_issue_cmd(struct qlcnic_adapter *adapter,
u32 pci_fn, u32 version, u32 arg1, u32 arg2, u32 arg3, u32 cmd);
@@ -1236,22 +1326,22 @@ netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
void qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring);
/* Management functions */
-int qlcnic_set_mac_address(struct qlcnic_adapter *, u8*);
int qlcnic_get_mac_address(struct qlcnic_adapter *, u8*);
int qlcnic_get_nic_info(struct qlcnic_adapter *, struct qlcnic_info *, u8);
int qlcnic_set_nic_info(struct qlcnic_adapter *, struct qlcnic_info *);
int qlcnic_get_pci_info(struct qlcnic_adapter *, struct qlcnic_pci_info*);
-int qlcnic_reset_partition(struct qlcnic_adapter *, u8);
/* eSwitch management functions */
-int qlcnic_get_eswitch_capabilities(struct qlcnic_adapter *, u8,
- struct qlcnic_eswitch *);
-int qlcnic_get_eswitch_status(struct qlcnic_adapter *, u8,
- struct qlcnic_eswitch *);
-int qlcnic_toggle_eswitch(struct qlcnic_adapter *, u8, u8);
-int qlcnic_config_switch_port(struct qlcnic_adapter *, u8, int, u8, u8,
- u8, u8, u16);
+int qlcnic_config_switch_port(struct qlcnic_adapter *,
+ struct qlcnic_esw_func_cfg *);
+int qlcnic_get_eswitch_port_config(struct qlcnic_adapter *,
+ struct qlcnic_esw_func_cfg *);
int qlcnic_config_port_mirroring(struct qlcnic_adapter *, u8, u8, u8);
+int qlcnic_get_port_stats(struct qlcnic_adapter *, const u8, const u8,
+ struct __qlcnic_esw_statistics *);
+int qlcnic_get_eswitch_stats(struct qlcnic_adapter *, const u8, u8,
+ struct __qlcnic_esw_statistics *);
+int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, u8, u8, u8);
extern int qlcnic_config_tso;
/*
@@ -1280,6 +1370,8 @@ static const struct qlcnic_brdinfo qlcnic_boards[] = {
"3200 Series Quad Port 1Gb Intelligent Ethernet Adapter"},
{0x1077, 0x8020, 0x1077, 0x20f,
"3200 Series Single Port 10Gb Intelligent Ethernet Adapter"},
+ {0x1077, 0x8020, 0x103c, 0x3733,
+ "NC523SFP 10Gb 2-port Server Adapter"},
{0x1077, 0x8020, 0x0, 0x0, "cLOM8214 1/10GbE Controller"},
};
@@ -1298,7 +1390,6 @@ static inline u32 qlcnic_tx_avail(struct qlcnic_host_tx_ring *tx_ring)
extern const struct ethtool_ops qlcnic_ethtool_ops;
struct qlcnic_nic_template {
- int (*get_mac_addr) (struct qlcnic_adapter *, u8*);
int (*config_bridged_mode) (struct qlcnic_adapter *, u32);
int (*config_led) (struct qlcnic_adapter *, u32, u32);
int (*start_firmware) (struct qlcnic_adapter *);
diff --git a/drivers/net/qlcnic/qlcnic_ctx.c b/drivers/net/qlcnic/qlcnic_ctx.c
index cc5d861d9a12..1cdc05dade6b 100644
--- a/drivers/net/qlcnic/qlcnic_ctx.c
+++ b/drivers/net/qlcnic/qlcnic_ctx.c
@@ -556,32 +556,6 @@ void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter)
}
}
-/* Set MAC address of a NIC partition */
-int qlcnic_set_mac_address(struct qlcnic_adapter *adapter, u8* mac)
-{
- int err = 0;
- u32 arg1, arg2, arg3;
-
- arg1 = adapter->ahw.pci_func | BIT_9;
- arg2 = mac[0] | (mac[1] << 8) | (mac[2] << 16) | (mac[3] << 24);
- arg3 = mac[4] | (mac[5] << 16);
-
- err = qlcnic_issue_cmd(adapter,
- adapter->ahw.pci_func,
- adapter->fw_hal_version,
- arg1,
- arg2,
- arg3,
- QLCNIC_CDRP_CMD_MAC_ADDRESS);
-
- if (err != QLCNIC_RCODE_SUCCESS) {
- dev_err(&adapter->pdev->dev,
- "Failed to set mac address%d\n", err);
- err = -EIO;
- }
-
- return err;
-}
/* Get MAC address of a NIC partition */
int qlcnic_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac)
@@ -742,15 +716,15 @@ int qlcnic_get_pci_info(struct qlcnic_adapter *adapter,
if (err == QLCNIC_RCODE_SUCCESS) {
for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++, npar++, pci_info++) {
- pci_info->id = le32_to_cpu(npar->id);
- pci_info->active = le32_to_cpu(npar->active);
- pci_info->type = le32_to_cpu(npar->type);
+ pci_info->id = le16_to_cpu(npar->id);
+ pci_info->active = le16_to_cpu(npar->active);
+ pci_info->type = le16_to_cpu(npar->type);
pci_info->default_port =
- le32_to_cpu(npar->default_port);
+ le16_to_cpu(npar->default_port);
pci_info->tx_min_bw =
- le32_to_cpu(npar->tx_min_bw);
+ le16_to_cpu(npar->tx_min_bw);
pci_info->tx_max_bw =
- le32_to_cpu(npar->tx_max_bw);
+ le16_to_cpu(npar->tx_max_bw);
memcpy(pci_info->mac, npar->mac, ETH_ALEN);
}
} else {
@@ -764,222 +738,319 @@ int qlcnic_get_pci_info(struct qlcnic_adapter *adapter,
return err;
}
-/* Reset a NIC partition */
-
-int qlcnic_reset_partition(struct qlcnic_adapter *adapter, u8 func_no)
+/* Configure eSwitch for port mirroring */
+int qlcnic_config_port_mirroring(struct qlcnic_adapter *adapter, u8 id,
+ u8 enable_mirroring, u8 pci_func)
{
int err = -EIO;
+ u32 arg1;
- if (adapter->op_mode != QLCNIC_MGMT_FUNC)
+ if (adapter->op_mode != QLCNIC_MGMT_FUNC ||
+ !(adapter->eswitch[id].flags & QLCNIC_SWITCH_ENABLE))
return err;
+ arg1 = id | (enable_mirroring ? BIT_4 : 0);
+ arg1 |= pci_func << 8;
+
err = qlcnic_issue_cmd(adapter,
adapter->ahw.pci_func,
adapter->fw_hal_version,
- func_no,
+ arg1,
0,
0,
- QLCNIC_CDRP_CMD_RESET_NPAR);
+ QLCNIC_CDRP_CMD_SET_PORTMIRRORING);
if (err != QLCNIC_RCODE_SUCCESS) {
dev_err(&adapter->pdev->dev,
- "Failed to issue reset partition%d\n", err);
- err = -EIO;
+ "Failed to configure port mirroring%d on eswitch:%d\n",
+ pci_func, id);
+ } else {
+ dev_info(&adapter->pdev->dev,
+ "Configured eSwitch %d for port mirroring:%d\n",
+ id, pci_func);
}
return err;
}
-/* Get eSwitch Capabilities */
-int qlcnic_get_eswitch_capabilities(struct qlcnic_adapter *adapter, u8 port,
- struct qlcnic_eswitch *eswitch)
-{
- int err = -EIO;
- u32 arg1, arg2;
+int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func,
+ const u8 rx_tx, struct __qlcnic_esw_statistics *esw_stats) {
- if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC)
- return err;
+ size_t stats_size = sizeof(struct __qlcnic_esw_statistics);
+ struct __qlcnic_esw_statistics *stats;
+ dma_addr_t stats_dma_t;
+ void *stats_addr;
+ u32 arg1;
+ int err;
- err = qlcnic_issue_cmd(adapter,
- adapter->ahw.pci_func,
- adapter->fw_hal_version,
- port,
- 0,
- 0,
- QLCNIC_CDRP_CMD_GET_ESWITCH_CAPABILITY);
+ if (esw_stats == NULL)
+ return -ENOMEM;
- if (err == QLCNIC_RCODE_SUCCESS) {
- arg1 = QLCRD32(adapter, QLCNIC_ARG1_CRB_OFFSET);
- arg2 = QLCRD32(adapter, QLCNIC_ARG2_CRB_OFFSET);
-
- eswitch->port = arg1 & 0xf;
- eswitch->active_vports = LSB(arg2);
- eswitch->max_ucast_filters = MSB(arg2);
- eswitch->max_active_vlans = LSB(MSW(arg2));
- if (arg1 & BIT_6)
- eswitch->flags |= QLCNIC_SWITCH_VLAN_FILTERING;
- if (arg1 & BIT_7)
- eswitch->flags |= QLCNIC_SWITCH_PROMISC_MODE;
- if (arg1 & BIT_8)
- eswitch->flags |= QLCNIC_SWITCH_PORT_MIRRORING;
- } else {
+ if (adapter->op_mode != QLCNIC_MGMT_FUNC &&
+ func != adapter->ahw.pci_func) {
dev_err(&adapter->pdev->dev,
- "Failed to get eswitch capabilities%d\n", err);
+ "Not privilege to query stats for func=%d", func);
+ return -EIO;
}
- return err;
-}
-
-/* Get current status of eswitch */
-int qlcnic_get_eswitch_status(struct qlcnic_adapter *adapter, u8 port,
- struct qlcnic_eswitch *eswitch)
-{
- int err = -EIO;
- u32 arg1, arg2;
+ stats_addr = pci_alloc_consistent(adapter->pdev, stats_size,
+ &stats_dma_t);
+ if (!stats_addr) {
+ dev_err(&adapter->pdev->dev, "Unable to allocate memory\n");
+ return -ENOMEM;
+ }
+ memset(stats_addr, 0, stats_size);
- if (adapter->op_mode != QLCNIC_MGMT_FUNC)
- return err;
+ arg1 = func | QLCNIC_STATS_VERSION << 8 | QLCNIC_STATS_PORT << 12;
+ arg1 |= rx_tx << 15 | stats_size << 16;
err = qlcnic_issue_cmd(adapter,
adapter->ahw.pci_func,
adapter->fw_hal_version,
- port,
- 0,
- 0,
- QLCNIC_CDRP_CMD_GET_ESWITCH_STATUS);
-
- if (err == QLCNIC_RCODE_SUCCESS) {
- arg1 = QLCRD32(adapter, QLCNIC_ARG1_CRB_OFFSET);
- arg2 = QLCRD32(adapter, QLCNIC_ARG2_CRB_OFFSET);
-
- eswitch->port = arg1 & 0xf;
- eswitch->active_vports = LSB(arg2);
- eswitch->active_ucast_filters = MSB(arg2);
- eswitch->active_vlans = LSB(MSW(arg2));
- if (arg1 & BIT_6)
- eswitch->flags |= QLCNIC_SWITCH_VLAN_FILTERING;
- if (arg1 & BIT_8)
- eswitch->flags |= QLCNIC_SWITCH_PORT_MIRRORING;
-
- } else {
- dev_err(&adapter->pdev->dev,
- "Failed to get eswitch status%d\n", err);
+ arg1,
+ MSD(stats_dma_t),
+ LSD(stats_dma_t),
+ QLCNIC_CDRP_CMD_GET_ESWITCH_STATS);
+
+ if (!err) {
+ stats = (struct __qlcnic_esw_statistics *)stats_addr;
+ esw_stats->context_id = le16_to_cpu(stats->context_id);
+ esw_stats->version = le16_to_cpu(stats->version);
+ esw_stats->size = le16_to_cpu(stats->size);
+ esw_stats->multicast_frames =
+ le64_to_cpu(stats->multicast_frames);
+ esw_stats->broadcast_frames =
+ le64_to_cpu(stats->broadcast_frames);
+ esw_stats->unicast_frames = le64_to_cpu(stats->unicast_frames);
+ esw_stats->dropped_frames = le64_to_cpu(stats->dropped_frames);
+ esw_stats->local_frames = le64_to_cpu(stats->local_frames);
+ esw_stats->errors = le64_to_cpu(stats->errors);
+ esw_stats->numbytes = le64_to_cpu(stats->numbytes);
}
+ pci_free_consistent(adapter->pdev, stats_size, stats_addr,
+ stats_dma_t);
return err;
}
-/* Enable/Disable eSwitch */
-int qlcnic_toggle_eswitch(struct qlcnic_adapter *adapter, u8 id, u8 enable)
+int qlcnic_get_eswitch_stats(struct qlcnic_adapter *adapter, const u8 eswitch,
+ const u8 rx_tx, struct __qlcnic_esw_statistics *esw_stats) {
+
+ struct __qlcnic_esw_statistics port_stats;
+ u8 i;
+ int ret = -EIO;
+
+ if (esw_stats == NULL)
+ return -ENOMEM;
+ if (adapter->op_mode != QLCNIC_MGMT_FUNC)
+ return -EIO;
+ if (adapter->npars == NULL)
+ return -EIO;
+
+ memset(esw_stats, 0, sizeof(u64));
+ esw_stats->unicast_frames = QLCNIC_ESW_STATS_NOT_AVAIL;
+ esw_stats->multicast_frames = QLCNIC_ESW_STATS_NOT_AVAIL;
+ esw_stats->broadcast_frames = QLCNIC_ESW_STATS_NOT_AVAIL;
+ esw_stats->dropped_frames = QLCNIC_ESW_STATS_NOT_AVAIL;
+ esw_stats->errors = QLCNIC_ESW_STATS_NOT_AVAIL;
+ esw_stats->local_frames = QLCNIC_ESW_STATS_NOT_AVAIL;
+ esw_stats->numbytes = QLCNIC_ESW_STATS_NOT_AVAIL;
+ esw_stats->context_id = eswitch;
+
+ for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
+ if (adapter->npars[i].phy_port != eswitch)
+ continue;
+
+ memset(&port_stats, 0, sizeof(struct __qlcnic_esw_statistics));
+ if (qlcnic_get_port_stats(adapter, i, rx_tx, &port_stats))
+ continue;
+
+ esw_stats->size = port_stats.size;
+ esw_stats->version = port_stats.version;
+ QLCNIC_ADD_ESW_STATS(esw_stats->unicast_frames,
+ port_stats.unicast_frames);
+ QLCNIC_ADD_ESW_STATS(esw_stats->multicast_frames,
+ port_stats.multicast_frames);
+ QLCNIC_ADD_ESW_STATS(esw_stats->broadcast_frames,
+ port_stats.broadcast_frames);
+ QLCNIC_ADD_ESW_STATS(esw_stats->dropped_frames,
+ port_stats.dropped_frames);
+ QLCNIC_ADD_ESW_STATS(esw_stats->errors,
+ port_stats.errors);
+ QLCNIC_ADD_ESW_STATS(esw_stats->local_frames,
+ port_stats.local_frames);
+ QLCNIC_ADD_ESW_STATS(esw_stats->numbytes,
+ port_stats.numbytes);
+ ret = 0;
+ }
+ return ret;
+}
+
+int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, const u8 func_esw,
+ const u8 port, const u8 rx_tx)
{
- int err = -EIO;
- u32 arg1, arg2;
- struct qlcnic_eswitch *eswitch;
+
+ u32 arg1;
if (adapter->op_mode != QLCNIC_MGMT_FUNC)
- return err;
+ return -EIO;
- eswitch = &adapter->eswitch[id];
- if (!eswitch)
- return err;
+ if (func_esw == QLCNIC_STATS_PORT) {
+ if (port >= QLCNIC_MAX_PCI_FUNC)
+ goto err_ret;
+ } else if (func_esw == QLCNIC_STATS_ESWITCH) {
+ if (port >= QLCNIC_NIU_MAX_XG_PORTS)
+ goto err_ret;
+ } else {
+ goto err_ret;
+ }
- arg1 = eswitch->port | (enable ? BIT_4 : 0);
- arg2 = eswitch->active_vports | (eswitch->max_ucast_filters << 8) |
- (eswitch->max_active_vlans << 16);
- err = qlcnic_issue_cmd(adapter,
+ if (rx_tx > QLCNIC_QUERY_TX_COUNTER)
+ goto err_ret;
+
+ arg1 = port | QLCNIC_STATS_VERSION << 8 | func_esw << 12;
+ arg1 |= BIT_14 | rx_tx << 15;
+
+ return qlcnic_issue_cmd(adapter,
adapter->ahw.pci_func,
adapter->fw_hal_version,
arg1,
- arg2,
0,
- QLCNIC_CDRP_CMD_TOGGLE_ESWITCH);
-
- if (err != QLCNIC_RCODE_SUCCESS) {
- dev_err(&adapter->pdev->dev,
- "Failed to enable eswitch%d\n", eswitch->port);
- eswitch->flags &= ~QLCNIC_SWITCH_ENABLE;
- err = -EIO;
- } else {
- eswitch->flags |= QLCNIC_SWITCH_ENABLE;
- dev_info(&adapter->pdev->dev,
- "Enabled eSwitch for port %d\n", eswitch->port);
- }
+ 0,
+ QLCNIC_CDRP_CMD_GET_ESWITCH_STATS);
- return err;
+err_ret:
+ dev_err(&adapter->pdev->dev, "Invalid argument func_esw=%d port=%d"
+ "rx_ctx=%d\n", func_esw, port, rx_tx);
+ return -EIO;
}
-/* Configure eSwitch for port mirroring */
-int qlcnic_config_port_mirroring(struct qlcnic_adapter *adapter, u8 id,
- u8 enable_mirroring, u8 pci_func)
+static int
+__qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter,
+ u32 *arg1, u32 *arg2)
{
int err = -EIO;
- u32 arg1;
-
- if (adapter->op_mode != QLCNIC_MGMT_FUNC ||
- !(adapter->eswitch[id].flags & QLCNIC_SWITCH_ENABLE))
- return err;
-
- arg1 = id | (enable_mirroring ? BIT_4 : 0);
- arg1 |= pci_func << 8;
-
+ u8 pci_func;
+ pci_func = (*arg1 >> 8);
err = qlcnic_issue_cmd(adapter,
adapter->ahw.pci_func,
adapter->fw_hal_version,
- arg1,
+ *arg1,
0,
0,
- QLCNIC_CDRP_CMD_SET_PORTMIRRORING);
+ QLCNIC_CDRP_CMD_GET_ESWITCH_PORT_CONFIG);
- if (err != QLCNIC_RCODE_SUCCESS) {
- dev_err(&adapter->pdev->dev,
- "Failed to configure port mirroring%d on eswitch:%d\n",
- pci_func, id);
- } else {
+ if (err == QLCNIC_RCODE_SUCCESS) {
+ *arg1 = QLCRD32(adapter, QLCNIC_ARG1_CRB_OFFSET);
+ *arg2 = QLCRD32(adapter, QLCNIC_ARG2_CRB_OFFSET);
dev_info(&adapter->pdev->dev,
- "Configured eSwitch %d for port mirroring:%d\n",
- id, pci_func);
+ "eSwitch port config for pci func %d\n", pci_func);
+ } else {
+ dev_err(&adapter->pdev->dev,
+ "Failed to get eswitch port config for pci func %d\n",
+ pci_func);
}
-
return err;
}
-
-/* Configure eSwitch port */
-int qlcnic_config_switch_port(struct qlcnic_adapter *adapter, u8 id,
- int vlan_tagging, u8 discard_tagged, u8 promsc_mode,
- u8 mac_learn, u8 pci_func, u16 vlan_id)
+/* Configure eSwitch port
+op_mode = 0 for setting default port behavior
+op_mode = 1 for setting vlan id
+op_mode = 2 for deleting vlan id
+op_type = 0 for vlan_id
+op_type = 1 for port vlan_id
+*/
+int qlcnic_config_switch_port(struct qlcnic_adapter *adapter,
+ struct qlcnic_esw_func_cfg *esw_cfg)
{
int err = -EIO;
- u32 arg1;
- struct qlcnic_eswitch *eswitch;
+ u32 arg1, arg2 = 0;
+ u8 pci_func;
if (adapter->op_mode != QLCNIC_MGMT_FUNC)
return err;
+ pci_func = esw_cfg->pci_func;
+ arg1 = (adapter->npars[pci_func].phy_port & BIT_0);
+ arg1 |= (pci_func << 8);
- eswitch = &adapter->eswitch[id];
- if (!(eswitch->flags & QLCNIC_SWITCH_ENABLE))
+ if (__qlcnic_get_eswitch_port_config(adapter, &arg1, &arg2))
return err;
-
- arg1 = eswitch->port | (discard_tagged ? BIT_4 : 0);
- arg1 |= (promsc_mode ? BIT_6 : 0) | (mac_learn ? BIT_7 : 0);
- arg1 |= pci_func << 8;
- if (vlan_tagging)
- arg1 |= BIT_5 | (vlan_id << 16);
+ arg1 &= ~(0x0ff << 8);
+ arg1 |= (pci_func << 8);
+ arg1 &= ~(BIT_2 | BIT_3);
+ switch (esw_cfg->op_mode) {
+ case QLCNIC_PORT_DEFAULTS:
+ arg1 |= (BIT_4 | BIT_6 | BIT_7);
+ arg2 |= (BIT_0 | BIT_1);
+ if (adapter->capabilities & QLCNIC_FW_CAPABILITY_TSO)
+ arg2 |= (BIT_2 | BIT_3);
+ if (!(esw_cfg->discard_tagged))
+ arg1 &= ~BIT_4;
+ if (!(esw_cfg->promisc_mode))
+ arg1 &= ~BIT_6;
+ if (!(esw_cfg->mac_override))
+ arg1 &= ~BIT_7;
+ if (!(esw_cfg->mac_anti_spoof))
+ arg2 &= ~BIT_0;
+ if (!(esw_cfg->offload_flags & BIT_0))
+ arg2 &= ~(BIT_1 | BIT_2 | BIT_3);
+ if (!(esw_cfg->offload_flags & BIT_1))
+ arg2 &= ~BIT_2;
+ if (!(esw_cfg->offload_flags & BIT_2))
+ arg2 &= ~BIT_3;
+ break;
+ case QLCNIC_ADD_VLAN:
+ arg1 |= (BIT_2 | BIT_5);
+ arg1 |= (esw_cfg->vlan_id << 16);
+ break;
+ case QLCNIC_DEL_VLAN:
+ arg1 |= (BIT_3 | BIT_5);
+ arg1 &= ~(0x0ffff << 16);
+ break;
+ default:
+ return err;
+ }
err = qlcnic_issue_cmd(adapter,
adapter->ahw.pci_func,
adapter->fw_hal_version,
arg1,
- 0,
+ arg2,
0,
QLCNIC_CDRP_CMD_CONFIGURE_ESWITCH);
if (err != QLCNIC_RCODE_SUCCESS) {
dev_err(&adapter->pdev->dev,
- "Failed to configure eswitch port%d\n", eswitch->port);
+ "Failed to configure eswitch pci func %d\n", pci_func);
} else {
dev_info(&adapter->pdev->dev,
- "Configured eSwitch for port %d\n", eswitch->port);
+ "Configured eSwitch for pci func %d\n", pci_func);
}
return err;
}
+
+int
+qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter,
+ struct qlcnic_esw_func_cfg *esw_cfg)
+{
+ u32 arg1, arg2;
+ u8 phy_port;
+ if (adapter->op_mode == QLCNIC_MGMT_FUNC)
+ phy_port = adapter->npars[esw_cfg->pci_func].phy_port;
+ else
+ phy_port = adapter->physical_port;
+ arg1 = phy_port;
+ arg1 |= (esw_cfg->pci_func << 8);
+ if (__qlcnic_get_eswitch_port_config(adapter, &arg1, &arg2))
+ return -EIO;
+
+ esw_cfg->discard_tagged = !!(arg1 & BIT_4);
+ esw_cfg->host_vlan_tag = !!(arg1 & BIT_5);
+ esw_cfg->promisc_mode = !!(arg1 & BIT_6);
+ esw_cfg->mac_override = !!(arg1 & BIT_7);
+ esw_cfg->vlan_id = LSW(arg1 >> 16);
+ esw_cfg->mac_anti_spoof = (arg2 & 0x1);
+ esw_cfg->offload_flags = ((arg2 >> 1) & 0x7);
+
+ return 0;
+}
diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c
index 9328d59e21e0..25e93a53fca0 100644
--- a/drivers/net/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/qlcnic/qlcnic_ethtool.c
@@ -78,7 +78,25 @@ static const struct qlcnic_stats qlcnic_gstrings_stats[] = {
};
+static const char qlcnic_device_gstrings_stats[][ETH_GSTRING_LEN] = {
+ "rx unicast frames",
+ "rx multicast frames",
+ "rx broadcast frames",
+ "rx dropped frames",
+ "rx errors",
+ "rx local frames",
+ "rx numbytes",
+ "tx unicast frames",
+ "tx multicast frames",
+ "tx broadcast frames",
+ "tx dropped frames",
+ "tx errors",
+ "tx local frames",
+ "tx numbytes",
+};
+
#define QLCNIC_STATS_LEN ARRAY_SIZE(qlcnic_gstrings_stats)
+#define QLCNIC_DEVICE_STATS_LEN ARRAY_SIZE(qlcnic_device_gstrings_stats)
static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = {
"Register_Test_on_offline",
@@ -96,10 +114,10 @@ static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = {
static const u32 diag_registers[] = {
CRB_CMDPEG_STATE,
CRB_RCVPEG_STATE,
- CRB_XG_STATE_P3,
+ CRB_XG_STATE_P3P,
CRB_FW_CAPABILITIES_1,
ISR_INT_STATE_REG,
- QLCNIC_CRB_DEV_REF_COUNT,
+ QLCNIC_CRB_DRV_ACTIVE,
QLCNIC_CRB_DEV_STATE,
QLCNIC_CRB_DRV_STATE,
QLCNIC_CRB_DRV_SCRATCH,
@@ -115,9 +133,13 @@ static const u32 diag_registers[] = {
-1
};
+#define QLCNIC_MGMT_API_VERSION 2
+#define QLCNIC_DEV_INFO_SIZE 1
+#define QLCNIC_ETHTOOL_REGS_VER 2
static int qlcnic_get_regs_len(struct net_device *dev)
{
- return sizeof(diag_registers) + QLCNIC_RING_REGS_LEN;
+ return sizeof(diag_registers) + QLCNIC_RING_REGS_LEN +
+ QLCNIC_DEV_INFO_SIZE + 1;
}
static int qlcnic_get_eeprom_len(struct net_device *dev)
@@ -185,9 +207,9 @@ qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
goto skip;
}
- val = QLCRD32(adapter, P3_LINK_SPEED_REG(pcifn));
- ecmd->speed = P3_LINK_SPEED_MHZ *
- P3_LINK_SPEED_VAL(pcifn, val);
+ val = QLCRD32(adapter, P3P_LINK_SPEED_REG(pcifn));
+ ecmd->speed = P3P_LINK_SPEED_MHZ *
+ P3P_LINK_SPEED_VAL(pcifn, val);
ecmd->duplex = DUPLEX_FULL;
ecmd->autoneg = AUTONEG_DISABLE;
} else
@@ -198,42 +220,42 @@ skip:
ecmd->transceiver = XCVR_EXTERNAL;
switch (adapter->ahw.board_type) {
- case QLCNIC_BRDTYPE_P3_REF_QG:
- case QLCNIC_BRDTYPE_P3_4_GB:
- case QLCNIC_BRDTYPE_P3_4_GB_MM:
+ case QLCNIC_BRDTYPE_P3P_REF_QG:
+ case QLCNIC_BRDTYPE_P3P_4_GB:
+ case QLCNIC_BRDTYPE_P3P_4_GB_MM:
ecmd->supported |= SUPPORTED_Autoneg;
ecmd->advertising |= ADVERTISED_Autoneg;
- case QLCNIC_BRDTYPE_P3_10G_CX4:
- case QLCNIC_BRDTYPE_P3_10G_CX4_LP:
- case QLCNIC_BRDTYPE_P3_10000_BASE_T:
+ case QLCNIC_BRDTYPE_P3P_10G_CX4:
+ case QLCNIC_BRDTYPE_P3P_10G_CX4_LP:
+ case QLCNIC_BRDTYPE_P3P_10000_BASE_T:
ecmd->supported |= SUPPORTED_TP;
ecmd->advertising |= ADVERTISED_TP;
ecmd->port = PORT_TP;
ecmd->autoneg = adapter->link_autoneg;
break;
- case QLCNIC_BRDTYPE_P3_IMEZ:
- case QLCNIC_BRDTYPE_P3_XG_LOM:
- case QLCNIC_BRDTYPE_P3_HMEZ:
+ case QLCNIC_BRDTYPE_P3P_IMEZ:
+ case QLCNIC_BRDTYPE_P3P_XG_LOM:
+ case QLCNIC_BRDTYPE_P3P_HMEZ:
ecmd->supported |= SUPPORTED_MII;
ecmd->advertising |= ADVERTISED_MII;
ecmd->port = PORT_MII;
ecmd->autoneg = AUTONEG_DISABLE;
break;
- case QLCNIC_BRDTYPE_P3_10G_SFP_PLUS:
- case QLCNIC_BRDTYPE_P3_10G_SFP_CT:
- case QLCNIC_BRDTYPE_P3_10G_SFP_QT:
+ case QLCNIC_BRDTYPE_P3P_10G_SFP_PLUS:
+ case QLCNIC_BRDTYPE_P3P_10G_SFP_CT:
+ case QLCNIC_BRDTYPE_P3P_10G_SFP_QT:
ecmd->advertising |= ADVERTISED_TP;
ecmd->supported |= SUPPORTED_TP;
check_sfp_module = netif_running(dev) &&
adapter->has_link_events;
- case QLCNIC_BRDTYPE_P3_10G_XFP:
+ case QLCNIC_BRDTYPE_P3P_10G_XFP:
ecmd->supported |= SUPPORTED_FIBRE;
ecmd->advertising |= ADVERTISED_FIBRE;
ecmd->port = PORT_FIBRE;
ecmd->autoneg = AUTONEG_DISABLE;
break;
- case QLCNIC_BRDTYPE_P3_10G_TP:
+ case QLCNIC_BRDTYPE_P3P_10G_TP:
if (adapter->ahw.port_type == QLCNIC_XGBE) {
ecmd->autoneg = AUTONEG_DISABLE;
ecmd->supported |= (SUPPORTED_FIBRE | SUPPORTED_TP);
@@ -339,14 +361,17 @@ qlcnic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx;
struct qlcnic_host_sds_ring *sds_ring;
u32 *regs_buff = p;
- int ring, i = 0;
+ int ring, i = 0, j = 0;
memset(p, 0, qlcnic_get_regs_len(dev));
- regs->version = (1 << 24) | (adapter->ahw.revision_id << 16) |
- (adapter->pdev)->device;
+ regs->version = (QLCNIC_ETHTOOL_REGS_VER << 24) |
+ (adapter->ahw.revision_id << 16) | (adapter->pdev)->device;
+
+ regs_buff[0] = (0xcafe0000 | (QLCNIC_DEV_INFO_SIZE & 0xffff));
+ regs_buff[1] = QLCNIC_MGMT_API_VERSION;
- for (i = 0; diag_registers[i] != -1; i++)
- regs_buff[i] = QLCRD32(adapter, diag_registers[i]);
+ for (i = QLCNIC_DEV_INFO_SIZE + 1; diag_registers[j] != -1; j++, i++)
+ regs_buff[i] = QLCRD32(adapter, diag_registers[j]);
if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
return;
@@ -374,9 +399,9 @@ static u32 qlcnic_test_link(struct net_device *dev)
struct qlcnic_adapter *adapter = netdev_priv(dev);
u32 val;
- val = QLCRD32(adapter, CRB_XG_STATE_P3);
- val = XG_LINK_STATE_P3(adapter->ahw.pci_func, val);
- return (val == XG_LINK_UP_P3) ? 0 : 1;
+ val = QLCRD32(adapter, CRB_XG_STATE_P3P);
+ val = XG_LINK_STATE_P3P(adapter->ahw.pci_func, val);
+ return (val == XG_LINK_UP_P3P) ? 0 : 1;
}
static int
@@ -618,10 +643,13 @@ static int qlcnic_reg_test(struct net_device *dev)
static int qlcnic_get_sset_count(struct net_device *dev, int sset)
{
+ struct qlcnic_adapter *adapter = netdev_priv(dev);
switch (sset) {
case ETH_SS_TEST:
return QLCNIC_TEST_LEN;
case ETH_SS_STATS:
+ if (adapter->flags & QLCNIC_ESWITCH_ENABLED)
+ return QLCNIC_STATS_LEN + QLCNIC_DEVICE_STATS_LEN;
return QLCNIC_STATS_LEN;
default:
return -EOPNOTSUPP;
@@ -629,6 +657,8 @@ static int qlcnic_get_sset_count(struct net_device *dev, int sset)
}
#define QLC_ILB_PKT_SIZE 64
+#define QLC_NUM_ILB_PKT 16
+#define QLC_ILB_MAX_RCV_LOOP 10
static void qlcnic_create_loopback_buff(unsigned char *data)
{
@@ -650,24 +680,34 @@ static int qlcnic_do_ilb_test(struct qlcnic_adapter *adapter)
struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx;
struct qlcnic_host_sds_ring *sds_ring = &recv_ctx->sds_rings[0];
struct sk_buff *skb;
- int i;
+ int i, loop, cnt = 0;
- for (i = 0; i < 16; i++) {
+ for (i = 0; i < QLC_NUM_ILB_PKT; i++) {
skb = dev_alloc_skb(QLC_ILB_PKT_SIZE);
qlcnic_create_loopback_buff(skb->data);
skb_put(skb, QLC_ILB_PKT_SIZE);
adapter->diag_cnt = 0;
-
qlcnic_xmit_frame(skb, adapter->netdev);
- msleep(5);
-
- qlcnic_process_rcv_ring_diag(sds_ring);
+ loop = 0;
+ do {
+ msleep(1);
+ qlcnic_process_rcv_ring_diag(sds_ring);
+ } while (loop++ < QLC_ILB_MAX_RCV_LOOP &&
+ !adapter->diag_cnt);
dev_kfree_skb_any(skb);
+
if (!adapter->diag_cnt)
- return -1;
+ dev_warn(&adapter->pdev->dev, "ILB Test: %dth packet"
+ " not recevied\n", i + 1);
+ else
+ cnt++;
+ }
+ if (cnt != i) {
+ dev_warn(&adapter->pdev->dev, "ILB Test failed\n");
+ return -1;
}
return 0;
}
@@ -687,6 +727,11 @@ static int qlcnic_loopback_test(struct net_device *netdev)
if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
return -EIO;
+ if (qlcnic_request_quiscent_mode(adapter)) {
+ clear_bit(__QLCNIC_RESETTING, &adapter->state);
+ return -EIO;
+ }
+
ret = qlcnic_diag_alloc_res(netdev, QLCNIC_LOOPBACK_TEST);
if (ret)
goto clear_it;
@@ -703,6 +748,7 @@ done:
qlcnic_diag_free_res(netdev, max_sds_rings);
clear_it:
+ qlcnic_clear_quiscent_mode(adapter);
adapter->max_sds_rings = max_sds_rings;
clear_bit(__QLCNIC_RESETTING, &adapter->state);
return ret;
@@ -747,6 +793,14 @@ qlcnic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
{
memset(data, 0, sizeof(u64) * QLCNIC_TEST_LEN);
+ data[0] = qlcnic_reg_test(dev);
+ if (data[0])
+ eth_test->flags |= ETH_TEST_FL_FAILED;
+
+ data[1] = (u64) qlcnic_test_link(dev);
+ if (data[1])
+ eth_test->flags |= ETH_TEST_FL_FAILED;
+
if (eth_test->flags == ETH_TEST_FL_OFFLINE) {
data[2] = qlcnic_irq_test(dev);
if (data[2])
@@ -757,21 +811,13 @@ qlcnic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
eth_test->flags |= ETH_TEST_FL_FAILED;
}
-
- data[0] = qlcnic_reg_test(dev);
- if (data[0])
- eth_test->flags |= ETH_TEST_FL_FAILED;
-
- /* link test */
- data[1] = (u64) qlcnic_test_link(dev);
- if (data[1])
- eth_test->flags |= ETH_TEST_FL_FAILED;
}
static void
qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 * data)
{
- int index;
+ struct qlcnic_adapter *adapter = netdev_priv(dev);
+ int index, i;
switch (stringset) {
case ETH_SS_TEST:
@@ -784,16 +830,43 @@ qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 * data)
qlcnic_gstrings_stats[index].stat_string,
ETH_GSTRING_LEN);
}
- break;
+ if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
+ return;
+ for (i = 0; i < QLCNIC_DEVICE_STATS_LEN; index++, i++) {
+ memcpy(data + index * ETH_GSTRING_LEN,
+ qlcnic_device_gstrings_stats[i],
+ ETH_GSTRING_LEN);
+ }
}
}
+#define QLCNIC_FILL_ESWITCH_STATS(VAL1) \
+ (((VAL1) == QLCNIC_ESW_STATS_NOT_AVAIL) ? 0 : VAL1)
+
+static void
+qlcnic_fill_device_stats(int *index, u64 *data,
+ struct __qlcnic_esw_statistics *stats)
+{
+ int ind = *index;
+
+ data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->unicast_frames);
+ data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->multicast_frames);
+ data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->broadcast_frames);
+ data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->dropped_frames);
+ data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->errors);
+ data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->local_frames);
+ data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->numbytes);
+
+ *index = ind;
+}
+
static void
qlcnic_get_ethtool_stats(struct net_device *dev,
struct ethtool_stats *stats, u64 * data)
{
struct qlcnic_adapter *adapter = netdev_priv(dev);
- int index;
+ struct qlcnic_esw_statistics port_stats;
+ int index, ret;
for (index = 0; index < QLCNIC_STATS_LEN; index++) {
char *p =
@@ -803,8 +876,40 @@ qlcnic_get_ethtool_stats(struct net_device *dev,
(qlcnic_gstrings_stats[index].sizeof_stat ==
sizeof(u64)) ? *(u64 *)p:(*(u32 *)p);
}
+
+ if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
+ return;
+
+ memset(&port_stats, 0, sizeof(struct qlcnic_esw_statistics));
+ ret = qlcnic_get_port_stats(adapter, adapter->ahw.pci_func,
+ QLCNIC_QUERY_RX_COUNTER, &port_stats.rx);
+ if (ret)
+ return;
+
+ qlcnic_fill_device_stats(&index, data, &port_stats.rx);
+
+ ret = qlcnic_get_port_stats(adapter, adapter->ahw.pci_func,
+ QLCNIC_QUERY_TX_COUNTER, &port_stats.tx);
+ if (ret)
+ return;
+
+ qlcnic_fill_device_stats(&index, data, &port_stats.tx);
}
+static int qlcnic_set_tx_csum(struct net_device *dev, u32 data)
+{
+ struct qlcnic_adapter *adapter = netdev_priv(dev);
+
+ if ((adapter->flags & QLCNIC_ESWITCH_ENABLED))
+ return -EOPNOTSUPP;
+ if (data)
+ dev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
+ else
+ dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
+
+ return 0;
+
+}
static u32 qlcnic_get_tx_csum(struct net_device *dev)
{
return dev->features & NETIF_F_IP_CSUM;
@@ -819,7 +924,23 @@ static u32 qlcnic_get_rx_csum(struct net_device *dev)
static int qlcnic_set_rx_csum(struct net_device *dev, u32 data)
{
struct qlcnic_adapter *adapter = netdev_priv(dev);
+
+ if ((adapter->flags & QLCNIC_ESWITCH_ENABLED))
+ return -EOPNOTSUPP;
+ if (!!data) {
+ adapter->rx_csum = !!data;
+ return 0;
+ }
+
+ if (dev->features & NETIF_F_LRO) {
+ if (qlcnic_config_hw_lro(adapter, QLCNIC_LRO_DISABLED))
+ return -EIO;
+
+ dev->features &= ~NETIF_F_LRO;
+ qlcnic_send_lro_cleanup(adapter);
+ }
adapter->rx_csum = !!data;
+ dev_info(&adapter->pdev->dev, "disabling LRO as rx_csum is off\n");
return 0;
}
@@ -1002,6 +1123,15 @@ static int qlcnic_set_flags(struct net_device *netdev, u32 data)
if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO))
return -EINVAL;
+ if (!adapter->rx_csum) {
+ dev_info(&adapter->pdev->dev, "rx csum is off, "
+ "cannot toggle lro\n");
+ return -EINVAL;
+ }
+
+ if ((data & ETH_FLAG_LRO) && (netdev->features & NETIF_F_LRO))
+ return 0;
+
if (data & ETH_FLAG_LRO) {
hw_lro = QLCNIC_LRO_ENABLED;
netdev->features |= NETIF_F_LRO;
@@ -1048,7 +1178,7 @@ const struct ethtool_ops qlcnic_ethtool_ops = {
.get_pauseparam = qlcnic_get_pauseparam,
.set_pauseparam = qlcnic_set_pauseparam,
.get_tx_csum = qlcnic_get_tx_csum,
- .set_tx_csum = ethtool_op_set_tx_csum,
+ .set_tx_csum = qlcnic_set_tx_csum,
.set_sg = ethtool_op_set_sg,
.get_tso = qlcnic_get_tso,
.set_tso = qlcnic_set_tso,
diff --git a/drivers/net/qlcnic/qlcnic_hdr.h b/drivers/net/qlcnic/qlcnic_hdr.h
index 15fc32070be3..4290b80cde1a 100644
--- a/drivers/net/qlcnic/qlcnic_hdr.h
+++ b/drivers/net/qlcnic/qlcnic_hdr.h
@@ -556,18 +556,18 @@ enum {
#define XG_LINK_UP 0x10
#define XG_LINK_DOWN 0x20
-#define XG_LINK_UP_P3 0x01
-#define XG_LINK_DOWN_P3 0x02
-#define XG_LINK_STATE_P3_MASK 0xf
-#define XG_LINK_STATE_P3(pcifn, val) \
- (((val) >> ((pcifn) * 4)) & XG_LINK_STATE_P3_MASK)
-
-#define P3_LINK_SPEED_MHZ 100
-#define P3_LINK_SPEED_MASK 0xff
-#define P3_LINK_SPEED_REG(pcifn) \
+#define XG_LINK_UP_P3P 0x01
+#define XG_LINK_DOWN_P3P 0x02
+#define XG_LINK_STATE_P3P_MASK 0xf
+#define XG_LINK_STATE_P3P(pcifn, val) \
+ (((val) >> ((pcifn) * 4)) & XG_LINK_STATE_P3P_MASK)
+
+#define P3P_LINK_SPEED_MHZ 100
+#define P3P_LINK_SPEED_MASK 0xff
+#define P3P_LINK_SPEED_REG(pcifn) \
(CRB_PF_LINK_SPEED_1 + (((pcifn) / 4) * 4))
-#define P3_LINK_SPEED_VAL(pcifn, reg) \
- (((reg) >> (8 * ((pcifn) & 0x3))) & P3_LINK_SPEED_MASK)
+#define P3P_LINK_SPEED_VAL(pcifn, reg) \
+ (((reg) >> (8 * ((pcifn) & 0x3))) & P3P_LINK_SPEED_MASK)
#define QLCNIC_CAM_RAM_BASE (QLCNIC_CRB_CAM + 0x02000)
#define QLCNIC_CAM_RAM(reg) (QLCNIC_CAM_RAM_BASE + (reg))
@@ -592,7 +592,7 @@ enum {
#define CRB_CMDPEG_STATE (QLCNIC_REG(0x50))
#define CRB_RCVPEG_STATE (QLCNIC_REG(0x13c))
-#define CRB_XG_STATE_P3 (QLCNIC_REG(0x98))
+#define CRB_XG_STATE_P3P (QLCNIC_REG(0x98))
#define CRB_PF_LINK_SPEED_1 (QLCNIC_REG(0xe8))
#define CRB_PF_LINK_SPEED_2 (QLCNIC_REG(0xec))
@@ -698,7 +698,7 @@ enum {
#define QLCNIC_PEG_ALIVE_COUNTER (QLCNIC_CAM_RAM(0xb0))
#define QLCNIC_PEG_HALT_STATUS1 (QLCNIC_CAM_RAM(0xa8))
#define QLCNIC_PEG_HALT_STATUS2 (QLCNIC_CAM_RAM(0xac))
-#define QLCNIC_CRB_DEV_REF_COUNT (QLCNIC_CAM_RAM(0x138))
+#define QLCNIC_CRB_DRV_ACTIVE (QLCNIC_CAM_RAM(0x138))
#define QLCNIC_CRB_DEV_STATE (QLCNIC_CAM_RAM(0x140))
#define QLCNIC_CRB_DRV_STATE (QLCNIC_CAM_RAM(0x144))
@@ -718,8 +718,9 @@ enum {
#define QLCNIC_DEV_FAILED 0x6
#define QLCNIC_DEV_QUISCENT 0x7
-#define QLCNIC_DEV_NPAR_NOT_RDY 0
-#define QLCNIC_DEV_NPAR_RDY 1
+#define QLCNIC_DEV_NPAR_NON_OPER 0 /* NON Operational */
+#define QLCNIC_DEV_NPAR_OPER 1 /* NPAR Operational */
+#define QLCNIC_DEV_NPAR_OPER_TIMEO 30 /* Operational time out */
#define QLC_DEV_CHECK_ACTIVE(VAL, FN) ((VAL) &= (1 << (FN * 4)))
#define QLC_DEV_SET_REF_CNT(VAL, FN) ((VAL) |= (1 << (FN * 4)))
@@ -744,6 +745,15 @@ enum {
#define FW_POLL_DELAY (1 * HZ)
#define FW_FAIL_THRESH 2
+#define QLCNIC_RESET_TIMEOUT_SECS 10
+#define QLCNIC_INIT_TIMEOUT_SECS 30
+#define QLCNIC_RCVPEG_CHECK_RETRY_COUNT 2000
+#define QLCNIC_RCVPEG_CHECK_DELAY 10
+#define QLCNIC_CMDPEG_CHECK_RETRY_COUNT 60
+#define QLCNIC_CMDPEG_CHECK_DELAY 500
+#define QLCNIC_HEARTBEAT_PERIOD_MSECS 200
+#define QLCNIC_HEARTBEAT_CHECK_RETRY_COUNT 45
+
#define ISR_MSI_INT_TRIGGER(FUNC) (QLCNIC_PCIX_PS_REG(PCIX_MSI_F(FUNC)))
#define ISR_LEGACY_INT_TRIGGERED(VAL) (((VAL) & 0x300) == 0x200)
@@ -770,6 +780,7 @@ struct qlcnic_legacy_intr_set {
#define QLCNIC_DRV_OP_MODE 0x1b2170
#define QLCNIC_MSIX_BASE 0x132110
#define QLCNIC_MAX_PCI_FUNC 8
+#define QLCNIC_MAX_VLAN_FILTERS 64
/* PCI function operational mode */
enum {
@@ -778,6 +789,12 @@ enum {
QLCNIC_NON_PRIV_FUNC = 2
};
+enum {
+ QLCNIC_PORT_DEFAULTS = 0,
+ QLCNIC_ADD_VLAN = 1,
+ QLCNIC_DEL_VLAN = 2
+};
+
#define QLC_DEV_DRV_DEFAULT 0x11111111
#define LSB(x) ((uint8_t)(x))
diff --git a/drivers/net/qlcnic/qlcnic_hw.c b/drivers/net/qlcnic/qlcnic_hw.c
index e08c8b0556a4..7a47a2a7ee27 100644
--- a/drivers/net/qlcnic/qlcnic_hw.c
+++ b/drivers/net/qlcnic/qlcnic_hw.c
@@ -297,8 +297,8 @@ qlcnic_pcie_sem_lock(struct qlcnic_adapter *adapter, int sem, u32 id_reg)
break;
if (++timeout >= QLCNIC_PCIE_SEM_TIMEOUT) {
dev_err(&adapter->pdev->dev,
- "Failed to acquire sem=%d lock;reg_id=%d\n",
- sem, id_reg);
+ "Failed to acquire sem=%d lock; holdby=%d\n",
+ sem, id_reg ? QLCRD32(adapter, id_reg) : -1);
return -EIO;
}
msleep(1);
@@ -375,10 +375,11 @@ qlcnic_send_cmd_descs(struct qlcnic_adapter *adapter,
static int
qlcnic_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr,
- unsigned op)
+ __le16 vlan_id, unsigned op)
{
struct qlcnic_nic_req req;
struct qlcnic_mac_req *mac_req;
+ struct qlcnic_vlan_req *vlan_req;
u64 word;
memset(&req, 0, sizeof(struct qlcnic_nic_req));
@@ -391,6 +392,9 @@ qlcnic_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr,
mac_req->op = op;
memcpy(mac_req->mac_addr, addr, 6);
+ vlan_req = (struct qlcnic_vlan_req *)&req.words[1];
+ vlan_req->vlan_id = vlan_id;
+
return qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
}
@@ -415,7 +419,7 @@ static int qlcnic_nic_add_mac(struct qlcnic_adapter *adapter, u8 *addr)
memcpy(cur->mac_addr, addr, ETH_ALEN);
if (qlcnic_sre_macaddr_change(adapter,
- cur->mac_addr, QLCNIC_MAC_ADD)) {
+ cur->mac_addr, 0, QLCNIC_MAC_ADD)) {
kfree(cur);
return -EIO;
}
@@ -438,7 +442,8 @@ void qlcnic_set_multi(struct net_device *netdev)
qlcnic_nic_add_mac(adapter, bcast_addr);
if (netdev->flags & IFF_PROMISC) {
- mode = VPORT_MISS_MODE_ACCEPT_ALL;
+ if (!(adapter->flags & QLCNIC_PROMISC_DISABLED))
+ mode = VPORT_MISS_MODE_ACCEPT_ALL;
goto send_fw_cmd;
}
@@ -485,12 +490,63 @@ void qlcnic_free_mac_list(struct qlcnic_adapter *adapter)
while (!list_empty(head)) {
cur = list_entry(head->next, struct qlcnic_mac_list_s, list);
qlcnic_sre_macaddr_change(adapter,
- cur->mac_addr, QLCNIC_MAC_DEL);
+ cur->mac_addr, 0, QLCNIC_MAC_DEL);
list_del(&cur->list);
kfree(cur);
}
}
+void qlcnic_prune_lb_filters(struct qlcnic_adapter *adapter)
+{
+ struct qlcnic_filter *tmp_fil;
+ struct hlist_node *tmp_hnode, *n;
+ struct hlist_head *head;
+ int i;
+
+ for (i = 0; i < adapter->fhash.fmax; i++) {
+ head = &(adapter->fhash.fhead[i]);
+
+ hlist_for_each_entry_safe(tmp_fil, tmp_hnode, n, head, fnode)
+ {
+ if (jiffies >
+ (QLCNIC_FILTER_AGE * HZ + tmp_fil->ftime)) {
+ qlcnic_sre_macaddr_change(adapter,
+ tmp_fil->faddr, tmp_fil->vlan_id,
+ tmp_fil->vlan_id ? QLCNIC_MAC_VLAN_DEL :
+ QLCNIC_MAC_DEL);
+ spin_lock_bh(&adapter->mac_learn_lock);
+ adapter->fhash.fnum--;
+ hlist_del(&tmp_fil->fnode);
+ spin_unlock_bh(&adapter->mac_learn_lock);
+ kfree(tmp_fil);
+ }
+ }
+ }
+}
+
+void qlcnic_delete_lb_filters(struct qlcnic_adapter *adapter)
+{
+ struct qlcnic_filter *tmp_fil;
+ struct hlist_node *tmp_hnode, *n;
+ struct hlist_head *head;
+ int i;
+
+ for (i = 0; i < adapter->fhash.fmax; i++) {
+ head = &(adapter->fhash.fhead[i]);
+
+ hlist_for_each_entry_safe(tmp_fil, tmp_hnode, n, head, fnode) {
+ qlcnic_sre_macaddr_change(adapter, tmp_fil->faddr,
+ tmp_fil->vlan_id, tmp_fil->vlan_id ?
+ QLCNIC_MAC_VLAN_DEL : QLCNIC_MAC_DEL);
+ spin_lock_bh(&adapter->mac_learn_lock);
+ adapter->fhash.fnum--;
+ hlist_del(&tmp_fil->fnode);
+ spin_unlock_bh(&adapter->mac_learn_lock);
+ kfree(tmp_fil);
+ }
+ }
+}
+
#define QLCNIC_CONFIG_INTR_COALESCE 3
/*
@@ -527,9 +583,6 @@ int qlcnic_config_hw_lro(struct qlcnic_adapter *adapter, int enable)
u64 word;
int rv;
- if ((adapter->flags & QLCNIC_LRO_ENABLED) == enable)
- return 0;
-
memset(&req, 0, sizeof(struct qlcnic_nic_req));
req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23);
@@ -544,8 +597,6 @@ int qlcnic_config_hw_lro(struct qlcnic_adapter *adapter, int enable)
dev_err(&adapter->netdev->dev,
"Could not send configure hw lro request\n");
- adapter->flags ^= QLCNIC_LRO_ENABLED;
-
return rv;
}
@@ -623,9 +674,10 @@ int qlcnic_config_rss(struct qlcnic_adapter *adapter, int enable)
return rv;
}
-int qlcnic_config_ipaddr(struct qlcnic_adapter *adapter, u32 ip, int cmd)
+int qlcnic_config_ipaddr(struct qlcnic_adapter *adapter, __be32 ip, int cmd)
{
struct qlcnic_nic_req req;
+ struct qlcnic_ipaddr *ipa;
u64 word;
int rv;
@@ -636,7 +688,8 @@ int qlcnic_config_ipaddr(struct qlcnic_adapter *adapter, u32 ip, int cmd)
req.req_hdr = cpu_to_le64(word);
req.words[0] = cpu_to_le64(cmd);
- req.words[1] = cpu_to_le64(ip);
+ ipa = (struct qlcnic_ipaddr *)&req.words[1];
+ ipa->ipv4 = ip;
rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
if (rv != 0)
@@ -701,9 +754,9 @@ int qlcnic_change_mtu(struct net_device *netdev, int mtu)
struct qlcnic_adapter *adapter = netdev_priv(netdev);
int rc = 0;
- if (mtu > P3_MAX_MTU) {
- dev_err(&adapter->netdev->dev, "mtu > %d bytes unsupported\n",
- P3_MAX_MTU);
+ if (mtu < P3P_MIN_MTU || mtu > P3P_MAX_MTU) {
+ dev_err(&adapter->netdev->dev, "%d bytes < mtu < %d bytes"
+ " not supported\n", P3P_MAX_MTU, P3P_MIN_MTU);
return -EINVAL;
}
@@ -715,19 +768,6 @@ int qlcnic_change_mtu(struct net_device *netdev, int mtu)
return rc;
}
-int qlcnic_get_mac_addr(struct qlcnic_adapter *adapter, u8 *mac)
-{
- u32 crbaddr;
- int pci_func = adapter->ahw.pci_func;
-
- crbaddr = CRB_MAC_BLOCK_START +
- (4 * ((pci_func/2) * 3)) + (4 * (pci_func & 1));
-
- qlcnic_fetch_mac(adapter, crbaddr, crbaddr+4, pci_func & 1, mac);
-
- return 0;
-}
-
/*
* Changes the CRB window to the specified window.
*/
@@ -1121,31 +1161,31 @@ int qlcnic_get_board_info(struct qlcnic_adapter *adapter)
adapter->ahw.board_type = board_type;
- if (board_type == QLCNIC_BRDTYPE_P3_4_GB_MM) {
+ if (board_type == QLCNIC_BRDTYPE_P3P_4_GB_MM) {
u32 gpio = QLCRD32(adapter, QLCNIC_ROMUSB_GLB_PAD_GPIO_I);
if ((gpio & 0x8000) == 0)
- board_type = QLCNIC_BRDTYPE_P3_10G_TP;
+ board_type = QLCNIC_BRDTYPE_P3P_10G_TP;
}
switch (board_type) {
- case QLCNIC_BRDTYPE_P3_HMEZ:
- case QLCNIC_BRDTYPE_P3_XG_LOM:
- case QLCNIC_BRDTYPE_P3_10G_CX4:
- case QLCNIC_BRDTYPE_P3_10G_CX4_LP:
- case QLCNIC_BRDTYPE_P3_IMEZ:
- case QLCNIC_BRDTYPE_P3_10G_SFP_PLUS:
- case QLCNIC_BRDTYPE_P3_10G_SFP_CT:
- case QLCNIC_BRDTYPE_P3_10G_SFP_QT:
- case QLCNIC_BRDTYPE_P3_10G_XFP:
- case QLCNIC_BRDTYPE_P3_10000_BASE_T:
+ case QLCNIC_BRDTYPE_P3P_HMEZ:
+ case QLCNIC_BRDTYPE_P3P_XG_LOM:
+ case QLCNIC_BRDTYPE_P3P_10G_CX4:
+ case QLCNIC_BRDTYPE_P3P_10G_CX4_LP:
+ case QLCNIC_BRDTYPE_P3P_IMEZ:
+ case QLCNIC_BRDTYPE_P3P_10G_SFP_PLUS:
+ case QLCNIC_BRDTYPE_P3P_10G_SFP_CT:
+ case QLCNIC_BRDTYPE_P3P_10G_SFP_QT:
+ case QLCNIC_BRDTYPE_P3P_10G_XFP:
+ case QLCNIC_BRDTYPE_P3P_10000_BASE_T:
adapter->ahw.port_type = QLCNIC_XGBE;
break;
- case QLCNIC_BRDTYPE_P3_REF_QG:
- case QLCNIC_BRDTYPE_P3_4_GB:
- case QLCNIC_BRDTYPE_P3_4_GB_MM:
+ case QLCNIC_BRDTYPE_P3P_REF_QG:
+ case QLCNIC_BRDTYPE_P3P_4_GB:
+ case QLCNIC_BRDTYPE_P3P_4_GB_MM:
adapter->ahw.port_type = QLCNIC_GBE;
break;
- case QLCNIC_BRDTYPE_P3_10G_TP:
+ case QLCNIC_BRDTYPE_P3P_10G_TP:
adapter->ahw.port_type = (adapter->portnum < 2) ?
QLCNIC_XGBE : QLCNIC_GBE;
break;
@@ -1245,4 +1285,5 @@ void qlcnic_clear_ilb_mode(struct qlcnic_adapter *adapter)
mode = VPORT_MISS_MODE_ACCEPT_MULTI;
qlcnic_nic_set_promisc(adapter, mode);
+ msleep(1000);
}
diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c
index 2c7cf0b64811..0d180c6e41fe 100644
--- a/drivers/net/qlcnic/qlcnic_init.c
+++ b/drivers/net/qlcnic/qlcnic_init.c
@@ -25,6 +25,7 @@
#include <linux/netdevice.h>
#include <linux/delay.h>
#include <linux/slab.h>
+#include <linux/if_vlan.h>
#include "qlcnic.h"
struct crb_addr_pair {
@@ -45,6 +46,9 @@ static void
qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter,
struct qlcnic_host_rds_ring *rds_ring);
+static int
+qlcnic_check_fw_hearbeat(struct qlcnic_adapter *adapter);
+
static void crb_addr_transform_setup(void)
{
crb_addr_transform(XDMA);
@@ -136,8 +140,6 @@ void qlcnic_reset_rx_buffers_list(struct qlcnic_adapter *adapter)
for (ring = 0; ring < adapter->max_rds_rings; ring++) {
rds_ring = &recv_ctx->rds_rings[ring];
- spin_lock(&rds_ring->lock);
-
INIT_LIST_HEAD(&rds_ring->free_list);
rx_buf = rds_ring->rx_buf_arr;
@@ -146,8 +148,6 @@ void qlcnic_reset_rx_buffers_list(struct qlcnic_adapter *adapter)
&rds_ring->free_list);
rx_buf++;
}
-
- spin_unlock(&rds_ring->lock);
}
}
@@ -259,14 +259,14 @@ int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter)
switch (ring) {
case RCV_RING_NORMAL:
rds_ring->num_desc = adapter->num_rxd;
- rds_ring->dma_size = QLCNIC_P3_RX_BUF_MAX_LEN;
+ rds_ring->dma_size = QLCNIC_P3P_RX_BUF_MAX_LEN;
rds_ring->skb_size = rds_ring->dma_size + NET_IP_ALIGN;
break;
case RCV_RING_JUMBO:
rds_ring->num_desc = adapter->num_jumbo_rxd;
rds_ring->dma_size =
- QLCNIC_P3_RX_JUMBO_BUF_MAX_LEN;
+ QLCNIC_P3P_RX_JUMBO_BUF_MAX_LEN;
if (adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO)
rds_ring->dma_size += QLCNIC_LRO_BUFFER_EXTRA;
@@ -439,11 +439,14 @@ int qlcnic_pinit_from_rom(struct qlcnic_adapter *adapter)
u32 off;
struct pci_dev *pdev = adapter->pdev;
- /* resetall */
+ QLCWR32(adapter, CRB_CMDPEG_STATE, 0);
+ QLCWR32(adapter, CRB_RCVPEG_STATE, 0);
+
qlcnic_rom_lock(adapter);
QLCWR32(adapter, QLCNIC_ROMUSB_GLB_SW_RESET, 0xfeffffff);
qlcnic_rom_unlock(adapter);
+ /* Init HW CRB block */
if (qlcnic_rom_fast_read(adapter, 0, &n) != 0 || (n != 0xcafecafe) ||
qlcnic_rom_fast_read(adapter, 4, &n) != 0) {
dev_err(&pdev->dev, "ERROR Reading crb_init area: val:%x\n", n);
@@ -524,13 +527,10 @@ int qlcnic_pinit_from_rom(struct qlcnic_adapter *adapter)
}
kfree(buf);
- /* p2dn replyCount */
+ /* Initialize protocol process engine */
QLCWR32(adapter, QLCNIC_CRB_PEG_NET_D + 0xec, 0x1e);
- /* disable_peg_cache 0 & 1*/
QLCWR32(adapter, QLCNIC_CRB_PEG_NET_D + 0x4c, 8);
QLCWR32(adapter, QLCNIC_CRB_PEG_NET_I + 0x4c, 8);
-
- /* peg_clr_all */
QLCWR32(adapter, QLCNIC_CRB_PEG_NET_0 + 0x8, 0);
QLCWR32(adapter, QLCNIC_CRB_PEG_NET_0 + 0xc, 0);
QLCWR32(adapter, QLCNIC_CRB_PEG_NET_1 + 0x8, 0);
@@ -539,10 +539,88 @@ int qlcnic_pinit_from_rom(struct qlcnic_adapter *adapter)
QLCWR32(adapter, QLCNIC_CRB_PEG_NET_2 + 0xc, 0);
QLCWR32(adapter, QLCNIC_CRB_PEG_NET_3 + 0x8, 0);
QLCWR32(adapter, QLCNIC_CRB_PEG_NET_3 + 0xc, 0);
+ QLCWR32(adapter, QLCNIC_CRB_PEG_NET_4 + 0x8, 0);
+ QLCWR32(adapter, QLCNIC_CRB_PEG_NET_4 + 0xc, 0);
+ msleep(1);
+ QLCWR32(adapter, QLCNIC_PEG_HALT_STATUS1, 0);
+ QLCWR32(adapter, QLCNIC_PEG_HALT_STATUS2, 0);
+ return 0;
+}
+
+static int qlcnic_cmd_peg_ready(struct qlcnic_adapter *adapter)
+{
+ u32 val;
+ int retries = QLCNIC_CMDPEG_CHECK_RETRY_COUNT;
+
+ do {
+ val = QLCRD32(adapter, CRB_CMDPEG_STATE);
+
+ switch (val) {
+ case PHAN_INITIALIZE_COMPLETE:
+ case PHAN_INITIALIZE_ACK:
+ return 0;
+ case PHAN_INITIALIZE_FAILED:
+ goto out_err;
+ default:
+ break;
+ }
+
+ msleep(QLCNIC_CMDPEG_CHECK_DELAY);
+
+ } while (--retries);
+
+ QLCWR32(adapter, CRB_CMDPEG_STATE, PHAN_INITIALIZE_FAILED);
+
+out_err:
+ dev_err(&adapter->pdev->dev, "Command Peg initialization not "
+ "complete, state: 0x%x.\n", val);
+ return -EIO;
+}
+
+static int
+qlcnic_receive_peg_ready(struct qlcnic_adapter *adapter)
+{
+ u32 val;
+ int retries = QLCNIC_RCVPEG_CHECK_RETRY_COUNT;
+
+ do {
+ val = QLCRD32(adapter, CRB_RCVPEG_STATE);
+
+ if (val == PHAN_PEG_RCV_INITIALIZED)
+ return 0;
+
+ msleep(QLCNIC_RCVPEG_CHECK_DELAY);
+
+ } while (--retries);
+
+ if (!retries) {
+ dev_err(&adapter->pdev->dev, "Receive Peg initialization not "
+ "complete, state: 0x%x.\n", val);
+ return -EIO;
+ }
+
return 0;
}
int
+qlcnic_check_fw_status(struct qlcnic_adapter *adapter)
+{
+ int err;
+
+ err = qlcnic_cmd_peg_ready(adapter);
+ if (err)
+ return err;
+
+ err = qlcnic_receive_peg_ready(adapter);
+ if (err)
+ return err;
+
+ QLCWR32(adapter, CRB_CMDPEG_STATE, PHAN_INITIALIZE_ACK);
+
+ return err;
+}
+
+int
qlcnic_setup_idc_param(struct qlcnic_adapter *adapter) {
int timeo;
@@ -557,12 +635,12 @@ qlcnic_setup_idc_param(struct qlcnic_adapter *adapter) {
}
adapter->physical_port = (val >> 2);
if (qlcnic_rom_fast_read(adapter, QLCNIC_ROM_DEV_INIT_TIMEOUT, &timeo))
- timeo = 30;
+ timeo = QLCNIC_INIT_TIMEOUT_SECS;
adapter->dev_init_timeo = timeo;
if (qlcnic_rom_fast_read(adapter, QLCNIC_ROM_DRV_RESET_TIMEOUT, &timeo))
- timeo = 10;
+ timeo = QLCNIC_RESET_TIMEOUT_SECS;
adapter->reset_ack_timeo = timeo;
@@ -906,54 +984,47 @@ qlcnic_get_bios_version(struct qlcnic_adapter *adapter)
return (bios_ver << 16) + ((bios_ver >> 8) & 0xff00) + (bios_ver >> 24);
}
-int
-qlcnic_need_fw_reset(struct qlcnic_adapter *adapter)
+static void qlcnic_rom_lock_recovery(struct qlcnic_adapter *adapter)
{
- u32 count, old_count;
- u32 val, version, major, minor, build;
- int i, timeout;
-
- if (adapter->need_fw_reset)
- return 1;
+ if (qlcnic_pcie_sem_lock(adapter, 2, QLCNIC_ROM_LOCK_ID))
+ dev_info(&adapter->pdev->dev, "Resetting rom_lock\n");
- /* last attempt had failed */
- if (QLCRD32(adapter, CRB_CMDPEG_STATE) == PHAN_INITIALIZE_FAILED)
- return 1;
+ qlcnic_pcie_sem_unlock(adapter, 2);
+}
- old_count = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER);
+static int
+qlcnic_check_fw_hearbeat(struct qlcnic_adapter *adapter)
+{
+ u32 heartbeat, ret = -EIO;
+ int retries = QLCNIC_HEARTBEAT_CHECK_RETRY_COUNT;
- for (i = 0; i < 10; i++) {
+ adapter->heartbeat = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER);
- timeout = msleep_interruptible(200);
- if (timeout) {
- QLCWR32(adapter, CRB_CMDPEG_STATE,
- PHAN_INITIALIZE_FAILED);
- return -EINTR;
+ do {
+ msleep(QLCNIC_HEARTBEAT_PERIOD_MSECS);
+ heartbeat = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER);
+ if (heartbeat != adapter->heartbeat) {
+ ret = QLCNIC_RCODE_SUCCESS;
+ break;
}
+ } while (--retries);
- count = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER);
- if (count != old_count)
- break;
- }
+ return ret;
+}
- /* firmware is dead */
- if (count == old_count)
+int
+qlcnic_need_fw_reset(struct qlcnic_adapter *adapter)
+{
+ if (qlcnic_check_fw_hearbeat(adapter)) {
+ qlcnic_rom_lock_recovery(adapter);
return 1;
+ }
- /* check if we have got newer or different file firmware */
- if (adapter->fw) {
-
- val = qlcnic_get_fw_version(adapter);
-
- version = QLCNIC_DECODE_VERSION(val);
-
- major = QLCRD32(adapter, QLCNIC_FW_VERSION_MAJOR);
- minor = QLCRD32(adapter, QLCNIC_FW_VERSION_MINOR);
- build = QLCRD32(adapter, QLCNIC_FW_VERSION_SUB);
+ if (adapter->need_fw_reset)
+ return 1;
- if (version > QLCNIC_VERSION_CODE(major, minor, build))
- return 1;
- }
+ if (adapter->fw)
+ return 1;
return 0;
}
@@ -1089,18 +1160,6 @@ qlcnic_validate_firmware(struct qlcnic_adapter *adapter)
return -EINVAL;
}
- /* check if flashed firmware is newer */
- if (qlcnic_rom_fast_read(adapter,
- QLCNIC_FW_VERSION_OFFSET, (int *)&val))
- return -EIO;
-
- val = QLCNIC_DECODE_VERSION(val);
- if (val > ver) {
- dev_info(&pdev->dev, "%s: firmware is older than flash\n",
- fw_name[fw_type]);
- return -EINVAL;
- }
-
QLCWR32(adapter, QLCNIC_CAM_RAM(0x1fc), QLCNIC_BDINFO_MAGIC);
return 0;
}
@@ -1162,78 +1221,6 @@ qlcnic_release_firmware(struct qlcnic_adapter *adapter)
adapter->fw = NULL;
}
-static int qlcnic_cmd_peg_ready(struct qlcnic_adapter *adapter)
-{
- u32 val;
- int retries = 60;
-
- do {
- val = QLCRD32(adapter, CRB_CMDPEG_STATE);
-
- switch (val) {
- case PHAN_INITIALIZE_COMPLETE:
- case PHAN_INITIALIZE_ACK:
- return 0;
- case PHAN_INITIALIZE_FAILED:
- goto out_err;
- default:
- break;
- }
-
- msleep(500);
-
- } while (--retries);
-
- QLCWR32(adapter, CRB_CMDPEG_STATE, PHAN_INITIALIZE_FAILED);
-
-out_err:
- dev_err(&adapter->pdev->dev, "Command Peg initialization not "
- "complete, state: 0x%x.\n", val);
- return -EIO;
-}
-
-static int
-qlcnic_receive_peg_ready(struct qlcnic_adapter *adapter)
-{
- u32 val;
- int retries = 2000;
-
- do {
- val = QLCRD32(adapter, CRB_RCVPEG_STATE);
-
- if (val == PHAN_PEG_RCV_INITIALIZED)
- return 0;
-
- msleep(10);
-
- } while (--retries);
-
- if (!retries) {
- dev_err(&adapter->pdev->dev, "Receive Peg initialization not "
- "complete, state: 0x%x.\n", val);
- return -EIO;
- }
-
- return 0;
-}
-
-int qlcnic_init_firmware(struct qlcnic_adapter *adapter)
-{
- int err;
-
- err = qlcnic_cmd_peg_ready(adapter);
- if (err)
- return err;
-
- err = qlcnic_receive_peg_ready(adapter);
- if (err)
- return err;
-
- QLCWR32(adapter, CRB_CMDPEG_STATE, PHAN_INITIALIZE_ACK);
-
- return err;
-}
-
static void
qlcnic_handle_linkevent(struct qlcnic_adapter *adapter,
struct qlcnic_fw_msg *msg)
@@ -1351,11 +1338,12 @@ static struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *adapter,
skb = buffer->skb;
- if (likely(adapter->rx_csum && cksum == STATUS_CKSUM_OK)) {
+ if (likely(adapter->rx_csum && (cksum == STATUS_CKSUM_OK ||
+ cksum == STATUS_CKSUM_LOOP))) {
adapter->stats.csummed++;
skb->ip_summed = CHECKSUM_UNNECESSARY;
} else {
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
}
skb->dev = adapter->netdev;
@@ -1365,6 +1353,31 @@ static struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *adapter,
return skb;
}
+static int
+qlcnic_check_rx_tagging(struct qlcnic_adapter *adapter, struct sk_buff *skb,
+ u16 *vlan_tag)
+{
+ struct ethhdr *eth_hdr;
+
+ if (!__vlan_get_tag(skb, vlan_tag)) {
+ eth_hdr = (struct ethhdr *) skb->data;
+ memmove(skb->data + VLAN_HLEN, eth_hdr, ETH_ALEN * 2);
+ skb_pull(skb, VLAN_HLEN);
+ }
+ if (!adapter->pvid)
+ return 0;
+
+ if (*vlan_tag == adapter->pvid) {
+ /* Outer vlan tag. Packet should follow non-vlan path */
+ *vlan_tag = 0xffff;
+ return 0;
+ }
+ if (adapter->flags & QLCNIC_TAGGING_ENABLED)
+ return 0;
+
+ return -EINVAL;
+}
+
static struct qlcnic_rx_buffer *
qlcnic_process_rcv(struct qlcnic_adapter *adapter,
struct qlcnic_host_sds_ring *sds_ring,
@@ -1376,6 +1389,7 @@ qlcnic_process_rcv(struct qlcnic_adapter *adapter,
struct sk_buff *skb;
struct qlcnic_host_rds_ring *rds_ring;
int index, length, cksum, pkt_offset;
+ u16 vid = 0xffff;
if (unlikely(ring >= adapter->max_rds_rings))
return NULL;
@@ -1404,9 +1418,18 @@ qlcnic_process_rcv(struct qlcnic_adapter *adapter,
if (pkt_offset)
skb_pull(skb, pkt_offset);
+ if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) {
+ adapter->stats.rxdropped++;
+ dev_kfree_skb(skb);
+ return buffer;
+ }
+
skb->protocol = eth_type_trans(skb, netdev);
- napi_gro_receive(&sds_ring->napi, skb);
+ if ((vid != 0xffff) && adapter->vlgrp)
+ vlan_gro_receive(&sds_ring->napi, adapter->vlgrp, vid, skb);
+ else
+ napi_gro_receive(&sds_ring->napi, skb);
adapter->stats.rx_pkts++;
adapter->stats.rxbytes += length;
@@ -1435,6 +1458,7 @@ qlcnic_process_lro(struct qlcnic_adapter *adapter,
int index;
u16 lro_length, length, data_offset;
u32 seq_number;
+ u16 vid = 0xffff;
if (unlikely(ring > adapter->max_rds_rings))
return NULL;
@@ -1466,6 +1490,13 @@ qlcnic_process_lro(struct qlcnic_adapter *adapter,
skb_put(skb, lro_length + data_offset);
skb_pull(skb, l2_hdr_offset);
+
+ if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) {
+ adapter->stats.rxdropped++;
+ dev_kfree_skb(skb);
+ return buffer;
+ }
+
skb->protocol = eth_type_trans(skb, netdev);
iph = (struct iphdr *)skb->data;
@@ -1480,7 +1511,10 @@ qlcnic_process_lro(struct qlcnic_adapter *adapter,
length = skb->len;
- netif_receive_skb(skb);
+ if ((vid != 0xffff) && adapter->vlgrp)
+ vlan_hwaccel_receive_skb(skb, adapter->vlgrp, vid);
+ else
+ netif_receive_skb(skb);
adapter->stats.lro_pkts++;
adapter->stats.lrobytes += length;
@@ -1584,8 +1618,6 @@ qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter, u32 ringid,
int producer, count = 0;
struct list_head *head;
- spin_lock(&rds_ring->lock);
-
producer = rds_ring->producer;
head = &rds_ring->free_list;
@@ -1615,7 +1647,6 @@ qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter, u32 ringid,
writel((producer-1) & (rds_ring->num_desc-1),
rds_ring->crb_rcv_producer);
}
- spin_unlock(&rds_ring->lock);
}
static void
@@ -1662,6 +1693,18 @@ qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter,
spin_unlock(&rds_ring->lock);
}
+static void dump_skb(struct sk_buff *skb)
+{
+ int i;
+ unsigned char *data = skb->data;
+
+ for (i = 0; i < skb->len; i++) {
+ printk("%02x ", data[i]);
+ if ((i & 0x0f) == 8)
+ printk("\n");
+ }
+}
+
static struct qlcnic_rx_buffer *
qlcnic_process_rcv_diag(struct qlcnic_adapter *adapter,
struct qlcnic_host_sds_ring *sds_ring,
@@ -1692,13 +1735,18 @@ qlcnic_process_rcv_diag(struct qlcnic_adapter *adapter,
if (!skb)
return buffer;
- skb_put(skb, rds_ring->skb_size);
+ if (length > rds_ring->skb_size)
+ skb_put(skb, rds_ring->skb_size);
+ else
+ skb_put(skb, length);
if (pkt_offset)
skb_pull(skb, pkt_offset);
if (!qlcnic_check_loopback_buff(skb->data))
adapter->diag_cnt++;
+ else
+ dump_skb(skb);
dev_kfree_skb_any(skb);
adapter->stats.rx_pkts++;
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index 66eea5972020..f047c7c48314 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -28,6 +28,7 @@
#include "qlcnic.h"
+#include <linux/swab.h>
#include <linux/dma-mapping.h>
#include <linux/if_vlan.h>
#include <net/ip.h>
@@ -45,10 +46,10 @@ char qlcnic_driver_name[] = "qlcnic";
static const char qlcnic_driver_string[] = "QLogic 1/10 GbE "
"Converged/Intelligent Ethernet Driver v" QLCNIC_LINUX_VERSIONID;
-static int port_mode = QLCNIC_PORT_MODE_AUTO_NEG;
-
-/* Default to restricted 1G auto-neg mode */
-static int wol_port_mode = 5;
+static struct workqueue_struct *qlcnic_wq;
+static int qlcnic_mac_learn;
+module_param(qlcnic_mac_learn, int, 0644);
+MODULE_PARM_DESC(qlcnic_mac_learn, "Mac Filter (0=disabled, 1=enabled)");
static int use_msi = 1;
module_param(use_msi, int, 0644);
@@ -94,7 +95,7 @@ static void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter);
static void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter);
static void qlcnic_idc_debug_info(struct qlcnic_adapter *adapter, u8 encoding);
-static void qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter);
+static void qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8);
static int qlcnic_can_start_firmware(struct qlcnic_adapter *adapter);
static irqreturn_t qlcnic_tmp_intr(int irq, void *data);
@@ -103,13 +104,17 @@ static irqreturn_t qlcnic_msi_intr(int irq, void *data);
static irqreturn_t qlcnic_msix_intr(int irq, void *data);
static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev);
-static void qlcnic_config_indev_addr(struct net_device *dev, unsigned long);
+static void qlcnic_restore_indev_addr(struct net_device *dev, unsigned long);
static int qlcnic_start_firmware(struct qlcnic_adapter *);
+static void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter);
+static void qlcnic_free_lb_filters_mem(struct qlcnic_adapter *adapter);
static void qlcnic_dev_set_npar_ready(struct qlcnic_adapter *);
static int qlcnicvf_config_led(struct qlcnic_adapter *, u32, u32);
static int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *, u32);
static int qlcnicvf_start_firmware(struct qlcnic_adapter *);
+static void qlcnic_set_netdev_features(struct qlcnic_adapter *,
+ struct qlcnic_esw_func_cfg *);
/* PCI Device ID Table */
#define ENTRY(device) \
{PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, (device)), \
@@ -164,7 +169,7 @@ qlcnic_alloc_sds_rings(struct qlcnic_recv_context *recv_ctx, int count)
recv_ctx->sds_rings = kzalloc(size, GFP_KERNEL);
- return (recv_ctx->sds_rings == NULL);
+ return recv_ctx->sds_rings == NULL;
}
static void
@@ -255,40 +260,6 @@ static void qlcnic_clear_stats(struct qlcnic_adapter *adapter)
memset(&adapter->stats, 0, sizeof(adapter->stats));
}
-static void qlcnic_set_port_mode(struct qlcnic_adapter *adapter)
-{
- u32 val, data;
-
- val = adapter->ahw.board_type;
- if ((val == QLCNIC_BRDTYPE_P3_HMEZ) ||
- (val == QLCNIC_BRDTYPE_P3_XG_LOM)) {
- if (port_mode == QLCNIC_PORT_MODE_802_3_AP) {
- data = QLCNIC_PORT_MODE_802_3_AP;
- QLCWR32(adapter, QLCNIC_PORT_MODE_ADDR, data);
- } else if (port_mode == QLCNIC_PORT_MODE_XG) {
- data = QLCNIC_PORT_MODE_XG;
- QLCWR32(adapter, QLCNIC_PORT_MODE_ADDR, data);
- } else if (port_mode == QLCNIC_PORT_MODE_AUTO_NEG_1G) {
- data = QLCNIC_PORT_MODE_AUTO_NEG_1G;
- QLCWR32(adapter, QLCNIC_PORT_MODE_ADDR, data);
- } else if (port_mode == QLCNIC_PORT_MODE_AUTO_NEG_XG) {
- data = QLCNIC_PORT_MODE_AUTO_NEG_XG;
- QLCWR32(adapter, QLCNIC_PORT_MODE_ADDR, data);
- } else {
- data = QLCNIC_PORT_MODE_AUTO_NEG;
- QLCWR32(adapter, QLCNIC_PORT_MODE_ADDR, data);
- }
-
- if ((wol_port_mode != QLCNIC_PORT_MODE_802_3_AP) &&
- (wol_port_mode != QLCNIC_PORT_MODE_XG) &&
- (wol_port_mode != QLCNIC_PORT_MODE_AUTO_NEG_1G) &&
- (wol_port_mode != QLCNIC_PORT_MODE_AUTO_NEG_XG)) {
- wol_port_mode = QLCNIC_PORT_MODE_AUTO_NEG;
- }
- QLCWR32(adapter, QLCNIC_WOL_PORT_MODE, wol_port_mode);
- }
-}
-
static void qlcnic_set_msix_bit(struct pci_dev *pdev, int enable)
{
u32 control;
@@ -320,7 +291,7 @@ qlcnic_read_mac_addr(struct qlcnic_adapter *adapter)
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
- if (adapter->nic_ops->get_mac_addr(adapter, mac_addr) != 0)
+ if (qlcnic_get_mac_address(adapter, mac_addr) != 0)
return -EIO;
memcpy(netdev->dev_addr, mac_addr, ETH_ALEN);
@@ -341,6 +312,9 @@ static int qlcnic_set_mac(struct net_device *netdev, void *p)
struct qlcnic_adapter *adapter = netdev_priv(netdev);
struct sockaddr *addr = p;
+ if ((adapter->flags & QLCNIC_MAC_OVERRIDE_DISABLED))
+ return -EOPNOTSUPP;
+
if (!is_valid_ether_addr(addr->sa_data))
return -EINVAL;
@@ -360,6 +334,13 @@ static int qlcnic_set_mac(struct net_device *netdev, void *p)
return 0;
}
+static void qlcnic_vlan_rx_register(struct net_device *netdev,
+ struct vlan_group *grp)
+{
+ struct qlcnic_adapter *adapter = netdev_priv(netdev);
+ adapter->vlgrp = grp;
+}
+
static const struct net_device_ops qlcnic_netdev_ops = {
.ndo_open = qlcnic_open,
.ndo_stop = qlcnic_close,
@@ -370,20 +351,19 @@ static const struct net_device_ops qlcnic_netdev_ops = {
.ndo_set_mac_address = qlcnic_set_mac,
.ndo_change_mtu = qlcnic_change_mtu,
.ndo_tx_timeout = qlcnic_tx_timeout,
+ .ndo_vlan_rx_register = qlcnic_vlan_rx_register,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = qlcnic_poll_controller,
#endif
};
static struct qlcnic_nic_template qlcnic_ops = {
- .get_mac_addr = qlcnic_get_mac_address,
.config_bridged_mode = qlcnic_config_bridged_mode,
.config_led = qlcnic_config_led,
.start_firmware = qlcnic_start_firmware
};
static struct qlcnic_nic_template qlcnic_vf_ops = {
- .get_mac_addr = qlcnic_get_mac_address,
.config_bridged_mode = qlcnicvf_config_bridged_mode,
.config_led = qlcnicvf_config_led,
.start_firmware = qlcnicvf_start_firmware
@@ -474,7 +454,7 @@ static int
qlcnic_init_pci_info(struct qlcnic_adapter *adapter)
{
struct qlcnic_pci_info *pci_info;
- int i, ret = 0, err;
+ int i, ret = 0;
u8 pfn;
pci_info = kcalloc(QLCNIC_MAX_PCI_FUNC, sizeof(*pci_info), GFP_KERNEL);
@@ -484,14 +464,14 @@ qlcnic_init_pci_info(struct qlcnic_adapter *adapter)
adapter->npars = kzalloc(sizeof(struct qlcnic_npar_info) *
QLCNIC_MAX_PCI_FUNC, GFP_KERNEL);
if (!adapter->npars) {
- err = -ENOMEM;
+ ret = -ENOMEM;
goto err_pci_info;
}
adapter->eswitch = kzalloc(sizeof(struct qlcnic_eswitch) *
QLCNIC_NIU_MAX_XG_PORTS, GFP_KERNEL);
if (!adapter->eswitch) {
- err = -ENOMEM;
+ ret = -ENOMEM;
goto err_npars;
}
@@ -503,10 +483,9 @@ qlcnic_init_pci_info(struct qlcnic_adapter *adapter)
pfn = pci_info[i].id;
if (pfn > QLCNIC_MAX_PCI_FUNC)
return QL_STATUS_INVALID_PARAM;
- adapter->npars[pfn].active = pci_info[i].active;
- adapter->npars[pfn].type = pci_info[i].type;
- adapter->npars[pfn].phy_port = pci_info[i].default_port;
- adapter->npars[pfn].mac_learning = DEFAULT_MAC_LEARN;
+ adapter->npars[pfn].active = (u8)pci_info[i].active;
+ adapter->npars[pfn].type = (u8)pci_info[i].type;
+ adapter->npars[pfn].phy_port = (u8)pci_info[i].default_port;
adapter->npars[pfn].min_bw = pci_info[i].tx_min_bw;
adapter->npars[pfn].max_bw = pci_info[i].tx_max_bw;
}
@@ -539,12 +518,10 @@ qlcnic_set_function_modes(struct qlcnic_adapter *adapter)
void __iomem *priv_op = adapter->ahw.pci_base0 + QLCNIC_DRV_OP_MODE;
/* If other drivers are not in use set their privilege level */
- ref_count = QLCRD32(adapter, QLCNIC_CRB_DEV_REF_COUNT);
+ ref_count = QLCRD32(adapter, QLCNIC_CRB_DRV_ACTIVE);
ret = qlcnic_api_lock(adapter);
if (ret)
goto err_lock;
- if (QLC_DEV_CLR_REF_CNT(ref_count, adapter->ahw.pci_func))
- goto err_npar;
if (qlcnic_config_npars) {
for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
@@ -562,18 +539,16 @@ qlcnic_set_function_modes(struct qlcnic_adapter *adapter)
adapter->ahw.pci_func));
}
writel(data, priv_op);
-err_npar:
qlcnic_api_unlock(adapter);
err_lock:
return ret;
}
-static u32
-qlcnic_get_driver_mode(struct qlcnic_adapter *adapter)
+static void
+qlcnic_check_vf(struct qlcnic_adapter *adapter)
{
void __iomem *msix_base_addr;
void __iomem *priv_op;
- struct qlcnic_info nic_info;
u32 func;
u32 msix_base;
u32 op_mode, priv_level;
@@ -588,20 +563,6 @@ qlcnic_get_driver_mode(struct qlcnic_adapter *adapter)
func = (func - msix_base)/QLCNIC_MSIX_TBL_PGSIZE;
adapter->ahw.pci_func = func;
- if (!qlcnic_get_nic_info(adapter, &nic_info, adapter->ahw.pci_func)) {
- adapter->capabilities = nic_info.capabilities;
-
- if (adapter->capabilities & BIT_6)
- adapter->flags |= QLCNIC_ESWITCH_ENABLED;
- else
- adapter->flags &= ~QLCNIC_ESWITCH_ENABLED;
- }
-
- if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) {
- adapter->nic_ops = &qlcnic_ops;
- return adapter->fw_hal_version;
- }
-
/* Determine function privilege level */
priv_op = adapter->ahw.pci_base0 + QLCNIC_DRV_OP_MODE;
op_mode = readl(priv_op);
@@ -610,37 +571,14 @@ qlcnic_get_driver_mode(struct qlcnic_adapter *adapter)
else
priv_level = QLC_DEV_GET_DRV(op_mode, adapter->ahw.pci_func);
- switch (priv_level) {
- case QLCNIC_MGMT_FUNC:
- adapter->op_mode = QLCNIC_MGMT_FUNC;
- adapter->nic_ops = &qlcnic_ops;
- qlcnic_init_pci_info(adapter);
- /* Set privilege level for other functions */
- qlcnic_set_function_modes(adapter);
- dev_info(&adapter->pdev->dev,
- "HAL Version: %d, Management function\n",
- adapter->fw_hal_version);
- break;
- case QLCNIC_PRIV_FUNC:
- adapter->op_mode = QLCNIC_PRIV_FUNC;
- dev_info(&adapter->pdev->dev,
- "HAL Version: %d, Privileged function\n",
- adapter->fw_hal_version);
- adapter->nic_ops = &qlcnic_ops;
- break;
- case QLCNIC_NON_PRIV_FUNC:
+ if (priv_level == QLCNIC_NON_PRIV_FUNC) {
adapter->op_mode = QLCNIC_NON_PRIV_FUNC;
dev_info(&adapter->pdev->dev,
"HAL Version: %d Non Privileged function\n",
adapter->fw_hal_version);
adapter->nic_ops = &qlcnic_vf_ops;
- break;
- default:
- dev_info(&adapter->pdev->dev, "Unknown function mode: %d\n",
- priv_level);
- return 0;
- }
- return adapter->fw_hal_version;
+ } else
+ adapter->nic_ops = &qlcnic_ops;
}
static int
@@ -673,10 +611,7 @@ qlcnic_setup_pci_map(struct qlcnic_adapter *adapter)
adapter->ahw.pci_base0 = mem_ptr0;
adapter->ahw.pci_len0 = pci_len0;
- if (!qlcnic_get_driver_mode(adapter)) {
- iounmap(adapter->ahw.pci_base0);
- return -EIO;
- }
+ qlcnic_check_vf(adapter);
adapter->ahw.ocm_win_crb = qlcnic_get_ioaddr(adapter,
QLCNIC_PCIX_PS_REG(PCIX_OCM_WINDOW_REG(adapter->ahw.pci_func)));
@@ -711,25 +646,7 @@ static void
qlcnic_check_options(struct qlcnic_adapter *adapter)
{
u32 fw_major, fw_minor, fw_build;
- char brd_name[QLCNIC_MAX_BOARD_NAME_LEN];
- char serial_num[32];
- int i, offset, val;
- int *ptr32;
struct pci_dev *pdev = adapter->pdev;
- struct qlcnic_info nic_info;
- adapter->driver_mismatch = 0;
-
- ptr32 = (int *)&serial_num;
- offset = QLCNIC_FW_SERIAL_NUM_OFFSET;
- for (i = 0; i < 8; i++) {
- if (qlcnic_rom_fast_read(adapter, offset, &val) == -1) {
- dev_err(&pdev->dev, "error reading board info\n");
- adapter->driver_mismatch = 1;
- return;
- }
- ptr32[i] = cpu_to_le32(val);
- offset += sizeof(u32);
- }
fw_major = QLCRD32(adapter, QLCNIC_FW_VERSION_MAJOR);
fw_minor = QLCRD32(adapter, QLCNIC_FW_VERSION_MINOR);
@@ -737,19 +654,9 @@ qlcnic_check_options(struct qlcnic_adapter *adapter)
adapter->fw_version = QLCNIC_VERSION_CODE(fw_major, fw_minor, fw_build);
- if (adapter->portnum == 0) {
- get_brd_name(adapter, brd_name);
-
- pr_info("%s: %s Board Chip rev 0x%x\n",
- module_name(THIS_MODULE),
- brd_name, adapter->ahw.revision_id);
- }
-
dev_info(&pdev->dev, "firmware v%d.%d.%d\n",
fw_major, fw_minor, fw_build);
- adapter->flags &= ~QLCNIC_LRO_ENABLED;
-
if (adapter->ahw.port_type == QLCNIC_XGBE) {
adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_10G;
adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G;
@@ -758,136 +665,364 @@ qlcnic_check_options(struct qlcnic_adapter *adapter)
adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_1G;
}
- if (!qlcnic_get_nic_info(adapter, &nic_info, adapter->ahw.pci_func)) {
- adapter->physical_port = nic_info.phys_port;
- adapter->switch_mode = nic_info.switch_mode;
- adapter->max_tx_ques = nic_info.max_tx_ques;
- adapter->max_rx_ques = nic_info.max_rx_ques;
- adapter->capabilities = nic_info.capabilities;
- adapter->max_mac_filters = nic_info.max_mac_filters;
- adapter->max_mtu = nic_info.max_mtu;
- }
-
adapter->msix_supported = !!use_msi_x;
adapter->rss_supported = !!use_msi_x;
adapter->num_txd = MAX_CMD_DESCRIPTORS;
- adapter->max_rds_rings = 2;
+ adapter->max_rds_rings = MAX_RDS_RINGS;
+}
+
+static int
+qlcnic_initialize_nic(struct qlcnic_adapter *adapter)
+{
+ int err;
+ struct qlcnic_info nic_info;
+
+ err = qlcnic_get_nic_info(adapter, &nic_info, adapter->ahw.pci_func);
+ if (err)
+ return err;
+
+ adapter->physical_port = (u8)nic_info.phys_port;
+ adapter->switch_mode = nic_info.switch_mode;
+ adapter->max_tx_ques = nic_info.max_tx_ques;
+ adapter->max_rx_ques = nic_info.max_rx_ques;
+ adapter->capabilities = nic_info.capabilities;
+ adapter->max_mac_filters = nic_info.max_mac_filters;
+ adapter->max_mtu = nic_info.max_mtu;
+
+ if (adapter->capabilities & BIT_6)
+ adapter->flags |= QLCNIC_ESWITCH_ENABLED;
+ else
+ adapter->flags &= ~QLCNIC_ESWITCH_ENABLED;
+
+ return err;
+}
+
+static void
+qlcnic_set_vlan_config(struct qlcnic_adapter *adapter,
+ struct qlcnic_esw_func_cfg *esw_cfg)
+{
+ if (esw_cfg->discard_tagged)
+ adapter->flags &= ~QLCNIC_TAGGING_ENABLED;
+ else
+ adapter->flags |= QLCNIC_TAGGING_ENABLED;
+
+ if (esw_cfg->vlan_id)
+ adapter->pvid = esw_cfg->vlan_id;
+ else
+ adapter->pvid = 0;
+}
+
+static void
+qlcnic_set_eswitch_port_features(struct qlcnic_adapter *adapter,
+ struct qlcnic_esw_func_cfg *esw_cfg)
+{
+ adapter->flags &= ~(QLCNIC_MACSPOOF | QLCNIC_MAC_OVERRIDE_DISABLED |
+ QLCNIC_PROMISC_DISABLED);
+
+ if (esw_cfg->mac_anti_spoof)
+ adapter->flags |= QLCNIC_MACSPOOF;
+
+ if (!esw_cfg->mac_override)
+ adapter->flags |= QLCNIC_MAC_OVERRIDE_DISABLED;
+
+ if (!esw_cfg->promisc_mode)
+ adapter->flags |= QLCNIC_PROMISC_DISABLED;
+
+ qlcnic_set_netdev_features(adapter, esw_cfg);
+}
+
+static int
+qlcnic_set_eswitch_port_config(struct qlcnic_adapter *adapter)
+{
+ struct qlcnic_esw_func_cfg esw_cfg;
+
+ if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
+ return 0;
+
+ esw_cfg.pci_func = adapter->ahw.pci_func;
+ if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg))
+ return -EIO;
+ qlcnic_set_vlan_config(adapter, &esw_cfg);
+ qlcnic_set_eswitch_port_features(adapter, &esw_cfg);
+
+ return 0;
+}
+
+static void
+qlcnic_set_netdev_features(struct qlcnic_adapter *adapter,
+ struct qlcnic_esw_func_cfg *esw_cfg)
+{
+ struct net_device *netdev = adapter->netdev;
+ unsigned long features, vlan_features;
+
+ features = (NETIF_F_SG | NETIF_F_IP_CSUM |
+ NETIF_F_IPV6_CSUM | NETIF_F_GRO);
+ vlan_features = (NETIF_F_SG | NETIF_F_IP_CSUM |
+ NETIF_F_IPV6_CSUM);
+
+ if (adapter->capabilities & QLCNIC_FW_CAPABILITY_TSO) {
+ features |= (NETIF_F_TSO | NETIF_F_TSO6);
+ vlan_features |= (NETIF_F_TSO | NETIF_F_TSO6);
+ }
+ if (adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO)
+ features |= NETIF_F_LRO;
+
+ if (esw_cfg->offload_flags & BIT_0) {
+ netdev->features |= features;
+ adapter->rx_csum = 1;
+ if (!(esw_cfg->offload_flags & BIT_1))
+ netdev->features &= ~NETIF_F_TSO;
+ if (!(esw_cfg->offload_flags & BIT_2))
+ netdev->features &= ~NETIF_F_TSO6;
+ } else {
+ netdev->features &= ~features;
+ adapter->rx_csum = 0;
+ }
+
+ netdev->vlan_features = (features & vlan_features);
+}
+
+static int
+qlcnic_check_eswitch_mode(struct qlcnic_adapter *adapter)
+{
+ void __iomem *priv_op;
+ u32 op_mode, priv_level;
+ int err = 0;
+
+ err = qlcnic_initialize_nic(adapter);
+ if (err)
+ return err;
+
+ if (adapter->flags & QLCNIC_ADAPTER_INITIALIZED)
+ return 0;
+
+ priv_op = adapter->ahw.pci_base0 + QLCNIC_DRV_OP_MODE;
+ op_mode = readl(priv_op);
+ priv_level = QLC_DEV_GET_DRV(op_mode, adapter->ahw.pci_func);
+
+ if (op_mode == QLC_DEV_DRV_DEFAULT)
+ priv_level = QLCNIC_MGMT_FUNC;
+ else
+ priv_level = QLC_DEV_GET_DRV(op_mode, adapter->ahw.pci_func);
+
+ if (adapter->flags & QLCNIC_ESWITCH_ENABLED) {
+ if (priv_level == QLCNIC_MGMT_FUNC) {
+ adapter->op_mode = QLCNIC_MGMT_FUNC;
+ err = qlcnic_init_pci_info(adapter);
+ if (err)
+ return err;
+ /* Set privilege level for other functions */
+ qlcnic_set_function_modes(adapter);
+ dev_info(&adapter->pdev->dev,
+ "HAL Version: %d, Management function\n",
+ adapter->fw_hal_version);
+ } else if (priv_level == QLCNIC_PRIV_FUNC) {
+ adapter->op_mode = QLCNIC_PRIV_FUNC;
+ dev_info(&adapter->pdev->dev,
+ "HAL Version: %d, Privileged function\n",
+ adapter->fw_hal_version);
+ }
+ }
+
+ adapter->flags |= QLCNIC_ADAPTER_INITIALIZED;
+
+ return err;
+}
+
+static int
+qlcnic_set_default_offload_settings(struct qlcnic_adapter *adapter)
+{
+ struct qlcnic_esw_func_cfg esw_cfg;
+ struct qlcnic_npar_info *npar;
+ u8 i;
+
+ if (adapter->need_fw_reset)
+ return 0;
+
+ for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
+ if (adapter->npars[i].type != QLCNIC_TYPE_NIC)
+ continue;
+ memset(&esw_cfg, 0, sizeof(struct qlcnic_esw_func_cfg));
+ esw_cfg.pci_func = i;
+ esw_cfg.offload_flags = BIT_0;
+ esw_cfg.mac_override = BIT_0;
+ esw_cfg.promisc_mode = BIT_0;
+ if (adapter->capabilities & QLCNIC_FW_CAPABILITY_TSO)
+ esw_cfg.offload_flags |= (BIT_1 | BIT_2);
+ if (qlcnic_config_switch_port(adapter, &esw_cfg))
+ return -EIO;
+ npar = &adapter->npars[i];
+ npar->pvid = esw_cfg.vlan_id;
+ npar->mac_override = esw_cfg.mac_override;
+ npar->mac_anti_spoof = esw_cfg.mac_anti_spoof;
+ npar->discard_tagged = esw_cfg.discard_tagged;
+ npar->promisc_mode = esw_cfg.promisc_mode;
+ npar->offload_flags = esw_cfg.offload_flags;
+ }
+
+ return 0;
+}
+
+static int
+qlcnic_reset_eswitch_config(struct qlcnic_adapter *adapter,
+ struct qlcnic_npar_info *npar, int pci_func)
+{
+ struct qlcnic_esw_func_cfg esw_cfg;
+ esw_cfg.op_mode = QLCNIC_PORT_DEFAULTS;
+ esw_cfg.pci_func = pci_func;
+ esw_cfg.vlan_id = npar->pvid;
+ esw_cfg.mac_override = npar->mac_override;
+ esw_cfg.discard_tagged = npar->discard_tagged;
+ esw_cfg.mac_anti_spoof = npar->mac_anti_spoof;
+ esw_cfg.offload_flags = npar->offload_flags;
+ esw_cfg.promisc_mode = npar->promisc_mode;
+ if (qlcnic_config_switch_port(adapter, &esw_cfg))
+ return -EIO;
+
+ esw_cfg.op_mode = QLCNIC_ADD_VLAN;
+ if (qlcnic_config_switch_port(adapter, &esw_cfg))
+ return -EIO;
+
+ return 0;
}
static int
qlcnic_reset_npar_config(struct qlcnic_adapter *adapter)
{
- int i, err = 0;
+ int i, err;
struct qlcnic_npar_info *npar;
struct qlcnic_info nic_info;
- if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED) ||
- !adapter->need_fw_reset)
+ if (!adapter->need_fw_reset)
return 0;
- if (adapter->op_mode == QLCNIC_MGMT_FUNC) {
- /* Set the NPAR config data after FW reset */
- for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
- npar = &adapter->npars[i];
- if (npar->type != QLCNIC_TYPE_NIC)
- continue;
- err = qlcnic_get_nic_info(adapter, &nic_info, i);
- if (err)
- goto err_out;
- nic_info.min_tx_bw = npar->min_bw;
- nic_info.max_tx_bw = npar->max_bw;
- err = qlcnic_set_nic_info(adapter, &nic_info);
+ /* Set the NPAR config data after FW reset */
+ for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
+ npar = &adapter->npars[i];
+ if (npar->type != QLCNIC_TYPE_NIC)
+ continue;
+ err = qlcnic_get_nic_info(adapter, &nic_info, i);
+ if (err)
+ return err;
+ nic_info.min_tx_bw = npar->min_bw;
+ nic_info.max_tx_bw = npar->max_bw;
+ err = qlcnic_set_nic_info(adapter, &nic_info);
+ if (err)
+ return err;
+
+ if (npar->enable_pm) {
+ err = qlcnic_config_port_mirroring(adapter,
+ npar->dest_npar, 1, i);
if (err)
- goto err_out;
+ return err;
+ }
+ err = qlcnic_reset_eswitch_config(adapter, npar, i);
+ if (err)
+ return err;
+ }
+ return 0;
+}
- if (npar->enable_pm) {
- err = qlcnic_config_port_mirroring(adapter,
- npar->dest_npar, 1, i);
- if (err)
- goto err_out;
+static int qlcnic_check_npar_opertional(struct qlcnic_adapter *adapter)
+{
+ u8 npar_opt_timeo = QLCNIC_DEV_NPAR_OPER_TIMEO;
+ u32 npar_state;
- }
- npar->mac_learning = DEFAULT_MAC_LEARN;
- npar->host_vlan_tag = 0;
- npar->promisc_mode = 0;
- npar->discard_tagged = 0;
- npar->vlan_id = 0;
- }
+ if (adapter->op_mode == QLCNIC_MGMT_FUNC)
+ return 0;
+
+ npar_state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
+ while (npar_state != QLCNIC_DEV_NPAR_OPER && --npar_opt_timeo) {
+ msleep(1000);
+ npar_state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
}
-err_out:
+ if (!npar_opt_timeo) {
+ dev_err(&adapter->pdev->dev,
+ "Waiting for NPAR state to opertional timeout\n");
+ return -EIO;
+ }
+ return 0;
+}
+
+static int
+qlcnic_set_mgmt_operations(struct qlcnic_adapter *adapter)
+{
+ int err;
+
+ if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED) ||
+ adapter->op_mode != QLCNIC_MGMT_FUNC)
+ return 0;
+
+ err = qlcnic_set_default_offload_settings(adapter);
+ if (err)
+ return err;
+
+ err = qlcnic_reset_npar_config(adapter);
+ if (err)
+ return err;
+
+ qlcnic_dev_set_npar_ready(adapter);
+
return err;
}
static int
qlcnic_start_firmware(struct qlcnic_adapter *adapter)
{
- int val, err, first_boot;
+ int err;
err = qlcnic_can_start_firmware(adapter);
if (err < 0)
return err;
else if (!err)
- goto wait_init;
-
- first_boot = QLCRD32(adapter, QLCNIC_CAM_RAM(0x1fc));
- if (first_boot == 0x55555555)
- /* This is the first boot after power up */
- QLCWR32(adapter, QLCNIC_CAM_RAM(0x1fc), QLCNIC_BDINFO_MAGIC);
+ goto check_fw_status;
if (load_fw_file)
qlcnic_request_firmware(adapter);
else {
- if (qlcnic_check_flash_fw_ver(adapter))
+ err = qlcnic_check_flash_fw_ver(adapter);
+ if (err)
goto err_out;
adapter->fw_type = QLCNIC_FLASH_ROMIMAGE;
}
err = qlcnic_need_fw_reset(adapter);
- if (err < 0)
- goto err_out;
if (err == 0)
- goto wait_init;
+ goto check_fw_status;
- if (first_boot != 0x55555555) {
- QLCWR32(adapter, CRB_CMDPEG_STATE, 0);
- QLCWR32(adapter, CRB_RCVPEG_STATE, 0);
- qlcnic_pinit_from_rom(adapter);
- msleep(1);
- }
-
- QLCWR32(adapter, QLCNIC_PEG_HALT_STATUS1, 0);
- QLCWR32(adapter, QLCNIC_PEG_HALT_STATUS2, 0);
-
- qlcnic_set_port_mode(adapter);
+ err = qlcnic_pinit_from_rom(adapter);
+ if (err)
+ goto err_out;
err = qlcnic_load_firmware(adapter);
if (err)
goto err_out;
qlcnic_release_firmware(adapter);
+ QLCWR32(adapter, CRB_DRIVER_VERSION, QLCNIC_DRIVER_VERSION);
- val = (_QLCNIC_LINUX_MAJOR << 16)
- | ((_QLCNIC_LINUX_MINOR << 8))
- | (_QLCNIC_LINUX_SUBVERSION);
- QLCWR32(adapter, CRB_DRIVER_VERSION, val);
-
-wait_init:
- /* Handshake with the card before we register the devices. */
- err = qlcnic_init_firmware(adapter);
+check_fw_status:
+ err = qlcnic_check_fw_status(adapter);
if (err)
goto err_out;
QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_READY);
qlcnic_idc_debug_info(adapter, 1);
- qlcnic_check_options(adapter);
- if (qlcnic_reset_npar_config(adapter))
+ err = qlcnic_check_eswitch_mode(adapter);
+ if (err) {
+ dev_err(&adapter->pdev->dev,
+ "Memory allocation failed for eswitch\n");
+ goto err_out;
+ }
+ err = qlcnic_set_mgmt_operations(adapter);
+ if (err)
goto err_out;
- qlcnic_dev_set_npar_ready(adapter);
+ qlcnic_check_options(adapter);
adapter->need_fw_reset = 0;
qlcnic_release_firmware(adapter);
@@ -896,6 +1031,7 @@ wait_init:
err_out:
QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_FAILED);
dev_err(&adapter->pdev->dev, "Device state set to failed\n");
+
qlcnic_release_firmware(adapter);
return err;
}
@@ -979,6 +1115,8 @@ __qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev)
if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
return 0;
+ if (qlcnic_set_eswitch_port_config(adapter))
+ return -EIO;
if (qlcnic_fw_create_ctx(adapter))
return -EIO;
@@ -998,7 +1136,7 @@ __qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev)
qlcnic_config_intr_coalesce(adapter);
- if (adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO)
+ if (netdev->features & NETIF_F_LRO)
qlcnic_config_hw_lro(adapter, QLCNIC_LRO_ENABLED);
qlcnic_napi_enable(adapter);
@@ -1041,6 +1179,9 @@ __qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev)
qlcnic_free_mac_list(adapter);
+ if (adapter->fhash.fnum)
+ qlcnic_delete_lb_filters(adapter);
+
qlcnic_nic_set_promisc(adapter, QLCNIC_NIU_NON_PROMISC_MODE);
qlcnic_napi_disable(adapter);
@@ -1277,7 +1418,7 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter,
SET_ETHTOOL_OPS(netdev, &qlcnic_ethtool_ops);
netdev->features |= (NETIF_F_SG | NETIF_F_IP_CSUM |
- NETIF_F_IPV6_CSUM | NETIF_F_GRO);
+ NETIF_F_IPV6_CSUM | NETIF_F_GRO | NETIF_F_HW_VLAN_RX);
netdev->vlan_features |= (NETIF_F_SG | NETIF_F_IP_CSUM |
NETIF_F_IPV6_CSUM);
@@ -1296,12 +1437,8 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter,
if (adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO)
netdev->features |= NETIF_F_LRO;
-
netdev->irq = adapter->msix_entries[0].vector;
- if (qlcnic_read_mac_addr(adapter))
- dev_warn(&pdev->dev, "failed to read mac addr\n");
-
netif_carrier_off(netdev);
netif_stop_queue(netdev);
@@ -1338,6 +1475,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
int err;
uint8_t revision_id;
uint8_t pci_using_dac;
+ char brd_name[QLCNIC_MAX_BOARD_NAME_LEN];
err = pci_enable_device(pdev);
if (err)
@@ -1395,10 +1533,8 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_out_iounmap;
}
- if (qlcnic_read_mac_addr(adapter))
- dev_warn(&pdev->dev, "failed to read mac addr\n");
-
- if (qlcnic_setup_idc_param(adapter))
+ err = qlcnic_setup_idc_param(adapter);
+ if (err)
goto err_out_iounmap;
err = adapter->nic_ops->start_firmware(adapter);
@@ -1407,6 +1543,17 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_out_decr_ref;
}
+ if (qlcnic_read_mac_addr(adapter))
+ dev_warn(&pdev->dev, "failed to read mac addr\n");
+
+ if (adapter->portnum == 0) {
+ get_brd_name(adapter, brd_name);
+
+ pr_info("%s: %s Board Chip rev 0x%x\n",
+ module_name(THIS_MODULE),
+ brd_name, adapter->ahw.revision_id);
+ }
+
qlcnic_clear_stats(adapter);
qlcnic_setup_intr(adapter);
@@ -1430,6 +1577,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
break;
}
+ qlcnic_alloc_lb_filters_mem(adapter);
qlcnic_create_diag_entries(adapter);
return 0;
@@ -1438,7 +1586,7 @@ err_out_disable_msi:
qlcnic_teardown_intr(adapter);
err_out_decr_ref:
- qlcnic_clr_all_drv_state(adapter);
+ qlcnic_clr_all_drv_state(adapter, 0);
err_out_iounmap:
qlcnic_cleanup_pci_map(adapter);
@@ -1477,10 +1625,12 @@ static void __devexit qlcnic_remove(struct pci_dev *pdev)
if (adapter->eswitch != NULL)
kfree(adapter->eswitch);
- qlcnic_clr_all_drv_state(adapter);
+ qlcnic_clr_all_drv_state(adapter, 0);
clear_bit(__QLCNIC_RESETTING, &adapter->state);
+ qlcnic_free_lb_filters_mem(adapter);
+
qlcnic_teardown_intr(adapter);
qlcnic_remove_diag_entries(adapter);
@@ -1509,7 +1659,7 @@ static int __qlcnic_shutdown(struct pci_dev *pdev)
if (netif_running(netdev))
qlcnic_down(adapter, netdev);
- qlcnic_clr_all_drv_state(adapter);
+ qlcnic_clr_all_drv_state(adapter, 0);
clear_bit(__QLCNIC_RESETTING, &adapter->state);
@@ -1573,7 +1723,7 @@ qlcnic_resume(struct pci_dev *pdev)
if (err)
goto done;
- qlcnic_config_indev_addr(netdev, NETDEV_UP);
+ qlcnic_restore_indev_addr(netdev, NETDEV_UP);
}
done:
netif_device_attach(netdev);
@@ -1587,9 +1737,6 @@ static int qlcnic_open(struct net_device *netdev)
struct qlcnic_adapter *adapter = netdev_priv(netdev);
int err;
- if (adapter->driver_mismatch)
- return -EIO;
-
err = qlcnic_attach(adapter);
if (err)
return err;
@@ -1619,6 +1766,121 @@ static int qlcnic_close(struct net_device *netdev)
}
static void
+qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter)
+{
+ void *head;
+ int i;
+
+ if (!qlcnic_mac_learn)
+ return;
+
+ spin_lock_init(&adapter->mac_learn_lock);
+
+ head = kcalloc(QLCNIC_LB_MAX_FILTERS, sizeof(struct hlist_head),
+ GFP_KERNEL);
+ if (!head)
+ return;
+
+ adapter->fhash.fmax = QLCNIC_LB_MAX_FILTERS;
+ adapter->fhash.fhead = (struct hlist_head *)head;
+
+ for (i = 0; i < adapter->fhash.fmax; i++)
+ INIT_HLIST_HEAD(&adapter->fhash.fhead[i]);
+}
+
+static void qlcnic_free_lb_filters_mem(struct qlcnic_adapter *adapter)
+{
+ if (adapter->fhash.fmax && adapter->fhash.fhead)
+ kfree(adapter->fhash.fhead);
+
+ adapter->fhash.fhead = NULL;
+ adapter->fhash.fmax = 0;
+}
+
+static void qlcnic_change_filter(struct qlcnic_adapter *adapter,
+ u64 uaddr, __le16 vlan_id, struct qlcnic_host_tx_ring *tx_ring)
+{
+ struct cmd_desc_type0 *hwdesc;
+ struct qlcnic_nic_req *req;
+ struct qlcnic_mac_req *mac_req;
+ struct qlcnic_vlan_req *vlan_req;
+ u32 producer;
+ u64 word;
+
+ producer = tx_ring->producer;
+ hwdesc = &tx_ring->desc_head[tx_ring->producer];
+
+ req = (struct qlcnic_nic_req *)hwdesc;
+ memset(req, 0, sizeof(struct qlcnic_nic_req));
+ req->qhdr = cpu_to_le64(QLCNIC_REQUEST << 23);
+
+ word = QLCNIC_MAC_EVENT | ((u64)(adapter->portnum) << 16);
+ req->req_hdr = cpu_to_le64(word);
+
+ mac_req = (struct qlcnic_mac_req *)&(req->words[0]);
+ mac_req->op = vlan_id ? QLCNIC_MAC_VLAN_ADD : QLCNIC_MAC_ADD;
+ memcpy(mac_req->mac_addr, &uaddr, ETH_ALEN);
+
+ vlan_req = (struct qlcnic_vlan_req *)&req->words[1];
+ vlan_req->vlan_id = vlan_id;
+
+ tx_ring->producer = get_next_index(producer, tx_ring->num_desc);
+}
+
+#define QLCNIC_MAC_HASH(MAC)\
+ ((((MAC) & 0x70000) >> 0x10) | (((MAC) & 0x70000000000ULL) >> 0x25))
+
+static void
+qlcnic_send_filter(struct qlcnic_adapter *adapter,
+ struct qlcnic_host_tx_ring *tx_ring,
+ struct cmd_desc_type0 *first_desc,
+ struct sk_buff *skb)
+{
+ struct ethhdr *phdr = (struct ethhdr *)(skb->data);
+ struct qlcnic_filter *fil, *tmp_fil;
+ struct hlist_node *tmp_hnode, *n;
+ struct hlist_head *head;
+ u64 src_addr = 0;
+ __le16 vlan_id = 0;
+ u8 hindex;
+
+ if (!compare_ether_addr(phdr->h_source, adapter->mac_addr))
+ return;
+
+ if (adapter->fhash.fnum >= adapter->fhash.fmax)
+ return;
+
+ /* Only NPAR capable devices support vlan based learning*/
+ if (adapter->flags & QLCNIC_ESWITCH_ENABLED)
+ vlan_id = first_desc->vlan_TCI;
+ memcpy(&src_addr, phdr->h_source, ETH_ALEN);
+ hindex = QLCNIC_MAC_HASH(src_addr) & (QLCNIC_LB_MAX_FILTERS - 1);
+ head = &(adapter->fhash.fhead[hindex]);
+
+ hlist_for_each_entry_safe(tmp_fil, tmp_hnode, n, head, fnode) {
+ if (!memcmp(tmp_fil->faddr, &src_addr, ETH_ALEN) &&
+ tmp_fil->vlan_id == vlan_id) {
+ tmp_fil->ftime = jiffies;
+ return;
+ }
+ }
+
+ fil = kzalloc(sizeof(struct qlcnic_filter), GFP_ATOMIC);
+ if (!fil)
+ return;
+
+ qlcnic_change_filter(adapter, src_addr, vlan_id, tx_ring);
+
+ fil->ftime = jiffies;
+ fil->vlan_id = vlan_id;
+ memcpy(fil->faddr, &src_addr, ETH_ALEN);
+ spin_lock(&adapter->mac_learn_lock);
+ hlist_add_head(&(fil->fnode), head);
+ adapter->fhash.fnum++;
+ spin_unlock(&adapter->mac_learn_lock);
+}
+
+static void
qlcnic_tso_check(struct net_device *netdev,
struct qlcnic_host_tx_ring *tx_ring,
struct cmd_desc_type0 *first_desc,
@@ -1626,26 +1888,14 @@ qlcnic_tso_check(struct net_device *netdev,
{
u8 opcode = TX_ETHER_PKT;
__be16 protocol = skb->protocol;
- u16 flags = 0, vid = 0;
- int copied, offset, copy_len, hdr_len = 0, tso = 0, vlan_oob = 0;
+ u16 flags = 0;
+ int copied, offset, copy_len, hdr_len = 0, tso = 0;
struct cmd_desc_type0 *hwdesc;
struct vlan_ethhdr *vh;
struct qlcnic_adapter *adapter = netdev_priv(netdev);
u32 producer = tx_ring->producer;
-
- if (protocol == cpu_to_be16(ETH_P_8021Q)) {
-
- vh = (struct vlan_ethhdr *)skb->data;
- protocol = vh->h_vlan_encapsulated_proto;
- flags = FLAGS_VLAN_TAGGED;
-
- } else if (vlan_tx_tag_present(skb)) {
-
- flags = FLAGS_VLAN_OOB;
- vid = vlan_tx_tag_get(skb);
- qlcnic_set_tx_vlan_tci(first_desc, vid);
- vlan_oob = 1;
- }
+ __le16 vlan_oob = first_desc->flags_opcode &
+ cpu_to_le16(FLAGS_VLAN_OOB);
if (*(skb->data) & BIT_0) {
flags |= BIT_0;
@@ -1716,7 +1966,8 @@ qlcnic_tso_check(struct net_device *netdev,
vh = (struct vlan_ethhdr *)((char *)hwdesc + 2);
skb_copy_from_linear_data(skb, vh, 12);
vh->h_vlan_proto = htons(ETH_P_8021Q);
- vh->h_vlan_TCI = htons(vid);
+ vh->h_vlan_TCI = (__be16)swab16((u16)first_desc->vlan_TCI);
+
skb_copy_from_linear_data_offset(skb, 12,
(char *)vh + 16, copy_len - 16);
@@ -1796,11 +2047,47 @@ out_err:
return -ENOMEM;
}
+static int
+qlcnic_check_tx_tagging(struct qlcnic_adapter *adapter,
+ struct sk_buff *skb,
+ struct cmd_desc_type0 *first_desc)
+{
+ u8 opcode = 0;
+ u16 flags = 0;
+ __be16 protocol = skb->protocol;
+ struct vlan_ethhdr *vh;
+
+ if (protocol == cpu_to_be16(ETH_P_8021Q)) {
+ vh = (struct vlan_ethhdr *)skb->data;
+ protocol = vh->h_vlan_encapsulated_proto;
+ flags = FLAGS_VLAN_TAGGED;
+ qlcnic_set_tx_vlan_tci(first_desc, ntohs(vh->h_vlan_TCI));
+ } else if (vlan_tx_tag_present(skb)) {
+ flags = FLAGS_VLAN_OOB;
+ qlcnic_set_tx_vlan_tci(first_desc, vlan_tx_tag_get(skb));
+ }
+ if (unlikely(adapter->pvid)) {
+ if (first_desc->vlan_TCI &&
+ !(adapter->flags & QLCNIC_TAGGING_ENABLED))
+ return -EIO;
+ if (first_desc->vlan_TCI &&
+ (adapter->flags & QLCNIC_TAGGING_ENABLED))
+ goto set_flags;
+
+ flags = FLAGS_VLAN_OOB;
+ qlcnic_set_tx_vlan_tci(first_desc, adapter->pvid);
+ }
+set_flags:
+ qlcnic_set_tx_flags_opcode(first_desc, flags, opcode);
+ return 0;
+}
+
static inline void
qlcnic_clear_cmddesc(u64 *desc)
{
desc[0] = 0ULL;
desc[2] = 0ULL;
+ desc[7] = 0ULL;
}
netdev_tx_t
@@ -1812,6 +2099,7 @@ qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
struct qlcnic_skb_frag *buffrag;
struct cmd_desc_type0 *hwdesc, *first_desc;
struct pci_dev *pdev;
+ struct ethhdr *phdr;
int i, k;
u32 producer;
@@ -1823,6 +2111,13 @@ qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
return NETDEV_TX_BUSY;
}
+ if (adapter->flags & QLCNIC_MACSPOOF) {
+ phdr = (struct ethhdr *)skb->data;
+ if (compare_ether_addr(phdr->h_source,
+ adapter->mac_addr))
+ goto drop_packet;
+ }
+
frag_count = skb_shinfo(skb)->nr_frags + 1;
/* 4 fragments per cmd des */
@@ -1844,6 +2139,12 @@ qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
pdev = adapter->pdev;
+ first_desc = hwdesc = &tx_ring->desc_head[producer];
+ qlcnic_clear_cmddesc((u64 *)hwdesc);
+
+ if (qlcnic_check_tx_tagging(adapter, skb, first_desc))
+ goto drop_packet;
+
if (qlcnic_map_tx_skb(pdev, skb, pbuf)) {
adapter->stats.tx_dma_map_error++;
goto drop_packet;
@@ -1852,9 +2153,6 @@ qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
pbuf->skb = skb;
pbuf->frag_count = frag_count;
- first_desc = hwdesc = &tx_ring->desc_head[producer];
- qlcnic_clear_cmddesc((u64 *)hwdesc);
-
qlcnic_set_tx_frags_len(first_desc, frag_count, skb->len);
qlcnic_set_tx_port(first_desc, adapter->portnum);
@@ -1893,6 +2191,9 @@ qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
qlcnic_tso_check(netdev, tx_ring, first_desc, skb);
+ if (qlcnic_mac_learn)
+ qlcnic_send_filter(adapter, tx_ring, first_desc, skb);
+
qlcnic_update_cmd_producer(adapter, tx_ring);
adapter->stats.txbytes += skb->len;
@@ -1947,14 +2248,14 @@ void qlcnic_advert_link_change(struct qlcnic_adapter *adapter, int linkup)
struct net_device *netdev = adapter->netdev;
if (adapter->ahw.linkup && !linkup) {
- dev_info(&netdev->dev, "NIC Link is down\n");
+ netdev_info(netdev, "NIC Link is down\n");
adapter->ahw.linkup = 0;
if (netif_running(netdev)) {
netif_carrier_off(netdev);
netif_stop_queue(netdev);
}
} else if (!adapter->ahw.linkup && linkup) {
- dev_info(&netdev->dev, "NIC Link is up\n");
+ netdev_info(netdev, "NIC Link is up\n");
adapter->ahw.linkup = 1;
if (netif_running(netdev)) {
netif_carrier_on(netdev);
@@ -2258,18 +2559,22 @@ qlcnic_clr_drv_state(struct qlcnic_adapter *adapter)
}
static void
-qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter)
+qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8 failed)
{
u32 val;
if (qlcnic_api_lock(adapter))
goto err;
- val = QLCRD32(adapter, QLCNIC_CRB_DEV_REF_COUNT);
+ val = QLCRD32(adapter, QLCNIC_CRB_DRV_ACTIVE);
QLC_DEV_CLR_REF_CNT(val, adapter->portnum);
- QLCWR32(adapter, QLCNIC_CRB_DEV_REF_COUNT, val);
+ QLCWR32(adapter, QLCNIC_CRB_DRV_ACTIVE, val);
- if (!(val & 0x11111111))
+ if (failed) {
+ QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_FAILED);
+ dev_info(&adapter->pdev->dev,
+ "Device state set to Failed. Please Reboot\n");
+ } else if (!(val & 0x11111111))
QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_COLD);
val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE);
@@ -2290,7 +2595,7 @@ qlcnic_check_drv_state(struct qlcnic_adapter *adapter)
int act, state;
state = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE);
- act = QLCRD32(adapter, QLCNIC_CRB_DEV_REF_COUNT);
+ act = QLCRD32(adapter, QLCNIC_CRB_DRV_ACTIVE);
if (((state & 0x11111111) == (act & 0x11111111)) ||
((act & 0x11111111) == ((state >> 1) & 0x11111111)))
@@ -2325,10 +2630,10 @@ qlcnic_can_start_firmware(struct qlcnic_adapter *adapter)
if (qlcnic_api_lock(adapter))
return -1;
- val = QLCRD32(adapter, QLCNIC_CRB_DEV_REF_COUNT);
+ val = QLCRD32(adapter, QLCNIC_CRB_DRV_ACTIVE);
if (!(val & (1 << (portnum * 4)))) {
QLC_DEV_SET_REF_CNT(val, portnum);
- QLCWR32(adapter, QLCNIC_CRB_DEV_REF_COUNT, val);
+ QLCWR32(adapter, QLCNIC_CRB_DRV_ACTIVE, val);
}
prev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
@@ -2403,13 +2708,14 @@ qlcnic_fwinit_work(struct work_struct *work)
{
struct qlcnic_adapter *adapter = container_of(work,
struct qlcnic_adapter, fw_work.work);
- u32 dev_state = 0xf, npar_state;
+ u32 dev_state = 0xf;
if (qlcnic_api_lock(adapter))
goto err_ret;
dev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
- if (dev_state == QLCNIC_DEV_QUISCENT) {
+ if (dev_state == QLCNIC_DEV_QUISCENT ||
+ dev_state == QLCNIC_DEV_NEED_QUISCENT) {
qlcnic_api_unlock(adapter);
qlcnic_schedule_work(adapter, qlcnic_fwinit_work,
FW_POLL_DELAY * 2);
@@ -2417,16 +2723,8 @@ qlcnic_fwinit_work(struct work_struct *work)
}
if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) {
- npar_state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
- if (npar_state == QLCNIC_DEV_NPAR_RDY) {
- qlcnic_api_unlock(adapter);
- goto wait_npar;
- } else {
- qlcnic_schedule_work(adapter, qlcnic_fwinit_work,
- FW_POLL_DELAY);
- qlcnic_api_unlock(adapter);
- return;
- }
+ qlcnic_api_unlock(adapter);
+ goto wait_npar;
}
if (adapter->fw_wait_cnt++ > adapter->reset_ack_timeo) {
@@ -2439,18 +2737,6 @@ qlcnic_fwinit_work(struct work_struct *work)
skip_ack_check:
dev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
- if (dev_state == QLCNIC_DEV_NEED_QUISCENT) {
- QLCWR32(adapter, QLCNIC_CRB_DEV_STATE,
- QLCNIC_DEV_QUISCENT);
- qlcnic_schedule_work(adapter, qlcnic_fwinit_work,
- FW_POLL_DELAY * 2);
- QLCDB(adapter, DRV, "Quiscing the driver\n");
- qlcnic_idc_debug_info(adapter, 0);
-
- qlcnic_api_unlock(adapter);
- return;
- }
-
if (dev_state == QLCNIC_DEV_NEED_RESET) {
QLCWR32(adapter, QLCNIC_CRB_DEV_STATE,
QLCNIC_DEV_INITIALIZING);
@@ -2463,6 +2749,7 @@ skip_ack_check:
if (!adapter->nic_ops->start_firmware(adapter)) {
qlcnic_schedule_work(adapter, qlcnic_attach_work, 0);
+ adapter->fw_wait_cnt = 0;
return;
}
goto err_ret;
@@ -2475,27 +2762,25 @@ wait_npar:
QLCDB(adapter, HW, "Func waiting: Device state=%u\n", dev_state);
switch (dev_state) {
- case QLCNIC_DEV_QUISCENT:
- case QLCNIC_DEV_NEED_QUISCENT:
- case QLCNIC_DEV_NEED_RESET:
- qlcnic_schedule_work(adapter,
- qlcnic_fwinit_work, FW_POLL_DELAY);
- return;
- case QLCNIC_DEV_FAILED:
- break;
-
- default:
+ case QLCNIC_DEV_READY:
if (!adapter->nic_ops->start_firmware(adapter)) {
qlcnic_schedule_work(adapter, qlcnic_attach_work, 0);
+ adapter->fw_wait_cnt = 0;
return;
}
+ case QLCNIC_DEV_FAILED:
+ break;
+ default:
+ qlcnic_schedule_work(adapter,
+ qlcnic_fwinit_work, FW_POLL_DELAY);
+ return;
}
err_ret:
dev_err(&adapter->pdev->dev, "Fwinit work failed state=%u "
"fw_wait_cnt=%u\n", dev_state, adapter->fw_wait_cnt);
netif_device_attach(adapter->netdev);
- qlcnic_clr_all_drv_state(adapter);
+ qlcnic_clr_all_drv_state(adapter, 0);
}
static void
@@ -2508,7 +2793,12 @@ qlcnic_detach_work(struct work_struct *work)
netif_device_detach(netdev);
- qlcnic_down(adapter, netdev);
+ /* Dont grab rtnl lock during Quiscent mode */
+ if (adapter->dev_state == QLCNIC_DEV_NEED_QUISCENT) {
+ if (netif_running(netdev))
+ __qlcnic_down(adapter, netdev);
+ } else
+ qlcnic_down(adapter, netdev);
status = QLCRD32(adapter, QLCNIC_PEG_HALT_STATUS1);
@@ -2531,8 +2821,78 @@ err_ret:
dev_err(&adapter->pdev->dev, "detach failed; status=%d temp=%d\n",
status, adapter->temp);
netif_device_attach(netdev);
- qlcnic_clr_all_drv_state(adapter);
+ qlcnic_clr_all_drv_state(adapter, 1);
+}
+
+/*Transit NPAR state to NON Operational */
+static void
+qlcnic_set_npar_non_operational(struct qlcnic_adapter *adapter)
+{
+ u32 state;
+
+ state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
+ if (state == QLCNIC_DEV_NPAR_NON_OPER)
+ return;
+
+ if (qlcnic_api_lock(adapter))
+ return;
+ QLCWR32(adapter, QLCNIC_CRB_DEV_NPAR_STATE, QLCNIC_DEV_NPAR_NON_OPER);
+ qlcnic_api_unlock(adapter);
+}
+
+/* Caller should held RESETTING bit.
+ * This should be call in sync with qlcnic_request_quiscent_mode.
+ */
+void qlcnic_clear_quiscent_mode(struct qlcnic_adapter *adapter)
+{
+ qlcnic_clr_drv_state(adapter);
+ qlcnic_api_lock(adapter);
+ QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_READY);
+ qlcnic_api_unlock(adapter);
+}
+
+/* Caller should held RESETTING bit.
+ */
+int qlcnic_request_quiscent_mode(struct qlcnic_adapter *adapter)
+{
+ u8 timeo = adapter->dev_init_timeo / 2;
+ u32 state;
+
+ if (qlcnic_api_lock(adapter))
+ return -EIO;
+
+ state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
+ if (state != QLCNIC_DEV_READY)
+ return -EIO;
+
+ QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_NEED_QUISCENT);
+ qlcnic_api_unlock(adapter);
+ QLCDB(adapter, DRV, "NEED QUISCENT state set\n");
+ qlcnic_idc_debug_info(adapter, 0);
+ qlcnic_set_drv_state(adapter, QLCNIC_DEV_NEED_QUISCENT);
+
+ do {
+ msleep(2000);
+ state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
+ if (state == QLCNIC_DEV_QUISCENT)
+ return 0;
+ if (!qlcnic_check_drv_state(adapter)) {
+ if (qlcnic_api_lock(adapter))
+ return -EIO;
+ QLCWR32(adapter, QLCNIC_CRB_DEV_STATE,
+ QLCNIC_DEV_QUISCENT);
+ qlcnic_api_unlock(adapter);
+ QLCDB(adapter, DRV, "QUISCENT mode set\n");
+ return 0;
+ }
+ } while (--timeo);
+
+ dev_err(&adapter->pdev->dev, "Failed to quiesce device, DRV_STATE=%08x"
+ " DRV_ACTIVE=%08x\n", QLCRD32(adapter, QLCNIC_CRB_DRV_STATE),
+ QLCRD32(adapter, QLCNIC_CRB_DRV_ACTIVE));
+ qlcnic_clear_quiscent_mode(adapter);
+ return -EIO;
}
/*Transit to RESET state from READY state only */
@@ -2553,6 +2913,7 @@ qlcnic_dev_request_reset(struct qlcnic_adapter *adapter)
qlcnic_idc_debug_info(adapter, 0);
}
+ QLCWR32(adapter, QLCNIC_CRB_DEV_NPAR_STATE, QLCNIC_DEV_NPAR_NON_OPER);
qlcnic_api_unlock(adapter);
}
@@ -2560,21 +2921,11 @@ qlcnic_dev_request_reset(struct qlcnic_adapter *adapter)
static void
qlcnic_dev_set_npar_ready(struct qlcnic_adapter *adapter)
{
- u32 state;
-
- if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED) ||
- adapter->op_mode == QLCNIC_NON_PRIV_FUNC)
- return;
if (qlcnic_api_lock(adapter))
return;
- state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
-
- if (state != QLCNIC_DEV_NPAR_RDY) {
- QLCWR32(adapter, QLCNIC_CRB_DEV_NPAR_STATE,
- QLCNIC_DEV_NPAR_RDY);
- QLCDB(adapter, DRV, "NPAR READY state set\n");
- }
+ QLCWR32(adapter, QLCNIC_CRB_DEV_NPAR_STATE, QLCNIC_DEV_NPAR_OPER);
+ QLCDB(adapter, DRV, "NPAR operational state set\n");
qlcnic_api_unlock(adapter);
}
@@ -2587,7 +2938,8 @@ qlcnic_schedule_work(struct qlcnic_adapter *adapter,
return;
INIT_DELAYED_WORK(&adapter->fw_work, func);
- schedule_delayed_work(&adapter->fw_work, round_jiffies_relative(delay));
+ queue_delayed_work(qlcnic_wq, &adapter->fw_work,
+ round_jiffies_relative(delay));
}
static void
@@ -2605,12 +2957,26 @@ qlcnic_attach_work(struct work_struct *work)
struct qlcnic_adapter *adapter = container_of(work,
struct qlcnic_adapter, fw_work.work);
struct net_device *netdev = adapter->netdev;
+ u32 npar_state;
+ if (adapter->op_mode != QLCNIC_MGMT_FUNC) {
+ npar_state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
+ if (adapter->fw_wait_cnt++ > QLCNIC_DEV_NPAR_OPER_TIMEO)
+ qlcnic_clr_all_drv_state(adapter, 0);
+ else if (npar_state != QLCNIC_DEV_NPAR_OPER)
+ qlcnic_schedule_work(adapter, qlcnic_attach_work,
+ FW_POLL_DELAY);
+ else
+ goto attach;
+ QLCDB(adapter, DRV, "Waiting for NPAR state to operational\n");
+ return;
+ }
+attach:
if (netif_running(netdev)) {
if (qlcnic_up(adapter, netdev))
goto done;
- qlcnic_config_indev_addr(netdev, NETDEV_UP);
+ qlcnic_restore_indev_addr(netdev, NETDEV_UP);
}
done:
@@ -2626,7 +2992,7 @@ done:
static int
qlcnic_check_health(struct qlcnic_adapter *adapter)
{
- u32 state = 0, heartbit;
+ u32 state = 0, heartbeat;
struct net_device *netdev = adapter->netdev;
if (qlcnic_check_temp(adapter))
@@ -2636,12 +3002,15 @@ qlcnic_check_health(struct qlcnic_adapter *adapter)
qlcnic_dev_request_reset(adapter);
state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
- if (state == QLCNIC_DEV_NEED_RESET || state == QLCNIC_DEV_NEED_QUISCENT)
+ if (state == QLCNIC_DEV_NEED_RESET) {
+ qlcnic_set_npar_non_operational(adapter);
adapter->need_fw_reset = 1;
+ } else if (state == QLCNIC_DEV_NEED_QUISCENT)
+ goto detach;
- heartbit = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER);
- if (heartbit != adapter->heartbit) {
- adapter->heartbit = heartbit;
+ heartbeat = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER);
+ if (heartbeat != adapter->heartbeat) {
+ adapter->heartbeat = heartbeat;
adapter->fw_fail_cnt = 0;
if (adapter->need_fw_reset)
goto detach;
@@ -2692,6 +3061,9 @@ qlcnic_fw_poll_work(struct work_struct *work)
if (qlcnic_check_health(adapter))
return;
+ if (adapter->fhash.fnum)
+ qlcnic_prune_lb_filters(adapter);
+
reschedule:
qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, FW_POLL_DELAY);
}
@@ -2738,7 +3110,7 @@ static int qlcnic_attach_func(struct pci_dev *pdev)
if (qlcnic_api_lock(adapter))
return -EINVAL;
- if (first_func) {
+ if (adapter->op_mode != QLCNIC_NON_PRIV_FUNC && first_func) {
adapter->need_fw_reset = 1;
set_bit(__QLCNIC_START_FW, &adapter->state);
QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_INITIALIZING);
@@ -2756,7 +3128,7 @@ static int qlcnic_attach_func(struct pci_dev *pdev)
if (netif_running(netdev)) {
err = qlcnic_attach(adapter);
if (err) {
- qlcnic_clr_all_drv_state(adapter);
+ qlcnic_clr_all_drv_state(adapter, 1);
clear_bit(__QLCNIC_AER, &adapter->state);
netif_device_attach(netdev);
return err;
@@ -2766,7 +3138,7 @@ static int qlcnic_attach_func(struct pci_dev *pdev)
if (err)
goto done;
- qlcnic_config_indev_addr(netdev, NETDEV_UP);
+ qlcnic_restore_indev_addr(netdev, NETDEV_UP);
}
done:
netif_device_attach(netdev);
@@ -2822,7 +3194,6 @@ static void qlcnic_io_resume(struct pci_dev *pdev)
FW_POLL_DELAY);
}
-
static int
qlcnicvf_start_firmware(struct qlcnic_adapter *adapter)
{
@@ -2832,8 +3203,20 @@ qlcnicvf_start_firmware(struct qlcnic_adapter *adapter)
if (err)
return err;
+ err = qlcnic_check_npar_opertional(adapter);
+ if (err)
+ return err;
+
+ err = qlcnic_initialize_nic(adapter);
+ if (err)
+ return err;
+
qlcnic_check_options(adapter);
+ err = qlcnic_set_eswitch_port_config(adapter);
+ if (err)
+ return err;
+
adapter->need_fw_reset = 0;
return err;
@@ -3093,9 +3476,6 @@ validate_pm_config(struct qlcnic_adapter *adapter,
if (adapter->npars[dest_pci_func].type != QLCNIC_TYPE_NIC)
return QL_STATUS_INVALID_PARAM;
- if (!IS_VALID_MODE(pm_cfg[i].action))
- return QL_STATUS_INVALID_PARAM;
-
s_esw_id = adapter->npars[src_pci_func].phy_port;
d_esw_id = adapter->npars[dest_pci_func].phy_port;
@@ -3129,7 +3509,7 @@ qlcnic_sysfs_write_pm_config(struct file *filp, struct kobject *kobj,
return ret;
for (i = 0; i < count; i++) {
pci_func = pm_cfg[i].pci_func;
- action = pm_cfg[i].action;
+ action = !!pm_cfg[i].action;
id = adapter->npars[pci_func].phy_port;
ret = qlcnic_config_port_mirroring(adapter, id,
action, pci_func);
@@ -3140,7 +3520,7 @@ qlcnic_sysfs_write_pm_config(struct file *filp, struct kobject *kobj,
for (i = 0; i < count; i++) {
pci_func = pm_cfg[i].pci_func;
id = adapter->npars[pci_func].phy_port;
- adapter->npars[pci_func].enable_pm = pm_cfg[i].action;
+ adapter->npars[pci_func].enable_pm = !!pm_cfg[i].action;
adapter->npars[pci_func].dest_npar = id;
}
return size;
@@ -3172,30 +3552,46 @@ qlcnic_sysfs_read_pm_config(struct file *filp, struct kobject *kobj,
static int
validate_esw_config(struct qlcnic_adapter *adapter,
- struct qlcnic_esw_func_cfg *esw_cfg, int count)
+ struct qlcnic_esw_func_cfg *esw_cfg, int count)
{
+ u32 op_mode;
u8 pci_func;
int i;
+ op_mode = readl(adapter->ahw.pci_base0 + QLCNIC_DRV_OP_MODE);
+
for (i = 0; i < count; i++) {
pci_func = esw_cfg[i].pci_func;
if (pci_func >= QLCNIC_MAX_PCI_FUNC)
return QL_STATUS_INVALID_PARAM;
- if (adapter->npars[i].type != QLCNIC_TYPE_NIC)
- return QL_STATUS_INVALID_PARAM;
+ if (adapter->op_mode == QLCNIC_MGMT_FUNC)
+ if (adapter->npars[pci_func].type != QLCNIC_TYPE_NIC)
+ return QL_STATUS_INVALID_PARAM;
- if (esw_cfg->host_vlan_tag == 1)
+ switch (esw_cfg[i].op_mode) {
+ case QLCNIC_PORT_DEFAULTS:
+ if (QLC_DEV_GET_DRV(op_mode, pci_func) !=
+ QLCNIC_NON_PRIV_FUNC) {
+ esw_cfg[i].mac_anti_spoof = 0;
+ esw_cfg[i].mac_override = 1;
+ esw_cfg[i].promisc_mode = 1;
+ }
+ break;
+ case QLCNIC_ADD_VLAN:
if (!IS_VALID_VLAN(esw_cfg[i].vlan_id))
return QL_STATUS_INVALID_PARAM;
-
- if (!IS_VALID_MODE(esw_cfg[i].promisc_mode)
- || !IS_VALID_MODE(esw_cfg[i].host_vlan_tag)
- || !IS_VALID_MODE(esw_cfg[i].mac_learning)
- || !IS_VALID_MODE(esw_cfg[i].discard_tagged))
+ if (!esw_cfg[i].op_type)
+ return QL_STATUS_INVALID_PARAM;
+ break;
+ case QLCNIC_DEL_VLAN:
+ if (!esw_cfg[i].op_type)
+ return QL_STATUS_INVALID_PARAM;
+ break;
+ default:
return QL_STATUS_INVALID_PARAM;
+ }
}
-
return 0;
}
@@ -3206,8 +3602,9 @@ qlcnic_sysfs_write_esw_config(struct file *file, struct kobject *kobj,
struct device *dev = container_of(kobj, struct device, kobj);
struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
struct qlcnic_esw_func_cfg *esw_cfg;
+ struct qlcnic_npar_info *npar;
int count, rem, i, ret;
- u8 id, pci_func;
+ u8 pci_func, op_mode = 0;
count = size / sizeof(struct qlcnic_esw_func_cfg);
rem = size % sizeof(struct qlcnic_esw_func_cfg);
@@ -3220,30 +3617,55 @@ qlcnic_sysfs_write_esw_config(struct file *file, struct kobject *kobj,
return ret;
for (i = 0; i < count; i++) {
- pci_func = esw_cfg[i].pci_func;
- id = adapter->npars[pci_func].phy_port;
- ret = qlcnic_config_switch_port(adapter, id,
- esw_cfg[i].host_vlan_tag,
- esw_cfg[i].discard_tagged,
- esw_cfg[i].promisc_mode,
- esw_cfg[i].mac_learning,
- esw_cfg[i].pci_func,
- esw_cfg[i].vlan_id);
- if (ret)
- return ret;
+ if (adapter->op_mode == QLCNIC_MGMT_FUNC)
+ if (qlcnic_config_switch_port(adapter, &esw_cfg[i]))
+ return QL_STATUS_INVALID_PARAM;
+
+ if (adapter->ahw.pci_func != esw_cfg[i].pci_func)
+ continue;
+
+ op_mode = esw_cfg[i].op_mode;
+ qlcnic_get_eswitch_port_config(adapter, &esw_cfg[i]);
+ esw_cfg[i].op_mode = op_mode;
+ esw_cfg[i].pci_func = adapter->ahw.pci_func;
+
+ switch (esw_cfg[i].op_mode) {
+ case QLCNIC_PORT_DEFAULTS:
+ qlcnic_set_eswitch_port_features(adapter, &esw_cfg[i]);
+ break;
+ case QLCNIC_ADD_VLAN:
+ qlcnic_set_vlan_config(adapter, &esw_cfg[i]);
+ break;
+ case QLCNIC_DEL_VLAN:
+ esw_cfg[i].vlan_id = 0;
+ qlcnic_set_vlan_config(adapter, &esw_cfg[i]);
+ break;
+ }
}
+ if (adapter->op_mode != QLCNIC_MGMT_FUNC)
+ goto out;
+
for (i = 0; i < count; i++) {
pci_func = esw_cfg[i].pci_func;
- adapter->npars[pci_func].promisc_mode = esw_cfg[i].promisc_mode;
- adapter->npars[pci_func].mac_learning = esw_cfg[i].mac_learning;
- adapter->npars[pci_func].vlan_id = esw_cfg[i].vlan_id;
- adapter->npars[pci_func].discard_tagged =
- esw_cfg[i].discard_tagged;
- adapter->npars[pci_func].host_vlan_tag =
- esw_cfg[i].host_vlan_tag;
+ npar = &adapter->npars[pci_func];
+ switch (esw_cfg[i].op_mode) {
+ case QLCNIC_PORT_DEFAULTS:
+ npar->promisc_mode = esw_cfg[i].promisc_mode;
+ npar->mac_override = esw_cfg[i].mac_override;
+ npar->offload_flags = esw_cfg[i].offload_flags;
+ npar->mac_anti_spoof = esw_cfg[i].mac_anti_spoof;
+ npar->discard_tagged = esw_cfg[i].discard_tagged;
+ break;
+ case QLCNIC_ADD_VLAN:
+ npar->pvid = esw_cfg[i].vlan_id;
+ break;
+ case QLCNIC_DEL_VLAN:
+ npar->pvid = 0;
+ break;
+ }
}
-
+out:
return size;
}
@@ -3254,7 +3676,7 @@ qlcnic_sysfs_read_esw_config(struct file *file, struct kobject *kobj,
struct device *dev = container_of(kobj, struct device, kobj);
struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
struct qlcnic_esw_func_cfg esw_cfg[QLCNIC_MAX_PCI_FUNC];
- int i;
+ u8 i;
if (size != sizeof(esw_cfg))
return QL_STATUS_INVALID_PARAM;
@@ -3262,12 +3684,9 @@ qlcnic_sysfs_read_esw_config(struct file *file, struct kobject *kobj,
for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
if (adapter->npars[i].type != QLCNIC_TYPE_NIC)
continue;
-
- esw_cfg[i].host_vlan_tag = adapter->npars[i].host_vlan_tag;
- esw_cfg[i].promisc_mode = adapter->npars[i].promisc_mode;
- esw_cfg[i].discard_tagged = adapter->npars[i].discard_tagged;
- esw_cfg[i].vlan_id = adapter->npars[i].vlan_id;
- esw_cfg[i].mac_learning = adapter->npars[i].mac_learning;
+ esw_cfg[i].pci_func = i;
+ if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg[i]))
+ return QL_STATUS_INVALID_PARAM;
}
memcpy(buf, &esw_cfg, size);
@@ -3357,7 +3776,7 @@ qlcnic_sysfs_read_npar_config(struct file *file, struct kobject *kobj,
return ret;
np_cfg[i].pci_func = i;
- np_cfg[i].op_mode = nic_info.op_mode;
+ np_cfg[i].op_mode = (u8)nic_info.op_mode;
np_cfg[i].port_num = nic_info.phys_port;
np_cfg[i].fw_capab = nic_info.capabilities;
np_cfg[i].min_bw = nic_info.min_tx_bw ;
@@ -3370,6 +3789,115 @@ qlcnic_sysfs_read_npar_config(struct file *file, struct kobject *kobj,
}
static ssize_t
+qlcnic_sysfs_get_port_stats(struct file *file, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ struct qlcnic_esw_statistics port_stats;
+ int ret;
+
+ if (size != sizeof(struct qlcnic_esw_statistics))
+ return QL_STATUS_INVALID_PARAM;
+
+ if (offset >= QLCNIC_MAX_PCI_FUNC)
+ return QL_STATUS_INVALID_PARAM;
+
+ memset(&port_stats, 0, size);
+ ret = qlcnic_get_port_stats(adapter, offset, QLCNIC_QUERY_RX_COUNTER,
+ &port_stats.rx);
+ if (ret)
+ return ret;
+
+ ret = qlcnic_get_port_stats(adapter, offset, QLCNIC_QUERY_TX_COUNTER,
+ &port_stats.tx);
+ if (ret)
+ return ret;
+
+ memcpy(buf, &port_stats, size);
+ return size;
+}
+
+static ssize_t
+qlcnic_sysfs_get_esw_stats(struct file *file, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ struct qlcnic_esw_statistics esw_stats;
+ int ret;
+
+ if (size != sizeof(struct qlcnic_esw_statistics))
+ return QL_STATUS_INVALID_PARAM;
+
+ if (offset >= QLCNIC_NIU_MAX_XG_PORTS)
+ return QL_STATUS_INVALID_PARAM;
+
+ memset(&esw_stats, 0, size);
+ ret = qlcnic_get_eswitch_stats(adapter, offset, QLCNIC_QUERY_RX_COUNTER,
+ &esw_stats.rx);
+ if (ret)
+ return ret;
+
+ ret = qlcnic_get_eswitch_stats(adapter, offset, QLCNIC_QUERY_TX_COUNTER,
+ &esw_stats.tx);
+ if (ret)
+ return ret;
+
+ memcpy(buf, &esw_stats, size);
+ return size;
+}
+
+static ssize_t
+qlcnic_sysfs_clear_esw_stats(struct file *file, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ int ret;
+
+ if (offset >= QLCNIC_NIU_MAX_XG_PORTS)
+ return QL_STATUS_INVALID_PARAM;
+
+ ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_ESWITCH, offset,
+ QLCNIC_QUERY_RX_COUNTER);
+ if (ret)
+ return ret;
+
+ ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_ESWITCH, offset,
+ QLCNIC_QUERY_TX_COUNTER);
+ if (ret)
+ return ret;
+
+ return size;
+}
+
+static ssize_t
+qlcnic_sysfs_clear_port_stats(struct file *file, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
+{
+
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+ int ret;
+
+ if (offset >= QLCNIC_MAX_PCI_FUNC)
+ return QL_STATUS_INVALID_PARAM;
+
+ ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_PORT, offset,
+ QLCNIC_QUERY_RX_COUNTER);
+ if (ret)
+ return ret;
+
+ ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_PORT, offset,
+ QLCNIC_QUERY_TX_COUNTER);
+ if (ret)
+ return ret;
+
+ return size;
+}
+
+static ssize_t
qlcnic_sysfs_read_pci_config(struct file *file, struct kobject *kobj,
struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
{
@@ -3418,6 +3946,20 @@ static struct bin_attribute bin_attr_pci_config = {
.write = NULL,
};
+static struct bin_attribute bin_attr_port_stats = {
+ .attr = {.name = "port_stats", .mode = (S_IRUGO | S_IWUSR)},
+ .size = 0,
+ .read = qlcnic_sysfs_get_port_stats,
+ .write = qlcnic_sysfs_clear_port_stats,
+};
+
+static struct bin_attribute bin_attr_esw_stats = {
+ .attr = {.name = "esw_stats", .mode = (S_IRUGO | S_IWUSR)},
+ .size = 0,
+ .read = qlcnic_sysfs_get_esw_stats,
+ .write = qlcnic_sysfs_clear_esw_stats,
+};
+
static struct bin_attribute bin_attr_esw_config = {
.attr = {.name = "esw_config", .mode = (S_IRUGO | S_IWUSR)},
.size = 0,
@@ -3457,6 +3999,9 @@ qlcnic_create_diag_entries(struct qlcnic_adapter *adapter)
{
struct device *dev = &adapter->pdev->dev;
+ if (device_create_bin_file(dev, &bin_attr_port_stats))
+ dev_info(dev, "failed to create port stats sysfs entry");
+
if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC)
return;
if (device_create_file(dev, &dev_attr_diag_mode))
@@ -3465,18 +4010,20 @@ qlcnic_create_diag_entries(struct qlcnic_adapter *adapter)
dev_info(dev, "failed to create crb sysfs entry\n");
if (device_create_bin_file(dev, &bin_attr_mem))
dev_info(dev, "failed to create mem sysfs entry\n");
- if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED) ||
- adapter->op_mode != QLCNIC_MGMT_FUNC)
+ if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
+ return;
+ if (device_create_bin_file(dev, &bin_attr_esw_config))
+ dev_info(dev, "failed to create esw config sysfs entry");
+ if (adapter->op_mode != QLCNIC_MGMT_FUNC)
return;
if (device_create_bin_file(dev, &bin_attr_pci_config))
dev_info(dev, "failed to create pci config sysfs entry");
if (device_create_bin_file(dev, &bin_attr_npar_config))
dev_info(dev, "failed to create npar config sysfs entry");
- if (device_create_bin_file(dev, &bin_attr_esw_config))
- dev_info(dev, "failed to create esw config sysfs entry");
if (device_create_bin_file(dev, &bin_attr_pm_config))
dev_info(dev, "failed to create pm config sysfs entry");
-
+ if (device_create_bin_file(dev, &bin_attr_esw_stats))
+ dev_info(dev, "failed to create eswitch stats sysfs entry");
}
static void
@@ -3484,18 +4031,22 @@ qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter)
{
struct device *dev = &adapter->pdev->dev;
+ device_remove_bin_file(dev, &bin_attr_port_stats);
+
if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC)
return;
device_remove_file(dev, &dev_attr_diag_mode);
device_remove_bin_file(dev, &bin_attr_crb);
device_remove_bin_file(dev, &bin_attr_mem);
- if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED) ||
- adapter->op_mode != QLCNIC_MGMT_FUNC)
+ if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
+ return;
+ device_remove_bin_file(dev, &bin_attr_esw_config);
+ if (adapter->op_mode != QLCNIC_MGMT_FUNC)
return;
device_remove_bin_file(dev, &bin_attr_pci_config);
device_remove_bin_file(dev, &bin_attr_npar_config);
- device_remove_bin_file(dev, &bin_attr_esw_config);
device_remove_bin_file(dev, &bin_attr_pm_config);
+ device_remove_bin_file(dev, &bin_attr_esw_stats);
}
#ifdef CONFIG_INET
@@ -3503,10 +4054,10 @@ qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter)
#define is_qlcnic_netdev(dev) (dev->netdev_ops == &qlcnic_netdev_ops)
static void
-qlcnic_config_indev_addr(struct net_device *dev, unsigned long event)
+qlcnic_config_indev_addr(struct qlcnic_adapter *adapter,
+ struct net_device *dev, unsigned long event)
{
struct in_device *indev;
- struct qlcnic_adapter *adapter = netdev_priv(dev);
indev = in_dev_get(dev);
if (!indev)
@@ -3530,6 +4081,27 @@ qlcnic_config_indev_addr(struct net_device *dev, unsigned long event)
in_dev_put(indev);
}
+static void
+qlcnic_restore_indev_addr(struct net_device *netdev, unsigned long event)
+{
+ struct qlcnic_adapter *adapter = netdev_priv(netdev);
+ struct net_device *dev;
+ u16 vid;
+
+ qlcnic_config_indev_addr(adapter, netdev, event);
+
+ if (!adapter->vlgrp)
+ return;
+
+ for (vid = 0; vid < VLAN_N_VID; vid++) {
+ dev = vlan_group_get_device(adapter->vlgrp, vid);
+ if (!dev)
+ continue;
+
+ qlcnic_config_indev_addr(adapter, dev, event);
+ }
+}
+
static int qlcnic_netdev_event(struct notifier_block *this,
unsigned long event, void *ptr)
{
@@ -3556,7 +4128,7 @@ recheck:
if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
goto done;
- qlcnic_config_indev_addr(dev, event);
+ qlcnic_config_indev_addr(adapter, dev, event);
done:
return NOTIFY_DONE;
}
@@ -3573,7 +4145,7 @@ qlcnic_inetaddr_event(struct notifier_block *this,
dev = ifa->ifa_dev ? ifa->ifa_dev->dev : NULL;
recheck:
- if (dev == NULL || !netif_running(dev))
+ if (dev == NULL)
goto done;
if (dev->priv_flags & IFF_802_1Q_VLAN) {
@@ -3616,7 +4188,7 @@ static struct notifier_block qlcnic_inetaddr_cb = {
};
#else
static void
-qlcnic_config_indev_addr(struct net_device *dev, unsigned long event)
+qlcnic_restore_indev_addr(struct net_device *dev, unsigned long event)
{ }
#endif
static struct pci_error_handlers qlcnic_err_handler = {
@@ -3645,6 +4217,12 @@ static int __init qlcnic_init_module(void)
printk(KERN_INFO "%s\n", qlcnic_driver_string);
+ qlcnic_wq = create_singlethread_workqueue("qlcnic");
+ if (qlcnic_wq == NULL) {
+ printk(KERN_ERR "qlcnic: cannot create workqueue\n");
+ return -ENOMEM;
+ }
+
#ifdef CONFIG_INET
register_netdevice_notifier(&qlcnic_netdev_cb);
register_inetaddr_notifier(&qlcnic_inetaddr_cb);
@@ -3656,6 +4234,7 @@ static int __init qlcnic_init_module(void)
unregister_inetaddr_notifier(&qlcnic_inetaddr_cb);
unregister_netdevice_notifier(&qlcnic_netdev_cb);
#endif
+ destroy_workqueue(qlcnic_wq);
}
return ret;
@@ -3672,6 +4251,7 @@ static void __exit qlcnic_exit_module(void)
unregister_inetaddr_notifier(&qlcnic_inetaddr_cb);
unregister_netdevice_notifier(&qlcnic_netdev_cb);
#endif
+ destroy_workqueue(qlcnic_wq);
}
module_exit(qlcnic_exit_module);
diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c
index 5f89e83501f4..ba0053d8515e 100644
--- a/drivers/net/qlge/qlge_main.c
+++ b/drivers/net/qlge/qlge_main.c
@@ -1566,7 +1566,7 @@ static void ql_process_mac_rx_page(struct ql_adapter *qdev,
rx_ring->rx_packets++;
rx_ring->rx_bytes += skb->len;
skb->protocol = eth_type_trans(skb, ndev);
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
if (qdev->rx_csum &&
!(ib_mac_rsp->flags1 & IB_MAC_CSUM_ERR_MASK)) {
@@ -1676,7 +1676,7 @@ static void ql_process_mac_rx_skb(struct ql_adapter *qdev,
rx_ring->rx_packets++;
rx_ring->rx_bytes += skb->len;
skb->protocol = eth_type_trans(skb, ndev);
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
/* If rx checksum is on, and there are no
* csum or frame errors.
@@ -1996,7 +1996,7 @@ static void ql_process_mac_split_rx_intr(struct ql_adapter *qdev,
}
skb->protocol = eth_type_trans(skb, ndev);
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
/* If rx checksum is on, and there are no
* csum or frame errors.
@@ -2222,10 +2222,11 @@ static int ql_clean_outbound_rx_ring(struct rx_ring *rx_ring)
ql_update_cq(rx_ring);
prod = ql_read_sh_reg(rx_ring->prod_idx_sh_reg);
}
+ if (!net_rsp)
+ return 0;
ql_write_cq_idx(rx_ring);
tx_ring = &qdev->tx_ring[net_rsp->txq_idx];
- if (__netif_subqueue_stopped(qdev->ndev, tx_ring->wq_id) &&
- net_rsp != NULL) {
+ if (__netif_subqueue_stopped(qdev->ndev, tx_ring->wq_id)) {
if (atomic_read(&tx_ring->queue_stopped) &&
(atomic_read(&tx_ring->tx_count) > (tx_ring->wq_len / 4)))
/*
@@ -2571,7 +2572,7 @@ static netdev_tx_t qlge_send(struct sk_buff *skb, struct net_device *ndev)
mac_iocb_ptr->frame_len = cpu_to_le16((u16) skb->len);
- if (qdev->vlgrp && vlan_tx_tag_present(skb)) {
+ if (vlan_tx_tag_present(skb)) {
netif_printk(qdev, tx_queued, KERN_DEBUG, qdev->ndev,
"Adding a vlan tag %d.\n", vlan_tx_tag_get(skb));
mac_iocb_ptr->flags3 |= OB_MAC_IOCB_V;
@@ -3888,11 +3889,8 @@ int ql_wol(struct ql_adapter *qdev)
return status;
}
-static int ql_adapter_down(struct ql_adapter *qdev)
+static void ql_cancel_all_work_sync(struct ql_adapter *qdev)
{
- int i, status = 0;
-
- ql_link_off(qdev);
/* Don't kill the reset worker thread if we
* are in the process of recovery.
@@ -3904,6 +3902,15 @@ static int ql_adapter_down(struct ql_adapter *qdev)
cancel_delayed_work_sync(&qdev->mpi_idc_work);
cancel_delayed_work_sync(&qdev->mpi_core_to_log);
cancel_delayed_work_sync(&qdev->mpi_port_cfg_work);
+}
+
+static int ql_adapter_down(struct ql_adapter *qdev)
+{
+ int i, status = 0;
+
+ ql_link_off(qdev);
+
+ ql_cancel_all_work_sync(qdev);
for (i = 0; i < qdev->rss_ring_count; i++)
napi_disable(&qdev->rx_ring[i].napi);
@@ -4726,6 +4733,7 @@ static void __devexit qlge_remove(struct pci_dev *pdev)
struct net_device *ndev = pci_get_drvdata(pdev);
struct ql_adapter *qdev = netdev_priv(ndev);
del_timer_sync(&qdev->timer);
+ ql_cancel_all_work_sync(qdev);
unregister_netdev(ndev);
ql_release_all(pdev);
pci_disable_device(pdev);
@@ -4745,13 +4753,7 @@ static void ql_eeh_close(struct net_device *ndev)
/* Disabling the timer */
del_timer_sync(&qdev->timer);
- if (test_bit(QL_ADAPTER_UP, &qdev->flags))
- cancel_delayed_work_sync(&qdev->asic_reset_work);
- cancel_delayed_work_sync(&qdev->mpi_reset_work);
- cancel_delayed_work_sync(&qdev->mpi_work);
- cancel_delayed_work_sync(&qdev->mpi_idc_work);
- cancel_delayed_work_sync(&qdev->mpi_core_to_log);
- cancel_delayed_work_sync(&qdev->mpi_port_cfg_work);
+ ql_cancel_all_work_sync(qdev);
for (i = 0; i < qdev->rss_ring_count; i++)
netif_napi_del(&qdev->rx_ring[i].napi);
diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c
index 142c381e1d73..0b014c894686 100644
--- a/drivers/net/r6040.c
+++ b/drivers/net/r6040.c
@@ -200,7 +200,7 @@ struct r6040_private {
int old_duplex;
};
-static char version[] __devinitdata = KERN_INFO DRV_NAME
+static char version[] __devinitdata = DRV_NAME
": RDC R6040 NAPI net driver,"
"version "DRV_VERSION " (" DRV_RELDATE ")";
@@ -224,7 +224,8 @@ static int r6040_phy_read(void __iomem *ioaddr, int phy_addr, int reg)
}
/* Write a word data from PHY Chip */
-static void r6040_phy_write(void __iomem *ioaddr, int phy_addr, int reg, u16 val)
+static void r6040_phy_write(void __iomem *ioaddr,
+ int phy_addr, int reg, u16 val)
{
int limit = 2048;
u16 cmd;
@@ -348,8 +349,8 @@ static int r6040_alloc_rxbufs(struct net_device *dev)
}
desc->skb_ptr = skb;
desc->buf = cpu_to_le32(pci_map_single(lp->pdev,
- desc->skb_ptr->data,
- MAX_BUF_SIZE, PCI_DMA_FROMDEVICE));
+ desc->skb_ptr->data,
+ MAX_BUF_SIZE, PCI_DMA_FROMDEVICE));
desc->status = DSC_OWNER_MAC;
desc = desc->vndescp;
} while (desc != lp->rx_ring);
@@ -491,12 +492,14 @@ static int r6040_close(struct net_device *dev)
/* Free Descriptor memory */
if (lp->rx_ring) {
- pci_free_consistent(pdev, RX_DESC_SIZE, lp->rx_ring, lp->rx_ring_dma);
+ pci_free_consistent(pdev,
+ RX_DESC_SIZE, lp->rx_ring, lp->rx_ring_dma);
lp->rx_ring = NULL;
}
if (lp->tx_ring) {
- pci_free_consistent(pdev, TX_DESC_SIZE, lp->tx_ring, lp->tx_ring_dma);
+ pci_free_consistent(pdev,
+ TX_DESC_SIZE, lp->tx_ring, lp->tx_ring_dma);
lp->tx_ring = NULL;
}
@@ -547,7 +550,7 @@ static int r6040_rx(struct net_device *dev, int limit)
}
goto next_descr;
}
-
+
/* Packet successfully received */
new_skb = netdev_alloc_skb(dev, MAX_BUF_SIZE);
if (!new_skb) {
@@ -556,13 +559,13 @@ static int r6040_rx(struct net_device *dev, int limit)
}
skb_ptr = descptr->skb_ptr;
skb_ptr->dev = priv->dev;
-
+
/* Do not count the CRC */
skb_put(skb_ptr, descptr->len - 4);
pci_unmap_single(priv->pdev, le32_to_cpu(descptr->buf),
MAX_BUF_SIZE, PCI_DMA_FROMDEVICE);
skb_ptr->protocol = eth_type_trans(skb_ptr, priv->dev);
-
+
/* Send to upper layer */
netif_receive_skb(skb_ptr);
dev->stats.rx_packets++;
@@ -710,8 +713,10 @@ static int r6040_up(struct net_device *dev)
return ret;
/* improve performance (by RDC guys) */
- r6040_phy_write(ioaddr, 30, 17, (r6040_phy_read(ioaddr, 30, 17) | 0x4000));
- r6040_phy_write(ioaddr, 30, 17, ~((~r6040_phy_read(ioaddr, 30, 17)) | 0x2000));
+ r6040_phy_write(ioaddr, 30, 17,
+ (r6040_phy_read(ioaddr, 30, 17) | 0x4000));
+ r6040_phy_write(ioaddr, 30, 17,
+ ~((~r6040_phy_read(ioaddr, 30, 17)) | 0x2000));
r6040_phy_write(ioaddr, 0, 19, 0x0000);
r6040_phy_write(ioaddr, 0, 30, 0x01F0);
@@ -740,6 +745,9 @@ static void r6040_mac_address(struct net_device *dev)
iowrite16(adrp[0], ioaddr + MID_0L);
iowrite16(adrp[1], ioaddr + MID_0M);
iowrite16(adrp[2], ioaddr + MID_0H);
+
+ /* Store MAC Address in perm_addr */
+ memcpy(dev->perm_addr, dev->dev_addr, ETH_ALEN);
}
static int r6040_open(struct net_device *dev)
@@ -751,7 +759,7 @@ static int r6040_open(struct net_device *dev)
ret = request_irq(dev->irq, r6040_interrupt,
IRQF_SHARED, dev->name, dev);
if (ret)
- return ret;
+ goto out;
/* Set MAC address */
r6040_mac_address(dev);
@@ -759,30 +767,37 @@ static int r6040_open(struct net_device *dev)
/* Allocate Descriptor memory */
lp->rx_ring =
pci_alloc_consistent(lp->pdev, RX_DESC_SIZE, &lp->rx_ring_dma);
- if (!lp->rx_ring)
- return -ENOMEM;
+ if (!lp->rx_ring) {
+ ret = -ENOMEM;
+ goto err_free_irq;
+ }
lp->tx_ring =
pci_alloc_consistent(lp->pdev, TX_DESC_SIZE, &lp->tx_ring_dma);
if (!lp->tx_ring) {
- pci_free_consistent(lp->pdev, RX_DESC_SIZE, lp->rx_ring,
- lp->rx_ring_dma);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto err_free_rx_ring;
}
ret = r6040_up(dev);
- if (ret) {
- pci_free_consistent(lp->pdev, TX_DESC_SIZE, lp->tx_ring,
- lp->tx_ring_dma);
- pci_free_consistent(lp->pdev, RX_DESC_SIZE, lp->rx_ring,
- lp->rx_ring_dma);
- return ret;
- }
+ if (ret)
+ goto err_free_tx_ring;
napi_enable(&lp->napi);
netif_start_queue(dev);
return 0;
+
+err_free_tx_ring:
+ pci_free_consistent(lp->pdev, TX_DESC_SIZE, lp->tx_ring,
+ lp->tx_ring_dma);
+err_free_rx_ring:
+ pci_free_consistent(lp->pdev, RX_DESC_SIZE, lp->rx_ring,
+ lp->rx_ring_dma);
+err_free_irq:
+ free_irq(dev->irq, dev);
+out:
+ return ret;
}
static netdev_tx_t r6040_start_xmit(struct sk_buff *skb,
@@ -893,16 +908,18 @@ static void r6040_multicast_list(struct net_device *dev)
/* Multicast Address 1~4 case */
i = 0;
netdev_for_each_mc_addr(ha, dev) {
- if (i < MCAST_MAX) {
- adrp = (u16 *) ha->addr;
- iowrite16(adrp[0], ioaddr + MID_1L + 8 * i);
- iowrite16(adrp[1], ioaddr + MID_1M + 8 * i);
- iowrite16(adrp[2], ioaddr + MID_1H + 8 * i);
- } else {
- iowrite16(0xffff, ioaddr + MID_1L + 8 * i);
- iowrite16(0xffff, ioaddr + MID_1M + 8 * i);
- iowrite16(0xffff, ioaddr + MID_1H + 8 * i);
- }
+ if (i >= MCAST_MAX)
+ break;
+ adrp = (u16 *) ha->addr;
+ iowrite16(adrp[0], ioaddr + MID_1L + 8 * i);
+ iowrite16(adrp[1], ioaddr + MID_1M + 8 * i);
+ iowrite16(adrp[2], ioaddr + MID_1H + 8 * i);
+ i++;
+ }
+ while (i < MCAST_MAX) {
+ iowrite16(0xffff, ioaddr + MID_1L + 8 * i);
+ iowrite16(0xffff, ioaddr + MID_1M + 8 * i);
+ iowrite16(0xffff, ioaddr + MID_1H + 8 * i);
i++;
}
}
@@ -946,7 +963,7 @@ static const struct net_device_ops r6040_netdev_ops = {
.ndo_set_multicast_list = r6040_multicast_list,
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
- .ndo_set_mac_address = eth_mac_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_do_ioctl = r6040_ioctl,
.ndo_tx_timeout = r6040_tx_timeout,
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -1039,7 +1056,7 @@ static int __devinit r6040_init_one(struct pci_dev *pdev,
u16 *adrp;
int i;
- printk("%s\n", version);
+ pr_info("%s\n", version);
err = pci_enable_device(pdev);
if (err)
@@ -1113,7 +1130,8 @@ static int __devinit r6040_init_one(struct pci_dev *pdev,
/* Some bootloader/BIOSes do not initialize
* MAC address, warn about that */
if (!(adrp[0] || adrp[1] || adrp[2])) {
- netdev_warn(dev, "MAC address not initialized, generating random\n");
+ netdev_warn(dev, "MAC address not initialized, "
+ "generating random\n");
random_ether_addr(dev->dev_addr);
}
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index a0da4a17b025..d88ce9fb1cbd 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -187,12 +187,7 @@ static DEFINE_PCI_DEVICE_TABLE(rtl8169_pci_tbl) = {
MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl);
-/*
- * we set our copybreak very high so that we don't have
- * to allocate 16k frames all the time (see note in
- * rtl8169_open()
- */
-static int rx_copybreak = 16383;
+static int rx_buf_sz = 16383;
static int use_dac;
static struct {
u32 msg_enable;
@@ -484,10 +479,8 @@ struct rtl8169_private {
struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */
dma_addr_t TxPhyAddr;
dma_addr_t RxPhyAddr;
- struct sk_buff *Rx_skbuff[NUM_RX_DESC]; /* Rx data buffers */
+ void *Rx_databuff[NUM_RX_DESC]; /* Rx data buffers */
struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */
- unsigned align;
- unsigned rx_buf_sz;
struct timer_list timer;
u16 cp_cmd;
u16 intr_event;
@@ -515,8 +508,6 @@ struct rtl8169_private {
MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver");
-module_param(rx_copybreak, int, 0);
-MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames");
module_param(use_dac, int, 0);
MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot.");
module_param_named(debug, debug.msg_enable, int, 0);
@@ -1043,7 +1034,7 @@ static int rtl8169_set_rx_csum(struct net_device *dev, u32 data)
static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp,
struct sk_buff *skb)
{
- return (tp->vlgrp && vlan_tx_tag_present(skb)) ?
+ return (vlan_tx_tag_present(skb)) ?
TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00;
}
@@ -1076,7 +1067,12 @@ static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc,
int ret;
if (vlgrp && (opts2 & RxVlanTag)) {
- __vlan_hwaccel_rx(skb, vlgrp, swab16(opts2 & 0xffff), polling);
+ u16 vtag = swab16(opts2 & 0xffff);
+
+ if (likely(polling))
+ vlan_gro_receive(&tp->napi, vlgrp, vtag, skb);
+ else
+ __vlan_hwaccel_rx(skb, vlgrp, vtag, polling);
ret = 0;
} else
ret = -1;
@@ -1204,6 +1200,7 @@ static void rtl8169_update_counters(struct net_device *dev)
dma_addr_t paddr;
u32 cmd;
int wait = 1000;
+ struct device *d = &tp->pci_dev->dev;
/*
* Some chips are unable to dump tally counters when the receiver
@@ -1212,7 +1209,7 @@ static void rtl8169_update_counters(struct net_device *dev)
if ((RTL_R8(ChipCmd) & CmdRxEnb) == 0)
return;
- counters = pci_alloc_consistent(tp->pci_dev, sizeof(*counters), &paddr);
+ counters = dma_alloc_coherent(d, sizeof(*counters), &paddr, GFP_KERNEL);
if (!counters)
return;
@@ -1233,7 +1230,7 @@ static void rtl8169_update_counters(struct net_device *dev)
RTL_W32(CounterAddrLow, 0);
RTL_W32(CounterAddrHigh, 0);
- pci_free_consistent(tp->pci_dev, sizeof(*counters), counters, paddr);
+ dma_free_coherent(d, sizeof(*counters), counters, paddr);
}
static void rtl8169_get_ethtool_stats(struct net_device *dev,
@@ -3186,9 +3183,9 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
#ifdef CONFIG_R8169_VLAN
dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
#endif
+ dev->features |= NETIF_F_GRO;
tp->intr_mask = 0xffff;
- tp->align = cfg->align;
tp->hw_start = cfg->hw_start;
tp->intr_event = cfg->intr_event;
tp->napi_event = cfg->napi_event;
@@ -3258,18 +3255,6 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev)
pci_set_drvdata(pdev, NULL);
}
-static void rtl8169_set_rxbufsize(struct rtl8169_private *tp,
- unsigned int mtu)
-{
- unsigned int max_frame = mtu + VLAN_ETH_HLEN + ETH_FCS_LEN;
-
- if (max_frame != 16383)
- printk(KERN_WARNING PFX "WARNING! Changing of MTU on this "
- "NIC may lead to frame reception errors!\n");
-
- tp->rx_buf_sz = (max_frame > RX_BUF_SIZE) ? max_frame : RX_BUF_SIZE;
-}
-
static int rtl8169_open(struct net_device *dev)
{
struct rtl8169_private *tp = netdev_priv(dev);
@@ -3279,28 +3264,16 @@ static int rtl8169_open(struct net_device *dev)
pm_runtime_get_sync(&pdev->dev);
/*
- * Note that we use a magic value here, its wierd I know
- * its done because, some subset of rtl8169 hardware suffers from
- * a problem in which frames received that are longer than
- * the size set in RxMaxSize register return garbage sizes
- * when received. To avoid this we need to turn off filtering,
- * which is done by setting a value of 16383 in the RxMaxSize register
- * and allocating 16k frames to handle the largest possible rx value
- * thats what the magic math below does.
- */
- rtl8169_set_rxbufsize(tp, 16383 - VLAN_ETH_HLEN - ETH_FCS_LEN);
-
- /*
* Rx and Tx desscriptors needs 256 bytes alignment.
- * pci_alloc_consistent provides more.
+ * dma_alloc_coherent provides more.
*/
- tp->TxDescArray = pci_alloc_consistent(pdev, R8169_TX_RING_BYTES,
- &tp->TxPhyAddr);
+ tp->TxDescArray = dma_alloc_coherent(&pdev->dev, R8169_TX_RING_BYTES,
+ &tp->TxPhyAddr, GFP_KERNEL);
if (!tp->TxDescArray)
goto err_pm_runtime_put;
- tp->RxDescArray = pci_alloc_consistent(pdev, R8169_RX_RING_BYTES,
- &tp->RxPhyAddr);
+ tp->RxDescArray = dma_alloc_coherent(&pdev->dev, R8169_RX_RING_BYTES,
+ &tp->RxPhyAddr, GFP_KERNEL);
if (!tp->RxDescArray)
goto err_free_tx_0;
@@ -3334,12 +3307,12 @@ out:
err_release_ring_2:
rtl8169_rx_clear(tp);
err_free_rx_1:
- pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray,
- tp->RxPhyAddr);
+ dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray,
+ tp->RxPhyAddr);
tp->RxDescArray = NULL;
err_free_tx_0:
- pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray,
- tp->TxPhyAddr);
+ dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray,
+ tp->TxPhyAddr);
tp->TxDescArray = NULL;
err_pm_runtime_put:
pm_runtime_put_noidle(&pdev->dev);
@@ -3466,7 +3439,7 @@ static void rtl_hw_start_8169(struct net_device *dev)
RTL_W8(EarlyTxThres, EarlyTxThld);
- rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz);
+ rtl_set_rx_max_size(ioaddr, rx_buf_sz);
if ((tp->mac_version == RTL_GIGA_MAC_VER_01) ||
(tp->mac_version == RTL_GIGA_MAC_VER_02) ||
@@ -3727,7 +3700,7 @@ static void rtl_hw_start_8168(struct net_device *dev)
RTL_W8(EarlyTxThres, EarlyTxThld);
- rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz);
+ rtl_set_rx_max_size(ioaddr, rx_buf_sz);
tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1;
@@ -3907,7 +3880,7 @@ static void rtl_hw_start_8101(struct net_device *dev)
RTL_W8(EarlyTxThres, EarlyTxThld);
- rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz);
+ rtl_set_rx_max_size(ioaddr, rx_buf_sz);
tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW;
@@ -3935,33 +3908,11 @@ static void rtl_hw_start_8101(struct net_device *dev)
static int rtl8169_change_mtu(struct net_device *dev, int new_mtu)
{
- struct rtl8169_private *tp = netdev_priv(dev);
- int ret = 0;
-
if (new_mtu < ETH_ZLEN || new_mtu > SafeMtu)
return -EINVAL;
dev->mtu = new_mtu;
-
- if (!netif_running(dev))
- goto out;
-
- rtl8169_down(dev);
-
- rtl8169_set_rxbufsize(tp, dev->mtu);
-
- ret = rtl8169_init_ring(dev);
- if (ret < 0)
- goto out;
-
- napi_enable(&tp->napi);
-
- rtl_hw_start(dev);
-
- rtl8169_request_timer(dev);
-
-out:
- return ret;
+ return 0;
}
static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc)
@@ -3970,15 +3921,14 @@ static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc)
desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask);
}
-static void rtl8169_free_rx_skb(struct rtl8169_private *tp,
- struct sk_buff **sk_buff, struct RxDesc *desc)
+static void rtl8169_free_rx_databuff(struct rtl8169_private *tp,
+ void **data_buff, struct RxDesc *desc)
{
- struct pci_dev *pdev = tp->pci_dev;
+ dma_unmap_single(&tp->pci_dev->dev, le64_to_cpu(desc->addr), rx_buf_sz,
+ DMA_FROM_DEVICE);
- pci_unmap_single(pdev, le64_to_cpu(desc->addr), tp->rx_buf_sz,
- PCI_DMA_FROMDEVICE);
- dev_kfree_skb(*sk_buff);
- *sk_buff = NULL;
+ kfree(*data_buff);
+ *data_buff = NULL;
rtl8169_make_unusable_by_asic(desc);
}
@@ -3997,33 +3947,45 @@ static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping,
rtl8169_mark_to_asic(desc, rx_buf_sz);
}
-static struct sk_buff *rtl8169_alloc_rx_skb(struct pci_dev *pdev,
- struct net_device *dev,
- struct RxDesc *desc, int rx_buf_sz,
- unsigned int align)
+static inline void *rtl8169_align(void *data)
{
- struct sk_buff *skb;
- dma_addr_t mapping;
- unsigned int pad;
+ return (void *)ALIGN((long)data, 16);
+}
- pad = align ? align : NET_IP_ALIGN;
+static struct sk_buff *rtl8169_alloc_rx_data(struct rtl8169_private *tp,
+ struct RxDesc *desc)
+{
+ void *data;
+ dma_addr_t mapping;
+ struct device *d = &tp->pci_dev->dev;
+ struct net_device *dev = tp->dev;
+ int node = dev->dev.parent ? dev_to_node(dev->dev.parent) : -1;
- skb = netdev_alloc_skb(dev, rx_buf_sz + pad);
- if (!skb)
- goto err_out;
+ data = kmalloc_node(rx_buf_sz, GFP_KERNEL, node);
+ if (!data)
+ return NULL;
- skb_reserve(skb, align ? ((pad - 1) & (unsigned long)skb->data) : pad);
+ if (rtl8169_align(data) != data) {
+ kfree(data);
+ data = kmalloc_node(rx_buf_sz + 15, GFP_KERNEL, node);
+ if (!data)
+ return NULL;
+ }
- mapping = pci_map_single(pdev, skb->data, rx_buf_sz,
- PCI_DMA_FROMDEVICE);
+ mapping = dma_map_single(d, rtl8169_align(data), rx_buf_sz,
+ DMA_FROM_DEVICE);
+ if (unlikely(dma_mapping_error(d, mapping))) {
+ if (net_ratelimit())
+ netif_err(tp, drv, tp->dev, "Failed to map RX DMA!\n");
+ goto err_out;
+ }
rtl8169_map_to_asic(desc, mapping, rx_buf_sz);
-out:
- return skb;
+ return data;
err_out:
- rtl8169_make_unusable_by_asic(desc);
- goto out;
+ kfree(data);
+ return NULL;
}
static void rtl8169_rx_clear(struct rtl8169_private *tp)
@@ -4031,41 +3993,42 @@ static void rtl8169_rx_clear(struct rtl8169_private *tp)
unsigned int i;
for (i = 0; i < NUM_RX_DESC; i++) {
- if (tp->Rx_skbuff[i]) {
- rtl8169_free_rx_skb(tp, tp->Rx_skbuff + i,
+ if (tp->Rx_databuff[i]) {
+ rtl8169_free_rx_databuff(tp, tp->Rx_databuff + i,
tp->RxDescArray + i);
}
}
}
-static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev,
- u32 start, u32 end)
+static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc)
{
- u32 cur;
+ desc->opts1 |= cpu_to_le32(RingEnd);
+}
- for (cur = start; end - cur != 0; cur++) {
- struct sk_buff *skb;
- unsigned int i = cur % NUM_RX_DESC;
+static int rtl8169_rx_fill(struct rtl8169_private *tp)
+{
+ unsigned int i;
- WARN_ON((s32)(end - cur) < 0);
+ for (i = 0; i < NUM_RX_DESC; i++) {
+ void *data;
- if (tp->Rx_skbuff[i])
+ if (tp->Rx_databuff[i])
continue;
- skb = rtl8169_alloc_rx_skb(tp->pci_dev, dev,
- tp->RxDescArray + i,
- tp->rx_buf_sz, tp->align);
- if (!skb)
- break;
-
- tp->Rx_skbuff[i] = skb;
+ data = rtl8169_alloc_rx_data(tp, tp->RxDescArray + i);
+ if (!data) {
+ rtl8169_make_unusable_by_asic(tp->RxDescArray + i);
+ goto err_out;
+ }
+ tp->Rx_databuff[i] = data;
}
- return cur - start;
-}
-static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc)
-{
- desc->opts1 |= cpu_to_le32(RingEnd);
+ rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1);
+ return 0;
+
+err_out:
+ rtl8169_rx_clear(tp);
+ return -ENOMEM;
}
static void rtl8169_init_ring_indexes(struct rtl8169_private *tp)
@@ -4080,53 +4043,51 @@ static int rtl8169_init_ring(struct net_device *dev)
rtl8169_init_ring_indexes(tp);
memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info));
- memset(tp->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *));
-
- if (rtl8169_rx_fill(tp, dev, 0, NUM_RX_DESC) != NUM_RX_DESC)
- goto err_out;
-
- rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1);
-
- return 0;
+ memset(tp->Rx_databuff, 0x0, NUM_RX_DESC * sizeof(void *));
-err_out:
- rtl8169_rx_clear(tp);
- return -ENOMEM;
+ return rtl8169_rx_fill(tp);
}
-static void rtl8169_unmap_tx_skb(struct pci_dev *pdev, struct ring_info *tx_skb,
+static void rtl8169_unmap_tx_skb(struct device *d, struct ring_info *tx_skb,
struct TxDesc *desc)
{
unsigned int len = tx_skb->len;
- pci_unmap_single(pdev, le64_to_cpu(desc->addr), len, PCI_DMA_TODEVICE);
+ dma_unmap_single(d, le64_to_cpu(desc->addr), len, DMA_TO_DEVICE);
+
desc->opts1 = 0x00;
desc->opts2 = 0x00;
desc->addr = 0x00;
tx_skb->len = 0;
}
-static void rtl8169_tx_clear(struct rtl8169_private *tp)
+static void rtl8169_tx_clear_range(struct rtl8169_private *tp, u32 start,
+ unsigned int n)
{
unsigned int i;
- for (i = tp->dirty_tx; i < tp->dirty_tx + NUM_TX_DESC; i++) {
- unsigned int entry = i % NUM_TX_DESC;
+ for (i = 0; i < n; i++) {
+ unsigned int entry = (start + i) % NUM_TX_DESC;
struct ring_info *tx_skb = tp->tx_skb + entry;
unsigned int len = tx_skb->len;
if (len) {
struct sk_buff *skb = tx_skb->skb;
- rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb,
+ rtl8169_unmap_tx_skb(&tp->pci_dev->dev, tx_skb,
tp->TxDescArray + entry);
if (skb) {
+ tp->dev->stats.tx_dropped++;
dev_kfree_skb(skb);
tx_skb->skb = NULL;
}
- tp->dev->stats.tx_dropped++;
}
}
+}
+
+static void rtl8169_tx_clear(struct rtl8169_private *tp)
+{
+ rtl8169_tx_clear_range(tp, tp->dirty_tx, NUM_TX_DESC);
tp->cur_tx = tp->dirty_tx = 0;
}
@@ -4230,6 +4191,7 @@ static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb,
struct skb_shared_info *info = skb_shinfo(skb);
unsigned int cur_frag, entry;
struct TxDesc * uninitialized_var(txd);
+ struct device *d = &tp->pci_dev->dev;
entry = tp->cur_tx;
for (cur_frag = 0; cur_frag < info->nr_frags; cur_frag++) {
@@ -4243,7 +4205,13 @@ static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb,
txd = tp->TxDescArray + entry;
len = frag->size;
addr = ((void *) page_address(frag->page)) + frag->page_offset;
- mapping = pci_map_single(tp->pci_dev, addr, len, PCI_DMA_TODEVICE);
+ mapping = dma_map_single(d, addr, len, DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(d, mapping))) {
+ if (net_ratelimit())
+ netif_err(tp, drv, tp->dev,
+ "Failed to map TX fragments DMA!\n");
+ goto err_out;
+ }
/* anti gcc 2.95.3 bugware (sic) */
status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC));
@@ -4260,6 +4228,10 @@ static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb,
}
return cur_frag;
+
+err_out:
+ rtl8169_tx_clear_range(tp, tp->cur_tx + 1, cur_frag);
+ return -EIO;
}
static inline u32 rtl8169_tso_csum(struct sk_buff *skb, struct net_device *dev)
@@ -4286,39 +4258,47 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
struct net_device *dev)
{
struct rtl8169_private *tp = netdev_priv(dev);
- unsigned int frags, entry = tp->cur_tx % NUM_TX_DESC;
+ unsigned int entry = tp->cur_tx % NUM_TX_DESC;
struct TxDesc *txd = tp->TxDescArray + entry;
void __iomem *ioaddr = tp->mmio_addr;
+ struct device *d = &tp->pci_dev->dev;
dma_addr_t mapping;
u32 status, len;
u32 opts1;
+ int frags;
if (unlikely(TX_BUFFS_AVAIL(tp) < skb_shinfo(skb)->nr_frags)) {
netif_err(tp, drv, dev, "BUG! Tx Ring full when queue awake!\n");
- goto err_stop;
+ goto err_stop_0;
}
if (unlikely(le32_to_cpu(txd->opts1) & DescOwn))
- goto err_stop;
+ goto err_stop_0;
+
+ len = skb_headlen(skb);
+ mapping = dma_map_single(d, skb->data, len, DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(d, mapping))) {
+ if (net_ratelimit())
+ netif_err(tp, drv, dev, "Failed to map TX DMA!\n");
+ goto err_dma_0;
+ }
+
+ tp->tx_skb[entry].len = len;
+ txd->addr = cpu_to_le64(mapping);
+ txd->opts2 = cpu_to_le32(rtl8169_tx_vlan_tag(tp, skb));
opts1 = DescOwn | rtl8169_tso_csum(skb, dev);
frags = rtl8169_xmit_frags(tp, skb, opts1);
- if (frags) {
- len = skb_headlen(skb);
+ if (frags < 0)
+ goto err_dma_1;
+ else if (frags)
opts1 |= FirstFrag;
- } else {
- len = skb->len;
+ else {
opts1 |= FirstFrag | LastFrag;
tp->tx_skb[entry].skb = skb;
}
- mapping = pci_map_single(tp->pci_dev, skb->data, len, PCI_DMA_TODEVICE);
-
- tp->tx_skb[entry].len = len;
- txd->addr = cpu_to_le64(mapping);
- txd->opts2 = cpu_to_le32(rtl8169_tx_vlan_tag(tp, skb));
-
wmb();
/* anti gcc 2.95.3 bugware (sic) */
@@ -4340,7 +4320,14 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
return NETDEV_TX_OK;
-err_stop:
+err_dma_1:
+ rtl8169_unmap_tx_skb(d, tp->tx_skb + entry, txd);
+err_dma_0:
+ dev_kfree_skb(skb);
+ dev->stats.tx_dropped++;
+ return NETDEV_TX_OK;
+
+err_stop_0:
netif_stop_queue(dev);
dev->stats.tx_dropped++;
return NETDEV_TX_BUSY;
@@ -4405,7 +4392,6 @@ static void rtl8169_tx_interrupt(struct net_device *dev,
while (tx_left > 0) {
unsigned int entry = dirty_tx % NUM_TX_DESC;
struct ring_info *tx_skb = tp->tx_skb + entry;
- u32 len = tx_skb->len;
u32 status;
rmb();
@@ -4413,12 +4399,11 @@ static void rtl8169_tx_interrupt(struct net_device *dev,
if (status & DescOwn)
break;
- dev->stats.tx_bytes += len;
- dev->stats.tx_packets++;
-
- rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, tp->TxDescArray + entry);
-
+ rtl8169_unmap_tx_skb(&tp->pci_dev->dev, tx_skb,
+ tp->TxDescArray + entry);
if (status & LastFrag) {
+ dev->stats.tx_packets++;
+ dev->stats.tx_bytes += tx_skb->skb->len;
dev_kfree_skb(tx_skb->skb);
tx_skb->skb = NULL;
}
@@ -4450,9 +4435,8 @@ static inline int rtl8169_fragmented_frame(u32 status)
return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag);
}
-static inline void rtl8169_rx_csum(struct sk_buff *skb, struct RxDesc *desc)
+static inline void rtl8169_rx_csum(struct sk_buff *skb, u32 opts1)
{
- u32 opts1 = le32_to_cpu(desc->opts1);
u32 status = opts1 & RxProtoMask;
if (((status == RxProtoTCP) && !(opts1 & TCPFail)) ||
@@ -4460,30 +4444,26 @@ static inline void rtl8169_rx_csum(struct sk_buff *skb, struct RxDesc *desc)
((status == RxProtoIP) && !(opts1 & IPFail)))
skb->ip_summed = CHECKSUM_UNNECESSARY;
else
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
}
-static inline bool rtl8169_try_rx_copy(struct sk_buff **sk_buff,
- struct rtl8169_private *tp, int pkt_size,
- dma_addr_t addr)
+static struct sk_buff *rtl8169_try_rx_copy(void *data,
+ struct rtl8169_private *tp,
+ int pkt_size,
+ dma_addr_t addr)
{
struct sk_buff *skb;
- bool done = false;
-
- if (pkt_size >= rx_copybreak)
- goto out;
+ struct device *d = &tp->pci_dev->dev;
+ data = rtl8169_align(data);
+ dma_sync_single_for_cpu(d, addr, pkt_size, DMA_FROM_DEVICE);
+ prefetch(data);
skb = netdev_alloc_skb_ip_align(tp->dev, pkt_size);
- if (!skb)
- goto out;
+ if (skb)
+ memcpy(skb->data, data, pkt_size);
+ dma_sync_single_for_device(d, addr, pkt_size, DMA_FROM_DEVICE);
- pci_dma_sync_single_for_cpu(tp->pci_dev, addr, pkt_size,
- PCI_DMA_FROMDEVICE);
- skb_copy_from_linear_data(*sk_buff, skb->data, pkt_size);
- *sk_buff = skb;
- done = true;
-out:
- return done;
+ return skb;
}
/*
@@ -4498,7 +4478,7 @@ static int rtl8169_rx_interrupt(struct net_device *dev,
void __iomem *ioaddr, u32 budget)
{
unsigned int cur_rx, rx_left;
- unsigned int delta, count;
+ unsigned int count;
int polling = (budget != ~(u32)0) ? 1 : 0;
cur_rx = tp->cur_rx;
@@ -4527,12 +4507,11 @@ static int rtl8169_rx_interrupt(struct net_device *dev,
rtl8169_schedule_work(dev, rtl8169_reset_task);
dev->stats.rx_fifo_errors++;
}
- rtl8169_mark_to_asic(desc, tp->rx_buf_sz);
+ rtl8169_mark_to_asic(desc, rx_buf_sz);
} else {
- struct sk_buff *skb = tp->Rx_skbuff[entry];
+ struct sk_buff *skb;
dma_addr_t addr = le64_to_cpu(desc->addr);
int pkt_size = (status & 0x00001FFF) - 4;
- struct pci_dev *pdev = tp->pci_dev;
/*
* The driver does not support incoming fragmented
@@ -4542,28 +4521,25 @@ static int rtl8169_rx_interrupt(struct net_device *dev,
if (unlikely(rtl8169_fragmented_frame(status))) {
dev->stats.rx_dropped++;
dev->stats.rx_length_errors++;
- rtl8169_mark_to_asic(desc, tp->rx_buf_sz);
+ rtl8169_mark_to_asic(desc, rx_buf_sz);
continue;
}
- rtl8169_rx_csum(skb, desc);
-
- if (rtl8169_try_rx_copy(&skb, tp, pkt_size, addr)) {
- pci_dma_sync_single_for_device(pdev, addr,
- pkt_size, PCI_DMA_FROMDEVICE);
- rtl8169_mark_to_asic(desc, tp->rx_buf_sz);
- } else {
- pci_unmap_single(pdev, addr, tp->rx_buf_sz,
- PCI_DMA_FROMDEVICE);
- tp->Rx_skbuff[entry] = NULL;
+ skb = rtl8169_try_rx_copy(tp->Rx_databuff[entry],
+ tp, pkt_size, addr);
+ rtl8169_mark_to_asic(desc, rx_buf_sz);
+ if (!skb) {
+ dev->stats.rx_dropped++;
+ continue;
}
+ rtl8169_rx_csum(skb, status);
skb_put(skb, pkt_size);
skb->protocol = eth_type_trans(skb, dev);
if (rtl8169_rx_vlan_skb(tp, desc, skb, polling) < 0) {
if (likely(polling))
- netif_receive_skb(skb);
+ napi_gro_receive(&tp->napi, skb);
else
netif_rx(skb);
}
@@ -4583,20 +4559,7 @@ static int rtl8169_rx_interrupt(struct net_device *dev,
count = cur_rx - tp->cur_rx;
tp->cur_rx = cur_rx;
- delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx);
- if (!delta && count)
- netif_info(tp, intr, dev, "no Rx buffer allocated\n");
- tp->dirty_rx += delta;
-
- /*
- * FIXME: until there is periodic timer to try and refill the ring,
- * a temporary shortage may definitely kill the Rx process.
- * - disable the asic to try and avoid an overflow and kick it again
- * after refill ?
- * - how do others driver handle this condition (Uh oh...).
- */
- if (tp->dirty_rx + NUM_RX_DESC == tp->cur_rx)
- netif_emerg(tp, intr, dev, "Rx buffers exhausted\n");
+ tp->dirty_rx += count;
return count;
}
@@ -4711,7 +4674,6 @@ static void rtl8169_down(struct net_device *dev)
{
struct rtl8169_private *tp = netdev_priv(dev);
void __iomem *ioaddr = tp->mmio_addr;
- unsigned int intrmask;
rtl8169_delete_timer(dev);
@@ -4719,11 +4681,14 @@ static void rtl8169_down(struct net_device *dev)
napi_disable(&tp->napi);
-core_down:
spin_lock_irq(&tp->lock);
rtl8169_asic_down(ioaddr);
-
+ /*
+ * At this point device interrupts can not be enabled in any function,
+ * as netif_running is not true (rtl8169_interrupt, rtl8169_reset_task,
+ * rtl8169_reinit_task) and napi is disabled (rtl8169_poll).
+ */
rtl8169_rx_missed(dev, ioaddr);
spin_unlock_irq(&tp->lock);
@@ -4733,23 +4698,6 @@ core_down:
/* Give a racing hard_start_xmit a few cycles to complete. */
synchronize_sched(); /* FIXME: should this be synchronize_irq()? */
- /*
- * And now for the 50k$ question: are IRQ disabled or not ?
- *
- * Two paths lead here:
- * 1) dev->close
- * -> netif_running() is available to sync the current code and the
- * IRQ handler. See rtl8169_interrupt for details.
- * 2) dev->change_mtu
- * -> rtl8169_poll can not be issued again and re-enable the
- * interruptions. Let's simply issue the IRQ down sequence again.
- *
- * No loop if hotpluged or major error (0xffff).
- */
- intrmask = RTL_R16(IntrMask);
- if (intrmask && (intrmask != 0xffff))
- goto core_down;
-
rtl8169_tx_clear(tp);
rtl8169_rx_clear(tp);
@@ -4769,10 +4717,10 @@ static int rtl8169_close(struct net_device *dev)
free_irq(dev->irq, dev);
- pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray,
- tp->RxPhyAddr);
- pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray,
- tp->TxPhyAddr);
+ dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray,
+ tp->RxPhyAddr);
+ dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray,
+ tp->TxPhyAddr);
tp->TxDescArray = NULL;
tp->RxDescArray = NULL;
@@ -4886,6 +4834,9 @@ static int rtl8169_resume(struct device *device)
{
struct pci_dev *pdev = to_pci_dev(device);
struct net_device *dev = pci_get_drvdata(pdev);
+ struct rtl8169_private *tp = netdev_priv(dev);
+
+ rtl8169_init_phy(dev, tp);
if (netif_running(dev))
__rtl8169_resume(dev);
@@ -4926,6 +4877,8 @@ static int rtl8169_runtime_resume(struct device *device)
tp->saved_wolopts = 0;
spin_unlock_irq(&tp->lock);
+ rtl8169_init_phy(dev, tp);
+
__rtl8169_resume(dev);
return 0;
diff --git a/drivers/net/rrunner.c b/drivers/net/rrunner.c
index e26e107f93e0..e68c941926f1 100644
--- a/drivers/net/rrunner.c
+++ b/drivers/net/rrunner.c
@@ -1245,7 +1245,7 @@ static int rr_open(struct net_device *dev)
init_timer(&rrpriv->timer);
rrpriv->timer.expires = RUN_AT(5*HZ); /* 5 sec. watchdog */
rrpriv->timer.data = (unsigned long)dev;
- rrpriv->timer.function = &rr_timer; /* timer handler */
+ rrpriv->timer.function = rr_timer; /* timer handler */
add_timer(&rrpriv->timer);
netif_start_queue(dev);
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index 18bc5b718bbb..ecc25aab896a 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -38,8 +38,6 @@
* Tx descriptors that can be associated with each corresponding FIFO.
* intr_type: This defines the type of interrupt. The values can be 0(INTA),
* 2(MSI_X). Default value is '2(MSI_X)'
- * lro: Specifies whether to enable Large Receive Offload (LRO) or not.
- * Possible values '1' for enable '0' for disable. Default is '0'
* lro_max_pkts: This parameter defines maximum number of packets can be
* aggregated as a single large packet
* napi: This parameter used to enable/disable NAPI (polling Rx)
@@ -90,7 +88,7 @@
#include "s2io.h"
#include "s2io-regs.h"
-#define DRV_VERSION "2.0.26.26"
+#define DRV_VERSION "2.0.26.27"
/* S2io Driver name & version. */
static char s2io_driver_name[] = "Neterion";
@@ -496,8 +494,6 @@ S2IO_PARM_INT(rxsync_frequency, 3);
/* Interrupt type. Values can be 0(INTA), 2(MSI_X) */
S2IO_PARM_INT(intr_type, 2);
/* Large receive offload feature */
-static unsigned int lro_enable = 1;
-module_param_named(lro, lro_enable, uint, 0);
/* Max pkts to be aggregated by LRO at one time. If not specified,
* aggregation happens until we hit max IP pkt size(64K)
@@ -4105,7 +4101,7 @@ static netdev_tx_t s2io_xmit(struct sk_buff *skb, struct net_device *dev)
}
queue = 0;
- if (sp->vlgrp && vlan_tx_tag_present(skb))
+ if (vlan_tx_tag_present(skb))
vlan_tag = vlan_tx_tag_get(skb);
if (sp->config.tx_steering_type == TX_DEFAULT_STEERING) {
if (skb->protocol == htons(ETH_P_IP)) {
@@ -5124,8 +5120,6 @@ static void s2io_set_multicast(struct net_device *dev)
/* Create the new Rx filter list and update the same in H/W. */
i = 0;
netdev_for_each_mc_addr(ha, dev) {
- memcpy(sp->usr_addrs[i].addr, ha->addr,
- ETH_ALEN);
mac_addr = 0;
for (j = 0; j < ETH_ALEN; j++) {
mac_addr |= ha->addr[j];
@@ -6735,13 +6729,10 @@ static int s2io_ethtool_set_flags(struct net_device *dev, u32 data)
return -EINVAL;
if (data & ETH_FLAG_LRO) {
- if (lro_enable) {
- if (!(dev->features & NETIF_F_LRO)) {
- dev->features |= NETIF_F_LRO;
- changed = 1;
- }
- } else
- rc = -EINVAL;
+ if (!(dev->features & NETIF_F_LRO)) {
+ dev->features |= NETIF_F_LRO;
+ changed = 1;
+ }
} else if (dev->features & NETIF_F_LRO) {
dev->features &= ~NETIF_F_LRO;
changed = 1;
@@ -6750,7 +6741,6 @@ static int s2io_ethtool_set_flags(struct net_device *dev, u32 data)
if (changed && netif_running(dev)) {
s2io_stop_all_tx_queue(sp);
s2io_card_down(sp);
- sp->lro = !!(dev->features & NETIF_F_LRO);
rc = s2io_card_up(sp);
if (rc)
s2io_reset(sp);
@@ -7307,7 +7297,7 @@ static int s2io_card_up(struct s2io_nic *sp)
struct ring_info *ring = &mac_control->rings[i];
ring->mtu = dev->mtu;
- ring->lro = sp->lro;
+ ring->lro = !!(dev->features & NETIF_F_LRO);
ret = fill_rx_buffers(sp, ring, 1);
if (ret) {
DBG_PRINT(ERR_DBG, "%s: Out of memory in Open\n",
@@ -7341,7 +7331,7 @@ static int s2io_card_up(struct s2io_nic *sp)
/* Setting its receive mode */
s2io_set_multicast(dev);
- if (sp->lro) {
+ if (dev->features & NETIF_F_LRO) {
/* Initialize max aggregatable pkts per session based on MTU */
sp->lro_max_aggr_per_sess = ((1<<16) - 1) / dev->mtu;
/* Check if we can use (if specified) user provided value */
@@ -7613,10 +7603,10 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp)
* Packet with erroneous checksum, let the
* upper layers deal with it.
*/
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
}
} else
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
swstats->mem_freed += skb->truesize;
send_up:
@@ -7911,7 +7901,6 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
else
sp->device_type = XFRAME_I_DEVICE;
- sp->lro = lro_enable;
/* Initialize some PCI/PCI-X fields of the NIC. */
s2io_init_pci(sp);
@@ -8047,8 +8036,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
dev->netdev_ops = &s2io_netdev_ops;
SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
- if (lro_enable)
- dev->features |= NETIF_F_LRO;
+ dev->features |= NETIF_F_LRO;
dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
if (sp->high_dma_flag == true)
dev->features |= NETIF_F_HIGHDMA;
@@ -8283,9 +8271,8 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
dev->name);
}
- if (sp->lro)
- DBG_PRINT(ERR_DBG, "%s: Large receive offload enabled\n",
- dev->name);
+ DBG_PRINT(ERR_DBG, "%s: Large receive offload enabled\n",
+ dev->name);
if (ufo)
DBG_PRINT(ERR_DBG,
"%s: UDP Fragmentation Offload(UFO) enabled\n",
diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h
index 0af033533905..00b8614efe48 100644
--- a/drivers/net/s2io.h
+++ b/drivers/net/s2io.h
@@ -816,12 +816,6 @@ struct mac_info {
struct stat_block *stats_info; /* Logical address of the stat block */
};
-/* structure representing the user defined MAC addresses */
-struct usr_addr {
- char addr[ETH_ALEN];
- int usage_cnt;
-};
-
/* Default Tunable parameters of the NIC. */
#define DEFAULT_FIFO_0_LEN 4096
#define DEFAULT_FIFO_1_7_LEN 512
@@ -894,9 +888,7 @@ struct s2io_nic {
#define ALL_MULTI 2
#define MAX_ADDRS_SUPPORTED 64
- u16 usr_addr_count;
u16 mc_addr_count;
- struct usr_addr usr_addrs[256];
u16 m_cast_flg;
u16 all_multi_pos;
@@ -971,7 +963,6 @@ struct s2io_nic {
unsigned long clubbed_frms_cnt;
unsigned long sending_both;
- u8 lro;
u16 lro_max_aggr_per_sess;
volatile unsigned long state;
u64 general_int_mask;
diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c
index 8e6bd45b9f31..d8249d7653c6 100644
--- a/drivers/net/sb1250-mac.c
+++ b/drivers/net/sb1250-mac.c
@@ -1170,7 +1170,7 @@ again:
sb->ip_summed = CHECKSUM_UNNECESSARY;
/* don't need to set sb->csum */
} else {
- sb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(sb);
}
}
prefetch(sb->data);
diff --git a/drivers/net/sc92031.c b/drivers/net/sc92031.c
index 8c4067af32b0..31b92f5f32cb 100644
--- a/drivers/net/sc92031.c
+++ b/drivers/net/sc92031.c
@@ -1251,16 +1251,6 @@ static int sc92031_ethtool_set_settings(struct net_device *dev,
return 0;
}
-static void sc92031_ethtool_get_drvinfo(struct net_device *dev,
- struct ethtool_drvinfo *drvinfo)
-{
- struct sc92031_priv *priv = netdev_priv(dev);
- struct pci_dev *pdev = priv->pdev;
-
- strcpy(drvinfo->driver, SC92031_NAME);
- strcpy(drvinfo->bus_info, pci_name(pdev));
-}
-
static void sc92031_ethtool_get_wol(struct net_device *dev,
struct ethtool_wolinfo *wolinfo)
{
@@ -1382,7 +1372,6 @@ static void sc92031_ethtool_get_ethtool_stats(struct net_device *dev,
static const struct ethtool_ops sc92031_ethtool_ops = {
.get_settings = sc92031_ethtool_get_settings,
.set_settings = sc92031_ethtool_set_settings,
- .get_drvinfo = sc92031_ethtool_get_drvinfo,
.get_wol = sc92031_ethtool_get_wol,
.set_wol = sc92031_ethtool_set_wol,
.nway_reset = sc92031_ethtool_nway_reset,
diff --git a/drivers/net/sfc/Makefile b/drivers/net/sfc/Makefile
index 1047b19c60a5..ab31c7124db1 100644
--- a/drivers/net/sfc/Makefile
+++ b/drivers/net/sfc/Makefile
@@ -1,7 +1,8 @@
-sfc-y += efx.o nic.o falcon.o siena.o tx.o rx.o \
- falcon_gmac.o falcon_xmac.o mcdi_mac.o \
+sfc-y += efx.o nic.o falcon.o siena.o tx.o rx.o filter.o \
+ falcon_xmac.o mcdi_mac.o \
selftest.o ethtool.o qt202x_phy.o mdio_10g.o \
- tenxpress.o falcon_boards.o mcdi.o mcdi_phy.o
+ tenxpress.o txc43128_phy.o falcon_boards.o \
+ mcdi.o mcdi_phy.o
sfc-$(CONFIG_SFC_MTD) += mtd.o
obj-$(CONFIG_SFC) += sfc.o
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index ba674c5ca29e..05df20e47976 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -68,14 +68,6 @@ const char *efx_loopback_mode_names[] = {
[LOOPBACK_PHYXS_WS] = "PHYXS_WS",
};
-/* Interrupt mode names (see INT_MODE())) */
-const unsigned int efx_interrupt_mode_max = EFX_INT_MODE_MAX;
-const char *efx_interrupt_mode_names[] = {
- [EFX_INT_MODE_MSIX] = "MSI-X",
- [EFX_INT_MODE_MSI] = "MSI",
- [EFX_INT_MODE_LEGACY] = "legacy",
-};
-
const unsigned int efx_reset_type_max = RESET_TYPE_MAX;
const char *efx_reset_type_names[] = {
[RESET_TYPE_INVISIBLE] = "INVISIBLE",
@@ -114,7 +106,7 @@ static struct workqueue_struct *reset_workqueue;
* This is only used in MSI-X interrupt mode
*/
static unsigned int separate_tx_channels;
-module_param(separate_tx_channels, uint, 0644);
+module_param(separate_tx_channels, uint, 0444);
MODULE_PARM_DESC(separate_tx_channels,
"Use separate channels for TX and RX");
@@ -124,10 +116,11 @@ MODULE_PARM_DESC(separate_tx_channels,
static int napi_weight = 64;
/* This is the time (in jiffies) between invocations of the hardware
- * monitor, which checks for known hardware bugs and resets the
- * hardware and driver as necessary.
+ * monitor. On Falcon-based NICs, this will:
+ * - Check the on-board hardware monitor;
+ * - Poll the link state and reconfigure the hardware as necessary.
*/
-unsigned int efx_monitor_interval = 1 * HZ;
+static unsigned int efx_monitor_interval = 1 * HZ;
/* This controls whether or not the driver will initialise devices
* with invalid MAC addresses stored in the EEPROM or flash. If true,
@@ -201,10 +194,13 @@ MODULE_PARM_DESC(debug, "Bitmapped debugging message enable value");
* Utility functions and prototypes
*
*************************************************************************/
-static void efx_remove_channel(struct efx_channel *channel);
+
+static void efx_remove_channels(struct efx_nic *efx);
static void efx_remove_port(struct efx_nic *efx);
static void efx_fini_napi(struct efx_nic *efx);
-static void efx_fini_channels(struct efx_nic *efx);
+static void efx_fini_struct(struct efx_nic *efx);
+static void efx_start_all(struct efx_nic *efx);
+static void efx_stop_all(struct efx_nic *efx);
#define EFX_ASSERT_RESET_SERIALISED(efx) \
do { \
@@ -248,7 +244,7 @@ static int efx_process_channel(struct efx_channel *channel, int budget)
efx_rx_strategy(channel);
- efx_fast_push_rx_descriptors(&efx->rx_queue[channel->channel]);
+ efx_fast_push_rx_descriptors(efx_channel_get_rx_queue(channel));
return spent;
}
@@ -334,6 +330,7 @@ void efx_process_channel_now(struct efx_channel *channel)
{
struct efx_nic *efx = channel->efx;
+ BUG_ON(channel->channel >= efx->n_channels);
BUG_ON(!channel->enabled);
/* Disable interrupts and wait for ISRs to complete */
@@ -347,7 +344,7 @@ void efx_process_channel_now(struct efx_channel *channel)
napi_disable(&channel->napi_str);
/* Poll the channel */
- efx_process_channel(channel, EFX_EVQ_SIZE);
+ efx_process_channel(channel, channel->eventq_mask + 1);
/* Ack the eventq. This may cause an interrupt to be generated
* when they are reenabled */
@@ -364,9 +361,18 @@ void efx_process_channel_now(struct efx_channel *channel)
*/
static int efx_probe_eventq(struct efx_channel *channel)
{
+ struct efx_nic *efx = channel->efx;
+ unsigned long entries;
+
netif_dbg(channel->efx, probe, channel->efx->net_dev,
"chan %d create event queue\n", channel->channel);
+ /* Build an event queue with room for one event per tx and rx buffer,
+ * plus some extra for link state events and MCDI completions. */
+ entries = roundup_pow_of_two(efx->rxq_entries + efx->txq_entries + 128);
+ EFX_BUG_ON_PARANOID(entries > EFX_MAX_EVQ_SIZE);
+ channel->eventq_mask = max(entries, EFX_MIN_EVQ_SIZE) - 1;
+
return efx_nic_probe_eventq(channel);
}
@@ -403,6 +409,63 @@ static void efx_remove_eventq(struct efx_channel *channel)
*
*************************************************************************/
+/* Allocate and initialise a channel structure, optionally copying
+ * parameters (but not resources) from an old channel structure. */
+static struct efx_channel *
+efx_alloc_channel(struct efx_nic *efx, int i, struct efx_channel *old_channel)
+{
+ struct efx_channel *channel;
+ struct efx_rx_queue *rx_queue;
+ struct efx_tx_queue *tx_queue;
+ int j;
+
+ if (old_channel) {
+ channel = kmalloc(sizeof(*channel), GFP_KERNEL);
+ if (!channel)
+ return NULL;
+
+ *channel = *old_channel;
+
+ memset(&channel->eventq, 0, sizeof(channel->eventq));
+
+ rx_queue = &channel->rx_queue;
+ rx_queue->buffer = NULL;
+ memset(&rx_queue->rxd, 0, sizeof(rx_queue->rxd));
+
+ for (j = 0; j < EFX_TXQ_TYPES; j++) {
+ tx_queue = &channel->tx_queue[j];
+ if (tx_queue->channel)
+ tx_queue->channel = channel;
+ tx_queue->buffer = NULL;
+ memset(&tx_queue->txd, 0, sizeof(tx_queue->txd));
+ }
+ } else {
+ channel = kzalloc(sizeof(*channel), GFP_KERNEL);
+ if (!channel)
+ return NULL;
+
+ channel->efx = efx;
+ channel->channel = i;
+
+ for (j = 0; j < EFX_TXQ_TYPES; j++) {
+ tx_queue = &channel->tx_queue[j];
+ tx_queue->efx = efx;
+ tx_queue->queue = i * EFX_TXQ_TYPES + j;
+ tx_queue->channel = channel;
+ }
+ }
+
+ spin_lock_init(&channel->tx_stop_lock);
+ atomic_set(&channel->tx_stop_count, 1);
+
+ rx_queue = &channel->rx_queue;
+ rx_queue->efx = efx;
+ setup_timer(&rx_queue->slow_fill, efx_rx_slow_fill,
+ (unsigned long)rx_queue);
+
+ return channel;
+}
+
static int efx_probe_channel(struct efx_channel *channel)
{
struct efx_tx_queue *tx_queue;
@@ -459,11 +522,38 @@ static void efx_set_channel_names(struct efx_nic *efx)
number -= efx->n_rx_channels;
}
}
- snprintf(channel->name, sizeof(channel->name),
+ snprintf(efx->channel_name[channel->channel],
+ sizeof(efx->channel_name[0]),
"%s%s-%d", efx->name, type, number);
}
}
+static int efx_probe_channels(struct efx_nic *efx)
+{
+ struct efx_channel *channel;
+ int rc;
+
+ /* Restart special buffer allocation */
+ efx->next_buffer_table = 0;
+
+ efx_for_each_channel(channel, efx) {
+ rc = efx_probe_channel(channel);
+ if (rc) {
+ netif_err(efx, probe, efx->net_dev,
+ "failed to create channel %d\n",
+ channel->channel);
+ goto fail;
+ }
+ }
+ efx_set_channel_names(efx);
+
+ return 0;
+
+fail:
+ efx_remove_channels(efx);
+ return rc;
+}
+
/* Channels are shutdown and reinitialised whilst the NIC is running
* to propagate configuration changes (mtu, checksum offload), or
* to clear hardware error conditions
@@ -601,6 +691,75 @@ static void efx_remove_channel(struct efx_channel *channel)
efx_remove_eventq(channel);
}
+static void efx_remove_channels(struct efx_nic *efx)
+{
+ struct efx_channel *channel;
+
+ efx_for_each_channel(channel, efx)
+ efx_remove_channel(channel);
+}
+
+int
+efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries)
+{
+ struct efx_channel *other_channel[EFX_MAX_CHANNELS], *channel;
+ u32 old_rxq_entries, old_txq_entries;
+ unsigned i;
+ int rc;
+
+ efx_stop_all(efx);
+ efx_fini_channels(efx);
+
+ /* Clone channels */
+ memset(other_channel, 0, sizeof(other_channel));
+ for (i = 0; i < efx->n_channels; i++) {
+ channel = efx_alloc_channel(efx, i, efx->channel[i]);
+ if (!channel) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ other_channel[i] = channel;
+ }
+
+ /* Swap entry counts and channel pointers */
+ old_rxq_entries = efx->rxq_entries;
+ old_txq_entries = efx->txq_entries;
+ efx->rxq_entries = rxq_entries;
+ efx->txq_entries = txq_entries;
+ for (i = 0; i < efx->n_channels; i++) {
+ channel = efx->channel[i];
+ efx->channel[i] = other_channel[i];
+ other_channel[i] = channel;
+ }
+
+ rc = efx_probe_channels(efx);
+ if (rc)
+ goto rollback;
+
+ /* Destroy old channels */
+ for (i = 0; i < efx->n_channels; i++)
+ efx_remove_channel(other_channel[i]);
+out:
+ /* Free unused channel structures */
+ for (i = 0; i < efx->n_channels; i++)
+ kfree(other_channel[i]);
+
+ efx_init_channels(efx);
+ efx_start_all(efx);
+ return rc;
+
+rollback:
+ /* Swap back */
+ efx->rxq_entries = old_rxq_entries;
+ efx->txq_entries = old_txq_entries;
+ for (i = 0; i < efx->n_channels; i++) {
+ channel = efx->channel[i];
+ efx->channel[i] = other_channel[i];
+ other_channel[i] = channel;
+ }
+ goto out;
+}
+
void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue)
{
mod_timer(&rx_queue->slow_fill, jiffies + msecs_to_jiffies(100));
@@ -761,7 +920,7 @@ static int efx_probe_port(struct efx_nic *efx)
/* Connect up MAC/PHY operations table */
rc = efx->type->probe_port(efx);
if (rc)
- goto err;
+ return rc;
/* Sanity check MAC address */
if (is_valid_ether_addr(efx->mac_address)) {
@@ -782,7 +941,7 @@ static int efx_probe_port(struct efx_nic *efx)
return 0;
err:
- efx_remove_port(efx);
+ efx->type->remove_port(efx);
return rc;
}
@@ -1050,7 +1209,8 @@ static void efx_probe_interrupts(struct efx_nic *efx)
efx->n_rx_channels = efx->n_channels;
}
for (i = 0; i < n_channels; i++)
- efx->channel[i].irq = xentries[i].vector;
+ efx_get_channel(efx, i)->irq =
+ xentries[i].vector;
} else {
/* Fall back to single channel MSI */
efx->interrupt_mode = EFX_INT_MODE_MSI;
@@ -1066,7 +1226,7 @@ static void efx_probe_interrupts(struct efx_nic *efx)
efx->n_tx_channels = 1;
rc = pci_enable_msi(efx->pci_dev);
if (rc == 0) {
- efx->channel[0].irq = efx->pci_dev->irq;
+ efx_get_channel(efx, 0)->irq = efx->pci_dev->irq;
} else {
netif_err(efx, drv, efx->net_dev,
"could not enable MSI\n");
@@ -1097,26 +1257,32 @@ static void efx_remove_interrupts(struct efx_nic *efx)
efx->legacy_irq = 0;
}
+struct efx_tx_queue *
+efx_get_tx_queue(struct efx_nic *efx, unsigned index, unsigned type)
+{
+ unsigned tx_channel_offset =
+ separate_tx_channels ? efx->n_channels - efx->n_tx_channels : 0;
+ EFX_BUG_ON_PARANOID(index >= efx->n_tx_channels ||
+ type >= EFX_TXQ_TYPES);
+ return &efx->channel[tx_channel_offset + index]->tx_queue[type];
+}
+
static void efx_set_channels(struct efx_nic *efx)
{
struct efx_channel *channel;
struct efx_tx_queue *tx_queue;
- struct efx_rx_queue *rx_queue;
unsigned tx_channel_offset =
separate_tx_channels ? efx->n_channels - efx->n_tx_channels : 0;
+ /* Channel pointers were set in efx_init_struct() but we now
+ * need to clear them for TX queues in any RX-only channels. */
efx_for_each_channel(channel, efx) {
- if (channel->channel - tx_channel_offset < efx->n_tx_channels) {
- channel->tx_queue = &efx->tx_queue[
- (channel->channel - tx_channel_offset) *
- EFX_TXQ_TYPES];
+ if (channel->channel - tx_channel_offset >=
+ efx->n_tx_channels) {
efx_for_each_channel_tx_queue(tx_queue, channel)
- tx_queue->channel = channel;
+ tx_queue->channel = NULL;
}
}
-
- efx_for_each_rx_queue(rx_queue, efx)
- rx_queue->channel = &efx->channel[rx_queue->queue];
}
static int efx_probe_nic(struct efx_nic *efx)
@@ -1141,7 +1307,8 @@ static int efx_probe_nic(struct efx_nic *efx)
efx->rx_indir_table[i] = i % efx->n_rx_channels;
efx_set_channels(efx);
- efx->net_dev->real_num_tx_queues = efx->n_tx_channels;
+ netif_set_real_num_tx_queues(efx->net_dev, efx->n_tx_channels);
+ netif_set_real_num_rx_queues(efx->net_dev, efx->n_rx_channels);
/* Initialise the interrupt moderation settings */
efx_init_irq_moderation(efx, tx_irq_mod_usec, rx_irq_mod_usec, true);
@@ -1165,40 +1332,37 @@ static void efx_remove_nic(struct efx_nic *efx)
static int efx_probe_all(struct efx_nic *efx)
{
- struct efx_channel *channel;
int rc;
- /* Create NIC */
rc = efx_probe_nic(efx);
if (rc) {
netif_err(efx, probe, efx->net_dev, "failed to create NIC\n");
goto fail1;
}
- /* Create port */
rc = efx_probe_port(efx);
if (rc) {
netif_err(efx, probe, efx->net_dev, "failed to create port\n");
goto fail2;
}
- /* Create channels */
- efx_for_each_channel(channel, efx) {
- rc = efx_probe_channel(channel);
- if (rc) {
- netif_err(efx, probe, efx->net_dev,
- "failed to create channel %d\n",
- channel->channel);
- goto fail3;
- }
+ efx->rxq_entries = efx->txq_entries = EFX_DEFAULT_DMAQ_SIZE;
+ rc = efx_probe_channels(efx);
+ if (rc)
+ goto fail3;
+
+ rc = efx_probe_filters(efx);
+ if (rc) {
+ netif_err(efx, probe, efx->net_dev,
+ "failed to create filter tables\n");
+ goto fail4;
}
- efx_set_channel_names(efx);
return 0;
+ fail4:
+ efx_remove_channels(efx);
fail3:
- efx_for_each_channel(channel, efx)
- efx_remove_channel(channel);
efx_remove_port(efx);
fail2:
efx_remove_nic(efx);
@@ -1328,10 +1492,8 @@ static void efx_stop_all(struct efx_nic *efx)
static void efx_remove_all(struct efx_nic *efx)
{
- struct efx_channel *channel;
-
- efx_for_each_channel(channel, efx)
- efx_remove_channel(channel);
+ efx_remove_filters(efx);
+ efx_remove_channels(efx);
efx_remove_port(efx);
efx_remove_nic(efx);
}
@@ -1355,20 +1517,20 @@ static unsigned irq_mod_ticks(int usecs, int resolution)
void efx_init_irq_moderation(struct efx_nic *efx, int tx_usecs, int rx_usecs,
bool rx_adaptive)
{
- struct efx_tx_queue *tx_queue;
- struct efx_rx_queue *rx_queue;
+ struct efx_channel *channel;
unsigned tx_ticks = irq_mod_ticks(tx_usecs, EFX_IRQ_MOD_RESOLUTION);
unsigned rx_ticks = irq_mod_ticks(rx_usecs, EFX_IRQ_MOD_RESOLUTION);
EFX_ASSERT_RESET_SERIALISED(efx);
- efx_for_each_tx_queue(tx_queue, efx)
- tx_queue->channel->irq_moderation = tx_ticks;
-
efx->irq_rx_adaptive = rx_adaptive;
efx->irq_rx_moderation = rx_ticks;
- efx_for_each_rx_queue(rx_queue, efx)
- rx_queue->channel->irq_moderation = rx_ticks;
+ efx_for_each_channel(channel, efx) {
+ if (efx_channel_get_rx_queue(channel))
+ channel->irq_moderation = rx_ticks;
+ else if (efx_channel_get_tx_queue(channel, 0))
+ channel->irq_moderation = tx_ticks;
+ }
}
/**************************************************************************
@@ -1377,8 +1539,7 @@ void efx_init_irq_moderation(struct efx_nic *efx, int tx_usecs, int rx_usecs,
*
**************************************************************************/
-/* Run periodically off the general workqueue. Serialised against
- * efx_reconfigure_port via the mac_lock */
+/* Run periodically off the general workqueue */
static void efx_monitor(struct work_struct *data)
{
struct efx_nic *efx = container_of(data, struct efx_nic,
@@ -1391,16 +1552,13 @@ static void efx_monitor(struct work_struct *data)
/* If the mac_lock is already held then it is likely a port
* reconfiguration is already in place, which will likely do
- * most of the work of check_hw() anyway. */
- if (!mutex_trylock(&efx->mac_lock))
- goto out_requeue;
- if (!efx->port_enabled)
- goto out_unlock;
- efx->type->monitor(efx);
+ * most of the work of monitor() anyway. */
+ if (mutex_trylock(&efx->mac_lock)) {
+ if (efx->port_enabled)
+ efx->type->monitor(efx);
+ mutex_unlock(&efx->mac_lock);
+ }
-out_unlock:
- mutex_unlock(&efx->mac_lock);
-out_requeue:
queue_delayed_work(efx->workqueue, &efx->monitor_work,
efx_monitor_interval);
}
@@ -1546,11 +1704,11 @@ static struct rtnl_link_stats64 *efx_net_stats(struct net_device *net_dev, struc
stats->tx_packets = mac_stats->tx_packets;
stats->rx_bytes = mac_stats->rx_bytes;
stats->tx_bytes = mac_stats->tx_bytes;
+ stats->rx_dropped = efx->n_rx_nodesc_drop_cnt;
stats->multicast = mac_stats->rx_multicast;
stats->collisions = mac_stats->tx_collision;
stats->rx_length_errors = (mac_stats->rx_gtjumbo +
mac_stats->rx_length_error);
- stats->rx_over_errors = efx->n_rx_nodesc_drop_cnt;
stats->rx_crc_errors = mac_stats->rx_bad;
stats->rx_frame_errors = mac_stats->rx_align_error;
stats->rx_fifo_errors = mac_stats->rx_overflow;
@@ -1767,6 +1925,7 @@ fail_registered:
static void efx_unregister_netdev(struct efx_nic *efx)
{
+ struct efx_channel *channel;
struct efx_tx_queue *tx_queue;
if (!efx->net_dev)
@@ -1777,8 +1936,10 @@ static void efx_unregister_netdev(struct efx_nic *efx)
/* Free up any skbs still remaining. This has to happen before
* we try to unregister the netdev as running their destructors
* may be needed to get the device ref. count to 0. */
- efx_for_each_tx_queue(tx_queue, efx)
- efx_release_tx_buffers(tx_queue);
+ efx_for_each_channel(channel, efx) {
+ efx_for_each_channel_tx_queue(tx_queue, channel)
+ efx_release_tx_buffers(tx_queue);
+ }
if (efx_dev_registered(efx)) {
strlcpy(efx->name, pci_name(efx->pci_dev), sizeof(efx->name));
@@ -1841,6 +2002,7 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok)
efx->mac_op->reconfigure(efx);
efx_init_channels(efx);
+ efx_restore_filters(efx);
mutex_unlock(&efx->spi_lock);
mutex_unlock(&efx->mac_lock);
@@ -2010,10 +2172,8 @@ int efx_port_dummy_op_int(struct efx_nic *efx)
return 0;
}
void efx_port_dummy_op_void(struct efx_nic *efx) {}
-void efx_port_dummy_op_set_id_led(struct efx_nic *efx, enum efx_led_mode mode)
-{
-}
-bool efx_port_dummy_op_poll(struct efx_nic *efx)
+
+static bool efx_port_dummy_op_poll(struct efx_nic *efx)
{
return false;
}
@@ -2037,9 +2197,6 @@ static struct efx_phy_operations efx_dummy_phy_operations = {
static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,
struct pci_dev *pci_dev, struct net_device *net_dev)
{
- struct efx_channel *channel;
- struct efx_tx_queue *tx_queue;
- struct efx_rx_queue *rx_queue;
int i;
/* Initialise common structures */
@@ -2068,36 +2225,13 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,
INIT_WORK(&efx->mac_work, efx_mac_work);
for (i = 0; i < EFX_MAX_CHANNELS; i++) {
- channel = &efx->channel[i];
- channel->efx = efx;
- channel->channel = i;
- channel->work_pending = false;
- spin_lock_init(&channel->tx_stop_lock);
- atomic_set(&channel->tx_stop_count, 1);
- }
- for (i = 0; i < EFX_MAX_TX_QUEUES; i++) {
- tx_queue = &efx->tx_queue[i];
- tx_queue->efx = efx;
- tx_queue->queue = i;
- tx_queue->buffer = NULL;
- tx_queue->channel = &efx->channel[0]; /* for safety */
- tx_queue->tso_headers_free = NULL;
- }
- for (i = 0; i < EFX_MAX_RX_QUEUES; i++) {
- rx_queue = &efx->rx_queue[i];
- rx_queue->efx = efx;
- rx_queue->queue = i;
- rx_queue->channel = &efx->channel[0]; /* for safety */
- rx_queue->buffer = NULL;
- setup_timer(&rx_queue->slow_fill, efx_rx_slow_fill,
- (unsigned long)rx_queue);
+ efx->channel[i] = efx_alloc_channel(efx, i, NULL);
+ if (!efx->channel[i])
+ goto fail;
}
efx->type = type;
- /* As close as we can get to guaranteeing that we don't overflow */
- BUILD_BUG_ON(EFX_EVQ_SIZE < EFX_TXQ_SIZE + EFX_RXQ_SIZE);
-
EFX_BUG_ON_PARANOID(efx->type->phys_addr_channels > EFX_MAX_CHANNELS);
/* Higher numbered interrupt modes are less capable! */
@@ -2109,13 +2243,22 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,
pci_name(pci_dev));
efx->workqueue = create_singlethread_workqueue(efx->workqueue_name);
if (!efx->workqueue)
- return -ENOMEM;
+ goto fail;
return 0;
+
+fail:
+ efx_fini_struct(efx);
+ return -ENOMEM;
}
static void efx_fini_struct(struct efx_nic *efx)
{
+ int i;
+
+ for (i = 0; i < EFX_MAX_CHANNELS; i++)
+ kfree(efx->channel[i]);
+
if (efx->workqueue) {
destroy_workqueue(efx->workqueue);
efx->workqueue = NULL;
diff --git a/drivers/net/sfc/efx.h b/drivers/net/sfc/efx.h
index 060dc952a0fd..10a1bf40da96 100644
--- a/drivers/net/sfc/efx.h
+++ b/drivers/net/sfc/efx.h
@@ -12,6 +12,7 @@
#define EFX_EFX_H
#include "net_driver.h"
+#include "filter.h"
/* PCI IDs */
#define EFX_VENDID_SFC 0x1924
@@ -37,8 +38,6 @@ efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb);
extern void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index);
extern void efx_stop_queue(struct efx_channel *channel);
extern void efx_wake_queue(struct efx_channel *channel);
-#define EFX_TXQ_SIZE 1024
-#define EFX_TXQ_MASK (EFX_TXQ_SIZE - 1)
/* RX */
extern int efx_probe_rx_queue(struct efx_rx_queue *rx_queue);
@@ -53,23 +52,42 @@ extern void __efx_rx_packet(struct efx_channel *channel,
extern void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
unsigned int len, bool checksummed, bool discard);
extern void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue);
-#define EFX_RXQ_SIZE 1024
-#define EFX_RXQ_MASK (EFX_RXQ_SIZE - 1)
+
+#define EFX_MAX_DMAQ_SIZE 4096UL
+#define EFX_DEFAULT_DMAQ_SIZE 1024UL
+#define EFX_MIN_DMAQ_SIZE 512UL
+
+#define EFX_MAX_EVQ_SIZE 16384UL
+#define EFX_MIN_EVQ_SIZE 512UL
+
+/* The smallest [rt]xq_entries that the driver supports. Callers of
+ * efx_wake_queue() assume that they can subsequently send at least one
+ * skb. Falcon/A1 may require up to three descriptors per skb_frag. */
+#define EFX_MIN_RING_SIZE (roundup_pow_of_two(2 * 3 * MAX_SKB_FRAGS))
+
+/* Filters */
+extern int efx_probe_filters(struct efx_nic *efx);
+extern void efx_restore_filters(struct efx_nic *efx);
+extern void efx_remove_filters(struct efx_nic *efx);
+extern int efx_filter_insert_filter(struct efx_nic *efx,
+ struct efx_filter_spec *spec,
+ bool replace);
+extern int efx_filter_remove_filter(struct efx_nic *efx,
+ struct efx_filter_spec *spec);
+extern void efx_filter_table_clear(struct efx_nic *efx,
+ enum efx_filter_table_id table_id,
+ enum efx_filter_priority priority);
/* Channels */
extern void efx_process_channel_now(struct efx_channel *channel);
-#define EFX_EVQ_SIZE 4096
-#define EFX_EVQ_MASK (EFX_EVQ_SIZE - 1)
+extern int
+efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries);
/* Ports */
extern int efx_reconfigure_port(struct efx_nic *efx);
extern int __efx_reconfigure_port(struct efx_nic *efx);
/* Ethtool support */
-extern int efx_ethtool_get_settings(struct net_device *net_dev,
- struct ethtool_cmd *ecmd);
-extern int efx_ethtool_set_settings(struct net_device *net_dev,
- struct ethtool_cmd *ecmd);
extern const struct ethtool_ops efx_ethtool_ops;
/* Reset handling */
@@ -81,15 +99,11 @@ extern int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok);
extern void efx_schedule_reset(struct efx_nic *efx, enum reset_type type);
extern void efx_init_irq_moderation(struct efx_nic *efx, int tx_usecs,
int rx_usecs, bool rx_adaptive);
-extern int efx_request_power(struct efx_nic *efx, int mw, const char *name);
-extern void efx_hex_dump(const u8 *, unsigned int, const char *);
/* Dummy PHY ops for PHY drivers */
extern int efx_port_dummy_op_int(struct efx_nic *efx);
extern void efx_port_dummy_op_void(struct efx_nic *efx);
-extern void
-efx_port_dummy_op_set_id_led(struct efx_nic *efx, enum efx_led_mode mode);
-extern bool efx_port_dummy_op_poll(struct efx_nic *efx);
+
/* MTD */
#ifdef CONFIG_SFC_MTD
@@ -102,8 +116,6 @@ static inline void efx_mtd_rename(struct efx_nic *efx) {}
static inline void efx_mtd_remove(struct efx_nic *efx) {}
#endif
-extern unsigned int efx_monitor_interval;
-
static inline void efx_schedule_channel(struct efx_channel *channel)
{
netif_vdbg(channel->efx, intr, channel->efx->net_dev,
diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c
index fd19d6ab97a2..edb9d16b8b47 100644
--- a/drivers/net/sfc/ethtool.c
+++ b/drivers/net/sfc/ethtool.c
@@ -15,6 +15,7 @@
#include "workarounds.h"
#include "selftest.h"
#include "efx.h"
+#include "filter.h"
#include "nic.h"
#include "spi.h"
#include "mdio_10g.h"
@@ -186,8 +187,8 @@ static int efx_ethtool_phys_id(struct net_device *net_dev, u32 count)
}
/* This must be called with rtnl_lock held. */
-int efx_ethtool_get_settings(struct net_device *net_dev,
- struct ethtool_cmd *ecmd)
+static int efx_ethtool_get_settings(struct net_device *net_dev,
+ struct ethtool_cmd *ecmd)
{
struct efx_nic *efx = netdev_priv(net_dev);
struct efx_link_state *link_state = &efx->link_state;
@@ -210,8 +211,8 @@ int efx_ethtool_get_settings(struct net_device *net_dev,
}
/* This must be called with rtnl_lock held. */
-int efx_ethtool_set_settings(struct net_device *net_dev,
- struct ethtool_cmd *ecmd)
+static int efx_ethtool_set_settings(struct net_device *net_dev,
+ struct ethtool_cmd *ecmd)
{
struct efx_nic *efx = netdev_priv(net_dev);
int rc;
@@ -328,9 +329,10 @@ static int efx_fill_loopback_test(struct efx_nic *efx,
unsigned int test_index,
struct ethtool_string *strings, u64 *data)
{
+ struct efx_channel *channel = efx_get_channel(efx, 0);
struct efx_tx_queue *tx_queue;
- efx_for_each_channel_tx_queue(tx_queue, &efx->channel[0]) {
+ efx_for_each_channel_tx_queue(tx_queue, channel) {
efx_fill_test(test_index++, strings, data,
&lb_tests->tx_sent[tx_queue->queue],
EFX_TX_QUEUE_NAME(tx_queue),
@@ -550,9 +552,22 @@ static u32 efx_ethtool_get_rx_csum(struct net_device *net_dev)
static int efx_ethtool_set_flags(struct net_device *net_dev, u32 data)
{
struct efx_nic *efx = netdev_priv(net_dev);
- u32 supported = efx->type->offload_features & ETH_FLAG_RXHASH;
+ u32 supported = (efx->type->offload_features &
+ (ETH_FLAG_RXHASH | ETH_FLAG_NTUPLE));
+ int rc;
+
+ rc = ethtool_op_set_flags(net_dev, data, supported);
+ if (rc)
+ return rc;
- return ethtool_op_set_flags(net_dev, data, supported);
+ if (!(data & ETH_FLAG_NTUPLE)) {
+ efx_filter_table_clear(efx, EFX_FILTER_TABLE_RX_IP,
+ EFX_FILTER_PRI_MANUAL);
+ efx_filter_table_clear(efx, EFX_FILTER_TABLE_RX_MAC,
+ EFX_FILTER_PRI_MANUAL);
+ }
+
+ return 0;
}
static void efx_ethtool_self_test(struct net_device *net_dev,
@@ -673,15 +688,15 @@ static int efx_ethtool_get_coalesce(struct net_device *net_dev,
struct ethtool_coalesce *coalesce)
{
struct efx_nic *efx = netdev_priv(net_dev);
- struct efx_tx_queue *tx_queue;
struct efx_channel *channel;
memset(coalesce, 0, sizeof(*coalesce));
/* Find lowest IRQ moderation across all used TX queues */
coalesce->tx_coalesce_usecs_irq = ~((u32) 0);
- efx_for_each_tx_queue(tx_queue, efx) {
- channel = tx_queue->channel;
+ efx_for_each_channel(channel, efx) {
+ if (!efx_channel_get_tx_queue(channel, 0))
+ continue;
if (channel->irq_moderation < coalesce->tx_coalesce_usecs_irq) {
if (channel->channel < efx->n_rx_channels)
coalesce->tx_coalesce_usecs_irq =
@@ -708,7 +723,6 @@ static int efx_ethtool_set_coalesce(struct net_device *net_dev,
{
struct efx_nic *efx = netdev_priv(net_dev);
struct efx_channel *channel;
- struct efx_tx_queue *tx_queue;
unsigned tx_usecs, rx_usecs, adaptive;
if (coalesce->use_adaptive_tx_coalesce)
@@ -725,8 +739,9 @@ static int efx_ethtool_set_coalesce(struct net_device *net_dev,
adaptive = coalesce->use_adaptive_rx_coalesce;
/* If the channel is shared only allow RX parameters to be set */
- efx_for_each_tx_queue(tx_queue, efx) {
- if ((tx_queue->channel->channel < efx->n_rx_channels) &&
+ efx_for_each_channel(channel, efx) {
+ if (efx_channel_get_rx_queue(channel) &&
+ efx_channel_get_tx_queue(channel, 0) &&
tx_usecs) {
netif_err(efx, drv, efx->net_dev, "Channel is shared. "
"Only RX coalescing may be set\n");
@@ -741,6 +756,42 @@ static int efx_ethtool_set_coalesce(struct net_device *net_dev,
return 0;
}
+static void efx_ethtool_get_ringparam(struct net_device *net_dev,
+ struct ethtool_ringparam *ring)
+{
+ struct efx_nic *efx = netdev_priv(net_dev);
+
+ ring->rx_max_pending = EFX_MAX_DMAQ_SIZE;
+ ring->tx_max_pending = EFX_MAX_DMAQ_SIZE;
+ ring->rx_mini_max_pending = 0;
+ ring->rx_jumbo_max_pending = 0;
+ ring->rx_pending = efx->rxq_entries;
+ ring->tx_pending = efx->txq_entries;
+ ring->rx_mini_pending = 0;
+ ring->rx_jumbo_pending = 0;
+}
+
+static int efx_ethtool_set_ringparam(struct net_device *net_dev,
+ struct ethtool_ringparam *ring)
+{
+ struct efx_nic *efx = netdev_priv(net_dev);
+
+ if (ring->rx_mini_pending || ring->rx_jumbo_pending ||
+ ring->rx_pending > EFX_MAX_DMAQ_SIZE ||
+ ring->tx_pending > EFX_MAX_DMAQ_SIZE)
+ return -EINVAL;
+
+ if (ring->rx_pending < EFX_MIN_RING_SIZE ||
+ ring->tx_pending < EFX_MIN_RING_SIZE) {
+ netif_err(efx, drv, efx->net_dev,
+ "TX and RX queues cannot be smaller than %ld\n",
+ EFX_MIN_RING_SIZE);
+ return -EINVAL;
+ }
+
+ return efx_realloc_channels(efx, ring->rx_pending, ring->tx_pending);
+}
+
static int efx_ethtool_set_pauseparam(struct net_device *net_dev,
struct ethtool_pauseparam *pause)
{
@@ -840,7 +891,7 @@ static int efx_ethtool_set_wol(struct net_device *net_dev,
return efx->type->set_wol(efx, wol->wolopts);
}
-extern int efx_ethtool_reset(struct net_device *net_dev, u32 *flags)
+static int efx_ethtool_reset(struct net_device *net_dev, u32 *flags)
{
struct efx_nic *efx = netdev_priv(net_dev);
enum reset_type method;
@@ -918,6 +969,105 @@ efx_ethtool_get_rxnfc(struct net_device *net_dev,
}
}
+static int efx_ethtool_set_rx_ntuple(struct net_device *net_dev,
+ struct ethtool_rx_ntuple *ntuple)
+{
+ struct efx_nic *efx = netdev_priv(net_dev);
+ struct ethtool_tcpip4_spec *ip_entry = &ntuple->fs.h_u.tcp_ip4_spec;
+ struct ethtool_tcpip4_spec *ip_mask = &ntuple->fs.m_u.tcp_ip4_spec;
+ struct ethhdr *mac_entry = &ntuple->fs.h_u.ether_spec;
+ struct ethhdr *mac_mask = &ntuple->fs.m_u.ether_spec;
+ struct efx_filter_spec filter;
+
+ /* Range-check action */
+ if (ntuple->fs.action < ETHTOOL_RXNTUPLE_ACTION_CLEAR ||
+ ntuple->fs.action >= (s32)efx->n_rx_channels)
+ return -EINVAL;
+
+ if (~ntuple->fs.data_mask)
+ return -EINVAL;
+
+ switch (ntuple->fs.flow_type) {
+ case TCP_V4_FLOW:
+ case UDP_V4_FLOW:
+ /* Must match all of destination, */
+ if (ip_mask->ip4dst | ip_mask->pdst)
+ return -EINVAL;
+ /* all or none of source, */
+ if ((ip_mask->ip4src | ip_mask->psrc) &&
+ ((__force u32)~ip_mask->ip4src |
+ (__force u16)~ip_mask->psrc))
+ return -EINVAL;
+ /* and nothing else */
+ if ((u8)~ip_mask->tos | (u16)~ntuple->fs.vlan_tag_mask)
+ return -EINVAL;
+ break;
+ case ETHER_FLOW:
+ /* Must match all of destination, */
+ if (!is_zero_ether_addr(mac_mask->h_dest))
+ return -EINVAL;
+ /* all or none of VID, */
+ if (ntuple->fs.vlan_tag_mask != 0xf000 &&
+ ntuple->fs.vlan_tag_mask != 0xffff)
+ return -EINVAL;
+ /* and nothing else */
+ if (!is_broadcast_ether_addr(mac_mask->h_source) ||
+ mac_mask->h_proto != htons(0xffff))
+ return -EINVAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ filter.priority = EFX_FILTER_PRI_MANUAL;
+ filter.flags = 0;
+
+ switch (ntuple->fs.flow_type) {
+ case TCP_V4_FLOW:
+ if (!ip_mask->ip4src)
+ efx_filter_set_rx_tcp_full(&filter,
+ htonl(ip_entry->ip4src),
+ htons(ip_entry->psrc),
+ htonl(ip_entry->ip4dst),
+ htons(ip_entry->pdst));
+ else
+ efx_filter_set_rx_tcp_wild(&filter,
+ htonl(ip_entry->ip4dst),
+ htons(ip_entry->pdst));
+ break;
+ case UDP_V4_FLOW:
+ if (!ip_mask->ip4src)
+ efx_filter_set_rx_udp_full(&filter,
+ htonl(ip_entry->ip4src),
+ htons(ip_entry->psrc),
+ htonl(ip_entry->ip4dst),
+ htons(ip_entry->pdst));
+ else
+ efx_filter_set_rx_udp_wild(&filter,
+ htonl(ip_entry->ip4dst),
+ htons(ip_entry->pdst));
+ break;
+ case ETHER_FLOW:
+ if (ntuple->fs.vlan_tag_mask == 0xf000)
+ efx_filter_set_rx_mac_full(&filter,
+ ntuple->fs.vlan_tag & 0xfff,
+ mac_entry->h_dest);
+ else
+ efx_filter_set_rx_mac_wild(&filter, mac_entry->h_dest);
+ break;
+ }
+
+ if (ntuple->fs.action == ETHTOOL_RXNTUPLE_ACTION_CLEAR) {
+ return efx_filter_remove_filter(efx, &filter);
+ } else {
+ if (ntuple->fs.action == ETHTOOL_RXNTUPLE_ACTION_DROP)
+ filter.dmaq_id = 0xfff;
+ else
+ filter.dmaq_id = ntuple->fs.action;
+ return efx_filter_insert_filter(efx, &filter, true);
+ }
+}
+
static int efx_ethtool_get_rxfh_indir(struct net_device *net_dev,
struct ethtool_rxfh_indir *indir)
{
@@ -971,6 +1121,8 @@ const struct ethtool_ops efx_ethtool_ops = {
.set_eeprom = efx_ethtool_set_eeprom,
.get_coalesce = efx_ethtool_get_coalesce,
.set_coalesce = efx_ethtool_set_coalesce,
+ .get_ringparam = efx_ethtool_get_ringparam,
+ .set_ringparam = efx_ethtool_set_ringparam,
.get_pauseparam = efx_ethtool_get_pauseparam,
.set_pauseparam = efx_ethtool_set_pauseparam,
.get_rx_csum = efx_ethtool_get_rx_csum,
@@ -994,6 +1146,7 @@ const struct ethtool_ops efx_ethtool_ops = {
.set_wol = efx_ethtool_set_wol,
.reset = efx_ethtool_reset,
.get_rxnfc = efx_ethtool_get_rxnfc,
+ .set_rx_ntuple = efx_ethtool_set_rx_ntuple,
.get_rxfh_indir = efx_ethtool_get_rxfh_indir,
.set_rxfh_indir = efx_ethtool_set_rxfh_indir,
};
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c
index 4f9d33f3cca1..267019bb2b15 100644
--- a/drivers/net/sfc/falcon.c
+++ b/drivers/net/sfc/falcon.c
@@ -159,7 +159,6 @@ irqreturn_t falcon_legacy_interrupt_a1(int irq, void *dev_id)
{
struct efx_nic *efx = dev_id;
efx_oword_t *int_ker = efx->irq_status.addr;
- struct efx_channel *channel;
int syserr;
int queues;
@@ -194,15 +193,10 @@ irqreturn_t falcon_legacy_interrupt_a1(int irq, void *dev_id)
wmb(); /* Ensure the vector is cleared before interrupt ack */
falcon_irq_ack_a1(efx);
- /* Schedule processing of any interrupting queues */
- channel = &efx->channel[0];
- while (queues) {
- if (queues & 0x01)
- efx_schedule_channel(channel);
- channel++;
- queues >>= 1;
- }
-
+ if (queues & 1)
+ efx_schedule_channel(efx_get_channel(efx, 0));
+ if (queues & 2)
+ efx_schedule_channel(efx_get_channel(efx, 1));
return IRQ_HANDLED;
}
/**************************************************************************
@@ -452,30 +446,19 @@ static void falcon_reset_macs(struct efx_nic *efx)
/* It's not safe to use GLB_CTL_REG to reset the
* macs, so instead use the internal MAC resets
*/
- if (!EFX_IS10G(efx)) {
- EFX_POPULATE_OWORD_1(reg, FRF_AB_GM_SW_RST, 1);
- efx_writeo(efx, &reg, FR_AB_GM_CFG1);
- udelay(1000);
-
- EFX_POPULATE_OWORD_1(reg, FRF_AB_GM_SW_RST, 0);
- efx_writeo(efx, &reg, FR_AB_GM_CFG1);
- udelay(1000);
- return;
- } else {
- EFX_POPULATE_OWORD_1(reg, FRF_AB_XM_CORE_RST, 1);
- efx_writeo(efx, &reg, FR_AB_XM_GLB_CFG);
-
- for (count = 0; count < 10000; count++) {
- efx_reado(efx, &reg, FR_AB_XM_GLB_CFG);
- if (EFX_OWORD_FIELD(reg, FRF_AB_XM_CORE_RST) ==
- 0)
- return;
- udelay(10);
- }
-
- netif_err(efx, hw, efx->net_dev,
- "timed out waiting for XMAC core reset\n");
+ EFX_POPULATE_OWORD_1(reg, FRF_AB_XM_CORE_RST, 1);
+ efx_writeo(efx, &reg, FR_AB_XM_GLB_CFG);
+
+ for (count = 0; count < 10000; count++) {
+ efx_reado(efx, &reg, FR_AB_XM_GLB_CFG);
+ if (EFX_OWORD_FIELD(reg, FRF_AB_XM_CORE_RST) ==
+ 0)
+ return;
+ udelay(10);
}
+
+ netif_err(efx, hw, efx->net_dev,
+ "timed out waiting for XMAC core reset\n");
}
/* Mac stats will fail whist the TX fifo is draining */
@@ -514,7 +497,6 @@ static void falcon_reset_macs(struct efx_nic *efx)
* are re-enabled by the caller */
efx_writeo(efx, &mac_ctrl, FR_AB_MAC_CTRL);
- /* This can run even when the GMAC is selected */
falcon_setup_xaui(efx);
}
@@ -652,8 +634,6 @@ static void falcon_stats_timer_func(unsigned long context)
spin_unlock(&efx->stats_lock);
}
-static void falcon_switch_mac(struct efx_nic *efx);
-
static bool falcon_loopback_link_poll(struct efx_nic *efx)
{
struct efx_link_state old_state = efx->link_state;
@@ -664,11 +644,7 @@ static bool falcon_loopback_link_poll(struct efx_nic *efx)
efx->link_state.fd = true;
efx->link_state.fc = efx->wanted_fc;
efx->link_state.up = true;
-
- if (efx->loopback_mode == LOOPBACK_GMAC)
- efx->link_state.speed = 1000;
- else
- efx->link_state.speed = 10000;
+ efx->link_state.speed = 10000;
return !efx_link_state_equal(&efx->link_state, &old_state);
}
@@ -691,7 +667,7 @@ static int falcon_reconfigure_port(struct efx_nic *efx)
falcon_stop_nic_stats(efx);
falcon_deconfigure_mac_wrapper(efx);
- falcon_switch_mac(efx);
+ falcon_reset_macs(efx);
efx->phy_op->reconfigure(efx);
rc = efx->mac_op->reconfigure(efx);
@@ -841,73 +817,23 @@ out:
return rc;
}
-static void falcon_clock_mac(struct efx_nic *efx)
-{
- unsigned strap_val;
- efx_oword_t nic_stat;
-
- /* Configure the NIC generated MAC clock correctly */
- efx_reado(efx, &nic_stat, FR_AB_NIC_STAT);
- strap_val = EFX_IS10G(efx) ? 5 : 3;
- if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) {
- EFX_SET_OWORD_FIELD(nic_stat, FRF_BB_EE_STRAP_EN, 1);
- EFX_SET_OWORD_FIELD(nic_stat, FRF_BB_EE_STRAP, strap_val);
- efx_writeo(efx, &nic_stat, FR_AB_NIC_STAT);
- } else {
- /* Falcon A1 does not support 1G/10G speed switching
- * and must not be used with a PHY that does. */
- BUG_ON(EFX_OWORD_FIELD(nic_stat, FRF_AB_STRAP_PINS) !=
- strap_val);
- }
-}
-
-static void falcon_switch_mac(struct efx_nic *efx)
-{
- struct efx_mac_operations *old_mac_op = efx->mac_op;
- struct falcon_nic_data *nic_data = efx->nic_data;
- unsigned int stats_done_offset;
-
- WARN_ON(!mutex_is_locked(&efx->mac_lock));
- WARN_ON(nic_data->stats_disable_count == 0);
-
- efx->mac_op = (EFX_IS10G(efx) ?
- &falcon_xmac_operations : &falcon_gmac_operations);
-
- if (EFX_IS10G(efx))
- stats_done_offset = XgDmaDone_offset;
- else
- stats_done_offset = GDmaDone_offset;
- nic_data->stats_dma_done = efx->stats_buffer.addr + stats_done_offset;
-
- if (old_mac_op == efx->mac_op)
- return;
-
- falcon_clock_mac(efx);
-
- netif_dbg(efx, hw, efx->net_dev, "selected %cMAC\n",
- EFX_IS10G(efx) ? 'X' : 'G');
- /* Not all macs support a mac-level link state */
- efx->xmac_poll_required = false;
- falcon_reset_macs(efx);
-}
-
/* This call is responsible for hooking in the MAC and PHY operations */
static int falcon_probe_port(struct efx_nic *efx)
{
+ struct falcon_nic_data *nic_data = efx->nic_data;
int rc;
switch (efx->phy_type) {
case PHY_TYPE_SFX7101:
efx->phy_op = &falcon_sfx7101_phy_ops;
break;
- case PHY_TYPE_SFT9001A:
- case PHY_TYPE_SFT9001B:
- efx->phy_op = &falcon_sft9001_phy_ops;
- break;
case PHY_TYPE_QT2022C2:
case PHY_TYPE_QT2025C:
efx->phy_op = &falcon_qt202x_phy_ops;
break;
+ case PHY_TYPE_TXC43128:
+ efx->phy_op = &falcon_txc_phy_ops;
+ break;
default:
netif_err(efx, probe, efx->net_dev, "Unknown PHY type %d\n",
efx->phy_type);
@@ -943,6 +869,7 @@ static int falcon_probe_port(struct efx_nic *efx)
(u64)efx->stats_buffer.dma_addr,
efx->stats_buffer.addr,
(u64)virt_to_phys(efx->stats_buffer.addr));
+ nic_data->stats_dma_done = efx->stats_buffer.addr + XgDmaDone_offset;
return 0;
}
@@ -1207,7 +1134,7 @@ static void falcon_monitor(struct efx_nic *efx)
falcon_stop_nic_stats(efx);
falcon_deconfigure_mac_wrapper(efx);
- falcon_switch_mac(efx);
+ falcon_reset_macs(efx);
rc = efx->mac_op->reconfigure(efx);
BUG_ON(rc);
@@ -1216,8 +1143,7 @@ static void falcon_monitor(struct efx_nic *efx)
efx_link_status_changed(efx);
}
- if (EFX_IS10G(efx))
- falcon_poll_xmac(efx);
+ falcon_poll_xmac(efx);
}
/* Zeroes out the SRAM contents. This routine must be called in
@@ -1610,16 +1536,6 @@ static int falcon_init_nic(struct efx_nic *efx)
EFX_SET_OWORD_FIELD(temp, FRF_AB_ONCHIP_SRAM, 1);
efx_writeo(efx, &temp, FR_AB_NIC_STAT);
- /* Set the source of the GMAC clock */
- if (efx_nic_rev(efx) == EFX_REV_FALCON_B0) {
- efx_reado(efx, &temp, FR_AB_GPIO_CTL);
- EFX_SET_OWORD_FIELD(temp, FRF_AB_USE_NIC_CLK, true);
- efx_writeo(efx, &temp, FR_AB_GPIO_CTL);
- }
-
- /* Select the correct MAC */
- falcon_clock_mac(efx);
-
rc = falcon_reset_sram(efx);
if (rc)
return rc;
@@ -1880,7 +1796,7 @@ struct efx_nic_type falcon_b0_nic_type = {
* channels */
.tx_dc_base = 0x130000,
.rx_dc_base = 0x100000,
- .offload_features = NETIF_F_IP_CSUM | NETIF_F_RXHASH,
+ .offload_features = NETIF_F_IP_CSUM | NETIF_F_RXHASH | NETIF_F_NTUPLE,
.reset_world_flags = ETH_RESET_IRQ,
};
diff --git a/drivers/net/sfc/falcon_boards.c b/drivers/net/sfc/falcon_boards.c
index 3d950c2cf205..cfc6a5b5a477 100644
--- a/drivers/net/sfc/falcon_boards.c
+++ b/drivers/net/sfc/falcon_boards.c
@@ -26,7 +26,7 @@
/* Board types */
#define FALCON_BOARD_SFE4001 0x01
#define FALCON_BOARD_SFE4002 0x02
-#define FALCON_BOARD_SFN4111T 0x51
+#define FALCON_BOARD_SFE4003 0x03
#define FALCON_BOARD_SFN4112F 0x52
/* Board temperature is about 15°C above ambient when air flow is
@@ -142,17 +142,17 @@ static inline int efx_check_lm87(struct efx_nic *efx, unsigned mask)
#endif /* CONFIG_SENSORS_LM87 */
/*****************************************************************************
- * Support for the SFE4001 and SFN4111T NICs.
+ * Support for the SFE4001 NIC.
*
* The SFE4001 does not power-up fully at reset due to its high power
* consumption. We control its power via a PCA9539 I/O expander.
- * Both boards have a MAX6647 temperature monitor which we expose to
+ * It also has a MAX6647 temperature monitor which we expose to
* the lm90 driver.
*
* This also provides minimal support for reflashing the PHY, which is
* initiated by resetting it with the FLASH_CFG_1 pin pulled down.
* On SFE4001 rev A2 and later this is connected to the 3V3X output of
- * the IO-expander; on the SFN4111T it is connected to Falcon's GPIO3.
+ * the IO-expander.
* We represent reflash mode as PHY_MODE_SPECIAL and make it mutually
* exclusive with the network device being open.
*/
@@ -304,34 +304,6 @@ fail_on:
return rc;
}
-static int sfn4111t_reset(struct efx_nic *efx)
-{
- struct falcon_board *board = falcon_board(efx);
- efx_oword_t reg;
-
- /* GPIO 3 and the GPIO register are shared with I2C, so block that */
- i2c_lock_adapter(&board->i2c_adap);
-
- /* Pull RST_N (GPIO 2) low then let it up again, setting the
- * FLASH_CFG_1 strap (GPIO 3) appropriately. Only change the
- * output enables; the output levels should always be 0 (low)
- * and we rely on external pull-ups. */
- efx_reado(efx, &reg, FR_AB_GPIO_CTL);
- EFX_SET_OWORD_FIELD(reg, FRF_AB_GPIO2_OEN, true);
- efx_writeo(efx, &reg, FR_AB_GPIO_CTL);
- msleep(1000);
- EFX_SET_OWORD_FIELD(reg, FRF_AB_GPIO2_OEN, false);
- EFX_SET_OWORD_FIELD(reg, FRF_AB_GPIO3_OEN,
- !!(efx->phy_mode & PHY_MODE_SPECIAL));
- efx_writeo(efx, &reg, FR_AB_GPIO_CTL);
- msleep(1);
-
- i2c_unlock_adapter(&board->i2c_adap);
-
- ssleep(1);
- return 0;
-}
-
static ssize_t show_phy_flash_cfg(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -363,10 +335,7 @@ static ssize_t set_phy_flash_cfg(struct device *dev,
efx->phy_mode = new_mode;
if (new_mode & PHY_MODE_SPECIAL)
falcon_stop_nic_stats(efx);
- if (falcon_board(efx)->type->id == FALCON_BOARD_SFE4001)
- err = sfe4001_poweron(efx);
- else
- err = sfn4111t_reset(efx);
+ err = sfe4001_poweron(efx);
if (!err)
err = efx_reconfigure_port(efx);
if (!(new_mode & PHY_MODE_SPECIAL))
@@ -479,83 +448,6 @@ fail_hwmon:
return rc;
}
-static int sfn4111t_check_hw(struct efx_nic *efx)
-{
- s32 status;
-
- /* If XAUI link is up then do not monitor */
- if (EFX_WORKAROUND_7884(efx) && !efx->xmac_poll_required)
- return 0;
-
- /* Test LHIGH, RHIGH, FAULT, EOT and IOT alarms */
- status = i2c_smbus_read_byte_data(falcon_board(efx)->hwmon_client,
- MAX664X_REG_RSL);
- if (status < 0)
- return -EIO;
- if (status & 0x57)
- return -ERANGE;
- return 0;
-}
-
-static void sfn4111t_fini(struct efx_nic *efx)
-{
- netif_info(efx, drv, efx->net_dev, "%s\n", __func__);
-
- device_remove_file(&efx->pci_dev->dev, &dev_attr_phy_flash_cfg);
- i2c_unregister_device(falcon_board(efx)->hwmon_client);
-}
-
-static struct i2c_board_info sfn4111t_a0_hwmon_info = {
- I2C_BOARD_INFO("max6647", 0x4e),
-};
-
-static struct i2c_board_info sfn4111t_r5_hwmon_info = {
- I2C_BOARD_INFO("max6646", 0x4d),
-};
-
-static void sfn4111t_init_phy(struct efx_nic *efx)
-{
- if (!(efx->phy_mode & PHY_MODE_SPECIAL)) {
- if (sft9001_wait_boot(efx) != -EINVAL)
- return;
-
- efx->phy_mode = PHY_MODE_SPECIAL;
- falcon_stop_nic_stats(efx);
- }
-
- sfn4111t_reset(efx);
- sft9001_wait_boot(efx);
-}
-
-static int sfn4111t_init(struct efx_nic *efx)
-{
- struct falcon_board *board = falcon_board(efx);
- int rc;
-
- board->hwmon_client =
- i2c_new_device(&board->i2c_adap,
- (board->minor < 5) ?
- &sfn4111t_a0_hwmon_info :
- &sfn4111t_r5_hwmon_info);
- if (!board->hwmon_client)
- return -EIO;
-
- rc = device_create_file(&efx->pci_dev->dev, &dev_attr_phy_flash_cfg);
- if (rc)
- goto fail_hwmon;
-
- if (efx->phy_mode & PHY_MODE_SPECIAL)
- /* PHY may not generate a 156.25 MHz clock and MAC
- * stats fetch will fail. */
- falcon_stop_nic_stats(efx);
-
- return 0;
-
-fail_hwmon:
- i2c_unregister_device(board->hwmon_client);
- return rc;
-}
-
/*****************************************************************************
* Support for the SFE4002
*
@@ -691,6 +583,75 @@ static int sfn4112f_init(struct efx_nic *efx)
return efx_init_lm87(efx, &sfn4112f_hwmon_info, sfn4112f_lm87_regs);
}
+/*****************************************************************************
+ * Support for the SFE4003
+ *
+ */
+static u8 sfe4003_lm87_channel = 0x03; /* use AIN not FAN inputs */
+
+static const u8 sfe4003_lm87_regs[] = {
+ LM87_IN_LIMITS(0, 0x67, 0x7f), /* 2.5V: 1.5V +/- 10% */
+ LM87_IN_LIMITS(1, 0x4c, 0x5e), /* Vccp1: 1.2V +/- 10% */
+ LM87_IN_LIMITS(2, 0xac, 0xd4), /* 3.3V: 3.3V +/- 10% */
+ LM87_IN_LIMITS(4, 0xac, 0xe0), /* 12V: 10.8-14V */
+ LM87_IN_LIMITS(5, 0x3f, 0x4f), /* Vccp2: 1.0V +/- 10% */
+ LM87_TEMP_INT_LIMITS(0, 70 + FALCON_BOARD_TEMP_BIAS),
+ 0
+};
+
+static struct i2c_board_info sfe4003_hwmon_info = {
+ I2C_BOARD_INFO("lm87", 0x2e),
+ .platform_data = &sfe4003_lm87_channel,
+};
+
+/* Board-specific LED info. */
+#define SFE4003_RED_LED_GPIO 11
+#define SFE4003_LED_ON 1
+#define SFE4003_LED_OFF 0
+
+static void sfe4003_set_id_led(struct efx_nic *efx, enum efx_led_mode mode)
+{
+ struct falcon_board *board = falcon_board(efx);
+
+ /* The LEDs were not wired to GPIOs before A3 */
+ if (board->minor < 3 && board->major == 0)
+ return;
+
+ falcon_txc_set_gpio_val(
+ efx, SFE4003_RED_LED_GPIO,
+ (mode == EFX_LED_ON) ? SFE4003_LED_ON : SFE4003_LED_OFF);
+}
+
+static void sfe4003_init_phy(struct efx_nic *efx)
+{
+ struct falcon_board *board = falcon_board(efx);
+
+ /* The LEDs were not wired to GPIOs before A3 */
+ if (board->minor < 3 && board->major == 0)
+ return;
+
+ falcon_txc_set_gpio_dir(efx, SFE4003_RED_LED_GPIO, TXC_GPIO_DIR_OUTPUT);
+ falcon_txc_set_gpio_val(efx, SFE4003_RED_LED_GPIO, SFE4003_LED_OFF);
+}
+
+static int sfe4003_check_hw(struct efx_nic *efx)
+{
+ struct falcon_board *board = falcon_board(efx);
+
+ /* A0/A1/A2 board rev. 4003s report a temperature fault the whole time
+ * (bad sensor) so we mask it out. */
+ unsigned alarm_mask =
+ (board->major == 0 && board->minor <= 2) ?
+ ~LM87_ALARM_TEMP_EXT1 : ~0;
+
+ return efx_check_lm87(efx, alarm_mask);
+}
+
+static int sfe4003_init(struct efx_nic *efx)
+{
+ return efx_init_lm87(efx, &sfe4003_hwmon_info, sfe4003_lm87_regs);
+}
+
static const struct falcon_board_type board_types[] = {
{
.id = FALCON_BOARD_SFE4001,
@@ -713,14 +674,14 @@ static const struct falcon_board_type board_types[] = {
.monitor = sfe4002_check_hw,
},
{
- .id = FALCON_BOARD_SFN4111T,
- .ref_model = "SFN4111T",
- .gen_type = "100/1000/10GBASE-T adapter",
- .init = sfn4111t_init,
- .init_phy = sfn4111t_init_phy,
- .fini = sfn4111t_fini,
- .set_id_led = tenxpress_set_id_led,
- .monitor = sfn4111t_check_hw,
+ .id = FALCON_BOARD_SFE4003,
+ .ref_model = "SFE4003",
+ .gen_type = "10GBASE-CX4 adapter",
+ .init = sfe4003_init,
+ .init_phy = sfe4003_init_phy,
+ .fini = efx_fini_lm87,
+ .set_id_led = sfe4003_set_id_led,
+ .monitor = sfe4003_check_hw,
},
{
.id = FALCON_BOARD_SFN4112F,
diff --git a/drivers/net/sfc/falcon_gmac.c b/drivers/net/sfc/falcon_gmac.c
deleted file mode 100644
index 7dadfcbd6ce7..000000000000
--- a/drivers/net/sfc/falcon_gmac.c
+++ /dev/null
@@ -1,230 +0,0 @@
-/****************************************************************************
- * Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2006-2009 Solarflare Communications Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation, incorporated herein by reference.
- */
-
-#include <linux/delay.h>
-#include "net_driver.h"
-#include "efx.h"
-#include "nic.h"
-#include "mac.h"
-#include "regs.h"
-#include "io.h"
-
-/**************************************************************************
- *
- * MAC operations
- *
- *************************************************************************/
-
-static int falcon_reconfigure_gmac(struct efx_nic *efx)
-{
- struct efx_link_state *link_state = &efx->link_state;
- bool loopback, tx_fc, rx_fc, bytemode;
- int if_mode;
- unsigned int max_frame_len;
- efx_oword_t reg;
-
- /* Configuration register 1 */
- tx_fc = (link_state->fc & EFX_FC_TX) || !link_state->fd;
- rx_fc = !!(link_state->fc & EFX_FC_RX);
- loopback = (efx->loopback_mode == LOOPBACK_GMAC);
- bytemode = (link_state->speed == 1000);
-
- EFX_POPULATE_OWORD_5(reg,
- FRF_AB_GM_LOOP, loopback,
- FRF_AB_GM_TX_EN, 1,
- FRF_AB_GM_TX_FC_EN, tx_fc,
- FRF_AB_GM_RX_EN, 1,
- FRF_AB_GM_RX_FC_EN, rx_fc);
- efx_writeo(efx, &reg, FR_AB_GM_CFG1);
- udelay(10);
-
- /* Configuration register 2 */
- if_mode = (bytemode) ? 2 : 1;
- EFX_POPULATE_OWORD_5(reg,
- FRF_AB_GM_IF_MODE, if_mode,
- FRF_AB_GM_PAD_CRC_EN, 1,
- FRF_AB_GM_LEN_CHK, 1,
- FRF_AB_GM_FD, link_state->fd,
- FRF_AB_GM_PAMBL_LEN, 0x7/*datasheet recommended */);
-
- efx_writeo(efx, &reg, FR_AB_GM_CFG2);
- udelay(10);
-
- /* Max frame len register */
- max_frame_len = EFX_MAX_FRAME_LEN(efx->net_dev->mtu);
- EFX_POPULATE_OWORD_1(reg, FRF_AB_GM_MAX_FLEN, max_frame_len);
- efx_writeo(efx, &reg, FR_AB_GM_MAX_FLEN);
- udelay(10);
-
- /* FIFO configuration register 0 */
- EFX_POPULATE_OWORD_5(reg,
- FRF_AB_GMF_FTFENREQ, 1,
- FRF_AB_GMF_STFENREQ, 1,
- FRF_AB_GMF_FRFENREQ, 1,
- FRF_AB_GMF_SRFENREQ, 1,
- FRF_AB_GMF_WTMENREQ, 1);
- efx_writeo(efx, &reg, FR_AB_GMF_CFG0);
- udelay(10);
-
- /* FIFO configuration register 1 */
- EFX_POPULATE_OWORD_2(reg,
- FRF_AB_GMF_CFGFRTH, 0x12,
- FRF_AB_GMF_CFGXOFFRTX, 0xffff);
- efx_writeo(efx, &reg, FR_AB_GMF_CFG1);
- udelay(10);
-
- /* FIFO configuration register 2 */
- EFX_POPULATE_OWORD_2(reg,
- FRF_AB_GMF_CFGHWM, 0x3f,
- FRF_AB_GMF_CFGLWM, 0xa);
- efx_writeo(efx, &reg, FR_AB_GMF_CFG2);
- udelay(10);
-
- /* FIFO configuration register 3 */
- EFX_POPULATE_OWORD_2(reg,
- FRF_AB_GMF_CFGHWMFT, 0x1c,
- FRF_AB_GMF_CFGFTTH, 0x08);
- efx_writeo(efx, &reg, FR_AB_GMF_CFG3);
- udelay(10);
-
- /* FIFO configuration register 4 */
- EFX_POPULATE_OWORD_1(reg, FRF_AB_GMF_HSTFLTRFRM_PAUSE, 1);
- efx_writeo(efx, &reg, FR_AB_GMF_CFG4);
- udelay(10);
-
- /* FIFO configuration register 5 */
- efx_reado(efx, &reg, FR_AB_GMF_CFG5);
- EFX_SET_OWORD_FIELD(reg, FRF_AB_GMF_CFGBYTMODE, bytemode);
- EFX_SET_OWORD_FIELD(reg, FRF_AB_GMF_CFGHDPLX, !link_state->fd);
- EFX_SET_OWORD_FIELD(reg, FRF_AB_GMF_HSTDRPLT64, !link_state->fd);
- EFX_SET_OWORD_FIELD(reg, FRF_AB_GMF_HSTFLTRFRMDC_PAUSE, 0);
- efx_writeo(efx, &reg, FR_AB_GMF_CFG5);
- udelay(10);
-
- /* MAC address */
- EFX_POPULATE_OWORD_4(reg,
- FRF_AB_GM_ADR_B0, efx->net_dev->dev_addr[5],
- FRF_AB_GM_ADR_B1, efx->net_dev->dev_addr[4],
- FRF_AB_GM_ADR_B2, efx->net_dev->dev_addr[3],
- FRF_AB_GM_ADR_B3, efx->net_dev->dev_addr[2]);
- efx_writeo(efx, &reg, FR_AB_GM_ADR1);
- udelay(10);
- EFX_POPULATE_OWORD_2(reg,
- FRF_AB_GM_ADR_B4, efx->net_dev->dev_addr[1],
- FRF_AB_GM_ADR_B5, efx->net_dev->dev_addr[0]);
- efx_writeo(efx, &reg, FR_AB_GM_ADR2);
- udelay(10);
-
- falcon_reconfigure_mac_wrapper(efx);
-
- return 0;
-}
-
-static void falcon_update_stats_gmac(struct efx_nic *efx)
-{
- struct efx_mac_stats *mac_stats = &efx->mac_stats;
- unsigned long old_rx_pause, old_tx_pause;
- unsigned long new_rx_pause, new_tx_pause;
-
- /* Pause frames are erroneously counted as errors (SFC bug 3269) */
- old_rx_pause = mac_stats->rx_pause;
- old_tx_pause = mac_stats->tx_pause;
-
- /* Update MAC stats from DMAed values */
- FALCON_STAT(efx, GRxGoodOct, rx_good_bytes);
- FALCON_STAT(efx, GRxBadOct, rx_bad_bytes);
- FALCON_STAT(efx, GRxMissPkt, rx_missed);
- FALCON_STAT(efx, GRxFalseCRS, rx_false_carrier);
- FALCON_STAT(efx, GRxPausePkt, rx_pause);
- FALCON_STAT(efx, GRxBadPkt, rx_bad);
- FALCON_STAT(efx, GRxUcastPkt, rx_unicast);
- FALCON_STAT(efx, GRxMcastPkt, rx_multicast);
- FALCON_STAT(efx, GRxBcastPkt, rx_broadcast);
- FALCON_STAT(efx, GRxGoodLt64Pkt, rx_good_lt64);
- FALCON_STAT(efx, GRxBadLt64Pkt, rx_bad_lt64);
- FALCON_STAT(efx, GRx64Pkt, rx_64);
- FALCON_STAT(efx, GRx65to127Pkt, rx_65_to_127);
- FALCON_STAT(efx, GRx128to255Pkt, rx_128_to_255);
- FALCON_STAT(efx, GRx256to511Pkt, rx_256_to_511);
- FALCON_STAT(efx, GRx512to1023Pkt, rx_512_to_1023);
- FALCON_STAT(efx, GRx1024to15xxPkt, rx_1024_to_15xx);
- FALCON_STAT(efx, GRx15xxtoJumboPkt, rx_15xx_to_jumbo);
- FALCON_STAT(efx, GRxGtJumboPkt, rx_gtjumbo);
- FALCON_STAT(efx, GRxFcsErr64to15xxPkt, rx_bad_64_to_15xx);
- FALCON_STAT(efx, GRxFcsErr15xxtoJumboPkt, rx_bad_15xx_to_jumbo);
- FALCON_STAT(efx, GRxFcsErrGtJumboPkt, rx_bad_gtjumbo);
- FALCON_STAT(efx, GTxGoodBadOct, tx_bytes);
- FALCON_STAT(efx, GTxGoodOct, tx_good_bytes);
- FALCON_STAT(efx, GTxSglColPkt, tx_single_collision);
- FALCON_STAT(efx, GTxMultColPkt, tx_multiple_collision);
- FALCON_STAT(efx, GTxExColPkt, tx_excessive_collision);
- FALCON_STAT(efx, GTxDefPkt, tx_deferred);
- FALCON_STAT(efx, GTxLateCol, tx_late_collision);
- FALCON_STAT(efx, GTxExDefPkt, tx_excessive_deferred);
- FALCON_STAT(efx, GTxPausePkt, tx_pause);
- FALCON_STAT(efx, GTxBadPkt, tx_bad);
- FALCON_STAT(efx, GTxUcastPkt, tx_unicast);
- FALCON_STAT(efx, GTxMcastPkt, tx_multicast);
- FALCON_STAT(efx, GTxBcastPkt, tx_broadcast);
- FALCON_STAT(efx, GTxLt64Pkt, tx_lt64);
- FALCON_STAT(efx, GTx64Pkt, tx_64);
- FALCON_STAT(efx, GTx65to127Pkt, tx_65_to_127);
- FALCON_STAT(efx, GTx128to255Pkt, tx_128_to_255);
- FALCON_STAT(efx, GTx256to511Pkt, tx_256_to_511);
- FALCON_STAT(efx, GTx512to1023Pkt, tx_512_to_1023);
- FALCON_STAT(efx, GTx1024to15xxPkt, tx_1024_to_15xx);
- FALCON_STAT(efx, GTx15xxtoJumboPkt, tx_15xx_to_jumbo);
- FALCON_STAT(efx, GTxGtJumboPkt, tx_gtjumbo);
- FALCON_STAT(efx, GTxNonTcpUdpPkt, tx_non_tcpudp);
- FALCON_STAT(efx, GTxMacSrcErrPkt, tx_mac_src_error);
- FALCON_STAT(efx, GTxIpSrcErrPkt, tx_ip_src_error);
-
- /* Pause frames are erroneously counted as errors (SFC bug 3269) */
- new_rx_pause = mac_stats->rx_pause;
- new_tx_pause = mac_stats->tx_pause;
- mac_stats->rx_bad -= (new_rx_pause - old_rx_pause);
- mac_stats->tx_bad -= (new_tx_pause - old_tx_pause);
-
- /* Derive stats that the MAC doesn't provide directly */
- mac_stats->tx_bad_bytes =
- mac_stats->tx_bytes - mac_stats->tx_good_bytes;
- mac_stats->tx_packets =
- mac_stats->tx_lt64 + mac_stats->tx_64 +
- mac_stats->tx_65_to_127 + mac_stats->tx_128_to_255 +
- mac_stats->tx_256_to_511 + mac_stats->tx_512_to_1023 +
- mac_stats->tx_1024_to_15xx + mac_stats->tx_15xx_to_jumbo +
- mac_stats->tx_gtjumbo;
- mac_stats->tx_collision =
- mac_stats->tx_single_collision +
- mac_stats->tx_multiple_collision +
- mac_stats->tx_excessive_collision +
- mac_stats->tx_late_collision;
- mac_stats->rx_bytes =
- mac_stats->rx_good_bytes + mac_stats->rx_bad_bytes;
- mac_stats->rx_packets =
- mac_stats->rx_good_lt64 + mac_stats->rx_bad_lt64 +
- mac_stats->rx_64 + mac_stats->rx_65_to_127 +
- mac_stats->rx_128_to_255 + mac_stats->rx_256_to_511 +
- mac_stats->rx_512_to_1023 + mac_stats->rx_1024_to_15xx +
- mac_stats->rx_15xx_to_jumbo + mac_stats->rx_gtjumbo;
- mac_stats->rx_good = mac_stats->rx_packets - mac_stats->rx_bad;
- mac_stats->rx_lt64 = mac_stats->rx_good_lt64 + mac_stats->rx_bad_lt64;
-}
-
-static bool falcon_gmac_check_fault(struct efx_nic *efx)
-{
- return false;
-}
-
-struct efx_mac_operations falcon_gmac_operations = {
- .reconfigure = falcon_reconfigure_gmac,
- .update_stats = falcon_update_stats_gmac,
- .check_fault = falcon_gmac_check_fault,
-};
diff --git a/drivers/net/sfc/falcon_xmac.c b/drivers/net/sfc/falcon_xmac.c
index bae656dd2c4e..b31f595ebb5b 100644
--- a/drivers/net/sfc/falcon_xmac.c
+++ b/drivers/net/sfc/falcon_xmac.c
@@ -143,7 +143,7 @@ static bool falcon_xmac_link_ok(struct efx_nic *efx)
efx_mdio_phyxgxs_lane_sync(efx));
}
-void falcon_reconfigure_xmac_core(struct efx_nic *efx)
+static void falcon_reconfigure_xmac_core(struct efx_nic *efx)
{
unsigned int max_frame_len;
efx_oword_t reg;
diff --git a/drivers/net/sfc/filter.c b/drivers/net/sfc/filter.c
new file mode 100644
index 000000000000..52cb6082b910
--- /dev/null
+++ b/drivers/net/sfc/filter.c
@@ -0,0 +1,454 @@
+/****************************************************************************
+ * Driver for Solarflare Solarstorm network controllers and boards
+ * Copyright 2005-2010 Solarflare Communications Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation, incorporated herein by reference.
+ */
+
+#include "efx.h"
+#include "filter.h"
+#include "io.h"
+#include "nic.h"
+#include "regs.h"
+
+/* "Fudge factors" - difference between programmed value and actual depth.
+ * Due to pipelined implementation we need to program H/W with a value that
+ * is larger than the hop limit we want.
+ */
+#define FILTER_CTL_SRCH_FUDGE_WILD 3
+#define FILTER_CTL_SRCH_FUDGE_FULL 1
+
+/* Hard maximum hop limit. Hardware will time-out beyond 200-something.
+ * We also need to avoid infinite loops in efx_filter_search() when the
+ * table is full.
+ */
+#define FILTER_CTL_SRCH_MAX 200
+
+struct efx_filter_table {
+ u32 offset; /* address of table relative to BAR */
+ unsigned size; /* number of entries */
+ unsigned step; /* step between entries */
+ unsigned used; /* number currently used */
+ unsigned long *used_bitmap;
+ struct efx_filter_spec *spec;
+};
+
+struct efx_filter_state {
+ spinlock_t lock;
+ struct efx_filter_table table[EFX_FILTER_TABLE_COUNT];
+ unsigned search_depth[EFX_FILTER_TYPE_COUNT];
+};
+
+/* The filter hash function is LFSR polynomial x^16 + x^3 + 1 of a 32-bit
+ * key derived from the n-tuple. The initial LFSR state is 0xffff. */
+static u16 efx_filter_hash(u32 key)
+{
+ u16 tmp;
+
+ /* First 16 rounds */
+ tmp = 0x1fff ^ key >> 16;
+ tmp = tmp ^ tmp >> 3 ^ tmp >> 6;
+ tmp = tmp ^ tmp >> 9;
+ /* Last 16 rounds */
+ tmp = tmp ^ tmp << 13 ^ key;
+ tmp = tmp ^ tmp >> 3 ^ tmp >> 6;
+ return tmp ^ tmp >> 9;
+}
+
+/* To allow for hash collisions, filter search continues at these
+ * increments from the first possible entry selected by the hash. */
+static u16 efx_filter_increment(u32 key)
+{
+ return key * 2 - 1;
+}
+
+static enum efx_filter_table_id
+efx_filter_type_table_id(enum efx_filter_type type)
+{
+ BUILD_BUG_ON(EFX_FILTER_TABLE_RX_IP != (EFX_FILTER_RX_TCP_FULL >> 2));
+ BUILD_BUG_ON(EFX_FILTER_TABLE_RX_IP != (EFX_FILTER_RX_TCP_WILD >> 2));
+ BUILD_BUG_ON(EFX_FILTER_TABLE_RX_IP != (EFX_FILTER_RX_UDP_FULL >> 2));
+ BUILD_BUG_ON(EFX_FILTER_TABLE_RX_IP != (EFX_FILTER_RX_UDP_WILD >> 2));
+ BUILD_BUG_ON(EFX_FILTER_TABLE_RX_MAC != (EFX_FILTER_RX_MAC_FULL >> 2));
+ BUILD_BUG_ON(EFX_FILTER_TABLE_RX_MAC != (EFX_FILTER_RX_MAC_WILD >> 2));
+ return type >> 2;
+}
+
+static void
+efx_filter_table_reset_search_depth(struct efx_filter_state *state,
+ enum efx_filter_table_id table_id)
+{
+ memset(state->search_depth + (table_id << 2), 0,
+ sizeof(state->search_depth[0]) << 2);
+}
+
+static void efx_filter_push_rx_limits(struct efx_nic *efx)
+{
+ struct efx_filter_state *state = efx->filter_state;
+ efx_oword_t filter_ctl;
+
+ efx_reado(efx, &filter_ctl, FR_BZ_RX_FILTER_CTL);
+
+ EFX_SET_OWORD_FIELD(filter_ctl, FRF_BZ_TCP_FULL_SRCH_LIMIT,
+ state->search_depth[EFX_FILTER_RX_TCP_FULL] +
+ FILTER_CTL_SRCH_FUDGE_FULL);
+ EFX_SET_OWORD_FIELD(filter_ctl, FRF_BZ_TCP_WILD_SRCH_LIMIT,
+ state->search_depth[EFX_FILTER_RX_TCP_WILD] +
+ FILTER_CTL_SRCH_FUDGE_WILD);
+ EFX_SET_OWORD_FIELD(filter_ctl, FRF_BZ_UDP_FULL_SRCH_LIMIT,
+ state->search_depth[EFX_FILTER_RX_UDP_FULL] +
+ FILTER_CTL_SRCH_FUDGE_FULL);
+ EFX_SET_OWORD_FIELD(filter_ctl, FRF_BZ_UDP_WILD_SRCH_LIMIT,
+ state->search_depth[EFX_FILTER_RX_UDP_WILD] +
+ FILTER_CTL_SRCH_FUDGE_WILD);
+
+ if (state->table[EFX_FILTER_TABLE_RX_MAC].size) {
+ EFX_SET_OWORD_FIELD(
+ filter_ctl, FRF_CZ_ETHERNET_FULL_SEARCH_LIMIT,
+ state->search_depth[EFX_FILTER_RX_MAC_FULL] +
+ FILTER_CTL_SRCH_FUDGE_FULL);
+ EFX_SET_OWORD_FIELD(
+ filter_ctl, FRF_CZ_ETHERNET_WILDCARD_SEARCH_LIMIT,
+ state->search_depth[EFX_FILTER_RX_MAC_WILD] +
+ FILTER_CTL_SRCH_FUDGE_WILD);
+ }
+
+ efx_writeo(efx, &filter_ctl, FR_BZ_RX_FILTER_CTL);
+}
+
+/* Build a filter entry and return its n-tuple key. */
+static u32 efx_filter_build(efx_oword_t *filter, struct efx_filter_spec *spec)
+{
+ u32 data3;
+
+ switch (efx_filter_type_table_id(spec->type)) {
+ case EFX_FILTER_TABLE_RX_IP: {
+ bool is_udp = (spec->type == EFX_FILTER_RX_UDP_FULL ||
+ spec->type == EFX_FILTER_RX_UDP_WILD);
+ EFX_POPULATE_OWORD_7(
+ *filter,
+ FRF_BZ_RSS_EN,
+ !!(spec->flags & EFX_FILTER_FLAG_RX_RSS),
+ FRF_BZ_SCATTER_EN,
+ !!(spec->flags & EFX_FILTER_FLAG_RX_SCATTER),
+ FRF_BZ_TCP_UDP, is_udp,
+ FRF_BZ_RXQ_ID, spec->dmaq_id,
+ EFX_DWORD_2, spec->data[2],
+ EFX_DWORD_1, spec->data[1],
+ EFX_DWORD_0, spec->data[0]);
+ data3 = is_udp;
+ break;
+ }
+
+ case EFX_FILTER_TABLE_RX_MAC: {
+ bool is_wild = spec->type == EFX_FILTER_RX_MAC_WILD;
+ EFX_POPULATE_OWORD_8(
+ *filter,
+ FRF_CZ_RMFT_RSS_EN,
+ !!(spec->flags & EFX_FILTER_FLAG_RX_RSS),
+ FRF_CZ_RMFT_SCATTER_EN,
+ !!(spec->flags & EFX_FILTER_FLAG_RX_SCATTER),
+ FRF_CZ_RMFT_IP_OVERRIDE,
+ !!(spec->flags & EFX_FILTER_FLAG_RX_OVERRIDE_IP),
+ FRF_CZ_RMFT_RXQ_ID, spec->dmaq_id,
+ FRF_CZ_RMFT_WILDCARD_MATCH, is_wild,
+ FRF_CZ_RMFT_DEST_MAC_HI, spec->data[2],
+ FRF_CZ_RMFT_DEST_MAC_LO, spec->data[1],
+ FRF_CZ_RMFT_VLAN_ID, spec->data[0]);
+ data3 = is_wild;
+ break;
+ }
+
+ default:
+ BUG();
+ }
+
+ return spec->data[0] ^ spec->data[1] ^ spec->data[2] ^ data3;
+}
+
+static bool efx_filter_equal(const struct efx_filter_spec *left,
+ const struct efx_filter_spec *right)
+{
+ if (left->type != right->type ||
+ memcmp(left->data, right->data, sizeof(left->data)))
+ return false;
+
+ return true;
+}
+
+static int efx_filter_search(struct efx_filter_table *table,
+ struct efx_filter_spec *spec, u32 key,
+ bool for_insert, int *depth_required)
+{
+ unsigned hash, incr, filter_idx, depth;
+ struct efx_filter_spec *cmp;
+
+ hash = efx_filter_hash(key);
+ incr = efx_filter_increment(key);
+
+ for (depth = 1, filter_idx = hash & (table->size - 1);
+ depth <= FILTER_CTL_SRCH_MAX &&
+ test_bit(filter_idx, table->used_bitmap);
+ ++depth) {
+ cmp = &table->spec[filter_idx];
+ if (efx_filter_equal(spec, cmp))
+ goto found;
+ filter_idx = (filter_idx + incr) & (table->size - 1);
+ }
+ if (!for_insert)
+ return -ENOENT;
+ if (depth > FILTER_CTL_SRCH_MAX)
+ return -EBUSY;
+found:
+ *depth_required = depth;
+ return filter_idx;
+}
+
+/**
+ * efx_filter_insert_filter - add or replace a filter
+ * @efx: NIC in which to insert the filter
+ * @spec: Specification for the filter
+ * @replace: Flag for whether the specified filter may replace a filter
+ * with an identical match expression and equal or lower priority
+ *
+ * On success, return the filter index within its table.
+ * On failure, return a negative error code.
+ */
+int efx_filter_insert_filter(struct efx_nic *efx, struct efx_filter_spec *spec,
+ bool replace)
+{
+ struct efx_filter_state *state = efx->filter_state;
+ enum efx_filter_table_id table_id =
+ efx_filter_type_table_id(spec->type);
+ struct efx_filter_table *table = &state->table[table_id];
+ struct efx_filter_spec *saved_spec;
+ efx_oword_t filter;
+ int filter_idx, depth;
+ u32 key;
+ int rc;
+
+ if (table->size == 0)
+ return -EINVAL;
+
+ key = efx_filter_build(&filter, spec);
+
+ netif_vdbg(efx, hw, efx->net_dev,
+ "%s: type %d search_depth=%d", __func__, spec->type,
+ state->search_depth[spec->type]);
+
+ spin_lock_bh(&state->lock);
+
+ rc = efx_filter_search(table, spec, key, true, &depth);
+ if (rc < 0)
+ goto out;
+ filter_idx = rc;
+ BUG_ON(filter_idx >= table->size);
+ saved_spec = &table->spec[filter_idx];
+
+ if (test_bit(filter_idx, table->used_bitmap)) {
+ /* Should we replace the existing filter? */
+ if (!replace) {
+ rc = -EEXIST;
+ goto out;
+ }
+ if (spec->priority < saved_spec->priority) {
+ rc = -EPERM;
+ goto out;
+ }
+ } else {
+ __set_bit(filter_idx, table->used_bitmap);
+ ++table->used;
+ }
+ *saved_spec = *spec;
+
+ if (state->search_depth[spec->type] < depth) {
+ state->search_depth[spec->type] = depth;
+ efx_filter_push_rx_limits(efx);
+ }
+
+ efx_writeo(efx, &filter, table->offset + table->step * filter_idx);
+
+ netif_vdbg(efx, hw, efx->net_dev,
+ "%s: filter type %d index %d rxq %u set",
+ __func__, spec->type, filter_idx, spec->dmaq_id);
+
+out:
+ spin_unlock_bh(&state->lock);
+ return rc;
+}
+
+static void efx_filter_table_clear_entry(struct efx_nic *efx,
+ struct efx_filter_table *table,
+ int filter_idx)
+{
+ static efx_oword_t filter;
+
+ if (test_bit(filter_idx, table->used_bitmap)) {
+ __clear_bit(filter_idx, table->used_bitmap);
+ --table->used;
+ memset(&table->spec[filter_idx], 0, sizeof(table->spec[0]));
+
+ efx_writeo(efx, &filter,
+ table->offset + table->step * filter_idx);
+ }
+}
+
+/**
+ * efx_filter_remove_filter - remove a filter by specification
+ * @efx: NIC from which to remove the filter
+ * @spec: Specification for the filter
+ *
+ * On success, return zero.
+ * On failure, return a negative error code.
+ */
+int efx_filter_remove_filter(struct efx_nic *efx, struct efx_filter_spec *spec)
+{
+ struct efx_filter_state *state = efx->filter_state;
+ enum efx_filter_table_id table_id =
+ efx_filter_type_table_id(spec->type);
+ struct efx_filter_table *table = &state->table[table_id];
+ struct efx_filter_spec *saved_spec;
+ efx_oword_t filter;
+ int filter_idx, depth;
+ u32 key;
+ int rc;
+
+ key = efx_filter_build(&filter, spec);
+
+ spin_lock_bh(&state->lock);
+
+ rc = efx_filter_search(table, spec, key, false, &depth);
+ if (rc < 0)
+ goto out;
+ filter_idx = rc;
+ saved_spec = &table->spec[filter_idx];
+
+ if (spec->priority < saved_spec->priority) {
+ rc = -EPERM;
+ goto out;
+ }
+
+ efx_filter_table_clear_entry(efx, table, filter_idx);
+ if (table->used == 0)
+ efx_filter_table_reset_search_depth(state, table_id);
+ rc = 0;
+
+out:
+ spin_unlock_bh(&state->lock);
+ return rc;
+}
+
+/**
+ * efx_filter_table_clear - remove filters from a table by priority
+ * @efx: NIC from which to remove the filters
+ * @table_id: Table from which to remove the filters
+ * @priority: Maximum priority to remove
+ */
+void efx_filter_table_clear(struct efx_nic *efx,
+ enum efx_filter_table_id table_id,
+ enum efx_filter_priority priority)
+{
+ struct efx_filter_state *state = efx->filter_state;
+ struct efx_filter_table *table = &state->table[table_id];
+ int filter_idx;
+
+ spin_lock_bh(&state->lock);
+
+ for (filter_idx = 0; filter_idx < table->size; ++filter_idx)
+ if (table->spec[filter_idx].priority <= priority)
+ efx_filter_table_clear_entry(efx, table, filter_idx);
+ if (table->used == 0)
+ efx_filter_table_reset_search_depth(state, table_id);
+
+ spin_unlock_bh(&state->lock);
+}
+
+/* Restore filter stater after reset */
+void efx_restore_filters(struct efx_nic *efx)
+{
+ struct efx_filter_state *state = efx->filter_state;
+ enum efx_filter_table_id table_id;
+ struct efx_filter_table *table;
+ efx_oword_t filter;
+ int filter_idx;
+
+ spin_lock_bh(&state->lock);
+
+ for (table_id = 0; table_id < EFX_FILTER_TABLE_COUNT; table_id++) {
+ table = &state->table[table_id];
+ for (filter_idx = 0; filter_idx < table->size; filter_idx++) {
+ if (!test_bit(filter_idx, table->used_bitmap))
+ continue;
+ efx_filter_build(&filter, &table->spec[filter_idx]);
+ efx_writeo(efx, &filter,
+ table->offset + table->step * filter_idx);
+ }
+ }
+
+ efx_filter_push_rx_limits(efx);
+
+ spin_unlock_bh(&state->lock);
+}
+
+int efx_probe_filters(struct efx_nic *efx)
+{
+ struct efx_filter_state *state;
+ struct efx_filter_table *table;
+ unsigned table_id;
+
+ state = kzalloc(sizeof(*efx->filter_state), GFP_KERNEL);
+ if (!state)
+ return -ENOMEM;
+ efx->filter_state = state;
+
+ spin_lock_init(&state->lock);
+
+ if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) {
+ table = &state->table[EFX_FILTER_TABLE_RX_IP];
+ table->offset = FR_BZ_RX_FILTER_TBL0;
+ table->size = FR_BZ_RX_FILTER_TBL0_ROWS;
+ table->step = FR_BZ_RX_FILTER_TBL0_STEP;
+ }
+
+ if (efx_nic_rev(efx) >= EFX_REV_SIENA_A0) {
+ table = &state->table[EFX_FILTER_TABLE_RX_MAC];
+ table->offset = FR_CZ_RX_MAC_FILTER_TBL0;
+ table->size = FR_CZ_RX_MAC_FILTER_TBL0_ROWS;
+ table->step = FR_CZ_RX_MAC_FILTER_TBL0_STEP;
+ }
+
+ for (table_id = 0; table_id < EFX_FILTER_TABLE_COUNT; table_id++) {
+ table = &state->table[table_id];
+ if (table->size == 0)
+ continue;
+ table->used_bitmap = kcalloc(BITS_TO_LONGS(table->size),
+ sizeof(unsigned long),
+ GFP_KERNEL);
+ if (!table->used_bitmap)
+ goto fail;
+ table->spec = vmalloc(table->size * sizeof(*table->spec));
+ if (!table->spec)
+ goto fail;
+ memset(table->spec, 0, table->size * sizeof(*table->spec));
+ }
+
+ return 0;
+
+fail:
+ efx_remove_filters(efx);
+ return -ENOMEM;
+}
+
+void efx_remove_filters(struct efx_nic *efx)
+{
+ struct efx_filter_state *state = efx->filter_state;
+ enum efx_filter_table_id table_id;
+
+ for (table_id = 0; table_id < EFX_FILTER_TABLE_COUNT; table_id++) {
+ kfree(state->table[table_id].used_bitmap);
+ vfree(state->table[table_id].spec);
+ }
+ kfree(state);
+}
diff --git a/drivers/net/sfc/filter.h b/drivers/net/sfc/filter.h
new file mode 100644
index 000000000000..a53319ded79c
--- /dev/null
+++ b/drivers/net/sfc/filter.h
@@ -0,0 +1,189 @@
+/****************************************************************************
+ * Driver for Solarflare Solarstorm network controllers and boards
+ * Copyright 2005-2010 Solarflare Communications Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation, incorporated herein by reference.
+ */
+
+#ifndef EFX_FILTER_H
+#define EFX_FILTER_H
+
+#include <linux/types.h>
+
+enum efx_filter_table_id {
+ EFX_FILTER_TABLE_RX_IP = 0,
+ EFX_FILTER_TABLE_RX_MAC,
+ EFX_FILTER_TABLE_COUNT,
+};
+
+/**
+ * enum efx_filter_type - type of hardware filter
+ * @EFX_FILTER_RX_TCP_FULL: RX, matching TCP/IPv4 4-tuple
+ * @EFX_FILTER_RX_TCP_WILD: RX, matching TCP/IPv4 destination (host, port)
+ * @EFX_FILTER_RX_UDP_FULL: RX, matching UDP/IPv4 4-tuple
+ * @EFX_FILTER_RX_UDP_WILD: RX, matching UDP/IPv4 destination (host, port)
+ * @EFX_FILTER_RX_MAC_FULL: RX, matching Ethernet destination MAC address, VID
+ * @EFX_FILTER_RX_MAC_WILD: RX, matching Ethernet destination MAC address
+ *
+ * Falcon NICs only support the RX TCP/IPv4 and UDP/IPv4 filter types.
+ */
+enum efx_filter_type {
+ EFX_FILTER_RX_TCP_FULL = 0,
+ EFX_FILTER_RX_TCP_WILD,
+ EFX_FILTER_RX_UDP_FULL,
+ EFX_FILTER_RX_UDP_WILD,
+ EFX_FILTER_RX_MAC_FULL = 4,
+ EFX_FILTER_RX_MAC_WILD,
+ EFX_FILTER_TYPE_COUNT,
+};
+
+/**
+ * enum efx_filter_priority - priority of a hardware filter specification
+ * @EFX_FILTER_PRI_HINT: Performance hint
+ * @EFX_FILTER_PRI_MANUAL: Manually configured filter
+ * @EFX_FILTER_PRI_REQUIRED: Required for correct behaviour
+ */
+enum efx_filter_priority {
+ EFX_FILTER_PRI_HINT = 0,
+ EFX_FILTER_PRI_MANUAL,
+ EFX_FILTER_PRI_REQUIRED,
+};
+
+/**
+ * enum efx_filter_flags - flags for hardware filter specifications
+ * @EFX_FILTER_FLAG_RX_RSS: Use RSS to spread across multiple queues.
+ * By default, matching packets will be delivered only to the
+ * specified queue. If this flag is set, they will be delivered
+ * to a range of queues offset from the specified queue number
+ * according to the indirection table.
+ * @EFX_FILTER_FLAG_RX_SCATTER: Enable DMA scatter on the receiving
+ * queue.
+ * @EFX_FILTER_FLAG_RX_OVERRIDE_IP: Enables a MAC filter to override
+ * any IP filter that matches the same packet. By default, IP
+ * filters take precedence.
+ *
+ * Currently, no flags are defined for TX filters.
+ */
+enum efx_filter_flags {
+ EFX_FILTER_FLAG_RX_RSS = 0x01,
+ EFX_FILTER_FLAG_RX_SCATTER = 0x02,
+ EFX_FILTER_FLAG_RX_OVERRIDE_IP = 0x04,
+};
+
+/**
+ * struct efx_filter_spec - specification for a hardware filter
+ * @type: Type of match to be performed, from &enum efx_filter_type
+ * @priority: Priority of the filter, from &enum efx_filter_priority
+ * @flags: Miscellaneous flags, from &enum efx_filter_flags
+ * @dmaq_id: Source/target queue index
+ * @data: Match data (type-dependent)
+ *
+ * Use the efx_filter_set_*() functions to initialise the @type and
+ * @data fields.
+ */
+struct efx_filter_spec {
+ u8 type:4;
+ u8 priority:4;
+ u8 flags;
+ u16 dmaq_id;
+ u32 data[3];
+};
+
+/**
+ * efx_filter_set_rx_tcp_full - specify RX filter with TCP/IPv4 full match
+ * @spec: Specification to initialise
+ * @shost: Source host address (host byte order)
+ * @sport: Source port (host byte order)
+ * @dhost: Destination host address (host byte order)
+ * @dport: Destination port (host byte order)
+ */
+static inline void
+efx_filter_set_rx_tcp_full(struct efx_filter_spec *spec,
+ u32 shost, u16 sport, u32 dhost, u16 dport)
+{
+ spec->type = EFX_FILTER_RX_TCP_FULL;
+ spec->data[0] = sport | shost << 16;
+ spec->data[1] = dport << 16 | shost >> 16;
+ spec->data[2] = dhost;
+}
+
+/**
+ * efx_filter_set_rx_tcp_wild - specify RX filter with TCP/IPv4 wildcard match
+ * @spec: Specification to initialise
+ * @dhost: Destination host address (host byte order)
+ * @dport: Destination port (host byte order)
+ */
+static inline void
+efx_filter_set_rx_tcp_wild(struct efx_filter_spec *spec, u32 dhost, u16 dport)
+{
+ spec->type = EFX_FILTER_RX_TCP_WILD;
+ spec->data[0] = 0;
+ spec->data[1] = dport << 16;
+ spec->data[2] = dhost;
+}
+
+/**
+ * efx_filter_set_rx_udp_full - specify RX filter with UDP/IPv4 full match
+ * @spec: Specification to initialise
+ * @shost: Source host address (host byte order)
+ * @sport: Source port (host byte order)
+ * @dhost: Destination host address (host byte order)
+ * @dport: Destination port (host byte order)
+ */
+static inline void
+efx_filter_set_rx_udp_full(struct efx_filter_spec *spec,
+ u32 shost, u16 sport, u32 dhost, u16 dport)
+{
+ spec->type = EFX_FILTER_RX_UDP_FULL;
+ spec->data[0] = sport | shost << 16;
+ spec->data[1] = dport << 16 | shost >> 16;
+ spec->data[2] = dhost;
+}
+
+/**
+ * efx_filter_set_rx_udp_wild - specify RX filter with UDP/IPv4 wildcard match
+ * @spec: Specification to initialise
+ * @dhost: Destination host address (host byte order)
+ * @dport: Destination port (host byte order)
+ */
+static inline void
+efx_filter_set_rx_udp_wild(struct efx_filter_spec *spec, u32 dhost, u16 dport)
+{
+ spec->type = EFX_FILTER_RX_UDP_WILD;
+ spec->data[0] = dport;
+ spec->data[1] = 0;
+ spec->data[2] = dhost;
+}
+
+/**
+ * efx_filter_set_rx_mac_full - specify RX filter with MAC full match
+ * @spec: Specification to initialise
+ * @vid: VLAN ID
+ * @addr: Destination MAC address
+ */
+static inline void efx_filter_set_rx_mac_full(struct efx_filter_spec *spec,
+ u16 vid, const u8 *addr)
+{
+ spec->type = EFX_FILTER_RX_MAC_FULL;
+ spec->data[0] = vid;
+ spec->data[1] = addr[2] << 24 | addr[3] << 16 | addr[4] << 8 | addr[5];
+ spec->data[2] = addr[0] << 8 | addr[1];
+}
+
+/**
+ * efx_filter_set_rx_mac_full - specify RX filter with MAC wildcard match
+ * @spec: Specification to initialise
+ * @addr: Destination MAC address
+ */
+static inline void efx_filter_set_rx_mac_wild(struct efx_filter_spec *spec,
+ const u8 *addr)
+{
+ spec->type = EFX_FILTER_RX_MAC_WILD;
+ spec->data[0] = 0;
+ spec->data[1] = addr[2] << 24 | addr[3] << 16 | addr[4] << 8 | addr[5];
+ spec->data[2] = addr[0] << 8 | addr[1];
+}
+
+#endif /* EFX_FILTER_H */
diff --git a/drivers/net/sfc/mac.h b/drivers/net/sfc/mac.h
index f1aa5f374890..6886cdf87c12 100644
--- a/drivers/net/sfc/mac.h
+++ b/drivers/net/sfc/mac.h
@@ -13,10 +13,8 @@
#include "net_driver.h"
-extern struct efx_mac_operations falcon_gmac_operations;
extern struct efx_mac_operations falcon_xmac_operations;
extern struct efx_mac_operations efx_mcdi_mac_operations;
-extern void falcon_reconfigure_xmac_core(struct efx_nic *efx);
extern int efx_mcdi_mac_stats(struct efx_nic *efx, dma_addr_t dma_addr,
u32 dma_len, int enable, int clear);
diff --git a/drivers/net/sfc/mcdi.c b/drivers/net/sfc/mcdi.c
index 3912b8fed912..12cf910c2ce7 100644
--- a/drivers/net/sfc/mcdi.c
+++ b/drivers/net/sfc/mcdi.c
@@ -1093,8 +1093,8 @@ int efx_mcdi_reset_mc(struct efx_nic *efx)
return rc;
}
-int efx_mcdi_wol_filter_set(struct efx_nic *efx, u32 type,
- const u8 *mac, int *id_out)
+static int efx_mcdi_wol_filter_set(struct efx_nic *efx, u32 type,
+ const u8 *mac, int *id_out)
{
u8 inbuf[MC_CMD_WOL_FILTER_SET_IN_LEN];
u8 outbuf[MC_CMD_WOL_FILTER_SET_OUT_LEN];
diff --git a/drivers/net/sfc/mcdi.h b/drivers/net/sfc/mcdi.h
index f1f89ad4075a..c792f1d65e48 100644
--- a/drivers/net/sfc/mcdi.h
+++ b/drivers/net/sfc/mcdi.h
@@ -121,8 +121,6 @@ extern int efx_mcdi_handle_assertion(struct efx_nic *efx);
extern void efx_mcdi_set_id_led(struct efx_nic *efx, enum efx_led_mode mode);
extern int efx_mcdi_reset_port(struct efx_nic *efx);
extern int efx_mcdi_reset_mc(struct efx_nic *efx);
-extern int efx_mcdi_wol_filter_set(struct efx_nic *efx, u32 type,
- const u8 *mac, int *id_out);
extern int efx_mcdi_wol_filter_set_magic(struct efx_nic *efx,
const u8 *mac, int *id_out);
extern int efx_mcdi_wol_filter_get_magic(struct efx_nic *efx, int *id_out);
diff --git a/drivers/net/sfc/mcdi_phy.c b/drivers/net/sfc/mcdi_phy.c
index 0121e71702bf..c992742446b1 100644
--- a/drivers/net/sfc/mcdi_phy.c
+++ b/drivers/net/sfc/mcdi_phy.c
@@ -713,7 +713,8 @@ static int efx_mcdi_phy_run_tests(struct efx_nic *efx, int *results,
return 0;
}
-const char *efx_mcdi_phy_test_name(struct efx_nic *efx, unsigned int index)
+static const char *efx_mcdi_phy_test_name(struct efx_nic *efx,
+ unsigned int index)
{
struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
diff --git a/drivers/net/sfc/mdio_10g.c b/drivers/net/sfc/mdio_10g.c
index eeaf0bd64bd3..98d946020429 100644
--- a/drivers/net/sfc/mdio_10g.c
+++ b/drivers/net/sfc/mdio_10g.c
@@ -286,46 +286,24 @@ int efx_mdio_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
*/
void efx_mdio_an_reconfigure(struct efx_nic *efx)
{
- bool xnp = (efx->link_advertising & ADVERTISED_10000baseT_Full
- || EFX_WORKAROUND_13204(efx));
int reg;
WARN_ON(!(efx->mdio.mmds & MDIO_DEVS_AN));
/* Set up the base page */
- reg = ADVERTISE_CSMA;
- if (efx->link_advertising & ADVERTISED_10baseT_Half)
- reg |= ADVERTISE_10HALF;
- if (efx->link_advertising & ADVERTISED_10baseT_Full)
- reg |= ADVERTISE_10FULL;
- if (efx->link_advertising & ADVERTISED_100baseT_Half)
- reg |= ADVERTISE_100HALF;
- if (efx->link_advertising & ADVERTISED_100baseT_Full)
- reg |= ADVERTISE_100FULL;
- if (xnp)
- reg |= ADVERTISE_RESV;
- else if (efx->link_advertising & (ADVERTISED_1000baseT_Half |
- ADVERTISED_1000baseT_Full))
- reg |= ADVERTISE_NPAGE;
+ reg = ADVERTISE_CSMA | ADVERTISE_RESV;
if (efx->link_advertising & ADVERTISED_Pause)
reg |= ADVERTISE_PAUSE_CAP;
if (efx->link_advertising & ADVERTISED_Asym_Pause)
reg |= ADVERTISE_PAUSE_ASYM;
efx_mdio_write(efx, MDIO_MMD_AN, MDIO_AN_ADVERTISE, reg);
- /* Set up the (extended) next page if necessary */
- if (efx->phy_op->set_npage_adv)
- efx->phy_op->set_npage_adv(efx, efx->link_advertising);
+ /* Set up the (extended) next page */
+ efx->phy_op->set_npage_adv(efx, efx->link_advertising);
/* Enable and restart AN */
reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_CTRL1);
- reg |= MDIO_AN_CTRL1_ENABLE;
- if (!(EFX_WORKAROUND_15195(efx) && LOOPBACK_EXTERNAL(efx)))
- reg |= MDIO_AN_CTRL1_RESTART;
- if (xnp)
- reg |= MDIO_AN_CTRL1_XNP;
- else
- reg &= ~MDIO_AN_CTRL1_XNP;
+ reg |= MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART | MDIO_AN_CTRL1_XNP;
efx_mdio_write(efx, MDIO_MMD_AN, MDIO_CTRL1, reg);
}
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h
index 64e7caa4bbb5..0a7e26d73b52 100644
--- a/drivers/net/sfc/net_driver.h
+++ b/drivers/net/sfc/net_driver.h
@@ -29,6 +29,7 @@
#include <linux/device.h>
#include <linux/highmem.h>
#include <linux/workqueue.h>
+#include <linux/vmalloc.h>
#include <linux/i2c.h>
#include "enum.h"
@@ -137,6 +138,7 @@ struct efx_tx_buffer {
* @channel: The associated channel
* @buffer: The software buffer ring
* @txd: The hardware descriptor ring
+ * @ptr_mask: The size of the ring minus 1.
* @flushed: Used when handling queue flushing
* @read_count: Current read pointer.
* This is the number of buffers that have been removed from both rings.
@@ -170,6 +172,7 @@ struct efx_tx_queue {
struct efx_nic *nic;
struct efx_tx_buffer *buffer;
struct efx_special_buffer txd;
+ unsigned int ptr_mask;
enum efx_flush_state flushed;
/* Members used mainly on the completion path */
@@ -225,10 +228,9 @@ struct efx_rx_page_state {
/**
* struct efx_rx_queue - An Efx RX queue
* @efx: The associated Efx NIC
- * @queue: DMA queue number
- * @channel: The associated channel
* @buffer: The software buffer ring
* @rxd: The hardware descriptor ring
+ * @ptr_mask: The size of the ring minus 1.
* @added_count: Number of buffers added to the receive queue.
* @notified_count: Number of buffers given to NIC (<= @added_count).
* @removed_count: Number of buffers removed from the receive queue.
@@ -240,9 +242,6 @@ struct efx_rx_page_state {
* @min_fill: RX descriptor minimum non-zero fill level.
* This records the minimum fill level observed when a ring
* refill was triggered.
- * @min_overfill: RX descriptor minimum overflow fill level.
- * This records the minimum fill level at which RX queue
- * overflow was observed. It should never be set.
* @alloc_page_count: RX allocation strategy counter.
* @alloc_skb_count: RX allocation strategy counter.
* @slow_fill: Timer used to defer efx_nic_generate_fill_event().
@@ -250,10 +249,9 @@ struct efx_rx_page_state {
*/
struct efx_rx_queue {
struct efx_nic *efx;
- int queue;
- struct efx_channel *channel;
struct efx_rx_buffer *buffer;
struct efx_special_buffer rxd;
+ unsigned int ptr_mask;
int added_count;
int notified_count;
@@ -302,7 +300,6 @@ enum efx_rx_alloc_method {
*
* @efx: Associated Efx NIC
* @channel: Channel instance number
- * @name: Name for channel and IRQ
* @enabled: Channel enabled indicator
* @irq: IRQ number (MSI and MSI-X only)
* @irq_moderation: IRQ moderation value (in hardware ticks)
@@ -311,6 +308,7 @@ enum efx_rx_alloc_method {
* @reset_work: Scheduled reset work thread
* @work_pending: Is work pending via NAPI?
* @eventq: Event queue buffer
+ * @eventq_mask: Event queue pointer mask
* @eventq_read_ptr: Event queue read pointer
* @last_eventq_read_ptr: Last event queue read pointer value.
* @magic_count: Event queue test event count
@@ -327,14 +325,14 @@ enum efx_rx_alloc_method {
* @n_rx_frm_trunc: Count of RX_FRM_TRUNC errors
* @n_rx_overlength: Count of RX_OVERLENGTH errors
* @n_skbuff_leaks: Count of skbuffs leaked due to RX overrun
- * @tx_queue: Pointer to first TX queue, or %NULL if not used for TX
+ * @rx_queue: RX queue for this channel
* @tx_stop_count: Core TX queue stop count
* @tx_stop_lock: Core TX queue stop lock
+ * @tx_queue: TX queues for this channel
*/
struct efx_channel {
struct efx_nic *efx;
int channel;
- char name[IFNAMSIZ + 6];
bool enabled;
int irq;
unsigned int irq_moderation;
@@ -342,6 +340,7 @@ struct efx_channel {
struct napi_struct napi_str;
bool work_pending;
struct efx_special_buffer eventq;
+ unsigned int eventq_mask;
unsigned int eventq_read_ptr;
unsigned int last_eventq_read_ptr;
unsigned int magic_count;
@@ -366,9 +365,12 @@ struct efx_channel {
struct efx_rx_buffer *rx_pkt;
bool rx_pkt_csummed;
- struct efx_tx_queue *tx_queue;
+ struct efx_rx_queue rx_queue;
+
atomic_t tx_stop_count;
spinlock_t tx_stop_lock;
+
+ struct efx_tx_queue tx_queue[2];
};
enum efx_led_mode {
@@ -385,11 +387,6 @@ extern const unsigned int efx_loopback_mode_max;
#define LOOPBACK_MODE(efx) \
STRING_TABLE_LOOKUP((efx)->loopback_mode, efx_loopback_mode)
-extern const char *efx_interrupt_mode_names[];
-extern const unsigned int efx_interrupt_mode_max;
-#define INT_MODE(efx) \
- STRING_TABLE_LOOKUP(efx->interrupt_mode, efx_interrupt_mode)
-
extern const char *efx_reset_type_names[];
extern const unsigned int efx_reset_type_max;
#define RESET_TYPE(type) \
@@ -404,8 +401,6 @@ enum efx_int_mode {
};
#define EFX_INT_MODE_USE_MSI(x) (((x)->interrupt_mode) <= EFX_INT_MODE_MSI)
-#define EFX_IS10G(efx) ((efx)->link_state.speed == 10000)
-
enum nic_state {
STATE_INIT = 0,
STATE_RUNNING = 1,
@@ -618,6 +613,8 @@ union efx_multicast_hash {
efx_oword_t oword[EFX_MCAST_HASH_ENTRIES / sizeof(efx_oword_t) / 8];
};
+struct efx_filter_state;
+
/**
* struct efx_nic - an Efx NIC
* @name: Device name (net device name or bus id before net device registered)
@@ -641,6 +638,9 @@ union efx_multicast_hash {
* @tx_queue: TX DMA queues
* @rx_queue: RX DMA queues
* @channel: Channels
+ * @channel_name: Names for channels and their IRQs
+ * @rxq_entries: Size of receive queues requested by user.
+ * @txq_entries: Size of transmit queues requested by user.
* @next_buffer_table: First available buffer table id
* @n_channels: Number of channels in use
* @n_rx_channels: Number of channels used for RX (= number of RX queues)
@@ -724,10 +724,11 @@ struct efx_nic {
enum nic_state state;
enum reset_type reset_pending;
- struct efx_tx_queue tx_queue[EFX_MAX_TX_QUEUES];
- struct efx_rx_queue rx_queue[EFX_MAX_RX_QUEUES];
- struct efx_channel channel[EFX_MAX_CHANNELS];
+ struct efx_channel *channel[EFX_MAX_CHANNELS];
+ char channel_name[EFX_MAX_CHANNELS][IFNAMSIZ + 6];
+ unsigned rxq_entries;
+ unsigned txq_entries;
unsigned next_buffer_table;
unsigned n_channels;
unsigned n_rx_channels;
@@ -794,6 +795,8 @@ struct efx_nic {
u64 loopback_modes;
void *loopback_selftest;
+
+ struct efx_filter_state *filter_state;
};
static inline int efx_dev_registered(struct efx_nic *efx)
@@ -909,39 +912,67 @@ struct efx_nic_type {
*
*************************************************************************/
+static inline struct efx_channel *
+efx_get_channel(struct efx_nic *efx, unsigned index)
+{
+ EFX_BUG_ON_PARANOID(index >= efx->n_channels);
+ return efx->channel[index];
+}
+
/* Iterate over all used channels */
#define efx_for_each_channel(_channel, _efx) \
- for (_channel = &((_efx)->channel[0]); \
- _channel < &((_efx)->channel[(efx)->n_channels]); \
- _channel++)
-
-/* Iterate over all used TX queues */
-#define efx_for_each_tx_queue(_tx_queue, _efx) \
- for (_tx_queue = &((_efx)->tx_queue[0]); \
- _tx_queue < &((_efx)->tx_queue[EFX_TXQ_TYPES * \
- (_efx)->n_tx_channels]); \
- _tx_queue++)
+ for (_channel = (_efx)->channel[0]; \
+ _channel; \
+ _channel = (_channel->channel + 1 < (_efx)->n_channels) ? \
+ (_efx)->channel[_channel->channel + 1] : NULL)
+
+extern struct efx_tx_queue *
+efx_get_tx_queue(struct efx_nic *efx, unsigned index, unsigned type);
+
+static inline struct efx_tx_queue *
+efx_channel_get_tx_queue(struct efx_channel *channel, unsigned type)
+{
+ struct efx_tx_queue *tx_queue = channel->tx_queue;
+ EFX_BUG_ON_PARANOID(type >= EFX_TXQ_TYPES);
+ return tx_queue->channel ? tx_queue + type : NULL;
+}
/* Iterate over all TX queues belonging to a channel */
#define efx_for_each_channel_tx_queue(_tx_queue, _channel) \
- for (_tx_queue = (_channel)->tx_queue; \
+ for (_tx_queue = efx_channel_get_tx_queue(channel, 0); \
_tx_queue && _tx_queue < (_channel)->tx_queue + EFX_TXQ_TYPES; \
_tx_queue++)
-/* Iterate over all used RX queues */
-#define efx_for_each_rx_queue(_rx_queue, _efx) \
- for (_rx_queue = &((_efx)->rx_queue[0]); \
- _rx_queue < &((_efx)->rx_queue[(_efx)->n_rx_channels]); \
- _rx_queue++)
+static inline struct efx_rx_queue *
+efx_get_rx_queue(struct efx_nic *efx, unsigned index)
+{
+ EFX_BUG_ON_PARANOID(index >= efx->n_rx_channels);
+ return &efx->channel[index]->rx_queue;
+}
+
+static inline struct efx_rx_queue *
+efx_channel_get_rx_queue(struct efx_channel *channel)
+{
+ return channel->channel < channel->efx->n_rx_channels ?
+ &channel->rx_queue : NULL;
+}
/* Iterate over all RX queues belonging to a channel */
#define efx_for_each_channel_rx_queue(_rx_queue, _channel) \
- for (_rx_queue = &((_channel)->efx->rx_queue[(_channel)->channel]); \
+ for (_rx_queue = efx_channel_get_rx_queue(channel); \
_rx_queue; \
- _rx_queue = NULL) \
- if (_rx_queue->channel != (_channel)) \
- continue; \
- else
+ _rx_queue = NULL)
+
+static inline struct efx_channel *
+efx_rx_queue_channel(struct efx_rx_queue *rx_queue)
+{
+ return container_of(rx_queue, struct efx_channel, rx_queue);
+}
+
+static inline int efx_rx_queue_index(struct efx_rx_queue *rx_queue)
+{
+ return efx_rx_queue_channel(rx_queue)->channel;
+}
/* Returns a pointer to the specified receive buffer in the RX
* descriptor queue.
@@ -949,7 +980,7 @@ struct efx_nic_type {
static inline struct efx_rx_buffer *efx_rx_buffer(struct efx_rx_queue *rx_queue,
unsigned int index)
{
- return (&rx_queue->buffer[index]);
+ return &rx_queue->buffer[index];
}
/* Set bit in a little-endian bitfield */
diff --git a/drivers/net/sfc/nic.c b/drivers/net/sfc/nic.c
index f595d920c7c4..41c36b9a4244 100644
--- a/drivers/net/sfc/nic.c
+++ b/drivers/net/sfc/nic.c
@@ -104,7 +104,7 @@ static inline void efx_write_buf_tbl(struct efx_nic *efx, efx_qword_t *value,
static inline efx_qword_t *efx_event(struct efx_channel *channel,
unsigned int index)
{
- return (((efx_qword_t *) (channel->eventq.addr)) + index);
+ return ((efx_qword_t *) (channel->eventq.addr)) + index;
}
/* See if an event is present
@@ -119,8 +119,8 @@ static inline efx_qword_t *efx_event(struct efx_channel *channel,
*/
static inline int efx_event_present(efx_qword_t *event)
{
- return (!(EFX_DWORD_IS_ALL_ONES(event->dword[0]) |
- EFX_DWORD_IS_ALL_ONES(event->dword[1])));
+ return !(EFX_DWORD_IS_ALL_ONES(event->dword[0]) |
+ EFX_DWORD_IS_ALL_ONES(event->dword[1]));
}
static bool efx_masked_compare_oword(const efx_oword_t *a, const efx_oword_t *b,
@@ -263,8 +263,8 @@ static int efx_alloc_special_buffer(struct efx_nic *efx,
{
len = ALIGN(len, EFX_BUF_SIZE);
- buffer->addr = pci_alloc_consistent(efx->pci_dev, len,
- &buffer->dma_addr);
+ buffer->addr = dma_alloc_coherent(&efx->pci_dev->dev, len,
+ &buffer->dma_addr, GFP_KERNEL);
if (!buffer->addr)
return -ENOMEM;
buffer->len = len;
@@ -301,8 +301,8 @@ efx_free_special_buffer(struct efx_nic *efx, struct efx_special_buffer *buffer)
(u64)buffer->dma_addr, buffer->len,
buffer->addr, (u64)virt_to_phys(buffer->addr));
- pci_free_consistent(efx->pci_dev, buffer->len, buffer->addr,
- buffer->dma_addr);
+ dma_free_coherent(&efx->pci_dev->dev, buffer->len, buffer->addr,
+ buffer->dma_addr);
buffer->addr = NULL;
buffer->entries = 0;
}
@@ -347,7 +347,7 @@ void efx_nic_free_buffer(struct efx_nic *efx, struct efx_buffer *buffer)
static inline efx_qword_t *
efx_tx_desc(struct efx_tx_queue *tx_queue, unsigned int index)
{
- return (((efx_qword_t *) (tx_queue->txd.addr)) + index);
+ return ((efx_qword_t *) (tx_queue->txd.addr)) + index;
}
/* This writes to the TX_DESC_WPTR; write pointer for TX descriptor ring */
@@ -356,7 +356,7 @@ static inline void efx_notify_tx_desc(struct efx_tx_queue *tx_queue)
unsigned write_ptr;
efx_dword_t reg;
- write_ptr = tx_queue->write_count & EFX_TXQ_MASK;
+ write_ptr = tx_queue->write_count & tx_queue->ptr_mask;
EFX_POPULATE_DWORD_1(reg, FRF_AZ_TX_DESC_WPTR_DWORD, write_ptr);
efx_writed_page(tx_queue->efx, &reg,
FR_AZ_TX_DESC_UPD_DWORD_P0, tx_queue->queue);
@@ -377,7 +377,7 @@ void efx_nic_push_buffers(struct efx_tx_queue *tx_queue)
BUG_ON(tx_queue->write_count == tx_queue->insert_count);
do {
- write_ptr = tx_queue->write_count & EFX_TXQ_MASK;
+ write_ptr = tx_queue->write_count & tx_queue->ptr_mask;
buffer = &tx_queue->buffer[write_ptr];
txd = efx_tx_desc(tx_queue, write_ptr);
++tx_queue->write_count;
@@ -398,10 +398,11 @@ void efx_nic_push_buffers(struct efx_tx_queue *tx_queue)
int efx_nic_probe_tx(struct efx_tx_queue *tx_queue)
{
struct efx_nic *efx = tx_queue->efx;
- BUILD_BUG_ON(EFX_TXQ_SIZE < 512 || EFX_TXQ_SIZE > 4096 ||
- EFX_TXQ_SIZE & EFX_TXQ_MASK);
+ unsigned entries;
+
+ entries = tx_queue->ptr_mask + 1;
return efx_alloc_special_buffer(efx, &tx_queue->txd,
- EFX_TXQ_SIZE * sizeof(efx_qword_t));
+ entries * sizeof(efx_qword_t));
}
void efx_nic_init_tx(struct efx_tx_queue *tx_queue)
@@ -501,7 +502,7 @@ void efx_nic_remove_tx(struct efx_tx_queue *tx_queue)
static inline efx_qword_t *
efx_rx_desc(struct efx_rx_queue *rx_queue, unsigned int index)
{
- return (((efx_qword_t *) (rx_queue->rxd.addr)) + index);
+ return ((efx_qword_t *) (rx_queue->rxd.addr)) + index;
}
/* This creates an entry in the RX descriptor queue */
@@ -526,30 +527,32 @@ efx_build_rx_desc(struct efx_rx_queue *rx_queue, unsigned index)
*/
void efx_nic_notify_rx_desc(struct efx_rx_queue *rx_queue)
{
+ struct efx_nic *efx = rx_queue->efx;
efx_dword_t reg;
unsigned write_ptr;
while (rx_queue->notified_count != rx_queue->added_count) {
- efx_build_rx_desc(rx_queue,
- rx_queue->notified_count &
- EFX_RXQ_MASK);
+ efx_build_rx_desc(
+ rx_queue,
+ rx_queue->notified_count & rx_queue->ptr_mask);
++rx_queue->notified_count;
}
wmb();
- write_ptr = rx_queue->added_count & EFX_RXQ_MASK;
+ write_ptr = rx_queue->added_count & rx_queue->ptr_mask;
EFX_POPULATE_DWORD_1(reg, FRF_AZ_RX_DESC_WPTR_DWORD, write_ptr);
- efx_writed_page(rx_queue->efx, &reg,
- FR_AZ_RX_DESC_UPD_DWORD_P0, rx_queue->queue);
+ efx_writed_page(efx, &reg, FR_AZ_RX_DESC_UPD_DWORD_P0,
+ efx_rx_queue_index(rx_queue));
}
int efx_nic_probe_rx(struct efx_rx_queue *rx_queue)
{
struct efx_nic *efx = rx_queue->efx;
- BUILD_BUG_ON(EFX_RXQ_SIZE < 512 || EFX_RXQ_SIZE > 4096 ||
- EFX_RXQ_SIZE & EFX_RXQ_MASK);
+ unsigned entries;
+
+ entries = rx_queue->ptr_mask + 1;
return efx_alloc_special_buffer(efx, &rx_queue->rxd,
- EFX_RXQ_SIZE * sizeof(efx_qword_t));
+ entries * sizeof(efx_qword_t));
}
void efx_nic_init_rx(struct efx_rx_queue *rx_queue)
@@ -561,7 +564,7 @@ void efx_nic_init_rx(struct efx_rx_queue *rx_queue)
netif_dbg(efx, hw, efx->net_dev,
"RX queue %d ring in special buffers %d-%d\n",
- rx_queue->queue, rx_queue->rxd.index,
+ efx_rx_queue_index(rx_queue), rx_queue->rxd.index,
rx_queue->rxd.index + rx_queue->rxd.entries - 1);
rx_queue->flushed = FLUSH_NONE;
@@ -575,9 +578,10 @@ void efx_nic_init_rx(struct efx_rx_queue *rx_queue)
FRF_AZ_RX_ISCSI_HDIG_EN, iscsi_digest_en,
FRF_AZ_RX_DESCQ_BUF_BASE_ID, rx_queue->rxd.index,
FRF_AZ_RX_DESCQ_EVQ_ID,
- rx_queue->channel->channel,
+ efx_rx_queue_channel(rx_queue)->channel,
FRF_AZ_RX_DESCQ_OWNER_ID, 0,
- FRF_AZ_RX_DESCQ_LABEL, rx_queue->queue,
+ FRF_AZ_RX_DESCQ_LABEL,
+ efx_rx_queue_index(rx_queue),
FRF_AZ_RX_DESCQ_SIZE,
__ffs(rx_queue->rxd.entries),
FRF_AZ_RX_DESCQ_TYPE, 0 /* kernel queue */ ,
@@ -585,7 +589,7 @@ void efx_nic_init_rx(struct efx_rx_queue *rx_queue)
FRF_AZ_RX_DESCQ_JUMBO, !is_b0,
FRF_AZ_RX_DESCQ_EN, 1);
efx_writeo_table(efx, &rx_desc_ptr, efx->type->rxd_ptr_tbl_base,
- rx_queue->queue);
+ efx_rx_queue_index(rx_queue));
}
static void efx_flush_rx_queue(struct efx_rx_queue *rx_queue)
@@ -598,7 +602,8 @@ static void efx_flush_rx_queue(struct efx_rx_queue *rx_queue)
/* Post a flush command */
EFX_POPULATE_OWORD_2(rx_flush_descq,
FRF_AZ_RX_FLUSH_DESCQ_CMD, 1,
- FRF_AZ_RX_FLUSH_DESCQ, rx_queue->queue);
+ FRF_AZ_RX_FLUSH_DESCQ,
+ efx_rx_queue_index(rx_queue));
efx_writeo(efx, &rx_flush_descq, FR_AZ_RX_FLUSH_DESCQ);
}
@@ -613,7 +618,7 @@ void efx_nic_fini_rx(struct efx_rx_queue *rx_queue)
/* Remove RX descriptor ring from card */
EFX_ZERO_OWORD(rx_desc_ptr);
efx_writeo_table(efx, &rx_desc_ptr, efx->type->rxd_ptr_tbl_base,
- rx_queue->queue);
+ efx_rx_queue_index(rx_queue));
/* Unpin RX descriptor ring */
efx_fini_special_buffer(efx, &rx_queue->rxd);
@@ -648,7 +653,7 @@ void efx_nic_eventq_read_ack(struct efx_channel *channel)
}
/* Use HW to insert a SW defined event */
-void efx_generate_event(struct efx_channel *channel, efx_qword_t *event)
+static void efx_generate_event(struct efx_channel *channel, efx_qword_t *event)
{
efx_oword_t drv_ev_reg;
@@ -680,15 +685,17 @@ efx_handle_tx_event(struct efx_channel *channel, efx_qword_t *event)
/* Transmit completion */
tx_ev_desc_ptr = EFX_QWORD_FIELD(*event, FSF_AZ_TX_EV_DESC_PTR);
tx_ev_q_label = EFX_QWORD_FIELD(*event, FSF_AZ_TX_EV_Q_LABEL);
- tx_queue = &efx->tx_queue[tx_ev_q_label];
+ tx_queue = efx_channel_get_tx_queue(
+ channel, tx_ev_q_label % EFX_TXQ_TYPES);
tx_packets = ((tx_ev_desc_ptr - tx_queue->read_count) &
- EFX_TXQ_MASK);
+ tx_queue->ptr_mask);
channel->irq_mod_score += tx_packets;
efx_xmit_done(tx_queue, tx_ev_desc_ptr);
} else if (EFX_QWORD_FIELD(*event, FSF_AZ_TX_EV_WQ_FF_FULL)) {
/* Rewrite the FIFO write pointer */
tx_ev_q_label = EFX_QWORD_FIELD(*event, FSF_AZ_TX_EV_Q_LABEL);
- tx_queue = &efx->tx_queue[tx_ev_q_label];
+ tx_queue = efx_channel_get_tx_queue(
+ channel, tx_ev_q_label % EFX_TXQ_TYPES);
if (efx_dev_registered(efx))
netif_tx_lock(efx->net_dev);
@@ -714,6 +721,7 @@ static void efx_handle_rx_not_ok(struct efx_rx_queue *rx_queue,
bool *rx_ev_pkt_ok,
bool *discard)
{
+ struct efx_channel *channel = efx_rx_queue_channel(rx_queue);
struct efx_nic *efx = rx_queue->efx;
bool rx_ev_buf_owner_id_err, rx_ev_ip_hdr_chksum_err;
bool rx_ev_tcp_udp_chksum_err, rx_ev_eth_crc_err;
@@ -746,14 +754,14 @@ static void efx_handle_rx_not_ok(struct efx_rx_queue *rx_queue,
/* Count errors that are not in MAC stats. Ignore expected
* checksum errors during self-test. */
if (rx_ev_frm_trunc)
- ++rx_queue->channel->n_rx_frm_trunc;
+ ++channel->n_rx_frm_trunc;
else if (rx_ev_tobe_disc)
- ++rx_queue->channel->n_rx_tobe_disc;
+ ++channel->n_rx_tobe_disc;
else if (!efx->loopback_selftest) {
if (rx_ev_ip_hdr_chksum_err)
- ++rx_queue->channel->n_rx_ip_hdr_chksum_err;
+ ++channel->n_rx_ip_hdr_chksum_err;
else if (rx_ev_tcp_udp_chksum_err)
- ++rx_queue->channel->n_rx_tcp_udp_chksum_err;
+ ++channel->n_rx_tcp_udp_chksum_err;
}
/* The frame must be discarded if any of these are true. */
@@ -769,7 +777,7 @@ static void efx_handle_rx_not_ok(struct efx_rx_queue *rx_queue,
netif_dbg(efx, rx_err, efx->net_dev,
" RX queue %d unexpected RX event "
EFX_QWORD_FMT "%s%s%s%s%s%s%s%s\n",
- rx_queue->queue, EFX_QWORD_VAL(*event),
+ efx_rx_queue_index(rx_queue), EFX_QWORD_VAL(*event),
rx_ev_buf_owner_id_err ? " [OWNER_ID_ERR]" : "",
rx_ev_ip_hdr_chksum_err ?
" [IP_HDR_CHKSUM_ERR]" : "",
@@ -791,8 +799,8 @@ efx_handle_rx_bad_index(struct efx_rx_queue *rx_queue, unsigned index)
struct efx_nic *efx = rx_queue->efx;
unsigned expected, dropped;
- expected = rx_queue->removed_count & EFX_RXQ_MASK;
- dropped = (index - expected) & EFX_RXQ_MASK;
+ expected = rx_queue->removed_count & rx_queue->ptr_mask;
+ dropped = (index - expected) & rx_queue->ptr_mask;
netif_info(efx, rx_err, efx->net_dev,
"dropped %d events (index=%d expected=%d)\n",
dropped, index, expected);
@@ -827,10 +835,10 @@ efx_handle_rx_event(struct efx_channel *channel, const efx_qword_t *event)
WARN_ON(EFX_QWORD_FIELD(*event, FSF_AZ_RX_EV_Q_LABEL) !=
channel->channel);
- rx_queue = &efx->rx_queue[channel->channel];
+ rx_queue = efx_channel_get_rx_queue(channel);
rx_ev_desc_ptr = EFX_QWORD_FIELD(*event, FSF_AZ_RX_EV_DESC_PTR);
- expected_ptr = rx_queue->removed_count & EFX_RXQ_MASK;
+ expected_ptr = rx_queue->removed_count & rx_queue->ptr_mask;
if (unlikely(rx_ev_desc_ptr != expected_ptr))
efx_handle_rx_bad_index(rx_queue, rx_ev_desc_ptr);
@@ -879,7 +887,7 @@ efx_handle_generated_event(struct efx_channel *channel, efx_qword_t *event)
/* The queue must be empty, so we won't receive any rx
* events, so efx_process_channel() won't refill the
* queue. Refill it here */
- efx_fast_push_rx_descriptors(&efx->rx_queue[channel->channel]);
+ efx_fast_push_rx_descriptors(efx_channel_get_rx_queue(channel));
else
netif_dbg(efx, hw, efx->net_dev, "channel %d received "
"generated event "EFX_QWORD_FMT"\n",
@@ -997,6 +1005,7 @@ efx_handle_driver_event(struct efx_channel *channel, efx_qword_t *event)
int efx_nic_process_eventq(struct efx_channel *channel, int budget)
{
+ struct efx_nic *efx = channel->efx;
unsigned int read_ptr;
efx_qword_t event, *p_event;
int ev_code;
@@ -1021,7 +1030,7 @@ int efx_nic_process_eventq(struct efx_channel *channel, int budget)
EFX_SET_QWORD(*p_event);
/* Increment read pointer */
- read_ptr = (read_ptr + 1) & EFX_EVQ_MASK;
+ read_ptr = (read_ptr + 1) & channel->eventq_mask;
ev_code = EFX_QWORD_FIELD(event, FSF_AZ_EV_CODE);
@@ -1033,7 +1042,7 @@ int efx_nic_process_eventq(struct efx_channel *channel, int budget)
break;
case FSE_AZ_EV_CODE_TX_EV:
tx_packets += efx_handle_tx_event(channel, &event);
- if (tx_packets >= EFX_TXQ_SIZE) {
+ if (tx_packets > efx->txq_entries) {
spent = budget;
goto out;
}
@@ -1068,10 +1077,11 @@ out:
int efx_nic_probe_eventq(struct efx_channel *channel)
{
struct efx_nic *efx = channel->efx;
- BUILD_BUG_ON(EFX_EVQ_SIZE < 512 || EFX_EVQ_SIZE > 32768 ||
- EFX_EVQ_SIZE & EFX_EVQ_MASK);
+ unsigned entries;
+
+ entries = channel->eventq_mask + 1;
return efx_alloc_special_buffer(efx, &channel->eventq,
- EFX_EVQ_SIZE * sizeof(efx_qword_t));
+ entries * sizeof(efx_qword_t));
}
void efx_nic_init_eventq(struct efx_channel *channel)
@@ -1163,11 +1173,11 @@ void efx_nic_generate_fill_event(struct efx_channel *channel)
static void efx_poll_flush_events(struct efx_nic *efx)
{
- struct efx_channel *channel = &efx->channel[0];
+ struct efx_channel *channel = efx_get_channel(efx, 0);
struct efx_tx_queue *tx_queue;
struct efx_rx_queue *rx_queue;
unsigned int read_ptr = channel->eventq_read_ptr;
- unsigned int end_ptr = (read_ptr - 1) & EFX_EVQ_MASK;
+ unsigned int end_ptr = (read_ptr - 1) & channel->eventq_mask;
do {
efx_qword_t *event = efx_event(channel, read_ptr);
@@ -1185,7 +1195,9 @@ static void efx_poll_flush_events(struct efx_nic *efx)
ev_queue = EFX_QWORD_FIELD(*event,
FSF_AZ_DRIVER_EV_SUBDATA);
if (ev_queue < EFX_TXQ_TYPES * efx->n_tx_channels) {
- tx_queue = efx->tx_queue + ev_queue;
+ tx_queue = efx_get_tx_queue(
+ efx, ev_queue / EFX_TXQ_TYPES,
+ ev_queue % EFX_TXQ_TYPES);
tx_queue->flushed = FLUSH_DONE;
}
} else if (ev_code == FSE_AZ_EV_CODE_DRIVER_EV &&
@@ -1195,7 +1207,7 @@ static void efx_poll_flush_events(struct efx_nic *efx)
ev_failed = EFX_QWORD_FIELD(
*event, FSF_AZ_DRIVER_EV_RX_FLUSH_FAIL);
if (ev_queue < efx->n_rx_channels) {
- rx_queue = efx->rx_queue + ev_queue;
+ rx_queue = efx_get_rx_queue(efx, ev_queue);
rx_queue->flushed =
ev_failed ? FLUSH_FAILED : FLUSH_DONE;
}
@@ -1205,7 +1217,7 @@ static void efx_poll_flush_events(struct efx_nic *efx)
* it's ok to throw away every non-flush event */
EFX_SET_QWORD(*event);
- read_ptr = (read_ptr + 1) & EFX_EVQ_MASK;
+ read_ptr = (read_ptr + 1) & channel->eventq_mask;
} while (read_ptr != end_ptr);
channel->eventq_read_ptr = read_ptr;
@@ -1216,6 +1228,7 @@ static void efx_poll_flush_events(struct efx_nic *efx)
* serialise them */
int efx_nic_flush_queues(struct efx_nic *efx)
{
+ struct efx_channel *channel;
struct efx_rx_queue *rx_queue;
struct efx_tx_queue *tx_queue;
int i, tx_pending, rx_pending;
@@ -1224,29 +1237,35 @@ int efx_nic_flush_queues(struct efx_nic *efx)
efx->type->prepare_flush(efx);
/* Flush all tx queues in parallel */
- efx_for_each_tx_queue(tx_queue, efx)
- efx_flush_tx_queue(tx_queue);
+ efx_for_each_channel(channel, efx) {
+ efx_for_each_channel_tx_queue(tx_queue, channel)
+ efx_flush_tx_queue(tx_queue);
+ }
/* The hardware supports four concurrent rx flushes, each of which may
* need to be retried if there is an outstanding descriptor fetch */
for (i = 0; i < EFX_FLUSH_POLL_COUNT; ++i) {
rx_pending = tx_pending = 0;
- efx_for_each_rx_queue(rx_queue, efx) {
- if (rx_queue->flushed == FLUSH_PENDING)
- ++rx_pending;
- }
- efx_for_each_rx_queue(rx_queue, efx) {
- if (rx_pending == EFX_RX_FLUSH_COUNT)
- break;
- if (rx_queue->flushed == FLUSH_FAILED ||
- rx_queue->flushed == FLUSH_NONE) {
- efx_flush_rx_queue(rx_queue);
- ++rx_pending;
+ efx_for_each_channel(channel, efx) {
+ efx_for_each_channel_rx_queue(rx_queue, channel) {
+ if (rx_queue->flushed == FLUSH_PENDING)
+ ++rx_pending;
}
}
- efx_for_each_tx_queue(tx_queue, efx) {
- if (tx_queue->flushed != FLUSH_DONE)
- ++tx_pending;
+ efx_for_each_channel(channel, efx) {
+ efx_for_each_channel_rx_queue(rx_queue, channel) {
+ if (rx_pending == EFX_RX_FLUSH_COUNT)
+ break;
+ if (rx_queue->flushed == FLUSH_FAILED ||
+ rx_queue->flushed == FLUSH_NONE) {
+ efx_flush_rx_queue(rx_queue);
+ ++rx_pending;
+ }
+ }
+ efx_for_each_channel_tx_queue(tx_queue, channel) {
+ if (tx_queue->flushed != FLUSH_DONE)
+ ++tx_pending;
+ }
}
if (rx_pending == 0 && tx_pending == 0)
@@ -1258,19 +1277,21 @@ int efx_nic_flush_queues(struct efx_nic *efx)
/* Mark the queues as all flushed. We're going to return failure
* leading to a reset, or fake up success anyway */
- efx_for_each_tx_queue(tx_queue, efx) {
- if (tx_queue->flushed != FLUSH_DONE)
- netif_err(efx, hw, efx->net_dev,
- "tx queue %d flush command timed out\n",
- tx_queue->queue);
- tx_queue->flushed = FLUSH_DONE;
- }
- efx_for_each_rx_queue(rx_queue, efx) {
- if (rx_queue->flushed != FLUSH_DONE)
- netif_err(efx, hw, efx->net_dev,
- "rx queue %d flush command timed out\n",
- rx_queue->queue);
- rx_queue->flushed = FLUSH_DONE;
+ efx_for_each_channel(channel, efx) {
+ efx_for_each_channel_tx_queue(tx_queue, channel) {
+ if (tx_queue->flushed != FLUSH_DONE)
+ netif_err(efx, hw, efx->net_dev,
+ "tx queue %d flush command timed out\n",
+ tx_queue->queue);
+ tx_queue->flushed = FLUSH_DONE;
+ }
+ efx_for_each_channel_rx_queue(rx_queue, channel) {
+ if (rx_queue->flushed != FLUSH_DONE)
+ netif_err(efx, hw, efx->net_dev,
+ "rx queue %d flush command timed out\n",
+ efx_rx_queue_index(rx_queue));
+ rx_queue->flushed = FLUSH_DONE;
+ }
}
return -ETIMEDOUT;
@@ -1457,7 +1478,7 @@ static irqreturn_t efx_legacy_interrupt(int irq, void *dev_id)
*/
static irqreturn_t efx_msi_interrupt(int irq, void *dev_id)
{
- struct efx_channel *channel = dev_id;
+ struct efx_channel *channel = *(struct efx_channel **)dev_id;
struct efx_nic *efx = channel->efx;
efx_oword_t *int_ker = efx->irq_status.addr;
int syserr;
@@ -1532,7 +1553,8 @@ int efx_nic_init_interrupt(struct efx_nic *efx)
efx_for_each_channel(channel, efx) {
rc = request_irq(channel->irq, efx_msi_interrupt,
IRQF_PROBE_SHARED, /* Not shared */
- channel->name, channel);
+ efx->channel_name[channel->channel],
+ &efx->channel[channel->channel]);
if (rc) {
netif_err(efx, drv, efx->net_dev,
"failed to hook IRQ %d\n", channel->irq);
@@ -1544,7 +1566,7 @@ int efx_nic_init_interrupt(struct efx_nic *efx)
fail2:
efx_for_each_channel(channel, efx)
- free_irq(channel->irq, channel);
+ free_irq(channel->irq, &efx->channel[channel->channel]);
fail1:
return rc;
}
@@ -1557,7 +1579,7 @@ void efx_nic_fini_interrupt(struct efx_nic *efx)
/* Disable MSI/MSI-X interrupts */
efx_for_each_channel(channel, efx) {
if (channel->irq)
- free_irq(channel->irq, channel);
+ free_irq(channel->irq, &efx->channel[channel->channel]);
}
/* ACK legacy interrupt */
@@ -1827,8 +1849,7 @@ static const struct efx_nic_reg_table efx_nic_reg_tables[] = {
REGISTER_TABLE_BB_CZ(TX_DESC_PTR_TBL),
REGISTER_TABLE_AA(EVQ_PTR_TBL_KER),
REGISTER_TABLE_BB_CZ(EVQ_PTR_TBL),
- /* The register buffer is allocated with slab, so we can't
- * reasonably read all of the buffer table (up to 8MB!).
+ /* We can't reasonably read all of the buffer table (up to 8MB!).
* However this driver will only use a few entries. Reading
* 1K entries allows for some expansion of queue count and
* size before we need to change the version. */
@@ -1836,7 +1857,6 @@ static const struct efx_nic_reg_table efx_nic_reg_tables[] = {
A, A, 8, 1024),
REGISTER_TABLE_DIMENSIONS(BUF_FULL_TBL, FR_BZ_BUF_FULL_TBL,
B, Z, 8, 1024),
- /* RX_FILTER_TBL{0,1} is huge and not used by this driver */
REGISTER_TABLE_CZ(RX_MAC_FILTER_TBL0),
REGISTER_TABLE_BB_CZ(TIMER_TBL),
REGISTER_TABLE_BB_CZ(TX_PACE_TBL),
@@ -1846,6 +1866,7 @@ static const struct efx_nic_reg_table efx_nic_reg_tables[] = {
REGISTER_TABLE_CZ(MC_TREG_SMEM),
/* MSIX_PBA_TABLE is not mapped */
/* SRM_DBG is not mapped (and is redundant with BUF_FLL_TBL) */
+ REGISTER_TABLE_BZ(RX_FILTER_TBL0),
};
size_t efx_nic_get_regs_len(struct efx_nic *efx)
diff --git a/drivers/net/sfc/phy.h b/drivers/net/sfc/phy.h
index 5bc26137257b..1dab609757fb 100644
--- a/drivers/net/sfc/phy.h
+++ b/drivers/net/sfc/phy.h
@@ -11,17 +11,12 @@
#define EFX_PHY_H
/****************************************************************************
- * 10Xpress (SFX7101 and SFT9001) PHYs
+ * 10Xpress (SFX7101) PHY
*/
extern struct efx_phy_operations falcon_sfx7101_phy_ops;
-extern struct efx_phy_operations falcon_sft9001_phy_ops;
extern void tenxpress_set_id_led(struct efx_nic *efx, enum efx_led_mode mode);
-/* Wait for the PHY to boot. Return 0 on success, -EINVAL if the PHY failed
- * to boot due to corrupt flash, or some other negative error code. */
-extern int sft9001_wait_boot(struct efx_nic *efx);
-
/****************************************************************************
* AMCC/Quake QT202x PHYs
*/
@@ -42,6 +37,17 @@ extern struct efx_phy_operations falcon_qt202x_phy_ops;
extern void falcon_qt202x_set_led(struct efx_nic *p, int led, int state);
/****************************************************************************
+* Transwitch CX4 retimer
+*/
+extern struct efx_phy_operations falcon_txc_phy_ops;
+
+#define TXC_GPIO_DIR_INPUT 0
+#define TXC_GPIO_DIR_OUTPUT 1
+
+extern void falcon_txc_set_gpio_dir(struct efx_nic *efx, int pin, int dir);
+extern void falcon_txc_set_gpio_val(struct efx_nic *efx, int pin, int val);
+
+/****************************************************************************
* Siena managed PHYs
*/
extern struct efx_phy_operations efx_mcdi_phy_ops;
diff --git a/drivers/net/sfc/regs.h b/drivers/net/sfc/regs.h
index 18a3be428348..96430ed81c36 100644
--- a/drivers/net/sfc/regs.h
+++ b/drivers/net/sfc/regs.h
@@ -2893,6 +2893,20 @@
#define FRF_AB_XX_FORCE_SIG_WIDTH 8
#define FFE_AB_XX_FORCE_SIG_ALL_LANES 0xff
+/* RX_MAC_FILTER_TBL0 */
+/* RMFT_DEST_MAC is wider than 32 bits */
+#define FRF_CZ_RMFT_DEST_MAC_LO_LBN 12
+#define FRF_CZ_RMFT_DEST_MAC_LO_WIDTH 32
+#define FRF_CZ_RMFT_DEST_MAC_HI_LBN 44
+#define FRF_CZ_RMFT_DEST_MAC_HI_WIDTH 16
+
+/* TX_MAC_FILTER_TBL0 */
+/* TMFT_SRC_MAC is wider than 32 bits */
+#define FRF_CZ_TMFT_SRC_MAC_LO_LBN 12
+#define FRF_CZ_TMFT_SRC_MAC_LO_WIDTH 32
+#define FRF_CZ_TMFT_SRC_MAC_HI_LBN 44
+#define FRF_CZ_TMFT_SRC_MAC_HI_WIDTH 16
+
/* DRIVER_EV */
/* Sub-fields of an RX flush completion event */
#define FSF_AZ_DRIVER_EV_RX_FLUSH_FAIL_LBN 12
diff --git a/drivers/net/sfc/rx.c b/drivers/net/sfc/rx.c
index 799c461ce7b8..6d0959b5158e 100644
--- a/drivers/net/sfc/rx.c
+++ b/drivers/net/sfc/rx.c
@@ -133,7 +133,7 @@ static int efx_init_rx_buffers_skb(struct efx_rx_queue *rx_queue)
unsigned index, count;
for (count = 0; count < EFX_RX_BATCH; ++count) {
- index = rx_queue->added_count & EFX_RXQ_MASK;
+ index = rx_queue->added_count & rx_queue->ptr_mask;
rx_buf = efx_rx_buffer(rx_queue, index);
rx_buf->skb = netdev_alloc_skb(net_dev, skb_len);
@@ -208,7 +208,7 @@ static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue)
dma_addr += sizeof(struct efx_rx_page_state);
split:
- index = rx_queue->added_count & EFX_RXQ_MASK;
+ index = rx_queue->added_count & rx_queue->ptr_mask;
rx_buf = efx_rx_buffer(rx_queue, index);
rx_buf->dma_addr = dma_addr + EFX_PAGE_IP_ALIGN;
rx_buf->skb = NULL;
@@ -285,7 +285,7 @@ static void efx_resurrect_rx_buffer(struct efx_rx_queue *rx_queue,
* we'd like to insert an additional descriptor whilst leaving
* EFX_RXD_HEAD_ROOM for the non-recycle path */
fill_level = (rx_queue->added_count - rx_queue->removed_count + 2);
- if (unlikely(fill_level >= EFX_RXQ_SIZE - EFX_RXD_HEAD_ROOM)) {
+ if (unlikely(fill_level > rx_queue->max_fill)) {
/* We could place "state" on a list, and drain the list in
* efx_fast_push_rx_descriptors(). For now, this will do. */
return;
@@ -294,7 +294,7 @@ static void efx_resurrect_rx_buffer(struct efx_rx_queue *rx_queue,
++state->refcnt;
get_page(rx_buf->page);
- index = rx_queue->added_count & EFX_RXQ_MASK;
+ index = rx_queue->added_count & rx_queue->ptr_mask;
new_buf = efx_rx_buffer(rx_queue, index);
new_buf->dma_addr = rx_buf->dma_addr ^ (PAGE_SIZE >> 1);
new_buf->skb = NULL;
@@ -311,7 +311,7 @@ static void efx_recycle_rx_buffer(struct efx_channel *channel,
struct efx_rx_buffer *rx_buf)
{
struct efx_nic *efx = channel->efx;
- struct efx_rx_queue *rx_queue = &efx->rx_queue[channel->channel];
+ struct efx_rx_queue *rx_queue = efx_channel_get_rx_queue(channel);
struct efx_rx_buffer *new_buf;
unsigned index;
@@ -319,7 +319,7 @@ static void efx_recycle_rx_buffer(struct efx_channel *channel,
page_count(rx_buf->page) == 1)
efx_resurrect_rx_buffer(rx_queue, rx_buf);
- index = rx_queue->added_count & EFX_RXQ_MASK;
+ index = rx_queue->added_count & rx_queue->ptr_mask;
new_buf = efx_rx_buffer(rx_queue, index);
memcpy(new_buf, rx_buf, sizeof(*new_buf));
@@ -341,13 +341,13 @@ static void efx_recycle_rx_buffer(struct efx_channel *channel,
*/
void efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue)
{
- struct efx_channel *channel = rx_queue->channel;
+ struct efx_channel *channel = efx_rx_queue_channel(rx_queue);
unsigned fill_level;
int space, rc = 0;
/* Calculate current fill level, and exit if we don't need to fill */
fill_level = (rx_queue->added_count - rx_queue->removed_count);
- EFX_BUG_ON_PARANOID(fill_level > EFX_RXQ_SIZE);
+ EFX_BUG_ON_PARANOID(fill_level > rx_queue->efx->rxq_entries);
if (fill_level >= rx_queue->fast_fill_trigger)
goto out;
@@ -364,7 +364,8 @@ void efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue)
netif_vdbg(rx_queue->efx, rx_status, rx_queue->efx->net_dev,
"RX queue %d fast-filling descriptor ring from"
" level %d to level %d using %s allocation\n",
- rx_queue->queue, fill_level, rx_queue->fast_fill_limit,
+ efx_rx_queue_index(rx_queue), fill_level,
+ rx_queue->fast_fill_limit,
channel->rx_alloc_push_pages ? "page" : "skb");
do {
@@ -382,7 +383,7 @@ void efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue)
netif_vdbg(rx_queue->efx, rx_status, rx_queue->efx->net_dev,
"RX queue %d fast-filled descriptor ring "
- "to level %d\n", rx_queue->queue,
+ "to level %d\n", efx_rx_queue_index(rx_queue),
rx_queue->added_count - rx_queue->removed_count);
out:
@@ -393,7 +394,7 @@ void efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue)
void efx_rx_slow_fill(unsigned long context)
{
struct efx_rx_queue *rx_queue = (struct efx_rx_queue *)context;
- struct efx_channel *channel = rx_queue->channel;
+ struct efx_channel *channel = efx_rx_queue_channel(rx_queue);
/* Post an event to cause NAPI to run and refill the queue */
efx_nic_generate_fill_event(channel);
@@ -421,7 +422,7 @@ static void efx_rx_packet__check_len(struct efx_rx_queue *rx_queue,
netif_err(efx, rx_err, efx->net_dev,
" RX queue %d seriously overlength "
"RX event (0x%x > 0x%x+0x%x). Leaking\n",
- rx_queue->queue, len, max_len,
+ efx_rx_queue_index(rx_queue), len, max_len,
efx->type->rx_buffer_padding);
/* If this buffer was skb-allocated, then the meta
* data at the end of the skb will be trashed. So
@@ -434,10 +435,10 @@ static void efx_rx_packet__check_len(struct efx_rx_queue *rx_queue,
netif_err(efx, rx_err, efx->net_dev,
" RX queue %d overlength RX event "
"(0x%x > 0x%x)\n",
- rx_queue->queue, len, max_len);
+ efx_rx_queue_index(rx_queue), len, max_len);
}
- rx_queue->channel->n_rx_overlength++;
+ efx_rx_queue_channel(rx_queue)->n_rx_overlength++;
}
/* Pass a received packet up through the generic LRO stack
@@ -507,7 +508,7 @@ void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
unsigned int len, bool checksummed, bool discard)
{
struct efx_nic *efx = rx_queue->efx;
- struct efx_channel *channel = rx_queue->channel;
+ struct efx_channel *channel = efx_rx_queue_channel(rx_queue);
struct efx_rx_buffer *rx_buf;
bool leak_packet = false;
@@ -528,7 +529,7 @@ void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
netif_vdbg(efx, rx_status, efx->net_dev,
"RX queue %d received id %x at %llx+%x %s%s\n",
- rx_queue->queue, index,
+ efx_rx_queue_index(rx_queue), index,
(unsigned long long)rx_buf->dma_addr, len,
(checksummed ? " [SUMMED]" : ""),
(discard ? " [DISCARD]" : ""));
@@ -560,12 +561,11 @@ void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
*/
rx_buf->len = len;
out:
- if (rx_queue->channel->rx_pkt)
- __efx_rx_packet(rx_queue->channel,
- rx_queue->channel->rx_pkt,
- rx_queue->channel->rx_pkt_csummed);
- rx_queue->channel->rx_pkt = rx_buf;
- rx_queue->channel->rx_pkt_csummed = checksummed;
+ if (channel->rx_pkt)
+ __efx_rx_packet(channel,
+ channel->rx_pkt, channel->rx_pkt_csummed);
+ channel->rx_pkt = rx_buf;
+ channel->rx_pkt_csummed = checksummed;
}
/* Handle a received packet. Second half: Touches packet payload. */
@@ -615,7 +615,7 @@ void __efx_rx_packet(struct efx_channel *channel,
EFX_BUG_ON_PARANOID(!skb);
/* Set the SKB flags */
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
/* Pass the packet up */
netif_receive_skb(skb);
@@ -650,15 +650,22 @@ void efx_rx_strategy(struct efx_channel *channel)
int efx_probe_rx_queue(struct efx_rx_queue *rx_queue)
{
struct efx_nic *efx = rx_queue->efx;
- unsigned int rxq_size;
+ unsigned int entries;
int rc;
+ /* Create the smallest power-of-two aligned ring */
+ entries = max(roundup_pow_of_two(efx->rxq_entries), EFX_MIN_DMAQ_SIZE);
+ EFX_BUG_ON_PARANOID(entries > EFX_MAX_DMAQ_SIZE);
+ rx_queue->ptr_mask = entries - 1;
+
netif_dbg(efx, probe, efx->net_dev,
- "creating RX queue %d\n", rx_queue->queue);
+ "creating RX queue %d size %#x mask %#x\n",
+ efx_rx_queue_index(rx_queue), efx->rxq_entries,
+ rx_queue->ptr_mask);
/* Allocate RX buffers */
- rxq_size = EFX_RXQ_SIZE * sizeof(*rx_queue->buffer);
- rx_queue->buffer = kzalloc(rxq_size, GFP_KERNEL);
+ rx_queue->buffer = kzalloc(entries * sizeof(*rx_queue->buffer),
+ GFP_KERNEL);
if (!rx_queue->buffer)
return -ENOMEM;
@@ -672,20 +679,20 @@ int efx_probe_rx_queue(struct efx_rx_queue *rx_queue)
void efx_init_rx_queue(struct efx_rx_queue *rx_queue)
{
+ struct efx_nic *efx = rx_queue->efx;
unsigned int max_fill, trigger, limit;
netif_dbg(rx_queue->efx, drv, rx_queue->efx->net_dev,
- "initialising RX queue %d\n", rx_queue->queue);
+ "initialising RX queue %d\n", efx_rx_queue_index(rx_queue));
/* Initialise ptr fields */
rx_queue->added_count = 0;
rx_queue->notified_count = 0;
rx_queue->removed_count = 0;
rx_queue->min_fill = -1U;
- rx_queue->min_overfill = -1U;
/* Initialise limit fields */
- max_fill = EFX_RXQ_SIZE - EFX_RXD_HEAD_ROOM;
+ max_fill = efx->rxq_entries - EFX_RXD_HEAD_ROOM;
trigger = max_fill * min(rx_refill_threshold, 100U) / 100U;
limit = max_fill * min(rx_refill_limit, 100U) / 100U;
@@ -703,14 +710,14 @@ void efx_fini_rx_queue(struct efx_rx_queue *rx_queue)
struct efx_rx_buffer *rx_buf;
netif_dbg(rx_queue->efx, drv, rx_queue->efx->net_dev,
- "shutting down RX queue %d\n", rx_queue->queue);
+ "shutting down RX queue %d\n", efx_rx_queue_index(rx_queue));
del_timer_sync(&rx_queue->slow_fill);
efx_nic_fini_rx(rx_queue);
/* Release RX buffers NB start at index 0 not current HW ptr */
if (rx_queue->buffer) {
- for (i = 0; i <= EFX_RXQ_MASK; i++) {
+ for (i = 0; i <= rx_queue->ptr_mask; i++) {
rx_buf = efx_rx_buffer(rx_queue, i);
efx_fini_rx_buffer(rx_queue, rx_buf);
}
@@ -720,7 +727,7 @@ void efx_fini_rx_queue(struct efx_rx_queue *rx_queue)
void efx_remove_rx_queue(struct efx_rx_queue *rx_queue)
{
netif_dbg(rx_queue->efx, drv, rx_queue->efx->net_dev,
- "destroying RX queue %d\n", rx_queue->queue);
+ "destroying RX queue %d\n", efx_rx_queue_index(rx_queue));
efx_nic_remove_rx(rx_queue);
diff --git a/drivers/net/sfc/selftest.c b/drivers/net/sfc/selftest.c
index 85f015f005d5..0ebfb99f1299 100644
--- a/drivers/net/sfc/selftest.c
+++ b/drivers/net/sfc/selftest.c
@@ -48,6 +48,16 @@ static const unsigned char payload_source[ETH_ALEN] = {
static const char payload_msg[] =
"Hello world! This is an Efx loopback test in progress!";
+/* Interrupt mode names */
+static const unsigned int efx_interrupt_mode_max = EFX_INT_MODE_MAX;
+static const char *efx_interrupt_mode_names[] = {
+ [EFX_INT_MODE_MSIX] = "MSI-X",
+ [EFX_INT_MODE_MSI] = "MSI",
+ [EFX_INT_MODE_LEGACY] = "legacy",
+};
+#define INT_MODE(efx) \
+ STRING_TABLE_LOOKUP(efx->interrupt_mode, efx_interrupt_mode)
+
/**
* efx_loopback_state - persistent state during a loopback selftest
* @flush: Drop all packets in efx_loopback_rx_packet
@@ -506,7 +516,7 @@ efx_test_loopback(struct efx_tx_queue *tx_queue,
for (i = 0; i < 3; i++) {
/* Determine how many packets to send */
- state->packet_count = EFX_TXQ_SIZE / 3;
+ state->packet_count = efx->txq_entries / 3;
state->packet_count = min(1 << (i << 2), state->packet_count);
state->skbs = kzalloc(sizeof(state->skbs[0]) *
state->packet_count, GFP_KERNEL);
@@ -567,7 +577,7 @@ static int efx_wait_for_link(struct efx_nic *efx)
efx->type->monitor(efx);
mutex_unlock(&efx->mac_lock);
} else {
- struct efx_channel *channel = &efx->channel[0];
+ struct efx_channel *channel = efx_get_channel(efx, 0);
if (channel->work_pending)
efx_process_channel_now(channel);
}
@@ -594,6 +604,7 @@ static int efx_test_loopbacks(struct efx_nic *efx, struct efx_self_tests *tests,
{
enum efx_loopback_mode mode;
struct efx_loopback_state *state;
+ struct efx_channel *channel = efx_get_channel(efx, 0);
struct efx_tx_queue *tx_queue;
int rc = 0;
@@ -634,7 +645,7 @@ static int efx_test_loopbacks(struct efx_nic *efx, struct efx_self_tests *tests,
}
/* Test both types of TX queue */
- efx_for_each_channel_tx_queue(tx_queue, &efx->channel[0]) {
+ efx_for_each_channel_tx_queue(tx_queue, channel) {
state->offload_csum = (tx_queue->queue &
EFX_TXQ_TYPE_OFFLOAD);
rc = efx_test_loopback(tx_queue,
diff --git a/drivers/net/sfc/siena.c b/drivers/net/sfc/siena.c
index 3fab030f8ab5..45236f58a258 100644
--- a/drivers/net/sfc/siena.c
+++ b/drivers/net/sfc/siena.c
@@ -129,7 +129,7 @@ static int siena_probe_port(struct efx_nic *efx)
return 0;
}
-void siena_remove_port(struct efx_nic *efx)
+static void siena_remove_port(struct efx_nic *efx)
{
efx->phy_op->remove(efx);
efx_nic_free_buffer(efx, &efx->stats_buffer);
@@ -450,7 +450,7 @@ static int siena_try_update_nic_stats(struct efx_nic *efx)
mac_stats->rx_bad_bytes);
MAC_STAT(rx_packets, RX_PKTS);
MAC_STAT(rx_good, RX_GOOD_PKTS);
- mac_stats->rx_bad = mac_stats->rx_packets - mac_stats->rx_good;
+ MAC_STAT(rx_bad, RX_BAD_FCS_PKTS);
MAC_STAT(rx_pause, RX_PAUSE_PKTS);
MAC_STAT(rx_control, RX_CONTROL_PKTS);
MAC_STAT(rx_unicast, RX_UNICAST_PKTS);
@@ -651,6 +651,6 @@ struct efx_nic_type siena_a0_nic_type = {
.tx_dc_base = 0x88000,
.rx_dc_base = 0x68000,
.offload_features = (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
- NETIF_F_RXHASH),
+ NETIF_F_RXHASH | NETIF_F_NTUPLE),
.reset_world_flags = ETH_RESET_MGMT << ETH_RESET_SHARED_SHIFT,
};
diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c
index 6791be90c2fe..1bc6c48c96ee 100644
--- a/drivers/net/sfc/tenxpress.c
+++ b/drivers/net/sfc/tenxpress.c
@@ -19,10 +19,7 @@
#include "workarounds.h"
#include "selftest.h"
-/* We expect these MMDs to be in the package. SFT9001 also has a
- * clause 22 extension MMD, but since it doesn't have all the generic
- * MMD registers it is pointless to include it here.
- */
+/* We expect these MMDs to be in the package. */
#define TENXPRESS_REQUIRED_DEVS (MDIO_DEVS_PMAPMD | \
MDIO_DEVS_PCS | \
MDIO_DEVS_PHYXS | \
@@ -33,12 +30,6 @@
(1 << LOOPBACK_PMAPMD) | \
(1 << LOOPBACK_PHYXS_WS))
-#define SFT9001_LOOPBACKS ((1 << LOOPBACK_GPHY) | \
- (1 << LOOPBACK_PHYXS) | \
- (1 << LOOPBACK_PCS) | \
- (1 << LOOPBACK_PMAPMD) | \
- (1 << LOOPBACK_PHYXS_WS))
-
/* We complain if we fail to see the link partner as 10G capable this many
* times in a row (must be > 1 as sampling the autoneg. registers is racy)
*/
@@ -50,9 +41,8 @@
#define PMA_PMD_EXT_GMII_EN_WIDTH 1
#define PMA_PMD_EXT_CLK_OUT_LBN 2
#define PMA_PMD_EXT_CLK_OUT_WIDTH 1
-#define PMA_PMD_LNPGA_POWERDOWN_LBN 8 /* SFX7101 only */
+#define PMA_PMD_LNPGA_POWERDOWN_LBN 8
#define PMA_PMD_LNPGA_POWERDOWN_WIDTH 1
-#define PMA_PMD_EXT_CLK312_LBN 8 /* SFT9001 only */
#define PMA_PMD_EXT_CLK312_WIDTH 1
#define PMA_PMD_EXT_LPOWER_LBN 12
#define PMA_PMD_EXT_LPOWER_WIDTH 1
@@ -84,7 +74,6 @@
#define PMA_PMD_LED_FLASH (3)
#define PMA_PMD_LED_MASK 3
/* All LEDs under hardware control */
-#define SFT9001_PMA_PMD_LED_DEFAULT 0
/* Green and Amber under hardware control, Red off */
#define SFX7101_PMA_PMD_LED_DEFAULT (PMA_PMD_LED_OFF << PMA_PMD_LED_RX_LBN)
@@ -98,31 +87,7 @@
#define PMA_PMD_SPEED_LBN 4
#define PMA_PMD_SPEED_WIDTH 4
-/* Cable diagnostics - SFT9001 only */
-#define PMA_PMD_CDIAG_CTRL_REG 49213
-#define CDIAG_CTRL_IMMED_LBN 15
-#define CDIAG_CTRL_BRK_LINK_LBN 12
-#define CDIAG_CTRL_IN_PROG_LBN 11
-#define CDIAG_CTRL_LEN_UNIT_LBN 10
-#define CDIAG_CTRL_LEN_METRES 1
-#define PMA_PMD_CDIAG_RES_REG 49174
-#define CDIAG_RES_A_LBN 12
-#define CDIAG_RES_B_LBN 8
-#define CDIAG_RES_C_LBN 4
-#define CDIAG_RES_D_LBN 0
-#define CDIAG_RES_WIDTH 4
-#define CDIAG_RES_OPEN 2
-#define CDIAG_RES_OK 1
-#define CDIAG_RES_INVALID 0
-/* Set of 4 registers for pairs A-D */
-#define PMA_PMD_CDIAG_LEN_REG 49175
-
-/* Serdes control registers - SFT9001 only */
-#define PMA_PMD_CSERDES_CTRL_REG 64258
-/* Set the 156.25 MHz output to 312.5 MHz to drive Falcon's XMAC */
-#define PMA_PMD_CSERDES_DEFAULT 0x000f
-
-/* Misc register defines - SFX7101 only */
+/* Misc register defines */
#define PCS_CLOCK_CTRL_REG 55297
#define PLL312_RST_N_LBN 2
@@ -185,121 +150,17 @@ struct tenxpress_phy_data {
int bad_lp_tries;
};
-static ssize_t show_phy_short_reach(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev));
- int reg;
-
- reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, MDIO_PMA_10GBT_TXPWR);
- return sprintf(buf, "%d\n", !!(reg & MDIO_PMA_10GBT_TXPWR_SHORT));
-}
-
-static ssize_t set_phy_short_reach(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev));
- int rc;
-
- rtnl_lock();
- if (efx->state != STATE_RUNNING) {
- rc = -EBUSY;
- } else {
- efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, MDIO_PMA_10GBT_TXPWR,
- MDIO_PMA_10GBT_TXPWR_SHORT,
- count != 0 && *buf != '0');
- rc = efx_reconfigure_port(efx);
- }
- rtnl_unlock();
-
- return rc < 0 ? rc : (ssize_t)count;
-}
-
-static DEVICE_ATTR(phy_short_reach, 0644, show_phy_short_reach,
- set_phy_short_reach);
-
-int sft9001_wait_boot(struct efx_nic *efx)
-{
- unsigned long timeout = jiffies + HZ + 1;
- int boot_stat;
-
- for (;;) {
- boot_stat = efx_mdio_read(efx, MDIO_MMD_PCS,
- PCS_BOOT_STATUS_REG);
- if (boot_stat >= 0) {
- netif_dbg(efx, hw, efx->net_dev,
- "PHY boot status = %#x\n", boot_stat);
- switch (boot_stat &
- ((1 << PCS_BOOT_FATAL_ERROR_LBN) |
- (3 << PCS_BOOT_PROGRESS_LBN) |
- (1 << PCS_BOOT_DOWNLOAD_WAIT_LBN) |
- (1 << PCS_BOOT_CODE_STARTED_LBN))) {
- case ((1 << PCS_BOOT_FATAL_ERROR_LBN) |
- (PCS_BOOT_PROGRESS_CHECKSUM <<
- PCS_BOOT_PROGRESS_LBN)):
- case ((1 << PCS_BOOT_FATAL_ERROR_LBN) |
- (PCS_BOOT_PROGRESS_INIT <<
- PCS_BOOT_PROGRESS_LBN) |
- (1 << PCS_BOOT_DOWNLOAD_WAIT_LBN)):
- return -EINVAL;
- case ((PCS_BOOT_PROGRESS_WAIT_MDIO <<
- PCS_BOOT_PROGRESS_LBN) |
- (1 << PCS_BOOT_DOWNLOAD_WAIT_LBN)):
- return (efx->phy_mode & PHY_MODE_SPECIAL) ?
- 0 : -EIO;
- case ((PCS_BOOT_PROGRESS_JUMP <<
- PCS_BOOT_PROGRESS_LBN) |
- (1 << PCS_BOOT_CODE_STARTED_LBN)):
- case ((PCS_BOOT_PROGRESS_JUMP <<
- PCS_BOOT_PROGRESS_LBN) |
- (1 << PCS_BOOT_DOWNLOAD_WAIT_LBN) |
- (1 << PCS_BOOT_CODE_STARTED_LBN)):
- return (efx->phy_mode & PHY_MODE_SPECIAL) ?
- -EIO : 0;
- default:
- if (boot_stat & (1 << PCS_BOOT_FATAL_ERROR_LBN))
- return -EIO;
- break;
- }
- }
-
- if (time_after_eq(jiffies, timeout))
- return -ETIMEDOUT;
-
- msleep(50);
- }
-}
-
static int tenxpress_init(struct efx_nic *efx)
{
- int reg;
-
- if (efx->phy_type == PHY_TYPE_SFX7101) {
- /* Enable 312.5 MHz clock */
- efx_mdio_write(efx, MDIO_MMD_PCS, PCS_TEST_SELECT_REG,
- 1 << CLK312_EN_LBN);
- } else {
- /* Enable 312.5 MHz clock and GMII */
- reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG);
- reg |= ((1 << PMA_PMD_EXT_GMII_EN_LBN) |
- (1 << PMA_PMD_EXT_CLK_OUT_LBN) |
- (1 << PMA_PMD_EXT_CLK312_LBN) |
- (1 << PMA_PMD_EXT_ROBUST_LBN));
-
- efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG, reg);
- efx_mdio_set_flag(efx, MDIO_MMD_C22EXT,
- GPHY_XCONTROL_REG, 1 << GPHY_ISOLATE_LBN,
- false);
- }
+ /* Enable 312.5 MHz clock */
+ efx_mdio_write(efx, MDIO_MMD_PCS, PCS_TEST_SELECT_REG,
+ 1 << CLK312_EN_LBN);
/* Set the LEDs up as: Green = Link, Amber = Link/Act, Red = Off */
- if (efx->phy_type == PHY_TYPE_SFX7101) {
- efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_CTRL_REG,
- 1 << PMA_PMA_LED_ACTIVITY_LBN, true);
- efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_OVERR_REG,
- SFX7101_PMA_PMD_LED_DEFAULT);
- }
+ efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_CTRL_REG,
+ 1 << PMA_PMA_LED_ACTIVITY_LBN, true);
+ efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_OVERR_REG,
+ SFX7101_PMA_PMD_LED_DEFAULT);
return 0;
}
@@ -307,7 +168,6 @@ static int tenxpress_init(struct efx_nic *efx)
static int tenxpress_phy_probe(struct efx_nic *efx)
{
struct tenxpress_phy_data *phy_data;
- int rc;
/* Allocate phy private storage */
phy_data = kzalloc(sizeof(*phy_data), GFP_KERNEL);
@@ -316,42 +176,15 @@ static int tenxpress_phy_probe(struct efx_nic *efx)
efx->phy_data = phy_data;
phy_data->phy_mode = efx->phy_mode;
- /* Create any special files */
- if (efx->phy_type == PHY_TYPE_SFT9001B) {
- rc = device_create_file(&efx->pci_dev->dev,
- &dev_attr_phy_short_reach);
- if (rc)
- goto fail;
- }
-
- if (efx->phy_type == PHY_TYPE_SFX7101) {
- efx->mdio.mmds = TENXPRESS_REQUIRED_DEVS;
- efx->mdio.mode_support = MDIO_SUPPORTS_C45;
-
- efx->loopback_modes = SFX7101_LOOPBACKS | FALCON_XMAC_LOOPBACKS;
+ efx->mdio.mmds = TENXPRESS_REQUIRED_DEVS;
+ efx->mdio.mode_support = MDIO_SUPPORTS_C45;
- efx->link_advertising = (ADVERTISED_TP | ADVERTISED_Autoneg |
- ADVERTISED_10000baseT_Full);
- } else {
- efx->mdio.mmds = TENXPRESS_REQUIRED_DEVS;
- efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22;
+ efx->loopback_modes = SFX7101_LOOPBACKS | FALCON_XMAC_LOOPBACKS;
- efx->loopback_modes = (SFT9001_LOOPBACKS |
- FALCON_XMAC_LOOPBACKS |
- FALCON_GMAC_LOOPBACKS);
-
- efx->link_advertising = (ADVERTISED_TP | ADVERTISED_Autoneg |
- ADVERTISED_10000baseT_Full |
- ADVERTISED_1000baseT_Full |
- ADVERTISED_100baseT_Full);
- }
+ efx->link_advertising = (ADVERTISED_TP | ADVERTISED_Autoneg |
+ ADVERTISED_10000baseT_Full);
return 0;
-
-fail:
- kfree(efx->phy_data);
- efx->phy_data = NULL;
- return rc;
}
static int tenxpress_phy_init(struct efx_nic *efx)
@@ -361,16 +194,6 @@ static int tenxpress_phy_init(struct efx_nic *efx)
falcon_board(efx)->type->init_phy(efx);
if (!(efx->phy_mode & PHY_MODE_SPECIAL)) {
- if (efx->phy_type == PHY_TYPE_SFT9001A) {
- int reg;
- reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD,
- PMA_PMD_XCONTROL_REG);
- reg |= (1 << PMA_PMD_EXT_SSR_LBN);
- efx_mdio_write(efx, MDIO_MMD_PMAPMD,
- PMA_PMD_XCONTROL_REG, reg);
- mdelay(200);
- }
-
rc = efx_mdio_wait_reset_mmds(efx, TENXPRESS_REQUIRED_DEVS);
if (rc < 0)
return rc;
@@ -403,7 +226,7 @@ static int tenxpress_special_reset(struct efx_nic *efx)
{
int rc, reg;
- /* The XGMAC clock is driven from the SFC7101/SFT9001 312MHz clock, so
+ /* The XGMAC clock is driven from the SFX7101 312MHz clock, so
* a special software reset can glitch the XGMAC sufficiently for stats
* requests to fail. */
falcon_stop_nic_stats(efx);
@@ -484,53 +307,18 @@ static bool sfx7101_link_ok(struct efx_nic *efx)
MDIO_DEVS_PHYXS);
}
-static bool sft9001_link_ok(struct efx_nic *efx, struct ethtool_cmd *ecmd)
-{
- u32 reg;
-
- if (efx_phy_mode_disabled(efx->phy_mode))
- return false;
- else if (efx->loopback_mode == LOOPBACK_GPHY)
- return true;
- else if (efx->loopback_mode)
- return efx_mdio_links_ok(efx,
- MDIO_DEVS_PMAPMD |
- MDIO_DEVS_PHYXS);
-
- /* We must use the same definition of link state as LASI,
- * otherwise we can miss a link state transition
- */
- if (ecmd->speed == 10000) {
- reg = efx_mdio_read(efx, MDIO_MMD_PCS, MDIO_PCS_10GBRT_STAT1);
- return reg & MDIO_PCS_10GBRT_STAT1_BLKLK;
- } else {
- reg = efx_mdio_read(efx, MDIO_MMD_C22EXT, C22EXT_STATUS_REG);
- return reg & (1 << C22EXT_STATUS_LINK_LBN);
- }
-}
-
static void tenxpress_ext_loopback(struct efx_nic *efx)
{
efx_mdio_set_flag(efx, MDIO_MMD_PHYXS, PHYXS_TEST1,
1 << LOOPBACK_NEAR_LBN,
efx->loopback_mode == LOOPBACK_PHYXS);
- if (efx->phy_type != PHY_TYPE_SFX7101)
- efx_mdio_set_flag(efx, MDIO_MMD_C22EXT, GPHY_XCONTROL_REG,
- 1 << GPHY_LOOPBACK_NEAR_LBN,
- efx->loopback_mode == LOOPBACK_GPHY);
}
static void tenxpress_low_power(struct efx_nic *efx)
{
- if (efx->phy_type == PHY_TYPE_SFX7101)
- efx_mdio_set_mmds_lpower(
- efx, !!(efx->phy_mode & PHY_MODE_LOW_POWER),
- TENXPRESS_REQUIRED_DEVS);
- else
- efx_mdio_set_flag(
- efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG,
- 1 << PMA_PMD_EXT_LPOWER_LBN,
- !!(efx->phy_mode & PHY_MODE_LOW_POWER));
+ efx_mdio_set_mmds_lpower(
+ efx, !!(efx->phy_mode & PHY_MODE_LOW_POWER),
+ TENXPRESS_REQUIRED_DEVS);
}
static int tenxpress_phy_reconfigure(struct efx_nic *efx)
@@ -550,12 +338,7 @@ static int tenxpress_phy_reconfigure(struct efx_nic *efx)
if (loop_reset || phy_mode_change) {
tenxpress_special_reset(efx);
-
- /* Reset XAUI if we were in 10G, and are staying
- * in 10G. If we're moving into and out of 10G
- * then xaui will be reset anyway */
- if (EFX_IS10G(efx))
- falcon_reset_xaui(efx);
+ falcon_reset_xaui(efx);
}
tenxpress_low_power(efx);
@@ -578,29 +361,12 @@ static bool tenxpress_phy_poll(struct efx_nic *efx)
{
struct efx_link_state old_state = efx->link_state;
- if (efx->phy_type == PHY_TYPE_SFX7101) {
- efx->link_state.up = sfx7101_link_ok(efx);
- efx->link_state.speed = 10000;
- efx->link_state.fd = true;
- efx->link_state.fc = efx_mdio_get_pause(efx);
-
- sfx7101_check_bad_lp(efx, efx->link_state.up);
- } else {
- struct ethtool_cmd ecmd;
-
- /* Check the LASI alarm first */
- if (efx->loopback_mode == LOOPBACK_NONE &&
- !(efx_mdio_read(efx, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_STAT) &
- MDIO_PMA_LASI_LSALARM))
- return false;
+ efx->link_state.up = sfx7101_link_ok(efx);
+ efx->link_state.speed = 10000;
+ efx->link_state.fd = true;
+ efx->link_state.fc = efx_mdio_get_pause(efx);
- tenxpress_get_settings(efx, &ecmd);
-
- efx->link_state.up = sft9001_link_ok(efx, &ecmd);
- efx->link_state.speed = ecmd.speed;
- efx->link_state.fd = (ecmd.duplex == DUPLEX_FULL);
- efx->link_state.fc = efx_mdio_get_pause(efx);
- }
+ sfx7101_check_bad_lp(efx, efx->link_state.up);
return !efx_link_state_equal(&efx->link_state, &old_state);
}
@@ -621,10 +387,6 @@ static void sfx7101_phy_fini(struct efx_nic *efx)
static void tenxpress_phy_remove(struct efx_nic *efx)
{
- if (efx->phy_type == PHY_TYPE_SFT9001B)
- device_remove_file(&efx->pci_dev->dev,
- &dev_attr_phy_short_reach);
-
kfree(efx->phy_data);
efx->phy_data = NULL;
}
@@ -647,10 +409,7 @@ void tenxpress_set_id_led(struct efx_nic *efx, enum efx_led_mode mode)
(PMA_PMD_LED_ON << PMA_PMD_LED_LINK_LBN);
break;
default:
- if (efx->phy_type == PHY_TYPE_SFX7101)
- reg = SFX7101_PMA_PMD_LED_DEFAULT;
- else
- reg = SFT9001_PMA_PMD_LED_DEFAULT;
+ reg = SFX7101_PMA_PMD_LED_DEFAULT;
break;
}
@@ -685,102 +444,12 @@ sfx7101_run_tests(struct efx_nic *efx, int *results, unsigned flags)
return rc;
}
-static const char *const sft9001_test_names[] = {
- "bist",
- "cable.pairA.status",
- "cable.pairB.status",
- "cable.pairC.status",
- "cable.pairD.status",
- "cable.pairA.length",
- "cable.pairB.length",
- "cable.pairC.length",
- "cable.pairD.length",
-};
-
-static const char *sft9001_test_name(struct efx_nic *efx, unsigned int index)
-{
- if (index < ARRAY_SIZE(sft9001_test_names))
- return sft9001_test_names[index];
- return NULL;
-}
-
-static int sft9001_run_tests(struct efx_nic *efx, int *results, unsigned flags)
-{
- int rc = 0, rc2, i, ctrl_reg, res_reg;
-
- /* Initialise cable diagnostic results to unknown failure */
- for (i = 1; i < 9; ++i)
- results[i] = -1;
-
- /* Run cable diagnostics; wait up to 5 seconds for them to complete.
- * A cable fault is not a self-test failure, but a timeout is. */
- ctrl_reg = ((1 << CDIAG_CTRL_IMMED_LBN) |
- (CDIAG_CTRL_LEN_METRES << CDIAG_CTRL_LEN_UNIT_LBN));
- if (flags & ETH_TEST_FL_OFFLINE) {
- /* Break the link in order to run full diagnostics. We
- * must reset the PHY to resume normal service. */
- ctrl_reg |= (1 << CDIAG_CTRL_BRK_LINK_LBN);
- }
- efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_CDIAG_CTRL_REG,
- ctrl_reg);
- i = 0;
- while (efx_mdio_read(efx, MDIO_MMD_PMAPMD, PMA_PMD_CDIAG_CTRL_REG) &
- (1 << CDIAG_CTRL_IN_PROG_LBN)) {
- if (++i == 50) {
- rc = -ETIMEDOUT;
- goto out;
- }
- msleep(100);
- }
- res_reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, PMA_PMD_CDIAG_RES_REG);
- for (i = 0; i < 4; i++) {
- int pair_res =
- (res_reg >> (CDIAG_RES_A_LBN - i * CDIAG_RES_WIDTH))
- & ((1 << CDIAG_RES_WIDTH) - 1);
- int len_reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD,
- PMA_PMD_CDIAG_LEN_REG + i);
- if (pair_res == CDIAG_RES_OK)
- results[1 + i] = 1;
- else if (pair_res == CDIAG_RES_INVALID)
- results[1 + i] = -1;
- else
- results[1 + i] = -pair_res;
- if (pair_res != CDIAG_RES_INVALID &&
- pair_res != CDIAG_RES_OPEN &&
- len_reg != 0xffff)
- results[5 + i] = len_reg;
- }
-
-out:
- if (flags & ETH_TEST_FL_OFFLINE) {
- /* Reset, running the BIST and then resuming normal service. */
- rc2 = tenxpress_special_reset(efx);
- results[0] = rc2 ? -1 : 1;
- if (!rc)
- rc = rc2;
-
- efx_mdio_an_reconfigure(efx);
- }
-
- return rc;
-}
-
static void
tenxpress_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
{
u32 adv = 0, lpa = 0;
int reg;
- if (efx->phy_type != PHY_TYPE_SFX7101) {
- reg = efx_mdio_read(efx, MDIO_MMD_C22EXT, C22EXT_MSTSLV_CTRL);
- if (reg & (1 << C22EXT_MSTSLV_CTRL_ADV_1000_FD_LBN))
- adv |= ADVERTISED_1000baseT_Full;
- reg = efx_mdio_read(efx, MDIO_MMD_C22EXT, C22EXT_MSTSLV_STATUS);
- if (reg & (1 << C22EXT_MSTSLV_STATUS_LP_1000_HD_LBN))
- lpa |= ADVERTISED_1000baseT_Half;
- if (reg & (1 << C22EXT_MSTSLV_STATUS_LP_1000_FD_LBN))
- lpa |= ADVERTISED_1000baseT_Full;
- }
reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL);
if (reg & MDIO_AN_10GBT_CTRL_ADV10G)
adv |= ADVERTISED_10000baseT_Full;
@@ -790,23 +459,9 @@ tenxpress_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
mdio45_ethtool_gset_npage(&efx->mdio, ecmd, adv, lpa);
- if (efx->phy_type != PHY_TYPE_SFX7101) {
- ecmd->supported |= (SUPPORTED_100baseT_Full |
- SUPPORTED_1000baseT_Full);
- if (ecmd->speed != SPEED_10000) {
- ecmd->eth_tp_mdix =
- (efx_mdio_read(efx, MDIO_MMD_PMAPMD,
- PMA_PMD_XSTATUS_REG) &
- (1 << PMA_PMD_XSTAT_MDIX_LBN))
- ? ETH_TP_MDI_X : ETH_TP_MDI;
- }
- }
-
/* In loopback, the PHY automatically brings up the correct interface,
* but doesn't advertise the correct speed. So override it */
- if (efx->loopback_mode == LOOPBACK_GPHY)
- ecmd->speed = SPEED_1000;
- else if (LOOPBACK_EXTERNAL(efx))
+ if (LOOPBACK_EXTERNAL(efx))
ecmd->speed = SPEED_10000;
}
@@ -825,16 +480,6 @@ static void sfx7101_set_npage_adv(struct efx_nic *efx, u32 advertising)
advertising & ADVERTISED_10000baseT_Full);
}
-static void sft9001_set_npage_adv(struct efx_nic *efx, u32 advertising)
-{
- efx_mdio_set_flag(efx, MDIO_MMD_C22EXT, C22EXT_MSTSLV_CTRL,
- 1 << C22EXT_MSTSLV_CTRL_ADV_1000_FD_LBN,
- advertising & ADVERTISED_1000baseT_Full);
- efx_mdio_set_flag(efx, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL,
- MDIO_AN_10GBT_CTRL_ADV10G,
- advertising & ADVERTISED_10000baseT_Full);
-}
-
struct efx_phy_operations falcon_sfx7101_phy_ops = {
.probe = tenxpress_phy_probe,
.init = tenxpress_phy_init,
@@ -849,18 +494,3 @@ struct efx_phy_operations falcon_sfx7101_phy_ops = {
.test_name = sfx7101_test_name,
.run_tests = sfx7101_run_tests,
};
-
-struct efx_phy_operations falcon_sft9001_phy_ops = {
- .probe = tenxpress_phy_probe,
- .init = tenxpress_phy_init,
- .reconfigure = tenxpress_phy_reconfigure,
- .poll = tenxpress_phy_poll,
- .fini = efx_port_dummy_op_void,
- .remove = tenxpress_phy_remove,
- .get_settings = tenxpress_get_settings,
- .set_settings = tenxpress_set_settings,
- .set_npage_adv = sft9001_set_npage_adv,
- .test_alive = efx_mdio_test_alive,
- .test_name = sft9001_test_name,
- .run_tests = sft9001_run_tests,
-};
diff --git a/drivers/net/sfc/tx.c b/drivers/net/sfc/tx.c
index c6942da2c99a..11726989fe2d 100644
--- a/drivers/net/sfc/tx.c
+++ b/drivers/net/sfc/tx.c
@@ -28,7 +28,7 @@
* The tx_queue descriptor ring fill-level must fall below this value
* before we restart the netif queue
*/
-#define EFX_TXQ_THRESHOLD (EFX_TXQ_MASK / 2u)
+#define EFX_TXQ_THRESHOLD(_efx) ((_efx)->txq_entries / 2u)
/* We need to be able to nest calls to netif_tx_stop_queue(), partly
* because of the 2 hardware queues associated with each core queue,
@@ -37,8 +37,9 @@
void efx_stop_queue(struct efx_channel *channel)
{
struct efx_nic *efx = channel->efx;
+ struct efx_tx_queue *tx_queue = efx_channel_get_tx_queue(channel, 0);
- if (!channel->tx_queue)
+ if (!tx_queue)
return;
spin_lock_bh(&channel->tx_stop_lock);
@@ -46,9 +47,8 @@ void efx_stop_queue(struct efx_channel *channel)
atomic_inc(&channel->tx_stop_count);
netif_tx_stop_queue(
- netdev_get_tx_queue(
- efx->net_dev,
- channel->tx_queue->queue / EFX_TXQ_TYPES));
+ netdev_get_tx_queue(efx->net_dev,
+ tx_queue->queue / EFX_TXQ_TYPES));
spin_unlock_bh(&channel->tx_stop_lock);
}
@@ -57,8 +57,9 @@ void efx_stop_queue(struct efx_channel *channel)
void efx_wake_queue(struct efx_channel *channel)
{
struct efx_nic *efx = channel->efx;
+ struct efx_tx_queue *tx_queue = efx_channel_get_tx_queue(channel, 0);
- if (!channel->tx_queue)
+ if (!tx_queue)
return;
local_bh_disable();
@@ -66,9 +67,8 @@ void efx_wake_queue(struct efx_channel *channel)
&channel->tx_stop_lock)) {
netif_vdbg(efx, tx_queued, efx->net_dev, "waking TX queue\n");
netif_tx_wake_queue(
- netdev_get_tx_queue(
- efx->net_dev,
- channel->tx_queue->queue / EFX_TXQ_TYPES));
+ netdev_get_tx_queue(efx->net_dev,
+ tx_queue->queue / EFX_TXQ_TYPES));
spin_unlock(&channel->tx_stop_lock);
}
local_bh_enable();
@@ -207,7 +207,7 @@ netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
}
fill_level = tx_queue->insert_count - tx_queue->old_read_count;
- q_space = EFX_TXQ_MASK - 1 - fill_level;
+ q_space = efx->txq_entries - 1 - fill_level;
/* Map for DMA. Use pci_map_single rather than pci_map_page
* since this is more efficient on machines with sparse
@@ -244,14 +244,14 @@ netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
&tx_queue->read_count;
fill_level = (tx_queue->insert_count
- tx_queue->old_read_count);
- q_space = EFX_TXQ_MASK - 1 - fill_level;
+ q_space = efx->txq_entries - 1 - fill_level;
if (unlikely(q_space-- <= 0))
goto stop;
smp_mb();
--tx_queue->stopped;
}
- insert_ptr = tx_queue->insert_count & EFX_TXQ_MASK;
+ insert_ptr = tx_queue->insert_count & tx_queue->ptr_mask;
buffer = &tx_queue->buffer[insert_ptr];
efx_tsoh_free(tx_queue, buffer);
EFX_BUG_ON_PARANOID(buffer->tsoh);
@@ -320,7 +320,7 @@ netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
/* Work backwards until we hit the original insert pointer value */
while (tx_queue->insert_count != tx_queue->write_count) {
--tx_queue->insert_count;
- insert_ptr = tx_queue->insert_count & EFX_TXQ_MASK;
+ insert_ptr = tx_queue->insert_count & tx_queue->ptr_mask;
buffer = &tx_queue->buffer[insert_ptr];
efx_dequeue_buffer(tx_queue, buffer);
buffer->len = 0;
@@ -350,8 +350,8 @@ static void efx_dequeue_buffers(struct efx_tx_queue *tx_queue,
struct efx_nic *efx = tx_queue->efx;
unsigned int stop_index, read_ptr;
- stop_index = (index + 1) & EFX_TXQ_MASK;
- read_ptr = tx_queue->read_count & EFX_TXQ_MASK;
+ stop_index = (index + 1) & tx_queue->ptr_mask;
+ read_ptr = tx_queue->read_count & tx_queue->ptr_mask;
while (read_ptr != stop_index) {
struct efx_tx_buffer *buffer = &tx_queue->buffer[read_ptr];
@@ -368,7 +368,7 @@ static void efx_dequeue_buffers(struct efx_tx_queue *tx_queue,
buffer->len = 0;
++tx_queue->read_count;
- read_ptr = tx_queue->read_count & EFX_TXQ_MASK;
+ read_ptr = tx_queue->read_count & tx_queue->ptr_mask;
}
}
@@ -390,9 +390,9 @@ netdev_tx_t efx_hard_start_xmit(struct sk_buff *skb,
if (unlikely(efx->port_inhibited))
return NETDEV_TX_BUSY;
- tx_queue = &efx->tx_queue[EFX_TXQ_TYPES * skb_get_queue_mapping(skb)];
- if (likely(skb->ip_summed == CHECKSUM_PARTIAL))
- tx_queue += EFX_TXQ_TYPE_OFFLOAD;
+ tx_queue = efx_get_tx_queue(efx, skb_get_queue_mapping(skb),
+ skb->ip_summed == CHECKSUM_PARTIAL ?
+ EFX_TXQ_TYPE_OFFLOAD : 0);
return efx_enqueue_skb(tx_queue, skb);
}
@@ -402,7 +402,7 @@ void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index)
unsigned fill_level;
struct efx_nic *efx = tx_queue->efx;
- EFX_BUG_ON_PARANOID(index > EFX_TXQ_MASK);
+ EFX_BUG_ON_PARANOID(index > tx_queue->ptr_mask);
efx_dequeue_buffers(tx_queue, index);
@@ -412,7 +412,7 @@ void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index)
smp_mb();
if (unlikely(tx_queue->stopped) && likely(efx->port_enabled)) {
fill_level = tx_queue->insert_count - tx_queue->read_count;
- if (fill_level < EFX_TXQ_THRESHOLD) {
+ if (fill_level < EFX_TXQ_THRESHOLD(efx)) {
EFX_BUG_ON_PARANOID(!efx_dev_registered(efx));
/* Do this under netif_tx_lock(), to avoid racing
@@ -430,18 +430,24 @@ void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index)
int efx_probe_tx_queue(struct efx_tx_queue *tx_queue)
{
struct efx_nic *efx = tx_queue->efx;
- unsigned int txq_size;
+ unsigned int entries;
int i, rc;
- netif_dbg(efx, probe, efx->net_dev, "creating TX queue %d\n",
- tx_queue->queue);
+ /* Create the smallest power-of-two aligned ring */
+ entries = max(roundup_pow_of_two(efx->txq_entries), EFX_MIN_DMAQ_SIZE);
+ EFX_BUG_ON_PARANOID(entries > EFX_MAX_DMAQ_SIZE);
+ tx_queue->ptr_mask = entries - 1;
+
+ netif_dbg(efx, probe, efx->net_dev,
+ "creating TX queue %d size %#x mask %#x\n",
+ tx_queue->queue, efx->txq_entries, tx_queue->ptr_mask);
/* Allocate software ring */
- txq_size = EFX_TXQ_SIZE * sizeof(*tx_queue->buffer);
- tx_queue->buffer = kzalloc(txq_size, GFP_KERNEL);
+ tx_queue->buffer = kzalloc(entries * sizeof(*tx_queue->buffer),
+ GFP_KERNEL);
if (!tx_queue->buffer)
return -ENOMEM;
- for (i = 0; i <= EFX_TXQ_MASK; ++i)
+ for (i = 0; i <= tx_queue->ptr_mask; ++i)
tx_queue->buffer[i].continuation = true;
/* Allocate hardware ring */
@@ -481,7 +487,7 @@ void efx_release_tx_buffers(struct efx_tx_queue *tx_queue)
/* Free any buffers left in the ring */
while (tx_queue->read_count != tx_queue->write_count) {
- buffer = &tx_queue->buffer[tx_queue->read_count & EFX_TXQ_MASK];
+ buffer = &tx_queue->buffer[tx_queue->read_count & tx_queue->ptr_mask];
efx_dequeue_buffer(tx_queue, buffer);
buffer->continuation = true;
buffer->len = 0;
@@ -741,7 +747,7 @@ static int efx_tx_queue_insert(struct efx_tx_queue *tx_queue,
fill_level = tx_queue->insert_count - tx_queue->old_read_count;
/* -1 as there is no way to represent all descriptors used */
- q_space = EFX_TXQ_MASK - 1 - fill_level;
+ q_space = efx->txq_entries - 1 - fill_level;
while (1) {
if (unlikely(q_space-- <= 0)) {
@@ -757,7 +763,7 @@ static int efx_tx_queue_insert(struct efx_tx_queue *tx_queue,
*(volatile unsigned *)&tx_queue->read_count;
fill_level = (tx_queue->insert_count
- tx_queue->old_read_count);
- q_space = EFX_TXQ_MASK - 1 - fill_level;
+ q_space = efx->txq_entries - 1 - fill_level;
if (unlikely(q_space-- <= 0)) {
*final_buffer = NULL;
return 1;
@@ -766,13 +772,13 @@ static int efx_tx_queue_insert(struct efx_tx_queue *tx_queue,
--tx_queue->stopped;
}
- insert_ptr = tx_queue->insert_count & EFX_TXQ_MASK;
+ insert_ptr = tx_queue->insert_count & tx_queue->ptr_mask;
buffer = &tx_queue->buffer[insert_ptr];
++tx_queue->insert_count;
EFX_BUG_ON_PARANOID(tx_queue->insert_count -
- tx_queue->read_count >
- EFX_TXQ_MASK);
+ tx_queue->read_count >=
+ efx->txq_entries);
efx_tsoh_free(tx_queue, buffer);
EFX_BUG_ON_PARANOID(buffer->len);
@@ -813,7 +819,7 @@ static void efx_tso_put_header(struct efx_tx_queue *tx_queue,
{
struct efx_tx_buffer *buffer;
- buffer = &tx_queue->buffer[tx_queue->insert_count & EFX_TXQ_MASK];
+ buffer = &tx_queue->buffer[tx_queue->insert_count & tx_queue->ptr_mask];
efx_tsoh_free(tx_queue, buffer);
EFX_BUG_ON_PARANOID(buffer->len);
EFX_BUG_ON_PARANOID(buffer->unmap_len);
@@ -838,7 +844,7 @@ static void efx_enqueue_unwind(struct efx_tx_queue *tx_queue)
while (tx_queue->insert_count != tx_queue->write_count) {
--tx_queue->insert_count;
buffer = &tx_queue->buffer[tx_queue->insert_count &
- EFX_TXQ_MASK];
+ tx_queue->ptr_mask];
efx_tsoh_free(tx_queue, buffer);
EFX_BUG_ON_PARANOID(buffer->skb);
if (buffer->unmap_len) {
@@ -1168,7 +1174,7 @@ static void efx_fini_tso(struct efx_tx_queue *tx_queue)
unsigned i;
if (tx_queue->buffer) {
- for (i = 0; i <= EFX_TXQ_MASK; ++i)
+ for (i = 0; i <= tx_queue->ptr_mask; ++i)
efx_tsoh_free(tx_queue, &tx_queue->buffer[i]);
}
diff --git a/drivers/net/sfc/txc43128_phy.c b/drivers/net/sfc/txc43128_phy.c
new file mode 100644
index 000000000000..351794a79215
--- /dev/null
+++ b/drivers/net/sfc/txc43128_phy.c
@@ -0,0 +1,560 @@
+/****************************************************************************
+ * Driver for Solarflare Solarstorm network controllers and boards
+ * Copyright 2006-2010 Solarflare Communications Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation, incorporated herein by reference.
+ */
+
+/*
+ * Driver for Transwitch/Mysticom CX4 retimer
+ * see www.transwitch.com, part is TXC-43128
+ */
+
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include "efx.h"
+#include "mdio_10g.h"
+#include "phy.h"
+#include "nic.h"
+
+/* We expect these MMDs to be in the package */
+#define TXC_REQUIRED_DEVS (MDIO_DEVS_PCS | \
+ MDIO_DEVS_PMAPMD | \
+ MDIO_DEVS_PHYXS)
+
+#define TXC_LOOPBACKS ((1 << LOOPBACK_PCS) | \
+ (1 << LOOPBACK_PMAPMD) | \
+ (1 << LOOPBACK_PHYXS_WS))
+
+/**************************************************************************
+ *
+ * Compile-time config
+ *
+ **************************************************************************
+ */
+#define TXCNAME "TXC43128"
+/* Total length of time we'll wait for the PHY to come out of reset (ms) */
+#define TXC_MAX_RESET_TIME 500
+/* Interval between checks (ms) */
+#define TXC_RESET_WAIT 10
+/* How long to run BIST (us) */
+#define TXC_BIST_DURATION 50
+
+/**************************************************************************
+ *
+ * Register definitions
+ *
+ **************************************************************************
+ */
+
+/* Command register */
+#define TXC_GLRGS_GLCMD 0xc004
+/* Useful bits in command register */
+/* Lane power-down */
+#define TXC_GLCMD_L01PD_LBN 5
+#define TXC_GLCMD_L23PD_LBN 6
+/* Limited SW reset: preserves configuration but
+ * initiates a logic reset. Self-clearing */
+#define TXC_GLCMD_LMTSWRST_LBN 14
+
+/* Signal Quality Control */
+#define TXC_GLRGS_GSGQLCTL 0xc01a
+/* Enable bit */
+#define TXC_GSGQLCT_SGQLEN_LBN 15
+/* Lane selection */
+#define TXC_GSGQLCT_LNSL_LBN 13
+#define TXC_GSGQLCT_LNSL_WIDTH 2
+
+/* Analog TX control */
+#define TXC_ALRGS_ATXCTL 0xc040
+/* Lane power-down */
+#define TXC_ATXCTL_TXPD3_LBN 15
+#define TXC_ATXCTL_TXPD2_LBN 14
+#define TXC_ATXCTL_TXPD1_LBN 13
+#define TXC_ATXCTL_TXPD0_LBN 12
+
+/* Amplitude on lanes 0, 1 */
+#define TXC_ALRGS_ATXAMP0 0xc041
+/* Amplitude on lanes 2, 3 */
+#define TXC_ALRGS_ATXAMP1 0xc042
+/* Bit position of value for lane 0 (or 2) */
+#define TXC_ATXAMP_LANE02_LBN 3
+/* Bit position of value for lane 1 (or 3) */
+#define TXC_ATXAMP_LANE13_LBN 11
+
+#define TXC_ATXAMP_1280_mV 0
+#define TXC_ATXAMP_1200_mV 8
+#define TXC_ATXAMP_1120_mV 12
+#define TXC_ATXAMP_1060_mV 14
+#define TXC_ATXAMP_0820_mV 25
+#define TXC_ATXAMP_0720_mV 26
+#define TXC_ATXAMP_0580_mV 27
+#define TXC_ATXAMP_0440_mV 28
+
+#define TXC_ATXAMP_0820_BOTH \
+ ((TXC_ATXAMP_0820_mV << TXC_ATXAMP_LANE02_LBN) \
+ | (TXC_ATXAMP_0820_mV << TXC_ATXAMP_LANE13_LBN))
+
+#define TXC_ATXAMP_DEFAULT 0x6060 /* From databook */
+
+/* Preemphasis on lanes 0, 1 */
+#define TXC_ALRGS_ATXPRE0 0xc043
+/* Preemphasis on lanes 2, 3 */
+#define TXC_ALRGS_ATXPRE1 0xc044
+
+#define TXC_ATXPRE_NONE 0
+#define TXC_ATXPRE_DEFAULT 0x1010 /* From databook */
+
+#define TXC_ALRGS_ARXCTL 0xc045
+/* Lane power-down */
+#define TXC_ARXCTL_RXPD3_LBN 15
+#define TXC_ARXCTL_RXPD2_LBN 14
+#define TXC_ARXCTL_RXPD1_LBN 13
+#define TXC_ARXCTL_RXPD0_LBN 12
+
+/* Main control */
+#define TXC_MRGS_CTL 0xc340
+/* Bits in main control */
+#define TXC_MCTL_RESET_LBN 15 /* Self clear */
+#define TXC_MCTL_TXLED_LBN 14 /* 1 to show align status */
+#define TXC_MCTL_RXLED_LBN 13 /* 1 to show align status */
+
+/* GPIO output */
+#define TXC_GPIO_OUTPUT 0xc346
+#define TXC_GPIO_DIR 0xc348
+
+/* Vendor-specific BIST registers */
+#define TXC_BIST_CTL 0xc280
+#define TXC_BIST_TXFRMCNT 0xc281
+#define TXC_BIST_RX0FRMCNT 0xc282
+#define TXC_BIST_RX1FRMCNT 0xc283
+#define TXC_BIST_RX2FRMCNT 0xc284
+#define TXC_BIST_RX3FRMCNT 0xc285
+#define TXC_BIST_RX0ERRCNT 0xc286
+#define TXC_BIST_RX1ERRCNT 0xc287
+#define TXC_BIST_RX2ERRCNT 0xc288
+#define TXC_BIST_RX3ERRCNT 0xc289
+
+/* BIST type (controls bit patter in test) */
+#define TXC_BIST_CTRL_TYPE_LBN 10
+#define TXC_BIST_CTRL_TYPE_TSD 0 /* TranSwitch Deterministic */
+#define TXC_BIST_CTRL_TYPE_CRP 1 /* CRPAT standard */
+#define TXC_BIST_CTRL_TYPE_CJP 2 /* CJPAT standard */
+#define TXC_BIST_CTRL_TYPE_TSR 3 /* TranSwitch pseudo-random */
+/* Set this to 1 for 10 bit and 0 for 8 bit */
+#define TXC_BIST_CTRL_B10EN_LBN 12
+/* Enable BIST (write 0 to disable) */
+#define TXC_BIST_CTRL_ENAB_LBN 13
+/* Stop BIST (self-clears when stop complete) */
+#define TXC_BIST_CTRL_STOP_LBN 14
+/* Start BIST (cleared by writing 1 to STOP) */
+#define TXC_BIST_CTRL_STRT_LBN 15
+
+/* Mt. Diablo test configuration */
+#define TXC_MTDIABLO_CTRL 0xc34f
+#define TXC_MTDIABLO_CTRL_PMA_LOOP_LBN 10
+
+struct txc43128_data {
+ unsigned long bug10934_timer;
+ enum efx_phy_mode phy_mode;
+ enum efx_loopback_mode loopback_mode;
+};
+
+/* The PHY sometimes needs a reset to bring the link back up. So long as
+ * it reports link down, we reset it every 5 seconds.
+ */
+#define BUG10934_RESET_INTERVAL (5 * HZ)
+
+/* Perform a reset that doesn't clear configuration changes */
+static void txc_reset_logic(struct efx_nic *efx);
+
+/* Set the output value of a gpio */
+void falcon_txc_set_gpio_val(struct efx_nic *efx, int pin, int on)
+{
+ efx_mdio_set_flag(efx, MDIO_MMD_PHYXS, TXC_GPIO_OUTPUT, 1 << pin, on);
+}
+
+/* Set up the GPIO direction register */
+void falcon_txc_set_gpio_dir(struct efx_nic *efx, int pin, int dir)
+{
+ efx_mdio_set_flag(efx, MDIO_MMD_PHYXS, TXC_GPIO_DIR, 1 << pin, dir);
+}
+
+/* Reset the PMA/PMD MMD. The documentation is explicit that this does a
+ * global reset (it's less clear what reset of other MMDs does).*/
+static int txc_reset_phy(struct efx_nic *efx)
+{
+ int rc = efx_mdio_reset_mmd(efx, MDIO_MMD_PMAPMD,
+ TXC_MAX_RESET_TIME / TXC_RESET_WAIT,
+ TXC_RESET_WAIT);
+ if (rc < 0)
+ goto fail;
+
+ /* Check that all the MMDs we expect are present and responding. */
+ rc = efx_mdio_check_mmds(efx, TXC_REQUIRED_DEVS, 0);
+ if (rc < 0)
+ goto fail;
+
+ return 0;
+
+fail:
+ netif_err(efx, hw, efx->net_dev, TXCNAME ": reset timed out!\n");
+ return rc;
+}
+
+/* Run a single BIST on one MMD */
+static int txc_bist_one(struct efx_nic *efx, int mmd, int test)
+{
+ int ctrl, bctl;
+ int lane;
+ int rc = 0;
+
+ /* Set PMA to test into loopback using Mt Diablo reg as per app note */
+ ctrl = efx_mdio_read(efx, MDIO_MMD_PCS, TXC_MTDIABLO_CTRL);
+ ctrl |= (1 << TXC_MTDIABLO_CTRL_PMA_LOOP_LBN);
+ efx_mdio_write(efx, MDIO_MMD_PCS, TXC_MTDIABLO_CTRL, ctrl);
+
+ /* The BIST app. note lists these as 3 distinct steps. */
+ /* Set the BIST type */
+ bctl = (test << TXC_BIST_CTRL_TYPE_LBN);
+ efx_mdio_write(efx, mmd, TXC_BIST_CTL, bctl);
+
+ /* Set the BSTEN bit in the BIST Control register to enable */
+ bctl |= (1 << TXC_BIST_CTRL_ENAB_LBN);
+ efx_mdio_write(efx, mmd, TXC_BIST_CTL, bctl);
+
+ /* Set the BSTRT bit in the BIST Control register */
+ efx_mdio_write(efx, mmd, TXC_BIST_CTL,
+ bctl | (1 << TXC_BIST_CTRL_STRT_LBN));
+
+ /* Wait. */
+ udelay(TXC_BIST_DURATION);
+
+ /* Set the BSTOP bit in the BIST Control register */
+ bctl |= (1 << TXC_BIST_CTRL_STOP_LBN);
+ efx_mdio_write(efx, mmd, TXC_BIST_CTL, bctl);
+
+ /* The STOP bit should go off when things have stopped */
+ while (bctl & (1 << TXC_BIST_CTRL_STOP_LBN))
+ bctl = efx_mdio_read(efx, mmd, TXC_BIST_CTL);
+
+ /* Check all the error counts are 0 and all the frame counts are
+ non-zero */
+ for (lane = 0; lane < 4; lane++) {
+ int count = efx_mdio_read(efx, mmd, TXC_BIST_RX0ERRCNT + lane);
+ if (count != 0) {
+ netif_err(efx, hw, efx->net_dev, TXCNAME": BIST error. "
+ "Lane %d had %d errs\n", lane, count);
+ rc = -EIO;
+ }
+ count = efx_mdio_read(efx, mmd, TXC_BIST_RX0FRMCNT + lane);
+ if (count == 0) {
+ netif_err(efx, hw, efx->net_dev, TXCNAME": BIST error. "
+ "Lane %d got 0 frames\n", lane);
+ rc = -EIO;
+ }
+ }
+
+ if (rc == 0)
+ netif_info(efx, hw, efx->net_dev, TXCNAME": BIST pass\n");
+
+ /* Disable BIST */
+ efx_mdio_write(efx, mmd, TXC_BIST_CTL, 0);
+
+ /* Turn off loopback */
+ ctrl &= ~(1 << TXC_MTDIABLO_CTRL_PMA_LOOP_LBN);
+ efx_mdio_write(efx, MDIO_MMD_PCS, TXC_MTDIABLO_CTRL, ctrl);
+
+ return rc;
+}
+
+static int txc_bist(struct efx_nic *efx)
+{
+ return txc_bist_one(efx, MDIO_MMD_PCS, TXC_BIST_CTRL_TYPE_TSD);
+}
+
+/* Push the non-configurable defaults into the PHY. This must be
+ * done after every full reset */
+static void txc_apply_defaults(struct efx_nic *efx)
+{
+ int mctrl;
+
+ /* Turn amplitude down and preemphasis off on the host side
+ * (PHY<->MAC) as this is believed less likely to upset Falcon
+ * and no adverse effects have been noted. It probably also
+ * saves a picowatt or two */
+
+ /* Turn off preemphasis */
+ efx_mdio_write(efx, MDIO_MMD_PHYXS, TXC_ALRGS_ATXPRE0, TXC_ATXPRE_NONE);
+ efx_mdio_write(efx, MDIO_MMD_PHYXS, TXC_ALRGS_ATXPRE1, TXC_ATXPRE_NONE);
+
+ /* Turn down the amplitude */
+ efx_mdio_write(efx, MDIO_MMD_PHYXS,
+ TXC_ALRGS_ATXAMP0, TXC_ATXAMP_0820_BOTH);
+ efx_mdio_write(efx, MDIO_MMD_PHYXS,
+ TXC_ALRGS_ATXAMP1, TXC_ATXAMP_0820_BOTH);
+
+ /* Set the line side amplitude and preemphasis to the databook
+ * defaults as an erratum causes them to be 0 on at least some
+ * PHY rev.s */
+ efx_mdio_write(efx, MDIO_MMD_PMAPMD,
+ TXC_ALRGS_ATXPRE0, TXC_ATXPRE_DEFAULT);
+ efx_mdio_write(efx, MDIO_MMD_PMAPMD,
+ TXC_ALRGS_ATXPRE1, TXC_ATXPRE_DEFAULT);
+ efx_mdio_write(efx, MDIO_MMD_PMAPMD,
+ TXC_ALRGS_ATXAMP0, TXC_ATXAMP_DEFAULT);
+ efx_mdio_write(efx, MDIO_MMD_PMAPMD,
+ TXC_ALRGS_ATXAMP1, TXC_ATXAMP_DEFAULT);
+
+ /* Set up the LEDs */
+ mctrl = efx_mdio_read(efx, MDIO_MMD_PHYXS, TXC_MRGS_CTL);
+
+ /* Set the Green and Red LEDs to their default modes */
+ mctrl &= ~((1 << TXC_MCTL_TXLED_LBN) | (1 << TXC_MCTL_RXLED_LBN));
+ efx_mdio_write(efx, MDIO_MMD_PHYXS, TXC_MRGS_CTL, mctrl);
+
+ /* Databook recommends doing this after configuration changes */
+ txc_reset_logic(efx);
+
+ falcon_board(efx)->type->init_phy(efx);
+}
+
+static int txc43128_phy_probe(struct efx_nic *efx)
+{
+ struct txc43128_data *phy_data;
+
+ /* Allocate phy private storage */
+ phy_data = kzalloc(sizeof(*phy_data), GFP_KERNEL);
+ if (!phy_data)
+ return -ENOMEM;
+ efx->phy_data = phy_data;
+ phy_data->phy_mode = efx->phy_mode;
+
+ efx->mdio.mmds = TXC_REQUIRED_DEVS;
+ efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22;
+
+ efx->loopback_modes = TXC_LOOPBACKS | FALCON_XMAC_LOOPBACKS;
+
+ return 0;
+}
+
+/* Initialisation entry point for this PHY driver */
+static int txc43128_phy_init(struct efx_nic *efx)
+{
+ int rc;
+
+ rc = txc_reset_phy(efx);
+ if (rc < 0)
+ return rc;
+
+ rc = txc_bist(efx);
+ if (rc < 0)
+ return rc;
+
+ txc_apply_defaults(efx);
+
+ return 0;
+}
+
+/* Set the lane power down state in the global registers */
+static void txc_glrgs_lane_power(struct efx_nic *efx, int mmd)
+{
+ int pd = (1 << TXC_GLCMD_L01PD_LBN) | (1 << TXC_GLCMD_L23PD_LBN);
+ int ctl = efx_mdio_read(efx, mmd, TXC_GLRGS_GLCMD);
+
+ if (!(efx->phy_mode & PHY_MODE_LOW_POWER))
+ ctl &= ~pd;
+ else
+ ctl |= pd;
+
+ efx_mdio_write(efx, mmd, TXC_GLRGS_GLCMD, ctl);
+}
+
+/* Set the lane power down state in the analog control registers */
+static void txc_analog_lane_power(struct efx_nic *efx, int mmd)
+{
+ int txpd = (1 << TXC_ATXCTL_TXPD3_LBN) | (1 << TXC_ATXCTL_TXPD2_LBN)
+ | (1 << TXC_ATXCTL_TXPD1_LBN) | (1 << TXC_ATXCTL_TXPD0_LBN);
+ int rxpd = (1 << TXC_ARXCTL_RXPD3_LBN) | (1 << TXC_ARXCTL_RXPD2_LBN)
+ | (1 << TXC_ARXCTL_RXPD1_LBN) | (1 << TXC_ARXCTL_RXPD0_LBN);
+ int txctl = efx_mdio_read(efx, mmd, TXC_ALRGS_ATXCTL);
+ int rxctl = efx_mdio_read(efx, mmd, TXC_ALRGS_ARXCTL);
+
+ if (!(efx->phy_mode & PHY_MODE_LOW_POWER)) {
+ txctl &= ~txpd;
+ rxctl &= ~rxpd;
+ } else {
+ txctl |= txpd;
+ rxctl |= rxpd;
+ }
+
+ efx_mdio_write(efx, mmd, TXC_ALRGS_ATXCTL, txctl);
+ efx_mdio_write(efx, mmd, TXC_ALRGS_ARXCTL, rxctl);
+}
+
+static void txc_set_power(struct efx_nic *efx)
+{
+ /* According to the data book, all the MMDs can do low power */
+ efx_mdio_set_mmds_lpower(efx,
+ !!(efx->phy_mode & PHY_MODE_LOW_POWER),
+ TXC_REQUIRED_DEVS);
+
+ /* Global register bank is in PCS, PHY XS. These control the host
+ * side and line side settings respectively. */
+ txc_glrgs_lane_power(efx, MDIO_MMD_PCS);
+ txc_glrgs_lane_power(efx, MDIO_MMD_PHYXS);
+
+ /* Analog register bank in PMA/PMD, PHY XS */
+ txc_analog_lane_power(efx, MDIO_MMD_PMAPMD);
+ txc_analog_lane_power(efx, MDIO_MMD_PHYXS);
+}
+
+static void txc_reset_logic_mmd(struct efx_nic *efx, int mmd)
+{
+ int val = efx_mdio_read(efx, mmd, TXC_GLRGS_GLCMD);
+ int tries = 50;
+
+ val |= (1 << TXC_GLCMD_LMTSWRST_LBN);
+ efx_mdio_write(efx, mmd, TXC_GLRGS_GLCMD, val);
+ while (tries--) {
+ val = efx_mdio_read(efx, mmd, TXC_GLRGS_GLCMD);
+ if (!(val & (1 << TXC_GLCMD_LMTSWRST_LBN)))
+ break;
+ udelay(1);
+ }
+ if (!tries)
+ netif_info(efx, hw, efx->net_dev,
+ TXCNAME " Logic reset timed out!\n");
+}
+
+/* Perform a logic reset. This preserves the configuration registers
+ * and is needed for some configuration changes to take effect */
+static void txc_reset_logic(struct efx_nic *efx)
+{
+ /* The data sheet claims we can do the logic reset on either the
+ * PCS or the PHYXS and the result is a reset of both host- and
+ * line-side logic. */
+ txc_reset_logic_mmd(efx, MDIO_MMD_PCS);
+}
+
+static bool txc43128_phy_read_link(struct efx_nic *efx)
+{
+ return efx_mdio_links_ok(efx, TXC_REQUIRED_DEVS);
+}
+
+static int txc43128_phy_reconfigure(struct efx_nic *efx)
+{
+ struct txc43128_data *phy_data = efx->phy_data;
+ enum efx_phy_mode mode_change = efx->phy_mode ^ phy_data->phy_mode;
+ bool loop_change = LOOPBACK_CHANGED(phy_data, efx, TXC_LOOPBACKS);
+
+ if (efx->phy_mode & mode_change & PHY_MODE_TX_DISABLED) {
+ txc_reset_phy(efx);
+ txc_apply_defaults(efx);
+ falcon_reset_xaui(efx);
+ mode_change &= ~PHY_MODE_TX_DISABLED;
+ }
+
+ efx_mdio_transmit_disable(efx);
+ efx_mdio_phy_reconfigure(efx);
+ if (mode_change & PHY_MODE_LOW_POWER)
+ txc_set_power(efx);
+
+ /* The data sheet claims this is required after every reconfiguration
+ * (note at end of 7.1), but we mustn't do it when nothing changes as
+ * it glitches the link, and reconfigure gets called on link change,
+ * so we get an IRQ storm on link up. */
+ if (loop_change || mode_change)
+ txc_reset_logic(efx);
+
+ phy_data->phy_mode = efx->phy_mode;
+ phy_data->loopback_mode = efx->loopback_mode;
+
+ return 0;
+}
+
+static void txc43128_phy_fini(struct efx_nic *efx)
+{
+ /* Disable link events */
+ efx_mdio_write(efx, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_CTRL, 0);
+}
+
+static void txc43128_phy_remove(struct efx_nic *efx)
+{
+ kfree(efx->phy_data);
+ efx->phy_data = NULL;
+}
+
+/* Periodic callback: this exists mainly to poll link status as we
+ * don't use LASI interrupts */
+static bool txc43128_phy_poll(struct efx_nic *efx)
+{
+ struct txc43128_data *data = efx->phy_data;
+ bool was_up = efx->link_state.up;
+
+ efx->link_state.up = txc43128_phy_read_link(efx);
+ efx->link_state.speed = 10000;
+ efx->link_state.fd = true;
+ efx->link_state.fc = efx->wanted_fc;
+
+ if (efx->link_state.up || (efx->loopback_mode != LOOPBACK_NONE)) {
+ data->bug10934_timer = jiffies;
+ } else {
+ if (time_after_eq(jiffies, (data->bug10934_timer +
+ BUG10934_RESET_INTERVAL))) {
+ data->bug10934_timer = jiffies;
+ txc_reset_logic(efx);
+ }
+ }
+
+ return efx->link_state.up != was_up;
+}
+
+static const char *txc43128_test_names[] = {
+ "bist"
+};
+
+static const char *txc43128_test_name(struct efx_nic *efx, unsigned int index)
+{
+ if (index < ARRAY_SIZE(txc43128_test_names))
+ return txc43128_test_names[index];
+ return NULL;
+}
+
+static int txc43128_run_tests(struct efx_nic *efx, int *results, unsigned flags)
+{
+ int rc;
+
+ if (!(flags & ETH_TEST_FL_OFFLINE))
+ return 0;
+
+ rc = txc_reset_phy(efx);
+ if (rc < 0)
+ return rc;
+
+ rc = txc_bist(efx);
+ txc_apply_defaults(efx);
+ results[0] = rc ? -1 : 1;
+ return rc;
+}
+
+static void txc43128_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
+{
+ mdio45_ethtool_gset(&efx->mdio, ecmd);
+}
+
+struct efx_phy_operations falcon_txc_phy_ops = {
+ .probe = txc43128_phy_probe,
+ .init = txc43128_phy_init,
+ .reconfigure = txc43128_phy_reconfigure,
+ .poll = txc43128_phy_poll,
+ .fini = txc43128_phy_fini,
+ .remove = txc43128_phy_remove,
+ .get_settings = txc43128_get_settings,
+ .set_settings = efx_mdio_set_settings,
+ .test_alive = efx_mdio_test_alive,
+ .run_tests = txc43128_run_tests,
+ .test_name = txc43128_test_name,
+};
diff --git a/drivers/net/sfc/workarounds.h b/drivers/net/sfc/workarounds.h
index 782e45a613d6..e0d63083c3a8 100644
--- a/drivers/net/sfc/workarounds.h
+++ b/drivers/net/sfc/workarounds.h
@@ -19,9 +19,7 @@
#define EFX_WORKAROUND_FALCON_A(efx) (efx_nic_rev(efx) <= EFX_REV_FALCON_A1)
#define EFX_WORKAROUND_FALCON_AB(efx) (efx_nic_rev(efx) <= EFX_REV_FALCON_B0)
#define EFX_WORKAROUND_SIENA(efx) (efx_nic_rev(efx) == EFX_REV_SIENA_A0)
-#define EFX_WORKAROUND_10G(efx) EFX_IS10G(efx)
-#define EFX_WORKAROUND_SFT9001(efx) ((efx)->phy_type == PHY_TYPE_SFT9001A || \
- (efx)->phy_type == PHY_TYPE_SFT9001B)
+#define EFX_WORKAROUND_10G(efx) 1
/* XAUI resets if link not detected */
#define EFX_WORKAROUND_5147 EFX_WORKAROUND_ALWAYS
@@ -58,9 +56,4 @@
/* Leak overlength packets rather than free */
#define EFX_WORKAROUND_8071 EFX_WORKAROUND_FALCON_A
-/* Need to send XNP pages for 100BaseT */
-#define EFX_WORKAROUND_13204 EFX_WORKAROUND_SFT9001
-/* Don't restart AN in near-side loopback */
-#define EFX_WORKAROUND_15195 EFX_WORKAROUND_SFT9001
-
#endif /* EFX_WORKAROUNDS_H */
diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c
index 79fd02bc69fd..50259dfec583 100644
--- a/drivers/net/sh_eth.c
+++ b/drivers/net/sh_eth.c
@@ -798,7 +798,7 @@ static int sh_eth_rx(struct net_device *ndev)
skb->dev = ndev;
sh_eth_set_receive_align(skb);
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
rxdesc->addr = virt_to_phys(PTR_ALIGN(skb->data, 4));
}
if (entry >= RX_RING_SIZE - 1)
@@ -1031,7 +1031,7 @@ static int sh_eth_phy_init(struct net_device *ndev)
mdp->duplex = -1;
/* Try connect to PHY */
- phydev = phy_connect(ndev, phy_id, &sh_eth_adjust_link,
+ phydev = phy_connect(ndev, phy_id, sh_eth_adjust_link,
0, PHY_INTERFACE_MODE_MII);
if (IS_ERR(phydev)) {
dev_err(&ndev->dev, "phy_connect failed\n");
diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c
index bbbded76ff14..581836867098 100644
--- a/drivers/net/sis900.c
+++ b/drivers/net/sis900.c
@@ -832,7 +832,7 @@ static u16 __devinit read_eeprom(long ioaddr, int location)
outl(0, ee_addr);
eeprom_delay();
- return (retval);
+ return retval;
}
/* Read and write the MII management registers using software-generated
@@ -1042,7 +1042,7 @@ sis900_open(struct net_device *net_dev)
init_timer(&sis_priv->timer);
sis_priv->timer.expires = jiffies + HZ;
sis_priv->timer.data = (unsigned long)net_dev;
- sis_priv->timer.function = &sis900_timer;
+ sis_priv->timer.function = sis900_timer;
add_timer(&sis_priv->timer);
return 0;
@@ -2247,9 +2247,9 @@ static inline u16 sis900_mcast_bitnr(u8 *addr, u8 revision)
/* leave 8 or 7 most siginifant bits */
if ((revision >= SIS635A_900_REV) || (revision == SIS900B_900_REV))
- return ((int)(crc >> 24));
+ return (int)(crc >> 24);
else
- return ((int)(crc >> 25));
+ return (int)(crc >> 25);
}
/**
diff --git a/drivers/net/skfp/cfm.c b/drivers/net/skfp/cfm.c
index 5310d39b5737..e395ace3120b 100644
--- a/drivers/net/skfp/cfm.c
+++ b/drivers/net/skfp/cfm.c
@@ -542,8 +542,8 @@ static void cfm_fsm(struct s_smc *smc, int cmd)
*/
int cfm_get_mac_input(struct s_smc *smc)
{
- return((smc->mib.fddiSMTCF_State == SC10_C_WRAP_B ||
- smc->mib.fddiSMTCF_State == SC5_THRU_B) ? PB : PA) ;
+ return (smc->mib.fddiSMTCF_State == SC10_C_WRAP_B ||
+ smc->mib.fddiSMTCF_State == SC5_THRU_B) ? PB : PA;
}
/*
@@ -553,8 +553,8 @@ int cfm_get_mac_input(struct s_smc *smc)
*/
int cfm_get_mac_output(struct s_smc *smc)
{
- return((smc->mib.fddiSMTCF_State == SC10_C_WRAP_B ||
- smc->mib.fddiSMTCF_State == SC4_THRU_A) ? PB : PA) ;
+ return (smc->mib.fddiSMTCF_State == SC10_C_WRAP_B ||
+ smc->mib.fddiSMTCF_State == SC4_THRU_A) ? PB : PA;
}
static char path_iso[] = {
@@ -623,5 +623,5 @@ int cem_build_path(struct s_smc *smc, char *to, int path_index)
LINT_USE(path_index);
- return(len) ;
+ return len;
}
diff --git a/drivers/net/skfp/drvfbi.c b/drivers/net/skfp/drvfbi.c
index c77cc14b3227..07da97c303d6 100644
--- a/drivers/net/skfp/drvfbi.c
+++ b/drivers/net/skfp/drvfbi.c
@@ -267,7 +267,7 @@ void timer_irq(struct s_smc *smc)
int pcm_get_s_port(struct s_smc *smc)
{
SK_UNUSED(smc) ;
- return(PS) ;
+ return PS;
}
/*
@@ -366,7 +366,7 @@ void sm_pm_bypass_req(struct s_smc *smc, int mode)
*/
int sm_pm_bypass_present(struct s_smc *smc)
{
- return( (inp(ADDR(B0_DAS)) & DAS_BYP_ST) ? TRUE: FALSE) ;
+ return (inp(ADDR(B0_DAS)) & DAS_BYP_ST) ? TRUE : FALSE;
}
void plc_clear_irq(struct s_smc *smc, int p)
@@ -483,9 +483,9 @@ static int is_equal_num(char comp1[], char comp2[], int num)
for (i = 0 ; i < num ; i++) {
if (comp1[i] != comp2[i])
- return (0) ;
+ return 0;
}
- return (1) ;
+ return 1;
} /* is_equal_num */
@@ -522,18 +522,18 @@ int set_oi_id_def(struct s_smc *smc)
i++ ;
break ; /* entry ok */
default:
- return (1) ; /* invalid oi_status */
+ return 1; /* invalid oi_status */
}
}
if (i == 0)
- return (2) ;
+ return 2;
if (!act_entries)
- return (3) ;
+ return 3;
/* ok, we have a valid OEM data base with an active entry */
smc->hw.oem_id = (struct s_oem_ids *) &oem_ids[sel_id] ;
- return (0) ;
+ return 0;
}
#endif /* MULT_OEM */
diff --git a/drivers/net/skfp/ess.c b/drivers/net/skfp/ess.c
index e8387d25f24a..8639a0884f5c 100644
--- a/drivers/net/skfp/ess.c
+++ b/drivers/net/skfp/ess.c
@@ -135,7 +135,7 @@ int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm,
*/
if (!(p = (void *) sm_to_para(smc,sm,SMT_P0015))) {
DB_ESS("ESS: RAF frame error, parameter type not found\n",0,0) ;
- return(fs) ;
+ return fs;
}
msg_res_type = ((struct smt_p_0015 *)p)->res_type ;
@@ -147,7 +147,7 @@ int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm,
* error in frame: para ESS command was not found
*/
DB_ESS("ESS: RAF frame error, parameter command not found\n",0,0);
- return(fs) ;
+ return fs;
}
DB_ESSN(2,"fc %x ft %x\n",sm->smt_class,sm->smt_type) ;
@@ -175,12 +175,12 @@ int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm,
* local and no static allocation is used
*/
if (!local || smc->mib.fddiESSPayload)
- return(fs) ;
+ return fs;
p = (void *) sm_to_para(smc,sm,SMT_P0019) ;
for (i = 0; i < 5; i++) {
if (((struct smt_p_0019 *)p)->alloc_addr.a[i]) {
- return(fs) ;
+ return fs;
}
}
@@ -199,10 +199,10 @@ int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm,
sm->smt_dest = smt_sba_da ;
if (smc->ess.local_sba_active)
- return(fs | I_INDICATOR) ;
+ return fs | I_INDICATOR;
if (!(db = smt_get_mbuf(smc)))
- return(fs) ;
+ return fs;
db->sm_len = mb->sm_len ;
db->sm_off = mb->sm_off ;
@@ -212,7 +212,7 @@ int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm,
(struct smt_header *)(db->sm_data+db->sm_off),
"RAF") ;
smt_send_frame(smc,db,FC_SMT_INFO,0) ;
- return(fs) ;
+ return fs;
}
/*
@@ -221,7 +221,7 @@ int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm,
*/
if (smt_check_para(smc,sm,plist_raf_alc_res)) {
DB_ESS("ESS: RAF with para problem, ignoring\n",0,0) ;
- return(fs) ;
+ return fs;
}
/*
@@ -242,7 +242,7 @@ int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm,
(sm->smt_tid != smc->ess.alloc_trans_id)) {
DB_ESS("ESS: Allocation Responce not accepted\n",0,0) ;
- return(fs) ;
+ return fs;
}
/*
@@ -268,7 +268,7 @@ int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm,
*/
(void)process_bw_alloc(smc,(long)payload,(long)overhead) ;
- return(fs) ;
+ return fs;
/* end of Process Allocation Request */
/*
@@ -280,7 +280,7 @@ int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm,
*/
if (sm->smt_type != SMT_REQUEST) {
DB_ESS("ESS: Do not process Change Responses\n",0,0) ;
- return(fs) ;
+ return fs;
}
/*
@@ -288,7 +288,7 @@ int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm,
*/
if (smt_check_para(smc,sm,plist_raf_chg_req)) {
DB_ESS("ESS: RAF with para problem, ignoring\n",0,0) ;
- return(fs) ;
+ return fs;
}
/*
@@ -300,7 +300,7 @@ int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm,
if ((((struct smt_p_320b *)sm_to_para(smc,sm,SMT_P320B))->path_index
!= PRIMARY_RING) || (msg_res_type != SYNC_BW)) {
DB_ESS("ESS: RAF frame with para problem, ignoring\n",0,0) ;
- return(fs) ;
+ return fs;
}
/*
@@ -319,14 +319,14 @@ int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm,
* process the bandwidth allocation
*/
if(!process_bw_alloc(smc,(long)payload,(long)overhead))
- return(fs) ;
+ return fs;
/*
* send an RAF Change Reply
*/
ess_send_response(smc,sm,CHANGE_ALLOCATION) ;
- return(fs) ;
+ return fs;
/* end of Process Change Request */
/*
@@ -338,7 +338,7 @@ int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm,
*/
if (sm->smt_type != SMT_REQUEST) {
DB_ESS("ESS: Do not process a Report Reply\n",0,0) ;
- return(fs) ;
+ return fs;
}
DB_ESSN(2,"ESS: Report Request from %s\n",
@@ -349,7 +349,7 @@ int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm,
*/
if (msg_res_type != SYNC_BW) {
DB_ESS("ESS: ignoring RAF with para problem\n",0,0) ;
- return(fs) ;
+ return fs;
}
/*
@@ -357,7 +357,7 @@ int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm,
*/
ess_send_response(smc,sm,REPORT_ALLOCATION) ;
- return(fs) ;
+ return fs;
/* end of Process Report Request */
default:
@@ -368,7 +368,7 @@ int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm,
break ;
}
- return(fs) ;
+ return fs;
}
/*
@@ -418,17 +418,17 @@ static int process_bw_alloc(struct s_smc *smc, long int payload, long int overhe
*/
/* if (smt_set_obj(smc,SMT_P320F,payload,S_SET)) {
DB_ESS("ESS: SMT does not accept the payload value\n",0,0) ;
- return(FALSE) ;
+ return FALSE;
}
if (smt_set_obj(smc,SMT_P3210,overhead,S_SET)) {
DB_ESS("ESS: SMT does not accept the overhead value\n",0,0) ;
- return(FALSE) ;
+ return FALSE;
} */
/* premliminary */
if (payload > MAX_PAYLOAD || overhead > 5000) {
DB_ESS("ESS: payload / overhead not accepted\n",0,0) ;
- return(FALSE) ;
+ return FALSE;
}
/*
@@ -468,7 +468,7 @@ static int process_bw_alloc(struct s_smc *smc, long int payload, long int overhe
ess_config_fifo(smc) ;
set_formac_tsync(smc,smc->ess.sync_bw) ;
- return(TRUE) ;
+ return TRUE;
}
static void ess_send_response(struct s_smc *smc, struct smt_header *sm,
diff --git a/drivers/net/skfp/fplustm.c b/drivers/net/skfp/fplustm.c
index 9d8d1ac48176..ca4e7bb6a5a8 100644
--- a/drivers/net/skfp/fplustm.c
+++ b/drivers/net/skfp/fplustm.c
@@ -112,8 +112,8 @@ static u_long mac_get_tneg(struct s_smc *smc)
u_long tneg ;
tneg = (u_long)((long)inpw(FM_A(FM_TNEG))<<5) ;
- return((u_long)((tneg + ((inpw(FM_A(FM_TMRS))>>10)&0x1f)) |
- 0xffe00000L)) ;
+ return (u_long)((tneg + ((inpw(FM_A(FM_TMRS))>>10)&0x1f)) |
+ 0xffe00000L) ;
}
void mac_update_counter(struct s_smc *smc)
@@ -163,7 +163,7 @@ static u_long read_mdr(struct s_smc *smc, unsigned int addr)
/* is used */
p = (u_long)inpw(FM_A(FM_MDRU))<<16 ;
p += (u_long)inpw(FM_A(FM_MDRL)) ;
- return(p) ;
+ return p;
}
#endif
@@ -887,7 +887,7 @@ int init_fplus(struct s_smc *smc)
/* make sure all PCI settings are correct */
mac_do_pci_fix(smc) ;
- return(init_mac(smc,1)) ;
+ return init_mac(smc, 1);
/* enable_formac(smc) ; */
}
@@ -989,7 +989,7 @@ static int init_mac(struct s_smc *smc, int all)
}
smc->hw.hw_state = STARTED ;
- return(0) ;
+ return 0;
}
@@ -1049,7 +1049,7 @@ void sm_ma_control(struct s_smc *smc, int mode)
int sm_mac_get_tx_state(struct s_smc *smc)
{
- return((inpw(FM_A(FM_STMCHN))>>4)&7) ;
+ return (inpw(FM_A(FM_STMCHN))>>4) & 7;
}
/*
@@ -1084,9 +1084,9 @@ static struct s_fpmc* mac_get_mc_table(struct s_smc *smc,
}
if (memcmp((char *)&tb->a,(char *)own,6))
continue ;
- return(tb) ;
+ return tb;
}
- return(slot) ; /* return first free or NULL */
+ return slot; /* return first free or NULL */
}
/*
@@ -1152,12 +1152,12 @@ int mac_add_multicast(struct s_smc *smc, struct fddi_addr *addr, int can)
*/
if (can & 0x80) {
if (smc->hw.fp.smt_slots_used >= SMT_MAX_MULTI) {
- return(1) ;
+ return 1;
}
}
else {
if (smc->hw.fp.os_slots_used >= FPMAX_MULTICAST-SMT_MAX_MULTI) {
- return(1) ;
+ return 1;
}
}
@@ -1165,7 +1165,7 @@ int mac_add_multicast(struct s_smc *smc, struct fddi_addr *addr, int can)
* find empty slot
*/
if (!(tb = mac_get_mc_table(smc,addr,&own,0,can & ~0x80)))
- return(1) ;
+ return 1;
tb->n++ ;
tb->a = own ;
tb->perm = (can & 0x80) ? 1 : 0 ;
@@ -1175,7 +1175,7 @@ int mac_add_multicast(struct s_smc *smc, struct fddi_addr *addr, int can)
else
smc->hw.fp.os_slots_used++ ;
- return(0) ;
+ return 0;
}
/*
diff --git a/drivers/net/skfp/hwmtm.c b/drivers/net/skfp/hwmtm.c
index d322f1b702ac..af5a755e269d 100644
--- a/drivers/net/skfp/hwmtm.c
+++ b/drivers/net/skfp/hwmtm.c
@@ -232,16 +232,16 @@ u_int mac_drv_check_space(void)
#ifdef COMMON_MB_POOL
call_count++ ;
if (call_count == 1) {
- return(EXT_VIRT_MEM) ;
+ return EXT_VIRT_MEM;
}
else {
- return(EXT_VIRT_MEM_2) ;
+ return EXT_VIRT_MEM_2;
}
#else
- return (EXT_VIRT_MEM) ;
+ return EXT_VIRT_MEM;
#endif
#else
- return (0) ;
+ return 0;
#endif
}
@@ -271,7 +271,7 @@ int mac_drv_init(struct s_smc *smc)
if (!(smc->os.hwm.descr_p = (union s_fp_descr volatile *)
mac_drv_get_desc_mem(smc,(u_int)
(RXD_TXD_COUNT+1)*sizeof(struct s_smt_fp_txd)))) {
- return(1) ; /* no space the hwm modul can't work */
+ return 1; /* no space the hwm modul can't work */
}
/*
@@ -283,18 +283,18 @@ int mac_drv_init(struct s_smc *smc)
#ifndef COMMON_MB_POOL
if (!(smc->os.hwm.mbuf_pool.mb_start = (SMbuf *) mac_drv_get_space(smc,
MAX_MBUF*sizeof(SMbuf)))) {
- return(1) ; /* no space the hwm modul can't work */
+ return 1; /* no space the hwm modul can't work */
}
#else
if (!mb_start) {
if (!(mb_start = (SMbuf *) mac_drv_get_space(smc,
MAX_MBUF*sizeof(SMbuf)))) {
- return(1) ; /* no space the hwm modul can't work */
+ return 1; /* no space the hwm modul can't work */
}
}
#endif
#endif
- return (0) ;
+ return 0;
}
/*
@@ -349,7 +349,7 @@ static u_long init_descr_ring(struct s_smc *smc,
DRV_BUF_FLUSH(&d1->r,DDI_DMA_SYNC_FORDEV) ;
d1++;
}
- return(phys) ;
+ return phys;
}
static void init_txd_ring(struct s_smc *smc)
@@ -502,7 +502,7 @@ SMbuf *smt_get_mbuf(struct s_smc *smc)
mb->sm_use_count = 1 ;
}
DB_GEN("get SMbuf: mb = %x",(void *)mb,0,3) ;
- return (mb) ; /* May be NULL */
+ return mb; /* May be NULL */
}
void smt_free_mbuf(struct s_smc *smc, SMbuf *mb)
@@ -621,7 +621,7 @@ static u_long repair_txd_ring(struct s_smc *smc, struct s_smt_tx_queue *queue)
t = t->txd_next ;
tx_used-- ;
}
- return(phys) ;
+ return phys;
}
/*
@@ -673,7 +673,7 @@ static u_long repair_rxd_ring(struct s_smc *smc, struct s_smt_rx_queue *queue)
r = r->rxd_next ;
rx_used-- ;
}
- return(phys) ;
+ return phys;
}
@@ -1595,7 +1595,7 @@ int hwm_tx_init(struct s_smc *smc, u_char fc, int frag_count, int frame_len,
}
DB_TX("frame_status = %x",frame_status,0,3) ;
NDD_TRACE("THiE",frame_status,smc->os.hwm.tx_p->tx_free,0) ;
- return(frame_status) ;
+ return frame_status;
}
/*
@@ -1764,7 +1764,7 @@ static SMbuf *get_llc_rx(struct s_smc *smc)
smc->os.hwm.llc_rx_pipe = mb->sm_next ;
}
DB_GEN("get_llc_rx: mb = 0x%x",(void *)mb,0,4) ;
- return(mb) ;
+ return mb;
}
/*
@@ -1797,7 +1797,7 @@ static SMbuf *get_txd_mb(struct s_smc *smc)
smc->os.hwm.txd_tx_pipe = mb->sm_next ;
}
DB_GEN("get_txd_mb: mb = 0x%x",(void *)mb,0,4) ;
- return(mb) ;
+ return mb;
}
/*
diff --git a/drivers/net/skfp/hwt.c b/drivers/net/skfp/hwt.c
index 053151468f93..e6baa53307c7 100644
--- a/drivers/net/skfp/hwt.c
+++ b/drivers/net/skfp/hwt.c
@@ -179,7 +179,7 @@ u_long hwt_read(struct s_smc *smc)
else
smc->hw.t_stop = smc->hw.t_start - tr ;
}
- return (smc->hw.t_stop) ;
+ return smc->hw.t_stop;
}
#ifdef PCI
@@ -208,7 +208,7 @@ u_long hwt_quick_read(struct s_smc *smc)
outpw(ADDR(B2_TI_CRTL), TIM_START) ;
outpd(ADDR(B2_TI_INI),interval) ;
- return(time) ;
+ return time;
}
/************************
diff --git a/drivers/net/skfp/pcmplc.c b/drivers/net/skfp/pcmplc.c
index ba45bc794d77..112d35b1bf0e 100644
--- a/drivers/net/skfp/pcmplc.c
+++ b/drivers/net/skfp/pcmplc.c
@@ -504,7 +504,7 @@ int sm_pm_get_ls(struct s_smc *smc, int phy)
#ifdef CONCENTRATOR
if (!plc_is_installed(smc,phy))
- return(PC_QLS) ;
+ return PC_QLS;
#endif
state = inpw(PLC(phy,PL_STATUS_A)) & PL_LINE_ST ;
@@ -528,7 +528,7 @@ int sm_pm_get_ls(struct s_smc *smc, int phy)
default :
state = PC_LS_NONE ;
}
- return(state) ;
+ return state;
}
static int plc_send_bits(struct s_smc *smc, struct s_phy *phy, int len)
@@ -547,7 +547,7 @@ static int plc_send_bits(struct s_smc *smc, struct s_phy *phy, int len)
#if 0
printf("PL_PCM_SIGNAL is set\n") ;
#endif
- return(1) ;
+ return 1;
}
/* write bit[n] & length = 1 to regs */
outpw(PLC(np,PL_VECTOR_LEN),len-1) ; /* len=nr-1 */
@@ -562,7 +562,7 @@ static int plc_send_bits(struct s_smc *smc, struct s_phy *phy, int len)
printf("SIGNALING bit %d .. %d\n",phy->bitn,phy->bitn+len-1) ;
#endif
#endif
- return(0) ;
+ return 0;
}
/*
@@ -1590,12 +1590,12 @@ int pcm_status_twisted(struct s_smc *smc)
{
int twist = 0 ;
if (smc->s.sas != SMT_DAS)
- return(0) ;
+ return 0;
if (smc->y[PA].twisted && (smc->y[PA].mib->fddiPORTPCMState == PC8_ACTIVE))
twist |= 1 ;
if (smc->y[PB].twisted && (smc->y[PB].mib->fddiPORTPCMState == PC8_ACTIVE))
twist |= 2 ;
- return(twist) ;
+ return twist;
}
/*
@@ -1636,9 +1636,9 @@ int pcm_rooted_station(struct s_smc *smc)
for (n = 0 ; n < NUMPHYS ; n++) {
if (smc->y[n].mib->fddiPORTPCMState == PC8_ACTIVE &&
smc->y[n].mib->fddiPORTNeighborType == TM)
- return(0) ;
+ return 0;
}
- return(1) ;
+ return 1;
}
/*
@@ -1915,7 +1915,7 @@ int get_pcm_state(struct s_smc *smc, int np)
case PL_PC9 : pcs = PC_MAINT ; break ;
default : pcs = PC_DISABLE ; break ;
}
- return(pcs) ;
+ return pcs;
}
char *get_linestate(struct s_smc *smc, int np)
@@ -1937,7 +1937,7 @@ char *get_linestate(struct s_smc *smc, int np)
default: ls = "unknown" ; break ;
#endif
}
- return(ls) ;
+ return ls;
}
char *get_pcmstate(struct s_smc *smc, int np)
@@ -1959,7 +1959,7 @@ char *get_pcmstate(struct s_smc *smc, int np)
case PL_PC9 : pcs = "MAINT" ; break ;
default : pcs = "UNKNOWN" ; break ;
}
- return(pcs) ;
+ return pcs;
}
void list_phy(struct s_smc *smc)
diff --git a/drivers/net/skfp/pmf.c b/drivers/net/skfp/pmf.c
index a320fdb3727d..9ac4665d7411 100644
--- a/drivers/net/skfp/pmf.c
+++ b/drivers/net/skfp/pmf.c
@@ -328,7 +328,7 @@ static SMbuf *smt_build_pmf_response(struct s_smc *smc, struct smt_header *req,
* build SMT header
*/
if (!(mb = smt_get_mbuf(smc)))
- return(mb) ;
+ return mb;
smt = smtod(mb, struct smt_header *) ;
smt->smt_dest = req->smt_source ; /* DA == source of request */
@@ -493,7 +493,7 @@ static SMbuf *smt_build_pmf_response(struct s_smc *smc, struct smt_header *req,
smt_add_para(smc,&set_pcon,(u_short) SMT_P1035,0,0) ;
smt_add_para(smc,&set_pcon,(u_short) SMT_P1036,0,0) ;
}
- return(mb) ;
+ return mb;
}
static int smt_authorize(struct s_smc *smc, struct smt_header *sm)
@@ -511,7 +511,7 @@ static int smt_authorize(struct s_smc *smc, struct smt_header *sm)
if (i != 8) {
if (memcmp((char *) &sm->smt_sid,
(char *) &smc->mib.fddiPRPMFStation,8))
- return(1) ;
+ return 1;
}
/*
* check authoriziation parameter if passwd not zero
@@ -522,13 +522,13 @@ static int smt_authorize(struct s_smc *smc, struct smt_header *sm)
if (i != 8) {
pa = (struct smt_para *) sm_to_para(smc,sm,SMT_P_AUTHOR) ;
if (!pa)
- return(1) ;
+ return 1;
if (pa->p_len != 8)
- return(1) ;
+ return 1;
if (memcmp((char *)(pa+1),(char *)smc->mib.fddiPRPMFPasswd,8))
- return(1) ;
+ return 1;
}
- return(0) ;
+ return 0;
}
static int smt_check_set_count(struct s_smc *smc, struct smt_header *sm)
@@ -542,9 +542,9 @@ static int smt_check_set_count(struct s_smc *smc, struct smt_header *sm)
if ((smc->mib.fddiSMTSetCount.count != sc->count) ||
memcmp((char *) smc->mib.fddiSMTSetCount.timestamp,
(char *)sc->timestamp,8))
- return(1) ;
+ return 1;
}
- return(0) ;
+ return 0;
}
void smt_add_para(struct s_smc *smc, struct s_pcon *pcon, u_short para,
@@ -1109,7 +1109,7 @@ static int smt_set_para(struct s_smc *smc, struct smt_para *pa, int index,
break ;
case 0x2000 :
if (mac < 0 || mac >= NUMMACS) {
- return(SMT_RDF_NOPARAM) ;
+ return SMT_RDF_NOPARAM;
}
mib_m = &smc->mib.m[mac] ;
mib_addr = (char *) mib_m ;
@@ -1118,7 +1118,7 @@ static int smt_set_para(struct s_smc *smc, struct smt_para *pa, int index,
break ;
case 0x3000 :
if (path < 0 || path >= NUMPATHS) {
- return(SMT_RDF_NOPARAM) ;
+ return SMT_RDF_NOPARAM;
}
mib_a = &smc->mib.a[path] ;
mib_addr = (char *) mib_a ;
@@ -1127,7 +1127,7 @@ static int smt_set_para(struct s_smc *smc, struct smt_para *pa, int index,
break ;
case 0x4000 :
if (port < 0 || port >= smt_mib_phys(smc)) {
- return(SMT_RDF_NOPARAM) ;
+ return SMT_RDF_NOPARAM;
}
mib_p = &smc->mib.p[port_to_mib(smc,port)] ;
mib_addr = (char *) mib_p ;
@@ -1151,22 +1151,20 @@ static int smt_set_para(struct s_smc *smc, struct smt_para *pa, int index,
case SMT_P10F9 :
#endif
case SMT_P20F1 :
- if (!local) {
- return(SMT_RDF_NOPARAM) ;
- }
+ if (!local)
+ return SMT_RDF_NOPARAM;
break ;
}
pt = smt_get_ptab(pa->p_type) ;
- if (!pt) {
- return( (pa->p_type & 0xff00) ? SMT_RDF_NOPARAM :
- SMT_RDF_ILLEGAL ) ;
- }
+ if (!pt)
+ return (pa->p_type & 0xff00) ? SMT_RDF_NOPARAM :
+ SMT_RDF_ILLEGAL;
switch (pt->p_access) {
case AC_GR :
case AC_S :
break ;
default :
- return(SMT_RDF_ILLEGAL) ;
+ return SMT_RDF_ILLEGAL;
}
to = mib_addr + pt->p_offset ;
swap = pt->p_swap ; /* pointer to swap string */
@@ -1292,7 +1290,7 @@ static int smt_set_para(struct s_smc *smc, struct smt_para *pa, int index,
break ;
default :
SMT_PANIC(smc,SMT_E0120, SMT_E0120_MSG) ;
- return(SMT_RDF_ILLEGAL) ;
+ return SMT_RDF_ILLEGAL;
}
}
/*
@@ -1501,15 +1499,15 @@ change_mac_para:
default :
break ;
}
- return(0) ;
+ return 0;
val_error:
/* parameter value in frame is out of range */
- return(SMT_RDF_RANGE) ;
+ return SMT_RDF_RANGE;
len_error:
/* parameter value in frame is too short */
- return(SMT_RDF_LENGTH) ;
+ return SMT_RDF_LENGTH;
#if 0
no_author_error:
@@ -1518,7 +1516,7 @@ no_author_error:
* because SBA denied is not a valid return code in the
* PMF protocol.
*/
- return(SMT_RDF_AUTHOR) ;
+ return SMT_RDF_AUTHOR;
#endif
}
@@ -1527,7 +1525,7 @@ static const struct s_p_tab *smt_get_ptab(u_short para)
const struct s_p_tab *pt ;
for (pt = p_tab ; pt->p_num && pt->p_num != para ; pt++)
;
- return(pt->p_num ? pt : NULL) ;
+ return pt->p_num ? pt : NULL;
}
static int smt_mib_phys(struct s_smc *smc)
@@ -1535,11 +1533,11 @@ static int smt_mib_phys(struct s_smc *smc)
#ifdef CONCENTRATOR
SK_UNUSED(smc) ;
- return(NUMPHYS) ;
+ return NUMPHYS;
#else
if (smc->s.sas == SMT_SAS)
- return(1) ;
- return(NUMPHYS) ;
+ return 1;
+ return NUMPHYS;
#endif
}
@@ -1548,11 +1546,11 @@ static int port_to_mib(struct s_smc *smc, int p)
#ifdef CONCENTRATOR
SK_UNUSED(smc) ;
- return(p) ;
+ return p;
#else
if (smc->s.sas == SMT_SAS)
- return(PS) ;
- return(p) ;
+ return PS;
+ return p;
#endif
}
diff --git a/drivers/net/skfp/queue.c b/drivers/net/skfp/queue.c
index 09adb3d68b7c..c1a0df455a59 100644
--- a/drivers/net/skfp/queue.c
+++ b/drivers/net/skfp/queue.c
@@ -128,7 +128,7 @@ u_short smt_online(struct s_smc *smc, int on)
{
queue_event(smc,EVENT_ECM,on ? EC_CONNECT : EC_DISCONNECT) ;
ev_dispatcher(smc) ;
- return(smc->mib.fddiSMTCF_State) ;
+ return smc->mib.fddiSMTCF_State;
}
/*
diff --git a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c
index 31b2dabf094c..ba2e8339fe90 100644
--- a/drivers/net/skfp/skfddi.c
+++ b/drivers/net/skfp/skfddi.c
@@ -209,7 +209,7 @@ static int skfp_init_one(struct pci_dev *pdev,
void __iomem *mem;
int err;
- pr_debug(KERN_INFO "entering skfp_init_one\n");
+ pr_debug("entering skfp_init_one\n");
if (num_boards == 0)
printk("%s\n", boot_msg);
@@ -385,7 +385,7 @@ static int skfp_driver_init(struct net_device *dev)
skfddi_priv *bp = &smc->os;
int err = -EIO;
- pr_debug(KERN_INFO "entering skfp_driver_init\n");
+ pr_debug("entering skfp_driver_init\n");
// set the io address in private structures
bp->base_addr = dev->base_addr;
@@ -405,7 +405,7 @@ static int skfp_driver_init(struct net_device *dev)
// Determine the required size of the 'shared' memory area.
bp->SharedMemSize = mac_drv_check_space();
- pr_debug(KERN_INFO "Memory for HWM: %ld\n", bp->SharedMemSize);
+ pr_debug("Memory for HWM: %ld\n", bp->SharedMemSize);
if (bp->SharedMemSize > 0) {
bp->SharedMemSize += 16; // for descriptor alignment
@@ -429,18 +429,18 @@ static int skfp_driver_init(struct net_device *dev)
card_stop(smc); // Reset adapter.
- pr_debug(KERN_INFO "mac_drv_init()..\n");
+ pr_debug("mac_drv_init()..\n");
if (mac_drv_init(smc) != 0) {
- pr_debug(KERN_INFO "mac_drv_init() failed.\n");
+ pr_debug("mac_drv_init() failed\n");
goto fail;
}
read_address(smc, NULL);
- pr_debug(KERN_INFO "HW-Addr: %pMF\n", smc->hw.fddi_canon_addr.a);
+ pr_debug("HW-Addr: %pMF\n", smc->hw.fddi_canon_addr.a);
memcpy(dev->dev_addr, smc->hw.fddi_canon_addr.a, 6);
smt_reset_defaults(smc, 0);
- return (0);
+ return 0;
fail:
if (bp->SharedMemAddr) {
@@ -485,7 +485,7 @@ static int skfp_open(struct net_device *dev)
struct s_smc *smc = netdev_priv(dev);
int err;
- pr_debug(KERN_INFO "entering skfp_open\n");
+ pr_debug("entering skfp_open\n");
/* Register IRQ - support shared interrupts by passing device ptr */
err = request_irq(dev->irq, skfp_interrupt, IRQF_SHARED,
dev->name, dev);
@@ -516,7 +516,7 @@ static int skfp_open(struct net_device *dev)
mac_drv_rx_mode(smc, RX_DISABLE_PROMISC);
netif_start_queue(dev);
- return (0);
+ return 0;
} // skfp_open
@@ -565,7 +565,7 @@ static int skfp_close(struct net_device *dev)
skb_queue_purge(&bp->SendSkbQueue);
bp->QueueSkb = MAX_TX_QUEUE_LEN;
- return (0);
+ return 0;
} // skfp_close
@@ -794,7 +794,7 @@ static struct net_device_stats *skfp_ctl_get_stats(struct net_device *dev)
bp->stats.port_lem_cts[1] = bp->cmd_rsp_virt->cntrs_get.cntrs.link_errors[1].ls;
#endif
- return ((struct net_device_stats *) &bp->os.MacStat);
+ return (struct net_device_stats *)&bp->os.MacStat;
} // ctl_get_stat
@@ -856,12 +856,12 @@ static void skfp_ctl_set_multicast_list_wo_lock(struct net_device *dev)
/* Enable promiscuous mode, if necessary */
if (dev->flags & IFF_PROMISC) {
mac_drv_rx_mode(smc, RX_ENABLE_PROMISC);
- pr_debug(KERN_INFO "PROMISCUOUS MODE ENABLED\n");
+ pr_debug("PROMISCUOUS MODE ENABLED\n");
}
/* Else, update multicast address table */
else {
mac_drv_rx_mode(smc, RX_DISABLE_PROMISC);
- pr_debug(KERN_INFO "PROMISCUOUS MODE DISABLED\n");
+ pr_debug("PROMISCUOUS MODE DISABLED\n");
// Reset all MC addresses
mac_clear_multicast(smc);
@@ -869,7 +869,7 @@ static void skfp_ctl_set_multicast_list_wo_lock(struct net_device *dev)
if (dev->flags & IFF_ALLMULTI) {
mac_drv_rx_mode(smc, RX_ENABLE_ALLMULTI);
- pr_debug(KERN_INFO "ENABLE ALL MC ADDRESSES\n");
+ pr_debug("ENABLE ALL MC ADDRESSES\n");
} else if (!netdev_mc_empty(dev)) {
if (netdev_mc_count(dev) <= FPMAX_MULTICAST) {
/* use exact filtering */
@@ -880,18 +880,18 @@ static void skfp_ctl_set_multicast_list_wo_lock(struct net_device *dev)
(struct fddi_addr *)ha->addr,
1);
- pr_debug(KERN_INFO "ENABLE MC ADDRESS: %pMF\n",
- ha->addr);
+ pr_debug("ENABLE MC ADDRESS: %pMF\n",
+ ha->addr);
}
} else { // more MC addresses than HW supports
mac_drv_rx_mode(smc, RX_ENABLE_ALLMULTI);
- pr_debug(KERN_INFO "ENABLE ALL MC ADDRESSES\n");
+ pr_debug("ENABLE ALL MC ADDRESSES\n");
}
} else { // no MC addresses
- pr_debug(KERN_INFO "DISABLE ALL MC ADDRESSES\n");
+ pr_debug("DISABLE ALL MC ADDRESSES\n");
}
/* Update adapter filters */
@@ -932,7 +932,7 @@ static int skfp_ctl_set_mac_address(struct net_device *dev, void *addr)
ResetAdapter(smc);
spin_unlock_irqrestore(&bp->DriverLock, Flags);
- return (0); /* always return zero */
+ return 0; /* always return zero */
} // skfp_ctl_set_mac_address
@@ -1045,7 +1045,7 @@ static netdev_tx_t skfp_send_pkt(struct sk_buff *skb,
struct s_smc *smc = netdev_priv(dev);
skfddi_priv *bp = &smc->os;
- pr_debug(KERN_INFO "skfp_send_pkt\n");
+ pr_debug("skfp_send_pkt\n");
/*
* Verify that incoming transmit request is OK
@@ -1114,13 +1114,13 @@ static void send_queued_packets(struct s_smc *smc)
int frame_status; // HWM tx frame status.
- pr_debug(KERN_INFO "send queued packets\n");
+ pr_debug("send queued packets\n");
for (;;) {
// send first buffer from queue
skb = skb_dequeue(&bp->SendSkbQueue);
if (!skb) {
- pr_debug(KERN_INFO "queue empty\n");
+ pr_debug("queue empty\n");
return;
} // queue empty !
@@ -1232,7 +1232,7 @@ static void CheckSourceAddress(unsigned char *frame, unsigned char *hw_addr)
static void ResetAdapter(struct s_smc *smc)
{
- pr_debug(KERN_INFO "[fddi: ResetAdapter]\n");
+ pr_debug("[fddi: ResetAdapter]\n");
// Stop the adapter.
@@ -1278,7 +1278,7 @@ void llc_restart_tx(struct s_smc *smc)
{
skfddi_priv *bp = &smc->os;
- pr_debug(KERN_INFO "[llc_restart_tx]\n");
+ pr_debug("[llc_restart_tx]\n");
// Try to send queued packets
spin_unlock(&bp->DriverLock);
@@ -1308,21 +1308,21 @@ void *mac_drv_get_space(struct s_smc *smc, unsigned int size)
{
void *virt;
- pr_debug(KERN_INFO "mac_drv_get_space (%d bytes), ", size);
+ pr_debug("mac_drv_get_space (%d bytes), ", size);
virt = (void *) (smc->os.SharedMemAddr + smc->os.SharedMemHeap);
if ((smc->os.SharedMemHeap + size) > smc->os.SharedMemSize) {
printk("Unexpected SMT memory size requested: %d\n", size);
- return (NULL);
+ return NULL;
}
smc->os.SharedMemHeap += size; // Move heap pointer.
- pr_debug(KERN_INFO "mac_drv_get_space end\n");
- pr_debug(KERN_INFO "virt addr: %lx\n", (ulong) virt);
- pr_debug(KERN_INFO "bus addr: %lx\n", (ulong)
+ pr_debug("mac_drv_get_space end\n");
+ pr_debug("virt addr: %lx\n", (ulong) virt);
+ pr_debug("bus addr: %lx\n", (ulong)
(smc->os.SharedMemDMA +
((char *) virt - (char *)smc->os.SharedMemAddr)));
- return (virt);
+ return virt;
} // mac_drv_get_space
@@ -1349,7 +1349,7 @@ void *mac_drv_get_desc_mem(struct s_smc *smc, unsigned int size)
char *virt;
- pr_debug(KERN_INFO "mac_drv_get_desc_mem\n");
+ pr_debug("mac_drv_get_desc_mem\n");
// Descriptor memory must be aligned on 16-byte boundary.
@@ -1363,9 +1363,9 @@ void *mac_drv_get_desc_mem(struct s_smc *smc, unsigned int size)
if (!mac_drv_get_space(smc, size)) {
printk("fddi: Unable to align descriptor memory.\n");
- return (NULL);
+ return NULL;
}
- return (virt + size);
+ return virt + size;
} // mac_drv_get_desc_mem
@@ -1384,8 +1384,8 @@ void *mac_drv_get_desc_mem(struct s_smc *smc, unsigned int size)
************************/
unsigned long mac_drv_virt2phys(struct s_smc *smc, void *virt)
{
- return (smc->os.SharedMemDMA +
- ((char *) virt - (char *)smc->os.SharedMemAddr));
+ return smc->os.SharedMemDMA +
+ ((char *) virt - (char *)smc->os.SharedMemAddr);
} // mac_drv_virt2phys
@@ -1419,8 +1419,8 @@ unsigned long mac_drv_virt2phys(struct s_smc *smc, void *virt)
************************/
u_long dma_master(struct s_smc * smc, void *virt, int len, int flag)
{
- return (smc->os.SharedMemDMA +
- ((char *) virt - (char *)smc->os.SharedMemAddr));
+ return smc->os.SharedMemDMA +
+ ((char *) virt - (char *)smc->os.SharedMemAddr);
} // dma_master
@@ -1493,7 +1493,7 @@ void mac_drv_tx_complete(struct s_smc *smc, volatile struct s_smt_fp_txd *txd)
{
struct sk_buff *skb;
- pr_debug(KERN_INFO "entering mac_drv_tx_complete\n");
+ pr_debug("entering mac_drv_tx_complete\n");
// Check if this TxD points to a skb
if (!(skb = txd->txd_os.skb)) {
@@ -1513,7 +1513,7 @@ void mac_drv_tx_complete(struct s_smc *smc, volatile struct s_smt_fp_txd *txd)
// free the skb
dev_kfree_skb_irq(skb);
- pr_debug(KERN_INFO "leaving mac_drv_tx_complete\n");
+ pr_debug("leaving mac_drv_tx_complete\n");
} // mac_drv_tx_complete
@@ -1580,7 +1580,7 @@ void mac_drv_rx_complete(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd,
unsigned short ri;
u_int RifLength;
- pr_debug(KERN_INFO "entering mac_drv_rx_complete (len=%d)\n", len);
+ pr_debug("entering mac_drv_rx_complete (len=%d)\n", len);
if (frag_count != 1) { // This is not allowed to happen.
printk("fddi: Multi-fragment receive!\n");
@@ -1589,7 +1589,7 @@ void mac_drv_rx_complete(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd,
}
skb = rxd->rxd_os.skb;
if (!skb) {
- pr_debug(KERN_INFO "No skb in rxd\n");
+ pr_debug("No skb in rxd\n");
smc->os.MacStat.gen.rx_errors++;
goto RequeueRxd;
}
@@ -1619,7 +1619,7 @@ void mac_drv_rx_complete(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd,
else {
int n;
// goos: RIF removal has still to be tested
- pr_debug(KERN_INFO "RIF found\n");
+ pr_debug("RIF found\n");
// Get RIF length from Routing Control (RC) field.
cp = virt + FDDI_MAC_HDR_LEN; // Point behind MAC header.
@@ -1664,7 +1664,7 @@ void mac_drv_rx_complete(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd,
return;
RequeueRxd:
- pr_debug(KERN_INFO "Rx: re-queue RXD.\n");
+ pr_debug("Rx: re-queue RXD.\n");
mac_drv_requeue_rxd(smc, rxd, frag_count);
smc->os.MacStat.gen.rx_errors++; // Count receive packets
// not indicated.
@@ -1775,7 +1775,7 @@ void mac_drv_fill_rxd(struct s_smc *smc)
struct sk_buff *skb;
volatile struct s_smt_fp_rxd *rxd;
- pr_debug(KERN_INFO "entering mac_drv_fill_rxd\n");
+ pr_debug("entering mac_drv_fill_rxd\n");
// Walk through the list of free receive buffers, passing receive
// buffers to the HWM as long as RXDs are available.
@@ -1783,7 +1783,7 @@ void mac_drv_fill_rxd(struct s_smc *smc)
MaxFrameSize = smc->os.MaxFrameSize;
// Check if there is any RXD left.
while (HWM_GET_RX_FREE(smc) > 0) {
- pr_debug(KERN_INFO ".\n");
+ pr_debug(".\n");
rxd = HWM_GET_CURR_RXD(smc);
skb = alloc_skb(MaxFrameSize + 3, GFP_ATOMIC);
@@ -1814,7 +1814,7 @@ void mac_drv_fill_rxd(struct s_smc *smc)
hwm_rx_frag(smc, v_addr, b_addr, MaxFrameSize,
FIRST_FRAG | LAST_FRAG);
}
- pr_debug(KERN_INFO "leaving mac_drv_fill_rxd\n");
+ pr_debug("leaving mac_drv_fill_rxd\n");
} // mac_drv_fill_rxd
@@ -1904,12 +1904,12 @@ int mac_drv_rx_init(struct s_smc *smc, int len, int fc,
pr_debug("fddi: Discard invalid local SMT frame\n");
pr_debug(" len=%d, la_len=%d, (ULONG) look_ahead=%08lXh.\n",
len, la_len, (unsigned long) look_ahead);
- return (0);
+ return 0;
}
skb = alloc_skb(len + 3, GFP_ATOMIC);
if (!skb) {
pr_debug("fddi: Local SMT: skb memory exhausted.\n");
- return (0);
+ return 0;
}
skb_reserve(skb, 3);
skb_put(skb, len);
@@ -1919,7 +1919,7 @@ int mac_drv_rx_init(struct s_smc *smc, int len, int fc,
skb->protocol = fddi_type_trans(skb, smc->os.dev);
netif_rx(skb);
- return (0);
+ return 0;
} // mac_drv_rx_init
@@ -2034,17 +2034,17 @@ void smt_stat_counter(struct s_smc *smc, int stat)
{
// BOOLEAN RingIsUp ;
- pr_debug(KERN_INFO "smt_stat_counter\n");
+ pr_debug("smt_stat_counter\n");
switch (stat) {
case 0:
- pr_debug(KERN_INFO "Ring operational change.\n");
+ pr_debug("Ring operational change.\n");
break;
case 1:
- pr_debug(KERN_INFO "Receive fifo overflow.\n");
+ pr_debug("Receive fifo overflow.\n");
smc->os.MacStat.gen.rx_errors++;
break;
default:
- pr_debug(KERN_INFO "Unknown status (%d).\n", stat);
+ pr_debug("Unknown status (%d).\n", stat);
break;
}
} // smt_stat_counter
@@ -2100,10 +2100,10 @@ void cfm_state_change(struct s_smc *smc, int c_state)
s = "SC11_C_WRAP_S";
break;
default:
- pr_debug(KERN_INFO "cfm_state_change: unknown %d\n", c_state);
+ pr_debug("cfm_state_change: unknown %d\n", c_state);
return;
}
- pr_debug(KERN_INFO "cfm_state_change: %s\n", s);
+ pr_debug("cfm_state_change: %s\n", s);
#endif // DRIVERDEBUG
} // cfm_state_change
@@ -2158,7 +2158,7 @@ void ecm_state_change(struct s_smc *smc, int e_state)
s = "unknown";
break;
}
- pr_debug(KERN_INFO "ecm_state_change: %s\n", s);
+ pr_debug("ecm_state_change: %s\n", s);
#endif //DRIVERDEBUG
} // ecm_state_change
@@ -2213,7 +2213,7 @@ void rmt_state_change(struct s_smc *smc, int r_state)
s = "unknown";
break;
}
- pr_debug(KERN_INFO "[rmt_state_change: %s]\n", s);
+ pr_debug("[rmt_state_change: %s]\n", s);
#endif // DRIVERDEBUG
} // rmt_state_change
@@ -2233,7 +2233,7 @@ void rmt_state_change(struct s_smc *smc, int r_state)
************************/
void drv_reset_indication(struct s_smc *smc)
{
- pr_debug(KERN_INFO "entering drv_reset_indication\n");
+ pr_debug("entering drv_reset_indication\n");
smc->os.ResetRequested = TRUE; // Set flag.
diff --git a/drivers/net/skfp/smt.c b/drivers/net/skfp/smt.c
index 6f35bb77595f..2d9941c045bc 100644
--- a/drivers/net/skfp/smt.c
+++ b/drivers/net/skfp/smt.c
@@ -127,22 +127,22 @@ static inline int is_my_addr(const struct s_smc *smc,
static inline int is_broadcast(const struct fddi_addr *addr)
{
- return(*(u_short *)(&addr->a[0]) == 0xffff &&
+ return *(u_short *)(&addr->a[0]) == 0xffff &&
*(u_short *)(&addr->a[2]) == 0xffff &&
- *(u_short *)(&addr->a[4]) == 0xffff ) ;
+ *(u_short *)(&addr->a[4]) == 0xffff;
}
static inline int is_individual(const struct fddi_addr *addr)
{
- return(!(addr->a[0] & GROUP_ADDR)) ;
+ return !(addr->a[0] & GROUP_ADDR);
}
static inline int is_equal(const struct fddi_addr *addr1,
const struct fddi_addr *addr2)
{
- return(*(u_short *)(&addr1->a[0]) == *(u_short *)(&addr2->a[0]) &&
+ return *(u_short *)(&addr1->a[0]) == *(u_short *)(&addr2->a[0]) &&
*(u_short *)(&addr1->a[2]) == *(u_short *)(&addr2->a[2]) &&
- *(u_short *)(&addr1->a[4]) == *(u_short *)(&addr2->a[4]) ) ;
+ *(u_short *)(&addr1->a[4]) == *(u_short *)(&addr2->a[4]);
}
/*
@@ -457,8 +457,8 @@ static int div_ratio(u_long upper, u_long lower)
else
upper <<= 16L ;
if (!lower)
- return(0) ;
- return((int)(upper/lower)) ;
+ return 0;
+ return (int)(upper/lower) ;
}
#ifndef SLIM_SMT
@@ -1111,11 +1111,11 @@ SMbuf *smt_build_frame(struct s_smc *smc, int class, int type,
#if 0
if (!smc->r.sm_ma_avail) {
- return(0) ;
+ return 0;
}
#endif
if (!(mb = smt_get_mbuf(smc)))
- return(mb) ;
+ return mb;
mb->sm_len = length ;
smt = smtod(mb, struct smt_header *) ;
@@ -1136,7 +1136,7 @@ SMbuf *smt_build_frame(struct s_smc *smc, int class, int type,
smt->smt_tid = smt_get_tid(smc) ; /* set transaction ID */
smt->smt_pad = 0 ;
smt->smt_len = length - sizeof(struct smt_header) ;
- return(mb) ;
+ return mb;
}
static void smt_add_frame_len(SMbuf *mb, int len)
@@ -1375,7 +1375,7 @@ static int smt_fill_path(struct s_smc *smc, struct smt_p_path *path)
pd_mac = (struct smt_mac_rec *) phy ;
pd_mac->mac_addr = smc->mib.m[MAC0].fddiMACSMTAddress ;
pd_mac->mac_resource_idx = mac_con_resource_index(smc,1) ;
- return(len) ;
+ return len;
}
/*
@@ -1563,7 +1563,7 @@ u_long smt_get_tid(struct s_smc *smc)
u_long tid ;
while ((tid = ++(smc->sm.smt_tid) ^ SMT_TID_MAGIC) == 0)
;
- return(tid & 0x3fffffffL) ;
+ return tid & 0x3fffffffL;
}
@@ -1654,11 +1654,11 @@ int smt_check_para(struct s_smc *smc, struct smt_header *sm,
while (*p) {
if (!sm_to_para(smc,sm,(int) *p)) {
DB_SMT("SMT: smt_check_para - missing para %x\n",*p,0);
- return(-1) ;
+ return -1;
}
p++ ;
}
- return(0) ;
+ return 0;
}
void *sm_to_para(struct s_smc *smc, struct smt_header *sm, int para)
@@ -1687,7 +1687,7 @@ void *sm_to_para(struct s_smc *smc, struct smt_header *sm, int para)
return NULL;
}
if (found)
- return(found) ;
+ return found;
}
return NULL;
}
@@ -1732,7 +1732,7 @@ char *addr_to_string(struct fddi_addr *addr)
string[i * 3 + 2] = ':';
}
string[5 * 3 + 2] = 0;
- return(string);
+ return string;
}
#endif
@@ -1742,9 +1742,9 @@ int smt_ifconfig(int argc, char *argv[])
if (argc >= 2 && !strcmp(argv[0],"opt_bypass") &&
!strcmp(argv[1],"yes")) {
smc->mib.fddiSMTBypassPresent = 1 ;
- return(0) ;
+ return 0;
}
- return(amdfddi_config(0,argc,argv)) ;
+ return amdfddi_config(0, argc, argv);
}
#endif
@@ -1756,9 +1756,9 @@ static int mac_index(struct s_smc *smc, int mac)
SK_UNUSED(mac) ;
#ifdef CONCENTRATOR
SK_UNUSED(smc) ;
- return(NUMPHYS+1) ;
+ return NUMPHYS + 1;
#else
- return((smc->s.sas == SMT_SAS) ? 2 : 3) ;
+ return (smc->s.sas == SMT_SAS) ? 2 : 3;
#endif
}
@@ -1768,7 +1768,7 @@ static int mac_index(struct s_smc *smc, int mac)
static int phy_index(struct s_smc *smc, int phy)
{
SK_UNUSED(smc) ;
- return(phy+1);
+ return phy + 1;
}
/*
@@ -1779,19 +1779,19 @@ static int mac_con_resource_index(struct s_smc *smc, int mac)
#ifdef CONCENTRATOR
SK_UNUSED(smc) ;
SK_UNUSED(mac) ;
- return(entity_to_index(smc,cem_get_downstream(smc,ENTITY_MAC))) ;
+ return entity_to_index(smc, cem_get_downstream(smc, ENTITY_MAC));
#else
SK_UNUSED(mac) ;
switch (smc->mib.fddiSMTCF_State) {
case SC9_C_WRAP_A :
case SC5_THRU_B :
case SC11_C_WRAP_S :
- return(1) ;
+ return 1;
case SC10_C_WRAP_B :
case SC4_THRU_A :
- return(2) ;
+ return 2;
}
- return(smc->s.sas == SMT_SAS ? 2 : 3) ;
+ return smc->s.sas == SMT_SAS ? 2 : 3;
#endif
}
@@ -1801,21 +1801,21 @@ static int mac_con_resource_index(struct s_smc *smc, int mac)
static int phy_con_resource_index(struct s_smc *smc, int phy)
{
#ifdef CONCENTRATOR
- return(entity_to_index(smc,cem_get_downstream(smc,ENTITY_PHY(phy)))) ;
+ return entity_to_index(smc, cem_get_downstream(smc, ENTITY_PHY(phy))) ;
#else
switch (smc->mib.fddiSMTCF_State) {
case SC9_C_WRAP_A :
- return(phy == PA ? 3 : 2) ;
+ return phy == PA ? 3 : 2;
case SC10_C_WRAP_B :
- return(phy == PA ? 1 : 3) ;
+ return phy == PA ? 1 : 3;
case SC4_THRU_A :
- return(phy == PA ? 3 : 1) ;
+ return phy == PA ? 3 : 1;
case SC5_THRU_B :
- return(phy == PA ? 2 : 3) ;
+ return phy == PA ? 2 : 3;
case SC11_C_WRAP_S :
- return(2) ;
+ return 2;
}
- return(phy) ;
+ return phy;
#endif
}
@@ -1823,16 +1823,16 @@ static int phy_con_resource_index(struct s_smc *smc, int phy)
static int entity_to_index(struct s_smc *smc, int e)
{
if (e == ENTITY_MAC)
- return(mac_index(smc,1)) ;
+ return mac_index(smc, 1);
else
- return(phy_index(smc,e - ENTITY_PHY(0))) ;
+ return phy_index(smc, e - ENTITY_PHY(0));
}
#endif
#ifdef LITTLE_ENDIAN
static int smt_swap_short(u_short s)
{
- return(((s>>8)&0xff)|((s&0xff)<<8)) ;
+ return ((s>>8)&0xff) | ((s&0xff)<<8);
}
void smt_swap_para(struct smt_header *sm, int len, int direction)
@@ -1996,7 +1996,7 @@ int smt_action(struct s_smc *smc, int class, int code, int index)
}
break ;
default :
- return(1) ;
+ return 1;
}
break ;
case SMT_PORT_ACTION :
@@ -2017,14 +2017,14 @@ int smt_action(struct s_smc *smc, int class, int code, int index)
event = PC_STOP ;
break ;
default :
- return(1) ;
+ return 1;
}
queue_event(smc,EVENT_PCM+index,event) ;
break ;
default :
- return(1) ;
+ return 1;
}
- return(0) ;
+ return 0;
}
/*
diff --git a/drivers/net/skfp/smtdef.c b/drivers/net/skfp/smtdef.c
index 4e07ff7073f1..1acab0b368e3 100644
--- a/drivers/net/skfp/smtdef.c
+++ b/drivers/net/skfp/smtdef.c
@@ -303,7 +303,7 @@ int smt_set_mac_opvalues(struct s_smc *smc)
FDDI_SMT_EVENT, (u_long) FDDI_REMOTE_T_REQ,
smt_get_event_word(smc));
}
- return(st) ;
+ return st;
}
void smt_fixup_mib(struct s_smc *smc)
@@ -350,6 +350,6 @@ static int set_min_max(int maxflag, u_long mib, u_long limit, u_long *oper)
*oper = limit ;
else
*oper = mib ;
- return(old != *oper) ;
+ return old != *oper;
}
diff --git a/drivers/net/skfp/smtinit.c b/drivers/net/skfp/smtinit.c
index 3c8964ce1837..e3a0c0bc2233 100644
--- a/drivers/net/skfp/smtinit.c
+++ b/drivers/net/skfp/smtinit.c
@@ -120,6 +120,6 @@ int init_smt(struct s_smc *smc, u_char *mac_addr)
PNMI_INIT(smc) ; /* PNMI initialization */
- return(0) ;
+ return 0;
}
diff --git a/drivers/net/skfp/srf.c b/drivers/net/skfp/srf.c
index 40882b3faba6..f6f7baf9f27a 100644
--- a/drivers/net/skfp/srf.c
+++ b/drivers/net/skfp/srf.c
@@ -165,7 +165,7 @@ static struct s_srf_evc *smt_get_evc(struct s_smc *smc, int code, int index)
for (i = 0, evc = smc->evcs ; (unsigned) i < MAX_EVCS ; i++, evc++) {
if (evc->evc_code == code && evc->evc_index == index)
- return(evc) ;
+ return evc;
}
return NULL;
}
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index 40e5c46e7571..bfec2e0f5275 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -43,6 +43,7 @@
#include <linux/seq_file.h>
#include <linux/mii.h>
#include <linux/slab.h>
+#include <linux/dmi.h>
#include <asm/irq.h>
#include "skge.h"
@@ -3178,8 +3179,7 @@ static int skge_poll(struct napi_struct *napi, int to_do)
skb = skge_rx_get(dev, e, control, rd->status, rd->csum2);
if (likely(skb)) {
- netif_receive_skb(skb);
-
+ napi_gro_receive(napi, skb);
++work_done;
}
}
@@ -3192,6 +3192,7 @@ static int skge_poll(struct napi_struct *napi, int to_do)
if (work_done < to_do) {
unsigned long flags;
+ napi_gro_flush(napi);
spin_lock_irqsave(&hw->hw_lock, flags);
__napi_complete(napi);
hw->intr_mask |= napimask[skge->port];
@@ -3849,6 +3850,7 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port,
dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
skge->rx_csum = 1;
}
+ dev->features |= NETIF_F_GRO;
/* read the mac address */
memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port*8, ETH_ALEN);
@@ -3868,6 +3870,8 @@ static void __devinit skge_show_addr(struct net_device *dev)
netif_info(skge, probe, skge->netdev, "addr %pM\n", dev->dev_addr);
}
+static int only_32bit_dma;
+
static int __devinit skge_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
@@ -3889,7 +3893,7 @@ static int __devinit skge_probe(struct pci_dev *pdev,
pci_set_master(pdev);
- if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
+ if (!only_32bit_dma && !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
using_dac = 1;
err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
} else if (!(err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))) {
@@ -4147,8 +4151,21 @@ static struct pci_driver skge_driver = {
.shutdown = skge_shutdown,
};
+static struct dmi_system_id skge_32bit_dma_boards[] = {
+ {
+ .ident = "Gigabyte nForce boards",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co"),
+ DMI_MATCH(DMI_BOARD_NAME, "nForce"),
+ },
+ },
+ {}
+};
+
static int __init skge_init_module(void)
{
+ if (dmi_check_system(skge_32bit_dma_boards))
+ only_32bit_dma = 1;
skge_debug_init();
return pci_register_driver(&skge_driver);
}
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 194e5cf8c763..d6577084ce70 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -1782,7 +1782,7 @@ static netdev_tx_t sky2_xmit_frame(struct sk_buff *skb,
ctrl = 0;
#ifdef SKY2_VLAN_TAG_USED
/* Add VLAN tag, can piggyback on LRGLEN or ADDR64 */
- if (sky2->vlgrp && vlan_tx_tag_present(skb)) {
+ if (vlan_tx_tag_present(skb)) {
if (!le) {
le = get_tx_le(sky2, &slot);
le->addr = 0;
@@ -4581,7 +4581,8 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw,
sky2->port = port;
- dev->features |= NETIF_F_TSO | NETIF_F_IP_CSUM | NETIF_F_SG;
+ dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG
+ | NETIF_F_TSO | NETIF_F_GRO;
if (highmem)
dev->features |= NETIF_F_HIGHDMA;
diff --git a/drivers/net/slip.c b/drivers/net/slip.c
index fa434fb8fb7c..86cbb9ea2f26 100644
--- a/drivers/net/slip.c
+++ b/drivers/net/slip.c
@@ -271,7 +271,7 @@ static int sl_realloc_bufs(struct slip *sl, int mtu)
memcpy(sl->xbuff, sl->xhead, sl->xleft);
} else {
sl->xleft = 0;
- sl->tx_dropped++;
+ dev->stats.tx_dropped++;
}
}
sl->xhead = sl->xbuff;
@@ -281,7 +281,7 @@ static int sl_realloc_bufs(struct slip *sl, int mtu)
memcpy(sl->rbuff, rbuff, sl->rcount);
} else {
sl->rcount = 0;
- sl->rx_over_errors++;
+ dev->stats.rx_over_errors++;
set_bit(SLF_ERROR, &sl->flags);
}
}
@@ -319,6 +319,7 @@ static inline void sl_unlock(struct slip *sl)
/* Send one completely decapsulated IP datagram to the IP layer. */
static void sl_bump(struct slip *sl)
{
+ struct net_device *dev = sl->dev;
struct sk_buff *skb;
int count;
@@ -329,13 +330,13 @@ static void sl_bump(struct slip *sl)
if (c & SL_TYPE_COMPRESSED_TCP) {
/* ignore compressed packets when CSLIP is off */
if (!(sl->mode & SL_MODE_CSLIP)) {
- printk(KERN_WARNING "%s: compressed packet ignored\n", sl->dev->name);
+ printk(KERN_WARNING "%s: compressed packet ignored\n", dev->name);
return;
}
/* make sure we've reserved enough space for uncompress
to use */
if (count + 80 > sl->buffsize) {
- sl->rx_over_errors++;
+ dev->stats.rx_over_errors++;
return;
}
count = slhc_uncompress(sl->slcomp, sl->rbuff, count);
@@ -346,7 +347,7 @@ static void sl_bump(struct slip *sl)
/* turn on header compression */
sl->mode |= SL_MODE_CSLIP;
sl->mode &= ~SL_MODE_ADAPTIVE;
- printk(KERN_INFO "%s: header compression turned on\n", sl->dev->name);
+ printk(KERN_INFO "%s: header compression turned on\n", dev->name);
}
sl->rbuff[0] &= 0x4f;
if (slhc_remember(sl->slcomp, sl->rbuff, count) <= 0)
@@ -355,20 +356,20 @@ static void sl_bump(struct slip *sl)
}
#endif /* SL_INCLUDE_CSLIP */
- sl->rx_bytes += count;
+ dev->stats.rx_bytes += count;
skb = dev_alloc_skb(count);
if (skb == NULL) {
- printk(KERN_WARNING "%s: memory squeeze, dropping packet.\n", sl->dev->name);
- sl->rx_dropped++;
+ printk(KERN_WARNING "%s: memory squeeze, dropping packet.\n", dev->name);
+ dev->stats.rx_dropped++;
return;
}
- skb->dev = sl->dev;
+ skb->dev = dev;
memcpy(skb_put(skb, count), sl->rbuff, count);
skb_reset_mac_header(skb);
skb->protocol = htons(ETH_P_IP);
netif_rx(skb);
- sl->rx_packets++;
+ dev->stats.rx_packets++;
}
/* Encapsulate one IP datagram and stuff into a TTY queue. */
@@ -379,7 +380,7 @@ static void sl_encaps(struct slip *sl, unsigned char *icp, int len)
if (len > sl->mtu) { /* Sigh, shouldn't occur BUT ... */
printk(KERN_WARNING "%s: truncating oversized transmit packet!\n", sl->dev->name);
- sl->tx_dropped++;
+ sl->dev->stats.tx_dropped++;
sl_unlock(sl);
return;
}
@@ -433,7 +434,7 @@ static void slip_write_wakeup(struct tty_struct *tty)
if (sl->xleft <= 0) {
/* Now serial buffer is almost free & we can start
* transmission of another packet */
- sl->tx_packets++;
+ sl->dev->stats.tx_packets++;
clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
sl_unlock(sl);
return;
@@ -496,7 +497,7 @@ sl_xmit(struct sk_buff *skb, struct net_device *dev)
}
sl_lock(sl);
- sl->tx_bytes += skb->len;
+ dev->stats.tx_bytes += skb->len;
sl_encaps(sl, skb->data, skb->len);
spin_unlock(&sl->lock);
@@ -558,39 +559,39 @@ static int sl_change_mtu(struct net_device *dev, int new_mtu)
/* Netdevice get statistics request */
-static struct net_device_stats *
-sl_get_stats(struct net_device *dev)
+static struct rtnl_link_stats64 *
+sl_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
{
- static struct net_device_stats stats;
- struct slip *sl = netdev_priv(dev);
+ struct net_device_stats *devstats = &dev->stats;
+ unsigned long c_rx_dropped = 0;
#ifdef SL_INCLUDE_CSLIP
- struct slcompress *comp;
-#endif
+ unsigned long c_rx_fifo_errors = 0;
+ unsigned long c_tx_fifo_errors = 0;
+ unsigned long c_collisions = 0;
+ struct slip *sl = netdev_priv(dev);
+ struct slcompress *comp = sl->slcomp;
- memset(&stats, 0, sizeof(struct net_device_stats));
-
- stats.rx_packets = sl->rx_packets;
- stats.tx_packets = sl->tx_packets;
- stats.rx_bytes = sl->rx_bytes;
- stats.tx_bytes = sl->tx_bytes;
- stats.rx_dropped = sl->rx_dropped;
- stats.tx_dropped = sl->tx_dropped;
- stats.tx_errors = sl->tx_errors;
- stats.rx_errors = sl->rx_errors;
- stats.rx_over_errors = sl->rx_over_errors;
-#ifdef SL_INCLUDE_CSLIP
- stats.rx_fifo_errors = sl->rx_compressed;
- stats.tx_fifo_errors = sl->tx_compressed;
- stats.collisions = sl->tx_misses;
- comp = sl->slcomp;
if (comp) {
- stats.rx_fifo_errors += comp->sls_i_compressed;
- stats.rx_dropped += comp->sls_i_tossed;
- stats.tx_fifo_errors += comp->sls_o_compressed;
- stats.collisions += comp->sls_o_misses;
+ c_rx_fifo_errors = comp->sls_i_compressed;
+ c_rx_dropped = comp->sls_i_tossed;
+ c_tx_fifo_errors = comp->sls_o_compressed;
+ c_collisions = comp->sls_o_misses;
}
-#endif /* CONFIG_INET */
- return (&stats);
+ stats->rx_fifo_errors = sl->rx_compressed + c_rx_fifo_errors;
+ stats->tx_fifo_errors = sl->tx_compressed + c_tx_fifo_errors;
+ stats->collisions = sl->tx_misses + c_collisions;
+#endif
+ stats->rx_packets = devstats->rx_packets;
+ stats->tx_packets = devstats->tx_packets;
+ stats->rx_bytes = devstats->rx_bytes;
+ stats->tx_bytes = devstats->tx_bytes;
+ stats->rx_dropped = devstats->rx_dropped + c_rx_dropped;
+ stats->tx_dropped = devstats->tx_dropped;
+ stats->tx_errors = devstats->tx_errors;
+ stats->rx_errors = devstats->rx_errors;
+ stats->rx_over_errors = devstats->rx_over_errors;
+
+ return stats;
}
/* Netdevice register callback */
@@ -633,7 +634,7 @@ static const struct net_device_ops sl_netdev_ops = {
.ndo_open = sl_open,
.ndo_stop = sl_close,
.ndo_start_xmit = sl_xmit,
- .ndo_get_stats = sl_get_stats,
+ .ndo_get_stats64 = sl_get_stats64,
.ndo_change_mtu = sl_change_mtu,
.ndo_tx_timeout = sl_tx_timeout,
#ifdef CONFIG_SLIP_SMART
@@ -681,7 +682,7 @@ static void slip_receive_buf(struct tty_struct *tty, const unsigned char *cp,
while (count--) {
if (fp && *fp++) {
if (!test_and_set_bit(SLF_ERROR, &sl->flags))
- sl->rx_errors++;
+ sl->dev->stats.rx_errors++;
cp++;
continue;
}
@@ -943,7 +944,7 @@ static int slip_esc(unsigned char *s, unsigned char *d, int len)
}
}
*ptr++ = END;
- return (ptr - d);
+ return ptr - d;
}
static void slip_unesc(struct slip *sl, unsigned char s)
@@ -981,7 +982,7 @@ static void slip_unesc(struct slip *sl, unsigned char s)
sl->rbuff[sl->rcount++] = s;
return;
}
- sl->rx_over_errors++;
+ sl->dev->stats.rx_over_errors++;
set_bit(SLF_ERROR, &sl->flags);
}
}
@@ -1057,7 +1058,7 @@ static void slip_unesc6(struct slip *sl, unsigned char s)
sl->rbuff[sl->rcount++] = c;
return;
}
- sl->rx_over_errors++;
+ sl->dev->stats.rx_over_errors++;
set_bit(SLF_ERROR, &sl->flags);
}
}
diff --git a/drivers/net/slip.h b/drivers/net/slip.h
index 9ea5c11287d2..914e958abbfc 100644
--- a/drivers/net/slip.h
+++ b/drivers/net/slip.h
@@ -67,15 +67,6 @@ struct slip {
int xleft; /* bytes left in XMIT queue */
/* SLIP interface statistics. */
- unsigned long rx_packets; /* inbound frames counter */
- unsigned long tx_packets; /* outbound frames counter */
- unsigned long rx_bytes; /* inbound byte counte */
- unsigned long tx_bytes; /* outbound byte counter */
- unsigned long rx_errors; /* Parity, etc. errors */
- unsigned long tx_errors; /* Planned stuff */
- unsigned long rx_dropped; /* No memory for skb */
- unsigned long tx_dropped; /* When MTU change */
- unsigned long rx_over_errors; /* Frame bigger than SLIP buf. */
#ifdef SL_INCLUDE_CSLIP
unsigned long tx_compressed;
unsigned long rx_compressed;
diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c
index 10cf0cbc2185..726df611ee17 100644
--- a/drivers/net/smc91x.c
+++ b/drivers/net/smc91x.c
@@ -72,6 +72,7 @@ static const char version[] =
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
+#include <linux/irq.h>
#include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/crc32.h>
diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c
index 8150ba154116..a8e5856ce882 100644
--- a/drivers/net/smsc911x.c
+++ b/drivers/net/smsc911x.c
@@ -1049,7 +1049,7 @@ static int smsc911x_poll(struct napi_struct *napi, int budget)
smsc911x_rx_readfifo(pdata, (unsigned int *)skb->head,
pktwords);
skb->protocol = eth_type_trans(skb, dev);
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
netif_receive_skb(skb);
/* Update counters */
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c
index 1636a34d95dd..cb6bcca9d541 100644
--- a/drivers/net/spider_net.c
+++ b/drivers/net/spider_net.c
@@ -1000,9 +1000,9 @@ spider_net_pass_skb_up(struct spider_net_descr *descr,
!(data_error & SPIDER_NET_DATA_ERR_CKSUM_MASK))
skb->ip_summed = CHECKSUM_UNNECESSARY;
else
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
} else
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
if (data_status & SPIDER_NET_VLAN_PACKET) {
/* further enhancements: HW-accel VLAN
diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c
index a42b6873370b..4adf12422787 100644
--- a/drivers/net/starfire.c
+++ b/drivers/net/starfire.c
@@ -148,7 +148,7 @@ static int full_duplex[MAX_UNITS] = {0, };
* This SUCKS.
* We need a much better method to determine if dma_addr_t is 64-bit.
*/
-#if (defined(__i386__) && defined(CONFIG_HIGHMEM64G)) || defined(__x86_64__) || defined (__ia64__) || defined(__alpha__) || defined(__mips64__) || (defined(__mips__) && defined(CONFIG_HIGHMEM) && defined(CONFIG_64BIT_PHYS_ADDR))
+#if (defined(__i386__) && defined(CONFIG_HIGHMEM64G)) || defined(__x86_64__) || defined (__ia64__) || defined(__alpha__) || defined(__mips64__) || (defined(__mips__) && defined(CONFIG_HIGHMEM) && defined(CONFIG_64BIT_PHYS_ADDR)) || (defined(__powerpc64__) || defined(CONFIG_PHYS_64BIT))
/* 64-bit dma_addr_t */
#define ADDR_64BITS /* This chip uses 64 bit addresses. */
#define netdrv_addr_t __le64
@@ -302,7 +302,7 @@ enum chipset {
};
static DEFINE_PCI_DEVICE_TABLE(starfire_pci_tbl) = {
- { 0x9004, 0x6915, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_6915 },
+ { PCI_VDEVICE(ADAPTEC, 0x6915), CH_6915 },
{ 0, }
};
MODULE_DEVICE_TABLE(pci, starfire_pci_tbl);
@@ -2078,11 +2078,7 @@ static int __init starfire_init (void)
printk(KERN_INFO DRV_NAME ": polling (NAPI) enabled\n");
#endif
- /* we can do this test only at run-time... sigh */
- if (sizeof(dma_addr_t) != sizeof(netdrv_addr_t)) {
- printk("This driver has dma_addr_t issues, please send email to maintainer\n");
- return -ENODEV;
- }
+ BUILD_BUG_ON(sizeof(dma_addr_t) != sizeof(netdrv_addr_t));
return pci_register_driver(&starfire_driver);
}
diff --git a/drivers/net/stmmac/Kconfig b/drivers/net/stmmac/Kconfig
index eb63d44748a7..7df7df4e79c5 100644
--- a/drivers/net/stmmac/Kconfig
+++ b/drivers/net/stmmac/Kconfig
@@ -3,10 +3,10 @@ config STMMAC_ETH
select MII
select PHYLIB
select CRC32
- depends on NETDEVICES && CPU_SUBTYPE_ST40
+ depends on NETDEVICES && HAS_IOMEM
help
This is the driver for the Ethernet IPs are built around a
- Synopsys IP Core and fully tested on the STMicroelectronics
+ Synopsys IP Core and only tested on the STMicroelectronics
platforms.
if STMMAC_ETH
@@ -32,6 +32,7 @@ config STMMAC_DUAL_MAC
config STMMAC_TIMER
bool "STMMAC Timer optimisation"
default n
+ depends on RTC_HCTOSYS_DEVICE
help
Use an external timer for mitigating the number of network
interrupts. Currently, for SH architectures, it is possible
diff --git a/drivers/net/stmmac/common.h b/drivers/net/stmmac/common.h
index 66b9da0260fe..375ea193e139 100644
--- a/drivers/net/stmmac/common.h
+++ b/drivers/net/stmmac/common.h
@@ -102,8 +102,6 @@ struct stmmac_extra_stats {
#define SF_DMA_MODE 1 /* DMA STORE-AND-FORWARD Operation Mode */
-#define HW_CSUM 1
-#define NO_HW_CSUM 0
enum rx_frame_status { /* IPC status */
good_frame = 0,
discard_frame = 1,
@@ -167,7 +165,7 @@ struct stmmac_desc_ops {
int (*get_tx_ls) (struct dma_desc *p);
/* Return the transmit status looking at the TDES1 */
int (*tx_status) (void *data, struct stmmac_extra_stats *x,
- struct dma_desc *p, unsigned long ioaddr);
+ struct dma_desc *p, void __iomem *ioaddr);
/* Get the buffer size from the descriptor */
int (*get_tx_len) (struct dma_desc *p);
/* Handle extra events on specific interrupts hw dependent */
@@ -182,44 +180,46 @@ struct stmmac_desc_ops {
struct stmmac_dma_ops {
/* DMA core initialization */
- int (*init) (unsigned long ioaddr, int pbl, u32 dma_tx, u32 dma_rx);
+ int (*init) (void __iomem *ioaddr, int pbl, u32 dma_tx, u32 dma_rx);
/* Dump DMA registers */
- void (*dump_regs) (unsigned long ioaddr);
+ void (*dump_regs) (void __iomem *ioaddr);
/* Set tx/rx threshold in the csr6 register
* An invalid value enables the store-and-forward mode */
- void (*dma_mode) (unsigned long ioaddr, int txmode, int rxmode);
+ void (*dma_mode) (void __iomem *ioaddr, int txmode, int rxmode);
/* To track extra statistic (if supported) */
void (*dma_diagnostic_fr) (void *data, struct stmmac_extra_stats *x,
- unsigned long ioaddr);
- void (*enable_dma_transmission) (unsigned long ioaddr);
- void (*enable_dma_irq) (unsigned long ioaddr);
- void (*disable_dma_irq) (unsigned long ioaddr);
- void (*start_tx) (unsigned long ioaddr);
- void (*stop_tx) (unsigned long ioaddr);
- void (*start_rx) (unsigned long ioaddr);
- void (*stop_rx) (unsigned long ioaddr);
- int (*dma_interrupt) (unsigned long ioaddr,
+ void __iomem *ioaddr);
+ void (*enable_dma_transmission) (void __iomem *ioaddr);
+ void (*enable_dma_irq) (void __iomem *ioaddr);
+ void (*disable_dma_irq) (void __iomem *ioaddr);
+ void (*start_tx) (void __iomem *ioaddr);
+ void (*stop_tx) (void __iomem *ioaddr);
+ void (*start_rx) (void __iomem *ioaddr);
+ void (*stop_rx) (void __iomem *ioaddr);
+ int (*dma_interrupt) (void __iomem *ioaddr,
struct stmmac_extra_stats *x);
};
struct stmmac_ops {
/* MAC core initialization */
- void (*core_init) (unsigned long ioaddr) ____cacheline_aligned;
+ void (*core_init) (void __iomem *ioaddr) ____cacheline_aligned;
+ /* Support checksum offload engine */
+ int (*rx_coe) (void __iomem *ioaddr);
/* Dump MAC registers */
- void (*dump_regs) (unsigned long ioaddr);
+ void (*dump_regs) (void __iomem *ioaddr);
/* Handle extra events on specific interrupts hw dependent */
- void (*host_irq_status) (unsigned long ioaddr);
+ void (*host_irq_status) (void __iomem *ioaddr);
/* Multicast filter setting */
void (*set_filter) (struct net_device *dev);
/* Flow control setting */
- void (*flow_ctrl) (unsigned long ioaddr, unsigned int duplex,
+ void (*flow_ctrl) (void __iomem *ioaddr, unsigned int duplex,
unsigned int fc, unsigned int pause_time);
/* Set power management mode (e.g. magic frame) */
- void (*pmt) (unsigned long ioaddr, unsigned long mode);
+ void (*pmt) (void __iomem *ioaddr, unsigned long mode);
/* Set/Get Unicast MAC addresses */
- void (*set_umac_addr) (unsigned long ioaddr, unsigned char *addr,
+ void (*set_umac_addr) (void __iomem *ioaddr, unsigned char *addr,
unsigned int reg_n);
- void (*get_umac_addr) (unsigned long ioaddr, unsigned char *addr,
+ void (*get_umac_addr) (void __iomem *ioaddr, unsigned char *addr,
unsigned int reg_n);
};
@@ -235,19 +235,18 @@ struct mii_regs {
};
struct mac_device_info {
- struct stmmac_ops *mac;
- struct stmmac_desc_ops *desc;
- struct stmmac_dma_ops *dma;
- unsigned int pmt; /* support Power-Down */
+ const struct stmmac_ops *mac;
+ const struct stmmac_desc_ops *desc;
+ const struct stmmac_dma_ops *dma;
struct mii_regs mii; /* MII register Addresses */
struct mac_link link;
};
-struct mac_device_info *dwmac1000_setup(unsigned long addr);
-struct mac_device_info *dwmac100_setup(unsigned long addr);
+struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr);
+struct mac_device_info *dwmac100_setup(void __iomem *ioaddr);
-extern void stmmac_set_mac_addr(unsigned long ioaddr, u8 addr[6],
+extern void stmmac_set_mac_addr(void __iomem *ioaddr, u8 addr[6],
unsigned int high, unsigned int low);
-extern void stmmac_get_mac_addr(unsigned long ioaddr, unsigned char *addr,
+extern void stmmac_get_mac_addr(void __iomem *ioaddr, unsigned char *addr,
unsigned int high, unsigned int low);
-extern void dwmac_dma_flush_tx_fifo(unsigned long ioaddr);
+extern void dwmac_dma_flush_tx_fifo(void __iomem *ioaddr);
diff --git a/drivers/net/stmmac/dwmac100.h b/drivers/net/stmmac/dwmac100.h
index 97956cbf1cb4..7c6d857a9cc7 100644
--- a/drivers/net/stmmac/dwmac100.h
+++ b/drivers/net/stmmac/dwmac100.h
@@ -118,4 +118,4 @@ enum ttc_control {
#define DMA_MISSED_FRAME_OVE_M 0x00010000 /* Missed Frame Overflow */
#define DMA_MISSED_FRAME_M_CNTR 0x0000ffff /* Missed Frame Couinter */
-extern struct stmmac_dma_ops dwmac100_dma_ops;
+extern const struct stmmac_dma_ops dwmac100_dma_ops;
diff --git a/drivers/net/stmmac/dwmac1000.h b/drivers/net/stmmac/dwmac1000.h
index 8b20b19971cb..cfcef0ea0fa5 100644
--- a/drivers/net/stmmac/dwmac1000.h
+++ b/drivers/net/stmmac/dwmac1000.h
@@ -99,7 +99,7 @@ enum inter_frame_gap {
#define GMAC_CONTROL_RE 0x00000004 /* Receiver Enable */
#define GMAC_CORE_INIT (GMAC_CONTROL_JD | GMAC_CONTROL_PS | GMAC_CONTROL_ACS | \
- GMAC_CONTROL_IPC | GMAC_CONTROL_JE | GMAC_CONTROL_BE)
+ GMAC_CONTROL_JE | GMAC_CONTROL_BE)
/* GMAC Frame Filter defines */
#define GMAC_FRAME_FILTER_PR 0x00000001 /* Promiscuous Mode */
@@ -205,4 +205,4 @@ enum rtc_control {
#define GMAC_MMC_TX_INTR 0x108
#define GMAC_MMC_RX_CSUM_OFFLOAD 0x208
-extern struct stmmac_dma_ops dwmac1000_dma_ops;
+extern const struct stmmac_dma_ops dwmac1000_dma_ops;
diff --git a/drivers/net/stmmac/dwmac1000_core.c b/drivers/net/stmmac/dwmac1000_core.c
index 2b2f5c8caf1c..6ae4c3f4c63c 100644
--- a/drivers/net/stmmac/dwmac1000_core.c
+++ b/drivers/net/stmmac/dwmac1000_core.c
@@ -30,7 +30,7 @@
#include <linux/slab.h>
#include "dwmac1000.h"
-static void dwmac1000_core_init(unsigned long ioaddr)
+static void dwmac1000_core_init(void __iomem *ioaddr)
{
u32 value = readl(ioaddr + GMAC_CONTROL);
value |= GMAC_CORE_INIT;
@@ -50,10 +50,22 @@ static void dwmac1000_core_init(unsigned long ioaddr)
#endif
}
-static void dwmac1000_dump_regs(unsigned long ioaddr)
+static int dwmac1000_rx_coe_supported(void __iomem *ioaddr)
+{
+ u32 value = readl(ioaddr + GMAC_CONTROL);
+
+ value |= GMAC_CONTROL_IPC;
+ writel(value, ioaddr + GMAC_CONTROL);
+
+ value = readl(ioaddr + GMAC_CONTROL);
+
+ return !!(value & GMAC_CONTROL_IPC);
+}
+
+static void dwmac1000_dump_regs(void __iomem *ioaddr)
{
int i;
- pr_info("\tDWMAC1000 regs (base addr = 0x%8x)\n", (unsigned int)ioaddr);
+ pr_info("\tDWMAC1000 regs (base addr = 0x%p)\n", ioaddr);
for (i = 0; i < 55; i++) {
int offset = i * 4;
@@ -62,14 +74,14 @@ static void dwmac1000_dump_regs(unsigned long ioaddr)
}
}
-static void dwmac1000_set_umac_addr(unsigned long ioaddr, unsigned char *addr,
+static void dwmac1000_set_umac_addr(void __iomem *ioaddr, unsigned char *addr,
unsigned int reg_n)
{
stmmac_set_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n),
GMAC_ADDR_LOW(reg_n));
}
-static void dwmac1000_get_umac_addr(unsigned long ioaddr, unsigned char *addr,
+static void dwmac1000_get_umac_addr(void __iomem *ioaddr, unsigned char *addr,
unsigned int reg_n)
{
stmmac_get_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n),
@@ -78,7 +90,7 @@ static void dwmac1000_get_umac_addr(unsigned long ioaddr, unsigned char *addr,
static void dwmac1000_set_filter(struct net_device *dev)
{
- unsigned long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = (void __iomem *) dev->base_addr;
unsigned int value = 0;
CHIP_DBG(KERN_INFO "%s: # mcasts %d, # unicast %d\n",
@@ -139,7 +151,7 @@ static void dwmac1000_set_filter(struct net_device *dev)
readl(ioaddr + GMAC_HASH_HIGH), readl(ioaddr + GMAC_HASH_LOW));
}
-static void dwmac1000_flow_ctrl(unsigned long ioaddr, unsigned int duplex,
+static void dwmac1000_flow_ctrl(void __iomem *ioaddr, unsigned int duplex,
unsigned int fc, unsigned int pause_time)
{
unsigned int flow = 0;
@@ -162,7 +174,7 @@ static void dwmac1000_flow_ctrl(unsigned long ioaddr, unsigned int duplex,
writel(flow, ioaddr + GMAC_FLOW_CTRL);
}
-static void dwmac1000_pmt(unsigned long ioaddr, unsigned long mode)
+static void dwmac1000_pmt(void __iomem *ioaddr, unsigned long mode)
{
unsigned int pmt = 0;
@@ -178,7 +190,7 @@ static void dwmac1000_pmt(unsigned long ioaddr, unsigned long mode)
}
-static void dwmac1000_irq_status(unsigned long ioaddr)
+static void dwmac1000_irq_status(void __iomem *ioaddr)
{
u32 intr_status = readl(ioaddr + GMAC_INT_STATUS);
@@ -200,8 +212,9 @@ static void dwmac1000_irq_status(unsigned long ioaddr)
}
}
-struct stmmac_ops dwmac1000_ops = {
+static const struct stmmac_ops dwmac1000_ops = {
.core_init = dwmac1000_core_init,
+ .rx_coe = dwmac1000_rx_coe_supported,
.dump_regs = dwmac1000_dump_regs,
.host_irq_status = dwmac1000_irq_status,
.set_filter = dwmac1000_set_filter,
@@ -211,7 +224,7 @@ struct stmmac_ops dwmac1000_ops = {
.get_umac_addr = dwmac1000_get_umac_addr,
};
-struct mac_device_info *dwmac1000_setup(unsigned long ioaddr)
+struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr)
{
struct mac_device_info *mac;
u32 uid = readl(ioaddr + GMAC_VERSION);
@@ -226,7 +239,6 @@ struct mac_device_info *dwmac1000_setup(unsigned long ioaddr)
mac->mac = &dwmac1000_ops;
mac->dma = &dwmac1000_dma_ops;
- mac->pmt = PMT_SUPPORTED;
mac->link.port = GMAC_CONTROL_PS;
mac->link.duplex = GMAC_CONTROL_DM;
mac->link.speed = GMAC_CONTROL_FES;
diff --git a/drivers/net/stmmac/dwmac1000_dma.c b/drivers/net/stmmac/dwmac1000_dma.c
index 415805057cb0..2c47712d45d0 100644
--- a/drivers/net/stmmac/dwmac1000_dma.c
+++ b/drivers/net/stmmac/dwmac1000_dma.c
@@ -29,14 +29,22 @@
#include "dwmac1000.h"
#include "dwmac_dma.h"
-static int dwmac1000_dma_init(unsigned long ioaddr, int pbl, u32 dma_tx,
+static int dwmac1000_dma_init(void __iomem *ioaddr, int pbl, u32 dma_tx,
u32 dma_rx)
{
u32 value = readl(ioaddr + DMA_BUS_MODE);
+ int limit;
+
/* DMA SW reset */
value |= DMA_BUS_MODE_SFT_RESET;
writel(value, ioaddr + DMA_BUS_MODE);
- do {} while ((readl(ioaddr + DMA_BUS_MODE) & DMA_BUS_MODE_SFT_RESET));
+ limit = 15000;
+ while (limit--) {
+ if (!(readl(ioaddr + DMA_BUS_MODE) & DMA_BUS_MODE_SFT_RESET))
+ break;
+ }
+ if (limit < 0)
+ return -EBUSY;
value = /* DMA_BUS_MODE_FB | */ DMA_BUS_MODE_4PBL |
((pbl << DMA_BUS_MODE_PBL_SHIFT) |
@@ -58,7 +66,7 @@ static int dwmac1000_dma_init(unsigned long ioaddr, int pbl, u32 dma_tx,
return 0;
}
-static void dwmac1000_dma_operation_mode(unsigned long ioaddr, int txmode,
+static void dwmac1000_dma_operation_mode(void __iomem *ioaddr, int txmode,
int rxmode)
{
u32 csr6 = readl(ioaddr + DMA_CONTROL);
@@ -111,12 +119,12 @@ static void dwmac1000_dma_operation_mode(unsigned long ioaddr, int txmode,
/* Not yet implemented --- no RMON module */
static void dwmac1000_dma_diagnostic_fr(void *data,
- struct stmmac_extra_stats *x, unsigned long ioaddr)
+ struct stmmac_extra_stats *x, void __iomem *ioaddr)
{
return;
}
-static void dwmac1000_dump_dma_regs(unsigned long ioaddr)
+static void dwmac1000_dump_dma_regs(void __iomem *ioaddr)
{
int i;
pr_info(" DMA registers\n");
@@ -130,7 +138,7 @@ static void dwmac1000_dump_dma_regs(unsigned long ioaddr)
}
}
-struct stmmac_dma_ops dwmac1000_dma_ops = {
+const struct stmmac_dma_ops dwmac1000_dma_ops = {
.init = dwmac1000_dma_init,
.dump_regs = dwmac1000_dump_dma_regs,
.dma_mode = dwmac1000_dma_operation_mode,
diff --git a/drivers/net/stmmac/dwmac100_core.c b/drivers/net/stmmac/dwmac100_core.c
index 2fb165fa2ba0..c724fc36a24f 100644
--- a/drivers/net/stmmac/dwmac100_core.c
+++ b/drivers/net/stmmac/dwmac100_core.c
@@ -31,7 +31,7 @@
#include <linux/crc32.h>
#include "dwmac100.h"
-static void dwmac100_core_init(unsigned long ioaddr)
+static void dwmac100_core_init(void __iomem *ioaddr)
{
u32 value = readl(ioaddr + MAC_CONTROL);
@@ -42,12 +42,17 @@ static void dwmac100_core_init(unsigned long ioaddr)
#endif
}
-static void dwmac100_dump_mac_regs(unsigned long ioaddr)
+static int dwmac100_rx_coe_supported(void __iomem *ioaddr)
+{
+ return 0;
+}
+
+static void dwmac100_dump_mac_regs(void __iomem *ioaddr)
{
pr_info("\t----------------------------------------------\n"
- "\t DWMAC 100 CSR (base addr = 0x%8x)\n"
+ "\t DWMAC 100 CSR (base addr = 0x%p)\n"
"\t----------------------------------------------\n",
- (unsigned int)ioaddr);
+ ioaddr);
pr_info("\tcontrol reg (offset 0x%x): 0x%08x\n", MAC_CONTROL,
readl(ioaddr + MAC_CONTROL));
pr_info("\taddr HI (offset 0x%x): 0x%08x\n ", MAC_ADDR_HIGH,
@@ -77,18 +82,18 @@ static void dwmac100_dump_mac_regs(unsigned long ioaddr)
MMC_LOW_INTR_MASK, readl(ioaddr + MMC_LOW_INTR_MASK));
}
-static void dwmac100_irq_status(unsigned long ioaddr)
+static void dwmac100_irq_status(void __iomem *ioaddr)
{
return;
}
-static void dwmac100_set_umac_addr(unsigned long ioaddr, unsigned char *addr,
+static void dwmac100_set_umac_addr(void __iomem *ioaddr, unsigned char *addr,
unsigned int reg_n)
{
stmmac_set_mac_addr(ioaddr, addr, MAC_ADDR_HIGH, MAC_ADDR_LOW);
}
-static void dwmac100_get_umac_addr(unsigned long ioaddr, unsigned char *addr,
+static void dwmac100_get_umac_addr(void __iomem *ioaddr, unsigned char *addr,
unsigned int reg_n)
{
stmmac_get_mac_addr(ioaddr, addr, MAC_ADDR_HIGH, MAC_ADDR_LOW);
@@ -96,7 +101,7 @@ static void dwmac100_get_umac_addr(unsigned long ioaddr, unsigned char *addr,
static void dwmac100_set_filter(struct net_device *dev)
{
- unsigned long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = (void __iomem *) dev->base_addr;
u32 value = readl(ioaddr + MAC_CONTROL);
if (dev->flags & IFF_PROMISC) {
@@ -145,7 +150,7 @@ static void dwmac100_set_filter(struct net_device *dev)
readl(ioaddr + MAC_HASH_HIGH), readl(ioaddr + MAC_HASH_LOW));
}
-static void dwmac100_flow_ctrl(unsigned long ioaddr, unsigned int duplex,
+static void dwmac100_flow_ctrl(void __iomem *ioaddr, unsigned int duplex,
unsigned int fc, unsigned int pause_time)
{
unsigned int flow = MAC_FLOW_CTRL_ENABLE;
@@ -158,13 +163,14 @@ static void dwmac100_flow_ctrl(unsigned long ioaddr, unsigned int duplex,
/* No PMT module supported for this Ethernet Controller.
* Tested on ST platforms only.
*/
-static void dwmac100_pmt(unsigned long ioaddr, unsigned long mode)
+static void dwmac100_pmt(void __iomem *ioaddr, unsigned long mode)
{
return;
}
-struct stmmac_ops dwmac100_ops = {
+static const struct stmmac_ops dwmac100_ops = {
.core_init = dwmac100_core_init,
+ .rx_coe = dwmac100_rx_coe_supported,
.dump_regs = dwmac100_dump_mac_regs,
.host_irq_status = dwmac100_irq_status,
.set_filter = dwmac100_set_filter,
@@ -174,7 +180,7 @@ struct stmmac_ops dwmac100_ops = {
.get_umac_addr = dwmac100_get_umac_addr,
};
-struct mac_device_info *dwmac100_setup(unsigned long ioaddr)
+struct mac_device_info *dwmac100_setup(void __iomem *ioaddr)
{
struct mac_device_info *mac;
@@ -187,7 +193,6 @@ struct mac_device_info *dwmac100_setup(unsigned long ioaddr)
mac->mac = &dwmac100_ops;
mac->dma = &dwmac100_dma_ops;
- mac->pmt = PMT_NOT_SUPPORTED;
mac->link.port = MAC_CONTROL_PS;
mac->link.duplex = MAC_CONTROL_F;
mac->link.speed = 0;
diff --git a/drivers/net/stmmac/dwmac100_dma.c b/drivers/net/stmmac/dwmac100_dma.c
index 2fece7b72727..e3e224b7d9e2 100644
--- a/drivers/net/stmmac/dwmac100_dma.c
+++ b/drivers/net/stmmac/dwmac100_dma.c
@@ -31,14 +31,22 @@
#include "dwmac100.h"
#include "dwmac_dma.h"
-static int dwmac100_dma_init(unsigned long ioaddr, int pbl, u32 dma_tx,
+static int dwmac100_dma_init(void __iomem *ioaddr, int pbl, u32 dma_tx,
u32 dma_rx)
{
u32 value = readl(ioaddr + DMA_BUS_MODE);
+ int limit;
+
/* DMA SW reset */
value |= DMA_BUS_MODE_SFT_RESET;
writel(value, ioaddr + DMA_BUS_MODE);
- do {} while ((readl(ioaddr + DMA_BUS_MODE) & DMA_BUS_MODE_SFT_RESET));
+ limit = 15000;
+ while (limit--) {
+ if (!(readl(ioaddr + DMA_BUS_MODE) & DMA_BUS_MODE_SFT_RESET))
+ break;
+ }
+ if (limit < 0)
+ return -EBUSY;
/* Enable Application Access by writing to DMA CSR0 */
writel(DMA_BUS_MODE_DEFAULT | (pbl << DMA_BUS_MODE_PBL_SHIFT),
@@ -58,7 +66,7 @@ static int dwmac100_dma_init(unsigned long ioaddr, int pbl, u32 dma_tx,
/* Store and Forward capability is not used at all..
* The transmit threshold can be programmed by
* setting the TTC bits in the DMA control register.*/
-static void dwmac100_dma_operation_mode(unsigned long ioaddr, int txmode,
+static void dwmac100_dma_operation_mode(void __iomem *ioaddr, int txmode,
int rxmode)
{
u32 csr6 = readl(ioaddr + DMA_CONTROL);
@@ -73,7 +81,7 @@ static void dwmac100_dma_operation_mode(unsigned long ioaddr, int txmode,
writel(csr6, ioaddr + DMA_CONTROL);
}
-static void dwmac100_dump_dma_regs(unsigned long ioaddr)
+static void dwmac100_dump_dma_regs(void __iomem *ioaddr)
{
int i;
@@ -91,7 +99,7 @@ static void dwmac100_dump_dma_regs(unsigned long ioaddr)
/* DMA controller has two counters to track the number of
* the receive missed frames. */
static void dwmac100_dma_diagnostic_fr(void *data, struct stmmac_extra_stats *x,
- unsigned long ioaddr)
+ void __iomem *ioaddr)
{
struct net_device_stats *stats = (struct net_device_stats *)data;
u32 csr8 = readl(ioaddr + DMA_MISSED_FRAME_CTR);
@@ -118,7 +126,7 @@ static void dwmac100_dma_diagnostic_fr(void *data, struct stmmac_extra_stats *x,
}
}
-struct stmmac_dma_ops dwmac100_dma_ops = {
+const struct stmmac_dma_ops dwmac100_dma_ops = {
.init = dwmac100_dma_init,
.dump_regs = dwmac100_dump_dma_regs,
.dma_mode = dwmac100_dma_operation_mode,
diff --git a/drivers/net/stmmac/dwmac_dma.h b/drivers/net/stmmac/dwmac_dma.h
index 7b815a1b7b8c..da3f5ccf83d3 100644
--- a/drivers/net/stmmac/dwmac_dma.h
+++ b/drivers/net/stmmac/dwmac_dma.h
@@ -97,12 +97,12 @@
#define DMA_STATUS_TI 0x00000001 /* Transmit Interrupt */
#define DMA_CONTROL_FTF 0x00100000 /* Flush transmit FIFO */
-extern void dwmac_enable_dma_transmission(unsigned long ioaddr);
-extern void dwmac_enable_dma_irq(unsigned long ioaddr);
-extern void dwmac_disable_dma_irq(unsigned long ioaddr);
-extern void dwmac_dma_start_tx(unsigned long ioaddr);
-extern void dwmac_dma_stop_tx(unsigned long ioaddr);
-extern void dwmac_dma_start_rx(unsigned long ioaddr);
-extern void dwmac_dma_stop_rx(unsigned long ioaddr);
-extern int dwmac_dma_interrupt(unsigned long ioaddr,
+extern void dwmac_enable_dma_transmission(void __iomem *ioaddr);
+extern void dwmac_enable_dma_irq(void __iomem *ioaddr);
+extern void dwmac_disable_dma_irq(void __iomem *ioaddr);
+extern void dwmac_dma_start_tx(void __iomem *ioaddr);
+extern void dwmac_dma_stop_tx(void __iomem *ioaddr);
+extern void dwmac_dma_start_rx(void __iomem *ioaddr);
+extern void dwmac_dma_stop_rx(void __iomem *ioaddr);
+extern int dwmac_dma_interrupt(void __iomem *ioaddr,
struct stmmac_extra_stats *x);
diff --git a/drivers/net/stmmac/dwmac_lib.c b/drivers/net/stmmac/dwmac_lib.c
index a85415216ef4..d65fab1ba790 100644
--- a/drivers/net/stmmac/dwmac_lib.c
+++ b/drivers/net/stmmac/dwmac_lib.c
@@ -32,43 +32,43 @@
#endif
/* CSR1 enables the transmit DMA to check for new descriptor */
-void dwmac_enable_dma_transmission(unsigned long ioaddr)
+void dwmac_enable_dma_transmission(void __iomem *ioaddr)
{
writel(1, ioaddr + DMA_XMT_POLL_DEMAND);
}
-void dwmac_enable_dma_irq(unsigned long ioaddr)
+void dwmac_enable_dma_irq(void __iomem *ioaddr)
{
writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA);
}
-void dwmac_disable_dma_irq(unsigned long ioaddr)
+void dwmac_disable_dma_irq(void __iomem *ioaddr)
{
writel(0, ioaddr + DMA_INTR_ENA);
}
-void dwmac_dma_start_tx(unsigned long ioaddr)
+void dwmac_dma_start_tx(void __iomem *ioaddr)
{
u32 value = readl(ioaddr + DMA_CONTROL);
value |= DMA_CONTROL_ST;
writel(value, ioaddr + DMA_CONTROL);
}
-void dwmac_dma_stop_tx(unsigned long ioaddr)
+void dwmac_dma_stop_tx(void __iomem *ioaddr)
{
u32 value = readl(ioaddr + DMA_CONTROL);
value &= ~DMA_CONTROL_ST;
writel(value, ioaddr + DMA_CONTROL);
}
-void dwmac_dma_start_rx(unsigned long ioaddr)
+void dwmac_dma_start_rx(void __iomem *ioaddr)
{
u32 value = readl(ioaddr + DMA_CONTROL);
value |= DMA_CONTROL_SR;
writel(value, ioaddr + DMA_CONTROL);
}
-void dwmac_dma_stop_rx(unsigned long ioaddr)
+void dwmac_dma_stop_rx(void __iomem *ioaddr)
{
u32 value = readl(ioaddr + DMA_CONTROL);
value &= ~DMA_CONTROL_SR;
@@ -145,7 +145,7 @@ static void show_rx_process_state(unsigned int status)
}
#endif
-int dwmac_dma_interrupt(unsigned long ioaddr,
+int dwmac_dma_interrupt(void __iomem *ioaddr,
struct stmmac_extra_stats *x)
{
int ret = 0;
@@ -219,7 +219,7 @@ int dwmac_dma_interrupt(unsigned long ioaddr,
return ret;
}
-void dwmac_dma_flush_tx_fifo(unsigned long ioaddr)
+void dwmac_dma_flush_tx_fifo(void __iomem *ioaddr)
{
u32 csr6 = readl(ioaddr + DMA_CONTROL);
writel((csr6 | DMA_CONTROL_FTF), ioaddr + DMA_CONTROL);
@@ -227,7 +227,7 @@ void dwmac_dma_flush_tx_fifo(unsigned long ioaddr)
do {} while ((readl(ioaddr + DMA_CONTROL) & DMA_CONTROL_FTF));
}
-void stmmac_set_mac_addr(unsigned long ioaddr, u8 addr[6],
+void stmmac_set_mac_addr(void __iomem *ioaddr, u8 addr[6],
unsigned int high, unsigned int low)
{
unsigned long data;
@@ -238,7 +238,7 @@ void stmmac_set_mac_addr(unsigned long ioaddr, u8 addr[6],
writel(data, ioaddr + low);
}
-void stmmac_get_mac_addr(unsigned long ioaddr, unsigned char *addr,
+void stmmac_get_mac_addr(void __iomem *ioaddr, unsigned char *addr,
unsigned int high, unsigned int low)
{
unsigned int hi_addr, lo_addr;
diff --git a/drivers/net/stmmac/enh_desc.c b/drivers/net/stmmac/enh_desc.c
index f612f986a7e1..e5dfb6a30182 100644
--- a/drivers/net/stmmac/enh_desc.c
+++ b/drivers/net/stmmac/enh_desc.c
@@ -25,7 +25,7 @@
#include "common.h"
static int enh_desc_get_tx_status(void *data, struct stmmac_extra_stats *x,
- struct dma_desc *p, unsigned long ioaddr)
+ struct dma_desc *p, void __iomem *ioaddr)
{
int ret = 0;
struct net_device_stats *stats = (struct net_device_stats *)data;
@@ -284,7 +284,7 @@ static void enh_desc_release_tx_desc(struct dma_desc *p)
{
int ter = p->des01.etx.end_ring;
- memset(p, 0, sizeof(struct dma_desc));
+ memset(p, 0, offsetof(struct dma_desc, des2));
p->des01.etx.end_ring = ter;
}
@@ -318,7 +318,7 @@ static int enh_desc_get_rx_frame_len(struct dma_desc *p)
return p->des01.erx.frame_length;
}
-struct stmmac_desc_ops enh_desc_ops = {
+const struct stmmac_desc_ops enh_desc_ops = {
.tx_status = enh_desc_get_tx_status,
.rx_status = enh_desc_get_rx_status,
.get_tx_len = enh_desc_get_tx_len,
diff --git a/drivers/net/stmmac/norm_desc.c b/drivers/net/stmmac/norm_desc.c
index 31ad53643792..cd0cc76f7a1c 100644
--- a/drivers/net/stmmac/norm_desc.c
+++ b/drivers/net/stmmac/norm_desc.c
@@ -25,7 +25,7 @@
#include "common.h"
static int ndesc_get_tx_status(void *data, struct stmmac_extra_stats *x,
- struct dma_desc *p, unsigned long ioaddr)
+ struct dma_desc *p, void __iomem *ioaddr)
{
int ret = 0;
struct net_device_stats *stats = (struct net_device_stats *)data;
@@ -174,22 +174,7 @@ static void ndesc_release_tx_desc(struct dma_desc *p)
{
int ter = p->des01.tx.end_ring;
- /* clean field used within the xmit */
- p->des01.tx.first_segment = 0;
- p->des01.tx.last_segment = 0;
- p->des01.tx.buffer1_size = 0;
-
- /* clean status reported */
- p->des01.tx.error_summary = 0;
- p->des01.tx.underflow_error = 0;
- p->des01.tx.no_carrier = 0;
- p->des01.tx.loss_carrier = 0;
- p->des01.tx.excessive_deferral = 0;
- p->des01.tx.excessive_collisions = 0;
- p->des01.tx.late_collision = 0;
- p->des01.tx.heartbeat_fail = 0;
- p->des01.tx.deferred = 0;
-
+ memset(p, 0, offsetof(struct dma_desc, des2));
/* set termination field */
p->des01.tx.end_ring = ter;
}
@@ -217,7 +202,7 @@ static int ndesc_get_rx_frame_len(struct dma_desc *p)
return p->des01.rx.frame_length;
}
-struct stmmac_desc_ops ndesc_ops = {
+const struct stmmac_desc_ops ndesc_ops = {
.tx_status = ndesc_get_tx_status,
.rx_status = ndesc_get_rx_status,
.get_tx_len = ndesc_get_tx_len,
diff --git a/drivers/net/stmmac/stmmac.h b/drivers/net/stmmac/stmmac.h
index ebebc644b1b8..79bdc2e13224 100644
--- a/drivers/net/stmmac/stmmac.h
+++ b/drivers/net/stmmac/stmmac.h
@@ -21,6 +21,7 @@
*******************************************************************************/
#define DRV_MODULE_VERSION "Apr_2010"
+#include <linux/platform_device.h>
#include <linux/stmmac.h>
#include "common.h"
@@ -50,10 +51,10 @@ struct stmmac_priv {
int is_gmac;
dma_addr_t dma_rx_phy;
unsigned int dma_rx_size;
- int rx_csum;
unsigned int dma_buf_sz;
struct device *device;
struct mac_device_info *hw;
+ void __iomem *ioaddr;
struct stmmac_extra_stats xstats;
struct napi_struct napi;
@@ -65,7 +66,7 @@ struct stmmac_priv {
int phy_mask;
int (*phy_reset) (void *priv);
void (*fix_mac_speed) (void *priv, unsigned int speed);
- void (*bus_setup)(unsigned long ioaddr);
+ void (*bus_setup)(void __iomem *ioaddr);
void *bsp_priv;
int phy_irq;
@@ -76,6 +77,7 @@ struct stmmac_priv {
unsigned int flow_ctrl;
unsigned int pause;
struct mii_bus *mii;
+ int mii_clk_csr;
u32 msg_enable;
spinlock_t lock;
@@ -89,6 +91,9 @@ struct stmmac_priv {
struct vlan_group *vlgrp;
#endif
int enh_desc;
+ int rx_coe;
+ int bugged_jumbo;
+ int no_csum_insertion;
};
#ifdef CONFIG_STM_DRIVERS
@@ -116,5 +121,5 @@ static inline int stmmac_claim_resource(struct platform_device *pdev)
extern int stmmac_mdio_unregister(struct net_device *ndev);
extern int stmmac_mdio_register(struct net_device *ndev);
extern void stmmac_set_ethtool_ops(struct net_device *netdev);
-extern struct stmmac_desc_ops enh_desc_ops;
-extern struct stmmac_desc_ops ndesc_ops;
+extern const struct stmmac_desc_ops enh_desc_ops;
+extern const struct stmmac_desc_ops ndesc_ops;
diff --git a/drivers/net/stmmac/stmmac_ethtool.c b/drivers/net/stmmac/stmmac_ethtool.c
index f080509923f0..6d65482e789a 100644
--- a/drivers/net/stmmac/stmmac_ethtool.c
+++ b/drivers/net/stmmac/stmmac_ethtool.c
@@ -89,8 +89,8 @@ static const struct stmmac_stats stmmac_gstrings_stats[] = {
};
#define STMMAC_STATS_LEN ARRAY_SIZE(stmmac_gstrings_stats)
-void stmmac_ethtool_getdrvinfo(struct net_device *dev,
- struct ethtool_drvinfo *info)
+static void stmmac_ethtool_getdrvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *info)
{
struct stmmac_priv *priv = netdev_priv(dev);
@@ -104,7 +104,8 @@ void stmmac_ethtool_getdrvinfo(struct net_device *dev,
info->n_stats = STMMAC_STATS_LEN;
}
-int stmmac_ethtool_getsettings(struct net_device *dev, struct ethtool_cmd *cmd)
+static int stmmac_ethtool_getsettings(struct net_device *dev,
+ struct ethtool_cmd *cmd)
{
struct stmmac_priv *priv = netdev_priv(dev);
struct phy_device *phy = priv->phydev;
@@ -126,7 +127,8 @@ int stmmac_ethtool_getsettings(struct net_device *dev, struct ethtool_cmd *cmd)
return rc;
}
-int stmmac_ethtool_setsettings(struct net_device *dev, struct ethtool_cmd *cmd)
+static int stmmac_ethtool_setsettings(struct net_device *dev,
+ struct ethtool_cmd *cmd)
{
struct stmmac_priv *priv = netdev_priv(dev);
struct phy_device *phy = priv->phydev;
@@ -139,32 +141,32 @@ int stmmac_ethtool_setsettings(struct net_device *dev, struct ethtool_cmd *cmd)
return rc;
}
-u32 stmmac_ethtool_getmsglevel(struct net_device *dev)
+static u32 stmmac_ethtool_getmsglevel(struct net_device *dev)
{
struct stmmac_priv *priv = netdev_priv(dev);
return priv->msg_enable;
}
-void stmmac_ethtool_setmsglevel(struct net_device *dev, u32 level)
+static void stmmac_ethtool_setmsglevel(struct net_device *dev, u32 level)
{
struct stmmac_priv *priv = netdev_priv(dev);
priv->msg_enable = level;
}
-int stmmac_check_if_running(struct net_device *dev)
+static int stmmac_check_if_running(struct net_device *dev)
{
if (!netif_running(dev))
return -EBUSY;
return 0;
}
-int stmmac_ethtool_get_regs_len(struct net_device *dev)
+static int stmmac_ethtool_get_regs_len(struct net_device *dev)
{
return REG_SPACE_SIZE;
}
-void stmmac_ethtool_gregs(struct net_device *dev,
+static void stmmac_ethtool_gregs(struct net_device *dev,
struct ethtool_regs *regs, void *space)
{
int i;
@@ -177,25 +179,25 @@ void stmmac_ethtool_gregs(struct net_device *dev,
if (!priv->is_gmac) {
/* MAC registers */
for (i = 0; i < 12; i++)
- reg_space[i] = readl(dev->base_addr + (i * 4));
+ reg_space[i] = readl(priv->ioaddr + (i * 4));
/* DMA registers */
for (i = 0; i < 9; i++)
reg_space[i + 12] =
- readl(dev->base_addr + (DMA_BUS_MODE + (i * 4)));
- reg_space[22] = readl(dev->base_addr + DMA_CUR_TX_BUF_ADDR);
- reg_space[23] = readl(dev->base_addr + DMA_CUR_RX_BUF_ADDR);
+ readl(priv->ioaddr + (DMA_BUS_MODE + (i * 4)));
+ reg_space[22] = readl(priv->ioaddr + DMA_CUR_TX_BUF_ADDR);
+ reg_space[23] = readl(priv->ioaddr + DMA_CUR_RX_BUF_ADDR);
} else {
/* MAC registers */
for (i = 0; i < 55; i++)
- reg_space[i] = readl(dev->base_addr + (i * 4));
+ reg_space[i] = readl(priv->ioaddr + (i * 4));
/* DMA registers */
for (i = 0; i < 22; i++)
reg_space[i + 55] =
- readl(dev->base_addr + (DMA_BUS_MODE + (i * 4)));
+ readl(priv->ioaddr + (DMA_BUS_MODE + (i * 4)));
}
}
-int stmmac_ethtool_set_tx_csum(struct net_device *netdev, u32 data)
+static int stmmac_ethtool_set_tx_csum(struct net_device *netdev, u32 data)
{
if (data)
netdev->features |= NETIF_F_HW_CSUM;
@@ -205,11 +207,11 @@ int stmmac_ethtool_set_tx_csum(struct net_device *netdev, u32 data)
return 0;
}
-u32 stmmac_ethtool_get_rx_csum(struct net_device *dev)
+static u32 stmmac_ethtool_get_rx_csum(struct net_device *dev)
{
struct stmmac_priv *priv = netdev_priv(dev);
- return priv->rx_csum;
+ return priv->rx_coe;
}
static void
@@ -263,11 +265,9 @@ stmmac_set_pauseparam(struct net_device *netdev,
cmd.phy_address = phy->addr;
ret = phy_ethtool_sset(phy, &cmd);
}
- } else {
- unsigned long ioaddr = netdev->base_addr;
- priv->hw->mac->flow_ctrl(ioaddr, phy->duplex,
+ } else
+ priv->hw->mac->flow_ctrl(priv->ioaddr, phy->duplex,
priv->flow_ctrl, priv->pause);
- }
spin_unlock(&priv->lock);
return ret;
}
@@ -276,12 +276,11 @@ static void stmmac_get_ethtool_stats(struct net_device *dev,
struct ethtool_stats *dummy, u64 *data)
{
struct stmmac_priv *priv = netdev_priv(dev);
- unsigned long ioaddr = dev->base_addr;
int i;
/* Update HW stats if supported */
priv->hw->dma->dma_diagnostic_fr(&dev->stats, (void *) &priv->xstats,
- ioaddr);
+ priv->ioaddr);
for (i = 0; i < STMMAC_STATS_LEN; i++) {
char *p = (char *)priv + stmmac_gstrings_stats[i].stat_offset;
@@ -325,7 +324,7 @@ static void stmmac_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
struct stmmac_priv *priv = netdev_priv(dev);
spin_lock_irq(&priv->lock);
- if (priv->wolenabled == PMT_SUPPORTED) {
+ if (device_can_wakeup(priv->device)) {
wol->supported = WAKE_MAGIC;
wol->wolopts = priv->wolopts;
}
@@ -337,16 +336,20 @@ static int stmmac_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
struct stmmac_priv *priv = netdev_priv(dev);
u32 support = WAKE_MAGIC;
- if (priv->wolenabled == PMT_NOT_SUPPORTED)
+ if (!device_can_wakeup(priv->device))
return -EINVAL;
if (wol->wolopts & ~support)
return -EINVAL;
- if (wol->wolopts == 0)
- device_set_wakeup_enable(priv->device, 0);
- else
+ if (wol->wolopts) {
+ pr_info("stmmac: wakeup enable\n");
device_set_wakeup_enable(priv->device, 1);
+ enable_irq_wake(dev->irq);
+ } else {
+ device_set_wakeup_enable(priv->device, 0);
+ disable_irq_wake(dev->irq);
+ }
spin_lock_irq(&priv->lock);
priv->wolopts = wol->wolopts;
@@ -377,10 +380,8 @@ static struct ethtool_ops stmmac_ethtool_ops = {
.get_wol = stmmac_get_wol,
.set_wol = stmmac_set_wol,
.get_sset_count = stmmac_get_sset_count,
-#ifdef NETIF_F_TSO
.get_tso = ethtool_op_get_tso,
.set_tso = ethtool_op_set_tso,
-#endif
};
void stmmac_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c
index ea0461eb2dbe..823b9e6431d5 100644
--- a/drivers/net/stmmac/stmmac_main.c
+++ b/drivers/net/stmmac/stmmac_main.c
@@ -134,13 +134,6 @@ static int buf_sz = DMA_BUFFER_SIZE;
module_param(buf_sz, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(buf_sz, "DMA buffer size");
-/* In case of Giga ETH, we can enable/disable the COE for the
- * transmit HW checksum computation.
- * Note that, if tx csum is off in HW, SG will be still supported. */
-static int tx_coe = HW_CSUM;
-module_param(tx_coe, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(tx_coe, "GMAC COE type 2 [on/off]");
-
static const u32 default_msg_level = (NETIF_MSG_DRV | NETIF_MSG_PROBE |
NETIF_MSG_LINK | NETIF_MSG_IFUP |
NETIF_MSG_IFDOWN | NETIF_MSG_TIMER);
@@ -202,7 +195,6 @@ static void stmmac_adjust_link(struct net_device *dev)
{
struct stmmac_priv *priv = netdev_priv(dev);
struct phy_device *phydev = priv->phydev;
- unsigned long ioaddr = dev->base_addr;
unsigned long flags;
int new_state = 0;
unsigned int fc = priv->flow_ctrl, pause_time = priv->pause;
@@ -215,7 +207,7 @@ static void stmmac_adjust_link(struct net_device *dev)
spin_lock_irqsave(&priv->lock, flags);
if (phydev->link) {
- u32 ctrl = readl(ioaddr + MAC_CTRL_REG);
+ u32 ctrl = readl(priv->ioaddr + MAC_CTRL_REG);
/* Now we make sure that we can be in full duplex mode.
* If not, we operate in half-duplex mode. */
@@ -229,7 +221,7 @@ static void stmmac_adjust_link(struct net_device *dev)
}
/* Flow Control operation */
if (phydev->pause)
- priv->hw->mac->flow_ctrl(ioaddr, phydev->duplex,
+ priv->hw->mac->flow_ctrl(priv->ioaddr, phydev->duplex,
fc, pause_time);
if (phydev->speed != priv->speed) {
@@ -238,6 +230,9 @@ static void stmmac_adjust_link(struct net_device *dev)
case 1000:
if (likely(priv->is_gmac))
ctrl &= ~priv->hw->link.port;
+ if (likely(priv->fix_mac_speed))
+ priv->fix_mac_speed(priv->bsp_priv,
+ phydev->speed);
break;
case 100:
case 10:
@@ -265,7 +260,7 @@ static void stmmac_adjust_link(struct net_device *dev)
priv->speed = phydev->speed;
}
- writel(ctrl, ioaddr + MAC_CTRL_REG);
+ writel(ctrl, priv->ioaddr + MAC_CTRL_REG);
if (!priv->oldlink) {
new_state = 1;
@@ -342,7 +337,7 @@ static int stmmac_init_phy(struct net_device *dev)
return 0;
}
-static inline void stmmac_mac_enable_rx(unsigned long ioaddr)
+static inline void stmmac_mac_enable_rx(void __iomem *ioaddr)
{
u32 value = readl(ioaddr + MAC_CTRL_REG);
value |= MAC_RNABLE_RX;
@@ -350,7 +345,7 @@ static inline void stmmac_mac_enable_rx(unsigned long ioaddr)
writel(value, ioaddr + MAC_CTRL_REG);
}
-static inline void stmmac_mac_enable_tx(unsigned long ioaddr)
+static inline void stmmac_mac_enable_tx(void __iomem *ioaddr)
{
u32 value = readl(ioaddr + MAC_CTRL_REG);
value |= MAC_ENABLE_TX;
@@ -358,14 +353,14 @@ static inline void stmmac_mac_enable_tx(unsigned long ioaddr)
writel(value, ioaddr + MAC_CTRL_REG);
}
-static inline void stmmac_mac_disable_rx(unsigned long ioaddr)
+static inline void stmmac_mac_disable_rx(void __iomem *ioaddr)
{
u32 value = readl(ioaddr + MAC_CTRL_REG);
value &= ~MAC_RNABLE_RX;
writel(value, ioaddr + MAC_CTRL_REG);
}
-static inline void stmmac_mac_disable_tx(unsigned long ioaddr)
+static inline void stmmac_mac_disable_tx(void __iomem *ioaddr)
{
u32 value = readl(ioaddr + MAC_CTRL_REG);
value &= ~MAC_ENABLE_TX;
@@ -567,29 +562,22 @@ static void free_dma_desc_resources(struct stmmac_priv *priv)
* stmmac_dma_operation_mode - HW DMA operation mode
* @priv : pointer to the private device structure.
* Description: it sets the DMA operation mode: tx/rx DMA thresholds
- * or Store-And-Forward capability. It also verifies the COE for the
- * transmission in case of Giga ETH.
+ * or Store-And-Forward capability.
*/
static void stmmac_dma_operation_mode(struct stmmac_priv *priv)
{
- if (!priv->is_gmac) {
- /* MAC 10/100 */
- priv->hw->dma->dma_mode(priv->dev->base_addr, tc, 0);
- priv->tx_coe = NO_HW_CSUM;
- } else {
- if ((priv->dev->mtu <= ETH_DATA_LEN) && (tx_coe)) {
- priv->hw->dma->dma_mode(priv->dev->base_addr,
- SF_DMA_MODE, SF_DMA_MODE);
- tc = SF_DMA_MODE;
- priv->tx_coe = HW_CSUM;
- } else {
- /* Checksum computation is performed in software. */
- priv->hw->dma->dma_mode(priv->dev->base_addr, tc,
- SF_DMA_MODE);
- priv->tx_coe = NO_HW_CSUM;
- }
- }
- tx_coe = priv->tx_coe;
+ if (likely((priv->tx_coe) && (!priv->no_csum_insertion))) {
+ /* In case of GMAC, SF mode has to be enabled
+ * to perform the TX COE. This depends on:
+ * 1) TX COE if actually supported
+ * 2) There is no bugged Jumbo frame support
+ * that needs to not insert csum in the TDES.
+ */
+ priv->hw->dma->dma_mode(priv->ioaddr,
+ SF_DMA_MODE, SF_DMA_MODE);
+ tc = SF_DMA_MODE;
+ } else
+ priv->hw->dma->dma_mode(priv->ioaddr, tc, SF_DMA_MODE);
}
/**
@@ -600,7 +588,6 @@ static void stmmac_dma_operation_mode(struct stmmac_priv *priv)
static void stmmac_tx(struct stmmac_priv *priv)
{
unsigned int txsize = priv->dma_tx_size;
- unsigned long ioaddr = priv->dev->base_addr;
while (priv->dirty_tx != priv->cur_tx) {
int last;
@@ -618,7 +605,7 @@ static void stmmac_tx(struct stmmac_priv *priv)
int tx_error =
priv->hw->desc->tx_status(&priv->dev->stats,
&priv->xstats, p,
- ioaddr);
+ priv->ioaddr);
if (likely(tx_error == 0)) {
priv->dev->stats.tx_packets++;
priv->xstats.tx_pkt_n++;
@@ -674,7 +661,7 @@ static inline void stmmac_enable_irq(struct stmmac_priv *priv)
priv->tm->timer_start(tmrate);
else
#endif
- priv->hw->dma->enable_dma_irq(priv->dev->base_addr);
+ priv->hw->dma->enable_dma_irq(priv->ioaddr);
}
static inline void stmmac_disable_irq(struct stmmac_priv *priv)
@@ -684,7 +671,7 @@ static inline void stmmac_disable_irq(struct stmmac_priv *priv)
priv->tm->timer_stop();
else
#endif
- priv->hw->dma->disable_dma_irq(priv->dev->base_addr);
+ priv->hw->dma->disable_dma_irq(priv->ioaddr);
}
static int stmmac_has_work(struct stmmac_priv *priv)
@@ -739,14 +726,15 @@ static void stmmac_no_timer_stopped(void)
*/
static void stmmac_tx_err(struct stmmac_priv *priv)
{
+
netif_stop_queue(priv->dev);
- priv->hw->dma->stop_tx(priv->dev->base_addr);
+ priv->hw->dma->stop_tx(priv->ioaddr);
dma_free_tx_skbufs(priv);
priv->hw->desc->init_tx_desc(priv->dma_tx, priv->dma_tx_size);
priv->dirty_tx = 0;
priv->cur_tx = 0;
- priv->hw->dma->start_tx(priv->dev->base_addr);
+ priv->hw->dma->start_tx(priv->ioaddr);
priv->dev->stats.tx_errors++;
netif_wake_queue(priv->dev);
@@ -755,11 +743,9 @@ static void stmmac_tx_err(struct stmmac_priv *priv)
static void stmmac_dma_interrupt(struct stmmac_priv *priv)
{
- unsigned long ioaddr = priv->dev->base_addr;
int status;
- status = priv->hw->dma->dma_interrupt(priv->dev->base_addr,
- &priv->xstats);
+ status = priv->hw->dma->dma_interrupt(priv->ioaddr, &priv->xstats);
if (likely(status == handle_tx_rx))
_stmmac_schedule(priv);
@@ -767,7 +753,7 @@ static void stmmac_dma_interrupt(struct stmmac_priv *priv)
/* Try to bump up the dma threshold on this failure */
if (unlikely(tc != SF_DMA_MODE) && (tc <= 256)) {
tc += 64;
- priv->hw->dma->dma_mode(ioaddr, tc, SF_DMA_MODE);
+ priv->hw->dma->dma_mode(priv->ioaddr, tc, SF_DMA_MODE);
priv->xstats.threshold = tc;
}
stmmac_tx_err(priv);
@@ -787,7 +773,6 @@ static void stmmac_dma_interrupt(struct stmmac_priv *priv)
static int stmmac_open(struct net_device *dev)
{
struct stmmac_priv *priv = netdev_priv(dev);
- unsigned long ioaddr = dev->base_addr;
int ret;
/* Check that the MAC address is valid. If its not, refuse
@@ -843,7 +828,8 @@ static int stmmac_open(struct net_device *dev)
init_dma_desc_rings(dev);
/* DMA initialization and SW reset */
- if (unlikely(priv->hw->dma->init(ioaddr, priv->pbl, priv->dma_tx_phy,
+ if (unlikely(priv->hw->dma->init(priv->ioaddr, priv->pbl,
+ priv->dma_tx_phy,
priv->dma_rx_phy) < 0)) {
pr_err("%s: DMA initialization failed\n", __func__);
@@ -851,22 +837,28 @@ static int stmmac_open(struct net_device *dev)
}
/* Copy the MAC addr into the HW */
- priv->hw->mac->set_umac_addr(ioaddr, dev->dev_addr, 0);
+ priv->hw->mac->set_umac_addr(priv->ioaddr, dev->dev_addr, 0);
/* If required, perform hw setup of the bus. */
if (priv->bus_setup)
- priv->bus_setup(ioaddr);
+ priv->bus_setup(priv->ioaddr);
/* Initialize the MAC Core */
- priv->hw->mac->core_init(ioaddr);
+ priv->hw->mac->core_init(priv->ioaddr);
+
+ priv->rx_coe = priv->hw->mac->rx_coe(priv->ioaddr);
+ if (priv->rx_coe)
+ pr_info("stmmac: Rx Checksum Offload Engine supported\n");
+ if (priv->tx_coe)
+ pr_info("\tTX Checksum insertion supported\n");
priv->shutdown = 0;
/* Initialise the MMC (if present) to disable all interrupts. */
- writel(0xffffffff, ioaddr + MMC_HIGH_INTR_MASK);
- writel(0xffffffff, ioaddr + MMC_LOW_INTR_MASK);
+ writel(0xffffffff, priv->ioaddr + MMC_HIGH_INTR_MASK);
+ writel(0xffffffff, priv->ioaddr + MMC_LOW_INTR_MASK);
/* Enable the MAC Rx/Tx */
- stmmac_mac_enable_rx(ioaddr);
- stmmac_mac_enable_tx(ioaddr);
+ stmmac_mac_enable_rx(priv->ioaddr);
+ stmmac_mac_enable_tx(priv->ioaddr);
/* Set the HW DMA mode and the COE */
stmmac_dma_operation_mode(priv);
@@ -877,16 +869,16 @@ static int stmmac_open(struct net_device *dev)
/* Start the ball rolling... */
DBG(probe, DEBUG, "%s: DMA RX/TX processes started...\n", dev->name);
- priv->hw->dma->start_tx(ioaddr);
- priv->hw->dma->start_rx(ioaddr);
+ priv->hw->dma->start_tx(priv->ioaddr);
+ priv->hw->dma->start_rx(priv->ioaddr);
#ifdef CONFIG_STMMAC_TIMER
priv->tm->timer_start(tmrate);
#endif
/* Dump DMA/MAC registers */
if (netif_msg_hw(priv)) {
- priv->hw->mac->dump_regs(ioaddr);
- priv->hw->dma->dump_regs(ioaddr);
+ priv->hw->mac->dump_regs(priv->ioaddr);
+ priv->hw->dma->dump_regs(priv->ioaddr);
}
if (priv->phydev)
@@ -930,15 +922,15 @@ static int stmmac_release(struct net_device *dev)
free_irq(dev->irq, dev);
/* Stop TX/RX DMA and clear the descriptors */
- priv->hw->dma->stop_tx(dev->base_addr);
- priv->hw->dma->stop_rx(dev->base_addr);
+ priv->hw->dma->stop_tx(priv->ioaddr);
+ priv->hw->dma->stop_rx(priv->ioaddr);
/* Release and free the Rx/Tx resources */
free_dma_desc_resources(priv);
/* Disable the MAC core */
- stmmac_mac_disable_tx(dev->base_addr);
- stmmac_mac_disable_rx(dev->base_addr);
+ stmmac_mac_disable_tx(priv->ioaddr);
+ stmmac_mac_disable_rx(priv->ioaddr);
netif_carrier_off(dev);
@@ -1066,7 +1058,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
return stmmac_sw_tso(priv, skb);
if (likely((skb->ip_summed == CHECKSUM_PARTIAL))) {
- if (likely(priv->tx_coe == NO_HW_CSUM))
+ if (unlikely((!priv->tx_coe) || (priv->no_csum_insertion)))
skb_checksum_help(skb);
else
csum_insertion = 1;
@@ -1140,7 +1132,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
dev->stats.tx_bytes += skb->len;
- priv->hw->dma->enable_dma_transmission(dev->base_addr);
+ priv->hw->dma->enable_dma_transmission(priv->ioaddr);
return NETDEV_TX_OK;
}
@@ -1256,7 +1248,7 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit)
if (unlikely(status == csum_none)) {
/* always for the old mac 10/100 */
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
netif_receive_skb(skb);
} else {
skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -1390,6 +1382,15 @@ static int stmmac_change_mtu(struct net_device *dev, int new_mtu)
return -EINVAL;
}
+ /* Some GMAC devices have a bugged Jumbo frame support that
+ * needs to have the Tx COE disabled for oversized frames
+ * (due to limited buffer sizes). In this case we disable
+ * the TX csum insertionin the TDES and not use SF. */
+ if ((priv->bugged_jumbo) && (priv->dev->mtu > ETH_DATA_LEN))
+ priv->no_csum_insertion = 1;
+ else
+ priv->no_csum_insertion = 0;
+
dev->mtu = new_mtu;
return 0;
@@ -1405,11 +1406,9 @@ static irqreturn_t stmmac_interrupt(int irq, void *dev_id)
return IRQ_NONE;
}
- if (priv->is_gmac) {
- unsigned long ioaddr = dev->base_addr;
+ if (priv->is_gmac)
/* To handle GMAC own interrupts */
- priv->hw->mac->host_irq_status(ioaddr);
- }
+ priv->hw->mac->host_irq_status((void __iomem *) dev->base_addr);
stmmac_dma_interrupt(priv);
@@ -1512,9 +1511,6 @@ static int stmmac_probe(struct net_device *dev)
#endif
priv->msg_enable = netif_msg_init(debug, default_msg_level);
- if (priv->is_gmac)
- priv->rx_csum = 1;
-
if (flow_ctrl)
priv->flow_ctrl = FLOW_AUTO; /* RX/TX pause on */
@@ -1522,7 +1518,8 @@ static int stmmac_probe(struct net_device *dev)
netif_napi_add(dev, &priv->napi, stmmac_poll, 64);
/* Get the MAC address */
- priv->hw->mac->get_umac_addr(dev->base_addr, dev->dev_addr, 0);
+ priv->hw->mac->get_umac_addr((void __iomem *) dev->base_addr,
+ dev->dev_addr, 0);
if (!is_valid_ether_addr(dev->dev_addr))
pr_warning("\tno valid MAC address;"
@@ -1552,14 +1549,13 @@ static int stmmac_probe(struct net_device *dev)
static int stmmac_mac_device_setup(struct net_device *dev)
{
struct stmmac_priv *priv = netdev_priv(dev);
- unsigned long ioaddr = dev->base_addr;
struct mac_device_info *device;
if (priv->is_gmac)
- device = dwmac1000_setup(ioaddr);
+ device = dwmac1000_setup(priv->ioaddr);
else
- device = dwmac100_setup(ioaddr);
+ device = dwmac100_setup(priv->ioaddr);
if (!device)
return -ENOMEM;
@@ -1572,9 +1568,8 @@ static int stmmac_mac_device_setup(struct net_device *dev)
priv->hw = device;
- priv->wolenabled = priv->hw->pmt; /* PMT supported */
- if (priv->wolenabled == PMT_SUPPORTED)
- priv->wolopts = WAKE_MAGIC; /* Magic Frame */
+ if (device_can_wakeup(priv->device))
+ priv->wolopts = WAKE_MAGIC; /* Magic Frame as default */
return 0;
}
@@ -1653,7 +1648,7 @@ static int stmmac_dvr_probe(struct platform_device *pdev)
{
int ret = 0;
struct resource *res;
- unsigned int *addr = NULL;
+ void __iomem *addr = NULL;
struct net_device *ndev = NULL;
struct stmmac_priv *priv;
struct plat_stmmacenet_data *plat_dat;
@@ -1664,7 +1659,7 @@ static int stmmac_dvr_probe(struct platform_device *pdev)
ret = -ENODEV;
goto out;
}
- pr_info("done!\n");
+ pr_info("\tdone!\n");
if (!request_mem_region(res->start, resource_size(res),
pdev->name)) {
@@ -1706,8 +1701,18 @@ static int stmmac_dvr_probe(struct platform_device *pdev)
plat_dat = pdev->dev.platform_data;
priv->bus_id = plat_dat->bus_id;
priv->pbl = plat_dat->pbl; /* TLI */
+ priv->mii_clk_csr = plat_dat->clk_csr;
+ priv->tx_coe = plat_dat->tx_coe;
+ priv->bugged_jumbo = plat_dat->bugged_jumbo;
priv->is_gmac = plat_dat->has_gmac; /* GMAC is on board */
priv->enh_desc = plat_dat->enh_desc;
+ priv->ioaddr = addr;
+
+ /* PMT module is not integrated in all the MAC devices. */
+ if (plat_dat->pmt) {
+ pr_info("\tPMT module supported\n");
+ device_set_wakeup_capable(&pdev->dev, 1);
+ }
platform_set_drvdata(pdev, ndev);
@@ -1743,8 +1748,8 @@ static int stmmac_dvr_probe(struct platform_device *pdev)
priv->bsp_priv = plat_dat->bsp_priv;
pr_info("\t%s - (dev. name: %s - id: %d, IRQ #%d\n"
- "\tIO base addr: 0x%08x)\n", ndev->name, pdev->name,
- pdev->id, ndev->irq, (unsigned int)addr);
+ "\tIO base addr: 0x%p)\n", ndev->name, pdev->name,
+ pdev->id, ndev->irq, addr);
/* MDIO bus Registration */
pr_debug("\tMDIO bus (id: %d)...", priv->bus_id);
@@ -1779,11 +1784,11 @@ static int stmmac_dvr_remove(struct platform_device *pdev)
pr_info("%s:\n\tremoving driver", __func__);
- priv->hw->dma->stop_rx(ndev->base_addr);
- priv->hw->dma->stop_tx(ndev->base_addr);
+ priv->hw->dma->stop_rx(priv->ioaddr);
+ priv->hw->dma->stop_tx(priv->ioaddr);
- stmmac_mac_disable_rx(ndev->base_addr);
- stmmac_mac_disable_tx(ndev->base_addr);
+ stmmac_mac_disable_rx(priv->ioaddr);
+ stmmac_mac_disable_tx(priv->ioaddr);
netif_carrier_off(ndev);
@@ -1792,7 +1797,7 @@ static int stmmac_dvr_remove(struct platform_device *pdev)
platform_set_drvdata(pdev, NULL);
unregister_netdev(ndev);
- iounmap((void *)ndev->base_addr);
+ iounmap((void *)priv->ioaddr);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(res->start, resource_size(res));
@@ -1827,23 +1832,20 @@ static int stmmac_suspend(struct platform_device *pdev, pm_message_t state)
napi_disable(&priv->napi);
/* Stop TX/RX DMA */
- priv->hw->dma->stop_tx(dev->base_addr);
- priv->hw->dma->stop_rx(dev->base_addr);
+ priv->hw->dma->stop_tx(priv->ioaddr);
+ priv->hw->dma->stop_rx(priv->ioaddr);
/* Clear the Rx/Tx descriptors */
priv->hw->desc->init_rx_desc(priv->dma_rx, priv->dma_rx_size,
dis_ic);
priv->hw->desc->init_tx_desc(priv->dma_tx, priv->dma_tx_size);
- stmmac_mac_disable_tx(dev->base_addr);
+ stmmac_mac_disable_tx(priv->ioaddr);
- if (device_may_wakeup(&(pdev->dev))) {
- /* Enable Power down mode by programming the PMT regs */
- if (priv->wolenabled == PMT_SUPPORTED)
- priv->hw->mac->pmt(dev->base_addr,
- priv->wolopts);
- } else {
- stmmac_mac_disable_rx(dev->base_addr);
- }
+ /* Enable Power down mode by programming the PMT regs */
+ if (device_can_wakeup(priv->device))
+ priv->hw->mac->pmt(priv->ioaddr, priv->wolopts);
+ else
+ stmmac_mac_disable_rx(priv->ioaddr);
} else {
priv->shutdown = 1;
/* Although this can appear slightly redundant it actually
@@ -1860,7 +1862,6 @@ static int stmmac_resume(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
struct stmmac_priv *priv = netdev_priv(dev);
- unsigned long ioaddr = dev->base_addr;
if (!netif_running(dev))
return 0;
@@ -1879,17 +1880,16 @@ static int stmmac_resume(struct platform_device *pdev)
* is received. Anyway, it's better to manually clear
* this bit because it can generate problems while resuming
* from another devices (e.g. serial console). */
- if (device_may_wakeup(&(pdev->dev)))
- if (priv->wolenabled == PMT_SUPPORTED)
- priv->hw->mac->pmt(dev->base_addr, 0);
+ if (device_can_wakeup(priv->device))
+ priv->hw->mac->pmt(priv->ioaddr, 0);
netif_device_attach(dev);
/* Enable the MAC and DMA */
- stmmac_mac_enable_rx(ioaddr);
- stmmac_mac_enable_tx(ioaddr);
- priv->hw->dma->start_tx(ioaddr);
- priv->hw->dma->start_rx(ioaddr);
+ stmmac_mac_enable_rx(priv->ioaddr);
+ stmmac_mac_enable_tx(priv->ioaddr);
+ priv->hw->dma->start_tx(priv->ioaddr);
+ priv->hw->dma->start_rx(priv->ioaddr);
#ifdef CONFIG_STMMAC_TIMER
priv->tm->timer_start(tmrate);
@@ -1968,8 +1968,6 @@ static int __init stmmac_cmdline_opt(char *str)
strict_strtoul(opt + 7, 0, (unsigned long *)&buf_sz);
else if (!strncmp(opt, "tc:", 3))
strict_strtoul(opt + 3, 0, (unsigned long *)&tc);
- else if (!strncmp(opt, "tx_coe:", 7))
- strict_strtoul(opt + 7, 0, (unsigned long *)&tx_coe);
else if (!strncmp(opt, "watchdog:", 9))
strict_strtoul(opt + 9, 0, (unsigned long *)&watchdog);
else if (!strncmp(opt, "flow_ctrl:", 10))
diff --git a/drivers/net/stmmac/stmmac_mdio.c b/drivers/net/stmmac/stmmac_mdio.c
index 40b2c7929719..d7441616357d 100644
--- a/drivers/net/stmmac/stmmac_mdio.c
+++ b/drivers/net/stmmac/stmmac_mdio.c
@@ -47,21 +47,20 @@ static int stmmac_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg)
{
struct net_device *ndev = bus->priv;
struct stmmac_priv *priv = netdev_priv(ndev);
- unsigned long ioaddr = ndev->base_addr;
unsigned int mii_address = priv->hw->mii.addr;
unsigned int mii_data = priv->hw->mii.data;
int data;
u16 regValue = (((phyaddr << 11) & (0x0000F800)) |
((phyreg << 6) & (0x000007C0)));
- regValue |= MII_BUSY; /* in case of GMAC */
+ regValue |= MII_BUSY | ((priv->mii_clk_csr & 7) << 2);
- do {} while (((readl(ioaddr + mii_address)) & MII_BUSY) == 1);
- writel(regValue, ioaddr + mii_address);
- do {} while (((readl(ioaddr + mii_address)) & MII_BUSY) == 1);
+ do {} while (((readl(priv->ioaddr + mii_address)) & MII_BUSY) == 1);
+ writel(regValue, priv->ioaddr + mii_address);
+ do {} while (((readl(priv->ioaddr + mii_address)) & MII_BUSY) == 1);
/* Read the data from the MII data register */
- data = (int)readl(ioaddr + mii_data);
+ data = (int)readl(priv->ioaddr + mii_data);
return data;
}
@@ -79,7 +78,6 @@ static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg,
{
struct net_device *ndev = bus->priv;
struct stmmac_priv *priv = netdev_priv(ndev);
- unsigned long ioaddr = ndev->base_addr;
unsigned int mii_address = priv->hw->mii.addr;
unsigned int mii_data = priv->hw->mii.data;
@@ -87,17 +85,18 @@ static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg,
(((phyaddr << 11) & (0x0000F800)) | ((phyreg << 6) & (0x000007C0)))
| MII_WRITE;
- value |= MII_BUSY;
+ value |= MII_BUSY | ((priv->mii_clk_csr & 7) << 2);
+
/* Wait until any existing MII operation is complete */
- do {} while (((readl(ioaddr + mii_address)) & MII_BUSY) == 1);
+ do {} while (((readl(priv->ioaddr + mii_address)) & MII_BUSY) == 1);
/* Set the MII address register to write */
- writel(phydata, ioaddr + mii_data);
- writel(value, ioaddr + mii_address);
+ writel(phydata, priv->ioaddr + mii_data);
+ writel(value, priv->ioaddr + mii_address);
/* Wait until any existing MII operation is complete */
- do {} while (((readl(ioaddr + mii_address)) & MII_BUSY) == 1);
+ do {} while (((readl(priv->ioaddr + mii_address)) & MII_BUSY) == 1);
return 0;
}
@@ -111,7 +110,6 @@ static int stmmac_mdio_reset(struct mii_bus *bus)
{
struct net_device *ndev = bus->priv;
struct stmmac_priv *priv = netdev_priv(ndev);
- unsigned long ioaddr = ndev->base_addr;
unsigned int mii_address = priv->hw->mii.addr;
if (priv->phy_reset) {
@@ -123,7 +121,7 @@ static int stmmac_mdio_reset(struct mii_bus *bus)
* It doesn't complete its reset until at least one clock cycle
* on MDC, so perform a dummy mdio read.
*/
- writel(0, ioaddr + mii_address);
+ writel(0, priv->ioaddr + mii_address);
return 0;
}
diff --git a/drivers/net/sun3lance.c b/drivers/net/sun3lance.c
index 358c22f9acbe..7d9ec23aabf6 100644
--- a/drivers/net/sun3lance.c
+++ b/drivers/net/sun3lance.c
@@ -436,7 +436,7 @@ static int lance_open( struct net_device *dev )
DPRINTK( 2, ( "lance_open(): opening %s failed, i=%d, csr0=%04x\n",
dev->name, i, DREG ));
DREG = CSR0_STOP;
- return( -EIO );
+ return -EIO;
}
DREG = CSR0_IDON | CSR0_STRT | CSR0_INEA;
@@ -445,7 +445,7 @@ static int lance_open( struct net_device *dev )
DPRINTK( 2, ( "%s: LANCE is open, csr0 %04x\n", dev->name, DREG ));
- return( 0 );
+ return 0;
}
diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c
index 618643e3ca3e..0a6a5ced3c1c 100644
--- a/drivers/net/sunbmac.c
+++ b/drivers/net/sunbmac.c
@@ -617,7 +617,7 @@ static void bigmac_begin_auto_negotiation(struct bigmac *bp)
bp->timer_ticks = 0;
bp->bigmac_timer.expires = jiffies + (12 * HZ) / 10;
bp->bigmac_timer.data = (unsigned long) bp;
- bp->bigmac_timer.function = &bigmac_timer;
+ bp->bigmac_timer.function = bigmac_timer;
add_timer(&bp->bigmac_timer);
}
diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c
index 2678588ea4b2..3ed2a67bd6d3 100644
--- a/drivers/net/sundance.c
+++ b/drivers/net/sundance.c
@@ -96,16 +96,10 @@ static char *media[MAX_UNITS];
#include <asm/io.h>
#include <linux/delay.h>
#include <linux/spinlock.h>
-#ifndef _COMPAT_WITH_OLD_KERNEL
+#include <linux/dma-mapping.h>
#include <linux/crc32.h>
#include <linux/ethtool.h>
#include <linux/mii.h>
-#else
-#include "crc32.h"
-#include "ethtool.h"
-#include "mii.h"
-#include "compat.h"
-#endif
/* These identify the driver base version and may not be removed. */
static const char version[] __devinitconst =
@@ -369,9 +363,21 @@ struct netdev_private {
dma_addr_t tx_ring_dma;
dma_addr_t rx_ring_dma;
struct timer_list timer; /* Media monitoring timer. */
+ /* ethtool extra stats */
+ struct {
+ u64 tx_multiple_collisions;
+ u64 tx_single_collisions;
+ u64 tx_late_collisions;
+ u64 tx_deferred;
+ u64 tx_deferred_excessive;
+ u64 tx_aborted;
+ u64 tx_bcasts;
+ u64 rx_bcasts;
+ u64 tx_mcasts;
+ u64 rx_mcasts;
+ } xstats;
/* Frequently used values: keep some adjacent for cache effect. */
spinlock_t lock;
- spinlock_t rx_lock; /* Group with Tx control cache line. */
int msg_enable;
int chip_id;
unsigned int cur_rx, dirty_rx; /* Producer/consumer ring indices */
@@ -396,6 +402,7 @@ struct netdev_private {
unsigned char phys[MII_CNT]; /* MII device addresses, only first one used. */
struct pci_dev *pci_dev;
void __iomem *base;
+ spinlock_t statlock;
};
/* The station address location in the EEPROM. */
@@ -520,16 +527,19 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
np->chip_id = chip_idx;
np->msg_enable = (1 << debug) - 1;
spin_lock_init(&np->lock);
+ spin_lock_init(&np->statlock);
tasklet_init(&np->rx_tasklet, rx_poll, (unsigned long)dev);
tasklet_init(&np->tx_tasklet, tx_poll, (unsigned long)dev);
- ring_space = pci_alloc_consistent(pdev, TX_TOTAL_SIZE, &ring_dma);
+ ring_space = dma_alloc_coherent(&pdev->dev, TX_TOTAL_SIZE,
+ &ring_dma, GFP_KERNEL);
if (!ring_space)
goto err_out_cleardev;
np->tx_ring = (struct netdev_desc *)ring_space;
np->tx_ring_dma = ring_dma;
- ring_space = pci_alloc_consistent(pdev, RX_TOTAL_SIZE, &ring_dma);
+ ring_space = dma_alloc_coherent(&pdev->dev, RX_TOTAL_SIZE,
+ &ring_dma, GFP_KERNEL);
if (!ring_space)
goto err_out_unmap_tx;
np->rx_ring = (struct netdev_desc *)ring_space;
@@ -663,9 +673,11 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
err_out_unregister:
unregister_netdev(dev);
err_out_unmap_rx:
- pci_free_consistent(pdev, RX_TOTAL_SIZE, np->rx_ring, np->rx_ring_dma);
+ dma_free_coherent(&pdev->dev, RX_TOTAL_SIZE,
+ np->rx_ring, np->rx_ring_dma);
err_out_unmap_tx:
- pci_free_consistent(pdev, TX_TOTAL_SIZE, np->tx_ring, np->tx_ring_dma);
+ dma_free_coherent(&pdev->dev, TX_TOTAL_SIZE,
+ np->tx_ring, np->tx_ring_dma);
err_out_cleardev:
pci_set_drvdata(pdev, NULL);
pci_iounmap(pdev, ioaddr);
@@ -874,7 +886,7 @@ static int netdev_open(struct net_device *dev)
init_timer(&np->timer);
np->timer.expires = jiffies + 3*HZ;
np->timer.data = (unsigned long)dev;
- np->timer.function = &netdev_timer; /* timer handler */
+ np->timer.function = netdev_timer; /* timer handler */
add_timer(&np->timer);
/* Enable interrupts by setting the interrupt mask. */
@@ -1011,8 +1023,14 @@ static void init_ring(struct net_device *dev)
skb->dev = dev; /* Mark as being used by this device. */
skb_reserve(skb, 2); /* 16 byte align the IP header. */
np->rx_ring[i].frag[0].addr = cpu_to_le32(
- pci_map_single(np->pci_dev, skb->data, np->rx_buf_sz,
- PCI_DMA_FROMDEVICE));
+ dma_map_single(&np->pci_dev->dev, skb->data,
+ np->rx_buf_sz, DMA_FROM_DEVICE));
+ if (dma_mapping_error(&np->pci_dev->dev,
+ np->rx_ring[i].frag[0].addr)) {
+ dev_kfree_skb(skb);
+ np->rx_skbuff[i] = NULL;
+ break;
+ }
np->rx_ring[i].frag[0].length = cpu_to_le32(np->rx_buf_sz | LastFrag);
}
np->dirty_rx = (unsigned int)(i - RX_RING_SIZE);
@@ -1063,9 +1081,11 @@ start_tx (struct sk_buff *skb, struct net_device *dev)
txdesc->next_desc = 0;
txdesc->status = cpu_to_le32 ((entry << 2) | DisableAlign);
- txdesc->frag[0].addr = cpu_to_le32 (pci_map_single (np->pci_dev, skb->data,
- skb->len,
- PCI_DMA_TODEVICE));
+ txdesc->frag[0].addr = cpu_to_le32(dma_map_single(&np->pci_dev->dev,
+ skb->data, skb->len, DMA_TO_DEVICE));
+ if (dma_mapping_error(&np->pci_dev->dev,
+ txdesc->frag[0].addr))
+ goto drop_frame;
txdesc->frag[0].length = cpu_to_le32 (skb->len | LastFrag);
/* Increment cur_tx before tasklet_schedule() */
@@ -1087,6 +1107,12 @@ start_tx (struct sk_buff *skb, struct net_device *dev)
dev->name, np->cur_tx, entry);
}
return NETDEV_TX_OK;
+
+drop_frame:
+ dev_kfree_skb(skb);
+ np->tx_skbuff[entry] = NULL;
+ dev->stats.tx_dropped++;
+ return NETDEV_TX_OK;
}
/* Reset hardware tx and free all of tx buffers */
@@ -1097,7 +1123,6 @@ reset_tx (struct net_device *dev)
void __iomem *ioaddr = np->base;
struct sk_buff *skb;
int i;
- int irq = in_interrupt();
/* Reset tx logic, TxListPtr will be cleaned */
iowrite16 (TxDisable, ioaddr + MACCtrl1);
@@ -1109,13 +1134,10 @@ reset_tx (struct net_device *dev)
skb = np->tx_skbuff[i];
if (skb) {
- pci_unmap_single(np->pci_dev,
+ dma_unmap_single(&np->pci_dev->dev,
le32_to_cpu(np->tx_ring[i].frag[0].addr),
- skb->len, PCI_DMA_TODEVICE);
- if (irq)
- dev_kfree_skb_irq (skb);
- else
- dev_kfree_skb (skb);
+ skb->len, DMA_TO_DEVICE);
+ dev_kfree_skb_any(skb);
np->tx_skbuff[i] = NULL;
dev->stats.tx_dropped++;
}
@@ -1233,9 +1255,9 @@ static irqreturn_t intr_handler(int irq, void *dev_instance)
break;
skb = np->tx_skbuff[entry];
/* Free the original skb. */
- pci_unmap_single(np->pci_dev,
+ dma_unmap_single(&np->pci_dev->dev,
le32_to_cpu(np->tx_ring[entry].frag[0].addr),
- skb->len, PCI_DMA_TODEVICE);
+ skb->len, DMA_TO_DEVICE);
dev_kfree_skb_irq (np->tx_skbuff[entry]);
np->tx_skbuff[entry] = NULL;
np->tx_ring[entry].frag[0].addr = 0;
@@ -1252,9 +1274,9 @@ static irqreturn_t intr_handler(int irq, void *dev_instance)
break;
skb = np->tx_skbuff[entry];
/* Free the original skb. */
- pci_unmap_single(np->pci_dev,
+ dma_unmap_single(&np->pci_dev->dev,
le32_to_cpu(np->tx_ring[entry].frag[0].addr),
- skb->len, PCI_DMA_TODEVICE);
+ skb->len, DMA_TO_DEVICE);
dev_kfree_skb_irq (np->tx_skbuff[entry]);
np->tx_skbuff[entry] = NULL;
np->tx_ring[entry].frag[0].addr = 0;
@@ -1334,22 +1356,18 @@ static void rx_poll(unsigned long data)
if (pkt_len < rx_copybreak &&
(skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
skb_reserve(skb, 2); /* 16 byte align the IP header */
- pci_dma_sync_single_for_cpu(np->pci_dev,
- le32_to_cpu(desc->frag[0].addr),
- np->rx_buf_sz,
- PCI_DMA_FROMDEVICE);
-
+ dma_sync_single_for_cpu(&np->pci_dev->dev,
+ le32_to_cpu(desc->frag[0].addr),
+ np->rx_buf_sz, DMA_FROM_DEVICE);
skb_copy_to_linear_data(skb, np->rx_skbuff[entry]->data, pkt_len);
- pci_dma_sync_single_for_device(np->pci_dev,
- le32_to_cpu(desc->frag[0].addr),
- np->rx_buf_sz,
- PCI_DMA_FROMDEVICE);
+ dma_sync_single_for_device(&np->pci_dev->dev,
+ le32_to_cpu(desc->frag[0].addr),
+ np->rx_buf_sz, DMA_FROM_DEVICE);
skb_put(skb, pkt_len);
} else {
- pci_unmap_single(np->pci_dev,
+ dma_unmap_single(&np->pci_dev->dev,
le32_to_cpu(desc->frag[0].addr),
- np->rx_buf_sz,
- PCI_DMA_FROMDEVICE);
+ np->rx_buf_sz, DMA_FROM_DEVICE);
skb_put(skb = np->rx_skbuff[entry], pkt_len);
np->rx_skbuff[entry] = NULL;
}
@@ -1396,8 +1414,14 @@ static void refill_rx (struct net_device *dev)
skb->dev = dev; /* Mark as being used by this device. */
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
np->rx_ring[entry].frag[0].addr = cpu_to_le32(
- pci_map_single(np->pci_dev, skb->data,
- np->rx_buf_sz, PCI_DMA_FROMDEVICE));
+ dma_map_single(&np->pci_dev->dev, skb->data,
+ np->rx_buf_sz, DMA_FROM_DEVICE));
+ if (dma_mapping_error(&np->pci_dev->dev,
+ np->rx_ring[entry].frag[0].addr)) {
+ dev_kfree_skb_irq(skb);
+ np->rx_skbuff[entry] = NULL;
+ break;
+ }
}
/* Perhaps we need not reset this field. */
np->rx_ring[entry].frag[0].length =
@@ -1475,27 +1499,41 @@ static struct net_device_stats *get_stats(struct net_device *dev)
{
struct netdev_private *np = netdev_priv(dev);
void __iomem *ioaddr = np->base;
- int i;
+ unsigned long flags;
+ u8 late_coll, single_coll, mult_coll;
- /* We should lock this segment of code for SMP eventually, although
- the vulnerability window is very small and statistics are
- non-critical. */
+ spin_lock_irqsave(&np->statlock, flags);
/* The chip only need report frame silently dropped. */
dev->stats.rx_missed_errors += ioread8(ioaddr + RxMissed);
dev->stats.tx_packets += ioread16(ioaddr + TxFramesOK);
dev->stats.rx_packets += ioread16(ioaddr + RxFramesOK);
- dev->stats.collisions += ioread8(ioaddr + StatsLateColl);
- dev->stats.collisions += ioread8(ioaddr + StatsMultiColl);
- dev->stats.collisions += ioread8(ioaddr + StatsOneColl);
dev->stats.tx_carrier_errors += ioread8(ioaddr + StatsCarrierError);
- ioread8(ioaddr + StatsTxDefer);
- for (i = StatsTxDefer; i <= StatsMcastRx; i++)
- ioread8(ioaddr + i);
+
+ mult_coll = ioread8(ioaddr + StatsMultiColl);
+ np->xstats.tx_multiple_collisions += mult_coll;
+ single_coll = ioread8(ioaddr + StatsOneColl);
+ np->xstats.tx_single_collisions += single_coll;
+ late_coll = ioread8(ioaddr + StatsLateColl);
+ np->xstats.tx_late_collisions += late_coll;
+ dev->stats.collisions += mult_coll
+ + single_coll
+ + late_coll;
+
+ np->xstats.tx_deferred += ioread8(ioaddr + StatsTxDefer);
+ np->xstats.tx_deferred_excessive += ioread8(ioaddr + StatsTxXSDefer);
+ np->xstats.tx_aborted += ioread8(ioaddr + StatsTxAbort);
+ np->xstats.tx_bcasts += ioread8(ioaddr + StatsBcastTx);
+ np->xstats.rx_bcasts += ioread8(ioaddr + StatsBcastRx);
+ np->xstats.tx_mcasts += ioread8(ioaddr + StatsMcastTx);
+ np->xstats.rx_mcasts += ioread8(ioaddr + StatsMcastRx);
+
dev->stats.tx_bytes += ioread16(ioaddr + TxOctetsLow);
dev->stats.tx_bytes += ioread16(ioaddr + TxOctetsHigh) << 16;
dev->stats.rx_bytes += ioread16(ioaddr + RxOctetsLow);
dev->stats.rx_bytes += ioread16(ioaddr + RxOctetsHigh) << 16;
+ spin_unlock_irqrestore(&np->statlock, flags);
+
return &dev->stats;
}
@@ -1554,6 +1592,21 @@ static int __set_mac_addr(struct net_device *dev)
return 0;
}
+static const struct {
+ const char name[ETH_GSTRING_LEN];
+} sundance_stats[] = {
+ { "tx_multiple_collisions" },
+ { "tx_single_collisions" },
+ { "tx_late_collisions" },
+ { "tx_deferred" },
+ { "tx_deferred_excessive" },
+ { "tx_aborted" },
+ { "tx_bcasts" },
+ { "rx_bcasts" },
+ { "tx_mcasts" },
+ { "rx_mcasts" },
+};
+
static int check_if_running(struct net_device *dev)
{
if (!netif_running(dev))
@@ -1612,6 +1665,42 @@ static void set_msglevel(struct net_device *dev, u32 val)
np->msg_enable = val;
}
+static void get_strings(struct net_device *dev, u32 stringset,
+ u8 *data)
+{
+ if (stringset == ETH_SS_STATS)
+ memcpy(data, sundance_stats, sizeof(sundance_stats));
+}
+
+static int get_sset_count(struct net_device *dev, int sset)
+{
+ switch (sset) {
+ case ETH_SS_STATS:
+ return ARRAY_SIZE(sundance_stats);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static void get_ethtool_stats(struct net_device *dev,
+ struct ethtool_stats *stats, u64 *data)
+{
+ struct netdev_private *np = netdev_priv(dev);
+ int i = 0;
+
+ get_stats(dev);
+ data[i++] = np->xstats.tx_multiple_collisions;
+ data[i++] = np->xstats.tx_single_collisions;
+ data[i++] = np->xstats.tx_late_collisions;
+ data[i++] = np->xstats.tx_deferred;
+ data[i++] = np->xstats.tx_deferred_excessive;
+ data[i++] = np->xstats.tx_aborted;
+ data[i++] = np->xstats.tx_bcasts;
+ data[i++] = np->xstats.rx_bcasts;
+ data[i++] = np->xstats.tx_mcasts;
+ data[i++] = np->xstats.rx_mcasts;
+}
+
static const struct ethtool_ops ethtool_ops = {
.begin = check_if_running,
.get_drvinfo = get_drvinfo,
@@ -1621,6 +1710,9 @@ static const struct ethtool_ops ethtool_ops = {
.get_link = get_link,
.get_msglevel = get_msglevel,
.set_msglevel = set_msglevel,
+ .get_strings = get_strings,
+ .get_sset_count = get_sset_count,
+ .get_ethtool_stats = get_ethtool_stats,
};
static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
@@ -1715,9 +1807,9 @@ static int netdev_close(struct net_device *dev)
np->rx_ring[i].status = 0;
skb = np->rx_skbuff[i];
if (skb) {
- pci_unmap_single(np->pci_dev,
+ dma_unmap_single(&np->pci_dev->dev,
le32_to_cpu(np->rx_ring[i].frag[0].addr),
- np->rx_buf_sz, PCI_DMA_FROMDEVICE);
+ np->rx_buf_sz, DMA_FROM_DEVICE);
dev_kfree_skb(skb);
np->rx_skbuff[i] = NULL;
}
@@ -1727,9 +1819,9 @@ static int netdev_close(struct net_device *dev)
np->tx_ring[i].next_desc = 0;
skb = np->tx_skbuff[i];
if (skb) {
- pci_unmap_single(np->pci_dev,
+ dma_unmap_single(&np->pci_dev->dev,
le32_to_cpu(np->tx_ring[i].frag[0].addr),
- skb->len, PCI_DMA_TODEVICE);
+ skb->len, DMA_TO_DEVICE);
dev_kfree_skb(skb);
np->tx_skbuff[i] = NULL;
}
@@ -1743,25 +1835,72 @@ static void __devexit sundance_remove1 (struct pci_dev *pdev)
struct net_device *dev = pci_get_drvdata(pdev);
if (dev) {
- struct netdev_private *np = netdev_priv(dev);
-
- unregister_netdev(dev);
- pci_free_consistent(pdev, RX_TOTAL_SIZE, np->rx_ring,
- np->rx_ring_dma);
- pci_free_consistent(pdev, TX_TOTAL_SIZE, np->tx_ring,
- np->tx_ring_dma);
- pci_iounmap(pdev, np->base);
- pci_release_regions(pdev);
- free_netdev(dev);
- pci_set_drvdata(pdev, NULL);
+ struct netdev_private *np = netdev_priv(dev);
+ unregister_netdev(dev);
+ dma_free_coherent(&pdev->dev, RX_TOTAL_SIZE,
+ np->rx_ring, np->rx_ring_dma);
+ dma_free_coherent(&pdev->dev, TX_TOTAL_SIZE,
+ np->tx_ring, np->tx_ring_dma);
+ pci_iounmap(pdev, np->base);
+ pci_release_regions(pdev);
+ free_netdev(dev);
+ pci_set_drvdata(pdev, NULL);
+ }
+}
+
+#ifdef CONFIG_PM
+
+static int sundance_suspend(struct pci_dev *pci_dev, pm_message_t state)
+{
+ struct net_device *dev = pci_get_drvdata(pci_dev);
+
+ if (!netif_running(dev))
+ return 0;
+
+ netdev_close(dev);
+ netif_device_detach(dev);
+
+ pci_save_state(pci_dev);
+ pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state));
+
+ return 0;
+}
+
+static int sundance_resume(struct pci_dev *pci_dev)
+{
+ struct net_device *dev = pci_get_drvdata(pci_dev);
+ int err = 0;
+
+ if (!netif_running(dev))
+ return 0;
+
+ pci_set_power_state(pci_dev, PCI_D0);
+ pci_restore_state(pci_dev);
+
+ err = netdev_open(dev);
+ if (err) {
+ printk(KERN_ERR "%s: Can't resume interface!\n",
+ dev->name);
+ goto out;
}
+
+ netif_device_attach(dev);
+
+out:
+ return err;
}
+#endif /* CONFIG_PM */
+
static struct pci_driver sundance_driver = {
.name = DRV_NAME,
.id_table = sundance_pci_tbl,
.probe = sundance_probe1,
.remove = __devexit_p(sundance_remove1),
+#ifdef CONFIG_PM
+ .suspend = sundance_suspend,
+ .resume = sundance_resume,
+#endif /* CONFIG_PM */
};
static int __init sundance_init(void)
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c
index 434f9d735333..4ceb3cf6a9a9 100644
--- a/drivers/net/sungem.c
+++ b/drivers/net/sungem.c
@@ -31,6 +31,8 @@
* about when we can start taking interrupts or get xmit() called...
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
@@ -105,7 +107,6 @@ MODULE_DESCRIPTION("Sun GEM Gbit ethernet driver");
MODULE_LICENSE("GPL");
#define GEM_MODULE_NAME "gem"
-#define PFX GEM_MODULE_NAME ": "
static DEFINE_PCI_DEVICE_TABLE(gem_pci_tbl) = {
{ PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_GEM,
@@ -262,8 +263,7 @@ static int gem_pcs_interrupt(struct net_device *dev, struct gem *gp, u32 gem_sta
gp->dev->name, pcs_istat);
if (!(pcs_istat & PCS_ISTAT_LSC)) {
- printk(KERN_ERR "%s: PCS irq but no link status change???\n",
- dev->name);
+ netdev_err(dev, "PCS irq but no link status change???\n");
return 0;
}
@@ -282,20 +282,16 @@ static int gem_pcs_interrupt(struct net_device *dev, struct gem *gp, u32 gem_sta
* when autoneg has completed.
*/
if (pcs_miistat & PCS_MIISTAT_RF)
- printk(KERN_INFO "%s: PCS AutoNEG complete, "
- "RemoteFault\n", dev->name);
+ netdev_info(dev, "PCS AutoNEG complete, RemoteFault\n");
else
- printk(KERN_INFO "%s: PCS AutoNEG complete.\n",
- dev->name);
+ netdev_info(dev, "PCS AutoNEG complete\n");
}
if (pcs_miistat & PCS_MIISTAT_LS) {
- printk(KERN_INFO "%s: PCS link is now up.\n",
- dev->name);
+ netdev_info(dev, "PCS link is now up\n");
netif_carrier_on(gp->dev);
} else {
- printk(KERN_INFO "%s: PCS link is now down.\n",
- dev->name);
+ netdev_info(dev, "PCS link is now down\n");
netif_carrier_off(gp->dev);
/* If this happens and the link timer is not running,
* reset so we re-negotiate.
@@ -323,14 +319,12 @@ static int gem_txmac_interrupt(struct net_device *dev, struct gem *gp, u32 gem_s
return 0;
if (txmac_stat & MAC_TXSTAT_URUN) {
- printk(KERN_ERR "%s: TX MAC xmit underrun.\n",
- dev->name);
+ netdev_err(dev, "TX MAC xmit underrun\n");
gp->net_stats.tx_fifo_errors++;
}
if (txmac_stat & MAC_TXSTAT_MPE) {
- printk(KERN_ERR "%s: TX MAC max packet size error.\n",
- dev->name);
+ netdev_err(dev, "TX MAC max packet size error\n");
gp->net_stats.tx_errors++;
}
@@ -377,8 +371,7 @@ static int gem_rxmac_reset(struct gem *gp)
udelay(10);
}
if (limit == 5000) {
- printk(KERN_ERR "%s: RX MAC will not reset, resetting whole "
- "chip.\n", dev->name);
+ netdev_err(dev, "RX MAC will not reset, resetting whole chip\n");
return 1;
}
@@ -390,8 +383,7 @@ static int gem_rxmac_reset(struct gem *gp)
udelay(10);
}
if (limit == 5000) {
- printk(KERN_ERR "%s: RX MAC will not disable, resetting whole "
- "chip.\n", dev->name);
+ netdev_err(dev, "RX MAC will not disable, resetting whole chip\n");
return 1;
}
@@ -403,8 +395,7 @@ static int gem_rxmac_reset(struct gem *gp)
udelay(10);
}
if (limit == 5000) {
- printk(KERN_ERR "%s: RX DMA will not disable, resetting whole "
- "chip.\n", dev->name);
+ netdev_err(dev, "RX DMA will not disable, resetting whole chip\n");
return 1;
}
@@ -419,8 +410,7 @@ static int gem_rxmac_reset(struct gem *gp)
udelay(10);
}
if (limit == 5000) {
- printk(KERN_ERR "%s: RX reset command will not execute, resetting "
- "whole chip.\n", dev->name);
+ netdev_err(dev, "RX reset command will not execute, resetting whole chip\n");
return 1;
}
@@ -429,8 +419,7 @@ static int gem_rxmac_reset(struct gem *gp)
struct gem_rxd *rxd = &gp->init_block->rxd[i];
if (gp->rx_skbs[i] == NULL) {
- printk(KERN_ERR "%s: Parts of RX ring empty, resetting "
- "whole chip.\n", dev->name);
+ netdev_err(dev, "Parts of RX ring empty, resetting whole chip\n");
return 1;
}
@@ -479,8 +468,7 @@ static int gem_rxmac_interrupt(struct net_device *dev, struct gem *gp, u32 gem_s
if (rxmac_stat & MAC_RXSTAT_OFLW) {
u32 smac = readl(gp->regs + MAC_SMACHINE);
- printk(KERN_ERR "%s: RX MAC fifo overflow smac[%08x].\n",
- dev->name, smac);
+ netdev_err(dev, "RX MAC fifo overflow smac[%08x]\n", smac);
gp->net_stats.rx_over_errors++;
gp->net_stats.rx_fifo_errors++;
@@ -542,19 +530,18 @@ static int gem_pci_interrupt(struct net_device *dev, struct gem *gp, u32 gem_sta
if (gp->pdev->vendor == PCI_VENDOR_ID_SUN &&
gp->pdev->device == PCI_DEVICE_ID_SUN_GEM) {
- printk(KERN_ERR "%s: PCI error [%04x] ",
- dev->name, pci_estat);
+ netdev_err(dev, "PCI error [%04x]", pci_estat);
if (pci_estat & GREG_PCIESTAT_BADACK)
- printk("<No ACK64# during ABS64 cycle> ");
+ pr_cont(" <No ACK64# during ABS64 cycle>");
if (pci_estat & GREG_PCIESTAT_DTRTO)
- printk("<Delayed transaction timeout> ");
+ pr_cont(" <Delayed transaction timeout>");
if (pci_estat & GREG_PCIESTAT_OTHER)
- printk("<other>");
- printk("\n");
+ pr_cont(" <other>");
+ pr_cont("\n");
} else {
pci_estat |= GREG_PCIESTAT_OTHER;
- printk(KERN_ERR "%s: PCI error\n", dev->name);
+ netdev_err(dev, "PCI error\n");
}
if (pci_estat & GREG_PCIESTAT_OTHER) {
@@ -565,26 +552,20 @@ static int gem_pci_interrupt(struct net_device *dev, struct gem *gp, u32 gem_sta
*/
pci_read_config_word(gp->pdev, PCI_STATUS,
&pci_cfg_stat);
- printk(KERN_ERR "%s: Read PCI cfg space status [%04x]\n",
- dev->name, pci_cfg_stat);
+ netdev_err(dev, "Read PCI cfg space status [%04x]\n",
+ pci_cfg_stat);
if (pci_cfg_stat & PCI_STATUS_PARITY)
- printk(KERN_ERR "%s: PCI parity error detected.\n",
- dev->name);
+ netdev_err(dev, "PCI parity error detected\n");
if (pci_cfg_stat & PCI_STATUS_SIG_TARGET_ABORT)
- printk(KERN_ERR "%s: PCI target abort.\n",
- dev->name);
+ netdev_err(dev, "PCI target abort\n");
if (pci_cfg_stat & PCI_STATUS_REC_TARGET_ABORT)
- printk(KERN_ERR "%s: PCI master acks target abort.\n",
- dev->name);
+ netdev_err(dev, "PCI master acks target abort\n");
if (pci_cfg_stat & PCI_STATUS_REC_MASTER_ABORT)
- printk(KERN_ERR "%s: PCI master abort.\n",
- dev->name);
+ netdev_err(dev, "PCI master abort\n");
if (pci_cfg_stat & PCI_STATUS_SIG_SYSTEM_ERROR)
- printk(KERN_ERR "%s: PCI system error SERR#.\n",
- dev->name);
+ netdev_err(dev, "PCI system error SERR#\n");
if (pci_cfg_stat & PCI_STATUS_DETECTED_PARITY)
- printk(KERN_ERR "%s: PCI parity error.\n",
- dev->name);
+ netdev_err(dev, "PCI parity error\n");
/* Write the error bits back to clear them. */
pci_cfg_stat &= (PCI_STATUS_PARITY |
@@ -874,8 +855,7 @@ static int gem_rx(struct gem *gp, int work_to_do)
gp->rx_new = entry;
if (drops)
- printk(KERN_INFO "%s: Memory squeeze, deferring packet.\n",
- gp->dev->name);
+ netdev_info(gp->dev, "Memory squeeze, deferring packet\n");
return work_done;
}
@@ -981,21 +961,19 @@ static void gem_tx_timeout(struct net_device *dev)
{
struct gem *gp = netdev_priv(dev);
- printk(KERN_ERR "%s: transmit timed out, resetting\n", dev->name);
+ netdev_err(dev, "transmit timed out, resetting\n");
if (!gp->running) {
- printk("%s: hrm.. hw not running !\n", dev->name);
+ netdev_err(dev, "hrm.. hw not running !\n");
return;
}
- printk(KERN_ERR "%s: TX_STATE[%08x:%08x:%08x]\n",
- dev->name,
- readl(gp->regs + TXDMA_CFG),
- readl(gp->regs + MAC_TXSTAT),
- readl(gp->regs + MAC_TXCFG));
- printk(KERN_ERR "%s: RX_STATE[%08x:%08x:%08x]\n",
- dev->name,
- readl(gp->regs + RXDMA_CFG),
- readl(gp->regs + MAC_RXSTAT),
- readl(gp->regs + MAC_RXCFG));
+ netdev_err(dev, "TX_STATE[%08x:%08x:%08x]\n",
+ readl(gp->regs + TXDMA_CFG),
+ readl(gp->regs + MAC_TXSTAT),
+ readl(gp->regs + MAC_TXCFG));
+ netdev_err(dev, "RX_STATE[%08x:%08x:%08x]\n",
+ readl(gp->regs + RXDMA_CFG),
+ readl(gp->regs + MAC_RXSTAT),
+ readl(gp->regs + MAC_RXCFG));
spin_lock_irq(&gp->lock);
spin_lock(&gp->tx_lock);
@@ -1048,8 +1026,7 @@ static netdev_tx_t gem_start_xmit(struct sk_buff *skb,
if (TX_BUFFS_AVAIL(gp) <= (skb_shinfo(skb)->nr_frags + 1)) {
netif_stop_queue(dev);
spin_unlock_irqrestore(&gp->tx_lock, flags);
- printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n",
- dev->name);
+ netdev_err(dev, "BUG! Tx Ring full when queue awake!\n");
return NETDEV_TX_BUSY;
}
@@ -1158,8 +1135,7 @@ static void gem_pcs_reset(struct gem *gp)
break;
}
if (limit < 0)
- printk(KERN_WARNING "%s: PCS reset bit would not clear.\n",
- gp->dev->name);
+ netdev_warn(gp->dev, "PCS reset bit would not clear\n");
}
static void gem_pcs_reinit_adv(struct gem *gp)
@@ -1230,7 +1206,7 @@ static void gem_reset(struct gem *gp)
} while (val & (GREG_SWRST_TXRST | GREG_SWRST_RXRST));
if (limit < 0)
- printk(KERN_ERR "%s: SW reset is ghetto.\n", gp->dev->name);
+ netdev_err(gp->dev, "SW reset is ghetto\n");
if (gp->phy_type == phy_serialink || gp->phy_type == phy_serdes)
gem_pcs_reinit_adv(gp);
@@ -1395,9 +1371,8 @@ static int gem_set_link_modes(struct gem *gp)
speed = SPEED_1000;
}
- if (netif_msg_link(gp))
- printk(KERN_INFO "%s: Link is up at %d Mbps, %s-duplex.\n",
- gp->dev->name, speed, (full_duplex ? "full" : "half"));
+ netif_info(gp, link, gp->dev, "Link is up at %d Mbps, %s-duplex\n",
+ speed, (full_duplex ? "full" : "half"));
if (!gp->running)
return 0;
@@ -1451,15 +1426,13 @@ static int gem_set_link_modes(struct gem *gp)
if (netif_msg_link(gp)) {
if (pause) {
- printk(KERN_INFO "%s: Pause is enabled "
- "(rxfifo: %d off: %d on: %d)\n",
- gp->dev->name,
- gp->rx_fifo_sz,
- gp->rx_pause_off,
- gp->rx_pause_on);
+ netdev_info(gp->dev,
+ "Pause is enabled (rxfifo: %d off: %d on: %d)\n",
+ gp->rx_fifo_sz,
+ gp->rx_pause_off,
+ gp->rx_pause_on);
} else {
- printk(KERN_INFO "%s: Pause is disabled\n",
- gp->dev->name);
+ netdev_info(gp->dev, "Pause is disabled\n");
}
}
@@ -1484,9 +1457,8 @@ static int gem_mdio_link_not_up(struct gem *gp)
{
switch (gp->lstate) {
case link_force_ret:
- if (netif_msg_link(gp))
- printk(KERN_INFO "%s: Autoneg failed again, keeping"
- " forced mode\n", gp->dev->name);
+ netif_info(gp, link, gp->dev,
+ "Autoneg failed again, keeping forced mode\n");
gp->phy_mii.def->ops->setup_forced(&gp->phy_mii,
gp->last_forced_speed, DUPLEX_HALF);
gp->timer_ticks = 5;
@@ -1499,9 +1471,7 @@ static int gem_mdio_link_not_up(struct gem *gp)
*/
if (gp->phy_mii.def->magic_aneg)
return 1;
- if (netif_msg_link(gp))
- printk(KERN_INFO "%s: switching to forced 100bt\n",
- gp->dev->name);
+ netif_info(gp, link, gp->dev, "switching to forced 100bt\n");
/* Try forced modes. */
gp->phy_mii.def->ops->setup_forced(&gp->phy_mii, SPEED_100,
DUPLEX_HALF);
@@ -1517,9 +1487,8 @@ static int gem_mdio_link_not_up(struct gem *gp)
gp->phy_mii.def->ops->setup_forced(&gp->phy_mii, SPEED_10,
DUPLEX_HALF);
gp->timer_ticks = 5;
- if (netif_msg_link(gp))
- printk(KERN_INFO "%s: switching to forced 10bt\n",
- gp->dev->name);
+ netif_info(gp, link, gp->dev,
+ "switching to forced 10bt\n");
return 0;
} else
return 1;
@@ -1574,8 +1543,8 @@ static void gem_link_timer(unsigned long data)
gp->last_forced_speed = gp->phy_mii.speed;
gp->timer_ticks = 5;
if (netif_msg_link(gp))
- printk(KERN_INFO "%s: Got link after fallback, retrying"
- " autoneg once...\n", gp->dev->name);
+ netdev_info(gp->dev,
+ "Got link after fallback, retrying autoneg once...\n");
gp->phy_mii.def->ops->setup_aneg(&gp->phy_mii, gp->phy_mii.advertising);
} else if (gp->lstate != link_up) {
gp->lstate = link_up;
@@ -1589,9 +1558,7 @@ static void gem_link_timer(unsigned long data)
*/
if (gp->lstate == link_up) {
gp->lstate = link_down;
- if (netif_msg_link(gp))
- printk(KERN_INFO "%s: Link down\n",
- gp->dev->name);
+ netif_info(gp, link, gp->dev, "Link down\n");
netif_carrier_off(gp->dev);
gp->reset_task_pending = 1;
schedule_work(&gp->reset_task);
@@ -1746,8 +1713,7 @@ static void gem_init_phy(struct gem *gp)
if (phy_read(gp, MII_BMCR) != 0xffff)
break;
if (i == 2)
- printk(KERN_WARNING "%s: GMAC PHY not responding !\n",
- gp->dev->name);
+ netdev_warn(gp->dev, "GMAC PHY not responding !\n");
}
}
@@ -2038,7 +2004,7 @@ static int gem_check_invariants(struct gem *gp)
* as this chip has no gigabit PHY.
*/
if ((mif_cfg & (MIF_CFG_MDI0 | MIF_CFG_MDI1)) == 0) {
- printk(KERN_ERR PFX "RIO GEM lacks MII phy, mif_cfg[%08x]\n",
+ pr_err("RIO GEM lacks MII phy, mif_cfg[%08x]\n",
mif_cfg);
return -1;
}
@@ -2078,7 +2044,7 @@ static int gem_check_invariants(struct gem *gp)
}
if (i == 32) {
if (pdev->device != PCI_DEVICE_ID_SUN_GEM) {
- printk(KERN_ERR PFX "RIO MII phy will not respond.\n");
+ pr_err("RIO MII phy will not respond\n");
return -1;
}
gp->phy_type = phy_serdes;
@@ -2093,7 +2059,7 @@ static int gem_check_invariants(struct gem *gp)
if (pdev->device == PCI_DEVICE_ID_SUN_GEM) {
if (gp->tx_fifo_sz != (9 * 1024) ||
gp->rx_fifo_sz != (20 * 1024)) {
- printk(KERN_ERR PFX "GEM has bogus fifo sizes tx(%d) rx(%d)\n",
+ pr_err("GEM has bogus fifo sizes tx(%d) rx(%d)\n",
gp->tx_fifo_sz, gp->rx_fifo_sz);
return -1;
}
@@ -2101,7 +2067,7 @@ static int gem_check_invariants(struct gem *gp)
} else {
if (gp->tx_fifo_sz != (2 * 1024) ||
gp->rx_fifo_sz != (2 * 1024)) {
- printk(KERN_ERR PFX "RIO GEM has bogus fifo sizes tx(%d) rx(%d)\n",
+ pr_err("RIO GEM has bogus fifo sizes tx(%d) rx(%d)\n",
gp->tx_fifo_sz, gp->rx_fifo_sz);
return -1;
}
@@ -2239,7 +2205,7 @@ static int gem_do_start(struct net_device *dev)
if (request_irq(gp->pdev->irq, gem_interrupt,
IRQF_SHARED, dev->name, (void *)dev)) {
- printk(KERN_ERR "%s: failed to request irq !\n", gp->dev->name);
+ netdev_err(dev, "failed to request irq !\n");
spin_lock_irqsave(&gp->lock, flags);
spin_lock(&gp->tx_lock);
@@ -2378,9 +2344,8 @@ static int gem_suspend(struct pci_dev *pdev, pm_message_t state)
mutex_lock(&gp->pm_mutex);
- printk(KERN_INFO "%s: suspending, WakeOnLan %s\n",
- dev->name,
- (gp->wake_on_lan && gp->opened) ? "enabled" : "disabled");
+ netdev_info(dev, "suspending, WakeOnLan %s\n",
+ (gp->wake_on_lan && gp->opened) ? "enabled" : "disabled");
/* Keep the cell enabled during the entire operation */
spin_lock_irqsave(&gp->lock, flags);
@@ -2440,7 +2405,7 @@ static int gem_resume(struct pci_dev *pdev)
struct gem *gp = netdev_priv(dev);
unsigned long flags;
- printk(KERN_INFO "%s: resuming\n", dev->name);
+ netdev_info(dev, "resuming\n");
mutex_lock(&gp->pm_mutex);
@@ -2452,8 +2417,7 @@ static int gem_resume(struct pci_dev *pdev)
/* Make sure PCI access and bus master are enabled */
if (pci_enable_device(gp->pdev)) {
- printk(KERN_ERR "%s: Can't re-enable chip !\n",
- dev->name);
+ netdev_err(dev, "Can't re-enable chip !\n");
/* Put cell and forget it for now, it will be considered as
* still asleep, a new sleep cycle may bring it back
*/
@@ -2938,7 +2902,7 @@ static int __devinit gem_get_device_address(struct gem *gp)
addr = idprom->id_ethaddr;
#else
printk("\n");
- printk(KERN_ERR "%s: can't get mac-address\n", dev->name);
+ pr_err("%s: can't get mac-address\n", dev->name);
return -1;
#endif
}
@@ -3009,14 +2973,12 @@ static const struct net_device_ops gem_netdev_ops = {
static int __devinit gem_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
- static int gem_version_printed = 0;
unsigned long gemreg_base, gemreg_len;
struct net_device *dev;
struct gem *gp;
int err, pci_using_dac;
- if (gem_version_printed++ == 0)
- printk(KERN_INFO "%s", version);
+ printk_once(KERN_INFO "%s", version);
/* Apple gmac note: during probe, the chip is powered up by
* the arch code to allow the code below to work (and to let
@@ -3026,8 +2988,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
*/
err = pci_enable_device(pdev);
if (err) {
- printk(KERN_ERR PFX "Cannot enable MMIO operation, "
- "aborting.\n");
+ pr_err("Cannot enable MMIO operation, aborting\n");
return err;
}
pci_set_master(pdev);
@@ -3048,8 +3009,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
} else {
err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
if (err) {
- printk(KERN_ERR PFX "No usable DMA configuration, "
- "aborting.\n");
+ pr_err("No usable DMA configuration, aborting\n");
goto err_disable_device;
}
pci_using_dac = 0;
@@ -3059,15 +3019,14 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
gemreg_len = pci_resource_len(pdev, 0);
if ((pci_resource_flags(pdev, 0) & IORESOURCE_IO) != 0) {
- printk(KERN_ERR PFX "Cannot find proper PCI device "
- "base address, aborting.\n");
+ pr_err("Cannot find proper PCI device base address, aborting\n");
err = -ENODEV;
goto err_disable_device;
}
dev = alloc_etherdev(sizeof(*gp));
if (!dev) {
- printk(KERN_ERR PFX "Etherdev alloc failed, aborting.\n");
+ pr_err("Etherdev alloc failed, aborting\n");
err = -ENOMEM;
goto err_disable_device;
}
@@ -3077,8 +3036,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
err = pci_request_regions(pdev, DRV_NAME);
if (err) {
- printk(KERN_ERR PFX "Cannot obtain PCI resources, "
- "aborting.\n");
+ pr_err("Cannot obtain PCI resources, aborting\n");
goto err_out_free_netdev;
}
@@ -3104,8 +3062,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
gp->regs = ioremap(gemreg_base, gemreg_len);
if (!gp->regs) {
- printk(KERN_ERR PFX "Cannot map device registers, "
- "aborting.\n");
+ pr_err("Cannot map device registers, aborting\n");
err = -EIO;
goto err_out_free_res;
}
@@ -3150,8 +3107,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
pci_alloc_consistent(pdev, sizeof(struct gem_init_block),
&gp->gblock_dvma);
if (!gp->init_block) {
- printk(KERN_ERR PFX "Cannot allocate init block, "
- "aborting.\n");
+ pr_err("Cannot allocate init block, aborting\n");
err = -ENOMEM;
goto err_out_iounmap;
}
@@ -3180,19 +3136,18 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
/* Register with kernel */
if (register_netdev(dev)) {
- printk(KERN_ERR PFX "Cannot register net device, "
- "aborting.\n");
+ pr_err("Cannot register net device, aborting\n");
err = -ENOMEM;
goto err_out_free_consistent;
}
- printk(KERN_INFO "%s: Sun GEM (PCI) 10/100/1000BaseT Ethernet %pM\n",
- dev->name, dev->dev_addr);
+ netdev_info(dev, "Sun GEM (PCI) 10/100/1000BaseT Ethernet %pM\n",
+ dev->dev_addr);
if (gp->phy_type == phy_mii_mdio0 ||
gp->phy_type == phy_mii_mdio1)
- printk(KERN_INFO "%s: Found %s PHY\n", dev->name,
- gp->phy_mii.def ? gp->phy_mii.def->name : "no");
+ netdev_info(dev, "Found %s PHY\n",
+ gp->phy_mii.def ? gp->phy_mii.def->name : "no");
/* GEM can do it all... */
dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_LLTX;
diff --git a/drivers/net/sungem_phy.c b/drivers/net/sungem_phy.c
index 78f8cee5fd74..d16880d7099b 100644
--- a/drivers/net/sungem_phy.c
+++ b/drivers/net/sungem_phy.c
@@ -88,7 +88,7 @@ static int reset_one_mii_phy(struct mii_phy* phy, int phy_id)
if ((val & BMCR_ISOLATE) && limit > 0)
__phy_write(phy, phy_id, MII_BMCR, val & ~BMCR_ISOLATE);
- return (limit <= 0);
+ return limit <= 0;
}
static int bcm5201_init(struct mii_phy* phy)
@@ -1175,7 +1175,8 @@ int mii_phy_probe(struct mii_phy *phy, int mii_id)
/* Read ID and find matching entry */
id = (phy_read(phy, MII_PHYSID1) << 16 | phy_read(phy, MII_PHYSID2));
- printk(KERN_DEBUG "PHY ID: %x, addr: %x\n", id, mii_id);
+ printk(KERN_DEBUG KBUILD_MODNAME ": " "PHY ID: %x, addr: %x\n",
+ id, mii_id);
for (i=0; (def = mii_phy_table[i]) != NULL; i++)
if ((id & def->phy_id_mask) == def->phy_id)
break;
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c
index bd0df1c14955..5e28c414421a 100644
--- a/drivers/net/sunhme.c
+++ b/drivers/net/sunhme.c
@@ -1409,7 +1409,7 @@ force_link:
hp->timer_ticks = 0;
hp->happy_timer.expires = jiffies + (12 * HZ)/10; /* 1.2 sec. */
hp->happy_timer.data = (unsigned long) hp;
- hp->happy_timer.function = &happy_meal_timer;
+ hp->happy_timer.function = happy_meal_timer;
add_timer(&hp->happy_timer);
}
@@ -2497,7 +2497,7 @@ static u32 hme_get_link(struct net_device *dev)
hp->sw_bmcr = happy_meal_tcvr_read(hp, hp->tcvregs, MII_BMCR);
spin_unlock_irq(&hp->happy_lock);
- return (hp->sw_bmsr & BMSR_LSTATUS);
+ return hp->sw_bmsr & BMSR_LSTATUS;
}
static const struct ethtool_ops hme_ethtool_ops = {
@@ -2808,7 +2808,8 @@ static int __devinit happy_meal_sbus_probe_one(struct platform_device *op, int i
happy_meal_set_initial_advertisement(hp);
spin_unlock_irq(&hp->happy_lock);
- if (register_netdev(hp->dev)) {
+ err = register_netdev(hp->dev);
+ if (err) {
printk(KERN_ERR "happymeal: Cannot register net device, "
"aborting.\n");
goto err_out_free_coherent;
@@ -3130,7 +3131,8 @@ static int __devinit happy_meal_pci_probe(struct pci_dev *pdev,
happy_meal_set_initial_advertisement(hp);
spin_unlock_irq(&hp->happy_lock);
- if (register_netdev(hp->dev)) {
+ err = register_netdev(hp->dev);
+ if (err) {
printk(KERN_ERR "happymeal(PCI): Cannot register net device, "
"aborting.\n");
goto err_out_iounmap;
diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c
index 8dcb858f2168..2cf84e5968b2 100644
--- a/drivers/net/sunlance.c
+++ b/drivers/net/sunlance.c
@@ -1483,7 +1483,7 @@ no_link_test:
*/
init_timer(&lp->multicast_timer);
lp->multicast_timer.data = (unsigned long) dev;
- lp->multicast_timer.function = &lance_set_multicast_retry;
+ lp->multicast_timer.function = lance_set_multicast_retry;
if (register_netdev(dev)) {
printk(KERN_ERR "SunLance: Cannot register device.\n");
diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c
index 72e65d4666ef..9536b2f010be 100644
--- a/drivers/net/sunqe.c
+++ b/drivers/net/sunqe.c
@@ -711,7 +711,7 @@ static u32 qe_get_link(struct net_device *dev)
phyconfig = sbus_readb(mregs + MREGS_PHYCONFIG);
spin_unlock_irq(&qep->lock);
- return (phyconfig & MREGS_PHYCONFIG_LSTAT);
+ return phyconfig & MREGS_PHYCONFIG_LSTAT;
}
static const struct ethtool_ops qe_ethtool_ops = {
diff --git a/drivers/net/sunvnet.c b/drivers/net/sunvnet.c
index d281a7b34701..bf3c762de620 100644
--- a/drivers/net/sunvnet.c
+++ b/drivers/net/sunvnet.c
@@ -3,6 +3,8 @@
* Copyright (C) 2007, 2008 David S. Miller <davem@davemloft.net>
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
@@ -20,7 +22,6 @@
#include "sunvnet.h"
#define DRV_MODULE_NAME "sunvnet"
-#define PFX DRV_MODULE_NAME ": "
#define DRV_MODULE_VERSION "1.0"
#define DRV_MODULE_RELDATE "June 25, 2007"
@@ -45,9 +46,9 @@ static int vnet_handle_unknown(struct vnet_port *port, void *arg)
{
struct vio_msg_tag *pkt = arg;
- printk(KERN_ERR PFX "Received unknown msg [%02x:%02x:%04x:%08x]\n",
+ pr_err("Received unknown msg [%02x:%02x:%04x:%08x]\n",
pkt->type, pkt->stype, pkt->stype_env, pkt->sid);
- printk(KERN_ERR PFX "Resetting connection.\n");
+ pr_err("Resetting connection\n");
ldc_disconnect(port->vio.lp);
@@ -400,8 +401,8 @@ static int vnet_rx(struct vnet_port *port, void *msgbuf)
if (unlikely(pkt->tag.stype_env != VIO_DRING_DATA))
return 0;
if (unlikely(pkt->seq != dr->rcv_nxt)) {
- printk(KERN_ERR PFX "RX out of sequence seq[0x%llx] "
- "rcv_nxt[0x%llx]\n", pkt->seq, dr->rcv_nxt);
+ pr_err("RX out of sequence seq[0x%llx] rcv_nxt[0x%llx]\n",
+ pkt->seq, dr->rcv_nxt);
return 0;
}
@@ -464,8 +465,7 @@ static int handle_mcast(struct vnet_port *port, void *msgbuf)
struct vio_net_mcast_info *pkt = msgbuf;
if (pkt->tag.stype != VIO_SUBTYPE_ACK)
- printk(KERN_ERR PFX "%s: Got unexpected MCAST reply "
- "[%02x:%02x:%04x:%08x]\n",
+ pr_err("%s: Got unexpected MCAST reply [%02x:%02x:%04x:%08x]\n",
port->vp->dev->name,
pkt->tag.type,
pkt->tag.stype,
@@ -520,7 +520,7 @@ static void vnet_event(void *arg, int event)
}
if (unlikely(event != LDC_EVENT_DATA_READY)) {
- printk(KERN_WARNING PFX "Unexpected LDC event %d\n", event);
+ pr_warning("Unexpected LDC event %d\n", event);
spin_unlock_irqrestore(&vio->lock, flags);
return;
}
@@ -662,8 +662,7 @@ static int vnet_start_xmit(struct sk_buff *skb, struct net_device *dev)
netif_stop_queue(dev);
/* This is a hard error, log it. */
- printk(KERN_ERR PFX "%s: BUG! Tx Ring full when "
- "queue awake!\n", dev->name);
+ netdev_err(dev, "BUG! Tx Ring full when queue awake!\n");
dev->stats.tx_errors++;
}
spin_unlock_irqrestore(&port->vio.lock, flags);
@@ -696,8 +695,7 @@ static int vnet_start_xmit(struct sk_buff *skb, struct net_device *dev)
err = __vnet_tx_trigger(port);
if (unlikely(err < 0)) {
- printk(KERN_INFO PFX "%s: TX trigger error %d\n",
- dev->name, err);
+ netdev_info(dev, "TX trigger error %d\n", err);
d->hdr.state = VIO_DESC_FREE;
dev->stats.tx_carrier_errors++;
goto out_dropped_unlock;
@@ -952,12 +950,12 @@ static int __devinit vnet_port_alloc_tx_bufs(struct vnet_port *port)
err = -ENOMEM;
if (!buf) {
- printk(KERN_ERR "TX buffer allocation failure\n");
+ pr_err("TX buffer allocation failure\n");
goto err_out;
}
err = -EFAULT;
if ((unsigned long)buf & (8UL - 1)) {
- printk(KERN_ERR "TX buffer misaligned\n");
+ pr_err("TX buffer misaligned\n");
kfree(buf);
goto err_out;
}
@@ -1030,7 +1028,7 @@ static struct vnet * __devinit vnet_new(const u64 *local_mac)
dev = alloc_etherdev(sizeof(*vp));
if (!dev) {
- printk(KERN_ERR PFX "Etherdev alloc failed, aborting.\n");
+ pr_err("Etherdev alloc failed, aborting\n");
return ERR_PTR(-ENOMEM);
}
@@ -1056,12 +1054,11 @@ static struct vnet * __devinit vnet_new(const u64 *local_mac)
err = register_netdev(dev);
if (err) {
- printk(KERN_ERR PFX "Cannot register net device, "
- "aborting.\n");
+ pr_err("Cannot register net device, aborting\n");
goto err_out_free_dev;
}
- printk(KERN_INFO "%s: Sun LDOM vnet %pM\n", dev->name, dev->dev_addr);
+ netdev_info(dev, "Sun LDOM vnet %pM\n", dev->dev_addr);
list_add(&vp->list, &vnet_list);
@@ -1133,10 +1130,7 @@ static struct vio_driver_ops vnet_vio_ops = {
static void __devinit print_version(void)
{
- static int version_printed;
-
- if (version_printed++ == 0)
- printk(KERN_INFO "%s", version);
+ printk_once(KERN_INFO "%s", version);
}
const char *remote_macaddr_prop = "remote-mac-address";
@@ -1157,7 +1151,7 @@ static int __devinit vnet_port_probe(struct vio_dev *vdev,
vp = vnet_find_parent(hp, vdev->mp);
if (IS_ERR(vp)) {
- printk(KERN_ERR PFX "Cannot find port parent vnet.\n");
+ pr_err("Cannot find port parent vnet\n");
err = PTR_ERR(vp);
goto err_out_put_mdesc;
}
@@ -1165,15 +1159,14 @@ static int __devinit vnet_port_probe(struct vio_dev *vdev,
rmac = mdesc_get_property(hp, vdev->mp, remote_macaddr_prop, &len);
err = -ENODEV;
if (!rmac) {
- printk(KERN_ERR PFX "Port lacks %s property.\n",
- remote_macaddr_prop);
+ pr_err("Port lacks %s property\n", remote_macaddr_prop);
goto err_out_put_mdesc;
}
port = kzalloc(sizeof(*port), GFP_KERNEL);
err = -ENOMEM;
if (!port) {
- printk(KERN_ERR PFX "Cannot allocate vnet_port.\n");
+ pr_err("Cannot allocate vnet_port\n");
goto err_out_put_mdesc;
}
@@ -1214,9 +1207,8 @@ static int __devinit vnet_port_probe(struct vio_dev *vdev,
dev_set_drvdata(&vdev->dev, port);
- printk(KERN_INFO "%s: PORT ( remote-mac %pM%s )\n",
- vp->dev->name, port->raddr,
- switch_port ? " switch-port" : "");
+ pr_info("%s: PORT ( remote-mac %pM%s )\n",
+ vp->dev->name, port->raddr, switch_port ? " switch-port" : "");
vio_port_up(&port->vio);
diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c
index 99e423a5b9f1..b6eec8cea209 100644
--- a/drivers/net/tc35815.c
+++ b/drivers/net/tc35815.c
@@ -1167,7 +1167,7 @@ static void print_eth(const u8 *add)
static int tc35815_tx_full(struct net_device *dev)
{
struct tc35815_local *lp = netdev_priv(dev);
- return ((lp->tfd_start + 1) % TX_FD_NUM == lp->tfd_end);
+ return (lp->tfd_start + 1) % TX_FD_NUM == lp->tfd_end;
}
static void tc35815_restart(struct net_device *dev)
diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c
index 737df6032bbc..8b3dc1eb4015 100644
--- a/drivers/net/tehuti.c
+++ b/drivers/net/tehuti.c
@@ -92,7 +92,7 @@ static void bdx_rx_free(struct bdx_priv *priv);
static void bdx_tx_free(struct bdx_priv *priv);
/* Definitions needed by bdx_probe */
-static void bdx_ethtool_ops(struct net_device *netdev);
+static void bdx_set_ethtool_ops(struct net_device *netdev);
/*************************************************************************
* Print Info *
@@ -927,13 +927,6 @@ static void bdx_update_stats(struct bdx_priv *priv)
BDX_ASSERT((sizeof(struct bdx_stats) / sizeof(u64)) != i);
}
-static struct net_device_stats *bdx_get_stats(struct net_device *ndev)
-{
- struct bdx_priv *priv = netdev_priv(ndev);
- struct net_device_stats *net_stat = &priv->net_stats;
- return net_stat;
-}
-
static void print_rxdd(struct rxd_desc *rxdd, u32 rxd_val1, u16 len,
u16 rxd_vlan);
static void print_rxfd(struct rxf_desc *rxfd);
@@ -1220,6 +1213,7 @@ static void bdx_recycle_skb(struct bdx_priv *priv, struct rxd_desc *rxdd)
static int bdx_rx_receive(struct bdx_priv *priv, struct rxd_fifo *f, int budget)
{
+ struct net_device *ndev = priv->ndev;
struct sk_buff *skb, *skb2;
struct rxd_desc *rxdd;
struct rx_map *dm;
@@ -1273,7 +1267,7 @@ static int bdx_rx_receive(struct bdx_priv *priv, struct rxd_fifo *f, int budget)
if (unlikely(GET_RXD_ERR(rxd_val1))) {
DBG("rxd_err = 0x%x\n", GET_RXD_ERR(rxd_val1));
- priv->net_stats.rx_errors++;
+ ndev->stats.rx_errors++;
bdx_recycle_skb(priv, rxdd);
continue;
}
@@ -1300,15 +1294,16 @@ static int bdx_rx_receive(struct bdx_priv *priv, struct rxd_fifo *f, int budget)
bdx_rxdb_free_elem(db, rxdd->va_lo);
}
- priv->net_stats.rx_bytes += len;
+ ndev->stats.rx_bytes += len;
skb_put(skb, len);
- skb->ip_summed = CHECKSUM_UNNECESSARY;
- skb->protocol = eth_type_trans(skb, priv->ndev);
+ skb->protocol = eth_type_trans(skb, ndev);
/* Non-IP packets aren't checksum-offloaded */
if (GET_RXD_PKT_ID(rxd_val1) == 0)
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
+ else
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
NETIF_RX_MUX(priv, rxd_val1, rxd_vlan, skb);
@@ -1316,7 +1311,7 @@ static int bdx_rx_receive(struct bdx_priv *priv, struct rxd_fifo *f, int budget)
break;
}
- priv->net_stats.rx_packets += done;
+ ndev->stats.rx_packets += done;
/* FIXME: do smth to minimize pci accesses */
WRITE_REG(priv, f->m.reg_RPTR, f->m.rptr & TXF_WPTR_WR_PTR);
@@ -1712,8 +1707,8 @@ static netdev_tx_t bdx_tx_transmit(struct sk_buff *skb,
#ifdef BDX_LLTX
ndev->trans_start = jiffies; /* NETIF_F_LLTX driver :( */
#endif
- priv->net_stats.tx_packets++;
- priv->net_stats.tx_bytes += skb->len;
+ ndev->stats.tx_packets++;
+ ndev->stats.tx_bytes += skb->len;
if (priv->tx_level < BDX_MIN_TX_LEVEL) {
DBG("%s: %s: TX Q STOP level %d\n",
@@ -1888,7 +1883,6 @@ static const struct net_device_ops bdx_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
.ndo_do_ioctl = bdx_ioctl,
.ndo_set_multicast_list = bdx_setmulti,
- .ndo_get_stats = bdx_get_stats,
.ndo_change_mtu = bdx_change_mtu,
.ndo_set_mac_address = bdx_set_mac,
.ndo_vlan_rx_register = bdx_vlan_rx_register,
@@ -2012,7 +2006,7 @@ bdx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
ndev->netdev_ops = &bdx_netdev_ops;
ndev->tx_queue_len = BDX_NDEV_TXQ_LEN;
- bdx_ethtool_ops(ndev); /* ethtool interface */
+ bdx_set_ethtool_ops(ndev); /* ethtool interface */
/* these fields are used for info purposes only
* so we can have them same for all ports of the board */
@@ -2417,10 +2411,10 @@ static void bdx_get_ethtool_stats(struct net_device *netdev,
}
/*
- * bdx_ethtool_ops - ethtool interface implementation
+ * bdx_set_ethtool_ops - ethtool interface implementation
* @netdev
*/
-static void bdx_ethtool_ops(struct net_device *netdev)
+static void bdx_set_ethtool_ops(struct net_device *netdev)
{
static const struct ethtool_ops bdx_ethtool_ops = {
.get_settings = bdx_get_settings,
diff --git a/drivers/net/tehuti.h b/drivers/net/tehuti.h
index 67e3b71bf705..b6ba8601e2b5 100644
--- a/drivers/net/tehuti.h
+++ b/drivers/net/tehuti.h
@@ -269,7 +269,6 @@ struct bdx_priv {
u32 msg_enable;
int stats_flag;
struct bdx_stats hw_stats;
- struct net_device_stats net_stats;
struct pci_dev *pdev;
struct pci_nic *nic;
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index bc3af78a869f..852e917778f8 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -69,10 +69,10 @@
#define DRV_MODULE_NAME "tg3"
#define TG3_MAJ_NUM 3
-#define TG3_MIN_NUM 113
+#define TG3_MIN_NUM 115
#define DRV_MODULE_VERSION \
__stringify(TG3_MAJ_NUM) "." __stringify(TG3_MIN_NUM)
-#define DRV_MODULE_RELDATE "August 2, 2010"
+#define DRV_MODULE_RELDATE "October 14, 2010"
#define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0
@@ -101,9 +101,15 @@
* You can't change the ring sizes, but you can change where you place
* them in the NIC onboard memory.
*/
-#define TG3_RX_RING_SIZE 512
+#define TG3_RX_STD_RING_SIZE(tp) \
+ ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || \
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) ? \
+ RX_STD_MAX_SIZE_5717 : 512)
#define TG3_DEF_RX_RING_PENDING 200
-#define TG3_RX_JUMBO_RING_SIZE 256
+#define TG3_RX_JMB_RING_SIZE(tp) \
+ ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || \
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) ? \
+ 1024 : 256)
#define TG3_DEF_RX_JUMBO_RING_PENDING 100
#define TG3_RSS_INDIR_TBL_SIZE 128
@@ -113,19 +119,16 @@
* hw multiply/modulo instructions. Another solution would be to
* replace things like '% foo' with '& (foo - 1)'.
*/
-#define TG3_RX_RCB_RING_SIZE(tp) \
- (((tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) && \
- !(tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) ? 1024 : 512)
#define TG3_TX_RING_SIZE 512
#define TG3_DEF_TX_RING_PENDING (TG3_TX_RING_SIZE - 1)
-#define TG3_RX_RING_BYTES (sizeof(struct tg3_rx_buffer_desc) * \
- TG3_RX_RING_SIZE)
-#define TG3_RX_JUMBO_RING_BYTES (sizeof(struct tg3_ext_rx_buffer_desc) * \
- TG3_RX_JUMBO_RING_SIZE)
-#define TG3_RX_RCB_RING_BYTES(tp) (sizeof(struct tg3_rx_buffer_desc) * \
- TG3_RX_RCB_RING_SIZE(tp))
+#define TG3_RX_STD_RING_BYTES(tp) \
+ (sizeof(struct tg3_rx_buffer_desc) * TG3_RX_STD_RING_SIZE(tp))
+#define TG3_RX_JMB_RING_BYTES(tp) \
+ (sizeof(struct tg3_ext_rx_buffer_desc) * TG3_RX_JMB_RING_SIZE(tp))
+#define TG3_RX_RCB_RING_BYTES(tp) \
+ (sizeof(struct tg3_rx_buffer_desc) * (tp->rx_ret_ring_mask + 1))
#define TG3_TX_RING_BYTES (sizeof(struct tg3_tx_buffer_desc) * \
TG3_TX_RING_SIZE)
#define NEXT_TX(N) (((N) + 1) & (TG3_TX_RING_SIZE - 1))
@@ -143,11 +146,11 @@
#define TG3_RX_STD_MAP_SZ TG3_RX_DMA_TO_MAP_SZ(TG3_RX_STD_DMA_SZ)
#define TG3_RX_JMB_MAP_SZ TG3_RX_DMA_TO_MAP_SZ(TG3_RX_JMB_DMA_SZ)
-#define TG3_RX_STD_BUFF_RING_SIZE \
- (sizeof(struct ring_info) * TG3_RX_RING_SIZE)
+#define TG3_RX_STD_BUFF_RING_SIZE(tp) \
+ (sizeof(struct ring_info) * TG3_RX_STD_RING_SIZE(tp))
-#define TG3_RX_JMB_BUFF_RING_SIZE \
- (sizeof(struct ring_info) * TG3_RX_JUMBO_RING_SIZE)
+#define TG3_RX_JMB_BUFF_RING_SIZE(tp) \
+ (sizeof(struct ring_info) * TG3_RX_JMB_RING_SIZE(tp))
/* Due to a hardware bug, the 5701 can only DMA to memory addresses
* that are at least dword aligned when used in PCIX mode. The driver
@@ -264,7 +267,6 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = {
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57788)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5717)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5718)},
- {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5724)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57781)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57785)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57761)},
@@ -752,42 +754,6 @@ static void tg3_int_reenable(struct tg3_napi *tnapi)
HOSTCC_MODE_ENABLE | tnapi->coal_now);
}
-static void tg3_napi_disable(struct tg3 *tp)
-{
- int i;
-
- for (i = tp->irq_cnt - 1; i >= 0; i--)
- napi_disable(&tp->napi[i].napi);
-}
-
-static void tg3_napi_enable(struct tg3 *tp)
-{
- int i;
-
- for (i = 0; i < tp->irq_cnt; i++)
- napi_enable(&tp->napi[i].napi);
-}
-
-static inline void tg3_netif_stop(struct tg3 *tp)
-{
- tp->dev->trans_start = jiffies; /* prevent tx timeout */
- tg3_napi_disable(tp);
- netif_tx_disable(tp->dev);
-}
-
-static inline void tg3_netif_start(struct tg3 *tp)
-{
- /* NOTE: unconditional netif_tx_wake_all_queues is only
- * appropriate so long as all callers are assured to
- * have free tx slots (such as after tg3_init_hw)
- */
- netif_tx_wake_all_queues(tp->dev);
-
- tg3_napi_enable(tp);
- tp->napi[0].hw_status->status |= SD_STATUS_UPDATED;
- tg3_enable_ints(tp);
-}
-
static void tg3_switch_clocks(struct tg3 *tp)
{
u32 clock_ctrl;
@@ -1196,6 +1162,52 @@ static void tg3_mdio_fini(struct tg3 *tp)
}
}
+static int tg3_phy_cl45_write(struct tg3 *tp, u32 devad, u32 addr, u32 val)
+{
+ int err;
+
+ err = tg3_writephy(tp, MII_TG3_MMD_CTRL, devad);
+ if (err)
+ goto done;
+
+ err = tg3_writephy(tp, MII_TG3_MMD_ADDRESS, addr);
+ if (err)
+ goto done;
+
+ err = tg3_writephy(tp, MII_TG3_MMD_CTRL,
+ MII_TG3_MMD_CTRL_DATA_NOINC | devad);
+ if (err)
+ goto done;
+
+ err = tg3_writephy(tp, MII_TG3_MMD_ADDRESS, val);
+
+done:
+ return err;
+}
+
+static int tg3_phy_cl45_read(struct tg3 *tp, u32 devad, u32 addr, u32 *val)
+{
+ int err;
+
+ err = tg3_writephy(tp, MII_TG3_MMD_CTRL, devad);
+ if (err)
+ goto done;
+
+ err = tg3_writephy(tp, MII_TG3_MMD_ADDRESS, addr);
+ if (err)
+ goto done;
+
+ err = tg3_writephy(tp, MII_TG3_MMD_CTRL,
+ MII_TG3_MMD_CTRL_DATA_NOINC | devad);
+ if (err)
+ goto done;
+
+ err = tg3_readphy(tp, MII_TG3_MMD_ADDRESS, val);
+
+done:
+ return err;
+}
+
/* tp->lock is held. */
static inline void tg3_generate_fw_event(struct tg3 *tp)
{
@@ -1572,6 +1584,17 @@ static void tg3_phy_fini(struct tg3 *tp)
}
}
+static int tg3_phydsp_read(struct tg3 *tp, u32 reg, u32 *val)
+{
+ int err;
+
+ err = tg3_writephy(tp, MII_TG3_DSP_ADDRESS, reg);
+ if (!err)
+ err = tg3_readphy(tp, MII_TG3_DSP_RW_PORT, val);
+
+ return err;
+}
+
static int tg3_phydsp_write(struct tg3 *tp, u32 reg, u32 val)
{
int err;
@@ -1735,6 +1758,42 @@ static void tg3_phy_apply_otp(struct tg3 *tp)
tg3_writephy(tp, MII_TG3_AUX_CTRL, phy);
}
+static void tg3_phy_eee_adjust(struct tg3 *tp, u32 current_link_up)
+{
+ u32 val;
+
+ if (!(tp->phy_flags & TG3_PHYFLG_EEE_CAP))
+ return;
+
+ tp->setlpicnt = 0;
+
+ if (tp->link_config.autoneg == AUTONEG_ENABLE &&
+ current_link_up == 1 &&
+ (tp->link_config.active_speed == SPEED_1000 ||
+ (tp->link_config.active_speed == SPEED_100 &&
+ tp->link_config.active_duplex == DUPLEX_FULL))) {
+ u32 eeectl;
+
+ if (tp->link_config.active_speed == SPEED_1000)
+ eeectl = TG3_CPMU_EEE_CTRL_EXIT_16_5_US;
+ else
+ eeectl = TG3_CPMU_EEE_CTRL_EXIT_36_US;
+
+ tw32(TG3_CPMU_EEE_CTRL, eeectl);
+
+ tg3_phy_cl45_read(tp, 0x7, TG3_CL45_D7_EEERES_STAT, &val);
+
+ if (val == TG3_CL45_D7_EEERES_STAT_LP_1000T ||
+ val == TG3_CL45_D7_EEERES_STAT_LP_100TX)
+ tp->setlpicnt = 2;
+ }
+
+ if (!tp->setlpicnt) {
+ val = tr32(TG3_CPMU_EEE_MODE);
+ tw32(TG3_CPMU_EEE_MODE, val & ~TG3_CPMU_EEEMD_LPI_ENABLE);
+ }
+}
+
static int tg3_wait_macro_done(struct tg3 *tp)
{
int limit = 100;
@@ -1917,19 +1976,16 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp)
*/
static int tg3_phy_reset(struct tg3 *tp)
{
- u32 cpmuctrl;
- u32 phy_status;
+ u32 val, cpmuctrl;
int err;
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
- u32 val;
-
val = tr32(GRC_MISC_CFG);
tw32_f(GRC_MISC_CFG, val & ~GRC_MISC_CFG_EPHY_IDDQ);
udelay(40);
}
- err = tg3_readphy(tp, MII_BMSR, &phy_status);
- err |= tg3_readphy(tp, MII_BMSR, &phy_status);
+ err = tg3_readphy(tp, MII_BMSR, &val);
+ err |= tg3_readphy(tp, MII_BMSR, &val);
if (err != 0)
return -EBUSY;
@@ -1961,18 +2017,14 @@ static int tg3_phy_reset(struct tg3 *tp)
return err;
if (cpmuctrl & CPMU_CTRL_GPHY_10MB_RXONLY) {
- u32 phy;
-
- phy = MII_TG3_DSP_EXP8_AEDW | MII_TG3_DSP_EXP8_REJ2MHz;
- tg3_phydsp_write(tp, MII_TG3_DSP_EXP8, phy);
+ val = MII_TG3_DSP_EXP8_AEDW | MII_TG3_DSP_EXP8_REJ2MHz;
+ tg3_phydsp_write(tp, MII_TG3_DSP_EXP8, val);
tw32(TG3_CPMU_CTRL, cpmuctrl);
}
if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX ||
GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5761_AX) {
- u32 val;
-
val = tr32(TG3_CPMU_LSPD_1000MB_CLK);
if ((val & CPMU_LSPD_1000MB_MACCLK_MASK) ==
CPMU_LSPD_1000MB_MACCLK_12_5) {
@@ -2028,23 +2080,19 @@ out:
/* Cannot do read-modify-write on 5401 */
tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x4c20);
} else if (tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) {
- u32 phy_reg;
-
/* Set bit 14 with read-modify-write to preserve other bits */
if (!tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0007) &&
- !tg3_readphy(tp, MII_TG3_AUX_CTRL, &phy_reg))
- tg3_writephy(tp, MII_TG3_AUX_CTRL, phy_reg | 0x4000);
+ !tg3_readphy(tp, MII_TG3_AUX_CTRL, &val))
+ tg3_writephy(tp, MII_TG3_AUX_CTRL, val | 0x4000);
}
/* Set phy register 0x10 bit 0 to high fifo elasticity to support
* jumbo frames transmission.
*/
if (tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) {
- u32 phy_reg;
-
- if (!tg3_readphy(tp, MII_TG3_EXT_CTRL, &phy_reg))
+ if (!tg3_readphy(tp, MII_TG3_EXT_CTRL, &val))
tg3_writephy(tp, MII_TG3_EXT_CTRL,
- phy_reg | MII_TG3_EXT_CTRL_FIFO_ELASTIC);
+ val | MII_TG3_EXT_CTRL_FIFO_ELASTIC);
}
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
@@ -2920,6 +2968,44 @@ static void tg3_phy_copper_begin(struct tg3 *tp)
tg3_writephy(tp, MII_TG3_CTRL, new_adv);
}
+ if (tp->phy_flags & TG3_PHYFLG_EEE_CAP) {
+ u32 val = 0;
+
+ tw32(TG3_CPMU_EEE_MODE,
+ tr32(TG3_CPMU_EEE_MODE) & ~TG3_CPMU_EEEMD_LPI_ENABLE);
+
+ /* Enable SM_DSP clock and tx 6dB coding. */
+ val = MII_TG3_AUXCTL_SHDWSEL_AUXCTL |
+ MII_TG3_AUXCTL_ACTL_SMDSP_ENA |
+ MII_TG3_AUXCTL_ACTL_TX_6DB;
+ tg3_writephy(tp, MII_TG3_AUX_CTRL, val);
+
+ if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) &&
+ !tg3_phydsp_read(tp, MII_TG3_DSP_CH34TP2, &val))
+ tg3_phydsp_write(tp, MII_TG3_DSP_CH34TP2,
+ val | MII_TG3_DSP_CH34TP2_HIBW01);
+
+ if (tp->link_config.autoneg == AUTONEG_ENABLE) {
+ /* Advertise 100-BaseTX EEE ability */
+ if (tp->link_config.advertising &
+ (ADVERTISED_100baseT_Half |
+ ADVERTISED_100baseT_Full))
+ val |= TG3_CL45_D7_EEEADV_CAP_100TX;
+ /* Advertise 1000-BaseT EEE ability */
+ if (tp->link_config.advertising &
+ (ADVERTISED_1000baseT_Half |
+ ADVERTISED_1000baseT_Full))
+ val |= TG3_CL45_D7_EEEADV_CAP_1000T;
+ }
+ tg3_phy_cl45_write(tp, 0x7, TG3_CL45_D7_EEEADV_CAP, val);
+
+ /* Turn off SM_DSP clock. */
+ val = MII_TG3_AUXCTL_SHDWSEL_AUXCTL |
+ MII_TG3_AUXCTL_ACTL_TX_6DB;
+ tg3_writephy(tp, MII_TG3_AUX_CTRL, val);
+ }
+
if (tp->link_config.autoneg == AUTONEG_DISABLE &&
tp->link_config.speed != SPEED_INVALID) {
u32 bmcr, orig_bmcr;
@@ -3060,7 +3146,7 @@ static int tg3_adv_1000T_flowctrl_ok(struct tg3 *tp, u32 *lcladv, u32 *rmtadv)
static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
{
int current_link_up;
- u32 bmsr, dummy;
+ u32 bmsr, val;
u32 lcl_adv, rmt_adv;
u16 current_speed;
u8 current_duplex;
@@ -3140,8 +3226,8 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
}
/* Clear pending interrupts... */
- tg3_readphy(tp, MII_TG3_ISTAT, &dummy);
- tg3_readphy(tp, MII_TG3_ISTAT, &dummy);
+ tg3_readphy(tp, MII_TG3_ISTAT, &val);
+ tg3_readphy(tp, MII_TG3_ISTAT, &val);
if (tp->phy_flags & TG3_PHYFLG_USE_MI_INTERRUPT)
tg3_writephy(tp, MII_TG3_IMASK, ~MII_TG3_INT_LINKCHG);
@@ -3162,8 +3248,6 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
current_duplex = DUPLEX_INVALID;
if (tp->phy_flags & TG3_PHYFLG_CAPACITIVE_COUPLING) {
- u32 val;
-
tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x4007);
tg3_readphy(tp, MII_TG3_AUX_CTRL, &val);
if (!(val & (1 << 10))) {
@@ -3238,13 +3322,11 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
relink:
if (current_link_up == 0 || (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER)) {
- u32 tmp;
-
tg3_phy_copper_begin(tp);
- tg3_readphy(tp, MII_BMSR, &tmp);
- if (!tg3_readphy(tp, MII_BMSR, &tmp) &&
- (tmp & BMSR_LSTATUS))
+ tg3_readphy(tp, MII_BMSR, &bmsr);
+ if (!tg3_readphy(tp, MII_BMSR, &bmsr) &&
+ (bmsr & BMSR_LSTATUS))
current_link_up = 1;
}
@@ -3285,6 +3367,8 @@ relink:
tw32_f(MAC_MODE, tp->mac_mode);
udelay(40);
+ tg3_phy_eee_adjust(tp, current_link_up);
+
if (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) {
/* Polled via timer. */
tw32_f(MAC_EVENT, 0);
@@ -4353,6 +4437,11 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset)
return err;
}
+static inline int tg3_irq_sync(struct tg3 *tp)
+{
+ return tp->irq_sync;
+}
+
/* This is called whenever we suspect that the system chipset is re-
* ordering the sequence of MMIO to the tx send mailbox. The symptom
* is bogus tx completions. We try to recover by setting the
@@ -4484,22 +4573,21 @@ static int tg3_alloc_rx_skb(struct tg3 *tp, struct tg3_rx_prodring_set *tpr,
u32 opaque_key, u32 dest_idx_unmasked)
{
struct tg3_rx_buffer_desc *desc;
- struct ring_info *map, *src_map;
+ struct ring_info *map;
struct sk_buff *skb;
dma_addr_t mapping;
int skb_size, dest_idx;
- src_map = NULL;
switch (opaque_key) {
case RXD_OPAQUE_RING_STD:
- dest_idx = dest_idx_unmasked % TG3_RX_RING_SIZE;
+ dest_idx = dest_idx_unmasked & tp->rx_std_ring_mask;
desc = &tpr->rx_std[dest_idx];
map = &tpr->rx_std_buffers[dest_idx];
skb_size = tp->rx_pkt_map_sz;
break;
case RXD_OPAQUE_RING_JUMBO:
- dest_idx = dest_idx_unmasked % TG3_RX_JUMBO_RING_SIZE;
+ dest_idx = dest_idx_unmasked & tp->rx_jmb_ring_mask;
desc = &tpr->rx_jmb[dest_idx].std;
map = &tpr->rx_jmb_buffers[dest_idx];
skb_size = TG3_RX_JMB_MAP_SZ;
@@ -4549,12 +4637,12 @@ static void tg3_recycle_rx(struct tg3_napi *tnapi,
struct tg3 *tp = tnapi->tp;
struct tg3_rx_buffer_desc *src_desc, *dest_desc;
struct ring_info *src_map, *dest_map;
- struct tg3_rx_prodring_set *spr = &tp->prodring[0];
+ struct tg3_rx_prodring_set *spr = &tp->napi[0].prodring;
int dest_idx;
switch (opaque_key) {
case RXD_OPAQUE_RING_STD:
- dest_idx = dest_idx_unmasked % TG3_RX_RING_SIZE;
+ dest_idx = dest_idx_unmasked & tp->rx_std_ring_mask;
dest_desc = &dpr->rx_std[dest_idx];
dest_map = &dpr->rx_std_buffers[dest_idx];
src_desc = &spr->rx_std[src_idx];
@@ -4562,7 +4650,7 @@ static void tg3_recycle_rx(struct tg3_napi *tnapi,
break;
case RXD_OPAQUE_RING_JUMBO:
- dest_idx = dest_idx_unmasked % TG3_RX_JUMBO_RING_SIZE;
+ dest_idx = dest_idx_unmasked & tp->rx_jmb_ring_mask;
dest_desc = &dpr->rx_jmb[dest_idx].std;
dest_map = &dpr->rx_jmb_buffers[dest_idx];
src_desc = &spr->rx_jmb[src_idx].std;
@@ -4619,7 +4707,7 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
u32 sw_idx = tnapi->rx_rcb_ptr;
u16 hw_idx;
int received;
- struct tg3_rx_prodring_set *tpr = tnapi->prodring;
+ struct tg3_rx_prodring_set *tpr = &tnapi->prodring;
hw_idx = *(tnapi->rx_rcb_prod_idx);
/*
@@ -4644,13 +4732,13 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
desc_idx = desc->opaque & RXD_OPAQUE_INDEX_MASK;
opaque_key = desc->opaque & RXD_OPAQUE_RING_MASK;
if (opaque_key == RXD_OPAQUE_RING_STD) {
- ri = &tp->prodring[0].rx_std_buffers[desc_idx];
+ ri = &tp->napi[0].prodring.rx_std_buffers[desc_idx];
dma_addr = dma_unmap_addr(ri, mapping);
skb = ri->skb;
post_ptr = &std_prod_idx;
rx_std_posted++;
} else if (opaque_key == RXD_OPAQUE_RING_JUMBO) {
- ri = &tp->prodring[0].rx_jmb_buffers[desc_idx];
+ ri = &tp->napi[0].prodring.rx_jmb_buffers[desc_idx];
dma_addr = dma_unmap_addr(ri, mapping);
skb = ri->skb;
post_ptr = &jmb_prod_idx;
@@ -4666,7 +4754,7 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
desc_idx, *post_ptr);
drop_it_no_recycle:
/* Other statistics kept track of by card. */
- tp->net_stats.rx_dropped++;
+ tp->rx_dropped++;
goto next_pkt;
}
@@ -4719,14 +4807,14 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
>> RXD_TCPCSUM_SHIFT) == 0xffff))
skb->ip_summed = CHECKSUM_UNNECESSARY;
else
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
skb->protocol = eth_type_trans(skb, tp->dev);
if (len > (tp->dev->mtu + ETH_HLEN) &&
skb->protocol != htons(ETH_P_8021Q)) {
dev_kfree_skb(skb);
- goto next_pkt;
+ goto drop_it_no_recycle;
}
if (desc->type_flags & RXD_FLAG_VLAN &&
@@ -4762,7 +4850,8 @@ next_pkt:
(*post_ptr)++;
if (unlikely(rx_std_posted >= tp->rx_std_max_post)) {
- tpr->rx_std_prod_idx = std_prod_idx % TG3_RX_RING_SIZE;
+ tpr->rx_std_prod_idx = std_prod_idx &
+ tp->rx_std_ring_mask;
tw32_rx_mbox(TG3_RX_STD_PROD_IDX_REG,
tpr->rx_std_prod_idx);
work_mask &= ~RXD_OPAQUE_RING_STD;
@@ -4770,7 +4859,7 @@ next_pkt:
}
next_pkt_nopost:
sw_idx++;
- sw_idx &= (TG3_RX_RCB_RING_SIZE(tp) - 1);
+ sw_idx &= tp->rx_ret_ring_mask;
/* Refresh hw_idx to see if there is new work */
if (sw_idx == hw_idx) {
@@ -4786,13 +4875,14 @@ next_pkt_nopost:
/* Refill RX ring(s). */
if (!(tp->tg3_flags3 & TG3_FLG3_ENABLE_RSS)) {
if (work_mask & RXD_OPAQUE_RING_STD) {
- tpr->rx_std_prod_idx = std_prod_idx % TG3_RX_RING_SIZE;
+ tpr->rx_std_prod_idx = std_prod_idx &
+ tp->rx_std_ring_mask;
tw32_rx_mbox(TG3_RX_STD_PROD_IDX_REG,
tpr->rx_std_prod_idx);
}
if (work_mask & RXD_OPAQUE_RING_JUMBO) {
- tpr->rx_jmb_prod_idx = jmb_prod_idx %
- TG3_RX_JUMBO_RING_SIZE;
+ tpr->rx_jmb_prod_idx = jmb_prod_idx &
+ tp->rx_jmb_ring_mask;
tw32_rx_mbox(TG3_RX_JMB_PROD_IDX_REG,
tpr->rx_jmb_prod_idx);
}
@@ -4803,8 +4893,8 @@ next_pkt_nopost:
*/
smp_wmb();
- tpr->rx_std_prod_idx = std_prod_idx % TG3_RX_RING_SIZE;
- tpr->rx_jmb_prod_idx = jmb_prod_idx % TG3_RX_JUMBO_RING_SIZE;
+ tpr->rx_std_prod_idx = std_prod_idx & tp->rx_std_ring_mask;
+ tpr->rx_jmb_prod_idx = jmb_prod_idx & tp->rx_jmb_ring_mask;
if (tnapi != &tp->napi[1])
napi_schedule(&tp->napi[1].napi);
@@ -4860,9 +4950,11 @@ static int tg3_rx_prodring_xfer(struct tg3 *tp,
if (spr->rx_std_cons_idx < src_prod_idx)
cpycnt = src_prod_idx - spr->rx_std_cons_idx;
else
- cpycnt = TG3_RX_RING_SIZE - spr->rx_std_cons_idx;
+ cpycnt = tp->rx_std_ring_mask + 1 -
+ spr->rx_std_cons_idx;
- cpycnt = min(cpycnt, TG3_RX_RING_SIZE - dpr->rx_std_prod_idx);
+ cpycnt = min(cpycnt,
+ tp->rx_std_ring_mask + 1 - dpr->rx_std_prod_idx);
si = spr->rx_std_cons_idx;
di = dpr->rx_std_prod_idx;
@@ -4896,10 +4988,10 @@ static int tg3_rx_prodring_xfer(struct tg3 *tp,
dbd->addr_lo = sbd->addr_lo;
}
- spr->rx_std_cons_idx = (spr->rx_std_cons_idx + cpycnt) %
- TG3_RX_RING_SIZE;
- dpr->rx_std_prod_idx = (dpr->rx_std_prod_idx + cpycnt) %
- TG3_RX_RING_SIZE;
+ spr->rx_std_cons_idx = (spr->rx_std_cons_idx + cpycnt) &
+ tp->rx_std_ring_mask;
+ dpr->rx_std_prod_idx = (dpr->rx_std_prod_idx + cpycnt) &
+ tp->rx_std_ring_mask;
}
while (1) {
@@ -4916,10 +5008,11 @@ static int tg3_rx_prodring_xfer(struct tg3 *tp,
if (spr->rx_jmb_cons_idx < src_prod_idx)
cpycnt = src_prod_idx - spr->rx_jmb_cons_idx;
else
- cpycnt = TG3_RX_JUMBO_RING_SIZE - spr->rx_jmb_cons_idx;
+ cpycnt = tp->rx_jmb_ring_mask + 1 -
+ spr->rx_jmb_cons_idx;
cpycnt = min(cpycnt,
- TG3_RX_JUMBO_RING_SIZE - dpr->rx_jmb_prod_idx);
+ tp->rx_jmb_ring_mask + 1 - dpr->rx_jmb_prod_idx);
si = spr->rx_jmb_cons_idx;
di = dpr->rx_jmb_prod_idx;
@@ -4953,10 +5046,10 @@ static int tg3_rx_prodring_xfer(struct tg3 *tp,
dbd->addr_lo = sbd->addr_lo;
}
- spr->rx_jmb_cons_idx = (spr->rx_jmb_cons_idx + cpycnt) %
- TG3_RX_JUMBO_RING_SIZE;
- dpr->rx_jmb_prod_idx = (dpr->rx_jmb_prod_idx + cpycnt) %
- TG3_RX_JUMBO_RING_SIZE;
+ spr->rx_jmb_cons_idx = (spr->rx_jmb_cons_idx + cpycnt) &
+ tp->rx_jmb_ring_mask;
+ dpr->rx_jmb_prod_idx = (dpr->rx_jmb_prod_idx + cpycnt) &
+ tp->rx_jmb_ring_mask;
}
return err;
@@ -4981,14 +5074,14 @@ static int tg3_poll_work(struct tg3_napi *tnapi, int work_done, int budget)
work_done += tg3_rx(tnapi, budget - work_done);
if ((tp->tg3_flags3 & TG3_FLG3_ENABLE_RSS) && tnapi == &tp->napi[1]) {
- struct tg3_rx_prodring_set *dpr = &tp->prodring[0];
+ struct tg3_rx_prodring_set *dpr = &tp->napi[0].prodring;
int i, err = 0;
u32 std_prod_idx = dpr->rx_std_prod_idx;
u32 jmb_prod_idx = dpr->rx_jmb_prod_idx;
for (i = 1; i < tp->irq_cnt; i++)
err |= tg3_rx_prodring_xfer(tp, dpr,
- tp->napi[i].prodring);
+ &tp->napi[i].prodring);
wmb();
@@ -5098,6 +5191,59 @@ tx_recovery:
return work_done;
}
+static void tg3_napi_disable(struct tg3 *tp)
+{
+ int i;
+
+ for (i = tp->irq_cnt - 1; i >= 0; i--)
+ napi_disable(&tp->napi[i].napi);
+}
+
+static void tg3_napi_enable(struct tg3 *tp)
+{
+ int i;
+
+ for (i = 0; i < tp->irq_cnt; i++)
+ napi_enable(&tp->napi[i].napi);
+}
+
+static void tg3_napi_init(struct tg3 *tp)
+{
+ int i;
+
+ netif_napi_add(tp->dev, &tp->napi[0].napi, tg3_poll, 64);
+ for (i = 1; i < tp->irq_cnt; i++)
+ netif_napi_add(tp->dev, &tp->napi[i].napi, tg3_poll_msix, 64);
+}
+
+static void tg3_napi_fini(struct tg3 *tp)
+{
+ int i;
+
+ for (i = 0; i < tp->irq_cnt; i++)
+ netif_napi_del(&tp->napi[i].napi);
+}
+
+static inline void tg3_netif_stop(struct tg3 *tp)
+{
+ tp->dev->trans_start = jiffies; /* prevent tx timeout */
+ tg3_napi_disable(tp);
+ netif_tx_disable(tp->dev);
+}
+
+static inline void tg3_netif_start(struct tg3 *tp)
+{
+ /* NOTE: unconditional netif_tx_wake_all_queues is only
+ * appropriate so long as all callers are assured to
+ * have free tx slots (such as after tg3_init_hw)
+ */
+ netif_tx_wake_all_queues(tp->dev);
+
+ tg3_napi_enable(tp);
+ tp->napi[0].hw_status->status |= SD_STATUS_UPDATED;
+ tg3_enable_ints(tp);
+}
+
static void tg3_irq_quiesce(struct tg3 *tp)
{
int i;
@@ -5111,11 +5257,6 @@ static void tg3_irq_quiesce(struct tg3 *tp)
synchronize_irq(tp->napi[i].irq_vec);
}
-static inline int tg3_irq_sync(struct tg3 *tp)
-{
- return tp->irq_sync;
-}
-
/* Fully shutdown all tg3 driver activity elsewhere in the system.
* If irq_sync is non-zero, then the IRQ handler must be synchronized
* with as well. Most of the time, this is not necessary except when
@@ -5404,8 +5545,7 @@ static inline int tg3_4g_overflow_test(dma_addr_t mapping, int len)
{
u32 base = (u32) mapping & 0xffffffff;
- return ((base > 0xffffdcc0) &&
- (base + len + 8 < base));
+ return (base > 0xffffdcc0) && (base + len + 8 < base);
}
/* Test for DMA addresses > 40-bit */
@@ -5414,7 +5554,7 @@ static inline int tg3_40bit_overflow_test(struct tg3 *tp, dma_addr_t mapping,
{
#if defined(CONFIG_HIGHMEM) && (BITS_PER_LONG == 64)
if (tp->tg3_flags & TG3_FLAG_40BIT_DMA_BUG)
- return (((u64) mapping + len) > DMA_BIT_MASK(40));
+ return ((u64) mapping + len) > DMA_BIT_MASK(40);
return 0;
#else
return 0;
@@ -5574,9 +5714,9 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb,
goto out_unlock;
}
- if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6)
+ if (skb_is_gso_v6(skb)) {
hdrlen = skb_headlen(skb) - ETH_HLEN;
- else {
+ } else {
struct iphdr *iph = ip_hdr(skb);
tcp_opt_len = tcp_optlen(skb);
@@ -5605,7 +5745,7 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb,
}
#if TG3_VLAN_TAG_USED
- if (tp->vlgrp != NULL && vlan_tx_tag_present(skb))
+ if (vlan_tx_tag_present(skb))
base_flags |= (TXD_FLAG_VLAN |
(vlan_tx_tag_get(skb) << 16));
#endif
@@ -5798,7 +5938,7 @@ static netdev_tx_t tg3_start_xmit_dma_bug(struct sk_buff *skb,
iph = ip_hdr(skb);
tcp_opt_len = tcp_optlen(skb);
- if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) {
+ if (skb_is_gso_v6(skb)) {
hdr_len = skb_headlen(skb) - ETH_HLEN;
} else {
u32 ip_tcp_len;
@@ -5851,7 +5991,7 @@ static netdev_tx_t tg3_start_xmit_dma_bug(struct sk_buff *skb,
}
}
#if TG3_VLAN_TAG_USED
- if (tp->vlgrp != NULL && vlan_tx_tag_present(skb))
+ if (vlan_tx_tag_present(skb))
base_flags |= (TXD_FLAG_VLAN |
(vlan_tx_tag_get(skb) << 16));
#endif
@@ -6057,16 +6197,16 @@ static void tg3_rx_prodring_free(struct tg3 *tp,
{
int i;
- if (tpr != &tp->prodring[0]) {
+ if (tpr != &tp->napi[0].prodring) {
for (i = tpr->rx_std_cons_idx; i != tpr->rx_std_prod_idx;
- i = (i + 1) % TG3_RX_RING_SIZE)
+ i = (i + 1) & tp->rx_std_ring_mask)
tg3_rx_skb_free(tp, &tpr->rx_std_buffers[i],
tp->rx_pkt_map_sz);
if (tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) {
for (i = tpr->rx_jmb_cons_idx;
i != tpr->rx_jmb_prod_idx;
- i = (i + 1) % TG3_RX_JUMBO_RING_SIZE) {
+ i = (i + 1) & tp->rx_jmb_ring_mask) {
tg3_rx_skb_free(tp, &tpr->rx_jmb_buffers[i],
TG3_RX_JMB_MAP_SZ);
}
@@ -6075,12 +6215,13 @@ static void tg3_rx_prodring_free(struct tg3 *tp,
return;
}
- for (i = 0; i < TG3_RX_RING_SIZE; i++)
+ for (i = 0; i <= tp->rx_std_ring_mask; i++)
tg3_rx_skb_free(tp, &tpr->rx_std_buffers[i],
tp->rx_pkt_map_sz);
- if (tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) {
- for (i = 0; i < TG3_RX_JUMBO_RING_SIZE; i++)
+ if ((tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) &&
+ !(tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) {
+ for (i = 0; i <= tp->rx_jmb_ring_mask; i++)
tg3_rx_skb_free(tp, &tpr->rx_jmb_buffers[i],
TG3_RX_JMB_MAP_SZ);
}
@@ -6103,16 +6244,17 @@ static int tg3_rx_prodring_alloc(struct tg3 *tp,
tpr->rx_jmb_cons_idx = 0;
tpr->rx_jmb_prod_idx = 0;
- if (tpr != &tp->prodring[0]) {
- memset(&tpr->rx_std_buffers[0], 0, TG3_RX_STD_BUFF_RING_SIZE);
- if (tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE)
+ if (tpr != &tp->napi[0].prodring) {
+ memset(&tpr->rx_std_buffers[0], 0,
+ TG3_RX_STD_BUFF_RING_SIZE(tp));
+ if (tpr->rx_jmb_buffers)
memset(&tpr->rx_jmb_buffers[0], 0,
- TG3_RX_JMB_BUFF_RING_SIZE);
+ TG3_RX_JMB_BUFF_RING_SIZE(tp));
goto done;
}
/* Zero out all descriptors. */
- memset(tpr->rx_std, 0, TG3_RX_RING_BYTES);
+ memset(tpr->rx_std, 0, TG3_RX_STD_RING_BYTES(tp));
rx_pkt_dma_sz = TG3_RX_STD_DMA_SZ;
if ((tp->tg3_flags2 & TG3_FLG2_5780_CLASS) &&
@@ -6124,7 +6266,7 @@ static int tg3_rx_prodring_alloc(struct tg3 *tp,
* stuff once. This works because the card does not
* write into the rx buffer posting rings.
*/
- for (i = 0; i < TG3_RX_RING_SIZE; i++) {
+ for (i = 0; i <= tp->rx_std_ring_mask; i++) {
struct tg3_rx_buffer_desc *rxd;
rxd = &tpr->rx_std[i];
@@ -6148,15 +6290,16 @@ static int tg3_rx_prodring_alloc(struct tg3 *tp,
}
}
- if (!(tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE))
+ if (!(tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) ||
+ (tp->tg3_flags2 & TG3_FLG2_5780_CLASS))
goto done;
- memset(tpr->rx_jmb, 0, TG3_RX_JUMBO_RING_BYTES);
+ memset(tpr->rx_jmb, 0, TG3_RX_JMB_RING_BYTES(tp));
if (!(tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE))
goto done;
- for (i = 0; i < TG3_RX_JUMBO_RING_SIZE; i++) {
+ for (i = 0; i <= tp->rx_jmb_ring_mask; i++) {
struct tg3_rx_buffer_desc *rxd;
rxd = &tpr->rx_jmb[i].std;
@@ -6196,12 +6339,12 @@ static void tg3_rx_prodring_fini(struct tg3 *tp,
kfree(tpr->rx_jmb_buffers);
tpr->rx_jmb_buffers = NULL;
if (tpr->rx_std) {
- pci_free_consistent(tp->pdev, TG3_RX_RING_BYTES,
+ pci_free_consistent(tp->pdev, TG3_RX_STD_RING_BYTES(tp),
tpr->rx_std, tpr->rx_std_mapping);
tpr->rx_std = NULL;
}
if (tpr->rx_jmb) {
- pci_free_consistent(tp->pdev, TG3_RX_JUMBO_RING_BYTES,
+ pci_free_consistent(tp->pdev, TG3_RX_JMB_RING_BYTES(tp),
tpr->rx_jmb, tpr->rx_jmb_mapping);
tpr->rx_jmb = NULL;
}
@@ -6210,23 +6353,25 @@ static void tg3_rx_prodring_fini(struct tg3 *tp,
static int tg3_rx_prodring_init(struct tg3 *tp,
struct tg3_rx_prodring_set *tpr)
{
- tpr->rx_std_buffers = kzalloc(TG3_RX_STD_BUFF_RING_SIZE, GFP_KERNEL);
+ tpr->rx_std_buffers = kzalloc(TG3_RX_STD_BUFF_RING_SIZE(tp),
+ GFP_KERNEL);
if (!tpr->rx_std_buffers)
return -ENOMEM;
- tpr->rx_std = pci_alloc_consistent(tp->pdev, TG3_RX_RING_BYTES,
+ tpr->rx_std = pci_alloc_consistent(tp->pdev, TG3_RX_STD_RING_BYTES(tp),
&tpr->rx_std_mapping);
if (!tpr->rx_std)
goto err_out;
- if (tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) {
- tpr->rx_jmb_buffers = kzalloc(TG3_RX_JMB_BUFF_RING_SIZE,
+ if ((tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) &&
+ !(tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) {
+ tpr->rx_jmb_buffers = kzalloc(TG3_RX_JMB_BUFF_RING_SIZE(tp),
GFP_KERNEL);
if (!tpr->rx_jmb_buffers)
goto err_out;
tpr->rx_jmb = pci_alloc_consistent(tp->pdev,
- TG3_RX_JUMBO_RING_BYTES,
+ TG3_RX_JMB_RING_BYTES(tp),
&tpr->rx_jmb_mapping);
if (!tpr->rx_jmb)
goto err_out;
@@ -6253,7 +6398,7 @@ static void tg3_free_rings(struct tg3 *tp)
for (j = 0; j < tp->irq_cnt; j++) {
struct tg3_napi *tnapi = &tp->napi[j];
- tg3_rx_prodring_free(tp, &tp->prodring[j]);
+ tg3_rx_prodring_free(tp, &tnapi->prodring);
if (!tnapi->tx_buffers)
continue;
@@ -6325,7 +6470,7 @@ static int tg3_init_rings(struct tg3 *tp)
if (tnapi->rx_rcb)
memset(tnapi->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp));
- if (tg3_rx_prodring_alloc(tp, &tp->prodring[i])) {
+ if (tg3_rx_prodring_alloc(tp, &tnapi->prodring)) {
tg3_free_rings(tp);
return -ENOMEM;
}
@@ -6361,6 +6506,8 @@ static void tg3_free_consistent(struct tg3 *tp)
tnapi->rx_rcb = NULL;
}
+ tg3_rx_prodring_fini(tp, &tnapi->prodring);
+
if (tnapi->hw_status) {
pci_free_consistent(tp->pdev, TG3_HW_STATUS_SIZE,
tnapi->hw_status,
@@ -6374,9 +6521,6 @@ static void tg3_free_consistent(struct tg3 *tp)
tp->hw_stats, tp->stats_mapping);
tp->hw_stats = NULL;
}
-
- for (i = 0; i < tp->irq_cnt; i++)
- tg3_rx_prodring_fini(tp, &tp->prodring[i]);
}
/*
@@ -6387,11 +6531,6 @@ static int tg3_alloc_consistent(struct tg3 *tp)
{
int i;
- for (i = 0; i < tp->irq_cnt; i++) {
- if (tg3_rx_prodring_init(tp, &tp->prodring[i]))
- goto err_out;
- }
-
tp->hw_stats = pci_alloc_consistent(tp->pdev,
sizeof(struct tg3_hw_stats),
&tp->stats_mapping);
@@ -6413,6 +6552,9 @@ static int tg3_alloc_consistent(struct tg3 *tp)
memset(tnapi->hw_status, 0, TG3_HW_STATUS_SIZE);
sblk = tnapi->hw_status;
+ if (tg3_rx_prodring_init(tp, &tnapi->prodring))
+ goto err_out;
+
/* If multivector TSS is enabled, vector 0 does not handle
* tx interrupts. Don't allocate any resources for it.
*/
@@ -6452,8 +6594,6 @@ static int tg3_alloc_consistent(struct tg3 *tp)
break;
}
- tnapi->prodring = &tp->prodring[i];
-
/*
* If multivector RSS is enabled, vector 0 does not handle
* rx or tx interrupts. Don't allocate any resources for it.
@@ -6596,6 +6736,10 @@ static void tg3_ape_send_event(struct tg3 *tp, u32 event)
int i;
u32 apedata;
+ /* NCSI does not support APE events */
+ if (tp->tg3_flags3 & TG3_FLG3_APE_HAS_NCSI)
+ return;
+
apedata = tg3_ape_read32(tp, TG3_APE_SEG_SIG);
if (apedata != APE_SEG_SIG_MAGIC)
return;
@@ -6647,6 +6791,8 @@ static void tg3_ape_driver_state_change(struct tg3 *tp, int kind)
APE_HOST_DRIVER_ID_MAGIC(TG3_MAJ_NUM, TG3_MIN_NUM));
tg3_ape_write32(tp, TG3_APE_HOST_BEHAVIOR,
APE_HOST_BEHAV_NO_PHYLOCK);
+ tg3_ape_write32(tp, TG3_APE_HOST_DRVR_STATE,
+ TG3_APE_HOST_DRVR_STATE_START);
event = APE_EVENT_STATUS_STATE_START;
break;
@@ -6658,6 +6804,16 @@ static void tg3_ape_driver_state_change(struct tg3 *tp, int kind)
*/
tg3_ape_write32(tp, TG3_APE_HOST_SEG_SIG, 0x0);
+ if (device_may_wakeup(&tp->pdev->dev) &&
+ (tp->tg3_flags & TG3_FLAG_WOL_ENABLE)) {
+ tg3_ape_write32(tp, TG3_APE_HOST_WOL_SPEED,
+ TG3_APE_HOST_WOL_SPEED_AUTO);
+ apedata = TG3_APE_HOST_DRVR_STATE_WOL;
+ } else
+ apedata = TG3_APE_HOST_DRVR_STATE_UNLOAD;
+
+ tg3_ape_write32(tp, TG3_APE_HOST_DRVR_STATE, apedata);
+
event = APE_EVENT_STATUS_STATE_UNLOAD;
break;
case RESET_KIND_SUSPEND:
@@ -7515,6 +7671,9 @@ static void tg3_rings_reset(struct tg3 *tp)
/* Disable all transmit rings but the first. */
if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS))
limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE * 16;
+ else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719)
+ limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE * 4;
else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765)
limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE * 2;
else
@@ -7548,7 +7707,7 @@ static void tg3_rings_reset(struct tg3 *tp)
/* Zero mailbox registers. */
if (tp->tg3_flags & TG3_FLAG_SUPPORT_MSIX) {
- for (i = 1; i < TG3_IRQ_MAX_VECS; i++) {
+ for (i = 1; i < tp->irq_max; i++) {
tp->napi[i].tx_prod = 0;
tp->napi[i].tx_cons = 0;
if (tp->tg3_flags3 & TG3_FLG3_ENABLE_TSS)
@@ -7594,8 +7753,8 @@ static void tg3_rings_reset(struct tg3 *tp)
if (tnapi->rx_rcb) {
tg3_set_bdinfo(tp, rxrcb, tnapi->rx_rcb_mapping,
- (TG3_RX_RCB_RING_SIZE(tp) <<
- BDINFO_FLAGS_MAXLEN_SHIFT), 0);
+ (tp->rx_ret_ring_mask + 1) <<
+ BDINFO_FLAGS_MAXLEN_SHIFT, 0);
rxrcb += TG3_BDINFO_SIZE;
}
@@ -7618,7 +7777,7 @@ static void tg3_rings_reset(struct tg3 *tp)
}
tg3_set_bdinfo(tp, rxrcb, tnapi->rx_rcb_mapping,
- (TG3_RX_RCB_RING_SIZE(tp) <<
+ ((tp->rx_ret_ring_mask + 1) <<
BDINFO_FLAGS_MAXLEN_SHIFT), 0);
stblk += 8;
@@ -7631,7 +7790,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
{
u32 val, rdmac_mode;
int i, err, limit;
- struct tg3_rx_prodring_set *tpr = &tp->prodring[0];
+ struct tg3_rx_prodring_set *tpr = &tp->napi[0].prodring;
tg3_disable_ints(tp);
@@ -7720,6 +7879,22 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
tw32(TG3_CPMU_LSPD_10MB_CLK, val);
}
+ /* Enable MAC control of LPI */
+ if (tp->phy_flags & TG3_PHYFLG_EEE_CAP) {
+ tw32_f(TG3_CPMU_EEE_LNKIDL_CTRL,
+ TG3_CPMU_EEE_LNKIDL_PCIE_NL0 |
+ TG3_CPMU_EEE_LNKIDL_UART_IDL);
+
+ tw32_f(TG3_CPMU_EEE_CTRL,
+ TG3_CPMU_EEE_CTRL_EXIT_20_1_US);
+
+ tw32_f(TG3_CPMU_EEE_MODE,
+ TG3_CPMU_EEEMD_ERLY_L1_XIT_DET |
+ TG3_CPMU_EEEMD_LPI_IN_TX |
+ TG3_CPMU_EEEMD_LPI_IN_RX |
+ TG3_CPMU_EEEMD_EEE_ENABLE);
+ }
+
/* This works around an issue with Athlon chipsets on
* B3 tigon3 silicon. This bit has no effect on any
* other revision. But do not set this on PCI Express
@@ -7845,7 +8020,10 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
tw32(BUFMGR_DMA_HIGH_WATER,
tp->bufmgr_config.dma_high_water);
- tw32(BUFMGR_MODE, BUFMGR_MODE_ENABLE | BUFMGR_MODE_ATTN_ENABLE);
+ val = BUFMGR_MODE_ENABLE | BUFMGR_MODE_ATTN_ENABLE;
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719)
+ val |= BUFMGR_MODE_NO_TX_UNDERRUN;
+ tw32(BUFMGR_MODE, val);
for (i = 0; i < 2000; i++) {
if (tr32(BUFMGR_MODE) & BUFMGR_MODE_ENABLE)
break;
@@ -7928,10 +8106,14 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
BDINFO_FLAGS_DISABLED);
}
- if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS)
- val = (RX_STD_MAX_SIZE_5705 << BDINFO_FLAGS_MAXLEN_SHIFT) |
- (TG3_RX_STD_DMA_SZ << 2);
- else
+ if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS) {
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765)
+ val = RX_STD_MAX_SIZE_5705;
+ else
+ val = RX_STD_MAX_SIZE_5717;
+ val <<= BDINFO_FLAGS_MAXLEN_SHIFT;
+ val |= (TG3_RX_STD_DMA_SZ << 2);
+ } else
val = TG3_RX_STD_DMA_SZ << BDINFO_FLAGS_MAXLEN_SHIFT;
} else
val = RX_STD_MAX_SIZE_5705 << BDINFO_FLAGS_MAXLEN_SHIFT;
@@ -8015,6 +8197,23 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
rdmac_mode |= RDMAC_MODE_IPV6_LSO_EN;
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 ||
+ (tp->tg3_flags3 & TG3_FLG3_5717_PLUS)) {
+ val = tr32(TG3_RDMA_RSRVCTRL_REG);
+ tw32(TG3_RDMA_RSRVCTRL_REG,
+ val | TG3_RDMA_RSRVCTRL_FIFO_OFLW_FIX);
+ }
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) {
+ val = tr32(TG3_LSO_RD_DMA_CRPTEN_CTRL);
+ tw32(TG3_LSO_RD_DMA_CRPTEN_CTRL, val |
+ TG3_LSO_RD_DMA_CRPTEN_CTRL_BLEN_BD_4K |
+ TG3_LSO_RD_DMA_CRPTEN_CTRL_BLEN_LSO_4K);
+ }
+
/* Receive/send statistics. */
if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) {
val = tr32(RCVLPC_STATS_ENABLE);
@@ -8197,7 +8396,11 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
tw32(SNDBDC_MODE, SNDBDC_MODE_ENABLE | SNDBDC_MODE_ATTN_ENABLE);
tw32(RCVBDI_MODE, RCVBDI_MODE_ENABLE | RCVBDI_MODE_RCB_ATTN_ENAB);
- tw32(RCVDBDI_MODE, RCVDBDI_MODE_ENABLE | RCVDBDI_MODE_INV_RING_SZ);
+ val = RCVDBDI_MODE_ENABLE | RCVDBDI_MODE_INV_RING_SZ;
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719)
+ val |= RCVDBDI_MODE_LRG_RING_SZ;
+ tw32(RCVDBDI_MODE, val);
tw32(SNDDATAI_MODE, SNDDATAI_MODE_ENABLE);
if (tp->tg3_flags2 & TG3_FLG2_HW_TSO)
tw32(SNDDATAI_MODE, SNDDATAI_MODE_ENABLE | 0x8);
@@ -8500,6 +8703,12 @@ static void tg3_timer(unsigned long __opaque)
if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)
tg3_periodic_fetch_stats(tp);
+ if (tp->setlpicnt && !--tp->setlpicnt) {
+ u32 val = tr32(TG3_CPMU_EEE_MODE);
+ tw32(TG3_CPMU_EEE_MODE,
+ val | TG3_CPMU_EEEMD_LPI_ENABLE);
+ }
+
if (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) {
u32 mac_stat;
int phy_event;
@@ -8816,16 +9025,14 @@ static bool tg3_enable_msix(struct tg3 *tp)
for (i = 0; i < tp->irq_max; i++)
tp->napi[i].irq_vec = msix_ent[i].vector;
- tp->dev->real_num_tx_queues = 1;
- if (tp->irq_cnt > 1) {
- tp->tg3_flags3 |= TG3_FLG3_ENABLE_RSS;
-
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) {
- tp->tg3_flags3 |= TG3_FLG3_ENABLE_TSS;
- tp->dev->real_num_tx_queues = tp->irq_cnt - 1;
- }
+ netif_set_real_num_tx_queues(tp->dev, 1);
+ rc = tp->irq_cnt > 1 ? tp->irq_cnt - 1 : 1;
+ if (netif_set_real_num_rx_queues(tp->dev, rc)) {
+ pci_disable_msix(tp->pdev);
+ return false;
}
+ if (tp->irq_cnt > 1)
+ tp->tg3_flags3 |= TG3_FLG3_ENABLE_RSS;
return true;
}
@@ -8858,7 +9065,8 @@ defcfg:
if (!(tp->tg3_flags2 & TG3_FLG2_USING_MSIX)) {
tp->irq_cnt = 1;
tp->napi[0].irq_vec = tp->pdev->irq;
- tp->dev->real_num_tx_queues = 1;
+ netif_set_real_num_tx_queues(tp->dev, 1);
+ netif_set_real_num_rx_queues(tp->dev, 1);
}
}
@@ -8917,6 +9125,8 @@ static int tg3_open(struct net_device *dev)
if (err)
goto err_out1;
+ tg3_napi_init(tp);
+
tg3_napi_enable(tp);
for (i = 0; i < tp->irq_cnt; i++) {
@@ -9004,6 +9214,7 @@ err_out3:
err_out2:
tg3_napi_disable(tp);
+ tg3_napi_fini(tp);
tg3_free_consistent(tp);
err_out1:
@@ -9051,6 +9262,8 @@ static int tg3_close(struct net_device *dev)
memcpy(&tp->estats_prev, tg3_get_estats(tp),
sizeof(tp->estats_prev));
+ tg3_napi_fini(tp);
+
tg3_free_consistent(tp);
tg3_set_power_state(tp, PCI_D3hot);
@@ -9240,6 +9453,8 @@ static struct rtnl_link_stats64 *tg3_get_stats64(struct net_device *dev,
stats->rx_missed_errors = old_stats->rx_missed_errors +
get_stat64(&hw_stats->rx_discards);
+ stats->rx_dropped = tp->rx_dropped;
+
return stats;
}
@@ -9594,6 +9809,9 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
if (netif_running(dev)) {
cmd->speed = tp->link_config.active_speed;
cmd->duplex = tp->link_config.active_duplex;
+ } else {
+ cmd->speed = SPEED_INVALID;
+ cmd->duplex = DUPLEX_INVALID;
}
cmd->phy_address = tp->phy_addr;
cmd->transceiver = XCVR_INTERNAL;
@@ -9820,10 +10038,10 @@ static void tg3_get_ringparam(struct net_device *dev, struct ethtool_ringparam *
{
struct tg3 *tp = netdev_priv(dev);
- ering->rx_max_pending = TG3_RX_RING_SIZE - 1;
+ ering->rx_max_pending = tp->rx_std_ring_mask;
ering->rx_mini_max_pending = 0;
if (tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE)
- ering->rx_jumbo_max_pending = TG3_RX_JUMBO_RING_SIZE - 1;
+ ering->rx_jumbo_max_pending = tp->rx_jmb_ring_mask;
else
ering->rx_jumbo_max_pending = 0;
@@ -9844,8 +10062,8 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e
struct tg3 *tp = netdev_priv(dev);
int i, irq_sync = 0, err = 0;
- if ((ering->rx_pending > TG3_RX_RING_SIZE - 1) ||
- (ering->rx_jumbo_pending > TG3_RX_JUMBO_RING_SIZE - 1) ||
+ if ((ering->rx_pending > tp->rx_std_ring_mask) ||
+ (ering->rx_jumbo_pending > tp->rx_jmb_ring_mask) ||
(ering->tx_pending > TG3_TX_RING_SIZE - 1) ||
(ering->tx_pending <= MAX_SKB_FRAGS) ||
((tp->tg3_flags2 & TG3_FLG2_TSO_BUG) &&
@@ -9867,7 +10085,7 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e
tp->rx_pending = 63;
tp->rx_jumbo_pending = ering->rx_jumbo_pending;
- for (i = 0; i < TG3_IRQ_MAX_VECS; i++)
+ for (i = 0; i < tp->irq_max; i++)
tp->napi[i].tx_pending = ering->tx_pending;
if (netif_running(dev)) {
@@ -9915,8 +10133,7 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam
if (!(phydev->supported & SUPPORTED_Pause) ||
(!(phydev->supported & SUPPORTED_Asym_Pause) &&
- ((epause->rx_pause && !epause->tx_pause) ||
- (!epause->rx_pause && epause->tx_pause))))
+ (epause->rx_pause != epause->tx_pause)))
return -EINVAL;
tp->link_config.flowctrl = 0;
@@ -10608,12 +10825,13 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
int num_pkts, tx_len, rx_len, i, err;
struct tg3_rx_buffer_desc *desc;
struct tg3_napi *tnapi, *rnapi;
- struct tg3_rx_prodring_set *tpr = &tp->prodring[0];
+ struct tg3_rx_prodring_set *tpr = &tp->napi[0].prodring;
tnapi = &tp->napi[0];
rnapi = &tp->napi[0];
if (tp->irq_cnt > 1) {
- rnapi = &tp->napi[1];
+ if (tp->tg3_flags3 & TG3_FLG3_ENABLE_RSS)
+ rnapi = &tp->napi[1];
if (tp->tg3_flags3 & TG3_FLG3_ENABLE_TSS)
tnapi = &tp->napi[1];
}
@@ -12330,6 +12548,11 @@ static int __devinit tg3_phy_probe(struct tg3 *tp)
}
}
+ if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 ||
+ (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 &&
+ tp->pci_chip_rev_id != CHIPREV_ID_57765_A0))
+ tp->phy_flags |= TG3_PHYFLG_EEE_CAP;
+
if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES) &&
!(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) &&
!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) {
@@ -12401,14 +12624,18 @@ skip_phy_reset:
static void __devinit tg3_read_vpd(struct tg3 *tp)
{
- u8 vpd_data[TG3_NVM_VPD_LEN];
+ u8 *vpd_data;
unsigned int block_end, rosize, len;
int j, i = 0;
u32 magic;
if ((tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) ||
tg3_nvram_read(tp, 0x0, &magic))
- goto out_not_found;
+ goto out_no_vpd;
+
+ vpd_data = kmalloc(TG3_NVM_VPD_LEN, GFP_KERNEL);
+ if (!vpd_data)
+ goto out_no_vpd;
if (magic == TG3_EEPROM_MAGIC) {
for (i = 0; i < TG3_NVM_VPD_LEN; i += 4) {
@@ -12492,43 +12719,51 @@ partno:
memcpy(tp->board_part_number, &vpd_data[i], len);
- return;
-
out_not_found:
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
+ kfree(vpd_data);
+ if (tp->board_part_number[0])
+ return;
+
+out_no_vpd:
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) {
+ if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717)
+ strcpy(tp->board_part_number, "BCM5717");
+ else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718)
+ strcpy(tp->board_part_number, "BCM5718");
+ else
+ goto nomatch;
+ } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) {
+ if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57780)
+ strcpy(tp->board_part_number, "BCM57780");
+ else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57760)
+ strcpy(tp->board_part_number, "BCM57760");
+ else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57790)
+ strcpy(tp->board_part_number, "BCM57790");
+ else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57788)
+ strcpy(tp->board_part_number, "BCM57788");
+ else
+ goto nomatch;
+ } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) {
+ if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57761)
+ strcpy(tp->board_part_number, "BCM57761");
+ else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57765)
+ strcpy(tp->board_part_number, "BCM57765");
+ else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57781)
+ strcpy(tp->board_part_number, "BCM57781");
+ else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57785)
+ strcpy(tp->board_part_number, "BCM57785");
+ else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57791)
+ strcpy(tp->board_part_number, "BCM57791");
+ else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57795)
+ strcpy(tp->board_part_number, "BCM57795");
+ else
+ goto nomatch;
+ } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
strcpy(tp->board_part_number, "BCM95906");
- else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 &&
- tp->pdev->device == TG3PCI_DEVICE_TIGON3_57780)
- strcpy(tp->board_part_number, "BCM57780");
- else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 &&
- tp->pdev->device == TG3PCI_DEVICE_TIGON3_57760)
- strcpy(tp->board_part_number, "BCM57760");
- else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 &&
- tp->pdev->device == TG3PCI_DEVICE_TIGON3_57790)
- strcpy(tp->board_part_number, "BCM57790");
- else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 &&
- tp->pdev->device == TG3PCI_DEVICE_TIGON3_57788)
- strcpy(tp->board_part_number, "BCM57788");
- else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 &&
- tp->pdev->device == TG3PCI_DEVICE_TIGON3_57761)
- strcpy(tp->board_part_number, "BCM57761");
- else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 &&
- tp->pdev->device == TG3PCI_DEVICE_TIGON3_57765)
- strcpy(tp->board_part_number, "BCM57765");
- else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 &&
- tp->pdev->device == TG3PCI_DEVICE_TIGON3_57781)
- strcpy(tp->board_part_number, "BCM57781");
- else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 &&
- tp->pdev->device == TG3PCI_DEVICE_TIGON3_57785)
- strcpy(tp->board_part_number, "BCM57785");
- else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 &&
- tp->pdev->device == TG3PCI_DEVICE_TIGON3_57791)
- strcpy(tp->board_part_number, "BCM57791");
- else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 &&
- tp->pdev->device == TG3PCI_DEVICE_TIGON3_57795)
- strcpy(tp->board_part_number, "BCM57795");
- else
+ } else {
+nomatch:
strcpy(tp->board_part_number, "none");
+ }
}
static int __devinit tg3_fw_img_is_valid(struct tg3 *tp, u32 offset)
@@ -12637,6 +12872,9 @@ static void __devinit tg3_read_sb_ver(struct tg3 *tp, u32 val)
case TG3_EEPROM_SB_REVISION_5:
offset = TG3_EEPROM_SB_F1R5_EDH_OFF;
break;
+ case TG3_EEPROM_SB_REVISION_6:
+ offset = TG3_EEPROM_SB_F1R6_EDH_OFF;
+ break;
default:
return;
}
@@ -12736,10 +12974,12 @@ static void __devinit tg3_read_dash_ver(struct tg3 *tp)
apedata = tg3_ape_read32(tp, TG3_APE_FW_VERSION);
- if (tg3_ape_read32(tp, TG3_APE_FW_FEATURES) & TG3_APE_FW_FEATURE_NCSI)
+ if (tg3_ape_read32(tp, TG3_APE_FW_FEATURES) & TG3_APE_FW_FEATURE_NCSI) {
+ tp->tg3_flags3 |= TG3_FLG3_APE_HAS_NCSI;
fwtype = "NCSI";
- else
+ } else {
fwtype = "DASH";
+ }
vlen = strlen(tp->fw_ver);
@@ -12795,6 +13035,18 @@ static void inline vlan_features_add(struct net_device *dev, unsigned long flags
#endif
}
+static inline u32 tg3_rx_ret_ring_size(struct tg3 *tp)
+{
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719)
+ return 4096;
+ else if ((tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) &&
+ !(tp->tg3_flags2 & TG3_FLG2_5780_CLASS))
+ return 1024;
+ else
+ return 512;
+}
+
static int __devinit tg3_get_invariants(struct tg3 *tp)
{
static struct pci_device_id write_reorder_chipsets[] = {
@@ -12839,7 +13091,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717 ||
tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 ||
- tp->pdev->device == TG3PCI_DEVICE_TIGON3_5724 ||
tp->pdev->device == TG3PCI_DEVICE_TIGON3_5719)
pci_read_config_dword(tp->pdev,
TG3PCI_GEN2_PRODID_ASICREV,
@@ -13410,10 +13661,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
if (err)
return err;
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 &&
- tp->pci_chip_rev_id != CHIPREV_ID_5717_A0)
- return -ENOTSUPP;
-
/* Initialize data/descriptor byte/word swapping. */
val = tr32(GRC_MODE);
val &= GRC_MODE_HOST_STACKUP;
@@ -13553,7 +13800,11 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
#endif
}
- tp->rx_std_max_post = TG3_RX_RING_SIZE;
+ tp->rx_std_ring_mask = TG3_RX_STD_RING_SIZE(tp) - 1;
+ tp->rx_jmb_ring_mask = TG3_RX_JMB_RING_SIZE(tp) - 1;
+ tp->rx_ret_ring_mask = tg3_rx_ret_ring_size(tp) - 1;
+
+ tp->rx_std_max_post = tp->rx_std_ring_mask + 1;
/* Increment the rx prod index on the rx std ring by at most
* 8 for these chips to workaround hw errata.
@@ -14442,7 +14693,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
}
if ((tp->tg3_flags3 & TG3_FLG3_5755_PLUS) &&
- tp->pci_chip_rev_id != CHIPREV_ID_5717_A0 &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717 &&
GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5719)
dev->netdev_ops = &tg3_netdev_ops;
else
@@ -14581,7 +14832,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
intmbx = MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW;
rcvmbx = MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW;
sndmbx = MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW;
- for (i = 0; i < TG3_IRQ_MAX_VECS; i++) {
+ for (i = 0; i < tp->irq_max; i++) {
struct tg3_napi *tnapi = &tp->napi[i];
tnapi->tp = tp;
@@ -14596,13 +14847,10 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
tnapi->consmbox = rcvmbx;
tnapi->prodmbox = sndmbx;
- if (i) {
+ if (i)
tnapi->coal_now = HOSTCC_MODE_COAL_VEC1_NOW << (i - 1);
- netif_napi_add(dev, &tnapi->napi, tg3_poll_msix, 64);
- } else {
+ else
tnapi->coal_now = HOSTCC_MODE_NOW;
- netif_napi_add(dev, &tnapi->napi, tg3_poll, 64);
- }
if (!(tp->tg3_flags & TG3_FLAG_SUPPORT_MSIX))
break;
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 4937bd190964..4a1974804b9f 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -26,6 +26,7 @@
#define TG3_RX_INTERNAL_RING_SZ_5906 32
#define RX_STD_MAX_SIZE_5705 512
+#define RX_STD_MAX_SIZE_5717 2048
#define RX_JUMBO_MAX_SIZE 0xdeadbeef /* XXX */
/* First 256 bytes are a mirror of PCI config space. */
@@ -46,7 +47,6 @@
#define TG3PCI_DEVICE_TIGON3_5785_F 0x16a0 /* 10/100 only */
#define TG3PCI_DEVICE_TIGON3_5717 0x1655
#define TG3PCI_DEVICE_TIGON3_5718 0x1656
-#define TG3PCI_DEVICE_TIGON3_5724 0x165c
#define TG3PCI_DEVICE_TIGON3_57781 0x16b1
#define TG3PCI_DEVICE_TIGON3_57785 0x16b5
#define TG3PCI_DEVICE_TIGON3_57761 0x16b0
@@ -973,6 +973,7 @@
#define RCVDBDI_MODE_JUMBOBD_NEEDED 0x00000004
#define RCVDBDI_MODE_FRM_TOO_BIG 0x00000008
#define RCVDBDI_MODE_INV_RING_SZ 0x00000010
+#define RCVDBDI_MODE_LRG_RING_SZ 0x00010000
#define RCVDBDI_STATUS 0x00002404
#define RCVDBDI_STATUS_JUMBOBD_NEEDED 0x00000004
#define RCVDBDI_STATUS_FRM_TOO_BIG 0x00000008
@@ -1090,7 +1091,26 @@
#define CPMU_MUTEX_GNT_DRIVER 0x00001000
#define TG3_CPMU_PHY_STRAP 0x00003664
#define TG3_CPMU_PHY_STRAP_IS_SERDES 0x00000020
-/* 0x3664 --> 0x3800 unused */
+/* 0x3664 --> 0x36b0 unused */
+
+#define TG3_CPMU_EEE_MODE 0x000036b0
+#define TG3_CPMU_EEEMD_ERLY_L1_XIT_DET 0x00000008
+#define TG3_CPMU_EEEMD_LPI_ENABLE 0x00000080
+#define TG3_CPMU_EEEMD_LPI_IN_TX 0x00000100
+#define TG3_CPMU_EEEMD_LPI_IN_RX 0x00000200
+#define TG3_CPMU_EEEMD_EEE_ENABLE 0x00100000
+/* 0x36b4 --> 0x36b8 unused */
+
+#define TG3_CPMU_EEE_LNKIDL_CTRL 0x000036bc
+#define TG3_CPMU_EEE_LNKIDL_PCIE_NL0 0x01000000
+#define TG3_CPMU_EEE_LNKIDL_UART_IDL 0x00000004
+/* 0x36c0 --> 0x36d0 unused */
+
+#define TG3_CPMU_EEE_CTRL 0x000036d0
+#define TG3_CPMU_EEE_CTRL_EXIT_16_5_US 0x0000019d
+#define TG3_CPMU_EEE_CTRL_EXIT_36_US 0x00000384
+#define TG3_CPMU_EEE_CTRL_EXIT_20_1_US 0x000001f8
+/* 0x36d4 --> 0x3800 unused */
/* Mbuf cluster free registers */
#define MBFREE_MODE 0x00003800
@@ -1225,6 +1245,7 @@
#define BUFMGR_MODE_ATTN_ENABLE 0x00000004
#define BUFMGR_MODE_BM_TEST 0x00000008
#define BUFMGR_MODE_MBLOW_ATTN_ENAB 0x00000010
+#define BUFMGR_MODE_NO_TX_UNDERRUN 0x80000000
#define BUFMGR_STATUS 0x00004404
#define BUFMGR_STATUS_ERROR 0x00000004
#define BUFMGR_STATUS_MBLOW 0x00000010
@@ -1302,7 +1323,16 @@
#define RDMAC_STATUS_FIFOURUN 0x00000080
#define RDMAC_STATUS_FIFOOREAD 0x00000100
#define RDMAC_STATUS_LNGREAD 0x00000200
-/* 0x4808 --> 0x4c00 unused */
+/* 0x4808 --> 0x4900 unused */
+
+#define TG3_RDMA_RSRVCTRL_REG 0x00004900
+#define TG3_RDMA_RSRVCTRL_FIFO_OFLW_FIX 0x00000004
+/* 0x4904 --> 0x4910 unused */
+
+#define TG3_LSO_RD_DMA_CRPTEN_CTRL 0x00004910
+#define TG3_LSO_RD_DMA_CRPTEN_CTRL_BLEN_BD_4K 0x00030000
+#define TG3_LSO_RD_DMA_CRPTEN_CTRL_BLEN_LSO_4K 0x000c0000
+/* 0x4914 --> 0x4c00 unused */
/* Write DMA control registers */
#define WDMAC_MODE 0x00004c00
@@ -1904,6 +1934,7 @@
#define TG3_EEPROM_SB_REVISION_3 0x00030000
#define TG3_EEPROM_SB_REVISION_4 0x00040000
#define TG3_EEPROM_SB_REVISION_5 0x00050000
+#define TG3_EEPROM_SB_REVISION_6 0x00060000
#define TG3_EEPROM_MAGIC_HW 0xabcd
#define TG3_EEPROM_MAGIC_HW_MSK 0xffff
@@ -1923,6 +1954,7 @@
#define TG3_EEPROM_SB_F1R3_EDH_OFF 0x18
#define TG3_EEPROM_SB_F1R4_EDH_OFF 0x1c
#define TG3_EEPROM_SB_F1R5_EDH_OFF 0x20
+#define TG3_EEPROM_SB_F1R6_EDH_OFF 0x4c
#define TG3_EEPROM_SB_EDH_MAJ_MASK 0x00000700
#define TG3_EEPROM_SB_EDH_MAJ_SHFT 8
#define TG3_EEPROM_SB_EDH_MIN_MASK 0x000000ff
@@ -2048,6 +2080,10 @@
#define MII_TG3_CTRL_AS_MASTER 0x0800
#define MII_TG3_CTRL_ENABLE_AS_MASTER 0x1000
+#define MII_TG3_MMD_CTRL 0x0d /* MMD Access Control register */
+#define MII_TG3_MMD_CTRL_DATA_NOINC 0x4000
+#define MII_TG3_MMD_ADDRESS 0x0e /* MMD Address Data register */
+
#define MII_TG3_EXT_CTRL 0x10 /* Extended control register */
#define MII_TG3_EXT_CTRL_FIFO_ELASTIC 0x0001
#define MII_TG3_EXT_CTRL_LNK3_LED_MODE 0x0002
@@ -2065,6 +2101,8 @@
#define MII_TG3_DSP_TAP1 0x0001
#define MII_TG3_DSP_TAP1_AGCTGT_DFLT 0x0007
#define MII_TG3_DSP_AADJ1CH0 0x001f
+#define MII_TG3_DSP_CH34TP2 0x4022
+#define MII_TG3_DSP_CH34TP2_HIBW01 0x0010
#define MII_TG3_DSP_AADJ1CH3 0x601f
#define MII_TG3_DSP_AADJ1CH3_ADCCKADJ 0x0002
#define MII_TG3_DSP_EXP1_INT_STAT 0x0f01
@@ -2131,6 +2169,14 @@
#define MII_TG3_TEST1_TRIM_EN 0x0010
#define MII_TG3_TEST1_CRC_EN 0x8000
+/* Clause 45 expansion registers */
+#define TG3_CL45_D7_EEEADV_CAP 0x003c
+#define TG3_CL45_D7_EEEADV_CAP_100TX 0x0002
+#define TG3_CL45_D7_EEEADV_CAP_1000T 0x0004
+#define TG3_CL45_D7_EEERES_STAT 0x803e
+#define TG3_CL45_D7_EEERES_STAT_LP_100TX 0x0002
+#define TG3_CL45_D7_EEERES_STAT_LP_1000T 0x0004
+
/* Fast Ethernet Tranceiver definitions */
#define MII_TG3_FET_PTEST 0x17
@@ -2176,7 +2222,7 @@
#define TG3_APE_HOST_SEG_SIG 0x4200
#define APE_HOST_SEG_SIG_MAGIC 0x484f5354
#define TG3_APE_HOST_SEG_LEN 0x4204
-#define APE_HOST_SEG_LEN_MAGIC 0x0000001c
+#define APE_HOST_SEG_LEN_MAGIC 0x00000020
#define TG3_APE_HOST_INIT_COUNT 0x4208
#define TG3_APE_HOST_DRIVER_ID 0x420c
#define APE_HOST_DRIVER_ID_LINUX 0xf0000000
@@ -2188,6 +2234,12 @@
#define APE_HOST_HEARTBEAT_INT_DISABLE 0
#define APE_HOST_HEARTBEAT_INT_5SEC 5000
#define TG3_APE_HOST_HEARTBEAT_COUNT 0x4218
+#define TG3_APE_HOST_DRVR_STATE 0x421c
+#define TG3_APE_HOST_DRVR_STATE_START 0x00000001
+#define TG3_APE_HOST_DRVR_STATE_UNLOAD 0x00000002
+#define TG3_APE_HOST_DRVR_STATE_WOL 0x00000003
+#define TG3_APE_HOST_WOL_SPEED 0x4224
+#define TG3_APE_HOST_WOL_SPEED_AUTO 0x00008000
#define TG3_APE_EVENT_STATUS 0x4300
@@ -2649,7 +2701,8 @@ struct tg3_rx_prodring_set {
dma_addr_t rx_jmb_mapping;
};
-#define TG3_IRQ_MAX_VECS 5
+#define TG3_IRQ_MAX_VECS_RSS 5
+#define TG3_IRQ_MAX_VECS TG3_IRQ_MAX_VECS_RSS
struct tg3_napi {
struct napi_struct napi ____cacheline_aligned;
@@ -2668,7 +2721,7 @@ struct tg3_napi {
u32 consmbox;
u32 rx_rcb_ptr;
u16 *rx_rcb_prod_idx;
- struct tg3_rx_prodring_set *prodring;
+ struct tg3_rx_prodring_set prodring;
struct tg3_rx_buffer_desc *rx_rcb;
struct tg3_tx_buffer_desc *tx_ring;
@@ -2746,6 +2799,9 @@ struct tg3 {
void (*write32_rx_mbox) (struct tg3 *, u32,
u32);
u32 rx_copy_thresh;
+ u32 rx_std_ring_mask;
+ u32 rx_jmb_ring_mask;
+ u32 rx_ret_ring_mask;
u32 rx_pending;
u32 rx_jumbo_pending;
u32 rx_std_max_post;
@@ -2755,11 +2811,9 @@ struct tg3 {
struct vlan_group *vlgrp;
#endif
- struct tg3_rx_prodring_set prodring[TG3_IRQ_MAX_VECS];
-
/* begin "everything else" cacheline(s) section */
- struct rtnl_link_stats64 net_stats;
+ unsigned long rx_dropped;
struct rtnl_link_stats64 net_stats_prev;
struct tg3_ethtool_stats estats;
struct tg3_ethtool_stats estats_prev;
@@ -2850,6 +2904,7 @@ struct tg3 {
#define TG3_FLG3_USE_JUMBO_BDFLAG 0x00400000
#define TG3_FLG3_L1PLLPD_EN 0x00800000
#define TG3_FLG3_5717_PLUS 0x01000000
+#define TG3_FLG3_APE_HAS_NCSI 0x02000000
struct timer_list timer;
u16 timer_counter;
@@ -2966,9 +3021,11 @@ struct tg3 {
#define TG3_PHYFLG_BER_BUG 0x00008000
#define TG3_PHYFLG_SERDES_PREEMPHASIS 0x00010000
#define TG3_PHYFLG_PARALLEL_DETECT 0x00020000
+#define TG3_PHYFLG_EEE_CAP 0x00040000
u32 led_ctrl;
u32 phy_otp;
+ u32 setlpicnt;
#define TG3_BPN_SIZE 24
char board_part_number[TG3_BPN_SIZE];
diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c
index ccee3eddc5f4..ec8c804a795d 100644
--- a/drivers/net/tlan.c
+++ b/drivers/net/tlan.c
@@ -393,7 +393,7 @@ TLan_SetTimer( struct net_device *dev, u32 ticks, u32 type )
spin_unlock_irqrestore(&priv->lock, flags);
return;
}
- priv->timer.function = &TLan_Timer;
+ priv->timer.function = TLan_Timer;
if (!in_irq())
spin_unlock_irqrestore(&priv->lock, flags);
@@ -1453,7 +1453,7 @@ static u32 TLan_HandleTxEOF( struct net_device *dev, u16 host_int )
TLan_DioWrite8( dev->base_addr,
TLAN_LED_REG, TLAN_LED_LINK | TLAN_LED_ACT );
if ( priv->timer.function == NULL ) {
- priv->timer.function = &TLan_Timer;
+ priv->timer.function = TLan_Timer;
priv->timer.data = (unsigned long) dev;
priv->timer.expires = jiffies + TLAN_TIMER_ACT_DELAY;
priv->timerSetAt = jiffies;
@@ -1601,7 +1601,7 @@ drop_and_reuse:
TLan_DioWrite8( dev->base_addr,
TLAN_LED_REG, TLAN_LED_LINK | TLAN_LED_ACT );
if ( priv->timer.function == NULL ) {
- priv->timer.function = &TLan_Timer;
+ priv->timer.function = TLan_Timer;
priv->timer.data = (unsigned long) dev;
priv->timer.expires = jiffies + TLAN_TIMER_ACT_DELAY;
priv->timerSetAt = jiffies;
@@ -1897,7 +1897,7 @@ static void TLan_Timer( unsigned long data )
TLan_DioWrite8( dev->base_addr,
TLAN_LED_REG, TLAN_LED_LINK );
} else {
- priv->timer.function = &TLan_Timer;
+ priv->timer.function = TLan_Timer;
priv->timer.expires = priv->timerSetAt
+ TLAN_TIMER_ACT_DELAY;
spin_unlock_irqrestore(&priv->lock, flags);
@@ -3187,7 +3187,7 @@ static int TLan_EeSendByte( u16 io_base, u8 data, int stop )
TLan_SetBit( TLAN_NET_SIO_EDATA, sio );
}
- return ( err );
+ return err;
} /* TLan_EeSendByte */
diff --git a/drivers/net/tlan.h b/drivers/net/tlan.h
index d13ff12d7500..3315ced774e2 100644
--- a/drivers/net/tlan.h
+++ b/drivers/net/tlan.h
@@ -442,7 +442,7 @@ typedef struct tlan_private_tag {
static inline u8 TLan_DioRead8(u16 base_addr, u16 internal_addr)
{
outw(internal_addr, base_addr + TLAN_DIO_ADR);
- return (inb((base_addr + TLAN_DIO_DATA) + (internal_addr & 0x3)));
+ return inb((base_addr + TLAN_DIO_DATA) + (internal_addr & 0x3));
} /* TLan_DioRead8 */
@@ -452,7 +452,7 @@ static inline u8 TLan_DioRead8(u16 base_addr, u16 internal_addr)
static inline u16 TLan_DioRead16(u16 base_addr, u16 internal_addr)
{
outw(internal_addr, base_addr + TLAN_DIO_ADR);
- return (inw((base_addr + TLAN_DIO_DATA) + (internal_addr & 0x2)));
+ return inw((base_addr + TLAN_DIO_DATA) + (internal_addr & 0x2));
} /* TLan_DioRead16 */
@@ -462,7 +462,7 @@ static inline u16 TLan_DioRead16(u16 base_addr, u16 internal_addr)
static inline u32 TLan_DioRead32(u16 base_addr, u16 internal_addr)
{
outw(internal_addr, base_addr + TLAN_DIO_ADR);
- return (inl(base_addr + TLAN_DIO_DATA));
+ return inl(base_addr + TLAN_DIO_DATA);
} /* TLan_DioRead32 */
@@ -537,6 +537,6 @@ static inline u32 TLan_HashFunc( const u8 *a )
hash ^= ((a[2]^a[5])<<4); /* & 060 */
hash ^= ((a[2]^a[5])>>2); /* & 077 */
- return (hash & 077);
+ return hash & 077;
}
#endif
diff --git a/drivers/net/tokenring/proteon.c b/drivers/net/tokenring/proteon.c
index 16e8783ee9cd..8d362e64a40e 100644
--- a/drivers/net/tokenring/proteon.c
+++ b/drivers/net/tokenring/proteon.c
@@ -110,7 +110,7 @@ static int __init proteon_probe1(struct net_device *dev, int ioaddr)
}
dev->base_addr = ioaddr;
- return (0);
+ return 0;
nodev:
release_region(ioaddr, PROTEON_IO_EXTENT);
return -ENODEV;
diff --git a/drivers/net/tokenring/smctr.c b/drivers/net/tokenring/smctr.c
index 0929fff5982c..63db5a6762ae 100644
--- a/drivers/net/tokenring/smctr.c
+++ b/drivers/net/tokenring/smctr.c
@@ -435,7 +435,7 @@ static int smctr_alloc_shared_memory(struct net_device *dev)
RX_DATA_BUFFER_SIZE * tp->num_rx_bdbs[NON_MAC_QUEUE]);
tp->rx_buff_end[NON_MAC_QUEUE] = (__u16 *)smctr_malloc(dev, 0);
- return (0);
+ return 0;
}
/* Enter Bypass state. */
@@ -448,7 +448,7 @@ static int smctr_bypass_state(struct net_device *dev)
err = smctr_setup_single_cmd(dev, ACB_CMD_CHANGE_JOIN_STATE, JS_BYPASS_STATE);
- return (err);
+ return err;
}
static int smctr_checksum_firmware(struct net_device *dev)
@@ -471,9 +471,9 @@ static int smctr_checksum_firmware(struct net_device *dev)
smctr_disable_adapter_ctrl_store(dev);
if(checksum)
- return (checksum);
+ return checksum;
- return (0);
+ return 0;
}
static int __init smctr_chk_mca(struct net_device *dev)
@@ -485,7 +485,7 @@ static int __init smctr_chk_mca(struct net_device *dev)
current_slot = mca_find_unused_adapter(smctr_posid, 0);
if(current_slot == MCA_NOTFOUND)
- return (-ENODEV);
+ return -ENODEV;
mca_set_adapter_name(current_slot, smctr_name);
mca_mark_as_used(current_slot);
@@ -622,9 +622,9 @@ static int __init smctr_chk_mca(struct net_device *dev)
break;
}
- return (0);
+ return 0;
#else
- return (-1);
+ return -1;
#endif /* CONFIG_MCA_LEGACY */
}
@@ -677,18 +677,18 @@ static int smctr_chg_rx_mask(struct net_device *dev)
if((err = smctr_issue_write_word_cmd(dev, RW_CONFIG_REGISTER_0,
&tp->config_word0)))
{
- return (err);
+ return err;
}
if((err = smctr_issue_write_word_cmd(dev, RW_CONFIG_REGISTER_1,
&tp->config_word1)))
{
- return (err);
+ return err;
}
smctr_disable_16bit(dev);
- return (0);
+ return 0;
}
static int smctr_clear_int(struct net_device *dev)
@@ -697,7 +697,7 @@ static int smctr_clear_int(struct net_device *dev)
outb((tp->trc_mask | CSR_CLRTINT), dev->base_addr + CSR);
- return (0);
+ return 0;
}
static int smctr_clear_trc_reset(int ioaddr)
@@ -707,7 +707,7 @@ static int smctr_clear_trc_reset(int ioaddr)
r = inb(ioaddr + MSR);
outb(~MSR_RST & r, ioaddr + MSR);
- return (0);
+ return 0;
}
/*
@@ -725,7 +725,7 @@ static int smctr_close(struct net_device *dev)
/* Check to see if adapter is already in a closed state. */
if(tp->status != OPEN)
- return (0);
+ return 0;
smctr_enable_16bit(dev);
smctr_set_page(dev, (__u8 *)tp->ram_access);
@@ -733,7 +733,7 @@ static int smctr_close(struct net_device *dev)
if((err = smctr_issue_remove_cmd(dev)))
{
smctr_disable_16bit(dev);
- return (err);
+ return err;
}
for(;;)
@@ -746,7 +746,7 @@ static int smctr_close(struct net_device *dev)
}
- return (0);
+ return 0;
}
static int smctr_decode_firmware(struct net_device *dev,
@@ -807,12 +807,12 @@ static int smctr_decode_firmware(struct net_device *dev,
if(buff)
*(mem++) = SWAP_BYTES(buff);
- return (0);
+ return 0;
}
static int smctr_disable_16bit(struct net_device *dev)
{
- return (0);
+ return 0;
}
/*
@@ -832,7 +832,7 @@ static int smctr_disable_adapter_ctrl_store(struct net_device *dev)
tp->trc_mask |= CSR_WCSS;
outb(tp->trc_mask, ioaddr + CSR);
- return (0);
+ return 0;
}
static int smctr_disable_bic_int(struct net_device *dev)
@@ -844,7 +844,7 @@ static int smctr_disable_bic_int(struct net_device *dev)
| CSR_MSKTINT | CSR_WCSS;
outb(tp->trc_mask, ioaddr + CSR);
- return (0);
+ return 0;
}
static int smctr_enable_16bit(struct net_device *dev)
@@ -858,7 +858,7 @@ static int smctr_enable_16bit(struct net_device *dev)
outb((r | LAAR_MEM16ENB), dev->base_addr + LAAR);
}
- return (0);
+ return 0;
}
/*
@@ -881,7 +881,7 @@ static int smctr_enable_adapter_ctrl_store(struct net_device *dev)
tp->trc_mask &= ~CSR_WCSS;
outb(tp->trc_mask, ioaddr + CSR);
- return (0);
+ return 0;
}
static int smctr_enable_adapter_ram(struct net_device *dev)
@@ -895,7 +895,7 @@ static int smctr_enable_adapter_ram(struct net_device *dev)
r = inb(ioaddr + MSR);
outb(MSR_MEMB | r, ioaddr + MSR);
- return (0);
+ return 0;
}
static int smctr_enable_bic_int(struct net_device *dev)
@@ -921,7 +921,7 @@ static int smctr_enable_bic_int(struct net_device *dev)
break;
}
- return (0);
+ return 0;
}
static int __init smctr_chk_isa(struct net_device *dev)
@@ -1145,7 +1145,7 @@ static int __init smctr_chk_isa(struct net_device *dev)
*/
}
- return (0);
+ return 0;
out2:
release_region(ioaddr, SMCTR_IO_EXTENT);
@@ -1199,7 +1199,7 @@ static int __init smctr_get_boardid(struct net_device *dev, int mca)
* return;
*/
if(IdByte & 0xF8)
- return (-1);
+ return -1;
r1 = inb(ioaddr + BID_REG_1);
r1 &= BID_ICR_MASK;
@@ -1250,21 +1250,21 @@ static int __init smctr_get_boardid(struct net_device *dev, int mca)
while(r1 & BID_RECALL_DONE_MASK)
r1 = inb(ioaddr + BID_REG_1);
- return (BoardIdMask);
+ return BoardIdMask;
}
static int smctr_get_group_address(struct net_device *dev)
{
smctr_issue_read_word_cmd(dev, RW_INDIVIDUAL_GROUP_ADDR);
- return(smctr_wait_cmd(dev));
+ return smctr_wait_cmd(dev);
}
static int smctr_get_functional_address(struct net_device *dev)
{
smctr_issue_read_word_cmd(dev, RW_FUNCTIONAL_ADDR);
- return(smctr_wait_cmd(dev));
+ return smctr_wait_cmd(dev);
}
/* Calculate number of Non-MAC receive BDB's and data buffers.
@@ -1346,14 +1346,14 @@ static unsigned int smctr_get_num_rx_bdbs(struct net_device *dev)
*/
mem_used += 0x100;
- return((0xffff - mem_used) / (RX_DATA_BUFFER_SIZE + sizeof(BDBlock)));
+ return (0xffff - mem_used) / (RX_DATA_BUFFER_SIZE + sizeof(BDBlock));
}
static int smctr_get_physical_drop_number(struct net_device *dev)
{
smctr_issue_read_word_cmd(dev, RW_PHYSICAL_DROP_NUMBER);
- return(smctr_wait_cmd(dev));
+ return smctr_wait_cmd(dev);
}
static __u8 * smctr_get_rx_pointer(struct net_device *dev, short queue)
@@ -1366,14 +1366,14 @@ static __u8 * smctr_get_rx_pointer(struct net_device *dev, short queue)
tp->rx_fcb_curr[queue]->bdb_ptr = bdb;
- return ((__u8 *)bdb->data_block_ptr);
+ return (__u8 *)bdb->data_block_ptr;
}
static int smctr_get_station_id(struct net_device *dev)
{
smctr_issue_read_word_cmd(dev, RW_INDIVIDUAL_MAC_ADDRESS);
- return(smctr_wait_cmd(dev));
+ return smctr_wait_cmd(dev);
}
/*
@@ -1384,7 +1384,7 @@ static struct net_device_stats *smctr_get_stats(struct net_device *dev)
{
struct net_local *tp = netdev_priv(dev);
- return ((struct net_device_stats *)&tp->MacStat);
+ return (struct net_device_stats *)&tp->MacStat;
}
static FCBlock *smctr_get_tx_fcb(struct net_device *dev, __u16 queue,
@@ -1401,14 +1401,14 @@ static FCBlock *smctr_get_tx_fcb(struct net_device *dev, __u16 queue,
/* check if there is enough FCB blocks */
if(tp->num_tx_fcbs_used[queue] >= tp->num_tx_fcbs[queue])
- return ((FCBlock *)(-1L));
+ return (FCBlock *)(-1L);
/* round off the input pkt size to the nearest even number */
alloc_size = (bytes_count + 1) & 0xfffe;
/* check if enough mem */
if((tp->tx_buff_used[queue] + alloc_size) > tp->tx_buff_size[queue])
- return ((FCBlock *)(-1L));
+ return (FCBlock *)(-1L);
/* check if past the end ;
* if exactly enough mem to end of ring, alloc from front.
@@ -1425,7 +1425,7 @@ static FCBlock *smctr_get_tx_fcb(struct net_device *dev, __u16 queue,
if((tp->tx_buff_used[queue] + alloc_size)
> tp->tx_buff_size[queue])
{
- return ((FCBlock *)(-1L));
+ return (FCBlock *)(-1L);
}
/* ring wrap */
@@ -1448,14 +1448,14 @@ static FCBlock *smctr_get_tx_fcb(struct net_device *dev, __u16 queue,
pFCB = tp->tx_fcb_curr[queue];
tp->tx_fcb_curr[queue] = tp->tx_fcb_curr[queue]->next_ptr;
- return (pFCB);
+ return pFCB;
}
static int smctr_get_upstream_neighbor_addr(struct net_device *dev)
{
smctr_issue_read_word_cmd(dev, RW_UPSTREAM_NEIGHBOR_ADDRESS);
- return(smctr_wait_cmd(dev));
+ return smctr_wait_cmd(dev);
}
static int smctr_hardware_send_packet(struct net_device *dev,
@@ -1469,21 +1469,22 @@ static int smctr_hardware_send_packet(struct net_device *dev,
printk(KERN_DEBUG"%s: smctr_hardware_send_packet\n", dev->name);
if(tp->status != OPEN)
- return (-1);
+ return -1;
if(tp->monitor_state_ready != 1)
- return (-1);
+ return -1;
for(;;)
{
/* Send first buffer from queue */
skb = skb_dequeue(&tp->SendSkbQueue);
if(skb == NULL)
- return (-1);
+ return -1;
tp->QueueSkb++;
- if(skb->len < SMC_HEADER_SIZE || skb->len > tp->max_packet_size) return (-1);
+ if(skb->len < SMC_HEADER_SIZE || skb->len > tp->max_packet_size)
+ return -1;
smctr_enable_16bit(dev);
smctr_set_page(dev, (__u8 *)tp->ram_access);
@@ -1492,7 +1493,7 @@ static int smctr_hardware_send_packet(struct net_device *dev,
== (FCBlock *)(-1L))
{
smctr_disable_16bit(dev);
- return (-1);
+ return -1;
}
smctr_tx_move_frame(dev, skb,
@@ -1508,7 +1509,7 @@ static int smctr_hardware_send_packet(struct net_device *dev,
smctr_disable_16bit(dev);
}
- return (0);
+ return 0;
}
static int smctr_init_acbs(struct net_device *dev)
@@ -1552,7 +1553,7 @@ static int smctr_init_acbs(struct net_device *dev)
tp->acb_curr = tp->acb_head->next_ptr;
tp->num_acbs_used = 0;
- return (0);
+ return 0;
}
static int smctr_init_adapter(struct net_device *dev)
@@ -1590,13 +1591,14 @@ static int smctr_init_adapter(struct net_device *dev)
if(smctr_checksum_firmware(dev))
{
- printk(KERN_ERR "%s: Previously loaded firmware is missing\n",dev->name); return (-ENOENT);
+ printk(KERN_ERR "%s: Previously loaded firmware is missing\n",dev->name);
+ return -ENOENT;
}
if((err = smctr_ram_memory_test(dev)))
{
printk(KERN_ERR "%s: RAM memory test failed.\n", dev->name);
- return (-EIO);
+ return -EIO;
}
smctr_set_rx_look_ahead(dev);
@@ -1608,7 +1610,7 @@ static int smctr_init_adapter(struct net_device *dev)
{
printk(KERN_ERR "%s: Initialization of card failed (%d)\n",
dev->name, err);
- return (-EINVAL);
+ return -EINVAL;
}
/* This routine clobbers the TRC's internal registers. */
@@ -1616,7 +1618,7 @@ static int smctr_init_adapter(struct net_device *dev)
{
printk(KERN_ERR "%s: Card failed internal self test (%d)\n",
dev->name, err);
- return (-EINVAL);
+ return -EINVAL;
}
/* Re-Initialize adapter's internal registers */
@@ -1625,17 +1627,17 @@ static int smctr_init_adapter(struct net_device *dev)
{
printk(KERN_ERR "%s: Initialization of card failed (%d)\n",
dev->name, err);
- return (-EINVAL);
+ return -EINVAL;
}
smctr_enable_bic_int(dev);
if((err = smctr_issue_enable_int_cmd(dev, TRC_INTERRUPT_ENABLE_MASK)))
- return (err);
+ return err;
smctr_disable_16bit(dev);
- return (0);
+ return 0;
}
static int smctr_init_card_real(struct net_device *dev)
@@ -1703,15 +1705,15 @@ static int smctr_init_card_real(struct net_device *dev)
smctr_init_shared_memory(dev);
if((err = smctr_issue_init_timers_cmd(dev)))
- return (err);
+ return err;
if((err = smctr_issue_init_txrx_cmd(dev)))
{
printk(KERN_ERR "%s: Hardware failure\n", dev->name);
- return (err);
+ return err;
}
- return (0);
+ return 0;
}
static int smctr_init_rx_bdbs(struct net_device *dev)
@@ -1763,7 +1765,7 @@ static int smctr_init_rx_bdbs(struct net_device *dev)
tp->rx_bdb_curr[i] = tp->rx_bdb_head[i]->next_ptr;
}
- return (0);
+ return 0;
}
static int smctr_init_rx_fcbs(struct net_device *dev)
@@ -1813,7 +1815,7 @@ static int smctr_init_rx_fcbs(struct net_device *dev)
tp->rx_fcb_curr[i] = tp->rx_fcb_head[i]->next_ptr;
}
- return(0);
+ return 0;
}
static int smctr_init_shared_memory(struct net_device *dev)
@@ -1871,7 +1873,7 @@ static int smctr_init_shared_memory(struct net_device *dev)
smctr_init_rx_bdbs(dev);
smctr_init_rx_fcbs(dev);
- return (0);
+ return 0;
}
static int smctr_init_tx_bdbs(struct net_device *dev)
@@ -1901,7 +1903,7 @@ static int smctr_init_tx_bdbs(struct net_device *dev)
tp->tx_bdb_head[i]->back_ptr = bdb;
}
- return (0);
+ return 0;
}
static int smctr_init_tx_fcbs(struct net_device *dev)
@@ -1940,7 +1942,7 @@ static int smctr_init_tx_fcbs(struct net_device *dev)
tp->num_tx_fcbs_used[i] = 0;
}
- return (0);
+ return 0;
}
static int smctr_internal_self_test(struct net_device *dev)
@@ -1949,33 +1951,33 @@ static int smctr_internal_self_test(struct net_device *dev)
int err;
if((err = smctr_issue_test_internal_rom_cmd(dev)))
- return (err);
+ return err;
if((err = smctr_wait_cmd(dev)))
- return (err);
+ return err;
if(tp->acb_head->cmd_done_status & 0xff)
- return (-1);
+ return -1;
if((err = smctr_issue_test_hic_cmd(dev)))
- return (err);
+ return err;
if((err = smctr_wait_cmd(dev)))
- return (err);
+ return err;
if(tp->acb_head->cmd_done_status & 0xff)
- return (-1);
+ return -1;
if((err = smctr_issue_test_mac_reg_cmd(dev)))
- return (err);
+ return err;
if((err = smctr_wait_cmd(dev)))
- return (err);
+ return err;
if(tp->acb_head->cmd_done_status & 0xff)
- return (-1);
+ return -1;
- return (0);
+ return 0;
}
/*
@@ -2468,14 +2470,14 @@ static int smctr_issue_enable_int_cmd(struct net_device *dev,
int err;
if((err = smctr_wait_while_cbusy(dev)))
- return (err);
+ return err;
tp->sclb_ptr->int_mask_control = interrupt_enable_mask;
tp->sclb_ptr->valid_command = SCLB_VALID | SCLB_CMD_CLEAR_INTERRUPT_MASK;
smctr_set_ctrl_attention(dev);
- return (0);
+ return 0;
}
static int smctr_issue_int_ack(struct net_device *dev, __u16 iack_code, __u16 ibits)
@@ -2483,7 +2485,7 @@ static int smctr_issue_int_ack(struct net_device *dev, __u16 iack_code, __u16 ib
struct net_local *tp = netdev_priv(dev);
if(smctr_wait_while_cbusy(dev))
- return (-1);
+ return -1;
tp->sclb_ptr->int_mask_control = ibits;
tp->sclb_ptr->iack_code = iack_code << 1; /* use the offset from base */ tp->sclb_ptr->resume_control = 0;
@@ -2491,7 +2493,7 @@ static int smctr_issue_int_ack(struct net_device *dev, __u16 iack_code, __u16 ib
smctr_set_ctrl_attention(dev);
- return (0);
+ return 0;
}
static int smctr_issue_init_timers_cmd(struct net_device *dev)
@@ -2502,10 +2504,10 @@ static int smctr_issue_init_timers_cmd(struct net_device *dev)
__u16 *pTimer_Struc = (__u16 *)tp->misc_command_data;
if((err = smctr_wait_while_cbusy(dev)))
- return (err);
+ return err;
if((err = smctr_wait_cmd(dev)))
- return (err);
+ return err;
tp->config_word0 = THDREN | DMA_TRIGGER | USETPT | NO_AUTOREMOVE;
tp->config_word1 = 0;
@@ -2648,7 +2650,7 @@ static int smctr_issue_init_timers_cmd(struct net_device *dev)
err = smctr_setup_single_cmd_w_data(dev, ACB_CMD_INIT_TRC_TIMERS, 0);
- return (err);
+ return err;
}
static int smctr_issue_init_txrx_cmd(struct net_device *dev)
@@ -2659,12 +2661,12 @@ static int smctr_issue_init_txrx_cmd(struct net_device *dev)
void **txrx_ptrs = (void *)tp->misc_command_data;
if((err = smctr_wait_while_cbusy(dev)))
- return (err);
+ return err;
if((err = smctr_wait_cmd(dev)))
{
printk(KERN_ERR "%s: Hardware failure\n", dev->name);
- return (err);
+ return err;
}
/* Initialize Transmit Queue Pointers that are used, to point to
@@ -2695,7 +2697,7 @@ static int smctr_issue_init_txrx_cmd(struct net_device *dev)
err = smctr_setup_single_cmd_w_data(dev, ACB_CMD_INIT_TX_RX, 0);
- return (err);
+ return err;
}
static int smctr_issue_insert_cmd(struct net_device *dev)
@@ -2704,7 +2706,7 @@ static int smctr_issue_insert_cmd(struct net_device *dev)
err = smctr_setup_single_cmd(dev, ACB_CMD_INSERT, ACB_SUB_CMD_NOP);
- return (err);
+ return err;
}
static int smctr_issue_read_ring_status_cmd(struct net_device *dev)
@@ -2712,15 +2714,15 @@ static int smctr_issue_read_ring_status_cmd(struct net_device *dev)
int err;
if((err = smctr_wait_while_cbusy(dev)))
- return (err);
+ return err;
if((err = smctr_wait_cmd(dev)))
- return (err);
+ return err;
err = smctr_setup_single_cmd_w_data(dev, ACB_CMD_READ_TRC_STATUS,
RW_TRC_STATUS_BLOCK);
- return (err);
+ return err;
}
static int smctr_issue_read_word_cmd(struct net_device *dev, __u16 aword_cnt)
@@ -2728,15 +2730,15 @@ static int smctr_issue_read_word_cmd(struct net_device *dev, __u16 aword_cnt)
int err;
if((err = smctr_wait_while_cbusy(dev)))
- return (err);
+ return err;
if((err = smctr_wait_cmd(dev)))
- return (err);
+ return err;
err = smctr_setup_single_cmd_w_data(dev, ACB_CMD_MCT_READ_VALUE,
aword_cnt);
- return (err);
+ return err;
}
static int smctr_issue_remove_cmd(struct net_device *dev)
@@ -2745,14 +2747,14 @@ static int smctr_issue_remove_cmd(struct net_device *dev)
int err;
if((err = smctr_wait_while_cbusy(dev)))
- return (err);
+ return err;
tp->sclb_ptr->resume_control = 0;
tp->sclb_ptr->valid_command = SCLB_VALID | SCLB_CMD_REMOVE;
smctr_set_ctrl_attention(dev);
- return (0);
+ return 0;
}
static int smctr_issue_resume_acb_cmd(struct net_device *dev)
@@ -2761,7 +2763,7 @@ static int smctr_issue_resume_acb_cmd(struct net_device *dev)
int err;
if((err = smctr_wait_while_cbusy(dev)))
- return (err);
+ return err;
tp->sclb_ptr->resume_control = SCLB_RC_ACB;
tp->sclb_ptr->valid_command = SCLB_VALID | SCLB_RESUME_CONTROL_VALID;
@@ -2770,7 +2772,7 @@ static int smctr_issue_resume_acb_cmd(struct net_device *dev)
smctr_set_ctrl_attention(dev);
- return (0);
+ return 0;
}
static int smctr_issue_resume_rx_bdb_cmd(struct net_device *dev, __u16 queue)
@@ -2779,7 +2781,7 @@ static int smctr_issue_resume_rx_bdb_cmd(struct net_device *dev, __u16 queue)
int err;
if((err = smctr_wait_while_cbusy(dev)))
- return (err);
+ return err;
if(queue == MAC_QUEUE)
tp->sclb_ptr->resume_control = SCLB_RC_RX_MAC_BDB;
@@ -2790,7 +2792,7 @@ static int smctr_issue_resume_rx_bdb_cmd(struct net_device *dev, __u16 queue)
smctr_set_ctrl_attention(dev);
- return (0);
+ return 0;
}
static int smctr_issue_resume_rx_fcb_cmd(struct net_device *dev, __u16 queue)
@@ -2801,7 +2803,7 @@ static int smctr_issue_resume_rx_fcb_cmd(struct net_device *dev, __u16 queue)
printk(KERN_DEBUG "%s: smctr_issue_resume_rx_fcb_cmd\n", dev->name);
if(smctr_wait_while_cbusy(dev))
- return (-1);
+ return -1;
if(queue == MAC_QUEUE)
tp->sclb_ptr->resume_control = SCLB_RC_RX_MAC_FCB;
@@ -2812,7 +2814,7 @@ static int smctr_issue_resume_rx_fcb_cmd(struct net_device *dev, __u16 queue)
smctr_set_ctrl_attention(dev);
- return (0);
+ return 0;
}
static int smctr_issue_resume_tx_fcb_cmd(struct net_device *dev, __u16 queue)
@@ -2823,14 +2825,14 @@ static int smctr_issue_resume_tx_fcb_cmd(struct net_device *dev, __u16 queue)
printk(KERN_DEBUG "%s: smctr_issue_resume_tx_fcb_cmd\n", dev->name);
if(smctr_wait_while_cbusy(dev))
- return (-1);
+ return -1;
tp->sclb_ptr->resume_control = (SCLB_RC_TFCB0 << queue);
tp->sclb_ptr->valid_command = SCLB_RESUME_CONTROL_VALID | SCLB_VALID;
smctr_set_ctrl_attention(dev);
- return (0);
+ return 0;
}
static int smctr_issue_test_internal_rom_cmd(struct net_device *dev)
@@ -2840,7 +2842,7 @@ static int smctr_issue_test_internal_rom_cmd(struct net_device *dev)
err = smctr_setup_single_cmd(dev, ACB_CMD_MCT_TEST,
TRC_INTERNAL_ROM_TEST);
- return (err);
+ return err;
}
static int smctr_issue_test_hic_cmd(struct net_device *dev)
@@ -2850,7 +2852,7 @@ static int smctr_issue_test_hic_cmd(struct net_device *dev)
err = smctr_setup_single_cmd(dev, ACB_CMD_HIC_TEST,
TRC_HOST_INTERFACE_REG_TEST);
- return (err);
+ return err;
}
static int smctr_issue_test_mac_reg_cmd(struct net_device *dev)
@@ -2860,7 +2862,7 @@ static int smctr_issue_test_mac_reg_cmd(struct net_device *dev)
err = smctr_setup_single_cmd(dev, ACB_CMD_MCT_TEST,
TRC_MAC_REGISTERS_TEST);
- return (err);
+ return err;
}
static int smctr_issue_trc_loopback_cmd(struct net_device *dev)
@@ -2870,7 +2872,7 @@ static int smctr_issue_trc_loopback_cmd(struct net_device *dev)
err = smctr_setup_single_cmd(dev, ACB_CMD_MCT_TEST,
TRC_INTERNAL_LOOPBACK);
- return (err);
+ return err;
}
static int smctr_issue_tri_loopback_cmd(struct net_device *dev)
@@ -2880,7 +2882,7 @@ static int smctr_issue_tri_loopback_cmd(struct net_device *dev)
err = smctr_setup_single_cmd(dev, ACB_CMD_MCT_TEST,
TRC_TRI_LOOPBACK);
- return (err);
+ return err;
}
static int smctr_issue_write_byte_cmd(struct net_device *dev,
@@ -2891,10 +2893,10 @@ static int smctr_issue_write_byte_cmd(struct net_device *dev,
int err;
if((err = smctr_wait_while_cbusy(dev)))
- return (err);
+ return err;
if((err = smctr_wait_cmd(dev)))
- return (err);
+ return err;
for(iword = 0, ibyte = 0; iword < (unsigned int)(aword_cnt & 0xff);
iword++, ibyte += 2)
@@ -2903,8 +2905,8 @@ static int smctr_issue_write_byte_cmd(struct net_device *dev,
| (*((__u8 *)byte + ibyte + 1));
}
- return (smctr_setup_single_cmd_w_data(dev, ACB_CMD_MCT_WRITE_VALUE,
- aword_cnt));
+ return smctr_setup_single_cmd_w_data(dev, ACB_CMD_MCT_WRITE_VALUE,
+ aword_cnt);
}
static int smctr_issue_write_word_cmd(struct net_device *dev,
@@ -2914,10 +2916,10 @@ static int smctr_issue_write_word_cmd(struct net_device *dev,
unsigned int i, err;
if((err = smctr_wait_while_cbusy(dev)))
- return (err);
+ return err;
if((err = smctr_wait_cmd(dev)))
- return (err);
+ return err;
for(i = 0; i < (unsigned int)(aword_cnt & 0xff); i++)
tp->misc_command_data[i] = *((__u16 *)word + i);
@@ -2925,7 +2927,7 @@ static int smctr_issue_write_word_cmd(struct net_device *dev,
err = smctr_setup_single_cmd_w_data(dev, ACB_CMD_MCT_WRITE_VALUE,
aword_cnt);
- return (err);
+ return err;
}
static int smctr_join_complete_state(struct net_device *dev)
@@ -2935,7 +2937,7 @@ static int smctr_join_complete_state(struct net_device *dev)
err = smctr_setup_single_cmd(dev, ACB_CMD_CHANGE_JOIN_STATE,
JS_JOIN_COMPLETE_STATE);
- return (err);
+ return err;
}
static int smctr_link_tx_fcbs_to_bdbs(struct net_device *dev)
@@ -2959,7 +2961,7 @@ static int smctr_link_tx_fcbs_to_bdbs(struct net_device *dev)
}
}
- return (0);
+ return 0;
}
static int smctr_load_firmware(struct net_device *dev)
@@ -2974,7 +2976,7 @@ static int smctr_load_firmware(struct net_device *dev)
if (request_firmware(&fw, "tr_smctr.bin", &dev->dev)) {
printk(KERN_ERR "%s: firmware not found\n", dev->name);
- return (UCODE_NOT_PRESENT);
+ return UCODE_NOT_PRESENT;
}
tp->num_of_tx_buffs = 4;
@@ -3036,7 +3038,7 @@ static int smctr_load_firmware(struct net_device *dev)
smctr_disable_16bit(dev);
out:
release_firmware(fw);
- return (err);
+ return err;
}
static int smctr_load_node_addr(struct net_device *dev)
@@ -3052,7 +3054,7 @@ static int smctr_load_node_addr(struct net_device *dev)
}
dev->addr_len = 6;
- return (0);
+ return 0;
}
/* Lobe Media Test.
@@ -3146,14 +3148,14 @@ static int smctr_lobe_media_test_cmd(struct net_device *dev)
if(smctr_wait_cmd(dev))
{
printk(KERN_ERR "Lobe Failed test state\n");
- return (LOBE_MEDIA_TEST_FAILED);
+ return LOBE_MEDIA_TEST_FAILED;
}
}
err = smctr_setup_single_cmd(dev, ACB_CMD_MCT_TEST,
TRC_LOBE_MEDIA_TEST);
- return (err);
+ return err;
}
static int smctr_lobe_media_test_state(struct net_device *dev)
@@ -3163,7 +3165,7 @@ static int smctr_lobe_media_test_state(struct net_device *dev)
err = smctr_setup_single_cmd(dev, ACB_CMD_CHANGE_JOIN_STATE,
JS_LOBE_TEST_STATE);
- return (err);
+ return err;
}
static int smctr_make_8025_hdr(struct net_device *dev,
@@ -3212,7 +3214,7 @@ static int smctr_make_8025_hdr(struct net_device *dev,
break;
}
- return (0);
+ return 0;
}
static int smctr_make_access_pri(struct net_device *dev, MAC_SUB_VECTOR *tsv)
@@ -3225,7 +3227,7 @@ static int smctr_make_access_pri(struct net_device *dev, MAC_SUB_VECTOR *tsv)
tsv->svv[0] = MSB(tp->authorized_access_priority);
tsv->svv[1] = LSB(tp->authorized_access_priority);
- return (0);
+ return 0;
}
static int smctr_make_addr_mod(struct net_device *dev, MAC_SUB_VECTOR *tsv)
@@ -3236,7 +3238,7 @@ static int smctr_make_addr_mod(struct net_device *dev, MAC_SUB_VECTOR *tsv)
tsv->svv[0] = 0;
tsv->svv[1] = 0;
- return (0);
+ return 0;
}
static int smctr_make_auth_funct_class(struct net_device *dev,
@@ -3250,7 +3252,7 @@ static int smctr_make_auth_funct_class(struct net_device *dev,
tsv->svv[0] = MSB(tp->authorized_function_classes);
tsv->svv[1] = LSB(tp->authorized_function_classes);
- return (0);
+ return 0;
}
static int smctr_make_corr(struct net_device *dev,
@@ -3262,7 +3264,7 @@ static int smctr_make_corr(struct net_device *dev,
tsv->svv[0] = MSB(correlator);
tsv->svv[1] = LSB(correlator);
- return (0);
+ return 0;
}
static int smctr_make_funct_addr(struct net_device *dev, MAC_SUB_VECTOR *tsv)
@@ -3280,7 +3282,7 @@ static int smctr_make_funct_addr(struct net_device *dev, MAC_SUB_VECTOR *tsv)
tsv->svv[2] = MSB(tp->misc_command_data[1]);
tsv->svv[3] = LSB(tp->misc_command_data[1]);
- return (0);
+ return 0;
}
static int smctr_make_group_addr(struct net_device *dev, MAC_SUB_VECTOR *tsv)
@@ -3305,7 +3307,7 @@ static int smctr_make_group_addr(struct net_device *dev, MAC_SUB_VECTOR *tsv)
tsv->svv[2] == 0x00 && tsv->svv[3] == 0x00)
tsv->svv[0] = 0x00;
- return (0);
+ return 0;
}
static int smctr_make_phy_drop_num(struct net_device *dev,
@@ -3324,7 +3326,7 @@ static int smctr_make_phy_drop_num(struct net_device *dev,
tsv->svv[2] = MSB(tp->misc_command_data[1]);
tsv->svv[3] = LSB(tp->misc_command_data[1]);
- return (0);
+ return 0;
}
static int smctr_make_product_id(struct net_device *dev, MAC_SUB_VECTOR *tsv)
@@ -3337,7 +3339,7 @@ static int smctr_make_product_id(struct net_device *dev, MAC_SUB_VECTOR *tsv)
for(i = 0; i < 18; i++)
tsv->svv[i] = 0xF0;
- return (0);
+ return 0;
}
static int smctr_make_station_id(struct net_device *dev, MAC_SUB_VECTOR *tsv)
@@ -3358,7 +3360,7 @@ static int smctr_make_station_id(struct net_device *dev, MAC_SUB_VECTOR *tsv)
tsv->svv[4] = MSB(tp->misc_command_data[2]);
tsv->svv[5] = LSB(tp->misc_command_data[2]);
- return (0);
+ return 0;
}
static int smctr_make_ring_station_status(struct net_device *dev,
@@ -3374,7 +3376,7 @@ static int smctr_make_ring_station_status(struct net_device *dev,
tsv->svv[4] = 0;
tsv->svv[5] = 0;
- return (0);
+ return 0;
}
static int smctr_make_ring_station_version(struct net_device *dev,
@@ -3400,7 +3402,7 @@ static int smctr_make_ring_station_version(struct net_device *dev,
else
tsv->svv[9] = 0xc4; /* EBCDIC - D */
- return (0);
+ return 0;
}
static int smctr_make_tx_status_code(struct net_device *dev,
@@ -3414,7 +3416,7 @@ static int smctr_make_tx_status_code(struct net_device *dev,
/* Stripped frame status of Transmitted Frame */
tsv->svv[1] = tx_fstatus & 0xff;
- return (0);
+ return 0;
}
static int smctr_make_upstream_neighbor_addr(struct net_device *dev,
@@ -3436,7 +3438,7 @@ static int smctr_make_upstream_neighbor_addr(struct net_device *dev,
tsv->svv[4] = MSB(tp->misc_command_data[2]);
tsv->svv[5] = LSB(tp->misc_command_data[2]);
- return (0);
+ return 0;
}
static int smctr_make_wrap_data(struct net_device *dev, MAC_SUB_VECTOR *tsv)
@@ -3444,7 +3446,7 @@ static int smctr_make_wrap_data(struct net_device *dev, MAC_SUB_VECTOR *tsv)
tsv->svi = WRAP_DATA;
tsv->svl = S_WRAP_DATA;
- return (0);
+ return 0;
}
/*
@@ -3464,9 +3466,9 @@ static int smctr_open(struct net_device *dev)
err = smctr_init_adapter(dev);
if(err < 0)
- return (err);
+ return err;
- return (err);
+ return err;
}
/* Interrupt driven open of Token card. */
@@ -3481,9 +3483,9 @@ static int smctr_open_tr(struct net_device *dev)
/* Now we can actually open the adapter. */
if(tp->status == OPEN)
- return (0);
+ return 0;
if(tp->status != INITIALIZED)
- return (-1);
+ return -1;
/* FIXME: it would work a lot better if we masked the irq sources
on the card here, then we could skip the locking and poll nicely */
@@ -3560,7 +3562,7 @@ static int smctr_open_tr(struct net_device *dev)
out:
spin_unlock_irqrestore(&tp->lock, flags);
- return (err);
+ return err;
}
/* Check for a network adapter of this type,
@@ -3675,7 +3677,7 @@ static int __init smctr_probe1(struct net_device *dev, int ioaddr)
dev->netdev_ops = &smctr_netdev_ops;
dev->watchdog_timeo = HZ;
- return (0);
+ return 0;
out:
return err;
@@ -3699,13 +3701,13 @@ static int smctr_process_rx_packet(MAC_HEADER *rmf, __u16 size,
case INIT:
if((rcode = smctr_rcv_init(dev, rmf, &correlator)) == HARDWARE_FAILED)
{
- return (rcode);
+ return rcode;
}
if((err = smctr_send_rsp(dev, rmf, rcode,
correlator)))
{
- return (err);
+ return err;
}
break;
@@ -3713,13 +3715,13 @@ static int smctr_process_rx_packet(MAC_HEADER *rmf, __u16 size,
if((rcode = smctr_rcv_chg_param(dev, rmf,
&correlator)) ==HARDWARE_FAILED)
{
- return (rcode);
+ return rcode;
}
if((err = smctr_send_rsp(dev, rmf, rcode,
correlator)))
{
- return (err);
+ return err;
}
break;
@@ -3728,16 +3730,16 @@ static int smctr_process_rx_packet(MAC_HEADER *rmf, __u16 size,
rmf, &correlator)) != POSITIVE_ACK)
{
if(rcode == HARDWARE_FAILED)
- return (rcode);
+ return rcode;
else
- return (smctr_send_rsp(dev, rmf,
- rcode, correlator));
+ return smctr_send_rsp(dev, rmf,
+ rcode, correlator);
}
if((err = smctr_send_rpt_addr(dev, rmf,
correlator)))
{
- return (err);
+ return err;
}
break;
@@ -3746,17 +3748,17 @@ static int smctr_process_rx_packet(MAC_HEADER *rmf, __u16 size,
rmf, &correlator)) != POSITIVE_ACK)
{
if(rcode == HARDWARE_FAILED)
- return (rcode);
+ return rcode;
else
- return (smctr_send_rsp(dev, rmf,
+ return smctr_send_rsp(dev, rmf,
rcode,
- correlator));
+ correlator);
}
if((err = smctr_send_rpt_attch(dev, rmf,
correlator)))
{
- return (err);
+ return err;
}
break;
@@ -3765,17 +3767,17 @@ static int smctr_process_rx_packet(MAC_HEADER *rmf, __u16 size,
rmf, &correlator)) != POSITIVE_ACK)
{
if(rcode == HARDWARE_FAILED)
- return (rcode);
+ return rcode;
else
- return (smctr_send_rsp(dev, rmf,
+ return smctr_send_rsp(dev, rmf,
rcode,
- correlator));
+ correlator);
}
if((err = smctr_send_rpt_state(dev, rmf,
correlator)))
{
- return (err);
+ return err;
}
break;
@@ -3786,17 +3788,17 @@ static int smctr_process_rx_packet(MAC_HEADER *rmf, __u16 size,
!= POSITIVE_ACK)
{
if(rcode == HARDWARE_FAILED)
- return (rcode);
+ return rcode;
else
- return (smctr_send_rsp(dev, rmf,
+ return smctr_send_rsp(dev, rmf,
rcode,
- correlator));
+ correlator);
}
if((err = smctr_send_tx_forward(dev, rmf,
&tx_fstatus)) == HARDWARE_FAILED)
{
- return (err);
+ return err;
}
if(err == A_FRAME_WAS_FORWARDED)
@@ -3805,7 +3807,7 @@ static int smctr_process_rx_packet(MAC_HEADER *rmf, __u16 size,
rmf, tx_fstatus))
== HARDWARE_FAILED)
{
- return (err);
+ return err;
}
}
break;
@@ -3834,7 +3836,7 @@ static int smctr_process_rx_packet(MAC_HEADER *rmf, __u16 size,
if((err = smctr_send_rsp(dev, rmf,rcode,
correlator)))
{
- return (err);
+ return err;
}
}
@@ -3899,7 +3901,7 @@ static int smctr_process_rx_packet(MAC_HEADER *rmf, __u16 size,
err = 0;
}
- return (err);
+ return err;
}
/* Adapter RAM test. Incremental word ODD boundary data test. */
@@ -3942,7 +3944,7 @@ static int smctr_ram_memory_test(struct net_device *dev)
err_offset = j;
err_word = word_read;
err_pattern = word_pattern;
- return (RAM_TEST_FAILED);
+ return RAM_TEST_FAILED;
}
}
}
@@ -3966,14 +3968,14 @@ static int smctr_ram_memory_test(struct net_device *dev)
err_offset = j;
err_word = word_read;
err_pattern = word_pattern;
- return (RAM_TEST_FAILED);
+ return RAM_TEST_FAILED;
}
}
}
smctr_set_page(dev, (__u8 *)tp->ram_access);
- return (0);
+ return 0;
}
static int smctr_rcv_chg_param(struct net_device *dev, MAC_HEADER *rmf,
@@ -3986,7 +3988,7 @@ static int smctr_rcv_chg_param(struct net_device *dev, MAC_HEADER *rmf,
/* This Frame can only come from a CRS */
if((rmf->dc_sc & SC_MASK) != SC_CRS)
- return(E_INAPPROPRIATE_SOURCE_CLASS);
+ return E_INAPPROPRIATE_SOURCE_CLASS;
/* Remove MVID Length from total length. */
vlen = (signed short)rmf->vl - 4;
@@ -4058,7 +4060,7 @@ static int smctr_rcv_chg_param(struct net_device *dev, MAC_HEADER *rmf,
}
}
- return (rcode);
+ return rcode;
}
static int smctr_rcv_init(struct net_device *dev, MAC_HEADER *rmf,
@@ -4071,7 +4073,7 @@ static int smctr_rcv_init(struct net_device *dev, MAC_HEADER *rmf,
/* This Frame can only come from a RPS */
if((rmf->dc_sc & SC_MASK) != SC_RPS)
- return (E_INAPPROPRIATE_SOURCE_CLASS);
+ return E_INAPPROPRIATE_SOURCE_CLASS;
/* Remove MVID Length from total length. */
vlen = (signed short)rmf->vl - 4;
@@ -4133,7 +4135,7 @@ static int smctr_rcv_init(struct net_device *dev, MAC_HEADER *rmf,
}
}
- return (rcode);
+ return rcode;
}
static int smctr_rcv_tx_forward(struct net_device *dev, MAC_HEADER *rmf)
@@ -4145,7 +4147,7 @@ static int smctr_rcv_tx_forward(struct net_device *dev, MAC_HEADER *rmf)
/* This Frame can only come from a CRS */
if((rmf->dc_sc & SC_MASK) != SC_CRS)
- return (E_INAPPROPRIATE_SOURCE_CLASS);
+ return E_INAPPROPRIATE_SOURCE_CLASS;
/* Remove MVID Length from total length */
vlen = (signed short)rmf->vl - 4;
@@ -4193,7 +4195,7 @@ static int smctr_rcv_tx_forward(struct net_device *dev, MAC_HEADER *rmf)
}
}
- return (rcode);
+ return rcode;
}
static int smctr_rcv_rq_addr_state_attch(struct net_device *dev,
@@ -4250,7 +4252,7 @@ static int smctr_rcv_rq_addr_state_attch(struct net_device *dev,
}
}
- return (rcode);
+ return rcode;
}
static int smctr_rcv_unknown(struct net_device *dev, MAC_HEADER *rmf,
@@ -4284,7 +4286,7 @@ static int smctr_rcv_unknown(struct net_device *dev, MAC_HEADER *rmf,
rsv = (MAC_SUB_VECTOR *)((__u32)rsv + rsv->svl);
}
- return (E_UNRECOGNIZED_VECTOR_ID);
+ return E_UNRECOGNIZED_VECTOR_ID;
}
/*
@@ -4311,7 +4313,7 @@ static int smctr_reset_adapter(struct net_device *dev)
*/
outb(tp->trc_mask | CSR_CLRTINT | CSR_CLRCBUSY, ioaddr + CSR);
- return (0);
+ return 0;
}
static int smctr_restart_tx_chain(struct net_device *dev, short queue)
@@ -4329,7 +4331,7 @@ static int smctr_restart_tx_chain(struct net_device *dev, short queue)
err = smctr_issue_resume_tx_fcb_cmd(dev, queue);
}
- return (err);
+ return err;
}
static int smctr_ring_status_chg(struct net_device *dev)
@@ -4371,7 +4373,7 @@ static int smctr_ring_status_chg(struct net_device *dev)
}
if(!(tp->ring_status_flags & RING_STATUS_CHANGED))
- return (0);
+ return 0;
switch(tp->ring_status)
{
@@ -4421,7 +4423,7 @@ static int smctr_ring_status_chg(struct net_device *dev)
break;
}
- return (0);
+ return 0;
}
static int smctr_rx_frame(struct net_device *dev)
@@ -4486,7 +4488,7 @@ static int smctr_rx_frame(struct net_device *dev)
break;
}
- return (err);
+ return err;
}
static int smctr_send_dat(struct net_device *dev)
@@ -4502,7 +4504,7 @@ static int smctr_send_dat(struct net_device *dev)
if((fcb = smctr_get_tx_fcb(dev, MAC_QUEUE,
sizeof(MAC_HEADER))) == (FCBlock *)(-1L))
{
- return (OUT_OF_RESOURCES);
+ return OUT_OF_RESOURCES;
}
/* Initialize DAT Data Fields. */
@@ -4524,7 +4526,7 @@ static int smctr_send_dat(struct net_device *dev)
/* Start Transmit. */
if((err = smctr_trc_send_packet(dev, fcb, MAC_QUEUE)))
- return (err);
+ return err;
/* Wait for Transmit to Complete */
for(i = 0; i < 10000; i++)
@@ -4538,7 +4540,7 @@ static int smctr_send_dat(struct net_device *dev)
if(!(fcb->frame_status & FCB_COMMAND_DONE) ||
fcb->frame_status & (FCB_TX_STATUS_E | FCB_TX_AC_BITS))
{
- return (INITIALIZE_FAILED);
+ return INITIALIZE_FAILED;
}
/* De-allocated Tx FCB and Frame Buffer
@@ -4549,7 +4551,7 @@ static int smctr_send_dat(struct net_device *dev)
tp->tx_queue_status[MAC_QUEUE] = NOT_TRANSMITING;
smctr_update_tx_chain(dev, fcb, MAC_QUEUE);
- return (0);
+ return 0;
}
static void smctr_timeout(struct net_device *dev)
@@ -4610,7 +4612,7 @@ static int smctr_send_lobe_media_test(struct net_device *dev)
if((fcb = smctr_get_tx_fcb(dev, MAC_QUEUE, sizeof(struct trh_hdr)
+ S_WRAP_DATA + S_WRAP_DATA)) == (FCBlock *)(-1L))
{
- return (OUT_OF_RESOURCES);
+ return OUT_OF_RESOURCES;
}
/* Initialize DAT Data Fields. */
@@ -4639,7 +4641,7 @@ static int smctr_send_lobe_media_test(struct net_device *dev)
/* Start Transmit. */
tmf->vl = SWAP_BYTES(tmf->vl);
if((err = smctr_trc_send_packet(dev, fcb, MAC_QUEUE)))
- return (err);
+ return err;
/* Wait for Transmit to Complete. (10 ms). */
for(i=0; i < 10000; i++)
@@ -4653,7 +4655,7 @@ static int smctr_send_lobe_media_test(struct net_device *dev)
if(!(fcb->frame_status & FCB_COMMAND_DONE) ||
fcb->frame_status & (FCB_TX_STATUS_E | FCB_TX_AC_BITS))
{
- return (LOBE_MEDIA_TEST_FAILED);
+ return LOBE_MEDIA_TEST_FAILED;
}
/* De-allocated Tx FCB and Frame Buffer
@@ -4664,7 +4666,7 @@ static int smctr_send_lobe_media_test(struct net_device *dev)
tp->tx_queue_status[MAC_QUEUE] = NOT_TRANSMITING;
smctr_update_tx_chain(dev, fcb, MAC_QUEUE);
- return (0);
+ return 0;
}
static int smctr_send_rpt_addr(struct net_device *dev, MAC_HEADER *rmf,
@@ -4679,7 +4681,7 @@ static int smctr_send_rpt_addr(struct net_device *dev, MAC_HEADER *rmf,
+ S_ADDRESS_MODIFER + S_GROUP_ADDRESS + S_FUNCTIONAL_ADDRESS))
== (FCBlock *)(-1L))
{
- return (0);
+ return 0;
}
tmf = (MAC_HEADER *)fcb->bdb_ptr->data_block_ptr;
@@ -4722,7 +4724,7 @@ static int smctr_send_rpt_addr(struct net_device *dev, MAC_HEADER *rmf,
*/
tmf->vl = SWAP_BYTES(tmf->vl);
- return (smctr_trc_send_packet(dev, fcb, MAC_QUEUE));
+ return smctr_trc_send_packet(dev, fcb, MAC_QUEUE);
}
static int smctr_send_rpt_attch(struct net_device *dev, MAC_HEADER *rmf,
@@ -4737,7 +4739,7 @@ static int smctr_send_rpt_attch(struct net_device *dev, MAC_HEADER *rmf,
+ S_AUTHORIZED_FUNCTION_CLASS + S_AUTHORIZED_ACCESS_PRIORITY))
== (FCBlock *)(-1L))
{
- return (0);
+ return 0;
}
tmf = (MAC_HEADER *)fcb->bdb_ptr->data_block_ptr;
@@ -4776,7 +4778,7 @@ static int smctr_send_rpt_attch(struct net_device *dev, MAC_HEADER *rmf,
*/
tmf->vl = SWAP_BYTES(tmf->vl);
- return (smctr_trc_send_packet(dev, fcb, MAC_QUEUE));
+ return smctr_trc_send_packet(dev, fcb, MAC_QUEUE);
}
static int smctr_send_rpt_state(struct net_device *dev, MAC_HEADER *rmf,
@@ -4791,7 +4793,7 @@ static int smctr_send_rpt_state(struct net_device *dev, MAC_HEADER *rmf,
+ S_RING_STATION_STATUS + S_STATION_IDENTIFER))
== (FCBlock *)(-1L))
{
- return (0);
+ return 0;
}
tmf = (MAC_HEADER *)fcb->bdb_ptr->data_block_ptr;
@@ -4826,7 +4828,7 @@ static int smctr_send_rpt_state(struct net_device *dev, MAC_HEADER *rmf,
*/
tmf->vl = SWAP_BYTES(tmf->vl);
- return (smctr_trc_send_packet(dev, fcb, MAC_QUEUE));
+ return smctr_trc_send_packet(dev, fcb, MAC_QUEUE);
}
static int smctr_send_rpt_tx_forward(struct net_device *dev,
@@ -4839,7 +4841,7 @@ static int smctr_send_rpt_tx_forward(struct net_device *dev,
if((fcb = smctr_get_tx_fcb(dev, MAC_QUEUE, sizeof(MAC_HEADER)
+ S_TRANSMIT_STATUS_CODE)) == (FCBlock *)(-1L))
{
- return (0);
+ return 0;
}
tmf = (MAC_HEADER *)fcb->bdb_ptr->data_block_ptr;
@@ -4862,7 +4864,7 @@ static int smctr_send_rpt_tx_forward(struct net_device *dev,
*/
tmf->vl = SWAP_BYTES(tmf->vl);
- return(smctr_trc_send_packet(dev, fcb, MAC_QUEUE));
+ return smctr_trc_send_packet(dev, fcb, MAC_QUEUE);
}
static int smctr_send_rsp(struct net_device *dev, MAC_HEADER *rmf,
@@ -4875,7 +4877,7 @@ static int smctr_send_rsp(struct net_device *dev, MAC_HEADER *rmf,
if((fcb = smctr_get_tx_fcb(dev, MAC_QUEUE, sizeof(MAC_HEADER)
+ S_CORRELATOR + S_RESPONSE_CODE)) == (FCBlock *)(-1L))
{
- return (0);
+ return 0;
}
tmf = (MAC_HEADER *)fcb->bdb_ptr->data_block_ptr;
@@ -4888,7 +4890,7 @@ static int smctr_send_rsp(struct net_device *dev, MAC_HEADER *rmf,
tsv = (MAC_SUB_VECTOR *)((__u32)tmf + sizeof(MAC_HEADER));
smctr_make_corr(dev, tsv, correlator);
- return (0);
+ return 0;
}
static int smctr_send_rq_init(struct net_device *dev)
@@ -4907,7 +4909,7 @@ static int smctr_send_rq_init(struct net_device *dev)
+ S_RING_STATION_VERSION_NUMBER + S_ADDRESS_MODIFER))
== (FCBlock *)(-1L)))
{
- return (0);
+ return 0;
}
tmf = (MAC_HEADER *)fcb->bdb_ptr->data_block_ptr;
@@ -4943,7 +4945,7 @@ static int smctr_send_rq_init(struct net_device *dev)
tmf->vl = SWAP_BYTES(tmf->vl);
if((err = smctr_trc_send_packet(dev, fcb, MAC_QUEUE)))
- return (err);
+ return err;
/* Wait for Transmit to Complete */
for(i = 0; i < 10000; i++)
@@ -4957,7 +4959,7 @@ static int smctr_send_rq_init(struct net_device *dev)
fstatus = fcb->frame_status;
if(!(fstatus & FCB_COMMAND_DONE))
- return (HARDWARE_FAILED);
+ return HARDWARE_FAILED;
if(!(fstatus & FCB_TX_STATUS_E))
count++;
@@ -4971,7 +4973,7 @@ static int smctr_send_rq_init(struct net_device *dev)
smctr_update_tx_chain(dev, fcb, MAC_QUEUE);
} while(count < 4 && ((fstatus & FCB_TX_AC_BITS) ^ FCB_TX_AC_BITS));
- return (smctr_join_complete_state(dev));
+ return smctr_join_complete_state(dev);
}
static int smctr_send_tx_forward(struct net_device *dev, MAC_HEADER *rmf,
@@ -4984,13 +4986,13 @@ static int smctr_send_tx_forward(struct net_device *dev, MAC_HEADER *rmf,
/* Check if this is the END POINT of the Transmit Forward Chain. */
if(rmf->vl <= 18)
- return (0);
+ return 0;
/* Allocate Transmit FCB only by requesting 0 bytes
* of data buffer.
*/
if((fcb = smctr_get_tx_fcb(dev, MAC_QUEUE, 0)) == (FCBlock *)(-1L))
- return (0);
+ return 0;
/* Set pointer to Transmit Frame Buffer to the data
* portion of the received TX Forward frame, making
@@ -5006,7 +5008,7 @@ static int smctr_send_tx_forward(struct net_device *dev, MAC_HEADER *rmf,
fcb->bdb_ptr->buffer_length = rmf->vl - 4 - 2;
if((err = smctr_trc_send_packet(dev, fcb, MAC_QUEUE)))
- return (err);
+ return err;
/* Wait for Transmit to Complete */
for(i = 0; i < 10000; i++)
@@ -5020,7 +5022,7 @@ static int smctr_send_tx_forward(struct net_device *dev, MAC_HEADER *rmf,
if(!(fcb->frame_status & FCB_COMMAND_DONE))
{
if((err = smctr_issue_resume_tx_fcb_cmd(dev, MAC_QUEUE)))
- return (err);
+ return err;
for(i = 0; i < 10000; i++)
{
@@ -5030,12 +5032,12 @@ static int smctr_send_tx_forward(struct net_device *dev, MAC_HEADER *rmf,
}
if(!(fcb->frame_status & FCB_COMMAND_DONE))
- return (HARDWARE_FAILED);
+ return HARDWARE_FAILED;
}
*tx_fstatus = fcb->frame_status;
- return (A_FRAME_WAS_FORWARDED);
+ return A_FRAME_WAS_FORWARDED;
}
static int smctr_set_auth_access_pri(struct net_device *dev,
@@ -5044,11 +5046,11 @@ static int smctr_set_auth_access_pri(struct net_device *dev,
struct net_local *tp = netdev_priv(dev);
if(rsv->svl != S_AUTHORIZED_ACCESS_PRIORITY)
- return (E_SUB_VECTOR_LENGTH_ERROR);
+ return E_SUB_VECTOR_LENGTH_ERROR;
tp->authorized_access_priority = (rsv->svv[0] << 8 | rsv->svv[1]);
- return (POSITIVE_ACK);
+ return POSITIVE_ACK;
}
static int smctr_set_auth_funct_class(struct net_device *dev,
@@ -5057,22 +5059,22 @@ static int smctr_set_auth_funct_class(struct net_device *dev,
struct net_local *tp = netdev_priv(dev);
if(rsv->svl != S_AUTHORIZED_FUNCTION_CLASS)
- return (E_SUB_VECTOR_LENGTH_ERROR);
+ return E_SUB_VECTOR_LENGTH_ERROR;
tp->authorized_function_classes = (rsv->svv[0] << 8 | rsv->svv[1]);
- return (POSITIVE_ACK);
+ return POSITIVE_ACK;
}
static int smctr_set_corr(struct net_device *dev, MAC_SUB_VECTOR *rsv,
__u16 *correlator)
{
if(rsv->svl != S_CORRELATOR)
- return (E_SUB_VECTOR_LENGTH_ERROR);
+ return E_SUB_VECTOR_LENGTH_ERROR;
*correlator = (rsv->svv[0] << 8 | rsv->svv[1]);
- return (POSITIVE_ACK);
+ return POSITIVE_ACK;
}
static int smctr_set_error_timer_value(struct net_device *dev,
@@ -5082,34 +5084,34 @@ static int smctr_set_error_timer_value(struct net_device *dev,
int err;
if(rsv->svl != S_ERROR_TIMER_VALUE)
- return (E_SUB_VECTOR_LENGTH_ERROR);
+ return E_SUB_VECTOR_LENGTH_ERROR;
err_tval = (rsv->svv[0] << 8 | rsv->svv[1])*10;
smctr_issue_write_word_cmd(dev, RW_TER_THRESHOLD, &err_tval);
if((err = smctr_wait_cmd(dev)))
- return (err);
+ return err;
- return (POSITIVE_ACK);
+ return POSITIVE_ACK;
}
static int smctr_set_frame_forward(struct net_device *dev,
MAC_SUB_VECTOR *rsv, __u8 dc_sc)
{
if((rsv->svl < 2) || (rsv->svl > S_FRAME_FORWARD))
- return (E_SUB_VECTOR_LENGTH_ERROR);
+ return E_SUB_VECTOR_LENGTH_ERROR;
if((dc_sc & DC_MASK) != DC_CRS)
{
if(rsv->svl >= 2 && rsv->svl < 20)
- return (E_TRANSMIT_FORWARD_INVALID);
+ return E_TRANSMIT_FORWARD_INVALID;
if((rsv->svv[0] != 0) || (rsv->svv[1] != 0))
- return (E_TRANSMIT_FORWARD_INVALID);
+ return E_TRANSMIT_FORWARD_INVALID;
}
- return (POSITIVE_ACK);
+ return POSITIVE_ACK;
}
static int smctr_set_local_ring_num(struct net_device *dev,
@@ -5118,13 +5120,13 @@ static int smctr_set_local_ring_num(struct net_device *dev,
struct net_local *tp = netdev_priv(dev);
if(rsv->svl != S_LOCAL_RING_NUMBER)
- return (E_SUB_VECTOR_LENGTH_ERROR);
+ return E_SUB_VECTOR_LENGTH_ERROR;
if(tp->ptr_local_ring_num)
*(__u16 *)(tp->ptr_local_ring_num)
= (rsv->svv[0] << 8 | rsv->svv[1]);
- return (POSITIVE_ACK);
+ return POSITIVE_ACK;
}
static unsigned short smctr_set_ctrl_attention(struct net_device *dev)
@@ -5140,7 +5142,7 @@ static unsigned short smctr_set_ctrl_attention(struct net_device *dev)
outb(tp->trc_mask, ioaddr + CSR);
}
- return (0);
+ return 0;
}
static void smctr_set_multicast_list(struct net_device *dev)
@@ -5159,7 +5161,7 @@ static int smctr_set_page(struct net_device *dev, __u8 *buf)
amask = (__u8)((tptr & PR_PAGE_MASK) >> 8);
outb(amask, dev->base_addr + PR);
- return (0);
+ return 0;
}
static int smctr_set_phy_drop(struct net_device *dev, MAC_SUB_VECTOR *rsv)
@@ -5167,13 +5169,13 @@ static int smctr_set_phy_drop(struct net_device *dev, MAC_SUB_VECTOR *rsv)
int err;
if(rsv->svl != S_PHYSICAL_DROP)
- return (E_SUB_VECTOR_LENGTH_ERROR);
+ return E_SUB_VECTOR_LENGTH_ERROR;
smctr_issue_write_byte_cmd(dev, RW_PHYSICAL_DROP_NUMBER, &rsv->svv[0]);
if((err = smctr_wait_cmd(dev)))
- return (err);
+ return err;
- return (POSITIVE_ACK);
+ return POSITIVE_ACK;
}
/* Reset the ring speed to the opposite of what it was. This auto-pilot
@@ -5195,16 +5197,16 @@ static int smctr_set_ring_speed(struct net_device *dev)
smctr_reset_adapter(dev);
if((err = smctr_init_card_real(dev)))
- return (err);
+ return err;
smctr_enable_bic_int(dev);
if((err = smctr_issue_enable_int_cmd(dev, TRC_INTERRUPT_ENABLE_MASK)))
- return (err);
+ return err;
smctr_disable_16bit(dev);
- return (0);
+ return 0;
}
static int smctr_set_rx_look_ahead(struct net_device *dev)
@@ -5233,7 +5235,7 @@ static int smctr_set_rx_look_ahead(struct net_device *dev)
*((__u16 *)(tp->ram_access)) = sword;
}
- return (0);
+ return 0;
}
static int smctr_set_trc_reset(int ioaddr)
@@ -5243,7 +5245,7 @@ static int smctr_set_trc_reset(int ioaddr)
r = inb(ioaddr + MSR);
outb(MSR_RST | r, ioaddr + MSR);
- return (0);
+ return 0;
}
/*
@@ -5259,10 +5261,10 @@ static int smctr_setup_single_cmd(struct net_device *dev,
printk(KERN_DEBUG "%s: smctr_setup_single_cmd\n", dev->name);
if((err = smctr_wait_while_cbusy(dev)))
- return (err);
+ return err;
if((err = (unsigned int)smctr_wait_cmd(dev)))
- return (err);
+ return err;
tp->acb_head->cmd_done_status = 0;
tp->acb_head->cmd = command;
@@ -5270,7 +5272,7 @@ static int smctr_setup_single_cmd(struct net_device *dev,
err = smctr_issue_resume_acb_cmd(dev);
- return (err);
+ return err;
}
/*
@@ -5287,7 +5289,7 @@ static int smctr_setup_single_cmd_w_data(struct net_device *dev,
tp->acb_head->data_offset_lo
= (__u16)TRC_POINTER(tp->misc_command_data);
- return(smctr_issue_resume_acb_cmd(dev));
+ return smctr_issue_resume_acb_cmd(dev);
}
static char *smctr_malloc(struct net_device *dev, __u16 size)
@@ -5298,7 +5300,7 @@ static char *smctr_malloc(struct net_device *dev, __u16 size)
m = (char *)(tp->ram_access + tp->sh_mem_used);
tp->sh_mem_used += (__u32)size;
- return (m);
+ return m;
}
static int smctr_status_chg(struct net_device *dev)
@@ -5333,7 +5335,7 @@ static int smctr_status_chg(struct net_device *dev)
break;
}
- return (0);
+ return 0;
}
static int smctr_trc_send_packet(struct net_device *dev, FCBlock *fcb,
@@ -5355,7 +5357,7 @@ static int smctr_trc_send_packet(struct net_device *dev, FCBlock *fcb,
err = smctr_issue_resume_tx_fcb_cmd(dev, queue);
}
- return (err);
+ return err;
}
static __u16 smctr_tx_complete(struct net_device *dev, __u16 queue)
@@ -5409,7 +5411,7 @@ static __u16 smctr_tx_complete(struct net_device *dev, __u16 queue)
break;
}
- return (err);
+ return err;
}
static unsigned short smctr_tx_move_frame(struct net_device *dev,
@@ -5450,7 +5452,7 @@ static unsigned short smctr_tx_move_frame(struct net_device *dev,
pbuff += len;
}
- return (0);
+ return 0;
}
/* Update the error statistic counters for this adapter. */
@@ -5493,7 +5495,7 @@ static int smctr_update_err_stats(struct net_device *dev)
if(tstat->token_errors)
tstat->token_errors += *(tp->misc_command_data + 5) >> 8;
- return (0);
+ return 0;
}
static int smctr_update_rx_chain(struct net_device *dev, __u16 queue)
@@ -5530,7 +5532,7 @@ static int smctr_update_rx_chain(struct net_device *dev, __u16 queue)
tp->rx_bdb_curr[queue]->back_ptr->info = BDB_NOT_CHAIN_END;
tp->rx_bdb_curr[queue] = bdb;
- return (0);
+ return 0;
}
static int smctr_update_tx_chain(struct net_device *dev, FCBlock *fcb,
@@ -5542,13 +5544,13 @@ static int smctr_update_tx_chain(struct net_device *dev, FCBlock *fcb,
printk(KERN_DEBUG "smctr_update_tx_chain\n");
if(tp->num_tx_fcbs_used[queue] <= 0)
- return (HARDWARE_FAILED);
+ return HARDWARE_FAILED;
else
{
if(tp->tx_buff_used[queue] < fcb->memory_alloc)
{
tp->tx_buff_used[queue] = 0;
- return (HARDWARE_FAILED);
+ return HARDWARE_FAILED;
}
tp->tx_buff_used[queue] -= fcb->memory_alloc;
@@ -5566,7 +5568,7 @@ static int smctr_update_tx_chain(struct net_device *dev, FCBlock *fcb,
fcb->frame_status = 0;
tp->tx_fcb_end[queue] = fcb->next_ptr;
netif_wake_queue(dev);
- return (0);
+ return 0;
}
}
@@ -5587,12 +5589,12 @@ static int smctr_wait_cmd(struct net_device *dev)
}
if(loop_count == 0)
- return(HARDWARE_FAILED);
+ return HARDWARE_FAILED;
if(tp->acb_head->cmd_done_status & 0xff)
- return(HARDWARE_FAILED);
+ return HARDWARE_FAILED;
- return (0);
+ return 0;
}
static int smctr_wait_while_cbusy(struct net_device *dev)
@@ -5624,9 +5626,9 @@ static int smctr_wait_while_cbusy(struct net_device *dev)
}
if(timeout)
- return (0);
+ return 0;
else
- return (HARDWARE_FAILED);
+ return HARDWARE_FAILED;
}
#ifdef MODULE
diff --git a/drivers/net/tokenring/tms380tr.c b/drivers/net/tokenring/tms380tr.c
index 435ef7d5470f..c83f4f6e39e1 100644
--- a/drivers/net/tokenring/tms380tr.c
+++ b/drivers/net/tokenring/tms380tr.c
@@ -224,7 +224,7 @@ static int madgemc_sifprobe(struct net_device *dev)
chk2 ^= 0x0FE;
if(chk1 != chk2)
- return (-1); /* No adapter */
+ return -1; /* No adapter */
chk1 -= 2;
} while(chk1 != 0); /* Repeat 128 times (all byte values) */
@@ -232,7 +232,7 @@ static int madgemc_sifprobe(struct net_device *dev)
/* Restore the SIFADR value */
SIFWRITEB(old, SIFADR);
- return (0);
+ return 0;
}
#endif
@@ -271,7 +271,7 @@ int tms380tr_open(struct net_device *dev)
{
printk(KERN_INFO "%s: Chipset initialization error\n",
dev->name);
- return (-1);
+ return -1;
}
tp->timer.expires = jiffies + 30*HZ;
@@ -298,7 +298,7 @@ int tms380tr_open(struct net_device *dev)
if(tp->AdapterVirtOpenFlag == 0)
{
tms380tr_disable_interrupts(dev);
- return (-1);
+ return -1;
}
tp->StartTime = jiffies;
@@ -309,7 +309,7 @@ int tms380tr_open(struct net_device *dev)
tp->timer.data = (unsigned long)dev;
add_timer(&tp->timer);
- return (0);
+ return 0;
}
/*
@@ -343,23 +343,23 @@ static int tms380tr_chipset_init(struct net_device *dev)
printk(KERN_DEBUG "%s: Resetting adapter...\n", dev->name);
err = tms380tr_reset_adapter(dev);
if(err < 0)
- return (-1);
+ return -1;
if(tms380tr_debug > 3)
printk(KERN_DEBUG "%s: Bringup diags...\n", dev->name);
err = tms380tr_bringup_diags(dev);
if(err < 0)
- return (-1);
+ return -1;
if(tms380tr_debug > 3)
printk(KERN_DEBUG "%s: Init adapter...\n", dev->name);
err = tms380tr_init_adapter(dev);
if(err < 0)
- return (-1);
+ return -1;
if(tms380tr_debug > 3)
printk(KERN_DEBUG "%s: Done!\n", dev->name);
- return (0);
+ return 0;
}
/*
@@ -877,7 +877,7 @@ static unsigned char tms380tr_chk_ssb(struct net_local *tp, unsigned short IrqTy
IrqType != STS_IRQ_COMMAND_STATUS &&
IrqType != STS_IRQ_RING_STATUS)
{
- return (1); /* SSB not involved. */
+ return 1; /* SSB not involved. */
}
/* Note: All fields of the SSB have been set to all ones (-1) after it
@@ -887,21 +887,21 @@ static unsigned char tms380tr_chk_ssb(struct net_local *tp, unsigned short IrqTy
*/
if(ssb->STS == (unsigned short) -1)
- return (0); /* Command field not yet available. */
+ return 0; /* Command field not yet available. */
if(IrqType == STS_IRQ_COMMAND_STATUS)
- return (1); /* Status fields not always affected. */
+ return 1; /* Status fields not always affected. */
if(ssb->Parm[0] == (unsigned short) -1)
- return (0); /* Status 1 field not yet available. */
+ return 0; /* Status 1 field not yet available. */
if(IrqType == STS_IRQ_RING_STATUS)
- return (1); /* Status 2 & 3 fields not affected. */
+ return 1; /* Status 2 & 3 fields not affected. */
/* Note: At this point, the interrupt is either TRANSMIT or RECEIVE. */
if(ssb->Parm[1] == (unsigned short) -1)
- return (0); /* Status 2 field not yet available. */
+ return 0; /* Status 2 field not yet available. */
if(ssb->Parm[2] == (unsigned short) -1)
- return (0); /* Status 3 field not yet available. */
+ return 0; /* Status 3 field not yet available. */
- return (1); /* All SSB fields have been written by the adapter. */
+ return 1; /* All SSB fields have been written by the adapter. */
}
/*
@@ -1143,7 +1143,7 @@ int tms380tr_close(struct net_device *dev)
#endif
tms380tr_cancel_tx_queue(tp);
- return (0);
+ return 0;
}
/*
@@ -1154,7 +1154,7 @@ static struct net_device_stats *tms380tr_get_stats(struct net_device *dev)
{
struct net_local *tp = netdev_priv(dev);
- return ((struct net_device_stats *)&tp->MacStat);
+ return (struct net_device_stats *)&tp->MacStat;
}
/*
@@ -1256,7 +1256,7 @@ static int tms380tr_reset_adapter(struct net_device *dev)
if (request_firmware(&fw_entry, "tms380tr.bin", tp->pdev) != 0) {
printk(KERN_ALERT "%s: firmware %s is missing, cannot start.\n",
dev->name, "tms380tr.bin");
- return (-1);
+ return -1;
}
fw_ptr = (unsigned short *)fw_entry->data;
@@ -1321,16 +1321,14 @@ static int tms380tr_reset_adapter(struct net_device *dev)
/* Clear CPHALT and start BUD */
SIFWRITEW(c, SIFACL);
- if (fw_entry)
- release_firmware(fw_entry);
- return (1);
+ release_firmware(fw_entry);
+ return 1;
}
} while(count == 0);
- if (fw_entry)
- release_firmware(fw_entry);
+ release_firmware(fw_entry);
printk(KERN_INFO "%s: Adapter Download Failed\n", dev->name);
- return (-1);
+ return -1;
}
MODULE_FIRMWARE("tms380tr.bin");
@@ -1365,7 +1363,7 @@ static int tms380tr_bringup_diags(struct net_device *dev)
printk(KERN_DEBUG " %04X\n", Status);
/* BUD successfully completed */
if(Status == STS_INITIALIZE)
- return (1);
+ return 1;
/* Unrecoverable hardware error, BUD not completed? */
} while((loop_cnt > 0) && ((Status & (STS_ERROR | STS_TEST))
!= (STS_ERROR | STS_TEST)));
@@ -1392,7 +1390,7 @@ static int tms380tr_bringup_diags(struct net_device *dev)
else
printk(KERN_INFO "%s: Bring Up Diagnostics Error (%04X) occurred\n", dev->name, Status & 0x000f);
- return (-1);
+ return -1;
}
/*
@@ -1466,7 +1464,7 @@ static int tms380tr_init_adapter(struct net_device *dev)
{
printk(KERN_INFO "%s: DMA failed\n", dev->name);
/* DMA data error: wrong data in SCB */
- return (-1);
+ return -1;
}
i++;
} while(i < 6);
@@ -1475,11 +1473,11 @@ static int tms380tr_init_adapter(struct net_device *dev)
do { /* Test if contents of SSB is valid */
if(SSB_Test[i] != *(sb_ptr + i))
/* DMA data error: wrong data in SSB */
- return (-1);
+ return -1;
i++;
} while (i < 8);
- return (1); /* Adapter successfully initialized */
+ return 1; /* Adapter successfully initialized */
}
else
{
@@ -1490,7 +1488,7 @@ static int tms380tr_init_adapter(struct net_device *dev)
Status &= STS_ERROR_MASK;
/* ShowInitialisationErrorCode(Status); */
printk(KERN_INFO "%s: Status error: %d\n", dev->name, Status);
- return (-1); /* Unrecoverable error */
+ return -1; /* Unrecoverable error */
}
else
{
@@ -1505,7 +1503,7 @@ static int tms380tr_init_adapter(struct net_device *dev)
} while(retry_cnt > 0);
printk(KERN_INFO "%s: Retry exceeded\n", dev->name);
- return (-1);
+ return -1;
}
/*
diff --git a/drivers/net/tokenring/tmspci.c b/drivers/net/tokenring/tmspci.c
index d4c7c0c0a3d6..d3e788a9cd1c 100644
--- a/drivers/net/tokenring/tmspci.c
+++ b/drivers/net/tokenring/tmspci.c
@@ -125,18 +125,16 @@ static int __devinit tms_pci_attach(struct pci_dev *pdev, const struct pci_devic
dev->irq = pci_irq_line;
dev->dma = 0;
- printk("%s: %s\n", dev->name, cardinfo->name);
- printk("%s: IO: %#4lx IRQ: %d\n",
- dev->name, dev->base_addr, dev->irq);
+ dev_info(&pdev->dev, "%s\n", cardinfo->name);
+ dev_info(&pdev->dev, " IO: %#4lx IRQ: %d\n", dev->base_addr, dev->irq);
tms_pci_read_eeprom(dev);
- printk("%s: Ring Station Address: %pM\n",
- dev->name, dev->dev_addr);
+ dev_info(&pdev->dev, " Ring Station Address: %pM\n", dev->dev_addr);
ret = tmsdev_init(dev, &pdev->dev);
if (ret) {
- printk("%s: unable to get memory for dev->priv.\n", dev->name);
+ dev_info(&pdev->dev, "unable to get memory for dev->priv.\n");
goto err_out_region;
}
diff --git a/drivers/net/tsi108_eth.c b/drivers/net/tsi108_eth.c
index a03730bd1da5..5c633a32eaeb 100644
--- a/drivers/net/tsi108_eth.c
+++ b/drivers/net/tsi108_eth.c
@@ -219,7 +219,7 @@ static int tsi108_read_mii(struct tsi108_prv_data *data, int reg)
if (i == 100)
return 0xffff;
else
- return (TSI_READ_PHY(TSI108_MAC_MII_DATAIN));
+ return TSI_READ_PHY(TSI108_MAC_MII_DATAIN);
}
static void tsi108_write_mii(struct tsi108_prv_data *data,
diff --git a/drivers/net/tulip/Kconfig b/drivers/net/tulip/Kconfig
index 516713fa0a05..f3035951422f 100644
--- a/drivers/net/tulip/Kconfig
+++ b/drivers/net/tulip/Kconfig
@@ -11,8 +11,8 @@ menuconfig NET_TULIP
if NET_TULIP
config DE2104X
- tristate "Early DECchip Tulip (dc2104x) PCI support (EXPERIMENTAL)"
- depends on PCI && EXPERIMENTAL
+ tristate "Early DECchip Tulip (dc2104x) PCI support"
+ depends on PCI
select CRC32
---help---
This driver is developed for the SMC EtherPower series Ethernet
diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c
index 6888e3d41462..28e1ffb13db9 100644
--- a/drivers/net/tulip/de2104x.c
+++ b/drivers/net/tulip/de2104x.c
@@ -948,8 +948,9 @@ static void de_set_media (struct de_private *de)
else
macmode &= ~FullDuplex;
- if (netif_msg_link(de)) {
+ if (netif_msg_link(de))
dev_info(&de->dev->dev, "set link %s\n", media_name[media]);
+ if (netif_msg_hw(de)) {
dev_info(&de->dev->dev, "mode 0x%x, sia 0x%x,0x%x,0x%x,0x%x\n",
dr32(MacMode), dr32(SIAStatus),
dr32(CSR13), dr32(CSR14), dr32(CSR15));
diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c
index 75a64c88cf7a..4dbd493b996b 100644
--- a/drivers/net/tulip/de4x5.c
+++ b/drivers/net/tulip/de4x5.c
@@ -1448,7 +1448,7 @@ de4x5_sw_reset(struct net_device *dev)
status = -EIO;
}
- lp->tx_new = (++lp->tx_new) % lp->txRingSize;
+ lp->tx_new = (lp->tx_new + 1) % lp->txRingSize;
lp->tx_old = lp->tx_new;
return status;
@@ -1506,7 +1506,7 @@ de4x5_queue_pkt(struct sk_buff *skb, struct net_device *dev)
lp->stats.tx_bytes += skb->len;
outl(POLL_DEMAND, DE4X5_TPD);/* Start the TX */
- lp->tx_new = (++lp->tx_new) % lp->txRingSize;
+ lp->tx_new = (lp->tx_new + 1) % lp->txRingSize;
if (TX_BUFFS_AVAIL) {
netif_start_queue(dev); /* Another pkt may be queued */
@@ -1657,7 +1657,7 @@ de4x5_rx(struct net_device *dev)
}
/* Change buffer ownership for this frame, back to the adapter */
- for (;lp->rx_old!=entry;lp->rx_old=(++lp->rx_old)%lp->rxRingSize) {
+ for (;lp->rx_old!=entry;lp->rx_old=(lp->rx_old + 1)%lp->rxRingSize) {
lp->rx_ring[lp->rx_old].status = cpu_to_le32(R_OWN);
barrier();
}
@@ -1668,7 +1668,7 @@ de4x5_rx(struct net_device *dev)
/*
** Update entry information
*/
- lp->rx_new = (++lp->rx_new) % lp->rxRingSize;
+ lp->rx_new = (lp->rx_new + 1) % lp->rxRingSize;
}
return 0;
@@ -1726,7 +1726,7 @@ de4x5_tx(struct net_device *dev)
}
/* Update all the pointers */
- lp->tx_old = (++lp->tx_old) % lp->txRingSize;
+ lp->tx_old = (lp->tx_old + 1) % lp->txRingSize;
}
/* Any resources available? */
@@ -1801,7 +1801,7 @@ de4x5_rx_ovfc(struct net_device *dev)
for (; (s32)le32_to_cpu(lp->rx_ring[lp->rx_new].status)>=0;) {
lp->rx_ring[lp->rx_new].status = cpu_to_le32(R_OWN);
- lp->rx_new = (++lp->rx_new % lp->rxRingSize);
+ lp->rx_new = (lp->rx_new + 1) % lp->rxRingSize;
}
outl(omr, DE4X5_OMR);
@@ -1932,7 +1932,7 @@ set_multicast_list(struct net_device *dev)
load_packet(dev, lp->setup_frame, TD_IC | PERFECT_F | TD_SET |
SETUP_FRAME_LEN, (struct sk_buff *)1);
- lp->tx_new = (++lp->tx_new) % lp->txRingSize;
+ lp->tx_new = (lp->tx_new + 1) % lp->txRingSize;
outl(POLL_DEMAND, DE4X5_TPD); /* Start the TX */
dev->trans_start = jiffies; /* prevent tx timeout */
}
@@ -3119,7 +3119,7 @@ dc2114x_autoconf(struct net_device *dev)
if (lp->media == _100Mb) {
if ((slnk = test_for_100Mb(dev, 6500)) < 0) {
lp->media = SPD_DET;
- return (slnk & ~TIMER_CB);
+ return slnk & ~TIMER_CB;
}
} else {
if (wait_for_link(dev) < 0) {
@@ -3484,7 +3484,7 @@ is_spd_100(struct net_device *dev)
spd = ((~gep_rd(dev)) & GEP_SLNK);
} else {
if ((lp->ibn == 2) || !lp->asBitValid)
- return ((lp->chipset == DC21143)?(~inl(DE4X5_SISR)&SISR_LS100):0);
+ return (lp->chipset == DC21143) ? (~inl(DE4X5_SISR)&SISR_LS100) : 0;
spd = (lp->asBitValid & (lp->asPolarity ^ (gep_rd(dev) & lp->asBit))) |
(lp->linkOK & ~lp->asBitValid);
@@ -3502,15 +3502,15 @@ is_100_up(struct net_device *dev)
if (lp->useMII) {
/* Double read for sticky bits & temporary drops */
mii_rd(MII_SR, lp->phy[lp->active].addr, DE4X5_MII);
- return (mii_rd(MII_SR, lp->phy[lp->active].addr, DE4X5_MII) & MII_SR_LKS);
+ return mii_rd(MII_SR, lp->phy[lp->active].addr, DE4X5_MII) & MII_SR_LKS;
} else if (!lp->useSROM) { /* de500-xa */
- return ((~gep_rd(dev)) & GEP_SLNK);
+ return (~gep_rd(dev)) & GEP_SLNK;
} else {
if ((lp->ibn == 2) || !lp->asBitValid)
- return ((lp->chipset == DC21143)?(~inl(DE4X5_SISR)&SISR_LS100):0);
+ return (lp->chipset == DC21143) ? (~inl(DE4X5_SISR)&SISR_LS100) : 0;
- return ((lp->asBitValid&(lp->asPolarity^(gep_rd(dev)&lp->asBit))) |
- (lp->linkOK & ~lp->asBitValid));
+ return (lp->asBitValid&(lp->asPolarity^(gep_rd(dev)&lp->asBit))) |
+ (lp->linkOK & ~lp->asBitValid);
}
}
@@ -3523,17 +3523,17 @@ is_10_up(struct net_device *dev)
if (lp->useMII) {
/* Double read for sticky bits & temporary drops */
mii_rd(MII_SR, lp->phy[lp->active].addr, DE4X5_MII);
- return (mii_rd(MII_SR, lp->phy[lp->active].addr, DE4X5_MII) & MII_SR_LKS);
+ return mii_rd(MII_SR, lp->phy[lp->active].addr, DE4X5_MII) & MII_SR_LKS;
} else if (!lp->useSROM) { /* de500-xa */
- return ((~gep_rd(dev)) & GEP_LNP);
+ return (~gep_rd(dev)) & GEP_LNP;
} else {
if ((lp->ibn == 2) || !lp->asBitValid)
- return (((lp->chipset & ~0x00ff) == DC2114x) ?
+ return ((lp->chipset & ~0x00ff) == DC2114x) ?
(~inl(DE4X5_SISR)&SISR_LS10):
- 0);
+ 0;
- return ((lp->asBitValid&(lp->asPolarity^(gep_rd(dev)&lp->asBit))) |
- (lp->linkOK & ~lp->asBitValid));
+ return (lp->asBitValid&(lp->asPolarity^(gep_rd(dev)&lp->asBit))) |
+ (lp->linkOK & ~lp->asBitValid);
}
}
@@ -3544,7 +3544,7 @@ is_anc_capable(struct net_device *dev)
u_long iobase = dev->base_addr;
if (lp->phy[lp->active].id && (!lp->useSROM || lp->useMII)) {
- return (mii_rd(MII_SR, lp->phy[lp->active].addr, DE4X5_MII));
+ return mii_rd(MII_SR, lp->phy[lp->active].addr, DE4X5_MII);
} else if ((lp->chipset & ~0x00ff) == DC2114x) {
return (inl(DE4X5_SISR) & SISR_LPN) >> 12;
} else {
@@ -3568,7 +3568,7 @@ ping_media(struct net_device *dev, int msec)
lp->tmp = lp->tx_new; /* Remember the ring position */
load_packet(dev, lp->frame, TD_LS | TD_FS | sizeof(lp->frame), (struct sk_buff *)1);
- lp->tx_new = (++lp->tx_new) % lp->txRingSize;
+ lp->tx_new = (lp->tx_new + 1) % lp->txRingSize;
outl(POLL_DEMAND, DE4X5_TPD);
}
@@ -4930,7 +4930,7 @@ getfrom_mii(u32 command, u_long ioaddr)
outl(command | MII_MDC, ioaddr);
udelay(1);
- return ((inl(ioaddr) >> 19) & 1);
+ return (inl(ioaddr) >> 19) & 1;
}
/*
@@ -4975,8 +4975,8 @@ mii_get_oui(u_char phyaddr, u_long ioaddr)
a.breg[0]=a.breg[1];
a.breg[1]=i;
- return ((a.reg<<8)|ret); */ /* SEEQ and Cypress way */
-/* return ((r2<<6)|(u_int)(r3>>10)); */ /* NATIONAL and BROADCOM way */
+ return (a.reg<<8)|ret; */ /* SEEQ and Cypress way */
+/* return (r2<<6)|(u_int)(r3>>10); */ /* NATIONAL and BROADCOM way */
return r2; /* (I did it) My way */
}
@@ -5144,7 +5144,7 @@ gep_rd(struct net_device *dev)
if (lp->chipset == DC21140) {
return inl(DE4X5_GEP);
} else if ((lp->chipset & ~0x00ff) == DC2114x) {
- return (inl(DE4X5_SIGR) & 0x000fffff);
+ return inl(DE4X5_SIGR) & 0x000fffff;
}
return 0;
@@ -5417,7 +5417,7 @@ de4x5_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
/* Set up the descriptor and give ownership to the card */
load_packet(dev, lp->setup_frame, TD_IC | PERFECT_F | TD_SET |
SETUP_FRAME_LEN, (struct sk_buff *)1);
- lp->tx_new = (++lp->tx_new) % lp->txRingSize;
+ lp->tx_new = (lp->tx_new + 1) % lp->txRingSize;
outl(POLL_DEMAND, DE4X5_TPD); /* Start the TX */
netif_wake_queue(dev); /* Unlock the TX ring */
break;
@@ -5474,7 +5474,8 @@ de4x5_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
tmp.lval[6] = inl(DE4X5_STRR); j+=4;
tmp.lval[7] = inl(DE4X5_SIGR); j+=4;
ioc->len = j;
- if (copy_to_user(ioc->data, tmp.addr, ioc->len)) return -EFAULT;
+ if (copy_to_user(ioc->data, tmp.lval, ioc->len))
+ return -EFAULT;
break;
#define DE4X5_DUMP 0x0f /* Dump the DE4X5 Status */
diff --git a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c
index 0bc4f3030a80..a9f7d5d1a269 100644
--- a/drivers/net/tulip/dmfe.c
+++ b/drivers/net/tulip/dmfe.c
@@ -599,7 +599,7 @@ static int dmfe_open(struct DEVICE *dev)
init_timer(&db->timer);
db->timer.expires = DMFE_TIMER_WUT + HZ * 2;
db->timer.data = (unsigned long)dev;
- db->timer.function = &dmfe_timer;
+ db->timer.function = dmfe_timer;
add_timer(&db->timer);
return 0;
diff --git a/drivers/net/tulip/interrupt.c b/drivers/net/tulip/interrupt.c
index 1faf7a4d7202..0013642903ee 100644
--- a/drivers/net/tulip/interrupt.c
+++ b/drivers/net/tulip/interrupt.c
@@ -180,21 +180,24 @@ int tulip_poll(struct napi_struct *napi, int budget)
dev_warn(&dev->dev,
"Oversized Ethernet frame spanned multiple buffers, status %08x!\n",
status);
- tp->stats.rx_length_errors++;
- }
+ dev->stats.rx_length_errors++;
+ }
} else {
/* There was a fatal error. */
if (tulip_debug > 2)
printk(KERN_DEBUG "%s: Receive error, Rx status %08x\n",
dev->name, status);
- tp->stats.rx_errors++; /* end of a packet.*/
- if (pkt_len > 1518 ||
- (status & RxDescRunt))
- tp->stats.rx_length_errors++;
-
- if (status & 0x0004) tp->stats.rx_frame_errors++;
- if (status & 0x0002) tp->stats.rx_crc_errors++;
- if (status & 0x0001) tp->stats.rx_fifo_errors++;
+ dev->stats.rx_errors++; /* end of a packet.*/
+ if (pkt_len > 1518 ||
+ (status & RxDescRunt))
+ dev->stats.rx_length_errors++;
+
+ if (status & 0x0004)
+ dev->stats.rx_frame_errors++;
+ if (status & 0x0002)
+ dev->stats.rx_crc_errors++;
+ if (status & 0x0001)
+ dev->stats.rx_fifo_errors++;
}
} else {
struct sk_buff *skb;
@@ -244,8 +247,8 @@ int tulip_poll(struct napi_struct *napi, int budget)
netif_receive_skb(skb);
- tp->stats.rx_packets++;
- tp->stats.rx_bytes += pkt_len;
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += pkt_len;
}
#ifdef CONFIG_TULIP_NAPI_HW_MITIGATION
received++;
@@ -404,20 +407,23 @@ static int tulip_rx(struct net_device *dev)
dev_warn(&dev->dev,
"Oversized Ethernet frame spanned multiple buffers, status %08x!\n",
status);
- tp->stats.rx_length_errors++;
+ dev->stats.rx_length_errors++;
}
} else {
/* There was a fatal error. */
if (tulip_debug > 2)
printk(KERN_DEBUG "%s: Receive error, Rx status %08x\n",
dev->name, status);
- tp->stats.rx_errors++; /* end of a packet.*/
+ dev->stats.rx_errors++; /* end of a packet.*/
if (pkt_len > 1518 ||
(status & RxDescRunt))
- tp->stats.rx_length_errors++;
- if (status & 0x0004) tp->stats.rx_frame_errors++;
- if (status & 0x0002) tp->stats.rx_crc_errors++;
- if (status & 0x0001) tp->stats.rx_fifo_errors++;
+ dev->stats.rx_length_errors++;
+ if (status & 0x0004)
+ dev->stats.rx_frame_errors++;
+ if (status & 0x0002)
+ dev->stats.rx_crc_errors++;
+ if (status & 0x0001)
+ dev->stats.rx_fifo_errors++;
}
} else {
struct sk_buff *skb;
@@ -467,8 +473,8 @@ static int tulip_rx(struct net_device *dev)
netif_rx(skb);
- tp->stats.rx_packets++;
- tp->stats.rx_bytes += pkt_len;
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += pkt_len;
}
received++;
entry = (++tp->cur_rx) % RX_RING_SIZE;
@@ -602,18 +608,22 @@ irqreturn_t tulip_interrupt(int irq, void *dev_instance)
printk(KERN_DEBUG "%s: Transmit error, Tx status %08x\n",
dev->name, status);
#endif
- tp->stats.tx_errors++;
- if (status & 0x4104) tp->stats.tx_aborted_errors++;
- if (status & 0x0C00) tp->stats.tx_carrier_errors++;
- if (status & 0x0200) tp->stats.tx_window_errors++;
- if (status & 0x0002) tp->stats.tx_fifo_errors++;
+ dev->stats.tx_errors++;
+ if (status & 0x4104)
+ dev->stats.tx_aborted_errors++;
+ if (status & 0x0C00)
+ dev->stats.tx_carrier_errors++;
+ if (status & 0x0200)
+ dev->stats.tx_window_errors++;
+ if (status & 0x0002)
+ dev->stats.tx_fifo_errors++;
if ((status & 0x0080) && tp->full_duplex == 0)
- tp->stats.tx_heartbeat_errors++;
+ dev->stats.tx_heartbeat_errors++;
} else {
- tp->stats.tx_bytes +=
+ dev->stats.tx_bytes +=
tp->tx_buffers[entry].skb->len;
- tp->stats.collisions += (status >> 3) & 15;
- tp->stats.tx_packets++;
+ dev->stats.collisions += (status >> 3) & 15;
+ dev->stats.tx_packets++;
}
pci_unmap_single(tp->pdev, tp->tx_buffers[entry].mapping,
@@ -655,7 +665,8 @@ irqreturn_t tulip_interrupt(int irq, void *dev_instance)
if (csr5 & AbnormalIntr) { /* Abnormal error summary bit. */
if (csr5 == 0xffffffff)
break;
- if (csr5 & TxJabber) tp->stats.tx_errors++;
+ if (csr5 & TxJabber)
+ dev->stats.tx_errors++;
if (csr5 & TxFIFOUnderflow) {
if ((tp->csr6 & 0xC000) != 0xC000)
tp->csr6 += 0x4000; /* Bump up the Tx threshold */
@@ -672,8 +683,8 @@ irqreturn_t tulip_interrupt(int irq, void *dev_instance)
}
}
if (csr5 & RxDied) { /* Missed a Rx frame. */
- tp->stats.rx_missed_errors += ioread32(ioaddr + CSR8) & 0xffff;
- tp->stats.rx_errors++;
+ dev->stats.rx_missed_errors += ioread32(ioaddr + CSR8) & 0xffff;
+ dev->stats.rx_errors++;
tulip_start_rxtx(tp);
}
/*
@@ -789,7 +800,7 @@ irqreturn_t tulip_interrupt(int irq, void *dev_instance)
#endif /* CONFIG_TULIP_NAPI */
if ((missed = ioread32(ioaddr + CSR8) & 0x1ffff)) {
- tp->stats.rx_dropped += missed & 0x10000 ? 0x10000 : missed;
+ dev->stats.rx_dropped += missed & 0x10000 ? 0x10000 : missed;
}
if (tulip_debug > 4)
diff --git a/drivers/net/tulip/tulip.h b/drivers/net/tulip/tulip.h
index e525875ed67d..ed66a16711dc 100644
--- a/drivers/net/tulip/tulip.h
+++ b/drivers/net/tulip/tulip.h
@@ -417,7 +417,6 @@ struct tulip_private {
int revision;
int flags;
struct napi_struct napi;
- struct net_device_stats stats;
struct timer_list timer; /* Media selection timer. */
struct timer_list oom_timer; /* Out of memory timer. */
u32 mc_filter[2];
@@ -570,7 +569,7 @@ static inline void tulip_tx_timeout_complete(struct tulip_private *tp, void __io
/* Trigger an immediate transmit demand. */
iowrite32(0, ioaddr + CSR1);
- tp->stats.tx_errors++;
+ tp->dev->stats.tx_errors++;
}
#endif /* __NET_TULIP_H__ */
diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
index 3a8d7efa2acf..2c39f2591216 100644
--- a/drivers/net/tulip/tulip_core.c
+++ b/drivers/net/tulip/tulip_core.c
@@ -725,7 +725,7 @@ static void tulip_clean_tx_ring(struct tulip_private *tp)
int status = le32_to_cpu(tp->tx_ring[entry].status);
if (status < 0) {
- tp->stats.tx_errors++; /* It wasn't Txed */
+ tp->dev->stats.tx_errors++; /* It wasn't Txed */
tp->tx_ring[entry].status = 0;
}
@@ -781,8 +781,8 @@ static void tulip_down (struct net_device *dev)
/* release any unconsumed transmit buffers */
tulip_clean_tx_ring(tp);
- if (ioread32 (ioaddr + CSR6) != 0xffffffff)
- tp->stats.rx_missed_errors += ioread32 (ioaddr + CSR8) & 0xffff;
+ if (ioread32(ioaddr + CSR6) != 0xffffffff)
+ dev->stats.rx_missed_errors += ioread32(ioaddr + CSR8) & 0xffff;
spin_unlock_irqrestore (&tp->lock, flags);
@@ -864,12 +864,12 @@ static struct net_device_stats *tulip_get_stats(struct net_device *dev)
spin_lock_irqsave (&tp->lock, flags);
- tp->stats.rx_missed_errors += ioread32(ioaddr + CSR8) & 0xffff;
+ dev->stats.rx_missed_errors += ioread32(ioaddr + CSR8) & 0xffff;
spin_unlock_irqrestore(&tp->lock, flags);
}
- return &tp->stats;
+ return &dev->stats;
}
diff --git a/drivers/net/tulip/uli526x.c b/drivers/net/tulip/uli526x.c
index 96de5829b940..74217dbf0143 100644
--- a/drivers/net/tulip/uli526x.c
+++ b/drivers/net/tulip/uli526x.c
@@ -480,7 +480,7 @@ static int uli526x_open(struct net_device *dev)
init_timer(&db->timer);
db->timer.expires = ULI526X_TIMER_WUT + HZ * 2;
db->timer.data = (unsigned long)dev;
- db->timer.function = &uli526x_timer;
+ db->timer.function = uli526x_timer;
add_timer(&db->timer);
return 0;
@@ -1747,7 +1747,7 @@ static u16 phy_readby_cr10(unsigned long iobase, u8 phy_addr, u8 offset)
if(cr10_value&0x10000000)
break;
}
- return (cr10_value&0x0ffff);
+ return cr10_value & 0x0ffff;
}
static void phy_writeby_cr10(unsigned long iobase, u8 phy_addr, u8 offset, u16 phy_data)
diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c
index 66d41cf8da29..f0b231035dee 100644
--- a/drivers/net/tulip/winbond-840.c
+++ b/drivers/net/tulip/winbond-840.c
@@ -662,7 +662,7 @@ static int netdev_open(struct net_device *dev)
init_timer(&np->timer);
np->timer.expires = jiffies + 1*HZ;
np->timer.data = (unsigned long)dev;
- np->timer.function = &netdev_timer; /* timer handler */
+ np->timer.function = netdev_timer; /* timer handler */
add_timer(&np->timer);
return 0;
out_err:
diff --git a/drivers/net/tulip/xircom_cb.c b/drivers/net/tulip/xircom_cb.c
index a439e93be22d..5a73752be2ca 100644
--- a/drivers/net/tulip/xircom_cb.c
+++ b/drivers/net/tulip/xircom_cb.c
@@ -29,7 +29,6 @@
#include <linux/skbuff.h>
#include <linux/delay.h>
#include <linux/init.h>
-#include <linux/ethtool.h>
#include <linux/bitops.h>
#include <asm/uaccess.h>
@@ -181,19 +180,6 @@ static void print_binary(unsigned int number)
}
#endif
-static void netdev_get_drvinfo(struct net_device *dev,
- struct ethtool_drvinfo *info)
-{
- struct xircom_private *private = netdev_priv(dev);
-
- strcpy(info->driver, "xircom_cb");
- strcpy(info->bus_info, pci_name(private->pdev));
-}
-
-static const struct ethtool_ops netdev_ethtool_ops = {
- .get_drvinfo = netdev_get_drvinfo,
-};
-
static const struct net_device_ops netdev_ops = {
.ndo_open = xircom_open,
.ndo_stop = xircom_close,
@@ -279,7 +265,6 @@ static int __devinit xircom_probe(struct pci_dev *pdev, const struct pci_device_
setup_descriptors(private);
dev->netdev_ops = &netdev_ops;
- SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
pci_set_drvdata(pdev, dev);
if (register_netdev(dev)) {
diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c
index 2e50077ff450..1cc67138adbf 100644
--- a/drivers/net/typhoon.c
+++ b/drivers/net/typhoon.c
@@ -541,7 +541,7 @@ cleanup:
indexes->respCleared = cpu_to_le32(cleared);
wmb();
- return (resp_save == NULL);
+ return resp_save == NULL;
}
static inline int
@@ -962,36 +962,34 @@ typhoon_do_get_stats(struct typhoon *tp)
* The extra status reported would be a good candidate for
* ethtool_ops->get_{strings,stats}()
*/
- stats->tx_packets = le32_to_cpu(s->txPackets);
- stats->tx_bytes = le64_to_cpu(s->txBytes);
- stats->tx_errors = le32_to_cpu(s->txCarrierLost);
- stats->tx_carrier_errors = le32_to_cpu(s->txCarrierLost);
- stats->collisions = le32_to_cpu(s->txMultipleCollisions);
- stats->rx_packets = le32_to_cpu(s->rxPacketsGood);
- stats->rx_bytes = le64_to_cpu(s->rxBytesGood);
- stats->rx_fifo_errors = le32_to_cpu(s->rxFifoOverruns);
+ stats->tx_packets = le32_to_cpu(s->txPackets) +
+ saved->tx_packets;
+ stats->tx_bytes = le64_to_cpu(s->txBytes) +
+ saved->tx_bytes;
+ stats->tx_errors = le32_to_cpu(s->txCarrierLost) +
+ saved->tx_errors;
+ stats->tx_carrier_errors = le32_to_cpu(s->txCarrierLost) +
+ saved->tx_carrier_errors;
+ stats->collisions = le32_to_cpu(s->txMultipleCollisions) +
+ saved->collisions;
+ stats->rx_packets = le32_to_cpu(s->rxPacketsGood) +
+ saved->rx_packets;
+ stats->rx_bytes = le64_to_cpu(s->rxBytesGood) +
+ saved->rx_bytes;
+ stats->rx_fifo_errors = le32_to_cpu(s->rxFifoOverruns) +
+ saved->rx_fifo_errors;
stats->rx_errors = le32_to_cpu(s->rxFifoOverruns) +
- le32_to_cpu(s->BadSSD) + le32_to_cpu(s->rxCrcErrors);
- stats->rx_crc_errors = le32_to_cpu(s->rxCrcErrors);
- stats->rx_length_errors = le32_to_cpu(s->rxOversized);
+ le32_to_cpu(s->BadSSD) + le32_to_cpu(s->rxCrcErrors) +
+ saved->rx_errors;
+ stats->rx_crc_errors = le32_to_cpu(s->rxCrcErrors) +
+ saved->rx_crc_errors;
+ stats->rx_length_errors = le32_to_cpu(s->rxOversized) +
+ saved->rx_length_errors;
tp->speed = (s->linkStatus & TYPHOON_LINK_100MBPS) ?
SPEED_100 : SPEED_10;
tp->duplex = (s->linkStatus & TYPHOON_LINK_FULL_DUPLEX) ?
DUPLEX_FULL : DUPLEX_HALF;
- /* add in the saved statistics
- */
- stats->tx_packets += saved->tx_packets;
- stats->tx_bytes += saved->tx_bytes;
- stats->tx_errors += saved->tx_errors;
- stats->collisions += saved->collisions;
- stats->rx_packets += saved->rx_packets;
- stats->rx_bytes += saved->rx_bytes;
- stats->rx_fifo_errors += saved->rx_fifo_errors;
- stats->rx_errors += saved->rx_errors;
- stats->rx_crc_errors += saved->rx_crc_errors;
- stats->rx_length_errors += saved->rx_length_errors;
-
return 0;
}
@@ -1762,7 +1760,7 @@ typhoon_rx(struct typhoon *tp, struct basic_ring *rxRing, volatile __le32 * read
(TYPHOON_RX_IP_CHK_GOOD | TYPHOON_RX_UDP_CHK_GOOD)) {
new_skb->ip_summed = CHECKSUM_UNNECESSARY;
} else
- new_skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(new_skb);
spin_lock(&tp->state_lock);
if(tp->vlgrp != NULL && rx->rxStatus & TYPHOON_RX_VLAN)
diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig
index d7b7018a1de1..52ffabe6db0e 100644
--- a/drivers/net/usb/Kconfig
+++ b/drivers/net/usb/Kconfig
@@ -358,6 +358,14 @@ config USB_NET_ZAURUS
really need this non-conformant variant of CDC Ethernet (or in
some cases CDC MDLM) protocol, not "g_ether".
+config USB_NET_CX82310_ETH
+ tristate "Conexant CX82310 USB ethernet port"
+ depends on USB_USBNET
+ help
+ Choose this option if you're using a Conexant CX82310-based ADSL
+ router with USB ethernet port. This driver is for routers only,
+ it will not work with ADSL modems (use cxacru driver instead).
+
config USB_HSO
tristate "Option USB High Speed Mobile Devices"
depends on USB && RFKILL
diff --git a/drivers/net/usb/Makefile b/drivers/net/usb/Makefile
index b13a279663ba..a19b0259ae16 100644
--- a/drivers/net/usb/Makefile
+++ b/drivers/net/usb/Makefile
@@ -25,4 +25,5 @@ obj-$(CONFIG_USB_NET_INT51X1) += int51x1.o
obj-$(CONFIG_USB_CDC_PHONET) += cdc-phonet.o
obj-$(CONFIG_USB_IPHETH) += ipheth.o
obj-$(CONFIG_USB_SIERRA_NET) += sierra_net.o
+obj-$(CONFIG_USB_NET_CX82310_ETH) += cx82310_eth.o
diff --git a/drivers/net/usb/cx82310_eth.c b/drivers/net/usb/cx82310_eth.c
new file mode 100644
index 000000000000..8969f124c18c
--- /dev/null
+++ b/drivers/net/usb/cx82310_eth.c
@@ -0,0 +1,346 @@
+/*
+ * Driver for USB ethernet port of Conexant CX82310-based ADSL routers
+ * Copyright (C) 2010 by Ondrej Zary
+ * some parts inspired by the cxacru driver
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/workqueue.h>
+#include <linux/mii.h>
+#include <linux/usb.h>
+#include <linux/usb/usbnet.h>
+
+enum cx82310_cmd {
+ CMD_START = 0x84, /* no effect? */
+ CMD_STOP = 0x85, /* no effect? */
+ CMD_GET_STATUS = 0x90, /* returns nothing? */
+ CMD_GET_MAC_ADDR = 0x91, /* read MAC address */
+ CMD_GET_LINK_STATUS = 0x92, /* not useful, link is always up */
+ CMD_ETHERNET_MODE = 0x99, /* unknown, needed during init */
+};
+
+enum cx82310_status {
+ STATUS_UNDEFINED,
+ STATUS_SUCCESS,
+ STATUS_ERROR,
+ STATUS_UNSUPPORTED,
+ STATUS_UNIMPLEMENTED,
+ STATUS_PARAMETER_ERROR,
+ STATUS_DBG_LOOPBACK,
+};
+
+#define CMD_PACKET_SIZE 64
+/* first command after power on can take around 8 seconds */
+#define CMD_TIMEOUT 15000
+#define CMD_REPLY_RETRY 5
+
+#define CX82310_MTU 1514
+#define CMD_EP 0x01
+
+/*
+ * execute control command
+ * - optionally send some data (command parameters)
+ * - optionally wait for the reply
+ * - optionally read some data from the reply
+ */
+static int cx82310_cmd(struct usbnet *dev, enum cx82310_cmd cmd, bool reply,
+ u8 *wdata, int wlen, u8 *rdata, int rlen)
+{
+ int actual_len, retries, ret;
+ struct usb_device *udev = dev->udev;
+ u8 *buf = kzalloc(CMD_PACKET_SIZE, GFP_KERNEL);
+
+ if (!buf)
+ return -ENOMEM;
+
+ /* create command packet */
+ buf[0] = cmd;
+ if (wdata)
+ memcpy(buf + 4, wdata, min_t(int, wlen, CMD_PACKET_SIZE - 4));
+
+ /* send command packet */
+ ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, CMD_EP), buf,
+ CMD_PACKET_SIZE, &actual_len, CMD_TIMEOUT);
+ if (ret < 0) {
+ dev_err(&dev->udev->dev, "send command %#x: error %d\n",
+ cmd, ret);
+ goto end;
+ }
+
+ if (reply) {
+ /* wait for reply, retry if it's empty */
+ for (retries = 0; retries < CMD_REPLY_RETRY; retries++) {
+ ret = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, CMD_EP),
+ buf, CMD_PACKET_SIZE, &actual_len,
+ CMD_TIMEOUT);
+ if (ret < 0) {
+ dev_err(&dev->udev->dev,
+ "reply receive error %d\n", ret);
+ goto end;
+ }
+ if (actual_len > 0)
+ break;
+ }
+ if (actual_len == 0) {
+ dev_err(&dev->udev->dev, "no reply to command %#x\n",
+ cmd);
+ ret = -EIO;
+ goto end;
+ }
+ if (buf[0] != cmd) {
+ dev_err(&dev->udev->dev,
+ "got reply to command %#x, expected: %#x\n",
+ buf[0], cmd);
+ ret = -EIO;
+ goto end;
+ }
+ if (buf[1] != STATUS_SUCCESS) {
+ dev_err(&dev->udev->dev, "command %#x failed: %#x\n",
+ cmd, buf[1]);
+ ret = -EIO;
+ goto end;
+ }
+ if (rdata)
+ memcpy(rdata, buf + 4,
+ min_t(int, rlen, CMD_PACKET_SIZE - 4));
+ }
+end:
+ kfree(buf);
+ return ret;
+}
+
+#define partial_len data[0] /* length of partial packet data */
+#define partial_rem data[1] /* remaining (missing) data length */
+#define partial_data data[2] /* partial packet data */
+
+static int cx82310_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+ int ret;
+ char buf[15];
+ struct usb_device *udev = dev->udev;
+
+ /* avoid ADSL modems - continue only if iProduct is "USB NET CARD" */
+ if (usb_string(udev, udev->descriptor.iProduct, buf, sizeof(buf)) > 0
+ && strcmp(buf, "USB NET CARD")) {
+ dev_info(&udev->dev, "ignoring: probably an ADSL modem\n");
+ return -ENODEV;
+ }
+
+ ret = usbnet_get_endpoints(dev, intf);
+ if (ret)
+ return ret;
+
+ /*
+ * this must not include ethernet header as the device can send partial
+ * packets with no header (and sometimes even empty URBs)
+ */
+ dev->net->hard_header_len = 0;
+ /* we can send at most 1514 bytes of data (+ 2-byte header) per URB */
+ dev->hard_mtu = CX82310_MTU + 2;
+ /* we can receive URBs up to 4KB from the device */
+ dev->rx_urb_size = 4096;
+
+ dev->partial_data = (unsigned long) kmalloc(dev->hard_mtu, GFP_KERNEL);
+ if (!dev->partial_data)
+ return -ENOMEM;
+
+ /* enable ethernet mode (?) */
+ ret = cx82310_cmd(dev, CMD_ETHERNET_MODE, true, "\x01", 1, NULL, 0);
+ if (ret) {
+ dev_err(&udev->dev, "unable to enable ethernet mode: %d\n",
+ ret);
+ goto err;
+ }
+
+ /* get the MAC address */
+ ret = cx82310_cmd(dev, CMD_GET_MAC_ADDR, true, NULL, 0,
+ dev->net->dev_addr, ETH_ALEN);
+ if (ret) {
+ dev_err(&udev->dev, "unable to read MAC address: %d\n", ret);
+ goto err;
+ }
+
+ /* start (does not seem to have any effect?) */
+ ret = cx82310_cmd(dev, CMD_START, false, NULL, 0, NULL, 0);
+ if (ret)
+ goto err;
+
+ return 0;
+err:
+ kfree((void *)dev->partial_data);
+ return ret;
+}
+
+static void cx82310_unbind(struct usbnet *dev, struct usb_interface *intf)
+{
+ kfree((void *)dev->partial_data);
+}
+
+/*
+ * RX is NOT easy - we can receive multiple packets per skb, each having 2-byte
+ * packet length at the beginning.
+ * The last packet might be incomplete (when it crosses the 4KB URB size),
+ * continuing in the next skb (without any headers).
+ * If a packet has odd length, there is one extra byte at the end (before next
+ * packet or at the end of the URB).
+ */
+static int cx82310_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+{
+ int len;
+ struct sk_buff *skb2;
+
+ /*
+ * If the last skb ended with an incomplete packet, this skb contains
+ * end of that packet at the beginning.
+ */
+ if (dev->partial_rem) {
+ len = dev->partial_len + dev->partial_rem;
+ skb2 = alloc_skb(len, GFP_ATOMIC);
+ if (!skb2)
+ return 0;
+ skb_put(skb2, len);
+ memcpy(skb2->data, (void *)dev->partial_data,
+ dev->partial_len);
+ memcpy(skb2->data + dev->partial_len, skb->data,
+ dev->partial_rem);
+ usbnet_skb_return(dev, skb2);
+ skb_pull(skb, (dev->partial_rem + 1) & ~1);
+ dev->partial_rem = 0;
+ if (skb->len < 2)
+ return 1;
+ }
+
+ /* a skb can contain multiple packets */
+ while (skb->len > 1) {
+ /* first two bytes are packet length */
+ len = skb->data[0] | (skb->data[1] << 8);
+ skb_pull(skb, 2);
+
+ /* if last packet in the skb, let usbnet to process it */
+ if (len == skb->len || len + 1 == skb->len) {
+ skb_trim(skb, len);
+ break;
+ }
+
+ if (len > CX82310_MTU) {
+ dev_err(&dev->udev->dev, "RX packet too long: %d B\n",
+ len);
+ return 0;
+ }
+
+ /* incomplete packet, save it for the next skb */
+ if (len > skb->len) {
+ dev->partial_len = skb->len;
+ dev->partial_rem = len - skb->len;
+ memcpy((void *)dev->partial_data, skb->data,
+ dev->partial_len);
+ skb_pull(skb, skb->len);
+ break;
+ }
+
+ skb2 = alloc_skb(len, GFP_ATOMIC);
+ if (!skb2)
+ return 0;
+ skb_put(skb2, len);
+ memcpy(skb2->data, skb->data, len);
+ /* process the packet */
+ usbnet_skb_return(dev, skb2);
+
+ skb_pull(skb, (len + 1) & ~1);
+ }
+
+ /* let usbnet process the last packet */
+ return 1;
+}
+
+/* TX is easy, just add 2 bytes of length at the beginning */
+static struct sk_buff *cx82310_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
+ gfp_t flags)
+{
+ int len = skb->len;
+
+ if (skb_headroom(skb) < 2) {
+ struct sk_buff *skb2 = skb_copy_expand(skb, 2, 0, flags);
+ dev_kfree_skb_any(skb);
+ skb = skb2;
+ if (!skb)
+ return NULL;
+ }
+ skb_push(skb, 2);
+
+ skb->data[0] = len;
+ skb->data[1] = len >> 8;
+
+ return skb;
+}
+
+
+static const struct driver_info cx82310_info = {
+ .description = "Conexant CX82310 USB ethernet",
+ .flags = FLAG_ETHER,
+ .bind = cx82310_bind,
+ .unbind = cx82310_unbind,
+ .rx_fixup = cx82310_rx_fixup,
+ .tx_fixup = cx82310_tx_fixup,
+};
+
+#define USB_DEVICE_CLASS(vend, prod, cl, sc, pr) \
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
+ USB_DEVICE_ID_MATCH_DEV_INFO, \
+ .idVendor = (vend), \
+ .idProduct = (prod), \
+ .bDeviceClass = (cl), \
+ .bDeviceSubClass = (sc), \
+ .bDeviceProtocol = (pr)
+
+static const struct usb_device_id products[] = {
+ {
+ USB_DEVICE_CLASS(0x0572, 0xcb01, 0xff, 0, 0),
+ .driver_info = (unsigned long) &cx82310_info
+ },
+ { },
+};
+MODULE_DEVICE_TABLE(usb, products);
+
+static struct usb_driver cx82310_driver = {
+ .name = "cx82310_eth",
+ .id_table = products,
+ .probe = usbnet_probe,
+ .disconnect = usbnet_disconnect,
+ .suspend = usbnet_suspend,
+ .resume = usbnet_resume,
+};
+
+static int __init cx82310_init(void)
+{
+ return usb_register(&cx82310_driver);
+}
+module_init(cx82310_init);
+
+static void __exit cx82310_exit(void)
+{
+ usb_deregister(&cx82310_driver);
+}
+module_exit(cx82310_exit);
+
+MODULE_AUTHOR("Ondrej Zary");
+MODULE_DESCRIPTION("Conexant CX82310-based ADSL router USB ethernet driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c
index 1cd752f9a6e1..b154a94de03e 100644
--- a/drivers/net/usb/hso.c
+++ b/drivers/net/usb/hso.c
@@ -843,16 +843,7 @@ static netdev_tx_t hso_net_start_xmit(struct sk_buff *skb,
return NETDEV_TX_OK;
}
-static void hso_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *info)
-{
- struct hso_net *odev = netdev_priv(net);
-
- strncpy(info->driver, driver_name, ETHTOOL_BUSINFO_LEN);
- usb_make_path(odev->parent->usb, info->bus_info, sizeof info->bus_info);
-}
-
static const struct ethtool_ops ops = {
- .get_drvinfo = hso_get_drvinfo,
.get_link = ethtool_op_get_link
};
@@ -1645,11 +1636,11 @@ hso_wait_modem_status(struct hso_serial *serial, unsigned long arg)
* NB: both 1->0 and 0->1 transitions are counted except for
* RI where only 0->1 is counted.
*/
-static int hso_get_count(struct hso_serial *serial,
- struct serial_icounter_struct __user *icnt)
+static int hso_get_count(struct tty_struct *tty,
+ struct serial_icounter_struct *icount)
{
- struct serial_icounter_struct icount;
struct uart_icount cnow;
+ struct hso_serial *serial = get_serial_by_tty(tty);
struct hso_tiocmget *tiocmget = serial->tiocmget;
memset(&icount, 0, sizeof(struct serial_icounter_struct));
@@ -1660,19 +1651,19 @@ static int hso_get_count(struct hso_serial *serial,
memcpy(&cnow, &tiocmget->icount, sizeof(struct uart_icount));
spin_unlock_irq(&serial->serial_lock);
- icount.cts = cnow.cts;
- icount.dsr = cnow.dsr;
- icount.rng = cnow.rng;
- icount.dcd = cnow.dcd;
- icount.rx = cnow.rx;
- icount.tx = cnow.tx;
- icount.frame = cnow.frame;
- icount.overrun = cnow.overrun;
- icount.parity = cnow.parity;
- icount.brk = cnow.brk;
- icount.buf_overrun = cnow.buf_overrun;
+ icount->cts = cnow.cts;
+ icount->dsr = cnow.dsr;
+ icount->rng = cnow.rng;
+ icount->dcd = cnow.dcd;
+ icount->rx = cnow.rx;
+ icount->tx = cnow.tx;
+ icount->frame = cnow.frame;
+ icount->overrun = cnow.overrun;
+ icount->parity = cnow.parity;
+ icount->brk = cnow.brk;
+ icount->buf_overrun = cnow.buf_overrun;
- return copy_to_user(icnt, &icount, sizeof(icount)) ? -EFAULT : 0;
+ return 0;
}
@@ -1764,10 +1755,6 @@ static int hso_serial_ioctl(struct tty_struct *tty, struct file *file,
case TIOCMIWAIT:
ret = hso_wait_modem_status(serial, arg);
break;
-
- case TIOCGICOUNT:
- ret = hso_get_count(serial, uarg);
- break;
default:
ret = -ENOIOCTLCMD;
break;
@@ -3300,6 +3287,7 @@ static const struct tty_operations hso_serial_ops = {
.chars_in_buffer = hso_serial_chars_in_buffer,
.tiocmget = hso_serial_tiocmget,
.tiocmset = hso_serial_tiocmset,
+ .get_icount = hso_get_count,
.unthrottle = hso_unthrottle
};
diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c
index 2b7b39cad1ce..5e98643a4a21 100644
--- a/drivers/net/usb/kaweth.c
+++ b/drivers/net/usb/kaweth.c
@@ -759,14 +759,6 @@ static int kaweth_close(struct net_device *net)
return 0;
}
-static void kaweth_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
-{
- struct kaweth_device *kaweth = netdev_priv(dev);
-
- strlcpy(info->driver, driver_name, sizeof(info->driver));
- usb_make_path(kaweth->dev, info->bus_info, sizeof (info->bus_info));
-}
-
static u32 kaweth_get_link(struct net_device *dev)
{
struct kaweth_device *kaweth = netdev_priv(dev);
@@ -775,7 +767,6 @@ static u32 kaweth_get_link(struct net_device *dev)
}
static const struct ethtool_ops ops = {
- .get_drvinfo = kaweth_get_drvinfo,
.get_link = kaweth_get_link
};
diff --git a/drivers/net/usb/sierra_net.c b/drivers/net/usb/sierra_net.c
index ee85c8b9a858..d1ac15c95faf 100644
--- a/drivers/net/usb/sierra_net.c
+++ b/drivers/net/usb/sierra_net.c
@@ -203,7 +203,7 @@ static inline void sierra_net_set_private(struct usbnet *dev,
/* is packet IPv4 */
static inline int is_ip(struct sk_buff *skb)
{
- return (skb->protocol == cpu_to_be16(ETH_P_IP));
+ return skb->protocol == cpu_to_be16(ETH_P_IP);
}
/*
@@ -354,7 +354,7 @@ static void sierra_net_set_ctx_index(struct sierra_net_data *priv, u8 ctx_ix)
static inline int sierra_net_is_valid_addrlen(u8 len)
{
- return (len == sizeof(struct in_addr));
+ return len == sizeof(struct in_addr);
}
static int sierra_net_parse_lsi(struct usbnet *dev, char *data, int datalen)
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index 12a3c88c5282..65cb1abfbe57 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -805,8 +805,6 @@ static int smsc95xx_reset(struct usbnet *dev)
return ret;
}
- smsc95xx_init_mac_address(dev);
-
ret = smsc95xx_set_mac_address(dev);
if (ret < 0)
return ret;
@@ -1047,6 +1045,8 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf)
pdata->use_tx_csum = DEFAULT_TX_CSUM_ENABLE;
pdata->use_rx_csum = DEFAULT_RX_CSUM_ENABLE;
+ smsc95xx_init_mac_address(dev);
+
/* Init all registers */
ret = smsc95xx_reset(dev);
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index 5ec542dd5b50..0bbc0c323135 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -250,7 +250,7 @@ static int veth_close(struct net_device *dev)
static int is_valid_veth_mtu(int new_mtu)
{
- return (new_mtu >= MIN_MTU && new_mtu <= MAX_MTU);
+ return new_mtu >= MIN_MTU && new_mtu <= MAX_MTU;
}
static int veth_change_mtu(struct net_device *dev, int new_mtu)
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
index f53412368ce1..cab96ad49e60 100644
--- a/drivers/net/via-velocity.c
+++ b/drivers/net/via-velocity.c
@@ -312,13 +312,14 @@ VELOCITY_PARAM(flow_control, "Enable flow control ability");
#define MED_LNK_DEF 0
#define MED_LNK_MIN 0
-#define MED_LNK_MAX 4
+#define MED_LNK_MAX 5
/* speed_duplex[] is used for setting the speed and duplex mode of NIC.
0: indicate autonegotiation for both speed and duplex mode
1: indicate 100Mbps half duplex mode
2: indicate 100Mbps full duplex mode
3: indicate 10Mbps half duplex mode
4: indicate 10Mbps full duplex mode
+ 5: indicate 1000Mbps full duplex mode
Note:
if EEPROM have been set to the force mode, this option is ignored
@@ -617,6 +618,9 @@ static u32 velocity_get_opt_media_mode(struct velocity_info *vptr)
case SPD_DPX_10_HALF:
status = VELOCITY_SPEED_10;
break;
+ case SPD_DPX_1000_FULL:
+ status = VELOCITY_SPEED_1000 | VELOCITY_DUPLEX_FULL;
+ break;
}
vptr->mii_status = status;
return status;
@@ -922,6 +926,7 @@ static int velocity_set_media_mode(struct velocity_info *vptr, u32 mii_status)
/* enable AUTO-NEGO mode */
mii_set_auto_on(vptr);
} else {
+ u16 CTRL1000;
u16 ANAR;
u8 CHIPGCR;
@@ -936,7 +941,11 @@ static int velocity_set_media_mode(struct velocity_info *vptr, u32 mii_status)
BYTE_REG_BITS_ON(CHIPGCR_FCMODE, &regs->CHIPGCR);
CHIPGCR = readb(&regs->CHIPGCR);
- CHIPGCR &= ~CHIPGCR_FCGMII;
+
+ if (mii_status & VELOCITY_SPEED_1000)
+ CHIPGCR |= CHIPGCR_FCGMII;
+ else
+ CHIPGCR &= ~CHIPGCR_FCGMII;
if (mii_status & VELOCITY_DUPLEX_FULL) {
CHIPGCR |= CHIPGCR_FCFDX;
@@ -952,7 +961,13 @@ static int velocity_set_media_mode(struct velocity_info *vptr, u32 mii_status)
BYTE_REG_BITS_ON(TCR_TB2BDIS, &regs->TCR);
}
- MII_REG_BITS_OFF(ADVERTISE_1000FULL | ADVERTISE_1000HALF, MII_CTRL1000, vptr->mac_regs);
+ velocity_mii_read(vptr->mac_regs, MII_CTRL1000, &CTRL1000);
+ CTRL1000 &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
+ if ((mii_status & VELOCITY_SPEED_1000) &&
+ (mii_status & VELOCITY_DUPLEX_FULL)) {
+ CTRL1000 |= ADVERTISE_1000FULL;
+ }
+ velocity_mii_write(vptr->mac_regs, MII_CTRL1000, CTRL1000);
if (!(mii_status & VELOCITY_DUPLEX_FULL) && (mii_status & VELOCITY_SPEED_10))
BYTE_REG_BITS_OFF(TESTCFG_HBDIS, &regs->TESTCFG);
@@ -967,7 +982,7 @@ static int velocity_set_media_mode(struct velocity_info *vptr, u32 mii_status)
ANAR |= ADVERTISE_100FULL;
else
ANAR |= ADVERTISE_100HALF;
- } else {
+ } else if (mii_status & VELOCITY_SPEED_10) {
if (mii_status & VELOCITY_DUPLEX_FULL)
ANAR |= ADVERTISE_10FULL;
else
@@ -1013,6 +1028,9 @@ static void velocity_print_link_status(struct velocity_info *vptr)
} else {
VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: Link forced", vptr->dev->name);
switch (vptr->options.spd_dpx) {
+ case SPD_DPX_1000_FULL:
+ VELOCITY_PRT(MSG_LEVEL_INFO, " speed 1000M bps full duplex\n");
+ break;
case SPD_DPX_100_HALF:
VELOCITY_PRT(MSG_LEVEL_INFO, " speed 100M bps half duplex\n");
break;
@@ -1954,7 +1972,7 @@ static int velocity_tx_srv(struct velocity_info *vptr)
*/
static inline void velocity_rx_csum(struct rx_desc *rd, struct sk_buff *skb)
{
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
if (rd->rdesc1.CSM & CSM_IPKT) {
if (rd->rdesc1.CSM & CSM_IPOK) {
@@ -2574,7 +2592,7 @@ static netdev_tx_t velocity_xmit(struct sk_buff *skb,
td_ptr->tdesc1.cmd = TCPLS_NORMAL + (tdinfo->nskb_dma + 1) * 16;
- if (vptr->vlgrp && vlan_tx_tag_present(skb)) {
+ if (vlan_tx_tag_present(skb)) {
td_ptr->tdesc1.vlan = cpu_to_le16(vlan_tx_tag_get(skb));
td_ptr->tdesc1.TCR |= TCR0_VETAG;
}
@@ -3170,6 +3188,37 @@ static int velocity_get_settings(struct net_device *dev, struct ethtool_cmd *cmd
SUPPORTED_100baseT_Full |
SUPPORTED_1000baseT_Half |
SUPPORTED_1000baseT_Full;
+
+ cmd->advertising = ADVERTISED_TP | ADVERTISED_Autoneg;
+ if (vptr->options.spd_dpx == SPD_DPX_AUTO) {
+ cmd->advertising |=
+ ADVERTISED_10baseT_Half |
+ ADVERTISED_10baseT_Full |
+ ADVERTISED_100baseT_Half |
+ ADVERTISED_100baseT_Full |
+ ADVERTISED_1000baseT_Half |
+ ADVERTISED_1000baseT_Full;
+ } else {
+ switch (vptr->options.spd_dpx) {
+ case SPD_DPX_1000_FULL:
+ cmd->advertising |= ADVERTISED_1000baseT_Full;
+ break;
+ case SPD_DPX_100_HALF:
+ cmd->advertising |= ADVERTISED_100baseT_Half;
+ break;
+ case SPD_DPX_100_FULL:
+ cmd->advertising |= ADVERTISED_100baseT_Full;
+ break;
+ case SPD_DPX_10_HALF:
+ cmd->advertising |= ADVERTISED_10baseT_Half;
+ break;
+ case SPD_DPX_10_FULL:
+ cmd->advertising |= ADVERTISED_10baseT_Full;
+ break;
+ default:
+ break;
+ }
+ }
if (status & VELOCITY_SPEED_1000)
cmd->speed = SPEED_1000;
else if (status & VELOCITY_SPEED_100)
@@ -3200,14 +3249,35 @@ static int velocity_set_settings(struct net_device *dev, struct ethtool_cmd *cmd
curr_status &= (~VELOCITY_LINK_FAIL);
new_status |= ((cmd->autoneg) ? VELOCITY_AUTONEG_ENABLE : 0);
+ new_status |= ((cmd->speed == SPEED_1000) ? VELOCITY_SPEED_1000 : 0);
new_status |= ((cmd->speed == SPEED_100) ? VELOCITY_SPEED_100 : 0);
new_status |= ((cmd->speed == SPEED_10) ? VELOCITY_SPEED_10 : 0);
new_status |= ((cmd->duplex == DUPLEX_FULL) ? VELOCITY_DUPLEX_FULL : 0);
- if ((new_status & VELOCITY_AUTONEG_ENABLE) && (new_status != (curr_status | VELOCITY_AUTONEG_ENABLE)))
+ if ((new_status & VELOCITY_AUTONEG_ENABLE) &&
+ (new_status != (curr_status | VELOCITY_AUTONEG_ENABLE))) {
ret = -EINVAL;
- else
+ } else {
+ enum speed_opt spd_dpx;
+
+ if (new_status & VELOCITY_AUTONEG_ENABLE)
+ spd_dpx = SPD_DPX_AUTO;
+ else if ((new_status & VELOCITY_SPEED_1000) &&
+ (new_status & VELOCITY_DUPLEX_FULL)) {
+ spd_dpx = SPD_DPX_1000_FULL;
+ } else if (new_status & VELOCITY_SPEED_100)
+ spd_dpx = (new_status & VELOCITY_DUPLEX_FULL) ?
+ SPD_DPX_100_FULL : SPD_DPX_100_HALF;
+ else if (new_status & VELOCITY_SPEED_10)
+ spd_dpx = (new_status & VELOCITY_DUPLEX_FULL) ?
+ SPD_DPX_10_FULL : SPD_DPX_10_HALF;
+ else
+ return -EOPNOTSUPP;
+
+ vptr->options.spd_dpx = spd_dpx;
+
velocity_set_media_mode(vptr, new_status);
+ }
return ret;
}
diff --git a/drivers/net/via-velocity.h b/drivers/net/via-velocity.h
index f7b33ae7a703..aa2e69b9ff61 100644
--- a/drivers/net/via-velocity.h
+++ b/drivers/net/via-velocity.h
@@ -848,7 +848,7 @@ enum velocity_owner {
* Bits in CHIPGCR register
*/
-#define CHIPGCR_FCGMII 0x80
+#define CHIPGCR_FCGMII 0x80 /* enable GMII mode */
#define CHIPGCR_FCFDX 0x40
#define CHIPGCR_FCRESV 0x20
#define CHIPGCR_FCMODE 0x10
@@ -1390,7 +1390,8 @@ enum speed_opt {
SPD_DPX_100_HALF = 1,
SPD_DPX_100_FULL = 2,
SPD_DPX_10_HALF = 3,
- SPD_DPX_10_FULL = 4
+ SPD_DPX_10_FULL = 4,
+ SPD_DPX_1000_FULL = 5
};
enum velocity_init_type {
@@ -1504,22 +1505,25 @@ struct velocity_info {
* addresses on this chain then we use the first - multi-IP WOL is not
* supported.
*
- * CHECK ME: locking
*/
static inline int velocity_get_ip(struct velocity_info *vptr)
{
- struct in_device *in_dev = (struct in_device *) vptr->dev->ip_ptr;
+ struct in_device *in_dev;
struct in_ifaddr *ifa;
+ int res = -ENOENT;
+ rcu_read_lock();
+ in_dev = __in_dev_get_rcu(vptr->dev);
if (in_dev != NULL) {
ifa = (struct in_ifaddr *) in_dev->ifa_list;
if (ifa != NULL) {
memcpy(vptr->ip_addr, &ifa->ifa_address, 4);
- return 0;
+ res = 0;
}
}
- return -ENOENT;
+ rcu_read_unlock();
+ return res;
}
/**
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 4598e9d2608f..bb6b67f6b0cc 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -705,19 +705,6 @@ static int virtnet_close(struct net_device *dev)
return 0;
}
-static void virtnet_get_drvinfo(struct net_device *dev,
- struct ethtool_drvinfo *drvinfo)
-{
- struct virtnet_info *vi = netdev_priv(dev);
- struct virtio_device *vdev = vi->vdev;
-
- strncpy(drvinfo->driver, KBUILD_MODNAME, ARRAY_SIZE(drvinfo->driver));
- strncpy(drvinfo->version, "N/A", ARRAY_SIZE(drvinfo->version));
- strncpy(drvinfo->fw_version, "N/A", ARRAY_SIZE(drvinfo->fw_version));
- strncpy(drvinfo->bus_info, dev_name(&vdev->dev),
- ARRAY_SIZE(drvinfo->bus_info));
-}
-
static int virtnet_set_tx_csum(struct net_device *dev, u32 data)
{
struct virtnet_info *vi = netdev_priv(dev);
@@ -830,7 +817,6 @@ static void virtnet_vlan_rx_kill_vid(struct net_device *dev, u16 vid)
}
static const struct ethtool_ops virtnet_ethtool_ops = {
- .get_drvinfo = virtnet_get_drvinfo,
.set_tx_csum = virtnet_set_tx_csum,
.set_sg = ethtool_op_set_sg,
.set_tso = ethtool_op_set_tso,
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index abe0ff53daf3..3f60e0e3097b 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -1042,11 +1042,11 @@ vmxnet3_rx_csum(struct vmxnet3_adapter *adapter,
skb->csum = htons(gdesc->rcd.csum);
skb->ip_summed = CHECKSUM_PARTIAL;
} else {
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
}
}
} else {
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
}
}
@@ -1548,23 +1548,6 @@ vmxnet3_free_irqs(struct vmxnet3_adapter *adapter)
}
}
-
-inline void set_flag_le16(__le16 *data, u16 flag)
-{
- *data = cpu_to_le16(le16_to_cpu(*data) | flag);
-}
-
-inline void set_flag_le64(__le64 *data, u64 flag)
-{
- *data = cpu_to_le64(le64_to_cpu(*data) | flag);
-}
-
-inline void reset_flag_le64(__le64 *data, u64 flag)
-{
- *data = cpu_to_le64(le64_to_cpu(*data) & ~flag);
-}
-
-
static void
vmxnet3_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
{
@@ -1634,7 +1617,7 @@ vmxnet3_restore_vlan(struct vmxnet3_adapter *adapter)
u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable;
bool activeVlan = false;
- for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
+ for (vid = 0; vid < VLAN_N_VID; vid++) {
if (vlan_group_get_device(adapter->vlan_grp, vid)) {
VMXNET3_SET_VFTABLE_ENTRY(vfTable, vid);
activeVlan = true;
diff --git a/drivers/net/vmxnet3/vmxnet3_int.h b/drivers/net/vmxnet3/vmxnet3_int.h
index 2121c735cabd..c88ea5cbba0d 100644
--- a/drivers/net/vmxnet3/vmxnet3_int.h
+++ b/drivers/net/vmxnet3/vmxnet3_int.h
@@ -353,9 +353,20 @@ struct vmxnet3_adapter {
#define VMXNET3_MAX_ETH_HDR_SIZE 22
#define VMXNET3_MAX_SKB_BUF_SIZE (3*1024)
-void set_flag_le16(__le16 *data, u16 flag);
-void set_flag_le64(__le64 *data, u64 flag);
-void reset_flag_le64(__le64 *data, u64 flag);
+static inline void set_flag_le16(__le16 *data, u16 flag)
+{
+ *data = cpu_to_le16(le16_to_cpu(*data) | flag);
+}
+
+static inline void set_flag_le64(__le64 *data, u64 flag)
+{
+ *data = cpu_to_le64(le64_to_cpu(*data) | flag);
+}
+
+static inline void reset_flag_le64(__le64 *data, u64 flag)
+{
+ *data = cpu_to_le64(le64_to_cpu(*data) & ~flag);
+}
int
vmxnet3_quiesce_dev(struct vmxnet3_adapter *adapter);
diff --git a/drivers/net/vxge/vxge-main.c b/drivers/net/vxge/vxge-main.c
index c7c5605b3728..a69542ecb68d 100644
--- a/drivers/net/vxge/vxge-main.c
+++ b/drivers/net/vxge/vxge-main.c
@@ -501,7 +501,7 @@ vxge_rx_1b_compl(struct __vxge_hw_ring *ringh, void *dtr,
ext_info.l4_cksum == VXGE_HW_L4_CKSUM_OK)
skb->ip_summed = CHECKSUM_UNNECESSARY;
else
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
vxge_rx_complete(ring, skb, ext_info.vlan,
pkt_length, &ext_info);
@@ -822,7 +822,7 @@ vxge_xmit(struct sk_buff *skb, struct net_device *dev)
dev->name, __func__, __LINE__,
fifo_hw, dtr, dtr_priv);
- if (vdev->vlgrp && vlan_tx_tag_present(skb)) {
+ if (vlan_tx_tag_present(skb)) {
u16 vlan_tag = vlan_tx_tag_get(skb);
vxge_hw_fifo_txdl_vlan_set(dtr, vlan_tag);
}
@@ -1862,7 +1862,7 @@ enum vxge_hw_status vxge_restore_vpath_vid_table(struct vxge_vpath *vpath)
if (vdev->vlgrp && vpath->is_open) {
- for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
+ for (vid = 0; vid < VLAN_N_VID; vid++) {
if (!vlan_group_get_device(vdev->vlgrp, vid))
continue;
/* Add these vlan to the vid table */
@@ -2159,8 +2159,8 @@ start:
/* Alarm MSIX Vectors count */
vdev->intr_cnt++;
- vdev->entries = kzalloc(vdev->intr_cnt * sizeof(struct msix_entry),
- GFP_KERNEL);
+ vdev->entries = kcalloc(vdev->intr_cnt, sizeof(struct msix_entry),
+ GFP_KERNEL);
if (!vdev->entries) {
vxge_debug_init(VXGE_ERR,
"%s: memory allocation failed",
@@ -2169,9 +2169,9 @@ start:
goto alloc_entries_failed;
}
- vdev->vxge_entries =
- kzalloc(vdev->intr_cnt * sizeof(struct vxge_msix_entry),
- GFP_KERNEL);
+ vdev->vxge_entries = kcalloc(vdev->intr_cnt,
+ sizeof(struct vxge_msix_entry),
+ GFP_KERNEL);
if (!vdev->vxge_entries) {
vxge_debug_init(VXGE_ERR, "%s: memory allocation failed",
VXGE_DRIVER_NAME);
@@ -2914,26 +2914,18 @@ static int vxge_change_mtu(struct net_device *dev, int new_mtu)
}
/**
- * vxge_get_stats
+ * vxge_get_stats64
* @dev: pointer to the device structure
+ * @stats: pointer to struct rtnl_link_stats64
*
- * Updates the device statistics structure. This function updates the device
- * statistics structure in the net_device structure and returns a pointer
- * to the same.
*/
-static struct net_device_stats *
-vxge_get_stats(struct net_device *dev)
+static struct rtnl_link_stats64 *
+vxge_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *net_stats)
{
- struct vxgedev *vdev;
- struct net_device_stats *net_stats;
+ struct vxgedev *vdev = netdev_priv(dev);
int k;
- vdev = netdev_priv(dev);
-
- net_stats = &vdev->stats.net_stats;
-
- memset(net_stats, 0, sizeof(struct net_device_stats));
-
+ /* net_stats already zeroed by caller */
for (k = 0; k < vdev->no_of_vpath; k++) {
net_stats->rx_packets += vdev->vpaths[k].ring.stats.rx_frms;
net_stats->rx_bytes += vdev->vpaths[k].ring.stats.rx_bytes;
@@ -3102,7 +3094,7 @@ vxge_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
static const struct net_device_ops vxge_netdev_ops = {
.ndo_open = vxge_open,
.ndo_stop = vxge_close,
- .ndo_get_stats = vxge_get_stats,
+ .ndo_get_stats64 = vxge_get_stats64,
.ndo_start_xmit = vxge_xmit,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_multicast_list = vxge_set_multicast,
diff --git a/drivers/net/vxge/vxge-main.h b/drivers/net/vxge/vxge-main.h
index 2e3b064b8e4b..d4be07eaacd7 100644
--- a/drivers/net/vxge/vxge-main.h
+++ b/drivers/net/vxge/vxge-main.h
@@ -172,7 +172,6 @@ struct vxge_msix_entry {
struct vxge_sw_stats {
/* Network Stats (interface stats) */
- struct net_device_stats net_stats;
/* Tx */
u64 tx_frms;
diff --git a/drivers/net/wan/c101.c b/drivers/net/wan/c101.c
index 0bd898c94759..4ac85a09c5a6 100644
--- a/drivers/net/wan/c101.c
+++ b/drivers/net/wan/c101.c
@@ -264,7 +264,7 @@ static int c101_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
new_line.clock_type != CLOCK_TXFROMRX &&
new_line.clock_type != CLOCK_INT &&
new_line.clock_type != CLOCK_TXINT)
- return -EINVAL; /* No such clock setting */
+ return -EINVAL; /* No such clock setting */
if (new_line.loopback != 0 && new_line.loopback != 1)
return -EINVAL;
diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
index 04c6cd4333f1..10bafd59f9c3 100644
--- a/drivers/net/wan/cosa.c
+++ b/drivers/net/wan/cosa.c
@@ -575,7 +575,7 @@ static int cosa_probe(int base, int irq, int dma)
/* Initialize the chardev data structures */
mutex_init(&chan->rlock);
- init_MUTEX(&chan->wsem);
+ sema_init(&chan->wsem, 1);
/* Register the network interface */
if (!(chan->netdev = alloc_hdlcdev(chan))) {
diff --git a/drivers/net/wan/cycx_drv.c b/drivers/net/wan/cycx_drv.c
index a5ddc6c8963e..164c3624ba89 100644
--- a/drivers/net/wan/cycx_drv.c
+++ b/drivers/net/wan/cycx_drv.c
@@ -73,7 +73,7 @@ static int reset_cyc2x(void __iomem *addr);
static int detect_cyc2x(void __iomem *addr);
/* Miscellaneous functions */
-static int get_option_index(long *optlist, long optval);
+static int get_option_index(const long *optlist, long optval);
static u16 checksum(u8 *buf, u32 len);
#define wait_cyc(addr) cycx_exec(addr + CMD_OFFSET)
@@ -81,23 +81,23 @@ static u16 checksum(u8 *buf, u32 len);
/* Global Data */
/* private data */
-static char modname[] = "cycx_drv";
-static char fullname[] = "Cyclom 2X Support Module";
-static char copyright[] = "(c) 1998-2003 Arnaldo Carvalho de Melo "
+static const char modname[] = "cycx_drv";
+static const char fullname[] = "Cyclom 2X Support Module";
+static const char copyright[] = "(c) 1998-2003 Arnaldo Carvalho de Melo "
"<acme@conectiva.com.br>";
/* Hardware configuration options.
* These are arrays of configuration options used by verification routines.
* The first element of each array is its size (i.e. number of options).
*/
-static long cyc2x_dpmbase_options[] = {
+static const long cyc2x_dpmbase_options[] = {
20,
0xA0000, 0xA4000, 0xA8000, 0xAC000, 0xB0000, 0xB4000, 0xB8000,
0xBC000, 0xC0000, 0xC4000, 0xC8000, 0xCC000, 0xD0000, 0xD4000,
0xD8000, 0xDC000, 0xE0000, 0xE4000, 0xE8000, 0xEC000
};
-static long cycx_2x_irq_options[] = { 7, 3, 5, 9, 10, 11, 12, 15 };
+static const long cycx_2x_irq_options[] = { 7, 3, 5, 9, 10, 11, 12, 15 };
/* Kernel Loadable Module Entry Points */
/* Module 'insert' entry point.
@@ -529,7 +529,7 @@ static int detect_cyc2x(void __iomem *addr)
/* Miscellaneous */
/* Get option's index into the options list.
* Return option's index (1 .. N) or zero if option is invalid. */
-static int get_option_index(long *optlist, long optval)
+static int get_option_index(const long *optlist, long optval)
{
int i = 1;
diff --git a/drivers/net/wan/cycx_main.c b/drivers/net/wan/cycx_main.c
index a0e8611ad8e8..859dba9b972e 100644
--- a/drivers/net/wan/cycx_main.c
+++ b/drivers/net/wan/cycx_main.c
@@ -81,9 +81,9 @@ static irqreturn_t cycx_isr(int irq, void *dev_id);
*/
/* private data */
-static char cycx_drvname[] = "cyclomx";
-static char cycx_fullname[] = "CYCLOM 2X(tm) Sync Card Driver";
-static char cycx_copyright[] = "(c) 1998-2003 Arnaldo Carvalho de Melo "
+static const char cycx_drvname[] = "cyclomx";
+static const char cycx_fullname[] = "CYCLOM 2X(tm) Sync Card Driver";
+static const char cycx_copyright[] = "(c) 1998-2003 Arnaldo Carvalho de Melo "
"<acme@conectiva.com.br>";
static int cycx_ncards = CONFIG_CYCX_CARDS;
static struct cycx_device *cycx_card_array; /* adapter data space */
diff --git a/drivers/net/wan/dlci.c b/drivers/net/wan/dlci.c
index 421d0715310e..1481a446fefb 100644
--- a/drivers/net/wan/dlci.c
+++ b/drivers/net/wan/dlci.c
@@ -97,11 +97,11 @@ static int dlci_header(struct sk_buff *skb, struct net_device *dev,
dest = skb_push(skb, hlen);
if (!dest)
- return(0);
+ return 0;
memcpy(dest, &hdr, hlen);
- return(hlen);
+ return hlen;
}
static void dlci_receive(struct sk_buff *skb, struct net_device *dev)
@@ -211,14 +211,14 @@ static int dlci_config(struct net_device *dev, struct dlci_conf __user *conf, in
if (copy_from_user(&config, conf, sizeof(struct dlci_conf)))
return -EFAULT;
if (config.flags & ~DLCI_VALID_FLAGS)
- return(-EINVAL);
+ return -EINVAL;
memcpy(&dlp->config, &config, sizeof(struct dlci_conf));
dlp->configured = 1;
}
err = (*flp->dlci_conf)(dlp->slave, dev, get);
if (err)
- return(err);
+ return err;
if (get)
{
@@ -226,7 +226,7 @@ static int dlci_config(struct net_device *dev, struct dlci_conf __user *conf, in
return -EFAULT;
}
- return(0);
+ return 0;
}
static int dlci_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
@@ -234,7 +234,7 @@ static int dlci_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
struct dlci_local *dlp;
if (!capable(CAP_NET_ADMIN))
- return(-EPERM);
+ return -EPERM;
dlp = netdev_priv(dev);
@@ -242,7 +242,7 @@ static int dlci_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
case DLCI_GET_SLAVE:
if (!*(short *)(dev->dev_addr))
- return(-EINVAL);
+ return -EINVAL;
strncpy(ifr->ifr_slave, dlp->slave->name, sizeof(ifr->ifr_slave));
break;
@@ -250,15 +250,15 @@ static int dlci_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
case DLCI_GET_CONF:
case DLCI_SET_CONF:
if (!*(short *)(dev->dev_addr))
- return(-EINVAL);
+ return -EINVAL;
- return(dlci_config(dev, ifr->ifr_data, cmd == DLCI_GET_CONF));
+ return dlci_config(dev, ifr->ifr_data, cmd == DLCI_GET_CONF);
break;
default:
- return(-EOPNOTSUPP);
+ return -EOPNOTSUPP;
}
- return(0);
+ return 0;
}
static int dlci_change_mtu(struct net_device *dev, int new_mtu)
@@ -277,15 +277,15 @@ static int dlci_open(struct net_device *dev)
dlp = netdev_priv(dev);
if (!*(short *)(dev->dev_addr))
- return(-EINVAL);
+ return -EINVAL;
if (!netif_running(dlp->slave))
- return(-ENOTCONN);
+ return -ENOTCONN;
flp = netdev_priv(dlp->slave);
err = (*flp->activate)(dlp->slave, dev);
if (err)
- return(err);
+ return err;
netif_start_queue(dev);
@@ -365,14 +365,14 @@ static int dlci_add(struct dlci_add *dlci)
list_add(&dlp->list, &dlci_devs);
rtnl_unlock();
- return(0);
+ return 0;
err2:
rtnl_unlock();
free_netdev(master);
err1:
dev_put(slave);
- return(err);
+ return err;
}
static int dlci_del(struct dlci_add *dlci)
@@ -385,10 +385,10 @@ static int dlci_del(struct dlci_add *dlci)
/* validate slave device */
master = __dev_get_by_name(&init_net, dlci->devname);
if (!master)
- return(-ENODEV);
+ return -ENODEV;
if (netif_running(master)) {
- return(-EBUSY);
+ return -EBUSY;
}
dlp = netdev_priv(master);
@@ -406,7 +406,7 @@ static int dlci_del(struct dlci_add *dlci)
}
rtnl_unlock();
- return(err);
+ return err;
}
static int dlci_ioctl(unsigned int cmd, void __user *arg)
@@ -415,7 +415,7 @@ static int dlci_ioctl(unsigned int cmd, void __user *arg)
int err;
if (!capable(CAP_NET_ADMIN))
- return(-EPERM);
+ return -EPERM;
if (copy_from_user(&add, arg, sizeof(struct dlci_add)))
return -EFAULT;
@@ -438,7 +438,7 @@ static int dlci_ioctl(unsigned int cmd, void __user *arg)
err = -EINVAL;
}
- return(err);
+ return err;
}
static const struct header_ops dlci_header_ops = {
diff --git a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c
index b38ffa149aba..b1e5e5b69c2a 100644
--- a/drivers/net/wan/hdlc_cisco.c
+++ b/drivers/net/wan/hdlc_cisco.c
@@ -191,7 +191,8 @@ static int cisco_rx(struct sk_buff *skb)
switch (ntohl (cisco_data->type)) {
case CISCO_ADDR_REQ: /* Stolen from syncppp.c :-) */
- in_dev = dev->ip_ptr;
+ rcu_read_lock();
+ in_dev = __in_dev_get_rcu(dev);
addr = 0;
mask = ~cpu_to_be32(0); /* is the mask correct? */
@@ -211,6 +212,7 @@ static int cisco_rx(struct sk_buff *skb)
cisco_keepalive_send(dev, CISCO_ADDR_REPLY,
addr, mask);
}
+ rcu_read_unlock();
dev_kfree_skb_any(skb);
return NET_RX_SUCCESS;
diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c
index 4d4dc38c7290..7f5bb913c8b9 100644
--- a/drivers/net/wan/lapbether.c
+++ b/drivers/net/wan/lapbether.c
@@ -46,7 +46,7 @@
#include <net/x25device.h>
-static char bcast_addr[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+static const u8 bcast_addr[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
/* If this number is made larger, check that the temporary string buffer
* in lapbeth_new_device is large enough to store the probe device name.*/
diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c
index e2c6f7f4f51c..70feb84df670 100644
--- a/drivers/net/wan/lmc/lmc_main.c
+++ b/drivers/net/wan/lmc/lmc_main.c
@@ -1022,7 +1022,7 @@ static int lmc_open(struct net_device *dev)
if (sc->lmc_ok){
lmc_trace(dev, "lmc_open lmc_ok out");
- return (0);
+ return 0;
}
lmc_softreset (sc);
@@ -1105,12 +1105,12 @@ static int lmc_open(struct net_device *dev)
init_timer (&sc->timer);
sc->timer.expires = jiffies + HZ;
sc->timer.data = (unsigned long) dev;
- sc->timer.function = &lmc_watchdog;
+ sc->timer.function = lmc_watchdog;
add_timer (&sc->timer);
lmc_trace(dev, "lmc_open out");
- return (0);
+ return 0;
}
/* Total reset to compensate for the AdTran DSU doing bad things
diff --git a/drivers/net/wan/n2.c b/drivers/net/wan/n2.c
index 5394b51bdb2f..17d408fe693f 100644
--- a/drivers/net/wan/n2.c
+++ b/drivers/net/wan/n2.c
@@ -282,7 +282,7 @@ static int n2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
new_line.clock_type != CLOCK_TXFROMRX &&
new_line.clock_type != CLOCK_INT &&
new_line.clock_type != CLOCK_TXINT)
- return -EINVAL; /* No such clock setting */
+ return -EINVAL; /* No such clock setting */
if (new_line.loopback != 0 && new_line.loopback != 1)
return -EINVAL;
@@ -379,14 +379,14 @@ static int __init n2_run(unsigned long io, unsigned long irq,
if (request_irq(irq, sca_intr, 0, devname, card)) {
printk(KERN_ERR "n2: could not allocate IRQ\n");
n2_destroy_card(card);
- return(-EBUSY);
+ return -EBUSY;
}
card->irq = irq;
if (!request_mem_region(winbase, USE_WINDOWSIZE, devname)) {
printk(KERN_ERR "n2: could not request RAM window\n");
n2_destroy_card(card);
- return(-EBUSY);
+ return -EBUSY;
}
card->phy_winbase = winbase;
card->winbase = ioremap(winbase, USE_WINDOWSIZE);
diff --git a/drivers/net/wan/pc300_drv.c b/drivers/net/wan/pc300_drv.c
index c6aa66e5b52f..f875cfae3093 100644
--- a/drivers/net/wan/pc300_drv.c
+++ b/drivers/net/wan/pc300_drv.c
@@ -1,5 +1,5 @@
#define USE_PCI_CLOCK
-static char rcsid[] =
+static const char rcsid[] =
"Revision: 3.4.5 Date: 2002/03/07 ";
/*
@@ -451,11 +451,11 @@ static int dma_get_rx_frame_size(pc300_t * card, int ch)
if ((status & DST_EOM) || (first_bd == card->chan[ch].rx_last_bd)) {
/* Return the size of a good frame or incomplete bad frame
* (dma_buf_read will clean the buffer descriptors in this case). */
- return (rcvd);
+ return rcvd;
}
ptdescr = (card->hw.rambase + cpc_readl(&ptdescr->next));
}
- return (-1);
+ return -1;
}
/*
@@ -557,7 +557,7 @@ static int dma_buf_read(pc300_t * card, int ch, struct sk_buff *skb)
cpc_writel(card->hw.scabase + DRX_REG(EDAL, ch),
RX_BD_ADDR(ch, chan->rx_last_bd));
}
- return (rcvd);
+ return rcvd;
}
static void tx_dma_stop(pc300_t * card, int ch)
@@ -1733,7 +1733,7 @@ static u16 falc_pattern_test_error(pc300_t * card, int ch)
pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
falc_t *pfalc = (falc_t *) & chan->falc;
- return (pfalc->bec);
+ return pfalc->bec;
}
/**********************************/
@@ -2819,7 +2819,7 @@ static int clock_rate_calc(u32 rate, u32 clock, int *br_io)
*br_io = 0;
if (rate == 0)
- return (0);
+ return 0;
for (br = 0, br_pwr = 1; br <= 9; br++, br_pwr <<= 1) {
if ((tc = clock / br_pwr / rate) <= 0xff) {
@@ -2832,11 +2832,11 @@ static int clock_rate_calc(u32 rate, u32 clock, int *br_io)
error = ((rate - (clock / br_pwr / rate)) / rate) * 1000;
/* Errors bigger than +/- 1% won't be tolerated */
if (error < -10 || error > 10)
- return (-1);
+ return -1;
else
- return (tc);
+ return tc;
} else {
- return (-1);
+ return -1;
}
}
@@ -3207,7 +3207,7 @@ static u32 detect_ram(pc300_t * card)
break;
}
}
- return (i);
+ return i;
}
static void plx_init(pc300_t * card)
diff --git a/drivers/net/wan/pc300_tty.c b/drivers/net/wan/pc300_tty.c
index 4293889e287e..515d9b8af01e 100644
--- a/drivers/net/wan/pc300_tty.c
+++ b/drivers/net/wan/pc300_tty.c
@@ -540,7 +540,7 @@ static int cpc_tty_chars_in_buffer(struct tty_struct *tty)
return -ENODEV;
}
- return(0);
+ return 0;
}
static int pc300_tiocmset(struct tty_struct *tty, struct file *file,
diff --git a/drivers/net/wan/pci200syn.c b/drivers/net/wan/pci200syn.c
index e2cff64a446a..fd7375955e41 100644
--- a/drivers/net/wan/pci200syn.c
+++ b/drivers/net/wan/pci200syn.c
@@ -220,7 +220,7 @@ static int pci200_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
new_line.clock_type != CLOCK_TXFROMRX &&
new_line.clock_type != CLOCK_INT &&
new_line.clock_type != CLOCK_TXINT)
- return -EINVAL; /* No such clock setting */
+ return -EINVAL; /* No such clock setting */
if (new_line.loopback != 0 && new_line.loopback != 1)
return -EINVAL;
diff --git a/drivers/net/wan/sdla.c b/drivers/net/wan/sdla.c
index f4125da2762f..3f4e2b5684db 100644
--- a/drivers/net/wan/sdla.c
+++ b/drivers/net/wan/sdla.c
@@ -178,7 +178,7 @@ static char sdla_byte(struct net_device *dev, int addr)
byte = *temp;
spin_unlock_irqrestore(&sdla_lock, flags);
- return(byte);
+ return byte;
}
static void sdla_stop(struct net_device *dev)
@@ -267,7 +267,7 @@ static int sdla_z80_poll(struct net_device *dev, int z80_addr, int jiffs, char r
resp = *temp;
}
}
- return(time_before(jiffies, done) ? jiffies - start : -1);
+ return time_before(jiffies, done) ? jiffies - start : -1;
}
/* constants for Z80 CPU speed */
@@ -283,13 +283,13 @@ static int sdla_cpuspeed(struct net_device *dev, struct ifreq *ifr)
sdla_start(dev);
if (sdla_z80_poll(dev, 0, 3*HZ, Z80_READY, 0) < 0)
- return(-EIO);
+ return -EIO;
data = LOADER_READY;
sdla_write(dev, 0, &data, 1);
if ((jiffs = sdla_z80_poll(dev, 0, 8*HZ, Z80_SCC_OK, Z80_SCC_BAD)) < 0)
- return(-EIO);
+ return -EIO;
sdla_stop(dev);
sdla_read(dev, 0, &data, 1);
@@ -297,11 +297,11 @@ static int sdla_cpuspeed(struct net_device *dev, struct ifreq *ifr)
if (data == Z80_SCC_BAD)
{
printk("%s: SCC bad\n", dev->name);
- return(-EIO);
+ return -EIO;
}
if (data != Z80_SCC_OK)
- return(-EINVAL);
+ return -EINVAL;
if (jiffs < 165)
ifr->ifr_mtu = SDLA_CPU_16M;
@@ -316,7 +316,7 @@ static int sdla_cpuspeed(struct net_device *dev, struct ifreq *ifr)
else
ifr->ifr_mtu = SDLA_CPU_3M;
- return(0);
+ return 0;
}
/************************************************
@@ -493,7 +493,7 @@ static int sdla_cmd(struct net_device *dev, int cmd, short dlci, short flags,
if (ret != SDLA_RET_OK)
sdla_errors(dev, cmd, dlci, ret, len, &status);
- return(ret);
+ return ret;
}
/***********************************************
@@ -516,14 +516,14 @@ static int sdla_activate(struct net_device *slave, struct net_device *master)
break;
if (i == CONFIG_DLCI_MAX)
- return(-ENODEV);
+ return -ENODEV;
flp->dlci[i] = abs(flp->dlci[i]);
if (netif_running(slave) && (flp->config.station == FRAD_STATION_NODE))
sdla_cmd(slave, SDLA_ACTIVATE_DLCI, 0, 0, &flp->dlci[i], sizeof(short), NULL, NULL);
- return(0);
+ return 0;
}
static int sdla_deactivate(struct net_device *slave, struct net_device *master)
@@ -538,14 +538,14 @@ static int sdla_deactivate(struct net_device *slave, struct net_device *master)
break;
if (i == CONFIG_DLCI_MAX)
- return(-ENODEV);
+ return -ENODEV;
flp->dlci[i] = -abs(flp->dlci[i]);
if (netif_running(slave) && (flp->config.station == FRAD_STATION_NODE))
sdla_cmd(slave, SDLA_DEACTIVATE_DLCI, 0, 0, &flp->dlci[i], sizeof(short), NULL, NULL);
- return(0);
+ return 0;
}
static int sdla_assoc(struct net_device *slave, struct net_device *master)
@@ -554,7 +554,7 @@ static int sdla_assoc(struct net_device *slave, struct net_device *master)
int i;
if (master->type != ARPHRD_DLCI)
- return(-EINVAL);
+ return -EINVAL;
flp = netdev_priv(slave);
@@ -563,11 +563,11 @@ static int sdla_assoc(struct net_device *slave, struct net_device *master)
if (!flp->master[i])
break;
if (abs(flp->dlci[i]) == *(short *)(master->dev_addr))
- return(-EADDRINUSE);
+ return -EADDRINUSE;
}
if (i == CONFIG_DLCI_MAX)
- return(-EMLINK); /* #### Alan: Comments on this ?? */
+ return -EMLINK; /* #### Alan: Comments on this ?? */
flp->master[i] = master;
@@ -581,7 +581,7 @@ static int sdla_assoc(struct net_device *slave, struct net_device *master)
sdla_cmd(slave, SDLA_ADD_DLCI, 0, 0, master->dev_addr, sizeof(short), NULL, NULL);
}
- return(0);
+ return 0;
}
static int sdla_deassoc(struct net_device *slave, struct net_device *master)
@@ -596,7 +596,7 @@ static int sdla_deassoc(struct net_device *slave, struct net_device *master)
break;
if (i == CONFIG_DLCI_MAX)
- return(-ENODEV);
+ return -ENODEV;
flp->master[i] = NULL;
flp->dlci[i] = 0;
@@ -609,7 +609,7 @@ static int sdla_deassoc(struct net_device *slave, struct net_device *master)
sdla_cmd(slave, SDLA_DELETE_DLCI, 0, 0, master->dev_addr, sizeof(short), NULL, NULL);
}
- return(0);
+ return 0;
}
static int sdla_dlci_conf(struct net_device *slave, struct net_device *master, int get)
@@ -626,7 +626,7 @@ static int sdla_dlci_conf(struct net_device *slave, struct net_device *master, i
break;
if (i == CONFIG_DLCI_MAX)
- return(-ENODEV);
+ return -ENODEV;
dlp = netdev_priv(master);
@@ -641,7 +641,7 @@ static int sdla_dlci_conf(struct net_device *slave, struct net_device *master, i
&dlp->config, sizeof(struct dlci_conf) - 4 * sizeof(short), NULL, NULL);
}
- return(ret == SDLA_RET_OK ? 0 : -EIO);
+ return ret == SDLA_RET_OK ? 0 : -EIO;
}
/**************************
@@ -986,7 +986,7 @@ static int sdla_close(struct net_device *dev)
netif_stop_queue(dev);
- return(0);
+ return 0;
}
struct conf_data {
@@ -1006,10 +1006,10 @@ static int sdla_open(struct net_device *dev)
flp = netdev_priv(dev);
if (!flp->initialized)
- return(-EPERM);
+ return -EPERM;
if (!flp->configured)
- return(-EPERM);
+ return -EPERM;
/* time to send in the configuration */
len = 0;
@@ -1087,7 +1087,7 @@ static int sdla_open(struct net_device *dev)
netif_start_queue(dev);
- return(0);
+ return 0;
}
static int sdla_config(struct net_device *dev, struct frad_conf __user *conf, int get)
@@ -1098,48 +1098,48 @@ static int sdla_config(struct net_device *dev, struct frad_conf __user *conf, in
short size;
if (dev->type == 0xFFFF)
- return(-EUNATCH);
+ return -EUNATCH;
flp = netdev_priv(dev);
if (!get)
{
if (netif_running(dev))
- return(-EBUSY);
+ return -EBUSY;
if(copy_from_user(&data.config, conf, sizeof(struct frad_conf)))
return -EFAULT;
if (data.config.station & ~FRAD_STATION_NODE)
- return(-EINVAL);
+ return -EINVAL;
if (data.config.flags & ~FRAD_VALID_FLAGS)
- return(-EINVAL);
+ return -EINVAL;
if ((data.config.kbaud < 0) ||
((data.config.kbaud > 128) && (flp->type != SDLA_S508)))
- return(-EINVAL);
+ return -EINVAL;
if (data.config.clocking & ~(FRAD_CLOCK_INT | SDLA_S508_PORT_RS232))
- return(-EINVAL);
+ return -EINVAL;
if ((data.config.mtu < 0) || (data.config.mtu > SDLA_MAX_MTU))
- return(-EINVAL);
+ return -EINVAL;
if ((data.config.T391 < 5) || (data.config.T391 > 30))
- return(-EINVAL);
+ return -EINVAL;
if ((data.config.T392 < 5) || (data.config.T392 > 30))
- return(-EINVAL);
+ return -EINVAL;
if ((data.config.N391 < 1) || (data.config.N391 > 255))
- return(-EINVAL);
+ return -EINVAL;
if ((data.config.N392 < 1) || (data.config.N392 > 10))
- return(-EINVAL);
+ return -EINVAL;
if ((data.config.N393 < 1) || (data.config.N393 > 10))
- return(-EINVAL);
+ return -EINVAL;
memcpy(&flp->config, &data.config, sizeof(struct frad_conf));
flp->config.flags |= SDLA_DIRECT_RECV;
@@ -1171,7 +1171,7 @@ static int sdla_config(struct net_device *dev, struct frad_conf __user *conf, in
{
size = sizeof(data);
if (sdla_cmd(dev, SDLA_READ_DLCI_CONFIGURATION, 0, 0, NULL, 0, &data, &size) != SDLA_RET_OK)
- return(-EIO);
+ return -EIO;
}
else
if (flp->configured)
@@ -1185,7 +1185,7 @@ static int sdla_config(struct net_device *dev, struct frad_conf __user *conf, in
return copy_to_user(conf, &data.config, sizeof(struct frad_conf))?-EFAULT:0;
}
- return(0);
+ return 0;
}
static int sdla_xfer(struct net_device *dev, struct sdla_mem __user *info, int read)
@@ -1200,7 +1200,7 @@ static int sdla_xfer(struct net_device *dev, struct sdla_mem __user *info, int r
{
temp = kzalloc(mem.len, GFP_KERNEL);
if (!temp)
- return(-ENOMEM);
+ return -ENOMEM;
sdla_read(dev, mem.addr, temp, mem.len);
if(copy_to_user(mem.data, temp, mem.len))
{
@@ -1217,7 +1217,7 @@ static int sdla_xfer(struct net_device *dev, struct sdla_mem __user *info, int r
sdla_write(dev, mem.addr, temp, mem.len);
kfree(temp);
}
- return(0);
+ return 0;
}
static int sdla_reconfig(struct net_device *dev)
@@ -1241,7 +1241,7 @@ static int sdla_reconfig(struct net_device *dev)
sdla_cmd(dev, SDLA_SET_DLCI_CONFIGURATION, 0, 0, &data, len, NULL, NULL);
sdla_cmd(dev, SDLA_ENABLE_COMMUNICATIONS, 0, 0, NULL, 0, NULL, NULL);
- return(0);
+ return 0;
}
static int sdla_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
@@ -1254,20 +1254,20 @@ static int sdla_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
flp = netdev_priv(dev);
if (!flp->initialized)
- return(-EINVAL);
+ return -EINVAL;
switch (cmd)
{
case FRAD_GET_CONF:
case FRAD_SET_CONF:
- return(sdla_config(dev, ifr->ifr_data, cmd == FRAD_GET_CONF));
+ return sdla_config(dev, ifr->ifr_data, cmd == FRAD_GET_CONF);
case SDLA_IDENTIFY:
ifr->ifr_flags = flp->type;
break;
case SDLA_CPUSPEED:
- return(sdla_cpuspeed(dev, ifr));
+ return sdla_cpuspeed(dev, ifr);
/* ==========================================================
NOTE: This is rather a useless action right now, as the
@@ -1277,7 +1277,7 @@ NOTE: This is rather a useless action right now, as the
============================================================*/
case SDLA_PROTOCOL:
if (flp->configured)
- return(-EALREADY);
+ return -EALREADY;
switch (ifr->ifr_flags)
{
@@ -1285,7 +1285,7 @@ NOTE: This is rather a useless action right now, as the
dev->type = ifr->ifr_flags;
break;
default:
- return(-ENOPROTOOPT);
+ return -ENOPROTOOPT;
}
break;
@@ -1297,7 +1297,7 @@ NOTE: This is rather a useless action right now, as the
case SDLA_READMEM:
if(!capable(CAP_SYS_RAWIO))
return -EPERM;
- return(sdla_xfer(dev, ifr->ifr_data, cmd == SDLA_READMEM));
+ return sdla_xfer(dev, ifr->ifr_data, cmd == SDLA_READMEM);
case SDLA_START:
sdla_start(dev);
@@ -1308,9 +1308,9 @@ NOTE: This is rather a useless action right now, as the
break;
default:
- return(-EOPNOTSUPP);
+ return -EOPNOTSUPP;
}
- return(0);
+ return 0;
}
static int sdla_change_mtu(struct net_device *dev, int new_mtu)
@@ -1320,10 +1320,10 @@ static int sdla_change_mtu(struct net_device *dev, int new_mtu)
flp = netdev_priv(dev);
if (netif_running(dev))
- return(-EBUSY);
+ return -EBUSY;
/* for now, you can't change the MTU! */
- return(-EOPNOTSUPP);
+ return -EOPNOTSUPP;
}
static int sdla_set_config(struct net_device *dev, struct ifmap *map)
@@ -1337,18 +1337,18 @@ static int sdla_set_config(struct net_device *dev, struct ifmap *map)
flp = netdev_priv(dev);
if (flp->initialized)
- return(-EINVAL);
+ return -EINVAL;
for(i=0; i < ARRAY_SIZE(valid_port); i++)
if (valid_port[i] == map->base_addr)
break;
if (i == ARRAY_SIZE(valid_port))
- return(-EINVAL);
+ return -EINVAL;
if (!request_region(map->base_addr, SDLA_IO_EXTENTS, dev->name)){
printk(KERN_WARNING "SDLA: io-port 0x%04lx in use\n", dev->base_addr);
- return(-EINVAL);
+ return -EINVAL;
}
base = map->base_addr;
diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c
index e47f5a986b1c..d81ad8397885 100644
--- a/drivers/net/wan/x25_asy.c
+++ b/drivers/net/wan/x25_asy.c
@@ -648,7 +648,7 @@ static int x25_asy_esc(unsigned char *s, unsigned char *d, int len)
}
}
*ptr++ = X25_END;
- return (ptr - d);
+ return ptr - d;
}
static void x25_asy_unesc(struct x25_asy *sl, unsigned char s)
diff --git a/drivers/net/wan/z85230.c b/drivers/net/wan/z85230.c
index fbf5e843d48c..93956861ea21 100644
--- a/drivers/net/wan/z85230.c
+++ b/drivers/net/wan/z85230.c
@@ -766,7 +766,7 @@ irqreturn_t z8530_interrupt(int irq, void *dev_id)
EXPORT_SYMBOL(z8530_interrupt);
-static char reg_init[16]=
+static const u8 reg_init[16]=
{
0,0,0,0,
0,0,0,0,
@@ -1206,7 +1206,7 @@ EXPORT_SYMBOL(z8530_sync_txdma_close);
* it exists...
*/
-static char *z8530_type_name[]={
+static const char *z8530_type_name[]={
"Z8530",
"Z85C30",
"Z85230"
diff --git a/drivers/net/wd.c b/drivers/net/wd.c
index eb72c67699ab..f1549fff0edc 100644
--- a/drivers/net/wd.c
+++ b/drivers/net/wd.c
@@ -342,10 +342,10 @@ static int __init wd_probe1(struct net_device *dev, int ioaddr)
printk(" %s, IRQ %d, shared memory at %#lx-%#lx.\n",
model_name, dev->irq, dev->mem_start, dev->mem_end-1);
- ei_status.reset_8390 = &wd_reset_8390;
- ei_status.block_input = &wd_block_input;
- ei_status.block_output = &wd_block_output;
- ei_status.get_8390_hdr = &wd_get_8390_hdr;
+ ei_status.reset_8390 = wd_reset_8390;
+ ei_status.block_input = wd_block_input;
+ ei_status.block_output = wd_block_output;
+ ei_status.get_8390_hdr = wd_get_8390_hdr;
dev->netdev_ops = &wd_netdev_ops;
NS8390_init(dev, 0);
diff --git a/drivers/net/wimax/i2400m/control.c b/drivers/net/wimax/i2400m/control.c
index 9fb03082153a..12b84ed0e38a 100644
--- a/drivers/net/wimax/i2400m/control.c
+++ b/drivers/net/wimax/i2400m/control.c
@@ -98,7 +98,7 @@ MODULE_PARM_DESC(power_save_disabled,
"False by default (so the device is told to do power "
"saving).");
-int i2400m_passive_mode; /* 0 (passive mode disabled) by default */
+static int i2400m_passive_mode; /* 0 (passive mode disabled) by default */
module_param_named(passive_mode, i2400m_passive_mode, int, 0644);
MODULE_PARM_DESC(passive_mode,
"If true, the driver will not do any device setup "
@@ -558,8 +558,9 @@ void i2400m_report_hook(struct i2400m *i2400m,
* processing should be done in the function that calls the
* command. This is here for some cases where it can't happen...
*/
-void i2400m_msg_ack_hook(struct i2400m *i2400m,
- const struct i2400m_l3l4_hdr *l3l4_hdr, size_t size)
+static void i2400m_msg_ack_hook(struct i2400m *i2400m,
+ const struct i2400m_l3l4_hdr *l3l4_hdr,
+ size_t size)
{
int result;
struct device *dev = i2400m_dev(i2400m);
@@ -1135,7 +1136,7 @@ error_alloc:
* i2400m_report_state_hook() to parse the answer. This will set the
* carrier state, as well as the RF Kill switches state.
*/
-int i2400m_cmd_get_state(struct i2400m *i2400m)
+static int i2400m_cmd_get_state(struct i2400m *i2400m)
{
int result;
struct device *dev = i2400m_dev(i2400m);
@@ -1177,8 +1178,6 @@ error_msg_to_dev:
error_alloc:
return result;
}
-EXPORT_SYMBOL_GPL(i2400m_cmd_get_state);
-
/**
* Set basic configuration settings
@@ -1190,8 +1189,9 @@ EXPORT_SYMBOL_GPL(i2400m_cmd_get_state);
* right endianess (LE).
* @arg_size: number of pointers in the @args array
*/
-int i2400m_set_init_config(struct i2400m *i2400m,
- const struct i2400m_tlv_hdr **arg, size_t args)
+static int i2400m_set_init_config(struct i2400m *i2400m,
+ const struct i2400m_tlv_hdr **arg,
+ size_t args)
{
int result;
struct device *dev = i2400m_dev(i2400m);
@@ -1258,8 +1258,6 @@ none:
return result;
}
-EXPORT_SYMBOL_GPL(i2400m_set_init_config);
-
/**
* i2400m_set_idle_timeout - Set the device's idle mode timeout
diff --git a/drivers/net/wimax/i2400m/debugfs.c b/drivers/net/wimax/i2400m/debugfs.c
index b1aec3e1892f..9c70b5fa3f51 100644
--- a/drivers/net/wimax/i2400m/debugfs.c
+++ b/drivers/net/wimax/i2400m/debugfs.c
@@ -119,6 +119,7 @@ const struct file_operations i2400m_rx_stats_fops = {
.open = i2400m_stats_open,
.read = i2400m_rx_stats_read,
.write = i2400m_rx_stats_write,
+ .llseek = default_llseek,
};
@@ -171,6 +172,7 @@ const struct file_operations i2400m_tx_stats_fops = {
.open = i2400m_stats_open,
.read = i2400m_tx_stats_read,
.write = i2400m_tx_stats_write,
+ .llseek = default_llseek,
};
diff --git a/drivers/net/wimax/i2400m/driver.c b/drivers/net/wimax/i2400m/driver.c
index 9c8b78d4abd2..cdedab46ba21 100644
--- a/drivers/net/wimax/i2400m/driver.c
+++ b/drivers/net/wimax/i2400m/driver.c
@@ -122,7 +122,7 @@ struct i2400m_work *__i2400m_work_setup(
* works struct was already queued, but we have just allocated it, so
* it should not happen.
*/
-int i2400m_schedule_work(struct i2400m *i2400m,
+static int i2400m_schedule_work(struct i2400m *i2400m,
void (*fn)(struct work_struct *), gfp_t gfp_flags,
const void *pl, size_t pl_size)
{
diff --git a/drivers/net/wimax/i2400m/i2400m-sdio.h b/drivers/net/wimax/i2400m/i2400m-sdio.h
index 360d4fb195f4..1d63ffdedfde 100644
--- a/drivers/net/wimax/i2400m/i2400m-sdio.h
+++ b/drivers/net/wimax/i2400m/i2400m-sdio.h
@@ -140,7 +140,6 @@ void i2400ms_init(struct i2400ms *i2400ms)
extern int i2400ms_rx_setup(struct i2400ms *);
extern void i2400ms_rx_release(struct i2400ms *);
-extern ssize_t __i2400ms_rx_get_size(struct i2400ms *);
extern int i2400ms_tx_setup(struct i2400ms *);
extern void i2400ms_tx_release(struct i2400ms *);
diff --git a/drivers/net/wimax/i2400m/i2400m.h b/drivers/net/wimax/i2400m/i2400m.h
index fa74777fd65f..59ac7705e76e 100644
--- a/drivers/net/wimax/i2400m/i2400m.h
+++ b/drivers/net/wimax/i2400m/i2400m.h
@@ -910,28 +910,19 @@ struct i2400m_work {
u8 pl[0];
};
-extern int i2400m_schedule_work(struct i2400m *,
- void (*)(struct work_struct *), gfp_t,
- const void *, size_t);
-
extern int i2400m_msg_check_status(const struct i2400m_l3l4_hdr *,
char *, size_t);
extern int i2400m_msg_size_check(struct i2400m *,
const struct i2400m_l3l4_hdr *, size_t);
extern struct sk_buff *i2400m_msg_to_dev(struct i2400m *, const void *, size_t);
extern void i2400m_msg_to_dev_cancel_wait(struct i2400m *, int);
-extern void i2400m_msg_ack_hook(struct i2400m *,
- const struct i2400m_l3l4_hdr *, size_t);
extern void i2400m_report_hook(struct i2400m *,
const struct i2400m_l3l4_hdr *, size_t);
extern void i2400m_report_hook_work(struct work_struct *);
extern int i2400m_cmd_enter_powersave(struct i2400m *);
-extern int i2400m_cmd_get_state(struct i2400m *);
extern int i2400m_cmd_exit_idle(struct i2400m *);
extern struct sk_buff *i2400m_get_device_info(struct i2400m *);
extern int i2400m_firmware_check(struct i2400m *);
-extern int i2400m_set_init_config(struct i2400m *,
- const struct i2400m_tlv_hdr **, size_t);
extern int i2400m_set_idle_timeout(struct i2400m *, unsigned);
static inline
diff --git a/drivers/net/wimax/i2400m/rx.c b/drivers/net/wimax/i2400m/rx.c
index 8cc9e319f435..844133b44af0 100644
--- a/drivers/net/wimax/i2400m/rx.c
+++ b/drivers/net/wimax/i2400m/rx.c
@@ -922,7 +922,7 @@ void i2400m_roq_queue_update_ws(struct i2400m *i2400m, struct i2400m_roq *roq,
* rx_roq_refcount becomes zero. This routine gets executed when
* rx_roq_refcount becomes zero.
*/
-void i2400m_rx_roq_destroy(struct kref *ref)
+static void i2400m_rx_roq_destroy(struct kref *ref)
{
unsigned itr;
struct i2400m *i2400m
@@ -1244,16 +1244,16 @@ int i2400m_rx(struct i2400m *i2400m, struct sk_buff *skb)
int i, result;
struct device *dev = i2400m_dev(i2400m);
const struct i2400m_msg_hdr *msg_hdr;
- size_t pl_itr, pl_size, skb_len;
+ size_t pl_itr, pl_size;
unsigned long flags;
- unsigned num_pls, single_last;
+ unsigned num_pls, single_last, skb_len;
skb_len = skb->len;
- d_fnstart(4, dev, "(i2400m %p skb %p [size %zu])\n",
+ d_fnstart(4, dev, "(i2400m %p skb %p [size %u])\n",
i2400m, skb, skb_len);
result = -EIO;
msg_hdr = (void *) skb->data;
- result = i2400m_rx_msg_hdr_check(i2400m, msg_hdr, skb->len);
+ result = i2400m_rx_msg_hdr_check(i2400m, msg_hdr, skb_len);
if (result < 0)
goto error_msg_hdr_check;
result = -EIO;
@@ -1261,10 +1261,10 @@ int i2400m_rx(struct i2400m *i2400m, struct sk_buff *skb)
pl_itr = sizeof(*msg_hdr) + /* Check payload descriptor(s) */
num_pls * sizeof(msg_hdr->pld[0]);
pl_itr = ALIGN(pl_itr, I2400M_PL_ALIGN);
- if (pl_itr > skb->len) { /* got all the payload descriptors? */
+ if (pl_itr > skb_len) { /* got all the payload descriptors? */
dev_err(dev, "RX: HW BUG? message too short (%u bytes) for "
"%u payload descriptors (%zu each, total %zu)\n",
- skb->len, num_pls, sizeof(msg_hdr->pld[0]), pl_itr);
+ skb_len, num_pls, sizeof(msg_hdr->pld[0]), pl_itr);
goto error_pl_descr_short;
}
/* Walk each payload payload--check we really got it */
@@ -1272,7 +1272,7 @@ int i2400m_rx(struct i2400m *i2400m, struct sk_buff *skb)
/* work around old gcc warnings */
pl_size = i2400m_pld_size(&msg_hdr->pld[i]);
result = i2400m_rx_pl_descr_check(i2400m, &msg_hdr->pld[i],
- pl_itr, skb->len);
+ pl_itr, skb_len);
if (result < 0)
goto error_pl_descr_check;
single_last = num_pls == 1 || i == num_pls - 1;
@@ -1290,16 +1290,16 @@ int i2400m_rx(struct i2400m *i2400m, struct sk_buff *skb)
if (i < i2400m->rx_pl_min)
i2400m->rx_pl_min = i;
i2400m->rx_num++;
- i2400m->rx_size_acc += skb->len;
- if (skb->len < i2400m->rx_size_min)
- i2400m->rx_size_min = skb->len;
- if (skb->len > i2400m->rx_size_max)
- i2400m->rx_size_max = skb->len;
+ i2400m->rx_size_acc += skb_len;
+ if (skb_len < i2400m->rx_size_min)
+ i2400m->rx_size_min = skb_len;
+ if (skb_len > i2400m->rx_size_max)
+ i2400m->rx_size_max = skb_len;
spin_unlock_irqrestore(&i2400m->rx_lock, flags);
error_pl_descr_check:
error_pl_descr_short:
error_msg_hdr_check:
- d_fnend(4, dev, "(i2400m %p skb %p [size %zu]) = %d\n",
+ d_fnend(4, dev, "(i2400m %p skb %p [size %u]) = %d\n",
i2400m, skb, skb_len, result);
return result;
}
diff --git a/drivers/net/wimax/i2400m/sdio-rx.c b/drivers/net/wimax/i2400m/sdio-rx.c
index 8b809c2ead6c..fb6396dd115f 100644
--- a/drivers/net/wimax/i2400m/sdio-rx.c
+++ b/drivers/net/wimax/i2400m/sdio-rx.c
@@ -87,7 +87,7 @@ static const __le32 i2400m_ACK_BARKER[4] = {
*
* sdio_readl() doesn't work.
*/
-ssize_t __i2400ms_rx_get_size(struct i2400ms *i2400ms)
+static ssize_t __i2400ms_rx_get_size(struct i2400ms *i2400ms)
{
int ret, cnt, val;
ssize_t rx_size;
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 174e3442d519..4de4410cd38e 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -279,6 +279,7 @@ source "drivers/net/wireless/libertas/Kconfig"
source "drivers/net/wireless/orinoco/Kconfig"
source "drivers/net/wireless/p54/Kconfig"
source "drivers/net/wireless/rt2x00/Kconfig"
+source "drivers/net/wireless/wl1251/Kconfig"
source "drivers/net/wireless/wl12xx/Kconfig"
source "drivers/net/wireless/zd1211rw/Kconfig"
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
index 5d4ce4d2b32b..06f8ca26c5c1 100644
--- a/drivers/net/wireless/Makefile
+++ b/drivers/net/wireless/Makefile
@@ -49,6 +49,8 @@ obj-$(CONFIG_ATH_COMMON) += ath/
obj-$(CONFIG_MAC80211_HWSIM) += mac80211_hwsim.o
+obj-$(CONFIG_WL1251) += wl1251/
obj-$(CONFIG_WL12XX) += wl12xx/
+obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl12xx/
obj-$(CONFIG_IWM) += iwmc3200wifi/
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 1d05445d4ba3..a36e7870b03e 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -105,7 +105,7 @@ static struct pci_driver airo_driver = {
of statistics in the /proc filesystem */
#define IGNLABEL(comment) NULL
-static char *statsLabels[] = {
+static const char *statsLabels[] = {
"RxOverrun",
IGNLABEL("RxPlcpCrcErr"),
IGNLABEL("RxPlcpFormatErr"),
@@ -217,7 +217,6 @@ static char *statsLabels[] = {
(no spaces) list of rates (up to 8). */
static int rates[8];
-static int basic_rate;
static char *ssids[3];
static int io[4];
@@ -250,7 +249,6 @@ MODULE_LICENSE("Dual BSD/GPL");
MODULE_SUPPORTED_DEVICE("Aironet 4500, 4800 and Cisco 340/350");
module_param_array(io, int, NULL, 0);
module_param_array(irq, int, NULL, 0);
-module_param(basic_rate, int, 0);
module_param_array(rates, int, NULL, 0);
module_param_array(ssids, charp, NULL, 0);
module_param(auto_wep, int, 0);
@@ -932,7 +930,7 @@ typedef struct aironet_ioctl {
unsigned char __user *data; // d-data
} aironet_ioctl;
-static char swversion[] = "2.1";
+static const char swversion[] = "2.1";
#endif /* CISCO_EXT */
#define NUM_MODULES 2
@@ -1374,7 +1372,7 @@ static int micsetup(struct airo_info *ai) {
return SUCCESS;
}
-static char micsnap[] = {0xAA,0xAA,0x03,0x00,0x40,0x96,0x00,0x02};
+static const u8 micsnap[] = {0xAA,0xAA,0x03,0x00,0x40,0x96,0x00,0x02};
/*===========================================================================
* Description: Mic a packet
@@ -2723,9 +2721,8 @@ static int airo_networks_allocate(struct airo_info *ai)
if (ai->networks)
return 0;
- ai->networks =
- kzalloc(AIRO_MAX_NETWORK_COUNT * sizeof(BSSListElement),
- GFP_KERNEL);
+ ai->networks = kcalloc(AIRO_MAX_NETWORK_COUNT, sizeof(BSSListElement),
+ GFP_KERNEL);
if (!ai->networks) {
airo_print_warn("", "Out of memory allocating beacons");
return -ENOMEM;
@@ -3884,15 +3881,6 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
ai->config.rates[i] = rates[i];
}
}
- if ( basic_rate > 0 ) {
- for( i = 0; i < 8; i++ ) {
- if ( ai->config.rates[i] == basic_rate ||
- !ai->config.rates ) {
- ai->config.rates[i] = basic_rate | 0x80;
- break;
- }
- }
- }
set_bit (FLAG_COMMIT, &ai->flags);
}
@@ -4430,21 +4418,24 @@ static const struct file_operations proc_statsdelta_ops = {
.owner = THIS_MODULE,
.read = proc_read,
.open = proc_statsdelta_open,
- .release = proc_close
+ .release = proc_close,
+ .llseek = default_llseek,
};
static const struct file_operations proc_stats_ops = {
.owner = THIS_MODULE,
.read = proc_read,
.open = proc_stats_open,
- .release = proc_close
+ .release = proc_close,
+ .llseek = default_llseek,
};
static const struct file_operations proc_status_ops = {
.owner = THIS_MODULE,
.read = proc_read,
.open = proc_status_open,
- .release = proc_close
+ .release = proc_close,
+ .llseek = default_llseek,
};
static const struct file_operations proc_SSID_ops = {
@@ -4452,7 +4443,8 @@ static const struct file_operations proc_SSID_ops = {
.read = proc_read,
.write = proc_write,
.open = proc_SSID_open,
- .release = proc_close
+ .release = proc_close,
+ .llseek = default_llseek,
};
static const struct file_operations proc_BSSList_ops = {
@@ -4460,7 +4452,8 @@ static const struct file_operations proc_BSSList_ops = {
.read = proc_read,
.write = proc_write,
.open = proc_BSSList_open,
- .release = proc_close
+ .release = proc_close,
+ .llseek = default_llseek,
};
static const struct file_operations proc_APList_ops = {
@@ -4468,7 +4461,8 @@ static const struct file_operations proc_APList_ops = {
.read = proc_read,
.write = proc_write,
.open = proc_APList_open,
- .release = proc_close
+ .release = proc_close,
+ .llseek = default_llseek,
};
static const struct file_operations proc_config_ops = {
@@ -4476,7 +4470,8 @@ static const struct file_operations proc_config_ops = {
.read = proc_read,
.write = proc_write,
.open = proc_config_open,
- .release = proc_close
+ .release = proc_close,
+ .llseek = default_llseek,
};
static const struct file_operations proc_wepkey_ops = {
@@ -4484,7 +4479,8 @@ static const struct file_operations proc_wepkey_ops = {
.read = proc_read,
.write = proc_write,
.open = proc_wepkey_open,
- .release = proc_close
+ .release = proc_close,
+ .llseek = default_llseek,
};
static struct proc_dir_entry *airo_entry;
@@ -5024,7 +5020,7 @@ static void proc_config_on_close(struct inode *inode, struct file *file)
airo_config_commit(dev, NULL, NULL, NULL);
}
-static char *get_rmode(__le16 mode)
+static const char *get_rmode(__le16 mode)
{
switch(mode & RXMODE_MASK) {
case RXMODE_RFMON: return "rfmon";
diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c
index 9a121a5b787c..df2484d45474 100644
--- a/drivers/net/wireless/airo_cs.c
+++ b/drivers/net/wireless/airo_cs.c
@@ -32,7 +32,6 @@
#include <linux/timer.h>
#include <linux/netdevice.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/ds.h>
@@ -54,58 +53,21 @@ MODULE_SUPPORTED_DEVICE("Aironet 4500, 4800 and Cisco 340 PCMCIA cards");
/*====================================================================*/
-/*
- The event() function is this driver's Card Services event handler.
- It will be called by Card Services when an appropriate card status
- event is received. The config() and release() entry points are
- used to configure or release a socket, in response to card
- insertion and ejection events. They are invoked from the airo_cs
- event handler.
-*/
-
static int airo_config(struct pcmcia_device *link);
static void airo_release(struct pcmcia_device *link);
-/*
- The attach() and detach() entry points are used to create and destroy
- "instances" of the driver, where each instance represents everything
- needed to manage one actual PCMCIA card.
-*/
-
static void airo_detach(struct pcmcia_device *p_dev);
typedef struct local_info_t {
struct net_device *eth_dev;
} local_info_t;
-/*======================================================================
-
- airo_attach() creates an "instance" of the driver, allocating
- local data structures for one device. The device is registered
- with Card Services.
-
- The dev_link structure is initialized, but we don't actually
- configure the card at this point -- we wait until we receive a
- card insertion event.
-
- ======================================================================*/
-
static int airo_probe(struct pcmcia_device *p_dev)
{
local_info_t *local;
dev_dbg(&p_dev->dev, "airo_attach()\n");
- /*
- General socket configuration defaults can go here. In this
- client, we assume very little, and rely on the CIS for almost
- everything. In most clients, many details (i.e., number, sizes,
- and attributes of IO windows) are fixed by the nature of the
- device, and can be hard-wired here.
- */
- p_dev->conf.Attributes = 0;
- p_dev->conf.IntType = INT_MEMORY_AND_IO;
-
/* Allocate space for private device-specific data */
local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
if (!local) {
@@ -117,15 +79,6 @@ static int airo_probe(struct pcmcia_device *p_dev)
return airo_config(p_dev);
} /* airo_attach */
-/*======================================================================
-
- This deletes a driver "instance". The device is de-registered
- with Card Services. If it has been released, all local data
- structures are freed. Otherwise, the structures will be freed
- when the device is released.
-
- ======================================================================*/
-
static void airo_detach(struct pcmcia_device *link)
{
dev_dbg(&link->dev, "airo_detach\n");
@@ -140,60 +93,12 @@ static void airo_detach(struct pcmcia_device *link)
kfree(link->priv);
} /* airo_detach */
-/*======================================================================
-
- airo_config() is scheduled to run after a CARD_INSERTION event
- is received, to configure the PCMCIA socket, and to make the
- device available to the system.
-
- ======================================================================*/
-
-static int airo_cs_config_check(struct pcmcia_device *p_dev,
- cistpl_cftable_entry_t *cfg,
- cistpl_cftable_entry_t *dflt,
- unsigned int vcc,
- void *priv_data)
+static int airo_cs_config_check(struct pcmcia_device *p_dev, void *priv_data)
{
- if (cfg->index == 0)
- return -ENODEV;
-
- /* Does this card need audio output? */
- if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
- p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
- p_dev->conf.Status = CCSR_AUDIO_ENA;
- }
-
- /* Use power settings for Vcc and Vpp if present */
- /* Note that the CIS values need to be rescaled */
- if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
- p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
- else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM))
- p_dev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM]/10000;
-
- p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
-
- /* IO window settings */
- p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
- if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
- cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
- p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
- p_dev->resource[0]->flags |=
- pcmcia_io_cfg_data_width(io->flags);
- p_dev->resource[0]->start = io->win[0].base;
- p_dev->resource[0]->end = io->win[0].len;
- if (io->nwin > 1) {
- p_dev->resource[1]->flags = p_dev->resource[0]->flags;
- p_dev->resource[1]->start = io->win[1].base;
- p_dev->resource[1]->end = io->win[1].len;
- }
- }
+ if (p_dev->config_index == 0)
+ return -EINVAL;
- /* This reserves IO space but doesn't actually enable it */
- if (pcmcia_request_io(p_dev) != 0)
- return -ENODEV;
-
- /* If we got this far, we're cool! */
- return 0;
+ return pcmcia_request_io(p_dev);
}
@@ -206,20 +111,9 @@ static int airo_config(struct pcmcia_device *link)
dev_dbg(&link->dev, "airo_config\n");
- /*
- * In this loop, we scan the CIS for configuration table
- * entries, each of which describes a valid card
- * configuration, including voltage, IO window, memory window,
- * and interrupt settings.
- *
- * We make no assumptions about the card to be configured: we
- * use just the information available in the CIS. In an ideal
- * world, this would work for any PCMCIA card, but it requires
- * a complete and accurate CIS. In practice, a driver usually
- * "knows" most of these things without consulting the CIS,
- * and most client drivers will only use the CIS to fill in
- * implementation-defined details.
- */
+ link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP |
+ CONF_AUTO_AUDIO | CONF_AUTO_SET_IO;
+
ret = pcmcia_loop_config(link, airo_cs_config_check, NULL);
if (ret)
goto failed;
@@ -227,12 +121,7 @@ static int airo_config(struct pcmcia_device *link)
if (!link->irq)
goto failed;
- /*
- This actually configures the PCMCIA socket -- setting up
- the I/O windows and the interrupt mapping, and putting the
- card and host interface into "Memory and IO" mode.
- */
- ret = pcmcia_request_configuration(link, &link->conf);
+ ret = pcmcia_enable_device(link);
if (ret)
goto failed;
((local_info_t *)link->priv)->eth_dev =
@@ -241,17 +130,6 @@ static int airo_config(struct pcmcia_device *link)
if (!((local_info_t *)link->priv)->eth_dev)
goto failed;
- /* Finally, report what we've done */
- dev_info(&link->dev, "index 0x%02x: ",
- link->conf.ConfigIndex);
- if (link->conf.Vpp)
- printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10);
- printk(", irq %d", link->irq);
- if (link->resource[0])
- printk(" & %pR", link->resource[0]);
- if (link->resource[1])
- printk(" & %pR", link->resource[1]);
- printk("\n");
return 0;
failed:
@@ -259,14 +137,6 @@ static int airo_config(struct pcmcia_device *link)
return -ENODEV;
} /* airo_config */
-/*======================================================================
-
- After a card is removed, airo_release() will unregister the
- device, and release the PCMCIA configuration. If the device is
- still open, this will be postponed until it is closed.
-
- ======================================================================*/
-
static void airo_release(struct pcmcia_device *link)
{
dev_dbg(&link->dev, "airo_release\n");
@@ -305,9 +175,7 @@ MODULE_DEVICE_TABLE(pcmcia, airo_ids);
static struct pcmcia_driver airo_driver = {
.owner = THIS_MODULE,
- .drv = {
- .name = "airo_cs",
- },
+ .name = "airo_cs",
.probe = airo_probe,
.remove = airo_detach,
.id_table = airo_ids,
@@ -315,12 +183,12 @@ static struct pcmcia_driver airo_driver = {
.resume = airo_resume,
};
-static int airo_cs_init(void)
+static int __init airo_cs_init(void)
{
return pcmcia_register_driver(&airo_driver);
}
-static void airo_cs_cleanup(void)
+static void __exit airo_cs_cleanup(void)
{
pcmcia_unregister_driver(&airo_driver);
}
diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c
index 1128fa8c9ed5..1476314afa8a 100644
--- a/drivers/net/wireless/at76c50x-usb.c
+++ b/drivers/net/wireless/at76c50x-usb.c
@@ -1525,8 +1525,7 @@ static void at76_rx_tasklet(unsigned long param)
if (priv->device_unplugged) {
at76_dbg(DBG_DEVSTART, "device unplugged");
- if (urb)
- at76_dbg(DBG_DEVSTART, "urb status %d", urb->status);
+ at76_dbg(DBG_DEVSTART, "urb status %d", urb->status);
return;
}
@@ -2061,11 +2060,12 @@ static int at76_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
int i;
- at76_dbg(DBG_MAC80211, "%s(): cmd %d key->alg %d key->keyidx %d "
+ at76_dbg(DBG_MAC80211, "%s(): cmd %d key->cipher %d key->keyidx %d "
"key->keylen %d",
- __func__, cmd, key->alg, key->keyidx, key->keylen);
+ __func__, cmd, key->cipher, key->keyidx, key->keylen);
- if (key->alg != ALG_WEP)
+ if ((key->cipher != WLAN_CIPHER_SUITE_WEP40) &&
+ (key->cipher != WLAN_CIPHER_SUITE_WEP104))
return -EOPNOTSUPP;
key->hw_key_idx = key->keyidx;
diff --git a/drivers/net/wireless/ath/Kconfig b/drivers/net/wireless/ath/Kconfig
index 0a75be027afa..92c216263ee9 100644
--- a/drivers/net/wireless/ath/Kconfig
+++ b/drivers/net/wireless/ath/Kconfig
@@ -25,5 +25,6 @@ config ATH_DEBUG
source "drivers/net/wireless/ath/ath5k/Kconfig"
source "drivers/net/wireless/ath/ath9k/Kconfig"
source "drivers/net/wireless/ath/ar9170/Kconfig"
+source "drivers/net/wireless/ath/carl9170/Kconfig"
endif
diff --git a/drivers/net/wireless/ath/Makefile b/drivers/net/wireless/ath/Makefile
index 8113a5042afa..6d711ec97ec2 100644
--- a/drivers/net/wireless/ath/Makefile
+++ b/drivers/net/wireless/ath/Makefile
@@ -1,11 +1,13 @@
obj-$(CONFIG_ATH5K) += ath5k/
obj-$(CONFIG_ATH9K_HW) += ath9k/
obj-$(CONFIG_AR9170_USB) += ar9170/
+obj-$(CONFIG_CARL9170) += carl9170/
obj-$(CONFIG_ATH_COMMON) += ath.o
ath-objs := main.o \
regd.o \
- hw.o
+ hw.o \
+ key.o
ath-$(CONFIG_ATH_DEBUG) += debug.o
diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c
index debfb0fbc7c5..32bf79e6a320 100644
--- a/drivers/net/wireless/ath/ar9170/main.c
+++ b/drivers/net/wireless/ath/ar9170/main.c
@@ -1190,14 +1190,13 @@ static int ar9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb)
if (info->control.hw_key) {
icv = info->control.hw_key->icv_len;
- switch (info->control.hw_key->alg) {
- case ALG_WEP:
+ switch (info->control.hw_key->cipher) {
+ case WLAN_CIPHER_SUITE_WEP40:
+ case WLAN_CIPHER_SUITE_WEP104:
+ case WLAN_CIPHER_SUITE_TKIP:
keytype = AR9170_TX_MAC_ENCR_RC4;
break;
- case ALG_TKIP:
- keytype = AR9170_TX_MAC_ENCR_RC4;
- break;
- case ALG_CCMP:
+ case WLAN_CIPHER_SUITE_CCMP:
keytype = AR9170_TX_MAC_ENCR_AES;
break;
default:
@@ -1778,17 +1777,17 @@ static int ar9170_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
if ((!ar->vif) || (ar->disable_offload))
return -EOPNOTSUPP;
- switch (key->alg) {
- case ALG_WEP:
- if (key->keylen == WLAN_KEY_LEN_WEP40)
- ktype = AR9170_ENC_ALG_WEP64;
- else
- ktype = AR9170_ENC_ALG_WEP128;
+ switch (key->cipher) {
+ case WLAN_CIPHER_SUITE_WEP40:
+ ktype = AR9170_ENC_ALG_WEP64;
+ break;
+ case WLAN_CIPHER_SUITE_WEP104:
+ ktype = AR9170_ENC_ALG_WEP128;
break;
- case ALG_TKIP:
+ case WLAN_CIPHER_SUITE_TKIP:
ktype = AR9170_ENC_ALG_TKIP;
break;
- case ALG_CCMP:
+ case WLAN_CIPHER_SUITE_CCMP:
ktype = AR9170_ENC_ALG_AESCCMP;
break;
default:
@@ -1827,7 +1826,7 @@ static int ar9170_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
if (err)
goto out;
- if (key->alg == ALG_TKIP) {
+ if (key->cipher == WLAN_CIPHER_SUITE_TKIP) {
err = ar9170_upload_key(ar, i, sta ? sta->addr : NULL,
ktype, 1, key->key + 16, 16);
if (err)
@@ -1864,7 +1863,7 @@ static int ar9170_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
if (err)
goto out;
- if (key->alg == ALG_TKIP) {
+ if (key->cipher == WLAN_CIPHER_SUITE_TKIP) {
err = ar9170_upload_key(ar, key->hw_key_idx,
NULL,
AR9170_ENC_ALG_NONE, 1,
diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c
index a93dc18a45c3..5dbb5361fd51 100644
--- a/drivers/net/wireless/ath/ar9170/usb.c
+++ b/drivers/net/wireless/ath/ar9170/usb.c
@@ -54,8 +54,6 @@ MODULE_AUTHOR("Christian Lamparter <chunkeey@web.de>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Atheros AR9170 802.11n USB wireless");
MODULE_FIRMWARE("ar9170.fw");
-MODULE_FIRMWARE("ar9170-1.fw");
-MODULE_FIRMWARE("ar9170-2.fw");
enum ar9170_requirements {
AR9170_REQ_FW1_ONLY = 1,
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h
index d32f2828b098..501050c0296f 100644
--- a/drivers/net/wireless/ath/ath.h
+++ b/drivers/net/wireless/ath/ath.h
@@ -19,6 +19,7 @@
#include <linux/skbuff.h>
#include <linux/if_ether.h>
+#include <linux/spinlock.h>
#include <net/mac80211.h>
/*
@@ -35,7 +36,6 @@ static const u8 ath_bcast_mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
struct ath_ani {
bool caldone;
- int16_t noise_floor;
unsigned int longcal_timer;
unsigned int shortcal_timer;
unsigned int resetcal_timer;
@@ -43,6 +43,13 @@ struct ath_ani {
struct timer_list timer;
};
+struct ath_cycle_counters {
+ u32 cycles;
+ u32 rx_busy;
+ u32 rx_frame;
+ u32 tx_frame;
+};
+
enum ath_device_state {
ATH_HW_UNAVAILABLE,
ATH_HW_INITIALIZED,
@@ -71,20 +78,44 @@ struct ath_regulatory {
struct reg_dmn_pair_mapping *regpair;
};
+enum ath_crypt_caps {
+ ATH_CRYPT_CAP_CIPHER_AESCCM = BIT(0),
+ ATH_CRYPT_CAP_MIC_COMBINED = BIT(1),
+};
+
+struct ath_keyval {
+ u8 kv_type;
+ u8 kv_pad;
+ u16 kv_len;
+ u8 kv_val[16]; /* TK */
+ u8 kv_mic[8]; /* Michael MIC key */
+ u8 kv_txmic[8]; /* Michael MIC TX key (used only if the hardware
+ * supports both MIC keys in the same key cache entry;
+ * in that case, kv_mic is the RX key) */
+};
+
+enum ath_cipher {
+ ATH_CIPHER_WEP = 0,
+ ATH_CIPHER_AES_OCB = 1,
+ ATH_CIPHER_AES_CCM = 2,
+ ATH_CIPHER_CKIP = 3,
+ ATH_CIPHER_TKIP = 4,
+ ATH_CIPHER_CLR = 5,
+ ATH_CIPHER_MIC = 127
+};
+
/**
* struct ath_ops - Register read/write operations
*
* @read: Register read
* @write: Register write
* @enable_write_buffer: Enable multiple register writes
- * @disable_write_buffer: Disable multiple register writes
- * @write_flush: Flush buffered register writes
+ * @write_flush: flush buffered register writes and disable buffering
*/
struct ath_ops {
unsigned int (*read)(void *, u32 reg_offset);
void (*write)(void *, u32 val, u32 reg_offset);
void (*enable_write_buffer)(void *);
- void (*disable_write_buffer)(void *);
void (*write_flush) (void *);
};
@@ -119,7 +150,14 @@ struct ath_common {
u32 keymax;
DECLARE_BITMAP(keymap, ATH_KEYMAX);
- u8 splitmic;
+ DECLARE_BITMAP(tkip_keymap, ATH_KEYMAX);
+ enum ath_crypt_caps crypt_caps;
+
+ unsigned int clockrate;
+
+ spinlock_t cc_lock;
+ struct ath_cycle_counters cc_ani;
+ struct ath_cycle_counters cc_survey;
struct ath_regulatory regulatory;
const struct ath_ops *ops;
@@ -131,5 +169,13 @@ struct sk_buff *ath_rxbuf_alloc(struct ath_common *common,
gfp_t gfp_mask);
void ath_hw_setbssidmask(struct ath_common *common);
+void ath_key_delete(struct ath_common *common, struct ieee80211_key_conf *key);
+int ath_key_config(struct ath_common *common,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct ieee80211_key_conf *key);
+bool ath_hw_keyreset(struct ath_common *common, u16 entry);
+void ath_hw_cycle_counters_update(struct ath_common *common);
+int32_t ath_hw_get_listen_time(struct ath_common *common);
#endif /* ATH_H */
diff --git a/drivers/net/wireless/ath/ath5k/ani.c b/drivers/net/wireless/ath/ath5k/ani.c
index 26dbe65fedb0..f1419198a479 100644
--- a/drivers/net/wireless/ath/ath5k/ani.c
+++ b/drivers/net/wireless/ath/ath5k/ani.c
@@ -355,41 +355,28 @@ ath5k_ani_lower_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as)
/**
- * ath5k_hw_ani_get_listen_time() - Calculate time spent listening
+ * ath5k_hw_ani_get_listen_time() - Update counters and return listening time
*
* Return an approximation of the time spent "listening" in milliseconds (ms)
- * since the last call of this function by deducting the cycles spent
- * transmitting and receiving from the total cycle count.
- * Save profile count values for debugging/statistics and because we might want
- * to use them later.
- *
- * We assume no one else clears these registers!
+ * since the last call of this function.
+ * Save a snapshot of the counter values for debugging/statistics.
*/
static int
ath5k_hw_ani_get_listen_time(struct ath5k_hw *ah, struct ath5k_ani_state *as)
{
+ struct ath_common *common = ath5k_hw_common(ah);
int listen;
- /* freeze */
- ath5k_hw_reg_write(ah, AR5K_MIBC_FMC, AR5K_MIBC);
- /* read */
- as->pfc_cycles = ath5k_hw_reg_read(ah, AR5K_PROFCNT_CYCLE);
- as->pfc_busy = ath5k_hw_reg_read(ah, AR5K_PROFCNT_RXCLR);
- as->pfc_tx = ath5k_hw_reg_read(ah, AR5K_PROFCNT_TX);
- as->pfc_rx = ath5k_hw_reg_read(ah, AR5K_PROFCNT_RX);
- /* clear */
- ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_TX);
- ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RX);
- ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RXCLR);
- ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_CYCLE);
- /* un-freeze */
- ath5k_hw_reg_write(ah, 0, AR5K_MIBC);
-
- /* TODO: where does 44000 come from? (11g clock rate?) */
- listen = (as->pfc_cycles - as->pfc_rx - as->pfc_tx) / 44000;
-
- if (as->pfc_cycles == 0 || listen < 0)
- return 0;
+ spin_lock_bh(&common->cc_lock);
+
+ ath_hw_cycle_counters_update(common);
+ memcpy(&as->last_cc, &common->cc_ani, sizeof(as->last_cc));
+
+ /* clears common->cc_ani */
+ listen = ath_hw_get_listen_time(common);
+
+ spin_unlock_bh(&common->cc_lock);
+
return listen;
}
@@ -552,9 +539,9 @@ ath5k_ani_mib_intr(struct ath5k_hw *ah)
if (ah->ah_sc->ani_state.ani_mode != ATH5K_ANI_MODE_AUTO)
return;
- /* if one of the errors triggered, we can get a superfluous second
- * interrupt, even though we have already reset the register. the
- * function detects that so we can return early */
+ /* If one of the errors triggered, we can get a superfluous second
+ * interrupt, even though we have already reset the register. The
+ * function detects that so we can return early. */
if (ath5k_ani_save_and_clear_phy_errors(ah, as) == 0)
return;
diff --git a/drivers/net/wireless/ath/ath5k/ani.h b/drivers/net/wireless/ath/ath5k/ani.h
index 55cf26d8522c..d0a664039c87 100644
--- a/drivers/net/wireless/ath/ath5k/ani.h
+++ b/drivers/net/wireless/ath/ath5k/ani.h
@@ -75,10 +75,7 @@ struct ath5k_ani_state {
unsigned int cck_errors;
/* debug/statistics only: numbers from last ANI calibration */
- unsigned int pfc_tx;
- unsigned int pfc_rx;
- unsigned int pfc_busy;
- unsigned int pfc_cycles;
+ struct ath_cycle_counters last_cc;
unsigned int last_listen;
unsigned int last_ofdm_errors;
unsigned int last_cck_errors;
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
index ea6362a8988d..4a367cdb3eb9 100644
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -175,7 +175,7 @@
#define AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF 0
#define AR5K_TUNE_RADAR_ALERT false
#define AR5K_TUNE_MIN_TX_FIFO_THRES 1
-#define AR5K_TUNE_MAX_TX_FIFO_THRES ((IEEE80211_MAX_LEN / 64) + 1)
+#define AR5K_TUNE_MAX_TX_FIFO_THRES ((IEEE80211_MAX_FRAME_LEN / 64) + 1)
#define AR5K_TUNE_REGISTER_TIMEOUT 20000
/* Register for RSSI threshold has a mask of 0xff, so 255 seems to
* be the max value. */
@@ -206,6 +206,8 @@
#define ATH5K_TUNE_CALIBRATION_INTERVAL_ANI 1000 /* 1 sec */
#define ATH5K_TUNE_CALIBRATION_INTERVAL_NF 60000 /* 60 sec */
+#define ATH5K_TX_COMPLETE_POLL_INT 3000 /* 3 sec */
+
#define AR5K_INIT_CARR_SENSE_EN 1
/*Swap RX/TX Descriptor for big endian archs*/
@@ -256,8 +258,6 @@
(AR5K_INIT_PROG_IFS_TURBO) \
)
-/* token to use for aifs, cwmin, cwmax in MadWiFi */
-#define AR5K_TXQ_USEDEFAULT ((u32) -1)
/* GENERIC CHIPSET DEFINITIONS */
@@ -343,9 +343,6 @@ struct ath5k_srev_name {
#define AR5K_SREV_PHY_5413 0x61
#define AR5K_SREV_PHY_2425 0x70
-/* IEEE defs */
-#define IEEE80211_MAX_LEN 2500
-
/* TODO add support to mac80211 for vendor-specific rates and modes */
/*
@@ -531,9 +528,9 @@ struct ath5k_txq_info {
enum ath5k_tx_queue tqi_type;
enum ath5k_tx_queue_subtype tqi_subtype;
u16 tqi_flags; /* Tx queue flags (see above) */
- u32 tqi_aifs; /* Arbitrated Interframe Space */
- s32 tqi_cw_min; /* Minimum Contention Window */
- s32 tqi_cw_max; /* Maximum Contention Window */
+ u8 tqi_aifs; /* Arbitrated Interframe Space */
+ u16 tqi_cw_min; /* Minimum Contention Window */
+ u16 tqi_cw_max; /* Maximum Contention Window */
u32 tqi_cbr_period; /* Constant bit rate period */
u32 tqi_cbr_overflow_limit;
u32 tqi_burst_time;
@@ -1031,8 +1028,6 @@ struct ath5k_hw {
bool ah_turbo;
bool ah_calibration;
bool ah_single_chip;
- bool ah_aes_support;
- bool ah_combined_mic;
enum ath5k_version ah_version;
enum ath5k_radio ah_radio;
@@ -1046,10 +1041,6 @@ struct ath5k_hw {
#define ah_modes ah_capabilities.cap_mode
#define ah_ee_version ah_capabilities.cap_eeprom.ee_version
- u32 ah_atim_window;
- u32 ah_aifs;
- u32 ah_cw_min;
- u32 ah_cw_max;
u32 ah_limit_tx_retries;
u8 ah_coverage_class;
@@ -1190,7 +1181,7 @@ extern int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype opmode);
void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class);
/* BSSID Functions */
int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac);
-void ath5k_hw_set_associd(struct ath5k_hw *ah);
+void ath5k_hw_set_bssid(struct ath5k_hw *ah);
void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask);
/* Receive start/stop functions */
void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah);
@@ -1204,17 +1195,13 @@ u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah);
void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64);
void ath5k_hw_reset_tsf(struct ath5k_hw *ah);
void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval);
+bool ath5k_hw_check_beacon_timers(struct ath5k_hw *ah, int intval);
/* ACK bit rate */
void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high);
/* Clock rate related functions */
unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec);
unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock);
-unsigned int ath5k_hw_get_clockrate(struct ath5k_hw *ah);
-/* Key table (WEP) functions */
-int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry);
-int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry,
- const struct ieee80211_key_conf *key, const u8 *mac);
-int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac);
+void ath5k_hw_set_clockrate(struct ath5k_hw *ah);
/* Queue Control Unit, DFS Control Unit Functions */
int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue,
diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c
index b32e28caeee2..cd0b14a0a93a 100644
--- a/drivers/net/wireless/ath/ath5k/attach.c
+++ b/drivers/net/wireless/ath/ath5k/attach.c
@@ -118,9 +118,6 @@ int ath5k_hw_attach(struct ath5k_softc *sc)
ah->ah_turbo = false;
ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER;
ah->ah_imr = 0;
- ah->ah_atim_window = 0;
- ah->ah_aifs = AR5K_TUNE_AIFS;
- ah->ah_cw_min = AR5K_TUNE_CWMIN;
ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY;
ah->ah_software_retry = false;
ah->ah_ant_mode = AR5K_ANTMODE_DEFAULT;
@@ -139,12 +136,12 @@ int ath5k_hw_attach(struct ath5k_softc *sc)
else
ah->ah_version = AR5K_AR5212;
- /*Fill the ath5k_hw struct with the needed functions*/
+ /* Fill the ath5k_hw struct with the needed functions */
ret = ath5k_hw_init_desc_functions(ah);
if (ret)
goto err_free;
- /* Bring device out of sleep and reset it's units */
+ /* Bring device out of sleep and reset its units */
ret = ath5k_hw_nic_wakeup(ah, 0, true);
if (ret)
goto err_free;
@@ -158,7 +155,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc)
CHANNEL_5GHZ);
ah->ah_phy = AR5K_PHY(0);
- /* Try to identify radio chip based on it's srev */
+ /* Try to identify radio chip based on its srev */
switch (ah->ah_radio_5ghz_revision & 0xf0) {
case AR5K_SREV_RAD_5111:
ah->ah_radio = AR5K_RF5111;
@@ -314,12 +311,16 @@ int ath5k_hw_attach(struct ath5k_softc *sc)
}
/* Crypto settings */
- ah->ah_aes_support = srev >= AR5K_SREV_AR5212_V4 &&
- (ee->ee_version >= AR5K_EEPROM_VERSION_5_0 &&
- !AR5K_EEPROM_AES_DIS(ee->ee_misc5));
+ common->keymax = (sc->ah->ah_version == AR5K_AR5210 ?
+ AR5K_KEYTABLE_SIZE_5210 : AR5K_KEYTABLE_SIZE_5211);
+
+ if (srev >= AR5K_SREV_AR5212_V4 &&
+ (ee->ee_version >= AR5K_EEPROM_VERSION_5_0 &&
+ !AR5K_EEPROM_AES_DIS(ee->ee_misc5)))
+ common->crypt_caps |= ATH_CRYPT_CAP_CIPHER_AESCCM;
if (srev >= AR5K_SREV_AR2414) {
- ah->ah_combined_mic = true;
+ common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED;
AR5K_REG_ENABLE_BITS(ah, AR5K_MISC_MODE,
AR5K_MISC_MODE_COMBINED_MIC);
}
@@ -329,7 +330,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc)
/* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */
memcpy(common->curbssid, ath_bcast_mac, ETH_ALEN);
- ath5k_hw_set_associd(ah);
+ ath5k_hw_set_bssid(ah);
ath5k_hw_set_opmode(ah, sc->opmode);
ath5k_hw_rfgain_opt_init(ah);
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index d77ce9906b6c..f1ae75d35d5d 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -52,6 +52,7 @@
#include <linux/ethtool.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
+#include <linux/etherdevice.h>
#include <net/ieee80211_radiotap.h>
@@ -61,6 +62,7 @@
#include "reg.h"
#include "debug.h"
#include "ani.h"
+#include "../debug.h"
static int modparam_nohwcrypt;
module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
@@ -70,11 +72,6 @@ static int modparam_all_channels;
module_param_named(all_channels, modparam_all_channels, bool, S_IRUGO);
MODULE_PARM_DESC(all_channels, "Expose all channels the device can use.");
-
-/******************\
-* Internal defines *
-\******************/
-
/* Module info */
MODULE_AUTHOR("Jiri Slaby");
MODULE_AUTHOR("Nick Kossifidis");
@@ -83,6 +80,10 @@ MODULE_SUPPORTED_DEVICE("Atheros 5xxx WLAN cards");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_VERSION("0.6.0 (EXPERIMENTAL)");
+static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan);
+static int ath5k_beacon_update(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif);
+static void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf);
/* Known PCI ids */
static DEFINE_PCI_DEVICE_TABLE(ath5k_pci_id_table) = {
@@ -190,129 +191,6 @@ static const struct ieee80211_rate ath5k_rates[] = {
/* XR missing */
};
-/*
- * Prototypes - PCI stack related functions
- */
-static int __devinit ath5k_pci_probe(struct pci_dev *pdev,
- const struct pci_device_id *id);
-static void __devexit ath5k_pci_remove(struct pci_dev *pdev);
-#ifdef CONFIG_PM_SLEEP
-static int ath5k_pci_suspend(struct device *dev);
-static int ath5k_pci_resume(struct device *dev);
-
-static SIMPLE_DEV_PM_OPS(ath5k_pm_ops, ath5k_pci_suspend, ath5k_pci_resume);
-#define ATH5K_PM_OPS (&ath5k_pm_ops)
-#else
-#define ATH5K_PM_OPS NULL
-#endif /* CONFIG_PM_SLEEP */
-
-static struct pci_driver ath5k_pci_driver = {
- .name = KBUILD_MODNAME,
- .id_table = ath5k_pci_id_table,
- .probe = ath5k_pci_probe,
- .remove = __devexit_p(ath5k_pci_remove),
- .driver.pm = ATH5K_PM_OPS,
-};
-
-
-
-/*
- * Prototypes - MAC 802.11 stack related functions
- */
-static int ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
-static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
- struct ath5k_txq *txq);
-static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan);
-static int ath5k_start(struct ieee80211_hw *hw);
-static void ath5k_stop(struct ieee80211_hw *hw);
-static int ath5k_add_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif);
-static void ath5k_remove_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif);
-static int ath5k_config(struct ieee80211_hw *hw, u32 changed);
-static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw,
- struct netdev_hw_addr_list *mc_list);
-static void ath5k_configure_filter(struct ieee80211_hw *hw,
- unsigned int changed_flags,
- unsigned int *new_flags,
- u64 multicast);
-static int ath5k_set_key(struct ieee80211_hw *hw,
- enum set_key_cmd cmd,
- struct ieee80211_vif *vif, struct ieee80211_sta *sta,
- struct ieee80211_key_conf *key);
-static int ath5k_get_stats(struct ieee80211_hw *hw,
- struct ieee80211_low_level_stats *stats);
-static int ath5k_get_survey(struct ieee80211_hw *hw,
- int idx, struct survey_info *survey);
-static u64 ath5k_get_tsf(struct ieee80211_hw *hw);
-static void ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf);
-static void ath5k_reset_tsf(struct ieee80211_hw *hw);
-static int ath5k_beacon_update(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif);
-static void ath5k_bss_info_changed(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_bss_conf *bss_conf,
- u32 changes);
-static void ath5k_sw_scan_start(struct ieee80211_hw *hw);
-static void ath5k_sw_scan_complete(struct ieee80211_hw *hw);
-static void ath5k_set_coverage_class(struct ieee80211_hw *hw,
- u8 coverage_class);
-
-static const struct ieee80211_ops ath5k_hw_ops = {
- .tx = ath5k_tx,
- .start = ath5k_start,
- .stop = ath5k_stop,
- .add_interface = ath5k_add_interface,
- .remove_interface = ath5k_remove_interface,
- .config = ath5k_config,
- .prepare_multicast = ath5k_prepare_multicast,
- .configure_filter = ath5k_configure_filter,
- .set_key = ath5k_set_key,
- .get_stats = ath5k_get_stats,
- .get_survey = ath5k_get_survey,
- .conf_tx = NULL,
- .get_tsf = ath5k_get_tsf,
- .set_tsf = ath5k_set_tsf,
- .reset_tsf = ath5k_reset_tsf,
- .bss_info_changed = ath5k_bss_info_changed,
- .sw_scan_start = ath5k_sw_scan_start,
- .sw_scan_complete = ath5k_sw_scan_complete,
- .set_coverage_class = ath5k_set_coverage_class,
-};
-
-/*
- * Prototypes - Internal functions
- */
-/* Attach detach */
-static int ath5k_attach(struct pci_dev *pdev,
- struct ieee80211_hw *hw);
-static void ath5k_detach(struct pci_dev *pdev,
- struct ieee80211_hw *hw);
-/* Channel/mode setup */
-static inline short ath5k_ieee2mhz(short chan);
-static unsigned int ath5k_copy_channels(struct ath5k_hw *ah,
- struct ieee80211_channel *channels,
- unsigned int mode,
- unsigned int max);
-static int ath5k_setup_bands(struct ieee80211_hw *hw);
-static int ath5k_chan_set(struct ath5k_softc *sc,
- struct ieee80211_channel *chan);
-static void ath5k_setcurmode(struct ath5k_softc *sc,
- unsigned int mode);
-static void ath5k_mode_setup(struct ath5k_softc *sc);
-
-/* Descriptor setup */
-static int ath5k_desc_alloc(struct ath5k_softc *sc,
- struct pci_dev *pdev);
-static void ath5k_desc_free(struct ath5k_softc *sc,
- struct pci_dev *pdev);
-/* Buffers setup */
-static int ath5k_rxbuf_setup(struct ath5k_softc *sc,
- struct ath5k_buf *bf);
-static int ath5k_txbuf_setup(struct ath5k_softc *sc,
- struct ath5k_buf *bf,
- struct ath5k_txq *txq, int padsize);
-
static inline void ath5k_txbuf_free_skb(struct ath5k_softc *sc,
struct ath5k_buf *bf)
{
@@ -345,35 +223,6 @@ static inline void ath5k_rxbuf_free_skb(struct ath5k_softc *sc,
}
-/* Queues setup */
-static struct ath5k_txq *ath5k_txq_setup(struct ath5k_softc *sc,
- int qtype, int subtype);
-static int ath5k_beaconq_setup(struct ath5k_hw *ah);
-static int ath5k_beaconq_config(struct ath5k_softc *sc);
-static void ath5k_txq_drainq(struct ath5k_softc *sc,
- struct ath5k_txq *txq);
-static void ath5k_txq_cleanup(struct ath5k_softc *sc);
-static void ath5k_txq_release(struct ath5k_softc *sc);
-/* Rx handling */
-static int ath5k_rx_start(struct ath5k_softc *sc);
-static void ath5k_rx_stop(struct ath5k_softc *sc);
-static unsigned int ath5k_rx_decrypted(struct ath5k_softc *sc,
- struct sk_buff *skb,
- struct ath5k_rx_status *rs);
-static void ath5k_tasklet_rx(unsigned long data);
-/* Tx handling */
-static void ath5k_tx_processq(struct ath5k_softc *sc,
- struct ath5k_txq *txq);
-static void ath5k_tasklet_tx(unsigned long data);
-/* Beacon handling */
-static int ath5k_beacon_setup(struct ath5k_softc *sc,
- struct ath5k_buf *bf);
-static void ath5k_beacon_send(struct ath5k_softc *sc);
-static void ath5k_beacon_config(struct ath5k_softc *sc);
-static void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf);
-static void ath5k_tasklet_beacon(unsigned long data);
-static void ath5k_tasklet_ani(unsigned long data);
-
static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp)
{
u64 tsf = ath5k_hw_get_tsf64(ah);
@@ -384,50 +233,6 @@ static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp)
return (tsf & ~0x7fff) | rstamp;
}
-/* Interrupt handling */
-static int ath5k_init(struct ath5k_softc *sc);
-static int ath5k_stop_locked(struct ath5k_softc *sc);
-static int ath5k_stop_hw(struct ath5k_softc *sc);
-static irqreturn_t ath5k_intr(int irq, void *dev_id);
-static void ath5k_reset_work(struct work_struct *work);
-
-static void ath5k_tasklet_calibrate(unsigned long data);
-
-/*
- * Module init/exit functions
- */
-static int __init
-init_ath5k_pci(void)
-{
- int ret;
-
- ath5k_debug_init();
-
- ret = pci_register_driver(&ath5k_pci_driver);
- if (ret) {
- printk(KERN_ERR "ath5k_pci: can't register pci driver\n");
- return ret;
- }
-
- return 0;
-}
-
-static void __exit
-exit_ath5k_pci(void)
-{
- pci_unregister_driver(&ath5k_pci_driver);
-
- ath5k_debug_finish();
-}
-
-module_init(init_ath5k_pci);
-module_exit(exit_ath5k_pci);
-
-
-/********************\
-* PCI Initialization *
-\********************/
-
static const char *
ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val)
{
@@ -466,299 +271,6 @@ static const struct ath_ops ath5k_common_ops = {
.write = ath5k_iowrite32,
};
-static int __devinit
-ath5k_pci_probe(struct pci_dev *pdev,
- const struct pci_device_id *id)
-{
- void __iomem *mem;
- struct ath5k_softc *sc;
- struct ath_common *common;
- struct ieee80211_hw *hw;
- int ret;
- u8 csz;
-
- /*
- * L0s needs to be disabled on all ath5k cards.
- *
- * For distributions shipping with CONFIG_PCIEASPM (this will be enabled
- * by default in the future in 2.6.36) this will also mean both L1 and
- * L0s will be disabled when a pre 1.1 PCIe device is detected. We do
- * know L1 works correctly even for all ath5k pre 1.1 PCIe devices
- * though but cannot currently undue the effect of a blacklist, for
- * details you can read pcie_aspm_sanity_check() and see how it adjusts
- * the device link capability.
- *
- * It may be possible in the future to implement some PCI API to allow
- * drivers to override blacklists for pre 1.1 PCIe but for now it is
- * best to accept that both L0s and L1 will be disabled completely for
- * distributions shipping with CONFIG_PCIEASPM rather than having this
- * issue present. Motivation for adding this new API will be to help
- * with power consumption for some of these devices.
- */
- pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S);
-
- ret = pci_enable_device(pdev);
- if (ret) {
- dev_err(&pdev->dev, "can't enable device\n");
- goto err;
- }
-
- /* XXX 32-bit addressing only */
- ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
- if (ret) {
- dev_err(&pdev->dev, "32-bit DMA not available\n");
- goto err_dis;
- }
-
- /*
- * Cache line size is used to size and align various
- * structures used to communicate with the hardware.
- */
- pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz);
- if (csz == 0) {
- /*
- * Linux 2.4.18 (at least) writes the cache line size
- * register as a 16-bit wide register which is wrong.
- * We must have this setup properly for rx buffer
- * DMA to work so force a reasonable value here if it
- * comes up zero.
- */
- csz = L1_CACHE_BYTES >> 2;
- pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz);
- }
- /*
- * The default setting of latency timer yields poor results,
- * set it to the value used by other systems. It may be worth
- * tweaking this setting more.
- */
- pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8);
-
- /* Enable bus mastering */
- pci_set_master(pdev);
-
- /*
- * Disable the RETRY_TIMEOUT register (0x41) to keep
- * PCI Tx retries from interfering with C3 CPU state.
- */
- pci_write_config_byte(pdev, 0x41, 0);
-
- ret = pci_request_region(pdev, 0, "ath5k");
- if (ret) {
- dev_err(&pdev->dev, "cannot reserve PCI memory region\n");
- goto err_dis;
- }
-
- mem = pci_iomap(pdev, 0, 0);
- if (!mem) {
- dev_err(&pdev->dev, "cannot remap PCI memory region\n") ;
- ret = -EIO;
- goto err_reg;
- }
-
- /*
- * Allocate hw (mac80211 main struct)
- * and hw->priv (driver private data)
- */
- hw = ieee80211_alloc_hw(sizeof(*sc), &ath5k_hw_ops);
- if (hw == NULL) {
- dev_err(&pdev->dev, "cannot allocate ieee80211_hw\n");
- ret = -ENOMEM;
- goto err_map;
- }
-
- dev_info(&pdev->dev, "registered as '%s'\n", wiphy_name(hw->wiphy));
-
- /* Initialize driver private data */
- SET_IEEE80211_DEV(hw, &pdev->dev);
- hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
- IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
- IEEE80211_HW_SIGNAL_DBM;
-
- hw->wiphy->interface_modes =
- BIT(NL80211_IFTYPE_AP) |
- BIT(NL80211_IFTYPE_STATION) |
- BIT(NL80211_IFTYPE_ADHOC) |
- BIT(NL80211_IFTYPE_MESH_POINT);
-
- hw->extra_tx_headroom = 2;
- hw->channel_change_time = 5000;
- sc = hw->priv;
- sc->hw = hw;
- sc->pdev = pdev;
-
- ath5k_debug_init_device(sc);
-
- /*
- * Mark the device as detached to avoid processing
- * interrupts until setup is complete.
- */
- __set_bit(ATH_STAT_INVALID, sc->status);
-
- sc->iobase = mem; /* So we can unmap it on detach */
- sc->opmode = NL80211_IFTYPE_STATION;
- sc->bintval = 1000;
- mutex_init(&sc->lock);
- spin_lock_init(&sc->rxbuflock);
- spin_lock_init(&sc->txbuflock);
- spin_lock_init(&sc->block);
-
- /* Set private data */
- pci_set_drvdata(pdev, sc);
-
- /* Setup interrupt handler */
- ret = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc);
- if (ret) {
- ATH5K_ERR(sc, "request_irq failed\n");
- goto err_free;
- }
-
- /*If we passed the test malloc a ath5k_hw struct*/
- sc->ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL);
- if (!sc->ah) {
- ret = -ENOMEM;
- ATH5K_ERR(sc, "out of memory\n");
- goto err_irq;
- }
-
- sc->ah->ah_sc = sc;
- sc->ah->ah_iobase = sc->iobase;
- common = ath5k_hw_common(sc->ah);
- common->ops = &ath5k_common_ops;
- common->ah = sc->ah;
- common->hw = hw;
- common->cachelsz = csz << 2; /* convert to bytes */
-
- /* Initialize device */
- ret = ath5k_hw_attach(sc);
- if (ret) {
- goto err_free_ah;
- }
-
- /* set up multi-rate retry capabilities */
- if (sc->ah->ah_version == AR5K_AR5212) {
- hw->max_rates = 4;
- hw->max_rate_tries = 11;
- }
-
- /* Finish private driver data initialization */
- ret = ath5k_attach(pdev, hw);
- if (ret)
- goto err_ah;
-
- ATH5K_INFO(sc, "Atheros AR%s chip found (MAC: 0x%x, PHY: 0x%x)\n",
- ath5k_chip_name(AR5K_VERSION_MAC, sc->ah->ah_mac_srev),
- sc->ah->ah_mac_srev,
- sc->ah->ah_phy_revision);
-
- if (!sc->ah->ah_single_chip) {
- /* Single chip radio (!RF5111) */
- if (sc->ah->ah_radio_5ghz_revision &&
- !sc->ah->ah_radio_2ghz_revision) {
- /* No 5GHz support -> report 2GHz radio */
- if (!test_bit(AR5K_MODE_11A,
- sc->ah->ah_capabilities.cap_mode)) {
- ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n",
- ath5k_chip_name(AR5K_VERSION_RAD,
- sc->ah->ah_radio_5ghz_revision),
- sc->ah->ah_radio_5ghz_revision);
- /* No 2GHz support (5110 and some
- * 5Ghz only cards) -> report 5Ghz radio */
- } else if (!test_bit(AR5K_MODE_11B,
- sc->ah->ah_capabilities.cap_mode)) {
- ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n",
- ath5k_chip_name(AR5K_VERSION_RAD,
- sc->ah->ah_radio_5ghz_revision),
- sc->ah->ah_radio_5ghz_revision);
- /* Multiband radio */
- } else {
- ATH5K_INFO(sc, "RF%s multiband radio found"
- " (0x%x)\n",
- ath5k_chip_name(AR5K_VERSION_RAD,
- sc->ah->ah_radio_5ghz_revision),
- sc->ah->ah_radio_5ghz_revision);
- }
- }
- /* Multi chip radio (RF5111 - RF2111) ->
- * report both 2GHz/5GHz radios */
- else if (sc->ah->ah_radio_5ghz_revision &&
- sc->ah->ah_radio_2ghz_revision){
- ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n",
- ath5k_chip_name(AR5K_VERSION_RAD,
- sc->ah->ah_radio_5ghz_revision),
- sc->ah->ah_radio_5ghz_revision);
- ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n",
- ath5k_chip_name(AR5K_VERSION_RAD,
- sc->ah->ah_radio_2ghz_revision),
- sc->ah->ah_radio_2ghz_revision);
- }
- }
-
-
- /* ready to process interrupts */
- __clear_bit(ATH_STAT_INVALID, sc->status);
-
- return 0;
-err_ah:
- ath5k_hw_detach(sc->ah);
-err_irq:
- free_irq(pdev->irq, sc);
-err_free_ah:
- kfree(sc->ah);
-err_free:
- ieee80211_free_hw(hw);
-err_map:
- pci_iounmap(pdev, mem);
-err_reg:
- pci_release_region(pdev, 0);
-err_dis:
- pci_disable_device(pdev);
-err:
- return ret;
-}
-
-static void __devexit
-ath5k_pci_remove(struct pci_dev *pdev)
-{
- struct ath5k_softc *sc = pci_get_drvdata(pdev);
-
- ath5k_debug_finish_device(sc);
- ath5k_detach(pdev, sc->hw);
- ath5k_hw_detach(sc->ah);
- kfree(sc->ah);
- free_irq(pdev->irq, sc);
- pci_iounmap(pdev, sc->iobase);
- pci_release_region(pdev, 0);
- pci_disable_device(pdev);
- ieee80211_free_hw(sc->hw);
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int ath5k_pci_suspend(struct device *dev)
-{
- struct ath5k_softc *sc = pci_get_drvdata(to_pci_dev(dev));
-
- ath5k_led_off(sc);
- return 0;
-}
-
-static int ath5k_pci_resume(struct device *dev)
-{
- struct pci_dev *pdev = to_pci_dev(dev);
- struct ath5k_softc *sc = pci_get_drvdata(pdev);
-
- /*
- * Suspend/Resume resets the PCI configuration space, so we have to
- * re-disable the RETRY_TIMEOUT register (0x41) to keep
- * PCI Tx retries from interfering with C3 CPU state
- */
- pci_write_config_byte(pdev, 0x41, 0);
-
- ath5k_led_enable(sc);
- return 0;
-}
-#endif /* CONFIG_PM_SLEEP */
-
-
/***********************\
* Driver Initialization *
\***********************/
@@ -772,170 +284,6 @@ static int ath5k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *re
return ath_reg_notifier_apply(wiphy, request, regulatory);
}
-static int
-ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
-{
- struct ath5k_softc *sc = hw->priv;
- struct ath5k_hw *ah = sc->ah;
- struct ath_regulatory *regulatory = ath5k_hw_regulatory(ah);
- u8 mac[ETH_ALEN] = {};
- int ret;
-
- ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "devid 0x%x\n", pdev->device);
-
- /*
- * Check if the MAC has multi-rate retry support.
- * We do this by trying to setup a fake extended
- * descriptor. MAC's that don't have support will
- * return false w/o doing anything. MAC's that do
- * support it will return true w/o doing anything.
- */
- ret = ath5k_hw_setup_mrr_tx_desc(ah, NULL, 0, 0, 0, 0, 0, 0);
-
- if (ret < 0)
- goto err;
- if (ret > 0)
- __set_bit(ATH_STAT_MRRETRY, sc->status);
-
- /*
- * Collect the channel list. The 802.11 layer
- * is resposible for filtering this list based
- * on settings like the phy mode and regulatory
- * domain restrictions.
- */
- ret = ath5k_setup_bands(hw);
- if (ret) {
- ATH5K_ERR(sc, "can't get channels\n");
- goto err;
- }
-
- /* NB: setup here so ath5k_rate_update is happy */
- if (test_bit(AR5K_MODE_11A, ah->ah_modes))
- ath5k_setcurmode(sc, AR5K_MODE_11A);
- else
- ath5k_setcurmode(sc, AR5K_MODE_11B);
-
- /*
- * Allocate tx+rx descriptors and populate the lists.
- */
- ret = ath5k_desc_alloc(sc, pdev);
- if (ret) {
- ATH5K_ERR(sc, "can't allocate descriptors\n");
- goto err;
- }
-
- /*
- * Allocate hardware transmit queues: one queue for
- * beacon frames and one data queue for each QoS
- * priority. Note that hw functions handle reseting
- * these queues at the needed time.
- */
- ret = ath5k_beaconq_setup(ah);
- if (ret < 0) {
- ATH5K_ERR(sc, "can't setup a beacon xmit queue\n");
- goto err_desc;
- }
- sc->bhalq = ret;
- sc->cabq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_CAB, 0);
- if (IS_ERR(sc->cabq)) {
- ATH5K_ERR(sc, "can't setup cab queue\n");
- ret = PTR_ERR(sc->cabq);
- goto err_bhal;
- }
-
- sc->txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BK);
- if (IS_ERR(sc->txq)) {
- ATH5K_ERR(sc, "can't setup xmit queue\n");
- ret = PTR_ERR(sc->txq);
- goto err_queues;
- }
-
- tasklet_init(&sc->rxtq, ath5k_tasklet_rx, (unsigned long)sc);
- tasklet_init(&sc->txtq, ath5k_tasklet_tx, (unsigned long)sc);
- tasklet_init(&sc->calib, ath5k_tasklet_calibrate, (unsigned long)sc);
- tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc);
- tasklet_init(&sc->ani_tasklet, ath5k_tasklet_ani, (unsigned long)sc);
-
- INIT_WORK(&sc->reset_work, ath5k_reset_work);
-
- ret = ath5k_eeprom_read_mac(ah, mac);
- if (ret) {
- ATH5K_ERR(sc, "unable to read address from EEPROM: 0x%04x\n",
- sc->pdev->device);
- goto err_queues;
- }
-
- SET_IEEE80211_PERM_ADDR(hw, mac);
- /* All MAC address bits matter for ACKs */
- memcpy(sc->bssidmask, ath_bcast_mac, ETH_ALEN);
- ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask);
-
- regulatory->current_rd = ah->ah_capabilities.cap_eeprom.ee_regdomain;
- ret = ath_regd_init(regulatory, hw->wiphy, ath5k_reg_notifier);
- if (ret) {
- ATH5K_ERR(sc, "can't initialize regulatory system\n");
- goto err_queues;
- }
-
- ret = ieee80211_register_hw(hw);
- if (ret) {
- ATH5K_ERR(sc, "can't register ieee80211 hw\n");
- goto err_queues;
- }
-
- if (!ath_is_world_regd(regulatory))
- regulatory_hint(hw->wiphy, regulatory->alpha2);
-
- ath5k_init_leds(sc);
-
- ath5k_sysfs_register(sc);
-
- return 0;
-err_queues:
- ath5k_txq_release(sc);
-err_bhal:
- ath5k_hw_release_tx_queue(ah, sc->bhalq);
-err_desc:
- ath5k_desc_free(sc, pdev);
-err:
- return ret;
-}
-
-static void
-ath5k_detach(struct pci_dev *pdev, struct ieee80211_hw *hw)
-{
- struct ath5k_softc *sc = hw->priv;
-
- /*
- * NB: the order of these is important:
- * o call the 802.11 layer before detaching ath5k_hw to
- * insure callbacks into the driver to delete global
- * key cache entries can be handled
- * o reclaim the tx queue data structures after calling
- * the 802.11 layer as we'll get called back to reclaim
- * node state and potentially want to use them
- * o to cleanup the tx queues the hal is called, so detach
- * it last
- * XXX: ??? detach ath5k_hw ???
- * Other than that, it's straightforward...
- */
- ieee80211_unregister_hw(hw);
- ath5k_desc_free(sc, pdev);
- ath5k_txq_release(sc);
- ath5k_hw_release_tx_queue(sc->ah, sc->bhalq);
- ath5k_unregister_leds(sc);
-
- ath5k_sysfs_unregister(sc);
- /*
- * NB: can't reclaim these until after ieee80211_ifdetach
- * returns because we'll get called back to reclaim node
- * state and potentially want to use them.
- */
-}
-
-
-
-
/********************\
* Channel/mode setup *
\********************/
@@ -1163,8 +511,101 @@ ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode)
}
}
+struct ath_vif_iter_data {
+ const u8 *hw_macaddr;
+ u8 mask[ETH_ALEN];
+ u8 active_mac[ETH_ALEN]; /* first active MAC */
+ bool need_set_hw_addr;
+ bool found_active;
+ bool any_assoc;
+ enum nl80211_iftype opmode;
+};
+
+static void ath_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
+{
+ struct ath_vif_iter_data *iter_data = data;
+ int i;
+ struct ath5k_vif *avf = (void *)vif->drv_priv;
+
+ if (iter_data->hw_macaddr)
+ for (i = 0; i < ETH_ALEN; i++)
+ iter_data->mask[i] &=
+ ~(iter_data->hw_macaddr[i] ^ mac[i]);
+
+ if (!iter_data->found_active) {
+ iter_data->found_active = true;
+ memcpy(iter_data->active_mac, mac, ETH_ALEN);
+ }
+
+ if (iter_data->need_set_hw_addr && iter_data->hw_macaddr)
+ if (compare_ether_addr(iter_data->hw_macaddr, mac) == 0)
+ iter_data->need_set_hw_addr = false;
+
+ if (!iter_data->any_assoc) {
+ if (avf->assoc)
+ iter_data->any_assoc = true;
+ }
+
+ /* Calculate combined mode - when APs are active, operate in AP mode.
+ * Otherwise use the mode of the new interface. This can currently
+ * only deal with combinations of APs and STAs. Only one ad-hoc
+ * interfaces is allowed above.
+ */
+ if (avf->opmode == NL80211_IFTYPE_AP)
+ iter_data->opmode = NL80211_IFTYPE_AP;
+ else
+ if (iter_data->opmode == NL80211_IFTYPE_UNSPECIFIED)
+ iter_data->opmode = avf->opmode;
+}
+
+static void ath_do_set_opmode(struct ath5k_softc *sc)
+{
+ struct ath5k_hw *ah = sc->ah;
+ ath5k_hw_set_opmode(ah, sc->opmode);
+ ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "mode setup opmode %d (%s)\n",
+ sc->opmode, ath_opmode_to_string(sc->opmode));
+}
+
+void ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc,
+ struct ieee80211_vif *vif)
+{
+ struct ath_common *common = ath5k_hw_common(sc->ah);
+ struct ath_vif_iter_data iter_data;
+
+ /*
+ * Use the hardware MAC address as reference, the hardware uses it
+ * together with the BSSID mask when matching addresses.
+ */
+ iter_data.hw_macaddr = common->macaddr;
+ memset(&iter_data.mask, 0xff, ETH_ALEN);
+ iter_data.found_active = false;
+ iter_data.need_set_hw_addr = true;
+ iter_data.opmode = NL80211_IFTYPE_UNSPECIFIED;
+
+ if (vif)
+ ath_vif_iter(&iter_data, vif->addr, vif);
+
+ /* Get list of all active MAC addresses */
+ ieee80211_iterate_active_interfaces_atomic(sc->hw, ath_vif_iter,
+ &iter_data);
+ memcpy(sc->bssidmask, iter_data.mask, ETH_ALEN);
+
+ sc->opmode = iter_data.opmode;
+ if (sc->opmode == NL80211_IFTYPE_UNSPECIFIED)
+ /* Nothing active, default to station mode */
+ sc->opmode = NL80211_IFTYPE_STATION;
+
+ ath_do_set_opmode(sc);
+
+ if (iter_data.need_set_hw_addr && iter_data.found_active)
+ ath5k_hw_set_lladdr(sc->ah, iter_data.active_mac);
+
+ if (ath5k_hw_hasbssidmask(sc->ah))
+ ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask);
+}
+
static void
-ath5k_mode_setup(struct ath5k_softc *sc)
+ath5k_mode_setup(struct ath5k_softc *sc, struct ieee80211_vif *vif)
{
struct ath5k_hw *ah = sc->ah;
u32 rfilt;
@@ -1172,15 +613,9 @@ ath5k_mode_setup(struct ath5k_softc *sc)
/* configure rx filter */
rfilt = sc->filter_flags;
ath5k_hw_set_rx_filter(ah, rfilt);
-
- if (ath5k_hw_hasbssidmask(ah))
- ath5k_hw_set_bssid_mask(ah, sc->bssidmask);
-
- /* configure operational mode */
- ath5k_hw_set_opmode(ah, sc->opmode);
-
- ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "mode setup opmode %d\n", sc->opmode);
ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt);
+
+ ath5k_update_bssid_mask_and_opmode(sc, vif);
}
static inline int
@@ -1352,13 +787,13 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
flags |= AR5K_TXDESC_RTSENA;
cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value;
duration = le16_to_cpu(ieee80211_rts_duration(sc->hw,
- sc->vif, pktlen, info));
+ info->control.vif, pktlen, info));
}
if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
flags |= AR5K_TXDESC_CTSENA;
cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value;
duration = le16_to_cpu(ieee80211_ctstoself_duration(sc->hw,
- sc->vif, pktlen, info));
+ info->control.vif, pktlen, info));
}
ret = ah->ah_setup_tx_desc(ah, ds, pktlen,
ieee80211_get_hdrlen_from_skb(skb), padsize,
@@ -1391,6 +826,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
spin_lock_bh(&txq->lock);
list_add_tail(&bf->list, &txq->q);
+ txq->txq_len++;
if (txq->link == NULL) /* is this first packet? */
ath5k_hw_set_txdp(ah, txq->qnum, bf->daddr);
else /* no, so only link it */
@@ -1459,10 +895,13 @@ ath5k_desc_alloc(struct ath5k_softc *sc, struct pci_dev *pdev)
list_add_tail(&bf->list, &sc->txbuf);
}
- /* beacon buffer */
- bf->desc = ds;
- bf->daddr = da;
- sc->bbuf = bf;
+ /* beacon buffers */
+ INIT_LIST_HEAD(&sc->bcbuf);
+ for (i = 0; i < ATH_BCBUF; i++, bf++, ds++, da += sizeof(*ds)) {
+ bf->desc = ds;
+ bf->daddr = da;
+ list_add_tail(&bf->list, &sc->bcbuf);
+ }
return 0;
err_free:
@@ -1477,11 +916,12 @@ ath5k_desc_free(struct ath5k_softc *sc, struct pci_dev *pdev)
{
struct ath5k_buf *bf;
- ath5k_txbuf_free_skb(sc, sc->bbuf);
list_for_each_entry(bf, &sc->txbuf, list)
ath5k_txbuf_free_skb(sc, bf);
list_for_each_entry(bf, &sc->rxbuf, list)
ath5k_rxbuf_free_skb(sc, bf);
+ list_for_each_entry(bf, &sc->bcbuf, list)
+ ath5k_txbuf_free_skb(sc, bf);
/* Free memory associated with all descriptors */
pci_free_consistent(pdev, sc->desc_len, sc->desc, sc->desc_daddr);
@@ -1490,13 +930,9 @@ ath5k_desc_free(struct ath5k_softc *sc, struct pci_dev *pdev)
kfree(sc->bufptr);
sc->bufptr = NULL;
- sc->bbuf = NULL;
}
-
-
-
/**************\
* Queues setup *
\**************/
@@ -1509,16 +945,18 @@ ath5k_txq_setup(struct ath5k_softc *sc,
struct ath5k_txq *txq;
struct ath5k_txq_info qi = {
.tqi_subtype = subtype,
- .tqi_aifs = AR5K_TXQ_USEDEFAULT,
- .tqi_cw_min = AR5K_TXQ_USEDEFAULT,
- .tqi_cw_max = AR5K_TXQ_USEDEFAULT
+ /* XXX: default values not correct for B and XR channels,
+ * but who cares? */
+ .tqi_aifs = AR5K_TUNE_AIFS,
+ .tqi_cw_min = AR5K_TUNE_CWMIN,
+ .tqi_cw_max = AR5K_TUNE_CWMAX
};
int qnum;
/*
* Enable interrupts only for EOL and DESC conditions.
* We mark tx descriptors to receive a DESC interrupt
- * when a tx queue gets deep; otherwise waiting for the
+ * when a tx queue gets deep; otherwise we wait for the
* EOL to reap descriptors. Note that this is done to
* reduce interrupt load and this only defers reaping
* descriptors, never transmitting frames. Aside from
@@ -1550,6 +988,9 @@ ath5k_txq_setup(struct ath5k_softc *sc,
INIT_LIST_HEAD(&txq->q);
spin_lock_init(&txq->lock);
txq->setup = true;
+ txq->txq_len = 0;
+ txq->txq_poll_mark = false;
+ txq->txq_stuck = 0;
}
return &sc->txqs[qnum];
}
@@ -1558,9 +999,11 @@ static int
ath5k_beaconq_setup(struct ath5k_hw *ah)
{
struct ath5k_txq_info qi = {
- .tqi_aifs = AR5K_TXQ_USEDEFAULT,
- .tqi_cw_min = AR5K_TXQ_USEDEFAULT,
- .tqi_cw_max = AR5K_TXQ_USEDEFAULT,
+ /* XXX: default values not correct for B and XR channels,
+ * but who cares? */
+ .tqi_aifs = AR5K_TUNE_AIFS,
+ .tqi_cw_min = AR5K_TUNE_CWMIN,
+ .tqi_cw_max = AR5K_TUNE_CWMAX,
/* NB: for dynamic turbo, don't enable any other interrupts */
.tqi_flags = AR5K_TXQ_FLAG_TXDESCINT_ENABLE
};
@@ -1594,7 +1037,7 @@ ath5k_beaconq_config(struct ath5k_softc *sc)
*/
qi.tqi_aifs = 0;
qi.tqi_cw_min = 0;
- qi.tqi_cw_max = 2 * ah->ah_cw_min;
+ qi.tqi_cw_max = 2 * AR5K_TUNE_CWMIN;
}
ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
@@ -1644,9 +1087,11 @@ ath5k_txq_drainq(struct ath5k_softc *sc, struct ath5k_txq *txq)
spin_lock_bh(&sc->txbuflock);
list_move_tail(&bf->list, &sc->txbuf);
sc->txbuf_len++;
+ txq->txq_len--;
spin_unlock_bh(&sc->txbuflock);
}
txq->link = NULL;
+ txq->txq_poll_mark = false;
spin_unlock_bh(&txq->lock);
}
@@ -1696,8 +1141,6 @@ ath5k_txq_release(struct ath5k_softc *sc)
}
-
-
/*************\
* RX Handling *
\*************/
@@ -1713,7 +1156,7 @@ ath5k_rx_start(struct ath5k_softc *sc)
struct ath5k_buf *bf;
int ret;
- common->rx_bufsize = roundup(IEEE80211_MAX_LEN, common->cachelsz);
+ common->rx_bufsize = roundup(IEEE80211_MAX_FRAME_LEN, common->cachelsz);
ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rx_bufsize %u\n",
common->cachelsz, common->rx_bufsize);
@@ -1732,7 +1175,7 @@ ath5k_rx_start(struct ath5k_softc *sc)
spin_unlock_bh(&sc->rxbuflock);
ath5k_hw_start_rx_dma(ah); /* enable recv descriptors */
- ath5k_mode_setup(sc); /* set filters, etc. */
+ ath5k_mode_setup(sc, NULL); /* set filters, etc. */
ath5k_hw_start_rx_pcu(ah); /* re-enable PCU/DMA engine */
return 0;
@@ -1840,6 +1283,15 @@ ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb,
*/
if (hw_tu >= sc->nexttbtt)
ath5k_beacon_update_timers(sc, bc_tstamp);
+
+ /* Check if the beacon timers are still correct, because a TSF
+ * update might have created a window between them - for a
+ * longer description see the comment of this function: */
+ if (!ath5k_hw_check_beacon_timers(sc->ah, sc->bintval)) {
+ ath5k_beacon_update_timers(sc, bc_tstamp);
+ ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
+ "fixed beacon timers after beacon receive\n");
+ }
}
}
@@ -1863,7 +1315,7 @@ ath5k_update_beacon_rssi(struct ath5k_softc *sc, struct sk_buff *skb, int rssi)
}
/*
- * Compute padding position. skb must contains an IEEE 802.11 frame
+ * Compute padding position. skb must contain an IEEE 802.11 frame
*/
static int ath5k_common_padpos(struct sk_buff *skb)
{
@@ -1882,10 +1334,9 @@ static int ath5k_common_padpos(struct sk_buff *skb)
}
/*
- * This function expects a 802.11 frame and returns the number of
- * bytes added, or -1 if we don't have enought header room.
+ * This function expects an 802.11 frame and returns the number of
+ * bytes added, or -1 if we don't have enough header room.
*/
-
static int ath5k_add_padding(struct sk_buff *skb)
{
int padpos = ath5k_common_padpos(skb);
@@ -1905,10 +1356,18 @@ static int ath5k_add_padding(struct sk_buff *skb)
}
/*
- * This function expects a 802.11 frame and returns the number of
- * bytes removed
+ * The MAC header is padded to have 32-bit boundary if the
+ * packet payload is non-zero. The general calculation for
+ * padsize would take into account odd header lengths:
+ * padsize = 4 - (hdrlen & 3); however, since only
+ * even-length headers are used, padding can only be 0 or 2
+ * bytes and we can optimize this a bit. We must not try to
+ * remove padding from short control frames that do not have a
+ * payload.
+ *
+ * This function expects an 802.11 frame and returns the number of
+ * bytes removed.
*/
-
static int ath5k_remove_padding(struct sk_buff *skb)
{
int padpos = ath5k_common_padpos(skb);
@@ -1929,14 +1388,6 @@ ath5k_receive_frame(struct ath5k_softc *sc, struct sk_buff *skb,
{
struct ieee80211_rx_status *rxs;
- /* The MAC header is padded to have 32-bit boundary if the
- * packet payload is non-zero. The general calculation for
- * padsize would take into account odd header lengths:
- * padsize = (4 - hdrlen % 4) % 4; However, since only
- * even-length headers are used, padding can only be 0 or 2
- * bytes and we can optimize this a bit. In addition, we must
- * not try to remove padding from short control frames that do
- * not have payload. */
ath5k_remove_padding(skb);
rxs = IEEE80211_SKB_RXCB(skb);
@@ -2007,6 +1458,7 @@ static bool
ath5k_receive_frame_ok(struct ath5k_softc *sc, struct ath5k_rx_status *rs)
{
sc->stats.rx_all_count++;
+ sc->stats.rx_bytes_count += rs->rs_datalen;
if (unlikely(rs->rs_status)) {
if (rs->rs_status & AR5K_RXERR_CRC)
@@ -2040,9 +1492,8 @@ ath5k_receive_frame_ok(struct ath5k_softc *sc, struct ath5k_rx_status *rs)
return true;
}
- /* let crypto-error packets fall through in MNTR */
- if ((rs->rs_status & ~(AR5K_RXERR_DECRYPT|AR5K_RXERR_MIC)) ||
- sc->opmode != NL80211_IFTYPE_MONITOR)
+ /* reject any frames with non-crypto errors */
+ if (rs->rs_status & ~(AR5K_RXERR_DECRYPT))
return false;
}
@@ -2123,6 +1574,118 @@ unlock:
* TX Handling *
\*************/
+static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
+ struct ath5k_txq *txq)
+{
+ struct ath5k_softc *sc = hw->priv;
+ struct ath5k_buf *bf;
+ unsigned long flags;
+ int padsize;
+
+ ath5k_debug_dump_skb(sc, skb, "TX ", 1);
+
+ /*
+ * The hardware expects the header padded to 4 byte boundaries.
+ * If this is not the case, we add the padding after the header.
+ */
+ padsize = ath5k_add_padding(skb);
+ if (padsize < 0) {
+ ATH5K_ERR(sc, "tx hdrlen not %%4: not enough"
+ " headroom to pad");
+ goto drop_packet;
+ }
+
+ if (txq->txq_len >= ATH5K_TXQ_LEN_MAX)
+ ieee80211_stop_queue(hw, txq->qnum);
+
+ spin_lock_irqsave(&sc->txbuflock, flags);
+ if (list_empty(&sc->txbuf)) {
+ ATH5K_ERR(sc, "no further txbuf available, dropping packet\n");
+ spin_unlock_irqrestore(&sc->txbuflock, flags);
+ ieee80211_stop_queues(hw);
+ goto drop_packet;
+ }
+ bf = list_first_entry(&sc->txbuf, struct ath5k_buf, list);
+ list_del(&bf->list);
+ sc->txbuf_len--;
+ if (list_empty(&sc->txbuf))
+ ieee80211_stop_queues(hw);
+ spin_unlock_irqrestore(&sc->txbuflock, flags);
+
+ bf->skb = skb;
+
+ if (ath5k_txbuf_setup(sc, bf, txq, padsize)) {
+ bf->skb = NULL;
+ spin_lock_irqsave(&sc->txbuflock, flags);
+ list_add_tail(&bf->list, &sc->txbuf);
+ sc->txbuf_len++;
+ spin_unlock_irqrestore(&sc->txbuflock, flags);
+ goto drop_packet;
+ }
+ return NETDEV_TX_OK;
+
+drop_packet:
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+}
+
+static void
+ath5k_tx_frame_completed(struct ath5k_softc *sc, struct sk_buff *skb,
+ struct ath5k_tx_status *ts)
+{
+ struct ieee80211_tx_info *info;
+ int i;
+
+ sc->stats.tx_all_count++;
+ sc->stats.tx_bytes_count += skb->len;
+ info = IEEE80211_SKB_CB(skb);
+
+ ieee80211_tx_info_clear_status(info);
+ for (i = 0; i < 4; i++) {
+ struct ieee80211_tx_rate *r =
+ &info->status.rates[i];
+
+ if (ts->ts_rate[i]) {
+ r->idx = ath5k_hw_to_driver_rix(sc, ts->ts_rate[i]);
+ r->count = ts->ts_retry[i];
+ } else {
+ r->idx = -1;
+ r->count = 0;
+ }
+ }
+
+ /* count the successful attempt as well */
+ info->status.rates[ts->ts_final_idx].count++;
+
+ if (unlikely(ts->ts_status)) {
+ sc->stats.ack_fail++;
+ if (ts->ts_status & AR5K_TXERR_FILT) {
+ info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
+ sc->stats.txerr_filt++;
+ }
+ if (ts->ts_status & AR5K_TXERR_XRETRY)
+ sc->stats.txerr_retry++;
+ if (ts->ts_status & AR5K_TXERR_FIFO)
+ sc->stats.txerr_fifo++;
+ } else {
+ info->flags |= IEEE80211_TX_STAT_ACK;
+ info->status.ack_signal = ts->ts_rssi;
+ }
+
+ /*
+ * Remove MAC header padding before giving the frame
+ * back to mac80211.
+ */
+ ath5k_remove_padding(skb);
+
+ if (ts->ts_antenna > 0 && ts->ts_antenna < 5)
+ sc->stats.antenna_tx[ts->ts_antenna]++;
+ else
+ sc->stats.antenna_tx[0]++; /* invalid */
+
+ ieee80211_tx_status(sc->hw, skb);
+}
+
static void
ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
{
@@ -2130,96 +1693,51 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
struct ath5k_buf *bf, *bf0;
struct ath5k_desc *ds;
struct sk_buff *skb;
- struct ieee80211_tx_info *info;
- int i, ret;
+ int ret;
spin_lock(&txq->lock);
list_for_each_entry_safe(bf, bf0, &txq->q, list) {
- ds = bf->desc;
- /*
- * It's possible that the hardware can say the buffer is
- * completed when it hasn't yet loaded the ds_link from
- * host memory and moved on. If there are more TX
- * descriptors in the queue, wait for TXDP to change
- * before processing this one.
- */
- if (ath5k_hw_get_txdp(sc->ah, txq->qnum) == bf->daddr &&
- !list_is_last(&bf->list, &txq->q))
- break;
+ txq->txq_poll_mark = false;
- ret = sc->ah->ah_proc_tx_desc(sc->ah, ds, &ts);
- if (unlikely(ret == -EINPROGRESS))
- break;
- else if (unlikely(ret)) {
- ATH5K_ERR(sc, "error %d while processing queue %u\n",
- ret, txq->qnum);
- break;
- }
-
- sc->stats.tx_all_count++;
- skb = bf->skb;
- info = IEEE80211_SKB_CB(skb);
- bf->skb = NULL;
-
- pci_unmap_single(sc->pdev, bf->skbaddr, skb->len,
- PCI_DMA_TODEVICE);
+ /* skb might already have been processed last time. */
+ if (bf->skb != NULL) {
+ ds = bf->desc;
- ieee80211_tx_info_clear_status(info);
- for (i = 0; i < 4; i++) {
- struct ieee80211_tx_rate *r =
- &info->status.rates[i];
-
- if (ts.ts_rate[i]) {
- r->idx = ath5k_hw_to_driver_rix(sc, ts.ts_rate[i]);
- r->count = ts.ts_retry[i];
- } else {
- r->idx = -1;
- r->count = 0;
+ ret = sc->ah->ah_proc_tx_desc(sc->ah, ds, &ts);
+ if (unlikely(ret == -EINPROGRESS))
+ break;
+ else if (unlikely(ret)) {
+ ATH5K_ERR(sc,
+ "error %d while processing "
+ "queue %u\n", ret, txq->qnum);
+ break;
}
- }
- /* count the successful attempt as well */
- info->status.rates[ts.ts_final_idx].count++;
-
- if (unlikely(ts.ts_status)) {
- sc->stats.ack_fail++;
- if (ts.ts_status & AR5K_TXERR_FILT) {
- info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
- sc->stats.txerr_filt++;
- }
- if (ts.ts_status & AR5K_TXERR_XRETRY)
- sc->stats.txerr_retry++;
- if (ts.ts_status & AR5K_TXERR_FIFO)
- sc->stats.txerr_fifo++;
- } else {
- info->flags |= IEEE80211_TX_STAT_ACK;
- info->status.ack_signal = ts.ts_rssi;
+ skb = bf->skb;
+ bf->skb = NULL;
+ pci_unmap_single(sc->pdev, bf->skbaddr, skb->len,
+ PCI_DMA_TODEVICE);
+ ath5k_tx_frame_completed(sc, skb, &ts);
}
/*
- * Remove MAC header padding before giving the frame
- * back to mac80211.
+ * It's possible that the hardware can say the buffer is
+ * completed when it hasn't yet loaded the ds_link from
+ * host memory and moved on.
+ * Always keep the last descriptor to avoid HW races...
*/
- ath5k_remove_padding(skb);
-
- if (ts.ts_antenna > 0 && ts.ts_antenna < 5)
- sc->stats.antenna_tx[ts.ts_antenna]++;
- else
- sc->stats.antenna_tx[0]++; /* invalid */
-
- ieee80211_tx_status(sc->hw, skb);
-
- spin_lock(&sc->txbuflock);
- list_move_tail(&bf->list, &sc->txbuf);
- sc->txbuf_len++;
- spin_unlock(&sc->txbuflock);
+ if (ath5k_hw_get_txdp(sc->ah, txq->qnum) != bf->daddr) {
+ spin_lock(&sc->txbuflock);
+ list_move_tail(&bf->list, &sc->txbuf);
+ sc->txbuf_len++;
+ txq->txq_len--;
+ spin_unlock(&sc->txbuflock);
+ }
}
- if (likely(list_empty(&txq->q)))
- txq->link = NULL;
spin_unlock(&txq->lock);
- if (sc->txbuf_len > ATH_TXBUF / 5)
- ieee80211_wake_queues(sc->hw);
+ if (txq->txq_len < ATH5K_TXQ_LEN_LOW && txq->qnum < 4)
+ ieee80211_wake_queue(sc->hw, txq->qnum);
}
static void
@@ -2285,10 +1803,11 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
* default antenna which is supposed to be an omni.
*
* Note2: On sectored scenarios it's possible to have
- * multiple antennas (1omni -the default- and 14 sectors)
- * so if we choose to actually support this mode we need
- * to allow user to set how many antennas we have and tweak
- * the code below to send beacons on all of them.
+ * multiple antennas (1 omni -- the default -- and 14
+ * sectors), so if we choose to actually support this
+ * mode, we need to allow the user to set how many antennas
+ * we have and tweak the code below to send beacons
+ * on all of them.
*/
if (ah->ah_ant_mode == AR5K_ANTMODE_SECTOR_AP)
antenna = sc->bsent & 4 ? 2 : 1;
@@ -2314,6 +1833,44 @@ err_unmap:
}
/*
+ * Updates the beacon that is sent by ath5k_beacon_send. For adhoc,
+ * this is called only once at config_bss time, for AP we do it every
+ * SWBA interrupt so that the TIM will reflect buffered frames.
+ *
+ * Called with the beacon lock.
+ */
+static int
+ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+{
+ int ret;
+ struct ath5k_softc *sc = hw->priv;
+ struct ath5k_vif *avf = (void *)vif->drv_priv;
+ struct sk_buff *skb;
+
+ if (WARN_ON(!vif)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ skb = ieee80211_beacon_get(hw, vif);
+
+ if (!skb) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ath5k_debug_dump_skb(sc, skb, "BC ", 1);
+
+ ath5k_txbuf_free_skb(sc, avf->bbuf);
+ avf->bbuf->skb = skb;
+ ret = ath5k_beacon_setup(sc, avf->bbuf);
+ if (ret)
+ avf->bbuf->skb = NULL;
+out:
+ return ret;
+}
+
+/*
* Transmit a beacon frame at SWBA. Dynamic updates to the
* frame contents are done as needed and the slot time is
* also adjusted based on current state.
@@ -2324,20 +1881,17 @@ err_unmap:
static void
ath5k_beacon_send(struct ath5k_softc *sc)
{
- struct ath5k_buf *bf = sc->bbuf;
struct ath5k_hw *ah = sc->ah;
+ struct ieee80211_vif *vif;
+ struct ath5k_vif *avf;
+ struct ath5k_buf *bf;
struct sk_buff *skb;
ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "in beacon_send\n");
- if (unlikely(bf->skb == NULL || sc->opmode == NL80211_IFTYPE_STATION ||
- sc->opmode == NL80211_IFTYPE_MONITOR)) {
- ATH5K_WARN(sc, "bf=%p bf_skb=%p\n", bf, bf ? bf->skb : NULL);
- return;
- }
/*
* Check if the previous beacon has gone out. If
- * not don't don't try to post another, skip this
+ * not, don't don't try to post another: skip this
* period and wait for the next. Missed beacons
* indicate a problem and should not occur. If we
* miss too many consecutive beacons reset the device.
@@ -2363,6 +1917,28 @@ ath5k_beacon_send(struct ath5k_softc *sc)
sc->bmisscount = 0;
}
+ if (sc->opmode == NL80211_IFTYPE_AP && sc->num_ap_vifs > 1) {
+ u64 tsf = ath5k_hw_get_tsf64(ah);
+ u32 tsftu = TSF_TO_TU(tsf);
+ int slot = ((tsftu % sc->bintval) * ATH_BCBUF) / sc->bintval;
+ vif = sc->bslot[(slot + 1) % ATH_BCBUF];
+ ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
+ "tsf %llx tsftu %x intval %u slot %u vif %p\n",
+ (unsigned long long)tsf, tsftu, sc->bintval, slot, vif);
+ } else /* only one interface */
+ vif = sc->bslot[0];
+
+ if (!vif)
+ return;
+
+ avf = (void *)vif->drv_priv;
+ bf = avf->bbuf;
+ if (unlikely(bf->skb == NULL || sc->opmode == NL80211_IFTYPE_STATION ||
+ sc->opmode == NL80211_IFTYPE_MONITOR)) {
+ ATH5K_WARN(sc, "bf=%p bf_skb=%p\n", bf, bf ? bf->skb : NULL);
+ return;
+ }
+
/*
* Stop any current dma and put the new frame on the queue.
* This should never fail since we check above that no frames
@@ -2375,23 +1951,22 @@ ath5k_beacon_send(struct ath5k_softc *sc)
/* refresh the beacon for AP mode */
if (sc->opmode == NL80211_IFTYPE_AP)
- ath5k_beacon_update(sc->hw, sc->vif);
+ ath5k_beacon_update(sc->hw, vif);
ath5k_hw_set_txdp(ah, sc->bhalq, bf->daddr);
ath5k_hw_start_tx_dma(ah, sc->bhalq);
ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n",
sc->bhalq, (unsigned long long)bf->daddr, bf->desc);
- skb = ieee80211_get_buffered_bc(sc->hw, sc->vif);
+ skb = ieee80211_get_buffered_bc(sc->hw, vif);
while (skb) {
ath5k_tx_queue(sc->hw, skb, sc->cabq);
- skb = ieee80211_get_buffered_bc(sc->hw, sc->vif);
+ skb = ieee80211_get_buffered_bc(sc->hw, vif);
}
sc->bsent++;
}
-
/**
* ath5k_beacon_update_timers - update beacon timers
*
@@ -2416,6 +1991,12 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf)
u64 hw_tsf;
intval = sc->bintval & AR5K_BEACON_PERIOD;
+ if (sc->opmode == NL80211_IFTYPE_AP && sc->num_ap_vifs > 1) {
+ intval /= ATH_BCBUF; /* staggered multi-bss beacons */
+ if (intval < 15)
+ ATH5K_WARN(sc, "intval %u is too low, min 15\n",
+ intval);
+ }
if (WARN_ON(!intval))
return;
@@ -2426,8 +2007,11 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf)
hw_tsf = ath5k_hw_get_tsf64(ah);
hw_tu = TSF_TO_TU(hw_tsf);
-#define FUDGE 3
- /* we use FUDGE to make sure the next TBTT is ahead of the current TU */
+#define FUDGE AR5K_TUNE_SW_BEACON_RESP + 3
+ /* We use FUDGE to make sure the next TBTT is ahead of the current TU.
+ * Since we later substract AR5K_TUNE_SW_BEACON_RESP (10) in the timer
+ * configuration we need to make sure it is bigger than that. */
+
if (bc_tsf == -1) {
/*
* no beacons received, called internally.
@@ -2493,7 +2077,6 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf)
intval & AR5K_BEACON_RESET_TSF ? "AR5K_BEACON_RESET_TSF" : "");
}
-
/**
* ath5k_beacon_config - Configure the beacon queues and interrupts
*
@@ -2572,155 +2155,6 @@ static void ath5k_tasklet_beacon(unsigned long data)
* Interrupt handling *
\********************/
-static int
-ath5k_init(struct ath5k_softc *sc)
-{
- struct ath5k_hw *ah = sc->ah;
- int ret, i;
-
- mutex_lock(&sc->lock);
-
- ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mode %d\n", sc->opmode);
-
- /*
- * Stop anything previously setup. This is safe
- * no matter this is the first time through or not.
- */
- ath5k_stop_locked(sc);
-
- /*
- * The basic interface to setting the hardware in a good
- * state is ``reset''. On return the hardware is known to
- * be powered up and with interrupts disabled. This must
- * be followed by initialization of the appropriate bits
- * and then setup of the interrupt mask.
- */
- sc->curchan = sc->hw->conf.channel;
- sc->curband = &sc->sbands[sc->curchan->band];
- sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL |
- AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL |
- AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_MIB;
-
- ret = ath5k_reset(sc, NULL);
- if (ret)
- goto done;
-
- ath5k_rfkill_hw_start(ah);
-
- /*
- * Reset the key cache since some parts do not reset the
- * contents on initial power up or resume from suspend.
- */
- for (i = 0; i < AR5K_KEYTABLE_SIZE; i++)
- ath5k_hw_reset_key(ah, i);
-
- ath5k_hw_set_ack_bitrate_high(ah, true);
- ret = 0;
-done:
- mmiowb();
- mutex_unlock(&sc->lock);
- return ret;
-}
-
-static int
-ath5k_stop_locked(struct ath5k_softc *sc)
-{
- struct ath5k_hw *ah = sc->ah;
-
- ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "invalid %u\n",
- test_bit(ATH_STAT_INVALID, sc->status));
-
- /*
- * Shutdown the hardware and driver:
- * stop output from above
- * disable interrupts
- * turn off timers
- * turn off the radio
- * clear transmit machinery
- * clear receive machinery
- * drain and release tx queues
- * reclaim beacon resources
- * power down hardware
- *
- * Note that some of this work is not possible if the
- * hardware is gone (invalid).
- */
- ieee80211_stop_queues(sc->hw);
-
- if (!test_bit(ATH_STAT_INVALID, sc->status)) {
- ath5k_led_off(sc);
- ath5k_hw_set_imr(ah, 0);
- synchronize_irq(sc->pdev->irq);
- }
- ath5k_txq_cleanup(sc);
- if (!test_bit(ATH_STAT_INVALID, sc->status)) {
- ath5k_rx_stop(sc);
- ath5k_hw_phy_disable(ah);
- }
-
- return 0;
-}
-
-static void stop_tasklets(struct ath5k_softc *sc)
-{
- tasklet_kill(&sc->rxtq);
- tasklet_kill(&sc->txtq);
- tasklet_kill(&sc->calib);
- tasklet_kill(&sc->beacontq);
- tasklet_kill(&sc->ani_tasklet);
-}
-
-/*
- * Stop the device, grabbing the top-level lock to protect
- * against concurrent entry through ath5k_init (which can happen
- * if another thread does a system call and the thread doing the
- * stop is preempted).
- */
-static int
-ath5k_stop_hw(struct ath5k_softc *sc)
-{
- int ret;
-
- mutex_lock(&sc->lock);
- ret = ath5k_stop_locked(sc);
- if (ret == 0 && !test_bit(ATH_STAT_INVALID, sc->status)) {
- /*
- * Don't set the card in full sleep mode!
- *
- * a) When the device is in this state it must be carefully
- * woken up or references to registers in the PCI clock
- * domain may freeze the bus (and system). This varies
- * by chip and is mostly an issue with newer parts
- * (madwifi sources mentioned srev >= 0x78) that go to
- * sleep more quickly.
- *
- * b) On older chips full sleep results a weird behaviour
- * during wakeup. I tested various cards with srev < 0x78
- * and they don't wake up after module reload, a second
- * module reload is needed to bring the card up again.
- *
- * Until we figure out what's going on don't enable
- * full chip reset on any chip (this is what Legacy HAL
- * and Sam's HAL do anyway). Instead Perform a full reset
- * on the device (same as initial state after attach) and
- * leave it idle (keep MAC/BB on warm reset) */
- ret = ath5k_hw_on_hold(sc->ah);
-
- ATH5K_DBG(sc, ATH5K_DEBUG_RESET,
- "putting device to sleep\n");
- }
- ath5k_txbuf_free_skb(sc, sc->bbuf);
-
- mmiowb();
- mutex_unlock(&sc->lock);
-
- stop_tasklets(sc);
-
- ath5k_rfkill_hw_stop(sc->ah);
-
- return ret;
-}
-
static void
ath5k_intr_calibration_poll(struct ath5k_hw *ah)
{
@@ -2857,14 +2291,13 @@ ath5k_tasklet_calibrate(unsigned long data)
sc->curchan->center_freq));
/* Noise floor calibration interrupts rx/tx path while I/Q calibration
- * doesn't. We stop the queues so that calibration doesn't interfere
- * with TX and don't run it as often */
+ * doesn't.
+ * TODO: We should stop TX here, so that it doesn't interfere.
+ * Note that stopping the queues is not enough to stop TX! */
if (time_is_before_eq_jiffies(ah->ah_cal_next_nf)) {
ah->ah_cal_next_nf = jiffies +
msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_NF);
- ieee80211_stop_queues(sc->hw);
ath5k_hw_update_noise_floor(ah);
- ieee80211_wake_queues(sc->hw);
}
ah->ah_cal_mask &= ~AR5K_CALIBRATION_FULL;
@@ -2883,71 +2316,208 @@ ath5k_tasklet_ani(unsigned long data)
}
-/********************\
-* Mac80211 functions *
-\********************/
+static void
+ath5k_tx_complete_poll_work(struct work_struct *work)
+{
+ struct ath5k_softc *sc = container_of(work, struct ath5k_softc,
+ tx_complete_work.work);
+ struct ath5k_txq *txq;
+ int i;
+ bool needreset = false;
+
+ for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) {
+ if (sc->txqs[i].setup) {
+ txq = &sc->txqs[i];
+ spin_lock_bh(&txq->lock);
+ if (txq->txq_len > 1) {
+ if (txq->txq_poll_mark) {
+ ATH5K_DBG(sc, ATH5K_DEBUG_XMIT,
+ "TX queue stuck %d\n",
+ txq->qnum);
+ needreset = true;
+ txq->txq_stuck++;
+ spin_unlock_bh(&txq->lock);
+ break;
+ } else {
+ txq->txq_poll_mark = true;
+ }
+ }
+ spin_unlock_bh(&txq->lock);
+ }
+ }
+
+ if (needreset) {
+ ATH5K_DBG(sc, ATH5K_DEBUG_RESET,
+ "TX queues stuck, resetting\n");
+ ath5k_reset(sc, sc->curchan);
+ }
+
+ ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,
+ msecs_to_jiffies(ATH5K_TX_COMPLETE_POLL_INT));
+}
+
+
+/*************************\
+* Initialization routines *
+\*************************/
static int
-ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+ath5k_stop_locked(struct ath5k_softc *sc)
{
- struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = sc->ah;
+
+ ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "invalid %u\n",
+ test_bit(ATH_STAT_INVALID, sc->status));
+
+ /*
+ * Shutdown the hardware and driver:
+ * stop output from above
+ * disable interrupts
+ * turn off timers
+ * turn off the radio
+ * clear transmit machinery
+ * clear receive machinery
+ * drain and release tx queues
+ * reclaim beacon resources
+ * power down hardware
+ *
+ * Note that some of this work is not possible if the
+ * hardware is gone (invalid).
+ */
+ ieee80211_stop_queues(sc->hw);
- return ath5k_tx_queue(hw, skb, sc->txq);
+ if (!test_bit(ATH_STAT_INVALID, sc->status)) {
+ ath5k_led_off(sc);
+ ath5k_hw_set_imr(ah, 0);
+ synchronize_irq(sc->pdev->irq);
+ }
+ ath5k_txq_cleanup(sc);
+ if (!test_bit(ATH_STAT_INVALID, sc->status)) {
+ ath5k_rx_stop(sc);
+ ath5k_hw_phy_disable(ah);
+ }
+
+ return 0;
}
-static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
- struct ath5k_txq *txq)
+static int
+ath5k_init(struct ath5k_softc *sc)
{
- struct ath5k_softc *sc = hw->priv;
- struct ath5k_buf *bf;
- unsigned long flags;
- int padsize;
+ struct ath5k_hw *ah = sc->ah;
+ struct ath_common *common = ath5k_hw_common(ah);
+ int ret, i;
- ath5k_debug_dump_skb(sc, skb, "TX ", 1);
+ mutex_lock(&sc->lock);
- if (sc->opmode == NL80211_IFTYPE_MONITOR)
- ATH5K_DBG(sc, ATH5K_DEBUG_XMIT, "tx in monitor (scan?)\n");
+ ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mode %d\n", sc->opmode);
/*
- * the hardware expects the header padded to 4 byte boundaries
- * if this is not the case we add the padding after the header
+ * Stop anything previously setup. This is safe
+ * no matter this is the first time through or not.
*/
- padsize = ath5k_add_padding(skb);
- if (padsize < 0) {
- ATH5K_ERR(sc, "tx hdrlen not %%4: not enough"
- " headroom to pad");
- goto drop_packet;
- }
+ ath5k_stop_locked(sc);
- spin_lock_irqsave(&sc->txbuflock, flags);
- if (list_empty(&sc->txbuf)) {
- ATH5K_ERR(sc, "no further txbuf available, dropping packet\n");
- spin_unlock_irqrestore(&sc->txbuflock, flags);
- ieee80211_stop_queue(hw, skb_get_queue_mapping(skb));
- goto drop_packet;
- }
- bf = list_first_entry(&sc->txbuf, struct ath5k_buf, list);
- list_del(&bf->list);
- sc->txbuf_len--;
- if (list_empty(&sc->txbuf))
- ieee80211_stop_queues(hw);
- spin_unlock_irqrestore(&sc->txbuflock, flags);
+ /*
+ * The basic interface to setting the hardware in a good
+ * state is ``reset''. On return the hardware is known to
+ * be powered up and with interrupts disabled. This must
+ * be followed by initialization of the appropriate bits
+ * and then setup of the interrupt mask.
+ */
+ sc->curchan = sc->hw->conf.channel;
+ sc->curband = &sc->sbands[sc->curchan->band];
+ sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL |
+ AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL |
+ AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_MIB;
- bf->skb = skb;
+ ret = ath5k_reset(sc, NULL);
+ if (ret)
+ goto done;
- if (ath5k_txbuf_setup(sc, bf, txq, padsize)) {
- bf->skb = NULL;
- spin_lock_irqsave(&sc->txbuflock, flags);
- list_add_tail(&bf->list, &sc->txbuf);
- sc->txbuf_len++;
- spin_unlock_irqrestore(&sc->txbuflock, flags);
- goto drop_packet;
+ ath5k_rfkill_hw_start(ah);
+
+ /*
+ * Reset the key cache since some parts do not reset the
+ * contents on initial power up or resume from suspend.
+ */
+ for (i = 0; i < common->keymax; i++)
+ ath_hw_keyreset(common, (u16) i);
+
+ ath5k_hw_set_ack_bitrate_high(ah, true);
+
+ for (i = 0; i < ARRAY_SIZE(sc->bslot); i++)
+ sc->bslot[i] = NULL;
+
+ ret = 0;
+done:
+ mmiowb();
+ mutex_unlock(&sc->lock);
+
+ ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,
+ msecs_to_jiffies(ATH5K_TX_COMPLETE_POLL_INT));
+
+ return ret;
+}
+
+static void stop_tasklets(struct ath5k_softc *sc)
+{
+ tasklet_kill(&sc->rxtq);
+ tasklet_kill(&sc->txtq);
+ tasklet_kill(&sc->calib);
+ tasklet_kill(&sc->beacontq);
+ tasklet_kill(&sc->ani_tasklet);
+}
+
+/*
+ * Stop the device, grabbing the top-level lock to protect
+ * against concurrent entry through ath5k_init (which can happen
+ * if another thread does a system call and the thread doing the
+ * stop is preempted).
+ */
+static int
+ath5k_stop_hw(struct ath5k_softc *sc)
+{
+ int ret;
+
+ mutex_lock(&sc->lock);
+ ret = ath5k_stop_locked(sc);
+ if (ret == 0 && !test_bit(ATH_STAT_INVALID, sc->status)) {
+ /*
+ * Don't set the card in full sleep mode!
+ *
+ * a) When the device is in this state it must be carefully
+ * woken up or references to registers in the PCI clock
+ * domain may freeze the bus (and system). This varies
+ * by chip and is mostly an issue with newer parts
+ * (madwifi sources mentioned srev >= 0x78) that go to
+ * sleep more quickly.
+ *
+ * b) On older chips full sleep results a weird behaviour
+ * during wakeup. I tested various cards with srev < 0x78
+ * and they don't wake up after module reload, a second
+ * module reload is needed to bring the card up again.
+ *
+ * Until we figure out what's going on don't enable
+ * full chip reset on any chip (this is what Legacy HAL
+ * and Sam's HAL do anyway). Instead Perform a full reset
+ * on the device (same as initial state after attach) and
+ * leave it idle (keep MAC/BB on warm reset) */
+ ret = ath5k_hw_on_hold(sc->ah);
+
+ ATH5K_DBG(sc, ATH5K_DEBUG_RESET,
+ "putting device to sleep\n");
}
- return NETDEV_TX_OK;
-drop_packet:
- dev_kfree_skb_any(skb);
- return NETDEV_TX_OK;
+ mmiowb();
+ mutex_unlock(&sc->lock);
+
+ stop_tasklets(sc);
+
+ cancel_delayed_work_sync(&sc->tx_complete_work);
+
+ ath5k_rfkill_hw_stop(sc->ah);
+
+ return ret;
}
/*
@@ -3024,6 +2594,208 @@ static void ath5k_reset_work(struct work_struct *work)
mutex_unlock(&sc->lock);
}
+static int
+ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
+{
+ struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = sc->ah;
+ struct ath_regulatory *regulatory = ath5k_hw_regulatory(ah);
+ struct ath5k_txq *txq;
+ u8 mac[ETH_ALEN] = {};
+ int ret;
+
+ ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "devid 0x%x\n", pdev->device);
+
+ /*
+ * Check if the MAC has multi-rate retry support.
+ * We do this by trying to setup a fake extended
+ * descriptor. MACs that don't have support will
+ * return false w/o doing anything. MACs that do
+ * support it will return true w/o doing anything.
+ */
+ ret = ath5k_hw_setup_mrr_tx_desc(ah, NULL, 0, 0, 0, 0, 0, 0);
+
+ if (ret < 0)
+ goto err;
+ if (ret > 0)
+ __set_bit(ATH_STAT_MRRETRY, sc->status);
+
+ /*
+ * Collect the channel list. The 802.11 layer
+ * is resposible for filtering this list based
+ * on settings like the phy mode and regulatory
+ * domain restrictions.
+ */
+ ret = ath5k_setup_bands(hw);
+ if (ret) {
+ ATH5K_ERR(sc, "can't get channels\n");
+ goto err;
+ }
+
+ /* NB: setup here so ath5k_rate_update is happy */
+ if (test_bit(AR5K_MODE_11A, ah->ah_modes))
+ ath5k_setcurmode(sc, AR5K_MODE_11A);
+ else
+ ath5k_setcurmode(sc, AR5K_MODE_11B);
+
+ /*
+ * Allocate tx+rx descriptors and populate the lists.
+ */
+ ret = ath5k_desc_alloc(sc, pdev);
+ if (ret) {
+ ATH5K_ERR(sc, "can't allocate descriptors\n");
+ goto err;
+ }
+
+ /*
+ * Allocate hardware transmit queues: one queue for
+ * beacon frames and one data queue for each QoS
+ * priority. Note that hw functions handle resetting
+ * these queues at the needed time.
+ */
+ ret = ath5k_beaconq_setup(ah);
+ if (ret < 0) {
+ ATH5K_ERR(sc, "can't setup a beacon xmit queue\n");
+ goto err_desc;
+ }
+ sc->bhalq = ret;
+ sc->cabq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_CAB, 0);
+ if (IS_ERR(sc->cabq)) {
+ ATH5K_ERR(sc, "can't setup cab queue\n");
+ ret = PTR_ERR(sc->cabq);
+ goto err_bhal;
+ }
+
+ /* This order matches mac80211's queue priority, so we can
+ * directly use the mac80211 queue number without any mapping */
+ txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_VO);
+ if (IS_ERR(txq)) {
+ ATH5K_ERR(sc, "can't setup xmit queue\n");
+ ret = PTR_ERR(txq);
+ goto err_queues;
+ }
+ txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_VI);
+ if (IS_ERR(txq)) {
+ ATH5K_ERR(sc, "can't setup xmit queue\n");
+ ret = PTR_ERR(txq);
+ goto err_queues;
+ }
+ txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BE);
+ if (IS_ERR(txq)) {
+ ATH5K_ERR(sc, "can't setup xmit queue\n");
+ ret = PTR_ERR(txq);
+ goto err_queues;
+ }
+ txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BK);
+ if (IS_ERR(txq)) {
+ ATH5K_ERR(sc, "can't setup xmit queue\n");
+ ret = PTR_ERR(txq);
+ goto err_queues;
+ }
+ hw->queues = 4;
+
+ tasklet_init(&sc->rxtq, ath5k_tasklet_rx, (unsigned long)sc);
+ tasklet_init(&sc->txtq, ath5k_tasklet_tx, (unsigned long)sc);
+ tasklet_init(&sc->calib, ath5k_tasklet_calibrate, (unsigned long)sc);
+ tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc);
+ tasklet_init(&sc->ani_tasklet, ath5k_tasklet_ani, (unsigned long)sc);
+
+ INIT_WORK(&sc->reset_work, ath5k_reset_work);
+ INIT_DELAYED_WORK(&sc->tx_complete_work, ath5k_tx_complete_poll_work);
+
+ ret = ath5k_eeprom_read_mac(ah, mac);
+ if (ret) {
+ ATH5K_ERR(sc, "unable to read address from EEPROM: 0x%04x\n",
+ sc->pdev->device);
+ goto err_queues;
+ }
+
+ SET_IEEE80211_PERM_ADDR(hw, mac);
+ memcpy(&sc->lladdr, mac, ETH_ALEN);
+ /* All MAC address bits matter for ACKs */
+ ath5k_update_bssid_mask_and_opmode(sc, NULL);
+
+ regulatory->current_rd = ah->ah_capabilities.cap_eeprom.ee_regdomain;
+ ret = ath_regd_init(regulatory, hw->wiphy, ath5k_reg_notifier);
+ if (ret) {
+ ATH5K_ERR(sc, "can't initialize regulatory system\n");
+ goto err_queues;
+ }
+
+ ret = ieee80211_register_hw(hw);
+ if (ret) {
+ ATH5K_ERR(sc, "can't register ieee80211 hw\n");
+ goto err_queues;
+ }
+
+ if (!ath_is_world_regd(regulatory))
+ regulatory_hint(hw->wiphy, regulatory->alpha2);
+
+ ath5k_init_leds(sc);
+
+ ath5k_sysfs_register(sc);
+
+ return 0;
+err_queues:
+ ath5k_txq_release(sc);
+err_bhal:
+ ath5k_hw_release_tx_queue(ah, sc->bhalq);
+err_desc:
+ ath5k_desc_free(sc, pdev);
+err:
+ return ret;
+}
+
+static void
+ath5k_detach(struct pci_dev *pdev, struct ieee80211_hw *hw)
+{
+ struct ath5k_softc *sc = hw->priv;
+
+ /*
+ * NB: the order of these is important:
+ * o call the 802.11 layer before detaching ath5k_hw to
+ * ensure callbacks into the driver to delete global
+ * key cache entries can be handled
+ * o reclaim the tx queue data structures after calling
+ * the 802.11 layer as we'll get called back to reclaim
+ * node state and potentially want to use them
+ * o to cleanup the tx queues the hal is called, so detach
+ * it last
+ * XXX: ??? detach ath5k_hw ???
+ * Other than that, it's straightforward...
+ */
+ ieee80211_unregister_hw(hw);
+ ath5k_desc_free(sc, pdev);
+ ath5k_txq_release(sc);
+ ath5k_hw_release_tx_queue(sc->ah, sc->bhalq);
+ ath5k_unregister_leds(sc);
+
+ ath5k_sysfs_unregister(sc);
+ /*
+ * NB: can't reclaim these until after ieee80211_ifdetach
+ * returns because we'll get called back to reclaim node
+ * state and potentially want to use them.
+ */
+}
+
+/********************\
+* Mac80211 functions *
+\********************/
+
+static int
+ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+ struct ath5k_softc *sc = hw->priv;
+ u16 qnum = skb_get_queue_mapping(skb);
+
+ if (WARN_ON(qnum >= sc->ah->ah_capabilities.cap_queues.q_tx_num)) {
+ dev_kfree_skb_any(skb);
+ return 0;
+ }
+
+ return ath5k_tx_queue(hw, skb, &sc->txqs[qnum]);
+}
+
static int ath5k_start(struct ieee80211_hw *hw)
{
return ath5k_init(hw->priv);
@@ -3039,32 +2811,78 @@ static int ath5k_add_interface(struct ieee80211_hw *hw,
{
struct ath5k_softc *sc = hw->priv;
int ret;
+ struct ath5k_vif *avf = (void *)vif->drv_priv;
mutex_lock(&sc->lock);
- if (sc->vif) {
- ret = 0;
+
+ if ((vif->type == NL80211_IFTYPE_AP ||
+ vif->type == NL80211_IFTYPE_ADHOC)
+ && (sc->num_ap_vifs + sc->num_adhoc_vifs) >= ATH_BCBUF) {
+ ret = -ELNRNG;
goto end;
}
- sc->vif = vif;
+ /* Don't allow other interfaces if one ad-hoc is configured.
+ * TODO: Fix the problems with ad-hoc and multiple other interfaces.
+ * We would need to operate the HW in ad-hoc mode to allow TSF updates
+ * for the IBSS, but this breaks with additional AP or STA interfaces
+ * at the moment. */
+ if (sc->num_adhoc_vifs ||
+ (sc->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) {
+ ATH5K_ERR(sc, "Only one single ad-hoc interface is allowed.\n");
+ ret = -ELNRNG;
+ goto end;
+ }
switch (vif->type) {
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_ADHOC:
case NL80211_IFTYPE_MESH_POINT:
- case NL80211_IFTYPE_MONITOR:
- sc->opmode = vif->type;
+ avf->opmode = vif->type;
break;
default:
ret = -EOPNOTSUPP;
goto end;
}
- ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "add interface mode %d\n", sc->opmode);
+ sc->nvifs++;
+ ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "add interface mode %d\n", avf->opmode);
+
+ /* Assign the vap/adhoc to a beacon xmit slot. */
+ if ((avf->opmode == NL80211_IFTYPE_AP) ||
+ (avf->opmode == NL80211_IFTYPE_ADHOC)) {
+ int slot;
+ WARN_ON(list_empty(&sc->bcbuf));
+ avf->bbuf = list_first_entry(&sc->bcbuf, struct ath5k_buf,
+ list);
+ list_del(&avf->bbuf->list);
+
+ avf->bslot = 0;
+ for (slot = 0; slot < ATH_BCBUF; slot++) {
+ if (!sc->bslot[slot]) {
+ avf->bslot = slot;
+ break;
+ }
+ }
+ BUG_ON(sc->bslot[avf->bslot] != NULL);
+ sc->bslot[avf->bslot] = vif;
+ if (avf->opmode == NL80211_IFTYPE_AP)
+ sc->num_ap_vifs++;
+ else
+ sc->num_adhoc_vifs++;
+ }
+
+ /* Any MAC address is fine, all others are included through the
+ * filter.
+ */
+ memcpy(&sc->lladdr, vif->addr, ETH_ALEN);
ath5k_hw_set_lladdr(sc->ah, vif->addr);
- ath5k_mode_setup(sc);
+
+ memcpy(&avf->lladdr, vif->addr, ETH_ALEN);
+
+ ath5k_mode_setup(sc, vif);
ret = 0;
end:
@@ -3077,15 +2895,29 @@ ath5k_remove_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct ath5k_softc *sc = hw->priv;
- u8 mac[ETH_ALEN] = {};
+ struct ath5k_vif *avf = (void *)vif->drv_priv;
+ unsigned int i;
mutex_lock(&sc->lock);
- if (sc->vif != vif)
- goto end;
+ sc->nvifs--;
+
+ if (avf->bbuf) {
+ ath5k_txbuf_free_skb(sc, avf->bbuf);
+ list_add_tail(&avf->bbuf->list, &sc->bcbuf);
+ for (i = 0; i < ATH_BCBUF; i++) {
+ if (sc->bslot[i] == vif) {
+ sc->bslot[i] = NULL;
+ break;
+ }
+ }
+ avf->bbuf = NULL;
+ }
+ if (avf->opmode == NL80211_IFTYPE_AP)
+ sc->num_ap_vifs--;
+ else if (avf->opmode == NL80211_IFTYPE_ADHOC)
+ sc->num_adhoc_vifs--;
- ath5k_hw_set_lladdr(sc->ah, mac);
- sc->vif = NULL;
-end:
+ ath5k_update_bssid_mask_and_opmode(sc, NULL);
mutex_unlock(&sc->lock);
}
@@ -3168,6 +3000,19 @@ static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw,
return ((u64)(mfilt[1]) << 32) | mfilt[0];
}
+static bool ath_any_vif_assoc(struct ath5k_softc *sc)
+{
+ struct ath_vif_iter_data iter_data;
+ iter_data.hw_macaddr = NULL;
+ iter_data.any_assoc = false;
+ iter_data.need_set_hw_addr = false;
+ iter_data.found_active = true;
+
+ ieee80211_iterate_active_interfaces_atomic(sc->hw, ath_vif_iter,
+ &iter_data);
+ return iter_data.any_assoc;
+}
+
#define SUPPORTED_FIF_FLAGS \
FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | \
FIF_PLCPFAIL | FIF_CONTROL | FIF_OTHER_BSS | \
@@ -3237,9 +3082,9 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw,
rfilt |= AR5K_RX_FILTER_PHYERR;
/* FIF_BCN_PRBRESP_PROMISC really means to enable beacons
- * and probes for any BSSID, this needs testing */
- if (*new_flags & FIF_BCN_PRBRESP_PROMISC)
- rfilt |= AR5K_RX_FILTER_BEACON | AR5K_RX_FILTER_PROBEREQ;
+ * and probes for any BSSID */
+ if ((*new_flags & FIF_BCN_PRBRESP_PROMISC) || (sc->nvifs > 1))
+ rfilt |= AR5K_RX_FILTER_BEACON;
/* FIF_CONTROL doc says that if FIF_PROMISC_IN_BSS is not
* set we should only pass on control frames for this
@@ -3255,7 +3100,6 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw,
switch (sc->opmode) {
case NL80211_IFTYPE_MESH_POINT:
- case NL80211_IFTYPE_MONITOR:
rfilt |= AR5K_RX_FILTER_CONTROL |
AR5K_RX_FILTER_BEACON |
AR5K_RX_FILTER_PROBEREQ |
@@ -3278,7 +3122,7 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw,
/* Set multicast bits */
ath5k_hw_set_mcast_filter(ah, mfilt[0], mfilt[1]);
- /* Set the cached hw filter flags, this will alter actually
+ /* Set the cached hw filter flags, this will later actually
* be set in HW */
sc->filter_flags = rfilt;
@@ -3298,17 +3142,14 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
if (modparam_nohwcrypt)
return -EOPNOTSUPP;
- if (sc->opmode == NL80211_IFTYPE_AP)
- return -EOPNOTSUPP;
-
- switch (key->alg) {
- case ALG_WEP:
- case ALG_TKIP:
+ switch (key->cipher) {
+ case WLAN_CIPHER_SUITE_WEP40:
+ case WLAN_CIPHER_SUITE_WEP104:
+ case WLAN_CIPHER_SUITE_TKIP:
break;
- case ALG_CCMP:
- if (sc->ah->ah_aes_support)
+ case WLAN_CIPHER_SUITE_CCMP:
+ if (common->crypt_caps & ATH_CRYPT_CAP_CIPHER_AESCCM)
break;
-
return -EOPNOTSUPP;
default:
WARN_ON(1);
@@ -3319,27 +3160,25 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
switch (cmd) {
case SET_KEY:
- ret = ath5k_hw_set_key(sc->ah, key->keyidx, key,
- sta ? sta->addr : NULL);
- if (ret) {
- ATH5K_ERR(sc, "can't set the key\n");
- goto unlock;
+ ret = ath_key_config(common, vif, sta, key);
+ if (ret >= 0) {
+ key->hw_key_idx = ret;
+ /* push IV and Michael MIC generation to stack */
+ key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+ if (key->cipher == WLAN_CIPHER_SUITE_TKIP)
+ key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
+ if (key->cipher == WLAN_CIPHER_SUITE_CCMP)
+ key->flags |= IEEE80211_KEY_FLAG_SW_MGMT;
+ ret = 0;
}
- __set_bit(key->keyidx, common->keymap);
- key->hw_key_idx = key->keyidx;
- key->flags |= (IEEE80211_KEY_FLAG_GENERATE_IV |
- IEEE80211_KEY_FLAG_GENERATE_MMIC);
break;
case DISABLE_KEY:
- ath5k_hw_reset_key(sc->ah, key->keyidx);
- __clear_bit(key->keyidx, common->keymap);
+ ath_key_delete(common, key);
break;
default:
ret = -EINVAL;
- goto unlock;
}
-unlock:
mmiowb();
mutex_unlock(&sc->lock);
return ret;
@@ -3409,43 +3248,6 @@ ath5k_reset_tsf(struct ieee80211_hw *hw)
ath5k_hw_reset_tsf(sc->ah);
}
-/*
- * Updates the beacon that is sent by ath5k_beacon_send. For adhoc,
- * this is called only once at config_bss time, for AP we do it every
- * SWBA interrupt so that the TIM will reflect buffered frames.
- *
- * Called with the beacon lock.
- */
-static int
-ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
-{
- int ret;
- struct ath5k_softc *sc = hw->priv;
- struct sk_buff *skb;
-
- if (WARN_ON(!vif)) {
- ret = -EINVAL;
- goto out;
- }
-
- skb = ieee80211_beacon_get(hw, vif);
-
- if (!skb) {
- ret = -ENOMEM;
- goto out;
- }
-
- ath5k_debug_dump_skb(sc, skb, "BC ", 1);
-
- ath5k_txbuf_free_skb(sc, sc->bbuf);
- sc->bbuf->skb = skb;
- ret = ath5k_beacon_setup(sc, sc->bbuf);
- if (ret)
- sc->bbuf->skb = NULL;
-out:
- return ret;
-}
-
static void
set_beacon_filter(struct ieee80211_hw *hw, bool enable)
{
@@ -3466,20 +3268,19 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_bss_conf *bss_conf,
u32 changes)
{
+ struct ath5k_vif *avf = (void *)vif->drv_priv;
struct ath5k_softc *sc = hw->priv;
struct ath5k_hw *ah = sc->ah;
struct ath_common *common = ath5k_hw_common(ah);
unsigned long flags;
mutex_lock(&sc->lock);
- if (WARN_ON(sc->vif != vif))
- goto unlock;
if (changes & BSS_CHANGED_BSSID) {
/* Cache for later use during resets */
memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
common->curaid = 0;
- ath5k_hw_set_associd(ah);
+ ath5k_hw_set_bssid(ah);
mmiowb();
}
@@ -3487,7 +3288,12 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw,
sc->bintval = bss_conf->beacon_int;
if (changes & BSS_CHANGED_ASSOC) {
- sc->assoc = bss_conf->assoc;
+ avf->assoc = bss_conf->assoc;
+ if (bss_conf->assoc)
+ sc->assoc = bss_conf->assoc;
+ else
+ sc->assoc = ath_any_vif_assoc(sc);
+
if (sc->opmode == NL80211_IFTYPE_STATION)
set_beacon_filter(hw, sc->assoc);
ath5k_hw_set_ledstate(sc->ah, sc->assoc ?
@@ -3497,7 +3303,7 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw,
"Bss Info ASSOC %d, bssid: %pM\n",
bss_conf->aid, common->curbssid);
common->curaid = bss_conf->aid;
- ath5k_hw_set_associd(ah);
+ ath5k_hw_set_bssid(ah);
/* Once ANI is available you would start it here */
}
}
@@ -3515,7 +3321,6 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw,
BSS_CHANGED_BEACON_INT))
ath5k_beacon_config(sc);
- unlock:
mutex_unlock(&sc->lock);
}
@@ -3551,3 +3356,399 @@ static void ath5k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class)
ath5k_hw_set_coverage_class(sc->ah, coverage_class);
mutex_unlock(&sc->lock);
}
+
+static int ath5k_conf_tx(struct ieee80211_hw *hw, u16 queue,
+ const struct ieee80211_tx_queue_params *params)
+{
+ struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = sc->ah;
+ struct ath5k_txq_info qi;
+ int ret = 0;
+
+ if (queue >= ah->ah_capabilities.cap_queues.q_tx_num)
+ return 0;
+
+ mutex_lock(&sc->lock);
+
+ ath5k_hw_get_tx_queueprops(ah, queue, &qi);
+
+ qi.tqi_aifs = params->aifs;
+ qi.tqi_cw_min = params->cw_min;
+ qi.tqi_cw_max = params->cw_max;
+ qi.tqi_burst_time = params->txop;
+
+ ATH5K_DBG(sc, ATH5K_DEBUG_ANY,
+ "Configure tx [queue %d], "
+ "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n",
+ queue, params->aifs, params->cw_min,
+ params->cw_max, params->txop);
+
+ if (ath5k_hw_set_tx_queueprops(ah, queue, &qi)) {
+ ATH5K_ERR(sc,
+ "Unable to update hardware queue %u!\n", queue);
+ ret = -EIO;
+ } else
+ ath5k_hw_reset_tx_queue(ah, queue);
+
+ mutex_unlock(&sc->lock);
+
+ return ret;
+}
+
+static const struct ieee80211_ops ath5k_hw_ops = {
+ .tx = ath5k_tx,
+ .start = ath5k_start,
+ .stop = ath5k_stop,
+ .add_interface = ath5k_add_interface,
+ .remove_interface = ath5k_remove_interface,
+ .config = ath5k_config,
+ .prepare_multicast = ath5k_prepare_multicast,
+ .configure_filter = ath5k_configure_filter,
+ .set_key = ath5k_set_key,
+ .get_stats = ath5k_get_stats,
+ .get_survey = ath5k_get_survey,
+ .conf_tx = ath5k_conf_tx,
+ .get_tsf = ath5k_get_tsf,
+ .set_tsf = ath5k_set_tsf,
+ .reset_tsf = ath5k_reset_tsf,
+ .bss_info_changed = ath5k_bss_info_changed,
+ .sw_scan_start = ath5k_sw_scan_start,
+ .sw_scan_complete = ath5k_sw_scan_complete,
+ .set_coverage_class = ath5k_set_coverage_class,
+};
+
+/********************\
+* PCI Initialization *
+\********************/
+
+static int __devinit
+ath5k_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ void __iomem *mem;
+ struct ath5k_softc *sc;
+ struct ath_common *common;
+ struct ieee80211_hw *hw;
+ int ret;
+ u8 csz;
+
+ /*
+ * L0s needs to be disabled on all ath5k cards.
+ *
+ * For distributions shipping with CONFIG_PCIEASPM (this will be enabled
+ * by default in the future in 2.6.36) this will also mean both L1 and
+ * L0s will be disabled when a pre 1.1 PCIe device is detected. We do
+ * know L1 works correctly even for all ath5k pre 1.1 PCIe devices
+ * though but cannot currently undue the effect of a blacklist, for
+ * details you can read pcie_aspm_sanity_check() and see how it adjusts
+ * the device link capability.
+ *
+ * It may be possible in the future to implement some PCI API to allow
+ * drivers to override blacklists for pre 1.1 PCIe but for now it is
+ * best to accept that both L0s and L1 will be disabled completely for
+ * distributions shipping with CONFIG_PCIEASPM rather than having this
+ * issue present. Motivation for adding this new API will be to help
+ * with power consumption for some of these devices.
+ */
+ pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S);
+
+ ret = pci_enable_device(pdev);
+ if (ret) {
+ dev_err(&pdev->dev, "can't enable device\n");
+ goto err;
+ }
+
+ /* XXX 32-bit addressing only */
+ ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+ if (ret) {
+ dev_err(&pdev->dev, "32-bit DMA not available\n");
+ goto err_dis;
+ }
+
+ /*
+ * Cache line size is used to size and align various
+ * structures used to communicate with the hardware.
+ */
+ pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz);
+ if (csz == 0) {
+ /*
+ * Linux 2.4.18 (at least) writes the cache line size
+ * register as a 16-bit wide register which is wrong.
+ * We must have this setup properly for rx buffer
+ * DMA to work so force a reasonable value here if it
+ * comes up zero.
+ */
+ csz = L1_CACHE_BYTES >> 2;
+ pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz);
+ }
+ /*
+ * The default setting of latency timer yields poor results,
+ * set it to the value used by other systems. It may be worth
+ * tweaking this setting more.
+ */
+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8);
+
+ /* Enable bus mastering */
+ pci_set_master(pdev);
+
+ /*
+ * Disable the RETRY_TIMEOUT register (0x41) to keep
+ * PCI Tx retries from interfering with C3 CPU state.
+ */
+ pci_write_config_byte(pdev, 0x41, 0);
+
+ ret = pci_request_region(pdev, 0, "ath5k");
+ if (ret) {
+ dev_err(&pdev->dev, "cannot reserve PCI memory region\n");
+ goto err_dis;
+ }
+
+ mem = pci_iomap(pdev, 0, 0);
+ if (!mem) {
+ dev_err(&pdev->dev, "cannot remap PCI memory region\n") ;
+ ret = -EIO;
+ goto err_reg;
+ }
+
+ /*
+ * Allocate hw (mac80211 main struct)
+ * and hw->priv (driver private data)
+ */
+ hw = ieee80211_alloc_hw(sizeof(*sc), &ath5k_hw_ops);
+ if (hw == NULL) {
+ dev_err(&pdev->dev, "cannot allocate ieee80211_hw\n");
+ ret = -ENOMEM;
+ goto err_map;
+ }
+
+ dev_info(&pdev->dev, "registered as '%s'\n", wiphy_name(hw->wiphy));
+
+ /* Initialize driver private data */
+ SET_IEEE80211_DEV(hw, &pdev->dev);
+ hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
+ IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
+ IEEE80211_HW_SIGNAL_DBM;
+
+ hw->wiphy->interface_modes =
+ BIT(NL80211_IFTYPE_AP) |
+ BIT(NL80211_IFTYPE_STATION) |
+ BIT(NL80211_IFTYPE_ADHOC) |
+ BIT(NL80211_IFTYPE_MESH_POINT);
+
+ hw->extra_tx_headroom = 2;
+ hw->channel_change_time = 5000;
+ sc = hw->priv;
+ sc->hw = hw;
+ sc->pdev = pdev;
+
+ /*
+ * Mark the device as detached to avoid processing
+ * interrupts until setup is complete.
+ */
+ __set_bit(ATH_STAT_INVALID, sc->status);
+
+ sc->iobase = mem; /* So we can unmap it on detach */
+ sc->opmode = NL80211_IFTYPE_STATION;
+ sc->bintval = 1000;
+ mutex_init(&sc->lock);
+ spin_lock_init(&sc->rxbuflock);
+ spin_lock_init(&sc->txbuflock);
+ spin_lock_init(&sc->block);
+
+ /* Set private data */
+ pci_set_drvdata(pdev, sc);
+
+ /* Setup interrupt handler */
+ ret = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc);
+ if (ret) {
+ ATH5K_ERR(sc, "request_irq failed\n");
+ goto err_free;
+ }
+
+ /* If we passed the test, malloc an ath5k_hw struct */
+ sc->ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL);
+ if (!sc->ah) {
+ ret = -ENOMEM;
+ ATH5K_ERR(sc, "out of memory\n");
+ goto err_irq;
+ }
+
+ sc->ah->ah_sc = sc;
+ sc->ah->ah_iobase = sc->iobase;
+ common = ath5k_hw_common(sc->ah);
+ common->ops = &ath5k_common_ops;
+ common->ah = sc->ah;
+ common->hw = hw;
+ common->cachelsz = csz << 2; /* convert to bytes */
+
+ /* Initialize device */
+ ret = ath5k_hw_attach(sc);
+ if (ret) {
+ goto err_free_ah;
+ }
+
+ /* set up multi-rate retry capabilities */
+ if (sc->ah->ah_version == AR5K_AR5212) {
+ hw->max_rates = 4;
+ hw->max_rate_tries = 11;
+ }
+
+ hw->vif_data_size = sizeof(struct ath5k_vif);
+
+ /* Finish private driver data initialization */
+ ret = ath5k_attach(pdev, hw);
+ if (ret)
+ goto err_ah;
+
+ ATH5K_INFO(sc, "Atheros AR%s chip found (MAC: 0x%x, PHY: 0x%x)\n",
+ ath5k_chip_name(AR5K_VERSION_MAC, sc->ah->ah_mac_srev),
+ sc->ah->ah_mac_srev,
+ sc->ah->ah_phy_revision);
+
+ if (!sc->ah->ah_single_chip) {
+ /* Single chip radio (!RF5111) */
+ if (sc->ah->ah_radio_5ghz_revision &&
+ !sc->ah->ah_radio_2ghz_revision) {
+ /* No 5GHz support -> report 2GHz radio */
+ if (!test_bit(AR5K_MODE_11A,
+ sc->ah->ah_capabilities.cap_mode)) {
+ ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n",
+ ath5k_chip_name(AR5K_VERSION_RAD,
+ sc->ah->ah_radio_5ghz_revision),
+ sc->ah->ah_radio_5ghz_revision);
+ /* No 2GHz support (5110 and some
+ * 5Ghz only cards) -> report 5Ghz radio */
+ } else if (!test_bit(AR5K_MODE_11B,
+ sc->ah->ah_capabilities.cap_mode)) {
+ ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n",
+ ath5k_chip_name(AR5K_VERSION_RAD,
+ sc->ah->ah_radio_5ghz_revision),
+ sc->ah->ah_radio_5ghz_revision);
+ /* Multiband radio */
+ } else {
+ ATH5K_INFO(sc, "RF%s multiband radio found"
+ " (0x%x)\n",
+ ath5k_chip_name(AR5K_VERSION_RAD,
+ sc->ah->ah_radio_5ghz_revision),
+ sc->ah->ah_radio_5ghz_revision);
+ }
+ }
+ /* Multi chip radio (RF5111 - RF2111) ->
+ * report both 2GHz/5GHz radios */
+ else if (sc->ah->ah_radio_5ghz_revision &&
+ sc->ah->ah_radio_2ghz_revision){
+ ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n",
+ ath5k_chip_name(AR5K_VERSION_RAD,
+ sc->ah->ah_radio_5ghz_revision),
+ sc->ah->ah_radio_5ghz_revision);
+ ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n",
+ ath5k_chip_name(AR5K_VERSION_RAD,
+ sc->ah->ah_radio_2ghz_revision),
+ sc->ah->ah_radio_2ghz_revision);
+ }
+ }
+
+ ath5k_debug_init_device(sc);
+
+ /* ready to process interrupts */
+ __clear_bit(ATH_STAT_INVALID, sc->status);
+
+ return 0;
+err_ah:
+ ath5k_hw_detach(sc->ah);
+err_free_ah:
+ kfree(sc->ah);
+err_irq:
+ free_irq(pdev->irq, sc);
+err_free:
+ ieee80211_free_hw(hw);
+err_map:
+ pci_iounmap(pdev, mem);
+err_reg:
+ pci_release_region(pdev, 0);
+err_dis:
+ pci_disable_device(pdev);
+err:
+ return ret;
+}
+
+static void __devexit
+ath5k_pci_remove(struct pci_dev *pdev)
+{
+ struct ath5k_softc *sc = pci_get_drvdata(pdev);
+
+ ath5k_debug_finish_device(sc);
+ ath5k_detach(pdev, sc->hw);
+ ath5k_hw_detach(sc->ah);
+ kfree(sc->ah);
+ free_irq(pdev->irq, sc);
+ pci_iounmap(pdev, sc->iobase);
+ pci_release_region(pdev, 0);
+ pci_disable_device(pdev);
+ ieee80211_free_hw(sc->hw);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int ath5k_pci_suspend(struct device *dev)
+{
+ struct ath5k_softc *sc = pci_get_drvdata(to_pci_dev(dev));
+
+ ath5k_led_off(sc);
+ return 0;
+}
+
+static int ath5k_pci_resume(struct device *dev)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct ath5k_softc *sc = pci_get_drvdata(pdev);
+
+ /*
+ * Suspend/Resume resets the PCI configuration space, so we have to
+ * re-disable the RETRY_TIMEOUT register (0x41) to keep
+ * PCI Tx retries from interfering with C3 CPU state
+ */
+ pci_write_config_byte(pdev, 0x41, 0);
+
+ ath5k_led_enable(sc);
+ return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(ath5k_pm_ops, ath5k_pci_suspend, ath5k_pci_resume);
+#define ATH5K_PM_OPS (&ath5k_pm_ops)
+#else
+#define ATH5K_PM_OPS NULL
+#endif /* CONFIG_PM_SLEEP */
+
+static struct pci_driver ath5k_pci_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = ath5k_pci_id_table,
+ .probe = ath5k_pci_probe,
+ .remove = __devexit_p(ath5k_pci_remove),
+ .driver.pm = ATH5K_PM_OPS,
+};
+
+/*
+ * Module init/exit functions
+ */
+static int __init
+init_ath5k_pci(void)
+{
+ int ret;
+
+ ret = pci_register_driver(&ath5k_pci_driver);
+ if (ret) {
+ printk(KERN_ERR "ath5k_pci: can't register pci driver\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static void __exit
+exit_ath5k_pci(void)
+{
+ pci_unregister_driver(&ath5k_pci_driver);
+}
+
+module_init(init_ath5k_pci);
+module_exit(exit_ath5k_pci);
diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h
index dc1241f9c4e8..9a79773cdc2a 100644
--- a/drivers/net/wireless/ath/ath5k/base.h
+++ b/drivers/net/wireless/ath/ath5k/base.h
@@ -58,7 +58,9 @@
#define ATH_RXBUF 40 /* number of RX buffers */
#define ATH_TXBUF 200 /* number of TX buffers */
-#define ATH_BCBUF 1 /* number of beacon buffers */
+#define ATH_BCBUF 4 /* number of beacon buffers */
+#define ATH5K_TXQ_LEN_MAX (ATH_TXBUF / 4) /* bufs per queue */
+#define ATH5K_TXQ_LEN_LOW (ATH5K_TXQ_LEN_MAX / 2) /* low mark */
struct ath5k_buf {
struct list_head list;
@@ -83,6 +85,9 @@ struct ath5k_txq {
struct list_head q; /* transmit queue */
spinlock_t lock; /* lock on q and link */
bool setup;
+ int txq_len; /* number of queued buffers */
+ bool txq_poll_mark;
+ unsigned int txq_stuck; /* informational counter */
};
#define ATH5K_LED_MAX_NAME_LEN 31
@@ -116,6 +121,13 @@ struct ath5k_statistics {
/* frame errors */
unsigned int rx_all_count; /* all RX frames, including errors */
unsigned int tx_all_count; /* all TX frames, including errors */
+ unsigned int rx_bytes_count; /* all RX bytes, including errored pks
+ * and the MAC headers for each packet
+ */
+ unsigned int tx_bytes_count; /* all TX bytes, including errored pkts
+ * and the MAC headers and padding for
+ * each packet.
+ */
unsigned int rxerr_crc;
unsigned int rxerr_phy;
unsigned int rxerr_phy_code[32];
@@ -146,6 +158,14 @@ struct ath5k_statistics {
#define ATH_CHAN_MAX (14+14+14+252+20)
#endif
+struct ath5k_vif {
+ bool assoc; /* are we associated or not */
+ enum nl80211_iftype opmode;
+ int bslot;
+ struct ath5k_buf *bbuf; /* beacon buffer */
+ u8 lladdr[ETH_ALEN];
+};
+
/* Software Carrier, keeps track of the driver state
* associated with an instance of a device */
struct ath5k_softc {
@@ -182,10 +202,11 @@ struct ath5k_softc {
unsigned int curmode; /* current phy mode */
struct ieee80211_channel *curchan; /* current h/w channel */
- struct ieee80211_vif *vif;
+ u16 nvifs;
enum ath5k_int imask; /* interrupt mask copy */
+ u8 lladdr[ETH_ALEN];
u8 bssidmask[ETH_ALEN];
unsigned int led_pin, /* GPIO pin for driving LED */
@@ -204,7 +225,6 @@ struct ath5k_softc {
spinlock_t txbuflock;
unsigned int txbuf_len; /* buf count in txbuf list */
struct ath5k_txq txqs[AR5K_NUM_TX_QUEUES]; /* tx queues */
- struct ath5k_txq *txq; /* main tx queue */
struct tasklet_struct txtq; /* tx intr tasklet */
struct ath5k_led tx_led; /* tx led */
@@ -214,7 +234,10 @@ struct ath5k_softc {
spinlock_t block; /* protects beacon */
struct tasklet_struct beacontq; /* beacon intr tasklet */
- struct ath5k_buf *bbuf; /* beacon buffer */
+ struct list_head bcbuf; /* beacon buffer */
+ struct ieee80211_vif *bslot[ATH_BCBUF];
+ u16 num_ap_vifs;
+ u16 num_adhoc_vifs;
unsigned int bhalq, /* SW q for outgoing beacons */
bmisscount, /* missed beacon transmits */
bintval, /* beacon interval in TU */
@@ -230,6 +253,8 @@ struct ath5k_softc {
struct ath5k_ani_state ani_state;
struct tasklet_struct ani_tasklet; /* ANI calibration */
+
+ struct delayed_work tx_complete_work;
};
#define ath5k_hw_hasbssidmask(_ah) \
diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c
index 4cccc29964f6..acda56ee521b 100644
--- a/drivers/net/wireless/ath/ath5k/debug.c
+++ b/drivers/net/wireless/ath/ath5k/debug.c
@@ -60,6 +60,7 @@
#include "base.h"
#include "debug.h"
+#include "../debug.h"
static unsigned int ath5k_debug;
module_param_named(debug, ath5k_debug, uint, 0);
@@ -71,8 +72,6 @@ module_param_named(debug, ath5k_debug, uint, 0);
#include "reg.h"
#include "ani.h"
-static struct dentry *ath5k_global_debugfs;
-
static int ath5k_debugfs_open(struct inode *inode, struct file *file)
{
file->private_data = inode->i_private;
@@ -271,6 +270,7 @@ static const struct file_operations fops_beacon = {
.write = write_file_beacon,
.open = ath5k_debugfs_open,
.owner = THIS_MODULE,
+ .llseek = default_llseek,
};
@@ -290,6 +290,7 @@ static const struct file_operations fops_reset = {
.write = write_file_reset,
.open = ath5k_debugfs_open,
.owner = THIS_MODULE,
+ .llseek = noop_llseek,
};
@@ -312,6 +313,7 @@ static const struct {
{ ATH5K_DEBUG_DUMP_TX, "dumptx", "print transmit skb content" },
{ ATH5K_DEBUG_DUMPBANDS, "dumpbands", "dump bands" },
{ ATH5K_DEBUG_ANI, "ani", "adaptive noise immunity" },
+ { ATH5K_DEBUG_DESC, "desc", "descriptor chains" },
{ ATH5K_DEBUG_ANY, "all", "show all debug levels" },
};
@@ -369,6 +371,7 @@ static const struct file_operations fops_debug = {
.write = write_file_debug,
.open = ath5k_debugfs_open,
.owner = THIS_MODULE,
+ .llseek = default_llseek,
};
@@ -480,6 +483,61 @@ static const struct file_operations fops_antenna = {
.write = write_file_antenna,
.open = ath5k_debugfs_open,
.owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
+/* debugfs: misc */
+
+static ssize_t read_file_misc(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath5k_softc *sc = file->private_data;
+ char buf[700];
+ unsigned int len = 0;
+ u32 filt = ath5k_hw_get_rx_filter(sc->ah);
+
+ len += snprintf(buf+len, sizeof(buf)-len, "bssid-mask: %pM\n",
+ sc->bssidmask);
+ len += snprintf(buf+len, sizeof(buf)-len, "filter-flags: 0x%x ",
+ filt);
+ if (filt & AR5K_RX_FILTER_UCAST)
+ len += snprintf(buf+len, sizeof(buf)-len, " UCAST");
+ if (filt & AR5K_RX_FILTER_MCAST)
+ len += snprintf(buf+len, sizeof(buf)-len, " MCAST");
+ if (filt & AR5K_RX_FILTER_BCAST)
+ len += snprintf(buf+len, sizeof(buf)-len, " BCAST");
+ if (filt & AR5K_RX_FILTER_CONTROL)
+ len += snprintf(buf+len, sizeof(buf)-len, " CONTROL");
+ if (filt & AR5K_RX_FILTER_BEACON)
+ len += snprintf(buf+len, sizeof(buf)-len, " BEACON");
+ if (filt & AR5K_RX_FILTER_PROM)
+ len += snprintf(buf+len, sizeof(buf)-len, " PROM");
+ if (filt & AR5K_RX_FILTER_XRPOLL)
+ len += snprintf(buf+len, sizeof(buf)-len, " XRPOLL");
+ if (filt & AR5K_RX_FILTER_PROBEREQ)
+ len += snprintf(buf+len, sizeof(buf)-len, " PROBEREQ");
+ if (filt & AR5K_RX_FILTER_PHYERR_5212)
+ len += snprintf(buf+len, sizeof(buf)-len, " PHYERR-5212");
+ if (filt & AR5K_RX_FILTER_RADARERR_5212)
+ len += snprintf(buf+len, sizeof(buf)-len, " RADARERR-5212");
+ if (filt & AR5K_RX_FILTER_PHYERR_5211)
+ snprintf(buf+len, sizeof(buf)-len, " PHYERR-5211");
+ if (filt & AR5K_RX_FILTER_RADARERR_5211)
+ len += snprintf(buf+len, sizeof(buf)-len, " RADARERR-5211");
+
+ len += snprintf(buf+len, sizeof(buf)-len, "\nopmode: %s (%d)\n",
+ ath_opmode_to_string(sc->opmode), sc->opmode);
+
+ if (len > sizeof(buf))
+ len = sizeof(buf);
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static const struct file_operations fops_misc = {
+ .read = read_file_misc,
+ .open = ath5k_debugfs_open,
+ .owner = THIS_MODULE,
};
@@ -533,6 +591,8 @@ static ssize_t read_file_frameerrors(struct file *file, char __user *user_buf,
st->rxerr_jumbo*100/st->rx_all_count : 0);
len += snprintf(buf+len, sizeof(buf)-len, "[RX all\t%d]\n",
st->rx_all_count);
+ len += snprintf(buf+len, sizeof(buf)-len, "RX-all-bytes\t%d\n",
+ st->rx_bytes_count);
len += snprintf(buf+len, sizeof(buf)-len,
"\nTX\n---------------------\n");
@@ -550,6 +610,8 @@ static ssize_t read_file_frameerrors(struct file *file, char __user *user_buf,
st->txerr_filt*100/st->tx_all_count : 0);
len += snprintf(buf+len, sizeof(buf)-len, "[TX all\t%d]\n",
st->tx_all_count);
+ len += snprintf(buf+len, sizeof(buf)-len, "TX-all-bytes\t%d\n",
+ st->tx_bytes_count);
if (len > sizeof(buf))
len = sizeof(buf);
@@ -591,6 +653,7 @@ static const struct file_operations fops_frameerrors = {
.write = write_file_frameerrors,
.open = ath5k_debugfs_open,
.owner = THIS_MODULE,
+ .llseek = default_llseek,
};
@@ -657,20 +720,21 @@ static ssize_t read_file_ani(struct file *file, char __user *user_buf,
len += snprintf(buf+len, sizeof(buf)-len,
"beacon RSSI average:\t%d\n",
sc->ah->ah_beacon_rssi_avg.avg);
+
+#define CC_PRINT(_struct, _field) \
+ _struct._field, \
+ _struct.cycles > 0 ? \
+ _struct._field*100/_struct.cycles : 0
+
len += snprintf(buf+len, sizeof(buf)-len, "profcnt tx\t\t%u\t(%d%%)\n",
- as->pfc_tx,
- as->pfc_cycles > 0 ?
- as->pfc_tx*100/as->pfc_cycles : 0);
+ CC_PRINT(as->last_cc, tx_frame));
len += snprintf(buf+len, sizeof(buf)-len, "profcnt rx\t\t%u\t(%d%%)\n",
- as->pfc_rx,
- as->pfc_cycles > 0 ?
- as->pfc_rx*100/as->pfc_cycles : 0);
+ CC_PRINT(as->last_cc, rx_frame));
len += snprintf(buf+len, sizeof(buf)-len, "profcnt busy\t\t%u\t(%d%%)\n",
- as->pfc_busy,
- as->pfc_cycles > 0 ?
- as->pfc_busy*100/as->pfc_cycles : 0);
+ CC_PRINT(as->last_cc, rx_busy));
+#undef CC_PRINT
len += snprintf(buf+len, sizeof(buf)-len, "profcnt cycles\t\t%u\n",
- as->pfc_cycles);
+ as->last_cc.cycles);
len += snprintf(buf+len, sizeof(buf)-len,
"listen time\t\t%d\tlast: %d\n",
as->listen_time, as->last_listen);
@@ -748,6 +812,7 @@ static const struct file_operations fops_ani = {
.write = write_file_ani,
.open = ath5k_debugfs_open,
.owner = THIS_MODULE,
+ .llseek = default_llseek,
};
@@ -762,7 +827,7 @@ static ssize_t read_file_queue(struct file *file, char __user *user_buf,
struct ath5k_txq *txq;
struct ath5k_buf *bf, *bf0;
- int i, n = 0;
+ int i, n;
len += snprintf(buf+len, sizeof(buf)-len,
"available txbuffers: %d\n", sc->txbuf_len);
@@ -776,9 +841,16 @@ static ssize_t read_file_queue(struct file *file, char __user *user_buf,
if (!txq->setup)
continue;
+ n = 0;
+ spin_lock_bh(&txq->lock);
list_for_each_entry_safe(bf, bf0, &txq->q, list)
n++;
- len += snprintf(buf+len, sizeof(buf)-len, " len: %d\n", n);
+ spin_unlock_bh(&txq->lock);
+
+ len += snprintf(buf+len, sizeof(buf)-len,
+ " len: %d bufs: %d\n", txq->txq_len, n);
+ len += snprintf(buf+len, sizeof(buf)-len,
+ " stuck: %d\n", txq->txq_stuck);
}
if (len > sizeof(buf))
@@ -811,24 +883,17 @@ static const struct file_operations fops_queue = {
.write = write_file_queue,
.open = ath5k_debugfs_open,
.owner = THIS_MODULE,
+ .llseek = default_llseek,
};
-/* init */
-
-void
-ath5k_debug_init(void)
-{
- ath5k_global_debugfs = debugfs_create_dir("ath5k", NULL);
-}
-
void
ath5k_debug_init_device(struct ath5k_softc *sc)
{
sc->debug.level = ath5k_debug;
- sc->debug.debugfs_phydir = debugfs_create_dir(wiphy_name(sc->hw->wiphy),
- ath5k_global_debugfs);
+ sc->debug.debugfs_phydir = debugfs_create_dir("ath5k",
+ sc->hw->wiphy->debugfsdir);
sc->debug.debugfs_debug = debugfs_create_file("debug",
S_IWUSR | S_IRUSR,
@@ -848,6 +913,10 @@ ath5k_debug_init_device(struct ath5k_softc *sc)
S_IWUSR | S_IRUSR,
sc->debug.debugfs_phydir, sc, &fops_antenna);
+ sc->debug.debugfs_misc = debugfs_create_file("misc",
+ S_IRUSR,
+ sc->debug.debugfs_phydir, sc, &fops_misc);
+
sc->debug.debugfs_frameerrors = debugfs_create_file("frameerrors",
S_IWUSR | S_IRUSR,
sc->debug.debugfs_phydir, sc,
@@ -865,12 +934,6 @@ ath5k_debug_init_device(struct ath5k_softc *sc)
}
void
-ath5k_debug_finish(void)
-{
- debugfs_remove(ath5k_global_debugfs);
-}
-
-void
ath5k_debug_finish_device(struct ath5k_softc *sc)
{
debugfs_remove(sc->debug.debugfs_debug);
@@ -878,6 +941,7 @@ ath5k_debug_finish_device(struct ath5k_softc *sc)
debugfs_remove(sc->debug.debugfs_beacon);
debugfs_remove(sc->debug.debugfs_reset);
debugfs_remove(sc->debug.debugfs_antenna);
+ debugfs_remove(sc->debug.debugfs_misc);
debugfs_remove(sc->debug.debugfs_frameerrors);
debugfs_remove(sc->debug.debugfs_ani);
debugfs_remove(sc->debug.debugfs_queue);
@@ -955,7 +1019,7 @@ ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah)
struct ath5k_rx_status rs = {};
int status;
- if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET)))
+ if (likely(!(sc->debug.level & ATH5K_DEBUG_DESC)))
return;
printk(KERN_DEBUG "rxdp %x, rxlink %p\n",
@@ -997,7 +1061,7 @@ ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf)
struct ath5k_tx_status ts = {};
int done;
- if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET)))
+ if (likely(!(sc->debug.level & ATH5K_DEBUG_DESC)))
return;
done = sc->ah->ah_proc_tx_desc(sc->ah, bf->desc, &ts);
diff --git a/drivers/net/wireless/ath/ath5k/debug.h b/drivers/net/wireless/ath/ath5k/debug.h
index 606ae94a9157..236edbd2507d 100644
--- a/drivers/net/wireless/ath/ath5k/debug.h
+++ b/drivers/net/wireless/ath/ath5k/debug.h
@@ -75,6 +75,7 @@ struct ath5k_dbg_info {
struct dentry *debugfs_beacon;
struct dentry *debugfs_reset;
struct dentry *debugfs_antenna;
+ struct dentry *debugfs_misc;
struct dentry *debugfs_frameerrors;
struct dentry *debugfs_ani;
struct dentry *debugfs_queue;
@@ -95,6 +96,7 @@ struct ath5k_dbg_info {
* @ATH5K_DEBUG_DUMP_TX: print transmit skb content
* @ATH5K_DEBUG_DUMPBANDS: dump bands
* @ATH5K_DEBUG_TRACE: trace function calls
+ * @ATH5K_DEBUG_DESC: descriptor setup
* @ATH5K_DEBUG_ANY: show at any debug level
*
* The debug level is used to control the amount and type of debugging output
@@ -117,6 +119,7 @@ enum ath5k_debug_level {
ATH5K_DEBUG_DUMP_TX = 0x00000200,
ATH5K_DEBUG_DUMPBANDS = 0x00000400,
ATH5K_DEBUG_ANI = 0x00002000,
+ ATH5K_DEBUG_DESC = 0x00004000,
ATH5K_DEBUG_ANY = 0xffffffff
};
@@ -135,15 +138,9 @@ enum ath5k_debug_level {
} while (0)
void
-ath5k_debug_init(void);
-
-void
ath5k_debug_init_device(struct ath5k_softc *sc);
void
-ath5k_debug_finish(void);
-
-void
ath5k_debug_finish_device(struct ath5k_softc *sc);
void
@@ -171,15 +168,9 @@ ATH5K_DBG_UNLIMIT(struct ath5k_softc *sc, unsigned int m, const char *fmt, ...)
{}
static inline void
-ath5k_debug_init(void) {}
-
-static inline void
ath5k_debug_init_device(struct ath5k_softc *sc) {}
static inline void
-ath5k_debug_finish(void) {}
-
-static inline void
ath5k_debug_finish_device(struct ath5k_softc *sc) {}
static inline void
diff --git a/drivers/net/wireless/ath/ath5k/dma.c b/drivers/net/wireless/ath/ath5k/dma.c
index 484f31870ba8..923c9ca5c4f0 100644
--- a/drivers/net/wireless/ath/ath5k/dma.c
+++ b/drivers/net/wireless/ath/ath5k/dma.c
@@ -244,7 +244,7 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
/* Force channel idle high */
AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5211,
- AR5K_DIAG_SW_CHANEL_IDLE_HIGH);
+ AR5K_DIAG_SW_CHANNEL_IDLE_HIGH);
/* Wait a while and disable mechanism */
udelay(200);
@@ -261,7 +261,7 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
} while (--i && pending);
AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5211,
- AR5K_DIAG_SW_CHANEL_IDLE_HIGH);
+ AR5K_DIAG_SW_CHANNEL_IDLE_HIGH);
}
/* Clear register */
@@ -377,11 +377,11 @@ int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr)
*
* This function increases/decreases the tx trigger level for the tx fifo
* buffer (aka FIFO threshold) that is used to indicate when PCU flushes
- * the buffer and transmits it's data. Lowering this results sending small
+ * the buffer and transmits its data. Lowering this results sending small
* frames more quickly but can lead to tx underruns, raising it a lot can
* result other problems (i think bmiss is related). Right now we start with
* the lowest possible (64Bytes) and if we get tx underrun we increase it using
- * the increase flag. Returns -EIO if we have have reached maximum/minimum.
+ * the increase flag. Returns -EIO if we have reached maximum/minimum.
*
* XXX: Link this with tx DMA size ?
* XXX: Use it to save interrupts ?
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c
index ae316fec4a6a..39722dd73e43 100644
--- a/drivers/net/wireless/ath/ath5k/eeprom.c
+++ b/drivers/net/wireless/ath/ath5k/eeprom.c
@@ -661,7 +661,7 @@ ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset)
* (eeprom versions < 4). For RF5111 we have 11 pre-defined PCDAC
* steps that match with the power values we read from eeprom. On
* older eeprom versions (< 3.2) these steps are equaly spaced at
- * 10% of the pcdac curve -until the curve reaches it's maximum-
+ * 10% of the pcdac curve -until the curve reaches its maximum-
* (11 steps from 0 to 100%) but on newer eeprom versions (>= 3.2)
* these 11 steps are spaced in a different way. This function returns
* the pcdac steps based on eeprom version and curve min/max so that we
@@ -1113,7 +1113,7 @@ ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode)
*/
/* For RF2413 power calibration data doesn't start on a fixed location and
- * if a mode is not supported, it's section is missing -not zeroed-.
+ * if a mode is not supported, its section is missing -not zeroed-.
* So we need to calculate the starting offset for each section by using
* these two functions */
diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c
index 86fdb6ddfaaa..074b4c644399 100644
--- a/drivers/net/wireless/ath/ath5k/pcu.c
+++ b/drivers/net/wireless/ath/ath5k/pcu.c
@@ -137,11 +137,11 @@ void ath5k_hw_update_mib_counters(struct ath5k_hw *ah)
* ath5k_hw_set_ack_bitrate - set bitrate for ACKs
*
* @ah: The &struct ath5k_hw
- * @high: Flag to determine if we want to use high transmition rate
+ * @high: Flag to determine if we want to use high transmission rate
* for ACKs or not
*
* If high flag is set, we tell hw to use a set of control rates based on
- * the current transmition rate (check out control_rates array inside reset.c).
+ * the current transmission rate (check out control_rates array inside reset.c).
* If not hw just uses the lowest rate available for the current modulation
* scheme being used (1Mbit for CCK and 6Mbits for OFDM).
*/
@@ -207,7 +207,8 @@ static int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout)
*/
unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec)
{
- return usec * ath5k_hw_get_clockrate(ah);
+ struct ath_common *common = ath5k_hw_common(ah);
+ return usec * common->clockrate;
}
/**
@@ -216,17 +217,19 @@ unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec)
*/
unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock)
{
- return clock / ath5k_hw_get_clockrate(ah);
+ struct ath_common *common = ath5k_hw_common(ah);
+ return clock / common->clockrate;
}
/**
- * ath5k_hw_get_clockrate - Get the clock rate for current mode
+ * ath5k_hw_set_clockrate - Set common->clockrate for the current channel
*
* @ah: The &struct ath5k_hw
*/
-unsigned int ath5k_hw_get_clockrate(struct ath5k_hw *ah)
+void ath5k_hw_set_clockrate(struct ath5k_hw *ah)
{
struct ieee80211_channel *channel = ah->ah_current_channel;
+ struct ath_common *common = ath5k_hw_common(ah);
int clock;
if (channel->hw_value & CHANNEL_5GHZ)
@@ -240,7 +243,7 @@ unsigned int ath5k_hw_get_clockrate(struct ath5k_hw *ah)
if (channel->hw_value & CHANNEL_TURBO)
clock *= 2;
- return clock;
+ common->clockrate = clock;
}
/**
@@ -308,27 +311,26 @@ int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac)
}
/**
- * ath5k_hw_set_associd - Set BSSID for association
+ * ath5k_hw_set_bssid - Set current BSSID on hw
*
* @ah: The &struct ath5k_hw
- * @bssid: BSSID
- * @assoc_id: Assoc id
*
- * Sets the BSSID which trigers the "SME Join" operation
+ * Sets the current BSSID and BSSID mask we have from the
+ * common struct into the hardware
*/
-void ath5k_hw_set_associd(struct ath5k_hw *ah)
+void ath5k_hw_set_bssid(struct ath5k_hw *ah)
{
struct ath_common *common = ath5k_hw_common(ah);
u16 tim_offset = 0;
/*
- * Set simple BSSID mask on 5212
+ * Set BSSID mask on 5212
*/
if (ah->ah_version == AR5K_AR5212)
ath_hw_setbssidmask(common);
/*
- * Set BSSID which triggers the "SME Join" operation
+ * Set BSSID
*/
ath5k_hw_reg_write(ah,
get_unaligned_le32(common->curbssid),
@@ -496,6 +498,10 @@ u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah)
{
u32 tsf_lower, tsf_upper1, tsf_upper2;
int i;
+ unsigned long flags;
+
+ /* This code is time critical - we don't want to be interrupted here */
+ local_irq_save(flags);
/*
* While reading TSF upper and then lower part, the clock is still
@@ -518,6 +524,8 @@ u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah)
tsf_upper1 = tsf_upper2;
}
+ local_irq_restore(flags);
+
WARN_ON( i == ATH5K_MAX_TSF_READ );
return (((u64)tsf_upper1 << 32) | tsf_lower);
@@ -601,7 +609,7 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval)
/* Timer3 marks the end of our ATIM window
* a zero length window is not allowed because
* we 'll get no beacons */
- timer3 = next_beacon + (ah->ah_atim_window ? ah->ah_atim_window : 1);
+ timer3 = next_beacon + 1;
/*
* Set the beacon register and enable all timers.
@@ -641,198 +649,95 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval)
}
-
-/*********************\
-* Key table functions *
-\*********************/
-
-/*
- * Reset a key entry on the table
+/**
+ * ath5k_check_timer_win - Check if timer B is timer A + window
+ *
+ * @a: timer a (before b)
+ * @b: timer b (after a)
+ * @window: difference between a and b
+ * @intval: timers are increased by this interval
+ *
+ * This helper function checks if timer B is timer A + window and covers
+ * cases where timer A or B might have already been updated or wrapped
+ * around (Timers are 16 bit).
+ *
+ * Returns true if O.K.
*/
-int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry)
+static inline bool
+ath5k_check_timer_win(int a, int b, int window, int intval)
{
- unsigned int i, type;
- u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET;
-
- AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE);
-
- type = ath5k_hw_reg_read(ah, AR5K_KEYTABLE_TYPE(entry));
-
- for (i = 0; i < AR5K_KEYCACHE_SIZE; i++)
- ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_OFF(entry, i));
-
- /* Reset associated MIC entry if TKIP
- * is enabled located at offset (entry + 64) */
- if (type == AR5K_KEYTABLE_TYPE_TKIP) {
- AR5K_ASSERT_ENTRY(micentry, AR5K_KEYTABLE_SIZE);
- for (i = 0; i < AR5K_KEYCACHE_SIZE / 2 ; i++)
- ath5k_hw_reg_write(ah, 0,
- AR5K_KEYTABLE_OFF(micentry, i));
- }
-
/*
- * Set NULL encryption on AR5212+
- *
- * Note: AR5K_KEYTABLE_TYPE -> AR5K_KEYTABLE_OFF(entry, 5)
- * AR5K_KEYTABLE_TYPE_NULL -> 0x00000007
- *
- * Note2: Windows driver (ndiswrapper) sets this to
- * 0x00000714 instead of 0x00000007
+ * 1.) usually B should be A + window
+ * 2.) A already updated, B not updated yet
+ * 3.) A already updated and has wrapped around
+ * 4.) B has wrapped around
*/
- if (ah->ah_version >= AR5K_AR5211) {
- ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL,
- AR5K_KEYTABLE_TYPE(entry));
-
- if (type == AR5K_KEYTABLE_TYPE_TKIP) {
- ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL,
- AR5K_KEYTABLE_TYPE(micentry));
- }
- }
-
- return 0;
+ if ((b - a == window) || /* 1.) */
+ (a - b == intval - window) || /* 2.) */
+ ((a | 0x10000) - b == intval - window) || /* 3.) */
+ ((b | 0x10000) - a == window)) /* 4.) */
+ return true; /* O.K. */
+ return false;
}
-static
-int ath5k_keycache_type(const struct ieee80211_key_conf *key)
-{
- switch (key->alg) {
- case ALG_TKIP:
- return AR5K_KEYTABLE_TYPE_TKIP;
- case ALG_CCMP:
- return AR5K_KEYTABLE_TYPE_CCM;
- case ALG_WEP:
- if (key->keylen == WLAN_KEY_LEN_WEP40)
- return AR5K_KEYTABLE_TYPE_40;
- else if (key->keylen == WLAN_KEY_LEN_WEP104)
- return AR5K_KEYTABLE_TYPE_104;
- return -EINVAL;
- default:
- return -EINVAL;
- }
- return -EINVAL;
-}
-
-/*
- * Set a key entry on the table
+/**
+ * ath5k_hw_check_beacon_timers - Check if the beacon timers are correct
+ *
+ * @ah: The &struct ath5k_hw
+ * @intval: beacon interval
+ *
+ * This is a workaround for IBSS mode:
+ *
+ * The need for this function arises from the fact that we have 4 separate
+ * HW timer registers (TIMER0 - TIMER3), which are closely related to the
+ * next beacon target time (NBTT), and that the HW updates these timers
+ * seperately based on the current TSF value. The hardware increments each
+ * timer by the beacon interval, when the local TSF coverted to TU is equal
+ * to the value stored in the timer.
+ *
+ * The reception of a beacon with the same BSSID can update the local HW TSF
+ * at any time - this is something we can't avoid. If the TSF jumps to a
+ * time which is later than the time stored in a timer, this timer will not
+ * be updated until the TSF in TU wraps around at 16 bit (the size of the
+ * timers) and reaches the time which is stored in the timer.
+ *
+ * The problem is that these timers are closely related to TIMER0 (NBTT) and
+ * that they define a time "window". When the TSF jumps between two timers
+ * (e.g. ATIM and NBTT), the one in the past will be left behind (not
+ * updated), while the one in the future will be updated every beacon
+ * interval. This causes the window to get larger, until the TSF wraps
+ * around as described above and the timer which was left behind gets
+ * updated again. But - because the beacon interval is usually not an exact
+ * divisor of the size of the timers (16 bit), an unwanted "window" between
+ * these timers has developed!
+ *
+ * This is especially important with the ATIM window, because during
+ * the ATIM window only ATIM frames and no data frames are allowed to be
+ * sent, which creates transmission pauses after each beacon. This symptom
+ * has been described as "ramping ping" because ping times increase linearly
+ * for some time and then drop down again. A wrong window on the DMA beacon
+ * timer has the same effect, so we check for these two conditions.
+ *
+ * Returns true if O.K.
*/
-int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry,
- const struct ieee80211_key_conf *key, const u8 *mac)
-{
- unsigned int i;
- int keylen;
- __le32 key_v[5] = {};
- __le32 key0 = 0, key1 = 0;
- __le32 *rxmic, *txmic;
- int keytype;
- u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET;
- bool is_tkip;
- const u8 *key_ptr;
-
- is_tkip = (key->alg == ALG_TKIP);
-
- /*
- * key->keylen comes in from mac80211 in bytes.
- * TKIP is 128 bit + 128 bit mic
- */
- keylen = (is_tkip) ? (128 / 8) : key->keylen;
-
- if (entry > AR5K_KEYTABLE_SIZE ||
- (is_tkip && micentry > AR5K_KEYTABLE_SIZE))
- return -EOPNOTSUPP;
-
- if (unlikely(keylen > 16))
- return -EOPNOTSUPP;
-
- keytype = ath5k_keycache_type(key);
- if (keytype < 0)
- return keytype;
-
- /*
- * each key block is 6 bytes wide, written as pairs of
- * alternating 32 and 16 bit le values.
- */
- key_ptr = key->key;
- for (i = 0; keylen >= 6; keylen -= 6) {
- memcpy(&key_v[i], key_ptr, 6);
- i += 2;
- key_ptr += 6;
- }
- if (keylen)
- memcpy(&key_v[i], key_ptr, keylen);
-
- /* intentionally corrupt key until mic is installed */
- if (is_tkip) {
- key0 = key_v[0] = ~key_v[0];
- key1 = key_v[1] = ~key_v[1];
- }
-
- for (i = 0; i < ARRAY_SIZE(key_v); i++)
- ath5k_hw_reg_write(ah, le32_to_cpu(key_v[i]),
- AR5K_KEYTABLE_OFF(entry, i));
-
- ath5k_hw_reg_write(ah, keytype, AR5K_KEYTABLE_TYPE(entry));
-
- if (is_tkip) {
- /* Install rx/tx MIC */
- rxmic = (__le32 *) &key->key[16];
- txmic = (__le32 *) &key->key[24];
-
- if (ah->ah_combined_mic) {
- key_v[0] = rxmic[0];
- key_v[1] = cpu_to_le32(le32_to_cpu(txmic[0]) >> 16);
- key_v[2] = rxmic[1];
- key_v[3] = cpu_to_le32(le32_to_cpu(txmic[0]) & 0xffff);
- key_v[4] = txmic[1];
- } else {
- key_v[0] = rxmic[0];
- key_v[1] = 0;
- key_v[2] = rxmic[1];
- key_v[3] = 0;
- key_v[4] = 0;
- }
- for (i = 0; i < ARRAY_SIZE(key_v); i++)
- ath5k_hw_reg_write(ah, le32_to_cpu(key_v[i]),
- AR5K_KEYTABLE_OFF(micentry, i));
-
- ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL,
- AR5K_KEYTABLE_TYPE(micentry));
- ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_MAC0(micentry));
- ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_MAC1(micentry));
-
- /* restore first 2 words of key */
- ath5k_hw_reg_write(ah, le32_to_cpu(~key0),
- AR5K_KEYTABLE_OFF(entry, 0));
- ath5k_hw_reg_write(ah, le32_to_cpu(~key1),
- AR5K_KEYTABLE_OFF(entry, 1));
- }
-
- return ath5k_hw_set_key_lladdr(ah, entry, mac);
-}
-
-int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac)
+bool
+ath5k_hw_check_beacon_timers(struct ath5k_hw *ah, int intval)
{
- u32 low_id, high_id;
-
- /* Invalid entry (key table overflow) */
- AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE);
+ unsigned int nbtt, atim, dma;
- /*
- * MAC may be NULL if it's a broadcast key. In this case no need to
- * to compute get_unaligned_le32 and get_unaligned_le16 as we
- * already know it.
- */
- if (!mac) {
- low_id = 0xffffffff;
- high_id = 0xffff | AR5K_KEYTABLE_VALID;
- } else {
- low_id = get_unaligned_le32(mac);
- high_id = get_unaligned_le16(mac + 4) | AR5K_KEYTABLE_VALID;
- }
+ nbtt = ath5k_hw_reg_read(ah, AR5K_TIMER0);
+ atim = ath5k_hw_reg_read(ah, AR5K_TIMER3);
+ dma = ath5k_hw_reg_read(ah, AR5K_TIMER1) >> 3;
- ath5k_hw_reg_write(ah, low_id, AR5K_KEYTABLE_MAC0(entry));
- ath5k_hw_reg_write(ah, high_id, AR5K_KEYTABLE_MAC1(entry));
+ /* NOTE: SWBA is different. Having a wrong window there does not
+ * stop us from sending data and this condition is catched thru
+ * other means (SWBA interrupt) */
- return 0;
+ if (ath5k_check_timer_win(nbtt, atim, 1, intval) &&
+ ath5k_check_timer_win(dma, nbtt, AR5K_TUNE_DMA_BEACON_RESP,
+ intval))
+ return true; /* O.K. */
+ return false;
}
/**
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c
index 6284c389ba18..219367884e64 100644
--- a/drivers/net/wireless/ath/ath5k/phy.c
+++ b/drivers/net/wireless/ath/ath5k/phy.c
@@ -115,7 +115,7 @@ static unsigned int ath5k_hw_rfb_op(struct ath5k_hw *ah,
\**********************/
/*
- * This code is used to optimize rf gain on different environments
+ * This code is used to optimize RF gain on different environments
* (temperature mostly) based on feedback from a power detector.
*
* It's only used on RF5111 and RF5112, later RF chips seem to have
@@ -302,7 +302,7 @@ static bool ath5k_hw_rf_check_gainf_readback(struct ath5k_hw *ah)
}
/* Perform gain_F adjustment by choosing the right set
- * of parameters from rf gain optimization ladder */
+ * of parameters from RF gain optimization ladder */
static s8 ath5k_hw_rf_gainf_adjust(struct ath5k_hw *ah)
{
const struct ath5k_gain_opt *go;
@@ -367,7 +367,7 @@ done:
return ret;
}
-/* Main callback for thermal rf gain calibration engine
+/* Main callback for thermal RF gain calibration engine
* Check for a new gain reading and schedule an adjustment
* if needed.
*
@@ -433,7 +433,7 @@ done:
return ah->ah_gain.g_state;
}
-/* Write initial rf gain table to set the RF sensitivity
+/* Write initial RF gain table to set the RF sensitivity
* this one works on all RF chips and has nothing to do
* with gain_F calibration */
int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq)
@@ -496,7 +496,7 @@ int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq)
/*
- * Setup RF registers by writing rf buffer on hw
+ * Setup RF registers by writing RF buffer on hw
*/
int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
unsigned int mode)
@@ -571,7 +571,7 @@ int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
return -EINVAL;
}
- /* If it's the first time we set rf buffer, allocate
+ /* If it's the first time we set RF buffer, allocate
* ah->ah_rf_banks based on ah->ah_rf_banks_size
* we set above */
if (ah->ah_rf_banks == NULL) {
@@ -1093,6 +1093,7 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel)
ah->ah_current_channel = channel;
ah->ah_turbo = channel->hw_value == CHANNEL_T ? true : false;
+ ath5k_hw_set_clockrate(ah);
return 0;
}
@@ -1257,7 +1258,7 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah,
* Disable beacons and RX/TX queues, wait
*/
AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5210,
- AR5K_DIAG_SW_DIS_TX | AR5K_DIAG_SW_DIS_RX_5210);
+ AR5K_DIAG_SW_DIS_TX_5210 | AR5K_DIAG_SW_DIS_RX_5210);
beacon = ath5k_hw_reg_read(ah, AR5K_BEACON_5210);
ath5k_hw_reg_write(ah, beacon & ~AR5K_BEACON_ENABLE, AR5K_BEACON_5210);
@@ -1336,7 +1337,7 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah,
* Re-enable RX/TX and beacons
*/
AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5210,
- AR5K_DIAG_SW_DIS_TX | AR5K_DIAG_SW_DIS_RX_5210);
+ AR5K_DIAG_SW_DIS_TX_5210 | AR5K_DIAG_SW_DIS_RX_5210);
ath5k_hw_reg_write(ah, beacon, AR5K_BEACON_5210);
return 0;
@@ -1377,7 +1378,7 @@ ath5k_hw_rf511x_iq_calibrate(struct ath5k_hw *ah)
/* protect against divide by 0 and loss of sign bits */
if (i_coffd == 0 || q_coffd < 2)
- return -1;
+ return 0;
i_coff = (-iq_corr) / i_coffd;
i_coff = clamp(i_coff, -32, 31); /* signed 6 bit */
@@ -1582,7 +1583,7 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah,
else if (curr_sym_off >= 31 && curr_sym_off <= 46)
mag_mask[2] |=
plt_mag_map << (curr_sym_off - 31) * 2;
- else if (curr_sym_off >= 46 && curr_sym_off <= 53)
+ else if (curr_sym_off >= 47 && curr_sym_off <= 53)
mag_mask[3] |=
plt_mag_map << (curr_sym_off - 47) * 2;
@@ -2987,7 +2988,7 @@ ath5k_setup_rate_powertable(struct ath5k_hw *ah, u16 max_pwr,
/*
- * Set transmition power
+ * Set transmission power
*/
int
ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
@@ -3035,9 +3036,6 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
/* Limit max power if we have a CTL available */
ath5k_get_max_ctl_power(ah, channel);
- /* FIXME: Tx power limit for this regdomain
- * XXX: Mac80211/CRDA will do that anyway ? */
-
/* FIXME: Antenna reduction stuff */
/* FIXME: Limit power on turbo modes */
diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c
index 4186ff4c6e9c..84c717ded1c5 100644
--- a/drivers/net/wireless/ath/ath5k/qcu.c
+++ b/drivers/net/wireless/ath/ath5k/qcu.c
@@ -36,24 +36,58 @@ int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue,
}
/*
+ * Make sure cw is a power of 2 minus 1 and smaller than 1024
+ */
+static u16 ath5k_cw_validate(u16 cw_req)
+{
+ u32 cw = 1;
+ cw_req = min(cw_req, (u16)1023);
+
+ while (cw < cw_req)
+ cw = (cw << 1) | 1;
+
+ return cw;
+}
+
+/*
* Set properties for a transmit queue
*/
int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue,
- const struct ath5k_txq_info *queue_info)
+ const struct ath5k_txq_info *qinfo)
{
+ struct ath5k_txq_info *qi;
+
AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
- if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
+ qi = &ah->ah_txq[queue];
+
+ if (qi->tqi_type == AR5K_TX_QUEUE_INACTIVE)
return -EIO;
- memcpy(&ah->ah_txq[queue], queue_info, sizeof(struct ath5k_txq_info));
+ /* copy and validate values */
+ qi->tqi_type = qinfo->tqi_type;
+ qi->tqi_subtype = qinfo->tqi_subtype;
+ qi->tqi_flags = qinfo->tqi_flags;
+ /*
+ * According to the docs: Although the AIFS field is 8 bit wide,
+ * the maximum supported value is 0xFC. Setting it higher than that
+ * will cause the DCU to hang.
+ */
+ qi->tqi_aifs = min(qinfo->tqi_aifs, (u8)0xFC);
+ qi->tqi_cw_min = ath5k_cw_validate(qinfo->tqi_cw_min);
+ qi->tqi_cw_max = ath5k_cw_validate(qinfo->tqi_cw_max);
+ qi->tqi_cbr_period = qinfo->tqi_cbr_period;
+ qi->tqi_cbr_overflow_limit = qinfo->tqi_cbr_overflow_limit;
+ qi->tqi_burst_time = qinfo->tqi_burst_time;
+ qi->tqi_ready_time = qinfo->tqi_ready_time;
/*XXX: Is this supported on 5210 ?*/
- if ((queue_info->tqi_type == AR5K_TX_QUEUE_DATA &&
- ((queue_info->tqi_subtype == AR5K_WME_AC_VI) ||
- (queue_info->tqi_subtype == AR5K_WME_AC_VO))) ||
- queue_info->tqi_type == AR5K_TX_QUEUE_UAPSD)
- ah->ah_txq[queue].tqi_flags |= AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS;
+ /*XXX: Is this correct for AR5K_WME_AC_VI,VO ???*/
+ if ((qinfo->tqi_type == AR5K_TX_QUEUE_DATA &&
+ ((qinfo->tqi_subtype == AR5K_WME_AC_VI) ||
+ (qinfo->tqi_subtype == AR5K_WME_AC_VO))) ||
+ qinfo->tqi_type == AR5K_TX_QUEUE_UAPSD)
+ qi->tqi_flags |= AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS;
return 0;
}
@@ -186,7 +220,7 @@ void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue)
*/
int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
{
- u32 cw_min, cw_max, retry_lg, retry_sh;
+ u32 retry_lg, retry_sh;
struct ath5k_txq_info *tq = &ah->ah_txq[queue];
AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
@@ -217,14 +251,13 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
/* Set IFS0 */
if (ah->ah_turbo) {
ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS_TURBO +
- (ah->ah_aifs + tq->tqi_aifs) *
- AR5K_INIT_SLOT_TIME_TURBO) <<
+ tq->tqi_aifs * AR5K_INIT_SLOT_TIME_TURBO) <<
AR5K_IFS0_DIFS_S) | AR5K_INIT_SIFS_TURBO,
AR5K_IFS0);
} else {
ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS +
- (ah->ah_aifs + tq->tqi_aifs) *
- AR5K_INIT_SLOT_TIME) << AR5K_IFS0_DIFS_S) |
+ tq->tqi_aifs * AR5K_INIT_SLOT_TIME) <<
+ AR5K_IFS0_DIFS_S) |
AR5K_INIT_SIFS, AR5K_IFS0);
}
@@ -248,35 +281,6 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
}
/*
- * Calculate cwmin/max by channel mode
- */
- cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN;
- cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX;
- ah->ah_aifs = AR5K_TUNE_AIFS;
- /*XR is only supported on 5212*/
- if (IS_CHAN_XR(ah->ah_current_channel) &&
- ah->ah_version == AR5K_AR5212) {
- cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_XR;
- cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_XR;
- ah->ah_aifs = AR5K_TUNE_AIFS_XR;
- /*B mode is not supported on 5210*/
- } else if (IS_CHAN_B(ah->ah_current_channel) &&
- ah->ah_version != AR5K_AR5210) {
- cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_11B;
- cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_11B;
- ah->ah_aifs = AR5K_TUNE_AIFS_11B;
- }
-
- cw_min = 1;
- while (cw_min < ah->ah_cw_min)
- cw_min = (cw_min << 1) | 1;
-
- cw_min = tq->tqi_cw_min < 0 ? (cw_min >> (-tq->tqi_cw_min)) :
- ((cw_min << tq->tqi_cw_min) + (1 << tq->tqi_cw_min) - 1);
- cw_max = tq->tqi_cw_max < 0 ? (cw_max >> (-tq->tqi_cw_max)) :
- ((cw_max << tq->tqi_cw_max) + (1 << tq->tqi_cw_max) - 1);
-
- /*
* Calculate and set retry limits
*/
if (ah->ah_software_retry) {
@@ -292,7 +296,7 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
/*No QCU/DCU [5210]*/
if (ah->ah_version == AR5K_AR5210) {
ath5k_hw_reg_write(ah,
- (cw_min << AR5K_NODCU_RETRY_LMT_CW_MIN_S)
+ (tq->tqi_cw_min << AR5K_NODCU_RETRY_LMT_CW_MIN_S)
| AR5K_REG_SM(AR5K_INIT_SLG_RETRY,
AR5K_NODCU_RETRY_LMT_SLG_RETRY)
| AR5K_REG_SM(AR5K_INIT_SSH_RETRY,
@@ -314,14 +318,13 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
/*===Rest is also for QCU/DCU only [5211+]===*/
/*
- * Set initial content window (cw_min/cw_max)
+ * Set contention window (cw_min/cw_max)
* and arbitrated interframe space (aifs)...
*/
ath5k_hw_reg_write(ah,
- AR5K_REG_SM(cw_min, AR5K_DCU_LCL_IFS_CW_MIN) |
- AR5K_REG_SM(cw_max, AR5K_DCU_LCL_IFS_CW_MAX) |
- AR5K_REG_SM(ah->ah_aifs + tq->tqi_aifs,
- AR5K_DCU_LCL_IFS_AIFS),
+ AR5K_REG_SM(tq->tqi_cw_min, AR5K_DCU_LCL_IFS_CW_MIN) |
+ AR5K_REG_SM(tq->tqi_cw_max, AR5K_DCU_LCL_IFS_CW_MAX) |
+ AR5K_REG_SM(tq->tqi_aifs, AR5K_DCU_LCL_IFS_AIFS),
AR5K_QUEUE_DFS_LOCAL_IFS(queue));
/*
diff --git a/drivers/net/wireless/ath/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h
index 55b4ac6d236f..a34929f06533 100644
--- a/drivers/net/wireless/ath/ath5k/reg.h
+++ b/drivers/net/wireless/ath/ath5k/reg.h
@@ -1387,10 +1387,9 @@
/*
- * PCU control register
+ * PCU Diagnostic register
*
- * Only DIS_RX is used in the code, the rest i guess are
- * for tweaking/diagnostics.
+ * Used for tweaking/diagnostics.
*/
#define AR5K_DIAG_SW_5210 0x8068 /* Register Address [5210] */
#define AR5K_DIAG_SW_5211 0x8048 /* Register Address [5211+] */
@@ -1399,22 +1398,22 @@
#define AR5K_DIAG_SW_DIS_WEP_ACK 0x00000001 /* Disable ACKs if WEP key is invalid */
#define AR5K_DIAG_SW_DIS_ACK 0x00000002 /* Disable ACKs */
#define AR5K_DIAG_SW_DIS_CTS 0x00000004 /* Disable CTSs */
-#define AR5K_DIAG_SW_DIS_ENC 0x00000008 /* Disable encryption */
-#define AR5K_DIAG_SW_DIS_DEC 0x00000010 /* Disable decryption */
-#define AR5K_DIAG_SW_DIS_TX 0x00000020 /* Disable transmit [5210] */
-#define AR5K_DIAG_SW_DIS_RX_5210 0x00000040 /* Disable recieve */
+#define AR5K_DIAG_SW_DIS_ENC 0x00000008 /* Disable HW encryption */
+#define AR5K_DIAG_SW_DIS_DEC 0x00000010 /* Disable HW decryption */
+#define AR5K_DIAG_SW_DIS_TX_5210 0x00000020 /* Disable transmit [5210] */
+#define AR5K_DIAG_SW_DIS_RX_5210 0x00000040 /* Disable receive */
#define AR5K_DIAG_SW_DIS_RX_5211 0x00000020
#define AR5K_DIAG_SW_DIS_RX (ah->ah_version == AR5K_AR5210 ? \
AR5K_DIAG_SW_DIS_RX_5210 : AR5K_DIAG_SW_DIS_RX_5211)
-#define AR5K_DIAG_SW_LOOP_BACK_5210 0x00000080 /* Loopback (i guess it goes with DIS_TX) [5210] */
+#define AR5K_DIAG_SW_LOOP_BACK_5210 0x00000080 /* TX Data Loopback (i guess it goes with DIS_TX) [5210] */
#define AR5K_DIAG_SW_LOOP_BACK_5211 0x00000040
#define AR5K_DIAG_SW_LOOP_BACK (ah->ah_version == AR5K_AR5210 ? \
AR5K_DIAG_SW_LOOP_BACK_5210 : AR5K_DIAG_SW_LOOP_BACK_5211)
-#define AR5K_DIAG_SW_CORR_FCS_5210 0x00000100 /* Corrupted FCS */
+#define AR5K_DIAG_SW_CORR_FCS_5210 0x00000100 /* Generate invalid TX FCS */
#define AR5K_DIAG_SW_CORR_FCS_5211 0x00000080
#define AR5K_DIAG_SW_CORR_FCS (ah->ah_version == AR5K_AR5210 ? \
AR5K_DIAG_SW_CORR_FCS_5210 : AR5K_DIAG_SW_CORR_FCS_5211)
-#define AR5K_DIAG_SW_CHAN_INFO_5210 0x00000200 /* Dump channel info */
+#define AR5K_DIAG_SW_CHAN_INFO_5210 0x00000200 /* Add 56 bytes of channel info before the frame data in the RX buffer */
#define AR5K_DIAG_SW_CHAN_INFO_5211 0x00000100
#define AR5K_DIAG_SW_CHAN_INFO (ah->ah_version == AR5K_AR5210 ? \
AR5K_DIAG_SW_CHAN_INFO_5210 : AR5K_DIAG_SW_CHAN_INFO_5211)
@@ -1426,17 +1425,17 @@
#define AR5K_DIAG_SW_SCVRAM_SEED 0x0003f800 /* [5210] */
#define AR5K_DIAG_SW_SCRAM_SEED_M 0x0001fc00 /* Scrambler seed mask */
#define AR5K_DIAG_SW_SCRAM_SEED_S 10
-#define AR5K_DIAG_SW_DIS_SEQ_INC 0x00040000 /* Disable seqnum increment (?)[5210] */
+#define AR5K_DIAG_SW_DIS_SEQ_INC_5210 0x00040000 /* Disable seqnum increment (?)[5210] */
#define AR5K_DIAG_SW_FRAME_NV0_5210 0x00080000
#define AR5K_DIAG_SW_FRAME_NV0_5211 0x00020000 /* Accept frames of non-zero protocol number */
#define AR5K_DIAG_SW_FRAME_NV0 (ah->ah_version == AR5K_AR5210 ? \
AR5K_DIAG_SW_FRAME_NV0_5210 : AR5K_DIAG_SW_FRAME_NV0_5211)
#define AR5K_DIAG_SW_OBSPT_M 0x000c0000 /* Observation point select (?) */
#define AR5K_DIAG_SW_OBSPT_S 18
-#define AR5K_DIAG_SW_RX_CLEAR_HIGH 0x0010000 /* Force RX Clear high */
-#define AR5K_DIAG_SW_IGNORE_CARR_SENSE 0x0020000 /* Ignore virtual carrier sense */
-#define AR5K_DIAG_SW_CHANEL_IDLE_HIGH 0x0040000 /* Force channel idle high */
-#define AR5K_DIAG_SW_PHEAR_ME 0x0080000 /* ??? */
+#define AR5K_DIAG_SW_RX_CLEAR_HIGH 0x00100000 /* Ignore carrier sense */
+#define AR5K_DIAG_SW_IGNORE_CARR_SENSE 0x00200000 /* Ignore virtual carrier sense */
+#define AR5K_DIAG_SW_CHANNEL_IDLE_HIGH 0x00400000 /* Force channel idle high */
+#define AR5K_DIAG_SW_PHEAR_ME 0x00800000 /* ??? */
/*
* TSF (clock) register (lower 32 bits)
@@ -1822,50 +1821,8 @@
/*===5212 end===*/
-/*
- * Key table (WEP) register
- */
-#define AR5K_KEYTABLE_0_5210 0x9000
-#define AR5K_KEYTABLE_0_5211 0x8800
-#define AR5K_KEYTABLE_5210(_n) (AR5K_KEYTABLE_0_5210 + ((_n) << 5))
-#define AR5K_KEYTABLE_5211(_n) (AR5K_KEYTABLE_0_5211 + ((_n) << 5))
-#define AR5K_KEYTABLE(_n) (ah->ah_version == AR5K_AR5210 ? \
- AR5K_KEYTABLE_5210(_n) : AR5K_KEYTABLE_5211(_n))
-#define AR5K_KEYTABLE_OFF(_n, x) (AR5K_KEYTABLE(_n) + (x << 2))
-#define AR5K_KEYTABLE_TYPE(_n) AR5K_KEYTABLE_OFF(_n, 5)
-#define AR5K_KEYTABLE_TYPE_40 0x00000000
-#define AR5K_KEYTABLE_TYPE_104 0x00000001
-#define AR5K_KEYTABLE_TYPE_128 0x00000003
-#define AR5K_KEYTABLE_TYPE_TKIP 0x00000004 /* [5212+] */
-#define AR5K_KEYTABLE_TYPE_AES 0x00000005 /* [5211+] */
-#define AR5K_KEYTABLE_TYPE_CCM 0x00000006 /* [5212+] */
-#define AR5K_KEYTABLE_TYPE_NULL 0x00000007 /* [5211+] */
-#define AR5K_KEYTABLE_ANTENNA 0x00000008 /* [5212+] */
-#define AR5K_KEYTABLE_MAC0(_n) AR5K_KEYTABLE_OFF(_n, 6)
-#define AR5K_KEYTABLE_MAC1(_n) AR5K_KEYTABLE_OFF(_n, 7)
-#define AR5K_KEYTABLE_VALID 0x00008000
-
-/* If key type is TKIP and MIC is enabled
- * MIC key goes in offset entry + 64 */
-#define AR5K_KEYTABLE_MIC_OFFSET 64
-
-/* WEP 40-bit = 40-bit entered key + 24 bit IV = 64-bit
- * WEP 104-bit = 104-bit entered key + 24-bit IV = 128-bit
- * WEP 128-bit = 128-bit entered key + 24 bit IV = 152-bit
- *
- * Some vendors have introduced bigger WEP keys to address
- * security vulnerabilities in WEP. This includes:
- *
- * WEP 232-bit = 232-bit entered key + 24 bit IV = 256-bit
- *
- * We can expand this if we find ar5k Atheros cards with a larger
- * key table size.
- */
#define AR5K_KEYTABLE_SIZE_5210 64
#define AR5K_KEYTABLE_SIZE_5211 128
-#define AR5K_KEYTABLE_SIZE (ah->ah_version == AR5K_AR5210 ? \
- AR5K_KEYTABLE_SIZE_5210 : AR5K_KEYTABLE_SIZE_5211)
-
/*===PHY REGISTERS===*/
@@ -1911,7 +1868,7 @@
#define AR5K_PHY_TURBO 0x9804 /* Register Address */
#define AR5K_PHY_TURBO_MODE 0x00000001 /* Enable turbo mode */
#define AR5K_PHY_TURBO_SHORT 0x00000002 /* Set short symbols to turbo mode */
-#define AR5K_PHY_TURBO_MIMO 0x00000004 /* Set turbo for mimo mimo */
+#define AR5K_PHY_TURBO_MIMO 0x00000004 /* Set turbo for mimo */
/*
* PHY agility command register
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c
index 498aa28ea9e6..5b179d01f97d 100644
--- a/drivers/net/wireless/ath/ath5k/reset.c
+++ b/drivers/net/wireless/ath/ath5k/reset.c
@@ -167,7 +167,7 @@ static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah,
* ieee80211_duration() for a brief description of
* what rate we should choose to TX ACKs. */
tx_time = le16_to_cpu(ieee80211_generic_frame_duration(sc->hw,
- sc->vif, 10, rate));
+ NULL, 10, rate));
ath5k_hw_reg_write(ah, tx_time, reg);
@@ -326,7 +326,7 @@ commit:
* register). After this MAC and Baseband are
* disabled and a full reset is needed to come
* back. This way we save as much power as possible
- * without puting the card on full sleep.
+ * without putting the card on full sleep.
*/
int ath5k_hw_on_hold(struct ath5k_hw *ah)
{
@@ -344,7 +344,7 @@ int ath5k_hw_on_hold(struct ath5k_hw *ah)
/*
* Put chipset on warm reset...
*
- * Note: puting PCI core on warm reset on PCI-E cards
+ * Note: putting PCI core on warm reset on PCI-E cards
* results card to hang and always return 0xffff... so
* we ingore that flag for PCI-E cards. On PCI cards
* this flag gets cleared after 64 PCI clocks.
@@ -400,7 +400,7 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
/*
* Put chipset on warm reset...
*
- * Note: puting PCI core on warm reset on PCI-E cards
+ * Note: putting PCI core on warm reset on PCI-E cards
* results card to hang and always return 0xffff... so
* we ingore that flag for PCI-E cards. On PCI cards
* this flag gets cleared after 64 PCI clocks.
@@ -959,7 +959,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
AR5K_QUEUE_DCU_SEQNUM(0));
}
- /* TSF accelerates on AR5211 durring reset
+ /* TSF accelerates on AR5211 during reset
* As a workaround save it here and restore
* it later so that it's back in time after
* reset. This way it'll get re-synced on the
@@ -1060,7 +1060,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
* XXX: rethink this after new mode changes to
* mac80211 are integrated */
if (ah->ah_version == AR5K_AR5212 &&
- ah->ah_sc->vif != NULL)
+ ah->ah_sc->nvifs)
ath5k_hw_write_rate_duration(ah, mode);
/*
@@ -1080,7 +1080,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
return ret;
/* Spur info is available only from EEPROM versions
- * bigger than 5.3 but but the EEPOM routines will use
+ * greater than 5.3, but the EEPROM routines will use
* static values for older versions */
if (ah->ah_mac_srev >= AR5K_SREV_AR5424)
ath5k_hw_set_spur_mitigation_filter(ah,
@@ -1160,7 +1160,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
*/
/* Restore bssid and bssid mask */
- ath5k_hw_set_associd(ah);
+ ath5k_hw_set_bssid(ah);
/* Set PCU config */
ath5k_hw_set_opmode(ah, op_mode);
@@ -1173,11 +1173,11 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
/* Set RSSI/BRSSI thresholds
*
* Note: If we decide to set this value
- * dynamicaly, have in mind that when AR5K_RSSI_THR
- * register is read it might return 0x40 if we haven't
- * wrote anything to it plus BMISS RSSI threshold is zeroed.
+ * dynamically, keep in mind that when AR5K_RSSI_THR
+ * register is read, it might return 0x40 if we haven't
+ * written anything to it. Also, BMISS RSSI threshold is zeroed.
* So doing a save/restore procedure here isn't the right
- * choice. Instead store it on ath5k_hw */
+ * choice. Instead, store it in ath5k_hw */
ath5k_hw_reg_write(ah, (AR5K_TUNE_RSSI_THRES |
AR5K_TUNE_BMISS_THRES <<
AR5K_RSSI_THR_BMISS_S),
@@ -1235,7 +1235,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
/*
* Perform ADC test to see if baseband is ready
- * Set tx hold and check adc test register
+ * Set TX hold and check ADC test register
*/
phy_tst1 = ath5k_hw_reg_read(ah, AR5K_PHY_TST1);
ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1);
@@ -1254,15 +1254,15 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
*
* This method is used to calibrate some static offsets
* used together with on-the fly I/Q calibration (the
- * one performed via ath5k_hw_phy_calibrate), that doesn't
+ * one performed via ath5k_hw_phy_calibrate), which doesn't
* interrupt rx path.
*
* While rx path is re-routed to the power detector we also
- * start a noise floor calibration, to measure the
+ * start a noise floor calibration to measure the
* card's noise floor (the noise we measure when we are not
- * transmiting or receiving anything).
+ * transmitting or receiving anything).
*
- * If we are in a noisy environment AGC calibration may time
+ * If we are in a noisy environment, AGC calibration may time
* out and/or noise floor calibration might timeout.
*/
AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
diff --git a/drivers/net/wireless/ath/ath5k/rfbuffer.h b/drivers/net/wireless/ath/ath5k/rfbuffer.h
index e50baff66175..3ac4cff4239d 100644
--- a/drivers/net/wireless/ath/ath5k/rfbuffer.h
+++ b/drivers/net/wireless/ath/ath5k/rfbuffer.h
@@ -25,10 +25,10 @@
*
* We don't write on those registers directly but
* we send a data packet on the chip, using a special register,
- * that holds all the settings we need. After we 've sent the
+ * that holds all the settings we need. After we've sent the
* data packet, we write on another special register to notify hw
* to apply the settings. This is done so that control registers
- * can be dynamicaly programmed during operation and the settings
+ * can be dynamically programmed during operation and the settings
* are applied faster on the hw.
*
* We call each data packet an "RF Bank" and all the data we write
diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig
index 35f23bdc442f..ad57a6d23110 100644
--- a/drivers/net/wireless/ath/ath9k/Kconfig
+++ b/drivers/net/wireless/ath/ath9k/Kconfig
@@ -32,6 +32,14 @@ config ATH9K_DEBUGFS
Also required for changing debug message flags at run time.
+config ATH9K_RATE_CONTROL
+ bool "Atheros ath9k rate control"
+ depends on ATH9K
+ default y
+ ---help---
+ Say Y, if you want to use the ath9k specific rate control
+ module instead of minstrel_ht.
+
config ATH9K_HTC
tristate "Atheros HTC based wireless cards support"
depends on USB && MAC80211
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile
index 973ae4f49f35..aca01621c205 100644
--- a/drivers/net/wireless/ath/ath9k/Makefile
+++ b/drivers/net/wireless/ath/ath9k/Makefile
@@ -5,8 +5,8 @@ ath9k-y += beacon.o \
recv.o \
xmit.o \
virtual.o \
- rc.o
+ath9k-$(CONFIG_ATH9K_RATE_CONTROL) += rc.o
ath9k-$(CONFIG_PCI) += pci.o
ath9k-$(CONFIG_ATHEROS_AR71XX) += ahb.o
ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o
@@ -46,6 +46,7 @@ ath9k_htc-y += htc_hst.o \
htc_drv_txrx.o \
htc_drv_main.o \
htc_drv_beacon.o \
- htc_drv_init.o
+ htc_drv_init.o \
+ htc_drv_gpio.o
obj-$(CONFIG_ATH9K_HTC) += ath9k_htc.o
diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c
index cc648b6ae31c..63ccb39cdcd4 100644
--- a/drivers/net/wireless/ath/ath9k/ani.c
+++ b/drivers/net/wireless/ath/ath9k/ani.c
@@ -14,6 +14,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <linux/kernel.h>
#include "hw.h"
#include "hw-ops.h"
@@ -48,7 +49,7 @@ static const struct ani_ofdm_level_entry ofdm_level_table[] = {
{ 7, 8, 0 } /* lvl 9 */
};
#define ATH9K_ANI_OFDM_NUM_LEVEL \
- (sizeof(ofdm_level_table)/sizeof(ofdm_level_table[0]))
+ ARRAY_SIZE(ofdm_level_table)
#define ATH9K_ANI_OFDM_MAX_LEVEL \
(ATH9K_ANI_OFDM_NUM_LEVEL-1)
#define ATH9K_ANI_OFDM_DEF_LEVEL \
@@ -94,7 +95,7 @@ static const struct ani_cck_level_entry cck_level_table[] = {
};
#define ATH9K_ANI_CCK_NUM_LEVEL \
- (sizeof(cck_level_table)/sizeof(cck_level_table[0]))
+ ARRAY_SIZE(cck_level_table)
#define ATH9K_ANI_CCK_MAX_LEVEL \
(ATH9K_ANI_CCK_NUM_LEVEL-1)
#define ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI \
@@ -102,31 +103,9 @@ static const struct ani_cck_level_entry cck_level_table[] = {
#define ATH9K_ANI_CCK_DEF_LEVEL \
2 /* default level - matches the INI settings */
-/* Private to ani.c */
-static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah)
+static bool use_new_ani(struct ath_hw *ah)
{
- ath9k_hw_private_ops(ah)->ani_lower_immunity(ah);
-}
-
-int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah,
- struct ath9k_channel *chan)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(ah->ani); i++) {
- if (ah->ani[i].c &&
- ah->ani[i].c->channel == chan->channel)
- return i;
- if (ah->ani[i].c == NULL) {
- ah->ani[i].c = chan;
- return i;
- }
- }
-
- ath_print(ath9k_hw_common(ah), ATH_DBG_ANI,
- "No more channel states left. Using channel 0\n");
-
- return 0;
+ return AR_SREV_9300_20_OR_LATER(ah) || modparam_force_new_ani;
}
static void ath9k_hw_update_mibstats(struct ath_hw *ah,
@@ -139,82 +118,34 @@ static void ath9k_hw_update_mibstats(struct ath_hw *ah,
stats->beacons += REG_READ(ah, AR_BEACON_CNT);
}
-static void ath9k_ani_restart_old(struct ath_hw *ah)
+static void ath9k_ani_restart(struct ath_hw *ah)
{
struct ar5416AniState *aniState;
struct ath_common *common = ath9k_hw_common(ah);
+ u32 ofdm_base = 0, cck_base = 0;
if (!DO_ANI(ah))
return;
- aniState = ah->curani;
+ aniState = &ah->curchan->ani;
aniState->listenTime = 0;
- if (aniState->ofdmTrigHigh > AR_PHY_COUNTMAX) {
- aniState->ofdmPhyErrBase = 0;
- ath_print(common, ATH_DBG_ANI,
- "OFDM Trigger is too high for hw counters\n");
- } else {
- aniState->ofdmPhyErrBase =
- AR_PHY_COUNTMAX - aniState->ofdmTrigHigh;
- }
- if (aniState->cckTrigHigh > AR_PHY_COUNTMAX) {
- aniState->cckPhyErrBase = 0;
- ath_print(common, ATH_DBG_ANI,
- "CCK Trigger is too high for hw counters\n");
- } else {
- aniState->cckPhyErrBase =
- AR_PHY_COUNTMAX - aniState->cckTrigHigh;
+ if (!use_new_ani(ah)) {
+ ofdm_base = AR_PHY_COUNTMAX - ah->config.ofdm_trig_high;
+ cck_base = AR_PHY_COUNTMAX - ah->config.cck_trig_high;
}
- ath_print(common, ATH_DBG_ANI,
- "Writing ofdmbase=%u cckbase=%u\n",
- aniState->ofdmPhyErrBase,
- aniState->cckPhyErrBase);
-
- ENABLE_REGWRITE_BUFFER(ah);
-
- REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase);
- REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase);
- REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
- REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
-
- REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
-
- ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
-
- aniState->ofdmPhyErrCount = 0;
- aniState->cckPhyErrCount = 0;
-}
-
-static void ath9k_ani_restart_new(struct ath_hw *ah)
-{
- struct ar5416AniState *aniState;
- struct ath_common *common = ath9k_hw_common(ah);
-
- if (!DO_ANI(ah))
- return;
-
- aniState = ah->curani;
- aniState->listenTime = 0;
-
- aniState->ofdmPhyErrBase = 0;
- aniState->cckPhyErrBase = 0;
ath_print(common, ATH_DBG_ANI,
- "Writing ofdmbase=%08x cckbase=%08x\n",
- aniState->ofdmPhyErrBase,
- aniState->cckPhyErrBase);
+ "Writing ofdmbase=%u cckbase=%u\n", ofdm_base, cck_base);
ENABLE_REGWRITE_BUFFER(ah);
- REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase);
- REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase);
+ REG_WRITE(ah, AR_PHY_ERR_1, ofdm_base);
+ REG_WRITE(ah, AR_PHY_ERR_2, cck_base);
REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
@@ -228,10 +159,7 @@ static void ath9k_hw_ani_ofdm_err_trigger_old(struct ath_hw *ah)
struct ar5416AniState *aniState;
int32_t rssi;
- if (!DO_ANI(ah))
- return;
-
- aniState = ah->curani;
+ aniState = &ah->curchan->ani;
if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
@@ -300,10 +228,7 @@ static void ath9k_hw_ani_cck_err_trigger_old(struct ath_hw *ah)
struct ar5416AniState *aniState;
int32_t rssi;
- if (!DO_ANI(ah))
- return;
-
- aniState = ah->curani;
+ aniState = &ah->curchan->ani;
if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
aniState->noiseImmunityLevel + 1)) {
@@ -335,7 +260,7 @@ static void ath9k_hw_ani_cck_err_trigger_old(struct ath_hw *ah)
/* Adjust the OFDM Noise Immunity Level */
static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel)
{
- struct ar5416AniState *aniState = ah->curani;
+ struct ar5416AniState *aniState = &ah->curchan->ani;
struct ath_common *common = ath9k_hw_common(ah);
const struct ani_ofdm_level_entry *entry_ofdm;
const struct ani_cck_level_entry *entry_cck;
@@ -380,14 +305,19 @@ static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel)
}
}
-static void ath9k_hw_ani_ofdm_err_trigger_new(struct ath_hw *ah)
+static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah)
{
struct ar5416AniState *aniState;
if (!DO_ANI(ah))
return;
- aniState = ah->curani;
+ if (!use_new_ani(ah)) {
+ ath9k_hw_ani_ofdm_err_trigger_old(ah);
+ return;
+ }
+
+ aniState = &ah->curchan->ani;
if (aniState->ofdmNoiseImmunityLevel < ATH9K_ANI_OFDM_MAX_LEVEL)
ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel + 1);
@@ -398,7 +328,7 @@ static void ath9k_hw_ani_ofdm_err_trigger_new(struct ath_hw *ah)
*/
static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel)
{
- struct ar5416AniState *aniState = ah->curani;
+ struct ar5416AniState *aniState = &ah->curchan->ani;
struct ath_common *common = ath9k_hw_common(ah);
const struct ani_ofdm_level_entry *entry_ofdm;
const struct ani_cck_level_entry *entry_cck;
@@ -437,14 +367,19 @@ static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel)
entry_cck->mrc_cck_on);
}
-static void ath9k_hw_ani_cck_err_trigger_new(struct ath_hw *ah)
+static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah)
{
struct ar5416AniState *aniState;
if (!DO_ANI(ah))
return;
- aniState = ah->curani;
+ if (!use_new_ani(ah)) {
+ ath9k_hw_ani_cck_err_trigger_old(ah);
+ return;
+ }
+
+ aniState = &ah->curchan->ani;
if (aniState->cckNoiseImmunityLevel < ATH9K_ANI_CCK_MAX_LEVEL)
ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel + 1);
@@ -455,7 +390,7 @@ static void ath9k_hw_ani_lower_immunity_old(struct ath_hw *ah)
struct ar5416AniState *aniState;
int32_t rssi;
- aniState = ah->curani;
+ aniState = &ah->curchan->ani;
if (ah->opmode == NL80211_IFTYPE_AP) {
if (aniState->firstepLevel > 0) {
@@ -507,11 +442,16 @@ static void ath9k_hw_ani_lower_immunity_old(struct ath_hw *ah)
* only lower either OFDM or CCK errors per turn
* we lower the other one next time
*/
-static void ath9k_hw_ani_lower_immunity_new(struct ath_hw *ah)
+static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah)
{
struct ar5416AniState *aniState;
- aniState = ah->curani;
+ aniState = &ah->curchan->ani;
+
+ if (!use_new_ani(ah)) {
+ ath9k_hw_ani_lower_immunity_old(ah);
+ return;
+ }
/* lower OFDM noise immunity */
if (aniState->ofdmNoiseImmunityLevel > 0 &&
@@ -525,87 +465,18 @@ static void ath9k_hw_ani_lower_immunity_new(struct ath_hw *ah)
ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel - 1);
}
-static u8 ath9k_hw_chan_2_clockrate_mhz(struct ath_hw *ah)
-{
- struct ath9k_channel *chan = ah->curchan;
- struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
- u8 clockrate; /* in MHz */
-
- if (!ah->curchan) /* should really check for CCK instead */
- clockrate = ATH9K_CLOCK_RATE_CCK;
- else if (conf->channel->band == IEEE80211_BAND_2GHZ)
- clockrate = ATH9K_CLOCK_RATE_2GHZ_OFDM;
- else if (IS_CHAN_A_FAST_CLOCK(ah, chan))
- clockrate = ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM;
- else
- clockrate = ATH9K_CLOCK_RATE_5GHZ_OFDM;
-
- if (conf_is_ht40(conf))
- return clockrate * 2;
-
- return clockrate * 2;
-}
-
-static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah)
-{
- struct ar5416AniState *aniState;
- struct ath_common *common = ath9k_hw_common(ah);
- u32 txFrameCount, rxFrameCount, cycleCount;
- int32_t listenTime;
-
- txFrameCount = REG_READ(ah, AR_TFCNT);
- rxFrameCount = REG_READ(ah, AR_RFCNT);
- cycleCount = REG_READ(ah, AR_CCCNT);
-
- aniState = ah->curani;
- if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount) {
- listenTime = 0;
- ah->stats.ast_ani_lzero++;
- ath_print(common, ATH_DBG_ANI,
- "1st call: aniState->cycleCount=%d\n",
- aniState->cycleCount);
- } else {
- int32_t ccdelta = cycleCount - aniState->cycleCount;
- int32_t rfdelta = rxFrameCount - aniState->rxFrameCount;
- int32_t tfdelta = txFrameCount - aniState->txFrameCount;
- int32_t clock_rate;
-
- /*
- * convert HW counter values to ms using mode
- * specifix clock rate
- */
- clock_rate = ath9k_hw_chan_2_clockrate_mhz(ah) * 1000;;
-
- listenTime = (ccdelta - rfdelta - tfdelta) / clock_rate;
-
- ath_print(common, ATH_DBG_ANI,
- "cyclecount=%d, rfcount=%d, "
- "tfcount=%d, listenTime=%d CLOCK_RATE=%d\n",
- ccdelta, rfdelta, tfdelta, listenTime, clock_rate);
- }
-
- aniState->cycleCount = cycleCount;
- aniState->txFrameCount = txFrameCount;
- aniState->rxFrameCount = rxFrameCount;
-
- return listenTime;
-}
-
static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning)
{
struct ar5416AniState *aniState;
struct ath9k_channel *chan = ah->curchan;
struct ath_common *common = ath9k_hw_common(ah);
- int index;
if (!DO_ANI(ah))
return;
- index = ath9k_hw_get_ani_channel_idx(ah, chan);
- aniState = &ah->ani[index];
- ah->curani = aniState;
+ aniState = &ah->curchan->ani;
- if (DO_ANI(ah) && ah->opmode != NL80211_IFTYPE_STATION
+ if (ah->opmode != NL80211_IFTYPE_STATION
&& ah->opmode != NL80211_IFTYPE_ADHOC) {
ath_print(common, ATH_DBG_ANI,
"Reset ANI state opmode %u\n", ah->opmode);
@@ -634,17 +505,7 @@ static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning)
ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) |
ATH9K_RX_FILTER_PHYERR);
- if (ah->opmode == NL80211_IFTYPE_AP) {
- ah->curani->ofdmTrigHigh =
- ah->config.ofdm_trig_high;
- ah->curani->ofdmTrigLow =
- ah->config.ofdm_trig_low;
- ah->curani->cckTrigHigh =
- ah->config.cck_trig_high;
- ah->curani->cckTrigLow =
- ah->config.cck_trig_low;
- }
- ath9k_ani_restart_old(ah);
+ ath9k_ani_restart(ah);
return;
}
@@ -666,7 +527,7 @@ static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning)
ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) &
~ATH9K_RX_FILTER_PHYERR);
- ath9k_ani_restart_old(ah);
+ ath9k_ani_restart(ah);
ENABLE_REGWRITE_BUFFER(ah);
@@ -674,7 +535,6 @@ static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning)
REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
}
/*
@@ -682,15 +542,18 @@ static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning)
* This routine should be called for every hardware reset and for
* every channel change.
*/
-static void ath9k_ani_reset_new(struct ath_hw *ah, bool is_scanning)
+void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning)
{
- struct ar5416AniState *aniState = ah->curani;
+ struct ar5416AniState *aniState = &ah->curchan->ani;
struct ath9k_channel *chan = ah->curchan;
struct ath_common *common = ath9k_hw_common(ah);
if (!DO_ANI(ah))
return;
+ if (!use_new_ani(ah))
+ return ath9k_ani_reset_old(ah, is_scanning);
+
BUG_ON(aniState == NULL);
ah->stats.ast_ani_reset++;
@@ -760,7 +623,7 @@ static void ath9k_ani_reset_new(struct ath_hw *ah, bool is_scanning)
* enable phy counters if hw supports or if not, enable phy
* interrupts (so we can count each one)
*/
- ath9k_ani_restart_new(ah);
+ ath9k_ani_restart(ah);
ENABLE_REGWRITE_BUFFER(ah);
@@ -768,28 +631,30 @@ static void ath9k_ani_reset_new(struct ath_hw *ah, bool is_scanning)
REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
}
-static void ath9k_hw_ani_monitor_old(struct ath_hw *ah,
- struct ath9k_channel *chan)
+static bool ath9k_hw_ani_read_counters(struct ath_hw *ah)
{
- struct ar5416AniState *aniState;
struct ath_common *common = ath9k_hw_common(ah);
- int32_t listenTime;
- u32 phyCnt1, phyCnt2;
+ struct ar5416AniState *aniState = &ah->curchan->ani;
+ u32 ofdm_base = 0;
+ u32 cck_base = 0;
u32 ofdmPhyErrCnt, cckPhyErrCnt;
+ u32 phyCnt1, phyCnt2;
+ int32_t listenTime;
- if (!DO_ANI(ah))
- return;
-
- aniState = ah->curani;
+ ath_hw_cycle_counters_update(common);
+ listenTime = ath_hw_get_listen_time(common);
- listenTime = ath9k_hw_ani_get_listen_time(ah);
- if (listenTime < 0) {
+ if (listenTime <= 0) {
ah->stats.ast_ani_lneg++;
- ath9k_ani_restart_old(ah);
- return;
+ ath9k_ani_restart(ah);
+ return false;
+ }
+
+ if (!use_new_ani(ah)) {
+ ofdm_base = AR_PHY_COUNTMAX - ah->config.ofdm_trig_high;
+ cck_base = AR_PHY_COUNTMAX - ah->config.cck_trig_high;
}
aniState->listenTime += listenTime;
@@ -799,145 +664,55 @@ static void ath9k_hw_ani_monitor_old(struct ath_hw *ah,
phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
- if (phyCnt1 < aniState->ofdmPhyErrBase ||
- phyCnt2 < aniState->cckPhyErrBase) {
- if (phyCnt1 < aniState->ofdmPhyErrBase) {
+ if (!use_new_ani(ah) && (phyCnt1 < ofdm_base || phyCnt2 < cck_base)) {
+ if (phyCnt1 < ofdm_base) {
ath_print(common, ATH_DBG_ANI,
"phyCnt1 0x%x, resetting "
"counter value to 0x%x\n",
- phyCnt1,
- aniState->ofdmPhyErrBase);
- REG_WRITE(ah, AR_PHY_ERR_1,
- aniState->ofdmPhyErrBase);
+ phyCnt1, ofdm_base);
+ REG_WRITE(ah, AR_PHY_ERR_1, ofdm_base);
REG_WRITE(ah, AR_PHY_ERR_MASK_1,
AR_PHY_ERR_OFDM_TIMING);
}
- if (phyCnt2 < aniState->cckPhyErrBase) {
+ if (phyCnt2 < cck_base) {
ath_print(common, ATH_DBG_ANI,
"phyCnt2 0x%x, resetting "
"counter value to 0x%x\n",
- phyCnt2,
- aniState->cckPhyErrBase);
- REG_WRITE(ah, AR_PHY_ERR_2,
- aniState->cckPhyErrBase);
+ phyCnt2, cck_base);
+ REG_WRITE(ah, AR_PHY_ERR_2, cck_base);
REG_WRITE(ah, AR_PHY_ERR_MASK_2,
AR_PHY_ERR_CCK_TIMING);
}
- return;
+ return false;
}
- ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
+ ofdmPhyErrCnt = phyCnt1 - ofdm_base;
ah->stats.ast_ani_ofdmerrs +=
ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
- cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
+ cckPhyErrCnt = phyCnt2 - cck_base;
ah->stats.ast_ani_cckerrs +=
cckPhyErrCnt - aniState->cckPhyErrCount;
aniState->cckPhyErrCount = cckPhyErrCnt;
-
- if (aniState->listenTime > 5 * ah->aniperiod) {
- if (aniState->ofdmPhyErrCount <= aniState->listenTime *
- aniState->ofdmTrigLow / 1000 &&
- aniState->cckPhyErrCount <= aniState->listenTime *
- aniState->cckTrigLow / 1000)
- ath9k_hw_ani_lower_immunity(ah);
- ath9k_ani_restart_old(ah);
- } else if (aniState->listenTime > ah->aniperiod) {
- if (aniState->ofdmPhyErrCount > aniState->listenTime *
- aniState->ofdmTrigHigh / 1000) {
- ath9k_hw_ani_ofdm_err_trigger_old(ah);
- ath9k_ani_restart_old(ah);
- } else if (aniState->cckPhyErrCount >
- aniState->listenTime * aniState->cckTrigHigh /
- 1000) {
- ath9k_hw_ani_cck_err_trigger_old(ah);
- ath9k_ani_restart_old(ah);
- }
- }
+ return true;
}
-static void ath9k_hw_ani_monitor_new(struct ath_hw *ah,
- struct ath9k_channel *chan)
+void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan)
{
struct ar5416AniState *aniState;
struct ath_common *common = ath9k_hw_common(ah);
- int32_t listenTime;
- u32 phyCnt1, phyCnt2;
- u32 ofdmPhyErrCnt, cckPhyErrCnt;
u32 ofdmPhyErrRate, cckPhyErrRate;
if (!DO_ANI(ah))
return;
- aniState = ah->curani;
+ aniState = &ah->curchan->ani;
if (WARN_ON(!aniState))
return;
- listenTime = ath9k_hw_ani_get_listen_time(ah);
- if (listenTime <= 0) {
- ah->stats.ast_ani_lneg++;
- /* restart ANI period if listenTime is invalid */
- ath_print(common, ATH_DBG_ANI,
- "listenTime=%d - on new ani monitor\n",
- listenTime);
- ath9k_ani_restart_new(ah);
- return;
- }
-
- aniState->listenTime += listenTime;
-
- ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
-
- phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
- phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
-
- if (phyCnt1 < aniState->ofdmPhyErrBase ||
- phyCnt2 < aniState->cckPhyErrBase) {
- if (phyCnt1 < aniState->ofdmPhyErrBase) {
- ath_print(common, ATH_DBG_ANI,
- "phyCnt1 0x%x, resetting "
- "counter value to 0x%x\n",
- phyCnt1,
- aniState->ofdmPhyErrBase);
- REG_WRITE(ah, AR_PHY_ERR_1,
- aniState->ofdmPhyErrBase);
- REG_WRITE(ah, AR_PHY_ERR_MASK_1,
- AR_PHY_ERR_OFDM_TIMING);
- }
- if (phyCnt2 < aniState->cckPhyErrBase) {
- ath_print(common, ATH_DBG_ANI,
- "phyCnt2 0x%x, resetting "
- "counter value to 0x%x\n",
- phyCnt2,
- aniState->cckPhyErrBase);
- REG_WRITE(ah, AR_PHY_ERR_2,
- aniState->cckPhyErrBase);
- REG_WRITE(ah, AR_PHY_ERR_MASK_2,
- AR_PHY_ERR_CCK_TIMING);
- }
+ if (!ath9k_hw_ani_read_counters(ah))
return;
- }
-
- ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
- ah->stats.ast_ani_ofdmerrs +=
- ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
- aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
-
- cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
- ah->stats.ast_ani_cckerrs +=
- cckPhyErrCnt - aniState->cckPhyErrCount;
- aniState->cckPhyErrCount = cckPhyErrCnt;
-
- ath_print(common, ATH_DBG_ANI,
- "Errors: OFDM=0x%08x-0x%08x=%d "
- "CCK=0x%08x-0x%08x=%d\n",
- phyCnt1,
- aniState->ofdmPhyErrBase,
- ofdmPhyErrCnt,
- phyCnt2,
- aniState->cckPhyErrBase,
- cckPhyErrCnt);
ofdmPhyErrRate = aniState->ofdmPhyErrCount * 1000 /
aniState->listenTime;
@@ -947,61 +722,34 @@ static void ath9k_hw_ani_monitor_new(struct ath_hw *ah,
ath_print(common, ATH_DBG_ANI,
"listenTime=%d OFDM:%d errs=%d/s CCK:%d "
"errs=%d/s ofdm_turn=%d\n",
- listenTime, aniState->ofdmNoiseImmunityLevel,
+ aniState->listenTime,
+ aniState->ofdmNoiseImmunityLevel,
ofdmPhyErrRate, aniState->cckNoiseImmunityLevel,
cckPhyErrRate, aniState->ofdmsTurn);
if (aniState->listenTime > 5 * ah->aniperiod) {
- if (ofdmPhyErrRate <= aniState->ofdmTrigLow &&
- cckPhyErrRate <= aniState->cckTrigLow) {
- ath_print(common, ATH_DBG_ANI,
- "1. listenTime=%d OFDM:%d errs=%d/s(<%d) "
- "CCK:%d errs=%d/s(<%d) -> "
- "ath9k_hw_ani_lower_immunity()\n",
- aniState->listenTime,
- aniState->ofdmNoiseImmunityLevel,
- ofdmPhyErrRate,
- aniState->ofdmTrigLow,
- aniState->cckNoiseImmunityLevel,
- cckPhyErrRate,
- aniState->cckTrigLow);
+ if (ofdmPhyErrRate <= ah->config.ofdm_trig_low &&
+ cckPhyErrRate <= ah->config.cck_trig_low) {
ath9k_hw_ani_lower_immunity(ah);
aniState->ofdmsTurn = !aniState->ofdmsTurn;
}
- ath_print(common, ATH_DBG_ANI,
- "1 listenTime=%d ofdm=%d/s cck=%d/s - "
- "calling ath9k_ani_restart_new()\n",
- aniState->listenTime, ofdmPhyErrRate, cckPhyErrRate);
- ath9k_ani_restart_new(ah);
+ ath9k_ani_restart(ah);
} else if (aniState->listenTime > ah->aniperiod) {
/* check to see if need to raise immunity */
- if (ofdmPhyErrRate > aniState->ofdmTrigHigh &&
- (cckPhyErrRate <= aniState->cckTrigHigh ||
+ if (ofdmPhyErrRate > ah->config.ofdm_trig_high &&
+ (cckPhyErrRate <= ah->config.cck_trig_high ||
aniState->ofdmsTurn)) {
- ath_print(common, ATH_DBG_ANI,
- "2 listenTime=%d OFDM:%d errs=%d/s(>%d) -> "
- "ath9k_hw_ani_ofdm_err_trigger_new()\n",
- aniState->listenTime,
- aniState->ofdmNoiseImmunityLevel,
- ofdmPhyErrRate,
- aniState->ofdmTrigHigh);
- ath9k_hw_ani_ofdm_err_trigger_new(ah);
- ath9k_ani_restart_new(ah);
+ ath9k_hw_ani_ofdm_err_trigger(ah);
+ ath9k_ani_restart(ah);
aniState->ofdmsTurn = false;
- } else if (cckPhyErrRate > aniState->cckTrigHigh) {
- ath_print(common, ATH_DBG_ANI,
- "3 listenTime=%d CCK:%d errs=%d/s(>%d) -> "
- "ath9k_hw_ani_cck_err_trigger_new()\n",
- aniState->listenTime,
- aniState->cckNoiseImmunityLevel,
- cckPhyErrRate,
- aniState->cckTrigHigh);
- ath9k_hw_ani_cck_err_trigger_new(ah);
- ath9k_ani_restart_new(ah);
+ } else if (cckPhyErrRate > ah->config.cck_trig_high) {
+ ath9k_hw_ani_cck_err_trigger(ah);
+ ath9k_ani_restart(ah);
aniState->ofdmsTurn = true;
}
}
}
+EXPORT_SYMBOL(ath9k_hw_ani_monitor);
void ath9k_enable_mib_counters(struct ath_hw *ah)
{
@@ -1022,7 +770,6 @@ void ath9k_enable_mib_counters(struct ath_hw *ah)
REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
}
/* Freeze the MIB counters, get the stats and then clear them */
@@ -1040,53 +787,12 @@ void ath9k_hw_disable_mib_counters(struct ath_hw *ah)
}
EXPORT_SYMBOL(ath9k_hw_disable_mib_counters);
-u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah,
- u32 *rxc_pcnt,
- u32 *rxf_pcnt,
- u32 *txf_pcnt)
-{
- struct ath_common *common = ath9k_hw_common(ah);
- static u32 cycles, rx_clear, rx_frame, tx_frame;
- u32 good = 1;
-
- u32 rc = REG_READ(ah, AR_RCCNT);
- u32 rf = REG_READ(ah, AR_RFCNT);
- u32 tf = REG_READ(ah, AR_TFCNT);
- u32 cc = REG_READ(ah, AR_CCCNT);
-
- if (cycles == 0 || cycles > cc) {
- ath_print(common, ATH_DBG_ANI,
- "cycle counter wrap. ExtBusy = 0\n");
- good = 0;
- } else {
- u32 cc_d = cc - cycles;
- u32 rc_d = rc - rx_clear;
- u32 rf_d = rf - rx_frame;
- u32 tf_d = tf - tx_frame;
-
- if (cc_d != 0) {
- *rxc_pcnt = rc_d * 100 / cc_d;
- *rxf_pcnt = rf_d * 100 / cc_d;
- *txf_pcnt = tf_d * 100 / cc_d;
- } else {
- good = 0;
- }
- }
-
- cycles = cc;
- rx_frame = rf;
- rx_clear = rc;
- tx_frame = tf;
-
- return good;
-}
-
/*
* Process a MIB interrupt. We may potentially be invoked because
* any of the MIB counters overflow/trigger so don't assume we're
* here because a PHY error counter triggered.
*/
-static void ath9k_hw_proc_mib_event_old(struct ath_hw *ah)
+void ath9k_hw_proc_mib_event(struct ath_hw *ah)
{
u32 phyCnt1, phyCnt2;
@@ -1114,72 +820,15 @@ static void ath9k_hw_proc_mib_event_old(struct ath_hw *ah)
phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) ||
((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) {
- struct ar5416AniState *aniState = ah->curani;
- u32 ofdmPhyErrCnt, cckPhyErrCnt;
-
- /* NB: only use ast_ani_*errs with AH_PRIVATE_DIAG */
- ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
- ah->stats.ast_ani_ofdmerrs +=
- ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
- aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
- cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
- ah->stats.ast_ani_cckerrs +=
- cckPhyErrCnt - aniState->cckPhyErrCount;
- aniState->cckPhyErrCount = cckPhyErrCnt;
+ if (!use_new_ani(ah))
+ ath9k_hw_ani_read_counters(ah);
- /*
- * NB: figure out which counter triggered. If both
- * trigger we'll only deal with one as the processing
- * clobbers the error counter so the trigger threshold
- * check will never be true.
- */
- if (aniState->ofdmPhyErrCount > aniState->ofdmTrigHigh)
- ath9k_hw_ani_ofdm_err_trigger_new(ah);
- if (aniState->cckPhyErrCount > aniState->cckTrigHigh)
- ath9k_hw_ani_cck_err_trigger_old(ah);
/* NB: always restart to insure the h/w counters are reset */
- ath9k_ani_restart_old(ah);
- }
-}
-
-/*
- * Process a MIB interrupt. We may potentially be invoked because
- * any of the MIB counters overflow/trigger so don't assume we're
- * here because a PHY error counter triggered.
- */
-static void ath9k_hw_proc_mib_event_new(struct ath_hw *ah)
-{
- u32 phyCnt1, phyCnt2;
-
- /* Reset these counters regardless */
- REG_WRITE(ah, AR_FILT_OFDM, 0);
- REG_WRITE(ah, AR_FILT_CCK, 0);
- if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING))
- REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR);
-
- /* Clear the mib counters and save them in the stats */
- ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
-
- if (!DO_ANI(ah)) {
- /*
- * We must always clear the interrupt cause by
- * resetting the phy error regs.
- */
- REG_WRITE(ah, AR_PHY_ERR_1, 0);
- REG_WRITE(ah, AR_PHY_ERR_2, 0);
- return;
+ ath9k_ani_restart(ah);
}
-
- /* NB: these are not reset-on-read */
- phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
- phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
-
- /* NB: always restart to insure the h/w counters are reset */
- if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) ||
- ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK))
- ath9k_ani_restart_new(ah);
}
+EXPORT_SYMBOL(ath9k_hw_proc_mib_event);
void ath9k_hw_ani_setup(struct ath_hw *ah)
{
@@ -1205,61 +854,58 @@ void ath9k_hw_ani_init(struct ath_hw *ah)
ath_print(common, ATH_DBG_ANI, "Initialize ANI\n");
- memset(ah->ani, 0, sizeof(ah->ani));
- for (i = 0; i < ARRAY_SIZE(ah->ani); i++) {
- if (AR_SREV_9300_20_OR_LATER(ah) || modparam_force_new_ani) {
- ah->ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH_NEW;
- ah->ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW_NEW;
+ if (use_new_ani(ah)) {
+ ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_NEW;
+ ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW_NEW;
- ah->ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH_NEW;
- ah->ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW_NEW;
+ ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH_NEW;
+ ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW_NEW;
+ } else {
+ ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_OLD;
+ ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW_OLD;
- ah->ani[i].spurImmunityLevel =
- ATH9K_ANI_SPUR_IMMUNE_LVL_NEW;
+ ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH_OLD;
+ ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW_OLD;
+ }
- ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW;
+ for (i = 0; i < ARRAY_SIZE(ah->channels); i++) {
+ struct ath9k_channel *chan = &ah->channels[i];
+ struct ar5416AniState *ani = &chan->ani;
- ah->ani[i].ofdmPhyErrBase = 0;
- ah->ani[i].cckPhyErrBase = 0;
+ if (use_new_ani(ah)) {
+ ani->spurImmunityLevel =
+ ATH9K_ANI_SPUR_IMMUNE_LVL_NEW;
+
+ ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW;
if (AR_SREV_9300_20_OR_LATER(ah))
- ah->ani[i].mrcCCKOff =
+ ani->mrcCCKOff =
!ATH9K_ANI_ENABLE_MRC_CCK;
else
- ah->ani[i].mrcCCKOff = true;
+ ani->mrcCCKOff = true;
- ah->ani[i].ofdmsTurn = true;
+ ani->ofdmsTurn = true;
} else {
- ah->ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH_OLD;
- ah->ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW_OLD;
-
- ah->ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH_OLD;
- ah->ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW_OLD;
-
- ah->ani[i].spurImmunityLevel =
+ ani->spurImmunityLevel =
ATH9K_ANI_SPUR_IMMUNE_LVL_OLD;
- ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL_OLD;
+ ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_OLD;
- ah->ani[i].ofdmPhyErrBase =
- AR_PHY_COUNTMAX - ATH9K_ANI_OFDM_TRIG_HIGH_OLD;
- ah->ani[i].cckPhyErrBase =
- AR_PHY_COUNTMAX - ATH9K_ANI_CCK_TRIG_HIGH_OLD;
- ah->ani[i].cckWeakSigThreshold =
+ ani->cckWeakSigThreshold =
ATH9K_ANI_CCK_WEAK_SIG_THR;
}
- ah->ani[i].rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH;
- ah->ani[i].rssiThrLow = ATH9K_ANI_RSSI_THR_LOW;
- ah->ani[i].ofdmWeakSigDetectOff =
+ ani->rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH;
+ ani->rssiThrLow = ATH9K_ANI_RSSI_THR_LOW;
+ ani->ofdmWeakSigDetectOff =
!ATH9K_ANI_USE_OFDM_WEAK_SIG;
- ah->ani[i].cckNoiseImmunityLevel = ATH9K_ANI_CCK_DEF_LEVEL;
+ ani->cckNoiseImmunityLevel = ATH9K_ANI_CCK_DEF_LEVEL;
}
/*
* since we expect some ongoing maintenance on the tables, let's sanity
* check here default level should not modify INI setting.
*/
- if (AR_SREV_9300_20_OR_LATER(ah) || modparam_force_new_ani) {
+ if (use_new_ani(ah)) {
const struct ani_ofdm_level_entry *entry_ofdm;
const struct ani_cck_level_entry *entry_cck;
@@ -1273,50 +919,9 @@ void ath9k_hw_ani_init(struct ath_hw *ah)
ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_OLD;
}
- ath_print(common, ATH_DBG_ANI,
- "Setting OfdmErrBase = 0x%08x\n",
- ah->ani[0].ofdmPhyErrBase);
- ath_print(common, ATH_DBG_ANI, "Setting cckErrBase = 0x%08x\n",
- ah->ani[0].cckPhyErrBase);
-
- ENABLE_REGWRITE_BUFFER(ah);
-
- REG_WRITE(ah, AR_PHY_ERR_1, ah->ani[0].ofdmPhyErrBase);
- REG_WRITE(ah, AR_PHY_ERR_2, ah->ani[0].cckPhyErrBase);
-
- REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
-
- ath9k_enable_mib_counters(ah);
-
if (ah->config.enable_ani)
ah->proc_phyerr |= HAL_PROCESS_ANI;
-}
-
-void ath9k_hw_attach_ani_ops_old(struct ath_hw *ah)
-{
- struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
- struct ath_hw_ops *ops = ath9k_hw_ops(ah);
-
- priv_ops->ani_reset = ath9k_ani_reset_old;
- priv_ops->ani_lower_immunity = ath9k_hw_ani_lower_immunity_old;
-
- ops->ani_proc_mib_event = ath9k_hw_proc_mib_event_old;
- ops->ani_monitor = ath9k_hw_ani_monitor_old;
- ath_print(ath9k_hw_common(ah), ATH_DBG_ANY, "Using ANI v1\n");
-}
-
-void ath9k_hw_attach_ani_ops_new(struct ath_hw *ah)
-{
- struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
- struct ath_hw_ops *ops = ath9k_hw_ops(ah);
-
- priv_ops->ani_reset = ath9k_ani_reset_new;
- priv_ops->ani_lower_immunity = ath9k_hw_ani_lower_immunity_new;
-
- ops->ani_proc_mib_event = ath9k_hw_proc_mib_event_new;
- ops->ani_monitor = ath9k_hw_ani_monitor_new;
-
- ath_print(ath9k_hw_common(ah), ATH_DBG_ANY, "Using ANI v2\n");
+ ath9k_ani_restart(ah);
+ ath9k_enable_mib_counters(ah);
}
diff --git a/drivers/net/wireless/ath/ath9k/ani.h b/drivers/net/wireless/ath/ath9k/ani.h
index f4d0a4d48b37..0cd6783de883 100644
--- a/drivers/net/wireless/ath/ath9k/ani.h
+++ b/drivers/net/wireless/ath/ath9k/ani.h
@@ -19,7 +19,7 @@
#define HAL_PROCESS_ANI 0x00000001
-#define DO_ANI(ah) (((ah)->proc_phyerr & HAL_PROCESS_ANI))
+#define DO_ANI(ah) (((ah)->proc_phyerr & HAL_PROCESS_ANI) && ah->curchan)
#define BEACON_RSSI(ahp) (ahp->stats.avgbrssi)
@@ -123,20 +123,11 @@ struct ar5416AniState {
u8 ofdmWeakSigDetectOff;
u8 cckWeakSigThreshold;
u32 listenTime;
- u32 ofdmTrigHigh;
- u32 ofdmTrigLow;
- int32_t cckTrigHigh;
- int32_t cckTrigLow;
int32_t rssiThrLow;
int32_t rssiThrHigh;
u32 noiseFloor;
- u32 txFrameCount;
- u32 rxFrameCount;
- u32 cycleCount;
u32 ofdmPhyErrCount;
u32 cckPhyErrCount;
- u32 ofdmPhyErrBase;
- u32 cckPhyErrBase;
int16_t pktRssi[2];
int16_t ofdmErrRssi[2];
int16_t cckErrRssi[2];
@@ -166,8 +157,6 @@ struct ar5416Stats {
void ath9k_enable_mib_counters(struct ath_hw *ah);
void ath9k_hw_disable_mib_counters(struct ath_hw *ah);
-u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, u32 *rxc_pcnt,
- u32 *rxf_pcnt, u32 *txf_pcnt);
void ath9k_hw_ani_setup(struct ath_hw *ah);
void ath9k_hw_ani_init(struct ath_hw *ah);
int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah,
diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
index 3d2c8679bc85..ea9f4497f58c 100644
--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
@@ -118,7 +118,7 @@ static void ar5008_hw_force_bias(struct ath_hw *ah, u16 synth_freq)
if (!AR_SREV_5416(ah) || synth_freq >= 3000)
return;
- BUG_ON(AR_SREV_9280_10_OR_LATER(ah));
+ BUG_ON(AR_SREV_9280_20_OR_LATER(ah));
if (synth_freq < 2412)
new_bias = 0;
@@ -454,7 +454,7 @@ static int ar5008_hw_rf_alloc_ext_banks(struct ath_hw *ah)
struct ath_common *common = ath9k_hw_common(ah);
- BUG_ON(AR_SREV_9280_10_OR_LATER(ah));
+ BUG_ON(AR_SREV_9280_20_OR_LATER(ah));
ATH_ALLOC_BANK(ah->analogBank0Data, ah->iniBank0.ia_rows);
ATH_ALLOC_BANK(ah->analogBank1Data, ah->iniBank1.ia_rows);
@@ -484,7 +484,7 @@ static void ar5008_hw_rf_free_ext_banks(struct ath_hw *ah)
bank = NULL; \
} while (0);
- BUG_ON(AR_SREV_9280_10_OR_LATER(ah));
+ BUG_ON(AR_SREV_9280_20_OR_LATER(ah));
ATH_FREE_BANK(ah->analogBank0Data);
ATH_FREE_BANK(ah->analogBank1Data);
@@ -525,7 +525,7 @@ static bool ar5008_hw_set_rf_regs(struct ath_hw *ah,
* for single chip devices, that is AR9280 or anything
* after that.
*/
- if (AR_SREV_9280_10_OR_LATER(ah))
+ if (AR_SREV_9280_20_OR_LATER(ah))
return true;
/* Setup rf parameters */
@@ -613,14 +613,11 @@ static void ar5008_hw_init_chain_masks(struct ath_hw *ah)
rx_chainmask = ah->rxchainmask;
tx_chainmask = ah->txchainmask;
- ENABLE_REGWRITE_BUFFER(ah);
switch (rx_chainmask) {
case 0x5:
- DISABLE_REGWRITE_BUFFER(ah);
REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
AR_PHY_SWAP_ALT_CHAIN);
- ENABLE_REGWRITE_BUFFER(ah);
case 0x3:
if (ah->hw_version.macVersion == AR_SREV_REVISION_5416_10) {
REG_WRITE(ah, AR_PHY_RX_CHAINMASK, 0x7);
@@ -630,17 +627,18 @@ static void ar5008_hw_init_chain_masks(struct ath_hw *ah)
case 0x1:
case 0x2:
case 0x7:
+ ENABLE_REGWRITE_BUFFER(ah);
REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask);
REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask);
break;
default:
+ ENABLE_REGWRITE_BUFFER(ah);
break;
}
REG_WRITE(ah, AR_SELFGEN_MASK, tx_chainmask);
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
if (tx_chainmask == 0x5) {
REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
@@ -663,20 +661,20 @@ static void ar5008_hw_override_ini(struct ath_hw *ah,
*/
REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
- if (AR_SREV_9280_10_OR_LATER(ah)) {
+ if (AR_SREV_9280_20_OR_LATER(ah)) {
val = REG_READ(ah, AR_PCU_MISC_MODE2);
if (!AR_SREV_9271(ah))
val &= ~AR_PCU_MISC_MODE2_HWWAR1;
- if (AR_SREV_9287_10_OR_LATER(ah))
+ if (AR_SREV_9287_11_OR_LATER(ah))
val = val & (~AR_PCU_MISC_MODE2_HWWAR2);
REG_WRITE(ah, AR_PCU_MISC_MODE2, val);
}
if (!AR_SREV_5416_20_OR_LATER(ah) ||
- AR_SREV_9280_10_OR_LATER(ah))
+ AR_SREV_9280_20_OR_LATER(ah))
return;
/*
* Disable BB clock gating
@@ -701,7 +699,7 @@ static void ar5008_hw_set_channel_regs(struct ath_hw *ah,
u32 phymode;
u32 enableDacFifo = 0;
- if (AR_SREV_9285_10_OR_LATER(ah))
+ if (AR_SREV_9285_12_OR_LATER(ah))
enableDacFifo = (REG_READ(ah, AR_PHY_TURBO) &
AR_PHY_FC_ENABLE_DAC_FIFO);
@@ -726,7 +724,6 @@ static void ar5008_hw_set_channel_regs(struct ath_hw *ah,
REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S);
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
}
@@ -818,13 +815,12 @@ static int ar5008_hw_process_ini(struct ath_hw *ah,
}
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
- if (AR_SREV_9280(ah) || AR_SREV_9287_10_OR_LATER(ah))
+ if (AR_SREV_9280(ah) || AR_SREV_9287_11_OR_LATER(ah))
REG_WRITE_ARRAY(&ah->iniModesRxGain, modesIndex, regWrites);
if (AR_SREV_9280(ah) || AR_SREV_9285_12_OR_LATER(ah) ||
- AR_SREV_9287_10_OR_LATER(ah))
+ AR_SREV_9287_11_OR_LATER(ah))
REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites);
if (AR_SREV_9271_10(ah))
@@ -849,7 +845,6 @@ static int ar5008_hw_process_ini(struct ath_hw *ah,
}
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
if (AR_SREV_9271(ah)) {
if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) == 1)
@@ -900,7 +895,7 @@ static void ar5008_hw_set_rfmode(struct ath_hw *ah, struct ath9k_channel *chan)
rfMode |= (IS_CHAN_B(chan) || IS_CHAN_G(chan))
? AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM;
- if (!AR_SREV_9280_10_OR_LATER(ah))
+ if (!AR_SREV_9280_20_OR_LATER(ah))
rfMode |= (IS_CHAN_5GHZ(chan)) ?
AR_PHY_MODE_RF5GHZ : AR_PHY_MODE_RF2GHZ;
@@ -1053,7 +1048,7 @@ static bool ar5008_hw_ani_control_old(struct ath_hw *ah,
enum ath9k_ani_cmd cmd,
int param)
{
- struct ar5416AniState *aniState = ah->curani;
+ struct ar5416AniState *aniState = &ah->curchan->ani;
struct ath_common *common = ath9k_hw_common(ah);
switch (cmd & ah->ani_function) {
@@ -1225,8 +1220,7 @@ static bool ar5008_hw_ani_control_old(struct ath_hw *ah,
aniState->firstepLevel,
aniState->listenTime);
ath_print(common, ATH_DBG_ANI,
- "cycleCount=%d, ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n",
- aniState->cycleCount,
+ "ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n",
aniState->ofdmPhyErrCount,
aniState->cckPhyErrCount);
@@ -1237,9 +1231,9 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
enum ath9k_ani_cmd cmd,
int param)
{
- struct ar5416AniState *aniState = ah->curani;
struct ath_common *common = ath9k_hw_common(ah);
struct ath9k_channel *chan = ah->curchan;
+ struct ar5416AniState *aniState = &chan->ani;
s32 value, value2;
switch (cmd & ah->ani_function) {
@@ -1478,15 +1472,13 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
ath_print(common, ATH_DBG_ANI,
"ANI parameters: SI=%d, ofdmWS=%s FS=%d "
- "MRCcck=%s listenTime=%d CC=%d listen=%d "
+ "MRCcck=%s listenTime=%d "
"ofdmErrs=%d cckErrs=%d\n",
aniState->spurImmunityLevel,
!aniState->ofdmWeakSigDetectOff ? "on" : "off",
aniState->firstepLevel,
!aniState->mrcCCKOff ? "on" : "off",
aniState->listenTime,
- aniState->cycleCount,
- aniState->listenTime,
aniState->ofdmPhyErrCount,
aniState->cckPhyErrCount);
return true;
@@ -1526,16 +1518,12 @@ static void ar5008_hw_do_getnf(struct ath_hw *ah,
*/
static void ar5008_hw_ani_cache_ini_regs(struct ath_hw *ah)
{
- struct ar5416AniState *aniState;
struct ath_common *common = ath9k_hw_common(ah);
struct ath9k_channel *chan = ah->curchan;
+ struct ar5416AniState *aniState = &chan->ani;
struct ath9k_ani_default *iniDef;
- int index;
u32 val;
- index = ath9k_hw_get_ani_channel_idx(ah, chan);
- aniState = &ah->ani[index];
- ah->curani = aniState;
iniDef = &aniState->iniDef;
ath_print(common, ATH_DBG_ANI,
@@ -1579,8 +1567,6 @@ static void ar5008_hw_ani_cache_ini_regs(struct ath_hw *ah)
aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW;
aniState->ofdmWeakSigDetectOff = !ATH9K_ANI_USE_OFDM_WEAK_SIG;
aniState->mrcCCKOff = true; /* not available on pre AR9003 */
-
- aniState->cycleCount = 0;
}
static void ar5008_hw_set_nf_limits(struct ath_hw *ah)
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
index fe7418aefc4a..15f62cd0cc38 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
@@ -20,6 +20,13 @@
#define AR9285_CLCAL_REDO_THRESH 1
+enum ar9002_cal_types {
+ ADC_GAIN_CAL = BIT(0),
+ ADC_DC_CAL = BIT(1),
+ IQ_MISMATCH_CAL = BIT(2),
+};
+
+
static void ar9002_hw_setup_calibration(struct ath_hw *ah,
struct ath9k_cal_list *currCal)
{
@@ -45,13 +52,6 @@ static void ar9002_hw_setup_calibration(struct ath_hw *ah,
ath_print(common, ATH_DBG_CALIBRATE,
"starting ADC DC Calibration\n");
break;
- case ADC_DC_INIT_CAL:
- REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT);
- ath_print(common, ATH_DBG_CALIBRATE,
- "starting Init ADC DC Calibration\n");
- break;
- case TEMP_COMP_CAL:
- break; /* Not supported */
}
REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
@@ -96,25 +96,6 @@ static bool ar9002_hw_per_calibration(struct ath_hw *ah,
return iscaldone;
}
-/* Assumes you are talking about the currently configured channel */
-static bool ar9002_hw_iscal_supported(struct ath_hw *ah,
- enum ath9k_cal_types calType)
-{
- struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
-
- switch (calType & ah->supp_cals) {
- case IQ_MISMATCH_CAL: /* Both 2 GHz and 5 GHz support OFDM */
- return true;
- case ADC_GAIN_CAL:
- case ADC_DC_CAL:
- if (!(conf->channel->band == IEEE80211_BAND_2GHZ &&
- conf_is_ht20(conf)))
- return true;
- break;
- }
- return false;
-}
-
static void ar9002_hw_iqcal_collect(struct ath_hw *ah)
{
int i;
@@ -541,7 +522,6 @@ static void ar9271_hw_pa_cal(struct ath_hw *ah, bool is_reset)
REG_WRITE(ah, regList[i][0], regList[i][1]);
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
}
static inline void ar9285_hw_pa_cal(struct ath_hw *ah, bool is_reset)
@@ -567,11 +547,6 @@ static inline void ar9285_hw_pa_cal(struct ath_hw *ah, bool is_reset)
AR5416_EEP_TXGAIN_HIGH_POWER)
return;
- if (AR_SREV_9285_11(ah)) {
- REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14));
- udelay(10);
- }
-
for (i = 0; i < ARRAY_SIZE(regList); i++)
regList[i][1] = REG_READ(ah, regList[i][0]);
@@ -651,10 +626,6 @@ static inline void ar9285_hw_pa_cal(struct ath_hw *ah, bool is_reset)
REG_WRITE(ah, regList[i][0], regList[i][1]);
REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, ccomp_org);
-
- if (AR_SREV_9285_11(ah))
- REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT);
-
}
static void ar9002_hw_pa_cal(struct ath_hw *ah, bool is_reset)
@@ -664,7 +635,7 @@ static void ar9002_hw_pa_cal(struct ath_hw *ah, bool is_reset)
ar9271_hw_pa_cal(ah, is_reset);
else
ah->pacal_info.skipcount--;
- } else if (AR_SREV_9285_11_OR_LATER(ah)) {
+ } else if (AR_SREV_9285_12_OR_LATER(ah)) {
if (is_reset || !ah->pacal_info.skipcount)
ar9285_hw_pa_cal(ah, is_reset);
else
@@ -841,8 +812,8 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
if (!ar9285_hw_clc(ah, chan))
return false;
} else {
- if (AR_SREV_9280_10_OR_LATER(ah)) {
- if (!AR_SREV_9287_10_OR_LATER(ah))
+ if (AR_SREV_9280_20_OR_LATER(ah)) {
+ if (!AR_SREV_9287_11_OR_LATER(ah))
REG_CLR_BIT(ah, AR_PHY_ADC_CTL,
AR_PHY_ADC_CTL_OFF_PWDADC);
REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
@@ -864,8 +835,8 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
return false;
}
- if (AR_SREV_9280_10_OR_LATER(ah)) {
- if (!AR_SREV_9287_10_OR_LATER(ah))
+ if (AR_SREV_9280_20_OR_LATER(ah)) {
+ if (!AR_SREV_9287_11_OR_LATER(ah))
REG_SET_BIT(ah, AR_PHY_ADC_CTL,
AR_PHY_ADC_CTL_OFF_PWDADC);
REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
@@ -886,24 +857,28 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
/* Enable IQ, ADC Gain and ADC DC offset CALs */
if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) {
- if (ar9002_hw_iscal_supported(ah, ADC_GAIN_CAL)) {
+ ah->supp_cals = IQ_MISMATCH_CAL;
+
+ if (AR_SREV_9160_10_OR_LATER(ah) &&
+ !(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan))) {
+ ah->supp_cals |= ADC_GAIN_CAL | ADC_DC_CAL;
+
+
INIT_CAL(&ah->adcgain_caldata);
INSERT_CAL(ah, &ah->adcgain_caldata);
ath_print(common, ATH_DBG_CALIBRATE,
"enabling ADC Gain Calibration.\n");
- }
- if (ar9002_hw_iscal_supported(ah, ADC_DC_CAL)) {
+
INIT_CAL(&ah->adcdc_caldata);
INSERT_CAL(ah, &ah->adcdc_caldata);
ath_print(common, ATH_DBG_CALIBRATE,
"enabling ADC DC Calibration.\n");
}
- if (ar9002_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) {
- INIT_CAL(&ah->iq_caldata);
- INSERT_CAL(ah, &ah->iq_caldata);
- ath_print(common, ATH_DBG_CALIBRATE,
- "enabling IQ Calibration.\n");
- }
+
+ INIT_CAL(&ah->iq_caldata);
+ INSERT_CAL(ah, &ah->iq_caldata);
+ ath_print(common, ATH_DBG_CALIBRATE,
+ "enabling IQ Calibration.\n");
ah->cal_list_curr = ah->cal_list;
@@ -959,13 +934,6 @@ static const struct ath9k_percal_data adc_dc_cal_single_sample = {
ar9002_hw_adc_dccal_collect,
ar9002_hw_adc_dccal_calibrate
};
-static const struct ath9k_percal_data adc_init_dc_cal = {
- ADC_DC_INIT_CAL,
- MIN_CAL_SAMPLES,
- INIT_LOG_COUNT,
- ar9002_hw_adc_dccal_collect,
- ar9002_hw_adc_dccal_calibrate
-};
static void ar9002_hw_init_cal_settings(struct ath_hw *ah)
{
@@ -976,22 +944,18 @@ static void ar9002_hw_init_cal_settings(struct ath_hw *ah)
}
if (AR_SREV_9160_10_OR_LATER(ah)) {
- if (AR_SREV_9280_10_OR_LATER(ah)) {
+ if (AR_SREV_9280_20_OR_LATER(ah)) {
ah->iq_caldata.calData = &iq_cal_single_sample;
ah->adcgain_caldata.calData =
&adc_gain_cal_single_sample;
ah->adcdc_caldata.calData =
&adc_dc_cal_single_sample;
- ah->adcdc_calinitdata.calData =
- &adc_init_dc_cal;
} else {
ah->iq_caldata.calData = &iq_cal_multi_sample;
ah->adcgain_caldata.calData =
&adc_gain_cal_multi_sample;
ah->adcdc_caldata.calData =
&adc_dc_cal_multi_sample;
- ah->adcdc_calinitdata.calData =
- &adc_init_dc_cal;
}
ah->supp_cals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL;
}
@@ -1005,7 +969,6 @@ void ar9002_hw_attach_calib_ops(struct ath_hw *ah)
priv_ops->init_cal_settings = ar9002_hw_init_cal_settings;
priv_ops->init_cal = ar9002_hw_init_cal;
priv_ops->setup_calibration = ar9002_hw_setup_calibration;
- priv_ops->iscal_supported = ar9002_hw_iscal_supported;
ops->calibrate = ar9002_hw_calibrate;
}
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
index 303c63da5ea3..a0471f2e1c7a 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
@@ -371,7 +371,6 @@ static void ar9002_hw_configpcipowersave(struct ath_hw *ah,
REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
}
udelay(1000);
@@ -468,7 +467,6 @@ static int ar9002_hw_get_radiorev(struct ath_hw *ah)
REG_WRITE(ah, AR_PHY(0x20), 0x00010000);
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
val = (REG_READ(ah, AR_PHY(256)) >> 24) & 0xff;
val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4);
@@ -569,14 +567,57 @@ void ar9002_hw_attach_ops(struct ath_hw *ah)
ops->config_pci_powersave = ar9002_hw_configpcipowersave;
ar5008_hw_attach_phy_ops(ah);
- if (AR_SREV_9280_10_OR_LATER(ah))
+ if (AR_SREV_9280_20_OR_LATER(ah))
ar9002_hw_attach_phy_ops(ah);
ar9002_hw_attach_calib_ops(ah);
ar9002_hw_attach_mac_ops(ah);
+}
+
+void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+ u32 modesIndex;
+ int i;
+
+ switch (chan->chanmode) {
+ case CHANNEL_A:
+ case CHANNEL_A_HT20:
+ modesIndex = 1;
+ break;
+ case CHANNEL_A_HT40PLUS:
+ case CHANNEL_A_HT40MINUS:
+ modesIndex = 2;
+ break;
+ case CHANNEL_G:
+ case CHANNEL_G_HT20:
+ case CHANNEL_B:
+ modesIndex = 4;
+ break;
+ case CHANNEL_G_HT40PLUS:
+ case CHANNEL_G_HT40MINUS:
+ modesIndex = 3;
+ break;
+
+ default:
+ return;
+ }
+
+ ENABLE_REGWRITE_BUFFER(ah);
- if (modparam_force_new_ani)
- ath9k_hw_attach_ani_ops_new(ah);
- else
- ath9k_hw_attach_ani_ops_old(ah);
+ for (i = 0; i < ah->iniModes_9271_ANI_reg.ia_rows; i++) {
+ u32 reg = INI_RA(&ah->iniModes_9271_ANI_reg, i, 0);
+ u32 val = INI_RA(&ah->iniModes_9271_ANI_reg, i, modesIndex);
+ u32 val_orig;
+
+ if (reg == AR_PHY_CCK_DETECT) {
+ val_orig = REG_READ(ah, reg);
+ val &= AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK;
+ val_orig &= ~AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK;
+
+ REG_WRITE(ah, reg, val|val_orig);
+ } else
+ REG_WRITE(ah, reg, val);
+ }
+
+ REGWRITE_BUFFER_FLUSH(ah);
}
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.c b/drivers/net/wireless/ath/ath9k/ar9002_phy.c
index adbf031fbc5a..c00cdc67b55b 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c
@@ -415,7 +415,6 @@ static void ar9002_hw_spur_mitigate(struct ath_hw *ah,
REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
}
static void ar9002_olc_init(struct ath_hw *ah)
@@ -530,3 +529,38 @@ void ar9002_hw_attach_phy_ops(struct ath_hw *ah)
ar9002_hw_set_nf_limits(ah);
}
+
+void ath9k_hw_antdiv_comb_conf_get(struct ath_hw *ah,
+ struct ath_hw_antcomb_conf *antconf)
+{
+ u32 regval;
+
+ regval = REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL);
+ antconf->main_lna_conf = (regval & AR_PHY_9285_ANT_DIV_MAIN_LNACONF) >>
+ AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S;
+ antconf->alt_lna_conf = (regval & AR_PHY_9285_ANT_DIV_ALT_LNACONF) >>
+ AR_PHY_9285_ANT_DIV_ALT_LNACONF_S;
+ antconf->fast_div_bias = (regval & AR_PHY_9285_FAST_DIV_BIAS) >>
+ AR_PHY_9285_FAST_DIV_BIAS_S;
+}
+EXPORT_SYMBOL(ath9k_hw_antdiv_comb_conf_get);
+
+void ath9k_hw_antdiv_comb_conf_set(struct ath_hw *ah,
+ struct ath_hw_antcomb_conf *antconf)
+{
+ u32 regval;
+
+ regval = REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL);
+ regval &= ~(AR_PHY_9285_ANT_DIV_MAIN_LNACONF |
+ AR_PHY_9285_ANT_DIV_ALT_LNACONF |
+ AR_PHY_9285_FAST_DIV_BIAS);
+ regval |= ((antconf->main_lna_conf << AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S)
+ & AR_PHY_9285_ANT_DIV_MAIN_LNACONF);
+ regval |= ((antconf->alt_lna_conf << AR_PHY_9285_ANT_DIV_ALT_LNACONF_S)
+ & AR_PHY_9285_ANT_DIV_ALT_LNACONF);
+ regval |= ((antconf->fast_div_bias << AR_PHY_9285_FAST_DIV_BIAS_S)
+ & AR_PHY_9285_FAST_DIV_BIAS);
+
+ REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regval);
+}
+EXPORT_SYMBOL(ath9k_hw_antdiv_comb_conf_set);
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.h b/drivers/net/wireless/ath/ath9k/ar9002_phy.h
index c5151a4dd10b..37663dbbcf57 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_phy.h
+++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.h
@@ -302,6 +302,8 @@
#define AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE 0x80000000
#define AR_PHY_MULTICHAIN_GAIN_CTL 0x99ac
+#define AR_PHY_9285_FAST_DIV_BIAS 0x00007E00
+#define AR_PHY_9285_FAST_DIV_BIAS_S 9
#define AR_PHY_9285_ANT_DIV_CTL_ALL 0x7f000000
#define AR_PHY_9285_ANT_DIV_CTL 0x01000000
#define AR_PHY_9285_ANT_DIV_CTL_S 24
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p0_initvals.h
deleted file mode 100644
index d3375fc4ce8b..000000000000
--- a/drivers/net/wireless/ath/ath9k/ar9003_2p0_initvals.h
+++ /dev/null
@@ -1,1784 +0,0 @@
-/*
- * Copyright (c) 2010 Atheros Communications Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef INITVALS_9003_2P0_H
-#define INITVALS_9003_2P0_H
-
-/* AR9003 2.0 */
-
-static const u32 ar9300_2p0_radio_postamble[][5] = {
- /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
- {0x0001609c, 0x0dd08f29, 0x0dd08f29, 0x0b283f31, 0x0b283f31},
- {0x000160ac, 0xa4653c00, 0xa4653c00, 0x24652800, 0x24652800},
- {0x000160b0, 0x03284f3e, 0x03284f3e, 0x05d08f20, 0x05d08f20},
- {0x0001610c, 0x08000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00016140, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
- {0x0001650c, 0x08000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00016540, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
- {0x0001690c, 0x08000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00016940, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
-};
-
-static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p0[][5] = {
- /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
- {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
- {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
- {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
- {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
- {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202},
- {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400},
- {0x0000a518, 0x21020220, 0x21020220, 0x16000402, 0x16000402},
- {0x0000a51c, 0x27020223, 0x27020223, 0x19000404, 0x19000404},
- {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603},
- {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02},
- {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04},
- {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20},
- {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20},
- {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22},
- {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24},
- {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640},
- {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660},
- {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861},
- {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81},
- {0x0000a54c, 0x5c04286b, 0x5c04286b, 0x47001a83, 0x47001a83},
- {0x0000a550, 0x61042a6c, 0x61042a6c, 0x4a001c84, 0x4a001c84},
- {0x0000a554, 0x66062a6c, 0x66062a6c, 0x4e001ce3, 0x4e001ce3},
- {0x0000a558, 0x6b062e6c, 0x6b062e6c, 0x52001ce5, 0x52001ce5},
- {0x0000a55c, 0x7006308c, 0x7006308c, 0x56001ce9, 0x56001ce9},
- {0x0000a560, 0x730a308a, 0x730a308a, 0x5a001ceb, 0x5a001ceb},
- {0x0000a564, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
- {0x0000a568, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
- {0x0000a56c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
- {0x0000a570, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
- {0x0000a574, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
- {0x0000a578, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
- {0x0000a57c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
- {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
- {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002},
- {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004},
- {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200},
- {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202},
- {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400},
- {0x0000a598, 0x21820220, 0x21820220, 0x16800402, 0x16800402},
- {0x0000a59c, 0x27820223, 0x27820223, 0x19800404, 0x19800404},
- {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603},
- {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02},
- {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04},
- {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20},
- {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20},
- {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22},
- {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24},
- {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640},
- {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660},
- {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861},
- {0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81},
- {0x0000a5cc, 0x5c84286b, 0x5c84286b, 0x47801a83, 0x47801a83},
- {0x0000a5d0, 0x61842a6c, 0x61842a6c, 0x4a801c84, 0x4a801c84},
- {0x0000a5d4, 0x66862a6c, 0x66862a6c, 0x4e801ce3, 0x4e801ce3},
- {0x0000a5d8, 0x6b862e6c, 0x6b862e6c, 0x52801ce5, 0x52801ce5},
- {0x0000a5dc, 0x7086308c, 0x7086308c, 0x56801ce9, 0x56801ce9},
- {0x0000a5e0, 0x738a308a, 0x738a308a, 0x5a801ceb, 0x5a801ceb},
- {0x0000a5e4, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
- {0x0000a5e8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
- {0x0000a5ec, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
- {0x0000a5f0, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
- {0x0000a5f4, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
- {0x0000a5f8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
- {0x0000a5fc, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
- {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
- {0x00016048, 0x62480001, 0x62480001, 0x62480001, 0x62480001},
- {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
- {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
- {0x00016448, 0x62480001, 0x62480001, 0x62480001, 0x62480001},
- {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
- {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
- {0x00016848, 0x62480001, 0x62480001, 0x62480001, 0x62480001},
- {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
-};
-
-static const u32 ar9300Modes_fast_clock_2p0[][3] = {
- /* Addr 5G_HT20 5G_HT40 */
- {0x00001030, 0x00000268, 0x000004d0},
- {0x00001070, 0x0000018c, 0x00000318},
- {0x000010b0, 0x00000fd0, 0x00001fa0},
- {0x00008014, 0x044c044c, 0x08980898},
- {0x0000801c, 0x148ec02b, 0x148ec057},
- {0x00008318, 0x000044c0, 0x00008980},
- {0x00009e00, 0x03721821, 0x03721821},
- {0x0000a230, 0x0000000b, 0x00000016},
- {0x0000a254, 0x00000898, 0x00001130},
-};
-
-static const u32 ar9300_2p0_radio_core[][2] = {
- /* Addr allmodes */
- {0x00016000, 0x36db6db6},
- {0x00016004, 0x6db6db40},
- {0x00016008, 0x73f00000},
- {0x0001600c, 0x00000000},
- {0x00016040, 0x7f80fff8},
- {0x0001604c, 0x76d005b5},
- {0x00016050, 0x556cf031},
- {0x00016054, 0x13449440},
- {0x00016058, 0x0c51c92c},
- {0x0001605c, 0x3db7fffc},
- {0x00016060, 0xfffffffc},
- {0x00016064, 0x000f0278},
- {0x0001606c, 0x6db60000},
- {0x00016080, 0x00000000},
- {0x00016084, 0x0e48048c},
- {0x00016088, 0x54214514},
- {0x0001608c, 0x119f481e},
- {0x00016090, 0x24926490},
- {0x00016098, 0xd2888888},
- {0x000160a0, 0x0a108ffe},
- {0x000160a4, 0x812fc370},
- {0x000160a8, 0x423c8000},
- {0x000160b4, 0x92480080},
- {0x000160c0, 0x00adb6d0},
- {0x000160c4, 0x6db6db60},
- {0x000160c8, 0x6db6db6c},
- {0x000160cc, 0x01e6c000},
- {0x00016100, 0x3fffbe01},
- {0x00016104, 0xfff80000},
- {0x00016108, 0x00080010},
- {0x00016144, 0x02084080},
- {0x00016148, 0x00000000},
- {0x00016280, 0x058a0001},
- {0x00016284, 0x3d840208},
- {0x00016288, 0x05a20408},
- {0x0001628c, 0x00038c07},
- {0x00016290, 0x40000004},
- {0x00016294, 0x458aa14f},
- {0x00016380, 0x00000000},
- {0x00016384, 0x00000000},
- {0x00016388, 0x00800700},
- {0x0001638c, 0x00800700},
- {0x00016390, 0x00800700},
- {0x00016394, 0x00000000},
- {0x00016398, 0x00000000},
- {0x0001639c, 0x00000000},
- {0x000163a0, 0x00000001},
- {0x000163a4, 0x00000001},
- {0x000163a8, 0x00000000},
- {0x000163ac, 0x00000000},
- {0x000163b0, 0x00000000},
- {0x000163b4, 0x00000000},
- {0x000163b8, 0x00000000},
- {0x000163bc, 0x00000000},
- {0x000163c0, 0x000000a0},
- {0x000163c4, 0x000c0000},
- {0x000163c8, 0x14021402},
- {0x000163cc, 0x00001402},
- {0x000163d0, 0x00000000},
- {0x000163d4, 0x00000000},
- {0x00016400, 0x36db6db6},
- {0x00016404, 0x6db6db40},
- {0x00016408, 0x73f00000},
- {0x0001640c, 0x00000000},
- {0x00016440, 0x7f80fff8},
- {0x0001644c, 0x76d005b5},
- {0x00016450, 0x556cf031},
- {0x00016454, 0x13449440},
- {0x00016458, 0x0c51c92c},
- {0x0001645c, 0x3db7fffc},
- {0x00016460, 0xfffffffc},
- {0x00016464, 0x000f0278},
- {0x0001646c, 0x6db60000},
- {0x00016500, 0x3fffbe01},
- {0x00016504, 0xfff80000},
- {0x00016508, 0x00080010},
- {0x00016544, 0x02084080},
- {0x00016548, 0x00000000},
- {0x00016780, 0x00000000},
- {0x00016784, 0x00000000},
- {0x00016788, 0x00800700},
- {0x0001678c, 0x00800700},
- {0x00016790, 0x00800700},
- {0x00016794, 0x00000000},
- {0x00016798, 0x00000000},
- {0x0001679c, 0x00000000},
- {0x000167a0, 0x00000001},
- {0x000167a4, 0x00000001},
- {0x000167a8, 0x00000000},
- {0x000167ac, 0x00000000},
- {0x000167b0, 0x00000000},
- {0x000167b4, 0x00000000},
- {0x000167b8, 0x00000000},
- {0x000167bc, 0x00000000},
- {0x000167c0, 0x000000a0},
- {0x000167c4, 0x000c0000},
- {0x000167c8, 0x14021402},
- {0x000167cc, 0x00001402},
- {0x000167d0, 0x00000000},
- {0x000167d4, 0x00000000},
- {0x00016800, 0x36db6db6},
- {0x00016804, 0x6db6db40},
- {0x00016808, 0x73f00000},
- {0x0001680c, 0x00000000},
- {0x00016840, 0x7f80fff8},
- {0x0001684c, 0x76d005b5},
- {0x00016850, 0x556cf031},
- {0x00016854, 0x13449440},
- {0x00016858, 0x0c51c92c},
- {0x0001685c, 0x3db7fffc},
- {0x00016860, 0xfffffffc},
- {0x00016864, 0x000f0278},
- {0x0001686c, 0x6db60000},
- {0x00016900, 0x3fffbe01},
- {0x00016904, 0xfff80000},
- {0x00016908, 0x00080010},
- {0x00016944, 0x02084080},
- {0x00016948, 0x00000000},
- {0x00016b80, 0x00000000},
- {0x00016b84, 0x00000000},
- {0x00016b88, 0x00800700},
- {0x00016b8c, 0x00800700},
- {0x00016b90, 0x00800700},
- {0x00016b94, 0x00000000},
- {0x00016b98, 0x00000000},
- {0x00016b9c, 0x00000000},
- {0x00016ba0, 0x00000001},
- {0x00016ba4, 0x00000001},
- {0x00016ba8, 0x00000000},
- {0x00016bac, 0x00000000},
- {0x00016bb0, 0x00000000},
- {0x00016bb4, 0x00000000},
- {0x00016bb8, 0x00000000},
- {0x00016bbc, 0x00000000},
- {0x00016bc0, 0x000000a0},
- {0x00016bc4, 0x000c0000},
- {0x00016bc8, 0x14021402},
- {0x00016bcc, 0x00001402},
- {0x00016bd0, 0x00000000},
- {0x00016bd4, 0x00000000},
-};
-
-static const u32 ar9300Common_rx_gain_table_merlin_2p0[][2] = {
- /* Addr allmodes */
- {0x0000a000, 0x02000101},
- {0x0000a004, 0x02000102},
- {0x0000a008, 0x02000103},
- {0x0000a00c, 0x02000104},
- {0x0000a010, 0x02000200},
- {0x0000a014, 0x02000201},
- {0x0000a018, 0x02000202},
- {0x0000a01c, 0x02000203},
- {0x0000a020, 0x02000204},
- {0x0000a024, 0x02000205},
- {0x0000a028, 0x02000208},
- {0x0000a02c, 0x02000302},
- {0x0000a030, 0x02000303},
- {0x0000a034, 0x02000304},
- {0x0000a038, 0x02000400},
- {0x0000a03c, 0x02010300},
- {0x0000a040, 0x02010301},
- {0x0000a044, 0x02010302},
- {0x0000a048, 0x02000500},
- {0x0000a04c, 0x02010400},
- {0x0000a050, 0x02020300},
- {0x0000a054, 0x02020301},
- {0x0000a058, 0x02020302},
- {0x0000a05c, 0x02020303},
- {0x0000a060, 0x02020400},
- {0x0000a064, 0x02030300},
- {0x0000a068, 0x02030301},
- {0x0000a06c, 0x02030302},
- {0x0000a070, 0x02030303},
- {0x0000a074, 0x02030400},
- {0x0000a078, 0x02040300},
- {0x0000a07c, 0x02040301},
- {0x0000a080, 0x02040302},
- {0x0000a084, 0x02040303},
- {0x0000a088, 0x02030500},
- {0x0000a08c, 0x02040400},
- {0x0000a090, 0x02050203},
- {0x0000a094, 0x02050204},
- {0x0000a098, 0x02050205},
- {0x0000a09c, 0x02040500},
- {0x0000a0a0, 0x02050301},
- {0x0000a0a4, 0x02050302},
- {0x0000a0a8, 0x02050303},
- {0x0000a0ac, 0x02050400},
- {0x0000a0b0, 0x02050401},
- {0x0000a0b4, 0x02050402},
- {0x0000a0b8, 0x02050403},
- {0x0000a0bc, 0x02050500},
- {0x0000a0c0, 0x02050501},
- {0x0000a0c4, 0x02050502},
- {0x0000a0c8, 0x02050503},
- {0x0000a0cc, 0x02050504},
- {0x0000a0d0, 0x02050600},
- {0x0000a0d4, 0x02050601},
- {0x0000a0d8, 0x02050602},
- {0x0000a0dc, 0x02050603},
- {0x0000a0e0, 0x02050604},
- {0x0000a0e4, 0x02050700},
- {0x0000a0e8, 0x02050701},
- {0x0000a0ec, 0x02050702},
- {0x0000a0f0, 0x02050703},
- {0x0000a0f4, 0x02050704},
- {0x0000a0f8, 0x02050705},
- {0x0000a0fc, 0x02050708},
- {0x0000a100, 0x02050709},
- {0x0000a104, 0x0205070a},
- {0x0000a108, 0x0205070b},
- {0x0000a10c, 0x0205070c},
- {0x0000a110, 0x0205070d},
- {0x0000a114, 0x02050710},
- {0x0000a118, 0x02050711},
- {0x0000a11c, 0x02050712},
- {0x0000a120, 0x02050713},
- {0x0000a124, 0x02050714},
- {0x0000a128, 0x02050715},
- {0x0000a12c, 0x02050730},
- {0x0000a130, 0x02050731},
- {0x0000a134, 0x02050732},
- {0x0000a138, 0x02050733},
- {0x0000a13c, 0x02050734},
- {0x0000a140, 0x02050735},
- {0x0000a144, 0x02050750},
- {0x0000a148, 0x02050751},
- {0x0000a14c, 0x02050752},
- {0x0000a150, 0x02050753},
- {0x0000a154, 0x02050754},
- {0x0000a158, 0x02050755},
- {0x0000a15c, 0x02050770},
- {0x0000a160, 0x02050771},
- {0x0000a164, 0x02050772},
- {0x0000a168, 0x02050773},
- {0x0000a16c, 0x02050774},
- {0x0000a170, 0x02050775},
- {0x0000a174, 0x00000776},
- {0x0000a178, 0x00000776},
- {0x0000a17c, 0x00000776},
- {0x0000a180, 0x00000776},
- {0x0000a184, 0x00000776},
- {0x0000a188, 0x00000776},
- {0x0000a18c, 0x00000776},
- {0x0000a190, 0x00000776},
- {0x0000a194, 0x00000776},
- {0x0000a198, 0x00000776},
- {0x0000a19c, 0x00000776},
- {0x0000a1a0, 0x00000776},
- {0x0000a1a4, 0x00000776},
- {0x0000a1a8, 0x00000776},
- {0x0000a1ac, 0x00000776},
- {0x0000a1b0, 0x00000776},
- {0x0000a1b4, 0x00000776},
- {0x0000a1b8, 0x00000776},
- {0x0000a1bc, 0x00000776},
- {0x0000a1c0, 0x00000776},
- {0x0000a1c4, 0x00000776},
- {0x0000a1c8, 0x00000776},
- {0x0000a1cc, 0x00000776},
- {0x0000a1d0, 0x00000776},
- {0x0000a1d4, 0x00000776},
- {0x0000a1d8, 0x00000776},
- {0x0000a1dc, 0x00000776},
- {0x0000a1e0, 0x00000776},
- {0x0000a1e4, 0x00000776},
- {0x0000a1e8, 0x00000776},
- {0x0000a1ec, 0x00000776},
- {0x0000a1f0, 0x00000776},
- {0x0000a1f4, 0x00000776},
- {0x0000a1f8, 0x00000776},
- {0x0000a1fc, 0x00000776},
- {0x0000b000, 0x02000101},
- {0x0000b004, 0x02000102},
- {0x0000b008, 0x02000103},
- {0x0000b00c, 0x02000104},
- {0x0000b010, 0x02000200},
- {0x0000b014, 0x02000201},
- {0x0000b018, 0x02000202},
- {0x0000b01c, 0x02000203},
- {0x0000b020, 0x02000204},
- {0x0000b024, 0x02000205},
- {0x0000b028, 0x02000208},
- {0x0000b02c, 0x02000302},
- {0x0000b030, 0x02000303},
- {0x0000b034, 0x02000304},
- {0x0000b038, 0x02000400},
- {0x0000b03c, 0x02010300},
- {0x0000b040, 0x02010301},
- {0x0000b044, 0x02010302},
- {0x0000b048, 0x02000500},
- {0x0000b04c, 0x02010400},
- {0x0000b050, 0x02020300},
- {0x0000b054, 0x02020301},
- {0x0000b058, 0x02020302},
- {0x0000b05c, 0x02020303},
- {0x0000b060, 0x02020400},
- {0x0000b064, 0x02030300},
- {0x0000b068, 0x02030301},
- {0x0000b06c, 0x02030302},
- {0x0000b070, 0x02030303},
- {0x0000b074, 0x02030400},
- {0x0000b078, 0x02040300},
- {0x0000b07c, 0x02040301},
- {0x0000b080, 0x02040302},
- {0x0000b084, 0x02040303},
- {0x0000b088, 0x02030500},
- {0x0000b08c, 0x02040400},
- {0x0000b090, 0x02050203},
- {0x0000b094, 0x02050204},
- {0x0000b098, 0x02050205},
- {0x0000b09c, 0x02040500},
- {0x0000b0a0, 0x02050301},
- {0x0000b0a4, 0x02050302},
- {0x0000b0a8, 0x02050303},
- {0x0000b0ac, 0x02050400},
- {0x0000b0b0, 0x02050401},
- {0x0000b0b4, 0x02050402},
- {0x0000b0b8, 0x02050403},
- {0x0000b0bc, 0x02050500},
- {0x0000b0c0, 0x02050501},
- {0x0000b0c4, 0x02050502},
- {0x0000b0c8, 0x02050503},
- {0x0000b0cc, 0x02050504},
- {0x0000b0d0, 0x02050600},
- {0x0000b0d4, 0x02050601},
- {0x0000b0d8, 0x02050602},
- {0x0000b0dc, 0x02050603},
- {0x0000b0e0, 0x02050604},
- {0x0000b0e4, 0x02050700},
- {0x0000b0e8, 0x02050701},
- {0x0000b0ec, 0x02050702},
- {0x0000b0f0, 0x02050703},
- {0x0000b0f4, 0x02050704},
- {0x0000b0f8, 0x02050705},
- {0x0000b0fc, 0x02050708},
- {0x0000b100, 0x02050709},
- {0x0000b104, 0x0205070a},
- {0x0000b108, 0x0205070b},
- {0x0000b10c, 0x0205070c},
- {0x0000b110, 0x0205070d},
- {0x0000b114, 0x02050710},
- {0x0000b118, 0x02050711},
- {0x0000b11c, 0x02050712},
- {0x0000b120, 0x02050713},
- {0x0000b124, 0x02050714},
- {0x0000b128, 0x02050715},
- {0x0000b12c, 0x02050730},
- {0x0000b130, 0x02050731},
- {0x0000b134, 0x02050732},
- {0x0000b138, 0x02050733},
- {0x0000b13c, 0x02050734},
- {0x0000b140, 0x02050735},
- {0x0000b144, 0x02050750},
- {0x0000b148, 0x02050751},
- {0x0000b14c, 0x02050752},
- {0x0000b150, 0x02050753},
- {0x0000b154, 0x02050754},
- {0x0000b158, 0x02050755},
- {0x0000b15c, 0x02050770},
- {0x0000b160, 0x02050771},
- {0x0000b164, 0x02050772},
- {0x0000b168, 0x02050773},
- {0x0000b16c, 0x02050774},
- {0x0000b170, 0x02050775},
- {0x0000b174, 0x00000776},
- {0x0000b178, 0x00000776},
- {0x0000b17c, 0x00000776},
- {0x0000b180, 0x00000776},
- {0x0000b184, 0x00000776},
- {0x0000b188, 0x00000776},
- {0x0000b18c, 0x00000776},
- {0x0000b190, 0x00000776},
- {0x0000b194, 0x00000776},
- {0x0000b198, 0x00000776},
- {0x0000b19c, 0x00000776},
- {0x0000b1a0, 0x00000776},
- {0x0000b1a4, 0x00000776},
- {0x0000b1a8, 0x00000776},
- {0x0000b1ac, 0x00000776},
- {0x0000b1b0, 0x00000776},
- {0x0000b1b4, 0x00000776},
- {0x0000b1b8, 0x00000776},
- {0x0000b1bc, 0x00000776},
- {0x0000b1c0, 0x00000776},
- {0x0000b1c4, 0x00000776},
- {0x0000b1c8, 0x00000776},
- {0x0000b1cc, 0x00000776},
- {0x0000b1d0, 0x00000776},
- {0x0000b1d4, 0x00000776},
- {0x0000b1d8, 0x00000776},
- {0x0000b1dc, 0x00000776},
- {0x0000b1e0, 0x00000776},
- {0x0000b1e4, 0x00000776},
- {0x0000b1e8, 0x00000776},
- {0x0000b1ec, 0x00000776},
- {0x0000b1f0, 0x00000776},
- {0x0000b1f4, 0x00000776},
- {0x0000b1f8, 0x00000776},
- {0x0000b1fc, 0x00000776},
-};
-
-static const u32 ar9300_2p0_mac_postamble[][5] = {
- /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
- {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
- {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
- {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
- {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
- {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b},
- {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
- {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
- {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440},
-};
-
-static const u32 ar9300_2p0_soc_postamble[][5] = {
- /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
- {0x00007010, 0x00000023, 0x00000023, 0x00000023, 0x00000023},
-};
-
-static const u32 ar9200_merlin_2p0_radio_core[][2] = {
- /* Addr allmodes */
- {0x00007800, 0x00040000},
- {0x00007804, 0xdb005012},
- {0x00007808, 0x04924914},
- {0x0000780c, 0x21084210},
- {0x00007810, 0x6d801300},
- {0x00007814, 0x0019beff},
- {0x00007818, 0x07e41000},
- {0x0000781c, 0x00392000},
- {0x00007820, 0x92592480},
- {0x00007824, 0x00040000},
- {0x00007828, 0xdb005012},
- {0x0000782c, 0x04924914},
- {0x00007830, 0x21084210},
- {0x00007834, 0x6d801300},
- {0x00007838, 0x0019beff},
- {0x0000783c, 0x07e40000},
- {0x00007840, 0x00392000},
- {0x00007844, 0x92592480},
- {0x00007848, 0x00100000},
- {0x0000784c, 0x773f0567},
- {0x00007850, 0x54214514},
- {0x00007854, 0x12035828},
- {0x00007858, 0x92592692},
- {0x0000785c, 0x00000000},
- {0x00007860, 0x56400000},
- {0x00007864, 0x0a8e370e},
- {0x00007868, 0xc0102850},
- {0x0000786c, 0x812d4000},
- {0x00007870, 0x807ec400},
- {0x00007874, 0x001b6db0},
- {0x00007878, 0x00376b63},
- {0x0000787c, 0x06db6db6},
- {0x00007880, 0x006d8000},
- {0x00007884, 0xffeffffe},
- {0x00007888, 0xffeffffe},
- {0x0000788c, 0x00010000},
- {0x00007890, 0x02060aeb},
- {0x00007894, 0x5a108000},
-};
-
-static const u32 ar9300_2p0_baseband_postamble[][5] = {
- /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
- {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011},
- {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e},
- {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
- {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
- {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
- {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c},
- {0x00009c00, 0x00000044, 0x000000c4, 0x000000c4, 0x00000044},
- {0x00009e00, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0},
- {0x00009e04, 0x00802020, 0x00802020, 0x00802020, 0x00802020},
- {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
- {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e},
- {0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
- {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
- {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
- {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
- {0x00009e44, 0x02321e27, 0x02321e27, 0x02291e27, 0x02291e27},
- {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
- {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
- {0x0000a204, 0x000037c0, 0x000037c4, 0x000037c4, 0x000037c0},
- {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
- {0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
- {0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018},
- {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
- {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
- {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002},
- {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
- {0x0000a260, 0x0a021501, 0x0a021501, 0x3a021501, 0x3a021501},
- {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
- {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b},
- {0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150},
- {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110},
- {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222},
- {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
- {0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071982},
- {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a},
- {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
- {0x0000ae04, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
- {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000ae1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
- {0x0000ae20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce},
- {0x0000b284, 0x00000000, 0x00000000, 0x00000150, 0x00000150},
- {0x0000b830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
- {0x0000be04, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
- {0x0000be18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000be1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
- {0x0000be20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce},
- {0x0000c284, 0x00000000, 0x00000000, 0x00000150, 0x00000150},
-};
-
-static const u32 ar9300_2p0_baseband_core[][2] = {
- /* Addr allmodes */
- {0x00009800, 0xafe68e30},
- {0x00009804, 0xfd14e000},
- {0x00009808, 0x9c0a9f6b},
- {0x0000980c, 0x04900000},
- {0x00009814, 0x9280c00a},
- {0x00009818, 0x00000000},
- {0x0000981c, 0x00020028},
- {0x00009834, 0x5f3ca3de},
- {0x00009838, 0x0108ecff},
- {0x0000983c, 0x14750600},
- {0x00009880, 0x201fff00},
- {0x00009884, 0x00001042},
- {0x000098a4, 0x00200400},
- {0x000098b0, 0x52440bbe},
- {0x000098d0, 0x004b6a8e},
- {0x000098d4, 0x00000820},
- {0x000098dc, 0x00000000},
- {0x000098f0, 0x00000000},
- {0x000098f4, 0x00000000},
- {0x00009c04, 0xff55ff55},
- {0x00009c08, 0x0320ff55},
- {0x00009c0c, 0x00000000},
- {0x00009c10, 0x00000000},
- {0x00009c14, 0x00046384},
- {0x00009c18, 0x05b6b440},
- {0x00009c1c, 0x00b6b440},
- {0x00009d00, 0xc080a333},
- {0x00009d04, 0x40206c10},
- {0x00009d08, 0x009c4060},
- {0x00009d0c, 0x9883800a},
- {0x00009d10, 0x01834061},
- {0x00009d14, 0x00c0040b},
- {0x00009d18, 0x00000000},
- {0x00009e08, 0x0038230c},
- {0x00009e24, 0x990bb515},
- {0x00009e28, 0x0c6f0000},
- {0x00009e30, 0x06336f77},
- {0x00009e34, 0x6af6532f},
- {0x00009e38, 0x0cc80c00},
- {0x00009e3c, 0xcf946222},
- {0x00009e40, 0x0d261820},
- {0x00009e4c, 0x00001004},
- {0x00009e50, 0x00ff03f1},
- {0x00009e54, 0x00000000},
- {0x00009fc0, 0x803e4788},
- {0x00009fc4, 0x0001efb5},
- {0x00009fcc, 0x40000014},
- {0x00009fd0, 0x01193b93},
- {0x0000a20c, 0x00000000},
- {0x0000a220, 0x00000000},
- {0x0000a224, 0x00000000},
- {0x0000a228, 0x10002310},
- {0x0000a22c, 0x01036a1e},
- {0x0000a234, 0x10000fff},
- {0x0000a23c, 0x00000000},
- {0x0000a244, 0x0c000000},
- {0x0000a2a0, 0x00000001},
- {0x0000a2c0, 0x00000001},
- {0x0000a2c8, 0x00000000},
- {0x0000a2cc, 0x18c43433},
- {0x0000a2d4, 0x00000000},
- {0x0000a2dc, 0x00000000},
- {0x0000a2e0, 0x00000000},
- {0x0000a2e4, 0x00000000},
- {0x0000a2e8, 0x00000000},
- {0x0000a2ec, 0x00000000},
- {0x0000a2f0, 0x00000000},
- {0x0000a2f4, 0x00000000},
- {0x0000a2f8, 0x00000000},
- {0x0000a344, 0x00000000},
- {0x0000a34c, 0x00000000},
- {0x0000a350, 0x0000a000},
- {0x0000a364, 0x00000000},
- {0x0000a370, 0x00000000},
- {0x0000a390, 0x00000001},
- {0x0000a394, 0x00000444},
- {0x0000a398, 0x001f0e0f},
- {0x0000a39c, 0x0075393f},
- {0x0000a3a0, 0xb79f6427},
- {0x0000a3a4, 0x00000000},
- {0x0000a3a8, 0xaaaaaaaa},
- {0x0000a3ac, 0x3c466478},
- {0x0000a3c0, 0x20202020},
- {0x0000a3c4, 0x22222220},
- {0x0000a3c8, 0x20200020},
- {0x0000a3cc, 0x20202020},
- {0x0000a3d0, 0x20202020},
- {0x0000a3d4, 0x20202020},
- {0x0000a3d8, 0x20202020},
- {0x0000a3dc, 0x20202020},
- {0x0000a3e0, 0x20202020},
- {0x0000a3e4, 0x20202020},
- {0x0000a3e8, 0x20202020},
- {0x0000a3ec, 0x20202020},
- {0x0000a3f0, 0x00000000},
- {0x0000a3f4, 0x00000246},
- {0x0000a3f8, 0x0cdbd380},
- {0x0000a3fc, 0x000f0f01},
- {0x0000a400, 0x8fa91f01},
- {0x0000a404, 0x00000000},
- {0x0000a408, 0x0e79e5c6},
- {0x0000a40c, 0x00820820},
- {0x0000a414, 0x1ce739ce},
- {0x0000a418, 0x2d001dce},
- {0x0000a41c, 0x1ce739ce},
- {0x0000a420, 0x000001ce},
- {0x0000a424, 0x1ce739ce},
- {0x0000a428, 0x000001ce},
- {0x0000a42c, 0x1ce739ce},
- {0x0000a430, 0x1ce739ce},
- {0x0000a434, 0x00000000},
- {0x0000a438, 0x00001801},
- {0x0000a43c, 0x00000000},
- {0x0000a440, 0x00000000},
- {0x0000a444, 0x00000000},
- {0x0000a448, 0x04000080},
- {0x0000a44c, 0x00000001},
- {0x0000a450, 0x00010000},
- {0x0000a458, 0x00000000},
- {0x0000a600, 0x00000000},
- {0x0000a604, 0x00000000},
- {0x0000a608, 0x00000000},
- {0x0000a60c, 0x00000000},
- {0x0000a610, 0x00000000},
- {0x0000a614, 0x00000000},
- {0x0000a618, 0x00000000},
- {0x0000a61c, 0x00000000},
- {0x0000a620, 0x00000000},
- {0x0000a624, 0x00000000},
- {0x0000a628, 0x00000000},
- {0x0000a62c, 0x00000000},
- {0x0000a630, 0x00000000},
- {0x0000a634, 0x00000000},
- {0x0000a638, 0x00000000},
- {0x0000a63c, 0x00000000},
- {0x0000a640, 0x00000000},
- {0x0000a644, 0x3fad9d74},
- {0x0000a648, 0x0048060a},
- {0x0000a64c, 0x00000637},
- {0x0000a670, 0x03020100},
- {0x0000a674, 0x09080504},
- {0x0000a678, 0x0d0c0b0a},
- {0x0000a67c, 0x13121110},
- {0x0000a680, 0x31301514},
- {0x0000a684, 0x35343332},
- {0x0000a688, 0x00000036},
- {0x0000a690, 0x00000838},
- {0x0000a7c0, 0x00000000},
- {0x0000a7c4, 0xfffffffc},
- {0x0000a7c8, 0x00000000},
- {0x0000a7cc, 0x00000000},
- {0x0000a7d0, 0x00000000},
- {0x0000a7d4, 0x00000004},
- {0x0000a7dc, 0x00000001},
- {0x0000a8d0, 0x004b6a8e},
- {0x0000a8d4, 0x00000820},
- {0x0000a8dc, 0x00000000},
- {0x0000a8f0, 0x00000000},
- {0x0000a8f4, 0x00000000},
- {0x0000b2d0, 0x00000080},
- {0x0000b2d4, 0x00000000},
- {0x0000b2dc, 0x00000000},
- {0x0000b2e0, 0x00000000},
- {0x0000b2e4, 0x00000000},
- {0x0000b2e8, 0x00000000},
- {0x0000b2ec, 0x00000000},
- {0x0000b2f0, 0x00000000},
- {0x0000b2f4, 0x00000000},
- {0x0000b2f8, 0x00000000},
- {0x0000b408, 0x0e79e5c0},
- {0x0000b40c, 0x00820820},
- {0x0000b420, 0x00000000},
- {0x0000b8d0, 0x004b6a8e},
- {0x0000b8d4, 0x00000820},
- {0x0000b8dc, 0x00000000},
- {0x0000b8f0, 0x00000000},
- {0x0000b8f4, 0x00000000},
- {0x0000c2d0, 0x00000080},
- {0x0000c2d4, 0x00000000},
- {0x0000c2dc, 0x00000000},
- {0x0000c2e0, 0x00000000},
- {0x0000c2e4, 0x00000000},
- {0x0000c2e8, 0x00000000},
- {0x0000c2ec, 0x00000000},
- {0x0000c2f0, 0x00000000},
- {0x0000c2f4, 0x00000000},
- {0x0000c2f8, 0x00000000},
- {0x0000c408, 0x0e79e5c0},
- {0x0000c40c, 0x00820820},
- {0x0000c420, 0x00000000},
-};
-
-static const u32 ar9300Modes_high_power_tx_gain_table_2p0[][5] = {
- /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
- {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9},
- {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
- {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002},
- {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004},
- {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200},
- {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202},
- {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400},
- {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402},
- {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404},
- {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603},
- {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02},
- {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04},
- {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20},
- {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20},
- {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22},
- {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24},
- {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640},
- {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660},
- {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861},
- {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81},
- {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83},
- {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84},
- {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3},
- {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5},
- {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9},
- {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb},
- {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000},
- {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002},
- {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004},
- {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200},
- {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202},
- {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400},
- {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402},
- {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404},
- {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603},
- {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02},
- {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04},
- {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20},
- {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20},
- {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22},
- {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24},
- {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640},
- {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660},
- {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861},
- {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81},
- {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83},
- {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84},
- {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3},
- {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5},
- {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9},
- {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb},
- {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x00016044, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6},
- {0x00016048, 0xae480001, 0xae480001, 0xae480001, 0xae480001},
- {0x00016068, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c},
- {0x00016444, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6},
- {0x00016448, 0xae480001, 0xae480001, 0xae480001, 0xae480001},
- {0x00016468, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c},
- {0x00016844, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6},
- {0x00016848, 0xae480001, 0xae480001, 0xae480001, 0xae480001},
- {0x00016868, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c},
-};
-
-static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p0[][5] = {
- /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
- {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9},
- {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
- {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002},
- {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004},
- {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200},
- {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202},
- {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400},
- {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402},
- {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404},
- {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603},
- {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02},
- {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04},
- {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20},
- {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20},
- {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22},
- {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24},
- {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640},
- {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660},
- {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861},
- {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81},
- {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83},
- {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84},
- {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3},
- {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5},
- {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9},
- {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb},
- {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
- {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000},
- {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002},
- {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004},
- {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200},
- {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202},
- {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400},
- {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402},
- {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404},
- {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603},
- {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02},
- {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04},
- {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20},
- {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20},
- {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22},
- {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24},
- {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640},
- {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660},
- {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861},
- {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81},
- {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83},
- {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84},
- {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3},
- {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5},
- {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9},
- {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb},
- {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
- {0x00016044, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4},
- {0x00016048, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001},
- {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
- {0x00016444, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4},
- {0x00016448, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001},
- {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
- {0x00016844, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4},
- {0x00016848, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001},
- {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
-};
-
-static const u32 ar9300Common_rx_gain_table_2p0[][2] = {
- /* Addr allmodes */
- {0x0000a000, 0x00010000},
- {0x0000a004, 0x00030002},
- {0x0000a008, 0x00050004},
- {0x0000a00c, 0x00810080},
- {0x0000a010, 0x00830082},
- {0x0000a014, 0x01810180},
- {0x0000a018, 0x01830182},
- {0x0000a01c, 0x01850184},
- {0x0000a020, 0x01890188},
- {0x0000a024, 0x018b018a},
- {0x0000a028, 0x018d018c},
- {0x0000a02c, 0x01910190},
- {0x0000a030, 0x01930192},
- {0x0000a034, 0x01950194},
- {0x0000a038, 0x038a0196},
- {0x0000a03c, 0x038c038b},
- {0x0000a040, 0x0390038d},
- {0x0000a044, 0x03920391},
- {0x0000a048, 0x03940393},
- {0x0000a04c, 0x03960395},
- {0x0000a050, 0x00000000},
- {0x0000a054, 0x00000000},
- {0x0000a058, 0x00000000},
- {0x0000a05c, 0x00000000},
- {0x0000a060, 0x00000000},
- {0x0000a064, 0x00000000},
- {0x0000a068, 0x00000000},
- {0x0000a06c, 0x00000000},
- {0x0000a070, 0x00000000},
- {0x0000a074, 0x00000000},
- {0x0000a078, 0x00000000},
- {0x0000a07c, 0x00000000},
- {0x0000a080, 0x22222229},
- {0x0000a084, 0x1d1d1d1d},
- {0x0000a088, 0x1d1d1d1d},
- {0x0000a08c, 0x1d1d1d1d},
- {0x0000a090, 0x171d1d1d},
- {0x0000a094, 0x11111717},
- {0x0000a098, 0x00030311},
- {0x0000a09c, 0x00000000},
- {0x0000a0a0, 0x00000000},
- {0x0000a0a4, 0x00000000},
- {0x0000a0a8, 0x00000000},
- {0x0000a0ac, 0x00000000},
- {0x0000a0b0, 0x00000000},
- {0x0000a0b4, 0x00000000},
- {0x0000a0b8, 0x00000000},
- {0x0000a0bc, 0x00000000},
- {0x0000a0c0, 0x001f0000},
- {0x0000a0c4, 0x01000101},
- {0x0000a0c8, 0x011e011f},
- {0x0000a0cc, 0x011c011d},
- {0x0000a0d0, 0x02030204},
- {0x0000a0d4, 0x02010202},
- {0x0000a0d8, 0x021f0200},
- {0x0000a0dc, 0x0302021e},
- {0x0000a0e0, 0x03000301},
- {0x0000a0e4, 0x031e031f},
- {0x0000a0e8, 0x0402031d},
- {0x0000a0ec, 0x04000401},
- {0x0000a0f0, 0x041e041f},
- {0x0000a0f4, 0x0502041d},
- {0x0000a0f8, 0x05000501},
- {0x0000a0fc, 0x051e051f},
- {0x0000a100, 0x06010602},
- {0x0000a104, 0x061f0600},
- {0x0000a108, 0x061d061e},
- {0x0000a10c, 0x07020703},
- {0x0000a110, 0x07000701},
- {0x0000a114, 0x00000000},
- {0x0000a118, 0x00000000},
- {0x0000a11c, 0x00000000},
- {0x0000a120, 0x00000000},
- {0x0000a124, 0x00000000},
- {0x0000a128, 0x00000000},
- {0x0000a12c, 0x00000000},
- {0x0000a130, 0x00000000},
- {0x0000a134, 0x00000000},
- {0x0000a138, 0x00000000},
- {0x0000a13c, 0x00000000},
- {0x0000a140, 0x001f0000},
- {0x0000a144, 0x01000101},
- {0x0000a148, 0x011e011f},
- {0x0000a14c, 0x011c011d},
- {0x0000a150, 0x02030204},
- {0x0000a154, 0x02010202},
- {0x0000a158, 0x021f0200},
- {0x0000a15c, 0x0302021e},
- {0x0000a160, 0x03000301},
- {0x0000a164, 0x031e031f},
- {0x0000a168, 0x0402031d},
- {0x0000a16c, 0x04000401},
- {0x0000a170, 0x041e041f},
- {0x0000a174, 0x0502041d},
- {0x0000a178, 0x05000501},
- {0x0000a17c, 0x051e051f},
- {0x0000a180, 0x06010602},
- {0x0000a184, 0x061f0600},
- {0x0000a188, 0x061d061e},
- {0x0000a18c, 0x07020703},
- {0x0000a190, 0x07000701},
- {0x0000a194, 0x00000000},
- {0x0000a198, 0x00000000},
- {0x0000a19c, 0x00000000},
- {0x0000a1a0, 0x00000000},
- {0x0000a1a4, 0x00000000},
- {0x0000a1a8, 0x00000000},
- {0x0000a1ac, 0x00000000},
- {0x0000a1b0, 0x00000000},
- {0x0000a1b4, 0x00000000},
- {0x0000a1b8, 0x00000000},
- {0x0000a1bc, 0x00000000},
- {0x0000a1c0, 0x00000000},
- {0x0000a1c4, 0x00000000},
- {0x0000a1c8, 0x00000000},
- {0x0000a1cc, 0x00000000},
- {0x0000a1d0, 0x00000000},
- {0x0000a1d4, 0x00000000},
- {0x0000a1d8, 0x00000000},
- {0x0000a1dc, 0x00000000},
- {0x0000a1e0, 0x00000000},
- {0x0000a1e4, 0x00000000},
- {0x0000a1e8, 0x00000000},
- {0x0000a1ec, 0x00000000},
- {0x0000a1f0, 0x00000396},
- {0x0000a1f4, 0x00000396},
- {0x0000a1f8, 0x00000396},
- {0x0000a1fc, 0x00000196},
- {0x0000b000, 0x00010000},
- {0x0000b004, 0x00030002},
- {0x0000b008, 0x00050004},
- {0x0000b00c, 0x00810080},
- {0x0000b010, 0x00830082},
- {0x0000b014, 0x01810180},
- {0x0000b018, 0x01830182},
- {0x0000b01c, 0x01850184},
- {0x0000b020, 0x02810280},
- {0x0000b024, 0x02830282},
- {0x0000b028, 0x02850284},
- {0x0000b02c, 0x02890288},
- {0x0000b030, 0x028b028a},
- {0x0000b034, 0x0388028c},
- {0x0000b038, 0x038a0389},
- {0x0000b03c, 0x038c038b},
- {0x0000b040, 0x0390038d},
- {0x0000b044, 0x03920391},
- {0x0000b048, 0x03940393},
- {0x0000b04c, 0x03960395},
- {0x0000b050, 0x00000000},
- {0x0000b054, 0x00000000},
- {0x0000b058, 0x00000000},
- {0x0000b05c, 0x00000000},
- {0x0000b060, 0x00000000},
- {0x0000b064, 0x00000000},
- {0x0000b068, 0x00000000},
- {0x0000b06c, 0x00000000},
- {0x0000b070, 0x00000000},
- {0x0000b074, 0x00000000},
- {0x0000b078, 0x00000000},
- {0x0000b07c, 0x00000000},
- {0x0000b080, 0x32323232},
- {0x0000b084, 0x2f2f3232},
- {0x0000b088, 0x23282a2d},
- {0x0000b08c, 0x1c1e2123},
- {0x0000b090, 0x14171919},
- {0x0000b094, 0x0e0e1214},
- {0x0000b098, 0x03050707},
- {0x0000b09c, 0x00030303},
- {0x0000b0a0, 0x00000000},
- {0x0000b0a4, 0x00000000},
- {0x0000b0a8, 0x00000000},
- {0x0000b0ac, 0x00000000},
- {0x0000b0b0, 0x00000000},
- {0x0000b0b4, 0x00000000},
- {0x0000b0b8, 0x00000000},
- {0x0000b0bc, 0x00000000},
- {0x0000b0c0, 0x003f0020},
- {0x0000b0c4, 0x00400041},
- {0x0000b0c8, 0x0140005f},
- {0x0000b0cc, 0x0160015f},
- {0x0000b0d0, 0x017e017f},
- {0x0000b0d4, 0x02410242},
- {0x0000b0d8, 0x025f0240},
- {0x0000b0dc, 0x027f0260},
- {0x0000b0e0, 0x0341027e},
- {0x0000b0e4, 0x035f0340},
- {0x0000b0e8, 0x037f0360},
- {0x0000b0ec, 0x04400441},
- {0x0000b0f0, 0x0460045f},
- {0x0000b0f4, 0x0541047f},
- {0x0000b0f8, 0x055f0540},
- {0x0000b0fc, 0x057f0560},
- {0x0000b100, 0x06400641},
- {0x0000b104, 0x0660065f},
- {0x0000b108, 0x067e067f},
- {0x0000b10c, 0x07410742},
- {0x0000b110, 0x075f0740},
- {0x0000b114, 0x077f0760},
- {0x0000b118, 0x07800781},
- {0x0000b11c, 0x07a0079f},
- {0x0000b120, 0x07c107bf},
- {0x0000b124, 0x000007c0},
- {0x0000b128, 0x00000000},
- {0x0000b12c, 0x00000000},
- {0x0000b130, 0x00000000},
- {0x0000b134, 0x00000000},
- {0x0000b138, 0x00000000},
- {0x0000b13c, 0x00000000},
- {0x0000b140, 0x003f0020},
- {0x0000b144, 0x00400041},
- {0x0000b148, 0x0140005f},
- {0x0000b14c, 0x0160015f},
- {0x0000b150, 0x017e017f},
- {0x0000b154, 0x02410242},
- {0x0000b158, 0x025f0240},
- {0x0000b15c, 0x027f0260},
- {0x0000b160, 0x0341027e},
- {0x0000b164, 0x035f0340},
- {0x0000b168, 0x037f0360},
- {0x0000b16c, 0x04400441},
- {0x0000b170, 0x0460045f},
- {0x0000b174, 0x0541047f},
- {0x0000b178, 0x055f0540},
- {0x0000b17c, 0x057f0560},
- {0x0000b180, 0x06400641},
- {0x0000b184, 0x0660065f},
- {0x0000b188, 0x067e067f},
- {0x0000b18c, 0x07410742},
- {0x0000b190, 0x075f0740},
- {0x0000b194, 0x077f0760},
- {0x0000b198, 0x07800781},
- {0x0000b19c, 0x07a0079f},
- {0x0000b1a0, 0x07c107bf},
- {0x0000b1a4, 0x000007c0},
- {0x0000b1a8, 0x00000000},
- {0x0000b1ac, 0x00000000},
- {0x0000b1b0, 0x00000000},
- {0x0000b1b4, 0x00000000},
- {0x0000b1b8, 0x00000000},
- {0x0000b1bc, 0x00000000},
- {0x0000b1c0, 0x00000000},
- {0x0000b1c4, 0x00000000},
- {0x0000b1c8, 0x00000000},
- {0x0000b1cc, 0x00000000},
- {0x0000b1d0, 0x00000000},
- {0x0000b1d4, 0x00000000},
- {0x0000b1d8, 0x00000000},
- {0x0000b1dc, 0x00000000},
- {0x0000b1e0, 0x00000000},
- {0x0000b1e4, 0x00000000},
- {0x0000b1e8, 0x00000000},
- {0x0000b1ec, 0x00000000},
- {0x0000b1f0, 0x00000396},
- {0x0000b1f4, 0x00000396},
- {0x0000b1f8, 0x00000396},
- {0x0000b1fc, 0x00000196},
-};
-
-static const u32 ar9300Modes_low_ob_db_tx_gain_table_2p0[][5] = {
- /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
- {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
- {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
- {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
- {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
- {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202},
- {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400},
- {0x0000a518, 0x21020220, 0x21020220, 0x16000402, 0x16000402},
- {0x0000a51c, 0x27020223, 0x27020223, 0x19000404, 0x19000404},
- {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603},
- {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02},
- {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04},
- {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20},
- {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20},
- {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22},
- {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24},
- {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640},
- {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660},
- {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861},
- {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81},
- {0x0000a54c, 0x5c04286b, 0x5c04286b, 0x47001a83, 0x47001a83},
- {0x0000a550, 0x61042a6c, 0x61042a6c, 0x4a001c84, 0x4a001c84},
- {0x0000a554, 0x66062a6c, 0x66062a6c, 0x4e001ce3, 0x4e001ce3},
- {0x0000a558, 0x6b062e6c, 0x6b062e6c, 0x52001ce5, 0x52001ce5},
- {0x0000a55c, 0x7006308c, 0x7006308c, 0x56001ce9, 0x56001ce9},
- {0x0000a560, 0x730a308a, 0x730a308a, 0x5a001ceb, 0x5a001ceb},
- {0x0000a564, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
- {0x0000a568, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
- {0x0000a56c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
- {0x0000a570, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
- {0x0000a574, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
- {0x0000a578, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
- {0x0000a57c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
- {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
- {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002},
- {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004},
- {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200},
- {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202},
- {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400},
- {0x0000a598, 0x21820220, 0x21820220, 0x16800402, 0x16800402},
- {0x0000a59c, 0x27820223, 0x27820223, 0x19800404, 0x19800404},
- {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603},
- {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02},
- {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04},
- {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20},
- {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20},
- {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22},
- {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24},
- {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640},
- {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660},
- {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861},
- {0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81},
- {0x0000a5cc, 0x5c84286b, 0x5c84286b, 0x47801a83, 0x47801a83},
- {0x0000a5d0, 0x61842a6c, 0x61842a6c, 0x4a801c84, 0x4a801c84},
- {0x0000a5d4, 0x66862a6c, 0x66862a6c, 0x4e801ce3, 0x4e801ce3},
- {0x0000a5d8, 0x6b862e6c, 0x6b862e6c, 0x52801ce5, 0x52801ce5},
- {0x0000a5dc, 0x7086308c, 0x7086308c, 0x56801ce9, 0x56801ce9},
- {0x0000a5e0, 0x738a308a, 0x738a308a, 0x5a801ceb, 0x5a801ceb},
- {0x0000a5e4, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
- {0x0000a5e8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
- {0x0000a5ec, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
- {0x0000a5f0, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
- {0x0000a5f4, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
- {0x0000a5f8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
- {0x0000a5fc, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
- {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
- {0x00016048, 0x64000001, 0x64000001, 0x64000001, 0x64000001},
- {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
- {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
- {0x00016448, 0x64000001, 0x64000001, 0x64000001, 0x64000001},
- {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
- {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
- {0x00016848, 0x64000001, 0x64000001, 0x64000001, 0x64000001},
- {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
-};
-
-static const u32 ar9300_2p0_mac_core[][2] = {
- /* Addr allmodes */
- {0x00000008, 0x00000000},
- {0x00000030, 0x00020085},
- {0x00000034, 0x00000005},
- {0x00000040, 0x00000000},
- {0x00000044, 0x00000000},
- {0x00000048, 0x00000008},
- {0x0000004c, 0x00000010},
- {0x00000050, 0x00000000},
- {0x00001040, 0x002ffc0f},
- {0x00001044, 0x002ffc0f},
- {0x00001048, 0x002ffc0f},
- {0x0000104c, 0x002ffc0f},
- {0x00001050, 0x002ffc0f},
- {0x00001054, 0x002ffc0f},
- {0x00001058, 0x002ffc0f},
- {0x0000105c, 0x002ffc0f},
- {0x00001060, 0x002ffc0f},
- {0x00001064, 0x002ffc0f},
- {0x000010f0, 0x00000100},
- {0x00001270, 0x00000000},
- {0x000012b0, 0x00000000},
- {0x000012f0, 0x00000000},
- {0x0000143c, 0x00000000},
- {0x0000147c, 0x00000000},
- {0x00008000, 0x00000000},
- {0x00008004, 0x00000000},
- {0x00008008, 0x00000000},
- {0x0000800c, 0x00000000},
- {0x00008018, 0x00000000},
- {0x00008020, 0x00000000},
- {0x00008038, 0x00000000},
- {0x0000803c, 0x00000000},
- {0x00008040, 0x00000000},
- {0x00008044, 0x00000000},
- {0x00008048, 0x00000000},
- {0x0000804c, 0xffffffff},
- {0x00008054, 0x00000000},
- {0x00008058, 0x00000000},
- {0x0000805c, 0x000fc78f},
- {0x00008060, 0x0000000f},
- {0x00008064, 0x00000000},
- {0x00008070, 0x00000310},
- {0x00008074, 0x00000020},
- {0x00008078, 0x00000000},
- {0x0000809c, 0x0000000f},
- {0x000080a0, 0x00000000},
- {0x000080a4, 0x02ff0000},
- {0x000080a8, 0x0e070605},
- {0x000080ac, 0x0000000d},
- {0x000080b0, 0x00000000},
- {0x000080b4, 0x00000000},
- {0x000080b8, 0x00000000},
- {0x000080bc, 0x00000000},
- {0x000080c0, 0x2a800000},
- {0x000080c4, 0x06900168},
- {0x000080c8, 0x13881c20},
- {0x000080cc, 0x01f40000},
- {0x000080d0, 0x00252500},
- {0x000080d4, 0x00a00000},
- {0x000080d8, 0x00400000},
- {0x000080dc, 0x00000000},
- {0x000080e0, 0xffffffff},
- {0x000080e4, 0x0000ffff},
- {0x000080e8, 0x3f3f3f3f},
- {0x000080ec, 0x00000000},
- {0x000080f0, 0x00000000},
- {0x000080f4, 0x00000000},
- {0x000080fc, 0x00020000},
- {0x00008100, 0x00000000},
- {0x00008108, 0x00000052},
- {0x0000810c, 0x00000000},
- {0x00008110, 0x00000000},
- {0x00008114, 0x000007ff},
- {0x00008118, 0x000000aa},
- {0x0000811c, 0x00003210},
- {0x00008124, 0x00000000},
- {0x00008128, 0x00000000},
- {0x0000812c, 0x00000000},
- {0x00008130, 0x00000000},
- {0x00008134, 0x00000000},
- {0x00008138, 0x00000000},
- {0x0000813c, 0x0000ffff},
- {0x00008144, 0xffffffff},
- {0x00008168, 0x00000000},
- {0x0000816c, 0x00000000},
- {0x00008170, 0x18486200},
- {0x00008174, 0x33332210},
- {0x00008178, 0x00000000},
- {0x0000817c, 0x00020000},
- {0x000081c0, 0x00000000},
- {0x000081c4, 0x33332210},
- {0x000081c8, 0x00000000},
- {0x000081cc, 0x00000000},
- {0x000081d4, 0x00000000},
- {0x000081ec, 0x00000000},
- {0x000081f0, 0x00000000},
- {0x000081f4, 0x00000000},
- {0x000081f8, 0x00000000},
- {0x000081fc, 0x00000000},
- {0x00008240, 0x00100000},
- {0x00008244, 0x0010f424},
- {0x00008248, 0x00000800},
- {0x0000824c, 0x0001e848},
- {0x00008250, 0x00000000},
- {0x00008254, 0x00000000},
- {0x00008258, 0x00000000},
- {0x0000825c, 0x40000000},
- {0x00008260, 0x00080922},
- {0x00008264, 0x98a00010},
- {0x00008268, 0xffffffff},
- {0x0000826c, 0x0000ffff},
- {0x00008270, 0x00000000},
- {0x00008274, 0x40000000},
- {0x00008278, 0x003e4180},
- {0x0000827c, 0x00000004},
- {0x00008284, 0x0000002c},
- {0x00008288, 0x0000002c},
- {0x0000828c, 0x000000ff},
- {0x00008294, 0x00000000},
- {0x00008298, 0x00000000},
- {0x0000829c, 0x00000000},
- {0x00008300, 0x00000140},
- {0x00008314, 0x00000000},
- {0x0000831c, 0x0000010d},
- {0x00008328, 0x00000000},
- {0x0000832c, 0x00000007},
- {0x00008330, 0x00000302},
- {0x00008334, 0x00000700},
- {0x00008338, 0x00ff0000},
- {0x0000833c, 0x02400000},
- {0x00008340, 0x000107ff},
- {0x00008344, 0xaa48105b},
- {0x00008348, 0x008f0000},
- {0x0000835c, 0x00000000},
- {0x00008360, 0xffffffff},
- {0x00008364, 0xffffffff},
- {0x00008368, 0x00000000},
- {0x00008370, 0x00000000},
- {0x00008374, 0x000000ff},
- {0x00008378, 0x00000000},
- {0x0000837c, 0x00000000},
- {0x00008380, 0xffffffff},
- {0x00008384, 0xffffffff},
- {0x00008390, 0xffffffff},
- {0x00008394, 0xffffffff},
- {0x00008398, 0x00000000},
- {0x0000839c, 0x00000000},
- {0x000083a0, 0x00000000},
- {0x000083a4, 0x0000fa14},
- {0x000083a8, 0x000f0c00},
- {0x000083ac, 0x33332210},
- {0x000083b0, 0x33332210},
- {0x000083b4, 0x33332210},
- {0x000083b8, 0x33332210},
- {0x000083bc, 0x00000000},
- {0x000083c0, 0x00000000},
- {0x000083c4, 0x00000000},
- {0x000083c8, 0x00000000},
- {0x000083cc, 0x00000200},
- {0x000083d0, 0x000301ff},
-};
-
-static const u32 ar9300Common_wo_xlna_rx_gain_table_2p0[][2] = {
- /* Addr allmodes */
- {0x0000a000, 0x00010000},
- {0x0000a004, 0x00030002},
- {0x0000a008, 0x00050004},
- {0x0000a00c, 0x00810080},
- {0x0000a010, 0x00830082},
- {0x0000a014, 0x01810180},
- {0x0000a018, 0x01830182},
- {0x0000a01c, 0x01850184},
- {0x0000a020, 0x01890188},
- {0x0000a024, 0x018b018a},
- {0x0000a028, 0x018d018c},
- {0x0000a02c, 0x03820190},
- {0x0000a030, 0x03840383},
- {0x0000a034, 0x03880385},
- {0x0000a038, 0x038a0389},
- {0x0000a03c, 0x038c038b},
- {0x0000a040, 0x0390038d},
- {0x0000a044, 0x03920391},
- {0x0000a048, 0x03940393},
- {0x0000a04c, 0x03960395},
- {0x0000a050, 0x00000000},
- {0x0000a054, 0x00000000},
- {0x0000a058, 0x00000000},
- {0x0000a05c, 0x00000000},
- {0x0000a060, 0x00000000},
- {0x0000a064, 0x00000000},
- {0x0000a068, 0x00000000},
- {0x0000a06c, 0x00000000},
- {0x0000a070, 0x00000000},
- {0x0000a074, 0x00000000},
- {0x0000a078, 0x00000000},
- {0x0000a07c, 0x00000000},
- {0x0000a080, 0x29292929},
- {0x0000a084, 0x29292929},
- {0x0000a088, 0x29292929},
- {0x0000a08c, 0x29292929},
- {0x0000a090, 0x22292929},
- {0x0000a094, 0x1d1d2222},
- {0x0000a098, 0x0c111117},
- {0x0000a09c, 0x00030303},
- {0x0000a0a0, 0x00000000},
- {0x0000a0a4, 0x00000000},
- {0x0000a0a8, 0x00000000},
- {0x0000a0ac, 0x00000000},
- {0x0000a0b0, 0x00000000},
- {0x0000a0b4, 0x00000000},
- {0x0000a0b8, 0x00000000},
- {0x0000a0bc, 0x00000000},
- {0x0000a0c0, 0x001f0000},
- {0x0000a0c4, 0x01000101},
- {0x0000a0c8, 0x011e011f},
- {0x0000a0cc, 0x011c011d},
- {0x0000a0d0, 0x02030204},
- {0x0000a0d4, 0x02010202},
- {0x0000a0d8, 0x021f0200},
- {0x0000a0dc, 0x0302021e},
- {0x0000a0e0, 0x03000301},
- {0x0000a0e4, 0x031e031f},
- {0x0000a0e8, 0x0402031d},
- {0x0000a0ec, 0x04000401},
- {0x0000a0f0, 0x041e041f},
- {0x0000a0f4, 0x0502041d},
- {0x0000a0f8, 0x05000501},
- {0x0000a0fc, 0x051e051f},
- {0x0000a100, 0x06010602},
- {0x0000a104, 0x061f0600},
- {0x0000a108, 0x061d061e},
- {0x0000a10c, 0x07020703},
- {0x0000a110, 0x07000701},
- {0x0000a114, 0x00000000},
- {0x0000a118, 0x00000000},
- {0x0000a11c, 0x00000000},
- {0x0000a120, 0x00000000},
- {0x0000a124, 0x00000000},
- {0x0000a128, 0x00000000},
- {0x0000a12c, 0x00000000},
- {0x0000a130, 0x00000000},
- {0x0000a134, 0x00000000},
- {0x0000a138, 0x00000000},
- {0x0000a13c, 0x00000000},
- {0x0000a140, 0x001f0000},
- {0x0000a144, 0x01000101},
- {0x0000a148, 0x011e011f},
- {0x0000a14c, 0x011c011d},
- {0x0000a150, 0x02030204},
- {0x0000a154, 0x02010202},
- {0x0000a158, 0x021f0200},
- {0x0000a15c, 0x0302021e},
- {0x0000a160, 0x03000301},
- {0x0000a164, 0x031e031f},
- {0x0000a168, 0x0402031d},
- {0x0000a16c, 0x04000401},
- {0x0000a170, 0x041e041f},
- {0x0000a174, 0x0502041d},
- {0x0000a178, 0x05000501},
- {0x0000a17c, 0x051e051f},
- {0x0000a180, 0x06010602},
- {0x0000a184, 0x061f0600},
- {0x0000a188, 0x061d061e},
- {0x0000a18c, 0x07020703},
- {0x0000a190, 0x07000701},
- {0x0000a194, 0x00000000},
- {0x0000a198, 0x00000000},
- {0x0000a19c, 0x00000000},
- {0x0000a1a0, 0x00000000},
- {0x0000a1a4, 0x00000000},
- {0x0000a1a8, 0x00000000},
- {0x0000a1ac, 0x00000000},
- {0x0000a1b0, 0x00000000},
- {0x0000a1b4, 0x00000000},
- {0x0000a1b8, 0x00000000},
- {0x0000a1bc, 0x00000000},
- {0x0000a1c0, 0x00000000},
- {0x0000a1c4, 0x00000000},
- {0x0000a1c8, 0x00000000},
- {0x0000a1cc, 0x00000000},
- {0x0000a1d0, 0x00000000},
- {0x0000a1d4, 0x00000000},
- {0x0000a1d8, 0x00000000},
- {0x0000a1dc, 0x00000000},
- {0x0000a1e0, 0x00000000},
- {0x0000a1e4, 0x00000000},
- {0x0000a1e8, 0x00000000},
- {0x0000a1ec, 0x00000000},
- {0x0000a1f0, 0x00000396},
- {0x0000a1f4, 0x00000396},
- {0x0000a1f8, 0x00000396},
- {0x0000a1fc, 0x00000196},
- {0x0000b000, 0x00010000},
- {0x0000b004, 0x00030002},
- {0x0000b008, 0x00050004},
- {0x0000b00c, 0x00810080},
- {0x0000b010, 0x00830082},
- {0x0000b014, 0x01810180},
- {0x0000b018, 0x01830182},
- {0x0000b01c, 0x01850184},
- {0x0000b020, 0x02810280},
- {0x0000b024, 0x02830282},
- {0x0000b028, 0x02850284},
- {0x0000b02c, 0x02890288},
- {0x0000b030, 0x028b028a},
- {0x0000b034, 0x0388028c},
- {0x0000b038, 0x038a0389},
- {0x0000b03c, 0x038c038b},
- {0x0000b040, 0x0390038d},
- {0x0000b044, 0x03920391},
- {0x0000b048, 0x03940393},
- {0x0000b04c, 0x03960395},
- {0x0000b050, 0x00000000},
- {0x0000b054, 0x00000000},
- {0x0000b058, 0x00000000},
- {0x0000b05c, 0x00000000},
- {0x0000b060, 0x00000000},
- {0x0000b064, 0x00000000},
- {0x0000b068, 0x00000000},
- {0x0000b06c, 0x00000000},
- {0x0000b070, 0x00000000},
- {0x0000b074, 0x00000000},
- {0x0000b078, 0x00000000},
- {0x0000b07c, 0x00000000},
- {0x0000b080, 0x32323232},
- {0x0000b084, 0x2f2f3232},
- {0x0000b088, 0x23282a2d},
- {0x0000b08c, 0x1c1e2123},
- {0x0000b090, 0x14171919},
- {0x0000b094, 0x0e0e1214},
- {0x0000b098, 0x03050707},
- {0x0000b09c, 0x00030303},
- {0x0000b0a0, 0x00000000},
- {0x0000b0a4, 0x00000000},
- {0x0000b0a8, 0x00000000},
- {0x0000b0ac, 0x00000000},
- {0x0000b0b0, 0x00000000},
- {0x0000b0b4, 0x00000000},
- {0x0000b0b8, 0x00000000},
- {0x0000b0bc, 0x00000000},
- {0x0000b0c0, 0x003f0020},
- {0x0000b0c4, 0x00400041},
- {0x0000b0c8, 0x0140005f},
- {0x0000b0cc, 0x0160015f},
- {0x0000b0d0, 0x017e017f},
- {0x0000b0d4, 0x02410242},
- {0x0000b0d8, 0x025f0240},
- {0x0000b0dc, 0x027f0260},
- {0x0000b0e0, 0x0341027e},
- {0x0000b0e4, 0x035f0340},
- {0x0000b0e8, 0x037f0360},
- {0x0000b0ec, 0x04400441},
- {0x0000b0f0, 0x0460045f},
- {0x0000b0f4, 0x0541047f},
- {0x0000b0f8, 0x055f0540},
- {0x0000b0fc, 0x057f0560},
- {0x0000b100, 0x06400641},
- {0x0000b104, 0x0660065f},
- {0x0000b108, 0x067e067f},
- {0x0000b10c, 0x07410742},
- {0x0000b110, 0x075f0740},
- {0x0000b114, 0x077f0760},
- {0x0000b118, 0x07800781},
- {0x0000b11c, 0x07a0079f},
- {0x0000b120, 0x07c107bf},
- {0x0000b124, 0x000007c0},
- {0x0000b128, 0x00000000},
- {0x0000b12c, 0x00000000},
- {0x0000b130, 0x00000000},
- {0x0000b134, 0x00000000},
- {0x0000b138, 0x00000000},
- {0x0000b13c, 0x00000000},
- {0x0000b140, 0x003f0020},
- {0x0000b144, 0x00400041},
- {0x0000b148, 0x0140005f},
- {0x0000b14c, 0x0160015f},
- {0x0000b150, 0x017e017f},
- {0x0000b154, 0x02410242},
- {0x0000b158, 0x025f0240},
- {0x0000b15c, 0x027f0260},
- {0x0000b160, 0x0341027e},
- {0x0000b164, 0x035f0340},
- {0x0000b168, 0x037f0360},
- {0x0000b16c, 0x04400441},
- {0x0000b170, 0x0460045f},
- {0x0000b174, 0x0541047f},
- {0x0000b178, 0x055f0540},
- {0x0000b17c, 0x057f0560},
- {0x0000b180, 0x06400641},
- {0x0000b184, 0x0660065f},
- {0x0000b188, 0x067e067f},
- {0x0000b18c, 0x07410742},
- {0x0000b190, 0x075f0740},
- {0x0000b194, 0x077f0760},
- {0x0000b198, 0x07800781},
- {0x0000b19c, 0x07a0079f},
- {0x0000b1a0, 0x07c107bf},
- {0x0000b1a4, 0x000007c0},
- {0x0000b1a8, 0x00000000},
- {0x0000b1ac, 0x00000000},
- {0x0000b1b0, 0x00000000},
- {0x0000b1b4, 0x00000000},
- {0x0000b1b8, 0x00000000},
- {0x0000b1bc, 0x00000000},
- {0x0000b1c0, 0x00000000},
- {0x0000b1c4, 0x00000000},
- {0x0000b1c8, 0x00000000},
- {0x0000b1cc, 0x00000000},
- {0x0000b1d0, 0x00000000},
- {0x0000b1d4, 0x00000000},
- {0x0000b1d8, 0x00000000},
- {0x0000b1dc, 0x00000000},
- {0x0000b1e0, 0x00000000},
- {0x0000b1e4, 0x00000000},
- {0x0000b1e8, 0x00000000},
- {0x0000b1ec, 0x00000000},
- {0x0000b1f0, 0x00000396},
- {0x0000b1f4, 0x00000396},
- {0x0000b1f8, 0x00000396},
- {0x0000b1fc, 0x00000196},
-};
-
-static const u32 ar9300_2p0_soc_preamble[][2] = {
- /* Addr allmodes */
- {0x000040a4, 0x00a0c1c9},
- {0x00007008, 0x00000000},
- {0x00007020, 0x00000000},
- {0x00007034, 0x00000002},
- {0x00007038, 0x000004c2},
-};
-
-static const u32 ar9300PciePhy_pll_on_clkreq_disable_L1_2p0[][2] = {
- /* Addr allmodes */
- {0x00004040, 0x08212e5e},
- {0x00004040, 0x0008003b},
- {0x00004044, 0x00000000},
-};
-
-static const u32 ar9300PciePhy_clkreq_enable_L1_2p0[][2] = {
- /* Addr allmodes */
- {0x00004040, 0x08253e5e},
- {0x00004040, 0x0008003b},
- {0x00004044, 0x00000000},
-};
-
-static const u32 ar9300PciePhy_clkreq_disable_L1_2p0[][2] = {
- /* Addr allmodes */
- {0x00004040, 0x08213e5e},
- {0x00004040, 0x0008003b},
- {0x00004044, 0x00000000},
-};
-
-#endif /* INITVALS_9003_2P0_H */
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
index 4674ea8c9c99..9e6edffe0bd1 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
@@ -18,6 +18,11 @@
#include "hw-ops.h"
#include "ar9003_phy.h"
+enum ar9003_cal_types {
+ IQ_MISMATCH_CAL = BIT(0),
+ TEMP_COMP_CAL = BIT(1),
+};
+
static void ar9003_hw_setup_calibration(struct ath_hw *ah,
struct ath9k_cal_list *currCal)
{
@@ -50,11 +55,6 @@ static void ar9003_hw_setup_calibration(struct ath_hw *ah,
ath_print(common, ATH_DBG_CALIBRATE,
"starting Temperature Compensation Calibration\n");
break;
- case ADC_DC_INIT_CAL:
- case ADC_GAIN_CAL:
- case ADC_DC_CAL:
- /* Not yet */
- break;
}
}
@@ -314,27 +314,6 @@ static const struct ath9k_percal_data iq_cal_single_sample = {
static void ar9003_hw_init_cal_settings(struct ath_hw *ah)
{
ah->iq_caldata.calData = &iq_cal_single_sample;
- ah->supp_cals = IQ_MISMATCH_CAL;
-}
-
-static bool ar9003_hw_iscal_supported(struct ath_hw *ah,
- enum ath9k_cal_types calType)
-{
- switch (calType & ah->supp_cals) {
- case IQ_MISMATCH_CAL:
- /*
- * XXX: Run IQ Mismatch for non-CCK only
- * Note that CHANNEL_B is never set though.
- */
- return true;
- case ADC_GAIN_CAL:
- case ADC_DC_CAL:
- return false;
- case TEMP_COMP_CAL:
- return true;
- }
-
- return false;
}
/*
@@ -773,15 +752,16 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,
/* Initialize list pointers */
ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
+ ah->supp_cals = IQ_MISMATCH_CAL;
- if (ar9003_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) {
+ if (ah->supp_cals & IQ_MISMATCH_CAL) {
INIT_CAL(&ah->iq_caldata);
INSERT_CAL(ah, &ah->iq_caldata);
ath_print(common, ATH_DBG_CALIBRATE,
"enabling IQ Calibration.\n");
}
- if (ar9003_hw_iscal_supported(ah, TEMP_COMP_CAL)) {
+ if (ah->supp_cals & TEMP_COMP_CAL) {
INIT_CAL(&ah->tempCompCalData);
INSERT_CAL(ah, &ah->tempCompCalData);
ath_print(common, ATH_DBG_CALIBRATE,
@@ -808,7 +788,6 @@ void ar9003_hw_attach_calib_ops(struct ath_hw *ah)
priv_ops->init_cal_settings = ar9003_hw_init_cal_settings;
priv_ops->init_cal = ar9003_hw_init_cal;
priv_ops->setup_calibration = ar9003_hw_setup_calibration;
- priv_ops->iscal_supported = ar9003_hw_iscal_supported;
ops->calibrate = ar9003_hw_calibrate;
}
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
index 057fb69ddf7f..c4182359bee4 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
@@ -968,7 +968,7 @@ static int ath9k_hw_ar9300_get_eeprom_rev(struct ath_hw *ah)
}
static u8 ath9k_hw_ar9300_get_num_ant_config(struct ath_hw *ah,
- enum ieee80211_band freq_band)
+ enum ath9k_hal_freq_band freq_band)
{
return 1;
}
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
index 064168909108..c2a057156bfa 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
@@ -16,7 +16,6 @@
#include "hw.h"
#include "ar9003_mac.h"
-#include "ar9003_2p0_initvals.h"
#include "ar9003_2p2_initvals.h"
/* General hardware code for the AR9003 hadware family */
@@ -32,79 +31,12 @@ static bool ar9003_hw_macversion_supported(u32 macversion)
return false;
}
-/* AR9003 2.0 */
-static void ar9003_2p0_hw_init_mode_regs(struct ath_hw *ah)
-{
- /* mac */
- INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
- INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
- ar9300_2p0_mac_core,
- ARRAY_SIZE(ar9300_2p0_mac_core), 2);
- INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
- ar9300_2p0_mac_postamble,
- ARRAY_SIZE(ar9300_2p0_mac_postamble), 5);
-
- /* bb */
- INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
- INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
- ar9300_2p0_baseband_core,
- ARRAY_SIZE(ar9300_2p0_baseband_core), 2);
- INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
- ar9300_2p0_baseband_postamble,
- ARRAY_SIZE(ar9300_2p0_baseband_postamble), 5);
-
- /* radio */
- INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
- INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
- ar9300_2p0_radio_core,
- ARRAY_SIZE(ar9300_2p0_radio_core), 2);
- INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
- ar9300_2p0_radio_postamble,
- ARRAY_SIZE(ar9300_2p0_radio_postamble), 5);
-
- /* soc */
- INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
- ar9300_2p0_soc_preamble,
- ARRAY_SIZE(ar9300_2p0_soc_preamble), 2);
- INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
- INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
- ar9300_2p0_soc_postamble,
- ARRAY_SIZE(ar9300_2p0_soc_postamble), 5);
-
- /* rx/tx gain */
- INIT_INI_ARRAY(&ah->iniModesRxGain,
- ar9300Common_rx_gain_table_2p0,
- ARRAY_SIZE(ar9300Common_rx_gain_table_2p0), 2);
- INIT_INI_ARRAY(&ah->iniModesTxGain,
- ar9300Modes_lowest_ob_db_tx_gain_table_2p0,
- ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p0),
- 5);
-
- /* Load PCIE SERDES settings from INI */
-
- /* Awake Setting */
-
- INIT_INI_ARRAY(&ah->iniPcieSerdes,
- ar9300PciePhy_pll_on_clkreq_disable_L1_2p0,
- ARRAY_SIZE(ar9300PciePhy_pll_on_clkreq_disable_L1_2p0),
- 2);
-
- /* Sleep Setting */
-
- INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
- ar9300PciePhy_clkreq_enable_L1_2p0,
- ARRAY_SIZE(ar9300PciePhy_clkreq_enable_L1_2p0),
- 2);
-
- /* Fast clock modal settings */
- INIT_INI_ARRAY(&ah->iniModesAdditional,
- ar9300Modes_fast_clock_2p0,
- ARRAY_SIZE(ar9300Modes_fast_clock_2p0),
- 3);
-}
-
-/* AR9003 2.2 */
-static void ar9003_2p2_hw_init_mode_regs(struct ath_hw *ah)
+/*
+ * The AR9003 family uses a new INI format (pre, core, post
+ * arrays per subsystem). This provides support for the
+ * AR9003 2.2 chipsets.
+ */
+static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
{
/* mac */
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
@@ -174,57 +106,27 @@ static void ar9003_2p2_hw_init_mode_regs(struct ath_hw *ah)
3);
}
-/*
- * The AR9003 family uses a new INI format (pre, core, post
- * arrays per subsystem).
- */
-static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
-{
- if (AR_SREV_9300_20(ah))
- ar9003_2p0_hw_init_mode_regs(ah);
- else
- ar9003_2p2_hw_init_mode_regs(ah);
-}
-
static void ar9003_tx_gain_table_apply(struct ath_hw *ah)
{
switch (ar9003_hw_get_tx_gain_idx(ah)) {
case 0:
default:
- if (AR_SREV_9300_20(ah))
- INIT_INI_ARRAY(&ah->iniModesTxGain,
- ar9300Modes_lowest_ob_db_tx_gain_table_2p0,
- ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p0),
- 5);
- else
- INIT_INI_ARRAY(&ah->iniModesTxGain,
- ar9300Modes_lowest_ob_db_tx_gain_table_2p2,
- ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2),
- 5);
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9300Modes_lowest_ob_db_tx_gain_table_2p2,
+ ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2),
+ 5);
break;
case 1:
- if (AR_SREV_9300_20(ah))
- INIT_INI_ARRAY(&ah->iniModesTxGain,
- ar9300Modes_high_ob_db_tx_gain_table_2p0,
- ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p0),
- 5);
- else
- INIT_INI_ARRAY(&ah->iniModesTxGain,
- ar9300Modes_high_ob_db_tx_gain_table_2p2,
- ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p2),
- 5);
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9300Modes_high_ob_db_tx_gain_table_2p2,
+ ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p2),
+ 5);
break;
case 2:
- if (AR_SREV_9300_20(ah))
- INIT_INI_ARRAY(&ah->iniModesTxGain,
- ar9300Modes_low_ob_db_tx_gain_table_2p0,
- ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p0),
- 5);
- else
- INIT_INI_ARRAY(&ah->iniModesTxGain,
- ar9300Modes_low_ob_db_tx_gain_table_2p2,
- ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p2),
- 5);
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9300Modes_low_ob_db_tx_gain_table_2p2,
+ ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p2),
+ 5);
break;
}
}
@@ -234,28 +136,16 @@ static void ar9003_rx_gain_table_apply(struct ath_hw *ah)
switch (ar9003_hw_get_rx_gain_idx(ah)) {
case 0:
default:
- if (AR_SREV_9300_20(ah))
- INIT_INI_ARRAY(&ah->iniModesRxGain,
- ar9300Common_rx_gain_table_2p0,
- ARRAY_SIZE(ar9300Common_rx_gain_table_2p0),
- 2);
- else
- INIT_INI_ARRAY(&ah->iniModesRxGain,
- ar9300Common_rx_gain_table_2p2,
- ARRAY_SIZE(ar9300Common_rx_gain_table_2p2),
- 2);
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9300Common_rx_gain_table_2p2,
+ ARRAY_SIZE(ar9300Common_rx_gain_table_2p2),
+ 2);
break;
case 1:
- if (AR_SREV_9300_20(ah))
- INIT_INI_ARRAY(&ah->iniModesRxGain,
- ar9300Common_wo_xlna_rx_gain_table_2p0,
- ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p0),
- 2);
- else
- INIT_INI_ARRAY(&ah->iniModesRxGain,
- ar9300Common_wo_xlna_rx_gain_table_2p2,
- ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p2),
- 2);
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9300Common_wo_xlna_rx_gain_table_2p2,
+ ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p2),
+ 2);
break;
}
}
@@ -333,6 +223,4 @@ void ar9003_hw_attach_ops(struct ath_hw *ah)
ar9003_hw_attach_phy_ops(ah);
ar9003_hw_attach_calib_ops(ah);
ar9003_hw_attach_mac_ops(ah);
-
- ath9k_hw_attach_ani_ops_new(ah);
}
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
index 5b995bee70ae..3b424ca1ba84 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
@@ -185,7 +185,7 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
ath_print(common, ATH_DBG_INTERRUPT,
"AR_INTR_SYNC_LOCAL_TIMEOUT\n");
- REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause);
+ REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause);
(void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR);
}
@@ -616,7 +616,8 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs,
rxs->rs_status |= ATH9K_RXERR_DECRYPT;
} else if (rxsp->status11 & AR_MichaelErr) {
rxs->rs_status |= ATH9K_RXERR_MIC;
- }
+ } else if (rxsp->status11 & AR_KeyMiss)
+ rxs->rs_status |= ATH9K_RXERR_DECRYPT;
}
return 0;
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
index a491854fa38a..669b777729b3 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
@@ -747,9 +747,9 @@ static void ar9003_hw_set_diversity(struct ath_hw *ah, bool value)
static bool ar9003_hw_ani_control(struct ath_hw *ah,
enum ath9k_ani_cmd cmd, int param)
{
- struct ar5416AniState *aniState = ah->curani;
struct ath_common *common = ath9k_hw_common(ah);
struct ath9k_channel *chan = ah->curchan;
+ struct ar5416AniState *aniState = &chan->ani;
s32 value, value2;
switch (cmd & ah->ani_function) {
@@ -1005,15 +1005,13 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
ath_print(common, ATH_DBG_ANI,
"ANI parameters: SI=%d, ofdmWS=%s FS=%d "
- "MRCcck=%s listenTime=%d CC=%d listen=%d "
+ "MRCcck=%s listenTime=%d "
"ofdmErrs=%d cckErrs=%d\n",
aniState->spurImmunityLevel,
!aniState->ofdmWeakSigDetectOff ? "on" : "off",
aniState->firstepLevel,
!aniState->mrcCCKOff ? "on" : "off",
aniState->listenTime,
- aniState->cycleCount,
- aniState->listenTime,
aniState->ofdmPhyErrCount,
aniState->cckPhyErrCount);
return true;
@@ -1067,12 +1065,9 @@ static void ar9003_hw_ani_cache_ini_regs(struct ath_hw *ah)
struct ath_common *common = ath9k_hw_common(ah);
struct ath9k_channel *chan = ah->curchan;
struct ath9k_ani_default *iniDef;
- int index;
u32 val;
- index = ath9k_hw_get_ani_channel_idx(ah, chan);
- aniState = &ah->ani[index];
- ah->curani = aniState;
+ aniState = &ah->curchan->ani;
iniDef = &aniState->iniDef;
ath_print(common, ATH_DBG_ANI,
@@ -1116,8 +1111,6 @@ static void ar9003_hw_ani_cache_ini_regs(struct ath_hw *ah)
aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW;
aniState->ofdmWeakSigDetectOff = !ATH9K_ANI_USE_OFDM_WEAK_SIG;
aniState->mrcCCKOff = !ATH9K_ANI_ENABLE_MRC_CCK;
-
- aniState->cycleCount = 0;
}
void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
@@ -1232,7 +1225,7 @@ void ar9003_hw_bb_watchdog_read(struct ath_hw *ah)
void ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah)
{
struct ath_common *common = ath9k_hw_common(ah);
- u32 rxc_pcnt = 0, rxf_pcnt = 0, txf_pcnt = 0, status;
+ u32 status;
if (likely(!(common->debug_mask & ATH_DBG_RESET)))
return;
@@ -1261,11 +1254,12 @@ void ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah)
"** BB mode: BB_gen_controls=0x%08x **\n",
REG_READ(ah, AR_PHY_GEN_CTRL));
- if (ath9k_hw_GetMibCycleCountsPct(ah, &rxc_pcnt, &rxf_pcnt, &txf_pcnt))
+#define PCT(_field) (common->cc_survey._field * 100 / common->cc_survey.cycles)
+ if (common->cc_survey.cycles)
ath_print(common, ATH_DBG_RESET,
"** BB busy times: rx_clear=%d%%, "
"rx_frame=%d%%, tx_frame=%d%% **\n",
- rxc_pcnt, rxf_pcnt, txf_pcnt);
+ PCT(rx_busy), PCT(rx_frame), PCT(tx_frame));
ath_print(common, ATH_DBG_RESET,
"==== BB update: done ====\n\n");
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 07f26ee7a723..973c919fdd27 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -239,13 +239,11 @@ struct ath_buf {
struct sk_buff *bf_mpdu; /* enclosing frame structure */
void *bf_desc; /* virtual addr of desc */
dma_addr_t bf_daddr; /* physical addr of desc */
- dma_addr_t bf_buf_addr; /* physical addr of data buffer */
+ dma_addr_t bf_buf_addr; /* physical addr of data buffer, for DMA */
bool bf_stale;
- bool bf_isnullfunc;
bool bf_tx_aborted;
u16 bf_flags;
struct ath_buf_state bf_state;
- dma_addr_t bf_dmacontext;
struct ath_wiphy *aphy;
};
@@ -254,7 +252,7 @@ struct ath_atx_tid {
struct list_head buf_q;
struct ath_node *an;
struct ath_atx_ac *ac;
- struct ath_buf *tx_buf[ATH_TID_MAX_BUFS];
+ unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)];
u16 seq_start;
u16 seq_next;
u16 baw_size;
@@ -345,12 +343,10 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
void ath_tx_tasklet(struct ath_softc *sc);
void ath_tx_edma_tasklet(struct ath_softc *sc);
void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb);
-bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno);
-void ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
- u16 tid, u16 *ssn);
+int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
+ u16 tid, u16 *ssn);
void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
-void ath9k_enable_ps(struct ath_softc *sc);
/********/
/* VIFs */
@@ -423,6 +419,7 @@ int ath_beaconq_config(struct ath_softc *sc);
#define ATH_AP_SHORT_CALINTERVAL 100 /* 100 ms */
#define ATH_ANI_POLLINTERVAL_OLD 100 /* 100 ms */
#define ATH_ANI_POLLINTERVAL_NEW 1000 /* 1000 ms */
+#define ATH_LONG_CALINTERVAL_INT 1000 /* 1000 ms */
#define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */
#define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */
@@ -436,14 +433,6 @@ void ath_ani_calibrate(unsigned long data);
/* BTCOEX */
/**********/
-/* Defines the BT AR_BT_COEX_WGHT used */
-enum ath_stomp_type {
- ATH_BTCOEX_NO_STOMP,
- ATH_BTCOEX_STOMP_ALL,
- ATH_BTCOEX_STOMP_LOW,
- ATH_BTCOEX_STOMP_NONE
-};
-
struct ath_btcoex {
bool hw_timer_enabled;
spinlock_t btcoex_lock;
@@ -488,6 +477,60 @@ struct ath_led {
void ath_init_leds(struct ath_softc *sc);
void ath_deinit_leds(struct ath_softc *sc);
+/* Antenna diversity/combining */
+#define ATH_ANT_RX_CURRENT_SHIFT 4
+#define ATH_ANT_RX_MAIN_SHIFT 2
+#define ATH_ANT_RX_MASK 0x3
+
+#define ATH_ANT_DIV_COMB_SHORT_SCAN_INTR 50
+#define ATH_ANT_DIV_COMB_SHORT_SCAN_PKTCOUNT 0x100
+#define ATH_ANT_DIV_COMB_MAX_PKTCOUNT 0x200
+#define ATH_ANT_DIV_COMB_INIT_COUNT 95
+#define ATH_ANT_DIV_COMB_MAX_COUNT 100
+#define ATH_ANT_DIV_COMB_ALT_ANT_RATIO 30
+#define ATH_ANT_DIV_COMB_ALT_ANT_RATIO2 20
+
+#define ATH_ANT_DIV_COMB_LNA1_LNA2_DELTA -3
+#define ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA -1
+#define ATH_ANT_DIV_COMB_LNA1_DELTA_HI -4
+#define ATH_ANT_DIV_COMB_LNA1_DELTA_MID -2
+#define ATH_ANT_DIV_COMB_LNA1_DELTA_LOW 2
+
+enum ath9k_ant_div_comb_lna_conf {
+ ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2,
+ ATH_ANT_DIV_COMB_LNA2,
+ ATH_ANT_DIV_COMB_LNA1,
+ ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2,
+};
+
+struct ath_ant_comb {
+ u16 count;
+ u16 total_pkt_count;
+ bool scan;
+ bool scan_not_start;
+ int main_total_rssi;
+ int alt_total_rssi;
+ int alt_recv_cnt;
+ int main_recv_cnt;
+ int rssi_lna1;
+ int rssi_lna2;
+ int rssi_add;
+ int rssi_sub;
+ int rssi_first;
+ int rssi_second;
+ int rssi_third;
+ bool alt_good;
+ int quick_scan_cnt;
+ int main_conf;
+ enum ath9k_ant_div_comb_lna_conf first_quick_scan_conf;
+ enum ath9k_ant_div_comb_lna_conf second_quick_scan_conf;
+ int first_bias;
+ int second_bias;
+ bool first_ratio;
+ bool second_ratio;
+ unsigned long scan_start_time;
+};
+
/********************/
/* Main driver core */
/********************/
@@ -516,7 +559,6 @@ void ath_deinit_leds(struct ath_softc *sc);
#define SC_OP_RXFLUSH BIT(7)
#define SC_OP_LED_ASSOCIATED BIT(8)
#define SC_OP_LED_ON BIT(9)
-#define SC_OP_SCANNING BIT(10)
#define SC_OP_TSF_RESET BIT(11)
#define SC_OP_BT_PRIORITY_DETECTED BIT(12)
#define SC_OP_BT_SCAN BIT(13)
@@ -528,8 +570,6 @@ void ath_deinit_leds(struct ath_softc *sc);
#define PS_WAIT_FOR_PSPOLL_DATA BIT(2)
#define PS_WAIT_FOR_TX_ACK BIT(3)
#define PS_BEACON_SYNC BIT(4)
-#define PS_NULLFUNC_COMPLETED BIT(5)
-#define PS_ENABLED BIT(6)
struct ath_wiphy;
struct ath_rate_table;
@@ -552,6 +592,8 @@ struct ath_softc {
struct delayed_work wiphy_work;
unsigned long wiphy_scheduler_int;
int wiphy_scheduler_index;
+ struct survey_info *cur_survey;
+ struct survey_info survey[ATH9K_NUM_CHANNELS];
struct tasklet_struct intr_tq;
struct tasklet_struct bcon_tasklet;
@@ -580,8 +622,6 @@ struct ath_softc {
struct ath_rx rx;
struct ath_tx tx;
struct ath_beacon beacon;
- const struct ath_rate_table *cur_rate_table;
- enum wireless_mode cur_rate_mode;
struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
struct ath_led radio_led;
@@ -604,6 +644,8 @@ struct ath_softc {
struct ath_btcoex btcoex;
struct ath_descdma txsdma;
+
+ struct ath_ant_comb ant_comb;
};
struct ath_wiphy {
@@ -670,7 +712,7 @@ static inline void ath_ahb_exit(void) {};
void ath9k_ps_wakeup(struct ath_softc *sc);
void ath9k_ps_restore(struct ath_softc *sc);
-void ath9k_set_bssid_mask(struct ieee80211_hw *hw);
+void ath9k_set_bssid_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
int ath9k_wiphy_add(struct ath_softc *sc);
int ath9k_wiphy_del(struct ath_wiphy *aphy);
void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb);
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
index 4d4b22d52dfd..4ed010d4ef96 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -136,9 +136,10 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw,
bf = avp->av_bcbuf;
skb = bf->bf_mpdu;
if (skb) {
- dma_unmap_single(sc->dev, bf->bf_dmacontext,
+ dma_unmap_single(sc->dev, bf->bf_buf_addr,
skb->len, DMA_TO_DEVICE);
dev_kfree_skb_any(skb);
+ bf->bf_buf_addr = 0;
}
/* Get a new beacon from mac80211 */
@@ -162,12 +163,12 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw,
hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no);
}
- bf->bf_buf_addr = bf->bf_dmacontext =
- dma_map_single(sc->dev, skb->data,
- skb->len, DMA_TO_DEVICE);
+ bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
+ skb->len, DMA_TO_DEVICE);
if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) {
dev_kfree_skb_any(skb);
bf->bf_mpdu = NULL;
+ bf->bf_buf_addr = 0;
ath_print(common, ATH_DBG_FATAL,
"dma_mapping_error on beaconing\n");
return NULL;
@@ -252,10 +253,11 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
bf = avp->av_bcbuf;
if (bf->bf_mpdu != NULL) {
skb = bf->bf_mpdu;
- dma_unmap_single(sc->dev, bf->bf_dmacontext,
+ dma_unmap_single(sc->dev, bf->bf_buf_addr,
skb->len, DMA_TO_DEVICE);
dev_kfree_skb_any(skb);
bf->bf_mpdu = NULL;
+ bf->bf_buf_addr = 0;
}
/* NB: the beacon data buffer must be 32-bit aligned. */
@@ -296,12 +298,12 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
avp->tsf_adjust = cpu_to_le64(0);
bf->bf_mpdu = skb;
- bf->bf_buf_addr = bf->bf_dmacontext =
- dma_map_single(sc->dev, skb->data,
- skb->len, DMA_TO_DEVICE);
+ bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
+ skb->len, DMA_TO_DEVICE);
if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) {
dev_kfree_skb_any(skb);
bf->bf_mpdu = NULL;
+ bf->bf_buf_addr = 0;
ath_print(common, ATH_DBG_FATAL,
"dma_mapping_error on beacon alloc\n");
return -ENOMEM;
@@ -324,10 +326,11 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp)
bf = avp->av_bcbuf;
if (bf->bf_mpdu != NULL) {
struct sk_buff *skb = bf->bf_mpdu;
- dma_unmap_single(sc->dev, bf->bf_dmacontext,
+ dma_unmap_single(sc->dev, bf->bf_buf_addr,
skb->len, DMA_TO_DEVICE);
dev_kfree_skb_any(skb);
bf->bf_mpdu = NULL;
+ bf->bf_buf_addr = 0;
}
list_add_tail(&bf->list, &sc->beacon.bbuf);
@@ -359,11 +362,12 @@ void ath_beacon_tasklet(unsigned long data)
sc->beacon.bmisscnt++;
if (sc->beacon.bmisscnt < BSTUCK_THRESH) {
- ath_print(common, ATH_DBG_BEACON,
+ ath_print(common, ATH_DBG_BSTUCK,
"missed %u consecutive beacons\n",
sc->beacon.bmisscnt);
+ ath9k_hw_bstuck_nfcal(ah);
} else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) {
- ath_print(common, ATH_DBG_BEACON,
+ ath_print(common, ATH_DBG_BSTUCK,
"beacon is officially stuck\n");
sc->sc_flags |= SC_OP_TSF_RESET;
ath_reset(sc, false);
@@ -373,7 +377,7 @@ void ath_beacon_tasklet(unsigned long data)
}
if (sc->beacon.bmisscnt != 0) {
- ath_print(common, ATH_DBG_BEACON,
+ ath_print(common, ATH_DBG_BSTUCK,
"resume beacon xmit after %u misses\n",
sc->beacon.bmisscnt);
sc->beacon.bmisscnt = 0;
diff --git a/drivers/net/wireless/ath/ath9k/btcoex.c b/drivers/net/wireless/ath/ath9k/btcoex.c
index fb4ac15f3b93..6a92e57fddf0 100644
--- a/drivers/net/wireless/ath/ath9k/btcoex.c
+++ b/drivers/net/wireless/ath/ath9k/btcoex.c
@@ -168,6 +168,7 @@ EXPORT_SYMBOL(ath9k_hw_btcoex_set_weight);
static void ath9k_hw_btcoex_enable_3wire(struct ath_hw *ah)
{
struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
+ u32 val;
/*
* Program coex mode and weight registers to
@@ -177,6 +178,12 @@ static void ath9k_hw_btcoex_enable_3wire(struct ath_hw *ah)
REG_WRITE(ah, AR_BT_COEX_WEIGHT, btcoex_hw->bt_coex_weights);
REG_WRITE(ah, AR_BT_COEX_MODE2, btcoex_hw->bt_coex_mode2);
+ if (AR_SREV_9271(ah)) {
+ val = REG_READ(ah, 0x50040);
+ val &= 0xFFFFFEFF;
+ REG_WRITE(ah, 0x50040, val);
+ }
+
REG_RMW_FIELD(ah, AR_QUIET1, AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1);
REG_RMW_FIELD(ah, AR_PCU_MISC, AR_PCU_BT_ANT_PREVENT_RX, 0);
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c
index 45208690c0ec..6d509484b5f6 100644
--- a/drivers/net/wireless/ath/ath9k/calib.c
+++ b/drivers/net/wireless/ath/ath9k/calib.c
@@ -19,8 +19,7 @@
/* Common calibration code */
-/* We can tune this as we go by monitoring really low values */
-#define ATH9K_NF_TOO_LOW -60
+#define ATH9K_NF_TOO_HIGH -60
static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer)
{
@@ -45,11 +44,39 @@ static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer)
return nfval;
}
-static void ath9k_hw_update_nfcal_hist_buffer(struct ath9k_nfcal_hist *h,
+static struct ath_nf_limits *ath9k_hw_get_nf_limits(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ struct ath_nf_limits *limit;
+
+ if (!chan || IS_CHAN_2GHZ(chan))
+ limit = &ah->nf_2g;
+ else
+ limit = &ah->nf_5g;
+
+ return limit;
+}
+
+static s16 ath9k_hw_get_default_nf(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ return ath9k_hw_get_nf_limits(ah, chan)->nominal;
+}
+
+
+static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah,
+ struct ath9k_hw_cal_data *cal,
int16_t *nfarray)
{
+ struct ath_common *common = ath9k_hw_common(ah);
+ struct ath_nf_limits *limit;
+ struct ath9k_nfcal_hist *h;
+ bool high_nf_mid = false;
int i;
+ h = cal->nfCalHist;
+ limit = ath9k_hw_get_nf_limits(ah, ah->curchan);
+
for (i = 0; i < NUM_NF_READINGS; i++) {
h[i].nfCalBuffer[h[i].currIndex] = nfarray[i];
@@ -63,7 +90,39 @@ static void ath9k_hw_update_nfcal_hist_buffer(struct ath9k_nfcal_hist *h,
h[i].privNF =
ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer);
}
+
+ if (!h[i].privNF)
+ continue;
+
+ if (h[i].privNF > limit->max) {
+ high_nf_mid = true;
+
+ ath_print(common, ATH_DBG_CALIBRATE,
+ "NFmid[%d] (%d) > MAX (%d), %s\n",
+ i, h[i].privNF, limit->max,
+ (cal->nfcal_interference ?
+ "not corrected (due to interference)" :
+ "correcting to MAX"));
+
+ /*
+ * Normally we limit the average noise floor by the
+ * hardware specific maximum here. However if we have
+ * encountered stuck beacons because of interference,
+ * we bypass this limit here in order to better deal
+ * with our environment.
+ */
+ if (!cal->nfcal_interference)
+ h[i].privNF = limit->max;
+ }
}
+
+ /*
+ * If the noise floor seems normal for all chains, assume that
+ * there is no significant interference in the environment anymore.
+ * Re-enable the enforcement of the NF maximum again.
+ */
+ if (!high_nf_mid)
+ cal->nfcal_interference = false;
}
static bool ath9k_hw_get_nf_thresh(struct ath_hw *ah,
@@ -104,19 +163,6 @@ void ath9k_hw_reset_calibration(struct ath_hw *ah,
ah->cal_samples = 0;
}
-static s16 ath9k_hw_get_default_nf(struct ath_hw *ah,
- struct ath9k_channel *chan)
-{
- struct ath_nf_limits *limit;
-
- if (!chan || IS_CHAN_2GHZ(chan))
- limit = &ah->nf_2g;
- else
- limit = &ah->nf_5g;
-
- return limit->nominal;
-}
-
/* This is done for the currently configured channel */
bool ath9k_hw_reset_calvalid(struct ath_hw *ah)
{
@@ -140,7 +186,7 @@ bool ath9k_hw_reset_calvalid(struct ath_hw *ah)
return true;
}
- if (!ath9k_hw_iscal_supported(ah, currCal->calData->calType))
+ if (!(ah->supp_cals & currCal->calData->calType))
return true;
ath_print(common, ATH_DBG_CALIBRATE,
@@ -254,7 +300,6 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
}
}
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
}
@@ -277,10 +322,10 @@ static void ath9k_hw_nf_sanitize(struct ath_hw *ah, s16 *nf)
"NF calibrated [%s] [chain %d] is %d\n",
(i >= 3 ? "ext" : "ctl"), i % 3, nf[i]);
- if (nf[i] > limit->max) {
+ if (nf[i] > ATH9K_NF_TOO_HIGH) {
ath_print(common, ATH_DBG_CALIBRATE,
"NF[%d] (%d) > MAX (%d), correcting to MAX",
- i, nf[i], limit->max);
+ i, nf[i], ATH9K_NF_TOO_HIGH);
nf[i] = limit->max;
} else if (nf[i] < limit->min) {
ath_print(common, ATH_DBG_CALIBRATE,
@@ -300,34 +345,34 @@ bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan)
struct ieee80211_channel *c = chan->chan;
struct ath9k_hw_cal_data *caldata = ah->caldata;
- if (!caldata)
- return false;
-
chan->channelFlags &= (~CHANNEL_CW_INT);
if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) {
ath_print(common, ATH_DBG_CALIBRATE,
"NF did not complete in calibration window\n");
- nf = 0;
- caldata->rawNoiseFloor = nf;
return false;
- } else {
- ath9k_hw_do_getnf(ah, nfarray);
- ath9k_hw_nf_sanitize(ah, nfarray);
- nf = nfarray[0];
- if (ath9k_hw_get_nf_thresh(ah, c->band, &nfThresh)
- && nf > nfThresh) {
- ath_print(common, ATH_DBG_CALIBRATE,
- "noise floor failed detected; "
- "detected %d, threshold %d\n",
- nf, nfThresh);
- chan->channelFlags |= CHANNEL_CW_INT;
- }
+ }
+
+ ath9k_hw_do_getnf(ah, nfarray);
+ ath9k_hw_nf_sanitize(ah, nfarray);
+ nf = nfarray[0];
+ if (ath9k_hw_get_nf_thresh(ah, c->band, &nfThresh)
+ && nf > nfThresh) {
+ ath_print(common, ATH_DBG_CALIBRATE,
+ "noise floor failed detected; "
+ "detected %d, threshold %d\n",
+ nf, nfThresh);
+ chan->channelFlags |= CHANNEL_CW_INT;
+ }
+
+ if (!caldata) {
+ chan->noisefloor = nf;
+ return false;
}
h = caldata->nfCalHist;
caldata->nfcal_pending = false;
- ath9k_hw_update_nfcal_hist_buffer(h, nfarray);
- caldata->rawNoiseFloor = h[0].privNF;
+ ath9k_hw_update_nfcal_hist_buffer(ah, caldata, nfarray);
+ chan->noisefloor = h[0].privNF;
return true;
}
@@ -355,9 +400,34 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah,
s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan)
{
- if (!ah->caldata || !ah->caldata->rawNoiseFloor)
+ if (!ah->curchan || !ah->curchan->noisefloor)
return ath9k_hw_get_default_nf(ah, chan);
- return ah->caldata->rawNoiseFloor;
+ return ah->curchan->noisefloor;
}
EXPORT_SYMBOL(ath9k_hw_getchan_noise);
+
+void ath9k_hw_bstuck_nfcal(struct ath_hw *ah)
+{
+ struct ath9k_hw_cal_data *caldata = ah->caldata;
+
+ if (unlikely(!caldata))
+ return;
+
+ /*
+ * If beacons are stuck, the most likely cause is interference.
+ * Triggering a noise floor calibration at this point helps the
+ * hardware adapt to a noisy environment much faster.
+ * To ensure that we recover from stuck beacons quickly, let
+ * the baseband update the internal NF value itself, similar to
+ * what is being done after a full reset.
+ */
+ if (!caldata->nfcal_pending)
+ ath9k_hw_start_nfcal(ah, true);
+ else if (!(REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF))
+ ath9k_hw_getnf(ah, ah->curchan);
+
+ caldata->nfcal_interference = true;
+}
+EXPORT_SYMBOL(ath9k_hw_bstuck_nfcal);
+
diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h
index 0a304b3eeeb6..b8973eb8d858 100644
--- a/drivers/net/wireless/ath/ath9k/calib.h
+++ b/drivers/net/wireless/ath/ath9k/calib.h
@@ -58,14 +58,6 @@ struct ar5416IniArray {
} \
} while (0)
-enum ath9k_cal_types {
- ADC_DC_INIT_CAL = 0x1,
- ADC_GAIN_CAL = 0x2,
- ADC_DC_CAL = 0x4,
- IQ_MISMATCH_CAL = 0x8,
- TEMP_COMP_CAL = 0x10,
-};
-
enum ath9k_cal_state {
CAL_INACTIVE,
CAL_WAITING,
@@ -80,7 +72,7 @@ enum ath9k_cal_state {
#define PER_MAX_LOG_COUNT 10
struct ath9k_percal_data {
- enum ath9k_cal_types calType;
+ u32 calType;
u32 calNumSamples;
u32 calCountMax;
void (*calCollect) (struct ath_hw *);
@@ -113,6 +105,7 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan);
bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan);
void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah,
struct ath9k_channel *chan);
+void ath9k_hw_bstuck_nfcal(struct ath_hw *ah);
s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan);
void ath9k_hw_reset_calibration(struct ath_hw *ah,
struct ath9k_cal_list *currCal);
diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c
index c86f7d3593ab..f43a2d98421c 100644
--- a/drivers/net/wireless/ath/ath9k/common.c
+++ b/drivers/net/wireless/ath/ath9k/common.c
@@ -46,12 +46,17 @@ int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb)
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
if (tx_info->control.hw_key) {
- if (tx_info->control.hw_key->alg == ALG_WEP)
+ switch (tx_info->control.hw_key->cipher) {
+ case WLAN_CIPHER_SUITE_WEP40:
+ case WLAN_CIPHER_SUITE_WEP104:
return ATH9K_KEY_TYPE_WEP;
- else if (tx_info->control.hw_key->alg == ALG_TKIP)
+ case WLAN_CIPHER_SUITE_TKIP:
return ATH9K_KEY_TYPE_TKIP;
- else if (tx_info->control.hw_key->alg == ALG_CCMP)
+ case WLAN_CIPHER_SUITE_CCMP:
return ATH9K_KEY_TYPE_AES;
+ default:
+ break;
+ }
}
return ATH9K_KEY_TYPE_CLEAR;
@@ -143,276 +148,49 @@ struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw,
}
EXPORT_SYMBOL(ath9k_cmn_get_curchannel);
-static int ath_setkey_tkip(struct ath_common *common, u16 keyix, const u8 *key,
- struct ath9k_keyval *hk, const u8 *addr,
- bool authenticator)
-{
- struct ath_hw *ah = common->ah;
- const u8 *key_rxmic;
- const u8 *key_txmic;
-
- key_txmic = key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY;
- key_rxmic = key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY;
-
- if (addr == NULL) {
- /*
- * Group key installation - only two key cache entries are used
- * regardless of splitmic capability since group key is only
- * used either for TX or RX.
- */
- if (authenticator) {
- memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic));
- memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_mic));
- } else {
- memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
- memcpy(hk->kv_txmic, key_rxmic, sizeof(hk->kv_mic));
- }
- return ath9k_hw_set_keycache_entry(ah, keyix, hk, addr);
- }
- if (!common->splitmic) {
- /* TX and RX keys share the same key cache entry. */
- memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
- memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_txmic));
- return ath9k_hw_set_keycache_entry(ah, keyix, hk, addr);
- }
-
- /* Separate key cache entries for TX and RX */
-
- /* TX key goes at first index, RX key at +32. */
- memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic));
- if (!ath9k_hw_set_keycache_entry(ah, keyix, hk, NULL)) {
- /* TX MIC entry failed. No need to proceed further */
- ath_print(common, ATH_DBG_FATAL,
- "Setting TX MIC Key Failed\n");
- return 0;
- }
-
- memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
- /* XXX delete tx key on failure? */
- return ath9k_hw_set_keycache_entry(ah, keyix + 32, hk, addr);
-}
-
-static int ath_reserve_key_cache_slot_tkip(struct ath_common *common)
-{
- int i;
-
- for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) {
- if (test_bit(i, common->keymap) ||
- test_bit(i + 64, common->keymap))
- continue; /* At least one part of TKIP key allocated */
- if (common->splitmic &&
- (test_bit(i + 32, common->keymap) ||
- test_bit(i + 64 + 32, common->keymap)))
- continue; /* At least one part of TKIP key allocated */
-
- /* Found a free slot for a TKIP key */
- return i;
- }
- return -1;
-}
-
-static int ath_reserve_key_cache_slot(struct ath_common *common,
- enum ieee80211_key_alg alg)
+int ath9k_cmn_count_streams(unsigned int chainmask, int max)
{
- int i;
-
- if (alg == ALG_TKIP)
- return ath_reserve_key_cache_slot_tkip(common);
-
- /* First, try to find slots that would not be available for TKIP. */
- if (common->splitmic) {
- for (i = IEEE80211_WEP_NKID; i < common->keymax / 4; i++) {
- if (!test_bit(i, common->keymap) &&
- (test_bit(i + 32, common->keymap) ||
- test_bit(i + 64, common->keymap) ||
- test_bit(i + 64 + 32, common->keymap)))
- return i;
- if (!test_bit(i + 32, common->keymap) &&
- (test_bit(i, common->keymap) ||
- test_bit(i + 64, common->keymap) ||
- test_bit(i + 64 + 32, common->keymap)))
- return i + 32;
- if (!test_bit(i + 64, common->keymap) &&
- (test_bit(i , common->keymap) ||
- test_bit(i + 32, common->keymap) ||
- test_bit(i + 64 + 32, common->keymap)))
- return i + 64;
- if (!test_bit(i + 64 + 32, common->keymap) &&
- (test_bit(i, common->keymap) ||
- test_bit(i + 32, common->keymap) ||
- test_bit(i + 64, common->keymap)))
- return i + 64 + 32;
- }
- } else {
- for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) {
- if (!test_bit(i, common->keymap) &&
- test_bit(i + 64, common->keymap))
- return i;
- if (test_bit(i, common->keymap) &&
- !test_bit(i + 64, common->keymap))
- return i + 64;
- }
- }
-
- /* No partially used TKIP slots, pick any available slot */
- for (i = IEEE80211_WEP_NKID; i < common->keymax; i++) {
- /* Do not allow slots that could be needed for TKIP group keys
- * to be used. This limitation could be removed if we know that
- * TKIP will not be used. */
- if (i >= 64 && i < 64 + IEEE80211_WEP_NKID)
- continue;
- if (common->splitmic) {
- if (i >= 32 && i < 32 + IEEE80211_WEP_NKID)
- continue;
- if (i >= 64 + 32 && i < 64 + 32 + IEEE80211_WEP_NKID)
- continue;
- }
+ int streams = 0;
- if (!test_bit(i, common->keymap))
- return i; /* Found a free slot for a key */
- }
+ do {
+ if (++streams == max)
+ break;
+ } while ((chainmask = chainmask & (chainmask - 1)));
- /* No free slot found */
- return -1;
+ return streams;
}
+EXPORT_SYMBOL(ath9k_cmn_count_streams);
/*
- * Configure encryption in the HW.
+ * Configures appropriate weight based on stomp type.
*/
-int ath9k_cmn_key_config(struct ath_common *common,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
- struct ieee80211_key_conf *key)
+void ath9k_cmn_btcoex_bt_stomp(struct ath_common *common,
+ enum ath_stomp_type stomp_type)
{
struct ath_hw *ah = common->ah;
- struct ath9k_keyval hk;
- const u8 *mac = NULL;
- u8 gmac[ETH_ALEN];
- int ret = 0;
- int idx;
- memset(&hk, 0, sizeof(hk));
-
- switch (key->alg) {
- case ALG_WEP:
- hk.kv_type = ATH9K_CIPHER_WEP;
+ switch (stomp_type) {
+ case ATH_BTCOEX_STOMP_ALL:
+ ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
+ AR_STOMP_ALL_WLAN_WGHT);
break;
- case ALG_TKIP:
- hk.kv_type = ATH9K_CIPHER_TKIP;
+ case ATH_BTCOEX_STOMP_LOW:
+ ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
+ AR_STOMP_LOW_WLAN_WGHT);
break;
- case ALG_CCMP:
- hk.kv_type = ATH9K_CIPHER_AES_CCM;
+ case ATH_BTCOEX_STOMP_NONE:
+ ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
+ AR_STOMP_NONE_WLAN_WGHT);
break;
default:
- return -EOPNOTSUPP;
- }
-
- hk.kv_len = key->keylen;
- memcpy(hk.kv_val, key->key, key->keylen);
-
- if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
- switch (vif->type) {
- case NL80211_IFTYPE_AP:
- memcpy(gmac, vif->addr, ETH_ALEN);
- gmac[0] |= 0x01;
- mac = gmac;
- idx = ath_reserve_key_cache_slot(common, key->alg);
- break;
- case NL80211_IFTYPE_ADHOC:
- if (!sta) {
- idx = key->keyidx;
- break;
- }
- memcpy(gmac, sta->addr, ETH_ALEN);
- gmac[0] |= 0x01;
- mac = gmac;
- idx = ath_reserve_key_cache_slot(common, key->alg);
- break;
- default:
- idx = key->keyidx;
- break;
- }
- } else if (key->keyidx) {
- if (WARN_ON(!sta))
- return -EOPNOTSUPP;
- mac = sta->addr;
-
- if (vif->type != NL80211_IFTYPE_AP) {
- /* Only keyidx 0 should be used with unicast key, but
- * allow this for client mode for now. */
- idx = key->keyidx;
- } else
- return -EIO;
- } else {
- if (WARN_ON(!sta))
- return -EOPNOTSUPP;
- mac = sta->addr;
-
- idx = ath_reserve_key_cache_slot(common, key->alg);
- }
-
- if (idx < 0)
- return -ENOSPC; /* no free key cache entries */
-
- if (key->alg == ALG_TKIP)
- ret = ath_setkey_tkip(common, idx, key->key, &hk, mac,
- vif->type == NL80211_IFTYPE_AP);
- else
- ret = ath9k_hw_set_keycache_entry(ah, idx, &hk, mac);
-
- if (!ret)
- return -EIO;
-
- set_bit(idx, common->keymap);
- if (key->alg == ALG_TKIP) {
- set_bit(idx + 64, common->keymap);
- if (common->splitmic) {
- set_bit(idx + 32, common->keymap);
- set_bit(idx + 64 + 32, common->keymap);
- }
- }
-
- return idx;
-}
-EXPORT_SYMBOL(ath9k_cmn_key_config);
-
-/*
- * Delete Key.
- */
-void ath9k_cmn_key_delete(struct ath_common *common,
- struct ieee80211_key_conf *key)
-{
- struct ath_hw *ah = common->ah;
-
- ath9k_hw_keyreset(ah, key->hw_key_idx);
- if (key->hw_key_idx < IEEE80211_WEP_NKID)
- return;
-
- clear_bit(key->hw_key_idx, common->keymap);
- if (key->alg != ALG_TKIP)
- return;
-
- clear_bit(key->hw_key_idx + 64, common->keymap);
- if (common->splitmic) {
- ath9k_hw_keyreset(ah, key->hw_key_idx + 32);
- clear_bit(key->hw_key_idx + 32, common->keymap);
- clear_bit(key->hw_key_idx + 64 + 32, common->keymap);
+ ath_print(common, ATH_DBG_BTCOEX,
+ "Invalid Stomptype\n");
+ break;
}
-}
-EXPORT_SYMBOL(ath9k_cmn_key_delete);
-
-int ath9k_cmn_count_streams(unsigned int chainmask, int max)
-{
- int streams = 0;
-
- do {
- if (++streams == max)
- break;
- } while ((chainmask = chainmask & (chainmask - 1)));
- return streams;
+ ath9k_hw_btcoex_enable(ah);
}
-EXPORT_SYMBOL(ath9k_cmn_count_streams);
+EXPORT_SYMBOL(ath9k_cmn_btcoex_bt_stomp);
static int __init ath9k_cmn_init(void)
{
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h
index 97809d39c73f..fea3b3315391 100644
--- a/drivers/net/wireless/ath/ath9k/common.h
+++ b/drivers/net/wireless/ath/ath9k/common.h
@@ -52,16 +52,20 @@
#define ATH_EP_RND(x, mul) \
((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul))
+/* Defines the BT AR_BT_COEX_WGHT used */
+enum ath_stomp_type {
+ ATH_BTCOEX_NO_STOMP,
+ ATH_BTCOEX_STOMP_ALL,
+ ATH_BTCOEX_STOMP_LOW,
+ ATH_BTCOEX_STOMP_NONE
+};
+
int ath9k_cmn_padpos(__le16 frame_control);
int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb);
void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw,
struct ath9k_channel *ichan);
struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw,
struct ath_hw *ah);
-int ath9k_cmn_key_config(struct ath_common *common,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
- struct ieee80211_key_conf *key);
-void ath9k_cmn_key_delete(struct ath_common *common,
- struct ieee80211_key_conf *key);
int ath9k_cmn_count_streams(unsigned int chainmask, int max);
+void ath9k_cmn_btcoex_bt_stomp(struct ath_common *common,
+ enum ath_stomp_type stomp_type);
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index 54aae931424e..43e71a944cb1 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -71,7 +71,8 @@ static const struct file_operations fops_debug = {
.read = read_file_debug,
.write = write_file_debug,
.open = ath9k_debugfs_open,
- .owner = THIS_MODULE
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
};
#endif
@@ -116,7 +117,8 @@ static const struct file_operations fops_tx_chainmask = {
.read = read_file_tx_chainmask,
.write = write_file_tx_chainmask,
.open = ath9k_debugfs_open,
- .owner = THIS_MODULE
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
};
@@ -158,7 +160,8 @@ static const struct file_operations fops_rx_chainmask = {
.read = read_file_rx_chainmask,
.write = write_file_rx_chainmask,
.open = ath9k_debugfs_open,
- .owner = THIS_MODULE
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
};
@@ -259,7 +262,8 @@ static ssize_t read_file_dma(struct file *file, char __user *user_buf,
static const struct file_operations fops_dma = {
.read = read_file_dma,
.open = ath9k_debugfs_open,
- .owner = THIS_MODULE
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
};
@@ -375,96 +379,8 @@ static ssize_t read_file_interrupt(struct file *file, char __user *user_buf,
static const struct file_operations fops_interrupt = {
.read = read_file_interrupt,
.open = ath9k_debugfs_open,
- .owner = THIS_MODULE
-};
-
-void ath_debug_stat_rc(struct ath_softc *sc, int final_rate)
-{
- struct ath_rc_stats *stats;
-
- stats = &sc->debug.stats.rcstats[final_rate];
- stats->success++;
-}
-
-void ath_debug_stat_retries(struct ath_softc *sc, int rix,
- int xretries, int retries, u8 per)
-{
- struct ath_rc_stats *stats = &sc->debug.stats.rcstats[rix];
-
- stats->xretries += xretries;
- stats->retries += retries;
- stats->per = per;
-}
-
-static ssize_t read_file_rcstat(struct file *file, char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct ath_softc *sc = file->private_data;
- char *buf;
- unsigned int len = 0, max;
- int i = 0;
- ssize_t retval;
-
- if (sc->cur_rate_table == NULL)
- return 0;
-
- max = 80 + sc->cur_rate_table->rate_cnt * 1024 + 1;
- buf = kmalloc(max, GFP_KERNEL);
- if (buf == NULL)
- return -ENOMEM;
-
- len += sprintf(buf, "%6s %6s %6s "
- "%10s %10s %10s %10s\n",
- "HT", "MCS", "Rate",
- "Success", "Retries", "XRetries", "PER");
-
- for (i = 0; i < sc->cur_rate_table->rate_cnt; i++) {
- u32 ratekbps = sc->cur_rate_table->info[i].ratekbps;
- struct ath_rc_stats *stats = &sc->debug.stats.rcstats[i];
- char mcs[5];
- char htmode[5];
- int used_mcs = 0, used_htmode = 0;
-
- if (WLAN_RC_PHY_HT(sc->cur_rate_table->info[i].phy)) {
- used_mcs = snprintf(mcs, 5, "%d",
- sc->cur_rate_table->info[i].ratecode);
-
- if (WLAN_RC_PHY_40(sc->cur_rate_table->info[i].phy))
- used_htmode = snprintf(htmode, 5, "HT40");
- else if (WLAN_RC_PHY_20(sc->cur_rate_table->info[i].phy))
- used_htmode = snprintf(htmode, 5, "HT20");
- else
- used_htmode = snprintf(htmode, 5, "????");
- }
-
- mcs[used_mcs] = '\0';
- htmode[used_htmode] = '\0';
-
- len += snprintf(buf + len, max - len,
- "%6s %6s %3u.%d: "
- "%10u %10u %10u %10u\n",
- htmode,
- mcs,
- ratekbps / 1000,
- (ratekbps % 1000) / 100,
- stats->success,
- stats->retries,
- stats->xretries,
- stats->per);
- }
-
- if (len > max)
- len = max;
-
- retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
- kfree(buf);
- return retval;
-}
-
-static const struct file_operations fops_rcstat = {
- .read = read_file_rcstat,
- .open = ath9k_debugfs_open,
- .owner = THIS_MODULE
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
};
static const char * ath_wiphy_state_str(enum ath_wiphy_state state)
@@ -488,26 +404,20 @@ static ssize_t read_file_wiphy(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
+ struct ath_wiphy *aphy = sc->pri_wiphy;
+ struct ieee80211_channel *chan = aphy->hw->conf.channel;
char buf[512];
unsigned int len = 0;
int i;
u8 addr[ETH_ALEN];
+ u32 tmp;
len += snprintf(buf + len, sizeof(buf) - len,
"primary: %s (%s chan=%d ht=%d)\n",
wiphy_name(sc->pri_wiphy->hw->wiphy),
ath_wiphy_state_str(sc->pri_wiphy->state),
- sc->pri_wiphy->chan_idx, sc->pri_wiphy->chan_is_ht);
- for (i = 0; i < sc->num_sec_wiphy; i++) {
- struct ath_wiphy *aphy = sc->sec_wiphy[i];
- if (aphy == NULL)
- continue;
- len += snprintf(buf + len, sizeof(buf) - len,
- "secondary: %s (%s chan=%d ht=%d)\n",
- wiphy_name(aphy->hw->wiphy),
- ath_wiphy_state_str(aphy->state),
- aphy->chan_idx, aphy->chan_is_ht);
- }
+ ieee80211_frequency_to_channel(chan->center_freq),
+ aphy->chan_is_ht);
put_unaligned_le32(REG_READ_D(sc->sc_ah, AR_STA_ID0), addr);
put_unaligned_le16(REG_READ_D(sc->sc_ah, AR_STA_ID1) & 0xffff, addr + 4);
@@ -517,7 +427,51 @@ static ssize_t read_file_wiphy(struct file *file, char __user *user_buf,
put_unaligned_le16(REG_READ_D(sc->sc_ah, AR_BSSMSKU) & 0xffff, addr + 4);
len += snprintf(buf + len, sizeof(buf) - len,
"addrmask: %pM\n", addr);
-
+ tmp = ath9k_hw_getrxfilter(sc->sc_ah);
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "rfilt: 0x%x", tmp);
+ if (tmp & ATH9K_RX_FILTER_UCAST)
+ len += snprintf(buf + len, sizeof(buf) - len, " UCAST");
+ if (tmp & ATH9K_RX_FILTER_MCAST)
+ len += snprintf(buf + len, sizeof(buf) - len, " MCAST");
+ if (tmp & ATH9K_RX_FILTER_BCAST)
+ len += snprintf(buf + len, sizeof(buf) - len, " BCAST");
+ if (tmp & ATH9K_RX_FILTER_CONTROL)
+ len += snprintf(buf + len, sizeof(buf) - len, " CONTROL");
+ if (tmp & ATH9K_RX_FILTER_BEACON)
+ len += snprintf(buf + len, sizeof(buf) - len, " BEACON");
+ if (tmp & ATH9K_RX_FILTER_PROM)
+ len += snprintf(buf + len, sizeof(buf) - len, " PROM");
+ if (tmp & ATH9K_RX_FILTER_PROBEREQ)
+ len += snprintf(buf + len, sizeof(buf) - len, " PROBEREQ");
+ if (tmp & ATH9K_RX_FILTER_PHYERR)
+ len += snprintf(buf + len, sizeof(buf) - len, " PHYERR");
+ if (tmp & ATH9K_RX_FILTER_MYBEACON)
+ len += snprintf(buf + len, sizeof(buf) - len, " MYBEACON");
+ if (tmp & ATH9K_RX_FILTER_COMP_BAR)
+ len += snprintf(buf + len, sizeof(buf) - len, " COMP_BAR");
+ if (tmp & ATH9K_RX_FILTER_PSPOLL)
+ len += snprintf(buf + len, sizeof(buf) - len, " PSPOLL");
+ if (tmp & ATH9K_RX_FILTER_PHYRADAR)
+ len += snprintf(buf + len, sizeof(buf) - len, " PHYRADAR");
+ if (tmp & ATH9K_RX_FILTER_MCAST_BCAST_ALL)
+ len += snprintf(buf + len, sizeof(buf) - len, " MCAST_BCAST_ALL\n");
+ else
+ len += snprintf(buf + len, sizeof(buf) - len, "\n");
+
+ /* Put variable-length stuff down here, and check for overflows. */
+ for (i = 0; i < sc->num_sec_wiphy; i++) {
+ struct ath_wiphy *aphy = sc->sec_wiphy[i];
+ if (aphy == NULL)
+ continue;
+ chan = aphy->hw->conf.channel;
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "secondary: %s (%s chan=%d ht=%d)\n",
+ wiphy_name(aphy->hw->wiphy),
+ ath_wiphy_state_str(aphy->state),
+ ieee80211_frequency_to_channel(chan->center_freq),
+ aphy->chan_is_ht);
+ }
if (len > sizeof(buf))
len = sizeof(buf);
@@ -623,7 +577,8 @@ static const struct file_operations fops_wiphy = {
.read = read_file_wiphy,
.write = write_file_wiphy,
.open = ath9k_debugfs_open,
- .owner = THIS_MODULE
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
};
#define PR(str, elem) \
@@ -663,6 +618,8 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
PR("DESC CFG Error: ", desc_cfg_err);
PR("DATA Underrun: ", data_underrun);
PR("DELIM Underrun: ", delim_underrun);
+ PR("TX-Pkts-All: ", tx_pkts_all);
+ PR("TX-Bytes-All: ", tx_bytes_all);
if (len > size)
len = size;
@@ -676,6 +633,9 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq,
struct ath_buf *bf, struct ath_tx_status *ts)
{
+ TX_STAT_INC(txq->axq_qnum, tx_pkts_all);
+ sc->debug.stats.txstats[txq->axq_qnum].tx_bytes_all += bf->bf_mpdu->len;
+
if (bf_isampdu(bf)) {
if (bf_isxretried(bf))
TX_STAT_INC(txq->axq_qnum, a_xretries);
@@ -702,7 +662,8 @@ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq,
static const struct file_operations fops_xmit = {
.read = read_file_xmit,
.open = ath9k_debugfs_open,
- .owner = THIS_MODULE
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
};
static ssize_t read_file_recv(struct file *file, char __user *user_buf,
@@ -770,6 +731,13 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf,
PHY_ERR("HT-LENGTH", ATH9K_PHYERR_HT_LENGTH_ILLEGAL);
PHY_ERR("HT-RATE", ATH9K_PHYERR_HT_RATE_ILLEGAL);
+ len += snprintf(buf + len, size - len,
+ "%18s : %10u\n", "RX-Pkts-All",
+ sc->debug.stats.rxstats.rx_pkts_all);
+ len += snprintf(buf + len, size - len,
+ "%18s : %10u\n", "RX-Bytes-All",
+ sc->debug.stats.rxstats.rx_bytes_all);
+
if (len > size)
len = size;
@@ -788,6 +756,9 @@ void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs)
u32 phyerr;
+ RX_STAT_INC(rx_pkts_all);
+ sc->debug.stats.rxstats.rx_bytes_all += rs->rs_datalen;
+
if (rs->rs_status & ATH9K_RXERR_CRC)
RX_STAT_INC(crc_err);
if (rs->rs_status & ATH9K_RXERR_DECRYPT)
@@ -814,7 +785,8 @@ void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs)
static const struct file_operations fops_recv = {
.read = read_file_recv,
.open = ath9k_debugfs_open,
- .owner = THIS_MODULE
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
};
static ssize_t read_file_regidx(struct file *file, char __user *user_buf,
@@ -852,7 +824,8 @@ static const struct file_operations fops_regidx = {
.read = read_file_regidx,
.write = write_file_regidx,
.open = ath9k_debugfs_open,
- .owner = THIS_MODULE
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
};
static ssize_t read_file_regval(struct file *file, char __user *user_buf,
@@ -894,7 +867,8 @@ static const struct file_operations fops_regval = {
.read = read_file_regval,
.write = write_file_regval,
.open = ath9k_debugfs_open,
- .owner = THIS_MODULE
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
};
int ath9k_init_debug(struct ath_hw *ah)
@@ -924,10 +898,6 @@ int ath9k_init_debug(struct ath_hw *ah)
sc, &fops_interrupt))
goto err;
- if (!debugfs_create_file("rcstat", S_IRUSR, sc->debug.debugfs_phy,
- sc, &fops_rcstat))
- goto err;
-
if (!debugfs_create_file("wiphy", S_IRUSR | S_IWUSR,
sc->debug.debugfs_phy, sc, &fops_wiphy))
goto err;
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
index 5d21704e87ff..bb0823242ba0 100644
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -80,15 +80,12 @@ struct ath_interrupt_stats {
u32 bb_watchdog;
};
-struct ath_rc_stats {
- u32 success;
- u32 retries;
- u32 xretries;
- u8 per;
-};
-
/**
* struct ath_tx_stats - Statistics about TX
+ * @tx_pkts_all: No. of total frames transmitted, including ones that
+ may have had errors.
+ * @tx_bytes_all: No. of total bytes transmitted, including ones that
+ may have had errors.
* @queued: Total MPDUs (non-aggr) queued
* @completed: Total MPDUs (non-aggr) completed
* @a_aggr: Total no. of aggregates queued
@@ -107,6 +104,8 @@ struct ath_rc_stats {
* @delim_urn: TX delimiter underrun errors
*/
struct ath_tx_stats {
+ u32 tx_pkts_all;
+ u32 tx_bytes_all;
u32 queued;
u32 completed;
u32 a_aggr;
@@ -124,6 +123,10 @@ struct ath_tx_stats {
/**
* struct ath_rx_stats - RX Statistics
+ * @rx_pkts_all: No. of total frames received, including ones that
+ may have had errors.
+ * @rx_bytes_all: No. of total bytes received, including ones that
+ may have had errors.
* @crc_err: No. of frames with incorrect CRC value
* @decrypt_crc_err: No. of frames whose CRC check failed after
decryption process completed
@@ -136,6 +139,8 @@ struct ath_tx_stats {
* @phy_err_stats: Individual PHY error statistics
*/
struct ath_rx_stats {
+ u32 rx_pkts_all;
+ u32 rx_bytes_all;
u32 crc_err;
u32 decrypt_crc_err;
u32 phy_err;
@@ -148,7 +153,6 @@ struct ath_rx_stats {
struct ath_stats {
struct ath_interrupt_stats istats;
- struct ath_rc_stats rcstats[RATE_TABLE_SIZE];
struct ath_tx_stats txstats[ATH9K_NUM_TX_QUEUES];
struct ath_rx_stats rxstats;
};
@@ -165,12 +169,9 @@ void ath9k_exit_debug(struct ath_hw *ah);
int ath9k_debug_create_root(void);
void ath9k_debug_remove_root(void);
void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status);
-void ath_debug_stat_rc(struct ath_softc *sc, int final_rate);
void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq,
struct ath_buf *bf, struct ath_tx_status *ts);
void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs);
-void ath_debug_stat_retries(struct ath_softc *sc, int rix,
- int xretries, int retries, u8 per);
#else
@@ -197,11 +198,6 @@ static inline void ath_debug_stat_interrupt(struct ath_softc *sc,
{
}
-static inline void ath_debug_stat_rc(struct ath_softc *sc,
- int final_rate)
-{
-}
-
static inline void ath_debug_stat_tx(struct ath_softc *sc,
struct ath_txq *txq,
struct ath_buf *bf,
@@ -214,11 +210,6 @@ static inline void ath_debug_stat_rx(struct ath_softc *sc,
{
}
-static inline void ath_debug_stat_retries(struct ath_softc *sc, int rix,
- int xretries, int retries, u8 per)
-{
-}
-
#endif /* CONFIG_ATH9K_DEBUGFS */
#endif /* DEBUG_H */
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h
index 0b09db0f8e7d..dacb45e1b906 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom.h
+++ b/drivers/net/wireless/ath/ath9k/eeprom.h
@@ -101,7 +101,7 @@
#define AR5416_VER_MASK (eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK)
#define OLC_FOR_AR9280_20_LATER (AR_SREV_9280_20_OR_LATER(ah) && \
ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
-#define OLC_FOR_AR9287_10_LATER (AR_SREV_9287_10_OR_LATER(ah) && \
+#define OLC_FOR_AR9287_10_LATER (AR_SREV_9287_11_OR_LATER(ah) && \
ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
#define AR_EEPROM_RFSILENT_GPIO_SEL 0x001c
@@ -266,6 +266,8 @@ enum eeprom_param {
EEP_INTERNAL_REGULATOR,
EEP_SWREG,
EEP_PAPRD,
+ EEP_MODAL_VER,
+ EEP_ANT_DIV_CTL1,
};
enum ar5416_rates {
@@ -670,7 +672,8 @@ struct eeprom_ops {
bool (*fill_eeprom)(struct ath_hw *hw);
int (*get_eeprom_ver)(struct ath_hw *hw);
int (*get_eeprom_rev)(struct ath_hw *hw);
- u8 (*get_num_ant_config)(struct ath_hw *hw, enum ieee80211_band band);
+ u8 (*get_num_ant_config)(struct ath_hw *hw,
+ enum ath9k_hal_freq_band band);
u32 (*get_eeprom_antenna_cfg)(struct ath_hw *hw,
struct ath9k_channel *chan);
void (*set_board_values)(struct ath_hw *hw, struct ath9k_channel *chan);
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
index 9cccd12e8f21..4fa4d8e28c64 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
@@ -179,6 +179,9 @@ static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah,
struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
struct modal_eep_4k_header *pModal = &eep->modalHeader;
struct base_eep_header_4k *pBase = &eep->baseEepHeader;
+ u16 ver_minor;
+
+ ver_minor = pBase->version & AR5416_EEP_VER_MINOR_MASK;
switch (param) {
case EEP_NFTHRESH_2:
@@ -204,7 +207,7 @@ static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah,
case EEP_DB_2:
return pModal->db1_1;
case EEP_MINOR_REV:
- return pBase->version & AR5416_EEP_VER_MINOR_MASK;
+ return ver_minor;
case EEP_TX_MASK:
return pBase->txMask;
case EEP_RX_MASK:
@@ -213,6 +216,15 @@ static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah,
return 0;
case EEP_PWR_TABLE_OFFSET:
return AR5416_PWR_TABLE_OFFSET_DB;
+ case EEP_MODAL_VER:
+ return pModal->version;
+ case EEP_ANT_DIV_CTL1:
+ return pModal->antdiv_ctl1;
+ case EEP_TXGAIN_TYPE:
+ if (ver_minor >= AR5416_EEP_MINOR_VER_19)
+ return pBase->txGainType;
+ else
+ return AR5416_EEP_TXGAIN_ORIGINAL;
default:
return 0;
}
@@ -329,7 +341,7 @@ static void ath9k_hw_get_4k_gain_boundaries_pdadcs(struct ath_hw *ah,
}
if (i == 0) {
- if (AR_SREV_9280_10_OR_LATER(ah))
+ if (AR_SREV_9280_20_OR_LATER(ah))
ss = (int16_t)(0 - (minPwrT4[i] / 2));
else
ss = 0;
@@ -496,7 +508,6 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
}
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
}
}
@@ -757,7 +768,7 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
regulatory->max_power_level = ratesArray[i];
- if (AR_SREV_9280_10_OR_LATER(ah)) {
+ if (AR_SREV_9280_20_OR_LATER(ah)) {
for (i = 0; i < Ar5416RateSize; i++)
ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2;
}
@@ -828,7 +839,6 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
}
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
}
static void ath9k_hw_4k_set_addac(struct ath_hw *ah,
@@ -905,9 +915,6 @@ static void ath9k_hw_4k_set_gain(struct ath_hw *ah,
AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);
REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000,
AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]);
-
- if (AR_SREV_9285_11(ah))
- REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14));
}
/*
@@ -1105,9 +1112,6 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah,
}
- if (AR_SREV_9285_11(ah))
- REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT);
-
REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH,
pModal->switchSettling);
REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC,
@@ -1157,7 +1161,7 @@ static u32 ath9k_hw_4k_get_eeprom_antenna_cfg(struct ath_hw *ah,
}
static u8 ath9k_hw_4k_get_num_ant_config(struct ath_hw *ah,
- enum ieee80211_band freq_band)
+ enum ath9k_hal_freq_band freq_band)
{
return 1;
}
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
index dff2da777312..966b9496a9dd 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
@@ -324,7 +324,7 @@ static void ath9k_hw_get_ar9287_gain_boundaries_pdadcs(struct ath_hw *ah,
minDelta = 0;
if (i == 0) {
- if (AR_SREV_9280_10_OR_LATER(ah))
+ if (AR_SREV_9280_20_OR_LATER(ah))
ss = (int16_t)(0 - (minPwrT4[i] / 2));
else
ss = 0;
@@ -883,7 +883,7 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
ratesArray[i] = AR9287_MAX_RATE_POWER;
}
- if (AR_SREV_9280_10_OR_LATER(ah)) {
+ if (AR_SREV_9280_20_OR_LATER(ah)) {
for (i = 0; i < Ar5416RateSize; i++)
ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2;
}
@@ -977,7 +977,7 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
else
i = rate6mb;
- if (AR_SREV_9280_10_OR_LATER(ah))
+ if (AR_SREV_9280_20_OR_LATER(ah))
regulatory->max_power_level =
ratesArray[i] + AR9287_PWR_TABLE_OFFSET_DB * 2;
else
@@ -1126,7 +1126,7 @@ static void ath9k_hw_ar9287_set_board_values(struct ath_hw *ah,
}
static u8 ath9k_hw_ar9287_get_num_ant_config(struct ath_hw *ah,
- enum ieee80211_band freq_band)
+ enum ath9k_hal_freq_band freq_band)
{
return 1;
}
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c
index afa2b73ddbdd..76b4d65472dd 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_def.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
@@ -223,7 +223,7 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
}
/* Enable fixup for AR_AN_TOP2 if necessary */
- if (AR_SREV_9280_10_OR_LATER(ah) &&
+ if (AR_SREV_9280_20_OR_LATER(ah) &&
(eep->baseEepHeader.version & 0xff) > 0x0a &&
eep->baseEepHeader.pwdclkind == 0)
ah->need_an_top2_fixup = 1;
@@ -317,7 +317,7 @@ static void ath9k_hw_def_set_gain(struct ath_hw *ah,
if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) {
txRxAttenLocal = pModal->txRxAttenCh[i];
- if (AR_SREV_9280_10_OR_LATER(ah)) {
+ if (AR_SREV_9280_20_OR_LATER(ah)) {
REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
pModal->bswMargin[i]);
@@ -344,7 +344,7 @@ static void ath9k_hw_def_set_gain(struct ath_hw *ah,
}
}
- if (AR_SREV_9280_10_OR_LATER(ah)) {
+ if (AR_SREV_9280_20_OR_LATER(ah)) {
REG_RMW_FIELD(ah,
AR_PHY_RXGAIN + regChainOffset,
AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);
@@ -408,7 +408,7 @@ static void ath9k_hw_def_set_board_values(struct ath_hw *ah,
regChainOffset, i);
}
- if (AR_SREV_9280_10_OR_LATER(ah)) {
+ if (AR_SREV_9280_20_OR_LATER(ah)) {
if (IS_CHAN_2GHZ(chan)) {
ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0,
AR_AN_RF2G1_CH0_OB,
@@ -461,7 +461,7 @@ static void ath9k_hw_def_set_board_values(struct ath_hw *ah,
REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC,
pModal->adcDesiredSize);
- if (!AR_SREV_9280_10_OR_LATER(ah))
+ if (!AR_SREV_9280_20_OR_LATER(ah))
REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
AR_PHY_DESIRED_SZ_PGA,
pModal->pgaDesiredSize);
@@ -478,7 +478,7 @@ static void ath9k_hw_def_set_board_values(struct ath_hw *ah,
REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,
pModal->txEndToRxOn);
- if (AR_SREV_9280_10_OR_LATER(ah)) {
+ if (AR_SREV_9280_20_OR_LATER(ah)) {
REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62,
pModal->thresh62);
REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0,
@@ -696,7 +696,7 @@ static void ath9k_hw_get_def_gain_boundaries_pdadcs(struct ath_hw *ah,
}
if (i == 0) {
- if (AR_SREV_9280_10_OR_LATER(ah))
+ if (AR_SREV_9280_20_OR_LATER(ah))
ss = (int16_t)(0 - (minPwrT4[i] / 2));
else
ss = 0;
@@ -1291,7 +1291,7 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
ratesArray[i] = AR5416_MAX_RATE_POWER;
}
- if (AR_SREV_9280_10_OR_LATER(ah)) {
+ if (AR_SREV_9280_20_OR_LATER(ah)) {
for (i = 0; i < Ar5416RateSize; i++) {
int8_t pwr_table_offset;
@@ -1395,7 +1395,7 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
else if (IS_CHAN_HT20(chan))
i = rateHt20_0;
- if (AR_SREV_9280_10_OR_LATER(ah))
+ if (AR_SREV_9280_20_OR_LATER(ah))
regulatory->max_power_level =
ratesArray[i] + AR5416_PWR_TABLE_OFFSET_DB * 2;
else
@@ -1418,11 +1418,11 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
}
static u8 ath9k_hw_def_get_num_ant_config(struct ath_hw *ah,
- enum ieee80211_band freq_band)
+ enum ath9k_hal_freq_band freq_band)
{
struct ar5416_eeprom_def *eep = &ah->eeprom.def;
struct modal_eep_header *pModal =
- &(eep->modalHeader[ATH9K_HAL_FREQ_BAND_2GHZ == freq_band]);
+ &(eep->modalHeader[freq_band]);
struct base_eep_header *pBase = &eep->baseEepHeader;
u8 num_ant_config;
diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c
index 3a8ee999da5d..4a9a68bba324 100644
--- a/drivers/net/wireless/ath/ath9k/gpio.c
+++ b/drivers/net/wireless/ath/ath9k/gpio.c
@@ -251,36 +251,6 @@ static void ath_detect_bt_priority(struct ath_softc *sc)
}
}
-/*
- * Configures appropriate weight based on stomp type.
- */
-static void ath9k_btcoex_bt_stomp(struct ath_softc *sc,
- enum ath_stomp_type stomp_type)
-{
- struct ath_hw *ah = sc->sc_ah;
-
- switch (stomp_type) {
- case ATH_BTCOEX_STOMP_ALL:
- ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
- AR_STOMP_ALL_WLAN_WGHT);
- break;
- case ATH_BTCOEX_STOMP_LOW:
- ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
- AR_STOMP_LOW_WLAN_WGHT);
- break;
- case ATH_BTCOEX_STOMP_NONE:
- ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
- AR_STOMP_NONE_WLAN_WGHT);
- break;
- default:
- ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX,
- "Invalid Stomptype\n");
- break;
- }
-
- ath9k_hw_btcoex_enable(ah);
-}
-
static void ath9k_gen_timer_start(struct ath_hw *ah,
struct ath_gen_timer *timer,
u32 timer_next,
@@ -319,6 +289,7 @@ static void ath_btcoex_period_timer(unsigned long data)
struct ath_softc *sc = (struct ath_softc *) data;
struct ath_hw *ah = sc->sc_ah;
struct ath_btcoex *btcoex = &sc->btcoex;
+ struct ath_common *common = ath9k_hw_common(ah);
u32 timer_period;
bool is_btscan;
@@ -328,7 +299,7 @@ static void ath_btcoex_period_timer(unsigned long data)
spin_lock_bh(&btcoex->btcoex_lock);
- ath9k_btcoex_bt_stomp(sc, is_btscan ? ATH_BTCOEX_STOMP_ALL :
+ ath9k_cmn_btcoex_bt_stomp(common, is_btscan ? ATH_BTCOEX_STOMP_ALL :
btcoex->bt_stomp_type);
spin_unlock_bh(&btcoex->btcoex_lock);
@@ -359,17 +330,18 @@ static void ath_btcoex_no_stomp_timer(void *arg)
struct ath_softc *sc = (struct ath_softc *)arg;
struct ath_hw *ah = sc->sc_ah;
struct ath_btcoex *btcoex = &sc->btcoex;
+ struct ath_common *common = ath9k_hw_common(ah);
bool is_btscan = sc->sc_flags & SC_OP_BT_SCAN;
- ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX,
+ ath_print(common, ATH_DBG_BTCOEX,
"no stomp timer running\n");
spin_lock_bh(&btcoex->btcoex_lock);
if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW || is_btscan)
- ath9k_btcoex_bt_stomp(sc, ATH_BTCOEX_STOMP_NONE);
+ ath9k_cmn_btcoex_bt_stomp(common, ATH_BTCOEX_STOMP_NONE);
else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL)
- ath9k_btcoex_bt_stomp(sc, ATH_BTCOEX_STOMP_LOW);
+ ath9k_cmn_btcoex_bt_stomp(common, ATH_BTCOEX_STOMP_LOW);
spin_unlock_bh(&btcoex->btcoex_lock);
}
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index 17e7a9a367e7..728d904c74d7 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -92,10 +92,10 @@ static int hif_usb_send_regout(struct hif_device_usb *hif_dev,
cmd->skb = skb;
cmd->hif_dev = hif_dev;
- usb_fill_int_urb(urb, hif_dev->udev,
- usb_sndintpipe(hif_dev->udev, USB_REG_OUT_PIPE),
+ usb_fill_bulk_urb(urb, hif_dev->udev,
+ usb_sndbulkpipe(hif_dev->udev, USB_REG_OUT_PIPE),
skb->data, skb->len,
- hif_usb_regout_cb, cmd, 1);
+ hif_usb_regout_cb, cmd);
usb_anchor_urb(urb, &hif_dev->regout_submitted);
ret = usb_submit_urb(urb, GFP_KERNEL);
@@ -541,7 +541,8 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb)
}
usb_fill_int_urb(urb, hif_dev->udev,
- usb_rcvintpipe(hif_dev->udev, USB_REG_IN_PIPE),
+ usb_rcvbulkpipe(hif_dev->udev,
+ USB_REG_IN_PIPE),
nskb->data, MAX_REG_IN_BUF_SIZE,
ath9k_hif_usb_reg_in_cb, nskb, 1);
@@ -720,7 +721,8 @@ static int ath9k_hif_usb_alloc_reg_in_urb(struct hif_device_usb *hif_dev)
goto err;
usb_fill_int_urb(hif_dev->reg_in_urb, hif_dev->udev,
- usb_rcvintpipe(hif_dev->udev, USB_REG_IN_PIPE),
+ usb_rcvbulkpipe(hif_dev->udev,
+ USB_REG_IN_PIPE),
skb->data, MAX_REG_IN_BUF_SIZE,
ath9k_hif_usb_reg_in_cb, skb, 1);
@@ -822,7 +824,9 @@ static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev)
static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev)
{
- int ret;
+ int ret, idx;
+ struct usb_host_interface *alt = &hif_dev->interface->altsetting[0];
+ struct usb_endpoint_descriptor *endp;
/* Request firmware */
ret = request_firmware(&hif_dev->firmware, hif_dev->fw_name,
@@ -850,6 +854,22 @@ static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev)
goto err_fw_download;
}
+ /* On downloading the firmware to the target, the USB descriptor of EP4
+ * is 'patched' to change the type of the endpoint to Bulk. This will
+ * bring down CPU usage during the scan period.
+ */
+ for (idx = 0; idx < alt->desc.bNumEndpoints; idx++) {
+ endp = &alt->endpoint[idx].desc;
+ if (((endp->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK)
+ == 0x04) &&
+ ((endp->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+ == USB_ENDPOINT_XFER_INT)) {
+ endp->bmAttributes &= ~USB_ENDPOINT_XFERTYPE_MASK;
+ endp->bmAttributes |= USB_ENDPOINT_XFER_BULK;
+ endp->bInterval = 0;
+ }
+ }
+
return 0;
err_fw_download:
@@ -920,7 +940,8 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface,
}
ret = ath9k_htc_hw_init(hif_dev->htc_handle,
- &hif_dev->udev->dev, hif_dev->device_id);
+ &hif_dev->udev->dev, hif_dev->device_id,
+ hif_dev->udev->product);
if (ret) {
ret = -EINVAL;
goto err_htc_hw_init;
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index 43b9e21bc562..75ecf6a30d25 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -316,17 +316,32 @@ struct htc_beacon_config {
u8 dtim_count;
};
-#define OP_INVALID BIT(0)
-#define OP_SCANNING BIT(1)
-#define OP_FULL_RESET BIT(2)
-#define OP_LED_ASSOCIATED BIT(3)
-#define OP_LED_ON BIT(4)
-#define OP_PREAMBLE_SHORT BIT(5)
-#define OP_PROTECT_ENABLE BIT(6)
-#define OP_ASSOCIATED BIT(7)
-#define OP_ENABLE_BEACON BIT(8)
-#define OP_LED_DEINIT BIT(9)
-#define OP_UNPLUGGED BIT(10)
+struct ath_btcoex {
+ u32 bt_priority_cnt;
+ unsigned long bt_priority_time;
+ int bt_stomp_type; /* Types of BT stomping */
+ u32 btcoex_no_stomp;
+ u32 btcoex_period;
+ u32 btscan_no_stomp;
+};
+
+void ath_htc_init_btcoex_work(struct ath9k_htc_priv *priv);
+void ath_htc_resume_btcoex_work(struct ath9k_htc_priv *priv);
+void ath_htc_cancel_btcoex_work(struct ath9k_htc_priv *priv);
+
+#define OP_INVALID BIT(0)
+#define OP_SCANNING BIT(1)
+#define OP_FULL_RESET BIT(2)
+#define OP_LED_ASSOCIATED BIT(3)
+#define OP_LED_ON BIT(4)
+#define OP_PREAMBLE_SHORT BIT(5)
+#define OP_PROTECT_ENABLE BIT(6)
+#define OP_ASSOCIATED BIT(7)
+#define OP_ENABLE_BEACON BIT(8)
+#define OP_LED_DEINIT BIT(9)
+#define OP_UNPLUGGED BIT(10)
+#define OP_BT_PRIORITY_DETECTED BIT(11)
+#define OP_BT_SCAN BIT(12)
struct ath9k_htc_priv {
struct device *dev;
@@ -391,6 +406,9 @@ struct ath9k_htc_priv {
int cabq;
int hwq_map[WME_NUM_AC];
+ struct ath_btcoex btcoex;
+ struct delayed_work coex_period_work;
+ struct delayed_work duty_cycle_work;
#ifdef CONFIG_ATH9K_HTC_DEBUGFS
struct ath9k_debug debug;
#endif
@@ -443,7 +461,7 @@ void ath9k_init_leds(struct ath9k_htc_priv *priv);
void ath9k_deinit_leds(struct ath9k_htc_priv *priv);
int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev,
- u16 devid);
+ u16 devid, char *product);
void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug);
#ifdef CONFIG_PM
int ath9k_htc_resume(struct htc_target *htc_handle);
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
index bd1506e69105..1b72aa482ac7 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
@@ -235,7 +235,14 @@ void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv)
ath9k_hw_get_txq_props(ah, qnum, &qi_be);
qi.tqi_aifs = qi_be.tqi_aifs;
- qi.tqi_cwmin = 4*qi_be.tqi_cwmin;
+ /* For WIFI Beacon Distribution
+ * Long slot time : 2x cwmin
+ * Short slot time : 4x cwmin
+ */
+ if (ah->slottime == ATH9K_SLOT_TIME_20)
+ qi.tqi_cwmin = 2*qi_be.tqi_cwmin;
+ else
+ qi.tqi_cwmin = 4*qi_be.tqi_cwmin;
qi.tqi_cwmax = qi_be.tqi_cwmax;
if (!ath9k_hw_set_txq_props(ah, priv->beaconq, &qi)) {
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c
new file mode 100644
index 000000000000..50eec9a3b88c
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c
@@ -0,0 +1,134 @@
+#include "htc.h"
+
+/******************/
+/* BTCOEX */
+/******************/
+
+/*
+ * Detects if there is any priority bt traffic
+ */
+static void ath_detect_bt_priority(struct ath9k_htc_priv *priv)
+{
+ struct ath_btcoex *btcoex = &priv->btcoex;
+ struct ath_hw *ah = priv->ah;
+
+ if (ath9k_hw_gpio_get(ah, ah->btcoex_hw.btpriority_gpio))
+ btcoex->bt_priority_cnt++;
+
+ if (time_after(jiffies, btcoex->bt_priority_time +
+ msecs_to_jiffies(ATH_BT_PRIORITY_TIME_THRESHOLD))) {
+ priv->op_flags &= ~(OP_BT_PRIORITY_DETECTED | OP_BT_SCAN);
+ /* Detect if colocated bt started scanning */
+ if (btcoex->bt_priority_cnt >= ATH_BT_CNT_SCAN_THRESHOLD) {
+ ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX,
+ "BT scan detected");
+ priv->op_flags |= (OP_BT_SCAN |
+ OP_BT_PRIORITY_DETECTED);
+ } else if (btcoex->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) {
+ ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX,
+ "BT priority traffic detected");
+ priv->op_flags |= OP_BT_PRIORITY_DETECTED;
+ }
+
+ btcoex->bt_priority_cnt = 0;
+ btcoex->bt_priority_time = jiffies;
+ }
+}
+
+/*
+ * This is the master bt coex work which runs for every
+ * 45ms, bt traffic will be given priority during 55% of this
+ * period while wlan gets remaining 45%
+ */
+static void ath_btcoex_period_work(struct work_struct *work)
+{
+ struct ath9k_htc_priv *priv = container_of(work, struct ath9k_htc_priv,
+ coex_period_work.work);
+ struct ath_btcoex *btcoex = &priv->btcoex;
+ struct ath_common *common = ath9k_hw_common(priv->ah);
+ u32 timer_period;
+ bool is_btscan;
+ int ret;
+ u8 cmd_rsp, aggr;
+
+ ath_detect_bt_priority(priv);
+
+ is_btscan = !!(priv->op_flags & OP_BT_SCAN);
+
+ aggr = priv->op_flags & OP_BT_PRIORITY_DETECTED;
+
+ WMI_CMD_BUF(WMI_AGGR_LIMIT_CMD, &aggr);
+
+ ath9k_cmn_btcoex_bt_stomp(common, is_btscan ? ATH_BTCOEX_STOMP_ALL :
+ btcoex->bt_stomp_type);
+
+ timer_period = is_btscan ? btcoex->btscan_no_stomp :
+ btcoex->btcoex_no_stomp;
+ ieee80211_queue_delayed_work(priv->hw, &priv->duty_cycle_work,
+ msecs_to_jiffies(timer_period));
+ ieee80211_queue_delayed_work(priv->hw, &priv->coex_period_work,
+ msecs_to_jiffies(btcoex->btcoex_period));
+}
+
+/*
+ * Work to time slice between wlan and bt traffic and
+ * configure weight registers
+ */
+static void ath_btcoex_duty_cycle_work(struct work_struct *work)
+{
+ struct ath9k_htc_priv *priv = container_of(work, struct ath9k_htc_priv,
+ duty_cycle_work.work);
+ struct ath_hw *ah = priv->ah;
+ struct ath_btcoex *btcoex = &priv->btcoex;
+ struct ath_common *common = ath9k_hw_common(ah);
+ bool is_btscan = priv->op_flags & OP_BT_SCAN;
+
+ ath_print(common, ATH_DBG_BTCOEX,
+ "time slice work for bt and wlan\n");
+
+ if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW || is_btscan)
+ ath9k_cmn_btcoex_bt_stomp(common, ATH_BTCOEX_STOMP_NONE);
+ else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL)
+ ath9k_cmn_btcoex_bt_stomp(common, ATH_BTCOEX_STOMP_LOW);
+}
+
+void ath_htc_init_btcoex_work(struct ath9k_htc_priv *priv)
+{
+ struct ath_btcoex *btcoex = &priv->btcoex;
+
+ btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD;
+ btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) *
+ btcoex->btcoex_period / 100;
+ btcoex->btscan_no_stomp = (100 - ATH_BTCOEX_BTSCAN_DUTY_CYCLE) *
+ btcoex->btcoex_period / 100;
+ INIT_DELAYED_WORK(&priv->coex_period_work, ath_btcoex_period_work);
+ INIT_DELAYED_WORK(&priv->duty_cycle_work, ath_btcoex_duty_cycle_work);
+}
+
+/*
+ * (Re)start btcoex work
+ */
+
+void ath_htc_resume_btcoex_work(struct ath9k_htc_priv *priv)
+{
+ struct ath_btcoex *btcoex = &priv->btcoex;
+ struct ath_hw *ah = priv->ah;
+
+ ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX,
+ "Starting btcoex work");
+
+ btcoex->bt_priority_cnt = 0;
+ btcoex->bt_priority_time = jiffies;
+ priv->op_flags &= ~(OP_BT_PRIORITY_DETECTED | OP_BT_SCAN);
+ ieee80211_queue_delayed_work(priv->hw, &priv->coex_period_work, 0);
+}
+
+
+/*
+ * Cancel btcoex and bt duty cycle work.
+ */
+void ath_htc_cancel_btcoex_work(struct ath9k_htc_priv *priv)
+{
+ cancel_delayed_work_sync(&priv->coex_period_work);
+ cancel_delayed_work_sync(&priv->duty_cycle_work);
+}
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
index 2d4279191d7a..3d7b97f1b3ae 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
@@ -41,6 +41,8 @@ MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption");
.max_power = 20, \
}
+#define ATH_HTC_BTCOEX_PRODUCT_ID "wb193"
+
static struct ieee80211_channel ath9k_2ghz_channels[] = {
CHAN2G(2412, 0), /* Channel 1 */
CHAN2G(2417, 1), /* Channel 2 */
@@ -378,15 +380,6 @@ static void ath9k_enable_regwrite_buffer(void *hw_priv)
atomic_inc(&priv->wmi->mwrite_cnt);
}
-static void ath9k_disable_regwrite_buffer(void *hw_priv)
-{
- struct ath_hw *ah = (struct ath_hw *) hw_priv;
- struct ath_common *common = ath9k_hw_common(ah);
- struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
-
- atomic_dec(&priv->wmi->mwrite_cnt);
-}
-
static void ath9k_regwrite_flush(void *hw_priv)
{
struct ath_hw *ah = (struct ath_hw *) hw_priv;
@@ -395,6 +388,8 @@ static void ath9k_regwrite_flush(void *hw_priv)
u32 rsp_status;
int r;
+ atomic_dec(&priv->wmi->mwrite_cnt);
+
mutex_lock(&priv->wmi->multi_write_mutex);
if (priv->wmi->multi_write_idx) {
@@ -418,7 +413,6 @@ static const struct ath_ops ath9k_common_ops = {
.read = ath9k_regread,
.write = ath9k_regwrite,
.enable_write_buffer = ath9k_enable_regwrite_buffer,
- .disable_write_buffer = ath9k_disable_regwrite_buffer,
.write_flush = ath9k_regwrite_flush,
};
@@ -559,17 +553,20 @@ static void ath9k_init_crypto(struct ath9k_htc_priv *priv)
common->keymax = ATH_KEYMAX;
}
+ if (priv->ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA)
+ common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED;
+
/*
* Reset the key cache since some parts do not
* reset the contents on initial power up.
*/
for (i = 0; i < common->keymax; i++)
- ath9k_hw_keyreset(priv->ah, (u16) i);
+ ath_hw_keyreset(common, (u16) i);
}
static void ath9k_init_channels_rates(struct ath9k_htc_priv *priv)
{
- if (test_bit(ATH9K_MODE_11G, priv->ah->caps.wireless_modes)) {
+ if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) {
priv->sbands[IEEE80211_BAND_2GHZ].channels =
ath9k_2ghz_channels;
priv->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
@@ -580,7 +577,7 @@ static void ath9k_init_channels_rates(struct ath9k_htc_priv *priv)
ARRAY_SIZE(ath9k_legacy_rates);
}
- if (test_bit(ATH9K_MODE_11A, priv->ah->caps.wireless_modes)) {
+ if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) {
priv->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_channels;
priv->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ;
priv->sbands[IEEE80211_BAND_5GHZ].n_channels =
@@ -599,13 +596,36 @@ static void ath9k_init_misc(struct ath9k_htc_priv *priv)
common->tx_chainmask = priv->ah->caps.tx_chainmask;
common->rx_chainmask = priv->ah->caps.rx_chainmask;
- if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK)
- memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
+ memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
priv->ah->opmode = NL80211_IFTYPE_STATION;
}
-static int ath9k_init_priv(struct ath9k_htc_priv *priv, u16 devid)
+static void ath9k_init_btcoex(struct ath9k_htc_priv *priv)
+{
+ int qnum;
+
+ switch (priv->ah->btcoex_hw.scheme) {
+ case ATH_BTCOEX_CFG_NONE:
+ break;
+ case ATH_BTCOEX_CFG_3WIRE:
+ priv->ah->btcoex_hw.btactive_gpio = 7;
+ priv->ah->btcoex_hw.btpriority_gpio = 6;
+ priv->ah->btcoex_hw.wlanactive_gpio = 8;
+ priv->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
+ ath9k_hw_btcoex_init_3wire(priv->ah);
+ ath_htc_init_btcoex_work(priv);
+ qnum = priv->hwq_map[WME_AC_BE];
+ ath9k_hw_init_btcoex_hw(priv->ah, qnum);
+ break;
+ default:
+ WARN_ON(1);
+ break;
+ }
+}
+
+static int ath9k_init_priv(struct ath9k_htc_priv *priv,
+ u16 devid, char *product)
{
struct ath_hw *ah = NULL;
struct ath_common *common;
@@ -672,6 +692,11 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, u16 devid)
ath9k_init_channels_rates(priv);
ath9k_init_misc(priv);
+ if (product && strncmp(product, ATH_HTC_BTCOEX_PRODUCT_ID, 5) == 0) {
+ ah->btcoex_hw.scheme = ATH_BTCOEX_CFG_3WIRE;
+ ath9k_init_btcoex(priv);
+ }
+
return 0;
err_queues:
@@ -715,18 +740,18 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
hw->extra_tx_headroom = sizeof(struct tx_frame_hdr) +
sizeof(struct htc_frame_hdr) + 4;
- if (test_bit(ATH9K_MODE_11G, priv->ah->caps.wireless_modes))
+ if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
&priv->sbands[IEEE80211_BAND_2GHZ];
- if (test_bit(ATH9K_MODE_11A, priv->ah->caps.wireless_modes))
+ if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
&priv->sbands[IEEE80211_BAND_5GHZ];
if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
- if (test_bit(ATH9K_MODE_11G, priv->ah->caps.wireless_modes))
+ if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
setup_ht_cap(priv,
&priv->sbands[IEEE80211_BAND_2GHZ].ht_cap);
- if (test_bit(ATH9K_MODE_11A, priv->ah->caps.wireless_modes))
+ if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
setup_ht_cap(priv,
&priv->sbands[IEEE80211_BAND_5GHZ].ht_cap);
}
@@ -734,7 +759,8 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
}
-static int ath9k_init_device(struct ath9k_htc_priv *priv, u16 devid)
+static int ath9k_init_device(struct ath9k_htc_priv *priv,
+ u16 devid, char *product)
{
struct ieee80211_hw *hw = priv->hw;
struct ath_common *common;
@@ -743,7 +769,7 @@ static int ath9k_init_device(struct ath9k_htc_priv *priv, u16 devid)
struct ath_regulatory *reg;
/* Bring up device */
- error = ath9k_init_priv(priv, devid);
+ error = ath9k_init_priv(priv, devid, product);
if (error != 0)
goto err_init;
@@ -801,7 +827,7 @@ err_init:
}
int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev,
- u16 devid)
+ u16 devid, char *product)
{
struct ieee80211_hw *hw;
struct ath9k_htc_priv *priv;
@@ -835,7 +861,7 @@ int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev,
/* The device may have been unplugged earlier. */
priv->op_flags &= ~OP_UNPLUGGED;
- ret = ath9k_init_device(priv, devid);
+ ret = ath9k_init_device(priv, devid, product);
if (ret)
goto err_init;
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index 7d09b4b17bbd..9a3be8da755d 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -137,8 +137,6 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
if (priv->op_flags & OP_FULL_RESET)
fastcc = false;
- /* Fiddle around with fastcc later on, for now just use full reset */
- fastcc = false;
ath9k_htc_ps_wakeup(priv);
htc_stop(priv->htc);
WMI_CMD(WMI_DISABLE_INTR_CMDID);
@@ -146,9 +144,10 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
WMI_CMD(WMI_STOP_RECV_CMDID);
ath_print(common, ATH_DBG_CONFIG,
- "(%u MHz) -> (%u MHz), HT: %d, HT40: %d\n",
+ "(%u MHz) -> (%u MHz), HT: %d, HT40: %d fastcc: %d\n",
priv->ah->curchan->channel,
- channel->center_freq, conf_is_ht(conf), conf_is_ht40(conf));
+ channel->center_freq, conf_is_ht(conf), conf_is_ht40(conf),
+ fastcc);
caldata = &priv->caldata[channel->hw_value];
ret = ath9k_hw_reset(ah, hchan, caldata, fastcc);
@@ -536,7 +535,8 @@ static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf,
static const struct file_operations fops_tgt_stats = {
.read = read_file_tgt_stats,
.open = ath9k_debugfs_open,
- .owner = THIS_MODULE
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
};
static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
@@ -584,7 +584,8 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
static const struct file_operations fops_xmit = {
.read = read_file_xmit,
.open = ath9k_debugfs_open,
- .owner = THIS_MODULE
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
};
static ssize_t read_file_recv(struct file *file, char __user *user_buf,
@@ -613,7 +614,8 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf,
static const struct file_operations fops_recv = {
.read = read_file_recv,
.open = ath9k_debugfs_open,
- .owner = THIS_MODULE
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
};
int ath9k_htc_init_debug(struct ath_hw *ah)
@@ -761,23 +763,12 @@ void ath9k_ani_work(struct work_struct *work)
ath9k_hw_ani_monitor(ah, ah->curchan);
/* Perform calibration if necessary */
- if (longcal || shortcal) {
+ if (longcal || shortcal)
common->ani.caldone =
ath9k_hw_calibrate(ah, ah->curchan,
common->rx_chainmask,
longcal);
- if (longcal)
- common->ani.noise_floor =
- ath9k_hw_getchan_noise(ah, ah->curchan);
-
- ath_print(common, ATH_DBG_ANI,
- " calibrate chan %u/%x nf: %d\n",
- ah->curchan->channel,
- ah->curchan->channelFlags,
- common->ani.noise_floor);
- }
-
ath9k_htc_ps_restore(priv);
}
@@ -1210,6 +1201,12 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)
ieee80211_wake_queues(hw);
+ if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) {
+ ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
+ AR_STOMP_LOW_WLAN_WGHT);
+ ath9k_hw_btcoex_enable(ah);
+ ath_htc_resume_btcoex_work(priv);
+ }
mutex_unlock(&priv->mutex);
return ret;
@@ -1233,7 +1230,6 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
/* Cancel all the running timers/work .. */
cancel_work_sync(&priv->ps_work);
- cancel_delayed_work_sync(&priv->ath9k_ani_work);
cancel_delayed_work_sync(&priv->ath9k_led_blink_work);
ath9k_led_stop_brightness(priv);
@@ -1254,6 +1250,12 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
"Monitor interface removed\n");
}
+ if (ah->btcoex_hw.enabled) {
+ ath9k_hw_btcoex_disable(ah);
+ if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
+ ath_htc_cancel_btcoex_work(priv);
+ }
+
ath9k_hw_phy_disable(ah);
ath9k_hw_disable(ah);
ath9k_hw_configpcipowersave(ah, 1, 1);
@@ -1455,6 +1457,7 @@ out:
FIF_PSPOLL | \
FIF_OTHER_BSS | \
FIF_BCN_PRBRESP_PROMISC | \
+ FIF_PROBE_REQ | \
FIF_FCSFAIL)
static void ath9k_htc_configure_filter(struct ieee80211_hw *hw,
@@ -1580,20 +1583,21 @@ static int ath9k_htc_set_key(struct ieee80211_hw *hw,
switch (cmd) {
case SET_KEY:
- ret = ath9k_cmn_key_config(common, vif, sta, key);
+ ret = ath_key_config(common, vif, sta, key);
if (ret >= 0) {
key->hw_key_idx = ret;
/* push IV and Michael MIC generation to stack */
key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
- if (key->alg == ALG_TKIP)
+ if (key->cipher == WLAN_CIPHER_SUITE_TKIP)
key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
- if (priv->ah->sw_mgmt_crypto && key->alg == ALG_CCMP)
+ if (priv->ah->sw_mgmt_crypto &&
+ key->cipher == WLAN_CIPHER_SUITE_CCMP)
key->flags |= IEEE80211_KEY_FLAG_SW_MGMT;
ret = 0;
}
break;
case DISABLE_KEY:
- ath9k_cmn_key_delete(common, key);
+ ath_key_delete(common, key);
break;
default:
ret = -EINVAL;
@@ -1774,7 +1778,8 @@ static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw)
priv->op_flags |= OP_SCANNING;
spin_unlock_bh(&priv->beacon_lock);
cancel_work_sync(&priv->ps_work);
- cancel_delayed_work_sync(&priv->ath9k_ani_work);
+ if (priv->op_flags & OP_ASSOCIATED)
+ cancel_delayed_work_sync(&priv->ath9k_ani_work);
mutex_unlock(&priv->mutex);
}
@@ -1788,9 +1793,10 @@ static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw)
priv->op_flags &= ~OP_SCANNING;
spin_unlock_bh(&priv->beacon_lock);
priv->op_flags |= OP_FULL_RESET;
- if (priv->op_flags & OP_ASSOCIATED)
+ if (priv->op_flags & OP_ASSOCIATED) {
ath9k_htc_beacon_config(priv, priv->vif);
- ath_start_ani(priv);
+ ath_start_ani(priv);
+ }
ath9k_htc_ps_restore(priv);
mutex_unlock(&priv->mutex);
}
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
index 2a6e45a293a9..3d19b5bc937f 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
@@ -369,8 +369,7 @@ u32 ath9k_htc_calcrxfilter(struct ath9k_htc_priv *priv)
| ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST
| ATH9K_RX_FILTER_MCAST;
- /* If not a STA, enable processing of Probe Requests */
- if (ah->opmode != NL80211_IFTYPE_STATION)
+ if (priv->rxfilter & FIF_PROBE_REQ)
rfilt |= ATH9K_RX_FILTER_PROBEREQ;
/*
@@ -415,8 +414,7 @@ static void ath9k_htc_opmode_init(struct ath9k_htc_priv *priv)
ath9k_hw_setrxfilter(ah, rfilt);
/* configure bssid mask */
- if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK)
- ath_hw_setbssidmask(common);
+ ath_hw_setbssidmask(common);
/* configure operational mode */
ath9k_hw_setopmode(ah);
diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c
index 705c0f342e1c..861ec9269309 100644
--- a/drivers/net/wireless/ath/ath9k/htc_hst.c
+++ b/drivers/net/wireless/ath/ath9k/htc_hst.c
@@ -462,9 +462,9 @@ void ath9k_htc_hw_free(struct htc_target *htc)
}
int ath9k_htc_hw_init(struct htc_target *target,
- struct device *dev, u16 devid)
+ struct device *dev, u16 devid, char *product)
{
- if (ath9k_htc_probe_device(target, dev, devid)) {
+ if (ath9k_htc_probe_device(target, dev, devid, product)) {
printk(KERN_ERR "Failed to initialize the device\n");
return -ENODEV;
}
diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.h b/drivers/net/wireless/ath/ath9k/htc_hst.h
index faba6790328b..07b6509d5896 100644
--- a/drivers/net/wireless/ath/ath9k/htc_hst.h
+++ b/drivers/net/wireless/ath/ath9k/htc_hst.h
@@ -239,7 +239,7 @@ struct htc_target *ath9k_htc_hw_alloc(void *hif_handle,
struct device *dev);
void ath9k_htc_hw_free(struct htc_target *htc);
int ath9k_htc_hw_init(struct htc_target *target,
- struct device *dev, u16 devid);
+ struct device *dev, u16 devid, char *product);
void ath9k_htc_hw_deinit(struct htc_target *target, bool hot_unplug);
#endif /* HTC_HST_H */
diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h
index ffecbadaea4a..0a4ad348b699 100644
--- a/drivers/net/wireless/ath/ath9k/hw-ops.h
+++ b/drivers/net/wireless/ath/ath9k/hw-ops.h
@@ -128,17 +128,6 @@ static inline void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, void *ds,
ath9k_hw_ops(ah)->set11n_virtualmorefrag(ah, ds, vmf);
}
-static inline void ath9k_hw_procmibevent(struct ath_hw *ah)
-{
- ath9k_hw_ops(ah)->ani_proc_mib_event(ah);
-}
-
-static inline void ath9k_hw_ani_monitor(struct ath_hw *ah,
- struct ath9k_channel *chan)
-{
- ath9k_hw_ops(ah)->ani_monitor(ah, chan);
-}
-
/* Private hardware call ops */
/* PHY ops */
@@ -276,15 +265,4 @@ static inline void ath9k_hw_setup_calibration(struct ath_hw *ah,
ath9k_hw_private_ops(ah)->setup_calibration(ah, currCal);
}
-static inline bool ath9k_hw_iscal_supported(struct ath_hw *ah,
- enum ath9k_cal_types calType)
-{
- return ath9k_hw_private_ops(ah)->iscal_supported(ah, calType);
-}
-
-static inline void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning)
-{
- ath9k_hw_private_ops(ah)->ani_reset(ah, is_scanning);
-}
-
#endif /* ATH9K_HW_OPS_H */
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 3384ca164562..cc13ee117823 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -88,29 +88,32 @@ static void ath9k_hw_ani_cache_ini_regs(struct ath_hw *ah)
/* Helper Functions */
/********************/
-static u32 ath9k_hw_mac_clks(struct ath_hw *ah, u32 usecs)
+static void ath9k_hw_set_clockrate(struct ath_hw *ah)
{
struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
+ struct ath_common *common = ath9k_hw_common(ah);
+ unsigned int clockrate;
if (!ah->curchan) /* should really check for CCK instead */
- return usecs *ATH9K_CLOCK_RATE_CCK;
- if (conf->channel->band == IEEE80211_BAND_2GHZ)
- return usecs *ATH9K_CLOCK_RATE_2GHZ_OFDM;
-
- if (ah->caps.hw_caps & ATH9K_HW_CAP_FASTCLOCK)
- return usecs * ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM;
+ clockrate = ATH9K_CLOCK_RATE_CCK;
+ else if (conf->channel->band == IEEE80211_BAND_2GHZ)
+ clockrate = ATH9K_CLOCK_RATE_2GHZ_OFDM;
+ else if (ah->caps.hw_caps & ATH9K_HW_CAP_FASTCLOCK)
+ clockrate = ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM;
else
- return usecs * ATH9K_CLOCK_RATE_5GHZ_OFDM;
+ clockrate = ATH9K_CLOCK_RATE_5GHZ_OFDM;
+
+ if (conf_is_ht40(conf))
+ clockrate *= 2;
+
+ common->clockrate = clockrate;
}
static u32 ath9k_hw_mac_to_clks(struct ath_hw *ah, u32 usecs)
{
- struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
+ struct ath_common *common = ath9k_hw_common(ah);
- if (conf_is_ht40(conf))
- return ath9k_hw_mac_clks(ah, usecs) * 2;
- else
- return ath9k_hw_mac_clks(ah, usecs);
+ return usecs * common->clockrate;
}
bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout)
@@ -299,7 +302,6 @@ static void ath9k_hw_disablepcie(struct ath_hw *ah)
REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
}
/* This should work for all families including legacy */
@@ -371,10 +373,6 @@ static void ath9k_hw_init_config(struct ath_hw *ah)
ah->config.pcie_clock_req = 0;
ah->config.pcie_waen = 0;
ah->config.analog_shiftreg = 1;
- ah->config.ofdm_trig_low = 200;
- ah->config.ofdm_trig_high = 500;
- ah->config.cck_trig_high = 200;
- ah->config.cck_trig_low = 100;
ah->config.enable_ani = true;
for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
@@ -565,7 +563,7 @@ static int __ath9k_hw_init(struct ath_hw *ah)
ath9k_hw_init_cal_settings(ah);
ah->ani_function = ATH9K_ANI_ALL;
- if (AR_SREV_9280_10_OR_LATER(ah) && !AR_SREV_9300_20_OR_LATER(ah))
+ if (AR_SREV_9280_20_OR_LATER(ah) && !AR_SREV_9300_20_OR_LATER(ah))
ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL;
if (!AR_SREV_9300_20_OR_LATER(ah))
ah->ani_function &= ~ATH9K_ANI_MRC_CCK;
@@ -676,7 +674,6 @@ static void ath9k_hw_init_qos(struct ath_hw *ah)
REG_WRITE(ah, AR_TXOP_12_15, 0xFFFFFFFF);
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
}
static void ath9k_hw_init_pll(struct ath_hw *ah,
@@ -741,7 +738,6 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah,
}
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
if (AR_SREV_9300_20_OR_LATER(ah)) {
REG_WRITE(ah, AR_INTR_PRIO_ASYNC_ENABLE, 0);
@@ -885,7 +881,6 @@ static inline void ath9k_hw_set_dma(struct ath_hw *ah)
REG_WRITE(ah, AR_TXCFG, regval | AR_TXCFG_DMASZ_128B);
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
/*
* Restore TX Trigger Level to its pre-reset value.
@@ -933,7 +928,6 @@ static inline void ath9k_hw_set_dma(struct ath_hw *ah)
}
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
if (AR_SREV_9300_20_OR_LATER(ah))
ath9k_hw_reset_txstatus_ring(ah);
@@ -1031,7 +1025,6 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)
REG_WRITE(ah, AR_RTC_RC, rst_flags);
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
udelay(50);
@@ -1070,7 +1063,6 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah)
udelay(2);
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
if (!AR_SREV_9300_20_OR_LATER(ah))
udelay(2);
@@ -1167,6 +1159,7 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
"Failed to set channel\n");
return false;
}
+ ath9k_hw_set_clockrate(ah);
ah->eep_ops->set_txpower(ah, chan,
ath9k_regd_get_ctl(regulatory, chan),
@@ -1190,7 +1183,7 @@ bool ath9k_hw_check_alive(struct ath_hw *ah)
int count = 50;
u32 reg;
- if (AR_SREV_9285_10_OR_LATER(ah))
+ if (AR_SREV_9285_12_OR_LATER(ah))
return true;
do {
@@ -1239,7 +1232,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
return -EIO;
- if (curchan && !ah->chip_fullsleep && ah->caldata)
+ if (curchan && !ah->chip_fullsleep)
ath9k_hw_getnf(ah, curchan);
ah->caldata = caldata;
@@ -1258,11 +1251,13 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
(chan->channel != ah->curchan->channel) &&
((chan->channelFlags & CHANNEL_ALL) ==
(ah->curchan->channelFlags & CHANNEL_ALL)) &&
- !AR_SREV_9280(ah)) {
+ (!AR_SREV_9280(ah) || AR_DEVID_7010(ah))) {
if (ath9k_hw_channel_change(ah, chan)) {
ath9k_hw_loadnf(ah, ah->curchan);
ath9k_hw_start_nfcal(ah, true);
+ if (AR_SREV_9271(ah))
+ ar9002_hw_load_ani_reg(ah, chan);
return 0;
}
}
@@ -1310,7 +1305,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
if (tsf)
ath9k_hw_settsf64(ah, tsf);
- if (AR_SREV_9280_10_OR_LATER(ah))
+ if (AR_SREV_9280_20_OR_LATER(ah))
REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE);
if (!AR_SREV_9300_20_OR_LATER(ah))
@@ -1372,19 +1367,19 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR);
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
r = ath9k_hw_rf_set_freq(ah, chan);
if (r)
return r;
+ ath9k_hw_set_clockrate(ah);
+
ENABLE_REGWRITE_BUFFER(ah);
for (i = 0; i < AR_NUM_DCU; i++)
REG_WRITE(ah, AR_DQCUMASK(i), 1 << i);
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
ah->intr_txqs = 0;
for (i = 0; i < ah->caps.total_queues; i++)
@@ -1432,7 +1427,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
REG_WRITE(ah, AR_CFG_LED, saveLedState | AR_CFG_SCLK_32KHZ);
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
/*
* For big endian systems turn on swapping for descriptors
@@ -1474,283 +1468,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
}
EXPORT_SYMBOL(ath9k_hw_reset);
-/************************/
-/* Key Cache Management */
-/************************/
-
-bool ath9k_hw_keyreset(struct ath_hw *ah, u16 entry)
-{
- u32 keyType;
-
- if (entry >= ah->caps.keycache_size) {
- ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL,
- "keychache entry %u out of range\n", entry);
- return false;
- }
-
- keyType = REG_READ(ah, AR_KEYTABLE_TYPE(entry));
-
- REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0);
- REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0);
- REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0);
- REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0);
- REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0);
- REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), AR_KEYTABLE_TYPE_CLR);
- REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0);
- REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0);
-
- if (keyType == AR_KEYTABLE_TYPE_TKIP && ATH9K_IS_MIC_ENABLED(ah)) {
- u16 micentry = entry + 64;
-
- REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), 0);
- REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0);
- REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), 0);
- REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0);
-
- }
-
- return true;
-}
-EXPORT_SYMBOL(ath9k_hw_keyreset);
-
-static bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac)
-{
- u32 macHi, macLo;
- u32 unicast_flag = AR_KEYTABLE_VALID;
-
- if (entry >= ah->caps.keycache_size) {
- ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL,
- "keychache entry %u out of range\n", entry);
- return false;
- }
-
- if (mac != NULL) {
- /*
- * AR_KEYTABLE_VALID indicates that the address is a unicast
- * address, which must match the transmitter address for
- * decrypting frames.
- * Not setting this bit allows the hardware to use the key
- * for multicast frame decryption.
- */
- if (mac[0] & 0x01)
- unicast_flag = 0;
-
- macHi = (mac[5] << 8) | mac[4];
- macLo = (mac[3] << 24) |
- (mac[2] << 16) |
- (mac[1] << 8) |
- mac[0];
- macLo >>= 1;
- macLo |= (macHi & 1) << 31;
- macHi >>= 1;
- } else {
- macLo = macHi = 0;
- }
- REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo);
- REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | unicast_flag);
-
- return true;
-}
-
-bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry,
- const struct ath9k_keyval *k,
- const u8 *mac)
-{
- const struct ath9k_hw_capabilities *pCap = &ah->caps;
- struct ath_common *common = ath9k_hw_common(ah);
- u32 key0, key1, key2, key3, key4;
- u32 keyType;
-
- if (entry >= pCap->keycache_size) {
- ath_print(common, ATH_DBG_FATAL,
- "keycache entry %u out of range\n", entry);
- return false;
- }
-
- switch (k->kv_type) {
- case ATH9K_CIPHER_AES_OCB:
- keyType = AR_KEYTABLE_TYPE_AES;
- break;
- case ATH9K_CIPHER_AES_CCM:
- if (!(pCap->hw_caps & ATH9K_HW_CAP_CIPHER_AESCCM)) {
- ath_print(common, ATH_DBG_ANY,
- "AES-CCM not supported by mac rev 0x%x\n",
- ah->hw_version.macRev);
- return false;
- }
- keyType = AR_KEYTABLE_TYPE_CCM;
- break;
- case ATH9K_CIPHER_TKIP:
- keyType = AR_KEYTABLE_TYPE_TKIP;
- if (ATH9K_IS_MIC_ENABLED(ah)
- && entry + 64 >= pCap->keycache_size) {
- ath_print(common, ATH_DBG_ANY,
- "entry %u inappropriate for TKIP\n", entry);
- return false;
- }
- break;
- case ATH9K_CIPHER_WEP:
- if (k->kv_len < WLAN_KEY_LEN_WEP40) {
- ath_print(common, ATH_DBG_ANY,
- "WEP key length %u too small\n", k->kv_len);
- return false;
- }
- if (k->kv_len <= WLAN_KEY_LEN_WEP40)
- keyType = AR_KEYTABLE_TYPE_40;
- else if (k->kv_len <= WLAN_KEY_LEN_WEP104)
- keyType = AR_KEYTABLE_TYPE_104;
- else
- keyType = AR_KEYTABLE_TYPE_128;
- break;
- case ATH9K_CIPHER_CLR:
- keyType = AR_KEYTABLE_TYPE_CLR;
- break;
- default:
- ath_print(common, ATH_DBG_FATAL,
- "cipher %u not supported\n", k->kv_type);
- return false;
- }
-
- key0 = get_unaligned_le32(k->kv_val + 0);
- key1 = get_unaligned_le16(k->kv_val + 4);
- key2 = get_unaligned_le32(k->kv_val + 6);
- key3 = get_unaligned_le16(k->kv_val + 10);
- key4 = get_unaligned_le32(k->kv_val + 12);
- if (k->kv_len <= WLAN_KEY_LEN_WEP104)
- key4 &= 0xff;
-
- /*
- * Note: Key cache registers access special memory area that requires
- * two 32-bit writes to actually update the values in the internal
- * memory. Consequently, the exact order and pairs used here must be
- * maintained.
- */
-
- if (keyType == AR_KEYTABLE_TYPE_TKIP && ATH9K_IS_MIC_ENABLED(ah)) {
- u16 micentry = entry + 64;
-
- /*
- * Write inverted key[47:0] first to avoid Michael MIC errors
- * on frames that could be sent or received at the same time.
- * The correct key will be written in the end once everything
- * else is ready.
- */
- REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), ~key0);
- REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), ~key1);
-
- /* Write key[95:48] */
- REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
- REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
-
- /* Write key[127:96] and key type */
- REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
- REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType);
-
- /* Write MAC address for the entry */
- (void) ath9k_hw_keysetmac(ah, entry, mac);
-
- if (ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) {
- /*
- * TKIP uses two key cache entries:
- * Michael MIC TX/RX keys in the same key cache entry
- * (idx = main index + 64):
- * key0 [31:0] = RX key [31:0]
- * key1 [15:0] = TX key [31:16]
- * key1 [31:16] = reserved
- * key2 [31:0] = RX key [63:32]
- * key3 [15:0] = TX key [15:0]
- * key3 [31:16] = reserved
- * key4 [31:0] = TX key [63:32]
- */
- u32 mic0, mic1, mic2, mic3, mic4;
-
- mic0 = get_unaligned_le32(k->kv_mic + 0);
- mic2 = get_unaligned_le32(k->kv_mic + 4);
- mic1 = get_unaligned_le16(k->kv_txmic + 2) & 0xffff;
- mic3 = get_unaligned_le16(k->kv_txmic + 0) & 0xffff;
- mic4 = get_unaligned_le32(k->kv_txmic + 4);
-
- /* Write RX[31:0] and TX[31:16] */
- REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0);
- REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), mic1);
-
- /* Write RX[63:32] and TX[15:0] */
- REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2);
- REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), mic3);
-
- /* Write TX[63:32] and keyType(reserved) */
- REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), mic4);
- REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry),
- AR_KEYTABLE_TYPE_CLR);
-
- } else {
- /*
- * TKIP uses four key cache entries (two for group
- * keys):
- * Michael MIC TX/RX keys are in different key cache
- * entries (idx = main index + 64 for TX and
- * main index + 32 + 96 for RX):
- * key0 [31:0] = TX/RX MIC key [31:0]
- * key1 [31:0] = reserved
- * key2 [31:0] = TX/RX MIC key [63:32]
- * key3 [31:0] = reserved
- * key4 [31:0] = reserved
- *
- * Upper layer code will call this function separately
- * for TX and RX keys when these registers offsets are
- * used.
- */
- u32 mic0, mic2;
-
- mic0 = get_unaligned_le32(k->kv_mic + 0);
- mic2 = get_unaligned_le32(k->kv_mic + 4);
-
- /* Write MIC key[31:0] */
- REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0);
- REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0);
-
- /* Write MIC key[63:32] */
- REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2);
- REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0);
-
- /* Write TX[63:32] and keyType(reserved) */
- REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), 0);
- REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry),
- AR_KEYTABLE_TYPE_CLR);
- }
-
- /* MAC address registers are reserved for the MIC entry */
- REG_WRITE(ah, AR_KEYTABLE_MAC0(micentry), 0);
- REG_WRITE(ah, AR_KEYTABLE_MAC1(micentry), 0);
-
- /*
- * Write the correct (un-inverted) key[47:0] last to enable
- * TKIP now that all other registers are set with correct
- * values.
- */
- REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
- REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
- } else {
- /* Write key[47:0] */
- REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
- REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
-
- /* Write key[95:48] */
- REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
- REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
-
- /* Write key[127:96] and key type */
- REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
- REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType);
-
- /* Write MAC address for the entry */
- (void) ath9k_hw_keysetmac(ah, entry, mac);
- }
-
- return true;
-}
-EXPORT_SYMBOL(ath9k_hw_set_keycache_entry);
-
/******************************/
/* Power Management (Chipset) */
/******************************/
@@ -1959,7 +1676,6 @@ void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period)
REG_WRITE(ah, AR_NDP_PERIOD, TU_TO_USEC(beacon_period));
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
beacon_period &= ~ATH9K_BEACON_ENA;
if (beacon_period & ATH9K_BEACON_RESET_TSF) {
@@ -1987,7 +1703,6 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
TU_TO_USEC(bs->bs_intval & ATH9K_BEACON_PERIOD));
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
REG_RMW_FIELD(ah, AR_RSSI_THR,
AR_RSSI_THR_BM_THR, bs->bs_bmissthreshold);
@@ -2033,7 +1748,6 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
REG_WRITE(ah, AR_DTIM_PERIOD, TU_TO_USEC(dtimperiod));
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
REG_SET_BIT(ah, AR_TIMER_MODE,
AR_TBTT_TIMER_EN | AR_TIM_TIMER_EN |
@@ -2056,12 +1770,13 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
u16 capField = 0, eeval;
+ u8 ant_div_ctl1;
eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_0);
regulatory->current_rd = eeval;
eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_1);
- if (AR_SREV_9285_10_OR_LATER(ah))
+ if (AR_SREV_9285_12_OR_LATER(ah))
eeval |= AR9285_RDEXT_DEFAULT;
regulatory->current_rd_ext = eeval;
@@ -2085,37 +1800,11 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
return -EINVAL;
}
- bitmap_zero(pCap->wireless_modes, ATH9K_MODE_MAX);
+ if (eeval & AR5416_OPFLAGS_11A)
+ pCap->hw_caps |= ATH9K_HW_CAP_5GHZ;
- if (eeval & AR5416_OPFLAGS_11A) {
- set_bit(ATH9K_MODE_11A, pCap->wireless_modes);
- if (ah->config.ht_enable) {
- if (!(eeval & AR5416_OPFLAGS_N_5G_HT20))
- set_bit(ATH9K_MODE_11NA_HT20,
- pCap->wireless_modes);
- if (!(eeval & AR5416_OPFLAGS_N_5G_HT40)) {
- set_bit(ATH9K_MODE_11NA_HT40PLUS,
- pCap->wireless_modes);
- set_bit(ATH9K_MODE_11NA_HT40MINUS,
- pCap->wireless_modes);
- }
- }
- }
-
- if (eeval & AR5416_OPFLAGS_11G) {
- set_bit(ATH9K_MODE_11G, pCap->wireless_modes);
- if (ah->config.ht_enable) {
- if (!(eeval & AR5416_OPFLAGS_N_2G_HT20))
- set_bit(ATH9K_MODE_11NG_HT20,
- pCap->wireless_modes);
- if (!(eeval & AR5416_OPFLAGS_N_2G_HT40)) {
- set_bit(ATH9K_MODE_11NG_HT40PLUS,
- pCap->wireless_modes);
- set_bit(ATH9K_MODE_11NG_HT40MINUS,
- pCap->wireless_modes);
- }
- }
- }
+ if (eeval & AR5416_OPFLAGS_11G)
+ pCap->hw_caps |= ATH9K_HW_CAP_2GHZ;
pCap->tx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_TX_MASK);
/*
@@ -2131,8 +1820,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
/* Use rx_chainmask from EEPROM. */
pCap->rx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_RX_MASK);
- if (!(AR_SREV_9280(ah) && (ah->hw_version.macRev == 0)))
- ah->misc_mode |= AR_PCU_MIC_NEW_LOC_ENA;
+ ah->misc_mode |= AR_PCU_MIC_NEW_LOC_ENA;
pCap->low_2ghz_chan = 2312;
pCap->high_2ghz_chan = 2732;
@@ -2140,24 +1828,13 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
pCap->low_5ghz_chan = 4920;
pCap->high_5ghz_chan = 6100;
- pCap->hw_caps &= ~ATH9K_HW_CAP_CIPHER_CKIP;
- pCap->hw_caps |= ATH9K_HW_CAP_CIPHER_TKIP;
- pCap->hw_caps |= ATH9K_HW_CAP_CIPHER_AESCCM;
-
- pCap->hw_caps &= ~ATH9K_HW_CAP_MIC_CKIP;
- pCap->hw_caps |= ATH9K_HW_CAP_MIC_TKIP;
- pCap->hw_caps |= ATH9K_HW_CAP_MIC_AESCCM;
+ common->crypt_caps |= ATH_CRYPT_CAP_CIPHER_AESCCM;
if (ah->config.ht_enable)
pCap->hw_caps |= ATH9K_HW_CAP_HT;
else
pCap->hw_caps &= ~ATH9K_HW_CAP_HT;
- pCap->hw_caps |= ATH9K_HW_CAP_GTT;
- pCap->hw_caps |= ATH9K_HW_CAP_VEOL;
- pCap->hw_caps |= ATH9K_HW_CAP_BSSIDMASK;
- pCap->hw_caps &= ~ATH9K_HW_CAP_MCAST_KEYSEARCH;
-
if (capField & AR_EEPROM_EEPCAP_MAXQCU)
pCap->total_queues =
MS(capField, AR_EEPROM_EEPCAP_MAXQCU);
@@ -2170,8 +1847,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
else
pCap->keycache_size = AR_KEYTABLE_SIZE;
- pCap->hw_caps |= ATH9K_HW_CAP_FASTCC;
-
if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD >> 1;
else
@@ -2181,9 +1856,9 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
pCap->num_gpio_pins = AR9271_NUM_GPIO;
else if (AR_DEVID_7010(ah))
pCap->num_gpio_pins = AR7010_NUM_GPIO;
- else if (AR_SREV_9285_10_OR_LATER(ah))
+ else if (AR_SREV_9285_12_OR_LATER(ah))
pCap->num_gpio_pins = AR9285_NUM_GPIO;
- else if (AR_SREV_9280_10_OR_LATER(ah))
+ else if (AR_SREV_9280_20_OR_LATER(ah))
pCap->num_gpio_pins = AR928X_NUM_GPIO;
else
pCap->num_gpio_pins = AR_NUM_GPIO;
@@ -2240,7 +1915,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
pCap->num_antcfg_2ghz =
ah->eep_ops->get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_2GHZ);
- if (AR_SREV_9280_10_OR_LATER(ah) &&
+ if (AR_SREV_9280_20_OR_LATER(ah) &&
ath9k_hw_btcoex_supported(ah)) {
btcoex_hw->btactive_gpio = ATH_BTACTIVE_GPIO;
btcoex_hw->wlanactive_gpio = ATH_WLANACTIVE_GPIO;
@@ -2277,9 +1952,17 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
if (AR_SREV_9300_20_OR_LATER(ah))
pCap->hw_caps |= ATH9K_HW_CAP_RAC_SUPPORTED;
- if (AR_SREV_9287_10_OR_LATER(ah) || AR_SREV_9271(ah))
+ if (AR_SREV_9287_11_OR_LATER(ah) || AR_SREV_9271(ah))
pCap->hw_caps |= ATH9K_HW_CAP_SGI_20;
+ if (AR_SREV_9285(ah))
+ if (ah->eep_ops->get_eeprom(ah, EEP_MODAL_VER) >= 3) {
+ ant_div_ctl1 =
+ ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1);
+ if ((ant_div_ctl1 & 0x1) && ((ant_div_ctl1 >> 3) & 0x1))
+ pCap->hw_caps |= ATH9K_HW_CAP_ANT_DIV_COMB;
+ }
+
return 0;
}
@@ -2353,11 +2036,11 @@ u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio)
return MS_REG_READ(AR9300, gpio) != 0;
else if (AR_SREV_9271(ah))
return MS_REG_READ(AR9271, gpio) != 0;
- else if (AR_SREV_9287_10_OR_LATER(ah))
+ else if (AR_SREV_9287_11_OR_LATER(ah))
return MS_REG_READ(AR9287, gpio) != 0;
- else if (AR_SREV_9285_10_OR_LATER(ah))
+ else if (AR_SREV_9285_12_OR_LATER(ah))
return MS_REG_READ(AR9285, gpio) != 0;
- else if (AR_SREV_9280_10_OR_LATER(ah))
+ else if (AR_SREV_9280_20_OR_LATER(ah))
return MS_REG_READ(AR928X, gpio) != 0;
else
return MS_REG_READ(AR, gpio) != 0;
@@ -2456,7 +2139,6 @@ void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits)
REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_ZLFDMA);
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
}
EXPORT_SYMBOL(ath9k_hw_setrxfilter);
@@ -2854,7 +2536,7 @@ void ath9k_hw_name(struct ath_hw *ah, char *hw_name, size_t len)
int used;
/* chipsets >= AR9280 are single-chip */
- if (AR_SREV_9280_10_OR_LATER(ah)) {
+ if (AR_SREV_9280_20_OR_LATER(ah)) {
used = snprintf(hw_name, len,
"Atheros AR%s Rev:%x",
ath9k_hw_mac_bb_name(ah->hw_version.macVersion),
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 399f7c1283cd..d032939768b0 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -61,6 +61,8 @@
#define ATH9K_RSSI_BAD -128
+#define ATH9K_NUM_CHANNELS 38
+
/* Register read/write primitives */
#define REG_WRITE(_ah, _reg, _val) \
ath9k_hw_common(_ah)->ops->write((_ah), (_val), (_reg))
@@ -70,19 +72,13 @@
#define ENABLE_REGWRITE_BUFFER(_ah) \
do { \
- if (AR_SREV_9271(_ah)) \
+ if (ath9k_hw_common(_ah)->ops->enable_write_buffer) \
ath9k_hw_common(_ah)->ops->enable_write_buffer((_ah)); \
} while (0)
-#define DISABLE_REGWRITE_BUFFER(_ah) \
- do { \
- if (AR_SREV_9271(_ah)) \
- ath9k_hw_common(_ah)->ops->disable_write_buffer((_ah)); \
- } while (0)
-
#define REGWRITE_BUFFER_FLUSH(_ah) \
do { \
- if (AR_SREV_9271(_ah)) \
+ if (ath9k_hw_common(_ah)->ops->write_flush) \
ath9k_hw_common(_ah)->ops->write_flush((_ah)); \
} while (0)
@@ -168,47 +164,26 @@ enum ath_ini_subsys {
ATH_INI_NUM_SPLIT,
};
-enum wireless_mode {
- ATH9K_MODE_11A = 0,
- ATH9K_MODE_11G,
- ATH9K_MODE_11NA_HT20,
- ATH9K_MODE_11NG_HT20,
- ATH9K_MODE_11NA_HT40PLUS,
- ATH9K_MODE_11NA_HT40MINUS,
- ATH9K_MODE_11NG_HT40PLUS,
- ATH9K_MODE_11NG_HT40MINUS,
- ATH9K_MODE_MAX,
-};
-
enum ath9k_hw_caps {
- ATH9K_HW_CAP_MIC_AESCCM = BIT(0),
- ATH9K_HW_CAP_MIC_CKIP = BIT(1),
- ATH9K_HW_CAP_MIC_TKIP = BIT(2),
- ATH9K_HW_CAP_CIPHER_AESCCM = BIT(3),
- ATH9K_HW_CAP_CIPHER_CKIP = BIT(4),
- ATH9K_HW_CAP_CIPHER_TKIP = BIT(5),
- ATH9K_HW_CAP_VEOL = BIT(6),
- ATH9K_HW_CAP_BSSIDMASK = BIT(7),
- ATH9K_HW_CAP_MCAST_KEYSEARCH = BIT(8),
- ATH9K_HW_CAP_HT = BIT(9),
- ATH9K_HW_CAP_GTT = BIT(10),
- ATH9K_HW_CAP_FASTCC = BIT(11),
- ATH9K_HW_CAP_RFSILENT = BIT(12),
- ATH9K_HW_CAP_CST = BIT(13),
- ATH9K_HW_CAP_ENHANCEDPM = BIT(14),
- ATH9K_HW_CAP_AUTOSLEEP = BIT(15),
- ATH9K_HW_CAP_4KB_SPLITTRANS = BIT(16),
- ATH9K_HW_CAP_EDMA = BIT(17),
- ATH9K_HW_CAP_RAC_SUPPORTED = BIT(18),
- ATH9K_HW_CAP_LDPC = BIT(19),
- ATH9K_HW_CAP_FASTCLOCK = BIT(20),
- ATH9K_HW_CAP_SGI_20 = BIT(21),
- ATH9K_HW_CAP_PAPRD = BIT(22),
+ ATH9K_HW_CAP_HT = BIT(0),
+ ATH9K_HW_CAP_RFSILENT = BIT(1),
+ ATH9K_HW_CAP_CST = BIT(2),
+ ATH9K_HW_CAP_ENHANCEDPM = BIT(3),
+ ATH9K_HW_CAP_AUTOSLEEP = BIT(4),
+ ATH9K_HW_CAP_4KB_SPLITTRANS = BIT(5),
+ ATH9K_HW_CAP_EDMA = BIT(6),
+ ATH9K_HW_CAP_RAC_SUPPORTED = BIT(7),
+ ATH9K_HW_CAP_LDPC = BIT(8),
+ ATH9K_HW_CAP_FASTCLOCK = BIT(9),
+ ATH9K_HW_CAP_SGI_20 = BIT(10),
+ ATH9K_HW_CAP_PAPRD = BIT(11),
+ ATH9K_HW_CAP_ANT_DIV_COMB = BIT(12),
+ ATH9K_HW_CAP_2GHZ = BIT(13),
+ ATH9K_HW_CAP_5GHZ = BIT(14),
};
struct ath9k_hw_capabilities {
u32 hw_caps; /* ATH9K_HW_CAP_* from ath9k_hw_caps */
- DECLARE_BITMAP(wireless_modes, ATH9K_MODE_MAX); /* ATH9K_MODE_* */
u16 total_queues;
u16 keycache_size;
u16 low_5ghz_chan, high_5ghz_chan;
@@ -352,9 +327,9 @@ struct ath9k_hw_cal_data {
int32_t CalValid;
int8_t iCoff;
int8_t qCoff;
- int16_t rawNoiseFloor;
bool paprd_done;
bool nfcal_pending;
+ bool nfcal_interference;
u16 small_signal_gain[AR9300_MAX_CHAINS];
u32 pa_table[AR9300_MAX_CHAINS][PAPRD_TABLE_SZ];
struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS];
@@ -362,9 +337,11 @@ struct ath9k_hw_cal_data {
struct ath9k_channel {
struct ieee80211_channel *chan;
+ struct ar5416AniState ani;
u16 channel;
u32 channelFlags;
u32 chanmode;
+ s16 noisefloor;
};
#define IS_CHAN_G(_c) ((((_c)->channelFlags & (CHANNEL_G)) == CHANNEL_G) || \
@@ -494,6 +471,12 @@ struct ath_gen_timer_table {
} timer_mask;
};
+struct ath_hw_antcomb_conf {
+ u8 main_lna_conf;
+ u8 alt_lna_conf;
+ u8 fast_div_bias;
+};
+
/**
* struct ath_hw_private_ops - callbacks used internally by hardware code
*
@@ -517,14 +500,6 @@ struct ath_gen_timer_table {
* @setup_calibration: set up calibration
* @iscal_supported: used to query if a type of calibration is supported
*
- * @ani_reset: reset ANI parameters to default values
- * @ani_lower_immunity: lower the noise immunity level. The level controls
- * the power-based packet detection on hardware. If a power jump is
- * detected the adapter takes it as an indication that a packet has
- * arrived. The level ranges from 0-5. Each level corresponds to a
- * few dB more of noise immunity. If you have a strong time-varying
- * interference that is causing false detections (OFDM timing errors or
- * CCK timing errors) the level can be increased.
* @ani_cache_ini_regs: cache the values for ANI from the initial
* register settings through the register initialization.
*/
@@ -538,8 +513,6 @@ struct ath_hw_private_ops {
bool (*macversion_supported)(u32 macversion);
void (*setup_calibration)(struct ath_hw *ah,
struct ath9k_cal_list *currCal);
- bool (*iscal_supported)(struct ath_hw *ah,
- enum ath9k_cal_types calType);
/* PHY ops */
int (*rf_set_freq)(struct ath_hw *ah,
@@ -571,8 +544,6 @@ struct ath_hw_private_ops {
void (*do_getnf)(struct ath_hw *ah, int16_t nfarray[NUM_NF_READINGS]);
/* ANI */
- void (*ani_reset)(struct ath_hw *ah, bool is_scanning);
- void (*ani_lower_immunity)(struct ath_hw *ah);
void (*ani_cache_ini_regs)(struct ath_hw *ah);
};
@@ -584,11 +555,6 @@ struct ath_hw_private_ops {
*
* @config_pci_powersave:
* @calibrate: periodic calibration for NF, ANI, IQ, ADC gain, ADC-DC
- *
- * @ani_proc_mib_event: process MIB events, this would happen upon specific ANI
- * thresholds being reached or having overflowed.
- * @ani_monitor: called periodically by the core driver to collect
- * MIB stats and adjust ANI if specific thresholds have been reached.
*/
struct ath_hw_ops {
void (*config_pci_powersave)(struct ath_hw *ah,
@@ -629,9 +595,6 @@ struct ath_hw_ops {
u32 burstDuration);
void (*set11n_virtualmorefrag)(struct ath_hw *ah, void *ds,
u32 vmf);
-
- void (*ani_proc_mib_event)(struct ath_hw *ah);
- void (*ani_monitor)(struct ath_hw *ah, struct ath9k_channel *chan);
};
struct ath_nf_limits {
@@ -646,7 +609,7 @@ struct ath_hw {
struct ath9k_hw_version hw_version;
struct ath9k_ops_config config;
struct ath9k_hw_capabilities caps;
- struct ath9k_channel channels[38];
+ struct ath9k_channel channels[ATH9K_NUM_CHANNELS];
struct ath9k_channel *curchan;
union {
@@ -692,10 +655,9 @@ struct ath_hw {
u32 atim_window;
/* Calibration */
- enum ath9k_cal_types supp_cals;
+ u32 supp_cals;
struct ath9k_cal_list iq_caldata;
struct ath9k_cal_list adcgain_caldata;
- struct ath9k_cal_list adcdc_calinitdata;
struct ath9k_cal_list adcdc_caldata;
struct ath9k_cal_list tempCompCalData;
struct ath9k_cal_list *cal_list;
@@ -764,8 +726,6 @@ struct ath_hw {
/* ANI */
u32 proc_phyerr;
u32 aniperiod;
- struct ar5416AniState *curani;
- struct ar5416AniState ani[255];
int totalSizeDesired[5];
int coarse_high[5];
int coarse_low[5];
@@ -873,12 +833,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
int ath9k_hw_fill_cap_info(struct ath_hw *ah);
u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan);
-/* Key Cache Management */
-bool ath9k_hw_keyreset(struct ath_hw *ah, u16 entry);
-bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry,
- const struct ath9k_keyval *k,
- const u8 *mac);
-
/* GPIO / RFKILL / Antennae */
void ath9k_hw_cfg_gpio_input(struct ath_hw *ah, u32 gpio);
u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio);
@@ -887,6 +841,10 @@ void ath9k_hw_cfg_output(struct ath_hw *ah, u32 gpio,
void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val);
u32 ath9k_hw_getdefantenna(struct ath_hw *ah);
void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna);
+void ath9k_hw_antdiv_comb_conf_get(struct ath_hw *ah,
+ struct ath_hw_antcomb_conf *antconf);
+void ath9k_hw_antdiv_comb_conf_set(struct ath_hw *ah,
+ struct ath_hw_antcomb_conf *antconf);
/* General Operation */
bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout);
@@ -984,6 +942,7 @@ void ar9003_hw_attach_calib_ops(struct ath_hw *ah);
void ar9002_hw_attach_ops(struct ath_hw *ah);
void ar9003_hw_attach_ops(struct ath_hw *ah);
+void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan);
/*
* ANI work can be shared between all families but a next
* generation implementation of ANI will be used only for AR9003 only
@@ -992,8 +951,9 @@ void ar9003_hw_attach_ops(struct ath_hw *ah);
* older families (AR5008, AR9001, AR9002) by using modparam_force_new_ani.
*/
extern int modparam_force_new_ani;
-void ath9k_hw_attach_ani_ops_old(struct ath_hw *ah);
-void ath9k_hw_attach_ani_ops_new(struct ath_hw *ah);
+void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning);
+void ath9k_hw_proc_mib_event(struct ath_hw *ah);
+void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan);
#define ATH_PCIE_CAP_LINK_CTRL 0x70
#define ATH_PCIE_CAP_LINK_L0S 1
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index 243c1775f343..bc6c4df9712c 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -33,7 +33,7 @@ int modparam_nohwcrypt;
module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444);
MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption");
-int led_blink = 1;
+int led_blink;
module_param_named(blink, led_blink, int, 0444);
MODULE_PARM_DESC(blink, "Enable LED blink on activity");
@@ -56,7 +56,7 @@ MODULE_PARM_DESC(blink, "Enable LED blink on activity");
* on 5 MHz steps, we support the channels which we know
* we have calibration data for all cards though to make
* this static */
-static struct ieee80211_channel ath9k_2ghz_chantable[] = {
+static const struct ieee80211_channel ath9k_2ghz_chantable[] = {
CHAN2G(2412, 0), /* Channel 1 */
CHAN2G(2417, 1), /* Channel 2 */
CHAN2G(2422, 2), /* Channel 3 */
@@ -77,7 +77,7 @@ static struct ieee80211_channel ath9k_2ghz_chantable[] = {
* on 5 MHz steps, we support the channels which we know
* we have calibration data for all cards though to make
* this static */
-static struct ieee80211_channel ath9k_5ghz_chantable[] = {
+static const struct ieee80211_channel ath9k_5ghz_chantable[] = {
/* _We_ call this UNII 1 */
CHAN5G(5180, 14), /* Channel 36 */
CHAN5G(5200, 15), /* Channel 40 */
@@ -211,7 +211,7 @@ static void setup_ht_cap(struct ath_softc *sc,
else
max_streams = 2;
- if (AR_SREV_9280_10_OR_LATER(ah)) {
+ if (AR_SREV_9280_20_OR_LATER(ah)) {
if (max_streams >= 2)
ht_info->cap |= IEEE80211_HT_CAP_TX_STBC;
ht_info->cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
@@ -381,7 +381,7 @@ static void ath9k_init_crypto(struct ath_softc *sc)
* reset the contents on initial power up.
*/
for (i = 0; i < common->keymax; i++)
- ath9k_hw_keyreset(sc->sc_ah, (u16) i);
+ ath_hw_keyreset(common, (u16) i);
/*
* Check whether the separate key cache entries
@@ -389,8 +389,8 @@ static void ath9k_init_crypto(struct ath_softc *sc)
* With split mic keys the number of stations is limited
* to 27 otherwise 59.
*/
- if (!(sc->sc_ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA))
- common->splitmic = 1;
+ if (sc->sc_ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA)
+ common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED;
}
static int ath9k_init_btcoex(struct ath_softc *sc)
@@ -477,10 +477,21 @@ err:
return -EIO;
}
-static void ath9k_init_channels_rates(struct ath_softc *sc)
+static int ath9k_init_channels_rates(struct ath_softc *sc)
{
- if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes)) {
- sc->sbands[IEEE80211_BAND_2GHZ].channels = ath9k_2ghz_chantable;
+ void *channels;
+
+ BUILD_BUG_ON(ARRAY_SIZE(ath9k_2ghz_chantable) +
+ ARRAY_SIZE(ath9k_5ghz_chantable) !=
+ ATH9K_NUM_CHANNELS);
+
+ if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) {
+ channels = kmemdup(ath9k_2ghz_chantable,
+ sizeof(ath9k_2ghz_chantable), GFP_KERNEL);
+ if (!channels)
+ return -ENOMEM;
+
+ sc->sbands[IEEE80211_BAND_2GHZ].channels = channels;
sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
sc->sbands[IEEE80211_BAND_2GHZ].n_channels =
ARRAY_SIZE(ath9k_2ghz_chantable);
@@ -489,8 +500,16 @@ static void ath9k_init_channels_rates(struct ath_softc *sc)
ARRAY_SIZE(ath9k_legacy_rates);
}
- if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) {
- sc->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_chantable;
+ if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) {
+ channels = kmemdup(ath9k_5ghz_chantable,
+ sizeof(ath9k_5ghz_chantable), GFP_KERNEL);
+ if (!channels) {
+ if (sc->sbands[IEEE80211_BAND_2GHZ].channels)
+ kfree(sc->sbands[IEEE80211_BAND_2GHZ].channels);
+ return -ENOMEM;
+ }
+
+ sc->sbands[IEEE80211_BAND_5GHZ].channels = channels;
sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ;
sc->sbands[IEEE80211_BAND_5GHZ].n_channels =
ARRAY_SIZE(ath9k_5ghz_chantable);
@@ -499,6 +518,7 @@ static void ath9k_init_channels_rates(struct ath_softc *sc)
sc->sbands[IEEE80211_BAND_5GHZ].n_bitrates =
ARRAY_SIZE(ath9k_legacy_rates) - 4;
}
+ return 0;
}
static void ath9k_init_misc(struct ath_softc *sc)
@@ -506,7 +526,6 @@ static void ath9k_init_misc(struct ath_softc *sc)
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
int i = 0;
- common->ani.noise_floor = ATH_DEFAULT_NOISE_FLOOR;
setup_timer(&common->ani.timer, ath_ani_calibrate, (unsigned long)sc);
sc->config.txpowlimit = ATH_TXPOWER_MAX;
@@ -522,8 +541,7 @@ static void ath9k_init_misc(struct ath_softc *sc)
ath9k_hw_set_diversity(sc->sc_ah, true);
sc->rx.defant = ath9k_hw_getdefantenna(sc->sc_ah);
- if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK)
- memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
+ memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
sc->beacon.slottime = ATH9K_SLOT_TIME_9;
@@ -531,6 +549,9 @@ static void ath9k_init_misc(struct ath_softc *sc)
sc->beacon.bslot[i] = NULL;
sc->beacon.bslot_aphy[i] = NULL;
}
+
+ if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB)
+ sc->ant_comb.count = ATH_ANT_DIV_COMB_INIT_COUNT;
}
static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
@@ -593,8 +614,11 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
if (ret)
goto err_btcoex;
+ ret = ath9k_init_channels_rates(sc);
+ if (ret)
+ goto err_btcoex;
+
ath9k_init_crypto(sc);
- ath9k_init_channels_rates(sc);
ath9k_init_misc(sc);
return 0;
@@ -637,11 +661,13 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
hw->wiphy->interface_modes =
BIT(NL80211_IFTYPE_AP) |
+ BIT(NL80211_IFTYPE_WDS) |
BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_ADHOC) |
BIT(NL80211_IFTYPE_MESH_POINT);
- hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
+ if (AR_SREV_5416(sc->sc_ah))
+ hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
hw->queues = 4;
hw->max_rates = 4;
@@ -651,19 +677,21 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
hw->sta_data_size = sizeof(struct ath_node);
hw->vif_data_size = sizeof(struct ath_vif);
+#ifdef CONFIG_ATH9K_RATE_CONTROL
hw->rate_control_algorithm = "ath9k_rate_control";
+#endif
- if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes))
+ if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
&sc->sbands[IEEE80211_BAND_2GHZ];
- if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes))
+ if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
&sc->sbands[IEEE80211_BAND_5GHZ];
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
- if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes))
+ if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap);
- if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes))
+ if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap);
}
@@ -751,6 +779,12 @@ static void ath9k_deinit_softc(struct ath_softc *sc)
{
int i = 0;
+ if (sc->sbands[IEEE80211_BAND_2GHZ].channels)
+ kfree(sc->sbands[IEEE80211_BAND_2GHZ].channels);
+
+ if (sc->sbands[IEEE80211_BAND_5GHZ].channels)
+ kfree(sc->sbands[IEEE80211_BAND_5GHZ].channels);
+
if ((sc->btcoex.no_stomp_timer) &&
sc->sc_ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
ath_gen_timer_free(sc->sc_ah, sc->btcoex.no_stomp_timer);
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c
index e955bb9d98cb..8c13479b17cd 100644
--- a/drivers/net/wireless/ath/ath9k/mac.c
+++ b/drivers/net/wireless/ath/ath9k/mac.c
@@ -40,7 +40,6 @@ static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah,
REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg);
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
}
u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q)
@@ -492,8 +491,6 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
REG_WRITE(ah, AR_DMISC(q),
AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x2);
- REGWRITE_BUFFER_FLUSH(ah);
-
if (qi->tqi_cbrPeriod) {
REG_WRITE(ah, AR_QCBRCFG(q),
SM(qi->tqi_cbrPeriod, AR_Q_CBRCFG_INTERVAL) |
@@ -509,8 +506,6 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
AR_Q_RDYTIMECFG_EN);
}
- REGWRITE_BUFFER_FLUSH(ah);
-
REG_WRITE(ah, AR_DCHNTIME(q),
SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) |
(qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0));
@@ -530,7 +525,6 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
}
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
if (qi->tqi_qflags & TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) {
REG_WRITE(ah, AR_DMISC(q),
@@ -553,7 +547,6 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
| AR_D_MISC_POST_FR_BKOFF_DIS);
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
/*
* cwmin and cwmax should be 0 for beacon queue
@@ -585,7 +578,6 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
AR_D_MISC_ARB_LOCKOUT_CNTRL_S));
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
break;
case ATH9K_TX_QUEUE_PSPOLL:
@@ -711,8 +703,11 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
rs->rs_phyerr = phyerr;
} else if (ads.ds_rxstatus8 & AR_DecryptCRCErr)
rs->rs_status |= ATH9K_RXERR_DECRYPT;
- else if (ads.ds_rxstatus8 & AR_MichaelErr)
+ else if ((ads.ds_rxstatus8 & AR_MichaelErr) &&
+ rs->rs_keyix != ATH9K_RXKEYIX_INVALID)
rs->rs_status |= ATH9K_RXERR_MIC;
+ else if (ads.ds_rxstatus8 & AR_KeyMiss)
+ rs->rs_status |= ATH9K_RXERR_DECRYPT;
}
return 0;
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h
index 2633896d3998..7c1a34d64f6d 100644
--- a/drivers/net/wireless/ath/ath9k/mac.h
+++ b/drivers/net/wireless/ath/ath9k/mac.h
@@ -660,17 +660,6 @@ struct ath9k_11n_rate_series {
u32 RateFlags;
};
-struct ath9k_keyval {
- u8 kv_type;
- u8 kv_pad;
- u16 kv_len;
- u8 kv_val[16]; /* TK */
- u8 kv_mic[8]; /* Michael MIC key */
- u8 kv_txmic[8]; /* Michael MIC TX key (used only if the hardware
- * supports both MIC keys in the same key cache entry;
- * in that case, kv_mic is the RX key) */
-};
-
enum ath9k_key_type {
ATH9K_KEY_TYPE_CLEAR,
ATH9K_KEY_TYPE_WEP,
@@ -678,16 +667,6 @@ enum ath9k_key_type {
ATH9K_KEY_TYPE_TKIP,
};
-enum ath9k_cipher {
- ATH9K_CIPHER_WEP = 0,
- ATH9K_CIPHER_AES_OCB = 1,
- ATH9K_CIPHER_AES_CCM = 2,
- ATH9K_CIPHER_CKIP = 3,
- ATH9K_CIPHER_TKIP = 4,
- ATH9K_CIPHER_CLR = 5,
- ATH9K_CIPHER_MIC = 127
-};
-
struct ath_hw;
struct ath9k_channel;
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 3caa32316e7b..3ff0e476c2b3 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -18,36 +18,6 @@
#include "ath9k.h"
#include "btcoex.h"
-static void ath_cache_conf_rate(struct ath_softc *sc,
- struct ieee80211_conf *conf)
-{
- switch (conf->channel->band) {
- case IEEE80211_BAND_2GHZ:
- if (conf_is_ht20(conf))
- sc->cur_rate_mode = ATH9K_MODE_11NG_HT20;
- else if (conf_is_ht40_minus(conf))
- sc->cur_rate_mode = ATH9K_MODE_11NG_HT40MINUS;
- else if (conf_is_ht40_plus(conf))
- sc->cur_rate_mode = ATH9K_MODE_11NG_HT40PLUS;
- else
- sc->cur_rate_mode = ATH9K_MODE_11G;
- break;
- case IEEE80211_BAND_5GHZ:
- if (conf_is_ht20(conf))
- sc->cur_rate_mode = ATH9K_MODE_11NA_HT20;
- else if (conf_is_ht40_minus(conf))
- sc->cur_rate_mode = ATH9K_MODE_11NA_HT40MINUS;
- else if (conf_is_ht40_plus(conf))
- sc->cur_rate_mode = ATH9K_MODE_11NA_HT40PLUS;
- else
- sc->cur_rate_mode = ATH9K_MODE_11A;
- break;
- default:
- BUG_ON(1);
- break;
- }
-}
-
static void ath_update_txpow(struct ath_softc *sc)
{
struct ath_hw *ah = sc->sc_ah;
@@ -121,6 +91,7 @@ bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode)
void ath9k_ps_wakeup(struct ath_softc *sc)
{
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
unsigned long flags;
spin_lock_irqsave(&sc->sc_pm_lock, flags);
@@ -129,18 +100,33 @@ void ath9k_ps_wakeup(struct ath_softc *sc)
ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE);
+ /*
+ * While the hardware is asleep, the cycle counters contain no
+ * useful data. Better clear them now so that they don't mess up
+ * survey data results.
+ */
+ spin_lock(&common->cc_lock);
+ ath_hw_cycle_counters_update(common);
+ memset(&common->cc_survey, 0, sizeof(common->cc_survey));
+ spin_unlock(&common->cc_lock);
+
unlock:
spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
}
void ath9k_ps_restore(struct ath_softc *sc)
{
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
unsigned long flags;
spin_lock_irqsave(&sc->sc_pm_lock, flags);
if (--sc->ps_usecount != 0)
goto unlock;
+ spin_lock(&common->cc_lock);
+ ath_hw_cycle_counters_update(common);
+ spin_unlock(&common->cc_lock);
+
if (sc->ps_idle)
ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP);
else if (sc->ps_enabled &&
@@ -175,6 +161,45 @@ static void ath_start_ani(struct ath_common *common)
msecs_to_jiffies((u32)ah->config.ani_poll_interval));
}
+static void ath_update_survey_nf(struct ath_softc *sc, int channel)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath9k_channel *chan = &ah->channels[channel];
+ struct survey_info *survey = &sc->survey[channel];
+
+ if (chan->noisefloor) {
+ survey->filled |= SURVEY_INFO_NOISE_DBM;
+ survey->noise = chan->noisefloor;
+ }
+}
+
+static void ath_update_survey_stats(struct ath_softc *sc)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+ int pos = ah->curchan - &ah->channels[0];
+ struct survey_info *survey = &sc->survey[pos];
+ struct ath_cycle_counters *cc = &common->cc_survey;
+ unsigned int div = common->clockrate * 1000;
+
+ if (ah->power_mode == ATH9K_PM_AWAKE)
+ ath_hw_cycle_counters_update(common);
+
+ if (cc->cycles > 0) {
+ survey->filled |= SURVEY_INFO_CHANNEL_TIME |
+ SURVEY_INFO_CHANNEL_TIME_BUSY |
+ SURVEY_INFO_CHANNEL_TIME_RX |
+ SURVEY_INFO_CHANNEL_TIME_TX;
+ survey->channel_time += cc->cycles / div;
+ survey->channel_time_busy += cc->rx_busy / div;
+ survey->channel_time_rx += cc->rx_frame / div;
+ survey->channel_time_tx += cc->tx_frame / div;
+ }
+ memset(cc, 0, sizeof(*cc));
+
+ ath_update_survey_nf(sc, pos);
+}
+
/*
* Set/change channels. If the channel is really being changed, it's done
* by reseting the chip. To accomplish this we must first cleanup any pending
@@ -226,9 +251,10 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
caldata = &aphy->caldata;
ath_print(common, ATH_DBG_CONFIG,
- "(%u MHz) -> (%u MHz), conf_is_ht40: %d\n",
+ "(%u MHz) -> (%u MHz), conf_is_ht40: %d fastcc: %d\n",
sc->sc_ah->curchan->channel,
- channel->center_freq, conf_is_ht40(conf));
+ channel->center_freq, conf_is_ht40(conf),
+ fastcc);
spin_lock_bh(&sc->sc_resetlock);
@@ -250,14 +276,13 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
goto ps_restore;
}
- ath_cache_conf_rate(sc, &hw->conf);
ath_update_txpow(sc);
ath9k_hw_set_interrupts(ah, ah->imask);
- if (!(sc->sc_flags & (SC_OP_OFFCHANNEL | SC_OP_SCANNING))) {
- ath_start_ani(common);
- ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
+ if (!(sc->sc_flags & (SC_OP_OFFCHANNEL))) {
ath_beacon_config(sc, NULL);
+ ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
+ ath_start_ani(common);
}
ps_restore:
@@ -269,6 +294,7 @@ static void ath_paprd_activate(struct ath_softc *sc)
{
struct ath_hw *ah = sc->sc_ah;
struct ath9k_hw_cal_data *caldata = ah->caldata;
+ struct ath_common *common = ath9k_hw_common(ah);
int chain;
if (!caldata || !caldata->paprd_done)
@@ -277,7 +303,7 @@ static void ath_paprd_activate(struct ath_softc *sc)
ath9k_ps_wakeup(sc);
ar9003_paprd_enable(ah, false);
for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
- if (!(ah->caps.tx_chainmask & BIT(chain)))
+ if (!(common->tx_chainmask & BIT(chain)))
continue;
ar9003_paprd_populate_single_table(ah, caldata, chain);
@@ -299,6 +325,7 @@ void ath_paprd_calibrate(struct work_struct *work)
struct ieee80211_supported_band *sband = &sc->sbands[band];
struct ath_tx_control txctl;
struct ath9k_hw_cal_data *caldata = ah->caldata;
+ struct ath_common *common = ath9k_hw_common(ah);
int qnum, ftype;
int chain_ok = 0;
int chain;
@@ -332,7 +359,7 @@ void ath_paprd_calibrate(struct work_struct *work)
ath9k_ps_wakeup(sc);
ar9003_paprd_init_table(ah);
for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
- if (!(ah->caps.tx_chainmask & BIT(chain)))
+ if (!(common->tx_chainmask & BIT(chain)))
continue;
chain_ok = 0;
@@ -395,7 +422,13 @@ void ath_ani_calibrate(unsigned long data)
bool shortcal = false;
bool aniflag = false;
unsigned int timestamp = jiffies_to_msecs(jiffies);
- u32 cal_interval, short_cal_interval;
+ u32 cal_interval, short_cal_interval, long_cal_interval;
+ unsigned long flags;
+
+ if (ah->caldata && ah->caldata->nfcal_interference)
+ long_cal_interval = ATH_LONG_CALINTERVAL_INT;
+ else
+ long_cal_interval = ATH_LONG_CALINTERVAL;
short_cal_interval = (ah->opmode == NL80211_IFTYPE_AP) ?
ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL;
@@ -407,7 +440,7 @@ void ath_ani_calibrate(unsigned long data)
ath9k_ps_wakeup(sc);
/* Long calibration runs independently of short calibration. */
- if ((timestamp - common->ani.longcal_timer) >= ATH_LONG_CALINTERVAL) {
+ if ((timestamp - common->ani.longcal_timer) >= long_cal_interval) {
longcal = true;
ath_print(common, ATH_DBG_ANI, "longcal @%lu\n", jiffies);
common->ani.longcal_timer = timestamp;
@@ -441,8 +474,12 @@ void ath_ani_calibrate(unsigned long data)
/* Skip all processing if there's nothing to do. */
if (longcal || shortcal || aniflag) {
/* Call ANI routine if necessary */
- if (aniflag)
+ if (aniflag) {
+ spin_lock_irqsave(&common->cc_lock, flags);
ath9k_hw_ani_monitor(ah, ah->curchan);
+ ath_update_survey_stats(sc);
+ spin_unlock_irqrestore(&common->cc_lock, flags);
+ }
/* Perform calibration if necessary */
if (longcal || shortcal) {
@@ -451,16 +488,6 @@ void ath_ani_calibrate(unsigned long data)
ah->curchan,
common->rx_chainmask,
longcal);
-
- if (longcal)
- common->ani.noise_floor = ath9k_hw_getchan_noise(ah,
- ah->curchan);
-
- ath_print(common, ATH_DBG_ANI,
- " calibrate chan %u/%x nf: %d\n",
- ah->curchan->channel,
- ah->curchan->channelFlags,
- common->ani.noise_floor);
}
}
@@ -637,6 +664,7 @@ irqreturn_t ath_isr(int irq, void *dev)
struct ath_softc *sc = dev;
struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
enum ath9k_int status;
bool sched = false;
@@ -686,7 +714,12 @@ irqreturn_t ath_isr(int irq, void *dev)
if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
(status & ATH9K_INT_BB_WATCHDOG)) {
+
+ spin_lock(&common->cc_lock);
+ ath_hw_cycle_counters_update(common);
ar9003_hw_bb_watchdog_dbg_info(ah);
+ spin_unlock(&common->cc_lock);
+
goto chip_reset;
}
@@ -715,7 +748,9 @@ irqreturn_t ath_isr(int irq, void *dev)
* it will clear whatever condition caused
* the interrupt.
*/
- ath9k_hw_procmibevent(ah);
+ spin_lock(&common->cc_lock);
+ ath9k_hw_proc_mib_event(ah);
+ spin_unlock(&common->cc_lock);
ath9k_hw_set_interrupts(ah, ah->imask);
}
@@ -947,11 +982,9 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
* that changes the channel so update any state that
* might change as a result.
*/
- ath_cache_conf_rate(sc, &hw->conf);
-
ath_update_txpow(sc);
- if (sc->sc_flags & SC_OP_BEACONS)
+ if ((sc->sc_flags & SC_OP_BEACONS) || !(sc->sc_flags & (SC_OP_OFFCHANNEL)))
ath_beacon_config(sc, NULL); /* restart beacons */
ath9k_hw_set_interrupts(ah, ah->imask);
@@ -1150,14 +1183,11 @@ static int ath9k_start(struct ieee80211_hw *hw)
else
ah->imask |= ATH9K_INT_RX;
- if (ah->caps.hw_caps & ATH9K_HW_CAP_GTT)
- ah->imask |= ATH9K_INT_GTT;
+ ah->imask |= ATH9K_INT_GTT;
if (ah->caps.hw_caps & ATH9K_HW_CAP_HT)
ah->imask |= ATH9K_INT_CST;
- ath_cache_conf_rate(sc, &hw->conf);
-
sc->sc_flags &= ~SC_OP_INVALID;
/* Disable BMISS interrupt when we're not associated */
@@ -1373,16 +1403,13 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
mutex_lock(&sc->mutex);
- if (!(ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) &&
- sc->nvifs > 0) {
- ret = -ENOBUFS;
- goto out;
- }
-
switch (vif->type) {
case NL80211_IFTYPE_STATION:
ic_opmode = NL80211_IFTYPE_STATION;
break;
+ case NL80211_IFTYPE_WDS:
+ ic_opmode = NL80211_IFTYPE_WDS;
+ break;
case NL80211_IFTYPE_ADHOC:
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_MESH_POINT:
@@ -1408,8 +1435,7 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
sc->nvifs++;
- if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK)
- ath9k_set_bssid_mask(hw);
+ ath9k_set_bssid_mask(hw, vif);
if (sc->nvifs > 1)
goto out; /* skip global settings for secondary vif */
@@ -1491,7 +1517,7 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
mutex_unlock(&sc->mutex);
}
-void ath9k_enable_ps(struct ath_softc *sc)
+static void ath9k_enable_ps(struct ath_softc *sc)
{
struct ath_hw *ah = sc->sc_ah;
@@ -1505,13 +1531,33 @@ void ath9k_enable_ps(struct ath_softc *sc)
}
}
+static void ath9k_disable_ps(struct ath_softc *sc)
+{
+ struct ath_hw *ah = sc->sc_ah;
+
+ sc->ps_enabled = false;
+ ath9k_hw_setpower(ah, ATH9K_PM_AWAKE);
+ if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
+ ath9k_hw_setrxabort(ah, 0);
+ sc->ps_flags &= ~(PS_WAIT_FOR_BEACON |
+ PS_WAIT_FOR_CAB |
+ PS_WAIT_FOR_PSPOLL_DATA |
+ PS_WAIT_FOR_TX_ACK);
+ if (ah->imask & ATH9K_INT_TIM_TIMER) {
+ ah->imask &= ~ATH9K_INT_TIM_TIMER;
+ ath9k_hw_set_interrupts(ah, ah->imask);
+ }
+ }
+
+}
+
static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
{
struct ath_wiphy *aphy = hw->priv;
struct ath_softc *sc = aphy->sc;
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
- struct ieee80211_conf *conf = &hw->conf;
struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+ struct ieee80211_conf *conf = &hw->conf;
bool disable_radio;
mutex_lock(&sc->mutex);
@@ -1556,35 +1602,13 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
* IEEE80211_CONF_CHANGE_PS is only passed by mac80211 for STA mode.
*/
if (changed & IEEE80211_CONF_CHANGE_PS) {
- if (conf->flags & IEEE80211_CONF_PS) {
- sc->ps_flags |= PS_ENABLED;
- /*
- * At this point we know hardware has received an ACK
- * of a previously sent null data frame.
- */
- if ((sc->ps_flags & PS_NULLFUNC_COMPLETED)) {
- sc->ps_flags &= ~PS_NULLFUNC_COMPLETED;
- ath9k_enable_ps(sc);
- }
- } else {
- sc->ps_enabled = false;
- sc->ps_flags &= ~(PS_ENABLED |
- PS_NULLFUNC_COMPLETED);
- ath9k_setpower(sc, ATH9K_PM_AWAKE);
- if (!(ah->caps.hw_caps &
- ATH9K_HW_CAP_AUTOSLEEP)) {
- ath9k_hw_setrxabort(sc->sc_ah, 0);
- sc->ps_flags &= ~(PS_WAIT_FOR_BEACON |
- PS_WAIT_FOR_CAB |
- PS_WAIT_FOR_PSPOLL_DATA |
- PS_WAIT_FOR_TX_ACK);
- if (ah->imask & ATH9K_INT_TIM_TIMER) {
- ah->imask &= ~ATH9K_INT_TIM_TIMER;
- ath9k_hw_set_interrupts(sc->sc_ah,
- ah->imask);
- }
- }
- }
+ unsigned long flags;
+ spin_lock_irqsave(&sc->sc_pm_lock, flags);
+ if (conf->flags & IEEE80211_CONF_PS)
+ ath9k_enable_ps(sc);
+ else
+ ath9k_disable_ps(sc);
+ spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
}
if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
@@ -1598,6 +1622,11 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
struct ieee80211_channel *curchan = hw->conf.channel;
int pos = curchan->hw_value;
+ int old_pos = -1;
+ unsigned long flags;
+
+ if (ah->curchan)
+ old_pos = ah->curchan - &ah->channels[0];
aphy->chan_idx = pos;
aphy->chan_is_ht = conf_is_ht(conf);
@@ -1625,12 +1654,45 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
ath_update_chainmask(sc, conf_is_ht(conf));
+ /* update survey stats for the old channel before switching */
+ spin_lock_irqsave(&common->cc_lock, flags);
+ ath_update_survey_stats(sc);
+ spin_unlock_irqrestore(&common->cc_lock, flags);
+
+ /*
+ * If the operating channel changes, change the survey in-use flags
+ * along with it.
+ * Reset the survey data for the new channel, unless we're switching
+ * back to the operating channel from an off-channel operation.
+ */
+ if (!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) &&
+ sc->cur_survey != &sc->survey[pos]) {
+
+ if (sc->cur_survey)
+ sc->cur_survey->filled &= ~SURVEY_INFO_IN_USE;
+
+ sc->cur_survey = &sc->survey[pos];
+
+ memset(sc->cur_survey, 0, sizeof(struct survey_info));
+ sc->cur_survey->filled |= SURVEY_INFO_IN_USE;
+ } else if (!(sc->survey[pos].filled & SURVEY_INFO_IN_USE)) {
+ memset(&sc->survey[pos], 0, sizeof(struct survey_info));
+ }
+
if (ath_set_channel(sc, hw, &sc->sc_ah->channels[pos]) < 0) {
ath_print(common, ATH_DBG_FATAL,
"Unable to set channel\n");
mutex_unlock(&sc->mutex);
return -EINVAL;
}
+
+ /*
+ * The most recent snapshot of channel->noisefloor for the old
+ * channel is only available after the hardware reset. Copy it to
+ * the survey stats now.
+ */
+ if (old_pos >= 0)
+ ath_update_survey_nf(sc, old_pos);
}
skip_chan_change:
@@ -1661,6 +1723,7 @@ skip_chan_change:
FIF_PSPOLL | \
FIF_OTHER_BSS | \
FIF_BCN_PRBRESP_PROMISC | \
+ FIF_PROBE_REQ | \
FIF_FCSFAIL)
/* FIXME: sc->sc_full_reset ? */
@@ -1771,20 +1834,21 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
switch (cmd) {
case SET_KEY:
- ret = ath9k_cmn_key_config(common, vif, sta, key);
+ ret = ath_key_config(common, vif, sta, key);
if (ret >= 0) {
key->hw_key_idx = ret;
/* push IV and Michael MIC generation to stack */
key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
- if (key->alg == ALG_TKIP)
+ if (key->cipher == WLAN_CIPHER_SUITE_TKIP)
key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
- if (sc->sc_ah->sw_mgmt_crypto && key->alg == ALG_CCMP)
+ if (sc->sc_ah->sw_mgmt_crypto &&
+ key->cipher == WLAN_CIPHER_SUITE_CCMP)
key->flags |= IEEE80211_KEY_FLAG_SW_MGMT;
ret = 0;
}
break;
case DISABLE_KEY:
- ath9k_cmn_key_delete(common, key);
+ ath_key_delete(common, key);
break;
default:
ret = -EINVAL;
@@ -1968,8 +2032,9 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw,
break;
case IEEE80211_AMPDU_TX_START:
ath9k_ps_wakeup(sc);
- ath_tx_aggr_start(sc, sta, tid, ssn);
- ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+ ret = ath_tx_aggr_start(sc, sta, tid, ssn);
+ if (!ret)
+ ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
ath9k_ps_restore(sc);
break;
case IEEE80211_AMPDU_TX_STOP:
@@ -1998,16 +2063,35 @@ static int ath9k_get_survey(struct ieee80211_hw *hw, int idx,
{
struct ath_wiphy *aphy = hw->priv;
struct ath_softc *sc = aphy->sc;
- struct ath_hw *ah = sc->sc_ah;
- struct ath_common *common = ath9k_hw_common(ah);
- struct ieee80211_conf *conf = &hw->conf;
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct ieee80211_supported_band *sband;
+ struct ieee80211_channel *chan;
+ unsigned long flags;
+ int pos;
- if (idx != 0)
+ spin_lock_irqsave(&common->cc_lock, flags);
+ if (idx == 0)
+ ath_update_survey_stats(sc);
+
+ sband = hw->wiphy->bands[IEEE80211_BAND_2GHZ];
+ if (sband && idx >= sband->n_channels) {
+ idx -= sband->n_channels;
+ sband = NULL;
+ }
+
+ if (!sband)
+ sband = hw->wiphy->bands[IEEE80211_BAND_5GHZ];
+
+ if (!sband || idx >= sband->n_channels) {
+ spin_unlock_irqrestore(&common->cc_lock, flags);
return -ENOENT;
+ }
- survey->channel = conf->channel;
- survey->filled = SURVEY_INFO_NOISE_DBM;
- survey->noise = common->ani.noise_floor;
+ chan = &sband->channels[idx];
+ pos = chan->hw_value;
+ memcpy(survey, &sc->survey[pos], sizeof(*survey));
+ survey->channel = chan;
+ spin_unlock_irqrestore(&common->cc_lock, flags);
return 0;
}
@@ -2032,7 +2116,6 @@ static void ath9k_sw_scan_start(struct ieee80211_hw *hw)
aphy->state = ATH_WIPHY_SCAN;
ath9k_wiphy_pause_all_forced(sc, aphy);
- sc->sc_flags |= SC_OP_SCANNING;
mutex_unlock(&sc->mutex);
}
@@ -2047,7 +2130,6 @@ static void ath9k_sw_scan_complete(struct ieee80211_hw *hw)
mutex_lock(&sc->mutex);
aphy->state = ATH_WIPHY_ACTIVE;
- sc->sc_flags &= ~SC_OP_SCANNING;
mutex_unlock(&sc->mutex);
}
diff --git a/drivers/net/wireless/ath/ath9k/phy.h b/drivers/net/wireless/ath/ath9k/phy.h
index e724c2c1ae2a..17969af842f6 100644
--- a/drivers/net/wireless/ath/ath9k/phy.h
+++ b/drivers/net/wireless/ath/ath9k/phy.h
@@ -45,9 +45,6 @@
} \
} while (0)
-#define ATH9K_IS_MIC_ENABLED(ah) \
- ((ah)->sta_id1_defaults & AR_STA_ID1_CRPT_MIC_ENABLE)
-
#define ANTSWAP_AB 0x0001
#define REDUCE_CHAIN_0 0x00000050
#define REDUCE_CHAIN_1 0x00000051
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c
index e49be733d546..0cee90cf8dc9 100644
--- a/drivers/net/wireless/ath/ath9k/rc.c
+++ b/drivers/net/wireless/ath/ath9k/rc.c
@@ -302,7 +302,7 @@ static const struct ath_rate_table ar5416_11ng_ratetable = {
[64] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 243000,
205100, 20, 20, 8, 64, 65, 65 }, /* 243 Mb */
[65] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS_HGI, 270000,
- 224700, 20, 20, 8, 64, 65, 65 }, /* 170 Mb */
+ 224700, 20, 20, 8, 64, 65, 65 }, /* 270 Mb */
[66] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 324000,
263100, 21, 21, 8, 66, 67, 67 }, /* 324 Mb */
[67] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 360000,
@@ -378,17 +378,6 @@ static const struct ath_rate_table ar5416_11g_ratetable = {
0, /* Phy rates allowed initially */
};
-static const struct ath_rate_table *hw_rate_table[ATH9K_MODE_MAX] = {
- [ATH9K_MODE_11A] = &ar5416_11a_ratetable,
- [ATH9K_MODE_11G] = &ar5416_11g_ratetable,
- [ATH9K_MODE_11NA_HT20] = &ar5416_11na_ratetable,
- [ATH9K_MODE_11NG_HT20] = &ar5416_11ng_ratetable,
- [ATH9K_MODE_11NA_HT40PLUS] = &ar5416_11na_ratetable,
- [ATH9K_MODE_11NA_HT40MINUS] = &ar5416_11na_ratetable,
- [ATH9K_MODE_11NG_HT40PLUS] = &ar5416_11ng_ratetable,
- [ATH9K_MODE_11NG_HT40MINUS] = &ar5416_11ng_ratetable,
-};
-
static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table,
struct ieee80211_tx_rate *rate);
@@ -791,7 +780,7 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
*/
try_per_rate = 4;
- rate_table = sc->cur_rate_table;
+ rate_table = ath_rc_priv->rate_table;
rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table, &is_probe);
/*
@@ -1026,6 +1015,16 @@ static bool ath_rc_update_per(struct ath_softc *sc,
return state_change;
}
+static void ath_debug_stat_retries(struct ath_rate_priv *rc, int rix,
+ int xretries, int retries, u8 per)
+{
+ struct ath_rc_stats *stats = &rc->rcstats[rix];
+
+ stats->xretries += xretries;
+ stats->retries += retries;
+ stats->per = per;
+}
+
/* Update PER, RSSI and whatever else that the code thinks it is doing.
If you can make sense of all this, you really need to go out more. */
@@ -1038,7 +1037,7 @@ static void ath_rc_update_ht(struct ath_softc *sc,
int rate;
u8 last_per;
bool state_change = false;
- const struct ath_rate_table *rate_table = sc->cur_rate_table;
+ const struct ath_rate_table *rate_table = ath_rc_priv->rate_table;
int size = ath_rc_priv->rate_table_size;
if ((tx_rate < 0) || (tx_rate > rate_table->rate_cnt))
@@ -1098,7 +1097,7 @@ static void ath_rc_update_ht(struct ath_softc *sc,
ath_rc_priv->per_down_time = now_msec;
}
- ath_debug_stat_retries(sc, tx_rate, xretries, retries,
+ ath_debug_stat_retries(ath_rc_priv, tx_rate, xretries, retries,
ath_rc_priv->per[tx_rate]);
}
@@ -1140,7 +1139,7 @@ static void ath_rc_tx_status(struct ath_softc *sc,
u8 flags;
u32 i = 0, rix;
- rate_table = sc->cur_rate_table;
+ rate_table = ath_rc_priv->rate_table;
/*
* If the first rate is not the final index, there
@@ -1190,39 +1189,23 @@ static void ath_rc_tx_status(struct ath_softc *sc,
static const
struct ath_rate_table *ath_choose_rate_table(struct ath_softc *sc,
enum ieee80211_band band,
- bool is_ht,
- bool is_cw_40)
+ bool is_ht)
{
- int mode = 0;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
switch(band) {
case IEEE80211_BAND_2GHZ:
- mode = ATH9K_MODE_11G;
if (is_ht)
- mode = ATH9K_MODE_11NG_HT20;
- if (is_cw_40)
- mode = ATH9K_MODE_11NG_HT40PLUS;
- break;
+ return &ar5416_11ng_ratetable;
+ return &ar5416_11g_ratetable;
case IEEE80211_BAND_5GHZ:
- mode = ATH9K_MODE_11A;
if (is_ht)
- mode = ATH9K_MODE_11NA_HT20;
- if (is_cw_40)
- mode = ATH9K_MODE_11NA_HT40PLUS;
- break;
+ return &ar5416_11na_ratetable;
+ return &ar5416_11a_ratetable;
default:
ath_print(common, ATH_DBG_CONFIG, "Invalid band\n");
return NULL;
}
-
- BUG_ON(mode >= ATH9K_MODE_MAX);
-
- ath_print(common, ATH_DBG_CONFIG,
- "Choosing rate table for mode: %d\n", mode);
-
- sc->cur_rate_mode = mode;
- return hw_rate_table[mode];
}
static void ath_rc_init(struct ath_softc *sc,
@@ -1293,7 +1276,7 @@ static void ath_rc_init(struct ath_softc *sc,
ath_rc_priv->max_valid_rate = k;
ath_rc_sort_validrates(rate_table, ath_rc_priv);
ath_rc_priv->rate_max_phy = ath_rc_priv->valid_rate_index[k-4];
- sc->cur_rate_table = rate_table;
+ ath_rc_priv->rate_table = rate_table;
ath_print(common, ATH_DBG_CONFIG,
"RC Initialized with capabilities: 0x%x\n",
@@ -1320,10 +1303,35 @@ static u8 ath_rc_build_ht_caps(struct ath_softc *sc, struct ieee80211_sta *sta,
return caps;
}
+static bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an,
+ u8 tidno)
+{
+ struct ath_atx_tid *txtid;
+
+ if (!(sc->sc_flags & SC_OP_TXAGGR))
+ return false;
+
+ txtid = ATH_AN_2_TID(an, tidno);
+
+ if (!(txtid->state & (AGGR_ADDBA_COMPLETE | AGGR_ADDBA_PROGRESS)))
+ return true;
+ return false;
+}
+
+
/***********************************/
/* mac80211 Rate Control callbacks */
/***********************************/
+static void ath_debug_stat_rc(struct ath_rate_priv *rc, int final_rate)
+{
+ struct ath_rc_stats *stats;
+
+ stats = &rc->rcstats[final_rate];
+ stats->success++;
+}
+
+
static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
struct ieee80211_sta *sta, void *priv_sta,
struct sk_buff *skb)
@@ -1359,6 +1367,12 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
if (tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED)
return;
+ if (!(tx_info->flags & IEEE80211_TX_STAT_AMPDU)) {
+ tx_info->status.ampdu_ack_len =
+ (tx_info->flags & IEEE80211_TX_STAT_ACK ? 1 : 0);
+ tx_info->status.ampdu_len = 1;
+ }
+
/*
* If an underrun error is seen assume it as an excessive retry only
* if max frame trigger level has been reached (2 KB for singel stream,
@@ -1397,8 +1411,9 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
}
}
- ath_debug_stat_rc(sc, ath_rc_get_rateindex(sc->cur_rate_table,
- &tx_info->status.rates[final_ts_idx]));
+ ath_debug_stat_rc(ath_rc_priv,
+ ath_rc_get_rateindex(ath_rc_priv->rate_table,
+ &tx_info->status.rates[final_ts_idx]));
}
static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband,
@@ -1438,14 +1453,8 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband,
/* Choose rate table first */
- if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) ||
- (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT) ||
- (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC)) {
- rate_table = ath_choose_rate_table(sc, sband->band,
- sta->ht_cap.ht_supported, is_cw40);
- } else {
- rate_table = hw_rate_table[sc->cur_rate_mode];
- }
+ rate_table = ath_choose_rate_table(sc, sband->band,
+ sta->ht_cap.ht_supported);
ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta, is_cw40, is_sgi);
ath_rc_init(sc, priv_sta, sband, sta, rate_table);
@@ -1485,8 +1494,7 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband,
if ((local_cw40 != oper_cw40) || (local_sgi != oper_sgi)) {
rate_table = ath_choose_rate_table(sc, sband->band,
- sta->ht_cap.ht_supported,
- oper_cw40);
+ sta->ht_cap.ht_supported);
ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta,
oper_cw40, oper_sgi);
ath_rc_init(sc, priv_sta, sband, sta, rate_table);
@@ -1494,11 +1502,98 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband,
ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG,
"Operating HT Bandwidth changed to: %d\n",
sc->hw->conf.channel_type);
- sc->cur_rate_table = hw_rate_table[sc->cur_rate_mode];
}
}
}
+#ifdef CONFIG_ATH9K_DEBUGFS
+
+static int ath9k_debugfs_open(struct inode *inode, struct file *file)
+{
+ file->private_data = inode->i_private;
+ return 0;
+}
+
+static ssize_t read_file_rcstat(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath_rate_priv *rc = file->private_data;
+ char *buf;
+ unsigned int len = 0, max;
+ int i = 0;
+ ssize_t retval;
+
+ if (rc->rate_table == NULL)
+ return 0;
+
+ max = 80 + rc->rate_table->rate_cnt * 1024 + 1;
+ buf = kmalloc(max, GFP_KERNEL);
+ if (buf == NULL)
+ return -ENOMEM;
+
+ len += sprintf(buf, "%6s %6s %6s "
+ "%10s %10s %10s %10s\n",
+ "HT", "MCS", "Rate",
+ "Success", "Retries", "XRetries", "PER");
+
+ for (i = 0; i < rc->rate_table->rate_cnt; i++) {
+ u32 ratekbps = rc->rate_table->info[i].ratekbps;
+ struct ath_rc_stats *stats = &rc->rcstats[i];
+ char mcs[5];
+ char htmode[5];
+ int used_mcs = 0, used_htmode = 0;
+
+ if (WLAN_RC_PHY_HT(rc->rate_table->info[i].phy)) {
+ used_mcs = snprintf(mcs, 5, "%d",
+ rc->rate_table->info[i].ratecode);
+
+ if (WLAN_RC_PHY_40(rc->rate_table->info[i].phy))
+ used_htmode = snprintf(htmode, 5, "HT40");
+ else if (WLAN_RC_PHY_20(rc->rate_table->info[i].phy))
+ used_htmode = snprintf(htmode, 5, "HT20");
+ else
+ used_htmode = snprintf(htmode, 5, "????");
+ }
+
+ mcs[used_mcs] = '\0';
+ htmode[used_htmode] = '\0';
+
+ len += snprintf(buf + len, max - len,
+ "%6s %6s %3u.%d: "
+ "%10u %10u %10u %10u\n",
+ htmode,
+ mcs,
+ ratekbps / 1000,
+ (ratekbps % 1000) / 100,
+ stats->success,
+ stats->retries,
+ stats->xretries,
+ stats->per);
+ }
+
+ if (len > max)
+ len = max;
+
+ retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+ kfree(buf);
+ return retval;
+}
+
+static const struct file_operations fops_rcstat = {
+ .read = read_file_rcstat,
+ .open = ath9k_debugfs_open,
+ .owner = THIS_MODULE
+};
+
+static void ath_rate_add_sta_debugfs(void *priv, void *priv_sta,
+ struct dentry *dir)
+{
+ struct ath_rate_priv *rc = priv_sta;
+ debugfs_create_file("rc_stats", S_IRUGO, dir, rc, &fops_rcstat);
+}
+
+#endif /* CONFIG_ATH9K_DEBUGFS */
+
static void *ath_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
{
struct ath_wiphy *aphy = hw->priv;
@@ -1545,6 +1640,9 @@ static struct rate_control_ops ath_rate_ops = {
.free = ath_rate_free,
.alloc_sta = ath_rate_alloc_sta,
.free_sta = ath_rate_free_sta,
+#ifdef CONFIG_ATH9K_DEBUGFS
+ .add_sta_debugfs = ath_rate_add_sta_debugfs,
+#endif
};
int ath_rate_control_register(void)
diff --git a/drivers/net/wireless/ath/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h
index dc1082654501..2f46a2266ba1 100644
--- a/drivers/net/wireless/ath/ath9k/rc.h
+++ b/drivers/net/wireless/ath/ath9k/rc.h
@@ -135,20 +135,21 @@ enum {
/**
* struct ath_rate_table - Rate Control table
- * @valid: valid for use in rate control
- * @valid_single_stream: valid for use in rate control for
- * single stream operation
- * @phy: CCK/OFDM
+ * @rate_cnt: total number of rates for the given wireless mode
+ * @mcs_start: MCS rate index offset
+ * @rate_flags: Rate Control flags
+ * @phy: CCK/OFDM/HT20/HT40
* @ratekbps: rate in Kbits per second
* @user_ratekbps: user rate in Kbits per second
* @ratecode: rate that goes into HW descriptors
- * @short_preamble: Mask for enabling short preamble in ratecode for CCK
* @dot11rate: value that goes into supported
* rates info element of MLME
* @ctrl_rate: Index of next lower basic rate, used for duration computation
- * @max_4ms_framelen: maximum frame length(bytes) for tx duration
+ * @cw40index: Index of rates having 40MHz channel width
+ * @sgi_index: Index of rates having Short Guard Interval
+ * @ht_index: high throughput rates having 40MHz channel width and
+ * Short Guard Interval
* @probe_interval: interval for rate control to probe for other rates
- * @rssi_reduce_interval: interval for rate control to reduce rssi
* @initial_ratemax: initial ratemax value
*/
struct ath_rate_table {
@@ -175,6 +176,13 @@ struct ath_rateset {
u8 rs_rates[ATH_RATE_MAX];
};
+struct ath_rc_stats {
+ u32 success;
+ u32 retries;
+ u32 xretries;
+ u8 per;
+};
+
/**
* struct ath_rate_priv - Rate Control priv data
* @state: RC state
@@ -211,6 +219,10 @@ struct ath_rate_priv {
struct ath_rateset neg_rates;
struct ath_rateset neg_ht_rates;
struct ath_rate_softc *asc;
+ const struct ath_rate_table *rate_table;
+
+ struct dentry *debugfs_rcstats;
+ struct ath_rc_stats rcstats[RATE_TABLE_SIZE];
};
#define ATH_TX_INFO_FRAME_TYPE_INTERNAL (1 << 0)
@@ -224,7 +236,18 @@ enum ath9k_internal_frame_type {
ATH9K_IFT_UNPAUSE
};
+#ifdef CONFIG_ATH9K_RATE_CONTROL
int ath_rate_control_register(void);
void ath_rate_control_unregister(void);
+#else
+static inline int ath_rate_control_register(void)
+{
+ return 0;
+}
+
+static inline void ath_rate_control_unregister(void)
+{
+}
+#endif
#endif /* RC_H */
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index a3fc987ebab0..fe73fc50082a 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -19,6 +19,15 @@
#define SKB_CB_ATHBUF(__skb) (*((struct ath_buf **)__skb->cb))
+static inline bool ath_is_alt_ant_ratio_better(int alt_ratio, int maxdelta,
+ int mindelta, int main_rssi_avg,
+ int alt_rssi_avg, int pkt_count)
+{
+ return (((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) &&
+ (alt_rssi_avg > main_rssi_avg + maxdelta)) ||
+ (alt_rssi_avg > main_rssi_avg + mindelta)) && (pkt_count > 50);
+}
+
static inline bool ath9k_check_auto_sleep(struct ath_softc *sc)
{
return sc->ps_enabled &&
@@ -110,8 +119,7 @@ static void ath_opmode_init(struct ath_softc *sc)
ath9k_hw_setrxfilter(ah, rfilt);
/* configure bssid mask */
- if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK)
- ath_hw_setbssidmask(common);
+ ath_hw_setbssidmask(common);
/* configure operational mode */
ath9k_hw_setopmode(ah);
@@ -260,6 +268,7 @@ static int ath_rx_edma_init(struct ath_softc *sc, int nbufs)
bf->bf_buf_addr))) {
dev_kfree_skb_any(skb);
bf->bf_mpdu = NULL;
+ bf->bf_buf_addr = 0;
ath_print(common, ATH_DBG_FATAL,
"dma_mapping_error() on RX init\n");
error = -ENOMEM;
@@ -292,7 +301,7 @@ static void ath_edma_start_recv(struct ath_softc *sc)
ath_opmode_init(sc);
- ath9k_hw_startpcureceive(sc->sc_ah, (sc->sc_flags & SC_OP_SCANNING));
+ ath9k_hw_startpcureceive(sc->sc_ah, (sc->sc_flags & SC_OP_OFFCHANNEL));
}
static void ath_edma_stop_recv(struct ath_softc *sc)
@@ -350,12 +359,12 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
bf->bf_buf_addr))) {
dev_kfree_skb_any(skb);
bf->bf_mpdu = NULL;
+ bf->bf_buf_addr = 0;
ath_print(common, ATH_DBG_FATAL,
"dma_mapping_error() on RX init\n");
error = -ENOMEM;
goto err;
}
- bf->bf_dmacontext = bf->bf_buf_addr;
}
sc->rx.rxlink = NULL;
}
@@ -385,6 +394,8 @@ void ath_rx_cleanup(struct ath_softc *sc)
common->rx_bufsize,
DMA_FROM_DEVICE);
dev_kfree_skb(skb);
+ bf->bf_buf_addr = 0;
+ bf->bf_mpdu = NULL;
}
}
@@ -422,8 +433,7 @@ u32 ath_calcrxfilter(struct ath_softc *sc)
| ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST
| ATH9K_RX_FILTER_MCAST;
- /* If not a STA, enable processing of Probe Requests */
- if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION)
+ if (sc->rx.rxfilter & FIF_PROBE_REQ)
rfilt |= ATH9K_RX_FILTER_PROBEREQ;
/*
@@ -440,13 +450,14 @@ u32 ath_calcrxfilter(struct ath_softc *sc)
rfilt |= ATH9K_RX_FILTER_CONTROL;
if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) &&
+ (sc->nvifs <= 1) &&
!(sc->rx.rxfilter & FIF_BCN_PRBRESP_PROMISC))
rfilt |= ATH9K_RX_FILTER_MYBEACON;
else
rfilt |= ATH9K_RX_FILTER_BEACON;
- if ((AR_SREV_9280_10_OR_LATER(sc->sc_ah) ||
- AR_SREV_9285_10_OR_LATER(sc->sc_ah)) &&
+ if ((AR_SREV_9280_20_OR_LATER(sc->sc_ah) ||
+ AR_SREV_9285_12_OR_LATER(sc->sc_ah)) &&
(sc->sc_ah->opmode == NL80211_IFTYPE_AP) &&
(sc->rx.rxfilter & FIF_PSPOLL))
rfilt |= ATH9K_RX_FILTER_PSPOLL;
@@ -454,9 +465,8 @@ u32 ath_calcrxfilter(struct ath_softc *sc)
if (conf_is_ht(&sc->hw->conf))
rfilt |= ATH9K_RX_FILTER_COMP_BAR;
- if (sc->sec_wiphy || (sc->rx.rxfilter & FIF_OTHER_BSS)) {
- /* TODO: only needed if more than one BSSID is in use in
- * station/adhoc mode */
+ if (sc->sec_wiphy || (sc->nvifs > 1) ||
+ (sc->rx.rxfilter & FIF_OTHER_BSS)) {
/* The following may also be needed for other older chips */
if (sc->sc_ah->hw_version.macVersion == AR_SREV_VERSION_9160)
rfilt |= ATH9K_RX_FILTER_PROM;
@@ -498,7 +508,7 @@ int ath_startrecv(struct ath_softc *sc)
start_recv:
spin_unlock_bh(&sc->rx.rxbuflock);
ath_opmode_init(sc);
- ath9k_hw_startpcureceive(ah, (sc->sc_flags & SC_OP_SCANNING));
+ ath9k_hw_startpcureceive(ah, (sc->sc_flags & SC_OP_OFFCHANNEL));
return 0;
}
@@ -631,7 +641,7 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb)
* No more broadcast/multicast frames to be received at this
* point.
*/
- sc->ps_flags &= ~PS_WAIT_FOR_CAB;
+ sc->ps_flags &= ~(PS_WAIT_FOR_CAB | PS_WAIT_FOR_BEACON);
ath_print(common, ATH_DBG_PS,
"All PS CAB frames received, back to sleep\n");
} else if ((sc->ps_flags & PS_WAIT_FOR_PSPOLL_DATA) &&
@@ -870,15 +880,18 @@ static bool ath9k_rx_accept(struct ath_common *common,
if (rx_stats->rs_status & ATH9K_RXERR_DECRYPT) {
*decrypt_error = true;
} else if (rx_stats->rs_status & ATH9K_RXERR_MIC) {
- if (ieee80211_is_ctl(fc))
- /*
- * Sometimes, we get invalid
- * MIC failures on valid control frames.
- * Remove these mic errors.
- */
- rx_stats->rs_status &= ~ATH9K_RXERR_MIC;
- else
+ /*
+ * The MIC error bit is only valid if the frame
+ * is not a control frame or fragment, and it was
+ * decrypted using a valid TKIP key.
+ */
+ if (!ieee80211_is_ctl(fc) &&
+ !ieee80211_has_morefrags(fc) &&
+ !(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) &&
+ test_bit(rx_stats->rs_keyix, common->tkip_keymap))
rxs->flag |= RX_FLAG_MMIC_ERROR;
+ else
+ rx_stats->rs_status &= ~ATH9K_RXERR_MIC;
}
/*
* Reject error frames with the exception of
@@ -966,7 +979,11 @@ static void ath9k_process_rssi(struct ath_common *common,
* at least one sdata of a wiphy on mac80211 but with ath9k virtual
* wiphy you'd have to iterate over every wiphy and each sdata.
*/
- sta = ieee80211_find_sta_by_hw(hw, hdr->addr2);
+ if (is_multicast_ether_addr(hdr->addr1))
+ sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr2, NULL);
+ else
+ sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr2, hdr->addr1);
+
if (sta) {
an = (struct ath_node *) sta->drv_priv;
if (rx_stats->rs_rssi != ATH9K_RSSI_BAD &&
@@ -1073,6 +1090,539 @@ static void ath9k_rx_skb_postprocess(struct ath_common *common,
rxs->flag &= ~RX_FLAG_DECRYPTED;
}
+static void ath_lnaconf_alt_good_scan(struct ath_ant_comb *antcomb,
+ struct ath_hw_antcomb_conf ant_conf,
+ int main_rssi_avg)
+{
+ antcomb->quick_scan_cnt = 0;
+
+ if (ant_conf.main_lna_conf == ATH_ANT_DIV_COMB_LNA2)
+ antcomb->rssi_lna2 = main_rssi_avg;
+ else if (ant_conf.main_lna_conf == ATH_ANT_DIV_COMB_LNA1)
+ antcomb->rssi_lna1 = main_rssi_avg;
+
+ switch ((ant_conf.main_lna_conf << 4) | ant_conf.alt_lna_conf) {
+ case (0x10): /* LNA2 A-B */
+ antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
+ antcomb->first_quick_scan_conf =
+ ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
+ antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA1;
+ break;
+ case (0x20): /* LNA1 A-B */
+ antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
+ antcomb->first_quick_scan_conf =
+ ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
+ antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA2;
+ break;
+ case (0x21): /* LNA1 LNA2 */
+ antcomb->main_conf = ATH_ANT_DIV_COMB_LNA2;
+ antcomb->first_quick_scan_conf =
+ ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
+ antcomb->second_quick_scan_conf =
+ ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
+ break;
+ case (0x12): /* LNA2 LNA1 */
+ antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1;
+ antcomb->first_quick_scan_conf =
+ ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
+ antcomb->second_quick_scan_conf =
+ ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
+ break;
+ case (0x13): /* LNA2 A+B */
+ antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
+ antcomb->first_quick_scan_conf =
+ ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
+ antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA1;
+ break;
+ case (0x23): /* LNA1 A+B */
+ antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
+ antcomb->first_quick_scan_conf =
+ ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
+ antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA2;
+ break;
+ default:
+ break;
+ }
+}
+
+static void ath_select_ant_div_from_quick_scan(struct ath_ant_comb *antcomb,
+ struct ath_hw_antcomb_conf *div_ant_conf,
+ int main_rssi_avg, int alt_rssi_avg,
+ int alt_ratio)
+{
+ /* alt_good */
+ switch (antcomb->quick_scan_cnt) {
+ case 0:
+ /* set alt to main, and alt to first conf */
+ div_ant_conf->main_lna_conf = antcomb->main_conf;
+ div_ant_conf->alt_lna_conf = antcomb->first_quick_scan_conf;
+ break;
+ case 1:
+ /* set alt to main, and alt to first conf */
+ div_ant_conf->main_lna_conf = antcomb->main_conf;
+ div_ant_conf->alt_lna_conf = antcomb->second_quick_scan_conf;
+ antcomb->rssi_first = main_rssi_avg;
+ antcomb->rssi_second = alt_rssi_avg;
+
+ if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) {
+ /* main is LNA1 */
+ if (ath_is_alt_ant_ratio_better(alt_ratio,
+ ATH_ANT_DIV_COMB_LNA1_DELTA_HI,
+ ATH_ANT_DIV_COMB_LNA1_DELTA_LOW,
+ main_rssi_avg, alt_rssi_avg,
+ antcomb->total_pkt_count))
+ antcomb->first_ratio = true;
+ else
+ antcomb->first_ratio = false;
+ } else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) {
+ if (ath_is_alt_ant_ratio_better(alt_ratio,
+ ATH_ANT_DIV_COMB_LNA1_DELTA_MID,
+ ATH_ANT_DIV_COMB_LNA1_DELTA_LOW,
+ main_rssi_avg, alt_rssi_avg,
+ antcomb->total_pkt_count))
+ antcomb->first_ratio = true;
+ else
+ antcomb->first_ratio = false;
+ } else {
+ if ((((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) &&
+ (alt_rssi_avg > main_rssi_avg +
+ ATH_ANT_DIV_COMB_LNA1_DELTA_HI)) ||
+ (alt_rssi_avg > main_rssi_avg)) &&
+ (antcomb->total_pkt_count > 50))
+ antcomb->first_ratio = true;
+ else
+ antcomb->first_ratio = false;
+ }
+ break;
+ case 2:
+ antcomb->alt_good = false;
+ antcomb->scan_not_start = false;
+ antcomb->scan = false;
+ antcomb->rssi_first = main_rssi_avg;
+ antcomb->rssi_third = alt_rssi_avg;
+
+ if (antcomb->second_quick_scan_conf == ATH_ANT_DIV_COMB_LNA1)
+ antcomb->rssi_lna1 = alt_rssi_avg;
+ else if (antcomb->second_quick_scan_conf ==
+ ATH_ANT_DIV_COMB_LNA2)
+ antcomb->rssi_lna2 = alt_rssi_avg;
+ else if (antcomb->second_quick_scan_conf ==
+ ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2) {
+ if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2)
+ antcomb->rssi_lna2 = main_rssi_avg;
+ else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1)
+ antcomb->rssi_lna1 = main_rssi_avg;
+ }
+
+ if (antcomb->rssi_lna2 > antcomb->rssi_lna1 +
+ ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA)
+ div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA2;
+ else
+ div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA1;
+
+ if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) {
+ if (ath_is_alt_ant_ratio_better(alt_ratio,
+ ATH_ANT_DIV_COMB_LNA1_DELTA_HI,
+ ATH_ANT_DIV_COMB_LNA1_DELTA_LOW,
+ main_rssi_avg, alt_rssi_avg,
+ antcomb->total_pkt_count))
+ antcomb->second_ratio = true;
+ else
+ antcomb->second_ratio = false;
+ } else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) {
+ if (ath_is_alt_ant_ratio_better(alt_ratio,
+ ATH_ANT_DIV_COMB_LNA1_DELTA_MID,
+ ATH_ANT_DIV_COMB_LNA1_DELTA_LOW,
+ main_rssi_avg, alt_rssi_avg,
+ antcomb->total_pkt_count))
+ antcomb->second_ratio = true;
+ else
+ antcomb->second_ratio = false;
+ } else {
+ if ((((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) &&
+ (alt_rssi_avg > main_rssi_avg +
+ ATH_ANT_DIV_COMB_LNA1_DELTA_HI)) ||
+ (alt_rssi_avg > main_rssi_avg)) &&
+ (antcomb->total_pkt_count > 50))
+ antcomb->second_ratio = true;
+ else
+ antcomb->second_ratio = false;
+ }
+
+ /* set alt to the conf with maximun ratio */
+ if (antcomb->first_ratio && antcomb->second_ratio) {
+ if (antcomb->rssi_second > antcomb->rssi_third) {
+ /* first alt*/
+ if ((antcomb->first_quick_scan_conf ==
+ ATH_ANT_DIV_COMB_LNA1) ||
+ (antcomb->first_quick_scan_conf ==
+ ATH_ANT_DIV_COMB_LNA2))
+ /* Set alt LNA1 or LNA2*/
+ if (div_ant_conf->main_lna_conf ==
+ ATH_ANT_DIV_COMB_LNA2)
+ div_ant_conf->alt_lna_conf =
+ ATH_ANT_DIV_COMB_LNA1;
+ else
+ div_ant_conf->alt_lna_conf =
+ ATH_ANT_DIV_COMB_LNA2;
+ else
+ /* Set alt to A+B or A-B */
+ div_ant_conf->alt_lna_conf =
+ antcomb->first_quick_scan_conf;
+ } else if ((antcomb->second_quick_scan_conf ==
+ ATH_ANT_DIV_COMB_LNA1) ||
+ (antcomb->second_quick_scan_conf ==
+ ATH_ANT_DIV_COMB_LNA2)) {
+ /* Set alt LNA1 or LNA2 */
+ if (div_ant_conf->main_lna_conf ==
+ ATH_ANT_DIV_COMB_LNA2)
+ div_ant_conf->alt_lna_conf =
+ ATH_ANT_DIV_COMB_LNA1;
+ else
+ div_ant_conf->alt_lna_conf =
+ ATH_ANT_DIV_COMB_LNA2;
+ } else {
+ /* Set alt to A+B or A-B */
+ div_ant_conf->alt_lna_conf =
+ antcomb->second_quick_scan_conf;
+ }
+ } else if (antcomb->first_ratio) {
+ /* first alt */
+ if ((antcomb->first_quick_scan_conf ==
+ ATH_ANT_DIV_COMB_LNA1) ||
+ (antcomb->first_quick_scan_conf ==
+ ATH_ANT_DIV_COMB_LNA2))
+ /* Set alt LNA1 or LNA2 */
+ if (div_ant_conf->main_lna_conf ==
+ ATH_ANT_DIV_COMB_LNA2)
+ div_ant_conf->alt_lna_conf =
+ ATH_ANT_DIV_COMB_LNA1;
+ else
+ div_ant_conf->alt_lna_conf =
+ ATH_ANT_DIV_COMB_LNA2;
+ else
+ /* Set alt to A+B or A-B */
+ div_ant_conf->alt_lna_conf =
+ antcomb->first_quick_scan_conf;
+ } else if (antcomb->second_ratio) {
+ /* second alt */
+ if ((antcomb->second_quick_scan_conf ==
+ ATH_ANT_DIV_COMB_LNA1) ||
+ (antcomb->second_quick_scan_conf ==
+ ATH_ANT_DIV_COMB_LNA2))
+ /* Set alt LNA1 or LNA2 */
+ if (div_ant_conf->main_lna_conf ==
+ ATH_ANT_DIV_COMB_LNA2)
+ div_ant_conf->alt_lna_conf =
+ ATH_ANT_DIV_COMB_LNA1;
+ else
+ div_ant_conf->alt_lna_conf =
+ ATH_ANT_DIV_COMB_LNA2;
+ else
+ /* Set alt to A+B or A-B */
+ div_ant_conf->alt_lna_conf =
+ antcomb->second_quick_scan_conf;
+ } else {
+ /* main is largest */
+ if ((antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) ||
+ (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2))
+ /* Set alt LNA1 or LNA2 */
+ if (div_ant_conf->main_lna_conf ==
+ ATH_ANT_DIV_COMB_LNA2)
+ div_ant_conf->alt_lna_conf =
+ ATH_ANT_DIV_COMB_LNA1;
+ else
+ div_ant_conf->alt_lna_conf =
+ ATH_ANT_DIV_COMB_LNA2;
+ else
+ /* Set alt to A+B or A-B */
+ div_ant_conf->alt_lna_conf = antcomb->main_conf;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf)
+{
+ /* Adjust the fast_div_bias based on main and alt lna conf */
+ switch ((ant_conf->main_lna_conf << 4) | ant_conf->alt_lna_conf) {
+ case (0x01): /* A-B LNA2 */
+ ant_conf->fast_div_bias = 0x3b;
+ break;
+ case (0x02): /* A-B LNA1 */
+ ant_conf->fast_div_bias = 0x3d;
+ break;
+ case (0x03): /* A-B A+B */
+ ant_conf->fast_div_bias = 0x1;
+ break;
+ case (0x10): /* LNA2 A-B */
+ ant_conf->fast_div_bias = 0x7;
+ break;
+ case (0x12): /* LNA2 LNA1 */
+ ant_conf->fast_div_bias = 0x2;
+ break;
+ case (0x13): /* LNA2 A+B */
+ ant_conf->fast_div_bias = 0x7;
+ break;
+ case (0x20): /* LNA1 A-B */
+ ant_conf->fast_div_bias = 0x6;
+ break;
+ case (0x21): /* LNA1 LNA2 */
+ ant_conf->fast_div_bias = 0x0;
+ break;
+ case (0x23): /* LNA1 A+B */
+ ant_conf->fast_div_bias = 0x6;
+ break;
+ case (0x30): /* A+B A-B */
+ ant_conf->fast_div_bias = 0x1;
+ break;
+ case (0x31): /* A+B LNA2 */
+ ant_conf->fast_div_bias = 0x3b;
+ break;
+ case (0x32): /* A+B LNA1 */
+ ant_conf->fast_div_bias = 0x3d;
+ break;
+ default:
+ break;
+ }
+}
+
+/* Antenna diversity and combining */
+static void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs)
+{
+ struct ath_hw_antcomb_conf div_ant_conf;
+ struct ath_ant_comb *antcomb = &sc->ant_comb;
+ int alt_ratio = 0, alt_rssi_avg = 0, main_rssi_avg = 0, curr_alt_set;
+ int curr_main_set, curr_bias;
+ int main_rssi = rs->rs_rssi_ctl0;
+ int alt_rssi = rs->rs_rssi_ctl1;
+ int rx_ant_conf, main_ant_conf;
+ bool short_scan = false;
+
+ rx_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_CURRENT_SHIFT) &
+ ATH_ANT_RX_MASK;
+ main_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_MAIN_SHIFT) &
+ ATH_ANT_RX_MASK;
+
+ /* Record packet only when alt_rssi is positive */
+ if (alt_rssi > 0) {
+ antcomb->total_pkt_count++;
+ antcomb->main_total_rssi += main_rssi;
+ antcomb->alt_total_rssi += alt_rssi;
+ if (main_ant_conf == rx_ant_conf)
+ antcomb->main_recv_cnt++;
+ else
+ antcomb->alt_recv_cnt++;
+ }
+
+ /* Short scan check */
+ if (antcomb->scan && antcomb->alt_good) {
+ if (time_after(jiffies, antcomb->scan_start_time +
+ msecs_to_jiffies(ATH_ANT_DIV_COMB_SHORT_SCAN_INTR)))
+ short_scan = true;
+ else
+ if (antcomb->total_pkt_count ==
+ ATH_ANT_DIV_COMB_SHORT_SCAN_PKTCOUNT) {
+ alt_ratio = ((antcomb->alt_recv_cnt * 100) /
+ antcomb->total_pkt_count);
+ if (alt_ratio < ATH_ANT_DIV_COMB_ALT_ANT_RATIO)
+ short_scan = true;
+ }
+ }
+
+ if (((antcomb->total_pkt_count < ATH_ANT_DIV_COMB_MAX_PKTCOUNT) ||
+ rs->rs_moreaggr) && !short_scan)
+ return;
+
+ if (antcomb->total_pkt_count) {
+ alt_ratio = ((antcomb->alt_recv_cnt * 100) /
+ antcomb->total_pkt_count);
+ main_rssi_avg = (antcomb->main_total_rssi /
+ antcomb->total_pkt_count);
+ alt_rssi_avg = (antcomb->alt_total_rssi /
+ antcomb->total_pkt_count);
+ }
+
+
+ ath9k_hw_antdiv_comb_conf_get(sc->sc_ah, &div_ant_conf);
+ curr_alt_set = div_ant_conf.alt_lna_conf;
+ curr_main_set = div_ant_conf.main_lna_conf;
+ curr_bias = div_ant_conf.fast_div_bias;
+
+ antcomb->count++;
+
+ if (antcomb->count == ATH_ANT_DIV_COMB_MAX_COUNT) {
+ if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) {
+ ath_lnaconf_alt_good_scan(antcomb, div_ant_conf,
+ main_rssi_avg);
+ antcomb->alt_good = true;
+ } else {
+ antcomb->alt_good = false;
+ }
+
+ antcomb->count = 0;
+ antcomb->scan = true;
+ antcomb->scan_not_start = true;
+ }
+
+ if (!antcomb->scan) {
+ if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) {
+ if (curr_alt_set == ATH_ANT_DIV_COMB_LNA2) {
+ /* Switch main and alt LNA */
+ div_ant_conf.main_lna_conf =
+ ATH_ANT_DIV_COMB_LNA2;
+ div_ant_conf.alt_lna_conf =
+ ATH_ANT_DIV_COMB_LNA1;
+ } else if (curr_alt_set == ATH_ANT_DIV_COMB_LNA1) {
+ div_ant_conf.main_lna_conf =
+ ATH_ANT_DIV_COMB_LNA1;
+ div_ant_conf.alt_lna_conf =
+ ATH_ANT_DIV_COMB_LNA2;
+ }
+
+ goto div_comb_done;
+ } else if ((curr_alt_set != ATH_ANT_DIV_COMB_LNA1) &&
+ (curr_alt_set != ATH_ANT_DIV_COMB_LNA2)) {
+ /* Set alt to another LNA */
+ if (curr_main_set == ATH_ANT_DIV_COMB_LNA2)
+ div_ant_conf.alt_lna_conf =
+ ATH_ANT_DIV_COMB_LNA1;
+ else if (curr_main_set == ATH_ANT_DIV_COMB_LNA1)
+ div_ant_conf.alt_lna_conf =
+ ATH_ANT_DIV_COMB_LNA2;
+
+ goto div_comb_done;
+ }
+
+ if ((alt_rssi_avg < (main_rssi_avg +
+ ATH_ANT_DIV_COMB_LNA1_LNA2_DELTA)))
+ goto div_comb_done;
+ }
+
+ if (!antcomb->scan_not_start) {
+ switch (curr_alt_set) {
+ case ATH_ANT_DIV_COMB_LNA2:
+ antcomb->rssi_lna2 = alt_rssi_avg;
+ antcomb->rssi_lna1 = main_rssi_avg;
+ antcomb->scan = true;
+ /* set to A+B */
+ div_ant_conf.main_lna_conf =
+ ATH_ANT_DIV_COMB_LNA1;
+ div_ant_conf.alt_lna_conf =
+ ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
+ break;
+ case ATH_ANT_DIV_COMB_LNA1:
+ antcomb->rssi_lna1 = alt_rssi_avg;
+ antcomb->rssi_lna2 = main_rssi_avg;
+ antcomb->scan = true;
+ /* set to A+B */
+ div_ant_conf.main_lna_conf = ATH_ANT_DIV_COMB_LNA2;
+ div_ant_conf.alt_lna_conf =
+ ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
+ break;
+ case ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2:
+ antcomb->rssi_add = alt_rssi_avg;
+ antcomb->scan = true;
+ /* set to A-B */
+ div_ant_conf.alt_lna_conf =
+ ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
+ break;
+ case ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2:
+ antcomb->rssi_sub = alt_rssi_avg;
+ antcomb->scan = false;
+ if (antcomb->rssi_lna2 >
+ (antcomb->rssi_lna1 +
+ ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA)) {
+ /* use LNA2 as main LNA */
+ if ((antcomb->rssi_add > antcomb->rssi_lna1) &&
+ (antcomb->rssi_add > antcomb->rssi_sub)) {
+ /* set to A+B */
+ div_ant_conf.main_lna_conf =
+ ATH_ANT_DIV_COMB_LNA2;
+ div_ant_conf.alt_lna_conf =
+ ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
+ } else if (antcomb->rssi_sub >
+ antcomb->rssi_lna1) {
+ /* set to A-B */
+ div_ant_conf.main_lna_conf =
+ ATH_ANT_DIV_COMB_LNA2;
+ div_ant_conf.alt_lna_conf =
+ ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
+ } else {
+ /* set to LNA1 */
+ div_ant_conf.main_lna_conf =
+ ATH_ANT_DIV_COMB_LNA2;
+ div_ant_conf.alt_lna_conf =
+ ATH_ANT_DIV_COMB_LNA1;
+ }
+ } else {
+ /* use LNA1 as main LNA */
+ if ((antcomb->rssi_add > antcomb->rssi_lna2) &&
+ (antcomb->rssi_add > antcomb->rssi_sub)) {
+ /* set to A+B */
+ div_ant_conf.main_lna_conf =
+ ATH_ANT_DIV_COMB_LNA1;
+ div_ant_conf.alt_lna_conf =
+ ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
+ } else if (antcomb->rssi_sub >
+ antcomb->rssi_lna1) {
+ /* set to A-B */
+ div_ant_conf.main_lna_conf =
+ ATH_ANT_DIV_COMB_LNA1;
+ div_ant_conf.alt_lna_conf =
+ ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
+ } else {
+ /* set to LNA2 */
+ div_ant_conf.main_lna_conf =
+ ATH_ANT_DIV_COMB_LNA1;
+ div_ant_conf.alt_lna_conf =
+ ATH_ANT_DIV_COMB_LNA2;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ } else {
+ if (!antcomb->alt_good) {
+ antcomb->scan_not_start = false;
+ /* Set alt to another LNA */
+ if (curr_main_set == ATH_ANT_DIV_COMB_LNA2) {
+ div_ant_conf.main_lna_conf =
+ ATH_ANT_DIV_COMB_LNA2;
+ div_ant_conf.alt_lna_conf =
+ ATH_ANT_DIV_COMB_LNA1;
+ } else if (curr_main_set == ATH_ANT_DIV_COMB_LNA1) {
+ div_ant_conf.main_lna_conf =
+ ATH_ANT_DIV_COMB_LNA1;
+ div_ant_conf.alt_lna_conf =
+ ATH_ANT_DIV_COMB_LNA2;
+ }
+ goto div_comb_done;
+ }
+ }
+
+ ath_select_ant_div_from_quick_scan(antcomb, &div_ant_conf,
+ main_rssi_avg, alt_rssi_avg,
+ alt_ratio);
+
+ antcomb->quick_scan_cnt++;
+
+div_comb_done:
+ ath_ant_div_conf_fast_divbias(&div_ant_conf);
+
+ ath9k_hw_antdiv_comb_conf_set(sc->sc_ah, &div_ant_conf);
+
+ antcomb->scan_start_time = jiffies;
+ antcomb->total_pkt_count = 0;
+ antcomb->main_total_rssi = 0;
+ antcomb->alt_total_rssi = 0;
+ antcomb->main_recv_cnt = 0;
+ antcomb->alt_recv_cnt = 0;
+}
+
int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
{
struct ath_buf *bf;
@@ -1096,6 +1646,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
u8 rx_status_len = ah->caps.rx_status_len;
u64 tsf = 0;
u32 tsf_lower = 0;
+ unsigned long flags;
if (edma)
dma_type = DMA_BIDIRECTIONAL;
@@ -1186,12 +1737,12 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
bf->bf_buf_addr))) {
dev_kfree_skb_any(requeue_skb);
bf->bf_mpdu = NULL;
+ bf->bf_buf_addr = 0;
ath_print(common, ATH_DBG_FATAL,
"dma_mapping_error() on RX\n");
ath_rx_send_to_mac80211(hw, sc, skb, rxs);
break;
}
- bf->bf_dmacontext = bf->bf_buf_addr;
/*
* change the default rx antenna if rx diversity chooses the
@@ -1204,11 +1755,16 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
sc->rx.rxotherant = 0;
}
+ spin_lock_irqsave(&sc->sc_pm_lock, flags);
if (unlikely(ath9k_check_auto_sleep(sc) ||
(sc->ps_flags & (PS_WAIT_FOR_BEACON |
PS_WAIT_FOR_CAB |
PS_WAIT_FOR_PSPOLL_DATA))))
ath_rx_ps(sc, skb);
+ spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
+
+ if (ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB)
+ ath_ant_comb_scan(sc, &rs);
ath_rx_send_to_mac80211(hw, sc, skb, rxs);
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h
index d01c4adab8d6..42976b0a01c1 100644
--- a/drivers/net/wireless/ath/ath9k/reg.h
+++ b/drivers/net/wireless/ath/ath9k/reg.h
@@ -107,12 +107,6 @@
#define AR_RXCFG_DMASZ_256B 6
#define AR_RXCFG_DMASZ_512B 7
-#define AR_MIBC 0x0040
-#define AR_MIBC_COW 0x00000001
-#define AR_MIBC_FMC 0x00000002
-#define AR_MIBC_CMC 0x00000004
-#define AR_MIBC_MCS 0x00000008
-
#define AR_TOPS 0x0044
#define AR_TOPS_MASK 0x0000FFFF
@@ -819,49 +813,23 @@
((_ah)->hw_version.macRev == AR_SREV_REVISION_9160_11))
#define AR_SREV_9280(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9280))
-#define AR_SREV_9280_10_OR_LATER(_ah) \
+#define AR_SREV_9280_20_OR_LATER(_ah) \
(((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9280))
#define AR_SREV_9280_20(_ah) \
- (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9280) && \
- ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9280_20))
-#define AR_SREV_9280_20_OR_LATER(_ah) \
- (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9280) || \
- (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9280) && \
- ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9280_20)))
+ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9280))
#define AR_SREV_9285(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9285))
-#define AR_SREV_9285_10_OR_LATER(_ah) \
- (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9285))
-#define AR_SREV_9285_11(_ah) \
- (AR_SREV_9285(ah) && \
- ((_ah)->hw_version.macRev == AR_SREV_REVISION_9285_11))
-#define AR_SREV_9285_11_OR_LATER(_ah) \
- (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9285) || \
- (AR_SREV_9285(ah) && ((_ah)->hw_version.macRev >= \
- AR_SREV_REVISION_9285_11)))
-#define AR_SREV_9285_12(_ah) \
- (AR_SREV_9285(ah) && \
- ((_ah)->hw_version.macRev == AR_SREV_REVISION_9285_12))
#define AR_SREV_9285_12_OR_LATER(_ah) \
- (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9285) || \
- (AR_SREV_9285(ah) && ((_ah)->hw_version.macRev >= \
- AR_SREV_REVISION_9285_12)))
+ (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9285))
#define AR_SREV_9287(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287))
-#define AR_SREV_9287_10_OR_LATER(_ah) \
+#define AR_SREV_9287_11_OR_LATER(_ah) \
(((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9287))
-#define AR_SREV_9287_10(_ah) \
- (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \
- ((_ah)->hw_version.macRev == AR_SREV_REVISION_9287_10))
#define AR_SREV_9287_11(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \
((_ah)->hw_version.macRev == AR_SREV_REVISION_9287_11))
-#define AR_SREV_9287_11_OR_LATER(_ah) \
- (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9287) || \
- (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \
- ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9287_11)))
#define AR_SREV_9287_12(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \
((_ah)->hw_version.macRev == AR_SREV_REVISION_9287_12))
@@ -885,9 +853,6 @@
#define AR_SREV_9300(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300))
-#define AR_SREV_9300_20(_ah) \
- (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300) && \
- ((_ah)->hw_version.macRev == AR_SREV_REVISION_9300_20))
#define AR_SREV_9300_20_OR_LATER(_ah) \
(((_ah)->hw_version.macVersion > AR_SREV_VERSION_9300) || \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300) && \
@@ -1550,11 +1515,6 @@ enum {
#define AR_TPC_CHIRP 0x003f0000
#define AR_TPC_CHIRP_S 0x16
-#define AR_TFCNT 0x80ec
-#define AR_RFCNT 0x80f0
-#define AR_RCCNT 0x80f4
-#define AR_CCCNT 0x80f8
-
#define AR_QUIET1 0x80fc
#define AR_QUIET1_NEXT_QUIET_S 0
#define AR_QUIET1_NEXT_QUIET_M 0x0000ffff
diff --git a/drivers/net/wireless/ath/ath9k/virtual.c b/drivers/net/wireless/ath/ath9k/virtual.c
index fd20241f57d8..ec7cf5ee56bc 100644
--- a/drivers/net/wireless/ath/ath9k/virtual.c
+++ b/drivers/net/wireless/ath/ath9k/virtual.c
@@ -19,45 +19,36 @@
#include "ath9k.h"
struct ath9k_vif_iter_data {
- int count;
- u8 *addr;
+ const u8 *hw_macaddr;
+ u8 mask[ETH_ALEN];
};
static void ath9k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
{
struct ath9k_vif_iter_data *iter_data = data;
- u8 *nbuf;
-
- nbuf = krealloc(iter_data->addr, (iter_data->count + 1) * ETH_ALEN,
- GFP_ATOMIC);
- if (nbuf == NULL)
- return;
+ int i;
- memcpy(nbuf + iter_data->count * ETH_ALEN, mac, ETH_ALEN);
- iter_data->addr = nbuf;
- iter_data->count++;
+ for (i = 0; i < ETH_ALEN; i++)
+ iter_data->mask[i] &= ~(iter_data->hw_macaddr[i] ^ mac[i]);
}
-void ath9k_set_bssid_mask(struct ieee80211_hw *hw)
+void ath9k_set_bssid_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
struct ath_wiphy *aphy = hw->priv;
struct ath_softc *sc = aphy->sc;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath9k_vif_iter_data iter_data;
- int i, j;
- u8 mask[ETH_ALEN];
+ int i;
/*
- * Add primary MAC address even if it is not in active use since it
- * will be configured to the hardware as the starting point and the
- * BSSID mask will need to be changed if another address is active.
+ * Use the hardware MAC address as reference, the hardware uses it
+ * together with the BSSID mask when matching addresses.
*/
- iter_data.addr = kmalloc(ETH_ALEN, GFP_ATOMIC);
- if (iter_data.addr) {
- memcpy(iter_data.addr, common->macaddr, ETH_ALEN);
- iter_data.count = 1;
- } else
- iter_data.count = 0;
+ iter_data.hw_macaddr = common->macaddr;
+ memset(&iter_data.mask, 0xff, ETH_ALEN);
+
+ if (vif)
+ ath9k_vif_iter(&iter_data, vif->addr, vif);
/* Get list of all active MAC addresses */
spin_lock_bh(&sc->wiphy_lock);
@@ -71,31 +62,7 @@ void ath9k_set_bssid_mask(struct ieee80211_hw *hw)
}
spin_unlock_bh(&sc->wiphy_lock);
- /* Generate an address mask to cover all active addresses */
- memset(mask, 0, ETH_ALEN);
- for (i = 0; i < iter_data.count; i++) {
- u8 *a1 = iter_data.addr + i * ETH_ALEN;
- for (j = i + 1; j < iter_data.count; j++) {
- u8 *a2 = iter_data.addr + j * ETH_ALEN;
- mask[0] |= a1[0] ^ a2[0];
- mask[1] |= a1[1] ^ a2[1];
- mask[2] |= a1[2] ^ a2[2];
- mask[3] |= a1[3] ^ a2[3];
- mask[4] |= a1[4] ^ a2[4];
- mask[5] |= a1[5] ^ a2[5];
- }
- }
-
- kfree(iter_data.addr);
-
- /* Invert the mask and configure hardware */
- common->bssidmask[0] = ~mask[0];
- common->bssidmask[1] = ~mask[1];
- common->bssidmask[2] = ~mask[2];
- common->bssidmask[3] = ~mask[3];
- common->bssidmask[4] = ~mask[4];
- common->bssidmask[5] = ~mask[5];
-
+ memcpy(common->bssidmask, iter_data.mask, ETH_ALEN);
ath_hw_setbssidmask(common);
}
diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c
index 6260faa658a2..93a8bda09c25 100644
--- a/drivers/net/wireless/ath/ath9k/wmi.c
+++ b/drivers/net/wireless/ath/ath9k/wmi.c
@@ -85,6 +85,8 @@ static const char *wmi_cmd_to_name(enum wmi_cmd_id wmi_cmd)
return "WMI_TGT_DETACH_CMDID";
case WMI_TGT_TXQ_ENABLE_CMDID:
return "WMI_TGT_TXQ_ENABLE_CMDID";
+ case WMI_AGGR_LIMIT_CMD:
+ return "WMI_AGGR_LIMIT_CMD";
}
return "Bogus";
@@ -122,55 +124,11 @@ void ath9k_wmi_tasklet(unsigned long data)
{
struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data;
struct ath_common *common = ath9k_hw_common(priv->ah);
- struct wmi_cmd_hdr *hdr;
- struct wmi_swba *swba_hdr;
- enum wmi_event_id event;
- struct sk_buff *skb;
- void *wmi_event;
- unsigned long flags;
-#ifdef CONFIG_ATH9K_HTC_DEBUGFS
- __be32 txrate;
-#endif
- spin_lock_irqsave(&priv->wmi->wmi_lock, flags);
- skb = priv->wmi->wmi_skb;
- spin_unlock_irqrestore(&priv->wmi->wmi_lock, flags);
+ ath_print(common, ATH_DBG_WMI, "SWBA Event received\n");
- hdr = (struct wmi_cmd_hdr *) skb->data;
- event = be16_to_cpu(hdr->command_id);
- wmi_event = skb_pull(skb, sizeof(struct wmi_cmd_hdr));
+ ath9k_htc_swba(priv, priv->wmi->beacon_pending);
- ath_print(common, ATH_DBG_WMI,
- "WMI Event: 0x%x\n", event);
-
- switch (event) {
- case WMI_TGT_RDY_EVENTID:
- break;
- case WMI_SWBA_EVENTID:
- swba_hdr = (struct wmi_swba *) wmi_event;
- ath9k_htc_swba(priv, swba_hdr->beacon_pending);
- break;
- case WMI_FATAL_EVENTID:
- break;
- case WMI_TXTO_EVENTID:
- break;
- case WMI_BMISS_EVENTID:
- break;
- case WMI_WLAN_TXCOMP_EVENTID:
- break;
- case WMI_DELBA_EVENTID:
- break;
- case WMI_TXRATE_EVENTID:
-#ifdef CONFIG_ATH9K_HTC_DEBUGFS
- txrate = ((struct wmi_event_txrate *)wmi_event)->txrate;
- priv->debug.txrate = be32_to_cpu(txrate);
-#endif
- break;
- default:
- break;
- }
-
- kfree_skb(skb);
}
static void ath9k_wmi_rsp_callback(struct wmi *wmi, struct sk_buff *skb)
@@ -189,6 +147,10 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb,
struct wmi *wmi = (struct wmi *) priv;
struct wmi_cmd_hdr *hdr;
u16 cmd_id;
+ void *wmi_event;
+#ifdef CONFIG_ATH9K_HTC_DEBUGFS
+ __be32 txrate;
+#endif
if (unlikely(wmi->stopped))
goto free_skb;
@@ -197,10 +159,22 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb,
cmd_id = be16_to_cpu(hdr->command_id);
if (cmd_id & 0x1000) {
- spin_lock(&wmi->wmi_lock);
- wmi->wmi_skb = skb;
- spin_unlock(&wmi->wmi_lock);
- tasklet_schedule(&wmi->drv_priv->wmi_tasklet);
+ wmi_event = skb_pull(skb, sizeof(struct wmi_cmd_hdr));
+ switch (cmd_id) {
+ case WMI_SWBA_EVENTID:
+ wmi->beacon_pending = *(u8 *)wmi_event;
+ tasklet_schedule(&wmi->drv_priv->wmi_tasklet);
+ break;
+ case WMI_TXRATE_EVENTID:
+#ifdef CONFIG_ATH9K_HTC_DEBUGFS
+ txrate = ((struct wmi_event_txrate *)wmi_event)->txrate;
+ wmi->drv_priv->debug.txrate = be32_to_cpu(txrate);
+#endif
+ break;
+ default:
+ break;
+ }
+ kfree_skb(skb);
return;
}
diff --git a/drivers/net/wireless/ath/ath9k/wmi.h b/drivers/net/wireless/ath/ath9k/wmi.h
index 765db5faa2d3..ac61074af8ac 100644
--- a/drivers/net/wireless/ath/ath9k/wmi.h
+++ b/drivers/net/wireless/ath/ath9k/wmi.h
@@ -31,10 +31,6 @@ struct wmi_cmd_hdr {
__be16 seq_no;
} __packed;
-struct wmi_swba {
- u8 beacon_pending;
-} __packed;
-
enum wmi_cmd_id {
WMI_ECHO_CMDID = 0x0001,
WMI_ACCESS_MEMORY_CMDID,
@@ -71,6 +67,7 @@ enum wmi_cmd_id {
WMI_TX_AGGR_ENABLE_CMDID,
WMI_TGT_DETACH_CMDID,
WMI_TGT_TXQ_ENABLE_CMDID,
+ WMI_AGGR_LIMIT_CMD = 0x0026,
};
enum wmi_event_id {
@@ -103,7 +100,7 @@ struct wmi {
u32 cmd_rsp_len;
bool stopped;
- struct sk_buff *wmi_skb;
+ u8 beacon_pending;
spinlock_t wmi_lock;
atomic_t mwrite_cnt;
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 4dda14e36227..d077186da870 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -61,6 +61,8 @@ static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf,
struct ath_tx_status *ts, int txok);
static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts,
int nbad, int txok, bool update_rc);
+static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
+ int seqno);
enum {
MCS_HT20,
@@ -143,18 +145,23 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum];
struct ath_buf *bf;
struct list_head bf_head;
- INIT_LIST_HEAD(&bf_head);
+ struct ath_tx_status ts;
- WARN_ON(!tid->paused);
+ INIT_LIST_HEAD(&bf_head);
+ memset(&ts, 0, sizeof(ts));
spin_lock_bh(&txq->axq_lock);
- tid->paused = false;
while (!list_empty(&tid->buf_q)) {
bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
- BUG_ON(bf_isretried(bf));
list_move_tail(&bf->list, &bf_head);
- ath_tx_send_ht_normal(sc, txq, tid, &bf_head);
+
+ if (bf_isretried(bf)) {
+ ath_tx_update_baw(sc, tid, bf->bf_seqno);
+ ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
+ } else {
+ ath_tx_send_ht_normal(sc, txq, tid, &bf_head);
+ }
}
spin_unlock_bh(&txq->axq_lock);
@@ -168,9 +175,9 @@ static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
index = ATH_BA_INDEX(tid->seq_start, seqno);
cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1);
- tid->tx_buf[cindex] = NULL;
+ __clear_bit(cindex, tid->tx_buf);
- while (tid->baw_head != tid->baw_tail && !tid->tx_buf[tid->baw_head]) {
+ while (tid->baw_head != tid->baw_tail && !test_bit(tid->baw_head, tid->tx_buf)) {
INCR(tid->seq_start, IEEE80211_SEQ_MAX);
INCR(tid->baw_head, ATH_TID_MAX_BUFS);
}
@@ -186,9 +193,7 @@ static void ath_tx_addto_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
index = ATH_BA_INDEX(tid->seq_start, bf->bf_seqno);
cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1);
-
- BUG_ON(tid->tx_buf[cindex] != NULL);
- tid->tx_buf[cindex] = bf;
+ __set_bit(cindex, tid->tx_buf);
if (index >= ((tid->baw_tail - tid->baw_head) &
(ATH_TID_MAX_BUFS - 1))) {
@@ -289,7 +294,6 @@ static struct ath_buf* ath_clone_txbuf(struct ath_softc *sc, struct ath_buf *bf)
tbf->bf_buf_addr = bf->bf_buf_addr;
memcpy(tbf->bf_desc, bf->bf_desc, sc->sc_ah->caps.tx_desc_len);
tbf->bf_state = bf->bf_state;
- tbf->bf_dmacontext = bf->bf_dmacontext;
return tbf;
}
@@ -312,6 +316,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0;
bool rc_update = true;
struct ieee80211_tx_rate rates[4];
+ int nframes;
skb = bf->bf_mpdu;
hdr = (struct ieee80211_hdr *)skb->data;
@@ -320,11 +325,11 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
hw = bf->aphy->hw;
memcpy(rates, tx_info->control.rates, sizeof(rates));
+ nframes = bf->bf_nframes;
rcu_read_lock();
- /* XXX: use ieee80211_find_sta! */
- sta = ieee80211_find_sta_by_hw(hw, hdr->addr1);
+ sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr1, hdr->addr2);
if (!sta) {
rcu_read_unlock();
@@ -337,7 +342,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
!bf->bf_stale || bf_next != NULL)
list_move_tail(&bf->list, &bf_head);
- ath_tx_rc_status(bf, ts, 0, 0, false);
+ ath_tx_rc_status(bf, ts, 1, 0, false);
ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
0, 0);
@@ -431,7 +436,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
list_move_tail(&bf->list, &bf_head);
}
- if (!txpending) {
+ if (!txpending || (tid->state & AGGR_CLEANUP)) {
/*
* complete the acked-ones/xretried ones; update
* block-ack window
@@ -442,6 +447,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) {
memcpy(tx_info->control.rates, rates, sizeof(rates));
+ bf->bf_nframes = nframes;
ath_tx_rc_status(bf, ts, nbad, txok, true);
rc_update = false;
} else {
@@ -510,15 +516,12 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
}
if (tid->state & AGGR_CLEANUP) {
+ ath_tx_flush_tid(sc, tid);
+
if (tid->baw_head == tid->baw_tail) {
tid->state &= ~AGGR_ADDBA_COMPLETE;
tid->state &= ~AGGR_CLEANUP;
-
- /* send buffered frames as singles */
- ath_tx_flush_tid(sc, tid);
}
- rcu_read_unlock();
- return;
}
rcu_read_unlock();
@@ -785,17 +788,23 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
status != ATH_AGGR_BAW_CLOSED);
}
-void ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
- u16 tid, u16 *ssn)
+int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
+ u16 tid, u16 *ssn)
{
struct ath_atx_tid *txtid;
struct ath_node *an;
an = (struct ath_node *)sta->drv_priv;
txtid = ATH_AN_2_TID(an, tid);
+
+ if (txtid->state & (AGGR_CLEANUP | AGGR_ADDBA_COMPLETE))
+ return -EAGAIN;
+
txtid->state |= AGGR_ADDBA_PROGRESS;
txtid->paused = true;
*ssn = txtid->seq_start;
+
+ return 0;
}
void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
@@ -803,12 +812,6 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
struct ath_node *an = (struct ath_node *)sta->drv_priv;
struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid);
struct ath_txq *txq = &sc->tx.txq[txtid->ac->qnum];
- struct ath_tx_status ts;
- struct ath_buf *bf;
- struct list_head bf_head;
-
- memset(&ts, 0, sizeof(ts));
- INIT_LIST_HEAD(&bf_head);
if (txtid->state & AGGR_CLEANUP)
return;
@@ -818,31 +821,22 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
return;
}
- /* drop all software retried frames and mark this TID */
spin_lock_bh(&txq->axq_lock);
txtid->paused = true;
- while (!list_empty(&txtid->buf_q)) {
- bf = list_first_entry(&txtid->buf_q, struct ath_buf, list);
- if (!bf_isretried(bf)) {
- /*
- * NB: it's based on the assumption that
- * software retried frame will always stay
- * at the head of software queue.
- */
- break;
- }
- list_move_tail(&bf->list, &bf_head);
- ath_tx_update_baw(sc, txtid, bf->bf_seqno);
- ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
- }
- spin_unlock_bh(&txq->axq_lock);
- if (txtid->baw_head != txtid->baw_tail) {
+ /*
+ * If frames are still being transmitted for this TID, they will be
+ * cleaned up during tx completion. To prevent race conditions, this
+ * TID can only be reused after all in-progress subframes have been
+ * completed.
+ */
+ if (txtid->baw_head != txtid->baw_tail)
txtid->state |= AGGR_CLEANUP;
- } else {
+ else
txtid->state &= ~AGGR_ADDBA_COMPLETE;
- ath_tx_flush_tid(sc, txtid);
- }
+ spin_unlock_bh(&txq->axq_lock);
+
+ ath_tx_flush_tid(sc, txtid);
}
void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
@@ -862,20 +856,6 @@ void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid
}
}
-bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno)
-{
- struct ath_atx_tid *txtid;
-
- if (!(sc->sc_flags & SC_OP_TXAGGR))
- return false;
-
- txtid = ATH_AN_2_TID(an, tidno);
-
- if (!(txtid->state & (AGGR_ADDBA_COMPLETE | AGGR_ADDBA_PROGRESS)))
- return true;
- return false;
-}
-
/********************/
/* Queue Management */
/********************/
@@ -1407,22 +1387,6 @@ static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb)
return htype;
}
-static int get_hw_crypto_keytype(struct sk_buff *skb)
-{
- struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-
- if (tx_info->control.hw_key) {
- if (tx_info->control.hw_key->alg == ALG_WEP)
- return ATH9K_KEY_TYPE_WEP;
- else if (tx_info->control.hw_key->alg == ALG_TKIP)
- return ATH9K_KEY_TYPE_TKIP;
- else if (tx_info->control.hw_key->alg == ALG_CCMP)
- return ATH9K_KEY_TYPE_AES;
- }
-
- return ATH9K_KEY_TYPE_CLEAR;
-}
-
static void assign_aggr_tid_seqno(struct sk_buff *skb,
struct ath_buf *bf)
{
@@ -1661,7 +1625,7 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf,
bf->bf_state.bfs_paprd_timestamp = jiffies;
bf->bf_flags = setup_tx_flags(skb, use_ldpc);
- bf->bf_keytype = get_hw_crypto_keytype(skb);
+ bf->bf_keytype = ath9k_cmn_get_hw_crypto_keytype(skb);
if (bf->bf_keytype != ATH9K_KEY_TYPE_CLEAR) {
bf->bf_frmlen += tx_info->control.hw_key->icv_len;
bf->bf_keyix = tx_info->control.hw_key->hw_key_idx;
@@ -1675,24 +1639,16 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf,
bf->bf_mpdu = skb;
- bf->bf_dmacontext = dma_map_single(sc->dev, skb->data,
- skb->len, DMA_TO_DEVICE);
- if (unlikely(dma_mapping_error(sc->dev, bf->bf_dmacontext))) {
+ bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
+ skb->len, DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) {
bf->bf_mpdu = NULL;
+ bf->bf_buf_addr = 0;
ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL,
"dma_mapping_error() on TX\n");
return -ENOMEM;
}
- bf->bf_buf_addr = bf->bf_dmacontext;
-
- /* tag if this is a nullfunc frame to enable PS when AP acks it */
- if (ieee80211_is_nullfunc(fc) && ieee80211_has_pm(fc)) {
- bf->bf_isnullfunc = true;
- sc->ps_flags &= ~PS_NULLFUNC_COMPLETED;
- } else
- bf->bf_isnullfunc = false;
-
bf->bf_tx_aborted = false;
return 0;
@@ -1956,7 +1912,8 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
tx_flags |= ATH_TX_XRETRY;
}
- dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE);
+ dma_unmap_single(sc->dev, bf->bf_buf_addr, skb->len, DMA_TO_DEVICE);
+ bf->bf_buf_addr = 0;
if (bf->bf_state.bfs_paprd) {
if (time_after(jiffies,
@@ -1966,9 +1923,13 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
else
complete(&sc->paprd_complete);
} else {
- ath_tx_complete(sc, skb, bf->aphy, tx_flags);
ath_debug_stat_tx(sc, txq, bf, ts);
+ ath_tx_complete(sc, skb, bf->aphy, tx_flags);
}
+ /* At this point, skb (bf->bf_mpdu) is consumed...make sure we don't
+ * accidentally reference it later.
+ */
+ bf->bf_mpdu = NULL;
/*
* Return the list of ath_buf of this mpdu to free queue
@@ -2024,9 +1985,15 @@ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts,
if (ts->ts_status & ATH9K_TXERR_FILT)
tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
- if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && update_rc)
+ if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && update_rc) {
tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
+ BUG_ON(nbad > bf->bf_nframes);
+
+ tx_info->status.ampdu_len = bf->bf_nframes;
+ tx_info->status.ampdu_ack_len = bf->bf_nframes - nbad;
+ }
+
if ((ts->ts_status & ATH9K_TXERR_FILT) == 0 &&
(bf->bf_flags & ATH9K_TXDESC_NOACK) == 0 && update_rc) {
if (ieee80211_is_data(hdr->frame_control)) {
@@ -2036,8 +2003,6 @@ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts,
if ((ts->ts_status & ATH9K_TXERR_XRETRY) ||
(ts->ts_status & ATH9K_TXERR_FIFO))
tx_info->pad[0] |= ATH_TX_INFO_XRETRY;
- tx_info->status.ampdu_len = bf->bf_nframes;
- tx_info->status.ampdu_ack_len = bf->bf_nframes - nbad;
}
}
@@ -2120,18 +2085,6 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
}
/*
- * We now know the nullfunc frame has been ACKed so we
- * can disable RX.
- */
- if (bf->bf_isnullfunc &&
- (ts.ts_status & ATH9K_TX_ACKED)) {
- if ((sc->ps_flags & PS_ENABLED))
- ath9k_enable_ps(sc);
- else
- sc->ps_flags |= PS_NULLFUNC_COMPLETED;
- }
-
- /*
* Remove ath_buf's of the same transmit unit from txq,
* however leave the last descriptor back as the holding
* descriptor for hw.
@@ -2159,7 +2112,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
*/
if (ts.ts_status & ATH9K_TXERR_XRETRY)
bf->bf_state.bf_type |= BUF_XRETRY;
- ath_tx_rc_status(bf, &ts, 0, txok, true);
+ ath_tx_rc_status(bf, &ts, txok ? 0 : 1, txok, true);
}
if (bf_isampdu(bf))
@@ -2274,21 +2227,10 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
txok = !(txs.ts_status & ATH9K_TXERR_MASK);
- /*
- * Make sure null func frame is acked before configuring
- * hw into ps mode.
- */
- if (bf->bf_isnullfunc && txok) {
- if ((sc->ps_flags & PS_ENABLED))
- ath9k_enable_ps(sc);
- else
- sc->ps_flags |= PS_NULLFUNC_COMPLETED;
- }
-
if (!bf_isampdu(bf)) {
if (txs.ts_status & ATH9K_TXERR_XRETRY)
bf->bf_state.bf_type |= BUF_XRETRY;
- ath_tx_rc_status(bf, &txs, 0, txok, true);
+ ath_tx_rc_status(bf, &txs, txok ? 0 : 1, txok, true);
}
if (bf_isampdu(bf))
diff --git a/drivers/net/wireless/ath/carl9170/Kconfig b/drivers/net/wireless/ath/carl9170/Kconfig
new file mode 100644
index 000000000000..2d1b821b440d
--- /dev/null
+++ b/drivers/net/wireless/ath/carl9170/Kconfig
@@ -0,0 +1,41 @@
+config CARL9170
+ tristate "Linux Community AR9170 802.11n USB support"
+ depends on USB && MAC80211 && EXPERIMENTAL
+ select FW_LOADER
+ select CRC32
+ help
+ This is another driver for the Atheros "otus" 802.11n USB devices.
+
+ This driver provides more features than the original,
+ but it needs a special firmware (carl9170-1.fw) to do that.
+
+ The firmware can be downloaded from our wiki here:
+ <http://wireless.kernel.org/en/users/Drivers/carl9170>
+
+ If you choose to build a module, it'll be called carl9170.
+
+config CARL9170_LEDS
+ bool "SoftLED Support"
+ depends on CARL9170
+ select MAC80211_LEDS
+ select LEDS_CLASS
+ select NEW_LEDS
+ default y
+ help
+ This option is necessary, if you want your device' LEDs to blink
+
+ Say Y, unless you need the LEDs for firmware debugging.
+
+config CARL9170_DEBUGFS
+ bool "DebugFS Support"
+ depends on CARL9170 && DEBUG_FS && MAC80211_DEBUGFS
+ default n
+ help
+ Export several driver and device internals to user space.
+
+ Say N.
+
+config CARL9170_WPC
+ bool
+ depends on CARL9170 && (INPUT = y || INPUT = CARL9170)
+ default y
diff --git a/drivers/net/wireless/ath/carl9170/Makefile b/drivers/net/wireless/ath/carl9170/Makefile
new file mode 100644
index 000000000000..f64ed76af8ad
--- /dev/null
+++ b/drivers/net/wireless/ath/carl9170/Makefile
@@ -0,0 +1,4 @@
+carl9170-objs := main.o usb.o cmd.o mac.o phy.o led.o fw.o tx.o rx.o
+carl9170-$(CONFIG_CARL9170_DEBUGFS) += debug.o
+
+obj-$(CONFIG_CARL9170) += carl9170.o
diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h
new file mode 100644
index 000000000000..6cf0c9ef47aa
--- /dev/null
+++ b/drivers/net/wireless/ath/carl9170/carl9170.h
@@ -0,0 +1,628 @@
+/*
+ * Atheros CARL9170 driver
+ *
+ * Driver specific definitions
+ *
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ * Copyright (c) 2007-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef __CARL9170_H
+#define __CARL9170_H
+
+#include <linux/kernel.h>
+#include <linux/firmware.h>
+#include <linux/completion.h>
+#include <linux/spinlock.h>
+#include <net/cfg80211.h>
+#include <net/mac80211.h>
+#include <linux/usb.h>
+#ifdef CONFIG_CARL9170_LEDS
+#include <linux/leds.h>
+#endif /* CONFIG_CARL170_LEDS */
+#ifdef CONFIG_CARL9170_WPC
+#include <linux/input.h>
+#endif /* CONFIG_CARL9170_WPC */
+#include "eeprom.h"
+#include "wlan.h"
+#include "hw.h"
+#include "fwdesc.h"
+#include "fwcmd.h"
+#include "../regd.h"
+
+#ifdef CONFIG_CARL9170_DEBUGFS
+#include "debug.h"
+#endif /* CONFIG_CARL9170_DEBUGFS */
+
+#define CARL9170FW_NAME "carl9170-1.fw"
+
+#define PAYLOAD_MAX (CARL9170_MAX_CMD_LEN / 4 - 1)
+
+enum carl9170_rf_init_mode {
+ CARL9170_RFI_NONE,
+ CARL9170_RFI_WARM,
+ CARL9170_RFI_COLD,
+};
+
+#define CARL9170_MAX_RX_BUFFER_SIZE 8192
+
+enum carl9170_device_state {
+ CARL9170_UNKNOWN_STATE,
+ CARL9170_STOPPED,
+ CARL9170_IDLE,
+ CARL9170_STARTED,
+};
+
+#define CARL9170_NUM_TID 16
+#define WME_BA_BMP_SIZE 64
+#define CARL9170_TX_USER_RATE_TRIES 3
+
+#define WME_AC_BE 2
+#define WME_AC_BK 3
+#define WME_AC_VI 1
+#define WME_AC_VO 0
+
+#define TID_TO_WME_AC(_tid) \
+ ((((_tid) == 0) || ((_tid) == 3)) ? WME_AC_BE : \
+ (((_tid) == 1) || ((_tid) == 2)) ? WME_AC_BK : \
+ (((_tid) == 4) || ((_tid) == 5)) ? WME_AC_VI : \
+ WME_AC_VO)
+
+#define SEQ_DIFF(_start, _seq) \
+ (((_start) - (_seq)) & 0x0fff)
+#define SEQ_PREV(_seq) \
+ (((_seq) - 1) & 0x0fff)
+#define SEQ_NEXT(_seq) \
+ (((_seq) + 1) & 0x0fff)
+#define BAW_WITHIN(_start, _bawsz, _seqno) \
+ ((((_seqno) - (_start)) & 0xfff) < (_bawsz))
+
+enum carl9170_tid_state {
+ CARL9170_TID_STATE_INVALID,
+ CARL9170_TID_STATE_KILLED,
+ CARL9170_TID_STATE_SHUTDOWN,
+ CARL9170_TID_STATE_SUSPEND,
+ CARL9170_TID_STATE_PROGRESS,
+ CARL9170_TID_STATE_IDLE,
+ CARL9170_TID_STATE_XMIT,
+};
+
+#define CARL9170_BAW_BITS (2 * WME_BA_BMP_SIZE)
+#define CARL9170_BAW_SIZE (BITS_TO_LONGS(CARL9170_BAW_BITS))
+#define CARL9170_BAW_LEN (DIV_ROUND_UP(CARL9170_BAW_BITS, BITS_PER_BYTE))
+
+struct carl9170_sta_tid {
+ /* must be the first entry! */
+ struct list_head list;
+
+ /* temporary list for RCU unlink procedure */
+ struct list_head tmp_list;
+
+ /* lock for the following data structures */
+ spinlock_t lock;
+
+ unsigned int counter;
+ enum carl9170_tid_state state;
+ u8 tid; /* TID number ( 0 - 15 ) */
+ u16 max; /* max. AMPDU size */
+
+ u16 snx; /* awaiting _next_ frame */
+ u16 hsn; /* highest _queued_ sequence */
+ u16 bsn; /* base of the tx/agg bitmap */
+ unsigned long bitmap[CARL9170_BAW_SIZE];
+
+ /* Preaggregation reorder queue */
+ struct sk_buff_head queue;
+};
+
+#define CARL9170_QUEUE_TIMEOUT 256
+#define CARL9170_BUMP_QUEUE 1000
+#define CARL9170_TX_TIMEOUT 2500
+#define CARL9170_JANITOR_DELAY 128
+#define CARL9170_QUEUE_STUCK_TIMEOUT 5500
+
+#define CARL9170_NUM_TX_AGG_MAX 30
+
+/*
+ * Tradeoff between stability/latency and speed.
+ *
+ * AR9170_TXQ_DEPTH is devised by dividing the amount of available
+ * tx buffers with the size of a full ethernet frame + overhead.
+ *
+ * Naturally: The higher the limit, the faster the device CAN send.
+ * However, even a slight over-commitment at the wrong time and the
+ * hardware is doomed to send all already-queued frames at suboptimal
+ * rates. This in turn leads to an enourmous amount of unsuccessful
+ * retries => Latency goes up, whereas the throughput goes down. CRASH!
+ */
+#define CARL9170_NUM_TX_LIMIT_HARD ((AR9170_TXQ_DEPTH * 3) / 2)
+#define CARL9170_NUM_TX_LIMIT_SOFT (AR9170_TXQ_DEPTH)
+
+struct carl9170_tx_queue_stats {
+ unsigned int count;
+ unsigned int limit;
+ unsigned int len;
+};
+
+struct carl9170_vif {
+ unsigned int id;
+ struct ieee80211_vif *vif;
+};
+
+struct carl9170_vif_info {
+ struct list_head list;
+ bool active;
+ unsigned int id;
+ struct sk_buff *beacon;
+ bool enable_beacon;
+};
+
+#define AR9170_NUM_RX_URBS 16
+#define AR9170_NUM_RX_URBS_MUL 2
+#define AR9170_NUM_TX_URBS 8
+#define AR9170_NUM_RX_URBS_POOL (AR9170_NUM_RX_URBS_MUL * AR9170_NUM_RX_URBS)
+
+enum carl9170_device_features {
+ CARL9170_WPS_BUTTON = BIT(0),
+ CARL9170_ONE_LED = BIT(1),
+};
+
+#ifdef CONFIG_CARL9170_LEDS
+struct ar9170;
+
+struct carl9170_led {
+ struct ar9170 *ar;
+ struct led_classdev l;
+ char name[32];
+ unsigned int toggled;
+ bool last_state;
+ bool registered;
+};
+#endif /* CONFIG_CARL9170_LEDS */
+
+enum carl9170_restart_reasons {
+ CARL9170_RR_NO_REASON = 0,
+ CARL9170_RR_FATAL_FIRMWARE_ERROR,
+ CARL9170_RR_TOO_MANY_FIRMWARE_ERRORS,
+ CARL9170_RR_WATCHDOG,
+ CARL9170_RR_STUCK_TX,
+ CARL9170_RR_SLOW_SYSTEM,
+ CARL9170_RR_COMMAND_TIMEOUT,
+ CARL9170_RR_TOO_MANY_PHY_ERRORS,
+ CARL9170_RR_LOST_RSP,
+ CARL9170_RR_INVALID_RSP,
+ CARL9170_RR_USER_REQUEST,
+
+ __CARL9170_RR_LAST,
+};
+
+enum carl9170_erp_modes {
+ CARL9170_ERP_INVALID,
+ CARL9170_ERP_AUTO,
+ CARL9170_ERP_MAC80211,
+ CARL9170_ERP_OFF,
+ CARL9170_ERP_CTS,
+ CARL9170_ERP_RTS,
+ __CARL9170_ERP_NUM,
+};
+
+struct ar9170 {
+ struct ath_common common;
+ struct ieee80211_hw *hw;
+ struct mutex mutex;
+ enum carl9170_device_state state;
+ spinlock_t state_lock;
+ enum carl9170_restart_reasons last_reason;
+ bool registered;
+
+ /* USB */
+ struct usb_device *udev;
+ struct usb_interface *intf;
+ struct usb_anchor rx_anch;
+ struct usb_anchor rx_work;
+ struct usb_anchor rx_pool;
+ struct usb_anchor tx_wait;
+ struct usb_anchor tx_anch;
+ struct usb_anchor tx_cmd;
+ struct usb_anchor tx_err;
+ struct tasklet_struct usb_tasklet;
+ atomic_t tx_cmd_urbs;
+ atomic_t tx_anch_urbs;
+ atomic_t rx_anch_urbs;
+ atomic_t rx_work_urbs;
+ atomic_t rx_pool_urbs;
+ kernel_ulong_t features;
+
+ /* firmware settings */
+ struct completion fw_load_wait;
+ struct completion fw_boot_wait;
+ struct {
+ const struct carl9170fw_desc_head *desc;
+ const struct firmware *fw;
+ unsigned int offset;
+ unsigned int address;
+ unsigned int cmd_bufs;
+ unsigned int api_version;
+ unsigned int vif_num;
+ unsigned int err_counter;
+ unsigned int bug_counter;
+ u32 beacon_addr;
+ unsigned int beacon_max_len;
+ bool rx_stream;
+ bool tx_stream;
+ bool rx_filter;
+ unsigned int mem_blocks;
+ unsigned int mem_block_size;
+ unsigned int rx_size;
+ } fw;
+
+ /* reset / stuck frames/queue detection */
+ struct work_struct restart_work;
+ unsigned int restart_counter;
+ unsigned long queue_stop_timeout[__AR9170_NUM_TXQ];
+ unsigned long max_queue_stop_timeout[__AR9170_NUM_TXQ];
+ bool needs_full_reset;
+ atomic_t pending_restarts;
+
+ /* interface mode settings */
+ struct list_head vif_list;
+ unsigned long vif_bitmap;
+ unsigned int vifs;
+ struct carl9170_vif vif_priv[AR9170_MAX_VIRTUAL_MAC];
+
+ /* beaconing */
+ spinlock_t beacon_lock;
+ unsigned int global_pretbtt;
+ unsigned int global_beacon_int;
+ struct carl9170_vif_info *beacon_iter;
+ unsigned int beacon_enabled;
+
+ /* cryptographic engine */
+ u64 usedkeys;
+ bool rx_software_decryption;
+ bool disable_offload;
+
+ /* filter settings */
+ u64 cur_mc_hash;
+ u32 cur_filter;
+ unsigned int filter_state;
+ unsigned int rx_filter_caps;
+ bool sniffer_enabled;
+
+ /* MAC */
+ enum carl9170_erp_modes erp_mode;
+
+ /* PHY */
+ struct ieee80211_channel *channel;
+ int noise[4];
+ unsigned int chan_fail;
+ unsigned int total_chan_fail;
+ u8 heavy_clip;
+ u8 ht_settings;
+
+ /* power calibration data */
+ u8 power_5G_leg[4];
+ u8 power_2G_cck[4];
+ u8 power_2G_ofdm[4];
+ u8 power_5G_ht20[8];
+ u8 power_5G_ht40[8];
+ u8 power_2G_ht20[8];
+ u8 power_2G_ht40[8];
+
+#ifdef CONFIG_CARL9170_LEDS
+ /* LED */
+ struct delayed_work led_work;
+ struct carl9170_led leds[AR9170_NUM_LEDS];
+#endif /* CONFIG_CARL9170_LEDS */
+
+ /* qos queue settings */
+ spinlock_t tx_stats_lock;
+ struct carl9170_tx_queue_stats tx_stats[__AR9170_NUM_TXQ];
+ struct ieee80211_tx_queue_params edcf[5];
+ struct completion tx_flush;
+
+ /* CMD */
+ int cmd_seq;
+ int readlen;
+ u8 *readbuf;
+ spinlock_t cmd_lock;
+ struct completion cmd_wait;
+ union {
+ __le32 cmd_buf[PAYLOAD_MAX + 1];
+ struct carl9170_cmd cmd;
+ struct carl9170_rsp rsp;
+ };
+
+ /* statistics */
+ unsigned int tx_dropped;
+ unsigned int tx_ack_failures;
+ unsigned int tx_fcs_errors;
+ unsigned int rx_dropped;
+
+ /* EEPROM */
+ struct ar9170_eeprom eeprom;
+
+ /* tx queuing */
+ struct sk_buff_head tx_pending[__AR9170_NUM_TXQ];
+ struct sk_buff_head tx_status[__AR9170_NUM_TXQ];
+ struct delayed_work tx_janitor;
+ unsigned long tx_janitor_last_run;
+ bool tx_schedule;
+
+ /* tx ampdu */
+ struct work_struct ampdu_work;
+ spinlock_t tx_ampdu_list_lock;
+ struct carl9170_sta_tid *tx_ampdu_iter;
+ struct list_head tx_ampdu_list;
+ atomic_t tx_ampdu_upload;
+ atomic_t tx_ampdu_scheduler;
+ atomic_t tx_total_pending;
+ atomic_t tx_total_queued;
+ unsigned int tx_ampdu_list_len;
+ int current_density;
+ int current_factor;
+ bool tx_ampdu_schedule;
+
+ /* internal memory management */
+ spinlock_t mem_lock;
+ unsigned long *mem_bitmap;
+ atomic_t mem_free_blocks;
+ atomic_t mem_allocs;
+
+ /* rxstream mpdu merge */
+ struct ar9170_rx_head rx_plcp;
+ bool rx_has_plcp;
+ struct sk_buff *rx_failover;
+ int rx_failover_missing;
+
+#ifdef CONFIG_CARL9170_WPC
+ struct {
+ bool pbc_state;
+ struct input_dev *pbc;
+ char name[32];
+ char phys[32];
+ } wps;
+#endif /* CONFIG_CARL9170_WPC */
+
+#ifdef CONFIG_CARL9170_DEBUGFS
+ struct carl9170_debug debug;
+ struct dentry *debug_dir;
+#endif /* CONFIG_CARL9170_DEBUGFS */
+
+ /* PSM */
+ struct work_struct ps_work;
+ struct {
+ unsigned int dtim_counter;
+ unsigned long last_beacon;
+ unsigned long last_action;
+ unsigned long last_slept;
+ unsigned int sleep_ms;
+ unsigned int off_override;
+ bool state;
+ } ps;
+};
+
+enum carl9170_ps_off_override_reasons {
+ PS_OFF_VIF = BIT(0),
+ PS_OFF_BCN = BIT(1),
+ PS_OFF_5GHZ = BIT(2),
+};
+
+struct carl9170_ba_stats {
+ u8 ampdu_len;
+ u8 ampdu_ack_len;
+ bool clear;
+};
+
+struct carl9170_sta_info {
+ bool ht_sta;
+ unsigned int ampdu_max_len;
+ struct carl9170_sta_tid *agg[CARL9170_NUM_TID];
+ struct carl9170_ba_stats stats[CARL9170_NUM_TID];
+};
+
+struct carl9170_tx_info {
+ unsigned long timeout;
+ struct ar9170 *ar;
+ struct kref ref;
+};
+
+#define CHK_DEV_STATE(a, s) (((struct ar9170 *)a)->state >= (s))
+#define IS_INITIALIZED(a) (CHK_DEV_STATE(a, CARL9170_STOPPED))
+#define IS_ACCEPTING_CMD(a) (CHK_DEV_STATE(a, CARL9170_IDLE))
+#define IS_STARTED(a) (CHK_DEV_STATE(a, CARL9170_STARTED))
+
+static inline void __carl9170_set_state(struct ar9170 *ar,
+ enum carl9170_device_state newstate)
+{
+ ar->state = newstate;
+}
+
+static inline void carl9170_set_state(struct ar9170 *ar,
+ enum carl9170_device_state newstate)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&ar->state_lock, flags);
+ __carl9170_set_state(ar, newstate);
+ spin_unlock_irqrestore(&ar->state_lock, flags);
+}
+
+static inline void carl9170_set_state_when(struct ar9170 *ar,
+ enum carl9170_device_state min, enum carl9170_device_state newstate)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&ar->state_lock, flags);
+ if (CHK_DEV_STATE(ar, min))
+ __carl9170_set_state(ar, newstate);
+ spin_unlock_irqrestore(&ar->state_lock, flags);
+}
+
+/* exported interface */
+void *carl9170_alloc(size_t priv_size);
+int carl9170_register(struct ar9170 *ar);
+void carl9170_unregister(struct ar9170 *ar);
+void carl9170_free(struct ar9170 *ar);
+void carl9170_restart(struct ar9170 *ar, const enum carl9170_restart_reasons r);
+void carl9170_ps_check(struct ar9170 *ar);
+
+/* USB back-end */
+int carl9170_usb_open(struct ar9170 *ar);
+void carl9170_usb_stop(struct ar9170 *ar);
+void carl9170_usb_tx(struct ar9170 *ar, struct sk_buff *skb);
+void carl9170_usb_handle_tx_err(struct ar9170 *ar);
+int carl9170_exec_cmd(struct ar9170 *ar, const enum carl9170_cmd_oids,
+ u32 plen, void *payload, u32 rlen, void *resp);
+int __carl9170_exec_cmd(struct ar9170 *ar, struct carl9170_cmd *cmd,
+ const bool free_buf);
+int carl9170_usb_restart(struct ar9170 *ar);
+void carl9170_usb_reset(struct ar9170 *ar);
+
+/* MAC */
+int carl9170_init_mac(struct ar9170 *ar);
+int carl9170_set_qos(struct ar9170 *ar);
+int carl9170_update_multicast(struct ar9170 *ar, const u64 mc_hast);
+int carl9170_mod_virtual_mac(struct ar9170 *ar, const unsigned int id,
+ const u8 *mac);
+int carl9170_set_operating_mode(struct ar9170 *ar);
+int carl9170_set_beacon_timers(struct ar9170 *ar);
+int carl9170_set_dyn_sifs_ack(struct ar9170 *ar);
+int carl9170_set_rts_cts_rate(struct ar9170 *ar);
+int carl9170_set_ampdu_settings(struct ar9170 *ar);
+int carl9170_set_slot_time(struct ar9170 *ar);
+int carl9170_set_mac_rates(struct ar9170 *ar);
+int carl9170_set_hwretry_limit(struct ar9170 *ar, const u32 max_retry);
+int carl9170_update_beacon(struct ar9170 *ar, const bool submit);
+int carl9170_upload_key(struct ar9170 *ar, const u8 id, const u8 *mac,
+ const u8 ktype, const u8 keyidx, const u8 *keydata, const int keylen);
+int carl9170_disable_key(struct ar9170 *ar, const u8 id);
+
+/* RX */
+void carl9170_rx(struct ar9170 *ar, void *buf, unsigned int len);
+void carl9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len);
+
+/* TX */
+int carl9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
+void carl9170_tx_janitor(struct work_struct *work);
+void carl9170_tx_process_status(struct ar9170 *ar,
+ const struct carl9170_rsp *cmd);
+void carl9170_tx_status(struct ar9170 *ar, struct sk_buff *skb,
+ const bool success);
+void carl9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb);
+void carl9170_tx_drop(struct ar9170 *ar, struct sk_buff *skb);
+void carl9170_tx_scheduler(struct ar9170 *ar);
+void carl9170_tx_get_skb(struct sk_buff *skb);
+int carl9170_tx_put_skb(struct sk_buff *skb);
+
+/* LEDs */
+#ifdef CONFIG_CARL9170_LEDS
+int carl9170_led_register(struct ar9170 *ar);
+void carl9170_led_unregister(struct ar9170 *ar);
+#endif /* CONFIG_CARL9170_LEDS */
+int carl9170_led_init(struct ar9170 *ar);
+int carl9170_led_set_state(struct ar9170 *ar, const u32 led_state);
+
+/* PHY / RF */
+int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
+ enum nl80211_channel_type bw, enum carl9170_rf_init_mode rfi);
+int carl9170_get_noisefloor(struct ar9170 *ar);
+
+/* FW */
+int carl9170_parse_firmware(struct ar9170 *ar);
+int carl9170_fw_fix_eeprom(struct ar9170 *ar);
+
+extern struct ieee80211_rate __carl9170_ratetable[];
+extern int modparam_noht;
+
+static inline struct ar9170 *carl9170_get_priv(struct carl9170_vif *carl_vif)
+{
+ return container_of(carl_vif, struct ar9170,
+ vif_priv[carl_vif->id]);
+}
+
+static inline struct ieee80211_hdr *carl9170_get_hdr(struct sk_buff *skb)
+{
+ return (void *)((struct _carl9170_tx_superframe *)
+ skb->data)->frame_data;
+}
+
+static inline u16 get_seq_h(struct ieee80211_hdr *hdr)
+{
+ return le16_to_cpu(hdr->seq_ctrl) >> 4;
+}
+
+static inline u16 carl9170_get_seq(struct sk_buff *skb)
+{
+ return get_seq_h(carl9170_get_hdr(skb));
+}
+
+static inline u16 get_tid_h(struct ieee80211_hdr *hdr)
+{
+ return (ieee80211_get_qos_ctl(hdr))[0] & IEEE80211_QOS_CTL_TID_MASK;
+}
+
+static inline u16 carl9170_get_tid(struct sk_buff *skb)
+{
+ return get_tid_h(carl9170_get_hdr(skb));
+}
+
+static inline struct ieee80211_vif *
+carl9170_get_vif(struct carl9170_vif_info *priv)
+{
+ return container_of((void *)priv, struct ieee80211_vif, drv_priv);
+}
+
+/* Protected by ar->mutex or RCU */
+static inline struct ieee80211_vif *carl9170_get_main_vif(struct ar9170 *ar)
+{
+ struct carl9170_vif_info *cvif;
+
+ list_for_each_entry_rcu(cvif, &ar->vif_list, list) {
+ if (cvif->active)
+ return carl9170_get_vif(cvif);
+ }
+
+ return NULL;
+}
+
+static inline bool is_main_vif(struct ar9170 *ar, struct ieee80211_vif *vif)
+{
+ bool ret;
+
+ rcu_read_lock();
+ ret = (carl9170_get_main_vif(ar) == vif);
+ rcu_read_unlock();
+ return ret;
+}
+
+#endif /* __CARL9170_H */
diff --git a/drivers/net/wireless/ath/carl9170/cmd.c b/drivers/net/wireless/ath/carl9170/cmd.c
new file mode 100644
index 000000000000..c21f3364bfec
--- /dev/null
+++ b/drivers/net/wireless/ath/carl9170/cmd.c
@@ -0,0 +1,188 @@
+/*
+ * Atheros CARL9170 driver
+ *
+ * Basic HW register/memory/command access functions
+ *
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ * Copyright (c) 2007-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "carl9170.h"
+#include "cmd.h"
+
+int carl9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val)
+{
+ __le32 buf[2] = {
+ cpu_to_le32(reg),
+ cpu_to_le32(val),
+ };
+ int err;
+
+ err = carl9170_exec_cmd(ar, CARL9170_CMD_WREG, sizeof(buf),
+ (u8 *) buf, 0, NULL);
+ if (err) {
+ if (net_ratelimit()) {
+ wiphy_err(ar->hw->wiphy, "writing reg %#x "
+ "(val %#x) failed (%d)\n", reg, val, err);
+ }
+ }
+ return err;
+}
+
+int carl9170_read_mreg(struct ar9170 *ar, const int nregs,
+ const u32 *regs, u32 *out)
+{
+ int i, err;
+ __le32 *offs, *res;
+
+ /* abuse "out" for the register offsets, must be same length */
+ offs = (__le32 *)out;
+ for (i = 0; i < nregs; i++)
+ offs[i] = cpu_to_le32(regs[i]);
+
+ /* also use the same buffer for the input */
+ res = (__le32 *)out;
+
+ err = carl9170_exec_cmd(ar, CARL9170_CMD_RREG,
+ 4 * nregs, (u8 *)offs,
+ 4 * nregs, (u8 *)res);
+ if (err) {
+ if (net_ratelimit()) {
+ wiphy_err(ar->hw->wiphy, "reading regs failed (%d)\n",
+ err);
+ }
+ return err;
+ }
+
+ /* convert result to cpu endian */
+ for (i = 0; i < nregs; i++)
+ out[i] = le32_to_cpu(res[i]);
+
+ return 0;
+}
+
+int carl9170_read_reg(struct ar9170 *ar, u32 reg, u32 *val)
+{
+ return carl9170_read_mreg(ar, 1, &reg, val);
+}
+
+int carl9170_echo_test(struct ar9170 *ar, const u32 v)
+{
+ u32 echores;
+ int err;
+
+ err = carl9170_exec_cmd(ar, CARL9170_CMD_ECHO,
+ 4, (u8 *)&v,
+ 4, (u8 *)&echores);
+ if (err)
+ return err;
+
+ if (v != echores) {
+ wiphy_info(ar->hw->wiphy, "wrong echo %x != %x", v, echores);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+struct carl9170_cmd *carl9170_cmd_buf(struct ar9170 *ar,
+ const enum carl9170_cmd_oids cmd, const unsigned int len)
+{
+ struct carl9170_cmd *tmp;
+
+ tmp = kzalloc(sizeof(struct carl9170_cmd_head) + len, GFP_ATOMIC);
+ if (tmp) {
+ tmp->hdr.cmd = cmd;
+ tmp->hdr.len = len;
+ }
+
+ return tmp;
+}
+
+int carl9170_reboot(struct ar9170 *ar)
+{
+ struct carl9170_cmd *cmd;
+ int err;
+
+ cmd = carl9170_cmd_buf(ar, CARL9170_CMD_REBOOT_ASYNC, 0);
+ if (!cmd)
+ return -ENOMEM;
+
+ err = __carl9170_exec_cmd(ar, (struct carl9170_cmd *)cmd, true);
+ return err;
+}
+
+int carl9170_mac_reset(struct ar9170 *ar)
+{
+ return carl9170_exec_cmd(ar, CARL9170_CMD_SWRST,
+ 0, NULL, 0, NULL);
+}
+
+int carl9170_bcn_ctrl(struct ar9170 *ar, const unsigned int vif_id,
+ const u32 mode, const u32 addr, const u32 len)
+{
+ struct carl9170_cmd *cmd;
+
+ cmd = carl9170_cmd_buf(ar, CARL9170_CMD_BCN_CTRL_ASYNC,
+ sizeof(struct carl9170_bcn_ctrl_cmd));
+ if (!cmd)
+ return -ENOMEM;
+
+ cmd->bcn_ctrl.vif_id = cpu_to_le32(vif_id);
+ cmd->bcn_ctrl.mode = cpu_to_le32(mode);
+ cmd->bcn_ctrl.bcn_addr = cpu_to_le32(addr);
+ cmd->bcn_ctrl.bcn_len = cpu_to_le32(len);
+
+ return __carl9170_exec_cmd(ar, cmd, true);
+}
+
+int carl9170_powersave(struct ar9170 *ar, const bool ps)
+{
+ struct carl9170_cmd *cmd;
+ u32 state;
+
+ cmd = carl9170_cmd_buf(ar, CARL9170_CMD_PSM_ASYNC,
+ sizeof(struct carl9170_psm));
+ if (!cmd)
+ return -ENOMEM;
+
+ if (ps) {
+ /* Sleep until next TBTT */
+ state = CARL9170_PSM_SLEEP | 1;
+ } else {
+ /* wake up immediately */
+ state = 1;
+ }
+
+ cmd->psm.state = cpu_to_le32(state);
+ return __carl9170_exec_cmd(ar, cmd, true);
+}
diff --git a/drivers/net/wireless/ath/carl9170/cmd.h b/drivers/net/wireless/ath/carl9170/cmd.h
new file mode 100644
index 000000000000..f78728c38294
--- /dev/null
+++ b/drivers/net/wireless/ath/carl9170/cmd.h
@@ -0,0 +1,168 @@
+/*
+ * Atheros CARL9170 driver
+ *
+ * Basic HW register/memory/command access functions
+ *
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2010, Christian Lamparter <chunkeey@googlemail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ * Copyright (c) 2007-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef __CMD_H
+#define __CMD_H
+
+#include "carl9170.h"
+
+/* basic HW access */
+int carl9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val);
+int carl9170_read_reg(struct ar9170 *ar, const u32 reg, u32 *val);
+int carl9170_read_mreg(struct ar9170 *ar, const int nregs,
+ const u32 *regs, u32 *out);
+int carl9170_echo_test(struct ar9170 *ar, u32 v);
+int carl9170_reboot(struct ar9170 *ar);
+int carl9170_mac_reset(struct ar9170 *ar);
+int carl9170_powersave(struct ar9170 *ar, const bool power_on);
+int carl9170_bcn_ctrl(struct ar9170 *ar, const unsigned int vif_id,
+ const u32 mode, const u32 addr, const u32 len);
+
+static inline int carl9170_flush_cab(struct ar9170 *ar,
+ const unsigned int vif_id)
+{
+ return carl9170_bcn_ctrl(ar, vif_id, CARL9170_BCN_CTRL_DRAIN, 0, 0);
+}
+
+static inline int carl9170_rx_filter(struct ar9170 *ar,
+ const unsigned int _rx_filter)
+{
+ __le32 rx_filter = cpu_to_le32(_rx_filter);
+
+ return carl9170_exec_cmd(ar, CARL9170_CMD_RX_FILTER,
+ sizeof(rx_filter), (u8 *)&rx_filter,
+ 0, NULL);
+}
+
+struct carl9170_cmd *carl9170_cmd_buf(struct ar9170 *ar,
+ const enum carl9170_cmd_oids cmd, const unsigned int len);
+
+/*
+ * Macros to facilitate writing multiple registers in a single
+ * write-combining USB command. Note that when the first group
+ * fails the whole thing will fail without any others attempted,
+ * but you won't know which write in the group failed.
+ */
+#define carl9170_regwrite_begin(ar) \
+do { \
+ int __nreg = 0, __err = 0; \
+ struct ar9170 *__ar = ar;
+
+#define carl9170_regwrite(r, v) do { \
+ __ar->cmd_buf[2 * __nreg + 1] = cpu_to_le32(r); \
+ __ar->cmd_buf[2 * __nreg + 2] = cpu_to_le32(v); \
+ __nreg++; \
+ if ((__nreg >= PAYLOAD_MAX/2)) { \
+ if (IS_ACCEPTING_CMD(__ar)) \
+ __err = carl9170_exec_cmd(__ar, \
+ CARL9170_CMD_WREG, 8 * __nreg, \
+ (u8 *) &__ar->cmd_buf[1], 0, NULL); \
+ else \
+ goto __regwrite_out; \
+ \
+ __nreg = 0; \
+ if (__err) \
+ goto __regwrite_out; \
+ } \
+} while (0)
+
+#define carl9170_regwrite_finish() \
+__regwrite_out : \
+ if (__err == 0 && __nreg) { \
+ if (IS_ACCEPTING_CMD(__ar)) \
+ __err = carl9170_exec_cmd(__ar, \
+ CARL9170_CMD_WREG, 8 * __nreg, \
+ (u8 *) &__ar->cmd_buf[1], 0, NULL); \
+ __nreg = 0; \
+ }
+
+#define carl9170_regwrite_result() \
+ __err; \
+} while (0);
+
+
+#define carl9170_async_get_buf() \
+do { \
+ __cmd = carl9170_cmd_buf(__carl, CARL9170_CMD_WREG_ASYNC, \
+ CARL9170_MAX_CMD_PAYLOAD_LEN); \
+ if (__cmd == NULL) { \
+ __err = -ENOMEM; \
+ goto __async_regwrite_out; \
+ } \
+} while (0);
+
+#define carl9170_async_regwrite_begin(carl) \
+do { \
+ int __nreg = 0, __err = 0; \
+ struct ar9170 *__carl = carl; \
+ struct carl9170_cmd *__cmd; \
+ carl9170_async_get_buf(); \
+
+#define carl9170_async_regwrite(r, v) do { \
+ __cmd->wreg.regs[__nreg].addr = cpu_to_le32(r); \
+ __cmd->wreg.regs[__nreg].val = cpu_to_le32(v); \
+ __nreg++; \
+ if ((__nreg >= PAYLOAD_MAX/2)) { \
+ if (IS_ACCEPTING_CMD(__carl)) { \
+ __cmd->hdr.len = 8 * __nreg; \
+ __err = __carl9170_exec_cmd(__carl, __cmd, true);\
+ __cmd = NULL; \
+ carl9170_async_get_buf(); \
+ } else { \
+ goto __async_regwrite_out; \
+ } \
+ __nreg = 0; \
+ if (__err) \
+ goto __async_regwrite_out; \
+ } \
+} while (0)
+
+#define carl9170_async_regwrite_finish() \
+__async_regwrite_out : \
+ if (__err == 0 && __nreg) { \
+ __cmd->hdr.len = 8 * __nreg; \
+ if (IS_ACCEPTING_CMD(__carl)) \
+ __err = __carl9170_exec_cmd(__carl, __cmd, true);\
+ __nreg = 0; \
+ }
+
+#define carl9170_async_regwrite_result() \
+ __err; \
+} while (0);
+
+#endif /* __CMD_H */
diff --git a/drivers/net/wireless/ath/carl9170/debug.c b/drivers/net/wireless/ath/carl9170/debug.c
new file mode 100644
index 000000000000..0ac1124c2a0b
--- /dev/null
+++ b/drivers/net/wireless/ath/carl9170/debug.c
@@ -0,0 +1,902 @@
+/*
+ * Atheros CARL9170 driver
+ *
+ * debug(fs) probing
+ *
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ * Copyright (c) 2008-2009 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/seq_file.h>
+#include <linux/vmalloc.h>
+#include "carl9170.h"
+#include "cmd.h"
+
+#define ADD(buf, off, max, fmt, args...) \
+ off += snprintf(&buf[off], max - off, fmt, ##args);
+
+static int carl9170_debugfs_open(struct inode *inode, struct file *file)
+{
+ file->private_data = inode->i_private;
+ return 0;
+}
+
+struct carl9170_debugfs_fops {
+ unsigned int read_bufsize;
+ mode_t attr;
+ char *(*read)(struct ar9170 *ar, char *buf, size_t bufsize,
+ ssize_t *len);
+ ssize_t (*write)(struct ar9170 *aru, const char *buf, size_t size);
+ const struct file_operations fops;
+
+ enum carl9170_device_state req_dev_state;
+};
+
+static ssize_t carl9170_debugfs_read(struct file *file, char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ struct carl9170_debugfs_fops *dfops;
+ struct ar9170 *ar;
+ char *buf = NULL, *res_buf = NULL;
+ ssize_t ret = 0;
+ int err = 0;
+
+ if (!count)
+ return 0;
+
+ ar = file->private_data;
+
+ if (!ar)
+ return -ENODEV;
+ dfops = container_of(file->f_op, struct carl9170_debugfs_fops, fops);
+
+ if (!dfops->read)
+ return -ENOSYS;
+
+ if (dfops->read_bufsize) {
+ buf = vmalloc(dfops->read_bufsize);
+ if (!buf)
+ return -ENOMEM;
+ }
+
+ mutex_lock(&ar->mutex);
+ if (!CHK_DEV_STATE(ar, dfops->req_dev_state)) {
+ err = -ENODEV;
+ res_buf = buf;
+ goto out_free;
+ }
+
+ res_buf = dfops->read(ar, buf, dfops->read_bufsize, &ret);
+
+ if (ret > 0)
+ err = simple_read_from_buffer(userbuf, count, ppos,
+ res_buf, ret);
+ else
+ err = ret;
+
+ WARN_ON_ONCE(dfops->read_bufsize && (res_buf != buf));
+
+out_free:
+ vfree(res_buf);
+ mutex_unlock(&ar->mutex);
+ return err;
+}
+
+static ssize_t carl9170_debugfs_write(struct file *file,
+ const char __user *userbuf, size_t count, loff_t *ppos)
+{
+ struct carl9170_debugfs_fops *dfops;
+ struct ar9170 *ar;
+ char *buf = NULL;
+ int err = 0;
+
+ if (!count)
+ return 0;
+
+ if (count > PAGE_SIZE)
+ return -E2BIG;
+
+ ar = file->private_data;
+
+ if (!ar)
+ return -ENODEV;
+ dfops = container_of(file->f_op, struct carl9170_debugfs_fops, fops);
+
+ if (!dfops->write)
+ return -ENOSYS;
+
+ buf = vmalloc(count);
+ if (!buf)
+ return -ENOMEM;
+
+ if (copy_from_user(buf, userbuf, count)) {
+ err = -EFAULT;
+ goto out_free;
+ }
+
+ if (mutex_trylock(&ar->mutex) == 0) {
+ err = -EAGAIN;
+ goto out_free;
+ }
+
+ if (!CHK_DEV_STATE(ar, dfops->req_dev_state)) {
+ err = -ENODEV;
+ goto out_unlock;
+ }
+
+ err = dfops->write(ar, buf, count);
+ if (err)
+ goto out_unlock;
+
+out_unlock:
+ mutex_unlock(&ar->mutex);
+
+out_free:
+ vfree(buf);
+ return err;
+}
+
+#define __DEBUGFS_DECLARE_FILE(name, _read, _write, _read_bufsize, \
+ _attr, _dstate) \
+static const struct carl9170_debugfs_fops carl_debugfs_##name ##_ops = {\
+ .read_bufsize = _read_bufsize, \
+ .read = _read, \
+ .write = _write, \
+ .attr = _attr, \
+ .req_dev_state = _dstate, \
+ .fops = { \
+ .open = carl9170_debugfs_open, \
+ .read = carl9170_debugfs_read, \
+ .write = carl9170_debugfs_write, \
+ .owner = THIS_MODULE \
+ }, \
+}
+
+#define DEBUGFS_DECLARE_FILE(name, _read, _write, _read_bufsize, _attr) \
+ __DEBUGFS_DECLARE_FILE(name, _read, _write, _read_bufsize, \
+ _attr, CARL9170_STARTED) \
+
+#define DEBUGFS_DECLARE_RO_FILE(name, _read_bufsize) \
+ DEBUGFS_DECLARE_FILE(name, carl9170_debugfs_##name ##_read, \
+ NULL, _read_bufsize, S_IRUSR)
+
+#define DEBUGFS_DECLARE_WO_FILE(name) \
+ DEBUGFS_DECLARE_FILE(name, NULL, carl9170_debugfs_##name ##_write,\
+ 0, S_IWUSR)
+
+#define DEBUGFS_DECLARE_RW_FILE(name, _read_bufsize) \
+ DEBUGFS_DECLARE_FILE(name, carl9170_debugfs_##name ##_read, \
+ carl9170_debugfs_##name ##_write, \
+ _read_bufsize, S_IRUSR | S_IWUSR)
+
+#define __DEBUGFS_DECLARE_RW_FILE(name, _read_bufsize, _dstate) \
+ __DEBUGFS_DECLARE_FILE(name, carl9170_debugfs_##name ##_read, \
+ carl9170_debugfs_##name ##_write, \
+ _read_bufsize, S_IRUSR | S_IWUSR, _dstate)
+
+#define DEBUGFS_READONLY_FILE(name, _read_bufsize, fmt, value...) \
+static char *carl9170_debugfs_ ##name ## _read(struct ar9170 *ar, \
+ char *buf, size_t buf_size,\
+ ssize_t *len) \
+{ \
+ ADD(buf, *len, buf_size, fmt "\n", ##value); \
+ return buf; \
+} \
+DEBUGFS_DECLARE_RO_FILE(name, _read_bufsize)
+
+static char *carl9170_debugfs_mem_usage_read(struct ar9170 *ar, char *buf,
+ size_t bufsize, ssize_t *len)
+{
+ ADD(buf, *len, bufsize, "jar: [");
+
+ spin_lock_bh(&ar->mem_lock);
+
+ *len += bitmap_scnprintf(&buf[*len], bufsize - *len,
+ ar->mem_bitmap, ar->fw.mem_blocks);
+
+ ADD(buf, *len, bufsize, "]\n");
+
+ ADD(buf, *len, bufsize, "cookies: used:%3d / total:%3d, allocs:%d\n",
+ bitmap_weight(ar->mem_bitmap, ar->fw.mem_blocks),
+ ar->fw.mem_blocks, atomic_read(&ar->mem_allocs));
+
+ ADD(buf, *len, bufsize, "memory: free:%3d (%3d KiB) / total:%3d KiB)\n",
+ atomic_read(&ar->mem_free_blocks),
+ (atomic_read(&ar->mem_free_blocks) * ar->fw.mem_block_size) / 1024,
+ (ar->fw.mem_blocks * ar->fw.mem_block_size) / 1024);
+
+ spin_unlock_bh(&ar->mem_lock);
+
+ return buf;
+}
+DEBUGFS_DECLARE_RO_FILE(mem_usage, 512);
+
+static char *carl9170_debugfs_qos_stat_read(struct ar9170 *ar, char *buf,
+ size_t bufsize, ssize_t *len)
+{
+ ADD(buf, *len, bufsize, "%s QoS AC\n", modparam_noht ? "Hardware" :
+ "Software");
+
+ ADD(buf, *len, bufsize, "[ VO VI "
+ " BE BK ]\n");
+
+ spin_lock_bh(&ar->tx_stats_lock);
+ ADD(buf, *len, bufsize, "[length/limit length/limit "
+ "length/limit length/limit ]\n"
+ "[ %3d/%3d %3d/%3d "
+ " %3d/%3d %3d/%3d ]\n\n",
+ ar->tx_stats[0].len, ar->tx_stats[0].limit,
+ ar->tx_stats[1].len, ar->tx_stats[1].limit,
+ ar->tx_stats[2].len, ar->tx_stats[2].limit,
+ ar->tx_stats[3].len, ar->tx_stats[3].limit);
+
+ ADD(buf, *len, bufsize, "[ total total "
+ " total total ]\n"
+ "[%10d %10d %10d %10d ]\n\n",
+ ar->tx_stats[0].count, ar->tx_stats[1].count,
+ ar->tx_stats[2].count, ar->tx_stats[3].count);
+
+ spin_unlock_bh(&ar->tx_stats_lock);
+
+ ADD(buf, *len, bufsize, "[ pend/waittx pend/waittx "
+ " pend/waittx pend/waittx]\n"
+ "[ %3d/%3d %3d/%3d "
+ " %3d/%3d %3d/%3d ]\n\n",
+ skb_queue_len(&ar->tx_pending[0]),
+ skb_queue_len(&ar->tx_status[0]),
+ skb_queue_len(&ar->tx_pending[1]),
+ skb_queue_len(&ar->tx_status[1]),
+ skb_queue_len(&ar->tx_pending[2]),
+ skb_queue_len(&ar->tx_status[2]),
+ skb_queue_len(&ar->tx_pending[3]),
+ skb_queue_len(&ar->tx_status[3]));
+
+ return buf;
+}
+DEBUGFS_DECLARE_RO_FILE(qos_stat, 512);
+
+static void carl9170_debugfs_format_frame(struct ar9170 *ar,
+ struct sk_buff *skb, const char *prefix, char *buf,
+ ssize_t *off, ssize_t bufsize)
+{
+ struct _carl9170_tx_superframe *txc = (void *) skb->data;
+ struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb);
+ struct carl9170_tx_info *arinfo = (void *) txinfo->rate_driver_data;
+ struct ieee80211_hdr *hdr = (void *) txc->frame_data;
+
+ ADD(buf, *off, bufsize, "%s %p, c:%2x, DA:%pM, sq:%4d, mc:%.4x, "
+ "pc:%.8x, to:%d ms\n", prefix, skb, txc->s.cookie,
+ ieee80211_get_DA(hdr), get_seq_h(hdr),
+ le16_to_cpu(txc->f.mac_control), le32_to_cpu(txc->f.phy_control),
+ jiffies_to_msecs(jiffies - arinfo->timeout));
+}
+
+
+static char *carl9170_debugfs_ampdu_state_read(struct ar9170 *ar, char *buf,
+ size_t bufsize, ssize_t *len)
+{
+ struct carl9170_sta_tid *iter;
+ struct sk_buff *skb;
+ int cnt = 0, fc;
+ int offset;
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(iter, &ar->tx_ampdu_list, list) {
+
+ spin_lock_bh(&iter->lock);
+ ADD(buf, *len, bufsize, "Entry: #%2d TID:%1d, BSN:%4d, "
+ "SNX:%4d, HSN:%4d, BAW:%2d, state:%1d, toggles:%d\n",
+ cnt, iter->tid, iter->bsn, iter->snx, iter->hsn,
+ iter->max, iter->state, iter->counter);
+
+ ADD(buf, *len, bufsize, "\tWindow: [");
+
+ *len += bitmap_scnprintf(&buf[*len], bufsize - *len,
+ iter->bitmap, CARL9170_BAW_BITS);
+
+#define BM_STR_OFF(offset) \
+ ((CARL9170_BAW_BITS - (offset) - 1) / 4 + \
+ (CARL9170_BAW_BITS - (offset) - 1) / 32 + 1)
+
+ ADD(buf, *len, bufsize, ",W]\n");
+
+ offset = BM_STR_OFF(0);
+ ADD(buf, *len, bufsize, "\tBase Seq: %*s\n", offset, "T");
+
+ offset = BM_STR_OFF(SEQ_DIFF(iter->snx, iter->bsn));
+ ADD(buf, *len, bufsize, "\tNext Seq: %*s\n", offset, "W");
+
+ offset = BM_STR_OFF(((int)iter->hsn - (int)iter->bsn) %
+ CARL9170_BAW_BITS);
+ ADD(buf, *len, bufsize, "\tLast Seq: %*s\n", offset, "N");
+
+ ADD(buf, *len, bufsize, "\tPre-Aggregation reorder buffer: "
+ " currently queued:%d\n", skb_queue_len(&iter->queue));
+
+ fc = 0;
+ skb_queue_walk(&iter->queue, skb) {
+ char prefix[32];
+
+ snprintf(prefix, sizeof(prefix), "\t\t%3d :", fc);
+ carl9170_debugfs_format_frame(ar, skb, prefix, buf,
+ len, bufsize);
+
+ fc++;
+ }
+ spin_unlock_bh(&iter->lock);
+ cnt++;
+ }
+ rcu_read_unlock();
+
+ return buf;
+}
+DEBUGFS_DECLARE_RO_FILE(ampdu_state, 8000);
+
+static void carl9170_debugfs_queue_dump(struct ar9170 *ar, char *buf,
+ ssize_t *len, size_t bufsize, struct sk_buff_head *queue)
+{
+ struct sk_buff *skb;
+ char prefix[16];
+ int fc = 0;
+
+ spin_lock_bh(&queue->lock);
+ skb_queue_walk(queue, skb) {
+ snprintf(prefix, sizeof(prefix), "%3d :", fc);
+ carl9170_debugfs_format_frame(ar, skb, prefix, buf,
+ len, bufsize);
+ fc++;
+ }
+ spin_unlock_bh(&queue->lock);
+}
+
+#define DEBUGFS_QUEUE_DUMP(q, qi) \
+static char *carl9170_debugfs_##q ##_##qi ##_read(struct ar9170 *ar, \
+ char *buf, size_t bufsize, ssize_t *len) \
+{ \
+ carl9170_debugfs_queue_dump(ar, buf, len, bufsize, &ar->q[qi]); \
+ return buf; \
+} \
+DEBUGFS_DECLARE_RO_FILE(q##_##qi, 8000);
+
+static char *carl9170_debugfs_sta_psm_read(struct ar9170 *ar, char *buf,
+ size_t bufsize, ssize_t *len)
+{
+ ADD(buf, *len, bufsize, "psm state: %s\n", (ar->ps.off_override ?
+ "FORCE CAM" : (ar->ps.state ? "PSM" : "CAM")));
+
+ ADD(buf, *len, bufsize, "sleep duration: %d ms.\n", ar->ps.sleep_ms);
+ ADD(buf, *len, bufsize, "last power-state transition: %d ms ago.\n",
+ jiffies_to_msecs(jiffies - ar->ps.last_action));
+ ADD(buf, *len, bufsize, "last CAM->PSM transition: %d ms ago.\n",
+ jiffies_to_msecs(jiffies - ar->ps.last_slept));
+
+ return buf;
+}
+DEBUGFS_DECLARE_RO_FILE(sta_psm, 160);
+
+static char *carl9170_debugfs_tx_stuck_read(struct ar9170 *ar, char *buf,
+ size_t bufsize, ssize_t *len)
+{
+ int i;
+
+ for (i = 0; i < ar->hw->queues; i++) {
+ ADD(buf, *len, bufsize, "TX queue [%d]: %10d max:%10d ms.\n",
+ i, ieee80211_queue_stopped(ar->hw, i) ?
+ jiffies_to_msecs(jiffies - ar->queue_stop_timeout[i]) : 0,
+ jiffies_to_msecs(ar->max_queue_stop_timeout[i]));
+
+ ar->max_queue_stop_timeout[i] = 0;
+ }
+
+ return buf;
+}
+DEBUGFS_DECLARE_RO_FILE(tx_stuck, 180);
+
+static char *carl9170_debugfs_phy_noise_read(struct ar9170 *ar, char *buf,
+ size_t bufsize, ssize_t *len)
+{
+ int err;
+
+ err = carl9170_get_noisefloor(ar);
+ if (err) {
+ *len = err;
+ return buf;
+ }
+
+ ADD(buf, *len, bufsize, "Chain 0: %10d dBm, ext. chan.:%10d dBm\n",
+ ar->noise[0], ar->noise[2]);
+ ADD(buf, *len, bufsize, "Chain 2: %10d dBm, ext. chan.:%10d dBm\n",
+ ar->noise[1], ar->noise[3]);
+
+ return buf;
+}
+DEBUGFS_DECLARE_RO_FILE(phy_noise, 180);
+
+static char *carl9170_debugfs_vif_dump_read(struct ar9170 *ar, char *buf,
+ size_t bufsize, ssize_t *len)
+{
+ struct carl9170_vif_info *iter;
+ int i = 0;
+
+ ADD(buf, *len, bufsize, "registered VIFs:%d \\ %d\n",
+ ar->vifs, ar->fw.vif_num);
+
+ ADD(buf, *len, bufsize, "VIF bitmap: [");
+
+ *len += bitmap_scnprintf(&buf[*len], bufsize - *len,
+ &ar->vif_bitmap, ar->fw.vif_num);
+
+ ADD(buf, *len, bufsize, "]\n");
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(iter, &ar->vif_list, list) {
+ struct ieee80211_vif *vif = carl9170_get_vif(iter);
+ ADD(buf, *len, bufsize, "\t%d = [%s VIF, id:%d, type:%x "
+ " mac:%pM %s]\n", i, (carl9170_get_main_vif(ar) == vif ?
+ "Master" : " Slave"), iter->id, vif->type, vif->addr,
+ iter->enable_beacon ? "beaconing " : "");
+ i++;
+ }
+ rcu_read_unlock();
+
+ return buf;
+}
+DEBUGFS_DECLARE_RO_FILE(vif_dump, 8000);
+
+#define UPDATE_COUNTER(ar, name) ({ \
+ u32 __tmp[ARRAY_SIZE(name##_regs)]; \
+ unsigned int __i, __err = -ENODEV; \
+ \
+ for (__i = 0; __i < ARRAY_SIZE(name##_regs); __i++) { \
+ __tmp[__i] = name##_regs[__i].reg; \
+ ar->debug.stats.name##_counter[__i] = 0; \
+ } \
+ \
+ if (IS_STARTED(ar)) \
+ __err = carl9170_read_mreg(ar, ARRAY_SIZE(name##_regs), \
+ __tmp, ar->debug.stats.name##_counter); \
+ (__err); })
+
+#define TALLY_SUM_UP(ar, name) do { \
+ unsigned int __i; \
+ \
+ for (__i = 0; __i < ARRAY_SIZE(name##_regs); __i++) { \
+ ar->debug.stats.name##_sum[__i] += \
+ ar->debug.stats.name##_counter[__i]; \
+ } \
+} while (0)
+
+#define DEBUGFS_HW_TALLY_FILE(name, f) \
+static char *carl9170_debugfs_##name ## _read(struct ar9170 *ar, \
+ char *dum, size_t bufsize, ssize_t *ret) \
+{ \
+ char *buf; \
+ int i, max_len, err; \
+ \
+ max_len = ARRAY_SIZE(name##_regs) * 80; \
+ buf = vmalloc(max_len); \
+ if (!buf) \
+ return NULL; \
+ \
+ err = UPDATE_COUNTER(ar, name); \
+ if (err) { \
+ *ret = err; \
+ return buf; \
+ } \
+ \
+ TALLY_SUM_UP(ar, name); \
+ \
+ for (i = 0; i < ARRAY_SIZE(name##_regs); i++) { \
+ ADD(buf, *ret, max_len, "%22s = %" f "[+%" f "]\n", \
+ name##_regs[i].nreg, ar->debug.stats.name ##_sum[i],\
+ ar->debug.stats.name ##_counter[i]); \
+ } \
+ \
+ return buf; \
+} \
+DEBUGFS_DECLARE_RO_FILE(name, 0);
+
+#define DEBUGFS_HW_REG_FILE(name, f) \
+static char *carl9170_debugfs_##name ## _read(struct ar9170 *ar, \
+ char *dum, size_t bufsize, ssize_t *ret) \
+{ \
+ char *buf; \
+ int i, max_len, err; \
+ \
+ max_len = ARRAY_SIZE(name##_regs) * 80; \
+ buf = vmalloc(max_len); \
+ if (!buf) \
+ return NULL; \
+ \
+ err = UPDATE_COUNTER(ar, name); \
+ if (err) { \
+ *ret = err; \
+ return buf; \
+ } \
+ \
+ for (i = 0; i < ARRAY_SIZE(name##_regs); i++) { \
+ ADD(buf, *ret, max_len, "%22s = %" f "\n", \
+ name##_regs[i].nreg, \
+ ar->debug.stats.name##_counter[i]); \
+ } \
+ \
+ return buf; \
+} \
+DEBUGFS_DECLARE_RO_FILE(name, 0);
+
+static ssize_t carl9170_debugfs_hw_ioread32_write(struct ar9170 *ar,
+ const char *buf, size_t count)
+{
+ int err = 0, i, n = 0, max_len = 32, res;
+ unsigned int reg, tmp;
+
+ if (!count)
+ return 0;
+
+ if (count > max_len)
+ return -E2BIG;
+
+ res = sscanf(buf, "0x%X %d", &reg, &n);
+ if (res < 1) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ if (res == 1)
+ n = 1;
+
+ if (n > 15) {
+ err = -EMSGSIZE;
+ goto out;
+ }
+
+ if ((reg >= 0x280000) || ((reg + (n << 2)) >= 0x280000)) {
+ err = -EADDRNOTAVAIL;
+ goto out;
+ }
+
+ if (reg & 3) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ for (i = 0; i < n; i++) {
+ err = carl9170_read_reg(ar, reg + (i << 2), &tmp);
+ if (err)
+ goto out;
+
+ ar->debug.ring[ar->debug.ring_tail].reg = reg + (i << 2);
+ ar->debug.ring[ar->debug.ring_tail].value = tmp;
+ ar->debug.ring_tail++;
+ ar->debug.ring_tail %= CARL9170_DEBUG_RING_SIZE;
+ }
+
+out:
+ return err ? err : count;
+}
+
+static char *carl9170_debugfs_hw_ioread32_read(struct ar9170 *ar, char *buf,
+ size_t bufsize, ssize_t *ret)
+{
+ int i = 0;
+
+ while (ar->debug.ring_head != ar->debug.ring_tail) {
+ ADD(buf, *ret, bufsize, "%.8x = %.8x\n",
+ ar->debug.ring[ar->debug.ring_head].reg,
+ ar->debug.ring[ar->debug.ring_head].value);
+
+ ar->debug.ring_head++;
+ ar->debug.ring_head %= CARL9170_DEBUG_RING_SIZE;
+
+ if (i++ == 64)
+ break;
+ }
+ ar->debug.ring_head = ar->debug.ring_tail;
+ return buf;
+}
+DEBUGFS_DECLARE_RW_FILE(hw_ioread32, CARL9170_DEBUG_RING_SIZE * 40);
+
+static ssize_t carl9170_debugfs_bug_write(struct ar9170 *ar, const char *buf,
+ size_t count)
+{
+ int err;
+
+ if (count < 1)
+ return -EINVAL;
+
+ switch (buf[0]) {
+ case 'F':
+ ar->needs_full_reset = true;
+ break;
+
+ case 'R':
+ if (!IS_STARTED(ar)) {
+ err = -EAGAIN;
+ goto out;
+ }
+
+ ar->needs_full_reset = false;
+ break;
+
+ case 'M':
+ err = carl9170_mac_reset(ar);
+ if (err < 0)
+ count = err;
+
+ goto out;
+
+ case 'P':
+ err = carl9170_set_channel(ar, ar->hw->conf.channel,
+ ar->hw->conf.channel_type, CARL9170_RFI_COLD);
+ if (err < 0)
+ count = err;
+
+ goto out;
+
+ default:
+ return -EINVAL;
+ }
+
+ carl9170_restart(ar, CARL9170_RR_USER_REQUEST);
+
+out:
+ return count;
+}
+
+static char *carl9170_debugfs_bug_read(struct ar9170 *ar, char *buf,
+ size_t bufsize, ssize_t *ret)
+{
+ ADD(buf, *ret, bufsize, "[P]hy reinit, [R]estart, [F]ull usb reset, "
+ "[M]ac reset\n");
+ ADD(buf, *ret, bufsize, "firmware restarts:%d, last reason:%d\n",
+ ar->restart_counter, ar->last_reason);
+ ADD(buf, *ret, bufsize, "phy reinit errors:%d (%d)\n",
+ ar->total_chan_fail, ar->chan_fail);
+ ADD(buf, *ret, bufsize, "reported firmware errors:%d\n",
+ ar->fw.err_counter);
+ ADD(buf, *ret, bufsize, "reported firmware BUGs:%d\n",
+ ar->fw.bug_counter);
+ ADD(buf, *ret, bufsize, "pending restart requests:%d\n",
+ atomic_read(&ar->pending_restarts));
+ return buf;
+}
+__DEBUGFS_DECLARE_RW_FILE(bug, 400, CARL9170_STOPPED);
+
+static const char *erp_modes[] = {
+ [CARL9170_ERP_INVALID] = "INVALID",
+ [CARL9170_ERP_AUTO] = "Automatic",
+ [CARL9170_ERP_MAC80211] = "Set by MAC80211",
+ [CARL9170_ERP_OFF] = "Force Off",
+ [CARL9170_ERP_RTS] = "Force RTS",
+ [CARL9170_ERP_CTS] = "Force CTS"
+};
+
+static char *carl9170_debugfs_erp_read(struct ar9170 *ar, char *buf,
+ size_t bufsize, ssize_t *ret)
+{
+ ADD(buf, *ret, bufsize, "ERP Setting: (%d) -> %s\n", ar->erp_mode,
+ erp_modes[ar->erp_mode]);
+ return buf;
+}
+
+static ssize_t carl9170_debugfs_erp_write(struct ar9170 *ar, const char *buf,
+ size_t count)
+{
+ int res, val;
+
+ if (count < 1)
+ return -EINVAL;
+
+ res = sscanf(buf, "%d", &val);
+ if (res != 1)
+ return -EINVAL;
+
+ if (!((val > CARL9170_ERP_INVALID) &&
+ (val < __CARL9170_ERP_NUM)))
+ return -EINVAL;
+
+ ar->erp_mode = val;
+ return count;
+}
+
+DEBUGFS_DECLARE_RW_FILE(erp, 80);
+
+static ssize_t carl9170_debugfs_hw_iowrite32_write(struct ar9170 *ar,
+ const char *buf, size_t count)
+{
+ int err = 0, max_len = 22, res;
+ u32 reg, val;
+
+ if (!count)
+ return 0;
+
+ if (count > max_len)
+ return -E2BIG;
+
+ res = sscanf(buf, "0x%X 0x%X", &reg, &val);
+ if (res != 2) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ if (reg <= 0x100000 || reg >= 0x280000) {
+ err = -EADDRNOTAVAIL;
+ goto out;
+ }
+
+ if (reg & 3) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ err = carl9170_write_reg(ar, reg, val);
+ if (err)
+ goto out;
+
+out:
+ return err ? err : count;
+}
+DEBUGFS_DECLARE_WO_FILE(hw_iowrite32);
+
+DEBUGFS_HW_TALLY_FILE(hw_tx_tally, "u");
+DEBUGFS_HW_TALLY_FILE(hw_rx_tally, "u");
+DEBUGFS_HW_TALLY_FILE(hw_phy_errors, "u");
+DEBUGFS_HW_REG_FILE(hw_wlan_queue, ".8x");
+DEBUGFS_HW_REG_FILE(hw_pta_queue, ".8x");
+DEBUGFS_HW_REG_FILE(hw_ampdu_info, ".8x");
+DEBUGFS_QUEUE_DUMP(tx_status, 0);
+DEBUGFS_QUEUE_DUMP(tx_status, 1);
+DEBUGFS_QUEUE_DUMP(tx_status, 2);
+DEBUGFS_QUEUE_DUMP(tx_status, 3);
+DEBUGFS_QUEUE_DUMP(tx_pending, 0);
+DEBUGFS_QUEUE_DUMP(tx_pending, 1);
+DEBUGFS_QUEUE_DUMP(tx_pending, 2);
+DEBUGFS_QUEUE_DUMP(tx_pending, 3);
+DEBUGFS_READONLY_FILE(usb_tx_anch_urbs, 20, "%d",
+ atomic_read(&ar->tx_anch_urbs));
+DEBUGFS_READONLY_FILE(usb_rx_anch_urbs, 20, "%d",
+ atomic_read(&ar->rx_anch_urbs));
+DEBUGFS_READONLY_FILE(usb_rx_work_urbs, 20, "%d",
+ atomic_read(&ar->rx_work_urbs));
+DEBUGFS_READONLY_FILE(usb_rx_pool_urbs, 20, "%d",
+ atomic_read(&ar->rx_pool_urbs));
+
+DEBUGFS_READONLY_FILE(tx_total_queued, 20, "%d",
+ atomic_read(&ar->tx_total_queued));
+DEBUGFS_READONLY_FILE(tx_ampdu_scheduler, 20, "%d",
+ atomic_read(&ar->tx_ampdu_scheduler));
+
+DEBUGFS_READONLY_FILE(tx_total_pending, 20, "%d",
+ atomic_read(&ar->tx_total_pending));
+
+DEBUGFS_READONLY_FILE(tx_ampdu_list_len, 20, "%d",
+ ar->tx_ampdu_list_len);
+
+DEBUGFS_READONLY_FILE(tx_ampdu_upload, 20, "%d",
+ atomic_read(&ar->tx_ampdu_upload));
+
+DEBUGFS_READONLY_FILE(tx_janitor_last_run, 64, "last run:%d ms ago",
+ jiffies_to_msecs(jiffies - ar->tx_janitor_last_run));
+
+DEBUGFS_READONLY_FILE(tx_dropped, 20, "%d", ar->tx_dropped);
+
+DEBUGFS_READONLY_FILE(rx_dropped, 20, "%d", ar->rx_dropped);
+
+DEBUGFS_READONLY_FILE(sniffer_enabled, 20, "%d", ar->sniffer_enabled);
+DEBUGFS_READONLY_FILE(rx_software_decryption, 20, "%d",
+ ar->rx_software_decryption);
+DEBUGFS_READONLY_FILE(ampdu_factor, 20, "%d",
+ ar->current_factor);
+DEBUGFS_READONLY_FILE(ampdu_density, 20, "%d",
+ ar->current_density);
+
+DEBUGFS_READONLY_FILE(beacon_int, 20, "%d TU", ar->global_beacon_int);
+DEBUGFS_READONLY_FILE(pretbtt, 20, "%d TU", ar->global_pretbtt);
+
+void carl9170_debugfs_register(struct ar9170 *ar)
+{
+ ar->debug_dir = debugfs_create_dir(KBUILD_MODNAME,
+ ar->hw->wiphy->debugfsdir);
+
+#define DEBUGFS_ADD(name) \
+ debugfs_create_file(#name, carl_debugfs_##name ##_ops.attr, \
+ ar->debug_dir, ar, \
+ &carl_debugfs_##name ## _ops.fops);
+
+ DEBUGFS_ADD(usb_tx_anch_urbs);
+ DEBUGFS_ADD(usb_rx_pool_urbs);
+ DEBUGFS_ADD(usb_rx_anch_urbs);
+ DEBUGFS_ADD(usb_rx_work_urbs);
+
+ DEBUGFS_ADD(tx_total_queued);
+ DEBUGFS_ADD(tx_total_pending);
+ DEBUGFS_ADD(tx_dropped);
+ DEBUGFS_ADD(tx_stuck);
+ DEBUGFS_ADD(tx_ampdu_upload);
+ DEBUGFS_ADD(tx_ampdu_scheduler);
+ DEBUGFS_ADD(tx_ampdu_list_len);
+
+ DEBUGFS_ADD(rx_dropped);
+ DEBUGFS_ADD(sniffer_enabled);
+ DEBUGFS_ADD(rx_software_decryption);
+
+ DEBUGFS_ADD(mem_usage);
+ DEBUGFS_ADD(qos_stat);
+ DEBUGFS_ADD(sta_psm);
+ DEBUGFS_ADD(ampdu_state);
+
+ DEBUGFS_ADD(hw_tx_tally);
+ DEBUGFS_ADD(hw_rx_tally);
+ DEBUGFS_ADD(hw_phy_errors);
+ DEBUGFS_ADD(phy_noise);
+
+ DEBUGFS_ADD(hw_wlan_queue);
+ DEBUGFS_ADD(hw_pta_queue);
+ DEBUGFS_ADD(hw_ampdu_info);
+
+ DEBUGFS_ADD(ampdu_density);
+ DEBUGFS_ADD(ampdu_factor);
+
+ DEBUGFS_ADD(tx_janitor_last_run);
+
+ DEBUGFS_ADD(tx_status_0);
+ DEBUGFS_ADD(tx_status_1);
+ DEBUGFS_ADD(tx_status_2);
+ DEBUGFS_ADD(tx_status_3);
+
+ DEBUGFS_ADD(tx_pending_0);
+ DEBUGFS_ADD(tx_pending_1);
+ DEBUGFS_ADD(tx_pending_2);
+ DEBUGFS_ADD(tx_pending_3);
+
+ DEBUGFS_ADD(hw_ioread32);
+ DEBUGFS_ADD(hw_iowrite32);
+ DEBUGFS_ADD(bug);
+
+ DEBUGFS_ADD(erp);
+
+ DEBUGFS_ADD(vif_dump);
+
+ DEBUGFS_ADD(beacon_int);
+ DEBUGFS_ADD(pretbtt);
+
+#undef DEBUGFS_ADD
+}
+
+void carl9170_debugfs_unregister(struct ar9170 *ar)
+{
+ debugfs_remove_recursive(ar->debug_dir);
+}
diff --git a/drivers/net/wireless/ath/carl9170/debug.h b/drivers/net/wireless/ath/carl9170/debug.h
new file mode 100644
index 000000000000..ea4b97524122
--- /dev/null
+++ b/drivers/net/wireless/ath/carl9170/debug.h
@@ -0,0 +1,134 @@
+/*
+ * Atheros CARL9170 driver
+ *
+ * debug header
+ *
+ * Copyright 2010, Christian Lamparter <chunkeey@googlemail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ * Copyright (c) 2007-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef __DEBUG_H
+#define __DEBUG_H
+
+#include "eeprom.h"
+#include "wlan.h"
+#include "hw.h"
+#include "fwdesc.h"
+#include "fwcmd.h"
+#include "../regd.h"
+
+struct hw_stat_reg_entry {
+ u32 reg;
+ char nreg[32];
+};
+
+#define STAT_MAC_REG(reg) \
+ { (AR9170_MAC_REG_##reg), #reg }
+
+#define STAT_PTA_REG(reg) \
+ { (AR9170_PTA_REG_##reg), #reg }
+
+#define STAT_USB_REG(reg) \
+ { (AR9170_USB_REG_##reg), #reg }
+
+static const struct hw_stat_reg_entry hw_rx_tally_regs[] = {
+ STAT_MAC_REG(RX_CRC32), STAT_MAC_REG(RX_CRC16),
+ STAT_MAC_REG(RX_TIMEOUT_COUNT), STAT_MAC_REG(RX_ERR_DECRYPTION_UNI),
+ STAT_MAC_REG(RX_ERR_DECRYPTION_MUL), STAT_MAC_REG(RX_MPDU),
+ STAT_MAC_REG(RX_DROPPED_MPDU), STAT_MAC_REG(RX_DEL_MPDU),
+};
+
+static const struct hw_stat_reg_entry hw_phy_errors_regs[] = {
+ STAT_MAC_REG(RX_PHY_MISC_ERROR), STAT_MAC_REG(RX_PHY_XR_ERROR),
+ STAT_MAC_REG(RX_PHY_OFDM_ERROR), STAT_MAC_REG(RX_PHY_CCK_ERROR),
+ STAT_MAC_REG(RX_PHY_HT_ERROR), STAT_MAC_REG(RX_PHY_TOTAL),
+};
+
+static const struct hw_stat_reg_entry hw_tx_tally_regs[] = {
+ STAT_MAC_REG(TX_TOTAL), STAT_MAC_REG(TX_UNDERRUN),
+ STAT_MAC_REG(TX_RETRY),
+};
+
+static const struct hw_stat_reg_entry hw_wlan_queue_regs[] = {
+ STAT_MAC_REG(DMA_STATUS), STAT_MAC_REG(DMA_TRIGGER),
+ STAT_MAC_REG(DMA_TXQ0_ADDR), STAT_MAC_REG(DMA_TXQ0_CURR_ADDR),
+ STAT_MAC_REG(DMA_TXQ1_ADDR), STAT_MAC_REG(DMA_TXQ1_CURR_ADDR),
+ STAT_MAC_REG(DMA_TXQ2_ADDR), STAT_MAC_REG(DMA_TXQ2_CURR_ADDR),
+ STAT_MAC_REG(DMA_TXQ3_ADDR), STAT_MAC_REG(DMA_TXQ3_CURR_ADDR),
+ STAT_MAC_REG(DMA_RXQ_ADDR), STAT_MAC_REG(DMA_RXQ_CURR_ADDR),
+};
+
+static const struct hw_stat_reg_entry hw_ampdu_info_regs[] = {
+ STAT_MAC_REG(AMPDU_DENSITY), STAT_MAC_REG(AMPDU_FACTOR),
+};
+
+static const struct hw_stat_reg_entry hw_pta_queue_regs[] = {
+ STAT_PTA_REG(DN_CURR_ADDRH), STAT_PTA_REG(DN_CURR_ADDRL),
+ STAT_PTA_REG(UP_CURR_ADDRH), STAT_PTA_REG(UP_CURR_ADDRL),
+ STAT_PTA_REG(DMA_STATUS), STAT_PTA_REG(DMA_MODE_CTRL),
+};
+
+#define DEFINE_TALLY(name) \
+ u32 name##_sum[ARRAY_SIZE(name##_regs)], \
+ name##_counter[ARRAY_SIZE(name##_regs)] \
+
+#define DEFINE_STAT(name) \
+ u32 name##_counter[ARRAY_SIZE(name##_regs)] \
+
+struct ath_stats {
+ DEFINE_TALLY(hw_tx_tally);
+ DEFINE_TALLY(hw_rx_tally);
+ DEFINE_TALLY(hw_phy_errors);
+ DEFINE_STAT(hw_wlan_queue);
+ DEFINE_STAT(hw_pta_queue);
+ DEFINE_STAT(hw_ampdu_info);
+};
+
+struct carl9170_debug_mem_rbe {
+ u32 reg;
+ u32 value;
+};
+
+#define CARL9170_DEBUG_RING_SIZE 64
+
+struct carl9170_debug {
+ struct ath_stats stats;
+ struct carl9170_debug_mem_rbe ring[CARL9170_DEBUG_RING_SIZE];
+ struct mutex ring_lock;
+ unsigned int ring_head, ring_tail;
+ struct delayed_work update_tally;
+};
+
+struct ar9170;
+
+void carl9170_debugfs_register(struct ar9170 *ar);
+void carl9170_debugfs_unregister(struct ar9170 *ar);
+#endif /* __DEBUG_H */
diff --git a/drivers/net/wireless/ath/carl9170/eeprom.h b/drivers/net/wireless/ath/carl9170/eeprom.h
new file mode 100644
index 000000000000..7cff40ac7759
--- /dev/null
+++ b/drivers/net/wireless/ath/carl9170/eeprom.h
@@ -0,0 +1,216 @@
+/*
+ * Shared Atheros AR9170 Header
+ *
+ * EEPROM layout
+ *
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ * Copyright (c) 2007-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef __CARL9170_SHARED_EEPROM_H
+#define __CARL9170_SHARED_EEPROM_H
+
+#define AR9170_EEPROM_START 0x1600
+
+#define AR5416_MAX_CHAINS 2
+#define AR5416_MODAL_SPURS 5
+
+struct ar9170_eeprom_modal {
+ __le32 antCtrlChain[AR5416_MAX_CHAINS];
+ __le32 antCtrlCommon;
+ s8 antennaGainCh[AR5416_MAX_CHAINS];
+ u8 switchSettling;
+ u8 txRxAttenCh[AR5416_MAX_CHAINS];
+ u8 rxTxMarginCh[AR5416_MAX_CHAINS];
+ s8 adcDesiredSize;
+ s8 pgaDesiredSize;
+ u8 xlnaGainCh[AR5416_MAX_CHAINS];
+ u8 txEndToXpaOff;
+ u8 txEndToRxOn;
+ u8 txFrameToXpaOn;
+ u8 thresh62;
+ s8 noiseFloorThreshCh[AR5416_MAX_CHAINS];
+ u8 xpdGain;
+ u8 xpd;
+ s8 iqCalICh[AR5416_MAX_CHAINS];
+ s8 iqCalQCh[AR5416_MAX_CHAINS];
+ u8 pdGainOverlap;
+ u8 ob;
+ u8 db;
+ u8 xpaBiasLvl;
+ u8 pwrDecreaseFor2Chain;
+ u8 pwrDecreaseFor3Chain;
+ u8 txFrameToDataStart;
+ u8 txFrameToPaOn;
+ u8 ht40PowerIncForPdadc;
+ u8 bswAtten[AR5416_MAX_CHAINS];
+ u8 bswMargin[AR5416_MAX_CHAINS];
+ u8 swSettleHt40;
+ u8 reserved[22];
+ struct spur_channel {
+ __le16 spurChan;
+ u8 spurRangeLow;
+ u8 spurRangeHigh;
+ } __packed spur_channels[AR5416_MODAL_SPURS];
+} __packed;
+
+#define AR5416_NUM_PD_GAINS 4
+#define AR5416_PD_GAIN_ICEPTS 5
+
+struct ar9170_calibration_data_per_freq {
+ u8 pwr_pdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
+ u8 vpd_pdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
+} __packed;
+
+#define AR5416_NUM_5G_CAL_PIERS 8
+#define AR5416_NUM_2G_CAL_PIERS 4
+
+#define AR5416_NUM_5G_TARGET_PWRS 8
+#define AR5416_NUM_2G_CCK_TARGET_PWRS 3
+#define AR5416_NUM_2G_OFDM_TARGET_PWRS 4
+#define AR5416_MAX_NUM_TGT_PWRS 8
+
+struct ar9170_calibration_target_power_legacy {
+ u8 freq;
+ u8 power[4];
+} __packed;
+
+struct ar9170_calibration_target_power_ht {
+ u8 freq;
+ u8 power[8];
+} __packed;
+
+#define AR5416_NUM_CTLS 24
+
+struct ar9170_calctl_edges {
+ u8 channel;
+#define AR9170_CALCTL_EDGE_FLAGS 0xC0
+ u8 power_flags;
+} __packed;
+
+#define AR5416_NUM_BAND_EDGES 8
+
+struct ar9170_calctl_data {
+ struct ar9170_calctl_edges
+ control_edges[AR5416_MAX_CHAINS][AR5416_NUM_BAND_EDGES];
+} __packed;
+
+struct ar9170_eeprom {
+ __le16 length;
+ __le16 checksum;
+ __le16 version;
+ u8 operating_flags;
+#define AR9170_OPFLAG_5GHZ 1
+#define AR9170_OPFLAG_2GHZ 2
+ u8 misc;
+ __le16 reg_domain[2];
+ u8 mac_address[6];
+ u8 rx_mask;
+ u8 tx_mask;
+ __le16 rf_silent;
+ __le16 bluetooth_options;
+ __le16 device_capabilities;
+ __le32 build_number;
+ u8 deviceType;
+ u8 reserved[33];
+
+ u8 customer_data[64];
+
+ struct ar9170_eeprom_modal
+ modal_header[2];
+
+ u8 cal_freq_pier_5G[AR5416_NUM_5G_CAL_PIERS];
+ u8 cal_freq_pier_2G[AR5416_NUM_2G_CAL_PIERS];
+
+ struct ar9170_calibration_data_per_freq
+ cal_pier_data_5G[AR5416_MAX_CHAINS][AR5416_NUM_5G_CAL_PIERS],
+ cal_pier_data_2G[AR5416_MAX_CHAINS][AR5416_NUM_2G_CAL_PIERS];
+
+ /* power calibration data */
+ struct ar9170_calibration_target_power_legacy
+ cal_tgt_pwr_5G[AR5416_NUM_5G_TARGET_PWRS];
+ struct ar9170_calibration_target_power_ht
+ cal_tgt_pwr_5G_ht20[AR5416_NUM_5G_TARGET_PWRS],
+ cal_tgt_pwr_5G_ht40[AR5416_NUM_5G_TARGET_PWRS];
+
+ struct ar9170_calibration_target_power_legacy
+ cal_tgt_pwr_2G_cck[AR5416_NUM_2G_CCK_TARGET_PWRS],
+ cal_tgt_pwr_2G_ofdm[AR5416_NUM_2G_OFDM_TARGET_PWRS];
+ struct ar9170_calibration_target_power_ht
+ cal_tgt_pwr_2G_ht20[AR5416_NUM_2G_OFDM_TARGET_PWRS],
+ cal_tgt_pwr_2G_ht40[AR5416_NUM_2G_OFDM_TARGET_PWRS];
+
+ /* conformance testing limits */
+ u8 ctl_index[AR5416_NUM_CTLS];
+ struct ar9170_calctl_data
+ ctl_data[AR5416_NUM_CTLS];
+
+ u8 pad;
+ __le16 subsystem_id;
+} __packed;
+
+#define AR9170_LED_MODE_POWER_ON 0x0001
+#define AR9170_LED_MODE_RESERVED 0x0002
+#define AR9170_LED_MODE_DISABLE_STATE 0x0004
+#define AR9170_LED_MODE_OFF_IN_PSM 0x0008
+
+/* AR9170_LED_MODE BIT is set */
+#define AR9170_LED_MODE_FREQUENCY_S 4
+#define AR9170_LED_MODE_FREQUENCY 0x0030
+#define AR9170_LED_MODE_FREQUENCY_1HZ 0x0000
+#define AR9170_LED_MODE_FREQUENCY_0_5HZ 0x0010
+#define AR9170_LED_MODE_FREQUENCY_0_25HZ 0x0020
+#define AR9170_LED_MODE_FREQUENCY_0_125HZ 0x0030
+
+/* AR9170_LED_MODE BIT is not set */
+#define AR9170_LED_MODE_CONN_STATE_S 4
+#define AR9170_LED_MODE_CONN_STATE 0x0030
+#define AR9170_LED_MODE_CONN_STATE_FORCE_OFF 0x0000
+#define AR9170_LED_MODE_CONN_STATE_FORCE_ON 0x0010
+/* Idle off / Active on */
+#define AR9170_LED_MODE_CONN_STATE_IOFF_AON 0x0020
+/* Idle on / Active off */
+#define AR9170_LED_MODE_CONN_STATE_ION_AOFF 0x0010
+
+#define AR9170_LED_MODE_MODE 0x0040
+#define AR9170_LED_MODE_RESERVED2 0x0080
+
+#define AR9170_LED_MODE_TON_SCAN_S 8
+#define AR9170_LED_MODE_TON_SCAN 0x0f00
+
+#define AR9170_LED_MODE_TOFF_SCAN_S 12
+#define AR9170_LED_MODE_TOFF_SCAN 0xf000
+
+struct ar9170_led_mode {
+ __le16 led;
+};
+
+#endif /* __CARL9170_SHARED_EEPROM_H */
diff --git a/drivers/net/wireless/ath/carl9170/fw.c b/drivers/net/wireless/ath/carl9170/fw.c
new file mode 100644
index 000000000000..ae6c006bbc56
--- /dev/null
+++ b/drivers/net/wireless/ath/carl9170/fw.c
@@ -0,0 +1,402 @@
+/*
+ * Atheros CARL9170 driver
+ *
+ * firmware parser
+ *
+ * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, see
+ * http://www.gnu.org/licenses/.
+ */
+
+#include <linux/kernel.h>
+#include <linux/firmware.h>
+#include <linux/crc32.h>
+#include "carl9170.h"
+#include "fwcmd.h"
+#include "version.h"
+
+#define MAKE_STR(symbol) #symbol
+#define TO_STR(symbol) MAKE_STR(symbol)
+#define CARL9170FW_API_VER_STR TO_STR(CARL9170FW_API_MAX_VER)
+MODULE_VERSION(CARL9170FW_API_VER_STR ":" CARL9170FW_VERSION_GIT);
+
+static const u8 otus_magic[4] = { OTUS_MAGIC };
+
+static const void *carl9170_fw_find_desc(struct ar9170 *ar, const u8 descid[4],
+ const unsigned int len, const u8 compatible_revision)
+{
+ const struct carl9170fw_desc_head *iter;
+
+ carl9170fw_for_each_hdr(iter, ar->fw.desc) {
+ if (carl9170fw_desc_cmp(iter, descid, len,
+ compatible_revision))
+ return (void *)iter;
+ }
+
+ /* needed to find the LAST desc */
+ if (carl9170fw_desc_cmp(iter, descid, len,
+ compatible_revision))
+ return (void *)iter;
+
+ return NULL;
+}
+
+static int carl9170_fw_verify_descs(struct ar9170 *ar,
+ const struct carl9170fw_desc_head *head, unsigned int max_len)
+{
+ const struct carl9170fw_desc_head *pos;
+ unsigned long pos_addr, end_addr;
+ unsigned int pos_length;
+
+ if (max_len < sizeof(*pos))
+ return -ENODATA;
+
+ max_len = min_t(unsigned int, CARL9170FW_DESC_MAX_LENGTH, max_len);
+
+ pos = head;
+ pos_addr = (unsigned long) pos;
+ end_addr = pos_addr + max_len;
+
+ while (pos_addr < end_addr) {
+ if (pos_addr + sizeof(*head) > end_addr)
+ return -E2BIG;
+
+ pos_length = le16_to_cpu(pos->length);
+
+ if (pos_length < sizeof(*head))
+ return -EBADMSG;
+
+ if (pos_length > max_len)
+ return -EOVERFLOW;
+
+ if (pos_addr + pos_length > end_addr)
+ return -EMSGSIZE;
+
+ if (carl9170fw_desc_cmp(pos, LAST_MAGIC,
+ CARL9170FW_LAST_DESC_SIZE,
+ CARL9170FW_LAST_DESC_CUR_VER))
+ return 0;
+
+ pos_addr += pos_length;
+ pos = (void *)pos_addr;
+ max_len -= pos_length;
+ }
+ return -EINVAL;
+}
+
+static void carl9170_fw_info(struct ar9170 *ar)
+{
+ const struct carl9170fw_motd_desc *motd_desc;
+ unsigned int str_ver_len;
+ u32 fw_date;
+
+ dev_info(&ar->udev->dev, "driver API: %s 2%03d-%02d-%02d [%d-%d]\n",
+ CARL9170FW_VERSION_GIT, CARL9170FW_VERSION_YEAR,
+ CARL9170FW_VERSION_MONTH, CARL9170FW_VERSION_DAY,
+ CARL9170FW_API_MIN_VER, CARL9170FW_API_MAX_VER);
+
+ motd_desc = carl9170_fw_find_desc(ar, MOTD_MAGIC,
+ sizeof(*motd_desc), CARL9170FW_MOTD_DESC_CUR_VER);
+
+ if (motd_desc) {
+ str_ver_len = strnlen(motd_desc->release,
+ CARL9170FW_MOTD_RELEASE_LEN);
+
+ fw_date = le32_to_cpu(motd_desc->fw_year_month_day);
+
+ dev_info(&ar->udev->dev, "firmware API: %.*s 2%03d-%02d-%02d\n",
+ str_ver_len, motd_desc->release,
+ CARL9170FW_GET_YEAR(fw_date),
+ CARL9170FW_GET_MONTH(fw_date),
+ CARL9170FW_GET_DAY(fw_date));
+
+ strlcpy(ar->hw->wiphy->fw_version, motd_desc->release,
+ sizeof(ar->hw->wiphy->fw_version));
+ }
+}
+
+static bool valid_dma_addr(const u32 address)
+{
+ if (address >= AR9170_SRAM_OFFSET &&
+ address < (AR9170_SRAM_OFFSET + AR9170_SRAM_SIZE))
+ return true;
+
+ return false;
+}
+
+static bool valid_cpu_addr(const u32 address)
+{
+ if (valid_dma_addr(address) || (address >= AR9170_PRAM_OFFSET &&
+ address < (AR9170_PRAM_OFFSET + AR9170_PRAM_SIZE)))
+ return true;
+
+ return false;
+}
+
+static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len)
+{
+ const struct carl9170fw_otus_desc *otus_desc;
+ const struct carl9170fw_chk_desc *chk_desc;
+ const struct carl9170fw_last_desc *last_desc;
+
+ last_desc = carl9170_fw_find_desc(ar, LAST_MAGIC,
+ sizeof(*last_desc), CARL9170FW_LAST_DESC_CUR_VER);
+ if (!last_desc)
+ return -EINVAL;
+
+ otus_desc = carl9170_fw_find_desc(ar, OTUS_MAGIC,
+ sizeof(*otus_desc), CARL9170FW_OTUS_DESC_CUR_VER);
+ if (!otus_desc) {
+ dev_err(&ar->udev->dev, "failed to find compatible firmware "
+ "descriptor.\n");
+ return -ENODATA;
+ }
+
+ chk_desc = carl9170_fw_find_desc(ar, CHK_MAGIC,
+ sizeof(*chk_desc), CARL9170FW_CHK_DESC_CUR_VER);
+
+ if (chk_desc) {
+ unsigned long fin, diff;
+ unsigned int dsc_len;
+ u32 crc32;
+
+ dsc_len = min_t(unsigned int, len,
+ (unsigned long)chk_desc - (unsigned long)otus_desc);
+
+ fin = (unsigned long) last_desc + sizeof(*last_desc);
+ diff = fin - (unsigned long) otus_desc;
+
+ if (diff < len)
+ len -= diff;
+
+ if (len < 256)
+ return -EIO;
+
+ crc32 = crc32_le(~0, data, len);
+ if (cpu_to_le32(crc32) != chk_desc->fw_crc32) {
+ dev_err(&ar->udev->dev, "fw checksum test failed.\n");
+ return -ENOEXEC;
+ }
+
+ crc32 = crc32_le(crc32, (void *)otus_desc, dsc_len);
+ if (cpu_to_le32(crc32) != chk_desc->hdr_crc32) {
+ dev_err(&ar->udev->dev, "descriptor check failed.\n");
+ return -EINVAL;
+ }
+ } else {
+ dev_warn(&ar->udev->dev, "Unprotected firmware image.\n");
+ }
+
+#define SUPP(feat) \
+ (carl9170fw_supports(otus_desc->feature_set, feat))
+
+ if (!SUPP(CARL9170FW_DUMMY_FEATURE)) {
+ dev_err(&ar->udev->dev, "invalid firmware descriptor "
+ "format detected.\n");
+ return -EINVAL;
+ }
+
+ ar->fw.api_version = otus_desc->api_ver;
+
+ if (ar->fw.api_version < CARL9170FW_API_MIN_VER ||
+ ar->fw.api_version > CARL9170FW_API_MAX_VER) {
+ dev_err(&ar->udev->dev, "unsupported firmware api version.\n");
+ return -EINVAL;
+ }
+
+ if (!SUPP(CARL9170FW_COMMAND_PHY) || SUPP(CARL9170FW_UNUSABLE) ||
+ !SUPP(CARL9170FW_HANDLE_BACK_REQ)) {
+ dev_err(&ar->udev->dev, "firmware does support "
+ "mandatory features.\n");
+ return -ECANCELED;
+ }
+
+ if (ilog2(le32_to_cpu(otus_desc->feature_set)) >=
+ __CARL9170FW_FEATURE_NUM) {
+ dev_warn(&ar->udev->dev, "driver does not support all "
+ "firmware features.\n");
+ }
+
+ if (!SUPP(CARL9170FW_COMMAND_CAM)) {
+ dev_info(&ar->udev->dev, "crypto offloading is disabled "
+ "by firmware.\n");
+ ar->disable_offload = true;
+ }
+
+ if (SUPP(CARL9170FW_PSM))
+ ar->hw->flags |= IEEE80211_HW_SUPPORTS_PS;
+
+ if (!SUPP(CARL9170FW_USB_INIT_FIRMWARE)) {
+ dev_err(&ar->udev->dev, "firmware does not provide "
+ "mandatory interfaces.\n");
+ return -EINVAL;
+ }
+
+ if (SUPP(CARL9170FW_MINIBOOT))
+ ar->fw.offset = le16_to_cpu(otus_desc->miniboot_size);
+ else
+ ar->fw.offset = 0;
+
+ if (SUPP(CARL9170FW_USB_DOWN_STREAM)) {
+ ar->hw->extra_tx_headroom += sizeof(struct ar9170_stream);
+ ar->fw.tx_stream = true;
+ }
+
+ if (SUPP(CARL9170FW_USB_UP_STREAM))
+ ar->fw.rx_stream = true;
+
+ if (SUPP(CARL9170FW_RX_FILTER)) {
+ ar->fw.rx_filter = true;
+ ar->rx_filter_caps = FIF_FCSFAIL | FIF_PLCPFAIL |
+ FIF_CONTROL | FIF_PSPOLL | FIF_OTHER_BSS |
+ FIF_PROMISC_IN_BSS;
+ }
+
+ ar->fw.vif_num = otus_desc->vif_num;
+ ar->fw.cmd_bufs = otus_desc->cmd_bufs;
+ ar->fw.address = le32_to_cpu(otus_desc->fw_address);
+ ar->fw.rx_size = le16_to_cpu(otus_desc->rx_max_frame_len);
+ ar->fw.mem_blocks = min_t(unsigned int, otus_desc->tx_descs, 0xfe);
+ atomic_set(&ar->mem_free_blocks, ar->fw.mem_blocks);
+ ar->fw.mem_block_size = le16_to_cpu(otus_desc->tx_frag_len);
+
+ if (ar->fw.vif_num >= AR9170_MAX_VIRTUAL_MAC || !ar->fw.vif_num ||
+ ar->fw.mem_blocks < 16 || !ar->fw.cmd_bufs ||
+ ar->fw.mem_block_size < 64 || ar->fw.mem_block_size > 512 ||
+ ar->fw.rx_size > 32768 || ar->fw.rx_size < 4096 ||
+ !valid_cpu_addr(ar->fw.address)) {
+ dev_err(&ar->udev->dev, "firmware shows obvious signs of "
+ "malicious tampering.\n");
+ return -EINVAL;
+ }
+
+ ar->fw.beacon_addr = le32_to_cpu(otus_desc->bcn_addr);
+ ar->fw.beacon_max_len = le16_to_cpu(otus_desc->bcn_len);
+
+ if (valid_dma_addr(ar->fw.beacon_addr) && ar->fw.beacon_max_len >=
+ AR9170_MAC_BCN_LENGTH_MAX) {
+ ar->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC);
+
+ if (SUPP(CARL9170FW_WLANTX_CAB)) {
+ ar->hw->wiphy->interface_modes |=
+ BIT(NL80211_IFTYPE_AP);
+ }
+ }
+
+#undef SUPPORTED
+ return 0;
+}
+
+static struct carl9170fw_desc_head *
+carl9170_find_fw_desc(struct ar9170 *ar, const __u8 *fw_data, const size_t len)
+
+{
+ int scan = 0, found = 0;
+
+ if (!carl9170fw_size_check(len)) {
+ dev_err(&ar->udev->dev, "firmware size is out of bound.\n");
+ return NULL;
+ }
+
+ while (scan < len - sizeof(struct carl9170fw_desc_head)) {
+ if (fw_data[scan++] == otus_magic[found])
+ found++;
+ else
+ found = 0;
+
+ if (scan >= len)
+ break;
+
+ if (found == sizeof(otus_magic))
+ break;
+ }
+
+ if (found != sizeof(otus_magic))
+ return NULL;
+
+ return (void *)&fw_data[scan - found];
+}
+
+int carl9170_fw_fix_eeprom(struct ar9170 *ar)
+{
+ const struct carl9170fw_fix_desc *fix_desc = NULL;
+ unsigned int i, n, off;
+ u32 *data = (void *)&ar->eeprom;
+
+ fix_desc = carl9170_fw_find_desc(ar, FIX_MAGIC,
+ sizeof(*fix_desc), CARL9170FW_FIX_DESC_CUR_VER);
+
+ if (!fix_desc)
+ return 0;
+
+ n = (le16_to_cpu(fix_desc->head.length) - sizeof(*fix_desc)) /
+ sizeof(struct carl9170fw_fix_entry);
+
+ for (i = 0; i < n; i++) {
+ off = le32_to_cpu(fix_desc->data[i].address) -
+ AR9170_EEPROM_START;
+
+ if (off >= sizeof(struct ar9170_eeprom) || (off & 3)) {
+ dev_err(&ar->udev->dev, "Skip invalid entry %d\n", i);
+ continue;
+ }
+
+ data[off / sizeof(*data)] &=
+ le32_to_cpu(fix_desc->data[i].mask);
+ data[off / sizeof(*data)] |=
+ le32_to_cpu(fix_desc->data[i].value);
+ }
+
+ return 0;
+}
+
+int carl9170_parse_firmware(struct ar9170 *ar)
+{
+ const struct carl9170fw_desc_head *fw_desc = NULL;
+ const struct firmware *fw = ar->fw.fw;
+ unsigned long header_offset = 0;
+ int err;
+
+ if (WARN_ON(!fw))
+ return -EINVAL;
+
+ fw_desc = carl9170_find_fw_desc(ar, fw->data, fw->size);
+
+ if (!fw_desc) {
+ dev_err(&ar->udev->dev, "unsupported firmware.\n");
+ return -ENODATA;
+ }
+
+ header_offset = (unsigned long)fw_desc - (unsigned long)fw->data;
+
+ err = carl9170_fw_verify_descs(ar, fw_desc, fw->size - header_offset);
+ if (err) {
+ dev_err(&ar->udev->dev, "damaged firmware (%d).\n", err);
+ return err;
+ }
+
+ ar->fw.desc = fw_desc;
+
+ carl9170_fw_info(ar);
+
+ err = carl9170_fw(ar, fw->data, fw->size);
+ if (err) {
+ dev_err(&ar->udev->dev, "failed to parse firmware (%d).\n",
+ err);
+ return err;
+ }
+
+ return 0;
+}
diff --git a/drivers/net/wireless/ath/carl9170/fwcmd.h b/drivers/net/wireless/ath/carl9170/fwcmd.h
new file mode 100644
index 000000000000..d552166db505
--- /dev/null
+++ b/drivers/net/wireless/ath/carl9170/fwcmd.h
@@ -0,0 +1,284 @@
+/*
+ * Shared Atheros AR9170 Header
+ *
+ * Firmware command interface definitions
+ *
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ * Copyright (c) 2007-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __CARL9170_SHARED_FWCMD_H
+#define __CARL9170_SHARED_FWCMD_H
+
+#define CARL9170_MAX_CMD_LEN 64
+#define CARL9170_MAX_CMD_PAYLOAD_LEN 60
+
+#define CARL9170FW_API_MIN_VER 1
+#define CARL9170FW_API_MAX_VER 1
+
+enum carl9170_cmd_oids {
+ CARL9170_CMD_RREG = 0x00,
+ CARL9170_CMD_WREG = 0x01,
+ CARL9170_CMD_ECHO = 0x02,
+ CARL9170_CMD_SWRST = 0x03,
+ CARL9170_CMD_REBOOT = 0x04,
+ CARL9170_CMD_BCN_CTRL = 0x05,
+ CARL9170_CMD_READ_TSF = 0x06,
+ CARL9170_CMD_RX_FILTER = 0x07,
+
+ /* CAM */
+ CARL9170_CMD_EKEY = 0x10,
+ CARL9170_CMD_DKEY = 0x11,
+
+ /* RF / PHY */
+ CARL9170_CMD_FREQUENCY = 0x20,
+ CARL9170_CMD_RF_INIT = 0x21,
+ CARL9170_CMD_SYNTH = 0x22,
+ CARL9170_CMD_FREQ_START = 0x23,
+ CARL9170_CMD_PSM = 0x24,
+
+ /* Asychronous command flag */
+ CARL9170_CMD_ASYNC_FLAG = 0x40,
+ CARL9170_CMD_WREG_ASYNC = (CARL9170_CMD_WREG |
+ CARL9170_CMD_ASYNC_FLAG),
+ CARL9170_CMD_REBOOT_ASYNC = (CARL9170_CMD_REBOOT |
+ CARL9170_CMD_ASYNC_FLAG),
+ CARL9170_CMD_BCN_CTRL_ASYNC = (CARL9170_CMD_BCN_CTRL |
+ CARL9170_CMD_ASYNC_FLAG),
+ CARL9170_CMD_PSM_ASYNC = (CARL9170_CMD_PSM |
+ CARL9170_CMD_ASYNC_FLAG),
+
+ /* responses and traps */
+ CARL9170_RSP_FLAG = 0xc0,
+ CARL9170_RSP_PRETBTT = 0xc0,
+ CARL9170_RSP_TXCOMP = 0xc1,
+ CARL9170_RSP_BEACON_CONFIG = 0xc2,
+ CARL9170_RSP_ATIM = 0xc3,
+ CARL9170_RSP_WATCHDOG = 0xc6,
+ CARL9170_RSP_TEXT = 0xca,
+ CARL9170_RSP_HEXDUMP = 0xcc,
+ CARL9170_RSP_RADAR = 0xcd,
+ CARL9170_RSP_GPIO = 0xce,
+ CARL9170_RSP_BOOT = 0xcf,
+};
+
+struct carl9170_set_key_cmd {
+ __le16 user;
+ __le16 keyId;
+ __le16 type;
+ u8 macAddr[6];
+ u32 key[4];
+} __packed;
+#define CARL9170_SET_KEY_CMD_SIZE 28
+
+struct carl9170_disable_key_cmd {
+ __le16 user;
+ __le16 padding;
+} __packed;
+#define CARL9170_DISABLE_KEY_CMD_SIZE 4
+
+struct carl9170_u32_list {
+ u32 vals[0];
+} __packed;
+
+struct carl9170_reg_list {
+ __le32 regs[0];
+} __packed;
+
+struct carl9170_write_reg {
+ struct {
+ __le32 addr;
+ __le32 val;
+ } regs[0] __packed;
+} __packed;
+
+#define CARL9170FW_PHY_HT_ENABLE 0x4
+#define CARL9170FW_PHY_HT_DYN2040 0x8
+#define CARL9170FW_PHY_HT_EXT_CHAN_OFF 0x3
+#define CARL9170FW_PHY_HT_EXT_CHAN_OFF_S 2
+
+struct carl9170_rf_init {
+ __le32 freq;
+ u8 ht_settings;
+ u8 padding2[3];
+ __le32 delta_slope_coeff_exp;
+ __le32 delta_slope_coeff_man;
+ __le32 delta_slope_coeff_exp_shgi;
+ __le32 delta_slope_coeff_man_shgi;
+ __le32 finiteLoopCount;
+} __packed;
+#define CARL9170_RF_INIT_SIZE 28
+
+struct carl9170_rf_init_result {
+ __le32 ret; /* AR9170_PHY_REG_AGC_CONTROL */
+} __packed;
+#define CARL9170_RF_INIT_RESULT_SIZE 4
+
+#define CARL9170_PSM_SLEEP 0x1000
+#define CARL9170_PSM_SOFTWARE 0
+#define CARL9170_PSM_WAKE 0 /* internally used. */
+#define CARL9170_PSM_COUNTER 0xfff
+#define CARL9170_PSM_COUNTER_S 0
+
+struct carl9170_psm {
+ __le32 state;
+} __packed;
+#define CARL9170_PSM_SIZE 4
+
+struct carl9170_rx_filter_cmd {
+ __le32 rx_filter;
+} __packed;
+#define CARL9170_RX_FILTER_CMD_SIZE 4
+
+#define CARL9170_RX_FILTER_BAD 0x01
+#define CARL9170_RX_FILTER_OTHER_RA 0x02
+#define CARL9170_RX_FILTER_DECRY_FAIL 0x04
+#define CARL9170_RX_FILTER_CTL_OTHER 0x08
+#define CARL9170_RX_FILTER_CTL_PSPOLL 0x10
+#define CARL9170_RX_FILTER_CTL_BACKR 0x20
+#define CARL9170_RX_FILTER_MGMT 0x40
+#define CARL9170_RX_FILTER_DATA 0x80
+
+struct carl9170_bcn_ctrl_cmd {
+ __le32 vif_id;
+ __le32 mode;
+ __le32 bcn_addr;
+ __le32 bcn_len;
+} __packed;
+#define CARL9170_BCN_CTRL_CMD_SIZE 16
+
+#define CARL9170_BCN_CTRL_DRAIN 0
+#define CARL9170_BCN_CTRL_CAB_TRIGGER 1
+
+struct carl9170_cmd_head {
+ union {
+ struct {
+ u8 len;
+ u8 cmd;
+ u8 seq;
+ u8 ext;
+ } __packed;
+
+ u32 hdr_data;
+ } __packed;
+} __packed;
+
+struct carl9170_cmd {
+ struct carl9170_cmd_head hdr;
+ union {
+ struct carl9170_set_key_cmd setkey;
+ struct carl9170_disable_key_cmd disablekey;
+ struct carl9170_u32_list echo;
+ struct carl9170_reg_list rreg;
+ struct carl9170_write_reg wreg;
+ struct carl9170_rf_init rf_init;
+ struct carl9170_psm psm;
+ struct carl9170_bcn_ctrl_cmd bcn_ctrl;
+ struct carl9170_rx_filter_cmd rx_filter;
+ u8 data[CARL9170_MAX_CMD_PAYLOAD_LEN];
+ } __packed;
+} __packed;
+
+#define CARL9170_TX_STATUS_QUEUE 3
+#define CARL9170_TX_STATUS_QUEUE_S 0
+#define CARL9170_TX_STATUS_RIX_S 2
+#define CARL9170_TX_STATUS_RIX (3 << CARL9170_TX_STATUS_RIX_S)
+#define CARL9170_TX_STATUS_TRIES_S 4
+#define CARL9170_TX_STATUS_TRIES (7 << CARL9170_TX_STATUS_TRIES_S)
+#define CARL9170_TX_STATUS_SUCCESS 0x80
+
+/*
+ * NOTE:
+ * Both structs [carl9170_tx_status and _carl9170_tx_status]
+ * need to be "bit for bit" in sync.
+ */
+struct carl9170_tx_status {
+ /*
+ * Beware of compiler bugs in all gcc pre 4.4!
+ */
+
+ u8 cookie;
+ u8 queue:2;
+ u8 rix:2;
+ u8 tries:3;
+ u8 success:1;
+} __packed;
+struct _carl9170_tx_status {
+ /*
+ * This version should be immune to all alignment bugs.
+ */
+
+ u8 cookie;
+ u8 info;
+} __packed;
+#define CARL9170_TX_STATUS_SIZE 2
+
+#define CARL9170_RSP_TX_STATUS_NUM (CARL9170_MAX_CMD_PAYLOAD_LEN / \
+ sizeof(struct _carl9170_tx_status))
+
+#define CARL9170_TX_MAX_RATE_TRIES 7
+
+#define CARL9170_TX_MAX_RATES 4
+#define CARL9170_TX_MAX_RETRY_RATES (CARL9170_TX_MAX_RATES - 1)
+#define CARL9170_ERR_MAGIC "ERR:"
+#define CARL9170_BUG_MAGIC "BUG:"
+
+struct carl9170_gpio {
+ __le32 gpio;
+} __packed;
+#define CARL9170_GPIO_SIZE 4
+
+struct carl9170_tsf_rsp {
+ union {
+ __le32 tsf[2];
+ __le64 tsf_64;
+ } __packed;
+} __packed;
+#define CARL9170_TSF_RSP_SIZE 8
+
+struct carl9170_rsp {
+ struct carl9170_cmd_head hdr;
+
+ union {
+ struct carl9170_rf_init_result rf_init_res;
+ struct carl9170_u32_list rreg_res;
+ struct carl9170_u32_list echo;
+ struct carl9170_tx_status tx_status[0];
+ struct _carl9170_tx_status _tx_status[0];
+ struct carl9170_gpio gpio;
+ struct carl9170_tsf_rsp tsf;
+ struct carl9170_psm psm;
+ u8 data[CARL9170_MAX_CMD_PAYLOAD_LEN];
+ } __packed;
+} __packed;
+
+#endif /* __CARL9170_SHARED_FWCMD_H */
diff --git a/drivers/net/wireless/ath/carl9170/fwdesc.h b/drivers/net/wireless/ath/carl9170/fwdesc.h
new file mode 100644
index 000000000000..71f3821f6058
--- /dev/null
+++ b/drivers/net/wireless/ath/carl9170/fwdesc.h
@@ -0,0 +1,241 @@
+/*
+ * Shared CARL9170 Header
+ *
+ * Firmware descriptor format
+ *
+ * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, see
+ * http://www.gnu.org/licenses/.
+ */
+
+#ifndef __CARL9170_SHARED_FWDESC_H
+#define __CARL9170_SHARED_FWDESC_H
+
+/* NOTE: Don't mess with the order of the flags! */
+enum carl9170fw_feature_list {
+ /* Always set */
+ CARL9170FW_DUMMY_FEATURE,
+
+ /*
+ * Indicates that this image has special boot block which prevents
+ * legacy drivers to drive the firmware.
+ */
+ CARL9170FW_MINIBOOT,
+
+ /* usb registers are initialized by the firmware */
+ CARL9170FW_USB_INIT_FIRMWARE,
+
+ /* command traps & notifications are send through EP2 */
+ CARL9170FW_USB_RESP_EP2,
+
+ /* usb download (app -> fw) stream */
+ CARL9170FW_USB_DOWN_STREAM,
+
+ /* usb upload (fw -> app) stream */
+ CARL9170FW_USB_UP_STREAM,
+
+ /* unusable - reserved to flag non-functional debug firmwares */
+ CARL9170FW_UNUSABLE,
+
+ /* AR9170_CMD_RF_INIT, AR9170_CMD_FREQ_START, AR9170_CMD_FREQUENCY */
+ CARL9170FW_COMMAND_PHY,
+
+ /* AR9170_CMD_EKEY, AR9170_CMD_DKEY */
+ CARL9170FW_COMMAND_CAM,
+
+ /* Firmware has a software Content After Beacon Queueing mechanism */
+ CARL9170FW_WLANTX_CAB,
+
+ /* The firmware is capable of responding to incoming BAR frames */
+ CARL9170FW_HANDLE_BACK_REQ,
+
+ /* GPIO Interrupt | CARL9170_RSP_GPIO */
+ CARL9170FW_GPIO_INTERRUPT,
+
+ /* Firmware PSM support | CARL9170_CMD_PSM */
+ CARL9170FW_PSM,
+
+ /* Firmware RX filter | CARL9170_CMD_RX_FILTER */
+ CARL9170FW_RX_FILTER,
+
+ /* KEEP LAST */
+ __CARL9170FW_FEATURE_NUM
+};
+
+#define OTUS_MAGIC "OTAR"
+#define MOTD_MAGIC "MOTD"
+#define FIX_MAGIC "FIX\0"
+#define DBG_MAGIC "DBG\0"
+#define CHK_MAGIC "CHK\0"
+#define LAST_MAGIC "LAST"
+
+#define CARL9170FW_SET_DAY(d) (((d) - 1) % 31)
+#define CARL9170FW_SET_MONTH(m) ((((m) - 1) % 12) * 31)
+#define CARL9170FW_SET_YEAR(y) (((y) - 10) * 372)
+
+#define CARL9170FW_GET_DAY(d) (((d) % 31) + 1)
+#define CARL9170FW_GET_MONTH(m) ((((m) / 31) % 12) + 1)
+#define CARL9170FW_GET_YEAR(y) ((y) / 372 + 10)
+
+struct carl9170fw_desc_head {
+ u8 magic[4];
+ __le16 length;
+ u8 min_ver;
+ u8 cur_ver;
+} __packed;
+#define CARL9170FW_DESC_HEAD_SIZE \
+ (sizeof(struct carl9170fw_desc_head))
+
+#define CARL9170FW_OTUS_DESC_MIN_VER 6
+#define CARL9170FW_OTUS_DESC_CUR_VER 6
+struct carl9170fw_otus_desc {
+ struct carl9170fw_desc_head head;
+ __le32 feature_set;
+ __le32 fw_address;
+ __le32 bcn_addr;
+ __le16 bcn_len;
+ __le16 miniboot_size;
+ __le16 tx_frag_len;
+ __le16 rx_max_frame_len;
+ u8 tx_descs;
+ u8 cmd_bufs;
+ u8 api_ver;
+ u8 vif_num;
+} __packed;
+#define CARL9170FW_OTUS_DESC_SIZE \
+ (sizeof(struct carl9170fw_otus_desc))
+
+#define CARL9170FW_MOTD_STRING_LEN 24
+#define CARL9170FW_MOTD_RELEASE_LEN 20
+#define CARL9170FW_MOTD_DESC_MIN_VER 1
+#define CARL9170FW_MOTD_DESC_CUR_VER 2
+struct carl9170fw_motd_desc {
+ struct carl9170fw_desc_head head;
+ __le32 fw_year_month_day;
+ char desc[CARL9170FW_MOTD_STRING_LEN];
+ char release[CARL9170FW_MOTD_RELEASE_LEN];
+} __packed;
+#define CARL9170FW_MOTD_DESC_SIZE \
+ (sizeof(struct carl9170fw_motd_desc))
+
+#define CARL9170FW_FIX_DESC_MIN_VER 1
+#define CARL9170FW_FIX_DESC_CUR_VER 2
+struct carl9170fw_fix_entry {
+ __le32 address;
+ __le32 mask;
+ __le32 value;
+} __packed;
+
+struct carl9170fw_fix_desc {
+ struct carl9170fw_desc_head head;
+ struct carl9170fw_fix_entry data[0];
+} __packed;
+#define CARL9170FW_FIX_DESC_SIZE \
+ (sizeof(struct carl9170fw_fix_desc))
+
+#define CARL9170FW_DBG_DESC_MIN_VER 1
+#define CARL9170FW_DBG_DESC_CUR_VER 3
+struct carl9170fw_dbg_desc {
+ struct carl9170fw_desc_head head;
+
+ __le32 bogoclock_addr;
+ __le32 counter_addr;
+ __le32 rx_total_addr;
+ __le32 rx_overrun_addr;
+ __le32 rx_filter;
+
+ /* Put your debugging definitions here */
+} __packed;
+#define CARL9170FW_DBG_DESC_SIZE \
+ (sizeof(struct carl9170fw_dbg_desc))
+
+#define CARL9170FW_CHK_DESC_MIN_VER 1
+#define CARL9170FW_CHK_DESC_CUR_VER 2
+struct carl9170fw_chk_desc {
+ struct carl9170fw_desc_head head;
+ __le32 fw_crc32;
+ __le32 hdr_crc32;
+} __packed;
+#define CARL9170FW_CHK_DESC_SIZE \
+ (sizeof(struct carl9170fw_chk_desc))
+
+#define CARL9170FW_LAST_DESC_MIN_VER 1
+#define CARL9170FW_LAST_DESC_CUR_VER 2
+struct carl9170fw_last_desc {
+ struct carl9170fw_desc_head head;
+} __packed;
+#define CARL9170FW_LAST_DESC_SIZE \
+ (sizeof(struct carl9170fw_fix_desc))
+
+#define CARL9170FW_DESC_MAX_LENGTH 8192
+
+#define CARL9170FW_FILL_DESC(_magic, _length, _min_ver, _cur_ver) \
+ .head = { \
+ .magic = _magic, \
+ .length = cpu_to_le16(_length), \
+ .min_ver = _min_ver, \
+ .cur_ver = _cur_ver, \
+ }
+
+static inline void carl9170fw_fill_desc(struct carl9170fw_desc_head *head,
+ u8 magic[4], __le16 length,
+ u8 min_ver, u8 cur_ver)
+{
+ head->magic[0] = magic[0];
+ head->magic[1] = magic[1];
+ head->magic[2] = magic[2];
+ head->magic[3] = magic[3];
+
+ head->length = length;
+ head->min_ver = min_ver;
+ head->cur_ver = cur_ver;
+}
+
+#define carl9170fw_for_each_hdr(desc, fw_desc) \
+ for (desc = fw_desc; \
+ memcmp(desc->magic, LAST_MAGIC, 4) && \
+ le16_to_cpu(desc->length) >= CARL9170FW_DESC_HEAD_SIZE && \
+ le16_to_cpu(desc->length) < CARL9170FW_DESC_MAX_LENGTH; \
+ desc = (void *)((unsigned long)desc + le16_to_cpu(desc->length)))
+
+#define CHECK_HDR_VERSION(head, _min_ver) \
+ (((head)->cur_ver < _min_ver) || ((head)->min_ver > _min_ver)) \
+
+static inline bool carl9170fw_supports(__le32 list, u8 feature)
+{
+ return le32_to_cpu(list) & BIT(feature);
+}
+
+static inline bool carl9170fw_desc_cmp(const struct carl9170fw_desc_head *head,
+ const u8 descid[4], u16 min_len,
+ u8 compatible_revision)
+{
+ if (descid[0] == head->magic[0] && descid[1] == head->magic[1] &&
+ descid[2] == head->magic[2] && descid[3] == head->magic[3] &&
+ !CHECK_HDR_VERSION(head, compatible_revision) &&
+ (le16_to_cpu(head->length) >= min_len))
+ return true;
+
+ return false;
+}
+
+#define CARL9170FW_MIN_SIZE 32
+#define CARL9170FW_MAX_SIZE 16384
+
+static inline bool carl9170fw_size_check(unsigned int len)
+{
+ return (len <= CARL9170FW_MAX_SIZE && len >= CARL9170FW_MIN_SIZE);
+}
+
+#endif /* __CARL9170_SHARED_FWDESC_H */
diff --git a/drivers/net/wireless/ath/carl9170/hw.h b/drivers/net/wireless/ath/carl9170/hw.h
new file mode 100644
index 000000000000..2f471b3f05af
--- /dev/null
+++ b/drivers/net/wireless/ath/carl9170/hw.h
@@ -0,0 +1,739 @@
+/*
+ * Shared Atheros AR9170 Header
+ *
+ * Register map, hardware-specific definitions
+ *
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ * Copyright (c) 2007-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __CARL9170_SHARED_HW_H
+#define __CARL9170_SHARED_HW_H
+
+/* High Speed UART */
+#define AR9170_UART_REG_BASE 0x1c0000
+
+/* Definitions of interrupt registers */
+#define AR9170_UART_REG_RX_BUFFER (AR9170_UART_REG_BASE + 0x000)
+#define AR9170_UART_REG_TX_HOLDING (AR9170_UART_REG_BASE + 0x004)
+#define AR9170_UART_REG_FIFO_CONTROL (AR9170_UART_REG_BASE + 0x010)
+#define AR9170_UART_FIFO_CTRL_RESET_RX_FIFO 0x02
+#define AR9170_UART_FIFO_CTRL_RESET_TX_FIFO 0x04
+
+#define AR9170_UART_REG_LINE_CONTROL (AR9170_UART_REG_BASE + 0x014)
+#define AR9170_UART_REG_MODEM_CONTROL (AR9170_UART_REG_BASE + 0x018)
+#define AR9170_UART_MODEM_CTRL_DTR_BIT 0x01
+#define AR9170_UART_MODEM_CTRL_RTS_BIT 0x02
+#define AR9170_UART_MODEM_CTRL_INTERNAL_LOOP_BACK 0x10
+#define AR9170_UART_MODEM_CTRL_AUTO_RTS 0x20
+#define AR9170_UART_MODEM_CTRL_AUTO_CTR 0x40
+
+#define AR9170_UART_REG_LINE_STATUS (AR9170_UART_REG_BASE + 0x01c)
+#define AR9170_UART_LINE_STS_RX_DATA_READY 0x01
+#define AR9170_UART_LINE_STS_RX_BUFFER_OVERRUN 0x02
+#define AR9170_UART_LINE_STS_RX_BREAK_IND 0x10
+#define AR9170_UART_LINE_STS_TX_FIFO_NEAR_EMPTY 0x20
+#define AR9170_UART_LINE_STS_TRANSMITTER_EMPTY 0x40
+
+#define AR9170_UART_REG_MODEM_STATUS (AR9170_UART_REG_BASE + 0x020)
+#define AR9170_UART_MODEM_STS_CTS_CHANGE 0x01
+#define AR9170_UART_MODEM_STS_DSR_CHANGE 0x02
+#define AR9170_UART_MODEM_STS_DCD_CHANGE 0x08
+#define AR9170_UART_MODEM_STS_CTS_COMPL 0x10
+#define AR9170_UART_MODEM_STS_DSR_COMPL 0x20
+#define AR9170_UART_MODEM_STS_DCD_COMPL 0x80
+
+#define AR9170_UART_REG_SCRATCH (AR9170_UART_REG_BASE + 0x024)
+#define AR9170_UART_REG_DIVISOR_LSB (AR9170_UART_REG_BASE + 0x028)
+#define AR9170_UART_REG_DIVISOR_MSB (AR9170_UART_REG_BASE + 0x02c)
+#define AR9170_UART_REG_WORD_RX_BUFFER (AR9170_UART_REG_BASE + 0x034)
+#define AR9170_UART_REG_WORD_TX_HOLDING (AR9170_UART_REG_BASE + 0x038)
+#define AR9170_UART_REG_FIFO_COUNT (AR9170_UART_REG_BASE + 0x03c)
+#define AR9170_UART_REG_REMAINDER (AR9170_UART_REG_BASE + 0x04c)
+
+/* Timer */
+#define AR9170_TIMER_REG_BASE 0x1c1000
+
+#define AR9170_TIMER_REG_WATCH_DOG (AR9170_TIMER_REG_BASE + 0x000)
+#define AR9170_TIMER_REG_TIMER0 (AR9170_TIMER_REG_BASE + 0x010)
+#define AR9170_TIMER_REG_TIMER1 (AR9170_TIMER_REG_BASE + 0x014)
+#define AR9170_TIMER_REG_TIMER2 (AR9170_TIMER_REG_BASE + 0x018)
+#define AR9170_TIMER_REG_TIMER3 (AR9170_TIMER_REG_BASE + 0x01c)
+#define AR9170_TIMER_REG_TIMER4 (AR9170_TIMER_REG_BASE + 0x020)
+#define AR9170_TIMER_REG_CONTROL (AR9170_TIMER_REG_BASE + 0x024)
+#define AR9170_TIMER_CTRL_DISABLE_CLOCK 0x100
+
+#define AR9170_TIMER_REG_INTERRUPT (AR9170_TIMER_REG_BASE + 0x028)
+#define AR9170_TIMER_INT_TIMER0 0x001
+#define AR9170_TIMER_INT_TIMER1 0x002
+#define AR9170_TIMER_INT_TIMER2 0x004
+#define AR9170_TIMER_INT_TIMER3 0x008
+#define AR9170_TIMER_INT_TIMER4 0x010
+#define AR9170_TIMER_INT_TICK_TIMER 0x100
+
+#define AR9170_TIMER_REG_TICK_TIMER (AR9170_TIMER_REG_BASE + 0x030)
+#define AR9170_TIMER_REG_CLOCK_LOW (AR9170_TIMER_REG_BASE + 0x040)
+#define AR9170_TIMER_REG_CLOCK_HIGH (AR9170_TIMER_REG_BASE + 0x044)
+
+#define AR9170_MAC_REG_BASE 0x1c3000
+
+#define AR9170_MAC_REG_POWER_STATE_CTRL (AR9170_MAC_REG_BASE + 0x500)
+#define AR9170_MAC_POWER_STATE_CTRL_RESET 0x20
+
+#define AR9170_MAC_REG_MAC_POWER_STATE_CTRL (AR9170_MAC_REG_BASE + 0x50c)
+
+#define AR9170_MAC_REG_INT_CTRL (AR9170_MAC_REG_BASE + 0x510)
+#define AR9170_MAC_INT_TXC BIT(0)
+#define AR9170_MAC_INT_RXC BIT(1)
+#define AR9170_MAC_INT_RETRY_FAIL BIT(2)
+#define AR9170_MAC_INT_WAKEUP BIT(3)
+#define AR9170_MAC_INT_ATIM BIT(4)
+#define AR9170_MAC_INT_DTIM BIT(5)
+#define AR9170_MAC_INT_CFG_BCN BIT(6)
+#define AR9170_MAC_INT_ABORT BIT(7)
+#define AR9170_MAC_INT_QOS BIT(8)
+#define AR9170_MAC_INT_MIMO_PS BIT(9)
+#define AR9170_MAC_INT_KEY_GEN BIT(10)
+#define AR9170_MAC_INT_DECRY_NOUSER BIT(11)
+#define AR9170_MAC_INT_RADAR BIT(12)
+#define AR9170_MAC_INT_QUIET_FRAME BIT(13)
+#define AR9170_MAC_INT_PRETBTT BIT(14)
+
+#define AR9170_MAC_REG_TSF_L (AR9170_MAC_REG_BASE + 0x514)
+#define AR9170_MAC_REG_TSF_H (AR9170_MAC_REG_BASE + 0x518)
+
+#define AR9170_MAC_REG_ATIM_WINDOW (AR9170_MAC_REG_BASE + 0x51c)
+#define AR9170_MAC_ATIM_PERIOD_S 0
+#define AR9170_MAC_ATIM_PERIOD 0x0000ffff
+
+#define AR9170_MAC_REG_BCN_PERIOD (AR9170_MAC_REG_BASE + 0x520)
+#define AR9170_MAC_BCN_PERIOD_S 0
+#define AR9170_MAC_BCN_PERIOD 0x0000ffff
+#define AR9170_MAC_BCN_DTIM_S 16
+#define AR9170_MAC_BCN_DTIM 0x00ff0000
+#define AR9170_MAC_BCN_AP_MODE BIT(24)
+#define AR9170_MAC_BCN_IBSS_MODE BIT(25)
+#define AR9170_MAC_BCN_PWR_MGT BIT(26)
+#define AR9170_MAC_BCN_STA_PS BIT(27)
+
+#define AR9170_MAC_REG_PRETBTT (AR9170_MAC_REG_BASE + 0x524)
+#define AR9170_MAC_PRETBTT_S 0
+#define AR9170_MAC_PRETBTT 0x0000ffff
+#define AR9170_MAC_PRETBTT2_S 16
+#define AR9170_MAC_PRETBTT2 0xffff0000
+
+#define AR9170_MAC_REG_MAC_ADDR_L (AR9170_MAC_REG_BASE + 0x610)
+#define AR9170_MAC_REG_MAC_ADDR_H (AR9170_MAC_REG_BASE + 0x614)
+#define AR9170_MAC_REG_BSSID_L (AR9170_MAC_REG_BASE + 0x618)
+#define AR9170_MAC_REG_BSSID_H (AR9170_MAC_REG_BASE + 0x61c)
+
+#define AR9170_MAC_REG_GROUP_HASH_TBL_L (AR9170_MAC_REG_BASE + 0x624)
+#define AR9170_MAC_REG_GROUP_HASH_TBL_H (AR9170_MAC_REG_BASE + 0x628)
+
+#define AR9170_MAC_REG_RX_TIMEOUT (AR9170_MAC_REG_BASE + 0x62c)
+
+#define AR9170_MAC_REG_BASIC_RATE (AR9170_MAC_REG_BASE + 0x630)
+#define AR9170_MAC_REG_MANDATORY_RATE (AR9170_MAC_REG_BASE + 0x634)
+#define AR9170_MAC_REG_RTS_CTS_RATE (AR9170_MAC_REG_BASE + 0x638)
+#define AR9170_MAC_REG_BACKOFF_PROTECT (AR9170_MAC_REG_BASE + 0x63c)
+#define AR9170_MAC_REG_RX_THRESHOLD (AR9170_MAC_REG_BASE + 0x640)
+#define AR9170_MAC_REG_AFTER_PNP (AR9170_MAC_REG_BASE + 0x648)
+#define AR9170_MAC_REG_RX_PE_DELAY (AR9170_MAC_REG_BASE + 0x64c)
+
+#define AR9170_MAC_REG_DYNAMIC_SIFS_ACK (AR9170_MAC_REG_BASE + 0x658)
+#define AR9170_MAC_REG_SNIFFER (AR9170_MAC_REG_BASE + 0x674)
+#define AR9170_MAC_SNIFFER_ENABLE_PROMISC BIT(0)
+#define AR9170_MAC_SNIFFER_DEFAULTS 0x02000000
+#define AR9170_MAC_REG_ENCRYPTION (AR9170_MAC_REG_BASE + 0x678)
+#define AR9170_MAC_ENCRYPTION_RX_SOFTWARE BIT(3)
+#define AR9170_MAC_ENCRYPTION_DEFAULTS 0x70
+
+#define AR9170_MAC_REG_MISC_680 (AR9170_MAC_REG_BASE + 0x680)
+#define AR9170_MAC_REG_MISC_684 (AR9170_MAC_REG_BASE + 0x684)
+#define AR9170_MAC_REG_TX_UNDERRUN (AR9170_MAC_REG_BASE + 0x688)
+
+#define AR9170_MAC_REG_FRAMETYPE_FILTER (AR9170_MAC_REG_BASE + 0x68c)
+#define AR9170_MAC_FTF_ASSOC_REQ BIT(0)
+#define AR9170_MAC_FTF_ASSOC_RESP BIT(1)
+#define AR9170_MAC_FTF_REASSOC_REQ BIT(2)
+#define AR9170_MAC_FTF_REASSOC_RESP BIT(3)
+#define AR9170_MAC_FTF_PRB_REQ BIT(4)
+#define AR9170_MAC_FTF_PRB_RESP BIT(5)
+#define AR9170_MAC_FTF_BIT6 BIT(6)
+#define AR9170_MAC_FTF_BIT7 BIT(7)
+#define AR9170_MAC_FTF_BEACON BIT(8)
+#define AR9170_MAC_FTF_ATIM BIT(9)
+#define AR9170_MAC_FTF_DEASSOC BIT(10)
+#define AR9170_MAC_FTF_AUTH BIT(11)
+#define AR9170_MAC_FTF_DEAUTH BIT(12)
+#define AR9170_MAC_FTF_BIT13 BIT(13)
+#define AR9170_MAC_FTF_BIT14 BIT(14)
+#define AR9170_MAC_FTF_BIT15 BIT(15)
+#define AR9170_MAC_FTF_BAR BIT(24)
+#define AR9170_MAC_FTF_BA BIT(25)
+#define AR9170_MAC_FTF_PSPOLL BIT(26)
+#define AR9170_MAC_FTF_RTS BIT(27)
+#define AR9170_MAC_FTF_CTS BIT(28)
+#define AR9170_MAC_FTF_ACK BIT(29)
+#define AR9170_MAC_FTF_CFE BIT(30)
+#define AR9170_MAC_FTF_CFE_ACK BIT(31)
+#define AR9170_MAC_FTF_DEFAULTS 0x0500ffff
+#define AR9170_MAC_FTF_MONITOR 0xff00ffff
+
+#define AR9170_MAC_REG_ACK_EXTENSION (AR9170_MAC_REG_BASE + 0x690)
+#define AR9170_MAC_REG_ACK_TPC (AR9170_MAC_REG_BASE + 0x694)
+#define AR9170_MAC_REG_EIFS_AND_SIFS (AR9170_MAC_REG_BASE + 0x698)
+#define AR9170_MAC_REG_RX_TIMEOUT_COUNT (AR9170_MAC_REG_BASE + 0x69c)
+#define AR9170_MAC_REG_RX_TOTAL (AR9170_MAC_REG_BASE + 0x6a0)
+#define AR9170_MAC_REG_RX_CRC32 (AR9170_MAC_REG_BASE + 0x6a4)
+#define AR9170_MAC_REG_RX_CRC16 (AR9170_MAC_REG_BASE + 0x6a8)
+#define AR9170_MAC_REG_RX_ERR_DECRYPTION_UNI (AR9170_MAC_REG_BASE + 0x6ac)
+#define AR9170_MAC_REG_RX_OVERRUN (AR9170_MAC_REG_BASE + 0x6b0)
+#define AR9170_MAC_REG_RX_ERR_DECRYPTION_MUL (AR9170_MAC_REG_BASE + 0x6bc)
+#define AR9170_MAC_REG_TX_BLOCKACKS (AR9170_MAC_REG_BASE + 0x6c0)
+#define AR9170_MAC_REG_NAV_COUNT (AR9170_MAC_REG_BASE + 0x6c4)
+#define AR9170_MAC_REG_BACKOFF_STATUS (AR9170_MAC_REG_BASE + 0x6c8)
+#define AR9170_MAC_REG_TX_RETRY (AR9170_MAC_REG_BASE + 0x6cc)
+
+#define AR9170_MAC_REG_TX_COMPLETE (AR9170_MAC_REG_BASE + 0x6d4)
+
+#define AR9170_MAC_REG_CHANNEL_BUSY (AR9170_MAC_REG_BASE + 0x6e8)
+#define AR9170_MAC_REG_EXT_BUSY (AR9170_MAC_REG_BASE + 0x6ec)
+
+#define AR9170_MAC_REG_SLOT_TIME (AR9170_MAC_REG_BASE + 0x6f0)
+#define AR9170_MAC_REG_TX_TOTAL (AR9170_MAC_REG_BASE + 0x6f4)
+#define AR9170_MAC_REG_ACK_FC (AR9170_MAC_REG_BASE + 0x6f8)
+
+#define AR9170_MAC_REG_CAM_MODE (AR9170_MAC_REG_BASE + 0x700)
+#define AR9170_MAC_CAM_IBSS 0xe0
+#define AR9170_MAC_CAM_AP 0xa1
+#define AR9170_MAC_CAM_STA 0x2
+#define AR9170_MAC_CAM_AP_WDS 0x3
+#define AR9170_MAC_CAM_DEFAULTS (0xf << 24)
+#define AR9170_MAC_CAM_HOST_PENDING 0x80000000
+
+#define AR9170_MAC_REG_CAM_ROLL_CALL_TBL_L (AR9170_MAC_REG_BASE + 0x704)
+#define AR9170_MAC_REG_CAM_ROLL_CALL_TBL_H (AR9170_MAC_REG_BASE + 0x708)
+
+#define AR9170_MAC_REG_CAM_ADDR (AR9170_MAC_REG_BASE + 0x70c)
+#define AR9170_MAC_CAM_ADDR_WRITE 0x80000000
+#define AR9170_MAC_REG_CAM_DATA0 (AR9170_MAC_REG_BASE + 0x720)
+#define AR9170_MAC_REG_CAM_DATA1 (AR9170_MAC_REG_BASE + 0x724)
+#define AR9170_MAC_REG_CAM_DATA2 (AR9170_MAC_REG_BASE + 0x728)
+#define AR9170_MAC_REG_CAM_DATA3 (AR9170_MAC_REG_BASE + 0x72c)
+
+#define AR9170_MAC_REG_CAM_DBG0 (AR9170_MAC_REG_BASE + 0x730)
+#define AR9170_MAC_REG_CAM_DBG1 (AR9170_MAC_REG_BASE + 0x734)
+#define AR9170_MAC_REG_CAM_DBG2 (AR9170_MAC_REG_BASE + 0x738)
+#define AR9170_MAC_REG_CAM_STATE (AR9170_MAC_REG_BASE + 0x73c)
+#define AR9170_MAC_CAM_STATE_READ_PENDING 0x40000000
+#define AR9170_MAC_CAM_STATE_WRITE_PENDING 0x80000000
+
+#define AR9170_MAC_REG_CAM_TXKEY (AR9170_MAC_REG_BASE + 0x740)
+#define AR9170_MAC_REG_CAM_RXKEY (AR9170_MAC_REG_BASE + 0x750)
+
+#define AR9170_MAC_REG_CAM_TX_ENC_TYPE (AR9170_MAC_REG_BASE + 0x760)
+#define AR9170_MAC_REG_CAM_RX_ENC_TYPE (AR9170_MAC_REG_BASE + 0x770)
+#define AR9170_MAC_REG_CAM_TX_SERACH_HIT (AR9170_MAC_REG_BASE + 0x780)
+#define AR9170_MAC_REG_CAM_RX_SERACH_HIT (AR9170_MAC_REG_BASE + 0x790)
+
+#define AR9170_MAC_REG_AC0_CW (AR9170_MAC_REG_BASE + 0xb00)
+#define AR9170_MAC_REG_AC1_CW (AR9170_MAC_REG_BASE + 0xb04)
+#define AR9170_MAC_REG_AC2_CW (AR9170_MAC_REG_BASE + 0xb08)
+#define AR9170_MAC_REG_AC3_CW (AR9170_MAC_REG_BASE + 0xb0c)
+#define AR9170_MAC_REG_AC4_CW (AR9170_MAC_REG_BASE + 0xb10)
+#define AR9170_MAC_REG_AC2_AC1_AC0_AIFS (AR9170_MAC_REG_BASE + 0xb14)
+#define AR9170_MAC_REG_AC4_AC3_AC2_AIFS (AR9170_MAC_REG_BASE + 0xb18)
+#define AR9170_MAC_REG_TXOP_ACK_EXTENSION (AR9170_MAC_REG_BASE + 0xb1c)
+#define AR9170_MAC_REG_TXOP_ACK_INTERVAL (AR9170_MAC_REG_BASE + 0xb20)
+#define AR9170_MAC_REG_CONTENTION_POINT (AR9170_MAC_REG_BASE + 0xb24)
+#define AR9170_MAC_REG_RETRY_MAX (AR9170_MAC_REG_BASE + 0xb28)
+#define AR9170_MAC_REG_TID_CFACK_CFEND_RATE (AR9170_MAC_REG_BASE + 0xb2c)
+#define AR9170_MAC_REG_TXOP_NOT_ENOUGH_IND (AR9170_MAC_REG_BASE + 0xb30)
+#define AR9170_MAC_REG_TKIP_TSC (AR9170_MAC_REG_BASE + 0xb34)
+#define AR9170_MAC_REG_TXOP_DURATION (AR9170_MAC_REG_BASE + 0xb38)
+#define AR9170_MAC_REG_TX_QOS_THRESHOLD (AR9170_MAC_REG_BASE + 0xb3c)
+#define AR9170_MAC_REG_QOS_PRIORITY_VIRTUAL_CCA (AR9170_MAC_REG_BASE + 0xb40)
+#define AR9170_MAC_VIRTUAL_CCA_Q0 BIT(15)
+#define AR9170_MAC_VIRTUAL_CCA_Q1 BIT(16)
+#define AR9170_MAC_VIRTUAL_CCA_Q2 BIT(17)
+#define AR9170_MAC_VIRTUAL_CCA_Q3 BIT(18)
+#define AR9170_MAC_VIRTUAL_CCA_Q4 BIT(19)
+#define AR9170_MAC_VIRTUAL_CCA_ALL (0xf8000)
+
+#define AR9170_MAC_REG_AC1_AC0_TXOP (AR9170_MAC_REG_BASE + 0xb44)
+#define AR9170_MAC_REG_AC3_AC2_TXOP (AR9170_MAC_REG_BASE + 0xb48)
+
+#define AR9170_MAC_REG_AMPDU_COUNT (AR9170_MAC_REG_BASE + 0xb88)
+#define AR9170_MAC_REG_MPDU_COUNT (AR9170_MAC_REG_BASE + 0xb8c)
+
+#define AR9170_MAC_REG_AMPDU_FACTOR (AR9170_MAC_REG_BASE + 0xb9c)
+#define AR9170_MAC_AMPDU_FACTOR 0x7f0000
+#define AR9170_MAC_AMPDU_FACTOR_S 16
+#define AR9170_MAC_REG_AMPDU_DENSITY (AR9170_MAC_REG_BASE + 0xba0)
+#define AR9170_MAC_AMPDU_DENSITY 0x7
+#define AR9170_MAC_AMPDU_DENSITY_S 0
+
+#define AR9170_MAC_REG_FCS_SELECT (AR9170_MAC_REG_BASE + 0xbb0)
+#define AR9170_MAC_FCS_SWFCS 0x1
+#define AR9170_MAC_FCS_FIFO_PROT 0x4
+
+#define AR9170_MAC_REG_RTS_CTS_TPC (AR9170_MAC_REG_BASE + 0xbb4)
+#define AR9170_MAC_REG_CFEND_QOSNULL_TPC (AR9170_MAC_REG_BASE + 0xbb8)
+
+#define AR9170_MAC_REG_ACK_TABLE (AR9170_MAC_REG_BASE + 0xc00)
+#define AR9170_MAC_REG_RX_CONTROL (AR9170_MAC_REG_BASE + 0xc40)
+#define AR9170_MAC_RX_CTRL_DEAGG 0x1
+#define AR9170_MAC_RX_CTRL_SHORT_FILTER 0x2
+#define AR9170_MAC_RX_CTRL_SA_DA_SEARCH 0x20
+#define AR9170_MAC_RX_CTRL_PASS_TO_HOST BIT(28)
+#define AR9170_MAC_RX_CTRL_ACK_IN_SNIFFER BIT(30)
+
+#define AR9170_MAC_REG_RX_CONTROL_1 (AR9170_MAC_REG_BASE + 0xc44)
+
+#define AR9170_MAC_REG_AMPDU_RX_THRESH (AR9170_MAC_REG_BASE + 0xc50)
+
+#define AR9170_MAC_REG_RX_MPDU (AR9170_MAC_REG_BASE + 0xca0)
+#define AR9170_MAC_REG_RX_DROPPED_MPDU (AR9170_MAC_REG_BASE + 0xca4)
+#define AR9170_MAC_REG_RX_DEL_MPDU (AR9170_MAC_REG_BASE + 0xca8)
+#define AR9170_MAC_REG_RX_PHY_MISC_ERROR (AR9170_MAC_REG_BASE + 0xcac)
+#define AR9170_MAC_REG_RX_PHY_XR_ERROR (AR9170_MAC_REG_BASE + 0xcb0)
+#define AR9170_MAC_REG_RX_PHY_OFDM_ERROR (AR9170_MAC_REG_BASE + 0xcb4)
+#define AR9170_MAC_REG_RX_PHY_CCK_ERROR (AR9170_MAC_REG_BASE + 0xcb8)
+#define AR9170_MAC_REG_RX_PHY_HT_ERROR (AR9170_MAC_REG_BASE + 0xcbc)
+#define AR9170_MAC_REG_RX_PHY_TOTAL (AR9170_MAC_REG_BASE + 0xcc0)
+
+#define AR9170_MAC_REG_DMA_TXQ_ADDR (AR9170_MAC_REG_BASE + 0xd00)
+#define AR9170_MAC_REG_DMA_TXQ_CURR_ADDR (AR9170_MAC_REG_BASE + 0xd04)
+#define AR9170_MAC_REG_DMA_TXQ0_ADDR (AR9170_MAC_REG_BASE + 0xd00)
+#define AR9170_MAC_REG_DMA_TXQ0_CURR_ADDR (AR9170_MAC_REG_BASE + 0xd04)
+#define AR9170_MAC_REG_DMA_TXQ1_ADDR (AR9170_MAC_REG_BASE + 0xd08)
+#define AR9170_MAC_REG_DMA_TXQ1_CURR_ADDR (AR9170_MAC_REG_BASE + 0xd0c)
+#define AR9170_MAC_REG_DMA_TXQ2_ADDR (AR9170_MAC_REG_BASE + 0xd10)
+#define AR9170_MAC_REG_DMA_TXQ2_CURR_ADDR (AR9170_MAC_REG_BASE + 0xd14)
+#define AR9170_MAC_REG_DMA_TXQ3_ADDR (AR9170_MAC_REG_BASE + 0xd18)
+#define AR9170_MAC_REG_DMA_TXQ3_CURR_ADDR (AR9170_MAC_REG_BASE + 0xd1c)
+#define AR9170_MAC_REG_DMA_TXQ4_ADDR (AR9170_MAC_REG_BASE + 0xd20)
+#define AR9170_MAC_REG_DMA_TXQ4_CURR_ADDR (AR9170_MAC_REG_BASE + 0xd24)
+#define AR9170_MAC_REG_DMA_RXQ_ADDR (AR9170_MAC_REG_BASE + 0xd28)
+#define AR9170_MAC_REG_DMA_RXQ_CURR_ADDR (AR9170_MAC_REG_BASE + 0xd2c)
+
+#define AR9170_MAC_REG_DMA_TRIGGER (AR9170_MAC_REG_BASE + 0xd30)
+#define AR9170_DMA_TRIGGER_TXQ0 BIT(0)
+#define AR9170_DMA_TRIGGER_TXQ1 BIT(1)
+#define AR9170_DMA_TRIGGER_TXQ2 BIT(2)
+#define AR9170_DMA_TRIGGER_TXQ3 BIT(3)
+#define AR9170_DMA_TRIGGER_TXQ4 BIT(4)
+#define AR9170_DMA_TRIGGER_RXQ BIT(8)
+
+#define AR9170_MAC_REG_DMA_WLAN_STATUS (AR9170_MAC_REG_BASE + 0xd38)
+#define AR9170_MAC_REG_DMA_STATUS (AR9170_MAC_REG_BASE + 0xd3c)
+
+#define AR9170_MAC_REG_TXRX_MPI (AR9170_MAC_REG_BASE + 0xd7c)
+#define AR9170_MAC_TXRX_MPI_TX_MPI_MASK 0x0000000f
+#define AR9170_MAC_TXRX_MPI_TX_TO_MASK 0x0000fff0
+#define AR9170_MAC_TXRX_MPI_RX_MPI_MASK 0x000f0000
+#define AR9170_MAC_TXRX_MPI_RX_TO_MASK 0xfff00000
+
+#define AR9170_MAC_REG_BCN_ADDR (AR9170_MAC_REG_BASE + 0xd84)
+#define AR9170_MAC_REG_BCN_LENGTH (AR9170_MAC_REG_BASE + 0xd88)
+#define AR9170_MAC_BCN_LENGTH_MAX 256
+
+#define AR9170_MAC_REG_BCN_STATUS (AR9170_MAC_REG_BASE + 0xd8c)
+
+#define AR9170_MAC_REG_BCN_PLCP (AR9170_MAC_REG_BASE + 0xd90)
+#define AR9170_MAC_REG_BCN_CTRL (AR9170_MAC_REG_BASE + 0xd94)
+#define AR9170_BCN_CTRL_READY 0x01
+#define AR9170_BCN_CTRL_LOCK 0x02
+
+#define AR9170_MAC_REG_BCN_CURR_ADDR (AR9170_MAC_REG_BASE + 0xd98)
+#define AR9170_MAC_REG_BCN_COUNT (AR9170_MAC_REG_BASE + 0xd9c)
+
+
+#define AR9170_MAC_REG_BCN_HT1 (AR9170_MAC_REG_BASE + 0xda0)
+#define AR9170_MAC_REG_BCN_HT2 (AR9170_MAC_REG_BASE + 0xda4)
+
+#define AR9170_MAC_REG_DMA_TXQX_ADDR_CURR (AR9170_MAC_REG_BASE + 0xdc0)
+
+/* Random number generator */
+#define AR9170_RAND_REG_BASE 0x1d0000
+
+#define AR9170_RAND_REG_NUM (AR9170_RAND_REG_BASE + 0x000)
+#define AR9170_RAND_REG_MODE (AR9170_RAND_REG_BASE + 0x004)
+#define AR9170_RAND_MODE_MANUAL 0x000
+#define AR9170_RAND_MODE_FREE 0x001
+
+/* GPIO */
+#define AR9170_GPIO_REG_BASE 0x1d0100
+#define AR9170_GPIO_REG_PORT_TYPE (AR9170_GPIO_REG_BASE + 0x000)
+#define AR9170_GPIO_REG_PORT_DATA (AR9170_GPIO_REG_BASE + 0x004)
+#define AR9170_GPIO_PORT_LED_0 1
+#define AR9170_GPIO_PORT_LED_1 2
+/* WPS Button GPIO for TP-Link TL-WN821N */
+#define AR9170_GPIO_PORT_WPS_BUTTON_PRESSED 4
+
+/* Memory Controller */
+#define AR9170_MC_REG_BASE 0x1d1000
+
+#define AR9170_MC_REG_FLASH_WAIT_STATE (AR9170_MC_REG_BASE + 0x000)
+#define AR9170_MC_REG_SEEPROM_WP0 (AR9170_MC_REG_BASE + 0x400)
+#define AR9170_MC_REG_SEEPROM_WP1 (AR9170_MC_REG_BASE + 0x404)
+#define AR9170_MC_REG_SEEPROM_WP2 (AR9170_MC_REG_BASE + 0x408)
+
+/* Interrupt Controller */
+#define AR9170_MAX_INT_SRC 9
+#define AR9170_INT_REG_BASE 0x1d2000
+
+#define AR9170_INT_REG_FLAG (AR9170_INT_REG_BASE + 0x000)
+#define AR9170_INT_REG_FIQ_MASK (AR9170_INT_REG_BASE + 0x004)
+#define AR9170_INT_REG_IRQ_MASK (AR9170_INT_REG_BASE + 0x008)
+/* INT_REG_FLAG, INT_REG_FIQ_MASK and INT_REG_IRQ_MASK */
+#define AR9170_INT_FLAG_WLAN 0x001
+#define AR9170_INT_FLAG_PTAB_BIT 0x002
+#define AR9170_INT_FLAG_SE_BIT 0x004
+#define AR9170_INT_FLAG_UART_BIT 0x008
+#define AR9170_INT_FLAG_TIMER_BIT 0x010
+#define AR9170_INT_FLAG_EXT_BIT 0x020
+#define AR9170_INT_FLAG_SW_BIT 0x040
+#define AR9170_INT_FLAG_USB_BIT 0x080
+#define AR9170_INT_FLAG_ETHERNET_BIT 0x100
+
+#define AR9170_INT_REG_PRIORITY1 (AR9170_INT_REG_BASE + 0x00c)
+#define AR9170_INT_REG_PRIORITY2 (AR9170_INT_REG_BASE + 0x010)
+#define AR9170_INT_REG_PRIORITY3 (AR9170_INT_REG_BASE + 0x014)
+#define AR9170_INT_REG_EXT_INT_CONTROL (AR9170_INT_REG_BASE + 0x018)
+#define AR9170_INT_REG_SW_INT_CONTROL (AR9170_INT_REG_BASE + 0x01c)
+#define AR9170_INT_SW_INT_ENABLE 0x1
+
+#define AR9170_INT_REG_FIQ_ENCODE (AR9170_INT_REG_BASE + 0x020)
+#define AR9170_INT_INT_IRQ_ENCODE (AR9170_INT_REG_BASE + 0x024)
+
+/* Power Management */
+#define AR9170_PWR_REG_BASE 0x1d4000
+
+#define AR9170_PWR_REG_POWER_STATE (AR9170_PWR_REG_BASE + 0x000)
+
+#define AR9170_PWR_REG_RESET (AR9170_PWR_REG_BASE + 0x004)
+#define AR9170_PWR_RESET_COMMIT_RESET_MASK BIT(0)
+#define AR9170_PWR_RESET_WLAN_MASK BIT(1)
+#define AR9170_PWR_RESET_DMA_MASK BIT(2)
+#define AR9170_PWR_RESET_BRIDGE_MASK BIT(3)
+#define AR9170_PWR_RESET_AHB_MASK BIT(9)
+#define AR9170_PWR_RESET_BB_WARM_RESET BIT(10)
+#define AR9170_PWR_RESET_BB_COLD_RESET BIT(11)
+#define AR9170_PWR_RESET_ADDA_CLK_COLD_RESET BIT(12)
+#define AR9170_PWR_RESET_PLL BIT(13)
+#define AR9170_PWR_RESET_USB_PLL BIT(14)
+
+#define AR9170_PWR_REG_CLOCK_SEL (AR9170_PWR_REG_BASE + 0x008)
+#define AR9170_PWR_CLK_AHB_40MHZ 0
+#define AR9170_PWR_CLK_AHB_20_22MHZ 1
+#define AR9170_PWR_CLK_AHB_40_44MHZ 2
+#define AR9170_PWR_CLK_AHB_80_88MHZ 3
+#define AR9170_PWR_CLK_DAC_160_INV_DLY 0x70
+
+#define AR9170_PWR_REG_CHIP_REVISION (AR9170_PWR_REG_BASE + 0x010)
+#define AR9170_PWR_REG_PLL_ADDAC (AR9170_PWR_REG_BASE + 0x014)
+#define AR9170_PWR_REG_WATCH_DOG_MAGIC (AR9170_PWR_REG_BASE + 0x020)
+
+/* Faraday USB Controller */
+#define AR9170_USB_REG_BASE 0x1e1000
+
+#define AR9170_USB_REG_MAIN_CTRL (AR9170_USB_REG_BASE + 0x000)
+#define AR9170_USB_MAIN_CTRL_REMOTE_WAKEUP BIT(0)
+#define AR9170_USB_MAIN_CTRL_ENABLE_GLOBAL_INT BIT(2)
+#define AR9170_USB_MAIN_CTRL_HIGHSPEED BIT(6)
+
+#define AR9170_USB_REG_DEVICE_ADDRESS (AR9170_USB_REG_BASE + 0x001)
+#define AR9170_USB_DEVICE_ADDRESS_CONFIGURE BIT(7)
+
+#define AR9170_USB_REG_TEST (AR9170_USB_REG_BASE + 0x002)
+#define AR9170_USB_REG_PHY_TEST_SELECT (AR9170_USB_REG_BASE + 0x008)
+#define AR9170_USB_REG_CX_CONFIG_STATUS (AR9170_USB_REG_BASE + 0x00b)
+#define AR9170_USB_REG_EP0_DATA (AR9170_USB_REG_BASE + 0x00c)
+#define AR9170_USB_REG_EP0_DATA1 (AR9170_USB_REG_BASE + 0x00c)
+#define AR9170_USB_REG_EP0_DATA2 (AR9170_USB_REG_BASE + 0x00d)
+
+#define AR9170_USB_REG_INTR_MASK_BYTE_0 (AR9170_USB_REG_BASE + 0x011)
+#define AR9170_USB_REG_INTR_MASK_BYTE_1 (AR9170_USB_REG_BASE + 0x012)
+#define AR9170_USB_REG_INTR_MASK_BYTE_2 (AR9170_USB_REG_BASE + 0x013)
+#define AR9170_USB_REG_INTR_MASK_BYTE_3 (AR9170_USB_REG_BASE + 0x014)
+#define AR9170_USB_REG_INTR_MASK_BYTE_4 (AR9170_USB_REG_BASE + 0x015)
+#define AR9170_USB_INTR_DISABLE_OUT_INT (BIT(7) | BIT(6))
+
+#define AR9170_USB_REG_INTR_MASK_BYTE_5 (AR9170_USB_REG_BASE + 0x016)
+#define AR9170_USB_REG_INTR_MASK_BYTE_6 (AR9170_USB_REG_BASE + 0x017)
+#define AR9170_USB_INTR_DISABLE_IN_INT BIT(6)
+
+#define AR9170_USB_REG_INTR_MASK_BYTE_7 (AR9170_USB_REG_BASE + 0x018)
+
+#define AR9170_USB_REG_INTR_GROUP (AR9170_USB_REG_BASE + 0x020)
+
+#define AR9170_USB_REG_INTR_SOURCE_0 (AR9170_USB_REG_BASE + 0x021)
+#define AR9170_USB_REG_INTR_SOURCE_1 (AR9170_USB_REG_BASE + 0x022)
+#define AR9170_USB_REG_INTR_SOURCE_2 (AR9170_USB_REG_BASE + 0x023)
+#define AR9170_USB_REG_INTR_SOURCE_3 (AR9170_USB_REG_BASE + 0x024)
+#define AR9170_USB_REG_INTR_SOURCE_4 (AR9170_USB_REG_BASE + 0x025)
+#define AR9170_USB_REG_INTR_SOURCE_5 (AR9170_USB_REG_BASE + 0x026)
+#define AR9170_USB_REG_INTR_SOURCE_6 (AR9170_USB_REG_BASE + 0x027)
+#define AR9170_USB_REG_INTR_SOURCE_7 (AR9170_USB_REG_BASE + 0x028)
+
+#define AR9170_USB_REG_EP_MAP (AR9170_USB_REG_BASE + 0x030)
+#define AR9170_USB_REG_EP1_MAP (AR9170_USB_REG_BASE + 0x030)
+#define AR9170_USB_REG_EP2_MAP (AR9170_USB_REG_BASE + 0x031)
+#define AR9170_USB_REG_EP3_MAP (AR9170_USB_REG_BASE + 0x032)
+#define AR9170_USB_REG_EP4_MAP (AR9170_USB_REG_BASE + 0x033)
+#define AR9170_USB_REG_EP5_MAP (AR9170_USB_REG_BASE + 0x034)
+#define AR9170_USB_REG_EP6_MAP (AR9170_USB_REG_BASE + 0x035)
+#define AR9170_USB_REG_EP7_MAP (AR9170_USB_REG_BASE + 0x036)
+#define AR9170_USB_REG_EP8_MAP (AR9170_USB_REG_BASE + 0x037)
+#define AR9170_USB_REG_EP9_MAP (AR9170_USB_REG_BASE + 0x038)
+#define AR9170_USB_REG_EP10_MAP (AR9170_USB_REG_BASE + 0x039)
+
+#define AR9170_USB_REG_EP_IN_MAX_SIZE_HIGH (AR9170_USB_REG_BASE + 0x03f)
+#define AR9170_USB_EP_IN_TOGGLE 0x10
+
+#define AR9170_USB_REG_EP_IN_MAX_SIZE_LOW (AR9170_USB_REG_BASE + 0x03e)
+
+#define AR9170_USB_REG_EP_OUT_MAX_SIZE_HIGH (AR9170_USB_REG_BASE + 0x05f)
+#define AR9170_USB_EP_OUT_TOGGLE 0x10
+
+#define AR9170_USB_REG_EP_OUT_MAX_SIZE_LOW (AR9170_USB_REG_BASE + 0x05e)
+
+#define AR9170_USB_REG_EP3_BYTE_COUNT_HIGH (AR9170_USB_REG_BASE + 0x0ae)
+#define AR9170_USB_REG_EP3_BYTE_COUNT_LOW (AR9170_USB_REG_BASE + 0x0be)
+#define AR9170_USB_REG_EP4_BYTE_COUNT_HIGH (AR9170_USB_REG_BASE + 0x0af)
+#define AR9170_USB_REG_EP4_BYTE_COUNT_LOW (AR9170_USB_REG_BASE + 0x0bf)
+
+#define AR9170_USB_REG_FIFO_MAP (AR9170_USB_REG_BASE + 0x080)
+#define AR9170_USB_REG_FIFO0_MAP (AR9170_USB_REG_BASE + 0x080)
+#define AR9170_USB_REG_FIFO1_MAP (AR9170_USB_REG_BASE + 0x081)
+#define AR9170_USB_REG_FIFO2_MAP (AR9170_USB_REG_BASE + 0x082)
+#define AR9170_USB_REG_FIFO3_MAP (AR9170_USB_REG_BASE + 0x083)
+#define AR9170_USB_REG_FIFO4_MAP (AR9170_USB_REG_BASE + 0x084)
+#define AR9170_USB_REG_FIFO5_MAP (AR9170_USB_REG_BASE + 0x085)
+#define AR9170_USB_REG_FIFO6_MAP (AR9170_USB_REG_BASE + 0x086)
+#define AR9170_USB_REG_FIFO7_MAP (AR9170_USB_REG_BASE + 0x087)
+#define AR9170_USB_REG_FIFO8_MAP (AR9170_USB_REG_BASE + 0x088)
+#define AR9170_USB_REG_FIFO9_MAP (AR9170_USB_REG_BASE + 0x089)
+
+#define AR9170_USB_REG_FIFO_CONFIG (AR9170_USB_REG_BASE + 0x090)
+#define AR9170_USB_REG_FIFO0_CONFIG (AR9170_USB_REG_BASE + 0x090)
+#define AR9170_USB_REG_FIFO1_CONFIG (AR9170_USB_REG_BASE + 0x091)
+#define AR9170_USB_REG_FIFO2_CONFIG (AR9170_USB_REG_BASE + 0x092)
+#define AR9170_USB_REG_FIFO3_CONFIG (AR9170_USB_REG_BASE + 0x093)
+#define AR9170_USB_REG_FIFO4_CONFIG (AR9170_USB_REG_BASE + 0x094)
+#define AR9170_USB_REG_FIFO5_CONFIG (AR9170_USB_REG_BASE + 0x095)
+#define AR9170_USB_REG_FIFO6_CONFIG (AR9170_USB_REG_BASE + 0x096)
+#define AR9170_USB_REG_FIFO7_CONFIG (AR9170_USB_REG_BASE + 0x097)
+#define AR9170_USB_REG_FIFO8_CONFIG (AR9170_USB_REG_BASE + 0x098)
+#define AR9170_USB_REG_FIFO9_CONFIG (AR9170_USB_REG_BASE + 0x099)
+
+#define AR9170_USB_REG_EP3_DATA (AR9170_USB_REG_BASE + 0x0f8)
+#define AR9170_USB_REG_EP4_DATA (AR9170_USB_REG_BASE + 0x0fc)
+
+#define AR9170_USB_REG_FIFO_SIZE (AR9170_USB_REG_BASE + 0x100)
+#define AR9170_USB_REG_DMA_CTL (AR9170_USB_REG_BASE + 0x108)
+#define AR9170_USB_DMA_CTL_ENABLE_TO_DEVICE BIT(0)
+#define AR9170_USB_DMA_CTL_ENABLE_FROM_DEVICE BIT(1)
+#define AR9170_USB_DMA_CTL_HIGH_SPEED BIT(2)
+#define AR9170_USB_DMA_CTL_UP_PACKET_MODE BIT(3)
+#define AR9170_USB_DMA_CTL_UP_STREAM_S 4
+#define AR9170_USB_DMA_CTL_UP_STREAM (BIT(4) | BIT(5))
+#define AR9170_USB_DMA_CTL_UP_STREAM_4K (0)
+#define AR9170_USB_DMA_CTL_UP_STREAM_8K BIT(4)
+#define AR9170_USB_DMA_CTL_UP_STREAM_16K BIT(5)
+#define AR9170_USB_DMA_CTL_UP_STREAM_32K (BIT(4) | BIT(5))
+#define AR9170_USB_DMA_CTL_DOWN_STREAM BIT(6)
+
+#define AR9170_USB_REG_DMA_STATUS (AR9170_USB_REG_BASE + 0x10c)
+#define AR9170_USB_DMA_STATUS_UP_IDLE BIT(8)
+#define AR9170_USB_DMA_STATUS_DN_IDLE BIT(16)
+
+#define AR9170_USB_REG_MAX_AGG_UPLOAD (AR9170_USB_REG_BASE + 0x110)
+#define AR9170_USB_REG_UPLOAD_TIME_CTL (AR9170_USB_REG_BASE + 0x114)
+#define AR9170_USB_REG_CBUS_CTRL (AR9170_USB_REG_BASE + 0x1f0)
+#define AR9170_USB_CBUS_CTRL_BUFFER_END (BIT(1))
+
+/* PCI/USB to AHB Bridge */
+#define AR9170_PTA_REG_BASE 0x1e2000
+
+#define AR9170_PTA_REG_CMD (AR9170_PTA_REG_BASE + 0x000)
+#define AR9170_PTA_REG_PARAM1 (AR9170_PTA_REG_BASE + 0x004)
+#define AR9170_PTA_REG_PARAM2 (AR9170_PTA_REG_BASE + 0x008)
+#define AR9170_PTA_REG_PARAM3 (AR9170_PTA_REG_BASE + 0x00c)
+#define AR9170_PTA_REG_RSP (AR9170_PTA_REG_BASE + 0x010)
+#define AR9170_PTA_REG_STATUS1 (AR9170_PTA_REG_BASE + 0x014)
+#define AR9170_PTA_REG_STATUS2 (AR9170_PTA_REG_BASE + 0x018)
+#define AR9170_PTA_REG_STATUS3 (AR9170_PTA_REG_BASE + 0x01c)
+#define AR9170_PTA_REG_AHB_INT_FLAG (AR9170_PTA_REG_BASE + 0x020)
+#define AR9170_PTA_REG_AHB_INT_MASK (AR9170_PTA_REG_BASE + 0x024)
+#define AR9170_PTA_REG_AHB_INT_ACK (AR9170_PTA_REG_BASE + 0x028)
+#define AR9170_PTA_REG_AHB_SCRATCH1 (AR9170_PTA_REG_BASE + 0x030)
+#define AR9170_PTA_REG_AHB_SCRATCH2 (AR9170_PTA_REG_BASE + 0x034)
+#define AR9170_PTA_REG_AHB_SCRATCH3 (AR9170_PTA_REG_BASE + 0x038)
+#define AR9170_PTA_REG_AHB_SCRATCH4 (AR9170_PTA_REG_BASE + 0x03c)
+
+#define AR9170_PTA_REG_SHARE_MEM_CTRL (AR9170_PTA_REG_BASE + 0x124)
+
+/*
+ * PCI to AHB Bridge
+ */
+
+#define AR9170_PTA_REG_INT_FLAG (AR9170_PTA_REG_BASE + 0x100)
+#define AR9170_PTA_INT_FLAG_DN 0x01
+#define AR9170_PTA_INT_FLAG_UP 0x02
+#define AR9170_PTA_INT_FLAG_CMD 0x04
+
+#define AR9170_PTA_REG_INT_MASK (AR9170_PTA_REG_BASE + 0x104)
+#define AR9170_PTA_REG_DN_DMA_ADDRL (AR9170_PTA_REG_BASE + 0x108)
+#define AR9170_PTA_REG_DN_DMA_ADDRH (AR9170_PTA_REG_BASE + 0x10c)
+#define AR9170_PTA_REG_UP_DMA_ADDRL (AR9170_PTA_REG_BASE + 0x110)
+#define AR9170_PTA_REG_UP_DMA_ADDRH (AR9170_PTA_REG_BASE + 0x114)
+#define AR9170_PTA_REG_DN_PEND_TIME (AR9170_PTA_REG_BASE + 0x118)
+#define AR9170_PTA_REG_UP_PEND_TIME (AR9170_PTA_REG_BASE + 0x11c)
+#define AR9170_PTA_REG_CONTROL (AR9170_PTA_REG_BASE + 0x120)
+#define AR9170_PTA_CTRL_4_BEAT_BURST 0x00
+#define AR9170_PTA_CTRL_8_BEAT_BURST 0x01
+#define AR9170_PTA_CTRL_16_BEAT_BURST 0x02
+#define AR9170_PTA_CTRL_LOOPBACK_MODE 0x10
+
+#define AR9170_PTA_REG_MEM_CTRL (AR9170_PTA_REG_BASE + 0x124)
+#define AR9170_PTA_REG_MEM_ADDR (AR9170_PTA_REG_BASE + 0x128)
+#define AR9170_PTA_REG_DN_DMA_TRIGGER (AR9170_PTA_REG_BASE + 0x12c)
+#define AR9170_PTA_REG_UP_DMA_TRIGGER (AR9170_PTA_REG_BASE + 0x130)
+#define AR9170_PTA_REG_DMA_STATUS (AR9170_PTA_REG_BASE + 0x134)
+#define AR9170_PTA_REG_DN_CURR_ADDRL (AR9170_PTA_REG_BASE + 0x138)
+#define AR9170_PTA_REG_DN_CURR_ADDRH (AR9170_PTA_REG_BASE + 0x13c)
+#define AR9170_PTA_REG_UP_CURR_ADDRL (AR9170_PTA_REG_BASE + 0x140)
+#define AR9170_PTA_REG_UP_CURR_ADDRH (AR9170_PTA_REG_BASE + 0x144)
+#define AR9170_PTA_REG_DMA_MODE_CTRL (AR9170_PTA_REG_BASE + 0x148)
+#define AR9170_PTA_DMA_MODE_CTRL_RESET BIT(0)
+#define AR9170_PTA_DMA_MODE_CTRL_DISABLE_USB BIT(1)
+
+/* Protocol Controller Module */
+#define AR9170_MAC_REG_PC_REG_BASE (AR9170_MAC_REG_BASE + 0xe00)
+
+
+#define AR9170_NUM_LEDS 2
+
+/* CAM */
+#define AR9170_CAM_MAX_USER 64
+#define AR9170_CAM_MAX_KEY_LENGTH 16
+
+#define AR9170_SRAM_OFFSET 0x100000
+#define AR9170_SRAM_SIZE 0x18000
+
+#define AR9170_PRAM_OFFSET 0x200000
+#define AR9170_PRAM_SIZE 0x8000
+
+enum cpu_clock {
+ AHB_STATIC_40MHZ = 0,
+ AHB_GMODE_22MHZ = 1,
+ AHB_AMODE_20MHZ = 1,
+ AHB_GMODE_44MHZ = 2,
+ AHB_AMODE_40MHZ = 2,
+ AHB_GMODE_88MHZ = 3,
+ AHB_AMODE_80MHZ = 3
+};
+
+/* USB endpoints */
+enum ar9170_usb_ep {
+ /*
+ * Control EP is always EP 0 (USB SPEC)
+ *
+ * The weird thing is: the original firmware has a few
+ * comments that suggest that the actual EP numbers
+ * are in the 1 to 10 range?!
+ */
+ AR9170_USB_EP_CTRL = 0,
+
+ AR9170_USB_EP_TX,
+ AR9170_USB_EP_RX,
+ AR9170_USB_EP_IRQ,
+ AR9170_USB_EP_CMD,
+ AR9170_USB_NUM_EXTRA_EP = 4,
+
+ __AR9170_USB_NUM_EP,
+
+ __AR9170_USB_NUM_MAX_EP = 10
+};
+
+enum ar9170_usb_fifo {
+ __AR9170_USB_NUM_MAX_FIFO = 10
+};
+
+enum ar9170_tx_queues {
+ AR9170_TXQ0 = 0,
+ AR9170_TXQ1,
+ AR9170_TXQ2,
+ AR9170_TXQ3,
+ AR9170_TXQ_SPECIAL,
+
+ /* keep last */
+ __AR9170_NUM_TX_QUEUES = 5
+};
+
+#define AR9170_TX_STREAM_TAG 0x697e
+#define AR9170_RX_STREAM_TAG 0x4e00
+#define AR9170_RX_STREAM_MAX_SIZE 0xffff
+
+struct ar9170_stream {
+ __le16 length;
+ __le16 tag;
+
+ u8 payload[0];
+};
+
+#define AR9170_MAX_ACKTABLE_ENTRIES 8
+#define AR9170_MAX_VIRTUAL_MAC 7
+
+#define AR9170_USB_EP_CTRL_MAX 64
+#define AR9170_USB_EP_TX_MAX 512
+#define AR9170_USB_EP_RX_MAX 512
+#define AR9170_USB_EP_IRQ_MAX 64
+#define AR9170_USB_EP_CMD_MAX 64
+
+/* Trigger PRETBTT interrupt 6 Kus earlier */
+#define CARL9170_PRETBTT_KUS 6
+
+#define AR5416_MAX_RATE_POWER 63
+
+#define SET_VAL(reg, value, newvalue) \
+ (value = ((value) & ~reg) | (((newvalue) << reg##_S) & reg))
+
+#define SET_CONSTVAL(reg, newvalue) \
+ (((newvalue) << reg##_S) & reg)
+
+#define MOD_VAL(reg, value, newvalue) \
+ (((value) & ~reg) | (((newvalue) << reg##_S) & reg))
+#endif /* __CARL9170_SHARED_HW_H */
diff --git a/drivers/net/wireless/ath/carl9170/led.c b/drivers/net/wireless/ath/carl9170/led.c
new file mode 100644
index 000000000000..4bb2cbd8bd9b
--- /dev/null
+++ b/drivers/net/wireless/ath/carl9170/led.c
@@ -0,0 +1,190 @@
+/*
+ * Atheros CARL9170 driver
+ *
+ * LED handling
+ *
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2009, 2010, Christian Lamparer <chunkeey@googlemail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ * Copyright (c) 2007-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "carl9170.h"
+#include "cmd.h"
+
+int carl9170_led_set_state(struct ar9170 *ar, const u32 led_state)
+{
+ return carl9170_write_reg(ar, AR9170_GPIO_REG_PORT_DATA, led_state);
+}
+
+int carl9170_led_init(struct ar9170 *ar)
+{
+ int err;
+
+ /* disable LEDs */
+ /* GPIO [0/1 mode: output, 2/3: input] */
+ err = carl9170_write_reg(ar, AR9170_GPIO_REG_PORT_TYPE, 3);
+ if (err)
+ goto out;
+
+ /* GPIO 0/1 value: off */
+ err = carl9170_led_set_state(ar, 0);
+
+out:
+ return err;
+}
+
+#ifdef CONFIG_CARL9170_LEDS
+static void carl9170_led_update(struct work_struct *work)
+{
+ struct ar9170 *ar = container_of(work, struct ar9170, led_work.work);
+ int i, tmp = 300, blink_delay = 1000;
+ u32 led_val = 0;
+ bool rerun = false;
+
+ if (!IS_ACCEPTING_CMD(ar))
+ return;
+
+ mutex_lock(&ar->mutex);
+ for (i = 0; i < AR9170_NUM_LEDS; i++) {
+ if (ar->leds[i].registered) {
+ if (ar->leds[i].last_state ||
+ ar->leds[i].toggled) {
+
+ if (ar->leds[i].toggled)
+ tmp = 70 + 200 / (ar->leds[i].toggled);
+
+ if (tmp < blink_delay)
+ blink_delay = tmp;
+
+ led_val |= 1 << i;
+ ar->leds[i].toggled = 0;
+ rerun = true;
+ }
+ }
+ }
+
+ carl9170_led_set_state(ar, led_val);
+ mutex_unlock(&ar->mutex);
+
+ if (!rerun)
+ return;
+
+ ieee80211_queue_delayed_work(ar->hw,
+ &ar->led_work,
+ msecs_to_jiffies(blink_delay));
+}
+
+static void carl9170_led_set_brightness(struct led_classdev *led,
+ enum led_brightness brightness)
+{
+ struct carl9170_led *arl = container_of(led, struct carl9170_led, l);
+ struct ar9170 *ar = arl->ar;
+
+ if (!arl->registered)
+ return;
+
+ if (arl->last_state != !!brightness) {
+ arl->toggled++;
+ arl->last_state = !!brightness;
+ }
+
+ if (likely(IS_ACCEPTING_CMD(ar) && arl->toggled))
+ ieee80211_queue_delayed_work(ar->hw, &ar->led_work, HZ/10);
+}
+
+static int carl9170_led_register_led(struct ar9170 *ar, int i, char *name,
+ char *trigger)
+{
+ int err;
+
+ snprintf(ar->leds[i].name, sizeof(ar->leds[i].name),
+ "carl9170-%s::%s", wiphy_name(ar->hw->wiphy), name);
+
+ ar->leds[i].ar = ar;
+ ar->leds[i].l.name = ar->leds[i].name;
+ ar->leds[i].l.brightness_set = carl9170_led_set_brightness;
+ ar->leds[i].l.brightness = 0;
+ ar->leds[i].l.default_trigger = trigger;
+
+ err = led_classdev_register(wiphy_dev(ar->hw->wiphy),
+ &ar->leds[i].l);
+ if (err) {
+ wiphy_err(ar->hw->wiphy, "failed to register %s LED (%d).\n",
+ ar->leds[i].name, err);
+ } else {
+ ar->leds[i].registered = true;
+ }
+
+ return err;
+}
+
+void carl9170_led_unregister(struct ar9170 *ar)
+{
+ int i;
+
+ for (i = 0; i < AR9170_NUM_LEDS; i++)
+ if (ar->leds[i].registered) {
+ led_classdev_unregister(&ar->leds[i].l);
+ ar->leds[i].registered = false;
+ ar->leds[i].toggled = 0;
+ }
+
+ cancel_delayed_work_sync(&ar->led_work);
+}
+
+int carl9170_led_register(struct ar9170 *ar)
+{
+ int err;
+
+ INIT_DELAYED_WORK(&ar->led_work, carl9170_led_update);
+
+ err = carl9170_led_register_led(ar, 0, "tx",
+ ieee80211_get_tx_led_name(ar->hw));
+ if (err)
+ goto fail;
+
+ if (ar->features & CARL9170_ONE_LED)
+ return 0;
+
+ err = carl9170_led_register_led(ar, 1, "assoc",
+ ieee80211_get_assoc_led_name(ar->hw));
+ if (err)
+ goto fail;
+
+ return 0;
+
+fail:
+ carl9170_led_unregister(ar);
+ return err;
+}
+
+#endif /* CONFIG_CARL9170_LEDS */
diff --git a/drivers/net/wireless/ath/carl9170/mac.c b/drivers/net/wireless/ath/carl9170/mac.c
new file mode 100644
index 000000000000..2305bc27151c
--- /dev/null
+++ b/drivers/net/wireless/ath/carl9170/mac.c
@@ -0,0 +1,604 @@
+/*
+ * Atheros CARL9170 driver
+ *
+ * MAC programming
+ *
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ * Copyright (c) 2007-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <asm/unaligned.h>
+
+#include "carl9170.h"
+#include "cmd.h"
+
+int carl9170_set_dyn_sifs_ack(struct ar9170 *ar)
+{
+ u32 val;
+
+ if (conf_is_ht40(&ar->hw->conf))
+ val = 0x010a;
+ else {
+ if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ)
+ val = 0x105;
+ else
+ val = 0x104;
+ }
+
+ return carl9170_write_reg(ar, AR9170_MAC_REG_DYNAMIC_SIFS_ACK, val);
+}
+
+int carl9170_set_rts_cts_rate(struct ar9170 *ar)
+{
+ u32 rts_rate, cts_rate;
+
+ if (conf_is_ht(&ar->hw->conf)) {
+ /* 12 mbit OFDM */
+ rts_rate = 0x1da;
+ cts_rate = 0x10a;
+ } else {
+ if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) {
+ /* 11 mbit CCK */
+ rts_rate = 033;
+ cts_rate = 003;
+ } else {
+ /* 6 mbit OFDM */
+ rts_rate = 0x1bb;
+ cts_rate = 0x10b;
+ }
+ }
+
+ return carl9170_write_reg(ar, AR9170_MAC_REG_RTS_CTS_RATE,
+ rts_rate | (cts_rate) << 16);
+}
+
+int carl9170_set_slot_time(struct ar9170 *ar)
+{
+ struct ieee80211_vif *vif;
+ u32 slottime = 20;
+
+ rcu_read_lock();
+ vif = carl9170_get_main_vif(ar);
+ if (!vif) {
+ rcu_read_unlock();
+ return 0;
+ }
+
+ if ((ar->hw->conf.channel->band == IEEE80211_BAND_5GHZ) ||
+ vif->bss_conf.use_short_slot)
+ slottime = 9;
+
+ rcu_read_unlock();
+
+ return carl9170_write_reg(ar, AR9170_MAC_REG_SLOT_TIME,
+ slottime << 10);
+}
+
+int carl9170_set_mac_rates(struct ar9170 *ar)
+{
+ struct ieee80211_vif *vif;
+ u32 basic, mandatory;
+
+ rcu_read_lock();
+ vif = carl9170_get_main_vif(ar);
+
+ if (!vif) {
+ rcu_read_unlock();
+ return 0;
+ }
+
+ basic = (vif->bss_conf.basic_rates & 0xf);
+ basic |= (vif->bss_conf.basic_rates & 0xff0) << 4;
+ rcu_read_unlock();
+
+ if (ar->hw->conf.channel->band == IEEE80211_BAND_5GHZ)
+ mandatory = 0xff00; /* OFDM 6/9/12/18/24/36/48/54 */
+ else
+ mandatory = 0xff0f; /* OFDM (6/9../54) + CCK (1/2/5.5/11) */
+
+ carl9170_regwrite_begin(ar);
+ carl9170_regwrite(AR9170_MAC_REG_BASIC_RATE, basic);
+ carl9170_regwrite(AR9170_MAC_REG_MANDATORY_RATE, mandatory);
+ carl9170_regwrite_finish();
+
+ return carl9170_regwrite_result();
+}
+
+int carl9170_set_qos(struct ar9170 *ar)
+{
+ carl9170_regwrite_begin(ar);
+
+ carl9170_regwrite(AR9170_MAC_REG_AC0_CW, ar->edcf[0].cw_min |
+ (ar->edcf[0].cw_max << 16));
+ carl9170_regwrite(AR9170_MAC_REG_AC1_CW, ar->edcf[1].cw_min |
+ (ar->edcf[1].cw_max << 16));
+ carl9170_regwrite(AR9170_MAC_REG_AC2_CW, ar->edcf[2].cw_min |
+ (ar->edcf[2].cw_max << 16));
+ carl9170_regwrite(AR9170_MAC_REG_AC3_CW, ar->edcf[3].cw_min |
+ (ar->edcf[3].cw_max << 16));
+ carl9170_regwrite(AR9170_MAC_REG_AC4_CW, ar->edcf[4].cw_min |
+ (ar->edcf[4].cw_max << 16));
+
+ carl9170_regwrite(AR9170_MAC_REG_AC2_AC1_AC0_AIFS,
+ ((ar->edcf[0].aifs * 9 + 10)) |
+ ((ar->edcf[1].aifs * 9 + 10) << 12) |
+ ((ar->edcf[2].aifs * 9 + 10) << 24));
+ carl9170_regwrite(AR9170_MAC_REG_AC4_AC3_AC2_AIFS,
+ ((ar->edcf[2].aifs * 9 + 10) >> 8) |
+ ((ar->edcf[3].aifs * 9 + 10) << 4) |
+ ((ar->edcf[4].aifs * 9 + 10) << 16));
+
+ carl9170_regwrite(AR9170_MAC_REG_AC1_AC0_TXOP,
+ ar->edcf[0].txop | ar->edcf[1].txop << 16);
+ carl9170_regwrite(AR9170_MAC_REG_AC3_AC2_TXOP,
+ ar->edcf[2].txop | ar->edcf[3].txop << 16 |
+ ar->edcf[4].txop << 24);
+
+ carl9170_regwrite_finish();
+
+ return carl9170_regwrite_result();
+}
+
+int carl9170_init_mac(struct ar9170 *ar)
+{
+ carl9170_regwrite_begin(ar);
+
+ /* switch MAC to OTUS interface */
+ carl9170_regwrite(0x1c3600, 0x3);
+
+ carl9170_regwrite(AR9170_MAC_REG_ACK_EXTENSION, 0x40);
+
+ carl9170_regwrite(AR9170_MAC_REG_RETRY_MAX, 0x0);
+
+ carl9170_regwrite(AR9170_MAC_REG_FRAMETYPE_FILTER,
+ AR9170_MAC_FTF_MONITOR);
+
+ /* enable MMIC */
+ carl9170_regwrite(AR9170_MAC_REG_SNIFFER,
+ AR9170_MAC_SNIFFER_DEFAULTS);
+
+ carl9170_regwrite(AR9170_MAC_REG_RX_THRESHOLD, 0xc1f80);
+
+ carl9170_regwrite(AR9170_MAC_REG_RX_PE_DELAY, 0x70);
+ carl9170_regwrite(AR9170_MAC_REG_EIFS_AND_SIFS, 0xa144000);
+ carl9170_regwrite(AR9170_MAC_REG_SLOT_TIME, 9 << 10);
+
+ /* CF-END & CF-ACK rate => 24M OFDM */
+ carl9170_regwrite(AR9170_MAC_REG_TID_CFACK_CFEND_RATE, 0x59900000);
+
+ /* NAV protects ACK only (in TXOP) */
+ carl9170_regwrite(AR9170_MAC_REG_TXOP_DURATION, 0x201);
+
+ /* Set Beacon PHY CTRL's TPC to 0x7, TA1=1 */
+ /* OTUS set AM to 0x1 */
+ carl9170_regwrite(AR9170_MAC_REG_BCN_HT1, 0x8000170);
+
+ carl9170_regwrite(AR9170_MAC_REG_BACKOFF_PROTECT, 0x105);
+
+ /* Aggregation MAX number and timeout */
+ carl9170_regwrite(AR9170_MAC_REG_AMPDU_FACTOR, 0xa);
+ carl9170_regwrite(AR9170_MAC_REG_AMPDU_DENSITY, 0x140a00);
+
+ carl9170_regwrite(AR9170_MAC_REG_FRAMETYPE_FILTER,
+ AR9170_MAC_FTF_DEFAULTS);
+
+ carl9170_regwrite(AR9170_MAC_REG_RX_CONTROL,
+ AR9170_MAC_RX_CTRL_DEAGG |
+ AR9170_MAC_RX_CTRL_SHORT_FILTER);
+
+ /* rate sets */
+ carl9170_regwrite(AR9170_MAC_REG_BASIC_RATE, 0x150f);
+ carl9170_regwrite(AR9170_MAC_REG_MANDATORY_RATE, 0x150f);
+ carl9170_regwrite(AR9170_MAC_REG_RTS_CTS_RATE, 0x0030033);
+
+ /* MIMO response control */
+ carl9170_regwrite(AR9170_MAC_REG_ACK_TPC, 0x4003c1e);
+
+ carl9170_regwrite(AR9170_MAC_REG_AMPDU_RX_THRESH, 0xffff);
+
+ /* set PHY register read timeout (??) */
+ carl9170_regwrite(AR9170_MAC_REG_MISC_680, 0xf00008);
+
+ /* Disable Rx TimeOut, workaround for BB. */
+ carl9170_regwrite(AR9170_MAC_REG_RX_TIMEOUT, 0x0);
+
+ /* Set WLAN DMA interrupt mode: generate int per packet */
+ carl9170_regwrite(AR9170_MAC_REG_TXRX_MPI, 0x110011);
+
+ carl9170_regwrite(AR9170_MAC_REG_FCS_SELECT,
+ AR9170_MAC_FCS_FIFO_PROT);
+
+ /* Disables the CF_END frame, undocumented register */
+ carl9170_regwrite(AR9170_MAC_REG_TXOP_NOT_ENOUGH_IND,
+ 0x141e0f48);
+
+ /* reset group hash table */
+ carl9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_L, 0xffffffff);
+ carl9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_H, 0xffffffff);
+
+ /* disable PRETBTT interrupt */
+ carl9170_regwrite(AR9170_MAC_REG_PRETBTT, 0x0);
+ carl9170_regwrite(AR9170_MAC_REG_BCN_PERIOD, 0x0);
+
+ carl9170_regwrite_finish();
+
+ return carl9170_regwrite_result();
+}
+
+static int carl9170_set_mac_reg(struct ar9170 *ar,
+ const u32 reg, const u8 *mac)
+{
+ static const u8 zero[ETH_ALEN] = { 0 };
+
+ if (!mac)
+ mac = zero;
+
+ carl9170_regwrite_begin(ar);
+
+ carl9170_regwrite(reg, get_unaligned_le32(mac));
+ carl9170_regwrite(reg + 4, get_unaligned_le16(mac + 4));
+
+ carl9170_regwrite_finish();
+
+ return carl9170_regwrite_result();
+}
+
+int carl9170_mod_virtual_mac(struct ar9170 *ar, const unsigned int id,
+ const u8 *mac)
+{
+ if (WARN_ON(id >= ar->fw.vif_num))
+ return -EINVAL;
+
+ return carl9170_set_mac_reg(ar,
+ AR9170_MAC_REG_ACK_TABLE + (id - 1) * 8, mac);
+}
+
+int carl9170_update_multicast(struct ar9170 *ar, const u64 mc_hash)
+{
+ int err;
+
+ carl9170_regwrite_begin(ar);
+ carl9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_H, mc_hash >> 32);
+ carl9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_L, mc_hash);
+ carl9170_regwrite_finish();
+ err = carl9170_regwrite_result();
+ if (err)
+ return err;
+
+ ar->cur_mc_hash = mc_hash;
+ return 0;
+}
+
+int carl9170_set_operating_mode(struct ar9170 *ar)
+{
+ struct ieee80211_vif *vif;
+ struct ath_common *common = &ar->common;
+ u8 *mac_addr, *bssid;
+ u32 cam_mode = AR9170_MAC_CAM_DEFAULTS;
+ u32 enc_mode = AR9170_MAC_ENCRYPTION_DEFAULTS;
+ u32 rx_ctrl = AR9170_MAC_RX_CTRL_DEAGG |
+ AR9170_MAC_RX_CTRL_SHORT_FILTER;
+ u32 sniffer = AR9170_MAC_SNIFFER_DEFAULTS;
+ int err = 0;
+
+ rcu_read_lock();
+ vif = carl9170_get_main_vif(ar);
+
+ if (vif) {
+ mac_addr = common->macaddr;
+ bssid = common->curbssid;
+
+ switch (vif->type) {
+ case NL80211_IFTYPE_MESH_POINT:
+ case NL80211_IFTYPE_ADHOC:
+ cam_mode |= AR9170_MAC_CAM_IBSS;
+ break;
+ case NL80211_IFTYPE_AP:
+ cam_mode |= AR9170_MAC_CAM_AP;
+
+ /* iwlagn 802.11n STA Workaround */
+ rx_ctrl |= AR9170_MAC_RX_CTRL_PASS_TO_HOST;
+ break;
+ case NL80211_IFTYPE_WDS:
+ cam_mode |= AR9170_MAC_CAM_AP_WDS;
+ rx_ctrl |= AR9170_MAC_RX_CTRL_PASS_TO_HOST;
+ break;
+ case NL80211_IFTYPE_STATION:
+ cam_mode |= AR9170_MAC_CAM_STA;
+ rx_ctrl |= AR9170_MAC_RX_CTRL_PASS_TO_HOST;
+ break;
+ default:
+ WARN(1, "Unsupported operation mode %x\n", vif->type);
+ err = -EOPNOTSUPP;
+ break;
+ }
+ } else {
+ mac_addr = NULL;
+ bssid = NULL;
+ }
+ rcu_read_unlock();
+
+ if (err)
+ return err;
+
+ if (ar->rx_software_decryption)
+ enc_mode |= AR9170_MAC_ENCRYPTION_RX_SOFTWARE;
+
+ if (ar->sniffer_enabled) {
+ rx_ctrl |= AR9170_MAC_RX_CTRL_ACK_IN_SNIFFER;
+ sniffer |= AR9170_MAC_SNIFFER_ENABLE_PROMISC;
+ enc_mode |= AR9170_MAC_ENCRYPTION_RX_SOFTWARE;
+ }
+
+ err = carl9170_set_mac_reg(ar, AR9170_MAC_REG_MAC_ADDR_L, mac_addr);
+ if (err)
+ return err;
+
+ err = carl9170_set_mac_reg(ar, AR9170_MAC_REG_BSSID_L, bssid);
+ if (err)
+ return err;
+
+ carl9170_regwrite_begin(ar);
+ carl9170_regwrite(AR9170_MAC_REG_SNIFFER, sniffer);
+ carl9170_regwrite(AR9170_MAC_REG_CAM_MODE, cam_mode);
+ carl9170_regwrite(AR9170_MAC_REG_ENCRYPTION, enc_mode);
+ carl9170_regwrite(AR9170_MAC_REG_RX_CONTROL, rx_ctrl);
+ carl9170_regwrite_finish();
+
+ return carl9170_regwrite_result();
+}
+
+int carl9170_set_hwretry_limit(struct ar9170 *ar, const unsigned int max_retry)
+{
+ u32 tmp = min_t(u32, 0x33333, max_retry * 0x11111);
+
+ return carl9170_write_reg(ar, AR9170_MAC_REG_RETRY_MAX, tmp);
+}
+
+int carl9170_set_beacon_timers(struct ar9170 *ar)
+{
+ struct ieee80211_vif *vif;
+ u32 v = 0;
+ u32 pretbtt = 0;
+
+ rcu_read_lock();
+ vif = carl9170_get_main_vif(ar);
+
+ if (vif) {
+ struct carl9170_vif_info *mvif;
+ mvif = (void *) vif->drv_priv;
+
+ if (mvif->enable_beacon && !WARN_ON(!ar->beacon_enabled)) {
+ ar->global_beacon_int = vif->bss_conf.beacon_int /
+ ar->beacon_enabled;
+
+ SET_VAL(AR9170_MAC_BCN_DTIM, v,
+ vif->bss_conf.dtim_period);
+
+ switch (vif->type) {
+ case NL80211_IFTYPE_MESH_POINT:
+ case NL80211_IFTYPE_ADHOC:
+ v |= AR9170_MAC_BCN_IBSS_MODE;
+ break;
+ case NL80211_IFTYPE_AP:
+ v |= AR9170_MAC_BCN_AP_MODE;
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ break;
+ }
+ } else if (vif->type == NL80211_IFTYPE_STATION) {
+ ar->global_beacon_int = vif->bss_conf.beacon_int;
+
+ SET_VAL(AR9170_MAC_BCN_DTIM, v,
+ ar->hw->conf.ps_dtim_period);
+
+ v |= AR9170_MAC_BCN_STA_PS |
+ AR9170_MAC_BCN_PWR_MGT;
+ }
+
+ if (ar->global_beacon_int) {
+ if (ar->global_beacon_int < 15) {
+ rcu_read_unlock();
+ return -ERANGE;
+ }
+
+ ar->global_pretbtt = ar->global_beacon_int -
+ CARL9170_PRETBTT_KUS;
+ } else {
+ ar->global_pretbtt = 0;
+ }
+ } else {
+ ar->global_beacon_int = 0;
+ ar->global_pretbtt = 0;
+ }
+
+ rcu_read_unlock();
+
+ SET_VAL(AR9170_MAC_BCN_PERIOD, v, ar->global_beacon_int);
+ SET_VAL(AR9170_MAC_PRETBTT, pretbtt, ar->global_pretbtt);
+ SET_VAL(AR9170_MAC_PRETBTT2, pretbtt, ar->global_pretbtt);
+
+ carl9170_regwrite_begin(ar);
+ carl9170_regwrite(AR9170_MAC_REG_PRETBTT, pretbtt);
+ carl9170_regwrite(AR9170_MAC_REG_BCN_PERIOD, v);
+ carl9170_regwrite_finish();
+ return carl9170_regwrite_result();
+}
+
+int carl9170_update_beacon(struct ar9170 *ar, const bool submit)
+{
+ struct sk_buff *skb;
+ struct carl9170_vif_info *cvif;
+ __le32 *data, *old = NULL;
+ u32 word, off, addr, len;
+ int i = 0, err = 0;
+
+ rcu_read_lock();
+ cvif = rcu_dereference(ar->beacon_iter);
+retry:
+ if (ar->vifs == 0 || !cvif)
+ goto out_unlock;
+
+ list_for_each_entry_continue_rcu(cvif, &ar->vif_list, list) {
+ if (cvif->active && cvif->enable_beacon)
+ goto found;
+ }
+
+ if (!ar->beacon_enabled || i++)
+ goto out_unlock;
+
+ goto retry;
+
+found:
+ rcu_assign_pointer(ar->beacon_iter, cvif);
+
+ skb = ieee80211_beacon_get_tim(ar->hw, carl9170_get_vif(cvif),
+ NULL, NULL);
+
+ if (!skb) {
+ err = -ENOMEM;
+ goto out_unlock;
+ }
+
+ spin_lock_bh(&ar->beacon_lock);
+ data = (__le32 *)skb->data;
+ if (cvif->beacon)
+ old = (__le32 *)cvif->beacon->data;
+
+ off = cvif->id * AR9170_MAC_BCN_LENGTH_MAX;
+ addr = ar->fw.beacon_addr + off;
+ len = roundup(skb->len + FCS_LEN, 4);
+
+ if ((off + len) > ar->fw.beacon_max_len) {
+ if (net_ratelimit()) {
+ wiphy_err(ar->hw->wiphy, "beacon does not "
+ "fit into device memory!\n");
+ }
+
+ spin_unlock_bh(&ar->beacon_lock);
+ dev_kfree_skb_any(skb);
+ err = -EINVAL;
+ goto out_unlock;
+ }
+
+ if (len > AR9170_MAC_BCN_LENGTH_MAX) {
+ if (net_ratelimit()) {
+ wiphy_err(ar->hw->wiphy, "no support for beacons "
+ "bigger than %d (yours:%d).\n",
+ AR9170_MAC_BCN_LENGTH_MAX, len);
+ }
+
+ spin_unlock_bh(&ar->beacon_lock);
+ dev_kfree_skb_any(skb);
+ err = -EMSGSIZE;
+ goto out_unlock;
+ }
+
+ carl9170_async_regwrite_begin(ar);
+
+ /* XXX: use skb->cb info */
+ if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) {
+ carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP,
+ ((skb->len + FCS_LEN) << (3 + 16)) + 0x0400);
+ } else {
+ carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP,
+ ((skb->len + FCS_LEN) << 16) + 0x001b);
+ }
+
+ for (i = 0; i < DIV_ROUND_UP(skb->len, 4); i++) {
+ /*
+ * XXX: This accesses beyond skb data for up
+ * to the last 3 bytes!!
+ */
+
+ if (old && (data[i] == old[i]))
+ continue;
+
+ word = le32_to_cpu(data[i]);
+ carl9170_async_regwrite(addr + 4 * i, word);
+ }
+ carl9170_async_regwrite_finish();
+
+ dev_kfree_skb_any(cvif->beacon);
+ cvif->beacon = NULL;
+
+ err = carl9170_async_regwrite_result();
+ if (!err)
+ cvif->beacon = skb;
+ spin_unlock_bh(&ar->beacon_lock);
+ if (err)
+ goto out_unlock;
+
+ if (submit) {
+ err = carl9170_bcn_ctrl(ar, cvif->id,
+ CARL9170_BCN_CTRL_CAB_TRIGGER,
+ addr, skb->len + FCS_LEN);
+
+ if (err)
+ goto out_unlock;
+ }
+out_unlock:
+ rcu_read_unlock();
+ return err;
+}
+
+int carl9170_upload_key(struct ar9170 *ar, const u8 id, const u8 *mac,
+ const u8 ktype, const u8 keyidx, const u8 *keydata,
+ const int keylen)
+{
+ struct carl9170_set_key_cmd key = { };
+ static const u8 bcast[ETH_ALEN] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+ mac = mac ? : bcast;
+
+ key.user = cpu_to_le16(id);
+ key.keyId = cpu_to_le16(keyidx);
+ key.type = cpu_to_le16(ktype);
+ memcpy(&key.macAddr, mac, ETH_ALEN);
+ if (keydata)
+ memcpy(&key.key, keydata, keylen);
+
+ return carl9170_exec_cmd(ar, CARL9170_CMD_EKEY,
+ sizeof(key), (u8 *)&key, 0, NULL);
+}
+
+int carl9170_disable_key(struct ar9170 *ar, const u8 id)
+{
+ struct carl9170_disable_key_cmd key = { };
+
+ key.user = cpu_to_le16(id);
+
+ return carl9170_exec_cmd(ar, CARL9170_CMD_DKEY,
+ sizeof(key), (u8 *)&key, 0, NULL);
+}
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c
new file mode 100644
index 000000000000..3cc99f3f7ab5
--- /dev/null
+++ b/drivers/net/wireless/ath/carl9170/main.c
@@ -0,0 +1,1891 @@
+/*
+ * Atheros CARL9170 driver
+ *
+ * mac80211 interaction code
+ *
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ * Copyright (c) 2007-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/etherdevice.h>
+#include <linux/random.h>
+#include <net/mac80211.h>
+#include <net/cfg80211.h>
+#include "hw.h"
+#include "carl9170.h"
+#include "cmd.h"
+
+static int modparam_nohwcrypt;
+module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
+MODULE_PARM_DESC(nohwcrypt, "Disable hardware crypto offload.");
+
+int modparam_noht;
+module_param_named(noht, modparam_noht, int, S_IRUGO);
+MODULE_PARM_DESC(noht, "Disable MPDU aggregation.");
+
+#define RATE(_bitrate, _hw_rate, _txpidx, _flags) { \
+ .bitrate = (_bitrate), \
+ .flags = (_flags), \
+ .hw_value = (_hw_rate) | (_txpidx) << 4, \
+}
+
+struct ieee80211_rate __carl9170_ratetable[] = {
+ RATE(10, 0, 0, 0),
+ RATE(20, 1, 1, IEEE80211_RATE_SHORT_PREAMBLE),
+ RATE(55, 2, 2, IEEE80211_RATE_SHORT_PREAMBLE),
+ RATE(110, 3, 3, IEEE80211_RATE_SHORT_PREAMBLE),
+ RATE(60, 0xb, 0, 0),
+ RATE(90, 0xf, 0, 0),
+ RATE(120, 0xa, 0, 0),
+ RATE(180, 0xe, 0, 0),
+ RATE(240, 0x9, 0, 0),
+ RATE(360, 0xd, 1, 0),
+ RATE(480, 0x8, 2, 0),
+ RATE(540, 0xc, 3, 0),
+};
+#undef RATE
+
+#define carl9170_g_ratetable (__carl9170_ratetable + 0)
+#define carl9170_g_ratetable_size 12
+#define carl9170_a_ratetable (__carl9170_ratetable + 4)
+#define carl9170_a_ratetable_size 8
+
+/*
+ * NB: The hw_value is used as an index into the carl9170_phy_freq_params
+ * array in phy.c so that we don't have to do frequency lookups!
+ */
+#define CHAN(_freq, _idx) { \
+ .center_freq = (_freq), \
+ .hw_value = (_idx), \
+ .max_power = 18, /* XXX */ \
+}
+
+static struct ieee80211_channel carl9170_2ghz_chantable[] = {
+ CHAN(2412, 0),
+ CHAN(2417, 1),
+ CHAN(2422, 2),
+ CHAN(2427, 3),
+ CHAN(2432, 4),
+ CHAN(2437, 5),
+ CHAN(2442, 6),
+ CHAN(2447, 7),
+ CHAN(2452, 8),
+ CHAN(2457, 9),
+ CHAN(2462, 10),
+ CHAN(2467, 11),
+ CHAN(2472, 12),
+ CHAN(2484, 13),
+};
+
+static struct ieee80211_channel carl9170_5ghz_chantable[] = {
+ CHAN(4920, 14),
+ CHAN(4940, 15),
+ CHAN(4960, 16),
+ CHAN(4980, 17),
+ CHAN(5040, 18),
+ CHAN(5060, 19),
+ CHAN(5080, 20),
+ CHAN(5180, 21),
+ CHAN(5200, 22),
+ CHAN(5220, 23),
+ CHAN(5240, 24),
+ CHAN(5260, 25),
+ CHAN(5280, 26),
+ CHAN(5300, 27),
+ CHAN(5320, 28),
+ CHAN(5500, 29),
+ CHAN(5520, 30),
+ CHAN(5540, 31),
+ CHAN(5560, 32),
+ CHAN(5580, 33),
+ CHAN(5600, 34),
+ CHAN(5620, 35),
+ CHAN(5640, 36),
+ CHAN(5660, 37),
+ CHAN(5680, 38),
+ CHAN(5700, 39),
+ CHAN(5745, 40),
+ CHAN(5765, 41),
+ CHAN(5785, 42),
+ CHAN(5805, 43),
+ CHAN(5825, 44),
+ CHAN(5170, 45),
+ CHAN(5190, 46),
+ CHAN(5210, 47),
+ CHAN(5230, 48),
+};
+#undef CHAN
+
+#define CARL9170_HT_CAP \
+{ \
+ .ht_supported = true, \
+ .cap = IEEE80211_HT_CAP_MAX_AMSDU | \
+ IEEE80211_HT_CAP_SUP_WIDTH_20_40 | \
+ IEEE80211_HT_CAP_SGI_40 | \
+ IEEE80211_HT_CAP_DSSSCCK40 | \
+ IEEE80211_HT_CAP_SM_PS, \
+ .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, \
+ .ampdu_density = IEEE80211_HT_MPDU_DENSITY_8, \
+ .mcs = { \
+ .rx_mask = { 0xff, 0xff, 0, 0, 0x1, 0, 0, 0, 0, 0, }, \
+ .rx_highest = cpu_to_le16(300), \
+ .tx_params = IEEE80211_HT_MCS_TX_DEFINED, \
+ }, \
+}
+
+static struct ieee80211_supported_band carl9170_band_2GHz = {
+ .channels = carl9170_2ghz_chantable,
+ .n_channels = ARRAY_SIZE(carl9170_2ghz_chantable),
+ .bitrates = carl9170_g_ratetable,
+ .n_bitrates = carl9170_g_ratetable_size,
+ .ht_cap = CARL9170_HT_CAP,
+};
+
+static struct ieee80211_supported_band carl9170_band_5GHz = {
+ .channels = carl9170_5ghz_chantable,
+ .n_channels = ARRAY_SIZE(carl9170_5ghz_chantable),
+ .bitrates = carl9170_a_ratetable,
+ .n_bitrates = carl9170_a_ratetable_size,
+ .ht_cap = CARL9170_HT_CAP,
+};
+
+static void carl9170_ampdu_gc(struct ar9170 *ar)
+{
+ struct carl9170_sta_tid *tid_info;
+ LIST_HEAD(tid_gc);
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(tid_info, &ar->tx_ampdu_list, list) {
+ spin_lock_bh(&ar->tx_ampdu_list_lock);
+ if (tid_info->state == CARL9170_TID_STATE_SHUTDOWN) {
+ tid_info->state = CARL9170_TID_STATE_KILLED;
+ list_del_rcu(&tid_info->list);
+ ar->tx_ampdu_list_len--;
+ list_add_tail(&tid_info->tmp_list, &tid_gc);
+ }
+ spin_unlock_bh(&ar->tx_ampdu_list_lock);
+
+ }
+ rcu_assign_pointer(ar->tx_ampdu_iter, tid_info);
+ rcu_read_unlock();
+
+ synchronize_rcu();
+
+ while (!list_empty(&tid_gc)) {
+ struct sk_buff *skb;
+ tid_info = list_first_entry(&tid_gc, struct carl9170_sta_tid,
+ tmp_list);
+
+ while ((skb = __skb_dequeue(&tid_info->queue)))
+ carl9170_tx_status(ar, skb, false);
+
+ list_del_init(&tid_info->tmp_list);
+ kfree(tid_info);
+ }
+}
+
+static void carl9170_flush(struct ar9170 *ar, bool drop_queued)
+{
+ if (drop_queued) {
+ int i;
+
+ /*
+ * We can only drop frames which have not been uploaded
+ * to the device yet.
+ */
+
+ for (i = 0; i < ar->hw->queues; i++) {
+ struct sk_buff *skb;
+
+ while ((skb = skb_dequeue(&ar->tx_pending[i]))) {
+ struct ieee80211_tx_info *info;
+
+ info = IEEE80211_SKB_CB(skb);
+ if (info->flags & IEEE80211_TX_CTL_AMPDU)
+ atomic_dec(&ar->tx_ampdu_upload);
+
+ carl9170_tx_status(ar, skb, false);
+ }
+ }
+ }
+
+ /* Wait for all other outstanding frames to timeout. */
+ if (atomic_read(&ar->tx_total_queued))
+ WARN_ON(wait_for_completion_timeout(&ar->tx_flush, HZ) == 0);
+}
+
+static void carl9170_flush_ba(struct ar9170 *ar)
+{
+ struct sk_buff_head free;
+ struct carl9170_sta_tid *tid_info;
+ struct sk_buff *skb;
+
+ __skb_queue_head_init(&free);
+
+ rcu_read_lock();
+ spin_lock_bh(&ar->tx_ampdu_list_lock);
+ list_for_each_entry_rcu(tid_info, &ar->tx_ampdu_list, list) {
+ if (tid_info->state > CARL9170_TID_STATE_SUSPEND) {
+ tid_info->state = CARL9170_TID_STATE_SUSPEND;
+
+ spin_lock(&tid_info->lock);
+ while ((skb = __skb_dequeue(&tid_info->queue)))
+ __skb_queue_tail(&free, skb);
+ spin_unlock(&tid_info->lock);
+ }
+ }
+ spin_unlock_bh(&ar->tx_ampdu_list_lock);
+ rcu_read_unlock();
+
+ while ((skb = __skb_dequeue(&free)))
+ carl9170_tx_status(ar, skb, false);
+}
+
+static void carl9170_zap_queues(struct ar9170 *ar)
+{
+ struct carl9170_vif_info *cvif;
+ unsigned int i;
+
+ carl9170_ampdu_gc(ar);
+
+ carl9170_flush_ba(ar);
+ carl9170_flush(ar, true);
+
+ for (i = 0; i < ar->hw->queues; i++) {
+ spin_lock_bh(&ar->tx_status[i].lock);
+ while (!skb_queue_empty(&ar->tx_status[i])) {
+ struct sk_buff *skb;
+
+ skb = skb_peek(&ar->tx_status[i]);
+ carl9170_tx_get_skb(skb);
+ spin_unlock_bh(&ar->tx_status[i].lock);
+ carl9170_tx_drop(ar, skb);
+ spin_lock_bh(&ar->tx_status[i].lock);
+ carl9170_tx_put_skb(skb);
+ }
+ spin_unlock_bh(&ar->tx_status[i].lock);
+ }
+
+ BUILD_BUG_ON(CARL9170_NUM_TX_LIMIT_SOFT < 1);
+ BUILD_BUG_ON(CARL9170_NUM_TX_LIMIT_HARD < CARL9170_NUM_TX_LIMIT_SOFT);
+ BUILD_BUG_ON(CARL9170_NUM_TX_LIMIT_HARD >= CARL9170_BAW_BITS);
+
+ /* reinitialize queues statistics */
+ memset(&ar->tx_stats, 0, sizeof(ar->tx_stats));
+ for (i = 0; i < ar->hw->queues; i++)
+ ar->tx_stats[i].limit = CARL9170_NUM_TX_LIMIT_HARD;
+
+ for (i = 0; i < DIV_ROUND_UP(ar->fw.mem_blocks, BITS_PER_LONG); i++)
+ ar->mem_bitmap[i] = 0;
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(cvif, &ar->vif_list, list) {
+ spin_lock_bh(&ar->beacon_lock);
+ dev_kfree_skb_any(cvif->beacon);
+ cvif->beacon = NULL;
+ spin_unlock_bh(&ar->beacon_lock);
+ }
+ rcu_read_unlock();
+
+ atomic_set(&ar->tx_ampdu_upload, 0);
+ atomic_set(&ar->tx_ampdu_scheduler, 0);
+ atomic_set(&ar->tx_total_pending, 0);
+ atomic_set(&ar->tx_total_queued, 0);
+ atomic_set(&ar->mem_free_blocks, ar->fw.mem_blocks);
+}
+
+#define CARL9170_FILL_QUEUE(queue, ai_fs, cwmin, cwmax, _txop) \
+do { \
+ queue.aifs = ai_fs; \
+ queue.cw_min = cwmin; \
+ queue.cw_max = cwmax; \
+ queue.txop = _txop; \
+} while (0)
+
+static int carl9170_op_start(struct ieee80211_hw *hw)
+{
+ struct ar9170 *ar = hw->priv;
+ int err, i;
+
+ mutex_lock(&ar->mutex);
+
+ carl9170_zap_queues(ar);
+
+ /* reset QoS defaults */
+ CARL9170_FILL_QUEUE(ar->edcf[0], 3, 15, 1023, 0); /* BEST EFFORT */
+ CARL9170_FILL_QUEUE(ar->edcf[1], 2, 7, 15, 94); /* VIDEO */
+ CARL9170_FILL_QUEUE(ar->edcf[2], 2, 3, 7, 47); /* VOICE */
+ CARL9170_FILL_QUEUE(ar->edcf[3], 7, 15, 1023, 0); /* BACKGROUND */
+ CARL9170_FILL_QUEUE(ar->edcf[4], 2, 3, 7, 0); /* SPECIAL */
+
+ ar->current_factor = ar->current_density = -1;
+ /* "The first key is unique." */
+ ar->usedkeys = 1;
+ ar->filter_state = 0;
+ ar->ps.last_action = jiffies;
+ ar->ps.last_slept = jiffies;
+ ar->erp_mode = CARL9170_ERP_AUTO;
+ ar->rx_software_decryption = false;
+ ar->disable_offload = false;
+
+ for (i = 0; i < ar->hw->queues; i++) {
+ ar->queue_stop_timeout[i] = jiffies;
+ ar->max_queue_stop_timeout[i] = 0;
+ }
+
+ atomic_set(&ar->mem_allocs, 0);
+
+ err = carl9170_usb_open(ar);
+ if (err)
+ goto out;
+
+ err = carl9170_init_mac(ar);
+ if (err)
+ goto out;
+
+ err = carl9170_set_qos(ar);
+ if (err)
+ goto out;
+
+ if (ar->fw.rx_filter) {
+ err = carl9170_rx_filter(ar, CARL9170_RX_FILTER_OTHER_RA |
+ CARL9170_RX_FILTER_CTL_OTHER | CARL9170_RX_FILTER_BAD);
+ if (err)
+ goto out;
+ }
+
+ err = carl9170_write_reg(ar, AR9170_MAC_REG_DMA_TRIGGER,
+ AR9170_DMA_TRIGGER_RXQ);
+ if (err)
+ goto out;
+
+ /* Clear key-cache */
+ for (i = 0; i < AR9170_CAM_MAX_USER + 4; i++) {
+ err = carl9170_upload_key(ar, i, NULL, AR9170_ENC_ALG_NONE,
+ 0, NULL, 0);
+ if (err)
+ goto out;
+
+ err = carl9170_upload_key(ar, i, NULL, AR9170_ENC_ALG_NONE,
+ 1, NULL, 0);
+ if (err)
+ goto out;
+
+ if (i < AR9170_CAM_MAX_USER) {
+ err = carl9170_disable_key(ar, i);
+ if (err)
+ goto out;
+ }
+ }
+
+ carl9170_set_state_when(ar, CARL9170_IDLE, CARL9170_STARTED);
+
+ ieee80211_wake_queues(ar->hw);
+ err = 0;
+
+out:
+ mutex_unlock(&ar->mutex);
+ return err;
+}
+
+static void carl9170_cancel_worker(struct ar9170 *ar)
+{
+ cancel_delayed_work_sync(&ar->tx_janitor);
+#ifdef CONFIG_CARL9170_LEDS
+ cancel_delayed_work_sync(&ar->led_work);
+#endif /* CONFIG_CARL9170_LEDS */
+ cancel_work_sync(&ar->ps_work);
+ cancel_work_sync(&ar->ampdu_work);
+}
+
+static void carl9170_op_stop(struct ieee80211_hw *hw)
+{
+ struct ar9170 *ar = hw->priv;
+
+ carl9170_set_state_when(ar, CARL9170_STARTED, CARL9170_IDLE);
+
+ ieee80211_stop_queues(ar->hw);
+
+ mutex_lock(&ar->mutex);
+ if (IS_ACCEPTING_CMD(ar)) {
+ rcu_assign_pointer(ar->beacon_iter, NULL);
+
+ carl9170_led_set_state(ar, 0);
+
+ /* stop DMA */
+ carl9170_write_reg(ar, AR9170_MAC_REG_DMA_TRIGGER, 0);
+ carl9170_usb_stop(ar);
+ }
+
+ carl9170_zap_queues(ar);
+ mutex_unlock(&ar->mutex);
+
+ carl9170_cancel_worker(ar);
+}
+
+static void carl9170_restart_work(struct work_struct *work)
+{
+ struct ar9170 *ar = container_of(work, struct ar9170,
+ restart_work);
+ int err;
+
+ ar->usedkeys = 0;
+ ar->filter_state = 0;
+ carl9170_cancel_worker(ar);
+
+ mutex_lock(&ar->mutex);
+ err = carl9170_usb_restart(ar);
+ if (net_ratelimit()) {
+ if (err) {
+ dev_err(&ar->udev->dev, "Failed to restart device "
+ " (%d).\n", err);
+ } else {
+ dev_info(&ar->udev->dev, "device restarted "
+ "successfully.\n");
+ }
+ }
+
+ carl9170_zap_queues(ar);
+ mutex_unlock(&ar->mutex);
+ if (!err) {
+ ar->restart_counter++;
+ atomic_set(&ar->pending_restarts, 0);
+
+ ieee80211_restart_hw(ar->hw);
+ } else {
+ /*
+ * The reset was unsuccessful and the device seems to
+ * be dead. But there's still one option: a low-level
+ * usb subsystem reset...
+ */
+
+ carl9170_usb_reset(ar);
+ }
+}
+
+void carl9170_restart(struct ar9170 *ar, const enum carl9170_restart_reasons r)
+{
+ carl9170_set_state_when(ar, CARL9170_STARTED, CARL9170_IDLE);
+
+ /*
+ * Sometimes, an error can trigger several different reset events.
+ * By ignoring these *surplus* reset events, the device won't be
+ * killed again, right after it has recovered.
+ */
+ if (atomic_inc_return(&ar->pending_restarts) > 1) {
+ dev_dbg(&ar->udev->dev, "ignoring restart (%d)\n", r);
+ return;
+ }
+
+ ieee80211_stop_queues(ar->hw);
+
+ dev_err(&ar->udev->dev, "restart device (%d)\n", r);
+
+ if (!WARN_ON(r == CARL9170_RR_NO_REASON) ||
+ !WARN_ON(r >= __CARL9170_RR_LAST))
+ ar->last_reason = r;
+
+ if (!ar->registered)
+ return;
+
+ if (IS_ACCEPTING_CMD(ar) && !ar->needs_full_reset)
+ ieee80211_queue_work(ar->hw, &ar->restart_work);
+ else
+ carl9170_usb_reset(ar);
+
+ /*
+ * At this point, the device instance might have vanished/disabled.
+ * So, don't put any code which access the ar9170 struct
+ * without proper protection.
+ */
+}
+
+static int carl9170_init_interface(struct ar9170 *ar,
+ struct ieee80211_vif *vif)
+{
+ struct ath_common *common = &ar->common;
+ int err;
+
+ if (!vif) {
+ WARN_ON_ONCE(IS_STARTED(ar));
+ return 0;
+ }
+
+ memcpy(common->macaddr, vif->addr, ETH_ALEN);
+
+ if (modparam_nohwcrypt ||
+ ((vif->type != NL80211_IFTYPE_STATION) &&
+ (vif->type != NL80211_IFTYPE_AP))) {
+ ar->rx_software_decryption = true;
+ ar->disable_offload = true;
+ }
+
+ err = carl9170_set_operating_mode(ar);
+ return err;
+}
+
+static int carl9170_op_add_interface(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
+{
+ struct carl9170_vif_info *vif_priv = (void *) vif->drv_priv;
+ struct ieee80211_vif *main_vif;
+ struct ar9170 *ar = hw->priv;
+ int vif_id = -1, err = 0;
+
+ mutex_lock(&ar->mutex);
+ rcu_read_lock();
+ if (vif_priv->active) {
+ /*
+ * Skip the interface structure initialization,
+ * if the vif survived the _restart call.
+ */
+ vif_id = vif_priv->id;
+ vif_priv->enable_beacon = false;
+
+ spin_lock_bh(&ar->beacon_lock);
+ dev_kfree_skb_any(vif_priv->beacon);
+ vif_priv->beacon = NULL;
+ spin_unlock_bh(&ar->beacon_lock);
+
+ goto init;
+ }
+
+ main_vif = carl9170_get_main_vif(ar);
+
+ if (main_vif) {
+ switch (main_vif->type) {
+ case NL80211_IFTYPE_STATION:
+ if (vif->type == NL80211_IFTYPE_STATION)
+ break;
+
+ err = -EBUSY;
+ rcu_read_unlock();
+
+ goto unlock;
+
+ case NL80211_IFTYPE_AP:
+ if ((vif->type == NL80211_IFTYPE_STATION) ||
+ (vif->type == NL80211_IFTYPE_WDS) ||
+ (vif->type == NL80211_IFTYPE_AP))
+ break;
+
+ err = -EBUSY;
+ rcu_read_unlock();
+ goto unlock;
+
+ default:
+ rcu_read_unlock();
+ goto unlock;
+ }
+ }
+
+ vif_id = bitmap_find_free_region(&ar->vif_bitmap, ar->fw.vif_num, 0);
+
+ if (vif_id < 0) {
+ rcu_read_unlock();
+
+ err = -ENOSPC;
+ goto unlock;
+ }
+
+ BUG_ON(ar->vif_priv[vif_id].id != vif_id);
+
+ vif_priv->active = true;
+ vif_priv->id = vif_id;
+ vif_priv->enable_beacon = false;
+ ar->vifs++;
+ list_add_tail_rcu(&vif_priv->list, &ar->vif_list);
+ rcu_assign_pointer(ar->vif_priv[vif_id].vif, vif);
+
+init:
+ if (carl9170_get_main_vif(ar) == vif) {
+ rcu_assign_pointer(ar->beacon_iter, vif_priv);
+ rcu_read_unlock();
+
+ err = carl9170_init_interface(ar, vif);
+ if (err)
+ goto unlock;
+ } else {
+ err = carl9170_mod_virtual_mac(ar, vif_id, vif->addr);
+ rcu_read_unlock();
+
+ if (err)
+ goto unlock;
+ }
+
+unlock:
+ if (err && (vif_id != -1)) {
+ vif_priv->active = false;
+ bitmap_release_region(&ar->vif_bitmap, vif_id, 0);
+ ar->vifs--;
+ rcu_assign_pointer(ar->vif_priv[vif_id].vif, NULL);
+ list_del_rcu(&vif_priv->list);
+ mutex_unlock(&ar->mutex);
+ synchronize_rcu();
+ } else {
+ if (ar->vifs > 1)
+ ar->ps.off_override |= PS_OFF_VIF;
+
+ mutex_unlock(&ar->mutex);
+ }
+
+ return err;
+}
+
+static void carl9170_op_remove_interface(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
+{
+ struct carl9170_vif_info *vif_priv = (void *) vif->drv_priv;
+ struct ieee80211_vif *main_vif;
+ struct ar9170 *ar = hw->priv;
+ unsigned int id;
+
+ mutex_lock(&ar->mutex);
+
+ if (WARN_ON_ONCE(!vif_priv->active))
+ goto unlock;
+
+ ar->vifs--;
+
+ rcu_read_lock();
+ main_vif = carl9170_get_main_vif(ar);
+
+ id = vif_priv->id;
+
+ vif_priv->active = false;
+ WARN_ON(vif_priv->enable_beacon);
+ vif_priv->enable_beacon = false;
+ list_del_rcu(&vif_priv->list);
+ rcu_assign_pointer(ar->vif_priv[id].vif, NULL);
+
+ if (vif == main_vif) {
+ rcu_read_unlock();
+
+ if (ar->vifs) {
+ WARN_ON(carl9170_init_interface(ar,
+ carl9170_get_main_vif(ar)));
+ } else {
+ carl9170_set_operating_mode(ar);
+ }
+ } else {
+ rcu_read_unlock();
+
+ WARN_ON(carl9170_mod_virtual_mac(ar, id, NULL));
+ }
+
+ carl9170_update_beacon(ar, false);
+ carl9170_flush_cab(ar, id);
+
+ spin_lock_bh(&ar->beacon_lock);
+ dev_kfree_skb_any(vif_priv->beacon);
+ vif_priv->beacon = NULL;
+ spin_unlock_bh(&ar->beacon_lock);
+
+ bitmap_release_region(&ar->vif_bitmap, id, 0);
+
+ carl9170_set_beacon_timers(ar);
+
+ if (ar->vifs == 1)
+ ar->ps.off_override &= ~PS_OFF_VIF;
+
+unlock:
+ mutex_unlock(&ar->mutex);
+
+ synchronize_rcu();
+}
+
+void carl9170_ps_check(struct ar9170 *ar)
+{
+ ieee80211_queue_work(ar->hw, &ar->ps_work);
+}
+
+/* caller must hold ar->mutex */
+static int carl9170_ps_update(struct ar9170 *ar)
+{
+ bool ps = false;
+ int err = 0;
+
+ if (!ar->ps.off_override)
+ ps = (ar->hw->conf.flags & IEEE80211_CONF_PS);
+
+ if (ps != ar->ps.state) {
+ err = carl9170_powersave(ar, ps);
+ if (err)
+ return err;
+
+ if (ar->ps.state && !ps) {
+ ar->ps.sleep_ms = jiffies_to_msecs(jiffies -
+ ar->ps.last_action);
+ }
+
+ if (ps)
+ ar->ps.last_slept = jiffies;
+
+ ar->ps.last_action = jiffies;
+ ar->ps.state = ps;
+ }
+
+ return 0;
+}
+
+static void carl9170_ps_work(struct work_struct *work)
+{
+ struct ar9170 *ar = container_of(work, struct ar9170,
+ ps_work);
+ mutex_lock(&ar->mutex);
+ if (IS_STARTED(ar))
+ WARN_ON_ONCE(carl9170_ps_update(ar) != 0);
+ mutex_unlock(&ar->mutex);
+}
+
+
+static int carl9170_op_config(struct ieee80211_hw *hw, u32 changed)
+{
+ struct ar9170 *ar = hw->priv;
+ int err = 0;
+
+ mutex_lock(&ar->mutex);
+ if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) {
+ /* TODO */
+ err = 0;
+ }
+
+ if (changed & IEEE80211_CONF_CHANGE_PS) {
+ err = carl9170_ps_update(ar);
+ if (err)
+ goto out;
+ }
+
+ if (changed & IEEE80211_CONF_CHANGE_POWER) {
+ /* TODO */
+ err = 0;
+ }
+
+ if (changed & IEEE80211_CONF_CHANGE_SMPS) {
+ /* TODO */
+ err = 0;
+ }
+
+ if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
+ /* adjust slot time for 5 GHz */
+ err = carl9170_set_slot_time(ar);
+ if (err)
+ goto out;
+
+ err = carl9170_set_channel(ar, hw->conf.channel,
+ hw->conf.channel_type, CARL9170_RFI_NONE);
+ if (err)
+ goto out;
+
+ err = carl9170_set_dyn_sifs_ack(ar);
+ if (err)
+ goto out;
+
+ err = carl9170_set_rts_cts_rate(ar);
+ if (err)
+ goto out;
+ }
+
+out:
+ mutex_unlock(&ar->mutex);
+ return err;
+}
+
+static u64 carl9170_op_prepare_multicast(struct ieee80211_hw *hw,
+ struct netdev_hw_addr_list *mc_list)
+{
+ struct netdev_hw_addr *ha;
+ u64 mchash;
+
+ /* always get broadcast frames */
+ mchash = 1ULL << (0xff >> 2);
+
+ netdev_hw_addr_list_for_each(ha, mc_list)
+ mchash |= 1ULL << (ha->addr[5] >> 2);
+
+ return mchash;
+}
+
+static void carl9170_op_configure_filter(struct ieee80211_hw *hw,
+ unsigned int changed_flags,
+ unsigned int *new_flags,
+ u64 multicast)
+{
+ struct ar9170 *ar = hw->priv;
+
+ /* mask supported flags */
+ *new_flags &= FIF_ALLMULTI | ar->rx_filter_caps;
+
+ if (!IS_ACCEPTING_CMD(ar))
+ return;
+
+ mutex_lock(&ar->mutex);
+
+ ar->filter_state = *new_flags;
+ /*
+ * We can support more by setting the sniffer bit and
+ * then checking the error flags, later.
+ */
+
+ if (changed_flags & FIF_ALLMULTI && *new_flags & FIF_ALLMULTI)
+ multicast = ~0ULL;
+
+ if (multicast != ar->cur_mc_hash)
+ WARN_ON(carl9170_update_multicast(ar, multicast));
+
+ if (changed_flags & (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS)) {
+ ar->sniffer_enabled = !!(*new_flags &
+ (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS));
+
+ WARN_ON(carl9170_set_operating_mode(ar));
+ }
+
+ if (ar->fw.rx_filter && changed_flags & ar->rx_filter_caps) {
+ u32 rx_filter = 0;
+
+ if (!(*new_flags & (FIF_FCSFAIL | FIF_PLCPFAIL)))
+ rx_filter |= CARL9170_RX_FILTER_BAD;
+
+ if (!(*new_flags & FIF_CONTROL))
+ rx_filter |= CARL9170_RX_FILTER_CTL_OTHER;
+
+ if (!(*new_flags & FIF_PSPOLL))
+ rx_filter |= CARL9170_RX_FILTER_CTL_PSPOLL;
+
+ if (!(*new_flags & (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS))) {
+ rx_filter |= CARL9170_RX_FILTER_OTHER_RA;
+ rx_filter |= CARL9170_RX_FILTER_DECRY_FAIL;
+ }
+
+ WARN_ON(carl9170_rx_filter(ar, rx_filter));
+ }
+
+ mutex_unlock(&ar->mutex);
+}
+
+
+static void carl9170_op_bss_info_changed(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *bss_conf,
+ u32 changed)
+{
+ struct ar9170 *ar = hw->priv;
+ struct ath_common *common = &ar->common;
+ int err = 0;
+ struct carl9170_vif_info *vif_priv;
+ struct ieee80211_vif *main_vif;
+
+ mutex_lock(&ar->mutex);
+ vif_priv = (void *) vif->drv_priv;
+ main_vif = carl9170_get_main_vif(ar);
+ if (WARN_ON(!main_vif))
+ goto out;
+
+ if (changed & BSS_CHANGED_BEACON_ENABLED) {
+ struct carl9170_vif_info *iter;
+ int i = 0;
+
+ vif_priv->enable_beacon = bss_conf->enable_beacon;
+ rcu_read_lock();
+ list_for_each_entry_rcu(iter, &ar->vif_list, list) {
+ if (iter->active && iter->enable_beacon)
+ i++;
+
+ }
+ rcu_read_unlock();
+
+ ar->beacon_enabled = i;
+ }
+
+ if (changed & BSS_CHANGED_BEACON) {
+ err = carl9170_update_beacon(ar, false);
+ if (err)
+ goto out;
+ }
+
+ if (changed & (BSS_CHANGED_BEACON_ENABLED | BSS_CHANGED_BEACON |
+ BSS_CHANGED_BEACON_INT)) {
+
+ if (main_vif != vif) {
+ bss_conf->beacon_int = main_vif->bss_conf.beacon_int;
+ bss_conf->dtim_period = main_vif->bss_conf.dtim_period;
+ }
+
+ /*
+ * Therefore a hard limit for the broadcast traffic should
+ * prevent false alarms.
+ */
+ if (vif->type != NL80211_IFTYPE_STATION &&
+ (bss_conf->beacon_int * bss_conf->dtim_period >=
+ (CARL9170_QUEUE_STUCK_TIMEOUT / 2))) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ err = carl9170_set_beacon_timers(ar);
+ if (err)
+ goto out;
+ }
+
+ if (changed & BSS_CHANGED_HT) {
+ /* TODO */
+ err = 0;
+ if (err)
+ goto out;
+ }
+
+ if (main_vif != vif)
+ goto out;
+
+ /*
+ * The following settings can only be changed by the
+ * master interface.
+ */
+
+ if (changed & BSS_CHANGED_BSSID) {
+ memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
+ err = carl9170_set_operating_mode(ar);
+ if (err)
+ goto out;
+ }
+
+ if (changed & BSS_CHANGED_ASSOC) {
+ ar->common.curaid = bss_conf->aid;
+ err = carl9170_set_beacon_timers(ar);
+ if (err)
+ goto out;
+ }
+
+ if (changed & BSS_CHANGED_ERP_SLOT) {
+ err = carl9170_set_slot_time(ar);
+ if (err)
+ goto out;
+ }
+
+ if (changed & BSS_CHANGED_BASIC_RATES) {
+ err = carl9170_set_mac_rates(ar);
+ if (err)
+ goto out;
+ }
+
+out:
+ WARN_ON_ONCE(err && IS_STARTED(ar));
+ mutex_unlock(&ar->mutex);
+}
+
+static u64 carl9170_op_get_tsf(struct ieee80211_hw *hw)
+{
+ struct ar9170 *ar = hw->priv;
+ struct carl9170_tsf_rsp tsf;
+ int err;
+
+ mutex_lock(&ar->mutex);
+ err = carl9170_exec_cmd(ar, CARL9170_CMD_READ_TSF,
+ 0, NULL, sizeof(tsf), &tsf);
+ mutex_unlock(&ar->mutex);
+ if (WARN_ON(err))
+ return 0;
+
+ return le64_to_cpu(tsf.tsf_64);
+}
+
+static int carl9170_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct ieee80211_key_conf *key)
+{
+ struct ar9170 *ar = hw->priv;
+ int err = 0, i;
+ u8 ktype;
+
+ if (ar->disable_offload || !vif)
+ return -EOPNOTSUPP;
+
+ /*
+ * We have to fall back to software encryption, whenever
+ * the user choose to participates in an IBSS or is connected
+ * to more than one network.
+ *
+ * This is very unfortunate, because some machines cannot handle
+ * the high througput speed in 802.11n networks.
+ */
+
+ if (!is_main_vif(ar, vif))
+ goto err_softw;
+
+ /*
+ * While the hardware supports *catch-all* key, for offloading
+ * group-key en-/de-cryption. The way of how the hardware
+ * decides which keyId maps to which key, remains a mystery...
+ */
+ if ((vif->type != NL80211_IFTYPE_STATION &&
+ vif->type != NL80211_IFTYPE_ADHOC) &&
+ !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
+ return -EOPNOTSUPP;
+
+ switch (key->cipher) {
+ case WLAN_CIPHER_SUITE_WEP40:
+ ktype = AR9170_ENC_ALG_WEP64;
+ break;
+ case WLAN_CIPHER_SUITE_WEP104:
+ ktype = AR9170_ENC_ALG_WEP128;
+ break;
+ case WLAN_CIPHER_SUITE_TKIP:
+ ktype = AR9170_ENC_ALG_TKIP;
+ break;
+ case WLAN_CIPHER_SUITE_CCMP:
+ ktype = AR9170_ENC_ALG_AESCCMP;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ mutex_lock(&ar->mutex);
+ if (cmd == SET_KEY) {
+ if (!IS_STARTED(ar)) {
+ err = -EOPNOTSUPP;
+ goto out;
+ }
+
+ if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
+ sta = NULL;
+
+ i = 64 + key->keyidx;
+ } else {
+ for (i = 0; i < 64; i++)
+ if (!(ar->usedkeys & BIT(i)))
+ break;
+ if (i == 64)
+ goto err_softw;
+ }
+
+ key->hw_key_idx = i;
+
+ err = carl9170_upload_key(ar, i, sta ? sta->addr : NULL,
+ ktype, 0, key->key,
+ min_t(u8, 16, key->keylen));
+ if (err)
+ goto out;
+
+ if (key->cipher == WLAN_CIPHER_SUITE_TKIP) {
+ err = carl9170_upload_key(ar, i, sta ? sta->addr :
+ NULL, ktype, 1,
+ key->key + 16, 16);
+ if (err)
+ goto out;
+
+ /*
+ * hardware is not capable generating MMIC
+ * of fragmented frames!
+ */
+ key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
+ }
+
+ if (i < 64)
+ ar->usedkeys |= BIT(i);
+
+ key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+ } else {
+ if (!IS_STARTED(ar)) {
+ /* The device is gone... together with the key ;-) */
+ err = 0;
+ goto out;
+ }
+
+ if (key->hw_key_idx < 64) {
+ ar->usedkeys &= ~BIT(key->hw_key_idx);
+ } else {
+ err = carl9170_upload_key(ar, key->hw_key_idx, NULL,
+ AR9170_ENC_ALG_NONE, 0,
+ NULL, 0);
+ if (err)
+ goto out;
+
+ if (key->cipher == WLAN_CIPHER_SUITE_TKIP) {
+ err = carl9170_upload_key(ar, key->hw_key_idx,
+ NULL,
+ AR9170_ENC_ALG_NONE,
+ 1, NULL, 0);
+ if (err)
+ goto out;
+ }
+
+ }
+
+ err = carl9170_disable_key(ar, key->hw_key_idx);
+ if (err)
+ goto out;
+ }
+
+out:
+ mutex_unlock(&ar->mutex);
+ return err;
+
+err_softw:
+ if (!ar->rx_software_decryption) {
+ ar->rx_software_decryption = true;
+ carl9170_set_operating_mode(ar);
+ }
+ mutex_unlock(&ar->mutex);
+ return -ENOSPC;
+}
+
+static int carl9170_op_sta_add(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
+{
+ struct carl9170_sta_info *sta_info = (void *) sta->drv_priv;
+ unsigned int i;
+
+ if (sta->ht_cap.ht_supported) {
+ if (sta->ht_cap.ampdu_density > 6) {
+ /*
+ * HW does support 16us AMPDU density.
+ * No HT-Xmit for station.
+ */
+
+ return 0;
+ }
+
+ for (i = 0; i < CARL9170_NUM_TID; i++)
+ rcu_assign_pointer(sta_info->agg[i], NULL);
+
+ sta_info->ampdu_max_len = 1 << (3 + sta->ht_cap.ampdu_factor);
+ sta_info->ht_sta = true;
+ }
+
+ return 0;
+}
+
+static int carl9170_op_sta_remove(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
+{
+ struct ar9170 *ar = hw->priv;
+ struct carl9170_sta_info *sta_info = (void *) sta->drv_priv;
+ unsigned int i;
+ bool cleanup = false;
+
+ if (sta->ht_cap.ht_supported) {
+
+ sta_info->ht_sta = false;
+
+ rcu_read_lock();
+ for (i = 0; i < CARL9170_NUM_TID; i++) {
+ struct carl9170_sta_tid *tid_info;
+
+ tid_info = rcu_dereference(sta_info->agg[i]);
+ rcu_assign_pointer(sta_info->agg[i], NULL);
+
+ if (!tid_info)
+ continue;
+
+ spin_lock_bh(&ar->tx_ampdu_list_lock);
+ if (tid_info->state > CARL9170_TID_STATE_SHUTDOWN)
+ tid_info->state = CARL9170_TID_STATE_SHUTDOWN;
+ spin_unlock_bh(&ar->tx_ampdu_list_lock);
+ cleanup = true;
+ }
+ rcu_read_unlock();
+
+ if (cleanup)
+ carl9170_ampdu_gc(ar);
+ }
+
+ return 0;
+}
+
+static int carl9170_op_conf_tx(struct ieee80211_hw *hw, u16 queue,
+ const struct ieee80211_tx_queue_params *param)
+{
+ struct ar9170 *ar = hw->priv;
+ int ret;
+
+ mutex_lock(&ar->mutex);
+ if (queue < ar->hw->queues) {
+ memcpy(&ar->edcf[ar9170_qmap[queue]], param, sizeof(*param));
+ ret = carl9170_set_qos(ar);
+ } else {
+ ret = -EINVAL;
+ }
+
+ mutex_unlock(&ar->mutex);
+ return ret;
+}
+
+static void carl9170_ampdu_work(struct work_struct *work)
+{
+ struct ar9170 *ar = container_of(work, struct ar9170,
+ ampdu_work);
+
+ if (!IS_STARTED(ar))
+ return;
+
+ mutex_lock(&ar->mutex);
+ carl9170_ampdu_gc(ar);
+ mutex_unlock(&ar->mutex);
+}
+
+static int carl9170_op_ampdu_action(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ enum ieee80211_ampdu_mlme_action action,
+ struct ieee80211_sta *sta,
+ u16 tid, u16 *ssn)
+{
+ struct ar9170 *ar = hw->priv;
+ struct carl9170_sta_info *sta_info = (void *) sta->drv_priv;
+ struct carl9170_sta_tid *tid_info;
+
+ if (modparam_noht)
+ return -EOPNOTSUPP;
+
+ switch (action) {
+ case IEEE80211_AMPDU_TX_START:
+ if (!sta_info->ht_sta)
+ return -EOPNOTSUPP;
+
+ rcu_read_lock();
+ if (rcu_dereference(sta_info->agg[tid])) {
+ rcu_read_unlock();
+ return -EBUSY;
+ }
+
+ tid_info = kzalloc(sizeof(struct carl9170_sta_tid),
+ GFP_ATOMIC);
+ if (!tid_info) {
+ rcu_read_unlock();
+ return -ENOMEM;
+ }
+
+ tid_info->hsn = tid_info->bsn = tid_info->snx = (*ssn);
+ tid_info->state = CARL9170_TID_STATE_PROGRESS;
+ tid_info->tid = tid;
+ tid_info->max = sta_info->ampdu_max_len;
+
+ INIT_LIST_HEAD(&tid_info->list);
+ INIT_LIST_HEAD(&tid_info->tmp_list);
+ skb_queue_head_init(&tid_info->queue);
+ spin_lock_init(&tid_info->lock);
+
+ spin_lock_bh(&ar->tx_ampdu_list_lock);
+ ar->tx_ampdu_list_len++;
+ list_add_tail_rcu(&tid_info->list, &ar->tx_ampdu_list);
+ rcu_assign_pointer(sta_info->agg[tid], tid_info);
+ spin_unlock_bh(&ar->tx_ampdu_list_lock);
+ rcu_read_unlock();
+
+ ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+ break;
+
+ case IEEE80211_AMPDU_TX_STOP:
+ rcu_read_lock();
+ tid_info = rcu_dereference(sta_info->agg[tid]);
+ if (tid_info) {
+ spin_lock_bh(&ar->tx_ampdu_list_lock);
+ if (tid_info->state > CARL9170_TID_STATE_SHUTDOWN)
+ tid_info->state = CARL9170_TID_STATE_SHUTDOWN;
+ spin_unlock_bh(&ar->tx_ampdu_list_lock);
+ }
+
+ rcu_assign_pointer(sta_info->agg[tid], NULL);
+ rcu_read_unlock();
+
+ ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+ ieee80211_queue_work(ar->hw, &ar->ampdu_work);
+ break;
+
+ case IEEE80211_AMPDU_TX_OPERATIONAL:
+ rcu_read_lock();
+ tid_info = rcu_dereference(sta_info->agg[tid]);
+
+ sta_info->stats[tid].clear = true;
+
+ if (tid_info) {
+ bitmap_zero(tid_info->bitmap, CARL9170_BAW_SIZE);
+ tid_info->state = CARL9170_TID_STATE_IDLE;
+ }
+ rcu_read_unlock();
+
+ if (WARN_ON_ONCE(!tid_info))
+ return -EFAULT;
+
+ break;
+
+ case IEEE80211_AMPDU_RX_START:
+ case IEEE80211_AMPDU_RX_STOP:
+ /* Handled by hardware */
+ break;
+
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_CARL9170_WPC
+static int carl9170_register_wps_button(struct ar9170 *ar)
+{
+ struct input_dev *input;
+ int err;
+
+ if (!(ar->features & CARL9170_WPS_BUTTON))
+ return 0;
+
+ input = input_allocate_device();
+ if (!input)
+ return -ENOMEM;
+
+ snprintf(ar->wps.name, sizeof(ar->wps.name), "%s WPS Button",
+ wiphy_name(ar->hw->wiphy));
+
+ snprintf(ar->wps.phys, sizeof(ar->wps.phys),
+ "ieee80211/%s/input0", wiphy_name(ar->hw->wiphy));
+
+ input->name = ar->wps.name;
+ input->phys = ar->wps.phys;
+ input->id.bustype = BUS_USB;
+ input->dev.parent = &ar->hw->wiphy->dev;
+
+ input_set_capability(input, EV_KEY, KEY_WPS_BUTTON);
+
+ err = input_register_device(input);
+ if (err) {
+ input_free_device(input);
+ return err;
+ }
+
+ ar->wps.pbc = input;
+ return 0;
+}
+#endif /* CONFIG_CARL9170_WPC */
+
+static int carl9170_op_get_survey(struct ieee80211_hw *hw, int idx,
+ struct survey_info *survey)
+{
+ struct ar9170 *ar = hw->priv;
+ int err;
+
+ if (idx != 0)
+ return -ENOENT;
+
+ mutex_lock(&ar->mutex);
+ err = carl9170_get_noisefloor(ar);
+ mutex_unlock(&ar->mutex);
+ if (err)
+ return err;
+
+ survey->channel = ar->channel;
+ survey->filled = SURVEY_INFO_NOISE_DBM;
+ survey->noise = ar->noise[0];
+ return 0;
+}
+
+static void carl9170_op_flush(struct ieee80211_hw *hw, bool drop)
+{
+ struct ar9170 *ar = hw->priv;
+ unsigned int vid;
+
+ mutex_lock(&ar->mutex);
+ for_each_set_bit(vid, &ar->vif_bitmap, ar->fw.vif_num)
+ carl9170_flush_cab(ar, vid);
+
+ carl9170_flush(ar, drop);
+ mutex_unlock(&ar->mutex);
+}
+
+static int carl9170_op_get_stats(struct ieee80211_hw *hw,
+ struct ieee80211_low_level_stats *stats)
+{
+ struct ar9170 *ar = hw->priv;
+
+ memset(stats, 0, sizeof(*stats));
+ stats->dot11ACKFailureCount = ar->tx_ack_failures;
+ stats->dot11FCSErrorCount = ar->tx_fcs_errors;
+ return 0;
+}
+
+static void carl9170_op_sta_notify(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ enum sta_notify_cmd cmd,
+ struct ieee80211_sta *sta)
+{
+ struct ar9170 *ar = hw->priv;
+ struct carl9170_sta_info *sta_info = (void *) sta->drv_priv;
+ struct sk_buff *skb, *tmp;
+ struct sk_buff_head free;
+ int i;
+
+ switch (cmd) {
+ case STA_NOTIFY_SLEEP:
+ /*
+ * Since the peer is no longer listening, we have to return
+ * as many SKBs as possible back to the mac80211 stack.
+ * It will deal with the retry procedure, once the peer
+ * has become available again.
+ *
+ * NB: Ideally, the driver should return the all frames in
+ * the correct, ascending order. However, I think that this
+ * functionality should be implemented in the stack and not
+ * here...
+ */
+
+ __skb_queue_head_init(&free);
+
+ if (sta->ht_cap.ht_supported) {
+ rcu_read_lock();
+ for (i = 0; i < CARL9170_NUM_TID; i++) {
+ struct carl9170_sta_tid *tid_info;
+
+ tid_info = rcu_dereference(sta_info->agg[i]);
+
+ if (!tid_info)
+ continue;
+
+ spin_lock_bh(&ar->tx_ampdu_list_lock);
+ if (tid_info->state >
+ CARL9170_TID_STATE_SUSPEND)
+ tid_info->state =
+ CARL9170_TID_STATE_SUSPEND;
+ spin_unlock_bh(&ar->tx_ampdu_list_lock);
+
+ spin_lock_bh(&tid_info->lock);
+ while ((skb = __skb_dequeue(&tid_info->queue)))
+ __skb_queue_tail(&free, skb);
+ spin_unlock_bh(&tid_info->lock);
+ }
+ rcu_read_unlock();
+ }
+
+ for (i = 0; i < ar->hw->queues; i++) {
+ spin_lock_bh(&ar->tx_pending[i].lock);
+ skb_queue_walk_safe(&ar->tx_pending[i], skb, tmp) {
+ struct _carl9170_tx_superframe *super;
+ struct ieee80211_hdr *hdr;
+ struct ieee80211_tx_info *info;
+
+ super = (void *) skb->data;
+ hdr = (void *) super->frame_data;
+
+ if (compare_ether_addr(hdr->addr1, sta->addr))
+ continue;
+
+ __skb_unlink(skb, &ar->tx_pending[i]);
+
+ info = IEEE80211_SKB_CB(skb);
+ if (info->flags & IEEE80211_TX_CTL_AMPDU)
+ atomic_dec(&ar->tx_ampdu_upload);
+
+ carl9170_tx_status(ar, skb, false);
+ }
+ spin_unlock_bh(&ar->tx_pending[i].lock);
+ }
+
+ while ((skb = __skb_dequeue(&free)))
+ carl9170_tx_status(ar, skb, false);
+
+ break;
+
+ case STA_NOTIFY_AWAKE:
+ if (!sta->ht_cap.ht_supported)
+ return;
+
+ rcu_read_lock();
+ for (i = 0; i < CARL9170_NUM_TID; i++) {
+ struct carl9170_sta_tid *tid_info;
+
+ tid_info = rcu_dereference(sta_info->agg[i]);
+
+ if (!tid_info)
+ continue;
+
+ if ((tid_info->state == CARL9170_TID_STATE_SUSPEND))
+ tid_info->state = CARL9170_TID_STATE_IDLE;
+ }
+ rcu_read_unlock();
+ break;
+ }
+}
+
+static const struct ieee80211_ops carl9170_ops = {
+ .start = carl9170_op_start,
+ .stop = carl9170_op_stop,
+ .tx = carl9170_op_tx,
+ .flush = carl9170_op_flush,
+ .add_interface = carl9170_op_add_interface,
+ .remove_interface = carl9170_op_remove_interface,
+ .config = carl9170_op_config,
+ .prepare_multicast = carl9170_op_prepare_multicast,
+ .configure_filter = carl9170_op_configure_filter,
+ .conf_tx = carl9170_op_conf_tx,
+ .bss_info_changed = carl9170_op_bss_info_changed,
+ .get_tsf = carl9170_op_get_tsf,
+ .set_key = carl9170_op_set_key,
+ .sta_add = carl9170_op_sta_add,
+ .sta_remove = carl9170_op_sta_remove,
+ .sta_notify = carl9170_op_sta_notify,
+ .get_survey = carl9170_op_get_survey,
+ .get_stats = carl9170_op_get_stats,
+ .ampdu_action = carl9170_op_ampdu_action,
+};
+
+void *carl9170_alloc(size_t priv_size)
+{
+ struct ieee80211_hw *hw;
+ struct ar9170 *ar;
+ struct sk_buff *skb;
+ int i;
+
+ /*
+ * this buffer is used for rx stream reconstruction.
+ * Under heavy load this device (or the transport layer?)
+ * tends to split the streams into separate rx descriptors.
+ */
+
+ skb = __dev_alloc_skb(AR9170_RX_STREAM_MAX_SIZE, GFP_KERNEL);
+ if (!skb)
+ goto err_nomem;
+
+ hw = ieee80211_alloc_hw(priv_size, &carl9170_ops);
+ if (!hw)
+ goto err_nomem;
+
+ ar = hw->priv;
+ ar->hw = hw;
+ ar->rx_failover = skb;
+
+ memset(&ar->rx_plcp, 0, sizeof(struct ar9170_rx_head));
+ ar->rx_has_plcp = false;
+
+ /*
+ * Here's a hidden pitfall!
+ *
+ * All 4 AC queues work perfectly well under _legacy_ operation.
+ * However as soon as aggregation is enabled, the traffic flow
+ * gets very bumpy. Therefore we have to _switch_ to a
+ * software AC with a single HW queue.
+ */
+ hw->queues = __AR9170_NUM_TXQ;
+
+ mutex_init(&ar->mutex);
+ spin_lock_init(&ar->beacon_lock);
+ spin_lock_init(&ar->cmd_lock);
+ spin_lock_init(&ar->tx_stats_lock);
+ spin_lock_init(&ar->tx_ampdu_list_lock);
+ spin_lock_init(&ar->mem_lock);
+ spin_lock_init(&ar->state_lock);
+ atomic_set(&ar->pending_restarts, 0);
+ ar->vifs = 0;
+ for (i = 0; i < ar->hw->queues; i++) {
+ skb_queue_head_init(&ar->tx_status[i]);
+ skb_queue_head_init(&ar->tx_pending[i]);
+ }
+ INIT_WORK(&ar->ps_work, carl9170_ps_work);
+ INIT_WORK(&ar->restart_work, carl9170_restart_work);
+ INIT_WORK(&ar->ampdu_work, carl9170_ampdu_work);
+ INIT_DELAYED_WORK(&ar->tx_janitor, carl9170_tx_janitor);
+ INIT_LIST_HEAD(&ar->tx_ampdu_list);
+ rcu_assign_pointer(ar->tx_ampdu_iter,
+ (struct carl9170_sta_tid *) &ar->tx_ampdu_list);
+
+ bitmap_zero(&ar->vif_bitmap, ar->fw.vif_num);
+ INIT_LIST_HEAD(&ar->vif_list);
+ init_completion(&ar->tx_flush);
+
+ /*
+ * Note:
+ * IBSS/ADHOC and AP mode are only enabled, if the firmware
+ * supports these modes. The code which will add the
+ * additional interface_modes is in fw.c.
+ */
+ hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
+
+ hw->flags |= IEEE80211_HW_RX_INCLUDES_FCS |
+ IEEE80211_HW_REPORTS_TX_ACK_STATUS |
+ IEEE80211_HW_SUPPORTS_PS |
+ IEEE80211_HW_PS_NULLFUNC_STACK |
+ IEEE80211_HW_SIGNAL_DBM;
+
+ if (!modparam_noht) {
+ /*
+ * see the comment above, why we allow the user
+ * to disable HT by a module parameter.
+ */
+ hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION;
+ }
+
+ hw->extra_tx_headroom = sizeof(struct _carl9170_tx_superframe);
+ hw->sta_data_size = sizeof(struct carl9170_sta_info);
+ hw->vif_data_size = sizeof(struct carl9170_vif_info);
+
+ hw->max_rates = CARL9170_TX_MAX_RATES;
+ hw->max_rate_tries = CARL9170_TX_USER_RATE_TRIES;
+
+ for (i = 0; i < ARRAY_SIZE(ar->noise); i++)
+ ar->noise[i] = -95; /* ATH_DEFAULT_NOISE_FLOOR */
+
+ hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
+ return ar;
+
+err_nomem:
+ kfree_skb(skb);
+ return ERR_PTR(-ENOMEM);
+}
+
+static int carl9170_read_eeprom(struct ar9170 *ar)
+{
+#define RW 8 /* number of words to read at once */
+#define RB (sizeof(u32) * RW)
+ u8 *eeprom = (void *)&ar->eeprom;
+ __le32 offsets[RW];
+ int i, j, err;
+
+ BUILD_BUG_ON(sizeof(ar->eeprom) & 3);
+
+ BUILD_BUG_ON(RB > CARL9170_MAX_CMD_LEN - 4);
+#ifndef __CHECKER__
+ /* don't want to handle trailing remains */
+ BUILD_BUG_ON(sizeof(ar->eeprom) % RB);
+#endif
+
+ for (i = 0; i < sizeof(ar->eeprom)/RB; i++) {
+ for (j = 0; j < RW; j++)
+ offsets[j] = cpu_to_le32(AR9170_EEPROM_START +
+ RB * i + 4 * j);
+
+ err = carl9170_exec_cmd(ar, CARL9170_CMD_RREG,
+ RB, (u8 *) &offsets,
+ RB, eeprom + RB * i);
+ if (err)
+ return err;
+ }
+
+#undef RW
+#undef RB
+ return 0;
+}
+
+static int carl9170_parse_eeprom(struct ar9170 *ar)
+{
+ struct ath_regulatory *regulatory = &ar->common.regulatory;
+ unsigned int rx_streams, tx_streams, tx_params = 0;
+ int bands = 0;
+
+ if (ar->eeprom.length == cpu_to_le16(0xffff))
+ return -ENODATA;
+
+ rx_streams = hweight8(ar->eeprom.rx_mask);
+ tx_streams = hweight8(ar->eeprom.tx_mask);
+
+ if (rx_streams != tx_streams) {
+ tx_params = IEEE80211_HT_MCS_TX_RX_DIFF;
+
+ WARN_ON(!(tx_streams >= 1 && tx_streams <=
+ IEEE80211_HT_MCS_TX_MAX_STREAMS));
+
+ tx_params = (tx_streams - 1) <<
+ IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
+
+ carl9170_band_2GHz.ht_cap.mcs.tx_params |= tx_params;
+ carl9170_band_5GHz.ht_cap.mcs.tx_params |= tx_params;
+ }
+
+ if (ar->eeprom.operating_flags & AR9170_OPFLAG_2GHZ) {
+ ar->hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
+ &carl9170_band_2GHz;
+ bands++;
+ }
+ if (ar->eeprom.operating_flags & AR9170_OPFLAG_5GHZ) {
+ ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
+ &carl9170_band_5GHz;
+ bands++;
+ }
+
+ /*
+ * I measured this, a bandswitch takes roughly
+ * 135 ms and a frequency switch about 80.
+ *
+ * FIXME: measure these values again once EEPROM settings
+ * are used, that will influence them!
+ */
+ if (bands == 2)
+ ar->hw->channel_change_time = 135 * 1000;
+ else
+ ar->hw->channel_change_time = 80 * 1000;
+
+ regulatory->current_rd = le16_to_cpu(ar->eeprom.reg_domain[0]);
+ regulatory->current_rd_ext = le16_to_cpu(ar->eeprom.reg_domain[1]);
+
+ /* second part of wiphy init */
+ SET_IEEE80211_PERM_ADDR(ar->hw, ar->eeprom.mac_address);
+
+ return bands ? 0 : -EINVAL;
+}
+
+static int carl9170_reg_notifier(struct wiphy *wiphy,
+ struct regulatory_request *request)
+{
+ struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
+ struct ar9170 *ar = hw->priv;
+
+ return ath_reg_notifier_apply(wiphy, request, &ar->common.regulatory);
+}
+
+int carl9170_register(struct ar9170 *ar)
+{
+ struct ath_regulatory *regulatory = &ar->common.regulatory;
+ int err = 0, i;
+
+ if (WARN_ON(ar->mem_bitmap))
+ return -EINVAL;
+
+ ar->mem_bitmap = kzalloc(roundup(ar->fw.mem_blocks, BITS_PER_LONG) *
+ sizeof(unsigned long), GFP_KERNEL);
+
+ if (!ar->mem_bitmap)
+ return -ENOMEM;
+
+ /* try to read EEPROM, init MAC addr */
+ err = carl9170_read_eeprom(ar);
+ if (err)
+ return err;
+
+ err = carl9170_fw_fix_eeprom(ar);
+ if (err)
+ return err;
+
+ err = carl9170_parse_eeprom(ar);
+ if (err)
+ return err;
+
+ err = ath_regd_init(regulatory, ar->hw->wiphy,
+ carl9170_reg_notifier);
+ if (err)
+ return err;
+
+ if (modparam_noht) {
+ carl9170_band_2GHz.ht_cap.ht_supported = false;
+ carl9170_band_5GHz.ht_cap.ht_supported = false;
+ }
+
+ for (i = 0; i < ar->fw.vif_num; i++) {
+ ar->vif_priv[i].id = i;
+ ar->vif_priv[i].vif = NULL;
+ }
+
+ err = ieee80211_register_hw(ar->hw);
+ if (err)
+ return err;
+
+ /* mac80211 interface is now registered */
+ ar->registered = true;
+
+ if (!ath_is_world_regd(regulatory))
+ regulatory_hint(ar->hw->wiphy, regulatory->alpha2);
+
+#ifdef CONFIG_CARL9170_DEBUGFS
+ carl9170_debugfs_register(ar);
+#endif /* CONFIG_CARL9170_DEBUGFS */
+
+ err = carl9170_led_init(ar);
+ if (err)
+ goto err_unreg;
+
+#ifdef CONFIG_CARL9170_LEDS
+ err = carl9170_led_register(ar);
+ if (err)
+ goto err_unreg;
+#endif /* CONFIG_CAR9L170_LEDS */
+
+#ifdef CONFIG_CARL9170_WPC
+ err = carl9170_register_wps_button(ar);
+ if (err)
+ goto err_unreg;
+#endif /* CONFIG_CARL9170_WPC */
+
+ dev_info(&ar->udev->dev, "Atheros AR9170 is registered as '%s'\n",
+ wiphy_name(ar->hw->wiphy));
+
+ return 0;
+
+err_unreg:
+ carl9170_unregister(ar);
+ return err;
+}
+
+void carl9170_unregister(struct ar9170 *ar)
+{
+ if (!ar->registered)
+ return;
+
+ ar->registered = false;
+
+#ifdef CONFIG_CARL9170_LEDS
+ carl9170_led_unregister(ar);
+#endif /* CONFIG_CARL9170_LEDS */
+
+#ifdef CONFIG_CARL9170_DEBUGFS
+ carl9170_debugfs_unregister(ar);
+#endif /* CONFIG_CARL9170_DEBUGFS */
+
+#ifdef CONFIG_CARL9170_WPC
+ if (ar->wps.pbc) {
+ input_unregister_device(ar->wps.pbc);
+ ar->wps.pbc = NULL;
+ }
+#endif /* CONFIG_CARL9170_WPC */
+
+ carl9170_cancel_worker(ar);
+ cancel_work_sync(&ar->restart_work);
+
+ ieee80211_unregister_hw(ar->hw);
+}
+
+void carl9170_free(struct ar9170 *ar)
+{
+ WARN_ON(ar->registered);
+ WARN_ON(IS_INITIALIZED(ar));
+
+ kfree_skb(ar->rx_failover);
+ ar->rx_failover = NULL;
+
+ kfree(ar->mem_bitmap);
+ ar->mem_bitmap = NULL;
+
+ mutex_destroy(&ar->mutex);
+
+ ieee80211_free_hw(ar->hw);
+}
diff --git a/drivers/net/wireless/ath/carl9170/phy.c b/drivers/net/wireless/ath/carl9170/phy.c
new file mode 100644
index 000000000000..89deca37a988
--- /dev/null
+++ b/drivers/net/wireless/ath/carl9170/phy.c
@@ -0,0 +1,1810 @@
+/*
+ * Atheros CARL9170 driver
+ *
+ * PHY and RF code
+ *
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ * Copyright (c) 2007-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/bitrev.h>
+#include "carl9170.h"
+#include "cmd.h"
+#include "phy.h"
+
+static int carl9170_init_power_cal(struct ar9170 *ar)
+{
+ carl9170_regwrite_begin(ar);
+
+ carl9170_regwrite(AR9170_PHY_REG_POWER_TX_RATE_MAX, 0x7f);
+ carl9170_regwrite(AR9170_PHY_REG_POWER_TX_RATE1, 0x3f3f3f3f);
+ carl9170_regwrite(AR9170_PHY_REG_POWER_TX_RATE2, 0x3f3f3f3f);
+ carl9170_regwrite(AR9170_PHY_REG_POWER_TX_RATE3, 0x3f3f3f3f);
+ carl9170_regwrite(AR9170_PHY_REG_POWER_TX_RATE4, 0x3f3f3f3f);
+ carl9170_regwrite(AR9170_PHY_REG_POWER_TX_RATE5, 0x3f3f3f3f);
+ carl9170_regwrite(AR9170_PHY_REG_POWER_TX_RATE6, 0x3f3f3f3f);
+ carl9170_regwrite(AR9170_PHY_REG_POWER_TX_RATE7, 0x3f3f3f3f);
+ carl9170_regwrite(AR9170_PHY_REG_POWER_TX_RATE8, 0x3f3f3f3f);
+ carl9170_regwrite(AR9170_PHY_REG_POWER_TX_RATE9, 0x3f3f3f3f);
+
+ carl9170_regwrite_finish();
+ return carl9170_regwrite_result();
+}
+
+struct carl9170_phy_init {
+ u32 reg, _5ghz_20, _5ghz_40, _2ghz_40, _2ghz_20;
+};
+
+static struct carl9170_phy_init ar5416_phy_init[] = {
+ { 0x1c5800, 0x00000007, 0x00000007, 0x00000007, 0x00000007, },
+ { 0x1c5804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, },
+ { 0x1c5808, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c580c, 0xad848e19, 0xad848e19, 0xad848e19, 0xad848e19, },
+ { 0x1c5810, 0x7d14e000, 0x7d14e000, 0x7d14e000, 0x7d14e000, },
+ { 0x1c5814, 0x9c0a9f6b, 0x9c0a9f6b, 0x9c0a9f6b, 0x9c0a9f6b, },
+ { 0x1c5818, 0x00000090, 0x00000090, 0x00000090, 0x00000090, },
+ { 0x1c581c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c5820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, },
+ { 0x1c5824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, },
+ { 0x1c5828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, },
+ { 0x1c582c, 0x0000a000, 0x0000a000, 0x0000a000, 0x0000a000, },
+ { 0x1c5830, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c5834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, },
+ { 0x1c5838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, },
+ { 0x1c583c, 0x00200400, 0x00200400, 0x00200400, 0x00200400, },
+ { 0x1c5840, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e, },
+ { 0x1c5844, 0x1372161e, 0x13721c1e, 0x13721c24, 0x137216a4, },
+ { 0x1c5848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, },
+ { 0x1c584c, 0x1284233c, 0x1284233c, 0x1284233c, 0x1284233c, },
+ { 0x1c5850, 0x6c48b4e4, 0x6d48b4e4, 0x6d48b0e4, 0x6c48b0e4, },
+ { 0x1c5854, 0x00000859, 0x00000859, 0x00000859, 0x00000859, },
+ { 0x1c5858, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, },
+ { 0x1c585c, 0x31395c5e, 0x3139605e, 0x3139605e, 0x31395c5e, },
+ { 0x1c5860, 0x0004dd10, 0x0004dd10, 0x0004dd20, 0x0004dd20, },
+ { 0x1c5864, 0x0001c600, 0x0001c600, 0x0001c600, 0x0001c600, },
+ { 0x1c5868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, },
+ { 0x1c586c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, },
+ { 0x1c5900, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c5904, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c5908, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c590c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c5914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, },
+ { 0x1c5918, 0x00000118, 0x00000230, 0x00000268, 0x00000134, },
+ { 0x1c591c, 0x10000fff, 0x10000fff, 0x10000fff, 0x10000fff, },
+ { 0x1c5920, 0x0510081c, 0x0510081c, 0x0510001c, 0x0510001c, },
+ { 0x1c5924, 0xd0058a15, 0xd0058a15, 0xd0058a15, 0xd0058a15, },
+ { 0x1c5928, 0x00000001, 0x00000001, 0x00000001, 0x00000001, },
+ { 0x1c592c, 0x00000004, 0x00000004, 0x00000004, 0x00000004, },
+ { 0x1c5934, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, },
+ { 0x1c5938, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, },
+ { 0x1c593c, 0x0000007f, 0x0000007f, 0x0000007f, 0x0000007f, },
+ { 0x1c5944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, },
+ { 0x1c5948, 0x9280b212, 0x9280b212, 0x9280b212, 0x9280b212, },
+ { 0x1c594c, 0x00020028, 0x00020028, 0x00020028, 0x00020028, },
+ { 0x1c5954, 0x5d50e188, 0x5d50e188, 0x5d50e188, 0x5d50e188, },
+ { 0x1c5958, 0x00081fff, 0x00081fff, 0x00081fff, 0x00081fff, },
+ { 0x1c5960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, },
+ { 0x1c5964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, },
+ { 0x1c5970, 0x190fb515, 0x190fb515, 0x190fb515, 0x190fb515, },
+ { 0x1c5974, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c5978, 0x00000001, 0x00000001, 0x00000001, 0x00000001, },
+ { 0x1c597c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c5980, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c5984, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c5988, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c598c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c5990, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c5994, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c5998, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c599c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c59a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c59a4, 0x00000007, 0x00000007, 0x00000007, 0x00000007, },
+ { 0x1c59a8, 0x001fff00, 0x001fff00, 0x001fff00, 0x001fff00, },
+ { 0x1c59ac, 0x006f00c4, 0x006f00c4, 0x006f00c4, 0x006f00c4, },
+ { 0x1c59b0, 0x03051000, 0x03051000, 0x03051000, 0x03051000, },
+ { 0x1c59b4, 0x00000820, 0x00000820, 0x00000820, 0x00000820, },
+ { 0x1c59bc, 0x00181400, 0x00181400, 0x00181400, 0x00181400, },
+ { 0x1c59c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, },
+ { 0x1c59c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, },
+ { 0x1c59c8, 0x6af6532c, 0x6af6532c, 0x6af6532c, 0x6af6532c, },
+ { 0x1c59cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, },
+ { 0x1c59d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, },
+ { 0x1c59d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c59d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c59dc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c59e0, 0x00000200, 0x00000200, 0x00000200, 0x00000200, },
+ { 0x1c59e4, 0x64646464, 0x64646464, 0x64646464, 0x64646464, },
+ { 0x1c59e8, 0x3c787878, 0x3c787878, 0x3c787878, 0x3c787878, },
+ { 0x1c59ec, 0x000000aa, 0x000000aa, 0x000000aa, 0x000000aa, },
+ { 0x1c59f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c59fc, 0x00001042, 0x00001042, 0x00001042, 0x00001042, },
+ { 0x1c5a00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c5a04, 0x00000040, 0x00000040, 0x00000040, 0x00000040, },
+ { 0x1c5a08, 0x00000080, 0x00000080, 0x00000080, 0x00000080, },
+ { 0x1c5a0c, 0x000001a1, 0x000001a1, 0x00000141, 0x00000141, },
+ { 0x1c5a10, 0x000001e1, 0x000001e1, 0x00000181, 0x00000181, },
+ { 0x1c5a14, 0x00000021, 0x00000021, 0x000001c1, 0x000001c1, },
+ { 0x1c5a18, 0x00000061, 0x00000061, 0x00000001, 0x00000001, },
+ { 0x1c5a1c, 0x00000168, 0x00000168, 0x00000041, 0x00000041, },
+ { 0x1c5a20, 0x000001a8, 0x000001a8, 0x000001a8, 0x000001a8, },
+ { 0x1c5a24, 0x000001e8, 0x000001e8, 0x000001e8, 0x000001e8, },
+ { 0x1c5a28, 0x00000028, 0x00000028, 0x00000028, 0x00000028, },
+ { 0x1c5a2c, 0x00000068, 0x00000068, 0x00000068, 0x00000068, },
+ { 0x1c5a30, 0x00000189, 0x00000189, 0x000000a8, 0x000000a8, },
+ { 0x1c5a34, 0x000001c9, 0x000001c9, 0x00000169, 0x00000169, },
+ { 0x1c5a38, 0x00000009, 0x00000009, 0x000001a9, 0x000001a9, },
+ { 0x1c5a3c, 0x00000049, 0x00000049, 0x000001e9, 0x000001e9, },
+ { 0x1c5a40, 0x00000089, 0x00000089, 0x00000029, 0x00000029, },
+ { 0x1c5a44, 0x00000170, 0x00000170, 0x00000069, 0x00000069, },
+ { 0x1c5a48, 0x000001b0, 0x000001b0, 0x00000190, 0x00000190, },
+ { 0x1c5a4c, 0x000001f0, 0x000001f0, 0x000001d0, 0x000001d0, },
+ { 0x1c5a50, 0x00000030, 0x00000030, 0x00000010, 0x00000010, },
+ { 0x1c5a54, 0x00000070, 0x00000070, 0x00000050, 0x00000050, },
+ { 0x1c5a58, 0x00000191, 0x00000191, 0x00000090, 0x00000090, },
+ { 0x1c5a5c, 0x000001d1, 0x000001d1, 0x00000151, 0x00000151, },
+ { 0x1c5a60, 0x00000011, 0x00000011, 0x00000191, 0x00000191, },
+ { 0x1c5a64, 0x00000051, 0x00000051, 0x000001d1, 0x000001d1, },
+ { 0x1c5a68, 0x00000091, 0x00000091, 0x00000011, 0x00000011, },
+ { 0x1c5a6c, 0x000001b8, 0x000001b8, 0x00000051, 0x00000051, },
+ { 0x1c5a70, 0x000001f8, 0x000001f8, 0x00000198, 0x00000198, },
+ { 0x1c5a74, 0x00000038, 0x00000038, 0x000001d8, 0x000001d8, },
+ { 0x1c5a78, 0x00000078, 0x00000078, 0x00000018, 0x00000018, },
+ { 0x1c5a7c, 0x00000199, 0x00000199, 0x00000058, 0x00000058, },
+ { 0x1c5a80, 0x000001d9, 0x000001d9, 0x00000098, 0x00000098, },
+ { 0x1c5a84, 0x00000019, 0x00000019, 0x00000159, 0x00000159, },
+ { 0x1c5a88, 0x00000059, 0x00000059, 0x00000199, 0x00000199, },
+ { 0x1c5a8c, 0x00000099, 0x00000099, 0x000001d9, 0x000001d9, },
+ { 0x1c5a90, 0x000000d9, 0x000000d9, 0x00000019, 0x00000019, },
+ { 0x1c5a94, 0x000000f9, 0x000000f9, 0x00000059, 0x00000059, },
+ { 0x1c5a98, 0x000000f9, 0x000000f9, 0x00000099, 0x00000099, },
+ { 0x1c5a9c, 0x000000f9, 0x000000f9, 0x000000d9, 0x000000d9, },
+ { 0x1c5aa0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+ { 0x1c5aa4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+ { 0x1c5aa8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+ { 0x1c5aac, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+ { 0x1c5ab0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+ { 0x1c5ab4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+ { 0x1c5ab8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+ { 0x1c5abc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+ { 0x1c5ac0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+ { 0x1c5ac4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+ { 0x1c5ac8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+ { 0x1c5acc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+ { 0x1c5ad0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+ { 0x1c5ad4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+ { 0x1c5ad8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+ { 0x1c5adc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+ { 0x1c5ae0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+ { 0x1c5ae4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+ { 0x1c5ae8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+ { 0x1c5aec, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+ { 0x1c5af0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+ { 0x1c5af4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+ { 0x1c5af8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+ { 0x1c5afc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, },
+ { 0x1c5b00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c5b04, 0x00000001, 0x00000001, 0x00000001, 0x00000001, },
+ { 0x1c5b08, 0x00000002, 0x00000002, 0x00000002, 0x00000002, },
+ { 0x1c5b0c, 0x00000003, 0x00000003, 0x00000003, 0x00000003, },
+ { 0x1c5b10, 0x00000004, 0x00000004, 0x00000004, 0x00000004, },
+ { 0x1c5b14, 0x00000005, 0x00000005, 0x00000005, 0x00000005, },
+ { 0x1c5b18, 0x00000008, 0x00000008, 0x00000008, 0x00000008, },
+ { 0x1c5b1c, 0x00000009, 0x00000009, 0x00000009, 0x00000009, },
+ { 0x1c5b20, 0x0000000a, 0x0000000a, 0x0000000a, 0x0000000a, },
+ { 0x1c5b24, 0x0000000b, 0x0000000b, 0x0000000b, 0x0000000b, },
+ { 0x1c5b28, 0x0000000c, 0x0000000c, 0x0000000c, 0x0000000c, },
+ { 0x1c5b2c, 0x0000000d, 0x0000000d, 0x0000000d, 0x0000000d, },
+ { 0x1c5b30, 0x00000010, 0x00000010, 0x00000010, 0x00000010, },
+ { 0x1c5b34, 0x00000011, 0x00000011, 0x00000011, 0x00000011, },
+ { 0x1c5b38, 0x00000012, 0x00000012, 0x00000012, 0x00000012, },
+ { 0x1c5b3c, 0x00000013, 0x00000013, 0x00000013, 0x00000013, },
+ { 0x1c5b40, 0x00000014, 0x00000014, 0x00000014, 0x00000014, },
+ { 0x1c5b44, 0x00000015, 0x00000015, 0x00000015, 0x00000015, },
+ { 0x1c5b48, 0x00000018, 0x00000018, 0x00000018, 0x00000018, },
+ { 0x1c5b4c, 0x00000019, 0x00000019, 0x00000019, 0x00000019, },
+ { 0x1c5b50, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, },
+ { 0x1c5b54, 0x0000001b, 0x0000001b, 0x0000001b, 0x0000001b, },
+ { 0x1c5b58, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c, },
+ { 0x1c5b5c, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, },
+ { 0x1c5b60, 0x00000020, 0x00000020, 0x00000020, 0x00000020, },
+ { 0x1c5b64, 0x00000021, 0x00000021, 0x00000021, 0x00000021, },
+ { 0x1c5b68, 0x00000022, 0x00000022, 0x00000022, 0x00000022, },
+ { 0x1c5b6c, 0x00000023, 0x00000023, 0x00000023, 0x00000023, },
+ { 0x1c5b70, 0x00000024, 0x00000024, 0x00000024, 0x00000024, },
+ { 0x1c5b74, 0x00000025, 0x00000025, 0x00000025, 0x00000025, },
+ { 0x1c5b78, 0x00000028, 0x00000028, 0x00000028, 0x00000028, },
+ { 0x1c5b7c, 0x00000029, 0x00000029, 0x00000029, 0x00000029, },
+ { 0x1c5b80, 0x0000002a, 0x0000002a, 0x0000002a, 0x0000002a, },
+ { 0x1c5b84, 0x0000002b, 0x0000002b, 0x0000002b, 0x0000002b, },
+ { 0x1c5b88, 0x0000002c, 0x0000002c, 0x0000002c, 0x0000002c, },
+ { 0x1c5b8c, 0x0000002d, 0x0000002d, 0x0000002d, 0x0000002d, },
+ { 0x1c5b90, 0x00000030, 0x00000030, 0x00000030, 0x00000030, },
+ { 0x1c5b94, 0x00000031, 0x00000031, 0x00000031, 0x00000031, },
+ { 0x1c5b98, 0x00000032, 0x00000032, 0x00000032, 0x00000032, },
+ { 0x1c5b9c, 0x00000033, 0x00000033, 0x00000033, 0x00000033, },
+ { 0x1c5ba0, 0x00000034, 0x00000034, 0x00000034, 0x00000034, },
+ { 0x1c5ba4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+ { 0x1c5ba8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+ { 0x1c5bac, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+ { 0x1c5bb0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+ { 0x1c5bb4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+ { 0x1c5bb8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+ { 0x1c5bbc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+ { 0x1c5bc0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+ { 0x1c5bc4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+ { 0x1c5bc8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+ { 0x1c5bcc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+ { 0x1c5bd0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+ { 0x1c5bd4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+ { 0x1c5bd8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+ { 0x1c5bdc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+ { 0x1c5be0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+ { 0x1c5be4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+ { 0x1c5be8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+ { 0x1c5bec, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+ { 0x1c5bf0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+ { 0x1c5bf4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, },
+ { 0x1c5bf8, 0x00000010, 0x00000010, 0x00000010, 0x00000010, },
+ { 0x1c5bfc, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, },
+ { 0x1c5c00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c5c0c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c5c10, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c5c14, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c5c18, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c5c1c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c5c20, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c5c24, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c5c28, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c5c2c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c5c30, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c5c34, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c5c38, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c5c3c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c5cf0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c5cf4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c5cf8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c5cfc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c6200, 0x00000008, 0x00000008, 0x0000000e, 0x0000000e, },
+ { 0x1c6204, 0x00000440, 0x00000440, 0x00000440, 0x00000440, },
+ { 0x1c6208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, },
+ { 0x1c620c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, },
+ { 0x1c6210, 0x40806333, 0x40806333, 0x40806333, 0x40806333, },
+ { 0x1c6214, 0x00106c10, 0x00106c10, 0x00106c10, 0x00106c10, },
+ { 0x1c6218, 0x009c4060, 0x009c4060, 0x009c4060, 0x009c4060, },
+ { 0x1c621c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, },
+ { 0x1c6220, 0x018830c6, 0x018830c6, 0x018830c6, 0x018830c6, },
+ { 0x1c6224, 0x00000400, 0x00000400, 0x00000400, 0x00000400, },
+ { 0x1c6228, 0x000009b5, 0x000009b5, 0x000009b5, 0x000009b5, },
+ { 0x1c622c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c6230, 0x00000108, 0x00000210, 0x00000210, 0x00000108, },
+ { 0x1c6234, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, },
+ { 0x1c6238, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, },
+ { 0x1c623c, 0x13c889af, 0x13c889af, 0x13c889af, 0x13c889af, },
+ { 0x1c6240, 0x38490a20, 0x38490a20, 0x38490a20, 0x38490a20, },
+ { 0x1c6244, 0x00007bb6, 0x00007bb6, 0x00007bb6, 0x00007bb6, },
+ { 0x1c6248, 0x0fff3ffc, 0x0fff3ffc, 0x0fff3ffc, 0x0fff3ffc, },
+ { 0x1c624c, 0x00000001, 0x00000001, 0x00000001, 0x00000001, },
+ { 0x1c6250, 0x0000a000, 0x0000a000, 0x0000a000, 0x0000a000, },
+ { 0x1c6254, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c6258, 0x0cc75380, 0x0cc75380, 0x0cc75380, 0x0cc75380, },
+ { 0x1c625c, 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01, },
+ { 0x1c6260, 0xdfa91f01, 0xdfa91f01, 0xdfa91f01, 0xdfa91f01, },
+ { 0x1c6264, 0x00418a11, 0x00418a11, 0x00418a11, 0x00418a11, },
+ { 0x1c6268, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c626c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, },
+ { 0x1c6274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, },
+ { 0x1c6278, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, },
+ { 0x1c627c, 0x051701ce, 0x051701ce, 0x051701ce, 0x051701ce, },
+ { 0x1c6300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, },
+ { 0x1c6304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, },
+ { 0x1c6308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, },
+ { 0x1c630c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, },
+ { 0x1c6310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, },
+ { 0x1c6314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, },
+ { 0x1c6318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, },
+ { 0x1c631c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, },
+ { 0x1c6320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, },
+ { 0x1c6324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, },
+ { 0x1c6328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, },
+ { 0x1c632c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c6330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c6334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c6338, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c633c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c6340, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c6344, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c6348, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, },
+ { 0x1c634c, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, },
+ { 0x1c6350, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, },
+ { 0x1c6354, 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff, },
+ { 0x1c6358, 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f, },
+ { 0x1c6388, 0x08000000, 0x08000000, 0x08000000, 0x08000000, },
+ { 0x1c638c, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, },
+ { 0x1c6390, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, },
+ { 0x1c6394, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, },
+ { 0x1c6398, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce, },
+ { 0x1c639c, 0x00000007, 0x00000007, 0x00000007, 0x00000007, },
+ { 0x1c63a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c63a4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c63a8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c63ac, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c63b0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c63b4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c63b8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c63bc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c63c0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c63c4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c63c8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c63cc, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, },
+ { 0x1c63d0, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, },
+ { 0x1c63d4, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, },
+ { 0x1c63d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, },
+ { 0x1c63dc, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, },
+ { 0x1c63e0, 0x000000c0, 0x000000c0, 0x000000c0, 0x000000c0, },
+ { 0x1c6848, 0x00180a65, 0x00180a65, 0x00180a68, 0x00180a68, },
+ { 0x1c6920, 0x0510001c, 0x0510001c, 0x0510001c, 0x0510001c, },
+ { 0x1c6960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, },
+ { 0x1c720c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, },
+ { 0x1c726c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, },
+ { 0x1c7848, 0x00180a65, 0x00180a65, 0x00180a68, 0x00180a68, },
+ { 0x1c7920, 0x0510001c, 0x0510001c, 0x0510001c, 0x0510001c, },
+ { 0x1c7960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, },
+ { 0x1c820c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, },
+ { 0x1c826c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, },
+/* { 0x1c8864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, }, */
+ { 0x1c8864, 0x0001c600, 0x0001c600, 0x0001c600, 0x0001c600, },
+ { 0x1c895c, 0x004b6a8e, 0x004b6a8e, 0x004b6a8e, 0x004b6a8e, },
+ { 0x1c8968, 0x000003ce, 0x000003ce, 0x000003ce, 0x000003ce, },
+ { 0x1c89bc, 0x00181400, 0x00181400, 0x00181400, 0x00181400, },
+ { 0x1c9270, 0x00820820, 0x00820820, 0x00820820, 0x00820820, },
+ { 0x1c935c, 0x066c420f, 0x066c420f, 0x066c420f, 0x066c420f, },
+ { 0x1c9360, 0x0f282207, 0x0f282207, 0x0f282207, 0x0f282207, },
+ { 0x1c9364, 0x17601685, 0x17601685, 0x17601685, 0x17601685, },
+ { 0x1c9368, 0x1f801104, 0x1f801104, 0x1f801104, 0x1f801104, },
+ { 0x1c936c, 0x37a00c03, 0x37a00c03, 0x37a00c03, 0x37a00c03, },
+ { 0x1c9370, 0x3fc40883, 0x3fc40883, 0x3fc40883, 0x3fc40883, },
+ { 0x1c9374, 0x57c00803, 0x57c00803, 0x57c00803, 0x57c00803, },
+ { 0x1c9378, 0x5fd80682, 0x5fd80682, 0x5fd80682, 0x5fd80682, },
+ { 0x1c937c, 0x7fe00482, 0x7fe00482, 0x7fe00482, 0x7fe00482, },
+ { 0x1c9380, 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba, },
+ { 0x1c9384, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, }
+};
+
+/*
+ * look up a certain register in ar5416_phy_init[] and return the init. value
+ * for the band and bandwidth given. Return 0 if register address not found.
+ */
+static u32 carl9170_def_val(u32 reg, bool is_2ghz, bool is_40mhz)
+{
+ unsigned int i;
+ for (i = 0; i < ARRAY_SIZE(ar5416_phy_init); i++) {
+ if (ar5416_phy_init[i].reg != reg)
+ continue;
+
+ if (is_2ghz) {
+ if (is_40mhz)
+ return ar5416_phy_init[i]._2ghz_40;
+ else
+ return ar5416_phy_init[i]._2ghz_20;
+ } else {
+ if (is_40mhz)
+ return ar5416_phy_init[i]._5ghz_40;
+ else
+ return ar5416_phy_init[i]._5ghz_20;
+ }
+ }
+ return 0;
+}
+
+/*
+ * initialize some phy regs from eeprom values in modal_header[]
+ * acc. to band and bandwith
+ */
+static int carl9170_init_phy_from_eeprom(struct ar9170 *ar,
+ bool is_2ghz, bool is_40mhz)
+{
+ static const u8 xpd2pd[16] = {
+ 0x2, 0x2, 0x2, 0x1, 0x2, 0x2, 0x6, 0x2,
+ 0x2, 0x3, 0x7, 0x2, 0xb, 0x2, 0x2, 0x2
+ };
+ /* pointer to the modal_header acc. to band */
+ struct ar9170_eeprom_modal *m = &ar->eeprom.modal_header[is_2ghz];
+ u32 val;
+
+ carl9170_regwrite_begin(ar);
+
+ /* ant common control (index 0) */
+ carl9170_regwrite(AR9170_PHY_REG_SWITCH_COM,
+ le32_to_cpu(m->antCtrlCommon));
+
+ /* ant control chain 0 (index 1) */
+ carl9170_regwrite(AR9170_PHY_REG_SWITCH_CHAIN_0,
+ le32_to_cpu(m->antCtrlChain[0]));
+
+ /* ant control chain 2 (index 2) */
+ carl9170_regwrite(AR9170_PHY_REG_SWITCH_CHAIN_2,
+ le32_to_cpu(m->antCtrlChain[1]));
+
+ /* SwSettle (index 3) */
+ if (!is_40mhz) {
+ val = carl9170_def_val(AR9170_PHY_REG_SETTLING,
+ is_2ghz, is_40mhz);
+ SET_VAL(AR9170_PHY_SETTLING_SWITCH, val, m->switchSettling);
+ carl9170_regwrite(AR9170_PHY_REG_SETTLING, val);
+ }
+
+ /* adcDesired, pdaDesired (index 4) */
+ val = carl9170_def_val(AR9170_PHY_REG_DESIRED_SZ, is_2ghz, is_40mhz);
+ SET_VAL(AR9170_PHY_DESIRED_SZ_PGA, val, m->pgaDesiredSize);
+ SET_VAL(AR9170_PHY_DESIRED_SZ_ADC, val, m->adcDesiredSize);
+ carl9170_regwrite(AR9170_PHY_REG_DESIRED_SZ, val);
+
+ /* TxEndToXpaOff, TxFrameToXpaOn (index 5) */
+ val = carl9170_def_val(AR9170_PHY_REG_RF_CTL4, is_2ghz, is_40mhz);
+ SET_VAL(AR9170_PHY_RF_CTL4_TX_END_XPAB_OFF, val, m->txEndToXpaOff);
+ SET_VAL(AR9170_PHY_RF_CTL4_TX_END_XPAA_OFF, val, m->txEndToXpaOff);
+ SET_VAL(AR9170_PHY_RF_CTL4_FRAME_XPAB_ON, val, m->txFrameToXpaOn);
+ SET_VAL(AR9170_PHY_RF_CTL4_FRAME_XPAA_ON, val, m->txFrameToXpaOn);
+ carl9170_regwrite(AR9170_PHY_REG_RF_CTL4, val);
+
+ /* TxEndToRxOn (index 6) */
+ val = carl9170_def_val(AR9170_PHY_REG_RF_CTL3, is_2ghz, is_40mhz);
+ SET_VAL(AR9170_PHY_RF_CTL3_TX_END_TO_A2_RX_ON, val, m->txEndToRxOn);
+ carl9170_regwrite(AR9170_PHY_REG_RF_CTL3, val);
+
+ /* thresh62 (index 7) */
+ val = carl9170_def_val(0x1c8864, is_2ghz, is_40mhz);
+ val = (val & ~0x7f000) | (m->thresh62 << 12);
+ carl9170_regwrite(0x1c8864, val);
+
+ /* tx/rx attenuation chain 0 (index 8) */
+ val = carl9170_def_val(AR9170_PHY_REG_RXGAIN, is_2ghz, is_40mhz);
+ SET_VAL(AR9170_PHY_RXGAIN_TXRX_ATTEN, val, m->txRxAttenCh[0]);
+ carl9170_regwrite(AR9170_PHY_REG_RXGAIN, val);
+
+ /* tx/rx attenuation chain 2 (index 9) */
+ val = carl9170_def_val(AR9170_PHY_REG_RXGAIN_CHAIN_2,
+ is_2ghz, is_40mhz);
+ SET_VAL(AR9170_PHY_RXGAIN_TXRX_ATTEN, val, m->txRxAttenCh[1]);
+ carl9170_regwrite(AR9170_PHY_REG_RXGAIN_CHAIN_2, val);
+
+ /* tx/rx margin chain 0 (index 10) */
+ val = carl9170_def_val(AR9170_PHY_REG_GAIN_2GHZ, is_2ghz, is_40mhz);
+ SET_VAL(AR9170_PHY_GAIN_2GHZ_RXTX_MARGIN, val, m->rxTxMarginCh[0]);
+ /* bsw margin chain 0 for 5GHz only */
+ if (!is_2ghz)
+ SET_VAL(AR9170_PHY_GAIN_2GHZ_BSW_MARGIN, val, m->bswMargin[0]);
+ carl9170_regwrite(AR9170_PHY_REG_GAIN_2GHZ, val);
+
+ /* tx/rx margin chain 2 (index 11) */
+ val = carl9170_def_val(AR9170_PHY_REG_GAIN_2GHZ_CHAIN_2,
+ is_2ghz, is_40mhz);
+ SET_VAL(AR9170_PHY_GAIN_2GHZ_RXTX_MARGIN, val, m->rxTxMarginCh[1]);
+ carl9170_regwrite(AR9170_PHY_REG_GAIN_2GHZ_CHAIN_2, val);
+
+ /* iqCall, iqCallq chain 0 (index 12) */
+ val = carl9170_def_val(AR9170_PHY_REG_TIMING_CTRL4(0),
+ is_2ghz, is_40mhz);
+ SET_VAL(AR9170_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, val, m->iqCalICh[0]);
+ SET_VAL(AR9170_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, val, m->iqCalQCh[0]);
+ carl9170_regwrite(AR9170_PHY_REG_TIMING_CTRL4(0), val);
+
+ /* iqCall, iqCallq chain 2 (index 13) */
+ val = carl9170_def_val(AR9170_PHY_REG_TIMING_CTRL4(2),
+ is_2ghz, is_40mhz);
+ SET_VAL(AR9170_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, val, m->iqCalICh[1]);
+ SET_VAL(AR9170_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, val, m->iqCalQCh[1]);
+ carl9170_regwrite(AR9170_PHY_REG_TIMING_CTRL4(2), val);
+
+ /* xpd gain mask (index 14) */
+ val = carl9170_def_val(AR9170_PHY_REG_TPCRG1, is_2ghz, is_40mhz);
+ SET_VAL(AR9170_PHY_TPCRG1_PD_GAIN_1, val,
+ xpd2pd[m->xpdGain & 0xf] & 3);
+ SET_VAL(AR9170_PHY_TPCRG1_PD_GAIN_2, val,
+ xpd2pd[m->xpdGain & 0xf] >> 2);
+ carl9170_regwrite(AR9170_PHY_REG_TPCRG1, val);
+
+ carl9170_regwrite(AR9170_PHY_REG_RX_CHAINMASK, ar->eeprom.rx_mask);
+ carl9170_regwrite(AR9170_PHY_REG_CAL_CHAINMASK, ar->eeprom.rx_mask);
+
+ carl9170_regwrite_finish();
+ return carl9170_regwrite_result();
+}
+
+static int carl9170_init_phy(struct ar9170 *ar, enum ieee80211_band band)
+{
+ int i, err;
+ u32 val;
+ bool is_2ghz = band == IEEE80211_BAND_2GHZ;
+ bool is_40mhz = conf_is_ht40(&ar->hw->conf);
+
+ carl9170_regwrite_begin(ar);
+
+ for (i = 0; i < ARRAY_SIZE(ar5416_phy_init); i++) {
+ if (is_40mhz) {
+ if (is_2ghz)
+ val = ar5416_phy_init[i]._2ghz_40;
+ else
+ val = ar5416_phy_init[i]._5ghz_40;
+ } else {
+ if (is_2ghz)
+ val = ar5416_phy_init[i]._2ghz_20;
+ else
+ val = ar5416_phy_init[i]._5ghz_20;
+ }
+
+ carl9170_regwrite(ar5416_phy_init[i].reg, val);
+ }
+
+ carl9170_regwrite_finish();
+ err = carl9170_regwrite_result();
+ if (err)
+ return err;
+
+ err = carl9170_init_phy_from_eeprom(ar, is_2ghz, is_40mhz);
+ if (err)
+ return err;
+
+ err = carl9170_init_power_cal(ar);
+ if (err)
+ return err;
+
+ /* XXX: remove magic! */
+ if (is_2ghz)
+ err = carl9170_write_reg(ar, AR9170_PWR_REG_PLL_ADDAC, 0x5163);
+ else
+ err = carl9170_write_reg(ar, AR9170_PWR_REG_PLL_ADDAC, 0x5143);
+
+ return err;
+}
+
+struct carl9170_rf_initvals {
+ u32 reg, _5ghz, _2ghz;
+};
+
+static struct carl9170_rf_initvals carl9170_rf_initval[] = {
+ /* bank 0 */
+ { 0x1c58b0, 0x1e5795e5, 0x1e5795e5},
+ { 0x1c58e0, 0x02008020, 0x02008020},
+ /* bank 1 */
+ { 0x1c58b0, 0x02108421, 0x02108421},
+ { 0x1c58ec, 0x00000008, 0x00000008},
+ /* bank 2 */
+ { 0x1c58b0, 0x0e73ff17, 0x0e73ff17},
+ { 0x1c58e0, 0x00000420, 0x00000420},
+ /* bank 3 */
+ { 0x1c58f0, 0x01400018, 0x01c00018},
+ /* bank 4 */
+ { 0x1c58b0, 0x000001a1, 0x000001a1},
+ { 0x1c58e8, 0x00000001, 0x00000001},
+ /* bank 5 */
+ { 0x1c58b0, 0x00000013, 0x00000013},
+ { 0x1c58e4, 0x00000002, 0x00000002},
+ /* bank 6 */
+ { 0x1c58b0, 0x00000000, 0x00000000},
+ { 0x1c58b0, 0x00000000, 0x00000000},
+ { 0x1c58b0, 0x00000000, 0x00000000},
+ { 0x1c58b0, 0x00000000, 0x00000000},
+ { 0x1c58b0, 0x00000000, 0x00000000},
+ { 0x1c58b0, 0x00004000, 0x00004000},
+ { 0x1c58b0, 0x00006c00, 0x00006c00},
+ { 0x1c58b0, 0x00002c00, 0x00002c00},
+ { 0x1c58b0, 0x00004800, 0x00004800},
+ { 0x1c58b0, 0x00004000, 0x00004000},
+ { 0x1c58b0, 0x00006000, 0x00006000},
+ { 0x1c58b0, 0x00001000, 0x00001000},
+ { 0x1c58b0, 0x00004000, 0x00004000},
+ { 0x1c58b0, 0x00007c00, 0x00007c00},
+ { 0x1c58b0, 0x00007c00, 0x00007c00},
+ { 0x1c58b0, 0x00007c00, 0x00007c00},
+ { 0x1c58b0, 0x00007c00, 0x00007c00},
+ { 0x1c58b0, 0x00007c00, 0x00007c00},
+ { 0x1c58b0, 0x00087c00, 0x00087c00},
+ { 0x1c58b0, 0x00007c00, 0x00007c00},
+ { 0x1c58b0, 0x00005400, 0x00005400},
+ { 0x1c58b0, 0x00000c00, 0x00000c00},
+ { 0x1c58b0, 0x00001800, 0x00001800},
+ { 0x1c58b0, 0x00007c00, 0x00007c00},
+ { 0x1c58b0, 0x00006c00, 0x00006c00},
+ { 0x1c58b0, 0x00006c00, 0x00006c00},
+ { 0x1c58b0, 0x00007c00, 0x00007c00},
+ { 0x1c58b0, 0x00002c00, 0x00002c00},
+ { 0x1c58b0, 0x00003c00, 0x00003c00},
+ { 0x1c58b0, 0x00003800, 0x00003800},
+ { 0x1c58b0, 0x00001c00, 0x00001c00},
+ { 0x1c58b0, 0x00000800, 0x00000800},
+ { 0x1c58b0, 0x00000408, 0x00000408},
+ { 0x1c58b0, 0x00004c15, 0x00004c15},
+ { 0x1c58b0, 0x00004188, 0x00004188},
+ { 0x1c58b0, 0x0000201e, 0x0000201e},
+ { 0x1c58b0, 0x00010408, 0x00010408},
+ { 0x1c58b0, 0x00000801, 0x00000801},
+ { 0x1c58b0, 0x00000c08, 0x00000c08},
+ { 0x1c58b0, 0x0000181e, 0x0000181e},
+ { 0x1c58b0, 0x00001016, 0x00001016},
+ { 0x1c58b0, 0x00002800, 0x00002800},
+ { 0x1c58b0, 0x00004010, 0x00004010},
+ { 0x1c58b0, 0x0000081c, 0x0000081c},
+ { 0x1c58b0, 0x00000115, 0x00000115},
+ { 0x1c58b0, 0x00000015, 0x00000015},
+ { 0x1c58b0, 0x00000066, 0x00000066},
+ { 0x1c58b0, 0x0000001c, 0x0000001c},
+ { 0x1c58b0, 0x00000000, 0x00000000},
+ { 0x1c58b0, 0x00000004, 0x00000004},
+ { 0x1c58b0, 0x00000015, 0x00000015},
+ { 0x1c58b0, 0x0000001f, 0x0000001f},
+ { 0x1c58e0, 0x00000000, 0x00000400},
+ /* bank 7 */
+ { 0x1c58b0, 0x000000a0, 0x000000a0},
+ { 0x1c58b0, 0x00000000, 0x00000000},
+ { 0x1c58b0, 0x00000040, 0x00000040},
+ { 0x1c58f0, 0x0000001c, 0x0000001c},
+};
+
+static int carl9170_init_rf_banks_0_7(struct ar9170 *ar, bool band5ghz)
+{
+ int err, i;
+
+ carl9170_regwrite_begin(ar);
+
+ for (i = 0; i < ARRAY_SIZE(carl9170_rf_initval); i++)
+ carl9170_regwrite(carl9170_rf_initval[i].reg,
+ band5ghz ? carl9170_rf_initval[i]._5ghz
+ : carl9170_rf_initval[i]._2ghz);
+
+ carl9170_regwrite_finish();
+ err = carl9170_regwrite_result();
+ if (err)
+ wiphy_err(ar->hw->wiphy, "rf init failed\n");
+
+ return err;
+}
+
+struct carl9170_phy_freq_params {
+ u8 coeff_exp;
+ u16 coeff_man;
+ u8 coeff_exp_shgi;
+ u16 coeff_man_shgi;
+};
+
+enum carl9170_bw {
+ CARL9170_BW_20,
+ CARL9170_BW_40_BELOW,
+ CARL9170_BW_40_ABOVE,
+
+ __CARL9170_NUM_BW,
+};
+
+struct carl9170_phy_freq_entry {
+ u16 freq;
+ struct carl9170_phy_freq_params params[__CARL9170_NUM_BW];
+};
+
+/* NB: must be in sync with channel tables in main! */
+static const struct carl9170_phy_freq_entry carl9170_phy_freq_params[] = {
+/*
+ * freq,
+ * 20MHz,
+ * 40MHz (below),
+ * 40Mhz (above),
+ */
+ { 2412, {
+ { 3, 21737, 3, 19563, },
+ { 3, 21827, 3, 19644, },
+ { 3, 21647, 3, 19482, },
+ } },
+ { 2417, {
+ { 3, 21692, 3, 19523, },
+ { 3, 21782, 3, 19604, },
+ { 3, 21602, 3, 19442, },
+ } },
+ { 2422, {
+ { 3, 21647, 3, 19482, },
+ { 3, 21737, 3, 19563, },
+ { 3, 21558, 3, 19402, },
+ } },
+ { 2427, {
+ { 3, 21602, 3, 19442, },
+ { 3, 21692, 3, 19523, },
+ { 3, 21514, 3, 19362, },
+ } },
+ { 2432, {
+ { 3, 21558, 3, 19402, },
+ { 3, 21647, 3, 19482, },
+ { 3, 21470, 3, 19323, },
+ } },
+ { 2437, {
+ { 3, 21514, 3, 19362, },
+ { 3, 21602, 3, 19442, },
+ { 3, 21426, 3, 19283, },
+ } },
+ { 2442, {
+ { 3, 21470, 3, 19323, },
+ { 3, 21558, 3, 19402, },
+ { 3, 21382, 3, 19244, },
+ } },
+ { 2447, {
+ { 3, 21426, 3, 19283, },
+ { 3, 21514, 3, 19362, },
+ { 3, 21339, 3, 19205, },
+ } },
+ { 2452, {
+ { 3, 21382, 3, 19244, },
+ { 3, 21470, 3, 19323, },
+ { 3, 21295, 3, 19166, },
+ } },
+ { 2457, {
+ { 3, 21339, 3, 19205, },
+ { 3, 21426, 3, 19283, },
+ { 3, 21252, 3, 19127, },
+ } },
+ { 2462, {
+ { 3, 21295, 3, 19166, },
+ { 3, 21382, 3, 19244, },
+ { 3, 21209, 3, 19088, },
+ } },
+ { 2467, {
+ { 3, 21252, 3, 19127, },
+ { 3, 21339, 3, 19205, },
+ { 3, 21166, 3, 19050, },
+ } },
+ { 2472, {
+ { 3, 21209, 3, 19088, },
+ { 3, 21295, 3, 19166, },
+ { 3, 21124, 3, 19011, },
+ } },
+ { 2484, {
+ { 3, 21107, 3, 18996, },
+ { 3, 21192, 3, 19073, },
+ { 3, 21022, 3, 18920, },
+ } },
+ { 4920, {
+ { 4, 21313, 4, 19181, },
+ { 4, 21356, 4, 19220, },
+ { 4, 21269, 4, 19142, },
+ } },
+ { 4940, {
+ { 4, 21226, 4, 19104, },
+ { 4, 21269, 4, 19142, },
+ { 4, 21183, 4, 19065, },
+ } },
+ { 4960, {
+ { 4, 21141, 4, 19027, },
+ { 4, 21183, 4, 19065, },
+ { 4, 21098, 4, 18988, },
+ } },
+ { 4980, {
+ { 4, 21056, 4, 18950, },
+ { 4, 21098, 4, 18988, },
+ { 4, 21014, 4, 18912, },
+ } },
+ { 5040, {
+ { 4, 20805, 4, 18725, },
+ { 4, 20846, 4, 18762, },
+ { 4, 20764, 4, 18687, },
+ } },
+ { 5060, {
+ { 4, 20723, 4, 18651, },
+ { 4, 20764, 4, 18687, },
+ { 4, 20682, 4, 18614, },
+ } },
+ { 5080, {
+ { 4, 20641, 4, 18577, },
+ { 4, 20682, 4, 18614, },
+ { 4, 20601, 4, 18541, },
+ } },
+ { 5180, {
+ { 4, 20243, 4, 18219, },
+ { 4, 20282, 4, 18254, },
+ { 4, 20204, 4, 18183, },
+ } },
+ { 5200, {
+ { 4, 20165, 4, 18148, },
+ { 4, 20204, 4, 18183, },
+ { 4, 20126, 4, 18114, },
+ } },
+ { 5220, {
+ { 4, 20088, 4, 18079, },
+ { 4, 20126, 4, 18114, },
+ { 4, 20049, 4, 18044, },
+ } },
+ { 5240, {
+ { 4, 20011, 4, 18010, },
+ { 4, 20049, 4, 18044, },
+ { 4, 19973, 4, 17976, },
+ } },
+ { 5260, {
+ { 4, 19935, 4, 17941, },
+ { 4, 19973, 4, 17976, },
+ { 4, 19897, 4, 17907, },
+ } },
+ { 5280, {
+ { 4, 19859, 4, 17873, },
+ { 4, 19897, 4, 17907, },
+ { 4, 19822, 4, 17840, },
+ } },
+ { 5300, {
+ { 4, 19784, 4, 17806, },
+ { 4, 19822, 4, 17840, },
+ { 4, 19747, 4, 17772, },
+ } },
+ { 5320, {
+ { 4, 19710, 4, 17739, },
+ { 4, 19747, 4, 17772, },
+ { 4, 19673, 4, 17706, },
+ } },
+ { 5500, {
+ { 4, 19065, 4, 17159, },
+ { 4, 19100, 4, 17190, },
+ { 4, 19030, 4, 17127, },
+ } },
+ { 5520, {
+ { 4, 18996, 4, 17096, },
+ { 4, 19030, 4, 17127, },
+ { 4, 18962, 4, 17065, },
+ } },
+ { 5540, {
+ { 4, 18927, 4, 17035, },
+ { 4, 18962, 4, 17065, },
+ { 4, 18893, 4, 17004, },
+ } },
+ { 5560, {
+ { 4, 18859, 4, 16973, },
+ { 4, 18893, 4, 17004, },
+ { 4, 18825, 4, 16943, },
+ } },
+ { 5580, {
+ { 4, 18792, 4, 16913, },
+ { 4, 18825, 4, 16943, },
+ { 4, 18758, 4, 16882, },
+ } },
+ { 5600, {
+ { 4, 18725, 4, 16852, },
+ { 4, 18758, 4, 16882, },
+ { 4, 18691, 4, 16822, },
+ } },
+ { 5620, {
+ { 4, 18658, 4, 16792, },
+ { 4, 18691, 4, 16822, },
+ { 4, 18625, 4, 16762, },
+ } },
+ { 5640, {
+ { 4, 18592, 4, 16733, },
+ { 4, 18625, 4, 16762, },
+ { 4, 18559, 4, 16703, },
+ } },
+ { 5660, {
+ { 4, 18526, 4, 16673, },
+ { 4, 18559, 4, 16703, },
+ { 4, 18493, 4, 16644, },
+ } },
+ { 5680, {
+ { 4, 18461, 4, 16615, },
+ { 4, 18493, 4, 16644, },
+ { 4, 18428, 4, 16586, },
+ } },
+ { 5700, {
+ { 4, 18396, 4, 16556, },
+ { 4, 18428, 4, 16586, },
+ { 4, 18364, 4, 16527, },
+ } },
+ { 5745, {
+ { 4, 18252, 4, 16427, },
+ { 4, 18284, 4, 16455, },
+ { 4, 18220, 4, 16398, },
+ } },
+ { 5765, {
+ { 4, 18189, 5, 32740, },
+ { 4, 18220, 4, 16398, },
+ { 4, 18157, 5, 32683, },
+ } },
+ { 5785, {
+ { 4, 18126, 5, 32626, },
+ { 4, 18157, 5, 32683, },
+ { 4, 18094, 5, 32570, },
+ } },
+ { 5805, {
+ { 4, 18063, 5, 32514, },
+ { 4, 18094, 5, 32570, },
+ { 4, 18032, 5, 32458, },
+ } },
+ { 5825, {
+ { 4, 18001, 5, 32402, },
+ { 4, 18032, 5, 32458, },
+ { 4, 17970, 5, 32347, },
+ } },
+ { 5170, {
+ { 4, 20282, 4, 18254, },
+ { 4, 20321, 4, 18289, },
+ { 4, 20243, 4, 18219, },
+ } },
+ { 5190, {
+ { 4, 20204, 4, 18183, },
+ { 4, 20243, 4, 18219, },
+ { 4, 20165, 4, 18148, },
+ } },
+ { 5210, {
+ { 4, 20126, 4, 18114, },
+ { 4, 20165, 4, 18148, },
+ { 4, 20088, 4, 18079, },
+ } },
+ { 5230, {
+ { 4, 20049, 4, 18044, },
+ { 4, 20088, 4, 18079, },
+ { 4, 20011, 4, 18010, },
+ } },
+};
+
+static int carl9170_init_rf_bank4_pwr(struct ar9170 *ar, bool band5ghz,
+ u32 freq, enum carl9170_bw bw)
+{
+ int err;
+ u32 d0, d1, td0, td1, fd0, fd1;
+ u8 chansel;
+ u8 refsel0 = 1, refsel1 = 0;
+ u8 lf_synth = 0;
+
+ switch (bw) {
+ case CARL9170_BW_40_ABOVE:
+ freq += 10;
+ break;
+ case CARL9170_BW_40_BELOW:
+ freq -= 10;
+ break;
+ case CARL9170_BW_20:
+ break;
+ default:
+ BUG();
+ return -ENOSYS;
+ }
+
+ if (band5ghz) {
+ if (freq % 10) {
+ chansel = (freq - 4800) / 5;
+ } else {
+ chansel = ((freq - 4800) / 10) * 2;
+ refsel0 = 0;
+ refsel1 = 1;
+ }
+ chansel = byte_rev_table[chansel];
+ } else {
+ if (freq == 2484) {
+ chansel = 10 + (freq - 2274) / 5;
+ lf_synth = 1;
+ } else
+ chansel = 16 + (freq - 2272) / 5;
+ chansel *= 4;
+ chansel = byte_rev_table[chansel];
+ }
+
+ d1 = chansel;
+ d0 = 0x21 |
+ refsel0 << 3 |
+ refsel1 << 2 |
+ lf_synth << 1;
+ td0 = d0 & 0x1f;
+ td1 = d1 & 0x1f;
+ fd0 = td1 << 5 | td0;
+
+ td0 = (d0 >> 5) & 0x7;
+ td1 = (d1 >> 5) & 0x7;
+ fd1 = td1 << 5 | td0;
+
+ carl9170_regwrite_begin(ar);
+
+ carl9170_regwrite(0x1c58b0, fd0);
+ carl9170_regwrite(0x1c58e8, fd1);
+
+ carl9170_regwrite_finish();
+ err = carl9170_regwrite_result();
+ if (err)
+ return err;
+
+ msleep(20);
+
+ return 0;
+}
+
+static const struct carl9170_phy_freq_params *
+carl9170_get_hw_dyn_params(struct ieee80211_channel *channel,
+ enum carl9170_bw bw)
+{
+ unsigned int chanidx = 0;
+ u16 freq = 2412;
+
+ if (channel) {
+ chanidx = channel->hw_value;
+ freq = channel->center_freq;
+ }
+
+ BUG_ON(chanidx >= ARRAY_SIZE(carl9170_phy_freq_params));
+
+ BUILD_BUG_ON(__CARL9170_NUM_BW != 3);
+
+ WARN_ON(carl9170_phy_freq_params[chanidx].freq != freq);
+
+ return &carl9170_phy_freq_params[chanidx].params[bw];
+}
+
+static int carl9170_find_freq_idx(int nfreqs, u8 *freqs, u8 f)
+{
+ int idx = nfreqs - 2;
+
+ while (idx >= 0) {
+ if (f >= freqs[idx])
+ return idx;
+ idx--;
+ }
+
+ return 0;
+}
+
+static s32 carl9170_interpolate_s32(s32 x, s32 x1, s32 y1, s32 x2, s32 y2)
+{
+ /* nothing to interpolate, it's horizontal */
+ if (y2 == y1)
+ return y1;
+
+ /* check if we hit one of the edges */
+ if (x == x1)
+ return y1;
+ if (x == x2)
+ return y2;
+
+ /* x1 == x2 is bad, hopefully == x */
+ if (x2 == x1)
+ return y1;
+
+ return y1 + (((y2 - y1) * (x - x1)) / (x2 - x1));
+}
+
+static u8 carl9170_interpolate_u8(u8 x, u8 x1, u8 y1, u8 x2, u8 y2)
+{
+#define SHIFT 8
+ s32 y;
+
+ y = carl9170_interpolate_s32(x << SHIFT, x1 << SHIFT,
+ y1 << SHIFT, x2 << SHIFT, y2 << SHIFT);
+
+ /*
+ * XXX: unwrap this expression
+ * Isn't it just DIV_ROUND_UP(y, 1<<SHIFT)?
+ * Can we rely on the compiler to optimise away the div?
+ */
+ return (y >> SHIFT) + ((y & (1<<(SHIFT-1))) >> (SHIFT - 1));
+#undef SHIFT
+}
+
+static u8 carl9170_interpolate_val(u8 x, u8 *x_array, u8 *y_array)
+{
+ int i;
+
+ for (i = 0; i < 3; i++) {
+ if (x <= x_array[i + 1])
+ break;
+ }
+
+ return carl9170_interpolate_u8(x, x_array[i], y_array[i],
+ x_array[i + 1], y_array[i + 1]);
+}
+
+static int carl9170_set_freq_cal_data(struct ar9170 *ar,
+ struct ieee80211_channel *channel)
+{
+ u8 *cal_freq_pier;
+ u8 vpds[2][AR5416_PD_GAIN_ICEPTS];
+ u8 pwrs[2][AR5416_PD_GAIN_ICEPTS];
+ int chain, idx, i;
+ u32 phy_data = 0;
+ u8 f, tmp;
+
+ switch (channel->band) {
+ case IEEE80211_BAND_2GHZ:
+ f = channel->center_freq - 2300;
+ cal_freq_pier = ar->eeprom.cal_freq_pier_2G;
+ i = AR5416_NUM_2G_CAL_PIERS - 1;
+ break;
+
+ case IEEE80211_BAND_5GHZ:
+ f = (channel->center_freq - 4800) / 5;
+ cal_freq_pier = ar->eeprom.cal_freq_pier_5G;
+ i = AR5416_NUM_5G_CAL_PIERS - 1;
+ break;
+
+ default:
+ return -EINVAL;
+ break;
+ }
+
+ for (; i >= 0; i--) {
+ if (cal_freq_pier[i] != 0xff)
+ break;
+ }
+ if (i < 0)
+ return -EINVAL;
+
+ idx = carl9170_find_freq_idx(i, cal_freq_pier, f);
+
+ carl9170_regwrite_begin(ar);
+
+ for (chain = 0; chain < AR5416_MAX_CHAINS; chain++) {
+ for (i = 0; i < AR5416_PD_GAIN_ICEPTS; i++) {
+ struct ar9170_calibration_data_per_freq *cal_pier_data;
+ int j;
+
+ switch (channel->band) {
+ case IEEE80211_BAND_2GHZ:
+ cal_pier_data = &ar->eeprom.
+ cal_pier_data_2G[chain][idx];
+ break;
+
+ case IEEE80211_BAND_5GHZ:
+ cal_pier_data = &ar->eeprom.
+ cal_pier_data_5G[chain][idx];
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ for (j = 0; j < 2; j++) {
+ vpds[j][i] = carl9170_interpolate_u8(f,
+ cal_freq_pier[idx],
+ cal_pier_data->vpd_pdg[j][i],
+ cal_freq_pier[idx + 1],
+ cal_pier_data[1].vpd_pdg[j][i]);
+
+ pwrs[j][i] = carl9170_interpolate_u8(f,
+ cal_freq_pier[idx],
+ cal_pier_data->pwr_pdg[j][i],
+ cal_freq_pier[idx + 1],
+ cal_pier_data[1].pwr_pdg[j][i]) / 2;
+ }
+ }
+
+ for (i = 0; i < 76; i++) {
+ if (i < 25) {
+ tmp = carl9170_interpolate_val(i, &pwrs[0][0],
+ &vpds[0][0]);
+ } else {
+ tmp = carl9170_interpolate_val(i - 12,
+ &pwrs[1][0],
+ &vpds[1][0]);
+ }
+
+ phy_data |= tmp << ((i & 3) << 3);
+ if ((i & 3) == 3) {
+ carl9170_regwrite(0x1c6280 + chain * 0x1000 +
+ (i & ~3), phy_data);
+ phy_data = 0;
+ }
+ }
+
+ for (i = 19; i < 32; i++)
+ carl9170_regwrite(0x1c6280 + chain * 0x1000 + (i << 2),
+ 0x0);
+ }
+
+ carl9170_regwrite_finish();
+ return carl9170_regwrite_result();
+}
+
+static u8 carl9170_get_max_edge_power(struct ar9170 *ar,
+ u32 freq, struct ar9170_calctl_edges edges[])
+{
+ int i;
+ u8 rc = AR5416_MAX_RATE_POWER;
+ u8 f;
+ if (freq < 3000)
+ f = freq - 2300;
+ else
+ f = (freq - 4800) / 5;
+
+ for (i = 0; i < AR5416_NUM_BAND_EDGES; i++) {
+ if (edges[i].channel == 0xff)
+ break;
+ if (f == edges[i].channel) {
+ /* exact freq match */
+ rc = edges[i].power_flags & ~AR9170_CALCTL_EDGE_FLAGS;
+ break;
+ }
+ if (i > 0 && f < edges[i].channel) {
+ if (f > edges[i - 1].channel &&
+ edges[i - 1].power_flags &
+ AR9170_CALCTL_EDGE_FLAGS) {
+ /* lower channel has the inband flag set */
+ rc = edges[i - 1].power_flags &
+ ~AR9170_CALCTL_EDGE_FLAGS;
+ }
+ break;
+ }
+ }
+
+ if (i == AR5416_NUM_BAND_EDGES) {
+ if (f > edges[i - 1].channel &&
+ edges[i - 1].power_flags & AR9170_CALCTL_EDGE_FLAGS) {
+ /* lower channel has the inband flag set */
+ rc = edges[i - 1].power_flags &
+ ~AR9170_CALCTL_EDGE_FLAGS;
+ }
+ }
+ return rc;
+}
+
+static u8 carl9170_get_heavy_clip(struct ar9170 *ar, u32 freq,
+ enum carl9170_bw bw, struct ar9170_calctl_edges edges[])
+{
+ u8 f;
+ int i;
+ u8 rc = 0;
+
+ if (freq < 3000)
+ f = freq - 2300;
+ else
+ f = (freq - 4800) / 5;
+
+ if (bw == CARL9170_BW_40_BELOW || bw == CARL9170_BW_40_ABOVE)
+ rc |= 0xf0;
+
+ for (i = 0; i < AR5416_NUM_BAND_EDGES; i++) {
+ if (edges[i].channel == 0xff)
+ break;
+ if (f == edges[i].channel) {
+ if (!(edges[i].power_flags & AR9170_CALCTL_EDGE_FLAGS))
+ rc |= 0x0f;
+ break;
+ }
+ }
+
+ return rc;
+}
+
+/*
+ * calculate the conformance test limits and the heavy clip parameter
+ * and apply them to ar->power* (derived from otus hal/hpmain.c, line 3706)
+ */
+static void carl9170_calc_ctl(struct ar9170 *ar, u32 freq, enum carl9170_bw bw)
+{
+ u8 ctl_grp; /* CTL group */
+ u8 ctl_idx; /* CTL index */
+ int i, j;
+ struct ctl_modes {
+ u8 ctl_mode;
+ u8 max_power;
+ u8 *pwr_cal_data;
+ int pwr_cal_len;
+ } *modes;
+
+ /*
+ * order is relevant in the mode_list_*: we fall back to the
+ * lower indices if any mode is missed in the EEPROM.
+ */
+ struct ctl_modes mode_list_2ghz[] = {
+ { CTL_11B, 0, ar->power_2G_cck, 4 },
+ { CTL_11G, 0, ar->power_2G_ofdm, 4 },
+ { CTL_2GHT20, 0, ar->power_2G_ht20, 8 },
+ { CTL_2GHT40, 0, ar->power_2G_ht40, 8 },
+ };
+ struct ctl_modes mode_list_5ghz[] = {
+ { CTL_11A, 0, ar->power_5G_leg, 4 },
+ { CTL_5GHT20, 0, ar->power_5G_ht20, 8 },
+ { CTL_5GHT40, 0, ar->power_5G_ht40, 8 },
+ };
+ int nr_modes;
+
+#define EDGES(c, n) (ar->eeprom.ctl_data[c].control_edges[n])
+
+ ar->heavy_clip = 0;
+
+ /*
+ * TODO: investigate the differences between OTUS'
+ * hpreg.c::zfHpGetRegulatoryDomain() and
+ * ath/regd.c::ath_regd_get_band_ctl() -
+ * e.g. for FCC3_WORLD the OTUS procedure
+ * always returns CTL_FCC, while the one in ath/ delivers
+ * CTL_ETSI for 2GHz and CTL_FCC for 5GHz.
+ */
+ ctl_grp = ath_regd_get_band_ctl(&ar->common.regulatory,
+ ar->hw->conf.channel->band);
+
+ /* ctl group not found - either invalid band (NO_CTL) or ww roaming */
+ if (ctl_grp == NO_CTL || ctl_grp == SD_NO_CTL)
+ ctl_grp = CTL_FCC;
+
+ if (ctl_grp != CTL_FCC)
+ /* skip CTL and heavy clip for CTL_MKK and CTL_ETSI */
+ return;
+
+ if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) {
+ modes = mode_list_2ghz;
+ nr_modes = ARRAY_SIZE(mode_list_2ghz);
+ } else {
+ modes = mode_list_5ghz;
+ nr_modes = ARRAY_SIZE(mode_list_5ghz);
+ }
+
+ for (i = 0; i < nr_modes; i++) {
+ u8 c = ctl_grp | modes[i].ctl_mode;
+ for (ctl_idx = 0; ctl_idx < AR5416_NUM_CTLS; ctl_idx++)
+ if (c == ar->eeprom.ctl_index[ctl_idx])
+ break;
+ if (ctl_idx < AR5416_NUM_CTLS) {
+ int f_off = 0;
+
+ /*
+ * determine heavy clip parameter
+ * from the 11G edges array
+ */
+ if (modes[i].ctl_mode == CTL_11G) {
+ ar->heavy_clip =
+ carl9170_get_heavy_clip(ar,
+ freq, bw, EDGES(ctl_idx, 1));
+ }
+
+ /* adjust freq for 40MHz */
+ if (modes[i].ctl_mode == CTL_2GHT40 ||
+ modes[i].ctl_mode == CTL_5GHT40) {
+ if (bw == CARL9170_BW_40_BELOW)
+ f_off = -10;
+ else
+ f_off = 10;
+ }
+
+ modes[i].max_power =
+ carl9170_get_max_edge_power(ar,
+ freq+f_off, EDGES(ctl_idx, 1));
+
+ /*
+ * TODO: check if the regulatory max. power is
+ * controlled by cfg80211 for DFS.
+ * (hpmain applies it to max_power itself for DFS freq)
+ */
+
+ } else {
+ /*
+ * Workaround in otus driver, hpmain.c, line 3906:
+ * if no data for 5GHT20 are found, take the
+ * legacy 5G value. We extend this here to fallback
+ * from any other HT* or 11G, too.
+ */
+ int k = i;
+
+ modes[i].max_power = AR5416_MAX_RATE_POWER;
+ while (k-- > 0) {
+ if (modes[k].max_power !=
+ AR5416_MAX_RATE_POWER) {
+ modes[i].max_power = modes[k].max_power;
+ break;
+ }
+ }
+ }
+
+ /* apply max power to pwr_cal_data (ar->power_*) */
+ for (j = 0; j < modes[i].pwr_cal_len; j++) {
+ modes[i].pwr_cal_data[j] = min(modes[i].pwr_cal_data[j],
+ modes[i].max_power);
+ }
+ }
+
+ if (ar->heavy_clip & 0xf0) {
+ ar->power_2G_ht40[0]--;
+ ar->power_2G_ht40[1]--;
+ ar->power_2G_ht40[2]--;
+ }
+ if (ar->heavy_clip & 0xf) {
+ ar->power_2G_ht20[0]++;
+ ar->power_2G_ht20[1]++;
+ ar->power_2G_ht20[2]++;
+ }
+
+#undef EDGES
+}
+
+static int carl9170_set_power_cal(struct ar9170 *ar, u32 freq,
+ enum carl9170_bw bw)
+{
+ struct ar9170_calibration_target_power_legacy *ctpl;
+ struct ar9170_calibration_target_power_ht *ctph;
+ u8 *ctpres;
+ int ntargets;
+ int idx, i, n;
+ u8 ackpower, ackchains, f;
+ u8 pwr_freqs[AR5416_MAX_NUM_TGT_PWRS];
+
+ if (freq < 3000)
+ f = freq - 2300;
+ else
+ f = (freq - 4800)/5;
+
+ /*
+ * cycle through the various modes
+ *
+ * legacy modes first: 5G, 2G CCK, 2G OFDM
+ */
+ for (i = 0; i < 3; i++) {
+ switch (i) {
+ case 0: /* 5 GHz legacy */
+ ctpl = &ar->eeprom.cal_tgt_pwr_5G[0];
+ ntargets = AR5416_NUM_5G_TARGET_PWRS;
+ ctpres = ar->power_5G_leg;
+ break;
+ case 1: /* 2.4 GHz CCK */
+ ctpl = &ar->eeprom.cal_tgt_pwr_2G_cck[0];
+ ntargets = AR5416_NUM_2G_CCK_TARGET_PWRS;
+ ctpres = ar->power_2G_cck;
+ break;
+ case 2: /* 2.4 GHz OFDM */
+ ctpl = &ar->eeprom.cal_tgt_pwr_2G_ofdm[0];
+ ntargets = AR5416_NUM_2G_OFDM_TARGET_PWRS;
+ ctpres = ar->power_2G_ofdm;
+ break;
+ default:
+ BUG();
+ }
+
+ for (n = 0; n < ntargets; n++) {
+ if (ctpl[n].freq == 0xff)
+ break;
+ pwr_freqs[n] = ctpl[n].freq;
+ }
+ ntargets = n;
+ idx = carl9170_find_freq_idx(ntargets, pwr_freqs, f);
+ for (n = 0; n < 4; n++)
+ ctpres[n] = carl9170_interpolate_u8(f,
+ ctpl[idx + 0].freq, ctpl[idx + 0].power[n],
+ ctpl[idx + 1].freq, ctpl[idx + 1].power[n]);
+ }
+
+ /* HT modes now: 5G HT20, 5G HT40, 2G CCK, 2G OFDM, 2G HT20, 2G HT40 */
+ for (i = 0; i < 4; i++) {
+ switch (i) {
+ case 0: /* 5 GHz HT 20 */
+ ctph = &ar->eeprom.cal_tgt_pwr_5G_ht20[0];
+ ntargets = AR5416_NUM_5G_TARGET_PWRS;
+ ctpres = ar->power_5G_ht20;
+ break;
+ case 1: /* 5 GHz HT 40 */
+ ctph = &ar->eeprom.cal_tgt_pwr_5G_ht40[0];
+ ntargets = AR5416_NUM_5G_TARGET_PWRS;
+ ctpres = ar->power_5G_ht40;
+ break;
+ case 2: /* 2.4 GHz HT 20 */
+ ctph = &ar->eeprom.cal_tgt_pwr_2G_ht20[0];
+ ntargets = AR5416_NUM_2G_OFDM_TARGET_PWRS;
+ ctpres = ar->power_2G_ht20;
+ break;
+ case 3: /* 2.4 GHz HT 40 */
+ ctph = &ar->eeprom.cal_tgt_pwr_2G_ht40[0];
+ ntargets = AR5416_NUM_2G_OFDM_TARGET_PWRS;
+ ctpres = ar->power_2G_ht40;
+ break;
+ default:
+ BUG();
+ }
+
+ for (n = 0; n < ntargets; n++) {
+ if (ctph[n].freq == 0xff)
+ break;
+ pwr_freqs[n] = ctph[n].freq;
+ }
+ ntargets = n;
+ idx = carl9170_find_freq_idx(ntargets, pwr_freqs, f);
+ for (n = 0; n < 8; n++)
+ ctpres[n] = carl9170_interpolate_u8(f,
+ ctph[idx + 0].freq, ctph[idx + 0].power[n],
+ ctph[idx + 1].freq, ctph[idx + 1].power[n]);
+ }
+
+ /* calc. conformance test limits and apply to ar->power*[] */
+ carl9170_calc_ctl(ar, freq, bw);
+
+ /* set ACK/CTS TX power */
+ carl9170_regwrite_begin(ar);
+
+ if (ar->eeprom.tx_mask != 1)
+ ackchains = AR9170_TX_PHY_TXCHAIN_2;
+ else
+ ackchains = AR9170_TX_PHY_TXCHAIN_1;
+
+ if (freq < 3000)
+ ackpower = ar->power_2G_ofdm[0] & 0x3f;
+ else
+ ackpower = ar->power_5G_leg[0] & 0x3f;
+
+ carl9170_regwrite(AR9170_MAC_REG_ACK_TPC,
+ 0x3c1e | ackpower << 20 | ackchains << 26);
+ carl9170_regwrite(AR9170_MAC_REG_RTS_CTS_TPC,
+ ackpower << 5 | ackchains << 11 |
+ ackpower << 21 | ackchains << 27);
+
+ carl9170_regwrite(AR9170_MAC_REG_CFEND_QOSNULL_TPC,
+ ackpower << 5 | ackchains << 11 |
+ ackpower << 21 | ackchains << 27);
+
+ carl9170_regwrite_finish();
+ return carl9170_regwrite_result();
+}
+
+/* TODO: replace this with sign_extend32(noise, 8) */
+static int carl9170_calc_noise_dbm(u32 raw_noise)
+{
+ if (raw_noise & 0x100)
+ return ~0x1ff | raw_noise;
+ else
+ return raw_noise;
+}
+
+int carl9170_get_noisefloor(struct ar9170 *ar)
+{
+ static const u32 phy_regs[] = {
+ AR9170_PHY_REG_CCA, AR9170_PHY_REG_CH2_CCA,
+ AR9170_PHY_REG_EXT_CCA, AR9170_PHY_REG_CH2_EXT_CCA };
+ u32 phy_res[ARRAY_SIZE(phy_regs)];
+ int err, i;
+
+ BUILD_BUG_ON(ARRAY_SIZE(phy_regs) != ARRAY_SIZE(ar->noise));
+
+ err = carl9170_read_mreg(ar, ARRAY_SIZE(phy_regs), phy_regs, phy_res);
+ if (err)
+ return err;
+
+ for (i = 0; i < 2; i++) {
+ ar->noise[i] = carl9170_calc_noise_dbm(
+ (phy_res[i] >> 19) & 0x1ff);
+
+ ar->noise[i + 2] = carl9170_calc_noise_dbm(
+ (phy_res[i + 2] >> 23) & 0x1ff);
+ }
+
+ return 0;
+}
+
+static enum carl9170_bw nl80211_to_carl(enum nl80211_channel_type type)
+{
+ switch (type) {
+ case NL80211_CHAN_NO_HT:
+ case NL80211_CHAN_HT20:
+ return CARL9170_BW_20;
+ case NL80211_CHAN_HT40MINUS:
+ return CARL9170_BW_40_BELOW;
+ case NL80211_CHAN_HT40PLUS:
+ return CARL9170_BW_40_ABOVE;
+ default:
+ BUG();
+ }
+}
+
+int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
+ enum nl80211_channel_type _bw,
+ enum carl9170_rf_init_mode rfi)
+{
+ const struct carl9170_phy_freq_params *freqpar;
+ struct carl9170_rf_init_result rf_res;
+ struct carl9170_rf_init rf;
+ u32 cmd, tmp, offs = 0, new_ht = 0;
+ int err;
+ enum carl9170_bw bw;
+ bool warm_reset;
+ struct ieee80211_channel *old_channel = NULL;
+
+ bw = nl80211_to_carl(_bw);
+
+ if (conf_is_ht(&ar->hw->conf))
+ new_ht |= CARL9170FW_PHY_HT_ENABLE;
+
+ if (conf_is_ht40(&ar->hw->conf))
+ new_ht |= CARL9170FW_PHY_HT_DYN2040;
+
+ /* may be NULL at first setup */
+ if (ar->channel) {
+ old_channel = ar->channel;
+ warm_reset = (old_channel->band != channel->band) ||
+ (old_channel->center_freq ==
+ channel->center_freq) ||
+ (ar->ht_settings != new_ht);
+
+ ar->channel = NULL;
+ } else {
+ warm_reset = true;
+ }
+
+ /* HW workaround */
+ if (!ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] &&
+ channel->center_freq <= 2417)
+ warm_reset = true;
+
+ if (rfi != CARL9170_RFI_NONE || warm_reset) {
+ u32 val;
+
+ if (rfi == CARL9170_RFI_COLD)
+ val = AR9170_PWR_RESET_BB_COLD_RESET;
+ else
+ val = AR9170_PWR_RESET_BB_WARM_RESET;
+
+ /* warm/cold reset BB/ADDA */
+ err = carl9170_write_reg(ar, AR9170_PWR_REG_RESET, val);
+ if (err)
+ return err;
+
+ err = carl9170_write_reg(ar, AR9170_PWR_REG_RESET, 0x0);
+ if (err)
+ return err;
+
+ err = carl9170_init_phy(ar, channel->band);
+ if (err)
+ return err;
+
+ err = carl9170_init_rf_banks_0_7(ar,
+ channel->band == IEEE80211_BAND_5GHZ);
+ if (err)
+ return err;
+
+ cmd = CARL9170_CMD_RF_INIT;
+
+ msleep(100);
+
+ err = carl9170_echo_test(ar, 0xaabbccdd);
+ if (err)
+ return err;
+ } else {
+ cmd = CARL9170_CMD_FREQUENCY;
+ }
+
+ err = carl9170_exec_cmd(ar, CARL9170_CMD_FREQ_START, 0, NULL, 0, NULL);
+ if (err)
+ return err;
+
+ err = carl9170_write_reg(ar, AR9170_PHY_REG_HEAVY_CLIP_ENABLE,
+ 0x200);
+
+ err = carl9170_init_rf_bank4_pwr(ar,
+ channel->band == IEEE80211_BAND_5GHZ,
+ channel->center_freq, bw);
+ if (err)
+ return err;
+
+ tmp = AR9170_PHY_TURBO_FC_SINGLE_HT_LTF1 |
+ AR9170_PHY_TURBO_FC_HT_EN;
+
+ switch (bw) {
+ case CARL9170_BW_20:
+ break;
+ case CARL9170_BW_40_BELOW:
+ tmp |= AR9170_PHY_TURBO_FC_DYN2040_EN |
+ AR9170_PHY_TURBO_FC_SHORT_GI_40;
+ offs = 3;
+ break;
+ case CARL9170_BW_40_ABOVE:
+ tmp |= AR9170_PHY_TURBO_FC_DYN2040_EN |
+ AR9170_PHY_TURBO_FC_SHORT_GI_40 |
+ AR9170_PHY_TURBO_FC_DYN2040_PRI_CH;
+ offs = 1;
+ break;
+ default:
+ BUG();
+ return -ENOSYS;
+ }
+
+ if (ar->eeprom.tx_mask != 1)
+ tmp |= AR9170_PHY_TURBO_FC_WALSH;
+
+ err = carl9170_write_reg(ar, AR9170_PHY_REG_TURBO, tmp);
+ if (err)
+ return err;
+
+ err = carl9170_set_freq_cal_data(ar, channel);
+ if (err)
+ return err;
+
+ err = carl9170_set_power_cal(ar, channel->center_freq, bw);
+ if (err)
+ return err;
+
+ freqpar = carl9170_get_hw_dyn_params(channel, bw);
+
+ rf.ht_settings = new_ht;
+ if (conf_is_ht40(&ar->hw->conf))
+ SET_VAL(CARL9170FW_PHY_HT_EXT_CHAN_OFF, rf.ht_settings, offs);
+
+ rf.freq = cpu_to_le32(channel->center_freq * 1000);
+ rf.delta_slope_coeff_exp = cpu_to_le32(freqpar->coeff_exp);
+ rf.delta_slope_coeff_man = cpu_to_le32(freqpar->coeff_man);
+ rf.delta_slope_coeff_exp_shgi = cpu_to_le32(freqpar->coeff_exp_shgi);
+ rf.delta_slope_coeff_man_shgi = cpu_to_le32(freqpar->coeff_man_shgi);
+
+ if (rfi != CARL9170_RFI_NONE)
+ rf.finiteLoopCount = cpu_to_le32(2000);
+ else
+ rf.finiteLoopCount = cpu_to_le32(1000);
+
+ err = carl9170_exec_cmd(ar, cmd, sizeof(rf), &rf,
+ sizeof(rf_res), &rf_res);
+ if (err)
+ return err;
+
+ err = le32_to_cpu(rf_res.ret);
+ if (err != 0) {
+ ar->chan_fail++;
+ ar->total_chan_fail++;
+
+ wiphy_err(ar->hw->wiphy, "channel change: %d -> %d "
+ "failed (%d).\n", old_channel ?
+ old_channel->center_freq : -1, channel->center_freq,
+ err);
+
+ if ((rfi == CARL9170_RFI_COLD) || (ar->chan_fail > 3)) {
+ /*
+ * We have tried very hard to change to _another_
+ * channel and we've failed to do so!
+ * Chances are that the PHY/RF is no longer
+ * operable (due to corruptions/fatal events/bugs?)
+ * and we need to reset at a higher level.
+ */
+ carl9170_restart(ar, CARL9170_RR_TOO_MANY_PHY_ERRORS);
+ return 0;
+ }
+
+ err = carl9170_set_channel(ar, channel, _bw,
+ CARL9170_RFI_COLD);
+ if (err)
+ return err;
+ } else {
+ ar->chan_fail = 0;
+ }
+
+ err = carl9170_get_noisefloor(ar);
+ if (err)
+ return err;
+
+ if (ar->heavy_clip) {
+ err = carl9170_write_reg(ar, AR9170_PHY_REG_HEAVY_CLIP_ENABLE,
+ 0x200 | ar->heavy_clip);
+ if (err) {
+ if (net_ratelimit()) {
+ wiphy_err(ar->hw->wiphy, "failed to set "
+ "heavy clip\n");
+ }
+
+ return err;
+ }
+ }
+
+ /* FIXME: PSM does not work in 5GHz Band */
+ if (channel->band == IEEE80211_BAND_5GHZ)
+ ar->ps.off_override |= PS_OFF_5GHZ;
+ else
+ ar->ps.off_override &= ~PS_OFF_5GHZ;
+
+ ar->channel = channel;
+ ar->ht_settings = new_ht;
+ return 0;
+}
diff --git a/drivers/net/wireless/ath/carl9170/phy.h b/drivers/net/wireless/ath/carl9170/phy.h
new file mode 100644
index 000000000000..02c34eb4ebde
--- /dev/null
+++ b/drivers/net/wireless/ath/carl9170/phy.h
@@ -0,0 +1,564 @@
+/*
+ * Shared Atheros AR9170 Header
+ *
+ * PHY register map
+ *
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __CARL9170_SHARED_PHY_H
+#define __CARL9170_SHARED_PHY_H
+
+#define AR9170_PHY_REG_BASE (0x1bc000 + 0x9800)
+#define AR9170_PHY_REG(_n) (AR9170_PHY_REG_BASE + \
+ ((_n) << 2))
+
+#define AR9170_PHY_REG_TEST (AR9170_PHY_REG_BASE + 0x0000)
+#define AR9170_PHY_TEST_AGC_CLR 0x10000000
+#define AR9170_PHY_TEST_RFSILENT_BB 0x00002000
+
+#define AR9170_PHY_REG_TURBO (AR9170_PHY_REG_BASE + 0x0004)
+#define AR9170_PHY_TURBO_FC_TURBO_MODE 0x00000001
+#define AR9170_PHY_TURBO_FC_TURBO_SHORT 0x00000002
+#define AR9170_PHY_TURBO_FC_DYN2040_EN 0x00000004
+#define AR9170_PHY_TURBO_FC_DYN2040_PRI_ONLY 0x00000008
+#define AR9170_PHY_TURBO_FC_DYN2040_PRI_CH 0x00000010
+/* For 25 MHz channel spacing -- not used but supported by hw */
+#define AR9170_PHY_TURBO_FC_DYN2040_EXT_CH 0x00000020
+#define AR9170_PHY_TURBO_FC_HT_EN 0x00000040
+#define AR9170_PHY_TURBO_FC_SHORT_GI_40 0x00000080
+#define AR9170_PHY_TURBO_FC_WALSH 0x00000100
+#define AR9170_PHY_TURBO_FC_SINGLE_HT_LTF1 0x00000200
+#define AR9170_PHY_TURBO_FC_ENABLE_DAC_FIFO 0x00000800
+
+#define AR9170_PHY_REG_TEST2 (AR9170_PHY_REG_BASE + 0x0008)
+
+#define AR9170_PHY_REG_TIMING2 (AR9170_PHY_REG_BASE + 0x0010)
+#define AR9170_PHY_TIMING2_USE_FORCE 0x00001000
+#define AR9170_PHY_TIMING2_FORCE 0x00000fff
+#define AR9170_PHY_TIMING2_FORCE_S 0
+
+#define AR9170_PHY_REG_TIMING3 (AR9170_PHY_REG_BASE + 0x0014)
+#define AR9170_PHY_TIMING3_DSC_EXP 0x0001e000
+#define AR9170_PHY_TIMING3_DSC_EXP_S 13
+#define AR9170_PHY_TIMING3_DSC_MAN 0xfffe0000
+#define AR9170_PHY_TIMING3_DSC_MAN_S 17
+
+#define AR9170_PHY_REG_CHIP_ID (AR9170_PHY_REG_BASE + 0x0018)
+#define AR9170_PHY_CHIP_ID_REV_0 0x80
+#define AR9170_PHY_CHIP_ID_REV_1 0x81
+#define AR9170_PHY_CHIP_ID_9160_REV_0 0xb0
+
+#define AR9170_PHY_REG_ACTIVE (AR9170_PHY_REG_BASE + 0x001c)
+#define AR9170_PHY_ACTIVE_EN 0x00000001
+#define AR9170_PHY_ACTIVE_DIS 0x00000000
+
+#define AR9170_PHY_REG_RF_CTL2 (AR9170_PHY_REG_BASE + 0x0024)
+#define AR9170_PHY_RF_CTL2_TX_END_DATA_START 0x000000ff
+#define AR9170_PHY_RF_CTL2_TX_END_DATA_START_S 0
+#define AR9170_PHY_RF_CTL2_TX_END_PA_ON 0x0000ff00
+#define AR9170_PHY_RF_CTL2_TX_END_PA_ON_S 8
+
+#define AR9170_PHY_REG_RF_CTL3 (AR9170_PHY_REG_BASE + 0x0028)
+#define AR9170_PHY_RF_CTL3_TX_END_TO_A2_RX_ON 0x00ff0000
+#define AR9170_PHY_RF_CTL3_TX_END_TO_A2_RX_ON_S 16
+
+#define AR9170_PHY_REG_ADC_CTL (AR9170_PHY_REG_BASE + 0x002c)
+#define AR9170_PHY_ADC_CTL_OFF_INBUFGAIN 0x00000003
+#define AR9170_PHY_ADC_CTL_OFF_INBUFGAIN_S 0
+#define AR9170_PHY_ADC_CTL_OFF_PWDDAC 0x00002000
+#define AR9170_PHY_ADC_CTL_OFF_PWDBANDGAP 0x00004000
+#define AR9170_PHY_ADC_CTL_OFF_PWDADC 0x00008000
+#define AR9170_PHY_ADC_CTL_ON_INBUFGAIN 0x00030000
+#define AR9170_PHY_ADC_CTL_ON_INBUFGAIN_S 16
+
+#define AR9170_PHY_REG_ADC_SERIAL_CTL (AR9170_PHY_REG_BASE + 0x0030)
+#define AR9170_PHY_ADC_SCTL_SEL_INTERNAL_ADDAC 0x00000000
+#define AR9170_PHY_ADC_SCTL_SEL_EXTERNAL_RADIO 0x00000001
+
+#define AR9170_PHY_REG_RF_CTL4 (AR9170_PHY_REG_BASE + 0x0034)
+#define AR9170_PHY_RF_CTL4_TX_END_XPAB_OFF 0xff000000
+#define AR9170_PHY_RF_CTL4_TX_END_XPAB_OFF_S 24
+#define AR9170_PHY_RF_CTL4_TX_END_XPAA_OFF 0x00ff0000
+#define AR9170_PHY_RF_CTL4_TX_END_XPAA_OFF_S 16
+#define AR9170_PHY_RF_CTL4_FRAME_XPAB_ON 0x0000ff00
+#define AR9170_PHY_RF_CTL4_FRAME_XPAB_ON_S 8
+#define AR9170_PHY_RF_CTL4_FRAME_XPAA_ON 0x000000ff
+#define AR9170_PHY_RF_CTL4_FRAME_XPAA_ON_S 0
+
+#define AR9170_PHY_REG_TSTDAC_CONST (AR9170_PHY_REG_BASE + 0x003c)
+
+#define AR9170_PHY_REG_SETTLING (AR9170_PHY_REG_BASE + 0x0044)
+#define AR9170_PHY_SETTLING_SWITCH 0x00003f80
+#define AR9170_PHY_SETTLING_SWITCH_S 7
+
+#define AR9170_PHY_REG_RXGAIN (AR9170_PHY_REG_BASE + 0x0048)
+#define AR9170_PHY_REG_RXGAIN_CHAIN_2 (AR9170_PHY_REG_BASE + 0x2048)
+#define AR9170_PHY_RXGAIN_TXRX_ATTEN 0x0003f000
+#define AR9170_PHY_RXGAIN_TXRX_ATTEN_S 12
+#define AR9170_PHY_RXGAIN_TXRX_RF_MAX 0x007c0000
+#define AR9170_PHY_RXGAIN_TXRX_RF_MAX_S 18
+
+#define AR9170_PHY_REG_DESIRED_SZ (AR9170_PHY_REG_BASE + 0x0050)
+#define AR9170_PHY_DESIRED_SZ_ADC 0x000000ff
+#define AR9170_PHY_DESIRED_SZ_ADC_S 0
+#define AR9170_PHY_DESIRED_SZ_PGA 0x0000ff00
+#define AR9170_PHY_DESIRED_SZ_PGA_S 8
+#define AR9170_PHY_DESIRED_SZ_TOT_DES 0x0ff00000
+#define AR9170_PHY_DESIRED_SZ_TOT_DES_S 20
+
+#define AR9170_PHY_REG_FIND_SIG (AR9170_PHY_REG_BASE + 0x0058)
+#define AR9170_PHY_FIND_SIG_FIRSTEP 0x0003f000
+#define AR9170_PHY_FIND_SIG_FIRSTEP_S 12
+#define AR9170_PHY_FIND_SIG_FIRPWR 0x03fc0000
+#define AR9170_PHY_FIND_SIG_FIRPWR_S 18
+
+#define AR9170_PHY_REG_AGC_CTL1 (AR9170_PHY_REG_BASE + 0x005c)
+#define AR9170_PHY_AGC_CTL1_COARSE_LOW 0x00007f80
+#define AR9170_PHY_AGC_CTL1_COARSE_LOW_S 7
+#define AR9170_PHY_AGC_CTL1_COARSE_HIGH 0x003f8000
+#define AR9170_PHY_AGC_CTL1_COARSE_HIGH_S 15
+
+#define AR9170_PHY_REG_AGC_CONTROL (AR9170_PHY_REG_BASE + 0x0060)
+#define AR9170_PHY_AGC_CONTROL_CAL 0x00000001
+#define AR9170_PHY_AGC_CONTROL_NF 0x00000002
+#define AR9170_PHY_AGC_CONTROL_ENABLE_NF 0x00008000
+#define AR9170_PHY_AGC_CONTROL_FLTR_CAL 0x00010000
+#define AR9170_PHY_AGC_CONTROL_NO_UPDATE_NF 0x00020000
+
+#define AR9170_PHY_REG_CCA (AR9170_PHY_REG_BASE + 0x0064)
+#define AR9170_PHY_CCA_MINCCA_PWR 0x0ff80000
+#define AR9170_PHY_CCA_MINCCA_PWR_S 19
+#define AR9170_PHY_CCA_THRESH62 0x0007f000
+#define AR9170_PHY_CCA_THRESH62_S 12
+
+#define AR9170_PHY_REG_SFCORR (AR9170_PHY_REG_BASE + 0x0068)
+#define AR9170_PHY_SFCORR_M2COUNT_THR 0x0000001f
+#define AR9170_PHY_SFCORR_M2COUNT_THR_S 0
+#define AR9170_PHY_SFCORR_M1_THRESH 0x00fe0000
+#define AR9170_PHY_SFCORR_M1_THRESH_S 17
+#define AR9170_PHY_SFCORR_M2_THRESH 0x7f000000
+#define AR9170_PHY_SFCORR_M2_THRESH_S 24
+
+#define AR9170_PHY_REG_SFCORR_LOW (AR9170_PHY_REG_BASE + 0x006c)
+#define AR9170_PHY_SFCORR_LOW_USE_SELF_CORR_LOW 0x00000001
+#define AR9170_PHY_SFCORR_LOW_M2COUNT_THR_LOW 0x00003f00
+#define AR9170_PHY_SFCORR_LOW_M2COUNT_THR_LOW_S 8
+#define AR9170_PHY_SFCORR_LOW_M1_THRESH_LOW 0x001fc000
+#define AR9170_PHY_SFCORR_LOW_M1_THRESH_LOW_S 14
+#define AR9170_PHY_SFCORR_LOW_M2_THRESH_LOW 0x0fe00000
+#define AR9170_PHY_SFCORR_LOW_M2_THRESH_LOW_S 21
+
+#define AR9170_PHY_REG_SLEEP_CTR_CONTROL (AR9170_PHY_REG_BASE + 0x0070)
+#define AR9170_PHY_REG_SLEEP_CTR_LIMIT (AR9170_PHY_REG_BASE + 0x0074)
+#define AR9170_PHY_REG_SLEEP_SCAL (AR9170_PHY_REG_BASE + 0x0078)
+
+#define AR9170_PHY_REG_PLL_CTL (AR9170_PHY_REG_BASE + 0x007c)
+#define AR9170_PHY_PLL_CTL_40 0xaa
+#define AR9170_PHY_PLL_CTL_40_5413 0x04
+#define AR9170_PHY_PLL_CTL_44 0xab
+#define AR9170_PHY_PLL_CTL_44_2133 0xeb
+#define AR9170_PHY_PLL_CTL_40_2133 0xea
+
+#define AR9170_PHY_REG_BIN_MASK_1 (AR9170_PHY_REG_BASE + 0x0100)
+#define AR9170_PHY_REG_BIN_MASK_2 (AR9170_PHY_REG_BASE + 0x0104)
+#define AR9170_PHY_REG_BIN_MASK_3 (AR9170_PHY_REG_BASE + 0x0108)
+#define AR9170_PHY_REG_MASK_CTL (AR9170_PHY_REG_BASE + 0x010c)
+
+/* analogue power on time (100ns) */
+#define AR9170_PHY_REG_RX_DELAY (AR9170_PHY_REG_BASE + 0x0114)
+#define AR9170_PHY_REG_SEARCH_START_DELAY (AR9170_PHY_REG_BASE + 0x0118)
+#define AR9170_PHY_RX_DELAY_DELAY 0x00003fff
+
+#define AR9170_PHY_REG_TIMING_CTRL4(_i) (AR9170_PHY_REG_BASE + \
+ (0x0120 + ((_i) << 12)))
+#define AR9170_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF 0x01f
+#define AR9170_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF_S 0
+#define AR9170_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF 0x7e0
+#define AR9170_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF_S 5
+#define AR9170_PHY_TIMING_CTRL4_IQCORR_ENABLE 0x800
+#define AR9170_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX 0xf000
+#define AR9170_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX_S 12
+#define AR9170_PHY_TIMING_CTRL4_DO_IQCAL 0x10000
+#define AR9170_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI 0x80000000
+#define AR9170_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER 0x40000000
+#define AR9170_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK 0x20000000
+#define AR9170_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK 0x10000000
+
+#define AR9170_PHY_REG_TIMING5 (AR9170_PHY_REG_BASE + 0x0124)
+#define AR9170_PHY_TIMING5_CYCPWR_THR1 0x000000fe
+#define AR9170_PHY_TIMING5_CYCPWR_THR1_S 1
+
+#define AR9170_PHY_REG_POWER_TX_RATE1 (AR9170_PHY_REG_BASE + 0x0134)
+#define AR9170_PHY_REG_POWER_TX_RATE2 (AR9170_PHY_REG_BASE + 0x0138)
+#define AR9170_PHY_REG_POWER_TX_RATE_MAX (AR9170_PHY_REG_BASE + 0x013c)
+#define AR9170_PHY_POWER_TX_RATE_MAX_TPC_ENABLE 0x00000040
+
+#define AR9170_PHY_REG_FRAME_CTL (AR9170_PHY_REG_BASE + 0x0144)
+#define AR9170_PHY_FRAME_CTL_TX_CLIP 0x00000038
+#define AR9170_PHY_FRAME_CTL_TX_CLIP_S 3
+
+#define AR9170_PHY_REG_SPUR_REG (AR9170_PHY_REG_BASE + 0x014c)
+#define AR9170_PHY_SPUR_REG_MASK_RATE_CNTL (0xff << 18)
+#define AR9170_PHY_SPUR_REG_MASK_RATE_CNTL_S 18
+#define AR9170_PHY_SPUR_REG_ENABLE_MASK_PPM 0x20000
+#define AR9170_PHY_SPUR_REG_MASK_RATE_SELECT (0xff << 9)
+#define AR9170_PHY_SPUR_REG_MASK_RATE_SELECT_S 9
+#define AR9170_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI 0x100
+#define AR9170_PHY_SPUR_REG_SPUR_RSSI_THRESH 0x7f
+#define AR9170_PHY_SPUR_REG_SPUR_RSSI_THRESH_S 0
+
+#define AR9170_PHY_REG_RADAR_EXT (AR9170_PHY_REG_BASE + 0x0140)
+#define AR9170_PHY_RADAR_EXT_ENA 0x00004000
+
+#define AR9170_PHY_REG_RADAR_0 (AR9170_PHY_REG_BASE + 0x0154)
+#define AR9170_PHY_RADAR_0_ENA 0x00000001
+#define AR9170_PHY_RADAR_0_FFT_ENA 0x80000000
+/* inband pulse threshold */
+#define AR9170_PHY_RADAR_0_INBAND 0x0000003e
+#define AR9170_PHY_RADAR_0_INBAND_S 1
+/* pulse RSSI threshold */
+#define AR9170_PHY_RADAR_0_PRSSI 0x00000fc0
+#define AR9170_PHY_RADAR_0_PRSSI_S 6
+/* pulse height threshold */
+#define AR9170_PHY_RADAR_0_HEIGHT 0x0003f000
+#define AR9170_PHY_RADAR_0_HEIGHT_S 12
+/* radar RSSI threshold */
+#define AR9170_PHY_RADAR_0_RRSSI 0x00fc0000
+#define AR9170_PHY_RADAR_0_RRSSI_S 18
+/* radar firepower threshold */
+#define AR9170_PHY_RADAR_0_FIRPWR 0x7f000000
+#define AR9170_PHY_RADAR_0_FIRPWR_S 24
+
+#define AR9170_PHY_REG_RADAR_1 (AR9170_PHY_REG_BASE + 0x0158)
+#define AR9170_PHY_RADAR_1_RELPWR_ENA 0x00800000
+#define AR9170_PHY_RADAR_1_USE_FIR128 0x00400000
+#define AR9170_PHY_RADAR_1_RELPWR_THRESH 0x003f0000
+#define AR9170_PHY_RADAR_1_RELPWR_THRESH_S 16
+#define AR9170_PHY_RADAR_1_BLOCK_CHECK 0x00008000
+#define AR9170_PHY_RADAR_1_MAX_RRSSI 0x00004000
+#define AR9170_PHY_RADAR_1_RELSTEP_CHECK 0x00002000
+#define AR9170_PHY_RADAR_1_RELSTEP_THRESH 0x00001f00
+#define AR9170_PHY_RADAR_1_RELSTEP_THRESH_S 8
+#define AR9170_PHY_RADAR_1_MAXLEN 0x000000ff
+#define AR9170_PHY_RADAR_1_MAXLEN_S 0
+
+#define AR9170_PHY_REG_SWITCH_CHAIN_0 (AR9170_PHY_REG_BASE + 0x0160)
+#define AR9170_PHY_REG_SWITCH_CHAIN_2 (AR9170_PHY_REG_BASE + 0x2160)
+
+#define AR9170_PHY_REG_SWITCH_COM (AR9170_PHY_REG_BASE + 0x0164)
+
+#define AR9170_PHY_REG_CCA_THRESHOLD (AR9170_PHY_REG_BASE + 0x0168)
+
+#define AR9170_PHY_REG_SIGMA_DELTA (AR9170_PHY_REG_BASE + 0x016c)
+#define AR9170_PHY_SIGMA_DELTA_ADC_SEL 0x00000003
+#define AR9170_PHY_SIGMA_DELTA_ADC_SEL_S 0
+#define AR9170_PHY_SIGMA_DELTA_FILT2 0x000000f8
+#define AR9170_PHY_SIGMA_DELTA_FILT2_S 3
+#define AR9170_PHY_SIGMA_DELTA_FILT1 0x00001f00
+#define AR9170_PHY_SIGMA_DELTA_FILT1_S 8
+#define AR9170_PHY_SIGMA_DELTA_ADC_CLIP 0x01ffe000
+#define AR9170_PHY_SIGMA_DELTA_ADC_CLIP_S 13
+
+#define AR9170_PHY_REG_RESTART (AR9170_PHY_REG_BASE + 0x0170)
+#define AR9170_PHY_RESTART_DIV_GC 0x001c0000
+#define AR9170_PHY_RESTART_DIV_GC_S 18
+
+#define AR9170_PHY_REG_RFBUS_REQ (AR9170_PHY_REG_BASE + 0x017c)
+#define AR9170_PHY_RFBUS_REQ_EN 0x00000001
+
+#define AR9170_PHY_REG_TIMING7 (AR9170_PHY_REG_BASE + 0x0180)
+#define AR9170_PHY_REG_TIMING8 (AR9170_PHY_REG_BASE + 0x0184)
+#define AR9170_PHY_TIMING8_PILOT_MASK_2 0x000fffff
+#define AR9170_PHY_TIMING8_PILOT_MASK_2_S 0
+
+#define AR9170_PHY_REG_BIN_MASK2_1 (AR9170_PHY_REG_BASE + 0x0188)
+#define AR9170_PHY_REG_BIN_MASK2_2 (AR9170_PHY_REG_BASE + 0x018c)
+#define AR9170_PHY_REG_BIN_MASK2_3 (AR9170_PHY_REG_BASE + 0x0190)
+#define AR9170_PHY_REG_BIN_MASK2_4 (AR9170_PHY_REG_BASE + 0x0194)
+#define AR9170_PHY_BIN_MASK2_4_MASK_4 0x00003fff
+#define AR9170_PHY_BIN_MASK2_4_MASK_4_S 0
+
+#define AR9170_PHY_REG_TIMING9 (AR9170_PHY_REG_BASE + 0x0198)
+#define AR9170_PHY_REG_TIMING10 (AR9170_PHY_REG_BASE + 0x019c)
+#define AR9170_PHY_TIMING10_PILOT_MASK_2 0x000fffff
+#define AR9170_PHY_TIMING10_PILOT_MASK_2_S 0
+
+#define AR9170_PHY_REG_TIMING11 (AR9170_PHY_REG_BASE + 0x01a0)
+#define AR9170_PHY_TIMING11_SPUR_DELTA_PHASE 0x000fffff
+#define AR9170_PHY_TIMING11_SPUR_DELTA_PHASE_S 0
+#define AR9170_PHY_TIMING11_SPUR_FREQ_SD 0x3ff00000
+#define AR9170_PHY_TIMING11_SPUR_FREQ_SD_S 20
+#define AR9170_PHY_TIMING11_USE_SPUR_IN_AGC 0x40000000
+#define AR9170_PHY_TIMING11_USE_SPUR_IN_SELFCOR 0x80000000
+
+#define AR9170_PHY_REG_RX_CHAINMASK (AR9170_PHY_REG_BASE + 0x01a4)
+#define AR9170_PHY_REG_NEW_ADC_DC_GAIN_CORR(_i) (AR9170_PHY_REG_BASE + \
+ 0x01b4 + ((_i) << 12))
+#define AR9170_PHY_NEW_ADC_GAIN_CORR_ENABLE 0x40000000
+#define AR9170_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE 0x80000000
+
+#define AR9170_PHY_REG_MULTICHAIN_GAIN_CTL (AR9170_PHY_REG_BASE + 0x01ac)
+#define AR9170_PHY_9285_ANT_DIV_CTL_ALL 0x7f000000
+#define AR9170_PHY_9285_ANT_DIV_CTL 0x01000000
+#define AR9170_PHY_9285_ANT_DIV_CTL_S 24
+#define AR9170_PHY_9285_ANT_DIV_ALT_LNACONF 0x06000000
+#define AR9170_PHY_9285_ANT_DIV_ALT_LNACONF_S 25
+#define AR9170_PHY_9285_ANT_DIV_MAIN_LNACONF 0x18000000
+#define AR9170_PHY_9285_ANT_DIV_MAIN_LNACONF_S 27
+#define AR9170_PHY_9285_ANT_DIV_ALT_GAINTB 0x20000000
+#define AR9170_PHY_9285_ANT_DIV_ALT_GAINTB_S 29
+#define AR9170_PHY_9285_ANT_DIV_MAIN_GAINTB 0x40000000
+#define AR9170_PHY_9285_ANT_DIV_MAIN_GAINTB_S 30
+#define AR9170_PHY_9285_ANT_DIV_LNA1 2
+#define AR9170_PHY_9285_ANT_DIV_LNA2 1
+#define AR9170_PHY_9285_ANT_DIV_LNA1_PLUS_LNA2 3
+#define AR9170_PHY_9285_ANT_DIV_LNA1_MINUS_LNA2 0
+#define AR9170_PHY_9285_ANT_DIV_GAINTB_0 0
+#define AR9170_PHY_9285_ANT_DIV_GAINTB_1 1
+
+#define AR9170_PHY_REG_EXT_CCA0 (AR9170_PHY_REG_BASE + 0x01b8)
+#define AR9170_PHY_REG_EXT_CCA0_THRESH62 0x000000ff
+#define AR9170_PHY_REG_EXT_CCA0_THRESH62_S 0
+
+#define AR9170_PHY_REG_EXT_CCA (AR9170_PHY_REG_BASE + 0x01bc)
+#define AR9170_PHY_EXT_CCA_CYCPWR_THR1 0x0000fe00
+#define AR9170_PHY_EXT_CCA_CYCPWR_THR1_S 9
+#define AR9170_PHY_EXT_CCA_THRESH62 0x007f0000
+#define AR9170_PHY_EXT_CCA_THRESH62_S 16
+#define AR9170_PHY_EXT_MINCCA_PWR 0xff800000
+#define AR9170_PHY_EXT_MINCCA_PWR_S 23
+
+#define AR9170_PHY_REG_SFCORR_EXT (AR9170_PHY_REG_BASE + 0x01c0)
+#define AR9170_PHY_SFCORR_EXT_M1_THRESH 0x0000007f
+#define AR9170_PHY_SFCORR_EXT_M1_THRESH_S 0
+#define AR9170_PHY_SFCORR_EXT_M2_THRESH 0x00003f80
+#define AR9170_PHY_SFCORR_EXT_M2_THRESH_S 7
+#define AR9170_PHY_SFCORR_EXT_M1_THRESH_LOW 0x001fc000
+#define AR9170_PHY_SFCORR_EXT_M1_THRESH_LOW_S 14
+#define AR9170_PHY_SFCORR_EXT_M2_THRESH_LOW 0x0fe00000
+#define AR9170_PHY_SFCORR_EXT_M2_THRESH_LOW_S 21
+#define AR9170_PHY_SFCORR_SPUR_SUBCHNL_SD_S 28
+
+#define AR9170_PHY_REG_HALFGI (AR9170_PHY_REG_BASE + 0x01d0)
+#define AR9170_PHY_HALFGI_DSC_MAN 0x0007fff0
+#define AR9170_PHY_HALFGI_DSC_MAN_S 4
+#define AR9170_PHY_HALFGI_DSC_EXP 0x0000000f
+#define AR9170_PHY_HALFGI_DSC_EXP_S 0
+
+#define AR9170_PHY_REG_CHANNEL_MASK_01_30 (AR9170_PHY_REG_BASE + 0x01d4)
+#define AR9170_PHY_REG_CHANNEL_MASK_31_60 (AR9170_PHY_REG_BASE + 0x01d8)
+
+#define AR9170_PHY_REG_CHAN_INFO_MEMORY (AR9170_PHY_REG_BASE + 0x01dc)
+#define AR9170_PHY_CHAN_INFO_MEMORY_CAPTURE_MASK 0x0001
+
+#define AR9170_PHY_REG_HEAVY_CLIP_ENABLE (AR9170_PHY_REG_BASE + 0x01e0)
+#define AR9170_PHY_REG_HEAVY_CLIP_FACTOR_RIFS (AR9170_PHY_REG_BASE + 0x01ec)
+#define AR9170_PHY_RIFS_INIT_DELAY 0x03ff0000
+
+#define AR9170_PHY_REG_CALMODE (AR9170_PHY_REG_BASE + 0x01f0)
+#define AR9170_PHY_CALMODE_IQ 0x00000000
+#define AR9170_PHY_CALMODE_ADC_GAIN 0x00000001
+#define AR9170_PHY_CALMODE_ADC_DC_PER 0x00000002
+#define AR9170_PHY_CALMODE_ADC_DC_INIT 0x00000003
+
+#define AR9170_PHY_REG_REFCLKDLY (AR9170_PHY_REG_BASE + 0x01f4)
+#define AR9170_PHY_REG_REFCLKPD (AR9170_PHY_REG_BASE + 0x01f8)
+
+
+#define AR9170_PHY_REG_CAL_MEAS_0(_i) (AR9170_PHY_REG_BASE + \
+ 0x0410 + ((_i) << 12))
+#define AR9170_PHY_REG_CAL_MEAS_1(_i) (AR9170_PHY_REG_BASE + \
+ 0x0414 \ + ((_i) << 12))
+#define AR9170_PHY_REG_CAL_MEAS_2(_i) (AR9170_PHY_REG_BASE + \
+ 0x0418 + ((_i) << 12))
+#define AR9170_PHY_REG_CAL_MEAS_3(_i) (AR9170_PHY_REG_BASE + \
+ 0x041c + ((_i) << 12))
+
+#define AR9170_PHY_REG_CURRENT_RSSI (AR9170_PHY_REG_BASE + 0x041c)
+
+#define AR9170_PHY_REG_RFBUS_GRANT (AR9170_PHY_REG_BASE + 0x0420)
+#define AR9170_PHY_RFBUS_GRANT_EN 0x00000001
+
+#define AR9170_PHY_REG_CHAN_INFO_GAIN_DIFF (AR9170_PHY_REG_BASE + 0x04f4)
+#define AR9170_PHY_CHAN_INFO_GAIN_DIFF_UPPER_LIMIT 320
+
+#define AR9170_PHY_REG_CHAN_INFO_GAIN (AR9170_PHY_REG_BASE + 0x04fc)
+
+#define AR9170_PHY_REG_MODE (AR9170_PHY_REG_BASE + 0x0a00)
+#define AR9170_PHY_MODE_ASYNCFIFO 0x80
+#define AR9170_PHY_MODE_AR2133 0x08
+#define AR9170_PHY_MODE_AR5111 0x00
+#define AR9170_PHY_MODE_AR5112 0x08
+#define AR9170_PHY_MODE_DYNAMIC 0x04
+#define AR9170_PHY_MODE_RF2GHZ 0x02
+#define AR9170_PHY_MODE_RF5GHZ 0x00
+#define AR9170_PHY_MODE_CCK 0x01
+#define AR9170_PHY_MODE_OFDM 0x00
+#define AR9170_PHY_MODE_DYN_CCK_DISABLE 0x100
+
+#define AR9170_PHY_REG_CCK_TX_CTRL (AR9170_PHY_REG_BASE + 0x0a04)
+#define AR9170_PHY_CCK_TX_CTRL_JAPAN 0x00000010
+#define AR9170_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK 0x0000000c
+#define AR9170_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK_S 2
+
+#define AR9170_PHY_REG_CCK_DETECT (AR9170_PHY_REG_BASE + 0x0a08)
+#define AR9170_PHY_CCK_DETECT_WEAK_SIG_THR_CCK 0x0000003f
+#define AR9170_PHY_CCK_DETECT_WEAK_SIG_THR_CCK_S 0
+/* [12:6] settling time for antenna switch */
+#define AR9170_PHY_CCK_DETECT_ANT_SWITCH_TIME 0x00001fc0
+#define AR9170_PHY_CCK_DETECT_ANT_SWITCH_TIME_S 6
+#define AR9170_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV 0x2000
+#define AR9170_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV_S 13
+
+#define AR9170_PHY_REG_GAIN_2GHZ (AR9170_PHY_REG_BASE + 0x0a0c)
+#define AR9170_PHY_REG_GAIN_2GHZ_CHAIN_2 (AR9170_PHY_REG_BASE + 0x2a0c)
+#define AR9170_PHY_GAIN_2GHZ_RXTX_MARGIN 0x00fc0000
+#define AR9170_PHY_GAIN_2GHZ_RXTX_MARGIN_S 18
+#define AR9170_PHY_GAIN_2GHZ_BSW_MARGIN 0x00003c00
+#define AR9170_PHY_GAIN_2GHZ_BSW_MARGIN_S 10
+#define AR9170_PHY_GAIN_2GHZ_BSW_ATTEN 0x0000001f
+#define AR9170_PHY_GAIN_2GHZ_BSW_ATTEN_S 0
+#define AR9170_PHY_GAIN_2GHZ_XATTEN2_MARGIN 0x003e0000
+#define AR9170_PHY_GAIN_2GHZ_XATTEN2_MARGIN_S 17
+#define AR9170_PHY_GAIN_2GHZ_XATTEN1_MARGIN 0x0001f000
+#define AR9170_PHY_GAIN_2GHZ_XATTEN1_MARGIN_S 12
+#define AR9170_PHY_GAIN_2GHZ_XATTEN2_DB 0x00000fc0
+#define AR9170_PHY_GAIN_2GHZ_XATTEN2_DB_S 6
+#define AR9170_PHY_GAIN_2GHZ_XATTEN1_DB 0x0000003f
+#define AR9170_PHY_GAIN_2GHZ_XATTEN1_DB_S 0
+
+#define AR9170_PHY_REG_CCK_RXCTRL4 (AR9170_PHY_REG_BASE + 0x0a1c)
+#define AR9170_PHY_CCK_RXCTRL4_FREQ_EST_SHORT 0x01f80000
+#define AR9170_PHY_CCK_RXCTRL4_FREQ_EST_SHORT_S 19
+
+#define AR9170_PHY_REG_DAG_CTRLCCK (AR9170_PHY_REG_BASE + 0x0a28)
+#define AR9170_REG_DAG_CTRLCCK_EN_RSSI_THR 0x00000200
+#define AR9170_REG_DAG_CTRLCCK_RSSI_THR 0x0001fc00
+#define AR9170_REG_DAG_CTRLCCK_RSSI_THR_S 10
+
+#define AR9170_PHY_REG_FORCE_CLKEN_CCK (AR9170_PHY_REG_BASE + 0x0a2c)
+#define AR9170_FORCE_CLKEN_CCK_MRC_MUX 0x00000040
+
+#define AR9170_PHY_REG_POWER_TX_RATE3 (AR9170_PHY_REG_BASE + 0x0a34)
+#define AR9170_PHY_REG_POWER_TX_RATE4 (AR9170_PHY_REG_BASE + 0x0a38)
+
+#define AR9170_PHY_REG_SCRM_SEQ_XR (AR9170_PHY_REG_BASE + 0x0a3c)
+#define AR9170_PHY_REG_HEADER_DETECT_XR (AR9170_PHY_REG_BASE + 0x0a40)
+#define AR9170_PHY_REG_CHIRP_DETECTED_XR (AR9170_PHY_REG_BASE + 0x0a44)
+#define AR9170_PHY_REG_BLUETOOTH (AR9170_PHY_REG_BASE + 0x0a54)
+
+#define AR9170_PHY_REG_TPCRG1 (AR9170_PHY_REG_BASE + 0x0a58)
+#define AR9170_PHY_TPCRG1_NUM_PD_GAIN 0x0000c000
+#define AR9170_PHY_TPCRG1_NUM_PD_GAIN_S 14
+#define AR9170_PHY_TPCRG1_PD_GAIN_1 0x00030000
+#define AR9170_PHY_TPCRG1_PD_GAIN_1_S 16
+#define AR9170_PHY_TPCRG1_PD_GAIN_2 0x000c0000
+#define AR9170_PHY_TPCRG1_PD_GAIN_2_S 18
+#define AR9170_PHY_TPCRG1_PD_GAIN_3 0x00300000
+#define AR9170_PHY_TPCRG1_PD_GAIN_3_S 20
+#define AR9170_PHY_TPCRG1_PD_CAL_ENABLE 0x00400000
+#define AR9170_PHY_TPCRG1_PD_CAL_ENABLE_S 22
+
+#define AR9170_PHY_REG_TX_PWRCTRL4 (AR9170_PHY_REG_BASE + 0x0a64)
+#define AR9170_PHY_TX_PWRCTRL_PD_AVG_VALID 0x00000001
+#define AR9170_PHY_TX_PWRCTRL_PD_AVG_VALID_S 0
+#define AR9170_PHY_TX_PWRCTRL_PD_AVG_OUT 0x000001fe
+#define AR9170_PHY_TX_PWRCTRL_PD_AVG_OUT_S 1
+
+#define AR9170_PHY_REG_ANALOG_SWAP (AR9170_PHY_REG_BASE + 0x0a68)
+#define AR9170_PHY_ANALOG_SWAP_AB 0x0001
+#define AR9170_PHY_ANALOG_SWAP_ALT_CHAIN 0x00000040
+
+#define AR9170_PHY_REG_TPCRG5 (AR9170_PHY_REG_BASE + 0x0a6c)
+#define AR9170_PHY_TPCRG5_PD_GAIN_OVERLAP 0x0000000f
+#define AR9170_PHY_TPCRG5_PD_GAIN_OVERLAP_S 0
+#define AR9170_PHY_TPCRG5_PD_GAIN_BOUNDARY_1 0x000003f0
+#define AR9170_PHY_TPCRG5_PD_GAIN_BOUNDARY_1_S 4
+#define AR9170_PHY_TPCRG5_PD_GAIN_BOUNDARY_2 0x0000fc00
+#define AR9170_PHY_TPCRG5_PD_GAIN_BOUNDARY_2_S 10
+#define AR9170_PHY_TPCRG5_PD_GAIN_BOUNDARY_3 0x003f0000
+#define AR9170_PHY_TPCRG5_PD_GAIN_BOUNDARY_3_S 16
+#define AR9170_PHY_TPCRG5_PD_GAIN_BOUNDARY_4 0x0fc00000
+#define AR9170_PHY_TPCRG5_PD_GAIN_BOUNDARY_4_S 22
+
+#define AR9170_PHY_REG_TX_PWRCTRL6_0 (AR9170_PHY_REG_BASE + 0x0a70)
+#define AR9170_PHY_REG_TX_PWRCTRL6_1 (AR9170_PHY_REG_BASE + 0x1a70)
+#define AR9170_PHY_TX_PWRCTRL_ERR_EST_MODE 0x03000000
+#define AR9170_PHY_TX_PWRCTRL_ERR_EST_MODE_S 24
+
+#define AR9170_PHY_REG_TX_PWRCTRL7 (AR9170_PHY_REG_BASE + 0x0a74)
+#define AR9170_PHY_TX_PWRCTRL_INIT_TX_GAIN 0x01f80000
+#define AR9170_PHY_TX_PWRCTRL_INIT_TX_GAIN_S 19
+
+#define AR9170_PHY_REG_TX_PWRCTRL9 (AR9170_PHY_REG_BASE + 0x0a7c)
+#define AR9170_PHY_TX_DESIRED_SCALE_CCK 0x00007c00
+#define AR9170_PHY_TX_DESIRED_SCALE_CCK_S 10
+#define AR9170_PHY_TX_PWRCTRL9_RES_DC_REMOVAL 0x80000000
+#define AR9170_PHY_TX_PWRCTRL9_RES_DC_REMOVAL_S 31
+
+#define AR9170_PHY_REG_TX_GAIN_TBL1 (AR9170_PHY_REG_BASE + 0x0b00)
+#define AR9170_PHY_TX_GAIN 0x0007f000
+#define AR9170_PHY_TX_GAIN_S 12
+
+/* Carrier leak calibration control, do it after AGC calibration */
+#define AR9170_PHY_REG_CL_CAL_CTL (AR9170_PHY_REG_BASE + 0x0b58)
+#define AR9170_PHY_CL_CAL_ENABLE 0x00000002
+#define AR9170_PHY_CL_CAL_PARALLEL_CAL_ENABLE 0x00000001
+
+#define AR9170_PHY_REG_POWER_TX_RATE5 (AR9170_PHY_REG_BASE + 0x0b8c)
+#define AR9170_PHY_REG_POWER_TX_RATE6 (AR9170_PHY_REG_BASE + 0x0b90)
+
+#define AR9170_PHY_REG_CH0_TX_PWRCTRL11 (AR9170_PHY_REG_BASE + 0x0b98)
+#define AR9170_PHY_REG_CH1_TX_PWRCTRL11 (AR9170_PHY_REG_BASE + 0x1b98)
+#define AR9170_PHY_TX_CHX_PWRCTRL_OLPC_TEMP_COMP 0x0000fc00
+#define AR9170_PHY_TX_CHX_PWRCTRL_OLPC_TEMP_COMP_S 10
+
+#define AR9170_PHY_REG_CAL_CHAINMASK (AR9170_PHY_REG_BASE + 0x0b9c)
+#define AR9170_PHY_REG_VIT_MASK2_M_46_61 (AR9170_PHY_REG_BASE + 0x0ba0)
+#define AR9170_PHY_REG_MASK2_M_31_45 (AR9170_PHY_REG_BASE + 0x0ba4)
+#define AR9170_PHY_REG_MASK2_M_16_30 (AR9170_PHY_REG_BASE + 0x0ba8)
+#define AR9170_PHY_REG_MASK2_M_00_15 (AR9170_PHY_REG_BASE + 0x0bac)
+#define AR9170_PHY_REG_PILOT_MASK_01_30 (AR9170_PHY_REG_BASE + 0x0bb0)
+#define AR9170_PHY_REG_PILOT_MASK_31_60 (AR9170_PHY_REG_BASE + 0x0bb4)
+#define AR9170_PHY_REG_MASK2_P_15_01 (AR9170_PHY_REG_BASE + 0x0bb8)
+#define AR9170_PHY_REG_MASK2_P_30_16 (AR9170_PHY_REG_BASE + 0x0bbc)
+#define AR9170_PHY_REG_MASK2_P_45_31 (AR9170_PHY_REG_BASE + 0x0bc0)
+#define AR9170_PHY_REG_MASK2_P_61_45 (AR9170_PHY_REG_BASE + 0x0bc4)
+#define AR9170_PHY_REG_POWER_TX_SUB (AR9170_PHY_REG_BASE + 0x0bc8)
+#define AR9170_PHY_REG_POWER_TX_RATE7 (AR9170_PHY_REG_BASE + 0x0bcc)
+#define AR9170_PHY_REG_POWER_TX_RATE8 (AR9170_PHY_REG_BASE + 0x0bd0)
+#define AR9170_PHY_REG_POWER_TX_RATE9 (AR9170_PHY_REG_BASE + 0x0bd4)
+#define AR9170_PHY_REG_XPA_CFG (AR9170_PHY_REG_BASE + 0x0bd8)
+#define AR9170_PHY_FORCE_XPA_CFG 0x000000001
+#define AR9170_PHY_FORCE_XPA_CFG_S 0
+
+#define AR9170_PHY_REG_CH1_CCA (AR9170_PHY_REG_BASE + 0x1064)
+#define AR9170_PHY_CH1_MINCCA_PWR 0x0ff80000
+#define AR9170_PHY_CH1_MINCCA_PWR_S 19
+
+#define AR9170_PHY_REG_CH2_CCA (AR9170_PHY_REG_BASE + 0x2064)
+#define AR9170_PHY_CH2_MINCCA_PWR 0x0ff80000
+#define AR9170_PHY_CH2_MINCCA_PWR_S 19
+
+#define AR9170_PHY_REG_CH1_EXT_CCA (AR9170_PHY_REG_BASE + 0x11bc)
+#define AR9170_PHY_CH1_EXT_MINCCA_PWR 0xff800000
+#define AR9170_PHY_CH1_EXT_MINCCA_PWR_S 23
+
+#define AR9170_PHY_REG_CH2_EXT_CCA (AR9170_PHY_REG_BASE + 0x21bc)
+#define AR9170_PHY_CH2_EXT_MINCCA_PWR 0xff800000
+#define AR9170_PHY_CH2_EXT_MINCCA_PWR_S 23
+
+#endif /* __CARL9170_SHARED_PHY_H */
diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c
new file mode 100644
index 000000000000..939a0e96ed1f
--- /dev/null
+++ b/drivers/net/wireless/ath/carl9170/rx.c
@@ -0,0 +1,938 @@
+/*
+ * Atheros CARL9170 driver
+ *
+ * 802.11 & command trap routines
+ *
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ * Copyright (c) 2007-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/etherdevice.h>
+#include <linux/crc32.h>
+#include <net/mac80211.h>
+#include "carl9170.h"
+#include "hw.h"
+#include "cmd.h"
+
+static void carl9170_dbg_message(struct ar9170 *ar, const char *buf, u32 len)
+{
+ bool restart = false;
+ enum carl9170_restart_reasons reason = CARL9170_RR_NO_REASON;
+
+ if (len > 3) {
+ if (memcmp(buf, CARL9170_ERR_MAGIC, 3) == 0) {
+ ar->fw.err_counter++;
+ if (ar->fw.err_counter > 3) {
+ restart = true;
+ reason = CARL9170_RR_TOO_MANY_FIRMWARE_ERRORS;
+ }
+ }
+
+ if (memcmp(buf, CARL9170_BUG_MAGIC, 3) == 0) {
+ ar->fw.bug_counter++;
+ restart = true;
+ reason = CARL9170_RR_FATAL_FIRMWARE_ERROR;
+ }
+ }
+
+ wiphy_info(ar->hw->wiphy, "FW: %.*s\n", len, buf);
+
+ if (restart)
+ carl9170_restart(ar, reason);
+}
+
+static void carl9170_handle_ps(struct ar9170 *ar, struct carl9170_rsp *rsp)
+{
+ u32 ps;
+ bool new_ps;
+
+ ps = le32_to_cpu(rsp->psm.state);
+
+ new_ps = (ps & CARL9170_PSM_COUNTER) != CARL9170_PSM_WAKE;
+ if (ar->ps.state != new_ps) {
+ if (!new_ps) {
+ ar->ps.sleep_ms = jiffies_to_msecs(jiffies -
+ ar->ps.last_action);
+ }
+
+ ar->ps.last_action = jiffies;
+
+ ar->ps.state = new_ps;
+ }
+}
+
+static int carl9170_check_sequence(struct ar9170 *ar, unsigned int seq)
+{
+ if (ar->cmd_seq < -1)
+ return 0;
+
+ /*
+ * Initialize Counter
+ */
+ if (ar->cmd_seq < 0)
+ ar->cmd_seq = seq;
+
+ /*
+ * The sequence is strictly monotonic increasing and it never skips!
+ *
+ * Therefore we can safely assume that whenever we received an
+ * unexpected sequence we have lost some valuable data.
+ */
+ if (seq != ar->cmd_seq) {
+ int count;
+
+ count = (seq - ar->cmd_seq) % ar->fw.cmd_bufs;
+
+ wiphy_err(ar->hw->wiphy, "lost %d command responses/traps! "
+ "w:%d g:%d\n", count, ar->cmd_seq, seq);
+
+ carl9170_restart(ar, CARL9170_RR_LOST_RSP);
+ return -EIO;
+ }
+
+ ar->cmd_seq = (ar->cmd_seq + 1) % ar->fw.cmd_bufs;
+ return 0;
+}
+
+static void carl9170_cmd_callback(struct ar9170 *ar, u32 len, void *buffer)
+{
+ /*
+ * Some commands may have a variable response length
+ * and we cannot predict the correct length in advance.
+ * So we only check if we provided enough space for the data.
+ */
+ if (unlikely(ar->readlen != (len - 4))) {
+ dev_warn(&ar->udev->dev, "received invalid command response:"
+ "got %d, instead of %d\n", len - 4, ar->readlen);
+ print_hex_dump_bytes("carl9170 cmd:", DUMP_PREFIX_OFFSET,
+ ar->cmd_buf, (ar->cmd.hdr.len + 4) & 0x3f);
+ print_hex_dump_bytes("carl9170 rsp:", DUMP_PREFIX_OFFSET,
+ buffer, len);
+ /*
+ * Do not complete. The command times out,
+ * and we get a stack trace from there.
+ */
+ carl9170_restart(ar, CARL9170_RR_INVALID_RSP);
+ }
+
+ spin_lock(&ar->cmd_lock);
+ if (ar->readbuf) {
+ if (len >= 4)
+ memcpy(ar->readbuf, buffer + 4, len - 4);
+
+ ar->readbuf = NULL;
+ }
+ complete(&ar->cmd_wait);
+ spin_unlock(&ar->cmd_lock);
+}
+
+void carl9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len)
+{
+ struct carl9170_rsp *cmd = (void *) buf;
+ struct ieee80211_vif *vif;
+
+ if (carl9170_check_sequence(ar, cmd->hdr.seq))
+ return;
+
+ if ((cmd->hdr.cmd & CARL9170_RSP_FLAG) != CARL9170_RSP_FLAG) {
+ if (!(cmd->hdr.cmd & CARL9170_CMD_ASYNC_FLAG))
+ carl9170_cmd_callback(ar, len, buf);
+
+ return;
+ }
+
+ if (unlikely(cmd->hdr.len != (len - 4))) {
+ if (net_ratelimit()) {
+ wiphy_err(ar->hw->wiphy, "FW: received over-/under"
+ "sized event %x (%d, but should be %d).\n",
+ cmd->hdr.cmd, cmd->hdr.len, len - 4);
+
+ print_hex_dump_bytes("dump:", DUMP_PREFIX_NONE,
+ buf, len);
+ }
+
+ return;
+ }
+
+ /* hardware event handlers */
+ switch (cmd->hdr.cmd) {
+ case CARL9170_RSP_PRETBTT:
+ /* pre-TBTT event */
+ rcu_read_lock();
+ vif = carl9170_get_main_vif(ar);
+
+ if (!vif) {
+ rcu_read_unlock();
+ break;
+ }
+
+ switch (vif->type) {
+ case NL80211_IFTYPE_STATION:
+ carl9170_handle_ps(ar, cmd);
+ break;
+
+ case NL80211_IFTYPE_AP:
+ case NL80211_IFTYPE_ADHOC:
+ carl9170_update_beacon(ar, true);
+ break;
+
+ default:
+ break;
+ }
+ rcu_read_unlock();
+
+ break;
+
+
+ case CARL9170_RSP_TXCOMP:
+ /* TX status notification */
+ carl9170_tx_process_status(ar, cmd);
+ break;
+
+ case CARL9170_RSP_BEACON_CONFIG:
+ /*
+ * (IBSS) beacon send notification
+ * bytes: 04 c2 XX YY B4 B3 B2 B1
+ *
+ * XX always 80
+ * YY always 00
+ * B1-B4 "should" be the number of send out beacons.
+ */
+ break;
+
+ case CARL9170_RSP_ATIM:
+ /* End of Atim Window */
+ break;
+
+ case CARL9170_RSP_WATCHDOG:
+ /* Watchdog Interrupt */
+ carl9170_restart(ar, CARL9170_RR_WATCHDOG);
+ break;
+
+ case CARL9170_RSP_TEXT:
+ /* firmware debug */
+ carl9170_dbg_message(ar, (char *)buf + 4, len - 4);
+ break;
+
+ case CARL9170_RSP_HEXDUMP:
+ wiphy_dbg(ar->hw->wiphy, "FW: HD %d\n", len - 4);
+ print_hex_dump_bytes("FW:", DUMP_PREFIX_NONE,
+ (char *)buf + 4, len - 4);
+ break;
+
+ case CARL9170_RSP_RADAR:
+ if (!net_ratelimit())
+ break;
+
+ wiphy_info(ar->hw->wiphy, "FW: RADAR! Please report this "
+ "incident to linux-wireless@vger.kernel.org !\n");
+ break;
+
+ case CARL9170_RSP_GPIO:
+#ifdef CONFIG_CARL9170_WPC
+ if (ar->wps.pbc) {
+ bool state = !!(cmd->gpio.gpio & cpu_to_le32(
+ AR9170_GPIO_PORT_WPS_BUTTON_PRESSED));
+
+ if (state != ar->wps.pbc_state) {
+ ar->wps.pbc_state = state;
+ input_report_key(ar->wps.pbc, KEY_WPS_BUTTON,
+ state);
+ input_sync(ar->wps.pbc);
+ }
+ }
+#endif /* CONFIG_CARL9170_WPC */
+ break;
+
+ case CARL9170_RSP_BOOT:
+ complete(&ar->fw_boot_wait);
+ break;
+
+ default:
+ wiphy_err(ar->hw->wiphy, "FW: received unhandled event %x\n",
+ cmd->hdr.cmd);
+ print_hex_dump_bytes("dump:", DUMP_PREFIX_NONE, buf, len);
+ break;
+ }
+}
+
+static int carl9170_rx_mac_status(struct ar9170 *ar,
+ struct ar9170_rx_head *head, struct ar9170_rx_macstatus *mac,
+ struct ieee80211_rx_status *status)
+{
+ struct ieee80211_channel *chan;
+ u8 error, decrypt;
+
+ BUILD_BUG_ON(sizeof(struct ar9170_rx_head) != 12);
+ BUILD_BUG_ON(sizeof(struct ar9170_rx_macstatus) != 4);
+
+ error = mac->error;
+
+ if (error & AR9170_RX_ERROR_WRONG_RA) {
+ if (!ar->sniffer_enabled)
+ return -EINVAL;
+ }
+
+ if (error & AR9170_RX_ERROR_PLCP) {
+ if (!(ar->filter_state & FIF_PLCPFAIL))
+ return -EINVAL;
+
+ status->flag |= RX_FLAG_FAILED_PLCP_CRC;
+ }
+
+ if (error & AR9170_RX_ERROR_FCS) {
+ ar->tx_fcs_errors++;
+
+ if (!(ar->filter_state & FIF_FCSFAIL))
+ return -EINVAL;
+
+ status->flag |= RX_FLAG_FAILED_FCS_CRC;
+ }
+
+ decrypt = ar9170_get_decrypt_type(mac);
+ if (!(decrypt & AR9170_RX_ENC_SOFTWARE) &&
+ decrypt != AR9170_ENC_ALG_NONE) {
+ if ((decrypt == AR9170_ENC_ALG_TKIP) &&
+ (error & AR9170_RX_ERROR_MMIC))
+ status->flag |= RX_FLAG_MMIC_ERROR;
+
+ status->flag |= RX_FLAG_DECRYPTED;
+ }
+
+ if (error & AR9170_RX_ERROR_DECRYPT && !ar->sniffer_enabled)
+ return -ENODATA;
+
+ error &= ~(AR9170_RX_ERROR_MMIC |
+ AR9170_RX_ERROR_FCS |
+ AR9170_RX_ERROR_WRONG_RA |
+ AR9170_RX_ERROR_DECRYPT |
+ AR9170_RX_ERROR_PLCP);
+
+ /* drop any other error frames */
+ if (unlikely(error)) {
+ /* TODO: update netdevice's RX dropped/errors statistics */
+
+ if (net_ratelimit())
+ wiphy_dbg(ar->hw->wiphy, "received frame with "
+ "suspicious error code (%#x).\n", error);
+
+ return -EINVAL;
+ }
+
+ chan = ar->channel;
+ if (chan) {
+ status->band = chan->band;
+ status->freq = chan->center_freq;
+ }
+
+ switch (mac->status & AR9170_RX_STATUS_MODULATION) {
+ case AR9170_RX_STATUS_MODULATION_CCK:
+ if (mac->status & AR9170_RX_STATUS_SHORT_PREAMBLE)
+ status->flag |= RX_FLAG_SHORTPRE;
+ switch (head->plcp[0]) {
+ case AR9170_RX_PHY_RATE_CCK_1M:
+ status->rate_idx = 0;
+ break;
+ case AR9170_RX_PHY_RATE_CCK_2M:
+ status->rate_idx = 1;
+ break;
+ case AR9170_RX_PHY_RATE_CCK_5M:
+ status->rate_idx = 2;
+ break;
+ case AR9170_RX_PHY_RATE_CCK_11M:
+ status->rate_idx = 3;
+ break;
+ default:
+ if (net_ratelimit()) {
+ wiphy_err(ar->hw->wiphy, "invalid plcp cck "
+ "rate (%x).\n", head->plcp[0]);
+ }
+
+ return -EINVAL;
+ }
+ break;
+
+ case AR9170_RX_STATUS_MODULATION_DUPOFDM:
+ case AR9170_RX_STATUS_MODULATION_OFDM:
+ switch (head->plcp[0] & 0xf) {
+ case AR9170_TXRX_PHY_RATE_OFDM_6M:
+ status->rate_idx = 0;
+ break;
+ case AR9170_TXRX_PHY_RATE_OFDM_9M:
+ status->rate_idx = 1;
+ break;
+ case AR9170_TXRX_PHY_RATE_OFDM_12M:
+ status->rate_idx = 2;
+ break;
+ case AR9170_TXRX_PHY_RATE_OFDM_18M:
+ status->rate_idx = 3;
+ break;
+ case AR9170_TXRX_PHY_RATE_OFDM_24M:
+ status->rate_idx = 4;
+ break;
+ case AR9170_TXRX_PHY_RATE_OFDM_36M:
+ status->rate_idx = 5;
+ break;
+ case AR9170_TXRX_PHY_RATE_OFDM_48M:
+ status->rate_idx = 6;
+ break;
+ case AR9170_TXRX_PHY_RATE_OFDM_54M:
+ status->rate_idx = 7;
+ break;
+ default:
+ if (net_ratelimit()) {
+ wiphy_err(ar->hw->wiphy, "invalid plcp ofdm "
+ "rate (%x).\n", head->plcp[0]);
+ }
+
+ return -EINVAL;
+ }
+ if (status->band == IEEE80211_BAND_2GHZ)
+ status->rate_idx += 4;
+ break;
+
+ case AR9170_RX_STATUS_MODULATION_HT:
+ if (head->plcp[3] & 0x80)
+ status->flag |= RX_FLAG_40MHZ;
+ if (head->plcp[6] & 0x80)
+ status->flag |= RX_FLAG_SHORT_GI;
+
+ status->rate_idx = clamp(0, 75, head->plcp[3] & 0x7f);
+ status->flag |= RX_FLAG_HT;
+ break;
+
+ default:
+ BUG();
+ return -ENOSYS;
+ }
+
+ return 0;
+}
+
+static void carl9170_rx_phy_status(struct ar9170 *ar,
+ struct ar9170_rx_phystatus *phy, struct ieee80211_rx_status *status)
+{
+ int i;
+
+ BUILD_BUG_ON(sizeof(struct ar9170_rx_phystatus) != 20);
+
+ for (i = 0; i < 3; i++)
+ if (phy->rssi[i] != 0x80)
+ status->antenna |= BIT(i);
+
+ /* post-process RSSI */
+ for (i = 0; i < 7; i++)
+ if (phy->rssi[i] & 0x80)
+ phy->rssi[i] = ((phy->rssi[i] & 0x7f) + 1) & 0x7f;
+
+ /* TODO: we could do something with phy_errors */
+ status->signal = ar->noise[0] + phy->rssi_combined;
+}
+
+static struct sk_buff *carl9170_rx_copy_data(u8 *buf, int len)
+{
+ struct sk_buff *skb;
+ int reserved = 0;
+ struct ieee80211_hdr *hdr = (void *) buf;
+
+ if (ieee80211_is_data_qos(hdr->frame_control)) {
+ u8 *qc = ieee80211_get_qos_ctl(hdr);
+ reserved += NET_IP_ALIGN;
+
+ if (*qc & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT)
+ reserved += NET_IP_ALIGN;
+ }
+
+ if (ieee80211_has_a4(hdr->frame_control))
+ reserved += NET_IP_ALIGN;
+
+ reserved = 32 + (reserved & NET_IP_ALIGN);
+
+ skb = dev_alloc_skb(len + reserved);
+ if (likely(skb)) {
+ skb_reserve(skb, reserved);
+ memcpy(skb_put(skb, len), buf, len);
+ }
+
+ return skb;
+}
+
+static u8 *carl9170_find_ie(u8 *data, unsigned int len, u8 ie)
+{
+ struct ieee80211_mgmt *mgmt = (void *)data;
+ u8 *pos, *end;
+
+ pos = (u8 *)mgmt->u.beacon.variable;
+ end = data + len;
+ while (pos < end) {
+ if (pos + 2 + pos[1] > end)
+ return NULL;
+
+ if (pos[0] == ie)
+ return pos;
+
+ pos += 2 + pos[1];
+ }
+ return NULL;
+}
+
+/*
+ * NOTE:
+ *
+ * The firmware is in charge of waking up the device just before
+ * the AP is expected to transmit the next beacon.
+ *
+ * This leaves the driver with the important task of deciding when
+ * to set the PHY back to bed again.
+ */
+static void carl9170_ps_beacon(struct ar9170 *ar, void *data, unsigned int len)
+{
+ struct ieee80211_hdr *hdr = (void *) data;
+ struct ieee80211_tim_ie *tim_ie;
+ u8 *tim;
+ u8 tim_len;
+ bool cam;
+
+ if (likely(!(ar->hw->conf.flags & IEEE80211_CONF_PS)))
+ return;
+
+ /* check if this really is a beacon */
+ if (!ieee80211_is_beacon(hdr->frame_control))
+ return;
+
+ /* min. beacon length + FCS_LEN */
+ if (len <= 40 + FCS_LEN)
+ return;
+
+ /* and only beacons from the associated BSSID, please */
+ if (compare_ether_addr(hdr->addr3, ar->common.curbssid) ||
+ !ar->common.curaid)
+ return;
+
+ ar->ps.last_beacon = jiffies;
+
+ tim = carl9170_find_ie(data, len - FCS_LEN, WLAN_EID_TIM);
+ if (!tim)
+ return;
+
+ if (tim[1] < sizeof(*tim_ie))
+ return;
+
+ tim_len = tim[1];
+ tim_ie = (struct ieee80211_tim_ie *) &tim[2];
+
+ if (!WARN_ON_ONCE(!ar->hw->conf.ps_dtim_period))
+ ar->ps.dtim_counter = (tim_ie->dtim_count - 1) %
+ ar->hw->conf.ps_dtim_period;
+
+ /* Check whenever the PHY can be turned off again. */
+
+ /* 1. What about buffered unicast traffic for our AID? */
+ cam = ieee80211_check_tim(tim_ie, tim_len, ar->common.curaid);
+
+ /* 2. Maybe the AP wants to send multicast/broadcast data? */
+ cam = !!(tim_ie->bitmap_ctrl & 0x01);
+
+ if (!cam) {
+ /* back to low-power land. */
+ ar->ps.off_override &= ~PS_OFF_BCN;
+ carl9170_ps_check(ar);
+ } else {
+ /* force CAM */
+ ar->ps.off_override |= PS_OFF_BCN;
+ }
+}
+
+static bool carl9170_ampdu_check(struct ar9170 *ar, u8 *buf, u8 ms)
+{
+ __le16 fc;
+
+ if ((ms & AR9170_RX_STATUS_MPDU) == AR9170_RX_STATUS_MPDU_SINGLE) {
+ /*
+ * This frame is not part of an aMPDU.
+ * Therefore it is not subjected to any
+ * of the following content restrictions.
+ */
+ return true;
+ }
+
+ /*
+ * "802.11n - 7.4a.3 A-MPDU contents" describes in which contexts
+ * certain frame types can be part of an aMPDU.
+ *
+ * In order to keep the processing cost down, I opted for a
+ * stateless filter solely based on the frame control field.
+ */
+
+ fc = ((struct ieee80211_hdr *)buf)->frame_control;
+ if (ieee80211_is_data_qos(fc) && ieee80211_is_data_present(fc))
+ return true;
+
+ if (ieee80211_is_ack(fc) || ieee80211_is_back(fc) ||
+ ieee80211_is_back_req(fc))
+ return true;
+
+ if (ieee80211_is_action(fc))
+ return true;
+
+ return false;
+}
+
+/*
+ * If the frame alignment is right (or the kernel has
+ * CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS), and there
+ * is only a single MPDU in the USB frame, then we could
+ * submit to mac80211 the SKB directly. However, since
+ * there may be multiple packets in one SKB in stream
+ * mode, and we need to observe the proper ordering,
+ * this is non-trivial.
+ */
+
+static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len)
+{
+ struct ar9170_rx_head *head;
+ struct ar9170_rx_macstatus *mac;
+ struct ar9170_rx_phystatus *phy = NULL;
+ struct ieee80211_rx_status status;
+ struct sk_buff *skb;
+ int mpdu_len;
+ u8 mac_status;
+
+ if (!IS_STARTED(ar))
+ return;
+
+ if (unlikely(len < sizeof(*mac)))
+ goto drop;
+
+ mpdu_len = len - sizeof(*mac);
+
+ mac = (void *)(buf + mpdu_len);
+ mac_status = mac->status;
+ switch (mac_status & AR9170_RX_STATUS_MPDU) {
+ case AR9170_RX_STATUS_MPDU_FIRST:
+ /* Aggregated MPDUs start with an PLCP header */
+ if (likely(mpdu_len >= sizeof(struct ar9170_rx_head))) {
+ head = (void *) buf;
+
+ /*
+ * The PLCP header needs to be cached for the
+ * following MIDDLE + LAST A-MPDU packets.
+ *
+ * So, if you are wondering why all frames seem
+ * to share a common RX status information,
+ * then you have the answer right here...
+ */
+ memcpy(&ar->rx_plcp, (void *) buf,
+ sizeof(struct ar9170_rx_head));
+
+ mpdu_len -= sizeof(struct ar9170_rx_head);
+ buf += sizeof(struct ar9170_rx_head);
+
+ ar->rx_has_plcp = true;
+ } else {
+ if (net_ratelimit()) {
+ wiphy_err(ar->hw->wiphy, "plcp info "
+ "is clipped.\n");
+ }
+
+ goto drop;
+ }
+ break;
+
+ case AR9170_RX_STATUS_MPDU_LAST:
+ /*
+ * The last frame of an A-MPDU has an extra tail
+ * which does contain the phy status of the whole
+ * aggregate.
+ */
+
+ if (likely(mpdu_len >= sizeof(struct ar9170_rx_phystatus))) {
+ mpdu_len -= sizeof(struct ar9170_rx_phystatus);
+ phy = (void *)(buf + mpdu_len);
+ } else {
+ if (net_ratelimit()) {
+ wiphy_err(ar->hw->wiphy, "frame tail "
+ "is clipped.\n");
+ }
+
+ goto drop;
+ }
+
+ case AR9170_RX_STATUS_MPDU_MIDDLE:
+ /* These are just data + mac status */
+ if (unlikely(!ar->rx_has_plcp)) {
+ if (!net_ratelimit())
+ return;
+
+ wiphy_err(ar->hw->wiphy, "rx stream does not start "
+ "with a first_mpdu frame tag.\n");
+
+ goto drop;
+ }
+
+ head = &ar->rx_plcp;
+ break;
+
+ case AR9170_RX_STATUS_MPDU_SINGLE:
+ /* single mpdu has both: plcp (head) and phy status (tail) */
+ head = (void *) buf;
+
+ mpdu_len -= sizeof(struct ar9170_rx_head);
+ mpdu_len -= sizeof(struct ar9170_rx_phystatus);
+
+ buf += sizeof(struct ar9170_rx_head);
+ phy = (void *)(buf + mpdu_len);
+ break;
+
+ default:
+ BUG_ON(1);
+ break;
+ }
+
+ /* FC + DU + RA + FCS */
+ if (unlikely(mpdu_len < (2 + 2 + ETH_ALEN + FCS_LEN)))
+ goto drop;
+
+ memset(&status, 0, sizeof(status));
+ if (unlikely(carl9170_rx_mac_status(ar, head, mac, &status)))
+ goto drop;
+
+ if (!carl9170_ampdu_check(ar, buf, mac_status))
+ goto drop;
+
+ if (phy)
+ carl9170_rx_phy_status(ar, phy, &status);
+
+ carl9170_ps_beacon(ar, buf, mpdu_len);
+
+ skb = carl9170_rx_copy_data(buf, mpdu_len);
+ if (!skb)
+ goto drop;
+
+ memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
+ ieee80211_rx(ar->hw, skb);
+ return;
+
+drop:
+ ar->rx_dropped++;
+}
+
+static void carl9170_rx_untie_cmds(struct ar9170 *ar, const u8 *respbuf,
+ const unsigned int resplen)
+{
+ struct carl9170_rsp *cmd;
+ int i = 0;
+
+ while (i < resplen) {
+ cmd = (void *) &respbuf[i];
+
+ i += cmd->hdr.len + 4;
+ if (unlikely(i > resplen))
+ break;
+
+ carl9170_handle_command_response(ar, cmd, cmd->hdr.len + 4);
+ }
+
+ if (unlikely(i != resplen)) {
+ if (!net_ratelimit())
+ return;
+
+ wiphy_err(ar->hw->wiphy, "malformed firmware trap:\n");
+ print_hex_dump_bytes("rxcmd:", DUMP_PREFIX_OFFSET,
+ respbuf, resplen);
+ }
+}
+
+static void __carl9170_rx(struct ar9170 *ar, u8 *buf, unsigned int len)
+{
+ unsigned int i = 0;
+
+ /* weird thing, but this is the same in the original driver */
+ while (len > 2 && i < 12 && buf[0] == 0xff && buf[1] == 0xff) {
+ i += 2;
+ len -= 2;
+ buf += 2;
+ }
+
+ if (unlikely(len < 4))
+ return;
+
+ /* found the 6 * 0xffff marker? */
+ if (i == 12)
+ carl9170_rx_untie_cmds(ar, buf, len);
+ else
+ carl9170_handle_mpdu(ar, buf, len);
+}
+
+static void carl9170_rx_stream(struct ar9170 *ar, void *buf, unsigned int len)
+{
+ unsigned int tlen, wlen = 0, clen = 0;
+ struct ar9170_stream *rx_stream;
+ u8 *tbuf;
+
+ tbuf = buf;
+ tlen = len;
+
+ while (tlen >= 4) {
+ rx_stream = (void *) tbuf;
+ clen = le16_to_cpu(rx_stream->length);
+ wlen = ALIGN(clen, 4);
+
+ /* check if this is stream has a valid tag.*/
+ if (rx_stream->tag != cpu_to_le16(AR9170_RX_STREAM_TAG)) {
+ /*
+ * TODO: handle the highly unlikely event that the
+ * corrupted stream has the TAG at the right position.
+ */
+
+ /* check if the frame can be repaired. */
+ if (!ar->rx_failover_missing) {
+
+ /* this is not "short read". */
+ if (net_ratelimit()) {
+ wiphy_err(ar->hw->wiphy,
+ "missing tag!\n");
+ }
+
+ __carl9170_rx(ar, tbuf, tlen);
+ return;
+ }
+
+ if (ar->rx_failover_missing > tlen) {
+ if (net_ratelimit()) {
+ wiphy_err(ar->hw->wiphy,
+ "possible multi "
+ "stream corruption!\n");
+ goto err_telluser;
+ } else {
+ goto err_silent;
+ }
+ }
+
+ memcpy(skb_put(ar->rx_failover, tlen), tbuf, tlen);
+ ar->rx_failover_missing -= tlen;
+
+ if (ar->rx_failover_missing <= 0) {
+ /*
+ * nested carl9170_rx_stream call!
+ *
+ * termination is guranteed, even when the
+ * combined frame also have an element with
+ * a bad tag.
+ */
+
+ ar->rx_failover_missing = 0;
+ carl9170_rx_stream(ar, ar->rx_failover->data,
+ ar->rx_failover->len);
+
+ skb_reset_tail_pointer(ar->rx_failover);
+ skb_trim(ar->rx_failover, 0);
+ }
+
+ return;
+ }
+
+ /* check if stream is clipped */
+ if (wlen > tlen - 4) {
+ if (ar->rx_failover_missing) {
+ /* TODO: handle double stream corruption. */
+ if (net_ratelimit()) {
+ wiphy_err(ar->hw->wiphy, "double rx "
+ "stream corruption!\n");
+ goto err_telluser;
+ } else {
+ goto err_silent;
+ }
+ }
+
+ /*
+ * save incomplete data set.
+ * the firmware will resend the missing bits when
+ * the rx - descriptor comes round again.
+ */
+
+ memcpy(skb_put(ar->rx_failover, tlen), tbuf, tlen);
+ ar->rx_failover_missing = clen - tlen;
+ return;
+ }
+ __carl9170_rx(ar, rx_stream->payload, clen);
+
+ tbuf += wlen + 4;
+ tlen -= wlen + 4;
+ }
+
+ if (tlen) {
+ if (net_ratelimit()) {
+ wiphy_err(ar->hw->wiphy, "%d bytes of unprocessed "
+ "data left in rx stream!\n", tlen);
+ }
+
+ goto err_telluser;
+ }
+
+ return;
+
+err_telluser:
+ wiphy_err(ar->hw->wiphy, "damaged RX stream data [want:%d, "
+ "data:%d, rx:%d, pending:%d ]\n", clen, wlen, tlen,
+ ar->rx_failover_missing);
+
+ if (ar->rx_failover_missing)
+ print_hex_dump_bytes("rxbuf:", DUMP_PREFIX_OFFSET,
+ ar->rx_failover->data,
+ ar->rx_failover->len);
+
+ print_hex_dump_bytes("stream:", DUMP_PREFIX_OFFSET,
+ buf, len);
+
+ wiphy_err(ar->hw->wiphy, "please check your hardware and cables, if "
+ "you see this message frequently.\n");
+
+err_silent:
+ if (ar->rx_failover_missing) {
+ skb_reset_tail_pointer(ar->rx_failover);
+ skb_trim(ar->rx_failover, 0);
+ ar->rx_failover_missing = 0;
+ }
+}
+
+void carl9170_rx(struct ar9170 *ar, void *buf, unsigned int len)
+{
+ if (ar->fw.rx_stream)
+ carl9170_rx_stream(ar, buf, len);
+ else
+ __carl9170_rx(ar, buf, len);
+}
diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c
new file mode 100644
index 000000000000..b575c865142d
--- /dev/null
+++ b/drivers/net/wireless/ath/carl9170/tx.c
@@ -0,0 +1,1335 @@
+/*
+ * Atheros CARL9170 driver
+ *
+ * 802.11 xmit & status routines
+ *
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ * Copyright (c) 2007-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/etherdevice.h>
+#include <net/mac80211.h>
+#include "carl9170.h"
+#include "hw.h"
+#include "cmd.h"
+
+static inline unsigned int __carl9170_get_queue(struct ar9170 *ar,
+ unsigned int queue)
+{
+ if (unlikely(modparam_noht)) {
+ return queue;
+ } else {
+ /*
+ * This is just another workaround, until
+ * someone figures out how to get QoS and
+ * AMPDU to play nicely together.
+ */
+
+ return 2; /* AC_BE */
+ }
+}
+
+static inline unsigned int carl9170_get_queue(struct ar9170 *ar,
+ struct sk_buff *skb)
+{
+ return __carl9170_get_queue(ar, skb_get_queue_mapping(skb));
+}
+
+static bool is_mem_full(struct ar9170 *ar)
+{
+ return (DIV_ROUND_UP(IEEE80211_MAX_FRAME_LEN, ar->fw.mem_block_size) >
+ atomic_read(&ar->mem_free_blocks));
+}
+
+static void carl9170_tx_accounting(struct ar9170 *ar, struct sk_buff *skb)
+{
+ int queue, i;
+ bool mem_full;
+
+ atomic_inc(&ar->tx_total_queued);
+
+ queue = skb_get_queue_mapping(skb);
+ spin_lock_bh(&ar->tx_stats_lock);
+
+ /*
+ * The driver has to accept the frame, regardless if the queue is
+ * full to the brim, or not. We have to do the queuing internally,
+ * since mac80211 assumes that a driver which can operate with
+ * aggregated frames does not reject frames for this reason.
+ */
+ ar->tx_stats[queue].len++;
+ ar->tx_stats[queue].count++;
+
+ mem_full = is_mem_full(ar);
+ for (i = 0; i < ar->hw->queues; i++) {
+ if (mem_full || ar->tx_stats[i].len >= ar->tx_stats[i].limit) {
+ ieee80211_stop_queue(ar->hw, i);
+ ar->queue_stop_timeout[i] = jiffies;
+ }
+ }
+
+ spin_unlock_bh(&ar->tx_stats_lock);
+}
+
+static void carl9170_tx_accounting_free(struct ar9170 *ar, struct sk_buff *skb)
+{
+ struct ieee80211_tx_info *txinfo;
+ int queue;
+
+ txinfo = IEEE80211_SKB_CB(skb);
+ queue = skb_get_queue_mapping(skb);
+
+ spin_lock_bh(&ar->tx_stats_lock);
+
+ ar->tx_stats[queue].len--;
+
+ if (!is_mem_full(ar)) {
+ unsigned int i;
+ for (i = 0; i < ar->hw->queues; i++) {
+ if (ar->tx_stats[i].len >= CARL9170_NUM_TX_LIMIT_SOFT)
+ continue;
+
+ if (ieee80211_queue_stopped(ar->hw, i)) {
+ unsigned long tmp;
+
+ tmp = jiffies - ar->queue_stop_timeout[i];
+ if (tmp > ar->max_queue_stop_timeout[i])
+ ar->max_queue_stop_timeout[i] = tmp;
+ }
+
+ ieee80211_wake_queue(ar->hw, i);
+ }
+ }
+
+ spin_unlock_bh(&ar->tx_stats_lock);
+ if (atomic_dec_and_test(&ar->tx_total_queued))
+ complete(&ar->tx_flush);
+}
+
+static int carl9170_alloc_dev_space(struct ar9170 *ar, struct sk_buff *skb)
+{
+ struct _carl9170_tx_superframe *super = (void *) skb->data;
+ unsigned int chunks;
+ int cookie = -1;
+
+ atomic_inc(&ar->mem_allocs);
+
+ chunks = DIV_ROUND_UP(skb->len, ar->fw.mem_block_size);
+ if (unlikely(atomic_sub_return(chunks, &ar->mem_free_blocks) < 0)) {
+ atomic_add(chunks, &ar->mem_free_blocks);
+ return -ENOSPC;
+ }
+
+ spin_lock_bh(&ar->mem_lock);
+ cookie = bitmap_find_free_region(ar->mem_bitmap, ar->fw.mem_blocks, 0);
+ spin_unlock_bh(&ar->mem_lock);
+
+ if (unlikely(cookie < 0)) {
+ atomic_add(chunks, &ar->mem_free_blocks);
+ return -ENOSPC;
+ }
+
+ super = (void *) skb->data;
+
+ /*
+ * Cookie #0 serves two special purposes:
+ * 1. The firmware might use it generate BlockACK frames
+ * in responds of an incoming BlockAckReqs.
+ *
+ * 2. Prevent double-free bugs.
+ */
+ super->s.cookie = (u8) cookie + 1;
+ return 0;
+}
+
+static void carl9170_release_dev_space(struct ar9170 *ar, struct sk_buff *skb)
+{
+ struct _carl9170_tx_superframe *super = (void *) skb->data;
+ int cookie;
+
+ /* make a local copy of the cookie */
+ cookie = super->s.cookie;
+ /* invalidate cookie */
+ super->s.cookie = 0;
+
+ /*
+ * Do a out-of-bounds check on the cookie:
+ *
+ * * cookie "0" is reserved and won't be assigned to any
+ * out-going frame. Internally however, it is used to
+ * mark no longer/un-accounted frames and serves as a
+ * cheap way of preventing frames from being freed
+ * twice by _accident_. NB: There is a tiny race...
+ *
+ * * obviously, cookie number is limited by the amount
+ * of available memory blocks, so the number can
+ * never execeed the mem_blocks count.
+ */
+ if (unlikely(WARN_ON_ONCE(cookie == 0) ||
+ WARN_ON_ONCE(cookie > ar->fw.mem_blocks)))
+ return;
+
+ atomic_add(DIV_ROUND_UP(skb->len, ar->fw.mem_block_size),
+ &ar->mem_free_blocks);
+
+ spin_lock_bh(&ar->mem_lock);
+ bitmap_release_region(ar->mem_bitmap, cookie - 1, 0);
+ spin_unlock_bh(&ar->mem_lock);
+}
+
+/* Called from any context */
+static void carl9170_tx_release(struct kref *ref)
+{
+ struct ar9170 *ar;
+ struct carl9170_tx_info *arinfo;
+ struct ieee80211_tx_info *txinfo;
+ struct sk_buff *skb;
+
+ arinfo = container_of(ref, struct carl9170_tx_info, ref);
+ txinfo = container_of((void *) arinfo, struct ieee80211_tx_info,
+ rate_driver_data);
+ skb = container_of((void *) txinfo, struct sk_buff, cb);
+
+ ar = arinfo->ar;
+ if (WARN_ON_ONCE(!ar))
+ return;
+
+ BUILD_BUG_ON(
+ offsetof(struct ieee80211_tx_info, status.ampdu_ack_len) != 23);
+
+ memset(&txinfo->status.ampdu_ack_len, 0,
+ sizeof(struct ieee80211_tx_info) -
+ offsetof(struct ieee80211_tx_info, status.ampdu_ack_len));
+
+ if (atomic_read(&ar->tx_total_queued))
+ ar->tx_schedule = true;
+
+ if (txinfo->flags & IEEE80211_TX_CTL_AMPDU) {
+ if (!atomic_read(&ar->tx_ampdu_upload))
+ ar->tx_ampdu_schedule = true;
+
+ if (txinfo->flags & IEEE80211_TX_STAT_AMPDU) {
+ txinfo->status.ampdu_len = txinfo->pad[0];
+ txinfo->status.ampdu_ack_len = txinfo->pad[1];
+ txinfo->pad[0] = txinfo->pad[1] = 0;
+ } else if (txinfo->flags & IEEE80211_TX_STAT_ACK) {
+ /*
+ * drop redundant tx_status reports:
+ *
+ * 1. ampdu_ack_len of the final tx_status does
+ * include the feedback of this particular frame.
+ *
+ * 2. tx_status_irqsafe only queues up to 128
+ * tx feedback reports and discards the rest.
+ *
+ * 3. minstrel_ht is picky, it only accepts
+ * reports of frames with the TX_STATUS_AMPDU flag.
+ */
+
+ dev_kfree_skb_any(skb);
+ return;
+ } else {
+ /*
+ * Frame has failed, but we want to keep it in
+ * case it was lost due to a power-state
+ * transition.
+ */
+ }
+ }
+
+ skb_pull(skb, sizeof(struct _carl9170_tx_superframe));
+ ieee80211_tx_status_irqsafe(ar->hw, skb);
+}
+
+void carl9170_tx_get_skb(struct sk_buff *skb)
+{
+ struct carl9170_tx_info *arinfo = (void *)
+ (IEEE80211_SKB_CB(skb))->rate_driver_data;
+ kref_get(&arinfo->ref);
+}
+
+int carl9170_tx_put_skb(struct sk_buff *skb)
+{
+ struct carl9170_tx_info *arinfo = (void *)
+ (IEEE80211_SKB_CB(skb))->rate_driver_data;
+
+ return kref_put(&arinfo->ref, carl9170_tx_release);
+}
+
+/* Caller must hold the tid_info->lock & rcu_read_lock */
+static void carl9170_tx_shift_bm(struct ar9170 *ar,
+ struct carl9170_sta_tid *tid_info, u16 seq)
+{
+ u16 off;
+
+ off = SEQ_DIFF(seq, tid_info->bsn);
+
+ if (WARN_ON_ONCE(off >= CARL9170_BAW_BITS))
+ return;
+
+ /*
+ * Sanity check. For each MPDU we set the bit in bitmap and
+ * clear it once we received the tx_status.
+ * But if the bit is already cleared then we've been bitten
+ * by a bug.
+ */
+ WARN_ON_ONCE(!test_and_clear_bit(off, tid_info->bitmap));
+
+ off = SEQ_DIFF(tid_info->snx, tid_info->bsn);
+ if (WARN_ON_ONCE(off >= CARL9170_BAW_BITS))
+ return;
+
+ if (!bitmap_empty(tid_info->bitmap, off))
+ off = find_first_bit(tid_info->bitmap, off);
+
+ tid_info->bsn += off;
+ tid_info->bsn &= 0x0fff;
+
+ bitmap_shift_right(tid_info->bitmap, tid_info->bitmap,
+ off, CARL9170_BAW_BITS);
+}
+
+static void carl9170_tx_status_process_ampdu(struct ar9170 *ar,
+ struct sk_buff *skb, struct ieee80211_tx_info *txinfo)
+{
+ struct _carl9170_tx_superframe *super = (void *) skb->data;
+ struct ieee80211_hdr *hdr = (void *) super->frame_data;
+ struct ieee80211_tx_info *tx_info;
+ struct carl9170_tx_info *ar_info;
+ struct carl9170_sta_info *sta_info;
+ struct ieee80211_sta *sta;
+ struct carl9170_sta_tid *tid_info;
+ struct ieee80211_vif *vif;
+ unsigned int vif_id;
+ u8 tid;
+
+ if (!(txinfo->flags & IEEE80211_TX_CTL_AMPDU) ||
+ txinfo->flags & IEEE80211_TX_CTL_INJECTED)
+ return;
+
+ tx_info = IEEE80211_SKB_CB(skb);
+ ar_info = (void *) tx_info->rate_driver_data;
+
+ vif_id = (super->s.misc & CARL9170_TX_SUPER_MISC_VIF_ID) >>
+ CARL9170_TX_SUPER_MISC_VIF_ID_S;
+
+ if (WARN_ON_ONCE(vif_id >= AR9170_MAX_VIRTUAL_MAC))
+ return;
+
+ rcu_read_lock();
+ vif = rcu_dereference(ar->vif_priv[vif_id].vif);
+ if (unlikely(!vif))
+ goto out_rcu;
+
+ /*
+ * Normally we should use wrappers like ieee80211_get_DA to get
+ * the correct peer ieee80211_sta.
+ *
+ * But there is a problem with indirect traffic (broadcasts, or
+ * data which is designated for other stations) in station mode.
+ * The frame will be directed to the AP for distribution and not
+ * to the actual destination.
+ */
+ sta = ieee80211_find_sta(vif, hdr->addr1);
+ if (unlikely(!sta))
+ goto out_rcu;
+
+ tid = get_tid_h(hdr);
+
+ sta_info = (void *) sta->drv_priv;
+ tid_info = rcu_dereference(sta_info->agg[tid]);
+ if (!tid_info)
+ goto out_rcu;
+
+ spin_lock_bh(&tid_info->lock);
+ if (likely(tid_info->state >= CARL9170_TID_STATE_IDLE))
+ carl9170_tx_shift_bm(ar, tid_info, get_seq_h(hdr));
+
+ if (sta_info->stats[tid].clear) {
+ sta_info->stats[tid].clear = false;
+ sta_info->stats[tid].ampdu_len = 0;
+ sta_info->stats[tid].ampdu_ack_len = 0;
+ }
+
+ sta_info->stats[tid].ampdu_len++;
+ if (txinfo->status.rates[0].count == 1)
+ sta_info->stats[tid].ampdu_ack_len++;
+
+ if (super->f.mac_control & cpu_to_le16(AR9170_TX_MAC_IMM_BA)) {
+ txinfo->pad[0] = sta_info->stats[tid].ampdu_len;
+ txinfo->pad[1] = sta_info->stats[tid].ampdu_ack_len;
+ txinfo->flags |= IEEE80211_TX_STAT_AMPDU;
+ sta_info->stats[tid].clear = true;
+ }
+ spin_unlock_bh(&tid_info->lock);
+
+out_rcu:
+ rcu_read_unlock();
+}
+
+void carl9170_tx_status(struct ar9170 *ar, struct sk_buff *skb,
+ const bool success)
+{
+ struct ieee80211_tx_info *txinfo;
+
+ carl9170_tx_accounting_free(ar, skb);
+
+ txinfo = IEEE80211_SKB_CB(skb);
+
+ if (success)
+ txinfo->flags |= IEEE80211_TX_STAT_ACK;
+ else
+ ar->tx_ack_failures++;
+
+ if (txinfo->flags & IEEE80211_TX_CTL_AMPDU)
+ carl9170_tx_status_process_ampdu(ar, skb, txinfo);
+
+ carl9170_tx_put_skb(skb);
+}
+
+/* This function may be called form any context */
+void carl9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb)
+{
+ struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb);
+
+ atomic_dec(&ar->tx_total_pending);
+
+ if (txinfo->flags & IEEE80211_TX_CTL_AMPDU)
+ atomic_dec(&ar->tx_ampdu_upload);
+
+ if (carl9170_tx_put_skb(skb))
+ tasklet_hi_schedule(&ar->usb_tasklet);
+}
+
+static struct sk_buff *carl9170_get_queued_skb(struct ar9170 *ar, u8 cookie,
+ struct sk_buff_head *queue)
+{
+ struct sk_buff *skb;
+
+ spin_lock_bh(&queue->lock);
+ skb_queue_walk(queue, skb) {
+ struct _carl9170_tx_superframe *txc = (void *) skb->data;
+
+ if (txc->s.cookie != cookie)
+ continue;
+
+ __skb_unlink(skb, queue);
+ spin_unlock_bh(&queue->lock);
+
+ carl9170_release_dev_space(ar, skb);
+ return skb;
+ }
+ spin_unlock_bh(&queue->lock);
+
+ return NULL;
+}
+
+static void carl9170_tx_fill_rateinfo(struct ar9170 *ar, unsigned int rix,
+ unsigned int tries, struct ieee80211_tx_info *txinfo)
+{
+ unsigned int i;
+
+ for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
+ if (txinfo->status.rates[i].idx < 0)
+ break;
+
+ if (i == rix) {
+ txinfo->status.rates[i].count = tries;
+ i++;
+ break;
+ }
+ }
+
+ for (; i < IEEE80211_TX_MAX_RATES; i++) {
+ txinfo->status.rates[i].idx = -1;
+ txinfo->status.rates[i].count = 0;
+ }
+}
+
+static void carl9170_check_queue_stop_timeout(struct ar9170 *ar)
+{
+ int i;
+ struct sk_buff *skb;
+ struct ieee80211_tx_info *txinfo;
+ struct carl9170_tx_info *arinfo;
+ bool restart = false;
+
+ for (i = 0; i < ar->hw->queues; i++) {
+ spin_lock_bh(&ar->tx_status[i].lock);
+
+ skb = skb_peek(&ar->tx_status[i]);
+
+ if (!skb)
+ goto next;
+
+ txinfo = IEEE80211_SKB_CB(skb);
+ arinfo = (void *) txinfo->rate_driver_data;
+
+ if (time_is_before_jiffies(arinfo->timeout +
+ msecs_to_jiffies(CARL9170_QUEUE_STUCK_TIMEOUT)) == true)
+ restart = true;
+
+next:
+ spin_unlock_bh(&ar->tx_status[i].lock);
+ }
+
+ if (restart) {
+ /*
+ * At least one queue has been stuck for long enough.
+ * Give the device a kick and hope it gets back to
+ * work.
+ *
+ * possible reasons may include:
+ * - frames got lost/corrupted (bad connection to the device)
+ * - stalled rx processing/usb controller hiccups
+ * - firmware errors/bugs
+ * - every bug you can think of.
+ * - all bugs you can't...
+ * - ...
+ */
+ carl9170_restart(ar, CARL9170_RR_STUCK_TX);
+ }
+}
+
+void carl9170_tx_janitor(struct work_struct *work)
+{
+ struct ar9170 *ar = container_of(work, struct ar9170,
+ tx_janitor.work);
+ if (!IS_STARTED(ar))
+ return;
+
+ ar->tx_janitor_last_run = jiffies;
+
+ carl9170_check_queue_stop_timeout(ar);
+
+ if (!atomic_read(&ar->tx_total_queued))
+ return;
+
+ ieee80211_queue_delayed_work(ar->hw, &ar->tx_janitor,
+ msecs_to_jiffies(CARL9170_TX_TIMEOUT));
+}
+
+static void __carl9170_tx_process_status(struct ar9170 *ar,
+ const uint8_t cookie, const uint8_t info)
+{
+ struct sk_buff *skb;
+ struct ieee80211_tx_info *txinfo;
+ struct carl9170_tx_info *arinfo;
+ unsigned int r, t, q;
+ bool success = true;
+
+ q = ar9170_qmap[info & CARL9170_TX_STATUS_QUEUE];
+
+ skb = carl9170_get_queued_skb(ar, cookie, &ar->tx_status[q]);
+ if (!skb) {
+ /*
+ * We have lost the race to another thread.
+ */
+
+ return ;
+ }
+
+ txinfo = IEEE80211_SKB_CB(skb);
+ arinfo = (void *) txinfo->rate_driver_data;
+
+ if (!(info & CARL9170_TX_STATUS_SUCCESS))
+ success = false;
+
+ r = (info & CARL9170_TX_STATUS_RIX) >> CARL9170_TX_STATUS_RIX_S;
+ t = (info & CARL9170_TX_STATUS_TRIES) >> CARL9170_TX_STATUS_TRIES_S;
+
+ carl9170_tx_fill_rateinfo(ar, r, t, txinfo);
+ carl9170_tx_status(ar, skb, success);
+}
+
+void carl9170_tx_process_status(struct ar9170 *ar,
+ const struct carl9170_rsp *cmd)
+{
+ unsigned int i;
+
+ for (i = 0; i < cmd->hdr.ext; i++) {
+ if (WARN_ON(i > ((cmd->hdr.len / 2) + 1))) {
+ print_hex_dump_bytes("UU:", DUMP_PREFIX_NONE,
+ (void *) cmd, cmd->hdr.len + 4);
+ break;
+ }
+
+ __carl9170_tx_process_status(ar, cmd->_tx_status[i].cookie,
+ cmd->_tx_status[i].info);
+ }
+}
+
+static __le32 carl9170_tx_physet(struct ar9170 *ar,
+ struct ieee80211_tx_info *info, struct ieee80211_tx_rate *txrate)
+{
+ struct ieee80211_rate *rate = NULL;
+ u32 power, chains;
+ __le32 tmp;
+
+ tmp = cpu_to_le32(0);
+
+ if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+ tmp |= cpu_to_le32(AR9170_TX_PHY_BW_40MHZ <<
+ AR9170_TX_PHY_BW_S);
+ /* this works because 40 MHz is 2 and dup is 3 */
+ if (txrate->flags & IEEE80211_TX_RC_DUP_DATA)
+ tmp |= cpu_to_le32(AR9170_TX_PHY_BW_40MHZ_DUP <<
+ AR9170_TX_PHY_BW_S);
+
+ if (txrate->flags & IEEE80211_TX_RC_SHORT_GI)
+ tmp |= cpu_to_le32(AR9170_TX_PHY_SHORT_GI);
+
+ if (txrate->flags & IEEE80211_TX_RC_MCS) {
+ u32 r = txrate->idx;
+ u8 *txpower;
+
+ /* heavy clip control */
+ tmp |= cpu_to_le32((r & 0x7) <<
+ AR9170_TX_PHY_TX_HEAVY_CLIP_S);
+
+ if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) {
+ if (info->band == IEEE80211_BAND_5GHZ)
+ txpower = ar->power_5G_ht40;
+ else
+ txpower = ar->power_2G_ht40;
+ } else {
+ if (info->band == IEEE80211_BAND_5GHZ)
+ txpower = ar->power_5G_ht20;
+ else
+ txpower = ar->power_2G_ht20;
+ }
+
+ power = txpower[r & 7];
+
+ /* +1 dBm for HT40 */
+ if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+ power += 2;
+
+ r <<= AR9170_TX_PHY_MCS_S;
+ BUG_ON(r & ~AR9170_TX_PHY_MCS);
+
+ tmp |= cpu_to_le32(r & AR9170_TX_PHY_MCS);
+ tmp |= cpu_to_le32(AR9170_TX_PHY_MOD_HT);
+
+ /*
+ * green field preamble does not work.
+ *
+ * if (txrate->flags & IEEE80211_TX_RC_GREEN_FIELD)
+ * tmp |= cpu_to_le32(AR9170_TX_PHY_GREENFIELD);
+ */
+ } else {
+ u8 *txpower;
+ u32 mod;
+ u32 phyrate;
+ u8 idx = txrate->idx;
+
+ if (info->band != IEEE80211_BAND_2GHZ) {
+ idx += 4;
+ txpower = ar->power_5G_leg;
+ mod = AR9170_TX_PHY_MOD_OFDM;
+ } else {
+ if (idx < 4) {
+ txpower = ar->power_2G_cck;
+ mod = AR9170_TX_PHY_MOD_CCK;
+ } else {
+ mod = AR9170_TX_PHY_MOD_OFDM;
+ txpower = ar->power_2G_ofdm;
+ }
+ }
+
+ rate = &__carl9170_ratetable[idx];
+
+ phyrate = rate->hw_value & 0xF;
+ power = txpower[(rate->hw_value & 0x30) >> 4];
+ phyrate <<= AR9170_TX_PHY_MCS_S;
+
+ tmp |= cpu_to_le32(mod);
+ tmp |= cpu_to_le32(phyrate);
+
+ /*
+ * short preamble seems to be broken too.
+ *
+ * if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
+ * tmp |= cpu_to_le32(AR9170_TX_PHY_SHORT_PREAMBLE);
+ */
+ }
+ power <<= AR9170_TX_PHY_TX_PWR_S;
+ power &= AR9170_TX_PHY_TX_PWR;
+ tmp |= cpu_to_le32(power);
+
+ /* set TX chains */
+ if (ar->eeprom.tx_mask == 1) {
+ chains = AR9170_TX_PHY_TXCHAIN_1;
+ } else {
+ chains = AR9170_TX_PHY_TXCHAIN_2;
+
+ /* >= 36M legacy OFDM - use only one chain */
+ if (rate && rate->bitrate >= 360 &&
+ !(txrate->flags & IEEE80211_TX_RC_MCS))
+ chains = AR9170_TX_PHY_TXCHAIN_1;
+ }
+ tmp |= cpu_to_le32(chains << AR9170_TX_PHY_TXCHAIN_S);
+
+ return tmp;
+}
+
+static bool carl9170_tx_rts_check(struct ar9170 *ar,
+ struct ieee80211_tx_rate *rate,
+ bool ampdu, bool multi)
+{
+ switch (ar->erp_mode) {
+ case CARL9170_ERP_AUTO:
+ if (ampdu)
+ break;
+
+ case CARL9170_ERP_MAC80211:
+ if (!(rate->flags & IEEE80211_TX_RC_USE_RTS_CTS))
+ break;
+
+ case CARL9170_ERP_RTS:
+ if (likely(!multi))
+ return true;
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
+static bool carl9170_tx_cts_check(struct ar9170 *ar,
+ struct ieee80211_tx_rate *rate)
+{
+ switch (ar->erp_mode) {
+ case CARL9170_ERP_AUTO:
+ case CARL9170_ERP_MAC80211:
+ if (!(rate->flags & IEEE80211_TX_RC_USE_CTS_PROTECT))
+ break;
+
+ case CARL9170_ERP_CTS:
+ return true;
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
+static int carl9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb)
+{
+ struct ieee80211_hdr *hdr;
+ struct _carl9170_tx_superframe *txc;
+ struct carl9170_vif_info *cvif;
+ struct ieee80211_tx_info *info;
+ struct ieee80211_tx_rate *txrate;
+ struct ieee80211_sta *sta;
+ struct carl9170_tx_info *arinfo;
+ unsigned int hw_queue;
+ int i;
+ __le16 mac_tmp;
+ u16 len;
+ bool ampdu, no_ack;
+
+ BUILD_BUG_ON(sizeof(*arinfo) > sizeof(info->rate_driver_data));
+ BUILD_BUG_ON(sizeof(struct _carl9170_tx_superdesc) !=
+ CARL9170_TX_SUPERDESC_LEN);
+
+ BUILD_BUG_ON(sizeof(struct _ar9170_tx_hwdesc) !=
+ AR9170_TX_HWDESC_LEN);
+
+ BUILD_BUG_ON(IEEE80211_TX_MAX_RATES < CARL9170_TX_MAX_RATES);
+
+ BUILD_BUG_ON(AR9170_MAX_VIRTUAL_MAC >
+ ((CARL9170_TX_SUPER_MISC_VIF_ID >>
+ CARL9170_TX_SUPER_MISC_VIF_ID_S) + 1));
+
+ hw_queue = ar9170_qmap[carl9170_get_queue(ar, skb)];
+
+ hdr = (void *)skb->data;
+ info = IEEE80211_SKB_CB(skb);
+ len = skb->len;
+
+ /*
+ * Note: If the frame was sent through a monitor interface,
+ * the ieee80211_vif pointer can be NULL.
+ */
+ if (likely(info->control.vif))
+ cvif = (void *) info->control.vif->drv_priv;
+ else
+ cvif = NULL;
+
+ sta = info->control.sta;
+
+ txc = (void *)skb_push(skb, sizeof(*txc));
+ memset(txc, 0, sizeof(*txc));
+
+ SET_VAL(CARL9170_TX_SUPER_MISC_QUEUE, txc->s.misc, hw_queue);
+
+ if (likely(cvif))
+ SET_VAL(CARL9170_TX_SUPER_MISC_VIF_ID, txc->s.misc, cvif->id);
+
+ if (unlikely(info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM))
+ txc->s.misc |= CARL9170_TX_SUPER_MISC_CAB;
+
+ if (unlikely(ieee80211_is_probe_resp(hdr->frame_control)))
+ txc->s.misc |= CARL9170_TX_SUPER_MISC_FILL_IN_TSF;
+
+ mac_tmp = cpu_to_le16(AR9170_TX_MAC_HW_DURATION |
+ AR9170_TX_MAC_BACKOFF);
+ mac_tmp |= cpu_to_le16((hw_queue << AR9170_TX_MAC_QOS_S) &&
+ AR9170_TX_MAC_QOS);
+
+ no_ack = !!(info->flags & IEEE80211_TX_CTL_NO_ACK);
+ if (unlikely(no_ack))
+ mac_tmp |= cpu_to_le16(AR9170_TX_MAC_NO_ACK);
+
+ if (info->control.hw_key) {
+ len += info->control.hw_key->icv_len;
+
+ switch (info->control.hw_key->cipher) {
+ case WLAN_CIPHER_SUITE_WEP40:
+ case WLAN_CIPHER_SUITE_WEP104:
+ case WLAN_CIPHER_SUITE_TKIP:
+ mac_tmp |= cpu_to_le16(AR9170_TX_MAC_ENCR_RC4);
+ break;
+ case WLAN_CIPHER_SUITE_CCMP:
+ mac_tmp |= cpu_to_le16(AR9170_TX_MAC_ENCR_AES);
+ break;
+ default:
+ WARN_ON(1);
+ goto err_out;
+ }
+ }
+
+ ampdu = !!(info->flags & IEEE80211_TX_CTL_AMPDU);
+ if (ampdu) {
+ unsigned int density, factor;
+
+ if (unlikely(!sta || !cvif))
+ goto err_out;
+
+ factor = min_t(unsigned int, 1u,
+ info->control.sta->ht_cap.ampdu_factor);
+
+ density = info->control.sta->ht_cap.ampdu_density;
+
+ if (density) {
+ /*
+ * Watch out!
+ *
+ * Otus uses slightly different density values than
+ * those from the 802.11n spec.
+ */
+
+ density = max_t(unsigned int, density + 1, 7u);
+ }
+
+ SET_VAL(CARL9170_TX_SUPER_AMPDU_DENSITY,
+ txc->s.ampdu_settings, density);
+
+ SET_VAL(CARL9170_TX_SUPER_AMPDU_FACTOR,
+ txc->s.ampdu_settings, factor);
+
+ for (i = 0; i < CARL9170_TX_MAX_RATES; i++) {
+ txrate = &info->control.rates[i];
+ if (txrate->idx >= 0) {
+ txc->s.ri[i] =
+ CARL9170_TX_SUPER_RI_AMPDU;
+
+ if (WARN_ON(!(txrate->flags &
+ IEEE80211_TX_RC_MCS))) {
+ /*
+ * Not sure if it's even possible
+ * to aggregate non-ht rates with
+ * this HW.
+ */
+ goto err_out;
+ }
+ continue;
+ }
+
+ txrate->idx = 0;
+ txrate->count = ar->hw->max_rate_tries;
+ }
+
+ mac_tmp |= cpu_to_le16(AR9170_TX_MAC_AGGR);
+ }
+
+ /*
+ * NOTE: For the first rate, the ERP & AMPDU flags are directly
+ * taken from mac_control. For all fallback rate, the firmware
+ * updates the mac_control flags from the rate info field.
+ */
+ for (i = 1; i < CARL9170_TX_MAX_RATES; i++) {
+ txrate = &info->control.rates[i];
+ if (txrate->idx < 0)
+ break;
+
+ SET_VAL(CARL9170_TX_SUPER_RI_TRIES, txc->s.ri[i],
+ txrate->count);
+
+ if (carl9170_tx_rts_check(ar, txrate, ampdu, no_ack))
+ txc->s.ri[i] |= (AR9170_TX_MAC_PROT_RTS <<
+ CARL9170_TX_SUPER_RI_ERP_PROT_S);
+ else if (carl9170_tx_cts_check(ar, txrate))
+ txc->s.ri[i] |= (AR9170_TX_MAC_PROT_CTS <<
+ CARL9170_TX_SUPER_RI_ERP_PROT_S);
+
+ txc->s.rr[i - 1] = carl9170_tx_physet(ar, info, txrate);
+ }
+
+ txrate = &info->control.rates[0];
+ SET_VAL(CARL9170_TX_SUPER_RI_TRIES, txc->s.ri[0], txrate->count);
+
+ if (carl9170_tx_rts_check(ar, txrate, ampdu, no_ack))
+ mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_RTS);
+ else if (carl9170_tx_cts_check(ar, txrate))
+ mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_CTS);
+
+ txc->s.len = cpu_to_le16(skb->len);
+ txc->f.length = cpu_to_le16(len + FCS_LEN);
+ txc->f.mac_control = mac_tmp;
+ txc->f.phy_control = carl9170_tx_physet(ar, info, txrate);
+
+ arinfo = (void *)info->rate_driver_data;
+ arinfo->timeout = jiffies;
+ arinfo->ar = ar;
+ kref_init(&arinfo->ref);
+ return 0;
+
+err_out:
+ skb_pull(skb, sizeof(*txc));
+ return -EINVAL;
+}
+
+static void carl9170_set_immba(struct ar9170 *ar, struct sk_buff *skb)
+{
+ struct _carl9170_tx_superframe *super;
+
+ super = (void *) skb->data;
+ super->f.mac_control |= cpu_to_le16(AR9170_TX_MAC_IMM_BA);
+}
+
+static void carl9170_set_ampdu_params(struct ar9170 *ar, struct sk_buff *skb)
+{
+ struct _carl9170_tx_superframe *super;
+ int tmp;
+
+ super = (void *) skb->data;
+
+ tmp = (super->s.ampdu_settings & CARL9170_TX_SUPER_AMPDU_DENSITY) <<
+ CARL9170_TX_SUPER_AMPDU_DENSITY_S;
+
+ /*
+ * If you haven't noticed carl9170_tx_prepare has already filled
+ * in all ampdu spacing & factor parameters.
+ * Now it's the time to check whenever the settings have to be
+ * updated by the firmware, or if everything is still the same.
+ *
+ * There's no sane way to handle different density values with
+ * this hardware, so we may as well just do the compare in the
+ * driver.
+ */
+
+ if (tmp != ar->current_density) {
+ ar->current_density = tmp;
+ super->s.ampdu_settings |=
+ CARL9170_TX_SUPER_AMPDU_COMMIT_DENSITY;
+ }
+
+ tmp = (super->s.ampdu_settings & CARL9170_TX_SUPER_AMPDU_FACTOR) <<
+ CARL9170_TX_SUPER_AMPDU_FACTOR_S;
+
+ if (tmp != ar->current_factor) {
+ ar->current_factor = tmp;
+ super->s.ampdu_settings |=
+ CARL9170_TX_SUPER_AMPDU_COMMIT_FACTOR;
+ }
+}
+
+static bool carl9170_tx_rate_check(struct ar9170 *ar, struct sk_buff *_dest,
+ struct sk_buff *_src)
+{
+ struct _carl9170_tx_superframe *dest, *src;
+
+ dest = (void *) _dest->data;
+ src = (void *) _src->data;
+
+ /*
+ * The mac80211 rate control algorithm expects that all MPDUs in
+ * an AMPDU share the same tx vectors.
+ * This is not really obvious right now, because the hardware
+ * does the AMPDU setup according to its own rulebook.
+ * Our nicely assembled, strictly monotonic increasing mpdu
+ * chains will be broken up, mashed back together...
+ */
+
+ return (dest->f.phy_control == src->f.phy_control);
+}
+
+static void carl9170_tx_ampdu(struct ar9170 *ar)
+{
+ struct sk_buff_head agg;
+ struct carl9170_sta_tid *tid_info;
+ struct sk_buff *skb, *first;
+ unsigned int i = 0, done_ampdus = 0;
+ u16 seq, queue, tmpssn;
+
+ atomic_inc(&ar->tx_ampdu_scheduler);
+ ar->tx_ampdu_schedule = false;
+
+ if (atomic_read(&ar->tx_ampdu_upload))
+ return;
+
+ if (!ar->tx_ampdu_list_len)
+ return;
+
+ __skb_queue_head_init(&agg);
+
+ rcu_read_lock();
+ tid_info = rcu_dereference(ar->tx_ampdu_iter);
+ if (WARN_ON_ONCE(!tid_info)) {
+ rcu_read_unlock();
+ return;
+ }
+
+retry:
+ list_for_each_entry_continue_rcu(tid_info, &ar->tx_ampdu_list, list) {
+ i++;
+
+ if (tid_info->state < CARL9170_TID_STATE_PROGRESS)
+ continue;
+
+ queue = TID_TO_WME_AC(tid_info->tid);
+
+ spin_lock_bh(&tid_info->lock);
+ if (tid_info->state != CARL9170_TID_STATE_XMIT)
+ goto processed;
+
+ tid_info->counter++;
+ first = skb_peek(&tid_info->queue);
+ tmpssn = carl9170_get_seq(first);
+ seq = tid_info->snx;
+
+ if (unlikely(tmpssn != seq)) {
+ tid_info->state = CARL9170_TID_STATE_IDLE;
+
+ goto processed;
+ }
+
+ while ((skb = skb_peek(&tid_info->queue))) {
+ /* strict 0, 1, ..., n - 1, n frame sequence order */
+ if (unlikely(carl9170_get_seq(skb) != seq))
+ break;
+
+ /* don't upload more than AMPDU FACTOR allows. */
+ if (unlikely(SEQ_DIFF(tid_info->snx, tid_info->bsn) >=
+ (tid_info->max - 1)))
+ break;
+
+ if (!carl9170_tx_rate_check(ar, skb, first))
+ break;
+
+ atomic_inc(&ar->tx_ampdu_upload);
+ tid_info->snx = seq = SEQ_NEXT(seq);
+ __skb_unlink(skb, &tid_info->queue);
+
+ __skb_queue_tail(&agg, skb);
+
+ if (skb_queue_len(&agg) >= CARL9170_NUM_TX_AGG_MAX)
+ break;
+ }
+
+ if (skb_queue_empty(&tid_info->queue) ||
+ carl9170_get_seq(skb_peek(&tid_info->queue)) !=
+ tid_info->snx) {
+ /*
+ * stop TID, if A-MPDU frames are still missing,
+ * or whenever the queue is empty.
+ */
+
+ tid_info->state = CARL9170_TID_STATE_IDLE;
+ }
+ done_ampdus++;
+
+processed:
+ spin_unlock_bh(&tid_info->lock);
+
+ if (skb_queue_empty(&agg))
+ continue;
+
+ /* apply ampdu spacing & factor settings */
+ carl9170_set_ampdu_params(ar, skb_peek(&agg));
+
+ /* set aggregation push bit */
+ carl9170_set_immba(ar, skb_peek_tail(&agg));
+
+ spin_lock_bh(&ar->tx_pending[queue].lock);
+ skb_queue_splice_tail_init(&agg, &ar->tx_pending[queue]);
+ spin_unlock_bh(&ar->tx_pending[queue].lock);
+ ar->tx_schedule = true;
+ }
+ if ((done_ampdus++ == 0) && (i++ == 0))
+ goto retry;
+
+ rcu_assign_pointer(ar->tx_ampdu_iter, tid_info);
+ rcu_read_unlock();
+}
+
+static struct sk_buff *carl9170_tx_pick_skb(struct ar9170 *ar,
+ struct sk_buff_head *queue)
+{
+ struct sk_buff *skb;
+ struct ieee80211_tx_info *info;
+ struct carl9170_tx_info *arinfo;
+
+ BUILD_BUG_ON(sizeof(*arinfo) > sizeof(info->rate_driver_data));
+
+ spin_lock_bh(&queue->lock);
+ skb = skb_peek(queue);
+ if (unlikely(!skb))
+ goto err_unlock;
+
+ if (carl9170_alloc_dev_space(ar, skb))
+ goto err_unlock;
+
+ __skb_unlink(skb, queue);
+ spin_unlock_bh(&queue->lock);
+
+ info = IEEE80211_SKB_CB(skb);
+ arinfo = (void *) info->rate_driver_data;
+
+ arinfo->timeout = jiffies;
+
+ /*
+ * increase ref count to "2".
+ * Ref counting is the easiest way to solve the race between
+ * the the urb's completion routine: carl9170_tx_callback and
+ * wlan tx status functions: carl9170_tx_status/janitor.
+ */
+ carl9170_tx_get_skb(skb);
+
+ return skb;
+
+err_unlock:
+ spin_unlock_bh(&queue->lock);
+ return NULL;
+}
+
+void carl9170_tx_drop(struct ar9170 *ar, struct sk_buff *skb)
+{
+ struct _carl9170_tx_superframe *super;
+ uint8_t q = 0;
+
+ ar->tx_dropped++;
+
+ super = (void *)skb->data;
+ SET_VAL(CARL9170_TX_SUPER_MISC_QUEUE, q,
+ ar9170_qmap[carl9170_get_queue(ar, skb)]);
+ __carl9170_tx_process_status(ar, super->s.cookie, q);
+}
+
+static void carl9170_tx(struct ar9170 *ar)
+{
+ struct sk_buff *skb;
+ unsigned int i, q;
+ bool schedule_garbagecollector = false;
+
+ ar->tx_schedule = false;
+
+ if (unlikely(!IS_STARTED(ar)))
+ return;
+
+ carl9170_usb_handle_tx_err(ar);
+
+ for (i = 0; i < ar->hw->queues; i++) {
+ while (!skb_queue_empty(&ar->tx_pending[i])) {
+ skb = carl9170_tx_pick_skb(ar, &ar->tx_pending[i]);
+ if (unlikely(!skb))
+ break;
+
+ atomic_inc(&ar->tx_total_pending);
+
+ q = __carl9170_get_queue(ar, i);
+ /*
+ * NB: tx_status[i] vs. tx_status[q],
+ * TODO: Move into pick_skb or alloc_dev_space.
+ */
+ skb_queue_tail(&ar->tx_status[q], skb);
+
+ carl9170_usb_tx(ar, skb);
+ schedule_garbagecollector = true;
+ }
+ }
+
+ if (!schedule_garbagecollector)
+ return;
+
+ ieee80211_queue_delayed_work(ar->hw, &ar->tx_janitor,
+ msecs_to_jiffies(CARL9170_TX_TIMEOUT));
+}
+
+static bool carl9170_tx_ampdu_queue(struct ar9170 *ar,
+ struct ieee80211_sta *sta, struct sk_buff *skb)
+{
+ struct carl9170_sta_info *sta_info;
+ struct carl9170_sta_tid *agg;
+ struct sk_buff *iter;
+ unsigned int max;
+ u16 tid, seq, qseq, off;
+ bool run = false;
+
+ tid = carl9170_get_tid(skb);
+ seq = carl9170_get_seq(skb);
+ sta_info = (void *) sta->drv_priv;
+
+ rcu_read_lock();
+ agg = rcu_dereference(sta_info->agg[tid]);
+ max = sta_info->ampdu_max_len;
+
+ if (!agg)
+ goto err_unlock_rcu;
+
+ spin_lock_bh(&agg->lock);
+ if (unlikely(agg->state < CARL9170_TID_STATE_IDLE))
+ goto err_unlock;
+
+ /* check if sequence is within the BA window */
+ if (unlikely(!BAW_WITHIN(agg->bsn, CARL9170_BAW_BITS, seq)))
+ goto err_unlock;
+
+ if (WARN_ON_ONCE(!BAW_WITHIN(agg->snx, CARL9170_BAW_BITS, seq)))
+ goto err_unlock;
+
+ off = SEQ_DIFF(seq, agg->bsn);
+ if (WARN_ON_ONCE(test_and_set_bit(off, agg->bitmap)))
+ goto err_unlock;
+
+ if (likely(BAW_WITHIN(agg->hsn, CARL9170_BAW_BITS, seq))) {
+ __skb_queue_tail(&agg->queue, skb);
+ agg->hsn = seq;
+ goto queued;
+ }
+
+ skb_queue_reverse_walk(&agg->queue, iter) {
+ qseq = carl9170_get_seq(iter);
+
+ if (BAW_WITHIN(qseq, CARL9170_BAW_BITS, seq)) {
+ __skb_queue_after(&agg->queue, iter, skb);
+ goto queued;
+ }
+ }
+
+ __skb_queue_head(&agg->queue, skb);
+queued:
+
+ if (unlikely(agg->state != CARL9170_TID_STATE_XMIT)) {
+ if (agg->snx == carl9170_get_seq(skb_peek(&agg->queue))) {
+ agg->state = CARL9170_TID_STATE_XMIT;
+ run = true;
+ }
+ }
+
+ spin_unlock_bh(&agg->lock);
+ rcu_read_unlock();
+
+ return run;
+
+err_unlock:
+ spin_unlock_bh(&agg->lock);
+
+err_unlock_rcu:
+ rcu_read_unlock();
+ carl9170_tx_status(ar, skb, false);
+ ar->tx_dropped++;
+ return false;
+}
+
+int carl9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+ struct ar9170 *ar = hw->priv;
+ struct ieee80211_tx_info *info;
+ struct ieee80211_sta *sta;
+ bool run;
+
+ if (unlikely(!IS_STARTED(ar)))
+ goto err_free;
+
+ info = IEEE80211_SKB_CB(skb);
+ sta = info->control.sta;
+
+ if (unlikely(carl9170_tx_prepare(ar, skb)))
+ goto err_free;
+
+ carl9170_tx_accounting(ar, skb);
+ /*
+ * from now on, one has to use carl9170_tx_status to free
+ * all ressouces which are associated with the frame.
+ */
+
+ if (info->flags & IEEE80211_TX_CTL_AMPDU) {
+ if (WARN_ON_ONCE(!sta))
+ goto err_free;
+
+ run = carl9170_tx_ampdu_queue(ar, sta, skb);
+ if (run)
+ carl9170_tx_ampdu(ar);
+
+ } else {
+ unsigned int queue = skb_get_queue_mapping(skb);
+
+ skb_queue_tail(&ar->tx_pending[queue], skb);
+ }
+
+ carl9170_tx(ar);
+ return NETDEV_TX_OK;
+
+err_free:
+ ar->tx_dropped++;
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+}
+
+void carl9170_tx_scheduler(struct ar9170 *ar)
+{
+
+ if (ar->tx_ampdu_schedule)
+ carl9170_tx_ampdu(ar);
+
+ if (ar->tx_schedule)
+ carl9170_tx(ar);
+}
diff --git a/drivers/net/wireless/ath/carl9170/usb.c b/drivers/net/wireless/ath/carl9170/usb.c
new file mode 100644
index 000000000000..c7f6193934ea
--- /dev/null
+++ b/drivers/net/wireless/ath/carl9170/usb.c
@@ -0,0 +1,1136 @@
+/*
+ * Atheros CARL9170 driver
+ *
+ * USB - frontend
+ *
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ * Copyright (c) 2007-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/firmware.h>
+#include <linux/etherdevice.h>
+#include <linux/device.h>
+#include <net/mac80211.h>
+#include "carl9170.h"
+#include "cmd.h"
+#include "hw.h"
+#include "fwcmd.h"
+
+MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
+MODULE_AUTHOR("Christian Lamparter <chunkeey@googlemail.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Atheros AR9170 802.11n USB wireless");
+MODULE_FIRMWARE(CARL9170FW_NAME);
+MODULE_ALIAS("ar9170usb");
+MODULE_ALIAS("arusb_lnx");
+
+/*
+ * Note:
+ *
+ * Always update our wiki's device list (located at:
+ * http://wireless.kernel.org/en/users/Drivers/ar9170/devices ),
+ * whenever you add a new device.
+ */
+static struct usb_device_id carl9170_usb_ids[] = {
+ /* Atheros 9170 */
+ { USB_DEVICE(0x0cf3, 0x9170) },
+ /* Atheros TG121N */
+ { USB_DEVICE(0x0cf3, 0x1001) },
+ /* TP-Link TL-WN821N v2 */
+ { USB_DEVICE(0x0cf3, 0x1002), .driver_info = CARL9170_WPS_BUTTON |
+ CARL9170_ONE_LED },
+ /* 3Com Dual Band 802.11n USB Adapter */
+ { USB_DEVICE(0x0cf3, 0x1010) },
+ /* H3C Dual Band 802.11n USB Adapter */
+ { USB_DEVICE(0x0cf3, 0x1011) },
+ /* Cace Airpcap NX */
+ { USB_DEVICE(0xcace, 0x0300) },
+ /* D-Link DWA 160 A1 */
+ { USB_DEVICE(0x07d1, 0x3c10) },
+ /* D-Link DWA 160 A2 */
+ { USB_DEVICE(0x07d1, 0x3a09) },
+ /* Netgear WNA1000 */
+ { USB_DEVICE(0x0846, 0x9040) },
+ /* Netgear WNDA3100 */
+ { USB_DEVICE(0x0846, 0x9010) },
+ /* Netgear WN111 v2 */
+ { USB_DEVICE(0x0846, 0x9001), .driver_info = CARL9170_ONE_LED },
+ /* Zydas ZD1221 */
+ { USB_DEVICE(0x0ace, 0x1221) },
+ /* Proxim ORiNOCO 802.11n USB */
+ { USB_DEVICE(0x1435, 0x0804) },
+ /* WNC Generic 11n USB Dongle */
+ { USB_DEVICE(0x1435, 0x0326) },
+ /* ZyXEL NWD271N */
+ { USB_DEVICE(0x0586, 0x3417) },
+ /* Z-Com UB81 BG */
+ { USB_DEVICE(0x0cde, 0x0023) },
+ /* Z-Com UB82 ABG */
+ { USB_DEVICE(0x0cde, 0x0026) },
+ /* Sphairon Homelink 1202 */
+ { USB_DEVICE(0x0cde, 0x0027) },
+ /* Arcadyan WN7512 */
+ { USB_DEVICE(0x083a, 0xf522) },
+ /* Planex GWUS300 */
+ { USB_DEVICE(0x2019, 0x5304) },
+ /* IO-Data WNGDNUS2 */
+ { USB_DEVICE(0x04bb, 0x093f) },
+ /* NEC WL300NU-G */
+ { USB_DEVICE(0x0409, 0x0249) },
+ /* AVM FRITZ!WLAN USB Stick N */
+ { USB_DEVICE(0x057c, 0x8401) },
+ /* AVM FRITZ!WLAN USB Stick N 2.4 */
+ { USB_DEVICE(0x057c, 0x8402) },
+ /* Qwest/Actiontec 802AIN Wireless N USB Network Adapter */
+ { USB_DEVICE(0x1668, 0x1200) },
+
+ /* terminate */
+ {}
+};
+MODULE_DEVICE_TABLE(usb, carl9170_usb_ids);
+
+static void carl9170_usb_submit_data_urb(struct ar9170 *ar)
+{
+ struct urb *urb;
+ int err;
+
+ if (atomic_inc_return(&ar->tx_anch_urbs) > AR9170_NUM_TX_URBS)
+ goto err_acc;
+
+ urb = usb_get_from_anchor(&ar->tx_wait);
+ if (!urb)
+ goto err_acc;
+
+ usb_anchor_urb(urb, &ar->tx_anch);
+
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (unlikely(err)) {
+ if (net_ratelimit()) {
+ dev_err(&ar->udev->dev, "tx submit failed (%d)\n",
+ urb->status);
+ }
+
+ usb_unanchor_urb(urb);
+ usb_anchor_urb(urb, &ar->tx_err);
+ }
+
+ usb_free_urb(urb);
+
+ if (likely(err == 0))
+ return;
+
+err_acc:
+ atomic_dec(&ar->tx_anch_urbs);
+}
+
+static void carl9170_usb_tx_data_complete(struct urb *urb)
+{
+ struct ar9170 *ar = (struct ar9170 *)
+ usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
+
+ if (WARN_ON_ONCE(!ar)) {
+ dev_kfree_skb_irq(urb->context);
+ return;
+ }
+
+ atomic_dec(&ar->tx_anch_urbs);
+
+ switch (urb->status) {
+ /* everything is fine */
+ case 0:
+ carl9170_tx_callback(ar, (void *)urb->context);
+ break;
+
+ /* disconnect */
+ case -ENOENT:
+ case -ECONNRESET:
+ case -ENODEV:
+ case -ESHUTDOWN:
+ /*
+ * Defer the frame clean-up to the tasklet worker.
+ * This is necessary, because carl9170_tx_drop
+ * does not work in an irqsave context.
+ */
+ usb_anchor_urb(urb, &ar->tx_err);
+ return;
+
+ /* a random transmission error has occurred? */
+ default:
+ if (net_ratelimit()) {
+ dev_err(&ar->udev->dev, "tx failed (%d)\n",
+ urb->status);
+ }
+
+ usb_anchor_urb(urb, &ar->tx_err);
+ break;
+ }
+
+ if (likely(IS_STARTED(ar)))
+ carl9170_usb_submit_data_urb(ar);
+}
+
+static int carl9170_usb_submit_cmd_urb(struct ar9170 *ar)
+{
+ struct urb *urb;
+ int err;
+
+ if (atomic_inc_return(&ar->tx_cmd_urbs) != 1) {
+ atomic_dec(&ar->tx_cmd_urbs);
+ return 0;
+ }
+
+ urb = usb_get_from_anchor(&ar->tx_cmd);
+ if (!urb) {
+ atomic_dec(&ar->tx_cmd_urbs);
+ return 0;
+ }
+
+ usb_anchor_urb(urb, &ar->tx_anch);
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (unlikely(err)) {
+ usb_unanchor_urb(urb);
+ atomic_dec(&ar->tx_cmd_urbs);
+ }
+ usb_free_urb(urb);
+
+ return err;
+}
+
+static void carl9170_usb_cmd_complete(struct urb *urb)
+{
+ struct ar9170 *ar = urb->context;
+ int err = 0;
+
+ if (WARN_ON_ONCE(!ar))
+ return;
+
+ atomic_dec(&ar->tx_cmd_urbs);
+
+ switch (urb->status) {
+ /* everything is fine */
+ case 0:
+ break;
+
+ /* disconnect */
+ case -ENOENT:
+ case -ECONNRESET:
+ case -ENODEV:
+ case -ESHUTDOWN:
+ return;
+
+ default:
+ err = urb->status;
+ break;
+ }
+
+ if (!IS_INITIALIZED(ar))
+ return;
+
+ if (err)
+ dev_err(&ar->udev->dev, "submit cmd cb failed (%d).\n", err);
+
+ err = carl9170_usb_submit_cmd_urb(ar);
+ if (err)
+ dev_err(&ar->udev->dev, "submit cmd failed (%d).\n", err);
+}
+
+static void carl9170_usb_rx_irq_complete(struct urb *urb)
+{
+ struct ar9170 *ar = urb->context;
+
+ if (WARN_ON_ONCE(!ar))
+ return;
+
+ switch (urb->status) {
+ /* everything is fine */
+ case 0:
+ break;
+
+ /* disconnect */
+ case -ENOENT:
+ case -ECONNRESET:
+ case -ENODEV:
+ case -ESHUTDOWN:
+ return;
+
+ default:
+ goto resubmit;
+ }
+
+ carl9170_handle_command_response(ar, urb->transfer_buffer,
+ urb->actual_length);
+
+resubmit:
+ usb_anchor_urb(urb, &ar->rx_anch);
+ if (unlikely(usb_submit_urb(urb, GFP_ATOMIC)))
+ usb_unanchor_urb(urb);
+}
+
+static int carl9170_usb_submit_rx_urb(struct ar9170 *ar, gfp_t gfp)
+{
+ struct urb *urb;
+ int err = 0, runs = 0;
+
+ while ((atomic_read(&ar->rx_anch_urbs) < AR9170_NUM_RX_URBS) &&
+ (runs++ < AR9170_NUM_RX_URBS)) {
+ err = -ENOSPC;
+ urb = usb_get_from_anchor(&ar->rx_pool);
+ if (urb) {
+ usb_anchor_urb(urb, &ar->rx_anch);
+ err = usb_submit_urb(urb, gfp);
+ if (unlikely(err)) {
+ usb_unanchor_urb(urb);
+ usb_anchor_urb(urb, &ar->rx_pool);
+ } else {
+ atomic_dec(&ar->rx_pool_urbs);
+ atomic_inc(&ar->rx_anch_urbs);
+ }
+ usb_free_urb(urb);
+ }
+ }
+
+ return err;
+}
+
+static void carl9170_usb_rx_work(struct ar9170 *ar)
+{
+ struct urb *urb;
+ int i;
+
+ for (i = 0; i < AR9170_NUM_RX_URBS_POOL; i++) {
+ urb = usb_get_from_anchor(&ar->rx_work);
+ if (!urb)
+ break;
+
+ atomic_dec(&ar->rx_work_urbs);
+ if (IS_INITIALIZED(ar)) {
+ carl9170_rx(ar, urb->transfer_buffer,
+ urb->actual_length);
+ }
+
+ usb_anchor_urb(urb, &ar->rx_pool);
+ atomic_inc(&ar->rx_pool_urbs);
+
+ usb_free_urb(urb);
+
+ carl9170_usb_submit_rx_urb(ar, GFP_ATOMIC);
+ }
+}
+
+void carl9170_usb_handle_tx_err(struct ar9170 *ar)
+{
+ struct urb *urb;
+
+ while ((urb = usb_get_from_anchor(&ar->tx_err))) {
+ struct sk_buff *skb = (void *)urb->context;
+
+ carl9170_tx_drop(ar, skb);
+ carl9170_tx_callback(ar, skb);
+ usb_free_urb(urb);
+ }
+}
+
+static void carl9170_usb_tasklet(unsigned long data)
+{
+ struct ar9170 *ar = (struct ar9170 *) data;
+
+ if (!IS_INITIALIZED(ar))
+ return;
+
+ carl9170_usb_rx_work(ar);
+
+ /*
+ * Strictly speaking: The tx scheduler is not part of the USB system.
+ * But the rx worker returns frames back to the mac80211-stack and
+ * this is the _perfect_ place to generate the next transmissions.
+ */
+ if (IS_STARTED(ar))
+ carl9170_tx_scheduler(ar);
+}
+
+static void carl9170_usb_rx_complete(struct urb *urb)
+{
+ struct ar9170 *ar = (struct ar9170 *)urb->context;
+ int err;
+
+ if (WARN_ON_ONCE(!ar))
+ return;
+
+ atomic_dec(&ar->rx_anch_urbs);
+
+ switch (urb->status) {
+ case 0:
+ /* rx path */
+ usb_anchor_urb(urb, &ar->rx_work);
+ atomic_inc(&ar->rx_work_urbs);
+ break;
+
+ case -ENOENT:
+ case -ECONNRESET:
+ case -ENODEV:
+ case -ESHUTDOWN:
+ /* handle disconnect events*/
+ return;
+
+ default:
+ /* handle all other errors */
+ usb_anchor_urb(urb, &ar->rx_pool);
+ atomic_inc(&ar->rx_pool_urbs);
+ break;
+ }
+
+ err = carl9170_usb_submit_rx_urb(ar, GFP_ATOMIC);
+ if (unlikely(err)) {
+ /*
+ * usb_submit_rx_urb reported a problem.
+ * In case this is due to a rx buffer shortage,
+ * elevate the tasklet worker priority to
+ * the highest available level.
+ */
+ tasklet_hi_schedule(&ar->usb_tasklet);
+
+ if (atomic_read(&ar->rx_anch_urbs) == 0) {
+ /*
+ * The system is too slow to cope with
+ * the enormous workload. We have simply
+ * run out of active rx urbs and this
+ * unfortunatly leads to an unpredictable
+ * device.
+ */
+
+ carl9170_restart(ar, CARL9170_RR_SLOW_SYSTEM);
+ }
+ } else {
+ /*
+ * Using anything less than _high_ priority absolutely
+ * kills the rx performance my UP-System...
+ */
+ tasklet_hi_schedule(&ar->usb_tasklet);
+ }
+}
+
+static struct urb *carl9170_usb_alloc_rx_urb(struct ar9170 *ar, gfp_t gfp)
+{
+ struct urb *urb;
+ void *buf;
+
+ buf = kmalloc(ar->fw.rx_size, gfp);
+ if (!buf)
+ return NULL;
+
+ urb = usb_alloc_urb(0, gfp);
+ if (!urb) {
+ kfree(buf);
+ return NULL;
+ }
+
+ usb_fill_bulk_urb(urb, ar->udev, usb_rcvbulkpipe(ar->udev,
+ AR9170_USB_EP_RX), buf, ar->fw.rx_size,
+ carl9170_usb_rx_complete, ar);
+
+ urb->transfer_flags |= URB_FREE_BUFFER;
+
+ return urb;
+}
+
+static int carl9170_usb_send_rx_irq_urb(struct ar9170 *ar)
+{
+ struct urb *urb = NULL;
+ void *ibuf;
+ int err = -ENOMEM;
+
+ urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!urb)
+ goto out;
+
+ ibuf = kmalloc(AR9170_USB_EP_CTRL_MAX, GFP_KERNEL);
+ if (!ibuf)
+ goto out;
+
+ usb_fill_int_urb(urb, ar->udev, usb_rcvintpipe(ar->udev,
+ AR9170_USB_EP_IRQ), ibuf, AR9170_USB_EP_CTRL_MAX,
+ carl9170_usb_rx_irq_complete, ar, 1);
+
+ urb->transfer_flags |= URB_FREE_BUFFER;
+
+ usb_anchor_urb(urb, &ar->rx_anch);
+ err = usb_submit_urb(urb, GFP_KERNEL);
+ if (err)
+ usb_unanchor_urb(urb);
+
+out:
+ usb_free_urb(urb);
+ return err;
+}
+
+static int carl9170_usb_init_rx_bulk_urbs(struct ar9170 *ar)
+{
+ struct urb *urb;
+ int i, err = -EINVAL;
+
+ /*
+ * The driver actively maintains a second shadow
+ * pool for inactive, but fully-prepared rx urbs.
+ *
+ * The pool should help the driver to master huge
+ * workload spikes without running the risk of
+ * undersupplying the hardware or wasting time by
+ * processing rx data (streams) inside the urb
+ * completion (hardirq context).
+ */
+ for (i = 0; i < AR9170_NUM_RX_URBS_POOL; i++) {
+ urb = carl9170_usb_alloc_rx_urb(ar, GFP_KERNEL);
+ if (!urb) {
+ err = -ENOMEM;
+ goto err_out;
+ }
+
+ usb_anchor_urb(urb, &ar->rx_pool);
+ atomic_inc(&ar->rx_pool_urbs);
+ usb_free_urb(urb);
+ }
+
+ err = carl9170_usb_submit_rx_urb(ar, GFP_KERNEL);
+ if (err)
+ goto err_out;
+
+ /* the device now waiting for the firmware. */
+ carl9170_set_state_when(ar, CARL9170_STOPPED, CARL9170_IDLE);
+ return 0;
+
+err_out:
+
+ usb_scuttle_anchored_urbs(&ar->rx_pool);
+ usb_scuttle_anchored_urbs(&ar->rx_work);
+ usb_kill_anchored_urbs(&ar->rx_anch);
+ return err;
+}
+
+static int carl9170_usb_flush(struct ar9170 *ar)
+{
+ struct urb *urb;
+ int ret, err = 0;
+
+ while ((urb = usb_get_from_anchor(&ar->tx_wait))) {
+ struct sk_buff *skb = (void *)urb->context;
+ carl9170_tx_drop(ar, skb);
+ carl9170_tx_callback(ar, skb);
+ usb_free_urb(urb);
+ }
+
+ ret = usb_wait_anchor_empty_timeout(&ar->tx_cmd, HZ);
+ if (ret == 0)
+ err = -ETIMEDOUT;
+
+ /* lets wait a while until the tx - queues are dried out */
+ ret = usb_wait_anchor_empty_timeout(&ar->tx_anch, HZ);
+ if (ret == 0)
+ err = -ETIMEDOUT;
+
+ usb_kill_anchored_urbs(&ar->tx_anch);
+ carl9170_usb_handle_tx_err(ar);
+
+ return err;
+}
+
+static void carl9170_usb_cancel_urbs(struct ar9170 *ar)
+{
+ int err;
+
+ carl9170_set_state(ar, CARL9170_UNKNOWN_STATE);
+
+ err = carl9170_usb_flush(ar);
+ if (err)
+ dev_err(&ar->udev->dev, "stuck tx urbs!\n");
+
+ usb_poison_anchored_urbs(&ar->tx_anch);
+ carl9170_usb_handle_tx_err(ar);
+ usb_poison_anchored_urbs(&ar->rx_anch);
+
+ tasklet_kill(&ar->usb_tasklet);
+
+ usb_scuttle_anchored_urbs(&ar->rx_work);
+ usb_scuttle_anchored_urbs(&ar->rx_pool);
+ usb_scuttle_anchored_urbs(&ar->tx_cmd);
+}
+
+int __carl9170_exec_cmd(struct ar9170 *ar, struct carl9170_cmd *cmd,
+ const bool free_buf)
+{
+ struct urb *urb;
+
+ if (!IS_INITIALIZED(ar))
+ return -EPERM;
+
+ if (WARN_ON(cmd->hdr.len > CARL9170_MAX_CMD_LEN - 4))
+ return -EINVAL;
+
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
+ if (!urb)
+ return -ENOMEM;
+
+ usb_fill_int_urb(urb, ar->udev, usb_sndintpipe(ar->udev,
+ AR9170_USB_EP_CMD), cmd, cmd->hdr.len + 4,
+ carl9170_usb_cmd_complete, ar, 1);
+
+ if (free_buf)
+ urb->transfer_flags |= URB_FREE_BUFFER;
+
+ usb_anchor_urb(urb, &ar->tx_cmd);
+ usb_free_urb(urb);
+
+ return carl9170_usb_submit_cmd_urb(ar);
+}
+
+int carl9170_exec_cmd(struct ar9170 *ar, const enum carl9170_cmd_oids cmd,
+ unsigned int plen, void *payload, unsigned int outlen, void *out)
+{
+ int err = -ENOMEM;
+
+ if (!IS_ACCEPTING_CMD(ar))
+ return -EIO;
+
+ if (!(cmd & CARL9170_CMD_ASYNC_FLAG))
+ might_sleep();
+
+ ar->cmd.hdr.len = plen;
+ ar->cmd.hdr.cmd = cmd;
+ /* writing multiple regs fills this buffer already */
+ if (plen && payload != (u8 *)(ar->cmd.data))
+ memcpy(ar->cmd.data, payload, plen);
+
+ spin_lock_bh(&ar->cmd_lock);
+ ar->readbuf = (u8 *)out;
+ ar->readlen = outlen;
+ spin_unlock_bh(&ar->cmd_lock);
+
+ err = __carl9170_exec_cmd(ar, &ar->cmd, false);
+
+ if (!(cmd & CARL9170_CMD_ASYNC_FLAG)) {
+ err = wait_for_completion_timeout(&ar->cmd_wait, HZ);
+ if (err == 0) {
+ err = -ETIMEDOUT;
+ goto err_unbuf;
+ }
+
+ if (ar->readlen != outlen) {
+ err = -EMSGSIZE;
+ goto err_unbuf;
+ }
+ }
+
+ return 0;
+
+err_unbuf:
+ /* Maybe the device was removed in the moment we were waiting? */
+ if (IS_STARTED(ar)) {
+ dev_err(&ar->udev->dev, "no command feedback "
+ "received (%d).\n", err);
+
+ /* provide some maybe useful debug information */
+ print_hex_dump_bytes("carl9170 cmd: ", DUMP_PREFIX_NONE,
+ &ar->cmd, plen + 4);
+
+ carl9170_restart(ar, CARL9170_RR_COMMAND_TIMEOUT);
+ }
+
+ /* invalidate to avoid completing the next command prematurely */
+ spin_lock_bh(&ar->cmd_lock);
+ ar->readbuf = NULL;
+ ar->readlen = 0;
+ spin_unlock_bh(&ar->cmd_lock);
+
+ return err;
+}
+
+void carl9170_usb_tx(struct ar9170 *ar, struct sk_buff *skb)
+{
+ struct urb *urb;
+ struct ar9170_stream *tx_stream;
+ void *data;
+ unsigned int len;
+
+ if (!IS_STARTED(ar))
+ goto err_drop;
+
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
+ if (!urb)
+ goto err_drop;
+
+ if (ar->fw.tx_stream) {
+ tx_stream = (void *) (skb->data - sizeof(*tx_stream));
+
+ len = skb->len + sizeof(*tx_stream);
+ tx_stream->length = cpu_to_le16(len);
+ tx_stream->tag = cpu_to_le16(AR9170_TX_STREAM_TAG);
+ data = tx_stream;
+ } else {
+ data = skb->data;
+ len = skb->len;
+ }
+
+ usb_fill_bulk_urb(urb, ar->udev, usb_sndbulkpipe(ar->udev,
+ AR9170_USB_EP_TX), data, len,
+ carl9170_usb_tx_data_complete, skb);
+
+ urb->transfer_flags |= URB_ZERO_PACKET;
+
+ usb_anchor_urb(urb, &ar->tx_wait);
+
+ usb_free_urb(urb);
+
+ carl9170_usb_submit_data_urb(ar);
+ return;
+
+err_drop:
+ carl9170_tx_drop(ar, skb);
+ carl9170_tx_callback(ar, skb);
+}
+
+static void carl9170_release_firmware(struct ar9170 *ar)
+{
+ if (ar->fw.fw) {
+ release_firmware(ar->fw.fw);
+ memset(&ar->fw, 0, sizeof(ar->fw));
+ }
+}
+
+void carl9170_usb_stop(struct ar9170 *ar)
+{
+ int ret;
+
+ carl9170_set_state_when(ar, CARL9170_IDLE, CARL9170_STOPPED);
+
+ ret = carl9170_usb_flush(ar);
+ if (ret)
+ dev_err(&ar->udev->dev, "kill pending tx urbs.\n");
+
+ usb_poison_anchored_urbs(&ar->tx_anch);
+ carl9170_usb_handle_tx_err(ar);
+
+ /* kill any pending command */
+ spin_lock_bh(&ar->cmd_lock);
+ ar->readlen = 0;
+ spin_unlock_bh(&ar->cmd_lock);
+ complete_all(&ar->cmd_wait);
+
+ /* This is required to prevent an early completion on _start */
+ INIT_COMPLETION(ar->cmd_wait);
+
+ /*
+ * Note:
+ * So far we freed all tx urbs, but we won't dare to touch any rx urbs.
+ * Else we would end up with a unresponsive device...
+ */
+}
+
+int carl9170_usb_open(struct ar9170 *ar)
+{
+ usb_unpoison_anchored_urbs(&ar->tx_anch);
+
+ carl9170_set_state_when(ar, CARL9170_STOPPED, CARL9170_IDLE);
+ return 0;
+}
+
+static int carl9170_usb_load_firmware(struct ar9170 *ar)
+{
+ const u8 *data;
+ u8 *buf;
+ unsigned int transfer;
+ size_t len;
+ u32 addr;
+ int err = 0;
+
+ buf = kmalloc(4096, GFP_KERNEL);
+ if (!buf) {
+ err = -ENOMEM;
+ goto err_out;
+ }
+
+ data = ar->fw.fw->data;
+ len = ar->fw.fw->size;
+ addr = ar->fw.address;
+
+ /* this removes the miniboot image */
+ data += ar->fw.offset;
+ len -= ar->fw.offset;
+
+ while (len) {
+ transfer = min_t(unsigned int, len, 4096u);
+ memcpy(buf, data, transfer);
+
+ err = usb_control_msg(ar->udev, usb_sndctrlpipe(ar->udev, 0),
+ 0x30 /* FW DL */, 0x40 | USB_DIR_OUT,
+ addr >> 8, 0, buf, transfer, 100);
+
+ if (err < 0) {
+ kfree(buf);
+ goto err_out;
+ }
+
+ len -= transfer;
+ data += transfer;
+ addr += transfer;
+ }
+ kfree(buf);
+
+ err = usb_control_msg(ar->udev, usb_sndctrlpipe(ar->udev, 0),
+ 0x31 /* FW DL COMPLETE */,
+ 0x40 | USB_DIR_OUT, 0, 0, NULL, 0, 200);
+
+ if (wait_for_completion_timeout(&ar->fw_boot_wait, HZ) == 0) {
+ err = -ETIMEDOUT;
+ goto err_out;
+ }
+
+ err = carl9170_echo_test(ar, 0x4a110123);
+ if (err)
+ goto err_out;
+
+ /* firmware restarts cmd counter */
+ ar->cmd_seq = -1;
+
+ return 0;
+
+err_out:
+ dev_err(&ar->udev->dev, "firmware upload failed (%d).\n", err);
+ return err;
+}
+
+int carl9170_usb_restart(struct ar9170 *ar)
+{
+ int err = 0;
+
+ if (ar->intf->condition != USB_INTERFACE_BOUND)
+ return 0;
+
+ /* Disable command response sequence counter. */
+ ar->cmd_seq = -2;
+
+ err = carl9170_reboot(ar);
+
+ carl9170_usb_stop(ar);
+
+ if (err)
+ goto err_out;
+
+ tasklet_schedule(&ar->usb_tasklet);
+
+ /* The reboot procedure can take quite a while to complete. */
+ msleep(1100);
+
+ err = carl9170_usb_open(ar);
+ if (err)
+ goto err_out;
+
+ err = carl9170_usb_load_firmware(ar);
+ if (err)
+ goto err_out;
+
+ return 0;
+
+err_out:
+ carl9170_usb_cancel_urbs(ar);
+ return err;
+}
+
+void carl9170_usb_reset(struct ar9170 *ar)
+{
+ /*
+ * This is the last resort to get the device going again
+ * without any *user replugging action*.
+ *
+ * But there is a catch: usb_reset really is like a physical
+ * *reconnect*. The mac80211 state will be lost in the process.
+ * Therefore a userspace application, which is monitoring
+ * the link must step in.
+ */
+ carl9170_usb_cancel_urbs(ar);
+
+ carl9170_usb_stop(ar);
+
+ usb_queue_reset_device(ar->intf);
+}
+
+static int carl9170_usb_init_device(struct ar9170 *ar)
+{
+ int err;
+
+ err = carl9170_usb_send_rx_irq_urb(ar);
+ if (err)
+ goto err_out;
+
+ err = carl9170_usb_init_rx_bulk_urbs(ar);
+ if (err)
+ goto err_unrx;
+
+ mutex_lock(&ar->mutex);
+ err = carl9170_usb_load_firmware(ar);
+ mutex_unlock(&ar->mutex);
+ if (err)
+ goto err_unrx;
+
+ return 0;
+
+err_unrx:
+ carl9170_usb_cancel_urbs(ar);
+
+err_out:
+ return err;
+}
+
+static void carl9170_usb_firmware_failed(struct ar9170 *ar)
+{
+ struct device *parent = ar->udev->dev.parent;
+ struct usb_device *udev;
+
+ /*
+ * Store a copy of the usb_device pointer locally.
+ * This is because device_release_driver initiates
+ * carl9170_usb_disconnect, which in turn frees our
+ * driver context (ar).
+ */
+ udev = ar->udev;
+
+ complete(&ar->fw_load_wait);
+
+ /* unbind anything failed */
+ if (parent)
+ device_lock(parent);
+
+ device_release_driver(&udev->dev);
+ if (parent)
+ device_unlock(parent);
+
+ usb_put_dev(udev);
+}
+
+static void carl9170_usb_firmware_finish(struct ar9170 *ar)
+{
+ int err;
+
+ err = carl9170_parse_firmware(ar);
+ if (err)
+ goto err_freefw;
+
+ err = carl9170_usb_init_device(ar);
+ if (err)
+ goto err_freefw;
+
+ err = carl9170_usb_open(ar);
+ if (err)
+ goto err_unrx;
+
+ err = carl9170_register(ar);
+
+ carl9170_usb_stop(ar);
+ if (err)
+ goto err_unrx;
+
+ complete(&ar->fw_load_wait);
+ usb_put_dev(ar->udev);
+ return;
+
+err_unrx:
+ carl9170_usb_cancel_urbs(ar);
+
+err_freefw:
+ carl9170_release_firmware(ar);
+ carl9170_usb_firmware_failed(ar);
+}
+
+static void carl9170_usb_firmware_step2(const struct firmware *fw,
+ void *context)
+{
+ struct ar9170 *ar = context;
+
+ if (fw) {
+ ar->fw.fw = fw;
+ carl9170_usb_firmware_finish(ar);
+ return;
+ }
+
+ dev_err(&ar->udev->dev, "firmware not found.\n");
+ carl9170_usb_firmware_failed(ar);
+}
+
+static int carl9170_usb_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct ar9170 *ar;
+ struct usb_device *udev;
+ int err;
+
+ err = usb_reset_device(interface_to_usbdev(intf));
+ if (err)
+ return err;
+
+ ar = carl9170_alloc(sizeof(*ar));
+ if (IS_ERR(ar))
+ return PTR_ERR(ar);
+
+ udev = interface_to_usbdev(intf);
+ usb_get_dev(udev);
+ ar->udev = udev;
+ ar->intf = intf;
+ ar->features = id->driver_info;
+
+ usb_set_intfdata(intf, ar);
+ SET_IEEE80211_DEV(ar->hw, &intf->dev);
+
+ init_usb_anchor(&ar->rx_anch);
+ init_usb_anchor(&ar->rx_pool);
+ init_usb_anchor(&ar->rx_work);
+ init_usb_anchor(&ar->tx_wait);
+ init_usb_anchor(&ar->tx_anch);
+ init_usb_anchor(&ar->tx_cmd);
+ init_usb_anchor(&ar->tx_err);
+ init_completion(&ar->cmd_wait);
+ init_completion(&ar->fw_boot_wait);
+ init_completion(&ar->fw_load_wait);
+ tasklet_init(&ar->usb_tasklet, carl9170_usb_tasklet,
+ (unsigned long)ar);
+
+ atomic_set(&ar->tx_cmd_urbs, 0);
+ atomic_set(&ar->tx_anch_urbs, 0);
+ atomic_set(&ar->rx_work_urbs, 0);
+ atomic_set(&ar->rx_anch_urbs, 0);
+ atomic_set(&ar->rx_pool_urbs, 0);
+ ar->cmd_seq = -2;
+
+ usb_get_dev(ar->udev);
+
+ carl9170_set_state(ar, CARL9170_STOPPED);
+
+ return request_firmware_nowait(THIS_MODULE, 1, CARL9170FW_NAME,
+ &ar->udev->dev, GFP_KERNEL, ar, carl9170_usb_firmware_step2);
+}
+
+static void carl9170_usb_disconnect(struct usb_interface *intf)
+{
+ struct ar9170 *ar = usb_get_intfdata(intf);
+ struct usb_device *udev;
+
+ if (WARN_ON(!ar))
+ return;
+
+ udev = ar->udev;
+ wait_for_completion(&ar->fw_load_wait);
+
+ if (IS_INITIALIZED(ar)) {
+ carl9170_reboot(ar);
+ carl9170_usb_stop(ar);
+ }
+
+ carl9170_usb_cancel_urbs(ar);
+ carl9170_unregister(ar);
+
+ usb_set_intfdata(intf, NULL);
+
+ carl9170_release_firmware(ar);
+ carl9170_free(ar);
+ usb_put_dev(udev);
+}
+
+#ifdef CONFIG_PM
+static int carl9170_usb_suspend(struct usb_interface *intf,
+ pm_message_t message)
+{
+ struct ar9170 *ar = usb_get_intfdata(intf);
+
+ if (!ar)
+ return -ENODEV;
+
+ carl9170_usb_cancel_urbs(ar);
+
+ /*
+ * firmware automatically reboots for usb suspend.
+ */
+
+ return 0;
+}
+
+static int carl9170_usb_resume(struct usb_interface *intf)
+{
+ struct ar9170 *ar = usb_get_intfdata(intf);
+ int err;
+
+ if (!ar)
+ return -ENODEV;
+
+ usb_unpoison_anchored_urbs(&ar->rx_anch);
+
+ err = carl9170_usb_init_device(ar);
+ if (err)
+ goto err_unrx;
+
+ err = carl9170_usb_open(ar);
+ if (err)
+ goto err_unrx;
+
+ return 0;
+
+err_unrx:
+ carl9170_usb_cancel_urbs(ar);
+
+ return err;
+}
+#endif /* CONFIG_PM */
+
+static struct usb_driver carl9170_driver = {
+ .name = KBUILD_MODNAME,
+ .probe = carl9170_usb_probe,
+ .disconnect = carl9170_usb_disconnect,
+ .id_table = carl9170_usb_ids,
+ .soft_unbind = 1,
+#ifdef CONFIG_PM
+ .suspend = carl9170_usb_suspend,
+ .resume = carl9170_usb_resume,
+#endif /* CONFIG_PM */
+};
+
+static int __init carl9170_usb_init(void)
+{
+ return usb_register(&carl9170_driver);
+}
+
+static void __exit carl9170_usb_exit(void)
+{
+ usb_deregister(&carl9170_driver);
+}
+
+module_init(carl9170_usb_init);
+module_exit(carl9170_usb_exit);
diff --git a/drivers/net/wireless/ath/carl9170/version.h b/drivers/net/wireless/ath/carl9170/version.h
new file mode 100644
index 000000000000..ff53f078a0b5
--- /dev/null
+++ b/drivers/net/wireless/ath/carl9170/version.h
@@ -0,0 +1,7 @@
+#ifndef __CARL9170_SHARED_VERSION_H
+#define __CARL9170_SHARED_VERSION_H
+#define CARL9170FW_VERSION_YEAR 10
+#define CARL9170FW_VERSION_MONTH 9
+#define CARL9170FW_VERSION_DAY 28
+#define CARL9170FW_VERSION_GIT "1.8.8.3"
+#endif /* __CARL9170_SHARED_VERSION_H */
diff --git a/drivers/net/wireless/ath/carl9170/wlan.h b/drivers/net/wireless/ath/carl9170/wlan.h
new file mode 100644
index 000000000000..24d63b583b6b
--- /dev/null
+++ b/drivers/net/wireless/ath/carl9170/wlan.h
@@ -0,0 +1,420 @@
+/*
+ * Shared Atheros AR9170 Header
+ *
+ * RX/TX meta descriptor format
+ *
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, see
+ * http://www.gnu.org/licenses/.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ * Copyright (c) 2007-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __CARL9170_SHARED_WLAN_H
+#define __CARL9170_SHARED_WLAN_H
+
+#include "fwcmd.h"
+
+#define AR9170_RX_PHY_RATE_CCK_1M 0x0a
+#define AR9170_RX_PHY_RATE_CCK_2M 0x14
+#define AR9170_RX_PHY_RATE_CCK_5M 0x37
+#define AR9170_RX_PHY_RATE_CCK_11M 0x6e
+
+#define AR9170_ENC_ALG_NONE 0x0
+#define AR9170_ENC_ALG_WEP64 0x1
+#define AR9170_ENC_ALG_TKIP 0x2
+#define AR9170_ENC_ALG_AESCCMP 0x4
+#define AR9170_ENC_ALG_WEP128 0x5
+#define AR9170_ENC_ALG_WEP256 0x6
+#define AR9170_ENC_ALG_CENC 0x7
+
+#define AR9170_RX_ENC_SOFTWARE 0x8
+
+#define AR9170_RX_STATUS_MODULATION 0x03
+#define AR9170_RX_STATUS_MODULATION_S 0
+#define AR9170_RX_STATUS_MODULATION_CCK 0x00
+#define AR9170_RX_STATUS_MODULATION_OFDM 0x01
+#define AR9170_RX_STATUS_MODULATION_HT 0x02
+#define AR9170_RX_STATUS_MODULATION_DUPOFDM 0x03
+
+/* depends on modulation */
+#define AR9170_RX_STATUS_SHORT_PREAMBLE 0x08
+#define AR9170_RX_STATUS_GREENFIELD 0x08
+
+#define AR9170_RX_STATUS_MPDU 0x30
+#define AR9170_RX_STATUS_MPDU_S 4
+#define AR9170_RX_STATUS_MPDU_SINGLE 0x00
+#define AR9170_RX_STATUS_MPDU_FIRST 0x20
+#define AR9170_RX_STATUS_MPDU_MIDDLE 0x30
+#define AR9170_RX_STATUS_MPDU_LAST 0x10
+
+#define AR9170_RX_STATUS_CONT_AGGR 0x40
+#define AR9170_RX_STATUS_TOTAL_ERROR 0x80
+
+#define AR9170_RX_ERROR_RXTO 0x01
+#define AR9170_RX_ERROR_OVERRUN 0x02
+#define AR9170_RX_ERROR_DECRYPT 0x04
+#define AR9170_RX_ERROR_FCS 0x08
+#define AR9170_RX_ERROR_WRONG_RA 0x10
+#define AR9170_RX_ERROR_PLCP 0x20
+#define AR9170_RX_ERROR_MMIC 0x40
+
+/* these are either-or */
+#define AR9170_TX_MAC_PROT_RTS 0x0001
+#define AR9170_TX_MAC_PROT_CTS 0x0002
+#define AR9170_TX_MAC_PROT 0x0003
+
+#define AR9170_TX_MAC_NO_ACK 0x0004
+/* if unset, MAC will only do SIFS space before frame */
+#define AR9170_TX_MAC_BACKOFF 0x0008
+#define AR9170_TX_MAC_BURST 0x0010
+#define AR9170_TX_MAC_AGGR 0x0020
+
+/* encryption is a two-bit field */
+#define AR9170_TX_MAC_ENCR_NONE 0x0000
+#define AR9170_TX_MAC_ENCR_RC4 0x0040
+#define AR9170_TX_MAC_ENCR_CENC 0x0080
+#define AR9170_TX_MAC_ENCR_AES 0x00c0
+
+#define AR9170_TX_MAC_MMIC 0x0100
+#define AR9170_TX_MAC_HW_DURATION 0x0200
+#define AR9170_TX_MAC_QOS_S 10
+#define AR9170_TX_MAC_QOS 0x0c00
+#define AR9170_TX_MAC_DISABLE_TXOP 0x1000
+#define AR9170_TX_MAC_TXOP_RIFS 0x2000
+#define AR9170_TX_MAC_IMM_BA 0x4000
+
+/* either-or */
+#define AR9170_TX_PHY_MOD_CCK 0x00000000
+#define AR9170_TX_PHY_MOD_OFDM 0x00000001
+#define AR9170_TX_PHY_MOD_HT 0x00000002
+
+/* depends on modulation */
+#define AR9170_TX_PHY_SHORT_PREAMBLE 0x00000004
+#define AR9170_TX_PHY_GREENFIELD 0x00000004
+
+#define AR9170_TX_PHY_BW_S 3
+#define AR9170_TX_PHY_BW (3 << AR9170_TX_PHY_BW_SHIFT)
+#define AR9170_TX_PHY_BW_20MHZ 0
+#define AR9170_TX_PHY_BW_40MHZ 2
+#define AR9170_TX_PHY_BW_40MHZ_DUP 3
+
+#define AR9170_TX_PHY_TX_HEAVY_CLIP_S 6
+#define AR9170_TX_PHY_TX_HEAVY_CLIP (7 << \
+ AR9170_TX_PHY_TX_HEAVY_CLIP_S)
+
+#define AR9170_TX_PHY_TX_PWR_S 9
+#define AR9170_TX_PHY_TX_PWR (0x3f << \
+ AR9170_TX_PHY_TX_PWR_S)
+
+#define AR9170_TX_PHY_TXCHAIN_S 15
+#define AR9170_TX_PHY_TXCHAIN (7 << \
+ AR9170_TX_PHY_TXCHAIN_S)
+#define AR9170_TX_PHY_TXCHAIN_1 1
+/* use for cck, ofdm 6/9/12/18/24 and HT if capable */
+#define AR9170_TX_PHY_TXCHAIN_2 5
+
+#define AR9170_TX_PHY_MCS_S 18
+#define AR9170_TX_PHY_MCS (0x7f << \
+ AR9170_TX_PHY_MCS_S)
+
+#define AR9170_TX_PHY_RATE_CCK_1M 0x0
+#define AR9170_TX_PHY_RATE_CCK_2M 0x1
+#define AR9170_TX_PHY_RATE_CCK_5M 0x2
+#define AR9170_TX_PHY_RATE_CCK_11M 0x3
+
+/* same as AR9170_RX_PHY_RATE */
+#define AR9170_TXRX_PHY_RATE_OFDM_6M 0xb
+#define AR9170_TXRX_PHY_RATE_OFDM_9M 0xf
+#define AR9170_TXRX_PHY_RATE_OFDM_12M 0xa
+#define AR9170_TXRX_PHY_RATE_OFDM_18M 0xe
+#define AR9170_TXRX_PHY_RATE_OFDM_24M 0x9
+#define AR9170_TXRX_PHY_RATE_OFDM_36M 0xd
+#define AR9170_TXRX_PHY_RATE_OFDM_48M 0x8
+#define AR9170_TXRX_PHY_RATE_OFDM_54M 0xc
+
+#define AR9170_TXRX_PHY_RATE_HT_MCS0 0x0
+#define AR9170_TXRX_PHY_RATE_HT_MCS1 0x1
+#define AR9170_TXRX_PHY_RATE_HT_MCS2 0x2
+#define AR9170_TXRX_PHY_RATE_HT_MCS3 0x3
+#define AR9170_TXRX_PHY_RATE_HT_MCS4 0x4
+#define AR9170_TXRX_PHY_RATE_HT_MCS5 0x5
+#define AR9170_TXRX_PHY_RATE_HT_MCS6 0x6
+#define AR9170_TXRX_PHY_RATE_HT_MCS7 0x7
+#define AR9170_TXRX_PHY_RATE_HT_MCS8 0x8
+#define AR9170_TXRX_PHY_RATE_HT_MCS9 0x9
+#define AR9170_TXRX_PHY_RATE_HT_MCS10 0xa
+#define AR9170_TXRX_PHY_RATE_HT_MCS11 0xb
+#define AR9170_TXRX_PHY_RATE_HT_MCS12 0xc
+#define AR9170_TXRX_PHY_RATE_HT_MCS13 0xd
+#define AR9170_TXRX_PHY_RATE_HT_MCS14 0xe
+#define AR9170_TXRX_PHY_RATE_HT_MCS15 0xf
+
+#define AR9170_TX_PHY_SHORT_GI 0x80000000
+
+#ifdef __CARL9170FW__
+struct ar9170_tx_hw_mac_control {
+ union {
+ struct {
+ /*
+ * Beware of compiler bugs in all gcc pre 4.4!
+ */
+
+ u8 erp_prot:2;
+ u8 no_ack:1;
+ u8 backoff:1;
+ u8 burst:1;
+ u8 ampdu:1;
+
+ u8 enc_mode:2;
+
+ u8 hw_mmic:1;
+ u8 hw_duration:1;
+
+ u8 qos_queue:2;
+
+ u8 disable_txop:1;
+ u8 txop_rifs:1;
+
+ u8 ba_end:1;
+ u8 probe:1;
+ } __packed;
+
+ __le16 set;
+ } __packed;
+} __packed;
+
+struct ar9170_tx_hw_phy_control {
+ union {
+ struct {
+ /*
+ * Beware of compiler bugs in all gcc pre 4.4!
+ */
+
+ u8 modulation:2;
+ u8 preamble:1;
+ u8 bandwidth:2;
+ u8:1;
+ u8 heavy_clip:3;
+ u8 tx_power:6;
+ u8 chains:3;
+ u8 mcs:7;
+ u8:6;
+ u8 short_gi:1;
+ } __packed;
+
+ __le32 set;
+ } __packed;
+} __packed;
+
+struct ar9170_tx_rate_info {
+ u8 tries:3;
+ u8 erp_prot:2;
+ u8 ampdu:1;
+ u8 free:2; /* free for use (e.g.:RIFS/TXOP/AMPDU) */
+} __packed;
+
+struct carl9170_tx_superdesc {
+ __le16 len;
+ u8 rix;
+ u8 cnt;
+ u8 cookie;
+ u8 ampdu_density:3;
+ u8 ampdu_factor:2;
+ u8 ampdu_commit_density:1;
+ u8 ampdu_commit_factor:1;
+ u8 ampdu_unused_bit:1;
+ u8 queue:2;
+ u8 reserved:1;
+ u8 vif_id:3;
+ u8 fill_in_tsf:1;
+ u8 cab:1;
+ u8 padding2;
+ struct ar9170_tx_rate_info ri[CARL9170_TX_MAX_RATES];
+ struct ar9170_tx_hw_phy_control rr[CARL9170_TX_MAX_RETRY_RATES];
+} __packed;
+
+struct ar9170_tx_hwdesc {
+ __le16 length;
+ struct ar9170_tx_hw_mac_control mac;
+ struct ar9170_tx_hw_phy_control phy;
+} __packed;
+
+struct ar9170_tx_frame {
+ struct ar9170_tx_hwdesc hdr;
+
+ union {
+ struct ieee80211_hdr i3e;
+ u8 payload[0];
+ } data;
+} __packed;
+
+struct carl9170_tx_superframe {
+ struct carl9170_tx_superdesc s;
+ struct ar9170_tx_frame f;
+} __packed;
+
+#endif /* __CARL9170FW__ */
+
+struct _ar9170_tx_hwdesc {
+ __le16 length;
+ __le16 mac_control;
+ __le32 phy_control;
+} __packed;
+
+#define CARL9170_TX_SUPER_AMPDU_DENSITY_S 0
+#define CARL9170_TX_SUPER_AMPDU_DENSITY 0x7
+#define CARL9170_TX_SUPER_AMPDU_FACTOR 0x18
+#define CARL9170_TX_SUPER_AMPDU_FACTOR_S 3
+#define CARL9170_TX_SUPER_AMPDU_COMMIT_DENSITY 0x20
+#define CARL9170_TX_SUPER_AMPDU_COMMIT_DENSITY_S 5
+#define CARL9170_TX_SUPER_AMPDU_COMMIT_FACTOR 0x40
+#define CARL9170_TX_SUPER_AMPDU_COMMIT_FACTOR_S 6
+
+#define CARL9170_TX_SUPER_MISC_QUEUE 0x3
+#define CARL9170_TX_SUPER_MISC_QUEUE_S 0
+#define CARL9170_TX_SUPER_MISC_VIF_ID 0x38
+#define CARL9170_TX_SUPER_MISC_VIF_ID_S 3
+#define CARL9170_TX_SUPER_MISC_FILL_IN_TSF 0x40
+#define CARL9170_TX_SUPER_MISC_CAB 0x80
+
+#define CARL9170_TX_SUPER_RI_TRIES 0x7
+#define CARL9170_TX_SUPER_RI_TRIES_S 0
+#define CARL9170_TX_SUPER_RI_ERP_PROT 0x18
+#define CARL9170_TX_SUPER_RI_ERP_PROT_S 3
+#define CARL9170_TX_SUPER_RI_AMPDU 0x20
+#define CARL9170_TX_SUPER_RI_AMPDU_S 5
+
+struct _carl9170_tx_superdesc {
+ __le16 len;
+ u8 rix;
+ u8 cnt;
+ u8 cookie;
+ u8 ampdu_settings;
+ u8 misc;
+ u8 padding;
+ u8 ri[CARL9170_TX_MAX_RATES];
+ __le32 rr[CARL9170_TX_MAX_RETRY_RATES];
+} __packed;
+
+struct _carl9170_tx_superframe {
+ struct _carl9170_tx_superdesc s;
+ struct _ar9170_tx_hwdesc f;
+ u8 frame_data[0];
+} __packed;
+
+#define CARL9170_TX_SUPERDESC_LEN 24
+#define AR9170_TX_HWDESC_LEN 8
+#define CARL9170_TX_SUPERFRAME_LEN (CARL9170_TX_SUPERDESC_LEN + \
+ AR9170_TX_HWDESC_LEN)
+
+struct ar9170_rx_head {
+ u8 plcp[12];
+} __packed;
+
+#define AR9170_RX_HEAD_LEN 12
+
+struct ar9170_rx_phystatus {
+ union {
+ struct {
+ u8 rssi_ant0, rssi_ant1, rssi_ant2,
+ rssi_ant0x, rssi_ant1x, rssi_ant2x,
+ rssi_combined;
+ } __packed;
+ u8 rssi[7];
+ } __packed;
+
+ u8 evm_stream0[6], evm_stream1[6];
+ u8 phy_err;
+} __packed;
+
+#define AR9170_RX_PHYSTATUS_LEN 20
+
+struct ar9170_rx_macstatus {
+ u8 SAidx, DAidx;
+ u8 error;
+ u8 status;
+} __packed;
+
+#define AR9170_RX_MACSTATUS_LEN 4
+
+struct ar9170_rx_frame_single {
+ struct ar9170_rx_head phy_head;
+ struct ieee80211_hdr i3e;
+ struct ar9170_rx_phystatus phy_tail;
+ struct ar9170_rx_macstatus macstatus;
+} __packed;
+
+struct ar9170_rx_frame_head {
+ struct ar9170_rx_head phy_head;
+ struct ieee80211_hdr i3e;
+ struct ar9170_rx_macstatus macstatus;
+} __packed;
+
+struct ar9170_rx_frame_middle {
+ struct ieee80211_hdr i3e;
+ struct ar9170_rx_macstatus macstatus;
+} __packed;
+
+struct ar9170_rx_frame_tail {
+ struct ieee80211_hdr i3e;
+ struct ar9170_rx_phystatus phy_tail;
+ struct ar9170_rx_macstatus macstatus;
+} __packed;
+
+struct ar9170_rx_frame {
+ union {
+ struct ar9170_rx_frame_single single;
+ struct ar9170_rx_frame_head head;
+ struct ar9170_rx_frame_middle middle;
+ struct ar9170_rx_frame_tail tail;
+ } __packed;
+} __packed;
+
+static inline u8 ar9170_get_decrypt_type(struct ar9170_rx_macstatus *t)
+{
+ return (t->SAidx & 0xc0) >> 4 |
+ (t->DAidx & 0xc0) >> 6;
+}
+
+enum ar9170_txq {
+ AR9170_TXQ_BE,
+
+ AR9170_TXQ_VI,
+ AR9170_TXQ_VO,
+ AR9170_TXQ_BK,
+
+ __AR9170_NUM_TXQ,
+};
+
+static const u8 ar9170_qmap[__AR9170_NUM_TXQ] = { 2, 1, 0, 3 };
+
+#define AR9170_TXQ_DEPTH 32
+
+#endif /* __CARL9170_SHARED_WLAN_H */
diff --git a/drivers/net/wireless/ath/debug.c b/drivers/net/wireless/ath/debug.c
index 53e77bd131b9..dacfb234f491 100644
--- a/drivers/net/wireless/ath/debug.c
+++ b/drivers/net/wireless/ath/debug.c
@@ -30,3 +30,32 @@ void ath_print(struct ath_common *common, int dbg_mask, const char *fmt, ...)
va_end(args);
}
EXPORT_SYMBOL(ath_print);
+
+const char *ath_opmode_to_string(enum nl80211_iftype opmode)
+{
+ switch (opmode) {
+ case NL80211_IFTYPE_UNSPECIFIED:
+ return "UNSPEC";
+ case NL80211_IFTYPE_ADHOC:
+ return "ADHOC";
+ case NL80211_IFTYPE_STATION:
+ return "STATION";
+ case NL80211_IFTYPE_AP:
+ return "AP";
+ case NL80211_IFTYPE_AP_VLAN:
+ return "AP-VLAN";
+ case NL80211_IFTYPE_WDS:
+ return "WDS";
+ case NL80211_IFTYPE_MONITOR:
+ return "MONITOR";
+ case NL80211_IFTYPE_MESH_POINT:
+ return "MESH";
+ case NL80211_IFTYPE_P2P_CLIENT:
+ return "P2P-CLIENT";
+ case NL80211_IFTYPE_P2P_GO:
+ return "P2P-GO";
+ default:
+ return "UNKNOWN";
+ }
+}
+EXPORT_SYMBOL(ath_opmode_to_string);
diff --git a/drivers/net/wireless/ath/debug.h b/drivers/net/wireless/ath/debug.h
index 873bf526e11f..64e4af2c2887 100644
--- a/drivers/net/wireless/ath/debug.h
+++ b/drivers/net/wireless/ath/debug.h
@@ -36,6 +36,7 @@
* @ATH_DBG_PS: power save processing
* @ATH_DBG_HWTIMER: hardware timer handling
* @ATH_DBG_BTCOEX: bluetooth coexistance
+ * @ATH_DBG_BSTUCK: stuck beacons
* @ATH_DBG_ANY: enable all debugging
*
* The debug level is used to control the amount and type of debugging output
@@ -60,6 +61,7 @@ enum ATH_DEBUG {
ATH_DBG_HWTIMER = 0x00001000,
ATH_DBG_BTCOEX = 0x00002000,
ATH_DBG_WMI = 0x00004000,
+ ATH_DBG_BSTUCK = 0x00008000,
ATH_DBG_ANY = 0xffffffff
};
@@ -75,4 +77,14 @@ ath_print(struct ath_common *common, int dbg_mask, const char *fmt, ...)
}
#endif /* CONFIG_ATH_DEBUG */
+/** Returns string describing opmode, or NULL if unknown mode. */
+#ifdef CONFIG_ATH_DEBUG
+const char *ath_opmode_to_string(enum nl80211_iftype opmode);
+#else
+static inline const char *ath_opmode_to_string(enum nl80211_iftype opmode)
+{
+ return "UNKNOWN";
+}
+#endif
+
#endif /* ATH_DEBUG_H */
diff --git a/drivers/net/wireless/ath/hw.c b/drivers/net/wireless/ath/hw.c
index a8f81ea09f14..183c28281385 100644
--- a/drivers/net/wireless/ath/hw.c
+++ b/drivers/net/wireless/ath/hw.c
@@ -124,3 +124,62 @@ void ath_hw_setbssidmask(struct ath_common *common)
REG_WRITE(ah, get_unaligned_le16(common->bssidmask + 4), AR_BSSMSKU);
}
EXPORT_SYMBOL(ath_hw_setbssidmask);
+
+
+/**
+ * ath_hw_cycle_counters_update - common function to update cycle counters
+ *
+ * @common: the ath_common struct for the device.
+ *
+ * This function is used to update all cycle counters in one place.
+ * It has to be called while holding common->cc_lock!
+ */
+void ath_hw_cycle_counters_update(struct ath_common *common)
+{
+ u32 cycles, busy, rx, tx;
+ void *ah = common->ah;
+
+ /* freeze */
+ REG_WRITE(ah, AR_MIBC_FMC, AR_MIBC);
+
+ /* read */
+ cycles = REG_READ(ah, AR_CCCNT);
+ busy = REG_READ(ah, AR_RCCNT);
+ rx = REG_READ(ah, AR_RFCNT);
+ tx = REG_READ(ah, AR_TFCNT);
+
+ /* clear */
+ REG_WRITE(ah, 0, AR_CCCNT);
+ REG_WRITE(ah, 0, AR_RFCNT);
+ REG_WRITE(ah, 0, AR_RCCNT);
+ REG_WRITE(ah, 0, AR_TFCNT);
+
+ /* unfreeze */
+ REG_WRITE(ah, 0, AR_MIBC);
+
+ /* update all cycle counters here */
+ common->cc_ani.cycles += cycles;
+ common->cc_ani.rx_busy += busy;
+ common->cc_ani.rx_frame += rx;
+ common->cc_ani.tx_frame += tx;
+
+ common->cc_survey.cycles += cycles;
+ common->cc_survey.rx_busy += busy;
+ common->cc_survey.rx_frame += rx;
+ common->cc_survey.tx_frame += tx;
+}
+EXPORT_SYMBOL(ath_hw_cycle_counters_update);
+
+int32_t ath_hw_get_listen_time(struct ath_common *common)
+{
+ struct ath_cycle_counters *cc = &common->cc_ani;
+ int32_t listen_time;
+
+ listen_time = (cc->cycles - cc->rx_frame - cc->tx_frame) /
+ (common->clockrate * 1000);
+
+ memset(cc, 0, sizeof(*cc));
+
+ return listen_time;
+}
+EXPORT_SYMBOL(ath_hw_get_listen_time);
diff --git a/drivers/net/wireless/ath/key.c b/drivers/net/wireless/ath/key.c
new file mode 100644
index 000000000000..bd21a4d82085
--- /dev/null
+++ b/drivers/net/wireless/ath/key.c
@@ -0,0 +1,568 @@
+/*
+ * Copyright (c) 2009 Atheros Communications Inc.
+ * Copyright (c) 2010 Bruno Randolf <br1@einfach.org>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <asm/unaligned.h>
+#include <net/mac80211.h>
+
+#include "ath.h"
+#include "reg.h"
+#include "debug.h"
+
+#define REG_READ (common->ops->read)
+#define REG_WRITE(_ah, _reg, _val) (common->ops->write)(_ah, _val, _reg)
+
+#define IEEE80211_WEP_NKID 4 /* number of key ids */
+
+/************************/
+/* Key Cache Management */
+/************************/
+
+bool ath_hw_keyreset(struct ath_common *common, u16 entry)
+{
+ u32 keyType;
+ void *ah = common->ah;
+
+ if (entry >= common->keymax) {
+ ath_print(common, ATH_DBG_FATAL,
+ "keychache entry %u out of range\n", entry);
+ return false;
+ }
+
+ keyType = REG_READ(ah, AR_KEYTABLE_TYPE(entry));
+
+ REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), AR_KEYTABLE_TYPE_CLR);
+ REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0);
+
+ if (keyType == AR_KEYTABLE_TYPE_TKIP) {
+ u16 micentry = entry + 64;
+
+ REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0);
+
+ }
+
+ return true;
+}
+EXPORT_SYMBOL(ath_hw_keyreset);
+
+bool ath_hw_keysetmac(struct ath_common *common, u16 entry, const u8 *mac)
+{
+ u32 macHi, macLo;
+ u32 unicast_flag = AR_KEYTABLE_VALID;
+ void *ah = common->ah;
+
+ if (entry >= common->keymax) {
+ ath_print(common, ATH_DBG_FATAL,
+ "keychache entry %u out of range\n", entry);
+ return false;
+ }
+
+ if (mac != NULL) {
+ /*
+ * AR_KEYTABLE_VALID indicates that the address is a unicast
+ * address, which must match the transmitter address for
+ * decrypting frames.
+ * Not setting this bit allows the hardware to use the key
+ * for multicast frame decryption.
+ */
+ if (mac[0] & 0x01)
+ unicast_flag = 0;
+
+ macHi = (mac[5] << 8) | mac[4];
+ macLo = (mac[3] << 24) |
+ (mac[2] << 16) |
+ (mac[1] << 8) |
+ mac[0];
+ macLo >>= 1;
+ macLo |= (macHi & 1) << 31;
+ macHi >>= 1;
+ } else {
+ macLo = macHi = 0;
+ }
+ REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo);
+ REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | unicast_flag);
+
+ return true;
+}
+
+bool ath_hw_set_keycache_entry(struct ath_common *common, u16 entry,
+ const struct ath_keyval *k,
+ const u8 *mac)
+{
+ void *ah = common->ah;
+ u32 key0, key1, key2, key3, key4;
+ u32 keyType;
+
+ if (entry >= common->keymax) {
+ ath_print(common, ATH_DBG_FATAL,
+ "keycache entry %u out of range\n", entry);
+ return false;
+ }
+
+ switch (k->kv_type) {
+ case ATH_CIPHER_AES_OCB:
+ keyType = AR_KEYTABLE_TYPE_AES;
+ break;
+ case ATH_CIPHER_AES_CCM:
+ if (!(common->crypt_caps & ATH_CRYPT_CAP_CIPHER_AESCCM)) {
+ ath_print(common, ATH_DBG_ANY,
+ "AES-CCM not supported by this mac rev\n");
+ return false;
+ }
+ keyType = AR_KEYTABLE_TYPE_CCM;
+ break;
+ case ATH_CIPHER_TKIP:
+ keyType = AR_KEYTABLE_TYPE_TKIP;
+ if (entry + 64 >= common->keymax) {
+ ath_print(common, ATH_DBG_ANY,
+ "entry %u inappropriate for TKIP\n", entry);
+ return false;
+ }
+ break;
+ case ATH_CIPHER_WEP:
+ if (k->kv_len < WLAN_KEY_LEN_WEP40) {
+ ath_print(common, ATH_DBG_ANY,
+ "WEP key length %u too small\n", k->kv_len);
+ return false;
+ }
+ if (k->kv_len <= WLAN_KEY_LEN_WEP40)
+ keyType = AR_KEYTABLE_TYPE_40;
+ else if (k->kv_len <= WLAN_KEY_LEN_WEP104)
+ keyType = AR_KEYTABLE_TYPE_104;
+ else
+ keyType = AR_KEYTABLE_TYPE_128;
+ break;
+ case ATH_CIPHER_CLR:
+ keyType = AR_KEYTABLE_TYPE_CLR;
+ break;
+ default:
+ ath_print(common, ATH_DBG_FATAL,
+ "cipher %u not supported\n", k->kv_type);
+ return false;
+ }
+
+ key0 = get_unaligned_le32(k->kv_val + 0);
+ key1 = get_unaligned_le16(k->kv_val + 4);
+ key2 = get_unaligned_le32(k->kv_val + 6);
+ key3 = get_unaligned_le16(k->kv_val + 10);
+ key4 = get_unaligned_le32(k->kv_val + 12);
+ if (k->kv_len <= WLAN_KEY_LEN_WEP104)
+ key4 &= 0xff;
+
+ /*
+ * Note: Key cache registers access special memory area that requires
+ * two 32-bit writes to actually update the values in the internal
+ * memory. Consequently, the exact order and pairs used here must be
+ * maintained.
+ */
+
+ if (keyType == AR_KEYTABLE_TYPE_TKIP) {
+ u16 micentry = entry + 64;
+
+ /*
+ * Write inverted key[47:0] first to avoid Michael MIC errors
+ * on frames that could be sent or received at the same time.
+ * The correct key will be written in the end once everything
+ * else is ready.
+ */
+ REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), ~key0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), ~key1);
+
+ /* Write key[95:48] */
+ REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
+ REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
+
+ /* Write key[127:96] and key type */
+ REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
+ REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType);
+
+ /* Write MAC address for the entry */
+ (void) ath_hw_keysetmac(common, entry, mac);
+
+ if (common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED) {
+ /*
+ * TKIP uses two key cache entries:
+ * Michael MIC TX/RX keys in the same key cache entry
+ * (idx = main index + 64):
+ * key0 [31:0] = RX key [31:0]
+ * key1 [15:0] = TX key [31:16]
+ * key1 [31:16] = reserved
+ * key2 [31:0] = RX key [63:32]
+ * key3 [15:0] = TX key [15:0]
+ * key3 [31:16] = reserved
+ * key4 [31:0] = TX key [63:32]
+ */
+ u32 mic0, mic1, mic2, mic3, mic4;
+
+ mic0 = get_unaligned_le32(k->kv_mic + 0);
+ mic2 = get_unaligned_le32(k->kv_mic + 4);
+ mic1 = get_unaligned_le16(k->kv_txmic + 2) & 0xffff;
+ mic3 = get_unaligned_le16(k->kv_txmic + 0) & 0xffff;
+ mic4 = get_unaligned_le32(k->kv_txmic + 4);
+
+ /* Write RX[31:0] and TX[31:16] */
+ REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), mic1);
+
+ /* Write RX[63:32] and TX[15:0] */
+ REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2);
+ REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), mic3);
+
+ /* Write TX[63:32] and keyType(reserved) */
+ REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), mic4);
+ REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry),
+ AR_KEYTABLE_TYPE_CLR);
+
+ } else {
+ /*
+ * TKIP uses four key cache entries (two for group
+ * keys):
+ * Michael MIC TX/RX keys are in different key cache
+ * entries (idx = main index + 64 for TX and
+ * main index + 32 + 96 for RX):
+ * key0 [31:0] = TX/RX MIC key [31:0]
+ * key1 [31:0] = reserved
+ * key2 [31:0] = TX/RX MIC key [63:32]
+ * key3 [31:0] = reserved
+ * key4 [31:0] = reserved
+ *
+ * Upper layer code will call this function separately
+ * for TX and RX keys when these registers offsets are
+ * used.
+ */
+ u32 mic0, mic2;
+
+ mic0 = get_unaligned_le32(k->kv_mic + 0);
+ mic2 = get_unaligned_le32(k->kv_mic + 4);
+
+ /* Write MIC key[31:0] */
+ REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0);
+
+ /* Write MIC key[63:32] */
+ REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2);
+ REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0);
+
+ /* Write TX[63:32] and keyType(reserved) */
+ REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry),
+ AR_KEYTABLE_TYPE_CLR);
+ }
+
+ /* MAC address registers are reserved for the MIC entry */
+ REG_WRITE(ah, AR_KEYTABLE_MAC0(micentry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_MAC1(micentry), 0);
+
+ /*
+ * Write the correct (un-inverted) key[47:0] last to enable
+ * TKIP now that all other registers are set with correct
+ * values.
+ */
+ REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
+ } else {
+ /* Write key[47:0] */
+ REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
+
+ /* Write key[95:48] */
+ REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
+ REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
+
+ /* Write key[127:96] and key type */
+ REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
+ REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType);
+
+ /* Write MAC address for the entry */
+ (void) ath_hw_keysetmac(common, entry, mac);
+ }
+
+ return true;
+}
+
+static int ath_setkey_tkip(struct ath_common *common, u16 keyix, const u8 *key,
+ struct ath_keyval *hk, const u8 *addr,
+ bool authenticator)
+{
+ const u8 *key_rxmic;
+ const u8 *key_txmic;
+
+ key_txmic = key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY;
+ key_rxmic = key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY;
+
+ if (addr == NULL) {
+ /*
+ * Group key installation - only two key cache entries are used
+ * regardless of splitmic capability since group key is only
+ * used either for TX or RX.
+ */
+ if (authenticator) {
+ memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic));
+ memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_mic));
+ } else {
+ memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
+ memcpy(hk->kv_txmic, key_rxmic, sizeof(hk->kv_mic));
+ }
+ return ath_hw_set_keycache_entry(common, keyix, hk, addr);
+ }
+ if (common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED) {
+ /* TX and RX keys share the same key cache entry. */
+ memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
+ memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_txmic));
+ return ath_hw_set_keycache_entry(common, keyix, hk, addr);
+ }
+
+ /* Separate key cache entries for TX and RX */
+
+ /* TX key goes at first index, RX key at +32. */
+ memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic));
+ if (!ath_hw_set_keycache_entry(common, keyix, hk, NULL)) {
+ /* TX MIC entry failed. No need to proceed further */
+ ath_print(common, ATH_DBG_FATAL,
+ "Setting TX MIC Key Failed\n");
+ return 0;
+ }
+
+ memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
+ /* XXX delete tx key on failure? */
+ return ath_hw_set_keycache_entry(common, keyix + 32, hk, addr);
+}
+
+static int ath_reserve_key_cache_slot_tkip(struct ath_common *common)
+{
+ int i;
+
+ for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) {
+ if (test_bit(i, common->keymap) ||
+ test_bit(i + 64, common->keymap))
+ continue; /* At least one part of TKIP key allocated */
+ if (!(common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED) &&
+ (test_bit(i + 32, common->keymap) ||
+ test_bit(i + 64 + 32, common->keymap)))
+ continue; /* At least one part of TKIP key allocated */
+
+ /* Found a free slot for a TKIP key */
+ return i;
+ }
+ return -1;
+}
+
+static int ath_reserve_key_cache_slot(struct ath_common *common,
+ u32 cipher)
+{
+ int i;
+
+ if (cipher == WLAN_CIPHER_SUITE_TKIP)
+ return ath_reserve_key_cache_slot_tkip(common);
+
+ /* First, try to find slots that would not be available for TKIP. */
+ if (!(common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED)) {
+ for (i = IEEE80211_WEP_NKID; i < common->keymax / 4; i++) {
+ if (!test_bit(i, common->keymap) &&
+ (test_bit(i + 32, common->keymap) ||
+ test_bit(i + 64, common->keymap) ||
+ test_bit(i + 64 + 32, common->keymap)))
+ return i;
+ if (!test_bit(i + 32, common->keymap) &&
+ (test_bit(i, common->keymap) ||
+ test_bit(i + 64, common->keymap) ||
+ test_bit(i + 64 + 32, common->keymap)))
+ return i + 32;
+ if (!test_bit(i + 64, common->keymap) &&
+ (test_bit(i , common->keymap) ||
+ test_bit(i + 32, common->keymap) ||
+ test_bit(i + 64 + 32, common->keymap)))
+ return i + 64;
+ if (!test_bit(i + 64 + 32, common->keymap) &&
+ (test_bit(i, common->keymap) ||
+ test_bit(i + 32, common->keymap) ||
+ test_bit(i + 64, common->keymap)))
+ return i + 64 + 32;
+ }
+ } else {
+ for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) {
+ if (!test_bit(i, common->keymap) &&
+ test_bit(i + 64, common->keymap))
+ return i;
+ if (test_bit(i, common->keymap) &&
+ !test_bit(i + 64, common->keymap))
+ return i + 64;
+ }
+ }
+
+ /* No partially used TKIP slots, pick any available slot */
+ for (i = IEEE80211_WEP_NKID; i < common->keymax; i++) {
+ /* Do not allow slots that could be needed for TKIP group keys
+ * to be used. This limitation could be removed if we know that
+ * TKIP will not be used. */
+ if (i >= 64 && i < 64 + IEEE80211_WEP_NKID)
+ continue;
+ if (!(common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED)) {
+ if (i >= 32 && i < 32 + IEEE80211_WEP_NKID)
+ continue;
+ if (i >= 64 + 32 && i < 64 + 32 + IEEE80211_WEP_NKID)
+ continue;
+ }
+
+ if (!test_bit(i, common->keymap))
+ return i; /* Found a free slot for a key */
+ }
+
+ /* No free slot found */
+ return -1;
+}
+
+/*
+ * Configure encryption in the HW.
+ */
+int ath_key_config(struct ath_common *common,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct ieee80211_key_conf *key)
+{
+ struct ath_keyval hk;
+ const u8 *mac = NULL;
+ u8 gmac[ETH_ALEN];
+ int ret = 0;
+ int idx;
+
+ memset(&hk, 0, sizeof(hk));
+
+ switch (key->cipher) {
+ case WLAN_CIPHER_SUITE_WEP40:
+ case WLAN_CIPHER_SUITE_WEP104:
+ hk.kv_type = ATH_CIPHER_WEP;
+ break;
+ case WLAN_CIPHER_SUITE_TKIP:
+ hk.kv_type = ATH_CIPHER_TKIP;
+ break;
+ case WLAN_CIPHER_SUITE_CCMP:
+ hk.kv_type = ATH_CIPHER_AES_CCM;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ hk.kv_len = key->keylen;
+ memcpy(hk.kv_val, key->key, key->keylen);
+
+ if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
+ switch (vif->type) {
+ case NL80211_IFTYPE_AP:
+ memcpy(gmac, vif->addr, ETH_ALEN);
+ gmac[0] |= 0x01;
+ mac = gmac;
+ idx = ath_reserve_key_cache_slot(common, key->cipher);
+ break;
+ case NL80211_IFTYPE_ADHOC:
+ if (!sta) {
+ idx = key->keyidx;
+ break;
+ }
+ memcpy(gmac, sta->addr, ETH_ALEN);
+ gmac[0] |= 0x01;
+ mac = gmac;
+ idx = ath_reserve_key_cache_slot(common, key->cipher);
+ break;
+ default:
+ idx = key->keyidx;
+ break;
+ }
+ } else if (key->keyidx) {
+ if (WARN_ON(!sta))
+ return -EOPNOTSUPP;
+ mac = sta->addr;
+
+ if (vif->type != NL80211_IFTYPE_AP) {
+ /* Only keyidx 0 should be used with unicast key, but
+ * allow this for client mode for now. */
+ idx = key->keyidx;
+ } else
+ return -EIO;
+ } else {
+ if (WARN_ON(!sta))
+ return -EOPNOTSUPP;
+ mac = sta->addr;
+
+ idx = ath_reserve_key_cache_slot(common, key->cipher);
+ }
+
+ if (idx < 0)
+ return -ENOSPC; /* no free key cache entries */
+
+ if (key->cipher == WLAN_CIPHER_SUITE_TKIP)
+ ret = ath_setkey_tkip(common, idx, key->key, &hk, mac,
+ vif->type == NL80211_IFTYPE_AP);
+ else
+ ret = ath_hw_set_keycache_entry(common, idx, &hk, mac);
+
+ if (!ret)
+ return -EIO;
+
+ set_bit(idx, common->keymap);
+ if (key->cipher == WLAN_CIPHER_SUITE_TKIP) {
+ set_bit(idx + 64, common->keymap);
+ set_bit(idx, common->tkip_keymap);
+ set_bit(idx + 64, common->tkip_keymap);
+ if (!(common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED)) {
+ set_bit(idx + 32, common->keymap);
+ set_bit(idx + 64 + 32, common->keymap);
+ set_bit(idx + 32, common->tkip_keymap);
+ set_bit(idx + 64 + 32, common->tkip_keymap);
+ }
+ }
+
+ return idx;
+}
+EXPORT_SYMBOL(ath_key_config);
+
+/*
+ * Delete Key.
+ */
+void ath_key_delete(struct ath_common *common, struct ieee80211_key_conf *key)
+{
+ ath_hw_keyreset(common, key->hw_key_idx);
+ if (key->hw_key_idx < IEEE80211_WEP_NKID)
+ return;
+
+ clear_bit(key->hw_key_idx, common->keymap);
+ if (key->cipher != WLAN_CIPHER_SUITE_TKIP)
+ return;
+
+ clear_bit(key->hw_key_idx + 64, common->keymap);
+
+ clear_bit(key->hw_key_idx, common->tkip_keymap);
+ clear_bit(key->hw_key_idx + 64, common->tkip_keymap);
+
+ if (!(common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED)) {
+ ath_hw_keyreset(common, key->hw_key_idx + 32);
+ clear_bit(key->hw_key_idx + 32, common->keymap);
+ clear_bit(key->hw_key_idx + 64 + 32, common->keymap);
+
+ clear_bit(key->hw_key_idx + 32, common->tkip_keymap);
+ clear_bit(key->hw_key_idx + 64 + 32, common->tkip_keymap);
+ }
+}
+EXPORT_SYMBOL(ath_key_delete);
diff --git a/drivers/net/wireless/ath/reg.h b/drivers/net/wireless/ath/reg.h
index dfe1fbec24f5..298e53f3fa48 100644
--- a/drivers/net/wireless/ath/reg.h
+++ b/drivers/net/wireless/ath/reg.h
@@ -17,6 +17,12 @@
#ifndef ATH_REGISTERS_H
#define ATH_REGISTERS_H
+#define AR_MIBC 0x0040
+#define AR_MIBC_COW 0x00000001
+#define AR_MIBC_FMC 0x00000002
+#define AR_MIBC_CMC 0x00000004
+#define AR_MIBC_MCS 0x00000008
+
/*
* BSSID mask registers. See ath_hw_set_bssid_mask()
* for detailed documentation about these registers.
@@ -24,4 +30,32 @@
#define AR_BSSMSKL 0x80e0
#define AR_BSSMSKU 0x80e4
+#define AR_TFCNT 0x80ec
+#define AR_RFCNT 0x80f0
+#define AR_RCCNT 0x80f4
+#define AR_CCCNT 0x80f8
+
+#define AR_KEYTABLE_0 0x8800
+#define AR_KEYTABLE(_n) (AR_KEYTABLE_0 + ((_n)*32))
+#define AR_KEY_CACHE_SIZE 128
+#define AR_RSVD_KEYTABLE_ENTRIES 4
+#define AR_KEY_TYPE 0x00000007
+#define AR_KEYTABLE_TYPE_40 0x00000000
+#define AR_KEYTABLE_TYPE_104 0x00000001
+#define AR_KEYTABLE_TYPE_128 0x00000003
+#define AR_KEYTABLE_TYPE_TKIP 0x00000004
+#define AR_KEYTABLE_TYPE_AES 0x00000005
+#define AR_KEYTABLE_TYPE_CCM 0x00000006
+#define AR_KEYTABLE_TYPE_CLR 0x00000007
+#define AR_KEYTABLE_ANT 0x00000008
+#define AR_KEYTABLE_VALID 0x00008000
+#define AR_KEYTABLE_KEY0(_n) (AR_KEYTABLE(_n) + 0)
+#define AR_KEYTABLE_KEY1(_n) (AR_KEYTABLE(_n) + 4)
+#define AR_KEYTABLE_KEY2(_n) (AR_KEYTABLE(_n) + 8)
+#define AR_KEYTABLE_KEY3(_n) (AR_KEYTABLE(_n) + 12)
+#define AR_KEYTABLE_KEY4(_n) (AR_KEYTABLE(_n) + 16)
+#define AR_KEYTABLE_TYPE(_n) (AR_KEYTABLE(_n) + 20)
+#define AR_KEYTABLE_MAC0(_n) (AR_KEYTABLE(_n) + 24)
+#define AR_KEYTABLE_MAC1(_n) (AR_KEYTABLE(_n) + 28)
+
#endif /* ATH_REGISTERS_H */
diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c
index 3b632161c106..c96e19da2949 100644
--- a/drivers/net/wireless/atmel_cs.c
+++ b/drivers/net/wireless/atmel_cs.c
@@ -42,7 +42,6 @@
#include <linux/moduleparam.h>
#include <linux/device.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/ds.h>
@@ -64,58 +63,21 @@ MODULE_SUPPORTED_DEVICE("Atmel at76c50x PCMCIA cards");
/*====================================================================*/
-/*
- The event() function is this driver's Card Services event handler.
- It will be called by Card Services when an appropriate card status
- event is received. The config() and release() entry points are
- used to configure or release a socket, in response to card
- insertion and ejection events. They are invoked from the atmel_cs
- event handler.
-*/
-
static int atmel_config(struct pcmcia_device *link);
static void atmel_release(struct pcmcia_device *link);
-/*
- The attach() and detach() entry points are used to create and destroy
- "instances" of the driver, where each instance represents everything
- needed to manage one actual PCMCIA card.
-*/
-
static void atmel_detach(struct pcmcia_device *p_dev);
typedef struct local_info_t {
struct net_device *eth_dev;
} local_info_t;
-/*======================================================================
-
- atmel_attach() creates an "instance" of the driver, allocating
- local data structures for one device. The device is registered
- with Card Services.
-
- The dev_link structure is initialized, but we don't actually
- configure the card at this point -- we wait until we receive a
- card insertion event.
-
- ======================================================================*/
-
static int atmel_probe(struct pcmcia_device *p_dev)
{
local_info_t *local;
dev_dbg(&p_dev->dev, "atmel_attach()\n");
- /*
- General socket configuration defaults can go here. In this
- client, we assume very little, and rely on the CIS for almost
- everything. In most clients, many details (i.e., number, sizes,
- and attributes of IO windows) are fixed by the nature of the
- device, and can be hard-wired here.
- */
- p_dev->conf.Attributes = 0;
- p_dev->conf.IntType = INT_MEMORY_AND_IO;
-
/* Allocate space for private device-specific data */
local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
if (!local) {
@@ -127,15 +89,6 @@ static int atmel_probe(struct pcmcia_device *p_dev)
return atmel_config(p_dev);
} /* atmel_attach */
-/*======================================================================
-
- This deletes a driver "instance". The device is de-registered
- with Card Services. If it has been released, all local data
- structures are freed. Otherwise, the structures will be freed
- when the device is released.
-
- ======================================================================*/
-
static void atmel_detach(struct pcmcia_device *link)
{
dev_dbg(&link->dev, "atmel_detach\n");
@@ -145,14 +98,6 @@ static void atmel_detach(struct pcmcia_device *link)
kfree(link->priv);
}
-/*======================================================================
-
- atmel_config() is scheduled to run after a CARD_INSERTION event
- is received, to configure the PCMCIA socket, and to make the
- device available to the system.
-
- ======================================================================*/
-
/* Call-back function to interrogate PCMCIA-specific information
about the current existance of the card */
static int card_present(void *arg)
@@ -165,47 +110,11 @@ static int card_present(void *arg)
return 0;
}
-static int atmel_config_check(struct pcmcia_device *p_dev,
- cistpl_cftable_entry_t *cfg,
- cistpl_cftable_entry_t *dflt,
- unsigned int vcc,
- void *priv_data)
+static int atmel_config_check(struct pcmcia_device *p_dev, void *priv_data)
{
- if (cfg->index == 0)
- return -ENODEV;
-
- /* Does this card need audio output? */
- if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
- p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
- p_dev->conf.Status = CCSR_AUDIO_ENA;
- }
+ if (p_dev->config_index == 0)
+ return -EINVAL;
- /* Use power settings for Vcc and Vpp if present */
- /* Note that the CIS values need to be rescaled */
- if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
- p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
- else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM))
- p_dev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM]/10000;
-
- p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
-
- /* IO window settings */
- p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
- if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
- cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
- p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
- p_dev->resource[0]->flags |=
- pcmcia_io_cfg_data_width(io->flags);
- p_dev->resource[0]->start = io->win[0].base;
- p_dev->resource[0]->end = io->win[0].len;
- if (io->nwin > 1) {
- p_dev->resource[1]->flags = p_dev->resource[0]->flags;
- p_dev->resource[1]->start = io->win[1].base;
- p_dev->resource[1]->end = io->win[1].len;
- }
- }
-
- /* This reserves IO space but doesn't actually enable it */
return pcmcia_request_io(p_dev);
}
@@ -220,18 +129,9 @@ static int atmel_config(struct pcmcia_device *link)
dev_dbg(&link->dev, "atmel_config\n");
- /*
- In this loop, we scan the CIS for configuration table entries,
- each of which describes a valid card configuration, including
- voltage, IO window, memory window, and interrupt settings.
-
- We make no assumptions about the card to be configured: we use
- just the information available in the CIS. In an ideal world,
- this would work for any PCMCIA card, but it requires a complete
- and accurate CIS. In practice, a driver usually "knows" most of
- these things without consulting the CIS, and most client drivers
- will only use the CIS to fill in implementation-defined details.
- */
+ link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP |
+ CONF_AUTO_AUDIO | CONF_AUTO_SET_IO;
+
if (pcmcia_loop_config(link, atmel_config_check, NULL))
goto failed;
@@ -240,12 +140,7 @@ static int atmel_config(struct pcmcia_device *link)
goto failed;
}
- /*
- This actually configures the PCMCIA socket -- setting up
- the I/O windows and the interrupt mapping, and putting the
- card and host interface into "Memory and IO" mode.
- */
- ret = pcmcia_request_configuration(link, &link->conf);
+ ret = pcmcia_enable_device(link);
if (ret)
goto failed;
@@ -267,14 +162,6 @@ static int atmel_config(struct pcmcia_device *link)
return -ENODEV;
}
-/*======================================================================
-
- After a card is removed, atmel_release() will unregister the
- device, and release the PCMCIA configuration. If the device is
- still open, this will be postponed until it is closed.
-
- ======================================================================*/
-
static void atmel_release(struct pcmcia_device *link)
{
struct net_device *dev = ((local_info_t*)link->priv)->eth_dev;
@@ -353,9 +240,7 @@ MODULE_DEVICE_TABLE(pcmcia, atmel_ids);
static struct pcmcia_driver atmel_driver = {
.owner = THIS_MODULE,
- .drv = {
- .name = "atmel_cs",
- },
+ .name = "atmel_cs",
.probe = atmel_probe,
.remove = atmel_detach,
.id_table = atmel_ids,
@@ -363,12 +248,12 @@ static struct pcmcia_driver atmel_driver = {
.resume = atmel_resume,
};
-static int atmel_cs_init(void)
+static int __init atmel_cs_init(void)
{
return pcmcia_register_driver(&atmel_driver);
}
-static void atmel_cs_cleanup(void)
+static void __exit atmel_cs_cleanup(void)
{
pcmcia_unregister_driver(&atmel_driver);
}
diff --git a/drivers/net/wireless/b43/Makefile b/drivers/net/wireless/b43/Makefile
index 5e83b6f0a3a0..69d4af09a6cb 100644
--- a/drivers/net/wireless/b43/Makefile
+++ b/drivers/net/wireless/b43/Makefile
@@ -1,6 +1,8 @@
b43-y += main.o
b43-y += tables.o
b43-$(CONFIG_B43_NPHY) += tables_nphy.o
+b43-$(CONFIG_B43_NPHY) += radio_2055.o
+b43-$(CONFIG_B43_NPHY) += radio_2056.o
b43-y += phy_common.o
b43-y += phy_g.o
b43-y += phy_a.o
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h
index 8674a99356af..72821c456b02 100644
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
@@ -186,7 +186,8 @@ enum {
#define B43_SHM_SH_PHYTXNOI 0x006E /* PHY noise directly after TX (lower 8bit only) */
#define B43_SHM_SH_RFRXSP1 0x0072 /* RF RX SP Register 1 */
#define B43_SHM_SH_CHAN 0x00A0 /* Current channel (low 8bit only) */
-#define B43_SHM_SH_CHAN_5GHZ 0x0100 /* Bit set, if 5Ghz channel */
+#define B43_SHM_SH_CHAN_5GHZ 0x0100 /* Bit set, if 5 Ghz channel */
+#define B43_SHM_SH_CHAN_40MHZ 0x0200 /* Bit set, if 40 Mhz channel width */
#define B43_SHM_SH_BCMCFIFOID 0x0108 /* Last posted cookie to the bcast/mcast FIFO */
/* TSSI information */
#define B43_SHM_SH_TSSI_CCK 0x0058 /* TSSI for last 4 CCK frames (32bit) */
diff --git a/drivers/net/wireless/b43/debugfs.c b/drivers/net/wireless/b43/debugfs.c
index 80b19a44a407..59f59fa40334 100644
--- a/drivers/net/wireless/b43/debugfs.c
+++ b/drivers/net/wireless/b43/debugfs.c
@@ -627,6 +627,7 @@ out_unlock:
.open = b43_debugfs_open, \
.read = b43_debugfs_read, \
.write = b43_debugfs_write, \
+ .llseek = generic_file_llseek, \
}, \
.file_struct_offset = offsetof(struct b43_dfsentry, \
file_##name), \
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 20631ae2ddd7..a1186525c70d 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -2280,6 +2280,7 @@ out:
static int b43_upload_microcode(struct b43_wldev *dev)
{
+ struct wiphy *wiphy = dev->wl->hw->wiphy;
const size_t hdr_len = sizeof(struct b43_fw_header);
const __be32 *data;
unsigned int i, len;
@@ -2405,6 +2406,10 @@ static int b43_upload_microcode(struct b43_wldev *dev)
}
}
+ snprintf(wiphy->fw_version, sizeof(wiphy->fw_version), "%u.%u",
+ dev->fw.rev, dev->fw.patch);
+ wiphy->hw_version = dev->dev->id.coreid;
+
if (b43_is_old_txhdr_format(dev)) {
/* We're over the deadline, but we keep support for old fw
* until it turns out to be in major conflict with something new. */
@@ -3754,17 +3759,17 @@ static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
}
err = -EINVAL;
- switch (key->alg) {
- case ALG_WEP:
- if (key->keylen == WLAN_KEY_LEN_WEP40)
- algorithm = B43_SEC_ALGO_WEP40;
- else
- algorithm = B43_SEC_ALGO_WEP104;
+ switch (key->cipher) {
+ case WLAN_CIPHER_SUITE_WEP40:
+ algorithm = B43_SEC_ALGO_WEP40;
+ break;
+ case WLAN_CIPHER_SUITE_WEP104:
+ algorithm = B43_SEC_ALGO_WEP104;
break;
- case ALG_TKIP:
+ case WLAN_CIPHER_SUITE_TKIP:
algorithm = B43_SEC_ALGO_TKIP;
break;
- case ALG_CCMP:
+ case WLAN_CIPHER_SUITE_CCMP:
algorithm = B43_SEC_ALGO_AES;
break;
default:
@@ -4250,6 +4255,10 @@ static void b43_wireless_core_exit(struct b43_wldev *dev)
B43_WARN_ON(dev && b43_status(dev) > B43_STAT_INITIALIZED);
if (!dev || b43_status(dev) != B43_STAT_INITIALIZED)
return;
+
+ /* Unregister HW RNG driver */
+ b43_rng_exit(dev->wl);
+
b43_set_status(dev, B43_STAT_UNINIT);
/* Stop the microcode PSM. */
@@ -4379,6 +4388,9 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
b43_set_status(dev, B43_STAT_INITIALIZED);
+ /* Register HW RNG driver */
+ b43_rng_init(dev->wl);
+
out:
return err;
@@ -4984,7 +4996,6 @@ static int b43_probe(struct ssb_device *dev, const struct ssb_device_id *id)
if (err)
goto err_one_core_detach;
b43_leds_register(wl->current_dev);
- b43_rng_init(wl);
}
out:
@@ -5020,7 +5031,6 @@ static void b43_remove(struct ssb_device *dev)
b43_one_core_detach(dev);
if (list_empty(&wl->devlist)) {
- b43_rng_exit(wl);
b43_leds_unregister(wl);
/* Last core on the chip unregistered.
* We can destroy common struct b43_wl.
diff --git a/drivers/net/wireless/b43/pcmcia.c b/drivers/net/wireless/b43/pcmcia.c
index dfbc41d431ff..7dcba5fafdc7 100644
--- a/drivers/net/wireless/b43/pcmcia.c
+++ b/drivers/net/wireless/b43/pcmcia.c
@@ -26,7 +26,6 @@
#include <linux/ssb/ssb.h>
#include <linux/slab.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ciscode.h>
#include <pcmcia/ds.h>
@@ -63,7 +62,6 @@ static int b43_pcmcia_resume(struct pcmcia_device *dev)
static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev)
{
struct ssb_bus *ssb;
- win_req_t win;
int err = -ENOMEM;
int res = 0;
@@ -73,30 +71,28 @@ static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev)
err = -ENODEV;
- dev->conf.Attributes = CONF_ENABLE_IRQ;
- dev->conf.IntType = INT_MEMORY_AND_IO;
+ dev->config_flags |= CONF_ENABLE_IRQ;
- win.Attributes = WIN_ENABLE | WIN_DATA_WIDTH_16 |
+ dev->resource[2]->flags |= WIN_ENABLE | WIN_DATA_WIDTH_16 |
WIN_USE_WAIT;
- win.Base = 0;
- win.Size = SSB_CORE_SIZE;
- win.AccessSpeed = 250;
- res = pcmcia_request_window(dev, &win, &dev->win);
+ dev->resource[2]->start = 0;
+ dev->resource[2]->end = SSB_CORE_SIZE;
+ res = pcmcia_request_window(dev, dev->resource[2], 250);
if (res != 0)
goto err_kfree_ssb;
- res = pcmcia_map_mem_page(dev, dev->win, 0);
+ res = pcmcia_map_mem_page(dev, dev->resource[2], 0);
if (res != 0)
goto err_disable;
if (!dev->irq)
goto err_disable;
- res = pcmcia_request_configuration(dev, &dev->conf);
+ res = pcmcia_enable_device(dev);
if (res != 0)
goto err_disable;
- err = ssb_bus_pcmciabus_register(ssb, dev, win.Base);
+ err = ssb_bus_pcmciabus_register(ssb, dev, dev->resource[2]->start);
if (err)
goto err_disable;
dev->priv = ssb;
@@ -125,9 +121,7 @@ static void __devexit b43_pcmcia_remove(struct pcmcia_device *dev)
static struct pcmcia_driver b43_pcmcia_driver = {
.owner = THIS_MODULE,
- .drv = {
- .name = "b43-pcmcia",
- },
+ .name = "b43-pcmcia",
.id_table = b43_pcmcia_tbl,
.probe = b43_pcmcia_probe,
.remove = __devexit_p(b43_pcmcia_remove),
diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c
index 8f7d7eff2d80..7b2ea6781457 100644
--- a/drivers/net/wireless/b43/phy_common.c
+++ b/drivers/net/wireless/b43/phy_common.c
@@ -294,8 +294,10 @@ int b43_switch_channel(struct b43_wldev *dev, unsigned int new_channel)
*/
channelcookie = new_channel;
if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ)
- channelcookie |= 0x100;
- //FIXME set 40Mhz flag if required
+ channelcookie |= B43_SHM_SH_CHAN_5GHZ;
+ /* FIXME: set 40Mhz flag if required */
+ if (0)
+ channelcookie |= B43_SHM_SH_CHAN_40MHZ;
savedcookie = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_CHAN);
b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_CHAN, channelcookie);
diff --git a/drivers/net/wireless/b43/phy_common.h b/drivers/net/wireless/b43/phy_common.h
index bd480b481bfc..0e6194228845 100644
--- a/drivers/net/wireless/b43/phy_common.h
+++ b/drivers/net/wireless/b43/phy_common.h
@@ -2,6 +2,7 @@
#define LINUX_B43_PHY_COMMON_H_
#include <linux/types.h>
+#include <linux/nl80211.h>
struct b43_wldev;
@@ -250,8 +251,10 @@ struct b43_phy {
* check is needed. */
unsigned long next_txpwr_check_time;
- /* current channel */
+ /* Current channel */
unsigned int channel;
+ u16 channel_freq;
+ enum nl80211_channel_type channel_type;
/* PHY TX errors counter. */
atomic_t txerr_cnt;
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c
index 5a725703770c..dfec5496055e 100644
--- a/drivers/net/wireless/b43/phy_n.c
+++ b/drivers/net/wireless/b43/phy_n.c
@@ -29,6 +29,8 @@
#include "b43.h"
#include "phy_n.h"
#include "tables_nphy.h"
+#include "radio_2055.h"
+#include "radio_2056.h"
#include "main.h"
struct nphy_txgains {
@@ -73,21 +75,12 @@ static void b43_nphy_rf_control_override(struct b43_wldev *dev, u16 field,
u16 value, u8 core, bool off);
static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field,
u16 value, u8 core);
-static int nphy_channel_switch(struct b43_wldev *dev, unsigned int channel);
-static inline bool b43_empty_chanspec(struct b43_chanspec *chanspec)
+static inline bool b43_channel_type_is_40mhz(
+ enum nl80211_channel_type channel_type)
{
- return !chanspec->channel && !chanspec->sideband &&
- !chanspec->b_width && !chanspec->b_freq;
-}
-
-static inline bool b43_eq_chanspecs(struct b43_chanspec *chanspec1,
- struct b43_chanspec *chanspec2)
-{
- return (chanspec1->channel == chanspec2->channel &&
- chanspec1->sideband == chanspec2->sideband &&
- chanspec1->b_width == chanspec2->b_width &&
- chanspec1->b_freq == chanspec2->b_freq);
+ return (channel_type == NL80211_CHAN_HT40MINUS ||
+ channel_type == NL80211_CHAN_HT40PLUS);
}
void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna)
@@ -223,7 +216,7 @@ static void b43_radio_init2055_post(struct b43_wldev *dev)
if (i)
b43err(dev->wl, "radio post init timeout\n");
b43_radio_mask(dev, B2055_CAL_LPOCTL, 0xFF7F);
- nphy_channel_switch(dev, dev->phy.channel);
+ b43_switch_channel(dev, dev->phy.channel);
b43_radio_write(dev, B2055_C1_RX_BB_LPF, 0x9);
b43_radio_write(dev, B2055_C2_RX_BB_LPF, 0x9);
b43_radio_write(dev, B2055_C1_RX_BB_MIDACHP, 0x83);
@@ -782,7 +775,7 @@ static void b43_nphy_spur_workaround(struct b43_wldev *dev)
{
struct b43_phy_n *nphy = dev->phy.n;
- u8 channel = nphy->radio_chanspec.channel;
+ u8 channel = dev->phy.channel;
int tone[2] = { 57, 58 };
u32 noise[2] = { 0x3FF, 0x3FF };
@@ -856,9 +849,9 @@ static void b43_nphy_adjust_lna_gain_table(struct b43_wldev *dev)
gain[0] = 6;
gain[1] = 6;
} else {
- tmp = 40370 - 315 * nphy->radio_chanspec.channel;
+ tmp = 40370 - 315 * dev->phy.channel;
gain[0] = ((tmp >> 13) + ((tmp >> 12) & 1));
- tmp = 23242 - 224 * nphy->radio_chanspec.channel;
+ tmp = 23242 - 224 * dev->phy.channel;
gain[1] = ((tmp >> 13) + ((tmp >> 12) & 1));
}
} else {
@@ -893,7 +886,7 @@ static void b43_nphy_adjust_lna_gain_table(struct b43_wldev *dev)
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/WorkaroundsGainCtrl */
-static void b43_nphy_gain_crtl_workarounds(struct b43_wldev *dev)
+static void b43_nphy_gain_ctrl_workarounds(struct b43_wldev *dev)
{
struct b43_phy_n *nphy = dev->phy.n;
u8 i, j;
@@ -1094,11 +1087,12 @@ static void b43_nphy_workarounds(struct b43_wldev *dev)
b43_nphy_set_rf_sequence(dev, 0, events1, delays1, 7);
b43_nphy_set_rf_sequence(dev, 1, events2, delays2, 7);
- b43_nphy_gain_crtl_workarounds(dev);
+ b43_nphy_gain_ctrl_workarounds(dev);
if (dev->phy.rev < 2) {
if (b43_phy_read(dev, B43_NPHY_RXCTL) & 0x2)
- ; /*TODO: b43_mhf(dev, 2, 0x0010, 0x0010, 3);*/
+ b43_hf_write(dev, b43_hf_read(dev) |
+ B43_HF_MLADVW);
} else if (dev->phy.rev == 2) {
b43_phy_write(dev, B43_NPHY_CRSCHECK2, 0);
b43_phy_write(dev, B43_NPHY_CRSCHECK3, 0);
@@ -1182,7 +1176,7 @@ static u16 b43_nphy_gen_load_samples(struct b43_wldev *dev, u32 freq, u16 max,
len = bw << 1;
}
- samples = kzalloc(len * sizeof(struct b43_c32), GFP_KERNEL);
+ samples = kcalloc(len, sizeof(struct b43_c32), GFP_KERNEL);
if (!samples) {
b43err(dev->wl, "allocation for samples generation failed\n");
return 0;
@@ -2083,12 +2077,12 @@ static void b43_nphy_restore_rssi_cal(struct b43_wldev *dev)
u16 *rssical_phy_regs = NULL;
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
- if (b43_empty_chanspec(&nphy->rssical_chanspec_2G))
+ if (!nphy->rssical_chanspec_2G.center_freq)
return;
rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_2G;
rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_2G;
} else {
- if (b43_empty_chanspec(&nphy->rssical_chanspec_5G))
+ if (!nphy->rssical_chanspec_5G.center_freq)
return;
rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_5G;
rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G;
@@ -2544,8 +2538,9 @@ static void b43_nphy_save_cal(struct b43_wldev *dev)
txcal_radio_regs[2] = b43_radio_read(dev, 0x8D);
txcal_radio_regs[3] = b43_radio_read(dev, 0xBC);
}
- *iqcal_chanspec = nphy->radio_chanspec;
- b43_ntab_write_bulk(dev, B43_NTAB16(15, 80), 8, table);
+ iqcal_chanspec->center_freq = dev->phy.channel_freq;
+ iqcal_chanspec->channel_type = dev->phy.channel_type;
+ b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 8, table);
if (nphy->hang_avoid)
b43_nphy_stay_in_carrier_search(dev, 0);
@@ -2565,12 +2560,12 @@ static void b43_nphy_restore_cal(struct b43_wldev *dev)
struct b43_phy_n_iq_comp *rxcal_coeffs = NULL;
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
- if (b43_empty_chanspec(&nphy->iqcal_chanspec_2G))
+ if (!nphy->iqcal_chanspec_2G.center_freq)
return;
table = nphy->cal_cache.txcal_coeffs_2G;
loft = &nphy->cal_cache.txcal_coeffs_2G[5];
} else {
- if (b43_empty_chanspec(&nphy->iqcal_chanspec_5G))
+ if (!nphy->iqcal_chanspec_5G.center_freq)
return;
table = nphy->cal_cache.txcal_coeffs_5G;
loft = &nphy->cal_cache.txcal_coeffs_5G[5];
@@ -2815,7 +2810,10 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev,
b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length,
nphy->txiqlocal_bestc);
nphy->txiqlocal_coeffsvalid = true;
- nphy->txiqlocal_chanspec = nphy->radio_chanspec;
+ nphy->txiqlocal_chanspec.center_freq =
+ dev->phy.channel_freq;
+ nphy->txiqlocal_chanspec.channel_type =
+ dev->phy.channel_type;
} else {
length = 11;
if (dev->phy.rev < 3)
@@ -2851,7 +2849,8 @@ static void b43_nphy_reapply_tx_cal_coeffs(struct b43_wldev *dev)
bool equal = true;
if (!nphy->txiqlocal_coeffsvalid ||
- b43_eq_chanspecs(&nphy->txiqlocal_chanspec, &nphy->radio_chanspec))
+ nphy->txiqlocal_chanspec.center_freq != dev->phy.channel_freq ||
+ nphy->txiqlocal_chanspec.channel_type != dev->phy.channel_type)
return;
b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 7, buffer);
@@ -3073,6 +3072,57 @@ static int b43_nphy_cal_rx_iq(struct b43_wldev *dev,
return b43_nphy_rev2_cal_rx_iq(dev, target, type, debug);
}
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/MacPhyClkSet */
+static void b43_nphy_mac_phy_clock_set(struct b43_wldev *dev, bool on)
+{
+ u32 tmslow = ssb_read32(dev->dev, SSB_TMSLOW);
+ if (on)
+ tmslow |= SSB_TMSLOW_PHYCLK;
+ else
+ tmslow &= ~SSB_TMSLOW_PHYCLK;
+ ssb_write32(dev->dev, SSB_TMSLOW, tmslow);
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCoreSetState */
+static void b43_nphy_set_rx_core_state(struct b43_wldev *dev, u8 mask)
+{
+ struct b43_phy *phy = &dev->phy;
+ struct b43_phy_n *nphy = phy->n;
+ u16 buf[16];
+
+ nphy->phyrxchain = mask;
+
+ if (0 /* FIXME clk */)
+ return;
+
+ b43_mac_suspend(dev);
+
+ if (nphy->hang_avoid)
+ b43_nphy_stay_in_carrier_search(dev, true);
+
+ b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_RXEN,
+ (mask & 0x3) << B43_NPHY_RFSEQCA_RXEN_SHIFT);
+
+ if ((mask & 0x3) != 0x3) {
+ b43_phy_write(dev, B43_NPHY_HPANT_SWTHRES, 1);
+ if (dev->phy.rev >= 3) {
+ /* TODO */
+ }
+ } else {
+ b43_phy_write(dev, B43_NPHY_HPANT_SWTHRES, 0x1E);
+ if (dev->phy.rev >= 3) {
+ /* TODO */
+ }
+ }
+
+ b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
+
+ if (nphy->hang_avoid)
+ b43_nphy_stay_in_carrier_search(dev, false);
+
+ b43_mac_enable(dev);
+}
+
/*
* Init N-PHY
* http://bcm-v4.sipsolutions.net/802.11/PHY/Init/N
@@ -3173,7 +3223,7 @@ int b43_phy_initn(struct b43_wldev *dev)
b43_phy_write(dev, B43_NPHY_BBCFG, tmp & ~B43_NPHY_BBCFG_RSTCCA);
b43_nphy_bmac_clock_fgc(dev, 0);
- /* TODO N PHY MAC PHY Clock Set with argument 1 */
+ b43_nphy_mac_phy_clock_set(dev, true);
b43_nphy_pa_override(dev, false);
b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX);
@@ -3199,18 +3249,16 @@ int b43_phy_initn(struct b43_wldev *dev)
}
if (nphy->phyrxchain != 3)
- ;/* TODO N PHY RX Core Set State with phyrxchain as argument */
+ b43_nphy_set_rx_core_state(dev, nphy->phyrxchain);
if (nphy->mphase_cal_phase_id > 0)
;/* TODO PHY Periodic Calibration Multi-Phase Restart */
do_rssi_cal = false;
if (phy->rev >= 3) {
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
- do_rssi_cal =
- b43_empty_chanspec(&nphy->rssical_chanspec_2G);
+ do_rssi_cal = !nphy->rssical_chanspec_2G.center_freq;
else
- do_rssi_cal =
- b43_empty_chanspec(&nphy->rssical_chanspec_5G);
+ do_rssi_cal = !nphy->rssical_chanspec_5G.center_freq;
if (do_rssi_cal)
b43_nphy_rssi_cal(dev);
@@ -3222,9 +3270,9 @@ int b43_phy_initn(struct b43_wldev *dev)
if (!((nphy->measure_hold & 0x6) != 0)) {
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
- do_cal = b43_empty_chanspec(&nphy->iqcal_chanspec_2G);
+ do_cal = !nphy->iqcal_chanspec_2G.center_freq;
else
- do_cal = b43_empty_chanspec(&nphy->iqcal_chanspec_5G);
+ do_cal = !nphy->iqcal_chanspec_5G.center_freq;
if (nphy->mute)
do_cal = false;
@@ -3272,24 +3320,25 @@ int b43_phy_initn(struct b43_wldev *dev)
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ChanspecSetup */
-static void b43_nphy_chanspec_setup(struct b43_wldev *dev,
+static void b43_nphy_channel_setup(struct b43_wldev *dev,
const struct b43_phy_n_sfo_cfg *e,
- struct b43_chanspec chanspec)
+ struct ieee80211_channel *new_channel)
{
struct b43_phy *phy = &dev->phy;
struct b43_phy_n *nphy = dev->phy.n;
- u16 tmp;
+ u16 old_band_5ghz;
u32 tmp32;
- tmp = b43_phy_read(dev, B43_NPHY_BANDCTL) & B43_NPHY_BANDCTL_5GHZ;
- if (chanspec.b_freq == 1 && tmp == 0) {
+ old_band_5ghz =
+ b43_phy_read(dev, B43_NPHY_BANDCTL) & B43_NPHY_BANDCTL_5GHZ;
+ if (new_channel->band == IEEE80211_BAND_5GHZ && !old_band_5ghz) {
tmp32 = b43_read32(dev, B43_MMIO_PSM_PHY_HDR);
b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32 | 4);
b43_phy_set(dev, B43_PHY_B_BBCFG, 0xC000);
b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32);
b43_phy_set(dev, B43_NPHY_BANDCTL, B43_NPHY_BANDCTL_5GHZ);
- } else if (chanspec.b_freq == 1) {
+ } else if (new_channel->band == IEEE80211_BAND_2GHZ && old_band_5ghz) {
b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ);
tmp32 = b43_read32(dev, B43_MMIO_PSM_PHY_HDR);
b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32 | 4);
@@ -3299,19 +3348,12 @@ static void b43_nphy_chanspec_setup(struct b43_wldev *dev,
b43_chantab_phy_upload(dev, e);
- tmp = chanspec.channel;
- if (chanspec.b_freq == 1)
- tmp |= 0x0100;
- if (chanspec.b_width == 3)
- tmp |= 0x0200;
- b43_shm_write16(dev, B43_SHM_SHARED, 0xA0, tmp);
-
- if (nphy->radio_chanspec.channel == 14) {
+ if (new_channel->hw_value == 14) {
b43_nphy_classifier(dev, 2, 0);
b43_phy_set(dev, B43_PHY_B_TEST, 0x0800);
} else {
b43_nphy_classifier(dev, 2, 2);
- if (chanspec.b_freq == 2)
+ if (new_channel->band == IEEE80211_BAND_2GHZ)
b43_phy_mask(dev, B43_PHY_B_TEST, ~0x840);
}
@@ -3334,70 +3376,62 @@ static void b43_nphy_chanspec_setup(struct b43_wldev *dev,
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetChanspec */
-static int b43_nphy_set_chanspec(struct b43_wldev *dev,
- struct b43_chanspec chanspec)
+static int b43_nphy_set_channel(struct b43_wldev *dev,
+ struct ieee80211_channel *channel,
+ enum nl80211_channel_type channel_type)
{
+ struct b43_phy *phy = &dev->phy;
struct b43_phy_n *nphy = dev->phy.n;
const struct b43_nphy_channeltab_entry_rev2 *tabent_r2;
const struct b43_nphy_channeltab_entry_rev3 *tabent_r3;
u8 tmp;
- u8 channel = chanspec.channel;
if (dev->phy.rev >= 3) {
- /* TODO */
+ tabent_r3 = b43_nphy_get_chantabent_rev3(dev,
+ channel->center_freq);
tabent_r3 = NULL;
if (!tabent_r3)
return -ESRCH;
} else {
- tabent_r2 = b43_nphy_get_chantabent_rev2(dev, channel);
+ tabent_r2 = b43_nphy_get_chantabent_rev2(dev,
+ channel->hw_value);
if (!tabent_r2)
return -ESRCH;
}
- nphy->radio_chanspec = chanspec;
+ /* Channel is set later in common code, but we need to set it on our
+ own to let this function's subcalls work properly. */
+ phy->channel = channel->hw_value;
+ phy->channel_freq = channel->center_freq;
- if (chanspec.b_width != nphy->b_width)
- ; /* TODO: BMAC BW Set (chanspec.b_width) */
+ if (b43_channel_type_is_40mhz(phy->channel_type) !=
+ b43_channel_type_is_40mhz(channel_type))
+ ; /* TODO: BMAC BW Set (channel_type) */
- /* TODO: use defines */
- if (chanspec.b_width == 3) {
- if (chanspec.sideband == 2)
- b43_phy_set(dev, B43_NPHY_RXCTL,
- B43_NPHY_RXCTL_BSELU20);
- else
- b43_phy_mask(dev, B43_NPHY_RXCTL,
- ~B43_NPHY_RXCTL_BSELU20);
- }
+ if (channel_type == NL80211_CHAN_HT40PLUS)
+ b43_phy_set(dev, B43_NPHY_RXCTL,
+ B43_NPHY_RXCTL_BSELU20);
+ else if (channel_type == NL80211_CHAN_HT40MINUS)
+ b43_phy_mask(dev, B43_NPHY_RXCTL,
+ ~B43_NPHY_RXCTL_BSELU20);
if (dev->phy.rev >= 3) {
- tmp = (chanspec.b_freq == 1) ? 4 : 0;
+ tmp = (channel->band == IEEE80211_BAND_5GHZ) ? 4 : 0;
b43_radio_maskset(dev, 0x08, 0xFFFB, tmp);
/* TODO: PHY Radio2056 Setup (dev, tabent_r3); */
- b43_nphy_chanspec_setup(dev, &(tabent_r3->phy_regs), chanspec);
+ b43_nphy_channel_setup(dev, &(tabent_r3->phy_regs), channel);
} else {
- tmp = (chanspec.b_freq == 1) ? 0x0020 : 0x0050;
+ tmp = (channel->band == IEEE80211_BAND_5GHZ) ? 0x0020 : 0x0050;
b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, tmp);
b43_radio_2055_setup(dev, tabent_r2);
- b43_nphy_chanspec_setup(dev, &(tabent_r2->phy_regs), chanspec);
+ b43_nphy_channel_setup(dev, &(tabent_r2->phy_regs), channel);
}
return 0;
}
-/* Tune the hardware to a new channel */
-static int nphy_channel_switch(struct b43_wldev *dev, unsigned int channel)
-{
- struct b43_phy_n *nphy = dev->phy.n;
-
- struct b43_chanspec chanspec;
- chanspec = nphy->radio_chanspec;
- chanspec.channel = channel;
-
- return b43_nphy_set_chanspec(dev, chanspec);
-}
-
static int b43_nphy_op_allocate(struct b43_wldev *dev)
{
struct b43_phy_n *nphy;
@@ -3518,7 +3552,7 @@ static void b43_nphy_op_software_rfkill(struct b43_wldev *dev,
} else {
if (dev->phy.rev >= 3) {
b43_radio_init2056(dev);
- b43_nphy_set_chanspec(dev, nphy->radio_chanspec);
+ b43_switch_channel(dev, dev->phy.channel);
} else {
b43_radio_init2055(dev);
}
@@ -3534,6 +3568,9 @@ static void b43_nphy_op_switch_analog(struct b43_wldev *dev, bool on)
static int b43_nphy_op_switch_channel(struct b43_wldev *dev,
unsigned int new_channel)
{
+ struct ieee80211_channel *channel = dev->wl->hw->conf.channel;
+ enum nl80211_channel_type channel_type = dev->wl->hw->conf.channel_type;
+
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
if ((new_channel < 1) || (new_channel > 14))
return -EINVAL;
@@ -3542,7 +3579,7 @@ static int b43_nphy_op_switch_channel(struct b43_wldev *dev,
return -EINVAL;
}
- return nphy_channel_switch(dev, new_channel);
+ return b43_nphy_set_channel(dev, channel, channel_type);
}
static unsigned int b43_nphy_op_get_default_chan(struct b43_wldev *dev)
diff --git a/drivers/net/wireless/b43/phy_n.h b/drivers/net/wireless/b43/phy_n.h
index 8b6d570dd0aa..c144e59a708b 100644
--- a/drivers/net/wireless/b43/phy_n.h
+++ b/drivers/net/wireless/b43/phy_n.h
@@ -714,223 +714,11 @@
#define B43_PHY_B_BBCFG B43_PHY_N_BMODE(0x001) /* BB config */
#define B43_PHY_B_TEST B43_PHY_N_BMODE(0x00A)
-
-/* Broadcom 2055 radio registers */
-
-#define B2055_GEN_SPARE 0x00 /* GEN spare */
-#define B2055_SP_PINPD 0x02 /* SP PIN PD */
-#define B2055_C1_SP_RSSI 0x03 /* SP RSSI Core 1 */
-#define B2055_C1_SP_PDMISC 0x04 /* SP PD MISC Core 1 */
-#define B2055_C2_SP_RSSI 0x05 /* SP RSSI Core 2 */
-#define B2055_C2_SP_PDMISC 0x06 /* SP PD MISC Core 2 */
-#define B2055_C1_SP_RXGC1 0x07 /* SP RX GC1 Core 1 */
-#define B2055_C1_SP_RXGC2 0x08 /* SP RX GC2 Core 1 */
-#define B2055_C2_SP_RXGC1 0x09 /* SP RX GC1 Core 2 */
-#define B2055_C2_SP_RXGC2 0x0A /* SP RX GC2 Core 2 */
-#define B2055_C1_SP_LPFBWSEL 0x0B /* SP LPF BW select Core 1 */
-#define B2055_C2_SP_LPFBWSEL 0x0C /* SP LPF BW select Core 2 */
-#define B2055_C1_SP_TXGC1 0x0D /* SP TX GC1 Core 1 */
-#define B2055_C1_SP_TXGC2 0x0E /* SP TX GC2 Core 1 */
-#define B2055_C2_SP_TXGC1 0x0F /* SP TX GC1 Core 2 */
-#define B2055_C2_SP_TXGC2 0x10 /* SP TX GC2 Core 2 */
-#define B2055_MASTER1 0x11 /* Master control 1 */
-#define B2055_MASTER2 0x12 /* Master control 2 */
-#define B2055_PD_LGEN 0x13 /* PD LGEN */
-#define B2055_PD_PLLTS 0x14 /* PD PLL TS */
-#define B2055_C1_PD_LGBUF 0x15 /* PD Core 1 LGBUF */
-#define B2055_C1_PD_TX 0x16 /* PD Core 1 TX */
-#define B2055_C1_PD_RXTX 0x17 /* PD Core 1 RXTX */
-#define B2055_C1_PD_RSSIMISC 0x18 /* PD Core 1 RSSI MISC */
-#define B2055_C2_PD_LGBUF 0x19 /* PD Core 2 LGBUF */
-#define B2055_C2_PD_TX 0x1A /* PD Core 2 TX */
-#define B2055_C2_PD_RXTX 0x1B /* PD Core 2 RXTX */
-#define B2055_C2_PD_RSSIMISC 0x1C /* PD Core 2 RSSI MISC */
-#define B2055_PWRDET_LGEN 0x1D /* PWRDET LGEN */
-#define B2055_C1_PWRDET_LGBUF 0x1E /* PWRDET LGBUF Core 1 */
-#define B2055_C1_PWRDET_RXTX 0x1F /* PWRDET RXTX Core 1 */
-#define B2055_C2_PWRDET_LGBUF 0x20 /* PWRDET LGBUF Core 2 */
-#define B2055_C2_PWRDET_RXTX 0x21 /* PWRDET RXTX Core 2 */
-#define B2055_RRCCAL_CS 0x22 /* RRCCAL Control spare */
-#define B2055_RRCCAL_NOPTSEL 0x23 /* RRCCAL N OPT SEL */
-#define B2055_CAL_MISC 0x24 /* CAL MISC */
-#define B2055_CAL_COUT 0x25 /* CAL Counter out */
-#define B2055_CAL_COUT2 0x26 /* CAL Counter out 2 */
-#define B2055_CAL_CVARCTL 0x27 /* CAL CVAR Control */
-#define B2055_CAL_RVARCTL 0x28 /* CAL RVAR Control */
-#define B2055_CAL_LPOCTL 0x29 /* CAL LPO Control */
-#define B2055_CAL_TS 0x2A /* CAL TS */
-#define B2055_CAL_RCCALRTS 0x2B /* CAL RCCAL READ TS */
-#define B2055_CAL_RCALRTS 0x2C /* CAL RCAL READ TS */
-#define B2055_PADDRV 0x2D /* PAD driver */
-#define B2055_XOCTL1 0x2E /* XO Control 1 */
-#define B2055_XOCTL2 0x2F /* XO Control 2 */
-#define B2055_XOREGUL 0x30 /* XO Regulator */
-#define B2055_XOMISC 0x31 /* XO misc */
-#define B2055_PLL_LFC1 0x32 /* PLL LF C1 */
-#define B2055_PLL_CALVTH 0x33 /* PLL CAL VTH */
-#define B2055_PLL_LFC2 0x34 /* PLL LF C2 */
-#define B2055_PLL_REF 0x35 /* PLL reference */
-#define B2055_PLL_LFR1 0x36 /* PLL LF R1 */
-#define B2055_PLL_PFDCP 0x37 /* PLL PFD CP */
-#define B2055_PLL_IDAC_CPOPAMP 0x38 /* PLL IDAC CPOPAMP */
-#define B2055_PLL_CPREG 0x39 /* PLL CP Regulator */
-#define B2055_PLL_RCAL 0x3A /* PLL RCAL */
-#define B2055_RF_PLLMOD0 0x3B /* RF PLL MOD0 */
-#define B2055_RF_PLLMOD1 0x3C /* RF PLL MOD1 */
-#define B2055_RF_MMDIDAC1 0x3D /* RF MMD IDAC 1 */
-#define B2055_RF_MMDIDAC0 0x3E /* RF MMD IDAC 0 */
-#define B2055_RF_MMDSP 0x3F /* RF MMD spare */
-#define B2055_VCO_CAL1 0x40 /* VCO cal 1 */
-#define B2055_VCO_CAL2 0x41 /* VCO cal 2 */
-#define B2055_VCO_CAL3 0x42 /* VCO cal 3 */
-#define B2055_VCO_CAL4 0x43 /* VCO cal 4 */
-#define B2055_VCO_CAL5 0x44 /* VCO cal 5 */
-#define B2055_VCO_CAL6 0x45 /* VCO cal 6 */
-#define B2055_VCO_CAL7 0x46 /* VCO cal 7 */
-#define B2055_VCO_CAL8 0x47 /* VCO cal 8 */
-#define B2055_VCO_CAL9 0x48 /* VCO cal 9 */
-#define B2055_VCO_CAL10 0x49 /* VCO cal 10 */
-#define B2055_VCO_CAL11 0x4A /* VCO cal 11 */
-#define B2055_VCO_CAL12 0x4B /* VCO cal 12 */
-#define B2055_VCO_CAL13 0x4C /* VCO cal 13 */
-#define B2055_VCO_CAL14 0x4D /* VCO cal 14 */
-#define B2055_VCO_CAL15 0x4E /* VCO cal 15 */
-#define B2055_VCO_CAL16 0x4F /* VCO cal 16 */
-#define B2055_VCO_KVCO 0x50 /* VCO KVCO */
-#define B2055_VCO_CAPTAIL 0x51 /* VCO CAP TAIL */
-#define B2055_VCO_IDACVCO 0x52 /* VCO IDAC VCO */
-#define B2055_VCO_REG 0x53 /* VCO Regulator */
-#define B2055_PLL_RFVTH 0x54 /* PLL RF VTH */
-#define B2055_LGBUF_CENBUF 0x55 /* LGBUF CEN BUF */
-#define B2055_LGEN_TUNE1 0x56 /* LGEN tune 1 */
-#define B2055_LGEN_TUNE2 0x57 /* LGEN tune 2 */
-#define B2055_LGEN_IDAC1 0x58 /* LGEN IDAC 1 */
-#define B2055_LGEN_IDAC2 0x59 /* LGEN IDAC 2 */
-#define B2055_LGEN_BIASC 0x5A /* LGEN BIAS counter */
-#define B2055_LGEN_BIASIDAC 0x5B /* LGEN BIAS IDAC */
-#define B2055_LGEN_RCAL 0x5C /* LGEN RCAL */
-#define B2055_LGEN_DIV 0x5D /* LGEN div */
-#define B2055_LGEN_SPARE2 0x5E /* LGEN spare 2 */
-#define B2055_C1_LGBUF_ATUNE 0x5F /* Core 1 LGBUF A tune */
-#define B2055_C1_LGBUF_GTUNE 0x60 /* Core 1 LGBUF G tune */
-#define B2055_C1_LGBUF_DIV 0x61 /* Core 1 LGBUF div */
-#define B2055_C1_LGBUF_AIDAC 0x62 /* Core 1 LGBUF A IDAC */
-#define B2055_C1_LGBUF_GIDAC 0x63 /* Core 1 LGBUF G IDAC */
-#define B2055_C1_LGBUF_IDACFO 0x64 /* Core 1 LGBUF IDAC filter override */
-#define B2055_C1_LGBUF_SPARE 0x65 /* Core 1 LGBUF spare */
-#define B2055_C1_RX_RFSPC1 0x66 /* Core 1 RX RF SPC1 */
-#define B2055_C1_RX_RFR1 0x67 /* Core 1 RX RF reg 1 */
-#define B2055_C1_RX_RFR2 0x68 /* Core 1 RX RF reg 2 */
-#define B2055_C1_RX_RFRCAL 0x69 /* Core 1 RX RF RCAL */
-#define B2055_C1_RX_BB_BLCMP 0x6A /* Core 1 RX Baseband BUFI LPF CMP */
-#define B2055_C1_RX_BB_LPF 0x6B /* Core 1 RX Baseband LPF */
-#define B2055_C1_RX_BB_MIDACHP 0x6C /* Core 1 RX Baseband MIDAC High-pass */
-#define B2055_C1_RX_BB_VGA1IDAC 0x6D /* Core 1 RX Baseband VGA1 IDAC */
-#define B2055_C1_RX_BB_VGA2IDAC 0x6E /* Core 1 RX Baseband VGA2 IDAC */
-#define B2055_C1_RX_BB_VGA3IDAC 0x6F /* Core 1 RX Baseband VGA3 IDAC */
-#define B2055_C1_RX_BB_BUFOCTL 0x70 /* Core 1 RX Baseband BUFO Control */
-#define B2055_C1_RX_BB_RCCALCTL 0x71 /* Core 1 RX Baseband RCCAL Control */
-#define B2055_C1_RX_BB_RSSICTL1 0x72 /* Core 1 RX Baseband RSSI Control 1 */
-#define B2055_C1_RX_BB_RSSICTL2 0x73 /* Core 1 RX Baseband RSSI Control 2 */
-#define B2055_C1_RX_BB_RSSICTL3 0x74 /* Core 1 RX Baseband RSSI Control 3 */
-#define B2055_C1_RX_BB_RSSICTL4 0x75 /* Core 1 RX Baseband RSSI Control 4 */
-#define B2055_C1_RX_BB_RSSICTL5 0x76 /* Core 1 RX Baseband RSSI Control 5 */
-#define B2055_C1_RX_BB_REG 0x77 /* Core 1 RX Baseband Regulator */
-#define B2055_C1_RX_BB_SPARE1 0x78 /* Core 1 RX Baseband spare 1 */
-#define B2055_C1_RX_TXBBRCAL 0x79 /* Core 1 RX TX BB RCAL */
-#define B2055_C1_TX_RF_SPGA 0x7A /* Core 1 TX RF SGM PGA */
-#define B2055_C1_TX_RF_SPAD 0x7B /* Core 1 TX RF SGM PAD */
-#define B2055_C1_TX_RF_CNTPGA1 0x7C /* Core 1 TX RF counter PGA 1 */
-#define B2055_C1_TX_RF_CNTPAD1 0x7D /* Core 1 TX RF counter PAD 1 */
-#define B2055_C1_TX_RF_PGAIDAC 0x7E /* Core 1 TX RF PGA IDAC */
-#define B2055_C1_TX_PGAPADTN 0x7F /* Core 1 TX PGA PAD TN */
-#define B2055_C1_TX_PADIDAC1 0x80 /* Core 1 TX PAD IDAC 1 */
-#define B2055_C1_TX_PADIDAC2 0x81 /* Core 1 TX PAD IDAC 2 */
-#define B2055_C1_TX_MXBGTRIM 0x82 /* Core 1 TX MX B/G TRIM */
-#define B2055_C1_TX_RF_RCAL 0x83 /* Core 1 TX RF RCAL */
-#define B2055_C1_TX_RF_PADTSSI1 0x84 /* Core 1 TX RF PAD TSSI1 */
-#define B2055_C1_TX_RF_PADTSSI2 0x85 /* Core 1 TX RF PAD TSSI2 */
-#define B2055_C1_TX_RF_SPARE 0x86 /* Core 1 TX RF spare */
-#define B2055_C1_TX_RF_IQCAL1 0x87 /* Core 1 TX RF I/Q CAL 1 */
-#define B2055_C1_TX_RF_IQCAL2 0x88 /* Core 1 TX RF I/Q CAL 2 */
-#define B2055_C1_TXBB_RCCAL 0x89 /* Core 1 TXBB RC CAL Control */
-#define B2055_C1_TXBB_LPF1 0x8A /* Core 1 TXBB LPF 1 */
-#define B2055_C1_TX_VOSCNCL 0x8B /* Core 1 TX VOS CNCL */
-#define B2055_C1_TX_LPF_MXGMIDAC 0x8C /* Core 1 TX LPF MXGM IDAC */
-#define B2055_C1_TX_BB_MXGM 0x8D /* Core 1 TX BB MXGM */
-#define B2055_C2_LGBUF_ATUNE 0x8E /* Core 2 LGBUF A tune */
-#define B2055_C2_LGBUF_GTUNE 0x8F /* Core 2 LGBUF G tune */
-#define B2055_C2_LGBUF_DIV 0x90 /* Core 2 LGBUF div */
-#define B2055_C2_LGBUF_AIDAC 0x91 /* Core 2 LGBUF A IDAC */
-#define B2055_C2_LGBUF_GIDAC 0x92 /* Core 2 LGBUF G IDAC */
-#define B2055_C2_LGBUF_IDACFO 0x93 /* Core 2 LGBUF IDAC filter override */
-#define B2055_C2_LGBUF_SPARE 0x94 /* Core 2 LGBUF spare */
-#define B2055_C2_RX_RFSPC1 0x95 /* Core 2 RX RF SPC1 */
-#define B2055_C2_RX_RFR1 0x96 /* Core 2 RX RF reg 1 */
-#define B2055_C2_RX_RFR2 0x97 /* Core 2 RX RF reg 2 */
-#define B2055_C2_RX_RFRCAL 0x98 /* Core 2 RX RF RCAL */
-#define B2055_C2_RX_BB_BLCMP 0x99 /* Core 2 RX Baseband BUFI LPF CMP */
-#define B2055_C2_RX_BB_LPF 0x9A /* Core 2 RX Baseband LPF */
-#define B2055_C2_RX_BB_MIDACHP 0x9B /* Core 2 RX Baseband MIDAC High-pass */
-#define B2055_C2_RX_BB_VGA1IDAC 0x9C /* Core 2 RX Baseband VGA1 IDAC */
-#define B2055_C2_RX_BB_VGA2IDAC 0x9D /* Core 2 RX Baseband VGA2 IDAC */
-#define B2055_C2_RX_BB_VGA3IDAC 0x9E /* Core 2 RX Baseband VGA3 IDAC */
-#define B2055_C2_RX_BB_BUFOCTL 0x9F /* Core 2 RX Baseband BUFO Control */
-#define B2055_C2_RX_BB_RCCALCTL 0xA0 /* Core 2 RX Baseband RCCAL Control */
-#define B2055_C2_RX_BB_RSSICTL1 0xA1 /* Core 2 RX Baseband RSSI Control 1 */
-#define B2055_C2_RX_BB_RSSICTL2 0xA2 /* Core 2 RX Baseband RSSI Control 2 */
-#define B2055_C2_RX_BB_RSSICTL3 0xA3 /* Core 2 RX Baseband RSSI Control 3 */
-#define B2055_C2_RX_BB_RSSICTL4 0xA4 /* Core 2 RX Baseband RSSI Control 4 */
-#define B2055_C2_RX_BB_RSSICTL5 0xA5 /* Core 2 RX Baseband RSSI Control 5 */
-#define B2055_C2_RX_BB_REG 0xA6 /* Core 2 RX Baseband Regulator */
-#define B2055_C2_RX_BB_SPARE1 0xA7 /* Core 2 RX Baseband spare 1 */
-#define B2055_C2_RX_TXBBRCAL 0xA8 /* Core 2 RX TX BB RCAL */
-#define B2055_C2_TX_RF_SPGA 0xA9 /* Core 2 TX RF SGM PGA */
-#define B2055_C2_TX_RF_SPAD 0xAA /* Core 2 TX RF SGM PAD */
-#define B2055_C2_TX_RF_CNTPGA1 0xAB /* Core 2 TX RF counter PGA 1 */
-#define B2055_C2_TX_RF_CNTPAD1 0xAC /* Core 2 TX RF counter PAD 1 */
-#define B2055_C2_TX_RF_PGAIDAC 0xAD /* Core 2 TX RF PGA IDAC */
-#define B2055_C2_TX_PGAPADTN 0xAE /* Core 2 TX PGA PAD TN */
-#define B2055_C2_TX_PADIDAC1 0xAF /* Core 2 TX PAD IDAC 1 */
-#define B2055_C2_TX_PADIDAC2 0xB0 /* Core 2 TX PAD IDAC 2 */
-#define B2055_C2_TX_MXBGTRIM 0xB1 /* Core 2 TX MX B/G TRIM */
-#define B2055_C2_TX_RF_RCAL 0xB2 /* Core 2 TX RF RCAL */
-#define B2055_C2_TX_RF_PADTSSI1 0xB3 /* Core 2 TX RF PAD TSSI1 */
-#define B2055_C2_TX_RF_PADTSSI2 0xB4 /* Core 2 TX RF PAD TSSI2 */
-#define B2055_C2_TX_RF_SPARE 0xB5 /* Core 2 TX RF spare */
-#define B2055_C2_TX_RF_IQCAL1 0xB6 /* Core 2 TX RF I/Q CAL 1 */
-#define B2055_C2_TX_RF_IQCAL2 0xB7 /* Core 2 TX RF I/Q CAL 2 */
-#define B2055_C2_TXBB_RCCAL 0xB8 /* Core 2 TXBB RC CAL Control */
-#define B2055_C2_TXBB_LPF1 0xB9 /* Core 2 TXBB LPF 1 */
-#define B2055_C2_TX_VOSCNCL 0xBA /* Core 2 TX VOS CNCL */
-#define B2055_C2_TX_LPF_MXGMIDAC 0xBB /* Core 2 TX LPF MXGM IDAC */
-#define B2055_C2_TX_BB_MXGM 0xBC /* Core 2 TX BB MXGM */
-#define B2055_PRG_GCHP21 0xBD /* PRG GC HPVGA23 21 */
-#define B2055_PRG_GCHP22 0xBE /* PRG GC HPVGA23 22 */
-#define B2055_PRG_GCHP23 0xBF /* PRG GC HPVGA23 23 */
-#define B2055_PRG_GCHP24 0xC0 /* PRG GC HPVGA23 24 */
-#define B2055_PRG_GCHP25 0xC1 /* PRG GC HPVGA23 25 */
-#define B2055_PRG_GCHP26 0xC2 /* PRG GC HPVGA23 26 */
-#define B2055_PRG_GCHP27 0xC3 /* PRG GC HPVGA23 27 */
-#define B2055_PRG_GCHP28 0xC4 /* PRG GC HPVGA23 28 */
-#define B2055_PRG_GCHP29 0xC5 /* PRG GC HPVGA23 29 */
-#define B2055_PRG_GCHP30 0xC6 /* PRG GC HPVGA23 30 */
-#define B2055_C1_LNA_GAINBST 0xCD /* Core 1 LNA GAINBST */
-#define B2055_C1_B0NB_RSSIVCM 0xD2 /* Core 1 B0 narrow-band RSSI VCM */
-#define B2055_C1_GENSPARE2 0xD6 /* Core 1 GEN spare 2 */
-#define B2055_C2_LNA_GAINBST 0xD9 /* Core 2 LNA GAINBST */
-#define B2055_C2_B0NB_RSSIVCM 0xDE /* Core 2 B0 narrow-band RSSI VCM */
-#define B2055_C2_GENSPARE2 0xE2 /* Core 2 GEN spare 2 */
-
-
-
struct b43_wldev;
struct b43_chanspec {
- u8 channel;
- u8 sideband;
- u8 b_width;
- u8 b_freq;
+ u16 center_freq;
+ enum nl80211_channel_type channel_type;
};
struct b43_phy_n_iq_comp {
@@ -984,8 +772,6 @@ struct b43_phy_n {
u16 papd_epsilon_offset[2];
s32 preamble_override;
u32 bb_mult_save;
- u8 b_width;
- struct b43_chanspec radio_chanspec;
bool gain_boost;
bool elna_gain_config;
diff --git a/drivers/net/wireless/b43/radio_2055.c b/drivers/net/wireless/b43/radio_2055.c
new file mode 100644
index 000000000000..1b5316586cbf
--- /dev/null
+++ b/drivers/net/wireless/b43/radio_2055.c
@@ -0,0 +1,1332 @@
+/*
+
+ Broadcom B43 wireless driver
+ IEEE 802.11n PHY and radio device data tables
+
+ Copyright (c) 2008 Michael Buesch <mb@bu3sch.de>
+
+ 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.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+
+#include "b43.h"
+#include "radio_2055.h"
+#include "phy_common.h"
+
+struct b2055_inittab_entry {
+ /* Value to write if we use the 5GHz band. */
+ u16 ghz5;
+ /* Value to write if we use the 2.4GHz band. */
+ u16 ghz2;
+ /* Flags */
+ u8 flags;
+#define B2055_INITTAB_ENTRY_OK 0x01
+#define B2055_INITTAB_UPLOAD 0x02
+};
+#define UPLOAD .flags = B2055_INITTAB_ENTRY_OK | B2055_INITTAB_UPLOAD
+#define NOUPLOAD .flags = B2055_INITTAB_ENTRY_OK
+
+static const struct b2055_inittab_entry b2055_inittab [] = {
+ [B2055_SP_PINPD] = { .ghz5 = 0x0080, .ghz2 = 0x0080, NOUPLOAD, },
+ [B2055_C1_SP_RSSI] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_C1_SP_PDMISC] = { .ghz5 = 0x0027, .ghz2 = 0x0027, NOUPLOAD, },
+ [B2055_C2_SP_RSSI] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_C2_SP_PDMISC] = { .ghz5 = 0x0027, .ghz2 = 0x0027, NOUPLOAD, },
+ [B2055_C1_SP_RXGC1] = { .ghz5 = 0x007F, .ghz2 = 0x007F, UPLOAD, },
+ [B2055_C1_SP_RXGC2] = { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, },
+ [B2055_C2_SP_RXGC1] = { .ghz5 = 0x007F, .ghz2 = 0x007F, UPLOAD, },
+ [B2055_C2_SP_RXGC2] = { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, },
+ [B2055_C1_SP_LPFBWSEL] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+ [B2055_C2_SP_LPFBWSEL] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+ [B2055_C1_SP_TXGC1] = { .ghz5 = 0x004F, .ghz2 = 0x004F, UPLOAD, },
+ [B2055_C1_SP_TXGC2] = { .ghz5 = 0x0005, .ghz2 = 0x0005, UPLOAD, },
+ [B2055_C2_SP_TXGC1] = { .ghz5 = 0x004F, .ghz2 = 0x004F, UPLOAD, },
+ [B2055_C2_SP_TXGC2] = { .ghz5 = 0x0005, .ghz2 = 0x0005, UPLOAD, },
+ [B2055_MASTER1] = { .ghz5 = 0x00D0, .ghz2 = 0x00D0, NOUPLOAD, },
+ [B2055_MASTER2] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+ [B2055_PD_LGEN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_PD_PLLTS] = { .ghz5 = 0x0040, .ghz2 = 0x0040, NOUPLOAD, },
+ [B2055_C1_PD_LGBUF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_C1_PD_TX] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_C1_PD_RXTX] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_C1_PD_RSSIMISC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_C2_PD_LGBUF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_C2_PD_TX] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_C2_PD_RXTX] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_C2_PD_RSSIMISC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_PWRDET_LGEN] = { .ghz5 = 0x00C0, .ghz2 = 0x00C0, NOUPLOAD, },
+ [B2055_C1_PWRDET_LGBUF] = { .ghz5 = 0x00FF, .ghz2 = 0x00FF, NOUPLOAD, },
+ [B2055_C1_PWRDET_RXTX] = { .ghz5 = 0x00C0, .ghz2 = 0x00C0, NOUPLOAD, },
+ [B2055_C2_PWRDET_LGBUF] = { .ghz5 = 0x00FF, .ghz2 = 0x00FF, NOUPLOAD, },
+ [B2055_C2_PWRDET_RXTX] = { .ghz5 = 0x00C0, .ghz2 = 0x00C0, NOUPLOAD, },
+ [B2055_RRCCAL_CS] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_RRCCAL_NOPTSEL] = { .ghz5 = 0x002C, .ghz2 = 0x002C, NOUPLOAD, },
+ [B2055_CAL_MISC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_CAL_COUT] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_CAL_COUT2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_CAL_CVARCTL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_CAL_RVARCTL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_CAL_LPOCTL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_CAL_TS] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_CAL_RCCALRTS] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_CAL_RCALRTS] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_PADDRV] = { .ghz5 = 0x00A4, .ghz2 = 0x00A4, NOUPLOAD, },
+ [B2055_XOCTL1] = { .ghz5 = 0x0038, .ghz2 = 0x0038, NOUPLOAD, },
+ [B2055_XOCTL2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_XOREGUL] = { .ghz5 = 0x0004, .ghz2 = 0x0004, UPLOAD, },
+ [B2055_XOMISC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_PLL_LFC1] = { .ghz5 = 0x000A, .ghz2 = 0x000A, NOUPLOAD, },
+ [B2055_PLL_CALVTH] = { .ghz5 = 0x0087, .ghz2 = 0x0087, NOUPLOAD, },
+ [B2055_PLL_LFC2] = { .ghz5 = 0x0009, .ghz2 = 0x0009, NOUPLOAD, },
+ [B2055_PLL_REF] = { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
+ [B2055_PLL_LFR1] = { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
+ [B2055_PLL_PFDCP] = { .ghz5 = 0x0018, .ghz2 = 0x0018, UPLOAD, },
+ [B2055_PLL_IDAC_CPOPAMP] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+ [B2055_PLL_CPREG] = { .ghz5 = 0x0004, .ghz2 = 0x0004, UPLOAD, },
+ [B2055_PLL_RCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+ [B2055_RF_PLLMOD0] = { .ghz5 = 0x009E, .ghz2 = 0x009E, NOUPLOAD, },
+ [B2055_RF_PLLMOD1] = { .ghz5 = 0x0009, .ghz2 = 0x0009, NOUPLOAD, },
+ [B2055_RF_MMDIDAC1] = { .ghz5 = 0x00C8, .ghz2 = 0x00C8, UPLOAD, },
+ [B2055_RF_MMDIDAC0] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+ [B2055_RF_MMDSP] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_VCO_CAL1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_VCO_CAL2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_VCO_CAL3] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+ [B2055_VCO_CAL4] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+ [B2055_VCO_CAL5] = { .ghz5 = 0x0096, .ghz2 = 0x0096, NOUPLOAD, },
+ [B2055_VCO_CAL6] = { .ghz5 = 0x003E, .ghz2 = 0x003E, NOUPLOAD, },
+ [B2055_VCO_CAL7] = { .ghz5 = 0x003E, .ghz2 = 0x003E, NOUPLOAD, },
+ [B2055_VCO_CAL8] = { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+ [B2055_VCO_CAL9] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+ [B2055_VCO_CAL10] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+ [B2055_VCO_CAL11] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+ [B2055_VCO_CAL12] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_VCO_CAL13] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_VCO_CAL14] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_VCO_CAL15] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_VCO_CAL16] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_VCO_KVCO] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+ [B2055_VCO_CAPTAIL] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+ [B2055_VCO_IDACVCO] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+ [B2055_VCO_REG] = { .ghz5 = 0x0084, .ghz2 = 0x0084, UPLOAD, },
+ [B2055_PLL_RFVTH] = { .ghz5 = 0x00C3, .ghz2 = 0x00C3, NOUPLOAD, },
+ [B2055_LGBUF_CENBUF] = { .ghz5 = 0x008F, .ghz2 = 0x008F, NOUPLOAD, },
+ [B2055_LGEN_TUNE1] = { .ghz5 = 0x00FF, .ghz2 = 0x00FF, NOUPLOAD, },
+ [B2055_LGEN_TUNE2] = { .ghz5 = 0x00FF, .ghz2 = 0x00FF, NOUPLOAD, },
+ [B2055_LGEN_IDAC1] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+ [B2055_LGEN_IDAC2] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+ [B2055_LGEN_BIASC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_LGEN_BIASIDAC] = { .ghz5 = 0x00CC, .ghz2 = 0x00CC, NOUPLOAD, },
+ [B2055_LGEN_RCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+ [B2055_LGEN_DIV] = { .ghz5 = 0x0080, .ghz2 = 0x0080, NOUPLOAD, },
+ [B2055_LGEN_SPARE2] = { .ghz5 = 0x0080, .ghz2 = 0x0080, NOUPLOAD, },
+ [B2055_C1_LGBUF_ATUNE] = { .ghz5 = 0x00F8, .ghz2 = 0x00F8, NOUPLOAD, },
+ [B2055_C1_LGBUF_GTUNE] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+ [B2055_C1_LGBUF_DIV] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+ [B2055_C1_LGBUF_AIDAC] = { .ghz5 = 0x0088, .ghz2 = 0x0008, UPLOAD, },
+ [B2055_C1_LGBUF_GIDAC] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+ [B2055_C1_LGBUF_IDACFO] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_C1_LGBUF_SPARE] = { .ghz5 = 0x0001, .ghz2 = 0x0001, UPLOAD, },
+ [B2055_C1_RX_RFSPC1] = { .ghz5 = 0x008A, .ghz2 = 0x008A, NOUPLOAD, },
+ [B2055_C1_RX_RFR1] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+ [B2055_C1_RX_RFR2] = { .ghz5 = 0x0083, .ghz2 = 0x0083, NOUPLOAD, },
+ [B2055_C1_RX_RFRCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+ [B2055_C1_RX_BB_BLCMP] = { .ghz5 = 0x00A0, .ghz2 = 0x00A0, NOUPLOAD, },
+ [B2055_C1_RX_BB_LPF] = { .ghz5 = 0x000A, .ghz2 = 0x000A, NOUPLOAD, },
+ [B2055_C1_RX_BB_MIDACHP] = { .ghz5 = 0x0087, .ghz2 = 0x0087, UPLOAD, },
+ [B2055_C1_RX_BB_VGA1IDAC] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
+ [B2055_C1_RX_BB_VGA2IDAC] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
+ [B2055_C1_RX_BB_VGA3IDAC] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
+ [B2055_C1_RX_BB_BUFOCTL] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
+ [B2055_C1_RX_BB_RCCALCTL] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
+ [B2055_C1_RX_BB_RSSICTL1] = { .ghz5 = 0x006A, .ghz2 = 0x006A, UPLOAD, },
+ [B2055_C1_RX_BB_RSSICTL2] = { .ghz5 = 0x00AB, .ghz2 = 0x00AB, UPLOAD, },
+ [B2055_C1_RX_BB_RSSICTL3] = { .ghz5 = 0x0013, .ghz2 = 0x0013, UPLOAD, },
+ [B2055_C1_RX_BB_RSSICTL4] = { .ghz5 = 0x00C1, .ghz2 = 0x00C1, UPLOAD, },
+ [B2055_C1_RX_BB_RSSICTL5] = { .ghz5 = 0x00AA, .ghz2 = 0x00AA, UPLOAD, },
+ [B2055_C1_RX_BB_REG] = { .ghz5 = 0x0087, .ghz2 = 0x0087, UPLOAD, },
+ [B2055_C1_RX_BB_SPARE1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_C1_RX_TXBBRCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+ [B2055_C1_TX_RF_SPGA] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+ [B2055_C1_TX_RF_SPAD] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+ [B2055_C1_TX_RF_CNTPGA1] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+ [B2055_C1_TX_RF_CNTPAD1] = { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
+ [B2055_C1_TX_RF_PGAIDAC] = { .ghz5 = 0x0097, .ghz2 = 0x0097, UPLOAD, },
+ [B2055_C1_TX_PGAPADTN] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+ [B2055_C1_TX_PADIDAC1] = { .ghz5 = 0x0014, .ghz2 = 0x0014, UPLOAD, },
+ [B2055_C1_TX_PADIDAC2] = { .ghz5 = 0x0033, .ghz2 = 0x0033, NOUPLOAD, },
+ [B2055_C1_TX_MXBGTRIM] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+ [B2055_C1_TX_RF_RCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+ [B2055_C1_TX_RF_PADTSSI1] = { .ghz5 = 0x0003, .ghz2 = 0x0003, UPLOAD, },
+ [B2055_C1_TX_RF_PADTSSI2] = { .ghz5 = 0x000A, .ghz2 = 0x000A, NOUPLOAD, },
+ [B2055_C1_TX_RF_SPARE] = { .ghz5 = 0x0003, .ghz2 = 0x0003, UPLOAD, },
+ [B2055_C1_TX_RF_IQCAL1] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
+ [B2055_C1_TX_RF_IQCAL2] = { .ghz5 = 0x00A4, .ghz2 = 0x00A4, NOUPLOAD, },
+ [B2055_C1_TXBB_RCCAL] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
+ [B2055_C1_TXBB_LPF1] = { .ghz5 = 0x0028, .ghz2 = 0x0028, NOUPLOAD, },
+ [B2055_C1_TX_VOSCNCL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_C1_TX_LPF_MXGMIDAC] = { .ghz5 = 0x004A, .ghz2 = 0x004A, NOUPLOAD, },
+ [B2055_C1_TX_BB_MXGM] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_C2_LGBUF_ATUNE] = { .ghz5 = 0x00F8, .ghz2 = 0x00F8, NOUPLOAD, },
+ [B2055_C2_LGBUF_GTUNE] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+ [B2055_C2_LGBUF_DIV] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+ [B2055_C2_LGBUF_AIDAC] = { .ghz5 = 0x0088, .ghz2 = 0x0008, UPLOAD, },
+ [B2055_C2_LGBUF_GIDAC] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+ [B2055_C2_LGBUF_IDACFO] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_C2_LGBUF_SPARE] = { .ghz5 = 0x0001, .ghz2 = 0x0001, UPLOAD, },
+ [B2055_C2_RX_RFSPC1] = { .ghz5 = 0x008A, .ghz2 = 0x008A, NOUPLOAD, },
+ [B2055_C2_RX_RFR1] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+ [B2055_C2_RX_RFR2] = { .ghz5 = 0x0083, .ghz2 = 0x0083, NOUPLOAD, },
+ [B2055_C2_RX_RFRCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+ [B2055_C2_RX_BB_BLCMP] = { .ghz5 = 0x00A0, .ghz2 = 0x00A0, NOUPLOAD, },
+ [B2055_C2_RX_BB_LPF] = { .ghz5 = 0x000A, .ghz2 = 0x000A, NOUPLOAD, },
+ [B2055_C2_RX_BB_MIDACHP] = { .ghz5 = 0x0087, .ghz2 = 0x0087, UPLOAD, },
+ [B2055_C2_RX_BB_VGA1IDAC] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
+ [B2055_C2_RX_BB_VGA2IDAC] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
+ [B2055_C2_RX_BB_VGA3IDAC] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
+ [B2055_C2_RX_BB_BUFOCTL] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
+ [B2055_C2_RX_BB_RCCALCTL] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
+ [B2055_C2_RX_BB_RSSICTL1] = { .ghz5 = 0x006A, .ghz2 = 0x006A, UPLOAD, },
+ [B2055_C2_RX_BB_RSSICTL2] = { .ghz5 = 0x00AB, .ghz2 = 0x00AB, UPLOAD, },
+ [B2055_C2_RX_BB_RSSICTL3] = { .ghz5 = 0x0013, .ghz2 = 0x0013, UPLOAD, },
+ [B2055_C2_RX_BB_RSSICTL4] = { .ghz5 = 0x00C1, .ghz2 = 0x00C1, UPLOAD, },
+ [B2055_C2_RX_BB_RSSICTL5] = { .ghz5 = 0x00AA, .ghz2 = 0x00AA, UPLOAD, },
+ [B2055_C2_RX_BB_REG] = { .ghz5 = 0x0087, .ghz2 = 0x0087, UPLOAD, },
+ [B2055_C2_RX_BB_SPARE1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_C2_RX_TXBBRCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+ [B2055_C2_TX_RF_SPGA] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+ [B2055_C2_TX_RF_SPAD] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+ [B2055_C2_TX_RF_CNTPGA1] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+ [B2055_C2_TX_RF_CNTPAD1] = { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
+ [B2055_C2_TX_RF_PGAIDAC] = { .ghz5 = 0x0097, .ghz2 = 0x0097, UPLOAD, },
+ [B2055_C2_TX_PGAPADTN] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+ [B2055_C2_TX_PADIDAC1] = { .ghz5 = 0x0014, .ghz2 = 0x0014, UPLOAD, },
+ [B2055_C2_TX_PADIDAC2] = { .ghz5 = 0x0033, .ghz2 = 0x0033, NOUPLOAD, },
+ [B2055_C2_TX_MXBGTRIM] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+ [B2055_C2_TX_RF_RCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+ [B2055_C2_TX_RF_PADTSSI1] = { .ghz5 = 0x0003, .ghz2 = 0x0003, UPLOAD, },
+ [B2055_C2_TX_RF_PADTSSI2] = { .ghz5 = 0x000A, .ghz2 = 0x000A, NOUPLOAD, },
+ [B2055_C2_TX_RF_SPARE] = { .ghz5 = 0x0003, .ghz2 = 0x0003, UPLOAD, },
+ [B2055_C2_TX_RF_IQCAL1] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
+ [B2055_C2_TX_RF_IQCAL2] = { .ghz5 = 0x00A4, .ghz2 = 0x00A4, NOUPLOAD, },
+ [B2055_C2_TXBB_RCCAL] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
+ [B2055_C2_TXBB_LPF1] = { .ghz5 = 0x0028, .ghz2 = 0x0028, NOUPLOAD, },
+ [B2055_C2_TX_VOSCNCL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_C2_TX_LPF_MXGMIDAC] = { .ghz5 = 0x004A, .ghz2 = 0x004A, NOUPLOAD, },
+ [B2055_C2_TX_BB_MXGM] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_PRG_GCHP21] = { .ghz5 = 0x0071, .ghz2 = 0x0071, NOUPLOAD, },
+ [B2055_PRG_GCHP22] = { .ghz5 = 0x0072, .ghz2 = 0x0072, NOUPLOAD, },
+ [B2055_PRG_GCHP23] = { .ghz5 = 0x0073, .ghz2 = 0x0073, NOUPLOAD, },
+ [B2055_PRG_GCHP24] = { .ghz5 = 0x0074, .ghz2 = 0x0074, NOUPLOAD, },
+ [B2055_PRG_GCHP25] = { .ghz5 = 0x0075, .ghz2 = 0x0075, NOUPLOAD, },
+ [B2055_PRG_GCHP26] = { .ghz5 = 0x0076, .ghz2 = 0x0076, NOUPLOAD, },
+ [B2055_PRG_GCHP27] = { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, },
+ [B2055_PRG_GCHP28] = { .ghz5 = 0x0078, .ghz2 = 0x0078, NOUPLOAD, },
+ [B2055_PRG_GCHP29] = { .ghz5 = 0x0079, .ghz2 = 0x0079, NOUPLOAD, },
+ [B2055_PRG_GCHP30] = { .ghz5 = 0x007A, .ghz2 = 0x007A, NOUPLOAD, },
+ [0xC7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [0xC8] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [0xC9] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [0xCA] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [0xCB] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [0xCC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_C1_LNA_GAINBST] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [0xCE] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [0xCF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [0xD0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [0xD1] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
+ [B2055_C1_B0NB_RSSIVCM] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+ [0xD3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [0xD4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [0xD5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_C1_GENSPARE2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [0xD7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [0xD8] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_C2_LNA_GAINBST] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [0xDA] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [0xDB] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [0xDC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [0xDD] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
+ [B2055_C2_B0NB_RSSIVCM] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+ [0xDF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [0xE0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [0xE1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_C2_GENSPARE2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+};
+
+#define RADIOREGS(r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, \
+ r12, r13, r14, r15, r16, r17, r18, r19, r20, r21) \
+ .radio_pll_ref = r0, \
+ .radio_rf_pllmod0 = r1, \
+ .radio_rf_pllmod1 = r2, \
+ .radio_vco_captail = r3, \
+ .radio_vco_cal1 = r4, \
+ .radio_vco_cal2 = r5, \
+ .radio_pll_lfc1 = r6, \
+ .radio_pll_lfr1 = r7, \
+ .radio_pll_lfc2 = r8, \
+ .radio_lgbuf_cenbuf = r9, \
+ .radio_lgen_tune1 = r10, \
+ .radio_lgen_tune2 = r11, \
+ .radio_c1_lgbuf_atune = r12, \
+ .radio_c1_lgbuf_gtune = r13, \
+ .radio_c1_rx_rfr1 = r14, \
+ .radio_c1_tx_pgapadtn = r15, \
+ .radio_c1_tx_mxbgtrim = r16, \
+ .radio_c2_lgbuf_atune = r17, \
+ .radio_c2_lgbuf_gtune = r18, \
+ .radio_c2_rx_rfr1 = r19, \
+ .radio_c2_tx_pgapadtn = r20, \
+ .radio_c2_tx_mxbgtrim = r21
+
+#define PHYREGS(r0, r1, r2, r3, r4, r5) \
+ .phy_regs.phy_bw1a = r0, \
+ .phy_regs.phy_bw2 = r1, \
+ .phy_regs.phy_bw3 = r2, \
+ .phy_regs.phy_bw4 = r3, \
+ .phy_regs.phy_bw5 = r4, \
+ .phy_regs.phy_bw6 = r5
+
+static const struct b43_nphy_channeltab_entry_rev2 b43_nphy_channeltab_rev2[] = {
+ { .channel = 184,
+ .freq = 4920, /* MHz */
+ .unk2 = 3280,
+ RADIOREGS(0x71, 0x01, 0xEC, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+ 0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0x0F,
+ 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+ PHYREGS(0xB407, 0xB007, 0xAC07, 0x1402, 0x1502, 0x1602),
+ },
+ { .channel = 186,
+ .freq = 4930, /* MHz */
+ .unk2 = 3287,
+ RADIOREGS(0x71, 0x01, 0xED, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+ 0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0x0F,
+ 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+ PHYREGS(0xB807, 0xB407, 0xB007, 0x1302, 0x1402, 0x1502),
+ },
+ { .channel = 188,
+ .freq = 4940, /* MHz */
+ .unk2 = 3293,
+ RADIOREGS(0x71, 0x01, 0xEE, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+ 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F,
+ 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+ PHYREGS(0xBC07, 0xB807, 0xB407, 0x1202, 0x1302, 0x1402),
+ },
+ { .channel = 190,
+ .freq = 4950, /* MHz */
+ .unk2 = 3300,
+ RADIOREGS(0x71, 0x01, 0xEF, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+ 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F,
+ 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+ PHYREGS(0xC007, 0xBC07, 0xB807, 0x1102, 0x1202, 0x1302),
+ },
+ { .channel = 192,
+ .freq = 4960, /* MHz */
+ .unk2 = 3307,
+ RADIOREGS(0x71, 0x01, 0xF0, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+ 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F,
+ 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+ PHYREGS(0xC407, 0xC007, 0xBC07, 0x0F02, 0x1102, 0x1202),
+ },
+ { .channel = 194,
+ .freq = 4970, /* MHz */
+ .unk2 = 3313,
+ RADIOREGS(0x71, 0x01, 0xF1, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+ 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F,
+ 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+ PHYREGS(0xC807, 0xC407, 0xC007, 0x0E02, 0x0F02, 0x1102),
+ },
+ { .channel = 196,
+ .freq = 4980, /* MHz */
+ .unk2 = 3320,
+ RADIOREGS(0x71, 0x01, 0xF2, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
+ 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F,
+ 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+ PHYREGS(0xCC07, 0xC807, 0xC407, 0x0D02, 0x0E02, 0x0F02),
+ },
+ { .channel = 198,
+ .freq = 4990, /* MHz */
+ .unk2 = 3327,
+ RADIOREGS(0x71, 0x01, 0xF3, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
+ 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F,
+ 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+ PHYREGS(0xD007, 0xCC07, 0xC807, 0x0C02, 0x0D02, 0x0E02),
+ },
+ { .channel = 200,
+ .freq = 5000, /* MHz */
+ .unk2 = 3333,
+ RADIOREGS(0x71, 0x01, 0xF4, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
+ 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F,
+ 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+ PHYREGS(0xD407, 0xD007, 0xCC07, 0x0B02, 0x0C02, 0x0D02),
+ },
+ { .channel = 202,
+ .freq = 5010, /* MHz */
+ .unk2 = 3340,
+ RADIOREGS(0x71, 0x01, 0xF5, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
+ 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F,
+ 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+ PHYREGS(0xD807, 0xD407, 0xD007, 0x0A02, 0x0B02, 0x0C02),
+ },
+ { .channel = 204,
+ .freq = 5020, /* MHz */
+ .unk2 = 3347,
+ RADIOREGS(0x71, 0x01, 0xF6, 0x0E, 0xF7, 0x01, 0x04, 0x0A,
+ 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F,
+ 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+ PHYREGS(0xDC07, 0xD807, 0xD407, 0x0902, 0x0A02, 0x0B02),
+ },
+ { .channel = 206,
+ .freq = 5030, /* MHz */
+ .unk2 = 3353,
+ RADIOREGS(0x71, 0x01, 0xF7, 0x0E, 0xF7, 0x01, 0x04, 0x0A,
+ 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F,
+ 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+ PHYREGS(0xE007, 0xDC07, 0xD807, 0x0802, 0x0902, 0x0A02),
+ },
+ { .channel = 208,
+ .freq = 5040, /* MHz */
+ .unk2 = 3360,
+ RADIOREGS(0x71, 0x01, 0xF8, 0x0D, 0xEF, 0x01, 0x04, 0x0A,
+ 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F,
+ 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+ PHYREGS(0xE407, 0xE007, 0xDC07, 0x0702, 0x0802, 0x0902),
+ },
+ { .channel = 210,
+ .freq = 5050, /* MHz */
+ .unk2 = 3367,
+ RADIOREGS(0x71, 0x01, 0xF9, 0x0D, 0xEF, 0x01, 0x04, 0x0A,
+ 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F,
+ 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+ PHYREGS(0xE807, 0xE407, 0xE007, 0x0602, 0x0702, 0x0802),
+ },
+ { .channel = 212,
+ .freq = 5060, /* MHz */
+ .unk2 = 3373,
+ RADIOREGS(0x71, 0x01, 0xFA, 0x0D, 0xE6, 0x01, 0x04, 0x0A,
+ 0x00, 0x8F, 0xBB, 0xBB, 0xFF, 0x00, 0x0E, 0x0F,
+ 0x8E, 0xFF, 0x00, 0x0E, 0x0F, 0x8E),
+ PHYREGS(0xEC07, 0xE807, 0xE407, 0x0502, 0x0602, 0x0702),
+ },
+ { .channel = 214,
+ .freq = 5070, /* MHz */
+ .unk2 = 3380,
+ RADIOREGS(0x71, 0x01, 0xFB, 0x0D, 0xE6, 0x01, 0x04, 0x0A,
+ 0x00, 0x8F, 0xBB, 0xBB, 0xFF, 0x00, 0x0E, 0x0F,
+ 0x8E, 0xFF, 0x00, 0x0E, 0x0F, 0x8E),
+ PHYREGS(0xF007, 0xEC07, 0xE807, 0x0402, 0x0502, 0x0602),
+ },
+ { .channel = 216,
+ .freq = 5080, /* MHz */
+ .unk2 = 3387,
+ RADIOREGS(0x71, 0x01, 0xFC, 0x0D, 0xDE, 0x01, 0x04, 0x0A,
+ 0x00, 0x8E, 0xBB, 0xBB, 0xEE, 0x00, 0x0E, 0x0F,
+ 0x8D, 0xEE, 0x00, 0x0E, 0x0F, 0x8D),
+ PHYREGS(0xF407, 0xF007, 0xEC07, 0x0302, 0x0402, 0x0502),
+ },
+ { .channel = 218,
+ .freq = 5090, /* MHz */
+ .unk2 = 3393,
+ RADIOREGS(0x71, 0x01, 0xFD, 0x0D, 0xDE, 0x01, 0x04, 0x0A,
+ 0x00, 0x8E, 0xBB, 0xBB, 0xEE, 0x00, 0x0E, 0x0F,
+ 0x8D, 0xEE, 0x00, 0x0E, 0x0F, 0x8D),
+ PHYREGS(0xF807, 0xF407, 0xF007, 0x0202, 0x0302, 0x0402),
+ },
+ { .channel = 220,
+ .freq = 5100, /* MHz */
+ .unk2 = 3400,
+ RADIOREGS(0x71, 0x01, 0xFE, 0x0C, 0xD6, 0x01, 0x04, 0x0A,
+ 0x00, 0x8E, 0xAA, 0xAA, 0xEE, 0x00, 0x0D, 0x0F,
+ 0x8D, 0xEE, 0x00, 0x0D, 0x0F, 0x8D),
+ PHYREGS(0xFC07, 0xF807, 0xF407, 0x0102, 0x0202, 0x0302),
+ },
+ { .channel = 222,
+ .freq = 5110, /* MHz */
+ .unk2 = 3407,
+ RADIOREGS(0x71, 0x01, 0xFF, 0x0C, 0xD6, 0x01, 0x04, 0x0A,
+ 0x00, 0x8E, 0xAA, 0xAA, 0xEE, 0x00, 0x0D, 0x0F,
+ 0x8D, 0xEE, 0x00, 0x0D, 0x0F, 0x8D),
+ PHYREGS(0x0008, 0xFC07, 0xF807, 0x0002, 0x0102, 0x0202),
+ },
+ { .channel = 224,
+ .freq = 5120, /* MHz */
+ .unk2 = 3413,
+ RADIOREGS(0x71, 0x02, 0x00, 0x0C, 0xCE, 0x01, 0x04, 0x0A,
+ 0x00, 0x8D, 0xAA, 0xAA, 0xDD, 0x00, 0x0D, 0x0F,
+ 0x8C, 0xDD, 0x00, 0x0D, 0x0F, 0x8C),
+ PHYREGS(0x0408, 0x0008, 0xFC07, 0xFF01, 0x0002, 0x0102),
+ },
+ { .channel = 226,
+ .freq = 5130, /* MHz */
+ .unk2 = 3420,
+ RADIOREGS(0x71, 0x02, 0x01, 0x0C, 0xCE, 0x01, 0x04, 0x0A,
+ 0x00, 0x8D, 0xAA, 0xAA, 0xDD, 0x00, 0x0D, 0x0F,
+ 0x8C, 0xDD, 0x00, 0x0D, 0x0F, 0x8C),
+ PHYREGS(0x0808, 0x0408, 0x0008, 0xFE01, 0xFF01, 0x0002),
+ },
+ { .channel = 228,
+ .freq = 5140, /* MHz */
+ .unk2 = 3427,
+ RADIOREGS(0x71, 0x02, 0x02, 0x0C, 0xC6, 0x01, 0x04, 0x0A,
+ 0x00, 0x8D, 0x99, 0x99, 0xDD, 0x00, 0x0C, 0x0E,
+ 0x8B, 0xDD, 0x00, 0x0C, 0x0E, 0x8B),
+ PHYREGS(0x0C08, 0x0808, 0x0408, 0xFD01, 0xFE01, 0xFF01),
+ },
+ { .channel = 32,
+ .freq = 5160, /* MHz */
+ .unk2 = 3440,
+ RADIOREGS(0x71, 0x02, 0x04, 0x0B, 0xBE, 0x01, 0x04, 0x0A,
+ 0x00, 0x8C, 0x99, 0x99, 0xCC, 0x00, 0x0B, 0x0D,
+ 0x8A, 0xCC, 0x00, 0x0B, 0x0D, 0x8A),
+ PHYREGS(0x1408, 0x1008, 0x0C08, 0xFB01, 0xFC01, 0xFD01),
+ },
+ { .channel = 34,
+ .freq = 5170, /* MHz */
+ .unk2 = 3447,
+ RADIOREGS(0x71, 0x02, 0x05, 0x0B, 0xBE, 0x01, 0x04, 0x0A,
+ 0x00, 0x8C, 0x99, 0x99, 0xCC, 0x00, 0x0B, 0x0D,
+ 0x8A, 0xCC, 0x00, 0x0B, 0x0D, 0x8A),
+ PHYREGS(0x1808, 0x1408, 0x1008, 0xFA01, 0xFB01, 0xFC01),
+ },
+ { .channel = 36,
+ .freq = 5180, /* MHz */
+ .unk2 = 3453,
+ RADIOREGS(0x71, 0x02, 0x06, 0x0B, 0xB6, 0x01, 0x04, 0x0A,
+ 0x00, 0x8C, 0x88, 0x88, 0xCC, 0x00, 0x0B, 0x0C,
+ 0x89, 0xCC, 0x00, 0x0B, 0x0C, 0x89),
+ PHYREGS(0x1C08, 0x1808, 0x1408, 0xF901, 0xFA01, 0xFB01),
+ },
+ { .channel = 38,
+ .freq = 5190, /* MHz */
+ .unk2 = 3460,
+ RADIOREGS(0x71, 0x02, 0x07, 0x0B, 0xB6, 0x01, 0x04, 0x0A,
+ 0x00, 0x8C, 0x88, 0x88, 0xCC, 0x00, 0x0B, 0x0C,
+ 0x89, 0xCC, 0x00, 0x0B, 0x0C, 0x89),
+ PHYREGS(0x2008, 0x1C08, 0x1808, 0xF801, 0xF901, 0xFA01),
+ },
+ { .channel = 40,
+ .freq = 5200, /* MHz */
+ .unk2 = 3467,
+ RADIOREGS(0x71, 0x02, 0x08, 0x0B, 0xAF, 0x01, 0x04, 0x0A,
+ 0x00, 0x8B, 0x88, 0x88, 0xBB, 0x00, 0x0A, 0x0B,
+ 0x89, 0xBB, 0x00, 0x0A, 0x0B, 0x89),
+ PHYREGS(0x2408, 0x2008, 0x1C08, 0xF701, 0xF801, 0xF901),
+ },
+ { .channel = 42,
+ .freq = 5210, /* MHz */
+ .unk2 = 3473,
+ RADIOREGS(0x71, 0x02, 0x09, 0x0B, 0xAF, 0x01, 0x04, 0x0A,
+ 0x00, 0x8B, 0x88, 0x88, 0xBB, 0x00, 0x0A, 0x0B,
+ 0x89, 0xBB, 0x00, 0x0A, 0x0B, 0x89),
+ PHYREGS(0x2808, 0x2408, 0x2008, 0xF601, 0xF701, 0xF801),
+ },
+ { .channel = 44,
+ .freq = 5220, /* MHz */
+ .unk2 = 3480,
+ RADIOREGS(0x71, 0x02, 0x0A, 0x0A, 0xA7, 0x01, 0x04, 0x0A,
+ 0x00, 0x8B, 0x77, 0x77, 0xBB, 0x00, 0x09, 0x0A,
+ 0x88, 0xBB, 0x00, 0x09, 0x0A, 0x88),
+ PHYREGS(0x2C08, 0x2808, 0x2408, 0xF501, 0xF601, 0xF701),
+ },
+ { .channel = 46,
+ .freq = 5230, /* MHz */
+ .unk2 = 3487,
+ RADIOREGS(0x71, 0x02, 0x0B, 0x0A, 0xA7, 0x01, 0x04, 0x0A,
+ 0x00, 0x8B, 0x77, 0x77, 0xBB, 0x00, 0x09, 0x0A,
+ 0x88, 0xBB, 0x00, 0x09, 0x0A, 0x88),
+ PHYREGS(0x3008, 0x2C08, 0x2808, 0xF401, 0xF501, 0xF601),
+ },
+ { .channel = 48,
+ .freq = 5240, /* MHz */
+ .unk2 = 3493,
+ RADIOREGS(0x71, 0x02, 0x0C, 0x0A, 0xA0, 0x01, 0x04, 0x0A,
+ 0x00, 0x8A, 0x77, 0x77, 0xAA, 0x00, 0x09, 0x0A,
+ 0x87, 0xAA, 0x00, 0x09, 0x0A, 0x87),
+ PHYREGS(0x3408, 0x3008, 0x2C08, 0xF301, 0xF401, 0xF501),
+ },
+ { .channel = 50,
+ .freq = 5250, /* MHz */
+ .unk2 = 3500,
+ RADIOREGS(0x71, 0x02, 0x0D, 0x0A, 0xA0, 0x01, 0x04, 0x0A,
+ 0x00, 0x8A, 0x77, 0x77, 0xAA, 0x00, 0x09, 0x0A,
+ 0x87, 0xAA, 0x00, 0x09, 0x0A, 0x87),
+ PHYREGS(0x3808, 0x3408, 0x3008, 0xF201, 0xF301, 0xF401),
+ },
+ { .channel = 52,
+ .freq = 5260, /* MHz */
+ .unk2 = 3507,
+ RADIOREGS(0x71, 0x02, 0x0E, 0x0A, 0x98, 0x01, 0x04, 0x0A,
+ 0x00, 0x8A, 0x66, 0x66, 0xAA, 0x00, 0x08, 0x09,
+ 0x87, 0xAA, 0x00, 0x08, 0x09, 0x87),
+ PHYREGS(0x3C08, 0x3808, 0x3408, 0xF101, 0xF201, 0xF301),
+ },
+ { .channel = 54,
+ .freq = 5270, /* MHz */
+ .unk2 = 3513,
+ RADIOREGS(0x71, 0x02, 0x0F, 0x0A, 0x98, 0x01, 0x04, 0x0A,
+ 0x00, 0x8A, 0x66, 0x66, 0xAA, 0x00, 0x08, 0x09,
+ 0x87, 0xAA, 0x00, 0x08, 0x09, 0x87),
+ PHYREGS(0x4008, 0x3C08, 0x3808, 0xF001, 0xF101, 0xF201),
+ },
+ { .channel = 56,
+ .freq = 5280, /* MHz */
+ .unk2 = 3520,
+ RADIOREGS(0x71, 0x02, 0x10, 0x09, 0x91, 0x01, 0x04, 0x0A,
+ 0x00, 0x89, 0x66, 0x66, 0x99, 0x00, 0x08, 0x08,
+ 0x86, 0x99, 0x00, 0x08, 0x08, 0x86),
+ PHYREGS(0x4408, 0x4008, 0x3C08, 0xF001, 0xF001, 0xF101),
+ },
+ { .channel = 58,
+ .freq = 5290, /* MHz */
+ .unk2 = 3527,
+ RADIOREGS(0x71, 0x02, 0x11, 0x09, 0x91, 0x01, 0x04, 0x0A,
+ 0x00, 0x89, 0x66, 0x66, 0x99, 0x00, 0x08, 0x08,
+ 0x86, 0x99, 0x00, 0x08, 0x08, 0x86),
+ PHYREGS(0x4808, 0x4408, 0x4008, 0xEF01, 0xF001, 0xF001),
+ },
+ { .channel = 60,
+ .freq = 5300, /* MHz */
+ .unk2 = 3533,
+ RADIOREGS(0x71, 0x02, 0x12, 0x09, 0x8A, 0x01, 0x04, 0x0A,
+ 0x00, 0x89, 0x55, 0x55, 0x99, 0x00, 0x08, 0x07,
+ 0x85, 0x99, 0x00, 0x08, 0x07, 0x85),
+ PHYREGS(0x4C08, 0x4808, 0x4408, 0xEE01, 0xEF01, 0xF001),
+ },
+ { .channel = 62,
+ .freq = 5310, /* MHz */
+ .unk2 = 3540,
+ RADIOREGS(0x71, 0x02, 0x13, 0x09, 0x8A, 0x01, 0x04, 0x0A,
+ 0x00, 0x89, 0x55, 0x55, 0x99, 0x00, 0x08, 0x07,
+ 0x85, 0x99, 0x00, 0x08, 0x07, 0x85),
+ PHYREGS(0x5008, 0x4C08, 0x4808, 0xED01, 0xEE01, 0xEF01),
+ },
+ { .channel = 64,
+ .freq = 5320, /* MHz */
+ .unk2 = 3547,
+ RADIOREGS(0x71, 0x02, 0x14, 0x09, 0x83, 0x01, 0x04, 0x0A,
+ 0x00, 0x88, 0x55, 0x55, 0x88, 0x00, 0x07, 0x07,
+ 0x84, 0x88, 0x00, 0x07, 0x07, 0x84),
+ PHYREGS(0x5408, 0x5008, 0x4C08, 0xEC01, 0xED01, 0xEE01),
+ },
+ { .channel = 66,
+ .freq = 5330, /* MHz */
+ .unk2 = 3553,
+ RADIOREGS(0x71, 0x02, 0x15, 0x09, 0x83, 0x01, 0x04, 0x0A,
+ 0x00, 0x88, 0x55, 0x55, 0x88, 0x00, 0x07, 0x07,
+ 0x84, 0x88, 0x00, 0x07, 0x07, 0x84),
+ PHYREGS(0x5808, 0x5408, 0x5008, 0xEB01, 0xEC01, 0xED01),
+ },
+ { .channel = 68,
+ .freq = 5340, /* MHz */
+ .unk2 = 3560,
+ RADIOREGS(0x71, 0x02, 0x16, 0x08, 0x7C, 0x01, 0x04, 0x0A,
+ 0x00, 0x88, 0x44, 0x44, 0x88, 0x00, 0x07, 0x06,
+ 0x84, 0x88, 0x00, 0x07, 0x06, 0x84),
+ PHYREGS(0x5C08, 0x5808, 0x5408, 0xEA01, 0xEB01, 0xEC01),
+ },
+ { .channel = 70,
+ .freq = 5350, /* MHz */
+ .unk2 = 3567,
+ RADIOREGS(0x71, 0x02, 0x17, 0x08, 0x7C, 0x01, 0x04, 0x0A,
+ 0x00, 0x88, 0x44, 0x44, 0x88, 0x00, 0x07, 0x06,
+ 0x84, 0x88, 0x00, 0x07, 0x06, 0x84),
+ PHYREGS(0x6008, 0x5C08, 0x5808, 0xE901, 0xEA01, 0xEB01),
+ },
+ { .channel = 72,
+ .freq = 5360, /* MHz */
+ .unk2 = 3573,
+ RADIOREGS(0x71, 0x02, 0x18, 0x08, 0x75, 0x01, 0x04, 0x0A,
+ 0x00, 0x87, 0x44, 0x44, 0x77, 0x00, 0x06, 0x05,
+ 0x83, 0x77, 0x00, 0x06, 0x05, 0x83),
+ PHYREGS(0x6408, 0x6008, 0x5C08, 0xE801, 0xE901, 0xEA01),
+ },
+ { .channel = 74,
+ .freq = 5370, /* MHz */
+ .unk2 = 3580,
+ RADIOREGS(0x71, 0x02, 0x19, 0x08, 0x75, 0x01, 0x04, 0x0A,
+ 0x00, 0x87, 0x44, 0x44, 0x77, 0x00, 0x06, 0x05,
+ 0x83, 0x77, 0x00, 0x06, 0x05, 0x83),
+ PHYREGS(0x6808, 0x6408, 0x6008, 0xE701, 0xE801, 0xE901),
+ },
+ { .channel = 76,
+ .freq = 5380, /* MHz */
+ .unk2 = 3587,
+ RADIOREGS(0x71, 0x02, 0x1A, 0x08, 0x6E, 0x01, 0x04, 0x0A,
+ 0x00, 0x87, 0x33, 0x33, 0x77, 0x00, 0x06, 0x04,
+ 0x82, 0x77, 0x00, 0x06, 0x04, 0x82),
+ PHYREGS(0x6C08, 0x6808, 0x6408, 0xE601, 0xE701, 0xE801),
+ },
+ { .channel = 78,
+ .freq = 5390, /* MHz */
+ .unk2 = 3593,
+ RADIOREGS(0x71, 0x02, 0x1B, 0x08, 0x6E, 0x01, 0x04, 0x0A,
+ 0x00, 0x87, 0x33, 0x33, 0x77, 0x00, 0x06, 0x04,
+ 0x82, 0x77, 0x00, 0x06, 0x04, 0x82),
+ PHYREGS(0x7008, 0x6C08, 0x6808, 0xE501, 0xE601, 0xE701),
+ },
+ { .channel = 80,
+ .freq = 5400, /* MHz */
+ .unk2 = 3600,
+ RADIOREGS(0x71, 0x02, 0x1C, 0x07, 0x67, 0x01, 0x04, 0x0A,
+ 0x00, 0x86, 0x33, 0x33, 0x66, 0x00, 0x05, 0x04,
+ 0x81, 0x66, 0x00, 0x05, 0x04, 0x81),
+ PHYREGS(0x7408, 0x7008, 0x6C08, 0xE501, 0xE501, 0xE601),
+ },
+ { .channel = 82,
+ .freq = 5410, /* MHz */
+ .unk2 = 3607,
+ RADIOREGS(0x71, 0x02, 0x1D, 0x07, 0x67, 0x01, 0x04, 0x0A,
+ 0x00, 0x86, 0x33, 0x33, 0x66, 0x00, 0x05, 0x04,
+ 0x81, 0x66, 0x00, 0x05, 0x04, 0x81),
+ PHYREGS(0x7808, 0x7408, 0x7008, 0xE401, 0xE501, 0xE501),
+ },
+ { .channel = 84,
+ .freq = 5420, /* MHz */
+ .unk2 = 3613,
+ RADIOREGS(0x71, 0x02, 0x1E, 0x07, 0x61, 0x01, 0x04, 0x0A,
+ 0x00, 0x86, 0x22, 0x22, 0x66, 0x00, 0x05, 0x03,
+ 0x80, 0x66, 0x00, 0x05, 0x03, 0x80),
+ PHYREGS(0x7C08, 0x7808, 0x7408, 0xE301, 0xE401, 0xE501),
+ },
+ { .channel = 86,
+ .freq = 5430, /* MHz */
+ .unk2 = 3620,
+ RADIOREGS(0x71, 0x02, 0x1F, 0x07, 0x61, 0x01, 0x04, 0x0A,
+ 0x00, 0x86, 0x22, 0x22, 0x66, 0x00, 0x05, 0x03,
+ 0x80, 0x66, 0x00, 0x05, 0x03, 0x80),
+ PHYREGS(0x8008, 0x7C08, 0x7808, 0xE201, 0xE301, 0xE401),
+ },
+ { .channel = 88,
+ .freq = 5440, /* MHz */
+ .unk2 = 3627,
+ RADIOREGS(0x71, 0x02, 0x20, 0x07, 0x5A, 0x01, 0x04, 0x0A,
+ 0x00, 0x85, 0x22, 0x22, 0x55, 0x00, 0x04, 0x02,
+ 0x80, 0x55, 0x00, 0x04, 0x02, 0x80),
+ PHYREGS(0x8408, 0x8008, 0x7C08, 0xE101, 0xE201, 0xE301),
+ },
+ { .channel = 90,
+ .freq = 5450, /* MHz */
+ .unk2 = 3633,
+ RADIOREGS(0x71, 0x02, 0x21, 0x07, 0x5A, 0x01, 0x04, 0x0A,
+ 0x00, 0x85, 0x22, 0x22, 0x55, 0x00, 0x04, 0x02,
+ 0x80, 0x55, 0x00, 0x04, 0x02, 0x80),
+ PHYREGS(0x8808, 0x8408, 0x8008, 0xE001, 0xE101, 0xE201),
+ },
+ { .channel = 92,
+ .freq = 5460, /* MHz */
+ .unk2 = 3640,
+ RADIOREGS(0x71, 0x02, 0x22, 0x06, 0x53, 0x01, 0x04, 0x0A,
+ 0x00, 0x85, 0x11, 0x11, 0x55, 0x00, 0x04, 0x01,
+ 0x80, 0x55, 0x00, 0x04, 0x01, 0x80),
+ PHYREGS(0x8C08, 0x8808, 0x8408, 0xDF01, 0xE001, 0xE101),
+ },
+ { .channel = 94,
+ .freq = 5470, /* MHz */
+ .unk2 = 3647,
+ RADIOREGS(0x71, 0x02, 0x23, 0x06, 0x53, 0x01, 0x04, 0x0A,
+ 0x00, 0x85, 0x11, 0x11, 0x55, 0x00, 0x04, 0x01,
+ 0x80, 0x55, 0x00, 0x04, 0x01, 0x80),
+ PHYREGS(0x9008, 0x8C08, 0x8808, 0xDE01, 0xDF01, 0xE001),
+ },
+ { .channel = 96,
+ .freq = 5480, /* MHz */
+ .unk2 = 3653,
+ RADIOREGS(0x71, 0x02, 0x24, 0x06, 0x4D, 0x01, 0x04, 0x0A,
+ 0x00, 0x84, 0x11, 0x11, 0x44, 0x00, 0x03, 0x00,
+ 0x80, 0x44, 0x00, 0x03, 0x00, 0x80),
+ PHYREGS(0x9408, 0x9008, 0x8C08, 0xDD01, 0xDE01, 0xDF01),
+ },
+ { .channel = 98,
+ .freq = 5490, /* MHz */
+ .unk2 = 3660,
+ RADIOREGS(0x71, 0x02, 0x25, 0x06, 0x4D, 0x01, 0x04, 0x0A,
+ 0x00, 0x84, 0x11, 0x11, 0x44, 0x00, 0x03, 0x00,
+ 0x80, 0x44, 0x00, 0x03, 0x00, 0x80),
+ PHYREGS(0x9808, 0x9408, 0x9008, 0xDD01, 0xDD01, 0xDE01),
+ },
+ { .channel = 100,
+ .freq = 5500, /* MHz */
+ .unk2 = 3667,
+ RADIOREGS(0x71, 0x02, 0x26, 0x06, 0x47, 0x01, 0x04, 0x0A,
+ 0x00, 0x84, 0x00, 0x00, 0x44, 0x00, 0x03, 0x00,
+ 0x80, 0x44, 0x00, 0x03, 0x00, 0x80),
+ PHYREGS(0x9C08, 0x9808, 0x9408, 0xDC01, 0xDD01, 0xDD01),
+ },
+ { .channel = 102,
+ .freq = 5510, /* MHz */
+ .unk2 = 3673,
+ RADIOREGS(0x71, 0x02, 0x27, 0x06, 0x47, 0x01, 0x04, 0x0A,
+ 0x00, 0x84, 0x00, 0x00, 0x44, 0x00, 0x03, 0x00,
+ 0x80, 0x44, 0x00, 0x03, 0x00, 0x80),
+ PHYREGS(0xA008, 0x9C08, 0x9808, 0xDB01, 0xDC01, 0xDD01),
+ },
+ { .channel = 104,
+ .freq = 5520, /* MHz */
+ .unk2 = 3680,
+ RADIOREGS(0x71, 0x02, 0x28, 0x05, 0x40, 0x01, 0x04, 0x0A,
+ 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00,
+ 0x80, 0x33, 0x00, 0x02, 0x00, 0x80),
+ PHYREGS(0xA408, 0xA008, 0x9C08, 0xDA01, 0xDB01, 0xDC01),
+ },
+ { .channel = 106,
+ .freq = 5530, /* MHz */
+ .unk2 = 3687,
+ RADIOREGS(0x71, 0x02, 0x29, 0x05, 0x40, 0x01, 0x04, 0x0A,
+ 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00,
+ 0x80, 0x33, 0x00, 0x02, 0x00, 0x80),
+ PHYREGS(0xA808, 0xA408, 0xA008, 0xD901, 0xDA01, 0xDB01),
+ },
+ { .channel = 108,
+ .freq = 5540, /* MHz */
+ .unk2 = 3693,
+ RADIOREGS(0x71, 0x02, 0x2A, 0x05, 0x3A, 0x01, 0x04, 0x0A,
+ 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00,
+ 0x80, 0x33, 0x00, 0x02, 0x00, 0x80),
+ PHYREGS(0xAC08, 0xA808, 0xA408, 0xD801, 0xD901, 0xDA01),
+ },
+ { .channel = 110,
+ .freq = 5550, /* MHz */
+ .unk2 = 3700,
+ RADIOREGS(0x71, 0x02, 0x2B, 0x05, 0x3A, 0x01, 0x04, 0x0A,
+ 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00,
+ 0x80, 0x33, 0x00, 0x02, 0x00, 0x80),
+ PHYREGS(0xB008, 0xAC08, 0xA808, 0xD701, 0xD801, 0xD901),
+ },
+ { .channel = 112,
+ .freq = 5560, /* MHz */
+ .unk2 = 3707,
+ RADIOREGS(0x71, 0x02, 0x2C, 0x05, 0x34, 0x01, 0x04, 0x0A,
+ 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00,
+ 0x80, 0x22, 0x00, 0x01, 0x00, 0x80),
+ PHYREGS(0xB408, 0xB008, 0xAC08, 0xD701, 0xD701, 0xD801),
+ },
+ { .channel = 114,
+ .freq = 5570, /* MHz */
+ .unk2 = 3713,
+ RADIOREGS(0x71, 0x02, 0x2D, 0x05, 0x34, 0x01, 0x04, 0x0A,
+ 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00,
+ 0x80, 0x22, 0x00, 0x01, 0x00, 0x80),
+ PHYREGS(0xB808, 0xB408, 0xB008, 0xD601, 0xD701, 0xD701),
+ },
+ { .channel = 116,
+ .freq = 5580, /* MHz */
+ .unk2 = 3720,
+ RADIOREGS(0x71, 0x02, 0x2E, 0x04, 0x2E, 0x01, 0x04, 0x0A,
+ 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00,
+ 0x80, 0x22, 0x00, 0x01, 0x00, 0x80),
+ PHYREGS(0xBC08, 0xB808, 0xB408, 0xD501, 0xD601, 0xD701),
+ },
+ { .channel = 118,
+ .freq = 5590, /* MHz */
+ .unk2 = 3727,
+ RADIOREGS(0x71, 0x02, 0x2F, 0x04, 0x2E, 0x01, 0x04, 0x0A,
+ 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00,
+ 0x80, 0x22, 0x00, 0x01, 0x00, 0x80),
+ PHYREGS(0xC008, 0xBC08, 0xB808, 0xD401, 0xD501, 0xD601),
+ },
+ { .channel = 120,
+ .freq = 5600, /* MHz */
+ .unk2 = 3733,
+ RADIOREGS(0x71, 0x02, 0x30, 0x04, 0x28, 0x01, 0x04, 0x0A,
+ 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00,
+ 0x80, 0x11, 0x00, 0x01, 0x00, 0x80),
+ PHYREGS(0xC408, 0xC008, 0xBC08, 0xD301, 0xD401, 0xD501),
+ },
+ { .channel = 122,
+ .freq = 5610, /* MHz */
+ .unk2 = 3740,
+ RADIOREGS(0x71, 0x02, 0x31, 0x04, 0x28, 0x01, 0x04, 0x0A,
+ 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00,
+ 0x80, 0x11, 0x00, 0x01, 0x00, 0x80),
+ PHYREGS(0xC808, 0xC408, 0xC008, 0xD201, 0xD301, 0xD401),
+ },
+ { .channel = 124,
+ .freq = 5620, /* MHz */
+ .unk2 = 3747,
+ RADIOREGS(0x71, 0x02, 0x32, 0x04, 0x21, 0x01, 0x04, 0x0A,
+ 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
+ 0x80, 0x11, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0xCC08, 0xC808, 0xC408, 0xD201, 0xD201, 0xD301),
+ },
+ { .channel = 126,
+ .freq = 5630, /* MHz */
+ .unk2 = 3753,
+ RADIOREGS(0x71, 0x02, 0x33, 0x04, 0x21, 0x01, 0x04, 0x0A,
+ 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
+ 0x80, 0x11, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0xD008, 0xCC08, 0xC808, 0xD101, 0xD201, 0xD201),
+ },
+ { .channel = 128,
+ .freq = 5640, /* MHz */
+ .unk2 = 3760,
+ RADIOREGS(0x71, 0x02, 0x34, 0x03, 0x1C, 0x01, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0xD408, 0xD008, 0xCC08, 0xD001, 0xD101, 0xD201),
+ },
+ { .channel = 130,
+ .freq = 5650, /* MHz */
+ .unk2 = 3767,
+ RADIOREGS(0x71, 0x02, 0x35, 0x03, 0x1C, 0x01, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0xD808, 0xD408, 0xD008, 0xCF01, 0xD001, 0xD101),
+ },
+ { .channel = 132,
+ .freq = 5660, /* MHz */
+ .unk2 = 3773,
+ RADIOREGS(0x71, 0x02, 0x36, 0x03, 0x16, 0x01, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0xDC08, 0xD808, 0xD408, 0xCE01, 0xCF01, 0xD001),
+ },
+ { .channel = 134,
+ .freq = 5670, /* MHz */
+ .unk2 = 3780,
+ RADIOREGS(0x71, 0x02, 0x37, 0x03, 0x16, 0x01, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0xE008, 0xDC08, 0xD808, 0xCE01, 0xCE01, 0xCF01),
+ },
+ { .channel = 136,
+ .freq = 5680, /* MHz */
+ .unk2 = 3787,
+ RADIOREGS(0x71, 0x02, 0x38, 0x03, 0x10, 0x01, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0xE408, 0xE008, 0xDC08, 0xCD01, 0xCE01, 0xCE01),
+ },
+ { .channel = 138,
+ .freq = 5690, /* MHz */
+ .unk2 = 3793,
+ RADIOREGS(0x71, 0x02, 0x39, 0x03, 0x10, 0x01, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0xE808, 0xE408, 0xE008, 0xCC01, 0xCD01, 0xCE01),
+ },
+ { .channel = 140,
+ .freq = 5700, /* MHz */
+ .unk2 = 3800,
+ RADIOREGS(0x71, 0x02, 0x3A, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0xEC08, 0xE808, 0xE408, 0xCB01, 0xCC01, 0xCD01),
+ },
+ { .channel = 142,
+ .freq = 5710, /* MHz */
+ .unk2 = 3807,
+ RADIOREGS(0x71, 0x02, 0x3B, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0xF008, 0xEC08, 0xE808, 0xCA01, 0xCB01, 0xCC01),
+ },
+ { .channel = 144,
+ .freq = 5720, /* MHz */
+ .unk2 = 3813,
+ RADIOREGS(0x71, 0x02, 0x3C, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0xF408, 0xF008, 0xEC08, 0xC901, 0xCA01, 0xCB01),
+ },
+ { .channel = 145,
+ .freq = 5725, /* MHz */
+ .unk2 = 3817,
+ RADIOREGS(0x72, 0x04, 0x79, 0x02, 0x03, 0x01, 0x03, 0x14,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0xF608, 0xF208, 0xEE08, 0xC901, 0xCA01, 0xCB01),
+ },
+ { .channel = 146,
+ .freq = 5730, /* MHz */
+ .unk2 = 3820,
+ RADIOREGS(0x71, 0x02, 0x3D, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0xF808, 0xF408, 0xF008, 0xC901, 0xC901, 0xCA01),
+ },
+ { .channel = 147,
+ .freq = 5735, /* MHz */
+ .unk2 = 3823,
+ RADIOREGS(0x72, 0x04, 0x7B, 0x02, 0x03, 0x01, 0x03, 0x14,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0xFA08, 0xF608, 0xF208, 0xC801, 0xC901, 0xCA01),
+ },
+ { .channel = 148,
+ .freq = 5740, /* MHz */
+ .unk2 = 3827,
+ RADIOREGS(0x71, 0x02, 0x3E, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0xFC08, 0xF808, 0xF408, 0xC801, 0xC901, 0xC901),
+ },
+ { .channel = 149,
+ .freq = 5745, /* MHz */
+ .unk2 = 3830,
+ RADIOREGS(0x72, 0x04, 0x7D, 0x02, 0xFE, 0x00, 0x03, 0x14,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0xFE08, 0xFA08, 0xF608, 0xC801, 0xC801, 0xC901),
+ },
+ { .channel = 150,
+ .freq = 5750, /* MHz */
+ .unk2 = 3833,
+ RADIOREGS(0x71, 0x02, 0x3F, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x0009, 0xFC08, 0xF808, 0xC701, 0xC801, 0xC901),
+ },
+ { .channel = 151,
+ .freq = 5755, /* MHz */
+ .unk2 = 3837,
+ RADIOREGS(0x72, 0x04, 0x7F, 0x02, 0xFE, 0x00, 0x03, 0x14,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x0209, 0xFE08, 0xFA08, 0xC701, 0xC801, 0xC801),
+ },
+ { .channel = 152,
+ .freq = 5760, /* MHz */
+ .unk2 = 3840,
+ RADIOREGS(0x71, 0x02, 0x40, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x0409, 0x0009, 0xFC08, 0xC601, 0xC701, 0xC801),
+ },
+ { .channel = 153,
+ .freq = 5765, /* MHz */
+ .unk2 = 3843,
+ RADIOREGS(0x72, 0x04, 0x81, 0x02, 0xF8, 0x00, 0x03, 0x14,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x0609, 0x0209, 0xFE08, 0xC601, 0xC701, 0xC801),
+ },
+ { .channel = 154,
+ .freq = 5770, /* MHz */
+ .unk2 = 3847,
+ RADIOREGS(0x71, 0x02, 0x41, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x0809, 0x0409, 0x0009, 0xC601, 0xC601, 0xC701),
+ },
+ { .channel = 155,
+ .freq = 5775, /* MHz */
+ .unk2 = 3850,
+ RADIOREGS(0x72, 0x04, 0x83, 0x02, 0xF8, 0x00, 0x03, 0x14,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x0A09, 0x0609, 0x0209, 0xC501, 0xC601, 0xC701),
+ },
+ { .channel = 156,
+ .freq = 5780, /* MHz */
+ .unk2 = 3853,
+ RADIOREGS(0x71, 0x02, 0x42, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x0C09, 0x0809, 0x0409, 0xC501, 0xC601, 0xC601),
+ },
+ { .channel = 157,
+ .freq = 5785, /* MHz */
+ .unk2 = 3857,
+ RADIOREGS(0x72, 0x04, 0x85, 0x02, 0xF2, 0x00, 0x03, 0x14,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x0E09, 0x0A09, 0x0609, 0xC401, 0xC501, 0xC601),
+ },
+ { .channel = 158,
+ .freq = 5790, /* MHz */
+ .unk2 = 3860,
+ RADIOREGS(0x71, 0x02, 0x43, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x1009, 0x0C09, 0x0809, 0xC401, 0xC501, 0xC601),
+ },
+ { .channel = 159,
+ .freq = 5795, /* MHz */
+ .unk2 = 3863,
+ RADIOREGS(0x72, 0x04, 0x87, 0x02, 0xF2, 0x00, 0x03, 0x14,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x1209, 0x0E09, 0x0A09, 0xC401, 0xC401, 0xC501),
+ },
+ { .channel = 160,
+ .freq = 5800, /* MHz */
+ .unk2 = 3867,
+ RADIOREGS(0x71, 0x02, 0x44, 0x01, 0x0A, 0x01, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x1409, 0x1009, 0x0C09, 0xC301, 0xC401, 0xC501),
+ },
+ { .channel = 161,
+ .freq = 5805, /* MHz */
+ .unk2 = 3870,
+ RADIOREGS(0x72, 0x04, 0x89, 0x01, 0xED, 0x00, 0x03, 0x14,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x1609, 0x1209, 0x0E09, 0xC301, 0xC401, 0xC401),
+ },
+ { .channel = 162,
+ .freq = 5810, /* MHz */
+ .unk2 = 3873,
+ RADIOREGS(0x71, 0x02, 0x45, 0x01, 0x0A, 0x01, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x1809, 0x1409, 0x1009, 0xC201, 0xC301, 0xC401),
+ },
+ { .channel = 163,
+ .freq = 5815, /* MHz */
+ .unk2 = 3877,
+ RADIOREGS(0x72, 0x04, 0x8B, 0x01, 0xED, 0x00, 0x03, 0x14,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x1A09, 0x1609, 0x1209, 0xC201, 0xC301, 0xC401),
+ },
+ { .channel = 164,
+ .freq = 5820, /* MHz */
+ .unk2 = 3880,
+ RADIOREGS(0x71, 0x02, 0x46, 0x01, 0x0A, 0x01, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x1C09, 0x1809, 0x1409, 0xC201, 0xC201, 0xC301),
+ },
+ { .channel = 165,
+ .freq = 5825, /* MHz */
+ .unk2 = 3883,
+ RADIOREGS(0x72, 0x04, 0x8D, 0x01, 0xED, 0x00, 0x03, 0x14,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x1E09, 0x1A09, 0x1609, 0xC101, 0xC201, 0xC301),
+ },
+ { .channel = 166,
+ .freq = 5830, /* MHz */
+ .unk2 = 3887,
+ RADIOREGS(0x71, 0x02, 0x47, 0x01, 0x0A, 0x01, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x2009, 0x1C09, 0x1809, 0xC101, 0xC201, 0xC201),
+ },
+ { .channel = 168,
+ .freq = 5840, /* MHz */
+ .unk2 = 3893,
+ RADIOREGS(0x71, 0x02, 0x48, 0x01, 0x0A, 0x01, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x2409, 0x2009, 0x1C09, 0xC001, 0xC101, 0xC201),
+ },
+ { .channel = 170,
+ .freq = 5850, /* MHz */
+ .unk2 = 3900,
+ RADIOREGS(0x71, 0x02, 0x49, 0x01, 0xE0, 0x00, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x2809, 0x2409, 0x2009, 0xBF01, 0xC001, 0xC101),
+ },
+ { .channel = 172,
+ .freq = 5860, /* MHz */
+ .unk2 = 3907,
+ RADIOREGS(0x71, 0x02, 0x4A, 0x01, 0xDE, 0x00, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x2C09, 0x2809, 0x2409, 0xBF01, 0xBF01, 0xC001),
+ },
+ { .channel = 174,
+ .freq = 5870, /* MHz */
+ .unk2 = 3913,
+ RADIOREGS(0x71, 0x02, 0x4B, 0x00, 0xDB, 0x00, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x3009, 0x2C09, 0x2809, 0xBE01, 0xBF01, 0xBF01),
+ },
+ { .channel = 176,
+ .freq = 5880, /* MHz */
+ .unk2 = 3920,
+ RADIOREGS(0x71, 0x02, 0x4C, 0x00, 0xD8, 0x00, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x3409, 0x3009, 0x2C09, 0xBD01, 0xBE01, 0xBF01),
+ },
+ { .channel = 178,
+ .freq = 5890, /* MHz */
+ .unk2 = 3927,
+ RADIOREGS(0x71, 0x02, 0x4D, 0x00, 0xD6, 0x00, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x3809, 0x3409, 0x3009, 0xBC01, 0xBD01, 0xBE01),
+ },
+ { .channel = 180,
+ .freq = 5900, /* MHz */
+ .unk2 = 3933,
+ RADIOREGS(0x71, 0x02, 0x4E, 0x00, 0xD3, 0x00, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x3C09, 0x3809, 0x3409, 0xBC01, 0xBC01, 0xBD01),
+ },
+ { .channel = 182,
+ .freq = 5910, /* MHz */
+ .unk2 = 3940,
+ RADIOREGS(0x71, 0x02, 0x4F, 0x00, 0xD6, 0x00, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x4009, 0x3C09, 0x3809, 0xBB01, 0xBC01, 0xBC01),
+ },
+ { .channel = 1,
+ .freq = 2412, /* MHz */
+ .unk2 = 3216,
+ RADIOREGS(0x73, 0x09, 0x6C, 0x0F, 0x00, 0x01, 0x07, 0x15,
+ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0D, 0x0C,
+ 0x80, 0xFF, 0x88, 0x0D, 0x0C, 0x80),
+ PHYREGS(0xC903, 0xC503, 0xC103, 0x3A04, 0x3F04, 0x4304),
+ },
+ { .channel = 2,
+ .freq = 2417, /* MHz */
+ .unk2 = 3223,
+ RADIOREGS(0x73, 0x09, 0x71, 0x0F, 0x00, 0x01, 0x07, 0x15,
+ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0B,
+ 0x80, 0xFF, 0x88, 0x0C, 0x0B, 0x80),
+ PHYREGS(0xCB03, 0xC703, 0xC303, 0x3804, 0x3D04, 0x4104),
+ },
+ { .channel = 3,
+ .freq = 2422, /* MHz */
+ .unk2 = 3229,
+ RADIOREGS(0x73, 0x09, 0x76, 0x0F, 0x00, 0x01, 0x07, 0x15,
+ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0A,
+ 0x80, 0xFF, 0x88, 0x0C, 0x0A, 0x80),
+ PHYREGS(0xCD03, 0xC903, 0xC503, 0x3604, 0x3A04, 0x3F04),
+ },
+ { .channel = 4,
+ .freq = 2427, /* MHz */
+ .unk2 = 3236,
+ RADIOREGS(0x73, 0x09, 0x7B, 0x0F, 0x00, 0x01, 0x07, 0x15,
+ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0A,
+ 0x80, 0xFF, 0x88, 0x0C, 0x0A, 0x80),
+ PHYREGS(0xCF03, 0xCB03, 0xC703, 0x3404, 0x3804, 0x3D04),
+ },
+ { .channel = 5,
+ .freq = 2432, /* MHz */
+ .unk2 = 3243,
+ RADIOREGS(0x73, 0x09, 0x80, 0x0F, 0x00, 0x01, 0x07, 0x15,
+ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x09,
+ 0x80, 0xFF, 0x88, 0x0C, 0x09, 0x80),
+ PHYREGS(0xD103, 0xCD03, 0xC903, 0x3104, 0x3604, 0x3A04),
+ },
+ { .channel = 6,
+ .freq = 2437, /* MHz */
+ .unk2 = 3249,
+ RADIOREGS(0x73, 0x09, 0x85, 0x0F, 0x00, 0x01, 0x07, 0x15,
+ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0B, 0x08,
+ 0x80, 0xFF, 0x88, 0x0B, 0x08, 0x80),
+ PHYREGS(0xD303, 0xCF03, 0xCB03, 0x2F04, 0x3404, 0x3804),
+ },
+ { .channel = 7,
+ .freq = 2442, /* MHz */
+ .unk2 = 3256,
+ RADIOREGS(0x73, 0x09, 0x8A, 0x0F, 0x00, 0x01, 0x07, 0x15,
+ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0A, 0x07,
+ 0x80, 0xFF, 0x88, 0x0A, 0x07, 0x80),
+ PHYREGS(0xD503, 0xD103, 0xCD03, 0x2D04, 0x3104, 0x3604),
+ },
+ { .channel = 8,
+ .freq = 2447, /* MHz */
+ .unk2 = 3263,
+ RADIOREGS(0x73, 0x09, 0x8F, 0x0F, 0x00, 0x01, 0x07, 0x15,
+ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0A, 0x06,
+ 0x80, 0xFF, 0x88, 0x0A, 0x06, 0x80),
+ PHYREGS(0xD703, 0xD303, 0xCF03, 0x2B04, 0x2F04, 0x3404),
+ },
+ { .channel = 9,
+ .freq = 2452, /* MHz */
+ .unk2 = 3269,
+ RADIOREGS(0x73, 0x09, 0x94, 0x0F, 0x00, 0x01, 0x07, 0x15,
+ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x09, 0x06,
+ 0x80, 0xFF, 0x88, 0x09, 0x06, 0x80),
+ PHYREGS(0xD903, 0xD503, 0xD103, 0x2904, 0x2D04, 0x3104),
+ },
+ { .channel = 10,
+ .freq = 2457, /* MHz */
+ .unk2 = 3276,
+ RADIOREGS(0x73, 0x09, 0x99, 0x0F, 0x00, 0x01, 0x07, 0x15,
+ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x05,
+ 0x80, 0xFF, 0x88, 0x08, 0x05, 0x80),
+ PHYREGS(0xDB03, 0xD703, 0xD303, 0x2704, 0x2B04, 0x2F04),
+ },
+ { .channel = 11,
+ .freq = 2462, /* MHz */
+ .unk2 = 3283,
+ RADIOREGS(0x73, 0x09, 0x9E, 0x0F, 0x00, 0x01, 0x07, 0x15,
+ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x04,
+ 0x80, 0xFF, 0x88, 0x08, 0x04, 0x80),
+ PHYREGS(0xDD03, 0xD903, 0xD503, 0x2404, 0x2904, 0x2D04),
+ },
+ { .channel = 12,
+ .freq = 2467, /* MHz */
+ .unk2 = 3289,
+ RADIOREGS(0x73, 0x09, 0xA3, 0x0F, 0x00, 0x01, 0x07, 0x15,
+ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x03,
+ 0x80, 0xFF, 0x88, 0x08, 0x03, 0x80),
+ PHYREGS(0xDF03, 0xDB03, 0xD703, 0x2204, 0x2704, 0x2B04),
+ },
+ { .channel = 13,
+ .freq = 2472, /* MHz */
+ .unk2 = 3296,
+ RADIOREGS(0x73, 0x09, 0xA8, 0x0F, 0x00, 0x01, 0x07, 0x15,
+ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x07, 0x03,
+ 0x80, 0xFF, 0x88, 0x07, 0x03, 0x80),
+ PHYREGS(0xE103, 0xDD03, 0xD903, 0x2004, 0x2404, 0x2904),
+ },
+ { .channel = 14,
+ .freq = 2484, /* MHz */
+ .unk2 = 3312,
+ RADIOREGS(0x73, 0x09, 0xB4, 0x0F, 0xFF, 0x01, 0x07, 0x15,
+ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x07, 0x01,
+ 0x80, 0xFF, 0x88, 0x07, 0x01, 0x80),
+ PHYREGS(0xE603, 0xE203, 0xDE03, 0x1B04, 0x1F04, 0x2404),
+ },
+};
+
+void b2055_upload_inittab(struct b43_wldev *dev,
+ bool ghz5, bool ignore_uploadflag)
+{
+ const struct b2055_inittab_entry *e;
+ unsigned int i;
+ u16 value;
+
+ for (i = 0; i < ARRAY_SIZE(b2055_inittab); i++) {
+ e = &(b2055_inittab[i]);
+ if (!(e->flags & B2055_INITTAB_ENTRY_OK))
+ continue;
+ if ((e->flags & B2055_INITTAB_UPLOAD) || ignore_uploadflag) {
+ if (ghz5)
+ value = e->ghz5;
+ else
+ value = e->ghz2;
+ b43_radio_write16(dev, i, value);
+ }
+ }
+}
+
+const struct b43_nphy_channeltab_entry_rev2 *
+b43_nphy_get_chantabent_rev2(struct b43_wldev *dev, u8 channel)
+{
+ const struct b43_nphy_channeltab_entry_rev2 *e;
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(b43_nphy_channeltab_rev2); i++) {
+ e = &(b43_nphy_channeltab_rev2[i]);
+ if (e->channel == channel)
+ return e;
+ }
+
+ return NULL;
+}
diff --git a/drivers/net/wireless/b43/radio_2055.h b/drivers/net/wireless/b43/radio_2055.h
new file mode 100644
index 000000000000..d9bfa0f21b72
--- /dev/null
+++ b/drivers/net/wireless/b43/radio_2055.h
@@ -0,0 +1,254 @@
+#ifndef B43_RADIO_2055_H_
+#define B43_RADIO_2055_H_
+
+#include <linux/types.h>
+
+#include "tables_nphy.h"
+
+#define B2055_GEN_SPARE 0x00 /* GEN spare */
+#define B2055_SP_PINPD 0x02 /* SP PIN PD */
+#define B2055_C1_SP_RSSI 0x03 /* SP RSSI Core 1 */
+#define B2055_C1_SP_PDMISC 0x04 /* SP PD MISC Core 1 */
+#define B2055_C2_SP_RSSI 0x05 /* SP RSSI Core 2 */
+#define B2055_C2_SP_PDMISC 0x06 /* SP PD MISC Core 2 */
+#define B2055_C1_SP_RXGC1 0x07 /* SP RX GC1 Core 1 */
+#define B2055_C1_SP_RXGC2 0x08 /* SP RX GC2 Core 1 */
+#define B2055_C2_SP_RXGC1 0x09 /* SP RX GC1 Core 2 */
+#define B2055_C2_SP_RXGC2 0x0A /* SP RX GC2 Core 2 */
+#define B2055_C1_SP_LPFBWSEL 0x0B /* SP LPF BW select Core 1 */
+#define B2055_C2_SP_LPFBWSEL 0x0C /* SP LPF BW select Core 2 */
+#define B2055_C1_SP_TXGC1 0x0D /* SP TX GC1 Core 1 */
+#define B2055_C1_SP_TXGC2 0x0E /* SP TX GC2 Core 1 */
+#define B2055_C2_SP_TXGC1 0x0F /* SP TX GC1 Core 2 */
+#define B2055_C2_SP_TXGC2 0x10 /* SP TX GC2 Core 2 */
+#define B2055_MASTER1 0x11 /* Master control 1 */
+#define B2055_MASTER2 0x12 /* Master control 2 */
+#define B2055_PD_LGEN 0x13 /* PD LGEN */
+#define B2055_PD_PLLTS 0x14 /* PD PLL TS */
+#define B2055_C1_PD_LGBUF 0x15 /* PD Core 1 LGBUF */
+#define B2055_C1_PD_TX 0x16 /* PD Core 1 TX */
+#define B2055_C1_PD_RXTX 0x17 /* PD Core 1 RXTX */
+#define B2055_C1_PD_RSSIMISC 0x18 /* PD Core 1 RSSI MISC */
+#define B2055_C2_PD_LGBUF 0x19 /* PD Core 2 LGBUF */
+#define B2055_C2_PD_TX 0x1A /* PD Core 2 TX */
+#define B2055_C2_PD_RXTX 0x1B /* PD Core 2 RXTX */
+#define B2055_C2_PD_RSSIMISC 0x1C /* PD Core 2 RSSI MISC */
+#define B2055_PWRDET_LGEN 0x1D /* PWRDET LGEN */
+#define B2055_C1_PWRDET_LGBUF 0x1E /* PWRDET LGBUF Core 1 */
+#define B2055_C1_PWRDET_RXTX 0x1F /* PWRDET RXTX Core 1 */
+#define B2055_C2_PWRDET_LGBUF 0x20 /* PWRDET LGBUF Core 2 */
+#define B2055_C2_PWRDET_RXTX 0x21 /* PWRDET RXTX Core 2 */
+#define B2055_RRCCAL_CS 0x22 /* RRCCAL Control spare */
+#define B2055_RRCCAL_NOPTSEL 0x23 /* RRCCAL N OPT SEL */
+#define B2055_CAL_MISC 0x24 /* CAL MISC */
+#define B2055_CAL_COUT 0x25 /* CAL Counter out */
+#define B2055_CAL_COUT2 0x26 /* CAL Counter out 2 */
+#define B2055_CAL_CVARCTL 0x27 /* CAL CVAR Control */
+#define B2055_CAL_RVARCTL 0x28 /* CAL RVAR Control */
+#define B2055_CAL_LPOCTL 0x29 /* CAL LPO Control */
+#define B2055_CAL_TS 0x2A /* CAL TS */
+#define B2055_CAL_RCCALRTS 0x2B /* CAL RCCAL READ TS */
+#define B2055_CAL_RCALRTS 0x2C /* CAL RCAL READ TS */
+#define B2055_PADDRV 0x2D /* PAD driver */
+#define B2055_XOCTL1 0x2E /* XO Control 1 */
+#define B2055_XOCTL2 0x2F /* XO Control 2 */
+#define B2055_XOREGUL 0x30 /* XO Regulator */
+#define B2055_XOMISC 0x31 /* XO misc */
+#define B2055_PLL_LFC1 0x32 /* PLL LF C1 */
+#define B2055_PLL_CALVTH 0x33 /* PLL CAL VTH */
+#define B2055_PLL_LFC2 0x34 /* PLL LF C2 */
+#define B2055_PLL_REF 0x35 /* PLL reference */
+#define B2055_PLL_LFR1 0x36 /* PLL LF R1 */
+#define B2055_PLL_PFDCP 0x37 /* PLL PFD CP */
+#define B2055_PLL_IDAC_CPOPAMP 0x38 /* PLL IDAC CPOPAMP */
+#define B2055_PLL_CPREG 0x39 /* PLL CP Regulator */
+#define B2055_PLL_RCAL 0x3A /* PLL RCAL */
+#define B2055_RF_PLLMOD0 0x3B /* RF PLL MOD0 */
+#define B2055_RF_PLLMOD1 0x3C /* RF PLL MOD1 */
+#define B2055_RF_MMDIDAC1 0x3D /* RF MMD IDAC 1 */
+#define B2055_RF_MMDIDAC0 0x3E /* RF MMD IDAC 0 */
+#define B2055_RF_MMDSP 0x3F /* RF MMD spare */
+#define B2055_VCO_CAL1 0x40 /* VCO cal 1 */
+#define B2055_VCO_CAL2 0x41 /* VCO cal 2 */
+#define B2055_VCO_CAL3 0x42 /* VCO cal 3 */
+#define B2055_VCO_CAL4 0x43 /* VCO cal 4 */
+#define B2055_VCO_CAL5 0x44 /* VCO cal 5 */
+#define B2055_VCO_CAL6 0x45 /* VCO cal 6 */
+#define B2055_VCO_CAL7 0x46 /* VCO cal 7 */
+#define B2055_VCO_CAL8 0x47 /* VCO cal 8 */
+#define B2055_VCO_CAL9 0x48 /* VCO cal 9 */
+#define B2055_VCO_CAL10 0x49 /* VCO cal 10 */
+#define B2055_VCO_CAL11 0x4A /* VCO cal 11 */
+#define B2055_VCO_CAL12 0x4B /* VCO cal 12 */
+#define B2055_VCO_CAL13 0x4C /* VCO cal 13 */
+#define B2055_VCO_CAL14 0x4D /* VCO cal 14 */
+#define B2055_VCO_CAL15 0x4E /* VCO cal 15 */
+#define B2055_VCO_CAL16 0x4F /* VCO cal 16 */
+#define B2055_VCO_KVCO 0x50 /* VCO KVCO */
+#define B2055_VCO_CAPTAIL 0x51 /* VCO CAP TAIL */
+#define B2055_VCO_IDACVCO 0x52 /* VCO IDAC VCO */
+#define B2055_VCO_REG 0x53 /* VCO Regulator */
+#define B2055_PLL_RFVTH 0x54 /* PLL RF VTH */
+#define B2055_LGBUF_CENBUF 0x55 /* LGBUF CEN BUF */
+#define B2055_LGEN_TUNE1 0x56 /* LGEN tune 1 */
+#define B2055_LGEN_TUNE2 0x57 /* LGEN tune 2 */
+#define B2055_LGEN_IDAC1 0x58 /* LGEN IDAC 1 */
+#define B2055_LGEN_IDAC2 0x59 /* LGEN IDAC 2 */
+#define B2055_LGEN_BIASC 0x5A /* LGEN BIAS counter */
+#define B2055_LGEN_BIASIDAC 0x5B /* LGEN BIAS IDAC */
+#define B2055_LGEN_RCAL 0x5C /* LGEN RCAL */
+#define B2055_LGEN_DIV 0x5D /* LGEN div */
+#define B2055_LGEN_SPARE2 0x5E /* LGEN spare 2 */
+#define B2055_C1_LGBUF_ATUNE 0x5F /* Core 1 LGBUF A tune */
+#define B2055_C1_LGBUF_GTUNE 0x60 /* Core 1 LGBUF G tune */
+#define B2055_C1_LGBUF_DIV 0x61 /* Core 1 LGBUF div */
+#define B2055_C1_LGBUF_AIDAC 0x62 /* Core 1 LGBUF A IDAC */
+#define B2055_C1_LGBUF_GIDAC 0x63 /* Core 1 LGBUF G IDAC */
+#define B2055_C1_LGBUF_IDACFO 0x64 /* Core 1 LGBUF IDAC filter override */
+#define B2055_C1_LGBUF_SPARE 0x65 /* Core 1 LGBUF spare */
+#define B2055_C1_RX_RFSPC1 0x66 /* Core 1 RX RF SPC1 */
+#define B2055_C1_RX_RFR1 0x67 /* Core 1 RX RF reg 1 */
+#define B2055_C1_RX_RFR2 0x68 /* Core 1 RX RF reg 2 */
+#define B2055_C1_RX_RFRCAL 0x69 /* Core 1 RX RF RCAL */
+#define B2055_C1_RX_BB_BLCMP 0x6A /* Core 1 RX Baseband BUFI LPF CMP */
+#define B2055_C1_RX_BB_LPF 0x6B /* Core 1 RX Baseband LPF */
+#define B2055_C1_RX_BB_MIDACHP 0x6C /* Core 1 RX Baseband MIDAC High-pass */
+#define B2055_C1_RX_BB_VGA1IDAC 0x6D /* Core 1 RX Baseband VGA1 IDAC */
+#define B2055_C1_RX_BB_VGA2IDAC 0x6E /* Core 1 RX Baseband VGA2 IDAC */
+#define B2055_C1_RX_BB_VGA3IDAC 0x6F /* Core 1 RX Baseband VGA3 IDAC */
+#define B2055_C1_RX_BB_BUFOCTL 0x70 /* Core 1 RX Baseband BUFO Control */
+#define B2055_C1_RX_BB_RCCALCTL 0x71 /* Core 1 RX Baseband RCCAL Control */
+#define B2055_C1_RX_BB_RSSICTL1 0x72 /* Core 1 RX Baseband RSSI Control 1 */
+#define B2055_C1_RX_BB_RSSICTL2 0x73 /* Core 1 RX Baseband RSSI Control 2 */
+#define B2055_C1_RX_BB_RSSICTL3 0x74 /* Core 1 RX Baseband RSSI Control 3 */
+#define B2055_C1_RX_BB_RSSICTL4 0x75 /* Core 1 RX Baseband RSSI Control 4 */
+#define B2055_C1_RX_BB_RSSICTL5 0x76 /* Core 1 RX Baseband RSSI Control 5 */
+#define B2055_C1_RX_BB_REG 0x77 /* Core 1 RX Baseband Regulator */
+#define B2055_C1_RX_BB_SPARE1 0x78 /* Core 1 RX Baseband spare 1 */
+#define B2055_C1_RX_TXBBRCAL 0x79 /* Core 1 RX TX BB RCAL */
+#define B2055_C1_TX_RF_SPGA 0x7A /* Core 1 TX RF SGM PGA */
+#define B2055_C1_TX_RF_SPAD 0x7B /* Core 1 TX RF SGM PAD */
+#define B2055_C1_TX_RF_CNTPGA1 0x7C /* Core 1 TX RF counter PGA 1 */
+#define B2055_C1_TX_RF_CNTPAD1 0x7D /* Core 1 TX RF counter PAD 1 */
+#define B2055_C1_TX_RF_PGAIDAC 0x7E /* Core 1 TX RF PGA IDAC */
+#define B2055_C1_TX_PGAPADTN 0x7F /* Core 1 TX PGA PAD TN */
+#define B2055_C1_TX_PADIDAC1 0x80 /* Core 1 TX PAD IDAC 1 */
+#define B2055_C1_TX_PADIDAC2 0x81 /* Core 1 TX PAD IDAC 2 */
+#define B2055_C1_TX_MXBGTRIM 0x82 /* Core 1 TX MX B/G TRIM */
+#define B2055_C1_TX_RF_RCAL 0x83 /* Core 1 TX RF RCAL */
+#define B2055_C1_TX_RF_PADTSSI1 0x84 /* Core 1 TX RF PAD TSSI1 */
+#define B2055_C1_TX_RF_PADTSSI2 0x85 /* Core 1 TX RF PAD TSSI2 */
+#define B2055_C1_TX_RF_SPARE 0x86 /* Core 1 TX RF spare */
+#define B2055_C1_TX_RF_IQCAL1 0x87 /* Core 1 TX RF I/Q CAL 1 */
+#define B2055_C1_TX_RF_IQCAL2 0x88 /* Core 1 TX RF I/Q CAL 2 */
+#define B2055_C1_TXBB_RCCAL 0x89 /* Core 1 TXBB RC CAL Control */
+#define B2055_C1_TXBB_LPF1 0x8A /* Core 1 TXBB LPF 1 */
+#define B2055_C1_TX_VOSCNCL 0x8B /* Core 1 TX VOS CNCL */
+#define B2055_C1_TX_LPF_MXGMIDAC 0x8C /* Core 1 TX LPF MXGM IDAC */
+#define B2055_C1_TX_BB_MXGM 0x8D /* Core 1 TX BB MXGM */
+#define B2055_C2_LGBUF_ATUNE 0x8E /* Core 2 LGBUF A tune */
+#define B2055_C2_LGBUF_GTUNE 0x8F /* Core 2 LGBUF G tune */
+#define B2055_C2_LGBUF_DIV 0x90 /* Core 2 LGBUF div */
+#define B2055_C2_LGBUF_AIDAC 0x91 /* Core 2 LGBUF A IDAC */
+#define B2055_C2_LGBUF_GIDAC 0x92 /* Core 2 LGBUF G IDAC */
+#define B2055_C2_LGBUF_IDACFO 0x93 /* Core 2 LGBUF IDAC filter override */
+#define B2055_C2_LGBUF_SPARE 0x94 /* Core 2 LGBUF spare */
+#define B2055_C2_RX_RFSPC1 0x95 /* Core 2 RX RF SPC1 */
+#define B2055_C2_RX_RFR1 0x96 /* Core 2 RX RF reg 1 */
+#define B2055_C2_RX_RFR2 0x97 /* Core 2 RX RF reg 2 */
+#define B2055_C2_RX_RFRCAL 0x98 /* Core 2 RX RF RCAL */
+#define B2055_C2_RX_BB_BLCMP 0x99 /* Core 2 RX Baseband BUFI LPF CMP */
+#define B2055_C2_RX_BB_LPF 0x9A /* Core 2 RX Baseband LPF */
+#define B2055_C2_RX_BB_MIDACHP 0x9B /* Core 2 RX Baseband MIDAC High-pass */
+#define B2055_C2_RX_BB_VGA1IDAC 0x9C /* Core 2 RX Baseband VGA1 IDAC */
+#define B2055_C2_RX_BB_VGA2IDAC 0x9D /* Core 2 RX Baseband VGA2 IDAC */
+#define B2055_C2_RX_BB_VGA3IDAC 0x9E /* Core 2 RX Baseband VGA3 IDAC */
+#define B2055_C2_RX_BB_BUFOCTL 0x9F /* Core 2 RX Baseband BUFO Control */
+#define B2055_C2_RX_BB_RCCALCTL 0xA0 /* Core 2 RX Baseband RCCAL Control */
+#define B2055_C2_RX_BB_RSSICTL1 0xA1 /* Core 2 RX Baseband RSSI Control 1 */
+#define B2055_C2_RX_BB_RSSICTL2 0xA2 /* Core 2 RX Baseband RSSI Control 2 */
+#define B2055_C2_RX_BB_RSSICTL3 0xA3 /* Core 2 RX Baseband RSSI Control 3 */
+#define B2055_C2_RX_BB_RSSICTL4 0xA4 /* Core 2 RX Baseband RSSI Control 4 */
+#define B2055_C2_RX_BB_RSSICTL5 0xA5 /* Core 2 RX Baseband RSSI Control 5 */
+#define B2055_C2_RX_BB_REG 0xA6 /* Core 2 RX Baseband Regulator */
+#define B2055_C2_RX_BB_SPARE1 0xA7 /* Core 2 RX Baseband spare 1 */
+#define B2055_C2_RX_TXBBRCAL 0xA8 /* Core 2 RX TX BB RCAL */
+#define B2055_C2_TX_RF_SPGA 0xA9 /* Core 2 TX RF SGM PGA */
+#define B2055_C2_TX_RF_SPAD 0xAA /* Core 2 TX RF SGM PAD */
+#define B2055_C2_TX_RF_CNTPGA1 0xAB /* Core 2 TX RF counter PGA 1 */
+#define B2055_C2_TX_RF_CNTPAD1 0xAC /* Core 2 TX RF counter PAD 1 */
+#define B2055_C2_TX_RF_PGAIDAC 0xAD /* Core 2 TX RF PGA IDAC */
+#define B2055_C2_TX_PGAPADTN 0xAE /* Core 2 TX PGA PAD TN */
+#define B2055_C2_TX_PADIDAC1 0xAF /* Core 2 TX PAD IDAC 1 */
+#define B2055_C2_TX_PADIDAC2 0xB0 /* Core 2 TX PAD IDAC 2 */
+#define B2055_C2_TX_MXBGTRIM 0xB1 /* Core 2 TX MX B/G TRIM */
+#define B2055_C2_TX_RF_RCAL 0xB2 /* Core 2 TX RF RCAL */
+#define B2055_C2_TX_RF_PADTSSI1 0xB3 /* Core 2 TX RF PAD TSSI1 */
+#define B2055_C2_TX_RF_PADTSSI2 0xB4 /* Core 2 TX RF PAD TSSI2 */
+#define B2055_C2_TX_RF_SPARE 0xB5 /* Core 2 TX RF spare */
+#define B2055_C2_TX_RF_IQCAL1 0xB6 /* Core 2 TX RF I/Q CAL 1 */
+#define B2055_C2_TX_RF_IQCAL2 0xB7 /* Core 2 TX RF I/Q CAL 2 */
+#define B2055_C2_TXBB_RCCAL 0xB8 /* Core 2 TXBB RC CAL Control */
+#define B2055_C2_TXBB_LPF1 0xB9 /* Core 2 TXBB LPF 1 */
+#define B2055_C2_TX_VOSCNCL 0xBA /* Core 2 TX VOS CNCL */
+#define B2055_C2_TX_LPF_MXGMIDAC 0xBB /* Core 2 TX LPF MXGM IDAC */
+#define B2055_C2_TX_BB_MXGM 0xBC /* Core 2 TX BB MXGM */
+#define B2055_PRG_GCHP21 0xBD /* PRG GC HPVGA23 21 */
+#define B2055_PRG_GCHP22 0xBE /* PRG GC HPVGA23 22 */
+#define B2055_PRG_GCHP23 0xBF /* PRG GC HPVGA23 23 */
+#define B2055_PRG_GCHP24 0xC0 /* PRG GC HPVGA23 24 */
+#define B2055_PRG_GCHP25 0xC1 /* PRG GC HPVGA23 25 */
+#define B2055_PRG_GCHP26 0xC2 /* PRG GC HPVGA23 26 */
+#define B2055_PRG_GCHP27 0xC3 /* PRG GC HPVGA23 27 */
+#define B2055_PRG_GCHP28 0xC4 /* PRG GC HPVGA23 28 */
+#define B2055_PRG_GCHP29 0xC5 /* PRG GC HPVGA23 29 */
+#define B2055_PRG_GCHP30 0xC6 /* PRG GC HPVGA23 30 */
+#define B2055_C1_LNA_GAINBST 0xCD /* Core 1 LNA GAINBST */
+#define B2055_C1_B0NB_RSSIVCM 0xD2 /* Core 1 B0 narrow-band RSSI VCM */
+#define B2055_C1_GENSPARE2 0xD6 /* Core 1 GEN spare 2 */
+#define B2055_C2_LNA_GAINBST 0xD9 /* Core 2 LNA GAINBST */
+#define B2055_C2_B0NB_RSSIVCM 0xDE /* Core 2 B0 narrow-band RSSI VCM */
+#define B2055_C2_GENSPARE2 0xE2 /* Core 2 GEN spare 2 */
+
+struct b43_nphy_channeltab_entry_rev2 {
+ /* The channel number */
+ u8 channel;
+ /* The channel frequency in MHz */
+ u16 freq;
+ /* An unknown value */
+ u16 unk2;
+ /* Radio register values on channelswitch */
+ u8 radio_pll_ref;
+ u8 radio_rf_pllmod0;
+ u8 radio_rf_pllmod1;
+ u8 radio_vco_captail;
+ u8 radio_vco_cal1;
+ u8 radio_vco_cal2;
+ u8 radio_pll_lfc1;
+ u8 radio_pll_lfr1;
+ u8 radio_pll_lfc2;
+ u8 radio_lgbuf_cenbuf;
+ u8 radio_lgen_tune1;
+ u8 radio_lgen_tune2;
+ u8 radio_c1_lgbuf_atune;
+ u8 radio_c1_lgbuf_gtune;
+ u8 radio_c1_rx_rfr1;
+ u8 radio_c1_tx_pgapadtn;
+ u8 radio_c1_tx_mxbgtrim;
+ u8 radio_c2_lgbuf_atune;
+ u8 radio_c2_lgbuf_gtune;
+ u8 radio_c2_rx_rfr1;
+ u8 radio_c2_tx_pgapadtn;
+ u8 radio_c2_tx_mxbgtrim;
+ /* PHY register values on channelswitch */
+ struct b43_phy_n_sfo_cfg phy_regs;
+};
+
+/* Upload the default register value table.
+ * If "ghz5" is true, we upload the 5Ghz table. Otherwise the 2.4Ghz
+ * table is uploaded. If "ignore_uploadflag" is true, we upload any value
+ * and ignore the "UPLOAD" flag. */
+void b2055_upload_inittab(struct b43_wldev *dev,
+ bool ghz5, bool ignore_uploadflag);
+
+#endif /* B43_RADIO_2055_H_ */
diff --git a/drivers/net/wireless/b43/radio_2056.c b/drivers/net/wireless/b43/radio_2056.c
new file mode 100644
index 000000000000..d8563192ce56
--- /dev/null
+++ b/drivers/net/wireless/b43/radio_2056.c
@@ -0,0 +1,43 @@
+/*
+
+ Broadcom B43 wireless driver
+ IEEE 802.11n 2056 radio device data tables
+
+ 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.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+
+#include "b43.h"
+#include "radio_2056.h"
+#include "phy_common.h"
+
+static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_rev3[] = {
+};
+
+const struct b43_nphy_channeltab_entry_rev3 *
+b43_nphy_get_chantabent_rev3(struct b43_wldev *dev, u16 freq)
+{
+ const struct b43_nphy_channeltab_entry_rev3 *e;
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(b43_nphy_channeltab_rev3); i++) {
+ e = &(b43_nphy_channeltab_rev3[i]);
+ if (e->freq == freq)
+ return e;
+ }
+
+ return NULL;
+}
diff --git a/drivers/net/wireless/b43/radio_2056.h b/drivers/net/wireless/b43/radio_2056.h
new file mode 100644
index 000000000000..fda6dafecb8c
--- /dev/null
+++ b/drivers/net/wireless/b43/radio_2056.h
@@ -0,0 +1,42 @@
+/*
+
+ Broadcom B43 wireless driver
+
+ Copyright (c) 2010 Rafał Miłecki <zajec5@gmail.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef B43_RADIO_2056_H_
+#define B43_RADIO_2056_H_
+
+#include <linux/types.h>
+
+#include "tables_nphy.h"
+
+struct b43_nphy_channeltab_entry_rev3 {
+ /* The channel number */
+ u8 channel;
+ /* The channel frequency in MHz */
+ u16 freq;
+ /* Radio register values on channelswitch */
+ /* TODO */
+ /* PHY register values on channelswitch */
+ struct b43_phy_n_sfo_cfg phy_regs;
+};
+
+#endif /* B43_RADIO_2056_H_ */
diff --git a/drivers/net/wireless/b43/tables_nphy.c b/drivers/net/wireless/b43/tables_nphy.c
index d96e870ab8fe..d60db078eae2 100644
--- a/drivers/net/wireless/b43/tables_nphy.c
+++ b/drivers/net/wireless/b43/tables_nphy.c
@@ -1,7 +1,7 @@
/*
Broadcom B43 wireless driver
- IEEE 802.11n PHY and radio device data tables
+ IEEE 802.11n PHY data tables
Copyright (c) 2008 Michael Buesch <mb@bu3sch.de>
@@ -27,1315 +27,6 @@
#include "phy_common.h"
#include "phy_n.h"
-
-struct b2055_inittab_entry {
- /* Value to write if we use the 5GHz band. */
- u16 ghz5;
- /* Value to write if we use the 2.4GHz band. */
- u16 ghz2;
- /* Flags */
- u8 flags;
-#define B2055_INITTAB_ENTRY_OK 0x01
-#define B2055_INITTAB_UPLOAD 0x02
-};
-#define UPLOAD .flags = B2055_INITTAB_ENTRY_OK | B2055_INITTAB_UPLOAD
-#define NOUPLOAD .flags = B2055_INITTAB_ENTRY_OK
-
-static const struct b2055_inittab_entry b2055_inittab [] = {
- [B2055_SP_PINPD] = { .ghz5 = 0x0080, .ghz2 = 0x0080, NOUPLOAD, },
- [B2055_C1_SP_RSSI] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [B2055_C1_SP_PDMISC] = { .ghz5 = 0x0027, .ghz2 = 0x0027, NOUPLOAD, },
- [B2055_C2_SP_RSSI] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [B2055_C2_SP_PDMISC] = { .ghz5 = 0x0027, .ghz2 = 0x0027, NOUPLOAD, },
- [B2055_C1_SP_RXGC1] = { .ghz5 = 0x007F, .ghz2 = 0x007F, UPLOAD, },
- [B2055_C1_SP_RXGC2] = { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, },
- [B2055_C2_SP_RXGC1] = { .ghz5 = 0x007F, .ghz2 = 0x007F, UPLOAD, },
- [B2055_C2_SP_RXGC2] = { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, },
- [B2055_C1_SP_LPFBWSEL] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
- [B2055_C2_SP_LPFBWSEL] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
- [B2055_C1_SP_TXGC1] = { .ghz5 = 0x004F, .ghz2 = 0x004F, UPLOAD, },
- [B2055_C1_SP_TXGC2] = { .ghz5 = 0x0005, .ghz2 = 0x0005, UPLOAD, },
- [B2055_C2_SP_TXGC1] = { .ghz5 = 0x004F, .ghz2 = 0x004F, UPLOAD, },
- [B2055_C2_SP_TXGC2] = { .ghz5 = 0x0005, .ghz2 = 0x0005, UPLOAD, },
- [B2055_MASTER1] = { .ghz5 = 0x00D0, .ghz2 = 0x00D0, NOUPLOAD, },
- [B2055_MASTER2] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
- [B2055_PD_LGEN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [B2055_PD_PLLTS] = { .ghz5 = 0x0040, .ghz2 = 0x0040, NOUPLOAD, },
- [B2055_C1_PD_LGBUF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [B2055_C1_PD_TX] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [B2055_C1_PD_RXTX] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [B2055_C1_PD_RSSIMISC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [B2055_C2_PD_LGBUF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [B2055_C2_PD_TX] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [B2055_C2_PD_RXTX] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [B2055_C2_PD_RSSIMISC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [B2055_PWRDET_LGEN] = { .ghz5 = 0x00C0, .ghz2 = 0x00C0, NOUPLOAD, },
- [B2055_C1_PWRDET_LGBUF] = { .ghz5 = 0x00FF, .ghz2 = 0x00FF, NOUPLOAD, },
- [B2055_C1_PWRDET_RXTX] = { .ghz5 = 0x00C0, .ghz2 = 0x00C0, NOUPLOAD, },
- [B2055_C2_PWRDET_LGBUF] = { .ghz5 = 0x00FF, .ghz2 = 0x00FF, NOUPLOAD, },
- [B2055_C2_PWRDET_RXTX] = { .ghz5 = 0x00C0, .ghz2 = 0x00C0, NOUPLOAD, },
- [B2055_RRCCAL_CS] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [B2055_RRCCAL_NOPTSEL] = { .ghz5 = 0x002C, .ghz2 = 0x002C, NOUPLOAD, },
- [B2055_CAL_MISC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [B2055_CAL_COUT] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [B2055_CAL_COUT2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [B2055_CAL_CVARCTL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [B2055_CAL_RVARCTL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [B2055_CAL_LPOCTL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [B2055_CAL_TS] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [B2055_CAL_RCCALRTS] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [B2055_CAL_RCALRTS] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [B2055_PADDRV] = { .ghz5 = 0x00A4, .ghz2 = 0x00A4, NOUPLOAD, },
- [B2055_XOCTL1] = { .ghz5 = 0x0038, .ghz2 = 0x0038, NOUPLOAD, },
- [B2055_XOCTL2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [B2055_XOREGUL] = { .ghz5 = 0x0004, .ghz2 = 0x0004, UPLOAD, },
- [B2055_XOMISC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [B2055_PLL_LFC1] = { .ghz5 = 0x000A, .ghz2 = 0x000A, NOUPLOAD, },
- [B2055_PLL_CALVTH] = { .ghz5 = 0x0087, .ghz2 = 0x0087, NOUPLOAD, },
- [B2055_PLL_LFC2] = { .ghz5 = 0x0009, .ghz2 = 0x0009, NOUPLOAD, },
- [B2055_PLL_REF] = { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
- [B2055_PLL_LFR1] = { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
- [B2055_PLL_PFDCP] = { .ghz5 = 0x0018, .ghz2 = 0x0018, UPLOAD, },
- [B2055_PLL_IDAC_CPOPAMP] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
- [B2055_PLL_CPREG] = { .ghz5 = 0x0004, .ghz2 = 0x0004, UPLOAD, },
- [B2055_PLL_RCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
- [B2055_RF_PLLMOD0] = { .ghz5 = 0x009E, .ghz2 = 0x009E, NOUPLOAD, },
- [B2055_RF_PLLMOD1] = { .ghz5 = 0x0009, .ghz2 = 0x0009, NOUPLOAD, },
- [B2055_RF_MMDIDAC1] = { .ghz5 = 0x00C8, .ghz2 = 0x00C8, UPLOAD, },
- [B2055_RF_MMDIDAC0] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
- [B2055_RF_MMDSP] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [B2055_VCO_CAL1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [B2055_VCO_CAL2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [B2055_VCO_CAL3] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
- [B2055_VCO_CAL4] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
- [B2055_VCO_CAL5] = { .ghz5 = 0x0096, .ghz2 = 0x0096, NOUPLOAD, },
- [B2055_VCO_CAL6] = { .ghz5 = 0x003E, .ghz2 = 0x003E, NOUPLOAD, },
- [B2055_VCO_CAL7] = { .ghz5 = 0x003E, .ghz2 = 0x003E, NOUPLOAD, },
- [B2055_VCO_CAL8] = { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
- [B2055_VCO_CAL9] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
- [B2055_VCO_CAL10] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
- [B2055_VCO_CAL11] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
- [B2055_VCO_CAL12] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [B2055_VCO_CAL13] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [B2055_VCO_CAL14] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [B2055_VCO_CAL15] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [B2055_VCO_CAL16] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [B2055_VCO_KVCO] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
- [B2055_VCO_CAPTAIL] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
- [B2055_VCO_IDACVCO] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
- [B2055_VCO_REG] = { .ghz5 = 0x0084, .ghz2 = 0x0084, UPLOAD, },
- [B2055_PLL_RFVTH] = { .ghz5 = 0x00C3, .ghz2 = 0x00C3, NOUPLOAD, },
- [B2055_LGBUF_CENBUF] = { .ghz5 = 0x008F, .ghz2 = 0x008F, NOUPLOAD, },
- [B2055_LGEN_TUNE1] = { .ghz5 = 0x00FF, .ghz2 = 0x00FF, NOUPLOAD, },
- [B2055_LGEN_TUNE2] = { .ghz5 = 0x00FF, .ghz2 = 0x00FF, NOUPLOAD, },
- [B2055_LGEN_IDAC1] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
- [B2055_LGEN_IDAC2] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
- [B2055_LGEN_BIASC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [B2055_LGEN_BIASIDAC] = { .ghz5 = 0x00CC, .ghz2 = 0x00CC, NOUPLOAD, },
- [B2055_LGEN_RCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
- [B2055_LGEN_DIV] = { .ghz5 = 0x0080, .ghz2 = 0x0080, NOUPLOAD, },
- [B2055_LGEN_SPARE2] = { .ghz5 = 0x0080, .ghz2 = 0x0080, NOUPLOAD, },
- [B2055_C1_LGBUF_ATUNE] = { .ghz5 = 0x00F8, .ghz2 = 0x00F8, NOUPLOAD, },
- [B2055_C1_LGBUF_GTUNE] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
- [B2055_C1_LGBUF_DIV] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
- [B2055_C1_LGBUF_AIDAC] = { .ghz5 = 0x0088, .ghz2 = 0x0008, UPLOAD, },
- [B2055_C1_LGBUF_GIDAC] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
- [B2055_C1_LGBUF_IDACFO] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [B2055_C1_LGBUF_SPARE] = { .ghz5 = 0x0001, .ghz2 = 0x0001, UPLOAD, },
- [B2055_C1_RX_RFSPC1] = { .ghz5 = 0x008A, .ghz2 = 0x008A, NOUPLOAD, },
- [B2055_C1_RX_RFR1] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
- [B2055_C1_RX_RFR2] = { .ghz5 = 0x0083, .ghz2 = 0x0083, NOUPLOAD, },
- [B2055_C1_RX_RFRCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
- [B2055_C1_RX_BB_BLCMP] = { .ghz5 = 0x00A0, .ghz2 = 0x00A0, NOUPLOAD, },
- [B2055_C1_RX_BB_LPF] = { .ghz5 = 0x000A, .ghz2 = 0x000A, NOUPLOAD, },
- [B2055_C1_RX_BB_MIDACHP] = { .ghz5 = 0x0087, .ghz2 = 0x0087, UPLOAD, },
- [B2055_C1_RX_BB_VGA1IDAC] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
- [B2055_C1_RX_BB_VGA2IDAC] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
- [B2055_C1_RX_BB_VGA3IDAC] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
- [B2055_C1_RX_BB_BUFOCTL] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
- [B2055_C1_RX_BB_RCCALCTL] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
- [B2055_C1_RX_BB_RSSICTL1] = { .ghz5 = 0x006A, .ghz2 = 0x006A, UPLOAD, },
- [B2055_C1_RX_BB_RSSICTL2] = { .ghz5 = 0x00AB, .ghz2 = 0x00AB, UPLOAD, },
- [B2055_C1_RX_BB_RSSICTL3] = { .ghz5 = 0x0013, .ghz2 = 0x0013, UPLOAD, },
- [B2055_C1_RX_BB_RSSICTL4] = { .ghz5 = 0x00C1, .ghz2 = 0x00C1, UPLOAD, },
- [B2055_C1_RX_BB_RSSICTL5] = { .ghz5 = 0x00AA, .ghz2 = 0x00AA, UPLOAD, },
- [B2055_C1_RX_BB_REG] = { .ghz5 = 0x0087, .ghz2 = 0x0087, UPLOAD, },
- [B2055_C1_RX_BB_SPARE1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [B2055_C1_RX_TXBBRCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
- [B2055_C1_TX_RF_SPGA] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
- [B2055_C1_TX_RF_SPAD] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
- [B2055_C1_TX_RF_CNTPGA1] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
- [B2055_C1_TX_RF_CNTPAD1] = { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
- [B2055_C1_TX_RF_PGAIDAC] = { .ghz5 = 0x0097, .ghz2 = 0x0097, UPLOAD, },
- [B2055_C1_TX_PGAPADTN] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
- [B2055_C1_TX_PADIDAC1] = { .ghz5 = 0x0014, .ghz2 = 0x0014, UPLOAD, },
- [B2055_C1_TX_PADIDAC2] = { .ghz5 = 0x0033, .ghz2 = 0x0033, NOUPLOAD, },
- [B2055_C1_TX_MXBGTRIM] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
- [B2055_C1_TX_RF_RCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
- [B2055_C1_TX_RF_PADTSSI1] = { .ghz5 = 0x0003, .ghz2 = 0x0003, UPLOAD, },
- [B2055_C1_TX_RF_PADTSSI2] = { .ghz5 = 0x000A, .ghz2 = 0x000A, NOUPLOAD, },
- [B2055_C1_TX_RF_SPARE] = { .ghz5 = 0x0003, .ghz2 = 0x0003, UPLOAD, },
- [B2055_C1_TX_RF_IQCAL1] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
- [B2055_C1_TX_RF_IQCAL2] = { .ghz5 = 0x00A4, .ghz2 = 0x00A4, NOUPLOAD, },
- [B2055_C1_TXBB_RCCAL] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
- [B2055_C1_TXBB_LPF1] = { .ghz5 = 0x0028, .ghz2 = 0x0028, NOUPLOAD, },
- [B2055_C1_TX_VOSCNCL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [B2055_C1_TX_LPF_MXGMIDAC] = { .ghz5 = 0x004A, .ghz2 = 0x004A, NOUPLOAD, },
- [B2055_C1_TX_BB_MXGM] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [B2055_C2_LGBUF_ATUNE] = { .ghz5 = 0x00F8, .ghz2 = 0x00F8, NOUPLOAD, },
- [B2055_C2_LGBUF_GTUNE] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
- [B2055_C2_LGBUF_DIV] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
- [B2055_C2_LGBUF_AIDAC] = { .ghz5 = 0x0088, .ghz2 = 0x0008, UPLOAD, },
- [B2055_C2_LGBUF_GIDAC] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
- [B2055_C2_LGBUF_IDACFO] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [B2055_C2_LGBUF_SPARE] = { .ghz5 = 0x0001, .ghz2 = 0x0001, UPLOAD, },
- [B2055_C2_RX_RFSPC1] = { .ghz5 = 0x008A, .ghz2 = 0x008A, NOUPLOAD, },
- [B2055_C2_RX_RFR1] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
- [B2055_C2_RX_RFR2] = { .ghz5 = 0x0083, .ghz2 = 0x0083, NOUPLOAD, },
- [B2055_C2_RX_RFRCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
- [B2055_C2_RX_BB_BLCMP] = { .ghz5 = 0x00A0, .ghz2 = 0x00A0, NOUPLOAD, },
- [B2055_C2_RX_BB_LPF] = { .ghz5 = 0x000A, .ghz2 = 0x000A, NOUPLOAD, },
- [B2055_C2_RX_BB_MIDACHP] = { .ghz5 = 0x0087, .ghz2 = 0x0087, UPLOAD, },
- [B2055_C2_RX_BB_VGA1IDAC] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
- [B2055_C2_RX_BB_VGA2IDAC] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
- [B2055_C2_RX_BB_VGA3IDAC] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
- [B2055_C2_RX_BB_BUFOCTL] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
- [B2055_C2_RX_BB_RCCALCTL] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
- [B2055_C2_RX_BB_RSSICTL1] = { .ghz5 = 0x006A, .ghz2 = 0x006A, UPLOAD, },
- [B2055_C2_RX_BB_RSSICTL2] = { .ghz5 = 0x00AB, .ghz2 = 0x00AB, UPLOAD, },
- [B2055_C2_RX_BB_RSSICTL3] = { .ghz5 = 0x0013, .ghz2 = 0x0013, UPLOAD, },
- [B2055_C2_RX_BB_RSSICTL4] = { .ghz5 = 0x00C1, .ghz2 = 0x00C1, UPLOAD, },
- [B2055_C2_RX_BB_RSSICTL5] = { .ghz5 = 0x00AA, .ghz2 = 0x00AA, UPLOAD, },
- [B2055_C2_RX_BB_REG] = { .ghz5 = 0x0087, .ghz2 = 0x0087, UPLOAD, },
- [B2055_C2_RX_BB_SPARE1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [B2055_C2_RX_TXBBRCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
- [B2055_C2_TX_RF_SPGA] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
- [B2055_C2_TX_RF_SPAD] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
- [B2055_C2_TX_RF_CNTPGA1] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
- [B2055_C2_TX_RF_CNTPAD1] = { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
- [B2055_C2_TX_RF_PGAIDAC] = { .ghz5 = 0x0097, .ghz2 = 0x0097, UPLOAD, },
- [B2055_C2_TX_PGAPADTN] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
- [B2055_C2_TX_PADIDAC1] = { .ghz5 = 0x0014, .ghz2 = 0x0014, UPLOAD, },
- [B2055_C2_TX_PADIDAC2] = { .ghz5 = 0x0033, .ghz2 = 0x0033, NOUPLOAD, },
- [B2055_C2_TX_MXBGTRIM] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
- [B2055_C2_TX_RF_RCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
- [B2055_C2_TX_RF_PADTSSI1] = { .ghz5 = 0x0003, .ghz2 = 0x0003, UPLOAD, },
- [B2055_C2_TX_RF_PADTSSI2] = { .ghz5 = 0x000A, .ghz2 = 0x000A, NOUPLOAD, },
- [B2055_C2_TX_RF_SPARE] = { .ghz5 = 0x0003, .ghz2 = 0x0003, UPLOAD, },
- [B2055_C2_TX_RF_IQCAL1] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
- [B2055_C2_TX_RF_IQCAL2] = { .ghz5 = 0x00A4, .ghz2 = 0x00A4, NOUPLOAD, },
- [B2055_C2_TXBB_RCCAL] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
- [B2055_C2_TXBB_LPF1] = { .ghz5 = 0x0028, .ghz2 = 0x0028, NOUPLOAD, },
- [B2055_C2_TX_VOSCNCL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [B2055_C2_TX_LPF_MXGMIDAC] = { .ghz5 = 0x004A, .ghz2 = 0x004A, NOUPLOAD, },
- [B2055_C2_TX_BB_MXGM] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [B2055_PRG_GCHP21] = { .ghz5 = 0x0071, .ghz2 = 0x0071, NOUPLOAD, },
- [B2055_PRG_GCHP22] = { .ghz5 = 0x0072, .ghz2 = 0x0072, NOUPLOAD, },
- [B2055_PRG_GCHP23] = { .ghz5 = 0x0073, .ghz2 = 0x0073, NOUPLOAD, },
- [B2055_PRG_GCHP24] = { .ghz5 = 0x0074, .ghz2 = 0x0074, NOUPLOAD, },
- [B2055_PRG_GCHP25] = { .ghz5 = 0x0075, .ghz2 = 0x0075, NOUPLOAD, },
- [B2055_PRG_GCHP26] = { .ghz5 = 0x0076, .ghz2 = 0x0076, NOUPLOAD, },
- [B2055_PRG_GCHP27] = { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, },
- [B2055_PRG_GCHP28] = { .ghz5 = 0x0078, .ghz2 = 0x0078, NOUPLOAD, },
- [B2055_PRG_GCHP29] = { .ghz5 = 0x0079, .ghz2 = 0x0079, NOUPLOAD, },
- [B2055_PRG_GCHP30] = { .ghz5 = 0x007A, .ghz2 = 0x007A, NOUPLOAD, },
- [0xC7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [0xC8] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [0xC9] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [0xCA] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [0xCB] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [0xCC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [B2055_C1_LNA_GAINBST] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [0xCE] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [0xCF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [0xD0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [0xD1] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
- [B2055_C1_B0NB_RSSIVCM] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
- [0xD3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [0xD4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [0xD5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [B2055_C1_GENSPARE2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [0xD7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [0xD8] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [B2055_C2_LNA_GAINBST] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [0xDA] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [0xDB] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [0xDC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [0xDD] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
- [B2055_C2_B0NB_RSSIVCM] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
- [0xDF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [0xE0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [0xE1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
- [B2055_C2_GENSPARE2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-};
-
-
-void b2055_upload_inittab(struct b43_wldev *dev,
- bool ghz5, bool ignore_uploadflag)
-{
- const struct b2055_inittab_entry *e;
- unsigned int i;
- u16 value;
-
- for (i = 0; i < ARRAY_SIZE(b2055_inittab); i++) {
- e = &(b2055_inittab[i]);
- if (!(e->flags & B2055_INITTAB_ENTRY_OK))
- continue;
- if ((e->flags & B2055_INITTAB_UPLOAD) || ignore_uploadflag) {
- if (ghz5)
- value = e->ghz5;
- else
- value = e->ghz2;
- b43_radio_write16(dev, i, value);
- }
- }
-}
-
-
-#define RADIOREGS(r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, \
- r12, r13, r14, r15, r16, r17, r18, r19, r20, r21) \
- .radio_pll_ref = r0, \
- .radio_rf_pllmod0 = r1, \
- .radio_rf_pllmod1 = r2, \
- .radio_vco_captail = r3, \
- .radio_vco_cal1 = r4, \
- .radio_vco_cal2 = r5, \
- .radio_pll_lfc1 = r6, \
- .radio_pll_lfr1 = r7, \
- .radio_pll_lfc2 = r8, \
- .radio_lgbuf_cenbuf = r9, \
- .radio_lgen_tune1 = r10, \
- .radio_lgen_tune2 = r11, \
- .radio_c1_lgbuf_atune = r12, \
- .radio_c1_lgbuf_gtune = r13, \
- .radio_c1_rx_rfr1 = r14, \
- .radio_c1_tx_pgapadtn = r15, \
- .radio_c1_tx_mxbgtrim = r16, \
- .radio_c2_lgbuf_atune = r17, \
- .radio_c2_lgbuf_gtune = r18, \
- .radio_c2_rx_rfr1 = r19, \
- .radio_c2_tx_pgapadtn = r20, \
- .radio_c2_tx_mxbgtrim = r21
-
-#define PHYREGS(r0, r1, r2, r3, r4, r5) \
- .phy_regs.phy_bw1a = r0, \
- .phy_regs.phy_bw2 = r1, \
- .phy_regs.phy_bw3 = r2, \
- .phy_regs.phy_bw4 = r3, \
- .phy_regs.phy_bw5 = r4, \
- .phy_regs.phy_bw6 = r5
-
-static const struct b43_nphy_channeltab_entry_rev2 b43_nphy_channeltab[] = {
- { .channel = 184,
- .freq = 4920, /* MHz */
- .unk2 = 3280,
- RADIOREGS(0x71, 0x01, 0xEC, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
- 0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0x0F,
- 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
- PHYREGS(0xB407, 0xB007, 0xAC07, 0x1402, 0x1502, 0x1602),
- },
- { .channel = 186,
- .freq = 4930, /* MHz */
- .unk2 = 3287,
- RADIOREGS(0x71, 0x01, 0xED, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
- 0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0x0F,
- 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
- PHYREGS(0xB807, 0xB407, 0xB007, 0x1302, 0x1402, 0x1502),
- },
- { .channel = 188,
- .freq = 4940, /* MHz */
- .unk2 = 3293,
- RADIOREGS(0x71, 0x01, 0xEE, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
- 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F,
- 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
- PHYREGS(0xBC07, 0xB807, 0xB407, 0x1202, 0x1302, 0x1402),
- },
- { .channel = 190,
- .freq = 4950, /* MHz */
- .unk2 = 3300,
- RADIOREGS(0x71, 0x01, 0xEF, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
- 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F,
- 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
- PHYREGS(0xC007, 0xBC07, 0xB807, 0x1102, 0x1202, 0x1302),
- },
- { .channel = 192,
- .freq = 4960, /* MHz */
- .unk2 = 3307,
- RADIOREGS(0x71, 0x01, 0xF0, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
- 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F,
- 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
- PHYREGS(0xC407, 0xC007, 0xBC07, 0x0F02, 0x1102, 0x1202),
- },
- { .channel = 194,
- .freq = 4970, /* MHz */
- .unk2 = 3313,
- RADIOREGS(0x71, 0x01, 0xF1, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
- 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F,
- 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
- PHYREGS(0xC807, 0xC407, 0xC007, 0x0E02, 0x0F02, 0x1102),
- },
- { .channel = 196,
- .freq = 4980, /* MHz */
- .unk2 = 3320,
- RADIOREGS(0x71, 0x01, 0xF2, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
- 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F,
- 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
- PHYREGS(0xCC07, 0xC807, 0xC407, 0x0D02, 0x0E02, 0x0F02),
- },
- { .channel = 198,
- .freq = 4990, /* MHz */
- .unk2 = 3327,
- RADIOREGS(0x71, 0x01, 0xF3, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
- 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F,
- 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
- PHYREGS(0xD007, 0xCC07, 0xC807, 0x0C02, 0x0D02, 0x0E02),
- },
- { .channel = 200,
- .freq = 5000, /* MHz */
- .unk2 = 3333,
- RADIOREGS(0x71, 0x01, 0xF4, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
- 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F,
- 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
- PHYREGS(0xD407, 0xD007, 0xCC07, 0x0B02, 0x0C02, 0x0D02),
- },
- { .channel = 202,
- .freq = 5010, /* MHz */
- .unk2 = 3340,
- RADIOREGS(0x71, 0x01, 0xF5, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
- 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F,
- 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
- PHYREGS(0xD807, 0xD407, 0xD007, 0x0A02, 0x0B02, 0x0C02),
- },
- { .channel = 204,
- .freq = 5020, /* MHz */
- .unk2 = 3347,
- RADIOREGS(0x71, 0x01, 0xF6, 0x0E, 0xF7, 0x01, 0x04, 0x0A,
- 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F,
- 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
- PHYREGS(0xDC07, 0xD807, 0xD407, 0x0902, 0x0A02, 0x0B02),
- },
- { .channel = 206,
- .freq = 5030, /* MHz */
- .unk2 = 3353,
- RADIOREGS(0x71, 0x01, 0xF7, 0x0E, 0xF7, 0x01, 0x04, 0x0A,
- 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F,
- 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
- PHYREGS(0xE007, 0xDC07, 0xD807, 0x0802, 0x0902, 0x0A02),
- },
- { .channel = 208,
- .freq = 5040, /* MHz */
- .unk2 = 3360,
- RADIOREGS(0x71, 0x01, 0xF8, 0x0D, 0xEF, 0x01, 0x04, 0x0A,
- 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F,
- 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
- PHYREGS(0xE407, 0xE007, 0xDC07, 0x0702, 0x0802, 0x0902),
- },
- { .channel = 210,
- .freq = 5050, /* MHz */
- .unk2 = 3367,
- RADIOREGS(0x71, 0x01, 0xF9, 0x0D, 0xEF, 0x01, 0x04, 0x0A,
- 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F,
- 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
- PHYREGS(0xE807, 0xE407, 0xE007, 0x0602, 0x0702, 0x0802),
- },
- { .channel = 212,
- .freq = 5060, /* MHz */
- .unk2 = 3373,
- RADIOREGS(0x71, 0x01, 0xFA, 0x0D, 0xE6, 0x01, 0x04, 0x0A,
- 0x00, 0x8F, 0xBB, 0xBB, 0xFF, 0x00, 0x0E, 0x0F,
- 0x8E, 0xFF, 0x00, 0x0E, 0x0F, 0x8E),
- PHYREGS(0xEC07, 0xE807, 0xE407, 0x0502, 0x0602, 0x0702),
- },
- { .channel = 214,
- .freq = 5070, /* MHz */
- .unk2 = 3380,
- RADIOREGS(0x71, 0x01, 0xFB, 0x0D, 0xE6, 0x01, 0x04, 0x0A,
- 0x00, 0x8F, 0xBB, 0xBB, 0xFF, 0x00, 0x0E, 0x0F,
- 0x8E, 0xFF, 0x00, 0x0E, 0x0F, 0x8E),
- PHYREGS(0xF007, 0xEC07, 0xE807, 0x0402, 0x0502, 0x0602),
- },
- { .channel = 216,
- .freq = 5080, /* MHz */
- .unk2 = 3387,
- RADIOREGS(0x71, 0x01, 0xFC, 0x0D, 0xDE, 0x01, 0x04, 0x0A,
- 0x00, 0x8E, 0xBB, 0xBB, 0xEE, 0x00, 0x0E, 0x0F,
- 0x8D, 0xEE, 0x00, 0x0E, 0x0F, 0x8D),
- PHYREGS(0xF407, 0xF007, 0xEC07, 0x0302, 0x0402, 0x0502),
- },
- { .channel = 218,
- .freq = 5090, /* MHz */
- .unk2 = 3393,
- RADIOREGS(0x71, 0x01, 0xFD, 0x0D, 0xDE, 0x01, 0x04, 0x0A,
- 0x00, 0x8E, 0xBB, 0xBB, 0xEE, 0x00, 0x0E, 0x0F,
- 0x8D, 0xEE, 0x00, 0x0E, 0x0F, 0x8D),
- PHYREGS(0xF807, 0xF407, 0xF007, 0x0202, 0x0302, 0x0402),
- },
- { .channel = 220,
- .freq = 5100, /* MHz */
- .unk2 = 3400,
- RADIOREGS(0x71, 0x01, 0xFE, 0x0C, 0xD6, 0x01, 0x04, 0x0A,
- 0x00, 0x8E, 0xAA, 0xAA, 0xEE, 0x00, 0x0D, 0x0F,
- 0x8D, 0xEE, 0x00, 0x0D, 0x0F, 0x8D),
- PHYREGS(0xFC07, 0xF807, 0xF407, 0x0102, 0x0202, 0x0302),
- },
- { .channel = 222,
- .freq = 5110, /* MHz */
- .unk2 = 3407,
- RADIOREGS(0x71, 0x01, 0xFF, 0x0C, 0xD6, 0x01, 0x04, 0x0A,
- 0x00, 0x8E, 0xAA, 0xAA, 0xEE, 0x00, 0x0D, 0x0F,
- 0x8D, 0xEE, 0x00, 0x0D, 0x0F, 0x8D),
- PHYREGS(0x0008, 0xFC07, 0xF807, 0x0002, 0x0102, 0x0202),
- },
- { .channel = 224,
- .freq = 5120, /* MHz */
- .unk2 = 3413,
- RADIOREGS(0x71, 0x02, 0x00, 0x0C, 0xCE, 0x01, 0x04, 0x0A,
- 0x00, 0x8D, 0xAA, 0xAA, 0xDD, 0x00, 0x0D, 0x0F,
- 0x8C, 0xDD, 0x00, 0x0D, 0x0F, 0x8C),
- PHYREGS(0x0408, 0x0008, 0xFC07, 0xFF01, 0x0002, 0x0102),
- },
- { .channel = 226,
- .freq = 5130, /* MHz */
- .unk2 = 3420,
- RADIOREGS(0x71, 0x02, 0x01, 0x0C, 0xCE, 0x01, 0x04, 0x0A,
- 0x00, 0x8D, 0xAA, 0xAA, 0xDD, 0x00, 0x0D, 0x0F,
- 0x8C, 0xDD, 0x00, 0x0D, 0x0F, 0x8C),
- PHYREGS(0x0808, 0x0408, 0x0008, 0xFE01, 0xFF01, 0x0002),
- },
- { .channel = 228,
- .freq = 5140, /* MHz */
- .unk2 = 3427,
- RADIOREGS(0x71, 0x02, 0x02, 0x0C, 0xC6, 0x01, 0x04, 0x0A,
- 0x00, 0x8D, 0x99, 0x99, 0xDD, 0x00, 0x0C, 0x0E,
- 0x8B, 0xDD, 0x00, 0x0C, 0x0E, 0x8B),
- PHYREGS(0x0C08, 0x0808, 0x0408, 0xFD01, 0xFE01, 0xFF01),
- },
- { .channel = 32,
- .freq = 5160, /* MHz */
- .unk2 = 3440,
- RADIOREGS(0x71, 0x02, 0x04, 0x0B, 0xBE, 0x01, 0x04, 0x0A,
- 0x00, 0x8C, 0x99, 0x99, 0xCC, 0x00, 0x0B, 0x0D,
- 0x8A, 0xCC, 0x00, 0x0B, 0x0D, 0x8A),
- PHYREGS(0x1408, 0x1008, 0x0C08, 0xFB01, 0xFC01, 0xFD01),
- },
- { .channel = 34,
- .freq = 5170, /* MHz */
- .unk2 = 3447,
- RADIOREGS(0x71, 0x02, 0x05, 0x0B, 0xBE, 0x01, 0x04, 0x0A,
- 0x00, 0x8C, 0x99, 0x99, 0xCC, 0x00, 0x0B, 0x0D,
- 0x8A, 0xCC, 0x00, 0x0B, 0x0D, 0x8A),
- PHYREGS(0x1808, 0x1408, 0x1008, 0xFA01, 0xFB01, 0xFC01),
- },
- { .channel = 36,
- .freq = 5180, /* MHz */
- .unk2 = 3453,
- RADIOREGS(0x71, 0x02, 0x06, 0x0B, 0xB6, 0x01, 0x04, 0x0A,
- 0x00, 0x8C, 0x88, 0x88, 0xCC, 0x00, 0x0B, 0x0C,
- 0x89, 0xCC, 0x00, 0x0B, 0x0C, 0x89),
- PHYREGS(0x1C08, 0x1808, 0x1408, 0xF901, 0xFA01, 0xFB01),
- },
- { .channel = 38,
- .freq = 5190, /* MHz */
- .unk2 = 3460,
- RADIOREGS(0x71, 0x02, 0x07, 0x0B, 0xB6, 0x01, 0x04, 0x0A,
- 0x00, 0x8C, 0x88, 0x88, 0xCC, 0x00, 0x0B, 0x0C,
- 0x89, 0xCC, 0x00, 0x0B, 0x0C, 0x89),
- PHYREGS(0x2008, 0x1C08, 0x1808, 0xF801, 0xF901, 0xFA01),
- },
- { .channel = 40,
- .freq = 5200, /* MHz */
- .unk2 = 3467,
- RADIOREGS(0x71, 0x02, 0x08, 0x0B, 0xAF, 0x01, 0x04, 0x0A,
- 0x00, 0x8B, 0x88, 0x88, 0xBB, 0x00, 0x0A, 0x0B,
- 0x89, 0xBB, 0x00, 0x0A, 0x0B, 0x89),
- PHYREGS(0x2408, 0x2008, 0x1C08, 0xF701, 0xF801, 0xF901),
- },
- { .channel = 42,
- .freq = 5210, /* MHz */
- .unk2 = 3473,
- RADIOREGS(0x71, 0x02, 0x09, 0x0B, 0xAF, 0x01, 0x04, 0x0A,
- 0x00, 0x8B, 0x88, 0x88, 0xBB, 0x00, 0x0A, 0x0B,
- 0x89, 0xBB, 0x00, 0x0A, 0x0B, 0x89),
- PHYREGS(0x2808, 0x2408, 0x2008, 0xF601, 0xF701, 0xF801),
- },
- { .channel = 44,
- .freq = 5220, /* MHz */
- .unk2 = 3480,
- RADIOREGS(0x71, 0x02, 0x0A, 0x0A, 0xA7, 0x01, 0x04, 0x0A,
- 0x00, 0x8B, 0x77, 0x77, 0xBB, 0x00, 0x09, 0x0A,
- 0x88, 0xBB, 0x00, 0x09, 0x0A, 0x88),
- PHYREGS(0x2C08, 0x2808, 0x2408, 0xF501, 0xF601, 0xF701),
- },
- { .channel = 46,
- .freq = 5230, /* MHz */
- .unk2 = 3487,
- RADIOREGS(0x71, 0x02, 0x0B, 0x0A, 0xA7, 0x01, 0x04, 0x0A,
- 0x00, 0x8B, 0x77, 0x77, 0xBB, 0x00, 0x09, 0x0A,
- 0x88, 0xBB, 0x00, 0x09, 0x0A, 0x88),
- PHYREGS(0x3008, 0x2C08, 0x2808, 0xF401, 0xF501, 0xF601),
- },
- { .channel = 48,
- .freq = 5240, /* MHz */
- .unk2 = 3493,
- RADIOREGS(0x71, 0x02, 0x0C, 0x0A, 0xA0, 0x01, 0x04, 0x0A,
- 0x00, 0x8A, 0x77, 0x77, 0xAA, 0x00, 0x09, 0x0A,
- 0x87, 0xAA, 0x00, 0x09, 0x0A, 0x87),
- PHYREGS(0x3408, 0x3008, 0x2C08, 0xF301, 0xF401, 0xF501),
- },
- { .channel = 50,
- .freq = 5250, /* MHz */
- .unk2 = 3500,
- RADIOREGS(0x71, 0x02, 0x0D, 0x0A, 0xA0, 0x01, 0x04, 0x0A,
- 0x00, 0x8A, 0x77, 0x77, 0xAA, 0x00, 0x09, 0x0A,
- 0x87, 0xAA, 0x00, 0x09, 0x0A, 0x87),
- PHYREGS(0x3808, 0x3408, 0x3008, 0xF201, 0xF301, 0xF401),
- },
- { .channel = 52,
- .freq = 5260, /* MHz */
- .unk2 = 3507,
- RADIOREGS(0x71, 0x02, 0x0E, 0x0A, 0x98, 0x01, 0x04, 0x0A,
- 0x00, 0x8A, 0x66, 0x66, 0xAA, 0x00, 0x08, 0x09,
- 0x87, 0xAA, 0x00, 0x08, 0x09, 0x87),
- PHYREGS(0x3C08, 0x3808, 0x3408, 0xF101, 0xF201, 0xF301),
- },
- { .channel = 54,
- .freq = 5270, /* MHz */
- .unk2 = 3513,
- RADIOREGS(0x71, 0x02, 0x0F, 0x0A, 0x98, 0x01, 0x04, 0x0A,
- 0x00, 0x8A, 0x66, 0x66, 0xAA, 0x00, 0x08, 0x09,
- 0x87, 0xAA, 0x00, 0x08, 0x09, 0x87),
- PHYREGS(0x4008, 0x3C08, 0x3808, 0xF001, 0xF101, 0xF201),
- },
- { .channel = 56,
- .freq = 5280, /* MHz */
- .unk2 = 3520,
- RADIOREGS(0x71, 0x02, 0x10, 0x09, 0x91, 0x01, 0x04, 0x0A,
- 0x00, 0x89, 0x66, 0x66, 0x99, 0x00, 0x08, 0x08,
- 0x86, 0x99, 0x00, 0x08, 0x08, 0x86),
- PHYREGS(0x4408, 0x4008, 0x3C08, 0xF001, 0xF001, 0xF101),
- },
- { .channel = 58,
- .freq = 5290, /* MHz */
- .unk2 = 3527,
- RADIOREGS(0x71, 0x02, 0x11, 0x09, 0x91, 0x01, 0x04, 0x0A,
- 0x00, 0x89, 0x66, 0x66, 0x99, 0x00, 0x08, 0x08,
- 0x86, 0x99, 0x00, 0x08, 0x08, 0x86),
- PHYREGS(0x4808, 0x4408, 0x4008, 0xEF01, 0xF001, 0xF001),
- },
- { .channel = 60,
- .freq = 5300, /* MHz */
- .unk2 = 3533,
- RADIOREGS(0x71, 0x02, 0x12, 0x09, 0x8A, 0x01, 0x04, 0x0A,
- 0x00, 0x89, 0x55, 0x55, 0x99, 0x00, 0x08, 0x07,
- 0x85, 0x99, 0x00, 0x08, 0x07, 0x85),
- PHYREGS(0x4C08, 0x4808, 0x4408, 0xEE01, 0xEF01, 0xF001),
- },
- { .channel = 62,
- .freq = 5310, /* MHz */
- .unk2 = 3540,
- RADIOREGS(0x71, 0x02, 0x13, 0x09, 0x8A, 0x01, 0x04, 0x0A,
- 0x00, 0x89, 0x55, 0x55, 0x99, 0x00, 0x08, 0x07,
- 0x85, 0x99, 0x00, 0x08, 0x07, 0x85),
- PHYREGS(0x5008, 0x4C08, 0x4808, 0xED01, 0xEE01, 0xEF01),
- },
- { .channel = 64,
- .freq = 5320, /* MHz */
- .unk2 = 3547,
- RADIOREGS(0x71, 0x02, 0x14, 0x09, 0x83, 0x01, 0x04, 0x0A,
- 0x00, 0x88, 0x55, 0x55, 0x88, 0x00, 0x07, 0x07,
- 0x84, 0x88, 0x00, 0x07, 0x07, 0x84),
- PHYREGS(0x5408, 0x5008, 0x4C08, 0xEC01, 0xED01, 0xEE01),
- },
- { .channel = 66,
- .freq = 5330, /* MHz */
- .unk2 = 3553,
- RADIOREGS(0x71, 0x02, 0x15, 0x09, 0x83, 0x01, 0x04, 0x0A,
- 0x00, 0x88, 0x55, 0x55, 0x88, 0x00, 0x07, 0x07,
- 0x84, 0x88, 0x00, 0x07, 0x07, 0x84),
- PHYREGS(0x5808, 0x5408, 0x5008, 0xEB01, 0xEC01, 0xED01),
- },
- { .channel = 68,
- .freq = 5340, /* MHz */
- .unk2 = 3560,
- RADIOREGS(0x71, 0x02, 0x16, 0x08, 0x7C, 0x01, 0x04, 0x0A,
- 0x00, 0x88, 0x44, 0x44, 0x88, 0x00, 0x07, 0x06,
- 0x84, 0x88, 0x00, 0x07, 0x06, 0x84),
- PHYREGS(0x5C08, 0x5808, 0x5408, 0xEA01, 0xEB01, 0xEC01),
- },
- { .channel = 70,
- .freq = 5350, /* MHz */
- .unk2 = 3567,
- RADIOREGS(0x71, 0x02, 0x17, 0x08, 0x7C, 0x01, 0x04, 0x0A,
- 0x00, 0x88, 0x44, 0x44, 0x88, 0x00, 0x07, 0x06,
- 0x84, 0x88, 0x00, 0x07, 0x06, 0x84),
- PHYREGS(0x6008, 0x5C08, 0x5808, 0xE901, 0xEA01, 0xEB01),
- },
- { .channel = 72,
- .freq = 5360, /* MHz */
- .unk2 = 3573,
- RADIOREGS(0x71, 0x02, 0x18, 0x08, 0x75, 0x01, 0x04, 0x0A,
- 0x00, 0x87, 0x44, 0x44, 0x77, 0x00, 0x06, 0x05,
- 0x83, 0x77, 0x00, 0x06, 0x05, 0x83),
- PHYREGS(0x6408, 0x6008, 0x5C08, 0xE801, 0xE901, 0xEA01),
- },
- { .channel = 74,
- .freq = 5370, /* MHz */
- .unk2 = 3580,
- RADIOREGS(0x71, 0x02, 0x19, 0x08, 0x75, 0x01, 0x04, 0x0A,
- 0x00, 0x87, 0x44, 0x44, 0x77, 0x00, 0x06, 0x05,
- 0x83, 0x77, 0x00, 0x06, 0x05, 0x83),
- PHYREGS(0x6808, 0x6408, 0x6008, 0xE701, 0xE801, 0xE901),
- },
- { .channel = 76,
- .freq = 5380, /* MHz */
- .unk2 = 3587,
- RADIOREGS(0x71, 0x02, 0x1A, 0x08, 0x6E, 0x01, 0x04, 0x0A,
- 0x00, 0x87, 0x33, 0x33, 0x77, 0x00, 0x06, 0x04,
- 0x82, 0x77, 0x00, 0x06, 0x04, 0x82),
- PHYREGS(0x6C08, 0x6808, 0x6408, 0xE601, 0xE701, 0xE801),
- },
- { .channel = 78,
- .freq = 5390, /* MHz */
- .unk2 = 3593,
- RADIOREGS(0x71, 0x02, 0x1B, 0x08, 0x6E, 0x01, 0x04, 0x0A,
- 0x00, 0x87, 0x33, 0x33, 0x77, 0x00, 0x06, 0x04,
- 0x82, 0x77, 0x00, 0x06, 0x04, 0x82),
- PHYREGS(0x7008, 0x6C08, 0x6808, 0xE501, 0xE601, 0xE701),
- },
- { .channel = 80,
- .freq = 5400, /* MHz */
- .unk2 = 3600,
- RADIOREGS(0x71, 0x02, 0x1C, 0x07, 0x67, 0x01, 0x04, 0x0A,
- 0x00, 0x86, 0x33, 0x33, 0x66, 0x00, 0x05, 0x04,
- 0x81, 0x66, 0x00, 0x05, 0x04, 0x81),
- PHYREGS(0x7408, 0x7008, 0x6C08, 0xE501, 0xE501, 0xE601),
- },
- { .channel = 82,
- .freq = 5410, /* MHz */
- .unk2 = 3607,
- RADIOREGS(0x71, 0x02, 0x1D, 0x07, 0x67, 0x01, 0x04, 0x0A,
- 0x00, 0x86, 0x33, 0x33, 0x66, 0x00, 0x05, 0x04,
- 0x81, 0x66, 0x00, 0x05, 0x04, 0x81),
- PHYREGS(0x7808, 0x7408, 0x7008, 0xE401, 0xE501, 0xE501),
- },
- { .channel = 84,
- .freq = 5420, /* MHz */
- .unk2 = 3613,
- RADIOREGS(0x71, 0x02, 0x1E, 0x07, 0x61, 0x01, 0x04, 0x0A,
- 0x00, 0x86, 0x22, 0x22, 0x66, 0x00, 0x05, 0x03,
- 0x80, 0x66, 0x00, 0x05, 0x03, 0x80),
- PHYREGS(0x7C08, 0x7808, 0x7408, 0xE301, 0xE401, 0xE501),
- },
- { .channel = 86,
- .freq = 5430, /* MHz */
- .unk2 = 3620,
- RADIOREGS(0x71, 0x02, 0x1F, 0x07, 0x61, 0x01, 0x04, 0x0A,
- 0x00, 0x86, 0x22, 0x22, 0x66, 0x00, 0x05, 0x03,
- 0x80, 0x66, 0x00, 0x05, 0x03, 0x80),
- PHYREGS(0x8008, 0x7C08, 0x7808, 0xE201, 0xE301, 0xE401),
- },
- { .channel = 88,
- .freq = 5440, /* MHz */
- .unk2 = 3627,
- RADIOREGS(0x71, 0x02, 0x20, 0x07, 0x5A, 0x01, 0x04, 0x0A,
- 0x00, 0x85, 0x22, 0x22, 0x55, 0x00, 0x04, 0x02,
- 0x80, 0x55, 0x00, 0x04, 0x02, 0x80),
- PHYREGS(0x8408, 0x8008, 0x7C08, 0xE101, 0xE201, 0xE301),
- },
- { .channel = 90,
- .freq = 5450, /* MHz */
- .unk2 = 3633,
- RADIOREGS(0x71, 0x02, 0x21, 0x07, 0x5A, 0x01, 0x04, 0x0A,
- 0x00, 0x85, 0x22, 0x22, 0x55, 0x00, 0x04, 0x02,
- 0x80, 0x55, 0x00, 0x04, 0x02, 0x80),
- PHYREGS(0x8808, 0x8408, 0x8008, 0xE001, 0xE101, 0xE201),
- },
- { .channel = 92,
- .freq = 5460, /* MHz */
- .unk2 = 3640,
- RADIOREGS(0x71, 0x02, 0x22, 0x06, 0x53, 0x01, 0x04, 0x0A,
- 0x00, 0x85, 0x11, 0x11, 0x55, 0x00, 0x04, 0x01,
- 0x80, 0x55, 0x00, 0x04, 0x01, 0x80),
- PHYREGS(0x8C08, 0x8808, 0x8408, 0xDF01, 0xE001, 0xE101),
- },
- { .channel = 94,
- .freq = 5470, /* MHz */
- .unk2 = 3647,
- RADIOREGS(0x71, 0x02, 0x23, 0x06, 0x53, 0x01, 0x04, 0x0A,
- 0x00, 0x85, 0x11, 0x11, 0x55, 0x00, 0x04, 0x01,
- 0x80, 0x55, 0x00, 0x04, 0x01, 0x80),
- PHYREGS(0x9008, 0x8C08, 0x8808, 0xDE01, 0xDF01, 0xE001),
- },
- { .channel = 96,
- .freq = 5480, /* MHz */
- .unk2 = 3653,
- RADIOREGS(0x71, 0x02, 0x24, 0x06, 0x4D, 0x01, 0x04, 0x0A,
- 0x00, 0x84, 0x11, 0x11, 0x44, 0x00, 0x03, 0x00,
- 0x80, 0x44, 0x00, 0x03, 0x00, 0x80),
- PHYREGS(0x9408, 0x9008, 0x8C08, 0xDD01, 0xDE01, 0xDF01),
- },
- { .channel = 98,
- .freq = 5490, /* MHz */
- .unk2 = 3660,
- RADIOREGS(0x71, 0x02, 0x25, 0x06, 0x4D, 0x01, 0x04, 0x0A,
- 0x00, 0x84, 0x11, 0x11, 0x44, 0x00, 0x03, 0x00,
- 0x80, 0x44, 0x00, 0x03, 0x00, 0x80),
- PHYREGS(0x9808, 0x9408, 0x9008, 0xDD01, 0xDD01, 0xDE01),
- },
- { .channel = 100,
- .freq = 5500, /* MHz */
- .unk2 = 3667,
- RADIOREGS(0x71, 0x02, 0x26, 0x06, 0x47, 0x01, 0x04, 0x0A,
- 0x00, 0x84, 0x00, 0x00, 0x44, 0x00, 0x03, 0x00,
- 0x80, 0x44, 0x00, 0x03, 0x00, 0x80),
- PHYREGS(0x9C08, 0x9808, 0x9408, 0xDC01, 0xDD01, 0xDD01),
- },
- { .channel = 102,
- .freq = 5510, /* MHz */
- .unk2 = 3673,
- RADIOREGS(0x71, 0x02, 0x27, 0x06, 0x47, 0x01, 0x04, 0x0A,
- 0x00, 0x84, 0x00, 0x00, 0x44, 0x00, 0x03, 0x00,
- 0x80, 0x44, 0x00, 0x03, 0x00, 0x80),
- PHYREGS(0xA008, 0x9C08, 0x9808, 0xDB01, 0xDC01, 0xDD01),
- },
- { .channel = 104,
- .freq = 5520, /* MHz */
- .unk2 = 3680,
- RADIOREGS(0x71, 0x02, 0x28, 0x05, 0x40, 0x01, 0x04, 0x0A,
- 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00,
- 0x80, 0x33, 0x00, 0x02, 0x00, 0x80),
- PHYREGS(0xA408, 0xA008, 0x9C08, 0xDA01, 0xDB01, 0xDC01),
- },
- { .channel = 106,
- .freq = 5530, /* MHz */
- .unk2 = 3687,
- RADIOREGS(0x71, 0x02, 0x29, 0x05, 0x40, 0x01, 0x04, 0x0A,
- 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00,
- 0x80, 0x33, 0x00, 0x02, 0x00, 0x80),
- PHYREGS(0xA808, 0xA408, 0xA008, 0xD901, 0xDA01, 0xDB01),
- },
- { .channel = 108,
- .freq = 5540, /* MHz */
- .unk2 = 3693,
- RADIOREGS(0x71, 0x02, 0x2A, 0x05, 0x3A, 0x01, 0x04, 0x0A,
- 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00,
- 0x80, 0x33, 0x00, 0x02, 0x00, 0x80),
- PHYREGS(0xAC08, 0xA808, 0xA408, 0xD801, 0xD901, 0xDA01),
- },
- { .channel = 110,
- .freq = 5550, /* MHz */
- .unk2 = 3700,
- RADIOREGS(0x71, 0x02, 0x2B, 0x05, 0x3A, 0x01, 0x04, 0x0A,
- 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00,
- 0x80, 0x33, 0x00, 0x02, 0x00, 0x80),
- PHYREGS(0xB008, 0xAC08, 0xA808, 0xD701, 0xD801, 0xD901),
- },
- { .channel = 112,
- .freq = 5560, /* MHz */
- .unk2 = 3707,
- RADIOREGS(0x71, 0x02, 0x2C, 0x05, 0x34, 0x01, 0x04, 0x0A,
- 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00,
- 0x80, 0x22, 0x00, 0x01, 0x00, 0x80),
- PHYREGS(0xB408, 0xB008, 0xAC08, 0xD701, 0xD701, 0xD801),
- },
- { .channel = 114,
- .freq = 5570, /* MHz */
- .unk2 = 3713,
- RADIOREGS(0x71, 0x02, 0x2D, 0x05, 0x34, 0x01, 0x04, 0x0A,
- 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00,
- 0x80, 0x22, 0x00, 0x01, 0x00, 0x80),
- PHYREGS(0xB808, 0xB408, 0xB008, 0xD601, 0xD701, 0xD701),
- },
- { .channel = 116,
- .freq = 5580, /* MHz */
- .unk2 = 3720,
- RADIOREGS(0x71, 0x02, 0x2E, 0x04, 0x2E, 0x01, 0x04, 0x0A,
- 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00,
- 0x80, 0x22, 0x00, 0x01, 0x00, 0x80),
- PHYREGS(0xBC08, 0xB808, 0xB408, 0xD501, 0xD601, 0xD701),
- },
- { .channel = 118,
- .freq = 5590, /* MHz */
- .unk2 = 3727,
- RADIOREGS(0x71, 0x02, 0x2F, 0x04, 0x2E, 0x01, 0x04, 0x0A,
- 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00,
- 0x80, 0x22, 0x00, 0x01, 0x00, 0x80),
- PHYREGS(0xC008, 0xBC08, 0xB808, 0xD401, 0xD501, 0xD601),
- },
- { .channel = 120,
- .freq = 5600, /* MHz */
- .unk2 = 3733,
- RADIOREGS(0x71, 0x02, 0x30, 0x04, 0x28, 0x01, 0x04, 0x0A,
- 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00,
- 0x80, 0x11, 0x00, 0x01, 0x00, 0x80),
- PHYREGS(0xC408, 0xC008, 0xBC08, 0xD301, 0xD401, 0xD501),
- },
- { .channel = 122,
- .freq = 5610, /* MHz */
- .unk2 = 3740,
- RADIOREGS(0x71, 0x02, 0x31, 0x04, 0x28, 0x01, 0x04, 0x0A,
- 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00,
- 0x80, 0x11, 0x00, 0x01, 0x00, 0x80),
- PHYREGS(0xC808, 0xC408, 0xC008, 0xD201, 0xD301, 0xD401),
- },
- { .channel = 124,
- .freq = 5620, /* MHz */
- .unk2 = 3747,
- RADIOREGS(0x71, 0x02, 0x32, 0x04, 0x21, 0x01, 0x04, 0x0A,
- 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
- 0x80, 0x11, 0x00, 0x00, 0x00, 0x80),
- PHYREGS(0xCC08, 0xC808, 0xC408, 0xD201, 0xD201, 0xD301),
- },
- { .channel = 126,
- .freq = 5630, /* MHz */
- .unk2 = 3753,
- RADIOREGS(0x71, 0x02, 0x33, 0x04, 0x21, 0x01, 0x04, 0x0A,
- 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
- 0x80, 0x11, 0x00, 0x00, 0x00, 0x80),
- PHYREGS(0xD008, 0xCC08, 0xC808, 0xD101, 0xD201, 0xD201),
- },
- { .channel = 128,
- .freq = 5640, /* MHz */
- .unk2 = 3760,
- RADIOREGS(0x71, 0x02, 0x34, 0x03, 0x1C, 0x01, 0x04, 0x0A,
- 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
- PHYREGS(0xD408, 0xD008, 0xCC08, 0xD001, 0xD101, 0xD201),
- },
- { .channel = 130,
- .freq = 5650, /* MHz */
- .unk2 = 3767,
- RADIOREGS(0x71, 0x02, 0x35, 0x03, 0x1C, 0x01, 0x04, 0x0A,
- 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
- PHYREGS(0xD808, 0xD408, 0xD008, 0xCF01, 0xD001, 0xD101),
- },
- { .channel = 132,
- .freq = 5660, /* MHz */
- .unk2 = 3773,
- RADIOREGS(0x71, 0x02, 0x36, 0x03, 0x16, 0x01, 0x04, 0x0A,
- 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
- PHYREGS(0xDC08, 0xD808, 0xD408, 0xCE01, 0xCF01, 0xD001),
- },
- { .channel = 134,
- .freq = 5670, /* MHz */
- .unk2 = 3780,
- RADIOREGS(0x71, 0x02, 0x37, 0x03, 0x16, 0x01, 0x04, 0x0A,
- 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
- PHYREGS(0xE008, 0xDC08, 0xD808, 0xCE01, 0xCE01, 0xCF01),
- },
- { .channel = 136,
- .freq = 5680, /* MHz */
- .unk2 = 3787,
- RADIOREGS(0x71, 0x02, 0x38, 0x03, 0x10, 0x01, 0x04, 0x0A,
- 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
- PHYREGS(0xE408, 0xE008, 0xDC08, 0xCD01, 0xCE01, 0xCE01),
- },
- { .channel = 138,
- .freq = 5690, /* MHz */
- .unk2 = 3793,
- RADIOREGS(0x71, 0x02, 0x39, 0x03, 0x10, 0x01, 0x04, 0x0A,
- 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
- PHYREGS(0xE808, 0xE408, 0xE008, 0xCC01, 0xCD01, 0xCE01),
- },
- { .channel = 140,
- .freq = 5700, /* MHz */
- .unk2 = 3800,
- RADIOREGS(0x71, 0x02, 0x3A, 0x02, 0x0A, 0x01, 0x04, 0x0A,
- 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
- PHYREGS(0xEC08, 0xE808, 0xE408, 0xCB01, 0xCC01, 0xCD01),
- },
- { .channel = 142,
- .freq = 5710, /* MHz */
- .unk2 = 3807,
- RADIOREGS(0x71, 0x02, 0x3B, 0x02, 0x0A, 0x01, 0x04, 0x0A,
- 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
- PHYREGS(0xF008, 0xEC08, 0xE808, 0xCA01, 0xCB01, 0xCC01),
- },
- { .channel = 144,
- .freq = 5720, /* MHz */
- .unk2 = 3813,
- RADIOREGS(0x71, 0x02, 0x3C, 0x02, 0x0A, 0x01, 0x04, 0x0A,
- 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
- PHYREGS(0xF408, 0xF008, 0xEC08, 0xC901, 0xCA01, 0xCB01),
- },
- { .channel = 145,
- .freq = 5725, /* MHz */
- .unk2 = 3817,
- RADIOREGS(0x72, 0x04, 0x79, 0x02, 0x03, 0x01, 0x03, 0x14,
- 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
- PHYREGS(0xF608, 0xF208, 0xEE08, 0xC901, 0xCA01, 0xCB01),
- },
- { .channel = 146,
- .freq = 5730, /* MHz */
- .unk2 = 3820,
- RADIOREGS(0x71, 0x02, 0x3D, 0x02, 0x0A, 0x01, 0x04, 0x0A,
- 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
- PHYREGS(0xF808, 0xF408, 0xF008, 0xC901, 0xC901, 0xCA01),
- },
- { .channel = 147,
- .freq = 5735, /* MHz */
- .unk2 = 3823,
- RADIOREGS(0x72, 0x04, 0x7B, 0x02, 0x03, 0x01, 0x03, 0x14,
- 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
- PHYREGS(0xFA08, 0xF608, 0xF208, 0xC801, 0xC901, 0xCA01),
- },
- { .channel = 148,
- .freq = 5740, /* MHz */
- .unk2 = 3827,
- RADIOREGS(0x71, 0x02, 0x3E, 0x02, 0x0A, 0x01, 0x04, 0x0A,
- 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
- PHYREGS(0xFC08, 0xF808, 0xF408, 0xC801, 0xC901, 0xC901),
- },
- { .channel = 149,
- .freq = 5745, /* MHz */
- .unk2 = 3830,
- RADIOREGS(0x72, 0x04, 0x7D, 0x02, 0xFE, 0x00, 0x03, 0x14,
- 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
- PHYREGS(0xFE08, 0xFA08, 0xF608, 0xC801, 0xC801, 0xC901),
- },
- { .channel = 150,
- .freq = 5750, /* MHz */
- .unk2 = 3833,
- RADIOREGS(0x71, 0x02, 0x3F, 0x02, 0x0A, 0x01, 0x04, 0x0A,
- 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
- PHYREGS(0x0009, 0xFC08, 0xF808, 0xC701, 0xC801, 0xC901),
- },
- { .channel = 151,
- .freq = 5755, /* MHz */
- .unk2 = 3837,
- RADIOREGS(0x72, 0x04, 0x7F, 0x02, 0xFE, 0x00, 0x03, 0x14,
- 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
- PHYREGS(0x0209, 0xFE08, 0xFA08, 0xC701, 0xC801, 0xC801),
- },
- { .channel = 152,
- .freq = 5760, /* MHz */
- .unk2 = 3840,
- RADIOREGS(0x71, 0x02, 0x40, 0x02, 0x0A, 0x01, 0x04, 0x0A,
- 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
- PHYREGS(0x0409, 0x0009, 0xFC08, 0xC601, 0xC701, 0xC801),
- },
- { .channel = 153,
- .freq = 5765, /* MHz */
- .unk2 = 3843,
- RADIOREGS(0x72, 0x04, 0x81, 0x02, 0xF8, 0x00, 0x03, 0x14,
- 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
- PHYREGS(0x0609, 0x0209, 0xFE08, 0xC601, 0xC701, 0xC801),
- },
- { .channel = 154,
- .freq = 5770, /* MHz */
- .unk2 = 3847,
- RADIOREGS(0x71, 0x02, 0x41, 0x02, 0x0A, 0x01, 0x04, 0x0A,
- 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
- PHYREGS(0x0809, 0x0409, 0x0009, 0xC601, 0xC601, 0xC701),
- },
- { .channel = 155,
- .freq = 5775, /* MHz */
- .unk2 = 3850,
- RADIOREGS(0x72, 0x04, 0x83, 0x02, 0xF8, 0x00, 0x03, 0x14,
- 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
- PHYREGS(0x0A09, 0x0609, 0x0209, 0xC501, 0xC601, 0xC701),
- },
- { .channel = 156,
- .freq = 5780, /* MHz */
- .unk2 = 3853,
- RADIOREGS(0x71, 0x02, 0x42, 0x02, 0x0A, 0x01, 0x04, 0x0A,
- 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
- PHYREGS(0x0C09, 0x0809, 0x0409, 0xC501, 0xC601, 0xC601),
- },
- { .channel = 157,
- .freq = 5785, /* MHz */
- .unk2 = 3857,
- RADIOREGS(0x72, 0x04, 0x85, 0x02, 0xF2, 0x00, 0x03, 0x14,
- 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
- PHYREGS(0x0E09, 0x0A09, 0x0609, 0xC401, 0xC501, 0xC601),
- },
- { .channel = 158,
- .freq = 5790, /* MHz */
- .unk2 = 3860,
- RADIOREGS(0x71, 0x02, 0x43, 0x02, 0x0A, 0x01, 0x04, 0x0A,
- 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
- PHYREGS(0x1009, 0x0C09, 0x0809, 0xC401, 0xC501, 0xC601),
- },
- { .channel = 159,
- .freq = 5795, /* MHz */
- .unk2 = 3863,
- RADIOREGS(0x72, 0x04, 0x87, 0x02, 0xF2, 0x00, 0x03, 0x14,
- 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
- PHYREGS(0x1209, 0x0E09, 0x0A09, 0xC401, 0xC401, 0xC501),
- },
- { .channel = 160,
- .freq = 5800, /* MHz */
- .unk2 = 3867,
- RADIOREGS(0x71, 0x02, 0x44, 0x01, 0x0A, 0x01, 0x04, 0x0A,
- 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
- PHYREGS(0x1409, 0x1009, 0x0C09, 0xC301, 0xC401, 0xC501),
- },
- { .channel = 161,
- .freq = 5805, /* MHz */
- .unk2 = 3870,
- RADIOREGS(0x72, 0x04, 0x89, 0x01, 0xED, 0x00, 0x03, 0x14,
- 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
- PHYREGS(0x1609, 0x1209, 0x0E09, 0xC301, 0xC401, 0xC401),
- },
- { .channel = 162,
- .freq = 5810, /* MHz */
- .unk2 = 3873,
- RADIOREGS(0x71, 0x02, 0x45, 0x01, 0x0A, 0x01, 0x04, 0x0A,
- 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
- PHYREGS(0x1809, 0x1409, 0x1009, 0xC201, 0xC301, 0xC401),
- },
- { .channel = 163,
- .freq = 5815, /* MHz */
- .unk2 = 3877,
- RADIOREGS(0x72, 0x04, 0x8B, 0x01, 0xED, 0x00, 0x03, 0x14,
- 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
- PHYREGS(0x1A09, 0x1609, 0x1209, 0xC201, 0xC301, 0xC401),
- },
- { .channel = 164,
- .freq = 5820, /* MHz */
- .unk2 = 3880,
- RADIOREGS(0x71, 0x02, 0x46, 0x01, 0x0A, 0x01, 0x04, 0x0A,
- 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
- PHYREGS(0x1C09, 0x1809, 0x1409, 0xC201, 0xC201, 0xC301),
- },
- { .channel = 165,
- .freq = 5825, /* MHz */
- .unk2 = 3883,
- RADIOREGS(0x72, 0x04, 0x8D, 0x01, 0xED, 0x00, 0x03, 0x14,
- 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
- PHYREGS(0x1E09, 0x1A09, 0x1609, 0xC101, 0xC201, 0xC301),
- },
- { .channel = 166,
- .freq = 5830, /* MHz */
- .unk2 = 3887,
- RADIOREGS(0x71, 0x02, 0x47, 0x01, 0x0A, 0x01, 0x04, 0x0A,
- 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
- PHYREGS(0x2009, 0x1C09, 0x1809, 0xC101, 0xC201, 0xC201),
- },
- { .channel = 168,
- .freq = 5840, /* MHz */
- .unk2 = 3893,
- RADIOREGS(0x71, 0x02, 0x48, 0x01, 0x0A, 0x01, 0x04, 0x0A,
- 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
- PHYREGS(0x2409, 0x2009, 0x1C09, 0xC001, 0xC101, 0xC201),
- },
- { .channel = 170,
- .freq = 5850, /* MHz */
- .unk2 = 3900,
- RADIOREGS(0x71, 0x02, 0x49, 0x01, 0xE0, 0x00, 0x04, 0x0A,
- 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
- PHYREGS(0x2809, 0x2409, 0x2009, 0xBF01, 0xC001, 0xC101),
- },
- { .channel = 172,
- .freq = 5860, /* MHz */
- .unk2 = 3907,
- RADIOREGS(0x71, 0x02, 0x4A, 0x01, 0xDE, 0x00, 0x04, 0x0A,
- 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
- PHYREGS(0x2C09, 0x2809, 0x2409, 0xBF01, 0xBF01, 0xC001),
- },
- { .channel = 174,
- .freq = 5870, /* MHz */
- .unk2 = 3913,
- RADIOREGS(0x71, 0x02, 0x4B, 0x00, 0xDB, 0x00, 0x04, 0x0A,
- 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
- PHYREGS(0x3009, 0x2C09, 0x2809, 0xBE01, 0xBF01, 0xBF01),
- },
- { .channel = 176,
- .freq = 5880, /* MHz */
- .unk2 = 3920,
- RADIOREGS(0x71, 0x02, 0x4C, 0x00, 0xD8, 0x00, 0x04, 0x0A,
- 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
- PHYREGS(0x3409, 0x3009, 0x2C09, 0xBD01, 0xBE01, 0xBF01),
- },
- { .channel = 178,
- .freq = 5890, /* MHz */
- .unk2 = 3927,
- RADIOREGS(0x71, 0x02, 0x4D, 0x00, 0xD6, 0x00, 0x04, 0x0A,
- 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
- PHYREGS(0x3809, 0x3409, 0x3009, 0xBC01, 0xBD01, 0xBE01),
- },
- { .channel = 180,
- .freq = 5900, /* MHz */
- .unk2 = 3933,
- RADIOREGS(0x71, 0x02, 0x4E, 0x00, 0xD3, 0x00, 0x04, 0x0A,
- 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
- PHYREGS(0x3C09, 0x3809, 0x3409, 0xBC01, 0xBC01, 0xBD01),
- },
- { .channel = 182,
- .freq = 5910, /* MHz */
- .unk2 = 3940,
- RADIOREGS(0x71, 0x02, 0x4F, 0x00, 0xD6, 0x00, 0x04, 0x0A,
- 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
- PHYREGS(0x4009, 0x3C09, 0x3809, 0xBB01, 0xBC01, 0xBC01),
- },
- { .channel = 1,
- .freq = 2412, /* MHz */
- .unk2 = 3216,
- RADIOREGS(0x73, 0x09, 0x6C, 0x0F, 0x00, 0x01, 0x07, 0x15,
- 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0D, 0x0C,
- 0x80, 0xFF, 0x88, 0x0D, 0x0C, 0x80),
- PHYREGS(0xC903, 0xC503, 0xC103, 0x3A04, 0x3F04, 0x4304),
- },
- { .channel = 2,
- .freq = 2417, /* MHz */
- .unk2 = 3223,
- RADIOREGS(0x73, 0x09, 0x71, 0x0F, 0x00, 0x01, 0x07, 0x15,
- 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0B,
- 0x80, 0xFF, 0x88, 0x0C, 0x0B, 0x80),
- PHYREGS(0xCB03, 0xC703, 0xC303, 0x3804, 0x3D04, 0x4104),
- },
- { .channel = 3,
- .freq = 2422, /* MHz */
- .unk2 = 3229,
- RADIOREGS(0x73, 0x09, 0x76, 0x0F, 0x00, 0x01, 0x07, 0x15,
- 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0A,
- 0x80, 0xFF, 0x88, 0x0C, 0x0A, 0x80),
- PHYREGS(0xCD03, 0xC903, 0xC503, 0x3604, 0x3A04, 0x3F04),
- },
- { .channel = 4,
- .freq = 2427, /* MHz */
- .unk2 = 3236,
- RADIOREGS(0x73, 0x09, 0x7B, 0x0F, 0x00, 0x01, 0x07, 0x15,
- 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0A,
- 0x80, 0xFF, 0x88, 0x0C, 0x0A, 0x80),
- PHYREGS(0xCF03, 0xCB03, 0xC703, 0x3404, 0x3804, 0x3D04),
- },
- { .channel = 5,
- .freq = 2432, /* MHz */
- .unk2 = 3243,
- RADIOREGS(0x73, 0x09, 0x80, 0x0F, 0x00, 0x01, 0x07, 0x15,
- 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x09,
- 0x80, 0xFF, 0x88, 0x0C, 0x09, 0x80),
- PHYREGS(0xD103, 0xCD03, 0xC903, 0x3104, 0x3604, 0x3A04),
- },
- { .channel = 6,
- .freq = 2437, /* MHz */
- .unk2 = 3249,
- RADIOREGS(0x73, 0x09, 0x85, 0x0F, 0x00, 0x01, 0x07, 0x15,
- 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0B, 0x08,
- 0x80, 0xFF, 0x88, 0x0B, 0x08, 0x80),
- PHYREGS(0xD303, 0xCF03, 0xCB03, 0x2F04, 0x3404, 0x3804),
- },
- { .channel = 7,
- .freq = 2442, /* MHz */
- .unk2 = 3256,
- RADIOREGS(0x73, 0x09, 0x8A, 0x0F, 0x00, 0x01, 0x07, 0x15,
- 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0A, 0x07,
- 0x80, 0xFF, 0x88, 0x0A, 0x07, 0x80),
- PHYREGS(0xD503, 0xD103, 0xCD03, 0x2D04, 0x3104, 0x3604),
- },
- { .channel = 8,
- .freq = 2447, /* MHz */
- .unk2 = 3263,
- RADIOREGS(0x73, 0x09, 0x8F, 0x0F, 0x00, 0x01, 0x07, 0x15,
- 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0A, 0x06,
- 0x80, 0xFF, 0x88, 0x0A, 0x06, 0x80),
- PHYREGS(0xD703, 0xD303, 0xCF03, 0x2B04, 0x2F04, 0x3404),
- },
- { .channel = 9,
- .freq = 2452, /* MHz */
- .unk2 = 3269,
- RADIOREGS(0x73, 0x09, 0x94, 0x0F, 0x00, 0x01, 0x07, 0x15,
- 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x09, 0x06,
- 0x80, 0xFF, 0x88, 0x09, 0x06, 0x80),
- PHYREGS(0xD903, 0xD503, 0xD103, 0x2904, 0x2D04, 0x3104),
- },
- { .channel = 10,
- .freq = 2457, /* MHz */
- .unk2 = 3276,
- RADIOREGS(0x73, 0x09, 0x99, 0x0F, 0x00, 0x01, 0x07, 0x15,
- 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x05,
- 0x80, 0xFF, 0x88, 0x08, 0x05, 0x80),
- PHYREGS(0xDB03, 0xD703, 0xD303, 0x2704, 0x2B04, 0x2F04),
- },
- { .channel = 11,
- .freq = 2462, /* MHz */
- .unk2 = 3283,
- RADIOREGS(0x73, 0x09, 0x9E, 0x0F, 0x00, 0x01, 0x07, 0x15,
- 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x04,
- 0x80, 0xFF, 0x88, 0x08, 0x04, 0x80),
- PHYREGS(0xDD03, 0xD903, 0xD503, 0x2404, 0x2904, 0x2D04),
- },
- { .channel = 12,
- .freq = 2467, /* MHz */
- .unk2 = 3289,
- RADIOREGS(0x73, 0x09, 0xA3, 0x0F, 0x00, 0x01, 0x07, 0x15,
- 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x03,
- 0x80, 0xFF, 0x88, 0x08, 0x03, 0x80),
- PHYREGS(0xDF03, 0xDB03, 0xD703, 0x2204, 0x2704, 0x2B04),
- },
- { .channel = 13,
- .freq = 2472, /* MHz */
- .unk2 = 3296,
- RADIOREGS(0x73, 0x09, 0xA8, 0x0F, 0x00, 0x01, 0x07, 0x15,
- 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x07, 0x03,
- 0x80, 0xFF, 0x88, 0x07, 0x03, 0x80),
- PHYREGS(0xE103, 0xDD03, 0xD903, 0x2004, 0x2404, 0x2904),
- },
- { .channel = 14,
- .freq = 2484, /* MHz */
- .unk2 = 3312,
- RADIOREGS(0x73, 0x09, 0xB4, 0x0F, 0xFF, 0x01, 0x07, 0x15,
- 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x07, 0x01,
- 0x80, 0xFF, 0x88, 0x07, 0x01, 0x80),
- PHYREGS(0xE603, 0xE203, 0xDE03, 0x1B04, 0x1F04, 0x2404),
- },
-};
-
-const struct b43_nphy_channeltab_entry_rev2 *
-b43_nphy_get_chantabent_rev2(struct b43_wldev *dev, u8 channel)
-{
- const struct b43_nphy_channeltab_entry_rev2 *e;
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(b43_nphy_channeltab); i++) {
- e = &(b43_nphy_channeltab[i]);
- if (e->channel == channel)
- return e;
- }
-
- return NULL;
-}
-
-
static const u8 b43_ntab_adjustpower0[] = {
0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03,
diff --git a/drivers/net/wireless/b43/tables_nphy.h b/drivers/net/wireless/b43/tables_nphy.h
index 8fc1da9f8fe5..4ec593ba3eef 100644
--- a/drivers/net/wireless/b43/tables_nphy.h
+++ b/drivers/net/wireless/b43/tables_nphy.h
@@ -3,7 +3,6 @@
#include <linux/types.h>
-
struct b43_phy_n_sfo_cfg {
u16 phy_bw1a;
u16 phy_bw2;
@@ -13,52 +12,6 @@ struct b43_phy_n_sfo_cfg {
u16 phy_bw6;
};
-struct b43_nphy_channeltab_entry_rev2 {
- /* The channel number */
- u8 channel;
- /* The channel frequency in MHz */
- u16 freq;
- /* An unknown value */
- u16 unk2;
- /* Radio register values on channelswitch */
- u8 radio_pll_ref;
- u8 radio_rf_pllmod0;
- u8 radio_rf_pllmod1;
- u8 radio_vco_captail;
- u8 radio_vco_cal1;
- u8 radio_vco_cal2;
- u8 radio_pll_lfc1;
- u8 radio_pll_lfr1;
- u8 radio_pll_lfc2;
- u8 radio_lgbuf_cenbuf;
- u8 radio_lgen_tune1;
- u8 radio_lgen_tune2;
- u8 radio_c1_lgbuf_atune;
- u8 radio_c1_lgbuf_gtune;
- u8 radio_c1_rx_rfr1;
- u8 radio_c1_tx_pgapadtn;
- u8 radio_c1_tx_mxbgtrim;
- u8 radio_c2_lgbuf_atune;
- u8 radio_c2_lgbuf_gtune;
- u8 radio_c2_rx_rfr1;
- u8 radio_c2_tx_pgapadtn;
- u8 radio_c2_tx_mxbgtrim;
- /* PHY register values on channelswitch */
- struct b43_phy_n_sfo_cfg phy_regs;
-};
-
-struct b43_nphy_channeltab_entry_rev3 {
- /* The channel number */
- u8 channel;
- /* The channel frequency in MHz */
- u16 freq;
- /* Radio register values on channelswitch */
- /* TODO */
- /* PHY register values on channelswitch */
- struct b43_phy_n_sfo_cfg phy_regs;
-};
-
-
struct b43_wldev;
struct nphy_txiqcal_ladder {
@@ -82,18 +35,12 @@ struct nphy_rf_control_override_rev3 {
u8 val_addr1;
};
-/* Upload the default register value table.
- * If "ghz5" is true, we upload the 5Ghz table. Otherwise the 2.4Ghz
- * table is uploaded. If "ignore_uploadflag" is true, we upload any value
- * and ignore the "UPLOAD" flag. */
-void b2055_upload_inittab(struct b43_wldev *dev,
- bool ghz5, bool ignore_uploadflag);
-
-
-/* Get the NPHY Channel Switch Table entry for a channel number.
+/* Get the NPHY Channel Switch Table entry for a channel.
* Returns NULL on failure to find an entry. */
const struct b43_nphy_channeltab_entry_rev2 *
b43_nphy_get_chantabent_rev2(struct b43_wldev *dev, u8 channel);
+const struct b43_nphy_channeltab_entry_rev3 *
+b43_nphy_get_chantabent_rev3(struct b43_wldev *dev, u16 freq);
/* The N-PHY tables. */
diff --git a/drivers/net/wireless/b43legacy/debugfs.c b/drivers/net/wireless/b43legacy/debugfs.c
index 1f85ac569fec..f232618f2cd1 100644
--- a/drivers/net/wireless/b43legacy/debugfs.c
+++ b/drivers/net/wireless/b43legacy/debugfs.c
@@ -334,6 +334,7 @@ out_unlock:
.open = b43legacy_debugfs_open, \
.read = b43legacy_debugfs_read, \
.write = b43legacy_debugfs_write, \
+ .llseek = generic_file_llseek, \
}, \
.file_struct_offset = offsetof(struct b43legacy_dfsentry, \
file_##name), \
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index 1713f5f7a58b..67f18ecdb3bf 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -1623,6 +1623,7 @@ error:
static int b43legacy_upload_microcode(struct b43legacy_wldev *dev)
{
+ struct wiphy *wiphy = dev->wl->hw->wiphy;
const size_t hdr_len = sizeof(struct b43legacy_fw_header);
const __be32 *data;
unsigned int i;
@@ -1732,6 +1733,10 @@ static int b43legacy_upload_microcode(struct b43legacy_wldev *dev)
dev->fw.rev = fwrev;
dev->fw.patch = fwpatch;
+ snprintf(wiphy->fw_version, sizeof(wiphy->fw_version), "%u.%u",
+ dev->fw.rev, dev->fw.patch);
+ wiphy->hw_version = dev->dev->id.coreid;
+
return 0;
error:
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index ba54d1b04d22..bd8a4134edeb 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -12,7 +12,6 @@
#include <linux/wireless.h>
#include <net/iw_handler.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/ds.h>
@@ -437,7 +436,6 @@ static int hostap_cs_probe(struct pcmcia_device *p_dev)
int ret;
PDEBUG(DEBUG_HW, "%s: setting Vcc=33 (constant)\n", dev_info);
- p_dev->conf.IntType = INT_MEMORY_AND_IO;
ret = prism2_config(p_dev);
if (ret) {
@@ -468,74 +466,11 @@ static void prism2_detach(struct pcmcia_device *link)
}
-/* run after a CARD_INSERTION event is received to configure the PCMCIA
- * socket and make the device available to the system */
-
-static int prism2_config_check(struct pcmcia_device *p_dev,
- cistpl_cftable_entry_t *cfg,
- cistpl_cftable_entry_t *dflt,
- unsigned int vcc,
- void *priv_data)
+static int prism2_config_check(struct pcmcia_device *p_dev, void *priv_data)
{
- if (cfg->index == 0)
- return -ENODEV;
-
- PDEBUG(DEBUG_EXTRA, "Checking CFTABLE_ENTRY 0x%02X "
- "(default 0x%02X)\n", cfg->index, dflt->index);
-
- /* Does this card need audio output? */
- if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
- p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
- p_dev->conf.Status = CCSR_AUDIO_ENA;
- }
-
- /* Use power settings for Vcc and Vpp if present */
- /* Note that the CIS values need to be rescaled */
- if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
- if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] /
- 10000 && !ignore_cis_vcc) {
- PDEBUG(DEBUG_EXTRA, " Vcc mismatch - skipping"
- " this entry\n");
- return -ENODEV;
- }
- } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
- if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] /
- 10000 && !ignore_cis_vcc) {
- PDEBUG(DEBUG_EXTRA, " Vcc (default) mismatch "
- "- skipping this entry\n");
- return -ENODEV;
- }
- }
+ if (p_dev->config_index == 0)
+ return -EINVAL;
- if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
- p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
- else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
- p_dev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-
- /* Do we need to allocate an interrupt? */
- p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
-
- /* IO window settings */
- PDEBUG(DEBUG_EXTRA, "IO window settings: cfg->io.nwin=%d "
- "dflt->io.nwin=%d\n",
- cfg->io.nwin, dflt->io.nwin);
- p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
- if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
- cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
- p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
- p_dev->resource[0]->flags |=
- pcmcia_io_cfg_data_width(io->flags);
- p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
- p_dev->resource[0]->start = io->win[0].base;
- p_dev->resource[0]->end = io->win[0].len;
- if (io->nwin > 1) {
- p_dev->resource[1]->flags = p_dev->resource[0]->flags;
- p_dev->resource[1]->start = io->win[1].base;
- p_dev->resource[1]->end = io->win[1].len;
- }
- }
-
- /* This reserves IO space but doesn't actually enable it */
return pcmcia_request_io(p_dev);
}
@@ -557,6 +492,10 @@ static int prism2_config(struct pcmcia_device *link)
}
/* Look for an appropriate configuration table entry in the CIS */
+ link->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_AUDIO |
+ CONF_AUTO_CHECK_VCC | CONF_AUTO_SET_IO | CONF_ENABLE_IRQ;
+ if (ignore_cis_vcc)
+ link->config_flags &= ~CONF_AUTO_CHECK_VCC;
ret = pcmcia_loop_config(link, prism2_config_check, NULL);
if (ret) {
if (!ignore_cis_vcc)
@@ -588,12 +527,7 @@ static int prism2_config(struct pcmcia_device *link)
if (ret)
goto failed_unlock;
- /*
- * This actually configures the PCMCIA socket -- setting up
- * the I/O windows and the interrupt mapping, and putting the
- * card and host interface into "Memory and IO" mode.
- */
- ret = pcmcia_request_configuration(link, &link->conf);
+ ret = pcmcia_enable_device(link);
if (ret)
goto failed_unlock;
@@ -602,20 +536,6 @@ static int prism2_config(struct pcmcia_device *link)
spin_unlock_irqrestore(&local->irq_init_lock, flags);
- /* Finally, report what we've done */
- printk(KERN_INFO "%s: index 0x%02x: ",
- dev_info, link->conf.ConfigIndex);
- if (link->conf.Vpp)
- printk(", Vpp %d.%d", link->conf.Vpp / 10,
- link->conf.Vpp % 10);
- if (link->conf.Attributes & CONF_ENABLE_IRQ)
- printk(", irq %d", link->irq);
- if (link->resource[0])
- printk(" & %pR", link->resource[0]);
- if (link->resource[1])
- printk(" & %pR", link->resource[1]);
- printk("\n");
-
local->shutdown = 0;
sandisk_enable_wireless(dev);
@@ -627,7 +547,7 @@ static int prism2_config(struct pcmcia_device *link)
return ret;
failed_unlock:
- spin_unlock_irqrestore(&local->irq_init_lock, flags);
+ spin_unlock_irqrestore(&local->irq_init_lock, flags);
failed:
kfree(hw_priv);
prism2_release((u_long)link);
@@ -779,9 +699,7 @@ MODULE_DEVICE_TABLE(pcmcia, hostap_cs_ids);
static struct pcmcia_driver hostap_driver = {
- .drv = {
- .name = "hostap_cs",
- },
+ .name = "hostap_cs",
.probe = hostap_cs_probe,
.remove = prism2_detach,
.owner = THIS_MODULE,
diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c
index a85e43a8d758..6038633ef361 100644
--- a/drivers/net/wireless/hostap/hostap_ioctl.c
+++ b/drivers/net/wireless/hostap/hostap_ioctl.c
@@ -1696,7 +1696,7 @@ static int prism2_request_scan(struct net_device *dev)
hostap_set_word(dev, HFA384X_RID_CNFROAMINGMODE,
HFA384X_ROAMING_FIRMWARE);
- return 0;
+ return ret;
}
#else /* !PRISM2_NO_STATION_MODES */
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c
index 996e9d7d7586..61915f371416 100644
--- a/drivers/net/wireless/ipw2x00/ipw2100.c
+++ b/drivers/net/wireless/ipw2x00/ipw2100.c
@@ -1921,9 +1921,9 @@ static int ipw2100_net_init(struct net_device *dev)
bg_band->band = IEEE80211_BAND_2GHZ;
bg_band->n_channels = geo->bg_channels;
- bg_band->channels =
- kzalloc(geo->bg_channels *
- sizeof(struct ieee80211_channel), GFP_KERNEL);
+ bg_band->channels = kcalloc(geo->bg_channels,
+ sizeof(struct ieee80211_channel),
+ GFP_KERNEL);
if (!bg_band->channels) {
ipw2100_down(priv);
return -ENOMEM;
@@ -3056,9 +3056,9 @@ static void ipw2100_tx_send_commands(struct ipw2100_priv *priv)
packet = list_entry(element, struct ipw2100_tx_packet, list);
- IPW_DEBUG_TX("using TBD at virt=%p, phys=%p\n",
+ IPW_DEBUG_TX("using TBD at virt=%p, phys=%04X\n",
&txq->drv[txq->next],
- (void *)(txq->nic + txq->next *
+ (u32) (txq->nic + txq->next *
sizeof(struct ipw2100_bd)));
packet->index = txq->next;
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c
index cb2552a6777c..8d6ed5f6f46f 100644
--- a/drivers/net/wireless/ipw2x00/ipw2200.c
+++ b/drivers/net/wireless/ipw2x00/ipw2200.c
@@ -11467,9 +11467,13 @@ static int ipw_net_init(struct net_device *dev)
bg_band->band = IEEE80211_BAND_2GHZ;
bg_band->n_channels = geo->bg_channels;
- bg_band->channels =
- kzalloc(geo->bg_channels *
- sizeof(struct ieee80211_channel), GFP_KERNEL);
+ bg_band->channels = kcalloc(geo->bg_channels,
+ sizeof(struct ieee80211_channel),
+ GFP_KERNEL);
+ if (!bg_band->channels) {
+ rc = -ENOMEM;
+ goto out;
+ }
/* translate geo->bg to bg_band.channels */
for (i = 0; i < geo->bg_channels; i++) {
bg_band->channels[i].band = IEEE80211_BAND_2GHZ;
@@ -11502,9 +11506,13 @@ static int ipw_net_init(struct net_device *dev)
a_band->band = IEEE80211_BAND_5GHZ;
a_band->n_channels = geo->a_channels;
- a_band->channels =
- kzalloc(geo->a_channels *
- sizeof(struct ieee80211_channel), GFP_KERNEL);
+ a_band->channels = kcalloc(geo->a_channels,
+ sizeof(struct ieee80211_channel),
+ GFP_KERNEL);
+ if (!a_band->channels) {
+ rc = -ENOMEM;
+ goto out;
+ }
/* translate geo->bg to a_band.channels */
for (i = 0; i < geo->a_channels; i++) {
a_band->channels[i].band = IEEE80211_BAND_2GHZ;
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
index a51e4da1bdfc..b82364258dc5 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
@@ -3,6 +3,9 @@ config IWLWIFI
depends on PCI && MAC80211
select FW_LOADER
+menu "Debugging Options"
+ depends on IWLWIFI
+
config IWLWIFI_DEBUG
bool "Enable full debugging output in iwlagn and iwl3945 drivers"
depends on IWLWIFI
@@ -36,6 +39,12 @@ config IWLWIFI_DEBUGFS
is a low-impact option that allows getting insight into the
driver's state at runtime.
+config IWLWIFI_DEBUG_EXPERIMENTAL_UCODE
+ bool "Experimental uCode support"
+ depends on IWLWIFI && IWLWIFI_DEBUG
+ ---help---
+ Enable use of experimental ucode for testing and debugging.
+
config IWLWIFI_DEVICE_TRACING
bool "iwlwifi device access tracing"
depends on IWLWIFI
@@ -53,6 +62,7 @@ config IWLWIFI_DEVICE_TRACING
If unsure, say Y so we can help you better when problems
occur.
+endmenu
config IWLAGN
tristate "Intel Wireless WiFi Next Gen AGN (iwlagn)"
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile
index 728bb858ba97..63edbe2e557f 100644
--- a/drivers/net/wireless/iwlwifi/Makefile
+++ b/drivers/net/wireless/iwlwifi/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_IWLAGN) += iwlagn.o
iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o iwl-agn-ict.o
iwlagn-objs += iwl-agn-ucode.o iwl-agn-hcmd.o iwl-agn-tx.o
iwlagn-objs += iwl-agn-lib.o iwl-agn-rx.o iwl-agn-calib.o
+iwlagn-objs += iwl-agn-tt.o iwl-agn-sta.o iwl-agn-eeprom.o
iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-agn-debugfs.o
iwlagn-$(CONFIG_IWL4965) += iwl-4965.o
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c
index 0b779a41a142..db540910b110 100644
--- a/drivers/net/wireless/iwlwifi/iwl-1000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-1000.c
@@ -50,14 +50,20 @@
/* Highest firmware API version supported */
#define IWL1000_UCODE_API_MAX 3
+#define IWL100_UCODE_API_MAX 5
/* Lowest firmware API version supported */
#define IWL1000_UCODE_API_MIN 1
+#define IWL100_UCODE_API_MIN 5
#define IWL1000_FW_PRE "iwlwifi-1000-"
#define _IWL1000_MODULE_FIRMWARE(api) IWL1000_FW_PRE #api ".ucode"
#define IWL1000_MODULE_FIRMWARE(api) _IWL1000_MODULE_FIRMWARE(api)
+#define IWL100_FW_PRE "iwlwifi-100-"
+#define _IWL100_MODULE_FIRMWARE(api) IWL100_FW_PRE #api ".ucode"
+#define IWL100_MODULE_FIRMWARE(api) _IWL100_MODULE_FIRMWARE(api)
+
/*
* For 1000, use advance thermal throttling critical temperature threshold,
@@ -120,17 +126,17 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv)
{
if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES &&
priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES)
- priv->cfg->num_of_queues =
+ priv->cfg->base_params->num_of_queues =
priv->cfg->mod_params->num_of_queues;
- priv->hw_params.max_txq_num = priv->cfg->num_of_queues;
+ priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues;
priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM;
priv->hw_params.scd_bc_tbls_size =
- priv->cfg->num_of_queues *
+ priv->cfg->base_params->num_of_queues *
sizeof(struct iwlagn_scd_bc_tbl);
priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
priv->hw_params.max_stations = IWLAGN_STATION_COUNT;
- priv->hw_params.bcast_sta_id = IWLAGN_BROADCAST_ID;
+ priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID;
priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE;
priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE;
@@ -145,8 +151,7 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv)
priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant;
priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant;
- if (priv->cfg->ops->lib->temp_ops.set_ct_kill)
- priv->cfg->ops->lib->temp_ops.set_ct_kill(priv);
+ iwl1000_set_ct_threshold(priv);
/* Set initial sensitivity parameters */
/* Set initial calibration set */
@@ -189,9 +194,7 @@ static struct iwl_lib_ops iwl1000_lib = {
.update_chain_flags = iwl_update_chain_flags,
.apm_ops = {
.init = iwl_apm_init,
- .stop = iwl_apm_stop,
.config = iwl1000_nic_config,
- .set_pwr_src = iwl_set_pwr_src,
},
.eeprom_ops = {
.regulatory_bands = {
@@ -203,7 +206,6 @@ static struct iwl_lib_ops iwl1000_lib = {
EEPROM_REG_BAND_24_HT40_CHANNELS,
EEPROM_REG_BAND_52_HT40_CHANNELS
},
- .verify_signature = iwlcore_eeprom_verify_signature,
.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
.release_semaphore = iwlcore_eeprom_release_semaphore,
.calib_version = iwlagn_eeprom_calib_version,
@@ -214,21 +216,26 @@ static struct iwl_lib_ops iwl1000_lib = {
.config_ap = iwl_config_ap,
.temp_ops = {
.temperature = iwlagn_temperature,
- .set_ct_kill = iwl1000_set_ct_threshold,
},
.manage_ibss_station = iwlagn_manage_ibss_station,
- .update_bcast_station = iwl_update_bcast_station,
+ .update_bcast_stations = iwl_update_bcast_stations,
.debugfs_ops = {
.rx_stats_read = iwl_ucode_rx_stats_read,
.tx_stats_read = iwl_ucode_tx_stats_read,
.general_stats_read = iwl_ucode_general_stats_read,
.bt_stats_read = iwl_ucode_bt_stats_read,
+ .reply_tx_error = iwl_reply_tx_error_read,
},
.recover_from_tx_stall = iwl_bg_monitor_recover,
.check_plcp_health = iwl_good_plcp_health,
.check_ack_health = iwl_good_ack_health,
.txfifo_flush = iwlagn_txfifo_flush,
.dev_txfifo_flush = iwlagn_dev_txfifo_flush,
+ .tt_ops = {
+ .lower_power_detection = iwl_tt_is_low_power_state,
+ .tt_power_mode = iwl_tt_current_power_mode,
+ .ct_kill_check = iwl_check_for_ct_kill,
+ }
};
static const struct iwl_ops iwl1000_ops = {
@@ -238,29 +245,16 @@ static const struct iwl_ops iwl1000_ops = {
.led = &iwlagn_led_ops,
};
-struct iwl_cfg iwl1000_bgn_cfg = {
- .name = "Intel(R) Centrino(R) Wireless-N 1000 BGN",
- .fw_name_pre = IWL1000_FW_PRE,
- .ucode_api_max = IWL1000_UCODE_API_MAX,
- .ucode_api_min = IWL1000_UCODE_API_MIN,
- .sku = IWL_SKU_G|IWL_SKU_N,
- .ops = &iwl1000_ops,
- .eeprom_size = OTP_LOW_IMAGE_SIZE,
- .eeprom_ver = EEPROM_1000_EEPROM_VERSION,
- .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION,
+static struct iwl_base_params iwl1000_base_params = {
.num_of_queues = IWLAGN_NUM_QUEUES,
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
- .mod_params = &iwlagn_mod_params,
- .valid_tx_ant = ANT_A,
- .valid_rx_ant = ANT_AB,
+ .eeprom_size = OTP_LOW_IMAGE_SIZE,
.pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
.set_l0s = true,
.use_bsm = false,
.max_ll_items = OTP_MAX_LL_ITEMS_1000,
.shadow_ram_support = false,
- .ht_greenfield_support = true,
.led_compensation = 51,
- .use_rts_for_aggregation = true, /* use rts/cts protection */
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
.support_ct_kill_exit = true,
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF,
@@ -271,6 +265,26 @@ struct iwl_cfg iwl1000_bgn_cfg = {
.sensitivity_calib_by_driver = true,
.chain_noise_calib_by_driver = true,
};
+static struct iwl_ht_params iwl1000_ht_params = {
+ .ht_greenfield_support = true,
+ .use_rts_for_aggregation = true, /* use rts/cts protection */
+};
+
+struct iwl_cfg iwl1000_bgn_cfg = {
+ .name = "Intel(R) Centrino(R) Wireless-N 1000 BGN",
+ .fw_name_pre = IWL1000_FW_PRE,
+ .ucode_api_max = IWL1000_UCODE_API_MAX,
+ .ucode_api_min = IWL1000_UCODE_API_MIN,
+ .sku = IWL_SKU_G|IWL_SKU_N,
+ .valid_tx_ant = ANT_A,
+ .valid_rx_ant = ANT_AB,
+ .eeprom_ver = EEPROM_1000_EEPROM_VERSION,
+ .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION,
+ .ops = &iwl1000_ops,
+ .mod_params = &iwlagn_mod_params,
+ .base_params = &iwl1000_base_params,
+ .ht_params = &iwl1000_ht_params,
+};
struct iwl_cfg iwl1000_bg_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N 1000 BG",
@@ -278,30 +292,45 @@ struct iwl_cfg iwl1000_bg_cfg = {
.ucode_api_max = IWL1000_UCODE_API_MAX,
.ucode_api_min = IWL1000_UCODE_API_MIN,
.sku = IWL_SKU_G,
+ .valid_tx_ant = ANT_A,
+ .valid_rx_ant = ANT_AB,
+ .eeprom_ver = EEPROM_1000_EEPROM_VERSION,
+ .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION,
.ops = &iwl1000_ops,
- .eeprom_size = OTP_LOW_IMAGE_SIZE,
+ .mod_params = &iwlagn_mod_params,
+ .base_params = &iwl1000_base_params,
+};
+
+struct iwl_cfg iwl100_bgn_cfg = {
+ .name = "Intel(R) 100 Series 1x1 BGN",
+ .fw_name_pre = IWL100_FW_PRE,
+ .ucode_api_max = IWL100_UCODE_API_MAX,
+ .ucode_api_min = IWL100_UCODE_API_MIN,
+ .sku = IWL_SKU_G|IWL_SKU_N,
+ .valid_tx_ant = ANT_A,
+ .valid_rx_ant = ANT_A,
.eeprom_ver = EEPROM_1000_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION,
- .num_of_queues = IWLAGN_NUM_QUEUES,
- .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
+ .ops = &iwl1000_ops,
.mod_params = &iwlagn_mod_params,
+ .base_params = &iwl1000_base_params,
+ .ht_params = &iwl1000_ht_params,
+};
+
+struct iwl_cfg iwl100_bg_cfg = {
+ .name = "Intel(R) 100 Series 1x1 BG",
+ .fw_name_pre = IWL100_FW_PRE,
+ .ucode_api_max = IWL100_UCODE_API_MAX,
+ .ucode_api_min = IWL100_UCODE_API_MIN,
+ .sku = IWL_SKU_G,
.valid_tx_ant = ANT_A,
- .valid_rx_ant = ANT_AB,
- .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
- .set_l0s = true,
- .use_bsm = false,
- .max_ll_items = OTP_MAX_LL_ITEMS_1000,
- .shadow_ram_support = false,
- .led_compensation = 51,
- .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
- .support_ct_kill_exit = true,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF,
- .chain_noise_scale = 1000,
- .monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
- .max_event_log_size = 128,
- .ucode_tracing = true,
- .sensitivity_calib_by_driver = true,
- .chain_noise_calib_by_driver = true,
+ .valid_rx_ant = ANT_A,
+ .eeprom_ver = EEPROM_1000_EEPROM_VERSION,
+ .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION,
+ .ops = &iwl1000_ops,
+ .mod_params = &iwlagn_mod_params,
+ .base_params = &iwl1000_base_params,
};
MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL100_MODULE_FIRMWARE(IWL100_UCODE_API_MAX));
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
index 7c731a793632..65b5834da28c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
@@ -62,7 +62,7 @@
*****************************************************************************/
/*
* Please use this file (iwl-3945-hw.h) only for hardware-related definitions.
- * Please use iwl-3945-commands.h for uCode API definitions.
+ * Please use iwl-commands.h for uCode API definitions.
* Please use iwl-3945.h for driver implementation definitions.
*/
@@ -226,6 +226,7 @@ struct iwl3945_eeprom {
/* 4 DATA + 1 CMD. There are 2 HCCA queues that are not used. */
#define IWL39_NUM_QUEUES 5
+#define IWL39_CMD_QUEUE_NUM 4
#define IWL_DEFAULT_TX_RETRY 15
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
index 8e84a08ff951..1f3e7e34fbc7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
@@ -343,7 +343,7 @@ void iwl3945_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 s
int i;
IWL_DEBUG_INFO(priv, "enter\n");
- if (sta_id == priv->hw_params.bcast_sta_id)
+ if (sta_id == priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id)
goto out;
psta = (struct iwl3945_sta_priv *) sta->drv_priv;
@@ -873,6 +873,7 @@ static ssize_t iwl3945_sta_dbgfs_stats_table_read(struct file *file,
static const struct file_operations rs_sta_dbgfs_stats_table_ops = {
.read = iwl3945_sta_dbgfs_stats_table_read,
.open = iwl3945_open_file_generic,
+ .llseek = default_llseek,
};
static void iwl3945_add_debugfs(void *priv, void *priv_sta,
@@ -932,7 +933,7 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
rcu_read_lock();
- sta = ieee80211_find_sta(priv->vif,
+ sta = ieee80211_find_sta(priv->contexts[IWL_RXON_CTX_BSS].vif,
priv->stations[sta_id].sta.sta.addr);
if (!sta) {
IWL_DEBUG_RATE(priv, "Unable to find station to initialize rate scaling.\n");
@@ -949,7 +950,8 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
switch (priv->band) {
case IEEE80211_BAND_2GHZ:
/* TODO: this always does G, not a regression */
- if (priv->active_rxon.flags & RXON_FLG_TGG_PROTECT_MSK) {
+ if (priv->contexts[IWL_RXON_CTX_BSS].active.flags &
+ RXON_FLG_TGG_PROTECT_MSK) {
rs_sta->tgg = 1;
rs_sta->expected_tpt = iwl3945_expected_tpt_g_prot;
} else
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index 8ccfcd08218d..176e52577673 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -87,6 +87,15 @@ const struct iwl3945_rate_info iwl3945_rates[IWL_RATE_COUNT_3945] = {
IWL_DECLARE_RATE_INFO(54, 48, INV, 48, INV, 48, INV),/* 54mbps */
};
+static inline u8 iwl3945_get_prev_ieee_rate(u8 rate_index)
+{
+ u8 rate = iwl3945_rates[rate_index].prev_ieee;
+
+ if (rate == IWL_RATE_INVALID)
+ rate = rate_index;
+ return rate;
+}
+
/* 1 = enable the iwl3945_disable_events() function */
#define IWL_EVT_DISABLE (0)
#define IWL_EVT_DISABLE_SIZE (1532/32)
@@ -245,7 +254,7 @@ int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate)
break;
case IEEE80211_BAND_2GHZ:
if (!(priv->_3945.sta_supp_rates & IWL_OFDM_RATES_MASK) &&
- iwl_is_associated(priv)) {
+ iwl_is_associated(priv, IWL_RXON_CTX_BSS)) {
if (rate == IWL_RATE_11M_INDEX)
next_rate = IWL_RATE_5M_INDEX;
}
@@ -273,7 +282,7 @@ static void iwl3945_tx_queue_reclaim(struct iwl_priv *priv,
struct iwl_queue *q = &txq->q;
struct iwl_tx_info *tx_info;
- BUG_ON(txq_id == IWL_CMD_QUEUE_NUM);
+ BUG_ON(txq_id == IWL39_CMD_QUEUE_NUM);
for (index = iwl_queue_inc_wrap(index, q->n_bd); q->read_ptr != index;
q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
@@ -285,7 +294,7 @@ static void iwl3945_tx_queue_reclaim(struct iwl_priv *priv,
}
if (iwl_queue_space(q) > q->low_mark && (txq_id >= 0) &&
- (txq_id != IWL_CMD_QUEUE_NUM) &&
+ (txq_id != IWL39_CMD_QUEUE_NUM) &&
priv->mac80211_registered)
iwl_wake_queue(priv, txq_id);
}
@@ -339,7 +348,7 @@ static void iwl3945_rx_reply_tx(struct iwl_priv *priv,
IWL_DEBUG_TX_REPLY(priv, "Tx queue reclaim %d\n", index);
iwl3945_tx_queue_reclaim(priv, txq_id, index);
- if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK))
+ if (status & TX_ABORT_REQUIRED_MSK)
IWL_ERR(priv, "TODO: Implement Tx ABORT REQUIRED!!!\n");
}
@@ -406,7 +415,7 @@ static bool iwl3945_good_plcp_health(struct iwl_priv *priv,
unsigned int plcp_msec;
unsigned long plcp_received_jiffies;
- if (priv->cfg->plcp_delta_threshold ==
+ if (priv->cfg->base_params->plcp_delta_threshold ==
IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE) {
IWL_DEBUG_RADIO(priv, "plcp_err check disabled\n");
return rc;
@@ -432,7 +441,7 @@ static bool iwl3945_good_plcp_health(struct iwl_priv *priv,
if ((combined_plcp_delta > 0) &&
((combined_plcp_delta * 100) / plcp_msec) >
- priv->cfg->plcp_delta_threshold) {
+ priv->cfg->base_params->plcp_delta_threshold) {
/*
* if plcp_err exceed the threshold, the following
* data is printed in csv format:
@@ -444,7 +453,7 @@ static bool iwl3945_good_plcp_health(struct iwl_priv *priv,
*/
IWL_DEBUG_RADIO(priv, "plcp_err exceeded %u, "
"%u, %d, %u mSecs\n",
- priv->cfg->plcp_delta_threshold,
+ priv->cfg->base_params->plcp_delta_threshold,
le32_to_cpu(current_stat.rx.ofdm.plcp_err),
combined_plcp_delta, plcp_msec);
/*
@@ -760,7 +769,7 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv,
data_retry_limit = IWL_DEFAULT_TX_RETRY;
tx_cmd->data_retry_limit = data_retry_limit;
- if (tx_id >= IWL_CMD_QUEUE_NUM)
+ if (tx_id >= IWL39_CMD_QUEUE_NUM)
rts_retry_limit = 3;
else
rts_retry_limit = 7;
@@ -807,9 +816,12 @@ static u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, u16 tx_rate)
return sta_id;
}
-static int iwl3945_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src)
+static void iwl3945_set_pwr_vmain(struct iwl_priv *priv)
{
- if (src == IWL_PWR_SRC_VAUX) {
+/*
+ * (for documentation purposes)
+ * to set power to V_AUX, do
+
if (pci_pme_capable(priv->pci_dev, PCI_D3cold)) {
iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
APMG_PS_CTRL_VAL_PWR_SRC_VAUX,
@@ -819,16 +831,14 @@ static int iwl3945_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src)
CSR_GPIO_IN_VAL_VAUX_PWR_SRC,
CSR_GPIO_IN_BIT_AUX_POWER, 5000);
}
- } else {
- iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
- APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
- ~APMG_PS_CTRL_MSK_PWR_SRC);
+ */
- iwl_poll_bit(priv, CSR_GPIO_IN, CSR_GPIO_IN_VAL_VMAIN_PWR_SRC,
- CSR_GPIO_IN_BIT_AUX_POWER, 5000); /* uS */
- }
+ iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
+ APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
+ ~APMG_PS_CTRL_MSK_PWR_SRC);
- return 0;
+ iwl_poll_bit(priv, CSR_GPIO_IN, CSR_GPIO_IN_VAL_VMAIN_PWR_SRC,
+ CSR_GPIO_IN_BIT_AUX_POWER, 5000); /* uS */
}
static int iwl3945_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
@@ -909,7 +919,7 @@ static int iwl3945_txq_ctx_reset(struct iwl_priv *priv)
/* Tx queue(s) */
for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
- slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ?
+ slots_num = (txq_id == IWL39_CMD_QUEUE_NUM) ?
TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
rc = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num,
txq_id);
@@ -1022,9 +1032,7 @@ int iwl3945_hw_nic_init(struct iwl_priv *priv)
priv->cfg->ops->lib->apm_ops.init(priv);
spin_unlock_irqrestore(&priv->lock, flags);
- rc = priv->cfg->ops->lib->apm_ops.set_pwr_src(priv, IWL_PWR_SRC_VMAIN);
- if (rc)
- return rc;
+ iwl3945_set_pwr_vmain(priv);
priv->cfg->ops->lib->apm_ops.config(priv);
@@ -1072,7 +1080,7 @@ void iwl3945_hw_txq_ctx_free(struct iwl_priv *priv)
if (priv->txq)
for (txq_id = 0; txq_id < priv->hw_params.max_txq_num;
txq_id++)
- if (txq_id == IWL_CMD_QUEUE_NUM)
+ if (txq_id == IWL39_CMD_QUEUE_NUM)
iwl_cmd_queue_free(priv);
else
iwl_tx_queue_free(priv, txq_id);
@@ -1439,17 +1447,18 @@ static int iwl3945_send_tx_power(struct iwl_priv *priv)
int rate_idx, i;
const struct iwl_channel_info *ch_info = NULL;
struct iwl3945_txpowertable_cmd txpower = {
- .channel = priv->active_rxon.channel,
+ .channel = priv->contexts[IWL_RXON_CTX_BSS].active.channel,
};
+ u16 chan;
+
+ chan = le16_to_cpu(priv->contexts[IWL_RXON_CTX_BSS].active.channel);
txpower.band = (priv->band == IEEE80211_BAND_5GHZ) ? 0 : 1;
- ch_info = iwl_get_channel_info(priv,
- priv->band,
- le16_to_cpu(priv->active_rxon.channel));
+ ch_info = iwl_get_channel_info(priv, priv->band, chan);
if (!ch_info) {
IWL_ERR(priv,
"Failed to get channel info for channel %d [%d]\n",
- le16_to_cpu(priv->active_rxon.channel), priv->band);
+ chan, priv->band);
return -EINVAL;
}
@@ -1710,7 +1719,8 @@ int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power)
return 0;
}
-static int iwl3945_send_rxon_assoc(struct iwl_priv *priv)
+static int iwl3945_send_rxon_assoc(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx)
{
int rc = 0;
struct iwl_rx_packet *pkt;
@@ -1721,8 +1731,8 @@ static int iwl3945_send_rxon_assoc(struct iwl_priv *priv)
.flags = CMD_WANT_SKB,
.data = &rxon_assoc,
};
- const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon;
- const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon;
+ const struct iwl_rxon_cmd *rxon1 = &ctx->staging;
+ const struct iwl_rxon_cmd *rxon2 = &ctx->active;
if ((rxon1->flags == rxon2->flags) &&
(rxon1->filter_flags == rxon2->filter_flags) &&
@@ -1732,10 +1742,10 @@ static int iwl3945_send_rxon_assoc(struct iwl_priv *priv)
return 0;
}
- rxon_assoc.flags = priv->staging_rxon.flags;
- rxon_assoc.filter_flags = priv->staging_rxon.filter_flags;
- rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates;
- rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates;
+ rxon_assoc.flags = ctx->staging.flags;
+ rxon_assoc.filter_flags = ctx->staging.filter_flags;
+ rxon_assoc.ofdm_basic_rates = ctx->staging.ofdm_basic_rates;
+ rxon_assoc.cck_basic_rates = ctx->staging.cck_basic_rates;
rxon_assoc.reserved = 0;
rc = iwl_send_cmd_sync(priv, &cmd);
@@ -1761,14 +1771,13 @@ static int iwl3945_send_rxon_assoc(struct iwl_priv *priv)
* function correctly transitions out of the RXON_ASSOC_MSK state if
* a HW tune is required based on the RXON structure changes.
*/
-static int iwl3945_commit_rxon(struct iwl_priv *priv)
+int iwl3945_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
{
/* cast away the const for active_rxon in this function */
- struct iwl3945_rxon_cmd *active_rxon = (void *)&priv->active_rxon;
- struct iwl3945_rxon_cmd *staging_rxon = (void *)&priv->staging_rxon;
+ struct iwl3945_rxon_cmd *active_rxon = (void *)&ctx->active;
+ struct iwl3945_rxon_cmd *staging_rxon = (void *)&ctx->staging;
int rc = 0;
- bool new_assoc =
- !!(priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK);
+ bool new_assoc = !!(staging_rxon->filter_flags & RXON_FILTER_ASSOC_MSK);
if (!iwl_is_alive(priv))
return -1;
@@ -1781,7 +1790,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv)
~(RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_SEL_MSK);
staging_rxon->flags |= iwl3945_get_antenna_flags(priv);
- rc = iwl_check_rxon_cmd(priv);
+ rc = iwl_check_rxon_cmd(priv, ctx);
if (rc) {
IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n");
return -EINVAL;
@@ -1790,8 +1799,9 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv)
/* If we don't need to send a full RXON, we can use
* iwl3945_rxon_assoc_cmd which is used to reconfigure filter
* and other flags for the current radio configuration. */
- if (!iwl_full_rxon_required(priv)) {
- rc = iwl_send_rxon_assoc(priv);
+ if (!iwl_full_rxon_required(priv, &priv->contexts[IWL_RXON_CTX_BSS])) {
+ rc = iwl_send_rxon_assoc(priv,
+ &priv->contexts[IWL_RXON_CTX_BSS]);
if (rc) {
IWL_ERR(priv, "Error setting RXON_ASSOC "
"configuration (%d).\n", rc);
@@ -1807,7 +1817,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv)
* an RXON_ASSOC and the new config wants the associated mask enabled,
* we must clear the associated from the active configuration
* before we apply the new config */
- if (iwl_is_associated(priv) && new_assoc) {
+ if (iwl_is_associated(priv, IWL_RXON_CTX_BSS) && new_assoc) {
IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n");
active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
@@ -1819,7 +1829,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv)
active_rxon->reserved5 = 0;
rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
sizeof(struct iwl3945_rxon_cmd),
- &priv->active_rxon);
+ &priv->contexts[IWL_RXON_CTX_BSS].active);
/* If the mask clearing failed then we set
* active_rxon back to what it was previously */
@@ -1829,8 +1839,9 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv)
"configuration (%d).\n", rc);
return rc;
}
- iwl_clear_ucode_stations(priv);
- iwl_restore_stations(priv);
+ iwl_clear_ucode_stations(priv,
+ &priv->contexts[IWL_RXON_CTX_BSS]);
+ iwl_restore_stations(priv, &priv->contexts[IWL_RXON_CTX_BSS]);
}
IWL_DEBUG_INFO(priv, "Sending RXON\n"
@@ -1848,7 +1859,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv)
staging_rxon->reserved4 = 0;
staging_rxon->reserved5 = 0;
- iwl_set_rxon_hwcrypto(priv, !iwl3945_mod_params.sw_crypto);
+ iwl_set_rxon_hwcrypto(priv, ctx, !iwl3945_mod_params.sw_crypto);
/* Apply the new configuration */
rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
@@ -1862,8 +1873,9 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv)
memcpy(active_rxon, staging_rxon, sizeof(*active_rxon));
if (!new_assoc) {
- iwl_clear_ucode_stations(priv);
- iwl_restore_stations(priv);
+ iwl_clear_ucode_stations(priv,
+ &priv->contexts[IWL_RXON_CTX_BSS]);
+ iwl_restore_stations(priv, &priv->contexts[IWL_RXON_CTX_BSS]);
}
/* If we issue a new RXON command which required a tune then we must
@@ -2295,6 +2307,32 @@ static u16 iwl3945_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data)
return (u16)sizeof(struct iwl3945_addsta_cmd);
}
+static int iwl3945_add_bssid_station(struct iwl_priv *priv,
+ const u8 *addr, u8 *sta_id_r)
+{
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+ int ret;
+ u8 sta_id;
+ unsigned long flags;
+
+ if (sta_id_r)
+ *sta_id_r = IWL_INVALID_STATION;
+
+ ret = iwl_add_station_common(priv, ctx, addr, 0, NULL, &sta_id);
+ if (ret) {
+ IWL_ERR(priv, "Unable to add station %pM\n", addr);
+ return ret;
+ }
+
+ if (sta_id_r)
+ *sta_id_r = sta_id;
+
+ spin_lock_irqsave(&priv->sta_lock, flags);
+ priv->stations[sta_id].used |= IWL_STA_LOCAL;
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+ return 0;
+}
static int iwl3945_manage_ibss_station(struct iwl_priv *priv,
struct ieee80211_vif *vif, bool add)
{
@@ -2302,8 +2340,8 @@ static int iwl3945_manage_ibss_station(struct iwl_priv *priv,
int ret;
if (add) {
- ret = iwl_add_bssid_station(priv, vif->bss_conf.bssid, false,
- &vif_priv->ibss_bssid_sta_id);
+ ret = iwl3945_add_bssid_station(priv, vif->bss_conf.bssid,
+ &vif_priv->ibss_bssid_sta_id);
if (ret)
return ret;
@@ -2366,7 +2404,7 @@ int iwl3945_init_hw_rate_table(struct iwl_priv *priv)
* 1M CCK rates */
if (!(priv->_3945.sta_supp_rates & IWL_OFDM_RATES_MASK) &&
- iwl_is_associated(priv)) {
+ iwl_is_associated(priv, IWL_RXON_CTX_BSS)) {
index = IWL_FIRST_CCK_RATE;
for (i = IWL_RATE_6M_INDEX_TABLE;
@@ -2414,14 +2452,16 @@ int iwl3945_hw_set_hw_params(struct iwl_priv *priv)
}
/* Assign number of Usable TX queues */
- priv->hw_params.max_txq_num = priv->cfg->num_of_queues;
+ priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues;
priv->hw_params.tfd_size = sizeof(struct iwl3945_tfd);
priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_3K);
priv->hw_params.max_rxq_size = RX_QUEUE_SIZE;
priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG;
priv->hw_params.max_stations = IWL3945_STATION_COUNT;
- priv->hw_params.bcast_sta_id = IWL3945_BROADCAST_ID;
+ priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWL3945_BROADCAST_ID;
+
+ priv->sta_key_max_num = STA_KEY_MAX_NUM;
priv->hw_params.rx_wrt_ptr_reg = FH39_RSCSR_CHNL0_WPTR;
priv->hw_params.max_beacon_itrvl = IWL39_MAX_UCODE_BEACON_INTERVAL;
@@ -2439,7 +2479,8 @@ unsigned int iwl3945_hw_get_beacon_cmd(struct iwl_priv *priv,
tx_beacon_cmd = (struct iwl3945_tx_beacon_cmd *)&frame->u;
memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd));
- tx_beacon_cmd->tx.sta_id = priv->hw_params.bcast_sta_id;
+ tx_beacon_cmd->tx.sta_id =
+ priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id;
tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
frame_size = iwl3945_fill_beacon_frame(priv,
@@ -2663,9 +2704,7 @@ static struct iwl_lib_ops iwl3945_lib = {
.dump_nic_error_log = iwl3945_dump_nic_error_log,
.apm_ops = {
.init = iwl3945_apm_init,
- .stop = iwl_apm_stop,
.config = iwl3945_nic_config,
- .set_pwr_src = iwl3945_set_pwr_src,
},
.eeprom_ops = {
.regulatory_bands = {
@@ -2677,7 +2716,6 @@ static struct iwl_lib_ops iwl3945_lib = {
EEPROM_REGULATORY_BAND_NO_HT40,
EEPROM_REGULATORY_BAND_NO_HT40,
},
- .verify_signature = iwlcore_eeprom_verify_signature,
.acquire_semaphore = iwl3945_eeprom_acquire_semaphore,
.release_semaphore = iwl3945_eeprom_release_semaphore,
.query_addr = iwlcore_eeprom_query_addr,
@@ -2703,6 +2741,7 @@ static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = {
.build_addsta_hcmd = iwl3945_build_addsta_hcmd,
.tx_cmd_protection = iwlcore_tx_cmd_protection,
.request_scan = iwl3945_request_scan,
+ .post_scan = iwl3945_post_scan,
};
static const struct iwl_ops iwl3945_ops = {
@@ -2712,22 +2751,13 @@ static const struct iwl_ops iwl3945_ops = {
.led = &iwl3945_led_ops,
};
-static struct iwl_cfg iwl3945_bg_cfg = {
- .name = "3945BG",
- .fw_name_pre = IWL3945_FW_PRE,
- .ucode_api_max = IWL3945_UCODE_API_MAX,
- .ucode_api_min = IWL3945_UCODE_API_MIN,
- .sku = IWL_SKU_G,
+static struct iwl_base_params iwl3945_base_params = {
.eeprom_size = IWL3945_EEPROM_IMG_SIZE,
- .eeprom_ver = EEPROM_3945_EEPROM_VERSION,
- .ops = &iwl3945_ops,
.num_of_queues = IWL39_NUM_QUEUES,
- .mod_params = &iwl3945_mod_params,
.pll_cfg_val = CSR39_ANA_PLL_CFG_VAL,
.set_l0s = false,
.use_bsm = true,
.use_isr_legacy = true,
- .ht_greenfield_support = false,
.led_compensation = 64,
.broken_powersave = true,
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
@@ -2736,25 +2766,28 @@ static struct iwl_cfg iwl3945_bg_cfg = {
.tx_power_by_driver = true,
};
+static struct iwl_cfg iwl3945_bg_cfg = {
+ .name = "3945BG",
+ .fw_name_pre = IWL3945_FW_PRE,
+ .ucode_api_max = IWL3945_UCODE_API_MAX,
+ .ucode_api_min = IWL3945_UCODE_API_MIN,
+ .sku = IWL_SKU_G,
+ .eeprom_ver = EEPROM_3945_EEPROM_VERSION,
+ .ops = &iwl3945_ops,
+ .mod_params = &iwl3945_mod_params,
+ .base_params = &iwl3945_base_params,
+};
+
static struct iwl_cfg iwl3945_abg_cfg = {
.name = "3945ABG",
.fw_name_pre = IWL3945_FW_PRE,
.ucode_api_max = IWL3945_UCODE_API_MAX,
.ucode_api_min = IWL3945_UCODE_API_MIN,
.sku = IWL_SKU_A|IWL_SKU_G,
- .eeprom_size = IWL3945_EEPROM_IMG_SIZE,
.eeprom_ver = EEPROM_3945_EEPROM_VERSION,
.ops = &iwl3945_ops,
- .num_of_queues = IWL39_NUM_QUEUES,
.mod_params = &iwl3945_mod_params,
- .use_isr_legacy = true,
- .ht_greenfield_support = false,
- .led_compensation = 64,
- .broken_powersave = true,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
- .monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
- .max_event_log_size = 512,
- .tx_power_by_driver = true,
+ .base_params = &iwl3945_base_params,
};
DEFINE_PCI_DEVICE_TABLE(iwl3945_hw_card_ids) = {
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h
index bb2aeebf3652..09391f0ee61f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.h
@@ -138,8 +138,6 @@ enum iwl3945_antenna {
#define DEFAULT_SHORT_RETRY_LIMIT 7U
#define DEFAULT_LONG_RETRY_LIMIT 4U
-#include "iwl-agn-rs.h"
-
#define IWL_TX_FIFO_AC0 0
#define IWL_TX_FIFO_AC1 1
#define IWL_TX_FIFO_AC2 2
@@ -271,6 +269,9 @@ extern void iwl3945_post_associate(struct iwl_priv *priv,
extern void iwl3945_config_ap(struct iwl_priv *priv,
struct ieee80211_vif *vif);
+extern int iwl3945_commit_rxon(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx);
+
/**
* iwl3945_hw_find_station - Find station id for a given BSSID
* @bssid: MAC address of station ID to find
@@ -295,7 +296,11 @@ extern const struct iwl_channel_info *iwl3945_get_channel_info(
extern int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate);
/* scanning */
-void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif);
+int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif);
+void iwl3945_post_scan(struct iwl_priv *priv);
+
+/* rates */
+extern const struct iwl3945_rate_info iwl3945_rates[IWL_RATE_COUNT_3945];
/* Requires full declaration of iwl_priv before including */
#include "iwl-io.h"
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index d92b72909233..b207e3e9299f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -43,7 +43,7 @@
#include "iwl-core.h"
#include "iwl-io.h"
#include "iwl-helpers.h"
-#include "iwl-calib.h"
+#include "iwl-agn-calib.h"
#include "iwl-sta.h"
#include "iwl-agn-led.h"
#include "iwl-agn.h"
@@ -347,7 +347,7 @@ static void iwl4965_chain_noise_reset(struct iwl_priv *priv)
struct iwl_chain_noise_data *data = &(priv->chain_noise_data);
if ((data->state == IWL_CHAIN_NOISE_ALIVE) &&
- iwl_is_associated(priv)) {
+ iwl_is_any_associated(priv)) {
struct iwl_calib_diff_gain_cmd cmd;
/* clear data for chain noise calibration algorithm */
@@ -576,7 +576,7 @@ static int iwl4965_alive_notify(struct iwl_priv *priv)
/* Activate all Tx DMA/FIFO channels */
priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 6));
- iwl4965_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0);
+ iwl4965_set_wr_ptrs(priv, IWL_DEFAULT_CMD_QUEUE_NUM, 0);
/* make sure all queue are not stopped */
memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped));
@@ -587,6 +587,7 @@ static int iwl4965_alive_notify(struct iwl_priv *priv)
priv->txq_ctx_active_msk = 0;
/* Map each Tx/cmd queue to its corresponding fifo */
BUILD_BUG_ON(ARRAY_SIZE(default_queue_to_tx_fifo) != 7);
+
for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) {
int ac = default_queue_to_tx_fifo[i];
@@ -646,17 +647,17 @@ static int iwl4965_hw_set_hw_params(struct iwl_priv *priv)
{
if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES &&
priv->cfg->mod_params->num_of_queues <= IWL49_NUM_QUEUES)
- priv->cfg->num_of_queues =
+ priv->cfg->base_params->num_of_queues =
priv->cfg->mod_params->num_of_queues;
- priv->hw_params.max_txq_num = priv->cfg->num_of_queues;
+ priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues;
priv->hw_params.dma_chnl_num = FH49_TCSR_CHNL_NUM;
priv->hw_params.scd_bc_tbls_size =
- priv->cfg->num_of_queues *
+ priv->cfg->base_params->num_of_queues *
sizeof(struct iwl4965_scd_bc_tbl);
priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
priv->hw_params.max_stations = IWL4965_STATION_COUNT;
- priv->hw_params.bcast_sta_id = IWL4965_BROADCAST_ID;
+ priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWL4965_BROADCAST_ID;
priv->hw_params.max_data_size = IWL49_RTC_DATA_SIZE;
priv->hw_params.max_inst_size = IWL49_RTC_INST_SIZE;
priv->hw_params.max_bsm_size = BSM_SRAM_SIZE;
@@ -668,8 +669,8 @@ static int iwl4965_hw_set_hw_params(struct iwl_priv *priv)
priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant);
priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant;
priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant;
- if (priv->cfg->ops->lib->temp_ops.set_ct_kill)
- priv->cfg->ops->lib->temp_ops.set_ct_kill(priv);
+
+ iwl4965_set_ct_threshold(priv);
priv->hw_params.sens = &iwl4965_sensitivity;
priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
@@ -1374,6 +1375,7 @@ static int iwl4965_send_tx_power(struct iwl_priv *priv)
u8 band = 0;
bool is_ht40 = false;
u8 ctrl_chan_high = 0;
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
if (test_bit(STATUS_SCANNING, &priv->status)) {
/* If this gets hit a lot, switch it to a BUG() and catch
@@ -1385,17 +1387,16 @@ static int iwl4965_send_tx_power(struct iwl_priv *priv)
band = priv->band == IEEE80211_BAND_2GHZ;
- is_ht40 = is_ht40_channel(priv->active_rxon.flags);
+ is_ht40 = is_ht40_channel(ctx->active.flags);
- if (is_ht40 &&
- (priv->active_rxon.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK))
+ if (is_ht40 && (ctx->active.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK))
ctrl_chan_high = 1;
cmd.band = band;
- cmd.channel = priv->active_rxon.channel;
+ cmd.channel = ctx->active.channel;
ret = iwl4965_fill_txpower_tbl(priv, band,
- le16_to_cpu(priv->active_rxon.channel),
+ le16_to_cpu(ctx->active.channel),
is_ht40, ctrl_chan_high, &cmd.tx_power);
if (ret)
goto out;
@@ -1406,12 +1407,13 @@ out:
return ret;
}
-static int iwl4965_send_rxon_assoc(struct iwl_priv *priv)
+static int iwl4965_send_rxon_assoc(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx)
{
int ret = 0;
struct iwl4965_rxon_assoc_cmd rxon_assoc;
- const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon;
- const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon;
+ const struct iwl_rxon_cmd *rxon1 = &ctx->staging;
+ const struct iwl_rxon_cmd *rxon2 = &ctx->active;
if ((rxon1->flags == rxon2->flags) &&
(rxon1->filter_flags == rxon2->filter_flags) &&
@@ -1426,16 +1428,16 @@ static int iwl4965_send_rxon_assoc(struct iwl_priv *priv)
return 0;
}
- rxon_assoc.flags = priv->staging_rxon.flags;
- rxon_assoc.filter_flags = priv->staging_rxon.filter_flags;
- rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates;
- rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates;
+ rxon_assoc.flags = ctx->staging.flags;
+ rxon_assoc.filter_flags = ctx->staging.filter_flags;
+ rxon_assoc.ofdm_basic_rates = ctx->staging.ofdm_basic_rates;
+ rxon_assoc.cck_basic_rates = ctx->staging.cck_basic_rates;
rxon_assoc.reserved = 0;
rxon_assoc.ofdm_ht_single_stream_basic_rates =
- priv->staging_rxon.ofdm_ht_single_stream_basic_rates;
+ ctx->staging.ofdm_ht_single_stream_basic_rates;
rxon_assoc.ofdm_ht_dual_stream_basic_rates =
- priv->staging_rxon.ofdm_ht_dual_stream_basic_rates;
- rxon_assoc.rx_chain_select_flags = priv->staging_rxon.rx_chain;
+ ctx->staging.ofdm_ht_dual_stream_basic_rates;
+ rxon_assoc.rx_chain_select_flags = ctx->staging.rx_chain;
ret = iwl_send_cmd_pdu_async(priv, REPLY_RXON_ASSOC,
sizeof(rxon_assoc), &rxon_assoc, NULL);
@@ -1448,6 +1450,7 @@ static int iwl4965_send_rxon_assoc(struct iwl_priv *priv)
static int iwl4965_hw_channel_switch(struct iwl_priv *priv,
struct ieee80211_channel_switch *ch_switch)
{
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
int rc;
u8 band = 0;
bool is_ht40 = false;
@@ -1458,22 +1461,22 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv,
u16 ch;
u32 tsf_low;
u8 switch_count;
- u16 beacon_interval = le16_to_cpu(priv->rxon_timing.beacon_interval);
- struct ieee80211_vif *vif = priv->vif;
+ u16 beacon_interval = le16_to_cpu(ctx->timing.beacon_interval);
+ struct ieee80211_vif *vif = ctx->vif;
band = priv->band == IEEE80211_BAND_2GHZ;
- is_ht40 = is_ht40_channel(priv->staging_rxon.flags);
+ is_ht40 = is_ht40_channel(ctx->staging.flags);
if (is_ht40 &&
- (priv->staging_rxon.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK))
+ (ctx->staging.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK))
ctrl_chan_high = 1;
cmd.band = band;
cmd.expect_beacon = 0;
- ch = ieee80211_frequency_to_channel(ch_switch->channel->center_freq);
+ ch = ch_switch->channel->hw_value;
cmd.channel = cpu_to_le16(ch);
- cmd.rxon_flags = priv->staging_rxon.flags;
- cmd.rxon_filter_flags = priv->staging_rxon.filter_flags;
+ cmd.rxon_flags = ctx->staging.flags;
+ cmd.rxon_filter_flags = ctx->staging.filter_flags;
switch_count = ch_switch->count;
tsf_low = ch_switch->timestamp & 0x0ffffffff;
/*
@@ -1508,7 +1511,7 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv,
cmd.expect_beacon = is_channel_radar(ch_info);
else {
IWL_ERR(priv, "invalid channel switch from %u to %u\n",
- priv->active_rxon.channel, ch);
+ ctx->active.channel, ch);
return -EFAULT;
}
@@ -1721,13 +1724,13 @@ static int iwl4965_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
u16 ssn_idx, u8 tx_fifo)
{
if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) ||
- (IWL49_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues
- <= txq_id)) {
+ (IWL49_FIRST_AMPDU_QUEUE +
+ priv->cfg->base_params->num_of_ampdu_queues <= txq_id)) {
IWL_WARN(priv,
"queue number out of range: %d, must be %d to %d\n",
txq_id, IWL49_FIRST_AMPDU_QUEUE,
IWL49_FIRST_AMPDU_QUEUE +
- priv->cfg->num_of_ampdu_queues - 1);
+ priv->cfg->base_params->num_of_ampdu_queues - 1);
return -EINVAL;
}
@@ -1789,13 +1792,13 @@ static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id,
int ret;
if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) ||
- (IWL49_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues
- <= txq_id)) {
+ (IWL49_FIRST_AMPDU_QUEUE +
+ priv->cfg->base_params->num_of_ampdu_queues <= txq_id)) {
IWL_WARN(priv,
"queue number out of range: %d, must be %d to %d\n",
txq_id, IWL49_FIRST_AMPDU_QUEUE,
IWL49_FIRST_AMPDU_QUEUE +
- priv->cfg->num_of_ampdu_queues - 1);
+ priv->cfg->base_params->num_of_ampdu_queues - 1);
return -EINVAL;
}
@@ -2007,7 +2010,7 @@ static u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr)
start = IWL_STA_ID;
if (is_broadcast_ether_addr(addr))
- return priv->hw_params.bcast_sta_id;
+ return priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id;
spin_lock_irqsave(&priv->sta_lock, flags);
for (i = start; i < priv->hw_params.max_stations; i++)
@@ -2213,11 +2216,23 @@ static void iwl4965_cancel_deferred_work(struct iwl_priv *priv)
static struct iwl_hcmd_ops iwl4965_hcmd = {
.rxon_assoc = iwl4965_send_rxon_assoc,
- .commit_rxon = iwl_commit_rxon,
- .set_rxon_chain = iwl_set_rxon_chain,
+ .commit_rxon = iwlagn_commit_rxon,
+ .set_rxon_chain = iwlagn_set_rxon_chain,
.send_bt_config = iwl_send_bt_config,
};
+static void iwl4965_post_scan(struct iwl_priv *priv)
+{
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+
+ /*
+ * Since setting the RXON may have been deferred while
+ * performing the scan, fire one off if needed
+ */
+ if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
+ iwlcore_commit_rxon(priv, ctx);
+}
+
static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {
.get_hcmd_size = iwl4965_get_hcmd_size,
.build_addsta_hcmd = iwl4965_build_addsta_hcmd,
@@ -2226,6 +2241,7 @@ static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {
.tx_cmd_protection = iwlcore_tx_cmd_protection,
.calc_rssi = iwl4965_calc_rssi,
.request_scan = iwlagn_request_scan,
+ .post_scan = iwl4965_post_scan,
};
static struct iwl_lib_ops iwl4965_lib = {
@@ -2250,9 +2266,7 @@ static struct iwl_lib_ops iwl4965_lib = {
.set_channel_switch = iwl4965_hw_channel_switch,
.apm_ops = {
.init = iwl_apm_init,
- .stop = iwl_apm_stop,
.config = iwl4965_nic_config,
- .set_pwr_src = iwl_set_pwr_src,
},
.eeprom_ops = {
.regulatory_bands = {
@@ -2264,7 +2278,6 @@ static struct iwl_lib_ops iwl4965_lib = {
EEPROM_4965_REGULATORY_BAND_24_HT40_CHANNELS,
EEPROM_4965_REGULATORY_BAND_52_HT40_CHANNELS
},
- .verify_signature = iwlcore_eeprom_verify_signature,
.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
.release_semaphore = iwlcore_eeprom_release_semaphore,
.calib_version = iwl4965_eeprom_calib_version,
@@ -2277,15 +2290,15 @@ static struct iwl_lib_ops iwl4965_lib = {
.isr = iwl_isr_legacy,
.temp_ops = {
.temperature = iwl4965_temperature_calib,
- .set_ct_kill = iwl4965_set_ct_threshold,
},
.manage_ibss_station = iwlagn_manage_ibss_station,
- .update_bcast_station = iwl_update_bcast_station,
+ .update_bcast_stations = iwl_update_bcast_stations,
.debugfs_ops = {
.rx_stats_read = iwl_ucode_rx_stats_read,
.tx_stats_read = iwl_ucode_tx_stats_read,
.general_stats_read = iwl_ucode_general_stats_read,
.bt_stats_read = iwl_ucode_bt_stats_read,
+ .reply_tx_error = iwl_reply_tx_error_read,
},
.recover_from_tx_stall = iwl_bg_monitor_recover,
.check_plcp_health = iwl_good_plcp_health,
@@ -2298,26 +2311,14 @@ static const struct iwl_ops iwl4965_ops = {
.led = &iwlagn_led_ops,
};
-struct iwl_cfg iwl4965_agn_cfg = {
- .name = "Intel(R) Wireless WiFi Link 4965AGN",
- .fw_name_pre = IWL4965_FW_PRE,
- .ucode_api_max = IWL4965_UCODE_API_MAX,
- .ucode_api_min = IWL4965_UCODE_API_MIN,
- .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
+static struct iwl_base_params iwl4965_base_params = {
.eeprom_size = IWL4965_EEPROM_IMG_SIZE,
- .eeprom_ver = EEPROM_4965_EEPROM_VERSION,
- .eeprom_calib_ver = EEPROM_4965_TX_POWER_VERSION,
- .ops = &iwl4965_ops,
.num_of_queues = IWL49_NUM_QUEUES,
.num_of_ampdu_queues = IWL49_NUM_AMPDU_QUEUES,
- .mod_params = &iwlagn_mod_params,
- .valid_tx_ant = ANT_AB,
- .valid_rx_ant = ANT_ABC,
.pll_cfg_val = 0,
.set_l0s = true,
.use_bsm = true,
.use_isr_legacy = true,
- .ht_greenfield_support = false,
.broken_powersave = true,
.led_compensation = 61,
.chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS,
@@ -2329,6 +2330,21 @@ struct iwl_cfg iwl4965_agn_cfg = {
.ucode_tracing = true,
.sensitivity_calib_by_driver = true,
.chain_noise_calib_by_driver = true,
+};
+
+struct iwl_cfg iwl4965_agn_cfg = {
+ .name = "Intel(R) Wireless WiFi Link 4965AGN",
+ .fw_name_pre = IWL4965_FW_PRE,
+ .ucode_api_max = IWL4965_UCODE_API_MAX,
+ .ucode_api_min = IWL4965_UCODE_API_MIN,
+ .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
+ .valid_tx_ant = ANT_AB,
+ .valid_rx_ant = ANT_ABC,
+ .eeprom_ver = EEPROM_4965_EEPROM_VERSION,
+ .eeprom_calib_ver = EEPROM_4965_TX_POWER_VERSION,
+ .ops = &iwl4965_ops,
+ .mod_params = &iwlagn_mod_params,
+ .base_params = &iwl4965_base_params,
/*
* Force use of chains B and C for scan RX on 5 GHz band
* because the device has off-channel reception on chain A.
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h
index 146e6431ae95..3975e45e7500 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h
@@ -62,7 +62,7 @@
*****************************************************************************/
/*
* Please use this file (iwl-5000-hw.h) only for hardware-related definitions.
- * Use iwl-5000-commands.h for uCode API definitions.
+ * Use iwl-commands.h for uCode API definitions.
*/
#ifndef __iwl_5000_hw_h__
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index 48bdcd8d2e94..fd9fbc93ea1b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -170,17 +170,17 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
{
if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES &&
priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES)
- priv->cfg->num_of_queues =
+ priv->cfg->base_params->num_of_queues =
priv->cfg->mod_params->num_of_queues;
- priv->hw_params.max_txq_num = priv->cfg->num_of_queues;
+ priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues;
priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM;
priv->hw_params.scd_bc_tbls_size =
- priv->cfg->num_of_queues *
+ priv->cfg->base_params->num_of_queues *
sizeof(struct iwlagn_scd_bc_tbl);
priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
priv->hw_params.max_stations = IWLAGN_STATION_COUNT;
- priv->hw_params.bcast_sta_id = IWLAGN_BROADCAST_ID;
+ priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID;
priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE;
priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE;
@@ -195,8 +195,7 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant;
priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant;
- if (priv->cfg->ops->lib->temp_ops.set_ct_kill)
- priv->cfg->ops->lib->temp_ops.set_ct_kill(priv);
+ iwl5000_set_ct_threshold(priv);
/* Set initial sensitivity parameters */
/* Set initial calibration set */
@@ -217,17 +216,17 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv)
{
if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES &&
priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES)
- priv->cfg->num_of_queues =
+ priv->cfg->base_params->num_of_queues =
priv->cfg->mod_params->num_of_queues;
- priv->hw_params.max_txq_num = priv->cfg->num_of_queues;
+ priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues;
priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM;
priv->hw_params.scd_bc_tbls_size =
- priv->cfg->num_of_queues *
+ priv->cfg->base_params->num_of_queues *
sizeof(struct iwlagn_scd_bc_tbl);
priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
priv->hw_params.max_stations = IWLAGN_STATION_COUNT;
- priv->hw_params.bcast_sta_id = IWLAGN_BROADCAST_ID;
+ priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID;
priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE;
priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE;
@@ -242,8 +241,7 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv)
priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant;
priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant;
- if (priv->cfg->ops->lib->temp_ops.set_ct_kill)
- priv->cfg->ops->lib->temp_ops.set_ct_kill(priv);
+ iwl5150_set_ct_threshold(priv);
/* Set initial sensitivity parameters */
/* Set initial calibration set */
@@ -275,14 +273,19 @@ static void iwl5150_temperature(struct iwl_priv *priv)
static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
struct ieee80211_channel_switch *ch_switch)
{
+ /*
+ * MULTI-FIXME
+ * See iwl_mac_channel_switch.
+ */
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
struct iwl5000_channel_switch_cmd cmd;
const struct iwl_channel_info *ch_info;
u32 switch_time_in_usec, ucode_switch_time;
u16 ch;
u32 tsf_low;
u8 switch_count;
- u16 beacon_interval = le16_to_cpu(priv->rxon_timing.beacon_interval);
- struct ieee80211_vif *vif = priv->vif;
+ u16 beacon_interval = le16_to_cpu(ctx->timing.beacon_interval);
+ struct ieee80211_vif *vif = ctx->vif;
struct iwl_host_cmd hcmd = {
.id = REPLY_CHANNEL_SWITCH,
.len = sizeof(cmd),
@@ -291,12 +294,12 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
};
cmd.band = priv->band == IEEE80211_BAND_2GHZ;
- ch = ieee80211_frequency_to_channel(ch_switch->channel->center_freq);
+ ch = ch_switch->channel->hw_value;
IWL_DEBUG_11H(priv, "channel switch from %d to %d\n",
- priv->active_rxon.channel, ch);
+ ctx->active.channel, ch);
cmd.channel = cpu_to_le16(ch);
- cmd.rxon_flags = priv->staging_rxon.flags;
- cmd.rxon_filter_flags = priv->staging_rxon.filter_flags;
+ cmd.rxon_flags = ctx->staging.flags;
+ cmd.rxon_filter_flags = ctx->staging.filter_flags;
switch_count = ch_switch->count;
tsf_low = ch_switch->timestamp & 0x0ffffffff;
/*
@@ -331,7 +334,7 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
cmd.expect_beacon = is_channel_radar(ch_info);
else {
IWL_ERR(priv, "invalid channel switch from %u to %u\n",
- priv->active_rxon.channel, ch);
+ ctx->active.channel, ch);
return -EFAULT;
}
priv->switch_rxon.channel = cmd.channel;
@@ -365,9 +368,7 @@ static struct iwl_lib_ops iwl5000_lib = {
.set_channel_switch = iwl5000_hw_channel_switch,
.apm_ops = {
.init = iwl_apm_init,
- .stop = iwl_apm_stop,
.config = iwl5000_nic_config,
- .set_pwr_src = iwl_set_pwr_src,
},
.eeprom_ops = {
.regulatory_bands = {
@@ -379,7 +380,6 @@ static struct iwl_lib_ops iwl5000_lib = {
EEPROM_REG_BAND_24_HT40_CHANNELS,
EEPROM_REG_BAND_52_HT40_CHANNELS
},
- .verify_signature = iwlcore_eeprom_verify_signature,
.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
.release_semaphore = iwlcore_eeprom_release_semaphore,
.calib_version = iwlagn_eeprom_calib_version,
@@ -390,21 +390,26 @@ static struct iwl_lib_ops iwl5000_lib = {
.config_ap = iwl_config_ap,
.temp_ops = {
.temperature = iwlagn_temperature,
- .set_ct_kill = iwl5000_set_ct_threshold,
},
.manage_ibss_station = iwlagn_manage_ibss_station,
- .update_bcast_station = iwl_update_bcast_station,
+ .update_bcast_stations = iwl_update_bcast_stations,
.debugfs_ops = {
.rx_stats_read = iwl_ucode_rx_stats_read,
.tx_stats_read = iwl_ucode_tx_stats_read,
.general_stats_read = iwl_ucode_general_stats_read,
.bt_stats_read = iwl_ucode_bt_stats_read,
+ .reply_tx_error = iwl_reply_tx_error_read,
},
.recover_from_tx_stall = iwl_bg_monitor_recover,
.check_plcp_health = iwl_good_plcp_health,
.check_ack_health = iwl_good_ack_health,
.txfifo_flush = iwlagn_txfifo_flush,
.dev_txfifo_flush = iwlagn_dev_txfifo_flush,
+ .tt_ops = {
+ .lower_power_detection = iwl_tt_is_low_power_state,
+ .tt_power_mode = iwl_tt_current_power_mode,
+ .ct_kill_check = iwl_check_for_ct_kill,
+ }
};
static struct iwl_lib_ops iwl5150_lib = {
@@ -431,9 +436,7 @@ static struct iwl_lib_ops iwl5150_lib = {
.set_channel_switch = iwl5000_hw_channel_switch,
.apm_ops = {
.init = iwl_apm_init,
- .stop = iwl_apm_stop,
.config = iwl5000_nic_config,
- .set_pwr_src = iwl_set_pwr_src,
},
.eeprom_ops = {
.regulatory_bands = {
@@ -445,7 +448,6 @@ static struct iwl_lib_ops iwl5150_lib = {
EEPROM_REG_BAND_24_HT40_CHANNELS,
EEPROM_REG_BAND_52_HT40_CHANNELS
},
- .verify_signature = iwlcore_eeprom_verify_signature,
.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
.release_semaphore = iwlcore_eeprom_release_semaphore,
.calib_version = iwlagn_eeprom_calib_version,
@@ -456,20 +458,26 @@ static struct iwl_lib_ops iwl5150_lib = {
.config_ap = iwl_config_ap,
.temp_ops = {
.temperature = iwl5150_temperature,
- .set_ct_kill = iwl5150_set_ct_threshold,
},
.manage_ibss_station = iwlagn_manage_ibss_station,
- .update_bcast_station = iwl_update_bcast_station,
+ .update_bcast_stations = iwl_update_bcast_stations,
.debugfs_ops = {
.rx_stats_read = iwl_ucode_rx_stats_read,
.tx_stats_read = iwl_ucode_tx_stats_read,
.general_stats_read = iwl_ucode_general_stats_read,
+ .bt_stats_read = iwl_ucode_bt_stats_read,
+ .reply_tx_error = iwl_reply_tx_error_read,
},
.recover_from_tx_stall = iwl_bg_monitor_recover,
.check_plcp_health = iwl_good_plcp_health,
.check_ack_health = iwl_good_ack_health,
.txfifo_flush = iwlagn_txfifo_flush,
.dev_txfifo_flush = iwlagn_dev_txfifo_flush,
+ .tt_ops = {
+ .lower_power_detection = iwl_tt_is_low_power_state,
+ .tt_power_mode = iwl_tt_current_power_mode,
+ .ct_kill_check = iwl_check_for_ct_kill,
+ }
};
static const struct iwl_ops iwl5000_ops = {
@@ -486,27 +494,14 @@ static const struct iwl_ops iwl5150_ops = {
.led = &iwlagn_led_ops,
};
-struct iwl_cfg iwl5300_agn_cfg = {
- .name = "Intel(R) Ultimate N WiFi Link 5300 AGN",
- .fw_name_pre = IWL5000_FW_PRE,
- .ucode_api_max = IWL5000_UCODE_API_MAX,
- .ucode_api_min = IWL5000_UCODE_API_MIN,
- .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
- .ops = &iwl5000_ops,
+static struct iwl_base_params iwl5000_base_params = {
.eeprom_size = IWLAGN_EEPROM_IMG_SIZE,
- .eeprom_ver = EEPROM_5000_EEPROM_VERSION,
- .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
.num_of_queues = IWLAGN_NUM_QUEUES,
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
- .mod_params = &iwlagn_mod_params,
- .valid_tx_ant = ANT_ABC,
- .valid_rx_ant = ANT_ABC,
.pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
.set_l0s = true,
.use_bsm = false,
- .ht_greenfield_support = true,
.led_compensation = 51,
- .use_rts_for_aggregation = true, /* use rts/cts protection */
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
.chain_noise_scale = 1000,
@@ -516,6 +511,26 @@ struct iwl_cfg iwl5300_agn_cfg = {
.sensitivity_calib_by_driver = true,
.chain_noise_calib_by_driver = true,
};
+static struct iwl_ht_params iwl5000_ht_params = {
+ .ht_greenfield_support = true,
+ .use_rts_for_aggregation = true, /* use rts/cts protection */
+};
+
+struct iwl_cfg iwl5300_agn_cfg = {
+ .name = "Intel(R) Ultimate N WiFi Link 5300 AGN",
+ .fw_name_pre = IWL5000_FW_PRE,
+ .ucode_api_max = IWL5000_UCODE_API_MAX,
+ .ucode_api_min = IWL5000_UCODE_API_MIN,
+ .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
+ .valid_tx_ant = ANT_ABC,
+ .valid_rx_ant = ANT_ABC,
+ .eeprom_ver = EEPROM_5000_EEPROM_VERSION,
+ .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
+ .ops = &iwl5000_ops,
+ .mod_params = &iwlagn_mod_params,
+ .base_params = &iwl5000_base_params,
+ .ht_params = &iwl5000_ht_params,
+};
struct iwl_cfg iwl5100_bgn_cfg = {
.name = "Intel(R) WiFi Link 5100 BGN",
@@ -523,29 +538,14 @@ struct iwl_cfg iwl5100_bgn_cfg = {
.ucode_api_max = IWL5000_UCODE_API_MAX,
.ucode_api_min = IWL5000_UCODE_API_MIN,
.sku = IWL_SKU_G|IWL_SKU_N,
- .ops = &iwl5000_ops,
- .eeprom_size = IWLAGN_EEPROM_IMG_SIZE,
+ .valid_tx_ant = ANT_B,
+ .valid_rx_ant = ANT_AB,
.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
- .num_of_queues = IWLAGN_NUM_QUEUES,
- .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
+ .ops = &iwl5000_ops,
.mod_params = &iwlagn_mod_params,
- .valid_tx_ant = ANT_B,
- .valid_rx_ant = ANT_AB,
- .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
- .set_l0s = true,
- .use_bsm = false,
- .ht_greenfield_support = true,
- .led_compensation = 51,
- .use_rts_for_aggregation = true, /* use rts/cts protection */
- .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
- .chain_noise_scale = 1000,
- .monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
- .max_event_log_size = 512,
- .ucode_tracing = true,
- .sensitivity_calib_by_driver = true,
- .chain_noise_calib_by_driver = true,
+ .base_params = &iwl5000_base_params,
+ .ht_params = &iwl5000_ht_params,
};
struct iwl_cfg iwl5100_abg_cfg = {
@@ -554,27 +554,13 @@ struct iwl_cfg iwl5100_abg_cfg = {
.ucode_api_max = IWL5000_UCODE_API_MAX,
.ucode_api_min = IWL5000_UCODE_API_MIN,
.sku = IWL_SKU_A|IWL_SKU_G,
- .ops = &iwl5000_ops,
- .eeprom_size = IWLAGN_EEPROM_IMG_SIZE,
+ .valid_tx_ant = ANT_B,
+ .valid_rx_ant = ANT_AB,
.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
- .num_of_queues = IWLAGN_NUM_QUEUES,
- .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
+ .ops = &iwl5000_ops,
.mod_params = &iwlagn_mod_params,
- .valid_tx_ant = ANT_B,
- .valid_rx_ant = ANT_AB,
- .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
- .set_l0s = true,
- .use_bsm = false,
- .led_compensation = 51,
- .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
- .chain_noise_scale = 1000,
- .monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
- .max_event_log_size = 512,
- .ucode_tracing = true,
- .sensitivity_calib_by_driver = true,
- .chain_noise_calib_by_driver = true,
+ .base_params = &iwl5000_base_params,
};
struct iwl_cfg iwl5100_agn_cfg = {
@@ -583,29 +569,14 @@ struct iwl_cfg iwl5100_agn_cfg = {
.ucode_api_max = IWL5000_UCODE_API_MAX,
.ucode_api_min = IWL5000_UCODE_API_MIN,
.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
- .ops = &iwl5000_ops,
- .eeprom_size = IWLAGN_EEPROM_IMG_SIZE,
+ .valid_tx_ant = ANT_B,
+ .valid_rx_ant = ANT_AB,
.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
- .num_of_queues = IWLAGN_NUM_QUEUES,
- .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
+ .ops = &iwl5000_ops,
.mod_params = &iwlagn_mod_params,
- .valid_tx_ant = ANT_B,
- .valid_rx_ant = ANT_AB,
- .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
- .set_l0s = true,
- .use_bsm = false,
- .ht_greenfield_support = true,
- .led_compensation = 51,
- .use_rts_for_aggregation = true, /* use rts/cts protection */
- .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
- .chain_noise_scale = 1000,
- .monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
- .max_event_log_size = 512,
- .ucode_tracing = true,
- .sensitivity_calib_by_driver = true,
- .chain_noise_calib_by_driver = true,
+ .base_params = &iwl5000_base_params,
+ .ht_params = &iwl5000_ht_params,
};
struct iwl_cfg iwl5350_agn_cfg = {
@@ -614,29 +585,14 @@ struct iwl_cfg iwl5350_agn_cfg = {
.ucode_api_max = IWL5000_UCODE_API_MAX,
.ucode_api_min = IWL5000_UCODE_API_MIN,
.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
- .ops = &iwl5000_ops,
- .eeprom_size = IWLAGN_EEPROM_IMG_SIZE,
+ .valid_tx_ant = ANT_ABC,
+ .valid_rx_ant = ANT_ABC,
.eeprom_ver = EEPROM_5050_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION,
- .num_of_queues = IWLAGN_NUM_QUEUES,
- .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
+ .ops = &iwl5000_ops,
.mod_params = &iwlagn_mod_params,
- .valid_tx_ant = ANT_ABC,
- .valid_rx_ant = ANT_ABC,
- .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
- .set_l0s = true,
- .use_bsm = false,
- .ht_greenfield_support = true,
- .led_compensation = 51,
- .use_rts_for_aggregation = true, /* use rts/cts protection */
- .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
- .chain_noise_scale = 1000,
- .monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
- .max_event_log_size = 512,
- .ucode_tracing = true,
- .sensitivity_calib_by_driver = true,
- .chain_noise_calib_by_driver = true,
+ .base_params = &iwl5000_base_params,
+ .ht_params = &iwl5000_ht_params,
};
struct iwl_cfg iwl5150_agn_cfg = {
@@ -645,29 +601,14 @@ struct iwl_cfg iwl5150_agn_cfg = {
.ucode_api_max = IWL5150_UCODE_API_MAX,
.ucode_api_min = IWL5150_UCODE_API_MIN,
.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
- .ops = &iwl5150_ops,
- .eeprom_size = IWLAGN_EEPROM_IMG_SIZE,
+ .valid_tx_ant = ANT_A,
+ .valid_rx_ant = ANT_AB,
.eeprom_ver = EEPROM_5050_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION,
- .num_of_queues = IWLAGN_NUM_QUEUES,
- .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
+ .ops = &iwl5150_ops,
.mod_params = &iwlagn_mod_params,
- .valid_tx_ant = ANT_A,
- .valid_rx_ant = ANT_AB,
- .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
- .set_l0s = true,
- .use_bsm = false,
- .ht_greenfield_support = true,
- .led_compensation = 51,
- .use_rts_for_aggregation = true, /* use rts/cts protection */
- .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
- .chain_noise_scale = 1000,
- .monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
- .max_event_log_size = 512,
- .ucode_tracing = true,
- .sensitivity_calib_by_driver = true,
- .chain_noise_calib_by_driver = true,
+ .base_params = &iwl5000_base_params,
+ .ht_params = &iwl5000_ht_params,
.need_dc_calib = true,
};
@@ -677,27 +618,13 @@ struct iwl_cfg iwl5150_abg_cfg = {
.ucode_api_max = IWL5150_UCODE_API_MAX,
.ucode_api_min = IWL5150_UCODE_API_MIN,
.sku = IWL_SKU_A|IWL_SKU_G,
- .ops = &iwl5150_ops,
- .eeprom_size = IWLAGN_EEPROM_IMG_SIZE,
+ .valid_tx_ant = ANT_A,
+ .valid_rx_ant = ANT_AB,
.eeprom_ver = EEPROM_5050_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION,
- .num_of_queues = IWLAGN_NUM_QUEUES,
- .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
+ .ops = &iwl5150_ops,
.mod_params = &iwlagn_mod_params,
- .valid_tx_ant = ANT_A,
- .valid_rx_ant = ANT_AB,
- .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
- .set_l0s = true,
- .use_bsm = false,
- .led_compensation = 51,
- .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
- .chain_noise_scale = 1000,
- .monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
- .max_event_log_size = 512,
- .ucode_tracing = true,
- .sensitivity_calib_by_driver = true,
- .chain_noise_calib_by_driver = true,
+ .base_params = &iwl5000_base_params,
.need_dc_calib = true,
};
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000-hw.h b/drivers/net/wireless/iwlwifi/iwl-6000-hw.h
index ddba39999997..47891e16a758 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-6000-hw.h
@@ -62,7 +62,7 @@
*****************************************************************************/
/*
* Please use this file (iwl-6000-hw.h) only for hardware-related definitions.
- * Use iwl-5000-commands.h for uCode API definitions.
+ * Use iwl-commands.h for uCode API definitions.
*/
#ifndef __iwl_6000_hw_h__
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index cee06b968de8..11e6532fc573 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -51,13 +51,15 @@
/* Highest firmware API version supported */
#define IWL6000_UCODE_API_MAX 4
-#define IWL6050_UCODE_API_MAX 4
-#define IWL6000G2_UCODE_API_MAX 4
+#define IWL6050_UCODE_API_MAX 5
+#define IWL6000G2_UCODE_API_MAX 5
+#define IWL130_UCODE_API_MAX 5
/* Lowest firmware API version supported */
#define IWL6000_UCODE_API_MIN 4
#define IWL6050_UCODE_API_MIN 4
#define IWL6000G2_UCODE_API_MIN 4
+#define IWL130_UCODE_API_MIN 5
#define IWL6000_FW_PRE "iwlwifi-6000-"
#define _IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE #api ".ucode"
@@ -75,6 +77,9 @@
#define _IWL6000G2B_MODULE_FIRMWARE(api) IWL6000G2B_FW_PRE #api ".ucode"
#define IWL6000G2B_MODULE_FIRMWARE(api) _IWL6000G2B_MODULE_FIRMWARE(api)
+#define IWL130_FW_PRE "iwlwifi-130-"
+#define _IWL130_MODULE_FIRMWARE(api) IWL130_FW_PRE #api ".ucode"
+#define IWL130_MODULE_FIRMWARE(api) _IWL130_MODULE_FIRMWARE(api)
static void iwl6000_set_ct_threshold(struct iwl_priv *priv)
{
@@ -83,15 +88,24 @@ static void iwl6000_set_ct_threshold(struct iwl_priv *priv)
priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD;
}
-/* Indicate calibration version to uCode. */
-static void iwl6000_set_calib_version(struct iwl_priv *priv)
+static void iwl6050_additional_nic_config(struct iwl_priv *priv)
{
- if (priv->cfg->need_dc_calib &&
- (priv->cfg->ops->lib->eeprom_ops.calib_version(priv) >= 6))
+ /* Indicate calibration version to uCode. */
+ if (priv->cfg->ops->lib->eeprom_ops.calib_version(priv) >= 6)
iwl_set_bit(priv, CSR_GP_DRIVER_REG,
CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6);
}
+static void iwl6050g2_additional_nic_config(struct iwl_priv *priv)
+{
+ /* Indicate calibration version to uCode. */
+ if (priv->cfg->ops->lib->eeprom_ops.calib_version(priv) >= 6)
+ iwl_set_bit(priv, CSR_GP_DRIVER_REG,
+ CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6);
+ iwl_set_bit(priv, CSR_GP_DRIVER_REG,
+ CSR_GP_DRIVER_REG_BIT_6050_1x2);
+}
+
/* NIC configuration for 6000 series */
static void iwl6000_nic_config(struct iwl_priv *priv)
{
@@ -117,9 +131,11 @@ static void iwl6000_nic_config(struct iwl_priv *priv)
iwl_write32(priv, CSR_GP_DRIVER_REG,
CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA);
}
- /* else do nothing, uCode configured */
- if (priv->cfg->ops->lib->temp_ops.set_calib_version)
- priv->cfg->ops->lib->temp_ops.set_calib_version(priv);
+ /* do additional nic configuration if needed */
+ if (priv->cfg->ops->nic &&
+ priv->cfg->ops->nic->additional_nic_config) {
+ priv->cfg->ops->nic->additional_nic_config(priv);
+ }
}
static struct iwl_sensitivity_ranges iwl6000_sensitivity = {
@@ -151,17 +167,17 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
{
if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES &&
priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES)
- priv->cfg->num_of_queues =
+ priv->cfg->base_params->num_of_queues =
priv->cfg->mod_params->num_of_queues;
- priv->hw_params.max_txq_num = priv->cfg->num_of_queues;
+ priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues;
priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM;
priv->hw_params.scd_bc_tbls_size =
- priv->cfg->num_of_queues *
+ priv->cfg->base_params->num_of_queues *
sizeof(struct iwlagn_scd_bc_tbl);
priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
priv->hw_params.max_stations = IWLAGN_STATION_COUNT;
- priv->hw_params.bcast_sta_id = IWLAGN_BROADCAST_ID;
+ priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID;
priv->hw_params.max_data_size = IWL60_RTC_DATA_SIZE;
priv->hw_params.max_inst_size = IWL60_RTC_INST_SIZE;
@@ -176,8 +192,7 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant;
priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant;
- if (priv->cfg->ops->lib->temp_ops.set_ct_kill)
- priv->cfg->ops->lib->temp_ops.set_ct_kill(priv);
+ iwl6000_set_ct_threshold(priv);
/* Set initial sensitivity parameters */
/* Set initial calibration set */
@@ -188,7 +203,9 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
BIT(IWL_CALIB_TX_IQ) |
BIT(IWL_CALIB_BASE_BAND);
if (priv->cfg->need_dc_calib)
- priv->hw_params.calib_init_cfg |= BIT(IWL_CALIB_DC);
+ priv->hw_params.calib_rt_cfg |= BIT(IWL_CALIB_CFG_DC_IDX);
+ if (priv->cfg->need_temp_offset_calib)
+ priv->hw_params.calib_init_cfg |= BIT(IWL_CALIB_TEMP_OFFSET);
priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
@@ -198,14 +215,19 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
struct ieee80211_channel_switch *ch_switch)
{
+ /*
+ * MULTI-FIXME
+ * See iwl_mac_channel_switch.
+ */
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
struct iwl6000_channel_switch_cmd cmd;
const struct iwl_channel_info *ch_info;
u32 switch_time_in_usec, ucode_switch_time;
u16 ch;
u32 tsf_low;
u8 switch_count;
- u16 beacon_interval = le16_to_cpu(priv->rxon_timing.beacon_interval);
- struct ieee80211_vif *vif = priv->vif;
+ u16 beacon_interval = le16_to_cpu(ctx->timing.beacon_interval);
+ struct ieee80211_vif *vif = ctx->vif;
struct iwl_host_cmd hcmd = {
.id = REPLY_CHANNEL_SWITCH,
.len = sizeof(cmd),
@@ -214,12 +236,12 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
};
cmd.band = priv->band == IEEE80211_BAND_2GHZ;
- ch = ieee80211_frequency_to_channel(ch_switch->channel->center_freq);
+ ch = ch_switch->channel->hw_value;
IWL_DEBUG_11H(priv, "channel switch from %u to %u\n",
- priv->active_rxon.channel, ch);
+ ctx->active.channel, ch);
cmd.channel = cpu_to_le16(ch);
- cmd.rxon_flags = priv->staging_rxon.flags;
- cmd.rxon_filter_flags = priv->staging_rxon.filter_flags;
+ cmd.rxon_flags = ctx->staging.flags;
+ cmd.rxon_filter_flags = ctx->staging.filter_flags;
switch_count = ch_switch->count;
tsf_low = ch_switch->timestamp & 0x0ffffffff;
/*
@@ -254,7 +276,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
cmd.expect_beacon = is_channel_radar(ch_info);
else {
IWL_ERR(priv, "invalid channel switch from %u to %u\n",
- priv->active_rxon.channel, ch);
+ ctx->active.channel, ch);
return -EFAULT;
}
priv->switch_rxon.channel = cmd.channel;
@@ -288,9 +310,7 @@ static struct iwl_lib_ops iwl6000_lib = {
.set_channel_switch = iwl6000_hw_channel_switch,
.apm_ops = {
.init = iwl_apm_init,
- .stop = iwl_apm_stop,
.config = iwl6000_nic_config,
- .set_pwr_src = iwl_set_pwr_src,
},
.eeprom_ops = {
.regulatory_bands = {
@@ -302,7 +322,6 @@ static struct iwl_lib_ops iwl6000_lib = {
EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
EEPROM_REG_BAND_52_HT40_CHANNELS
},
- .verify_signature = iwlcore_eeprom_verify_signature,
.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
.release_semaphore = iwlcore_eeprom_release_semaphore,
.calib_version = iwlagn_eeprom_calib_version,
@@ -314,22 +333,105 @@ static struct iwl_lib_ops iwl6000_lib = {
.config_ap = iwl_config_ap,
.temp_ops = {
.temperature = iwlagn_temperature,
- .set_ct_kill = iwl6000_set_ct_threshold,
- .set_calib_version = iwl6000_set_calib_version,
},
.manage_ibss_station = iwlagn_manage_ibss_station,
- .update_bcast_station = iwl_update_bcast_station,
+ .update_bcast_stations = iwl_update_bcast_stations,
+ .debugfs_ops = {
+ .rx_stats_read = iwl_ucode_rx_stats_read,
+ .tx_stats_read = iwl_ucode_tx_stats_read,
+ .general_stats_read = iwl_ucode_general_stats_read,
+ .bt_stats_read = iwl_ucode_bt_stats_read,
+ .reply_tx_error = iwl_reply_tx_error_read,
+ },
+ .recover_from_tx_stall = iwl_bg_monitor_recover,
+ .check_plcp_health = iwl_good_plcp_health,
+ .check_ack_health = iwl_good_ack_health,
+ .txfifo_flush = iwlagn_txfifo_flush,
+ .dev_txfifo_flush = iwlagn_dev_txfifo_flush,
+ .tt_ops = {
+ .lower_power_detection = iwl_tt_is_low_power_state,
+ .tt_power_mode = iwl_tt_current_power_mode,
+ .ct_kill_check = iwl_check_for_ct_kill,
+ }
+};
+
+static struct iwl_lib_ops iwl6000g2b_lib = {
+ .set_hw_params = iwl6000_hw_set_hw_params,
+ .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl,
+ .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl,
+ .txq_set_sched = iwlagn_txq_set_sched,
+ .txq_agg_enable = iwlagn_txq_agg_enable,
+ .txq_agg_disable = iwlagn_txq_agg_disable,
+ .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd,
+ .txq_free_tfd = iwl_hw_txq_free_tfd,
+ .txq_init = iwl_hw_tx_queue_init,
+ .rx_handler_setup = iwlagn_bt_rx_handler_setup,
+ .setup_deferred_work = iwlagn_bt_setup_deferred_work,
+ .cancel_deferred_work = iwlagn_bt_cancel_deferred_work,
+ .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
+ .load_ucode = iwlagn_load_ucode,
+ .dump_nic_event_log = iwl_dump_nic_event_log,
+ .dump_nic_error_log = iwl_dump_nic_error_log,
+ .dump_csr = iwl_dump_csr,
+ .dump_fh = iwl_dump_fh,
+ .init_alive_start = iwlagn_init_alive_start,
+ .alive_notify = iwlagn_alive_notify,
+ .send_tx_power = iwlagn_send_tx_power,
+ .update_chain_flags = iwl_update_chain_flags,
+ .set_channel_switch = iwl6000_hw_channel_switch,
+ .apm_ops = {
+ .init = iwl_apm_init,
+ .config = iwl6000_nic_config,
+ },
+ .eeprom_ops = {
+ .regulatory_bands = {
+ EEPROM_REG_BAND_1_CHANNELS,
+ EEPROM_REG_BAND_2_CHANNELS,
+ EEPROM_REG_BAND_3_CHANNELS,
+ EEPROM_REG_BAND_4_CHANNELS,
+ EEPROM_REG_BAND_5_CHANNELS,
+ EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
+ EEPROM_REG_BAND_52_HT40_CHANNELS
+ },
+ .acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
+ .release_semaphore = iwlcore_eeprom_release_semaphore,
+ .calib_version = iwlagn_eeprom_calib_version,
+ .query_addr = iwlagn_eeprom_query_addr,
+ .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower,
+ },
+ .post_associate = iwl_post_associate,
+ .isr = iwl_isr_ict,
+ .config_ap = iwl_config_ap,
+ .temp_ops = {
+ .temperature = iwlagn_temperature,
+ },
+ .manage_ibss_station = iwlagn_manage_ibss_station,
+ .update_bcast_stations = iwl_update_bcast_stations,
.debugfs_ops = {
.rx_stats_read = iwl_ucode_rx_stats_read,
.tx_stats_read = iwl_ucode_tx_stats_read,
.general_stats_read = iwl_ucode_general_stats_read,
.bt_stats_read = iwl_ucode_bt_stats_read,
+ .reply_tx_error = iwl_reply_tx_error_read,
},
.recover_from_tx_stall = iwl_bg_monitor_recover,
.check_plcp_health = iwl_good_plcp_health,
.check_ack_health = iwl_good_ack_health,
.txfifo_flush = iwlagn_txfifo_flush,
.dev_txfifo_flush = iwlagn_dev_txfifo_flush,
+ .tt_ops = {
+ .lower_power_detection = iwl_tt_is_low_power_state,
+ .tt_power_mode = iwl_tt_current_power_mode,
+ .ct_kill_check = iwl_check_for_ct_kill,
+ }
+};
+
+static struct iwl_nic_ops iwl6050_nic_ops = {
+ .additional_nic_config = &iwl6050_additional_nic_config,
+};
+
+static struct iwl_nic_ops iwl6050g2_nic_ops = {
+ .additional_nic_config = &iwl6050g2_additional_nic_config,
};
static const struct iwl_ops iwl6000_ops = {
@@ -339,49 +441,39 @@ static const struct iwl_ops iwl6000_ops = {
.led = &iwlagn_led_ops,
};
-static void do_not_send_bt_config(struct iwl_priv *priv)
-{
-}
+static const struct iwl_ops iwl6050_ops = {
+ .lib = &iwl6000_lib,
+ .hcmd = &iwlagn_hcmd,
+ .utils = &iwlagn_hcmd_utils,
+ .led = &iwlagn_led_ops,
+ .nic = &iwl6050_nic_ops,
+};
-static struct iwl_hcmd_ops iwl6000g2b_hcmd = {
- .rxon_assoc = iwlagn_send_rxon_assoc,
- .commit_rxon = iwl_commit_rxon,
- .set_rxon_chain = iwl_set_rxon_chain,
- .set_tx_ant = iwlagn_send_tx_ant_config,
- .send_bt_config = do_not_send_bt_config,
+static const struct iwl_ops iwl6050g2_ops = {
+ .lib = &iwl6000_lib,
+ .hcmd = &iwlagn_hcmd,
+ .utils = &iwlagn_hcmd_utils,
+ .led = &iwlagn_led_ops,
+ .nic = &iwl6050g2_nic_ops,
};
static const struct iwl_ops iwl6000g2b_ops = {
- .lib = &iwl6000_lib,
- .hcmd = &iwl6000g2b_hcmd,
+ .lib = &iwl6000g2b_lib,
+ .hcmd = &iwlagn_bt_hcmd,
.utils = &iwlagn_hcmd_utils,
.led = &iwlagn_led_ops,
};
-struct iwl_cfg iwl6000g2a_2agn_cfg = {
- .name = "6000 Series 2x2 AGN Gen2a",
- .fw_name_pre = IWL6000G2A_FW_PRE,
- .ucode_api_max = IWL6000G2_UCODE_API_MAX,
- .ucode_api_min = IWL6000G2_UCODE_API_MIN,
- .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
- .ops = &iwl6000_ops,
+static struct iwl_base_params iwl6000_base_params = {
.eeprom_size = OTP_LOW_IMAGE_SIZE,
- .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
- .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
.num_of_queues = IWLAGN_NUM_QUEUES,
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
- .mod_params = &iwlagn_mod_params,
- .valid_tx_ant = ANT_AB,
- .valid_rx_ant = ANT_AB,
.pll_cfg_val = 0,
.set_l0s = true,
.use_bsm = false,
- .pa_type = IWL_PA_SYSTEM,
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
.shadow_ram_support = true,
- .ht_greenfield_support = true,
.led_compensation = 51,
- .use_rts_for_aggregation = true, /* use rts/cts protection */
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
.supports_idle = true,
.adv_thermal_throttle = true,
@@ -393,29 +485,16 @@ struct iwl_cfg iwl6000g2a_2agn_cfg = {
.ucode_tracing = true,
.sensitivity_calib_by_driver = true,
.chain_noise_calib_by_driver = true,
- .need_dc_calib = true,
};
-struct iwl_cfg iwl6000g2a_2abg_cfg = {
- .name = "6000 Series 2x2 ABG Gen2a",
- .fw_name_pre = IWL6000G2A_FW_PRE,
- .ucode_api_max = IWL6000G2_UCODE_API_MAX,
- .ucode_api_min = IWL6000G2_UCODE_API_MIN,
- .sku = IWL_SKU_A|IWL_SKU_G,
- .ops = &iwl6000_ops,
+static struct iwl_base_params iwl6050_base_params = {
.eeprom_size = OTP_LOW_IMAGE_SIZE,
- .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
- .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
.num_of_queues = IWLAGN_NUM_QUEUES,
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
- .mod_params = &iwlagn_mod_params,
- .valid_tx_ant = ANT_AB,
- .valid_rx_ant = ANT_AB,
.pll_cfg_val = 0,
.set_l0s = true,
.use_bsm = false,
- .pa_type = IWL_PA_SYSTEM,
- .max_ll_items = OTP_MAX_LL_ITEMS_6x00,
+ .max_ll_items = OTP_MAX_LL_ITEMS_6x50,
.shadow_ram_support = true,
.led_compensation = 51,
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
@@ -423,33 +502,20 @@ struct iwl_cfg iwl6000g2a_2abg_cfg = {
.adv_thermal_throttle = true,
.support_ct_kill_exit = true,
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
- .chain_noise_scale = 1000,
+ .chain_noise_scale = 1500,
.monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
- .max_event_log_size = 512,
+ .max_event_log_size = 1024,
+ .ucode_tracing = true,
.sensitivity_calib_by_driver = true,
.chain_noise_calib_by_driver = true,
- .need_dc_calib = true,
};
-
-struct iwl_cfg iwl6000g2a_2bg_cfg = {
- .name = "6000 Series 2x2 BG Gen2a",
- .fw_name_pre = IWL6000G2A_FW_PRE,
- .ucode_api_max = IWL6000G2_UCODE_API_MAX,
- .ucode_api_min = IWL6000G2_UCODE_API_MIN,
- .sku = IWL_SKU_G,
- .ops = &iwl6000_ops,
+static struct iwl_base_params iwl6000_coex_base_params = {
.eeprom_size = OTP_LOW_IMAGE_SIZE,
- .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
- .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
.num_of_queues = IWLAGN_NUM_QUEUES,
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
- .mod_params = &iwlagn_mod_params,
- .valid_tx_ant = ANT_AB,
- .valid_rx_ant = ANT_AB,
.pll_cfg_val = 0,
.set_l0s = true,
.use_bsm = false,
- .pa_type = IWL_PA_SYSTEM,
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
.shadow_ram_support = true,
.led_compensation = 51,
@@ -459,11 +525,76 @@ struct iwl_cfg iwl6000g2a_2bg_cfg = {
.support_ct_kill_exit = true,
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
.chain_noise_scale = 1000,
- .monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
+ .monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
.max_event_log_size = 512,
+ .ucode_tracing = true,
.sensitivity_calib_by_driver = true,
.chain_noise_calib_by_driver = true,
+};
+
+static struct iwl_ht_params iwl6000_ht_params = {
+ .ht_greenfield_support = true,
+ .use_rts_for_aggregation = true, /* use rts/cts protection */
+};
+
+static struct iwl_bt_params iwl6000_bt_params = {
+ .bt_statistics = true,
+ /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
+ .advanced_bt_coexist = true,
+ .bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE,
+ .bt_prio_boost = IWLAGN_BT_PRIO_BOOST_DEFAULT,
+};
+
+struct iwl_cfg iwl6000g2a_2agn_cfg = {
+ .name = "6000 Series 2x2 AGN Gen2a",
+ .fw_name_pre = IWL6000G2A_FW_PRE,
+ .ucode_api_max = IWL6000G2_UCODE_API_MAX,
+ .ucode_api_min = IWL6000G2_UCODE_API_MIN,
+ .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
+ .valid_tx_ant = ANT_AB,
+ .valid_rx_ant = ANT_AB,
+ .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
+ .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
+ .ops = &iwl6000_ops,
+ .mod_params = &iwlagn_mod_params,
+ .base_params = &iwl6000_base_params,
+ .ht_params = &iwl6000_ht_params,
+ .need_dc_calib = true,
+ .need_temp_offset_calib = true,
+};
+
+struct iwl_cfg iwl6000g2a_2abg_cfg = {
+ .name = "6000 Series 2x2 ABG Gen2a",
+ .fw_name_pre = IWL6000G2A_FW_PRE,
+ .ucode_api_max = IWL6000G2_UCODE_API_MAX,
+ .ucode_api_min = IWL6000G2_UCODE_API_MIN,
+ .sku = IWL_SKU_A|IWL_SKU_G,
+ .valid_tx_ant = ANT_AB,
+ .valid_rx_ant = ANT_AB,
+ .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
+ .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
+ .ops = &iwl6000_ops,
+ .mod_params = &iwlagn_mod_params,
+ .base_params = &iwl6000_base_params,
+ .need_dc_calib = true,
+ .need_temp_offset_calib = true,
+};
+
+struct iwl_cfg iwl6000g2a_2bg_cfg = {
+ .name = "6000 Series 2x2 BG Gen2a",
+ .fw_name_pre = IWL6000G2A_FW_PRE,
+ .ucode_api_max = IWL6000G2_UCODE_API_MAX,
+ .ucode_api_min = IWL6000G2_UCODE_API_MIN,
+ .sku = IWL_SKU_G,
+ .valid_tx_ant = ANT_AB,
+ .valid_rx_ant = ANT_AB,
+ .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
+ .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
+ .ops = &iwl6000_ops,
+ .mod_params = &iwlagn_mod_params,
+ .base_params = &iwl6000_base_params,
.need_dc_calib = true,
+ .need_temp_offset_calib = true,
};
struct iwl_cfg iwl6000g2b_2agn_cfg = {
@@ -472,36 +603,19 @@ struct iwl_cfg iwl6000g2b_2agn_cfg = {
.ucode_api_max = IWL6000G2_UCODE_API_MAX,
.ucode_api_min = IWL6000G2_UCODE_API_MIN,
.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
- .ops = &iwl6000g2b_ops,
- .eeprom_size = OTP_LOW_IMAGE_SIZE,
+ .valid_tx_ant = ANT_AB,
+ .valid_rx_ant = ANT_AB,
.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
- .num_of_queues = IWLAGN_NUM_QUEUES,
- .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
+ .ops = &iwl6000g2b_ops,
.mod_params = &iwlagn_mod_params,
- .valid_tx_ant = ANT_AB,
- .valid_rx_ant = ANT_AB,
- .pll_cfg_val = 0,
- .set_l0s = true,
- .use_bsm = false,
- .pa_type = IWL_PA_SYSTEM,
- .max_ll_items = OTP_MAX_LL_ITEMS_6x00,
- .shadow_ram_support = true,
- .ht_greenfield_support = true,
- .led_compensation = 51,
- .use_rts_for_aggregation = true, /* use rts/cts protection */
- .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
- .supports_idle = true,
- .adv_thermal_throttle = true,
- .support_ct_kill_exit = true,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
- .chain_noise_scale = 1000,
- .monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
- .max_event_log_size = 512,
- .sensitivity_calib_by_driver = true,
- .chain_noise_calib_by_driver = true,
+ .base_params = &iwl6000_coex_base_params,
+ .bt_params = &iwl6000_bt_params,
+ .ht_params = &iwl6000_ht_params,
.need_dc_calib = true,
- .bt_statistics = true,
+ .need_temp_offset_calib = true,
+ /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
+ .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
};
struct iwl_cfg iwl6000g2b_2abg_cfg = {
@@ -510,34 +624,18 @@ struct iwl_cfg iwl6000g2b_2abg_cfg = {
.ucode_api_max = IWL6000G2_UCODE_API_MAX,
.ucode_api_min = IWL6000G2_UCODE_API_MIN,
.sku = IWL_SKU_A|IWL_SKU_G,
- .ops = &iwl6000g2b_ops,
- .eeprom_size = OTP_LOW_IMAGE_SIZE,
+ .valid_tx_ant = ANT_AB,
+ .valid_rx_ant = ANT_AB,
.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
- .num_of_queues = IWLAGN_NUM_QUEUES,
- .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
+ .ops = &iwl6000g2b_ops,
.mod_params = &iwlagn_mod_params,
- .valid_tx_ant = ANT_AB,
- .valid_rx_ant = ANT_AB,
- .pll_cfg_val = 0,
- .set_l0s = true,
- .use_bsm = false,
- .pa_type = IWL_PA_SYSTEM,
- .max_ll_items = OTP_MAX_LL_ITEMS_6x00,
- .shadow_ram_support = true,
- .led_compensation = 51,
- .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
- .supports_idle = true,
- .adv_thermal_throttle = true,
- .support_ct_kill_exit = true,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
- .chain_noise_scale = 1000,
- .monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
- .max_event_log_size = 512,
- .sensitivity_calib_by_driver = true,
- .chain_noise_calib_by_driver = true,
+ .base_params = &iwl6000_coex_base_params,
+ .bt_params = &iwl6000_bt_params,
.need_dc_calib = true,
- .bt_statistics = true,
+ .need_temp_offset_calib = true,
+ /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
+ .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
};
struct iwl_cfg iwl6000g2b_2bgn_cfg = {
@@ -546,36 +644,19 @@ struct iwl_cfg iwl6000g2b_2bgn_cfg = {
.ucode_api_max = IWL6000G2_UCODE_API_MAX,
.ucode_api_min = IWL6000G2_UCODE_API_MIN,
.sku = IWL_SKU_G|IWL_SKU_N,
- .ops = &iwl6000g2b_ops,
- .eeprom_size = OTP_LOW_IMAGE_SIZE,
+ .valid_tx_ant = ANT_AB,
+ .valid_rx_ant = ANT_AB,
.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
- .num_of_queues = IWLAGN_NUM_QUEUES,
- .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
+ .ops = &iwl6000g2b_ops,
.mod_params = &iwlagn_mod_params,
- .valid_tx_ant = ANT_AB,
- .valid_rx_ant = ANT_AB,
- .pll_cfg_val = 0,
- .set_l0s = true,
- .use_bsm = false,
- .pa_type = IWL_PA_SYSTEM,
- .max_ll_items = OTP_MAX_LL_ITEMS_6x00,
- .shadow_ram_support = true,
- .ht_greenfield_support = true,
- .led_compensation = 51,
- .use_rts_for_aggregation = true, /* use rts/cts protection */
- .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
- .supports_idle = true,
- .adv_thermal_throttle = true,
- .support_ct_kill_exit = true,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
- .chain_noise_scale = 1000,
- .monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
- .max_event_log_size = 512,
- .sensitivity_calib_by_driver = true,
- .chain_noise_calib_by_driver = true,
+ .base_params = &iwl6000_coex_base_params,
+ .bt_params = &iwl6000_bt_params,
+ .ht_params = &iwl6000_ht_params,
.need_dc_calib = true,
- .bt_statistics = true,
+ .need_temp_offset_calib = true,
+ /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
+ .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
};
struct iwl_cfg iwl6000g2b_2bg_cfg = {
@@ -584,34 +665,18 @@ struct iwl_cfg iwl6000g2b_2bg_cfg = {
.ucode_api_max = IWL6000G2_UCODE_API_MAX,
.ucode_api_min = IWL6000G2_UCODE_API_MIN,
.sku = IWL_SKU_G,
- .ops = &iwl6000g2b_ops,
- .eeprom_size = OTP_LOW_IMAGE_SIZE,
+ .valid_tx_ant = ANT_AB,
+ .valid_rx_ant = ANT_AB,
.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
- .num_of_queues = IWLAGN_NUM_QUEUES,
- .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
+ .ops = &iwl6000g2b_ops,
.mod_params = &iwlagn_mod_params,
- .valid_tx_ant = ANT_AB,
- .valid_rx_ant = ANT_AB,
- .pll_cfg_val = 0,
- .set_l0s = true,
- .use_bsm = false,
- .pa_type = IWL_PA_SYSTEM,
- .max_ll_items = OTP_MAX_LL_ITEMS_6x00,
- .shadow_ram_support = true,
- .led_compensation = 51,
- .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
- .supports_idle = true,
- .adv_thermal_throttle = true,
- .support_ct_kill_exit = true,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
- .chain_noise_scale = 1000,
- .monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
- .max_event_log_size = 512,
- .sensitivity_calib_by_driver = true,
- .chain_noise_calib_by_driver = true,
+ .base_params = &iwl6000_coex_base_params,
+ .bt_params = &iwl6000_bt_params,
.need_dc_calib = true,
- .bt_statistics = true,
+ .need_temp_offset_calib = true,
+ /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
+ .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
};
struct iwl_cfg iwl6000g2b_bgn_cfg = {
@@ -620,36 +685,19 @@ struct iwl_cfg iwl6000g2b_bgn_cfg = {
.ucode_api_max = IWL6000G2_UCODE_API_MAX,
.ucode_api_min = IWL6000G2_UCODE_API_MIN,
.sku = IWL_SKU_G|IWL_SKU_N,
- .ops = &iwl6000g2b_ops,
- .eeprom_size = OTP_LOW_IMAGE_SIZE,
+ .valid_tx_ant = ANT_A,
+ .valid_rx_ant = ANT_AB,
.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
- .num_of_queues = IWLAGN_NUM_QUEUES,
- .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
+ .ops = &iwl6000g2b_ops,
.mod_params = &iwlagn_mod_params,
- .valid_tx_ant = ANT_A,
- .valid_rx_ant = ANT_AB,
- .pll_cfg_val = 0,
- .set_l0s = true,
- .use_bsm = false,
- .pa_type = IWL_PA_SYSTEM,
- .max_ll_items = OTP_MAX_LL_ITEMS_6x00,
- .shadow_ram_support = true,
- .ht_greenfield_support = true,
- .led_compensation = 51,
- .use_rts_for_aggregation = true, /* use rts/cts protection */
- .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
- .supports_idle = true,
- .adv_thermal_throttle = true,
- .support_ct_kill_exit = true,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
- .chain_noise_scale = 1000,
- .monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
- .max_event_log_size = 512,
- .sensitivity_calib_by_driver = true,
- .chain_noise_calib_by_driver = true,
+ .base_params = &iwl6000_coex_base_params,
+ .bt_params = &iwl6000_bt_params,
+ .ht_params = &iwl6000_ht_params,
.need_dc_calib = true,
- .bt_statistics = true,
+ .need_temp_offset_calib = true,
+ /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
+ .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
};
struct iwl_cfg iwl6000g2b_bg_cfg = {
@@ -658,34 +706,18 @@ struct iwl_cfg iwl6000g2b_bg_cfg = {
.ucode_api_max = IWL6000G2_UCODE_API_MAX,
.ucode_api_min = IWL6000G2_UCODE_API_MIN,
.sku = IWL_SKU_G,
- .ops = &iwl6000g2b_ops,
- .eeprom_size = OTP_LOW_IMAGE_SIZE,
+ .valid_tx_ant = ANT_A,
+ .valid_rx_ant = ANT_AB,
.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
- .num_of_queues = IWLAGN_NUM_QUEUES,
- .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
+ .ops = &iwl6000g2b_ops,
.mod_params = &iwlagn_mod_params,
- .valid_tx_ant = ANT_A,
- .valid_rx_ant = ANT_AB,
- .pll_cfg_val = 0,
- .set_l0s = true,
- .use_bsm = false,
- .pa_type = IWL_PA_SYSTEM,
- .max_ll_items = OTP_MAX_LL_ITEMS_6x00,
- .shadow_ram_support = true,
- .led_compensation = 51,
- .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
- .supports_idle = true,
- .adv_thermal_throttle = true,
- .support_ct_kill_exit = true,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
- .chain_noise_scale = 1000,
- .monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
- .max_event_log_size = 512,
- .sensitivity_calib_by_driver = true,
- .chain_noise_calib_by_driver = true,
+ .base_params = &iwl6000_coex_base_params,
+ .bt_params = &iwl6000_bt_params,
.need_dc_calib = true,
- .bt_statistics = true,
+ .need_temp_offset_calib = true,
+ /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
+ .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
};
/*
@@ -697,35 +729,15 @@ struct iwl_cfg iwl6000i_2agn_cfg = {
.ucode_api_max = IWL6000_UCODE_API_MAX,
.ucode_api_min = IWL6000_UCODE_API_MIN,
.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
- .ops = &iwl6000_ops,
- .eeprom_size = OTP_LOW_IMAGE_SIZE,
+ .valid_tx_ant = ANT_BC,
+ .valid_rx_ant = ANT_BC,
.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION,
- .num_of_queues = IWLAGN_NUM_QUEUES,
- .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
+ .ops = &iwl6000_ops,
.mod_params = &iwlagn_mod_params,
- .valid_tx_ant = ANT_BC,
- .valid_rx_ant = ANT_BC,
- .pll_cfg_val = 0,
- .set_l0s = true,
- .use_bsm = false,
+ .base_params = &iwl6000_base_params,
+ .ht_params = &iwl6000_ht_params,
.pa_type = IWL_PA_INTERNAL,
- .max_ll_items = OTP_MAX_LL_ITEMS_6x00,
- .shadow_ram_support = true,
- .ht_greenfield_support = true,
- .led_compensation = 51,
- .use_rts_for_aggregation = true, /* use rts/cts protection */
- .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
- .supports_idle = true,
- .adv_thermal_throttle = true,
- .support_ct_kill_exit = true,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
- .chain_noise_scale = 1000,
- .monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
- .max_event_log_size = 1024,
- .ucode_tracing = true,
- .sensitivity_calib_by_driver = true,
- .chain_noise_calib_by_driver = true,
};
struct iwl_cfg iwl6000i_2abg_cfg = {
@@ -734,33 +746,14 @@ struct iwl_cfg iwl6000i_2abg_cfg = {
.ucode_api_max = IWL6000_UCODE_API_MAX,
.ucode_api_min = IWL6000_UCODE_API_MIN,
.sku = IWL_SKU_A|IWL_SKU_G,
- .ops = &iwl6000_ops,
- .eeprom_size = OTP_LOW_IMAGE_SIZE,
+ .valid_tx_ant = ANT_BC,
+ .valid_rx_ant = ANT_BC,
.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION,
- .num_of_queues = IWLAGN_NUM_QUEUES,
- .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
+ .ops = &iwl6000_ops,
.mod_params = &iwlagn_mod_params,
- .valid_tx_ant = ANT_BC,
- .valid_rx_ant = ANT_BC,
- .pll_cfg_val = 0,
- .set_l0s = true,
- .use_bsm = false,
+ .base_params = &iwl6000_base_params,
.pa_type = IWL_PA_INTERNAL,
- .max_ll_items = OTP_MAX_LL_ITEMS_6x00,
- .shadow_ram_support = true,
- .led_compensation = 51,
- .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
- .supports_idle = true,
- .adv_thermal_throttle = true,
- .support_ct_kill_exit = true,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
- .chain_noise_scale = 1000,
- .monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
- .max_event_log_size = 1024,
- .ucode_tracing = true,
- .sensitivity_calib_by_driver = true,
- .chain_noise_calib_by_driver = true,
};
struct iwl_cfg iwl6000i_2bg_cfg = {
@@ -769,33 +762,14 @@ struct iwl_cfg iwl6000i_2bg_cfg = {
.ucode_api_max = IWL6000_UCODE_API_MAX,
.ucode_api_min = IWL6000_UCODE_API_MIN,
.sku = IWL_SKU_G,
- .ops = &iwl6000_ops,
- .eeprom_size = OTP_LOW_IMAGE_SIZE,
+ .valid_tx_ant = ANT_BC,
+ .valid_rx_ant = ANT_BC,
.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION,
- .num_of_queues = IWLAGN_NUM_QUEUES,
- .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
+ .ops = &iwl6000_ops,
.mod_params = &iwlagn_mod_params,
- .valid_tx_ant = ANT_BC,
- .valid_rx_ant = ANT_BC,
- .pll_cfg_val = 0,
- .set_l0s = true,
- .use_bsm = false,
+ .base_params = &iwl6000_base_params,
.pa_type = IWL_PA_INTERNAL,
- .max_ll_items = OTP_MAX_LL_ITEMS_6x00,
- .shadow_ram_support = true,
- .led_compensation = 51,
- .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
- .supports_idle = true,
- .adv_thermal_throttle = true,
- .support_ct_kill_exit = true,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
- .chain_noise_scale = 1000,
- .monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
- .max_event_log_size = 1024,
- .ucode_tracing = true,
- .sensitivity_calib_by_driver = true,
- .chain_noise_calib_by_driver = true,
};
struct iwl_cfg iwl6050_2agn_cfg = {
@@ -804,35 +778,14 @@ struct iwl_cfg iwl6050_2agn_cfg = {
.ucode_api_max = IWL6050_UCODE_API_MAX,
.ucode_api_min = IWL6050_UCODE_API_MIN,
.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
- .ops = &iwl6000_ops,
- .eeprom_size = OTP_LOW_IMAGE_SIZE,
+ .valid_tx_ant = ANT_AB,
+ .valid_rx_ant = ANT_AB,
+ .ops = &iwl6050_ops,
.eeprom_ver = EEPROM_6050_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION,
- .num_of_queues = IWLAGN_NUM_QUEUES,
- .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
.mod_params = &iwlagn_mod_params,
- .valid_tx_ant = ANT_AB,
- .valid_rx_ant = ANT_AB,
- .pll_cfg_val = 0,
- .set_l0s = true,
- .use_bsm = false,
- .pa_type = IWL_PA_SYSTEM,
- .max_ll_items = OTP_MAX_LL_ITEMS_6x50,
- .shadow_ram_support = true,
- .ht_greenfield_support = true,
- .led_compensation = 51,
- .use_rts_for_aggregation = true, /* use rts/cts protection */
- .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
- .supports_idle = true,
- .adv_thermal_throttle = true,
- .support_ct_kill_exit = true,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
- .chain_noise_scale = 1500,
- .monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
- .max_event_log_size = 1024,
- .ucode_tracing = true,
- .sensitivity_calib_by_driver = true,
- .chain_noise_calib_by_driver = true,
+ .base_params = &iwl6050_base_params,
+ .ht_params = &iwl6000_ht_params,
.need_dc_calib = true,
};
@@ -842,35 +795,14 @@ struct iwl_cfg iwl6050g2_bgn_cfg = {
.ucode_api_max = IWL6050_UCODE_API_MAX,
.ucode_api_min = IWL6050_UCODE_API_MIN,
.sku = IWL_SKU_G|IWL_SKU_N,
- .ops = &iwl6000_ops,
- .eeprom_size = OTP_LOW_IMAGE_SIZE,
+ .valid_tx_ant = ANT_A,
+ .valid_rx_ant = ANT_AB,
.eeprom_ver = EEPROM_6050G2_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_6050G2_TX_POWER_VERSION,
- .num_of_queues = IWLAGN_NUM_QUEUES,
- .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
+ .ops = &iwl6050g2_ops,
.mod_params = &iwlagn_mod_params,
- .valid_tx_ant = ANT_A,
- .valid_rx_ant = ANT_AB,
- .pll_cfg_val = 0,
- .set_l0s = true,
- .use_bsm = false,
- .pa_type = IWL_PA_SYSTEM,
- .max_ll_items = OTP_MAX_LL_ITEMS_6x50,
- .shadow_ram_support = true,
- .ht_greenfield_support = true,
- .led_compensation = 51,
- .use_rts_for_aggregation = true, /* use rts/cts protection */
- .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
- .supports_idle = true,
- .adv_thermal_throttle = true,
- .support_ct_kill_exit = true,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
- .chain_noise_scale = 1500,
- .monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
- .max_event_log_size = 1024,
- .ucode_tracing = true,
- .sensitivity_calib_by_driver = true,
- .chain_noise_calib_by_driver = true,
+ .base_params = &iwl6050_base_params,
+ .ht_params = &iwl6000_ht_params,
.need_dc_calib = true,
};
@@ -880,33 +812,13 @@ struct iwl_cfg iwl6050_2abg_cfg = {
.ucode_api_max = IWL6050_UCODE_API_MAX,
.ucode_api_min = IWL6050_UCODE_API_MIN,
.sku = IWL_SKU_A|IWL_SKU_G,
- .ops = &iwl6000_ops,
- .eeprom_size = OTP_LOW_IMAGE_SIZE,
+ .valid_tx_ant = ANT_AB,
+ .valid_rx_ant = ANT_AB,
.eeprom_ver = EEPROM_6050_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION,
- .num_of_queues = IWLAGN_NUM_QUEUES,
- .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
+ .ops = &iwl6050_ops,
.mod_params = &iwlagn_mod_params,
- .valid_tx_ant = ANT_AB,
- .valid_rx_ant = ANT_AB,
- .pll_cfg_val = 0,
- .set_l0s = true,
- .use_bsm = false,
- .pa_type = IWL_PA_SYSTEM,
- .max_ll_items = OTP_MAX_LL_ITEMS_6x50,
- .shadow_ram_support = true,
- .led_compensation = 51,
- .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
- .supports_idle = true,
- .adv_thermal_throttle = true,
- .support_ct_kill_exit = true,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
- .chain_noise_scale = 1500,
- .monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
- .max_event_log_size = 1024,
- .ucode_tracing = true,
- .sensitivity_calib_by_driver = true,
- .chain_noise_calib_by_driver = true,
+ .base_params = &iwl6050_base_params,
.need_dc_calib = true,
};
@@ -916,38 +828,58 @@ struct iwl_cfg iwl6000_3agn_cfg = {
.ucode_api_max = IWL6000_UCODE_API_MAX,
.ucode_api_min = IWL6000_UCODE_API_MIN,
.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
- .ops = &iwl6000_ops,
- .eeprom_size = OTP_LOW_IMAGE_SIZE,
+ .valid_tx_ant = ANT_ABC,
+ .valid_rx_ant = ANT_ABC,
.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION,
- .num_of_queues = IWLAGN_NUM_QUEUES,
- .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
+ .ops = &iwl6000_ops,
.mod_params = &iwlagn_mod_params,
- .valid_tx_ant = ANT_ABC,
- .valid_rx_ant = ANT_ABC,
- .pll_cfg_val = 0,
- .set_l0s = true,
- .use_bsm = false,
- .pa_type = IWL_PA_SYSTEM,
- .max_ll_items = OTP_MAX_LL_ITEMS_6x00,
- .shadow_ram_support = true,
- .ht_greenfield_support = true,
- .led_compensation = 51,
- .use_rts_for_aggregation = true, /* use rts/cts protection */
- .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
- .supports_idle = true,
- .adv_thermal_throttle = true,
- .support_ct_kill_exit = true,
- .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
- .chain_noise_scale = 1000,
- .monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
- .max_event_log_size = 1024,
- .ucode_tracing = true,
- .sensitivity_calib_by_driver = true,
- .chain_noise_calib_by_driver = true,
+ .base_params = &iwl6000_base_params,
+ .ht_params = &iwl6000_ht_params,
+ .need_dc_calib = true,
+};
+
+struct iwl_cfg iwl130_bgn_cfg = {
+ .name = "Intel(R) 130 Series 1x1 BGN",
+ .fw_name_pre = IWL6000G2B_FW_PRE,
+ .ucode_api_max = IWL130_UCODE_API_MAX,
+ .ucode_api_min = IWL130_UCODE_API_MIN,
+ .sku = IWL_SKU_G|IWL_SKU_N,
+ .valid_tx_ant = ANT_A,
+ .valid_rx_ant = ANT_A,
+ .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
+ .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
+ .ops = &iwl6000g2b_ops,
+ .mod_params = &iwlagn_mod_params,
+ .base_params = &iwl6000_coex_base_params,
+ .bt_params = &iwl6000_bt_params,
+ .ht_params = &iwl6000_ht_params,
+ .need_dc_calib = true,
+ /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
+ .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
+};
+
+struct iwl_cfg iwl130_bg_cfg = {
+ .name = "Intel(R) 130 Series 1x2 BG",
+ .fw_name_pre = IWL6000G2B_FW_PRE,
+ .ucode_api_max = IWL130_UCODE_API_MAX,
+ .ucode_api_min = IWL130_UCODE_API_MIN,
+ .sku = IWL_SKU_G,
+ .valid_tx_ant = ANT_A,
+ .valid_rx_ant = ANT_A,
+ .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
+ .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
+ .ops = &iwl6000g2b_ops,
+ .mod_params = &iwlagn_mod_params,
+ .base_params = &iwl6000_coex_base_params,
+ .bt_params = &iwl6000_bt_params,
+ .need_dc_calib = true,
+ /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
+ .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
};
MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL6050_MODULE_FIRMWARE(IWL6050_UCODE_API_MAX));
MODULE_FIRMWARE(IWL6000G2A_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX));
MODULE_FIRMWARE(IWL6000G2B_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL130_MODULE_FIRMWARE(IWL130_UCODE_API_MAX));
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
index c4c5691032a6..e2019e756936 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
@@ -65,7 +65,7 @@
#include "iwl-dev.h"
#include "iwl-core.h"
-#include "iwl-calib.h"
+#include "iwl-agn-calib.h"
/*****************************************************************************
* INIT calibrations framework
@@ -625,13 +625,14 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv, void *resp)
data = &(priv->sensitivity_data);
- if (!iwl_is_associated(priv)) {
+ if (!iwl_is_any_associated(priv)) {
IWL_DEBUG_CALIB(priv, "<< - not associated\n");
return;
}
spin_lock_irqsave(&priv->lock, flags);
- if (priv->cfg->bt_statistics) {
+ if (priv->cfg->bt_params &&
+ priv->cfg->bt_params->bt_statistics) {
rx_info = &(((struct iwl_bt_notif_statistics *)resp)->
rx.general.common);
ofdm = &(((struct iwl_bt_notif_statistics *)resp)->rx.ofdm);
@@ -763,6 +764,12 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp)
unsigned long flags;
struct statistics_rx_non_phy *rx_info;
u8 first_chain;
+ /*
+ * MULTI-FIXME:
+ * When we support multiple interfaces on different channels,
+ * this must be modified/fixed.
+ */
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
if (priv->disable_chain_noise_cal)
return;
@@ -780,7 +787,8 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp)
}
spin_lock_irqsave(&priv->lock, flags);
- if (priv->cfg->bt_statistics) {
+ if (priv->cfg->bt_params &&
+ priv->cfg->bt_params->bt_statistics) {
rx_info = &(((struct iwl_bt_notif_statistics *)stat_resp)->
rx.general.common);
} else {
@@ -793,9 +801,10 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp)
return;
}
- rxon_band24 = !!(priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK);
- rxon_chnum = le16_to_cpu(priv->staging_rxon.channel);
- if (priv->cfg->bt_statistics) {
+ rxon_band24 = !!(ctx->staging.flags & RXON_FLG_BAND_24G_MSK);
+ rxon_chnum = le16_to_cpu(ctx->staging.channel);
+ if (priv->cfg->bt_params &&
+ priv->cfg->bt_params->bt_statistics) {
stat_band24 = !!(((struct iwl_bt_notif_statistics *)
stat_resp)->flag &
STATISTICS_REPLY_FLG_BAND_24G_MSK);
@@ -855,16 +864,17 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp)
/* If this is the "chain_noise_num_beacons", determine:
* 1) Disconnected antennas (using signal strengths)
* 2) Differential gain (using silence noise) to balance receivers */
- if (data->beacon_count != priv->cfg->chain_noise_num_beacons)
+ if (data->beacon_count !=
+ priv->cfg->base_params->chain_noise_num_beacons)
return;
/* Analyze signal for disconnected antenna */
- average_sig[0] =
- (data->chain_signal_a) / priv->cfg->chain_noise_num_beacons;
- average_sig[1] =
- (data->chain_signal_b) / priv->cfg->chain_noise_num_beacons;
- average_sig[2] =
- (data->chain_signal_c) / priv->cfg->chain_noise_num_beacons;
+ average_sig[0] = data->chain_signal_a /
+ priv->cfg->base_params->chain_noise_num_beacons;
+ average_sig[1] = data->chain_signal_b /
+ priv->cfg->base_params->chain_noise_num_beacons;
+ average_sig[2] = data->chain_signal_c /
+ priv->cfg->base_params->chain_noise_num_beacons;
if (average_sig[0] >= average_sig[1]) {
max_average_sig = average_sig[0];
@@ -914,7 +924,13 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp)
* To be safe, simply mask out any chains that we know
* are not on the device.
*/
- active_chains &= priv->hw_params.valid_rx_ant;
+ if (priv->cfg->bt_params &&
+ priv->cfg->bt_params->advanced_bt_coexist &&
+ priv->bt_full_concurrent) {
+ /* operated as 1x1 in full concurrency mode */
+ active_chains &= first_antenna(priv->hw_params.valid_rx_ant);
+ } else
+ active_chains &= priv->hw_params.valid_rx_ant;
num_tx_chains = 0;
for (i = 0; i < NUM_RX_CHAINS; i++) {
@@ -957,12 +973,12 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp)
active_chains);
/* Analyze noise for rx balance */
- average_noise[0] =
- ((data->chain_noise_a) / priv->cfg->chain_noise_num_beacons);
- average_noise[1] =
- ((data->chain_noise_b) / priv->cfg->chain_noise_num_beacons);
- average_noise[2] =
- ((data->chain_noise_c) / priv->cfg->chain_noise_num_beacons);
+ average_noise[0] = data->chain_noise_a /
+ priv->cfg->base_params->chain_noise_num_beacons;
+ average_noise[1] = data->chain_noise_b /
+ priv->cfg->base_params->chain_noise_num_beacons;
+ average_noise[2] = data->chain_noise_c /
+ priv->cfg->base_params->chain_noise_num_beacons;
for (i = 0; i < NUM_RX_CHAINS; i++) {
if (!(data->disconn_array[i]) &&
diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.h b/drivers/net/wireless/iwlwifi/iwl-agn-calib.h
index ba9523fbb300..e37ae7261630 100644
--- a/drivers/net/wireless/iwlwifi/iwl-calib.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.h
@@ -79,4 +79,8 @@ static inline void iwl_chain_noise_reset(struct iwl_priv *priv)
priv->cfg->ops->utils->chain_noise_reset(priv);
}
+int iwl_send_calib_results(struct iwl_priv *priv);
+int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len);
+void iwl_calib_free_results(struct iwl_priv *priv);
+
#endif /* __iwl_calib_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c
index d706b8afbe5a..a358d4334a1a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c
@@ -25,15 +25,22 @@
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*****************************************************************************/
-
+#include "iwl-agn.h"
#include "iwl-agn-debugfs.h"
+static const char *fmt_value = " %-30s %10u\n";
+static const char *fmt_hex = " %-30s 0x%02X\n";
+static const char *fmt_table = " %-30s %10u %10u %10u %10u\n";
+static const char *fmt_header =
+ "%-32s current cumulative delta max\n";
+
static int iwl_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz)
{
int p = 0;
u32 flag;
- if (priv->cfg->bt_statistics)
+ if (priv->cfg->bt_params &&
+ priv->cfg->bt_params->bt_statistics)
flag = le32_to_cpu(priv->_agn.statistics_bt.flag);
else
flag = le32_to_cpu(priv->_agn.statistics.flag);
@@ -82,7 +89,8 @@ ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf,
* the last statistics notification from uCode
* might not reflect the current uCode activity
*/
- if (priv->cfg->bt_statistics) {
+ if (priv->cfg->bt_params &&
+ priv->cfg->bt_params->bt_statistics) {
ofdm = &priv->_agn.statistics_bt.rx.ofdm;
cck = &priv->_agn.statistics_bt.rx.cck;
general = &priv->_agn.statistics_bt.rx.general.common;
@@ -121,436 +129,380 @@ ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf,
}
pos += iwl_statistics_flag(priv, buf, bufsz);
- pos += scnprintf(buf + pos, bufsz - pos, "%-32s current"
- "acumulative delta max\n",
- "Statistics_Rx - OFDM:");
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "ina_cnt:", le32_to_cpu(ofdm->ina_cnt),
+ fmt_header, "Statistics_Rx - OFDM:");
+ pos += scnprintf(buf + pos, bufsz - pos,
+ fmt_table, "ina_cnt:",
+ le32_to_cpu(ofdm->ina_cnt),
accum_ofdm->ina_cnt,
delta_ofdm->ina_cnt, max_ofdm->ina_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "fina_cnt:",
+ fmt_table, "fina_cnt:",
le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt,
delta_ofdm->fina_cnt, max_ofdm->fina_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "plcp_err:",
+ fmt_table, "plcp_err:",
le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err,
delta_ofdm->plcp_err, max_ofdm->plcp_err);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n", "crc32_err:",
+ fmt_table, "crc32_err:",
le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err,
delta_ofdm->crc32_err, max_ofdm->crc32_err);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n", "overrun_err:",
+ fmt_table, "overrun_err:",
le32_to_cpu(ofdm->overrun_err),
accum_ofdm->overrun_err, delta_ofdm->overrun_err,
max_ofdm->overrun_err);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "early_overrun_err:",
+ fmt_table, "early_overrun_err:",
le32_to_cpu(ofdm->early_overrun_err),
accum_ofdm->early_overrun_err,
delta_ofdm->early_overrun_err,
max_ofdm->early_overrun_err);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "crc32_good:", le32_to_cpu(ofdm->crc32_good),
+ fmt_table, "crc32_good:",
+ le32_to_cpu(ofdm->crc32_good),
accum_ofdm->crc32_good, delta_ofdm->crc32_good,
max_ofdm->crc32_good);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n", "false_alarm_cnt:",
+ fmt_table, "false_alarm_cnt:",
le32_to_cpu(ofdm->false_alarm_cnt),
accum_ofdm->false_alarm_cnt,
delta_ofdm->false_alarm_cnt,
max_ofdm->false_alarm_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "fina_sync_err_cnt:",
+ fmt_table, "fina_sync_err_cnt:",
le32_to_cpu(ofdm->fina_sync_err_cnt),
accum_ofdm->fina_sync_err_cnt,
delta_ofdm->fina_sync_err_cnt,
max_ofdm->fina_sync_err_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n", "sfd_timeout:",
+ fmt_table, "sfd_timeout:",
le32_to_cpu(ofdm->sfd_timeout),
accum_ofdm->sfd_timeout, delta_ofdm->sfd_timeout,
max_ofdm->sfd_timeout);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n", "fina_timeout:",
+ fmt_table, "fina_timeout:",
le32_to_cpu(ofdm->fina_timeout),
accum_ofdm->fina_timeout, delta_ofdm->fina_timeout,
max_ofdm->fina_timeout);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "unresponded_rts:",
+ fmt_table, "unresponded_rts:",
le32_to_cpu(ofdm->unresponded_rts),
accum_ofdm->unresponded_rts,
delta_ofdm->unresponded_rts,
max_ofdm->unresponded_rts);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "rxe_frame_lmt_ovrun:",
+ fmt_table, "rxe_frame_lmt_ovrun:",
le32_to_cpu(ofdm->rxe_frame_limit_overrun),
accum_ofdm->rxe_frame_limit_overrun,
delta_ofdm->rxe_frame_limit_overrun,
max_ofdm->rxe_frame_limit_overrun);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n", "sent_ack_cnt:",
+ fmt_table, "sent_ack_cnt:",
le32_to_cpu(ofdm->sent_ack_cnt),
accum_ofdm->sent_ack_cnt, delta_ofdm->sent_ack_cnt,
max_ofdm->sent_ack_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n", "sent_cts_cnt:",
+ fmt_table, "sent_cts_cnt:",
le32_to_cpu(ofdm->sent_cts_cnt),
accum_ofdm->sent_cts_cnt, delta_ofdm->sent_cts_cnt,
max_ofdm->sent_cts_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "sent_ba_rsp_cnt:",
+ fmt_table, "sent_ba_rsp_cnt:",
le32_to_cpu(ofdm->sent_ba_rsp_cnt),
accum_ofdm->sent_ba_rsp_cnt,
delta_ofdm->sent_ba_rsp_cnt,
max_ofdm->sent_ba_rsp_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n", "dsp_self_kill:",
+ fmt_table, "dsp_self_kill:",
le32_to_cpu(ofdm->dsp_self_kill),
accum_ofdm->dsp_self_kill,
delta_ofdm->dsp_self_kill,
max_ofdm->dsp_self_kill);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "mh_format_err:",
+ fmt_table, "mh_format_err:",
le32_to_cpu(ofdm->mh_format_err),
accum_ofdm->mh_format_err,
delta_ofdm->mh_format_err,
max_ofdm->mh_format_err);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "re_acq_main_rssi_sum:",
+ fmt_table, "re_acq_main_rssi_sum:",
le32_to_cpu(ofdm->re_acq_main_rssi_sum),
accum_ofdm->re_acq_main_rssi_sum,
delta_ofdm->re_acq_main_rssi_sum,
max_ofdm->re_acq_main_rssi_sum);
- pos += scnprintf(buf + pos, bufsz - pos, "%-32s current"
- "acumulative delta max\n",
- "Statistics_Rx - CCK:");
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "ina_cnt:",
+ fmt_header, "Statistics_Rx - CCK:");
+ pos += scnprintf(buf + pos, bufsz - pos,
+ fmt_table, "ina_cnt:",
le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt,
delta_cck->ina_cnt, max_cck->ina_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "fina_cnt:",
+ fmt_table, "fina_cnt:",
le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt,
delta_cck->fina_cnt, max_cck->fina_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "plcp_err:",
+ fmt_table, "plcp_err:",
le32_to_cpu(cck->plcp_err), accum_cck->plcp_err,
delta_cck->plcp_err, max_cck->plcp_err);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "crc32_err:",
+ fmt_table, "crc32_err:",
le32_to_cpu(cck->crc32_err), accum_cck->crc32_err,
delta_cck->crc32_err, max_cck->crc32_err);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "overrun_err:",
+ fmt_table, "overrun_err:",
le32_to_cpu(cck->overrun_err),
accum_cck->overrun_err, delta_cck->overrun_err,
max_cck->overrun_err);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "early_overrun_err:",
+ fmt_table, "early_overrun_err:",
le32_to_cpu(cck->early_overrun_err),
accum_cck->early_overrun_err,
delta_cck->early_overrun_err,
max_cck->early_overrun_err);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "crc32_good:",
+ fmt_table, "crc32_good:",
le32_to_cpu(cck->crc32_good), accum_cck->crc32_good,
delta_cck->crc32_good, max_cck->crc32_good);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "false_alarm_cnt:",
+ fmt_table, "false_alarm_cnt:",
le32_to_cpu(cck->false_alarm_cnt),
accum_cck->false_alarm_cnt,
delta_cck->false_alarm_cnt, max_cck->false_alarm_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "fina_sync_err_cnt:",
+ fmt_table, "fina_sync_err_cnt:",
le32_to_cpu(cck->fina_sync_err_cnt),
accum_cck->fina_sync_err_cnt,
delta_cck->fina_sync_err_cnt,
max_cck->fina_sync_err_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "sfd_timeout:",
+ fmt_table, "sfd_timeout:",
le32_to_cpu(cck->sfd_timeout),
accum_cck->sfd_timeout, delta_cck->sfd_timeout,
max_cck->sfd_timeout);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n", "fina_timeout:",
+ fmt_table, "fina_timeout:",
le32_to_cpu(cck->fina_timeout),
accum_cck->fina_timeout, delta_cck->fina_timeout,
max_cck->fina_timeout);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "unresponded_rts:",
+ fmt_table, "unresponded_rts:",
le32_to_cpu(cck->unresponded_rts),
accum_cck->unresponded_rts, delta_cck->unresponded_rts,
max_cck->unresponded_rts);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "rxe_frame_lmt_ovrun:",
+ fmt_table, "rxe_frame_lmt_ovrun:",
le32_to_cpu(cck->rxe_frame_limit_overrun),
accum_cck->rxe_frame_limit_overrun,
delta_cck->rxe_frame_limit_overrun,
max_cck->rxe_frame_limit_overrun);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n", "sent_ack_cnt:",
+ fmt_table, "sent_ack_cnt:",
le32_to_cpu(cck->sent_ack_cnt),
accum_cck->sent_ack_cnt, delta_cck->sent_ack_cnt,
max_cck->sent_ack_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n", "sent_cts_cnt:",
+ fmt_table, "sent_cts_cnt:",
le32_to_cpu(cck->sent_cts_cnt),
accum_cck->sent_cts_cnt, delta_cck->sent_cts_cnt,
max_cck->sent_cts_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n", "sent_ba_rsp_cnt:",
+ fmt_table, "sent_ba_rsp_cnt:",
le32_to_cpu(cck->sent_ba_rsp_cnt),
accum_cck->sent_ba_rsp_cnt,
delta_cck->sent_ba_rsp_cnt,
max_cck->sent_ba_rsp_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n", "dsp_self_kill:",
+ fmt_table, "dsp_self_kill:",
le32_to_cpu(cck->dsp_self_kill),
accum_cck->dsp_self_kill, delta_cck->dsp_self_kill,
max_cck->dsp_self_kill);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n", "mh_format_err:",
+ fmt_table, "mh_format_err:",
le32_to_cpu(cck->mh_format_err),
accum_cck->mh_format_err, delta_cck->mh_format_err,
max_cck->mh_format_err);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "re_acq_main_rssi_sum:",
+ fmt_table, "re_acq_main_rssi_sum:",
le32_to_cpu(cck->re_acq_main_rssi_sum),
accum_cck->re_acq_main_rssi_sum,
delta_cck->re_acq_main_rssi_sum,
max_cck->re_acq_main_rssi_sum);
- pos += scnprintf(buf + pos, bufsz - pos, "%-32s current"
- "acumulative delta max\n",
- "Statistics_Rx - GENERAL:");
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n", "bogus_cts:",
+ fmt_header, "Statistics_Rx - GENERAL:");
+ pos += scnprintf(buf + pos, bufsz - pos,
+ fmt_table, "bogus_cts:",
le32_to_cpu(general->bogus_cts),
accum_general->bogus_cts, delta_general->bogus_cts,
max_general->bogus_cts);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n", "bogus_ack:",
+ fmt_table, "bogus_ack:",
le32_to_cpu(general->bogus_ack),
accum_general->bogus_ack, delta_general->bogus_ack,
max_general->bogus_ack);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "non_bssid_frames:",
+ fmt_table, "non_bssid_frames:",
le32_to_cpu(general->non_bssid_frames),
accum_general->non_bssid_frames,
delta_general->non_bssid_frames,
max_general->non_bssid_frames);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "filtered_frames:",
+ fmt_table, "filtered_frames:",
le32_to_cpu(general->filtered_frames),
accum_general->filtered_frames,
delta_general->filtered_frames,
max_general->filtered_frames);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "non_channel_beacons:",
+ fmt_table, "non_channel_beacons:",
le32_to_cpu(general->non_channel_beacons),
accum_general->non_channel_beacons,
delta_general->non_channel_beacons,
max_general->non_channel_beacons);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "channel_beacons:",
+ fmt_table, "channel_beacons:",
le32_to_cpu(general->channel_beacons),
accum_general->channel_beacons,
delta_general->channel_beacons,
max_general->channel_beacons);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "num_missed_bcon:",
+ fmt_table, "num_missed_bcon:",
le32_to_cpu(general->num_missed_bcon),
accum_general->num_missed_bcon,
delta_general->num_missed_bcon,
max_general->num_missed_bcon);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "adc_rx_saturation_time:",
+ fmt_table, "adc_rx_saturation_time:",
le32_to_cpu(general->adc_rx_saturation_time),
accum_general->adc_rx_saturation_time,
delta_general->adc_rx_saturation_time,
max_general->adc_rx_saturation_time);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "ina_detect_search_tm:",
+ fmt_table, "ina_detect_search_tm:",
le32_to_cpu(general->ina_detection_search_time),
accum_general->ina_detection_search_time,
delta_general->ina_detection_search_time,
max_general->ina_detection_search_time);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "beacon_silence_rssi_a:",
+ fmt_table, "beacon_silence_rssi_a:",
le32_to_cpu(general->beacon_silence_rssi_a),
accum_general->beacon_silence_rssi_a,
delta_general->beacon_silence_rssi_a,
max_general->beacon_silence_rssi_a);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "beacon_silence_rssi_b:",
+ fmt_table, "beacon_silence_rssi_b:",
le32_to_cpu(general->beacon_silence_rssi_b),
accum_general->beacon_silence_rssi_b,
delta_general->beacon_silence_rssi_b,
max_general->beacon_silence_rssi_b);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "beacon_silence_rssi_c:",
+ fmt_table, "beacon_silence_rssi_c:",
le32_to_cpu(general->beacon_silence_rssi_c),
accum_general->beacon_silence_rssi_c,
delta_general->beacon_silence_rssi_c,
max_general->beacon_silence_rssi_c);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "interference_data_flag:",
+ fmt_table, "interference_data_flag:",
le32_to_cpu(general->interference_data_flag),
accum_general->interference_data_flag,
delta_general->interference_data_flag,
max_general->interference_data_flag);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "channel_load:",
+ fmt_table, "channel_load:",
le32_to_cpu(general->channel_load),
accum_general->channel_load,
delta_general->channel_load,
max_general->channel_load);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "dsp_false_alarms:",
+ fmt_table, "dsp_false_alarms:",
le32_to_cpu(general->dsp_false_alarms),
accum_general->dsp_false_alarms,
delta_general->dsp_false_alarms,
max_general->dsp_false_alarms);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "beacon_rssi_a:",
+ fmt_table, "beacon_rssi_a:",
le32_to_cpu(general->beacon_rssi_a),
accum_general->beacon_rssi_a,
delta_general->beacon_rssi_a,
max_general->beacon_rssi_a);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "beacon_rssi_b:",
+ fmt_table, "beacon_rssi_b:",
le32_to_cpu(general->beacon_rssi_b),
accum_general->beacon_rssi_b,
delta_general->beacon_rssi_b,
max_general->beacon_rssi_b);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "beacon_rssi_c:",
+ fmt_table, "beacon_rssi_c:",
le32_to_cpu(general->beacon_rssi_c),
accum_general->beacon_rssi_c,
delta_general->beacon_rssi_c,
max_general->beacon_rssi_c);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "beacon_energy_a:",
+ fmt_table, "beacon_energy_a:",
le32_to_cpu(general->beacon_energy_a),
accum_general->beacon_energy_a,
delta_general->beacon_energy_a,
max_general->beacon_energy_a);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "beacon_energy_b:",
+ fmt_table, "beacon_energy_b:",
le32_to_cpu(general->beacon_energy_b),
accum_general->beacon_energy_b,
delta_general->beacon_energy_b,
max_general->beacon_energy_b);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "beacon_energy_c:",
+ fmt_table, "beacon_energy_c:",
le32_to_cpu(general->beacon_energy_c),
accum_general->beacon_energy_c,
delta_general->beacon_energy_c,
max_general->beacon_energy_c);
- pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM_HT:\n");
- pos += scnprintf(buf + pos, bufsz - pos, "%-32s current"
- "acumulative delta max\n",
- "Statistics_Rx - OFDM_HT:");
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "plcp_err:",
+ fmt_header, "Statistics_Rx - OFDM_HT:");
+ pos += scnprintf(buf + pos, bufsz - pos,
+ fmt_table, "plcp_err:",
le32_to_cpu(ht->plcp_err), accum_ht->plcp_err,
delta_ht->plcp_err, max_ht->plcp_err);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "overrun_err:",
+ fmt_table, "overrun_err:",
le32_to_cpu(ht->overrun_err), accum_ht->overrun_err,
delta_ht->overrun_err, max_ht->overrun_err);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "early_overrun_err:",
+ fmt_table, "early_overrun_err:",
le32_to_cpu(ht->early_overrun_err),
accum_ht->early_overrun_err,
delta_ht->early_overrun_err,
max_ht->early_overrun_err);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "crc32_good:",
+ fmt_table, "crc32_good:",
le32_to_cpu(ht->crc32_good), accum_ht->crc32_good,
delta_ht->crc32_good, max_ht->crc32_good);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "crc32_err:",
+ fmt_table, "crc32_err:",
le32_to_cpu(ht->crc32_err), accum_ht->crc32_err,
delta_ht->crc32_err, max_ht->crc32_err);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "mh_format_err:",
+ fmt_table, "mh_format_err:",
le32_to_cpu(ht->mh_format_err),
accum_ht->mh_format_err,
delta_ht->mh_format_err, max_ht->mh_format_err);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "agg_crc32_good:",
+ fmt_table, "agg_crc32_good:",
le32_to_cpu(ht->agg_crc32_good),
accum_ht->agg_crc32_good,
delta_ht->agg_crc32_good, max_ht->agg_crc32_good);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "agg_mpdu_cnt:",
+ fmt_table, "agg_mpdu_cnt:",
le32_to_cpu(ht->agg_mpdu_cnt),
accum_ht->agg_mpdu_cnt,
delta_ht->agg_mpdu_cnt, max_ht->agg_mpdu_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "agg_cnt:",
+ fmt_table, "agg_cnt:",
le32_to_cpu(ht->agg_cnt), accum_ht->agg_cnt,
delta_ht->agg_cnt, max_ht->agg_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "unsupport_mcs:",
+ fmt_table, "unsupport_mcs:",
le32_to_cpu(ht->unsupport_mcs),
accum_ht->unsupport_mcs,
delta_ht->unsupport_mcs, max_ht->unsupport_mcs);
@@ -584,7 +536,8 @@ ssize_t iwl_ucode_tx_stats_read(struct file *file,
* the last statistics notification from uCode
* might not reflect the current uCode activity
*/
- if (priv->cfg->bt_statistics) {
+ if (priv->cfg->bt_params &&
+ priv->cfg->bt_params->bt_statistics) {
tx = &priv->_agn.statistics_bt.tx;
accum_tx = &priv->_agn.accum_statistics_bt.tx;
delta_tx = &priv->_agn.delta_statistics_bt.tx;
@@ -597,166 +550,141 @@ ssize_t iwl_ucode_tx_stats_read(struct file *file,
}
pos += iwl_statistics_flag(priv, buf, bufsz);
- pos += scnprintf(buf + pos, bufsz - pos, "%-32s current"
- "acumulative delta max\n",
- "Statistics_Tx:");
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "preamble:",
+ fmt_header, "Statistics_Tx:");
+ pos += scnprintf(buf + pos, bufsz - pos,
+ fmt_table, "preamble:",
le32_to_cpu(tx->preamble_cnt),
accum_tx->preamble_cnt,
delta_tx->preamble_cnt, max_tx->preamble_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "rx_detected_cnt:",
+ fmt_table, "rx_detected_cnt:",
le32_to_cpu(tx->rx_detected_cnt),
accum_tx->rx_detected_cnt,
delta_tx->rx_detected_cnt, max_tx->rx_detected_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "bt_prio_defer_cnt:",
+ fmt_table, "bt_prio_defer_cnt:",
le32_to_cpu(tx->bt_prio_defer_cnt),
accum_tx->bt_prio_defer_cnt,
delta_tx->bt_prio_defer_cnt,
max_tx->bt_prio_defer_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "bt_prio_kill_cnt:",
+ fmt_table, "bt_prio_kill_cnt:",
le32_to_cpu(tx->bt_prio_kill_cnt),
accum_tx->bt_prio_kill_cnt,
delta_tx->bt_prio_kill_cnt,
max_tx->bt_prio_kill_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "few_bytes_cnt:",
+ fmt_table, "few_bytes_cnt:",
le32_to_cpu(tx->few_bytes_cnt),
accum_tx->few_bytes_cnt,
delta_tx->few_bytes_cnt, max_tx->few_bytes_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "cts_timeout:",
+ fmt_table, "cts_timeout:",
le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout,
delta_tx->cts_timeout, max_tx->cts_timeout);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "ack_timeout:",
+ fmt_table, "ack_timeout:",
le32_to_cpu(tx->ack_timeout),
accum_tx->ack_timeout,
delta_tx->ack_timeout, max_tx->ack_timeout);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "expected_ack_cnt:",
+ fmt_table, "expected_ack_cnt:",
le32_to_cpu(tx->expected_ack_cnt),
accum_tx->expected_ack_cnt,
delta_tx->expected_ack_cnt,
max_tx->expected_ack_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "actual_ack_cnt:",
+ fmt_table, "actual_ack_cnt:",
le32_to_cpu(tx->actual_ack_cnt),
accum_tx->actual_ack_cnt,
delta_tx->actual_ack_cnt,
max_tx->actual_ack_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "dump_msdu_cnt:",
+ fmt_table, "dump_msdu_cnt:",
le32_to_cpu(tx->dump_msdu_cnt),
accum_tx->dump_msdu_cnt,
delta_tx->dump_msdu_cnt,
max_tx->dump_msdu_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "abort_nxt_frame_mismatch:",
+ fmt_table, "abort_nxt_frame_mismatch:",
le32_to_cpu(tx->burst_abort_next_frame_mismatch_cnt),
accum_tx->burst_abort_next_frame_mismatch_cnt,
delta_tx->burst_abort_next_frame_mismatch_cnt,
max_tx->burst_abort_next_frame_mismatch_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "abort_missing_nxt_frame:",
+ fmt_table, "abort_missing_nxt_frame:",
le32_to_cpu(tx->burst_abort_missing_next_frame_cnt),
accum_tx->burst_abort_missing_next_frame_cnt,
delta_tx->burst_abort_missing_next_frame_cnt,
max_tx->burst_abort_missing_next_frame_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "cts_timeout_collision:",
+ fmt_table, "cts_timeout_collision:",
le32_to_cpu(tx->cts_timeout_collision),
accum_tx->cts_timeout_collision,
delta_tx->cts_timeout_collision,
max_tx->cts_timeout_collision);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "ack_ba_timeout_collision:",
+ fmt_table, "ack_ba_timeout_collision:",
le32_to_cpu(tx->ack_or_ba_timeout_collision),
accum_tx->ack_or_ba_timeout_collision,
delta_tx->ack_or_ba_timeout_collision,
max_tx->ack_or_ba_timeout_collision);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "agg ba_timeout:",
+ fmt_table, "agg ba_timeout:",
le32_to_cpu(tx->agg.ba_timeout),
accum_tx->agg.ba_timeout,
delta_tx->agg.ba_timeout,
max_tx->agg.ba_timeout);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "agg ba_resched_frames:",
+ fmt_table, "agg ba_resched_frames:",
le32_to_cpu(tx->agg.ba_reschedule_frames),
accum_tx->agg.ba_reschedule_frames,
delta_tx->agg.ba_reschedule_frames,
max_tx->agg.ba_reschedule_frames);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "agg scd_query_agg_frame:",
+ fmt_table, "agg scd_query_agg_frame:",
le32_to_cpu(tx->agg.scd_query_agg_frame_cnt),
accum_tx->agg.scd_query_agg_frame_cnt,
delta_tx->agg.scd_query_agg_frame_cnt,
max_tx->agg.scd_query_agg_frame_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "agg scd_query_no_agg:",
+ fmt_table, "agg scd_query_no_agg:",
le32_to_cpu(tx->agg.scd_query_no_agg),
accum_tx->agg.scd_query_no_agg,
delta_tx->agg.scd_query_no_agg,
max_tx->agg.scd_query_no_agg);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "agg scd_query_agg:",
+ fmt_table, "agg scd_query_agg:",
le32_to_cpu(tx->agg.scd_query_agg),
accum_tx->agg.scd_query_agg,
delta_tx->agg.scd_query_agg,
max_tx->agg.scd_query_agg);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "agg scd_query_mismatch:",
+ fmt_table, "agg scd_query_mismatch:",
le32_to_cpu(tx->agg.scd_query_mismatch),
accum_tx->agg.scd_query_mismatch,
delta_tx->agg.scd_query_mismatch,
max_tx->agg.scd_query_mismatch);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "agg frame_not_ready:",
+ fmt_table, "agg frame_not_ready:",
le32_to_cpu(tx->agg.frame_not_ready),
accum_tx->agg.frame_not_ready,
delta_tx->agg.frame_not_ready,
max_tx->agg.frame_not_ready);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "agg underrun:",
+ fmt_table, "agg underrun:",
le32_to_cpu(tx->agg.underrun),
accum_tx->agg.underrun,
delta_tx->agg.underrun, max_tx->agg.underrun);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "agg bt_prio_kill:",
+ fmt_table, "agg bt_prio_kill:",
le32_to_cpu(tx->agg.bt_prio_kill),
accum_tx->agg.bt_prio_kill,
delta_tx->agg.bt_prio_kill,
max_tx->agg.bt_prio_kill);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "agg rx_ba_rsp_cnt:",
+ fmt_table, "agg rx_ba_rsp_cnt:",
le32_to_cpu(tx->agg.rx_ba_rsp_cnt),
accum_tx->agg.rx_ba_rsp_cnt,
delta_tx->agg.rx_ba_rsp_cnt,
@@ -767,15 +695,15 @@ ssize_t iwl_ucode_tx_stats_read(struct file *file,
"tx power: (1/2 dB step)\n");
if ((priv->cfg->valid_tx_ant & ANT_A) && tx->tx_power.ant_a)
pos += scnprintf(buf + pos, bufsz - pos,
- "\tantenna A: 0x%X\n",
+ fmt_hex, "antenna A:",
tx->tx_power.ant_a);
if ((priv->cfg->valid_tx_ant & ANT_B) && tx->tx_power.ant_b)
pos += scnprintf(buf + pos, bufsz - pos,
- "\tantenna B: 0x%X\n",
+ fmt_hex, "antenna B:",
tx->tx_power.ant_b);
if ((priv->cfg->valid_tx_ant & ANT_C) && tx->tx_power.ant_c)
pos += scnprintf(buf + pos, bufsz - pos,
- "\tantenna C: 0x%X\n",
+ fmt_hex, "antenna C:",
tx->tx_power.ant_c);
}
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
@@ -809,7 +737,8 @@ ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf,
* the last statistics notification from uCode
* might not reflect the current uCode activity
*/
- if (priv->cfg->bt_statistics) {
+ if (priv->cfg->bt_params &&
+ priv->cfg->bt_params->bt_statistics) {
general = &priv->_agn.statistics_bt.general.common;
dbg = &priv->_agn.statistics_bt.general.common.dbg;
div = &priv->_agn.statistics_bt.general.common.div;
@@ -838,84 +767,72 @@ ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf,
}
pos += iwl_statistics_flag(priv, buf, bufsz);
- pos += scnprintf(buf + pos, bufsz - pos, "%-32s current"
- "acumulative delta max\n",
- "Statistics_General:");
- pos += scnprintf(buf + pos, bufsz - pos, " %-30s %10u\n",
- "temperature:",
+ pos += scnprintf(buf + pos, bufsz - pos,
+ fmt_header, "Statistics_General:");
+ pos += scnprintf(buf + pos, bufsz - pos,
+ fmt_value, "temperature:",
le32_to_cpu(general->temperature));
- pos += scnprintf(buf + pos, bufsz - pos, " %-30s %10u\n",
- "temperature_m:",
+ pos += scnprintf(buf + pos, bufsz - pos,
+ fmt_value, "temperature_m:",
le32_to_cpu(general->temperature_m));
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "burst_check:",
+ fmt_value, "ttl_timestamp:",
+ le32_to_cpu(general->ttl_timestamp));
+ pos += scnprintf(buf + pos, bufsz - pos,
+ fmt_table, "burst_check:",
le32_to_cpu(dbg->burst_check),
accum_dbg->burst_check,
delta_dbg->burst_check, max_dbg->burst_check);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "burst_count:",
+ fmt_table, "burst_count:",
le32_to_cpu(dbg->burst_count),
accum_dbg->burst_count,
delta_dbg->burst_count, max_dbg->burst_count);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "wait_for_silence_timeout_count:",
+ fmt_table, "wait_for_silence_timeout_count:",
le32_to_cpu(dbg->wait_for_silence_timeout_cnt),
accum_dbg->wait_for_silence_timeout_cnt,
delta_dbg->wait_for_silence_timeout_cnt,
max_dbg->wait_for_silence_timeout_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "sleep_time:",
+ fmt_table, "sleep_time:",
le32_to_cpu(general->sleep_time),
accum_general->sleep_time,
delta_general->sleep_time, max_general->sleep_time);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "slots_out:",
+ fmt_table, "slots_out:",
le32_to_cpu(general->slots_out),
accum_general->slots_out,
delta_general->slots_out, max_general->slots_out);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "slots_idle:",
+ fmt_table, "slots_idle:",
le32_to_cpu(general->slots_idle),
accum_general->slots_idle,
delta_general->slots_idle, max_general->slots_idle);
- pos += scnprintf(buf + pos, bufsz - pos, "ttl_timestamp:\t\t\t%u\n",
- le32_to_cpu(general->ttl_timestamp));
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "tx_on_a:",
+ fmt_table, "tx_on_a:",
le32_to_cpu(div->tx_on_a), accum_div->tx_on_a,
delta_div->tx_on_a, max_div->tx_on_a);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "tx_on_b:",
+ fmt_table, "tx_on_b:",
le32_to_cpu(div->tx_on_b), accum_div->tx_on_b,
delta_div->tx_on_b, max_div->tx_on_b);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "exec_time:",
+ fmt_table, "exec_time:",
le32_to_cpu(div->exec_time), accum_div->exec_time,
delta_div->exec_time, max_div->exec_time);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "probe_time:",
+ fmt_table, "probe_time:",
le32_to_cpu(div->probe_time), accum_div->probe_time,
delta_div->probe_time, max_div->probe_time);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "rx_enable_counter:",
+ fmt_table, "rx_enable_counter:",
le32_to_cpu(general->rx_enable_counter),
accum_general->rx_enable_counter,
delta_general->rx_enable_counter,
max_general->rx_enable_counter);
pos += scnprintf(buf + pos, bufsz - pos,
- " %-30s %10u %10u %10u %10u\n",
- "num_of_sos_states:",
+ fmt_table, "num_of_sos_states:",
le32_to_cpu(general->num_of_sos_states),
accum_general->num_of_sos_states,
delta_general->num_of_sos_states,
@@ -1011,3 +928,147 @@ ssize_t iwl_ucode_bt_stats_read(struct file *file,
kfree(buf);
return ret;
}
+
+ssize_t iwl_reply_tx_error_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
+ int pos = 0;
+ char *buf;
+ int bufsz = (sizeof(struct reply_tx_error_statistics) * 24) +
+ (sizeof(struct reply_agg_tx_error_statistics) * 24) + 200;
+ ssize_t ret;
+
+ if (!iwl_is_alive(priv))
+ return -EAGAIN;
+
+ buf = kzalloc(bufsz, GFP_KERNEL);
+ if (!buf) {
+ IWL_ERR(priv, "Can not allocate Buffer\n");
+ return -ENOMEM;
+ }
+
+ pos += scnprintf(buf + pos, bufsz - pos, "Statistics_TX_Error:\n");
+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t\t%u\n",
+ iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_DELAY),
+ priv->_agn.reply_tx_stats.pp_delay);
+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+ iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_FEW_BYTES),
+ priv->_agn.reply_tx_stats.pp_few_bytes);
+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+ iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_BT_PRIO),
+ priv->_agn.reply_tx_stats.pp_bt_prio);
+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+ iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_QUIET_PERIOD),
+ priv->_agn.reply_tx_stats.pp_quiet_period);
+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+ iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_CALC_TTAK),
+ priv->_agn.reply_tx_stats.pp_calc_ttak);
+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",
+ iwl_get_tx_fail_reason(
+ TX_STATUS_FAIL_INTERNAL_CROSSED_RETRY),
+ priv->_agn.reply_tx_stats.int_crossed_retry);
+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+ iwl_get_tx_fail_reason(TX_STATUS_FAIL_SHORT_LIMIT),
+ priv->_agn.reply_tx_stats.short_limit);
+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+ iwl_get_tx_fail_reason(TX_STATUS_FAIL_LONG_LIMIT),
+ priv->_agn.reply_tx_stats.long_limit);
+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+ iwl_get_tx_fail_reason(TX_STATUS_FAIL_FIFO_UNDERRUN),
+ priv->_agn.reply_tx_stats.fifo_underrun);
+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+ iwl_get_tx_fail_reason(TX_STATUS_FAIL_DRAIN_FLOW),
+ priv->_agn.reply_tx_stats.drain_flow);
+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+ iwl_get_tx_fail_reason(TX_STATUS_FAIL_RFKILL_FLUSH),
+ priv->_agn.reply_tx_stats.rfkill_flush);
+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+ iwl_get_tx_fail_reason(TX_STATUS_FAIL_LIFE_EXPIRE),
+ priv->_agn.reply_tx_stats.life_expire);
+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+ iwl_get_tx_fail_reason(TX_STATUS_FAIL_DEST_PS),
+ priv->_agn.reply_tx_stats.dest_ps);
+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+ iwl_get_tx_fail_reason(TX_STATUS_FAIL_HOST_ABORTED),
+ priv->_agn.reply_tx_stats.host_abort);
+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+ iwl_get_tx_fail_reason(TX_STATUS_FAIL_BT_RETRY),
+ priv->_agn.reply_tx_stats.pp_delay);
+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+ iwl_get_tx_fail_reason(TX_STATUS_FAIL_STA_INVALID),
+ priv->_agn.reply_tx_stats.sta_invalid);
+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+ iwl_get_tx_fail_reason(TX_STATUS_FAIL_FRAG_DROPPED),
+ priv->_agn.reply_tx_stats.frag_drop);
+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+ iwl_get_tx_fail_reason(TX_STATUS_FAIL_TID_DISABLE),
+ priv->_agn.reply_tx_stats.tid_disable);
+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+ iwl_get_tx_fail_reason(TX_STATUS_FAIL_FIFO_FLUSHED),
+ priv->_agn.reply_tx_stats.fifo_flush);
+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",
+ iwl_get_tx_fail_reason(
+ TX_STATUS_FAIL_INSUFFICIENT_CF_POLL),
+ priv->_agn.reply_tx_stats.insuff_cf_poll);
+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+ iwl_get_tx_fail_reason(TX_STATUS_FAIL_PASSIVE_NO_RX),
+ priv->_agn.reply_tx_stats.fail_hw_drop);
+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",
+ iwl_get_tx_fail_reason(
+ TX_STATUS_FAIL_NO_BEACON_ON_RADAR),
+ priv->_agn.reply_tx_stats.sta_color_mismatch);
+ pos += scnprintf(buf + pos, bufsz - pos, "UNKNOWN:\t\t\t%u\n",
+ priv->_agn.reply_tx_stats.unknown);
+
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "\nStatistics_Agg_TX_Error:\n");
+
+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+ iwl_get_agg_tx_fail_reason(AGG_TX_STATE_UNDERRUN_MSK),
+ priv->_agn.reply_agg_tx_stats.underrun);
+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+ iwl_get_agg_tx_fail_reason(AGG_TX_STATE_BT_PRIO_MSK),
+ priv->_agn.reply_agg_tx_stats.bt_prio);
+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+ iwl_get_agg_tx_fail_reason(AGG_TX_STATE_FEW_BYTES_MSK),
+ priv->_agn.reply_agg_tx_stats.few_bytes);
+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+ iwl_get_agg_tx_fail_reason(AGG_TX_STATE_ABORT_MSK),
+ priv->_agn.reply_agg_tx_stats.abort);
+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",
+ iwl_get_agg_tx_fail_reason(
+ AGG_TX_STATE_LAST_SENT_TTL_MSK),
+ priv->_agn.reply_agg_tx_stats.last_sent_ttl);
+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",
+ iwl_get_agg_tx_fail_reason(
+ AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK),
+ priv->_agn.reply_agg_tx_stats.last_sent_try);
+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",
+ iwl_get_agg_tx_fail_reason(
+ AGG_TX_STATE_LAST_SENT_BT_KILL_MSK),
+ priv->_agn.reply_agg_tx_stats.last_sent_bt_kill);
+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+ iwl_get_agg_tx_fail_reason(AGG_TX_STATE_SCD_QUERY_MSK),
+ priv->_agn.reply_agg_tx_stats.scd_query);
+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",
+ iwl_get_agg_tx_fail_reason(
+ AGG_TX_STATE_TEST_BAD_CRC32_MSK),
+ priv->_agn.reply_agg_tx_stats.bad_crc32);
+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+ iwl_get_agg_tx_fail_reason(AGG_TX_STATE_RESPONSE_MSK),
+ priv->_agn.reply_agg_tx_stats.response);
+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+ iwl_get_agg_tx_fail_reason(AGG_TX_STATE_DUMP_TX_MSK),
+ priv->_agn.reply_agg_tx_stats.dump_tx);
+ pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+ iwl_get_agg_tx_fail_reason(AGG_TX_STATE_DELAY_TX_MSK),
+ priv->_agn.reply_agg_tx_stats.delay_tx);
+ pos += scnprintf(buf + pos, bufsz - pos, "UNKNOWN:\t\t\t%u\n",
+ priv->_agn.reply_agg_tx_stats.unknown);
+
+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+ kfree(buf);
+ return ret;
+}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h
index bbdce5913ac7..f2573b5486cd 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h
@@ -39,6 +39,8 @@ ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos);
ssize_t iwl_ucode_bt_stats_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos);
+ssize_t iwl_reply_tx_error_read(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos);
#else
static ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
@@ -60,4 +62,9 @@ static ssize_t iwl_ucode_bt_stats_read(struct file *file, char __user *user_buf,
{
return 0;
}
+static ssize_t iwl_reply_tx_error_read(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ return 0;
+}
#endif
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c
new file mode 100644
index 000000000000..a650baba0809
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c
@@ -0,0 +1,454 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ * Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+
+#include <net/mac80211.h>
+
+#include "iwl-commands.h"
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-debug.h"
+#include "iwl-agn.h"
+#include "iwl-io.h"
+
+/************************** EEPROM BANDS ****************************
+ *
+ * The iwl_eeprom_band definitions below provide the mapping from the
+ * EEPROM contents to the specific channel number supported for each
+ * band.
+ *
+ * For example, iwl_priv->eeprom.band_3_channels[4] from the band_3
+ * definition below maps to physical channel 42 in the 5.2GHz spectrum.
+ * The specific geography and calibration information for that channel
+ * is contained in the eeprom map itself.
+ *
+ * During init, we copy the eeprom information and channel map
+ * information into priv->channel_info_24/52 and priv->channel_map_24/52
+ *
+ * channel_map_24/52 provides the index in the channel_info array for a
+ * given channel. We have to have two separate maps as there is channel
+ * overlap with the 2.4GHz and 5.2GHz spectrum as seen in band_1 and
+ * band_2
+ *
+ * A value of 0xff stored in the channel_map indicates that the channel
+ * is not supported by the hardware at all.
+ *
+ * A value of 0xfe in the channel_map indicates that the channel is not
+ * valid for Tx with the current hardware. This means that
+ * while the system can tune and receive on a given channel, it may not
+ * be able to associate or transmit any frames on that
+ * channel. There is no corresponding channel information for that
+ * entry.
+ *
+ *********************************************************************/
+
+/**
+ * struct iwl_txpwr_section: eeprom section information
+ * @offset: indirect address into eeprom image
+ * @count: number of "struct iwl_eeprom_enhanced_txpwr" in this section
+ * @band: band type for the section
+ * @is_common - true: common section, false: channel section
+ * @is_cck - true: cck section, false: not cck section
+ * @is_ht_40 - true: all channel in the section are HT40 channel,
+ * false: legacy or HT 20 MHz
+ * ignore if it is common section
+ * @iwl_eeprom_section_channel: channel array in the section,
+ * ignore if common section
+ */
+struct iwl_txpwr_section {
+ u32 offset;
+ u8 count;
+ enum ieee80211_band band;
+ bool is_common;
+ bool is_cck;
+ bool is_ht40;
+ u8 iwl_eeprom_section_channel[EEPROM_MAX_TXPOWER_SECTION_ELEMENTS];
+};
+
+/**
+ * section 1 - 3 are regulatory tx power apply to all channels based on
+ * modulation: CCK, OFDM
+ * Band: 2.4GHz, 5.2GHz
+ * section 4 - 10 are regulatory tx power apply to specified channels
+ * For example:
+ * 1L - Channel 1 Legacy
+ * 1HT - Channel 1 HT
+ * (1,+1) - Channel 1 HT40 "_above_"
+ *
+ * Section 1: all CCK channels
+ * Section 2: all 2.4 GHz OFDM (Legacy, HT and HT40) channels
+ * Section 3: all 5.2 GHz OFDM (Legacy, HT and HT40) channels
+ * Section 4: 2.4 GHz 20MHz channels: 1L, 1HT, 2L, 2HT, 10L, 10HT, 11L, 11HT
+ * Section 5: 2.4 GHz 40MHz channels: (1,+1) (2,+1) (6,+1) (7,+1) (9,+1)
+ * Section 6: 5.2 GHz 20MHz channels: 36L, 64L, 100L, 36HT, 64HT, 100HT
+ * Section 7: 5.2 GHz 40MHz channels: (36,+1) (60,+1) (100,+1)
+ * Section 8: 2.4 GHz channel: 13L, 13HT
+ * Section 9: 2.4 GHz channel: 140L, 140HT
+ * Section 10: 2.4 GHz 40MHz channels: (132,+1) (44,+1)
+ *
+ */
+static const struct iwl_txpwr_section enhinfo[] = {
+ { EEPROM_LB_CCK_20_COMMON, 1, IEEE80211_BAND_2GHZ, true, true, false },
+ { EEPROM_LB_OFDM_COMMON, 3, IEEE80211_BAND_2GHZ, true, false, false },
+ { EEPROM_HB_OFDM_COMMON, 3, IEEE80211_BAND_5GHZ, true, false, false },
+ { EEPROM_LB_OFDM_20_BAND, 8, IEEE80211_BAND_2GHZ,
+ false, false, false,
+ {1, 1, 2, 2, 10, 10, 11, 11 } },
+ { EEPROM_LB_OFDM_HT40_BAND, 5, IEEE80211_BAND_2GHZ,
+ false, false, true,
+ { 1, 2, 6, 7, 9 } },
+ { EEPROM_HB_OFDM_20_BAND, 6, IEEE80211_BAND_5GHZ,
+ false, false, false,
+ { 36, 64, 100, 36, 64, 100 } },
+ { EEPROM_HB_OFDM_HT40_BAND, 3, IEEE80211_BAND_5GHZ,
+ false, false, true,
+ { 36, 60, 100 } },
+ { EEPROM_LB_OFDM_20_CHANNEL_13, 2, IEEE80211_BAND_2GHZ,
+ false, false, false,
+ { 13, 13 } },
+ { EEPROM_HB_OFDM_20_CHANNEL_140, 2, IEEE80211_BAND_5GHZ,
+ false, false, false,
+ { 140, 140 } },
+ { EEPROM_HB_OFDM_HT40_BAND_1, 2, IEEE80211_BAND_5GHZ,
+ false, false, true,
+ { 132, 44 } },
+};
+
+/******************************************************************************
+ *
+ * EEPROM related functions
+ *
+******************************************************************************/
+
+/*
+ * The device's EEPROM semaphore prevents conflicts between driver and uCode
+ * when accessing the EEPROM; each access is a series of pulses to/from the
+ * EEPROM chip, not a single event, so even reads could conflict if they
+ * weren't arbitrated by the semaphore.
+ */
+int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv)
+{
+ u16 count;
+ int ret;
+
+ for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) {
+ /* Request semaphore */
+ iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+ CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
+
+ /* See if we got it */
+ ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG,
+ CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
+ CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
+ EEPROM_SEM_TIMEOUT);
+ if (ret >= 0) {
+ IWL_DEBUG_IO(priv,
+ "Acquired semaphore after %d tries.\n",
+ count+1);
+ return ret;
+ }
+ }
+
+ return ret;
+}
+
+void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv)
+{
+ iwl_clear_bit(priv, CSR_HW_IF_CONFIG_REG,
+ CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
+
+}
+
+int iwl_eeprom_check_version(struct iwl_priv *priv)
+{
+ u16 eeprom_ver;
+ u16 calib_ver;
+
+ eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION);
+ calib_ver = priv->cfg->ops->lib->eeprom_ops.calib_version(priv);
+
+ if (eeprom_ver < priv->cfg->eeprom_ver ||
+ calib_ver < priv->cfg->eeprom_calib_ver)
+ goto err;
+
+ IWL_INFO(priv, "device EEPROM VER=0x%x, CALIB=0x%x\n",
+ eeprom_ver, calib_ver);
+
+ return 0;
+err:
+ IWL_ERR(priv, "Unsupported (too old) EEPROM VER=0x%x < 0x%x "
+ "CALIB=0x%x < 0x%x\n",
+ eeprom_ver, priv->cfg->eeprom_ver,
+ calib_ver, priv->cfg->eeprom_calib_ver);
+ return -EINVAL;
+
+}
+
+void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac)
+{
+ const u8 *addr = priv->cfg->ops->lib->eeprom_ops.query_addr(priv,
+ EEPROM_MAC_ADDRESS);
+ memcpy(mac, addr, ETH_ALEN);
+}
+
+/**
+ * iwl_get_max_txpower_avg - get the highest tx power from all chains.
+ * find the highest tx power from all chains for the channel
+ */
+static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv,
+ struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
+ int element, s8 *max_txpower_in_half_dbm)
+{
+ s8 max_txpower_avg = 0; /* (dBm) */
+
+ IWL_DEBUG_INFO(priv, "%d - "
+ "chain_a: %d dB chain_b: %d dB "
+ "chain_c: %d dB mimo2: %d dB mimo3: %d dB\n",
+ element,
+ enhanced_txpower[element].chain_a_max >> 1,
+ enhanced_txpower[element].chain_b_max >> 1,
+ enhanced_txpower[element].chain_c_max >> 1,
+ enhanced_txpower[element].mimo2_max >> 1,
+ enhanced_txpower[element].mimo3_max >> 1);
+ /* Take the highest tx power from any valid chains */
+ if ((priv->cfg->valid_tx_ant & ANT_A) &&
+ (enhanced_txpower[element].chain_a_max > max_txpower_avg))
+ max_txpower_avg = enhanced_txpower[element].chain_a_max;
+ if ((priv->cfg->valid_tx_ant & ANT_B) &&
+ (enhanced_txpower[element].chain_b_max > max_txpower_avg))
+ max_txpower_avg = enhanced_txpower[element].chain_b_max;
+ if ((priv->cfg->valid_tx_ant & ANT_C) &&
+ (enhanced_txpower[element].chain_c_max > max_txpower_avg))
+ max_txpower_avg = enhanced_txpower[element].chain_c_max;
+ if (((priv->cfg->valid_tx_ant == ANT_AB) |
+ (priv->cfg->valid_tx_ant == ANT_BC) |
+ (priv->cfg->valid_tx_ant == ANT_AC)) &&
+ (enhanced_txpower[element].mimo2_max > max_txpower_avg))
+ max_txpower_avg = enhanced_txpower[element].mimo2_max;
+ if ((priv->cfg->valid_tx_ant == ANT_ABC) &&
+ (enhanced_txpower[element].mimo3_max > max_txpower_avg))
+ max_txpower_avg = enhanced_txpower[element].mimo3_max;
+
+ /*
+ * max. tx power in EEPROM is in 1/2 dBm format
+ * convert from 1/2 dBm to dBm (round-up convert)
+ * but we also do not want to loss 1/2 dBm resolution which
+ * will impact performance
+ */
+ *max_txpower_in_half_dbm = max_txpower_avg;
+ return (max_txpower_avg & 0x01) + (max_txpower_avg >> 1);
+}
+
+/**
+ * iwl_update_common_txpower: update channel tx power
+ * update tx power per band based on EEPROM enhanced tx power info.
+ */
+static s8 iwl_update_common_txpower(struct iwl_priv *priv,
+ struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
+ int section, int element, s8 *max_txpower_in_half_dbm)
+{
+ struct iwl_channel_info *ch_info;
+ int ch;
+ bool is_ht40 = false;
+ s8 max_txpower_avg; /* (dBm) */
+
+ /* it is common section, contain all type (Legacy, HT and HT40)
+ * based on the element in the section to determine
+ * is it HT 40 or not
+ */
+ if (element == EEPROM_TXPOWER_COMMON_HT40_INDEX)
+ is_ht40 = true;
+ max_txpower_avg =
+ iwl_get_max_txpower_avg(priv, enhanced_txpower,
+ element, max_txpower_in_half_dbm);
+
+ ch_info = priv->channel_info;
+
+ for (ch = 0; ch < priv->channel_count; ch++) {
+ /* find matching band and update tx power if needed */
+ if ((ch_info->band == enhinfo[section].band) &&
+ (ch_info->max_power_avg < max_txpower_avg) &&
+ (!is_ht40)) {
+ /* Update regulatory-based run-time data */
+ ch_info->max_power_avg = ch_info->curr_txpow =
+ max_txpower_avg;
+ ch_info->scan_power = max_txpower_avg;
+ }
+ if ((ch_info->band == enhinfo[section].band) && is_ht40 &&
+ (ch_info->ht40_max_power_avg < max_txpower_avg)) {
+ /* Update regulatory-based run-time data */
+ ch_info->ht40_max_power_avg = max_txpower_avg;
+ }
+ ch_info++;
+ }
+ return max_txpower_avg;
+}
+
+/**
+ * iwl_update_channel_txpower: update channel tx power
+ * update channel tx power based on EEPROM enhanced tx power info.
+ */
+static s8 iwl_update_channel_txpower(struct iwl_priv *priv,
+ struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
+ int section, int element, s8 *max_txpower_in_half_dbm)
+{
+ struct iwl_channel_info *ch_info;
+ int ch;
+ u8 channel;
+ s8 max_txpower_avg; /* (dBm) */
+
+ channel = enhinfo[section].iwl_eeprom_section_channel[element];
+ max_txpower_avg =
+ iwl_get_max_txpower_avg(priv, enhanced_txpower,
+ element, max_txpower_in_half_dbm);
+
+ ch_info = priv->channel_info;
+ for (ch = 0; ch < priv->channel_count; ch++) {
+ /* find matching channel and update tx power if needed */
+ if (ch_info->channel == channel) {
+ if ((ch_info->max_power_avg < max_txpower_avg) &&
+ (!enhinfo[section].is_ht40)) {
+ /* Update regulatory-based run-time data */
+ ch_info->max_power_avg = max_txpower_avg;
+ ch_info->curr_txpow = max_txpower_avg;
+ ch_info->scan_power = max_txpower_avg;
+ }
+ if ((enhinfo[section].is_ht40) &&
+ (ch_info->ht40_max_power_avg < max_txpower_avg)) {
+ /* Update regulatory-based run-time data */
+ ch_info->ht40_max_power_avg = max_txpower_avg;
+ }
+ break;
+ }
+ ch_info++;
+ }
+ return max_txpower_avg;
+}
+
+/**
+ * iwlcore_eeprom_enhanced_txpower: process enhanced tx power info
+ */
+void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv)
+{
+ int eeprom_section_count = 0;
+ int section, element;
+ struct iwl_eeprom_enhanced_txpwr *enhanced_txpower;
+ u32 offset;
+ s8 max_txpower_avg; /* (dBm) */
+ s8 max_txpower_in_half_dbm; /* (half-dBm) */
+
+ /* Loop through all the sections
+ * adjust bands and channel's max tx power
+ * Set the tx_power_user_lmt to the highest power
+ * supported by any channels and chains
+ */
+ for (section = 0; section < ARRAY_SIZE(enhinfo); section++) {
+ eeprom_section_count = enhinfo[section].count;
+ offset = enhinfo[section].offset;
+ enhanced_txpower = (struct iwl_eeprom_enhanced_txpwr *)
+ iwl_eeprom_query_addr(priv, offset);
+
+ /*
+ * check for valid entry -
+ * different version of EEPROM might contain different set
+ * of enhanced tx power table
+ * always check for valid entry before process
+ * the information
+ */
+ if (!enhanced_txpower->common || enhanced_txpower->reserved)
+ continue;
+
+ for (element = 0; element < eeprom_section_count; element++) {
+ if (enhinfo[section].is_common)
+ max_txpower_avg =
+ iwl_update_common_txpower(priv,
+ enhanced_txpower, section,
+ element,
+ &max_txpower_in_half_dbm);
+ else
+ max_txpower_avg =
+ iwl_update_channel_txpower(priv,
+ enhanced_txpower, section,
+ element,
+ &max_txpower_in_half_dbm);
+
+ /* Update the tx_power_user_lmt to the highest power
+ * supported by any channel */
+ if (max_txpower_avg > priv->tx_power_user_lmt)
+ priv->tx_power_user_lmt = max_txpower_avg;
+
+ /*
+ * Update the tx_power_lmt_in_half_dbm to
+ * the highest power supported by any channel
+ */
+ if (max_txpower_in_half_dbm >
+ priv->tx_power_lmt_in_half_dbm)
+ priv->tx_power_lmt_in_half_dbm =
+ max_txpower_in_half_dbm;
+ }
+ }
+}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
index 75b901b3eb1e..ffb2f4111ad0 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
@@ -37,12 +37,13 @@
#include "iwl-io.h"
#include "iwl-agn.h"
-int iwlagn_send_rxon_assoc(struct iwl_priv *priv)
+int iwlagn_send_rxon_assoc(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx)
{
int ret = 0;
struct iwl5000_rxon_assoc_cmd rxon_assoc;
- const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon;
- const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon;
+ const struct iwl_rxon_cmd *rxon1 = &ctx->staging;
+ const struct iwl_rxon_cmd *rxon2 = &ctx->active;
if ((rxon1->flags == rxon2->flags) &&
(rxon1->filter_flags == rxon2->filter_flags) &&
@@ -60,23 +61,23 @@ int iwlagn_send_rxon_assoc(struct iwl_priv *priv)
return 0;
}
- rxon_assoc.flags = priv->staging_rxon.flags;
- rxon_assoc.filter_flags = priv->staging_rxon.filter_flags;
- rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates;
- rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates;
+ rxon_assoc.flags = ctx->staging.flags;
+ rxon_assoc.filter_flags = ctx->staging.filter_flags;
+ rxon_assoc.ofdm_basic_rates = ctx->staging.ofdm_basic_rates;
+ rxon_assoc.cck_basic_rates = ctx->staging.cck_basic_rates;
rxon_assoc.reserved1 = 0;
rxon_assoc.reserved2 = 0;
rxon_assoc.reserved3 = 0;
rxon_assoc.ofdm_ht_single_stream_basic_rates =
- priv->staging_rxon.ofdm_ht_single_stream_basic_rates;
+ ctx->staging.ofdm_ht_single_stream_basic_rates;
rxon_assoc.ofdm_ht_dual_stream_basic_rates =
- priv->staging_rxon.ofdm_ht_dual_stream_basic_rates;
- rxon_assoc.rx_chain_select_flags = priv->staging_rxon.rx_chain;
+ ctx->staging.ofdm_ht_dual_stream_basic_rates;
+ rxon_assoc.rx_chain_select_flags = ctx->staging.rx_chain;
rxon_assoc.ofdm_ht_triple_stream_basic_rates =
- priv->staging_rxon.ofdm_ht_triple_stream_basic_rates;
- rxon_assoc.acquisition_data = priv->staging_rxon.acquisition_data;
+ ctx->staging.ofdm_ht_triple_stream_basic_rates;
+ rxon_assoc.acquisition_data = ctx->staging.acquisition_data;
- ret = iwl_send_cmd_pdu_async(priv, REPLY_RXON_ASSOC,
+ ret = iwl_send_cmd_pdu_async(priv, ctx->rxon_assoc_cmd,
sizeof(rxon_assoc), &rxon_assoc, NULL);
if (ret)
return ret;
@@ -136,7 +137,7 @@ static void iwlagn_gain_computation(struct iwl_priv *priv,
continue;
}
- delta_g = (priv->cfg->chain_noise_scale *
+ delta_g = (priv->cfg->base_params->chain_noise_scale *
((s32)average_noise[default_chain] -
(s32)average_noise[i])) / 1500;
@@ -184,7 +185,7 @@ static void iwlagn_chain_noise_reset(struct iwl_priv *priv)
int ret;
if ((data->state == IWL_CHAIN_NOISE_ALIVE) &&
- iwl_is_associated(priv)) {
+ iwl_is_any_associated(priv)) {
struct iwl_calib_chain_noise_reset_cmd cmd;
/* clear data for chain noise calibration algorithm */
@@ -221,7 +222,8 @@ static void iwlagn_tx_cmd_protection(struct iwl_priv *priv,
return;
}
- if (priv->cfg->use_rts_for_aggregation &&
+ if (priv->cfg->ht_params &&
+ priv->cfg->ht_params->use_rts_for_aggregation &&
info->flags & IEEE80211_TX_CTL_AMPDU) {
*tx_flags |= TX_CMD_FLG_PROT_REQUIRE_MSK;
return;
@@ -235,13 +237,13 @@ static int iwlagn_calc_rssi(struct iwl_priv *priv,
/* data from PHY/DSP regarding signal strength, etc.,
* contents are always there, not configurable by host
*/
- struct iwl5000_non_cfg_phy *ncphy =
- (struct iwl5000_non_cfg_phy *)rx_resp->non_cfg_phy_buf;
+ struct iwlagn_non_cfg_phy *ncphy =
+ (struct iwlagn_non_cfg_phy *)rx_resp->non_cfg_phy_buf;
u32 val, rssi_a, rssi_b, rssi_c, max_rssi;
u8 agc;
- val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_AGC_IDX]);
- agc = (val & IWL50_OFDM_AGC_MSK) >> IWL50_OFDM_AGC_BIT_POS;
+ val = le32_to_cpu(ncphy->non_cfg_phy[IWLAGN_RX_RES_AGC_IDX]);
+ agc = (val & IWLAGN_OFDM_AGC_MSK) >> IWLAGN_OFDM_AGC_BIT_POS;
/* Find max rssi among 3 possible receivers.
* These values are measured by the digital signal processor (DSP).
@@ -249,11 +251,14 @@ static int iwlagn_calc_rssi(struct iwl_priv *priv,
* if the radio's automatic gain control (AGC) is working right.
* AGC value (see below) will provide the "interesting" info.
*/
- val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_RSSI_AB_IDX]);
- rssi_a = (val & IWL50_OFDM_RSSI_A_MSK) >> IWL50_OFDM_RSSI_A_BIT_POS;
- rssi_b = (val & IWL50_OFDM_RSSI_B_MSK) >> IWL50_OFDM_RSSI_B_BIT_POS;
- val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_RSSI_C_IDX]);
- rssi_c = (val & IWL50_OFDM_RSSI_C_MSK) >> IWL50_OFDM_RSSI_C_BIT_POS;
+ val = le32_to_cpu(ncphy->non_cfg_phy[IWLAGN_RX_RES_RSSI_AB_IDX]);
+ rssi_a = (val & IWLAGN_OFDM_RSSI_INBAND_A_BITMSK) >>
+ IWLAGN_OFDM_RSSI_A_BIT_POS;
+ rssi_b = (val & IWLAGN_OFDM_RSSI_INBAND_B_BITMSK) >>
+ IWLAGN_OFDM_RSSI_B_BIT_POS;
+ val = le32_to_cpu(ncphy->non_cfg_phy[IWLAGN_RX_RES_RSSI_C_IDX]);
+ rssi_c = (val & IWLAGN_OFDM_RSSI_INBAND_C_BITMSK) >>
+ IWLAGN_OFDM_RSSI_C_BIT_POS;
max_rssi = max_t(u32, rssi_a, rssi_b);
max_rssi = max_t(u32, max_rssi, rssi_c);
@@ -266,12 +271,109 @@ static int iwlagn_calc_rssi(struct iwl_priv *priv,
return max_rssi - agc - IWLAGN_RSSI_OFFSET;
}
+static int iwlagn_set_pan_params(struct iwl_priv *priv)
+{
+ struct iwl_wipan_params_cmd cmd;
+ struct iwl_rxon_context *ctx_bss, *ctx_pan;
+ int slot0 = 300, slot1 = 0;
+ int ret;
+
+ if (priv->valid_contexts == BIT(IWL_RXON_CTX_BSS))
+ return 0;
+
+ BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
+
+ lockdep_assert_held(&priv->mutex);
+
+ ctx_bss = &priv->contexts[IWL_RXON_CTX_BSS];
+ ctx_pan = &priv->contexts[IWL_RXON_CTX_PAN];
+
+ /*
+ * If the PAN context is inactive, then we don't need
+ * to update the PAN parameters, the last thing we'll
+ * have done before it goes inactive is making the PAN
+ * parameters be WLAN-only.
+ */
+ if (!ctx_pan->is_active)
+ return 0;
+
+ memset(&cmd, 0, sizeof(cmd));
+
+ /* only 2 slots are currently allowed */
+ cmd.num_slots = 2;
+
+ cmd.slots[0].type = 0; /* BSS */
+ cmd.slots[1].type = 1; /* PAN */
+
+ if (ctx_bss->vif && ctx_pan->vif) {
+ int bcnint = ctx_pan->vif->bss_conf.beacon_int;
+
+ /* should be set, but seems unused?? */
+ cmd.flags |= cpu_to_le16(IWL_WIPAN_PARAMS_FLG_SLOTTED_MODE);
+
+ if (ctx_pan->vif->type == NL80211_IFTYPE_AP &&
+ bcnint &&
+ bcnint != ctx_bss->vif->bss_conf.beacon_int) {
+ IWL_ERR(priv,
+ "beacon intervals don't match (%d, %d)\n",
+ ctx_bss->vif->bss_conf.beacon_int,
+ ctx_pan->vif->bss_conf.beacon_int);
+ } else
+ bcnint = max_t(int, bcnint,
+ ctx_bss->vif->bss_conf.beacon_int);
+ if (!bcnint)
+ bcnint = DEFAULT_BEACON_INTERVAL;
+ slot0 = bcnint / 2;
+ slot1 = bcnint - slot0;
+
+ if (test_bit(STATUS_SCAN_HW, &priv->status) ||
+ (!ctx_bss->vif->bss_conf.idle &&
+ !ctx_bss->vif->bss_conf.assoc)) {
+ slot0 = bcnint * 3 - 20;
+ slot1 = 20;
+ } else if (!ctx_pan->vif->bss_conf.idle &&
+ !ctx_pan->vif->bss_conf.assoc) {
+ slot1 = bcnint * 3 - 20;
+ slot0 = 20;
+ }
+ } else if (ctx_pan->vif) {
+ slot0 = 0;
+ slot1 = max_t(int, 1, ctx_pan->vif->bss_conf.dtim_period) *
+ ctx_pan->vif->bss_conf.beacon_int;
+ slot1 = max_t(int, DEFAULT_BEACON_INTERVAL, slot1);
+
+ if (test_bit(STATUS_SCAN_HW, &priv->status)) {
+ slot0 = slot1 * 3 - 20;
+ slot1 = 20;
+ }
+ }
+
+ cmd.slots[0].width = cpu_to_le16(slot0);
+ cmd.slots[1].width = cpu_to_le16(slot1);
+
+ ret = iwl_send_cmd_pdu(priv, REPLY_WIPAN_PARAMS, sizeof(cmd), &cmd);
+ if (ret)
+ IWL_ERR(priv, "Error setting PAN parameters (%d)\n", ret);
+
+ return ret;
+}
+
struct iwl_hcmd_ops iwlagn_hcmd = {
.rxon_assoc = iwlagn_send_rxon_assoc,
- .commit_rxon = iwl_commit_rxon,
- .set_rxon_chain = iwl_set_rxon_chain,
+ .commit_rxon = iwlagn_commit_rxon,
+ .set_rxon_chain = iwlagn_set_rxon_chain,
.set_tx_ant = iwlagn_send_tx_ant_config,
.send_bt_config = iwl_send_bt_config,
+ .set_pan_params = iwlagn_set_pan_params,
+};
+
+struct iwl_hcmd_ops iwlagn_bt_hcmd = {
+ .rxon_assoc = iwlagn_send_rxon_assoc,
+ .commit_rxon = iwlagn_commit_rxon,
+ .set_rxon_chain = iwlagn_set_rxon_chain,
+ .set_tx_ant = iwlagn_send_tx_ant_config,
+ .send_bt_config = iwlagn_send_advance_bt_config,
+ .set_pan_params = iwlagn_set_pan_params,
};
struct iwl_hcmd_utils_ops iwlagn_hcmd_utils = {
@@ -282,4 +384,5 @@ struct iwl_hcmd_utils_ops iwlagn_hcmd_utils = {
.tx_cmd_protection = iwlagn_tx_cmd_protection,
.calc_rssi = iwlagn_calc_rssi,
.request_scan = iwlagn_request_scan,
+ .post_scan = iwlagn_post_scan,
};
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ict.c b/drivers/net/wireless/iwlwifi/iwl-agn-ict.c
index c92b2c0cbd91..a5dbfea1bfad 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-ict.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-ict.c
@@ -59,7 +59,7 @@ void iwl_free_isr_ict(struct iwl_priv *priv)
int iwl_alloc_isr_ict(struct iwl_priv *priv)
{
- if (priv->cfg->use_isr_legacy)
+ if (priv->cfg->base_params->use_isr_legacy)
return 0;
/* allocate shrared data table */
priv->_agn.ict_tbl_vir =
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
index 9dd9e64c2b0b..b555edd53354 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
@@ -40,22 +40,195 @@
#include "iwl-agn.h"
#include "iwl-sta.h"
-static inline u32 iwlagn_get_scd_ssn(struct iwl5000_tx_resp *tx_resp)
+static inline u32 iwlagn_get_scd_ssn(struct iwlagn_tx_resp *tx_resp)
{
return le32_to_cpup((__le32 *)&tx_resp->status +
tx_resp->frame_count) & MAX_SN;
}
+static void iwlagn_count_tx_err_status(struct iwl_priv *priv, u16 status)
+{
+ status &= TX_STATUS_MSK;
+
+ switch (status) {
+ case TX_STATUS_POSTPONE_DELAY:
+ priv->_agn.reply_tx_stats.pp_delay++;
+ break;
+ case TX_STATUS_POSTPONE_FEW_BYTES:
+ priv->_agn.reply_tx_stats.pp_few_bytes++;
+ break;
+ case TX_STATUS_POSTPONE_BT_PRIO:
+ priv->_agn.reply_tx_stats.pp_bt_prio++;
+ break;
+ case TX_STATUS_POSTPONE_QUIET_PERIOD:
+ priv->_agn.reply_tx_stats.pp_quiet_period++;
+ break;
+ case TX_STATUS_POSTPONE_CALC_TTAK:
+ priv->_agn.reply_tx_stats.pp_calc_ttak++;
+ break;
+ case TX_STATUS_FAIL_INTERNAL_CROSSED_RETRY:
+ priv->_agn.reply_tx_stats.int_crossed_retry++;
+ break;
+ case TX_STATUS_FAIL_SHORT_LIMIT:
+ priv->_agn.reply_tx_stats.short_limit++;
+ break;
+ case TX_STATUS_FAIL_LONG_LIMIT:
+ priv->_agn.reply_tx_stats.long_limit++;
+ break;
+ case TX_STATUS_FAIL_FIFO_UNDERRUN:
+ priv->_agn.reply_tx_stats.fifo_underrun++;
+ break;
+ case TX_STATUS_FAIL_DRAIN_FLOW:
+ priv->_agn.reply_tx_stats.drain_flow++;
+ break;
+ case TX_STATUS_FAIL_RFKILL_FLUSH:
+ priv->_agn.reply_tx_stats.rfkill_flush++;
+ break;
+ case TX_STATUS_FAIL_LIFE_EXPIRE:
+ priv->_agn.reply_tx_stats.life_expire++;
+ break;
+ case TX_STATUS_FAIL_DEST_PS:
+ priv->_agn.reply_tx_stats.dest_ps++;
+ break;
+ case TX_STATUS_FAIL_HOST_ABORTED:
+ priv->_agn.reply_tx_stats.host_abort++;
+ break;
+ case TX_STATUS_FAIL_BT_RETRY:
+ priv->_agn.reply_tx_stats.bt_retry++;
+ break;
+ case TX_STATUS_FAIL_STA_INVALID:
+ priv->_agn.reply_tx_stats.sta_invalid++;
+ break;
+ case TX_STATUS_FAIL_FRAG_DROPPED:
+ priv->_agn.reply_tx_stats.frag_drop++;
+ break;
+ case TX_STATUS_FAIL_TID_DISABLE:
+ priv->_agn.reply_tx_stats.tid_disable++;
+ break;
+ case TX_STATUS_FAIL_FIFO_FLUSHED:
+ priv->_agn.reply_tx_stats.fifo_flush++;
+ break;
+ case TX_STATUS_FAIL_INSUFFICIENT_CF_POLL:
+ priv->_agn.reply_tx_stats.insuff_cf_poll++;
+ break;
+ case TX_STATUS_FAIL_PASSIVE_NO_RX:
+ priv->_agn.reply_tx_stats.fail_hw_drop++;
+ break;
+ case TX_STATUS_FAIL_NO_BEACON_ON_RADAR:
+ priv->_agn.reply_tx_stats.sta_color_mismatch++;
+ break;
+ default:
+ priv->_agn.reply_tx_stats.unknown++;
+ break;
+ }
+}
+
+static void iwlagn_count_agg_tx_err_status(struct iwl_priv *priv, u16 status)
+{
+ status &= AGG_TX_STATUS_MSK;
+
+ switch (status) {
+ case AGG_TX_STATE_UNDERRUN_MSK:
+ priv->_agn.reply_agg_tx_stats.underrun++;
+ break;
+ case AGG_TX_STATE_BT_PRIO_MSK:
+ priv->_agn.reply_agg_tx_stats.bt_prio++;
+ break;
+ case AGG_TX_STATE_FEW_BYTES_MSK:
+ priv->_agn.reply_agg_tx_stats.few_bytes++;
+ break;
+ case AGG_TX_STATE_ABORT_MSK:
+ priv->_agn.reply_agg_tx_stats.abort++;
+ break;
+ case AGG_TX_STATE_LAST_SENT_TTL_MSK:
+ priv->_agn.reply_agg_tx_stats.last_sent_ttl++;
+ break;
+ case AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK:
+ priv->_agn.reply_agg_tx_stats.last_sent_try++;
+ break;
+ case AGG_TX_STATE_LAST_SENT_BT_KILL_MSK:
+ priv->_agn.reply_agg_tx_stats.last_sent_bt_kill++;
+ break;
+ case AGG_TX_STATE_SCD_QUERY_MSK:
+ priv->_agn.reply_agg_tx_stats.scd_query++;
+ break;
+ case AGG_TX_STATE_TEST_BAD_CRC32_MSK:
+ priv->_agn.reply_agg_tx_stats.bad_crc32++;
+ break;
+ case AGG_TX_STATE_RESPONSE_MSK:
+ priv->_agn.reply_agg_tx_stats.response++;
+ break;
+ case AGG_TX_STATE_DUMP_TX_MSK:
+ priv->_agn.reply_agg_tx_stats.dump_tx++;
+ break;
+ case AGG_TX_STATE_DELAY_TX_MSK:
+ priv->_agn.reply_agg_tx_stats.delay_tx++;
+ break;
+ default:
+ priv->_agn.reply_agg_tx_stats.unknown++;
+ break;
+ }
+}
+
+static void iwlagn_set_tx_status(struct iwl_priv *priv,
+ struct ieee80211_tx_info *info,
+ struct iwlagn_tx_resp *tx_resp,
+ int txq_id, bool is_agg)
+{
+ u16 status = le16_to_cpu(tx_resp->status.status);
+
+ info->status.rates[0].count = tx_resp->failure_frame + 1;
+ if (is_agg)
+ info->flags &= ~IEEE80211_TX_CTL_AMPDU;
+ info->flags |= iwl_tx_status_to_mac80211(status);
+ iwlagn_hwrate_to_tx_control(priv, le32_to_cpu(tx_resp->rate_n_flags),
+ info);
+ if (!iwl_is_tx_success(status))
+ iwlagn_count_tx_err_status(priv, status);
+
+ IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x) rate_n_flags "
+ "0x%x retries %d\n",
+ txq_id,
+ iwl_get_tx_fail_reason(status), status,
+ le32_to_cpu(tx_resp->rate_n_flags),
+ tx_resp->failure_frame);
+}
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+#define AGG_TX_STATE_FAIL(x) case AGG_TX_STATE_ ## x: return #x
+
+const char *iwl_get_agg_tx_fail_reason(u16 status)
+{
+ status &= AGG_TX_STATUS_MSK;
+ switch (status) {
+ case AGG_TX_STATE_TRANSMITTED:
+ return "SUCCESS";
+ AGG_TX_STATE_FAIL(UNDERRUN_MSK);
+ AGG_TX_STATE_FAIL(BT_PRIO_MSK);
+ AGG_TX_STATE_FAIL(FEW_BYTES_MSK);
+ AGG_TX_STATE_FAIL(ABORT_MSK);
+ AGG_TX_STATE_FAIL(LAST_SENT_TTL_MSK);
+ AGG_TX_STATE_FAIL(LAST_SENT_TRY_CNT_MSK);
+ AGG_TX_STATE_FAIL(LAST_SENT_BT_KILL_MSK);
+ AGG_TX_STATE_FAIL(SCD_QUERY_MSK);
+ AGG_TX_STATE_FAIL(TEST_BAD_CRC32_MSK);
+ AGG_TX_STATE_FAIL(RESPONSE_MSK);
+ AGG_TX_STATE_FAIL(DUMP_TX_MSK);
+ AGG_TX_STATE_FAIL(DELAY_TX_MSK);
+ }
+
+ return "UNKNOWN";
+}
+#endif /* CONFIG_IWLWIFI_DEBUG */
+
static int iwlagn_tx_status_reply_tx(struct iwl_priv *priv,
struct iwl_ht_agg *agg,
- struct iwl5000_tx_resp *tx_resp,
+ struct iwlagn_tx_resp *tx_resp,
int txq_id, u16 start_idx)
{
u16 status;
struct agg_tx_status *frame_status = &tx_resp->status;
- struct ieee80211_tx_info *info = NULL;
struct ieee80211_hdr *hdr = NULL;
- u32 rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags);
int i, sh, idx;
u16 seq;
@@ -64,31 +237,20 @@ static int iwlagn_tx_status_reply_tx(struct iwl_priv *priv,
agg->frame_count = tx_resp->frame_count;
agg->start_idx = start_idx;
- agg->rate_n_flags = rate_n_flags;
+ agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags);
agg->bitmap = 0;
/* # frames attempted by Tx command */
if (agg->frame_count == 1) {
/* Only one frame was attempted; no block-ack will arrive */
- status = le16_to_cpu(frame_status[0].status);
idx = start_idx;
- /* FIXME: code repetition */
IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n",
agg->frame_count, agg->start_idx, idx);
-
- info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb);
- info->status.rates[0].count = tx_resp->failure_frame + 1;
- info->flags &= ~IEEE80211_TX_CTL_AMPDU;
- info->flags |= iwl_tx_status_to_mac80211(status);
- iwlagn_hwrate_to_tx_control(priv, rate_n_flags, info);
-
- /* FIXME: code repetition end */
-
- IWL_DEBUG_TX_REPLY(priv, "1 Frame 0x%x failure :%d\n",
- status & 0xff, tx_resp->failure_frame);
- IWL_DEBUG_TX_REPLY(priv, "Rate Info rate_n_flags=%x\n", rate_n_flags);
-
+ iwlagn_set_tx_status(priv,
+ IEEE80211_SKB_CB(
+ priv->txq[txq_id].txb[idx].skb),
+ tx_resp, txq_id, true);
agg->wait_for_ba = 0;
} else {
/* Two or more frames were attempted; expect block-ack */
@@ -109,12 +271,20 @@ static int iwlagn_tx_status_reply_tx(struct iwl_priv *priv,
idx = SEQ_TO_INDEX(seq);
txq_id = SEQ_TO_QUEUE(seq);
+ if (status & AGG_TX_STATUS_MSK)
+ iwlagn_count_agg_tx_err_status(priv, status);
+
if (status & (AGG_TX_STATE_FEW_BYTES_MSK |
AGG_TX_STATE_ABORT_MSK))
continue;
IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, txq_id=%d idx=%d\n",
agg->frame_count, txq_id, idx);
+ IWL_DEBUG_TX_REPLY(priv, "status %s (0x%08x), "
+ "try-count (0x%08x)\n",
+ iwl_get_agg_tx_fail_reason(status),
+ status & AGG_TX_STATUS_MSK,
+ status & AGG_TX_TRY_MSK);
hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx);
if (!hdr) {
@@ -220,7 +390,7 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv,
int index = SEQ_TO_INDEX(sequence);
struct iwl_tx_queue *txq = &priv->txq[txq_id];
struct ieee80211_tx_info *info;
- struct iwl5000_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
+ struct iwlagn_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
u32 status = le16_to_cpu(tx_resp->status.status);
int tid;
int sta_id;
@@ -238,8 +408,10 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv,
info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb);
memset(&info->status, 0, sizeof(info->status));
- tid = (tx_resp->ra_tid & IWL50_TX_RES_TID_MSK) >> IWL50_TX_RES_TID_POS;
- sta_id = (tx_resp->ra_tid & IWL50_TX_RES_RA_MSK) >> IWL50_TX_RES_RA_POS;
+ tid = (tx_resp->ra_tid & IWLAGN_TX_RES_TID_MSK) >>
+ IWLAGN_TX_RES_TID_POS;
+ sta_id = (tx_resp->ra_tid & IWLAGN_TX_RES_RA_MSK) >>
+ IWLAGN_TX_RES_RA_POS;
spin_lock_irqsave(&priv->sta_lock, flags);
if (txq->sched_retry) {
@@ -247,7 +419,15 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv,
struct iwl_ht_agg *agg;
agg = &priv->stations[sta_id].tid[tid].agg;
-
+ /*
+ * If the BT kill count is non-zero, we'll get this
+ * notification again.
+ */
+ if (tx_resp->bt_kill_count && tx_resp->frame_count == 1 &&
+ priv->cfg->bt_params &&
+ priv->cfg->bt_params->advanced_bt_coexist) {
+ IWL_WARN(priv, "receive reply tx with bt_kill\n");
+ }
iwlagn_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index);
/* check if BAR is needed */
@@ -274,20 +454,7 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv,
}
} else {
BUG_ON(txq_id != txq->swq_id);
-
- info->status.rates[0].count = tx_resp->failure_frame + 1;
- info->flags |= iwl_tx_status_to_mac80211(status);
- iwlagn_hwrate_to_tx_control(priv,
- le32_to_cpu(tx_resp->rate_n_flags),
- info);
-
- IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x) rate_n_flags "
- "0x%x retries %d\n",
- txq_id,
- iwl_get_tx_fail_reason(status), status,
- le32_to_cpu(tx_resp->rate_n_flags),
- tx_resp->failure_frame);
-
+ iwlagn_set_tx_status(priv, info, tx_resp, txq_id, false);
freed = iwlagn_tx_queue_reclaim(priv, txq_id, index);
iwl_free_tfds_in_queue(priv, sta_id, tid, freed);
@@ -326,7 +493,7 @@ int iwlagn_hw_valid_rtc_data_addr(u32 addr)
int iwlagn_send_tx_power(struct iwl_priv *priv)
{
- struct iwl5000_tx_power_dbm_cmd tx_power_cmd;
+ struct iwlagn_tx_power_dbm_cmd tx_power_cmd;
u8 tx_ant_cfg_cmd;
/* half dBm need to multiply */
@@ -347,8 +514,8 @@ int iwlagn_send_tx_power(struct iwl_priv *priv)
*/
tx_power_cmd.global_lmt = priv->tx_power_lmt_in_half_dbm;
}
- tx_power_cmd.flags = IWL50_TX_POWER_NO_CLOSED;
- tx_power_cmd.srv_chan_lmt = IWL50_TX_POWER_AUTO;
+ tx_power_cmd.flags = IWLAGN_TX_POWER_NO_CLOSED;
+ tx_power_cmd.srv_chan_lmt = IWLAGN_TX_POWER_AUTO;
if (IWL_UCODE_API(priv->ucode_ver) == 1)
tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD_V1;
@@ -425,7 +592,7 @@ const u8 *iwlagn_eeprom_query_addr(const struct iwl_priv *priv,
size_t offset)
{
u32 address = eeprom_indirect_address(priv, offset);
- BUG_ON(address >= priv->cfg->eeprom_size);
+ BUG_ON(address >= priv->cfg->base_params->eeprom_size);
return &priv->eeprom[address];
}
@@ -473,7 +640,7 @@ int iwlagn_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */
u32 rb_timeout = 0; /* FIXME: RX_RB_TIMEOUT for all devices? */
- if (!priv->cfg->use_isr_legacy)
+ if (!priv->cfg->base_params->use_isr_legacy)
rb_timeout = RX_RB_TIMEOUT;
if (priv->cfg->mod_params->amsdu_size_8K)
@@ -518,6 +685,23 @@ int iwlagn_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
return 0;
}
+static void iwlagn_set_pwr_vmain(struct iwl_priv *priv)
+{
+/*
+ * (for documentation purposes)
+ * to set power to V_AUX, do:
+
+ if (pci_pme_capable(priv->pci_dev, PCI_D3cold))
+ iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
+ APMG_PS_CTRL_VAL_PWR_SRC_VAUX,
+ ~APMG_PS_CTRL_MSK_PWR_SRC);
+ */
+
+ iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
+ APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
+ ~APMG_PS_CTRL_MSK_PWR_SRC);
+}
+
int iwlagn_hw_nic_init(struct iwl_priv *priv)
{
unsigned long flags;
@@ -533,7 +717,7 @@ int iwlagn_hw_nic_init(struct iwl_priv *priv)
spin_unlock_irqrestore(&priv->lock, flags);
- ret = priv->cfg->ops->lib->apm_ops.set_pwr_src(priv, IWL_PWR_SRC_VMAIN);
+ iwlagn_set_pwr_vmain(priv);
priv->cfg->ops->lib->apm_ops.config(priv);
@@ -1098,7 +1282,7 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv,
if (chan->band != band)
continue;
- channel = ieee80211_frequency_to_channel(chan->center_freq);
+ channel = chan->hw_value;
scan_ch->channel = cpu_to_le16(channel);
ch_info = iwl_get_channel_info(priv, band, channel);
@@ -1147,7 +1331,7 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv,
return added;
}
-void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
+int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
{
struct iwl_host_cmd cmd = {
.id = REPLY_SCAN_CMD,
@@ -1155,7 +1339,7 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
.flags = CMD_SIZE_HUGE,
};
struct iwl_scan_cmd *scan;
- struct ieee80211_conf *conf = NULL;
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
u32 rate_flags = 0;
u16 cmd_len;
u16 rx_chain = 0;
@@ -1167,48 +1351,12 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
int chan_mod;
u8 active_chains;
u8 scan_tx_antennas = priv->hw_params.valid_tx_ant;
+ int ret;
- conf = ieee80211_get_hw_conf(priv->hw);
-
- cancel_delayed_work(&priv->scan_check);
-
- if (!iwl_is_ready(priv)) {
- IWL_WARN(priv, "request scan called when driver not ready.\n");
- goto done;
- }
-
- /* Make sure the scan wasn't canceled before this queued work
- * was given the chance to run... */
- if (!test_bit(STATUS_SCANNING, &priv->status))
- goto done;
-
- /* This should never be called or scheduled if there is currently
- * a scan active in the hardware. */
- if (test_bit(STATUS_SCAN_HW, &priv->status)) {
- IWL_DEBUG_INFO(priv, "Multiple concurrent scan requests in parallel. "
- "Ignoring second request.\n");
- goto done;
- }
-
- if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
- IWL_DEBUG_SCAN(priv, "Aborting scan due to device shutdown\n");
- goto done;
- }
-
- if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
- IWL_DEBUG_HC(priv, "Scan request while abort pending. Queuing.\n");
- goto done;
- }
-
- if (iwl_is_rfkill(priv)) {
- IWL_DEBUG_HC(priv, "Aborting scan due to RF Kill activation\n");
- goto done;
- }
+ lockdep_assert_held(&priv->mutex);
- if (!test_bit(STATUS_READY, &priv->status)) {
- IWL_DEBUG_HC(priv, "Scan request while uninitialized. Queuing.\n");
- goto done;
- }
+ if (vif)
+ ctx = iwl_rxon_ctx_from_vif(vif);
if (!priv->scan_cmd) {
priv->scan_cmd = kmalloc(sizeof(struct iwl_scan_cmd) +
@@ -1216,7 +1364,7 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
if (!priv->scan_cmd) {
IWL_DEBUG_SCAN(priv,
"fail to allocate memory for scan\n");
- goto done;
+ return -ENOMEM;
}
}
scan = priv->scan_cmd;
@@ -1225,7 +1373,7 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
- if (iwl_is_associated(priv)) {
+ if (iwl_is_any_associated(priv)) {
u16 interval = 0;
u32 extra;
u32 suspend_time = 100;
@@ -1276,13 +1424,15 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
IWL_DEBUG_SCAN(priv, "Start passive scan.\n");
scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
- scan->tx_cmd.sta_id = priv->hw_params.bcast_sta_id;
+ scan->tx_cmd.sta_id = ctx->bcast_sta_id;
scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
switch (priv->scan_band) {
case IEEE80211_BAND_2GHZ:
scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
- chan_mod = le32_to_cpu(priv->active_rxon.flags & RXON_FLG_CHANNEL_MODE_MSK)
+ chan_mod = le32_to_cpu(
+ priv->contexts[IWL_RXON_CTX_BSS].active.flags &
+ RXON_FLG_CHANNEL_MODE_MSK)
>> RXON_FLG_CHANNEL_MODE_POS;
if (chan_mod == CHANNEL_MODE_PURE_40) {
rate = IWL_RATE_6M_PLCP;
@@ -1290,35 +1440,42 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
rate = IWL_RATE_1M_PLCP;
rate_flags = RATE_MCS_CCK_MSK;
}
- scan->good_CRC_th = IWL_GOOD_CRC_TH_DISABLED;
+ /*
+ * Internal scans are passive, so we can indiscriminately set
+ * the BT ignore flag on 2.4 GHz since it applies to TX only.
+ */
+ if (priv->cfg->bt_params &&
+ priv->cfg->bt_params->advanced_bt_coexist)
+ scan->tx_cmd.tx_flags |= TX_CMD_FLG_IGNORE_BT;
break;
case IEEE80211_BAND_5GHZ:
rate = IWL_RATE_6M_PLCP;
- /*
- * If active scanning is requested but a certain channel is
- * marked passive, we can do active scanning if we detect
- * transmissions.
- *
- * There is an issue with some firmware versions that triggers
- * a sysassert on a "good CRC threshold" of zero (== disabled),
- * on a radar channel even though this means that we should NOT
- * send probes.
- *
- * The "good CRC threshold" is the number of frames that we
- * need to receive during our dwell time on a channel before
- * sending out probes -- setting this to a huge value will
- * mean we never reach it, but at the same time work around
- * the aforementioned issue. Thus use IWL_GOOD_CRC_TH_NEVER
- * here instead of IWL_GOOD_CRC_TH_DISABLED.
- */
- scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
- IWL_GOOD_CRC_TH_NEVER;
break;
default:
- IWL_WARN(priv, "Invalid scan band count\n");
- goto done;
+ IWL_WARN(priv, "Invalid scan band\n");
+ return -EIO;
}
+ /*
+ * If active scanning is requested but a certain channel is
+ * marked passive, we can do active scanning if we detect
+ * transmissions.
+ *
+ * There is an issue with some firmware versions that triggers
+ * a sysassert on a "good CRC threshold" of zero (== disabled),
+ * on a radar channel even though this means that we should NOT
+ * send probes.
+ *
+ * The "good CRC threshold" is the number of frames that we
+ * need to receive during our dwell time on a channel before
+ * sending out probes -- setting this to a huge value will
+ * mean we never reach it, but at the same time work around
+ * the aforementioned issue. Thus use IWL_GOOD_CRC_TH_NEVER
+ * here instead of IWL_GOOD_CRC_TH_DISABLED.
+ */
+ scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
+ IWL_GOOD_CRC_TH_NEVER;
+
band = priv->scan_band;
if (priv->cfg->scan_rx_antennas[band])
@@ -1327,6 +1484,14 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
if (priv->cfg->scan_tx_antennas[band])
scan_tx_antennas = priv->cfg->scan_tx_antennas[band];
+ if (priv->cfg->bt_params &&
+ priv->cfg->bt_params->advanced_bt_coexist &&
+ priv->bt_full_concurrent) {
+ /* operated as 1x1 in full concurrency mode */
+ scan_tx_antennas = first_antenna(
+ priv->cfg->scan_tx_antennas[band]);
+ }
+
priv->scan_tx_ant[band] = iwl_toggle_tx_ant(priv, priv->scan_tx_ant[band],
scan_tx_antennas);
rate_flags |= iwl_ant_idx_to_flags(priv->scan_tx_ant[band]);
@@ -1345,6 +1510,13 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
rx_ant = first_antenna(active_chains);
}
+ if (priv->cfg->bt_params &&
+ priv->cfg->bt_params->advanced_bt_coexist &&
+ priv->bt_full_concurrent) {
+ /* operated as 1x1 in full concurrency mode */
+ rx_ant = first_antenna(rx_ant);
+ }
+
/* MIMO is not used here, but value is required */
rx_chain |= priv->hw_params.valid_rx_ant << RXON_RX_CHAIN_VALID_POS;
rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS;
@@ -1385,7 +1557,7 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
}
if (scan->channel_count == 0) {
IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
- goto done;
+ return -EIO;
}
cmd.len += le16_to_cpu(scan->tx_cmd.len) +
@@ -1393,25 +1565,39 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
cmd.data = scan;
scan->len = cpu_to_le16(cmd.len);
+ /* set scan bit here for PAN params */
set_bit(STATUS_SCAN_HW, &priv->status);
- if (iwl_send_cmd_sync(priv, &cmd))
- goto done;
- queue_delayed_work(priv->workqueue, &priv->scan_check,
- IWL_SCAN_CHECK_WATCHDOG);
-
- return;
-
- done:
- /* Cannot perform scan. Make sure we clear scanning
- * bits from status so next scan request can be performed.
- * If we don't clear scanning status bit here all next scan
- * will fail
- */
- clear_bit(STATUS_SCAN_HW, &priv->status);
- clear_bit(STATUS_SCANNING, &priv->status);
- /* inform mac80211 scan aborted */
- queue_work(priv->workqueue, &priv->scan_completed);
+ if (priv->cfg->ops->hcmd->set_pan_params) {
+ ret = priv->cfg->ops->hcmd->set_pan_params(priv);
+ if (ret)
+ return ret;
+ }
+
+ ret = iwl_send_cmd_sync(priv, &cmd);
+ if (ret) {
+ clear_bit(STATUS_SCAN_HW, &priv->status);
+ if (priv->cfg->ops->hcmd->set_pan_params)
+ priv->cfg->ops->hcmd->set_pan_params(priv);
+ }
+
+ return ret;
+}
+
+void iwlagn_post_scan(struct iwl_priv *priv)
+{
+ struct iwl_rxon_context *ctx;
+
+ /*
+ * Since setting the RXON may have been deferred while
+ * performing the scan, fire one off if needed
+ */
+ for_each_context(priv, ctx)
+ if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
+ iwlagn_commit_rxon(priv, ctx);
+
+ if (priv->cfg->ops->hcmd->set_pan_params)
+ priv->cfg->ops->hcmd->set_pan_params(priv);
}
int iwlagn_manage_ibss_station(struct iwl_priv *priv,
@@ -1420,8 +1606,9 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv,
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
if (add)
- return iwl_add_bssid_station(priv, vif->bss_conf.bssid, true,
- &vif_priv->ibss_bssid_sta_id);
+ return iwlagn_add_bssid_station(priv, vif_priv->ctx,
+ vif->bss_conf.bssid,
+ &vif_priv->ibss_bssid_sta_id);
return iwl_remove_station(priv, vif_priv->ibss_bssid_sta_id,
vif->bss_conf.bssid);
}
@@ -1453,7 +1640,7 @@ int iwlagn_wait_tx_queue_empty(struct iwl_priv *priv)
/* waiting for all the tx frames complete might take a while */
for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
- if (cnt == IWL_CMD_QUEUE_NUM)
+ if (cnt == priv->cmd_queue)
continue;
txq = &priv->txq[cnt];
q = &txq->q;
@@ -1518,3 +1705,669 @@ done:
ieee80211_wake_queues(priv->hw);
mutex_unlock(&priv->mutex);
}
+
+/*
+ * BT coex
+ */
+/*
+ * Macros to access the lookup table.
+ *
+ * The lookup table has 7 inputs: bt3_prio, bt3_txrx, bt_rf_act, wifi_req,
+* wifi_prio, wifi_txrx and wifi_sh_ant_req.
+ *
+ * It has three outputs: WLAN_ACTIVE, WLAN_KILL and ANT_SWITCH
+ *
+ * The format is that "registers" 8 through 11 contain the WLAN_ACTIVE bits
+ * one after another in 32-bit registers, and "registers" 0 through 7 contain
+ * the WLAN_KILL and ANT_SWITCH bits interleaved (in that order).
+ *
+ * These macros encode that format.
+ */
+#define LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, wifi_req, wifi_prio, \
+ wifi_txrx, wifi_sh_ant_req) \
+ (bt3_prio | (bt3_txrx << 1) | (bt_rf_act << 2) | (wifi_req << 3) | \
+ (wifi_prio << 4) | (wifi_txrx << 5) | (wifi_sh_ant_req << 6))
+
+#define LUT_PTA_WLAN_ACTIVE_OP(lut, op, val) \
+ lut[8 + ((val) >> 5)] op (cpu_to_le32(BIT((val) & 0x1f)))
+#define LUT_TEST_PTA_WLAN_ACTIVE(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \
+ wifi_prio, wifi_txrx, wifi_sh_ant_req) \
+ (!!(LUT_PTA_WLAN_ACTIVE_OP(lut, &, LUT_VALUE(bt3_prio, bt3_txrx, \
+ bt_rf_act, wifi_req, wifi_prio, wifi_txrx, \
+ wifi_sh_ant_req))))
+#define LUT_SET_PTA_WLAN_ACTIVE(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \
+ wifi_prio, wifi_txrx, wifi_sh_ant_req) \
+ LUT_PTA_WLAN_ACTIVE_OP(lut, |=, LUT_VALUE(bt3_prio, bt3_txrx, \
+ bt_rf_act, wifi_req, wifi_prio, wifi_txrx, \
+ wifi_sh_ant_req))
+#define LUT_CLEAR_PTA_WLAN_ACTIVE(lut, bt3_prio, bt3_txrx, bt_rf_act, \
+ wifi_req, wifi_prio, wifi_txrx, \
+ wifi_sh_ant_req) \
+ LUT_PTA_WLAN_ACTIVE_OP(lut, &= ~, LUT_VALUE(bt3_prio, bt3_txrx, \
+ bt_rf_act, wifi_req, wifi_prio, wifi_txrx, \
+ wifi_sh_ant_req))
+
+#define LUT_WLAN_KILL_OP(lut, op, val) \
+ lut[(val) >> 4] op (cpu_to_le32(BIT(((val) << 1) & 0x1e)))
+#define LUT_TEST_WLAN_KILL(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \
+ wifi_prio, wifi_txrx, wifi_sh_ant_req) \
+ (!!(LUT_WLAN_KILL_OP(lut, &, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \
+ wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req))))
+#define LUT_SET_WLAN_KILL(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \
+ wifi_prio, wifi_txrx, wifi_sh_ant_req) \
+ LUT_WLAN_KILL_OP(lut, |=, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \
+ wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req))
+#define LUT_CLEAR_WLAN_KILL(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \
+ wifi_prio, wifi_txrx, wifi_sh_ant_req) \
+ LUT_WLAN_KILL_OP(lut, &= ~, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \
+ wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req))
+
+#define LUT_ANT_SWITCH_OP(lut, op, val) \
+ lut[(val) >> 4] op (cpu_to_le32(BIT((((val) << 1) & 0x1e) + 1)))
+#define LUT_TEST_ANT_SWITCH(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \
+ wifi_prio, wifi_txrx, wifi_sh_ant_req) \
+ (!!(LUT_ANT_SWITCH_OP(lut, &, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \
+ wifi_req, wifi_prio, wifi_txrx, \
+ wifi_sh_ant_req))))
+#define LUT_SET_ANT_SWITCH(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \
+ wifi_prio, wifi_txrx, wifi_sh_ant_req) \
+ LUT_ANT_SWITCH_OP(lut, |=, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \
+ wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req))
+#define LUT_CLEAR_ANT_SWITCH(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \
+ wifi_prio, wifi_txrx, wifi_sh_ant_req) \
+ LUT_ANT_SWITCH_OP(lut, &= ~, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \
+ wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req))
+
+static const __le32 iwlagn_def_3w_lookup[12] = {
+ cpu_to_le32(0xaaaaaaaa),
+ cpu_to_le32(0xaaaaaaaa),
+ cpu_to_le32(0xaeaaaaaa),
+ cpu_to_le32(0xaaaaaaaa),
+ cpu_to_le32(0xcc00ff28),
+ cpu_to_le32(0x0000aaaa),
+ cpu_to_le32(0xcc00aaaa),
+ cpu_to_le32(0x0000aaaa),
+ cpu_to_le32(0xc0004000),
+ cpu_to_le32(0x00004000),
+ cpu_to_le32(0xf0005000),
+ cpu_to_le32(0xf0004000),
+};
+
+static const __le32 iwlagn_concurrent_lookup[12] = {
+ cpu_to_le32(0xaaaaaaaa),
+ cpu_to_le32(0xaaaaaaaa),
+ cpu_to_le32(0xaaaaaaaa),
+ cpu_to_le32(0xaaaaaaaa),
+ cpu_to_le32(0xaaaaaaaa),
+ cpu_to_le32(0xaaaaaaaa),
+ cpu_to_le32(0xaaaaaaaa),
+ cpu_to_le32(0xaaaaaaaa),
+ cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000),
+};
+
+void iwlagn_send_advance_bt_config(struct iwl_priv *priv)
+{
+ struct iwlagn_bt_cmd bt_cmd = {
+ .max_kill = IWLAGN_BT_MAX_KILL_DEFAULT,
+ .bt3_timer_t7_value = IWLAGN_BT3_T7_DEFAULT,
+ .bt3_prio_sample_time = IWLAGN_BT3_PRIO_SAMPLE_DEFAULT,
+ .bt3_timer_t2_value = IWLAGN_BT3_T2_DEFAULT,
+ };
+
+ BUILD_BUG_ON(sizeof(iwlagn_def_3w_lookup) !=
+ sizeof(bt_cmd.bt3_lookup_table));
+
+ if (priv->cfg->bt_params)
+ bt_cmd.prio_boost = priv->cfg->bt_params->bt_prio_boost;
+ else
+ bt_cmd.prio_boost = 0;
+ bt_cmd.kill_ack_mask = priv->kill_ack_mask;
+ bt_cmd.kill_cts_mask = priv->kill_cts_mask;
+ bt_cmd.valid = priv->bt_valid;
+ bt_cmd.tx_prio_boost = 0;
+ bt_cmd.rx_prio_boost = 0;
+
+ /*
+ * Configure BT coex mode to "no coexistence" when the
+ * user disabled BT coexistence, we have no interface
+ * (might be in monitor mode), or the interface is in
+ * IBSS mode (no proper uCode support for coex then).
+ */
+ if (!bt_coex_active || priv->iw_mode == NL80211_IFTYPE_ADHOC) {
+ bt_cmd.flags = 0;
+ } else {
+ bt_cmd.flags = IWLAGN_BT_FLAG_COEX_MODE_3W <<
+ IWLAGN_BT_FLAG_COEX_MODE_SHIFT;
+ if (priv->bt_ch_announce)
+ bt_cmd.flags |= IWLAGN_BT_FLAG_CHANNEL_INHIBITION;
+ IWL_DEBUG_INFO(priv, "BT coex flag: 0X%x\n", bt_cmd.flags);
+ }
+ if (priv->bt_full_concurrent)
+ memcpy(bt_cmd.bt3_lookup_table, iwlagn_concurrent_lookup,
+ sizeof(iwlagn_concurrent_lookup));
+ else
+ memcpy(bt_cmd.bt3_lookup_table, iwlagn_def_3w_lookup,
+ sizeof(iwlagn_def_3w_lookup));
+
+ IWL_DEBUG_INFO(priv, "BT coex %s in %s mode\n",
+ bt_cmd.flags ? "active" : "disabled",
+ priv->bt_full_concurrent ?
+ "full concurrency" : "3-wire");
+
+ if (iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG, sizeof(bt_cmd), &bt_cmd))
+ IWL_ERR(priv, "failed to send BT Coex Config\n");
+
+ /*
+ * When we are doing a restart, need to also reconfigure BT
+ * SCO to the device. If not doing a restart, bt_sco_active
+ * will always be false, so there's no need to have an extra
+ * variable to check for it.
+ */
+ if (priv->bt_sco_active) {
+ struct iwlagn_bt_sco_cmd sco_cmd = { .flags = 0 };
+
+ if (priv->bt_sco_active)
+ sco_cmd.flags |= IWLAGN_BT_SCO_ACTIVE;
+ if (iwl_send_cmd_pdu(priv, REPLY_BT_COEX_SCO,
+ sizeof(sco_cmd), &sco_cmd))
+ IWL_ERR(priv, "failed to send BT SCO command\n");
+ }
+}
+
+static void iwlagn_bt_traffic_change_work(struct work_struct *work)
+{
+ struct iwl_priv *priv =
+ container_of(work, struct iwl_priv, bt_traffic_change_work);
+ struct iwl_rxon_context *ctx;
+ int smps_request = -1;
+
+ IWL_DEBUG_INFO(priv, "BT traffic load changes: %d\n",
+ priv->bt_traffic_load);
+
+ switch (priv->bt_traffic_load) {
+ case IWL_BT_COEX_TRAFFIC_LOAD_NONE:
+ smps_request = IEEE80211_SMPS_AUTOMATIC;
+ break;
+ case IWL_BT_COEX_TRAFFIC_LOAD_LOW:
+ smps_request = IEEE80211_SMPS_DYNAMIC;
+ break;
+ case IWL_BT_COEX_TRAFFIC_LOAD_HIGH:
+ case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS:
+ smps_request = IEEE80211_SMPS_STATIC;
+ break;
+ default:
+ IWL_ERR(priv, "Invalid BT traffic load: %d\n",
+ priv->bt_traffic_load);
+ break;
+ }
+
+ mutex_lock(&priv->mutex);
+
+ if (priv->cfg->ops->lib->update_chain_flags)
+ priv->cfg->ops->lib->update_chain_flags(priv);
+
+ if (smps_request != -1) {
+ for_each_context(priv, ctx) {
+ if (ctx->vif && ctx->vif->type == NL80211_IFTYPE_STATION)
+ ieee80211_request_smps(ctx->vif, smps_request);
+ }
+ }
+
+ mutex_unlock(&priv->mutex);
+}
+
+static void iwlagn_print_uartmsg(struct iwl_priv *priv,
+ struct iwl_bt_uart_msg *uart_msg)
+{
+ IWL_DEBUG_NOTIF(priv, "Message Type = 0x%X, SSN = 0x%X, "
+ "Update Req = 0x%X",
+ (BT_UART_MSG_FRAME1MSGTYPE_MSK & uart_msg->frame1) >>
+ BT_UART_MSG_FRAME1MSGTYPE_POS,
+ (BT_UART_MSG_FRAME1SSN_MSK & uart_msg->frame1) >>
+ BT_UART_MSG_FRAME1SSN_POS,
+ (BT_UART_MSG_FRAME1UPDATEREQ_MSK & uart_msg->frame1) >>
+ BT_UART_MSG_FRAME1UPDATEREQ_POS);
+
+ IWL_DEBUG_NOTIF(priv, "Open connections = 0x%X, Traffic load = 0x%X, "
+ "Chl_SeqN = 0x%X, In band = 0x%X",
+ (BT_UART_MSG_FRAME2OPENCONNECTIONS_MSK & uart_msg->frame2) >>
+ BT_UART_MSG_FRAME2OPENCONNECTIONS_POS,
+ (BT_UART_MSG_FRAME2TRAFFICLOAD_MSK & uart_msg->frame2) >>
+ BT_UART_MSG_FRAME2TRAFFICLOAD_POS,
+ (BT_UART_MSG_FRAME2CHLSEQN_MSK & uart_msg->frame2) >>
+ BT_UART_MSG_FRAME2CHLSEQN_POS,
+ (BT_UART_MSG_FRAME2INBAND_MSK & uart_msg->frame2) >>
+ BT_UART_MSG_FRAME2INBAND_POS);
+
+ IWL_DEBUG_NOTIF(priv, "SCO/eSCO = 0x%X, Sniff = 0x%X, A2DP = 0x%X, "
+ "ACL = 0x%X, Master = 0x%X, OBEX = 0x%X",
+ (BT_UART_MSG_FRAME3SCOESCO_MSK & uart_msg->frame3) >>
+ BT_UART_MSG_FRAME3SCOESCO_POS,
+ (BT_UART_MSG_FRAME3SNIFF_MSK & uart_msg->frame3) >>
+ BT_UART_MSG_FRAME3SNIFF_POS,
+ (BT_UART_MSG_FRAME3A2DP_MSK & uart_msg->frame3) >>
+ BT_UART_MSG_FRAME3A2DP_POS,
+ (BT_UART_MSG_FRAME3ACL_MSK & uart_msg->frame3) >>
+ BT_UART_MSG_FRAME3ACL_POS,
+ (BT_UART_MSG_FRAME3MASTER_MSK & uart_msg->frame3) >>
+ BT_UART_MSG_FRAME3MASTER_POS,
+ (BT_UART_MSG_FRAME3OBEX_MSK & uart_msg->frame3) >>
+ BT_UART_MSG_FRAME3OBEX_POS);
+
+ IWL_DEBUG_NOTIF(priv, "Idle duration = 0x%X",
+ (BT_UART_MSG_FRAME4IDLEDURATION_MSK & uart_msg->frame4) >>
+ BT_UART_MSG_FRAME4IDLEDURATION_POS);
+
+ IWL_DEBUG_NOTIF(priv, "Tx Activity = 0x%X, Rx Activity = 0x%X, "
+ "eSCO Retransmissions = 0x%X",
+ (BT_UART_MSG_FRAME5TXACTIVITY_MSK & uart_msg->frame5) >>
+ BT_UART_MSG_FRAME5TXACTIVITY_POS,
+ (BT_UART_MSG_FRAME5RXACTIVITY_MSK & uart_msg->frame5) >>
+ BT_UART_MSG_FRAME5RXACTIVITY_POS,
+ (BT_UART_MSG_FRAME5ESCORETRANSMIT_MSK & uart_msg->frame5) >>
+ BT_UART_MSG_FRAME5ESCORETRANSMIT_POS);
+
+ IWL_DEBUG_NOTIF(priv, "Sniff Interval = 0x%X, Discoverable = 0x%X",
+ (BT_UART_MSG_FRAME6SNIFFINTERVAL_MSK & uart_msg->frame6) >>
+ BT_UART_MSG_FRAME6SNIFFINTERVAL_POS,
+ (BT_UART_MSG_FRAME6DISCOVERABLE_MSK & uart_msg->frame6) >>
+ BT_UART_MSG_FRAME6DISCOVERABLE_POS);
+
+ IWL_DEBUG_NOTIF(priv, "Sniff Activity = 0x%X, Inquiry/Page SR Mode = "
+ "0x%X, Connectable = 0x%X",
+ (BT_UART_MSG_FRAME7SNIFFACTIVITY_MSK & uart_msg->frame7) >>
+ BT_UART_MSG_FRAME7SNIFFACTIVITY_POS,
+ (BT_UART_MSG_FRAME7INQUIRYPAGESRMODE_MSK & uart_msg->frame7) >>
+ BT_UART_MSG_FRAME7INQUIRYPAGESRMODE_POS,
+ (BT_UART_MSG_FRAME7CONNECTABLE_MSK & uart_msg->frame7) >>
+ BT_UART_MSG_FRAME7CONNECTABLE_POS);
+}
+
+static void iwlagn_set_kill_ack_msk(struct iwl_priv *priv,
+ struct iwl_bt_uart_msg *uart_msg)
+{
+ u8 kill_ack_msk;
+ __le32 bt_kill_ack_msg[2] = {
+ cpu_to_le32(0xFFFFFFF), cpu_to_le32(0xFFFFFC00) };
+
+ kill_ack_msk = (((BT_UART_MSG_FRAME3A2DP_MSK |
+ BT_UART_MSG_FRAME3SNIFF_MSK |
+ BT_UART_MSG_FRAME3SCOESCO_MSK) &
+ uart_msg->frame3) == 0) ? 1 : 0;
+ if (priv->kill_ack_mask != bt_kill_ack_msg[kill_ack_msk]) {
+ priv->bt_valid |= IWLAGN_BT_VALID_KILL_ACK_MASK;
+ priv->kill_ack_mask = bt_kill_ack_msg[kill_ack_msk];
+ /* schedule to send runtime bt_config */
+ queue_work(priv->workqueue, &priv->bt_runtime_config);
+ }
+
+}
+
+void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
+ struct iwl_rx_mem_buffer *rxb)
+{
+ unsigned long flags;
+ struct iwl_rx_packet *pkt = rxb_addr(rxb);
+ struct iwl_bt_coex_profile_notif *coex = &pkt->u.bt_coex_profile_notif;
+ struct iwlagn_bt_sco_cmd sco_cmd = { .flags = 0 };
+ struct iwl_bt_uart_msg *uart_msg = &coex->last_bt_uart_msg;
+ u8 last_traffic_load;
+
+ IWL_DEBUG_NOTIF(priv, "BT Coex notification:\n");
+ IWL_DEBUG_NOTIF(priv, " status: %d\n", coex->bt_status);
+ IWL_DEBUG_NOTIF(priv, " traffic load: %d\n", coex->bt_traffic_load);
+ IWL_DEBUG_NOTIF(priv, " CI compliance: %d\n",
+ coex->bt_ci_compliance);
+ iwlagn_print_uartmsg(priv, uart_msg);
+
+ last_traffic_load = priv->notif_bt_traffic_load;
+ priv->notif_bt_traffic_load = coex->bt_traffic_load;
+ if (priv->iw_mode != NL80211_IFTYPE_ADHOC) {
+ if (priv->bt_status != coex->bt_status ||
+ last_traffic_load != coex->bt_traffic_load) {
+ if (coex->bt_status) {
+ /* BT on */
+ if (!priv->bt_ch_announce)
+ priv->bt_traffic_load =
+ IWL_BT_COEX_TRAFFIC_LOAD_HIGH;
+ else
+ priv->bt_traffic_load =
+ coex->bt_traffic_load;
+ } else {
+ /* BT off */
+ priv->bt_traffic_load =
+ IWL_BT_COEX_TRAFFIC_LOAD_NONE;
+ }
+ priv->bt_status = coex->bt_status;
+ queue_work(priv->workqueue,
+ &priv->bt_traffic_change_work);
+ }
+ if (priv->bt_sco_active !=
+ (uart_msg->frame3 & BT_UART_MSG_FRAME3SCOESCO_MSK)) {
+ priv->bt_sco_active = uart_msg->frame3 &
+ BT_UART_MSG_FRAME3SCOESCO_MSK;
+ if (priv->bt_sco_active)
+ sco_cmd.flags |= IWLAGN_BT_SCO_ACTIVE;
+ iwl_send_cmd_pdu_async(priv, REPLY_BT_COEX_SCO,
+ sizeof(sco_cmd), &sco_cmd, NULL);
+ }
+ }
+
+ iwlagn_set_kill_ack_msk(priv, uart_msg);
+
+ /* FIXME: based on notification, adjust the prio_boost */
+
+ spin_lock_irqsave(&priv->lock, flags);
+ priv->bt_ci_compliance = coex->bt_ci_compliance;
+ spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+void iwlagn_bt_rx_handler_setup(struct iwl_priv *priv)
+{
+ iwlagn_rx_handler_setup(priv);
+ priv->rx_handlers[REPLY_BT_COEX_PROFILE_NOTIF] =
+ iwlagn_bt_coex_profile_notif;
+}
+
+void iwlagn_bt_setup_deferred_work(struct iwl_priv *priv)
+{
+ iwlagn_setup_deferred_work(priv);
+
+ INIT_WORK(&priv->bt_traffic_change_work,
+ iwlagn_bt_traffic_change_work);
+}
+
+void iwlagn_bt_cancel_deferred_work(struct iwl_priv *priv)
+{
+ cancel_work_sync(&priv->bt_traffic_change_work);
+}
+
+static bool is_single_rx_stream(struct iwl_priv *priv)
+{
+ return priv->current_ht_config.smps == IEEE80211_SMPS_STATIC ||
+ priv->current_ht_config.single_chain_sufficient;
+}
+
+#define IWL_NUM_RX_CHAINS_MULTIPLE 3
+#define IWL_NUM_RX_CHAINS_SINGLE 2
+#define IWL_NUM_IDLE_CHAINS_DUAL 2
+#define IWL_NUM_IDLE_CHAINS_SINGLE 1
+
+/*
+ * Determine how many receiver/antenna chains to use.
+ *
+ * More provides better reception via diversity. Fewer saves power
+ * at the expense of throughput, but only when not in powersave to
+ * start with.
+ *
+ * MIMO (dual stream) requires at least 2, but works better with 3.
+ * This does not determine *which* chains to use, just how many.
+ */
+static int iwl_get_active_rx_chain_count(struct iwl_priv *priv)
+{
+ if (priv->cfg->bt_params &&
+ priv->cfg->bt_params->advanced_bt_coexist &&
+ (priv->bt_full_concurrent ||
+ priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)) {
+ /*
+ * only use chain 'A' in bt high traffic load or
+ * full concurrency mode
+ */
+ return IWL_NUM_RX_CHAINS_SINGLE;
+ }
+ /* # of Rx chains to use when expecting MIMO. */
+ if (is_single_rx_stream(priv))
+ return IWL_NUM_RX_CHAINS_SINGLE;
+ else
+ return IWL_NUM_RX_CHAINS_MULTIPLE;
+}
+
+/*
+ * When we are in power saving mode, unless device support spatial
+ * multiplexing power save, use the active count for rx chain count.
+ */
+static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt)
+{
+ /* # Rx chains when idling, depending on SMPS mode */
+ switch (priv->current_ht_config.smps) {
+ case IEEE80211_SMPS_STATIC:
+ case IEEE80211_SMPS_DYNAMIC:
+ return IWL_NUM_IDLE_CHAINS_SINGLE;
+ case IEEE80211_SMPS_OFF:
+ return active_cnt;
+ default:
+ WARN(1, "invalid SMPS mode %d",
+ priv->current_ht_config.smps);
+ return active_cnt;
+ }
+}
+
+/* up to 4 chains */
+static u8 iwl_count_chain_bitmap(u32 chain_bitmap)
+{
+ u8 res;
+ res = (chain_bitmap & BIT(0)) >> 0;
+ res += (chain_bitmap & BIT(1)) >> 1;
+ res += (chain_bitmap & BIT(2)) >> 2;
+ res += (chain_bitmap & BIT(3)) >> 3;
+ return res;
+}
+
+/**
+ * iwlagn_set_rxon_chain - Set up Rx chain usage in "staging" RXON image
+ *
+ * Selects how many and which Rx receivers/antennas/chains to use.
+ * This should not be used for scan command ... it puts data in wrong place.
+ */
+void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
+{
+ bool is_single = is_single_rx_stream(priv);
+ bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status);
+ u8 idle_rx_cnt, active_rx_cnt, valid_rx_cnt;
+ u32 active_chains;
+ u16 rx_chain;
+
+ /* Tell uCode which antennas are actually connected.
+ * Before first association, we assume all antennas are connected.
+ * Just after first association, iwl_chain_noise_calibration()
+ * checks which antennas actually *are* connected. */
+ if (priv->chain_noise_data.active_chains)
+ active_chains = priv->chain_noise_data.active_chains;
+ else
+ active_chains = priv->hw_params.valid_rx_ant;
+
+ if (priv->cfg->bt_params &&
+ priv->cfg->bt_params->advanced_bt_coexist &&
+ (priv->bt_full_concurrent ||
+ priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)) {
+ /*
+ * only use chain 'A' in bt high traffic load or
+ * full concurrency mode
+ */
+ active_chains = first_antenna(active_chains);
+ }
+
+ rx_chain = active_chains << RXON_RX_CHAIN_VALID_POS;
+
+ /* How many receivers should we use? */
+ active_rx_cnt = iwl_get_active_rx_chain_count(priv);
+ idle_rx_cnt = iwl_get_idle_rx_chain_count(priv, active_rx_cnt);
+
+
+ /* correct rx chain count according hw settings
+ * and chain noise calibration
+ */
+ valid_rx_cnt = iwl_count_chain_bitmap(active_chains);
+ if (valid_rx_cnt < active_rx_cnt)
+ active_rx_cnt = valid_rx_cnt;
+
+ if (valid_rx_cnt < idle_rx_cnt)
+ idle_rx_cnt = valid_rx_cnt;
+
+ rx_chain |= active_rx_cnt << RXON_RX_CHAIN_MIMO_CNT_POS;
+ rx_chain |= idle_rx_cnt << RXON_RX_CHAIN_CNT_POS;
+
+ ctx->staging.rx_chain = cpu_to_le16(rx_chain);
+
+ if (!is_single && (active_rx_cnt >= IWL_NUM_RX_CHAINS_SINGLE) && is_cam)
+ ctx->staging.rx_chain |= RXON_RX_CHAIN_MIMO_FORCE_MSK;
+ else
+ ctx->staging.rx_chain &= ~RXON_RX_CHAIN_MIMO_FORCE_MSK;
+
+ IWL_DEBUG_ASSOC(priv, "rx_chain=0x%X active=%d idle=%d\n",
+ ctx->staging.rx_chain,
+ active_rx_cnt, idle_rx_cnt);
+
+ WARN_ON(active_rx_cnt == 0 || idle_rx_cnt == 0 ||
+ active_rx_cnt < idle_rx_cnt);
+}
+
+u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant, u8 valid)
+{
+ int i;
+ u8 ind = ant;
+
+ if (priv->band == IEEE80211_BAND_2GHZ &&
+ priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)
+ return 0;
+
+ for (i = 0; i < RATE_ANT_NUM - 1; i++) {
+ ind = (ind + 1) < RATE_ANT_NUM ? ind + 1 : 0;
+ if (valid & BIT(ind))
+ return ind;
+ }
+ return ant;
+}
+
+static const char *get_csr_string(int cmd)
+{
+ switch (cmd) {
+ IWL_CMD(CSR_HW_IF_CONFIG_REG);
+ IWL_CMD(CSR_INT_COALESCING);
+ IWL_CMD(CSR_INT);
+ IWL_CMD(CSR_INT_MASK);
+ IWL_CMD(CSR_FH_INT_STATUS);
+ IWL_CMD(CSR_GPIO_IN);
+ IWL_CMD(CSR_RESET);
+ IWL_CMD(CSR_GP_CNTRL);
+ IWL_CMD(CSR_HW_REV);
+ IWL_CMD(CSR_EEPROM_REG);
+ IWL_CMD(CSR_EEPROM_GP);
+ IWL_CMD(CSR_OTP_GP_REG);
+ IWL_CMD(CSR_GIO_REG);
+ IWL_CMD(CSR_GP_UCODE_REG);
+ IWL_CMD(CSR_GP_DRIVER_REG);
+ IWL_CMD(CSR_UCODE_DRV_GP1);
+ IWL_CMD(CSR_UCODE_DRV_GP2);
+ IWL_CMD(CSR_LED_REG);
+ IWL_CMD(CSR_DRAM_INT_TBL_REG);
+ IWL_CMD(CSR_GIO_CHICKEN_BITS);
+ IWL_CMD(CSR_ANA_PLL_CFG);
+ IWL_CMD(CSR_HW_REV_WA_REG);
+ IWL_CMD(CSR_DBG_HPET_MEM_REG);
+ default:
+ return "UNKNOWN";
+ }
+}
+
+void iwl_dump_csr(struct iwl_priv *priv)
+{
+ int i;
+ u32 csr_tbl[] = {
+ CSR_HW_IF_CONFIG_REG,
+ CSR_INT_COALESCING,
+ CSR_INT,
+ CSR_INT_MASK,
+ CSR_FH_INT_STATUS,
+ CSR_GPIO_IN,
+ CSR_RESET,
+ CSR_GP_CNTRL,
+ CSR_HW_REV,
+ CSR_EEPROM_REG,
+ CSR_EEPROM_GP,
+ CSR_OTP_GP_REG,
+ CSR_GIO_REG,
+ CSR_GP_UCODE_REG,
+ CSR_GP_DRIVER_REG,
+ CSR_UCODE_DRV_GP1,
+ CSR_UCODE_DRV_GP2,
+ CSR_LED_REG,
+ CSR_DRAM_INT_TBL_REG,
+ CSR_GIO_CHICKEN_BITS,
+ CSR_ANA_PLL_CFG,
+ CSR_HW_REV_WA_REG,
+ CSR_DBG_HPET_MEM_REG
+ };
+ IWL_ERR(priv, "CSR values:\n");
+ IWL_ERR(priv, "(2nd byte of CSR_INT_COALESCING is "
+ "CSR_INT_PERIODIC_REG)\n");
+ for (i = 0; i < ARRAY_SIZE(csr_tbl); i++) {
+ IWL_ERR(priv, " %25s: 0X%08x\n",
+ get_csr_string(csr_tbl[i]),
+ iwl_read32(priv, csr_tbl[i]));
+ }
+}
+
+static const char *get_fh_string(int cmd)
+{
+ switch (cmd) {
+ IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG);
+ IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG);
+ IWL_CMD(FH_RSCSR_CHNL0_WPTR);
+ IWL_CMD(FH_MEM_RCSR_CHNL0_CONFIG_REG);
+ IWL_CMD(FH_MEM_RSSR_SHARED_CTRL_REG);
+ IWL_CMD(FH_MEM_RSSR_RX_STATUS_REG);
+ IWL_CMD(FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV);
+ IWL_CMD(FH_TSSR_TX_STATUS_REG);
+ IWL_CMD(FH_TSSR_TX_ERROR_REG);
+ default:
+ return "UNKNOWN";
+ }
+}
+
+int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display)
+{
+ int i;
+#ifdef CONFIG_IWLWIFI_DEBUG
+ int pos = 0;
+ size_t bufsz = 0;
+#endif
+ u32 fh_tbl[] = {
+ FH_RSCSR_CHNL0_STTS_WPTR_REG,
+ FH_RSCSR_CHNL0_RBDCB_BASE_REG,
+ FH_RSCSR_CHNL0_WPTR,
+ FH_MEM_RCSR_CHNL0_CONFIG_REG,
+ FH_MEM_RSSR_SHARED_CTRL_REG,
+ FH_MEM_RSSR_RX_STATUS_REG,
+ FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV,
+ FH_TSSR_TX_STATUS_REG,
+ FH_TSSR_TX_ERROR_REG
+ };
+#ifdef CONFIG_IWLWIFI_DEBUG
+ if (display) {
+ bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40;
+ *buf = kmalloc(bufsz, GFP_KERNEL);
+ if (!*buf)
+ return -ENOMEM;
+ pos += scnprintf(*buf + pos, bufsz - pos,
+ "FH register values:\n");
+ for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) {
+ pos += scnprintf(*buf + pos, bufsz - pos,
+ " %34s: 0X%08x\n",
+ get_fh_string(fh_tbl[i]),
+ iwl_read_direct32(priv, fh_tbl[i]));
+ }
+ return pos;
+ }
+#endif
+ IWL_ERR(priv, "FH register values:\n");
+ for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) {
+ IWL_ERR(priv, " %34s: 0X%08x\n",
+ get_fh_string(fh_tbl[i]),
+ iwl_read_direct32(priv, fh_tbl[i]));
+ }
+ return 0;
+}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index 23e5c42e7d7e..065553629de5 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -39,6 +39,7 @@
#include "iwl-dev.h"
#include "iwl-sta.h"
#include "iwl-core.h"
+#include "iwl-agn.h"
#define RS_NAME "iwl-agn-rs"
@@ -76,12 +77,81 @@ static const u8 ant_toggle_lookup[] = {
/*ANT_ABC -> */ ANT_ABC,
};
+#define IWL_DECLARE_RATE_INFO(r, s, ip, in, rp, rn, pp, np) \
+ [IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \
+ IWL_RATE_SISO_##s##M_PLCP, \
+ IWL_RATE_MIMO2_##s##M_PLCP,\
+ IWL_RATE_MIMO3_##s##M_PLCP,\
+ IWL_RATE_##r##M_IEEE, \
+ IWL_RATE_##ip##M_INDEX, \
+ IWL_RATE_##in##M_INDEX, \
+ IWL_RATE_##rp##M_INDEX, \
+ IWL_RATE_##rn##M_INDEX, \
+ IWL_RATE_##pp##M_INDEX, \
+ IWL_RATE_##np##M_INDEX }
+
+/*
+ * Parameter order:
+ * rate, ht rate, prev rate, next rate, prev tgg rate, next tgg rate
+ *
+ * If there isn't a valid next or previous rate then INV is used which
+ * maps to IWL_RATE_INVALID
+ *
+ */
+const struct iwl_rate_info iwl_rates[IWL_RATE_COUNT] = {
+ IWL_DECLARE_RATE_INFO(1, INV, INV, 2, INV, 2, INV, 2), /* 1mbps */
+ IWL_DECLARE_RATE_INFO(2, INV, 1, 5, 1, 5, 1, 5), /* 2mbps */
+ IWL_DECLARE_RATE_INFO(5, INV, 2, 6, 2, 11, 2, 11), /*5.5mbps */
+ IWL_DECLARE_RATE_INFO(11, INV, 9, 12, 9, 12, 5, 18), /* 11mbps */
+ IWL_DECLARE_RATE_INFO(6, 6, 5, 9, 5, 11, 5, 11), /* 6mbps */
+ IWL_DECLARE_RATE_INFO(9, 6, 6, 11, 6, 11, 5, 11), /* 9mbps */
+ IWL_DECLARE_RATE_INFO(12, 12, 11, 18, 11, 18, 11, 18), /* 12mbps */
+ IWL_DECLARE_RATE_INFO(18, 18, 12, 24, 12, 24, 11, 24), /* 18mbps */
+ IWL_DECLARE_RATE_INFO(24, 24, 18, 36, 18, 36, 18, 36), /* 24mbps */
+ IWL_DECLARE_RATE_INFO(36, 36, 24, 48, 24, 48, 24, 48), /* 36mbps */
+ IWL_DECLARE_RATE_INFO(48, 48, 36, 54, 36, 54, 36, 54), /* 48mbps */
+ IWL_DECLARE_RATE_INFO(54, 54, 48, INV, 48, INV, 48, INV),/* 54mbps */
+ IWL_DECLARE_RATE_INFO(60, 60, 48, INV, 48, INV, 48, INV),/* 60mbps */
+ /* FIXME:RS: ^^ should be INV (legacy) */
+};
+
+static int iwl_hwrate_to_plcp_idx(u32 rate_n_flags)
+{
+ int idx = 0;
+
+ /* HT rate format */
+ if (rate_n_flags & RATE_MCS_HT_MSK) {
+ idx = (rate_n_flags & 0xff);
+
+ if (idx >= IWL_RATE_MIMO3_6M_PLCP)
+ idx = idx - IWL_RATE_MIMO3_6M_PLCP;
+ else if (idx >= IWL_RATE_MIMO2_6M_PLCP)
+ idx = idx - IWL_RATE_MIMO2_6M_PLCP;
+
+ idx += IWL_FIRST_OFDM_RATE;
+ /* skip 9M not supported in ht*/
+ if (idx >= IWL_RATE_9M_INDEX)
+ idx += 1;
+ if ((idx >= IWL_FIRST_OFDM_RATE) && (idx <= IWL_LAST_OFDM_RATE))
+ return idx;
+
+ /* legacy rate format, search for match in table */
+ } else {
+ for (idx = 0; idx < ARRAY_SIZE(iwl_rates); idx++)
+ if (iwl_rates[idx].plcp == (rate_n_flags & 0xFF))
+ return idx;
+ }
+
+ return -1;
+}
+
static void rs_rate_scale_perform(struct iwl_priv *priv,
struct sk_buff *skb,
struct ieee80211_sta *sta,
struct iwl_lq_sta *lq_sta);
static void rs_fill_link_cmd(struct iwl_priv *priv,
struct iwl_lq_sta *lq_sta, u32 rate_n_flags);
+static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search);
#ifdef CONFIG_MAC80211_DEBUGFS
@@ -300,7 +370,19 @@ static int rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv,
struct ieee80211_sta *sta)
{
int ret = -EAGAIN;
- u32 load = rs_tl_get_load(lq_data, tid);
+ u32 load;
+
+ /*
+ * Don't create TX aggregation sessions when in high
+ * BT traffic, as they would just be disrupted by BT.
+ */
+ if (priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH) {
+ IWL_ERR(priv, "BT traffic (%d), no aggregation allowed\n",
+ priv->bt_traffic_load);
+ return ret;
+ }
+
+ load = rs_tl_get_load(lq_data, tid);
if (load > IWL_AGG_LOAD_THRESHOLD) {
IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n",
@@ -502,6 +584,7 @@ static int rs_get_tbl_info_from_mcs(const u32 rate_n_flags,
u8 num_of_ant = get_num_of_ant_from_rate(rate_n_flags);
u8 mcs;
+ memset(tbl, 0, sizeof(struct iwl_scale_tbl_info));
*rate_idx = iwl_hwrate_to_plcp_idx(rate_n_flags);
if (*rate_idx == IWL_RATE_INVALID) {
@@ -588,11 +671,13 @@ static int rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags,
* Green-field mode is valid if the station supports it and
* there are no non-GF stations present in the BSS.
*/
-static inline u8 rs_use_green(struct ieee80211_sta *sta,
- struct iwl_ht_config *ht_conf)
+static bool rs_use_green(struct ieee80211_sta *sta)
{
+ struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
+ struct iwl_rxon_context *ctx = sta_priv->common.ctx;
+
return (sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) &&
- !(ht_conf->non_GF_STA_present);
+ !(ctx->ht.non_gf_sta_present);
}
/**
@@ -744,6 +829,32 @@ static bool table_type_matches(struct iwl_scale_tbl_info *a,
(a->is_SGI == b->is_SGI);
}
+static void rs_bt_update_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
+ struct iwl_lq_sta *lq_sta)
+{
+ struct iwl_scale_tbl_info *tbl;
+ bool full_concurrent;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ if (priv->bt_ci_compliance && priv->bt_ant_couple_ok)
+ full_concurrent = true;
+ else
+ full_concurrent = false;
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ if (priv->bt_full_concurrent != full_concurrent) {
+ priv->bt_full_concurrent = full_concurrent;
+
+ /* Update uCode's rate table. */
+ tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
+ rs_fill_link_cmd(priv, lq_sta, tbl->current_rate);
+ iwl_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_ASYNC, false);
+
+ queue_work(priv->workqueue, &priv->bt_full_concurrency);
+ }
+}
+
/*
* mac80211 sends us Tx status
*/
@@ -763,6 +874,8 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
u32 tx_rate;
struct iwl_scale_tbl_info tbl_type;
struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl;
+ struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
+ struct iwl_rxon_context *ctx = sta_priv->common.ctx;
IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n");
@@ -829,7 +942,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
lq_sta->missed_rate_counter++;
if (lq_sta->missed_rate_counter > IWL_MISSED_RATE_MAX) {
lq_sta->missed_rate_counter = 0;
- iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC, false);
+ iwl_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_ASYNC, false);
}
/* Regardless, ignore this status info for outdated rate */
return;
@@ -848,7 +961,20 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
other_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
} else {
IWL_DEBUG_RATE(priv, "Neither active nor search matches tx rate\n");
- return;
+ tmp_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
+ IWL_DEBUG_RATE(priv, "active- lq:%x, ant:%x, SGI:%d\n",
+ tmp_tbl->lq_type, tmp_tbl->ant_type, tmp_tbl->is_SGI);
+ tmp_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]);
+ IWL_DEBUG_RATE(priv, "search- lq:%x, ant:%x, SGI:%d\n",
+ tmp_tbl->lq_type, tmp_tbl->ant_type, tmp_tbl->is_SGI);
+ IWL_DEBUG_RATE(priv, "actual- lq:%x, ant:%x, SGI:%d\n",
+ tbl_type.lq_type, tbl_type.ant_type, tbl_type.is_SGI);
+ /*
+ * no matching table found, let's by-pass the data collection
+ * and continue to perform rate scale to find the rate table
+ */
+ rs_stay_in_table(lq_sta, true);
+ goto done;
}
/*
@@ -909,10 +1035,14 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
}
/* The last TX rate is cached in lq_sta; it's set in if/else above */
lq_sta->last_rate_n_flags = tx_rate;
-
+done:
/* See if there's a better rate or modulation mode to try. */
if (sta && sta->supp_rates[sband->band])
rs_rate_scale_perform(priv, skb, sta, lq_sta);
+
+ /* Is there a need to switch between full concurrency and 3-wire? */
+ if (priv->bt_ant_couple_ok)
+ rs_bt_update_lq(priv, ctx, lq_sta);
}
/*
@@ -1106,6 +1236,8 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv,
u16 rate_mask;
s32 rate;
s8 is_green = lq_sta->is_green;
+ struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
+ struct iwl_rxon_context *ctx = sta_priv->common.ctx;
if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported)
return -1;
@@ -1126,7 +1258,7 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv,
tbl->max_search = IWL_MAX_SEARCH;
rate_mask = lq_sta->active_mimo2_rate;
- if (iwl_is_ht40_tx_allowed(priv, &sta->ht_cap))
+ if (iwl_is_ht40_tx_allowed(priv, ctx, &sta->ht_cap))
tbl->is_ht40 = 1;
else
tbl->is_ht40 = 0;
@@ -1160,6 +1292,8 @@ static int rs_switch_to_mimo3(struct iwl_priv *priv,
u16 rate_mask;
s32 rate;
s8 is_green = lq_sta->is_green;
+ struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
+ struct iwl_rxon_context *ctx = sta_priv->common.ctx;
if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported)
return -1;
@@ -1180,7 +1314,7 @@ static int rs_switch_to_mimo3(struct iwl_priv *priv,
tbl->max_search = IWL_MAX_11N_MIMO3_SEARCH;
rate_mask = lq_sta->active_mimo3_rate;
- if (iwl_is_ht40_tx_allowed(priv, &sta->ht_cap))
+ if (iwl_is_ht40_tx_allowed(priv, ctx, &sta->ht_cap))
tbl->is_ht40 = 1;
else
tbl->is_ht40 = 0;
@@ -1215,6 +1349,8 @@ static int rs_switch_to_siso(struct iwl_priv *priv,
u16 rate_mask;
u8 is_green = lq_sta->is_green;
s32 rate;
+ struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
+ struct iwl_rxon_context *ctx = sta_priv->common.ctx;
if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported)
return -1;
@@ -1227,7 +1363,7 @@ static int rs_switch_to_siso(struct iwl_priv *priv,
tbl->max_search = IWL_MAX_SEARCH;
rate_mask = lq_sta->active_siso_rate;
- if (iwl_is_ht40_tx_allowed(priv, &sta->ht_cap))
+ if (iwl_is_ht40_tx_allowed(priv, ctx, &sta->ht_cap))
tbl->is_ht40 = 1;
else
tbl->is_ht40 = 0;
@@ -1265,18 +1401,52 @@ static int rs_move_legacy_other(struct iwl_priv *priv,
struct iwl_rate_scale_data *window = &(tbl->win[index]);
u32 sz = (sizeof(struct iwl_scale_tbl_info) -
(sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
- u8 start_action = tbl->action;
+ u8 start_action;
u8 valid_tx_ant = priv->hw_params.valid_tx_ant;
u8 tx_chains_num = priv->hw_params.tx_chains_num;
int ret = 0;
u8 update_search_tbl_counter = 0;
+ switch (priv->bt_traffic_load) {
+ case IWL_BT_COEX_TRAFFIC_LOAD_NONE:
+ /* nothing */
+ break;
+ case IWL_BT_COEX_TRAFFIC_LOAD_LOW:
+ /* avoid antenna B unless MIMO */
+ valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant);
+ if (tbl->action == IWL_LEGACY_SWITCH_ANTENNA2)
+ tbl->action = IWL_LEGACY_SWITCH_ANTENNA1;
+ break;
+ case IWL_BT_COEX_TRAFFIC_LOAD_HIGH:
+ case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS:
+ /* avoid antenna B and MIMO */
+ valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant);
+ if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2 &&
+ tbl->action != IWL_LEGACY_SWITCH_SISO)
+ tbl->action = IWL_LEGACY_SWITCH_SISO;
+ break;
+ default:
+ IWL_ERR(priv, "Invalid BT load %d", priv->bt_traffic_load);
+ break;
+ }
+
if (!iwl_ht_enabled(priv))
/* stay in Legacy */
tbl->action = IWL_LEGACY_SWITCH_ANTENNA1;
else if (iwl_tx_ant_restriction(priv) == IWL_ANT_OK_SINGLE &&
tbl->action > IWL_LEGACY_SWITCH_SISO)
tbl->action = IWL_LEGACY_SWITCH_SISO;
+
+ /* configure as 1x1 if bt full concurrency */
+ if (priv->bt_full_concurrent) {
+ if (!iwl_ht_enabled(priv))
+ tbl->action = IWL_LEGACY_SWITCH_ANTENNA1;
+ else if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2)
+ tbl->action = IWL_LEGACY_SWITCH_SISO;
+ valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant);
+ }
+
+ start_action = tbl->action;
for (; ;) {
lq_sta->action_counter++;
switch (tbl->action) {
@@ -1291,7 +1461,10 @@ static int rs_move_legacy_other(struct iwl_priv *priv,
break;
/* Don't change antenna if success has been great */
- if (window->success_ratio >= IWL_RS_GOOD_RATIO)
+ if (window->success_ratio >= IWL_RS_GOOD_RATIO &&
+ !priv->bt_full_concurrent &&
+ priv->bt_traffic_load ==
+ IWL_BT_COEX_TRAFFIC_LOAD_NONE)
break;
/* Set up search table to try other antenna */
@@ -1403,31 +1576,64 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
u32 sz = (sizeof(struct iwl_scale_tbl_info) -
(sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
- u8 start_action = tbl->action;
+ u8 start_action;
u8 valid_tx_ant = priv->hw_params.valid_tx_ant;
u8 tx_chains_num = priv->hw_params.tx_chains_num;
u8 update_search_tbl_counter = 0;
int ret;
+ switch (priv->bt_traffic_load) {
+ case IWL_BT_COEX_TRAFFIC_LOAD_NONE:
+ /* nothing */
+ break;
+ case IWL_BT_COEX_TRAFFIC_LOAD_LOW:
+ /* avoid antenna B unless MIMO */
+ valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant);
+ if (tbl->action == IWL_SISO_SWITCH_ANTENNA2)
+ tbl->action = IWL_SISO_SWITCH_ANTENNA1;
+ break;
+ case IWL_BT_COEX_TRAFFIC_LOAD_HIGH:
+ case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS:
+ /* avoid antenna B and MIMO */
+ valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant);
+ if (tbl->action != IWL_SISO_SWITCH_ANTENNA1)
+ tbl->action = IWL_SISO_SWITCH_ANTENNA1;
+ break;
+ default:
+ IWL_ERR(priv, "Invalid BT load %d", priv->bt_traffic_load);
+ break;
+ }
+
if (iwl_tx_ant_restriction(priv) == IWL_ANT_OK_SINGLE &&
tbl->action > IWL_SISO_SWITCH_ANTENNA2) {
/* stay in SISO */
tbl->action = IWL_SISO_SWITCH_ANTENNA1;
}
+
+ /* configure as 1x1 if bt full concurrency */
+ if (priv->bt_full_concurrent) {
+ valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant);
+ if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2)
+ tbl->action = IWL_SISO_SWITCH_ANTENNA1;
+ }
+
+ start_action = tbl->action;
for (;;) {
lq_sta->action_counter++;
switch (tbl->action) {
case IWL_SISO_SWITCH_ANTENNA1:
case IWL_SISO_SWITCH_ANTENNA2:
IWL_DEBUG_RATE(priv, "LQ: SISO toggle Antenna\n");
-
if ((tbl->action == IWL_SISO_SWITCH_ANTENNA1 &&
- tx_chains_num <= 1) ||
+ tx_chains_num <= 1) ||
(tbl->action == IWL_SISO_SWITCH_ANTENNA2 &&
- tx_chains_num <= 2))
+ tx_chains_num <= 2))
break;
- if (window->success_ratio >= IWL_RS_GOOD_RATIO)
+ if (window->success_ratio >= IWL_RS_GOOD_RATIO &&
+ !priv->bt_full_concurrent &&
+ priv->bt_traffic_load ==
+ IWL_BT_COEX_TRAFFIC_LOAD_NONE)
break;
memcpy(search_tbl, tbl, sz);
@@ -1541,18 +1747,47 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv,
struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
u32 sz = (sizeof(struct iwl_scale_tbl_info) -
(sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
- u8 start_action = tbl->action;
+ u8 start_action;
u8 valid_tx_ant = priv->hw_params.valid_tx_ant;
u8 tx_chains_num = priv->hw_params.tx_chains_num;
u8 update_search_tbl_counter = 0;
int ret;
+ switch (priv->bt_traffic_load) {
+ case IWL_BT_COEX_TRAFFIC_LOAD_NONE:
+ /* nothing */
+ break;
+ case IWL_BT_COEX_TRAFFIC_LOAD_HIGH:
+ case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS:
+ /* avoid antenna B and MIMO */
+ if (tbl->action != IWL_MIMO2_SWITCH_SISO_A)
+ tbl->action = IWL_MIMO2_SWITCH_SISO_A;
+ break;
+ case IWL_BT_COEX_TRAFFIC_LOAD_LOW:
+ /* avoid antenna B unless MIMO */
+ if (tbl->action == IWL_MIMO2_SWITCH_SISO_B ||
+ tbl->action == IWL_MIMO2_SWITCH_SISO_C)
+ tbl->action = IWL_MIMO2_SWITCH_SISO_A;
+ break;
+ default:
+ IWL_ERR(priv, "Invalid BT load %d", priv->bt_traffic_load);
+ break;
+ }
+
if ((iwl_tx_ant_restriction(priv) == IWL_ANT_OK_SINGLE) &&
(tbl->action < IWL_MIMO2_SWITCH_SISO_A ||
tbl->action > IWL_MIMO2_SWITCH_SISO_C)) {
/* switch in SISO */
tbl->action = IWL_MIMO2_SWITCH_SISO_A;
}
+
+ /* configure as 1x1 if bt full concurrency */
+ if (priv->bt_full_concurrent &&
+ (tbl->action < IWL_MIMO2_SWITCH_SISO_A ||
+ tbl->action > IWL_MIMO2_SWITCH_SISO_C))
+ tbl->action = IWL_MIMO2_SWITCH_SISO_A;
+
+ start_action = tbl->action;
for (;;) {
lq_sta->action_counter++;
switch (tbl->action) {
@@ -1682,18 +1917,47 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv,
struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
u32 sz = (sizeof(struct iwl_scale_tbl_info) -
(sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
- u8 start_action = tbl->action;
+ u8 start_action;
u8 valid_tx_ant = priv->hw_params.valid_tx_ant;
u8 tx_chains_num = priv->hw_params.tx_chains_num;
int ret;
u8 update_search_tbl_counter = 0;
+ switch (priv->bt_traffic_load) {
+ case IWL_BT_COEX_TRAFFIC_LOAD_NONE:
+ /* nothing */
+ break;
+ case IWL_BT_COEX_TRAFFIC_LOAD_HIGH:
+ case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS:
+ /* avoid antenna B and MIMO */
+ if (tbl->action != IWL_MIMO3_SWITCH_SISO_A)
+ tbl->action = IWL_MIMO3_SWITCH_SISO_A;
+ break;
+ case IWL_BT_COEX_TRAFFIC_LOAD_LOW:
+ /* avoid antenna B unless MIMO */
+ if (tbl->action == IWL_MIMO3_SWITCH_SISO_B ||
+ tbl->action == IWL_MIMO3_SWITCH_SISO_C)
+ tbl->action = IWL_MIMO3_SWITCH_SISO_A;
+ break;
+ default:
+ IWL_ERR(priv, "Invalid BT load %d", priv->bt_traffic_load);
+ break;
+ }
+
if ((iwl_tx_ant_restriction(priv) == IWL_ANT_OK_SINGLE) &&
(tbl->action < IWL_MIMO3_SWITCH_SISO_A ||
tbl->action > IWL_MIMO3_SWITCH_SISO_C)) {
/* switch in SISO */
tbl->action = IWL_MIMO3_SWITCH_SISO_A;
}
+
+ /* configure as 1x1 if bt full concurrency */
+ if (priv->bt_full_concurrent &&
+ (tbl->action < IWL_MIMO3_SWITCH_SISO_A ||
+ tbl->action > IWL_MIMO3_SWITCH_SISO_C))
+ tbl->action = IWL_MIMO3_SWITCH_SISO_A;
+
+ start_action = tbl->action;
for (;;) {
lq_sta->action_counter++;
switch (tbl->action) {
@@ -1820,7 +2084,7 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv,
* 2) # times calling this function
* 3) elapsed time in this mode (not used, for now)
*/
-static void rs_stay_in_table(struct iwl_lq_sta *lq_sta)
+static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search)
{
struct iwl_scale_tbl_info *tbl;
int i;
@@ -1851,7 +2115,8 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta)
* allow a new search. Also (below) reset all bitmaps and
* stats in active history.
*/
- if ((lq_sta->total_failed > lq_sta->max_failure_limit) ||
+ if (force_search ||
+ (lq_sta->total_failed > lq_sta->max_failure_limit) ||
(lq_sta->total_success > lq_sta->max_success_limit) ||
((!lq_sta->search_better_tbl) && (lq_sta->flush_timer)
&& (flush_interval_passed))) {
@@ -1900,6 +2165,7 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta)
* return rate_n_flags as used in the table
*/
static u32 rs_update_rate_tbl(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx,
struct iwl_lq_sta *lq_sta,
struct iwl_scale_tbl_info *tbl,
int index, u8 is_green)
@@ -1909,7 +2175,7 @@ static u32 rs_update_rate_tbl(struct iwl_priv *priv,
/* Update uCode's rate table. */
rate = rate_n_flags_from_tbl(priv, tbl, index, is_green);
rs_fill_link_cmd(priv, lq_sta, rate);
- iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC, false);
+ iwl_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_ASYNC, false);
return rate;
}
@@ -1948,6 +2214,8 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
s32 sr;
u8 tid = MAX_TID_COUNT;
struct iwl_tid_data *tid_data;
+ struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
+ struct iwl_rxon_context *ctx = sta_priv->common.ctx;
IWL_DEBUG_RATE(priv, "rate scale calculate new rate for skb\n");
@@ -1986,7 +2254,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
if (is_legacy(tbl->lq_type))
lq_sta->is_green = 0;
else
- lq_sta->is_green = rs_use_green(sta, &priv->current_ht_config);
+ lq_sta->is_green = rs_use_green(sta);
is_green = lq_sta->is_green;
/* current tx rate */
@@ -2025,7 +2293,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
/* get "active" rate info */
index = iwl_hwrate_to_plcp_idx(tbl->current_rate);
- rate = rs_update_rate_tbl(priv, lq_sta,
+ rate = rs_update_rate_tbl(priv, ctx, lq_sta,
tbl, index, is_green);
}
return;
@@ -2067,7 +2335,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
/* Should we stay with this modulation mode,
* or search for a new one? */
- rs_stay_in_table(lq_sta);
+ rs_stay_in_table(lq_sta, false);
goto out;
}
@@ -2215,6 +2483,28 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
if (iwl_tx_ant_restriction(priv) != IWL_ANT_OK_MULTI &&
(is_mimo2(tbl->lq_type) || is_mimo3(tbl->lq_type)))
scale_action = -1;
+
+ if ((priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH) &&
+ (is_mimo2(tbl->lq_type) || is_mimo3(tbl->lq_type))) {
+ if (lq_sta->last_bt_traffic > priv->bt_traffic_load) {
+ /*
+ * don't set scale_action, don't want to scale up if
+ * the rate scale doesn't otherwise think that is a
+ * good idea.
+ */
+ } else if (lq_sta->last_bt_traffic <= priv->bt_traffic_load) {
+ scale_action = -1;
+ }
+ }
+ lq_sta->last_bt_traffic = priv->bt_traffic_load;
+
+ if ((priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH) &&
+ (is_mimo2(tbl->lq_type) || is_mimo3(tbl->lq_type))) {
+ /* search for a new modulation */
+ rs_stay_in_table(lq_sta, true);
+ goto lq_update;
+ }
+
switch (scale_action) {
case -1:
/* Decrease starting rate, update uCode's rate table */
@@ -2245,13 +2535,13 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
lq_update:
/* Replace uCode's rate table for the destination station. */
if (update_lq)
- rate = rs_update_rate_tbl(priv, lq_sta,
+ rate = rs_update_rate_tbl(priv, ctx, lq_sta,
tbl, index, is_green);
if (iwl_tx_ant_restriction(priv) == IWL_ANT_OK_MULTI) {
/* Should we stay with this modulation mode,
* or search for a new one? */
- rs_stay_in_table(lq_sta);
+ rs_stay_in_table(lq_sta, false);
}
/*
* Search for new modulation mode if we're:
@@ -2287,7 +2577,7 @@ lq_update:
IWL_DEBUG_RATE(priv, "Switch current mcs: %X index: %d\n",
tbl->current_rate, index);
rs_fill_link_cmd(priv, lq_sta, tbl->current_rate);
- iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC, false);
+ iwl_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_ASYNC, false);
} else
done_search = 1;
}
@@ -2357,12 +2647,17 @@ static void rs_initialize_lq(struct iwl_priv *priv,
int rate_idx;
int i;
u32 rate;
- u8 use_green = rs_use_green(sta, &priv->current_ht_config);
+ u8 use_green = rs_use_green(sta);
u8 active_tbl = 0;
u8 valid_tx_ant;
+ struct iwl_station_priv *sta_priv;
+ struct iwl_rxon_context *ctx;
if (!sta || !lq_sta)
- goto out;
+ return;
+
+ sta_priv = (void *)sta->drv_priv;
+ ctx = sta_priv->common.ctx;
i = lq_sta->last_txrate_idx;
@@ -2394,9 +2689,7 @@ static void rs_initialize_lq(struct iwl_priv *priv,
rs_set_expected_tpt_table(lq_sta, tbl);
rs_fill_link_cmd(NULL, lq_sta, rate);
priv->stations[lq_sta->lq.sta_id].lq = &lq_sta->lq;
- iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_SYNC, true);
- out:
- return;
+ iwl_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_SYNC, true);
}
static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta,
@@ -2524,7 +2817,7 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i
lq_sta->is_dup = 0;
lq_sta->max_rate_idx = -1;
lq_sta->missed_rate_counter = IWL_MISSED_RATE_MAX;
- lq_sta->is_green = rs_use_green(sta, &priv->current_ht_config);
+ lq_sta->is_green = rs_use_green(sta);
lq_sta->active_legacy_rate = priv->active_rate & ~(0x1000);
lq_sta->band = priv->band;
/*
@@ -2594,10 +2887,15 @@ static void rs_fill_link_cmd(struct iwl_priv *priv,
rs_dbgfs_set_mcs(lq_sta, &new_rate, index);
/* Interpret new_rate (rate_n_flags) */
- memset(&tbl_type, 0, sizeof(tbl_type));
rs_get_tbl_info_from_mcs(new_rate, lq_sta->band,
&tbl_type, &rate_idx);
+ if (priv && priv->bt_full_concurrent) {
+ /* 1x1 only */
+ tbl_type.ant_type =
+ first_antenna(priv->hw_params.valid_tx_ant);
+ }
+
/* How many times should we repeat the initial rate? */
if (is_legacy(tbl_type.lq_type)) {
ant_toggle_cnt = 1;
@@ -2622,9 +2920,12 @@ static void rs_fill_link_cmd(struct iwl_priv *priv,
index++;
repeat_rate--;
-
- if (priv)
- valid_tx_ant = priv->hw_params.valid_tx_ant;
+ if (priv) {
+ if (priv->bt_full_concurrent)
+ valid_tx_ant = ANT_A;
+ else
+ valid_tx_ant = priv->hw_params.valid_tx_ant;
+ }
/* Fill rest of rate table */
while (index < LINK_QUAL_MAX_RETRY_NUM) {
@@ -2639,7 +2940,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv,
rs_toggle_antenna(valid_tx_ant,
&new_rate, &tbl_type))
ant_toggle_cnt = 1;
-}
+ }
/* Override next rate if needed for debug purposes */
rs_dbgfs_set_mcs(lq_sta, &new_rate, index);
@@ -2654,6 +2955,12 @@ static void rs_fill_link_cmd(struct iwl_priv *priv,
rs_get_tbl_info_from_mcs(new_rate, lq_sta->band, &tbl_type,
&rate_idx);
+ if (priv && priv->bt_full_concurrent) {
+ /* 1x1 only */
+ tbl_type.ant_type =
+ first_antenna(priv->hw_params.valid_tx_ant);
+ }
+
/* Indicate to uCode which entries might be MIMO.
* If initial rate was MIMO, this will finally end up
* as (IWL_HT_NUMBER_TRY * 2), after 2nd pass, otherwise 0. */
@@ -2694,8 +3001,21 @@ static void rs_fill_link_cmd(struct iwl_priv *priv,
lq_cmd->agg_params.agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_DEF;
lq_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF;
+
lq_cmd->agg_params.agg_time_limit =
cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF);
+ /*
+ * overwrite if needed, pass aggregation time limit
+ * to uCode in uSec
+ */
+ if (priv && priv->cfg->bt_params &&
+ priv->cfg->bt_params->agg_time_limit &&
+ priv->cfg->bt_params->agg_time_limit >=
+ LINK_QUAL_AGG_TIME_LIMIT_MIN &&
+ priv->cfg->bt_params->agg_time_limit <=
+ LINK_QUAL_AGG_TIME_LIMIT_MAX)
+ lq_cmd->agg_params.agg_time_limit =
+ cpu_to_le16(priv->cfg->bt_params->agg_time_limit);
}
static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
@@ -2760,6 +3080,9 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file,
char buf[64];
int buf_size;
u32 parsed_rate;
+ struct iwl_station_priv *sta_priv =
+ container_of(lq_sta, struct iwl_station_priv, lq_sta);
+ struct iwl_rxon_context *ctx = sta_priv->common.ctx;
priv = lq_sta->drv;
memset(buf, 0, sizeof(buf));
@@ -2782,7 +3105,8 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file,
if (lq_sta->dbg_fixed_rate) {
rs_fill_link_cmd(NULL, lq_sta, lq_sta->dbg_fixed_rate);
- iwl_send_lq_cmd(lq_sta->drv, &lq_sta->lq, CMD_ASYNC, false);
+ iwl_send_lq_cmd(lq_sta->drv, ctx, &lq_sta->lq, CMD_ASYNC,
+ false);
}
return count;
@@ -2873,6 +3197,7 @@ static const struct file_operations rs_sta_dbgfs_scale_table_ops = {
.write = rs_sta_dbgfs_scale_table_write,
.read = rs_sta_dbgfs_scale_table_read,
.open = open_file_generic,
+ .llseek = default_llseek,
};
static ssize_t rs_sta_dbgfs_stats_table_read(struct file *file,
char __user *user_buf, size_t count, loff_t *ppos)
@@ -2915,6 +3240,7 @@ static ssize_t rs_sta_dbgfs_stats_table_read(struct file *file,
static const struct file_operations rs_sta_dbgfs_stats_table_ops = {
.read = rs_sta_dbgfs_stats_table_read,
.open = open_file_generic,
+ .llseek = default_llseek,
};
static ssize_t rs_sta_dbgfs_rate_scale_data_read(struct file *file,
@@ -2946,6 +3272,7 @@ static ssize_t rs_sta_dbgfs_rate_scale_data_read(struct file *file,
static const struct file_operations rs_sta_dbgfs_rate_scale_data_ops = {
.read = rs_sta_dbgfs_rate_scale_data_read,
.open = open_file_generic,
+ .llseek = default_llseek,
};
static void rs_add_debugfs(void *priv, void *priv_sta,
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h
index 8292f6d48ec6..75e50d33ecb3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h
@@ -299,7 +299,6 @@ enum {
#define TIME_WRAP_AROUND(x, y) (((y) > (x)) ? (y) - (x) : (0-(x)) + (y))
extern const struct iwl_rate_info iwl_rates[IWL_RATE_COUNT];
-extern const struct iwl3945_rate_info iwl3945_rates[IWL_RATE_COUNT_3945];
enum iwl_table_type {
LQ_NONE,
@@ -432,6 +431,8 @@ struct iwl_lq_sta {
u32 last_rate_n_flags;
/* packets destined for this STA are aggregated */
u8 is_agg;
+ /* BT traffic this sta was last updated in */
+ u8 last_bt_traffic;
};
static inline u8 num_of_ant(u8 mask)
@@ -451,24 +452,6 @@ static inline u8 first_antenna(u8 mask)
}
-static inline u8 iwl_get_prev_ieee_rate(u8 rate_index)
-{
- u8 rate = iwl_rates[rate_index].prev_ieee;
-
- if (rate == IWL_RATE_INVALID)
- rate = rate_index;
- return rate;
-}
-
-static inline u8 iwl3945_get_prev_ieee_rate(u8 rate_index)
-{
- u8 rate = iwl3945_rates[rate_index].prev_ieee;
-
- if (rate == IWL_RATE_INVALID)
- rate = rate_index;
- return rate;
-}
-
/**
* iwl3945_rate_scale_init - Initialize the rate scale table based on assoc info
*
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
index 9490eced1198..bbd40b7dd597 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
@@ -34,7 +34,7 @@
#include "iwl-dev.h"
#include "iwl-core.h"
-#include "iwl-calib.h"
+#include "iwl-agn-calib.h"
#include "iwl-sta.h"
#include "iwl-io.h"
#include "iwl-helpers.h"
@@ -73,7 +73,8 @@ static void iwl_rx_calc_noise(struct iwl_priv *priv)
int bcn_silence_a, bcn_silence_b, bcn_silence_c;
int last_rx_noise;
- if (priv->cfg->bt_statistics)
+ if (priv->cfg->bt_params &&
+ priv->cfg->bt_params->bt_statistics)
rx_info = &(priv->_agn.statistics_bt.rx.general.common);
else
rx_info = &(priv->_agn.statistics.rx.general);
@@ -124,7 +125,8 @@ static void iwl_accumulative_statistics(struct iwl_priv *priv,
struct statistics_general_common *general, *accum_general;
struct statistics_tx *tx, *accum_tx;
- if (priv->cfg->bt_statistics) {
+ if (priv->cfg->bt_params &&
+ priv->cfg->bt_params->bt_statistics) {
prev_stats = (__le32 *)&priv->_agn.statistics_bt;
accum_stats = (u32 *)&priv->_agn.accum_statistics_bt;
size = sizeof(struct iwl_bt_notif_statistics);
@@ -183,7 +185,7 @@ bool iwl_good_plcp_health(struct iwl_priv *priv,
unsigned int plcp_msec;
unsigned long plcp_received_jiffies;
- if (priv->cfg->plcp_delta_threshold ==
+ if (priv->cfg->base_params->plcp_delta_threshold ==
IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE) {
IWL_DEBUG_RADIO(priv, "plcp_err check disabled\n");
return rc;
@@ -205,7 +207,8 @@ bool iwl_good_plcp_health(struct iwl_priv *priv,
struct statistics_rx_phy *ofdm;
struct statistics_rx_ht_phy *ofdm_ht;
- if (priv->cfg->bt_statistics) {
+ if (priv->cfg->bt_params &&
+ priv->cfg->bt_params->bt_statistics) {
ofdm = &pkt->u.stats_bt.rx.ofdm;
ofdm_ht = &pkt->u.stats_bt.rx.ofdm_ht;
combined_plcp_delta =
@@ -229,7 +232,7 @@ bool iwl_good_plcp_health(struct iwl_priv *priv,
if ((combined_plcp_delta > 0) &&
((combined_plcp_delta * 100) / plcp_msec) >
- priv->cfg->plcp_delta_threshold) {
+ priv->cfg->base_params->plcp_delta_threshold) {
/*
* if plcp_err exceed the threshold,
* the following data is printed in csv format:
@@ -242,13 +245,13 @@ bool iwl_good_plcp_health(struct iwl_priv *priv,
* plcp_msec
*/
IWL_DEBUG_RADIO(priv, "plcp_err exceeded %u, "
- "%u, %u, %u, %u, %d, %u mSecs\n",
- priv->cfg->plcp_delta_threshold,
- le32_to_cpu(ofdm->plcp_err),
- le32_to_cpu(ofdm->plcp_err),
- le32_to_cpu(ofdm_ht->plcp_err),
- le32_to_cpu(ofdm_ht->plcp_err),
- combined_plcp_delta, plcp_msec);
+ "%u, %u, %u, %u, %d, %u mSecs\n",
+ priv->cfg->base_params->plcp_delta_threshold,
+ le32_to_cpu(ofdm->plcp_err),
+ le32_to_cpu(ofdm->plcp_err),
+ le32_to_cpu(ofdm_ht->plcp_err),
+ le32_to_cpu(ofdm_ht->plcp_err),
+ combined_plcp_delta, plcp_msec);
rc = false;
}
@@ -262,7 +265,8 @@ void iwl_rx_statistics(struct iwl_priv *priv,
int change;
struct iwl_rx_packet *pkt = rxb_addr(rxb);
- if (priv->cfg->bt_statistics) {
+ if (priv->cfg->bt_params &&
+ priv->cfg->bt_params->bt_statistics) {
IWL_DEBUG_RX(priv,
"Statistics notification received (%d vs %d).\n",
(int)sizeof(struct iwl_bt_notif_statistics),
@@ -300,7 +304,8 @@ void iwl_rx_statistics(struct iwl_priv *priv,
iwl_recover_from_statistics(priv, pkt);
- if (priv->cfg->bt_statistics)
+ if (priv->cfg->bt_params &&
+ priv->cfg->bt_params->bt_statistics)
memcpy(&priv->_agn.statistics_bt, &pkt->u.stats_bt,
sizeof(priv->_agn.statistics_bt));
else
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c
new file mode 100644
index 000000000000..35a30d2e0734
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c
@@ -0,0 +1,716 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
+ *
+ * Portions of this file are derived from the ipw3945 project, as well
+ * as portions of the ieee80211 subsystem header files.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#include <net/mac80211.h>
+
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-sta.h"
+#include "iwl-agn.h"
+
+static struct iwl_link_quality_cmd *
+iwl_sta_alloc_lq(struct iwl_priv *priv, u8 sta_id)
+{
+ int i, r;
+ struct iwl_link_quality_cmd *link_cmd;
+ u32 rate_flags = 0;
+ __le32 rate_n_flags;
+
+ link_cmd = kzalloc(sizeof(struct iwl_link_quality_cmd), GFP_KERNEL);
+ if (!link_cmd) {
+ IWL_ERR(priv, "Unable to allocate memory for LQ cmd.\n");
+ return NULL;
+ }
+ /* Set up the rate scaling to start at selected rate, fall back
+ * all the way down to 1M in IEEE order, and then spin on 1M */
+ if (priv->band == IEEE80211_BAND_5GHZ)
+ r = IWL_RATE_6M_INDEX;
+ else
+ r = IWL_RATE_1M_INDEX;
+
+ if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE)
+ rate_flags |= RATE_MCS_CCK_MSK;
+
+ rate_flags |= first_antenna(priv->hw_params.valid_tx_ant) <<
+ RATE_MCS_ANT_POS;
+ rate_n_flags = iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags);
+ for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++)
+ link_cmd->rs_table[i].rate_n_flags = rate_n_flags;
+
+ link_cmd->general_params.single_stream_ant_msk =
+ first_antenna(priv->hw_params.valid_tx_ant);
+
+ link_cmd->general_params.dual_stream_ant_msk =
+ priv->hw_params.valid_tx_ant &
+ ~first_antenna(priv->hw_params.valid_tx_ant);
+ if (!link_cmd->general_params.dual_stream_ant_msk) {
+ link_cmd->general_params.dual_stream_ant_msk = ANT_AB;
+ } else if (num_of_ant(priv->hw_params.valid_tx_ant) == 2) {
+ link_cmd->general_params.dual_stream_ant_msk =
+ priv->hw_params.valid_tx_ant;
+ }
+
+ link_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF;
+ link_cmd->agg_params.agg_time_limit =
+ cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF);
+
+ link_cmd->sta_id = sta_id;
+
+ return link_cmd;
+}
+
+/*
+ * iwlagn_add_bssid_station - Add the special IBSS BSSID station
+ *
+ * Function sleeps.
+ */
+int iwlagn_add_bssid_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
+ const u8 *addr, u8 *sta_id_r)
+{
+ int ret;
+ u8 sta_id;
+ struct iwl_link_quality_cmd *link_cmd;
+ unsigned long flags;
+
+ if (sta_id_r)
+ *sta_id_r = IWL_INVALID_STATION;
+
+ ret = iwl_add_station_common(priv, ctx, addr, 0, NULL, &sta_id);
+ if (ret) {
+ IWL_ERR(priv, "Unable to add station %pM\n", addr);
+ return ret;
+ }
+
+ if (sta_id_r)
+ *sta_id_r = sta_id;
+
+ spin_lock_irqsave(&priv->sta_lock, flags);
+ priv->stations[sta_id].used |= IWL_STA_LOCAL;
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+ /* Set up default rate scaling table in device's station table */
+ link_cmd = iwl_sta_alloc_lq(priv, sta_id);
+ if (!link_cmd) {
+ IWL_ERR(priv, "Unable to initialize rate scaling for station %pM.\n",
+ addr);
+ return -ENOMEM;
+ }
+
+ ret = iwl_send_lq_cmd(priv, ctx, link_cmd, CMD_SYNC, true);
+ if (ret)
+ IWL_ERR(priv, "Link quality command failed (%d)\n", ret);
+
+ spin_lock_irqsave(&priv->sta_lock, flags);
+ priv->stations[sta_id].lq = link_cmd;
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+ return 0;
+}
+
+static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx,
+ bool send_if_empty)
+{
+ int i, not_empty = 0;
+ u8 buff[sizeof(struct iwl_wep_cmd) +
+ sizeof(struct iwl_wep_key) * WEP_KEYS_MAX];
+ struct iwl_wep_cmd *wep_cmd = (struct iwl_wep_cmd *)buff;
+ size_t cmd_size = sizeof(struct iwl_wep_cmd);
+ struct iwl_host_cmd cmd = {
+ .id = ctx->wep_key_cmd,
+ .data = wep_cmd,
+ .flags = CMD_SYNC,
+ };
+
+ might_sleep();
+
+ memset(wep_cmd, 0, cmd_size +
+ (sizeof(struct iwl_wep_key) * WEP_KEYS_MAX));
+
+ for (i = 0; i < WEP_KEYS_MAX ; i++) {
+ wep_cmd->key[i].key_index = i;
+ if (ctx->wep_keys[i].key_size) {
+ wep_cmd->key[i].key_offset = i;
+ not_empty = 1;
+ } else {
+ wep_cmd->key[i].key_offset = WEP_INVALID_OFFSET;
+ }
+
+ wep_cmd->key[i].key_size = ctx->wep_keys[i].key_size;
+ memcpy(&wep_cmd->key[i].key[3], ctx->wep_keys[i].key,
+ ctx->wep_keys[i].key_size);
+ }
+
+ wep_cmd->global_key_type = WEP_KEY_WEP_TYPE;
+ wep_cmd->num_keys = WEP_KEYS_MAX;
+
+ cmd_size += sizeof(struct iwl_wep_key) * WEP_KEYS_MAX;
+
+ cmd.len = cmd_size;
+
+ if (not_empty || send_if_empty)
+ return iwl_send_cmd(priv, &cmd);
+ else
+ return 0;
+}
+
+int iwl_restore_default_wep_keys(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx)
+{
+ lockdep_assert_held(&priv->mutex);
+
+ return iwl_send_static_wepkey_cmd(priv, ctx, false);
+}
+
+int iwl_remove_default_wep_key(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx,
+ struct ieee80211_key_conf *keyconf)
+{
+ int ret;
+
+ lockdep_assert_held(&priv->mutex);
+
+ IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n",
+ keyconf->keyidx);
+
+ memset(&ctx->wep_keys[keyconf->keyidx], 0, sizeof(ctx->wep_keys[0]));
+ if (iwl_is_rfkill(priv)) {
+ IWL_DEBUG_WEP(priv, "Not sending REPLY_WEPKEY command due to RFKILL.\n");
+ /* but keys in device are clear anyway so return success */
+ return 0;
+ }
+ ret = iwl_send_static_wepkey_cmd(priv, ctx, 1);
+ IWL_DEBUG_WEP(priv, "Remove default WEP key: idx=%d ret=%d\n",
+ keyconf->keyidx, ret);
+
+ return ret;
+}
+
+int iwl_set_default_wep_key(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx,
+ struct ieee80211_key_conf *keyconf)
+{
+ int ret;
+
+ lockdep_assert_held(&priv->mutex);
+
+ if (keyconf->keylen != WEP_KEY_LEN_128 &&
+ keyconf->keylen != WEP_KEY_LEN_64) {
+ IWL_DEBUG_WEP(priv, "Bad WEP key length %d\n", keyconf->keylen);
+ return -EINVAL;
+ }
+
+ keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
+ keyconf->hw_key_idx = HW_KEY_DEFAULT;
+ priv->stations[ctx->ap_sta_id].keyinfo.cipher = keyconf->cipher;
+
+ ctx->wep_keys[keyconf->keyidx].key_size = keyconf->keylen;
+ memcpy(&ctx->wep_keys[keyconf->keyidx].key, &keyconf->key,
+ keyconf->keylen);
+
+ ret = iwl_send_static_wepkey_cmd(priv, ctx, false);
+ IWL_DEBUG_WEP(priv, "Set default WEP key: len=%d idx=%d ret=%d\n",
+ keyconf->keylen, keyconf->keyidx, ret);
+
+ return ret;
+}
+
+static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx,
+ struct ieee80211_key_conf *keyconf,
+ u8 sta_id)
+{
+ unsigned long flags;
+ __le16 key_flags = 0;
+ struct iwl_addsta_cmd sta_cmd;
+
+ lockdep_assert_held(&priv->mutex);
+
+ keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
+
+ key_flags |= (STA_KEY_FLG_WEP | STA_KEY_FLG_MAP_KEY_MSK);
+ key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
+ key_flags &= ~STA_KEY_FLG_INVALID;
+
+ if (keyconf->keylen == WEP_KEY_LEN_128)
+ key_flags |= STA_KEY_FLG_KEY_SIZE_MSK;
+
+ if (sta_id == ctx->bcast_sta_id)
+ key_flags |= STA_KEY_MULTICAST_MSK;
+
+ spin_lock_irqsave(&priv->sta_lock, flags);
+
+ priv->stations[sta_id].keyinfo.cipher = keyconf->cipher;
+ priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;
+ priv->stations[sta_id].keyinfo.keyidx = keyconf->keyidx;
+
+ memcpy(priv->stations[sta_id].keyinfo.key,
+ keyconf->key, keyconf->keylen);
+
+ memcpy(&priv->stations[sta_id].sta.key.key[3],
+ keyconf->key, keyconf->keylen);
+
+ if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
+ == STA_KEY_FLG_NO_ENC)
+ priv->stations[sta_id].sta.key.key_offset =
+ iwl_get_free_ucode_key_index(priv);
+ /* else, we are overriding an existing key => no need to allocated room
+ * in uCode. */
+
+ WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
+ "no space for a new key");
+
+ priv->stations[sta_id].sta.key.key_flags = key_flags;
+ priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
+ priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+
+ memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+ return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
+}
+
+static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx,
+ struct ieee80211_key_conf *keyconf,
+ u8 sta_id)
+{
+ unsigned long flags;
+ __le16 key_flags = 0;
+ struct iwl_addsta_cmd sta_cmd;
+
+ lockdep_assert_held(&priv->mutex);
+
+ key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK);
+ key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
+ key_flags &= ~STA_KEY_FLG_INVALID;
+
+ if (sta_id == ctx->bcast_sta_id)
+ key_flags |= STA_KEY_MULTICAST_MSK;
+
+ keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+
+ spin_lock_irqsave(&priv->sta_lock, flags);
+ priv->stations[sta_id].keyinfo.cipher = keyconf->cipher;
+ priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;
+
+ memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key,
+ keyconf->keylen);
+
+ memcpy(priv->stations[sta_id].sta.key.key, keyconf->key,
+ keyconf->keylen);
+
+ if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
+ == STA_KEY_FLG_NO_ENC)
+ priv->stations[sta_id].sta.key.key_offset =
+ iwl_get_free_ucode_key_index(priv);
+ /* else, we are overriding an existing key => no need to allocated room
+ * in uCode. */
+
+ WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
+ "no space for a new key");
+
+ priv->stations[sta_id].sta.key.key_flags = key_flags;
+ priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
+ priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+
+ memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+ return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
+}
+
+static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx,
+ struct ieee80211_key_conf *keyconf,
+ u8 sta_id)
+{
+ unsigned long flags;
+ int ret = 0;
+ __le16 key_flags = 0;
+
+ key_flags |= (STA_KEY_FLG_TKIP | STA_KEY_FLG_MAP_KEY_MSK);
+ key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
+ key_flags &= ~STA_KEY_FLG_INVALID;
+
+ if (sta_id == ctx->bcast_sta_id)
+ key_flags |= STA_KEY_MULTICAST_MSK;
+
+ keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+ keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
+
+ spin_lock_irqsave(&priv->sta_lock, flags);
+
+ priv->stations[sta_id].keyinfo.cipher = keyconf->cipher;
+ priv->stations[sta_id].keyinfo.keylen = 16;
+
+ if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
+ == STA_KEY_FLG_NO_ENC)
+ priv->stations[sta_id].sta.key.key_offset =
+ iwl_get_free_ucode_key_index(priv);
+ /* else, we are overriding an existing key => no need to allocated room
+ * in uCode. */
+
+ WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
+ "no space for a new key");
+
+ priv->stations[sta_id].sta.key.key_flags = key_flags;
+
+
+ /* This copy is acutally not needed: we get the key with each TX */
+ memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, 16);
+
+ memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, 16);
+
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+ return ret;
+}
+
+void iwl_update_tkip_key(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx,
+ struct ieee80211_key_conf *keyconf,
+ struct ieee80211_sta *sta, u32 iv32, u16 *phase1key)
+{
+ u8 sta_id;
+ unsigned long flags;
+ int i;
+
+ if (iwl_scan_cancel(priv)) {
+ /* cancel scan failed, just live w/ bad key and rely
+ briefly on SW decryption */
+ return;
+ }
+
+ sta_id = iwl_sta_id_or_broadcast(priv, ctx, sta);
+ if (sta_id == IWL_INVALID_STATION)
+ return;
+
+ spin_lock_irqsave(&priv->sta_lock, flags);
+
+ priv->stations[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32;
+
+ for (i = 0; i < 5; i++)
+ priv->stations[sta_id].sta.key.tkip_rx_ttak[i] =
+ cpu_to_le16(phase1key[i]);
+
+ priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
+ priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+
+ iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
+
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+}
+
+int iwl_remove_dynamic_key(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx,
+ struct ieee80211_key_conf *keyconf,
+ u8 sta_id)
+{
+ unsigned long flags;
+ u16 key_flags;
+ u8 keyidx;
+ struct iwl_addsta_cmd sta_cmd;
+
+ lockdep_assert_held(&priv->mutex);
+
+ ctx->key_mapping_keys--;
+
+ spin_lock_irqsave(&priv->sta_lock, flags);
+ key_flags = le16_to_cpu(priv->stations[sta_id].sta.key.key_flags);
+ keyidx = (key_flags >> STA_KEY_FLG_KEYID_POS) & 0x3;
+
+ IWL_DEBUG_WEP(priv, "Remove dynamic key: idx=%d sta=%d\n",
+ keyconf->keyidx, sta_id);
+
+ if (keyconf->keyidx != keyidx) {
+ /* We need to remove a key with index different that the one
+ * in the uCode. This means that the key we need to remove has
+ * been replaced by another one with different index.
+ * Don't do anything and return ok
+ */
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+ return 0;
+ }
+
+ if (priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET) {
+ IWL_WARN(priv, "Removing wrong key %d 0x%x\n",
+ keyconf->keyidx, key_flags);
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+ return 0;
+ }
+
+ if (!test_and_clear_bit(priv->stations[sta_id].sta.key.key_offset,
+ &priv->ucode_key_table))
+ IWL_ERR(priv, "index %d not used in uCode key table.\n",
+ priv->stations[sta_id].sta.key.key_offset);
+ memset(&priv->stations[sta_id].keyinfo, 0,
+ sizeof(struct iwl_hw_key));
+ memset(&priv->stations[sta_id].sta.key, 0,
+ sizeof(struct iwl4965_keyinfo));
+ priv->stations[sta_id].sta.key.key_flags =
+ STA_KEY_FLG_NO_ENC | STA_KEY_FLG_INVALID;
+ priv->stations[sta_id].sta.key.key_offset = WEP_INVALID_OFFSET;
+ priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
+ priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+
+ if (iwl_is_rfkill(priv)) {
+ IWL_DEBUG_WEP(priv, "Not sending REPLY_ADD_STA command because RFKILL enabled.\n");
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+ return 0;
+ }
+ memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+ return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
+}
+
+int iwl_set_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
+ struct ieee80211_key_conf *keyconf, u8 sta_id)
+{
+ int ret;
+
+ lockdep_assert_held(&priv->mutex);
+
+ ctx->key_mapping_keys++;
+ keyconf->hw_key_idx = HW_KEY_DYNAMIC;
+
+ switch (keyconf->cipher) {
+ case WLAN_CIPHER_SUITE_CCMP:
+ ret = iwl_set_ccmp_dynamic_key_info(priv, ctx, keyconf, sta_id);
+ break;
+ case WLAN_CIPHER_SUITE_TKIP:
+ ret = iwl_set_tkip_dynamic_key_info(priv, ctx, keyconf, sta_id);
+ break;
+ case WLAN_CIPHER_SUITE_WEP40:
+ case WLAN_CIPHER_SUITE_WEP104:
+ ret = iwl_set_wep_dynamic_key_info(priv, ctx, keyconf, sta_id);
+ break;
+ default:
+ IWL_ERR(priv,
+ "Unknown alg: %s cipher = %x\n", __func__,
+ keyconf->cipher);
+ ret = -EINVAL;
+ }
+
+ IWL_DEBUG_WEP(priv, "Set dynamic key: cipher=%x len=%d idx=%d sta=%d ret=%d\n",
+ keyconf->cipher, keyconf->keylen, keyconf->keyidx,
+ sta_id, ret);
+
+ return ret;
+}
+
+/**
+ * iwlagn_alloc_bcast_station - add broadcast station into driver's station table.
+ *
+ * This adds the broadcast station into the driver's station table
+ * and marks it driver active, so that it will be restored to the
+ * device at the next best time.
+ */
+int iwlagn_alloc_bcast_station(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx)
+{
+ struct iwl_link_quality_cmd *link_cmd;
+ unsigned long flags;
+ u8 sta_id;
+
+ spin_lock_irqsave(&priv->sta_lock, flags);
+ sta_id = iwl_prep_station(priv, ctx, iwl_bcast_addr, false, NULL);
+ if (sta_id == IWL_INVALID_STATION) {
+ IWL_ERR(priv, "Unable to prepare broadcast station\n");
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+ return -EINVAL;
+ }
+
+ priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE;
+ priv->stations[sta_id].used |= IWL_STA_BCAST;
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+ link_cmd = iwl_sta_alloc_lq(priv, sta_id);
+ if (!link_cmd) {
+ IWL_ERR(priv,
+ "Unable to initialize rate scaling for bcast station.\n");
+ return -ENOMEM;
+ }
+
+ spin_lock_irqsave(&priv->sta_lock, flags);
+ priv->stations[sta_id].lq = link_cmd;
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+ return 0;
+}
+
+/**
+ * iwl_update_bcast_station - update broadcast station's LQ command
+ *
+ * Only used by iwlagn. Placed here to have all bcast station management
+ * code together.
+ */
+static int iwl_update_bcast_station(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx)
+{
+ unsigned long flags;
+ struct iwl_link_quality_cmd *link_cmd;
+ u8 sta_id = ctx->bcast_sta_id;
+
+ link_cmd = iwl_sta_alloc_lq(priv, sta_id);
+ if (!link_cmd) {
+ IWL_ERR(priv, "Unable to initialize rate scaling for bcast station.\n");
+ return -ENOMEM;
+ }
+
+ spin_lock_irqsave(&priv->sta_lock, flags);
+ if (priv->stations[sta_id].lq)
+ kfree(priv->stations[sta_id].lq);
+ else
+ IWL_DEBUG_INFO(priv, "Bcast station rate scaling has not been initialized yet.\n");
+ priv->stations[sta_id].lq = link_cmd;
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+ return 0;
+}
+
+int iwl_update_bcast_stations(struct iwl_priv *priv)
+{
+ struct iwl_rxon_context *ctx;
+ int ret = 0;
+
+ for_each_context(priv, ctx) {
+ ret = iwl_update_bcast_station(priv, ctx);
+ if (ret)
+ break;
+ }
+
+ return ret;
+}
+
+/**
+ * iwl_sta_tx_modify_enable_tid - Enable Tx for this TID in station table
+ */
+int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid)
+{
+ unsigned long flags;
+ struct iwl_addsta_cmd sta_cmd;
+
+ lockdep_assert_held(&priv->mutex);
+
+ /* Remove "disable" flag, to enable Tx for this TID */
+ spin_lock_irqsave(&priv->sta_lock, flags);
+ priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_TID_DISABLE_TX;
+ priv->stations[sta_id].sta.tid_disable_tx &= cpu_to_le16(~(1 << tid));
+ priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+ memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+ return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
+}
+
+int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
+ int tid, u16 ssn)
+{
+ unsigned long flags;
+ int sta_id;
+ struct iwl_addsta_cmd sta_cmd;
+
+ lockdep_assert_held(&priv->mutex);
+
+ sta_id = iwl_sta_id(sta);
+ if (sta_id == IWL_INVALID_STATION)
+ return -ENXIO;
+
+ spin_lock_irqsave(&priv->sta_lock, flags);
+ priv->stations[sta_id].sta.station_flags_msk = 0;
+ priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_ADDBA_TID_MSK;
+ priv->stations[sta_id].sta.add_immediate_ba_tid = (u8)tid;
+ priv->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn);
+ priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+ memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+ return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
+}
+
+int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
+ int tid)
+{
+ unsigned long flags;
+ int sta_id;
+ struct iwl_addsta_cmd sta_cmd;
+
+ lockdep_assert_held(&priv->mutex);
+
+ sta_id = iwl_sta_id(sta);
+ if (sta_id == IWL_INVALID_STATION) {
+ IWL_ERR(priv, "Invalid station for AGG tid %d\n", tid);
+ return -ENXIO;
+ }
+
+ spin_lock_irqsave(&priv->sta_lock, flags);
+ priv->stations[sta_id].sta.station_flags_msk = 0;
+ priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK;
+ priv->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid;
+ priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+ memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+ return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
+}
+
+void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->sta_lock, flags);
+ priv->stations[sta_id].sta.station_flags &= ~STA_FLG_PWR_SAVE_MSK;
+ priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK;
+ priv->stations[sta_id].sta.sta.modify_mask = 0;
+ priv->stations[sta_id].sta.sleep_tx_count = 0;
+ priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+ iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+}
+
+void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->sta_lock, flags);
+ priv->stations[sta_id].sta.station_flags |= STA_FLG_PWR_SAVE_MSK;
+ priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK;
+ priv->stations[sta_id].sta.sta.modify_mask =
+ STA_MODIFY_SLEEP_TX_COUNT_MSK;
+ priv->stations[sta_id].sta.sleep_tx_count = cpu_to_le16(cnt);
+ priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+ iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c
new file mode 100644
index 000000000000..e3a8216a033c
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c
@@ -0,0 +1,699 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved.
+ *
+ * Portions of this file are derived from the ipw3945 project, as well
+ * as portions of the ieee80211 subsystem header files.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *****************************************************************************/
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+
+#include <net/mac80211.h>
+
+#include "iwl-eeprom.h"
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-io.h"
+#include "iwl-commands.h"
+#include "iwl-debug.h"
+#include "iwl-agn-tt.h"
+
+/* default Thermal Throttling transaction table
+ * Current state | Throttling Down | Throttling Up
+ *=============================================================================
+ * Condition Nxt State Condition Nxt State Condition Nxt State
+ *-----------------------------------------------------------------------------
+ * IWL_TI_0 T >= 114 CT_KILL 114>T>=105 TI_1 N/A N/A
+ * IWL_TI_1 T >= 114 CT_KILL 114>T>=110 TI_2 T<=95 TI_0
+ * IWL_TI_2 T >= 114 CT_KILL T<=100 TI_1
+ * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0
+ *=============================================================================
+ */
+static const struct iwl_tt_trans tt_range_0[IWL_TI_STATE_MAX - 1] = {
+ {IWL_TI_0, IWL_ABSOLUTE_ZERO, 104},
+ {IWL_TI_1, 105, CT_KILL_THRESHOLD - 1},
+ {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX}
+};
+static const struct iwl_tt_trans tt_range_1[IWL_TI_STATE_MAX - 1] = {
+ {IWL_TI_0, IWL_ABSOLUTE_ZERO, 95},
+ {IWL_TI_2, 110, CT_KILL_THRESHOLD - 1},
+ {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX}
+};
+static const struct iwl_tt_trans tt_range_2[IWL_TI_STATE_MAX - 1] = {
+ {IWL_TI_1, IWL_ABSOLUTE_ZERO, 100},
+ {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX},
+ {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX}
+};
+static const struct iwl_tt_trans tt_range_3[IWL_TI_STATE_MAX - 1] = {
+ {IWL_TI_0, IWL_ABSOLUTE_ZERO, CT_KILL_EXIT_THRESHOLD},
+ {IWL_TI_CT_KILL, CT_KILL_EXIT_THRESHOLD + 1, IWL_ABSOLUTE_MAX},
+ {IWL_TI_CT_KILL, CT_KILL_EXIT_THRESHOLD + 1, IWL_ABSOLUTE_MAX}
+};
+
+/* Advance Thermal Throttling default restriction table */
+static const struct iwl_tt_restriction restriction_range[IWL_TI_STATE_MAX] = {
+ {IWL_ANT_OK_MULTI, IWL_ANT_OK_MULTI, true },
+ {IWL_ANT_OK_SINGLE, IWL_ANT_OK_MULTI, true },
+ {IWL_ANT_OK_SINGLE, IWL_ANT_OK_SINGLE, false },
+ {IWL_ANT_OK_NONE, IWL_ANT_OK_NONE, false }
+};
+
+bool iwl_tt_is_low_power_state(struct iwl_priv *priv)
+{
+ struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+
+ if (tt->state >= IWL_TI_1)
+ return true;
+ return false;
+}
+
+u8 iwl_tt_current_power_mode(struct iwl_priv *priv)
+{
+ struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+
+ return tt->tt_power_mode;
+}
+
+bool iwl_ht_enabled(struct iwl_priv *priv)
+{
+ struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+ struct iwl_tt_restriction *restriction;
+
+ if (!priv->thermal_throttle.advanced_tt)
+ return true;
+ restriction = tt->restriction + tt->state;
+ return restriction->is_ht;
+}
+
+static bool iwl_within_ct_kill_margin(struct iwl_priv *priv)
+{
+ s32 temp = priv->temperature; /* degrees CELSIUS except specified */
+ bool within_margin = false;
+
+ if (priv->cfg->base_params->temperature_kelvin)
+ temp = KELVIN_TO_CELSIUS(priv->temperature);
+
+ if (!priv->thermal_throttle.advanced_tt)
+ within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >=
+ CT_KILL_THRESHOLD_LEGACY) ? true : false;
+ else
+ within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >=
+ CT_KILL_THRESHOLD) ? true : false;
+ return within_margin;
+}
+
+bool iwl_check_for_ct_kill(struct iwl_priv *priv)
+{
+ bool is_ct_kill = false;
+
+ if (iwl_within_ct_kill_margin(priv)) {
+ iwl_tt_enter_ct_kill(priv);
+ is_ct_kill = true;
+ }
+ return is_ct_kill;
+}
+
+enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv)
+{
+ struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+ struct iwl_tt_restriction *restriction;
+
+ if (!priv->thermal_throttle.advanced_tt)
+ return IWL_ANT_OK_MULTI;
+ restriction = tt->restriction + tt->state;
+ return restriction->tx_stream;
+}
+
+enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv)
+{
+ struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+ struct iwl_tt_restriction *restriction;
+
+ if (!priv->thermal_throttle.advanced_tt)
+ return IWL_ANT_OK_MULTI;
+ restriction = tt->restriction + tt->state;
+ return restriction->rx_stream;
+}
+
+#define CT_KILL_EXIT_DURATION (5) /* 5 seconds duration */
+#define CT_KILL_WAITING_DURATION (300) /* 300ms duration */
+
+/*
+ * toggle the bit to wake up uCode and check the temperature
+ * if the temperature is below CT, uCode will stay awake and send card
+ * state notification with CT_KILL bit clear to inform Thermal Throttling
+ * Management to change state. Otherwise, uCode will go back to sleep
+ * without doing anything, driver should continue the 5 seconds timer
+ * to wake up uCode for temperature check until temperature drop below CT
+ */
+static void iwl_tt_check_exit_ct_kill(unsigned long data)
+{
+ struct iwl_priv *priv = (struct iwl_priv *)data;
+ struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+ unsigned long flags;
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return;
+
+ if (tt->state == IWL_TI_CT_KILL) {
+ if (priv->thermal_throttle.ct_kill_toggle) {
+ iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
+ CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
+ priv->thermal_throttle.ct_kill_toggle = false;
+ } else {
+ iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
+ CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
+ priv->thermal_throttle.ct_kill_toggle = true;
+ }
+ iwl_read32(priv, CSR_UCODE_DRV_GP1);
+ spin_lock_irqsave(&priv->reg_lock, flags);
+ if (!iwl_grab_nic_access(priv))
+ iwl_release_nic_access(priv);
+ spin_unlock_irqrestore(&priv->reg_lock, flags);
+
+ /* Reschedule the ct_kill timer to occur in
+ * CT_KILL_EXIT_DURATION seconds to ensure we get a
+ * thermal update */
+ IWL_DEBUG_POWER(priv, "schedule ct_kill exit timer\n");
+ mod_timer(&priv->thermal_throttle.ct_kill_exit_tm,
+ jiffies + CT_KILL_EXIT_DURATION * HZ);
+ }
+}
+
+static void iwl_perform_ct_kill_task(struct iwl_priv *priv,
+ bool stop)
+{
+ if (stop) {
+ IWL_DEBUG_POWER(priv, "Stop all queues\n");
+ if (priv->mac80211_registered)
+ ieee80211_stop_queues(priv->hw);
+ IWL_DEBUG_POWER(priv,
+ "Schedule 5 seconds CT_KILL Timer\n");
+ mod_timer(&priv->thermal_throttle.ct_kill_exit_tm,
+ jiffies + CT_KILL_EXIT_DURATION * HZ);
+ } else {
+ IWL_DEBUG_POWER(priv, "Wake all queues\n");
+ if (priv->mac80211_registered)
+ ieee80211_wake_queues(priv->hw);
+ }
+}
+
+static void iwl_tt_ready_for_ct_kill(unsigned long data)
+{
+ struct iwl_priv *priv = (struct iwl_priv *)data;
+ struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return;
+
+ /* temperature timer expired, ready to go into CT_KILL state */
+ if (tt->state != IWL_TI_CT_KILL) {
+ IWL_DEBUG_POWER(priv, "entering CT_KILL state when "
+ "temperature timer expired\n");
+ tt->state = IWL_TI_CT_KILL;
+ set_bit(STATUS_CT_KILL, &priv->status);
+ iwl_perform_ct_kill_task(priv, true);
+ }
+}
+
+static void iwl_prepare_ct_kill_task(struct iwl_priv *priv)
+{
+ IWL_DEBUG_POWER(priv, "Prepare to enter IWL_TI_CT_KILL\n");
+ /* make request to retrieve statistics information */
+ iwl_send_statistics_request(priv, CMD_SYNC, false);
+ /* Reschedule the ct_kill wait timer */
+ mod_timer(&priv->thermal_throttle.ct_kill_waiting_tm,
+ jiffies + msecs_to_jiffies(CT_KILL_WAITING_DURATION));
+}
+
+#define IWL_MINIMAL_POWER_THRESHOLD (CT_KILL_THRESHOLD_LEGACY)
+#define IWL_REDUCED_PERFORMANCE_THRESHOLD_2 (100)
+#define IWL_REDUCED_PERFORMANCE_THRESHOLD_1 (90)
+
+/*
+ * Legacy thermal throttling
+ * 1) Avoid NIC destruction due to high temperatures
+ * Chip will identify dangerously high temperatures that can
+ * harm the device and will power down
+ * 2) Avoid the NIC power down due to high temperature
+ * Throttle early enough to lower the power consumption before
+ * drastic steps are needed
+ */
+static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
+{
+ struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+ enum iwl_tt_state old_state;
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+ if ((tt->tt_previous_temp) &&
+ (temp > tt->tt_previous_temp) &&
+ ((temp - tt->tt_previous_temp) >
+ IWL_TT_INCREASE_MARGIN)) {
+ IWL_DEBUG_POWER(priv,
+ "Temperature increase %d degree Celsius\n",
+ (temp - tt->tt_previous_temp));
+ }
+#endif
+ old_state = tt->state;
+ /* in Celsius */
+ if (temp >= IWL_MINIMAL_POWER_THRESHOLD)
+ tt->state = IWL_TI_CT_KILL;
+ else if (temp >= IWL_REDUCED_PERFORMANCE_THRESHOLD_2)
+ tt->state = IWL_TI_2;
+ else if (temp >= IWL_REDUCED_PERFORMANCE_THRESHOLD_1)
+ tt->state = IWL_TI_1;
+ else
+ tt->state = IWL_TI_0;
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+ tt->tt_previous_temp = temp;
+#endif
+ /* stop ct_kill_waiting_tm timer */
+ del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm);
+ if (tt->state != old_state) {
+ switch (tt->state) {
+ case IWL_TI_0:
+ /*
+ * When the system is ready to go back to IWL_TI_0
+ * we only have to call iwl_power_update_mode() to
+ * do so.
+ */
+ break;
+ case IWL_TI_1:
+ tt->tt_power_mode = IWL_POWER_INDEX_3;
+ break;
+ case IWL_TI_2:
+ tt->tt_power_mode = IWL_POWER_INDEX_4;
+ break;
+ default:
+ tt->tt_power_mode = IWL_POWER_INDEX_5;
+ break;
+ }
+ mutex_lock(&priv->mutex);
+ if (old_state == IWL_TI_CT_KILL)
+ clear_bit(STATUS_CT_KILL, &priv->status);
+ if (tt->state != IWL_TI_CT_KILL &&
+ iwl_power_update_mode(priv, true)) {
+ /* TT state not updated
+ * try again during next temperature read
+ */
+ if (old_state == IWL_TI_CT_KILL)
+ set_bit(STATUS_CT_KILL, &priv->status);
+ tt->state = old_state;
+ IWL_ERR(priv, "Cannot update power mode, "
+ "TT state not updated\n");
+ } else {
+ if (tt->state == IWL_TI_CT_KILL) {
+ if (force) {
+ set_bit(STATUS_CT_KILL, &priv->status);
+ iwl_perform_ct_kill_task(priv, true);
+ } else {
+ iwl_prepare_ct_kill_task(priv);
+ tt->state = old_state;
+ }
+ } else if (old_state == IWL_TI_CT_KILL &&
+ tt->state != IWL_TI_CT_KILL)
+ iwl_perform_ct_kill_task(priv, false);
+ IWL_DEBUG_POWER(priv, "Temperature state changed %u\n",
+ tt->state);
+ IWL_DEBUG_POWER(priv, "Power Index change to %u\n",
+ tt->tt_power_mode);
+ }
+ mutex_unlock(&priv->mutex);
+ }
+}
+
+/*
+ * Advance thermal throttling
+ * 1) Avoid NIC destruction due to high temperatures
+ * Chip will identify dangerously high temperatures that can
+ * harm the device and will power down
+ * 2) Avoid the NIC power down due to high temperature
+ * Throttle early enough to lower the power consumption before
+ * drastic steps are needed
+ * Actions include relaxing the power down sleep thresholds and
+ * decreasing the number of TX streams
+ * 3) Avoid throughput performance impact as much as possible
+ *
+ *=============================================================================
+ * Condition Nxt State Condition Nxt State Condition Nxt State
+ *-----------------------------------------------------------------------------
+ * IWL_TI_0 T >= 114 CT_KILL 114>T>=105 TI_1 N/A N/A
+ * IWL_TI_1 T >= 114 CT_KILL 114>T>=110 TI_2 T<=95 TI_0
+ * IWL_TI_2 T >= 114 CT_KILL T<=100 TI_1
+ * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0
+ *=============================================================================
+ */
+static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
+{
+ struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+ int i;
+ bool changed = false;
+ enum iwl_tt_state old_state;
+ struct iwl_tt_trans *transaction;
+
+ old_state = tt->state;
+ for (i = 0; i < IWL_TI_STATE_MAX - 1; i++) {
+ /* based on the current TT state,
+ * find the curresponding transaction table
+ * each table has (IWL_TI_STATE_MAX - 1) entries
+ * tt->transaction + ((old_state * (IWL_TI_STATE_MAX - 1))
+ * will advance to the correct table.
+ * then based on the current temperature
+ * find the next state need to transaction to
+ * go through all the possible (IWL_TI_STATE_MAX - 1) entries
+ * in the current table to see if transaction is needed
+ */
+ transaction = tt->transaction +
+ ((old_state * (IWL_TI_STATE_MAX - 1)) + i);
+ if (temp >= transaction->tt_low &&
+ temp <= transaction->tt_high) {
+#ifdef CONFIG_IWLWIFI_DEBUG
+ if ((tt->tt_previous_temp) &&
+ (temp > tt->tt_previous_temp) &&
+ ((temp - tt->tt_previous_temp) >
+ IWL_TT_INCREASE_MARGIN)) {
+ IWL_DEBUG_POWER(priv,
+ "Temperature increase %d "
+ "degree Celsius\n",
+ (temp - tt->tt_previous_temp));
+ }
+ tt->tt_previous_temp = temp;
+#endif
+ if (old_state !=
+ transaction->next_state) {
+ changed = true;
+ tt->state =
+ transaction->next_state;
+ }
+ break;
+ }
+ }
+ /* stop ct_kill_waiting_tm timer */
+ del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm);
+ if (changed) {
+ if (tt->state >= IWL_TI_1) {
+ /* force PI = IWL_POWER_INDEX_5 in the case of TI > 0 */
+ tt->tt_power_mode = IWL_POWER_INDEX_5;
+
+ if (!iwl_ht_enabled(priv)) {
+ struct iwl_rxon_context *ctx;
+
+ for_each_context(priv, ctx) {
+ struct iwl_rxon_cmd *rxon;
+
+ rxon = &ctx->staging;
+
+ /* disable HT */
+ rxon->flags &= ~(
+ RXON_FLG_CHANNEL_MODE_MSK |
+ RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK |
+ RXON_FLG_HT40_PROT_MSK |
+ RXON_FLG_HT_PROT_MSK);
+ }
+ } else {
+ /* check HT capability and set
+ * according to the system HT capability
+ * in case get disabled before */
+ iwl_set_rxon_ht(priv, &priv->current_ht_config);
+ }
+
+ } else {
+ /*
+ * restore system power setting -- it will be
+ * recalculated automatically.
+ */
+
+ /* check HT capability and set
+ * according to the system HT capability
+ * in case get disabled before */
+ iwl_set_rxon_ht(priv, &priv->current_ht_config);
+ }
+ mutex_lock(&priv->mutex);
+ if (old_state == IWL_TI_CT_KILL)
+ clear_bit(STATUS_CT_KILL, &priv->status);
+ if (tt->state != IWL_TI_CT_KILL &&
+ iwl_power_update_mode(priv, true)) {
+ /* TT state not updated
+ * try again during next temperature read
+ */
+ IWL_ERR(priv, "Cannot update power mode, "
+ "TT state not updated\n");
+ if (old_state == IWL_TI_CT_KILL)
+ set_bit(STATUS_CT_KILL, &priv->status);
+ tt->state = old_state;
+ } else {
+ IWL_DEBUG_POWER(priv,
+ "Thermal Throttling to new state: %u\n",
+ tt->state);
+ if (old_state != IWL_TI_CT_KILL &&
+ tt->state == IWL_TI_CT_KILL) {
+ if (force) {
+ IWL_DEBUG_POWER(priv,
+ "Enter IWL_TI_CT_KILL\n");
+ set_bit(STATUS_CT_KILL, &priv->status);
+ iwl_perform_ct_kill_task(priv, true);
+ } else {
+ iwl_prepare_ct_kill_task(priv);
+ tt->state = old_state;
+ }
+ } else if (old_state == IWL_TI_CT_KILL &&
+ tt->state != IWL_TI_CT_KILL) {
+ IWL_DEBUG_POWER(priv, "Exit IWL_TI_CT_KILL\n");
+ iwl_perform_ct_kill_task(priv, false);
+ }
+ }
+ mutex_unlock(&priv->mutex);
+ }
+}
+
+/* Card State Notification indicated reach critical temperature
+ * if PSP not enable, no Thermal Throttling function will be performed
+ * just set the GP1 bit to acknowledge the event
+ * otherwise, go into IWL_TI_CT_KILL state
+ * since Card State Notification will not provide any temperature reading
+ * for Legacy mode
+ * so just pass the CT_KILL temperature to iwl_legacy_tt_handler()
+ * for advance mode
+ * pass CT_KILL_THRESHOLD+1 to make sure move into IWL_TI_CT_KILL state
+ */
+static void iwl_bg_ct_enter(struct work_struct *work)
+{
+ struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_enter);
+ struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return;
+
+ if (!iwl_is_ready(priv))
+ return;
+
+ if (tt->state != IWL_TI_CT_KILL) {
+ IWL_ERR(priv, "Device reached critical temperature "
+ "- ucode going to sleep!\n");
+ if (!priv->thermal_throttle.advanced_tt)
+ iwl_legacy_tt_handler(priv,
+ IWL_MINIMAL_POWER_THRESHOLD,
+ true);
+ else
+ iwl_advance_tt_handler(priv,
+ CT_KILL_THRESHOLD + 1, true);
+ }
+}
+
+/* Card State Notification indicated out of critical temperature
+ * since Card State Notification will not provide any temperature reading
+ * so pass the IWL_REDUCED_PERFORMANCE_THRESHOLD_2 temperature
+ * to iwl_legacy_tt_handler() to get out of IWL_CT_KILL state
+ */
+static void iwl_bg_ct_exit(struct work_struct *work)
+{
+ struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_exit);
+ struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return;
+
+ if (!iwl_is_ready(priv))
+ return;
+
+ /* stop ct_kill_exit_tm timer */
+ del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm);
+
+ if (tt->state == IWL_TI_CT_KILL) {
+ IWL_ERR(priv,
+ "Device temperature below critical"
+ "- ucode awake!\n");
+ /*
+ * exit from CT_KILL state
+ * reset the current temperature reading
+ */
+ priv->temperature = 0;
+ if (!priv->thermal_throttle.advanced_tt)
+ iwl_legacy_tt_handler(priv,
+ IWL_REDUCED_PERFORMANCE_THRESHOLD_2,
+ true);
+ else
+ iwl_advance_tt_handler(priv, CT_KILL_EXIT_THRESHOLD,
+ true);
+ }
+}
+
+void iwl_tt_enter_ct_kill(struct iwl_priv *priv)
+{
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return;
+
+ IWL_DEBUG_POWER(priv, "Queueing critical temperature enter.\n");
+ queue_work(priv->workqueue, &priv->ct_enter);
+}
+
+void iwl_tt_exit_ct_kill(struct iwl_priv *priv)
+{
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return;
+
+ IWL_DEBUG_POWER(priv, "Queueing critical temperature exit.\n");
+ queue_work(priv->workqueue, &priv->ct_exit);
+}
+
+static void iwl_bg_tt_work(struct work_struct *work)
+{
+ struct iwl_priv *priv = container_of(work, struct iwl_priv, tt_work);
+ s32 temp = priv->temperature; /* degrees CELSIUS except specified */
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return;
+
+ if (priv->cfg->base_params->temperature_kelvin)
+ temp = KELVIN_TO_CELSIUS(priv->temperature);
+
+ if (!priv->thermal_throttle.advanced_tt)
+ iwl_legacy_tt_handler(priv, temp, false);
+ else
+ iwl_advance_tt_handler(priv, temp, false);
+}
+
+void iwl_tt_handler(struct iwl_priv *priv)
+{
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return;
+
+ IWL_DEBUG_POWER(priv, "Queueing thermal throttling work.\n");
+ queue_work(priv->workqueue, &priv->tt_work);
+}
+
+/* Thermal throttling initialization
+ * For advance thermal throttling:
+ * Initialize Thermal Index and temperature threshold table
+ * Initialize thermal throttling restriction table
+ */
+void iwl_tt_initialize(struct iwl_priv *priv)
+{
+ struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+ int size = sizeof(struct iwl_tt_trans) * (IWL_TI_STATE_MAX - 1);
+ struct iwl_tt_trans *transaction;
+
+ IWL_DEBUG_POWER(priv, "Initialize Thermal Throttling\n");
+
+ memset(tt, 0, sizeof(struct iwl_tt_mgmt));
+
+ tt->state = IWL_TI_0;
+ init_timer(&priv->thermal_throttle.ct_kill_exit_tm);
+ priv->thermal_throttle.ct_kill_exit_tm.data = (unsigned long)priv;
+ priv->thermal_throttle.ct_kill_exit_tm.function =
+ iwl_tt_check_exit_ct_kill;
+ init_timer(&priv->thermal_throttle.ct_kill_waiting_tm);
+ priv->thermal_throttle.ct_kill_waiting_tm.data =
+ (unsigned long)priv;
+ priv->thermal_throttle.ct_kill_waiting_tm.function =
+ iwl_tt_ready_for_ct_kill;
+ /* setup deferred ct kill work */
+ INIT_WORK(&priv->tt_work, iwl_bg_tt_work);
+ INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter);
+ INIT_WORK(&priv->ct_exit, iwl_bg_ct_exit);
+
+ if (priv->cfg->base_params->adv_thermal_throttle) {
+ IWL_DEBUG_POWER(priv, "Advanced Thermal Throttling\n");
+ tt->restriction = kzalloc(sizeof(struct iwl_tt_restriction) *
+ IWL_TI_STATE_MAX, GFP_KERNEL);
+ tt->transaction = kzalloc(sizeof(struct iwl_tt_trans) *
+ IWL_TI_STATE_MAX * (IWL_TI_STATE_MAX - 1),
+ GFP_KERNEL);
+ if (!tt->restriction || !tt->transaction) {
+ IWL_ERR(priv, "Fallback to Legacy Throttling\n");
+ priv->thermal_throttle.advanced_tt = false;
+ kfree(tt->restriction);
+ tt->restriction = NULL;
+ kfree(tt->transaction);
+ tt->transaction = NULL;
+ } else {
+ transaction = tt->transaction +
+ (IWL_TI_0 * (IWL_TI_STATE_MAX - 1));
+ memcpy(transaction, &tt_range_0[0], size);
+ transaction = tt->transaction +
+ (IWL_TI_1 * (IWL_TI_STATE_MAX - 1));
+ memcpy(transaction, &tt_range_1[0], size);
+ transaction = tt->transaction +
+ (IWL_TI_2 * (IWL_TI_STATE_MAX - 1));
+ memcpy(transaction, &tt_range_2[0], size);
+ transaction = tt->transaction +
+ (IWL_TI_CT_KILL * (IWL_TI_STATE_MAX - 1));
+ memcpy(transaction, &tt_range_3[0], size);
+ size = sizeof(struct iwl_tt_restriction) *
+ IWL_TI_STATE_MAX;
+ memcpy(tt->restriction,
+ &restriction_range[0], size);
+ priv->thermal_throttle.advanced_tt = true;
+ }
+ } else {
+ IWL_DEBUG_POWER(priv, "Legacy Thermal Throttling\n");
+ priv->thermal_throttle.advanced_tt = false;
+ }
+}
+
+/* cleanup thermal throttling management related memory and timer */
+void iwl_tt_exit(struct iwl_priv *priv)
+{
+ struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+
+ /* stop ct_kill_exit_tm timer if activated */
+ del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm);
+ /* stop ct_kill_waiting_tm timer if activated */
+ del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm);
+ cancel_work_sync(&priv->tt_work);
+ cancel_work_sync(&priv->ct_enter);
+ cancel_work_sync(&priv->ct_exit);
+
+ if (priv->thermal_throttle.advanced_tt) {
+ /* free advance thermal throttling memory */
+ kfree(tt->restriction);
+ tt->restriction = NULL;
+ kfree(tt->transaction);
+ tt->transaction = NULL;
+ }
+}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.h b/drivers/net/wireless/iwlwifi/iwl-agn-tt.h
new file mode 100644
index 000000000000..d55060427cac
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tt.h
@@ -0,0 +1,129 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved.
+ *
+ * Portions of this file are derived from the ipw3945 project, as well
+ * as portions of the ieee80211 subsystem header files.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *****************************************************************************/
+#ifndef __iwl_tt_setting_h__
+#define __iwl_tt_setting_h__
+
+#include "iwl-commands.h"
+
+#define IWL_ABSOLUTE_ZERO 0
+#define IWL_ABSOLUTE_MAX 0xFFFFFFFF
+#define IWL_TT_INCREASE_MARGIN 5
+#define IWL_TT_CT_KILL_MARGIN 3
+
+enum iwl_antenna_ok {
+ IWL_ANT_OK_NONE,
+ IWL_ANT_OK_SINGLE,
+ IWL_ANT_OK_MULTI,
+};
+
+/* Thermal Throttling State Machine states */
+enum iwl_tt_state {
+ IWL_TI_0, /* normal temperature, system power state */
+ IWL_TI_1, /* high temperature detect, low power state */
+ IWL_TI_2, /* higher temperature detected, lower power state */
+ IWL_TI_CT_KILL, /* critical temperature detected, lowest power state */
+ IWL_TI_STATE_MAX
+};
+
+/**
+ * struct iwl_tt_restriction - Thermal Throttling restriction table
+ * @tx_stream: number of tx stream allowed
+ * @is_ht: ht enable/disable
+ * @rx_stream: number of rx stream allowed
+ *
+ * This table is used by advance thermal throttling management
+ * based on the current thermal throttling state, and determines
+ * the number of tx/rx streams and the status of HT operation.
+ */
+struct iwl_tt_restriction {
+ enum iwl_antenna_ok tx_stream;
+ enum iwl_antenna_ok rx_stream;
+ bool is_ht;
+};
+
+/**
+ * struct iwl_tt_trans - Thermal Throttling transaction table
+ * @next_state: next thermal throttling mode
+ * @tt_low: low temperature threshold to change state
+ * @tt_high: high temperature threshold to change state
+ *
+ * This is used by the advanced thermal throttling algorithm
+ * to determine the next thermal state to go based on the
+ * current temperature.
+ */
+struct iwl_tt_trans {
+ enum iwl_tt_state next_state;
+ u32 tt_low;
+ u32 tt_high;
+};
+
+/**
+ * struct iwl_tt_mgnt - Thermal Throttling Management structure
+ * @advanced_tt: advanced thermal throttle required
+ * @state: current Thermal Throttling state
+ * @tt_power_mode: Thermal Throttling power mode index
+ * being used to set power level when
+ * when thermal throttling state != IWL_TI_0
+ * the tt_power_mode should set to different
+ * power mode based on the current tt state
+ * @tt_previous_temperature: last measured temperature
+ * @iwl_tt_restriction: ptr to restriction tbl, used by advance
+ * thermal throttling to determine how many tx/rx streams
+ * should be used in tt state; and can HT be enabled or not
+ * @iwl_tt_trans: ptr to adv trans table, used by advance thermal throttling
+ * state transaction
+ * @ct_kill_toggle: used to toggle the CSR bit when checking uCode temperature
+ * @ct_kill_exit_tm: timer to exit thermal kill
+ */
+struct iwl_tt_mgmt {
+ enum iwl_tt_state state;
+ bool advanced_tt;
+ u8 tt_power_mode;
+ bool ct_kill_toggle;
+#ifdef CONFIG_IWLWIFI_DEBUG
+ s32 tt_previous_temp;
+#endif
+ struct iwl_tt_restriction *restriction;
+ struct iwl_tt_trans *transaction;
+ struct timer_list ct_kill_exit_tm;
+ struct timer_list ct_kill_waiting_tm;
+};
+
+u8 iwl_tt_current_power_mode(struct iwl_priv *priv);
+bool iwl_tt_is_low_power_state(struct iwl_priv *priv);
+bool iwl_ht_enabled(struct iwl_priv *priv);
+bool iwl_check_for_ct_kill(struct iwl_priv *priv);
+enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv);
+enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv);
+void iwl_tt_enter_ct_kill(struct iwl_priv *priv);
+void iwl_tt_exit_ct_kill(struct iwl_priv *priv);
+void iwl_tt_handler(struct iwl_priv *priv);
+void iwl_tt_initialize(struct iwl_priv *priv);
+void iwl_tt_exit(struct iwl_priv *priv);
+
+#endif /* __iwl_tt_setting_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
index 69155aa448fb..db57aea629d9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
@@ -71,18 +71,6 @@ static const u8 tid_to_ac[] = {
2, 3, 3, 2, 1, 1, 0, 0
};
-static const u8 ac_to_fifo[] = {
- IWL_TX_FIFO_VO,
- IWL_TX_FIFO_VI,
- IWL_TX_FIFO_BE,
- IWL_TX_FIFO_BK,
-};
-
-static inline int get_fifo_from_ac(u8 ac)
-{
- return ac_to_fifo[ac];
-}
-
static inline int get_ac_from_tid(u16 tid)
{
if (likely(tid < ARRAY_SIZE(tid_to_ac)))
@@ -92,10 +80,10 @@ static inline int get_ac_from_tid(u16 tid)
return -EINVAL;
}
-static inline int get_fifo_from_tid(u16 tid)
+static inline int get_fifo_from_tid(struct iwl_rxon_context *ctx, u16 tid)
{
if (likely(tid < ARRAY_SIZE(tid_to_ac)))
- return get_fifo_from_ac(tid_to_ac[tid]);
+ return ctx->ac_to_fifo[tid_to_ac[tid]];
/* no support for TIDs 8-15 yet */
return -EINVAL;
@@ -118,7 +106,7 @@ void iwlagn_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX);
- if (txq_id != IWL_CMD_QUEUE_NUM) {
+ if (txq_id != priv->cmd_queue) {
sta_id = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id;
sec_ctl = txq->cmd[txq->q.write_ptr]->cmd.tx.sec_ctl;
@@ -155,7 +143,7 @@ void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv,
WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX);
- if (txq_id != IWL_CMD_QUEUE_NUM)
+ if (txq_id != priv->cmd_queue)
sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id;
bc_ent = cpu_to_le16(1 | (sta_id << 12));
@@ -236,13 +224,13 @@ int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id,
int ret;
if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) ||
- (IWLAGN_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues
- <= txq_id)) {
+ (IWLAGN_FIRST_AMPDU_QUEUE +
+ priv->cfg->base_params->num_of_ampdu_queues <= txq_id)) {
IWL_WARN(priv,
"queue number out of range: %d, must be %d to %d\n",
txq_id, IWLAGN_FIRST_AMPDU_QUEUE,
IWLAGN_FIRST_AMPDU_QUEUE +
- priv->cfg->num_of_ampdu_queues - 1);
+ priv->cfg->base_params->num_of_ampdu_queues - 1);
return -EINVAL;
}
@@ -298,13 +286,13 @@ int iwlagn_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
u16 ssn_idx, u8 tx_fifo)
{
if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) ||
- (IWLAGN_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues
- <= txq_id)) {
+ (IWLAGN_FIRST_AMPDU_QUEUE +
+ priv->cfg->base_params->num_of_ampdu_queues <= txq_id)) {
IWL_ERR(priv,
"queue number out of range: %d, must be %d to %d\n",
txq_id, IWLAGN_FIRST_AMPDU_QUEUE,
IWLAGN_FIRST_AMPDU_QUEUE +
- priv->cfg->num_of_ampdu_queues - 1);
+ priv->cfg->base_params->num_of_ampdu_queues - 1);
return -EINVAL;
}
@@ -333,19 +321,15 @@ void iwlagn_txq_set_sched(struct iwl_priv *priv, u32 mask)
iwl_write_prph(priv, IWLAGN_SCD_TXFACT, mask);
}
-static inline int get_queue_from_ac(u16 ac)
-{
- return ac;
-}
-
/*
* handle build REPLY_TX command notification.
*/
static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv,
- struct iwl_tx_cmd *tx_cmd,
- struct ieee80211_tx_info *info,
- struct ieee80211_hdr *hdr,
- u8 std_id)
+ struct sk_buff *skb,
+ struct iwl_tx_cmd *tx_cmd,
+ struct ieee80211_tx_info *info,
+ struct ieee80211_hdr *hdr,
+ u8 std_id)
{
__le16 fc = hdr->frame_control;
__le32 tx_flags = tx_cmd->tx_flags;
@@ -365,6 +349,13 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv,
if (ieee80211_is_back_req(fc))
tx_flags |= TX_CMD_FLG_ACK_MSK | TX_CMD_FLG_IMM_BA_RSP_MASK;
+ else if (info->band == IEEE80211_BAND_2GHZ &&
+ priv->cfg->bt_params &&
+ priv->cfg->bt_params->advanced_bt_coexist &&
+ (ieee80211_is_auth(fc) || ieee80211_is_assoc_req(fc) ||
+ ieee80211_is_reassoc_req(fc) ||
+ skb->protocol == cpu_to_be16(ETH_P_PAE)))
+ tx_flags |= TX_CMD_FLG_IGNORE_BT;
tx_cmd->sta_id = std_id;
@@ -454,7 +445,14 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv,
rate_flags |= RATE_MCS_CCK_MSK;
/* Set up antennas */
- priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant,
+ if (priv->cfg->bt_params &&
+ priv->cfg->bt_params->advanced_bt_coexist &&
+ priv->bt_full_concurrent) {
+ /* operated as 1x1 in full concurrency mode */
+ priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant,
+ first_antenna(priv->hw_params.valid_tx_ant));
+ } else
+ priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant,
priv->hw_params.valid_tx_ant);
rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant);
@@ -470,8 +468,8 @@ static void iwlagn_tx_cmd_build_hwcrypto(struct iwl_priv *priv,
{
struct ieee80211_key_conf *keyconf = info->control.hw_key;
- switch (keyconf->alg) {
- case ALG_CCMP:
+ switch (keyconf->cipher) {
+ case WLAN_CIPHER_SUITE_CCMP:
tx_cmd->sec_ctl = TX_CMD_SEC_CCM;
memcpy(tx_cmd->key, keyconf->key, keyconf->keylen);
if (info->flags & IEEE80211_TX_CTL_AMPDU)
@@ -479,20 +477,20 @@ static void iwlagn_tx_cmd_build_hwcrypto(struct iwl_priv *priv,
IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n");
break;
- case ALG_TKIP:
+ case WLAN_CIPHER_SUITE_TKIP:
tx_cmd->sec_ctl = TX_CMD_SEC_TKIP;
ieee80211_get_tkip_key(keyconf, skb_frag,
IEEE80211_TKIP_P2_KEY, tx_cmd->key);
IWL_DEBUG_TX(priv, "tx_cmd with tkip hwcrypto\n");
break;
- case ALG_WEP:
+ case WLAN_CIPHER_SUITE_WEP104:
+ tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128;
+ /* fall through */
+ case WLAN_CIPHER_SUITE_WEP40:
tx_cmd->sec_ctl |= (TX_CMD_SEC_WEP |
(keyconf->keyidx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT);
- if (keyconf->keylen == WEP_KEY_LEN_128)
- tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128;
-
memcpy(&tx_cmd->key[3], keyconf->key, keyconf->keylen);
IWL_DEBUG_TX(priv, "Configuring packet for WEP encryption "
@@ -500,7 +498,7 @@ static void iwlagn_tx_cmd_build_hwcrypto(struct iwl_priv *priv,
break;
default:
- IWL_ERR(priv, "Unknown encode alg %d\n", keyconf->alg);
+ IWL_ERR(priv, "Unknown encode cipher %x\n", keyconf->cipher);
break;
}
}
@@ -519,6 +517,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
struct iwl_device_cmd *out_cmd;
struct iwl_cmd_meta *out_meta;
struct iwl_tx_cmd *tx_cmd;
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
int swq_id, txq_id;
dma_addr_t phys_addr;
dma_addr_t txcmd_phys;
@@ -533,6 +532,9 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
u8 *qc = NULL;
unsigned long flags;
+ if (info->control.vif)
+ ctx = iwl_rxon_ctx_from_vif(info->control.vif);
+
spin_lock_irqsave(&priv->lock, flags);
if (iwl_is_rfkill(priv)) {
IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n");
@@ -553,7 +555,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
hdr_len = ieee80211_hdrlen(fc);
/* Find index into station table for destination station */
- sta_id = iwl_sta_id_or_broadcast(priv, info->control.sta);
+ sta_id = iwl_sta_id_or_broadcast(priv, ctx, info->control.sta);
if (sta_id == IWL_INVALID_STATION) {
IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
hdr->addr1);
@@ -565,8 +567,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
if (sta)
sta_priv = (void *)sta->drv_priv;
- if (sta_priv && sta_id != priv->hw_params.bcast_sta_id &&
- sta_priv->asleep) {
+ if (sta_priv && sta_priv->asleep) {
WARN_ON(!(info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE));
/*
* This sends an asynchronous command to the device,
@@ -580,7 +581,20 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
iwl_sta_modify_sleep_tx_count(priv, sta_id, 1);
}
- txq_id = get_queue_from_ac(skb_get_queue_mapping(skb));
+ /*
+ * Send this frame after DTIM -- there's a special queue
+ * reserved for this for contexts that support AP mode.
+ */
+ if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) {
+ txq_id = ctx->mcast_queue;
+ /*
+ * The microcode will clear the more data
+ * bit in the last frame it transmits.
+ */
+ hdr->frame_control |=
+ cpu_to_le16(IEEE80211_FCTL_MOREDATA);
+ } else
+ txq_id = ctx->ac_to_queue[skb_get_queue_mapping(skb)];
/* irqs already disabled/saved above when locking priv->lock */
spin_lock(&priv->sta_lock);
@@ -625,6 +639,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
/* Set up driver data for this TFD */
memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info));
txq->txb[q->write_ptr].skb = skb;
+ txq->txb[q->write_ptr].ctx = ctx;
/* Set up first empty entry in queue's array of Tx/cmd buffers */
out_cmd = txq->cmd[q->write_ptr];
@@ -655,7 +670,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
iwlagn_tx_cmd_build_hwcrypto(priv, info, tx_cmd, skb, sta_id);
/* TODO need this for burst mode later on */
- iwlagn_tx_cmd_build_basic(priv, tx_cmd, info, hdr, sta_id);
+ iwlagn_tx_cmd_build_basic(priv, skb, tx_cmd, info, hdr, sta_id);
iwl_dbg_log_tx_data_frame(priv, len, hdr);
iwlagn_tx_cmd_build_rate(priv, tx_cmd, info, fc);
@@ -813,7 +828,7 @@ void iwlagn_hw_txq_ctx_free(struct iwl_priv *priv)
/* Tx queues */
if (priv->txq) {
for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
- if (txq_id == IWL_CMD_QUEUE_NUM)
+ if (txq_id == priv->cmd_queue)
iwl_cmd_queue_free(priv);
else
iwl_tx_queue_free(priv, txq_id);
@@ -870,9 +885,9 @@ int iwlagn_txq_ctx_alloc(struct iwl_priv *priv)
spin_unlock_irqrestore(&priv->lock, flags);
- /* Alloc and init all Tx queues, including the command queue (#4) */
+ /* Alloc and init all Tx queues, including the command queue (#4/#9) */
for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
- slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ?
+ slots_num = (txq_id == priv->cmd_queue) ?
TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
ret = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num,
txq_id);
@@ -910,7 +925,7 @@ void iwlagn_txq_ctx_reset(struct iwl_priv *priv)
/* Alloc and init all Tx queues, including the command queue (#4) */
for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
- slots_num = txq_id == IWL_CMD_QUEUE_NUM ?
+ slots_num = txq_id == priv->cmd_queue ?
TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
iwl_tx_queue_reset(priv, &priv->txq[txq_id], slots_num, txq_id);
}
@@ -968,7 +983,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
unsigned long flags;
struct iwl_tid_data *tid_data;
- tx_fifo = get_fifo_from_tid(tid);
+ tx_fifo = get_fifo_from_tid(iwl_rxon_ctx_from_vif(vif), tid);
if (unlikely(tx_fifo < 0))
return tx_fifo;
@@ -1024,12 +1039,12 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, u16 tid)
{
- int tx_fifo_id, txq_id, sta_id, ssn = -1;
+ int tx_fifo_id, txq_id, sta_id, ssn;
struct iwl_tid_data *tid_data;
int write_ptr, read_ptr;
unsigned long flags;
- tx_fifo_id = get_fifo_from_tid(tid);
+ tx_fifo_id = get_fifo_from_tid(iwl_rxon_ctx_from_vif(vif), tid);
if (unlikely(tx_fifo_id < 0))
return tx_fifo_id;
@@ -1042,21 +1057,26 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
spin_lock_irqsave(&priv->sta_lock, flags);
- if (priv->stations[sta_id].tid[tid].agg.state ==
- IWL_EMPTYING_HW_QUEUE_ADDBA) {
- IWL_DEBUG_HT(priv, "AGG stop before setup done\n");
- ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
- priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF;
- spin_unlock_irqrestore(&priv->sta_lock, flags);
- return 0;
- }
-
- if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_ON)
- IWL_WARN(priv, "Stopping AGG while state not ON or starting\n");
-
tid_data = &priv->stations[sta_id].tid[tid];
ssn = (tid_data->seq_number & IEEE80211_SCTL_SEQ) >> 4;
txq_id = tid_data->agg.txq_id;
+
+ switch (priv->stations[sta_id].tid[tid].agg.state) {
+ case IWL_EMPTYING_HW_QUEUE_ADDBA:
+ /*
+ * This can happen if the peer stops aggregation
+ * again before we've had a chance to drain the
+ * queue we selected previously, i.e. before the
+ * session was really started completely.
+ */
+ IWL_DEBUG_HT(priv, "AGG stop before setup done\n");
+ goto turn_off;
+ case IWL_AGG_ON:
+ break;
+ default:
+ IWL_WARN(priv, "Stopping AGG while state not ON or starting\n");
+ }
+
write_ptr = priv->txq[txq_id].q.write_ptr;
read_ptr = priv->txq[txq_id].q.read_ptr;
@@ -1070,6 +1090,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
}
IWL_DEBUG_HT(priv, "HW queue is empty\n");
+ turn_off:
priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF;
/* do not restore/save irqs */
@@ -1098,6 +1119,9 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv,
struct iwl_queue *q = &priv->txq[txq_id].q;
u8 *addr = priv->stations[sta_id].sta.sta.addr;
struct iwl_tid_data *tid_data = &priv->stations[sta_id].tid[tid];
+ struct iwl_rxon_context *ctx;
+
+ ctx = &priv->contexts[priv->stations[sta_id].ctxid];
lockdep_assert_held(&priv->sta_lock);
@@ -1108,12 +1132,12 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv,
if ((txq_id == tid_data->agg.txq_id) &&
(q->read_ptr == q->write_ptr)) {
u16 ssn = SEQ_TO_SN(tid_data->seq_number);
- int tx_fifo = get_fifo_from_tid(tid);
+ int tx_fifo = get_fifo_from_tid(ctx, tid);
IWL_DEBUG_HT(priv, "HW queue empty: continue DELBA flow\n");
priv->cfg->ops->lib->txq_agg_disable(priv, txq_id,
ssn, tx_fifo);
tid_data->agg.state = IWL_AGG_OFF;
- ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, addr, tid);
+ ieee80211_stop_tx_ba_cb_irqsafe(ctx->vif, addr, tid);
}
break;
case IWL_EMPTYING_HW_QUEUE_ADDBA:
@@ -1121,7 +1145,7 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv,
if (tid_data->tfds_in_queue == 0) {
IWL_DEBUG_HT(priv, "HW queue empty: continue ADDBA flow\n");
tid_data->agg.state = IWL_AGG_ON;
- ieee80211_start_tx_ba_cb_irqsafe(priv->vif, addr, tid);
+ ieee80211_start_tx_ba_cb_irqsafe(ctx->vif, addr, tid);
}
break;
}
@@ -1129,14 +1153,14 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv,
return 0;
}
-static void iwlagn_tx_status(struct iwl_priv *priv, struct sk_buff *skb)
+static void iwlagn_tx_status(struct iwl_priv *priv, struct iwl_tx_info *tx_info)
{
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx_info->skb->data;
struct ieee80211_sta *sta;
struct iwl_station_priv *sta_priv;
rcu_read_lock();
- sta = ieee80211_find_sta(priv->vif, hdr->addr1);
+ sta = ieee80211_find_sta(tx_info->ctx->vif, hdr->addr1);
if (sta) {
sta_priv = (void *)sta->drv_priv;
/* avoid atomic ops if this isn't a client */
@@ -1146,7 +1170,7 @@ static void iwlagn_tx_status(struct iwl_priv *priv, struct sk_buff *skb)
}
rcu_read_unlock();
- ieee80211_tx_status_irqsafe(priv->hw, skb);
+ ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb);
}
int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
@@ -1169,7 +1193,7 @@ int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
tx_info = &txq->txb[txq->q.read_ptr];
- iwlagn_tx_status(priv, tx_info->skb);
+ iwlagn_tx_status(priv, tx_info);
hdr = (struct ieee80211_hdr *)tx_info->skb->data;
if (hdr && ieee80211_is_data_qos(hdr->frame_control))
@@ -1367,3 +1391,43 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
spin_unlock_irqrestore(&priv->sta_lock, flags);
}
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+const char *iwl_get_tx_fail_reason(u32 status)
+{
+#define TX_STATUS_FAIL(x) case TX_STATUS_FAIL_ ## x: return #x
+#define TX_STATUS_POSTPONE(x) case TX_STATUS_POSTPONE_ ## x: return #x
+
+ switch (status & TX_STATUS_MSK) {
+ case TX_STATUS_SUCCESS:
+ return "SUCCESS";
+ TX_STATUS_POSTPONE(DELAY);
+ TX_STATUS_POSTPONE(FEW_BYTES);
+ TX_STATUS_POSTPONE(BT_PRIO);
+ TX_STATUS_POSTPONE(QUIET_PERIOD);
+ TX_STATUS_POSTPONE(CALC_TTAK);
+ TX_STATUS_FAIL(INTERNAL_CROSSED_RETRY);
+ TX_STATUS_FAIL(SHORT_LIMIT);
+ TX_STATUS_FAIL(LONG_LIMIT);
+ TX_STATUS_FAIL(FIFO_UNDERRUN);
+ TX_STATUS_FAIL(DRAIN_FLOW);
+ TX_STATUS_FAIL(RFKILL_FLUSH);
+ TX_STATUS_FAIL(LIFE_EXPIRE);
+ TX_STATUS_FAIL(DEST_PS);
+ TX_STATUS_FAIL(HOST_ABORTED);
+ TX_STATUS_FAIL(BT_RETRY);
+ TX_STATUS_FAIL(STA_INVALID);
+ TX_STATUS_FAIL(FRAG_DROPPED);
+ TX_STATUS_FAIL(TID_DISABLE);
+ TX_STATUS_FAIL(FIFO_FLUSHED);
+ TX_STATUS_FAIL(INSUFFICIENT_CF_POLL);
+ TX_STATUS_FAIL(PASSIVE_NO_RX);
+ TX_STATUS_FAIL(NO_BEACON_ON_RADAR);
+ }
+
+ return "UNKNOWN";
+
+#undef TX_STATUS_FAIL
+#undef TX_STATUS_POSTPONE
+}
+#endif /* CONFIG_IWLWIFI_DEBUG */
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
index 6f77441cb65a..703621107dac 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
@@ -38,6 +38,7 @@
#include "iwl-helpers.h"
#include "iwl-agn-hw.h"
#include "iwl-agn.h"
+#include "iwl-agn-calib.h"
static const s8 iwlagn_default_queue_to_tx_fifo[] = {
IWL_TX_FIFO_VO,
@@ -52,6 +53,19 @@ static const s8 iwlagn_default_queue_to_tx_fifo[] = {
IWL_TX_FIFO_UNUSED,
};
+static const s8 iwlagn_ipan_queue_to_tx_fifo[] = {
+ IWL_TX_FIFO_VO,
+ IWL_TX_FIFO_VI,
+ IWL_TX_FIFO_BE,
+ IWL_TX_FIFO_BK,
+ IWL_TX_FIFO_BK_IPAN,
+ IWL_TX_FIFO_BE_IPAN,
+ IWL_TX_FIFO_VI_IPAN,
+ IWL_TX_FIFO_VO_IPAN,
+ IWL_TX_FIFO_BE_IPAN,
+ IWLAGN_CMD_FIFO_NUM,
+};
+
static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = {
{COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP,
0, COEX_UNASSOC_IDLE_FLAGS},
@@ -201,6 +215,25 @@ static int iwlagn_set_Xtal_calib(struct iwl_priv *priv)
(u8 *)&cmd, sizeof(cmd));
}
+static int iwlagn_set_temperature_offset_calib(struct iwl_priv *priv)
+{
+ struct iwl_calib_temperature_offset_cmd cmd;
+ __le16 *offset_calib =
+ (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_TEMPERATURE);
+ cmd.hdr.op_code = IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD;
+ cmd.hdr.first_group = 0;
+ cmd.hdr.groups_num = 1;
+ cmd.hdr.data_valid = 1;
+ cmd.radio_sensor_offset = le16_to_cpu(offset_calib[1]);
+ if (!(cmd.radio_sensor_offset))
+ cmd.radio_sensor_offset = DEFAULT_RADIO_SENSOR_OFFSET;
+ cmd.reserved = 0;
+ IWL_DEBUG_CALIB(priv, "Radio sensor offset: %d\n",
+ cmd.radio_sensor_offset);
+ return iwl_calib_set(&priv->calib_results[IWL_CALIB_TEMP_OFFSET],
+ (u8 *)&cmd, sizeof(cmd));
+}
+
static int iwlagn_send_calib_cfg(struct iwl_priv *priv)
{
struct iwl_calib_cfg_cmd calib_cfg_cmd;
@@ -294,7 +327,27 @@ void iwlagn_init_alive_start(struct iwl_priv *priv)
goto restart;
}
+ if (priv->cfg->bt_params &&
+ priv->cfg->bt_params->advanced_bt_coexist) {
+ /*
+ * Tell uCode we are ready to perform calibration
+ * need to perform this before any calibration
+ * no need to close the envlope since we are going
+ * to load the runtime uCode later.
+ */
+ iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN,
+ BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
+
+ }
iwlagn_send_calib_cfg(priv);
+
+ /**
+ * temperature offset calibration is only needed for runtime ucode,
+ * so prepare the value now.
+ */
+ if (priv->cfg->need_temp_offset_calib)
+ iwlagn_set_temperature_offset_calib(priv);
+
return;
restart:
@@ -306,7 +359,7 @@ static int iwlagn_send_wimax_coex(struct iwl_priv *priv)
{
struct iwl_wimax_coex_cmd coex_cmd;
- if (priv->cfg->support_wimax_coexist) {
+ if (priv->cfg->base_params->support_wimax_coexist) {
/* UnMask wake up src at associated sleep */
coex_cmd.flags = COEX_FLAGS_ASSOC_WA_UNMASK_MSK;
@@ -329,8 +382,54 @@ static int iwlagn_send_wimax_coex(struct iwl_priv *priv)
sizeof(coex_cmd), &coex_cmd);
}
+static const u8 iwlagn_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = {
+ ((BT_COEX_PRIO_TBL_PRIO_BYPASS << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
+ (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)),
+ ((BT_COEX_PRIO_TBL_PRIO_BYPASS << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
+ (1 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)),
+ ((BT_COEX_PRIO_TBL_PRIO_LOW << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
+ (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)),
+ ((BT_COEX_PRIO_TBL_PRIO_LOW << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
+ (1 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)),
+ ((BT_COEX_PRIO_TBL_PRIO_HIGH << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
+ (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)),
+ ((BT_COEX_PRIO_TBL_PRIO_HIGH << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
+ (1 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)),
+ ((BT_COEX_PRIO_TBL_PRIO_BYPASS << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
+ (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)),
+ ((BT_COEX_PRIO_TBL_PRIO_COEX_OFF << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
+ (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)),
+ ((BT_COEX_PRIO_TBL_PRIO_COEX_ON << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
+ (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)),
+ 0, 0, 0, 0, 0, 0, 0
+};
+
+void iwlagn_send_prio_tbl(struct iwl_priv *priv)
+{
+ struct iwl_bt_coex_prio_table_cmd prio_tbl_cmd;
+
+ memcpy(prio_tbl_cmd.prio_tbl, iwlagn_bt_prio_tbl,
+ sizeof(iwlagn_bt_prio_tbl));
+ if (iwl_send_cmd_pdu(priv, REPLY_BT_COEX_PRIO_TABLE,
+ sizeof(prio_tbl_cmd), &prio_tbl_cmd))
+ IWL_ERR(priv, "failed to send BT prio tbl command\n");
+}
+
+void iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type)
+{
+ struct iwl_bt_coex_prot_env_cmd env_cmd;
+
+ env_cmd.action = action;
+ env_cmd.type = type;
+ if (iwl_send_cmd_pdu(priv, REPLY_BT_COEX_PROT_ENV,
+ sizeof(env_cmd), &env_cmd))
+ IWL_ERR(priv, "failed to send BT env command\n");
+}
+
+
int iwlagn_alive_notify(struct iwl_priv *priv)
{
+ const s8 *queues;
u32 a;
unsigned long flags;
int i, chan;
@@ -365,7 +464,7 @@ int iwlagn_alive_notify(struct iwl_priv *priv)
reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN);
iwl_write_prph(priv, IWLAGN_SCD_QUEUECHAIN_SEL,
- IWLAGN_SCD_QUEUECHAIN_SEL_ALL(priv->hw_params.max_txq_num));
+ IWLAGN_SCD_QUEUECHAIN_SEL_ALL(priv));
iwl_write_prph(priv, IWLAGN_SCD_AGGR_SEL, 0);
/* initiate the queues */
@@ -391,7 +490,13 @@ int iwlagn_alive_notify(struct iwl_priv *priv)
/* Activate all Tx DMA/FIFO channels */
priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 7));
- iwlagn_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0);
+ /* map queues to FIFOs */
+ if (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS))
+ queues = iwlagn_ipan_queue_to_tx_fifo;
+ else
+ queues = iwlagn_default_queue_to_tx_fifo;
+
+ iwlagn_set_wr_ptrs(priv, priv->cmd_queue, 0);
/* make sure all queue are not stopped */
memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped));
@@ -400,11 +505,12 @@ int iwlagn_alive_notify(struct iwl_priv *priv)
/* reset to 0 to enable all the queue first */
priv->txq_ctx_active_msk = 0;
- /* map qos queues to fifos one-to-one */
+
BUILD_BUG_ON(ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo) != 10);
+ BUILD_BUG_ON(ARRAY_SIZE(iwlagn_ipan_queue_to_tx_fifo) != 10);
- for (i = 0; i < ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo); i++) {
- int ac = iwlagn_default_queue_to_tx_fifo[i];
+ for (i = 0; i < 10; i++) {
+ int ac = queues[i];
iwl_txq_ctx_activate(priv, i);
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 10d7b9b7f064..c2636a7ab9ee 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -33,6 +33,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/pci.h>
+#include <linux/pci-aspm.h>
#include <linux/slab.h>
#include <linux/dma-mapping.h>
#include <linux/delay.h>
@@ -56,7 +57,7 @@
#include "iwl-io.h"
#include "iwl-helpers.h"
#include "iwl-sta.h"
-#include "iwl-calib.h"
+#include "iwl-agn-calib.h"
#include "iwl-agn.h"
@@ -86,29 +87,36 @@ MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
MODULE_LICENSE("GPL");
MODULE_ALIAS("iwl4965");
+static int iwlagn_ant_coupling;
+static bool iwlagn_bt_ch_announce = 1;
+
/**
- * iwl_commit_rxon - commit staging_rxon to hardware
+ * iwlagn_commit_rxon - commit staging_rxon to hardware
*
* The RXON command in staging_rxon is committed to the hardware and
* the active_rxon structure is updated with the new data. This
* function correctly transitions out of the RXON_ASSOC_MSK state if
* a HW tune is required based on the RXON structure changes.
*/
-int iwl_commit_rxon(struct iwl_priv *priv)
+int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
{
/* cast away the const for active_rxon in this function */
- struct iwl_rxon_cmd *active_rxon = (void *)&priv->active_rxon;
+ struct iwl_rxon_cmd *active_rxon = (void *)&ctx->active;
int ret;
bool new_assoc =
- !!(priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK);
+ !!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK);
+ bool old_assoc = !!(ctx->active.filter_flags & RXON_FILTER_ASSOC_MSK);
if (!iwl_is_alive(priv))
return -EBUSY;
+ if (!ctx->is_active)
+ return 0;
+
/* always get timestamp with Rx frame */
- priv->staging_rxon.flags |= RXON_FLG_TSF2HOST_MSK;
+ ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK;
- ret = iwl_check_rxon_cmd(priv);
+ ret = iwl_check_rxon_cmd(priv, ctx);
if (ret) {
IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n");
return -EINVAL;
@@ -119,7 +127,7 @@ int iwl_commit_rxon(struct iwl_priv *priv)
* abort any previous channel switch if still in process
*/
if (priv->switch_rxon.switch_in_progress &&
- (priv->switch_rxon.channel != priv->staging_rxon.channel)) {
+ (priv->switch_rxon.channel != ctx->staging.channel)) {
IWL_DEBUG_11H(priv, "abort channel switch on %d\n",
le16_to_cpu(priv->switch_rxon.channel));
iwl_chswitch_done(priv, false);
@@ -128,15 +136,15 @@ int iwl_commit_rxon(struct iwl_priv *priv)
/* If we don't need to send a full RXON, we can use
* iwl_rxon_assoc_cmd which is used to reconfigure filter
* and other flags for the current radio configuration. */
- if (!iwl_full_rxon_required(priv)) {
- ret = iwl_send_rxon_assoc(priv);
+ if (!iwl_full_rxon_required(priv, ctx)) {
+ ret = iwl_send_rxon_assoc(priv, ctx);
if (ret) {
IWL_ERR(priv, "Error setting RXON_ASSOC (%d)\n", ret);
return ret;
}
- memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
- iwl_print_rx_config_cmd(priv);
+ memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
+ iwl_print_rx_config_cmd(priv, ctx);
return 0;
}
@@ -144,13 +152,13 @@ int iwl_commit_rxon(struct iwl_priv *priv)
* an RXON_ASSOC and the new config wants the associated mask enabled,
* we must clear the associated from the active configuration
* before we apply the new config */
- if (iwl_is_associated(priv) && new_assoc) {
+ if (iwl_is_associated_ctx(ctx) && new_assoc) {
IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n");
active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
- ret = iwl_send_cmd_pdu(priv, REPLY_RXON,
- sizeof(struct iwl_rxon_cmd),
- &priv->active_rxon);
+ ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
+ sizeof(struct iwl_rxon_cmd),
+ active_rxon);
/* If the mask clearing failed then we set
* active_rxon back to what it was previously */
@@ -159,9 +167,9 @@ int iwl_commit_rxon(struct iwl_priv *priv)
IWL_ERR(priv, "Error clearing ASSOC_MSK (%d)\n", ret);
return ret;
}
- iwl_clear_ucode_stations(priv);
- iwl_restore_stations(priv);
- ret = iwl_restore_default_wep_keys(priv);
+ iwl_clear_ucode_stations(priv, ctx);
+ iwl_restore_stations(priv, ctx);
+ ret = iwl_restore_default_wep_keys(priv, ctx);
if (ret) {
IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret);
return ret;
@@ -173,47 +181,65 @@ int iwl_commit_rxon(struct iwl_priv *priv)
"* channel = %d\n"
"* bssid = %pM\n",
(new_assoc ? "" : "out"),
- le16_to_cpu(priv->staging_rxon.channel),
- priv->staging_rxon.bssid_addr);
+ le16_to_cpu(ctx->staging.channel),
+ ctx->staging.bssid_addr);
+
+ iwl_set_rxon_hwcrypto(priv, ctx, !priv->cfg->mod_params->sw_crypto);
- iwl_set_rxon_hwcrypto(priv, !priv->cfg->mod_params->sw_crypto);
+ if (!old_assoc) {
+ /*
+ * First of all, before setting associated, we need to
+ * send RXON timing so the device knows about the DTIM
+ * period and other timing values
+ */
+ ret = iwl_send_rxon_timing(priv, ctx);
+ if (ret) {
+ IWL_ERR(priv, "Error setting RXON timing!\n");
+ return ret;
+ }
+ }
+
+ if (priv->cfg->ops->hcmd->set_pan_params) {
+ ret = priv->cfg->ops->hcmd->set_pan_params(priv);
+ if (ret)
+ return ret;
+ }
/* Apply the new configuration
* RXON unassoc clears the station table in uCode so restoration of
* stations is needed after it (the RXON command) completes
*/
if (!new_assoc) {
- ret = iwl_send_cmd_pdu(priv, REPLY_RXON,
- sizeof(struct iwl_rxon_cmd), &priv->staging_rxon);
+ ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
+ sizeof(struct iwl_rxon_cmd), &ctx->staging);
if (ret) {
IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
return ret;
}
IWL_DEBUG_INFO(priv, "Return from !new_assoc RXON.\n");
- memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
- iwl_clear_ucode_stations(priv);
- iwl_restore_stations(priv);
- ret = iwl_restore_default_wep_keys(priv);
+ memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
+ iwl_clear_ucode_stations(priv, ctx);
+ iwl_restore_stations(priv, ctx);
+ ret = iwl_restore_default_wep_keys(priv, ctx);
if (ret) {
IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret);
return ret;
}
}
-
- priv->start_calib = 0;
if (new_assoc) {
+ priv->start_calib = 0;
/* Apply the new configuration
* RXON assoc doesn't clear the station table in uCode,
*/
- ret = iwl_send_cmd_pdu(priv, REPLY_RXON,
- sizeof(struct iwl_rxon_cmd), &priv->staging_rxon);
+ ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
+ sizeof(struct iwl_rxon_cmd), &ctx->staging);
if (ret) {
IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
return ret;
}
- memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
+ memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
}
- iwl_print_rx_config_cmd(priv);
+ iwl_print_rx_config_cmd(priv, ctx);
iwl_init_sensitivity(priv);
@@ -230,10 +256,14 @@ int iwl_commit_rxon(struct iwl_priv *priv)
void iwl_update_chain_flags(struct iwl_priv *priv)
{
+ struct iwl_rxon_context *ctx;
- if (priv->cfg->ops->hcmd->set_rxon_chain)
- priv->cfg->ops->hcmd->set_rxon_chain(priv);
- iwlcore_commit_rxon(priv);
+ if (priv->cfg->ops->hcmd->set_rxon_chain) {
+ for_each_context(priv, ctx) {
+ priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
+ iwlcore_commit_rxon(priv, ctx);
+ }
+ }
}
static void iwl_clear_free_frames(struct iwl_priv *priv)
@@ -284,24 +314,26 @@ static void iwl_free_frame(struct iwl_priv *priv, struct iwl_frame *frame)
}
static u32 iwl_fill_beacon_frame(struct iwl_priv *priv,
- struct ieee80211_hdr *hdr,
- int left)
+ struct ieee80211_hdr *hdr,
+ int left)
{
- if (!priv->ibss_beacon)
+ lockdep_assert_held(&priv->mutex);
+
+ if (!priv->beacon_skb)
return 0;
- if (priv->ibss_beacon->len > left)
+ if (priv->beacon_skb->len > left)
return 0;
- memcpy(hdr, priv->ibss_beacon->data, priv->ibss_beacon->len);
+ memcpy(hdr, priv->beacon_skb->data, priv->beacon_skb->len);
- return priv->ibss_beacon->len;
+ return priv->beacon_skb->len;
}
/* Parse the beacon frame to find the TIM element and set tim_idx & tim_size */
static void iwl_set_beacon_tim(struct iwl_priv *priv,
- struct iwl_tx_beacon_cmd *tx_beacon_cmd,
- u8 *beacon, u32 frame_size)
+ struct iwl_tx_beacon_cmd *tx_beacon_cmd,
+ u8 *beacon, u32 frame_size)
{
u16 tim_idx;
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)beacon;
@@ -337,6 +369,13 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv,
* beacon contents.
*/
+ lockdep_assert_held(&priv->mutex);
+
+ if (!priv->beacon_ctx) {
+ IWL_ERR(priv, "trying to build beacon w/o beacon context!\n");
+ return 0;
+ }
+
/* Initialize memory */
tx_beacon_cmd = &frame->u.beacon;
memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd));
@@ -346,20 +385,22 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv,
sizeof(frame->u) - sizeof(*tx_beacon_cmd));
if (WARN_ON_ONCE(frame_size > MAX_MPDU_SIZE))
return 0;
+ if (!frame_size)
+ return 0;
/* Set up TX command fields */
tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size);
- tx_beacon_cmd->tx.sta_id = priv->hw_params.bcast_sta_id;
+ tx_beacon_cmd->tx.sta_id = priv->beacon_ctx->bcast_sta_id;
tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
tx_beacon_cmd->tx.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK |
TX_CMD_FLG_TSF_MSK | TX_CMD_FLG_STA_RATE_MSK;
/* Set up TX beacon command fields */
iwl_set_beacon_tim(priv, tx_beacon_cmd, (u8 *)tx_beacon_cmd->frame,
- frame_size);
+ frame_size);
/* Set up packet rate and flags */
- rate = iwl_rate_get_lowest_plcp(priv);
+ rate = iwl_rate_get_lowest_plcp(priv, priv->beacon_ctx);
priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant,
priv->hw_params.valid_tx_ant);
rate_flags = iwl_ant_idx_to_flags(priv->mgmt_tx_ant);
@@ -592,23 +633,83 @@ static void iwl_bg_beacon_update(struct work_struct *work)
container_of(work, struct iwl_priv, beacon_update);
struct sk_buff *beacon;
- /* Pull updated AP beacon from mac80211. will fail if not in AP mode */
- beacon = ieee80211_beacon_get(priv->hw, priv->vif);
+ mutex_lock(&priv->mutex);
+ if (!priv->beacon_ctx) {
+ IWL_ERR(priv, "updating beacon w/o beacon context!\n");
+ goto out;
+ }
+
+ if (priv->beacon_ctx->vif->type != NL80211_IFTYPE_AP) {
+ /*
+ * The ucode will send beacon notifications even in
+ * IBSS mode, but we don't want to process them. But
+ * we need to defer the type check to here due to
+ * requiring locking around the beacon_ctx access.
+ */
+ goto out;
+ }
+ /* Pull updated AP beacon from mac80211. will fail if not in AP mode */
+ beacon = ieee80211_beacon_get(priv->hw, priv->beacon_ctx->vif);
if (!beacon) {
- IWL_ERR(priv, "update beacon failed\n");
- return;
+ IWL_ERR(priv, "update beacon failed -- keeping old\n");
+ goto out;
}
- mutex_lock(&priv->mutex);
/* new beacon skb is allocated every time; dispose previous.*/
- if (priv->ibss_beacon)
- dev_kfree_skb(priv->ibss_beacon);
+ dev_kfree_skb(priv->beacon_skb);
- priv->ibss_beacon = beacon;
- mutex_unlock(&priv->mutex);
+ priv->beacon_skb = beacon;
iwl_send_beacon_cmd(priv);
+ out:
+ mutex_unlock(&priv->mutex);
+}
+
+static void iwl_bg_bt_runtime_config(struct work_struct *work)
+{
+ struct iwl_priv *priv =
+ container_of(work, struct iwl_priv, bt_runtime_config);
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return;
+
+ /* dont send host command if rf-kill is on */
+ if (!iwl_is_ready_rf(priv))
+ return;
+ priv->cfg->ops->hcmd->send_bt_config(priv);
+}
+
+static void iwl_bg_bt_full_concurrency(struct work_struct *work)
+{
+ struct iwl_priv *priv =
+ container_of(work, struct iwl_priv, bt_full_concurrency);
+ struct iwl_rxon_context *ctx;
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return;
+
+ /* dont send host command if rf-kill is on */
+ if (!iwl_is_ready_rf(priv))
+ return;
+
+ IWL_DEBUG_INFO(priv, "BT coex in %s mode\n",
+ priv->bt_full_concurrent ?
+ "full concurrency" : "3-wire");
+
+ /*
+ * LQ & RXON updated cmds must be sent before BT Config cmd
+ * to avoid 3-wire collisions
+ */
+ mutex_lock(&priv->mutex);
+ for_each_context(priv, ctx) {
+ if (priv->cfg->ops->hcmd->set_rxon_chain)
+ priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
+ iwlcore_commit_rxon(priv, ctx);
+ }
+ mutex_unlock(&priv->mutex);
+
+ priv->cfg->ops->hcmd->send_bt_config(priv);
}
/**
@@ -763,10 +864,10 @@ static void iwl_bg_ucode_trace(unsigned long data)
static void iwl_rx_beacon_notif(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
-#ifdef CONFIG_IWLWIFI_DEBUG
struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl4965_beacon_notif *beacon =
(struct iwl4965_beacon_notif *)pkt->u.raw;
+#ifdef CONFIG_IWLWIFI_DEBUG
u8 rate = iwl_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags);
IWL_DEBUG_RX(priv, "beacon status %x retries %d iss %d "
@@ -778,8 +879,9 @@ static void iwl_rx_beacon_notif(struct iwl_priv *priv,
le32_to_cpu(beacon->low_tsf), rate);
#endif
- if ((priv->iw_mode == NL80211_IFTYPE_AP) &&
- (!test_bit(STATUS_EXIT_PENDING, &priv->status)))
+ priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status);
+
+ if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
queue_work(priv->workqueue, &priv->beacon_update);
}
@@ -836,22 +938,6 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv,
wake_up_interruptible(&priv->wait_command_queue);
}
-int iwl_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src)
-{
- if (src == IWL_PWR_SRC_VAUX) {
- if (pci_pme_capable(priv->pci_dev, PCI_D3cold))
- iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
- APMG_PS_CTRL_VAL_PWR_SRC_VAUX,
- ~APMG_PS_CTRL_MSK_PWR_SRC);
- } else {
- iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
- APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
- ~APMG_PS_CTRL_MSK_PWR_SRC);
- }
-
- return 0;
-}
-
static void iwl_bg_tx_flush(struct work_struct *work)
{
struct iwl_priv *priv =
@@ -1181,7 +1267,6 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv)
IWL_ERR(priv, "Microcode SW error detected. "
" Restarting 0x%X.\n", inta);
priv->isr_stats.sw++;
- priv->isr_stats.sw_err = inta;
iwl_irq_handle_error(priv);
handled |= CSR_INT_BIT_SW_ERR;
}
@@ -1362,7 +1447,6 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
IWL_ERR(priv, "Microcode SW error detected. "
" Restarting 0x%X.\n", inta);
priv->isr_stats.sw++;
- priv->isr_stats.sw_err = inta;
iwl_irq_handle_error(priv);
handled |= CSR_INT_BIT_SW_ERR;
}
@@ -1650,30 +1734,44 @@ static void iwl_nic_start(struct iwl_priv *priv)
struct iwlagn_ucode_capabilities {
u32 max_probe_length;
u32 standard_phy_calibration_size;
+ bool pan;
};
static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context);
static int iwl_mac_setup_register(struct iwl_priv *priv,
struct iwlagn_ucode_capabilities *capa);
+#define UCODE_EXPERIMENTAL_INDEX 100
+#define UCODE_EXPERIMENTAL_TAG "exp"
+
static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first)
{
const char *name_pre = priv->cfg->fw_name_pre;
+ char tag[8];
- if (first)
+ if (first) {
+#ifdef CONFIG_IWLWIFI_DEBUG_EXPERIMENTAL_UCODE
+ priv->fw_index = UCODE_EXPERIMENTAL_INDEX;
+ strcpy(tag, UCODE_EXPERIMENTAL_TAG);
+ } else if (priv->fw_index == UCODE_EXPERIMENTAL_INDEX) {
+#endif
priv->fw_index = priv->cfg->ucode_api_max;
- else
+ sprintf(tag, "%d", priv->fw_index);
+ } else {
priv->fw_index--;
+ sprintf(tag, "%d", priv->fw_index);
+ }
if (priv->fw_index < priv->cfg->ucode_api_min) {
IWL_ERR(priv, "no suitable firmware found!\n");
return -ENOENT;
}
- sprintf(priv->firmware_name, "%s%d%s",
- name_pre, priv->fw_index, ".ucode");
+ sprintf(priv->firmware_name, "%s%s%s", name_pre, tag, ".ucode");
- IWL_DEBUG_INFO(priv, "attempting to load firmware '%s'\n",
+ IWL_DEBUG_INFO(priv, "attempting to load firmware %s'%s'\n",
+ (priv->fw_index == UCODE_EXPERIMENTAL_INDEX)
+ ? "EXPERIMENTAL " : "",
priv->firmware_name);
return request_firmware_nowait(THIS_MODULE, 1, priv->firmware_name,
@@ -1874,6 +1972,11 @@ static int iwlagn_load_firmware(struct iwl_priv *priv,
capa->max_probe_length =
le32_to_cpup((__le32 *)tlv_data);
break;
+ case IWL_UCODE_TLV_PAN:
+ if (tlv_len)
+ goto invalid_tlv_len;
+ capa->pan = true;
+ break;
case IWL_UCODE_TLV_INIT_EVTLOG_PTR:
if (tlv_len != sizeof(u32))
goto invalid_tlv_len;
@@ -1962,14 +2065,16 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
struct iwlagn_ucode_capabilities ucode_capa = {
.max_probe_length = 200,
.standard_phy_calibration_size =
- IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE,
+ IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE,
};
memset(&pieces, 0, sizeof(pieces));
if (!ucode_raw) {
- IWL_ERR(priv, "request for firmware file '%s' failed.\n",
- priv->firmware_name);
+ if (priv->fw_index <= priv->cfg->ucode_api_max)
+ IWL_ERR(priv,
+ "request for firmware file '%s' failed.\n",
+ priv->firmware_name);
goto try_again;
}
@@ -2002,21 +2107,28 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
* firmware filename ... but we don't check for that and only rely
* on the API version read from firmware header from here on forward
*/
- if (api_ver < api_min || api_ver > api_max) {
- IWL_ERR(priv, "Driver unable to support your firmware API. "
- "Driver supports v%u, firmware is v%u.\n",
- api_max, api_ver);
- goto try_again;
- }
+ /* no api version check required for experimental uCode */
+ if (priv->fw_index != UCODE_EXPERIMENTAL_INDEX) {
+ if (api_ver < api_min || api_ver > api_max) {
+ IWL_ERR(priv,
+ "Driver unable to support your firmware API. "
+ "Driver supports v%u, firmware is v%u.\n",
+ api_max, api_ver);
+ goto try_again;
+ }
- if (api_ver != api_max)
- IWL_ERR(priv, "Firmware has old API version. Expected v%u, "
- "got v%u. New firmware can be obtained "
- "from http://www.intellinuxwireless.org.\n",
- api_max, api_ver);
+ if (api_ver != api_max)
+ IWL_ERR(priv,
+ "Firmware has old API version. Expected v%u, "
+ "got v%u. New firmware can be obtained "
+ "from http://www.intellinuxwireless.org.\n",
+ api_max, api_ver);
+ }
if (build)
- sprintf(buildstr, " build %u", build);
+ sprintf(buildstr, " build %u%s", build,
+ (priv->fw_index == UCODE_EXPERIMENTAL_INDEX)
+ ? " (EXP)" : "");
else
buildstr[0] = '\0';
@@ -2136,15 +2248,23 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
if (pieces.init_evtlog_size)
priv->_agn.init_evtlog_size = (pieces.init_evtlog_size - 16)/12;
else
- priv->_agn.init_evtlog_size = priv->cfg->max_event_log_size;
+ priv->_agn.init_evtlog_size =
+ priv->cfg->base_params->max_event_log_size;
priv->_agn.init_errlog_ptr = pieces.init_errlog_ptr;
priv->_agn.inst_evtlog_ptr = pieces.inst_evtlog_ptr;
if (pieces.inst_evtlog_size)
priv->_agn.inst_evtlog_size = (pieces.inst_evtlog_size - 16)/12;
else
- priv->_agn.inst_evtlog_size = priv->cfg->max_event_log_size;
+ priv->_agn.inst_evtlog_size =
+ priv->cfg->base_params->max_event_log_size;
priv->_agn.inst_errlog_ptr = pieces.inst_errlog_ptr;
+ if (ucode_capa.pan) {
+ priv->valid_contexts |= BIT(IWL_RXON_CTX_PAN);
+ priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN;
+ } else
+ priv->sta_key_max_num = STA_KEY_MAX_NUM;
+
/* Copy images into buffers for card's bus-master reads ... */
/* Runtime instructions (first block of data in file) */
@@ -2341,6 +2461,7 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv)
}
desc = iwl_read_targ_mem(priv, base + 1 * sizeof(u32));
+ priv->isr_stats.err_code = desc;
pc = iwl_read_targ_mem(priv, base + 2 * sizeof(u32));
blink1 = iwl_read_targ_mem(priv, base + 3 * sizeof(u32));
blink2 = iwl_read_targ_mem(priv, base + 4 * sizeof(u32));
@@ -2543,6 +2664,9 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
return pos;
}
+ /* enable/disable bt channel announcement */
+ priv->bt_ch_announce = iwlagn_bt_ch_announce;
+
#ifdef CONFIG_IWLWIFI_DEBUG
if (!(iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) && !full_log)
size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES)
@@ -2589,6 +2713,69 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
return pos;
}
+static void iwl_rf_kill_ct_config(struct iwl_priv *priv)
+{
+ struct iwl_ct_kill_config cmd;
+ struct iwl_ct_kill_throttling_config adv_cmd;
+ unsigned long flags;
+ int ret = 0;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
+ CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
+ spin_unlock_irqrestore(&priv->lock, flags);
+ priv->thermal_throttle.ct_kill_toggle = false;
+
+ if (priv->cfg->base_params->support_ct_kill_exit) {
+ adv_cmd.critical_temperature_enter =
+ cpu_to_le32(priv->hw_params.ct_kill_threshold);
+ adv_cmd.critical_temperature_exit =
+ cpu_to_le32(priv->hw_params.ct_kill_exit_threshold);
+
+ ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD,
+ sizeof(adv_cmd), &adv_cmd);
+ if (ret)
+ IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n");
+ else
+ IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD "
+ "succeeded, "
+ "critical temperature enter is %d,"
+ "exit is %d\n",
+ priv->hw_params.ct_kill_threshold,
+ priv->hw_params.ct_kill_exit_threshold);
+ } else {
+ cmd.critical_temperature_R =
+ cpu_to_le32(priv->hw_params.ct_kill_threshold);
+
+ ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD,
+ sizeof(cmd), &cmd);
+ if (ret)
+ IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n");
+ else
+ IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD "
+ "succeeded, "
+ "critical temperature is %d\n",
+ priv->hw_params.ct_kill_threshold);
+ }
+}
+
+static int iwlagn_send_calib_cfg_rt(struct iwl_priv *priv, u32 cfg)
+{
+ struct iwl_calib_cfg_cmd calib_cfg_cmd;
+ struct iwl_host_cmd cmd = {
+ .id = CALIBRATION_CFG_CMD,
+ .len = sizeof(struct iwl_calib_cfg_cmd),
+ .data = &calib_cfg_cmd,
+ };
+
+ memset(&calib_cfg_cmd, 0, sizeof(calib_cfg_cmd));
+ calib_cfg_cmd.ucd_calib_cfg.once.is_enable = IWL_CALIB_INIT_CFG_ALL;
+ calib_cfg_cmd.ucd_calib_cfg.once.start = cpu_to_le32(cfg);
+
+ return iwl_send_cmd(priv, &cmd);
+}
+
+
/**
* iwl_alive_start - called after REPLY_ALIVE notification received
* from protocol/runtime uCode (initialization uCode's
@@ -2597,6 +2784,7 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
static void iwl_alive_start(struct iwl_priv *priv)
{
int ret = 0;
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
@@ -2624,6 +2812,7 @@ static void iwl_alive_start(struct iwl_priv *priv)
goto restart;
}
+
/* After the ALIVE response, we can send host commands to the uCode */
set_bit(STATUS_ALIVE, &priv->status);
@@ -2631,12 +2820,33 @@ static void iwl_alive_start(struct iwl_priv *priv)
/* Enable timer to monitor the driver queues */
mod_timer(&priv->monitor_recover,
jiffies +
- msecs_to_jiffies(priv->cfg->monitor_recover_period));
+ msecs_to_jiffies(
+ priv->cfg->base_params->monitor_recover_period));
}
if (iwl_is_rfkill(priv))
return;
+ /* download priority table before any calibration request */
+ if (priv->cfg->bt_params &&
+ priv->cfg->bt_params->advanced_bt_coexist) {
+ /* Configure Bluetooth device coexistence support */
+ priv->bt_valid = IWLAGN_BT_ALL_VALID_MSK;
+ priv->kill_ack_mask = IWLAGN_BT_KILL_ACK_MASK_DEFAULT;
+ priv->kill_cts_mask = IWLAGN_BT_KILL_CTS_MASK_DEFAULT;
+ priv->cfg->ops->hcmd->send_bt_config(priv);
+ priv->bt_valid = IWLAGN_BT_VALID_ENABLE_FLAGS;
+ iwlagn_send_prio_tbl(priv);
+
+ /* FIXME: w/a to force change uCode BT state machine */
+ iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN,
+ BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
+ iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_CLOSE,
+ BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
+ }
+ if (priv->hw_params.calib_rt_cfg)
+ iwlagn_send_calib_cfg_rt(priv, priv->hw_params.calib_rt_cfg);
+
ieee80211_wake_queues(priv->hw);
priv->active_rate = IWL_RATES_MASK;
@@ -2645,27 +2855,32 @@ static void iwl_alive_start(struct iwl_priv *priv)
if (priv->cfg->ops->hcmd->set_tx_ant)
priv->cfg->ops->hcmd->set_tx_ant(priv, priv->cfg->valid_tx_ant);
- if (iwl_is_associated(priv)) {
+ if (iwl_is_associated_ctx(ctx)) {
struct iwl_rxon_cmd *active_rxon =
- (struct iwl_rxon_cmd *)&priv->active_rxon;
+ (struct iwl_rxon_cmd *)&ctx->active;
/* apply any changes in staging */
- priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
+ ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
} else {
+ struct iwl_rxon_context *tmp;
/* Initialize our rx_config data */
- iwl_connection_init_rx_config(priv, NULL);
+ for_each_context(priv, tmp)
+ iwl_connection_init_rx_config(priv, tmp);
if (priv->cfg->ops->hcmd->set_rxon_chain)
- priv->cfg->ops->hcmd->set_rxon_chain(priv);
+ priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
}
- /* Configure Bluetooth device coexistence support */
- priv->cfg->ops->hcmd->send_bt_config(priv);
+ if (priv->cfg->bt_params &&
+ !priv->cfg->bt_params->advanced_bt_coexist) {
+ /* Configure Bluetooth device coexistence support */
+ priv->cfg->ops->hcmd->send_bt_config(priv);
+ }
iwl_reset_run_time_calib(priv);
/* Configure the adapter for unassociated operation */
- iwlcore_commit_rxon(priv);
+ iwlcore_commit_rxon(priv, ctx);
/* At this point, the NIC is initialized and operational */
iwl_rf_kill_ct_config(priv);
@@ -2695,13 +2910,30 @@ static void __iwl_down(struct iwl_priv *priv)
IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n");
- if (!exit_pending)
- set_bit(STATUS_EXIT_PENDING, &priv->status);
+ iwl_scan_cancel_timeout(priv, 200);
- iwl_clear_ucode_stations(priv);
- iwl_dealloc_bcast_station(priv);
+ exit_pending = test_and_set_bit(STATUS_EXIT_PENDING, &priv->status);
+
+ /* Stop TX queues watchdog. We need to have STATUS_EXIT_PENDING bit set
+ * to prevent rearm timer */
+ if (priv->cfg->ops->lib->recover_from_tx_stall)
+ del_timer_sync(&priv->monitor_recover);
+
+ iwl_clear_ucode_stations(priv, NULL);
+ iwl_dealloc_bcast_stations(priv);
iwl_clear_driver_stations(priv);
+ /* reset BT coex data */
+ priv->bt_status = 0;
+ if (priv->cfg->bt_params)
+ priv->bt_traffic_load =
+ priv->cfg->bt_params->bt_init_traffic_load;
+ else
+ priv->bt_traffic_load = 0;
+ priv->bt_sco_active = false;
+ priv->bt_full_concurrent = false;
+ priv->bt_ci_compliance = 0;
+
/* Unblock any waiting calls */
wake_up_interruptible_all(&priv->wait_command_queue);
@@ -2759,14 +2991,13 @@ static void __iwl_down(struct iwl_priv *priv)
iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
/* Stop the device, and put it in low power state */
- priv->cfg->ops->lib->apm_ops.stop(priv);
+ iwl_apm_stop(priv);
exit:
memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp));
- if (priv->ibss_beacon)
- dev_kfree_skb(priv->ibss_beacon);
- priv->ibss_beacon = NULL;
+ dev_kfree_skb(priv->beacon_skb);
+ priv->beacon_skb = NULL;
/* clear out any free frames */
iwl_clear_free_frames(priv);
@@ -2834,6 +3065,7 @@ static int iwl_prepare_card_hw(struct iwl_priv *priv)
static int __iwl_up(struct iwl_priv *priv)
{
+ struct iwl_rxon_context *ctx;
int i;
int ret;
@@ -2847,9 +3079,13 @@ static int __iwl_up(struct iwl_priv *priv)
return -EIO;
}
- ret = iwl_alloc_bcast_station(priv, true);
- if (ret)
- return ret;
+ for_each_context(priv, ctx) {
+ ret = iwlagn_alloc_bcast_station(priv, ctx);
+ if (ret) {
+ iwl_dealloc_bcast_stations(priv);
+ return ret;
+ }
+ }
iwl_prepare_card_hw(priv);
@@ -2874,6 +3110,12 @@ static int __iwl_up(struct iwl_priv *priv)
iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
+ /* must be initialised before iwl_hw_nic_init */
+ if (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS))
+ priv->cmd_queue = IWL_IPAN_CMD_QUEUE_NUM;
+ else
+ priv->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
+
ret = iwlagn_hw_nic_init(priv);
if (ret) {
IWL_ERR(priv, "Unable to init nic\n");
@@ -2980,7 +3222,8 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work)
}
if (priv->start_calib) {
- if (priv->cfg->bt_statistics) {
+ if (priv->cfg->bt_params &&
+ priv->cfg->bt_params->bt_statistics) {
iwl_chain_noise_calibration(priv,
(void *)&priv->_agn.statistics_bt);
iwl_sensitivity_calibration(priv,
@@ -3004,11 +3247,42 @@ static void iwl_bg_restart(struct work_struct *data)
return;
if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) {
+ struct iwl_rxon_context *ctx;
+ bool bt_sco, bt_full_concurrent;
+ u8 bt_ci_compliance;
+ u8 bt_load;
+ u8 bt_status;
+
mutex_lock(&priv->mutex);
- priv->vif = NULL;
+ for_each_context(priv, ctx)
+ ctx->vif = NULL;
priv->is_open = 0;
+
+ /*
+ * __iwl_down() will clear the BT status variables,
+ * which is correct, but when we restart we really
+ * want to keep them so restore them afterwards.
+ *
+ * The restart process will later pick them up and
+ * re-configure the hw when we reconfigure the BT
+ * command.
+ */
+ bt_sco = priv->bt_sco_active;
+ bt_full_concurrent = priv->bt_full_concurrent;
+ bt_ci_compliance = priv->bt_ci_compliance;
+ bt_load = priv->bt_traffic_load;
+ bt_status = priv->bt_status;
+
+ __iwl_down(priv);
+
+ priv->bt_sco_active = bt_sco;
+ priv->bt_full_concurrent = bt_full_concurrent;
+ priv->bt_ci_compliance = bt_ci_compliance;
+ priv->bt_traffic_load = bt_load;
+ priv->bt_status = bt_status;
+
mutex_unlock(&priv->mutex);
- iwl_down(priv);
+ iwl_cancel_deferred_work(priv);
ieee80211_restart_hw(priv->hw);
} else {
iwl_down(priv);
@@ -3039,12 +3313,15 @@ static void iwl_bg_rx_replenish(struct work_struct *data)
void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif)
{
+ struct iwl_rxon_context *ctx;
struct ieee80211_conf *conf = NULL;
int ret = 0;
if (!vif || !priv->is_open)
return;
+ ctx = iwl_rxon_ctx_from_vif(vif);
+
if (vif->type == NL80211_IFTYPE_AP) {
IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__);
return;
@@ -3057,44 +3334,42 @@ void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif)
conf = ieee80211_get_hw_conf(priv->hw);
- priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
- iwlcore_commit_rxon(priv);
+ ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+ iwlcore_commit_rxon(priv, ctx);
- iwl_setup_rxon_timing(priv, vif);
- ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
- sizeof(priv->rxon_timing), &priv->rxon_timing);
+ ret = iwl_send_rxon_timing(priv, ctx);
if (ret)
- IWL_WARN(priv, "REPLY_RXON_TIMING failed - "
+ IWL_WARN(priv, "RXON timing - "
"Attempting to continue.\n");
- priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
+ ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
iwl_set_rxon_ht(priv, &priv->current_ht_config);
if (priv->cfg->ops->hcmd->set_rxon_chain)
- priv->cfg->ops->hcmd->set_rxon_chain(priv);
+ priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
- priv->staging_rxon.assoc_id = cpu_to_le16(vif->bss_conf.aid);
+ ctx->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid);
IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n",
vif->bss_conf.aid, vif->bss_conf.beacon_int);
if (vif->bss_conf.use_short_preamble)
- priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
+ ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
else
- priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
+ ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
- if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) {
+ if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
if (vif->bss_conf.use_short_slot)
- priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
+ ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
else
- priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
+ ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
}
- iwlcore_commit_rxon(priv);
+ iwlcore_commit_rxon(priv, ctx);
IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n",
- vif->bss_conf.aid, priv->active_rxon.bssid_addr);
+ vif->bss_conf.aid, ctx->active.bssid_addr);
switch (vif->type) {
case NL80211_IFTYPE_STATION:
@@ -3137,14 +3412,17 @@ static int iwl_mac_setup_register(struct iwl_priv *priv,
{
int ret;
struct ieee80211_hw *hw = priv->hw;
+ struct iwl_rxon_context *ctx;
+
hw->rate_control_algorithm = "iwl-agn-rs";
/* Tell mac80211 our characteristics */
hw->flags = IEEE80211_HW_SIGNAL_DBM |
IEEE80211_HW_AMPDU_AGGREGATION |
+ IEEE80211_HW_NEED_DTIM_PERIOD |
IEEE80211_HW_SPECTRUM_MGMT;
- if (!priv->cfg->broken_powersave)
+ if (!priv->cfg->base_params->broken_powersave)
hw->flags |= IEEE80211_HW_SUPPORTS_PS |
IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
@@ -3155,9 +3433,10 @@ static int iwl_mac_setup_register(struct iwl_priv *priv,
hw->sta_data_size = sizeof(struct iwl_station_priv);
hw->vif_data_size = sizeof(struct iwl_vif_priv);
- hw->wiphy->interface_modes =
- BIT(NL80211_IFTYPE_STATION) |
- BIT(NL80211_IFTYPE_ADHOC);
+ for_each_context(priv, ctx) {
+ hw->wiphy->interface_modes |= ctx->interface_modes;
+ hw->wiphy->interface_modes |= ctx->exclusive_interface_modes;
+ }
hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
WIPHY_FLAG_DISABLE_BEACON_HINTS;
@@ -3247,15 +3526,6 @@ static void iwl_mac_stop(struct ieee80211_hw *hw)
priv->is_open = 0;
- if (iwl_is_ready_rf(priv) || test_bit(STATUS_SCAN_HW, &priv->status)) {
- /* stop mac, cancel any scan request and clear
- * RXON_FILTER_ASSOC_MSK BIT
- */
- mutex_lock(&priv->mutex);
- iwl_scan_cancel_timeout(priv, 100);
- mutex_unlock(&priv->mutex);
- }
-
iwl_down(priv);
flush_workqueue(priv->workqueue);
@@ -3285,24 +3555,25 @@ static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif)
{
+ struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
int ret = 0;
+ lockdep_assert_held(&priv->mutex);
+
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
/* The following should be done only at AP bring up */
- if (!iwl_is_associated(priv)) {
+ if (!iwl_is_associated_ctx(ctx)) {
/* RXON - unassoc (to set timing command) */
- priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
- iwlcore_commit_rxon(priv);
+ ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+ iwlcore_commit_rxon(priv, ctx);
/* RXON Timing */
- iwl_setup_rxon_timing(priv, vif);
- ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
- sizeof(priv->rxon_timing), &priv->rxon_timing);
+ ret = iwl_send_rxon_timing(priv, ctx);
if (ret)
- IWL_WARN(priv, "REPLY_RXON_TIMING failed - "
+ IWL_WARN(priv, "RXON timing failed - "
"Attempting to continue.\n");
/* AP has all antennas */
@@ -3310,28 +3581,30 @@ void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif)
priv->hw_params.valid_rx_ant;
iwl_set_rxon_ht(priv, &priv->current_ht_config);
if (priv->cfg->ops->hcmd->set_rxon_chain)
- priv->cfg->ops->hcmd->set_rxon_chain(priv);
+ priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
- priv->staging_rxon.assoc_id = 0;
+ ctx->staging.assoc_id = 0;
if (vif->bss_conf.use_short_preamble)
- priv->staging_rxon.flags |=
+ ctx->staging.flags |=
RXON_FLG_SHORT_PREAMBLE_MSK;
else
- priv->staging_rxon.flags &=
+ ctx->staging.flags &=
~RXON_FLG_SHORT_PREAMBLE_MSK;
- if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) {
+ if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
if (vif->bss_conf.use_short_slot)
- priv->staging_rxon.flags |=
+ ctx->staging.flags |=
RXON_FLG_SHORT_SLOT_MSK;
else
- priv->staging_rxon.flags &=
+ ctx->staging.flags &=
~RXON_FLG_SHORT_SLOT_MSK;
}
+ /* need to send beacon cmd before committing assoc RXON! */
+ iwl_send_beacon_cmd(priv);
/* restore RXON assoc */
- priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
- iwlcore_commit_rxon(priv);
+ ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
+ iwlcore_commit_rxon(priv, ctx);
}
iwl_send_beacon_cmd(priv);
@@ -3348,9 +3621,11 @@ static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw,
{
struct iwl_priv *priv = hw->priv;
+ struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
+
IWL_DEBUG_MAC80211(priv, "enter\n");
- iwl_update_tkip_key(priv, keyconf, sta,
+ iwl_update_tkip_key(priv, vif_priv->ctx, keyconf, sta,
iv32, phase1key);
IWL_DEBUG_MAC80211(priv, "leave\n");
@@ -3362,6 +3637,8 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
struct ieee80211_key_conf *key)
{
struct iwl_priv *priv = hw->priv;
+ struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
+ struct iwl_rxon_context *ctx = vif_priv->ctx;
int ret;
u8 sta_id;
bool is_default_wep_key = false;
@@ -3373,7 +3650,7 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
return -EOPNOTSUPP;
}
- sta_id = iwl_sta_id_or_broadcast(priv, sta);
+ sta_id = iwl_sta_id_or_broadcast(priv, vif_priv->ctx, sta);
if (sta_id == IWL_INVALID_STATION)
return -EINVAL;
@@ -3386,9 +3663,11 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
* in 1X mode.
* In legacy wep mode, we use another host command to the uCode.
*/
- if (key->alg == ALG_WEP && !sta && vif->type != NL80211_IFTYPE_AP) {
+ if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
+ key->cipher == WLAN_CIPHER_SUITE_WEP104) &&
+ !sta) {
if (cmd == SET_KEY)
- is_default_wep_key = !priv->key_mapping_key;
+ is_default_wep_key = !ctx->key_mapping_keys;
else
is_default_wep_key =
(key->hw_key_idx == HW_KEY_DEFAULT);
@@ -3397,17 +3676,18 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
switch (cmd) {
case SET_KEY:
if (is_default_wep_key)
- ret = iwl_set_default_wep_key(priv, key);
+ ret = iwl_set_default_wep_key(priv, vif_priv->ctx, key);
else
- ret = iwl_set_dynamic_key(priv, key, sta_id);
+ ret = iwl_set_dynamic_key(priv, vif_priv->ctx,
+ key, sta_id);
IWL_DEBUG_MAC80211(priv, "enable hwcrypto key\n");
break;
case DISABLE_KEY:
if (is_default_wep_key)
- ret = iwl_remove_default_wep_key(priv, key);
+ ret = iwl_remove_default_wep_key(priv, ctx, key);
else
- ret = iwl_remove_dynamic_key(priv, key, sta_id);
+ ret = iwl_remove_dynamic_key(priv, ctx, key, sta_id);
IWL_DEBUG_MAC80211(priv, "disable hwcrypto key\n");
break;
@@ -3467,7 +3747,8 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
}
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
ret = 0;
- if (priv->cfg->use_rts_for_aggregation) {
+ if (priv->cfg->ht_params &&
+ priv->cfg->ht_params->use_rts_for_aggregation) {
struct iwl_station_priv *sta_priv =
(void *) sta->drv_priv;
/*
@@ -3476,12 +3757,13 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
sta_priv->lq_sta.lq.general_params.flags &=
~LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK;
- iwl_send_lq_cmd(priv, &sta_priv->lq_sta.lq,
- CMD_ASYNC, false);
+ iwl_send_lq_cmd(priv, iwl_rxon_ctx_from_vif(vif),
+ &sta_priv->lq_sta.lq, CMD_ASYNC, false);
}
break;
case IEEE80211_AMPDU_TX_OPERATIONAL:
- if (priv->cfg->use_rts_for_aggregation) {
+ if (priv->cfg->ht_params &&
+ priv->cfg->ht_params->use_rts_for_aggregation) {
struct iwl_station_priv *sta_priv =
(void *) sta->drv_priv;
@@ -3492,8 +3774,8 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
sta_priv->lq_sta.lq.general_params.flags |=
LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK;
- iwl_send_lq_cmd(priv, &sta_priv->lq_sta.lq,
- CMD_ASYNC, false);
+ iwl_send_lq_cmd(priv, iwl_rxon_ctx_from_vif(vif),
+ &sta_priv->lq_sta.lq, CMD_ASYNC, false);
}
ret = 0;
break;
@@ -3539,6 +3821,7 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
{
struct iwl_priv *priv = hw->priv;
struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
+ struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
bool is_ap = vif->type == NL80211_IFTYPE_STATION;
int ret;
u8 sta_id;
@@ -3554,8 +3837,8 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
if (vif->type == NL80211_IFTYPE_AP)
sta_priv->client = true;
- ret = iwl_add_station_common(priv, sta->addr, is_ap, &sta->ht_cap,
- &sta_id);
+ ret = iwl_add_station_common(priv, vif_priv->ctx, sta->addr,
+ is_ap, sta, &sta_id);
if (ret) {
IWL_ERR(priv, "Unable to add station %pM (%d)\n",
sta->addr, ret);
@@ -3581,7 +3864,17 @@ static void iwl_mac_channel_switch(struct ieee80211_hw *hw,
struct iwl_priv *priv = hw->priv;
const struct iwl_channel_info *ch_info;
struct ieee80211_conf *conf = &hw->conf;
+ struct ieee80211_channel *channel = ch_switch->channel;
struct iwl_ht_config *ht_conf = &priv->current_ht_config;
+ /*
+ * MULTI-FIXME
+ * When we add support for multiple interfaces, we need to
+ * revisit this. The channel switch command in the device
+ * only affects the BSS context, but what does that really
+ * mean? And what if we get a CSA on the second interface?
+ * This needs a lot of work.
+ */
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
u16 ch;
unsigned long flags = 0;
@@ -3594,7 +3887,7 @@ static void iwl_mac_channel_switch(struct ieee80211_hw *hw,
test_bit(STATUS_SCANNING, &priv->status))
goto out_exit;
- if (!iwl_is_associated(priv))
+ if (!iwl_is_associated_ctx(ctx))
goto out_exit;
/* channel switch in progress */
@@ -3604,11 +3897,10 @@ static void iwl_mac_channel_switch(struct ieee80211_hw *hw,
mutex_lock(&priv->mutex);
if (priv->cfg->ops->lib->set_channel_switch) {
- ch = ieee80211_frequency_to_channel(
- ch_switch->channel->center_freq);
- if (le16_to_cpu(priv->active_rxon.channel) != ch) {
+ ch = channel->hw_value;
+ if (le16_to_cpu(ctx->active.channel) != ch) {
ch_info = iwl_get_channel_info(priv,
- conf->channel->band,
+ channel->band,
ch);
if (!is_channel_valid(ch_info)) {
IWL_DEBUG_MAC80211(priv, "invalid channel\n");
@@ -3619,34 +3911,31 @@ static void iwl_mac_channel_switch(struct ieee80211_hw *hw,
priv->current_ht_config.smps = conf->smps_mode;
/* Configure HT40 channels */
- ht_conf->is_ht = conf_is_ht(conf);
- if (ht_conf->is_ht) {
+ ctx->ht.enabled = conf_is_ht(conf);
+ if (ctx->ht.enabled) {
if (conf_is_ht40_minus(conf)) {
- ht_conf->extension_chan_offset =
+ ctx->ht.extension_chan_offset =
IEEE80211_HT_PARAM_CHA_SEC_BELOW;
- ht_conf->is_40mhz = true;
+ ctx->ht.is_40mhz = true;
} else if (conf_is_ht40_plus(conf)) {
- ht_conf->extension_chan_offset =
+ ctx->ht.extension_chan_offset =
IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
- ht_conf->is_40mhz = true;
+ ctx->ht.is_40mhz = true;
} else {
- ht_conf->extension_chan_offset =
+ ctx->ht.extension_chan_offset =
IEEE80211_HT_PARAM_CHA_SEC_NONE;
- ht_conf->is_40mhz = false;
+ ctx->ht.is_40mhz = false;
}
} else
- ht_conf->is_40mhz = false;
+ ctx->ht.is_40mhz = false;
- /* if we are switching from ht to 2.4 clear flags
- * from any ht related info since 2.4 does not
- * support ht */
- if ((le16_to_cpu(priv->staging_rxon.channel) != ch))
- priv->staging_rxon.flags = 0;
+ if ((le16_to_cpu(ctx->staging.channel) != ch))
+ ctx->staging.flags = 0;
- iwl_set_rxon_channel(priv, conf->channel);
+ iwl_set_rxon_channel(priv, channel, ctx);
iwl_set_rxon_ht(priv, ht_conf);
- iwl_set_flags_for_band(priv, conf->channel->band,
- priv->vif);
+ iwl_set_flags_for_band(priv, ctx, channel->band,
+ ctx->vif);
spin_unlock_irqrestore(&priv->lock, flags);
iwl_set_rate(priv);
@@ -3663,7 +3952,7 @@ out:
mutex_unlock(&priv->mutex);
out_exit:
if (!priv->switch_rxon.switch_in_progress)
- ieee80211_chswitch_done(priv->vif, false);
+ ieee80211_chswitch_done(ctx->vif, false);
IWL_DEBUG_MAC80211(priv, "leave\n");
}
@@ -3674,6 +3963,7 @@ static void iwlagn_configure_filter(struct ieee80211_hw *hw,
{
struct iwl_priv *priv = hw->priv;
__le32 filter_or = 0, filter_nand = 0;
+ struct iwl_rxon_context *ctx;
#define CHK(test, flag) do { \
if (*total_flags & (test)) \
@@ -3693,10 +3983,11 @@ static void iwlagn_configure_filter(struct ieee80211_hw *hw,
mutex_lock(&priv->mutex);
- priv->staging_rxon.filter_flags &= ~filter_nand;
- priv->staging_rxon.filter_flags |= filter_or;
-
- iwlcore_commit_rxon(priv);
+ for_each_context(priv, ctx) {
+ ctx->staging.filter_flags &= ~filter_nand;
+ ctx->staging.filter_flags |= filter_or;
+ iwlcore_commit_rxon(priv, ctx);
+ }
mutex_unlock(&priv->mutex);
@@ -3765,6 +4056,8 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update);
INIT_WORK(&priv->run_time_calib_work, iwl_bg_run_time_calib_work);
INIT_WORK(&priv->tx_flush, iwl_bg_tx_flush);
+ INIT_WORK(&priv->bt_full_concurrency, iwl_bg_bt_full_concurrency);
+ INIT_WORK(&priv->bt_runtime_config, iwl_bg_bt_runtime_config);
INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start);
INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start);
@@ -3788,7 +4081,7 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
priv->cfg->ops->lib->recover_from_tx_stall;
}
- if (!priv->cfg->use_isr_legacy)
+ if (!priv->cfg->base_params->use_isr_legacy)
tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
iwl_irq_tasklet, (unsigned long)priv);
else
@@ -3802,15 +4095,17 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv)
priv->cfg->ops->lib->cancel_deferred_work(priv);
cancel_delayed_work_sync(&priv->init_alive_start);
- cancel_delayed_work(&priv->scan_check);
- cancel_work_sync(&priv->start_internal_scan);
cancel_delayed_work(&priv->alive_start);
cancel_work_sync(&priv->run_time_calib_work);
cancel_work_sync(&priv->beacon_update);
+
+ iwl_cancel_scan_deferred_work(priv);
+
+ cancel_work_sync(&priv->bt_full_concurrency);
+ cancel_work_sync(&priv->bt_runtime_config);
+
del_timer_sync(&priv->statistics_periodic);
del_timer_sync(&priv->ucode_trace);
- if (priv->cfg->ops->lib->recover_from_tx_stall)
- del_timer_sync(&priv->monitor_recover);
}
static void iwl_init_hw_rates(struct iwl_priv *priv,
@@ -3838,8 +4133,6 @@ static int iwl_init_drv(struct iwl_priv *priv)
{
int ret;
- priv->ibss_beacon = NULL;
-
spin_lock_init(&priv->sta_lock);
spin_lock_init(&priv->hcmd_lock);
@@ -3865,10 +4158,23 @@ static int iwl_init_drv(struct iwl_priv *priv)
/* Choose which receivers/antennas to use */
if (priv->cfg->ops->hcmd->set_rxon_chain)
- priv->cfg->ops->hcmd->set_rxon_chain(priv);
+ priv->cfg->ops->hcmd->set_rxon_chain(priv,
+ &priv->contexts[IWL_RXON_CTX_BSS]);
iwl_init_scan_params(priv);
+ /* init bt coex */
+ if (priv->cfg->bt_params &&
+ priv->cfg->bt_params->advanced_bt_coexist) {
+ priv->kill_ack_mask = IWLAGN_BT_KILL_ACK_MASK_DEFAULT;
+ priv->kill_cts_mask = IWLAGN_BT_KILL_CTS_MASK_DEFAULT;
+ priv->bt_valid = IWLAGN_BT_ALL_VALID_MSK;
+ priv->bt_on_thresh = BT_ON_THRESHOLD_DEF;
+ priv->bt_duration = BT_DURATION_LIMIT_DEF;
+ priv->dynamic_frag_thresh = BT_FRAG_THRESHOLD_DEF;
+ priv->dynamic_agg_thresh = BT_AGG_THRESHOLD_DEF;
+ }
+
/* Set the tx_power_user_lmt to the lowest power level
* this value will get overwritten by channel max power avg
* from eeprom */
@@ -3923,11 +4229,60 @@ static struct ieee80211_ops iwl_hw_ops = {
.sta_remove = iwl_mac_sta_remove,
.channel_switch = iwl_mac_channel_switch,
.flush = iwl_mac_flush,
+ .tx_last_beacon = iwl_mac_tx_last_beacon,
+};
+
+static void iwl_hw_detect(struct iwl_priv *priv)
+{
+ priv->hw_rev = _iwl_read32(priv, CSR_HW_REV);
+ priv->hw_wa_rev = _iwl_read32(priv, CSR_HW_REV_WA_REG);
+ pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &priv->rev_id);
+ IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", priv->rev_id);
+}
+
+static int iwl_set_hw_params(struct iwl_priv *priv)
+{
+ priv->hw_params.max_rxq_size = RX_QUEUE_SIZE;
+ priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG;
+ if (priv->cfg->mod_params->amsdu_size_8K)
+ priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_8K);
+ else
+ priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_4K);
+
+ priv->hw_params.max_beacon_itrvl = IWL_MAX_UCODE_BEACON_INTERVAL;
+
+ if (priv->cfg->mod_params->disable_11n)
+ priv->cfg->sku &= ~IWL_SKU_N;
+
+ /* Device-specific setup */
+ return priv->cfg->ops->lib->set_hw_params(priv);
+}
+
+static const u8 iwlagn_bss_ac_to_fifo[] = {
+ IWL_TX_FIFO_VO,
+ IWL_TX_FIFO_VI,
+ IWL_TX_FIFO_BE,
+ IWL_TX_FIFO_BK,
+};
+
+static const u8 iwlagn_bss_ac_to_queue[] = {
+ 0, 1, 2, 3,
+};
+
+static const u8 iwlagn_pan_ac_to_fifo[] = {
+ IWL_TX_FIFO_VO_IPAN,
+ IWL_TX_FIFO_VI_IPAN,
+ IWL_TX_FIFO_BE_IPAN,
+ IWL_TX_FIFO_BK_IPAN,
+};
+
+static const u8 iwlagn_pan_ac_to_queue[] = {
+ 7, 6, 5, 4,
};
static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
- int err = 0;
+ int err = 0, i;
struct iwl_priv *priv;
struct ieee80211_hw *hw;
struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
@@ -3941,9 +4296,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* Disabling hardware scan means that mac80211 will perform scans
* "the hard way", rather than using device's scan. */
if (cfg->mod_params->disable_hw_scan) {
- if (iwl_debug_level & IWL_DL_INFO)
- dev_printk(KERN_DEBUG, &(pdev->dev),
- "Disabling hw_scan\n");
+ dev_printk(KERN_DEBUG, &(pdev->dev),
+ "sw scan support is deprecated\n");
iwl_hw_ops.hw_scan = NULL;
}
@@ -3955,6 +4309,53 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
priv = hw->priv;
/* At this point both hw and priv are allocated. */
+ /*
+ * The default context is always valid,
+ * more may be discovered when firmware
+ * is loaded.
+ */
+ priv->valid_contexts = BIT(IWL_RXON_CTX_BSS);
+
+ for (i = 0; i < NUM_IWL_RXON_CTX; i++)
+ priv->contexts[i].ctxid = i;
+
+ priv->contexts[IWL_RXON_CTX_BSS].always_active = true;
+ priv->contexts[IWL_RXON_CTX_BSS].is_active = true;
+ priv->contexts[IWL_RXON_CTX_BSS].rxon_cmd = REPLY_RXON;
+ priv->contexts[IWL_RXON_CTX_BSS].rxon_timing_cmd = REPLY_RXON_TIMING;
+ priv->contexts[IWL_RXON_CTX_BSS].rxon_assoc_cmd = REPLY_RXON_ASSOC;
+ priv->contexts[IWL_RXON_CTX_BSS].qos_cmd = REPLY_QOS_PARAM;
+ priv->contexts[IWL_RXON_CTX_BSS].ap_sta_id = IWL_AP_ID;
+ priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY;
+ priv->contexts[IWL_RXON_CTX_BSS].ac_to_fifo = iwlagn_bss_ac_to_fifo;
+ priv->contexts[IWL_RXON_CTX_BSS].ac_to_queue = iwlagn_bss_ac_to_queue;
+ priv->contexts[IWL_RXON_CTX_BSS].exclusive_interface_modes =
+ BIT(NL80211_IFTYPE_ADHOC);
+ priv->contexts[IWL_RXON_CTX_BSS].interface_modes =
+ BIT(NL80211_IFTYPE_STATION);
+ priv->contexts[IWL_RXON_CTX_BSS].ibss_devtype = RXON_DEV_TYPE_IBSS;
+ priv->contexts[IWL_RXON_CTX_BSS].station_devtype = RXON_DEV_TYPE_ESS;
+ priv->contexts[IWL_RXON_CTX_BSS].unused_devtype = RXON_DEV_TYPE_ESS;
+
+ priv->contexts[IWL_RXON_CTX_PAN].rxon_cmd = REPLY_WIPAN_RXON;
+ priv->contexts[IWL_RXON_CTX_PAN].rxon_timing_cmd = REPLY_WIPAN_RXON_TIMING;
+ priv->contexts[IWL_RXON_CTX_PAN].rxon_assoc_cmd = REPLY_WIPAN_RXON_ASSOC;
+ priv->contexts[IWL_RXON_CTX_PAN].qos_cmd = REPLY_WIPAN_QOS_PARAM;
+ priv->contexts[IWL_RXON_CTX_PAN].ap_sta_id = IWL_AP_ID_PAN;
+ priv->contexts[IWL_RXON_CTX_PAN].wep_key_cmd = REPLY_WIPAN_WEPKEY;
+ priv->contexts[IWL_RXON_CTX_PAN].bcast_sta_id = IWLAGN_PAN_BCAST_ID;
+ priv->contexts[IWL_RXON_CTX_PAN].station_flags = STA_FLG_PAN_STATION;
+ priv->contexts[IWL_RXON_CTX_PAN].ac_to_fifo = iwlagn_pan_ac_to_fifo;
+ priv->contexts[IWL_RXON_CTX_PAN].ac_to_queue = iwlagn_pan_ac_to_queue;
+ priv->contexts[IWL_RXON_CTX_PAN].mcast_queue = IWL_IPAN_MCAST_QUEUE;
+ priv->contexts[IWL_RXON_CTX_PAN].interface_modes =
+ BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP);
+ priv->contexts[IWL_RXON_CTX_PAN].ap_devtype = RXON_DEV_TYPE_CP;
+ priv->contexts[IWL_RXON_CTX_PAN].station_devtype = RXON_DEV_TYPE_2STA;
+ priv->contexts[IWL_RXON_CTX_PAN].unused_devtype = RXON_DEV_TYPE_P2P;
+
+ BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
+
SET_IEEE80211_DEV(hw, &pdev->dev);
IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n");
@@ -3962,12 +4363,23 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
priv->pci_dev = pdev;
priv->inta_mask = CSR_INI_SET_MASK;
+ /* is antenna coupling more than 35dB ? */
+ priv->bt_ant_couple_ok =
+ (iwlagn_ant_coupling > IWL_BT_ANTENNA_COUPLING_THRESHOLD) ?
+ true : false;
+
+ /* enable/disable bt channel announcement */
+ priv->bt_ch_announce = iwlagn_bt_ch_announce;
+
if (iwl_alloc_traffic_mem(priv))
IWL_ERR(priv, "Not enough memory to generate traffic log\n");
/**************************
* 2. Initializing PCI bus
**************************/
+ pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
+ PCIE_LINK_STATE_CLKPM);
+
if (pci_enable_device(pdev)) {
err = -ENODEV;
goto out_ieee80211_free_hw;
@@ -4190,7 +4602,7 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
* paths to avoid running iwl_down() at all before leaving driver.
* This (inexpensive) call *makes sure* device is reset.
*/
- priv->cfg->ops->lib->apm_ops.stop(priv);
+ iwl_apm_stop(priv);
iwl_tt_exit(priv);
@@ -4233,8 +4645,7 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
iwl_free_isr_ict(priv);
- if (priv->ibss_beacon)
- dev_kfree_skb(priv->ibss_beacon);
+ dev_kfree_skb(priv->beacon_skb);
ieee80211_free_hw(priv->hw);
}
@@ -4398,6 +4809,22 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
{IWL_PCI_DEVICE(0x0083, 0x1326, iwl1000_bg_cfg)},
{IWL_PCI_DEVICE(0x0084, 0x1216, iwl1000_bg_cfg)},
{IWL_PCI_DEVICE(0x0084, 0x1316, iwl1000_bg_cfg)},
+
+/* 100 Series WiFi */
+ {IWL_PCI_DEVICE(0x08AE, 0x1005, iwl100_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x08AF, 0x1015, iwl100_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x08AE, 0x1025, iwl100_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x08AE, 0x1007, iwl100_bg_cfg)},
+ {IWL_PCI_DEVICE(0x08AE, 0x1017, iwl100_bg_cfg)},
+
+/* 130 Series WiFi */
+ {IWL_PCI_DEVICE(0x0896, 0x5005, iwl130_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0896, 0x5007, iwl130_bg_cfg)},
+ {IWL_PCI_DEVICE(0x0897, 0x5015, iwl130_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0897, 0x5017, iwl130_bg_cfg)},
+ {IWL_PCI_DEVICE(0x0896, 0x5025, iwl130_bgn_cfg)},
+ {IWL_PCI_DEVICE(0x0896, 0x5027, iwl130_bg_cfg)},
+
#endif /* CONFIG_IWL5000 */
{0}
@@ -4486,9 +4913,18 @@ module_param_named(fw_restart, iwlagn_mod_params.restart_fw, int, S_IRUGO);
MODULE_PARM_DESC(fw_restart, "restart firmware in case of error");
module_param_named(
disable_hw_scan, iwlagn_mod_params.disable_hw_scan, int, S_IRUGO);
-MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)");
+MODULE_PARM_DESC(disable_hw_scan,
+ "disable hardware scanning (default 0) (deprecated)");
module_param_named(ucode_alternative, iwlagn_wanted_ucode_alternative, int,
S_IRUGO);
MODULE_PARM_DESC(ucode_alternative,
"specify ucode alternative to use from ucode file");
+
+module_param_named(antenna_coupling, iwlagn_ant_coupling, int, S_IRUGO);
+MODULE_PARM_DESC(antenna_coupling,
+ "specify antenna coupling in dB (defualt: 0 dB)");
+
+module_param_named(bt_ch_announce, iwlagn_bt_ch_announce, bool, S_IRUGO);
+MODULE_PARM_DESC(bt_ch_announce,
+ "Enable BT channel announcement mode (default: enable)");
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h
index cc6464dc72e5..f525d55f2c0f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.h
@@ -92,9 +92,14 @@ extern struct iwl_cfg iwl6050_2abg_cfg;
extern struct iwl_cfg iwl6050g2_bgn_cfg;
extern struct iwl_cfg iwl1000_bgn_cfg;
extern struct iwl_cfg iwl1000_bg_cfg;
+extern struct iwl_cfg iwl100_bgn_cfg;
+extern struct iwl_cfg iwl100_bg_cfg;
+extern struct iwl_cfg iwl130_bgn_cfg;
+extern struct iwl_cfg iwl130_bg_cfg;
extern struct iwl_mod_params iwlagn_mod_params;
extern struct iwl_hcmd_ops iwlagn_hcmd;
+extern struct iwl_hcmd_ops iwlagn_bt_hcmd;
extern struct iwl_hcmd_utils_ops iwlagn_hcmd_utils;
int iwl_reset_ict(struct iwl_priv *priv);
@@ -124,6 +129,10 @@ void iwlagn_txq_set_sched(struct iwl_priv *priv, u32 mask);
void iwl_free_tfds_in_queue(struct iwl_priv *priv,
int sta_id, int tid, int freed);
+/* RXON */
+int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
+void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
+
/* uCode */
int iwlagn_load_ucode(struct iwl_priv *priv);
void iwlagn_rx_calib_result(struct iwl_priv *priv,
@@ -133,6 +142,8 @@ void iwlagn_rx_calib_complete(struct iwl_priv *priv,
void iwlagn_init_alive_start(struct iwl_priv *priv);
int iwlagn_alive_notify(struct iwl_priv *priv);
int iwl_verify_ucode(struct iwl_priv *priv);
+void iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type);
+void iwlagn_send_prio_tbl(struct iwl_priv *priv);
/* lib */
void iwl_check_abort_status(struct iwl_priv *priv,
@@ -151,6 +162,8 @@ int iwlagn_hw_nic_init(struct iwl_priv *priv);
int iwlagn_wait_tx_queue_empty(struct iwl_priv *priv);
int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control);
void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control);
+void iwl_dump_csr(struct iwl_priv *priv);
+int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display);
/* rx */
void iwlagn_rx_queue_restock(struct iwl_priv *priv);
@@ -164,8 +177,15 @@ void iwlagn_rx_reply_rx(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb);
void iwlagn_rx_reply_rx_phy(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb);
+void iwl_rx_handle(struct iwl_priv *priv);
/* tx */
+void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq);
+int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv,
+ struct iwl_tx_queue *txq,
+ dma_addr_t addr, u16 len, u8 reset, u8 pad);
+int iwl_hw_tx_queue_init(struct iwl_priv *priv,
+ struct iwl_tx_queue *txq);
void iwlagn_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags,
struct ieee80211_tx_info *info);
int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb);
@@ -205,6 +225,8 @@ static inline bool iwl_is_tx_success(u32 status)
(status == TX_STATUS_DIRECT_DONE);
}
+u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx, u8 valid);
+
/* rx */
void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb);
@@ -216,14 +238,84 @@ void iwl_reply_statistics(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb);
/* scan */
-void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif);
+int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif);
+void iwlagn_post_scan(struct iwl_priv *priv);
/* station mgmt */
int iwlagn_manage_ibss_station(struct iwl_priv *priv,
struct ieee80211_vif *vif, bool add);
/* hcmd */
-int iwlagn_send_rxon_assoc(struct iwl_priv *priv);
+int iwlagn_send_rxon_assoc(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx);
int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant);
+/* bt coex */
+void iwlagn_send_advance_bt_config(struct iwl_priv *priv);
+void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
+ struct iwl_rx_mem_buffer *rxb);
+void iwlagn_bt_rx_handler_setup(struct iwl_priv *priv);
+void iwlagn_bt_setup_deferred_work(struct iwl_priv *priv);
+void iwlagn_bt_cancel_deferred_work(struct iwl_priv *priv);
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+const char *iwl_get_tx_fail_reason(u32 status);
+const char *iwl_get_agg_tx_fail_reason(u16 status);
+#else
+static inline const char *iwl_get_tx_fail_reason(u32 status) { return ""; }
+static inline const char *iwl_get_agg_tx_fail_reason(u16 status) { return ""; }
+#endif
+
+/* station management */
+int iwlagn_alloc_bcast_station(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx);
+int iwlagn_add_bssid_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
+ const u8 *addr, u8 *sta_id_r);
+int iwl_remove_default_wep_key(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx,
+ struct ieee80211_key_conf *key);
+int iwl_set_default_wep_key(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx,
+ struct ieee80211_key_conf *key);
+int iwl_restore_default_wep_keys(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx);
+int iwl_set_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
+ struct ieee80211_key_conf *key, u8 sta_id);
+int iwl_remove_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
+ struct ieee80211_key_conf *key, u8 sta_id);
+void iwl_update_tkip_key(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx,
+ struct ieee80211_key_conf *keyconf,
+ struct ieee80211_sta *sta, u32 iv32, u16 *phase1key);
+int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid);
+int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
+ int tid, u16 ssn);
+int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
+ int tid);
+void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id);
+void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt);
+int iwl_update_bcast_stations(struct iwl_priv *priv);
+
+/* rate */
+static inline u32 iwl_ant_idx_to_flags(u8 ant_idx)
+{
+ return BIT(ant_idx) << RATE_MCS_ANT_POS;
+}
+
+static inline u8 iwl_hw_get_rate(__le32 rate_n_flags)
+{
+ return le32_to_cpu(rate_n_flags) & 0xFF;
+}
+
+static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags)
+{
+ return cpu_to_le32(flags|(u32)rate);
+}
+
+/* eeprom */
+void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv);
+void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac);
+int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv);
+void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv);
+
#endif /* __iwl_agn_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index 60725a5c1b69..424801abc80e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -62,7 +62,7 @@
*****************************************************************************/
/*
* Please use this file (iwl-commands.h) only for uCode API definitions.
- * Please use iwl-4965-hw.h for hardware-related definitions.
+ * Please use iwl-xxxx-hw.h for hardware-related definitions.
* Please use iwl-dev.h for driver implementation definitions.
*/
@@ -173,6 +173,23 @@ enum {
REPLY_RX_MPDU_CMD = 0xc1,
REPLY_RX = 0xc3,
REPLY_COMPRESSED_BA = 0xc5,
+
+ /* BT Coex */
+ REPLY_BT_COEX_PRIO_TABLE = 0xcc,
+ REPLY_BT_COEX_PROT_ENV = 0xcd,
+ REPLY_BT_COEX_PROFILE_NOTIF = 0xce,
+ REPLY_BT_COEX_SCO = 0xcf,
+
+ /* PAN commands */
+ REPLY_WIPAN_PARAMS = 0xb2,
+ REPLY_WIPAN_RXON = 0xb3, /* use REPLY_RXON structure */
+ REPLY_WIPAN_RXON_TIMING = 0xb4, /* use REPLY_RXON_TIMING structure */
+ REPLY_WIPAN_RXON_ASSOC = 0xb6, /* use REPLY_RXON_ASSOC structure */
+ REPLY_WIPAN_QOS_PARAM = 0xb7, /* use REPLY_QOS_PARAM structure */
+ REPLY_WIPAN_WEPKEY = 0xb8, /* use REPLY_WEPKEY structure */
+ REPLY_WIPAN_P2P_CHANNEL_SWITCH = 0xb9,
+ REPLY_WIPAN_NOA_NOTIFICATION = 0xbc,
+
REPLY_MAX = 0xff
};
@@ -403,12 +420,12 @@ struct iwl4965_tx_power_db {
/**
* Command REPLY_TX_POWER_DBM_CMD = 0x98
- * struct iwl5000_tx_power_dbm_cmd
+ * struct iwlagn_tx_power_dbm_cmd
*/
-#define IWL50_TX_POWER_AUTO 0x7f
-#define IWL50_TX_POWER_NO_CLOSED (0x1 << 6)
+#define IWLAGN_TX_POWER_AUTO 0x7f
+#define IWLAGN_TX_POWER_NO_CLOSED (0x1 << 6)
-struct iwl5000_tx_power_dbm_cmd {
+struct iwlagn_tx_power_dbm_cmd {
s8 global_lmt; /*in half-dBm (e.g. 30 = 15 dBm) */
u8 flags;
s8 srv_chan_lmt; /*in half-dBm (e.g. 30 = 15 dBm) */
@@ -600,6 +617,9 @@ enum {
RXON_DEV_TYPE_ESS = 3,
RXON_DEV_TYPE_IBSS = 4,
RXON_DEV_TYPE_SNIFFER = 6,
+ RXON_DEV_TYPE_CP = 7,
+ RXON_DEV_TYPE_2STA = 8,
+ RXON_DEV_TYPE_P2P = 9,
};
@@ -816,7 +836,8 @@ struct iwl_rxon_time_cmd {
__le16 atim_window;
__le32 beacon_init_val;
__le16 listen_interval;
- __le16 reserved;
+ u8 dtim_period;
+ u8 delta_cp_bss_tbtts;
} __packed;
/*
@@ -953,11 +974,13 @@ struct iwl_qosparam_cmd {
/* Special, dedicated locations within device's station table */
#define IWL_AP_ID 0
+#define IWL_AP_ID_PAN 1
#define IWL_STA_ID 2
#define IWL3945_BROADCAST_ID 24
#define IWL3945_STATION_COUNT 25
#define IWL4965_BROADCAST_ID 31
#define IWL4965_STATION_COUNT 32
+#define IWLAGN_PAN_BCAST_ID 14
#define IWLAGN_BROADCAST_ID 15
#define IWLAGN_STATION_COUNT 16
@@ -966,6 +989,7 @@ struct iwl_qosparam_cmd {
#define STA_FLG_TX_RATE_MSK cpu_to_le32(1 << 2)
#define STA_FLG_PWR_SAVE_MSK cpu_to_le32(1 << 8)
+#define STA_FLG_PAN_STATION cpu_to_le32(1 << 13)
#define STA_FLG_RTS_MIMO_PROT_MSK cpu_to_le32(1 << 17)
#define STA_FLG_AGG_MPDU_8US_MSK cpu_to_le32(1 << 18)
#define STA_FLG_MAX_AGG_SIZE_POS (19)
@@ -994,6 +1018,7 @@ struct iwl_qosparam_cmd {
#define STA_KEY_FLG_KEY_SIZE_MSK cpu_to_le16(0x1000)
#define STA_KEY_MULTICAST_MSK cpu_to_le16(0x4000)
#define STA_KEY_MAX_NUM 8
+#define STA_KEY_MAX_NUM_PAN 16
/* Flags indicate whether to modify vs. don't change various station params */
#define STA_MODIFY_KEY_MASK 0x01
@@ -1017,7 +1042,7 @@ struct iwl4965_keyinfo {
u8 key[16]; /* 16-byte unicast decryption key */
} __packed;
-/* 5000 */
+/* agn */
struct iwl_keyinfo {
__le16 key_flags;
u8 tkip_rx_tsc_byte2; /* TSC[2] for key mix ph1 detection */
@@ -1056,7 +1081,8 @@ struct sta_id_modify {
*
* The device contains an internal table of per-station information,
* with info on security keys, aggregation parameters, and Tx rates for
- * initial Tx attempt and any retries (4965 uses REPLY_TX_LINK_QUALITY_CMD,
+ * initial Tx attempt and any retries (agn devices uses
+ * REPLY_TX_LINK_QUALITY_CMD,
* 3945 uses REPLY_RATE_SCALE to set up rate tables).
*
* REPLY_ADD_STA sets up the table entry for one station, either creating
@@ -1142,7 +1168,7 @@ struct iwl4965_addsta_cmd {
__le16 reserved2;
} __packed;
-/* 5000 */
+/* agn */
struct iwl_addsta_cmd {
u8 mode; /* 1: modify existing, 0: add new station */
u8 reserved[3];
@@ -1367,21 +1393,24 @@ struct iwl4965_rx_non_cfg_phy {
} __packed;
-#define IWL50_RX_RES_PHY_CNT 8
-#define IWL50_RX_RES_AGC_IDX 1
-#define IWL50_RX_RES_RSSI_AB_IDX 2
-#define IWL50_RX_RES_RSSI_C_IDX 3
-#define IWL50_OFDM_AGC_MSK 0xfe00
-#define IWL50_OFDM_AGC_BIT_POS 9
-#define IWL50_OFDM_RSSI_A_MSK 0x00ff
-#define IWL50_OFDM_RSSI_A_BIT_POS 0
-#define IWL50_OFDM_RSSI_B_MSK 0xff0000
-#define IWL50_OFDM_RSSI_B_BIT_POS 16
-#define IWL50_OFDM_RSSI_C_MSK 0x00ff
-#define IWL50_OFDM_RSSI_C_BIT_POS 0
+#define IWLAGN_RX_RES_PHY_CNT 8
+#define IWLAGN_RX_RES_AGC_IDX 1
+#define IWLAGN_RX_RES_RSSI_AB_IDX 2
+#define IWLAGN_RX_RES_RSSI_C_IDX 3
+#define IWLAGN_OFDM_AGC_MSK 0xfe00
+#define IWLAGN_OFDM_AGC_BIT_POS 9
+#define IWLAGN_OFDM_RSSI_INBAND_A_BITMSK 0x00ff
+#define IWLAGN_OFDM_RSSI_ALLBAND_A_BITMSK 0xff00
+#define IWLAGN_OFDM_RSSI_A_BIT_POS 0
+#define IWLAGN_OFDM_RSSI_INBAND_B_BITMSK 0xff0000
+#define IWLAGN_OFDM_RSSI_ALLBAND_B_BITMSK 0xff000000
+#define IWLAGN_OFDM_RSSI_B_BIT_POS 16
+#define IWLAGN_OFDM_RSSI_INBAND_C_BITMSK 0x00ff
+#define IWLAGN_OFDM_RSSI_ALLBAND_C_BITMSK 0xff00
+#define IWLAGN_OFDM_RSSI_C_BIT_POS 0
-struct iwl5000_non_cfg_phy {
- __le32 non_cfg_phy[IWL50_RX_RES_PHY_CNT]; /* up to 8 phy entries */
+struct iwlagn_non_cfg_phy {
+ __le32 non_cfg_phy[IWLAGN_RX_RES_PHY_CNT]; /* up to 8 phy entries */
} __packed;
@@ -1401,7 +1430,7 @@ struct iwl_rx_phy_res {
u8 non_cfg_phy_buf[32]; /* for various implementations of non_cfg_phy */
__le32 rate_n_flags; /* RATE_MCS_* */
__le16 byte_count; /* frame's byte-count */
- __le16 reserved3;
+ __le16 frame_time; /* frame's time on the air */
} __packed;
struct iwl_rx_mpdu_res_start {
@@ -1424,12 +1453,12 @@ struct iwl_rx_mpdu_res_start {
* uCode handles all timing and protocol related to control frames
* (RTS/CTS/ACK), based on flags in the Tx command. uCode and Tx scheduler
* handle reception of block-acks; uCode updates the host driver via
- * REPLY_COMPRESSED_BA (4965).
+ * REPLY_COMPRESSED_BA.
*
* uCode handles retrying Tx when an ACK is expected but not received.
* This includes trying lower data rates than the one requested in the Tx
* command, as set up by the REPLY_RATE_SCALE (for 3945) or
- * REPLY_TX_LINK_QUALITY_CMD (4965).
+ * REPLY_TX_LINK_QUALITY_CMD (agn).
*
* Driver sets up transmit power for various rates via REPLY_TX_PWR_TABLE_CMD.
* This command must be executed after every RXON command, before Tx can occur.
@@ -1465,7 +1494,7 @@ struct iwl_rx_mpdu_res_start {
* Set this for unicast frames, but not broadcast/multicast. */
#define TX_CMD_FLG_ACK_MSK cpu_to_le32(1 << 3)
-/* For 4965:
+/* For agn devices:
* 1: Use rate scale table (see REPLY_TX_LINK_QUALITY_CMD).
* Tx command's initial_rate_index indicates first rate to try;
* uCode walks through table for additional Tx attempts.
@@ -1484,7 +1513,7 @@ struct iwl_rx_mpdu_res_start {
*/
#define TX_CMD_FLG_FULL_TXOP_PROT_MSK cpu_to_le32(1 << 7)
-/* Tx antenna selection field; used only for 3945, reserved (0) for 4965.
+/* Tx antenna selection field; used only for 3945, reserved (0) for agn devices.
* Set field to "0" to allow 3945 uCode to select antenna (normal usage). */
#define TX_CMD_FLG_ANT_SEL_MSK cpu_to_le32(0xf00)
#define TX_CMD_FLG_ANT_A_MSK cpu_to_le32(1 << 8)
@@ -1791,13 +1820,8 @@ enum {
TX_STATUS_FAIL_TID_DISABLE = 0x8d,
TX_STATUS_FAIL_FIFO_FLUSHED = 0x8e,
TX_STATUS_FAIL_INSUFFICIENT_CF_POLL = 0x8f,
- /* uCode drop due to FW drop request */
- TX_STATUS_FAIL_FW_DROP = 0x90,
- /*
- * uCode drop due to station color mismatch
- * between tx command and station table
- */
- TX_STATUS_FAIL_STA_COLOR_MISMATCH_DROP = 0x91,
+ TX_STATUS_FAIL_PASSIVE_NO_RX = 0x90,
+ TX_STATUS_FAIL_NO_BEACON_ON_RADAR = 0x91,
};
#define TX_PACKET_MODE_REGULAR 0x0000
@@ -1839,6 +1863,9 @@ enum {
AGG_TX_STATE_DELAY_TX_MSK = 0x400
};
+#define AGG_TX_STATUS_MSK 0x00000fff /* bits 0:11 */
+#define AGG_TX_TRY_MSK 0x0000f000 /* bits 12:15 */
+
#define AGG_TX_STATE_LAST_SENT_MSK (AGG_TX_STATE_LAST_SENT_TTL_MSK | \
AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK | \
AGG_TX_STATE_LAST_SENT_BT_KILL_MSK)
@@ -1867,9 +1894,10 @@ enum {
* frame in this new agg block failed in previous agg block(s).
*
* Note that, for aggregation, ACK (block-ack) status is not delivered here;
- * block-ack has not been received by the time the 4965 records this status.
+ * block-ack has not been received by the time the agn device records
+ * this status.
* This status relates to reasons the tx might have been blocked or aborted
- * within the sending station (this 4965), rather than whether it was
+ * within the sending station (this agn device), rather than whether it was
* received successfully by the destination station.
*/
struct agg_tx_status {
@@ -1931,12 +1959,12 @@ struct iwl4965_tx_resp {
#define IWL50_TX_RES_INV_RATE_INDEX_MSK 0x80
/* refer to ra_tid */
-#define IWL50_TX_RES_TID_POS 0
-#define IWL50_TX_RES_TID_MSK 0x0f
-#define IWL50_TX_RES_RA_POS 4
-#define IWL50_TX_RES_RA_MSK 0xf0
+#define IWLAGN_TX_RES_TID_POS 0
+#define IWLAGN_TX_RES_TID_MSK 0x0f
+#define IWLAGN_TX_RES_RA_POS 4
+#define IWLAGN_TX_RES_RA_MSK 0xf0
-struct iwl5000_tx_resp {
+struct iwlagn_tx_resp {
u8 frame_count; /* 1 no aggregation, >1 aggregation */
u8 bt_kill_count; /* # blocked by bluetooth (unused for agg) */
u8 failure_rts; /* # failures due to unsuccessful RTS */
@@ -2092,8 +2120,8 @@ struct iwl_link_qual_general_params {
} __packed;
#define LINK_QUAL_AGG_TIME_LIMIT_DEF (4000) /* 4 milliseconds */
-#define LINK_QUAL_AGG_TIME_LIMIT_MAX (65535)
-#define LINK_QUAL_AGG_TIME_LIMIT_MIN (0)
+#define LINK_QUAL_AGG_TIME_LIMIT_MAX (8000)
+#define LINK_QUAL_AGG_TIME_LIMIT_MIN (100)
#define LINK_QUAL_AGG_DISABLE_START_DEF (3)
#define LINK_QUAL_AGG_DISABLE_START_MAX (255)
@@ -2110,8 +2138,10 @@ struct iwl_link_qual_general_params {
*/
struct iwl_link_qual_agg_params {
- /* Maximum number of uSec in aggregation.
- * Driver should set this to 4000 (4 milliseconds). */
+ /*
+ *Maximum number of uSec in aggregation.
+ * default set to 4000 (4 milliseconds) if not configured in .cfg
+ */
__le16 agg_time_limit;
/*
@@ -2135,14 +2165,16 @@ struct iwl_link_qual_agg_params {
/*
* REPLY_TX_LINK_QUALITY_CMD = 0x4e (command, has simple generic response)
*
- * For 4965 only; 3945 uses REPLY_RATE_SCALE.
+ * For agn devices only; 3945 uses REPLY_RATE_SCALE.
*
- * Each station in the 4965's internal station table has its own table of 16
+ * Each station in the agn device's internal station table has its own table
+ * of 16
* Tx rates and modulation modes (e.g. legacy/SISO/MIMO) for retrying Tx when
* an ACK is not received. This command replaces the entire table for
* one station.
*
- * NOTE: Station must already be in 4965's station table. Use REPLY_ADD_STA.
+ * NOTE: Station must already be in agn device's station table.
+ * Use REPLY_ADD_STA.
*
* The rate scaling procedures described below work well. Of course, other
* procedures are possible, and may work better for particular environments.
@@ -2179,12 +2211,12 @@ struct iwl_link_qual_agg_params {
*
* ACCUMULATING HISTORY
*
- * The rate scaling algorithm for 4965, as implemented in Linux driver, uses
- * two sets of frame Tx success history: One for the current/active modulation
- * mode, and one for a speculative/search mode that is being attempted. If the
- * speculative mode turns out to be more effective (i.e. actual transfer
- * rate is better), then the driver continues to use the speculative mode
- * as the new current active mode.
+ * The rate scaling algorithm for agn devices, as implemented in Linux driver,
+ * uses two sets of frame Tx success history: One for the current/active
+ * modulation mode, and one for a speculative/search mode that is being
+ * attempted. If the speculative mode turns out to be more effective (i.e.
+ * actual transfer rate is better), then the driver continues to use the
+ * speculative mode as the new current active mode.
*
* Each history set contains, separately for each possible rate, data for a
* sliding window of the 62 most recent tx attempts at that rate. The data
@@ -2195,12 +2227,12 @@ struct iwl_link_qual_agg_params {
* The driver uses the bit map to remove successes from the success sum, as
* the oldest tx attempts fall out of the window.
*
- * When the 4965 makes multiple tx attempts for a given frame, each attempt
- * might be at a different rate, and have different modulation characteristics
- * (e.g. antenna, fat channel, short guard interval), as set up in the rate
- * scaling table in the Link Quality command. The driver must determine
- * which rate table entry was used for each tx attempt, to determine which
- * rate-specific history to update, and record only those attempts that
+ * When the agn device makes multiple tx attempts for a given frame, each
+ * attempt might be at a different rate, and have different modulation
+ * characteristics (e.g. antenna, fat channel, short guard interval), as set
+ * up in the rate scaling table in the Link Quality command. The driver must
+ * determine which rate table entry was used for each tx attempt, to determine
+ * which rate-specific history to update, and record only those attempts that
* match the modulation characteristics of the history set.
*
* When using block-ack (aggregation), all frames are transmitted at the same
@@ -2330,7 +2362,7 @@ struct iwl_link_quality_cmd {
/*
* Rate info; when using rate-scaling, Tx command's initial_rate_index
* specifies 1st Tx rate attempted, via index into this table.
- * 4965 works its way through table when retrying Tx.
+ * agn devices works its way through table when retrying Tx.
*/
struct {
__le32 rate_n_flags; /* RATE_MCS_*, IWL_RATE_* */
@@ -2363,10 +2395,26 @@ struct iwl_link_quality_cmd {
#define BT_MAX_KILL_DEF (0x5)
#define BT_MAX_KILL_MAX (0xFF)
+#define BT_DURATION_LIMIT_DEF 625
+#define BT_DURATION_LIMIT_MAX 1250
+#define BT_DURATION_LIMIT_MIN 625
+
+#define BT_ON_THRESHOLD_DEF 4
+#define BT_ON_THRESHOLD_MAX 1000
+#define BT_ON_THRESHOLD_MIN 1
+
+#define BT_FRAG_THRESHOLD_DEF 0
+#define BT_FRAG_THRESHOLD_MAX 0
+#define BT_FRAG_THRESHOLD_MIN 0
+
+#define BT_AGG_THRESHOLD_DEF 0
+#define BT_AGG_THRESHOLD_MAX 0
+#define BT_AGG_THRESHOLD_MIN 0
+
/*
* REPLY_BT_CONFIG = 0x9b (command, has simple generic response)
*
- * 3945 and 4965 support hardware handshake with Bluetooth device on
+ * 3945 and agn devices support hardware handshake with Bluetooth device on
* same platform. Bluetooth device alerts wireless device when it will Tx;
* wireless device can delay or kill its own Tx to accommodate.
*/
@@ -2379,6 +2427,79 @@ struct iwl_bt_cmd {
__le32 kill_cts_mask;
} __packed;
+#define IWLAGN_BT_FLAG_CHANNEL_INHIBITION BIT(0)
+
+#define IWLAGN_BT_FLAG_COEX_MODE_MASK (BIT(3)|BIT(4)|BIT(5))
+#define IWLAGN_BT_FLAG_COEX_MODE_SHIFT 3
+#define IWLAGN_BT_FLAG_COEX_MODE_DISABLED 0
+#define IWLAGN_BT_FLAG_COEX_MODE_LEGACY_2W 1
+#define IWLAGN_BT_FLAG_COEX_MODE_3W 2
+#define IWLAGN_BT_FLAG_COEX_MODE_4W 3
+
+#define IWLAGN_BT_FLAG_UCODE_DEFAULT BIT(6)
+#define IWLAGN_BT_FLAG_NOCOEX_NOTIF BIT(7)
+
+#define IWLAGN_BT_PRIO_BOOST_MAX 0xFF
+#define IWLAGN_BT_PRIO_BOOST_MIN 0x00
+#define IWLAGN_BT_PRIO_BOOST_DEFAULT 0xF0
+
+#define IWLAGN_BT_MAX_KILL_DEFAULT 5
+
+#define IWLAGN_BT3_T7_DEFAULT 1
+
+#define IWLAGN_BT_KILL_ACK_MASK_DEFAULT cpu_to_le32(0xffffffff)
+#define IWLAGN_BT_KILL_CTS_MASK_DEFAULT cpu_to_le32(0xffffffff)
+
+#define IWLAGN_BT3_PRIO_SAMPLE_DEFAULT 2
+
+#define IWLAGN_BT3_T2_DEFAULT 0xc
+
+#define IWLAGN_BT_VALID_ENABLE_FLAGS cpu_to_le16(BIT(0))
+#define IWLAGN_BT_VALID_BOOST cpu_to_le16(BIT(1))
+#define IWLAGN_BT_VALID_MAX_KILL cpu_to_le16(BIT(2))
+#define IWLAGN_BT_VALID_3W_TIMERS cpu_to_le16(BIT(3))
+#define IWLAGN_BT_VALID_KILL_ACK_MASK cpu_to_le16(BIT(4))
+#define IWLAGN_BT_VALID_KILL_CTS_MASK cpu_to_le16(BIT(5))
+#define IWLAGN_BT_VALID_BT4_TIMES cpu_to_le16(BIT(6))
+#define IWLAGN_BT_VALID_3W_LUT cpu_to_le16(BIT(7))
+
+#define IWLAGN_BT_ALL_VALID_MSK (IWLAGN_BT_VALID_ENABLE_FLAGS | \
+ IWLAGN_BT_VALID_BOOST | \
+ IWLAGN_BT_VALID_MAX_KILL | \
+ IWLAGN_BT_VALID_3W_TIMERS | \
+ IWLAGN_BT_VALID_KILL_ACK_MASK | \
+ IWLAGN_BT_VALID_KILL_CTS_MASK | \
+ IWLAGN_BT_VALID_BT4_TIMES | \
+ IWLAGN_BT_VALID_3W_LUT)
+
+struct iwlagn_bt_cmd {
+ u8 flags;
+ u8 ledtime; /* unused */
+ u8 max_kill;
+ u8 bt3_timer_t7_value;
+ __le32 kill_ack_mask;
+ __le32 kill_cts_mask;
+ u8 bt3_prio_sample_time;
+ u8 bt3_timer_t2_value;
+ __le16 bt4_reaction_time; /* unused */
+ __le32 bt3_lookup_table[12];
+ __le16 bt4_decision_time; /* unused */
+ __le16 valid;
+ u8 prio_boost;
+ /*
+ * set IWLAGN_BT_VALID_BOOST to "1" in "valid" bitmask
+ * if configure the following patterns
+ */
+ u8 tx_prio_boost; /* SW boost of WiFi tx priority */
+ __le16 rx_prio_boost; /* SW boost of WiFi rx priority */
+};
+
+#define IWLAGN_BT_SCO_ACTIVE cpu_to_le32(BIT(0))
+
+struct iwlagn_bt_sco_cmd {
+ __le32 flags;
+};
+
/******************************************************************************
* (6)
* Spectrum Management (802.11h) Commands, Responses, Notifications:
@@ -2567,7 +2688,7 @@ struct iwl_powertable_cmd {
/*
* PM_SLEEP_NOTIFICATION = 0x7A (notification only, not a command)
- * 3945 and 4965 identical.
+ * all devices identical.
*/
struct iwl_sleep_notification {
u8 pm_sleep_mode;
@@ -2578,7 +2699,7 @@ struct iwl_sleep_notification {
__le32 bcon_timer;
} __packed;
-/* Sleep states. 3945 and 4965 identical. */
+/* Sleep states. all devices identical. */
enum {
IWL_PM_NO_SLEEP = 0,
IWL_PM_SLP_MAC = 1,
@@ -2887,6 +3008,12 @@ struct iwl_scanstart_notification {
#define SCAN_OWNER_STATUS 0x1;
#define MEASURE_OWNER_STATUS 0x2;
+#define IWL_PROBE_STATUS_OK 0
+#define IWL_PROBE_STATUS_TX_FAILED BIT(0)
+/* error statuses combined with TX_FAILED */
+#define IWL_PROBE_STATUS_FAIL_TTL BIT(1)
+#define IWL_PROBE_STATUS_FAIL_BT BIT(2)
+
#define NUMBER_OF_STATISTICS 1 /* first __le32 is good CRC */
/*
* SCAN_RESULTS_NOTIFICATION = 0x83 (notification only, not a command)
@@ -2894,7 +3021,8 @@ struct iwl_scanstart_notification {
struct iwl_scanresults_notification {
u8 channel;
u8 band;
- u8 reserved[2];
+ u8 probe_status;
+ u8 num_probe_not_sent; /* not enough time to send */
__le32 tsf_low;
__le32 tsf_high;
__le32 statistics[NUMBER_OF_STATISTICS];
@@ -2906,7 +3034,7 @@ struct iwl_scanresults_notification {
struct iwl_scancomplete_notification {
u8 scanned_channels;
u8 status;
- u8 reserved;
+ u8 bt_status; /* BT On/Off status */
u8 last_channel;
__le32 tsf_low;
__le32 tsf_high;
@@ -2919,6 +3047,11 @@ struct iwl_scancomplete_notification {
*
*****************************************************************************/
+enum iwl_ibss_manager {
+ IWL_NOT_IBSS_MANAGER = 0,
+ IWL_IBSS_MANAGER = 1,
+};
+
/*
* BEACON_NOTIFICATION = 0x90 (notification only, not a command)
*/
@@ -3260,7 +3393,7 @@ struct statistics_general_bt {
/*
* REPLY_STATISTICS_CMD = 0x9c,
- * 3945 and 4965 identical.
+ * all devices identical.
*
* This command triggers an immediate response containing uCode statistics.
* The response is in the same format as STATISTICS_NOTIFICATION 0x9d, below.
@@ -3598,7 +3731,7 @@ struct iwl_enhance_sensitivity_cmd {
/**
* REPLY_PHY_CALIBRATION_CMD = 0xb0 (command, has simple generic response)
*
- * This command sets the relative gains of 4965's 3 radio receiver chains.
+ * This command sets the relative gains of agn device's 3 radio receiver chains.
*
* After the first association, driver should accumulate signal and noise
* statistics from the STATISTICS_NOTIFICATIONs that follow the first 20
@@ -3651,7 +3784,8 @@ struct iwl_enhance_sensitivity_cmd {
*/
/* Phy calibration command for series */
-
+/* The default calibrate table size if not specified by firmware */
+#define IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE 18
enum {
IWL_PHY_CALIBRATE_DIFF_GAIN_CMD = 7,
IWL_PHY_CALIBRATE_DC_CMD = 8,
@@ -3660,13 +3794,29 @@ enum {
IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD = 15,
IWL_PHY_CALIBRATE_BASE_BAND_CMD = 16,
IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD = 17,
- IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE = 18,
+ IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD = 18,
+ IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE = 19,
};
#define IWL_MAX_PHY_CALIBRATE_TBL_SIZE (253)
#define IWL_CALIB_INIT_CFG_ALL cpu_to_le32(0xffffffff)
+/* This enum defines the bitmap of various calibrations to enable in both
+ * init ucode and runtime ucode through CALIBRATION_CFG_CMD.
+ */
+enum iwl_ucode_calib_cfg {
+ IWL_CALIB_CFG_RX_BB_IDX,
+ IWL_CALIB_CFG_DC_IDX,
+ IWL_CALIB_CFG_TX_IQ_IDX,
+ IWL_CALIB_CFG_RX_IQ_IDX,
+ IWL_CALIB_CFG_NOISE_IDX,
+ IWL_CALIB_CFG_CRYSTAL_IDX,
+ IWL_CALIB_CFG_TEMPERATURE_IDX,
+ IWL_CALIB_CFG_PAPD_IDX,
+};
+
+
struct iwl_calib_cfg_elmnt_s {
__le32 is_enable;
__le32 start;
@@ -3715,6 +3865,13 @@ struct iwl_calib_xtal_freq_cmd {
u8 pad[2];
} __packed;
+#define DEFAULT_RADIO_SENSOR_OFFSET 2700
+struct iwl_calib_temperature_offset_cmd {
+ struct iwl_calib_hdr hdr;
+ s16 radio_sensor_offset;
+ s16 reserved;
+} __packed;
+
/* IWL_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD */
struct iwl_calib_chain_noise_reset_cmd {
struct iwl_calib_hdr hdr;
@@ -3955,6 +4112,201 @@ struct iwl_coex_event_resp {
/******************************************************************************
+ * Bluetooth Coexistence commands
+ *
+ *****************************************************************************/
+
+/*
+ * BT Status notification
+ * REPLY_BT_COEX_PROFILE_NOTIF = 0xce
+ */
+enum iwl_bt_coex_profile_traffic_load {
+ IWL_BT_COEX_TRAFFIC_LOAD_NONE = 0,
+ IWL_BT_COEX_TRAFFIC_LOAD_LOW = 1,
+ IWL_BT_COEX_TRAFFIC_LOAD_HIGH = 2,
+ IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS = 3,
+/*
+ * There are no more even though below is a u8, the
+ * indication from the BT device only has two bits.
+ */
+};
+
+#define BT_UART_MSG_FRAME1MSGTYPE_POS (0)
+#define BT_UART_MSG_FRAME1MSGTYPE_MSK \
+ (0x7 << BT_UART_MSG_FRAME1MSGTYPE_POS)
+#define BT_UART_MSG_FRAME1SSN_POS (3)
+#define BT_UART_MSG_FRAME1SSN_MSK \
+ (0x3 << BT_UART_MSG_FRAME1SSN_POS)
+#define BT_UART_MSG_FRAME1UPDATEREQ_POS (5)
+#define BT_UART_MSG_FRAME1UPDATEREQ_MSK \
+ (0x1 << BT_UART_MSG_FRAME1UPDATEREQ_POS)
+#define BT_UART_MSG_FRAME1RESERVED_POS (6)
+#define BT_UART_MSG_FRAME1RESERVED_MSK \
+ (0x3 << BT_UART_MSG_FRAME1RESERVED_POS)
+
+#define BT_UART_MSG_FRAME2OPENCONNECTIONS_POS (0)
+#define BT_UART_MSG_FRAME2OPENCONNECTIONS_MSK \
+ (0x3 << BT_UART_MSG_FRAME2OPENCONNECTIONS_POS)
+#define BT_UART_MSG_FRAME2TRAFFICLOAD_POS (2)
+#define BT_UART_MSG_FRAME2TRAFFICLOAD_MSK \
+ (0x3 << BT_UART_MSG_FRAME2TRAFFICLOAD_POS)
+#define BT_UART_MSG_FRAME2CHLSEQN_POS (4)
+#define BT_UART_MSG_FRAME2CHLSEQN_MSK \
+ (0x1 << BT_UART_MSG_FRAME2CHLSEQN_POS)
+#define BT_UART_MSG_FRAME2INBAND_POS (5)
+#define BT_UART_MSG_FRAME2INBAND_MSK \
+ (0x1 << BT_UART_MSG_FRAME2INBAND_POS)
+#define BT_UART_MSG_FRAME2RESERVED_POS (6)
+#define BT_UART_MSG_FRAME2RESERVED_MSK \
+ (0x3 << BT_UART_MSG_FRAME2RESERVED_POS)
+
+#define BT_UART_MSG_FRAME3SCOESCO_POS (0)
+#define BT_UART_MSG_FRAME3SCOESCO_MSK \
+ (0x1 << BT_UART_MSG_FRAME3SCOESCO_POS)
+#define BT_UART_MSG_FRAME3SNIFF_POS (1)
+#define BT_UART_MSG_FRAME3SNIFF_MSK \
+ (0x1 << BT_UART_MSG_FRAME3SNIFF_POS)
+#define BT_UART_MSG_FRAME3A2DP_POS (2)
+#define BT_UART_MSG_FRAME3A2DP_MSK \
+ (0x1 << BT_UART_MSG_FRAME3A2DP_POS)
+#define BT_UART_MSG_FRAME3ACL_POS (3)
+#define BT_UART_MSG_FRAME3ACL_MSK \
+ (0x1 << BT_UART_MSG_FRAME3ACL_POS)
+#define BT_UART_MSG_FRAME3MASTER_POS (4)
+#define BT_UART_MSG_FRAME3MASTER_MSK \
+ (0x1 << BT_UART_MSG_FRAME3MASTER_POS)
+#define BT_UART_MSG_FRAME3OBEX_POS (5)
+#define BT_UART_MSG_FRAME3OBEX_MSK \
+ (0x1 << BT_UART_MSG_FRAME3OBEX_POS)
+#define BT_UART_MSG_FRAME3RESERVED_POS (6)
+#define BT_UART_MSG_FRAME3RESERVED_MSK \
+ (0x3 << BT_UART_MSG_FRAME3RESERVED_POS)
+
+#define BT_UART_MSG_FRAME4IDLEDURATION_POS (0)
+#define BT_UART_MSG_FRAME4IDLEDURATION_MSK \
+ (0x3F << BT_UART_MSG_FRAME4IDLEDURATION_POS)
+#define BT_UART_MSG_FRAME4RESERVED_POS (6)
+#define BT_UART_MSG_FRAME4RESERVED_MSK \
+ (0x3 << BT_UART_MSG_FRAME4RESERVED_POS)
+
+#define BT_UART_MSG_FRAME5TXACTIVITY_POS (0)
+#define BT_UART_MSG_FRAME5TXACTIVITY_MSK \
+ (0x3 << BT_UART_MSG_FRAME5TXACTIVITY_POS)
+#define BT_UART_MSG_FRAME5RXACTIVITY_POS (2)
+#define BT_UART_MSG_FRAME5RXACTIVITY_MSK \
+ (0x3 << BT_UART_MSG_FRAME5RXACTIVITY_POS)
+#define BT_UART_MSG_FRAME5ESCORETRANSMIT_POS (4)
+#define BT_UART_MSG_FRAME5ESCORETRANSMIT_MSK \
+ (0x3 << BT_UART_MSG_FRAME5ESCORETRANSMIT_POS)
+#define BT_UART_MSG_FRAME5RESERVED_POS (6)
+#define BT_UART_MSG_FRAME5RESERVED_MSK \
+ (0x3 << BT_UART_MSG_FRAME5RESERVED_POS)
+
+#define BT_UART_MSG_FRAME6SNIFFINTERVAL_POS (0)
+#define BT_UART_MSG_FRAME6SNIFFINTERVAL_MSK \
+ (0x1F << BT_UART_MSG_FRAME6SNIFFINTERVAL_POS)
+#define BT_UART_MSG_FRAME6DISCOVERABLE_POS (5)
+#define BT_UART_MSG_FRAME6DISCOVERABLE_MSK \
+ (0x1 << BT_UART_MSG_FRAME6DISCOVERABLE_POS)
+#define BT_UART_MSG_FRAME6RESERVED_POS (6)
+#define BT_UART_MSG_FRAME6RESERVED_MSK \
+ (0x3 << BT_UART_MSG_FRAME6RESERVED_POS)
+
+#define BT_UART_MSG_FRAME7SNIFFACTIVITY_POS (0)
+#define BT_UART_MSG_FRAME7SNIFFACTIVITY_MSK \
+ (0x7 << BT_UART_MSG_FRAME7SNIFFACTIVITY_POS)
+#define BT_UART_MSG_FRAME7INQUIRYPAGESRMODE_POS (3)
+#define BT_UART_MSG_FRAME7INQUIRYPAGESRMODE_MSK \
+ (0x3 << BT_UART_MSG_FRAME7INQUIRYPAGESRMODE_POS)
+#define BT_UART_MSG_FRAME7CONNECTABLE_POS (5)
+#define BT_UART_MSG_FRAME7CONNECTABLE_MSK \
+ (0x1 << BT_UART_MSG_FRAME7CONNECTABLE_POS)
+#define BT_UART_MSG_FRAME7RESERVED_POS (6)
+#define BT_UART_MSG_FRAME7RESERVED_MSK \
+ (0x3 << BT_UART_MSG_FRAME7RESERVED_POS)
+
+
+struct iwl_bt_uart_msg {
+ u8 header;
+ u8 frame1;
+ u8 frame2;
+ u8 frame3;
+ u8 frame4;
+ u8 frame5;
+ u8 frame6;
+ u8 frame7;
+} __attribute__((packed));
+
+struct iwl_bt_coex_profile_notif {
+ struct iwl_bt_uart_msg last_bt_uart_msg;
+ u8 bt_status; /* 0 - off, 1 - on */
+ u8 bt_traffic_load; /* 0 .. 3? */
+ u8 bt_ci_compliance; /* 0 - not complied, 1 - complied */
+ u8 reserved;
+} __attribute__((packed));
+
+#define IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS 0
+#define IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_MSK 0x1
+#define IWL_BT_COEX_PRIO_TBL_PRIO_POS 1
+#define IWL_BT_COEX_PRIO_TBL_PRIO_MASK 0x0e
+#define IWL_BT_COEX_PRIO_TBL_RESERVED_POS 4
+#define IWL_BT_COEX_PRIO_TBL_RESERVED_MASK 0xf0
+#define IWL_BT_COEX_PRIO_TBL_PRIO_SHIFT 1
+
+/*
+ * BT Coexistence Priority table
+ * REPLY_BT_COEX_PRIO_TABLE = 0xcc
+ */
+enum bt_coex_prio_table_events {
+ BT_COEX_PRIO_TBL_EVT_INIT_CALIB1 = 0,
+ BT_COEX_PRIO_TBL_EVT_INIT_CALIB2 = 1,
+ BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_LOW1 = 2,
+ BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_LOW2 = 3, /* DC calib */
+ BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_HIGH1 = 4,
+ BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_HIGH2 = 5,
+ BT_COEX_PRIO_TBL_EVT_DTIM = 6,
+ BT_COEX_PRIO_TBL_EVT_SCAN52 = 7,
+ BT_COEX_PRIO_TBL_EVT_SCAN24 = 8,
+ BT_COEX_PRIO_TBL_EVT_RESERVED0 = 9,
+ BT_COEX_PRIO_TBL_EVT_RESERVED1 = 10,
+ BT_COEX_PRIO_TBL_EVT_RESERVED2 = 11,
+ BT_COEX_PRIO_TBL_EVT_RESERVED3 = 12,
+ BT_COEX_PRIO_TBL_EVT_RESERVED4 = 13,
+ BT_COEX_PRIO_TBL_EVT_RESERVED5 = 14,
+ BT_COEX_PRIO_TBL_EVT_RESERVED6 = 15,
+ /* BT_COEX_PRIO_TBL_EVT_MAX should always be last */
+ BT_COEX_PRIO_TBL_EVT_MAX,
+};
+
+enum bt_coex_prio_table_priorities {
+ BT_COEX_PRIO_TBL_DISABLED = 0,
+ BT_COEX_PRIO_TBL_PRIO_LOW = 1,
+ BT_COEX_PRIO_TBL_PRIO_HIGH = 2,
+ BT_COEX_PRIO_TBL_PRIO_BYPASS = 3,
+ BT_COEX_PRIO_TBL_PRIO_COEX_OFF = 4,
+ BT_COEX_PRIO_TBL_PRIO_COEX_ON = 5,
+ BT_COEX_PRIO_TBL_PRIO_RSRVD1 = 6,
+ BT_COEX_PRIO_TBL_PRIO_RSRVD2 = 7,
+ BT_COEX_PRIO_TBL_MAX,
+};
+
+struct iwl_bt_coex_prio_table_cmd {
+ u8 prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX];
+} __attribute__((packed));
+
+#define IWL_BT_COEX_ENV_CLOSE 0
+#define IWL_BT_COEX_ENV_OPEN 1
+/*
+ * BT Protection Envelope
+ * REPLY_BT_COEX_PROT_ENV = 0xcd
+ */
+struct iwl_bt_coex_prot_env_cmd {
+ u8 action; /* 0 = closed, 1 = open */
+ u8 type; /* 0 .. 15 */
+ u8 reserved[2];
+} __attribute__((packed));
+
+/******************************************************************************
* (13)
* Union of all expected notifications/responses:
*
@@ -3993,6 +4345,7 @@ struct iwl_rx_packet {
struct iwl_missed_beacon_notif missed_beacon;
struct iwl_coex_medium_notification coex_medium_notif;
struct iwl_coex_event_resp coex_event;
+ struct iwl_bt_coex_profile_notif bt_coex_profile_notif;
__le32 status;
u8 raw[0];
} u;
@@ -4000,4 +4353,94 @@ struct iwl_rx_packet {
int iwl_agn_check_rxon_cmd(struct iwl_priv *priv);
+/*
+ * REPLY_WIPAN_PARAMS = 0xb2 (Commands and Notification)
+ */
+
+/**
+ * struct iwl_wipan_slot
+ * @width: Time in TU
+ * @type:
+ * 0 - BSS
+ * 1 - PAN
+ */
+struct iwl_wipan_slot {
+ __le16 width;
+ u8 type;
+ u8 reserved;
+} __packed;
+
+#define IWL_WIPAN_PARAMS_FLG_LEAVE_CHANNEL_CTS BIT(1) /* reserved */
+#define IWL_WIPAN_PARAMS_FLG_LEAVE_CHANNEL_QUIET BIT(2) /* reserved */
+#define IWL_WIPAN_PARAMS_FLG_SLOTTED_MODE BIT(3) /* reserved */
+#define IWL_WIPAN_PARAMS_FLG_FILTER_BEACON_NOTIF BIT(4)
+#define IWL_WIPAN_PARAMS_FLG_FULL_SLOTTED_MODE BIT(5)
+
+/**
+ * struct iwl_wipan_params_cmd
+ * @flags:
+ * bit0: reserved
+ * bit1: CP leave channel with CTS
+ * bit2: CP leave channel qith Quiet
+ * bit3: slotted mode
+ * 1 - work in slotted mode
+ * 0 - work in non slotted mode
+ * bit4: filter beacon notification
+ * bit5: full tx slotted mode. if this flag is set,
+ * uCode will perform leaving channel methods in context switch
+ * also when working in same channel mode
+ * @num_slots: 1 - 10
+ */
+struct iwl_wipan_params_cmd {
+ __le16 flags;
+ u8 reserved;
+ u8 num_slots;
+ struct iwl_wipan_slot slots[10];
+} __packed;
+
+/*
+ * REPLY_WIPAN_P2P_CHANNEL_SWITCH = 0xb9
+ *
+ * TODO: Figure out what this is used for,
+ * it can only switch between 2.4 GHz
+ * channels!!
+ */
+
+struct iwl_wipan_p2p_channel_switch_cmd {
+ __le16 channel;
+ __le16 reserved;
+};
+
+/*
+ * REPLY_WIPAN_NOA_NOTIFICATION = 0xbc
+ *
+ * This is used by the device to notify us of the
+ * NoA schedule it determined so we can forward it
+ * to userspace for inclusion in probe responses.
+ *
+ * In beacons, the NoA schedule is simply appended
+ * to the frame we give the device.
+ */
+
+struct iwl_wipan_noa_descriptor {
+ u8 count;
+ __le32 duration;
+ __le32 interval;
+ __le32 starttime;
+} __packed;
+
+struct iwl_wipan_noa_attribute {
+ u8 id;
+ __le16 length;
+ u8 index;
+ u8 ct_window;
+ struct iwl_wipan_noa_descriptor descr0, descr1;
+ u8 reserved;
+} __packed;
+
+struct iwl_wipan_noa_notification {
+ u32 noa_active;
+ struct iwl_wipan_noa_attribute noa_attribute;
+} __packed;
+
#endif /* __iwl_commands_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index e23c4060a0f0..25fb3912342c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -64,97 +64,14 @@ MODULE_LICENSE("GPL");
*
* default: bt_coex_active = true (BT_COEX_ENABLE)
*/
-static bool bt_coex_active = true;
+bool bt_coex_active = true;
+EXPORT_SYMBOL_GPL(bt_coex_active);
module_param(bt_coex_active, bool, S_IRUGO);
MODULE_PARM_DESC(bt_coex_active, "enable wifi/bluetooth co-exist");
-#define IWL_DECLARE_RATE_INFO(r, s, ip, in, rp, rn, pp, np) \
- [IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \
- IWL_RATE_SISO_##s##M_PLCP, \
- IWL_RATE_MIMO2_##s##M_PLCP,\
- IWL_RATE_MIMO3_##s##M_PLCP,\
- IWL_RATE_##r##M_IEEE, \
- IWL_RATE_##ip##M_INDEX, \
- IWL_RATE_##in##M_INDEX, \
- IWL_RATE_##rp##M_INDEX, \
- IWL_RATE_##rn##M_INDEX, \
- IWL_RATE_##pp##M_INDEX, \
- IWL_RATE_##np##M_INDEX }
-
u32 iwl_debug_level;
EXPORT_SYMBOL(iwl_debug_level);
-/*
- * Parameter order:
- * rate, ht rate, prev rate, next rate, prev tgg rate, next tgg rate
- *
- * If there isn't a valid next or previous rate then INV is used which
- * maps to IWL_RATE_INVALID
- *
- */
-const struct iwl_rate_info iwl_rates[IWL_RATE_COUNT] = {
- IWL_DECLARE_RATE_INFO(1, INV, INV, 2, INV, 2, INV, 2), /* 1mbps */
- IWL_DECLARE_RATE_INFO(2, INV, 1, 5, 1, 5, 1, 5), /* 2mbps */
- IWL_DECLARE_RATE_INFO(5, INV, 2, 6, 2, 11, 2, 11), /*5.5mbps */
- IWL_DECLARE_RATE_INFO(11, INV, 9, 12, 9, 12, 5, 18), /* 11mbps */
- IWL_DECLARE_RATE_INFO(6, 6, 5, 9, 5, 11, 5, 11), /* 6mbps */
- IWL_DECLARE_RATE_INFO(9, 6, 6, 11, 6, 11, 5, 11), /* 9mbps */
- IWL_DECLARE_RATE_INFO(12, 12, 11, 18, 11, 18, 11, 18), /* 12mbps */
- IWL_DECLARE_RATE_INFO(18, 18, 12, 24, 12, 24, 11, 24), /* 18mbps */
- IWL_DECLARE_RATE_INFO(24, 24, 18, 36, 18, 36, 18, 36), /* 24mbps */
- IWL_DECLARE_RATE_INFO(36, 36, 24, 48, 24, 48, 24, 48), /* 36mbps */
- IWL_DECLARE_RATE_INFO(48, 48, 36, 54, 36, 54, 36, 54), /* 48mbps */
- IWL_DECLARE_RATE_INFO(54, 54, 48, INV, 48, INV, 48, INV),/* 54mbps */
- IWL_DECLARE_RATE_INFO(60, 60, 48, INV, 48, INV, 48, INV),/* 60mbps */
- /* FIXME:RS: ^^ should be INV (legacy) */
-};
-EXPORT_SYMBOL(iwl_rates);
-
-int iwl_hwrate_to_plcp_idx(u32 rate_n_flags)
-{
- int idx = 0;
-
- /* HT rate format */
- if (rate_n_flags & RATE_MCS_HT_MSK) {
- idx = (rate_n_flags & 0xff);
-
- if (idx >= IWL_RATE_MIMO3_6M_PLCP)
- idx = idx - IWL_RATE_MIMO3_6M_PLCP;
- else if (idx >= IWL_RATE_MIMO2_6M_PLCP)
- idx = idx - IWL_RATE_MIMO2_6M_PLCP;
-
- idx += IWL_FIRST_OFDM_RATE;
- /* skip 9M not supported in ht*/
- if (idx >= IWL_RATE_9M_INDEX)
- idx += 1;
- if ((idx >= IWL_FIRST_OFDM_RATE) && (idx <= IWL_LAST_OFDM_RATE))
- return idx;
-
- /* legacy rate format, search for match in table */
- } else {
- for (idx = 0; idx < ARRAY_SIZE(iwl_rates); idx++)
- if (iwl_rates[idx].plcp == (rate_n_flags & 0xFF))
- return idx;
- }
-
- return -1;
-}
-EXPORT_SYMBOL(iwl_hwrate_to_plcp_idx);
-
-u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant, u8 valid)
-{
- int i;
- u8 ind = ant;
-
- for (i = 0; i < RATE_ANT_NUM - 1; i++) {
- ind = (ind + 1) < RATE_ANT_NUM ? ind + 1 : 0;
- if (valid & BIT(ind))
- return ind;
- }
- return ant;
-}
-EXPORT_SYMBOL(iwl_toggle_tx_ant);
-
const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
EXPORT_SYMBOL(iwl_bcast_addr);
@@ -183,38 +100,33 @@ out:
}
EXPORT_SYMBOL(iwl_alloc_all);
-void iwl_hw_detect(struct iwl_priv *priv)
-{
- priv->hw_rev = _iwl_read32(priv, CSR_HW_REV);
- priv->hw_wa_rev = _iwl_read32(priv, CSR_HW_REV_WA_REG);
- pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &priv->rev_id);
-}
-EXPORT_SYMBOL(iwl_hw_detect);
-
/*
* QoS support
*/
-static void iwl_update_qos(struct iwl_priv *priv)
+static void iwl_update_qos(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
{
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
- priv->qos_data.def_qos_parm.qos_flags = 0;
+ if (!ctx->is_active)
+ return;
+
+ ctx->qos_data.def_qos_parm.qos_flags = 0;
- if (priv->qos_data.qos_active)
- priv->qos_data.def_qos_parm.qos_flags |=
+ if (ctx->qos_data.qos_active)
+ ctx->qos_data.def_qos_parm.qos_flags |=
QOS_PARAM_FLG_UPDATE_EDCA_MSK;
- if (priv->current_ht_config.is_ht)
- priv->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK;
+ if (ctx->ht.enabled)
+ ctx->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK;
IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n",
- priv->qos_data.qos_active,
- priv->qos_data.def_qos_parm.qos_flags);
+ ctx->qos_data.qos_active,
+ ctx->qos_data.def_qos_parm.qos_flags);
- iwl_send_cmd_pdu_async(priv, REPLY_QOS_PARAM,
+ iwl_send_cmd_pdu_async(priv, ctx->qos_cmd,
sizeof(struct iwl_qosparam_cmd),
- &priv->qos_data.def_qos_parm, NULL);
+ &ctx->qos_data.def_qos_parm, NULL);
}
#define MAX_BIT_RATE_40_MHZ 150 /* Mbps */
@@ -232,7 +144,8 @@ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv,
ht_info->ht_supported = true;
- if (priv->cfg->ht_greenfield_support)
+ if (priv->cfg->ht_params &&
+ priv->cfg->ht_params->ht_greenfield_support)
ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD;
ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
max_bit_rate = MAX_BIT_RATE_20_MHZ;
@@ -247,7 +160,11 @@ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv,
ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU;
ht_info->ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF;
+ if (priv->cfg->bt_params && priv->cfg->bt_params->ampdu_factor)
+ ht_info->ampdu_factor = priv->cfg->bt_params->ampdu_factor;
ht_info->ampdu_density = CFG_HT_MPDU_DENSITY_DEF;
+ if (priv->cfg->bt_params && priv->cfg->bt_params->ampdu_density)
+ ht_info->ampdu_density = priv->cfg->bt_params->ampdu_density;
ht_info->mcs.rx_mask[0] = 0xFF;
if (rx_chains_num >= 2)
@@ -434,21 +351,15 @@ void iwlcore_tx_cmd_protection(struct iwl_priv *priv,
EXPORT_SYMBOL(iwlcore_tx_cmd_protection);
-static bool is_single_rx_stream(struct iwl_priv *priv)
-{
- return priv->current_ht_config.smps == IEEE80211_SMPS_STATIC ||
- priv->current_ht_config.single_chain_sufficient;
-}
-
-static u8 iwl_is_channel_extension(struct iwl_priv *priv,
- enum ieee80211_band band,
- u16 channel, u8 extension_chan_offset)
+static bool iwl_is_channel_extension(struct iwl_priv *priv,
+ enum ieee80211_band band,
+ u16 channel, u8 extension_chan_offset)
{
const struct iwl_channel_info *ch_info;
ch_info = iwl_get_channel_info(priv, band, channel);
if (!is_channel_valid(ch_info))
- return 0;
+ return false;
if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE)
return !(ch_info->ht40_extension_channel &
@@ -457,38 +368,59 @@ static u8 iwl_is_channel_extension(struct iwl_priv *priv,
return !(ch_info->ht40_extension_channel &
IEEE80211_CHAN_NO_HT40MINUS);
- return 0;
+ return false;
}
-u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
- struct ieee80211_sta_ht_cap *sta_ht_inf)
+bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx,
+ struct ieee80211_sta_ht_cap *ht_cap)
{
- struct iwl_ht_config *ht_conf = &priv->current_ht_config;
-
- if (!ht_conf->is_ht || !ht_conf->is_40mhz)
- return 0;
+ if (!ctx->ht.enabled || !ctx->ht.is_40mhz)
+ return false;
- /* We do not check for IEEE80211_HT_CAP_SUP_WIDTH_20_40
+ /*
+ * We do not check for IEEE80211_HT_CAP_SUP_WIDTH_20_40
* the bit will not set if it is pure 40MHz case
*/
- if (sta_ht_inf) {
- if (!sta_ht_inf->ht_supported)
- return 0;
- }
+ if (ht_cap && !ht_cap->ht_supported)
+ return false;
+
#ifdef CONFIG_IWLWIFI_DEBUGFS
if (priv->disable_ht40)
- return 0;
+ return false;
#endif
+
return iwl_is_channel_extension(priv, priv->band,
- le16_to_cpu(priv->staging_rxon.channel),
- ht_conf->extension_chan_offset);
+ le16_to_cpu(ctx->staging.channel),
+ ctx->ht.extension_chan_offset);
}
EXPORT_SYMBOL(iwl_is_ht40_tx_allowed);
static u16 iwl_adjust_beacon_interval(u16 beacon_val, u16 max_beacon_val)
{
- u16 new_val = 0;
- u16 beacon_factor = 0;
+ u16 new_val;
+ u16 beacon_factor;
+
+ /*
+ * If mac80211 hasn't given us a beacon interval, program
+ * the default into the device (not checking this here
+ * would cause the adjustment below to return the maximum
+ * value, which may break PAN.)
+ */
+ if (!beacon_val)
+ return DEFAULT_BEACON_INTERVAL;
+
+ /*
+ * If the beacon interval we obtained from the peer
+ * is too large, we'll have to wake up more often
+ * (and in IBSS case, we'll beacon too much)
+ *
+ * For example, if max_beacon_val is 4096, and the
+ * requested beacon interval is 7000, we'll have to
+ * use 3500 to be able to wake up on the beacons.
+ *
+ * This could badly influence beacon detection stats.
+ */
beacon_factor = (beacon_val + max_beacon_val) / max_beacon_val;
new_val = beacon_val / beacon_factor;
@@ -499,51 +431,76 @@ static u16 iwl_adjust_beacon_interval(u16 beacon_val, u16 max_beacon_val)
return new_val;
}
-void iwl_setup_rxon_timing(struct iwl_priv *priv, struct ieee80211_vif *vif)
+int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
{
u64 tsf;
s32 interval_tm, rem;
- unsigned long flags;
struct ieee80211_conf *conf = NULL;
u16 beacon_int;
+ struct ieee80211_vif *vif = ctx->vif;
conf = ieee80211_get_hw_conf(priv->hw);
- spin_lock_irqsave(&priv->lock, flags);
- priv->rxon_timing.timestamp = cpu_to_le64(priv->timestamp);
- priv->rxon_timing.listen_interval = cpu_to_le16(conf->listen_interval);
+ lockdep_assert_held(&priv->mutex);
- beacon_int = vif->bss_conf.beacon_int;
+ memset(&ctx->timing, 0, sizeof(struct iwl_rxon_time_cmd));
- if (vif->type == NL80211_IFTYPE_ADHOC) {
- /* TODO: we need to get atim_window from upper stack
- * for now we set to 0 */
- priv->rxon_timing.atim_window = 0;
- } else {
- priv->rxon_timing.atim_window = 0;
- }
+ ctx->timing.timestamp = cpu_to_le64(priv->timestamp);
+ ctx->timing.listen_interval = cpu_to_le16(conf->listen_interval);
- beacon_int = iwl_adjust_beacon_interval(beacon_int,
+ beacon_int = vif ? vif->bss_conf.beacon_int : 0;
+
+ /*
+ * TODO: For IBSS we need to get atim_window from mac80211,
+ * for now just always use 0
+ */
+ ctx->timing.atim_window = 0;
+
+ if (ctx->ctxid == IWL_RXON_CTX_PAN &&
+ (!ctx->vif || ctx->vif->type != NL80211_IFTYPE_STATION) &&
+ iwl_is_associated(priv, IWL_RXON_CTX_BSS) &&
+ priv->contexts[IWL_RXON_CTX_BSS].vif &&
+ priv->contexts[IWL_RXON_CTX_BSS].vif->bss_conf.beacon_int) {
+ ctx->timing.beacon_interval =
+ priv->contexts[IWL_RXON_CTX_BSS].timing.beacon_interval;
+ beacon_int = le16_to_cpu(ctx->timing.beacon_interval);
+ } else if (ctx->ctxid == IWL_RXON_CTX_BSS &&
+ iwl_is_associated(priv, IWL_RXON_CTX_PAN) &&
+ priv->contexts[IWL_RXON_CTX_PAN].vif &&
+ priv->contexts[IWL_RXON_CTX_PAN].vif->bss_conf.beacon_int &&
+ (!iwl_is_associated_ctx(ctx) || !ctx->vif ||
+ !ctx->vif->bss_conf.beacon_int)) {
+ ctx->timing.beacon_interval =
+ priv->contexts[IWL_RXON_CTX_PAN].timing.beacon_interval;
+ beacon_int = le16_to_cpu(ctx->timing.beacon_interval);
+ } else {
+ beacon_int = iwl_adjust_beacon_interval(beacon_int,
priv->hw_params.max_beacon_itrvl * TIME_UNIT);
- priv->rxon_timing.beacon_interval = cpu_to_le16(beacon_int);
+ ctx->timing.beacon_interval = cpu_to_le16(beacon_int);
+ }
tsf = priv->timestamp; /* tsf is modifed by do_div: copy it */
interval_tm = beacon_int * TIME_UNIT;
rem = do_div(tsf, interval_tm);
- priv->rxon_timing.beacon_init_val = cpu_to_le32(interval_tm - rem);
+ ctx->timing.beacon_init_val = cpu_to_le32(interval_tm - rem);
+
+ ctx->timing.dtim_period = vif ? (vif->bss_conf.dtim_period ?: 1) : 1;
- spin_unlock_irqrestore(&priv->lock, flags);
IWL_DEBUG_ASSOC(priv,
"beacon interval %d beacon timer %d beacon tim %d\n",
- le16_to_cpu(priv->rxon_timing.beacon_interval),
- le32_to_cpu(priv->rxon_timing.beacon_init_val),
- le16_to_cpu(priv->rxon_timing.atim_window));
+ le16_to_cpu(ctx->timing.beacon_interval),
+ le32_to_cpu(ctx->timing.beacon_init_val),
+ le16_to_cpu(ctx->timing.atim_window));
+
+ return iwl_send_cmd_pdu(priv, ctx->rxon_timing_cmd,
+ sizeof(ctx->timing), &ctx->timing);
}
-EXPORT_SYMBOL(iwl_setup_rxon_timing);
+EXPORT_SYMBOL(iwl_send_rxon_timing);
-void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt)
+void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
+ int hw_decrypt)
{
- struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
+ struct iwl_rxon_cmd *rxon = &ctx->staging;
if (hw_decrypt)
rxon->filter_flags &= ~RXON_FILTER_DIS_DECRYPT_MSK;
@@ -553,76 +510,74 @@ void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt)
}
EXPORT_SYMBOL(iwl_set_rxon_hwcrypto);
-/**
- * iwl_check_rxon_cmd - validate RXON structure is valid
- *
- * NOTE: This is really only useful during development and can eventually
- * be #ifdef'd out once the driver is stable and folks aren't actively
- * making changes
- */
-int iwl_check_rxon_cmd(struct iwl_priv *priv)
+/* validate RXON structure is valid */
+int iwl_check_rxon_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
{
- int error = 0;
- int counter = 1;
- struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
+ struct iwl_rxon_cmd *rxon = &ctx->staging;
+ bool error = false;
if (rxon->flags & RXON_FLG_BAND_24G_MSK) {
- error |= le32_to_cpu(rxon->flags &
- (RXON_FLG_TGJ_NARROW_BAND_MSK |
- RXON_FLG_RADAR_DETECT_MSK));
- if (error)
- IWL_WARN(priv, "check 24G fields %d | %d\n",
- counter++, error);
+ if (rxon->flags & RXON_FLG_TGJ_NARROW_BAND_MSK) {
+ IWL_WARN(priv, "check 2.4G: wrong narrow\n");
+ error = true;
+ }
+ if (rxon->flags & RXON_FLG_RADAR_DETECT_MSK) {
+ IWL_WARN(priv, "check 2.4G: wrong radar\n");
+ error = true;
+ }
} else {
- error |= (rxon->flags & RXON_FLG_SHORT_SLOT_MSK) ?
- 0 : le32_to_cpu(RXON_FLG_SHORT_SLOT_MSK);
- if (error)
- IWL_WARN(priv, "check 52 fields %d | %d\n",
- counter++, error);
- error |= le32_to_cpu(rxon->flags & RXON_FLG_CCK_MSK);
- if (error)
- IWL_WARN(priv, "check 52 CCK %d | %d\n",
- counter++, error);
- }
- error |= (rxon->node_addr[0] | rxon->bssid_addr[0]) & 0x1;
- if (error)
- IWL_WARN(priv, "check mac addr %d | %d\n", counter++, error);
+ if (!(rxon->flags & RXON_FLG_SHORT_SLOT_MSK)) {
+ IWL_WARN(priv, "check 5.2G: not short slot!\n");
+ error = true;
+ }
+ if (rxon->flags & RXON_FLG_CCK_MSK) {
+ IWL_WARN(priv, "check 5.2G: CCK!\n");
+ error = true;
+ }
+ }
+ if ((rxon->node_addr[0] | rxon->bssid_addr[0]) & 0x1) {
+ IWL_WARN(priv, "mac/bssid mcast!\n");
+ error = true;
+ }
/* make sure basic rates 6Mbps and 1Mbps are supported */
- error |= (((rxon->ofdm_basic_rates & IWL_RATE_6M_MASK) == 0) &&
- ((rxon->cck_basic_rates & IWL_RATE_1M_MASK) == 0));
- if (error)
- IWL_WARN(priv, "check basic rate %d | %d\n", counter++, error);
+ if ((rxon->ofdm_basic_rates & IWL_RATE_6M_MASK) == 0 &&
+ (rxon->cck_basic_rates & IWL_RATE_1M_MASK) == 0) {
+ IWL_WARN(priv, "neither 1 nor 6 are basic\n");
+ error = true;
+ }
- error |= (le16_to_cpu(rxon->assoc_id) > 2007);
- if (error)
- IWL_WARN(priv, "check assoc id %d | %d\n", counter++, error);
+ if (le16_to_cpu(rxon->assoc_id) > 2007) {
+ IWL_WARN(priv, "aid > 2007\n");
+ error = true;
+ }
- error |= ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK))
- == (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK));
- if (error)
- IWL_WARN(priv, "check CCK and short slot %d | %d\n",
- counter++, error);
+ if ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK))
+ == (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK)) {
+ IWL_WARN(priv, "CCK and short slot\n");
+ error = true;
+ }
- error |= ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK))
- == (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK));
- if (error)
- IWL_WARN(priv, "check CCK & auto detect %d | %d\n",
- counter++, error);
+ if ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK))
+ == (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK)) {
+ IWL_WARN(priv, "CCK and auto detect");
+ error = true;
+ }
- error |= ((rxon->flags & (RXON_FLG_AUTO_DETECT_MSK |
- RXON_FLG_TGG_PROTECT_MSK)) == RXON_FLG_TGG_PROTECT_MSK);
- if (error)
- IWL_WARN(priv, "check TGG and auto detect %d | %d\n",
- counter++, error);
+ if ((rxon->flags & (RXON_FLG_AUTO_DETECT_MSK |
+ RXON_FLG_TGG_PROTECT_MSK)) ==
+ RXON_FLG_TGG_PROTECT_MSK) {
+ IWL_WARN(priv, "TGg but no auto-detect\n");
+ error = true;
+ }
if (error)
IWL_WARN(priv, "Tuning to channel %d\n",
le16_to_cpu(rxon->channel));
if (error) {
- IWL_ERR(priv, "Not a valid iwl_rxon_assoc_cmd field values\n");
- return -1;
+ IWL_ERR(priv, "Invalid RXON\n");
+ return -EINVAL;
}
return 0;
}
@@ -636,66 +591,83 @@ EXPORT_SYMBOL(iwl_check_rxon_cmd);
* or is clearing the RXON_FILTER_ASSOC_MSK, then return 1 to indicate that
* a new tune (full RXON command, rather than RXON_ASSOC cmd) is required.
*/
-int iwl_full_rxon_required(struct iwl_priv *priv)
+int iwl_full_rxon_required(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx)
{
+ const struct iwl_rxon_cmd *staging = &ctx->staging;
+ const struct iwl_rxon_cmd *active = &ctx->active;
+
+#define CHK(cond) \
+ if ((cond)) { \
+ IWL_DEBUG_INFO(priv, "need full RXON - " #cond "\n"); \
+ return 1; \
+ }
+
+#define CHK_NEQ(c1, c2) \
+ if ((c1) != (c2)) { \
+ IWL_DEBUG_INFO(priv, "need full RXON - " \
+ #c1 " != " #c2 " - %d != %d\n", \
+ (c1), (c2)); \
+ return 1; \
+ }
/* These items are only settable from the full RXON command */
- if (!(iwl_is_associated(priv)) ||
- compare_ether_addr(priv->staging_rxon.bssid_addr,
- priv->active_rxon.bssid_addr) ||
- compare_ether_addr(priv->staging_rxon.node_addr,
- priv->active_rxon.node_addr) ||
- compare_ether_addr(priv->staging_rxon.wlap_bssid_addr,
- priv->active_rxon.wlap_bssid_addr) ||
- (priv->staging_rxon.dev_type != priv->active_rxon.dev_type) ||
- (priv->staging_rxon.channel != priv->active_rxon.channel) ||
- (priv->staging_rxon.air_propagation !=
- priv->active_rxon.air_propagation) ||
- (priv->staging_rxon.ofdm_ht_single_stream_basic_rates !=
- priv->active_rxon.ofdm_ht_single_stream_basic_rates) ||
- (priv->staging_rxon.ofdm_ht_dual_stream_basic_rates !=
- priv->active_rxon.ofdm_ht_dual_stream_basic_rates) ||
- (priv->staging_rxon.ofdm_ht_triple_stream_basic_rates !=
- priv->active_rxon.ofdm_ht_triple_stream_basic_rates) ||
- (priv->staging_rxon.assoc_id != priv->active_rxon.assoc_id))
- return 1;
+ CHK(!iwl_is_associated_ctx(ctx));
+ CHK(compare_ether_addr(staging->bssid_addr, active->bssid_addr));
+ CHK(compare_ether_addr(staging->node_addr, active->node_addr));
+ CHK(compare_ether_addr(staging->wlap_bssid_addr,
+ active->wlap_bssid_addr));
+ CHK_NEQ(staging->dev_type, active->dev_type);
+ CHK_NEQ(staging->channel, active->channel);
+ CHK_NEQ(staging->air_propagation, active->air_propagation);
+ CHK_NEQ(staging->ofdm_ht_single_stream_basic_rates,
+ active->ofdm_ht_single_stream_basic_rates);
+ CHK_NEQ(staging->ofdm_ht_dual_stream_basic_rates,
+ active->ofdm_ht_dual_stream_basic_rates);
+ CHK_NEQ(staging->ofdm_ht_triple_stream_basic_rates,
+ active->ofdm_ht_triple_stream_basic_rates);
+ CHK_NEQ(staging->assoc_id, active->assoc_id);
/* flags, filter_flags, ofdm_basic_rates, and cck_basic_rates can
* be updated with the RXON_ASSOC command -- however only some
* flag transitions are allowed using RXON_ASSOC */
/* Check if we are not switching bands */
- if ((priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) !=
- (priv->active_rxon.flags & RXON_FLG_BAND_24G_MSK))
- return 1;
+ CHK_NEQ(staging->flags & RXON_FLG_BAND_24G_MSK,
+ active->flags & RXON_FLG_BAND_24G_MSK);
/* Check if we are switching association toggle */
- if ((priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) !=
- (priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK))
- return 1;
+ CHK_NEQ(staging->filter_flags & RXON_FILTER_ASSOC_MSK,
+ active->filter_flags & RXON_FILTER_ASSOC_MSK);
+
+#undef CHK
+#undef CHK_NEQ
return 0;
}
EXPORT_SYMBOL(iwl_full_rxon_required);
-u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv)
+u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx)
{
/*
* Assign the lowest rate -- should really get this from
* the beacon skb from mac80211.
*/
- if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK)
+ if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK)
return IWL_RATE_1M_PLCP;
else
return IWL_RATE_6M_PLCP;
}
EXPORT_SYMBOL(iwl_rate_get_lowest_plcp);
-void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf)
+static void _iwl_set_rxon_ht(struct iwl_priv *priv,
+ struct iwl_ht_config *ht_conf,
+ struct iwl_rxon_context *ctx)
{
- struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
+ struct iwl_rxon_cmd *rxon = &ctx->staging;
- if (!ht_conf->is_ht) {
+ if (!ctx->ht.enabled) {
rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK |
RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK |
RXON_FLG_HT40_PROT_MSK |
@@ -703,22 +675,22 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf)
return;
}
- /* FIXME: if the definition of ht_protection changed, the "translation"
+ /* FIXME: if the definition of ht.protection changed, the "translation"
* will be needed for rxon->flags
*/
- rxon->flags |= cpu_to_le32(ht_conf->ht_protection << RXON_FLG_HT_OPERATING_MODE_POS);
+ rxon->flags |= cpu_to_le32(ctx->ht.protection << RXON_FLG_HT_OPERATING_MODE_POS);
/* Set up channel bandwidth:
* 20 MHz only, 20/40 mixed or pure 40 if ht40 ok */
/* clear the HT channel mode before set the mode */
rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK |
RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK);
- if (iwl_is_ht40_tx_allowed(priv, NULL)) {
+ if (iwl_is_ht40_tx_allowed(priv, ctx, NULL)) {
/* pure ht40 */
- if (ht_conf->ht_protection == IEEE80211_HT_OP_MODE_PROTECTION_20MHZ) {
+ if (ctx->ht.protection == IEEE80211_HT_OP_MODE_PROTECTION_20MHZ) {
rxon->flags |= RXON_FLG_CHANNEL_MODE_PURE_40;
/* Note: control channel is opposite of extension channel */
- switch (ht_conf->extension_chan_offset) {
+ switch (ctx->ht.extension_chan_offset) {
case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
rxon->flags &= ~RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK;
break;
@@ -728,7 +700,7 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf)
}
} else {
/* Note: control channel is opposite of extension channel */
- switch (ht_conf->extension_chan_offset) {
+ switch (ctx->ht.extension_chan_offset) {
case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
rxon->flags &= ~(RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK);
rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED;
@@ -749,162 +721,58 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf)
}
if (priv->cfg->ops->hcmd->set_rxon_chain)
- priv->cfg->ops->hcmd->set_rxon_chain(priv);
+ priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
IWL_DEBUG_ASSOC(priv, "rxon flags 0x%X operation mode :0x%X "
"extension channel offset 0x%x\n",
- le32_to_cpu(rxon->flags), ht_conf->ht_protection,
- ht_conf->extension_chan_offset);
-}
-EXPORT_SYMBOL(iwl_set_rxon_ht);
-
-#define IWL_NUM_RX_CHAINS_MULTIPLE 3
-#define IWL_NUM_RX_CHAINS_SINGLE 2
-#define IWL_NUM_IDLE_CHAINS_DUAL 2
-#define IWL_NUM_IDLE_CHAINS_SINGLE 1
-
-/*
- * Determine how many receiver/antenna chains to use.
- *
- * More provides better reception via diversity. Fewer saves power
- * at the expense of throughput, but only when not in powersave to
- * start with.
- *
- * MIMO (dual stream) requires at least 2, but works better with 3.
- * This does not determine *which* chains to use, just how many.
- */
-static int iwl_get_active_rx_chain_count(struct iwl_priv *priv)
-{
- /* # of Rx chains to use when expecting MIMO. */
- if (is_single_rx_stream(priv))
- return IWL_NUM_RX_CHAINS_SINGLE;
- else
- return IWL_NUM_RX_CHAINS_MULTIPLE;
-}
-
-/*
- * When we are in power saving mode, unless device support spatial
- * multiplexing power save, use the active count for rx chain count.
- */
-static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt)
-{
- /* # Rx chains when idling, depending on SMPS mode */
- switch (priv->current_ht_config.smps) {
- case IEEE80211_SMPS_STATIC:
- case IEEE80211_SMPS_DYNAMIC:
- return IWL_NUM_IDLE_CHAINS_SINGLE;
- case IEEE80211_SMPS_OFF:
- return active_cnt;
- default:
- WARN(1, "invalid SMPS mode %d",
- priv->current_ht_config.smps);
- return active_cnt;
- }
+ le32_to_cpu(rxon->flags), ctx->ht.protection,
+ ctx->ht.extension_chan_offset);
}
-/* up to 4 chains */
-static u8 iwl_count_chain_bitmap(u32 chain_bitmap)
+void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf)
{
- u8 res;
- res = (chain_bitmap & BIT(0)) >> 0;
- res += (chain_bitmap & BIT(1)) >> 1;
- res += (chain_bitmap & BIT(2)) >> 2;
- res += (chain_bitmap & BIT(3)) >> 3;
- return res;
-}
-
-/**
- * iwl_set_rxon_chain - Set up Rx chain usage in "staging" RXON image
- *
- * Selects how many and which Rx receivers/antennas/chains to use.
- * This should not be used for scan command ... it puts data in wrong place.
- */
-void iwl_set_rxon_chain(struct iwl_priv *priv)
-{
- bool is_single = is_single_rx_stream(priv);
- bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status);
- u8 idle_rx_cnt, active_rx_cnt, valid_rx_cnt;
- u32 active_chains;
- u16 rx_chain;
-
- /* Tell uCode which antennas are actually connected.
- * Before first association, we assume all antennas are connected.
- * Just after first association, iwl_chain_noise_calibration()
- * checks which antennas actually *are* connected. */
- if (priv->chain_noise_data.active_chains)
- active_chains = priv->chain_noise_data.active_chains;
- else
- active_chains = priv->hw_params.valid_rx_ant;
-
- rx_chain = active_chains << RXON_RX_CHAIN_VALID_POS;
-
- /* How many receivers should we use? */
- active_rx_cnt = iwl_get_active_rx_chain_count(priv);
- idle_rx_cnt = iwl_get_idle_rx_chain_count(priv, active_rx_cnt);
-
-
- /* correct rx chain count according hw settings
- * and chain noise calibration
- */
- valid_rx_cnt = iwl_count_chain_bitmap(active_chains);
- if (valid_rx_cnt < active_rx_cnt)
- active_rx_cnt = valid_rx_cnt;
-
- if (valid_rx_cnt < idle_rx_cnt)
- idle_rx_cnt = valid_rx_cnt;
-
- rx_chain |= active_rx_cnt << RXON_RX_CHAIN_MIMO_CNT_POS;
- rx_chain |= idle_rx_cnt << RXON_RX_CHAIN_CNT_POS;
-
- priv->staging_rxon.rx_chain = cpu_to_le16(rx_chain);
-
- if (!is_single && (active_rx_cnt >= IWL_NUM_RX_CHAINS_SINGLE) && is_cam)
- priv->staging_rxon.rx_chain |= RXON_RX_CHAIN_MIMO_FORCE_MSK;
- else
- priv->staging_rxon.rx_chain &= ~RXON_RX_CHAIN_MIMO_FORCE_MSK;
+ struct iwl_rxon_context *ctx;
- IWL_DEBUG_ASSOC(priv, "rx_chain=0x%X active=%d idle=%d\n",
- priv->staging_rxon.rx_chain,
- active_rx_cnt, idle_rx_cnt);
-
- WARN_ON(active_rx_cnt == 0 || idle_rx_cnt == 0 ||
- active_rx_cnt < idle_rx_cnt);
+ for_each_context(priv, ctx)
+ _iwl_set_rxon_ht(priv, ht_conf, ctx);
}
-EXPORT_SYMBOL(iwl_set_rxon_chain);
+EXPORT_SYMBOL(iwl_set_rxon_ht);
-/* Return valid channel */
+/* Return valid, unused, channel for a passive scan to reset the RF */
u8 iwl_get_single_channel_number(struct iwl_priv *priv,
- enum ieee80211_band band)
+ enum ieee80211_band band)
{
const struct iwl_channel_info *ch_info;
int i;
u8 channel = 0;
+ u8 min, max;
+ struct iwl_rxon_context *ctx;
- /* only scan single channel, good enough to reset the RF */
- /* pick the first valid not in-use channel */
if (band == IEEE80211_BAND_5GHZ) {
- for (i = 14; i < priv->channel_count; i++) {
- if (priv->channel_info[i].channel !=
- le16_to_cpu(priv->staging_rxon.channel)) {
- channel = priv->channel_info[i].channel;
- ch_info = iwl_get_channel_info(priv,
- band, channel);
- if (is_channel_valid(ch_info))
- break;
- }
- }
+ min = 14;
+ max = priv->channel_count;
} else {
- for (i = 0; i < 14; i++) {
- if (priv->channel_info[i].channel !=
- le16_to_cpu(priv->staging_rxon.channel)) {
- channel =
- priv->channel_info[i].channel;
- ch_info = iwl_get_channel_info(priv,
- band, channel);
- if (is_channel_valid(ch_info))
- break;
- }
+ min = 0;
+ max = 14;
+ }
+
+ for (i = min; i < max; i++) {
+ bool busy = false;
+
+ for_each_context(priv, ctx) {
+ busy = priv->channel_info[i].channel ==
+ le16_to_cpu(ctx->staging.channel);
+ if (busy)
+ break;
}
+
+ if (busy)
+ continue;
+
+ channel = priv->channel_info[i].channel;
+ ch_info = iwl_get_channel_info(priv, band, channel);
+ if (is_channel_valid(ch_info))
+ break;
}
return channel;
@@ -912,35 +780,27 @@ u8 iwl_get_single_channel_number(struct iwl_priv *priv,
EXPORT_SYMBOL(iwl_get_single_channel_number);
/**
- * iwl_set_rxon_channel - Set the phymode and channel values in staging RXON
- * @phymode: MODE_IEEE80211A sets to 5.2GHz; all else set to 2.4GHz
- * @channel: Any channel valid for the requested phymode
+ * iwl_set_rxon_channel - Set the band and channel values in staging RXON
+ * @ch: requested channel as a pointer to struct ieee80211_channel
- * In addition to setting the staging RXON, priv->phymode is also set.
- *
* NOTE: Does not commit to the hardware; it sets appropriate bit fields
- * in the staging RXON flag structure based on the phymode
+ * in the staging RXON flag structure based on the ch->band
*/
-int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch)
+int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch,
+ struct iwl_rxon_context *ctx)
{
enum ieee80211_band band = ch->band;
- u16 channel = ieee80211_frequency_to_channel(ch->center_freq);
+ u16 channel = ch->hw_value;
- if (!iwl_get_channel_info(priv, band, channel)) {
- IWL_DEBUG_INFO(priv, "Could not set channel to %d [%d]\n",
- channel, band);
- return -EINVAL;
- }
-
- if ((le16_to_cpu(priv->staging_rxon.channel) == channel) &&
+ if ((le16_to_cpu(ctx->staging.channel) == channel) &&
(priv->band == band))
return 0;
- priv->staging_rxon.channel = cpu_to_le16(channel);
+ ctx->staging.channel = cpu_to_le16(channel);
if (band == IEEE80211_BAND_5GHZ)
- priv->staging_rxon.flags &= ~RXON_FLG_BAND_24G_MSK;
+ ctx->staging.flags &= ~RXON_FLG_BAND_24G_MSK;
else
- priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK;
+ ctx->staging.flags |= RXON_FLG_BAND_24G_MSK;
priv->band = band;
@@ -951,24 +811,25 @@ int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch)
EXPORT_SYMBOL(iwl_set_rxon_channel);
void iwl_set_flags_for_band(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx,
enum ieee80211_band band,
struct ieee80211_vif *vif)
{
if (band == IEEE80211_BAND_5GHZ) {
- priv->staging_rxon.flags &=
+ ctx->staging.flags &=
~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK
| RXON_FLG_CCK_MSK);
- priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
+ ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
} else {
/* Copied from iwl_post_associate() */
if (vif && vif->bss_conf.use_short_slot)
- priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
+ ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
else
- priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
+ ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
- priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK;
- priv->staging_rxon.flags |= RXON_FLG_AUTO_DETECT_MSK;
- priv->staging_rxon.flags &= ~RXON_FLG_CCK_MSK;
+ ctx->staging.flags |= RXON_FLG_BAND_24G_MSK;
+ ctx->staging.flags |= RXON_FLG_AUTO_DETECT_MSK;
+ ctx->staging.flags &= ~RXON_FLG_CCK_MSK;
}
}
EXPORT_SYMBOL(iwl_set_flags_for_band);
@@ -977,35 +838,34 @@ EXPORT_SYMBOL(iwl_set_flags_for_band);
* initialize rxon structure with default values from eeprom
*/
void iwl_connection_init_rx_config(struct iwl_priv *priv,
- struct ieee80211_vif *vif)
+ struct iwl_rxon_context *ctx)
{
const struct iwl_channel_info *ch_info;
- enum nl80211_iftype type = NL80211_IFTYPE_STATION;
- if (vif)
- type = vif->type;
+ memset(&ctx->staging, 0, sizeof(ctx->staging));
- memset(&priv->staging_rxon, 0, sizeof(priv->staging_rxon));
-
- switch (type) {
+ if (!ctx->vif) {
+ ctx->staging.dev_type = ctx->unused_devtype;
+ } else switch (ctx->vif->type) {
case NL80211_IFTYPE_AP:
- priv->staging_rxon.dev_type = RXON_DEV_TYPE_AP;
+ ctx->staging.dev_type = ctx->ap_devtype;
break;
case NL80211_IFTYPE_STATION:
- priv->staging_rxon.dev_type = RXON_DEV_TYPE_ESS;
- priv->staging_rxon.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK;
+ ctx->staging.dev_type = ctx->station_devtype;
+ ctx->staging.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK;
break;
case NL80211_IFTYPE_ADHOC:
- priv->staging_rxon.dev_type = RXON_DEV_TYPE_IBSS;
- priv->staging_rxon.flags = RXON_FLG_SHORT_PREAMBLE_MSK;
- priv->staging_rxon.filter_flags = RXON_FILTER_BCON_AWARE_MSK |
+ ctx->staging.dev_type = ctx->ibss_devtype;
+ ctx->staging.flags = RXON_FLG_SHORT_PREAMBLE_MSK;
+ ctx->staging.filter_flags = RXON_FILTER_BCON_AWARE_MSK |
RXON_FILTER_ACCEPT_GRP_MSK;
break;
default:
- IWL_ERR(priv, "Unsupported interface type %d\n", type);
+ IWL_ERR(priv, "Unsupported interface type %d\n",
+ ctx->vif->type);
break;
}
@@ -1013,37 +873,36 @@ void iwl_connection_init_rx_config(struct iwl_priv *priv,
/* TODO: Figure out when short_preamble would be set and cache from
* that */
if (!hw_to_local(priv->hw)->short_preamble)
- priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
+ ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
else
- priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
+ ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
#endif
ch_info = iwl_get_channel_info(priv, priv->band,
- le16_to_cpu(priv->active_rxon.channel));
+ le16_to_cpu(ctx->active.channel));
if (!ch_info)
ch_info = &priv->channel_info[0];
- priv->staging_rxon.channel = cpu_to_le16(ch_info->channel);
+ ctx->staging.channel = cpu_to_le16(ch_info->channel);
priv->band = ch_info->band;
- iwl_set_flags_for_band(priv, priv->band, vif);
+ iwl_set_flags_for_band(priv, ctx, priv->band, ctx->vif);
- priv->staging_rxon.ofdm_basic_rates =
+ ctx->staging.ofdm_basic_rates =
(IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
- priv->staging_rxon.cck_basic_rates =
+ ctx->staging.cck_basic_rates =
(IWL_CCK_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF;
/* clear both MIX and PURE40 mode flag */
- priv->staging_rxon.flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED |
+ ctx->staging.flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED |
RXON_FLG_CHANNEL_MODE_PURE_40);
+ if (ctx->vif)
+ memcpy(ctx->staging.node_addr, ctx->vif->addr, ETH_ALEN);
- if (vif)
- memcpy(priv->staging_rxon.node_addr, vif->addr, ETH_ALEN);
-
- priv->staging_rxon.ofdm_ht_single_stream_basic_rates = 0xff;
- priv->staging_rxon.ofdm_ht_dual_stream_basic_rates = 0xff;
- priv->staging_rxon.ofdm_ht_triple_stream_basic_rates = 0xff;
+ ctx->staging.ofdm_ht_single_stream_basic_rates = 0xff;
+ ctx->staging.ofdm_ht_dual_stream_basic_rates = 0xff;
+ ctx->staging.ofdm_ht_triple_stream_basic_rates = 0xff;
}
EXPORT_SYMBOL(iwl_connection_init_rx_config);
@@ -1051,6 +910,7 @@ void iwl_set_rate(struct iwl_priv *priv)
{
const struct ieee80211_supported_band *hw = NULL;
struct ieee80211_rate *rate;
+ struct iwl_rxon_context *ctx;
int i;
hw = iwl_get_hw_mode(priv, priv->band);
@@ -1069,21 +929,29 @@ void iwl_set_rate(struct iwl_priv *priv)
IWL_DEBUG_RATE(priv, "Set active_rate = %0x\n", priv->active_rate);
- priv->staging_rxon.cck_basic_rates =
- (IWL_CCK_BASIC_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF;
+ for_each_context(priv, ctx) {
+ ctx->staging.cck_basic_rates =
+ (IWL_CCK_BASIC_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF;
- priv->staging_rxon.ofdm_basic_rates =
- (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
+ ctx->staging.ofdm_basic_rates =
+ (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
+ }
}
EXPORT_SYMBOL(iwl_set_rate);
void iwl_chswitch_done(struct iwl_priv *priv, bool is_success)
{
+ /*
+ * MULTI-FIXME
+ * See iwl_mac_channel_switch.
+ */
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
if (priv->switch_rxon.switch_in_progress) {
- ieee80211_chswitch_done(priv->vif, is_success);
+ ieee80211_chswitch_done(ctx->vif, is_success);
mutex_lock(&priv->mutex);
priv->switch_rxon.switch_in_progress = false;
mutex_unlock(&priv->mutex);
@@ -1094,14 +962,19 @@ EXPORT_SYMBOL(iwl_chswitch_done);
void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
- struct iwl_rxon_cmd *rxon = (void *)&priv->active_rxon;
struct iwl_csa_notification *csa = &(pkt->u.csa_notif);
+ /*
+ * MULTI-FIXME
+ * See iwl_mac_channel_switch.
+ */
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+ struct iwl_rxon_cmd *rxon = (void *)&ctx->active;
if (priv->switch_rxon.switch_in_progress) {
if (!le32_to_cpu(csa->status) &&
(csa->channel == priv->switch_rxon.channel)) {
rxon->channel = csa->channel;
- priv->staging_rxon.channel = csa->channel;
+ ctx->staging.channel = csa->channel;
IWL_DEBUG_11H(priv, "CSA notif: channel %d\n",
le16_to_cpu(csa->channel));
iwl_chswitch_done(priv, true);
@@ -1115,9 +988,10 @@ void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
EXPORT_SYMBOL(iwl_rx_csa);
#ifdef CONFIG_IWLWIFI_DEBUG
-void iwl_print_rx_config_cmd(struct iwl_priv *priv)
+void iwl_print_rx_config_cmd(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx)
{
- struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
+ struct iwl_rxon_cmd *rxon = &ctx->staging;
IWL_DEBUG_RADIO(priv, "RX CONFIG:\n");
iwl_print_hex_dump(priv, IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon));
@@ -1157,7 +1031,8 @@ void iwl_irq_handle_error(struct iwl_priv *priv)
priv->cfg->ops->lib->dump_nic_event_log(priv, false, NULL, false);
#ifdef CONFIG_IWLWIFI_DEBUG
if (iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS)
- iwl_print_rx_config_cmd(priv);
+ iwl_print_rx_config_cmd(priv,
+ &priv->contexts[IWL_RXON_CTX_BSS]);
#endif
wake_up_interruptible(&priv->wait_command_queue);
@@ -1261,7 +1136,7 @@ int iwl_apm_init(struct iwl_priv *priv)
* If not (unlikely), enable L0S, so there is at least some
* power savings, even without L1.
*/
- if (priv->cfg->set_l0s) {
+ if (priv->cfg->base_params->set_l0s) {
lctl = iwl_pcie_link_ctl(priv);
if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) ==
PCI_CFG_LINK_CTRL_VAL_L1_EN) {
@@ -1278,8 +1153,9 @@ int iwl_apm_init(struct iwl_priv *priv)
}
/* Configure analog phase-lock-loop before activating to D0A */
- if (priv->cfg->pll_cfg_val)
- iwl_set_bit(priv, CSR_ANA_PLL_CFG, priv->cfg->pll_cfg_val);
+ if (priv->cfg->base_params->pll_cfg_val)
+ iwl_set_bit(priv, CSR_ANA_PLL_CFG,
+ priv->cfg->base_params->pll_cfg_val);
/*
* Set "initialization complete" bit to move adapter from
@@ -1310,7 +1186,7 @@ int iwl_apm_init(struct iwl_priv *priv)
* do not disable clocks. This preserves any hardware bits already
* set by default in "CLK_CTRL_REG" after reset.
*/
- if (priv->cfg->use_bsm)
+ if (priv->cfg->base_params->use_bsm)
iwl_write_prph(priv, APMG_CLK_EN_REG,
APMG_CLK_VAL_DMA_CLK_RQT | APMG_CLK_VAL_BSM_CLK_RQT);
else
@@ -1328,25 +1204,6 @@ out:
EXPORT_SYMBOL(iwl_apm_init);
-int iwl_set_hw_params(struct iwl_priv *priv)
-{
- priv->hw_params.max_rxq_size = RX_QUEUE_SIZE;
- priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG;
- if (priv->cfg->mod_params->amsdu_size_8K)
- priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_8K);
- else
- priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_4K);
-
- priv->hw_params.max_beacon_itrvl = IWL_MAX_UCODE_BEACON_INTERVAL;
-
- if (priv->cfg->mod_params->disable_11n)
- priv->cfg->sku &= ~IWL_SKU_N;
-
- /* Device-specific setup */
- return priv->cfg->ops->lib->set_hw_params(priv);
-}
-EXPORT_SYMBOL(iwl_set_hw_params);
-
int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
{
int ret = 0;
@@ -1496,76 +1353,6 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear)
}
EXPORT_SYMBOL(iwl_send_statistics_request);
-void iwl_rf_kill_ct_config(struct iwl_priv *priv)
-{
- struct iwl_ct_kill_config cmd;
- struct iwl_ct_kill_throttling_config adv_cmd;
- unsigned long flags;
- int ret = 0;
-
- spin_lock_irqsave(&priv->lock, flags);
- iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
- CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
- spin_unlock_irqrestore(&priv->lock, flags);
- priv->thermal_throttle.ct_kill_toggle = false;
-
- if (priv->cfg->support_ct_kill_exit) {
- adv_cmd.critical_temperature_enter =
- cpu_to_le32(priv->hw_params.ct_kill_threshold);
- adv_cmd.critical_temperature_exit =
- cpu_to_le32(priv->hw_params.ct_kill_exit_threshold);
-
- ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD,
- sizeof(adv_cmd), &adv_cmd);
- if (ret)
- IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n");
- else
- IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD "
- "succeeded, "
- "critical temperature enter is %d,"
- "exit is %d\n",
- priv->hw_params.ct_kill_threshold,
- priv->hw_params.ct_kill_exit_threshold);
- } else {
- cmd.critical_temperature_R =
- cpu_to_le32(priv->hw_params.ct_kill_threshold);
-
- ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD,
- sizeof(cmd), &cmd);
- if (ret)
- IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n");
- else
- IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD "
- "succeeded, "
- "critical temperature is %d\n",
- priv->hw_params.ct_kill_threshold);
- }
-}
-EXPORT_SYMBOL(iwl_rf_kill_ct_config);
-
-
-/*
- * CARD_STATE_CMD
- *
- * Use: Sets the device's internal card state to enable, disable, or halt
- *
- * When in the 'enable' state the card operates as normal.
- * When in the 'disable' state, the card enters into a low power mode.
- * When in the 'halt' state, the card is shut down and must be fully
- * restarted to come back on.
- */
-int iwl_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_flag)
-{
- struct iwl_host_cmd cmd = {
- .id = REPLY_CARD_STATE_CMD,
- .len = sizeof(u32),
- .data = &flags,
- .flags = meta_flag,
- };
-
- return iwl_send_cmd(priv, &cmd);
-}
-
void iwl_rx_pm_sleep_notif(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
@@ -1614,6 +1401,7 @@ int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
struct iwl_priv *priv = hw->priv;
+ struct iwl_rxon_context *ctx;
unsigned long flags;
int q;
@@ -1633,13 +1421,21 @@ int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
spin_lock_irqsave(&priv->lock, flags);
- priv->qos_data.def_qos_parm.ac[q].cw_min = cpu_to_le16(params->cw_min);
- priv->qos_data.def_qos_parm.ac[q].cw_max = cpu_to_le16(params->cw_max);
- priv->qos_data.def_qos_parm.ac[q].aifsn = params->aifs;
- priv->qos_data.def_qos_parm.ac[q].edca_txop =
- cpu_to_le16((params->txop * 32));
+ /*
+ * MULTI-FIXME
+ * This may need to be done per interface in nl80211/cfg80211/mac80211.
+ */
+ for_each_context(priv, ctx) {
+ ctx->qos_data.def_qos_parm.ac[q].cw_min =
+ cpu_to_le16(params->cw_min);
+ ctx->qos_data.def_qos_parm.ac[q].cw_max =
+ cpu_to_le16(params->cw_max);
+ ctx->qos_data.def_qos_parm.ac[q].aifsn = params->aifs;
+ ctx->qos_data.def_qos_parm.ac[q].edca_txop =
+ cpu_to_le16((params->txop * 32));
- priv->qos_data.def_qos_parm.ac[q].reserved1 = 0;
+ ctx->qos_data.def_qos_parm.ac[q].reserved1 = 0;
+ }
spin_unlock_irqrestore(&priv->lock, flags);
@@ -1648,21 +1444,30 @@ int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
}
EXPORT_SYMBOL(iwl_mac_conf_tx);
+int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw)
+{
+ struct iwl_priv *priv = hw->priv;
+
+ return priv->ibss_manager == IWL_IBSS_MANAGER;
+}
+EXPORT_SYMBOL_GPL(iwl_mac_tx_last_beacon);
+
static void iwl_ht_conf(struct iwl_priv *priv,
struct ieee80211_vif *vif)
{
struct iwl_ht_config *ht_conf = &priv->current_ht_config;
struct ieee80211_sta *sta;
struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
+ struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
IWL_DEBUG_MAC80211(priv, "enter:\n");
- if (!ht_conf->is_ht)
+ if (!ctx->ht.enabled)
return;
- ht_conf->ht_protection =
+ ctx->ht.protection =
bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION;
- ht_conf->non_GF_STA_present =
+ ctx->ht.non_gf_sta_present =
!!(bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
ht_conf->single_chain_sufficient = false;
@@ -1706,49 +1511,63 @@ static void iwl_ht_conf(struct iwl_priv *priv,
IWL_DEBUG_MAC80211(priv, "leave\n");
}
-static inline void iwl_set_no_assoc(struct iwl_priv *priv)
+static inline void iwl_set_no_assoc(struct iwl_priv *priv,
+ struct ieee80211_vif *vif)
{
+ struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
+
iwl_led_disassociate(priv);
/*
* inform the ucode that there is no longer an
* association and that no more packets should be
* sent
*/
- priv->staging_rxon.filter_flags &=
- ~RXON_FILTER_ASSOC_MSK;
- priv->staging_rxon.assoc_id = 0;
- iwlcore_commit_rxon(priv);
+ ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+ ctx->staging.assoc_id = 0;
+ iwlcore_commit_rxon(priv, ctx);
}
-static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
+static void iwlcore_beacon_update(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
{
struct iwl_priv *priv = hw->priv;
unsigned long flags;
__le64 timestamp;
+ struct sk_buff *skb = ieee80211_beacon_get(hw, vif);
- IWL_DEBUG_MAC80211(priv, "enter\n");
+ if (!skb)
+ return;
- if (!iwl_is_ready_rf(priv)) {
- IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
- return -EIO;
+ IWL_DEBUG_ASSOC(priv, "enter\n");
+
+ lockdep_assert_held(&priv->mutex);
+
+ if (!priv->beacon_ctx) {
+ IWL_ERR(priv, "update beacon but no beacon context!\n");
+ dev_kfree_skb(skb);
+ return;
}
spin_lock_irqsave(&priv->lock, flags);
- if (priv->ibss_beacon)
- dev_kfree_skb(priv->ibss_beacon);
+ if (priv->beacon_skb)
+ dev_kfree_skb(priv->beacon_skb);
- priv->ibss_beacon = skb;
+ priv->beacon_skb = skb;
timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
priv->timestamp = le64_to_cpu(timestamp);
- IWL_DEBUG_MAC80211(priv, "leave\n");
+ IWL_DEBUG_ASSOC(priv, "leave\n");
+
spin_unlock_irqrestore(&priv->lock, flags);
- priv->cfg->ops->lib->post_associate(priv, priv->vif);
+ if (!iwl_is_ready_rf(priv)) {
+ IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
+ return;
+ }
- return 0;
+ priv->cfg->ops->lib->post_associate(priv, priv->beacon_ctx->vif);
}
void iwl_bss_info_changed(struct ieee80211_hw *hw,
@@ -1757,6 +1576,7 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
u32 changes)
{
struct iwl_priv *priv = hw->priv;
+ struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
int ret;
IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes);
@@ -1770,20 +1590,31 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
unsigned long flags;
spin_lock_irqsave(&priv->lock, flags);
- priv->qos_data.qos_active = bss_conf->qos;
- iwl_update_qos(priv);
+ ctx->qos_data.qos_active = bss_conf->qos;
+ iwl_update_qos(priv, ctx);
spin_unlock_irqrestore(&priv->lock, flags);
}
- if (changes & BSS_CHANGED_BEACON && vif->type == NL80211_IFTYPE_AP) {
- dev_kfree_skb(priv->ibss_beacon);
- priv->ibss_beacon = ieee80211_beacon_get(hw, vif);
+ if (changes & BSS_CHANGED_BEACON_ENABLED) {
+ /*
+ * the add_interface code must make sure we only ever
+ * have a single interface that could be beaconing at
+ * any time.
+ */
+ if (vif->bss_conf.enable_beacon)
+ priv->beacon_ctx = ctx;
+ else
+ priv->beacon_ctx = NULL;
}
- if (changes & BSS_CHANGED_BEACON_INT) {
- /* TODO: in AP mode, do something to make this take effect */
+ if (changes & BSS_CHANGED_BEACON && vif->type == NL80211_IFTYPE_AP) {
+ dev_kfree_skb(priv->beacon_skb);
+ priv->beacon_skb = ieee80211_beacon_get(hw, vif);
}
+ if (changes & BSS_CHANGED_BEACON_INT && vif->type == NL80211_IFTYPE_AP)
+ iwl_send_rxon_timing(priv, ctx);
+
if (changes & BSS_CHANGED_BSSID) {
IWL_DEBUG_MAC80211(priv, "BSSID %pM\n", bss_conf->bssid);
@@ -1801,13 +1632,13 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
/* mac80211 only sets assoc when in STATION mode */
if (vif->type == NL80211_IFTYPE_ADHOC || bss_conf->assoc) {
- memcpy(priv->staging_rxon.bssid_addr,
+ memcpy(ctx->staging.bssid_addr,
bss_conf->bssid, ETH_ALEN);
/* currently needed in a few places */
memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN);
} else {
- priv->staging_rxon.filter_flags &=
+ ctx->staging.filter_flags &=
~RXON_FILTER_ASSOC_MSK;
}
@@ -1818,33 +1649,28 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
* mac80211 decides to do both changes at once because
* it will invoke post_associate.
*/
- if (vif->type == NL80211_IFTYPE_ADHOC &&
- changes & BSS_CHANGED_BEACON) {
- struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
-
- if (beacon)
- iwl_mac_beacon_update(hw, beacon);
- }
+ if (vif->type == NL80211_IFTYPE_ADHOC && changes & BSS_CHANGED_BEACON)
+ iwlcore_beacon_update(hw, vif);
if (changes & BSS_CHANGED_ERP_PREAMBLE) {
IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n",
bss_conf->use_short_preamble);
if (bss_conf->use_short_preamble)
- priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
+ ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
else
- priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
+ ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
}
if (changes & BSS_CHANGED_ERP_CTS_PROT) {
IWL_DEBUG_MAC80211(priv, "ERP_CTS %d\n", bss_conf->use_cts_prot);
if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ))
- priv->staging_rxon.flags |= RXON_FLG_TGG_PROTECT_MSK;
+ ctx->staging.flags |= RXON_FLG_TGG_PROTECT_MSK;
else
- priv->staging_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
+ ctx->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
if (bss_conf->use_cts_prot)
- priv->staging_rxon.flags |= RXON_FLG_SELF_CTS_EN;
+ ctx->staging.flags |= RXON_FLG_SELF_CTS_EN;
else
- priv->staging_rxon.flags &= ~RXON_FLG_SELF_CTS_EN;
+ ctx->staging.flags &= ~RXON_FLG_SELF_CTS_EN;
}
if (changes & BSS_CHANGED_BASIC_RATES) {
@@ -1854,12 +1680,12 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
* like this here:
*
if (A-band)
- priv->staging_rxon.ofdm_basic_rates =
+ ctx->staging.ofdm_basic_rates =
bss_conf->basic_rates;
else
- priv->staging_rxon.ofdm_basic_rates =
+ ctx->staging.ofdm_basic_rates =
bss_conf->basic_rates >> 4;
- priv->staging_rxon.cck_basic_rates =
+ ctx->staging.cck_basic_rates =
bss_conf->basic_rates & 0xF;
*/
}
@@ -1868,7 +1694,7 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
iwl_ht_conf(priv, vif);
if (priv->cfg->ops->hcmd->set_rxon_chain)
- priv->cfg->ops->hcmd->set_rxon_chain(priv);
+ priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
}
if (changes & BSS_CHANGED_ASSOC) {
@@ -1881,29 +1707,30 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
if (!iwl_is_rfkill(priv))
priv->cfg->ops->lib->post_associate(priv, vif);
} else
- iwl_set_no_assoc(priv);
+ iwl_set_no_assoc(priv, vif);
}
- if (changes && iwl_is_associated(priv) && bss_conf->aid) {
+ if (changes && iwl_is_associated_ctx(ctx) && bss_conf->aid) {
IWL_DEBUG_MAC80211(priv, "Changes (%#x) while associated\n",
changes);
- ret = iwl_send_rxon_assoc(priv);
+ ret = iwl_send_rxon_assoc(priv, ctx);
if (!ret) {
/* Sync active_rxon with latest change. */
- memcpy((void *)&priv->active_rxon,
- &priv->staging_rxon,
+ memcpy((void *)&ctx->active,
+ &ctx->staging,
sizeof(struct iwl_rxon_cmd));
}
}
if (changes & BSS_CHANGED_BEACON_ENABLED) {
if (vif->bss_conf.enable_beacon) {
- memcpy(priv->staging_rxon.bssid_addr,
+ memcpy(ctx->staging.bssid_addr,
bss_conf->bssid, ETH_ALEN);
memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN);
+ iwl_led_associate(priv);
iwlcore_config_ap(priv, vif);
} else
- iwl_set_no_assoc(priv);
+ iwl_set_no_assoc(priv, vif);
}
if (changes & BSS_CHANGED_IBSS) {
@@ -1915,6 +1742,12 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
bss_conf->bssid);
}
+ if (changes & BSS_CHANGED_IDLE &&
+ priv->cfg->ops->hcmd->set_pan_params) {
+ if (priv->cfg->ops->hcmd->set_pan_params(priv))
+ IWL_ERR(priv, "failed to update PAN params\n");
+ }
+
mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n");
@@ -1923,17 +1756,21 @@ EXPORT_SYMBOL(iwl_bss_info_changed);
static int iwl_set_mode(struct iwl_priv *priv, struct ieee80211_vif *vif)
{
- iwl_connection_init_rx_config(priv, vif);
+ struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
+
+ iwl_connection_init_rx_config(priv, ctx);
if (priv->cfg->ops->hcmd->set_rxon_chain)
- priv->cfg->ops->hcmd->set_rxon_chain(priv);
+ priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
- return iwlcore_commit_rxon(priv);
+ return iwlcore_commit_rxon(priv, ctx);
}
int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
struct iwl_priv *priv = hw->priv;
+ struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
+ struct iwl_rxon_context *tmp, *ctx = NULL;
int err = 0;
IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n",
@@ -1941,28 +1778,72 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
mutex_lock(&priv->mutex);
- if (WARN_ON(!iwl_is_ready_rf(priv))) {
+ if (!iwl_is_ready_rf(priv)) {
+ IWL_WARN(priv, "Try to add interface when device not ready\n");
err = -EINVAL;
goto out;
}
- if (priv->vif) {
- IWL_DEBUG_MAC80211(priv, "leave - vif != NULL\n");
+ for_each_context(priv, tmp) {
+ u32 possible_modes =
+ tmp->interface_modes | tmp->exclusive_interface_modes;
+
+ if (tmp->vif) {
+ /* check if this busy context is exclusive */
+ if (tmp->exclusive_interface_modes &
+ BIT(tmp->vif->type)) {
+ err = -EINVAL;
+ goto out;
+ }
+ continue;
+ }
+
+ if (!(possible_modes & BIT(vif->type)))
+ continue;
+
+ /* have maybe usable context w/o interface */
+ ctx = tmp;
+ break;
+ }
+
+ if (!ctx) {
err = -EOPNOTSUPP;
goto out;
}
- priv->vif = vif;
+ vif_priv->ctx = ctx;
+ ctx->vif = vif;
+ /*
+ * This variable will be correct only when there's just
+ * a single context, but all code using it is for hardware
+ * that supports only one context.
+ */
priv->iw_mode = vif->type;
+ ctx->is_active = true;
+
err = iwl_set_mode(priv, vif);
- if (err)
+ if (err) {
+ if (!ctx->always_active)
+ ctx->is_active = false;
goto out_err;
+ }
+
+ if (priv->cfg->bt_params &&
+ priv->cfg->bt_params->advanced_bt_coexist &&
+ vif->type == NL80211_IFTYPE_ADHOC) {
+ /*
+ * pretend to have high BT traffic as long as we
+ * are operating in IBSS mode, as this will cause
+ * the rate scaling etc. to behave as intended.
+ */
+ priv->bt_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_HIGH;
+ }
goto out;
out_err:
- priv->vif = NULL;
+ ctx->vif = NULL;
priv->iw_mode = NL80211_IFTYPE_STATION;
out:
mutex_unlock(&priv->mutex);
@@ -1976,30 +1857,36 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct iwl_priv *priv = hw->priv;
- bool scan_completed = false;
+ struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
IWL_DEBUG_MAC80211(priv, "enter\n");
mutex_lock(&priv->mutex);
- if (iwl_is_ready_rf(priv)) {
- iwl_scan_cancel_timeout(priv, 100);
- priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
- iwlcore_commit_rxon(priv);
- }
- if (priv->vif == vif) {
- priv->vif = NULL;
- if (priv->scan_vif == vif) {
- scan_completed = true;
- priv->scan_vif = NULL;
- priv->scan_request = NULL;
- }
- memset(priv->bssid, 0, ETH_ALEN);
+ WARN_ON(ctx->vif != vif);
+ ctx->vif = NULL;
+
+ if (priv->scan_vif == vif) {
+ iwl_scan_cancel_timeout(priv, 200);
+ iwl_force_scan_end(priv);
}
- mutex_unlock(&priv->mutex);
+ iwl_set_mode(priv, vif);
- if (scan_completed)
- ieee80211_scan_completed(priv->hw, true);
+ if (!ctx->always_active)
+ ctx->is_active = false;
+
+ /*
+ * When removing the IBSS interface, overwrite the
+ * BT traffic load with the stored one from the last
+ * notification, if any. If this is a device that
+ * doesn't implement this, this has no effect since
+ * both values are the same and zero.
+ */
+ if (vif->type == NL80211_IFTYPE_ADHOC)
+ priv->bt_traffic_load = priv->notif_bt_traffic_load;
+
+ memset(priv->bssid, 0, ETH_ALEN);
+ mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n");
@@ -2014,7 +1901,9 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
struct iwl_priv *priv = hw->priv;
const struct iwl_channel_info *ch_info;
struct ieee80211_conf *conf = &hw->conf;
+ struct ieee80211_channel *channel = conf->channel;
struct iwl_ht_config *ht_conf = &priv->current_ht_config;
+ struct iwl_rxon_context *ctx;
unsigned long flags = 0;
int ret = 0;
u16 ch;
@@ -2023,7 +1912,7 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
mutex_lock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "enter to channel %d changed 0x%X\n",
- conf->channel->hw_value, changed);
+ channel->hw_value, changed);
if (unlikely(!priv->cfg->mod_params->disable_hw_scan &&
test_bit(STATUS_SCANNING, &priv->status))) {
@@ -2044,7 +1933,8 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
* configured.
*/
if (priv->cfg->ops->hcmd->set_rxon_chain)
- priv->cfg->ops->hcmd->set_rxon_chain(priv);
+ for_each_context(priv, ctx)
+ priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
}
/* during scanning mac80211 will delay channel setting until
@@ -2054,8 +1944,8 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
if (scan_active)
goto set_ch_out;
- ch = ieee80211_frequency_to_channel(conf->channel->center_freq);
- ch_info = iwl_get_channel_info(priv, conf->channel->band, ch);
+ ch = channel->hw_value;
+ ch_info = iwl_get_channel_info(priv, channel->band, ch);
if (!is_channel_valid(ch_info)) {
IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n");
ret = -EINVAL;
@@ -2064,42 +1954,49 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
spin_lock_irqsave(&priv->lock, flags);
- /* Configure HT40 channels */
- ht_conf->is_ht = conf_is_ht(conf);
- if (ht_conf->is_ht) {
- if (conf_is_ht40_minus(conf)) {
- ht_conf->extension_chan_offset =
- IEEE80211_HT_PARAM_CHA_SEC_BELOW;
- ht_conf->is_40mhz = true;
- } else if (conf_is_ht40_plus(conf)) {
- ht_conf->extension_chan_offset =
- IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
- ht_conf->is_40mhz = true;
- } else {
- ht_conf->extension_chan_offset =
- IEEE80211_HT_PARAM_CHA_SEC_NONE;
- ht_conf->is_40mhz = false;
- }
- } else
- ht_conf->is_40mhz = false;
- /* Default to no protection. Protection mode will later be set
- * from BSS config in iwl_ht_conf */
- ht_conf->ht_protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE;
+ for_each_context(priv, ctx) {
+ /* Configure HT40 channels */
+ ctx->ht.enabled = conf_is_ht(conf);
+ if (ctx->ht.enabled) {
+ if (conf_is_ht40_minus(conf)) {
+ ctx->ht.extension_chan_offset =
+ IEEE80211_HT_PARAM_CHA_SEC_BELOW;
+ ctx->ht.is_40mhz = true;
+ } else if (conf_is_ht40_plus(conf)) {
+ ctx->ht.extension_chan_offset =
+ IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
+ ctx->ht.is_40mhz = true;
+ } else {
+ ctx->ht.extension_chan_offset =
+ IEEE80211_HT_PARAM_CHA_SEC_NONE;
+ ctx->ht.is_40mhz = false;
+ }
+ } else
+ ctx->ht.is_40mhz = false;
- /* if we are switching from ht to 2.4 clear flags
- * from any ht related info since 2.4 does not
- * support ht */
- if ((le16_to_cpu(priv->staging_rxon.channel) != ch))
- priv->staging_rxon.flags = 0;
+ /*
+ * Default to no protection. Protection mode will
+ * later be set from BSS config in iwl_ht_conf
+ */
+ ctx->ht.protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE;
- iwl_set_rxon_channel(priv, conf->channel);
- iwl_set_rxon_ht(priv, ht_conf);
+ /* if we are switching from ht to 2.4 clear flags
+ * from any ht related info since 2.4 does not
+ * support ht */
+ if ((le16_to_cpu(ctx->staging.channel) != ch))
+ ctx->staging.flags = 0;
+
+ iwl_set_rxon_channel(priv, channel, ctx);
+ iwl_set_rxon_ht(priv, ht_conf);
+
+ iwl_set_flags_for_band(priv, ctx, channel->band,
+ ctx->vif);
+ }
- iwl_set_flags_for_band(priv, conf->channel->band, priv->vif);
spin_unlock_irqrestore(&priv->lock, flags);
- if (priv->cfg->ops->lib->update_bcast_station)
- ret = priv->cfg->ops->lib->update_bcast_station(priv);
+ if (priv->cfg->ops->lib->update_bcast_stations)
+ ret = priv->cfg->ops->lib->update_bcast_stations(priv);
set_ch_out:
/* The list of supported rates and rate mask can be different
@@ -2130,12 +2027,13 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
if (scan_active)
goto out;
- if (memcmp(&priv->active_rxon,
- &priv->staging_rxon, sizeof(priv->staging_rxon)))
- iwlcore_commit_rxon(priv);
- else
- IWL_DEBUG_INFO(priv, "Not re-sending same RXON configuration.\n");
-
+ for_each_context(priv, ctx) {
+ if (memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging)))
+ iwlcore_commit_rxon(priv, ctx);
+ else
+ IWL_DEBUG_INFO(priv,
+ "Not re-sending same RXON configuration.\n");
+ }
out:
IWL_DEBUG_MAC80211(priv, "leave\n");
@@ -2148,6 +2046,8 @@ void iwl_mac_reset_tsf(struct ieee80211_hw *hw)
{
struct iwl_priv *priv = hw->priv;
unsigned long flags;
+ /* IBSS can only be the IWL_RXON_CTX_BSS context */
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
mutex_lock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "enter\n");
@@ -2159,15 +2059,16 @@ void iwl_mac_reset_tsf(struct ieee80211_hw *hw)
spin_lock_irqsave(&priv->lock, flags);
/* new association get rid of ibss beacon skb */
- if (priv->ibss_beacon)
- dev_kfree_skb(priv->ibss_beacon);
+ if (priv->beacon_skb)
+ dev_kfree_skb(priv->beacon_skb);
- priv->ibss_beacon = NULL;
+ priv->beacon_skb = NULL;
priv->timestamp = 0;
spin_unlock_irqrestore(&priv->lock, flags);
+ iwl_scan_cancel_timeout(priv, 100);
if (!iwl_is_ready_rf(priv)) {
IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
mutex_unlock(&priv->mutex);
@@ -2177,9 +2078,8 @@ void iwl_mac_reset_tsf(struct ieee80211_hw *hw)
/* we are restarting association process
* clear RXON_FILTER_ASSOC_MSK bit
*/
- iwl_scan_cancel_timeout(priv, 100);
- priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
- iwlcore_commit_rxon(priv);
+ ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+ iwlcore_commit_rxon(priv, ctx);
iwl_set_rate(priv);
@@ -2193,7 +2093,8 @@ int iwl_alloc_txq_mem(struct iwl_priv *priv)
{
if (!priv->txq)
priv->txq = kzalloc(
- sizeof(struct iwl_tx_queue) * priv->cfg->num_of_queues,
+ sizeof(struct iwl_tx_queue) *
+ priv->cfg->base_params->num_of_queues,
GFP_KERNEL);
if (!priv->txq) {
IWL_ERR(priv, "Not enough memory for txq\n");
@@ -2449,146 +2350,12 @@ void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len)
EXPORT_SYMBOL(iwl_update_stats);
#endif
-static const char *get_csr_string(int cmd)
-{
- switch (cmd) {
- IWL_CMD(CSR_HW_IF_CONFIG_REG);
- IWL_CMD(CSR_INT_COALESCING);
- IWL_CMD(CSR_INT);
- IWL_CMD(CSR_INT_MASK);
- IWL_CMD(CSR_FH_INT_STATUS);
- IWL_CMD(CSR_GPIO_IN);
- IWL_CMD(CSR_RESET);
- IWL_CMD(CSR_GP_CNTRL);
- IWL_CMD(CSR_HW_REV);
- IWL_CMD(CSR_EEPROM_REG);
- IWL_CMD(CSR_EEPROM_GP);
- IWL_CMD(CSR_OTP_GP_REG);
- IWL_CMD(CSR_GIO_REG);
- IWL_CMD(CSR_GP_UCODE_REG);
- IWL_CMD(CSR_GP_DRIVER_REG);
- IWL_CMD(CSR_UCODE_DRV_GP1);
- IWL_CMD(CSR_UCODE_DRV_GP2);
- IWL_CMD(CSR_LED_REG);
- IWL_CMD(CSR_DRAM_INT_TBL_REG);
- IWL_CMD(CSR_GIO_CHICKEN_BITS);
- IWL_CMD(CSR_ANA_PLL_CFG);
- IWL_CMD(CSR_HW_REV_WA_REG);
- IWL_CMD(CSR_DBG_HPET_MEM_REG);
- default:
- return "UNKNOWN";
-
- }
-}
-
-void iwl_dump_csr(struct iwl_priv *priv)
-{
- int i;
- u32 csr_tbl[] = {
- CSR_HW_IF_CONFIG_REG,
- CSR_INT_COALESCING,
- CSR_INT,
- CSR_INT_MASK,
- CSR_FH_INT_STATUS,
- CSR_GPIO_IN,
- CSR_RESET,
- CSR_GP_CNTRL,
- CSR_HW_REV,
- CSR_EEPROM_REG,
- CSR_EEPROM_GP,
- CSR_OTP_GP_REG,
- CSR_GIO_REG,
- CSR_GP_UCODE_REG,
- CSR_GP_DRIVER_REG,
- CSR_UCODE_DRV_GP1,
- CSR_UCODE_DRV_GP2,
- CSR_LED_REG,
- CSR_DRAM_INT_TBL_REG,
- CSR_GIO_CHICKEN_BITS,
- CSR_ANA_PLL_CFG,
- CSR_HW_REV_WA_REG,
- CSR_DBG_HPET_MEM_REG
- };
- IWL_ERR(priv, "CSR values:\n");
- IWL_ERR(priv, "(2nd byte of CSR_INT_COALESCING is "
- "CSR_INT_PERIODIC_REG)\n");
- for (i = 0; i < ARRAY_SIZE(csr_tbl); i++) {
- IWL_ERR(priv, " %25s: 0X%08x\n",
- get_csr_string(csr_tbl[i]),
- iwl_read32(priv, csr_tbl[i]));
- }
-}
-EXPORT_SYMBOL(iwl_dump_csr);
-
-static const char *get_fh_string(int cmd)
-{
- switch (cmd) {
- IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG);
- IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG);
- IWL_CMD(FH_RSCSR_CHNL0_WPTR);
- IWL_CMD(FH_MEM_RCSR_CHNL0_CONFIG_REG);
- IWL_CMD(FH_MEM_RSSR_SHARED_CTRL_REG);
- IWL_CMD(FH_MEM_RSSR_RX_STATUS_REG);
- IWL_CMD(FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV);
- IWL_CMD(FH_TSSR_TX_STATUS_REG);
- IWL_CMD(FH_TSSR_TX_ERROR_REG);
- default:
- return "UNKNOWN";
-
- }
-}
-
-int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display)
-{
- int i;
-#ifdef CONFIG_IWLWIFI_DEBUG
- int pos = 0;
- size_t bufsz = 0;
-#endif
- u32 fh_tbl[] = {
- FH_RSCSR_CHNL0_STTS_WPTR_REG,
- FH_RSCSR_CHNL0_RBDCB_BASE_REG,
- FH_RSCSR_CHNL0_WPTR,
- FH_MEM_RCSR_CHNL0_CONFIG_REG,
- FH_MEM_RSSR_SHARED_CTRL_REG,
- FH_MEM_RSSR_RX_STATUS_REG,
- FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV,
- FH_TSSR_TX_STATUS_REG,
- FH_TSSR_TX_ERROR_REG
- };
-#ifdef CONFIG_IWLWIFI_DEBUG
- if (display) {
- bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40;
- *buf = kmalloc(bufsz, GFP_KERNEL);
- if (!*buf)
- return -ENOMEM;
- pos += scnprintf(*buf + pos, bufsz - pos,
- "FH register values:\n");
- for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) {
- pos += scnprintf(*buf + pos, bufsz - pos,
- " %34s: 0X%08x\n",
- get_fh_string(fh_tbl[i]),
- iwl_read_direct32(priv, fh_tbl[i]));
- }
- return pos;
- }
-#endif
- IWL_ERR(priv, "FH register values:\n");
- for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) {
- IWL_ERR(priv, " %34s: 0X%08x\n",
- get_fh_string(fh_tbl[i]),
- iwl_read_direct32(priv, fh_tbl[i]));
- }
- return 0;
-}
-EXPORT_SYMBOL(iwl_dump_fh);
-
static void iwl_force_rf_reset(struct iwl_priv *priv)
{
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
- if (!iwl_is_associated(priv)) {
+ if (!iwl_is_any_associated(priv)) {
IWL_DEBUG_SCAN(priv, "force reset rejected: not associated\n");
return;
}
@@ -2613,11 +2380,6 @@ int iwl_force_reset(struct iwl_priv *priv, int mode, bool external)
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return -EINVAL;
- if (test_bit(STATUS_SCANNING, &priv->status)) {
- IWL_DEBUG_INFO(priv, "scan in progress.\n");
- return -EINVAL;
- }
-
if (mode >= IWL_MAX_FORCE_RESET) {
IWL_DEBUG_INFO(priv, "invalid reset request.\n");
return -EINVAL;
@@ -2668,7 +2430,6 @@ int iwl_force_reset(struct iwl_priv *priv, int mode, bool external)
}
return 0;
}
-EXPORT_SYMBOL(iwl_force_reset);
/**
* iwl_bg_monitor_recover - Timer callback to check for stuck queue and recover
@@ -2704,29 +2465,31 @@ static int iwl_check_stuck_queue(struct iwl_priv *priv, int cnt)
txq = &priv->txq[cnt];
q = &txq->q;
/* queue is empty, skip */
- if (q->read_ptr != q->write_ptr) {
- if (q->read_ptr == q->last_read_ptr) {
- /* a queue has not been read from last time */
- if (q->repeat_same_read_ptr > MAX_REPEAT) {
- IWL_ERR(priv,
- "queue %d stuck %d time. Fw reload.\n",
- q->id, q->repeat_same_read_ptr);
- q->repeat_same_read_ptr = 0;
- iwl_force_reset(priv, IWL_FW_RESET, false);
- } else {
- q->repeat_same_read_ptr++;
- IWL_DEBUG_RADIO(priv,
- "queue %d, not read %d time\n",
- q->id,
- q->repeat_same_read_ptr);
- mod_timer(&priv->monitor_recover, jiffies +
- msecs_to_jiffies(IWL_ONE_HUNDRED_MSECS));
- }
- return 1;
- } else {
- q->last_read_ptr = q->read_ptr;
+ if (q->read_ptr == q->write_ptr)
+ return 0;
+
+ if (q->read_ptr == q->last_read_ptr) {
+ /* a queue has not been read from last time */
+ if (q->repeat_same_read_ptr > MAX_REPEAT) {
+ IWL_ERR(priv,
+ "queue %d stuck %d time. Fw reload.\n",
+ q->id, q->repeat_same_read_ptr);
q->repeat_same_read_ptr = 0;
+ iwl_force_reset(priv, IWL_FW_RESET, false);
+ } else {
+ q->repeat_same_read_ptr++;
+ IWL_DEBUG_RADIO(priv,
+ "queue %d, not read %d time\n",
+ q->id,
+ q->repeat_same_read_ptr);
+ mod_timer(&priv->monitor_recover,
+ jiffies + msecs_to_jiffies(
+ IWL_ONE_HUNDRED_MSECS));
+ return 1;
}
+ } else {
+ q->last_read_ptr = q->read_ptr;
+ q->repeat_same_read_ptr = 0;
}
return 0;
}
@@ -2740,25 +2503,27 @@ void iwl_bg_monitor_recover(unsigned long data)
return;
/* monitor and check for stuck cmd queue */
- if (iwl_check_stuck_queue(priv, IWL_CMD_QUEUE_NUM))
+ if (iwl_check_stuck_queue(priv, priv->cmd_queue))
return;
/* monitor and check for other stuck queues */
- if (iwl_is_associated(priv)) {
+ if (iwl_is_any_associated(priv)) {
for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
/* skip as we already checked the command queue */
- if (cnt == IWL_CMD_QUEUE_NUM)
+ if (cnt == priv->cmd_queue)
continue;
if (iwl_check_stuck_queue(priv, cnt))
return;
}
}
- /*
- * Reschedule the timer to occur in
- * priv->cfg->monitor_recover_period
- */
- mod_timer(&priv->monitor_recover,
- jiffies + msecs_to_jiffies(priv->cfg->monitor_recover_period));
+ if (priv->cfg->base_params->monitor_recover_period) {
+ /*
+ * Reschedule the timer to occur in
+ * priv->cfg->base_params->monitor_recover_period
+ */
+ mod_timer(&priv->monitor_recover, jiffies + msecs_to_jiffies(
+ priv->cfg->base_params->monitor_recover_period));
+ }
}
EXPORT_SYMBOL(iwl_bg_monitor_recover);
@@ -2830,7 +2595,7 @@ int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state)
* it will not call apm_ops.stop() to stop the DMA operation.
* Calling apm_ops.stop here to make sure we stop the DMA.
*/
- priv->cfg->ops->lib->apm_ops.stop(priv);
+ iwl_apm_stop(priv);
pci_save_state(pdev);
pci_disable_device(pdev);
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 5e6ee3da6bbf..64527def059f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -88,11 +88,13 @@ struct iwl_cmd;
#define IWL_CMD(x) case x: return #x
struct iwl_hcmd_ops {
- int (*rxon_assoc)(struct iwl_priv *priv);
- int (*commit_rxon)(struct iwl_priv *priv);
- void (*set_rxon_chain)(struct iwl_priv *priv);
+ int (*rxon_assoc)(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
+ int (*commit_rxon)(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
+ void (*set_rxon_chain)(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx);
int (*set_tx_ant)(struct iwl_priv *priv, u8 valid_tx_ant);
void (*send_bt_config)(struct iwl_priv *priv);
+ int (*set_pan_params)(struct iwl_priv *priv);
};
struct iwl_hcmd_utils_ops {
@@ -109,14 +111,13 @@ struct iwl_hcmd_utils_ops {
__le16 fc, __le32 *tx_flags);
int (*calc_rssi)(struct iwl_priv *priv,
struct iwl_rx_phy_res *rx_resp);
- void (*request_scan)(struct iwl_priv *priv, struct ieee80211_vif *vif);
+ int (*request_scan)(struct iwl_priv *priv, struct ieee80211_vif *vif);
+ void (*post_scan)(struct iwl_priv *priv);
};
struct iwl_apm_ops {
int (*init)(struct iwl_priv *priv);
- void (*stop)(struct iwl_priv *priv);
void (*config)(struct iwl_priv *priv);
- int (*set_pwr_src)(struct iwl_priv *priv, enum iwl_pwr_src src);
};
struct iwl_debugfs_ops {
@@ -128,12 +129,18 @@ struct iwl_debugfs_ops {
size_t count, loff_t *ppos);
ssize_t (*bt_stats_read)(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos);
+ ssize_t (*reply_tx_error)(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos);
};
struct iwl_temp_ops {
void (*temperature)(struct iwl_priv *priv);
- void (*set_ct_kill)(struct iwl_priv *priv);
- void (*set_calib_version)(struct iwl_priv *priv);
+};
+
+struct iwl_tt_ops {
+ bool (*lower_power_detection)(struct iwl_priv *priv);
+ u8 (*tt_power_mode)(struct iwl_priv *priv);
+ bool (*ct_kill_check)(struct iwl_priv *priv);
};
struct iwl_lib_ops {
@@ -199,7 +206,7 @@ struct iwl_lib_ops {
/* station management */
int (*manage_ibss_station)(struct iwl_priv *priv,
struct ieee80211_vif *vif, bool add);
- int (*update_bcast_station)(struct iwl_priv *priv);
+ int (*update_bcast_stations)(struct iwl_priv *priv);
/* recover from tx queue stall */
void (*recover_from_tx_stall)(unsigned long data);
/* check for plcp health */
@@ -212,6 +219,9 @@ struct iwl_lib_ops {
void (*dev_txfifo_flush)(struct iwl_priv *priv, u16 flush_control);
struct iwl_debugfs_ops debugfs_ops;
+
+ /* thermal throttling */
+ struct iwl_tt_ops tt_ops;
};
struct iwl_led_ops {
@@ -220,11 +230,17 @@ struct iwl_led_ops {
int (*off)(struct iwl_priv *priv);
};
+/* NIC specific ops */
+struct iwl_nic_ops {
+ void (*additional_nic_config)(struct iwl_priv *priv);
+};
+
struct iwl_ops {
const struct iwl_lib_ops *lib;
const struct iwl_hcmd_ops *hcmd;
const struct iwl_hcmd_utils_ops *utils;
const struct iwl_led_ops *led;
+ const struct iwl_nic_ops *nic;
};
struct iwl_mod_params {
@@ -237,20 +253,12 @@ struct iwl_mod_params {
int restart_fw; /* def: 1 = restart firmware */
};
-/**
- * struct iwl_cfg
- * @fw_name_pre: Firmware filename prefix. The api version and extension
- * (.ucode) will be added to filename before loading from disk. The
- * filename is constructed as fw_name_pre<api>.ucode.
- * @ucode_api_max: Highest version of uCode API supported by driver.
- * @ucode_api_min: Lowest version of uCode API supported by driver.
- * @pa_type: used by 6000 series only to identify the type of Power Amplifier
+/*
* @max_ll_items: max number of OTP blocks
* @shadow_ram_support: shadow support for OTP memory
* @led_compensation: compensate on the led on/off time per HW according
* to the deviation to achieve the desired led frequency.
* The detail algorithm is described in iwl-led.c
- * @use_rts_for_aggregation: use rts/cts protection for HT traffic
* @chain_noise_num_beacons: number of beacons used to compute chain noise
* @adv_thermal_throttle: support advance thermal throttle
* @support_ct_kill_exit: support ct kill exit condition
@@ -268,6 +276,73 @@ struct iwl_mod_params {
* sensitivity calibration operation
* @chain_noise_calib_by_driver: driver has the capability to perform
* chain noise calibration operation
+*/
+struct iwl_base_params {
+ int eeprom_size;
+ int num_of_queues; /* def: HW dependent */
+ int num_of_ampdu_queues;/* def: HW dependent */
+ /* for iwl_apm_init() */
+ u32 pll_cfg_val;
+ bool set_l0s;
+ bool use_bsm;
+
+ bool use_isr_legacy;
+ const u16 max_ll_items;
+ const bool shadow_ram_support;
+ u16 led_compensation;
+ const bool broken_powersave;
+ int chain_noise_num_beacons;
+ const bool supports_idle;
+ bool adv_thermal_throttle;
+ bool support_ct_kill_exit;
+ const bool support_wimax_coexist;
+ u8 plcp_delta_threshold;
+ s32 chain_noise_scale;
+ /* timer period for monitor the driver queues */
+ u32 monitor_recover_period;
+ bool temperature_kelvin;
+ u32 max_event_log_size;
+ const bool tx_power_by_driver;
+ const bool ucode_tracing;
+ const bool sensitivity_calib_by_driver;
+ const bool chain_noise_calib_by_driver;
+};
+/*
+ * @advanced_bt_coexist: support advanced bt coexist
+ * @bt_init_traffic_load: specify initial bt traffic load
+ * @bt_prio_boost: default bt priority boost value
+ * @bt_statistics: use BT version of statistics notification
+ * @agg_time_limit: maximum number of uSec in aggregation
+ * @ampdu_factor: Maximum A-MPDU length factor
+ * @ampdu_density: Minimum A-MPDU spacing
+*/
+struct iwl_bt_params {
+ bool advanced_bt_coexist;
+ u8 bt_init_traffic_load;
+ u8 bt_prio_boost;
+ const bool bt_statistics;
+ u16 agg_time_limit;
+ u8 ampdu_factor;
+ u8 ampdu_density;
+};
+/*
+ * @use_rts_for_aggregation: use rts/cts protection for HT traffic
+*/
+struct iwl_ht_params {
+ const bool ht_greenfield_support; /* if used set to true */
+ bool use_rts_for_aggregation;
+};
+
+/**
+ * struct iwl_cfg
+ * @fw_name_pre: Firmware filename prefix. The api version and extension
+ * (.ucode) will be added to filename before loading from disk. The
+ * filename is constructed as fw_name_pre<api>.ucode.
+ * @ucode_api_max: Highest version of uCode API supported by driver.
+ * @ucode_api_min: Lowest version of uCode API supported by driver.
+ * @pa_type: used by 6000 series only to identify the type of Power Amplifier
+ * @need_dc_calib: need to perform init dc calibration
+ * @need_temp_offset_calib: need to perform temperature offset calibration
* @scan_antennas: available antenna for scan operation
*
* We enable the driver to be backward compatible wrt API version. The
@@ -279,9 +354,9 @@ struct iwl_mod_params {
*
* For example,
* if (IWL_UCODE_API(priv->ucode_ver) >= 2) {
- * Driver interacts with Firmware API version >= 2.
+ * Driver interacts with Firmware API version >= 2.
* } else {
- * Driver interacts with Firmware API version 1.
+ * Driver interacts with Firmware API version 1.
* }
*
* The ideal usage of this infrastructure is to treat a new ucode API
@@ -292,53 +367,29 @@ struct iwl_mod_params {
*
*/
struct iwl_cfg {
+ /* params specific to an individual device within a device family */
const char *name;
const char *fw_name_pre;
const unsigned int ucode_api_max;
const unsigned int ucode_api_min;
+ u8 valid_tx_ant;
+ u8 valid_rx_ant;
unsigned int sku;
- int eeprom_size;
u16 eeprom_ver;
u16 eeprom_calib_ver;
- int num_of_queues; /* def: HW dependent */
- int num_of_ampdu_queues;/* def: HW dependent */
const struct iwl_ops *ops;
+ /* module based parameters which can be set from modprobe cmd */
const struct iwl_mod_params *mod_params;
- u8 valid_tx_ant;
- u8 valid_rx_ant;
-
- /* for iwl_apm_init() */
- u32 pll_cfg_val;
- bool set_l0s;
- bool use_bsm;
-
- bool use_isr_legacy;
- enum iwl_pa_type pa_type;
- const u16 max_ll_items;
- const bool shadow_ram_support;
- const bool ht_greenfield_support;
- u16 led_compensation;
- const bool broken_powersave;
- bool use_rts_for_aggregation;
- int chain_noise_num_beacons;
- const bool supports_idle;
- bool adv_thermal_throttle;
- bool support_ct_kill_exit;
- const bool support_wimax_coexist;
- u8 plcp_delta_threshold;
- s32 chain_noise_scale;
- /* timer period for monitor the driver queues */
- u32 monitor_recover_period;
- bool temperature_kelvin;
- u32 max_event_log_size;
- const bool tx_power_by_driver;
- const bool ucode_tracing;
- const bool sensitivity_calib_by_driver;
- const bool chain_noise_calib_by_driver;
+ /* params not likely to change within a device family */
+ struct iwl_base_params *base_params;
+ /* params likely to change within a device family */
+ struct iwl_ht_params *ht_params;
+ struct iwl_bt_params *bt_params;
+ enum iwl_pa_type pa_type; /* if used set to IWL_PA_SYSTEM */
+ const bool need_dc_calib; /* if used set to true */
+ const bool need_temp_offset_calib; /* if used set to true */
u8 scan_rx_antennas[IEEE80211_NUM_BANDS];
u8 scan_tx_antennas[IEEE80211_NUM_BANDS];
- const bool need_dc_calib;
- const bool bt_statistics;
};
/***************************
@@ -347,38 +398,38 @@ struct iwl_cfg {
struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg,
struct ieee80211_ops *hw_ops);
-void iwl_hw_detect(struct iwl_priv *priv);
-void iwl_activate_qos(struct iwl_priv *priv);
int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
const struct ieee80211_tx_queue_params *params);
-void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt);
-int iwl_check_rxon_cmd(struct iwl_priv *priv);
-int iwl_full_rxon_required(struct iwl_priv *priv);
-void iwl_set_rxon_chain(struct iwl_priv *priv);
-int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch);
+int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw);
+void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
+ int hw_decrypt);
+int iwl_check_rxon_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
+int iwl_full_rxon_required(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
+int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch,
+ struct iwl_rxon_context *ctx);
void iwl_set_flags_for_band(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx,
enum ieee80211_band band,
struct ieee80211_vif *vif);
u8 iwl_get_single_channel_number(struct iwl_priv *priv,
enum ieee80211_band band);
void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf);
-u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
- struct ieee80211_sta_ht_cap *sta_ht_inf);
+bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx,
+ struct ieee80211_sta_ht_cap *ht_cap);
void iwl_connection_init_rx_config(struct iwl_priv *priv,
- struct ieee80211_vif *vif);
+ struct iwl_rxon_context *ctx);
void iwl_set_rate(struct iwl_priv *priv);
int iwl_set_decrypted_flag(struct iwl_priv *priv,
struct ieee80211_hdr *hdr,
u32 decrypt_res,
struct ieee80211_rx_status *stats);
void iwl_irq_handle_error(struct iwl_priv *priv);
-int iwl_set_hw_params(struct iwl_priv *priv);
void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif);
void iwl_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf,
u32 changes);
-int iwl_commit_rxon(struct iwl_priv *priv);
int iwl_mac_add_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif);
void iwl_mac_remove_interface(struct ieee80211_hw *hw,
@@ -455,7 +506,6 @@ void iwl_rx_reply_error(struct iwl_priv *priv,
******************************************************/
void iwl_cmd_queue_free(struct iwl_priv *priv);
int iwl_rx_queue_alloc(struct iwl_priv *priv);
-void iwl_rx_handle(struct iwl_priv *priv);
void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv,
struct iwl_rx_queue *q);
int iwl_rx_queue_space(const struct iwl_rx_queue *q);
@@ -473,12 +523,6 @@ void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
/*****************************************************
* TX
******************************************************/
-void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq);
-int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv,
- struct iwl_tx_queue *txq,
- dma_addr_t addr, u16 len, u8 reset, u8 pad);
-int iwl_hw_tx_queue_init(struct iwl_priv *priv,
- struct iwl_tx_queue *txq);
void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq);
int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
int slots_num, u32 txq_id);
@@ -494,29 +538,8 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force);
* Rate
******************************************************************************/
-int iwl_hwrate_to_plcp_idx(u32 rate_n_flags);
-
-u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv);
-
-u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx, u8 valid);
-
-static inline u32 iwl_ant_idx_to_flags(u8 ant_idx)
-{
- return BIT(ant_idx) << RATE_MCS_ANT_POS;
-}
-
-static inline u8 iwl_hw_get_rate(__le32 rate_n_flags)
-{
- return le32_to_cpu(rate_n_flags) & 0xFF;
-}
-static inline u32 iwl_hw_get_rate_n_flags(__le32 rate_n_flags)
-{
- return le32_to_cpu(rate_n_flags) & 0x1FFFF;
-}
-static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags)
-{
- return cpu_to_le32(flags|(u32)rate);
-}
+u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx);
/*******************************************************************************
* Scanning
@@ -524,10 +547,10 @@ static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags)
void iwl_init_scan_params(struct iwl_priv *priv);
int iwl_scan_cancel(struct iwl_priv *priv);
int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms);
+void iwl_force_scan_end(struct iwl_priv *priv);
int iwl_mac_hw_scan(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct cfg80211_scan_request *req);
-void iwl_bg_start_internal_scan(struct work_struct *work);
void iwl_internal_short_hw_scan(struct iwl_priv *priv);
int iwl_force_reset(struct iwl_priv *priv, int mode, bool external);
u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
@@ -539,10 +562,8 @@ u16 iwl_get_active_dwell_time(struct iwl_priv *priv,
u16 iwl_get_passive_dwell_time(struct iwl_priv *priv,
enum ieee80211_band band,
struct ieee80211_vif *vif);
-void iwl_bg_scan_check(struct work_struct *data);
-void iwl_bg_abort_scan(struct work_struct *work);
-void iwl_bg_scan_completed(struct work_struct *work);
void iwl_setup_scan_deferred_work(struct iwl_priv *priv);
+void iwl_cancel_scan_deferred_work(struct iwl_priv *priv);
/* For faster active scanning, scan will move to the next channel if fewer than
* PLCP_QUIET_THRESH packets are heard on this channel within
@@ -555,13 +576,6 @@ void iwl_setup_scan_deferred_work(struct iwl_priv *priv);
#define IWL_SCAN_CHECK_WATCHDOG (HZ * 7)
-/*******************************************************************************
- * Calibrations - implemented in iwl-calib.c
- ******************************************************************************/
-int iwl_send_calib_results(struct iwl_priv *priv);
-int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len);
-void iwl_calib_free_results(struct iwl_priv *priv);
-
/*****************************************************
* S e n d i n g H o s t C o m m a n d s *
*****************************************************/
@@ -580,8 +594,6 @@ int iwl_send_cmd_pdu_async(struct iwl_priv *priv, u8 id, u16 len,
int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
-int iwl_send_card_state(struct iwl_priv *priv, u32 flags,
- u8 meta_flag);
/*****************************************************
* PCI *
@@ -613,12 +625,12 @@ int iwl_pci_resume(struct pci_dev *pdev);
void iwl_dump_nic_error_log(struct iwl_priv *priv);
int iwl_dump_nic_event_log(struct iwl_priv *priv,
bool full_log, char **buf, bool display);
-void iwl_dump_csr(struct iwl_priv *priv);
-int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display);
#ifdef CONFIG_IWLWIFI_DEBUG
-void iwl_print_rx_config_cmd(struct iwl_priv *priv);
+void iwl_print_rx_config_cmd(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx);
#else
-static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv)
+static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx)
{
}
#endif
@@ -695,23 +707,22 @@ static inline int iwl_is_ready_rf(struct iwl_priv *priv)
return iwl_is_ready(priv);
}
-extern void iwl_rf_kill_ct_config(struct iwl_priv *priv);
extern void iwl_send_bt_config(struct iwl_priv *priv);
extern int iwl_send_statistics_request(struct iwl_priv *priv,
u8 flags, bool clear);
-extern int iwl_send_lq_cmd(struct iwl_priv *priv,
- struct iwl_link_quality_cmd *lq, u8 flags, bool init);
void iwl_apm_stop(struct iwl_priv *priv);
int iwl_apm_init(struct iwl_priv *priv);
-void iwl_setup_rxon_timing(struct iwl_priv *priv, struct ieee80211_vif *vif);
-static inline int iwl_send_rxon_assoc(struct iwl_priv *priv)
+int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
+static inline int iwl_send_rxon_assoc(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx)
{
- return priv->cfg->ops->hcmd->rxon_assoc(priv);
+ return priv->cfg->ops->hcmd->rxon_assoc(priv, ctx);
}
-static inline int iwlcore_commit_rxon(struct iwl_priv *priv)
+static inline int iwlcore_commit_rxon(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx)
{
- return priv->cfg->ops->hcmd->commit_rxon(priv);
+ return priv->cfg->ops->hcmd->commit_rxon(priv, ctx);
}
static inline void iwlcore_config_ap(struct iwl_priv *priv,
struct ieee80211_vif *vif)
@@ -723,4 +734,8 @@ static inline const struct ieee80211_supported_band *iwl_get_hw_mode(
{
return priv->hw->wiphy->bands[band];
}
+
+extern bool bt_coex_active;
+extern bool bt_siso_mode;
+
#endif /* __iwl_core_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h
index ecf98e7ac4ed..2aa15ab13892 100644
--- a/drivers/net/wireless/iwlwifi/iwl-csr.h
+++ b/drivers/net/wireless/iwlwifi/iwl-csr.h
@@ -371,7 +371,8 @@
#define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_3x3_HYB (0x00000000)
#define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_HYB (0x00000001)
#define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA (0x00000002)
-#define CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6 (0x00000004)
+#define CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6 (0x00000004)
+#define CSR_GP_DRIVER_REG_BIT_6050_1x2 (0x00000008)
/* GIO Chicken Bits (PCI Express bus link power management) */
#define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX (0x00800000)
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index e96a1bb12783..8fdd4efdb1d3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -39,7 +39,6 @@
#include "iwl-debug.h"
#include "iwl-core.h"
#include "iwl-io.h"
-#include "iwl-calib.h"
/* create and remove of files */
#define DEBUGFS_ADD_FILE(name, parent, mode) do { \
@@ -87,6 +86,7 @@ static int iwl_dbgfs_open_file_generic(struct inode *inode, struct file *file)
static const struct file_operations iwl_dbgfs_##name##_ops = { \
.read = iwl_dbgfs_##name##_read, \
.open = iwl_dbgfs_open_file_generic, \
+ .llseek = generic_file_llseek, \
};
#define DEBUGFS_WRITE_FILE_OPS(name) \
@@ -94,6 +94,7 @@ static const struct file_operations iwl_dbgfs_##name##_ops = { \
static const struct file_operations iwl_dbgfs_##name##_ops = { \
.write = iwl_dbgfs_##name##_write, \
.open = iwl_dbgfs_open_file_generic, \
+ .llseek = generic_file_llseek, \
};
@@ -104,6 +105,7 @@ static const struct file_operations iwl_dbgfs_##name##_ops = { \
.write = iwl_dbgfs_##name##_write, \
.read = iwl_dbgfs_##name##_read, \
.open = iwl_dbgfs_open_file_generic, \
+ .llseek = generic_file_llseek, \
};
static ssize_t iwl_dbgfs_tx_statistics_read(struct file *file,
@@ -356,7 +358,7 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file,
const u8 *ptr;
char *buf;
u16 eeprom_ver;
- size_t eeprom_len = priv->cfg->eeprom_size;
+ size_t eeprom_len = priv->cfg->base_params->eeprom_size;
buf_size = 4 * eeprom_len + 256;
if (eeprom_len % 16) {
@@ -467,8 +469,7 @@ static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf,
for (i = 0; i < supp_band->n_channels; i++)
pos += scnprintf(buf + pos, bufsz - pos,
"%d: %ddBm: BSS%s%s, %s.\n",
- ieee80211_frequency_to_channel(
- channels[i].center_freq),
+ channels[i].hw_value,
channels[i].max_power,
channels[i].flags & IEEE80211_CHAN_RADAR ?
" (IEEE 802.11h required)" : "",
@@ -491,8 +492,7 @@ static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf,
for (i = 0; i < supp_band->n_channels; i++)
pos += scnprintf(buf + pos, bufsz - pos,
"%d: %ddBm: BSS%s%s, %s.\n",
- ieee80211_frequency_to_channel(
- channels[i].center_freq),
+ channels[i].hw_value,
channels[i].max_power,
channels[i].flags & IEEE80211_CHAN_RADAR ?
" (IEEE 802.11h required)" : "",
@@ -577,10 +577,10 @@ static ssize_t iwl_dbgfs_interrupt_read(struct file *file,
priv->isr_stats.hw);
pos += scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n",
priv->isr_stats.sw);
- if (priv->isr_stats.sw > 0) {
+ if (priv->isr_stats.sw || priv->isr_stats.hw) {
pos += scnprintf(buf + pos, bufsz - pos,
"\tLast Restarting Code: 0x%X\n",
- priv->isr_stats.sw_err);
+ priv->isr_stats.err_code);
}
#ifdef CONFIG_IWLWIFI_DEBUG
pos += scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n",
@@ -645,19 +645,25 @@ static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct iwl_priv *priv = file->private_data;
+ struct iwl_rxon_context *ctx;
int pos = 0, i;
- char buf[256];
+ char buf[256 * NUM_IWL_RXON_CTX];
const size_t bufsz = sizeof(buf);
- for (i = 0; i < AC_NUM; i++) {
- pos += scnprintf(buf + pos, bufsz - pos,
- "\tcw_min\tcw_max\taifsn\ttxop\n");
- pos += scnprintf(buf + pos, bufsz - pos,
+ for_each_context(priv, ctx) {
+ pos += scnprintf(buf + pos, bufsz - pos, "context %d:\n",
+ ctx->ctxid);
+ for (i = 0; i < AC_NUM; i++) {
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "\tcw_min\tcw_max\taifsn\ttxop\n");
+ pos += scnprintf(buf + pos, bufsz - pos,
"AC[%d]\t%u\t%u\t%u\t%u\n", i,
- priv->qos_data.def_qos_parm.ac[i].cw_min,
- priv->qos_data.def_qos_parm.ac[i].cw_max,
- priv->qos_data.def_qos_parm.ac[i].aifsn,
- priv->qos_data.def_qos_parm.ac[i].edca_txop);
+ ctx->qos_data.def_qos_parm.ac[i].cw_min,
+ ctx->qos_data.def_qos_parm.ac[i].cw_max,
+ ctx->qos_data.def_qos_parm.ac[i].aifsn,
+ ctx->qos_data.def_qos_parm.ac[i].edca_txop);
+ }
+ pos += scnprintf(buf + pos, bufsz - pos, "\n");
}
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
@@ -732,7 +738,7 @@ static ssize_t iwl_dbgfs_disable_ht40_write(struct file *file,
return -EFAULT;
if (sscanf(buf, "%d", &ht40) != 1)
return -EFAULT;
- if (!iwl_is_associated(priv))
+ if (!iwl_is_any_associated(priv))
priv->disable_ht40 = ht40 ? true : false;
else {
IWL_ERR(priv, "Sta associated with AP - "
@@ -868,7 +874,7 @@ static ssize_t iwl_dbgfs_traffic_log_read(struct file *file,
struct iwl_rx_queue *rxq = &priv->rxq;
char *buf;
int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) +
- (priv->cfg->num_of_queues * 32 * 8) + 400;
+ (priv->cfg->base_params->num_of_queues * 32 * 8) + 400;
const u8 *ptr;
ssize_t ret;
@@ -967,7 +973,8 @@ static ssize_t iwl_dbgfs_tx_queue_read(struct file *file,
int pos = 0;
int cnt;
int ret;
- const size_t bufsz = sizeof(char) * 64 * priv->cfg->num_of_queues;
+ const size_t bufsz = sizeof(char) * 64 *
+ priv->cfg->base_params->num_of_queues;
if (!priv->txq) {
IWL_ERR(priv, "txq not ready\n");
@@ -1321,7 +1328,8 @@ static ssize_t iwl_dbgfs_rxon_flags_read(struct file *file,
int len = 0;
char buf[20];
- len = sprintf(buf, "0x%04X\n", le32_to_cpu(priv->active_rxon.flags));
+ len = sprintf(buf, "0x%04X\n",
+ le32_to_cpu(priv->contexts[IWL_RXON_CTX_BSS].active.flags));
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
@@ -1334,7 +1342,7 @@ static ssize_t iwl_dbgfs_rxon_filter_flags_read(struct file *file,
char buf[20];
len = sprintf(buf, "0x%04X\n",
- le32_to_cpu(priv->active_rxon.filter_flags));
+ le32_to_cpu(priv->contexts[IWL_RXON_CTX_BSS].active.filter_flags));
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
@@ -1410,7 +1418,7 @@ static ssize_t iwl_dbgfs_plcp_delta_read(struct file *file,
const size_t bufsz = sizeof(buf);
pos += scnprintf(buf + pos, bufsz - pos, "%u\n",
- priv->cfg->plcp_delta_threshold);
+ priv->cfg->base_params->plcp_delta_threshold);
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
@@ -1432,10 +1440,10 @@ static ssize_t iwl_dbgfs_plcp_delta_write(struct file *file,
return -EINVAL;
if ((plcp < IWL_MAX_PLCP_ERR_THRESHOLD_MIN) ||
(plcp > IWL_MAX_PLCP_ERR_THRESHOLD_MAX))
- priv->cfg->plcp_delta_threshold =
+ priv->cfg->base_params->plcp_delta_threshold =
IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE;
else
- priv->cfg->plcp_delta_threshold = plcp;
+ priv->cfg->base_params->plcp_delta_threshold = plcp;
return count;
}
@@ -1529,6 +1537,135 @@ static ssize_t iwl_dbgfs_ucode_bt_stats_read(struct file *file,
user_buf, count, ppos);
}
+static ssize_t iwl_dbgfs_monitor_period_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos) {
+
+ struct iwl_priv *priv = file->private_data;
+ char buf[8];
+ int buf_size;
+ int period;
+
+ memset(buf, 0, sizeof(buf));
+ buf_size = min(count, sizeof(buf) - 1);
+ if (copy_from_user(buf, user_buf, buf_size))
+ return -EFAULT;
+ if (sscanf(buf, "%d", &period) != 1)
+ return -EINVAL;
+ if (period < 0 || period > IWL_MAX_MONITORING_PERIOD)
+ priv->cfg->base_params->monitor_recover_period =
+ IWL_DEF_MONITORING_PERIOD;
+ else
+ priv->cfg->base_params->monitor_recover_period = period;
+
+ if (priv->cfg->base_params->monitor_recover_period)
+ mod_timer(&priv->monitor_recover, jiffies + msecs_to_jiffies(
+ priv->cfg->base_params->monitor_recover_period));
+ else
+ del_timer_sync(&priv->monitor_recover);
+ return count;
+}
+
+static ssize_t iwl_dbgfs_bt_traffic_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos) {
+
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
+ int pos = 0;
+ char buf[200];
+ const size_t bufsz = sizeof(buf);
+ ssize_t ret;
+
+ pos += scnprintf(buf + pos, bufsz - pos, "BT in %s mode\n",
+ priv->bt_full_concurrent ? "full concurrency" : "3-wire");
+ pos += scnprintf(buf + pos, bufsz - pos, "BT status: %s, "
+ "last traffic notif: %d\n",
+ priv->bt_status ? "On" : "Off", priv->notif_bt_traffic_load);
+ pos += scnprintf(buf + pos, bufsz - pos, "ch_announcement: %d, "
+ "sco_active: %d, kill_ack_mask: %x, "
+ "kill_cts_mask: %x\n",
+ priv->bt_ch_announce, priv->bt_sco_active,
+ priv->kill_ack_mask, priv->kill_cts_mask);
+
+ pos += scnprintf(buf + pos, bufsz - pos, "bluetooth traffic load: ");
+ switch (priv->bt_traffic_load) {
+ case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS:
+ pos += scnprintf(buf + pos, bufsz - pos, "Continuous\n");
+ break;
+ case IWL_BT_COEX_TRAFFIC_LOAD_HIGH:
+ pos += scnprintf(buf + pos, bufsz - pos, "High\n");
+ break;
+ case IWL_BT_COEX_TRAFFIC_LOAD_LOW:
+ pos += scnprintf(buf + pos, bufsz - pos, "Low\n");
+ break;
+ case IWL_BT_COEX_TRAFFIC_LOAD_NONE:
+ default:
+ pos += scnprintf(buf + pos, bufsz - pos, "None\n");
+ break;
+ }
+
+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+ return ret;
+}
+
+static ssize_t iwl_dbgfs_protection_mode_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
+
+ int pos = 0;
+ char buf[40];
+ const size_t bufsz = sizeof(buf);
+
+ if (priv->cfg->ht_params)
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "use %s for aggregation\n",
+ (priv->cfg->ht_params->use_rts_for_aggregation) ?
+ "rts/cts" : "cts-to-self");
+ else
+ pos += scnprintf(buf + pos, bufsz - pos, "N/A");
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
+static ssize_t iwl_dbgfs_protection_mode_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos) {
+
+ struct iwl_priv *priv = file->private_data;
+ char buf[8];
+ int buf_size;
+ int rts;
+
+ if (!priv->cfg->ht_params)
+ return -EINVAL;
+
+ memset(buf, 0, sizeof(buf));
+ buf_size = min(count, sizeof(buf) - 1);
+ if (copy_from_user(buf, user_buf, buf_size))
+ return -EFAULT;
+ if (sscanf(buf, "%d", &rts) != 1)
+ return -EINVAL;
+ if (rts)
+ priv->cfg->ht_params->use_rts_for_aggregation = true;
+ else
+ priv->cfg->ht_params->use_rts_for_aggregation = false;
+ return count;
+}
+
+static ssize_t iwl_dbgfs_reply_tx_error_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_priv *priv = file->private_data;
+
+ if (priv->cfg->ops->lib->debugfs_ops.reply_tx_error)
+ return priv->cfg->ops->lib->debugfs_ops.reply_tx_error(
+ file, user_buf, count, ppos);
+ else
+ return -ENODATA;
+}
DEBUGFS_READ_FILE_OPS(rx_statistics);
DEBUGFS_READ_FILE_OPS(tx_statistics);
DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
@@ -1552,6 +1689,10 @@ DEBUGFS_READ_FILE_OPS(rxon_flags);
DEBUGFS_READ_FILE_OPS(rxon_filter_flags);
DEBUGFS_WRITE_FILE_OPS(txfifo_flush);
DEBUGFS_READ_FILE_OPS(ucode_bt_stats);
+DEBUGFS_WRITE_FILE_OPS(monitor_period);
+DEBUGFS_READ_FILE_OPS(bt_traffic);
+DEBUGFS_READ_WRITE_FILE_OPS(protection_mode);
+DEBUGFS_READ_FILE_OPS(reply_tx_error);
/*
* Create the debugfs files and directories
@@ -1587,7 +1728,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR);
DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR);
DEBUGFS_ADD_FILE(led, dir_data, S_IRUSR);
- if (!priv->cfg->broken_powersave) {
+ if (!priv->cfg->base_params->broken_powersave) {
DEBUGFS_ADD_FILE(sleep_level_override, dir_data,
S_IWUSR | S_IRUSR);
DEBUGFS_ADD_FILE(current_sleep_command, dir_data, S_IRUSR);
@@ -1612,24 +1753,29 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR);
if (priv->cfg->ops->lib->dev_txfifo_flush)
DEBUGFS_ADD_FILE(txfifo_flush, dir_debug, S_IWUSR);
+ DEBUGFS_ADD_FILE(protection_mode, dir_debug, S_IWUSR | S_IRUSR);
- if (priv->cfg->sensitivity_calib_by_driver)
+ if (priv->cfg->base_params->sensitivity_calib_by_driver)
DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR);
- if (priv->cfg->chain_noise_calib_by_driver)
+ if (priv->cfg->base_params->chain_noise_calib_by_driver)
DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR);
- if (priv->cfg->ucode_tracing)
+ if (priv->cfg->base_params->ucode_tracing)
DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR);
- if (priv->cfg->bt_statistics)
+ if (priv->cfg->bt_params && priv->cfg->bt_params->bt_statistics)
DEBUGFS_ADD_FILE(ucode_bt_stats, dir_debug, S_IRUSR);
+ DEBUGFS_ADD_FILE(reply_tx_error, dir_debug, S_IRUSR);
DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR);
DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR);
- if (priv->cfg->sensitivity_calib_by_driver)
+ DEBUGFS_ADD_FILE(monitor_period, dir_debug, S_IWUSR);
+ if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist)
+ DEBUGFS_ADD_FILE(bt_traffic, dir_debug, S_IRUSR);
+ if (priv->cfg->base_params->sensitivity_calib_by_driver)
DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf,
&priv->disable_sens_cal);
- if (priv->cfg->chain_noise_calib_by_driver)
+ if (priv->cfg->base_params->chain_noise_calib_by_driver)
DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf,
&priv->disable_chain_noise_cal);
- if (priv->cfg->tx_power_by_driver)
+ if (priv->cfg->base_params->tx_power_by_driver)
DEBUGFS_ADD_BOOL(disable_tx_power, dir_rf,
&priv->disable_tx_power_cal);
return 0;
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 2e97cd2fa98a..70e07fa48405 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -47,6 +47,7 @@
#include "iwl-led.h"
#include "iwl-power.h"
#include "iwl-agn-rs.h"
+#include "iwl-agn-tt.h"
struct iwl_tx_queue;
@@ -143,6 +144,7 @@ struct iwl_queue {
/* One for each TFD */
struct iwl_tx_info {
struct sk_buff *skb;
+ struct iwl_rxon_context *ctx;
};
/**
@@ -252,10 +254,14 @@ struct iwl_channel_info {
struct iwl3945_scan_power_info scan_pwr_info[IWL_NUM_SCAN_RATES];
};
-#define IWL_TX_FIFO_BK 0
+#define IWL_TX_FIFO_BK 0 /* shared */
#define IWL_TX_FIFO_BE 1
-#define IWL_TX_FIFO_VI 2
+#define IWL_TX_FIFO_VI 2 /* shared */
#define IWL_TX_FIFO_VO 3
+#define IWL_TX_FIFO_BK_IPAN IWL_TX_FIFO_BK
+#define IWL_TX_FIFO_BE_IPAN 4
+#define IWL_TX_FIFO_VI_IPAN IWL_TX_FIFO_VI
+#define IWL_TX_FIFO_VO_IPAN 5
#define IWL_TX_FIFO_UNUSED -1
/* Minimum number of queues. MAX_NUM is defined in hw specific files.
@@ -264,18 +270,17 @@ struct iwl_channel_info {
#define IWL_MIN_NUM_QUEUES 10
/*
- * Queue #4 is the command queue for 3945/4965/5x00/1000/6x00,
- * the driver maps it into the appropriate device FIFO for the
- * uCode.
+ * Command queue depends on iPAN support.
*/
-#define IWL_CMD_QUEUE_NUM 4
+#define IWL_DEFAULT_CMD_QUEUE_NUM 4
+#define IWL_IPAN_CMD_QUEUE_NUM 9
-/* Power management (not Tx power) structures */
-
-enum iwl_pwr_src {
- IWL_PWR_SRC_VMAIN,
- IWL_PWR_SRC_VAUX,
-};
+/*
+ * This queue number is required for proper operation
+ * because the ucode will stop/start the scheduler as
+ * required.
+ */
+#define IWL_IPAN_MCAST_QUEUE 8
#define IEEE80211_DATA_LEN 2304
#define IEEE80211_4ADDR_LEN 30
@@ -420,7 +425,7 @@ struct iwl_tid_data {
};
struct iwl_hw_key {
- enum ieee80211_key_alg alg;
+ u32 cipher;
int keylen;
u8 keyidx;
u8 key[32];
@@ -434,7 +439,13 @@ union iwl_ht_rate_supp {
};
};
-#define CFG_HT_RX_AMPDU_FACTOR_DEF (0x3)
+#define CFG_HT_RX_AMPDU_FACTOR_8K (0x0)
+#define CFG_HT_RX_AMPDU_FACTOR_16K (0x1)
+#define CFG_HT_RX_AMPDU_FACTOR_32K (0x2)
+#define CFG_HT_RX_AMPDU_FACTOR_64K (0x3)
+#define CFG_HT_RX_AMPDU_FACTOR_DEF CFG_HT_RX_AMPDU_FACTOR_64K
+#define CFG_HT_RX_AMPDU_FACTOR_MAX CFG_HT_RX_AMPDU_FACTOR_64K
+#define CFG_HT_RX_AMPDU_FACTOR_MIN CFG_HT_RX_AMPDU_FACTOR_8K
/*
* Maximal MPDU density for TX aggregation
@@ -443,19 +454,17 @@ union iwl_ht_rate_supp {
* 6 - 8us density
* 7 - 16us density
*/
+#define CFG_HT_MPDU_DENSITY_2USEC (0x4)
#define CFG_HT_MPDU_DENSITY_4USEC (0x5)
+#define CFG_HT_MPDU_DENSITY_8USEC (0x6)
+#define CFG_HT_MPDU_DENSITY_16USEC (0x7)
#define CFG_HT_MPDU_DENSITY_DEF CFG_HT_MPDU_DENSITY_4USEC
+#define CFG_HT_MPDU_DENSITY_MAX CFG_HT_MPDU_DENSITY_16USEC
+#define CFG_HT_MPDU_DENSITY_MIN (0x1)
struct iwl_ht_config {
- /* self configuration data */
- bool is_ht;
- bool is_40mhz;
bool single_chain_sufficient;
enum ieee80211_smps_mode smps; /* current smps mode */
- /* BSS related data */
- u8 extension_chan_offset;
- u8 ht_protection;
- u8 non_GF_STA_present;
};
/* QoS structures */
@@ -473,12 +482,13 @@ struct iwl_qos_info {
struct iwl_station_entry {
struct iwl_addsta_cmd sta;
struct iwl_tid_data tid[MAX_TID_COUNT];
- u8 used;
+ u8 used, ctxid;
struct iwl_hw_key keyinfo;
struct iwl_link_quality_cmd *lq;
};
struct iwl_station_priv_common {
+ struct iwl_rxon_context *ctx;
u8 sta_id;
};
@@ -507,6 +517,7 @@ struct iwl_station_priv {
* space for us to put data into.
*/
struct iwl_vif_priv {
+ struct iwl_rxon_context *ctx;
u8 ibss_bssid_sta_id;
};
@@ -564,6 +575,7 @@ enum iwl_ucode_tlv_type {
IWL_UCODE_TLV_INIT_DATA = 4,
IWL_UCODE_TLV_BOOT = 5,
IWL_UCODE_TLV_PROBE_MAX_LEN = 6, /* a u32 value */
+ IWL_UCODE_TLV_PAN = 7,
IWL_UCODE_TLV_RUNT_EVTLOG_PTR = 8,
IWL_UCODE_TLV_RUNT_EVTLOG_SIZE = 9,
IWL_UCODE_TLV_RUNT_ERRLOG_PTR = 10,
@@ -658,7 +670,6 @@ struct iwl_sensitivity_ranges {
* @rx_page_order: Rx buffer page order
* @rx_wrt_ptr_reg: FH{39}_RSCSR_CHNL0_WPTR
* @max_stations:
- * @bcast_sta_id:
* @ht40_channel: is 40MHz width possible in band 2.4
* BIT(IEEE80211_BAND_5GHZ) BIT(IEEE80211_BAND_5GHZ)
* @sw_crypto: 0 for hw, 1 for sw
@@ -666,6 +677,7 @@ struct iwl_sensitivity_ranges {
* @ct_kill_threshold: temperature threshold
* @beacon_time_tsf_bits: number of valid tsf bits for beacon time
* @calib_init_cfg: setup initial calibrations for the hw
+ * @calib_rt_cfg: setup runtime calibrations for the hw
* @struct iwl_sensitivity_ranges: range of sensitivity values
*/
struct iwl_hw_params {
@@ -682,7 +694,6 @@ struct iwl_hw_params {
u32 rx_page_order;
u32 rx_wrt_ptr_reg;
u8 max_stations;
- u8 bcast_sta_id;
u8 ht40_channel;
u8 max_beacon_itrvl; /* in 1024 ms */
u32 max_inst_size;
@@ -693,6 +704,7 @@ struct iwl_hw_params {
/* for 1000, 6000 series and up */
u16 beacon_time_tsf_bits;
u32 calib_init_cfg;
+ u32 calib_rt_cfg;
const struct iwl_sensitivity_ranges *sens;
};
@@ -713,7 +725,6 @@ struct iwl_hw_params {
*
****************************************************************************/
extern void iwl_update_chain_flags(struct iwl_priv *priv);
-extern int iwl_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src);
extern const u8 iwl_bcast_addr[ETH_ALEN];
extern int iwl_rxq_stop(struct iwl_priv *priv);
extern void iwl_txq_ctx_stop(struct iwl_priv *priv);
@@ -824,6 +835,7 @@ enum iwl_calib {
IWL_CALIB_TX_IQ,
IWL_CALIB_TX_IQ_PERD,
IWL_CALIB_BASE_BAND,
+ IWL_CALIB_TEMP_OFFSET,
IWL_CALIB_MAX
};
@@ -928,7 +940,7 @@ enum iwl_pa_type {
struct isr_statistics {
u32 hw;
u32 sw;
- u32 sw_err;
+ u32 err_code;
u32 sch;
u32 alive;
u32 rfkill;
@@ -940,6 +952,50 @@ struct isr_statistics {
u32 unhandled;
};
+/* reply_tx_statistics (for _agn devices) */
+struct reply_tx_error_statistics {
+ u32 pp_delay;
+ u32 pp_few_bytes;
+ u32 pp_bt_prio;
+ u32 pp_quiet_period;
+ u32 pp_calc_ttak;
+ u32 int_crossed_retry;
+ u32 short_limit;
+ u32 long_limit;
+ u32 fifo_underrun;
+ u32 drain_flow;
+ u32 rfkill_flush;
+ u32 life_expire;
+ u32 dest_ps;
+ u32 host_abort;
+ u32 bt_retry;
+ u32 sta_invalid;
+ u32 frag_drop;
+ u32 tid_disable;
+ u32 fifo_flush;
+ u32 insuff_cf_poll;
+ u32 fail_hw_drop;
+ u32 sta_color_mismatch;
+ u32 unknown;
+};
+
+/* reply_agg_tx_statistics (for _agn devices) */
+struct reply_agg_tx_error_statistics {
+ u32 underrun;
+ u32 bt_prio;
+ u32 few_bytes;
+ u32 abort;
+ u32 last_sent_ttl;
+ u32 last_sent_try;
+ u32 last_sent_bt_kill;
+ u32 scd_query;
+ u32 bad_crc32;
+ u32 response;
+ u32 dump_tx;
+ u32 delay_tx;
+ u32 unknown;
+};
+
#ifdef CONFIG_IWLWIFI_DEBUGFS
/* management statistics */
enum iwl_mgmt_stats {
@@ -1052,7 +1108,10 @@ struct iwl_event_log {
#define IWL_DEF_MONITORING_PERIOD (1000)
#define IWL_LONG_MONITORING_PERIOD (5000)
#define IWL_ONE_HUNDRED_MSECS (100)
-#define IWL_SIXTY_SECS (60000)
+#define IWL_MAX_MONITORING_PERIOD (60000)
+
+/* BT Antenna Coupling Threshold (dB) */
+#define IWL_BT_ANTENNA_COUPLING_THRESHOLD (35)
enum iwl_reset {
IWL_RF_RESET = 0,
@@ -1082,6 +1141,64 @@ struct iwl_force_reset {
*/
#define IWLAGN_EXT_BEACON_TIME_POS 22
+enum iwl_rxon_context_id {
+ IWL_RXON_CTX_BSS,
+ IWL_RXON_CTX_PAN,
+
+ NUM_IWL_RXON_CTX
+};
+
+struct iwl_rxon_context {
+ struct ieee80211_vif *vif;
+
+ const u8 *ac_to_fifo;
+ const u8 *ac_to_queue;
+ u8 mcast_queue;
+
+ /*
+ * We could use the vif to indicate active, but we
+ * also need it to be active during disabling when
+ * we already removed the vif for type setting.
+ */
+ bool always_active, is_active;
+
+ enum iwl_rxon_context_id ctxid;
+
+ u32 interface_modes, exclusive_interface_modes;
+ u8 unused_devtype, ap_devtype, ibss_devtype, station_devtype;
+
+ /*
+ * We declare this const so it can only be
+ * changed via explicit cast within the
+ * routines that actually update the physical
+ * hardware.
+ */
+ const struct iwl_rxon_cmd active;
+ struct iwl_rxon_cmd staging;
+
+ struct iwl_rxon_time_cmd timing;
+
+ struct iwl_qos_info qos_data;
+
+ u8 bcast_sta_id, ap_sta_id;
+
+ u8 rxon_cmd, rxon_assoc_cmd, rxon_timing_cmd;
+ u8 qos_cmd;
+ u8 wep_key_cmd;
+
+ struct iwl_wep_key wep_keys[WEP_KEYS_MAX];
+ u8 key_mapping_keys;
+
+ __le32 station_flags;
+
+ struct {
+ bool non_gf_sta_present;
+ u8 protection;
+ bool enabled, is_40mhz;
+ u8 extension_chan_offset;
+ } ht;
+};
+
struct iwl_priv {
/* ieee device used by generic ieee processing code */
@@ -1110,6 +1227,9 @@ struct iwl_priv {
u32 ucode_beacon_time;
int missed_beacon_threshold;
+ /* track IBSS manager (last beacon) status */
+ u32 ibss_manager;
+
/* storing the jiffies when the plcp error rate is received */
unsigned long plcp_jiffies;
@@ -1155,6 +1275,15 @@ struct iwl_priv {
u32 hw_wa_rev;
u8 rev_id;
+ /* microcode/device supports multiple contexts */
+ u8 valid_contexts;
+
+ /* command queue number */
+ u8 cmd_queue;
+
+ /* max number of station keys */
+ u8 sta_key_max_num;
+
/* EEPROM MAC addresses */
struct mac_address addresses[2];
@@ -1172,15 +1301,7 @@ struct iwl_priv {
u8 ucode_write_complete; /* the image write is complete */
char firmware_name[25];
-
- struct iwl_rxon_time_cmd rxon_timing;
-
- /* We declare this const so it can only be
- * changed via explicit cast within the
- * routines that actually update the physical
- * hardware */
- const struct iwl_rxon_cmd active_rxon;
- struct iwl_rxon_cmd staging_rxon;
+ struct iwl_rxon_context contexts[NUM_IWL_RXON_CTX];
struct iwl_switch_rxon switch_rxon;
@@ -1242,8 +1363,6 @@ struct iwl_priv {
spinlock_t sta_lock;
int num_stations;
struct iwl_station_entry stations[IWL_STATION_COUNT];
- struct iwl_wep_key wep_keys[WEP_KEYS_MAX]; /* protected by mutex */
- u8 key_mapping_key;
unsigned long ucode_key_table;
/* queue refcounts */
@@ -1264,11 +1383,8 @@ struct iwl_priv {
enum nl80211_iftype iw_mode;
- struct sk_buff *ibss_beacon;
-
/* Last Rx'd beacon timestamp */
u64 timestamp;
- struct ieee80211_vif *vif;
union {
#if defined(CONFIG_IWL3945) || defined(CONFIG_IWL3945_MODULE)
@@ -1336,6 +1452,9 @@ struct iwl_priv {
struct iwl_notif_statistics statistics;
struct iwl_bt_notif_statistics statistics_bt;
+ /* counts reply_tx error */
+ struct reply_tx_error_statistics reply_tx_stats;
+ struct reply_agg_tx_error_statistics reply_agg_tx_stats;
#ifdef CONFIG_IWLWIFI_DEBUGFS
struct iwl_notif_statistics accum_statistics;
struct iwl_notif_statistics delta_statistics;
@@ -1348,24 +1467,45 @@ struct iwl_priv {
#endif
};
+ /* bt coex */
+ u8 bt_status;
+ u8 bt_traffic_load, notif_bt_traffic_load;
+ bool bt_ch_announce;
+ bool bt_sco_active;
+ bool bt_full_concurrent;
+ bool bt_ant_couple_ok;
+ __le32 kill_ack_mask;
+ __le32 kill_cts_mask;
+ __le16 bt_valid;
+ u16 bt_on_thresh;
+ u16 bt_duration;
+ u16 dynamic_frag_thresh;
+ u16 dynamic_agg_thresh;
+ u8 bt_ci_compliance;
+ struct work_struct bt_traffic_change_work;
+
struct iwl_hw_params hw_params;
u32 inta_mask;
- struct iwl_qos_info qos_data;
-
struct workqueue_struct *workqueue;
struct work_struct restart;
struct work_struct scan_completed;
struct work_struct rx_replenish;
struct work_struct abort_scan;
+
struct work_struct beacon_update;
+ struct iwl_rxon_context *beacon_ctx;
+ struct sk_buff *beacon_skb;
+
struct work_struct tt_work;
struct work_struct ct_enter;
struct work_struct ct_exit;
struct work_struct start_internal_scan;
struct work_struct tx_flush;
+ struct work_struct bt_full_concurrency;
+ struct work_struct bt_runtime_config;
struct tasklet_struct irq_tasklet;
@@ -1419,7 +1559,6 @@ static inline void iwl_txq_ctx_deactivate(struct iwl_priv *priv, int txq_id)
}
#ifdef CONFIG_IWLWIFI_DEBUG
-const char *iwl_get_tx_fail_reason(u32 status);
/*
* iwl_get_debug_level: Return active debug level for device
*
@@ -1435,8 +1574,6 @@ static inline u32 iwl_get_debug_level(struct iwl_priv *priv)
return iwl_debug_level;
}
#else
-static inline const char *iwl_get_tx_fail_reason(u32 status) { return ""; }
-
static inline u32 iwl_get_debug_level(struct iwl_priv *priv)
{
return iwl_debug_level;
@@ -1453,10 +1590,34 @@ static inline struct ieee80211_hdr *iwl_tx_queue_get_hdr(struct iwl_priv *priv,
return NULL;
}
+static inline struct iwl_rxon_context *
+iwl_rxon_ctx_from_vif(struct ieee80211_vif *vif)
+{
+ struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
+
+ return vif_priv->ctx;
+}
+
+#define for_each_context(priv, ctx) \
+ for (ctx = &priv->contexts[IWL_RXON_CTX_BSS]; \
+ ctx < &priv->contexts[NUM_IWL_RXON_CTX]; ctx++) \
+ if (priv->valid_contexts & BIT(ctx->ctxid))
+
+static inline int iwl_is_associated(struct iwl_priv *priv,
+ enum iwl_rxon_context_id ctxid)
+{
+ return (priv->contexts[ctxid].active.filter_flags &
+ RXON_FILTER_ASSOC_MSK) ? 1 : 0;
+}
+
+static inline int iwl_is_any_associated(struct iwl_priv *priv)
+{
+ return iwl_is_associated(priv, IWL_RXON_CTX_BSS);
+}
-static inline int iwl_is_associated(struct iwl_priv *priv)
+static inline int iwl_is_associated_ctx(struct iwl_rxon_context *ctx)
{
- return (priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0;
+ return (ctx->active.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0;
}
static inline int is_channel_valid(const struct iwl_channel_info *ch_info)
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
index a45d02e555cf..87cd10ff285d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
@@ -136,85 +136,13 @@ static const u8 iwl_eeprom_band_7[] = { /* 5.2 ht40 channel */
36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157
};
-/**
- * struct iwl_txpwr_section: eeprom section information
- * @offset: indirect address into eeprom image
- * @count: number of "struct iwl_eeprom_enhanced_txpwr" in this section
- * @band: band type for the section
- * @is_common - true: common section, false: channel section
- * @is_cck - true: cck section, false: not cck section
- * @is_ht_40 - true: all channel in the section are HT40 channel,
- * false: legacy or HT 20 MHz
- * ignore if it is common section
- * @iwl_eeprom_section_channel: channel array in the section,
- * ignore if common section
- */
-struct iwl_txpwr_section {
- u32 offset;
- u8 count;
- enum ieee80211_band band;
- bool is_common;
- bool is_cck;
- bool is_ht40;
- u8 iwl_eeprom_section_channel[EEPROM_MAX_TXPOWER_SECTION_ELEMENTS];
-};
-
-/**
- * section 1 - 3 are regulatory tx power apply to all channels based on
- * modulation: CCK, OFDM
- * Band: 2.4GHz, 5.2GHz
- * section 4 - 10 are regulatory tx power apply to specified channels
- * For example:
- * 1L - Channel 1 Legacy
- * 1HT - Channel 1 HT
- * (1,+1) - Channel 1 HT40 "_above_"
- *
- * Section 1: all CCK channels
- * Section 2: all 2.4 GHz OFDM (Legacy, HT and HT40) channels
- * Section 3: all 5.2 GHz OFDM (Legacy, HT and HT40) channels
- * Section 4: 2.4 GHz 20MHz channels: 1L, 1HT, 2L, 2HT, 10L, 10HT, 11L, 11HT
- * Section 5: 2.4 GHz 40MHz channels: (1,+1) (2,+1) (6,+1) (7,+1) (9,+1)
- * Section 6: 5.2 GHz 20MHz channels: 36L, 64L, 100L, 36HT, 64HT, 100HT
- * Section 7: 5.2 GHz 40MHz channels: (36,+1) (60,+1) (100,+1)
- * Section 8: 2.4 GHz channel: 13L, 13HT
- * Section 9: 2.4 GHz channel: 140L, 140HT
- * Section 10: 2.4 GHz 40MHz channels: (132,+1) (44,+1)
- *
- */
-static const struct iwl_txpwr_section enhinfo[] = {
- { EEPROM_LB_CCK_20_COMMON, 1, IEEE80211_BAND_2GHZ, true, true, false },
- { EEPROM_LB_OFDM_COMMON, 3, IEEE80211_BAND_2GHZ, true, false, false },
- { EEPROM_HB_OFDM_COMMON, 3, IEEE80211_BAND_5GHZ, true, false, false },
- { EEPROM_LB_OFDM_20_BAND, 8, IEEE80211_BAND_2GHZ,
- false, false, false,
- {1, 1, 2, 2, 10, 10, 11, 11 } },
- { EEPROM_LB_OFDM_HT40_BAND, 5, IEEE80211_BAND_2GHZ,
- false, false, true,
- { 1, 2, 6, 7, 9 } },
- { EEPROM_HB_OFDM_20_BAND, 6, IEEE80211_BAND_5GHZ,
- false, false, false,
- { 36, 64, 100, 36, 64, 100 } },
- { EEPROM_HB_OFDM_HT40_BAND, 3, IEEE80211_BAND_5GHZ,
- false, false, true,
- { 36, 60, 100 } },
- { EEPROM_LB_OFDM_20_CHANNEL_13, 2, IEEE80211_BAND_2GHZ,
- false, false, false,
- { 13, 13 } },
- { EEPROM_HB_OFDM_20_CHANNEL_140, 2, IEEE80211_BAND_5GHZ,
- false, false, false,
- { 140, 140 } },
- { EEPROM_HB_OFDM_HT40_BAND_1, 2, IEEE80211_BAND_5GHZ,
- false, false, true,
- { 132, 44 } },
-};
-
/******************************************************************************
*
* EEPROM related functions
*
******************************************************************************/
-int iwlcore_eeprom_verify_signature(struct iwl_priv *priv)
+static int iwl_eeprom_verify_signature(struct iwl_priv *priv)
{
u32 gp = iwl_read32(priv, CSR_EEPROM_GP) & CSR_EEPROM_GP_VALID_MSK;
int ret = 0;
@@ -246,7 +174,6 @@ int iwlcore_eeprom_verify_signature(struct iwl_priv *priv)
}
return ret;
}
-EXPORT_SYMBOL(iwlcore_eeprom_verify_signature);
static void iwl_set_otp_access(struct iwl_priv *priv, enum iwl_access_mode mode)
{
@@ -290,49 +217,9 @@ static int iwlcore_get_nvm_type(struct iwl_priv *priv)
return nvm_type;
}
-/*
- * The device's EEPROM semaphore prevents conflicts between driver and uCode
- * when accessing the EEPROM; each access is a series of pulses to/from the
- * EEPROM chip, not a single event, so even reads could conflict if they
- * weren't arbitrated by the semaphore.
- */
-int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv)
-{
- u16 count;
- int ret;
-
- for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) {
- /* Request semaphore */
- iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
- CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
-
- /* See if we got it */
- ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG,
- CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
- CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
- EEPROM_SEM_TIMEOUT);
- if (ret >= 0) {
- IWL_DEBUG_IO(priv, "Acquired semaphore after %d tries.\n",
- count+1);
- return ret;
- }
- }
-
- return ret;
-}
-EXPORT_SYMBOL(iwlcore_eeprom_acquire_semaphore);
-
-void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv)
-{
- iwl_clear_bit(priv, CSR_HW_IF_CONFIG_REG,
- CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
-
-}
-EXPORT_SYMBOL(iwlcore_eeprom_release_semaphore);
-
const u8 *iwlcore_eeprom_query_addr(const struct iwl_priv *priv, size_t offset)
{
- BUG_ON(offset >= priv->cfg->eeprom_size);
+ BUG_ON(offset >= priv->cfg->base_params->eeprom_size);
return &priv->eeprom[offset];
}
EXPORT_SYMBOL(iwlcore_eeprom_query_addr);
@@ -364,7 +251,7 @@ static int iwl_init_otp_access(struct iwl_priv *priv)
* CSR auto clock gate disable bit -
* this is only applicable for HW with OTP shadow RAM
*/
- if (priv->cfg->shadow_ram_support)
+ if (priv->cfg->base_params->shadow_ram_support)
iwl_set_bit(priv, CSR_DBG_LINK_PWR_MGMT_REG,
CSR_RESET_LINK_PWR_MGMT_DISABLED);
}
@@ -484,13 +371,27 @@ static int iwl_find_otp_image(struct iwl_priv *priv,
}
/* more in the link list, continue */
usedblocks++;
- } while (usedblocks <= priv->cfg->max_ll_items);
+ } while (usedblocks <= priv->cfg->base_params->max_ll_items);
/* OTP has no valid blocks */
IWL_DEBUG_INFO(priv, "OTP has no valid blocks\n");
return -EINVAL;
}
+const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset)
+{
+ return priv->cfg->ops->lib->eeprom_ops.query_addr(priv, offset);
+}
+EXPORT_SYMBOL(iwl_eeprom_query_addr);
+
+u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset)
+{
+ if (!priv->eeprom)
+ return 0;
+ return (u16)priv->eeprom[offset] | ((u16)priv->eeprom[offset + 1] << 8);
+}
+EXPORT_SYMBOL(iwl_eeprom_query16);
+
/**
* iwl_eeprom_init - read EEPROM contents
*
@@ -512,8 +413,8 @@ int iwl_eeprom_init(struct iwl_priv *priv)
if (priv->nvm_device_type == -ENOENT)
return -ENOENT;
/* allocate eeprom */
- IWL_DEBUG_INFO(priv, "NVM size = %d\n", priv->cfg->eeprom_size);
- sz = priv->cfg->eeprom_size;
+ sz = priv->cfg->base_params->eeprom_size;
+ IWL_DEBUG_INFO(priv, "NVM size = %d\n", sz);
priv->eeprom = kzalloc(sz, GFP_KERNEL);
if (!priv->eeprom) {
ret = -ENOMEM;
@@ -523,7 +424,7 @@ int iwl_eeprom_init(struct iwl_priv *priv)
priv->cfg->ops->lib->apm_ops.init(priv);
- ret = priv->cfg->ops->lib->eeprom_ops.verify_signature(priv);
+ ret = iwl_eeprom_verify_signature(priv);
if (ret < 0) {
IWL_ERR(priv, "EEPROM not found, EEPROM_GP=0x%08x\n", gp);
ret = -ENOENT;
@@ -554,7 +455,7 @@ int iwl_eeprom_init(struct iwl_priv *priv)
CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK |
CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK);
/* traversing the linked list if no shadow ram supported */
- if (!priv->cfg->shadow_ram_support) {
+ if (!priv->cfg->base_params->shadow_ram_support) {
if (iwl_find_otp_image(priv, &validblockaddr)) {
ret = -ENOENT;
goto done;
@@ -604,7 +505,7 @@ err:
if (ret)
iwl_eeprom_free(priv);
/* Reset chip to save power until we load uCode during "up". */
- priv->cfg->ops->lib->apm_ops.stop(priv);
+ iwl_apm_stop(priv);
alloc_err:
return ret;
}
@@ -617,53 +518,6 @@ void iwl_eeprom_free(struct iwl_priv *priv)
}
EXPORT_SYMBOL(iwl_eeprom_free);
-int iwl_eeprom_check_version(struct iwl_priv *priv)
-{
- u16 eeprom_ver;
- u16 calib_ver;
-
- eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION);
- calib_ver = priv->cfg->ops->lib->eeprom_ops.calib_version(priv);
-
- if (eeprom_ver < priv->cfg->eeprom_ver ||
- calib_ver < priv->cfg->eeprom_calib_ver)
- goto err;
-
- IWL_INFO(priv, "device EEPROM VER=0x%x, CALIB=0x%x\n",
- eeprom_ver, calib_ver);
-
- return 0;
-err:
- IWL_ERR(priv, "Unsupported (too old) EEPROM VER=0x%x < 0x%x CALIB=0x%x < 0x%x\n",
- eeprom_ver, priv->cfg->eeprom_ver,
- calib_ver, priv->cfg->eeprom_calib_ver);
- return -EINVAL;
-
-}
-EXPORT_SYMBOL(iwl_eeprom_check_version);
-
-const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset)
-{
- return priv->cfg->ops->lib->eeprom_ops.query_addr(priv, offset);
-}
-EXPORT_SYMBOL(iwl_eeprom_query_addr);
-
-u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset)
-{
- if (!priv->eeprom)
- return 0;
- return (u16)priv->eeprom[offset] | ((u16)priv->eeprom[offset + 1] << 8);
-}
-EXPORT_SYMBOL(iwl_eeprom_query16);
-
-void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac)
-{
- const u8 *addr = priv->cfg->ops->lib->eeprom_ops.query_addr(priv,
- EEPROM_MAC_ADDRESS);
- memcpy(mac, addr, ETH_ALEN);
-}
-EXPORT_SYMBOL(iwl_eeprom_get_mac);
-
static void iwl_init_band_reference(const struct iwl_priv *priv,
int eep_band, int *eeprom_ch_count,
const struct iwl_eeprom_channel **eeprom_ch_info,
@@ -722,7 +576,6 @@ static void iwl_init_band_reference(const struct iwl_priv *priv,
#define CHECK_AND_PRINT(x) ((eeprom_ch->flags & EEPROM_CHANNEL_##x) \
? # x " " : "")
-
/**
* iwl_mod_ht40_chan_info - Copy ht40 channel info into driver's priv.
*
@@ -766,205 +619,6 @@ static int iwl_mod_ht40_chan_info(struct iwl_priv *priv,
return 0;
}
-/**
- * iwl_get_max_txpower_avg - get the highest tx power from all chains.
- * find the highest tx power from all chains for the channel
- */
-static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv,
- struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
- int element, s8 *max_txpower_in_half_dbm)
-{
- s8 max_txpower_avg = 0; /* (dBm) */
-
- IWL_DEBUG_INFO(priv, "%d - "
- "chain_a: %d dB chain_b: %d dB "
- "chain_c: %d dB mimo2: %d dB mimo3: %d dB\n",
- element,
- enhanced_txpower[element].chain_a_max >> 1,
- enhanced_txpower[element].chain_b_max >> 1,
- enhanced_txpower[element].chain_c_max >> 1,
- enhanced_txpower[element].mimo2_max >> 1,
- enhanced_txpower[element].mimo3_max >> 1);
- /* Take the highest tx power from any valid chains */
- if ((priv->cfg->valid_tx_ant & ANT_A) &&
- (enhanced_txpower[element].chain_a_max > max_txpower_avg))
- max_txpower_avg = enhanced_txpower[element].chain_a_max;
- if ((priv->cfg->valid_tx_ant & ANT_B) &&
- (enhanced_txpower[element].chain_b_max > max_txpower_avg))
- max_txpower_avg = enhanced_txpower[element].chain_b_max;
- if ((priv->cfg->valid_tx_ant & ANT_C) &&
- (enhanced_txpower[element].chain_c_max > max_txpower_avg))
- max_txpower_avg = enhanced_txpower[element].chain_c_max;
- if (((priv->cfg->valid_tx_ant == ANT_AB) |
- (priv->cfg->valid_tx_ant == ANT_BC) |
- (priv->cfg->valid_tx_ant == ANT_AC)) &&
- (enhanced_txpower[element].mimo2_max > max_txpower_avg))
- max_txpower_avg = enhanced_txpower[element].mimo2_max;
- if ((priv->cfg->valid_tx_ant == ANT_ABC) &&
- (enhanced_txpower[element].mimo3_max > max_txpower_avg))
- max_txpower_avg = enhanced_txpower[element].mimo3_max;
-
- /*
- * max. tx power in EEPROM is in 1/2 dBm format
- * convert from 1/2 dBm to dBm (round-up convert)
- * but we also do not want to loss 1/2 dBm resolution which
- * will impact performance
- */
- *max_txpower_in_half_dbm = max_txpower_avg;
- return (max_txpower_avg & 0x01) + (max_txpower_avg >> 1);
-}
-
-/**
- * iwl_update_common_txpower: update channel tx power
- * update tx power per band based on EEPROM enhanced tx power info.
- */
-static s8 iwl_update_common_txpower(struct iwl_priv *priv,
- struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
- int section, int element, s8 *max_txpower_in_half_dbm)
-{
- struct iwl_channel_info *ch_info;
- int ch;
- bool is_ht40 = false;
- s8 max_txpower_avg; /* (dBm) */
-
- /* it is common section, contain all type (Legacy, HT and HT40)
- * based on the element in the section to determine
- * is it HT 40 or not
- */
- if (element == EEPROM_TXPOWER_COMMON_HT40_INDEX)
- is_ht40 = true;
- max_txpower_avg =
- iwl_get_max_txpower_avg(priv, enhanced_txpower,
- element, max_txpower_in_half_dbm);
-
- ch_info = priv->channel_info;
-
- for (ch = 0; ch < priv->channel_count; ch++) {
- /* find matching band and update tx power if needed */
- if ((ch_info->band == enhinfo[section].band) &&
- (ch_info->max_power_avg < max_txpower_avg) &&
- (!is_ht40)) {
- /* Update regulatory-based run-time data */
- ch_info->max_power_avg = ch_info->curr_txpow =
- max_txpower_avg;
- ch_info->scan_power = max_txpower_avg;
- }
- if ((ch_info->band == enhinfo[section].band) && is_ht40 &&
- (ch_info->ht40_max_power_avg < max_txpower_avg)) {
- /* Update regulatory-based run-time data */
- ch_info->ht40_max_power_avg = max_txpower_avg;
- }
- ch_info++;
- }
- return max_txpower_avg;
-}
-
-/**
- * iwl_update_channel_txpower: update channel tx power
- * update channel tx power based on EEPROM enhanced tx power info.
- */
-static s8 iwl_update_channel_txpower(struct iwl_priv *priv,
- struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
- int section, int element, s8 *max_txpower_in_half_dbm)
-{
- struct iwl_channel_info *ch_info;
- int ch;
- u8 channel;
- s8 max_txpower_avg; /* (dBm) */
-
- channel = enhinfo[section].iwl_eeprom_section_channel[element];
- max_txpower_avg =
- iwl_get_max_txpower_avg(priv, enhanced_txpower,
- element, max_txpower_in_half_dbm);
-
- ch_info = priv->channel_info;
- for (ch = 0; ch < priv->channel_count; ch++) {
- /* find matching channel and update tx power if needed */
- if (ch_info->channel == channel) {
- if ((ch_info->max_power_avg < max_txpower_avg) &&
- (!enhinfo[section].is_ht40)) {
- /* Update regulatory-based run-time data */
- ch_info->max_power_avg = max_txpower_avg;
- ch_info->curr_txpow = max_txpower_avg;
- ch_info->scan_power = max_txpower_avg;
- }
- if ((enhinfo[section].is_ht40) &&
- (ch_info->ht40_max_power_avg < max_txpower_avg)) {
- /* Update regulatory-based run-time data */
- ch_info->ht40_max_power_avg = max_txpower_avg;
- }
- break;
- }
- ch_info++;
- }
- return max_txpower_avg;
-}
-
-/**
- * iwlcore_eeprom_enhanced_txpower: process enhanced tx power info
- */
-void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv)
-{
- int eeprom_section_count = 0;
- int section, element;
- struct iwl_eeprom_enhanced_txpwr *enhanced_txpower;
- u32 offset;
- s8 max_txpower_avg; /* (dBm) */
- s8 max_txpower_in_half_dbm; /* (half-dBm) */
-
- /* Loop through all the sections
- * adjust bands and channel's max tx power
- * Set the tx_power_user_lmt to the highest power
- * supported by any channels and chains
- */
- for (section = 0; section < ARRAY_SIZE(enhinfo); section++) {
- eeprom_section_count = enhinfo[section].count;
- offset = enhinfo[section].offset;
- enhanced_txpower = (struct iwl_eeprom_enhanced_txpwr *)
- iwl_eeprom_query_addr(priv, offset);
-
- /*
- * check for valid entry -
- * different version of EEPROM might contain different set
- * of enhanced tx power table
- * always check for valid entry before process
- * the information
- */
- if (!enhanced_txpower->common || enhanced_txpower->reserved)
- continue;
-
- for (element = 0; element < eeprom_section_count; element++) {
- if (enhinfo[section].is_common)
- max_txpower_avg =
- iwl_update_common_txpower(priv,
- enhanced_txpower, section,
- element,
- &max_txpower_in_half_dbm);
- else
- max_txpower_avg =
- iwl_update_channel_txpower(priv,
- enhanced_txpower, section,
- element,
- &max_txpower_in_half_dbm);
-
- /* Update the tx_power_user_lmt to the highest power
- * supported by any channel */
- if (max_txpower_avg > priv->tx_power_user_lmt)
- priv->tx_power_user_lmt = max_txpower_avg;
-
- /*
- * Update the tx_power_lmt_in_half_dbm to
- * the highest power supported by any channel
- */
- if (max_txpower_in_half_dbm >
- priv->tx_power_lmt_in_half_dbm)
- priv->tx_power_lmt_in_half_dbm =
- max_txpower_in_half_dbm;
- }
- }
-}
-EXPORT_SYMBOL(iwlcore_eeprom_enhanced_txpower);
-
#define CHECK_AND_PRINT_I(x) ((eeprom_ch_info[ch].flags & EEPROM_CHANNEL_##x) \
? # x " " : "")
@@ -1162,4 +816,3 @@ const struct iwl_channel_info *iwl_get_channel_info(const struct iwl_priv *priv,
return NULL;
}
EXPORT_SYMBOL(iwl_get_channel_info);
-
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
index a4772aff51fe..d9b590625ae4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
@@ -493,7 +493,6 @@ struct iwl_eeprom_calib_info {
struct iwl_eeprom_ops {
const u32 regulatory_bands[7];
- int (*verify_signature) (struct iwl_priv *priv);
int (*acquire_semaphore) (struct iwl_priv *priv);
void (*release_semaphore) (struct iwl_priv *priv);
u16 (*calib_version) (struct iwl_priv *priv);
@@ -502,18 +501,13 @@ struct iwl_eeprom_ops {
};
-void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac);
int iwl_eeprom_init(struct iwl_priv *priv);
void iwl_eeprom_free(struct iwl_priv *priv);
int iwl_eeprom_check_version(struct iwl_priv *priv);
const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset);
-u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset);
-
int iwlcore_eeprom_verify_signature(struct iwl_priv *priv);
-int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv);
-void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv);
+u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset);
const u8 *iwlcore_eeprom_query_addr(const struct iwl_priv *priv, size_t offset);
-void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv);
int iwl_init_channel_map(struct iwl_priv *priv);
void iwl_free_channel_map(struct iwl_priv *priv);
const struct iwl_channel_info *iwl_get_channel_info(
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
index 258d059ef41f..c373b53babea 100644
--- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c
+++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
@@ -97,6 +97,17 @@ const char *get_cmd_string(u8 cmd)
IWL_CMD(REPLY_TX_POWER_DBM_CMD);
IWL_CMD(TEMPERATURE_NOTIFICATION);
IWL_CMD(TX_ANT_CONFIGURATION_CMD);
+ IWL_CMD(REPLY_BT_COEX_PROFILE_NOTIF);
+ IWL_CMD(REPLY_BT_COEX_PRIO_TABLE);
+ IWL_CMD(REPLY_BT_COEX_PROT_ENV);
+ IWL_CMD(REPLY_WIPAN_PARAMS);
+ IWL_CMD(REPLY_WIPAN_RXON);
+ IWL_CMD(REPLY_WIPAN_RXON_TIMING);
+ IWL_CMD(REPLY_WIPAN_RXON_ASSOC);
+ IWL_CMD(REPLY_WIPAN_QOS_PARAM);
+ IWL_CMD(REPLY_WIPAN_WEPKEY);
+ IWL_CMD(REPLY_WIPAN_P2P_CHANNEL_SWITCH);
+ IWL_CMD(REPLY_WIPAN_NOA_NOTIFICATION);
default:
return "UNKNOWN";
@@ -229,7 +240,7 @@ cancel:
* in later, it will possibly set an invalid
* address (cmd->meta.source).
*/
- priv->txq[IWL_CMD_QUEUE_NUM].meta[cmd_idx].flags &=
+ priv->txq[priv->cmd_queue].meta[cmd_idx].flags &=
~CMD_WANT_SKB;
}
fail:
diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h
index 621abe3c5afc..1aaef70deaec 100644
--- a/drivers/net/wireless/iwlwifi/iwl-helpers.h
+++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h
@@ -44,11 +44,6 @@ static inline struct ieee80211_conf *ieee80211_get_hw_conf(
return &hw->conf;
}
-static inline int iwl_check_bits(unsigned long field, unsigned long mask)
-{
- return ((field & mask) == mask) ? 1 : 0;
-}
-
static inline unsigned long elapsed_jiffies(unsigned long start,
unsigned long end)
{
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c
index db5bfcb036ca..86c2b6fed0c6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-led.c
+++ b/drivers/net/wireless/iwlwifi/iwl-led.c
@@ -108,13 +108,13 @@ static int iwl_led_pattern(struct iwl_priv *priv, unsigned int idx)
BUG_ON(idx > IWL_MAX_BLINK_TBL);
IWL_DEBUG_LED(priv, "Led blink time compensation= %u\n",
- priv->cfg->led_compensation);
+ priv->cfg->base_params->led_compensation);
led_cmd.on =
iwl_blink_compensation(priv, blink_tbl[idx].on_time,
- priv->cfg->led_compensation);
+ priv->cfg->base_params->led_compensation);
led_cmd.off =
iwl_blink_compensation(priv, blink_tbl[idx].off_time,
- priv->cfg->led_compensation);
+ priv->cfg->base_params->led_compensation);
return priv->cfg->ops->led->cmd(priv, &led_cmd);
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c
index cda6a94d6cc9..49d7788937a9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.c
+++ b/drivers/net/wireless/iwlwifi/iwl-power.c
@@ -192,47 +192,6 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv,
IWL_DEBUG_POWER(priv, "Sleep command for index %d\n", lvl + 1);
}
-/* default Thermal Throttling transaction table
- * Current state | Throttling Down | Throttling Up
- *=============================================================================
- * Condition Nxt State Condition Nxt State Condition Nxt State
- *-----------------------------------------------------------------------------
- * IWL_TI_0 T >= 114 CT_KILL 114>T>=105 TI_1 N/A N/A
- * IWL_TI_1 T >= 114 CT_KILL 114>T>=110 TI_2 T<=95 TI_0
- * IWL_TI_2 T >= 114 CT_KILL T<=100 TI_1
- * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0
- *=============================================================================
- */
-static const struct iwl_tt_trans tt_range_0[IWL_TI_STATE_MAX - 1] = {
- {IWL_TI_0, IWL_ABSOLUTE_ZERO, 104},
- {IWL_TI_1, 105, CT_KILL_THRESHOLD - 1},
- {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX}
-};
-static const struct iwl_tt_trans tt_range_1[IWL_TI_STATE_MAX - 1] = {
- {IWL_TI_0, IWL_ABSOLUTE_ZERO, 95},
- {IWL_TI_2, 110, CT_KILL_THRESHOLD - 1},
- {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX}
-};
-static const struct iwl_tt_trans tt_range_2[IWL_TI_STATE_MAX - 1] = {
- {IWL_TI_1, IWL_ABSOLUTE_ZERO, 100},
- {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX},
- {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX}
-};
-static const struct iwl_tt_trans tt_range_3[IWL_TI_STATE_MAX - 1] = {
- {IWL_TI_0, IWL_ABSOLUTE_ZERO, CT_KILL_EXIT_THRESHOLD},
- {IWL_TI_CT_KILL, CT_KILL_EXIT_THRESHOLD + 1, IWL_ABSOLUTE_MAX},
- {IWL_TI_CT_KILL, CT_KILL_EXIT_THRESHOLD + 1, IWL_ABSOLUTE_MAX}
-};
-
-/* Advance Thermal Throttling default restriction table */
-static const struct iwl_tt_restriction restriction_range[IWL_TI_STATE_MAX] = {
- {IWL_ANT_OK_MULTI, IWL_ANT_OK_MULTI, true },
- {IWL_ANT_OK_SINGLE, IWL_ANT_OK_MULTI, true },
- {IWL_ANT_OK_SINGLE, IWL_ANT_OK_SINGLE, false },
- {IWL_ANT_OK_NONE, IWL_ANT_OK_NONE, false }
-};
-
-
static void iwl_power_sleep_cam_cmd(struct iwl_priv *priv,
struct iwl_powertable_cmd *cmd)
{
@@ -308,7 +267,6 @@ static int iwl_set_power(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd)
int iwl_power_update_mode(struct iwl_priv *priv, bool force)
{
int ret = 0;
- struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
bool enabled = priv->hw->conf.flags & IEEE80211_CONF_PS;
bool update_chains;
struct iwl_powertable_cmd cmd;
@@ -320,14 +278,18 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force)
dtimper = priv->hw->conf.ps_dtim_period ?: 1;
- if (priv->cfg->broken_powersave)
+ if (priv->cfg->base_params->broken_powersave)
iwl_power_sleep_cam_cmd(priv, &cmd);
- else if (priv->cfg->supports_idle &&
+ else if (priv->cfg->base_params->supports_idle &&
priv->hw->conf.flags & IEEE80211_CONF_IDLE)
iwl_static_sleep_cmd(priv, &cmd, IWL_POWER_INDEX_5, 20);
- else if (tt->state >= IWL_TI_1)
- iwl_static_sleep_cmd(priv, &cmd, tt->tt_power_mode, dtimper);
- else if (!enabled)
+ else if (priv->cfg->ops->lib->tt_ops.lower_power_detection &&
+ priv->cfg->ops->lib->tt_ops.tt_power_mode &&
+ priv->cfg->ops->lib->tt_ops.lower_power_detection(priv)) {
+ /* in thermal throttling low power state */
+ iwl_static_sleep_cmd(priv, &cmd,
+ priv->cfg->ops->lib->tt_ops.tt_power_mode(priv), dtimper);
+ } else if (!enabled)
iwl_power_sleep_cam_cmd(priv, &cmd);
else if (priv->power_data.debug_sleep_level_override >= 0)
iwl_static_sleep_cmd(priv, &cmd,
@@ -367,592 +329,6 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force)
}
EXPORT_SYMBOL(iwl_power_update_mode);
-bool iwl_ht_enabled(struct iwl_priv *priv)
-{
- struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
- struct iwl_tt_restriction *restriction;
-
- if (!priv->thermal_throttle.advanced_tt)
- return true;
- restriction = tt->restriction + tt->state;
- return restriction->is_ht;
-}
-EXPORT_SYMBOL(iwl_ht_enabled);
-
-bool iwl_within_ct_kill_margin(struct iwl_priv *priv)
-{
- s32 temp = priv->temperature; /* degrees CELSIUS except specified */
- bool within_margin = false;
-
- if (priv->cfg->temperature_kelvin)
- temp = KELVIN_TO_CELSIUS(priv->temperature);
-
- if (!priv->thermal_throttle.advanced_tt)
- within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >=
- CT_KILL_THRESHOLD_LEGACY) ? true : false;
- else
- within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >=
- CT_KILL_THRESHOLD) ? true : false;
- return within_margin;
-}
-
-enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv)
-{
- struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
- struct iwl_tt_restriction *restriction;
-
- if (!priv->thermal_throttle.advanced_tt)
- return IWL_ANT_OK_MULTI;
- restriction = tt->restriction + tt->state;
- return restriction->tx_stream;
-}
-EXPORT_SYMBOL(iwl_tx_ant_restriction);
-
-enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv)
-{
- struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
- struct iwl_tt_restriction *restriction;
-
- if (!priv->thermal_throttle.advanced_tt)
- return IWL_ANT_OK_MULTI;
- restriction = tt->restriction + tt->state;
- return restriction->rx_stream;
-}
-
-#define CT_KILL_EXIT_DURATION (5) /* 5 seconds duration */
-#define CT_KILL_WAITING_DURATION (300) /* 300ms duration */
-
-/*
- * toggle the bit to wake up uCode and check the temperature
- * if the temperature is below CT, uCode will stay awake and send card
- * state notification with CT_KILL bit clear to inform Thermal Throttling
- * Management to change state. Otherwise, uCode will go back to sleep
- * without doing anything, driver should continue the 5 seconds timer
- * to wake up uCode for temperature check until temperature drop below CT
- */
-static void iwl_tt_check_exit_ct_kill(unsigned long data)
-{
- struct iwl_priv *priv = (struct iwl_priv *)data;
- struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
- unsigned long flags;
-
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return;
-
- if (tt->state == IWL_TI_CT_KILL) {
- if (priv->thermal_throttle.ct_kill_toggle) {
- iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
- CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
- priv->thermal_throttle.ct_kill_toggle = false;
- } else {
- iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
- CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
- priv->thermal_throttle.ct_kill_toggle = true;
- }
- iwl_read32(priv, CSR_UCODE_DRV_GP1);
- spin_lock_irqsave(&priv->reg_lock, flags);
- if (!iwl_grab_nic_access(priv))
- iwl_release_nic_access(priv);
- spin_unlock_irqrestore(&priv->reg_lock, flags);
-
- /* Reschedule the ct_kill timer to occur in
- * CT_KILL_EXIT_DURATION seconds to ensure we get a
- * thermal update */
- IWL_DEBUG_POWER(priv, "schedule ct_kill exit timer\n");
- mod_timer(&priv->thermal_throttle.ct_kill_exit_tm, jiffies +
- CT_KILL_EXIT_DURATION * HZ);
- }
-}
-
-static void iwl_perform_ct_kill_task(struct iwl_priv *priv,
- bool stop)
-{
- if (stop) {
- IWL_DEBUG_POWER(priv, "Stop all queues\n");
- if (priv->mac80211_registered)
- ieee80211_stop_queues(priv->hw);
- IWL_DEBUG_POWER(priv,
- "Schedule 5 seconds CT_KILL Timer\n");
- mod_timer(&priv->thermal_throttle.ct_kill_exit_tm, jiffies +
- CT_KILL_EXIT_DURATION * HZ);
- } else {
- IWL_DEBUG_POWER(priv, "Wake all queues\n");
- if (priv->mac80211_registered)
- ieee80211_wake_queues(priv->hw);
- }
-}
-
-static void iwl_tt_ready_for_ct_kill(unsigned long data)
-{
- struct iwl_priv *priv = (struct iwl_priv *)data;
- struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
-
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return;
-
- /* temperature timer expired, ready to go into CT_KILL state */
- if (tt->state != IWL_TI_CT_KILL) {
- IWL_DEBUG_POWER(priv, "entering CT_KILL state when temperature timer expired\n");
- tt->state = IWL_TI_CT_KILL;
- set_bit(STATUS_CT_KILL, &priv->status);
- iwl_perform_ct_kill_task(priv, true);
- }
-}
-
-static void iwl_prepare_ct_kill_task(struct iwl_priv *priv)
-{
- IWL_DEBUG_POWER(priv, "Prepare to enter IWL_TI_CT_KILL\n");
- /* make request to retrieve statistics information */
- iwl_send_statistics_request(priv, CMD_SYNC, false);
- /* Reschedule the ct_kill wait timer */
- mod_timer(&priv->thermal_throttle.ct_kill_waiting_tm,
- jiffies + msecs_to_jiffies(CT_KILL_WAITING_DURATION));
-}
-
-#define IWL_MINIMAL_POWER_THRESHOLD (CT_KILL_THRESHOLD_LEGACY)
-#define IWL_REDUCED_PERFORMANCE_THRESHOLD_2 (100)
-#define IWL_REDUCED_PERFORMANCE_THRESHOLD_1 (90)
-
-/*
- * Legacy thermal throttling
- * 1) Avoid NIC destruction due to high temperatures
- * Chip will identify dangerously high temperatures that can
- * harm the device and will power down
- * 2) Avoid the NIC power down due to high temperature
- * Throttle early enough to lower the power consumption before
- * drastic steps are needed
- */
-static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
-{
- struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
- enum iwl_tt_state old_state;
-
-#ifdef CONFIG_IWLWIFI_DEBUG
- if ((tt->tt_previous_temp) &&
- (temp > tt->tt_previous_temp) &&
- ((temp - tt->tt_previous_temp) >
- IWL_TT_INCREASE_MARGIN)) {
- IWL_DEBUG_POWER(priv,
- "Temperature increase %d degree Celsius\n",
- (temp - tt->tt_previous_temp));
- }
-#endif
- old_state = tt->state;
- /* in Celsius */
- if (temp >= IWL_MINIMAL_POWER_THRESHOLD)
- tt->state = IWL_TI_CT_KILL;
- else if (temp >= IWL_REDUCED_PERFORMANCE_THRESHOLD_2)
- tt->state = IWL_TI_2;
- else if (temp >= IWL_REDUCED_PERFORMANCE_THRESHOLD_1)
- tt->state = IWL_TI_1;
- else
- tt->state = IWL_TI_0;
-
-#ifdef CONFIG_IWLWIFI_DEBUG
- tt->tt_previous_temp = temp;
-#endif
- /* stop ct_kill_waiting_tm timer */
- del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm);
- if (tt->state != old_state) {
- switch (tt->state) {
- case IWL_TI_0:
- /*
- * When the system is ready to go back to IWL_TI_0
- * we only have to call iwl_power_update_mode() to
- * do so.
- */
- break;
- case IWL_TI_1:
- tt->tt_power_mode = IWL_POWER_INDEX_3;
- break;
- case IWL_TI_2:
- tt->tt_power_mode = IWL_POWER_INDEX_4;
- break;
- default:
- tt->tt_power_mode = IWL_POWER_INDEX_5;
- break;
- }
- mutex_lock(&priv->mutex);
- if (old_state == IWL_TI_CT_KILL)
- clear_bit(STATUS_CT_KILL, &priv->status);
- if (tt->state != IWL_TI_CT_KILL &&
- iwl_power_update_mode(priv, true)) {
- /* TT state not updated
- * try again during next temperature read
- */
- if (old_state == IWL_TI_CT_KILL)
- set_bit(STATUS_CT_KILL, &priv->status);
- tt->state = old_state;
- IWL_ERR(priv, "Cannot update power mode, "
- "TT state not updated\n");
- } else {
- if (tt->state == IWL_TI_CT_KILL) {
- if (force) {
- set_bit(STATUS_CT_KILL, &priv->status);
- iwl_perform_ct_kill_task(priv, true);
- } else {
- iwl_prepare_ct_kill_task(priv);
- tt->state = old_state;
- }
- } else if (old_state == IWL_TI_CT_KILL &&
- tt->state != IWL_TI_CT_KILL)
- iwl_perform_ct_kill_task(priv, false);
- IWL_DEBUG_POWER(priv, "Temperature state changed %u\n",
- tt->state);
- IWL_DEBUG_POWER(priv, "Power Index change to %u\n",
- tt->tt_power_mode);
- }
- mutex_unlock(&priv->mutex);
- }
-}
-
-/*
- * Advance thermal throttling
- * 1) Avoid NIC destruction due to high temperatures
- * Chip will identify dangerously high temperatures that can
- * harm the device and will power down
- * 2) Avoid the NIC power down due to high temperature
- * Throttle early enough to lower the power consumption before
- * drastic steps are needed
- * Actions include relaxing the power down sleep thresholds and
- * decreasing the number of TX streams
- * 3) Avoid throughput performance impact as much as possible
- *
- *=============================================================================
- * Condition Nxt State Condition Nxt State Condition Nxt State
- *-----------------------------------------------------------------------------
- * IWL_TI_0 T >= 114 CT_KILL 114>T>=105 TI_1 N/A N/A
- * IWL_TI_1 T >= 114 CT_KILL 114>T>=110 TI_2 T<=95 TI_0
- * IWL_TI_2 T >= 114 CT_KILL T<=100 TI_1
- * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0
- *=============================================================================
- */
-static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
-{
- struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
- int i;
- bool changed = false;
- enum iwl_tt_state old_state;
- struct iwl_tt_trans *transaction;
-
- old_state = tt->state;
- for (i = 0; i < IWL_TI_STATE_MAX - 1; i++) {
- /* based on the current TT state,
- * find the curresponding transaction table
- * each table has (IWL_TI_STATE_MAX - 1) entries
- * tt->transaction + ((old_state * (IWL_TI_STATE_MAX - 1))
- * will advance to the correct table.
- * then based on the current temperature
- * find the next state need to transaction to
- * go through all the possible (IWL_TI_STATE_MAX - 1) entries
- * in the current table to see if transaction is needed
- */
- transaction = tt->transaction +
- ((old_state * (IWL_TI_STATE_MAX - 1)) + i);
- if (temp >= transaction->tt_low &&
- temp <= transaction->tt_high) {
-#ifdef CONFIG_IWLWIFI_DEBUG
- if ((tt->tt_previous_temp) &&
- (temp > tt->tt_previous_temp) &&
- ((temp - tt->tt_previous_temp) >
- IWL_TT_INCREASE_MARGIN)) {
- IWL_DEBUG_POWER(priv,
- "Temperature increase %d "
- "degree Celsius\n",
- (temp - tt->tt_previous_temp));
- }
- tt->tt_previous_temp = temp;
-#endif
- if (old_state !=
- transaction->next_state) {
- changed = true;
- tt->state =
- transaction->next_state;
- }
- break;
- }
- }
- /* stop ct_kill_waiting_tm timer */
- del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm);
- if (changed) {
- struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
-
- if (tt->state >= IWL_TI_1) {
- /* force PI = IWL_POWER_INDEX_5 in the case of TI > 0 */
- tt->tt_power_mode = IWL_POWER_INDEX_5;
- if (!iwl_ht_enabled(priv))
- /* disable HT */
- rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK |
- RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK |
- RXON_FLG_HT40_PROT_MSK |
- RXON_FLG_HT_PROT_MSK);
- else {
- /* check HT capability and set
- * according to the system HT capability
- * in case get disabled before */
- iwl_set_rxon_ht(priv, &priv->current_ht_config);
- }
-
- } else {
- /*
- * restore system power setting -- it will be
- * recalculated automatically.
- */
-
- /* check HT capability and set
- * according to the system HT capability
- * in case get disabled before */
- iwl_set_rxon_ht(priv, &priv->current_ht_config);
- }
- mutex_lock(&priv->mutex);
- if (old_state == IWL_TI_CT_KILL)
- clear_bit(STATUS_CT_KILL, &priv->status);
- if (tt->state != IWL_TI_CT_KILL &&
- iwl_power_update_mode(priv, true)) {
- /* TT state not updated
- * try again during next temperature read
- */
- IWL_ERR(priv, "Cannot update power mode, "
- "TT state not updated\n");
- if (old_state == IWL_TI_CT_KILL)
- set_bit(STATUS_CT_KILL, &priv->status);
- tt->state = old_state;
- } else {
- IWL_DEBUG_POWER(priv,
- "Thermal Throttling to new state: %u\n",
- tt->state);
- if (old_state != IWL_TI_CT_KILL &&
- tt->state == IWL_TI_CT_KILL) {
- if (force) {
- IWL_DEBUG_POWER(priv,
- "Enter IWL_TI_CT_KILL\n");
- set_bit(STATUS_CT_KILL, &priv->status);
- iwl_perform_ct_kill_task(priv, true);
- } else {
- iwl_prepare_ct_kill_task(priv);
- tt->state = old_state;
- }
- } else if (old_state == IWL_TI_CT_KILL &&
- tt->state != IWL_TI_CT_KILL) {
- IWL_DEBUG_POWER(priv, "Exit IWL_TI_CT_KILL\n");
- iwl_perform_ct_kill_task(priv, false);
- }
- }
- mutex_unlock(&priv->mutex);
- }
-}
-
-/* Card State Notification indicated reach critical temperature
- * if PSP not enable, no Thermal Throttling function will be performed
- * just set the GP1 bit to acknowledge the event
- * otherwise, go into IWL_TI_CT_KILL state
- * since Card State Notification will not provide any temperature reading
- * for Legacy mode
- * so just pass the CT_KILL temperature to iwl_legacy_tt_handler()
- * for advance mode
- * pass CT_KILL_THRESHOLD+1 to make sure move into IWL_TI_CT_KILL state
- */
-static void iwl_bg_ct_enter(struct work_struct *work)
-{
- struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_enter);
- struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
-
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return;
-
- if (!iwl_is_ready(priv))
- return;
-
- if (tt->state != IWL_TI_CT_KILL) {
- IWL_ERR(priv, "Device reached critical temperature "
- "- ucode going to sleep!\n");
- if (!priv->thermal_throttle.advanced_tt)
- iwl_legacy_tt_handler(priv,
- IWL_MINIMAL_POWER_THRESHOLD,
- true);
- else
- iwl_advance_tt_handler(priv,
- CT_KILL_THRESHOLD + 1, true);
- }
-}
-
-/* Card State Notification indicated out of critical temperature
- * since Card State Notification will not provide any temperature reading
- * so pass the IWL_REDUCED_PERFORMANCE_THRESHOLD_2 temperature
- * to iwl_legacy_tt_handler() to get out of IWL_CT_KILL state
- */
-static void iwl_bg_ct_exit(struct work_struct *work)
-{
- struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_exit);
- struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
-
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return;
-
- if (!iwl_is_ready(priv))
- return;
-
- /* stop ct_kill_exit_tm timer */
- del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm);
-
- if (tt->state == IWL_TI_CT_KILL) {
- IWL_ERR(priv,
- "Device temperature below critical"
- "- ucode awake!\n");
- /*
- * exit from CT_KILL state
- * reset the current temperature reading
- */
- priv->temperature = 0;
- if (!priv->thermal_throttle.advanced_tt)
- iwl_legacy_tt_handler(priv,
- IWL_REDUCED_PERFORMANCE_THRESHOLD_2,
- true);
- else
- iwl_advance_tt_handler(priv, CT_KILL_EXIT_THRESHOLD,
- true);
- }
-}
-
-void iwl_tt_enter_ct_kill(struct iwl_priv *priv)
-{
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return;
-
- IWL_DEBUG_POWER(priv, "Queueing critical temperature enter.\n");
- queue_work(priv->workqueue, &priv->ct_enter);
-}
-EXPORT_SYMBOL(iwl_tt_enter_ct_kill);
-
-void iwl_tt_exit_ct_kill(struct iwl_priv *priv)
-{
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return;
-
- IWL_DEBUG_POWER(priv, "Queueing critical temperature exit.\n");
- queue_work(priv->workqueue, &priv->ct_exit);
-}
-EXPORT_SYMBOL(iwl_tt_exit_ct_kill);
-
-static void iwl_bg_tt_work(struct work_struct *work)
-{
- struct iwl_priv *priv = container_of(work, struct iwl_priv, tt_work);
- s32 temp = priv->temperature; /* degrees CELSIUS except specified */
-
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return;
-
- if (priv->cfg->temperature_kelvin)
- temp = KELVIN_TO_CELSIUS(priv->temperature);
-
- if (!priv->thermal_throttle.advanced_tt)
- iwl_legacy_tt_handler(priv, temp, false);
- else
- iwl_advance_tt_handler(priv, temp, false);
-}
-
-void iwl_tt_handler(struct iwl_priv *priv)
-{
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return;
-
- IWL_DEBUG_POWER(priv, "Queueing thermal throttling work.\n");
- queue_work(priv->workqueue, &priv->tt_work);
-}
-EXPORT_SYMBOL(iwl_tt_handler);
-
-/* Thermal throttling initialization
- * For advance thermal throttling:
- * Initialize Thermal Index and temperature threshold table
- * Initialize thermal throttling restriction table
- */
-void iwl_tt_initialize(struct iwl_priv *priv)
-{
- struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
- int size = sizeof(struct iwl_tt_trans) * (IWL_TI_STATE_MAX - 1);
- struct iwl_tt_trans *transaction;
-
- IWL_DEBUG_POWER(priv, "Initialize Thermal Throttling\n");
-
- memset(tt, 0, sizeof(struct iwl_tt_mgmt));
-
- tt->state = IWL_TI_0;
- init_timer(&priv->thermal_throttle.ct_kill_exit_tm);
- priv->thermal_throttle.ct_kill_exit_tm.data = (unsigned long)priv;
- priv->thermal_throttle.ct_kill_exit_tm.function =
- iwl_tt_check_exit_ct_kill;
- init_timer(&priv->thermal_throttle.ct_kill_waiting_tm);
- priv->thermal_throttle.ct_kill_waiting_tm.data = (unsigned long)priv;
- priv->thermal_throttle.ct_kill_waiting_tm.function =
- iwl_tt_ready_for_ct_kill;
- /* setup deferred ct kill work */
- INIT_WORK(&priv->tt_work, iwl_bg_tt_work);
- INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter);
- INIT_WORK(&priv->ct_exit, iwl_bg_ct_exit);
-
- if (priv->cfg->adv_thermal_throttle) {
- IWL_DEBUG_POWER(priv, "Advanced Thermal Throttling\n");
- tt->restriction = kzalloc(sizeof(struct iwl_tt_restriction) *
- IWL_TI_STATE_MAX, GFP_KERNEL);
- tt->transaction = kzalloc(sizeof(struct iwl_tt_trans) *
- IWL_TI_STATE_MAX * (IWL_TI_STATE_MAX - 1),
- GFP_KERNEL);
- if (!tt->restriction || !tt->transaction) {
- IWL_ERR(priv, "Fallback to Legacy Throttling\n");
- priv->thermal_throttle.advanced_tt = false;
- kfree(tt->restriction);
- tt->restriction = NULL;
- kfree(tt->transaction);
- tt->transaction = NULL;
- } else {
- transaction = tt->transaction +
- (IWL_TI_0 * (IWL_TI_STATE_MAX - 1));
- memcpy(transaction, &tt_range_0[0], size);
- transaction = tt->transaction +
- (IWL_TI_1 * (IWL_TI_STATE_MAX - 1));
- memcpy(transaction, &tt_range_1[0], size);
- transaction = tt->transaction +
- (IWL_TI_2 * (IWL_TI_STATE_MAX - 1));
- memcpy(transaction, &tt_range_2[0], size);
- transaction = tt->transaction +
- (IWL_TI_CT_KILL * (IWL_TI_STATE_MAX - 1));
- memcpy(transaction, &tt_range_3[0], size);
- size = sizeof(struct iwl_tt_restriction) *
- IWL_TI_STATE_MAX;
- memcpy(tt->restriction,
- &restriction_range[0], size);
- priv->thermal_throttle.advanced_tt = true;
- }
- } else {
- IWL_DEBUG_POWER(priv, "Legacy Thermal Throttling\n");
- priv->thermal_throttle.advanced_tt = false;
- }
-}
-EXPORT_SYMBOL(iwl_tt_initialize);
-
-/* cleanup thermal throttling management related memory and timer */
-void iwl_tt_exit(struct iwl_priv *priv)
-{
- struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
-
- /* stop ct_kill_exit_tm timer if activated */
- del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm);
- /* stop ct_kill_waiting_tm timer if activated */
- del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm);
- cancel_work_sync(&priv->tt_work);
- cancel_work_sync(&priv->ct_enter);
- cancel_work_sync(&priv->ct_exit);
-
- if (priv->thermal_throttle.advanced_tt) {
- /* free advance thermal throttling memory */
- kfree(tt->restriction);
- tt->restriction = NULL;
- kfree(tt->transaction);
- tt->transaction = NULL;
- }
-}
-EXPORT_SYMBOL(iwl_tt_exit);
-
/* initialize to default */
void iwl_power_initialize(struct iwl_priv *priv)
{
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.h b/drivers/net/wireless/iwlwifi/iwl-power.h
index 5db91c10dcc8..df81565a7cc4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.h
+++ b/drivers/net/wireless/iwlwifi/iwl-power.h
@@ -30,90 +30,6 @@
#include "iwl-commands.h"
-#define IWL_ABSOLUTE_ZERO 0
-#define IWL_ABSOLUTE_MAX 0xFFFFFFFF
-#define IWL_TT_INCREASE_MARGIN 5
-#define IWL_TT_CT_KILL_MARGIN 3
-
-enum iwl_antenna_ok {
- IWL_ANT_OK_NONE,
- IWL_ANT_OK_SINGLE,
- IWL_ANT_OK_MULTI,
-};
-
-/* Thermal Throttling State Machine states */
-enum iwl_tt_state {
- IWL_TI_0, /* normal temperature, system power state */
- IWL_TI_1, /* high temperature detect, low power state */
- IWL_TI_2, /* higher temperature detected, lower power state */
- IWL_TI_CT_KILL, /* critical temperature detected, lowest power state */
- IWL_TI_STATE_MAX
-};
-
-/**
- * struct iwl_tt_restriction - Thermal Throttling restriction table
- * @tx_stream: number of tx stream allowed
- * @is_ht: ht enable/disable
- * @rx_stream: number of rx stream allowed
- *
- * This table is used by advance thermal throttling management
- * based on the current thermal throttling state, and determines
- * the number of tx/rx streams and the status of HT operation.
- */
-struct iwl_tt_restriction {
- enum iwl_antenna_ok tx_stream;
- enum iwl_antenna_ok rx_stream;
- bool is_ht;
-};
-
-/**
- * struct iwl_tt_trans - Thermal Throttling transaction table
- * @next_state: next thermal throttling mode
- * @tt_low: low temperature threshold to change state
- * @tt_high: high temperature threshold to change state
- *
- * This is used by the advanced thermal throttling algorithm
- * to determine the next thermal state to go based on the
- * current temperature.
- */
-struct iwl_tt_trans {
- enum iwl_tt_state next_state;
- u32 tt_low;
- u32 tt_high;
-};
-
-/**
- * struct iwl_tt_mgnt - Thermal Throttling Management structure
- * @advanced_tt: advanced thermal throttle required
- * @state: current Thermal Throttling state
- * @tt_power_mode: Thermal Throttling power mode index
- * being used to set power level when
- * when thermal throttling state != IWL_TI_0
- * the tt_power_mode should set to different
- * power mode based on the current tt state
- * @tt_previous_temperature: last measured temperature
- * @iwl_tt_restriction: ptr to restriction tbl, used by advance
- * thermal throttling to determine how many tx/rx streams
- * should be used in tt state; and can HT be enabled or not
- * @iwl_tt_trans: ptr to adv trans table, used by advance thermal throttling
- * state transaction
- * @ct_kill_toggle: used to toggle the CSR bit when checking uCode temperature
- * @ct_kill_exit_tm: timer to exit thermal kill
- */
-struct iwl_tt_mgmt {
- enum iwl_tt_state state;
- bool advanced_tt;
- u8 tt_power_mode;
- bool ct_kill_toggle;
-#ifdef CONFIG_IWLWIFI_DEBUG
- s32 tt_previous_temp;
-#endif
- struct iwl_tt_restriction *restriction;
- struct iwl_tt_trans *transaction;
- struct timer_list ct_kill_exit_tm;
- struct timer_list ct_kill_waiting_tm;
-};
-
enum iwl_power_level {
IWL_POWER_INDEX_1,
IWL_POWER_INDEX_2,
@@ -130,15 +46,6 @@ struct iwl_power_mgr {
};
int iwl_power_update_mode(struct iwl_priv *priv, bool force);
-bool iwl_ht_enabled(struct iwl_priv *priv);
-bool iwl_within_ct_kill_margin(struct iwl_priv *priv);
-enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv);
-enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv);
-void iwl_tt_enter_ct_kill(struct iwl_priv *priv);
-void iwl_tt_exit_ct_kill(struct iwl_priv *priv);
-void iwl_tt_handler(struct iwl_priv *priv);
-void iwl_tt_initialize(struct iwl_priv *priv);
-void iwl_tt_exit(struct iwl_priv *priv);
void iwl_power_initialize(struct iwl_priv *priv);
extern bool no_sleep_autoadjust;
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h
index b1f101caf19d..5469655646ae 100644
--- a/drivers/net/wireless/iwlwifi/iwl-prph.h
+++ b/drivers/net/wireless/iwlwifi/iwl-prph.h
@@ -306,7 +306,7 @@
* at a time, until receiving ACK from receiving station, or reaching
* retry limit and giving up.
*
- * The command queue (#4) must use this mode!
+ * The command queue (#4/#9) must use this mode!
* This mode does not require use of the Byte Count table in host DRAM.
*
* Driver controls scheduler operation via 3 means:
@@ -322,7 +322,7 @@
* (1024 bytes for each queue).
*
* After receiving "Alive" response from uCode, driver must initialize
- * the scheduler (especially for queue #4, the command queue, otherwise
+ * the scheduler (especially for queue #4/#9, the command queue, otherwise
* the driver can't issue commands!):
*/
@@ -555,8 +555,9 @@
#define IWLAGN_SCD_TRANSLATE_TBL_OFFSET_QUEUE(x) \
((IWLAGN_SCD_TRANSLATE_TBL_OFFSET + ((x) * 2)) & 0xfffc)
-#define IWLAGN_SCD_QUEUECHAIN_SEL_ALL(x) (((1<<(x)) - 1) &\
- (~(1<<IWL_CMD_QUEUE_NUM)))
+#define IWLAGN_SCD_QUEUECHAIN_SEL_ALL(priv) \
+ (((1<<(priv)->hw_params.max_txq_num) - 1) &\
+ (~(1<<(priv)->cmd_queue)))
#define IWLAGN_SCD_BASE (PRPH_BASE + 0xa02c00)
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index 79773e353baa..f436270ca39a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -36,7 +36,6 @@
#include "iwl-core.h"
#include "iwl-sta.h"
#include "iwl-io.h"
-#include "iwl-calib.h"
#include "iwl-helpers.h"
/************************** RX-FUNCTIONS ****************************/
/*
@@ -228,7 +227,7 @@ void iwl_recover_from_statistics(struct iwl_priv *priv,
{
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
- if (iwl_is_associated(priv)) {
+ if (iwl_is_any_associated(priv)) {
if (priv->cfg->ops->lib->check_ack_health) {
if (!priv->cfg->ops->lib->check_ack_health(
priv, pkt)) {
@@ -266,7 +265,12 @@ int iwl_set_decrypted_flag(struct iwl_priv *priv,
{
u16 fc = le16_to_cpu(hdr->frame_control);
- if (priv->active_rxon.filter_flags & RXON_FILTER_DIS_DECRYPT_MSK)
+ /*
+ * All contexts have the same setting here due to it being
+ * a module parameter, so OK to check any context.
+ */
+ if (priv->contexts[IWL_RXON_CTX_BSS].active.filter_flags &
+ RXON_FILTER_DIS_DECRYPT_MSK)
return 0;
if (!(fc & IEEE80211_FCTL_PROTECTED))
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index a4b3663a262f..67da31295781 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -54,100 +54,133 @@
#define IWL_PASSIVE_DWELL_BASE (100)
#define IWL_CHANNEL_TUNE_TIME 5
+static int iwl_send_scan_abort(struct iwl_priv *priv)
+{
+ int ret;
+ struct iwl_rx_packet *pkt;
+ struct iwl_host_cmd cmd = {
+ .id = REPLY_SCAN_ABORT_CMD,
+ .flags = CMD_WANT_SKB,
+ };
+ /* Exit instantly with error when device is not ready
+ * to receive scan abort command or it does not perform
+ * hardware scan currently */
+ if (!test_bit(STATUS_READY, &priv->status) ||
+ !test_bit(STATUS_GEO_CONFIGURED, &priv->status) ||
+ !test_bit(STATUS_SCAN_HW, &priv->status) ||
+ test_bit(STATUS_FW_ERROR, &priv->status) ||
+ test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return -EIO;
-/**
- * iwl_scan_cancel - Cancel any currently executing HW scan
- *
- * NOTE: priv->mutex is not required before calling this function
- */
-int iwl_scan_cancel(struct iwl_priv *priv)
+ ret = iwl_send_cmd_sync(priv, &cmd);
+ if (ret)
+ return ret;
+
+ pkt = (struct iwl_rx_packet *)cmd.reply_page;
+ if (pkt->u.status != CAN_ABORT_STATUS) {
+ /* The scan abort will return 1 for success or
+ * 2 for "failure". A failure condition can be
+ * due to simply not being in an active scan which
+ * can occur if we send the scan abort before we
+ * the microcode has notified us that a scan is
+ * completed. */
+ IWL_DEBUG_SCAN(priv, "SCAN_ABORT ret %d.\n", pkt->u.status);
+ ret = -EIO;
+ }
+
+ iwl_free_pages(priv, cmd.reply_page);
+ return ret;
+}
+
+static void iwl_complete_scan(struct iwl_priv *priv, bool aborted)
{
- if (!test_bit(STATUS_SCAN_HW, &priv->status)) {
- clear_bit(STATUS_SCANNING, &priv->status);
- return 0;
+ /* check if scan was requested from mac80211 */
+ if (priv->scan_request) {
+ IWL_DEBUG_SCAN(priv, "Complete scan in mac80211\n");
+ ieee80211_scan_completed(priv->hw, aborted);
}
- if (test_bit(STATUS_SCANNING, &priv->status)) {
- if (!test_and_set_bit(STATUS_SCAN_ABORTING, &priv->status)) {
- IWL_DEBUG_SCAN(priv, "Queuing scan abort.\n");
- queue_work(priv->workqueue, &priv->abort_scan);
+ priv->is_internal_short_scan = false;
+ priv->scan_vif = NULL;
+ priv->scan_request = NULL;
+}
- } else
- IWL_DEBUG_SCAN(priv, "Scan abort already in progress.\n");
+void iwl_force_scan_end(struct iwl_priv *priv)
+{
+ lockdep_assert_held(&priv->mutex);
- return test_bit(STATUS_SCANNING, &priv->status);
+ if (!test_bit(STATUS_SCANNING, &priv->status)) {
+ IWL_DEBUG_SCAN(priv, "Forcing scan end while not scanning\n");
+ return;
}
+ IWL_DEBUG_SCAN(priv, "Forcing scan end\n");
+ clear_bit(STATUS_SCANNING, &priv->status);
+ clear_bit(STATUS_SCAN_HW, &priv->status);
+ clear_bit(STATUS_SCAN_ABORTING, &priv->status);
+ iwl_complete_scan(priv, true);
+}
+
+static void iwl_do_scan_abort(struct iwl_priv *priv)
+{
+ int ret;
+
+ lockdep_assert_held(&priv->mutex);
+
+ if (!test_bit(STATUS_SCANNING, &priv->status)) {
+ IWL_DEBUG_SCAN(priv, "Not performing scan to abort\n");
+ return;
+ }
+
+ if (test_and_set_bit(STATUS_SCAN_ABORTING, &priv->status)) {
+ IWL_DEBUG_SCAN(priv, "Scan abort in progress\n");
+ return;
+ }
+
+ ret = iwl_send_scan_abort(priv);
+ if (ret) {
+ IWL_DEBUG_SCAN(priv, "Send scan abort failed %d\n", ret);
+ iwl_force_scan_end(priv);
+ } else
+ IWL_DEBUG_SCAN(priv, "Sucessfully send scan abort\n");
+}
+
+/**
+ * iwl_scan_cancel - Cancel any currently executing HW scan
+ */
+int iwl_scan_cancel(struct iwl_priv *priv)
+{
+ IWL_DEBUG_SCAN(priv, "Queuing abort scan\n");
+ queue_work(priv->workqueue, &priv->abort_scan);
return 0;
}
EXPORT_SYMBOL(iwl_scan_cancel);
+
/**
* iwl_scan_cancel_timeout - Cancel any currently executing HW scan
* @ms: amount of time to wait (in milliseconds) for scan to abort
*
- * NOTE: priv->mutex must be held before calling this function
*/
int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms)
{
- unsigned long now = jiffies;
- int ret;
-
- ret = iwl_scan_cancel(priv);
- if (ret && ms) {
- mutex_unlock(&priv->mutex);
- while (!time_after(jiffies, now + msecs_to_jiffies(ms)) &&
- test_bit(STATUS_SCANNING, &priv->status))
- msleep(1);
- mutex_lock(&priv->mutex);
-
- return test_bit(STATUS_SCANNING, &priv->status);
- }
+ unsigned long timeout = jiffies + msecs_to_jiffies(ms);
- return ret;
-}
-EXPORT_SYMBOL(iwl_scan_cancel_timeout);
+ lockdep_assert_held(&priv->mutex);
-static int iwl_send_scan_abort(struct iwl_priv *priv)
-{
- int ret = 0;
- struct iwl_rx_packet *pkt;
- struct iwl_host_cmd cmd = {
- .id = REPLY_SCAN_ABORT_CMD,
- .flags = CMD_WANT_SKB,
- };
+ IWL_DEBUG_SCAN(priv, "Scan cancel timeout\n");
- /* If there isn't a scan actively going on in the hardware
- * then we are in between scan bands and not actually
- * actively scanning, so don't send the abort command */
- if (!test_bit(STATUS_SCAN_HW, &priv->status)) {
- clear_bit(STATUS_SCAN_ABORTING, &priv->status);
- return 0;
- }
+ iwl_do_scan_abort(priv);
- ret = iwl_send_cmd_sync(priv, &cmd);
- if (ret) {
- clear_bit(STATUS_SCAN_ABORTING, &priv->status);
- return ret;
- }
-
- pkt = (struct iwl_rx_packet *)cmd.reply_page;
- if (pkt->u.status != CAN_ABORT_STATUS) {
- /* The scan abort will return 1 for success or
- * 2 for "failure". A failure condition can be
- * due to simply not being in an active scan which
- * can occur if we send the scan abort before we
- * the microcode has notified us that a scan is
- * completed. */
- IWL_DEBUG_INFO(priv, "SCAN_ABORT returned %d.\n", pkt->u.status);
- clear_bit(STATUS_SCAN_ABORTING, &priv->status);
- clear_bit(STATUS_SCAN_HW, &priv->status);
+ while (time_before_eq(jiffies, timeout)) {
+ if (!test_bit(STATUS_SCAN_HW, &priv->status))
+ break;
+ msleep(20);
}
- iwl_free_pages(priv, cmd.reply_page);
-
- return ret;
+ return test_bit(STATUS_SCAN_HW, &priv->status);
}
+EXPORT_SYMBOL(iwl_scan_cancel_timeout);
/* Service response to REPLY_SCAN_CMD (0x80) */
static void iwl_rx_reply_scan(struct iwl_priv *priv,
@@ -158,7 +191,7 @@ static void iwl_rx_reply_scan(struct iwl_priv *priv,
struct iwl_scanreq_notification *notif =
(struct iwl_scanreq_notification *)pkt->u.raw;
- IWL_DEBUG_RX(priv, "Scan request status = 0x%x\n", notif->status);
+ IWL_DEBUG_SCAN(priv, "Scan request status = 0x%x\n", notif->status);
#endif
}
@@ -206,7 +239,6 @@ static void iwl_rx_scan_results_notif(struct iwl_priv *priv,
static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
-#ifdef CONFIG_IWLWIFI_DEBUG
struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl_scancomplete_notification *scan_notif = (void *)pkt->u.raw;
@@ -214,29 +246,38 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,
scan_notif->scanned_channels,
scan_notif->tsf_low,
scan_notif->tsf_high, scan_notif->status);
-#endif
/* The HW is no longer scanning */
clear_bit(STATUS_SCAN_HW, &priv->status);
- IWL_DEBUG_INFO(priv, "Scan on %sGHz took %dms\n",
+ IWL_DEBUG_SCAN(priv, "Scan on %sGHz took %dms\n",
(priv->scan_band == IEEE80211_BAND_2GHZ) ? "2.4" : "5.2",
jiffies_to_msecs(elapsed_jiffies
(priv->scan_start, jiffies)));
- /*
- * If a request to abort was given, or the scan did not succeed
- * then we reset the scan state machine and terminate,
- * re-queuing another scan if one has been requested
- */
- if (test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->status))
- IWL_DEBUG_INFO(priv, "Aborted scan completed.\n");
-
- IWL_DEBUG_INFO(priv, "Setting scan to off\n");
-
- clear_bit(STATUS_SCANNING, &priv->status);
-
queue_work(priv->workqueue, &priv->scan_completed);
+
+ if (priv->iw_mode != NL80211_IFTYPE_ADHOC &&
+ priv->cfg->bt_params &&
+ priv->cfg->bt_params->advanced_bt_coexist &&
+ priv->bt_status != scan_notif->bt_status) {
+ if (scan_notif->bt_status) {
+ /* BT on */
+ if (!priv->bt_ch_announce)
+ priv->bt_traffic_load =
+ IWL_BT_COEX_TRAFFIC_LOAD_HIGH;
+ /*
+ * otherwise, no traffic load information provided
+ * no changes made
+ */
+ } else {
+ /* BT off */
+ priv->bt_traffic_load =
+ IWL_BT_COEX_TRAFFIC_LOAD_NONE;
+ }
+ priv->bt_status = scan_notif->bt_status;
+ queue_work(priv->workqueue, &priv->bt_traffic_change_work);
+ }
}
void iwl_setup_rx_scan_handlers(struct iwl_priv *priv)
@@ -268,18 +309,28 @@ u16 iwl_get_passive_dwell_time(struct iwl_priv *priv,
enum ieee80211_band band,
struct ieee80211_vif *vif)
{
+ struct iwl_rxon_context *ctx;
u16 passive = (band == IEEE80211_BAND_2GHZ) ?
IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 :
IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52;
- if (iwl_is_associated(priv)) {
- /* If we're associated, we clamp the maximum passive
- * dwell time to be 98% of the beacon interval (minus
- * 2 * channel tune time) */
- passive = vif ? vif->bss_conf.beacon_int : 0;
- if ((passive > IWL_PASSIVE_DWELL_BASE) || !passive)
- passive = IWL_PASSIVE_DWELL_BASE;
- passive = (passive * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2;
+ if (iwl_is_any_associated(priv)) {
+ /*
+ * If we're associated, we clamp the maximum passive
+ * dwell time to be 98% of the smallest beacon interval
+ * (minus 2 * channel tune time)
+ */
+ for_each_context(priv, ctx) {
+ u16 value;
+
+ if (!iwl_is_associated_ctx(ctx))
+ continue;
+ value = ctx->vif ? ctx->vif->bss_conf.beacon_int : 0;
+ if ((value > IWL_PASSIVE_DWELL_BASE) || !value)
+ value = IWL_PASSIVE_DWELL_BASE;
+ value = (value * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2;
+ passive = min(value, passive);
+ }
}
return passive;
@@ -296,19 +347,53 @@ void iwl_init_scan_params(struct iwl_priv *priv)
}
EXPORT_SYMBOL(iwl_init_scan_params);
-static int iwl_scan_initiate(struct iwl_priv *priv, struct ieee80211_vif *vif)
+static int __must_check iwl_scan_initiate(struct iwl_priv *priv,
+ struct ieee80211_vif *vif,
+ bool internal,
+ enum ieee80211_band band)
{
+ int ret;
+
lockdep_assert_held(&priv->mutex);
- IWL_DEBUG_INFO(priv, "Starting scan...\n");
+ if (WARN_ON(!priv->cfg->ops->utils->request_scan))
+ return -EOPNOTSUPP;
+
+ cancel_delayed_work(&priv->scan_check);
+
+ if (!iwl_is_ready_rf(priv)) {
+ IWL_WARN(priv, "Request scan called when driver not ready.\n");
+ return -EIO;
+ }
+
+ if (test_bit(STATUS_SCAN_HW, &priv->status)) {
+ IWL_DEBUG_SCAN(priv,
+ "Multiple concurrent scan requests in parallel.\n");
+ return -EBUSY;
+ }
+
+ if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
+ IWL_DEBUG_SCAN(priv, "Scan request while abort pending.\n");
+ return -EBUSY;
+ }
+
+ IWL_DEBUG_SCAN(priv, "Starting %sscan...\n",
+ internal ? "internal short " : "");
+
set_bit(STATUS_SCANNING, &priv->status);
- priv->is_internal_short_scan = false;
+ priv->is_internal_short_scan = internal;
priv->scan_start = jiffies;
+ priv->scan_band = band;
- if (WARN_ON(!priv->cfg->ops->utils->request_scan))
- return -EOPNOTSUPP;
+ ret = priv->cfg->ops->utils->request_scan(priv, vif);
+ if (ret) {
+ clear_bit(STATUS_SCANNING, &priv->status);
+ priv->is_internal_short_scan = false;
+ return ret;
+ }
- priv->cfg->ops->utils->request_scan(priv, vif);
+ queue_delayed_work(priv->workqueue, &priv->scan_check,
+ IWL_SCAN_CHECK_WATCHDOG);
return 0;
}
@@ -327,12 +412,6 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw,
mutex_lock(&priv->mutex);
- if (!iwl_is_ready_rf(priv)) {
- ret = -EIO;
- IWL_DEBUG_MAC80211(priv, "leave - not ready or exit pending\n");
- goto out_unlock;
- }
-
if (test_bit(STATUS_SCANNING, &priv->status) &&
!priv->is_internal_short_scan) {
IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
@@ -340,14 +419,7 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw,
goto out_unlock;
}
- if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
- IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n");
- ret = -EAGAIN;
- goto out_unlock;
- }
-
/* mac80211 will only ask for one band at a time */
- priv->scan_band = req->channels[0]->band;
priv->scan_request = req;
priv->scan_vif = vif;
@@ -355,10 +427,12 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw,
* If an internal scan is in progress, just set
* up the scan_request as per above.
*/
- if (priv->is_internal_short_scan)
+ if (priv->is_internal_short_scan) {
+ IWL_DEBUG_SCAN(priv, "SCAN request during internal scan\n");
ret = 0;
- else
- ret = iwl_scan_initiate(priv, vif);
+ } else
+ ret = iwl_scan_initiate(priv, vif, false,
+ req->channels[0]->band);
IWL_DEBUG_MAC80211(priv, "leave\n");
@@ -378,11 +452,13 @@ void iwl_internal_short_hw_scan(struct iwl_priv *priv)
queue_work(priv->workqueue, &priv->start_internal_scan);
}
-void iwl_bg_start_internal_scan(struct work_struct *work)
+static void iwl_bg_start_internal_scan(struct work_struct *work)
{
struct iwl_priv *priv =
container_of(work, struct iwl_priv, start_internal_scan);
+ IWL_DEBUG_SCAN(priv, "Start internal scan\n");
+
mutex_lock(&priv->mutex);
if (priv->is_internal_short_scan == true) {
@@ -390,56 +466,31 @@ void iwl_bg_start_internal_scan(struct work_struct *work)
goto unlock;
}
- if (!iwl_is_ready_rf(priv)) {
- IWL_DEBUG_SCAN(priv, "not ready or exit pending\n");
- goto unlock;
- }
-
if (test_bit(STATUS_SCANNING, &priv->status)) {
IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
goto unlock;
}
- if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
- IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n");
- goto unlock;
- }
-
- priv->scan_band = priv->band;
-
- IWL_DEBUG_SCAN(priv, "Start internal short scan...\n");
- set_bit(STATUS_SCANNING, &priv->status);
- priv->is_internal_short_scan = true;
-
- if (WARN_ON(!priv->cfg->ops->utils->request_scan))
- goto unlock;
-
- priv->cfg->ops->utils->request_scan(priv, NULL);
+ if (iwl_scan_initiate(priv, NULL, true, priv->band))
+ IWL_DEBUG_SCAN(priv, "failed to start internal short scan\n");
unlock:
mutex_unlock(&priv->mutex);
}
-EXPORT_SYMBOL(iwl_bg_start_internal_scan);
-void iwl_bg_scan_check(struct work_struct *data)
+static void iwl_bg_scan_check(struct work_struct *data)
{
struct iwl_priv *priv =
container_of(data, struct iwl_priv, scan_check.work);
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return;
+ IWL_DEBUG_SCAN(priv, "Scan check work\n");
+ /* Since we are here firmware does not finish scan and
+ * most likely is in bad shape, so we don't bother to
+ * send abort command, just force scan complete to mac80211 */
mutex_lock(&priv->mutex);
- if (test_bit(STATUS_SCANNING, &priv->status) &&
- !test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
- IWL_DEBUG_SCAN(priv, "Scan completion watchdog (%dms)\n",
- jiffies_to_msecs(IWL_SCAN_CHECK_WATCHDOG));
-
- if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
- iwl_send_scan_abort(priv);
- }
+ iwl_force_scan_end(priv);
mutex_unlock(&priv->mutex);
}
-EXPORT_SYMBOL(iwl_bg_scan_check);
/**
* iwl_fill_probe_req - fill in all required fields and IE for probe request
@@ -489,73 +540,78 @@ u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
}
EXPORT_SYMBOL(iwl_fill_probe_req);
-void iwl_bg_abort_scan(struct work_struct *work)
+static void iwl_bg_abort_scan(struct work_struct *work)
{
struct iwl_priv *priv = container_of(work, struct iwl_priv, abort_scan);
- if (!test_bit(STATUS_READY, &priv->status) ||
- !test_bit(STATUS_GEO_CONFIGURED, &priv->status))
- return;
-
- cancel_delayed_work(&priv->scan_check);
+ IWL_DEBUG_SCAN(priv, "Abort scan work\n");
+ /* We keep scan_check work queued in case when firmware will not
+ * report back scan completed notification */
mutex_lock(&priv->mutex);
- if (test_bit(STATUS_SCAN_ABORTING, &priv->status))
- iwl_send_scan_abort(priv);
+ iwl_scan_cancel_timeout(priv, 200);
mutex_unlock(&priv->mutex);
}
-EXPORT_SYMBOL(iwl_bg_abort_scan);
-void iwl_bg_scan_completed(struct work_struct *work)
+static void iwl_bg_scan_completed(struct work_struct *work)
{
struct iwl_priv *priv =
container_of(work, struct iwl_priv, scan_completed);
- bool internal = false;
+ bool aborted;
- IWL_DEBUG_SCAN(priv, "SCAN complete scan\n");
+ IWL_DEBUG_SCAN(priv, "Completed %sscan.\n",
+ priv->is_internal_short_scan ? "internal short " : "");
cancel_delayed_work(&priv->scan_check);
mutex_lock(&priv->mutex);
- if (priv->is_internal_short_scan) {
- priv->is_internal_short_scan = false;
- IWL_DEBUG_SCAN(priv, "internal short scan completed\n");
- internal = true;
- } else {
- priv->scan_request = NULL;
- priv->scan_vif = NULL;
+
+ aborted = test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->status);
+ if (aborted)
+ IWL_DEBUG_SCAN(priv, "Aborted scan completed.\n");
+
+ if (!test_and_clear_bit(STATUS_SCANNING, &priv->status)) {
+ IWL_DEBUG_SCAN(priv, "Scan already completed.\n");
+ goto out_settings;
}
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ if (priv->is_internal_short_scan && !aborted) {
+ int err;
+
+ /* Check if mac80211 requested scan during our internal scan */
+ if (priv->scan_request == NULL)
+ goto out_complete;
+
+ /* If so request a new scan */
+ err = iwl_scan_initiate(priv, priv->scan_vif, false,
+ priv->scan_request->channels[0]->band);
+ if (err) {
+ IWL_DEBUG_SCAN(priv,
+ "failed to initiate pending scan: %d\n", err);
+ aborted = true;
+ goto out_complete;
+ }
+
goto out;
+ }
+
+out_complete:
+ iwl_complete_scan(priv, aborted);
- if (internal && priv->scan_request)
- iwl_scan_initiate(priv, priv->scan_vif);
+out_settings:
+ /* Can we still talk to firmware ? */
+ if (!iwl_is_ready_rf(priv))
+ goto out;
/* Since setting the TXPOWER may have been deferred while
* performing the scan, fire one off */
iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
- /*
- * Since setting the RXON may have been deferred while
- * performing the scan, fire one off if needed
- */
- if (memcmp(&priv->active_rxon,
- &priv->staging_rxon, sizeof(priv->staging_rxon)))
- iwlcore_commit_rxon(priv);
+ priv->cfg->ops->utils->post_scan(priv);
out:
mutex_unlock(&priv->mutex);
-
- /*
- * Do not hold mutex here since this will cause mac80211 to call
- * into driver again into functions that will attempt to take
- * mutex.
- */
- if (!internal)
- ieee80211_scan_completed(priv->hw, false);
}
-EXPORT_SYMBOL(iwl_bg_scan_completed);
void iwl_setup_scan_deferred_work(struct iwl_priv *priv)
{
@@ -566,3 +622,16 @@ void iwl_setup_scan_deferred_work(struct iwl_priv *priv)
}
EXPORT_SYMBOL(iwl_setup_scan_deferred_work);
+void iwl_cancel_scan_deferred_work(struct iwl_priv *priv)
+{
+ cancel_work_sync(&priv->start_internal_scan);
+ cancel_work_sync(&priv->abort_scan);
+ cancel_work_sync(&priv->scan_completed);
+
+ if (cancel_delayed_work_sync(&priv->scan_check)) {
+ mutex_lock(&priv->mutex);
+ iwl_force_scan_end(priv);
+ mutex_unlock(&priv->mutex);
+ }
+}
+EXPORT_SYMBOL(iwl_cancel_scan_deferred_work);
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index 7e0829be5e78..7c7f7dcb1b1e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -172,12 +172,14 @@ int iwl_send_add_sta(struct iwl_priv *priv,
EXPORT_SYMBOL(iwl_send_add_sta);
static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
- struct ieee80211_sta_ht_cap *sta_ht_inf)
+ struct ieee80211_sta *sta,
+ struct iwl_rxon_context *ctx)
{
+ struct ieee80211_sta_ht_cap *sta_ht_inf = &sta->ht_cap;
__le32 sta_flags;
u8 mimo_ps_mode;
- if (!sta_ht_inf || !sta_ht_inf->ht_supported)
+ if (!sta || !sta_ht_inf->ht_supported)
goto done;
mimo_ps_mode = (sta_ht_inf->cap & IEEE80211_HT_CAP_SM_PS) >> 2;
@@ -211,7 +213,7 @@ static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
sta_flags |= cpu_to_le32(
(u32)sta_ht_inf->ampdu_density << STA_FLG_AGG_MPDU_DENSITY_POS);
- if (iwl_is_ht40_tx_allowed(priv, sta_ht_inf))
+ if (iwl_is_ht40_tx_allowed(priv, ctx, &sta->ht_cap))
sta_flags |= STA_FLG_HT40_EN_MSK;
else
sta_flags &= ~STA_FLG_HT40_EN_MSK;
@@ -226,9 +228,8 @@ static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
*
* should be called with sta_lock held
*/
-static u8 iwl_prep_station(struct iwl_priv *priv, const u8 *addr,
- bool is_ap,
- struct ieee80211_sta_ht_cap *ht_info)
+u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
+ const u8 *addr, bool is_ap, struct ieee80211_sta *sta)
{
struct iwl_station_entry *station;
int i;
@@ -236,9 +237,9 @@ static u8 iwl_prep_station(struct iwl_priv *priv, const u8 *addr,
u16 rate;
if (is_ap)
- sta_id = IWL_AP_ID;
+ sta_id = ctx->ap_sta_id;
else if (is_broadcast_ether_addr(addr))
- sta_id = priv->hw_params.bcast_sta_id;
+ sta_id = ctx->bcast_sta_id;
else
for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) {
if (!compare_ether_addr(priv->stations[i].sta.sta.addr,
@@ -289,14 +290,22 @@ static u8 iwl_prep_station(struct iwl_priv *priv, const u8 *addr,
memcpy(station->sta.sta.addr, addr, ETH_ALEN);
station->sta.mode = 0;
station->sta.sta.sta_id = sta_id;
- station->sta.station_flags = 0;
+ station->sta.station_flags = ctx->station_flags;
+ station->ctxid = ctx->ctxid;
+
+ if (sta) {
+ struct iwl_station_priv_common *sta_priv;
+
+ sta_priv = (void *)sta->drv_priv;
+ sta_priv->ctx = ctx;
+ }
/*
* OK to call unconditionally, since local stations (IBSS BSSID
- * STA and broadcast STA) pass in a NULL ht_info, and mac80211
+ * STA and broadcast STA) pass in a NULL sta, and mac80211
* doesn't allow HT IBSS.
*/
- iwl_set_ht_add_station(priv, sta_id, ht_info);
+ iwl_set_ht_add_station(priv, sta_id, sta, ctx);
/* 3945 only */
rate = (priv->band == IEEE80211_BAND_5GHZ) ?
@@ -307,16 +316,16 @@ static u8 iwl_prep_station(struct iwl_priv *priv, const u8 *addr,
return sta_id;
}
+EXPORT_SYMBOL_GPL(iwl_prep_station);
#define STA_WAIT_TIMEOUT (HZ/2)
/**
* iwl_add_station_common -
*/
-int iwl_add_station_common(struct iwl_priv *priv, const u8 *addr,
- bool is_ap,
- struct ieee80211_sta_ht_cap *ht_info,
- u8 *sta_id_r)
+int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
+ const u8 *addr, bool is_ap,
+ struct ieee80211_sta *sta, u8 *sta_id_r)
{
unsigned long flags_spin;
int ret = 0;
@@ -325,7 +334,7 @@ int iwl_add_station_common(struct iwl_priv *priv, const u8 *addr,
*sta_id_r = 0;
spin_lock_irqsave(&priv->sta_lock, flags_spin);
- sta_id = iwl_prep_station(priv, addr, is_ap, ht_info);
+ sta_id = iwl_prep_station(priv, ctx, addr, is_ap, sta);
if (sta_id == IWL_INVALID_STATION) {
IWL_ERR(priv, "Unable to prepare station %pM for addition\n",
addr);
@@ -372,111 +381,6 @@ int iwl_add_station_common(struct iwl_priv *priv, const u8 *addr,
}
EXPORT_SYMBOL(iwl_add_station_common);
-static struct iwl_link_quality_cmd *iwl_sta_alloc_lq(struct iwl_priv *priv,
- u8 sta_id)
-{
- int i, r;
- struct iwl_link_quality_cmd *link_cmd;
- u32 rate_flags;
-
- link_cmd = kzalloc(sizeof(struct iwl_link_quality_cmd), GFP_KERNEL);
- if (!link_cmd) {
- IWL_ERR(priv, "Unable to allocate memory for LQ cmd.\n");
- return NULL;
- }
- /* Set up the rate scaling to start at selected rate, fall back
- * all the way down to 1M in IEEE order, and then spin on 1M */
- if (priv->band == IEEE80211_BAND_5GHZ)
- r = IWL_RATE_6M_INDEX;
- else
- r = IWL_RATE_1M_INDEX;
-
- for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) {
- rate_flags = 0;
- if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE)
- rate_flags |= RATE_MCS_CCK_MSK;
-
- rate_flags |= first_antenna(priv->hw_params.valid_tx_ant) <<
- RATE_MCS_ANT_POS;
-
- link_cmd->rs_table[i].rate_n_flags =
- iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags);
- r = iwl_get_prev_ieee_rate(r);
- }
-
- link_cmd->general_params.single_stream_ant_msk =
- first_antenna(priv->hw_params.valid_tx_ant);
-
- link_cmd->general_params.dual_stream_ant_msk =
- priv->hw_params.valid_tx_ant &
- ~first_antenna(priv->hw_params.valid_tx_ant);
- if (!link_cmd->general_params.dual_stream_ant_msk) {
- link_cmd->general_params.dual_stream_ant_msk = ANT_AB;
- } else if (num_of_ant(priv->hw_params.valid_tx_ant) == 2) {
- link_cmd->general_params.dual_stream_ant_msk =
- priv->hw_params.valid_tx_ant;
- }
-
- link_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF;
- link_cmd->agg_params.agg_time_limit =
- cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF);
-
- link_cmd->sta_id = sta_id;
-
- return link_cmd;
-}
-
-/*
- * iwl_add_bssid_station - Add the special IBSS BSSID station
- *
- * Function sleeps.
- */
-int iwl_add_bssid_station(struct iwl_priv *priv, const u8 *addr, bool init_rs,
- u8 *sta_id_r)
-{
- int ret;
- u8 sta_id;
- struct iwl_link_quality_cmd *link_cmd;
- unsigned long flags;
-
- if (sta_id_r)
- *sta_id_r = IWL_INVALID_STATION;
-
- ret = iwl_add_station_common(priv, addr, 0, NULL, &sta_id);
- if (ret) {
- IWL_ERR(priv, "Unable to add station %pM\n", addr);
- return ret;
- }
-
- if (sta_id_r)
- *sta_id_r = sta_id;
-
- spin_lock_irqsave(&priv->sta_lock, flags);
- priv->stations[sta_id].used |= IWL_STA_LOCAL;
- spin_unlock_irqrestore(&priv->sta_lock, flags);
-
- if (init_rs) {
- /* Set up default rate scaling table in device's station table */
- link_cmd = iwl_sta_alloc_lq(priv, sta_id);
- if (!link_cmd) {
- IWL_ERR(priv, "Unable to initialize rate scaling for station %pM.\n",
- addr);
- return -ENOMEM;
- }
-
- ret = iwl_send_lq_cmd(priv, link_cmd, CMD_SYNC, true);
- if (ret)
- IWL_ERR(priv, "Link quality command failed (%d)\n", ret);
-
- spin_lock_irqsave(&priv->sta_lock, flags);
- priv->stations[sta_id].lq = link_cmd;
- spin_unlock_irqrestore(&priv->sta_lock, flags);
- }
-
- return 0;
-}
-EXPORT_SYMBOL(iwl_add_bssid_station);
-
/**
* iwl_sta_ucode_deactivate - deactivate ucode status for a station
*
@@ -616,7 +520,8 @@ EXPORT_SYMBOL_GPL(iwl_remove_station);
* other than explicit station management would cause this in
* the ucode, e.g. unassociated RXON.
*/
-void iwl_clear_ucode_stations(struct iwl_priv *priv)
+void iwl_clear_ucode_stations(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx)
{
int i;
unsigned long flags_spin;
@@ -626,6 +531,9 @@ void iwl_clear_ucode_stations(struct iwl_priv *priv)
spin_lock_irqsave(&priv->sta_lock, flags_spin);
for (i = 0; i < priv->hw_params.max_stations; i++) {
+ if (ctx && ctx->ctxid != priv->stations[i].ctxid)
+ continue;
+
if (priv->stations[i].used & IWL_STA_UCODE_ACTIVE) {
IWL_DEBUG_INFO(priv, "Clearing ucode active for station %d\n", i);
priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE;
@@ -647,7 +555,7 @@ EXPORT_SYMBOL(iwl_clear_ucode_stations);
*
* Function sleeps.
*/
-void iwl_restore_stations(struct iwl_priv *priv)
+void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
{
struct iwl_addsta_cmd sta_cmd;
struct iwl_link_quality_cmd lq;
@@ -665,6 +573,8 @@ void iwl_restore_stations(struct iwl_priv *priv)
IWL_DEBUG_ASSOC(priv, "Restoring all known stations ... start.\n");
spin_lock_irqsave(&priv->sta_lock, flags_spin);
for (i = 0; i < priv->hw_params.max_stations; i++) {
+ if (ctx->ctxid != priv->stations[i].ctxid)
+ continue;
if ((priv->stations[i].used & IWL_STA_DRIVER_ACTIVE) &&
!(priv->stations[i].used & IWL_STA_UCODE_ACTIVE)) {
IWL_DEBUG_ASSOC(priv, "Restoring sta %pM\n",
@@ -700,7 +610,7 @@ void iwl_restore_stations(struct iwl_priv *priv)
* current LQ command
*/
if (send_lq)
- iwl_send_lq_cmd(priv, &lq, CMD_SYNC, true);
+ iwl_send_lq_cmd(priv, ctx, &lq, CMD_SYNC, true);
spin_lock_irqsave(&priv->sta_lock, flags_spin);
priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS;
}
@@ -718,7 +628,7 @@ int iwl_get_free_ucode_key_index(struct iwl_priv *priv)
{
int i;
- for (i = 0; i < STA_KEY_MAX_NUM; i++)
+ for (i = 0; i < priv->sta_key_max_num; i++)
if (!test_and_set_bit(i, &priv->ucode_key_table))
return i;
@@ -726,393 +636,25 @@ int iwl_get_free_ucode_key_index(struct iwl_priv *priv)
}
EXPORT_SYMBOL(iwl_get_free_ucode_key_index);
-static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty)
-{
- int i, not_empty = 0;
- u8 buff[sizeof(struct iwl_wep_cmd) +
- sizeof(struct iwl_wep_key) * WEP_KEYS_MAX];
- struct iwl_wep_cmd *wep_cmd = (struct iwl_wep_cmd *)buff;
- size_t cmd_size = sizeof(struct iwl_wep_cmd);
- struct iwl_host_cmd cmd = {
- .id = REPLY_WEPKEY,
- .data = wep_cmd,
- .flags = CMD_SYNC,
- };
-
- might_sleep();
-
- memset(wep_cmd, 0, cmd_size +
- (sizeof(struct iwl_wep_key) * WEP_KEYS_MAX));
-
- for (i = 0; i < WEP_KEYS_MAX ; i++) {
- wep_cmd->key[i].key_index = i;
- if (priv->wep_keys[i].key_size) {
- wep_cmd->key[i].key_offset = i;
- not_empty = 1;
- } else {
- wep_cmd->key[i].key_offset = WEP_INVALID_OFFSET;
- }
-
- wep_cmd->key[i].key_size = priv->wep_keys[i].key_size;
- memcpy(&wep_cmd->key[i].key[3], priv->wep_keys[i].key,
- priv->wep_keys[i].key_size);
- }
-
- wep_cmd->global_key_type = WEP_KEY_WEP_TYPE;
- wep_cmd->num_keys = WEP_KEYS_MAX;
-
- cmd_size += sizeof(struct iwl_wep_key) * WEP_KEYS_MAX;
-
- cmd.len = cmd_size;
-
- if (not_empty || send_if_empty)
- return iwl_send_cmd(priv, &cmd);
- else
- return 0;
-}
-
-int iwl_restore_default_wep_keys(struct iwl_priv *priv)
-{
- lockdep_assert_held(&priv->mutex);
-
- return iwl_send_static_wepkey_cmd(priv, 0);
-}
-EXPORT_SYMBOL(iwl_restore_default_wep_keys);
-
-int iwl_remove_default_wep_key(struct iwl_priv *priv,
- struct ieee80211_key_conf *keyconf)
-{
- int ret;
-
- lockdep_assert_held(&priv->mutex);
-
- IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n",
- keyconf->keyidx);
-
- memset(&priv->wep_keys[keyconf->keyidx], 0, sizeof(priv->wep_keys[0]));
- if (iwl_is_rfkill(priv)) {
- IWL_DEBUG_WEP(priv, "Not sending REPLY_WEPKEY command due to RFKILL.\n");
- /* but keys in device are clear anyway so return success */
- return 0;
- }
- ret = iwl_send_static_wepkey_cmd(priv, 1);
- IWL_DEBUG_WEP(priv, "Remove default WEP key: idx=%d ret=%d\n",
- keyconf->keyidx, ret);
-
- return ret;
-}
-EXPORT_SYMBOL(iwl_remove_default_wep_key);
-
-int iwl_set_default_wep_key(struct iwl_priv *priv,
- struct ieee80211_key_conf *keyconf)
+void iwl_dealloc_bcast_stations(struct iwl_priv *priv)
{
- int ret;
-
- lockdep_assert_held(&priv->mutex);
-
- if (keyconf->keylen != WEP_KEY_LEN_128 &&
- keyconf->keylen != WEP_KEY_LEN_64) {
- IWL_DEBUG_WEP(priv, "Bad WEP key length %d\n", keyconf->keylen);
- return -EINVAL;
- }
-
- keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
- keyconf->hw_key_idx = HW_KEY_DEFAULT;
- priv->stations[IWL_AP_ID].keyinfo.alg = ALG_WEP;
-
- priv->wep_keys[keyconf->keyidx].key_size = keyconf->keylen;
- memcpy(&priv->wep_keys[keyconf->keyidx].key, &keyconf->key,
- keyconf->keylen);
-
- ret = iwl_send_static_wepkey_cmd(priv, 0);
- IWL_DEBUG_WEP(priv, "Set default WEP key: len=%d idx=%d ret=%d\n",
- keyconf->keylen, keyconf->keyidx, ret);
-
- return ret;
-}
-EXPORT_SYMBOL(iwl_set_default_wep_key);
-
-static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv,
- struct ieee80211_key_conf *keyconf,
- u8 sta_id)
-{
- unsigned long flags;
- __le16 key_flags = 0;
- struct iwl_addsta_cmd sta_cmd;
-
- lockdep_assert_held(&priv->mutex);
-
- keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
-
- key_flags |= (STA_KEY_FLG_WEP | STA_KEY_FLG_MAP_KEY_MSK);
- key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
- key_flags &= ~STA_KEY_FLG_INVALID;
-
- if (keyconf->keylen == WEP_KEY_LEN_128)
- key_flags |= STA_KEY_FLG_KEY_SIZE_MSK;
-
- if (sta_id == priv->hw_params.bcast_sta_id)
- key_flags |= STA_KEY_MULTICAST_MSK;
-
- spin_lock_irqsave(&priv->sta_lock, flags);
-
- priv->stations[sta_id].keyinfo.alg = keyconf->alg;
- priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;
- priv->stations[sta_id].keyinfo.keyidx = keyconf->keyidx;
-
- memcpy(priv->stations[sta_id].keyinfo.key,
- keyconf->key, keyconf->keylen);
-
- memcpy(&priv->stations[sta_id].sta.key.key[3],
- keyconf->key, keyconf->keylen);
-
- if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
- == STA_KEY_FLG_NO_ENC)
- priv->stations[sta_id].sta.key.key_offset =
- iwl_get_free_ucode_key_index(priv);
- /* else, we are overriding an existing key => no need to allocated room
- * in uCode. */
-
- WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
- "no space for a new key");
-
- priv->stations[sta_id].sta.key.key_flags = key_flags;
- priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
- priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
-
- memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
- spin_unlock_irqrestore(&priv->sta_lock, flags);
-
- return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
-}
-
-static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
- struct ieee80211_key_conf *keyconf,
- u8 sta_id)
-{
- unsigned long flags;
- __le16 key_flags = 0;
- struct iwl_addsta_cmd sta_cmd;
-
- lockdep_assert_held(&priv->mutex);
-
- key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK);
- key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
- key_flags &= ~STA_KEY_FLG_INVALID;
-
- if (sta_id == priv->hw_params.bcast_sta_id)
- key_flags |= STA_KEY_MULTICAST_MSK;
-
- keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
-
- spin_lock_irqsave(&priv->sta_lock, flags);
- priv->stations[sta_id].keyinfo.alg = keyconf->alg;
- priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;
-
- memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key,
- keyconf->keylen);
-
- memcpy(priv->stations[sta_id].sta.key.key, keyconf->key,
- keyconf->keylen);
-
- if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
- == STA_KEY_FLG_NO_ENC)
- priv->stations[sta_id].sta.key.key_offset =
- iwl_get_free_ucode_key_index(priv);
- /* else, we are overriding an existing key => no need to allocated room
- * in uCode. */
-
- WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
- "no space for a new key");
-
- priv->stations[sta_id].sta.key.key_flags = key_flags;
- priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
- priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
-
- memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
- spin_unlock_irqrestore(&priv->sta_lock, flags);
-
- return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
-}
-
-static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv,
- struct ieee80211_key_conf *keyconf,
- u8 sta_id)
-{
- unsigned long flags;
- int ret = 0;
- __le16 key_flags = 0;
-
- key_flags |= (STA_KEY_FLG_TKIP | STA_KEY_FLG_MAP_KEY_MSK);
- key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
- key_flags &= ~STA_KEY_FLG_INVALID;
-
- if (sta_id == priv->hw_params.bcast_sta_id)
- key_flags |= STA_KEY_MULTICAST_MSK;
-
- keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
- keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
-
- spin_lock_irqsave(&priv->sta_lock, flags);
-
- priv->stations[sta_id].keyinfo.alg = keyconf->alg;
- priv->stations[sta_id].keyinfo.keylen = 16;
-
- if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
- == STA_KEY_FLG_NO_ENC)
- priv->stations[sta_id].sta.key.key_offset =
- iwl_get_free_ucode_key_index(priv);
- /* else, we are overriding an existing key => no need to allocated room
- * in uCode. */
-
- WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
- "no space for a new key");
-
- priv->stations[sta_id].sta.key.key_flags = key_flags;
-
-
- /* This copy is acutally not needed: we get the key with each TX */
- memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, 16);
-
- memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, 16);
-
- spin_unlock_irqrestore(&priv->sta_lock, flags);
-
- return ret;
-}
-
-void iwl_update_tkip_key(struct iwl_priv *priv,
- struct ieee80211_key_conf *keyconf,
- struct ieee80211_sta *sta, u32 iv32, u16 *phase1key)
-{
- u8 sta_id;
unsigned long flags;
int i;
- if (iwl_scan_cancel(priv)) {
- /* cancel scan failed, just live w/ bad key and rely
- briefly on SW decryption */
- return;
- }
-
- sta_id = iwl_sta_id_or_broadcast(priv, sta);
- if (sta_id == IWL_INVALID_STATION)
- return;
-
spin_lock_irqsave(&priv->sta_lock, flags);
+ for (i = 0; i < priv->hw_params.max_stations; i++) {
+ if (!(priv->stations[i].used & IWL_STA_BCAST))
+ continue;
- priv->stations[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32;
-
- for (i = 0; i < 5; i++)
- priv->stations[sta_id].sta.key.tkip_rx_ttak[i] =
- cpu_to_le16(phase1key[i]);
-
- priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
- priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
-
- iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
-
- spin_unlock_irqrestore(&priv->sta_lock, flags);
-
-}
-EXPORT_SYMBOL(iwl_update_tkip_key);
-
-int iwl_remove_dynamic_key(struct iwl_priv *priv,
- struct ieee80211_key_conf *keyconf,
- u8 sta_id)
-{
- unsigned long flags;
- u16 key_flags;
- u8 keyidx;
- struct iwl_addsta_cmd sta_cmd;
-
- lockdep_assert_held(&priv->mutex);
-
- priv->key_mapping_key--;
-
- spin_lock_irqsave(&priv->sta_lock, flags);
- key_flags = le16_to_cpu(priv->stations[sta_id].sta.key.key_flags);
- keyidx = (key_flags >> STA_KEY_FLG_KEYID_POS) & 0x3;
-
- IWL_DEBUG_WEP(priv, "Remove dynamic key: idx=%d sta=%d\n",
- keyconf->keyidx, sta_id);
-
- if (keyconf->keyidx != keyidx) {
- /* We need to remove a key with index different that the one
- * in the uCode. This means that the key we need to remove has
- * been replaced by another one with different index.
- * Don't do anything and return ok
- */
- spin_unlock_irqrestore(&priv->sta_lock, flags);
- return 0;
- }
-
- if (priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET) {
- IWL_WARN(priv, "Removing wrong key %d 0x%x\n",
- keyconf->keyidx, key_flags);
- spin_unlock_irqrestore(&priv->sta_lock, flags);
- return 0;
- }
-
- if (!test_and_clear_bit(priv->stations[sta_id].sta.key.key_offset,
- &priv->ucode_key_table))
- IWL_ERR(priv, "index %d not used in uCode key table.\n",
- priv->stations[sta_id].sta.key.key_offset);
- memset(&priv->stations[sta_id].keyinfo, 0,
- sizeof(struct iwl_hw_key));
- memset(&priv->stations[sta_id].sta.key, 0,
- sizeof(struct iwl4965_keyinfo));
- priv->stations[sta_id].sta.key.key_flags =
- STA_KEY_FLG_NO_ENC | STA_KEY_FLG_INVALID;
- priv->stations[sta_id].sta.key.key_offset = WEP_INVALID_OFFSET;
- priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
- priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
-
- if (iwl_is_rfkill(priv)) {
- IWL_DEBUG_WEP(priv, "Not sending REPLY_ADD_STA command because RFKILL enabled.\n");
- spin_unlock_irqrestore(&priv->sta_lock, flags);
- return 0;
+ priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE;
+ priv->num_stations--;
+ BUG_ON(priv->num_stations < 0);
+ kfree(priv->stations[i].lq);
+ priv->stations[i].lq = NULL;
}
- memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
spin_unlock_irqrestore(&priv->sta_lock, flags);
-
- return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
-}
-EXPORT_SYMBOL(iwl_remove_dynamic_key);
-
-int iwl_set_dynamic_key(struct iwl_priv *priv,
- struct ieee80211_key_conf *keyconf, u8 sta_id)
-{
- int ret;
-
- lockdep_assert_held(&priv->mutex);
-
- priv->key_mapping_key++;
- keyconf->hw_key_idx = HW_KEY_DYNAMIC;
-
- switch (keyconf->alg) {
- case ALG_CCMP:
- ret = iwl_set_ccmp_dynamic_key_info(priv, keyconf, sta_id);
- break;
- case ALG_TKIP:
- ret = iwl_set_tkip_dynamic_key_info(priv, keyconf, sta_id);
- break;
- case ALG_WEP:
- ret = iwl_set_wep_dynamic_key_info(priv, keyconf, sta_id);
- break;
- default:
- IWL_ERR(priv,
- "Unknown alg: %s alg = %d\n", __func__, keyconf->alg);
- ret = -EINVAL;
- }
-
- IWL_DEBUG_WEP(priv, "Set dynamic key: alg= %d len=%d idx=%d sta=%d ret=%d\n",
- keyconf->alg, keyconf->keylen, keyconf->keyidx,
- sta_id, ret);
-
- return ret;
}
-EXPORT_SYMBOL(iwl_set_dynamic_key);
+EXPORT_SYMBOL_GPL(iwl_dealloc_bcast_stations);
#ifdef CONFIG_IWLWIFI_DEBUG
static void iwl_dump_lq_cmd(struct iwl_priv *priv,
@@ -1147,16 +689,16 @@ static inline void iwl_dump_lq_cmd(struct iwl_priv *priv,
* RXON flags are updated and when LQ command is updated.
*/
static bool is_lq_table_valid(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx,
struct iwl_link_quality_cmd *lq)
{
int i;
- struct iwl_ht_config *ht_conf = &priv->current_ht_config;
- if (ht_conf->is_ht)
+ if (ctx->ht.enabled)
return true;
IWL_DEBUG_INFO(priv, "Channel %u is not an HT channel\n",
- priv->active_rxon.channel);
+ ctx->active.channel);
for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) {
if (le32_to_cpu(lq->rs_table[i].rate_n_flags) & RATE_MCS_HT_MSK) {
IWL_DEBUG_INFO(priv,
@@ -1178,7 +720,7 @@ static bool is_lq_table_valid(struct iwl_priv *priv,
* this case to clear the state indicating that station creation is in
* progress.
*/
-int iwl_send_lq_cmd(struct iwl_priv *priv,
+int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
struct iwl_link_quality_cmd *lq, u8 flags, bool init)
{
int ret = 0;
@@ -1197,7 +739,7 @@ int iwl_send_lq_cmd(struct iwl_priv *priv,
iwl_dump_lq_cmd(priv, lq);
BUG_ON(init && (cmd.flags & CMD_ASYNC));
- if (is_lq_table_valid(priv, lq))
+ if (is_lq_table_valid(priv, ctx, lq))
ret = iwl_send_cmd(priv, &cmd);
else
ret = -EINVAL;
@@ -1216,207 +758,6 @@ int iwl_send_lq_cmd(struct iwl_priv *priv,
}
EXPORT_SYMBOL(iwl_send_lq_cmd);
-/**
- * iwl_alloc_bcast_station - add broadcast station into driver's station table.
- *
- * This adds the broadcast station into the driver's station table
- * and marks it driver active, so that it will be restored to the
- * device at the next best time.
- */
-int iwl_alloc_bcast_station(struct iwl_priv *priv, bool init_lq)
-{
- struct iwl_link_quality_cmd *link_cmd;
- unsigned long flags;
- u8 sta_id;
-
- spin_lock_irqsave(&priv->sta_lock, flags);
- sta_id = iwl_prep_station(priv, iwl_bcast_addr, false, NULL);
- if (sta_id == IWL_INVALID_STATION) {
- IWL_ERR(priv, "Unable to prepare broadcast station\n");
- spin_unlock_irqrestore(&priv->sta_lock, flags);
-
- return -EINVAL;
- }
-
- priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE;
- priv->stations[sta_id].used |= IWL_STA_BCAST;
- spin_unlock_irqrestore(&priv->sta_lock, flags);
-
- if (init_lq) {
- link_cmd = iwl_sta_alloc_lq(priv, sta_id);
- if (!link_cmd) {
- IWL_ERR(priv,
- "Unable to initialize rate scaling for bcast station.\n");
- return -ENOMEM;
- }
-
- spin_lock_irqsave(&priv->sta_lock, flags);
- priv->stations[sta_id].lq = link_cmd;
- spin_unlock_irqrestore(&priv->sta_lock, flags);
- }
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(iwl_alloc_bcast_station);
-
-/**
- * iwl_update_bcast_station - update broadcast station's LQ command
- *
- * Only used by iwlagn. Placed here to have all bcast station management
- * code together.
- */
-int iwl_update_bcast_station(struct iwl_priv *priv)
-{
- unsigned long flags;
- struct iwl_link_quality_cmd *link_cmd;
- u8 sta_id = priv->hw_params.bcast_sta_id;
-
- link_cmd = iwl_sta_alloc_lq(priv, sta_id);
- if (!link_cmd) {
- IWL_ERR(priv, "Unable to initialize rate scaling for bcast station.\n");
- return -ENOMEM;
- }
-
- spin_lock_irqsave(&priv->sta_lock, flags);
- if (priv->stations[sta_id].lq)
- kfree(priv->stations[sta_id].lq);
- else
- IWL_DEBUG_INFO(priv, "Bcast station rate scaling has not been initialized yet.\n");
- priv->stations[sta_id].lq = link_cmd;
- spin_unlock_irqrestore(&priv->sta_lock, flags);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(iwl_update_bcast_station);
-
-void iwl_dealloc_bcast_station(struct iwl_priv *priv)
-{
- unsigned long flags;
- int i;
-
- spin_lock_irqsave(&priv->sta_lock, flags);
- for (i = 0; i < priv->hw_params.max_stations; i++) {
- if (!(priv->stations[i].used & IWL_STA_BCAST))
- continue;
-
- priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE;
- priv->num_stations--;
- BUG_ON(priv->num_stations < 0);
- kfree(priv->stations[i].lq);
- priv->stations[i].lq = NULL;
- }
- spin_unlock_irqrestore(&priv->sta_lock, flags);
-}
-EXPORT_SYMBOL_GPL(iwl_dealloc_bcast_station);
-
-/**
- * iwl_sta_tx_modify_enable_tid - Enable Tx for this TID in station table
- */
-int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid)
-{
- unsigned long flags;
- struct iwl_addsta_cmd sta_cmd;
-
- lockdep_assert_held(&priv->mutex);
-
- /* Remove "disable" flag, to enable Tx for this TID */
- spin_lock_irqsave(&priv->sta_lock, flags);
- priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_TID_DISABLE_TX;
- priv->stations[sta_id].sta.tid_disable_tx &= cpu_to_le16(~(1 << tid));
- priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
- memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
- spin_unlock_irqrestore(&priv->sta_lock, flags);
-
- return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
-}
-EXPORT_SYMBOL(iwl_sta_tx_modify_enable_tid);
-
-int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
- int tid, u16 ssn)
-{
- unsigned long flags;
- int sta_id;
- struct iwl_addsta_cmd sta_cmd;
-
- lockdep_assert_held(&priv->mutex);
-
- sta_id = iwl_sta_id(sta);
- if (sta_id == IWL_INVALID_STATION)
- return -ENXIO;
-
- spin_lock_irqsave(&priv->sta_lock, flags);
- priv->stations[sta_id].sta.station_flags_msk = 0;
- priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_ADDBA_TID_MSK;
- priv->stations[sta_id].sta.add_immediate_ba_tid = (u8)tid;
- priv->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn);
- priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
- memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
- spin_unlock_irqrestore(&priv->sta_lock, flags);
-
- return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
-}
-EXPORT_SYMBOL(iwl_sta_rx_agg_start);
-
-int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
- int tid)
-{
- unsigned long flags;
- int sta_id;
- struct iwl_addsta_cmd sta_cmd;
-
- lockdep_assert_held(&priv->mutex);
-
- sta_id = iwl_sta_id(sta);
- if (sta_id == IWL_INVALID_STATION) {
- IWL_ERR(priv, "Invalid station for AGG tid %d\n", tid);
- return -ENXIO;
- }
-
- spin_lock_irqsave(&priv->sta_lock, flags);
- priv->stations[sta_id].sta.station_flags_msk = 0;
- priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK;
- priv->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid;
- priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
- memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
- spin_unlock_irqrestore(&priv->sta_lock, flags);
-
- return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
-}
-EXPORT_SYMBOL(iwl_sta_rx_agg_stop);
-
-void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&priv->sta_lock, flags);
- priv->stations[sta_id].sta.station_flags &= ~STA_FLG_PWR_SAVE_MSK;
- priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK;
- priv->stations[sta_id].sta.sta.modify_mask = 0;
- priv->stations[sta_id].sta.sleep_tx_count = 0;
- priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
- iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
- spin_unlock_irqrestore(&priv->sta_lock, flags);
-
-}
-EXPORT_SYMBOL(iwl_sta_modify_ps_wake);
-
-void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&priv->sta_lock, flags);
- priv->stations[sta_id].sta.station_flags |= STA_FLG_PWR_SAVE_MSK;
- priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK;
- priv->stations[sta_id].sta.sta.modify_mask =
- STA_MODIFY_SLEEP_TX_COUNT_MSK;
- priv->stations[sta_id].sta.sleep_tx_count = cpu_to_le16(cnt);
- priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
- iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
- spin_unlock_irqrestore(&priv->sta_lock, flags);
-
-}
-EXPORT_SYMBOL(iwl_sta_modify_sleep_tx_count);
-
int iwl_mac_sta_remove(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h
index d38a350ba0bd..06475872eee4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.h
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.h
@@ -43,44 +43,26 @@
#define IWL_STA_BCAST BIT(4) /* this station is the special bcast station */
-int iwl_remove_default_wep_key(struct iwl_priv *priv,
- struct ieee80211_key_conf *key);
-int iwl_set_default_wep_key(struct iwl_priv *priv,
- struct ieee80211_key_conf *key);
-int iwl_restore_default_wep_keys(struct iwl_priv *priv);
-int iwl_set_dynamic_key(struct iwl_priv *priv,
- struct ieee80211_key_conf *key, u8 sta_id);
-int iwl_remove_dynamic_key(struct iwl_priv *priv,
- struct ieee80211_key_conf *key, u8 sta_id);
-void iwl_update_tkip_key(struct iwl_priv *priv,
- struct ieee80211_key_conf *keyconf,
- struct ieee80211_sta *sta, u32 iv32, u16 *phase1key);
-
-void iwl_restore_stations(struct iwl_priv *priv);
-void iwl_clear_ucode_stations(struct iwl_priv *priv);
-int iwl_alloc_bcast_station(struct iwl_priv *priv, bool init_lq);
-void iwl_dealloc_bcast_station(struct iwl_priv *priv);
-int iwl_update_bcast_station(struct iwl_priv *priv);
+void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
+void iwl_clear_ucode_stations(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx);
+void iwl_dealloc_bcast_stations(struct iwl_priv *priv);
int iwl_get_free_ucode_key_index(struct iwl_priv *priv);
int iwl_send_add_sta(struct iwl_priv *priv,
struct iwl_addsta_cmd *sta, u8 flags);
-int iwl_add_bssid_station(struct iwl_priv *priv, const u8 *addr, bool init_rs,
- u8 *sta_id_r);
-int iwl_add_station_common(struct iwl_priv *priv, const u8 *addr,
- bool is_ap,
- struct ieee80211_sta_ht_cap *ht_info,
- u8 *sta_id_r);
+int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
+ const u8 *addr, bool is_ap,
+ struct ieee80211_sta *sta, u8 *sta_id_r);
int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
const u8 *addr);
int iwl_mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
-int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid);
-int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
- int tid, u16 ssn);
-int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
- int tid);
-void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id);
-void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt);
+
+u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
+ const u8 *addr, bool is_ap, struct ieee80211_sta *sta);
+
+int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
+ struct iwl_link_quality_cmd *lq, u8 flags, bool init);
/**
* iwl_clear_driver_stations - clear knowledge of all stations from driver
@@ -94,20 +76,25 @@ void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt);
static inline void iwl_clear_driver_stations(struct iwl_priv *priv)
{
unsigned long flags;
+ struct iwl_rxon_context *ctx;
spin_lock_irqsave(&priv->sta_lock, flags);
memset(priv->stations, 0, sizeof(priv->stations));
priv->num_stations = 0;
- /*
- * Remove all key information that is not stored as part of station
- * information since mac80211 may not have had a
- * chance to remove all the keys. When device is reconfigured by
- * mac80211 after an error all keys will be reconfigured.
- */
priv->ucode_key_table = 0;
- priv->key_mapping_key = 0;
- memset(priv->wep_keys, 0, sizeof(priv->wep_keys));
+
+ for_each_context(priv, ctx) {
+ /*
+ * Remove all key information that is not stored as part
+ * of station information since mac80211 may not have had
+ * a chance to remove all the keys. When device is
+ * reconfigured by mac80211 after an error all keys will
+ * be reconfigured.
+ */
+ memset(ctx->wep_keys, 0, sizeof(ctx->wep_keys));
+ ctx->key_mapping_keys = 0;
+ }
spin_unlock_irqrestore(&priv->sta_lock, flags);
}
@@ -123,6 +110,7 @@ static inline int iwl_sta_id(struct ieee80211_sta *sta)
/**
* iwl_sta_id_or_broadcast - return sta_id or broadcast sta
* @priv: iwl priv
+ * @context: the current context
* @sta: mac80211 station
*
* In certain circumstances mac80211 passes a station pointer
@@ -131,12 +119,13 @@ static inline int iwl_sta_id(struct ieee80211_sta *sta)
* inline wraps that pattern.
*/
static inline int iwl_sta_id_or_broadcast(struct iwl_priv *priv,
+ struct iwl_rxon_context *context,
struct ieee80211_sta *sta)
{
int sta_id;
if (!sta)
- return priv->hw_params.bcast_sta_id;
+ return context->bcast_sta_id;
sta_id = iwl_sta_id(sta);
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index a81989c06983..7261ee49f282 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -134,7 +134,7 @@ EXPORT_SYMBOL(iwl_tx_queue_free);
*/
void iwl_cmd_queue_free(struct iwl_priv *priv)
{
- struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM];
+ struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
struct iwl_queue *q = &txq->q;
struct device *dev = &priv->pci_dev->dev;
int i;
@@ -271,7 +271,7 @@ static int iwl_tx_queue_alloc(struct iwl_priv *priv,
/* Driver private data, only for Tx (not command) queues,
* not shared with device. */
- if (id != IWL_CMD_QUEUE_NUM) {
+ if (id != priv->cmd_queue) {
txq->txb = kzalloc(sizeof(txq->txb[0]) *
TFD_QUEUE_SIZE_MAX, GFP_KERNEL);
if (!txq->txb) {
@@ -314,13 +314,13 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
/*
* Alloc buffer array for commands (Tx or other types of commands).
- * For the command queue (#4), allocate command space + one big
+ * For the command queue (#4/#9), allocate command space + one big
* command for scan, since scan command is very huge; the system will
* not have two scans at the same time, so only one is needed.
* For normal Tx queues (all other queues), no super-size command
* space is needed.
*/
- if (txq_id == IWL_CMD_QUEUE_NUM)
+ if (txq_id == priv->cmd_queue)
actual_slots++;
txq->meta = kzalloc(sizeof(struct iwl_cmd_meta) * actual_slots,
@@ -355,7 +355,7 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
* need an swq_id so don't set one to catch errors, all others can
* be set up to the identity mapping.
*/
- if (txq_id != IWL_CMD_QUEUE_NUM)
+ if (txq_id != priv->cmd_queue)
txq->swq_id = txq_id;
/* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise
@@ -385,7 +385,7 @@ void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq,
{
int actual_slots = slots_num;
- if (txq_id == IWL_CMD_QUEUE_NUM)
+ if (txq_id == priv->cmd_queue)
actual_slots++;
memset(txq->meta, 0, sizeof(struct iwl_cmd_meta) * actual_slots);
@@ -413,7 +413,7 @@ EXPORT_SYMBOL(iwl_tx_queue_reset);
*/
int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
{
- struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM];
+ struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
struct iwl_queue *q = &txq->q;
struct iwl_device_cmd *out_cmd;
struct iwl_cmd_meta *out_meta;
@@ -422,6 +422,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
int len;
u32 idx;
u16 fix_size;
+ bool is_ct_kill = false;
cmd->len = priv->cfg->ops->utils->get_hcmd_size(cmd->id, cmd->len);
fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr));
@@ -443,9 +444,11 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) {
IWL_ERR(priv, "No space in command queue\n");
- if (iwl_within_ct_kill_margin(priv))
- iwl_tt_enter_ct_kill(priv);
- else {
+ if (priv->cfg->ops->lib->tt_ops.ct_kill_check) {
+ is_ct_kill =
+ priv->cfg->ops->lib->tt_ops.ct_kill_check(priv);
+ }
+ if (!is_ct_kill) {
IWL_ERR(priv, "Restarting adapter due to queue full\n");
queue_work(priv->workqueue, &priv->restart);
}
@@ -480,7 +483,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
* information */
out_cmd->hdr.flags = 0;
- out_cmd->hdr.sequence = cpu_to_le16(QUEUE_TO_SEQ(IWL_CMD_QUEUE_NUM) |
+ out_cmd->hdr.sequence = cpu_to_le16(QUEUE_TO_SEQ(priv->cmd_queue) |
INDEX_TO_SEQ(q->write_ptr));
if (cmd->flags & CMD_SIZE_HUGE)
out_cmd->hdr.sequence |= SEQ_HUGE_FRAME;
@@ -497,15 +500,15 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
get_cmd_string(out_cmd->hdr.cmd),
out_cmd->hdr.cmd,
le16_to_cpu(out_cmd->hdr.sequence), fix_size,
- q->write_ptr, idx, IWL_CMD_QUEUE_NUM);
- break;
+ q->write_ptr, idx, priv->cmd_queue);
+ break;
default:
IWL_DEBUG_HC(priv, "Sending command %s (#%x), seq: 0x%04X, "
"%d bytes at %d[%d]:%d\n",
get_cmd_string(out_cmd->hdr.cmd),
out_cmd->hdr.cmd,
le16_to_cpu(out_cmd->hdr.sequence), fix_size,
- q->write_ptr, idx, IWL_CMD_QUEUE_NUM);
+ q->write_ptr, idx, priv->cmd_queue);
}
#endif
txq->need_update = 1;
@@ -584,16 +587,16 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
bool huge = !!(pkt->hdr.sequence & SEQ_HUGE_FRAME);
struct iwl_device_cmd *cmd;
struct iwl_cmd_meta *meta;
- struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM];
+ struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
/* If a Tx command is being handled and it isn't in the actual
* command queue then there a command routing bug has been introduced
* in the queue management code. */
- if (WARN(txq_id != IWL_CMD_QUEUE_NUM,
- "wrong command queue %d, sequence 0x%X readp=%d writep=%d\n",
- txq_id, sequence,
- priv->txq[IWL_CMD_QUEUE_NUM].q.read_ptr,
- priv->txq[IWL_CMD_QUEUE_NUM].q.write_ptr)) {
+ if (WARN(txq_id != priv->cmd_queue,
+ "wrong command queue %d (should be %d), sequence 0x%X readp=%d writep=%d\n",
+ txq_id, priv->cmd_queue, sequence,
+ priv->txq[priv->cmd_queue].q.read_ptr,
+ priv->txq[priv->cmd_queue].q.write_ptr)) {
iwl_print_hex_error(priv, pkt, 32);
return;
}
@@ -633,41 +636,3 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
meta->flags = 0;
}
EXPORT_SYMBOL(iwl_tx_cmd_complete);
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-#define TX_STATUS_FAIL(x) case TX_STATUS_FAIL_ ## x: return #x
-#define TX_STATUS_POSTPONE(x) case TX_STATUS_POSTPONE_ ## x: return #x
-
-const char *iwl_get_tx_fail_reason(u32 status)
-{
- switch (status & TX_STATUS_MSK) {
- case TX_STATUS_SUCCESS:
- return "SUCCESS";
- TX_STATUS_POSTPONE(DELAY);
- TX_STATUS_POSTPONE(FEW_BYTES);
- TX_STATUS_POSTPONE(BT_PRIO);
- TX_STATUS_POSTPONE(QUIET_PERIOD);
- TX_STATUS_POSTPONE(CALC_TTAK);
- TX_STATUS_FAIL(INTERNAL_CROSSED_RETRY);
- TX_STATUS_FAIL(SHORT_LIMIT);
- TX_STATUS_FAIL(LONG_LIMIT);
- TX_STATUS_FAIL(FIFO_UNDERRUN);
- TX_STATUS_FAIL(DRAIN_FLOW);
- TX_STATUS_FAIL(RFKILL_FLUSH);
- TX_STATUS_FAIL(LIFE_EXPIRE);
- TX_STATUS_FAIL(DEST_PS);
- TX_STATUS_FAIL(HOST_ABORTED);
- TX_STATUS_FAIL(BT_RETRY);
- TX_STATUS_FAIL(STA_INVALID);
- TX_STATUS_FAIL(FRAG_DROPPED);
- TX_STATUS_FAIL(TID_DISABLE);
- TX_STATUS_FAIL(FIFO_FLUSHED);
- TX_STATUS_FAIL(INSUFFICIENT_CF_POLL);
- TX_STATUS_FAIL(FW_DROP);
- TX_STATUS_FAIL(STA_COLOR_MISMATCH_DROP);
- }
-
- return "UNKNOWN";
-}
-EXPORT_SYMBOL(iwl_get_tx_fail_reason);
-#endif /* CONFIG_IWLWIFI_DEBUG */
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 59a308b02f95..8f8c4b73f8b9 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -33,6 +33,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/pci.h>
+#include <linux/pci-aspm.h>
#include <linux/slab.h>
#include <linux/dma-mapping.h>
#include <linux/delay.h>
@@ -143,7 +144,7 @@ static int iwl3945_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK);
key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
- if (sta_id == priv->hw_params.bcast_sta_id)
+ if (sta_id == priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id)
key_flags |= STA_KEY_MULTICAST_MSK;
keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
@@ -151,7 +152,7 @@ static int iwl3945_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
key_flags &= ~STA_KEY_FLG_INVALID;
spin_lock_irqsave(&priv->sta_lock, flags);
- priv->stations[sta_id].keyinfo.alg = keyconf->alg;
+ priv->stations[sta_id].keyinfo.cipher = keyconf->cipher;
priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;
memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key,
keyconf->keylen);
@@ -222,23 +223,25 @@ static int iwl3945_set_dynamic_key(struct iwl_priv *priv,
keyconf->hw_key_idx = HW_KEY_DYNAMIC;
- switch (keyconf->alg) {
- case ALG_CCMP:
+ switch (keyconf->cipher) {
+ case WLAN_CIPHER_SUITE_CCMP:
ret = iwl3945_set_ccmp_dynamic_key_info(priv, keyconf, sta_id);
break;
- case ALG_TKIP:
+ case WLAN_CIPHER_SUITE_TKIP:
ret = iwl3945_set_tkip_dynamic_key_info(priv, keyconf, sta_id);
break;
- case ALG_WEP:
+ case WLAN_CIPHER_SUITE_WEP40:
+ case WLAN_CIPHER_SUITE_WEP104:
ret = iwl3945_set_wep_dynamic_key_info(priv, keyconf, sta_id);
break;
default:
- IWL_ERR(priv, "Unknown alg: %s alg = %d\n", __func__, keyconf->alg);
+ IWL_ERR(priv, "Unknown alg: %s alg=%x\n", __func__,
+ keyconf->cipher);
ret = -EINVAL;
}
- IWL_DEBUG_WEP(priv, "Set dynamic key: alg= %d len=%d idx=%d sta=%d ret=%d\n",
- keyconf->alg, keyconf->keylen, keyconf->keyidx,
+ IWL_DEBUG_WEP(priv, "Set dynamic key: alg=%x len=%d idx=%d sta=%d ret=%d\n",
+ keyconf->cipher, keyconf->keylen, keyconf->keyidx,
sta_id, ret);
return ret;
@@ -254,10 +257,11 @@ static int iwl3945_remove_static_key(struct iwl_priv *priv)
static int iwl3945_set_static_key(struct iwl_priv *priv,
struct ieee80211_key_conf *key)
{
- if (key->alg == ALG_WEP)
+ if (key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
+ key->cipher == WLAN_CIPHER_SUITE_WEP104)
return -EOPNOTSUPP;
- IWL_ERR(priv, "Static key invalid: alg %d\n", key->alg);
+ IWL_ERR(priv, "Static key invalid: cipher %x\n", key->cipher);
return -EINVAL;
}
@@ -313,15 +317,15 @@ unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv,
int left)
{
- if (!iwl_is_associated(priv) || !priv->ibss_beacon)
+ if (!iwl_is_associated(priv, IWL_RXON_CTX_BSS) || !priv->beacon_skb)
return 0;
- if (priv->ibss_beacon->len > left)
+ if (priv->beacon_skb->len > left)
return 0;
- memcpy(hdr, priv->ibss_beacon->data, priv->ibss_beacon->len);
+ memcpy(hdr, priv->beacon_skb->data, priv->beacon_skb->len);
- return priv->ibss_beacon->len;
+ return priv->beacon_skb->len;
}
static int iwl3945_send_beacon_cmd(struct iwl_priv *priv)
@@ -339,7 +343,8 @@ static int iwl3945_send_beacon_cmd(struct iwl_priv *priv)
return -ENOMEM;
}
- rate = iwl_rate_get_lowest_plcp(priv);
+ rate = iwl_rate_get_lowest_plcp(priv,
+ &priv->contexts[IWL_RXON_CTX_BSS]);
frame_size = iwl3945_hw_get_beacon_cmd(priv, frame, rate);
@@ -369,23 +374,25 @@ static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
struct iwl3945_tx_cmd *tx_cmd = (struct iwl3945_tx_cmd *)cmd->cmd.payload;
struct iwl_hw_key *keyinfo = &priv->stations[sta_id].keyinfo;
- switch (keyinfo->alg) {
- case ALG_CCMP:
+ tx_cmd->sec_ctl = 0;
+
+ switch (keyinfo->cipher) {
+ case WLAN_CIPHER_SUITE_CCMP:
tx_cmd->sec_ctl = TX_CMD_SEC_CCM;
memcpy(tx_cmd->key, keyinfo->key, keyinfo->keylen);
IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n");
break;
- case ALG_TKIP:
+ case WLAN_CIPHER_SUITE_TKIP:
break;
- case ALG_WEP:
- tx_cmd->sec_ctl = TX_CMD_SEC_WEP |
+ case WLAN_CIPHER_SUITE_WEP104:
+ tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128;
+ /* fall through */
+ case WLAN_CIPHER_SUITE_WEP40:
+ tx_cmd->sec_ctl |= TX_CMD_SEC_WEP |
(info->control.hw_key->hw_key_idx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT;
- if (keyinfo->keylen == 13)
- tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128;
-
memcpy(&tx_cmd->key[3], keyinfo->key, keyinfo->keylen);
IWL_DEBUG_TX(priv, "Configuring packet for WEP encryption "
@@ -393,7 +400,7 @@ static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
break;
default:
- IWL_ERR(priv, "Unknown encode alg %d\n", keyinfo->alg);
+ IWL_ERR(priv, "Unknown encode cipher %x\n", keyinfo->cipher);
break;
}
}
@@ -506,7 +513,9 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
hdr_len = ieee80211_hdrlen(fc);
/* Find index into station table for destination station */
- sta_id = iwl_sta_id_or_broadcast(priv, info->control.sta);
+ sta_id = iwl_sta_id_or_broadcast(
+ priv, &priv->contexts[IWL_RXON_CTX_BSS],
+ info->control.sta);
if (sta_id == IWL_INVALID_STATION) {
IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
hdr->addr1);
@@ -536,6 +545,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
/* Set up driver data for this TFD */
memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info));
txq->txb[q->write_ptr].skb = skb;
+ txq->txb[q->write_ptr].ctx = &priv->contexts[IWL_RXON_CTX_BSS];
/* Init first empty entry in queue's array of Tx/cmd buffers */
out_cmd = txq->cmd[idx];
@@ -677,11 +687,12 @@ static int iwl3945_get_measurement(struct iwl_priv *priv,
int rc;
int spectrum_resp_status;
int duration = le16_to_cpu(params->duration);
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
- if (iwl_is_associated(priv))
+ if (iwl_is_associated(priv, IWL_RXON_CTX_BSS))
add_time = iwl_usecs_to_beacons(priv,
le64_to_cpu(params->start_time) - priv->_3945.last_tsf,
- le16_to_cpu(priv->rxon_timing.beacon_interval));
+ le16_to_cpu(ctx->timing.beacon_interval));
memset(&spectrum, 0, sizeof(spectrum));
@@ -692,18 +703,18 @@ static int iwl3945_get_measurement(struct iwl_priv *priv,
cmd.len = sizeof(spectrum);
spectrum.len = cpu_to_le16(cmd.len - sizeof(spectrum.len));
- if (iwl_is_associated(priv))
+ if (iwl_is_associated(priv, IWL_RXON_CTX_BSS))
spectrum.start_time =
iwl_add_beacon_time(priv,
priv->_3945.last_beacon_time, add_time,
- le16_to_cpu(priv->rxon_timing.beacon_interval));
+ le16_to_cpu(ctx->timing.beacon_interval));
else
spectrum.start_time = 0;
spectrum.channels[0].duration = cpu_to_le32(duration * TIME_UNIT);
spectrum.channels[0].channel = params->channel;
spectrum.channels[0].type = type;
- if (priv->active_rxon.flags & RXON_FLG_BAND_24G_MSK)
+ if (ctx->active.flags & RXON_FLG_BAND_24G_MSK)
spectrum.flags |= RXON_FLG_BAND_24G_MSK |
RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_TGG_PROTECT_MSK;
@@ -792,7 +803,8 @@ static void iwl3945_bg_beacon_update(struct work_struct *work)
struct sk_buff *beacon;
/* Pull updated AP beacon from mac80211. will fail if not in AP mode */
- beacon = ieee80211_beacon_get(priv->hw, priv->vif);
+ beacon = ieee80211_beacon_get(priv->hw,
+ priv->contexts[IWL_RXON_CTX_BSS].vif);
if (!beacon) {
IWL_ERR(priv, "update beacon failed\n");
@@ -801,10 +813,10 @@ static void iwl3945_bg_beacon_update(struct work_struct *work)
mutex_lock(&priv->mutex);
/* new beacon skb is allocated every time; dispose previous.*/
- if (priv->ibss_beacon)
- dev_kfree_skb(priv->ibss_beacon);
+ if (priv->beacon_skb)
+ dev_kfree_skb(priv->beacon_skb);
- priv->ibss_beacon = beacon;
+ priv->beacon_skb = beacon;
mutex_unlock(&priv->mutex);
iwl3945_send_beacon_cmd(priv);
@@ -813,9 +825,9 @@ static void iwl3945_bg_beacon_update(struct work_struct *work)
static void iwl3945_rx_beacon_notif(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
-#ifdef CONFIG_IWLWIFI_DEBUG
struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl3945_beacon_notif *beacon = &(pkt->u.beacon_status);
+#ifdef CONFIG_IWLWIFI_DEBUG
u8 rate = beacon->beacon_notify_hdr.rate;
IWL_DEBUG_RX(priv, "beacon status %x retries %d iss %d "
@@ -827,6 +839,8 @@ static void iwl3945_rx_beacon_notif(struct iwl_priv *priv,
le32_to_cpu(beacon->low_tsf), rate);
#endif
+ priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status);
+
if ((priv->iw_mode == NL80211_IFTYPE_AP) &&
(!test_bit(STATUS_EXIT_PENDING, &priv->status)))
queue_work(priv->workqueue, &priv->beacon_update);
@@ -1567,16 +1581,16 @@ int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32)));
next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32)));
- if (capacity > priv->cfg->max_event_log_size) {
+ if (capacity > priv->cfg->base_params->max_event_log_size) {
IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n",
- capacity, priv->cfg->max_event_log_size);
- capacity = priv->cfg->max_event_log_size;
+ capacity, priv->cfg->base_params->max_event_log_size);
+ capacity = priv->cfg->base_params->max_event_log_size;
}
- if (next_entry > priv->cfg->max_event_log_size) {
+ if (next_entry > priv->cfg->base_params->max_event_log_size) {
IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n",
- next_entry, priv->cfg->max_event_log_size);
- next_entry = priv->cfg->max_event_log_size;
+ next_entry, priv->cfg->base_params->max_event_log_size);
+ next_entry = priv->cfg->base_params->max_event_log_size;
}
size = num_wraps ? capacity : next_entry;
@@ -1716,7 +1730,6 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
IWL_ERR(priv, "Microcode SW error detected. "
"Restarting 0x%X.\n", inta);
priv->isr_stats.sw++;
- priv->isr_stats.sw_err = inta;
iwl_irq_handle_error(priv);
handled |= CSR_INT_BIT_SW_ERR;
}
@@ -2460,6 +2473,7 @@ static void iwl3945_alive_start(struct iwl_priv *priv)
{
int thermal_spin = 0;
u32 rfkill;
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
@@ -2505,7 +2519,8 @@ static void iwl3945_alive_start(struct iwl_priv *priv)
/* Enable timer to monitor the driver queues */
mod_timer(&priv->monitor_recover,
jiffies +
- msecs_to_jiffies(priv->cfg->monitor_recover_period));
+ msecs_to_jiffies(
+ priv->cfg->base_params->monitor_recover_period));
}
if (iwl_is_rfkill(priv))
@@ -2517,22 +2532,22 @@ static void iwl3945_alive_start(struct iwl_priv *priv)
iwl_power_update_mode(priv, true);
- if (iwl_is_associated(priv)) {
+ if (iwl_is_associated(priv, IWL_RXON_CTX_BSS)) {
struct iwl3945_rxon_cmd *active_rxon =
- (struct iwl3945_rxon_cmd *)(&priv->active_rxon);
+ (struct iwl3945_rxon_cmd *)(&ctx->active);
- priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
+ ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
} else {
/* Initialize our rx_config data */
- iwl_connection_init_rx_config(priv, NULL);
+ iwl_connection_init_rx_config(priv, ctx);
}
/* Configure Bluetooth device coexistence support */
priv->cfg->ops->hcmd->send_bt_config(priv);
/* Configure the adapter for unassociated operation */
- iwlcore_commit_rxon(priv);
+ iwl3945_commit_rxon(priv, ctx);
iwl3945_reg_txpower_periodic(priv);
@@ -2553,19 +2568,22 @@ static void iwl3945_cancel_deferred_work(struct iwl_priv *priv);
static void __iwl3945_down(struct iwl_priv *priv)
{
unsigned long flags;
- int exit_pending = test_bit(STATUS_EXIT_PENDING, &priv->status);
- struct ieee80211_conf *conf = NULL;
+ int exit_pending;
IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n");
- conf = ieee80211_get_hw_conf(priv->hw);
+ iwl_scan_cancel_timeout(priv, 200);
- if (!exit_pending)
- set_bit(STATUS_EXIT_PENDING, &priv->status);
+ exit_pending = test_and_set_bit(STATUS_EXIT_PENDING, &priv->status);
+
+ /* Stop TX queues watchdog. We need to have STATUS_EXIT_PENDING bit set
+ * to prevent rearm timer */
+ if (priv->cfg->ops->lib->recover_from_tx_stall)
+ del_timer_sync(&priv->monitor_recover);
/* Station information will now be cleared in device */
- iwl_clear_ucode_stations(priv);
- iwl_dealloc_bcast_station(priv);
+ iwl_clear_ucode_stations(priv, NULL);
+ iwl_dealloc_bcast_stations(priv);
iwl_clear_driver_stations(priv);
/* Unblock any waiting calls */
@@ -2619,14 +2637,14 @@ static void __iwl3945_down(struct iwl_priv *priv)
udelay(5);
/* Stop the device, and put it in low power state */
- priv->cfg->ops->lib->apm_ops.stop(priv);
+ iwl_apm_stop(priv);
exit:
memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp));
- if (priv->ibss_beacon)
- dev_kfree_skb(priv->ibss_beacon);
- priv->ibss_beacon = NULL;
+ if (priv->beacon_skb)
+ dev_kfree_skb(priv->beacon_skb);
+ priv->beacon_skb = NULL;
/* clear out any free frames */
iwl3945_clear_free_frames(priv);
@@ -2643,11 +2661,33 @@ static void iwl3945_down(struct iwl_priv *priv)
#define MAX_HW_RESTARTS 5
+static int iwl3945_alloc_bcast_station(struct iwl_priv *priv)
+{
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+ unsigned long flags;
+ u8 sta_id;
+
+ spin_lock_irqsave(&priv->sta_lock, flags);
+ sta_id = iwl_prep_station(priv, ctx, iwl_bcast_addr, false, NULL);
+ if (sta_id == IWL_INVALID_STATION) {
+ IWL_ERR(priv, "Unable to prepare broadcast station\n");
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+ return -EINVAL;
+ }
+
+ priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE;
+ priv->stations[sta_id].used |= IWL_STA_BCAST;
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+ return 0;
+}
+
static int __iwl3945_up(struct iwl_priv *priv)
{
int rc, i;
- rc = iwl_alloc_bcast_station(priv, false);
+ rc = iwl3945_alloc_bcast_station(priv);
if (rc)
return rc;
@@ -2799,7 +2839,7 @@ static void iwl3945_rfkill_poll(struct work_struct *data)
}
-void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
+int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
{
struct iwl_host_cmd cmd = {
.id = REPLY_SCAN_CMD,
@@ -2807,61 +2847,19 @@ void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
.flags = CMD_SIZE_HUGE,
};
struct iwl3945_scan_cmd *scan;
- struct ieee80211_conf *conf = NULL;
u8 n_probes = 0;
enum ieee80211_band band;
bool is_active = false;
+ int ret;
- conf = ieee80211_get_hw_conf(priv->hw);
-
- cancel_delayed_work(&priv->scan_check);
-
- if (!iwl_is_ready(priv)) {
- IWL_WARN(priv, "request scan called when driver not ready.\n");
- goto done;
- }
-
- /* Make sure the scan wasn't canceled before this queued work
- * was given the chance to run... */
- if (!test_bit(STATUS_SCANNING, &priv->status))
- goto done;
-
- /* This should never be called or scheduled if there is currently
- * a scan active in the hardware. */
- if (test_bit(STATUS_SCAN_HW, &priv->status)) {
- IWL_DEBUG_INFO(priv, "Multiple concurrent scan requests "
- "Ignoring second request.\n");
- goto done;
- }
-
- if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
- IWL_DEBUG_SCAN(priv, "Aborting scan due to device shutdown\n");
- goto done;
- }
-
- if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
- IWL_DEBUG_HC(priv,
- "Scan request while abort pending. Queuing.\n");
- goto done;
- }
-
- if (iwl_is_rfkill(priv)) {
- IWL_DEBUG_HC(priv, "Aborting scan due to RF Kill activation\n");
- goto done;
- }
-
- if (!test_bit(STATUS_READY, &priv->status)) {
- IWL_DEBUG_HC(priv,
- "Scan request while uninitialized. Queuing.\n");
- goto done;
- }
+ lockdep_assert_held(&priv->mutex);
if (!priv->scan_cmd) {
priv->scan_cmd = kmalloc(sizeof(struct iwl3945_scan_cmd) +
IWL_MAX_SCAN_SIZE, GFP_KERNEL);
if (!priv->scan_cmd) {
IWL_DEBUG_SCAN(priv, "Fail to allocate scan memory\n");
- goto done;
+ return -ENOMEM;
}
}
scan = priv->scan_cmd;
@@ -2870,7 +2868,7 @@ void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
- if (iwl_is_associated(priv)) {
+ if (iwl_is_associated(priv, IWL_RXON_CTX_BSS)) {
u16 interval = 0;
u32 extra;
u32 suspend_time = 100;
@@ -2931,7 +2929,7 @@ void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
/* We don't build a direct scan probe request; the uCode will do
* that based on the direct_mask added to each channel entry */
scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
- scan->tx_cmd.sta_id = priv->hw_params.bcast_sta_id;
+ scan->tx_cmd.sta_id = priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id;
scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
/* flags + rate selection */
@@ -2940,25 +2938,25 @@ void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
case IEEE80211_BAND_2GHZ:
scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
scan->tx_cmd.rate = IWL_RATE_1M_PLCP;
- scan->good_CRC_th = 0;
band = IEEE80211_BAND_2GHZ;
break;
case IEEE80211_BAND_5GHZ:
scan->tx_cmd.rate = IWL_RATE_6M_PLCP;
- /*
- * If active scaning is requested but a certain channel
- * is marked passive, we can do active scanning if we
- * detect transmissions.
- */
- scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
- IWL_GOOD_CRC_TH_DISABLED;
band = IEEE80211_BAND_5GHZ;
break;
default:
IWL_WARN(priv, "Invalid scan band\n");
- goto done;
+ return -EIO;
}
+ /*
+ * If active scaning is requested but a certain channel
+ * is marked passive, we can do active scanning if we
+ * detect transmissions.
+ */
+ scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
+ IWL_GOOD_CRC_TH_DISABLED;
+
if (!priv->is_internal_short_scan) {
scan->tx_cmd.len = cpu_to_le16(
iwl_fill_probe_req(priv,
@@ -2991,7 +2989,7 @@ void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
if (scan->channel_count == 0) {
IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
- goto done;
+ return -EIO;
}
cmd.len += le16_to_cpu(scan->tx_cmd.len) +
@@ -3000,25 +2998,22 @@ void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
scan->len = cpu_to_le16(cmd.len);
set_bit(STATUS_SCAN_HW, &priv->status);
- if (iwl_send_cmd_sync(priv, &cmd))
- goto done;
-
- queue_delayed_work(priv->workqueue, &priv->scan_check,
- IWL_SCAN_CHECK_WATCHDOG);
+ ret = iwl_send_cmd_sync(priv, &cmd);
+ if (ret)
+ clear_bit(STATUS_SCAN_HW, &priv->status);
+ return ret;
+}
- return;
+void iwl3945_post_scan(struct iwl_priv *priv)
+{
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
- done:
- /* can not perform scan make sure we clear scanning
- * bits from status so next scan request can be performed.
- * if we dont clear scanning status bit here all next scan
- * will fail
- */
- clear_bit(STATUS_SCAN_HW, &priv->status);
- clear_bit(STATUS_SCANNING, &priv->status);
-
- /* inform mac80211 scan aborted */
- queue_work(priv->workqueue, &priv->scan_completed);
+ /*
+ * Since setting the RXON may have been deferred while
+ * performing the scan, fire one off if needed
+ */
+ if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
+ iwl3945_commit_rxon(priv, ctx);
}
static void iwl3945_bg_restart(struct work_struct *data)
@@ -3029,8 +3024,10 @@ static void iwl3945_bg_restart(struct work_struct *data)
return;
if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) {
+ struct iwl_rxon_context *ctx;
mutex_lock(&priv->mutex);
- priv->vif = NULL;
+ for_each_context(priv, ctx)
+ ctx->vif = NULL;
priv->is_open = 0;
mutex_unlock(&priv->mutex);
iwl3945_down(priv);
@@ -3064,6 +3061,7 @@ void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif)
{
int rc = 0;
struct ieee80211_conf *conf = NULL;
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
if (!vif || !priv->is_open)
return;
@@ -3074,7 +3072,7 @@ void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif)
}
IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n",
- vif->bss_conf.aid, priv->active_rxon.bssid_addr);
+ vif->bss_conf.aid, ctx->active.bssid_addr);
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
@@ -3083,37 +3081,34 @@ void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif)
conf = ieee80211_get_hw_conf(priv->hw);
- priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
- iwlcore_commit_rxon(priv);
+ ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+ iwl3945_commit_rxon(priv, ctx);
- memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd));
- iwl_setup_rxon_timing(priv, vif);
- rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
- sizeof(priv->rxon_timing), &priv->rxon_timing);
+ rc = iwl_send_rxon_timing(priv, ctx);
if (rc)
IWL_WARN(priv, "REPLY_RXON_TIMING failed - "
"Attempting to continue.\n");
- priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
+ ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
- priv->staging_rxon.assoc_id = cpu_to_le16(vif->bss_conf.aid);
+ ctx->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid);
IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n",
vif->bss_conf.aid, vif->bss_conf.beacon_int);
if (vif->bss_conf.use_short_preamble)
- priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
+ ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
else
- priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
+ ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
- if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) {
+ if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
if (vif->bss_conf.use_short_slot)
- priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
+ ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
else
- priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
+ ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
}
- iwlcore_commit_rxon(priv);
+ iwl3945_commit_rxon(priv, ctx);
switch (vif->type) {
case NL80211_IFTYPE_STATION:
@@ -3212,15 +3207,6 @@ static void iwl3945_mac_stop(struct ieee80211_hw *hw)
priv->is_open = 0;
- if (iwl_is_ready_rf(priv)) {
- /* stop mac, cancel any scan request and clear
- * RXON_FILTER_ASSOC_MSK BIT
- */
- mutex_lock(&priv->mutex);
- iwl_scan_cancel_timeout(priv, 100);
- mutex_unlock(&priv->mutex);
- }
-
iwl3945_down(priv);
flush_workqueue(priv->workqueue);
@@ -3250,48 +3236,45 @@ static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
void iwl3945_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif)
{
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
int rc = 0;
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
/* The following should be done only at AP bring up */
- if (!(iwl_is_associated(priv))) {
+ if (!(iwl_is_associated(priv, IWL_RXON_CTX_BSS))) {
/* RXON - unassoc (to set timing command) */
- priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
- iwlcore_commit_rxon(priv);
+ ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+ iwl3945_commit_rxon(priv, ctx);
/* RXON Timing */
- memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd));
- iwl_setup_rxon_timing(priv, vif);
- rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
- sizeof(priv->rxon_timing),
- &priv->rxon_timing);
+ rc = iwl_send_rxon_timing(priv, ctx);
if (rc)
IWL_WARN(priv, "REPLY_RXON_TIMING failed - "
"Attempting to continue.\n");
- priv->staging_rxon.assoc_id = 0;
+ ctx->staging.assoc_id = 0;
if (vif->bss_conf.use_short_preamble)
- priv->staging_rxon.flags |=
+ ctx->staging.flags |=
RXON_FLG_SHORT_PREAMBLE_MSK;
else
- priv->staging_rxon.flags &=
+ ctx->staging.flags &=
~RXON_FLG_SHORT_PREAMBLE_MSK;
- if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) {
+ if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
if (vif->bss_conf.use_short_slot)
- priv->staging_rxon.flags |=
+ ctx->staging.flags |=
RXON_FLG_SHORT_SLOT_MSK;
else
- priv->staging_rxon.flags &=
+ ctx->staging.flags &=
~RXON_FLG_SHORT_SLOT_MSK;
}
/* restore RXON assoc */
- priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
- iwlcore_commit_rxon(priv);
+ ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
+ iwl3945_commit_rxon(priv, ctx);
}
iwl3945_send_beacon_cmd(priv);
@@ -3317,10 +3300,11 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
return -EOPNOTSUPP;
}
- static_key = !iwl_is_associated(priv);
+ static_key = !iwl_is_associated(priv, IWL_RXON_CTX_BSS);
if (!static_key) {
- sta_id = iwl_sta_id_or_broadcast(priv, sta);
+ sta_id = iwl_sta_id_or_broadcast(
+ priv, &priv->contexts[IWL_RXON_CTX_BSS], sta);
if (sta_id == IWL_INVALID_STATION)
return -EINVAL;
}
@@ -3371,8 +3355,8 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw,
sta_priv->common.sta_id = IWL_INVALID_STATION;
- ret = iwl_add_station_common(priv, sta->addr, is_ap, &sta->ht_cap,
- &sta_id);
+ ret = iwl_add_station_common(priv, &priv->contexts[IWL_RXON_CTX_BSS],
+ sta->addr, is_ap, sta, &sta_id);
if (ret) {
IWL_ERR(priv, "Unable to add station %pM (%d)\n",
sta->addr, ret);
@@ -3399,6 +3383,7 @@ static void iwl3945_configure_filter(struct ieee80211_hw *hw,
{
struct iwl_priv *priv = hw->priv;
__le32 filter_or = 0, filter_nand = 0;
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
#define CHK(test, flag) do { \
if (*total_flags & (test)) \
@@ -3418,8 +3403,8 @@ static void iwl3945_configure_filter(struct ieee80211_hw *hw,
mutex_lock(&priv->mutex);
- priv->staging_rxon.filter_flags &= ~filter_nand;
- priv->staging_rxon.filter_flags |= filter_or;
+ ctx->staging.filter_flags &= ~filter_nand;
+ ctx->staging.filter_flags |= filter_or;
/*
* Committing directly here breaks for some reason,
@@ -3533,8 +3518,9 @@ static ssize_t show_flags(struct device *d,
struct device_attribute *attr, char *buf)
{
struct iwl_priv *priv = dev_get_drvdata(d);
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
- return sprintf(buf, "0x%04X\n", priv->active_rxon.flags);
+ return sprintf(buf, "0x%04X\n", ctx->active.flags);
}
static ssize_t store_flags(struct device *d,
@@ -3543,17 +3529,18 @@ static ssize_t store_flags(struct device *d,
{
struct iwl_priv *priv = dev_get_drvdata(d);
u32 flags = simple_strtoul(buf, NULL, 0);
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
mutex_lock(&priv->mutex);
- if (le32_to_cpu(priv->staging_rxon.flags) != flags) {
+ if (le32_to_cpu(ctx->staging.flags) != flags) {
/* Cancel any currently running scans... */
if (iwl_scan_cancel_timeout(priv, 100))
IWL_WARN(priv, "Could not cancel scan.\n");
else {
IWL_DEBUG_INFO(priv, "Committing rxon.flags = 0x%04X\n",
flags);
- priv->staging_rxon.flags = cpu_to_le32(flags);
- iwlcore_commit_rxon(priv);
+ ctx->staging.flags = cpu_to_le32(flags);
+ iwl3945_commit_rxon(priv, ctx);
}
}
mutex_unlock(&priv->mutex);
@@ -3567,9 +3554,10 @@ static ssize_t show_filter_flags(struct device *d,
struct device_attribute *attr, char *buf)
{
struct iwl_priv *priv = dev_get_drvdata(d);
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
return sprintf(buf, "0x%04X\n",
- le32_to_cpu(priv->active_rxon.filter_flags));
+ le32_to_cpu(ctx->active.filter_flags));
}
static ssize_t store_filter_flags(struct device *d,
@@ -3577,19 +3565,20 @@ static ssize_t store_filter_flags(struct device *d,
const char *buf, size_t count)
{
struct iwl_priv *priv = dev_get_drvdata(d);
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
u32 filter_flags = simple_strtoul(buf, NULL, 0);
mutex_lock(&priv->mutex);
- if (le32_to_cpu(priv->staging_rxon.filter_flags) != filter_flags) {
+ if (le32_to_cpu(ctx->staging.filter_flags) != filter_flags) {
/* Cancel any currently running scans... */
if (iwl_scan_cancel_timeout(priv, 100))
IWL_WARN(priv, "Could not cancel scan.\n");
else {
IWL_DEBUG_INFO(priv, "Committing rxon.filter_flags = "
"0x%04X\n", filter_flags);
- priv->staging_rxon.filter_flags =
+ ctx->staging.filter_flags =
cpu_to_le32(filter_flags);
- iwlcore_commit_rxon(priv);
+ iwl3945_commit_rxon(priv, ctx);
}
}
mutex_unlock(&priv->mutex);
@@ -3637,8 +3626,9 @@ static ssize_t store_measurement(struct device *d,
const char *buf, size_t count)
{
struct iwl_priv *priv = dev_get_drvdata(d);
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
struct ieee80211_measurement_params params = {
- .channel = le16_to_cpu(priv->active_rxon.channel),
+ .channel = le16_to_cpu(ctx->active.channel),
.start_time = cpu_to_le64(priv->_3945.last_tsf),
.duration = cpu_to_le16(1),
};
@@ -3785,10 +3775,8 @@ static void iwl3945_setup_deferred_work(struct iwl_priv *priv)
INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start);
INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start);
INIT_DELAYED_WORK(&priv->_3945.rfkill_poll, iwl3945_rfkill_poll);
- INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed);
- INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan);
- INIT_WORK(&priv->start_internal_scan, iwl_bg_start_internal_scan);
- INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check);
+
+ iwl_setup_scan_deferred_work(priv);
iwl3945_hw_setup_deferred_work(priv);
@@ -3808,12 +3796,10 @@ static void iwl3945_cancel_deferred_work(struct iwl_priv *priv)
iwl3945_hw_cancel_deferred_work(priv);
cancel_delayed_work_sync(&priv->init_alive_start);
- cancel_delayed_work(&priv->scan_check);
cancel_delayed_work(&priv->alive_start);
- cancel_work_sync(&priv->start_internal_scan);
cancel_work_sync(&priv->beacon_update);
- if (priv->cfg->ops->lib->recover_from_tx_stall)
- del_timer_sync(&priv->monitor_recover);
+
+ iwl_cancel_scan_deferred_work(priv);
}
static struct attribute *iwl3945_sysfs_entries[] = {
@@ -3853,6 +3839,7 @@ static struct ieee80211_ops iwl3945_hw_ops = {
.hw_scan = iwl_mac_hw_scan,
.sta_add = iwl3945_mac_sta_add,
.sta_remove = iwl_mac_sta_remove,
+ .tx_last_beacon = iwl_mac_tx_last_beacon,
};
static int iwl3945_init_drv(struct iwl_priv *priv)
@@ -3861,7 +3848,7 @@ static int iwl3945_init_drv(struct iwl_priv *priv)
struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
priv->retry_rate = 1;
- priv->ibss_beacon = NULL;
+ priv->beacon_skb = NULL;
spin_lock_init(&priv->sta_lock);
spin_lock_init(&priv->hcmd_lock);
@@ -3928,13 +3915,12 @@ static int iwl3945_setup_mac(struct iwl_priv *priv)
hw->flags = IEEE80211_HW_SIGNAL_DBM |
IEEE80211_HW_SPECTRUM_MGMT;
- if (!priv->cfg->broken_powersave)
+ if (!priv->cfg->base_params->broken_powersave)
hw->flags |= IEEE80211_HW_SUPPORTS_PS |
IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
hw->wiphy->interface_modes =
- BIT(NL80211_IFTYPE_STATION) |
- BIT(NL80211_IFTYPE_ADHOC);
+ priv->contexts[IWL_RXON_CTX_BSS].interface_modes;
hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
WIPHY_FLAG_DISABLE_BEACON_HINTS;
@@ -3966,7 +3952,7 @@ static int iwl3945_setup_mac(struct iwl_priv *priv)
static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
- int err = 0;
+ int err = 0, i;
struct iwl_priv *priv;
struct ieee80211_hw *hw;
struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
@@ -3988,12 +3974,33 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
priv = hw->priv;
SET_IEEE80211_DEV(hw, &pdev->dev);
+ priv->cmd_queue = IWL39_CMD_QUEUE_NUM;
+
+ /* 3945 has only one valid context */
+ priv->valid_contexts = BIT(IWL_RXON_CTX_BSS);
+
+ for (i = 0; i < NUM_IWL_RXON_CTX; i++)
+ priv->contexts[i].ctxid = i;
+
+ priv->contexts[IWL_RXON_CTX_BSS].rxon_cmd = REPLY_RXON;
+ priv->contexts[IWL_RXON_CTX_BSS].rxon_timing_cmd = REPLY_RXON_TIMING;
+ priv->contexts[IWL_RXON_CTX_BSS].rxon_assoc_cmd = REPLY_RXON_ASSOC;
+ priv->contexts[IWL_RXON_CTX_BSS].qos_cmd = REPLY_QOS_PARAM;
+ priv->contexts[IWL_RXON_CTX_BSS].ap_sta_id = IWL_AP_ID;
+ priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY;
+ priv->contexts[IWL_RXON_CTX_BSS].interface_modes =
+ BIT(NL80211_IFTYPE_STATION) |
+ BIT(NL80211_IFTYPE_ADHOC);
+ priv->contexts[IWL_RXON_CTX_BSS].ibss_devtype = RXON_DEV_TYPE_IBSS;
+ priv->contexts[IWL_RXON_CTX_BSS].station_devtype = RXON_DEV_TYPE_ESS;
+ priv->contexts[IWL_RXON_CTX_BSS].unused_devtype = RXON_DEV_TYPE_ESS;
+
/*
* Disabling hardware scan means that mac80211 will perform scans
* "the hard way", rather than using device's scan.
*/
if (iwl3945_mod_params.disable_hw_scan) {
- IWL_DEBUG_INFO(priv, "Disabling hw_scan\n");
+ IWL_ERR(priv, "sw scan support is deprecated\n");
iwl3945_hw_ops.hw_scan = NULL;
}
@@ -4009,6 +4016,9 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
/***************************
* 2. Initializing PCI bus
* *************************/
+ pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
+ PCIE_LINK_STATE_CLKPM);
+
if (pci_enable_device(pdev)) {
err = -ENODEV;
goto out_ieee80211_free_hw;
@@ -4120,7 +4130,8 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
}
iwl_set_rxon_channel(priv,
- &priv->bands[IEEE80211_BAND_2GHZ].channels[5]);
+ &priv->bands[IEEE80211_BAND_2GHZ].channels[5],
+ &priv->contexts[IWL_RXON_CTX_BSS]);
iwl3945_setup_deferred_work(priv);
iwl3945_setup_rx_handlers(priv);
iwl_power_initialize(priv);
@@ -4201,7 +4212,7 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
* paths to avoid running iwl_down() at all before leaving driver.
* This (inexpensive) call *makes sure* device is reset.
*/
- priv->cfg->ops->lib->apm_ops.stop(priv);
+ iwl_apm_stop(priv);
/* make sure we flush any pending irq or
* tasklet for the driver
@@ -4245,8 +4256,8 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
iwl_free_channel_map(priv);
iwlcore_free_geos(priv);
kfree(priv->scan_cmd);
- if (priv->ibss_beacon)
- dev_kfree_skb(priv->ibss_beacon);
+ if (priv->beacon_skb)
+ dev_kfree_skb(priv->beacon_skb);
ieee80211_free_hw(priv->hw);
}
@@ -4314,7 +4325,8 @@ MODULE_PARM_DESC(debug, "debug output mask");
#endif
module_param_named(disable_hw_scan, iwl3945_mod_params.disable_hw_scan,
int, S_IRUGO);
-MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)");
+MODULE_PARM_DESC(disable_hw_scan,
+ "disable hardware scanning (default 0) (deprecated)");
module_param_named(fw_restart3945, iwl3945_mod_params.restart_fw, int, S_IRUGO);
MODULE_PARM_DESC(fw_restart3945, "restart firmware in case of error");
diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c
index 60619678f4ec..c6c0eff9b5ed 100644
--- a/drivers/net/wireless/iwmc3200wifi/cfg80211.c
+++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.c
@@ -161,7 +161,7 @@ static int iwm_key_init(struct iwm_key *key, u8 key_index,
}
static int iwm_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
- u8 key_index, const u8 *mac_addr,
+ u8 key_index, bool pairwise, const u8 *mac_addr,
struct key_params *params)
{
struct iwm_priv *iwm = ndev_to_iwm(ndev);
@@ -181,7 +181,8 @@ static int iwm_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
}
static int iwm_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
- u8 key_index, const u8 *mac_addr, void *cookie,
+ u8 key_index, bool pairwise, const u8 *mac_addr,
+ void *cookie,
void (*callback)(void *cookie,
struct key_params*))
{
@@ -206,7 +207,7 @@ static int iwm_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
static int iwm_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
- u8 key_index, const u8 *mac_addr)
+ u8 key_index, bool pairwise, const u8 *mac_addr)
{
struct iwm_priv *iwm = ndev_to_iwm(ndev);
struct iwm_key *key = &iwm->keys[key_index];
diff --git a/drivers/net/wireless/iwmc3200wifi/debugfs.c b/drivers/net/wireless/iwmc3200wifi/debugfs.c
index 53b0b7711f02..0a0cc9667cd6 100644
--- a/drivers/net/wireless/iwmc3200wifi/debugfs.c
+++ b/drivers/net/wireless/iwmc3200wifi/debugfs.c
@@ -402,24 +402,28 @@ static const struct file_operations iwm_debugfs_txq_fops = {
.owner = THIS_MODULE,
.open = iwm_generic_open,
.read = iwm_debugfs_txq_read,
+ .llseek = default_llseek,
};
static const struct file_operations iwm_debugfs_tx_credit_fops = {
.owner = THIS_MODULE,
.open = iwm_generic_open,
.read = iwm_debugfs_tx_credit_read,
+ .llseek = default_llseek,
};
static const struct file_operations iwm_debugfs_rx_ticket_fops = {
.owner = THIS_MODULE,
.open = iwm_generic_open,
.read = iwm_debugfs_rx_ticket_read,
+ .llseek = default_llseek,
};
static const struct file_operations iwm_debugfs_fw_err_fops = {
.owner = THIS_MODULE,
.open = iwm_generic_open,
.read = iwm_debugfs_fw_err_read,
+ .llseek = default_llseek,
};
void iwm_debugfs_init(struct iwm_priv *iwm)
diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c
index c02fcedea9fa..a944893ae3ca 100644
--- a/drivers/net/wireless/iwmc3200wifi/rx.c
+++ b/drivers/net/wireless/iwmc3200wifi/rx.c
@@ -1195,11 +1195,8 @@ static int iwm_ntf_wifi_if_wrapper(struct iwm_priv *iwm, u8 *buf,
IWM_DBG_NTF(iwm, DBG, "WIFI_IF_WRAPPER cmd is delivered to UMAC: "
"oid is 0x%x\n", hdr->oid);
- if (hdr->oid <= WIFI_IF_NTFY_MAX) {
- set_bit(hdr->oid, &iwm->wifi_ntfy[0]);
- wake_up_interruptible(&iwm->wifi_ntfy_queue);
- } else
- return -EINVAL;
+ set_bit(hdr->oid, &iwm->wifi_ntfy[0]);
+ wake_up_interruptible(&iwm->wifi_ntfy_queue);
switch (hdr->oid) {
case UMAC_WIFI_IF_CMD_SET_PROFILE:
diff --git a/drivers/net/wireless/iwmc3200wifi/sdio.c b/drivers/net/wireless/iwmc3200wifi/sdio.c
index edcb52330cf5..56383e7be835 100644
--- a/drivers/net/wireless/iwmc3200wifi/sdio.c
+++ b/drivers/net/wireless/iwmc3200wifi/sdio.c
@@ -364,6 +364,7 @@ static const struct file_operations iwm_debugfs_sdio_fops = {
.owner = THIS_MODULE,
.open = iwm_debugfs_sdio_open,
.read = iwm_debugfs_sdio_read,
+ .llseek = default_llseek,
};
static void if_sdio_debugfs_init(struct iwm_priv *iwm, struct dentry *parent_dir)
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c
index 3e82f1627209..5046a0005034 100644
--- a/drivers/net/wireless/libertas/cfg.c
+++ b/drivers/net/wireless/libertas/cfg.c
@@ -10,6 +10,7 @@
#include <linux/wait.h>
#include <linux/slab.h>
#include <linux/sched.h>
+#include <linux/wait.h>
#include <linux/ieee80211.h>
#include <net/cfg80211.h>
#include <asm/unaligned.h>
@@ -480,7 +481,6 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy,
struct cmd_ds_802_11_scan_rsp *scanresp = (void *)resp;
int bsssize;
const u8 *pos;
- u16 nr_sets;
const u8 *tsfdesc;
int tsfsize;
int i;
@@ -489,12 +489,11 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy,
lbs_deb_enter(LBS_DEB_CFG80211);
bsssize = get_unaligned_le16(&scanresp->bssdescriptsize);
- nr_sets = le16_to_cpu(scanresp->nr_sets);
lbs_deb_scan("scan response: %d BSSs (%d bytes); resp size %d bytes\n",
- nr_sets, bsssize, le16_to_cpu(resp->size));
+ scanresp->nr_sets, bsssize, le16_to_cpu(resp->size));
- if (nr_sets == 0) {
+ if (scanresp->nr_sets == 0) {
ret = 0;
goto done;
}
@@ -526,20 +525,31 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy,
pos = scanresp->bssdesc_and_tlvbuffer;
+ lbs_deb_hex(LBS_DEB_SCAN, "SCAN_RSP", scanresp->bssdesc_and_tlvbuffer,
+ scanresp->bssdescriptsize);
+
tsfdesc = pos + bsssize;
tsfsize = 4 + 8 * scanresp->nr_sets;
+ lbs_deb_hex(LBS_DEB_SCAN, "SCAN_TSF", (u8 *) tsfdesc, tsfsize);
/* Validity check: we expect a Marvell-Local TLV */
i = get_unaligned_le16(tsfdesc);
tsfdesc += 2;
- if (i != TLV_TYPE_TSFTIMESTAMP)
+ if (i != TLV_TYPE_TSFTIMESTAMP) {
+ lbs_deb_scan("scan response: invalid TSF Timestamp %d\n", i);
goto done;
+ }
+
/* Validity check: the TLV holds TSF values with 8 bytes each, so
* the size in the TLV must match the nr_sets value */
i = get_unaligned_le16(tsfdesc);
tsfdesc += 2;
- if (i / 8 != scanresp->nr_sets)
+ if (i / 8 != scanresp->nr_sets) {
+ lbs_deb_scan("scan response: invalid number of TSF timestamp "
+ "sets (expected %d got %d)\n", scanresp->nr_sets,
+ i / 8);
goto done;
+ }
for (i = 0; i < scanresp->nr_sets; i++) {
const u8 *bssid;
@@ -581,8 +591,11 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy,
id = *pos++;
elen = *pos++;
left -= 2;
- if (elen > left || elen == 0)
+ if (elen > left || elen == 0) {
+ lbs_deb_scan("scan response: invalid IE fmt\n");
goto done;
+ }
+
if (id == WLAN_EID_DS_PARAMS)
chan_no = *pos;
if (id == WLAN_EID_SSID) {
@@ -613,7 +626,9 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy,
capa, intvl, ie, ielen,
LBS_SCAN_RSSI_TO_MBM(rssi),
GFP_KERNEL);
- }
+ } else
+ lbs_deb_scan("scan response: missing BSS channel IE\n");
+
tsfdesc += 8;
}
ret = 0;
@@ -1103,7 +1118,7 @@ static int lbs_associate(struct lbs_private *priv,
lbs_deb_hex(LBS_DEB_ASSOC, "Common Rates", tmp, pos - tmp);
/* add auth type TLV */
- if (priv->fwrelease >= 0x09000000)
+ if (MRVL_FW_MAJOR_REV(priv->fwrelease) >= 9)
pos += lbs_add_auth_type_tlv(pos, sme->auth_type);
/* add WPA/WPA2 TLV */
@@ -1114,6 +1129,9 @@ static int lbs_associate(struct lbs_private *priv,
(u16)(pos - (u8 *) &cmd->iebuf);
cmd->hdr.size = cpu_to_le16(len);
+ lbs_deb_hex(LBS_DEB_ASSOC, "ASSOC_CMD", (u8 *) cmd,
+ le16_to_cpu(cmd->hdr.size));
+
/* store for later use */
memcpy(priv->assoc_bss, bss->bssid, ETH_ALEN);
@@ -1121,14 +1139,28 @@ static int lbs_associate(struct lbs_private *priv,
if (ret)
goto done;
-
/* generate connect message to cfg80211 */
resp = (void *) cmd; /* recast for easier field access */
status = le16_to_cpu(resp->statuscode);
- /* Convert statis code of old firmware */
- if (priv->fwrelease < 0x09000000)
+ /* Older FW versions map the IEEE 802.11 Status Code in the association
+ * response to the following values returned in resp->statuscode:
+ *
+ * IEEE Status Code Marvell Status Code
+ * 0 -> 0x0000 ASSOC_RESULT_SUCCESS
+ * 13 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
+ * 14 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
+ * 15 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
+ * 16 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
+ * others -> 0x0003 ASSOC_RESULT_REFUSED
+ *
+ * Other response codes:
+ * 0x0001 -> ASSOC_RESULT_INVALID_PARAMETERS (unused)
+ * 0x0002 -> ASSOC_RESULT_TIMEOUT (internal timer expired waiting for
+ * association response from the AP)
+ */
+ if (MRVL_FW_MAJOR_REV(priv->fwrelease) <= 8) {
switch (status) {
case 0:
break;
@@ -1150,11 +1182,16 @@ static int lbs_associate(struct lbs_private *priv,
break;
default:
lbs_deb_assoc("association failure %d\n", status);
- status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ /* v5 OLPC firmware does return the AP status code if
+ * it's not one of the values above. Let that through.
+ */
+ break;
+ }
}
- lbs_deb_assoc("status %d, capability 0x%04x\n", status,
- le16_to_cpu(resp->capability));
+ lbs_deb_assoc("status %d, statuscode 0x%04x, capability 0x%04x, "
+ "aid 0x%04x\n", status, le16_to_cpu(resp->statuscode),
+ le16_to_cpu(resp->capability), le16_to_cpu(resp->aid));
resp_ie_len = le16_to_cpu(resp->hdr.size)
- sizeof(resp->hdr)
@@ -1174,7 +1211,6 @@ static int lbs_associate(struct lbs_private *priv,
netif_tx_wake_all_queues(priv->dev);
}
-
done:
lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
return ret;
@@ -1404,7 +1440,7 @@ static int lbs_cfg_set_default_key(struct wiphy *wiphy,
static int lbs_cfg_add_key(struct wiphy *wiphy, struct net_device *netdev,
- u8 idx, const u8 *mac_addr,
+ u8 idx, bool pairwise, const u8 *mac_addr,
struct key_params *params)
{
struct lbs_private *priv = wiphy_priv(wiphy);
@@ -1464,7 +1500,7 @@ static int lbs_cfg_add_key(struct wiphy *wiphy, struct net_device *netdev,
static int lbs_cfg_del_key(struct wiphy *wiphy, struct net_device *netdev,
- u8 key_index, const u8 *mac_addr)
+ u8 key_index, bool pairwise, const u8 *mac_addr)
{
lbs_deb_enter(LBS_DEB_CFG80211);
diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c
index 651a79c8de8a..fbf3b0332bb7 100644
--- a/drivers/net/wireless/libertas/debugfs.c
+++ b/drivers/net/wireless/libertas/debugfs.c
@@ -696,6 +696,7 @@ out_unlock:
.open = open_file_generic, \
.read = (fread), \
.write = (fwrite), \
+ .llseek = generic_file_llseek, \
}
struct lbs_debugfs_files {
@@ -961,6 +962,7 @@ static const struct file_operations lbs_debug_fops = {
.open = open_file_generic,
.write = lbs_debugfs_write,
.read = lbs_debugfs_read,
+ .llseek = default_llseek,
};
/**
diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h
index 1d141fefd767..2ae752d10065 100644
--- a/drivers/net/wireless/libertas/decl.h
+++ b/drivers/net/wireless/libertas/decl.h
@@ -8,7 +8,14 @@
#define _LBS_DECL_H_
#include <linux/netdevice.h>
+#include <linux/firmware.h>
+/* Should be terminated by a NULL entry */
+struct lbs_fw_table {
+ int model;
+ const char *helper;
+ const char *fwname;
+};
struct lbs_private;
struct sk_buff;
@@ -53,4 +60,10 @@ int lbs_exit_auto_deep_sleep(struct lbs_private *priv);
u32 lbs_fw_index_to_data_rate(u8 index);
u8 lbs_data_rate_to_fw_index(u32 rate);
+int lbs_get_firmware(struct device *dev, const char *user_helper,
+ const char *user_mainfw, u32 card_model,
+ const struct lbs_fw_table *fw_table,
+ const struct firmware **helper,
+ const struct firmware **mainfw);
+
#endif
diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c
index 9c298396be50..fc8121190d38 100644
--- a/drivers/net/wireless/libertas/if_cs.c
+++ b/drivers/net/wireless/libertas/if_cs.c
@@ -28,7 +28,6 @@
#include <linux/firmware.h>
#include <linux/netdevice.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
@@ -48,7 +47,6 @@
MODULE_AUTHOR("Holger Schurig <hs4233@mail.mn-solutions.de>");
MODULE_DESCRIPTION("Driver for Marvell 83xx compact flash WLAN cards");
MODULE_LICENSE("GPL");
-MODULE_FIRMWARE("libertas_cs_helper.fw");
@@ -61,9 +59,34 @@ struct if_cs_card {
struct lbs_private *priv;
void __iomem *iobase;
bool align_regs;
+ u32 model;
};
+enum {
+ MODEL_UNKNOWN = 0x00,
+ MODEL_8305 = 0x01,
+ MODEL_8381 = 0x02,
+ MODEL_8385 = 0x03
+};
+
+static const struct lbs_fw_table fw_table[] = {
+ { MODEL_8305, "libertas/cf8305.bin", NULL },
+ { MODEL_8305, "libertas_cs_helper.fw", NULL },
+ { MODEL_8381, "libertas/cf8381_helper.bin", "libertas/cf8381.bin" },
+ { MODEL_8381, "libertas_cs_helper.fw", "libertas_cs.fw" },
+ { MODEL_8385, "libertas/cf8385_helper.bin", "libertas/cf8385.bin" },
+ { MODEL_8385, "libertas_cs_helper.fw", "libertas_cs.fw" },
+ { 0, NULL, NULL }
+};
+MODULE_FIRMWARE("libertas/cf8305.bin");
+MODULE_FIRMWARE("libertas/cf8381_helper.bin");
+MODULE_FIRMWARE("libertas/cf8381.bin");
+MODULE_FIRMWARE("libertas/cf8385_helper.bin");
+MODULE_FIRMWARE("libertas/cf8385.bin");
+MODULE_FIRMWARE("libertas_cs_helper.fw");
+MODULE_FIRMWARE("libertas_cs.fw");
+
/********************************************************************/
/* Hardware access */
@@ -289,22 +312,19 @@ static int if_cs_poll_while_fw_download(struct if_cs_card *card, uint addr, u8 r
#define CF8385_MANFID 0x02df
#define CF8385_CARDID 0x8103
-static inline int if_cs_hw_is_cf8305(struct pcmcia_device *p_dev)
-{
- return (p_dev->manf_id == CF8305_MANFID &&
- p_dev->card_id == CF8305_CARDID);
-}
-
-static inline int if_cs_hw_is_cf8381(struct pcmcia_device *p_dev)
-{
- return (p_dev->manf_id == CF8381_MANFID &&
- p_dev->card_id == CF8381_CARDID);
-}
-
-static inline int if_cs_hw_is_cf8385(struct pcmcia_device *p_dev)
+/* FIXME: just use the 'driver_info' field of 'struct pcmcia_device_id' when
+ * that gets fixed. Currently there's no way to access it from the probe hook.
+ */
+static inline u32 get_model(u16 manf_id, u16 card_id)
{
- return (p_dev->manf_id == CF8385_MANFID &&
- p_dev->card_id == CF8385_CARDID);
+ /* NOTE: keep in sync with if_cs_ids */
+ if (manf_id == CF8305_MANFID && card_id == CF8305_CARDID)
+ return MODEL_8305;
+ else if (manf_id == CF8381_MANFID && card_id == CF8381_CARDID)
+ return MODEL_8381;
+ else if (manf_id == CF8385_MANFID && card_id == CF8385_CARDID)
+ return MODEL_8385;
+ return MODEL_UNKNOWN;
}
/********************************************************************/
@@ -558,12 +578,11 @@ static irqreturn_t if_cs_interrupt(int irq, void *data)
*
* Return 0 on success
*/
-static int if_cs_prog_helper(struct if_cs_card *card)
+static int if_cs_prog_helper(struct if_cs_card *card, const struct firmware *fw)
{
int ret = 0;
int sent = 0;
u8 scratch;
- const struct firmware *fw;
lbs_deb_enter(LBS_DEB_CS);
@@ -589,14 +608,6 @@ static int if_cs_prog_helper(struct if_cs_card *card)
goto done;
}
- /* TODO: make firmware file configurable */
- ret = request_firmware(&fw, "libertas_cs_helper.fw",
- &card->p_dev->dev);
- if (ret) {
- lbs_pr_err("can't load helper firmware\n");
- ret = -ENODEV;
- goto done;
- }
lbs_deb_cs("helper size %td\n", fw->size);
/* "Set the 5 bytes of the helper image to 0" */
@@ -635,7 +646,7 @@ static int if_cs_prog_helper(struct if_cs_card *card)
if (ret < 0) {
lbs_pr_err("can't download helper at 0x%x, ret %d\n",
sent, ret);
- goto err_release;
+ goto done;
}
if (count == 0)
@@ -644,17 +655,14 @@ static int if_cs_prog_helper(struct if_cs_card *card)
sent += count;
}
-err_release:
- release_firmware(fw);
done:
lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret);
return ret;
}
-static int if_cs_prog_real(struct if_cs_card *card)
+static int if_cs_prog_real(struct if_cs_card *card, const struct firmware *fw)
{
- const struct firmware *fw;
int ret = 0;
int retry = 0;
int len = 0;
@@ -662,21 +670,13 @@ static int if_cs_prog_real(struct if_cs_card *card)
lbs_deb_enter(LBS_DEB_CS);
- /* TODO: make firmware file configurable */
- ret = request_firmware(&fw, "libertas_cs.fw",
- &card->p_dev->dev);
- if (ret) {
- lbs_pr_err("can't load firmware\n");
- ret = -ENODEV;
- goto done;
- }
lbs_deb_cs("fw size %td\n", fw->size);
ret = if_cs_poll_while_fw_download(card, IF_CS_SQ_READ_LOW,
IF_CS_SQ_HELPER_OK);
if (ret < 0) {
lbs_pr_err("helper firmware doesn't answer\n");
- goto err_release;
+ goto done;
}
for (sent = 0; sent < fw->size; sent += len) {
@@ -691,7 +691,7 @@ static int if_cs_prog_real(struct if_cs_card *card)
if (retry > 20) {
lbs_pr_err("could not download firmware\n");
ret = -ENODEV;
- goto err_release;
+ goto done;
}
if (retry) {
sent -= len;
@@ -710,7 +710,7 @@ static int if_cs_prog_real(struct if_cs_card *card)
IF_CS_BIT_COMMAND);
if (ret < 0) {
lbs_pr_err("can't download firmware at 0x%x\n", sent);
- goto err_release;
+ goto done;
}
}
@@ -718,9 +718,6 @@ static int if_cs_prog_real(struct if_cs_card *card)
if (ret < 0)
lbs_pr_err("firmware download failed\n");
-err_release:
- release_firmware(fw);
-
done:
lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret);
return ret;
@@ -761,15 +758,6 @@ static int if_cs_host_to_card(struct lbs_private *priv,
}
-/********************************************************************/
-/* Card Services */
-/********************************************************************/
-
-/*
- * After a card is removed, if_cs_release() will unregister the
- * device, and release the PCMCIA configuration. If the device is
- * still open, this will be postponed until it is closed.
- */
static void if_cs_release(struct pcmcia_device *p_dev)
{
struct if_cs_card *card = p_dev->priv;
@@ -785,31 +773,12 @@ static void if_cs_release(struct pcmcia_device *p_dev)
}
-/*
- * This creates an "instance" of the driver, allocating local data
- * structures for one device. The device is registered with Card
- * Services.
- *
- * The dev_link structure is initialized, but we don't actually
- * configure the card at this point -- we wait until we receive a card
- * insertion event.
- */
-
-static int if_cs_ioprobe(struct pcmcia_device *p_dev,
- cistpl_cftable_entry_t *cfg,
- cistpl_cftable_entry_t *dflt,
- unsigned int vcc,
- void *priv_data)
+static int if_cs_ioprobe(struct pcmcia_device *p_dev, void *priv_data)
{
+ p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
- p_dev->resource[0]->start = cfg->io.win[0].base;
- p_dev->resource[0]->end = cfg->io.win[0].len;
-
- /* Do we need to allocate an interrupt? */
- p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
- /* IO window settings */
- if (cfg->io.nwin != 1) {
+ if (p_dev->resource[1]->end) {
lbs_pr_err("wrong CIS (check number of IO windows)\n");
return -ENODEV;
}
@@ -824,6 +793,8 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
unsigned int prod_id;
struct lbs_private *priv;
struct if_cs_card *card;
+ const struct firmware *helper = NULL;
+ const struct firmware *mainfw = NULL;
lbs_deb_enter(LBS_DEB_CS);
@@ -835,15 +806,13 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
card->p_dev = p_dev;
p_dev->priv = card;
- p_dev->conf.Attributes = 0;
- p_dev->conf.IntType = INT_MEMORY_AND_IO;
+ p_dev->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
if (pcmcia_loop_config(p_dev, if_cs_ioprobe, NULL)) {
lbs_pr_err("error in pcmcia_loop_config\n");
goto out1;
}
-
/*
* Allocate an interrupt line. Note that this does not assign
* a handler to the interrupt, unless the 'Handler' member of
@@ -861,14 +830,9 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
goto out1;
}
- /*
- * This actually configures the PCMCIA socket -- setting up
- * the I/O windows and the interrupt mapping, and putting the
- * card and host interface into "Memory and IO" mode.
- */
- ret = pcmcia_request_configuration(p_dev, &p_dev->conf);
+ ret = pcmcia_enable_device(p_dev);
if (ret) {
- lbs_pr_err("error in pcmcia_request_configuration\n");
+ lbs_pr_err("error in pcmcia_enable_device\n");
goto out2;
}
@@ -881,34 +845,47 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
*/
card->align_regs = 0;
+ card->model = get_model(p_dev->manf_id, p_dev->card_id);
+ if (card->model == MODEL_UNKNOWN) {
+ lbs_pr_err("unsupported manf_id 0x%04x / card_id 0x%04x\n",
+ p_dev->manf_id, p_dev->card_id);
+ goto out2;
+ }
+
/* Check if we have a current silicon */
prod_id = if_cs_read8(card, IF_CS_PRODUCT_ID);
- if (if_cs_hw_is_cf8305(p_dev)) {
+ if (card->model == MODEL_8305) {
card->align_regs = 1;
if (prod_id < IF_CS_CF8305_B1_REV) {
- lbs_pr_err("old chips like 8305 rev B3 "
- "aren't supported\n");
+ lbs_pr_err("8305 rev B0 and older are not supported\n");
ret = -ENODEV;
goto out2;
}
}
- if (if_cs_hw_is_cf8381(p_dev) && prod_id < IF_CS_CF8381_B3_REV) {
- lbs_pr_err("old chips like 8381 rev B3 aren't supported\n");
+ if ((card->model == MODEL_8381) && prod_id < IF_CS_CF8381_B3_REV) {
+ lbs_pr_err("8381 rev B2 and older are not supported\n");
ret = -ENODEV;
goto out2;
}
- if (if_cs_hw_is_cf8385(p_dev) && prod_id < IF_CS_CF8385_B1_REV) {
- lbs_pr_err("old chips like 8385 rev B1 aren't supported\n");
+ if ((card->model == MODEL_8385) && prod_id < IF_CS_CF8385_B1_REV) {
+ lbs_pr_err("8385 rev B0 and older are not supported\n");
ret = -ENODEV;
goto out2;
}
+ ret = lbs_get_firmware(&p_dev->dev, NULL, NULL, card->model,
+ &fw_table[0], &helper, &mainfw);
+ if (ret) {
+ lbs_pr_err("failed to find firmware (%d)\n", ret);
+ goto out2;
+ }
+
/* Load the firmware early, before calling into libertas.ko */
- ret = if_cs_prog_helper(card);
- if (ret == 0 && !if_cs_hw_is_cf8305(p_dev))
- ret = if_cs_prog_real(card);
+ ret = if_cs_prog_helper(card, helper);
+ if (ret == 0 && (card->model != MODEL_8305))
+ ret = if_cs_prog_real(card, mainfw);
if (ret)
goto out2;
@@ -957,17 +934,16 @@ out2:
out1:
pcmcia_disable_device(p_dev);
out:
+ if (helper)
+ release_firmware(helper);
+ if (mainfw)
+ release_firmware(mainfw);
+
lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret);
return ret;
}
-/*
- * This deletes a driver "instance". The device is de-registered with
- * Card Services. If it has been released, all local data structures
- * are freed. Otherwise, the structures will be freed when the device
- * is released.
- */
static void if_cs_detach(struct pcmcia_device *p_dev)
{
struct if_cs_card *card = p_dev->priv;
@@ -993,6 +969,7 @@ static struct pcmcia_device_id if_cs_ids[] = {
PCMCIA_DEVICE_MANF_CARD(CF8305_MANFID, CF8305_CARDID),
PCMCIA_DEVICE_MANF_CARD(CF8381_MANFID, CF8381_CARDID),
PCMCIA_DEVICE_MANF_CARD(CF8385_MANFID, CF8385_CARDID),
+ /* NOTE: keep in sync with get_model() */
PCMCIA_DEVICE_NULL,
};
MODULE_DEVICE_TABLE(pcmcia, if_cs_ids);
@@ -1000,9 +977,7 @@ MODULE_DEVICE_TABLE(pcmcia, if_cs_ids);
static struct pcmcia_driver lbs_driver = {
.owner = THIS_MODULE,
- .drv = {
- .name = DRV_NAME,
- },
+ .name = DRV_NAME,
.probe = if_cs_probe,
.remove = if_cs_detach,
.id_table = if_cs_ids,
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c
index 87b634978b35..296fd00a5129 100644
--- a/drivers/net/wireless/libertas/if_sdio.c
+++ b/drivers/net/wireless/libertas/if_sdio.c
@@ -76,36 +76,32 @@ static const struct sdio_device_id if_sdio_ids[] = {
MODULE_DEVICE_TABLE(sdio, if_sdio_ids);
-struct if_sdio_model {
- int model;
- const char *helper;
- const char *firmware;
-};
-
-static struct if_sdio_model if_sdio_models[] = {
- {
- /* 8385 */
- .model = IF_SDIO_MODEL_8385,
- .helper = "sd8385_helper.bin",
- .firmware = "sd8385.bin",
- },
- {
- /* 8686 */
- .model = IF_SDIO_MODEL_8686,
- .helper = "sd8686_helper.bin",
- .firmware = "sd8686.bin",
- },
- {
- /* 8688 */
- .model = IF_SDIO_MODEL_8688,
- .helper = "sd8688_helper.bin",
- .firmware = "sd8688.bin",
- },
+#define MODEL_8385 0x04
+#define MODEL_8686 0x0b
+#define MODEL_8688 0x10
+
+static const struct lbs_fw_table fw_table[] = {
+ { MODEL_8385, "libertas/sd8385_helper.bin", "libertas/sd8385.bin" },
+ { MODEL_8385, "sd8385_helper.bin", "sd8385.bin" },
+ { MODEL_8686, "libertas/sd8686_v9_helper.bin", "libertas/sd8686_v9.bin" },
+ { MODEL_8686, "libertas/sd8686_v8_helper.bin", "libertas/sd8686_v8.bin" },
+ { MODEL_8686, "sd8686_helper.bin", "sd8686.bin" },
+ { MODEL_8688, "libertas/sd8688_helper.bin", "libertas/sd8688.bin" },
+ { MODEL_8688, "sd8688_helper.bin", "sd8688.bin" },
+ { 0, NULL, NULL }
};
+MODULE_FIRMWARE("libertas/sd8385_helper.bin");
+MODULE_FIRMWARE("libertas/sd8385.bin");
MODULE_FIRMWARE("sd8385_helper.bin");
MODULE_FIRMWARE("sd8385.bin");
+MODULE_FIRMWARE("libertas/sd8686_v9_helper.bin");
+MODULE_FIRMWARE("libertas/sd8686_v9.bin");
+MODULE_FIRMWARE("libertas/sd8686_v8_helper.bin");
+MODULE_FIRMWARE("libertas/sd8686_v8.bin");
MODULE_FIRMWARE("sd8686_helper.bin");
MODULE_FIRMWARE("sd8686.bin");
+MODULE_FIRMWARE("libertas/sd8688_helper.bin");
+MODULE_FIRMWARE("libertas/sd8688.bin");
MODULE_FIRMWARE("sd8688_helper.bin");
MODULE_FIRMWARE("sd8688.bin");
@@ -187,11 +183,11 @@ static u16 if_sdio_read_rx_len(struct if_sdio_card *card, int *err)
u16 rx_len;
switch (card->model) {
- case IF_SDIO_MODEL_8385:
- case IF_SDIO_MODEL_8686:
+ case MODEL_8385:
+ case MODEL_8686:
rx_len = if_sdio_read_scratch(card, &ret);
break;
- case IF_SDIO_MODEL_8688:
+ case MODEL_8688:
default: /* for newer chipsets */
rx_len = sdio_readb(card->func, IF_SDIO_RX_LEN, &ret);
if (!ret)
@@ -288,7 +284,7 @@ static int if_sdio_handle_event(struct if_sdio_card *card,
lbs_deb_enter(LBS_DEB_SDIO);
- if (card->model == IF_SDIO_MODEL_8385) {
+ if (card->model == MODEL_8385) {
event = sdio_readb(card->func, IF_SDIO_EVENT, &ret);
if (ret)
goto out;
@@ -466,10 +462,10 @@ static void if_sdio_host_to_card_worker(struct work_struct *work)
#define FW_DL_READY_STATUS (IF_SDIO_IO_RDY | IF_SDIO_DL_RDY)
-static int if_sdio_prog_helper(struct if_sdio_card *card)
+static int if_sdio_prog_helper(struct if_sdio_card *card,
+ const struct firmware *fw)
{
int ret;
- const struct firmware *fw;
unsigned long timeout;
u8 *chunk_buffer;
u32 chunk_size;
@@ -478,16 +474,10 @@ static int if_sdio_prog_helper(struct if_sdio_card *card)
lbs_deb_enter(LBS_DEB_SDIO);
- ret = request_firmware(&fw, card->helper, &card->func->dev);
- if (ret) {
- lbs_pr_err("can't load helper firmware\n");
- goto out;
- }
-
chunk_buffer = kzalloc(64, GFP_KERNEL);
if (!chunk_buffer) {
ret = -ENOMEM;
- goto release_fw;
+ goto out;
}
sdio_claim_host(card->func);
@@ -562,22 +552,19 @@ static int if_sdio_prog_helper(struct if_sdio_card *card)
release:
sdio_release_host(card->func);
kfree(chunk_buffer);
-release_fw:
- release_firmware(fw);
out:
if (ret)
lbs_pr_err("failed to load helper firmware\n");
lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
-
return ret;
}
-static int if_sdio_prog_real(struct if_sdio_card *card)
+static int if_sdio_prog_real(struct if_sdio_card *card,
+ const struct firmware *fw)
{
int ret;
- const struct firmware *fw;
unsigned long timeout;
u8 *chunk_buffer;
u32 chunk_size;
@@ -586,16 +573,10 @@ static int if_sdio_prog_real(struct if_sdio_card *card)
lbs_deb_enter(LBS_DEB_SDIO);
- ret = request_firmware(&fw, card->firmware, &card->func->dev);
- if (ret) {
- lbs_pr_err("can't load firmware\n");
- goto out;
- }
-
chunk_buffer = kzalloc(512, GFP_KERNEL);
if (!chunk_buffer) {
ret = -ENOMEM;
- goto release_fw;
+ goto out;
}
sdio_claim_host(card->func);
@@ -685,15 +666,12 @@ static int if_sdio_prog_real(struct if_sdio_card *card)
release:
sdio_release_host(card->func);
kfree(chunk_buffer);
-release_fw:
- release_firmware(fw);
out:
if (ret)
lbs_pr_err("failed to load firmware\n");
lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
-
return ret;
}
@@ -701,6 +679,8 @@ static int if_sdio_prog_firmware(struct if_sdio_card *card)
{
int ret;
u16 scratch;
+ const struct firmware *helper = NULL;
+ const struct firmware *mainfw = NULL;
lbs_deb_enter(LBS_DEB_SDIO);
@@ -718,11 +698,18 @@ static int if_sdio_prog_firmware(struct if_sdio_card *card)
goto success;
}
- ret = if_sdio_prog_helper(card);
+ ret = lbs_get_firmware(&card->func->dev, lbs_helper_name, lbs_fw_name,
+ card->model, &fw_table[0], &helper, &mainfw);
+ if (ret) {
+ lbs_pr_err("failed to find firmware (%d)\n", ret);
+ goto out;
+ }
+
+ ret = if_sdio_prog_helper(card, helper);
if (ret)
goto out;
- ret = if_sdio_prog_real(card);
+ ret = if_sdio_prog_real(card, mainfw);
if (ret)
goto out;
@@ -733,8 +720,12 @@ success:
ret = 0;
out:
- lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
+ if (helper)
+ release_firmware(helper);
+ if (mainfw)
+ release_firmware(mainfw);
+ lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
return ret;
}
@@ -938,7 +929,7 @@ static int if_sdio_probe(struct sdio_func *func,
"ID: %x", &model) == 1)
break;
if (!strcmp(func->card->info[i], "IBIS Wireless SDIO Card")) {
- model = IF_SDIO_MODEL_8385;
+ model = MODEL_8385;
break;
}
}
@@ -956,13 +947,13 @@ static int if_sdio_probe(struct sdio_func *func,
card->model = model;
switch (card->model) {
- case IF_SDIO_MODEL_8385:
+ case MODEL_8385:
card->scratch_reg = IF_SDIO_SCRATCH_OLD;
break;
- case IF_SDIO_MODEL_8686:
+ case MODEL_8686:
card->scratch_reg = IF_SDIO_SCRATCH;
break;
- case IF_SDIO_MODEL_8688:
+ case MODEL_8688:
default: /* for newer chipsets */
card->scratch_reg = IF_SDIO_FW_STATUS;
break;
@@ -972,49 +963,17 @@ static int if_sdio_probe(struct sdio_func *func,
card->workqueue = create_workqueue("libertas_sdio");
INIT_WORK(&card->packet_worker, if_sdio_host_to_card_worker);
- for (i = 0;i < ARRAY_SIZE(if_sdio_models);i++) {
- if (card->model == if_sdio_models[i].model)
+ /* Check if we support this card */
+ for (i = 0; i < ARRAY_SIZE(fw_table); i++) {
+ if (card->model == fw_table[i].model)
break;
}
-
- if (i == ARRAY_SIZE(if_sdio_models)) {
+ if (i == ARRAY_SIZE(fw_table)) {
lbs_pr_err("unknown card model 0x%x\n", card->model);
ret = -ENODEV;
goto free;
}
- card->helper = if_sdio_models[i].helper;
- card->firmware = if_sdio_models[i].firmware;
-
- kparam_block_sysfs_write(helper_name);
- if (lbs_helper_name) {
- char *helper = kstrdup(lbs_helper_name, GFP_KERNEL);
- if (!helper) {
- kparam_unblock_sysfs_write(helper_name);
- ret = -ENOMEM;
- goto free;
- }
- lbs_deb_sdio("overriding helper firmware: %s\n",
- lbs_helper_name);
- card->helper = helper;
- card->helper_allocated = true;
- }
- kparam_unblock_sysfs_write(helper_name);
-
- kparam_block_sysfs_write(fw_name);
- if (lbs_fw_name) {
- char *fw_name = kstrdup(lbs_fw_name, GFP_KERNEL);
- if (!fw_name) {
- kparam_unblock_sysfs_write(fw_name);
- ret = -ENOMEM;
- goto free;
- }
- lbs_deb_sdio("overriding firmware: %s\n", lbs_fw_name);
- card->firmware = fw_name;
- card->firmware_allocated = true;
- }
- kparam_unblock_sysfs_write(fw_name);
-
sdio_claim_host(func);
ret = sdio_enable_func(func);
@@ -1028,7 +987,7 @@ static int if_sdio_probe(struct sdio_func *func,
/* For 1-bit transfers to the 8686 model, we need to enable the
* interrupt flag in the CCCR register. Set the MMC_QUIRK_LENIENT_FN0
* bit to allow access to non-vendor registers. */
- if ((card->model == IF_SDIO_MODEL_8686) &&
+ if ((card->model == MODEL_8686) &&
(host->caps & MMC_CAP_SDIO_IRQ) &&
(host->ios.bus_width == MMC_BUS_WIDTH_1)) {
u8 reg;
@@ -1091,8 +1050,8 @@ static int if_sdio_probe(struct sdio_func *func,
* Get rx_unit if the chip is SD8688 or newer.
* SD8385 & SD8686 do not have rx_unit.
*/
- if ((card->model != IF_SDIO_MODEL_8385)
- && (card->model != IF_SDIO_MODEL_8686))
+ if ((card->model != MODEL_8385)
+ && (card->model != MODEL_8686))
card->rx_unit = if_sdio_read_rx_unit(card);
else
card->rx_unit = 0;
@@ -1108,7 +1067,7 @@ static int if_sdio_probe(struct sdio_func *func,
/*
* FUNC_INIT is required for SD8688 WLAN/BT multiple functions
*/
- if (card->model == IF_SDIO_MODEL_8688) {
+ if (card->model == MODEL_8688) {
struct cmd_header cmd;
memset(&cmd, 0, sizeof(cmd));
@@ -1165,7 +1124,7 @@ static void if_sdio_remove(struct sdio_func *func)
card = sdio_get_drvdata(func);
- if (user_rmmod && (card->model == IF_SDIO_MODEL_8688)) {
+ if (user_rmmod && (card->model == MODEL_8688)) {
/*
* FUNC_SHUTDOWN is required for SD8688 WLAN/BT
* multiple functions
diff --git a/drivers/net/wireless/libertas/if_sdio.h b/drivers/net/wireless/libertas/if_sdio.h
index 12179c1dc9c9..62fda3592f67 100644
--- a/drivers/net/wireless/libertas/if_sdio.h
+++ b/drivers/net/wireless/libertas/if_sdio.h
@@ -12,10 +12,6 @@
#ifndef _LBS_IF_SDIO_H
#define _LBS_IF_SDIO_H
-#define IF_SDIO_MODEL_8385 0x04
-#define IF_SDIO_MODEL_8686 0x0b
-#define IF_SDIO_MODEL_8688 0x10
-
#define IF_SDIO_IOPORT 0x00
#define IF_SDIO_H_INT_MASK 0x04
diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c
index fe3f08028eb3..79bcb4e5d2ca 100644
--- a/drivers/net/wireless/libertas/if_spi.c
+++ b/drivers/net/wireless/libertas/if_spi.c
@@ -39,9 +39,6 @@ struct if_spi_card {
struct lbs_private *priv;
struct libertas_spi_platform_data *pdata;
- char helper_fw_name[IF_SPI_FW_NAME_MAX];
- char main_fw_name[IF_SPI_FW_NAME_MAX];
-
/* The card ID and card revision, as reported by the hardware. */
u16 card_id;
u8 card_rev;
@@ -70,10 +67,28 @@ static void free_if_spi_card(struct if_spi_card *card)
kfree(card);
}
-static struct chip_ident chip_id_to_device_name[] = {
- { .chip_id = 0x04, .name = 8385 },
- { .chip_id = 0x0b, .name = 8686 },
+#define MODEL_8385 0x04
+#define MODEL_8686 0x0b
+#define MODEL_8688 0x10
+
+static const struct lbs_fw_table fw_table[] = {
+ { MODEL_8385, "libertas/gspi8385_helper.bin", "libertas/gspi8385.bin" },
+ { MODEL_8385, "libertas/gspi8385_hlp.bin", "libertas/gspi8385.bin" },
+ { MODEL_8686, "libertas/gspi8686_v9_helper.bin", "libertas/gspi8686_v9.bin" },
+ { MODEL_8686, "libertas/gspi8686_hlp.bin", "libertas/gspi8686.bin" },
+ { MODEL_8688, "libertas/gspi8688_helper.bin", "libertas/gspi8688.bin" },
+ { 0, NULL, NULL }
};
+MODULE_FIRMWARE("libertas/gspi8385_helper.bin");
+MODULE_FIRMWARE("libertas/gspi8385_hlp.bin");
+MODULE_FIRMWARE("libertas/gspi8385.bin");
+MODULE_FIRMWARE("libertas/gspi8686_v9_helper.bin");
+MODULE_FIRMWARE("libertas/gspi8686_v9.bin");
+MODULE_FIRMWARE("libertas/gspi8686_hlp.bin");
+MODULE_FIRMWARE("libertas/gspi8686.bin");
+MODULE_FIRMWARE("libertas/gspi8688_helper.bin");
+MODULE_FIRMWARE("libertas/gspi8688.bin");
+
/*
* SPI Interface Unit Routines
@@ -399,26 +414,20 @@ static int spu_init(struct if_spi_card *card, int use_dummy_writes)
* Firmware Loading
*/
-static int if_spi_prog_helper_firmware(struct if_spi_card *card)
+static int if_spi_prog_helper_firmware(struct if_spi_card *card,
+ const struct firmware *firmware)
{
int err = 0;
- const struct firmware *firmware = NULL;
int bytes_remaining;
const u8 *fw;
u8 temp[HELPER_FW_LOAD_CHUNK_SZ];
- struct spi_device *spi = card->spi;
lbs_deb_enter(LBS_DEB_SPI);
err = spu_set_interrupt_mode(card, 1, 0);
if (err)
goto out;
- /* Get helper firmware image */
- err = request_firmware(&firmware, card->helper_fw_name, &spi->dev);
- if (err) {
- lbs_pr_err("request_firmware failed with err = %d\n", err);
- goto out;
- }
+
bytes_remaining = firmware->size;
fw = firmware->data;
@@ -429,13 +438,13 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card)
err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG,
HELPER_FW_LOAD_CHUNK_SZ);
if (err)
- goto release_firmware;
+ goto out;
err = spu_wait_for_u16(card, IF_SPI_HOST_INT_STATUS_REG,
IF_SPI_HIST_CMD_DOWNLOAD_RDY,
IF_SPI_HIST_CMD_DOWNLOAD_RDY);
if (err)
- goto release_firmware;
+ goto out;
/* Feed the data into the command read/write port reg
* in chunks of 64 bytes */
@@ -446,16 +455,16 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card)
err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG,
temp, HELPER_FW_LOAD_CHUNK_SZ);
if (err)
- goto release_firmware;
+ goto out;
/* Interrupt the boot code */
err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0);
if (err)
- goto release_firmware;
+ goto out;
err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG,
IF_SPI_CIC_CMD_DOWNLOAD_OVER);
if (err)
- goto release_firmware;
+ goto out;
bytes_remaining -= HELPER_FW_LOAD_CHUNK_SZ;
fw += HELPER_FW_LOAD_CHUNK_SZ;
}
@@ -465,18 +474,16 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card)
* bootloader. This completes the helper download. */
err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG, FIRMWARE_DNLD_OK);
if (err)
- goto release_firmware;
+ goto out;
err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0);
if (err)
- goto release_firmware;
+ goto out;
err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG,
IF_SPI_CIC_CMD_DOWNLOAD_OVER);
- goto release_firmware;
+ goto out;
lbs_deb_spi("waiting for helper to boot...\n");
-release_firmware:
- release_firmware(firmware);
out:
if (err)
lbs_pr_err("failed to load helper firmware (err=%d)\n", err);
@@ -523,13 +530,12 @@ static int if_spi_prog_main_firmware_check_len(struct if_spi_card *card,
return len;
}
-static int if_spi_prog_main_firmware(struct if_spi_card *card)
+static int if_spi_prog_main_firmware(struct if_spi_card *card,
+ const struct firmware *firmware)
{
int len, prev_len;
int bytes, crc_err = 0, err = 0;
- const struct firmware *firmware = NULL;
const u8 *fw;
- struct spi_device *spi = card->spi;
u16 num_crc_errs;
lbs_deb_enter(LBS_DEB_SPI);
@@ -538,19 +544,11 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card)
if (err)
goto out;
- /* Get firmware image */
- err = request_firmware(&firmware, card->main_fw_name, &spi->dev);
- if (err) {
- lbs_pr_err("%s: can't get firmware '%s' from kernel. "
- "err = %d\n", __func__, card->main_fw_name, err);
- goto out;
- }
-
err = spu_wait_for_u16(card, IF_SPI_SCRATCH_1_REG, 0, 0);
if (err) {
lbs_pr_err("%s: timed out waiting for initial "
"scratch reg = 0\n", __func__);
- goto release_firmware;
+ goto out;
}
num_crc_errs = 0;
@@ -560,7 +558,7 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card)
while ((len = if_spi_prog_main_firmware_check_len(card, &crc_err))) {
if (len < 0) {
err = len;
- goto release_firmware;
+ goto out;
}
if (bytes < 0) {
/* If there are no more bytes left, we would normally
@@ -575,7 +573,7 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card)
lbs_pr_err("Too many CRC errors encountered "
"in firmware load.\n");
err = -EIO;
- goto release_firmware;
+ goto out;
}
} else {
/* Previous transfer succeeded. Advance counters. */
@@ -590,15 +588,15 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card)
err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0);
if (err)
- goto release_firmware;
+ goto out;
err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG,
card->cmd_buffer, len);
if (err)
- goto release_firmware;
+ goto out;
err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG ,
IF_SPI_CIC_CMD_DOWNLOAD_OVER);
if (err)
- goto release_firmware;
+ goto out;
prev_len = len;
}
if (bytes > prev_len) {
@@ -611,12 +609,9 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card)
SUCCESSFUL_FW_DOWNLOAD_MAGIC);
if (err) {
lbs_pr_err("failed to confirm the firmware download\n");
- goto release_firmware;
+ goto out;
}
-release_firmware:
- release_firmware(firmware);
-
out:
if (err)
lbs_pr_err("failed to load firmware (err=%d)\n", err);
@@ -800,14 +795,16 @@ static int lbs_spi_thread(void *data)
goto err;
}
- if (hiStatus & IF_SPI_HIST_CMD_UPLOAD_RDY)
+ if (hiStatus & IF_SPI_HIST_CMD_UPLOAD_RDY) {
err = if_spi_c2h_cmd(card);
if (err)
goto err;
- if (hiStatus & IF_SPI_HIST_RX_UPLOAD_RDY)
+ }
+ if (hiStatus & IF_SPI_HIST_RX_UPLOAD_RDY) {
err = if_spi_c2h_data(card);
if (err)
goto err;
+ }
/* workaround: in PS mode, the card does not set the Command
* Download Ready bit, but it sets TX Download Ready. */
@@ -886,37 +883,16 @@ static irqreturn_t if_spi_host_interrupt(int irq, void *dev_id)
* SPI callbacks
*/
-static int if_spi_calculate_fw_names(u16 card_id,
- char *helper_fw, char *main_fw)
-{
- int i;
- for (i = 0; i < ARRAY_SIZE(chip_id_to_device_name); ++i) {
- if (card_id == chip_id_to_device_name[i].chip_id)
- break;
- }
- if (i == ARRAY_SIZE(chip_id_to_device_name)) {
- lbs_pr_err("Unsupported chip_id: 0x%02x\n", card_id);
- return -EAFNOSUPPORT;
- }
- snprintf(helper_fw, IF_SPI_FW_NAME_MAX, "libertas/gspi%d_hlp.bin",
- chip_id_to_device_name[i].name);
- snprintf(main_fw, IF_SPI_FW_NAME_MAX, "libertas/gspi%d.bin",
- chip_id_to_device_name[i].name);
- return 0;
-}
-MODULE_FIRMWARE("libertas/gspi8385_hlp.bin");
-MODULE_FIRMWARE("libertas/gspi8385.bin");
-MODULE_FIRMWARE("libertas/gspi8686_hlp.bin");
-MODULE_FIRMWARE("libertas/gspi8686.bin");
-
static int __devinit if_spi_probe(struct spi_device *spi)
{
struct if_spi_card *card;
struct lbs_private *priv = NULL;
struct libertas_spi_platform_data *pdata = spi->dev.platform_data;
- int err = 0;
+ int err = 0, i;
u32 scratch;
struct sched_param param = { .sched_priority = 1 };
+ const struct firmware *helper = NULL;
+ const struct firmware *mainfw = NULL;
lbs_deb_enter(LBS_DEB_SPI);
@@ -961,10 +937,25 @@ static int __devinit if_spi_probe(struct spi_device *spi)
lbs_deb_spi("Firmware is already loaded for "
"Marvell WLAN 802.11 adapter\n");
else {
- err = if_spi_calculate_fw_names(card->card_id,
- card->helper_fw_name, card->main_fw_name);
- if (err)
+ /* Check if we support this card */
+ for (i = 0; i < ARRAY_SIZE(fw_table); i++) {
+ if (card->card_id == fw_table[i].model)
+ break;
+ }
+ if (i == ARRAY_SIZE(fw_table)) {
+ lbs_pr_err("Unsupported chip_id: 0x%02x\n",
+ card->card_id);
+ err = -ENODEV;
goto free_card;
+ }
+
+ err = lbs_get_firmware(&card->spi->dev, NULL, NULL,
+ card->card_id, &fw_table[0], &helper,
+ &mainfw);
+ if (err) {
+ lbs_pr_err("failed to find firmware (%d)\n", err);
+ goto free_card;
+ }
lbs_deb_spi("Initializing FW for Marvell WLAN 802.11 adapter "
"(chip_id = 0x%04x, chip_rev = 0x%02x) "
@@ -973,10 +964,10 @@ static int __devinit if_spi_probe(struct spi_device *spi)
card->card_id, card->card_rev,
spi->master->bus_num, spi->chip_select,
spi->max_speed_hz);
- err = if_spi_prog_helper_firmware(card);
+ err = if_spi_prog_helper_firmware(card, helper);
if (err)
goto free_card;
- err = if_spi_prog_main_firmware(card);
+ err = if_spi_prog_main_firmware(card, mainfw);
if (err)
goto free_card;
lbs_deb_spi("loaded FW for Marvell WLAN 802.11 adapter\n");
@@ -1044,6 +1035,11 @@ remove_card:
free_card:
free_if_spi_card(card);
out:
+ if (helper)
+ release_firmware(helper);
+ if (mainfw)
+ release_firmware(mainfw);
+
lbs_deb_leave_args(LBS_DEB_SPI, "err %d\n", err);
return err;
}
diff --git a/drivers/net/wireless/libertas/if_spi.h b/drivers/net/wireless/libertas/if_spi.h
index f87eec410848..8b1417d3b71b 100644
--- a/drivers/net/wireless/libertas/if_spi.h
+++ b/drivers/net/wireless/libertas/if_spi.h
@@ -25,11 +25,6 @@
#define IF_SPI_FW_NAME_MAX 30
-struct chip_ident {
- u16 chip_id;
- u16 name;
-};
-
#define MAX_MAIN_FW_LOAD_CRC_ERR 10
/* Chunk size when loading the helper firmware */
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
index 3ff61063671a..efaf85032208 100644
--- a/drivers/net/wireless/libertas/if_usb.c
+++ b/drivers/net/wireless/libertas/if_usb.c
@@ -26,15 +26,25 @@
#define MESSAGE_HEADER_LEN 4
-static char *lbs_fw_name = "usb8388.bin";
+static char *lbs_fw_name = NULL;
module_param_named(fw_name, lbs_fw_name, charp, 0644);
+MODULE_FIRMWARE("libertas/usb8388_v9.bin");
+MODULE_FIRMWARE("libertas/usb8388_v5.bin");
+MODULE_FIRMWARE("libertas/usb8388.bin");
+MODULE_FIRMWARE("libertas/usb8682.bin");
MODULE_FIRMWARE("usb8388.bin");
+enum {
+ MODEL_UNKNOWN = 0x0,
+ MODEL_8388 = 0x1,
+ MODEL_8682 = 0x2
+};
+
static struct usb_device_id if_usb_table[] = {
/* Enter the device signature inside */
- { USB_DEVICE(0x1286, 0x2001) },
- { USB_DEVICE(0x05a3, 0x8388) },
+ { USB_DEVICE(0x1286, 0x2001), .driver_info = MODEL_8388 },
+ { USB_DEVICE(0x05a3, 0x8388), .driver_info = MODEL_8388 },
{} /* Terminating entry */
};
@@ -66,6 +76,8 @@ static ssize_t if_usb_firmware_set(struct device *dev,
struct if_usb_card *cardp = priv->card;
int ret;
+ BUG_ON(buf == NULL);
+
ret = if_usb_prog_firmware(cardp, buf, BOOT_CMD_UPDATE_FW);
if (ret == 0)
return count;
@@ -91,6 +103,8 @@ static ssize_t if_usb_boot2_set(struct device *dev,
struct if_usb_card *cardp = priv->card;
int ret;
+ BUG_ON(buf == NULL);
+
ret = if_usb_prog_firmware(cardp, buf, BOOT_CMD_UPDATE_BOOT2);
if (ret == 0)
return count;
@@ -244,6 +258,7 @@ static int if_usb_probe(struct usb_interface *intf,
init_waitqueue_head(&cardp->fw_wq);
cardp->udev = udev;
+ cardp->model = (uint32_t) id->driver_info;
iface_desc = intf->cur_altsetting;
lbs_deb_usbd(&udev->dev, "bcdUSB = 0x%X bDeviceClass = 0x%X"
@@ -472,11 +487,12 @@ static int if_usb_reset_device(struct if_usb_card *cardp)
*/
static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, uint16_t nb)
{
- int ret = -1;
+ int ret;
/* check if device is removed */
if (cardp->surprise_removed) {
lbs_deb_usbd(&cardp->udev->dev, "Device removed\n");
+ ret = -ENODEV;
goto tx_ret;
}
@@ -489,7 +505,6 @@ static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, uint16_t nb
if ((ret = usb_submit_urb(cardp->tx_urb, GFP_ATOMIC))) {
lbs_deb_usbd(&cardp->udev->dev, "usb_submit_urb failed: %d\n", ret);
- ret = -1;
} else {
lbs_deb_usb2(&cardp->udev->dev, "usb_submit_urb success\n");
ret = 0;
@@ -924,6 +939,38 @@ static int if_usb_prog_firmware(struct if_usb_card *cardp,
return ret;
}
+/* table of firmware file names */
+static const struct {
+ u32 model;
+ const char *fwname;
+} fw_table[] = {
+ { MODEL_8388, "libertas/usb8388_v9.bin" },
+ { MODEL_8388, "libertas/usb8388_v5.bin" },
+ { MODEL_8388, "libertas/usb8388.bin" },
+ { MODEL_8388, "usb8388.bin" },
+ { MODEL_8682, "libertas/usb8682.bin" }
+};
+
+static int get_fw(struct if_usb_card *cardp, const char *fwname)
+{
+ int i;
+
+ /* Try user-specified firmware first */
+ if (fwname)
+ return request_firmware(&cardp->fw, fwname, &cardp->udev->dev);
+
+ /* Otherwise search for firmware to use */
+ for (i = 0; i < ARRAY_SIZE(fw_table); i++) {
+ if (fw_table[i].model != cardp->model)
+ continue;
+ if (request_firmware(&cardp->fw, fw_table[i].fwname,
+ &cardp->udev->dev) == 0)
+ return 0;
+ }
+
+ return -ENOENT;
+}
+
static int __if_usb_prog_firmware(struct if_usb_card *cardp,
const char *fwname, int cmd)
{
@@ -933,10 +980,9 @@ static int __if_usb_prog_firmware(struct if_usb_card *cardp,
lbs_deb_enter(LBS_DEB_USB);
- ret = request_firmware(&cardp->fw, fwname, &cardp->udev->dev);
- if (ret < 0) {
- lbs_pr_err("request_firmware() failed with %#x\n", ret);
- lbs_pr_err("firmware %s not found\n", fwname);
+ ret = get_fw(cardp, fwname);
+ if (ret) {
+ lbs_pr_err("failed to find firmware (%d)\n", ret);
goto done;
}
diff --git a/drivers/net/wireless/libertas/if_usb.h b/drivers/net/wireless/libertas/if_usb.h
index 5ba0aee0eb2f..d819e7e3c9aa 100644
--- a/drivers/net/wireless/libertas/if_usb.h
+++ b/drivers/net/wireless/libertas/if_usb.h
@@ -43,6 +43,7 @@ struct bootcmdresp
/** USB card description structure*/
struct if_usb_card {
struct usb_device *udev;
+ uint32_t model; /* MODEL_* */
struct urb *rx_urb, *tx_urb;
struct lbs_private *priv;
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index 24958a86747b..47ce5a6ba120 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -1047,6 +1047,111 @@ void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx)
}
EXPORT_SYMBOL_GPL(lbs_notify_command_response);
+/**
+ * @brief Retrieves two-stage firmware
+ *
+ * @param dev A pointer to device structure
+ * @param user_helper User-defined helper firmware file
+ * @param user_mainfw User-defined main firmware file
+ * @param card_model Bus-specific card model ID used to filter firmware table
+ * elements
+ * @param fw_table Table of firmware file names and device model numbers
+ * terminated by an entry with a NULL helper name
+ * @param helper On success, the helper firmware; caller must free
+ * @param mainfw On success, the main firmware; caller must free
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int lbs_get_firmware(struct device *dev, const char *user_helper,
+ const char *user_mainfw, u32 card_model,
+ const struct lbs_fw_table *fw_table,
+ const struct firmware **helper,
+ const struct firmware **mainfw)
+{
+ const struct lbs_fw_table *iter;
+ int ret;
+
+ BUG_ON(helper == NULL);
+ BUG_ON(mainfw == NULL);
+
+ /* Try user-specified firmware first */
+ if (user_helper) {
+ ret = request_firmware(helper, user_helper, dev);
+ if (ret) {
+ lbs_pr_err("couldn't find helper firmware %s",
+ user_helper);
+ goto fail;
+ }
+ }
+ if (user_mainfw) {
+ ret = request_firmware(mainfw, user_mainfw, dev);
+ if (ret) {
+ lbs_pr_err("couldn't find main firmware %s",
+ user_mainfw);
+ goto fail;
+ }
+ }
+
+ if (*helper && *mainfw)
+ return 0;
+
+ /* Otherwise search for firmware to use. If neither the helper or
+ * the main firmware were specified by the user, then we need to
+ * make sure that found helper & main are from the same entry in
+ * fw_table.
+ */
+ iter = fw_table;
+ while (iter && iter->helper) {
+ if (iter->model != card_model)
+ goto next;
+
+ if (*helper == NULL) {
+ ret = request_firmware(helper, iter->helper, dev);
+ if (ret)
+ goto next;
+
+ /* If the device has one-stage firmware (ie cf8305) and
+ * we've got it then we don't need to bother with the
+ * main firmware.
+ */
+ if (iter->fwname == NULL)
+ return 0;
+ }
+
+ if (*mainfw == NULL) {
+ ret = request_firmware(mainfw, iter->fwname, dev);
+ if (ret && !user_helper) {
+ /* Clear the helper if it wasn't user-specified
+ * and the main firmware load failed, to ensure
+ * we don't have mismatched firmware pairs.
+ */
+ release_firmware(*helper);
+ *helper = NULL;
+ }
+ }
+
+ if (*helper && *mainfw)
+ return 0;
+
+ next:
+ iter++;
+ }
+
+ fail:
+ /* Failed */
+ if (*helper) {
+ release_firmware(*helper);
+ *helper = NULL;
+ }
+ if (*mainfw) {
+ release_firmware(*mainfw);
+ *mainfw = NULL;
+ }
+
+ return -ENOENT;
+}
+EXPORT_SYMBOL_GPL(lbs_get_firmware);
+
static int __init lbs_init_module(void)
{
lbs_deb_enter(LBS_DEB_MAIN);
diff --git a/drivers/net/wireless/libertas/mesh.c b/drivers/net/wireless/libertas/mesh.c
index 194762ab0142..acf3bf63ee33 100644
--- a/drivers/net/wireless/libertas/mesh.c
+++ b/drivers/net/wireless/libertas/mesh.c
@@ -574,7 +574,7 @@ int lbs_mesh_bt_set_inverted(struct lbs_private *priv, bool inverted)
memset(&cmd, 0, sizeof(cmd));
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_SET_INVERT);
- cmd.id = !!inverted;
+ cmd.id = cpu_to_le32(!!inverted);
ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd);
diff --git a/drivers/net/wireless/libertas_tf/if_usb.c b/drivers/net/wireless/libertas_tf/if_usb.c
index 41a4f214ade1..ba7d96584cb6 100644
--- a/drivers/net/wireless/libertas_tf/if_usb.c
+++ b/drivers/net/wireless/libertas_tf/if_usb.c
@@ -54,7 +54,7 @@ static int if_usb_reset_device(struct if_usb_card *cardp);
/**
* if_usb_wrike_bulk_callback - call back to handle URB status
*
- * @param urb pointer to urb structure
+ * @param urb pointer to urb structure
*/
static void if_usb_write_bulk_callback(struct urb *urb)
{
@@ -178,16 +178,19 @@ static int if_usb_probe(struct usb_interface *intf,
le16_to_cpu(endpoint->wMaxPacketSize);
cardp->ep_in = usb_endpoint_num(endpoint);
- lbtf_deb_usbd(&udev->dev, "in_endpoint = %d\n", cardp->ep_in);
- lbtf_deb_usbd(&udev->dev, "Bulk in size is %d\n", cardp->ep_in_size);
+ lbtf_deb_usbd(&udev->dev, "in_endpoint = %d\n",
+ cardp->ep_in);
+ lbtf_deb_usbd(&udev->dev, "Bulk in size is %d\n",
+ cardp->ep_in_size);
} else if (usb_endpoint_is_bulk_out(endpoint)) {
cardp->ep_out_size =
le16_to_cpu(endpoint->wMaxPacketSize);
cardp->ep_out = usb_endpoint_num(endpoint);
- lbtf_deb_usbd(&udev->dev, "out_endpoint = %d\n", cardp->ep_out);
+ lbtf_deb_usbd(&udev->dev, "out_endpoint = %d\n",
+ cardp->ep_out);
lbtf_deb_usbd(&udev->dev, "Bulk out size is %d\n",
- cardp->ep_out_size);
+ cardp->ep_out_size);
}
}
if (!cardp->ep_out_size || !cardp->ep_in_size) {
@@ -318,10 +321,12 @@ static int if_usb_send_fw_pkt(struct if_usb_card *cardp)
if (fwdata->hdr.dnldcmd == cpu_to_le32(FW_HAS_DATA_TO_RECV)) {
lbtf_deb_usb2(&cardp->udev->dev, "There are data to follow\n");
- lbtf_deb_usb2(&cardp->udev->dev, "seqnum = %d totalbytes = %d\n",
- cardp->fwseqnum, cardp->totalbytes);
+ lbtf_deb_usb2(&cardp->udev->dev,
+ "seqnum = %d totalbytes = %d\n",
+ cardp->fwseqnum, cardp->totalbytes);
} else if (fwdata->hdr.dnldcmd == cpu_to_le32(FW_HAS_LAST_BLOCK)) {
- lbtf_deb_usb2(&cardp->udev->dev, "Host has finished FW downloading\n");
+ lbtf_deb_usb2(&cardp->udev->dev,
+ "Host has finished FW downloading\n");
lbtf_deb_usb2(&cardp->udev->dev, "Donwloading FW JUMP BLOCK\n");
/* Host has finished FW downloading
@@ -367,7 +372,7 @@ EXPORT_SYMBOL_GPL(if_usb_reset_device);
/**
* usb_tx_block - transfer data to the device
*
- * @priv pointer to struct lbtf_private
+ * @priv pointer to struct lbtf_private
* @payload pointer to payload data
* @nb data length
* @data non-zero for data, zero for commands
@@ -400,7 +405,8 @@ static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload,
urb->transfer_flags |= URB_ZERO_PACKET;
if (usb_submit_urb(urb, GFP_ATOMIC)) {
- lbtf_deb_usbd(&cardp->udev->dev, "usb_submit_urb failed: %d\n", ret);
+ lbtf_deb_usbd(&cardp->udev->dev,
+ "usb_submit_urb failed: %d\n", ret);
goto tx_ret;
}
@@ -438,10 +444,12 @@ static int __if_usb_submit_rx_urb(struct if_usb_card *cardp,
cardp->rx_urb->transfer_flags |= URB_ZERO_PACKET;
- lbtf_deb_usb2(&cardp->udev->dev, "Pointer for rx_urb %p\n", cardp->rx_urb);
+ lbtf_deb_usb2(&cardp->udev->dev, "Pointer for rx_urb %p\n",
+ cardp->rx_urb);
ret = usb_submit_urb(cardp->rx_urb, GFP_ATOMIC);
if (ret) {
- lbtf_deb_usbd(&cardp->udev->dev, "Submit Rx URB failed: %d\n", ret);
+ lbtf_deb_usbd(&cardp->udev->dev,
+ "Submit Rx URB failed: %d\n", ret);
kfree_skb(skb);
cardp->rx_skb = NULL;
lbtf_deb_leave(LBTF_DEB_USB);
@@ -522,14 +530,14 @@ static void if_usb_receive_fwload(struct urb *urb)
}
} else if (bcmdresp.cmd != BOOT_CMD_FW_BY_USB) {
pr_info("boot cmd response cmd_tag error (%d)\n",
- bcmdresp.cmd);
+ bcmdresp.cmd);
} else if (bcmdresp.result != BOOT_CMD_RESP_OK) {
pr_info("boot cmd response result error (%d)\n",
- bcmdresp.result);
+ bcmdresp.result);
} else {
cardp->bootcmdresp = 1;
lbtf_deb_usbd(&cardp->udev->dev,
- "Received valid boot command response\n");
+ "Received valid boot command response\n");
}
kfree_skb(skb);
@@ -541,19 +549,23 @@ static void if_usb_receive_fwload(struct urb *urb)
syncfwheader = kmemdup(skb->data, sizeof(struct fwsyncheader),
GFP_ATOMIC);
if (!syncfwheader) {
- lbtf_deb_usbd(&cardp->udev->dev, "Failure to allocate syncfwheader\n");
+ lbtf_deb_usbd(&cardp->udev->dev,
+ "Failure to allocate syncfwheader\n");
kfree_skb(skb);
lbtf_deb_leave(LBTF_DEB_USB);
return;
}
if (!syncfwheader->cmd) {
- lbtf_deb_usb2(&cardp->udev->dev, "FW received Blk with correct CRC\n");
- lbtf_deb_usb2(&cardp->udev->dev, "FW received Blk seqnum = %d\n",
- le32_to_cpu(syncfwheader->seqnum));
+ lbtf_deb_usb2(&cardp->udev->dev,
+ "FW received Blk with correct CRC\n");
+ lbtf_deb_usb2(&cardp->udev->dev,
+ "FW received Blk seqnum = %d\n",
+ le32_to_cpu(syncfwheader->seqnum));
cardp->CRC_OK = 1;
} else {
- lbtf_deb_usbd(&cardp->udev->dev, "FW received Blk with CRC error\n");
+ lbtf_deb_usbd(&cardp->udev->dev,
+ "FW received Blk with CRC error\n");
cardp->CRC_OK = 0;
}
@@ -666,7 +678,8 @@ static void if_usb_receive(struct urb *urb)
{
/* Event cause handling */
u32 event_cause = le32_to_cpu(pkt[1]);
- lbtf_deb_usbd(&cardp->udev->dev, "**EVENT** 0x%X\n", event_cause);
+ lbtf_deb_usbd(&cardp->udev->dev, "**EVENT** 0x%X\n",
+ event_cause);
/* Icky undocumented magic special case */
if (event_cause & 0xffff0000) {
@@ -689,7 +702,7 @@ static void if_usb_receive(struct urb *urb)
}
default:
lbtf_deb_usbd(&cardp->udev->dev,
- "libertastf: unknown command type 0x%X\n", recvtype);
+ "libertastf: unknown command type 0x%X\n", recvtype);
kfree_skb(skb);
break;
}
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 86fa8abdd66f..7eaaa3bab547 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -9,7 +9,8 @@
/*
* TODO:
- * - IBSS mode simulation (Beacon transmission with competition for "air time")
+ * - Add TSF sync and fix IBSS beacon transmission by adding
+ * competition for "air time" at TBTT
* - RX filtering based on filter configuration (data->rx_filter)
*/
@@ -594,17 +595,34 @@ static int mac80211_hwsim_add_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
wiphy_debug(hw->wiphy, "%s (type=%d mac_addr=%pM)\n",
- __func__, vif->type, vif->addr);
+ __func__, ieee80211_vif_type_p2p(vif),
+ vif->addr);
hwsim_set_magic(vif);
return 0;
}
+static int mac80211_hwsim_change_interface(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ enum nl80211_iftype newtype,
+ bool newp2p)
+{
+ newtype = ieee80211_iftype_p2p(newtype, newp2p);
+ wiphy_debug(hw->wiphy,
+ "%s (old type=%d, new type=%d, mac_addr=%pM)\n",
+ __func__, ieee80211_vif_type_p2p(vif),
+ newtype, vif->addr);
+ hwsim_check_magic(vif);
+
+ return 0;
+}
+
static void mac80211_hwsim_remove_interface(
struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
wiphy_debug(hw->wiphy, "%s (type=%d mac_addr=%pM)\n",
- __func__, vif->type, vif->addr);
+ __func__, ieee80211_vif_type_p2p(vif),
+ vif->addr);
hwsim_check_magic(vif);
hwsim_clear_magic(vif);
}
@@ -620,7 +638,8 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
hwsim_check_magic(vif);
if (vif->type != NL80211_IFTYPE_AP &&
- vif->type != NL80211_IFTYPE_MESH_POINT)
+ vif->type != NL80211_IFTYPE_MESH_POINT &&
+ vif->type != NL80211_IFTYPE_ADHOC)
return;
skb = ieee80211_beacon_get(hw, vif);
@@ -1025,6 +1044,7 @@ static struct ieee80211_ops mac80211_hwsim_ops =
.start = mac80211_hwsim_start,
.stop = mac80211_hwsim_stop,
.add_interface = mac80211_hwsim_add_interface,
+ .change_interface = mac80211_hwsim_change_interface,
.remove_interface = mac80211_hwsim_remove_interface,
.config = mac80211_hwsim_config,
.configure_filter = mac80211_hwsim_configure_filter,
@@ -1295,6 +1315,9 @@ static int __init init_mac80211_hwsim(void)
hw->wiphy->interface_modes =
BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_AP) |
+ BIT(NL80211_IFTYPE_P2P_CLIENT) |
+ BIT(NL80211_IFTYPE_P2P_GO) |
+ BIT(NL80211_IFTYPE_ADHOC) |
BIT(NL80211_IFTYPE_MESH_POINT);
hw->flags = IEEE80211_HW_MFP_CAPABLE |
diff --git a/drivers/net/wireless/orinoco/hw.c b/drivers/net/wireless/orinoco/hw.c
index 077baa86756b..b4772c1c6135 100644
--- a/drivers/net/wireless/orinoco/hw.c
+++ b/drivers/net/wireless/orinoco/hw.c
@@ -762,14 +762,17 @@ int orinoco_hw_get_act_bitrate(struct orinoco_private *priv, int *bitrate)
case FIRMWARE_TYPE_INTERSIL: /* Intersil style rate */
case FIRMWARE_TYPE_SYMBOL: /* Symbol style rate */
for (i = 0; i < BITRATE_TABLE_SIZE; i++)
- if (bitrate_table[i].intersil_txratectrl == val)
+ if (bitrate_table[i].intersil_txratectrl == val) {
+ *bitrate = bitrate_table[i].bitrate * 100000;
break;
+ }
- if (i >= BITRATE_TABLE_SIZE)
+ if (i >= BITRATE_TABLE_SIZE) {
printk(KERN_INFO "%s: Unable to determine current bitrate (0x%04hx)\n",
priv->ndev->name, val);
+ err = -EIO;
+ }
- *bitrate = bitrate_table[i].bitrate * 100000;
break;
default:
BUG();
diff --git a/drivers/net/wireless/orinoco/orinoco_cs.c b/drivers/net/wireless/orinoco/orinoco_cs.c
index ef46a2d88539..71b3d68b9403 100644
--- a/drivers/net/wireless/orinoco/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco/orinoco_cs.c
@@ -17,7 +17,6 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/ds.h>
@@ -93,14 +92,6 @@ orinoco_cs_hard_reset(struct orinoco_private *priv)
/* PCMCIA stuff */
/********************************************************************/
-/*
- * This creates an "instance" of the driver, allocating local data
- * structures for one device. The device is registered with Card
- * Services.
- *
- * The dev_link structure is initialized, but we don't actually
- * configure the card at this point -- we wait until we receive a card
- * insertion event. */
static int
orinoco_cs_probe(struct pcmcia_device *link)
{
@@ -117,23 +108,9 @@ orinoco_cs_probe(struct pcmcia_device *link)
card->p_dev = link;
link->priv = priv;
- /* General socket configuration defaults can go here. In this
- * client, we assume very little, and rely on the CIS for
- * almost everything. In most clients, many details (i.e.,
- * number, sizes, and attributes of IO windows) are fixed by
- * the nature of the device, and can be hard-wired here. */
- link->conf.Attributes = 0;
- link->conf.IntType = INT_MEMORY_AND_IO;
-
return orinoco_cs_config(link);
} /* orinoco_cs_attach */
-/*
- * This deletes a driver "instance". The device is de-registered with
- * Card Services. If it has been released, all local data structures
- * are freed. Otherwise, the structures will be freed when the device
- * is released.
- */
static void orinoco_cs_detach(struct pcmcia_device *link)
{
struct orinoco_private *priv = link->priv;
@@ -145,76 +122,12 @@ static void orinoco_cs_detach(struct pcmcia_device *link)
free_orinocodev(priv);
} /* orinoco_cs_detach */
-/*
- * orinoco_cs_config() is scheduled to run after a CARD_INSERTION
- * event is received, to configure the PCMCIA socket, and to make the
- * device available to the system.
- */
-
-static int orinoco_cs_config_check(struct pcmcia_device *p_dev,
- cistpl_cftable_entry_t *cfg,
- cistpl_cftable_entry_t *dflt,
- unsigned int vcc,
- void *priv_data)
+static int orinoco_cs_config_check(struct pcmcia_device *p_dev, void *priv_data)
{
- if (cfg->index == 0)
- goto next_entry;
-
- /* Use power settings for Vcc and Vpp if present */
- /* Note that the CIS values need to be rescaled */
- if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
- if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) {
- DEBUG(2, "%s: Vcc mismatch (vcc = %d, CIS = %d)\n",
- __func__, vcc,
- cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
- if (!ignore_cis_vcc)
- goto next_entry;
- }
- } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
- if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000) {
- DEBUG(2, "%s: Vcc mismatch (vcc = %d, CIS = %d)\n",
- __func__, vcc,
- dflt->vcc.param[CISTPL_POWER_VNOM] / 10000);
- if (!ignore_cis_vcc)
- goto next_entry;
- }
- }
+ if (p_dev->config_index == 0)
+ return -EINVAL;
- if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
- p_dev->conf.Vpp =
- cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
- else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
- p_dev->conf.Vpp =
- dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-
- /* Do we need to allocate an interrupt? */
- p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
-
- /* IO window settings */
- p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
- if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
- cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
- p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
- p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
- p_dev->resource[0]->flags |=
- pcmcia_io_cfg_data_width(io->flags);
- p_dev->resource[0]->start = io->win[0].base;
- p_dev->resource[0]->end = io->win[0].len;
- if (io->nwin > 1) {
- p_dev->resource[1]->flags = p_dev->resource[0]->flags;
- p_dev->resource[1]->start = io->win[1].base;
- p_dev->resource[1]->end = io->win[1].len;
- }
-
- /* This reserves IO space but doesn't actually enable it */
- if (pcmcia_request_io(p_dev) != 0)
- goto next_entry;
- }
- return 0;
-
-next_entry:
- pcmcia_disable_device(p_dev);
- return -ENODEV;
+ return pcmcia_request_io(p_dev);
};
static int
@@ -225,20 +138,10 @@ orinoco_cs_config(struct pcmcia_device *link)
int ret;
void __iomem *mem;
- /*
- * In this loop, we scan the CIS for configuration table
- * entries, each of which describes a valid card
- * configuration, including voltage, IO window, memory window,
- * and interrupt settings.
- *
- * We make no assumptions about the card to be configured: we
- * use just the information available in the CIS. In an ideal
- * world, this would work for any PCMCIA card, but it requires
- * a complete and accurate CIS. In practice, a driver usually
- * "knows" most of these things without consulting the CIS,
- * and most client drivers will only use the CIS to fill in
- * implementation-defined details.
- */
+ link->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC |
+ CONF_AUTO_SET_IO | CONF_ENABLE_IRQ;
+ if (ignore_cis_vcc)
+ link->config_flags &= ~CONF_AUTO_CHECK_VCC;
ret = pcmcia_loop_config(link, orinoco_cs_config_check, NULL);
if (ret) {
if (!ignore_cis_vcc)
@@ -262,12 +165,7 @@ orinoco_cs_config(struct pcmcia_device *link)
hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING);
- /*
- * This actually configures the PCMCIA socket -- setting up
- * the I/O windows and the interrupt mapping, and putting the
- * card and host interface into "Memory and IO" mode.
- */
- ret = pcmcia_request_configuration(link, &link->conf);
+ ret = pcmcia_enable_device(link);
if (ret)
goto failed;
@@ -291,11 +189,6 @@ orinoco_cs_config(struct pcmcia_device *link)
return -ENODEV;
} /* orinoco_cs_config */
-/*
- * After a card is removed, orinoco_cs_release() will unregister the
- * device, and release the PCMCIA configuration. If the device is
- * still open, this will be postponed until it is closed.
- */
static void
orinoco_cs_release(struct pcmcia_device *link)
{
@@ -344,12 +237,6 @@ static int orinoco_cs_resume(struct pcmcia_device *link)
/* Module initialization */
/********************************************************************/
-/* Can't be declared "const" or the whole __initdata section will
- * become const */
-static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
- " (David Gibson <hermes@gibson.dropbear.id.au>, "
- "Pavel Roskin <proski@gnu.org>, et al)";
-
static struct pcmcia_device_id orinoco_cs_ids[] = {
PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0777), /* 3Com AirConnect PCI 777A */
PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002), /* Lucent Orinoco and old Intersil */
@@ -441,9 +328,7 @@ MODULE_DEVICE_TABLE(pcmcia, orinoco_cs_ids);
static struct pcmcia_driver orinoco_driver = {
.owner = THIS_MODULE,
- .drv = {
- .name = DRIVER_NAME,
- },
+ .name = DRIVER_NAME,
.probe = orinoco_cs_probe,
.remove = orinoco_cs_detach,
.id_table = orinoco_cs_ids,
@@ -454,8 +339,6 @@ static struct pcmcia_driver orinoco_driver = {
static int __init
init_orinoco_cs(void)
{
- printk(KERN_DEBUG "%s\n", version);
-
return pcmcia_register_driver(&orinoco_driver);
}
diff --git a/drivers/net/wireless/orinoco/spectrum_cs.c b/drivers/net/wireless/orinoco/spectrum_cs.c
index 873877e17e1b..fb859a5ad2eb 100644
--- a/drivers/net/wireless/orinoco/spectrum_cs.c
+++ b/drivers/net/wireless/orinoco/spectrum_cs.c
@@ -25,7 +25,6 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/ds.h>
@@ -154,14 +153,6 @@ spectrum_cs_stop_firmware(struct orinoco_private *priv, int idle)
/* PCMCIA stuff */
/********************************************************************/
-/*
- * This creates an "instance" of the driver, allocating local data
- * structures for one device. The device is registered with Card
- * Services.
- *
- * The dev_link structure is initialized, but we don't actually
- * configure the card at this point -- we wait until we receive a card
- * insertion event. */
static int
spectrum_cs_probe(struct pcmcia_device *link)
{
@@ -179,23 +170,9 @@ spectrum_cs_probe(struct pcmcia_device *link)
card->p_dev = link;
link->priv = priv;
- /* General socket configuration defaults can go here. In this
- * client, we assume very little, and rely on the CIS for
- * almost everything. In most clients, many details (i.e.,
- * number, sizes, and attributes of IO windows) are fixed by
- * the nature of the device, and can be hard-wired here. */
- link->conf.Attributes = 0;
- link->conf.IntType = INT_MEMORY_AND_IO;
-
return spectrum_cs_config(link);
} /* spectrum_cs_attach */
-/*
- * This deletes a driver "instance". The device is de-registered with
- * Card Services. If it has been released, all local data structures
- * are freed. Otherwise, the structures will be freed when the device
- * is released.
- */
static void spectrum_cs_detach(struct pcmcia_device *link)
{
struct orinoco_private *priv = link->priv;
@@ -207,76 +184,13 @@ static void spectrum_cs_detach(struct pcmcia_device *link)
free_orinocodev(priv);
} /* spectrum_cs_detach */
-/*
- * spectrum_cs_config() is scheduled to run after a CARD_INSERTION
- * event is received, to configure the PCMCIA socket, and to make the
- * device available to the system.
- */
-
static int spectrum_cs_config_check(struct pcmcia_device *p_dev,
- cistpl_cftable_entry_t *cfg,
- cistpl_cftable_entry_t *dflt,
- unsigned int vcc,
void *priv_data)
{
- if (cfg->index == 0)
- goto next_entry;
-
- /* Use power settings for Vcc and Vpp if present */
- /* Note that the CIS values need to be rescaled */
- if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
- if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) {
- DEBUG(2, "%s: Vcc mismatch (vcc = %d, CIS = %d)\n",
- __func__, vcc,
- cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
- if (!ignore_cis_vcc)
- goto next_entry;
- }
- } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
- if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000) {
- DEBUG(2, "%s: Vcc mismatch (vcc = %d, CIS = %d)\n",
- __func__, vcc,
- dflt->vcc.param[CISTPL_POWER_VNOM] / 10000);
- if (!ignore_cis_vcc)
- goto next_entry;
- }
- }
+ if (p_dev->config_index == 0)
+ return -EINVAL;
- if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
- p_dev->conf.Vpp =
- cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
- else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
- p_dev->conf.Vpp =
- dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-
- /* Do we need to allocate an interrupt? */
- p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
-
- /* IO window settings */
- p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
- if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
- cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
- p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
- p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
- p_dev->resource[0]->flags |=
- pcmcia_io_cfg_data_width(io->flags);
- p_dev->resource[0]->start = io->win[0].base;
- p_dev->resource[0]->end = io->win[0].len;
- if (io->nwin > 1) {
- p_dev->resource[1]->flags = p_dev->resource[0]->flags;
- p_dev->resource[1]->start = io->win[1].base;
- p_dev->resource[1]->end = io->win[1].len;
- }
-
- /* This reserves IO space but doesn't actually enable it */
- if (pcmcia_request_io(p_dev) != 0)
- goto next_entry;
- }
- return 0;
-
-next_entry:
- pcmcia_disable_device(p_dev);
- return -ENODEV;
+ return pcmcia_request_io(p_dev);
};
static int
@@ -287,20 +201,10 @@ spectrum_cs_config(struct pcmcia_device *link)
int ret;
void __iomem *mem;
- /*
- * In this loop, we scan the CIS for configuration table
- * entries, each of which describes a valid card
- * configuration, including voltage, IO window, memory window,
- * and interrupt settings.
- *
- * We make no assumptions about the card to be configured: we
- * use just the information available in the CIS. In an ideal
- * world, this would work for any PCMCIA card, but it requires
- * a complete and accurate CIS. In practice, a driver usually
- * "knows" most of these things without consulting the CIS,
- * and most client drivers will only use the CIS to fill in
- * implementation-defined details.
- */
+ link->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC |
+ CONF_AUTO_SET_IO | CONF_ENABLE_IRQ;
+ if (ignore_cis_vcc)
+ link->config_flags &= ~CONF_AUTO_CHECK_VCC;
ret = pcmcia_loop_config(link, spectrum_cs_config_check, NULL);
if (ret) {
if (!ignore_cis_vcc)
@@ -325,12 +229,7 @@ spectrum_cs_config(struct pcmcia_device *link)
hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING);
hw->eeprom_pda = true;
- /*
- * This actually configures the PCMCIA socket -- setting up
- * the I/O windows and the interrupt mapping, and putting the
- * card and host interface into "Memory and IO" mode.
- */
- ret = pcmcia_request_configuration(link, &link->conf);
+ ret = pcmcia_enable_device(link);
if (ret)
goto failed;
@@ -358,11 +257,6 @@ spectrum_cs_config(struct pcmcia_device *link)
return -ENODEV;
} /* spectrum_cs_config */
-/*
- * After a card is removed, spectrum_cs_release() will unregister the
- * device, and release the PCMCIA configuration. If the device is
- * still open, this will be postponed until it is closed.
- */
static void
spectrum_cs_release(struct pcmcia_device *link)
{
@@ -407,12 +301,6 @@ spectrum_cs_resume(struct pcmcia_device *link)
/* Module initialization */
/********************************************************************/
-/* Can't be declared "const" or the whole __initdata section will
- * become const */
-static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
- " (Pavel Roskin <proski@gnu.org>,"
- " David Gibson <hermes@gibson.dropbear.id.au>, et al)";
-
static struct pcmcia_device_id spectrum_cs_ids[] = {
PCMCIA_DEVICE_MANF_CARD(0x026c, 0x0001), /* Symbol Spectrum24 LA4137 */
PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0001), /* Socket Communications CF */
@@ -423,9 +311,7 @@ MODULE_DEVICE_TABLE(pcmcia, spectrum_cs_ids);
static struct pcmcia_driver orinoco_driver = {
.owner = THIS_MODULE,
- .drv = {
- .name = DRIVER_NAME,
- },
+ .name = DRIVER_NAME,
.probe = spectrum_cs_probe,
.remove = spectrum_cs_detach,
.suspend = spectrum_cs_suspend,
@@ -436,8 +322,6 @@ static struct pcmcia_driver orinoco_driver = {
static int __init
init_spectrum_cs(void)
{
- printk(KERN_DEBUG "%s\n", version);
-
return pcmcia_register_driver(&orinoco_driver);
}
diff --git a/drivers/net/wireless/orinoco/wext.c b/drivers/net/wireless/orinoco/wext.c
index cf7be1eb6124..93505f93bf97 100644
--- a/drivers/net/wireless/orinoco/wext.c
+++ b/drivers/net/wireless/orinoco/wext.c
@@ -589,8 +589,15 @@ static int orinoco_ioctl_getrate(struct net_device *dev,
/* If the interface is running we try to find more about the
current mode */
- if (netif_running(dev))
- err = orinoco_hw_get_act_bitrate(priv, &bitrate);
+ if (netif_running(dev)) {
+ int act_bitrate;
+ int lerr;
+
+ /* Ignore errors if we can't get the actual bitrate */
+ lerr = orinoco_hw_get_act_bitrate(priv, &act_bitrate);
+ if (!lerr)
+ bitrate = act_bitrate;
+ }
orinoco_unlock(priv, &flags);
diff --git a/drivers/net/wireless/p54/Kconfig b/drivers/net/wireless/p54/Kconfig
index b0342a520bf1..e5f45cb2a7a2 100644
--- a/drivers/net/wireless/p54/Kconfig
+++ b/drivers/net/wireless/p54/Kconfig
@@ -2,6 +2,7 @@ config P54_COMMON
tristate "Softmac Prism54 support"
depends on MAC80211 && EXPERIMENTAL
select FW_LOADER
+ select CRC_CCITT
---help---
This is common code for isl38xx/stlc45xx based modules.
This module does nothing by itself - the USB/PCI/SPI front-ends
@@ -48,6 +49,23 @@ config P54_SPI
If you choose to build a module, it'll be called p54spi.
+config P54_SPI_DEFAULT_EEPROM
+ bool "Include fallback EEPROM blob"
+ depends on P54_SPI
+ default n
+ ---help---
+ Unlike the PCI or USB devices, the SPI variants don't have
+ a dedicated EEPROM chip to store all device specific values
+ for calibration, country and interface settings.
+
+ The driver will try to load the image "3826.eeprom", if the
+ file is put at the right place. (usually /lib/firmware.)
+
+ Only if this request fails, this option will provide a
+ backup set of generic values to get the device working.
+
+ Enabling this option adds about 4k to p54spi.
+
config P54_LEDS
bool
depends on P54_COMMON && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = P54_COMMON)
diff --git a/drivers/net/wireless/p54/eeprom.c b/drivers/net/wireless/p54/eeprom.c
index 78347041ec40..35b09aa0529b 100644
--- a/drivers/net/wireless/p54/eeprom.c
+++ b/drivers/net/wireless/p54/eeprom.c
@@ -23,6 +23,7 @@
#include <linux/slab.h>
#include <net/mac80211.h>
+#include <linux/crc-ccitt.h>
#include "p54.h"
#include "eeprom.h"
@@ -260,8 +261,10 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev)
list->max_entries = max_channel_num;
list->channels = kzalloc(sizeof(struct p54_channel_entry) *
max_channel_num, GFP_KERNEL);
- if (!list->channels)
+ if (!list->channels) {
+ ret = -ENOMEM;
goto free;
+ }
for (i = 0; i < max_channel_num; i++) {
if (i < priv->iq_autocal_len) {
@@ -540,6 +543,7 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
int err;
u8 *end = (u8 *)eeprom + len;
u16 synth = 0;
+ u16 crc16 = ~0;
wrap = (struct eeprom_pda_wrap *) eeprom;
entry = (void *)wrap->data + le16_to_cpu(wrap->len);
@@ -655,16 +659,29 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
}
break;
case PDR_END:
- /* make it overrun */
- entry_len = len;
+ crc16 = ~crc_ccitt(crc16, (u8 *) entry, sizeof(*entry));
+ if (crc16 != le16_to_cpup((__le16 *)entry->data)) {
+ wiphy_err(dev->wiphy, "eeprom failed checksum "
+ "test!\n");
+ err = -ENOMSG;
+ goto err;
+ } else {
+ goto good_eeprom;
+ }
break;
default:
break;
}
- entry = (void *)entry + (entry_len + 1)*2;
+ crc16 = crc_ccitt(crc16, (u8 *)entry, (entry_len + 1) * 2);
+ entry = (void *)entry + (entry_len + 1) * 2;
}
+ wiphy_err(dev->wiphy, "unexpected end of eeprom data.\n");
+ err = -ENODATA;
+ goto err;
+
+good_eeprom:
if (!synth || !priv->iq_autocal || !priv->output_limit ||
!priv->curve_data) {
wiphy_err(dev->wiphy,
diff --git a/drivers/net/wireless/p54/fwio.c b/drivers/net/wireless/p54/fwio.c
index 15b20c29a604..92b9b1f05fd5 100644
--- a/drivers/net/wireless/p54/fwio.c
+++ b/drivers/net/wireless/p54/fwio.c
@@ -123,10 +123,14 @@ int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw)
bootrec = (struct bootrec *)&bootrec->data[len];
}
- if (fw_version)
+ if (fw_version) {
wiphy_info(priv->hw->wiphy,
"FW rev %s - Softmac protocol %x.%x\n",
fw_version, priv->fw_var >> 8, priv->fw_var & 0xff);
+ snprintf(dev->wiphy->fw_version, sizeof(dev->wiphy->fw_version),
+ "%s - %x.%x", fw_version,
+ priv->fw_var >> 8, priv->fw_var & 0xff);
+ }
if (priv->fw_var < 0x500)
wiphy_info(priv->hw->wiphy,
diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c
index 47db439b63bf..622d27b6d8f2 100644
--- a/drivers/net/wireless/p54/main.c
+++ b/drivers/net/wireless/p54/main.c
@@ -429,8 +429,8 @@ static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd,
mutex_lock(&priv->conf_mutex);
if (cmd == SET_KEY) {
- switch (key->alg) {
- case ALG_TKIP:
+ switch (key->cipher) {
+ case WLAN_CIPHER_SUITE_TKIP:
if (!(priv->privacy_caps & (BR_DESC_PRIV_CAP_MICHAEL |
BR_DESC_PRIV_CAP_TKIP))) {
ret = -EOPNOTSUPP;
@@ -439,7 +439,8 @@ static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd,
key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
algo = P54_CRYPTO_TKIPMICHAEL;
break;
- case ALG_WEP:
+ case WLAN_CIPHER_SUITE_WEP40:
+ case WLAN_CIPHER_SUITE_WEP104:
if (!(priv->privacy_caps & BR_DESC_PRIV_CAP_WEP)) {
ret = -EOPNOTSUPP;
goto out_unlock;
@@ -447,7 +448,7 @@ static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd,
key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
algo = P54_CRYPTO_WEP;
break;
- case ALG_CCMP:
+ case WLAN_CIPHER_SUITE_CCMP:
if (!(priv->privacy_caps & BR_DESC_PRIV_CAP_AESCCMP)) {
ret = -EOPNOTSUPP;
goto out_unlock;
diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c
index 087bf0698a5a..18d24b7b1e34 100644
--- a/drivers/net/wireless/p54/p54spi.c
+++ b/drivers/net/wireless/p54/p54spi.c
@@ -32,11 +32,14 @@
#include <linux/slab.h>
#include "p54spi.h"
-#include "p54spi_eeprom.h"
#include "p54.h"
#include "lmac.h"
+#ifdef CONFIG_P54_SPI_DEFAULT_EEPROM
+#include "p54spi_eeprom.h"
+#endif /* CONFIG_P54_SPI_DEFAULT_EEPROM */
+
MODULE_FIRMWARE("3826.arm");
MODULE_ALIAS("stlc45xx");
@@ -195,9 +198,13 @@ static int p54spi_request_eeprom(struct ieee80211_hw *dev)
ret = request_firmware(&eeprom, "3826.eeprom", &priv->spi->dev);
if (ret < 0) {
+#ifdef CONFIG_P54_SPI_DEFAULT_EEPROM
dev_info(&priv->spi->dev, "loading default eeprom...\n");
ret = p54_parse_eeprom(dev, (void *) p54spi_eeprom,
sizeof(p54spi_eeprom));
+#else
+ dev_err(&priv->spi->dev, "Failed to request user eeprom\n");
+#endif /* CONFIG_P54_SPI_DEFAULT_EEPROM */
} else {
dev_info(&priv->spi->dev, "loading user eeprom...\n");
ret = p54_parse_eeprom(dev, (void *) eeprom->data,
diff --git a/drivers/net/wireless/p54/p54spi_eeprom.h b/drivers/net/wireless/p54/p54spi_eeprom.h
index 1ea1050911d9..d592cbd34d78 100644
--- a/drivers/net/wireless/p54/p54spi_eeprom.h
+++ b/drivers/net/wireless/p54/p54spi_eeprom.h
@@ -671,7 +671,7 @@ static unsigned char p54spi_eeprom[] = {
0xa8, 0x09, 0x25, 0x00, 0xf5, 0xff, 0xf9, 0xff, 0x00, 0x01,
0x02, 0x00, 0x00, 0x00, /* PDR_END */
- 0xa8, 0xf5 /* bogus data */
+ 0x67, 0x99,
};
#endif /* P54SPI_EEPROM_H */
diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c
index ad595958b7df..d5bc21e5a02c 100644
--- a/drivers/net/wireless/p54/p54usb.c
+++ b/drivers/net/wireless/p54/p54usb.c
@@ -33,8 +33,17 @@ MODULE_ALIAS("prism54usb");
MODULE_FIRMWARE("isl3886usb");
MODULE_FIRMWARE("isl3887usb");
+/*
+ * Note:
+ *
+ * Always update our wiki's device list (located at:
+ * http://wireless.kernel.org/en/users/Drivers/p54/devices ),
+ * whenever you add a new device.
+ */
+
static struct usb_device_id p54u_table[] __devinitdata = {
/* Version 1 devices (pci chip + net2280) */
+ {USB_DEVICE(0x045e, 0x00c2)}, /* Microsoft MN-710 */
{USB_DEVICE(0x0506, 0x0a11)}, /* 3COM 3CRWE254G72 */
{USB_DEVICE(0x06b9, 0x0120)}, /* Thomson SpeedTouch 120g */
{USB_DEVICE(0x0707, 0xee06)}, /* SMC 2862W-G */
@@ -47,7 +56,9 @@ static struct usb_device_id p54u_table[] __devinitdata = {
{USB_DEVICE(0x0846, 0x4220)}, /* Netgear WG111 */
{USB_DEVICE(0x09aa, 0x1000)}, /* Spinnaker Proto board */
{USB_DEVICE(0x0cde, 0x0006)}, /* Medion 40900, Roper Europe */
+ {USB_DEVICE(0x107b, 0x55f2)}, /* Gateway WGU-210 (Gemtek) */
{USB_DEVICE(0x124a, 0x4023)}, /* Shuttle PN15, Airvast WM168g, IOGear GWU513 */
+ {USB_DEVICE(0x1630, 0x0005)}, /* 2Wire 802.11g USB (v1) / Z-Com */
{USB_DEVICE(0x1915, 0x2234)}, /* Linksys WUSB54G OEM */
{USB_DEVICE(0x1915, 0x2235)}, /* Linksys WUSB54G Portable OEM */
{USB_DEVICE(0x2001, 0x3701)}, /* DLink DWL-G120 Spinnaker */
@@ -60,6 +71,7 @@ static struct usb_device_id p54u_table[] __devinitdata = {
{USB_DEVICE(0x050d, 0x7050)}, /* Belkin F5D7050 ver 1000 */
{USB_DEVICE(0x0572, 0x2000)}, /* Cohiba Proto board */
{USB_DEVICE(0x0572, 0x2002)}, /* Cohiba Proto board */
+ {USB_DEVICE(0x06a9, 0x000e)}, /* Westell 802.11g USB (A90-211WG-01) */
{USB_DEVICE(0x06b9, 0x0121)}, /* Thomson SpeedTouch 121g */
{USB_DEVICE(0x0707, 0xee13)}, /* SMC 2862W-G version 2 */
{USB_DEVICE(0x083a, 0x4521)}, /* Siemens Gigaset USB Adapter 54 version 2 */
@@ -80,6 +92,7 @@ static struct usb_device_id p54u_table[] __devinitdata = {
{USB_DEVICE(0x13B1, 0x000C)}, /* Linksys WUSB54AG */
{USB_DEVICE(0x1413, 0x5400)}, /* Telsey 802.11g USB2.0 Adapter */
{USB_DEVICE(0x1435, 0x0427)}, /* Inventel UR054G */
+ {USB_DEVICE(0x1668, 0x1050)}, /* Actiontec 802UIG-1 */
{USB_DEVICE(0x2001, 0x3704)}, /* DLink DWL-G122 rev A2 */
{USB_DEVICE(0x413c, 0x5513)}, /* Dell WLA3310 USB Wireless Adapter */
{USB_DEVICE(0x413c, 0x8102)}, /* Spinnaker DUT */
@@ -930,8 +943,8 @@ static int __devinit p54u_probe(struct usb_interface *intf,
#ifdef CONFIG_PM
/* ISL3887 needs a full reset on resume */
udev->reset_resume = 1;
+#endif /* CONFIG_PM */
err = p54u_device_reset(dev);
-#endif
priv->hw_type = P54U_3887;
dev->extra_tx_headroom += sizeof(struct lm87_tx_hdr);
diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c
index 0e937dc0c9c4..76b2318a7dc7 100644
--- a/drivers/net/wireless/p54/txrx.c
+++ b/drivers/net/wireless/p54/txrx.c
@@ -275,15 +275,15 @@ static int p54_rssi_to_dbm(struct p54_common *priv, int rssi)
{
int band = priv->hw->conf.channel->band;
- if (priv->rxhw != 5)
+ if (priv->rxhw != 5) {
return ((rssi * priv->rssical_db[band].mul) / 64 +
priv->rssical_db[band].add) / 4;
- else
+ } else {
/*
* TODO: find the correct formula
*/
- return ((rssi * priv->rssical_db[band].mul) / 64 +
- priv->rssical_db[band].add) / 4;
+ return rssi / 2 - 110;
+ }
}
/*
@@ -683,14 +683,15 @@ static void p54_tx_80211_header(struct p54_common *priv, struct sk_buff *skb,
}
}
-static u8 p54_convert_algo(enum ieee80211_key_alg alg)
+static u8 p54_convert_algo(u32 cipher)
{
- switch (alg) {
- case ALG_WEP:
+ switch (cipher) {
+ case WLAN_CIPHER_SUITE_WEP40:
+ case WLAN_CIPHER_SUITE_WEP104:
return P54_CRYPTO_WEP;
- case ALG_TKIP:
+ case WLAN_CIPHER_SUITE_TKIP:
return P54_CRYPTO_TKIPMICHAEL;
- case ALG_CCMP:
+ case WLAN_CIPHER_SUITE_CCMP:
return P54_CRYPTO_AESCCMP;
default:
return 0;
@@ -731,7 +732,7 @@ int p54_tx_80211(struct ieee80211_hw *dev, struct sk_buff *skb)
if (info->control.hw_key) {
crypt_offset = ieee80211_get_hdrlen_from_skb(skb);
- if (info->control.hw_key->alg == ALG_TKIP) {
+ if (info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) {
u8 *iv = (u8 *)(skb->data + crypt_offset);
/*
* The firmware excepts that the IV has to have
@@ -827,10 +828,10 @@ int p54_tx_80211(struct ieee80211_hw *dev, struct sk_buff *skb)
hdr->tries = ridx;
txhdr->rts_rate_idx = 0;
if (info->control.hw_key) {
- txhdr->key_type = p54_convert_algo(info->control.hw_key->alg);
+ txhdr->key_type = p54_convert_algo(info->control.hw_key->cipher);
txhdr->key_len = min((u8)16, info->control.hw_key->keylen);
memcpy(txhdr->key, info->control.hw_key->key, txhdr->key_len);
- if (info->control.hw_key->alg == ALG_TKIP) {
+ if (info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) {
/* reserve space for the MIC key */
len += 8;
memcpy(skb_put(skb, 8), &(info->control.hw_key->key
diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c
index 77cd65db8500..d97a2caf582b 100644
--- a/drivers/net/wireless/prism54/isl_ioctl.c
+++ b/drivers/net/wireless/prism54/isl_ioctl.c
@@ -3234,7 +3234,7 @@ prism54_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
switch (cmd) {
case PRISM54_HOSTAPD:
if (!capable(CAP_NET_ADMIN))
- return -EPERM;
+ return -EPERM;
ret = prism54_hostapd(ndev, &wrq->u.data);
return ret;
}
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index 88560d0ae50a..97007d9e2c1f 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -43,10 +43,8 @@
#include <linux/if_arp.h>
#include <linux/ioport.h>
#include <linux/skbuff.h>
-#include <linux/ethtool.h>
#include <linux/ieee80211.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/ds.h>
@@ -80,8 +78,6 @@ static int ray_dev_config(struct net_device *dev, struct ifmap *map);
static struct net_device_stats *ray_get_stats(struct net_device *dev);
static int ray_dev_init(struct net_device *dev);
-static const struct ethtool_ops netdev_ethtool_ops;
-
static int ray_open(struct net_device *dev);
static netdev_tx_t ray_dev_start_xmit(struct sk_buff *skb,
struct net_device *dev);
@@ -169,13 +165,6 @@ static int bc;
*/
static char *phy_addr = NULL;
-
-/* A struct pcmcia_device structure has fields for most things that are needed
- to keep track of a socket, but there will usually be some device
- specific information that also needs to be kept track of. The
- 'priv' pointer in a struct pcmcia_device structure can be used to point to
- a device-specific private data structure, like this.
-*/
static unsigned int ray_mem_speed = 500;
/* WARNING: THIS DRIVER IS NOT CAPABLE OF HANDLING MULTIPLE DEVICES! */
@@ -197,7 +186,7 @@ module_param(bc, int, 0);
module_param(phy_addr, charp, 0);
module_param(ray_mem_speed, int, 0);
-static UCHAR b5_default_startup_parms[] = {
+static const UCHAR b5_default_startup_parms[] = {
0, 0, /* Adhoc station */
'L', 'I', 'N', 'U', 'X', 0, 0, 0, /* 32 char ESSID */
0, 0, 0, 0, 0, 0, 0, 0,
@@ -232,7 +221,7 @@ static UCHAR b5_default_startup_parms[] = {
2, 0, 0, 0, 0, 0, 0, 0 /* basic rate set */
};
-static UCHAR b4_default_startup_parms[] = {
+static const UCHAR b4_default_startup_parms[] = {
0, 0, /* Adhoc station */
'L', 'I', 'N', 'U', 'X', 0, 0, 0, /* 32 char ESSID */
0, 0, 0, 0, 0, 0, 0, 0,
@@ -264,9 +253,9 @@ static UCHAR b4_default_startup_parms[] = {
};
/*===========================================================================*/
-static unsigned char eth2_llc[] = { 0xaa, 0xaa, 3, 0, 0, 0 };
+static const u8 eth2_llc[] = { 0xaa, 0xaa, 3, 0, 0, 0 };
-static char hop_pattern_length[] = { 1,
+static const char hop_pattern_length[] = { 1,
USA_HOP_MOD, EUROPE_HOP_MOD,
JAPAN_HOP_MOD, KOREA_HOP_MOD,
SPAIN_HOP_MOD, FRANCE_HOP_MOD,
@@ -274,7 +263,7 @@ static char hop_pattern_length[] = { 1,
JAPAN_TEST_HOP_MOD
};
-static char rcsid[] =
+static const char rcsid[] =
"Raylink/WebGear wireless LAN - Corey <Thomas corey@world.std.com>";
static const struct net_device_ops ray_netdev_ops = {
@@ -290,14 +279,6 @@ static const struct net_device_ops ray_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
};
-/*=============================================================================
- ray_attach() creates an "instance" of the driver, allocating
- local data structures for one device. The device is registered
- with Card Services.
- The dev_link structure is initialized, but we don't actually
- configure the card at this point -- we wait until we receive a
- card insertion event.
-=============================================================================*/
static int ray_probe(struct pcmcia_device *p_dev)
{
ray_dev_t *local;
@@ -318,9 +299,8 @@ static int ray_probe(struct pcmcia_device *p_dev)
p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
/* General socket configuration */
- p_dev->conf.Attributes = CONF_ENABLE_IRQ;
- p_dev->conf.IntType = INT_MEMORY_AND_IO;
- p_dev->conf.ConfigIndex = 1;
+ p_dev->config_flags |= CONF_ENABLE_IRQ;
+ p_dev->config_index = 1;
p_dev->priv = dev;
@@ -333,7 +313,6 @@ static int ray_probe(struct pcmcia_device *p_dev)
/* Raylink entries in the device structure */
dev->netdev_ops = &ray_netdev_ops;
- SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
dev->wireless_handlers = &ray_handler_def;
#ifdef WIRELESS_SPY
local->wireless_data.spy_data = &local->spy_data;
@@ -353,12 +332,6 @@ fail_alloc_dev:
return -ENOMEM;
} /* ray_attach */
-/*=============================================================================
- This deletes a driver "instance". The device is de-registered
- with Card Services. If it has been released, all local data
- structures are freed. Otherwise, the structures will be freed
- when the device is released.
-=============================================================================*/
static void ray_detach(struct pcmcia_device *link)
{
struct net_device *dev;
@@ -381,17 +354,11 @@ static void ray_detach(struct pcmcia_device *link)
dev_dbg(&link->dev, "ray_cs ray_detach ending\n");
} /* ray_detach */
-/*=============================================================================
- ray_config() is run after a CARD_INSERTION event
- is received, to configure the PCMCIA socket, and to make the
- ethernet device available to the system.
-=============================================================================*/
#define MAX_TUPLE_SIZE 128
static int ray_config(struct pcmcia_device *link)
{
int ret = 0;
int i;
- win_req_t req;
struct net_device *dev = (struct net_device *)link->priv;
ray_dev_t *local = netdev_priv(dev);
@@ -412,54 +379,50 @@ static int ray_config(struct pcmcia_device *link)
goto failed;
dev->irq = link->irq;
- /* This actually configures the PCMCIA socket -- setting up
- the I/O windows and the interrupt mapping.
- */
- ret = pcmcia_request_configuration(link, &link->conf);
+ ret = pcmcia_enable_device(link);
if (ret)
goto failed;
/*** Set up 32k window for shared memory (transmit and control) ************/
- req.Attributes =
- WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT;
- req.Base = 0;
- req.Size = 0x8000;
- req.AccessSpeed = ray_mem_speed;
- ret = pcmcia_request_window(link, &req, &link->win);
+ link->resource[2]->flags |= WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT;
+ link->resource[2]->start = 0;
+ link->resource[2]->end = 0x8000;
+ ret = pcmcia_request_window(link, link->resource[2], ray_mem_speed);
if (ret)
goto failed;
- ret = pcmcia_map_mem_page(link, link->win, 0);
+ ret = pcmcia_map_mem_page(link, link->resource[2], 0);
if (ret)
goto failed;
- local->sram = ioremap(req.Base, req.Size);
+ local->sram = ioremap(link->resource[2]->start,
+ resource_size(link->resource[2]));
/*** Set up 16k window for shared memory (receive buffer) ***************/
- req.Attributes =
+ link->resource[3]->flags |=
WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT;
- req.Base = 0;
- req.Size = 0x4000;
- req.AccessSpeed = ray_mem_speed;
- ret = pcmcia_request_window(link, &req, &local->rmem_handle);
+ link->resource[3]->start = 0;
+ link->resource[3]->end = 0x4000;
+ ret = pcmcia_request_window(link, link->resource[3], ray_mem_speed);
if (ret)
goto failed;
- ret = pcmcia_map_mem_page(link, local->rmem_handle, 0x8000);
+ ret = pcmcia_map_mem_page(link, link->resource[3], 0x8000);
if (ret)
goto failed;
- local->rmem = ioremap(req.Base, req.Size);
+ local->rmem = ioremap(link->resource[3]->start,
+ resource_size(link->resource[3]));
/*** Set up window for attribute memory ***********************************/
- req.Attributes =
+ link->resource[4]->flags |=
WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_AM | WIN_ENABLE | WIN_USE_WAIT;
- req.Base = 0;
- req.Size = 0x1000;
- req.AccessSpeed = ray_mem_speed;
- ret = pcmcia_request_window(link, &req, &local->amem_handle);
+ link->resource[4]->start = 0;
+ link->resource[4]->end = 0x1000;
+ ret = pcmcia_request_window(link, link->resource[4], ray_mem_speed);
if (ret)
goto failed;
- ret = pcmcia_map_mem_page(link, local->amem_handle, 0);
+ ret = pcmcia_map_mem_page(link, link->resource[4], 0);
if (ret)
goto failed;
- local->amem = ioremap(req.Base, req.Size);
+ local->amem = ioremap(link->resource[4]->start,
+ resource_size(link->resource[4]));
dev_dbg(&link->dev, "ray_config sram=%p\n", local->sram);
dev_dbg(&link->dev, "ray_config rmem=%p\n", local->rmem);
@@ -608,7 +571,7 @@ static int dl_startup_params(struct net_device *dev)
/* Start kernel timer to wait for dl startup to complete. */
local->timer.expires = jiffies + HZ / 2;
local->timer.data = (long)local;
- local->timer.function = &verify_dl_startup;
+ local->timer.function = verify_dl_startup;
add_timer(&local->timer);
dev_dbg(&link->dev,
"ray_cs dl_startup_params started timer for verify_dl_startup\n");
@@ -775,11 +738,7 @@ static void join_net(u_long data)
local->card_status = CARD_DOING_ACQ;
}
-/*============================================================================
- After a card is removed, ray_release() will unregister the net
- device, and release the PCMCIA configuration. If the device is
- still open, this will be postponed until it is closed.
-=============================================================================*/
+
static void ray_release(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
@@ -1062,18 +1021,6 @@ AP to AP 1 1 dest AP src AP dest source
}
} /* end encapsulate_frame */
-/*===========================================================================*/
-
-static void netdev_get_drvinfo(struct net_device *dev,
- struct ethtool_drvinfo *info)
-{
- strcpy(info->driver, "ray_cs");
-}
-
-static const struct ethtool_ops netdev_ethtool_ops = {
- .get_drvinfo = netdev_get_drvinfo,
-};
-
/*====================================================================*/
/*------------------------------------------------------------------*/
@@ -1997,12 +1944,12 @@ static irqreturn_t ray_interrupt(int irq, void *dev_id)
dev_dbg(&link->dev,
"ray_cs interrupt network \"%s\" start failed\n",
local->sparm.b4.a_current_ess_id);
- local->timer.function = &start_net;
+ local->timer.function = start_net;
} else {
dev_dbg(&link->dev,
"ray_cs interrupt network \"%s\" join failed\n",
local->sparm.b4.a_current_ess_id);
- local->timer.function = &join_net;
+ local->timer.function = join_net;
}
add_timer(&local->timer);
}
@@ -2470,9 +2417,9 @@ static void authenticate(ray_dev_t *local)
del_timer(&local->timer);
if (build_auth_frame(local, local->bss_id, OPEN_AUTH_REQUEST)) {
- local->timer.function = &join_net;
+ local->timer.function = join_net;
} else {
- local->timer.function = &authenticate_timeout;
+ local->timer.function = authenticate_timeout;
}
local->timer.expires = jiffies + HZ * 2;
local->timer.data = (long)local;
@@ -2557,7 +2504,7 @@ static void associate(ray_dev_t *local)
del_timer(&local->timer);
local->timer.expires = jiffies + HZ * 2;
local->timer.data = (long)local;
- local->timer.function = &join_net;
+ local->timer.function = join_net;
add_timer(&local->timer);
local->card_status = CARD_ASSOC_FAILED;
return;
@@ -2591,7 +2538,7 @@ static void clear_interrupt(ray_dev_t *local)
#ifdef CONFIG_PROC_FS
#define MAXDATA (PAGE_SIZE - 80)
-static char *card_status[] = {
+static const char *card_status[] = {
"Card inserted - uninitialized", /* 0 */
"Card not downloaded", /* 1 */
"Waiting for download parameters", /* 2 */
@@ -2608,8 +2555,8 @@ static char *card_status[] = {
"Association failed" /* 16 */
};
-static char *nettype[] = { "Adhoc", "Infra " };
-static char *framing[] = { "Encapsulation", "Translation" }
+static const char *nettype[] = { "Adhoc", "Infra " };
+static const char *framing[] = { "Encapsulation", "Translation" }
;
/*===========================================================================*/
@@ -2802,6 +2749,7 @@ static ssize_t ray_cs_essid_proc_write(struct file *file,
static const struct file_operations ray_cs_essid_proc_fops = {
.owner = THIS_MODULE,
.write = ray_cs_essid_proc_write,
+ .llseek = noop_llseek,
};
static ssize_t int_proc_write(struct file *file, const char __user *buffer,
@@ -2835,6 +2783,7 @@ static ssize_t int_proc_write(struct file *file, const char __user *buffer,
static const struct file_operations int_proc_fops = {
.owner = THIS_MODULE,
.write = int_proc_write,
+ .llseek = noop_llseek,
};
#endif
@@ -2847,9 +2796,7 @@ MODULE_DEVICE_TABLE(pcmcia, ray_ids);
static struct pcmcia_driver ray_driver = {
.owner = THIS_MODULE,
- .drv = {
- .name = "ray_cs",
- },
+ .name = "ray_cs",
.probe = ray_probe,
.remove = ray_detach,
.id_table = ray_ids,
diff --git a/drivers/net/wireless/ray_cs.h b/drivers/net/wireless/ray_cs.h
index 9f01ddb19748..e79848fbcca1 100644
--- a/drivers/net/wireless/ray_cs.h
+++ b/drivers/net/wireless/ray_cs.h
@@ -25,8 +25,6 @@ struct beacon_rx {
typedef struct ray_dev_t {
int card_status;
int authentication_state;
- window_handle_t amem_handle; /* handle to window for attribute memory */
- window_handle_t rmem_handle; /* handle to window for rx buffer on card */
void __iomem *sram; /* pointer to beginning of shared RAM */
void __iomem *amem; /* pointer to attribute mem window */
void __iomem *rmem; /* pointer to receive buffer window */
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 719573bbbf81..71b5971da597 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -540,11 +540,11 @@ static int rndis_set_channel(struct wiphy *wiphy, struct net_device *dev,
struct ieee80211_channel *chan, enum nl80211_channel_type channel_type);
static int rndis_add_key(struct wiphy *wiphy, struct net_device *netdev,
- u8 key_index, const u8 *mac_addr,
- struct key_params *params);
+ u8 key_index, bool pairwise, const u8 *mac_addr,
+ struct key_params *params);
static int rndis_del_key(struct wiphy *wiphy, struct net_device *netdev,
- u8 key_index, const u8 *mac_addr);
+ u8 key_index, bool pairwise, const u8 *mac_addr);
static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev,
u8 key_index);
@@ -2308,8 +2308,8 @@ static int rndis_set_channel(struct wiphy *wiphy, struct net_device *netdev,
}
static int rndis_add_key(struct wiphy *wiphy, struct net_device *netdev,
- u8 key_index, const u8 *mac_addr,
- struct key_params *params)
+ u8 key_index, bool pairwise, const u8 *mac_addr,
+ struct key_params *params)
{
struct rndis_wlan_private *priv = wiphy_priv(wiphy);
struct usbnet *usbdev = priv->usbdev;
@@ -2344,7 +2344,7 @@ static int rndis_add_key(struct wiphy *wiphy, struct net_device *netdev,
}
static int rndis_del_key(struct wiphy *wiphy, struct net_device *netdev,
- u8 key_index, const u8 *mac_addr)
+ u8 key_index, bool pairwise, const u8 *mac_addr)
{
struct rndis_wlan_private *priv = wiphy_priv(wiphy);
struct usbnet *usbdev = priv->usbdev;
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 5063e01410e5..4f420a9ec5dc 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -321,7 +321,8 @@ static void rt2400pci_config_intf(struct rt2x00_dev *rt2x00dev,
}
static void rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev,
- struct rt2x00lib_erp *erp)
+ struct rt2x00lib_erp *erp,
+ u32 changed)
{
int preamble_mask;
u32 reg;
@@ -329,59 +330,72 @@ static void rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev,
/*
* When short preamble is enabled, we should set bit 0x08
*/
- preamble_mask = erp->short_preamble << 3;
-
- rt2x00pci_register_read(rt2x00dev, TXCSR1, &reg);
- rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT, 0x1ff);
- rt2x00_set_field32(&reg, TXCSR1_ACK_CONSUME_TIME, 0x13a);
- rt2x00_set_field32(&reg, TXCSR1_TSF_OFFSET, IEEE80211_HEADER);
- rt2x00_set_field32(&reg, TXCSR1_AUTORESPONDER, 1);
- rt2x00pci_register_write(rt2x00dev, TXCSR1, reg);
-
- rt2x00pci_register_read(rt2x00dev, ARCSR2, &reg);
- rt2x00_set_field32(&reg, ARCSR2_SIGNAL, 0x00);
- rt2x00_set_field32(&reg, ARCSR2_SERVICE, 0x04);
- rt2x00_set_field32(&reg, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 10));
- rt2x00pci_register_write(rt2x00dev, ARCSR2, reg);
-
- rt2x00pci_register_read(rt2x00dev, ARCSR3, &reg);
- rt2x00_set_field32(&reg, ARCSR3_SIGNAL, 0x01 | preamble_mask);
- rt2x00_set_field32(&reg, ARCSR3_SERVICE, 0x04);
- rt2x00_set_field32(&reg, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 20));
- rt2x00pci_register_write(rt2x00dev, ARCSR3, reg);
-
- rt2x00pci_register_read(rt2x00dev, ARCSR4, &reg);
- rt2x00_set_field32(&reg, ARCSR4_SIGNAL, 0x02 | preamble_mask);
- rt2x00_set_field32(&reg, ARCSR4_SERVICE, 0x04);
- rt2x00_set_field32(&reg, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 55));
- rt2x00pci_register_write(rt2x00dev, ARCSR4, reg);
-
- rt2x00pci_register_read(rt2x00dev, ARCSR5, &reg);
- rt2x00_set_field32(&reg, ARCSR5_SIGNAL, 0x03 | preamble_mask);
- rt2x00_set_field32(&reg, ARCSR5_SERVICE, 0x84);
- rt2x00_set_field32(&reg, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 110));
- rt2x00pci_register_write(rt2x00dev, ARCSR5, reg);
-
- rt2x00pci_register_write(rt2x00dev, ARCSR1, erp->basic_rates);
+ if (changed & BSS_CHANGED_ERP_PREAMBLE) {
+ preamble_mask = erp->short_preamble << 3;
+
+ rt2x00pci_register_read(rt2x00dev, TXCSR1, &reg);
+ rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT, 0x1ff);
+ rt2x00_set_field32(&reg, TXCSR1_ACK_CONSUME_TIME, 0x13a);
+ rt2x00_set_field32(&reg, TXCSR1_TSF_OFFSET, IEEE80211_HEADER);
+ rt2x00_set_field32(&reg, TXCSR1_AUTORESPONDER, 1);
+ rt2x00pci_register_write(rt2x00dev, TXCSR1, reg);
+
+ rt2x00pci_register_read(rt2x00dev, ARCSR2, &reg);
+ rt2x00_set_field32(&reg, ARCSR2_SIGNAL, 0x00);
+ rt2x00_set_field32(&reg, ARCSR2_SERVICE, 0x04);
+ rt2x00_set_field32(&reg, ARCSR2_LENGTH,
+ GET_DURATION(ACK_SIZE, 10));
+ rt2x00pci_register_write(rt2x00dev, ARCSR2, reg);
+
+ rt2x00pci_register_read(rt2x00dev, ARCSR3, &reg);
+ rt2x00_set_field32(&reg, ARCSR3_SIGNAL, 0x01 | preamble_mask);
+ rt2x00_set_field32(&reg, ARCSR3_SERVICE, 0x04);
+ rt2x00_set_field32(&reg, ARCSR2_LENGTH,
+ GET_DURATION(ACK_SIZE, 20));
+ rt2x00pci_register_write(rt2x00dev, ARCSR3, reg);
+
+ rt2x00pci_register_read(rt2x00dev, ARCSR4, &reg);
+ rt2x00_set_field32(&reg, ARCSR4_SIGNAL, 0x02 | preamble_mask);
+ rt2x00_set_field32(&reg, ARCSR4_SERVICE, 0x04);
+ rt2x00_set_field32(&reg, ARCSR2_LENGTH,
+ GET_DURATION(ACK_SIZE, 55));
+ rt2x00pci_register_write(rt2x00dev, ARCSR4, reg);
+
+ rt2x00pci_register_read(rt2x00dev, ARCSR5, &reg);
+ rt2x00_set_field32(&reg, ARCSR5_SIGNAL, 0x03 | preamble_mask);
+ rt2x00_set_field32(&reg, ARCSR5_SERVICE, 0x84);
+ rt2x00_set_field32(&reg, ARCSR2_LENGTH,
+ GET_DURATION(ACK_SIZE, 110));
+ rt2x00pci_register_write(rt2x00dev, ARCSR5, reg);
+ }
- rt2x00pci_register_read(rt2x00dev, CSR11, &reg);
- rt2x00_set_field32(&reg, CSR11_SLOT_TIME, erp->slot_time);
- rt2x00pci_register_write(rt2x00dev, CSR11, reg);
+ if (changed & BSS_CHANGED_BASIC_RATES)
+ rt2x00pci_register_write(rt2x00dev, ARCSR1, erp->basic_rates);
- rt2x00pci_register_read(rt2x00dev, CSR12, &reg);
- rt2x00_set_field32(&reg, CSR12_BEACON_INTERVAL, erp->beacon_int * 16);
- rt2x00_set_field32(&reg, CSR12_CFP_MAX_DURATION, erp->beacon_int * 16);
- rt2x00pci_register_write(rt2x00dev, CSR12, reg);
+ if (changed & BSS_CHANGED_ERP_SLOT) {
+ rt2x00pci_register_read(rt2x00dev, CSR11, &reg);
+ rt2x00_set_field32(&reg, CSR11_SLOT_TIME, erp->slot_time);
+ rt2x00pci_register_write(rt2x00dev, CSR11, reg);
- rt2x00pci_register_read(rt2x00dev, CSR18, &reg);
- rt2x00_set_field32(&reg, CSR18_SIFS, erp->sifs);
- rt2x00_set_field32(&reg, CSR18_PIFS, erp->pifs);
- rt2x00pci_register_write(rt2x00dev, CSR18, reg);
+ rt2x00pci_register_read(rt2x00dev, CSR18, &reg);
+ rt2x00_set_field32(&reg, CSR18_SIFS, erp->sifs);
+ rt2x00_set_field32(&reg, CSR18_PIFS, erp->pifs);
+ rt2x00pci_register_write(rt2x00dev, CSR18, reg);
+
+ rt2x00pci_register_read(rt2x00dev, CSR19, &reg);
+ rt2x00_set_field32(&reg, CSR19_DIFS, erp->difs);
+ rt2x00_set_field32(&reg, CSR19_EIFS, erp->eifs);
+ rt2x00pci_register_write(rt2x00dev, CSR19, reg);
+ }
- rt2x00pci_register_read(rt2x00dev, CSR19, &reg);
- rt2x00_set_field32(&reg, CSR19_DIFS, erp->difs);
- rt2x00_set_field32(&reg, CSR19_EIFS, erp->eifs);
- rt2x00pci_register_write(rt2x00dev, CSR19, reg);
+ if (changed & BSS_CHANGED_BEACON_INT) {
+ rt2x00pci_register_read(rt2x00dev, CSR12, &reg);
+ rt2x00_set_field32(&reg, CSR12_BEACON_INTERVAL,
+ erp->beacon_int * 16);
+ rt2x00_set_field32(&reg, CSR12_CFP_MAX_DURATION,
+ erp->beacon_int * 16);
+ rt2x00pci_register_write(rt2x00dev, CSR12, reg);
+ }
}
static void rt2400pci_config_ant(struct rt2x00_dev *rt2x00dev,
@@ -1007,12 +1021,11 @@ static int rt2400pci_set_device_state(struct rt2x00_dev *rt2x00dev,
/*
* TX descriptor initialization
*/
-static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
- struct sk_buff *skb,
+static void rt2400pci_write_tx_desc(struct queue_entry *entry,
struct txentry_desc *txdesc)
{
- struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
- struct queue_entry_priv_pci *entry_priv = skbdesc->entry->priv_data;
+ struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+ struct queue_entry_priv_pci *entry_priv = entry->priv_data;
__le32 *txd = entry_priv->desc;
u32 word;
@@ -1091,12 +1104,12 @@ static void rt2400pci_write_beacon(struct queue_entry *entry,
rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
rt2x00pci_register_write(rt2x00dev, CSR14, reg);
- rt2x00queue_map_txskb(rt2x00dev, entry->skb);
+ rt2x00queue_map_txskb(entry);
/*
* Write the TX descriptor for the beacon.
*/
- rt2400pci_write_tx_desc(rt2x00dev, entry->skb, txdesc);
+ rt2400pci_write_tx_desc(entry, txdesc);
/*
* Dump beacon to userspace through debugfs.
@@ -1112,24 +1125,24 @@ static void rt2400pci_write_beacon(struct queue_entry *entry,
rt2x00pci_register_write(rt2x00dev, CSR14, reg);
}
-static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
- const enum data_queue_qid queue)
+static void rt2400pci_kick_tx_queue(struct data_queue *queue)
{
+ struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
u32 reg;
rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
- rt2x00_set_field32(&reg, TXCSR0_KICK_PRIO, (queue == QID_AC_BE));
- rt2x00_set_field32(&reg, TXCSR0_KICK_TX, (queue == QID_AC_BK));
- rt2x00_set_field32(&reg, TXCSR0_KICK_ATIM, (queue == QID_ATIM));
+ rt2x00_set_field32(&reg, TXCSR0_KICK_PRIO, (queue->qid == QID_AC_BE));
+ rt2x00_set_field32(&reg, TXCSR0_KICK_TX, (queue->qid == QID_AC_BK));
+ rt2x00_set_field32(&reg, TXCSR0_KICK_ATIM, (queue->qid == QID_ATIM));
rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
}
-static void rt2400pci_kill_tx_queue(struct rt2x00_dev *rt2x00dev,
- const enum data_queue_qid qid)
+static void rt2400pci_kill_tx_queue(struct data_queue *queue)
{
+ struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
u32 reg;
- if (qid == QID_BEACON) {
+ if (queue->qid == QID_BEACON) {
rt2x00pci_register_write(rt2x00dev, CSR14, 0);
} else {
rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
@@ -1481,15 +1494,17 @@ static int rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
/*
* Create channel information array
*/
- info = kzalloc(spec->num_channels * sizeof(*info), GFP_KERNEL);
+ info = kcalloc(spec->num_channels, sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
spec->channels_info = info;
tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START);
- for (i = 0; i < 14; i++)
- info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+ for (i = 0; i < 14; i++) {
+ info[i].max_power = TXPOWER_FROM_DEV(MAX_TXPOWER);
+ info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+ }
return 0;
}
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index c2a555d5376b..97feb7aef809 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -327,7 +327,8 @@ static void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev,
}
static void rt2500pci_config_erp(struct rt2x00_dev *rt2x00dev,
- struct rt2x00lib_erp *erp)
+ struct rt2x00lib_erp *erp,
+ u32 changed)
{
int preamble_mask;
u32 reg;
@@ -335,59 +336,73 @@ static void rt2500pci_config_erp(struct rt2x00_dev *rt2x00dev,
/*
* When short preamble is enabled, we should set bit 0x08
*/
- preamble_mask = erp->short_preamble << 3;
-
- rt2x00pci_register_read(rt2x00dev, TXCSR1, &reg);
- rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT, 0x162);
- rt2x00_set_field32(&reg, TXCSR1_ACK_CONSUME_TIME, 0xa2);
- rt2x00_set_field32(&reg, TXCSR1_TSF_OFFSET, IEEE80211_HEADER);
- rt2x00_set_field32(&reg, TXCSR1_AUTORESPONDER, 1);
- rt2x00pci_register_write(rt2x00dev, TXCSR1, reg);
-
- rt2x00pci_register_read(rt2x00dev, ARCSR2, &reg);
- rt2x00_set_field32(&reg, ARCSR2_SIGNAL, 0x00);
- rt2x00_set_field32(&reg, ARCSR2_SERVICE, 0x04);
- rt2x00_set_field32(&reg, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 10));
- rt2x00pci_register_write(rt2x00dev, ARCSR2, reg);
-
- rt2x00pci_register_read(rt2x00dev, ARCSR3, &reg);
- rt2x00_set_field32(&reg, ARCSR3_SIGNAL, 0x01 | preamble_mask);
- rt2x00_set_field32(&reg, ARCSR3_SERVICE, 0x04);
- rt2x00_set_field32(&reg, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 20));
- rt2x00pci_register_write(rt2x00dev, ARCSR3, reg);
-
- rt2x00pci_register_read(rt2x00dev, ARCSR4, &reg);
- rt2x00_set_field32(&reg, ARCSR4_SIGNAL, 0x02 | preamble_mask);
- rt2x00_set_field32(&reg, ARCSR4_SERVICE, 0x04);
- rt2x00_set_field32(&reg, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 55));
- rt2x00pci_register_write(rt2x00dev, ARCSR4, reg);
-
- rt2x00pci_register_read(rt2x00dev, ARCSR5, &reg);
- rt2x00_set_field32(&reg, ARCSR5_SIGNAL, 0x03 | preamble_mask);
- rt2x00_set_field32(&reg, ARCSR5_SERVICE, 0x84);
- rt2x00_set_field32(&reg, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 110));
- rt2x00pci_register_write(rt2x00dev, ARCSR5, reg);
-
- rt2x00pci_register_write(rt2x00dev, ARCSR1, erp->basic_rates);
+ if (changed & BSS_CHANGED_ERP_PREAMBLE) {
+ preamble_mask = erp->short_preamble << 3;
+
+ rt2x00pci_register_read(rt2x00dev, TXCSR1, &reg);
+ rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT, 0x162);
+ rt2x00_set_field32(&reg, TXCSR1_ACK_CONSUME_TIME, 0xa2);
+ rt2x00_set_field32(&reg, TXCSR1_TSF_OFFSET, IEEE80211_HEADER);
+ rt2x00_set_field32(&reg, TXCSR1_AUTORESPONDER, 1);
+ rt2x00pci_register_write(rt2x00dev, TXCSR1, reg);
+
+ rt2x00pci_register_read(rt2x00dev, ARCSR2, &reg);
+ rt2x00_set_field32(&reg, ARCSR2_SIGNAL, 0x00);
+ rt2x00_set_field32(&reg, ARCSR2_SERVICE, 0x04);
+ rt2x00_set_field32(&reg, ARCSR2_LENGTH,
+ GET_DURATION(ACK_SIZE, 10));
+ rt2x00pci_register_write(rt2x00dev, ARCSR2, reg);
+
+ rt2x00pci_register_read(rt2x00dev, ARCSR3, &reg);
+ rt2x00_set_field32(&reg, ARCSR3_SIGNAL, 0x01 | preamble_mask);
+ rt2x00_set_field32(&reg, ARCSR3_SERVICE, 0x04);
+ rt2x00_set_field32(&reg, ARCSR2_LENGTH,
+ GET_DURATION(ACK_SIZE, 20));
+ rt2x00pci_register_write(rt2x00dev, ARCSR3, reg);
+
+ rt2x00pci_register_read(rt2x00dev, ARCSR4, &reg);
+ rt2x00_set_field32(&reg, ARCSR4_SIGNAL, 0x02 | preamble_mask);
+ rt2x00_set_field32(&reg, ARCSR4_SERVICE, 0x04);
+ rt2x00_set_field32(&reg, ARCSR2_LENGTH,
+ GET_DURATION(ACK_SIZE, 55));
+ rt2x00pci_register_write(rt2x00dev, ARCSR4, reg);
+
+ rt2x00pci_register_read(rt2x00dev, ARCSR5, &reg);
+ rt2x00_set_field32(&reg, ARCSR5_SIGNAL, 0x03 | preamble_mask);
+ rt2x00_set_field32(&reg, ARCSR5_SERVICE, 0x84);
+ rt2x00_set_field32(&reg, ARCSR2_LENGTH,
+ GET_DURATION(ACK_SIZE, 110));
+ rt2x00pci_register_write(rt2x00dev, ARCSR5, reg);
+ }
- rt2x00pci_register_read(rt2x00dev, CSR11, &reg);
- rt2x00_set_field32(&reg, CSR11_SLOT_TIME, erp->slot_time);
- rt2x00pci_register_write(rt2x00dev, CSR11, reg);
+ if (changed & BSS_CHANGED_BASIC_RATES)
+ rt2x00pci_register_write(rt2x00dev, ARCSR1, erp->basic_rates);
- rt2x00pci_register_read(rt2x00dev, CSR12, &reg);
- rt2x00_set_field32(&reg, CSR12_BEACON_INTERVAL, erp->beacon_int * 16);
- rt2x00_set_field32(&reg, CSR12_CFP_MAX_DURATION, erp->beacon_int * 16);
- rt2x00pci_register_write(rt2x00dev, CSR12, reg);
+ if (changed & BSS_CHANGED_ERP_SLOT) {
+ rt2x00pci_register_read(rt2x00dev, CSR11, &reg);
+ rt2x00_set_field32(&reg, CSR11_SLOT_TIME, erp->slot_time);
+ rt2x00pci_register_write(rt2x00dev, CSR11, reg);
- rt2x00pci_register_read(rt2x00dev, CSR18, &reg);
- rt2x00_set_field32(&reg, CSR18_SIFS, erp->sifs);
- rt2x00_set_field32(&reg, CSR18_PIFS, erp->pifs);
- rt2x00pci_register_write(rt2x00dev, CSR18, reg);
+ rt2x00pci_register_read(rt2x00dev, CSR18, &reg);
+ rt2x00_set_field32(&reg, CSR18_SIFS, erp->sifs);
+ rt2x00_set_field32(&reg, CSR18_PIFS, erp->pifs);
+ rt2x00pci_register_write(rt2x00dev, CSR18, reg);
+
+ rt2x00pci_register_read(rt2x00dev, CSR19, &reg);
+ rt2x00_set_field32(&reg, CSR19_DIFS, erp->difs);
+ rt2x00_set_field32(&reg, CSR19_EIFS, erp->eifs);
+ rt2x00pci_register_write(rt2x00dev, CSR19, reg);
+ }
+
+ if (changed & BSS_CHANGED_BEACON_INT) {
+ rt2x00pci_register_read(rt2x00dev, CSR12, &reg);
+ rt2x00_set_field32(&reg, CSR12_BEACON_INTERVAL,
+ erp->beacon_int * 16);
+ rt2x00_set_field32(&reg, CSR12_CFP_MAX_DURATION,
+ erp->beacon_int * 16);
+ rt2x00pci_register_write(rt2x00dev, CSR12, reg);
+ }
- rt2x00pci_register_read(rt2x00dev, CSR19, &reg);
- rt2x00_set_field32(&reg, CSR19_DIFS, erp->difs);
- rt2x00_set_field32(&reg, CSR19_EIFS, erp->eifs);
- rt2x00pci_register_write(rt2x00dev, CSR19, reg);
}
static void rt2500pci_config_ant(struct rt2x00_dev *rt2x00dev,
@@ -1161,12 +1176,11 @@ static int rt2500pci_set_device_state(struct rt2x00_dev *rt2x00dev,
/*
* TX descriptor initialization
*/
-static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
- struct sk_buff *skb,
+static void rt2500pci_write_tx_desc(struct queue_entry *entry,
struct txentry_desc *txdesc)
{
- struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
- struct queue_entry_priv_pci *entry_priv = skbdesc->entry->priv_data;
+ struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+ struct queue_entry_priv_pci *entry_priv = entry->priv_data;
__le32 *txd = entry_priv->desc;
u32 word;
@@ -1244,12 +1258,12 @@ static void rt2500pci_write_beacon(struct queue_entry *entry,
rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
rt2x00pci_register_write(rt2x00dev, CSR14, reg);
- rt2x00queue_map_txskb(rt2x00dev, entry->skb);
+ rt2x00queue_map_txskb(entry);
/*
* Write the TX descriptor for the beacon.
*/
- rt2500pci_write_tx_desc(rt2x00dev, entry->skb, txdesc);
+ rt2500pci_write_tx_desc(entry, txdesc);
/*
* Dump beacon to userspace through debugfs.
@@ -1265,24 +1279,24 @@ static void rt2500pci_write_beacon(struct queue_entry *entry,
rt2x00pci_register_write(rt2x00dev, CSR14, reg);
}
-static void rt2500pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
- const enum data_queue_qid queue)
+static void rt2500pci_kick_tx_queue(struct data_queue *queue)
{
+ struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
u32 reg;
rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
- rt2x00_set_field32(&reg, TXCSR0_KICK_PRIO, (queue == QID_AC_BE));
- rt2x00_set_field32(&reg, TXCSR0_KICK_TX, (queue == QID_AC_BK));
- rt2x00_set_field32(&reg, TXCSR0_KICK_ATIM, (queue == QID_ATIM));
+ rt2x00_set_field32(&reg, TXCSR0_KICK_PRIO, (queue->qid == QID_AC_BE));
+ rt2x00_set_field32(&reg, TXCSR0_KICK_TX, (queue->qid == QID_AC_BK));
+ rt2x00_set_field32(&reg, TXCSR0_KICK_ATIM, (queue->qid == QID_ATIM));
rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
}
-static void rt2500pci_kill_tx_queue(struct rt2x00_dev *rt2x00dev,
- const enum data_queue_qid qid)
+static void rt2500pci_kill_tx_queue(struct data_queue *queue)
{
+ struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
u32 reg;
- if (qid == QID_BEACON) {
+ if (queue->qid == QID_BEACON) {
rt2x00pci_register_write(rt2x00dev, CSR14, 0);
} else {
rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
@@ -1795,19 +1809,23 @@ static int rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
/*
* Create channel information array
*/
- info = kzalloc(spec->num_channels * sizeof(*info), GFP_KERNEL);
+ info = kcalloc(spec->num_channels, sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
spec->channels_info = info;
tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START);
- for (i = 0; i < 14; i++)
- info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+ for (i = 0; i < 14; i++) {
+ info[i].max_power = MAX_TXPOWER;
+ info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+ }
if (spec->num_channels > 14) {
- for (i = 14; i < spec->num_channels; i++)
- info[i].tx_power1 = DEFAULT_TXPOWER;
+ for (i = 14; i < spec->num_channels; i++) {
+ info[i].max_power = MAX_TXPOWER;
+ info[i].default_power1 = DEFAULT_TXPOWER;
+ }
}
return 0;
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index cdaf93f48263..93e44c7f3a74 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -355,7 +355,9 @@ static int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev,
* it is known that not work at least on some hardware.
* SW crypto will be used in that case.
*/
- if (key->alg == ALG_WEP && key->keyidx != 0)
+ if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
+ key->cipher == WLAN_CIPHER_SUITE_WEP104) &&
+ key->keyidx != 0)
return -EOPNOTSUPP;
/*
@@ -492,24 +494,34 @@ static void rt2500usb_config_intf(struct rt2x00_dev *rt2x00dev,
}
static void rt2500usb_config_erp(struct rt2x00_dev *rt2x00dev,
- struct rt2x00lib_erp *erp)
+ struct rt2x00lib_erp *erp,
+ u32 changed)
{
u16 reg;
- rt2500usb_register_read(rt2x00dev, TXRX_CSR10, &reg);
- rt2x00_set_field16(&reg, TXRX_CSR10_AUTORESPOND_PREAMBLE,
- !!erp->short_preamble);
- rt2500usb_register_write(rt2x00dev, TXRX_CSR10, reg);
+ if (changed & BSS_CHANGED_ERP_PREAMBLE) {
+ rt2500usb_register_read(rt2x00dev, TXRX_CSR10, &reg);
+ rt2x00_set_field16(&reg, TXRX_CSR10_AUTORESPOND_PREAMBLE,
+ !!erp->short_preamble);
+ rt2500usb_register_write(rt2x00dev, TXRX_CSR10, reg);
+ }
- rt2500usb_register_write(rt2x00dev, TXRX_CSR11, erp->basic_rates);
+ if (changed & BSS_CHANGED_BASIC_RATES)
+ rt2500usb_register_write(rt2x00dev, TXRX_CSR11,
+ erp->basic_rates);
- rt2500usb_register_read(rt2x00dev, TXRX_CSR18, &reg);
- rt2x00_set_field16(&reg, TXRX_CSR18_INTERVAL, erp->beacon_int * 4);
- rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg);
+ if (changed & BSS_CHANGED_BEACON_INT) {
+ rt2500usb_register_read(rt2x00dev, TXRX_CSR18, &reg);
+ rt2x00_set_field16(&reg, TXRX_CSR18_INTERVAL,
+ erp->beacon_int * 4);
+ rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg);
+ }
- rt2500usb_register_write(rt2x00dev, MAC_CSR10, erp->slot_time);
- rt2500usb_register_write(rt2x00dev, MAC_CSR11, erp->sifs);
- rt2500usb_register_write(rt2x00dev, MAC_CSR12, erp->eifs);
+ if (changed & BSS_CHANGED_ERP_SLOT) {
+ rt2500usb_register_write(rt2x00dev, MAC_CSR10, erp->slot_time);
+ rt2500usb_register_write(rt2x00dev, MAC_CSR11, erp->sifs);
+ rt2500usb_register_write(rt2x00dev, MAC_CSR12, erp->eifs);
+ }
}
static void rt2500usb_config_ant(struct rt2x00_dev *rt2x00dev,
@@ -1039,12 +1051,11 @@ static int rt2500usb_set_device_state(struct rt2x00_dev *rt2x00dev,
/*
* TX descriptor initialization
*/
-static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
- struct sk_buff *skb,
+static void rt2500usb_write_tx_desc(struct queue_entry *entry,
struct txentry_desc *txdesc)
{
- struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
- __le32 *txd = (__le32 *) skb->data;
+ struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+ __le32 *txd = (__le32 *) entry->skb->data;
u32 word;
/*
@@ -1127,7 +1138,7 @@ static void rt2500usb_write_beacon(struct queue_entry *entry,
/*
* Write the TX descriptor for the beacon.
*/
- rt2500usb_write_tx_desc(rt2x00dev, entry->skb, txdesc);
+ rt2500usb_write_tx_desc(entry, txdesc);
/*
* Dump beacon to userspace through debugfs.
@@ -1195,6 +1206,14 @@ static int rt2500usb_get_tx_data_len(struct queue_entry *entry)
return length;
}
+static void rt2500usb_kill_tx_queue(struct data_queue *queue)
+{
+ if (queue->qid == QID_BEACON)
+ rt2500usb_register_write(queue->rt2x00dev, TXRX_CSR19, 0);
+
+ rt2x00usb_kill_tx_queue(queue);
+}
+
/*
* RX control handlers
*/
@@ -1655,10 +1674,15 @@ static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
/*
* Initialize all hw fields.
+ *
+ * Don't set IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING unless we are
+ * capable of sending the buffered frames out after the DTIM
+ * transmission using rt2x00lib_beacondone. This will send out
+ * multicast and broadcast traffic immediately instead of buffering it
+ * infinitly and thus dropping it after some time.
*/
rt2x00dev->hw->flags =
IEEE80211_HW_RX_INCLUDES_FCS |
- IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
IEEE80211_HW_SIGNAL_DBM |
IEEE80211_HW_SUPPORTS_PS |
IEEE80211_HW_PS_NULLFUNC_STACK;
@@ -1698,19 +1722,23 @@ static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
/*
* Create channel information array
*/
- info = kzalloc(spec->num_channels * sizeof(*info), GFP_KERNEL);
+ info = kcalloc(spec->num_channels, sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
spec->channels_info = info;
tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START);
- for (i = 0; i < 14; i++)
- info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+ for (i = 0; i < 14; i++) {
+ info[i].max_power = MAX_TXPOWER;
+ info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+ }
if (spec->num_channels > 14) {
- for (i = 14; i < spec->num_channels; i++)
- info[i].tx_power1 = DEFAULT_TXPOWER;
+ for (i = 14; i < spec->num_channels; i++) {
+ info[i].max_power = MAX_TXPOWER;
+ info[i].default_power1 = DEFAULT_TXPOWER;
+ }
}
return 0;
@@ -1789,7 +1817,7 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
.write_beacon = rt2500usb_write_beacon,
.get_tx_data_len = rt2500usb_get_tx_data_len,
.kick_tx_queue = rt2x00usb_kick_tx_queue,
- .kill_tx_queue = rt2x00usb_kill_tx_queue,
+ .kill_tx_queue = rt2500usb_kill_tx_queue,
.fill_rxdone = rt2500usb_fill_rxdone,
.config_shared_key = rt2500usb_config_key,
.config_pairwise_key = rt2500usb_config_key,
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h
index ed4ebcdde7c9..eb8b6cab9925 100644
--- a/drivers/net/wireless/rt2x00/rt2800.h
+++ b/drivers/net/wireless/rt2x00/rt2800.h
@@ -1,5 +1,6 @@
/*
- Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+ Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
+ Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com>
Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com>
@@ -639,6 +640,18 @@
#define LED_CFG_LED_POLAR FIELD32(0x40000000)
/*
+ * AMPDU_BA_WINSIZE: Force BlockAck window size
+ * FORCE_WINSIZE_ENABLE:
+ * 0: Disable forcing of BlockAck window size
+ * 1: Enable forcing of BlockAck window size, overwrites values BlockAck
+ * window size values in the TXWI
+ * FORCE_WINSIZE: BlockAck window size
+ */
+#define AMPDU_BA_WINSIZE 0x1040
+#define AMPDU_BA_WINSIZE_FORCE_WINSIZE_ENABLE FIELD32(0x00000020)
+#define AMPDU_BA_WINSIZE_FORCE_WINSIZE FIELD32(0x0000001f)
+
+/*
* XIFS_TIME_CFG: MAC timing
* CCKM_SIFS_TIME: unit 1us. Applied after CCK RX/TX
* OFDM_SIFS_TIME: unit 1us. Applied after OFDM RX/TX
@@ -698,8 +711,14 @@
/*
* TBTT_SYNC_CFG:
+ * BCN_AIFSN: Beacon AIFSN after TBTT interrupt in slots
+ * BCN_CWMIN: Beacon CWMin after TBTT interrupt in slots
*/
#define TBTT_SYNC_CFG 0x1118
+#define TBTT_SYNC_CFG_TBTT_ADJUST FIELD32(0x000000ff)
+#define TBTT_SYNC_CFG_BCN_EXP_WIN FIELD32(0x0000ff00)
+#define TBTT_SYNC_CFG_BCN_AIFSN FIELD32(0x000f0000)
+#define TBTT_SYNC_CFG_BCN_CWMIN FIELD32(0x00f00000)
/*
* TSF_TIMER_DW0: Local lsb TSF timer, read-only
@@ -735,16 +754,21 @@
#define INT_TIMER_EN_GP_TIMER FIELD32(0x00000002)
/*
- * CH_IDLE_STA: channel idle time
+ * CH_IDLE_STA: channel idle time (in us)
*/
#define CH_IDLE_STA 0x1130
/*
- * CH_BUSY_STA: channel busy time
+ * CH_BUSY_STA: channel busy time on primary channel (in us)
*/
#define CH_BUSY_STA 0x1134
/*
+ * CH_BUSY_STA_SEC: channel busy time on secondary channel in HT40 mode (in us)
+ */
+#define CH_BUSY_STA_SEC 0x1138
+
+/*
* MAC_STATUS_CFG:
* BBP_RF_BUSY: When set to 0, BBP and RF are stable.
* if 1 or higher one of the 2 registers is busy.
@@ -1318,11 +1342,34 @@
#define TX_STA_CNT2_TX_UNDER_FLOW_COUNT FIELD32(0xffff0000)
/*
- * TX_STA_FIFO: TX Result for specific PID status fifo register
+ * TX_STA_FIFO: TX Result for specific PID status fifo register.
+ *
+ * This register is implemented as FIFO with 16 entries in the HW. Each
+ * register read fetches the next tx result. If the FIFO is full because
+ * it wasn't read fast enough after the according interrupt (TX_FIFO_STATUS)
+ * triggered, the hw seems to simply drop further tx results.
+ *
+ * VALID: 1: this tx result is valid
+ * 0: no valid tx result -> driver should stop reading
+ * PID_TYPE: The PID latched from the PID field in the TXWI, can be used
+ * to match a frame with its tx result (even though the PID is
+ * only 4 bits wide).
+ * PID_QUEUE: Part of PID_TYPE, this is the queue index number (0-3)
+ * PID_ENTRY: Part of PID_TYPE, this is the queue entry index number (1-3)
+ * This identification number is calculated by ((idx % 3) + 1).
+ * TX_SUCCESS: Indicates tx success (1) or failure (0)
+ * TX_AGGRE: Indicates if the frame was part of an aggregate (1) or not (0)
+ * TX_ACK_REQUIRED: Indicates if the frame needed to get ack'ed (1) or not (0)
+ * WCID: The wireless client ID.
+ * MCS: The tx rate used during the last transmission of this frame, be it
+ * successful or not.
+ * PHYMODE: The phymode used for the transmission.
*/
#define TX_STA_FIFO 0x1718
#define TX_STA_FIFO_VALID FIELD32(0x00000001)
#define TX_STA_FIFO_PID_TYPE FIELD32(0x0000001e)
+#define TX_STA_FIFO_PID_QUEUE FIELD32(0x00000006)
+#define TX_STA_FIFO_PID_ENTRY FIELD32(0x00000018)
#define TX_STA_FIFO_TX_SUCCESS FIELD32(0x00000020)
#define TX_STA_FIFO_TX_AGGRE FIELD32(0x00000040)
#define TX_STA_FIFO_TX_ACK_REQUIRED FIELD32(0x00000080)
@@ -1405,6 +1452,24 @@
/*
* Security key table memory.
+ *
+ * The pairwise key table shares some memory with the beacon frame
+ * buffers 6 and 7. That basically means that when beacon 6 & 7
+ * are used we should only use the reduced pairwise key table which
+ * has a maximum of 222 entries.
+ *
+ * ---------------------------------------------
+ * |0x4000 | Pairwise Key | Reduced Pairwise |
+ * | | Table | Key Table |
+ * | | Size: 256 * 32 | Size: 222 * 32 |
+ * |0x5BC0 | |-------------------
+ * | | | Beacon 6 |
+ * |0x5DC0 | |-------------------
+ * | | | Beacon 7 |
+ * |0x5FC0 | |-------------------
+ * |0x5FFF | |
+ * --------------------------
+ *
* MAC_WCID_BASE: 8-bytes (use only 6 bytes) * 256 entry
* PAIRWISE_KEY_TABLE_BASE: 32-byte * 256 entry
* MAC_IVEIV_TABLE_BASE: 8-byte * 256-entry
@@ -1554,7 +1619,8 @@ struct mac_iveiv_entry {
* 2. Extract memory from FCE table for BCN 4~5
* 3. Extract memory from Pair-wise key table for BCN 6~7
* It occupied those memory of wcid 238~253 for BCN 6
- * and wcid 222~237 for BCN 7
+ * and wcid 222~237 for BCN 7 (see Security key table memory
+ * for more info).
*
* IMPORTANT NOTE: Not sure why legacy driver does this,
* but HW_BEACON_BASE7 is 0x0200 bytes below HW_BEACON_BASE6.
@@ -1841,6 +1907,13 @@ struct mac_iveiv_entry {
#define EEPROM_RSSI_A2_LNA_A2 FIELD16(0xff00)
/*
+ * EEPROM Maximum TX power values
+ */
+#define EEPROM_MAX_TX_POWER 0x0027
+#define EEPROM_MAX_TX_POWER_24GHZ FIELD16(0x00ff)
+#define EEPROM_MAX_TX_POWER_5GHZ FIELD16(0xff00)
+
+/*
* EEPROM TXpower delta: 20MHZ AND 40 MHZ use different power.
* This is delta in 40MHZ.
* VALUE: Tx Power dalta value (MAX=4)
@@ -1926,8 +1999,17 @@ struct mac_iveiv_entry {
* FRAG: 1 To inform TKIP engine this is a fragment.
* MIMO_PS: The remote peer is in dynamic MIMO-PS mode
* TX_OP: 0:HT TXOP rule , 1:PIFS TX ,2:Backoff, 3:sifs
- * BW: Channel bandwidth 20MHz or 40 MHz
+ * BW: Channel bandwidth 0:20MHz, 1:40 MHz (for legacy rates this will
+ * duplicate the frame to both channels).
* STBC: 1: STBC support MCS =0-7, 2,3 : RESERVED
+ * AMPDU: 1: this frame is eligible for AMPDU aggregation, the hw will
+ * aggregate consecutive frames with the same RA and QoS TID. If
+ * a frame A with the same RA and QoS TID but AMPDU=0 is queued
+ * directly after a frame B with AMPDU=1, frame A might still
+ * get aggregated into the AMPDU started by frame B. So, setting
+ * AMPDU to 0 does _not_ necessarily mean the frame is sent as
+ * MPDU, it can still end up in an AMPDU if the previous frame
+ * was tagged as AMPDU.
*/
#define TXWI_W0_FRAG FIELD32(0x00000001)
#define TXWI_W0_MIMO_PS FIELD32(0x00000002)
@@ -1945,6 +2027,19 @@ struct mac_iveiv_entry {
/*
* Word1
+ * ACK: 0: No Ack needed, 1: Ack needed
+ * NSEQ: 0: Don't assign hw sequence number, 1: Assign hw sequence number
+ * BW_WIN_SIZE: BA windows size of the recipient
+ * WIRELESS_CLI_ID: Client ID for WCID table access
+ * MPDU_TOTAL_BYTE_COUNT: Length of 802.11 frame
+ * PACKETID: Will be latched into the TX_STA_FIFO register once the according
+ * frame was processed. If multiple frames are aggregated together
+ * (AMPDU==1) the reported tx status will always contain the packet
+ * id of the first frame. 0: Don't report tx status for this frame.
+ * PACKETID_QUEUE: Part of PACKETID, This is the queue index (0-3)
+ * PACKETID_ENTRY: Part of PACKETID, THis is the queue entry index (1-3)
+ * This identification number is calculated by ((idx % 3) + 1).
+ * The (+1) is required to prevent PACKETID to become 0.
*/
#define TXWI_W1_ACK FIELD32(0x00000001)
#define TXWI_W1_NSEQ FIELD32(0x00000002)
@@ -1952,6 +2047,8 @@ struct mac_iveiv_entry {
#define TXWI_W1_WIRELESS_CLI_ID FIELD32(0x0000ff00)
#define TXWI_W1_MPDU_TOTAL_BYTE_COUNT FIELD32(0x0fff0000)
#define TXWI_W1_PACKETID FIELD32(0xf0000000)
+#define TXWI_W1_PACKETID_QUEUE FIELD32(0x30000000)
+#define TXWI_W1_PACKETID_ENTRY FIELD32(0xc0000000)
/*
* Word2
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index b66e0fd8f0fa..5f00e00789d8 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -1,4 +1,5 @@
/*
+ Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
Copyright (C) 2010 Ivo van Doorn <IvDoorn@gmail.com>
Copyright (C) 2009 Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Copyright (C) 2009 Gertjan van Wingerde <gwingerde@gmail.com>
@@ -254,6 +255,23 @@ void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev,
}
EXPORT_SYMBOL_GPL(rt2800_mcu_request);
+int rt2800_wait_csr_ready(struct rt2x00_dev *rt2x00dev)
+{
+ unsigned int i = 0;
+ u32 reg;
+
+ for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
+ rt2800_register_read(rt2x00dev, MAC_CSR0, &reg);
+ if (reg && reg != ~0)
+ return 0;
+ msleep(1);
+ }
+
+ ERROR(rt2x00dev, "Unstable hardware.\n");
+ return -EBUSY;
+}
+EXPORT_SYMBOL_GPL(rt2800_wait_csr_ready);
+
int rt2800_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev)
{
unsigned int i;
@@ -367,19 +385,16 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,
u32 reg;
/*
- * Wait for stable hardware.
+ * If driver doesn't wake up firmware here,
+ * rt2800_load_firmware will hang forever when interface is up again.
*/
- for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2800_register_read(rt2x00dev, MAC_CSR0, &reg);
- if (reg && reg != ~0)
- break;
- msleep(1);
- }
+ rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, 0x00000000);
- if (i == REGISTER_BUSY_COUNT) {
- ERROR(rt2x00dev, "Unstable hardware.\n");
+ /*
+ * Wait for stable hardware.
+ */
+ if (rt2800_wait_csr_ready(rt2x00dev))
return -EBUSY;
- }
if (rt2x00_is_pci(rt2x00dev))
rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000002);
@@ -427,8 +442,10 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,
}
EXPORT_SYMBOL_GPL(rt2800_load_firmware);
-void rt2800_write_txwi(__le32 *txwi, struct txentry_desc *txdesc)
+void rt2800_write_tx_data(struct queue_entry *entry,
+ struct txentry_desc *txdesc)
{
+ __le32 *txwi = rt2800_drv_get_txwi(entry);
u32 word;
/*
@@ -437,7 +454,8 @@ void rt2800_write_txwi(__le32 *txwi, struct txentry_desc *txdesc)
rt2x00_desc_read(txwi, 0, &word);
rt2x00_set_field32(&word, TXWI_W0_FRAG,
test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
- rt2x00_set_field32(&word, TXWI_W0_MIMO_PS, 0);
+ rt2x00_set_field32(&word, TXWI_W0_MIMO_PS,
+ test_bit(ENTRY_TXD_HT_MIMO_PS, &txdesc->flags));
rt2x00_set_field32(&word, TXWI_W0_CF_ACK, 0);
rt2x00_set_field32(&word, TXWI_W0_TS,
test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
@@ -465,7 +483,8 @@ void rt2800_write_txwi(__le32 *txwi, struct txentry_desc *txdesc)
txdesc->key_idx : 0xff);
rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT,
txdesc->length);
- rt2x00_set_field32(&word, TXWI_W1_PACKETID, txdesc->queue + 1);
+ rt2x00_set_field32(&word, TXWI_W1_PACKETID_QUEUE, txdesc->qid);
+ rt2x00_set_field32(&word, TXWI_W1_PACKETID_ENTRY, (entry->entry_idx % 3) + 1);
rt2x00_desc_write(txwi, 1, word);
/*
@@ -478,9 +497,9 @@ void rt2800_write_txwi(__le32 *txwi, struct txentry_desc *txdesc)
_rt2x00_desc_write(txwi, 2, 0 /* skbdesc->iv[0] */);
_rt2x00_desc_write(txwi, 3, 0 /* skbdesc->iv[1] */);
}
-EXPORT_SYMBOL_GPL(rt2800_write_txwi);
+EXPORT_SYMBOL_GPL(rt2800_write_tx_data);
-static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxwi_w2)
+static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, u32 rxwi_w2)
{
int rssi0 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI0);
int rssi1 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI1);
@@ -490,7 +509,7 @@ static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxwi_w2)
u8 offset1;
u8 offset2;
- if (rt2x00dev->rx_status.band == IEEE80211_BAND_2GHZ) {
+ if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) {
rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &eeprom);
offset0 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG_OFFSET0);
offset1 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG_OFFSET1);
@@ -569,6 +588,181 @@ void rt2800_process_rxwi(struct queue_entry *entry,
}
EXPORT_SYMBOL_GPL(rt2800_process_rxwi);
+static bool rt2800_txdone_entry_check(struct queue_entry *entry, u32 reg)
+{
+ __le32 *txwi;
+ u32 word;
+ int wcid, ack, pid;
+ int tx_wcid, tx_ack, tx_pid;
+
+ wcid = rt2x00_get_field32(reg, TX_STA_FIFO_WCID);
+ ack = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED);
+ pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE);
+
+ /*
+ * This frames has returned with an IO error,
+ * so the status report is not intended for this
+ * frame.
+ */
+ if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) {
+ rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE);
+ return false;
+ }
+
+ /*
+ * Validate if this TX status report is intended for
+ * this entry by comparing the WCID/ACK/PID fields.
+ */
+ txwi = rt2800_drv_get_txwi(entry);
+
+ rt2x00_desc_read(txwi, 1, &word);
+ tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID);
+ tx_ack = rt2x00_get_field32(word, TXWI_W1_ACK);
+ tx_pid = rt2x00_get_field32(word, TXWI_W1_PACKETID);
+
+ if ((wcid != tx_wcid) || (ack != tx_ack) || (pid != tx_pid)) {
+ WARNING(entry->queue->rt2x00dev,
+ "TX status report missed for queue %d entry %d\n",
+ entry->queue->qid, entry->entry_idx);
+ rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN);
+ return false;
+ }
+
+ return true;
+}
+
+void rt2800_txdone_entry(struct queue_entry *entry, u32 status)
+{
+ struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+ struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+ struct txdone_entry_desc txdesc;
+ u32 word;
+ u16 mcs, real_mcs;
+ int aggr, ampdu;
+ __le32 *txwi;
+
+ /*
+ * Obtain the status about this packet.
+ */
+ txdesc.flags = 0;
+ txwi = rt2800_drv_get_txwi(entry);
+ rt2x00_desc_read(txwi, 0, &word);
+
+ mcs = rt2x00_get_field32(word, TXWI_W0_MCS);
+ ampdu = rt2x00_get_field32(word, TXWI_W0_AMPDU);
+
+ real_mcs = rt2x00_get_field32(status, TX_STA_FIFO_MCS);
+ aggr = rt2x00_get_field32(status, TX_STA_FIFO_TX_AGGRE);
+
+ /*
+ * If a frame was meant to be sent as a single non-aggregated MPDU
+ * but ended up in an aggregate the used tx rate doesn't correlate
+ * with the one specified in the TXWI as the whole aggregate is sent
+ * with the same rate.
+ *
+ * For example: two frames are sent to rt2x00, the first one sets
+ * AMPDU=1 and requests MCS7 whereas the second frame sets AMDPU=0
+ * and requests MCS15. If the hw aggregates both frames into one
+ * AMDPU the tx status for both frames will contain MCS7 although
+ * the frame was sent successfully.
+ *
+ * Hence, replace the requested rate with the real tx rate to not
+ * confuse the rate control algortihm by providing clearly wrong
+ * data.
+ */
+ if (aggr == 1 && ampdu == 0 && real_mcs != mcs) {
+ skbdesc->tx_rate_idx = real_mcs;
+ mcs = real_mcs;
+ }
+
+ /*
+ * Ralink has a retry mechanism using a global fallback
+ * table. We setup this fallback table to try the immediate
+ * lower rate for all rates. In the TX_STA_FIFO, the MCS field
+ * always contains the MCS used for the last transmission, be
+ * it successful or not.
+ */
+ if (rt2x00_get_field32(status, TX_STA_FIFO_TX_SUCCESS)) {
+ /*
+ * Transmission succeeded. The number of retries is
+ * mcs - real_mcs
+ */
+ __set_bit(TXDONE_SUCCESS, &txdesc.flags);
+ txdesc.retry = ((mcs > real_mcs) ? mcs - real_mcs : 0);
+ } else {
+ /*
+ * Transmission failed. The number of retries is
+ * always 7 in this case (for a total number of 8
+ * frames sent).
+ */
+ __set_bit(TXDONE_FAILURE, &txdesc.flags);
+ txdesc.retry = rt2x00dev->long_retry;
+ }
+
+ /*
+ * the frame was retried at least once
+ * -> hw used fallback rates
+ */
+ if (txdesc.retry)
+ __set_bit(TXDONE_FALLBACK, &txdesc.flags);
+
+ rt2x00lib_txdone(entry, &txdesc);
+}
+EXPORT_SYMBOL_GPL(rt2800_txdone_entry);
+
+void rt2800_txdone(struct rt2x00_dev *rt2x00dev)
+{
+ struct data_queue *queue;
+ struct queue_entry *entry;
+ u32 reg;
+ u8 pid;
+ int i;
+
+ /*
+ * TX_STA_FIFO is a stack of X entries, hence read TX_STA_FIFO
+ * at most X times and also stop processing once the TX_STA_FIFO_VALID
+ * flag is not set anymore.
+ *
+ * The legacy drivers use X=TX_RING_SIZE but state in a comment
+ * that the TX_STA_FIFO stack has a size of 16. We stick to our
+ * tx ring size for now.
+ */
+ for (i = 0; i < TX_ENTRIES; i++) {
+ rt2800_register_read(rt2x00dev, TX_STA_FIFO, &reg);
+ if (!rt2x00_get_field32(reg, TX_STA_FIFO_VALID))
+ break;
+
+ /*
+ * Skip this entry when it contains an invalid
+ * queue identication number.
+ */
+ pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE);
+ if (pid >= QID_RX)
+ continue;
+
+ queue = rt2x00queue_get_queue(rt2x00dev, pid);
+ if (unlikely(!queue))
+ continue;
+
+ /*
+ * Inside each queue, we process each entry in a chronological
+ * order. We first check that the queue is not empty.
+ */
+ entry = NULL;
+ while (!rt2x00queue_empty(queue)) {
+ entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
+ if (rt2800_txdone_entry_check(entry, reg))
+ break;
+ }
+
+ if (!entry || rt2x00queue_empty(queue))
+ break;
+
+ rt2800_txdone_entry(entry, reg);
+ }
+}
+EXPORT_SYMBOL_GPL(rt2800_txdone);
+
void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
@@ -600,7 +794,7 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
/*
* Add the TXWI for the beacon to the skb.
*/
- rt2800_write_txwi((__le32 *)entry->skb->data, txdesc);
+ rt2800_write_tx_data(entry, txdesc);
/*
* Dump beacon to userspace through debugfs.
@@ -871,8 +1065,12 @@ int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
* 1 pairwise key is possible per AID, this means that the AID
* equals our hw_key_idx. Make sure the WCID starts _after_ the
* last possible shared key entry.
+ *
+ * Since parts of the pairwise key table might be shared with
+ * the beacon frame buffers 6 & 7 we should only write into the
+ * first 222 entries.
*/
- if (crypto->aid > (256 - 32))
+ if (crypto->aid > (222 - 32))
return -ENOSPC;
key->hw_key_idx = 32 + crypto->aid;
@@ -975,19 +1173,23 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
}
if (flags & CONFIG_UPDATE_MAC) {
- reg = le32_to_cpu(conf->mac[1]);
- rt2x00_set_field32(&reg, MAC_ADDR_DW1_UNICAST_TO_ME_MASK, 0xff);
- conf->mac[1] = cpu_to_le32(reg);
+ if (!is_zero_ether_addr((const u8 *)conf->mac)) {
+ reg = le32_to_cpu(conf->mac[1]);
+ rt2x00_set_field32(&reg, MAC_ADDR_DW1_UNICAST_TO_ME_MASK, 0xff);
+ conf->mac[1] = cpu_to_le32(reg);
+ }
rt2800_register_multiwrite(rt2x00dev, MAC_ADDR_DW0,
conf->mac, sizeof(conf->mac));
}
if (flags & CONFIG_UPDATE_BSSID) {
- reg = le32_to_cpu(conf->bssid[1]);
- rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_ID_MASK, 3);
- rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_BCN_NUM, 7);
- conf->bssid[1] = cpu_to_le32(reg);
+ if (!is_zero_ether_addr((const u8 *)conf->bssid)) {
+ reg = le32_to_cpu(conf->bssid[1]);
+ rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_ID_MASK, 3);
+ rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_BCN_NUM, 7);
+ conf->bssid[1] = cpu_to_le32(reg);
+ }
rt2800_register_multiwrite(rt2x00dev, MAC_BSSID_DW0,
conf->bssid, sizeof(conf->bssid));
@@ -995,38 +1197,149 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
}
EXPORT_SYMBOL_GPL(rt2800_config_intf);
-void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp)
+static void rt2800_config_ht_opmode(struct rt2x00_dev *rt2x00dev,
+ struct rt2x00lib_erp *erp)
{
+ bool any_sta_nongf = !!(erp->ht_opmode &
+ IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
+ u8 protection = erp->ht_opmode & IEEE80211_HT_OP_MODE_PROTECTION;
+ u8 mm20_mode, mm40_mode, gf20_mode, gf40_mode;
+ u16 mm20_rate, mm40_rate, gf20_rate, gf40_rate;
u32 reg;
- rt2800_register_read(rt2x00dev, AUTO_RSP_CFG, &reg);
- rt2x00_set_field32(&reg, AUTO_RSP_CFG_BAC_ACK_POLICY,
- !!erp->short_preamble);
- rt2x00_set_field32(&reg, AUTO_RSP_CFG_AR_PREAMBLE,
- !!erp->short_preamble);
- rt2800_register_write(rt2x00dev, AUTO_RSP_CFG, reg);
+ /* default protection rate for HT20: OFDM 24M */
+ mm20_rate = gf20_rate = 0x4004;
- rt2800_register_read(rt2x00dev, OFDM_PROT_CFG, &reg);
- rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_CTRL,
- erp->cts_protection ? 2 : 0);
- rt2800_register_write(rt2x00dev, OFDM_PROT_CFG, reg);
+ /* default protection rate for HT40: duplicate OFDM 24M */
+ mm40_rate = gf40_rate = 0x4084;
- rt2800_register_write(rt2x00dev, LEGACY_BASIC_RATE,
- erp->basic_rates);
- rt2800_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003);
+ switch (protection) {
+ case IEEE80211_HT_OP_MODE_PROTECTION_NONE:
+ /*
+ * All STAs in this BSS are HT20/40 but there might be
+ * STAs not supporting greenfield mode.
+ * => Disable protection for HT transmissions.
+ */
+ mm20_mode = mm40_mode = gf20_mode = gf40_mode = 0;
- rt2800_register_read(rt2x00dev, BKOFF_SLOT_CFG, &reg);
- rt2x00_set_field32(&reg, BKOFF_SLOT_CFG_SLOT_TIME, erp->slot_time);
- rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg);
+ break;
+ case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ:
+ /*
+ * All STAs in this BSS are HT20 or HT20/40 but there
+ * might be STAs not supporting greenfield mode.
+ * => Protect all HT40 transmissions.
+ */
+ mm20_mode = gf20_mode = 0;
+ mm40_mode = gf40_mode = 2;
- rt2800_register_read(rt2x00dev, XIFS_TIME_CFG, &reg);
- rt2x00_set_field32(&reg, XIFS_TIME_CFG_EIFS, erp->eifs);
- rt2800_register_write(rt2x00dev, XIFS_TIME_CFG, reg);
+ break;
+ case IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER:
+ /*
+ * Nonmember protection:
+ * According to 802.11n we _should_ protect all
+ * HT transmissions (but we don't have to).
+ *
+ * But if cts_protection is enabled we _shall_ protect
+ * all HT transmissions using a CCK rate.
+ *
+ * And if any station is non GF we _shall_ protect
+ * GF transmissions.
+ *
+ * We decide to protect everything
+ * -> fall through to mixed mode.
+ */
+ case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED:
+ /*
+ * Legacy STAs are present
+ * => Protect all HT transmissions.
+ */
+ mm20_mode = mm40_mode = gf20_mode = gf40_mode = 2;
- rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
- rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_INTERVAL,
- erp->beacon_int * 16);
- rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+ /*
+ * If erp protection is needed we have to protect HT
+ * transmissions with CCK 11M long preamble.
+ */
+ if (erp->cts_protection) {
+ /* don't duplicate RTS/CTS in CCK mode */
+ mm20_rate = mm40_rate = 0x0003;
+ gf20_rate = gf40_rate = 0x0003;
+ }
+ break;
+ };
+
+ /* check for STAs not supporting greenfield mode */
+ if (any_sta_nongf)
+ gf20_mode = gf40_mode = 2;
+
+ /* Update HT protection config */
+ rt2800_register_read(rt2x00dev, MM20_PROT_CFG, &reg);
+ rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_RATE, mm20_rate);
+ rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_CTRL, mm20_mode);
+ rt2800_register_write(rt2x00dev, MM20_PROT_CFG, reg);
+
+ rt2800_register_read(rt2x00dev, MM40_PROT_CFG, &reg);
+ rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_RATE, mm40_rate);
+ rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_CTRL, mm40_mode);
+ rt2800_register_write(rt2x00dev, MM40_PROT_CFG, reg);
+
+ rt2800_register_read(rt2x00dev, GF20_PROT_CFG, &reg);
+ rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_RATE, gf20_rate);
+ rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_CTRL, gf20_mode);
+ rt2800_register_write(rt2x00dev, GF20_PROT_CFG, reg);
+
+ rt2800_register_read(rt2x00dev, GF40_PROT_CFG, &reg);
+ rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_RATE, gf40_rate);
+ rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_CTRL, gf40_mode);
+ rt2800_register_write(rt2x00dev, GF40_PROT_CFG, reg);
+}
+
+void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp,
+ u32 changed)
+{
+ u32 reg;
+
+ if (changed & BSS_CHANGED_ERP_PREAMBLE) {
+ rt2800_register_read(rt2x00dev, AUTO_RSP_CFG, &reg);
+ rt2x00_set_field32(&reg, AUTO_RSP_CFG_BAC_ACK_POLICY,
+ !!erp->short_preamble);
+ rt2x00_set_field32(&reg, AUTO_RSP_CFG_AR_PREAMBLE,
+ !!erp->short_preamble);
+ rt2800_register_write(rt2x00dev, AUTO_RSP_CFG, reg);
+ }
+
+ if (changed & BSS_CHANGED_ERP_CTS_PROT) {
+ rt2800_register_read(rt2x00dev, OFDM_PROT_CFG, &reg);
+ rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_CTRL,
+ erp->cts_protection ? 2 : 0);
+ rt2800_register_write(rt2x00dev, OFDM_PROT_CFG, reg);
+ }
+
+ if (changed & BSS_CHANGED_BASIC_RATES) {
+ rt2800_register_write(rt2x00dev, LEGACY_BASIC_RATE,
+ erp->basic_rates);
+ rt2800_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003);
+ }
+
+ if (changed & BSS_CHANGED_ERP_SLOT) {
+ rt2800_register_read(rt2x00dev, BKOFF_SLOT_CFG, &reg);
+ rt2x00_set_field32(&reg, BKOFF_SLOT_CFG_SLOT_TIME,
+ erp->slot_time);
+ rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg);
+
+ rt2800_register_read(rt2x00dev, XIFS_TIME_CFG, &reg);
+ rt2x00_set_field32(&reg, XIFS_TIME_CFG_EIFS, erp->eifs);
+ rt2800_register_write(rt2x00dev, XIFS_TIME_CFG, reg);
+ }
+
+ if (changed & BSS_CHANGED_BEACON_INT) {
+ rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+ rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_INTERVAL,
+ erp->beacon_int * 16);
+ rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+ }
+
+ if (changed & BSS_CHANGED_HT)
+ rt2800_config_ht_opmode(rt2x00dev, erp);
}
EXPORT_SYMBOL_GPL(rt2800_config_erp);
@@ -1120,27 +1433,23 @@ static void rt2800_config_channel_rf2xxx(struct rt2x00_dev *rt2x00dev,
* double meaning, and we should set a 7DBm boost flag.
*/
rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A_7DBM_BOOST,
- (info->tx_power1 >= 0));
+ (info->default_power1 >= 0));
- if (info->tx_power1 < 0)
- info->tx_power1 += 7;
+ if (info->default_power1 < 0)
+ info->default_power1 += 7;
- rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A,
- TXPOWER_A_TO_DEV(info->tx_power1));
+ rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A, info->default_power1);
rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A_7DBM_BOOST,
- (info->tx_power2 >= 0));
+ (info->default_power2 >= 0));
- if (info->tx_power2 < 0)
- info->tx_power2 += 7;
+ if (info->default_power2 < 0)
+ info->default_power2 += 7;
- rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A,
- TXPOWER_A_TO_DEV(info->tx_power2));
+ rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A, info->default_power2);
} else {
- rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_G,
- TXPOWER_G_TO_DEV(info->tx_power1));
- rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_G,
- TXPOWER_G_TO_DEV(info->tx_power2));
+ rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_G, info->default_power1);
+ rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_G, info->default_power2);
}
rt2x00_set_field32(&rf->rf4, RF4_HT40, conf_is_ht40(conf));
@@ -1180,13 +1489,11 @@ static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev,
rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
rt2800_rfcsr_read(rt2x00dev, 12, &rfcsr);
- rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER,
- TXPOWER_G_TO_DEV(info->tx_power1));
+ rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER, info->default_power1);
rt2800_rfcsr_write(rt2x00dev, 12, rfcsr);
rt2800_rfcsr_read(rt2x00dev, 13, &rfcsr);
- rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER,
- TXPOWER_G_TO_DEV(info->tx_power2));
+ rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER, info->default_power2);
rt2800_rfcsr_write(rt2x00dev, 13, rfcsr);
rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr);
@@ -1210,10 +1517,19 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
unsigned int tx_pin;
u8 bbp;
+ if (rf->channel <= 14) {
+ info->default_power1 = TXPOWER_G_TO_DEV(info->default_power1);
+ info->default_power2 = TXPOWER_G_TO_DEV(info->default_power2);
+ } else {
+ info->default_power1 = TXPOWER_A_TO_DEV(info->default_power1);
+ info->default_power2 = TXPOWER_A_TO_DEV(info->default_power2);
+ }
+
if (rt2x00_rf(rt2x00dev, RF2020) ||
rt2x00_rf(rt2x00dev, RF3020) ||
rt2x00_rf(rt2x00dev, RF3021) ||
- rt2x00_rf(rt2x00dev, RF3022))
+ rt2x00_rf(rt2x00dev, RF3022) ||
+ rt2x00_rf(rt2x00dev, RF3052))
rt2800_config_channel_rf3xxx(rt2x00dev, conf, rf, info);
else
rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info);
@@ -1536,7 +1852,7 @@ EXPORT_SYMBOL_GPL(rt2800_link_tuner);
/*
* Initialization functions.
*/
-int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
+static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
u16 eeprom;
@@ -1728,8 +2044,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
rt2800_register_read(rt2x00dev, MM40_PROT_CFG, &reg);
rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_RATE, 0x4084);
- rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_CTRL,
- !rt2x00_is_usb(rt2x00dev));
+ rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_CTRL, 0);
rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_NAV, 1);
rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_CCK, 1);
rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
@@ -1886,6 +2201,14 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
rt2800_register_write(rt2x00dev, LG_FBK_CFG1, reg);
/*
+ * Do not force the BA window size, we use the TXWI to set it
+ */
+ rt2800_register_read(rt2x00dev, AMPDU_BA_WINSIZE, &reg);
+ rt2x00_set_field32(&reg, AMPDU_BA_WINSIZE_FORCE_WINSIZE_ENABLE, 0);
+ rt2x00_set_field32(&reg, AMPDU_BA_WINSIZE_FORCE_WINSIZE, 0);
+ rt2800_register_write(rt2x00dev, AMPDU_BA_WINSIZE, reg);
+
+ /*
* We must clear the error counters.
* These registers are cleared on read,
* so we may pass a useless variable to store the value.
@@ -1906,7 +2229,6 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
return 0;
}
-EXPORT_SYMBOL_GPL(rt2800_init_registers);
static int rt2800_wait_bbp_rf_ready(struct rt2x00_dev *rt2x00dev)
{
@@ -1949,7 +2271,7 @@ static int rt2800_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
return -EACCES;
}
-int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
+static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
{
unsigned int i;
u16 eeprom;
@@ -2044,7 +2366,6 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
return 0;
}
-EXPORT_SYMBOL_GPL(rt2800_init_bbp);
static u8 rt2800_init_rx_filter(struct rt2x00_dev *rt2x00dev,
bool bw40, u8 rfcsr24, u8 filter_target)
@@ -2106,7 +2427,7 @@ static u8 rt2800_init_rx_filter(struct rt2x00_dev *rt2x00dev,
return rfcsr24;
}
-int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
+static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
{
u8 rfcsr;
u8 bbp;
@@ -2360,7 +2681,100 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
return 0;
}
-EXPORT_SYMBOL_GPL(rt2800_init_rfcsr);
+
+int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev)
+{
+ u32 reg;
+ u16 word;
+
+ /*
+ * Initialize all registers.
+ */
+ if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev) ||
+ rt2800_init_registers(rt2x00dev) ||
+ rt2800_init_bbp(rt2x00dev) ||
+ rt2800_init_rfcsr(rt2x00dev)))
+ return -EIO;
+
+ /*
+ * Send signal to firmware during boot time.
+ */
+ rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0);
+
+ if (rt2x00_is_usb(rt2x00dev) &&
+ (rt2x00_rt(rt2x00dev, RT3070) ||
+ rt2x00_rt(rt2x00dev, RT3071) ||
+ rt2x00_rt(rt2x00dev, RT3572))) {
+ udelay(200);
+ rt2800_mcu_request(rt2x00dev, MCU_CURRENT, 0, 0, 0);
+ udelay(10);
+ }
+
+ /*
+ * Enable RX.
+ */
+ rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+ rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_TX, 1);
+ rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 0);
+ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+
+ udelay(50);
+
+ rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
+ rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 1);
+ rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 1);
+ rt2x00_set_field32(&reg, WPDMA_GLO_CFG_WP_DMA_BURST_SIZE, 2);
+ rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1);
+ rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
+
+ rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+ rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_TX, 1);
+ rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 1);
+ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+
+ /*
+ * Initialize LED control
+ */
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_LED1, &word);
+ rt2800_mcu_request(rt2x00dev, MCU_LED_1, 0xff,
+ word & 0xff, (word >> 8) & 0xff);
+
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_LED2, &word);
+ rt2800_mcu_request(rt2x00dev, MCU_LED_2, 0xff,
+ word & 0xff, (word >> 8) & 0xff);
+
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_LED3, &word);
+ rt2800_mcu_request(rt2x00dev, MCU_LED_3, 0xff,
+ word & 0xff, (word >> 8) & 0xff);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rt2800_enable_radio);
+
+void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev)
+{
+ u32 reg;
+
+ rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
+ rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0);
+ rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_DMA_BUSY, 0);
+ rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0);
+ rt2x00_set_field32(&reg, WPDMA_GLO_CFG_RX_DMA_BUSY, 0);
+ rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1);
+ rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
+
+ /* Wait for DMA, ignore error */
+ rt2800_wait_wpdma_ready(rt2x00dev);
+
+ rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+ rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_TX, 0);
+ rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 0);
+ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+
+ rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0);
+ rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0);
+}
+EXPORT_SYMBOL_GPL(rt2800_disable_radio);
int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev)
{
@@ -2516,6 +2930,13 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
default_lna_gain);
rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word);
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_MAX_TX_POWER, &word);
+ if (rt2x00_get_field16(word, EEPROM_MAX_TX_POWER_24GHZ) == 0xff)
+ rt2x00_set_field16(&word, EEPROM_MAX_TX_POWER_24GHZ, MAX_G_TXPOWER);
+ if (rt2x00_get_field16(word, EEPROM_MAX_TX_POWER_5GHZ) == 0xff)
+ rt2x00_set_field16(&word, EEPROM_MAX_TX_POWER_5GHZ, MAX_A_TXPOWER);
+ rt2x00_eeprom_write(rt2x00dev, EEPROM_MAX_TX_POWER, word);
+
return 0;
}
EXPORT_SYMBOL_GPL(rt2800_validate_eeprom);
@@ -2755,9 +3176,10 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
{
struct hw_mode_spec *spec = &rt2x00dev->spec;
struct channel_info *info;
- char *tx_power1;
- char *tx_power2;
+ char *default_power1;
+ char *default_power2;
unsigned int i;
+ unsigned short max_power;
u16 eeprom;
/*
@@ -2770,11 +3192,20 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
* Initialize all hw fields.
*/
rt2x00dev->hw->flags =
- IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
IEEE80211_HW_SIGNAL_DBM |
IEEE80211_HW_SUPPORTS_PS |
IEEE80211_HW_PS_NULLFUNC_STACK |
IEEE80211_HW_AMPDU_AGGREGATION;
+ /*
+ * Don't set IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING for USB devices
+ * unless we are capable of sending the buffered frames out after the
+ * DTIM transmission using rt2x00lib_beacondone. This will send out
+ * multicast and broadcast traffic immediately instead of buffering it
+ * infinitly and thus dropping it after some time.
+ */
+ if (!rt2x00_is_usb(rt2x00dev))
+ rt2x00dev->hw->flags |=
+ IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;
SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
@@ -2785,12 +3216,13 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
* As rt2800 has a global fallback table we cannot specify
* more then one tx rate per frame but since the hw will
* try several rates (based on the fallback table) we should
- * still initialize max_rates to the maximum number of rates
+ * initialize max_report_rates to the maximum number of rates
* we are going to try. Otherwise mac80211 will truncate our
* reported tx rates and the rc algortihm will end up with
* incorrect data.
*/
- rt2x00dev->hw->max_rates = 7;
+ rt2x00dev->hw->max_rates = 1;
+ rt2x00dev->hw->max_report_rates = 7;
rt2x00dev->hw->max_rate_tries = 1;
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
@@ -2865,27 +3297,32 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
/*
* Create channel information array
*/
- info = kzalloc(spec->num_channels * sizeof(*info), GFP_KERNEL);
+ info = kcalloc(spec->num_channels, sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
spec->channels_info = info;
- tx_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1);
- tx_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG2);
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_MAX_TX_POWER, &eeprom);
+ max_power = rt2x00_get_field16(eeprom, EEPROM_MAX_TX_POWER_24GHZ);
+ default_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1);
+ default_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG2);
for (i = 0; i < 14; i++) {
- info[i].tx_power1 = TXPOWER_G_FROM_DEV(tx_power1[i]);
- info[i].tx_power2 = TXPOWER_G_FROM_DEV(tx_power2[i]);
+ info[i].max_power = max_power;
+ info[i].default_power1 = TXPOWER_G_FROM_DEV(default_power1[i]);
+ info[i].default_power2 = TXPOWER_G_FROM_DEV(default_power2[i]);
}
if (spec->num_channels > 14) {
- tx_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A1);
- tx_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A2);
+ max_power = rt2x00_get_field16(eeprom, EEPROM_MAX_TX_POWER_5GHZ);
+ default_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A1);
+ default_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A2);
for (i = 14; i < spec->num_channels; i++) {
- info[i].tx_power1 = TXPOWER_A_FROM_DEV(tx_power1[i]);
- info[i].tx_power2 = TXPOWER_A_FROM_DEV(tx_power2[i]);
+ info[i].max_power = max_power;
+ info[i].default_power1 = TXPOWER_A_FROM_DEV(default_power1[i]);
+ info[i].default_power2 = TXPOWER_A_FROM_DEV(default_power2[i]);
}
}
@@ -3042,8 +3479,12 @@ int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
switch (action) {
case IEEE80211_AMPDU_RX_START:
case IEEE80211_AMPDU_RX_STOP:
- /* we don't support RX aggregation yet */
- ret = -ENOTSUPP;
+ /*
+ * The hw itself takes care of setting up BlockAck mechanisms.
+ * So, we only have to allow mac80211 to nagotiate a BlockAck
+ * agreement. Once that is done, the hw will BlockAck incoming
+ * AMPDUs without further setup.
+ */
break;
case IEEE80211_AMPDU_TX_START:
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h
index 091641e3c5e2..81cbc92e7857 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/rt2x00/rt2800lib.h
@@ -1,4 +1,6 @@
/*
+ Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
+ Copyright (C) 2010 Ivo van Doorn <IvDoorn@gmail.com>
Copyright (C) 2009 Bartlomiej Zolnierkiewicz
This program is free software; you can redistribute it and/or modify
@@ -44,6 +46,7 @@ struct rt2800_ops {
int (*drv_write_firmware)(struct rt2x00_dev *rt2x00dev,
const u8 *data, const size_t len);
int (*drv_init_registers)(struct rt2x00_dev *rt2x00dev);
+ __le32 *(*drv_get_txwi)(struct queue_entry *entry);
};
static inline void rt2800_register_read(struct rt2x00_dev *rt2x00dev,
@@ -126,18 +129,32 @@ static inline int rt2800_drv_init_registers(struct rt2x00_dev *rt2x00dev)
return rt2800ops->drv_init_registers(rt2x00dev);
}
+static inline __le32 *rt2800_drv_get_txwi(struct queue_entry *entry)
+{
+ const struct rt2800_ops *rt2800ops = entry->queue->rt2x00dev->ops->drv;
+
+ return rt2800ops->drv_get_txwi(entry);
+}
+
void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev,
const u8 command, const u8 token,
const u8 arg0, const u8 arg1);
+int rt2800_wait_csr_ready(struct rt2x00_dev *rt2x00dev);
+int rt2800_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev);
+
int rt2800_check_firmware(struct rt2x00_dev *rt2x00dev,
const u8 *data, const size_t len);
int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,
const u8 *data, const size_t len);
-void rt2800_write_txwi(__le32 *txwi, struct txentry_desc *txdesc);
+void rt2800_write_tx_data(struct queue_entry *entry,
+ struct txentry_desc *txdesc);
void rt2800_process_rxwi(struct queue_entry *entry, struct rxdone_entry_desc *txdesc);
+void rt2800_txdone(struct rt2x00_dev *rt2x00dev);
+void rt2800_txdone_entry(struct queue_entry *entry, u32 status);
+
void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc);
extern const struct rt2x00debug rt2800_rt2x00debug;
@@ -153,7 +170,8 @@ void rt2800_config_filter(struct rt2x00_dev *rt2x00dev,
const unsigned int filter_flags);
void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
struct rt2x00intf_conf *conf, const unsigned int flags);
-void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp);
+void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp,
+ u32 changed);
void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant);
void rt2800_config(struct rt2x00_dev *rt2x00dev,
struct rt2x00lib_conf *libconf,
@@ -163,10 +181,8 @@ void rt2800_reset_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual);
void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual,
const u32 count);
-int rt2800_init_registers(struct rt2x00_dev *rt2x00dev);
-int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev);
-int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev);
-int rt2800_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev);
+int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev);
+void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev);
int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev);
void rt2800_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev);
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index 39b3846fa340..b26739535986 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2009 Ivo van Doorn <IvDoorn@gmail.com>
+ Copyright (C) 2009 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com>
Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com>
@@ -196,8 +196,6 @@ static int rt2800pci_write_firmware(struct rt2x00_dev *rt2x00dev,
{
u32 reg;
- rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, 0x00000000);
-
/*
* enable Host program ram write selection
*/
@@ -243,6 +241,7 @@ static void rt2800pci_clear_entry(struct queue_entry *entry)
{
struct queue_entry_priv_pci *entry_priv = entry->priv_data;
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+ struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
u32 word;
if (entry->queue->qid == QID_RX) {
@@ -253,6 +252,13 @@ static void rt2800pci_clear_entry(struct queue_entry *entry)
rt2x00_desc_read(entry_priv->desc, 1, &word);
rt2x00_set_field32(&word, RXD_W1_DMA_DONE, 0);
rt2x00_desc_write(entry_priv->desc, 1, word);
+
+ /*
+ * Set RX IDX in register to inform hardware that we have
+ * handled this entry and it is available for reuse again.
+ */
+ rt2800_register_write(rt2x00dev, RX_CRX_IDX,
+ entry->entry_idx);
} else {
rt2x00_desc_read(entry_priv->desc, 1, &word);
rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 1);
@@ -344,24 +350,24 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
}
rt2800_register_read(rt2x00dev, INT_MASK_CSR, &reg);
- rt2x00_set_field32(&reg, INT_MASK_CSR_RXDELAYINT, mask);
- rt2x00_set_field32(&reg, INT_MASK_CSR_TXDELAYINT, mask);
+ rt2x00_set_field32(&reg, INT_MASK_CSR_RXDELAYINT, 0);
+ rt2x00_set_field32(&reg, INT_MASK_CSR_TXDELAYINT, 0);
rt2x00_set_field32(&reg, INT_MASK_CSR_RX_DONE, mask);
- rt2x00_set_field32(&reg, INT_MASK_CSR_AC0_DMA_DONE, mask);
- rt2x00_set_field32(&reg, INT_MASK_CSR_AC1_DMA_DONE, mask);
- rt2x00_set_field32(&reg, INT_MASK_CSR_AC2_DMA_DONE, mask);
- rt2x00_set_field32(&reg, INT_MASK_CSR_AC3_DMA_DONE, mask);
- rt2x00_set_field32(&reg, INT_MASK_CSR_HCCA_DMA_DONE, mask);
- rt2x00_set_field32(&reg, INT_MASK_CSR_MGMT_DMA_DONE, mask);
- rt2x00_set_field32(&reg, INT_MASK_CSR_MCU_COMMAND, mask);
- rt2x00_set_field32(&reg, INT_MASK_CSR_RXTX_COHERENT, mask);
+ rt2x00_set_field32(&reg, INT_MASK_CSR_AC0_DMA_DONE, 0);
+ rt2x00_set_field32(&reg, INT_MASK_CSR_AC1_DMA_DONE, 0);
+ rt2x00_set_field32(&reg, INT_MASK_CSR_AC2_DMA_DONE, 0);
+ rt2x00_set_field32(&reg, INT_MASK_CSR_AC3_DMA_DONE, 0);
+ rt2x00_set_field32(&reg, INT_MASK_CSR_HCCA_DMA_DONE, 0);
+ rt2x00_set_field32(&reg, INT_MASK_CSR_MGMT_DMA_DONE, 0);
+ rt2x00_set_field32(&reg, INT_MASK_CSR_MCU_COMMAND, 0);
+ rt2x00_set_field32(&reg, INT_MASK_CSR_RXTX_COHERENT, 0);
rt2x00_set_field32(&reg, INT_MASK_CSR_TBTT, mask);
rt2x00_set_field32(&reg, INT_MASK_CSR_PRE_TBTT, mask);
rt2x00_set_field32(&reg, INT_MASK_CSR_TX_FIFO_STATUS, mask);
rt2x00_set_field32(&reg, INT_MASK_CSR_AUTO_WAKEUP, mask);
- rt2x00_set_field32(&reg, INT_MASK_CSR_GPTIMER, mask);
- rt2x00_set_field32(&reg, INT_MASK_CSR_RX_COHERENT, mask);
- rt2x00_set_field32(&reg, INT_MASK_CSR_TX_COHERENT, mask);
+ rt2x00_set_field32(&reg, INT_MASK_CSR_GPTIMER, 0);
+ rt2x00_set_field32(&reg, INT_MASK_CSR_RX_COHERENT, 0);
+ rt2x00_set_field32(&reg, INT_MASK_CSR_TX_COHERENT, 0);
rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg);
}
@@ -399,78 +405,18 @@ static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev)
static int rt2800pci_enable_radio(struct rt2x00_dev *rt2x00dev)
{
- u32 reg;
- u16 word;
-
- /*
- * Initialize all registers.
- */
if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev) ||
- rt2800pci_init_queues(rt2x00dev) ||
- rt2800_init_registers(rt2x00dev) ||
- rt2800_wait_wpdma_ready(rt2x00dev) ||
- rt2800_init_bbp(rt2x00dev) ||
- rt2800_init_rfcsr(rt2x00dev)))
+ rt2800pci_init_queues(rt2x00dev)))
return -EIO;
- /*
- * Send signal to firmware during boot time.
- */
- rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0);
-
- /*
- * Enable RX.
- */
- rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
- rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_TX, 1);
- rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 0);
- rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
-
- rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
- rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 1);
- rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 1);
- rt2x00_set_field32(&reg, WPDMA_GLO_CFG_WP_DMA_BURST_SIZE, 2);
- rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1);
- rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
-
- rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
- rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_TX, 1);
- rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 1);
- rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
-
- /*
- * Initialize LED control
- */
- rt2x00_eeprom_read(rt2x00dev, EEPROM_LED1, &word);
- rt2800_mcu_request(rt2x00dev, MCU_LED_1, 0xff,
- word & 0xff, (word >> 8) & 0xff);
-
- rt2x00_eeprom_read(rt2x00dev, EEPROM_LED2, &word);
- rt2800_mcu_request(rt2x00dev, MCU_LED_2, 0xff,
- word & 0xff, (word >> 8) & 0xff);
-
- rt2x00_eeprom_read(rt2x00dev, EEPROM_LED3, &word);
- rt2800_mcu_request(rt2x00dev, MCU_LED_3, 0xff,
- word & 0xff, (word >> 8) & 0xff);
-
- return 0;
+ return rt2800_enable_radio(rt2x00dev);
}
static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
- rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
- rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0);
- rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_DMA_BUSY, 0);
- rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0);
- rt2x00_set_field32(&reg, WPDMA_GLO_CFG_RX_DMA_BUSY, 0);
- rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1);
- rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
-
- rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0);
- rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0);
- rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0);
+ rt2800_disable_radio(rt2x00dev);
rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001280);
@@ -486,9 +432,6 @@ static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev)
rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f);
rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00);
-
- /* Wait for DMA, ignore error */
- rt2800_wait_wpdma_ready(rt2x00dev);
}
static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev,
@@ -566,21 +509,16 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev,
/*
* TX descriptor initialization
*/
-static void rt2800pci_write_tx_data(struct queue_entry* entry,
- struct txentry_desc *txdesc)
+static __le32 *rt2800pci_get_txwi(struct queue_entry *entry)
{
- __le32 *txwi = (__le32 *) entry->skb->data;
-
- rt2800_write_txwi(txwi, txdesc);
+ return (__le32 *) entry->skb->data;
}
-
-static void rt2800pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
- struct sk_buff *skb,
+static void rt2800pci_write_tx_desc(struct queue_entry *entry,
struct txentry_desc *txdesc)
{
- struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
- struct queue_entry_priv_pci *entry_priv = skbdesc->entry->priv_data;
+ struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+ struct queue_entry_priv_pci *entry_priv = entry->priv_data;
__le32 *txd = entry_priv->desc;
u32 word;
@@ -600,7 +538,7 @@ static void rt2800pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
rt2x00_desc_write(txd, 0, word);
rt2x00_desc_read(txd, 1, &word);
- rt2x00_set_field32(&word, TXD_W1_SD_LEN1, skb->len);
+ rt2x00_set_field32(&word, TXD_W1_SD_LEN1, entry->skb->len);
rt2x00_set_field32(&word, TXD_W1_LAST_SEC1,
!test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
rt2x00_set_field32(&word, TXD_W1_BURST,
@@ -631,41 +569,35 @@ static void rt2800pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
/*
* TX data initialization
*/
-static void rt2800pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
- const enum data_queue_qid queue_idx)
+static void rt2800pci_kick_tx_queue(struct data_queue *queue)
{
- struct data_queue *queue;
- unsigned int idx, qidx = 0;
+ struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
+ struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX);
+ unsigned int qidx;
- if (queue_idx > QID_HCCA && queue_idx != QID_MGMT)
- return;
-
- queue = rt2x00queue_get_queue(rt2x00dev, queue_idx);
- idx = queue->index[Q_INDEX];
-
- if (queue_idx == QID_MGMT)
+ if (queue->qid == QID_MGMT)
qidx = 5;
else
- qidx = queue_idx;
+ qidx = queue->qid;
- rt2800_register_write(rt2x00dev, TX_CTX_IDX(qidx), idx);
+ rt2800_register_write(rt2x00dev, TX_CTX_IDX(qidx), entry->entry_idx);
}
-static void rt2800pci_kill_tx_queue(struct rt2x00_dev *rt2x00dev,
- const enum data_queue_qid qid)
+static void rt2800pci_kill_tx_queue(struct data_queue *queue)
{
+ struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
u32 reg;
- if (qid == QID_BEACON) {
+ if (queue->qid == QID_BEACON) {
rt2800_register_write(rt2x00dev, BCN_TIME_CFG, 0);
return;
}
rt2800_register_read(rt2x00dev, WPDMA_RST_IDX, &reg);
- rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX0, (qid == QID_AC_BE));
- rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX1, (qid == QID_AC_BK));
- rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX2, (qid == QID_AC_VI));
- rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX3, (qid == QID_AC_VO));
+ rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX0, (queue->qid == QID_AC_BE));
+ rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX1, (queue->qid == QID_AC_BK));
+ rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX2, (queue->qid == QID_AC_VI));
+ rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX3, (queue->qid == QID_AC_VO));
rt2800_register_write(rt2x00dev, WPDMA_RST_IDX, reg);
}
@@ -675,7 +607,6 @@ static void rt2800pci_kill_tx_queue(struct rt2x00_dev *rt2x00dev,
static void rt2800pci_fill_rxdone(struct queue_entry *entry,
struct rxdone_entry_desc *rxdesc)
{
- struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct queue_entry_priv_pci *entry_priv = entry->priv_data;
__le32 *rxd = entry_priv->desc;
u32 word;
@@ -717,127 +648,74 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry,
* Process the RXWI structure that is at the start of the buffer.
*/
rt2800_process_rxwi(entry, rxdesc);
-
- /*
- * Set RX IDX in register to inform hardware that we have handled
- * this entry and it is available for reuse again.
- */
- rt2800_register_write(rt2x00dev, RX_CRX_IDX, entry->entry_idx);
}
/*
* Interrupt functions.
*/
+static void rt2800pci_wakeup(struct rt2x00_dev *rt2x00dev)
+{
+ struct ieee80211_conf conf = { .flags = 0 };
+ struct rt2x00lib_conf libconf = { .conf = &conf };
+
+ rt2800_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS);
+}
+
static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
{
struct data_queue *queue;
struct queue_entry *entry;
- __le32 *txwi;
- struct txdone_entry_desc txdesc;
- u32 word;
- u32 reg;
- int wcid, ack, pid, tx_wcid, tx_ack, tx_pid;
- u16 mcs, real_mcs;
- int i;
-
- /*
- * TX_STA_FIFO is a stack of X entries, hence read TX_STA_FIFO
- * at most X times and also stop processing once the TX_STA_FIFO_VALID
- * flag is not set anymore.
- *
- * The legacy drivers use X=TX_RING_SIZE but state in a comment
- * that the TX_STA_FIFO stack has a size of 16. We stick to our
- * tx ring size for now.
- */
- for (i = 0; i < TX_ENTRIES; i++) {
- rt2800_register_read(rt2x00dev, TX_STA_FIFO, &reg);
- if (!rt2x00_get_field32(reg, TX_STA_FIFO_VALID))
+ u32 status;
+ u8 qid;
+
+ while (!kfifo_is_empty(&rt2x00dev->txstatus_fifo)) {
+ /* Now remove the tx status from the FIFO */
+ if (kfifo_out(&rt2x00dev->txstatus_fifo, &status,
+ sizeof(status)) != sizeof(status)) {
+ WARN_ON(1);
break;
+ }
- wcid = rt2x00_get_field32(reg, TX_STA_FIFO_WCID);
- ack = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED);
- pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE);
-
- /*
- * Skip this entry when it contains an invalid
- * queue identication number.
- */
- if (pid <= 0 || pid > QID_RX)
- continue;
-
- queue = rt2x00queue_get_queue(rt2x00dev, pid - 1);
- if (unlikely(!queue))
- continue;
-
- /*
- * Inside each queue, we process each entry in a chronological
- * order. We first check that the queue is not empty.
- */
- if (rt2x00queue_empty(queue))
- continue;
- entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
-
- /* Check if we got a match by looking at WCID/ACK/PID
- * fields */
- txwi = (__le32 *) entry->skb->data;
-
- rt2x00_desc_read(txwi, 1, &word);
- tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID);
- tx_ack = rt2x00_get_field32(word, TXWI_W1_ACK);
- tx_pid = rt2x00_get_field32(word, TXWI_W1_PACKETID);
-
- if ((wcid != tx_wcid) || (ack != tx_ack) || (pid != tx_pid))
- WARNING(rt2x00dev, "invalid TX_STA_FIFO content\n");
-
- /*
- * Obtain the status about this packet.
- */
- txdesc.flags = 0;
- rt2x00_desc_read(txwi, 0, &word);
- mcs = rt2x00_get_field32(word, TXWI_W0_MCS);
- real_mcs = rt2x00_get_field32(reg, TX_STA_FIFO_MCS);
-
- /*
- * Ralink has a retry mechanism using a global fallback
- * table. We setup this fallback table to try the immediate
- * lower rate for all rates. In the TX_STA_FIFO, the MCS field
- * always contains the MCS used for the last transmission, be
- * it successful or not.
- */
- if (rt2x00_get_field32(reg, TX_STA_FIFO_TX_SUCCESS)) {
+ qid = rt2x00_get_field32(status, TX_STA_FIFO_PID_QUEUE);
+ if (qid >= QID_RX) {
/*
- * Transmission succeeded. The number of retries is
- * mcs - real_mcs
+ * Unknown queue, this shouldn't happen. Just drop
+ * this tx status.
*/
- __set_bit(TXDONE_SUCCESS, &txdesc.flags);
- txdesc.retry = ((mcs > real_mcs) ? mcs - real_mcs : 0);
- } else {
+ WARNING(rt2x00dev, "Got TX status report with "
+ "unexpected pid %u, dropping", qid);
+ break;
+ }
+
+ queue = rt2x00queue_get_queue(rt2x00dev, qid);
+ if (unlikely(queue == NULL)) {
/*
- * Transmission failed. The number of retries is
- * always 7 in this case (for a total number of 8
- * frames sent).
+ * The queue is NULL, this shouldn't happen. Stop
+ * processing here and drop the tx status
*/
- __set_bit(TXDONE_FAILURE, &txdesc.flags);
- txdesc.retry = 7;
+ WARNING(rt2x00dev, "Got TX status for an unavailable "
+ "queue %u, dropping", qid);
+ break;
}
- /*
- * the frame was retried at least once
- * -> hw used fallback rates
- */
- if (txdesc.retry)
- __set_bit(TXDONE_FALLBACK, &txdesc.flags);
+ if (rt2x00queue_empty(queue)) {
+ /*
+ * The queue is empty. Stop processing here
+ * and drop the tx status.
+ */
+ WARNING(rt2x00dev, "Got TX status for an empty "
+ "queue %u, dropping", qid);
+ break;
+ }
- rt2x00lib_txdone(entry, &txdesc);
+ entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
+ rt2800_txdone_entry(entry, status);
}
}
-static void rt2800pci_wakeup(struct rt2x00_dev *rt2x00dev)
+static void rt2800pci_txstatus_tasklet(unsigned long data)
{
- struct ieee80211_conf conf = { .flags = 0 };
- struct rt2x00lib_conf libconf = { .conf = &conf };
-
- rt2800_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS);
+ rt2800pci_txdone((struct rt2x00_dev *)data);
}
static irqreturn_t rt2800pci_interrupt_thread(int irq, void *dev_instance)
@@ -864,13 +742,7 @@ static irqreturn_t rt2800pci_interrupt_thread(int irq, void *dev_instance)
rt2x00pci_rxdone(rt2x00dev);
/*
- * 4 - Tx done interrupt.
- */
- if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS))
- rt2800pci_txdone(rt2x00dev);
-
- /*
- * 5 - Auto wakeup interrupt.
+ * 4 - Auto wakeup interrupt.
*/
if (rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP))
rt2800pci_wakeup(rt2x00dev);
@@ -882,10 +754,58 @@ static irqreturn_t rt2800pci_interrupt_thread(int irq, void *dev_instance)
return IRQ_HANDLED;
}
+static void rt2800pci_txstatus_interrupt(struct rt2x00_dev *rt2x00dev)
+{
+ u32 status;
+ int i;
+
+ /*
+ * The TX_FIFO_STATUS interrupt needs special care. We should
+ * read TX_STA_FIFO but we should do it immediately as otherwise
+ * the register can overflow and we would lose status reports.
+ *
+ * Hence, read the TX_STA_FIFO register and copy all tx status
+ * reports into a kernel FIFO which is handled in the txstatus
+ * tasklet. We use a tasklet to process the tx status reports
+ * because we can schedule the tasklet multiple times (when the
+ * interrupt fires again during tx status processing).
+ *
+ * Furthermore we don't disable the TX_FIFO_STATUS
+ * interrupt here but leave it enabled so that the TX_STA_FIFO
+ * can also be read while the interrupt thread gets executed.
+ *
+ * Since we have only one producer and one consumer we don't
+ * need to lock the kfifo.
+ */
+ for (i = 0; i < TX_ENTRIES; i++) {
+ rt2800_register_read(rt2x00dev, TX_STA_FIFO, &status);
+
+ if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID))
+ break;
+
+ if (kfifo_is_full(&rt2x00dev->txstatus_fifo)) {
+ WARNING(rt2x00dev, "TX status FIFO overrun,"
+ " drop tx status report.\n");
+ break;
+ }
+
+ if (kfifo_in(&rt2x00dev->txstatus_fifo, &status,
+ sizeof(status)) != sizeof(status)) {
+ WARNING(rt2x00dev, "TX status FIFO overrun,"
+ "drop tx status report.\n");
+ break;
+ }
+ }
+
+ /* Schedule the tasklet for processing the tx status. */
+ tasklet_schedule(&rt2x00dev->txstatus_tasklet);
+}
+
static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance)
{
struct rt2x00_dev *rt2x00dev = dev_instance;
u32 reg;
+ irqreturn_t ret = IRQ_HANDLED;
/* Read status and ACK all interrupts */
rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
@@ -897,15 +817,38 @@ static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance)
if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
return IRQ_HANDLED;
- /* Store irqvalue for use in the interrupt thread. */
- rt2x00dev->irqvalue[0] = reg;
+ if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS))
+ rt2800pci_txstatus_interrupt(rt2x00dev);
- /* Disable interrupts, will be enabled again in the interrupt thread. */
- rt2x00dev->ops->lib->set_device_state(rt2x00dev,
- STATE_RADIO_IRQ_OFF_ISR);
+ if (rt2x00_get_field32(reg, INT_SOURCE_CSR_PRE_TBTT) ||
+ rt2x00_get_field32(reg, INT_SOURCE_CSR_TBTT) ||
+ rt2x00_get_field32(reg, INT_SOURCE_CSR_RX_DONE) ||
+ rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP)) {
+ /*
+ * All other interrupts are handled in the interrupt thread.
+ * Store irqvalue for use in the interrupt thread.
+ */
+ rt2x00dev->irqvalue[0] = reg;
+
+ /*
+ * Disable interrupts, will be enabled again in the
+ * interrupt thread.
+ */
+ rt2x00dev->ops->lib->set_device_state(rt2x00dev,
+ STATE_RADIO_IRQ_OFF_ISR);
+
+ /*
+ * Leave the TX_FIFO_STATUS interrupt enabled to not lose any
+ * tx status reports.
+ */
+ rt2800_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+ rt2x00_set_field32(&reg, INT_MASK_CSR_TX_FIFO_STATUS, 1);
+ rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg);
+ ret = IRQ_WAKE_THREAD;
+ }
- return IRQ_WAKE_THREAD;
+ return ret;
}
/*
@@ -968,6 +911,7 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
__set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
__set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags);
__set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags);
+ __set_bit(DRIVER_REQUIRE_TXSTATUS_FIFO, &rt2x00dev->flags);
if (!modparam_nohwcrypt)
__set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
__set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags);
@@ -1011,11 +955,13 @@ static const struct rt2800_ops rt2800pci_rt2800_ops = {
.regbusy_read = rt2x00pci_regbusy_read,
.drv_write_firmware = rt2800pci_write_firmware,
.drv_init_registers = rt2800pci_init_registers,
+ .drv_get_txwi = rt2800pci_get_txwi,
};
static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
.irq_handler = rt2800pci_interrupt,
.irq_handler_thread = rt2800pci_interrupt_thread,
+ .txstatus_tasklet = rt2800pci_txstatus_tasklet,
.probe_hw = rt2800pci_probe_hw,
.get_firmware_name = rt2800pci_get_firmware_name,
.check_firmware = rt2800_check_firmware,
@@ -1030,7 +976,7 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
.reset_tuner = rt2800_reset_tuner,
.link_tuner = rt2800_link_tuner,
.write_tx_desc = rt2800pci_write_tx_desc,
- .write_tx_data = rt2800pci_write_tx_data,
+ .write_tx_data = rt2800_write_tx_data,
.write_beacon = rt2800_write_beacon,
.kick_tx_queue = rt2800pci_kick_tx_queue,
.kill_tx_queue = rt2800pci_kill_tx_queue,
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 5a2dfe87c6b6..3dff56ec195a 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -1,5 +1,6 @@
/*
- Copyright (C) 2009 Ivo van Doorn <IvDoorn@gmail.com>
+ Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
+ Copyright (C) 2009 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de>
Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com>
@@ -100,19 +101,6 @@ static int rt2800usb_write_firmware(struct rt2x00_dev *rt2x00dev,
msleep(10);
rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
- /*
- * Send signal to firmware during boot time.
- */
- rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0);
-
- if (rt2x00_rt(rt2x00dev, RT3070) ||
- rt2x00_rt(rt2x00dev, RT3071) ||
- rt2x00_rt(rt2x00dev, RT3572)) {
- udelay(200);
- rt2800_mcu_request(rt2x00dev, MCU_CURRENT, 0, 0, 0);
- udelay(10);
- }
-
return 0;
}
@@ -134,26 +122,18 @@ static void rt2800usb_toggle_rx(struct rt2x00_dev *rt2x00dev,
static int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
- int i;
/*
* Wait until BBP and RF are ready.
*/
- for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2800_register_read(rt2x00dev, MAC_CSR0, &reg);
- if (reg && reg != ~0)
- break;
- msleep(1);
- }
-
- if (i == REGISTER_BUSY_COUNT) {
- ERROR(rt2x00dev, "Unstable hardware.\n");
+ if (rt2800_wait_csr_ready(rt2x00dev))
return -EBUSY;
- }
rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, &reg);
rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0x00002000);
+ rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003);
+
rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_CSR, 1);
rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_BBP, 1);
@@ -172,30 +152,10 @@ static int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev)
static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
- u16 word;
- /*
- * Initialize all registers.
- */
- if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev) ||
- rt2800_init_registers(rt2x00dev) ||
- rt2800_init_bbp(rt2x00dev) ||
- rt2800_init_rfcsr(rt2x00dev)))
+ if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev)))
return -EIO;
- rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
- rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_TX, 1);
- rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
-
- udelay(50);
-
- rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
- rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1);
- rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 1);
- rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 1);
- rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
-
-
rt2800_register_read(rt2x00dev, USB_DMA_CFG, &reg);
rt2x00_set_field32(&reg, USB_DMA_CFG_PHY_CLEAR, 0);
rt2x00_set_field32(&reg, USB_DMA_CFG_RX_BULK_AGG_EN, 0);
@@ -210,45 +170,12 @@ static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, USB_DMA_CFG_TX_BULK_EN, 1);
rt2800_register_write(rt2x00dev, USB_DMA_CFG, reg);
- rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
- rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_TX, 1);
- rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 1);
- rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
-
- /*
- * Initialize LED control
- */
- rt2x00_eeprom_read(rt2x00dev, EEPROM_LED1, &word);
- rt2800_mcu_request(rt2x00dev, MCU_LED_1, 0xff,
- word & 0xff, (word >> 8) & 0xff);
-
- rt2x00_eeprom_read(rt2x00dev, EEPROM_LED2, &word);
- rt2800_mcu_request(rt2x00dev, MCU_LED_2, 0xff,
- word & 0xff, (word >> 8) & 0xff);
-
- rt2x00_eeprom_read(rt2x00dev, EEPROM_LED3, &word);
- rt2800_mcu_request(rt2x00dev, MCU_LED_3, 0xff,
- word & 0xff, (word >> 8) & 0xff);
-
- return 0;
+ return rt2800_enable_radio(rt2x00dev);
}
static void rt2800usb_disable_radio(struct rt2x00_dev *rt2x00dev)
{
- u32 reg;
-
- rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
- rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0);
- rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0);
- rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
-
- rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0);
- rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0);
- rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0);
-
- /* Wait for DMA, ignore error */
- rt2800_wait_wpdma_ready(rt2x00dev);
-
+ rt2800_disable_radio(rt2x00dev);
rt2x00usb_disable_radio(rt2x00dev);
}
@@ -320,21 +247,19 @@ static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev,
/*
* TX descriptor initialization
*/
-static void rt2800usb_write_tx_data(struct queue_entry* entry,
- struct txentry_desc *txdesc)
+static __le32 *rt2800usb_get_txwi(struct queue_entry *entry)
{
- __le32 *txwi = (__le32 *) (entry->skb->data + TXINFO_DESC_SIZE);
-
- rt2800_write_txwi(txwi, txdesc);
+ if (entry->queue->qid == QID_BEACON)
+ return (__le32 *) (entry->skb->data);
+ else
+ return (__le32 *) (entry->skb->data + TXINFO_DESC_SIZE);
}
-
-static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
- struct sk_buff *skb,
+static void rt2800usb_write_tx_desc(struct queue_entry *entry,
struct txentry_desc *txdesc)
{
- struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
- __le32 *txi = (__le32 *) skb->data;
+ struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+ __le32 *txi = (__le32 *) entry->skb->data;
u32 word;
/*
@@ -342,7 +267,7 @@ static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
*/
rt2x00_desc_read(txi, 0, &word);
rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_TX_PKT_LEN,
- skb->len - TXINFO_DESC_SIZE);
+ entry->skb->len - TXINFO_DESC_SIZE);
rt2x00_set_field32(&word, TXINFO_W0_WIV,
!test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags));
rt2x00_set_field32(&word, TXINFO_W0_QSEL, 2);
@@ -379,6 +304,46 @@ static int rt2800usb_get_tx_data_len(struct queue_entry *entry)
}
/*
+ * TX control handlers
+ */
+static void rt2800usb_work_txdone(struct work_struct *work)
+{
+ struct rt2x00_dev *rt2x00dev =
+ container_of(work, struct rt2x00_dev, txdone_work);
+ struct data_queue *queue;
+ struct queue_entry *entry;
+
+ rt2800_txdone(rt2x00dev);
+
+ /*
+ * Process any trailing TX status reports for IO failures,
+ * we loop until we find the first non-IO error entry. This
+ * can either be a frame which is free, is being uploaded,
+ * or has completed the upload but didn't have an entry
+ * in the TX_STAT_FIFO register yet.
+ */
+ tx_queue_for_each(rt2x00dev, queue) {
+ while (!rt2x00queue_empty(queue)) {
+ entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
+
+ if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
+ !test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
+ break;
+
+ rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE);
+ }
+ }
+}
+
+static void rt2800usb_kill_tx_queue(struct data_queue *queue)
+{
+ if (queue->qid == QID_BEACON)
+ rt2x00usb_register_write(queue->rt2x00dev, BCN_TIME_CFG, 0);
+
+ rt2x00usb_kill_tx_queue(queue);
+}
+
+/*
* RX control handlers
*/
static void rt2800usb_fill_rxdone(struct queue_entry *entry,
@@ -514,6 +479,11 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
*/
rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET;
+ /*
+ * Overwrite TX done handler
+ */
+ PREPARE_WORK(&rt2x00dev->txdone_work, rt2800usb_work_txdone);
+
return 0;
}
@@ -549,6 +519,7 @@ static const struct rt2800_ops rt2800usb_rt2800_ops = {
.regbusy_read = rt2x00usb_regbusy_read,
.drv_write_firmware = rt2800usb_write_firmware,
.drv_init_registers = rt2800usb_init_registers,
+ .drv_get_txwi = rt2800usb_get_txwi,
};
static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
@@ -566,11 +537,11 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
.link_tuner = rt2800_link_tuner,
.watchdog = rt2x00usb_watchdog,
.write_tx_desc = rt2800usb_write_tx_desc,
- .write_tx_data = rt2800usb_write_tx_data,
+ .write_tx_data = rt2800_write_tx_data,
.write_beacon = rt2800_write_beacon,
.get_tx_data_len = rt2800usb_get_tx_data_len,
.kick_tx_queue = rt2x00usb_kick_tx_queue,
- .kill_tx_queue = rt2x00usb_kill_tx_queue,
+ .kill_tx_queue = rt2800usb_kill_tx_queue,
.fill_rxdone = rt2800usb_fill_rxdone,
.config_shared_key = rt2800_config_shared_key,
.config_pairwise_key = rt2800_config_pairwise_key,
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index c21af38cc5af..94fe589acfaa 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -1,5 +1,6 @@
/*
- Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+ Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
+ Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
Copyright (C) 2004 - 2009 Gertjan van Wingerde <gwingerde@gmail.com>
<http://rt2x00.serialmonkey.com>
@@ -35,6 +36,7 @@
#include <linux/mutex.h>
#include <linux/etherdevice.h>
#include <linux/input-polldev.h>
+#include <linux/kfifo.h>
#include <net/mac80211.h>
@@ -212,8 +214,9 @@ struct channel_info {
unsigned int flags;
#define GEOGRAPHY_ALLOWED 0x00000001
- short tx_power1;
- short tx_power2;
+ short max_power;
+ short default_power1;
+ short default_power2;
};
/*
@@ -335,6 +338,11 @@ struct link {
/*
* Work structure for scheduling periodic watchdog monitoring.
+ * This work must be scheduled on the kernel workqueue, while
+ * all other work structures must be queued on the mac80211
+ * workqueue. This guarantees that the watchdog can schedule
+ * other work structures and wait for their completion in order
+ * to bring the device/driver back into the desired state.
*/
struct delayed_work watchdog_work;
};
@@ -455,6 +463,7 @@ struct rt2x00lib_erp {
short eifs;
u16 beacon_int;
+ u16 ht_opmode;
};
/*
@@ -520,6 +529,11 @@ struct rt2x00lib_ops {
irq_handler_t irq_handler_thread;
/*
+ * TX status tasklet handler.
+ */
+ void (*txstatus_tasklet) (unsigned long data);
+
+ /*
* Device init handlers.
*/
int (*probe_hw) (struct rt2x00_dev *rt2x00dev);
@@ -558,18 +572,15 @@ struct rt2x00lib_ops {
/*
* TX control handlers
*/
- void (*write_tx_desc) (struct rt2x00_dev *rt2x00dev,
- struct sk_buff *skb,
+ void (*write_tx_desc) (struct queue_entry *entry,
struct txentry_desc *txdesc);
void (*write_tx_data) (struct queue_entry *entry,
struct txentry_desc *txdesc);
void (*write_beacon) (struct queue_entry *entry,
struct txentry_desc *txdesc);
int (*get_tx_data_len) (struct queue_entry *entry);
- void (*kick_tx_queue) (struct rt2x00_dev *rt2x00dev,
- const enum data_queue_qid queue);
- void (*kill_tx_queue) (struct rt2x00_dev *rt2x00dev,
- const enum data_queue_qid queue);
+ void (*kick_tx_queue) (struct data_queue *queue);
+ void (*kill_tx_queue) (struct data_queue *queue);
/*
* RX control handlers
@@ -597,7 +608,8 @@ struct rt2x00lib_ops {
#define CONFIG_UPDATE_BSSID ( 1 << 3 )
void (*config_erp) (struct rt2x00_dev *rt2x00dev,
- struct rt2x00lib_erp *erp);
+ struct rt2x00lib_erp *erp,
+ u32 changed);
void (*config_ant) (struct rt2x00_dev *rt2x00dev,
struct antenna_setup *ant);
void (*config) (struct rt2x00_dev *rt2x00dev,
@@ -651,6 +663,7 @@ enum rt2x00_flags {
DRIVER_REQUIRE_DMA,
DRIVER_REQUIRE_COPY_IV,
DRIVER_REQUIRE_L2PAD,
+ DRIVER_REQUIRE_TXSTATUS_FIFO,
/*
* Driver features
@@ -698,6 +711,7 @@ struct rt2x00_dev {
struct ieee80211_hw *hw;
struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
enum ieee80211_band curr_band;
+ int curr_freq;
/*
* If enabled, the debugfs interface structures
@@ -850,11 +864,6 @@ struct rt2x00_dev {
struct ieee80211_low_level_stats low_level_stats;
/*
- * RX configuration information.
- */
- struct ieee80211_rx_status rx_status;
-
- /*
* Scheduled work.
* NOTE: intf_work will use ieee80211_iterate_active_interfaces()
* which means it cannot be placed on the hw->workqueue
@@ -862,6 +871,12 @@ struct rt2x00_dev {
*/
struct work_struct intf_work;
+ /**
+ * Scheduled work for TX/RX done handling (USB devices)
+ */
+ struct work_struct rxdone_work;
+ struct work_struct txdone_work;
+
/*
* Data queue arrays for RX, TX and Beacon.
* The Beacon array also contains the Atim queue
@@ -882,6 +897,16 @@ struct rt2x00_dev {
* and interrupt thread routine.
*/
u32 irqvalue[2];
+
+ /*
+ * FIFO for storing tx status reports between isr and tasklet.
+ */
+ struct kfifo txstatus_fifo;
+
+ /*
+ * Tasklet for processing tx status reports (rt2800pci).
+ */
+ struct tasklet_struct txstatus_tasklet;
};
/*
@@ -1016,17 +1041,15 @@ static inline bool rt2x00_is_soc(struct rt2x00_dev *rt2x00dev)
/**
* rt2x00queue_map_txskb - Map a skb into DMA for TX purposes.
- * @rt2x00dev: Pointer to &struct rt2x00_dev.
- * @skb: The skb to map.
+ * @entry: Pointer to &struct queue_entry
*/
-void rt2x00queue_map_txskb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb);
+void rt2x00queue_map_txskb(struct queue_entry *entry);
/**
* rt2x00queue_unmap_skb - Unmap a skb from DMA.
- * @rt2x00dev: Pointer to &struct rt2x00_dev.
- * @skb: The skb to unmap.
+ * @entry: Pointer to &struct queue_entry
*/
-void rt2x00queue_unmap_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb);
+void rt2x00queue_unmap_skb(struct queue_entry *entry);
/**
* rt2x00queue_get_queue - Convert queue index to queue pointer
@@ -1069,10 +1092,11 @@ static inline void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
*/
void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev);
void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev);
+void rt2x00lib_dmadone(struct queue_entry *entry);
void rt2x00lib_txdone(struct queue_entry *entry,
struct txdone_entry_desc *txdesc);
-void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
- struct queue_entry *entry);
+void rt2x00lib_txdone_noinfo(struct queue_entry *entry, u32 status);
+void rt2x00lib_rxdone(struct queue_entry *entry);
/*
* mac80211 handlers.
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c
index 953dc4f2c6af..54ffb5aeb34e 100644
--- a/drivers/net/wireless/rt2x00/rt2x00config.c
+++ b/drivers/net/wireless/rt2x00/rt2x00config.c
@@ -81,7 +81,8 @@ void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev,
void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
struct rt2x00_intf *intf,
- struct ieee80211_bss_conf *bss_conf)
+ struct ieee80211_bss_conf *bss_conf,
+ u32 changed)
{
struct rt2x00lib_erp erp;
@@ -102,7 +103,10 @@ void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
/* Update global beacon interval time, this is needed for PS support */
rt2x00dev->beacon_int = bss_conf->beacon_int;
- rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp);
+ if (changed & BSS_CHANGED_HT)
+ erp.ht_opmode = bss_conf->ht_operation_mode;
+
+ rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp, changed);
}
static inline
@@ -126,25 +130,17 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
* ANTENNA_SW_DIVERSITY state to the driver.
* If that happens, fallback to hardware defaults,
* or our own default.
- * If diversity handling is active for a particular antenna,
- * we shouldn't overwrite that antenna.
- * The calls to rt2x00lib_config_antenna_check()
- * might have caused that we restore back to the already
- * active setting. If that has happened we can quit.
*/
if (!(ant->flags & ANTENNA_RX_DIVERSITY))
config.rx = rt2x00lib_config_antenna_check(config.rx, def->rx);
- else
+ else if(config.rx == ANTENNA_SW_DIVERSITY)
config.rx = active->rx;
if (!(ant->flags & ANTENNA_TX_DIVERSITY))
config.tx = rt2x00lib_config_antenna_check(config.tx, def->tx);
- else
+ else if (config.tx == ANTENNA_SW_DIVERSITY)
config.tx = active->tx;
- if (config.rx == active->rx && config.tx == active->tx)
- return;
-
/*
* Antenna setup changes require the RX to be disabled,
* else the changes will be ignored by the device.
@@ -209,10 +205,8 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
rt2x00link_reset_tuner(rt2x00dev, false);
rt2x00dev->curr_band = conf->channel->band;
+ rt2x00dev->curr_freq = conf->channel->center_freq;
rt2x00dev->tx_power = conf->power_level;
rt2x00dev->short_retry = conf->short_frame_max_tx_count;
rt2x00dev->long_retry = conf->long_frame_max_tx_count;
-
- rt2x00dev->rx_status.band = conf->channel->band;
- rt2x00dev->rx_status.freq = conf->channel->center_freq;
}
diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c
index 583dacd8d241..5e9074bf2b8e 100644
--- a/drivers/net/wireless/rt2x00/rt2x00crypto.c
+++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c
@@ -31,15 +31,14 @@
enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *key)
{
- switch (key->alg) {
- case ALG_WEP:
- if (key->keylen == WLAN_KEY_LEN_WEP40)
- return CIPHER_WEP64;
- else
- return CIPHER_WEP128;
- case ALG_TKIP:
+ switch (key->cipher) {
+ case WLAN_CIPHER_SUITE_WEP40:
+ return CIPHER_WEP64;
+ case WLAN_CIPHER_SUITE_WEP104:
+ return CIPHER_WEP128;
+ case WLAN_CIPHER_SUITE_TKIP:
return CIPHER_TKIP;
- case ALG_CCMP:
+ case WLAN_CIPHER_SUITE_CCMP:
return CIPHER_AES;
default:
return CIPHER_NONE;
@@ -95,7 +94,7 @@ unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev,
overhead += key->iv_len;
if (!(key->flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) {
- if (key->alg == ALG_TKIP)
+ if (key->cipher == WLAN_CIPHER_SUITE_TKIP)
overhead += 8;
}
diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c
index b0498e7e7aae..fcdb6b0dc40f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00debug.c
+++ b/drivers/net/wireless/rt2x00/rt2x00debug.c
@@ -315,6 +315,7 @@ static const struct file_operations rt2x00debug_fop_queue_dump = {
.poll = rt2x00debug_poll_queue_dump,
.open = rt2x00debug_open_queue_dump,
.release = rt2x00debug_release_queue_dump,
+ .llseek = default_llseek,
};
static ssize_t rt2x00debug_read_queue_stats(struct file *file,
@@ -333,12 +334,12 @@ static ssize_t rt2x00debug_read_queue_stats(struct file *file,
if (*offset)
return 0;
- data = kzalloc(lines * MAX_LINE_LENGTH, GFP_KERNEL);
+ data = kcalloc(lines, MAX_LINE_LENGTH, GFP_KERNEL);
if (!data)
return -ENOMEM;
temp = data +
- sprintf(data, "qid\tcount\tlimit\tlength\tindex\tdone\tcrypto\n");
+ sprintf(data, "qid\tcount\tlimit\tlength\tindex\tdma done\tdone\n");
queue_for_each(intf->rt2x00dev, queue) {
spin_lock_irqsave(&queue->lock, irqflags);
@@ -346,8 +347,8 @@ static ssize_t rt2x00debug_read_queue_stats(struct file *file,
temp += sprintf(temp, "%d\t%d\t%d\t%d\t%d\t%d\t%d\n", queue->qid,
queue->count, queue->limit, queue->length,
queue->index[Q_INDEX],
- queue->index[Q_INDEX_DONE],
- queue->index[Q_INDEX_CRYPTO]);
+ queue->index[Q_INDEX_DMA_DONE],
+ queue->index[Q_INDEX_DONE]);
spin_unlock_irqrestore(&queue->lock, irqflags);
}
@@ -371,6 +372,7 @@ static const struct file_operations rt2x00debug_fop_queue_stats = {
.read = rt2x00debug_read_queue_stats,
.open = rt2x00debug_file_open,
.release = rt2x00debug_file_release,
+ .llseek = default_llseek,
};
#ifdef CONFIG_RT2X00_LIB_CRYPTO
@@ -380,7 +382,7 @@ static ssize_t rt2x00debug_read_crypto_stats(struct file *file,
loff_t *offset)
{
struct rt2x00debug_intf *intf = file->private_data;
- char *name[] = { "WEP64", "WEP128", "TKIP", "AES" };
+ static const char * const name[] = { "WEP64", "WEP128", "TKIP", "AES" };
char *data;
char *temp;
size_t size;
@@ -423,6 +425,7 @@ static const struct file_operations rt2x00debug_fop_crypto_stats = {
.read = rt2x00debug_read_crypto_stats,
.open = rt2x00debug_file_open,
.release = rt2x00debug_file_release,
+ .llseek = default_llseek,
};
#endif
@@ -481,6 +484,9 @@ static ssize_t rt2x00debug_write_##__name(struct file *file, \
if (index >= debug->__name.word_count) \
return -EINVAL; \
\
+ if (length > sizeof(line)) \
+ return -EINVAL; \
+ \
if (copy_from_user(line, buf, length)) \
return -EFAULT; \
\
@@ -509,6 +515,7 @@ static const struct file_operations rt2x00debug_fop_##__name = {\
.write = rt2x00debug_write_##__name, \
.open = rt2x00debug_file_open, \
.release = rt2x00debug_file_release, \
+ .llseek = generic_file_llseek, \
};
RT2X00DEBUGFS_OPS(csr, "0x%.8x\n", u32);
@@ -542,6 +549,7 @@ static const struct file_operations rt2x00debug_fop_dev_flags = {
.read = rt2x00debug_read_dev_flags,
.open = rt2x00debug_file_open,
.release = rt2x00debug_file_release,
+ .llseek = default_llseek,
};
static struct dentry *rt2x00debug_create_file_driver(const char *name,
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 585e8166f22a..5ba79b935f09 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -1,5 +1,6 @@
/*
- Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+ Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
+ Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
<http://rt2x00.serialmonkey.com>
This program is free software; you can redistribute it and/or modify
@@ -250,6 +251,13 @@ void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev)
}
EXPORT_SYMBOL_GPL(rt2x00lib_pretbtt);
+void rt2x00lib_dmadone(struct queue_entry *entry)
+{
+ clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
+ rt2x00queue_index_inc(entry->queue, Q_INDEX_DMA_DONE);
+}
+EXPORT_SYMBOL_GPL(rt2x00lib_dmadone);
+
void rt2x00lib_txdone(struct queue_entry *entry,
struct txdone_entry_desc *txdesc)
{
@@ -266,7 +274,7 @@ void rt2x00lib_txdone(struct queue_entry *entry,
/*
* Unmap the skb.
*/
- rt2x00queue_unmap_skb(rt2x00dev, entry->skb);
+ rt2x00queue_unmap_skb(entry);
/*
* Remove the extra tx headroom from the skb.
@@ -383,15 +391,7 @@ void rt2x00lib_txdone(struct queue_entry *entry,
* send the status report back.
*/
if (!(skbdesc_flags & SKBDESC_NOT_MAC80211))
- /*
- * Only PCI and SOC devices process the tx status in process
- * context. Hence use ieee80211_tx_status for PCI and SOC
- * devices and stick to ieee80211_tx_status_irqsafe for USB.
- */
- if (rt2x00_is_usb(rt2x00dev))
- ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb);
- else
- ieee80211_tx_status(rt2x00dev->hw, entry->skb);
+ ieee80211_tx_status(rt2x00dev->hw, entry->skb);
else
dev_kfree_skb_any(entry->skb);
@@ -403,7 +403,6 @@ void rt2x00lib_txdone(struct queue_entry *entry,
rt2x00dev->ops->lib->clear_entry(entry);
- clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE);
/*
@@ -416,65 +415,89 @@ void rt2x00lib_txdone(struct queue_entry *entry,
}
EXPORT_SYMBOL_GPL(rt2x00lib_txdone);
+void rt2x00lib_txdone_noinfo(struct queue_entry *entry, u32 status)
+{
+ struct txdone_entry_desc txdesc;
+
+ txdesc.flags = 0;
+ __set_bit(status, &txdesc.flags);
+ txdesc.retry = 0;
+
+ rt2x00lib_txdone(entry, &txdesc);
+}
+EXPORT_SYMBOL_GPL(rt2x00lib_txdone_noinfo);
+
static int rt2x00lib_rxdone_read_signal(struct rt2x00_dev *rt2x00dev,
struct rxdone_entry_desc *rxdesc)
{
struct ieee80211_supported_band *sband;
const struct rt2x00_rate *rate;
unsigned int i;
- int signal;
- int type;
+ int signal = rxdesc->signal;
+ int type = (rxdesc->dev_flags & RXDONE_SIGNAL_MASK);
- /*
- * For non-HT rates the MCS value needs to contain the
- * actually used rate modulation (CCK or OFDM).
- */
- if (rxdesc->dev_flags & RXDONE_SIGNAL_MCS)
- signal = RATE_MCS(rxdesc->rate_mode, rxdesc->signal);
- else
- signal = rxdesc->signal;
-
- type = (rxdesc->dev_flags & RXDONE_SIGNAL_MASK);
-
- sband = &rt2x00dev->bands[rt2x00dev->curr_band];
- for (i = 0; i < sband->n_bitrates; i++) {
- rate = rt2x00_get_rate(sband->bitrates[i].hw_value);
-
- if (((type == RXDONE_SIGNAL_PLCP) &&
- (rate->plcp == signal)) ||
- ((type == RXDONE_SIGNAL_BITRATE) &&
- (rate->bitrate == signal)) ||
- ((type == RXDONE_SIGNAL_MCS) &&
- (rate->mcs == signal))) {
- return i;
+ switch (rxdesc->rate_mode) {
+ case RATE_MODE_CCK:
+ case RATE_MODE_OFDM:
+ /*
+ * For non-HT rates the MCS value needs to contain the
+ * actually used rate modulation (CCK or OFDM).
+ */
+ if (rxdesc->dev_flags & RXDONE_SIGNAL_MCS)
+ signal = RATE_MCS(rxdesc->rate_mode, signal);
+
+ sband = &rt2x00dev->bands[rt2x00dev->curr_band];
+ for (i = 0; i < sband->n_bitrates; i++) {
+ rate = rt2x00_get_rate(sband->bitrates[i].hw_value);
+ if (((type == RXDONE_SIGNAL_PLCP) &&
+ (rate->plcp == signal)) ||
+ ((type == RXDONE_SIGNAL_BITRATE) &&
+ (rate->bitrate == signal)) ||
+ ((type == RXDONE_SIGNAL_MCS) &&
+ (rate->mcs == signal))) {
+ return i;
+ }
}
+ break;
+ case RATE_MODE_HT_MIX:
+ case RATE_MODE_HT_GREENFIELD:
+ if (signal >= 0 && signal <= 76)
+ return signal;
+ break;
+ default:
+ break;
}
WARNING(rt2x00dev, "Frame received with unrecognized signal, "
- "signal=0x%.4x, type=%d.\n", signal, type);
+ "mode=0x%.4x, signal=0x%.4x, type=%d.\n",
+ rxdesc->rate_mode, signal, type);
return 0;
}
-void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
- struct queue_entry *entry)
+void rt2x00lib_rxdone(struct queue_entry *entry)
{
+ struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct rxdone_entry_desc rxdesc;
struct sk_buff *skb;
- struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status;
+ struct ieee80211_rx_status *rx_status;
unsigned int header_length;
int rate_idx;
+
+ if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
+ goto submit_entry;
+
/*
* Allocate a new sk_buffer. If no new buffer available, drop the
* received frame and reuse the existing buffer.
*/
- skb = rt2x00queue_alloc_rxskb(rt2x00dev, entry);
+ skb = rt2x00queue_alloc_rxskb(entry);
if (!skb)
- return;
+ goto submit_entry;
/*
* Unmap the skb.
*/
- rt2x00queue_unmap_skb(rt2x00dev, entry->skb);
+ rt2x00queue_unmap_skb(entry);
/*
* Extract the RXD details.
@@ -509,57 +532,44 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
skb_trim(entry->skb, rxdesc.size);
/*
- * Check if the frame was received using HT. In that case,
- * the rate is the MCS index and should be passed to mac80211
- * directly. Otherwise we need to translate the signal to
- * the correct bitrate index.
+ * Translate the signal to the correct bitrate index.
*/
- if (rxdesc.rate_mode == RATE_MODE_CCK ||
- rxdesc.rate_mode == RATE_MODE_OFDM) {
- rate_idx = rt2x00lib_rxdone_read_signal(rt2x00dev, &rxdesc);
- } else {
+ rate_idx = rt2x00lib_rxdone_read_signal(rt2x00dev, &rxdesc);
+ if (rxdesc.rate_mode == RATE_MODE_HT_MIX ||
+ rxdesc.rate_mode == RATE_MODE_HT_GREENFIELD)
rxdesc.flags |= RX_FLAG_HT;
- rate_idx = rxdesc.signal;
- }
/*
* Update extra components
*/
rt2x00link_update_stats(rt2x00dev, entry->skb, &rxdesc);
rt2x00debug_update_crypto(rt2x00dev, &rxdesc);
+ rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_RXDONE, entry->skb);
+ /*
+ * Initialize RX status information, and send frame
+ * to mac80211.
+ */
+ rx_status = IEEE80211_SKB_RXCB(entry->skb);
rx_status->mactime = rxdesc.timestamp;
+ rx_status->band = rt2x00dev->curr_band;
+ rx_status->freq = rt2x00dev->curr_freq;
rx_status->rate_idx = rate_idx;
rx_status->signal = rxdesc.rssi;
rx_status->flag = rxdesc.flags;
rx_status->antenna = rt2x00dev->link.ant.active.rx;
- /*
- * Send frame to mac80211 & debugfs.
- * mac80211 will clean up the skb structure.
- */
- rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_RXDONE, entry->skb);
- memcpy(IEEE80211_SKB_RXCB(entry->skb), rx_status, sizeof(*rx_status));
-
- /*
- * Currently only PCI and SOC devices handle rx interrupts in process
- * context. Hence, use ieee80211_rx_irqsafe for USB and ieee80211_rx_ni
- * for PCI and SOC devices.
- */
- if (rt2x00_is_usb(rt2x00dev))
- ieee80211_rx_irqsafe(rt2x00dev->hw, entry->skb);
- else
- ieee80211_rx_ni(rt2x00dev->hw, entry->skb);
+ ieee80211_rx_ni(rt2x00dev->hw, entry->skb);
/*
* Replace the skb with the freshly allocated one.
*/
entry->skb = skb;
- entry->flags = 0;
+submit_entry:
rt2x00dev->ops->lib->clear_entry(entry);
-
rt2x00queue_index_inc(entry->queue, Q_INDEX);
+ rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE);
}
EXPORT_SYMBOL_GPL(rt2x00lib_rxdone);
@@ -710,7 +720,7 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev,
for (i = 0; i < spec->num_channels; i++) {
rt2x00lib_channel(&channels[i],
spec->channels[i].channel,
- spec->channels_info[i].tx_power1, i);
+ spec->channels_info[i].max_power, i);
}
/*
@@ -806,6 +816,30 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev)
rt2x00dev->hw->extra_tx_headroom += RT2X00_ALIGN_SIZE;
/*
+ * Allocate tx status FIFO for driver use.
+ */
+ if (test_bit(DRIVER_REQUIRE_TXSTATUS_FIFO, &rt2x00dev->flags) &&
+ rt2x00dev->ops->lib->txstatus_tasklet) {
+ /*
+ * Allocate txstatus fifo and tasklet, we use a size of 512
+ * for the kfifo which is big enough to store 512/4=128 tx
+ * status reports. In the worst case (tx status for all tx
+ * queues gets reported before we've got a chance to handle
+ * them) 24*4=384 tx status reports need to be cached.
+ */
+ status = kfifo_alloc(&rt2x00dev->txstatus_fifo, 512,
+ GFP_KERNEL);
+ if (status)
+ return status;
+
+ /* tasklet for processing the tx status reports. */
+ tasklet_init(&rt2x00dev->txstatus_tasklet,
+ rt2x00dev->ops->lib->txstatus_tasklet,
+ (unsigned long)rt2x00dev);
+
+ }
+
+ /*
* Register HW.
*/
status = ieee80211_register_hw(rt2x00dev->hw);
@@ -902,10 +936,8 @@ int rt2x00lib_start(struct rt2x00_dev *rt2x00dev)
/* Enable the radio */
retval = rt2x00lib_enable_radio(rt2x00dev);
- if (retval) {
- rt2x00queue_uninitialize(rt2x00dev);
+ if (retval)
return retval;
- }
set_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags);
@@ -1017,6 +1049,18 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
* Stop all work.
*/
cancel_work_sync(&rt2x00dev->intf_work);
+ cancel_work_sync(&rt2x00dev->rxdone_work);
+ cancel_work_sync(&rt2x00dev->txdone_work);
+
+ /*
+ * Free the tx status fifo.
+ */
+ kfifo_free(&rt2x00dev->txstatus_fifo);
+
+ /*
+ * Kill the tx status tasklet.
+ */
+ tasklet_kill(&rt2x00dev->txstatus_tasklet);
/*
* Uninitialize device.
diff --git a/drivers/net/wireless/rt2x00/rt2x00firmware.c b/drivers/net/wireless/rt2x00/rt2x00firmware.c
index b818a43c4672..f0e1eb72befc 100644
--- a/drivers/net/wireless/rt2x00/rt2x00firmware.c
+++ b/drivers/net/wireless/rt2x00/rt2x00firmware.c
@@ -63,6 +63,9 @@ static int rt2x00lib_request_firmware(struct rt2x00_dev *rt2x00dev)
INFO(rt2x00dev, "Firmware detected - version: %d.%d.\n",
fw->data[fw->size - 4], fw->data[fw->size - 3]);
+ snprintf(rt2x00dev->hw->wiphy->fw_version,
+ sizeof(rt2x00dev->hw->wiphy->fw_version), "%d.%d",
+ fw->data[fw->size - 4], fw->data[fw->size - 3]);
retval = rt2x00dev->ops->lib->check_firmware(rt2x00dev, fw->data, fw->size);
switch (retval) {
diff --git a/drivers/net/wireless/rt2x00/rt2x00ht.c b/drivers/net/wireless/rt2x00/rt2x00ht.c
index c004cd3a8847..c637bcaec5f8 100644
--- a/drivers/net/wireless/rt2x00/rt2x00ht.c
+++ b/drivers/net/wireless/rt2x00/rt2x00ht.c
@@ -54,6 +54,17 @@ void rt2x00ht_create_tx_descriptor(struct queue_entry *entry,
*/
if (txrate->flags & IEEE80211_TX_RC_MCS) {
txdesc->mcs = txrate->idx;
+
+ /*
+ * MIMO PS should be set to 1 for STA's using dynamic SM PS
+ * when using more then one tx stream (>MCS7).
+ */
+ if (tx_info->control.sta && txdesc->mcs > 7 &&
+ ((tx_info->control.sta->ht_cap.cap &
+ IEEE80211_HT_CAP_SM_PS) >>
+ IEEE80211_HT_CAP_SM_PS_SHIFT) ==
+ WLAN_HT_CAP_SM_PS_DYNAMIC)
+ __set_bit(ENTRY_TXD_HT_MIMO_PS, &txdesc->flags);
} else {
txdesc->mcs = rt2x00_get_rate_mcs(hwrate->mcs);
if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
@@ -62,9 +73,11 @@ void rt2x00ht_create_tx_descriptor(struct queue_entry *entry,
/*
- * Convert flags
+ * This frame is eligible for an AMPDU, however, don't aggregate
+ * frames that are intended to probe a specific tx rate.
*/
- if (tx_info->flags & IEEE80211_TX_CTL_AMPDU)
+ if (tx_info->flags & IEEE80211_TX_CTL_AMPDU &&
+ !(tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE))
__set_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags);
/*
@@ -74,7 +87,13 @@ void rt2x00ht_create_tx_descriptor(struct queue_entry *entry,
txdesc->rate_mode = RATE_MODE_HT_MIX;
if (txrate->flags & IEEE80211_TX_RC_GREEN_FIELD)
txdesc->rate_mode = RATE_MODE_HT_GREENFIELD;
- if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+
+ /*
+ * Set 40Mhz mode if necessary (for legacy rates this will
+ * duplicate the frame to both channels).
+ */
+ if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH ||
+ txrate->flags & IEEE80211_TX_RC_DUP_DATA)
__set_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags);
if (txrate->flags & IEEE80211_TX_RC_SHORT_GI)
__set_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags);
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h
index dc5c6574aaf4..619da23b7b56 100644
--- a/drivers/net/wireless/rt2x00/rt2x00lib.h
+++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
@@ -86,7 +86,8 @@ void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev,
const u8 *mac, const u8 *bssid);
void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
struct rt2x00_intf *intf,
- struct ieee80211_bss_conf *conf);
+ struct ieee80211_bss_conf *conf,
+ u32 changed);
void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
struct antenna_setup ant);
void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
@@ -99,18 +100,15 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
/**
* rt2x00queue_alloc_rxskb - allocate a skb for RX purposes.
- * @rt2x00dev: Pointer to &struct rt2x00_dev.
- * @queue: The queue for which the skb will be applicable.
+ * @entry: The entry for which the skb will be applicable.
*/
-struct sk_buff *rt2x00queue_alloc_rxskb(struct rt2x00_dev *rt2x00dev,
- struct queue_entry *entry);
+struct sk_buff *rt2x00queue_alloc_rxskb(struct queue_entry *entry);
/**
* rt2x00queue_free_skb - free a skb
- * @rt2x00dev: Pointer to &struct rt2x00_dev.
- * @skb: The skb to free.
+ * @entry: The entry for which the skb will be applicable.
*/
-void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb);
+void rt2x00queue_free_skb(struct queue_entry *entry);
/**
* rt2x00queue_align_frame - Align 802.11 frame to 4-byte boundary
diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c
index 666cef3f8472..b971d8798ebf 100644
--- a/drivers/net/wireless/rt2x00/rt2x00link.c
+++ b/drivers/net/wireless/rt2x00/rt2x00link.c
@@ -188,7 +188,6 @@ static void rt2x00lib_antenna_diversity_eval(struct rt2x00_dev *rt2x00dev)
static bool rt2x00lib_antenna_diversity(struct rt2x00_dev *rt2x00dev)
{
struct link_ant *ant = &rt2x00dev->link.ant;
- unsigned int flags = ant->flags;
/*
* Determine if software diversity is enabled for
@@ -196,13 +195,13 @@ static bool rt2x00lib_antenna_diversity(struct rt2x00_dev *rt2x00dev)
* Always perform this check since within the link
* tuner interval the configuration might have changed.
*/
- flags &= ~ANTENNA_RX_DIVERSITY;
- flags &= ~ANTENNA_TX_DIVERSITY;
+ ant->flags &= ~ANTENNA_RX_DIVERSITY;
+ ant->flags &= ~ANTENNA_TX_DIVERSITY;
if (rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY)
- flags |= ANTENNA_RX_DIVERSITY;
+ ant->flags |= ANTENNA_RX_DIVERSITY;
if (rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY)
- flags |= ANTENNA_TX_DIVERSITY;
+ ant->flags |= ANTENNA_TX_DIVERSITY;
if (!(ant->flags & ANTENNA_RX_DIVERSITY) &&
!(ant->flags & ANTENNA_TX_DIVERSITY)) {
@@ -210,9 +209,6 @@ static bool rt2x00lib_antenna_diversity(struct rt2x00_dev *rt2x00dev)
return true;
}
- /* Update flags */
- ant->flags = flags;
-
/*
* If we have only sampled the data over the last period
* we should now harvest the data. Otherwise just evaluate
@@ -240,6 +236,12 @@ void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev,
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
/*
+ * No need to update the stats for !=STA interfaces
+ */
+ if (!rt2x00dev->intf_sta_count)
+ return;
+
+ /*
* Frame was received successfully since non-succesfull
* frames would have been dropped by the hardware.
*/
@@ -415,8 +417,7 @@ void rt2x00link_start_watchdog(struct rt2x00_dev *rt2x00dev)
!test_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags))
return;
- ieee80211_queue_delayed_work(rt2x00dev->hw,
- &link->watchdog_work, WATCHDOG_INTERVAL);
+ schedule_delayed_work(&link->watchdog_work, WATCHDOG_INTERVAL);
}
void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev)
@@ -440,8 +441,7 @@ static void rt2x00link_watchdog(struct work_struct *work)
rt2x00dev->ops->lib->watchdog(rt2x00dev);
if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
- ieee80211_queue_delayed_work(rt2x00dev->hw,
- &link->watchdog_work, WATCHDOG_INTERVAL);
+ schedule_delayed_work(&link->watchdog_work, WATCHDOG_INTERVAL);
}
void rt2x00link_register(struct rt2x00_dev *rt2x00dev)
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 235e037e6509..c3c206a97d54 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -669,8 +669,10 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
* When the erp information has changed, we should perform
* additional configuration steps. For all other changes we are done.
*/
- if (changes & ~(BSS_CHANGED_ASSOC | BSS_CHANGED_HT))
- rt2x00lib_config_erp(rt2x00dev, intf, bss_conf);
+ if (changes & (BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_ERP_PREAMBLE |
+ BSS_CHANGED_ERP_SLOT | BSS_CHANGED_BASIC_RATES |
+ BSS_CHANGED_BEACON_INT | BSS_CHANGED_HT))
+ rt2x00lib_config_erp(rt2x00dev, intf, bss_conf, changes);
}
EXPORT_SYMBOL_GPL(rt2x00mac_bss_info_changed);
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
index 63c2cc408e15..2449d785cf8d 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.c
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
@@ -84,7 +84,7 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
/*
* Send the frame to rt2x00lib for further processing.
*/
- rt2x00lib_rxdone(rt2x00dev, entry);
+ rt2x00lib_rxdone(entry);
}
}
EXPORT_SYMBOL_GPL(rt2x00pci_rxdone);
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index a3401d301058..e360d287defb 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -1,5 +1,6 @@
/*
- Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+ Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
+ Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
Copyright (C) 2004 - 2009 Gertjan van Wingerde <gwingerde@gmail.com>
<http://rt2x00.serialmonkey.com>
@@ -32,9 +33,9 @@
#include "rt2x00.h"
#include "rt2x00lib.h"
-struct sk_buff *rt2x00queue_alloc_rxskb(struct rt2x00_dev *rt2x00dev,
- struct queue_entry *entry)
+struct sk_buff *rt2x00queue_alloc_rxskb(struct queue_entry *entry)
{
+ struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct sk_buff *skb;
struct skb_frame_desc *skbdesc;
unsigned int frame_size;
@@ -96,41 +97,42 @@ struct sk_buff *rt2x00queue_alloc_rxskb(struct rt2x00_dev *rt2x00dev,
return skb;
}
-void rt2x00queue_map_txskb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb)
+void rt2x00queue_map_txskb(struct queue_entry *entry)
{
- struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
+ struct device *dev = entry->queue->rt2x00dev->dev;
+ struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
skbdesc->skb_dma =
- dma_map_single(rt2x00dev->dev, skb->data, skb->len, DMA_TO_DEVICE);
+ dma_map_single(dev, entry->skb->data, entry->skb->len, DMA_TO_DEVICE);
skbdesc->flags |= SKBDESC_DMA_MAPPED_TX;
}
EXPORT_SYMBOL_GPL(rt2x00queue_map_txskb);
-void rt2x00queue_unmap_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb)
+void rt2x00queue_unmap_skb(struct queue_entry *entry)
{
- struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
+ struct device *dev = entry->queue->rt2x00dev->dev;
+ struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
if (skbdesc->flags & SKBDESC_DMA_MAPPED_RX) {
- dma_unmap_single(rt2x00dev->dev, skbdesc->skb_dma, skb->len,
+ dma_unmap_single(dev, skbdesc->skb_dma, entry->skb->len,
DMA_FROM_DEVICE);
skbdesc->flags &= ~SKBDESC_DMA_MAPPED_RX;
- }
-
- if (skbdesc->flags & SKBDESC_DMA_MAPPED_TX) {
- dma_unmap_single(rt2x00dev->dev, skbdesc->skb_dma, skb->len,
+ } else if (skbdesc->flags & SKBDESC_DMA_MAPPED_TX) {
+ dma_unmap_single(dev, skbdesc->skb_dma, entry->skb->len,
DMA_TO_DEVICE);
skbdesc->flags &= ~SKBDESC_DMA_MAPPED_TX;
}
}
EXPORT_SYMBOL_GPL(rt2x00queue_unmap_skb);
-void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb)
+void rt2x00queue_free_skb(struct queue_entry *entry)
{
- if (!skb)
+ if (!entry->skb)
return;
- rt2x00queue_unmap_skb(rt2x00dev, skb);
- dev_kfree_skb_any(skb);
+ rt2x00queue_unmap_skb(entry);
+ dev_kfree_skb_any(entry->skb);
+ entry->skb = NULL;
}
void rt2x00queue_align_frame(struct sk_buff *skb)
@@ -311,7 +313,7 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
/*
* Initialize information from queue
*/
- txdesc->queue = entry->queue->qid;
+ txdesc->qid = entry->queue->qid;
txdesc->cw_min = entry->queue->cw_min;
txdesc->cw_max = entry->queue->cw_max;
txdesc->aifs = entry->queue->aifs;
@@ -439,7 +441,7 @@ static int rt2x00queue_write_tx_data(struct queue_entry *entry,
* Map the skb to DMA.
*/
if (test_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags))
- rt2x00queue_map_txskb(rt2x00dev, entry->skb);
+ rt2x00queue_map_txskb(entry);
return 0;
}
@@ -448,15 +450,14 @@ static void rt2x00queue_write_tx_descriptor(struct queue_entry *entry,
struct txentry_desc *txdesc)
{
struct data_queue *queue = entry->queue;
- struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
- rt2x00dev->ops->lib->write_tx_desc(rt2x00dev, entry->skb, txdesc);
+ queue->rt2x00dev->ops->lib->write_tx_desc(entry, txdesc);
/*
* All processing on the frame has been completed, this means
* it is now ready to be dumped to userspace through debugfs.
*/
- rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_TX, entry->skb);
+ rt2x00debug_dump_frame(queue->rt2x00dev, DUMP_FRAME_TX, entry->skb);
}
static void rt2x00queue_kick_tx_queue(struct queue_entry *entry,
@@ -476,7 +477,7 @@ static void rt2x00queue_kick_tx_queue(struct queue_entry *entry,
*/
if (rt2x00queue_threshold(queue) ||
!test_bit(ENTRY_TXD_BURST, &txdesc->flags))
- rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, queue->qid);
+ rt2x00dev->ops->lib->kick_tx_queue(queue);
}
int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
@@ -491,7 +492,8 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
if (unlikely(rt2x00queue_full(queue)))
return -ENOBUFS;
- if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) {
+ if (unlikely(test_and_set_bit(ENTRY_OWNER_DEVICE_DATA,
+ &entry->flags))) {
ERROR(queue->rt2x00dev,
"Arrived at non-free entry in the non-full queue %d.\n"
"Please file bug report to %s.\n",
@@ -586,11 +588,10 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
/*
* Clean up the beacon skb.
*/
- rt2x00queue_free_skb(rt2x00dev, intf->beacon->skb);
- intf->beacon->skb = NULL;
+ rt2x00queue_free_skb(intf->beacon);
if (!enable_beacon) {
- rt2x00dev->ops->lib->kill_tx_queue(rt2x00dev, QID_BEACON);
+ rt2x00dev->ops->lib->kill_tx_queue(intf->beacon->queue);
mutex_unlock(&intf->beacon_skb_mutex);
return 0;
}
@@ -625,6 +626,51 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
return 0;
}
+void rt2x00queue_for_each_entry(struct data_queue *queue,
+ enum queue_index start,
+ enum queue_index end,
+ void (*fn)(struct queue_entry *entry))
+{
+ unsigned long irqflags;
+ unsigned int index_start;
+ unsigned int index_end;
+ unsigned int i;
+
+ if (unlikely(start >= Q_INDEX_MAX || end >= Q_INDEX_MAX)) {
+ ERROR(queue->rt2x00dev,
+ "Entry requested from invalid index range (%d - %d)\n",
+ start, end);
+ return;
+ }
+
+ /*
+ * Only protect the range we are going to loop over,
+ * if during our loop a extra entry is set to pending
+ * it should not be kicked during this run, since it
+ * is part of another TX operation.
+ */
+ spin_lock_irqsave(&queue->lock, irqflags);
+ index_start = queue->index[start];
+ index_end = queue->index[end];
+ spin_unlock_irqrestore(&queue->lock, irqflags);
+
+ /*
+ * Start from the TX done pointer, this guarentees that we will
+ * send out all frames in the correct order.
+ */
+ if (index_start < index_end) {
+ for (i = index_start; i < index_end; i++)
+ fn(&queue->entries[i]);
+ } else {
+ for (i = index_start; i < queue->limit; i++)
+ fn(&queue->entries[i]);
+
+ for (i = 0; i < index_end; i++)
+ fn(&queue->entries[i]);
+ }
+}
+EXPORT_SYMBOL_GPL(rt2x00queue_for_each_entry);
+
struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev,
const enum data_queue_qid queue)
{
@@ -686,13 +732,13 @@ void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index)
if (queue->index[index] >= queue->limit)
queue->index[index] = 0;
+ queue->last_action[index] = jiffies;
+
if (index == Q_INDEX) {
queue->length++;
- queue->last_index = jiffies;
} else if (index == Q_INDEX_DONE) {
queue->length--;
queue->count++;
- queue->last_index_done = jiffies;
}
spin_unlock_irqrestore(&queue->lock, irqflags);
@@ -701,14 +747,17 @@ void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index)
static void rt2x00queue_reset(struct data_queue *queue)
{
unsigned long irqflags;
+ unsigned int i;
spin_lock_irqsave(&queue->lock, irqflags);
queue->count = 0;
queue->length = 0;
- queue->last_index = jiffies;
- queue->last_index_done = jiffies;
- memset(queue->index, 0, sizeof(queue->index));
+
+ for (i = 0; i < Q_INDEX_MAX; i++) {
+ queue->index[i] = 0;
+ queue->last_action[i] = jiffies;
+ }
spin_unlock_irqrestore(&queue->lock, irqflags);
}
@@ -718,7 +767,7 @@ void rt2x00queue_stop_queues(struct rt2x00_dev *rt2x00dev)
struct data_queue *queue;
txall_queue_for_each(rt2x00dev, queue)
- rt2x00dev->ops->lib->kill_tx_queue(rt2x00dev, queue->qid);
+ rt2x00dev->ops->lib->kill_tx_queue(queue);
}
void rt2x00queue_init_queues(struct rt2x00_dev *rt2x00dev)
@@ -730,9 +779,9 @@ void rt2x00queue_init_queues(struct rt2x00_dev *rt2x00dev)
rt2x00queue_reset(queue);
for (i = 0; i < queue->limit; i++) {
- queue->entries[i].flags = 0;
-
rt2x00dev->ops->lib->clear_entry(&queue->entries[i]);
+ if (queue->qid == QID_RX)
+ rt2x00queue_index_inc(queue, Q_INDEX);
}
}
}
@@ -755,7 +804,7 @@ static int rt2x00queue_alloc_entries(struct data_queue *queue,
* Allocate all queue entries.
*/
entry_size = sizeof(*entries) + qdesc->priv_size;
- entries = kzalloc(queue->limit * entry_size, GFP_KERNEL);
+ entries = kcalloc(queue->limit, entry_size, GFP_KERNEL);
if (!entries)
return -ENOMEM;
@@ -780,8 +829,7 @@ static int rt2x00queue_alloc_entries(struct data_queue *queue,
return 0;
}
-static void rt2x00queue_free_skbs(struct rt2x00_dev *rt2x00dev,
- struct data_queue *queue)
+static void rt2x00queue_free_skbs(struct data_queue *queue)
{
unsigned int i;
@@ -789,19 +837,17 @@ static void rt2x00queue_free_skbs(struct rt2x00_dev *rt2x00dev,
return;
for (i = 0; i < queue->limit; i++) {
- if (queue->entries[i].skb)
- rt2x00queue_free_skb(rt2x00dev, queue->entries[i].skb);
+ rt2x00queue_free_skb(&queue->entries[i]);
}
}
-static int rt2x00queue_alloc_rxskbs(struct rt2x00_dev *rt2x00dev,
- struct data_queue *queue)
+static int rt2x00queue_alloc_rxskbs(struct data_queue *queue)
{
unsigned int i;
struct sk_buff *skb;
for (i = 0; i < queue->limit; i++) {
- skb = rt2x00queue_alloc_rxskb(rt2x00dev, &queue->entries[i]);
+ skb = rt2x00queue_alloc_rxskb(&queue->entries[i]);
if (!skb)
return -ENOMEM;
queue->entries[i].skb = skb;
@@ -836,7 +882,7 @@ int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev)
goto exit;
}
- status = rt2x00queue_alloc_rxskbs(rt2x00dev, rt2x00dev->rx);
+ status = rt2x00queue_alloc_rxskbs(rt2x00dev->rx);
if (status)
goto exit;
@@ -854,7 +900,7 @@ void rt2x00queue_uninitialize(struct rt2x00_dev *rt2x00dev)
{
struct data_queue *queue;
- rt2x00queue_free_skbs(rt2x00dev, rt2x00dev->rx);
+ rt2x00queue_free_skbs(rt2x00dev->rx);
queue_for_each(rt2x00dev, queue) {
kfree(queue->entries);
@@ -891,7 +937,7 @@ int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev)
*/
rt2x00dev->data_queues = 2 + rt2x00dev->ops->tx_queues + req_atim;
- queue = kzalloc(rt2x00dev->data_queues * sizeof(*queue), GFP_KERNEL);
+ queue = kcalloc(rt2x00dev->data_queues, sizeof(*queue), GFP_KERNEL);
if (!queue) {
ERROR(rt2x00dev, "Queue allocation failed.\n");
return -ENOMEM;
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h
index 191e7775a9c0..d81d85f34866 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.h
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+ Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
<http://rt2x00.serialmonkey.com>
This program is free software; you can redistribute it and/or modify
@@ -268,6 +268,7 @@ struct txdone_entry_desc {
* @ENTRY_TXD_HT_AMPDU: This frame is part of an AMPDU.
* @ENTRY_TXD_HT_BW_40: Use 40MHz Bandwidth.
* @ENTRY_TXD_HT_SHORT_GI: Use short GI.
+ * @ENTRY_TXD_HT_MIMO_PS: The receiving STA is in dynamic SM PS mode.
*/
enum txentry_desc_flags {
ENTRY_TXD_RTS_FRAME,
@@ -286,6 +287,7 @@ enum txentry_desc_flags {
ENTRY_TXD_HT_AMPDU,
ENTRY_TXD_HT_BW_40,
ENTRY_TXD_HT_SHORT_GI,
+ ENTRY_TXD_HT_MIMO_PS,
};
/**
@@ -294,7 +296,7 @@ enum txentry_desc_flags {
* Summary of information for the frame descriptor before sending a TX frame.
*
* @flags: Descriptor flags (See &enum queue_entry_flags).
- * @queue: Queue identification (See &enum data_queue_qid).
+ * @qid: Queue identification (See &enum data_queue_qid).
* @length: Length of the entire frame.
* @header_length: Length of 802.11 header.
* @length_high: PLCP length high word.
@@ -320,7 +322,7 @@ enum txentry_desc_flags {
struct txentry_desc {
unsigned long flags;
- enum data_queue_qid queue;
+ enum data_queue_qid qid;
u16 length;
u16 header_length;
@@ -358,17 +360,17 @@ struct txentry_desc {
* @ENTRY_OWNER_DEVICE_DATA: This entry is owned by the device for data
* transfer (either TX or RX depending on the queue). The entry should
* only be touched after the device has signaled it is done with it.
- * @ENTRY_OWNER_DEVICE_CRYPTO: This entry is owned by the device for data
- * encryption or decryption. The entry should only be touched after
- * the device has signaled it is done with it.
* @ENTRY_DATA_PENDING: This entry contains a valid frame and is waiting
* for the signal to start sending.
+ * @ENTRY_DATA_IO_FAILED: Hardware indicated that an IO error occured
+ * while transfering the data to the hardware. No TX status report will
+ * be expected from the hardware.
*/
enum queue_entry_flags {
ENTRY_BCN_ASSIGNED,
ENTRY_OWNER_DEVICE_DATA,
- ENTRY_OWNER_DEVICE_CRYPTO,
ENTRY_DATA_PENDING,
+ ENTRY_DATA_IO_FAILED
};
/**
@@ -399,18 +401,18 @@ struct queue_entry {
*
* @Q_INDEX: Index pointer to the current entry in the queue, if this entry is
* owned by the hardware then the queue is considered to be full.
+ * @Q_INDEX_DMA_DONE: Index pointer for the next entry which will have been
+ * transfered to the hardware.
* @Q_INDEX_DONE: Index pointer to the next entry which will be completed by
* the hardware and for which we need to run the txdone handler. If this
* entry is not owned by the hardware the queue is considered to be empty.
- * @Q_INDEX_CRYPTO: Index pointer to the next entry which encryption/decription
- * will be completed by the hardware next.
* @Q_INDEX_MAX: Keep last, used in &struct data_queue to determine the size
* of the index array.
*/
enum queue_index {
Q_INDEX,
+ Q_INDEX_DMA_DONE,
Q_INDEX_DONE,
- Q_INDEX_CRYPTO,
Q_INDEX_MAX,
};
@@ -446,13 +448,12 @@ struct data_queue {
enum data_queue_qid qid;
spinlock_t lock;
- unsigned long last_index;
- unsigned long last_index_done;
unsigned int count;
unsigned short limit;
unsigned short threshold;
unsigned short length;
unsigned short index[Q_INDEX_MAX];
+ unsigned long last_action[Q_INDEX_MAX];
unsigned short txop;
unsigned short aifs;
@@ -565,6 +566,22 @@ struct data_queue_desc {
queue_loop(__entry, (__dev)->tx, queue_end(__dev))
/**
+ * rt2x00queue_for_each_entry - Loop through all entries in the queue
+ * @queue: Pointer to @data_queue
+ * @start: &enum queue_index Pointer to start index
+ * @end: &enum queue_index Pointer to end index
+ * @fn: The function to call for each &struct queue_entry
+ *
+ * This will walk through all entries in the queue, in chronological
+ * order. This means it will start at the current @start pointer
+ * and will walk through the queue until it reaches the @end pointer.
+ */
+void rt2x00queue_for_each_entry(struct data_queue *queue,
+ enum queue_index start,
+ enum queue_index end,
+ void (*fn)(struct queue_entry *entry));
+
+/**
* rt2x00queue_empty - Check if the queue is empty.
* @queue: Queue to check if empty.
*/
@@ -601,12 +618,23 @@ static inline int rt2x00queue_threshold(struct data_queue *queue)
}
/**
- * rt2x00queue_timeout - Check if a timeout occured for this queue
+ * rt2x00queue_timeout - Check if a timeout occured for STATUS reorts
* @queue: Queue to check.
*/
static inline int rt2x00queue_timeout(struct data_queue *queue)
{
- return time_after(queue->last_index, queue->last_index_done + (HZ / 10));
+ return time_after(queue->last_action[Q_INDEX_DMA_DONE],
+ queue->last_action[Q_INDEX_DONE] + (HZ / 10));
+}
+
+/**
+ * rt2x00queue_timeout - Check if a timeout occured for DMA transfers
+ * @queue: Queue to check.
+ */
+static inline int rt2x00queue_dma_timeout(struct data_queue *queue)
+{
+ return time_after(queue->last_action[Q_INDEX],
+ queue->last_action[Q_INDEX_DMA_DONE] + (HZ / 10));
}
/**
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index ff3a36622d1b..b3317df7a7d4 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -1,5 +1,6 @@
/*
- Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+ Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
+ Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
<http://rt2x00.serialmonkey.com>
This program is free software; you can redistribute it and/or modify
@@ -167,137 +168,137 @@ EXPORT_SYMBOL_GPL(rt2x00usb_regbusy_read);
/*
* TX data handlers.
*/
-static void rt2x00usb_interrupt_txdone(struct urb *urb)
+static void rt2x00usb_work_txdone_entry(struct queue_entry *entry)
{
- struct queue_entry *entry = (struct queue_entry *)urb->context;
- struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
- struct txdone_entry_desc txdesc;
-
- if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) ||
- !test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
- return;
-
/*
- * Obtain the status about this packet.
- * Note that when the status is 0 it does not mean the
+ * If the transfer to hardware succeeded, it does not mean the
* frame was send out correctly. It only means the frame
* was succesfully pushed to the hardware, we have no
* way to determine the transmission status right now.
* (Only indirectly by looking at the failed TX counters
* in the register).
*/
- txdesc.flags = 0;
- if (!urb->status)
- __set_bit(TXDONE_UNKNOWN, &txdesc.flags);
+ if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
+ rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE);
else
- __set_bit(TXDONE_FAILURE, &txdesc.flags);
- txdesc.retry = 0;
-
- rt2x00lib_txdone(entry, &txdesc);
+ rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN);
}
-static inline void rt2x00usb_kick_tx_entry(struct queue_entry *entry)
+static void rt2x00usb_work_txdone(struct work_struct *work)
{
- struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
- struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
- struct queue_entry_priv_usb *entry_priv = entry->priv_data;
- u32 length;
+ struct rt2x00_dev *rt2x00dev =
+ container_of(work, struct rt2x00_dev, txdone_work);
+ struct data_queue *queue;
+ struct queue_entry *entry;
- if (test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags)) {
- /*
- * USB devices cannot blindly pass the skb->len as the
- * length of the data to usb_fill_bulk_urb. Pass the skb
- * to the driver to determine what the length should be.
- */
- length = rt2x00dev->ops->lib->get_tx_data_len(entry);
+ tx_queue_for_each(rt2x00dev, queue) {
+ while (!rt2x00queue_empty(queue)) {
+ entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
- usb_fill_bulk_urb(entry_priv->urb, usb_dev,
- usb_sndbulkpipe(usb_dev, entry->queue->usb_endpoint),
- entry->skb->data, length,
- rt2x00usb_interrupt_txdone, entry);
+ if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
+ break;
- usb_submit_urb(entry_priv->urb, GFP_ATOMIC);
+ rt2x00usb_work_txdone_entry(entry);
+ }
}
}
-void rt2x00usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
- const enum data_queue_qid qid)
+static void rt2x00usb_interrupt_txdone(struct urb *urb)
{
- struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, qid);
- unsigned long irqflags;
- unsigned int index;
- unsigned int index_done;
- unsigned int i;
+ struct queue_entry *entry = (struct queue_entry *)urb->context;
+ struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+
+ if (!test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
+ return;
/*
- * Only protect the range we are going to loop over,
- * if during our loop a extra entry is set to pending
- * it should not be kicked during this run, since it
- * is part of another TX operation.
+ * Report the frame as DMA done
*/
- spin_lock_irqsave(&queue->lock, irqflags);
- index = queue->index[Q_INDEX];
- index_done = queue->index[Q_INDEX_DONE];
- spin_unlock_irqrestore(&queue->lock, irqflags);
+ rt2x00lib_dmadone(entry);
/*
- * Start from the TX done pointer, this guarentees that we will
- * send out all frames in the correct order.
+ * Check if the frame was correctly uploaded
*/
- if (index_done < index) {
- for (i = index_done; i < index; i++)
- rt2x00usb_kick_tx_entry(&queue->entries[i]);
- } else {
- for (i = index_done; i < queue->limit; i++)
- rt2x00usb_kick_tx_entry(&queue->entries[i]);
+ if (urb->status)
+ set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
- for (i = 0; i < index; i++)
- rt2x00usb_kick_tx_entry(&queue->entries[i]);
- }
+ /*
+ * Schedule the delayed work for reading the TX status
+ * from the device.
+ */
+ if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) &&
+ test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+ ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->txdone_work);
}
-EXPORT_SYMBOL_GPL(rt2x00usb_kick_tx_queue);
-void rt2x00usb_kill_tx_queue(struct rt2x00_dev *rt2x00dev,
- const enum data_queue_qid qid)
+static void rt2x00usb_kick_tx_entry(struct queue_entry *entry)
{
- struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, qid);
- struct queue_entry_priv_usb *entry_priv;
- struct queue_entry_priv_usb_bcn *bcn_priv;
- unsigned int i;
- bool kill_guard;
+ struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+ struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
+ struct queue_entry_priv_usb *entry_priv = entry->priv_data;
+ u32 length;
+
+ if (!test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags))
+ return;
/*
- * When killing the beacon queue, we must also kill
- * the beacon guard byte.
+ * USB devices cannot blindly pass the skb->len as the
+ * length of the data to usb_fill_bulk_urb. Pass the skb
+ * to the driver to determine what the length should be.
*/
- kill_guard =
- (qid == QID_BEACON) &&
- (test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags));
+ length = rt2x00dev->ops->lib->get_tx_data_len(entry);
+
+ usb_fill_bulk_urb(entry_priv->urb, usb_dev,
+ usb_sndbulkpipe(usb_dev, entry->queue->usb_endpoint),
+ entry->skb->data, length,
+ rt2x00usb_interrupt_txdone, entry);
+
+ if (usb_submit_urb(entry_priv->urb, GFP_ATOMIC)) {
+ set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
+ rt2x00lib_dmadone(entry);
+ }
+}
+
+void rt2x00usb_kick_tx_queue(struct data_queue *queue)
+{
+ rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX,
+ rt2x00usb_kick_tx_entry);
+}
+EXPORT_SYMBOL_GPL(rt2x00usb_kick_tx_queue);
+
+static void rt2x00usb_kill_tx_entry(struct queue_entry *entry)
+{
+ struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+ struct queue_entry_priv_usb *entry_priv = entry->priv_data;
+ struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data;
+
+ if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
+ return;
+
+ usb_kill_urb(entry_priv->urb);
/*
- * Cancel all entries.
+ * Kill guardian urb (if required by driver).
*/
- for (i = 0; i < queue->limit; i++) {
- entry_priv = queue->entries[i].priv_data;
- usb_kill_urb(entry_priv->urb);
+ if ((entry->queue->qid == QID_BEACON) &&
+ (test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags)))
+ usb_kill_urb(bcn_priv->guardian_urb);
+}
- /*
- * Kill guardian urb (if required by driver).
- */
- if (kill_guard) {
- bcn_priv = queue->entries[i].priv_data;
- usb_kill_urb(bcn_priv->guardian_urb);
- }
- }
+void rt2x00usb_kill_tx_queue(struct data_queue *queue)
+{
+ rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX,
+ rt2x00usb_kill_tx_entry);
}
EXPORT_SYMBOL_GPL(rt2x00usb_kill_tx_queue);
-static void rt2x00usb_watchdog_reset_tx(struct data_queue *queue)
+static void rt2x00usb_watchdog_tx_dma(struct data_queue *queue)
{
- struct queue_entry_priv_usb *entry_priv;
+ struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
unsigned short threshold = queue->threshold;
- WARNING(queue->rt2x00dev, "TX queue %d timed out, invoke reset", queue->qid);
+ WARNING(queue->rt2x00dev, "TX queue %d DMA timed out,"
+ " invoke forced forced reset", queue->qid);
/*
* Temporarily disable the TX queue, this will force mac80211
@@ -307,20 +308,33 @@ static void rt2x00usb_watchdog_reset_tx(struct data_queue *queue)
* queue from being enabled during the txdone handler.
*/
queue->threshold = queue->limit;
- ieee80211_stop_queue(queue->rt2x00dev->hw, queue->qid);
+ ieee80211_stop_queue(rt2x00dev->hw, queue->qid);
/*
- * Reset all currently uploaded TX frames.
+ * Kill all entries in the queue, afterwards we need to
+ * wait a bit for all URBs to be cancelled.
*/
- while (!rt2x00queue_empty(queue)) {
- entry_priv = rt2x00queue_get_entry(queue, Q_INDEX_DONE)->priv_data;
- usb_kill_urb(entry_priv->urb);
+ rt2x00usb_kill_tx_queue(queue);
- /*
- * We need a short delay here to wait for
- * the URB to be canceled and invoked the tx_done handler.
- */
- udelay(200);
+ /*
+ * In case that a driver has overriden the txdone_work
+ * function, we invoke the TX done through there.
+ */
+ rt2x00dev->txdone_work.func(&rt2x00dev->txdone_work);
+
+ /*
+ * Security measure: if the driver did override the
+ * txdone_work function, and the hardware did arrive
+ * in a state which causes it to malfunction, it is
+ * possible that the driver couldn't handle the txdone
+ * event correctly. So after giving the driver the
+ * chance to cleanup, we now force a cleanup of any
+ * leftovers.
+ */
+ if (!rt2x00queue_empty(queue)) {
+ WARNING(queue->rt2x00dev, "TX queue %d DMA timed out,"
+ " status handling failed, invoke hard reset", queue->qid);
+ rt2x00usb_work_txdone(&rt2x00dev->txdone_work);
}
/*
@@ -328,7 +342,15 @@ static void rt2x00usb_watchdog_reset_tx(struct data_queue *queue)
* queue again.
*/
queue->threshold = threshold;
- ieee80211_wake_queue(queue->rt2x00dev->hw, queue->qid);
+ ieee80211_wake_queue(rt2x00dev->hw, queue->qid);
+}
+
+static void rt2x00usb_watchdog_tx_status(struct data_queue *queue)
+{
+ WARNING(queue->rt2x00dev, "TX queue %d status timed out,"
+ " invoke forced tx handler", queue->qid);
+
+ ieee80211_queue_work(queue->rt2x00dev->hw, &queue->rt2x00dev->txdone_work);
}
void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev)
@@ -336,8 +358,12 @@ void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev)
struct data_queue *queue;
tx_queue_for_each(rt2x00dev, queue) {
- if (rt2x00queue_timeout(queue))
- rt2x00usb_watchdog_reset_tx(queue);
+ if (!rt2x00queue_empty(queue)) {
+ if (rt2x00queue_dma_timeout(queue))
+ rt2x00usb_watchdog_tx_dma(queue);
+ if (rt2x00queue_timeout(queue))
+ rt2x00usb_watchdog_tx_status(queue);
+ }
}
}
EXPORT_SYMBOL_GPL(rt2x00usb_watchdog);
@@ -345,38 +371,62 @@ EXPORT_SYMBOL_GPL(rt2x00usb_watchdog);
/*
* RX data handlers.
*/
+static void rt2x00usb_work_rxdone(struct work_struct *work)
+{
+ struct rt2x00_dev *rt2x00dev =
+ container_of(work, struct rt2x00_dev, rxdone_work);
+ struct queue_entry *entry;
+ struct skb_frame_desc *skbdesc;
+ u8 rxd[32];
+
+ while (!rt2x00queue_empty(rt2x00dev->rx)) {
+ entry = rt2x00queue_get_entry(rt2x00dev->rx, Q_INDEX_DONE);
+
+ if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
+ break;
+
+ /*
+ * Fill in desc fields of the skb descriptor
+ */
+ skbdesc = get_skb_frame_desc(entry->skb);
+ skbdesc->desc = rxd;
+ skbdesc->desc_len = entry->queue->desc_size;
+
+ /*
+ * Send the frame to rt2x00lib for further processing.
+ */
+ rt2x00lib_rxdone(entry);
+ }
+}
+
static void rt2x00usb_interrupt_rxdone(struct urb *urb)
{
struct queue_entry *entry = (struct queue_entry *)urb->context;
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
- struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
- u8 rxd[32];
- if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) ||
- !test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
+ if (!test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
return;
/*
- * Check if the received data is simply too small
- * to be actually valid, or if the urb is signaling
- * a problem.
+ * Report the frame as DMA done
*/
- if (urb->actual_length < entry->queue->desc_size || urb->status) {
- set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
- usb_submit_urb(urb, GFP_ATOMIC);
- return;
- }
+ rt2x00lib_dmadone(entry);
/*
- * Fill in desc fields of the skb descriptor
+ * Check if the received data is simply too small
+ * to be actually valid, or if the urb is signaling
+ * a problem.
*/
- skbdesc->desc = rxd;
- skbdesc->desc_len = entry->queue->desc_size;
+ if (urb->actual_length < entry->queue->desc_size || urb->status)
+ set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
/*
- * Send the frame to rt2x00lib for further processing.
+ * Schedule the delayed work for reading the RX status
+ * from the device.
*/
- rt2x00lib_rxdone(rt2x00dev, entry);
+ if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) &&
+ test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+ ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->rxdone_work);
}
/*
@@ -391,7 +441,7 @@ void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev)
* The USB version of kill_tx_queue also works
* on the RX queue.
*/
- rt2x00dev->ops->lib->kill_tx_queue(rt2x00dev, QID_RX);
+ rt2x00dev->ops->lib->kill_tx_queue(rt2x00dev->rx);
}
EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio);
@@ -405,6 +455,8 @@ void rt2x00usb_clear_entry(struct queue_entry *entry)
struct queue_entry_priv_usb *entry_priv = entry->priv_data;
int pipe;
+ entry->flags = 0;
+
if (entry->queue->qid == QID_RX) {
pipe = usb_rcvbulkpipe(usb_dev, entry->queue->usb_endpoint);
usb_fill_bulk_urb(entry_priv->urb, usb_dev, pipe,
@@ -412,9 +464,10 @@ void rt2x00usb_clear_entry(struct queue_entry *entry)
rt2x00usb_interrupt_rxdone, entry);
set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
- usb_submit_urb(entry_priv->urb, GFP_ATOMIC);
- } else {
- entry->flags = 0;
+ if (usb_submit_urb(entry_priv->urb, GFP_ATOMIC)) {
+ set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
+ rt2x00lib_dmadone(entry);
+ }
}
}
EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry);
@@ -489,9 +542,9 @@ static int rt2x00usb_find_endpoints(struct rt2x00_dev *rt2x00dev)
return 0;
}
-static int rt2x00usb_alloc_urb(struct rt2x00_dev *rt2x00dev,
- struct data_queue *queue)
+static int rt2x00usb_alloc_entries(struct data_queue *queue)
{
+ struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
struct queue_entry_priv_usb *entry_priv;
struct queue_entry_priv_usb_bcn *bcn_priv;
unsigned int i;
@@ -508,7 +561,7 @@ static int rt2x00usb_alloc_urb(struct rt2x00_dev *rt2x00dev,
* no guardian byte was required for the beacon,
* then we are done.
*/
- if (rt2x00dev->bcn != queue ||
+ if (queue->qid != QID_BEACON ||
!test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags))
return 0;
@@ -522,9 +575,9 @@ static int rt2x00usb_alloc_urb(struct rt2x00_dev *rt2x00dev,
return 0;
}
-static void rt2x00usb_free_urb(struct rt2x00_dev *rt2x00dev,
- struct data_queue *queue)
+static void rt2x00usb_free_entries(struct data_queue *queue)
{
+ struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
struct queue_entry_priv_usb *entry_priv;
struct queue_entry_priv_usb_bcn *bcn_priv;
unsigned int i;
@@ -543,7 +596,7 @@ static void rt2x00usb_free_urb(struct rt2x00_dev *rt2x00dev,
* no guardian byte was required for the beacon,
* then we are done.
*/
- if (rt2x00dev->bcn != queue ||
+ if (queue->qid != QID_BEACON ||
!test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags))
return;
@@ -570,7 +623,7 @@ int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev)
* Allocate DMA
*/
queue_for_each(rt2x00dev, queue) {
- status = rt2x00usb_alloc_urb(rt2x00dev, queue);
+ status = rt2x00usb_alloc_entries(queue);
if (status)
goto exit;
}
@@ -589,7 +642,7 @@ void rt2x00usb_uninitialize(struct rt2x00_dev *rt2x00dev)
struct data_queue *queue;
queue_for_each(rt2x00dev, queue)
- rt2x00usb_free_urb(rt2x00dev, queue);
+ rt2x00usb_free_entries(queue);
}
EXPORT_SYMBOL_GPL(rt2x00usb_uninitialize);
@@ -659,6 +712,9 @@ int rt2x00usb_probe(struct usb_interface *usb_intf,
rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_USB);
+ INIT_WORK(&rt2x00dev->rxdone_work, rt2x00usb_work_rxdone);
+ INIT_WORK(&rt2x00dev->txdone_work, rt2x00usb_work_txdone);
+
retval = rt2x00usb_alloc_reg(rt2x00dev);
if (retval)
goto exit_free_device;
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h
index d3d3ddc40875..c2d997f67b3e 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.h
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.h
@@ -379,25 +379,21 @@ struct queue_entry_priv_usb_bcn {
/**
* rt2x00usb_kick_tx_queue - Kick data queue
- * @rt2x00dev: Pointer to &struct rt2x00_dev
- * @qid: Data queue to kick
+ * @queue: Data queue to kick
*
* This will walk through all entries of the queue and push all pending
* frames to the hardware as a single burst.
*/
-void rt2x00usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
- const enum data_queue_qid qid);
+void rt2x00usb_kick_tx_queue(struct data_queue *queue);
/**
* rt2x00usb_kill_tx_queue - Kill data queue
- * @rt2x00dev: Pointer to &struct rt2x00_dev
- * @qid: Data queue to kill
+ * @queue: Data queue to kill
*
* This will walk through all entries of the queue and kill all
* previously kicked frames before they can be send.
*/
-void rt2x00usb_kill_tx_queue(struct rt2x00_dev *rt2x00dev,
- const enum data_queue_qid qid);
+void rt2x00usb_kill_tx_queue(struct data_queue *queue);
/**
* rt2x00usb_watchdog - Watchdog for USB communication
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index e539c6cb636f..af548c87f108 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -594,7 +594,8 @@ static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev,
}
static void rt61pci_config_erp(struct rt2x00_dev *rt2x00dev,
- struct rt2x00lib_erp *erp)
+ struct rt2x00lib_erp *erp,
+ u32 changed)
{
u32 reg;
@@ -603,28 +604,36 @@ static void rt61pci_config_erp(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER);
rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, &reg);
- rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_ENABLE, 1);
- rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_PREAMBLE,
- !!erp->short_preamble);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg);
+ if (changed & BSS_CHANGED_ERP_PREAMBLE) {
+ rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, &reg);
+ rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_ENABLE, 1);
+ rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_PREAMBLE,
+ !!erp->short_preamble);
+ rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg);
+ }
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR5, erp->basic_rates);
+ if (changed & BSS_CHANGED_BASIC_RATES)
+ rt2x00pci_register_write(rt2x00dev, TXRX_CSR5,
+ erp->basic_rates);
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
- rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL,
- erp->beacon_int * 16);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
+ if (changed & BSS_CHANGED_BEACON_INT) {
+ rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
+ rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL,
+ erp->beacon_int * 16);
+ rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
+ }
- rt2x00pci_register_read(rt2x00dev, MAC_CSR9, &reg);
- rt2x00_set_field32(&reg, MAC_CSR9_SLOT_TIME, erp->slot_time);
- rt2x00pci_register_write(rt2x00dev, MAC_CSR9, reg);
+ if (changed & BSS_CHANGED_ERP_SLOT) {
+ rt2x00pci_register_read(rt2x00dev, MAC_CSR9, &reg);
+ rt2x00_set_field32(&reg, MAC_CSR9_SLOT_TIME, erp->slot_time);
+ rt2x00pci_register_write(rt2x00dev, MAC_CSR9, reg);
- rt2x00pci_register_read(rt2x00dev, MAC_CSR8, &reg);
- rt2x00_set_field32(&reg, MAC_CSR8_SIFS, erp->sifs);
- rt2x00_set_field32(&reg, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3);
- rt2x00_set_field32(&reg, MAC_CSR8_EIFS, erp->eifs);
- rt2x00pci_register_write(rt2x00dev, MAC_CSR8, reg);
+ rt2x00pci_register_read(rt2x00dev, MAC_CSR8, &reg);
+ rt2x00_set_field32(&reg, MAC_CSR8_SIFS, erp->sifs);
+ rt2x00_set_field32(&reg, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3);
+ rt2x00_set_field32(&reg, MAC_CSR8_EIFS, erp->eifs);
+ rt2x00pci_register_write(rt2x00dev, MAC_CSR8, reg);
+ }
}
static void rt61pci_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
@@ -1050,7 +1059,7 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev,
/*
* Determine r17 bounds.
*/
- if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) {
+ if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
low_bound = 0x28;
up_bound = 0x48;
if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) {
@@ -1645,6 +1654,7 @@ static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, &reg);
rt2x00_set_field32(&reg, INT_MASK_CSR_TXDONE, mask);
rt2x00_set_field32(&reg, INT_MASK_CSR_RXDONE, mask);
+ rt2x00_set_field32(&reg, INT_MASK_CSR_BEACON_DONE, mask);
rt2x00_set_field32(&reg, INT_MASK_CSR_ENABLE_MITIGATION, mask);
rt2x00_set_field32(&reg, INT_MASK_CSR_MITIGATION_PERIOD, 0xff);
rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
@@ -1658,6 +1668,7 @@ static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_5, mask);
rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_6, mask);
rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_7, mask);
+ rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_TWAKEUP, mask);
rt2x00pci_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg);
}
@@ -1766,12 +1777,11 @@ static int rt61pci_set_device_state(struct rt2x00_dev *rt2x00dev,
/*
* TX descriptor initialization
*/
-static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
- struct sk_buff *skb,
+static void rt61pci_write_tx_desc(struct queue_entry *entry,
struct txentry_desc *txdesc)
{
- struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
- struct queue_entry_priv_pci *entry_priv = skbdesc->entry->priv_data;
+ struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+ struct queue_entry_priv_pci *entry_priv = entry->priv_data;
__le32 *txd = entry_priv->desc;
u32 word;
@@ -1779,7 +1789,7 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
* Start writing the descriptor words.
*/
rt2x00_desc_read(txd, 1, &word);
- rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, txdesc->queue);
+ rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, txdesc->qid);
rt2x00_set_field32(&word, TXD_W1_AIFSN, txdesc->aifs);
rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min);
rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max);
@@ -1802,15 +1812,15 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
}
rt2x00_desc_read(txd, 5, &word);
- rt2x00_set_field32(&word, TXD_W5_PID_TYPE, skbdesc->entry->queue->qid);
+ rt2x00_set_field32(&word, TXD_W5_PID_TYPE, entry->queue->qid);
rt2x00_set_field32(&word, TXD_W5_PID_SUBTYPE,
skbdesc->entry->entry_idx);
rt2x00_set_field32(&word, TXD_W5_TX_POWER,
- TXPOWER_TO_DEV(rt2x00dev->tx_power));
+ TXPOWER_TO_DEV(entry->queue->rt2x00dev->tx_power));
rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1);
rt2x00_desc_write(txd, 5, word);
- if (txdesc->queue != QID_BEACON) {
+ if (txdesc->qid != QID_BEACON) {
rt2x00_desc_read(txd, 6, &word);
rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS,
skbdesc->skb_dma);
@@ -1857,7 +1867,7 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
*/
skbdesc->desc = txd;
skbdesc->desc_len =
- (txdesc->queue == QID_BEACON) ? TXINFO_SIZE : TXD_DESC_SIZE;
+ (txdesc->qid == QID_BEACON) ? TXINFO_SIZE : TXD_DESC_SIZE;
}
/*
@@ -1882,7 +1892,7 @@ static void rt61pci_write_beacon(struct queue_entry *entry,
/*
* Write the TX descriptor for the beacon.
*/
- rt61pci_write_tx_desc(rt2x00dev, entry->skb, txdesc);
+ rt61pci_write_tx_desc(entry, txdesc);
/*
* Dump beacon to userspace through debugfs.
@@ -1918,34 +1928,34 @@ static void rt61pci_write_beacon(struct queue_entry *entry,
entry->skb = NULL;
}
-static void rt61pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
- const enum data_queue_qid queue)
+static void rt61pci_kick_tx_queue(struct data_queue *queue)
{
+ struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
u32 reg;
rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
- rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC0, (queue == QID_AC_BE));
- rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC1, (queue == QID_AC_BK));
- rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC2, (queue == QID_AC_VI));
- rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC3, (queue == QID_AC_VO));
+ rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC0, (queue->qid == QID_AC_BE));
+ rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC1, (queue->qid == QID_AC_BK));
+ rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC2, (queue->qid == QID_AC_VI));
+ rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC3, (queue->qid == QID_AC_VO));
rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
}
-static void rt61pci_kill_tx_queue(struct rt2x00_dev *rt2x00dev,
- const enum data_queue_qid qid)
+static void rt61pci_kill_tx_queue(struct data_queue *queue)
{
+ struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
u32 reg;
- if (qid == QID_BEACON) {
+ if (queue->qid == QID_BEACON) {
rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, 0);
return;
}
rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
- rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC0, (qid == QID_AC_BE));
- rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC1, (qid == QID_AC_BK));
- rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC2, (qid == QID_AC_VI));
- rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC3, (qid == QID_AC_VO));
+ rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC0, (queue->qid == QID_AC_BE));
+ rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC1, (queue->qid == QID_AC_BK));
+ rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC2, (queue->qid == QID_AC_VI));
+ rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC3, (queue->qid == QID_AC_VO));
rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
}
@@ -1972,7 +1982,7 @@ static int rt61pci_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1)
return 0;
}
- if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) {
+ if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
if (lna == 3 || lna == 2)
offset += 10;
}
@@ -2107,11 +2117,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
"TX status report missed for entry %d\n",
entry_done->entry_idx);
- txdesc.flags = 0;
- __set_bit(TXDONE_UNKNOWN, &txdesc.flags);
- txdesc.retry = 0;
-
- rt2x00lib_txdone(entry_done, &txdesc);
+ rt2x00lib_txdone_noinfo(entry_done, TXDONE_UNKNOWN);
entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
}
@@ -2624,12 +2630,13 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
* As rt61 has a global fallback table we cannot specify
* more then one tx rate per frame but since the hw will
* try several rates (based on the fallback table) we should
- * still initialize max_rates to the maximum number of rates
+ * initialize max_report_rates to the maximum number of rates
* we are going to try. Otherwise mac80211 will truncate our
* reported tx rates and the rc algortihm will end up with
* incorrect data.
*/
- rt2x00dev->hw->max_rates = 7;
+ rt2x00dev->hw->max_rates = 1;
+ rt2x00dev->hw->max_report_rates = 7;
rt2x00dev->hw->max_rate_tries = 1;
/*
@@ -2654,20 +2661,24 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
/*
* Create channel information array
*/
- info = kzalloc(spec->num_channels * sizeof(*info), GFP_KERNEL);
+ info = kcalloc(spec->num_channels, sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
spec->channels_info = info;
tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_G_START);
- for (i = 0; i < 14; i++)
- info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+ for (i = 0; i < 14; i++) {
+ info[i].max_power = MAX_TXPOWER;
+ info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+ }
if (spec->num_channels > 14) {
tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START);
- for (i = 14; i < spec->num_channels; i++)
- info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+ for (i = 14; i < spec->num_channels; i++) {
+ info[i].max_power = MAX_TXPOWER;
+ info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+ }
}
return 0;
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index aa9de18fd410..9be8089317e4 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -545,7 +545,8 @@ static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev,
}
static void rt73usb_config_erp(struct rt2x00_dev *rt2x00dev,
- struct rt2x00lib_erp *erp)
+ struct rt2x00lib_erp *erp,
+ u32 changed)
{
u32 reg;
@@ -554,28 +555,36 @@ static void rt73usb_config_erp(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER);
rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
- rt2x00usb_register_read(rt2x00dev, TXRX_CSR4, &reg);
- rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_ENABLE, 1);
- rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_PREAMBLE,
- !!erp->short_preamble);
- rt2x00usb_register_write(rt2x00dev, TXRX_CSR4, reg);
+ if (changed & BSS_CHANGED_ERP_PREAMBLE) {
+ rt2x00usb_register_read(rt2x00dev, TXRX_CSR4, &reg);
+ rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_ENABLE, 1);
+ rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_PREAMBLE,
+ !!erp->short_preamble);
+ rt2x00usb_register_write(rt2x00dev, TXRX_CSR4, reg);
+ }
- rt2x00usb_register_write(rt2x00dev, TXRX_CSR5, erp->basic_rates);
+ if (changed & BSS_CHANGED_BASIC_RATES)
+ rt2x00usb_register_write(rt2x00dev, TXRX_CSR5,
+ erp->basic_rates);
- rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
- rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL,
- erp->beacon_int * 16);
- rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
+ if (changed & BSS_CHANGED_BEACON_INT) {
+ rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
+ rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL,
+ erp->beacon_int * 16);
+ rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
+ }
- rt2x00usb_register_read(rt2x00dev, MAC_CSR9, &reg);
- rt2x00_set_field32(&reg, MAC_CSR9_SLOT_TIME, erp->slot_time);
- rt2x00usb_register_write(rt2x00dev, MAC_CSR9, reg);
+ if (changed & BSS_CHANGED_ERP_SLOT) {
+ rt2x00usb_register_read(rt2x00dev, MAC_CSR9, &reg);
+ rt2x00_set_field32(&reg, MAC_CSR9_SLOT_TIME, erp->slot_time);
+ rt2x00usb_register_write(rt2x00dev, MAC_CSR9, reg);
- rt2x00usb_register_read(rt2x00dev, MAC_CSR8, &reg);
- rt2x00_set_field32(&reg, MAC_CSR8_SIFS, erp->sifs);
- rt2x00_set_field32(&reg, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3);
- rt2x00_set_field32(&reg, MAC_CSR8_EIFS, erp->eifs);
- rt2x00usb_register_write(rt2x00dev, MAC_CSR8, reg);
+ rt2x00usb_register_read(rt2x00dev, MAC_CSR8, &reg);
+ rt2x00_set_field32(&reg, MAC_CSR8_SIFS, erp->sifs);
+ rt2x00_set_field32(&reg, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3);
+ rt2x00_set_field32(&reg, MAC_CSR8_EIFS, erp->eifs);
+ rt2x00usb_register_write(rt2x00dev, MAC_CSR8, reg);
+ }
}
static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
@@ -929,7 +938,7 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev,
/*
* Determine r17 bounds.
*/
- if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) {
+ if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
low_bound = 0x28;
up_bound = 0x48;
@@ -1426,12 +1435,11 @@ static int rt73usb_set_device_state(struct rt2x00_dev *rt2x00dev,
/*
* TX descriptor initialization
*/
-static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
- struct sk_buff *skb,
+static void rt73usb_write_tx_desc(struct queue_entry *entry,
struct txentry_desc *txdesc)
{
- struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
- __le32 *txd = (__le32 *) skb->data;
+ struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+ __le32 *txd = (__le32 *) entry->skb->data;
u32 word;
/*
@@ -1464,7 +1472,7 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
rt2x00_desc_write(txd, 0, word);
rt2x00_desc_read(txd, 1, &word);
- rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, txdesc->queue);
+ rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, txdesc->qid);
rt2x00_set_field32(&word, TXD_W1_AIFSN, txdesc->aifs);
rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min);
rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max);
@@ -1487,7 +1495,7 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
rt2x00_desc_read(txd, 5, &word);
rt2x00_set_field32(&word, TXD_W5_TX_POWER,
- TXPOWER_TO_DEV(rt2x00dev->tx_power));
+ TXPOWER_TO_DEV(entry->queue->rt2x00dev->tx_power));
rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1);
rt2x00_desc_write(txd, 5, word);
@@ -1526,7 +1534,7 @@ static void rt73usb_write_beacon(struct queue_entry *entry,
/*
* Write the TX descriptor for the beacon.
*/
- rt73usb_write_tx_desc(rt2x00dev, entry->skb, txdesc);
+ rt73usb_write_tx_desc(entry, txdesc);
/*
* Dump beacon to userspace through debugfs.
@@ -1574,6 +1582,14 @@ static int rt73usb_get_tx_data_len(struct queue_entry *entry)
return length;
}
+static void rt73usb_kill_tx_queue(struct data_queue *queue)
+{
+ if (queue->qid == QID_BEACON)
+ rt2x00usb_register_write(queue->rt2x00dev, TXRX_CSR9, 0);
+
+ rt2x00usb_kill_tx_queue(queue);
+}
+
/*
* RX control handlers
*/
@@ -1597,7 +1613,7 @@ static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1)
return 0;
}
- if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) {
+ if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) {
if (lna == 3 || lna == 2)
offset += 10;
@@ -2047,9 +2063,14 @@ static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
/*
* Initialize all hw fields.
+ *
+ * Don't set IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING unless we are
+ * capable of sending the buffered frames out after the DTIM
+ * transmission using rt2x00lib_beacondone. This will send out
+ * multicast and broadcast traffic immediately instead of buffering it
+ * infinitly and thus dropping it after some time.
*/
rt2x00dev->hw->flags =
- IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
IEEE80211_HW_SIGNAL_DBM |
IEEE80211_HW_SUPPORTS_PS |
IEEE80211_HW_PS_NULLFUNC_STACK;
@@ -2084,20 +2105,24 @@ static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
/*
* Create channel information array
*/
- info = kzalloc(spec->num_channels * sizeof(*info), GFP_KERNEL);
+ info = kcalloc(spec->num_channels, sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
spec->channels_info = info;
tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_G_START);
- for (i = 0; i < 14; i++)
- info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+ for (i = 0; i < 14; i++) {
+ info[i].max_power = MAX_TXPOWER;
+ info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+ }
if (spec->num_channels > 14) {
tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START);
- for (i = 14; i < spec->num_channels; i++)
- info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+ for (i = 14; i < spec->num_channels; i++) {
+ info[i].max_power = MAX_TXPOWER;
+ info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+ }
}
return 0;
@@ -2259,7 +2284,7 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
.write_beacon = rt73usb_write_beacon,
.get_tx_data_len = rt73usb_get_tx_data_len,
.kick_tx_queue = rt2x00usb_kick_tx_queue,
- .kill_tx_queue = rt2x00usb_kill_tx_queue,
+ .kill_tx_queue = rt73usb_kill_tx_queue,
.fill_rxdone = rt73usb_fill_rxdone,
.config_shared_key = rt73usb_config_shared_key,
.config_pairwise_key = rt73usb_config_pairwise_key,
@@ -2345,6 +2370,7 @@ static struct usb_device_id rt73usb_device_table[] = {
{ USB_DEVICE(0x0411, 0x00f4), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x0411, 0x0116), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x0411, 0x0119), USB_DEVICE_DATA(&rt73usb_ops) },
+ { USB_DEVICE(0x0411, 0x0137), USB_DEVICE_DATA(&rt73usb_ops) },
/* CEIVA */
{ USB_DEVICE(0x178d, 0x02be), USB_DEVICE_DATA(&rt73usb_ops) },
/* CNet */
diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c
index 30107ce78dfb..707c688da618 100644
--- a/drivers/net/wireless/rtl818x/rtl8180_dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c
@@ -783,6 +783,7 @@ static void rtl8180_bss_info_changed(struct ieee80211_hw *dev,
struct rtl8180_priv *priv = dev->priv;
struct rtl8180_vif *vif_priv;
int i;
+ u8 reg;
vif_priv = (struct rtl8180_vif *)&vif->drv_priv;
@@ -791,12 +792,14 @@ static void rtl8180_bss_info_changed(struct ieee80211_hw *dev,
rtl818x_iowrite8(priv, &priv->map->BSSID[i],
info->bssid[i]);
- if (is_valid_ether_addr(info->bssid))
- rtl818x_iowrite8(priv, &priv->map->MSR,
- RTL818X_MSR_INFRA);
- else
- rtl818x_iowrite8(priv, &priv->map->MSR,
- RTL818X_MSR_NO_LINK);
+ if (is_valid_ether_addr(info->bssid)) {
+ if (vif->type == NL80211_IFTYPE_ADHOC)
+ reg = RTL818X_MSR_ADHOC;
+ else
+ reg = RTL818X_MSR_INFRA;
+ } else
+ reg = RTL818X_MSR_NO_LINK;
+ rtl818x_iowrite8(priv, &priv->map->MSR, reg);
}
if (changed & BSS_CHANGED_ERP_SLOT && priv->rf->conf_erp)
diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c
index 98e0351c1dd6..38fa8244cc96 100644
--- a/drivers/net/wireless/rtl818x/rtl8187_dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c
@@ -1176,13 +1176,12 @@ static void rtl8187_bss_info_changed(struct ieee80211_hw *dev,
else
reg = 0;
- if (is_valid_ether_addr(info->bssid)) {
+ if (is_valid_ether_addr(info->bssid))
reg |= RTL818X_MSR_INFRA;
- rtl818x_iowrite8(priv, &priv->map->MSR, reg);
- } else {
+ else
reg |= RTL818X_MSR_NO_LINK;
- rtl818x_iowrite8(priv, &priv->map->MSR, reg);
- }
+
+ rtl818x_iowrite8(priv, &priv->map->MSR, reg);
mutex_unlock(&priv->conf_mutex);
}
diff --git a/drivers/net/wireless/wl1251/Kconfig b/drivers/net/wireless/wl1251/Kconfig
new file mode 100644
index 000000000000..1fb65849414f
--- /dev/null
+++ b/drivers/net/wireless/wl1251/Kconfig
@@ -0,0 +1,33 @@
+menuconfig WL1251
+ tristate "TI wl1251 driver support"
+ depends on MAC80211 && EXPERIMENTAL && GENERIC_HARDIRQS
+ select FW_LOADER
+ select CRC7
+ ---help---
+ This will enable TI wl1251 driver support. The drivers make
+ use of the mac80211 stack.
+
+ If you choose to build a module, it'll be called wl1251. Say
+ N if unsure.
+
+config WL1251_SPI
+ tristate "TI wl1251 SPI support"
+ depends on WL1251 && SPI_MASTER
+ ---help---
+ This module adds support for the SPI interface of adapters using
+ TI wl1251 chipset. Select this if your platform is using
+ the SPI bus.
+
+ If you choose to build a module, it'll be called wl1251_spi.
+ Say N if unsure.
+
+config WL1251_SDIO
+ tristate "TI wl1251 SDIO support"
+ depends on WL1251 && MMC
+ ---help---
+ This module adds support for the SDIO interface of adapters using
+ TI wl1251 chipset. Select this if your platform is using
+ the SDIO bus.
+
+ If you choose to build a module, it'll be called
+ wl1251_sdio. Say N if unsure.
diff --git a/drivers/net/wireless/wl1251/Makefile b/drivers/net/wireless/wl1251/Makefile
new file mode 100644
index 000000000000..4fe246824db3
--- /dev/null
+++ b/drivers/net/wireless/wl1251/Makefile
@@ -0,0 +1,6 @@
+wl1251-objs = main.o event.o tx.o rx.o ps.o cmd.o \
+ acx.o boot.o init.o debugfs.o io.o
+
+obj-$(CONFIG_WL1251) += wl1251.o
+obj-$(CONFIG_WL1251_SPI) += spi.o
+obj-$(CONFIG_WL1251_SDIO) += sdio.o
diff --git a/drivers/net/wireless/wl12xx/wl1251_acx.c b/drivers/net/wireless/wl1251/acx.c
index 91891f928070..64a0214cfb29 100644
--- a/drivers/net/wireless/wl12xx/wl1251_acx.c
+++ b/drivers/net/wireless/wl1251/acx.c
@@ -1,13 +1,13 @@
-#include "wl1251_acx.h"
+#include "acx.h"
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/crc7.h>
#include "wl1251.h"
-#include "wl1251_reg.h"
-#include "wl1251_cmd.h"
-#include "wl1251_ps.h"
+#include "reg.h"
+#include "cmd.h"
+#include "ps.h"
int wl1251_acx_frame_rates(struct wl1251 *wl, u8 ctrl_rate, u8 ctrl_mod,
u8 mgt_rate, u8 mgt_mod)
@@ -380,7 +380,7 @@ int wl1251_acx_pd_threshold(struct wl1251 *wl)
out:
kfree(pd);
- return 0;
+ return ret;
}
int wl1251_acx_slot(struct wl1251 *wl, enum acx_slot_type slot_time)
diff --git a/drivers/net/wireless/wl12xx/wl1251_acx.h b/drivers/net/wireless/wl1251/acx.h
index 842df310d92a..e54b21a4f8b1 100644
--- a/drivers/net/wireless/wl12xx/wl1251_acx.h
+++ b/drivers/net/wireless/wl1251/acx.h
@@ -4,8 +4,6 @@
* Copyright (c) 1998-2007 Texas Instruments Incorporated
* Copyright (C) 2008 Nokia Corporation
*
- * Contact: Kalle Valo <kalle.valo@nokia.com>
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
@@ -26,7 +24,7 @@
#define __WL1251_ACX_H__
#include "wl1251.h"
-#include "wl1251_cmd.h"
+#include "cmd.h"
/* Target's information element */
struct acx_header {
@@ -37,7 +35,7 @@ struct acx_header {
/* payload length (not including headers */
u16 len;
-};
+} __packed;
struct acx_error_counter {
struct acx_header header;
@@ -459,8 +457,8 @@ struct acx_beacon_filter_ie_table {
struct acx_header header;
u8 num_ie;
- u8 table[BEACON_FILTER_TABLE_MAX_SIZE];
u8 pad[3];
+ u8 table[BEACON_FILTER_TABLE_MAX_SIZE];
} __packed;
#define SYNCH_FAIL_DEFAULT_THRESHOLD 10 /* number of beacons */
@@ -471,7 +469,7 @@ struct acx_conn_monit_params {
u32 synch_fail_thold; /* number of beacons missed */
u32 bss_lose_timeout; /* number of TU's from synch fail */
-};
+} __packed;
enum {
SG_ENABLE = 0,
@@ -1056,7 +1054,7 @@ struct acx_rate_class {
u8 long_retry_limit;
u8 aflags;
u8 reserved;
-};
+} __packed;
struct acx_rate_policy {
struct acx_header header;
diff --git a/drivers/net/wireless/wl12xx/wl1251_boot.c b/drivers/net/wireless/wl1251/boot.c
index 65e0416be5b6..61572dfa1f60 100644
--- a/drivers/net/wireless/wl12xx/wl1251_boot.c
+++ b/drivers/net/wireless/wl1251/boot.c
@@ -3,8 +3,6 @@
*
* Copyright (C) 2008 Nokia Corporation
*
- * Contact: Kalle Valo <kalle.valo@nokia.com>
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
@@ -24,12 +22,12 @@
#include <linux/gpio.h>
#include <linux/slab.h>
-#include "wl1251_reg.h"
-#include "wl1251_boot.h"
-#include "wl1251_io.h"
-#include "wl1251_spi.h"
-#include "wl1251_event.h"
-#include "wl1251_acx.h"
+#include "reg.h"
+#include "boot.h"
+#include "io.h"
+#include "spi.h"
+#include "event.h"
+#include "acx.h"
void wl1251_boot_target_enable_interrupts(struct wl1251 *wl)
{
@@ -302,7 +300,7 @@ int wl1251_boot_run_firmware(struct wl1251 *wl)
ROAMING_TRIGGER_LOW_RSSI_EVENT_ID |
ROAMING_TRIGGER_REGAINED_RSSI_EVENT_ID |
REGAINED_BSS_EVENT_ID | BT_PTA_SENSE_EVENT_ID |
- BT_PTA_PREDICTION_EVENT_ID;
+ BT_PTA_PREDICTION_EVENT_ID | JOIN_EVENT_COMPLETE_ID;
ret = wl1251_event_unmask(wl);
if (ret < 0) {
diff --git a/drivers/net/wireless/wl12xx/wl1251_boot.h b/drivers/net/wireless/wl1251/boot.h
index 90063697e8f2..7661bc5e4662 100644
--- a/drivers/net/wireless/wl12xx/wl1251_boot.h
+++ b/drivers/net/wireless/wl1251/boot.h
@@ -3,8 +3,6 @@
*
* Copyright (C) 2008 Nokia Corporation
*
- * Contact: Kalle Valo <kalle.valo@nokia.com>
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
diff --git a/drivers/net/wireless/wl12xx/wl1251_cmd.c b/drivers/net/wireless/wl1251/cmd.c
index ce3722f4c3e3..0ade4bd617c0 100644
--- a/drivers/net/wireless/wl12xx/wl1251_cmd.c
+++ b/drivers/net/wireless/wl1251/cmd.c
@@ -1,14 +1,14 @@
-#include "wl1251_cmd.h"
+#include "cmd.h"
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/crc7.h>
#include "wl1251.h"
-#include "wl1251_reg.h"
-#include "wl1251_io.h"
-#include "wl1251_ps.h"
-#include "wl1251_acx.h"
+#include "reg.h"
+#include "io.h"
+#include "ps.h"
+#include "acx.h"
/**
* send command to firmware
@@ -200,7 +200,7 @@ int wl1251_cmd_vbm(struct wl1251 *wl, u8 identity,
out:
kfree(vbm);
- return 0;
+ return ret;
}
int wl1251_cmd_data_path(struct wl1251 *wl, u8 channel, bool enable)
diff --git a/drivers/net/wireless/wl12xx/wl1251_cmd.h b/drivers/net/wireless/wl1251/cmd.h
index a9e4991369be..e5c74c631374 100644
--- a/drivers/net/wireless/wl12xx/wl1251_cmd.h
+++ b/drivers/net/wireless/wl1251/cmd.h
@@ -4,8 +4,6 @@
* Copyright (c) 1998-2007 Texas Instruments Incorporated
* Copyright (C) 2008 Nokia Corporation
*
- * Contact: Kalle Valo <kalle.valo@nokia.com>
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
@@ -111,7 +109,7 @@ struct wl1251_cmd_header {
struct wl1251_command {
struct wl1251_cmd_header header;
u8 parameters[MAX_CMD_PARAMS];
-};
+} __packed;
enum {
CMD_MAILBOX_IDLE = 0,
@@ -164,7 +162,7 @@ struct cmd_read_write_memory {
of this field is the Host in WRITE command or the Wilink in READ
command. */
u8 value[MAX_READ_SIZE];
-};
+} __packed;
#define CMDMBOX_HEADER_LEN 4
#define CMDMBOX_INFO_ELEM_HEADER_LEN 4
@@ -339,7 +337,7 @@ struct wl1251_cmd_trigger_scan_to {
struct wl1251_cmd_header header;
u32 timeout;
-};
+} __packed;
/* HW encryption keys */
#define NUM_ACCESS_CATEGORIES_COPY 4
diff --git a/drivers/net/wireless/wl12xx/wl1251_debugfs.c b/drivers/net/wireless/wl1251/debugfs.c
index 5e4465ac08fa..6c274007d200 100644
--- a/drivers/net/wireless/wl12xx/wl1251_debugfs.c
+++ b/drivers/net/wireless/wl1251/debugfs.c
@@ -3,8 +3,6 @@
*
* Copyright (C) 2009 Nokia Corporation
*
- * Contact: Kalle Valo <kalle.valo@nokia.com>
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
@@ -21,14 +19,14 @@
*
*/
-#include "wl1251_debugfs.h"
+#include "debugfs.h"
#include <linux/skbuff.h>
#include <linux/slab.h>
#include "wl1251.h"
-#include "wl1251_acx.h"
-#include "wl1251_ps.h"
+#include "acx.h"
+#include "ps.h"
/* ms */
#define WL1251_DEBUGFS_STATS_LIFETIME 1000
@@ -50,6 +48,7 @@ static ssize_t name## _read(struct file *file, char __user *userbuf, \
static const struct file_operations name## _ops = { \
.read = name## _read, \
.open = wl1251_open_file_generic, \
+ .llseek = generic_file_llseek, \
};
#define DEBUGFS_ADD(name, parent) \
@@ -86,6 +85,7 @@ static ssize_t sub## _ ##name## _read(struct file *file, \
static const struct file_operations sub## _ ##name## _ops = { \
.read = sub## _ ##name## _read, \
.open = wl1251_open_file_generic, \
+ .llseek = generic_file_llseek, \
};
#define DEBUGFS_FWSTATS_ADD(sub, name) \
@@ -236,6 +236,7 @@ static ssize_t tx_queue_len_read(struct file *file, char __user *userbuf,
static const struct file_operations tx_queue_len_ops = {
.read = tx_queue_len_read,
.open = wl1251_open_file_generic,
+ .llseek = generic_file_llseek,
};
static ssize_t tx_queue_status_read(struct file *file, char __user *userbuf,
@@ -257,6 +258,7 @@ static ssize_t tx_queue_status_read(struct file *file, char __user *userbuf,
static const struct file_operations tx_queue_status_ops = {
.read = tx_queue_status_read,
.open = wl1251_open_file_generic,
+ .llseek = generic_file_llseek,
};
static void wl1251_debugfs_delete_files(struct wl1251 *wl)
diff --git a/drivers/net/wireless/wl12xx/wl1251_debugfs.h b/drivers/net/wireless/wl1251/debugfs.h
index 6dc3d080853c..b3417c02a218 100644
--- a/drivers/net/wireless/wl12xx/wl1251_debugfs.h
+++ b/drivers/net/wireless/wl1251/debugfs.h
@@ -3,8 +3,6 @@
*
* Copyright (C) 2009 Nokia Corporation
*
- * Contact: Kalle Valo <kalle.valo@nokia.com>
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
diff --git a/drivers/net/wireless/wl12xx/wl1251_event.c b/drivers/net/wireless/wl1251/event.c
index 020d764f9c13..712372e50a87 100644
--- a/drivers/net/wireless/wl12xx/wl1251_event.c
+++ b/drivers/net/wireless/wl1251/event.c
@@ -4,8 +4,6 @@
* Copyright (c) 1998-2007 Texas Instruments Incorporated
* Copyright (C) 2008 Nokia Corporation
*
- * Contact: Kalle Valo <kalle.valo@nokia.com>
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
@@ -23,10 +21,10 @@
*/
#include "wl1251.h"
-#include "wl1251_reg.h"
-#include "wl1251_io.h"
-#include "wl1251_event.h"
-#include "wl1251_ps.h"
+#include "reg.h"
+#include "io.h"
+#include "event.h"
+#include "ps.h"
static int wl1251_event_scan_complete(struct wl1251 *wl,
struct event_mailbox *mbox)
@@ -36,9 +34,7 @@ static int wl1251_event_scan_complete(struct wl1251 *wl,
mbox->scheduled_scan_channels);
if (wl->scanning) {
- mutex_unlock(&wl->mutex);
ieee80211_scan_completed(wl->hw, false);
- mutex_lock(&wl->mutex);
wl1251_debug(DEBUG_MAC80211, "mac80211 hw scan completed");
wl->scanning = false;
}
@@ -97,6 +93,35 @@ static int wl1251_event_process(struct wl1251 *wl, struct event_mailbox *mbox)
return 0;
}
+/*
+ * Poll the mailbox event field until any of the bits in the mask is set or a
+ * timeout occurs (WL1251_EVENT_TIMEOUT in msecs)
+ */
+int wl1251_event_wait(struct wl1251 *wl, u32 mask, int timeout_ms)
+{
+ u32 events_vector, event;
+ unsigned long timeout;
+
+ timeout = jiffies + msecs_to_jiffies(timeout_ms);
+
+ do {
+ if (time_after(jiffies, timeout))
+ return -ETIMEDOUT;
+
+ msleep(1);
+
+ /* read from both event fields */
+ wl1251_mem_read(wl, wl->mbox_ptr[0], &events_vector,
+ sizeof(events_vector));
+ event = events_vector & mask;
+ wl1251_mem_read(wl, wl->mbox_ptr[1], &events_vector,
+ sizeof(events_vector));
+ event |= events_vector & mask;
+ } while (!event);
+
+ return 0;
+}
+
int wl1251_event_unmask(struct wl1251 *wl)
{
int ret;
diff --git a/drivers/net/wireless/wl12xx/wl1251_event.h b/drivers/net/wireless/wl1251/event.h
index f48a2b66bc5a..30eb5d150bf7 100644
--- a/drivers/net/wireless/wl12xx/wl1251_event.h
+++ b/drivers/net/wireless/wl1251/event.h
@@ -4,8 +4,6 @@
* Copyright (c) 1998-2007 Texas Instruments Incorporated
* Copyright (C) 2008 Nokia Corporation
*
- * Contact: Kalle Valo <kalle.valo@nokia.com>
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
@@ -117,5 +115,6 @@ struct event_mailbox {
int wl1251_event_unmask(struct wl1251 *wl);
void wl1251_event_mbox_config(struct wl1251 *wl);
int wl1251_event_handle(struct wl1251 *wl, u8 mbox);
+int wl1251_event_wait(struct wl1251 *wl, u32 mask, int timeout_ms);
#endif
diff --git a/drivers/net/wireless/wl12xx/wl1251_init.c b/drivers/net/wireless/wl1251/init.c
index b538bdd7b320..89b43d35473c 100644
--- a/drivers/net/wireless/wl12xx/wl1251_init.c
+++ b/drivers/net/wireless/wl1251/init.c
@@ -3,8 +3,6 @@
*
* Copyright (C) 2009 Nokia Corporation
*
- * Contact: Kalle Valo <kalle.valo@nokia.com>
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
@@ -25,11 +23,11 @@
#include <linux/module.h>
#include <linux/slab.h>
-#include "wl1251_init.h"
+#include "init.h"
#include "wl12xx_80211.h"
-#include "wl1251_acx.h"
-#include "wl1251_cmd.h"
-#include "wl1251_reg.h"
+#include "acx.h"
+#include "cmd.h"
+#include "reg.h"
int wl1251_hw_init_hwenc_config(struct wl1251 *wl)
{
diff --git a/drivers/net/wireless/wl12xx/wl1251_init.h b/drivers/net/wireless/wl1251/init.h
index 269cefb3e7d4..543f17582ead 100644
--- a/drivers/net/wireless/wl12xx/wl1251_init.h
+++ b/drivers/net/wireless/wl1251/init.h
@@ -3,8 +3,6 @@
*
* Copyright (C) 2009 Nokia Corporation
*
- * Contact: Kalle Valo <kalle.valo@nokia.com>
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
diff --git a/drivers/net/wireless/wl12xx/wl1251_io.c b/drivers/net/wireless/wl1251/io.c
index f1c232e0887f..cdcadbf6ac2c 100644
--- a/drivers/net/wireless/wl12xx/wl1251_io.c
+++ b/drivers/net/wireless/wl1251/io.c
@@ -3,8 +3,6 @@
*
* Copyright (C) 2008 Nokia Corporation
*
- * Contact: Kalle Valo <kalle.valo@nokia.com>
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
@@ -22,8 +20,8 @@
*/
#include "wl1251.h"
-#include "wl1251_reg.h"
-#include "wl1251_io.h"
+#include "reg.h"
+#include "io.h"
/* FIXME: this is static data nowadays and the table can be removed */
static enum wl12xx_acx_int_reg wl1251_io_reg_table[ACX_REG_TABLE_LEN] = {
diff --git a/drivers/net/wireless/wl12xx/wl1251_io.h b/drivers/net/wireless/wl1251/io.h
index c545e9d5f512..c545e9d5f512 100644
--- a/drivers/net/wireless/wl12xx/wl1251_io.h
+++ b/drivers/net/wireless/wl1251/io.h
diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl1251/main.c
index 861a5f33761e..7a8762553cdc 100644
--- a/drivers/net/wireless/wl12xx/wl1251_main.c
+++ b/drivers/net/wireless/wl1251/main.c
@@ -3,8 +3,6 @@
*
* Copyright (C) 2008-2009 Nokia Corporation
*
- * Contact: Kalle Valo <kalle.valo@nokia.com>
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
@@ -33,16 +31,16 @@
#include "wl1251.h"
#include "wl12xx_80211.h"
-#include "wl1251_reg.h"
-#include "wl1251_io.h"
-#include "wl1251_cmd.h"
-#include "wl1251_event.h"
-#include "wl1251_tx.h"
-#include "wl1251_rx.h"
-#include "wl1251_ps.h"
-#include "wl1251_init.h"
-#include "wl1251_debugfs.h"
-#include "wl1251_boot.h"
+#include "reg.h"
+#include "io.h"
+#include "cmd.h"
+#include "event.h"
+#include "tx.h"
+#include "rx.h"
+#include "ps.h"
+#include "init.h"
+#include "debugfs.h"
+#include "boot.h"
void wl1251_enable_interrupts(struct wl1251 *wl)
{
@@ -293,14 +291,14 @@ static void wl1251_irq_work(struct work_struct *work)
wl1251_tx_complete(wl);
}
- if (intr & (WL1251_ACX_INTR_EVENT_A |
- WL1251_ACX_INTR_EVENT_B)) {
- wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_EVENT (0x%x)",
- intr);
- if (intr & WL1251_ACX_INTR_EVENT_A)
- wl1251_event_handle(wl, 0);
- else
- wl1251_event_handle(wl, 1);
+ if (intr & WL1251_ACX_INTR_EVENT_A) {
+ wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_EVENT_A");
+ wl1251_event_handle(wl, 0);
+ }
+
+ if (intr & WL1251_ACX_INTR_EVENT_B) {
+ wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_EVENT_B");
+ wl1251_event_handle(wl, 1);
}
if (intr & WL1251_ACX_INTR_INIT_COMPLETE)
@@ -339,11 +337,9 @@ static int wl1251_join(struct wl1251 *wl, u8 bss_type, u8 channel,
if (ret < 0)
goto out;
- /*
- * FIXME: we should wait for JOIN_EVENT_COMPLETE_ID but to simplify
- * locking we just sleep instead, for now
- */
- msleep(10);
+ ret = wl1251_event_wait(wl, JOIN_EVENT_COMPLETE_ID, 100);
+ if (ret < 0)
+ wl1251_warning("join timeout");
out:
return ret;
@@ -379,6 +375,7 @@ out:
static int wl1251_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
{
struct wl1251 *wl = hw->priv;
+ unsigned long flags;
skb_queue_tail(&wl->tx_queue, skb);
@@ -393,16 +390,13 @@ static int wl1251_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
* The workqueue is slow to process the tx_queue and we need stop
* the queue here, otherwise the queue will get too long.
*/
- if (skb_queue_len(&wl->tx_queue) >= WL1251_TX_QUEUE_MAX_LENGTH) {
+ if (skb_queue_len(&wl->tx_queue) >= WL1251_TX_QUEUE_HIGH_WATERMARK) {
wl1251_debug(DEBUG_TX, "op_tx: tx_queue full, stop queues");
- ieee80211_stop_queues(wl->hw);
- /*
- * FIXME: this is racy, the variable is not properly
- * protected. Maybe fix this by removing the stupid
- * variable altogether and checking the real queue state?
- */
+ spin_lock_irqsave(&wl->wl_lock, flags);
+ ieee80211_stop_queues(wl->hw);
wl->tx_queue_stopped = true;
+ spin_unlock_irqrestore(&wl->wl_lock, flags);
}
return NETDEV_TX_OK;
@@ -471,9 +465,7 @@ static void wl1251_op_stop(struct ieee80211_hw *hw)
WARN_ON(wl->state != WL1251_STATE_ON);
if (wl->scanning) {
- mutex_unlock(&wl->mutex);
ieee80211_scan_completed(wl->hw, true);
- mutex_lock(&wl->mutex);
wl->scanning = false;
}
@@ -725,8 +717,9 @@ static int wl1251_set_key_type(struct wl1251 *wl,
struct ieee80211_key_conf *mac80211_key,
const u8 *addr)
{
- switch (mac80211_key->alg) {
- case ALG_WEP:
+ switch (mac80211_key->cipher) {
+ case WLAN_CIPHER_SUITE_WEP40:
+ case WLAN_CIPHER_SUITE_WEP104:
if (is_broadcast_ether_addr(addr))
key->key_type = KEY_WEP_DEFAULT;
else
@@ -734,7 +727,7 @@ static int wl1251_set_key_type(struct wl1251 *wl,
mac80211_key->hw_key_idx = mac80211_key->keyidx;
break;
- case ALG_TKIP:
+ case WLAN_CIPHER_SUITE_TKIP:
if (is_broadcast_ether_addr(addr))
key->key_type = KEY_TKIP_MIC_GROUP;
else
@@ -742,7 +735,7 @@ static int wl1251_set_key_type(struct wl1251 *wl,
mac80211_key->hw_key_idx = mac80211_key->keyidx;
break;
- case ALG_CCMP:
+ case WLAN_CIPHER_SUITE_CCMP:
if (is_broadcast_ether_addr(addr))
key->key_type = KEY_AES_GROUP;
else
@@ -750,7 +743,7 @@ static int wl1251_set_key_type(struct wl1251 *wl,
mac80211_key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
break;
default:
- wl1251_error("Unknown key algo 0x%x", mac80211_key->alg);
+ wl1251_error("Unknown key cipher 0x%x", mac80211_key->cipher);
return -EOPNOTSUPP;
}
@@ -783,7 +776,7 @@ static int wl1251_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
wl1251_debug(DEBUG_CRYPT, "CMD: 0x%x", cmd);
wl1251_dump(DEBUG_CRYPT, "ADDR: ", addr, ETH_ALEN);
wl1251_debug(DEBUG_CRYPT, "Key: algo:0x%x, id:%d, len:%d flags 0x%x",
- key->alg, key->keyidx, key->keylen, key->flags);
+ key->cipher, key->keyidx, key->keylen, key->flags);
wl1251_dump(DEBUG_CRYPT, "KEY: ", key->key, key->keylen);
if (is_zero_ether_addr(addr)) {
@@ -1438,5 +1431,5 @@ EXPORT_SYMBOL_GPL(wl1251_free_hw);
MODULE_DESCRIPTION("TI wl1251 Wireles LAN Driver Core");
MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Kalle Valo <kalle.valo@nokia.com>");
+MODULE_AUTHOR("Kalle Valo <kvalo@adurom.com>");
MODULE_FIRMWARE(WL1251_FW_NAME);
diff --git a/drivers/net/wireless/wl12xx/wl1251_ps.c b/drivers/net/wireless/wl1251/ps.c
index b55cb2bd459a..5ed47c8373d2 100644
--- a/drivers/net/wireless/wl12xx/wl1251_ps.c
+++ b/drivers/net/wireless/wl1251/ps.c
@@ -3,8 +3,6 @@
*
* Copyright (C) 2008 Nokia Corporation
*
- * Contact: Kalle Valo <kalle.valo@nokia.com>
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
@@ -21,10 +19,10 @@
*
*/
-#include "wl1251_reg.h"
-#include "wl1251_ps.h"
-#include "wl1251_cmd.h"
-#include "wl1251_io.h"
+#include "reg.h"
+#include "ps.h"
+#include "cmd.h"
+#include "io.h"
/* in ms */
#define WL1251_WAKEUP_TIMEOUT 100
diff --git a/drivers/net/wireless/wl12xx/wl1251_ps.h b/drivers/net/wireless/wl1251/ps.h
index c688ac57aee4..55c3dda75e69 100644
--- a/drivers/net/wireless/wl12xx/wl1251_ps.h
+++ b/drivers/net/wireless/wl1251/ps.h
@@ -1,14 +1,9 @@
-#ifndef __WL1251_PS_H__
-#define __WL1251_PS_H__
-
/*
* This file is part of wl1251
*
* Copyright (c) 1998-2007 Texas Instruments Incorporated
* Copyright (C) 2008 Nokia Corporation
*
- * Contact: Kalle Valo <kalle.valo@nokia.com>
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
@@ -25,8 +20,11 @@
*
*/
+#ifndef __WL1251_PS_H__
+#define __WL1251_PS_H__
+
#include "wl1251.h"
-#include "wl1251_acx.h"
+#include "acx.h"
int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode);
void wl1251_ps_elp_sleep(struct wl1251 *wl);
diff --git a/drivers/net/wireless/wl12xx/wl1251_reg.h b/drivers/net/wireless/wl1251/reg.h
index d16edd9bf06c..a5809019c5c1 100644
--- a/drivers/net/wireless/wl12xx/wl1251_reg.h
+++ b/drivers/net/wireless/wl1251/reg.h
@@ -4,8 +4,6 @@
* Copyright (c) 1998-2007 Texas Instruments Incorporated
* Copyright (C) 2008 Nokia Corporation
*
- * Contact: Kalle Valo <kalle.valo@nokia.com>
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
diff --git a/drivers/net/wireless/wl12xx/wl1251_rx.c b/drivers/net/wireless/wl1251/rx.c
index 1b6294b3b996..efa53607d5c9 100644
--- a/drivers/net/wireless/wl12xx/wl1251_rx.c
+++ b/drivers/net/wireless/wl1251/rx.c
@@ -4,8 +4,6 @@
* Copyright (c) 1998-2007 Texas Instruments Incorporated
* Copyright (C) 2008 Nokia Corporation
*
- * Contact: Kalle Valo <kalle.valo@nokia.com>
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
@@ -27,11 +25,11 @@
#include <net/mac80211.h>
#include "wl1251.h"
-#include "wl1251_reg.h"
-#include "wl1251_io.h"
-#include "wl1251_rx.h"
-#include "wl1251_cmd.h"
-#include "wl1251_acx.h"
+#include "reg.h"
+#include "io.h"
+#include "rx.h"
+#include "cmd.h"
+#include "acx.h"
static void wl1251_rx_header(struct wl1251 *wl,
struct wl1251_rx_descriptor *desc)
diff --git a/drivers/net/wireless/wl12xx/wl1251_rx.h b/drivers/net/wireless/wl1251/rx.h
index da4e53406a0e..4448f635a4d8 100644
--- a/drivers/net/wireless/wl12xx/wl1251_rx.h
+++ b/drivers/net/wireless/wl1251/rx.h
@@ -4,8 +4,6 @@
* Copyright (c) 1998-2007 Texas Instruments Incorporated
* Copyright (C) 2008 Nokia Corporation
*
- * Contact: Kalle Valo <kalle.valo@nokia.com>
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
diff --git a/drivers/net/wireless/wl12xx/wl1251_sdio.c b/drivers/net/wireless/wl1251/sdio.c
index b901b6135654..74ba9ced5393 100644
--- a/drivers/net/wireless/wl12xx/wl1251_sdio.c
+++ b/drivers/net/wireless/wl1251/sdio.c
@@ -24,7 +24,7 @@
#include <linux/mmc/sdio_func.h>
#include <linux/mmc/sdio_ids.h>
#include <linux/platform_device.h>
-#include <linux/spi/wl12xx.h>
+#include <linux/wl12xx.h>
#include <linux/irq.h>
#include "wl1251.h"
@@ -339,4 +339,4 @@ module_init(wl1251_sdio_init);
module_exit(wl1251_sdio_exit);
MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Kalle Valo <kalle.valo@nokia.com>");
+MODULE_AUTHOR("Kalle Valo <kvalo@adurom.com>");
diff --git a/drivers/net/wireless/wl12xx/wl1251_spi.c b/drivers/net/wireless/wl1251/spi.c
index 27fdfaaeb074..88fa8e69d0d1 100644
--- a/drivers/net/wireless/wl12xx/wl1251_spi.c
+++ b/drivers/net/wireless/wl1251/spi.c
@@ -3,8 +3,6 @@
*
* Copyright (C) 2008 Nokia Corporation
*
- * Contact: Kalle Valo <kalle.valo@nokia.com>
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
@@ -26,11 +24,11 @@
#include <linux/slab.h>
#include <linux/crc7.h>
#include <linux/spi/spi.h>
-#include <linux/spi/wl12xx.h>
+#include <linux/wl12xx.h>
#include "wl1251.h"
-#include "wl1251_reg.h"
-#include "wl1251_spi.h"
+#include "reg.h"
+#include "spi.h"
static irqreturn_t wl1251_irq(int irq, void *cookie)
{
@@ -344,5 +342,5 @@ module_init(wl1251_spi_init);
module_exit(wl1251_spi_exit);
MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Kalle Valo <kalle.valo@nokia.com>");
+MODULE_AUTHOR("Kalle Valo <kvalo@adurom.com>");
MODULE_ALIAS("spi:wl1251");
diff --git a/drivers/net/wireless/wl12xx/wl1251_spi.h b/drivers/net/wireless/wl1251/spi.h
index 2e273a97e7f3..16d506955cc0 100644
--- a/drivers/net/wireless/wl12xx/wl1251_spi.h
+++ b/drivers/net/wireless/wl1251/spi.h
@@ -4,8 +4,6 @@
* Copyright (c) 1998-2007 Texas Instruments Incorporated
* Copyright (C) 2008 Nokia Corporation
*
- * Contact: Kalle Valo <kalle.valo@nokia.com>
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
@@ -25,9 +23,9 @@
#ifndef __WL1251_SPI_H__
#define __WL1251_SPI_H__
-#include "wl1251_cmd.h"
-#include "wl1251_acx.h"
-#include "wl1251_reg.h"
+#include "cmd.h"
+#include "acx.h"
+#include "reg.h"
#define WSPI_CMD_READ 0x40000000
#define WSPI_CMD_WRITE 0x00000000
diff --git a/drivers/net/wireless/wl12xx/wl1251_tx.c b/drivers/net/wireless/wl1251/tx.c
index a38ec199187a..554b4f9a3d3e 100644
--- a/drivers/net/wireless/wl12xx/wl1251_tx.c
+++ b/drivers/net/wireless/wl1251/tx.c
@@ -4,8 +4,6 @@
* Copyright (c) 1998-2007 Texas Instruments Incorporated
* Copyright (C) 2008 Nokia Corporation
*
- * Contact: Kalle Valo <kalle.valo@nokia.com>
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
@@ -26,10 +24,10 @@
#include <linux/module.h>
#include "wl1251.h"
-#include "wl1251_reg.h"
-#include "wl1251_tx.h"
-#include "wl1251_ps.h"
-#include "wl1251_io.h"
+#include "reg.h"
+#include "tx.h"
+#include "ps.h"
+#include "io.h"
static bool wl1251_tx_double_buffer_busy(struct wl1251 *wl, u32 data_out_count)
{
@@ -189,7 +187,7 @@ static int wl1251_tx_send_packet(struct wl1251 *wl, struct sk_buff *skb,
tx_hdr = (struct tx_double_buffer_desc *) skb->data;
if (control->control.hw_key &&
- control->control.hw_key->alg == ALG_TKIP) {
+ control->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) {
int hdrlen;
__le16 fc;
u16 length;
@@ -322,11 +320,6 @@ void wl1251_tx_work(struct work_struct *work)
ret = wl1251_tx_frame(wl, skb);
if (ret == -EBUSY) {
- /* firmware buffer is full, stop queues */
- wl1251_debug(DEBUG_TX, "tx_work: fw buffer full, "
- "stop queues");
- ieee80211_stop_queues(wl->hw);
- wl->tx_queue_stopped = true;
skb_queue_head(&wl->tx_queue, skb);
goto out;
} else if (ret < 0) {
@@ -399,7 +392,7 @@ static void wl1251_tx_packet_cb(struct wl1251 *wl,
*/
frame = skb_pull(skb, sizeof(struct tx_double_buffer_desc));
if (info->control.hw_key &&
- info->control.hw_key->alg == ALG_TKIP) {
+ info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) {
hdrlen = ieee80211_get_hdrlen_from_skb(skb);
memmove(frame + WL1251_TKIP_IV_SPACE, frame, hdrlen);
skb_pull(skb, WL1251_TKIP_IV_SPACE);
@@ -449,6 +442,7 @@ void wl1251_tx_complete(struct wl1251 *wl)
{
int i, result_index, num_complete = 0;
struct tx_result result[FW_TX_CMPLT_BLOCK_SIZE], *result_ptr;
+ unsigned long flags;
if (unlikely(wl->state != WL1251_STATE_ON))
return;
@@ -477,6 +471,20 @@ void wl1251_tx_complete(struct wl1251 *wl)
}
}
+ if (wl->tx_queue_stopped
+ &&
+ skb_queue_len(&wl->tx_queue) <= WL1251_TX_QUEUE_LOW_WATERMARK){
+
+ /* firmware buffer has space, restart queues */
+ wl1251_debug(DEBUG_TX, "tx_complete: waking queues");
+ spin_lock_irqsave(&wl->wl_lock, flags);
+ ieee80211_wake_queues(wl->hw);
+ wl->tx_queue_stopped = false;
+ spin_unlock_irqrestore(&wl->wl_lock, flags);
+ ieee80211_queue_work(wl->hw, &wl->tx_work);
+
+ }
+
/* Every completed frame needs to be acknowledged */
if (num_complete) {
/*
diff --git a/drivers/net/wireless/wl12xx/wl1251_tx.h b/drivers/net/wireless/wl1251/tx.h
index f40eeb37f5aa..81338d39b43e 100644
--- a/drivers/net/wireless/wl12xx/wl1251_tx.h
+++ b/drivers/net/wireless/wl1251/tx.h
@@ -4,8 +4,6 @@
* Copyright (c) 1998-2007 Texas Instruments Incorporated
* Copyright (C) 2008 Nokia Corporation
*
- * Contact: Kalle Valo <kalle.valo@nokia.com>
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
@@ -26,7 +24,7 @@
#define __WL1251_TX_H__
#include <linux/bitops.h>
-#include "wl1251_acx.h"
+#include "acx.h"
/*
*
diff --git a/drivers/net/wireless/wl12xx/wl1251.h b/drivers/net/wireless/wl1251/wl1251.h
index 6b942a28e6a5..e113d4c1fb35 100644
--- a/drivers/net/wireless/wl12xx/wl1251.h
+++ b/drivers/net/wireless/wl1251/wl1251.h
@@ -4,8 +4,6 @@
* Copyright (c) 1998-2007 Texas Instruments Incorporated
* Copyright (C) 2008-2009 Nokia Corporation
*
- * Contact: Kalle Valo <kalle.valo@nokia.com>
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
@@ -274,6 +272,8 @@ struct wl1251 {
int irq;
bool use_eeprom;
+ spinlock_t wl_lock;
+
enum wl1251_state state;
struct mutex mutex;
@@ -401,7 +401,8 @@ void wl1251_disable_interrupts(struct wl1251 *wl);
#define WL1251_DEFAULT_POWER_LEVEL 20
-#define WL1251_TX_QUEUE_MAX_LENGTH 20
+#define WL1251_TX_QUEUE_LOW_WATERMARK 10
+#define WL1251_TX_QUEUE_HIGH_WATERMARK 25
#define WL1251_DEFAULT_BEACON_INT 100
#define WL1251_DEFAULT_DTIM_PERIOD 1
diff --git a/drivers/net/wireless/wl1251/wl12xx_80211.h b/drivers/net/wireless/wl1251/wl12xx_80211.h
new file mode 100644
index 000000000000..184628027213
--- /dev/null
+++ b/drivers/net/wireless/wl1251/wl12xx_80211.h
@@ -0,0 +1,156 @@
+#ifndef __WL12XX_80211_H__
+#define __WL12XX_80211_H__
+
+#include <linux/if_ether.h> /* ETH_ALEN */
+
+/* RATES */
+#define IEEE80211_CCK_RATE_1MB 0x02
+#define IEEE80211_CCK_RATE_2MB 0x04
+#define IEEE80211_CCK_RATE_5MB 0x0B
+#define IEEE80211_CCK_RATE_11MB 0x16
+#define IEEE80211_OFDM_RATE_6MB 0x0C
+#define IEEE80211_OFDM_RATE_9MB 0x12
+#define IEEE80211_OFDM_RATE_12MB 0x18
+#define IEEE80211_OFDM_RATE_18MB 0x24
+#define IEEE80211_OFDM_RATE_24MB 0x30
+#define IEEE80211_OFDM_RATE_36MB 0x48
+#define IEEE80211_OFDM_RATE_48MB 0x60
+#define IEEE80211_OFDM_RATE_54MB 0x6C
+#define IEEE80211_BASIC_RATE_MASK 0x80
+
+#define IEEE80211_CCK_RATE_1MB_MASK (1<<0)
+#define IEEE80211_CCK_RATE_2MB_MASK (1<<1)
+#define IEEE80211_CCK_RATE_5MB_MASK (1<<2)
+#define IEEE80211_CCK_RATE_11MB_MASK (1<<3)
+#define IEEE80211_OFDM_RATE_6MB_MASK (1<<4)
+#define IEEE80211_OFDM_RATE_9MB_MASK (1<<5)
+#define IEEE80211_OFDM_RATE_12MB_MASK (1<<6)
+#define IEEE80211_OFDM_RATE_18MB_MASK (1<<7)
+#define IEEE80211_OFDM_RATE_24MB_MASK (1<<8)
+#define IEEE80211_OFDM_RATE_36MB_MASK (1<<9)
+#define IEEE80211_OFDM_RATE_48MB_MASK (1<<10)
+#define IEEE80211_OFDM_RATE_54MB_MASK (1<<11)
+
+#define IEEE80211_CCK_RATES_MASK 0x0000000F
+#define IEEE80211_CCK_BASIC_RATES_MASK (IEEE80211_CCK_RATE_1MB_MASK | \
+ IEEE80211_CCK_RATE_2MB_MASK)
+#define IEEE80211_CCK_DEFAULT_RATES_MASK (IEEE80211_CCK_BASIC_RATES_MASK | \
+ IEEE80211_CCK_RATE_5MB_MASK | \
+ IEEE80211_CCK_RATE_11MB_MASK)
+
+#define IEEE80211_OFDM_RATES_MASK 0x00000FF0
+#define IEEE80211_OFDM_BASIC_RATES_MASK (IEEE80211_OFDM_RATE_6MB_MASK | \
+ IEEE80211_OFDM_RATE_12MB_MASK | \
+ IEEE80211_OFDM_RATE_24MB_MASK)
+#define IEEE80211_OFDM_DEFAULT_RATES_MASK (IEEE80211_OFDM_BASIC_RATES_MASK | \
+ IEEE80211_OFDM_RATE_9MB_MASK | \
+ IEEE80211_OFDM_RATE_18MB_MASK | \
+ IEEE80211_OFDM_RATE_36MB_MASK | \
+ IEEE80211_OFDM_RATE_48MB_MASK | \
+ IEEE80211_OFDM_RATE_54MB_MASK)
+#define IEEE80211_DEFAULT_RATES_MASK (IEEE80211_OFDM_DEFAULT_RATES_MASK | \
+ IEEE80211_CCK_DEFAULT_RATES_MASK)
+
+
+/* This really should be 8, but not for our firmware */
+#define MAX_SUPPORTED_RATES 32
+#define COUNTRY_STRING_LEN 3
+#define MAX_COUNTRY_TRIPLETS 32
+
+/* Headers */
+struct ieee80211_header {
+ __le16 frame_ctl;
+ __le16 duration_id;
+ u8 da[ETH_ALEN];
+ u8 sa[ETH_ALEN];
+ u8 bssid[ETH_ALEN];
+ __le16 seq_ctl;
+ u8 payload[0];
+} __packed;
+
+struct wl12xx_ie_header {
+ u8 id;
+ u8 len;
+} __packed;
+
+/* IEs */
+
+struct wl12xx_ie_ssid {
+ struct wl12xx_ie_header header;
+ char ssid[IW_ESSID_MAX_SIZE];
+} __packed;
+
+struct wl12xx_ie_rates {
+ struct wl12xx_ie_header header;
+ u8 rates[MAX_SUPPORTED_RATES];
+} __packed;
+
+struct wl12xx_ie_ds_params {
+ struct wl12xx_ie_header header;
+ u8 channel;
+} __packed;
+
+struct country_triplet {
+ u8 channel;
+ u8 num_channels;
+ u8 max_tx_power;
+} __packed;
+
+struct wl12xx_ie_country {
+ struct wl12xx_ie_header header;
+ u8 country_string[COUNTRY_STRING_LEN];
+ struct country_triplet triplets[MAX_COUNTRY_TRIPLETS];
+} __packed;
+
+
+/* Templates */
+
+struct wl12xx_beacon_template {
+ struct ieee80211_header header;
+ __le32 time_stamp[2];
+ __le16 beacon_interval;
+ __le16 capability;
+ struct wl12xx_ie_ssid ssid;
+ struct wl12xx_ie_rates rates;
+ struct wl12xx_ie_rates ext_rates;
+ struct wl12xx_ie_ds_params ds_params;
+ struct wl12xx_ie_country country;
+} __packed;
+
+struct wl12xx_null_data_template {
+ struct ieee80211_header header;
+} __packed;
+
+struct wl12xx_ps_poll_template {
+ __le16 fc;
+ __le16 aid;
+ u8 bssid[ETH_ALEN];
+ u8 ta[ETH_ALEN];
+} __packed;
+
+struct wl12xx_qos_null_data_template {
+ struct ieee80211_header header;
+ __le16 qos_ctl;
+} __packed;
+
+struct wl12xx_probe_req_template {
+ struct ieee80211_header header;
+ struct wl12xx_ie_ssid ssid;
+ struct wl12xx_ie_rates rates;
+ struct wl12xx_ie_rates ext_rates;
+} __packed;
+
+
+struct wl12xx_probe_resp_template {
+ struct ieee80211_header header;
+ __le32 time_stamp[2];
+ __le16 beacon_interval;
+ __le16 capability;
+ struct wl12xx_ie_ssid ssid;
+ struct wl12xx_ie_rates rates;
+ struct wl12xx_ie_rates ext_rates;
+ struct wl12xx_ie_ds_params ds_params;
+ struct wl12xx_ie_country country;
+} __packed;
+
+#endif
diff --git a/drivers/net/wireless/wl12xx/Kconfig b/drivers/net/wireless/wl12xx/Kconfig
index 2f98058be451..b447559f1db5 100644
--- a/drivers/net/wireless/wl12xx/Kconfig
+++ b/drivers/net/wireless/wl12xx/Kconfig
@@ -5,40 +5,6 @@ menuconfig WL12XX
This will enable TI wl12xx driver support. The drivers make
use of the mac80211 stack.
-config WL1251
- tristate "TI wl1251 support"
- depends on WL12XX && GENERIC_HARDIRQS
- select FW_LOADER
- select CRC7
- ---help---
- This module adds support for wireless adapters based on
- TI wl1251 chipset.
-
- If you choose to build a module, it'll be called wl1251. Say
- N if unsure.
-
-config WL1251_SPI
- tristate "TI wl1251 SPI support"
- depends on WL1251 && SPI_MASTER
- ---help---
- This module adds support for the SPI interface of adapters using
- TI wl1251 chipset. Select this if your platform is using
- the SPI bus.
-
- If you choose to build a module, it'll be called wl1251_spi.
- Say N if unsure.
-
-config WL1251_SDIO
- tristate "TI wl1251 SDIO support"
- depends on WL1251 && MMC
- ---help---
- This module adds support for the SDIO interface of adapters using
- TI wl1251 chipset. Select this if your platform is using
- the SDIO bus.
-
- If you choose to build a module, it'll be called
- wl1251_sdio. Say N if unsure.
-
config WL1271
tristate "TI wl1271 support"
depends on WL12XX && GENERIC_HARDIRQS
@@ -74,4 +40,7 @@ config WL1271_SDIO
If you choose to build a module, it'll be called
wl1271_sdio. Say N if unsure.
-
+config WL12XX_PLATFORM_DATA
+ bool
+ depends on WL1271_SDIO != n
+ default y
diff --git a/drivers/net/wireless/wl12xx/Makefile b/drivers/net/wireless/wl12xx/Makefile
index 078b4398ac1f..3a807444b2af 100644
--- a/drivers/net/wireless/wl12xx/Makefile
+++ b/drivers/net/wireless/wl12xx/Makefile
@@ -1,12 +1,3 @@
-wl1251-objs = wl1251_main.o wl1251_event.o \
- wl1251_tx.o wl1251_rx.o wl1251_ps.o wl1251_cmd.o \
- wl1251_acx.o wl1251_boot.o wl1251_init.o \
- wl1251_debugfs.o wl1251_io.o
-
-obj-$(CONFIG_WL1251) += wl1251.o
-obj-$(CONFIG_WL1251_SPI) += wl1251_spi.o
-obj-$(CONFIG_WL1251_SDIO) += wl1251_sdio.o
-
wl1271-objs = wl1271_main.o wl1271_cmd.o wl1271_io.o \
wl1271_event.o wl1271_tx.o wl1271_rx.o \
wl1271_ps.o wl1271_acx.o wl1271_boot.o \
@@ -16,3 +7,6 @@ wl1271-$(CONFIG_NL80211_TESTMODE) += wl1271_testmode.o
obj-$(CONFIG_WL1271) += wl1271.o
obj-$(CONFIG_WL1271_SPI) += wl1271_spi.o
obj-$(CONFIG_WL1271_SDIO) += wl1271_sdio.o
+
+# small builtin driver bit
+obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl12xx_platform_data.o
diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h
index dd3cee6ea5bb..8a4cd763e5a2 100644
--- a/drivers/net/wireless/wl12xx/wl1271.h
+++ b/drivers/net/wireless/wl12xx/wl1271.h
@@ -117,10 +117,7 @@ enum {
#define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff))
#define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff))
-/*
- * Enable/disable 802.11a support for WL1273
- */
-#undef WL1271_80211A_ENABLED
+#define WL1271_CIPHER_SUITE_GEM 0x00147201
#define WL1271_BUSY_WORD_CNT 1
#define WL1271_BUSY_WORD_LEN (WL1271_BUSY_WORD_CNT * sizeof(u32))
@@ -133,6 +130,8 @@ enum {
#define ACX_TX_DESCRIPTORS 32
+#define WL1271_AGGR_BUFFER_SIZE (4 * PAGE_SIZE)
+
enum wl1271_state {
WL1271_STATE_OFF,
WL1271_STATE_ON,
@@ -301,6 +300,7 @@ struct wl1271_rx_mem_pool_addr {
struct wl1271_scan {
struct cfg80211_scan_request *req;
bool *scanned_ch;
+ bool failed;
u8 state;
u8 ssid[IW_ESSID_MAX_SIZE+1];
size_t ssid_len;
@@ -313,7 +313,7 @@ struct wl1271_if_operations {
bool fixed);
void (*reset)(struct wl1271 *wl);
void (*init)(struct wl1271 *wl);
- void (*power)(struct wl1271 *wl, bool enable);
+ int (*power)(struct wl1271 *wl, bool enable);
struct device* (*dev)(struct wl1271 *wl);
void (*enable_irq)(struct wl1271 *wl);
void (*disable_irq)(struct wl1271 *wl);
@@ -330,6 +330,7 @@ struct wl1271 {
void (*set_power)(bool enable);
int irq;
+ int ref_clock;
spinlock_t wl_lock;
@@ -349,6 +350,7 @@ struct wl1271 {
#define WL1271_FLAG_IDLE (10)
#define WL1271_FLAG_IDLE_REQUESTED (11)
#define WL1271_FLAG_PSPOLL_FAILURE (12)
+#define WL1271_FLAG_STA_STATE_SENT (13)
unsigned long flags;
struct wl1271_partition_set part;
@@ -361,6 +363,7 @@ struct wl1271 {
u8 *fw;
size_t fw_len;
struct wl1271_nvs_file *nvs;
+ size_t nvs_len;
s8 hw_pg_ver;
@@ -407,9 +410,15 @@ struct wl1271 {
/* Rx memory pool address */
struct wl1271_rx_mem_pool_addr rx_mem_pool_addr;
+ /* Intermediate buffer, used for packet aggregation */
+ u8 *aggr_buf;
+
/* The target interrupt mask */
struct work_struct irq_work;
+ /* Hardware recovery work */
+ struct work_struct recovery_work;
+
/* The mbox event mask */
u32 event_mask;
@@ -418,6 +427,7 @@ struct wl1271 {
/* Are we currently scanning */
struct wl1271_scan scan;
+ struct delayed_work scan_complete_work;
/* Our association ID */
u16 aid;
@@ -474,6 +484,8 @@ struct wl1271 {
bool sg_enabled;
+ bool enable_11a;
+
struct list_head list;
/* Most recently reported noise in dBm */
@@ -497,14 +509,4 @@ int wl1271_plt_stop(struct wl1271 *wl);
#define WL1271_PRE_POWER_ON_SLEEP 20 /* in miliseconds */
#define WL1271_POWER_ON_SLEEP 200 /* in miliseconds */
-static inline bool wl1271_11a_enabled(void)
-{
- /* FIXME: this could be determined based on the NVS-INI file */
-#ifdef WL1271_80211A_ENABLED
- return true;
-#else
- return false;
-#endif
-}
-
#endif
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c
index bb245f05af49..618993405262 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.c
@@ -86,40 +86,6 @@ out:
return ret;
}
-int wl1271_acx_fw_version(struct wl1271 *wl, char *buf, size_t len)
-{
- struct acx_revision *rev;
- int ret;
-
- wl1271_debug(DEBUG_ACX, "acx fw rev");
-
- rev = kzalloc(sizeof(*rev), GFP_KERNEL);
- if (!rev) {
- ret = -ENOMEM;
- goto out;
- }
-
- ret = wl1271_cmd_interrogate(wl, ACX_FW_REV, rev, sizeof(*rev));
- if (ret < 0) {
- wl1271_warning("ACX_FW_REV interrogate failed");
- goto out;
- }
-
- /* be careful with the buffer sizes */
- strncpy(buf, rev->fw_version, min(len, sizeof(rev->fw_version)));
-
- /*
- * if the firmware version string is exactly
- * sizeof(rev->fw_version) long or fw_len is less than
- * sizeof(rev->fw_version) it won't be null terminated
- */
- buf[min(len, sizeof(rev->fw_version)) - 1] = '\0';
-
-out:
- kfree(rev);
- return ret;
-}
-
int wl1271_acx_tx_power(struct wl1271 *wl, int power)
{
struct acx_current_tx_power *acx;
@@ -269,7 +235,7 @@ int wl1271_acx_pd_threshold(struct wl1271 *wl)
out:
kfree(pd);
- return 0;
+ return ret;
}
int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time)
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h
index 4235bc56f750..ebb341d36e8c 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.h
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.h
@@ -100,35 +100,6 @@ struct acx_error_counter {
__le32 seq_num_miss;
} __packed;
-struct acx_revision {
- struct acx_header header;
-
- /*
- * The WiLink firmware version, an ASCII string x.x.x.x,
- * that uniquely identifies the current firmware.
- * The left most digit is incremented each time a
- * significant change is made to the firmware, such as
- * code redesign or new platform support.
- * The second digit is incremented when major enhancements
- * are added or major fixes are made.
- * The third digit is incremented for each GA release.
- * The fourth digit is incremented for each build.
- * The first two digits identify a firmware release version,
- * in other words, a unique set of features.
- * The first three digits identify a GA release.
- */
- char fw_version[20];
-
- /*
- * This 4 byte field specifies the WiLink hardware version.
- * bits 0 - 15: Reserved.
- * bits 16 - 23: Version ID - The WiLink version ID
- * (1 = first spin, 2 = second spin, and so on).
- * bits 24 - 31: Chip ID - The WiLink chip ID.
- */
- __le32 hw_version;
-} __packed;
-
enum wl1271_psm_mode {
/* Active mode */
WL1271_PSM_CAM = 0,
@@ -1060,7 +1031,6 @@ enum {
ACX_PEER_HT_CAP = 0x0057,
ACX_HT_BSS_OPERATION = 0x0058,
ACX_COEX_ACTIVITY = 0x0059,
- ACX_SET_SMART_REFLEX_DEBUG = 0x005A,
ACX_SET_DCO_ITRIM_PARAMS = 0x0061,
DOT11_RX_MSDU_LIFE_TIME = 0x1004,
DOT11_CUR_TX_PWR = 0x100D,
@@ -1077,7 +1047,6 @@ enum {
int wl1271_acx_wake_up_conditions(struct wl1271 *wl);
int wl1271_acx_sleep_auth(struct wl1271 *wl, u8 sleep_auth);
-int wl1271_acx_fw_version(struct wl1271 *wl, char *buf, size_t len);
int wl1271_acx_tx_power(struct wl1271 *wl, int power);
int wl1271_acx_feature_cfg(struct wl1271 *wl);
int wl1271_acx_mem_map(struct wl1271 *wl,
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c
index f36430b0336d..b91021242098 100644
--- a/drivers/net/wireless/wl12xx/wl1271_boot.c
+++ b/drivers/net/wireless/wl12xx/wl1271_boot.c
@@ -225,6 +225,28 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
if (wl->nvs == NULL)
return -ENODEV;
+ /*
+ * FIXME: the LEGACY NVS image support (NVS's missing the 5GHz band
+ * configurations) can be removed when those NVS files stop floating
+ * around.
+ */
+ if (wl->nvs_len == sizeof(struct wl1271_nvs_file) ||
+ wl->nvs_len == WL1271_INI_LEGACY_NVS_FILE_SIZE) {
+ if (wl->nvs->general_params.dual_mode_select)
+ wl->enable_11a = true;
+ }
+
+ if (wl->nvs_len != sizeof(struct wl1271_nvs_file) &&
+ (wl->nvs_len != WL1271_INI_LEGACY_NVS_FILE_SIZE ||
+ wl->enable_11a)) {
+ wl1271_error("nvs size is not as expected: %zu != %zu",
+ wl->nvs_len, sizeof(struct wl1271_nvs_file));
+ kfree(wl->nvs);
+ wl->nvs = NULL;
+ wl->nvs_len = 0;
+ return -EILSEQ;
+ }
+
/* only the first part of the NVS needs to be uploaded */
nvs_len = sizeof(wl->nvs->nvs);
nvs_ptr = (u8 *)wl->nvs->nvs;
@@ -251,8 +273,10 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
burst_len = nvs_ptr[0];
dest_addr = (nvs_ptr[1] & 0xfe) | ((u32)(nvs_ptr[2] << 8));
- /* FIXME: Due to our new wl1271_translate_reg_addr function,
- we need to add the REGISTER_BASE to the destination */
+ /*
+ * Due to our new wl1271_translate_reg_addr function,
+ * we need to add the REGISTER_BASE to the destination
+ */
dest_addr += REGISTERS_BASE;
/* We move our pointer to the data */
@@ -274,31 +298,21 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
/*
* We've reached the first zero length, the first NVS table
- * is 7 bytes further.
+ * is located at an aligned offset which is at least 7 bytes further.
*/
- nvs_ptr += 7;
+ nvs_ptr = (u8 *)wl->nvs->nvs +
+ ALIGN(nvs_ptr - (u8 *)wl->nvs->nvs + 7, 4);
nvs_len -= nvs_ptr - (u8 *)wl->nvs->nvs;
- nvs_len = ALIGN(nvs_len, 4);
- /* FIXME: The driver sets the partition here, but this is not needed,
- since it sets to the same one as currently in use */
/* Now we must set the partition correctly */
wl1271_set_partition(wl, &part_table[PART_WORK]);
/* Copy the NVS tables to a new block to ensure alignment */
- /* FIXME: We jump 3 more bytes before uploading the NVS. It seems
- that our NVS files have three extra zeros here. I'm not sure whether
- the problem is in our NVS generation or we should really jumpt these
- 3 bytes here */
- nvs_ptr += 3;
-
- nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL); if
- (!nvs_aligned) return -ENOMEM;
+ nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL);
+ if (!nvs_aligned)
+ return -ENOMEM;
/* And finally we upload the NVS tables */
- /* FIXME: In wl1271, we upload everything at once.
- No endianness handling needed here?! The ref driver doesn't do
- anything about it at this point */
wl1271_write(wl, CMD_MBOX_ADDRESS, nvs_aligned, nvs_len, false);
kfree(nvs_aligned);
@@ -457,17 +471,20 @@ int wl1271_boot(struct wl1271 *wl)
{
int ret = 0;
u32 tmp, clk, pause;
+ int ref_clock = wl->ref_clock;
wl1271_boot_hw_version(wl);
- if (REF_CLOCK == 0 || REF_CLOCK == 2 || REF_CLOCK == 4)
+ if (ref_clock == 0 || ref_clock == 2 || ref_clock == 4)
/* ref clk: 19.2/38.4/38.4-XTAL */
clk = 0x3;
- else if (REF_CLOCK == 1 || REF_CLOCK == 3)
+ else if (ref_clock == 1 || ref_clock == 3)
/* ref clk: 26/52 */
clk = 0x5;
+ else
+ return -EINVAL;
- if (REF_CLOCK != 0) {
+ if (ref_clock != 0) {
u16 val;
/* Set clock type (open drain) */
val = wl1271_top_reg_read(wl, OCP_REG_CLK_TYPE);
@@ -493,10 +510,7 @@ int wl1271_boot(struct wl1271 *wl)
wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause);
- pause &= ~(WU_COUNTER_PAUSE_VAL); /* FIXME: This should probably be
- * WU_COUNTER_PAUSE_VAL instead of
- * 0x3ff (magic number ). How does
- * this work?! */
+ pause &= ~(WU_COUNTER_PAUSE_VAL);
pause |= WU_COUNTER_PAUSE_VAL;
wl1271_write32(wl, WU_COUNTER_PAUSE, pause);
@@ -516,7 +530,7 @@ int wl1271_boot(struct wl1271 *wl)
wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk);
/* 2 */
- clk |= (REF_CLOCK << 1) << 4;
+ clk |= (ref_clock << 1) << 4;
wl1271_write32(wl, DRPW_SCRATCH_START, clk);
wl1271_set_partition(wl, &part_table[PART_WORK]);
@@ -550,7 +564,6 @@ int wl1271_boot(struct wl1271 *wl)
if (ret < 0)
goto out;
- /* FIXME: Need to check whether this is really what we want */
wl1271_write32(wl, ACX_REG_INTERRUPT_MASK,
WL1271_ACX_ALL_EVENTS_VECTOR);
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.h b/drivers/net/wireless/wl12xx/wl1271_boot.h
index f829699d597e..f73b0b15a280 100644
--- a/drivers/net/wireless/wl12xx/wl1271_boot.h
+++ b/drivers/net/wireless/wl12xx/wl1271_boot.h
@@ -46,7 +46,6 @@ struct wl1271_static_data {
/* delay between retries */
#define INIT_LOOP_DELAY 50
-#define REF_CLOCK 2
#define WU_COUNTER_PAUSE_VAL 0x3FF
#define WELP_ARM_COMMAND_VAL 0x4
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c
index ce503ddd5a41..5d3e8485ea4e 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.c
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c
@@ -94,6 +94,7 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
status = le16_to_cpu(cmd->status);
if (status != CMD_STATUS_SUCCESS) {
wl1271_error("command execute failure %d", status);
+ ieee80211_queue_work(wl->hw, &wl->recovery_work);
ret = -EIO;
}
@@ -107,6 +108,8 @@ out:
int wl1271_cmd_general_parms(struct wl1271 *wl)
{
struct wl1271_general_parms_cmd *gen_parms;
+ struct wl1271_ini_general_params *gp = &wl->nvs->general_params;
+ bool answer = false;
int ret;
if (!wl->nvs)
@@ -118,13 +121,24 @@ int wl1271_cmd_general_parms(struct wl1271 *wl)
gen_parms->test.id = TEST_CMD_INI_FILE_GENERAL_PARAM;
- memcpy(&gen_parms->general_params, &wl->nvs->general_params,
- sizeof(struct wl1271_ini_general_params));
+ memcpy(&gen_parms->general_params, gp, sizeof(*gp));
- ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), 0);
- if (ret < 0)
+ if (gp->tx_bip_fem_auto_detect)
+ answer = true;
+
+ ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer);
+ if (ret < 0) {
wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed");
+ goto out;
+ }
+
+ gp->tx_bip_fem_manufacturer =
+ gen_parms->general_params.tx_bip_fem_manufacturer;
+
+ wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n",
+ answer ? "auto" : "manual", gp->tx_bip_fem_manufacturer);
+out:
kfree(gen_parms);
return ret;
}
@@ -170,6 +184,39 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl)
return ret;
}
+int wl1271_cmd_ext_radio_parms(struct wl1271 *wl)
+{
+ struct wl1271_ext_radio_parms_cmd *ext_radio_parms;
+ struct conf_rf_settings *rf = &wl->conf.rf;
+ int ret;
+
+ if (!wl->nvs)
+ return -ENODEV;
+
+ ext_radio_parms = kzalloc(sizeof(*ext_radio_parms), GFP_KERNEL);
+ if (!ext_radio_parms)
+ return -ENOMEM;
+
+ ext_radio_parms->test.id = TEST_CMD_INI_FILE_RF_EXTENDED_PARAM;
+
+ memcpy(ext_radio_parms->tx_per_channel_power_compensation_2,
+ rf->tx_per_channel_power_compensation_2,
+ CONF_TX_PWR_COMPENSATION_LEN_2);
+ memcpy(ext_radio_parms->tx_per_channel_power_compensation_5,
+ rf->tx_per_channel_power_compensation_5,
+ CONF_TX_PWR_COMPENSATION_LEN_5);
+
+ wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_EXT_RADIO_PARAM: ",
+ ext_radio_parms, sizeof(*ext_radio_parms));
+
+ ret = wl1271_cmd_test(wl, ext_radio_parms, sizeof(*ext_radio_parms), 0);
+ if (ret < 0)
+ wl1271_warning("TEST_CMD_INI_FILE_RF_EXTENDED_PARAM failed");
+
+ kfree(ext_radio_parms);
+ return ret;
+}
+
/*
* Poll the mailbox event field until any of the bits in the mask is set or a
* timeout occurs (WL1271_EVENT_TIMEOUT in msecs)
@@ -182,8 +229,10 @@ static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask)
timeout = jiffies + msecs_to_jiffies(WL1271_EVENT_TIMEOUT);
do {
- if (time_after(jiffies, timeout))
+ if (time_after(jiffies, timeout)) {
+ ieee80211_queue_work(wl->hw, &wl->recovery_work);
return -ETIMEDOUT;
+ }
msleep(1);
@@ -390,18 +439,11 @@ out:
return ret;
}
-int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send)
+int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, u32 rates, bool send)
{
struct wl1271_cmd_ps_params *ps_params = NULL;
int ret = 0;
- /* FIXME: this should be in ps.c */
- ret = wl1271_acx_wake_up_conditions(wl);
- if (ret < 0) {
- wl1271_error("couldn't set wake up conditions");
- goto out;
- }
-
wl1271_debug(DEBUG_CMD, "cmd set ps mode");
ps_params = kzalloc(sizeof(*ps_params), GFP_KERNEL);
@@ -412,9 +454,9 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send)
ps_params->ps_mode = ps_mode;
ps_params->send_null_data = send;
- ps_params->retries = 5;
- ps_params->hang_over_period = 1;
- ps_params->null_data_rate = cpu_to_le32(wl->basic_rate_set);
+ ps_params->retries = wl->conf.conn.psm_entry_nullfunc_retries;
+ ps_params->hang_over_period = wl->conf.conn.psm_entry_hangover_period;
+ ps_params->null_data_rate = cpu_to_le32(rates);
ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params,
sizeof(*ps_params), 0);
@@ -428,41 +470,6 @@ out:
return ret;
}
-int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer,
- size_t len)
-{
- struct cmd_read_write_memory *cmd;
- int ret = 0;
-
- wl1271_debug(DEBUG_CMD, "cmd read memory");
-
- cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
- if (!cmd) {
- ret = -ENOMEM;
- goto out;
- }
-
- WARN_ON(len > MAX_READ_SIZE);
- len = min_t(size_t, len, MAX_READ_SIZE);
-
- cmd->addr = cpu_to_le32(addr);
- cmd->size = cpu_to_le32(len);
-
- ret = wl1271_cmd_send(wl, CMD_READ_MEMORY, cmd, sizeof(*cmd),
- sizeof(*cmd));
- if (ret < 0) {
- wl1271_error("read memory command failed: %d", ret);
- goto out;
- }
-
- /* the read command got in */
- memcpy(answer, cmd->value, len);
-
-out:
- kfree(cmd);
- return ret;
-}
-
int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id,
void *buf, size_t buf_len, int index, u32 rates)
{
@@ -523,7 +530,7 @@ int wl1271_cmd_build_null_data(struct wl1271 *wl)
}
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, ptr, size, 0,
- WL1271_RATE_AUTOMATIC);
+ wl->basic_rate);
out:
dev_kfree_skb(skb);
@@ -546,7 +553,7 @@ int wl1271_cmd_build_klv_null_data(struct wl1271 *wl)
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV,
skb->data, skb->len,
CMD_TEMPL_KLV_IDX_NULL_DATA,
- WL1271_RATE_AUTOMATIC);
+ wl->basic_rate);
out:
dev_kfree_skb(skb);
@@ -623,7 +630,7 @@ int wl1271_build_qos_null_data(struct wl1271 *wl)
return wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, &template,
sizeof(template), 0,
- WL1271_RATE_AUTOMATIC);
+ wl->basic_rate);
}
int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id)
@@ -746,3 +753,31 @@ out_free:
out:
return ret;
}
+
+int wl1271_cmd_set_sta_state(struct wl1271 *wl)
+{
+ struct wl1271_cmd_set_sta_state *cmd;
+ int ret = 0;
+
+ wl1271_debug(DEBUG_CMD, "cmd set sta state");
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ cmd->state = WL1271_CMD_STA_STATE_CONNECTED;
+
+ ret = wl1271_cmd_send(wl, CMD_SET_STA_STATE, cmd, sizeof(*cmd), 0);
+ if (ret < 0) {
+ wl1271_error("failed to send set STA state command");
+ goto out_free;
+ }
+
+out_free:
+ kfree(cmd);
+
+out:
+ return ret;
+}
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h
index af577ee8eb02..a0caf4fc37b1 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.h
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h
@@ -33,12 +33,13 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
size_t res_len);
int wl1271_cmd_general_parms(struct wl1271 *wl);
int wl1271_cmd_radio_parms(struct wl1271 *wl);
+int wl1271_cmd_ext_radio_parms(struct wl1271 *wl);
int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type);
int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer);
int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len);
int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len);
int wl1271_cmd_data_path(struct wl1271 *wl, bool enable);
-int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send);
+int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, u32 rates, bool send);
int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer,
size_t len);
int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id,
@@ -55,6 +56,7 @@ int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
u8 key_size, const u8 *key, const u8 *addr,
u32 tx_seq_32, u16 tx_seq_16);
int wl1271_cmd_disconnect(struct wl1271 *wl);
+int wl1271_cmd_set_sta_state(struct wl1271 *wl);
enum wl1271_commands {
CMD_INTERROGATE = 1, /*use this to read information elements*/
@@ -160,41 +162,6 @@ enum {
MAX_COMMAND_STATUS = 0xff
};
-
-/*
- * CMD_READ_MEMORY
- *
- * The host issues this command to read the WiLink device memory/registers.
- *
- * Note: The Base Band address has special handling (16 bits registers and
- * addresses). For more information, see the hardware specification.
- */
-/*
- * CMD_WRITE_MEMORY
- *
- * The host issues this command to write the WiLink device memory/registers.
- *
- * The Base Band address has special handling (16 bits registers and
- * addresses). For more information, see the hardware specification.
- */
-#define MAX_READ_SIZE 256
-
-struct cmd_read_write_memory {
- struct wl1271_cmd_header header;
-
- /* The address of the memory to read from or write to.*/
- __le32 addr;
-
- /* The amount of data in bytes to read from or write to the WiLink
- * device.*/
- __le32 size;
-
- /* The actual value read from or written to the Wilink. The source
- of this field is the Host in WRITE command or the Wilink in READ
- command. */
- u8 value[MAX_READ_SIZE];
-} __packed;
-
#define CMDMBOX_HEADER_LEN 4
#define CMDMBOX_INFO_ELEM_HEADER_LEN 4
@@ -313,7 +280,7 @@ enum wl1271_cmd_key_type {
KEY_WEP = 1,
KEY_TKIP = 2,
KEY_AES = 3,
- KEY_GEM = 4
+ KEY_GEM = 4,
};
/* FIXME: Add description for key-types */
@@ -358,13 +325,14 @@ enum wl1271_channel_tune_bands {
WL1271_CHANNEL_TUNE_BAND_4_9
};
-#define WL1271_PD_REFERENCE_POINT_BAND_B_G 0
+#define WL1271_PD_REFERENCE_POINT_BAND_B_G 0
-#define TEST_CMD_P2G_CAL 0x02
-#define TEST_CMD_CHANNEL_TUNE 0x0d
-#define TEST_CMD_UPDATE_PD_REFERENCE_POINT 0x1d
-#define TEST_CMD_INI_FILE_RADIO_PARAM 0x19
-#define TEST_CMD_INI_FILE_GENERAL_PARAM 0x1E
+#define TEST_CMD_P2G_CAL 0x02
+#define TEST_CMD_CHANNEL_TUNE 0x0d
+#define TEST_CMD_UPDATE_PD_REFERENCE_POINT 0x1d
+#define TEST_CMD_INI_FILE_RADIO_PARAM 0x19
+#define TEST_CMD_INI_FILE_GENERAL_PARAM 0x1E
+#define TEST_CMD_INI_FILE_RF_EXTENDED_PARAM 0x26
struct wl1271_general_parms_cmd {
struct wl1271_cmd_header header;
@@ -397,6 +365,16 @@ struct wl1271_radio_parms_cmd {
u8 padding3[2];
} __packed;
+struct wl1271_ext_radio_parms_cmd {
+ struct wl1271_cmd_header header;
+
+ struct wl1271_cmd_test_header test;
+
+ u8 tx_per_channel_power_compensation_2[CONF_TX_PWR_COMPENSATION_LEN_2];
+ u8 tx_per_channel_power_compensation_5[CONF_TX_PWR_COMPENSATION_LEN_5];
+ u8 padding[3];
+} __packed;
+
struct wl1271_cmd_cal_channel_tune {
struct wl1271_cmd_header header;
@@ -469,4 +447,13 @@ struct wl1271_cmd_disconnect {
u8 padding;
} __packed;
+#define WL1271_CMD_STA_STATE_CONNECTED 1
+
+struct wl1271_cmd_set_sta_state {
+ struct wl1271_cmd_header header;
+
+ u8 state;
+ u8 padding[3];
+} __packed;
+
#endif /* __WL1271_CMD_H__ */
diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h
index 0435ffda8f73..5f78a6cb1433 100644
--- a/drivers/net/wireless/wl12xx/wl1271_conf.h
+++ b/drivers/net/wireless/wl12xx/wl1271_conf.h
@@ -595,7 +595,7 @@ struct conf_tx_ac_category {
u16 tx_op_limit;
};
-#define CONF_TX_MAX_TID_COUNT 7
+#define CONF_TX_MAX_TID_COUNT 8
enum {
CONF_CHANNEL_TYPE_DCF = 0, /* DC/LEGACY*/
@@ -912,6 +912,22 @@ struct conf_conn_settings {
u8 psm_entry_retries;
/*
+ * Specifies the maximum number of times to try transmit the PSM entry
+ * null-func frame for each PSM entry attempt
+ *
+ * Range 0 - 255
+ */
+ u8 psm_entry_nullfunc_retries;
+
+ /*
+ * Specifies the time to linger in active mode after successfully
+ * transmitting the PSM entry null-func frame.
+ *
+ * Range 0 - 255 TU's
+ */
+ u8 psm_entry_hangover_period;
+
+ /*
*
* Specifies the interval of the connection keep-alive null-func
* frame in ms.
@@ -1016,6 +1032,64 @@ struct conf_roam_trigger_settings {
u8 avg_weight_snr_data;
};
+struct conf_scan_settings {
+ /*
+ * The minimum time to wait on each channel for active scans
+ *
+ * Range: 0 - 65536 tu
+ */
+ u16 min_dwell_time_active;
+
+ /*
+ * The maximum time to wait on each channel for active scans
+ *
+ * Range: 0 - 65536 tu
+ */
+ u16 max_dwell_time_active;
+
+ /*
+ * The maximum time to wait on each channel for passive scans
+ *
+ * Range: 0 - 65536 tu
+ */
+ u16 min_dwell_time_passive;
+
+ /*
+ * The maximum time to wait on each channel for passive scans
+ *
+ * Range: 0 - 65536 tu
+ */
+ u16 max_dwell_time_passive;
+
+ /*
+ * Number of probe requests to transmit on each active scan channel
+ *
+ * Range: u8
+ */
+ u16 num_probe_reqs;
+
+};
+
+/* these are number of channels on the band divided by two, rounded up */
+#define CONF_TX_PWR_COMPENSATION_LEN_2 7
+#define CONF_TX_PWR_COMPENSATION_LEN_5 18
+
+struct conf_rf_settings {
+ /*
+ * Per channel power compensation for 2.4GHz
+ *
+ * Range: s8
+ */
+ u8 tx_per_channel_power_compensation_2[CONF_TX_PWR_COMPENSATION_LEN_2];
+
+ /*
+ * Per channel power compensation for 5GHz
+ *
+ * Range: s8
+ */
+ u8 tx_per_channel_power_compensation_5[CONF_TX_PWR_COMPENSATION_LEN_5];
+};
+
struct conf_drv_settings {
struct conf_sg_settings sg;
struct conf_rx_settings rx;
@@ -1024,6 +1098,8 @@ struct conf_drv_settings {
struct conf_itrim_settings itrim;
struct conf_pm_config_settings pm_config;
struct conf_roam_trigger_settings roam_trigger;
+ struct conf_scan_settings scan;
+ struct conf_rf_settings rf;
};
#endif
diff --git a/drivers/net/wireless/wl12xx/wl1271_debugfs.c b/drivers/net/wireless/wl12xx/wl1271_debugfs.c
index c239ef4d0b8d..66c2b90ddfd4 100644
--- a/drivers/net/wireless/wl12xx/wl1271_debugfs.c
+++ b/drivers/net/wireless/wl12xx/wl1271_debugfs.c
@@ -51,6 +51,7 @@ static ssize_t name## _read(struct file *file, char __user *userbuf, \
static const struct file_operations name## _ops = { \
.read = name## _read, \
.open = wl1271_open_file_generic, \
+ .llseek = generic_file_llseek, \
};
#define DEBUGFS_ADD(name, parent) \
@@ -87,6 +88,7 @@ static ssize_t sub## _ ##name## _read(struct file *file, \
static const struct file_operations sub## _ ##name## _ops = { \
.read = sub## _ ##name## _read, \
.open = wl1271_open_file_generic, \
+ .llseek = generic_file_llseek, \
};
#define DEBUGFS_FWSTATS_ADD(sub, name) \
@@ -237,6 +239,7 @@ static ssize_t tx_queue_len_read(struct file *file, char __user *userbuf,
static const struct file_operations tx_queue_len_ops = {
.read = tx_queue_len_read,
.open = wl1271_open_file_generic,
+ .llseek = default_llseek,
};
static ssize_t gpio_power_read(struct file *file, char __user *user_buf,
@@ -291,7 +294,8 @@ out:
static const struct file_operations gpio_power_ops = {
.read = gpio_power_read,
.write = gpio_power_write,
- .open = wl1271_open_file_generic
+ .open = wl1271_open_file_generic,
+ .llseek = default_llseek,
};
static void wl1271_debugfs_delete_files(struct wl1271 *wl)
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c
index 25ce2cd5e3f3..7b3f50382963 100644
--- a/drivers/net/wireless/wl12xx/wl1271_event.c
+++ b/drivers/net/wireless/wl12xx/wl1271_event.c
@@ -41,6 +41,9 @@ void wl1271_pspoll_work(struct work_struct *work)
mutex_lock(&wl->mutex);
+ if (unlikely(wl->state == WL1271_STATE_OFF))
+ goto out;
+
if (!test_and_clear_bit(WL1271_FLAG_PSPOLL_FAILURE, &wl->flags))
goto out;
@@ -52,7 +55,7 @@ void wl1271_pspoll_work(struct work_struct *work)
* delivery failure occurred, and no-one changed state since, so
* we should go back to powersave.
*/
- wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, true);
+ wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, wl->basic_rate, true);
out:
mutex_unlock(&wl->mutex);
@@ -70,7 +73,8 @@ static void wl1271_event_pspoll_delivery_fail(struct wl1271 *wl)
/* force active mode receive data from the AP */
if (test_bit(WL1271_FLAG_PSM, &wl->flags)) {
- ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, true);
+ ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE,
+ wl->basic_rate, true);
if (ret < 0)
return;
set_bit(WL1271_FLAG_PSPOLL_FAILURE, &wl->flags);
@@ -91,6 +95,7 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
bool *beacon_loss)
{
int ret = 0;
+ u32 total_retries = wl->conf.conn.psm_entry_retries;
wl1271_debug(DEBUG_EVENT, "ps_status: 0x%x", mbox->ps_status);
@@ -104,10 +109,10 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
break;
}
- if (wl->psm_entry_retry < wl->conf.conn.psm_entry_retries) {
+ if (wl->psm_entry_retry < total_retries) {
wl->psm_entry_retry++;
ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE,
- true);
+ wl->basic_rate, true);
} else {
wl1271_info("No ack to nullfunc from AP.");
wl->psm_entry_retry = 0;
@@ -143,7 +148,7 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
/* make sure the firmware goes to active mode - the frame to
be sent next will indicate to the AP, that we are active. */
ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE,
- false);
+ wl->basic_rate, false);
break;
case EVENT_EXIT_POWER_SAVE_SUCCESS:
default:
diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c
index 4447af1557f5..8044bba70ee7 100644
--- a/drivers/net/wireless/wl12xx/wl1271_init.c
+++ b/drivers/net/wireless/wl12xx/wl1271_init.c
@@ -53,6 +53,7 @@ static int wl1271_init_hwenc_config(struct wl1271 *wl)
int wl1271_init_templates_config(struct wl1271 *wl)
{
int ret, i;
+ size_t size;
/* send empty templates for fw memory reservation */
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL,
@@ -61,14 +62,12 @@ int wl1271_init_templates_config(struct wl1271 *wl)
if (ret < 0)
return ret;
- if (wl1271_11a_enabled()) {
- size_t size = sizeof(struct wl12xx_probe_req_template);
- ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5,
- NULL, size, 0,
- WL1271_RATE_AUTOMATIC);
- if (ret < 0)
- return ret;
- }
+ size = sizeof(struct wl12xx_probe_req_template);
+ ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5,
+ NULL, size, 0,
+ WL1271_RATE_AUTOMATIC);
+ if (ret < 0)
+ return ret;
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, NULL,
sizeof(struct wl12xx_null_data_template),
@@ -223,6 +222,10 @@ int wl1271_hw_init(struct wl1271 *wl)
if (ret < 0)
return ret;
+ ret = wl1271_cmd_ext_radio_parms(wl);
+ if (ret < 0)
+ return ret;
+
/* Template settings */
ret = wl1271_init_templates_config(wl);
if (ret < 0)
@@ -291,8 +294,16 @@ int wl1271_hw_init(struct wl1271 *wl)
if (ret < 0)
goto out_free_memmap;
- /* Default TID configuration */
+ /* Default TID/AC configuration */
+ BUG_ON(wl->conf.tx.tid_conf_count != wl->conf.tx.ac_conf_count);
for (i = 0; i < wl->conf.tx.tid_conf_count; i++) {
+ conf_ac = &wl->conf.tx.ac_conf[i];
+ ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min,
+ conf_ac->cw_max, conf_ac->aifsn,
+ conf_ac->tx_op_limit);
+ if (ret < 0)
+ goto out_free_memmap;
+
conf_tid = &wl->conf.tx.tid_conf[i];
ret = wl1271_acx_tid_cfg(wl, conf_tid->queue_id,
conf_tid->channel_type,
@@ -305,16 +316,6 @@ int wl1271_hw_init(struct wl1271 *wl)
goto out_free_memmap;
}
- /* Default AC configuration */
- for (i = 0; i < wl->conf.tx.ac_conf_count; i++) {
- conf_ac = &wl->conf.tx.ac_conf[i];
- ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min,
- conf_ac->cw_max, conf_ac->aifsn,
- conf_ac->tx_op_limit);
- if (ret < 0)
- goto out_free_memmap;
- }
-
/* Configure TX rate classes */
ret = wl1271_acx_rate_policies(wl);
if (ret < 0)
diff --git a/drivers/net/wireless/wl12xx/wl1271_io.h b/drivers/net/wireless/wl12xx/wl1271_io.h
index bc806c74c63a..c1f92e65ded0 100644
--- a/drivers/net/wireless/wl12xx/wl1271_io.h
+++ b/drivers/net/wireless/wl12xx/wl1271_io.h
@@ -144,10 +144,13 @@ static inline void wl1271_power_off(struct wl1271 *wl)
clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
}
-static inline void wl1271_power_on(struct wl1271 *wl)
+static inline int wl1271_power_on(struct wl1271 *wl)
{
- wl->if_ops->power(wl, true);
- set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
+ int ret = wl->if_ops->power(wl, true);
+ if (ret == 0)
+ set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
+
+ return ret;
}
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 9d68f0012f05..48a4b9961ae6 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -124,28 +124,28 @@ static struct conf_drv_settings default_conf = {
},
.ac_conf_count = 4,
.ac_conf = {
- [0] = {
+ [CONF_TX_AC_BE] = {
.ac = CONF_TX_AC_BE,
.cw_min = 15,
.cw_max = 63,
.aifsn = 3,
.tx_op_limit = 0,
},
- [1] = {
+ [CONF_TX_AC_BK] = {
.ac = CONF_TX_AC_BK,
.cw_min = 15,
.cw_max = 63,
.aifsn = 7,
.tx_op_limit = 0,
},
- [2] = {
+ [CONF_TX_AC_VI] = {
.ac = CONF_TX_AC_VI,
.cw_min = 15,
.cw_max = 63,
.aifsn = CONF_TX_AIFS_PIFS,
.tx_op_limit = 3008,
},
- [3] = {
+ [CONF_TX_AC_VO] = {
.ac = CONF_TX_AC_VO,
.cw_min = 15,
.cw_max = 63,
@@ -153,64 +153,40 @@ static struct conf_drv_settings default_conf = {
.tx_op_limit = 1504,
},
},
- .tid_conf_count = 7,
+ .tid_conf_count = 4,
.tid_conf = {
- [0] = {
- .queue_id = 0,
- .channel_type = CONF_CHANNEL_TYPE_DCF,
- .tsid = CONF_TX_AC_BE,
- .ps_scheme = CONF_PS_SCHEME_LEGACY,
- .ack_policy = CONF_ACK_POLICY_LEGACY,
- .apsd_conf = {0, 0},
- },
- [1] = {
- .queue_id = 1,
- .channel_type = CONF_CHANNEL_TYPE_DCF,
+ [CONF_TX_AC_BE] = {
+ .queue_id = CONF_TX_AC_BE,
+ .channel_type = CONF_CHANNEL_TYPE_EDCF,
.tsid = CONF_TX_AC_BE,
.ps_scheme = CONF_PS_SCHEME_LEGACY,
.ack_policy = CONF_ACK_POLICY_LEGACY,
.apsd_conf = {0, 0},
},
- [2] = {
- .queue_id = 2,
- .channel_type = CONF_CHANNEL_TYPE_DCF,
- .tsid = CONF_TX_AC_BE,
+ [CONF_TX_AC_BK] = {
+ .queue_id = CONF_TX_AC_BK,
+ .channel_type = CONF_CHANNEL_TYPE_EDCF,
+ .tsid = CONF_TX_AC_BK,
.ps_scheme = CONF_PS_SCHEME_LEGACY,
.ack_policy = CONF_ACK_POLICY_LEGACY,
.apsd_conf = {0, 0},
},
- [3] = {
- .queue_id = 3,
- .channel_type = CONF_CHANNEL_TYPE_DCF,
- .tsid = CONF_TX_AC_BE,
- .ps_scheme = CONF_PS_SCHEME_LEGACY,
- .ack_policy = CONF_ACK_POLICY_LEGACY,
- .apsd_conf = {0, 0},
- },
- [4] = {
- .queue_id = 4,
- .channel_type = CONF_CHANNEL_TYPE_DCF,
- .tsid = CONF_TX_AC_BE,
+ [CONF_TX_AC_VI] = {
+ .queue_id = CONF_TX_AC_VI,
+ .channel_type = CONF_CHANNEL_TYPE_EDCF,
+ .tsid = CONF_TX_AC_VI,
.ps_scheme = CONF_PS_SCHEME_LEGACY,
.ack_policy = CONF_ACK_POLICY_LEGACY,
.apsd_conf = {0, 0},
},
- [5] = {
- .queue_id = 5,
- .channel_type = CONF_CHANNEL_TYPE_DCF,
- .tsid = CONF_TX_AC_BE,
+ [CONF_TX_AC_VO] = {
+ .queue_id = CONF_TX_AC_VO,
+ .channel_type = CONF_CHANNEL_TYPE_EDCF,
+ .tsid = CONF_TX_AC_VO,
.ps_scheme = CONF_PS_SCHEME_LEGACY,
.ack_policy = CONF_ACK_POLICY_LEGACY,
.apsd_conf = {0, 0},
},
- [6] = {
- .queue_id = 6,
- .channel_type = CONF_CHANNEL_TYPE_DCF,
- .tsid = CONF_TX_AC_BE,
- .ps_scheme = CONF_PS_SCHEME_LEGACY,
- .ack_policy = CONF_ACK_POLICY_LEGACY,
- .apsd_conf = {0, 0},
- }
},
.frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD,
.tx_compl_timeout = 700,
@@ -238,7 +214,9 @@ static struct conf_drv_settings default_conf = {
.ps_poll_recovery_period = 700,
.bet_enable = CONF_BET_MODE_ENABLE,
.bet_max_consecutive = 10,
- .psm_entry_retries = 3,
+ .psm_entry_retries = 5,
+ .psm_entry_nullfunc_retries = 3,
+ .psm_entry_hangover_period = 1,
.keep_alive_interval = 55000,
.max_listen_interval = 20,
},
@@ -251,15 +229,34 @@ static struct conf_drv_settings default_conf = {
.host_fast_wakeup_support = false
},
.roam_trigger = {
- /* FIXME: due to firmware bug, must use value 1 for now */
.trigger_pacing = 1,
.avg_weight_rssi_beacon = 20,
.avg_weight_rssi_data = 10,
.avg_weight_snr_beacon = 20,
.avg_weight_snr_data = 10
- }
+ },
+ .scan = {
+ .min_dwell_time_active = 7500,
+ .max_dwell_time_active = 30000,
+ .min_dwell_time_passive = 30000,
+ .max_dwell_time_passive = 60000,
+ .num_probe_reqs = 2,
+ },
+ .rf = {
+ .tx_per_channel_power_compensation_2 = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ },
+ .tx_per_channel_power_compensation_5 = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ },
+ },
};
+static void __wl1271_op_remove_interface(struct wl1271 *wl);
+
+
static void wl1271_device_release(struct device *dev)
{
@@ -277,6 +274,67 @@ static struct platform_device wl1271_device = {
static LIST_HEAD(wl_list);
+static int wl1271_dev_notify(struct notifier_block *me, unsigned long what,
+ void *arg)
+{
+ struct net_device *dev = arg;
+ struct wireless_dev *wdev;
+ struct wiphy *wiphy;
+ struct ieee80211_hw *hw;
+ struct wl1271 *wl;
+ struct wl1271 *wl_temp;
+ int ret = 0;
+
+ /* Check that this notification is for us. */
+ if (what != NETDEV_CHANGE)
+ return NOTIFY_DONE;
+
+ wdev = dev->ieee80211_ptr;
+ if (wdev == NULL)
+ return NOTIFY_DONE;
+
+ wiphy = wdev->wiphy;
+ if (wiphy == NULL)
+ return NOTIFY_DONE;
+
+ hw = wiphy_priv(wiphy);
+ if (hw == NULL)
+ return NOTIFY_DONE;
+
+ wl_temp = hw->priv;
+ list_for_each_entry(wl, &wl_list, list) {
+ if (wl == wl_temp)
+ break;
+ }
+ if (wl != wl_temp)
+ return NOTIFY_DONE;
+
+ mutex_lock(&wl->mutex);
+
+ if (wl->state == WL1271_STATE_OFF)
+ goto out;
+
+ if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
+ goto out;
+
+ ret = wl1271_ps_elp_wakeup(wl, false);
+ if (ret < 0)
+ goto out;
+
+ if ((dev->operstate == IF_OPER_UP) &&
+ !test_and_set_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags)) {
+ wl1271_cmd_set_sta_state(wl);
+ wl1271_info("Association completed.");
+ }
+
+ wl1271_ps_elp_sleep(wl);
+
+out:
+ mutex_unlock(&wl->mutex);
+
+ return NOTIFY_OK;
+}
+
static void wl1271_conf_init(struct wl1271 *wl)
{
@@ -309,6 +367,10 @@ static int wl1271_plt_init(struct wl1271 *wl)
if (ret < 0)
return ret;
+ ret = wl1271_cmd_ext_radio_parms(wl);
+ if (ret < 0)
+ return ret;
+
ret = wl1271_init_templates_config(wl);
if (ret < 0)
return ret;
@@ -346,8 +408,16 @@ static int wl1271_plt_init(struct wl1271 *wl)
if (ret < 0)
goto out_free_memmap;
- /* Default TID configuration */
+ /* Default TID/AC configuration */
+ BUG_ON(wl->conf.tx.tid_conf_count != wl->conf.tx.ac_conf_count);
for (i = 0; i < wl->conf.tx.tid_conf_count; i++) {
+ conf_ac = &wl->conf.tx.ac_conf[i];
+ ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min,
+ conf_ac->cw_max, conf_ac->aifsn,
+ conf_ac->tx_op_limit);
+ if (ret < 0)
+ goto out_free_memmap;
+
conf_tid = &wl->conf.tx.tid_conf[i];
ret = wl1271_acx_tid_cfg(wl, conf_tid->queue_id,
conf_tid->channel_type,
@@ -360,16 +430,6 @@ static int wl1271_plt_init(struct wl1271 *wl)
goto out_free_memmap;
}
- /* Default AC configuration */
- for (i = 0; i < wl->conf.tx.ac_conf_count; i++) {
- conf_ac = &wl->conf.tx.ac_conf[i];
- ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min,
- conf_ac->cw_max, conf_ac->aifsn,
- conf_ac->tx_op_limit);
- if (ret < 0)
- goto out_free_memmap;
- }
-
/* Enable data path */
ret = wl1271_cmd_data_path(wl, 1);
if (ret < 0)
@@ -562,20 +622,6 @@ static int wl1271_fetch_nvs(struct wl1271 *wl)
return ret;
}
- /*
- * FIXME: the LEGACY NVS image support (NVS's missing the 5GHz band
- * configurations) can be removed when those NVS files stop floating
- * around.
- */
- if (fw->size != sizeof(struct wl1271_nvs_file) &&
- (fw->size != WL1271_INI_LEGACY_NVS_FILE_SIZE ||
- wl1271_11a_enabled())) {
- wl1271_error("nvs size is not as expected: %zu != %zu",
- fw->size, sizeof(struct wl1271_nvs_file));
- ret = -EILSEQ;
- goto out;
- }
-
wl->nvs = kmemdup(fw->data, sizeof(struct wl1271_nvs_file), GFP_KERNEL);
if (!wl->nvs) {
@@ -584,12 +630,37 @@ static int wl1271_fetch_nvs(struct wl1271 *wl)
goto out;
}
+ wl->nvs_len = fw->size;
+
out:
release_firmware(fw);
return ret;
}
+static void wl1271_recovery_work(struct work_struct *work)
+{
+ struct wl1271 *wl =
+ container_of(work, struct wl1271, recovery_work);
+
+ mutex_lock(&wl->mutex);
+
+ if (wl->state != WL1271_STATE_ON)
+ goto out;
+
+ wl1271_info("Hardware recovery in progress.");
+
+ if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
+ ieee80211_connection_loss(wl->vif);
+
+ /* reboot the chipset */
+ __wl1271_op_remove_interface(wl);
+ ieee80211_restart_hw(wl->hw);
+
+out:
+ mutex_unlock(&wl->mutex);
+}
+
static void wl1271_fw_wakeup(struct wl1271 *wl)
{
u32 elp_reg;
@@ -610,8 +681,6 @@ static int wl1271_setup(struct wl1271 *wl)
return -ENOMEM;
}
- INIT_WORK(&wl->irq_work, wl1271_irq_work);
- INIT_WORK(&wl->tx_work, wl1271_tx_work);
return 0;
}
@@ -621,7 +690,9 @@ static int wl1271_chip_wakeup(struct wl1271 *wl)
int ret = 0;
msleep(WL1271_PRE_POWER_ON_SLEEP);
- wl1271_power_on(wl);
+ ret = wl1271_power_on(wl);
+ if (ret < 0)
+ goto out;
msleep(WL1271_POWER_ON_SLEEP);
wl1271_io_reset(wl);
wl1271_io_init(wl);
@@ -766,10 +837,12 @@ int wl1271_plt_stop(struct wl1271 *wl)
out:
mutex_unlock(&wl->mutex);
+ cancel_work_sync(&wl->irq_work);
+ cancel_work_sync(&wl->recovery_work);
+
return ret;
}
-
static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
{
struct wl1271 *wl = hw->priv;
@@ -812,6 +885,10 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
return NETDEV_TX_OK;
}
+static struct notifier_block wl1271_dev_notifier = {
+ .notifier_call = wl1271_dev_notify,
+};
+
static int wl1271_op_start(struct ieee80211_hw *hw)
{
wl1271_debug(DEBUG_MAC80211, "mac80211 start");
@@ -928,13 +1005,10 @@ out:
return ret;
}
-static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+static void __wl1271_op_remove_interface(struct wl1271 *wl)
{
- struct wl1271 *wl = hw->priv;
int i;
- mutex_lock(&wl->mutex);
wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface");
wl1271_info("down");
@@ -948,12 +1022,10 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
ieee80211_enable_dyn_ps(wl->vif);
if (wl->scan.state != WL1271_SCAN_STATE_IDLE) {
- mutex_unlock(&wl->mutex);
- ieee80211_scan_completed(wl->hw, true);
- mutex_lock(&wl->mutex);
wl->scan.state = WL1271_SCAN_STATE_IDLE;
kfree(wl->scan.scanned_ch);
wl->scan.scanned_ch = NULL;
+ ieee80211_scan_completed(wl->hw, true);
}
wl->state = WL1271_STATE_OFF;
@@ -962,9 +1034,11 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
mutex_unlock(&wl->mutex);
+ cancel_delayed_work_sync(&wl->scan_complete_work);
cancel_work_sync(&wl->irq_work);
cancel_work_sync(&wl->tx_work);
cancel_delayed_work_sync(&wl->pspoll_work);
+ cancel_delayed_work_sync(&wl->elp_work);
mutex_lock(&wl->mutex);
@@ -1006,8 +1080,19 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
wl->tx_res_if = NULL;
kfree(wl->target_mem_map);
wl->target_mem_map = NULL;
+}
+static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
+{
+ struct wl1271 *wl = hw->priv;
+
+ mutex_lock(&wl->mutex);
+ WARN_ON(wl->vif != vif);
+ __wl1271_op_remove_interface(wl);
mutex_unlock(&wl->mutex);
+
+ cancel_work_sync(&wl->recovery_work);
}
static void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters)
@@ -1289,7 +1374,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) {
wl1271_debug(DEBUG_PSM, "psm enabled");
ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE,
- true);
+ wl->basic_rate, true);
}
} else if (!(conf->flags & IEEE80211_CONF_PS) &&
test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) {
@@ -1299,7 +1384,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
if (test_bit(WL1271_FLAG_PSM, &wl->flags))
ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE,
- true);
+ wl->basic_rate, true);
}
if (conf->power_level != wl->power_level) {
@@ -1439,7 +1524,7 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
wl1271_debug(DEBUG_CRYPT, "CMD: 0x%x", cmd);
wl1271_dump(DEBUG_CRYPT, "ADDR: ", addr, ETH_ALEN);
wl1271_debug(DEBUG_CRYPT, "Key: algo:0x%x, id:%d, len:%d flags 0x%x",
- key_conf->alg, key_conf->keyidx,
+ key_conf->cipher, key_conf->keyidx,
key_conf->keylen, key_conf->flags);
wl1271_dump(DEBUG_CRYPT, "KEY: ", key_conf->key, key_conf->keylen);
@@ -1455,28 +1540,34 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
if (ret < 0)
goto out_unlock;
- switch (key_conf->alg) {
- case ALG_WEP:
+ switch (key_conf->cipher) {
+ case WLAN_CIPHER_SUITE_WEP40:
+ case WLAN_CIPHER_SUITE_WEP104:
key_type = KEY_WEP;
key_conf->hw_key_idx = key_conf->keyidx;
break;
- case ALG_TKIP:
+ case WLAN_CIPHER_SUITE_TKIP:
key_type = KEY_TKIP;
key_conf->hw_key_idx = key_conf->keyidx;
tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq);
tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq);
break;
- case ALG_CCMP:
+ case WLAN_CIPHER_SUITE_CCMP:
key_type = KEY_AES;
key_conf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq);
tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq);
break;
+ case WL1271_CIPHER_SUITE_GEM:
+ key_type = KEY_GEM;
+ tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq);
+ tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq);
+ break;
default:
- wl1271_error("Unknown key algo 0x%x", key_conf->alg);
+ wl1271_error("Unknown key algo 0x%x", key_conf->cipher);
ret = -EOPNOTSUPP;
goto out_sleep;
@@ -1558,10 +1649,7 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw,
if (ret < 0)
goto out;
- if (wl1271_11a_enabled())
- ret = wl1271_scan(hw->priv, ssid, len, req);
- else
- ret = wl1271_scan(hw->priv, ssid, len, req);
+ ret = wl1271_scan(hw->priv, ssid, len, req);
wl1271_ps_elp_sleep(wl);
@@ -1633,7 +1721,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
if (ret < 0)
goto out;
- if ((changed && BSS_CHANGED_BEACON_INT) &&
+ if ((changed & BSS_CHANGED_BEACON_INT) &&
(wl->bss_type == BSS_TYPE_IBSS)) {
wl1271_debug(DEBUG_ADHOC, "ad-hoc beacon interval updated: %d",
bss_conf->beacon_int);
@@ -1642,7 +1730,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
do_join = true;
}
- if ((changed && BSS_CHANGED_BEACON) &&
+ if ((changed & BSS_CHANGED_BEACON) &&
(wl->bss_type == BSS_TYPE_IBSS)) {
struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
@@ -1776,12 +1864,15 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
if (test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags) &&
!test_bit(WL1271_FLAG_PSM, &wl->flags)) {
mode = STATION_POWER_SAVE_MODE;
- ret = wl1271_ps_set_mode(wl, mode, true);
+ ret = wl1271_ps_set_mode(wl, mode,
+ wl->basic_rate,
+ true);
if (ret < 0)
goto out_sleep;
}
} else {
/* use defaults when not associated */
+ clear_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags);
clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags);
wl->aid = 0;
@@ -1993,21 +2084,24 @@ static struct ieee80211_rate wl1271_rates[] = {
.hw_value_short = CONF_HW_BIT_RATE_54MBPS, },
};
-/* can't be const, mac80211 writes to this */
+/*
+ * Can't be const, mac80211 writes to this. The order of the channels here
+ * is designed to improve scanning.
+ */
static struct ieee80211_channel wl1271_channels[] = {
{ .hw_value = 1, .center_freq = 2412, .max_power = 25 },
- { .hw_value = 2, .center_freq = 2417, .max_power = 25 },
- { .hw_value = 3, .center_freq = 2422, .max_power = 25 },
- { .hw_value = 4, .center_freq = 2427, .max_power = 25 },
{ .hw_value = 5, .center_freq = 2432, .max_power = 25 },
- { .hw_value = 6, .center_freq = 2437, .max_power = 25 },
- { .hw_value = 7, .center_freq = 2442, .max_power = 25 },
- { .hw_value = 8, .center_freq = 2447, .max_power = 25 },
{ .hw_value = 9, .center_freq = 2452, .max_power = 25 },
- { .hw_value = 10, .center_freq = 2457, .max_power = 25 },
- { .hw_value = 11, .center_freq = 2462, .max_power = 25 },
- { .hw_value = 12, .center_freq = 2467, .max_power = 25 },
{ .hw_value = 13, .center_freq = 2472, .max_power = 25 },
+ { .hw_value = 4, .center_freq = 2427, .max_power = 25 },
+ { .hw_value = 8, .center_freq = 2447, .max_power = 25 },
+ { .hw_value = 12, .center_freq = 2467, .max_power = 25 },
+ { .hw_value = 3, .center_freq = 2422, .max_power = 25 },
+ { .hw_value = 7, .center_freq = 2442, .max_power = 25 },
+ { .hw_value = 11, .center_freq = 2462, .max_power = 25 },
+ { .hw_value = 2, .center_freq = 2417, .max_power = 25 },
+ { .hw_value = 6, .center_freq = 2437, .max_power = 25 },
+ { .hw_value = 10, .center_freq = 2457, .max_power = 25 },
};
/* mapping to indexes for wl1271_rates */
@@ -2076,49 +2170,52 @@ static struct ieee80211_rate wl1271_rates_5ghz[] = {
.hw_value_short = CONF_HW_BIT_RATE_54MBPS, },
};
-/* 5 GHz band channels for WL1273 */
+/*
+ * 5 GHz band channels for WL1273 - can't be const, mac80211 writes to this.
+ * The order of the channels here is designed to improve scanning.
+ */
static struct ieee80211_channel wl1271_channels_5ghz[] = {
{ .hw_value = 183, .center_freq = 4915},
- { .hw_value = 184, .center_freq = 4920},
- { .hw_value = 185, .center_freq = 4925},
- { .hw_value = 187, .center_freq = 4935},
{ .hw_value = 188, .center_freq = 4940},
- { .hw_value = 189, .center_freq = 4945},
- { .hw_value = 192, .center_freq = 4960},
- { .hw_value = 196, .center_freq = 4980},
- { .hw_value = 7, .center_freq = 5035},
{ .hw_value = 8, .center_freq = 5040},
- { .hw_value = 9, .center_freq = 5045},
- { .hw_value = 11, .center_freq = 5055},
- { .hw_value = 12, .center_freq = 5060},
- { .hw_value = 16, .center_freq = 5080},
{ .hw_value = 34, .center_freq = 5170},
- { .hw_value = 36, .center_freq = 5180},
- { .hw_value = 38, .center_freq = 5190},
- { .hw_value = 40, .center_freq = 5200},
- { .hw_value = 42, .center_freq = 5210},
{ .hw_value = 44, .center_freq = 5220},
- { .hw_value = 46, .center_freq = 5230},
- { .hw_value = 48, .center_freq = 5240},
- { .hw_value = 52, .center_freq = 5260},
- { .hw_value = 56, .center_freq = 5280},
{ .hw_value = 60, .center_freq = 5300},
- { .hw_value = 64, .center_freq = 5320},
- { .hw_value = 100, .center_freq = 5500},
- { .hw_value = 104, .center_freq = 5520},
- { .hw_value = 108, .center_freq = 5540},
{ .hw_value = 112, .center_freq = 5560},
- { .hw_value = 116, .center_freq = 5580},
- { .hw_value = 120, .center_freq = 5600},
- { .hw_value = 124, .center_freq = 5620},
- { .hw_value = 128, .center_freq = 5640},
{ .hw_value = 132, .center_freq = 5660},
+ { .hw_value = 157, .center_freq = 5785},
+ { .hw_value = 184, .center_freq = 4920},
+ { .hw_value = 189, .center_freq = 4945},
+ { .hw_value = 9, .center_freq = 5045},
+ { .hw_value = 36, .center_freq = 5180},
+ { .hw_value = 46, .center_freq = 5230},
+ { .hw_value = 64, .center_freq = 5320},
+ { .hw_value = 116, .center_freq = 5580},
{ .hw_value = 136, .center_freq = 5680},
+ { .hw_value = 192, .center_freq = 4960},
+ { .hw_value = 11, .center_freq = 5055},
+ { .hw_value = 38, .center_freq = 5190},
+ { .hw_value = 48, .center_freq = 5240},
+ { .hw_value = 100, .center_freq = 5500},
+ { .hw_value = 120, .center_freq = 5600},
{ .hw_value = 140, .center_freq = 5700},
+ { .hw_value = 185, .center_freq = 4925},
+ { .hw_value = 196, .center_freq = 4980},
+ { .hw_value = 12, .center_freq = 5060},
+ { .hw_value = 40, .center_freq = 5200},
+ { .hw_value = 52, .center_freq = 5260},
+ { .hw_value = 104, .center_freq = 5520},
+ { .hw_value = 124, .center_freq = 5620},
{ .hw_value = 149, .center_freq = 5745},
- { .hw_value = 153, .center_freq = 5765},
- { .hw_value = 157, .center_freq = 5785},
{ .hw_value = 161, .center_freq = 5805},
+ { .hw_value = 187, .center_freq = 4935},
+ { .hw_value = 7, .center_freq = 5035},
+ { .hw_value = 16, .center_freq = 5080},
+ { .hw_value = 42, .center_freq = 5210},
+ { .hw_value = 56, .center_freq = 5280},
+ { .hw_value = 108, .center_freq = 5540},
+ { .hw_value = 128, .center_freq = 5640},
+ { .hw_value = 153, .center_freq = 5765},
{ .hw_value = 165, .center_freq = 5825},
};
@@ -2211,8 +2308,7 @@ static ssize_t wl1271_sysfs_show_bt_coex_state(struct device *dev,
struct wl1271 *wl = dev_get_drvdata(dev);
ssize_t len;
- /* FIXME: what's the maximum length of buf? page size?*/
- len = 500;
+ len = PAGE_SIZE;
mutex_lock(&wl->mutex);
len = snprintf(buf, len, "%d\n\n0 - off\n1 - on\n",
@@ -2273,8 +2369,7 @@ static ssize_t wl1271_sysfs_show_hw_pg_ver(struct device *dev,
struct wl1271 *wl = dev_get_drvdata(dev);
ssize_t len;
- /* FIXME: what's the maximum length of buf? page size?*/
- len = 500;
+ len = PAGE_SIZE;
mutex_lock(&wl->mutex);
if (wl->hw_pg_ver >= 0)
@@ -2306,6 +2401,8 @@ int wl1271_register_hw(struct wl1271 *wl)
wl->mac80211_registered = true;
+ register_netdevice_notifier(&wl1271_dev_notifier);
+
wl1271_notice("loaded");
return 0;
@@ -2314,6 +2411,7 @@ EXPORT_SYMBOL_GPL(wl1271_register_hw);
void wl1271_unregister_hw(struct wl1271 *wl)
{
+ unregister_netdevice_notifier(&wl1271_dev_notifier);
ieee80211_unregister_hw(wl->hw);
wl->mac80211_registered = false;
@@ -2322,6 +2420,14 @@ EXPORT_SYMBOL_GPL(wl1271_unregister_hw);
int wl1271_init_ieee80211(struct wl1271 *wl)
{
+ static const u32 cipher_suites[] = {
+ WLAN_CIPHER_SUITE_WEP40,
+ WLAN_CIPHER_SUITE_WEP104,
+ WLAN_CIPHER_SUITE_TKIP,
+ WLAN_CIPHER_SUITE_CCMP,
+ WL1271_CIPHER_SUITE_GEM,
+ };
+
/* The tx descriptor buffer and the TKIP space. */
wl->hw->extra_tx_headroom = WL1271_TKIP_IV_SPACE +
sizeof(struct wl1271_tx_hw_descr);
@@ -2339,13 +2445,14 @@ int wl1271_init_ieee80211(struct wl1271 *wl)
IEEE80211_HW_CONNECTION_MONITOR |
IEEE80211_HW_SUPPORTS_CQM_RSSI;
+ wl->hw->wiphy->cipher_suites = cipher_suites;
+ wl->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
+
wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_ADHOC);
wl->hw->wiphy->max_scan_ssids = 1;
wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1271_band_2ghz;
-
- if (wl1271_11a_enabled())
- wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wl1271_band_5ghz;
+ wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wl1271_band_5ghz;
wl->hw->queues = 4;
wl->hw->max_rates = 1;
@@ -2364,6 +2471,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
struct platform_device *plat_dev = NULL;
struct wl1271 *wl;
int i, ret;
+ unsigned int order;
hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops);
if (!hw) {
@@ -2391,6 +2499,10 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work);
INIT_DELAYED_WORK(&wl->pspoll_work, wl1271_pspoll_work);
+ INIT_WORK(&wl->irq_work, wl1271_irq_work);
+ INIT_WORK(&wl->tx_work, wl1271_tx_work);
+ INIT_WORK(&wl->recovery_work, wl1271_recovery_work);
+ INIT_DELAYED_WORK(&wl->scan_complete_work, wl1271_scan_complete_work);
wl->channel = WL1271_DEFAULT_CHANNEL;
wl->beacon_int = WL1271_DEFAULT_BEACON_INT;
wl->default_key = 0;
@@ -2422,11 +2534,18 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
wl1271_debugfs_init(wl);
+ order = get_order(WL1271_AGGR_BUFFER_SIZE);
+ wl->aggr_buf = (u8 *)__get_free_pages(GFP_KERNEL, order);
+ if (!wl->aggr_buf) {
+ ret = -ENOMEM;
+ goto err_hw;
+ }
+
/* Register platform device */
ret = platform_device_register(wl->plat_dev);
if (ret) {
wl1271_error("couldn't register platform device");
- goto err_hw;
+ goto err_aggr;
}
dev_set_drvdata(&wl->plat_dev->dev, wl);
@@ -2452,6 +2571,9 @@ err_bt_coex_state:
err_platform:
platform_device_unregister(wl->plat_dev);
+err_aggr:
+ free_pages((unsigned long)wl->aggr_buf, order);
+
err_hw:
wl1271_debugfs_exit(wl);
kfree(plat_dev);
@@ -2468,6 +2590,8 @@ EXPORT_SYMBOL_GPL(wl1271_alloc_hw);
int wl1271_free_hw(struct wl1271 *wl)
{
platform_device_unregister(wl->plat_dev);
+ free_pages((unsigned long)wl->aggr_buf,
+ get_order(WL1271_AGGR_BUFFER_SIZE));
kfree(wl->plat_dev);
wl1271_debugfs_exit(wl);
diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.c b/drivers/net/wireless/wl12xx/wl1271_ps.c
index a5e60e0403e5..e3c332e2f97c 100644
--- a/drivers/net/wireless/wl12xx/wl1271_ps.c
+++ b/drivers/net/wireless/wl12xx/wl1271_ps.c
@@ -39,6 +39,9 @@ void wl1271_elp_work(struct work_struct *work)
mutex_lock(&wl->mutex);
+ if (unlikely(wl->state == WL1271_STATE_OFF))
+ goto out;
+
if (test_bit(WL1271_FLAG_IN_ELP, &wl->flags) ||
(!test_bit(WL1271_FLAG_PSM, &wl->flags) &&
!test_bit(WL1271_FLAG_IDLE, &wl->flags)))
@@ -61,7 +64,7 @@ void wl1271_ps_elp_sleep(struct wl1271 *wl)
test_bit(WL1271_FLAG_IDLE, &wl->flags)) {
cancel_delayed_work(&wl->elp_work);
ieee80211_queue_delayed_work(wl->hw, &wl->elp_work,
- msecs_to_jiffies(ELP_ENTRY_DELAY));
+ msecs_to_jiffies(ELP_ENTRY_DELAY));
}
}
@@ -96,6 +99,7 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake)
&compl, msecs_to_jiffies(WL1271_WAKEUP_TIMEOUT));
if (ret == 0) {
wl1271_error("ELP wakeup timeout!");
+ ieee80211_queue_work(wl->hw, &wl->recovery_work);
ret = -ETIMEDOUT;
goto err;
} else if (ret < 0) {
@@ -121,7 +125,7 @@ out:
}
int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
- bool send)
+ u32 rates, bool send)
{
int ret;
@@ -129,7 +133,14 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
case STATION_POWER_SAVE_MODE:
wl1271_debug(DEBUG_PSM, "entering psm");
- ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE, send);
+ ret = wl1271_acx_wake_up_conditions(wl);
+ if (ret < 0) {
+ wl1271_error("couldn't set wake up conditions");
+ return ret;
+ }
+
+ ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE,
+ rates, send);
if (ret < 0)
return ret;
@@ -152,7 +163,8 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
if (ret < 0)
return ret;
- ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE, send);
+ ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE,
+ rates, send);
if (ret < 0)
return ret;
diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.h b/drivers/net/wireless/wl12xx/wl1271_ps.h
index 940276f517a4..6ba7b032736f 100644
--- a/drivers/net/wireless/wl12xx/wl1271_ps.h
+++ b/drivers/net/wireless/wl12xx/wl1271_ps.h
@@ -28,7 +28,7 @@
#include "wl1271_acx.h"
int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
- bool send);
+ u32 rates, bool send);
void wl1271_ps_elp_sleep(struct wl1271 *wl);
int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake);
void wl1271_elp_work(struct work_struct *work);
diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.c b/drivers/net/wireless/wl12xx/wl1271_rx.c
index 019aa79cd9df..bea133b6e489 100644
--- a/drivers/net/wireless/wl12xx/wl1271_rx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_rx.c
@@ -74,9 +74,8 @@ static void wl1271_rx_status(struct wl1271 *wl,
}
}
-static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length)
+static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
{
- struct ieee80211_rx_status rx_status;
struct wl1271_rx_descriptor *desc;
struct sk_buff *skb;
u16 *fc;
@@ -88,16 +87,16 @@ static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length)
* workaround this by not retrieving them at all.
*/
if (unlikely(wl->state == WL1271_STATE_PLT))
- return;
+ return -EINVAL;
skb = __dev_alloc_skb(length, GFP_KERNEL);
if (!skb) {
wl1271_error("Couldn't allocate RX frame");
- return;
+ return -ENOMEM;
}
buf = skb_put(skb, length);
- wl1271_read(wl, WL1271_SLV_MEM_DATA, buf, length, true);
+ memcpy(buf, data, length);
/* the data read starts with the descriptor */
desc = (struct wl1271_rx_descriptor *) buf;
@@ -109,15 +108,16 @@ static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length)
if ((*fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON)
beacon = 1;
- wl1271_rx_status(wl, desc, &rx_status, beacon);
+ wl1271_rx_status(wl, desc, IEEE80211_SKB_RXCB(skb), beacon);
wl1271_debug(DEBUG_RX, "rx skb 0x%p: %d B %s", skb, skb->len,
beacon ? "beacon" : "");
skb_trim(skb, skb->len - desc->pad_len);
- memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
ieee80211_rx_ni(wl->hw, skb);
+
+ return 0;
}
void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status)
@@ -126,31 +126,60 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status)
u32 buf_size;
u32 fw_rx_counter = status->fw_rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
u32 drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
+ u32 rx_counter;
u32 mem_block;
+ u32 pkt_length;
+ u32 pkt_offset;
while (drv_rx_counter != fw_rx_counter) {
- mem_block = wl1271_rx_get_mem_block(status, drv_rx_counter);
- buf_size = wl1271_rx_get_buf_size(status, drv_rx_counter);
+ buf_size = 0;
+ rx_counter = drv_rx_counter;
+ while (rx_counter != fw_rx_counter) {
+ pkt_length = wl1271_rx_get_buf_size(status, rx_counter);
+ if (buf_size + pkt_length > WL1271_AGGR_BUFFER_SIZE)
+ break;
+ buf_size += pkt_length;
+ rx_counter++;
+ rx_counter &= NUM_RX_PKT_DESC_MOD_MASK;
+ }
if (buf_size == 0) {
wl1271_warning("received empty data");
break;
}
+ /*
+ * Choose the block we want to read
+ * For aggregated packets, only the first memory block should
+ * be retrieved. The FW takes care of the rest.
+ */
+ mem_block = wl1271_rx_get_mem_block(status, drv_rx_counter);
wl->rx_mem_pool_addr.addr = (mem_block << 8) +
le32_to_cpu(wl_mem_map->packet_memory_pool_start);
wl->rx_mem_pool_addr.addr_extra =
wl->rx_mem_pool_addr.addr + 4;
-
- /* Choose the block we want to read */
wl1271_write(wl, WL1271_SLV_REG_DATA, &wl->rx_mem_pool_addr,
- sizeof(wl->rx_mem_pool_addr), false);
-
- wl1271_rx_handle_data(wl, buf_size);
-
- wl->rx_counter++;
- drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
+ sizeof(wl->rx_mem_pool_addr), false);
+
+ /* Read all available packets at once */
+ wl1271_read(wl, WL1271_SLV_MEM_DATA, wl->aggr_buf,
+ buf_size, true);
+
+ /* Split data into separate packets */
+ pkt_offset = 0;
+ while (pkt_offset < buf_size) {
+ pkt_length = wl1271_rx_get_buf_size(status,
+ drv_rx_counter);
+ if (wl1271_rx_handle_data(wl,
+ wl->aggr_buf + pkt_offset,
+ pkt_length) < 0)
+ break;
+ wl->rx_counter++;
+ drv_rx_counter++;
+ drv_rx_counter &= NUM_RX_PKT_DESC_MOD_MASK;
+ pkt_offset += pkt_length;
+ }
}
-
- wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter);
+ wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS,
+ cpu_to_le32(wl->rx_counter));
}
diff --git a/drivers/net/wireless/wl12xx/wl1271_scan.c b/drivers/net/wireless/wl12xx/wl1271_scan.c
index fec43eed8c55..909bb47995b6 100644
--- a/drivers/net/wireless/wl12xx/wl1271_scan.c
+++ b/drivers/net/wireless/wl12xx/wl1271_scan.c
@@ -28,11 +28,43 @@
#include "wl1271_scan.h"
#include "wl1271_acx.h"
+void wl1271_scan_complete_work(struct work_struct *work)
+{
+ struct delayed_work *dwork;
+ struct wl1271 *wl;
+
+ dwork = container_of(work, struct delayed_work, work);
+ wl = container_of(dwork, struct wl1271, scan_complete_work);
+
+ wl1271_debug(DEBUG_SCAN, "Scanning complete");
+
+ mutex_lock(&wl->mutex);
+
+ if (wl->scan.state == WL1271_SCAN_STATE_IDLE) {
+ mutex_unlock(&wl->mutex);
+ return;
+ }
+
+ wl->scan.state = WL1271_SCAN_STATE_IDLE;
+ kfree(wl->scan.scanned_ch);
+ wl->scan.scanned_ch = NULL;
+ mutex_unlock(&wl->mutex);
+
+ ieee80211_scan_completed(wl->hw, false);
+
+ if (wl->scan.failed) {
+ wl1271_info("Scan completed due to error.");
+ ieee80211_queue_work(wl->hw, &wl->recovery_work);
+ }
+}
+
+
static int wl1271_get_scan_channels(struct wl1271 *wl,
struct cfg80211_scan_request *req,
struct basic_scan_channel_params *channels,
enum ieee80211_band band, bool passive)
{
+ struct conf_scan_settings *c = &wl->conf.scan;
int i, j;
u32 flags;
@@ -60,10 +92,17 @@ static int wl1271_get_scan_channels(struct wl1271 *wl,
wl1271_debug(DEBUG_SCAN, "beacon_found %d",
req->channels[i]->beacon_found);
- channels[j].min_duration =
- cpu_to_le32(WL1271_SCAN_CHAN_MIN_DURATION);
- channels[j].max_duration =
- cpu_to_le32(WL1271_SCAN_CHAN_MAX_DURATION);
+ if (!passive) {
+ channels[j].min_duration =
+ cpu_to_le32(c->min_dwell_time_active);
+ channels[j].max_duration =
+ cpu_to_le32(c->max_dwell_time_active);
+ } else {
+ channels[j].min_duration =
+ cpu_to_le32(c->min_dwell_time_passive);
+ channels[j].max_duration =
+ cpu_to_le32(c->max_dwell_time_passive);
+ }
channels[j].early_termination = 0;
channels[j].tx_power_att = req->channels[i]->max_power;
channels[j].channel = req->channels[i]->hw_value;
@@ -100,8 +139,11 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band,
/* We always use high priority scans */
scan_options = WL1271_SCAN_OPT_PRIORITY_HIGH;
- if(passive)
+
+ /* No SSIDs means that we have a forced passive scan */
+ if (passive || wl->scan.req->n_ssids == 0)
scan_options |= WL1271_SCAN_OPT_PASSIVE;
+
cmd->params.scan_options = cpu_to_le16(scan_options);
cmd->params.n_ch = wl1271_get_scan_channels(wl, wl->scan.req,
@@ -117,7 +159,7 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band,
cmd->params.rx_filter_options =
cpu_to_le32(CFG_RX_PRSP_EN | CFG_RX_MGMT_EN | CFG_RX_BCN_EN);
- cmd->params.n_probe_reqs = WL1271_SCAN_PROBE_REQS;
+ cmd->params.n_probe_reqs = wl->conf.scan.num_probe_reqs;
cmd->params.tx_rate = cpu_to_le32(basic_rate);
cmd->params.tid_trigger = 0;
cmd->params.scan_tag = WL1271_SCAN_DEFAULT_TAG;
@@ -165,7 +207,7 @@ out:
void wl1271_scan_stm(struct wl1271 *wl)
{
- int ret;
+ int ret = 0;
switch (wl->scan.state) {
case WL1271_SCAN_STATE_IDLE:
@@ -185,7 +227,7 @@ void wl1271_scan_stm(struct wl1271 *wl)
ret = wl1271_scan_send(wl, IEEE80211_BAND_2GHZ, true,
wl->conf.tx.basic_rate);
if (ret == WL1271_NOTHING_TO_SCAN) {
- if (wl1271_11a_enabled())
+ if (wl->enable_11a)
wl->scan.state = WL1271_SCAN_STATE_5GHZ_ACTIVE;
else
wl->scan.state = WL1271_SCAN_STATE_DONE;
@@ -215,20 +257,22 @@ void wl1271_scan_stm(struct wl1271 *wl)
break;
case WL1271_SCAN_STATE_DONE:
- mutex_unlock(&wl->mutex);
- ieee80211_scan_completed(wl->hw, false);
- mutex_lock(&wl->mutex);
-
- kfree(wl->scan.scanned_ch);
- wl->scan.scanned_ch = NULL;
-
- wl->scan.state = WL1271_SCAN_STATE_IDLE;
+ wl->scan.failed = false;
+ cancel_delayed_work(&wl->scan_complete_work);
+ ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work,
+ msecs_to_jiffies(0));
break;
default:
wl1271_error("invalid scan state");
break;
}
+
+ if (ret < 0) {
+ cancel_delayed_work(&wl->scan_complete_work);
+ ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work,
+ msecs_to_jiffies(0));
+ }
}
int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len,
@@ -248,9 +292,14 @@ int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len,
wl->scan.req = req;
- wl->scan.scanned_ch = kzalloc(req->n_channels *
+ wl->scan.scanned_ch = kcalloc(req->n_channels,
sizeof(*wl->scan.scanned_ch),
GFP_KERNEL);
+ /* we assume failure so that timeout scenarios are handled correctly */
+ wl->scan.failed = true;
+ ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work,
+ msecs_to_jiffies(WL1271_SCAN_TIMEOUT));
+
wl1271_scan_stm(wl);
return 0;
diff --git a/drivers/net/wireless/wl12xx/wl1271_scan.h b/drivers/net/wireless/wl12xx/wl1271_scan.h
index f1815700f5f9..6d57127b5e6b 100644
--- a/drivers/net/wireless/wl12xx/wl1271_scan.h
+++ b/drivers/net/wireless/wl12xx/wl1271_scan.h
@@ -32,6 +32,7 @@ int wl1271_scan_build_probe_req(struct wl1271 *wl,
const u8 *ssid, size_t ssid_len,
const u8 *ie, size_t ie_len, u8 band);
void wl1271_scan_stm(struct wl1271 *wl);
+void wl1271_scan_complete_work(struct work_struct *work);
#define WL1271_SCAN_MAX_CHANNELS 24
#define WL1271_SCAN_DEFAULT_TAG 1
@@ -39,11 +40,10 @@ void wl1271_scan_stm(struct wl1271 *wl);
#define WL1271_SCAN_OPT_ACTIVE 0
#define WL1271_SCAN_OPT_PASSIVE 1
#define WL1271_SCAN_OPT_PRIORITY_HIGH 4
-#define WL1271_SCAN_CHAN_MIN_DURATION 30000 /* TU */
-#define WL1271_SCAN_CHAN_MAX_DURATION 60000 /* TU */
#define WL1271_SCAN_BAND_2_4_GHZ 0
#define WL1271_SCAN_BAND_5_GHZ 1
-#define WL1271_SCAN_PROBE_REQS 3
+
+#define WL1271_SCAN_TIMEOUT 10000 /* msec */
enum {
WL1271_SCAN_STATE_IDLE,
diff --git a/drivers/net/wireless/wl12xx/wl1271_sdio.c b/drivers/net/wireless/wl12xx/wl1271_sdio.c
index 7059b5cccf0f..784ef3432641 100644
--- a/drivers/net/wireless/wl12xx/wl1271_sdio.c
+++ b/drivers/net/wireless/wl12xx/wl1271_sdio.c
@@ -29,14 +29,13 @@
#include <linux/mmc/sdio_ids.h>
#include <linux/mmc/card.h>
#include <linux/gpio.h>
+#include <linux/wl12xx.h>
+#include <linux/pm_runtime.h>
#include "wl1271.h"
#include "wl12xx_80211.h"
#include "wl1271_io.h"
-
-#define RX71_WL1271_IRQ_GPIO 42
-
#ifndef SDIO_VENDOR_ID_TI
#define SDIO_VENDOR_ID_TI 0x0097
#endif
@@ -107,6 +106,8 @@ static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf,
int ret;
struct sdio_func *func = wl_to_func(wl);
+ sdio_claim_host(func);
+
if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) {
((u8 *)buf)[0] = sdio_f0_readb(func, addr, &ret);
wl1271_debug(DEBUG_SDIO, "sdio read 52 addr 0x%x, byte 0x%02x",
@@ -122,9 +123,10 @@ static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf,
wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len);
}
+ sdio_release_host(func);
+
if (ret)
wl1271_error("sdio read failed (%d)", ret);
-
}
static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf,
@@ -133,6 +135,8 @@ static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf,
int ret;
struct sdio_func *func = wl_to_func(wl);
+ sdio_claim_host(func);
+
if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) {
sdio_f0_writeb(func, ((u8 *)buf)[0], addr, &ret);
wl1271_debug(DEBUG_SDIO, "sdio write 52 addr 0x%x, byte 0x%02x",
@@ -147,26 +151,49 @@ static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf,
else
ret = sdio_memcpy_toio(func, addr, buf, len);
}
+
+ sdio_release_host(func);
+
if (ret)
wl1271_error("sdio write failed (%d)", ret);
+}
+static int wl1271_sdio_power_on(struct wl1271 *wl)
+{
+ struct sdio_func *func = wl_to_func(wl);
+ int ret;
+
+ /* Power up the card */
+ ret = pm_runtime_get_sync(&func->dev);
+ if (ret < 0)
+ goto out;
+
+ sdio_claim_host(func);
+ sdio_enable_func(func);
+ sdio_release_host(func);
+
+out:
+ return ret;
}
-static void wl1271_sdio_set_power(struct wl1271 *wl, bool enable)
+static int wl1271_sdio_power_off(struct wl1271 *wl)
{
struct sdio_func *func = wl_to_func(wl);
- /* Let the SDIO stack handle wlan_enable control, so we
- * keep host claimed while wlan is in use to keep wl1271
- * alive.
- */
- if (enable) {
- sdio_claim_host(func);
- sdio_enable_func(func);
- } else {
- sdio_disable_func(func);
- sdio_release_host(func);
- }
+ sdio_claim_host(func);
+ sdio_disable_func(func);
+ sdio_release_host(func);
+
+ /* Power down the card */
+ return pm_runtime_put_sync(&func->dev);
+}
+
+static int wl1271_sdio_set_power(struct wl1271 *wl, bool enable)
+{
+ if (enable)
+ return wl1271_sdio_power_on(wl);
+ else
+ return wl1271_sdio_power_off(wl);
}
static struct wl1271_if_operations sdio_ops = {
@@ -184,6 +211,7 @@ static int __devinit wl1271_probe(struct sdio_func *func,
const struct sdio_device_id *id)
{
struct ieee80211_hw *hw;
+ const struct wl12xx_platform_data *wlan_data;
struct wl1271 *wl;
int ret;
@@ -203,13 +231,16 @@ static int __devinit wl1271_probe(struct sdio_func *func,
/* Grab access to FN0 for ELP reg. */
func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
- wl->irq = gpio_to_irq(RX71_WL1271_IRQ_GPIO);
- if (wl->irq < 0) {
- ret = wl->irq;
- wl1271_error("could not get irq!");
+ wlan_data = wl12xx_get_platform_data();
+ if (IS_ERR(wlan_data)) {
+ ret = PTR_ERR(wlan_data);
+ wl1271_error("missing wlan platform data: %d", ret);
goto out_free;
}
+ wl->irq = wlan_data->irq;
+ wl->ref_clock = wlan_data->board_ref_clock;
+
ret = request_irq(wl->irq, wl1271_irq, 0, DRIVER_NAME, wl);
if (ret < 0) {
wl1271_error("request_irq() failed: %d", ret);
@@ -230,6 +261,9 @@ static int __devinit wl1271_probe(struct sdio_func *func,
sdio_set_drvdata(func, wl);
+ /* Tell PM core that we don't need the card to be powered now */
+ pm_runtime_put_noidle(&func->dev);
+
wl1271_notice("initialized");
return 0;
@@ -248,17 +282,39 @@ static void __devexit wl1271_remove(struct sdio_func *func)
{
struct wl1271 *wl = sdio_get_drvdata(func);
- free_irq(wl->irq, wl);
+ /* Undo decrement done above in wl1271_probe */
+ pm_runtime_get_noresume(&func->dev);
wl1271_unregister_hw(wl);
+ free_irq(wl->irq, wl);
wl1271_free_hw(wl);
}
+static int wl1271_suspend(struct device *dev)
+{
+ /* Tell MMC/SDIO core it's OK to power down the card
+ * (if it isn't already), but not to remove it completely */
+ return 0;
+}
+
+static int wl1271_resume(struct device *dev)
+{
+ return 0;
+}
+
+static const struct dev_pm_ops wl1271_sdio_pm_ops = {
+ .suspend = wl1271_suspend,
+ .resume = wl1271_resume,
+};
+
static struct sdio_driver wl1271_sdio_driver = {
.name = "wl1271_sdio",
.id_table = wl1271_devices,
.probe = wl1271_probe,
.remove = __devexit_p(wl1271_remove),
+ .drv = {
+ .pm = &wl1271_sdio_pm_ops,
+ },
};
static int __init wl1271_init(void)
diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c
index 4cb99c541e2a..ef801680773f 100644
--- a/drivers/net/wireless/wl12xx/wl1271_spi.c
+++ b/drivers/net/wireless/wl12xx/wl1271_spi.c
@@ -25,7 +25,7 @@
#include <linux/module.h>
#include <linux/crc7.h>
#include <linux/spi/spi.h>
-#include <linux/spi/wl12xx.h>
+#include <linux/wl12xx.h>
#include <linux/slab.h>
#include "wl1271.h"
@@ -63,6 +63,11 @@
((WL1271_BUSY_WORD_LEN - 4) / sizeof(u32))
#define HW_ACCESS_WSPI_INIT_CMD_MASK 0
+/* HW limitation: maximum possible chunk size is 4095 bytes */
+#define WSPI_MAX_CHUNK_SIZE 4092
+
+#define WSPI_MAX_NUM_OF_CHUNKS (WL1271_AGGR_BUFFER_SIZE / WSPI_MAX_CHUNK_SIZE)
+
static inline struct spi_device *wl_to_spi(struct wl1271 *wl)
{
return wl->if_priv;
@@ -202,90 +207,117 @@ static int wl1271_spi_read_busy(struct wl1271 *wl)
static void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf,
size_t len, bool fixed)
{
- struct spi_transfer t[3];
+ struct spi_transfer t[2];
struct spi_message m;
u32 *busy_buf;
u32 *cmd;
+ u32 chunk_len;
- cmd = &wl->buffer_cmd;
- busy_buf = wl->buffer_busyword;
+ while (len > 0) {
+ chunk_len = min((size_t)WSPI_MAX_CHUNK_SIZE, len);
- *cmd = 0;
- *cmd |= WSPI_CMD_READ;
- *cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH;
- *cmd |= addr & WSPI_CMD_BYTE_ADDR;
+ cmd = &wl->buffer_cmd;
+ busy_buf = wl->buffer_busyword;
- if (fixed)
- *cmd |= WSPI_CMD_FIXED;
+ *cmd = 0;
+ *cmd |= WSPI_CMD_READ;
+ *cmd |= (chunk_len << WSPI_CMD_BYTE_LENGTH_OFFSET) &
+ WSPI_CMD_BYTE_LENGTH;
+ *cmd |= addr & WSPI_CMD_BYTE_ADDR;
- spi_message_init(&m);
- memset(t, 0, sizeof(t));
+ if (fixed)
+ *cmd |= WSPI_CMD_FIXED;
- t[0].tx_buf = cmd;
- t[0].len = 4;
- t[0].cs_change = true;
- spi_message_add_tail(&t[0], &m);
+ spi_message_init(&m);
+ memset(t, 0, sizeof(t));
- /* Busy and non busy words read */
- t[1].rx_buf = busy_buf;
- t[1].len = WL1271_BUSY_WORD_LEN;
- t[1].cs_change = true;
- spi_message_add_tail(&t[1], &m);
+ t[0].tx_buf = cmd;
+ t[0].len = 4;
+ t[0].cs_change = true;
+ spi_message_add_tail(&t[0], &m);
- spi_sync(wl_to_spi(wl), &m);
+ /* Busy and non busy words read */
+ t[1].rx_buf = busy_buf;
+ t[1].len = WL1271_BUSY_WORD_LEN;
+ t[1].cs_change = true;
+ spi_message_add_tail(&t[1], &m);
- if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1) &&
- wl1271_spi_read_busy(wl)) {
- memset(buf, 0, len);
- return;
- }
+ spi_sync(wl_to_spi(wl), &m);
- spi_message_init(&m);
- memset(t, 0, sizeof(t));
+ if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1) &&
+ wl1271_spi_read_busy(wl)) {
+ memset(buf, 0, chunk_len);
+ return;
+ }
- t[0].rx_buf = buf;
- t[0].len = len;
- t[0].cs_change = true;
- spi_message_add_tail(&t[0], &m);
+ spi_message_init(&m);
+ memset(t, 0, sizeof(t));
- spi_sync(wl_to_spi(wl), &m);
+ t[0].rx_buf = buf;
+ t[0].len = chunk_len;
+ t[0].cs_change = true;
+ spi_message_add_tail(&t[0], &m);
- wl1271_dump(DEBUG_SPI, "spi_read cmd -> ", cmd, sizeof(*cmd));
- wl1271_dump(DEBUG_SPI, "spi_read buf <- ", buf, len);
+ spi_sync(wl_to_spi(wl), &m);
+
+ wl1271_dump(DEBUG_SPI, "spi_read cmd -> ", cmd, sizeof(*cmd));
+ wl1271_dump(DEBUG_SPI, "spi_read buf <- ", buf, chunk_len);
+
+ if (!fixed)
+ addr += chunk_len;
+ buf += chunk_len;
+ len -= chunk_len;
+ }
}
static void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf,
size_t len, bool fixed)
{
- struct spi_transfer t[2];
+ struct spi_transfer t[2 * WSPI_MAX_NUM_OF_CHUNKS];
struct spi_message m;
+ u32 commands[WSPI_MAX_NUM_OF_CHUNKS];
u32 *cmd;
+ u32 chunk_len;
+ int i;
- cmd = &wl->buffer_cmd;
-
- *cmd = 0;
- *cmd |= WSPI_CMD_WRITE;
- *cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH;
- *cmd |= addr & WSPI_CMD_BYTE_ADDR;
-
- if (fixed)
- *cmd |= WSPI_CMD_FIXED;
+ WARN_ON(len > WL1271_AGGR_BUFFER_SIZE);
spi_message_init(&m);
memset(t, 0, sizeof(t));
- t[0].tx_buf = cmd;
- t[0].len = sizeof(*cmd);
- spi_message_add_tail(&t[0], &m);
+ cmd = &commands[0];
+ i = 0;
+ while (len > 0) {
+ chunk_len = min((size_t)WSPI_MAX_CHUNK_SIZE, len);
- t[1].tx_buf = buf;
- t[1].len = len;
- spi_message_add_tail(&t[1], &m);
+ *cmd = 0;
+ *cmd |= WSPI_CMD_WRITE;
+ *cmd |= (chunk_len << WSPI_CMD_BYTE_LENGTH_OFFSET) &
+ WSPI_CMD_BYTE_LENGTH;
+ *cmd |= addr & WSPI_CMD_BYTE_ADDR;
- spi_sync(wl_to_spi(wl), &m);
+ if (fixed)
+ *cmd |= WSPI_CMD_FIXED;
+
+ t[i].tx_buf = cmd;
+ t[i].len = sizeof(*cmd);
+ spi_message_add_tail(&t[i++], &m);
+
+ t[i].tx_buf = buf;
+ t[i].len = chunk_len;
+ spi_message_add_tail(&t[i++], &m);
- wl1271_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd));
- wl1271_dump(DEBUG_SPI, "spi_write buf -> ", buf, len);
+ wl1271_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd));
+ wl1271_dump(DEBUG_SPI, "spi_write buf -> ", buf, chunk_len);
+
+ if (!fixed)
+ addr += chunk_len;
+ buf += chunk_len;
+ len -= chunk_len;
+ cmd++;
+ }
+
+ spi_sync(wl_to_spi(wl), &m);
}
static irqreturn_t wl1271_irq(int irq, void *cookie)
@@ -312,10 +344,12 @@ static irqreturn_t wl1271_irq(int irq, void *cookie)
return IRQ_HANDLED;
}
-static void wl1271_spi_set_power(struct wl1271 *wl, bool enable)
+static int wl1271_spi_set_power(struct wl1271 *wl, bool enable)
{
if (wl->set_power)
wl->set_power(enable);
+
+ return 0;
}
static struct wl1271_if_operations spi_ops = {
@@ -370,6 +404,8 @@ static int __devinit wl1271_probe(struct spi_device *spi)
goto out_free;
}
+ wl->ref_clock = pdata->board_ref_clock;
+
wl->irq = spi->irq;
if (wl->irq < 0) {
wl1271_error("irq missing in platform data");
@@ -412,9 +448,8 @@ static int __devexit wl1271_remove(struct spi_device *spi)
{
struct wl1271 *wl = dev_get_drvdata(&spi->dev);
- free_irq(wl->irq, wl);
-
wl1271_unregister_hw(wl);
+ free_irq(wl->irq, wl);
wl1271_free_hw(wl);
return 0;
diff --git a/drivers/net/wireless/wl12xx/wl1271_testmode.c b/drivers/net/wireless/wl12xx/wl1271_testmode.c
index 6e0952f79e9a..a3aa84386c88 100644
--- a/drivers/net/wireless/wl12xx/wl1271_testmode.c
+++ b/drivers/net/wireless/wl12xx/wl1271_testmode.c
@@ -199,19 +199,6 @@ static int wl1271_tm_cmd_nvs_push(struct wl1271 *wl, struct nlattr *tb[])
buf = nla_data(tb[WL1271_TM_ATTR_DATA]);
len = nla_len(tb[WL1271_TM_ATTR_DATA]);
- /*
- * FIXME: the LEGACY NVS image support (NVS's missing the 5GHz band
- * configurations) can be removed when those NVS files stop floating
- * around.
- */
- if (len != sizeof(struct wl1271_nvs_file) &&
- (len != WL1271_INI_LEGACY_NVS_FILE_SIZE ||
- wl1271_11a_enabled())) {
- wl1271_error("nvs size is not as expected: %zu != %zu",
- len, sizeof(struct wl1271_nvs_file));
- return -EMSGSIZE;
- }
-
mutex_lock(&wl->mutex);
kfree(wl->nvs);
@@ -224,6 +211,7 @@ static int wl1271_tm_cmd_nvs_push(struct wl1271 *wl, struct nlattr *tb[])
}
memcpy(wl->nvs, buf, len);
+ wl->nvs_len = len;
wl1271_debug(DEBUG_TESTMODE, "testmode pushed nvs");
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c
index c592cc2e9fe8..e3dc13c4d01a 100644
--- a/drivers/net/wireless/wl12xx/wl1271_tx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_tx.c
@@ -43,13 +43,17 @@ static int wl1271_tx_id(struct wl1271 *wl, struct sk_buff *skb)
return -EBUSY;
}
-static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra)
+static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
+ u32 buf_offset)
{
struct wl1271_tx_hw_descr *desc;
u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra;
u32 total_blocks;
int id, ret = -EBUSY;
+ if (buf_offset + total_len > WL1271_AGGR_BUFFER_SIZE)
+ return -EBUSY;
+
/* allocate free identifier for the packet */
id = wl1271_tx_id(wl, skb);
if (id < 0)
@@ -82,7 +86,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra)
return ret;
}
-static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
+static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
u32 extra, struct ieee80211_tx_info *control)
{
struct timespec ts;
@@ -110,9 +114,9 @@ static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
/* configure the tx attributes */
tx_attr = wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER;
- /* queue */
+ /* queue (we use same identifiers for tid's and ac's */
ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
- desc->tid = wl1271_tx_ac_to_tid(ac);
+ desc->tid = ac;
desc->aid = TX_HW_DEFAULT_AID;
desc->reserved = 0;
@@ -133,59 +137,17 @@ static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
desc->tx_attr = cpu_to_le16(tx_attr);
wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d", pad);
- return 0;
-}
-
-static int wl1271_tx_send_packet(struct wl1271 *wl, struct sk_buff *skb,
- struct ieee80211_tx_info *control)
-{
-
- struct wl1271_tx_hw_descr *desc;
- int len;
-
- /* FIXME: This is a workaround for getting non-aligned packets.
- This happens at least with EAPOL packets from the user space.
- Our DMA requires packets to be aligned on a 4-byte boundary.
- */
- if (unlikely((long)skb->data & 0x03)) {
- int offset = (4 - (long)skb->data) & 0x03;
- wl1271_debug(DEBUG_TX, "skb offset %d", offset);
-
- /* check whether the current skb can be used */
- if (!skb_cloned(skb) && (skb_tailroom(skb) >= offset)) {
- unsigned char *src = skb->data;
-
- /* align the buffer on a 4-byte boundary */
- skb_reserve(skb, offset);
- memmove(skb->data, src, skb->len);
- } else {
- wl1271_info("No handler, fixme!");
- return -EINVAL;
- }
- }
-
- len = WL1271_TX_ALIGN(skb->len);
-
- /* perform a fixed address block write with the packet */
- wl1271_write(wl, WL1271_SLV_MEM_DATA, skb->data, len, true);
-
- /* write packet new counter into the write access register */
- wl->tx_packets_count++;
-
- desc = (struct wl1271_tx_hw_descr *) skb->data;
- wl1271_debug(DEBUG_TX, "tx id %u skb 0x%p payload %u (%u words)",
- desc->id, skb, len, desc->length);
-
- return 0;
}
/* caller must hold wl->mutex */
-static int wl1271_tx_frame(struct wl1271 *wl, struct sk_buff *skb)
+static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,
+ u32 buf_offset)
{
struct ieee80211_tx_info *info;
u32 extra = 0;
int ret = 0;
u8 idx;
+ u32 total_len;
if (!skb)
return -EINVAL;
@@ -193,7 +155,7 @@ static int wl1271_tx_frame(struct wl1271 *wl, struct sk_buff *skb)
info = IEEE80211_SKB_CB(skb);
if (info->control.hw_key &&
- info->control.hw_key->alg == ALG_TKIP)
+ info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP)
extra = WL1271_TKIP_IV_SPACE;
if (info->control.hw_key) {
@@ -208,19 +170,22 @@ static int wl1271_tx_frame(struct wl1271 *wl, struct sk_buff *skb)
}
}
- ret = wl1271_tx_allocate(wl, skb, extra);
+ ret = wl1271_tx_allocate(wl, skb, extra, buf_offset);
if (ret < 0)
return ret;
- ret = wl1271_tx_fill_hdr(wl, skb, extra, info);
- if (ret < 0)
- return ret;
+ wl1271_tx_fill_hdr(wl, skb, extra, info);
- ret = wl1271_tx_send_packet(wl, skb, info);
- if (ret < 0)
- return ret;
+ /*
+ * The length of each packet is stored in terms of words. Thus, we must
+ * pad the skb data to make sure its length is aligned.
+ * The number of padding bytes is computed and set in wl1271_tx_fill_hdr
+ */
+ total_len = WL1271_TX_ALIGN(skb->len);
+ memcpy(wl->aggr_buf + buf_offset, skb->data, skb->len);
+ memset(wl->aggr_buf + buf_offset + skb->len, 0, total_len - skb->len);
- return ret;
+ return total_len;
}
u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set)
@@ -245,7 +210,7 @@ void wl1271_tx_work(struct work_struct *work)
struct sk_buff *skb;
bool woken_up = false;
u32 sta_rates = 0;
- u32 prev_tx_packets_count;
+ u32 buf_offset;
int ret;
/* check if the rates supported by the AP have changed */
@@ -262,14 +227,15 @@ void wl1271_tx_work(struct work_struct *work)
if (unlikely(wl->state == WL1271_STATE_OFF))
goto out;
- prev_tx_packets_count = wl->tx_packets_count;
-
/* if rates have changed, re-configure the rate policy */
if (unlikely(sta_rates)) {
wl->rate_set = wl1271_tx_enabled_rates_get(wl, sta_rates);
wl1271_acx_rate_policies(wl);
}
+ /* Prepare the transfer buffer, by aggregating all
+ * available packets */
+ buf_offset = 0;
while ((skb = skb_dequeue(&wl->tx_queue))) {
if (!woken_up) {
ret = wl1271_ps_elp_wakeup(wl, false);
@@ -278,21 +244,30 @@ void wl1271_tx_work(struct work_struct *work)
woken_up = true;
}
- ret = wl1271_tx_frame(wl, skb);
+ ret = wl1271_prepare_tx_frame(wl, skb, buf_offset);
if (ret == -EBUSY) {
- /* firmware buffer is full, lets stop transmitting. */
+ /*
+ * Either the firmware buffer is full, or the
+ * aggregation buffer is.
+ * Queue back last skb, and stop aggregating.
+ */
skb_queue_head(&wl->tx_queue, skb);
goto out_ack;
} else if (ret < 0) {
dev_kfree_skb(skb);
goto out_ack;
}
+ buf_offset += ret;
+ wl->tx_packets_count++;
}
out_ack:
- /* interrupt the firmware with the new packets */
- if (prev_tx_packets_count != wl->tx_packets_count)
+ if (buf_offset) {
+ wl1271_write(wl, WL1271_SLV_MEM_DATA, wl->aggr_buf,
+ buf_offset, true);
+ /* interrupt the firmware with the new packets */
wl1271_write32(wl, WL1271_HOST_WR_ACCESS, wl->tx_packets_count);
+ }
out:
if (woken_up)
@@ -347,7 +322,7 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
/* remove TKIP header space if present */
if (info->control.hw_key &&
- info->control.hw_key->alg == ALG_TKIP) {
+ info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) {
int hdrlen = ieee80211_get_hdrlen_from_skb(skb);
memmove(skb->data + WL1271_TKIP_IV_SPACE, skb->data, hdrlen);
skb_pull(skb, WL1271_TKIP_IV_SPACE);
@@ -422,8 +397,6 @@ void wl1271_tx_reset(struct wl1271 *wl)
struct sk_buff *skb;
/* TX failure */
-/* control->flags = 0; FIXME */
-
while ((skb = skb_dequeue(&wl->tx_queue))) {
wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb);
ieee80211_tx_status(wl->hw, skb);
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.h b/drivers/net/wireless/wl12xx/wl1271_tx.h
index 48bf92621c03..d12a129ad11c 100644
--- a/drivers/net/wireless/wl12xx/wl1271_tx.h
+++ b/drivers/net/wireless/wl12xx/wl1271_tx.h
@@ -139,23 +139,6 @@ static inline int wl1271_tx_get_queue(int queue)
}
}
-/* wl1271 tx descriptor needs the tid and we need to convert it from ac */
-static inline int wl1271_tx_ac_to_tid(int ac)
-{
- switch (ac) {
- case 0:
- return 0;
- case 1:
- return 2;
- case 2:
- return 4;
- case 3:
- return 6;
- default:
- return 0;
- }
-}
-
void wl1271_tx_work(struct work_struct *work);
void wl1271_tx_complete(struct wl1271 *wl);
void wl1271_tx_reset(struct wl1271 *wl);
diff --git a/drivers/net/wireless/wl12xx/wl12xx_platform_data.c b/drivers/net/wireless/wl12xx/wl12xx_platform_data.c
new file mode 100644
index 000000000000..973b11060a8f
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl12xx_platform_data.c
@@ -0,0 +1,28 @@
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/wl12xx.h>
+
+static const struct wl12xx_platform_data *platform_data;
+
+int __init wl12xx_set_platform_data(const struct wl12xx_platform_data *data)
+{
+ if (platform_data)
+ return -EBUSY;
+ if (!data)
+ return -EINVAL;
+
+ platform_data = kmemdup(data, sizeof(*data), GFP_KERNEL);
+ if (!platform_data)
+ return -ENOMEM;
+
+ return 0;
+}
+
+const struct wl12xx_platform_data *wl12xx_get_platform_data(void)
+{
+ if (!platform_data)
+ return ERR_PTR(-ENODEV);
+
+ return platform_data;
+}
+EXPORT_SYMBOL(wl12xx_get_platform_data);
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c
index a1cc2d498a1c..ee82df62e646 100644
--- a/drivers/net/wireless/wl3501_cs.c
+++ b/drivers/net/wireless/wl3501_cs.c
@@ -29,7 +29,6 @@
#include <linux/delay.h>
#include <linux/types.h>
-#include <linux/ethtool.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/in.h>
@@ -48,7 +47,6 @@
#include <net/iw_handler.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/ds.h>
@@ -78,13 +76,6 @@
#define WL3501_RESUME 0
#define WL3501_SUSPEND 1
-/*
- * The event() function is this driver's Card Services event handler. It will
- * be called by Card Services when an appropriate card status event is
- * received. The config() and release() entry points are used to configure or
- * release a socket, in response to card insertion and ejection events. They
- * are invoked from the wl24 event handler.
- */
static int wl3501_config(struct pcmcia_device *link);
static void wl3501_release(struct pcmcia_device *link);
@@ -1411,15 +1402,6 @@ static struct iw_statistics *wl3501_get_wireless_stats(struct net_device *dev)
return wstats;
}
-static void wl3501_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
-{
- strlcpy(info->driver, "wl3501_cs", sizeof(info->driver));
-}
-
-static const struct ethtool_ops ops = {
- .get_drvinfo = wl3501_get_drvinfo
-};
-
/**
* wl3501_detach - deletes a driver "instance"
* @link - FILL_IN
@@ -1869,15 +1851,6 @@ static const struct net_device_ops wl3501_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
};
-/**
- * wl3501_attach - creates an "instance" of the driver
- *
- * Creates an "instance" of the driver, allocating local data structures for
- * one device. The device is registered with Card Services.
- *
- * The dev_link structure is initialized, but we don't actually configure the
- * card at this point -- we wait until we receive a card insertion event.
- */
static int wl3501_probe(struct pcmcia_device *p_dev)
{
struct net_device *dev;
@@ -1888,9 +1861,8 @@ static int wl3501_probe(struct pcmcia_device *p_dev)
p_dev->resource[0]->flags = IO_DATA_PATH_WIDTH_8;
/* General socket configuration */
- p_dev->conf.Attributes = CONF_ENABLE_IRQ;
- p_dev->conf.IntType = INT_MEMORY_AND_IO;
- p_dev->conf.ConfigIndex = 1;
+ p_dev->config_flags = CONF_ENABLE_IRQ;
+ p_dev->config_index = 1;
dev = alloc_etherdev(sizeof(struct wl3501_card));
if (!dev)
@@ -1905,7 +1877,6 @@ static int wl3501_probe(struct pcmcia_device *p_dev)
this->p_dev = p_dev;
dev->wireless_data = &this->wireless_data;
dev->wireless_handlers = &wl3501_handler_def;
- SET_ETHTOOL_OPS(dev, &ops);
netif_stop_queue(dev);
p_dev->priv = dev;
@@ -1914,14 +1885,6 @@ out_link:
return -ENOMEM;
}
-/**
- * wl3501_config - configure the PCMCIA socket and make eth device available
- * @link - FILL_IN
- *
- * wl3501_config() is scheduled to run after a CARD_INSERTION event is
- * received, to configure the PCMCIA socket, and to make the ethernet device
- * available to the system.
- */
static int wl3501_config(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
@@ -1952,10 +1915,7 @@ static int wl3501_config(struct pcmcia_device *link)
if (ret)
goto failed;
- /* This actually configures the PCMCIA socket -- setting up the I/O
- * windows and the interrupt mapping. */
-
- ret = pcmcia_request_configuration(link, &link->conf);
+ ret = pcmcia_enable_device(link);
if (ret)
goto failed;
@@ -2010,14 +1970,6 @@ failed:
return -ENODEV;
}
-/**
- * wl3501_release - unregister the net, release PCMCIA configuration
- * @arg - link
- *
- * After a card is removed, wl3501_release() will unregister the net device,
- * and release the PCMCIA configuration. If the device is still open, this
- * will be postponed until it is closed.
- */
static void wl3501_release(struct pcmcia_device *link)
{
pcmcia_disable_device(link);
@@ -2056,9 +2008,7 @@ MODULE_DEVICE_TABLE(pcmcia, wl3501_ids);
static struct pcmcia_driver wl3501_driver = {
.owner = THIS_MODULE,
- .drv = {
- .name = "wl3501_cs",
- },
+ .name = "wl3501_cs",
.probe = wl3501_probe,
.remove = wl3501_detach,
.id_table = wl3501_ids,
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
index b2af3c549bb3..87a95bcfee57 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.c
+++ b/drivers/net/wireless/zd1211rw/zd_chip.c
@@ -973,6 +973,7 @@ static void dump_fw_registers(struct zd_chip *chip)
static int print_fw_version(struct zd_chip *chip)
{
+ struct wiphy *wiphy = zd_chip_to_mac(chip)->hw->wiphy;
int r;
u16 version;
@@ -982,6 +983,10 @@ static int print_fw_version(struct zd_chip *chip)
return r;
dev_info(zd_chip_dev(chip),"firmware version %04hx\n", version);
+
+ snprintf(wiphy->fw_version, sizeof(wiphy->fw_version),
+ "%04hx", version);
+
return 0;
}
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index b50fedcef8ac..630fb8664768 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -135,7 +135,7 @@ static void skb_entry_set_link(union skb_entry *list, unsigned short id)
static int skb_entry_is_link(const union skb_entry *list)
{
BUILD_BUG_ON(sizeof(list->skb) != sizeof(list->link));
- return ((unsigned long)list->skb < PAGE_OFFSET);
+ return (unsigned long)list->skb < PAGE_OFFSET;
}
/*
@@ -203,8 +203,8 @@ static void rx_refill_timeout(unsigned long data)
static int netfront_tx_slot_available(struct netfront_info *np)
{
- return ((np->tx.req_prod_pvt - np->tx.rsp_cons) <
- (TX_MAX_TARGET - MAX_SKB_FRAGS - 2));
+ return (np->tx.req_prod_pvt - np->tx.rsp_cons) <
+ (TX_MAX_TARGET - MAX_SKB_FRAGS - 2);
}
static void xennet_maybe_wake_tx(struct net_device *dev)
@@ -1395,7 +1395,7 @@ static int setup_netfront(struct xenbus_device *dev, struct netfront_info *info)
}
/* Common code used when first setting up, and when resuming. */
-static int talk_to_backend(struct xenbus_device *dev,
+static int talk_to_netback(struct xenbus_device *dev,
struct netfront_info *info)
{
const char *message;
@@ -1545,7 +1545,7 @@ static int xennet_connect(struct net_device *dev)
return -ENODEV;
}
- err = talk_to_backend(np->xbdev, np);
+ err = talk_to_netback(np->xbdev, np);
if (err)
return err;
@@ -1599,7 +1599,7 @@ static int xennet_connect(struct net_device *dev)
/**
* Callback received when the backend's state changes.
*/
-static void backend_changed(struct xenbus_device *dev,
+static void netback_changed(struct xenbus_device *dev,
enum xenbus_state backend_state)
{
struct netfront_info *np = dev_get_drvdata(&dev->dev);
@@ -1801,7 +1801,7 @@ static struct xenbus_driver netfront_driver = {
.probe = netfront_probe,
.remove = __devexit_p(xennet_remove),
.resume = netfront_resume,
- .otherend_changed = backend_changed,
+ .otherend_changed = netback_changed,
};
static int __init netif_init(void)
diff --git a/drivers/net/xilinx_emaclite.c b/drivers/net/xilinx_emaclite.c
index ecbbb688eba0..f3f8be5a35fa 100644
--- a/drivers/net/xilinx_emaclite.c
+++ b/drivers/net/xilinx_emaclite.c
@@ -641,7 +641,7 @@ static void xemaclite_rx_handler(struct net_device *dev)
skb_put(skb, len); /* Tell the skb how much data we got */
skb->protocol = eth_type_trans(skb, dev);
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
dev->stats.rx_packets++;
dev->stats.rx_bytes += len;
@@ -1269,6 +1269,16 @@ static int __devexit xemaclite_of_remove(struct platform_device *of_dev)
return 0;
}
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void
+xemaclite_poll_controller(struct net_device *ndev)
+{
+ disable_irq(ndev->irq);
+ xemaclite_interrupt(ndev->irq, ndev);
+ enable_irq(ndev->irq);
+}
+#endif
+
static struct net_device_ops xemaclite_netdev_ops = {
.ndo_open = xemaclite_open,
.ndo_stop = xemaclite_close,
@@ -1276,6 +1286,9 @@ static struct net_device_ops xemaclite_netdev_ops = {
.ndo_set_mac_address = xemaclite_set_mac_address,
.ndo_tx_timeout = xemaclite_tx_timeout,
.ndo_get_stats = xemaclite_get_stats,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = xemaclite_poll_controller,
+#endif
};
/* Match table for OF platform binding */
diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c
index 4eb67aed68dd..cd1b3dcd61db 100644
--- a/drivers/net/yellowfin.c
+++ b/drivers/net/yellowfin.c
@@ -646,7 +646,7 @@ static int yellowfin_open(struct net_device *dev)
init_timer(&yp->timer);
yp->timer.expires = jiffies + 3*HZ;
yp->timer.data = (unsigned long)dev;
- yp->timer.function = &yellowfin_timer; /* timer handler */
+ yp->timer.function = yellowfin_timer; /* timer handler */
add_timer(&yp->timer);
return 0;
diff --git a/drivers/oprofile/oprof.c b/drivers/oprofile/oprof.c
index b336cd9ee7a1..f9bda64fcd1b 100644
--- a/drivers/oprofile/oprof.c
+++ b/drivers/oprofile/oprof.c
@@ -225,26 +225,17 @@ post_sync:
mutex_unlock(&start_mutex);
}
-int oprofile_set_backtrace(unsigned long val)
+int oprofile_set_ulong(unsigned long *addr, unsigned long val)
{
- int err = 0;
+ int err = -EBUSY;
mutex_lock(&start_mutex);
-
- if (oprofile_started) {
- err = -EBUSY;
- goto out;
- }
-
- if (!oprofile_ops.backtrace) {
- err = -EINVAL;
- goto out;
+ if (!oprofile_started) {
+ *addr = val;
+ err = 0;
}
-
- oprofile_backtrace_depth = val;
-
-out:
mutex_unlock(&start_mutex);
+
return err;
}
@@ -257,16 +248,9 @@ static int __init oprofile_init(void)
printk(KERN_INFO "oprofile: using timer interrupt.\n");
err = oprofile_timer_init(&oprofile_ops);
if (err)
- goto out_arch;
+ return err;
}
- err = oprofilefs_register();
- if (err)
- goto out_arch;
- return 0;
-
-out_arch:
- oprofile_arch_exit();
- return err;
+ return oprofilefs_register();
}
diff --git a/drivers/oprofile/oprof.h b/drivers/oprofile/oprof.h
index 47e12cb4ee8b..177b73de5e5f 100644
--- a/drivers/oprofile/oprof.h
+++ b/drivers/oprofile/oprof.h
@@ -37,7 +37,7 @@ void oprofile_create_files(struct super_block *sb, struct dentry *root);
int oprofile_timer_init(struct oprofile_operations *ops);
void oprofile_timer_exit(void);
-int oprofile_set_backtrace(unsigned long depth);
+int oprofile_set_ulong(unsigned long *addr, unsigned long val);
int oprofile_set_timeout(unsigned long time);
#endif /* OPROF_H */
diff --git a/drivers/oprofile/oprofile_files.c b/drivers/oprofile/oprofile_files.c
index bbd7516e0869..89f63456646f 100644
--- a/drivers/oprofile/oprofile_files.c
+++ b/drivers/oprofile/oprofile_files.c
@@ -59,6 +59,7 @@ static ssize_t timeout_write(struct file *file, char const __user *buf,
static const struct file_operations timeout_fops = {
.read = timeout_read,
.write = timeout_write,
+ .llseek = default_llseek,
};
#endif
@@ -79,21 +80,25 @@ static ssize_t depth_write(struct file *file, char const __user *buf, size_t cou
if (*offset)
return -EINVAL;
+ if (!oprofile_ops.backtrace)
+ return -EINVAL;
+
retval = oprofilefs_ulong_from_user(&val, buf, count);
if (retval)
return retval;
- retval = oprofile_set_backtrace(val);
-
+ retval = oprofile_set_ulong(&oprofile_backtrace_depth, val);
if (retval)
return retval;
+
return count;
}
static const struct file_operations depth_fops = {
.read = depth_read,
- .write = depth_write
+ .write = depth_write,
+ .llseek = default_llseek,
};
@@ -105,6 +110,7 @@ static ssize_t pointer_size_read(struct file *file, char __user *buf, size_t cou
static const struct file_operations pointer_size_fops = {
.read = pointer_size_read,
+ .llseek = default_llseek,
};
@@ -116,6 +122,7 @@ static ssize_t cpu_type_read(struct file *file, char __user *buf, size_t count,
static const struct file_operations cpu_type_fops = {
.read = cpu_type_read,
+ .llseek = default_llseek,
};
@@ -151,6 +158,7 @@ static ssize_t enable_write(struct file *file, char const __user *buf, size_t co
static const struct file_operations enable_fops = {
.read = enable_read,
.write = enable_write,
+ .llseek = default_llseek,
};
@@ -163,6 +171,7 @@ static ssize_t dump_write(struct file *file, char const __user *buf, size_t coun
static const struct file_operations dump_fops = {
.write = dump_write,
+ .llseek = noop_llseek,
};
void oprofile_create_files(struct super_block *sb, struct dentry *root)
diff --git a/drivers/oprofile/oprofile_perf.c b/drivers/oprofile/oprofile_perf.c
new file mode 100644
index 000000000000..9046f7b2ed79
--- /dev/null
+++ b/drivers/oprofile/oprofile_perf.c
@@ -0,0 +1,328 @@
+/*
+ * Copyright 2010 ARM Ltd.
+ *
+ * Perf-events backend for OProfile.
+ */
+#include <linux/perf_event.h>
+#include <linux/platform_device.h>
+#include <linux/oprofile.h>
+#include <linux/slab.h>
+
+/*
+ * Per performance monitor configuration as set via oprofilefs.
+ */
+struct op_counter_config {
+ unsigned long count;
+ unsigned long enabled;
+ unsigned long event;
+ unsigned long unit_mask;
+ unsigned long kernel;
+ unsigned long user;
+ struct perf_event_attr attr;
+};
+
+static int oprofile_perf_enabled;
+static DEFINE_MUTEX(oprofile_perf_mutex);
+
+static struct op_counter_config *counter_config;
+static struct perf_event **perf_events[nr_cpumask_bits];
+static int num_counters;
+
+/*
+ * Overflow callback for oprofile.
+ */
+static void op_overflow_handler(struct perf_event *event, int unused,
+ struct perf_sample_data *data, struct pt_regs *regs)
+{
+ int id;
+ u32 cpu = smp_processor_id();
+
+ for (id = 0; id < num_counters; ++id)
+ if (perf_events[cpu][id] == event)
+ break;
+
+ if (id != num_counters)
+ oprofile_add_sample(regs, id);
+ else
+ pr_warning("oprofile: ignoring spurious overflow "
+ "on cpu %u\n", cpu);
+}
+
+/*
+ * Called by oprofile_perf_setup to create perf attributes to mirror the oprofile
+ * settings in counter_config. Attributes are created as `pinned' events and
+ * so are permanently scheduled on the PMU.
+ */
+static void op_perf_setup(void)
+{
+ int i;
+ u32 size = sizeof(struct perf_event_attr);
+ struct perf_event_attr *attr;
+
+ for (i = 0; i < num_counters; ++i) {
+ attr = &counter_config[i].attr;
+ memset(attr, 0, size);
+ attr->type = PERF_TYPE_RAW;
+ attr->size = size;
+ attr->config = counter_config[i].event;
+ attr->sample_period = counter_config[i].count;
+ attr->pinned = 1;
+ }
+}
+
+static int op_create_counter(int cpu, int event)
+{
+ struct perf_event *pevent;
+
+ if (!counter_config[event].enabled || perf_events[cpu][event])
+ return 0;
+
+ pevent = perf_event_create_kernel_counter(&counter_config[event].attr,
+ cpu, NULL,
+ op_overflow_handler);
+
+ if (IS_ERR(pevent))
+ return PTR_ERR(pevent);
+
+ if (pevent->state != PERF_EVENT_STATE_ACTIVE) {
+ perf_event_release_kernel(pevent);
+ pr_warning("oprofile: failed to enable event %d "
+ "on CPU %d\n", event, cpu);
+ return -EBUSY;
+ }
+
+ perf_events[cpu][event] = pevent;
+
+ return 0;
+}
+
+static void op_destroy_counter(int cpu, int event)
+{
+ struct perf_event *pevent = perf_events[cpu][event];
+
+ if (pevent) {
+ perf_event_release_kernel(pevent);
+ perf_events[cpu][event] = NULL;
+ }
+}
+
+/*
+ * Called by oprofile_perf_start to create active perf events based on the
+ * perviously configured attributes.
+ */
+static int op_perf_start(void)
+{
+ int cpu, event, ret = 0;
+
+ for_each_online_cpu(cpu) {
+ for (event = 0; event < num_counters; ++event) {
+ ret = op_create_counter(cpu, event);
+ if (ret)
+ return ret;
+ }
+ }
+
+ return ret;
+}
+
+/*
+ * Called by oprofile_perf_stop at the end of a profiling run.
+ */
+static void op_perf_stop(void)
+{
+ int cpu, event;
+
+ for_each_online_cpu(cpu)
+ for (event = 0; event < num_counters; ++event)
+ op_destroy_counter(cpu, event);
+}
+
+static int oprofile_perf_create_files(struct super_block *sb, struct dentry *root)
+{
+ unsigned int i;
+
+ for (i = 0; i < num_counters; i++) {
+ struct dentry *dir;
+ char buf[4];
+
+ snprintf(buf, sizeof buf, "%d", i);
+ dir = oprofilefs_mkdir(sb, root, buf);
+ oprofilefs_create_ulong(sb, dir, "enabled", &counter_config[i].enabled);
+ oprofilefs_create_ulong(sb, dir, "event", &counter_config[i].event);
+ oprofilefs_create_ulong(sb, dir, "count", &counter_config[i].count);
+ oprofilefs_create_ulong(sb, dir, "unit_mask", &counter_config[i].unit_mask);
+ oprofilefs_create_ulong(sb, dir, "kernel", &counter_config[i].kernel);
+ oprofilefs_create_ulong(sb, dir, "user", &counter_config[i].user);
+ }
+
+ return 0;
+}
+
+static int oprofile_perf_setup(void)
+{
+ spin_lock(&oprofilefs_lock);
+ op_perf_setup();
+ spin_unlock(&oprofilefs_lock);
+ return 0;
+}
+
+static int oprofile_perf_start(void)
+{
+ int ret = -EBUSY;
+
+ mutex_lock(&oprofile_perf_mutex);
+ if (!oprofile_perf_enabled) {
+ ret = 0;
+ op_perf_start();
+ oprofile_perf_enabled = 1;
+ }
+ mutex_unlock(&oprofile_perf_mutex);
+ return ret;
+}
+
+static void oprofile_perf_stop(void)
+{
+ mutex_lock(&oprofile_perf_mutex);
+ if (oprofile_perf_enabled)
+ op_perf_stop();
+ oprofile_perf_enabled = 0;
+ mutex_unlock(&oprofile_perf_mutex);
+}
+
+#ifdef CONFIG_PM
+
+static int oprofile_perf_suspend(struct platform_device *dev, pm_message_t state)
+{
+ mutex_lock(&oprofile_perf_mutex);
+ if (oprofile_perf_enabled)
+ op_perf_stop();
+ mutex_unlock(&oprofile_perf_mutex);
+ return 0;
+}
+
+static int oprofile_perf_resume(struct platform_device *dev)
+{
+ mutex_lock(&oprofile_perf_mutex);
+ if (oprofile_perf_enabled && op_perf_start())
+ oprofile_perf_enabled = 0;
+ mutex_unlock(&oprofile_perf_mutex);
+ return 0;
+}
+
+static struct platform_driver oprofile_driver = {
+ .driver = {
+ .name = "oprofile-perf",
+ },
+ .resume = oprofile_perf_resume,
+ .suspend = oprofile_perf_suspend,
+};
+
+static struct platform_device *oprofile_pdev;
+
+static int __init init_driverfs(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&oprofile_driver);
+ if (ret)
+ return ret;
+
+ oprofile_pdev = platform_device_register_simple(
+ oprofile_driver.driver.name, 0, NULL, 0);
+ if (IS_ERR(oprofile_pdev)) {
+ ret = PTR_ERR(oprofile_pdev);
+ platform_driver_unregister(&oprofile_driver);
+ }
+
+ return ret;
+}
+
+static void exit_driverfs(void)
+{
+ platform_device_unregister(oprofile_pdev);
+ platform_driver_unregister(&oprofile_driver);
+}
+
+#else
+
+static inline int init_driverfs(void) { return 0; }
+static inline void exit_driverfs(void) { }
+
+#endif /* CONFIG_PM */
+
+void oprofile_perf_exit(void)
+{
+ int cpu, id;
+ struct perf_event *event;
+
+ for_each_possible_cpu(cpu) {
+ for (id = 0; id < num_counters; ++id) {
+ event = perf_events[cpu][id];
+ if (event)
+ perf_event_release_kernel(event);
+ }
+
+ kfree(perf_events[cpu]);
+ }
+
+ kfree(counter_config);
+ exit_driverfs();
+}
+
+int __init oprofile_perf_init(struct oprofile_operations *ops)
+{
+ int cpu, ret = 0;
+
+ ret = init_driverfs();
+ if (ret)
+ return ret;
+
+ memset(&perf_events, 0, sizeof(perf_events));
+
+ num_counters = perf_num_counters();
+ if (num_counters <= 0) {
+ pr_info("oprofile: no performance counters\n");
+ ret = -ENODEV;
+ goto out;
+ }
+
+ counter_config = kcalloc(num_counters,
+ sizeof(struct op_counter_config), GFP_KERNEL);
+
+ if (!counter_config) {
+ pr_info("oprofile: failed to allocate %d "
+ "counters\n", num_counters);
+ ret = -ENOMEM;
+ num_counters = 0;
+ goto out;
+ }
+
+ for_each_possible_cpu(cpu) {
+ perf_events[cpu] = kcalloc(num_counters,
+ sizeof(struct perf_event *), GFP_KERNEL);
+ if (!perf_events[cpu]) {
+ pr_info("oprofile: failed to allocate %d perf events "
+ "for cpu %d\n", num_counters, cpu);
+ ret = -ENOMEM;
+ goto out;
+ }
+ }
+
+ ops->create_files = oprofile_perf_create_files;
+ ops->setup = oprofile_perf_setup;
+ ops->start = oprofile_perf_start;
+ ops->stop = oprofile_perf_stop;
+ ops->shutdown = oprofile_perf_stop;
+ ops->cpu_type = op_name_from_perf_id();
+
+ if (!ops->cpu_type)
+ ret = -ENODEV;
+ else
+ pr_info("oprofile: using %s\n", ops->cpu_type);
+
+out:
+ if (ret)
+ oprofile_perf_exit();
+
+ return ret;
+}
diff --git a/drivers/oprofile/oprofilefs.c b/drivers/oprofile/oprofilefs.c
index 2766a6d3c2e9..95f711b251ad 100644
--- a/drivers/oprofile/oprofilefs.c
+++ b/drivers/oprofile/oprofilefs.c
@@ -91,16 +91,20 @@ static ssize_t ulong_read_file(struct file *file, char __user *buf, size_t count
static ssize_t ulong_write_file(struct file *file, char const __user *buf, size_t count, loff_t *offset)
{
- unsigned long *value = file->private_data;
+ unsigned long value;
int retval;
if (*offset)
return -EINVAL;
- retval = oprofilefs_ulong_from_user(value, buf, count);
+ retval = oprofilefs_ulong_from_user(&value, buf, count);
+ if (retval)
+ return retval;
+ retval = oprofile_set_ulong(file->private_data, value);
if (retval)
return retval;
+
return count;
}
@@ -117,59 +121,52 @@ static const struct file_operations ulong_fops = {
.read = ulong_read_file,
.write = ulong_write_file,
.open = default_open,
+ .llseek = default_llseek,
};
static const struct file_operations ulong_ro_fops = {
.read = ulong_read_file,
.open = default_open,
+ .llseek = default_llseek,
};
-static struct dentry *__oprofilefs_create_file(struct super_block *sb,
+static int __oprofilefs_create_file(struct super_block *sb,
struct dentry *root, char const *name, const struct file_operations *fops,
- int perm)
+ int perm, void *priv)
{
struct dentry *dentry;
struct inode *inode;
dentry = d_alloc_name(root, name);
if (!dentry)
- return NULL;
+ return -ENOMEM;
inode = oprofilefs_get_inode(sb, S_IFREG | perm);
if (!inode) {
dput(dentry);
- return NULL;
+ return -ENOMEM;
}
inode->i_fop = fops;
d_add(dentry, inode);
- return dentry;
+ dentry->d_inode->i_private = priv;
+ return 0;
}
int oprofilefs_create_ulong(struct super_block *sb, struct dentry *root,
char const *name, unsigned long *val)
{
- struct dentry *d = __oprofilefs_create_file(sb, root, name,
- &ulong_fops, 0644);
- if (!d)
- return -EFAULT;
-
- d->d_inode->i_private = val;
- return 0;
+ return __oprofilefs_create_file(sb, root, name,
+ &ulong_fops, 0644, val);
}
int oprofilefs_create_ro_ulong(struct super_block *sb, struct dentry *root,
char const *name, unsigned long *val)
{
- struct dentry *d = __oprofilefs_create_file(sb, root, name,
- &ulong_ro_fops, 0444);
- if (!d)
- return -EFAULT;
-
- d->d_inode->i_private = val;
- return 0;
+ return __oprofilefs_create_file(sb, root, name,
+ &ulong_ro_fops, 0444, val);
}
@@ -183,37 +180,29 @@ static ssize_t atomic_read_file(struct file *file, char __user *buf, size_t coun
static const struct file_operations atomic_ro_fops = {
.read = atomic_read_file,
.open = default_open,
+ .llseek = default_llseek,
};
int oprofilefs_create_ro_atomic(struct super_block *sb, struct dentry *root,
char const *name, atomic_t *val)
{
- struct dentry *d = __oprofilefs_create_file(sb, root, name,
- &atomic_ro_fops, 0444);
- if (!d)
- return -EFAULT;
-
- d->d_inode->i_private = val;
- return 0;
+ return __oprofilefs_create_file(sb, root, name,
+ &atomic_ro_fops, 0444, val);
}
int oprofilefs_create_file(struct super_block *sb, struct dentry *root,
char const *name, const struct file_operations *fops)
{
- if (!__oprofilefs_create_file(sb, root, name, fops, 0644))
- return -EFAULT;
- return 0;
+ return __oprofilefs_create_file(sb, root, name, fops, 0644, NULL);
}
int oprofilefs_create_file_perm(struct super_block *sb, struct dentry *root,
char const *name, const struct file_operations *fops, int perm)
{
- if (!__oprofilefs_create_file(sb, root, name, fops, perm))
- return -EFAULT;
- return 0;
+ return __oprofilefs_create_file(sb, root, name, fops, perm, NULL);
}
diff --git a/drivers/parport/parport_cs.c b/drivers/parport/parport_cs.c
index 23e50f4a27c5..787ebdeae310 100644
--- a/drivers/parport/parport_cs.c
+++ b/drivers/parport/parport_cs.c
@@ -48,7 +48,6 @@
#include <linux/parport.h>
#include <linux/parport_pc.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
#include <pcmcia/cisreg.h>
@@ -81,14 +80,6 @@ static void parport_detach(struct pcmcia_device *p_dev);
static int parport_config(struct pcmcia_device *link);
static void parport_cs_release(struct pcmcia_device *);
-/*======================================================================
-
- parport_attach() creates an "instance" of the driver, allocating
- local data structures for one device. The device is registered
- with Card Services.
-
-======================================================================*/
-
static int parport_probe(struct pcmcia_device *link)
{
parport_info_t *info;
@@ -101,23 +92,11 @@ static int parport_probe(struct pcmcia_device *link)
link->priv = info;
info->p_dev = link;
- link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
- link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
- link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.IntType = INT_MEMORY_AND_IO;
+ link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
return parport_config(link);
} /* parport_attach */
-/*======================================================================
-
- This deletes a driver "instance". The device is de-registered
- with Card Services. If it has been released, all local data
- structures are freed. Otherwise, the structures will be freed
- when the device is released.
-
-======================================================================*/
-
static void parport_detach(struct pcmcia_device *link)
{
dev_dbg(&link->dev, "parport_detach\n");
@@ -127,36 +106,14 @@ static void parport_detach(struct pcmcia_device *link)
kfree(link->priv);
} /* parport_detach */
-/*======================================================================
-
- parport_config() is scheduled to run after a CARD_INSERTION event
- is received, to configure the PCMCIA socket, and to make the
- parport device available to the system.
-
-======================================================================*/
-
-static int parport_config_check(struct pcmcia_device *p_dev,
- cistpl_cftable_entry_t *cfg,
- cistpl_cftable_entry_t *dflt,
- unsigned int vcc,
- void *priv_data)
+static int parport_config_check(struct pcmcia_device *p_dev, void *priv_data)
{
- if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
- cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
- p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
- if (epp_mode)
- p_dev->conf.ConfigIndex |= FORCE_EPP_MODE;
- p_dev->resource[0]->start = io->win[0].base;
- p_dev->resource[0]->end = io->win[0].len;
- if (io->nwin == 2) {
- p_dev->resource[1]->start = io->win[1].base;
- p_dev->resource[1]->end = io->win[1].len;
- }
- if (pcmcia_request_io(p_dev) != 0)
- return -ENODEV;
- return 0;
- }
- return -ENODEV;
+ p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+ p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+ p_dev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
+ p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
+
+ return pcmcia_request_io(p_dev);
}
static int parport_config(struct pcmcia_device *link)
@@ -167,13 +124,16 @@ static int parport_config(struct pcmcia_device *link)
dev_dbg(&link->dev, "parport_config\n");
+ if (epp_mode)
+ link->config_index |= FORCE_EPP_MODE;
+
ret = pcmcia_loop_config(link, parport_config_check, NULL);
if (ret)
goto failed;
if (!link->irq)
goto failed;
- ret = pcmcia_request_configuration(link, &link->conf);
+ ret = pcmcia_enable_device(link);
if (ret)
goto failed;
@@ -202,14 +162,6 @@ failed:
return -ENODEV;
} /* parport_config */
-/*======================================================================
-
- After a card is removed, parport_cs_release() will unregister the
- device, and release the PCMCIA configuration. If the device is
- still open, this will be postponed until it is closed.
-
-======================================================================*/
-
static void parport_cs_release(struct pcmcia_device *link)
{
parport_info_t *info = link->priv;
@@ -236,9 +188,7 @@ MODULE_DEVICE_TABLE(pcmcia, parport_ids);
static struct pcmcia_driver parport_cs_driver = {
.owner = THIS_MODULE,
- .drv = {
- .name = "parport_cs",
- },
+ .name = "parport_cs",
.probe = parport_probe,
.remove = parport_detach,
.id_table = parport_ids,
diff --git a/drivers/parport/share.c b/drivers/parport/share.c
index dffa5d4fb298..a2d9d1e59260 100644
--- a/drivers/parport/share.c
+++ b/drivers/parport/share.c
@@ -306,7 +306,7 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma,
spin_lock_init(&tmp->pardevice_lock);
tmp->ieee1284.mode = IEEE1284_MODE_COMPAT;
tmp->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
- init_MUTEX_LOCKED (&tmp->ieee1284.irq); /* actually a semaphore at 0 */
+ sema_init(&tmp->ieee1284.irq, 0);
tmp->spintime = parport_default_spintime;
atomic_set (&tmp->ref_count, 1);
INIT_LIST_HEAD(&tmp->full_list);
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c
index 0a19708074c2..0157708d474d 100644
--- a/drivers/pci/dmar.c
+++ b/drivers/pci/dmar.c
@@ -36,6 +36,7 @@
#include <linux/tboot.h>
#include <linux/dmi.h>
#include <linux/slab.h>
+#include <asm/iommu_table.h>
#define PREFIX "DMAR: "
@@ -687,7 +688,7 @@ failed:
return 0;
}
-void __init detect_intel_iommu(void)
+int __init detect_intel_iommu(void)
{
int ret;
@@ -723,6 +724,8 @@ void __init detect_intel_iommu(void)
}
early_acpi_os_unmap_memory(dmar_tbl, dmar_tbl_size);
dmar_tbl = NULL;
+
+ return ret ? 1 : -ENODEV;
}
@@ -1221,9 +1224,9 @@ const char *dmar_get_fault_reason(u8 fault_reason, int *fault_type)
}
}
-void dmar_msi_unmask(unsigned int irq)
+void dmar_msi_unmask(struct irq_data *data)
{
- struct intel_iommu *iommu = get_irq_data(irq);
+ struct intel_iommu *iommu = irq_data_get_irq_data(data);
unsigned long flag;
/* unmask it */
@@ -1234,10 +1237,10 @@ void dmar_msi_unmask(unsigned int irq)
spin_unlock_irqrestore(&iommu->register_lock, flag);
}
-void dmar_msi_mask(unsigned int irq)
+void dmar_msi_mask(struct irq_data *data)
{
unsigned long flag;
- struct intel_iommu *iommu = get_irq_data(irq);
+ struct intel_iommu *iommu = irq_data_get_irq_data(data);
/* mask it */
spin_lock_irqsave(&iommu->register_lock, flag);
@@ -1455,3 +1458,4 @@ int __init dmar_ir_support(void)
return 0;
return dmar->flags & 0x1;
}
+IOMMU_INIT_POST(detect_intel_iommu);
diff --git a/drivers/pci/hotplug/cpqphp_sysfs.c b/drivers/pci/hotplug/cpqphp_sysfs.c
index 56215322930a..4cb30447a486 100644
--- a/drivers/pci/hotplug/cpqphp_sysfs.c
+++ b/drivers/pci/hotplug/cpqphp_sysfs.c
@@ -34,10 +34,11 @@
#include <linux/workqueue.h>
#include <linux/pci.h>
#include <linux/pci_hotplug.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/debugfs.h>
#include "cpqphp.h"
+static DEFINE_MUTEX(cpqphp_mutex);
static int show_ctrl (struct controller *ctrl, char *buf)
{
char *out = buf;
@@ -147,7 +148,7 @@ static int open(struct inode *inode, struct file *file)
struct ctrl_dbg *dbg;
int retval = -ENOMEM;
- lock_kernel();
+ mutex_lock(&cpqphp_mutex);
dbg = kmalloc(sizeof(*dbg), GFP_KERNEL);
if (!dbg)
goto exit;
@@ -160,7 +161,7 @@ static int open(struct inode *inode, struct file *file)
file->private_data = dbg;
retval = 0;
exit:
- unlock_kernel();
+ mutex_unlock(&cpqphp_mutex);
return retval;
}
@@ -169,7 +170,7 @@ static loff_t lseek(struct file *file, loff_t off, int whence)
struct ctrl_dbg *dbg;
loff_t new = -1;
- lock_kernel();
+ mutex_lock(&cpqphp_mutex);
dbg = file->private_data;
switch (whence) {
@@ -181,10 +182,10 @@ static loff_t lseek(struct file *file, loff_t off, int whence)
break;
}
if (new < 0 || new > dbg->size) {
- unlock_kernel();
+ mutex_unlock(&cpqphp_mutex);
return -EINVAL;
}
- unlock_kernel();
+ mutex_unlock(&cpqphp_mutex);
return (file->f_pos = new);
}
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index 73d513989263..838f571027b7 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -36,6 +36,7 @@
#include <linux/sched.h> /* signal_pending() */
#include <linux/pcieport_if.h>
#include <linux/mutex.h>
+#include <linux/workqueue.h>
#define MY_NAME "pciehp"
@@ -44,6 +45,7 @@ extern int pciehp_poll_time;
extern int pciehp_debug;
extern int pciehp_force;
extern struct workqueue_struct *pciehp_wq;
+extern struct workqueue_struct *pciehp_ordered_wq;
#define dbg(format, arg...) \
do { \
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index aa5f3ff629ff..7ac8358df8fd 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -43,6 +43,7 @@ int pciehp_poll_mode;
int pciehp_poll_time;
int pciehp_force;
struct workqueue_struct *pciehp_wq;
+struct workqueue_struct *pciehp_ordered_wq;
#define DRIVER_VERSION "0.4"
#define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>"
@@ -340,18 +341,33 @@ static int __init pcied_init(void)
{
int retval = 0;
+ pciehp_wq = alloc_workqueue("pciehp", 0, 0);
+ if (!pciehp_wq)
+ return -ENOMEM;
+
+ pciehp_ordered_wq = alloc_ordered_workqueue("pciehp_ordered", 0);
+ if (!pciehp_ordered_wq) {
+ destroy_workqueue(pciehp_wq);
+ return -ENOMEM;
+ }
+
pciehp_firmware_init();
retval = pcie_port_service_register(&hpdriver_portdrv);
dbg("pcie_port_service_register = %d\n", retval);
info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
- if (retval)
+ if (retval) {
+ destroy_workqueue(pciehp_ordered_wq);
+ destroy_workqueue(pciehp_wq);
dbg("Failure to register service\n");
+ }
return retval;
}
static void __exit pcied_cleanup(void)
{
dbg("unload_pciehpd()\n");
+ destroy_workqueue(pciehp_ordered_wq);
+ destroy_workqueue(pciehp_wq);
pcie_port_service_unregister(&hpdriver_portdrv);
info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n");
}
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
index 8f58148be044..085dbb5fc168 100644
--- a/drivers/pci/hotplug/pciehp_ctrl.c
+++ b/drivers/pci/hotplug/pciehp_ctrl.c
@@ -32,7 +32,6 @@
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/pci.h>
-#include <linux/workqueue.h>
#include "../pci.h"
#include "pciehp.h"
@@ -50,7 +49,7 @@ static int queue_interrupt_event(struct slot *p_slot, u32 event_type)
info->p_slot = p_slot;
INIT_WORK(&info->work, interrupt_event_handler);
- schedule_work(&info->work);
+ queue_work(pciehp_wq, &info->work);
return 0;
}
@@ -345,7 +344,7 @@ void pciehp_queue_pushbutton_work(struct work_struct *work)
kfree(info);
goto out;
}
- queue_work(pciehp_wq, &info->work);
+ queue_work(pciehp_ordered_wq, &info->work);
out:
mutex_unlock(&p_slot->lock);
}
@@ -378,7 +377,7 @@ static void handle_button_press_event(struct slot *p_slot)
if (ATTN_LED(ctrl))
pciehp_set_attention_status(p_slot, 0);
- schedule_delayed_work(&p_slot->work, 5*HZ);
+ queue_delayed_work(pciehp_wq, &p_slot->work, 5*HZ);
break;
case BLINKINGOFF_STATE:
case BLINKINGON_STATE:
@@ -440,7 +439,7 @@ static void handle_surprise_event(struct slot *p_slot)
else
p_slot->state = POWERON_STATE;
- queue_work(pciehp_wq, &info->work);
+ queue_work(pciehp_ordered_wq, &info->work);
}
static void interrupt_event_handler(struct work_struct *work)
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 0cd42047d89b..50a23da5d24d 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -41,8 +41,6 @@
#include "../pci.h"
#include "pciehp.h"
-static atomic_t pciehp_num_controllers = ATOMIC_INIT(0);
-
static inline int pciehp_readw(struct controller *ctrl, int reg, u16 *value)
{
struct pci_dev *dev = ctrl->pcie->port;
@@ -805,8 +803,8 @@ static void pcie_cleanup_slot(struct controller *ctrl)
{
struct slot *slot = ctrl->slot;
cancel_delayed_work(&slot->work);
- flush_scheduled_work();
flush_workqueue(pciehp_wq);
+ flush_workqueue(pciehp_ordered_wq);
kfree(slot);
}
@@ -912,16 +910,6 @@ struct controller *pcie_init(struct pcie_device *dev)
/* Disable sotfware notification */
pcie_disable_notification(ctrl);
- /*
- * If this is the first controller to be initialized,
- * initialize the pciehp work queue
- */
- if (atomic_add_return(1, &pciehp_num_controllers) == 1) {
- pciehp_wq = create_singlethread_workqueue("pciehpd");
- if (!pciehp_wq)
- goto abort_ctrl;
- }
-
ctrl_info(ctrl, "HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n",
pdev->vendor, pdev->device, pdev->subsystem_vendor,
pdev->subsystem_device);
@@ -941,11 +929,5 @@ void pciehp_release_ctrl(struct controller *ctrl)
{
pcie_shutdown_notification(ctrl);
pcie_cleanup_slot(ctrl);
- /*
- * If this is the last controller to be released, destroy the
- * pciehp work queue
- */
- if (atomic_dec_and_test(&pciehp_num_controllers))
- destroy_workqueue(pciehp_wq);
kfree(ctrl);
}
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h
index d2627e1c3ac1..e0c90e643b5f 100644
--- a/drivers/pci/hotplug/shpchp.h
+++ b/drivers/pci/hotplug/shpchp.h
@@ -35,6 +35,7 @@
#include <linux/delay.h>
#include <linux/sched.h> /* signal_pending(), struct timer_list */
#include <linux/mutex.h>
+#include <linux/workqueue.h>
#if !defined(MODULE)
#define MY_NAME "shpchp"
@@ -46,6 +47,7 @@ extern int shpchp_poll_mode;
extern int shpchp_poll_time;
extern int shpchp_debug;
extern struct workqueue_struct *shpchp_wq;
+extern struct workqueue_struct *shpchp_ordered_wq;
#define dbg(format, arg...) \
do { \
diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c
index a7bd5048396e..aca972bbfb4c 100644
--- a/drivers/pci/hotplug/shpchp_core.c
+++ b/drivers/pci/hotplug/shpchp_core.c
@@ -33,7 +33,6 @@
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/pci.h>
-#include <linux/workqueue.h>
#include "shpchp.h"
/* Global variables */
@@ -41,6 +40,7 @@ int shpchp_debug;
int shpchp_poll_mode;
int shpchp_poll_time;
struct workqueue_struct *shpchp_wq;
+struct workqueue_struct *shpchp_ordered_wq;
#define DRIVER_VERSION "0.4"
#define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>"
@@ -174,8 +174,8 @@ void cleanup_slots(struct controller *ctrl)
slot = list_entry(tmp, struct slot, slot_list);
list_del(&slot->slot_list);
cancel_delayed_work(&slot->work);
- flush_scheduled_work();
flush_workqueue(shpchp_wq);
+ flush_workqueue(shpchp_ordered_wq);
pci_hp_deregister(slot->hotplug_slot);
}
}
@@ -360,9 +360,23 @@ static int __init shpcd_init(void)
{
int retval = 0;
+ shpchp_wq = alloc_ordered_workqueue("shpchp", 0);
+ if (!shpchp_wq)
+ return -ENOMEM;
+
+ shpchp_ordered_wq = alloc_ordered_workqueue("shpchp_ordered", 0);
+ if (!shpchp_ordered_wq) {
+ destroy_workqueue(shpchp_wq);
+ return -ENOMEM;
+ }
+
retval = pci_register_driver(&shpc_driver);
dbg("%s: pci_register_driver = %d\n", __func__, retval);
info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
+ if (retval) {
+ destroy_workqueue(shpchp_ordered_wq);
+ destroy_workqueue(shpchp_wq);
+ }
return retval;
}
@@ -370,6 +384,8 @@ static void __exit shpcd_cleanup(void)
{
dbg("unload_shpchpd()\n");
pci_unregister_driver(&shpc_driver);
+ destroy_workqueue(shpchp_ordered_wq);
+ destroy_workqueue(shpchp_wq);
info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n");
}
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c
index 3387fbfb0c54..b00b09bdd38a 100644
--- a/drivers/pci/hotplug/shpchp_ctrl.c
+++ b/drivers/pci/hotplug/shpchp_ctrl.c
@@ -32,7 +32,6 @@
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/pci.h>
-#include <linux/workqueue.h>
#include "../pci.h"
#include "shpchp.h"
@@ -52,7 +51,7 @@ static int queue_interrupt_event(struct slot *p_slot, u32 event_type)
info->p_slot = p_slot;
INIT_WORK(&info->work, interrupt_event_handler);
- schedule_work(&info->work);
+ queue_work(shpchp_wq, &info->work);
return 0;
}
@@ -457,7 +456,7 @@ void shpchp_queue_pushbutton_work(struct work_struct *work)
kfree(info);
goto out;
}
- queue_work(shpchp_wq, &info->work);
+ queue_work(shpchp_ordered_wq, &info->work);
out:
mutex_unlock(&p_slot->lock);
}
@@ -505,7 +504,7 @@ static void handle_button_press_event(struct slot *p_slot)
p_slot->hpc_ops->green_led_blink(p_slot);
p_slot->hpc_ops->set_attention_status(p_slot, 0);
- schedule_delayed_work(&p_slot->work, 5*HZ);
+ queue_delayed_work(shpchp_wq, &p_slot->work, 5*HZ);
break;
case BLINKINGOFF_STATE:
case BLINKINGON_STATE:
diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c
index d3985e7deab7..36547f0ce305 100644
--- a/drivers/pci/hotplug/shpchp_hpc.c
+++ b/drivers/pci/hotplug/shpchp_hpc.c
@@ -179,8 +179,6 @@
#define SLOT_EVENT_LATCH 0x2
#define SLOT_SERR_INT_MASK 0x3
-static atomic_t shpchp_num_controllers = ATOMIC_INIT(0);
-
static irqreturn_t shpc_isr(int irq, void *dev_id);
static void start_int_poll_timer(struct controller *ctrl, int sec);
static int hpc_check_cmd_status(struct controller *ctrl);
@@ -614,13 +612,6 @@ static void hpc_release_ctlr(struct controller *ctrl)
iounmap(ctrl->creg);
release_mem_region(ctrl->mmio_base, ctrl->mmio_size);
-
- /*
- * If this is the last controller to be released, destroy the
- * shpchpd work queue
- */
- if (atomic_dec_and_test(&shpchp_num_controllers))
- destroy_workqueue(shpchp_wq);
}
static int hpc_power_on_slot(struct slot * slot)
@@ -1077,9 +1068,8 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev)
rc = request_irq(ctrl->pci_dev->irq, shpc_isr, IRQF_SHARED,
MY_NAME, (void *)ctrl);
- ctrl_dbg(ctrl, "request_irq %d for hpc%d (returns %d)\n",
- ctrl->pci_dev->irq,
- atomic_read(&shpchp_num_controllers), rc);
+ ctrl_dbg(ctrl, "request_irq %d (returns %d)\n",
+ ctrl->pci_dev->irq, rc);
if (rc) {
ctrl_err(ctrl, "Can't get irq %d for the hotplug "
"controller\n", ctrl->pci_dev->irq);
@@ -1092,18 +1082,6 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev)
shpc_get_cur_bus_speed(ctrl);
/*
- * If this is the first controller to be initialized,
- * initialize the shpchpd work queue
- */
- if (atomic_add_return(1, &shpchp_num_controllers) == 1) {
- shpchp_wq = create_singlethread_workqueue("shpchpd");
- if (!shpchp_wq) {
- rc = -ENOMEM;
- goto abort_iounmap;
- }
- }
-
- /*
* Unmask all event interrupts of all slots
*/
for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) {
diff --git a/drivers/pci/htirq.c b/drivers/pci/htirq.c
index 98abf8b91294..834842aa5bbf 100644
--- a/drivers/pci/htirq.c
+++ b/drivers/pci/htirq.c
@@ -57,28 +57,22 @@ void fetch_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg)
*msg = cfg->msg;
}
-void mask_ht_irq(unsigned int irq)
+void mask_ht_irq(struct irq_data *data)
{
- struct ht_irq_cfg *cfg;
- struct ht_irq_msg msg;
-
- cfg = get_irq_data(irq);
+ struct ht_irq_cfg *cfg = irq_data_get_irq_data(data);
+ struct ht_irq_msg msg = cfg->msg;
- msg = cfg->msg;
msg.address_lo |= 1;
- write_ht_irq_msg(irq, &msg);
+ write_ht_irq_msg(data->irq, &msg);
}
-void unmask_ht_irq(unsigned int irq)
+void unmask_ht_irq(struct irq_data *data)
{
- struct ht_irq_cfg *cfg;
- struct ht_irq_msg msg;
-
- cfg = get_irq_data(irq);
+ struct ht_irq_cfg *cfg = irq_data_get_irq_data(data);
+ struct ht_irq_msg msg = cfg->msg;
- msg = cfg->msg;
msg.address_lo &= ~1;
- write_ht_irq_msg(irq, &msg);
+ write_ht_irq_msg(data->irq, &msg);
}
/**
diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c
index fd1d2867cdcc..ec87cd66f3eb 100644
--- a/drivers/pci/intr_remapping.c
+++ b/drivers/pci/intr_remapping.c
@@ -46,109 +46,24 @@ static __init int setup_intremap(char *str)
}
early_param("intremap", setup_intremap);
-struct irq_2_iommu {
- struct intel_iommu *iommu;
- u16 irte_index;
- u16 sub_handle;
- u8 irte_mask;
-};
-
-#ifdef CONFIG_GENERIC_HARDIRQS
-static struct irq_2_iommu *get_one_free_irq_2_iommu(int node)
-{
- struct irq_2_iommu *iommu;
-
- iommu = kzalloc_node(sizeof(*iommu), GFP_ATOMIC, node);
- printk(KERN_DEBUG "alloc irq_2_iommu on node %d\n", node);
-
- return iommu;
-}
-
-static struct irq_2_iommu *irq_2_iommu(unsigned int irq)
-{
- struct irq_desc *desc;
-
- desc = irq_to_desc(irq);
-
- if (WARN_ON_ONCE(!desc))
- return NULL;
-
- return desc->irq_2_iommu;
-}
-
-static struct irq_2_iommu *irq_2_iommu_alloc(unsigned int irq)
-{
- struct irq_desc *desc;
- struct irq_2_iommu *irq_iommu;
-
- desc = irq_to_desc(irq);
- if (!desc) {
- printk(KERN_INFO "can not get irq_desc for %d\n", irq);
- return NULL;
- }
-
- irq_iommu = desc->irq_2_iommu;
-
- if (!irq_iommu)
- desc->irq_2_iommu = get_one_free_irq_2_iommu(irq_node(irq));
-
- return desc->irq_2_iommu;
-}
-
-#else /* !CONFIG_SPARSE_IRQ */
-
-static struct irq_2_iommu irq_2_iommuX[NR_IRQS];
-
-static struct irq_2_iommu *irq_2_iommu(unsigned int irq)
-{
- if (irq < nr_irqs)
- return &irq_2_iommuX[irq];
-
- return NULL;
-}
-static struct irq_2_iommu *irq_2_iommu_alloc(unsigned int irq)
-{
- return irq_2_iommu(irq);
-}
-#endif
-
static DEFINE_SPINLOCK(irq_2_ir_lock);
-static struct irq_2_iommu *valid_irq_2_iommu(unsigned int irq)
-{
- struct irq_2_iommu *irq_iommu;
-
- irq_iommu = irq_2_iommu(irq);
-
- if (!irq_iommu)
- return NULL;
-
- if (!irq_iommu->iommu)
- return NULL;
-
- return irq_iommu;
-}
-
-int irq_remapped(int irq)
+static struct irq_2_iommu *irq_2_iommu(unsigned int irq)
{
- return valid_irq_2_iommu(irq) != NULL;
+ struct irq_cfg *cfg = get_irq_chip_data(irq);
+ return cfg ? &cfg->irq_2_iommu : NULL;
}
int get_irte(int irq, struct irte *entry)
{
- int index;
- struct irq_2_iommu *irq_iommu;
+ struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
unsigned long flags;
+ int index;
- if (!entry)
+ if (!entry || !irq_iommu)
return -1;
spin_lock_irqsave(&irq_2_ir_lock, flags);
- irq_iommu = valid_irq_2_iommu(irq);
- if (!irq_iommu) {
- spin_unlock_irqrestore(&irq_2_ir_lock, flags);
- return -1;
- }
index = irq_iommu->irte_index + irq_iommu->sub_handle;
*entry = *(irq_iommu->iommu->ir_table->base + index);
@@ -160,20 +75,14 @@ int get_irte(int irq, struct irte *entry)
int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
{
struct ir_table *table = iommu->ir_table;
- struct irq_2_iommu *irq_iommu;
+ struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
u16 index, start_index;
unsigned int mask = 0;
unsigned long flags;
int i;
- if (!count)
- return -1;
-
-#ifndef CONFIG_SPARSE_IRQ
- /* protect irq_2_iommu_alloc later */
- if (irq >= nr_irqs)
+ if (!count || !irq_iommu)
return -1;
-#endif
/*
* start the IRTE search from index 0.
@@ -214,13 +123,6 @@ int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
for (i = index; i < index + count; i++)
table->base[i].present = 1;
- irq_iommu = irq_2_iommu_alloc(irq);
- if (!irq_iommu) {
- spin_unlock_irqrestore(&irq_2_ir_lock, flags);
- printk(KERN_ERR "can't allocate irq_2_iommu\n");
- return -1;
- }
-
irq_iommu->iommu = iommu;
irq_iommu->irte_index = index;
irq_iommu->sub_handle = 0;
@@ -244,17 +146,14 @@ static int qi_flush_iec(struct intel_iommu *iommu, int index, int mask)
int map_irq_to_irte_handle(int irq, u16 *sub_handle)
{
- int index;
- struct irq_2_iommu *irq_iommu;
+ struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
unsigned long flags;
+ int index;
- spin_lock_irqsave(&irq_2_ir_lock, flags);
- irq_iommu = valid_irq_2_iommu(irq);
- if (!irq_iommu) {
- spin_unlock_irqrestore(&irq_2_ir_lock, flags);
+ if (!irq_iommu)
return -1;
- }
+ spin_lock_irqsave(&irq_2_ir_lock, flags);
*sub_handle = irq_iommu->sub_handle;
index = irq_iommu->irte_index;
spin_unlock_irqrestore(&irq_2_ir_lock, flags);
@@ -263,18 +162,13 @@ int map_irq_to_irte_handle(int irq, u16 *sub_handle)
int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle)
{
- struct irq_2_iommu *irq_iommu;
+ struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
unsigned long flags;
- spin_lock_irqsave(&irq_2_ir_lock, flags);
-
- irq_iommu = irq_2_iommu_alloc(irq);
-
- if (!irq_iommu) {
- spin_unlock_irqrestore(&irq_2_ir_lock, flags);
- printk(KERN_ERR "can't allocate irq_2_iommu\n");
+ if (!irq_iommu)
return -1;
- }
+
+ spin_lock_irqsave(&irq_2_ir_lock, flags);
irq_iommu->iommu = iommu;
irq_iommu->irte_index = index;
@@ -286,43 +180,18 @@ int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle)
return 0;
}
-int clear_irte_irq(int irq, struct intel_iommu *iommu, u16 index)
-{
- struct irq_2_iommu *irq_iommu;
- unsigned long flags;
-
- spin_lock_irqsave(&irq_2_ir_lock, flags);
- irq_iommu = valid_irq_2_iommu(irq);
- if (!irq_iommu) {
- spin_unlock_irqrestore(&irq_2_ir_lock, flags);
- return -1;
- }
-
- irq_iommu->iommu = NULL;
- irq_iommu->irte_index = 0;
- irq_iommu->sub_handle = 0;
- irq_2_iommu(irq)->irte_mask = 0;
-
- spin_unlock_irqrestore(&irq_2_ir_lock, flags);
-
- return 0;
-}
-
int modify_irte(int irq, struct irte *irte_modified)
{
- int rc;
- int index;
- struct irte *irte;
+ struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
struct intel_iommu *iommu;
- struct irq_2_iommu *irq_iommu;
unsigned long flags;
+ struct irte *irte;
+ int rc, index;
- spin_lock_irqsave(&irq_2_ir_lock, flags);
- irq_iommu = valid_irq_2_iommu(irq);
- if (!irq_iommu) {
- spin_unlock_irqrestore(&irq_2_ir_lock, flags);
+ if (!irq_iommu)
return -1;
- }
+
+ spin_lock_irqsave(&irq_2_ir_lock, flags);
iommu = irq_iommu->iommu;
@@ -339,31 +208,6 @@ int modify_irte(int irq, struct irte *irte_modified)
return rc;
}
-int flush_irte(int irq)
-{
- int rc;
- int index;
- struct intel_iommu *iommu;
- struct irq_2_iommu *irq_iommu;
- unsigned long flags;
-
- spin_lock_irqsave(&irq_2_ir_lock, flags);
- irq_iommu = valid_irq_2_iommu(irq);
- if (!irq_iommu) {
- spin_unlock_irqrestore(&irq_2_ir_lock, flags);
- return -1;
- }
-
- iommu = irq_iommu->iommu;
-
- index = irq_iommu->irte_index + irq_iommu->sub_handle;
-
- rc = qi_flush_iec(iommu, index, irq_iommu->irte_mask);
- spin_unlock_irqrestore(&irq_2_ir_lock, flags);
-
- return rc;
-}
-
struct intel_iommu *map_hpet_to_ir(u8 hpet_id)
{
int i;
@@ -420,16 +264,14 @@ static int clear_entries(struct irq_2_iommu *irq_iommu)
int free_irte(int irq)
{
- int rc = 0;
- struct irq_2_iommu *irq_iommu;
+ struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
unsigned long flags;
+ int rc;
- spin_lock_irqsave(&irq_2_ir_lock, flags);
- irq_iommu = valid_irq_2_iommu(irq);
- if (!irq_iommu) {
- spin_unlock_irqrestore(&irq_2_ir_lock, flags);
+ if (!irq_iommu)
return -1;
- }
+
+ spin_lock_irqsave(&irq_2_ir_lock, flags);
rc = clear_entries(irq_iommu);
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 69b7be33b3a2..5fcf5aec680f 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -170,33 +170,31 @@ static void msix_mask_irq(struct msi_desc *desc, u32 flag)
desc->masked = __msix_mask_irq(desc, flag);
}
-static void msi_set_mask_bit(unsigned irq, u32 flag)
+static void msi_set_mask_bit(struct irq_data *data, u32 flag)
{
- struct msi_desc *desc = get_irq_msi(irq);
+ struct msi_desc *desc = irq_data_get_msi(data);
if (desc->msi_attrib.is_msix) {
msix_mask_irq(desc, flag);
readl(desc->mask_base); /* Flush write to device */
} else {
- unsigned offset = irq - desc->dev->irq;
+ unsigned offset = data->irq - desc->dev->irq;
msi_mask_irq(desc, 1 << offset, flag << offset);
}
}
-void mask_msi_irq(unsigned int irq)
+void mask_msi_irq(struct irq_data *data)
{
- msi_set_mask_bit(irq, 1);
+ msi_set_mask_bit(data, 1);
}
-void unmask_msi_irq(unsigned int irq)
+void unmask_msi_irq(struct irq_data *data)
{
- msi_set_mask_bit(irq, 0);
+ msi_set_mask_bit(data, 0);
}
-void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg)
+void __read_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
{
- struct msi_desc *entry = get_irq_desc_msi(desc);
-
BUG_ON(entry->dev->current_state != PCI_D0);
if (entry->msi_attrib.is_msix) {
@@ -227,15 +225,13 @@ void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg)
void read_msi_msg(unsigned int irq, struct msi_msg *msg)
{
- struct irq_desc *desc = irq_to_desc(irq);
+ struct msi_desc *entry = get_irq_msi(irq);
- read_msi_msg_desc(desc, msg);
+ __read_msi_msg(entry, msg);
}
-void get_cached_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg)
+void __get_cached_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
{
- struct msi_desc *entry = get_irq_desc_msi(desc);
-
/* Assert that the cache is valid, assuming that
* valid messages are not all-zeroes. */
BUG_ON(!(entry->msg.address_hi | entry->msg.address_lo |
@@ -246,15 +242,13 @@ void get_cached_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg)
void get_cached_msi_msg(unsigned int irq, struct msi_msg *msg)
{
- struct irq_desc *desc = irq_to_desc(irq);
+ struct msi_desc *entry = get_irq_msi(irq);
- get_cached_msi_msg_desc(desc, msg);
+ __get_cached_msi_msg(entry, msg);
}
-void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg)
+void __write_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
{
- struct msi_desc *entry = get_irq_desc_msi(desc);
-
if (entry->dev->current_state != PCI_D0) {
/* Don't touch the hardware now */
} else if (entry->msi_attrib.is_msix) {
@@ -292,9 +286,9 @@ void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg)
void write_msi_msg(unsigned int irq, struct msi_msg *msg)
{
- struct irq_desc *desc = irq_to_desc(irq);
+ struct msi_desc *entry = get_irq_msi(irq);
- write_msi_msg_desc(desc, msg);
+ __write_msi_msg(entry, msg);
}
static void free_msi_irqs(struct pci_dev *dev)
diff --git a/drivers/pci/pcie/aer/aer_inject.c b/drivers/pci/pcie/aer/aer_inject.c
index 909924692b8a..b3cf6223f63a 100644
--- a/drivers/pci/pcie/aer/aer_inject.c
+++ b/drivers/pci/pcie/aer/aer_inject.c
@@ -472,6 +472,7 @@ static ssize_t aer_inject_write(struct file *filp, const char __user *ubuf,
static const struct file_operations aer_inject_fops = {
.write = aer_inject_write,
.owner = THIS_MODULE,
+ .llseek = noop_llseek,
};
static struct miscdevice aer_inject_device = {
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 89ed181cd90c..857ae01734a6 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -163,6 +163,26 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_2, quirk_isa_d
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_3, quirk_isa_dma_hangs);
/*
+ * Intel NM10 "TigerPoint" LPC PM1a_STS.BM_STS must be clear
+ * for some HT machines to use C4 w/o hanging.
+ */
+static void __devinit quirk_tigerpoint_bm_sts(struct pci_dev *dev)
+{
+ u32 pmbase;
+ u16 pm1a;
+
+ pci_read_config_dword(dev, 0x40, &pmbase);
+ pmbase = pmbase & 0xff80;
+ pm1a = inw(pmbase);
+
+ if (pm1a & 0x10) {
+ dev_info(&dev->dev, FW_BUG "TigerPoint LPC.BM_STS cleared\n");
+ outw(0x10, pmbase);
+ }
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TGP_LPC, quirk_tigerpoint_bm_sts);
+
+/*
* Chipsets where PCI->PCI transfers vanish or hang
*/
static void __devinit quirk_nopcipci(struct pci_dev *dev)
diff --git a/drivers/pcmcia/au1000_generic.c b/drivers/pcmcia/au1000_generic.c
index 88c4c4098789..95dd7c62741f 100644
--- a/drivers/pcmcia/au1000_generic.c
+++ b/drivers/pcmcia/au1000_generic.c
@@ -441,14 +441,12 @@ int au1x00_pcmcia_socket_probe(struct device *dev, struct pcmcia_low_level *ops,
out_err:
- flush_scheduled_work();
ops->hw_shutdown(skt);
while (i-- > 0) {
skt = PCMCIA_SOCKET(i);
del_timer_sync(&skt->poll_timer);
pcmcia_unregister_socket(&skt->socket);
- flush_scheduled_work();
if (i == 0) {
iounmap(skt->virt_io + (u32)mips_io_port_base);
skt->virt_io = NULL;
@@ -480,7 +478,6 @@ int au1x00_drv_pcmcia_remove(struct platform_device *dev)
del_timer_sync(&skt->poll_timer);
pcmcia_unregister_socket(&skt->socket);
- flush_scheduled_work();
skt->ops->hw_shutdown(skt);
au1x00_pcmcia_config_skt(skt, &dead_socket);
iounmap(skt->virt_io + (u32)mips_io_port_base);
diff --git a/drivers/pcmcia/au1000_generic.h b/drivers/pcmcia/au1000_generic.h
index 67530cefcf3c..5c36bda2963b 100644
--- a/drivers/pcmcia/au1000_generic.h
+++ b/drivers/pcmcia/au1000_generic.h
@@ -23,7 +23,6 @@
/* include the world */
-#include <pcmcia/cs.h>
#include <pcmcia/ss.h>
#include <pcmcia/cistpl.h>
#include "cs_internal.h"
diff --git a/drivers/pcmcia/au1000_pb1x00.c b/drivers/pcmcia/au1000_pb1x00.c
index 807f2d75dad3..b2396647a165 100644
--- a/drivers/pcmcia/au1000_pb1x00.c
+++ b/drivers/pcmcia/au1000_pb1x00.c
@@ -31,7 +31,6 @@
#include <linux/proc_fs.h>
#include <linux/types.h>
-#include <pcmcia/cs.h>
#include <pcmcia/ss.h>
#include <pcmcia/cistpl.h>
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
index 91414a0ddc44..884a984216fe 100644
--- a/drivers/pcmcia/cistpl.c
+++ b/drivers/pcmcia/cistpl.c
@@ -28,7 +28,6 @@
#include <asm/unaligned.h>
#include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/cistpl.h>
#include "cs_internal.h"
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index 2ec8ac97445c..d9ea192c4001 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -33,7 +33,6 @@
#include <asm/irq.h>
#include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/ds.h>
@@ -845,7 +844,7 @@ static int pcmcia_socket_dev_resume_noirq(struct device *dev)
return __pcmcia_pm_op(dev, socket_early_resume);
}
-static int pcmcia_socket_dev_resume(struct device *dev)
+static int __used pcmcia_socket_dev_resume(struct device *dev)
{
return __pcmcia_pm_op(dev, socket_late_resume);
}
diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h
index da055dc14d98..7f1953f78b12 100644
--- a/drivers/pcmcia/cs_internal.h
+++ b/drivers/pcmcia/cs_internal.h
@@ -33,18 +33,9 @@
typedef struct config_t {
struct kref ref;
unsigned int state;
- unsigned int Attributes;
- unsigned int IntType;
- unsigned int ConfigBase;
- unsigned char Status, Pin, Copy, Option, ExtStatus;
- unsigned int CardValues;
struct resource io[MAX_IO_WIN]; /* io ports */
struct resource mem[MAX_WIN]; /* mem areas */
-
- struct {
- u_int Attributes;
- } irq;
} config_t;
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 55570d9e1e4c..100c4412457d 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -26,7 +26,6 @@
#include <linux/dma-mapping.h>
#include <linux/slab.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
#include <pcmcia/ss.h>
@@ -52,7 +51,7 @@ static void pcmcia_check_driver(struct pcmcia_driver *p_drv)
if (!p_drv->probe || !p_drv->remove)
printk(KERN_DEBUG "pcmcia: %s lacks a requisite callback "
- "function\n", p_drv->drv.name);
+ "function\n", p_drv->name);
while (did && did->match_flags) {
for (i = 0; i < 4; i++) {
@@ -65,7 +64,7 @@ static void pcmcia_check_driver(struct pcmcia_driver *p_drv)
printk(KERN_DEBUG "pcmcia: %s: invalid hash for "
"product string \"%s\": is 0x%x, should "
- "be 0x%x\n", p_drv->drv.name, did->prod_id[i],
+ "be 0x%x\n", p_drv->name, did->prod_id[i],
did->prod_id_hash[i], hash);
printk(KERN_DEBUG "pcmcia: see "
"Documentation/pcmcia/devicetable.txt for "
@@ -180,10 +179,11 @@ int pcmcia_register_driver(struct pcmcia_driver *driver)
/* initialize common fields */
driver->drv.bus = &pcmcia_bus_type;
driver->drv.owner = driver->owner;
+ driver->drv.name = driver->name;
mutex_init(&driver->dynids.lock);
INIT_LIST_HEAD(&driver->dynids.list);
- pr_debug("registering driver %s\n", driver->drv.name);
+ pr_debug("registering driver %s\n", driver->name);
error = driver_register(&driver->drv);
if (error < 0)
@@ -203,7 +203,7 @@ EXPORT_SYMBOL(pcmcia_register_driver);
*/
void pcmcia_unregister_driver(struct pcmcia_driver *driver)
{
- pr_debug("unregistering driver %s\n", driver->drv.name);
+ pr_debug("unregistering driver %s\n", driver->name);
driver_unregister(&driver->drv);
pcmcia_free_dynids(driver);
}
@@ -264,7 +264,7 @@ static int pcmcia_device_probe(struct device *dev)
p_drv = to_pcmcia_drv(dev->driver);
s = p_dev->socket;
- dev_dbg(dev, "trying to bind to %s\n", p_drv->drv.name);
+ dev_dbg(dev, "trying to bind to %s\n", p_drv->name);
if ((!p_drv->probe) || (!p_dev->function_config) ||
(!try_module_get(p_drv->owner))) {
@@ -276,21 +276,28 @@ static int pcmcia_device_probe(struct device *dev)
ret = pccard_read_tuple(p_dev->socket, p_dev->func, CISTPL_CONFIG,
&cis_config);
if (!ret) {
- p_dev->conf.ConfigBase = cis_config.base;
- p_dev->conf.Present = cis_config.rmask[0];
+ p_dev->config_base = cis_config.base;
+ p_dev->config_regs = cis_config.rmask[0];
+ dev_dbg(dev, "base %x, regs %x", p_dev->config_base,
+ p_dev->config_regs);
} else {
dev_printk(KERN_INFO, dev,
"pcmcia: could not parse base and rmask0 of CIS\n");
- p_dev->conf.ConfigBase = 0;
- p_dev->conf.Present = 0;
+ p_dev->config_base = 0;
+ p_dev->config_regs = 0;
}
ret = p_drv->probe(p_dev);
if (ret) {
dev_dbg(dev, "binding to %s failed with %d\n",
- p_drv->drv.name, ret);
+ p_drv->name, ret);
goto put_module;
}
+ dev_dbg(dev, "%s bound: Vpp %d.%d, idx %x, IRQ %d", p_drv->name,
+ p_dev->vpp/10, p_dev->vpp%10, p_dev->config_index, p_dev->irq);
+ dev_dbg(dev, "resources: ioport %pR %pR iomem %pR %pR %pR",
+ p_dev->resource[0], p_dev->resource[1], p_dev->resource[2],
+ p_dev->resource[3], p_dev->resource[4]);
mutex_lock(&s->ops_mutex);
if ((s->pcmcia_pfc) &&
@@ -374,13 +381,13 @@ static int pcmcia_device_remove(struct device *dev)
if (p_dev->_irq || p_dev->_io || p_dev->_locked)
dev_printk(KERN_INFO, dev,
"pcmcia: driver %s did not release config properly\n",
- p_drv->drv.name);
+ p_drv->name);
for (i = 0; i < MAX_WIN; i++)
if (p_dev->_win & CLIENT_WIN_REQ(i))
dev_printk(KERN_INFO, dev,
"pcmcia: driver %s did not release window properly\n",
- p_drv->drv.name);
+ p_drv->name);
/* references from pcmcia_probe_device */
pcmcia_put_dev(p_dev);
@@ -1136,7 +1143,7 @@ static int pcmcia_dev_suspend(struct device *dev, pm_message_t state)
dev_printk(KERN_ERR, dev,
"pcmcia: device %s (driver %s) did "
"not want to go to sleep (%d)\n",
- p_dev->devname, p_drv->drv.name, ret);
+ p_dev->devname, p_drv->name, ret);
mutex_lock(&p_dev->socket->ops_mutex);
p_dev->suspended = 0;
mutex_unlock(&p_dev->socket->ops_mutex);
@@ -1178,7 +1185,7 @@ static int pcmcia_dev_resume(struct device *dev)
if (p_dev->device_no == p_dev->func) {
dev_dbg(dev, "requesting configuration\n");
- ret = pcmcia_request_configuration(p_dev, &p_dev->conf);
+ ret = pcmcia_enable_device(p_dev);
if (ret)
goto out;
}
diff --git a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c
index 05d0879ce935..fc7906eaf228 100644
--- a/drivers/pcmcia/i82092.c
+++ b/drivers/pcmcia/i82092.c
@@ -16,7 +16,6 @@
#include <linux/device.h>
#include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
#include <asm/system.h>
#include <asm/io.h>
diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c
index 61746bd598b3..72a033a2acdb 100644
--- a/drivers/pcmcia/i82365.c
+++ b/drivers/pcmcia/i82365.c
@@ -51,7 +51,6 @@
#include <asm/system.h>
#include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
#include <linux/isapnp.h>
diff --git a/drivers/pcmcia/m32r_cfc.c b/drivers/pcmcia/m32r_cfc.c
index 24de49925863..2adb0106a039 100644
--- a/drivers/pcmcia/m32r_cfc.c
+++ b/drivers/pcmcia/m32r_cfc.c
@@ -27,7 +27,6 @@
#include <asm/system.h>
#include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
#undef MAX_IO_WIN /* FIXME */
#define MAX_IO_WIN 1
diff --git a/drivers/pcmcia/m32r_pcc.c b/drivers/pcmcia/m32r_pcc.c
index 8e4723844ad3..1511ff71c87b 100644
--- a/drivers/pcmcia/m32r_pcc.c
+++ b/drivers/pcmcia/m32r_pcc.c
@@ -28,7 +28,6 @@
#include <asm/addrspace.h>
#include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
/* XXX: should be moved into asm/irq.h */
#define PCC0_IRQ 24
diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c
index f0ecad99ce81..99d4f23cb435 100644
--- a/drivers/pcmcia/m8xx_pcmcia.c
+++ b/drivers/pcmcia/m8xx_pcmcia.c
@@ -59,7 +59,6 @@
#include <asm/irq.h>
#include <asm/fs_pd.h>
-#include <pcmcia/cs.h>
#include <pcmcia/ss.h>
#define pcmcia_info(args...) printk(KERN_INFO "m8xx_pcmcia: "args)
diff --git a/drivers/pcmcia/o2micro.h b/drivers/pcmcia/o2micro.h
index e74bebac2695..5096e92c7a4c 100644
--- a/drivers/pcmcia/o2micro.h
+++ b/drivers/pcmcia/o2micro.h
@@ -153,14 +153,14 @@ static int o2micro_override(struct yenta_socket *socket)
if (use_speedup) {
dev_info(&socket->dev->dev,
- "O2: enabling read prefetch/write burst\n");
+ "O2: enabling read prefetch/write burst. If you experience problems or performance issues, use the yenta_socket parameter 'o2_speedup=off'\n");
config_writeb(socket, O2_RESERVED1,
a | O2_RES_READ_PREFETCH | O2_RES_WRITE_BURST);
config_writeb(socket, O2_RESERVED2,
b | O2_RES_READ_PREFETCH | O2_RES_WRITE_BURST);
} else {
dev_info(&socket->dev->dev,
- "O2: disabling read prefetch/write burst\n");
+ "O2: disabling read prefetch/write burst. If you experience problems or performance issues, use the yenta_socket parameter 'o2_speedup=on'\n");
config_writeb(socket, O2_RESERVED1,
a & ~(O2_RES_READ_PREFETCH | O2_RES_WRITE_BURST));
config_writeb(socket, O2_RESERVED2,
diff --git a/drivers/pcmcia/pcmcia_cis.c b/drivers/pcmcia/pcmcia_cis.c
index 0ac54da15885..e2c92415b892 100644
--- a/drivers/pcmcia/pcmcia_cis.c
+++ b/drivers/pcmcia/pcmcia_cis.c
@@ -6,7 +6,7 @@
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* Copyright (C) 1999 David A. Hinds
- * Copyright (C) 2004-2009 Dominik Brodowski
+ * Copyright (C) 2004-2010 Dominik Brodowski
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -22,7 +22,6 @@
#include <pcmcia/cisreg.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
#include <pcmcia/ds.h>
#include "cs_internal.h"
@@ -126,14 +125,24 @@ next_entry:
return ret;
}
+
+/**
+ * pcmcia_io_cfg_data_width() - convert cfgtable to data path width parameter
+ */
+static int pcmcia_io_cfg_data_width(unsigned int flags)
+{
+ if (!(flags & CISTPL_IO_8BIT))
+ return IO_DATA_PATH_WIDTH_16;
+ if (!(flags & CISTPL_IO_16BIT))
+ return IO_DATA_PATH_WIDTH_8;
+ return IO_DATA_PATH_WIDTH_AUTO;
+}
+
+
struct pcmcia_cfg_mem {
struct pcmcia_device *p_dev;
+ int (*conf_check) (struct pcmcia_device *p_dev, void *priv_data);
void *priv_data;
- int (*conf_check) (struct pcmcia_device *p_dev,
- cistpl_cftable_entry_t *cfg,
- cistpl_cftable_entry_t *dflt,
- unsigned int vcc,
- void *priv_data);
cisparse_t parse;
cistpl_cftable_entry_t dflt;
};
@@ -147,25 +156,102 @@ struct pcmcia_cfg_mem {
*/
static int pcmcia_do_loop_config(tuple_t *tuple, cisparse_t *parse, void *priv)
{
- cistpl_cftable_entry_t *cfg = &parse->cftable_entry;
struct pcmcia_cfg_mem *cfg_mem = priv;
+ struct pcmcia_device *p_dev = cfg_mem->p_dev;
+ cistpl_cftable_entry_t *cfg = &parse->cftable_entry;
+ cistpl_cftable_entry_t *dflt = &cfg_mem->dflt;
+ unsigned int flags = p_dev->config_flags;
+ unsigned int vcc = p_dev->socket->socket.Vcc;
+
+ dev_dbg(&p_dev->dev, "testing configuration %x, autoconf %x\n",
+ cfg->index, flags);
/* default values */
- cfg_mem->p_dev->conf.ConfigIndex = cfg->index;
+ cfg_mem->p_dev->config_index = cfg->index;
if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
cfg_mem->dflt = *cfg;
- return cfg_mem->conf_check(cfg_mem->p_dev, cfg, &cfg_mem->dflt,
- cfg_mem->p_dev->socket->socket.Vcc,
- cfg_mem->priv_data);
+ /* check for matching Vcc? */
+ if (flags & CONF_AUTO_CHECK_VCC) {
+ if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
+ if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
+ return -ENODEV;
+ } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
+ if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000)
+ return -ENODEV;
+ }
+ }
+
+ /* set Vpp? */
+ if (flags & CONF_AUTO_SET_VPP) {
+ if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
+ p_dev->vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+ else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
+ p_dev->vpp =
+ dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+ }
+
+ /* enable audio? */
+ if ((flags & CONF_AUTO_AUDIO) && (cfg->flags & CISTPL_CFTABLE_AUDIO))
+ p_dev->config_flags |= CONF_ENABLE_SPKR;
+
+
+ /* IO window settings? */
+ if (flags & CONF_AUTO_SET_IO) {
+ cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
+ int i = 0;
+
+ p_dev->resource[0]->start = p_dev->resource[0]->end = 0;
+ p_dev->resource[1]->start = p_dev->resource[1]->end = 0;
+ if (io->nwin == 0)
+ return -ENODEV;
+
+ p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+ p_dev->resource[0]->flags |=
+ pcmcia_io_cfg_data_width(io->flags);
+ if (io->nwin > 1) {
+ /* For multifunction cards, by convention, we
+ * configure the network function with window 0,
+ * and serial with window 1 */
+ i = (io->win[1].len > io->win[0].len);
+ p_dev->resource[1]->flags = p_dev->resource[0]->flags;
+ p_dev->resource[1]->start = io->win[1-i].base;
+ p_dev->resource[1]->end = io->win[1-i].len;
+ }
+ p_dev->resource[0]->start = io->win[i].base;
+ p_dev->resource[0]->end = io->win[i].len;
+ p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
+ }
+
+ /* MEM window settings? */
+ if (flags & CONF_AUTO_SET_IOMEM) {
+ /* so far, we only set one memory window */
+ cistpl_mem_t *mem = (cfg->mem.nwin) ? &cfg->mem : &dflt->mem;
+
+ p_dev->resource[2]->start = p_dev->resource[2]->end = 0;
+ if (mem->nwin == 0)
+ return -ENODEV;
+
+ p_dev->resource[2]->start = mem->win[0].host_addr;
+ p_dev->resource[2]->end = mem->win[0].len;
+ if (p_dev->resource[2]->end < 0x1000)
+ p_dev->resource[2]->end = 0x1000;
+ p_dev->card_addr = mem->win[0].card_addr;
+ }
+
+ dev_dbg(&p_dev->dev,
+ "checking configuration %x: %pr %pr %pr (%d lines)\n",
+ p_dev->config_index, p_dev->resource[0], p_dev->resource[1],
+ p_dev->resource[2], p_dev->io_lines);
+
+ return cfg_mem->conf_check(p_dev, cfg_mem->priv_data);
}
/**
* pcmcia_loop_config() - loop over configuration options
* @p_dev: the struct pcmcia_device which we need to loop for.
* @conf_check: function to call for each configuration option.
- * It gets passed the struct pcmcia_device, the CIS data
- * describing the configuration option, and private data
+ * It gets passed the struct pcmcia_device and private data
* being passed to pcmcia_loop_config()
* @priv_data: private data to be passed to the conf_check function.
*
@@ -175,9 +261,6 @@ static int pcmcia_do_loop_config(tuple_t *tuple, cisparse_t *parse, void *priv)
*/
int pcmcia_loop_config(struct pcmcia_device *p_dev,
int (*conf_check) (struct pcmcia_device *p_dev,
- cistpl_cftable_entry_t *cfg,
- cistpl_cftable_entry_t *dflt,
- unsigned int vcc,
void *priv_data),
void *priv_data)
{
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
index 9ba4dade69a4..0bdda5b3ed55 100644
--- a/drivers/pcmcia/pcmcia_resource.c
+++ b/drivers/pcmcia/pcmcia_resource.c
@@ -6,7 +6,7 @@
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* Copyright (C) 1999 David A. Hinds
- * Copyright (C) 2004-2005 Dominik Brodowski
+ * Copyright (C) 2004-2010 Dominik Brodowski
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -26,7 +26,6 @@
#include <asm/irq.h>
#include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/ds.h>
@@ -56,6 +55,12 @@ struct resource *pcmcia_find_mem_region(u_long base, u_long num, u_long align,
}
+/**
+ * release_io_space() - release IO ports allocated with alloc_io_space()
+ * @s: pcmcia socket
+ * @res: resource to release
+ *
+ */
static void release_io_space(struct pcmcia_socket *s, struct resource *res)
{
resource_size_t num = resource_size(res);
@@ -81,9 +86,14 @@ static void release_io_space(struct pcmcia_socket *s, struct resource *res)
}
}
}
-} /* release_io_space */
+}
+
-/** alloc_io_space
+/**
+ * alloc_io_space() - allocate IO ports for use by a PCMCIA device
+ * @s: pcmcia socket
+ * @res: resource to allocate (begin: begin, end: size)
+ * @lines: number of IO lines decoded by the PCMCIA card
*
* Special stuff for managing IO windows, because they are scarce
*/
@@ -135,7 +145,7 @@ static int alloc_io_space(struct pcmcia_socket *s, struct resource *res,
}
dev_dbg(&s->dev, "alloc_io_space request result %d: %pR\n", ret, res);
return ret;
-} /* alloc_io_space */
+}
/**
@@ -168,14 +178,14 @@ static int pcmcia_access_config(struct pcmcia_device *p_dev,
return -EACCES;
}
- addr = (c->ConfigBase + where) >> 1;
+ addr = (p_dev->config_base + where) >> 1;
ret = accessf(s, 1, addr, 1, val);
mutex_unlock(&s->ops_mutex);
return ret;
-} /* pcmcia_access_config */
+}
/**
@@ -204,11 +214,20 @@ int pcmcia_write_config_byte(struct pcmcia_device *p_dev, off_t where, u8 val)
EXPORT_SYMBOL(pcmcia_write_config_byte);
-int pcmcia_map_mem_page(struct pcmcia_device *p_dev, window_handle_t wh,
+/**
+ * pcmcia_map_mem_page() - modify iomem window to point to a different offset
+ * @p_dev: pcmcia device
+ * @res: iomem resource already enabled by pcmcia_request_window()
+ * @offset: card_offset to map
+ *
+ * pcmcia_map_mem_page() modifies what can be read and written by accessing
+ * an iomem range previously enabled by pcmcia_request_window(), by setting
+ * the card_offset value to @offset.
+ */
+int pcmcia_map_mem_page(struct pcmcia_device *p_dev, struct resource *res,
unsigned int offset)
{
struct pcmcia_socket *s = p_dev->socket;
- struct resource *res = wh;
unsigned int w;
int ret;
@@ -223,98 +242,111 @@ int pcmcia_map_mem_page(struct pcmcia_device *p_dev, window_handle_t wh,
dev_warn(&p_dev->dev, "failed to set_mem_map\n");
mutex_unlock(&s->ops_mutex);
return ret;
-} /* pcmcia_map_mem_page */
+}
EXPORT_SYMBOL(pcmcia_map_mem_page);
-/** pcmcia_modify_configuration
+/**
+ * pcmcia_fixup_iowidth() - reduce io width to 8bit
+ * @p_dev: pcmcia device
*
- * Modify a locked socket configuration
+ * pcmcia_fixup_iowidth() allows a PCMCIA device driver to reduce the
+ * IO width to 8bit after having called pcmcia_enable_device()
+ * previously.
*/
-int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
- modconf_t *mod)
+int pcmcia_fixup_iowidth(struct pcmcia_device *p_dev)
{
- struct pcmcia_socket *s;
- config_t *c;
- int ret;
-
- s = p_dev->socket;
+ struct pcmcia_socket *s = p_dev->socket;
+ pccard_io_map io_off = { 0, 0, 0, 0, 1 };
+ pccard_io_map io_on;
+ int i, ret = 0;
mutex_lock(&s->ops_mutex);
- c = p_dev->function_config;
- if (!(s->state & SOCKET_PRESENT)) {
- dev_dbg(&p_dev->dev, "No card present\n");
- ret = -ENODEV;
- goto unlock;
- }
- if (!(c->state & CONFIG_LOCKED)) {
- dev_dbg(&p_dev->dev, "Configuration isnt't locked\n");
+ dev_dbg(&p_dev->dev, "fixup iowidth to 8bit\n");
+
+ if (!(s->state & SOCKET_PRESENT) ||
+ !(p_dev->function_config->state & CONFIG_LOCKED)) {
+ dev_dbg(&p_dev->dev, "No card? Config not locked?\n");
ret = -EACCES;
goto unlock;
}
- if (mod->Attributes & (CONF_IRQ_CHANGE_VALID | CONF_VCC_CHANGE_VALID)) {
- dev_dbg(&p_dev->dev,
- "changing Vcc or IRQ is not allowed at this time\n");
- ret = -EINVAL;
- goto unlock;
- }
+ io_on.speed = io_speed;
+ for (i = 0; i < MAX_IO_WIN; i++) {
+ if (!s->io[i].res)
+ continue;
+ io_off.map = i;
+ io_on.map = i;
- /* We only allow changing Vpp1 and Vpp2 to the same value */
- if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) &&
- (mod->Attributes & CONF_VPP2_CHANGE_VALID)) {
- if (mod->Vpp1 != mod->Vpp2) {
- dev_dbg(&p_dev->dev,
- "Vpp1 and Vpp2 must be the same\n");
- ret = -EINVAL;
- goto unlock;
- }
- s->socket.Vpp = mod->Vpp1;
- if (s->ops->set_socket(s, &s->socket)) {
- dev_printk(KERN_WARNING, &p_dev->dev,
- "Unable to set VPP\n");
- ret = -EIO;
- goto unlock;
- }
- } else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) ||
- (mod->Attributes & CONF_VPP2_CHANGE_VALID)) {
- dev_dbg(&p_dev->dev,
- "changing Vcc is not allowed at this time\n");
- ret = -EINVAL;
- goto unlock;
+ io_on.flags = MAP_ACTIVE | IO_DATA_PATH_WIDTH_8;
+ io_on.start = s->io[i].res->start;
+ io_on.stop = s->io[i].res->end;
+
+ s->ops->set_io_map(s, &io_off);
+ mdelay(40);
+ s->ops->set_io_map(s, &io_on);
}
+unlock:
+ mutex_unlock(&s->ops_mutex);
+
+ return ret;
+}
+EXPORT_SYMBOL(pcmcia_fixup_iowidth);
+
+
+/**
+ * pcmcia_fixup_vpp() - set Vpp to a new voltage level
+ * @p_dev: pcmcia device
+ * @new_vpp: new Vpp voltage
+ *
+ * pcmcia_fixup_vpp() allows a PCMCIA device driver to set Vpp to
+ * a new voltage level between calls to pcmcia_enable_device()
+ * and pcmcia_disable_device().
+ */
+int pcmcia_fixup_vpp(struct pcmcia_device *p_dev, unsigned char new_vpp)
+{
+ struct pcmcia_socket *s = p_dev->socket;
+ int ret = 0;
- if (mod->Attributes & CONF_IO_CHANGE_WIDTH) {
- pccard_io_map io_off = { 0, 0, 0, 0, 1 };
- pccard_io_map io_on;
- int i;
+ mutex_lock(&s->ops_mutex);
- io_on.speed = io_speed;
- for (i = 0; i < MAX_IO_WIN; i++) {
- if (!s->io[i].res)
- continue;
- io_off.map = i;
- io_on.map = i;
+ dev_dbg(&p_dev->dev, "fixup Vpp to %d\n", new_vpp);
- io_on.flags = MAP_ACTIVE | IO_DATA_PATH_WIDTH_8;
- io_on.start = s->io[i].res->start;
- io_on.stop = s->io[i].res->end;
+ if (!(s->state & SOCKET_PRESENT) ||
+ !(p_dev->function_config->state & CONFIG_LOCKED)) {
+ dev_dbg(&p_dev->dev, "No card? Config not locked?\n");
+ ret = -EACCES;
+ goto unlock;
+ }
- s->ops->set_io_map(s, &io_off);
- mdelay(40);
- s->ops->set_io_map(s, &io_on);
- }
+ s->socket.Vpp = new_vpp;
+ if (s->ops->set_socket(s, &s->socket)) {
+ dev_warn(&p_dev->dev, "Unable to set VPP\n");
+ ret = -EIO;
+ goto unlock;
}
- ret = 0;
+ p_dev->vpp = new_vpp;
+
unlock:
mutex_unlock(&s->ops_mutex);
return ret;
-} /* modify_configuration */
-EXPORT_SYMBOL(pcmcia_modify_configuration);
+}
+EXPORT_SYMBOL(pcmcia_fixup_vpp);
+/**
+ * pcmcia_release_configuration() - physically disable a PCMCIA device
+ * @p_dev: pcmcia device
+ *
+ * pcmcia_release_configuration() is the 1:1 counterpart to
+ * pcmcia_enable_device(): If a PCMCIA device is no longer used by any
+ * driver, the Vpp voltage is set to 0, IRQs will no longer be generated,
+ * and I/O ranges will be disabled. As pcmcia_release_io() and
+ * pcmcia_release_window() still need to be called, device drivers are
+ * expected to call pcmcia_disable_device() instead.
+ */
int pcmcia_release_configuration(struct pcmcia_device *p_dev)
{
pccard_io_map io = { 0, 0, 0, 0, 1 };
@@ -327,7 +359,7 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev)
if (p_dev->_locked) {
p_dev->_locked = 0;
if (--(s->lock_count) == 0) {
- s->socket.flags = SS_OUTPUT_ENA; /* Is this correct? */
+ s->socket.flags = SS_OUTPUT_ENA; /* Is this correct? */
s->socket.Vpp = 0;
s->socket.io_irq = 0;
s->ops->set_socket(s, &s->socket);
@@ -349,16 +381,18 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev)
mutex_unlock(&s->ops_mutex);
return 0;
-} /* pcmcia_release_configuration */
+}
-/** pcmcia_release_io
+/**
+ * pcmcia_release_io() - release I/O allocated by a PCMCIA device
+ * @p_dev: pcmcia device
*
- * Release_io() releases the I/O ranges allocated by a client. This
- * may be invoked some time after a card ejection has already dumped
- * the actual socket configuration, so if the client is "stale", we
- * don't bother checking the port ranges against the current socket
- * values.
+ * pcmcia_release_io() releases the I/O ranges allocated by a PCMCIA
+ * device. This may be invoked some time after a card ejection has
+ * already dumped the actual socket configuration, so if the client is
+ * "stale", we don't bother checking the port ranges against the
+ * current socket values.
*/
static int pcmcia_release_io(struct pcmcia_device *p_dev)
{
@@ -387,6 +421,14 @@ out:
} /* pcmcia_release_io */
+/**
+ * pcmcia_release_window() - release reserved iomem for PCMCIA devices
+ * @p_dev: pcmcia device
+ * @res: iomem resource to release
+ *
+ * pcmcia_release_window() releases &struct resource *res which was
+ * previously reserved by calling pcmcia_request_window().
+ */
int pcmcia_release_window(struct pcmcia_device *p_dev, struct resource *res)
{
struct pcmcia_socket *s = p_dev->socket;
@@ -420,6 +462,8 @@ int pcmcia_release_window(struct pcmcia_device *p_dev, struct resource *res)
kfree(win->res);
win->res = NULL;
}
+ res->start = res->end = 0;
+ res->flags = IORESOURCE_MEM;
p_dev->_win &= ~CLIENT_WIN_REQ(w);
mutex_unlock(&s->ops_mutex);
@@ -428,23 +472,30 @@ int pcmcia_release_window(struct pcmcia_device *p_dev, struct resource *res)
EXPORT_SYMBOL(pcmcia_release_window);
-int pcmcia_request_configuration(struct pcmcia_device *p_dev,
- config_req_t *req)
+/**
+ * pcmcia_enable_device() - set up and activate a PCMCIA device
+ * @p_dev: the associated PCMCIA device
+ *
+ * pcmcia_enable_device() physically enables a PCMCIA device. It parses
+ * the flags passed to in @flags and stored in @p_dev->flags and sets up
+ * the Vpp voltage, enables the speaker line, I/O ports and store proper
+ * values to configuration registers.
+ */
+int pcmcia_enable_device(struct pcmcia_device *p_dev)
{
int i;
- u_int base;
+ unsigned int base;
struct pcmcia_socket *s = p_dev->socket;
config_t *c;
pccard_io_map iomap;
+ unsigned char status = 0;
+ unsigned char ext_status = 0;
+ unsigned char option = 0;
+ unsigned int flags = p_dev->config_flags;
if (!(s->state & SOCKET_PRESENT))
return -ENODEV;
- if (req->IntType & INT_CARDBUS) {
- dev_dbg(&p_dev->dev, "IntType may not be INT_CARDBUS\n");
- return -EINVAL;
- }
-
mutex_lock(&s->ops_mutex);
c = p_dev->function_config;
if (c->state & CONFIG_LOCKED) {
@@ -454,7 +505,7 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
}
/* Do power control. We don't allow changes in Vcc. */
- s->socket.Vpp = req->Vpp;
+ s->socket.Vpp = p_dev->vpp;
if (s->ops->set_socket(s, &s->socket)) {
mutex_unlock(&s->ops_mutex);
dev_printk(KERN_WARNING, &p_dev->dev,
@@ -463,64 +514,74 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
}
/* Pick memory or I/O card, DMA mode, interrupt */
- c->IntType = req->IntType;
- c->Attributes = req->Attributes;
- if (req->IntType & INT_MEMORY_AND_IO)
+ if (p_dev->_io || flags & CONF_ENABLE_IRQ)
+ flags |= CONF_ENABLE_IOCARD;
+ if (flags & CONF_ENABLE_IOCARD)
s->socket.flags |= SS_IOCARD;
- if (req->IntType & INT_ZOOMED_VIDEO)
- s->socket.flags |= SS_ZVCARD | SS_IOCARD;
- if (req->Attributes & CONF_ENABLE_DMA)
- s->socket.flags |= SS_DMA_MODE;
- if (req->Attributes & CONF_ENABLE_SPKR)
+ if (flags & CONF_ENABLE_SPKR) {
s->socket.flags |= SS_SPKR_ENA;
- if (req->Attributes & CONF_ENABLE_IRQ)
+ status = CCSR_AUDIO_ENA;
+ if (!(p_dev->config_regs & PRESENT_STATUS))
+ dev_warn(&p_dev->dev, "speaker requested, but "
+ "PRESENT_STATUS not set!\n");
+ }
+ if (flags & CONF_ENABLE_IRQ)
s->socket.io_irq = s->pcmcia_irq;
else
s->socket.io_irq = 0;
+ if (flags & CONF_ENABLE_ESR) {
+ p_dev->config_regs |= PRESENT_EXT_STATUS;
+ ext_status = ESR_REQ_ATTN_ENA;
+ }
s->ops->set_socket(s, &s->socket);
s->lock_count++;
+ dev_dbg(&p_dev->dev,
+ "enable_device: V %d, flags %x, base %x, regs %x, idx %x\n",
+ p_dev->vpp, flags, p_dev->config_base, p_dev->config_regs,
+ p_dev->config_index);
+
/* Set up CIS configuration registers */
- base = c->ConfigBase = req->ConfigBase;
- c->CardValues = req->Present;
- if (req->Present & PRESENT_COPY) {
- c->Copy = req->Copy;
- pcmcia_write_cis_mem(s, 1, (base + CISREG_SCR)>>1, 1, &c->Copy);
- }
- if (req->Present & PRESENT_OPTION) {
+ base = p_dev->config_base;
+ if (p_dev->config_regs & PRESENT_COPY) {
+ u16 tmp = 0;
+ dev_dbg(&p_dev->dev, "clearing CISREG_SCR\n");
+ pcmcia_write_cis_mem(s, 1, (base + CISREG_SCR)>>1, 1, &tmp);
+ }
+ if (p_dev->config_regs & PRESENT_PIN_REPLACE) {
+ u16 tmp = 0;
+ dev_dbg(&p_dev->dev, "clearing CISREG_PRR\n");
+ pcmcia_write_cis_mem(s, 1, (base + CISREG_PRR)>>1, 1, &tmp);
+ }
+ if (p_dev->config_regs & PRESENT_OPTION) {
if (s->functions == 1) {
- c->Option = req->ConfigIndex & COR_CONFIG_MASK;
+ option = p_dev->config_index & COR_CONFIG_MASK;
} else {
- c->Option = req->ConfigIndex & COR_MFC_CONFIG_MASK;
- c->Option |= COR_FUNC_ENA|COR_IREQ_ENA;
- if (req->Present & PRESENT_IOBASE_0)
- c->Option |= COR_ADDR_DECODE;
+ option = p_dev->config_index & COR_MFC_CONFIG_MASK;
+ option |= COR_FUNC_ENA|COR_IREQ_ENA;
+ if (p_dev->config_regs & PRESENT_IOBASE_0)
+ option |= COR_ADDR_DECODE;
}
- if ((req->Attributes & CONF_ENABLE_IRQ) &&
- !(req->Attributes & CONF_ENABLE_PULSE_IRQ))
- c->Option |= COR_LEVEL_REQ;
- pcmcia_write_cis_mem(s, 1, (base + CISREG_COR)>>1, 1, &c->Option);
+ if ((flags & CONF_ENABLE_IRQ) &&
+ !(flags & CONF_ENABLE_PULSE_IRQ))
+ option |= COR_LEVEL_REQ;
+ pcmcia_write_cis_mem(s, 1, (base + CISREG_COR)>>1, 1, &option);
mdelay(40);
}
- if (req->Present & PRESENT_STATUS) {
- c->Status = req->Status;
- pcmcia_write_cis_mem(s, 1, (base + CISREG_CCSR)>>1, 1, &c->Status);
- }
- if (req->Present & PRESENT_PIN_REPLACE) {
- c->Pin = req->Pin;
- pcmcia_write_cis_mem(s, 1, (base + CISREG_PRR)>>1, 1, &c->Pin);
- }
- if (req->Present & PRESENT_EXT_STATUS) {
- c->ExtStatus = req->ExtStatus;
- pcmcia_write_cis_mem(s, 1, (base + CISREG_ESR)>>1, 1, &c->ExtStatus);
- }
- if (req->Present & PRESENT_IOBASE_0) {
+ if (p_dev->config_regs & PRESENT_STATUS)
+ pcmcia_write_cis_mem(s, 1, (base + CISREG_CCSR)>>1, 1, &status);
+
+ if (p_dev->config_regs & PRESENT_EXT_STATUS)
+ pcmcia_write_cis_mem(s, 1, (base + CISREG_ESR)>>1, 1,
+ &ext_status);
+
+ if (p_dev->config_regs & PRESENT_IOBASE_0) {
u8 b = c->io[0].start & 0xff;
pcmcia_write_cis_mem(s, 1, (base + CISREG_IOBASE_0)>>1, 1, &b);
b = (c->io[0].start >> 8) & 0xff;
pcmcia_write_cis_mem(s, 1, (base + CISREG_IOBASE_1)>>1, 1, &b);
}
- if (req->Present & PRESENT_IOSIZE) {
+ if (p_dev->config_regs & PRESENT_IOSIZE) {
u8 b = resource_size(&c->io[0]) + resource_size(&c->io[1]) - 1;
pcmcia_write_cis_mem(s, 1, (base + CISREG_IOSIZE)>>1, 1, &b);
}
@@ -551,14 +612,15 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
p_dev->_locked = 1;
mutex_unlock(&s->ops_mutex);
return 0;
-} /* pcmcia_request_configuration */
-EXPORT_SYMBOL(pcmcia_request_configuration);
+} /* pcmcia_enable_device */
+EXPORT_SYMBOL(pcmcia_enable_device);
/**
* pcmcia_request_io() - attempt to reserve port ranges for PCMCIA devices
+ * @p_dev: the associated PCMCIA device
*
- * pcmcia_request_io() attepts to reserve the IO port ranges specified in
+ * pcmcia_request_io() attempts to reserve the IO port ranges specified in
* &struct pcmcia_device @p_dev->resource[0] and @p_dev->resource[1]. The
* "start" value is the requested start of the IO port resource; "end"
* reflects the number of ports requested. The number of IO lines requested
@@ -622,11 +684,13 @@ EXPORT_SYMBOL(pcmcia_request_io);
/**
* pcmcia_request_irq() - attempt to request a IRQ for a PCMCIA device
+ * @p_dev: the associated PCMCIA device
+ * @handler: IRQ handler to register
*
- * pcmcia_request_irq() is a wrapper around request_irq which will allow
+ * pcmcia_request_irq() is a wrapper around request_irq() which allows
* the PCMCIA core to clean up the registration in pcmcia_disable_device().
* Drivers are free to use request_irq() directly, but then they need to
- * call free_irq themselfves, too. Also, only IRQF_SHARED capable IRQ
+ * call free_irq() themselfves, too. Also, only %IRQF_SHARED capable IRQ
* handlers are allowed.
*/
int __must_check pcmcia_request_irq(struct pcmcia_device *p_dev,
@@ -649,12 +713,14 @@ EXPORT_SYMBOL(pcmcia_request_irq);
/**
* pcmcia_request_exclusive_irq() - attempt to request an exclusive IRQ first
+ * @p_dev: the associated PCMCIA device
+ * @handler: IRQ handler to register
*
- * pcmcia_request_exclusive_irq() is a wrapper around request_irq which
+ * pcmcia_request_exclusive_irq() is a wrapper around request_irq() which
* attempts first to request an exclusive IRQ. If it fails, it also accepts
* a shared IRQ, but prints out a warning. PCMCIA drivers should allow for
* IRQ sharing and either use request_irq directly (then they need to call
- * free_irq themselves, too), or the pcmcia_request_irq() function.
+ * free_irq() themselves, too), or the pcmcia_request_irq() function.
*/
int __must_check
__pcmcia_request_exclusive_irq(struct pcmcia_device *p_dev,
@@ -795,38 +861,47 @@ int pcmcia_setup_irq(struct pcmcia_device *p_dev)
}
-/** pcmcia_request_window
+/**
+ * pcmcia_request_window() - attempt to reserve iomem for PCMCIA devices
+ * @p_dev: the associated PCMCIA device
+ * @res: &struct resource pointing to p_dev->resource[2..5]
+ * @speed: access speed
*
- * Request_window() establishes a mapping between card memory space
- * and system memory space.
+ * pcmcia_request_window() attepts to reserve an iomem ranges specified in
+ * &struct resource @res pointing to one of the entries in
+ * &struct pcmcia_device @p_dev->resource[2..5]. The "start" value is the
+ * requested start of the IO mem resource; "end" reflects the size
+ * requested.
*/
-int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_handle_t *wh)
+int pcmcia_request_window(struct pcmcia_device *p_dev, struct resource *res,
+ unsigned int speed)
{
struct pcmcia_socket *s = p_dev->socket;
pccard_mem_map *win;
u_long align;
- struct resource *res;
int w;
+ dev_dbg(&p_dev->dev, "request_window %pR %d\n", res, speed);
+
if (!(s->state & SOCKET_PRESENT)) {
dev_dbg(&p_dev->dev, "No card present\n");
return -ENODEV;
}
/* Window size defaults to smallest available */
- if (req->Size == 0)
- req->Size = s->map_size;
- align = (s->features & SS_CAP_MEM_ALIGN) ? req->Size : s->map_size;
- if (req->Size & (s->map_size-1)) {
+ if (res->end == 0)
+ res->end = s->map_size;
+ align = (s->features & SS_CAP_MEM_ALIGN) ? res->end : s->map_size;
+ if (res->end & (s->map_size-1)) {
dev_dbg(&p_dev->dev, "invalid map size\n");
return -EINVAL;
}
- if ((req->Base && (s->features & SS_CAP_STATIC_MAP)) ||
- (req->Base & (align-1))) {
+ if ((res->start && (s->features & SS_CAP_STATIC_MAP)) ||
+ (res->start & (align-1))) {
dev_dbg(&p_dev->dev, "invalid base address\n");
return -EINVAL;
}
- if (req->Base)
+ if (res->start)
align = 0;
/* Allocate system memory window */
@@ -843,7 +918,7 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha
win = &s->win[w];
if (!(s->features & SS_CAP_STATIC_MAP)) {
- win->res = pcmcia_find_mem_region(req->Base, req->Size, align,
+ win->res = pcmcia_find_mem_region(res->start, res->end, align,
0, s);
if (!win->res) {
dev_dbg(&p_dev->dev, "allocating mem region failed\n");
@@ -855,8 +930,8 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha
/* Configure the socket controller */
win->map = w+1;
- win->flags = req->Attributes;
- win->speed = req->AccessSpeed;
+ win->flags = res->flags & WIN_FLAGS_MAP;
+ win->speed = speed;
win->card_start = 0;
if (s->ops->set_mem_map(s, win) != 0) {
@@ -868,17 +943,14 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha
/* Return window handle */
if (s->features & SS_CAP_STATIC_MAP)
- req->Base = win->static_start;
+ res->start = win->static_start;
else
- req->Base = win->res->start;
+ res->start = win->res->start;
/* convert to new-style resources */
- res = p_dev->resource[w + MAX_IO_WIN];
- res->start = req->Base;
- res->end = req->Base + req->Size - 1;
- res->flags &= ~IORESOURCE_BITS;
- res->flags |= (req->Attributes & WIN_FLAGS_MAP) | (win->map << 2);
- res->flags |= IORESOURCE_MEM;
+ res->end += res->start - 1;
+ res->flags &= ~WIN_FLAGS_REQ;
+ res->flags |= (win->map << 2) | IORESOURCE_MEM;
res->parent = win->res;
if (win->res)
request_resource(&iomem_resource, res);
@@ -886,15 +958,30 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha
dev_dbg(&p_dev->dev, "request_window results in %pR\n", res);
mutex_unlock(&s->ops_mutex);
- *wh = res;
return 0;
} /* pcmcia_request_window */
EXPORT_SYMBOL(pcmcia_request_window);
+
+/**
+ * pcmcia_disable_device() - disable and clean up a PCMCIA device
+ * @p_dev: the associated PCMCIA device
+ *
+ * pcmcia_disable_device() is the driver-callable counterpart to
+ * pcmcia_enable_device(): If a PCMCIA device is no longer used,
+ * drivers are expected to clean up and disable the device by calling
+ * this function. Any I/O ranges (iomem and ioports) will be released,
+ * the Vpp voltage will be set to 0, and IRQs will no longer be
+ * generated -- at least if there is no other card function (of
+ * multifunction devices) being used.
+ */
void pcmcia_disable_device(struct pcmcia_device *p_dev)
{
int i;
+
+ dev_dbg(&p_dev->dev, "disabling device\n");
+
for (i = 0; i < MAX_WIN; i++) {
struct resource *res = p_dev->resource[MAX_IO_WIN + i];
if (res->flags & WIN_FLAGS_REQ)
diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c
index deef6656ab7b..8cbfa067171f 100644
--- a/drivers/pcmcia/pd6729.c
+++ b/drivers/pcmcia/pd6729.c
@@ -18,7 +18,6 @@
#include <linux/io.h>
#include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
#include <asm/system.h>
diff --git a/drivers/pcmcia/rsrc_iodyn.c b/drivers/pcmcia/rsrc_iodyn.c
index 8510c35d2952..523eb691c30b 100644
--- a/drivers/pcmcia/rsrc_iodyn.c
+++ b/drivers/pcmcia/rsrc_iodyn.c
@@ -17,7 +17,6 @@
#include <linux/kernel.h>
#include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include "cs_internal.h"
diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c
index 4e80421fd908..aa628ed0e9f4 100644
--- a/drivers/pcmcia/rsrc_mgr.c
+++ b/drivers/pcmcia/rsrc_mgr.c
@@ -17,7 +17,6 @@
#include <linux/kernel.h>
#include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include "cs_internal.h"
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
index 96f348b35fde..b187555d4388 100644
--- a/drivers/pcmcia/rsrc_nonstatic.c
+++ b/drivers/pcmcia/rsrc_nonstatic.c
@@ -29,7 +29,6 @@
#include <asm/irq.h>
#include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include "cs_internal.h"
diff --git a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c
index e09851480295..945857f8c284 100644
--- a/drivers/pcmcia/sa1100_generic.c
+++ b/drivers/pcmcia/sa1100_generic.c
@@ -35,7 +35,6 @@
#include <linux/slab.h>
#include <linux/platform_device.h>
-#include <pcmcia/cs.h>
#include <pcmcia/ss.h>
#include <asm/hardware/scoop.h>
diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c
index 6f1a86b43c60..689e3c02edb8 100644
--- a/drivers/pcmcia/soc_common.c
+++ b/drivers/pcmcia/soc_common.c
@@ -627,8 +627,6 @@ void soc_pcmcia_remove_one(struct soc_pcmcia_socket *skt)
pcmcia_unregister_socket(&skt->socket);
- flush_scheduled_work();
-
skt->ops->hw_shutdown(skt);
soc_common_pcmcia_config_skt(skt, &dead_socket);
@@ -720,8 +718,6 @@ int soc_pcmcia_add_one(struct soc_pcmcia_socket *skt)
pcmcia_unregister_socket(&skt->socket);
out_err_7:
- flush_scheduled_work();
-
skt->ops->hw_shutdown(skt);
out_err_6:
list_del(&skt->node);
diff --git a/drivers/pcmcia/soc_common.h b/drivers/pcmcia/soc_common.h
index 3fba3a679128..bbcd5385a221 100644
--- a/drivers/pcmcia/soc_common.h
+++ b/drivers/pcmcia/soc_common.h
@@ -11,7 +11,6 @@
/* include the world */
#include <linux/cpufreq.h>
-#include <pcmcia/cs.h>
#include <pcmcia/ss.h>
#include <pcmcia/cistpl.h>
diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c
index cb0d3ace18bd..71aeed93037c 100644
--- a/drivers/pcmcia/socket_sysfs.c
+++ b/drivers/pcmcia/socket_sysfs.c
@@ -27,7 +27,6 @@
#include <asm/irq.h>
#include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/ds.h>
diff --git a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c
index be0d841c7ebd..310160bffe38 100644
--- a/drivers/pcmcia/tcic.c
+++ b/drivers/pcmcia/tcic.c
@@ -49,7 +49,6 @@
#include <asm/io.h>
#include <asm/system.h>
-#include <pcmcia/cs.h>
#include <pcmcia/ss.h>
#include "tcic.h"
diff --git a/drivers/pcmcia/vrc4173_cardu.c b/drivers/pcmcia/vrc4173_cardu.c
index 9b3c15827e5c..c6d36b3a6ce8 100644
--- a/drivers/pcmcia/vrc4173_cardu.c
+++ b/drivers/pcmcia/vrc4173_cardu.c
@@ -461,7 +461,7 @@ static int __devinit vrc4173_cardu_probe(struct pci_dev *dev,
{
vrc4173_socket_t *socket;
unsigned long start, len, flags;
- int slot, err;
+ int slot, err, ret;
slot = vrc4173_cardu_slots++;
socket = &cardu_sockets[slot];
@@ -474,43 +474,63 @@ static int __devinit vrc4173_cardu_probe(struct pci_dev *dev,
return err;
start = pci_resource_start(dev, 0);
- if (start == 0)
- return -ENODEV;
+ if (start == 0) {
+ ret = -ENODEV;
+ goto disable;
+ }
len = pci_resource_len(dev, 0);
- if (len == 0)
- return -ENODEV;
+ if (len == 0) {
+ ret = -ENODEV;
+ goto disable;
+ }
- if (((flags = pci_resource_flags(dev, 0)) & IORESOURCE_MEM) == 0)
- return -EBUSY;
+ flags = pci_resource_flags(dev, 0);
+ if ((flags & IORESOURCE_MEM) == 0) {
+ ret = -EBUSY;
+ goto disable;
+ }
- if ((err = pci_request_regions(dev, socket->name)) < 0)
- return err;
+ err = pci_request_regions(dev, socket->name);
+ if (err < 0) {
+ ret = err;
+ goto disable;
+ }
socket->base = ioremap(start, len);
- if (socket->base == NULL)
- return -ENODEV;
+ if (socket->base == NULL) {
+ ret = -ENODEV;
+ goto release;
+ }
socket->dev = dev;
socket->pcmcia_socket = pcmcia_register_socket(slot, &cardu_operations, 1);
if (socket->pcmcia_socket == NULL) {
- iounmap(socket->base);
- socket->base = NULL;
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto unmap;
}
if (request_irq(dev->irq, cardu_interrupt, IRQF_SHARED, socket->name, socket) < 0) {
- pcmcia_unregister_socket(socket->pcmcia_socket);
- socket->pcmcia_socket = NULL;
- iounmap(socket->base);
- socket->base = NULL;
- return -EBUSY;
+ ret = -EBUSY;
+ goto unregister;
}
printk(KERN_INFO "%s at %#08lx, IRQ %d\n", socket->name, start, dev->irq);
return 0;
+
+unregister:
+ pcmcia_unregister_socket(socket->pcmcia_socket);
+ socket->pcmcia_socket = NULL;
+unmap:
+ iounmap(socket->base);
+ socket->base = NULL;
+release:
+ pci_release_regions(dev);
+disable:
+ pci_disable_device(dev);
+ return ret;
}
static int __devinit vrc4173_cardu_setup(char *options)
diff --git a/drivers/pcmcia/xxs1500_ss.c b/drivers/pcmcia/xxs1500_ss.c
index fa88c360c37a..3b67a1b6a197 100644
--- a/drivers/pcmcia/xxs1500_ss.c
+++ b/drivers/pcmcia/xxs1500_ss.c
@@ -17,7 +17,6 @@
#include <linux/slab.h>
#include <linux/spinlock.h>
-#include <pcmcia/cs.h>
#include <pcmcia/ss.h>
#include <pcmcia/cistpl.h>
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
index 414d9a6f9a32..408dbaa080a1 100644
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -20,7 +20,6 @@
#include <linux/slab.h>
#include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
#include "yenta_socket.h"
#include "i82365.h"
diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c
index 9024480a8228..c44a5e8b8b82 100644
--- a/drivers/platform/x86/intel_ips.c
+++ b/drivers/platform/x86/intel_ips.c
@@ -51,7 +51,6 @@
* TODO:
* - handle CPU hotplug
* - provide turbo enable/disable api
- * - make sure we can write turbo enable/disable reg based on MISC_EN
*
* Related documents:
* - CDI 403777, 403778 - Auburndale EDS vol 1 & 2
@@ -230,7 +229,7 @@
#define THM_TC2 0xac
#define THM_DTV 0xb0
#define THM_ITV 0xd8
-#define ITV_ME_SEQNO_MASK 0x000f0000 /* ME should update every ~200ms */
+#define ITV_ME_SEQNO_MASK 0x00ff0000 /* ME should update every ~200ms */
#define ITV_ME_SEQNO_SHIFT (16)
#define ITV_MCH_TEMP_MASK 0x0000ff00
#define ITV_MCH_TEMP_SHIFT (8)
@@ -325,6 +324,7 @@ struct ips_driver {
bool gpu_preferred;
bool poll_turbo_status;
bool second_cpu;
+ bool turbo_toggle_allowed;
struct ips_mcp_limits *limits;
/* Optional MCH interfaces for if i915 is in use */
@@ -415,7 +415,7 @@ static void ips_cpu_lower(struct ips_driver *ips)
new_limit = cur_limit - 8; /* 1W decrease */
/* Clamp to SKU TDP limit */
- if (((new_limit * 10) / 8) < (ips->orig_turbo_limit & TURBO_TDP_MASK))
+ if (new_limit < (ips->orig_turbo_limit & TURBO_TDP_MASK))
new_limit = ips->orig_turbo_limit & TURBO_TDP_MASK;
thm_writew(THM_MPCPC, (new_limit * 10) / 8);
@@ -461,7 +461,8 @@ static void ips_enable_cpu_turbo(struct ips_driver *ips)
if (ips->__cpu_turbo_on)
return;
- on_each_cpu(do_enable_cpu_turbo, ips, 1);
+ if (ips->turbo_toggle_allowed)
+ on_each_cpu(do_enable_cpu_turbo, ips, 1);
ips->__cpu_turbo_on = true;
}
@@ -498,7 +499,8 @@ static void ips_disable_cpu_turbo(struct ips_driver *ips)
if (!ips->__cpu_turbo_on)
return;
- on_each_cpu(do_disable_cpu_turbo, ips, 1);
+ if (ips->turbo_toggle_allowed)
+ on_each_cpu(do_disable_cpu_turbo, ips, 1);
ips->__cpu_turbo_on = false;
}
@@ -598,17 +600,29 @@ static bool mcp_exceeded(struct ips_driver *ips)
{
unsigned long flags;
bool ret = false;
+ u32 temp_limit;
+ u32 avg_power;
+ const char *msg = "MCP limit exceeded: ";
spin_lock_irqsave(&ips->turbo_status_lock, flags);
- if (ips->mcp_avg_temp > (ips->mcp_temp_limit * 100))
- ret = true;
- if (ips->cpu_avg_power + ips->mch_avg_power > ips->mcp_power_limit)
+
+ temp_limit = ips->mcp_temp_limit * 100;
+ if (ips->mcp_avg_temp > temp_limit) {
+ dev_info(&ips->dev->dev,
+ "%sAvg temp %u, limit %u\n", msg, ips->mcp_avg_temp,
+ temp_limit);
ret = true;
- spin_unlock_irqrestore(&ips->turbo_status_lock, flags);
+ }
- if (ret)
+ avg_power = ips->cpu_avg_power + ips->mch_avg_power;
+ if (avg_power > ips->mcp_power_limit) {
dev_info(&ips->dev->dev,
- "MCP power or thermal limit exceeded\n");
+ "%sAvg power %u, limit %u\n", msg, avg_power,
+ ips->mcp_power_limit);
+ ret = true;
+ }
+
+ spin_unlock_irqrestore(&ips->turbo_status_lock, flags);
return ret;
}
@@ -663,6 +677,27 @@ static bool mch_exceeded(struct ips_driver *ips)
}
/**
+ * verify_limits - verify BIOS provided limits
+ * @ips: IPS structure
+ *
+ * BIOS can optionally provide non-default limits for power and temp. Check
+ * them here and use the defaults if the BIOS values are not provided or
+ * are otherwise unusable.
+ */
+static void verify_limits(struct ips_driver *ips)
+{
+ if (ips->mcp_power_limit < ips->limits->mcp_power_limit ||
+ ips->mcp_power_limit > 35000)
+ ips->mcp_power_limit = ips->limits->mcp_power_limit;
+
+ if (ips->mcp_temp_limit < ips->limits->core_temp_limit ||
+ ips->mcp_temp_limit < ips->limits->mch_temp_limit ||
+ ips->mcp_temp_limit > 150)
+ ips->mcp_temp_limit = min(ips->limits->core_temp_limit,
+ ips->limits->mch_temp_limit);
+}
+
+/**
* update_turbo_limits - get various limits & settings from regs
* @ips: IPS driver struct
*
@@ -680,12 +715,21 @@ static void update_turbo_limits(struct ips_driver *ips)
u32 hts = thm_readl(THM_HTS);
ips->cpu_turbo_enabled = !(hts & HTS_PCTD_DIS);
- ips->gpu_turbo_enabled = !(hts & HTS_GTD_DIS);
+ /*
+ * Disable turbo for now, until we can figure out why the power figures
+ * are wrong
+ */
+ ips->cpu_turbo_enabled = false;
+
+ if (ips->gpu_busy)
+ ips->gpu_turbo_enabled = !(hts & HTS_GTD_DIS);
+
ips->core_power_limit = thm_readw(THM_MPCPC);
ips->mch_power_limit = thm_readw(THM_MMGPC);
ips->mcp_temp_limit = thm_readw(THM_PTL);
ips->mcp_power_limit = thm_readw(THM_MPPC);
+ verify_limits(ips);
/* Ignore BIOS CPU vs GPU pref */
}
@@ -858,7 +902,7 @@ static u32 get_cpu_power(struct ips_driver *ips, u32 *last, int period)
ret = (ret * 1000) / 65535;
*last = val;
- return ret;
+ return 0;
}
static const u16 temp_decay_factor = 2;
@@ -940,7 +984,6 @@ static int ips_monitor(void *data)
kfree(mch_samples);
kfree(cpu_samples);
kfree(mchp_samples);
- kthread_stop(ips->adjust);
return -ENOMEM;
}
@@ -948,7 +991,7 @@ static int ips_monitor(void *data)
ITV_ME_SEQNO_SHIFT;
seqno_timestamp = get_jiffies_64();
- old_cpu_power = thm_readl(THM_CEC) / 65535;
+ old_cpu_power = thm_readl(THM_CEC);
schedule_timeout_interruptible(msecs_to_jiffies(IPS_SAMPLE_PERIOD));
/* Collect an initial average */
@@ -1150,11 +1193,18 @@ static irqreturn_t ips_irq_handler(int irq, void *arg)
STS_GPL_SHIFT;
/* ignore EC CPU vs GPU pref */
ips->cpu_turbo_enabled = !(sts & STS_PCTD_DIS);
- ips->gpu_turbo_enabled = !(sts & STS_GTD_DIS);
+ /*
+ * Disable turbo for now, until we can figure
+ * out why the power figures are wrong
+ */
+ ips->cpu_turbo_enabled = false;
+ if (ips->gpu_busy)
+ ips->gpu_turbo_enabled = !(sts & STS_GTD_DIS);
ips->mcp_temp_limit = (sts & STS_PTL_MASK) >>
STS_PTL_SHIFT;
ips->mcp_power_limit = (tc1 & STS_PPL_MASK) >>
STS_PPL_SHIFT;
+ verify_limits(ips);
spin_unlock(&ips->turbo_status_lock);
thm_writeb(THM_SEC, SEC_ACK);
@@ -1333,8 +1383,10 @@ static struct ips_mcp_limits *ips_detect_cpu(struct ips_driver *ips)
* turbo manually or we'll get an illegal MSR access, even though
* turbo will still be available.
*/
- if (!(misc_en & IA32_MISC_TURBO_EN))
- ; /* add turbo MSR write allowed flag if necessary */
+ if (misc_en & IA32_MISC_TURBO_EN)
+ ips->turbo_toggle_allowed = true;
+ else
+ ips->turbo_toggle_allowed = false;
if (strstr(boot_cpu_data.x86_model_id, "CPU M"))
limits = &ips_sv_limits;
@@ -1351,9 +1403,10 @@ static struct ips_mcp_limits *ips_detect_cpu(struct ips_driver *ips)
tdp = turbo_power & TURBO_TDP_MASK;
/* Sanity check TDP against CPU */
- if (limits->mcp_power_limit != (tdp / 8) * 1000) {
- dev_warn(&ips->dev->dev, "Warning: CPU TDP doesn't match expected value (found %d, expected %d)\n",
- tdp / 8, limits->mcp_power_limit / 1000);
+ if (limits->core_power_limit != (tdp / 8) * 1000) {
+ dev_info(&ips->dev->dev, "CPU TDP doesn't match expected value (found %d, expected %d)\n",
+ tdp / 8, limits->core_power_limit / 1000);
+ limits->core_power_limit = (tdp / 8) * 1000;
}
out:
@@ -1390,7 +1443,7 @@ static bool ips_get_i915_syms(struct ips_driver *ips)
return true;
out_put_busy:
- symbol_put(i915_gpu_turbo_disable);
+ symbol_put(i915_gpu_busy);
out_put_lower:
symbol_put(i915_gpu_lower);
out_put_raise:
@@ -1532,22 +1585,27 @@ static int ips_probe(struct pci_dev *dev, const struct pci_device_id *id)
/* Save turbo limits & ratios */
rdmsrl(TURBO_POWER_CURRENT_LIMIT, ips->orig_turbo_limit);
- ips_enable_cpu_turbo(ips);
- ips->cpu_turbo_enabled = true;
+ ips_disable_cpu_turbo(ips);
+ ips->cpu_turbo_enabled = false;
- /* Set up the work queue and monitor/adjust threads */
- ips->monitor = kthread_run(ips_monitor, ips, "ips-monitor");
- if (IS_ERR(ips->monitor)) {
+ /* Create thermal adjust thread */
+ ips->adjust = kthread_create(ips_adjust, ips, "ips-adjust");
+ if (IS_ERR(ips->adjust)) {
dev_err(&dev->dev,
- "failed to create thermal monitor thread, aborting\n");
+ "failed to create thermal adjust thread, aborting\n");
ret = -ENOMEM;
goto error_free_irq;
+
}
- ips->adjust = kthread_create(ips_adjust, ips, "ips-adjust");
- if (IS_ERR(ips->adjust)) {
+ /*
+ * Set up the work queue and monitor thread. The monitor thread
+ * will wake up ips_adjust thread.
+ */
+ ips->monitor = kthread_run(ips_monitor, ips, "ips-monitor");
+ if (IS_ERR(ips->monitor)) {
dev_err(&dev->dev,
- "failed to create thermal adjust thread, aborting\n");
+ "failed to create thermal monitor thread, aborting\n");
ret = -ENOMEM;
goto error_thread_cleanup;
}
@@ -1566,7 +1624,7 @@ static int ips_probe(struct pci_dev *dev, const struct pci_device_id *id)
return ret;
error_thread_cleanup:
- kthread_stop(ips->monitor);
+ kthread_stop(ips->adjust);
error_free_irq:
free_irq(ips->dev->irq, ips);
error_unmap:
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c
index e3154ff7a39f..f200677851b8 100644
--- a/drivers/platform/x86/sony-laptop.c
+++ b/drivers/platform/x86/sony-laptop.c
@@ -2360,6 +2360,7 @@ static const struct file_operations sonypi_misc_fops = {
.release = sonypi_misc_release,
.fasync = sonypi_misc_fasync,
.unlocked_ioctl = sonypi_misc_ioctl,
+ .llseek = noop_llseek,
};
static struct miscdevice sonypi_misc_device = {
diff --git a/drivers/pnp/isapnp/proc.c b/drivers/pnp/isapnp/proc.c
index 3f94edab25fa..e73ebefdf3e0 100644
--- a/drivers/pnp/isapnp/proc.c
+++ b/drivers/pnp/isapnp/proc.c
@@ -31,8 +31,9 @@ static struct proc_dir_entry *isapnp_proc_bus_dir = NULL;
static loff_t isapnp_proc_bus_lseek(struct file *file, loff_t off, int whence)
{
loff_t new = -1;
+ struct inode *inode = file->f_path.dentry->d_inode;
- lock_kernel();
+ mutex_lock(&inode->i_mutex);
switch (whence) {
case 0:
new = off;
@@ -44,12 +45,12 @@ static loff_t isapnp_proc_bus_lseek(struct file *file, loff_t off, int whence)
new = 256 + off;
break;
}
- if (new < 0 || new > 256) {
- unlock_kernel();
- return -EINVAL;
- }
- unlock_kernel();
- return (file->f_pos = new);
+ if (new < 0 || new > 256)
+ new = -EINVAL;
+ else
+ file->f_pos = new;
+ mutex_unlock(&inode->i_mutex);
+ return new;
}
static ssize_t isapnp_proc_bus_read(struct file *file, char __user * buf,
diff --git a/drivers/regulator/ad5398.c b/drivers/regulator/ad5398.c
index df1fb53c09d2..a4be41614eeb 100644
--- a/drivers/regulator/ad5398.c
+++ b/drivers/regulator/ad5398.c
@@ -256,7 +256,6 @@ static int __devexit ad5398_remove(struct i2c_client *client)
regulator_unregister(chip->rdev);
kfree(chip);
- i2c_set_clientdata(client, NULL);
return 0;
}
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 422a709d271d..cc8b337b9119 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -700,7 +700,7 @@ static void print_constraints(struct regulator_dev *rdev)
constraints->min_uA != constraints->max_uA) {
ret = _regulator_get_current_limit(rdev);
if (ret > 0)
- count += sprintf(buf + count, "at %d uA ", ret / 1000);
+ count += sprintf(buf + count, "at %d mA ", ret / 1000);
}
if (constraints->valid_modes_mask & REGULATOR_MODE_FAST)
@@ -2302,8 +2302,10 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
dev_set_name(&rdev->dev, "regulator.%d",
atomic_inc_return(&regulator_no) - 1);
ret = device_register(&rdev->dev);
- if (ret != 0)
+ if (ret != 0) {
+ put_device(&rdev->dev);
goto clean;
+ }
dev_set_drvdata(&rdev->dev, rdev);
diff --git a/drivers/regulator/isl6271a-regulator.c b/drivers/regulator/isl6271a-regulator.c
index d61ecb885a8c..b8cc6389a541 100644
--- a/drivers/regulator/isl6271a-regulator.c
+++ b/drivers/regulator/isl6271a-regulator.c
@@ -191,8 +191,6 @@ static int __devexit isl6271a_remove(struct i2c_client *i2c)
struct isl_pmic *pmic = i2c_get_clientdata(i2c);
int i;
- i2c_set_clientdata(i2c, NULL);
-
for (i = 0; i < 3; i++)
regulator_unregister(pmic->rdev[i]);
diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c
index 4520ace3f7e7..6b60a9c0366b 100644
--- a/drivers/regulator/max8649.c
+++ b/drivers/regulator/max8649.c
@@ -330,7 +330,7 @@ static int __devinit max8649_regulator_probe(struct i2c_client *client,
/* set external clock frequency */
info->extclk_freq = pdata->extclk_freq;
max8649_set_bits(info->i2c, MAX8649_SYNC, MAX8649_EXT_MASK,
- info->extclk_freq);
+ info->extclk_freq << 6);
}
if (pdata->ramp_timing) {
diff --git a/drivers/rtc/rtc-ds3232.c b/drivers/rtc/rtc-ds3232.c
index 9daed8db83d3..9de8516e3531 100644
--- a/drivers/rtc/rtc-ds3232.c
+++ b/drivers/rtc/rtc-ds3232.c
@@ -268,7 +268,6 @@ out_irq:
free_irq(client->irq, client);
out_free:
- i2c_set_clientdata(client, NULL);
kfree(ds3232);
return ret;
}
@@ -287,7 +286,6 @@ static int __devexit ds3232_remove(struct i2c_client *client)
}
rtc_device_unregister(ds3232->rtc);
- i2c_set_clientdata(client, NULL);
kfree(ds3232);
return 0;
}
diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c
index d60557cae8ef..5a8daa358066 100644
--- a/drivers/rtc/rtc-m41t80.c
+++ b/drivers/rtc/rtc-m41t80.c
@@ -20,7 +20,7 @@
#include <linux/module.h>
#include <linux/rtc.h>
#include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/string.h>
#ifdef CONFIG_RTC_DRV_M41T80_WDT
#include <linux/fs.h>
@@ -68,6 +68,7 @@
#define DRV_VERSION "0.05"
+static DEFINE_MUTEX(m41t80_rtc_mutex);
static const struct i2c_device_id m41t80_id[] = {
{ "m41t62", M41T80_FEATURE_SQ | M41T80_FEATURE_SQ_ALT },
{ "m41t65", M41T80_FEATURE_HT | M41T80_FEATURE_WD },
@@ -677,9 +678,9 @@ static long wdt_unlocked_ioctl(struct file *file, unsigned int cmd,
{
int ret;
- lock_kernel();
+ mutex_lock(&m41t80_rtc_mutex);
ret = wdt_ioctl(file, cmd, arg);
- unlock_kernel();
+ mutex_unlock(&m41t80_rtc_mutex);
return ret;
}
@@ -693,16 +694,16 @@ static long wdt_unlocked_ioctl(struct file *file, unsigned int cmd,
static int wdt_open(struct inode *inode, struct file *file)
{
if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) {
- lock_kernel();
+ mutex_lock(&m41t80_rtc_mutex);
if (test_and_set_bit(0, &wdt_is_open)) {
- unlock_kernel();
+ mutex_unlock(&m41t80_rtc_mutex);
return -EBUSY;
}
/*
* Activate
*/
wdt_is_open = 1;
- unlock_kernel();
+ mutex_unlock(&m41t80_rtc_mutex);
return nonseekable_open(inode, file);
}
return -ENODEV;
@@ -748,6 +749,7 @@ static const struct file_operations wdt_fops = {
.write = wdt_write,
.open = wdt_open,
.release = wdt_release,
+ .llseek = no_llseek,
};
static struct miscdevice wdt_dev = {
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 8373ca0de8e0..aa95f1001761 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -21,7 +21,6 @@
#include <linux/hdreg.h>
#include <linux/async.h>
#include <linux/mutex.h>
-#include <linux/smp_lock.h>
#include <asm/ccwdev.h>
#include <asm/ebcdic.h>
@@ -2197,7 +2196,6 @@ static void dasd_setup_queue(struct dasd_block *block)
*/
blk_queue_max_segment_size(block->request_queue, PAGE_SIZE);
blk_queue_segment_boundary(block->request_queue, PAGE_SIZE - 1);
- blk_queue_ordered(block->request_queue, QUEUE_ORDERED_DRAIN);
}
/*
@@ -2236,7 +2234,6 @@ static int dasd_open(struct block_device *bdev, fmode_t mode)
if (!block)
return -ENODEV;
- lock_kernel();
base = block->base;
atomic_inc(&block->open_count);
if (test_bit(DASD_FLAG_OFFLINE, &base->flags)) {
@@ -2271,14 +2268,12 @@ static int dasd_open(struct block_device *bdev, fmode_t mode)
goto out;
}
- unlock_kernel();
return 0;
out:
module_put(base->discipline->owner);
unlock:
atomic_dec(&block->open_count);
- unlock_kernel();
return rc;
}
@@ -2286,10 +2281,8 @@ static int dasd_release(struct gendisk *disk, fmode_t mode)
{
struct dasd_block *block = disk->private_data;
- lock_kernel();
atomic_dec(&block->open_count);
module_put(block->base->discipline->owner);
- unlock_kernel();
return 0;
}
diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c
index 7158f9528ecc..c71d89dba302 100644
--- a/drivers/s390/block/dasd_eer.c
+++ b/drivers/s390/block/dasd_eer.c
@@ -670,6 +670,7 @@ static const struct file_operations dasd_eer_fops = {
.read = &dasd_eer_read,
.poll = &dasd_eer_poll,
.owner = THIS_MODULE,
+ .llseek = noop_llseek,
};
static struct miscdevice *dasd_eer_dev = NULL;
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
index 1557214944f7..26075e95b1ba 100644
--- a/drivers/s390/block/dasd_ioctl.c
+++ b/drivers/s390/block/dasd_ioctl.c
@@ -16,7 +16,6 @@
#include <linux/major.h>
#include <linux/fs.h>
#include <linux/blkpg.h>
-#include <linux/smp_lock.h>
#include <linux/slab.h>
#include <asm/compat.h>
#include <asm/ccwdev.h>
@@ -370,9 +369,8 @@ static int dasd_ioctl_readall_cmb(struct dasd_block *block, unsigned int cmd,
return ret;
}
-static int
-dasd_do_ioctl(struct block_device *bdev, fmode_t mode,
- unsigned int cmd, unsigned long arg)
+int dasd_ioctl(struct block_device *bdev, fmode_t mode,
+ unsigned int cmd, unsigned long arg)
{
struct dasd_block *block = bdev->bd_disk->private_data;
void __user *argp;
@@ -430,14 +428,3 @@ dasd_do_ioctl(struct block_device *bdev, fmode_t mode,
return -EINVAL;
}
}
-
-int dasd_ioctl(struct block_device *bdev, fmode_t mode,
- unsigned int cmd, unsigned long arg)
-{
- int rc;
-
- lock_kernel();
- rc = dasd_do_ioctl(bdev, mode, cmd, arg);
- unlock_kernel();
- return rc;
-}
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c
index 2bd72aa34c59..9b43ae94beba 100644
--- a/drivers/s390/block/dcssblk.c
+++ b/drivers/s390/block/dcssblk.c
@@ -14,7 +14,6 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/blkdev.h>
-#include <linux/smp_lock.h>
#include <linux/completion.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
@@ -776,7 +775,6 @@ dcssblk_open(struct block_device *bdev, fmode_t mode)
struct dcssblk_dev_info *dev_info;
int rc;
- lock_kernel();
dev_info = bdev->bd_disk->private_data;
if (NULL == dev_info) {
rc = -ENODEV;
@@ -786,7 +784,6 @@ dcssblk_open(struct block_device *bdev, fmode_t mode)
bdev->bd_block_size = 4096;
rc = 0;
out:
- unlock_kernel();
return rc;
}
@@ -797,7 +794,6 @@ dcssblk_release(struct gendisk *disk, fmode_t mode)
struct segment_info *entry;
int rc;
- lock_kernel();
if (!dev_info) {
rc = -ENODEV;
goto out;
@@ -815,7 +811,6 @@ dcssblk_release(struct gendisk *disk, fmode_t mode)
up_write(&dcssblk_devices_sem);
rc = 0;
out:
- unlock_kernel();
return rc;
}
diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c
index 857dfcb7b359..eb28fb01a38a 100644
--- a/drivers/s390/char/fs3270.c
+++ b/drivers/s390/char/fs3270.c
@@ -520,6 +520,7 @@ static const struct file_operations fs3270_fops = {
.compat_ioctl = fs3270_ioctl, /* ioctl */
.open = fs3270_open, /* open */
.release = fs3270_close, /* release */
+ .llseek = no_llseek,
};
/*
diff --git a/drivers/s390/char/monreader.c b/drivers/s390/char/monreader.c
index e021ec663ef9..5b8b8592d311 100644
--- a/drivers/s390/char/monreader.c
+++ b/drivers/s390/char/monreader.c
@@ -447,6 +447,7 @@ static const struct file_operations mon_fops = {
.release = &mon_close,
.read = &mon_read,
.poll = &mon_poll,
+ .llseek = noop_llseek,
};
static struct miscdevice mon_dev = {
diff --git a/drivers/s390/char/monwriter.c b/drivers/s390/char/monwriter.c
index 572a1e7fd099..e0702d3ea33b 100644
--- a/drivers/s390/char/monwriter.c
+++ b/drivers/s390/char/monwriter.c
@@ -274,6 +274,7 @@ static const struct file_operations monwrite_fops = {
.open = &monwrite_open,
.release = &monwrite_close,
.write = &monwrite_write,
+ .llseek = noop_llseek,
};
static struct miscdevice mon_dev = {
diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c
index f6d72e1f2a38..5707a80b96b6 100644
--- a/drivers/s390/char/sclp.c
+++ b/drivers/s390/char/sclp.c
@@ -468,7 +468,7 @@ sclp_sync_wait(void)
cr0_sync &= 0xffff00a0;
cr0_sync |= 0x00000200;
__ctl_load(cr0_sync, 0, 0);
- __raw_local_irq_stosm(0x01);
+ __arch_local_irq_stosm(0x01);
/* Loop until driver state indicates finished request */
while (sclp_running_state != sclp_running_state_idle) {
/* Check for expired request timer */
diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c
index 85cf607fc78f..f0fa9ca5cb2c 100644
--- a/drivers/s390/char/tape_block.c
+++ b/drivers/s390/char/tape_block.c
@@ -16,7 +16,7 @@
#include <linux/fs.h>
#include <linux/module.h>
#include <linux/blkdev.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/interrupt.h>
#include <linux/buffer_head.h>
#include <linux/kernel.h>
@@ -45,6 +45,7 @@
/*
* file operation structure for tape block frontend
*/
+static DEFINE_MUTEX(tape_block_mutex);
static int tapeblock_open(struct block_device *, fmode_t);
static int tapeblock_release(struct gendisk *, fmode_t);
static int tapeblock_medium_changed(struct gendisk *);
@@ -361,7 +362,7 @@ tapeblock_open(struct block_device *bdev, fmode_t mode)
struct tape_device * device;
int rc;
- lock_kernel();
+ mutex_lock(&tape_block_mutex);
device = tape_get_device(disk->private_data);
if (device->required_tapemarks) {
@@ -385,14 +386,14 @@ tapeblock_open(struct block_device *bdev, fmode_t mode)
* is called.
*/
tape_state_set(device, TS_BLKUSE);
- unlock_kernel();
+ mutex_unlock(&tape_block_mutex);
return 0;
release:
tape_release(device);
put_device:
tape_put_device(device);
- unlock_kernel();
+ mutex_unlock(&tape_block_mutex);
return rc;
}
@@ -407,11 +408,11 @@ tapeblock_release(struct gendisk *disk, fmode_t mode)
{
struct tape_device *device = disk->private_data;
- lock_kernel();
+ mutex_lock(&tape_block_mutex);
tape_state_set(device, TS_IN_USE);
tape_release(device);
tape_put_device(device);
- unlock_kernel();
+ mutex_unlock(&tape_block_mutex);
return 0;
}
diff --git a/drivers/s390/char/tape_char.c b/drivers/s390/char/tape_char.c
index 539045acaad4..883e2db02bd3 100644
--- a/drivers/s390/char/tape_char.c
+++ b/drivers/s390/char/tape_char.c
@@ -53,6 +53,7 @@ static const struct file_operations tape_fops =
#endif
.open = tapechar_open,
.release = tapechar_release,
+ .llseek = no_llseek,
};
static int tapechar_major = TAPECHAR_MAJOR;
diff --git a/drivers/s390/char/vmcp.c b/drivers/s390/char/vmcp.c
index 04e532eec032..0e7cb1a84151 100644
--- a/drivers/s390/char/vmcp.c
+++ b/drivers/s390/char/vmcp.c
@@ -177,6 +177,7 @@ static const struct file_operations vmcp_fops = {
.write = vmcp_write,
.unlocked_ioctl = vmcp_ioctl,
.compat_ioctl = vmcp_ioctl,
+ .llseek = no_llseek,
};
static struct miscdevice vmcp_dev = {
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c
index e40a1b892866..0d6dc4b92cc2 100644
--- a/drivers/s390/char/vmlogrdr.c
+++ b/drivers/s390/char/vmlogrdr.c
@@ -97,6 +97,7 @@ static const struct file_operations vmlogrdr_fops = {
.open = vmlogrdr_open,
.release = vmlogrdr_release,
.read = vmlogrdr_read,
+ .llseek = no_llseek,
};
diff --git a/drivers/s390/char/vmwatchdog.c b/drivers/s390/char/vmwatchdog.c
index e13508c98b1a..12ef9121d4f0 100644
--- a/drivers/s390/char/vmwatchdog.c
+++ b/drivers/s390/char/vmwatchdog.c
@@ -297,6 +297,7 @@ static const struct file_operations vmwdt_fops = {
.unlocked_ioctl = &vmwdt_ioctl,
.write = &vmwdt_write,
.owner = THIS_MODULE,
+ .llseek = noop_llseek,
};
static struct miscdevice vmwdt_dev = {
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c
index f5ea3384a4b9..3b94044027c2 100644
--- a/drivers/s390/char/zcore.c
+++ b/drivers/s390/char/zcore.c
@@ -459,6 +459,7 @@ static const struct file_operations zcore_memmap_fops = {
.read = zcore_memmap_read,
.open = zcore_memmap_open,
.release = zcore_memmap_release,
+ .llseek = no_llseek,
};
static ssize_t zcore_reipl_write(struct file *filp, const char __user *buf,
@@ -486,6 +487,7 @@ static const struct file_operations zcore_reipl_fops = {
.write = zcore_reipl_write,
.open = zcore_reipl_open,
.release = zcore_reipl_release,
+ .llseek = no_llseek,
};
#ifdef CONFIG_32BIT
diff --git a/drivers/s390/cio/chsc_sch.c b/drivers/s390/cio/chsc_sch.c
index a83877c664a6..f2b77e7bfc6f 100644
--- a/drivers/s390/cio/chsc_sch.c
+++ b/drivers/s390/cio/chsc_sch.c
@@ -806,6 +806,7 @@ static const struct file_operations chsc_fops = {
.open = nonseekable_open,
.unlocked_ioctl = chsc_ioctl,
.compat_ioctl = chsc_ioctl,
+ .llseek = no_llseek,
};
static struct miscdevice chsc_misc_device = {
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index ac94ac751459..ca8e1c240c3c 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -1067,6 +1067,7 @@ static ssize_t cio_settle_write(struct file *file, const char __user *buf,
static const struct file_operations cio_settle_proc_fops = {
.open = nonseekable_open,
.write = cio_settle_write,
+ .llseek = no_llseek,
};
static int __init cio_settle_init(void)
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h
index f0037eefd44e..0f4ef8769a3d 100644
--- a/drivers/s390/cio/qdio.h
+++ b/drivers/s390/cio/qdio.h
@@ -208,6 +208,7 @@ struct qdio_dev_perf_stat {
unsigned int eqbs_partial;
unsigned int sqbs;
unsigned int sqbs_partial;
+ unsigned int int_discarded;
} ____cacheline_aligned;
struct qdio_queue_perf_stat {
@@ -222,6 +223,10 @@ struct qdio_queue_perf_stat {
unsigned int nr_sbal_total;
};
+enum qdio_queue_irq_states {
+ QDIO_QUEUE_IRQS_DISABLED,
+};
+
struct qdio_input_q {
/* input buffer acknowledgement flag */
int polling;
@@ -231,6 +236,10 @@ struct qdio_input_q {
int ack_count;
/* last time of noticing incoming data */
u64 timestamp;
+ /* upper-layer polling flag */
+ unsigned long queue_irq_state;
+ /* callback to start upper-layer polling */
+ void (*queue_start_poll) (struct ccw_device *, int, unsigned long);
};
struct qdio_output_q {
@@ -399,6 +408,26 @@ static inline int multicast_outbound(struct qdio_q *q)
#define sub_buf(bufnr, dec) \
((bufnr - dec) & QDIO_MAX_BUFFERS_MASK)
+#define queue_irqs_enabled(q) \
+ (test_bit(QDIO_QUEUE_IRQS_DISABLED, &q->u.in.queue_irq_state) == 0)
+#define queue_irqs_disabled(q) \
+ (test_bit(QDIO_QUEUE_IRQS_DISABLED, &q->u.in.queue_irq_state) != 0)
+
+#define TIQDIO_SHARED_IND 63
+
+/* device state change indicators */
+struct indicator_t {
+ u32 ind; /* u32 because of compare-and-swap performance */
+ atomic_t count; /* use count, 0 or 1 for non-shared indicators */
+};
+
+extern struct indicator_t *q_indicators;
+
+static inline int shared_ind(struct qdio_irq *irq_ptr)
+{
+ return irq_ptr->dsci == &q_indicators[TIQDIO_SHARED_IND].ind;
+}
+
/* prototypes for thin interrupt */
void qdio_setup_thinint(struct qdio_irq *irq_ptr);
int qdio_establish_thinint(struct qdio_irq *irq_ptr);
diff --git a/drivers/s390/cio/qdio_debug.c b/drivers/s390/cio/qdio_debug.c
index 6ce83f56d537..28868e7471a5 100644
--- a/drivers/s390/cio/qdio_debug.c
+++ b/drivers/s390/cio/qdio_debug.c
@@ -56,9 +56,16 @@ static int qstat_show(struct seq_file *m, void *v)
seq_printf(m, "DSCI: %d nr_used: %d\n",
*(u32 *)q->irq_ptr->dsci, atomic_read(&q->nr_buf_used));
- seq_printf(m, "ftc: %d last_move: %d\n", q->first_to_check, q->last_move);
- seq_printf(m, "polling: %d ack start: %d ack count: %d\n",
- q->u.in.polling, q->u.in.ack_start, q->u.in.ack_count);
+ seq_printf(m, "ftc: %d last_move: %d\n",
+ q->first_to_check, q->last_move);
+ if (q->is_input_q) {
+ seq_printf(m, "polling: %d ack start: %d ack count: %d\n",
+ q->u.in.polling, q->u.in.ack_start,
+ q->u.in.ack_count);
+ seq_printf(m, "IRQs disabled: %u\n",
+ test_bit(QDIO_QUEUE_IRQS_DISABLED,
+ &q->u.in.queue_irq_state));
+ }
seq_printf(m, "SBAL states:\n");
seq_printf(m, "|0 |8 |16 |24 |32 |40 |48 |56 63|\n");
@@ -113,22 +120,6 @@ static int qstat_show(struct seq_file *m, void *v)
return 0;
}
-static ssize_t qstat_seq_write(struct file *file, const char __user *buf,
- size_t count, loff_t *off)
-{
- struct seq_file *seq = file->private_data;
- struct qdio_q *q = seq->private;
-
- if (!q)
- return 0;
- if (q->is_input_q)
- xchg(q->irq_ptr->dsci, 1);
- local_bh_disable();
- tasklet_schedule(&q->tasklet);
- local_bh_enable();
- return count;
-}
-
static int qstat_seq_open(struct inode *inode, struct file *filp)
{
return single_open(filp, qstat_show,
@@ -139,7 +130,6 @@ static const struct file_operations debugfs_fops = {
.owner = THIS_MODULE,
.open = qstat_seq_open,
.read = seq_read,
- .write = qstat_seq_write,
.llseek = seq_lseek,
.release = single_release,
};
@@ -166,7 +156,8 @@ static char *qperf_names[] = {
"QEBSM eqbs",
"QEBSM eqbs partial",
"QEBSM sqbs",
- "QEBSM sqbs partial"
+ "QEBSM sqbs partial",
+ "Discarded interrupts"
};
static int qperf_show(struct seq_file *m, void *v)
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c
index 00520f9a7a8e..5fcfa7f9e9ef 100644
--- a/drivers/s390/cio/qdio_main.c
+++ b/drivers/s390/cio/qdio_main.c
@@ -884,8 +884,19 @@ static void qdio_int_handler_pci(struct qdio_irq *irq_ptr)
if (unlikely(irq_ptr->state == QDIO_IRQ_STATE_STOPPED))
return;
- for_each_input_queue(irq_ptr, q, i)
- tasklet_schedule(&q->tasklet);
+ for_each_input_queue(irq_ptr, q, i) {
+ if (q->u.in.queue_start_poll) {
+ /* skip if polling is enabled or already in work */
+ if (test_and_set_bit(QDIO_QUEUE_IRQS_DISABLED,
+ &q->u.in.queue_irq_state)) {
+ qperf_inc(q, int_discarded);
+ continue;
+ }
+ q->u.in.queue_start_poll(q->irq_ptr->cdev, q->nr,
+ q->irq_ptr->int_parm);
+ } else
+ tasklet_schedule(&q->tasklet);
+ }
if (!(irq_ptr->qib.ac & QIB_AC_OUTBOUND_PCI_SUPPORTED))
return;
@@ -1519,6 +1530,129 @@ int do_QDIO(struct ccw_device *cdev, unsigned int callflags,
}
EXPORT_SYMBOL_GPL(do_QDIO);
+/**
+ * qdio_start_irq - process input buffers
+ * @cdev: associated ccw_device for the qdio subchannel
+ * @nr: input queue number
+ *
+ * Return codes
+ * 0 - success
+ * 1 - irqs not started since new data is available
+ */
+int qdio_start_irq(struct ccw_device *cdev, int nr)
+{
+ struct qdio_q *q;
+ struct qdio_irq *irq_ptr = cdev->private->qdio_data;
+
+ if (!irq_ptr)
+ return -ENODEV;
+ q = irq_ptr->input_qs[nr];
+
+ WARN_ON(queue_irqs_enabled(q));
+
+ if (!shared_ind(q->irq_ptr))
+ xchg(q->irq_ptr->dsci, 0);
+
+ qdio_stop_polling(q);
+ clear_bit(QDIO_QUEUE_IRQS_DISABLED, &q->u.in.queue_irq_state);
+
+ /*
+ * We need to check again to not lose initiative after
+ * resetting the ACK state.
+ */
+ if (!shared_ind(q->irq_ptr) && *q->irq_ptr->dsci)
+ goto rescan;
+ if (!qdio_inbound_q_done(q))
+ goto rescan;
+ return 0;
+
+rescan:
+ if (test_and_set_bit(QDIO_QUEUE_IRQS_DISABLED,
+ &q->u.in.queue_irq_state))
+ return 0;
+ else
+ return 1;
+
+}
+EXPORT_SYMBOL(qdio_start_irq);
+
+/**
+ * qdio_get_next_buffers - process input buffers
+ * @cdev: associated ccw_device for the qdio subchannel
+ * @nr: input queue number
+ * @bufnr: first filled buffer number
+ * @error: buffers are in error state
+ *
+ * Return codes
+ * < 0 - error
+ * = 0 - no new buffers found
+ * > 0 - number of processed buffers
+ */
+int qdio_get_next_buffers(struct ccw_device *cdev, int nr, int *bufnr,
+ int *error)
+{
+ struct qdio_q *q;
+ int start, end;
+ struct qdio_irq *irq_ptr = cdev->private->qdio_data;
+
+ if (!irq_ptr)
+ return -ENODEV;
+ q = irq_ptr->input_qs[nr];
+ WARN_ON(queue_irqs_enabled(q));
+
+ qdio_sync_after_thinint(q);
+
+ /*
+ * The interrupt could be caused by a PCI request. Check the
+ * PCI capable outbound queues.
+ */
+ qdio_check_outbound_after_thinint(q);
+
+ if (!qdio_inbound_q_moved(q))
+ return 0;
+
+ /* Note: upper-layer MUST stop processing immediately here ... */
+ if (unlikely(q->irq_ptr->state != QDIO_IRQ_STATE_ACTIVE))
+ return -EIO;
+
+ start = q->first_to_kick;
+ end = q->first_to_check;
+ *bufnr = start;
+ *error = q->qdio_error;
+
+ /* for the next time */
+ q->first_to_kick = end;
+ q->qdio_error = 0;
+ return sub_buf(end, start);
+}
+EXPORT_SYMBOL(qdio_get_next_buffers);
+
+/**
+ * qdio_stop_irq - disable interrupt processing for the device
+ * @cdev: associated ccw_device for the qdio subchannel
+ * @nr: input queue number
+ *
+ * Return codes
+ * 0 - interrupts were already disabled
+ * 1 - interrupts successfully disabled
+ */
+int qdio_stop_irq(struct ccw_device *cdev, int nr)
+{
+ struct qdio_q *q;
+ struct qdio_irq *irq_ptr = cdev->private->qdio_data;
+
+ if (!irq_ptr)
+ return -ENODEV;
+ q = irq_ptr->input_qs[nr];
+
+ if (test_and_set_bit(QDIO_QUEUE_IRQS_DISABLED,
+ &q->u.in.queue_irq_state))
+ return 0;
+ else
+ return 1;
+}
+EXPORT_SYMBOL(qdio_stop_irq);
+
static int __init init_QDIO(void)
{
int rc;
diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c
index 34c7e4046df4..a13cf7ec64b2 100644
--- a/drivers/s390/cio/qdio_setup.c
+++ b/drivers/s390/cio/qdio_setup.c
@@ -161,6 +161,7 @@ static void setup_queues(struct qdio_irq *irq_ptr,
setup_queues_misc(q, irq_ptr, qdio_init->input_handler, i);
q->is_input_q = 1;
+ q->u.in.queue_start_poll = qdio_init->queue_start_poll;
setup_storage_lists(q, irq_ptr, input_sbal_array, i);
input_sbal_array += QDIO_MAX_BUFFERS_PER_Q;
diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c
index 8daf1b99f153..752dbee06af5 100644
--- a/drivers/s390/cio/qdio_thinint.c
+++ b/drivers/s390/cio/qdio_thinint.c
@@ -25,24 +25,20 @@
*/
#define TIQDIO_NR_NONSHARED_IND 63
#define TIQDIO_NR_INDICATORS (TIQDIO_NR_NONSHARED_IND + 1)
-#define TIQDIO_SHARED_IND 63
/* list of thin interrupt input queues */
static LIST_HEAD(tiq_list);
DEFINE_MUTEX(tiq_list_lock);
/* adapter local summary indicator */
-static unsigned char *tiqdio_alsi;
+static u8 *tiqdio_alsi;
-/* device state change indicators */
-struct indicator_t {
- u32 ind; /* u32 because of compare-and-swap performance */
- atomic_t count; /* use count, 0 or 1 for non-shared indicators */
-};
-static struct indicator_t *q_indicators;
+struct indicator_t *q_indicators;
static int css_qdio_omit_svs;
+static u64 last_ai_time;
+
static inline unsigned long do_clear_global_summary(void)
{
register unsigned long __fn asm("1") = 3;
@@ -116,59 +112,73 @@ void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr)
}
}
-static inline int shared_ind(struct qdio_irq *irq_ptr)
+static inline int shared_ind_used(void)
{
- return irq_ptr->dsci == &q_indicators[TIQDIO_SHARED_IND].ind;
+ return atomic_read(&q_indicators[TIQDIO_SHARED_IND].count);
}
/**
* tiqdio_thinint_handler - thin interrupt handler for qdio
- * @ind: pointer to adapter local summary indicator
- * @drv_data: NULL
+ * @alsi: pointer to adapter local summary indicator
+ * @data: NULL
*/
-static void tiqdio_thinint_handler(void *ind, void *drv_data)
+static void tiqdio_thinint_handler(void *alsi, void *data)
{
struct qdio_q *q;
+ last_ai_time = S390_lowcore.int_clock;
+
/*
* SVS only when needed: issue SVS to benefit from iqdio interrupt
- * avoidance (SVS clears adapter interrupt suppression overwrite)
+ * avoidance (SVS clears adapter interrupt suppression overwrite).
*/
if (!css_qdio_omit_svs)
do_clear_global_summary();
- /*
- * reset local summary indicator (tiqdio_alsi) to stop adapter
- * interrupts for now
- */
- xchg((u8 *)ind, 0);
+ /* reset local summary indicator */
+ if (shared_ind_used())
+ xchg(tiqdio_alsi, 0);
/* protect tiq_list entries, only changed in activate or shutdown */
rcu_read_lock();
/* check for work on all inbound thinint queues */
- list_for_each_entry_rcu(q, &tiq_list, entry)
+ list_for_each_entry_rcu(q, &tiq_list, entry) {
+
/* only process queues from changed sets */
- if (*q->irq_ptr->dsci) {
- qperf_inc(q, adapter_int);
+ if (!*q->irq_ptr->dsci)
+ continue;
+ if (q->u.in.queue_start_poll) {
+ /* skip if polling is enabled or already in work */
+ if (test_and_set_bit(QDIO_QUEUE_IRQS_DISABLED,
+ &q->u.in.queue_irq_state)) {
+ qperf_inc(q, int_discarded);
+ continue;
+ }
+
+ /* avoid dsci clear here, done after processing */
+ q->u.in.queue_start_poll(q->irq_ptr->cdev, q->nr,
+ q->irq_ptr->int_parm);
+ } else {
/* only clear it if the indicator is non-shared */
if (!shared_ind(q->irq_ptr))
xchg(q->irq_ptr->dsci, 0);
/*
- * don't call inbound processing directly since
- * that could starve other thinint queues
+ * Call inbound processing but not directly
+ * since that could starve other thinint queues.
*/
tasklet_schedule(&q->tasklet);
}
-
+ qperf_inc(q, adapter_int);
+ }
rcu_read_unlock();
/*
- * if we used the shared indicator clear it now after all queues
- * were processed
+ * If the shared indicator was used clear it now after all queues
+ * were processed.
*/
- if (atomic_read(&q_indicators[TIQDIO_SHARED_IND].count)) {
+ if (shared_ind_used()) {
xchg(&q_indicators[TIQDIO_SHARED_IND].ind, 0);
/* prevent racing */
diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c
index 41e0aaefafd5..f5221749d180 100644
--- a/drivers/s390/crypto/zcrypt_api.c
+++ b/drivers/s390/crypto/zcrypt_api.c
@@ -897,7 +897,8 @@ static const struct file_operations zcrypt_fops = {
.compat_ioctl = zcrypt_compat_ioctl,
#endif
.open = zcrypt_open,
- .release = zcrypt_release
+ .release = zcrypt_release,
+ .llseek = no_llseek,
};
/*
diff --git a/drivers/s390/net/Kconfig b/drivers/s390/net/Kconfig
index 977bb4d4ed15..456b18743397 100644
--- a/drivers/s390/net/Kconfig
+++ b/drivers/s390/net/Kconfig
@@ -100,6 +100,6 @@ config QETH_IPV6
config CCWGROUP
tristate
- default (LCS || CTCM || QETH)
+ default (LCS || CTCM || QETH || CLAW)
endmenu
diff --git a/drivers/s390/net/ctcm_mpc.c b/drivers/s390/net/ctcm_mpc.c
index 2861e78773cb..b64881f33f23 100644
--- a/drivers/s390/net/ctcm_mpc.c
+++ b/drivers/s390/net/ctcm_mpc.c
@@ -540,7 +540,7 @@ void ctc_mpc_dealloc_ch(int port_num)
CTCM_DBF_TEXT_(MPC_SETUP, CTC_DBF_DEBUG,
"%s: %s: refcount = %d\n",
- CTCM_FUNTAIL, dev->name, atomic_read(&dev->refcnt));
+ CTCM_FUNTAIL, dev->name, netdev_refcnt_read(dev));
fsm_deltimer(&priv->restart_timer);
grp->channels_terminating = 0;
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h
index d1257768be90..6be43eb126b4 100644
--- a/drivers/s390/net/qeth_core.h
+++ b/drivers/s390/net/qeth_core.h
@@ -676,6 +676,7 @@ enum qeth_discipline_id {
};
struct qeth_discipline {
+ void (*start_poll)(struct ccw_device *, int, unsigned long);
qdio_handler_t *input_handler;
qdio_handler_t *output_handler;
int (*recover)(void *ptr);
@@ -702,6 +703,16 @@ struct qeth_skb_data {
#define QETH_SKB_MAGIC 0x71657468
#define QETH_SIGA_CC2_RETRIES 3
+struct qeth_rx {
+ int b_count;
+ int b_index;
+ struct qdio_buffer_element *b_element;
+ int e_offset;
+ int qdio_err;
+};
+
+#define QETH_NAPI_WEIGHT 128
+
struct qeth_card {
struct list_head list;
enum qeth_card_states state;
@@ -749,6 +760,8 @@ struct qeth_card {
debug_info_t *debug;
struct mutex conf_mutex;
struct mutex discipline_mutex;
+ struct napi_struct napi;
+ struct qeth_rx rx;
};
struct qeth_card_list_struct {
@@ -831,6 +844,10 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *,
struct qdio_buffer *, struct qdio_buffer_element **, int *,
struct qeth_hdr **);
void qeth_schedule_recovery(struct qeth_card *);
+void qeth_qdio_start_poll(struct ccw_device *, int, unsigned long);
+void qeth_qdio_input_handler(struct ccw_device *,
+ unsigned int, unsigned int, int,
+ int, unsigned long);
void qeth_qdio_output_handler(struct ccw_device *, unsigned int,
int, int, int, unsigned long);
void qeth_clear_ipacmd_list(struct qeth_card *);
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 3a5a18a0fc28..764267062601 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -2911,6 +2911,27 @@ static void qeth_check_outbound_queue(struct qeth_qdio_out_q *queue)
}
}
+void qeth_qdio_start_poll(struct ccw_device *ccwdev, int queue,
+ unsigned long card_ptr)
+{
+ struct qeth_card *card = (struct qeth_card *)card_ptr;
+
+ if (card->dev)
+ napi_schedule(&card->napi);
+}
+EXPORT_SYMBOL_GPL(qeth_qdio_start_poll);
+
+void qeth_qdio_input_handler(struct ccw_device *ccwdev, unsigned int qdio_err,
+ unsigned int queue, int first_element, int count,
+ unsigned long card_ptr)
+{
+ struct qeth_card *card = (struct qeth_card *)card_ptr;
+
+ if (qdio_err)
+ qeth_schedule_recovery(card);
+}
+EXPORT_SYMBOL_GPL(qeth_qdio_input_handler);
+
void qeth_qdio_output_handler(struct ccw_device *ccwdev,
unsigned int qdio_error, int __queue, int first_element,
int count, unsigned long card_ptr)
@@ -3843,6 +3864,7 @@ static int qeth_qdio_establish(struct qeth_card *card)
init_data.no_output_qs = card->qdio.no_out_queues;
init_data.input_handler = card->discipline.input_handler;
init_data.output_handler = card->discipline.output_handler;
+ init_data.queue_start_poll = card->discipline.start_poll;
init_data.int_parm = (unsigned long) card;
init_data.input_sbal_addr_array = (void **) in_sbal_ptrs;
init_data.output_sbal_addr_array = (void **) out_sbal_ptrs;
@@ -4513,8 +4535,8 @@ static struct {
/* 20 */{"queue 1 buffer usage"},
{"queue 2 buffer usage"},
{"queue 3 buffer usage"},
- {"rx handler time"},
- {"rx handler count"},
+ {"rx poll time"},
+ {"rx poll count"},
{"rx do_QDIO time"},
{"rx do_QDIO count"},
{"tx handler time"},
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
index 830d63524d61..847e8797073c 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -310,6 +310,8 @@ static void qeth_l2_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
struct qeth_vlan_vid *id;
QETH_CARD_TEXT_(card, 4, "aid:%d", vid);
+ if (!vid)
+ return;
if (card->info.type == QETH_CARD_TYPE_OSM) {
QETH_CARD_TEXT(card, 3, "aidOSM");
return;
@@ -407,29 +409,25 @@ static int qeth_l2_stop_card(struct qeth_card *card, int recovery_mode)
return rc;
}
-static void qeth_l2_process_inbound_buffer(struct qeth_card *card,
- struct qeth_qdio_buffer *buf, int index)
+static int qeth_l2_process_inbound_buffer(struct qeth_card *card,
+ int budget, int *done)
{
- struct qdio_buffer_element *element;
+ int work_done = 0;
struct sk_buff *skb;
struct qeth_hdr *hdr;
- int offset;
unsigned int len;
- /* get first element of current buffer */
- element = (struct qdio_buffer_element *)&buf->buffer->element[0];
- offset = 0;
- if (card->options.performance_stats)
- card->perf_stats.bufs_rec++;
- while ((skb = qeth_core_get_next_skb(card, buf->buffer, &element,
- &offset, &hdr))) {
- skb->dev = card->dev;
- /* is device UP ? */
- if (!(card->dev->flags & IFF_UP)) {
- dev_kfree_skb_any(skb);
- continue;
+ *done = 0;
+ BUG_ON(!budget);
+ while (budget) {
+ skb = qeth_core_get_next_skb(card,
+ card->qdio.in_q->bufs[card->rx.b_index].buffer,
+ &card->rx.b_element, &card->rx.e_offset, &hdr);
+ if (!skb) {
+ *done = 1;
+ break;
}
-
+ skb->dev = card->dev;
switch (hdr->hdr.l2.id) {
case QETH_HEADER_TYPE_LAYER2:
skb->pkt_type = PACKET_HOST;
@@ -441,7 +439,7 @@ static void qeth_l2_process_inbound_buffer(struct qeth_card *card,
if (skb->protocol == htons(ETH_P_802_2))
*((__u32 *)skb->cb) = ++card->seqno.pkt_seqno;
len = skb->len;
- netif_rx(skb);
+ netif_receive_skb(skb);
break;
case QETH_HEADER_TYPE_OSN:
if (card->info.type == QETH_CARD_TYPE_OSN) {
@@ -459,9 +457,87 @@ static void qeth_l2_process_inbound_buffer(struct qeth_card *card,
QETH_DBF_HEX(CTRL, 3, hdr, QETH_DBF_CTRL_LEN);
continue;
}
+ work_done++;
+ budget--;
card->stats.rx_packets++;
card->stats.rx_bytes += len;
}
+ return work_done;
+}
+
+static int qeth_l2_poll(struct napi_struct *napi, int budget)
+{
+ struct qeth_card *card = container_of(napi, struct qeth_card, napi);
+ int work_done = 0;
+ struct qeth_qdio_buffer *buffer;
+ int done;
+ int new_budget = budget;
+
+ if (card->options.performance_stats) {
+ card->perf_stats.inbound_cnt++;
+ card->perf_stats.inbound_start_time = qeth_get_micros();
+ }
+
+ while (1) {
+ if (!card->rx.b_count) {
+ card->rx.qdio_err = 0;
+ card->rx.b_count = qdio_get_next_buffers(
+ card->data.ccwdev, 0, &card->rx.b_index,
+ &card->rx.qdio_err);
+ if (card->rx.b_count <= 0) {
+ card->rx.b_count = 0;
+ break;
+ }
+ card->rx.b_element =
+ &card->qdio.in_q->bufs[card->rx.b_index]
+ .buffer->element[0];
+ card->rx.e_offset = 0;
+ }
+
+ while (card->rx.b_count) {
+ buffer = &card->qdio.in_q->bufs[card->rx.b_index];
+ if (!(card->rx.qdio_err &&
+ qeth_check_qdio_errors(card, buffer->buffer,
+ card->rx.qdio_err, "qinerr")))
+ work_done += qeth_l2_process_inbound_buffer(
+ card, new_budget, &done);
+ else
+ done = 1;
+
+ if (done) {
+ if (card->options.performance_stats)
+ card->perf_stats.bufs_rec++;
+ qeth_put_buffer_pool_entry(card,
+ buffer->pool_entry);
+ qeth_queue_input_buffer(card, card->rx.b_index);
+ card->rx.b_count--;
+ if (card->rx.b_count) {
+ card->rx.b_index =
+ (card->rx.b_index + 1) %
+ QDIO_MAX_BUFFERS_PER_Q;
+ card->rx.b_element =
+ &card->qdio.in_q
+ ->bufs[card->rx.b_index]
+ .buffer->element[0];
+ card->rx.e_offset = 0;
+ }
+ }
+
+ if (work_done >= budget)
+ goto out;
+ else
+ new_budget = budget - work_done;
+ }
+ }
+
+ napi_complete(napi);
+ if (qdio_start_irq(card->data.ccwdev, 0))
+ napi_schedule(&card->napi);
+out:
+ if (card->options.performance_stats)
+ card->perf_stats.inbound_time += qeth_get_micros() -
+ card->perf_stats.inbound_start_time;
+ return work_done;
}
static int qeth_l2_send_setdelmac(struct qeth_card *card, __u8 *mac,
@@ -755,49 +831,10 @@ tx_drop:
return NETDEV_TX_OK;
}
-static void qeth_l2_qdio_input_handler(struct ccw_device *ccwdev,
- unsigned int qdio_err, unsigned int queue,
- int first_element, int count, unsigned long card_ptr)
-{
- struct net_device *net_dev;
- struct qeth_card *card;
- struct qeth_qdio_buffer *buffer;
- int index;
- int i;
-
- card = (struct qeth_card *) card_ptr;
- net_dev = card->dev;
- if (card->options.performance_stats) {
- card->perf_stats.inbound_cnt++;
- card->perf_stats.inbound_start_time = qeth_get_micros();
- }
- if (qdio_err & QDIO_ERROR_ACTIVATE_CHECK_CONDITION) {
- QETH_CARD_TEXT(card, 1, "qdinchk");
- QETH_CARD_TEXT_(card, 1, "%04X%04X", first_element,
- count);
- QETH_CARD_TEXT_(card, 1, "%04X", queue);
- qeth_schedule_recovery(card);
- return;
- }
- for (i = first_element; i < (first_element + count); ++i) {
- index = i % QDIO_MAX_BUFFERS_PER_Q;
- buffer = &card->qdio.in_q->bufs[index];
- if (!(qdio_err &&
- qeth_check_qdio_errors(card, buffer->buffer, qdio_err,
- "qinerr")))
- qeth_l2_process_inbound_buffer(card, buffer, index);
- /* clear buffer and give back to hardware */
- qeth_put_buffer_pool_entry(card, buffer->pool_entry);
- qeth_queue_input_buffer(card, index);
- }
- if (card->options.performance_stats)
- card->perf_stats.inbound_time += qeth_get_micros() -
- card->perf_stats.inbound_start_time;
-}
-
static int qeth_l2_open(struct net_device *dev)
{
struct qeth_card *card = dev->ml_priv;
+ int rc = 0;
QETH_CARD_TEXT(card, 4, "qethopen");
if (card->state != CARD_STATE_SOFTSETUP)
@@ -814,18 +851,24 @@ static int qeth_l2_open(struct net_device *dev)
if (!card->lan_online && netif_carrier_ok(dev))
netif_carrier_off(dev);
- return 0;
+ if (qdio_stop_irq(card->data.ccwdev, 0) >= 0) {
+ napi_enable(&card->napi);
+ napi_schedule(&card->napi);
+ } else
+ rc = -EIO;
+ return rc;
}
-
static int qeth_l2_stop(struct net_device *dev)
{
struct qeth_card *card = dev->ml_priv;
QETH_CARD_TEXT(card, 4, "qethstop");
netif_tx_disable(dev);
- if (card->state == CARD_STATE_UP)
+ if (card->state == CARD_STATE_UP) {
card->state = CARD_STATE_SOFTSETUP;
+ napi_disable(&card->napi);
+ }
return 0;
}
@@ -836,8 +879,9 @@ static int qeth_l2_probe_device(struct ccwgroup_device *gdev)
INIT_LIST_HEAD(&card->vid_list);
INIT_LIST_HEAD(&card->mc_list);
card->options.layer2 = 1;
+ card->discipline.start_poll = qeth_qdio_start_poll;
card->discipline.input_handler = (qdio_handler_t *)
- qeth_l2_qdio_input_handler;
+ qeth_qdio_input_handler;
card->discipline.output_handler = (qdio_handler_t *)
qeth_qdio_output_handler;
card->discipline.recover = qeth_l2_recover;
@@ -923,6 +967,7 @@ static int qeth_l2_setup_netdev(struct qeth_card *card)
card->info.broadcast_capable = 1;
qeth_l2_request_initial_mac(card);
SET_NETDEV_DEV(card->dev, &card->gdev->dev);
+ netif_napi_add(card->dev, &card->napi, qeth_l2_poll, QETH_NAPI_WEIGHT);
return register_netdev(card->dev);
}
@@ -955,6 +1000,7 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
qeth_l2_send_setmac(card, &card->dev->dev_addr[0]);
card->state = CARD_STATE_HARDSETUP;
+ memset(&card->rx, 0, sizeof(struct qeth_rx));
qeth_print_status_message(card);
/* softsetup */
@@ -1086,9 +1132,6 @@ static int qeth_l2_recover(void *ptr)
card->use_hard_stop = 1;
__qeth_l2_set_offline(card->gdev, 1);
rc = __qeth_l2_set_online(card->gdev, 1);
- /* don't run another scheduled recovery */
- qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
- qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
if (!rc)
dev_info(&card->gdev->dev,
"Device successfully recovered!\n");
@@ -1099,6 +1142,8 @@ static int qeth_l2_recover(void *ptr)
dev_warn(&card->gdev->dev, "The qeth device driver "
"failed to recover an error on the device\n");
}
+ qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
+ qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
return 0;
}
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index e22ae248f613..74d1401a5d5e 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -103,12 +103,7 @@ int qeth_l3_string_to_ipaddr4(const char *buf, __u8 *addr)
void qeth_l3_ipaddr6_to_string(const __u8 *addr, char *buf)
{
- sprintf(buf, "%02x%02x:%02x%02x:%02x%02x:%02x%02x"
- ":%02x%02x:%02x%02x:%02x%02x:%02x%02x",
- addr[0], addr[1], addr[2], addr[3],
- addr[4], addr[5], addr[6], addr[7],
- addr[8], addr[9], addr[10], addr[11],
- addr[12], addr[13], addr[14], addr[15]);
+ sprintf(buf, "%pI6", addr);
}
int qeth_l3_string_to_ipaddr6(const char *buf, __u8 *addr)
@@ -1825,7 +1820,7 @@ static void qeth_l3_add_vlan_mc(struct qeth_card *card)
return;
vg = card->vlangrp;
- for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
+ for (i = 0; i < VLAN_N_VID; i++) {
struct net_device *netdev = vlan_group_get_device(vg, i);
if (netdev == NULL ||
!(netdev->flags & IFF_UP))
@@ -1888,7 +1883,7 @@ static void qeth_l3_add_vlan_mc6(struct qeth_card *card)
return;
vg = card->vlangrp;
- for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
+ for (i = 0; i < VLAN_N_VID; i++) {
struct net_device *netdev = vlan_group_get_device(vg, i);
if (netdev == NULL ||
!(netdev->flags & IFF_UP))
@@ -2018,13 +2013,14 @@ static void qeth_l3_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
qeth_l3_set_multicast_list(card->dev);
}
-static inline __u16 qeth_l3_rebuild_skb(struct qeth_card *card,
- struct sk_buff *skb, struct qeth_hdr *hdr)
+static inline int qeth_l3_rebuild_skb(struct qeth_card *card,
+ struct sk_buff *skb, struct qeth_hdr *hdr,
+ unsigned short *vlan_id)
{
- unsigned short vlan_id = 0;
__be16 prot;
struct iphdr *ip_hdr;
unsigned char tg_addr[MAX_ADDR_LEN];
+ int is_vlan = 0;
if (!(hdr->hdr.l3.flags & QETH_HDR_PASSTHRU)) {
prot = htons((hdr->hdr.l3.flags & QETH_HDR_IPV6)? ETH_P_IPV6 :
@@ -2087,8 +2083,9 @@ static inline __u16 qeth_l3_rebuild_skb(struct qeth_card *card,
if (hdr->hdr.l3.ext_flags &
(QETH_HDR_EXT_VLAN_FRAME | QETH_HDR_EXT_INCLUDE_VLAN_TAG)) {
- vlan_id = (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_VLAN_FRAME)?
+ *vlan_id = (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_VLAN_FRAME) ?
hdr->hdr.l3.vlan_id : *((u16 *)&hdr->hdr.l3.dest_addr[12]);
+ is_vlan = 1;
}
switch (card->options.checksum_type) {
@@ -2109,54 +2106,44 @@ static inline __u16 qeth_l3_rebuild_skb(struct qeth_card *card,
skb->ip_summed = CHECKSUM_NONE;
}
- return vlan_id;
+ return is_vlan;
}
-static void qeth_l3_process_inbound_buffer(struct qeth_card *card,
- struct qeth_qdio_buffer *buf, int index)
+static int qeth_l3_process_inbound_buffer(struct qeth_card *card,
+ int budget, int *done)
{
- struct qdio_buffer_element *element;
+ int work_done = 0;
struct sk_buff *skb;
struct qeth_hdr *hdr;
- int offset;
__u16 vlan_tag = 0;
+ int is_vlan;
unsigned int len;
- /* get first element of current buffer */
- element = (struct qdio_buffer_element *)&buf->buffer->element[0];
- offset = 0;
- if (card->options.performance_stats)
- card->perf_stats.bufs_rec++;
- while ((skb = qeth_core_get_next_skb(card, buf->buffer, &element,
- &offset, &hdr))) {
- skb->dev = card->dev;
- /* is device UP ? */
- if (!(card->dev->flags & IFF_UP)) {
- dev_kfree_skb_any(skb);
- continue;
- }
+ *done = 0;
+ BUG_ON(!budget);
+ while (budget) {
+ skb = qeth_core_get_next_skb(card,
+ card->qdio.in_q->bufs[card->rx.b_index].buffer,
+ &card->rx.b_element, &card->rx.e_offset, &hdr);
+ if (!skb) {
+ *done = 1;
+ break;
+ }
+ skb->dev = card->dev;
switch (hdr->hdr.l3.id) {
case QETH_HEADER_TYPE_LAYER3:
- vlan_tag = qeth_l3_rebuild_skb(card, skb, hdr);
+ is_vlan = qeth_l3_rebuild_skb(card, skb, hdr,
+ &vlan_tag);
len = skb->len;
- if (vlan_tag && !card->options.sniffer)
- if (card->vlangrp)
- vlan_hwaccel_rx(skb, card->vlangrp,
- vlan_tag);
- else {
- dev_kfree_skb_any(skb);
- continue;
- }
+ if (is_vlan && !card->options.sniffer)
+ vlan_gro_receive(&card->napi, card->vlangrp,
+ vlan_tag, skb);
else
- netif_rx(skb);
+ napi_gro_receive(&card->napi, skb);
break;
case QETH_HEADER_TYPE_LAYER2: /* for HiperSockets sniffer */
skb->pkt_type = PACKET_HOST;
skb->protocol = eth_type_trans(skb, skb->dev);
- if (card->options.checksum_type == NO_CHECKSUMMING)
- skb->ip_summed = CHECKSUM_UNNECESSARY;
- else
- skb->ip_summed = CHECKSUM_NONE;
len = skb->len;
netif_receive_skb(skb);
break;
@@ -2166,10 +2153,87 @@ static void qeth_l3_process_inbound_buffer(struct qeth_card *card,
QETH_DBF_HEX(CTRL, 3, hdr, QETH_DBF_CTRL_LEN);
continue;
}
-
+ work_done++;
+ budget--;
card->stats.rx_packets++;
card->stats.rx_bytes += len;
}
+ return work_done;
+}
+
+static int qeth_l3_poll(struct napi_struct *napi, int budget)
+{
+ struct qeth_card *card = container_of(napi, struct qeth_card, napi);
+ int work_done = 0;
+ struct qeth_qdio_buffer *buffer;
+ int done;
+ int new_budget = budget;
+
+ if (card->options.performance_stats) {
+ card->perf_stats.inbound_cnt++;
+ card->perf_stats.inbound_start_time = qeth_get_micros();
+ }
+
+ while (1) {
+ if (!card->rx.b_count) {
+ card->rx.qdio_err = 0;
+ card->rx.b_count = qdio_get_next_buffers(
+ card->data.ccwdev, 0, &card->rx.b_index,
+ &card->rx.qdio_err);
+ if (card->rx.b_count <= 0) {
+ card->rx.b_count = 0;
+ break;
+ }
+ card->rx.b_element =
+ &card->qdio.in_q->bufs[card->rx.b_index]
+ .buffer->element[0];
+ card->rx.e_offset = 0;
+ }
+
+ while (card->rx.b_count) {
+ buffer = &card->qdio.in_q->bufs[card->rx.b_index];
+ if (!(card->rx.qdio_err &&
+ qeth_check_qdio_errors(card, buffer->buffer,
+ card->rx.qdio_err, "qinerr")))
+ work_done += qeth_l3_process_inbound_buffer(
+ card, new_budget, &done);
+ else
+ done = 1;
+
+ if (done) {
+ if (card->options.performance_stats)
+ card->perf_stats.bufs_rec++;
+ qeth_put_buffer_pool_entry(card,
+ buffer->pool_entry);
+ qeth_queue_input_buffer(card, card->rx.b_index);
+ card->rx.b_count--;
+ if (card->rx.b_count) {
+ card->rx.b_index =
+ (card->rx.b_index + 1) %
+ QDIO_MAX_BUFFERS_PER_Q;
+ card->rx.b_element =
+ &card->qdio.in_q
+ ->bufs[card->rx.b_index]
+ .buffer->element[0];
+ card->rx.e_offset = 0;
+ }
+ }
+
+ if (work_done >= budget)
+ goto out;
+ else
+ new_budget = budget - work_done;
+ }
+ }
+
+ napi_complete(napi);
+ if (qdio_start_irq(card->data.ccwdev, 0))
+ napi_schedule(&card->napi);
+out:
+ if (card->options.performance_stats)
+ card->perf_stats.inbound_time += qeth_get_micros() -
+ card->perf_stats.inbound_start_time;
+ return work_done;
}
static int qeth_l3_verify_vlan_dev(struct net_device *dev,
@@ -2183,7 +2247,7 @@ static int qeth_l3_verify_vlan_dev(struct net_device *dev,
if (!vg)
return rc;
- for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
+ for (i = 0; i < VLAN_N_VID; i++) {
if (vlan_group_get_device(vg, i) == dev) {
rc = QETH_VLAN_CARD;
break;
@@ -3103,6 +3167,7 @@ tx_drop:
static int qeth_l3_open(struct net_device *dev)
{
struct qeth_card *card = dev->ml_priv;
+ int rc = 0;
QETH_CARD_TEXT(card, 4, "qethopen");
if (card->state != CARD_STATE_SOFTSETUP)
@@ -3113,7 +3178,12 @@ static int qeth_l3_open(struct net_device *dev)
if (!card->lan_online && netif_carrier_ok(dev))
netif_carrier_off(dev);
- return 0;
+ if (qdio_stop_irq(card->data.ccwdev, 0) >= 0) {
+ napi_enable(&card->napi);
+ napi_schedule(&card->napi);
+ } else
+ rc = -EIO;
+ return rc;
}
static int qeth_l3_stop(struct net_device *dev)
@@ -3122,8 +3192,10 @@ static int qeth_l3_stop(struct net_device *dev)
QETH_CARD_TEXT(card, 4, "qethstop");
netif_tx_disable(dev);
- if (card->state == CARD_STATE_UP)
+ if (card->state == CARD_STATE_UP) {
card->state = CARD_STATE_SOFTSETUP;
+ napi_disable(&card->napi);
+ }
return 0;
}
@@ -3293,57 +3365,19 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
card->dev->gso_max_size = 15 * PAGE_SIZE;
SET_NETDEV_DEV(card->dev, &card->gdev->dev);
+ netif_napi_add(card->dev, &card->napi, qeth_l3_poll, QETH_NAPI_WEIGHT);
return register_netdev(card->dev);
}
-static void qeth_l3_qdio_input_handler(struct ccw_device *ccwdev,
- unsigned int qdio_err, unsigned int queue, int first_element,
- int count, unsigned long card_ptr)
-{
- struct net_device *net_dev;
- struct qeth_card *card;
- struct qeth_qdio_buffer *buffer;
- int index;
- int i;
-
- card = (struct qeth_card *) card_ptr;
- net_dev = card->dev;
- if (card->options.performance_stats) {
- card->perf_stats.inbound_cnt++;
- card->perf_stats.inbound_start_time = qeth_get_micros();
- }
- if (qdio_err & QDIO_ERROR_ACTIVATE_CHECK_CONDITION) {
- QETH_CARD_TEXT(card, 1, "qdinchk");
- QETH_CARD_TEXT_(card, 1, "%04X%04X",
- first_element, count);
- QETH_CARD_TEXT_(card, 1, "%04X", queue);
- qeth_schedule_recovery(card);
- return;
- }
- for (i = first_element; i < (first_element + count); ++i) {
- index = i % QDIO_MAX_BUFFERS_PER_Q;
- buffer = &card->qdio.in_q->bufs[index];
- if (!(qdio_err &&
- qeth_check_qdio_errors(card, buffer->buffer,
- qdio_err, "qinerr")))
- qeth_l3_process_inbound_buffer(card, buffer, index);
- /* clear buffer and give back to hardware */
- qeth_put_buffer_pool_entry(card, buffer->pool_entry);
- qeth_queue_input_buffer(card, index);
- }
- if (card->options.performance_stats)
- card->perf_stats.inbound_time += qeth_get_micros() -
- card->perf_stats.inbound_start_time;
-}
-
static int qeth_l3_probe_device(struct ccwgroup_device *gdev)
{
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
qeth_l3_create_device_attributes(&gdev->dev);
card->options.layer2 = 0;
+ card->discipline.start_poll = qeth_qdio_start_poll;
card->discipline.input_handler = (qdio_handler_t *)
- qeth_l3_qdio_input_handler;
+ qeth_qdio_input_handler;
card->discipline.output_handler = (qdio_handler_t *)
qeth_qdio_output_handler;
card->discipline.recover = qeth_l3_recover;
@@ -3402,6 +3436,7 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
}
card->state = CARD_STATE_HARDSETUP;
+ memset(&card->rx, 0, sizeof(struct qeth_rx));
qeth_print_status_message(card);
/* softsetup */
@@ -3538,9 +3573,6 @@ static int qeth_l3_recover(void *ptr)
card->use_hard_stop = 1;
__qeth_l3_set_offline(card->gdev, 1);
rc = __qeth_l3_set_online(card->gdev, 1);
- /* don't run another scheduled recovery */
- qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
- qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
if (!rc)
dev_info(&card->gdev->dev,
"Device successfully recovered!\n");
@@ -3551,6 +3583,8 @@ static int qeth_l3_recover(void *ptr)
dev_warn(&card->gdev->dev, "The qeth device driver "
"failed to recover an error on the device\n");
}
+ qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
+ qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
return 0;
}
diff --git a/drivers/s390/scsi/Makefile b/drivers/s390/scsi/Makefile
index cb301cc6178c..c454ffebb63e 100644
--- a/drivers/s390/scsi/Makefile
+++ b/drivers/s390/scsi/Makefile
@@ -2,7 +2,8 @@
# Makefile for the S/390 specific device drivers
#
-zfcp-objs := zfcp_aux.o zfcp_ccw.o zfcp_scsi.o zfcp_erp.o zfcp_qdio.o \
- zfcp_fsf.o zfcp_dbf.o zfcp_sysfs.o zfcp_fc.o zfcp_cfdc.o
+zfcp-objs := zfcp_aux.o zfcp_ccw.o zfcp_cfdc.o zfcp_dbf.o zfcp_erp.o \
+ zfcp_fc.o zfcp_fsf.o zfcp_qdio.o zfcp_scsi.o zfcp_sysfs.o \
+ zfcp_unit.o
obj-$(CONFIG_ZFCP) += zfcp.o
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 96fa1f536394..044fb22718d2 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -56,7 +56,6 @@ static void __init zfcp_init_device_configure(char *busid, u64 wwpn, u64 lun)
struct ccw_device *cdev;
struct zfcp_adapter *adapter;
struct zfcp_port *port;
- struct zfcp_unit *unit;
cdev = get_ccwdev_by_busid(&zfcp_ccw_driver, busid);
if (!cdev)
@@ -72,17 +71,11 @@ static void __init zfcp_init_device_configure(char *busid, u64 wwpn, u64 lun)
port = zfcp_get_port_by_wwpn(adapter, wwpn);
if (!port)
goto out_port;
+ flush_work(&port->rport_work);
- unit = zfcp_unit_enqueue(port, lun);
- if (IS_ERR(unit))
- goto out_unit;
-
- zfcp_erp_unit_reopen(unit, 0, "auidc_1", NULL);
- zfcp_erp_wait(adapter);
- flush_work(&unit->scsi_work);
-
-out_unit:
+ zfcp_unit_add(port, lun);
put_device(&port->dev);
+
out_port:
zfcp_ccw_adapter_put(adapter);
out_ccw_device:
@@ -158,6 +151,9 @@ static int __init zfcp_module_init(void)
fc_attach_transport(&zfcp_transport_functions);
if (!zfcp_data.scsi_transport_template)
goto out_transport;
+ scsi_transport_reserve_device(zfcp_data.scsi_transport_template,
+ sizeof(struct zfcp_scsi_dev));
+
retval = misc_register(&zfcp_cfdc_misc);
if (retval) {
@@ -211,30 +207,6 @@ static void __exit zfcp_module_exit(void)
module_exit(zfcp_module_exit);
/**
- * zfcp_get_unit_by_lun - find unit in unit list of port by FCP LUN
- * @port: pointer to port to search for unit
- * @fcp_lun: FCP LUN to search for
- *
- * Returns: pointer to zfcp_unit or NULL
- */
-struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *port, u64 fcp_lun)
-{
- unsigned long flags;
- struct zfcp_unit *unit;
-
- read_lock_irqsave(&port->unit_list_lock, flags);
- list_for_each_entry(unit, &port->unit_list, list)
- if (unit->fcp_lun == fcp_lun) {
- if (!get_device(&unit->dev))
- unit = NULL;
- read_unlock_irqrestore(&port->unit_list_lock, flags);
- return unit;
- }
- read_unlock_irqrestore(&port->unit_list_lock, flags);
- return NULL;
-}
-
-/**
* zfcp_get_port_by_wwpn - find port in port list of adapter by wwpn
* @adapter: pointer to adapter to search for port
* @wwpn: wwpn to search for
@@ -259,92 +231,6 @@ struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *adapter,
return NULL;
}
-/**
- * zfcp_unit_release - dequeue unit
- * @dev: pointer to device
- *
- * waits until all work is done on unit and removes it then from the unit->list
- * of the associated port.
- */
-static void zfcp_unit_release(struct device *dev)
-{
- struct zfcp_unit *unit = container_of(dev, struct zfcp_unit, dev);
-
- put_device(&unit->port->dev);
- kfree(unit);
-}
-
-/**
- * zfcp_unit_enqueue - enqueue unit to unit list of a port.
- * @port: pointer to port where unit is added
- * @fcp_lun: FCP LUN of unit to be enqueued
- * Returns: pointer to enqueued unit on success, ERR_PTR on error
- *
- * Sets up some unit internal structures and creates sysfs entry.
- */
-struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun)
-{
- struct zfcp_unit *unit;
- int retval = -ENOMEM;
-
- get_device(&port->dev);
-
- unit = zfcp_get_unit_by_lun(port, fcp_lun);
- if (unit) {
- put_device(&unit->dev);
- retval = -EEXIST;
- goto err_out;
- }
-
- unit = kzalloc(sizeof(struct zfcp_unit), GFP_KERNEL);
- if (!unit)
- goto err_out;
-
- unit->port = port;
- unit->fcp_lun = fcp_lun;
- unit->dev.parent = &port->dev;
- unit->dev.release = zfcp_unit_release;
-
- if (dev_set_name(&unit->dev, "0x%016llx",
- (unsigned long long) fcp_lun)) {
- kfree(unit);
- goto err_out;
- }
- retval = -EINVAL;
-
- INIT_WORK(&unit->scsi_work, zfcp_scsi_scan_work);
-
- spin_lock_init(&unit->latencies.lock);
- unit->latencies.write.channel.min = 0xFFFFFFFF;
- unit->latencies.write.fabric.min = 0xFFFFFFFF;
- unit->latencies.read.channel.min = 0xFFFFFFFF;
- unit->latencies.read.fabric.min = 0xFFFFFFFF;
- unit->latencies.cmd.channel.min = 0xFFFFFFFF;
- unit->latencies.cmd.fabric.min = 0xFFFFFFFF;
-
- if (device_register(&unit->dev)) {
- put_device(&unit->dev);
- goto err_out;
- }
-
- if (sysfs_create_group(&unit->dev.kobj, &zfcp_sysfs_unit_attrs))
- goto err_out_put;
-
- write_lock_irq(&port->unit_list_lock);
- list_add_tail(&unit->list, &port->unit_list);
- write_unlock_irq(&port->unit_list_lock);
-
- atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &unit->status);
-
- return unit;
-
-err_out_put:
- device_unregister(&unit->dev);
-err_out:
- put_device(&port->dev);
- return ERR_PTR(retval);
-}
-
static int zfcp_allocate_low_mem_buffers(struct zfcp_adapter *adapter)
{
adapter->pool.erp_req =
diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c
index ce1cc7a11fb4..0833c2b51e39 100644
--- a/drivers/s390/scsi/zfcp_ccw.c
+++ b/drivers/s390/scsi/zfcp_ccw.c
@@ -46,8 +46,7 @@ static int zfcp_ccw_activate(struct ccw_device *cdev)
if (!adapter)
return 0;
- zfcp_erp_modify_adapter_status(adapter, "ccresu1", NULL,
- ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
+ zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING);
zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
"ccresu2", NULL);
zfcp_erp_wait(adapter);
@@ -164,14 +163,7 @@ static int zfcp_ccw_set_online(struct ccw_device *cdev)
BUG_ON(!zfcp_reqlist_isempty(adapter->req_list));
adapter->req_no = 0;
- zfcp_erp_modify_adapter_status(adapter, "ccsonl1", NULL,
- ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
- zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
- "ccsonl2", NULL);
- zfcp_erp_wait(adapter);
-
- flush_work(&adapter->scan_work);
-
+ zfcp_ccw_activate(cdev);
zfcp_ccw_adapter_put(adapter);
return 0;
}
@@ -224,9 +216,8 @@ static int zfcp_ccw_notify(struct ccw_device *cdev, int event)
break;
case CIO_OPER:
dev_info(&cdev->dev, "The FCP device is operational again\n");
- zfcp_erp_modify_adapter_status(adapter, "ccnoti3", NULL,
- ZFCP_STATUS_COMMON_RUNNING,
- ZFCP_SET);
+ zfcp_erp_set_adapter_status(adapter,
+ ZFCP_STATUS_COMMON_RUNNING);
zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
"ccnoti4", NULL);
break;
diff --git a/drivers/s390/scsi/zfcp_cfdc.c b/drivers/s390/scsi/zfcp_cfdc.c
index fcbd2b756da4..d692e229ecba 100644
--- a/drivers/s390/scsi/zfcp_cfdc.c
+++ b/drivers/s390/scsi/zfcp_cfdc.c
@@ -2,9 +2,10 @@
* zfcp device driver
*
* Userspace interface for accessing the
- * Access Control Lists / Control File Data Channel
+ * Access Control Lists / Control File Data Channel;
+ * handling of response code and states for ports and LUNs.
*
- * Copyright IBM Corporation 2008, 2009
+ * Copyright IBM Corporation 2008, 2010
*/
#define KMSG_COMPONENT "zfcp"
@@ -251,8 +252,9 @@ static const struct file_operations zfcp_cfdc_fops = {
.open = nonseekable_open,
.unlocked_ioctl = zfcp_cfdc_dev_ioctl,
#ifdef CONFIG_COMPAT
- .compat_ioctl = zfcp_cfdc_dev_ioctl
+ .compat_ioctl = zfcp_cfdc_dev_ioctl,
#endif
+ .llseek = no_llseek,
};
struct miscdevice zfcp_cfdc_misc = {
@@ -260,3 +262,184 @@ struct miscdevice zfcp_cfdc_misc = {
.name = "zfcp_cfdc",
.fops = &zfcp_cfdc_fops,
};
+
+/**
+ * zfcp_cfdc_adapter_access_changed - Process change in adapter ACT
+ * @adapter: Adapter where the Access Control Table (ACT) changed
+ *
+ * After a change in the adapter ACT, check if access to any
+ * previously denied resources is now possible.
+ */
+void zfcp_cfdc_adapter_access_changed(struct zfcp_adapter *adapter)
+{
+ unsigned long flags;
+ struct zfcp_port *port;
+ struct scsi_device *sdev;
+ struct zfcp_scsi_dev *zfcp_sdev;
+ int status;
+
+ if (adapter->connection_features & FSF_FEATURE_NPIV_MODE)
+ return;
+
+ read_lock_irqsave(&adapter->port_list_lock, flags);
+ list_for_each_entry(port, &adapter->port_list, list) {
+ status = atomic_read(&port->status);
+ if ((status & ZFCP_STATUS_COMMON_ACCESS_DENIED) ||
+ (status & ZFCP_STATUS_COMMON_ACCESS_BOXED))
+ zfcp_erp_port_reopen(port,
+ ZFCP_STATUS_COMMON_ERP_FAILED,
+ "cfaac_1", NULL);
+ }
+ read_unlock_irqrestore(&adapter->port_list_lock, flags);
+
+ shost_for_each_device(sdev, port->adapter->scsi_host) {
+ zfcp_sdev = sdev_to_zfcp(sdev);
+ status = atomic_read(&zfcp_sdev->status);
+ if ((status & ZFCP_STATUS_COMMON_ACCESS_DENIED) ||
+ (status & ZFCP_STATUS_COMMON_ACCESS_BOXED))
+ zfcp_erp_lun_reopen(sdev,
+ ZFCP_STATUS_COMMON_ERP_FAILED,
+ "cfaac_2", NULL);
+ }
+}
+
+static void zfcp_act_eval_err(struct zfcp_adapter *adapter, u32 table)
+{
+ u16 subtable = table >> 16;
+ u16 rule = table & 0xffff;
+ const char *act_type[] = { "unknown", "OS", "WWPN", "DID", "LUN" };
+
+ if (subtable && subtable < ARRAY_SIZE(act_type))
+ dev_warn(&adapter->ccw_device->dev,
+ "Access denied according to ACT rule type %s, "
+ "rule %d\n", act_type[subtable], rule);
+}
+
+/**
+ * zfcp_cfdc_port_denied - Process "access denied" for port
+ * @port: The port where the acces has been denied
+ * @qual: The FSF status qualifier for the access denied FSF status
+ */
+void zfcp_cfdc_port_denied(struct zfcp_port *port,
+ union fsf_status_qual *qual)
+{
+ dev_warn(&port->adapter->ccw_device->dev,
+ "Access denied to port 0x%016Lx\n",
+ (unsigned long long)port->wwpn);
+
+ zfcp_act_eval_err(port->adapter, qual->halfword[0]);
+ zfcp_act_eval_err(port->adapter, qual->halfword[1]);
+ zfcp_erp_set_port_status(port,
+ ZFCP_STATUS_COMMON_ERP_FAILED |
+ ZFCP_STATUS_COMMON_ACCESS_DENIED);
+}
+
+/**
+ * zfcp_cfdc_lun_denied - Process "access denied" for LUN
+ * @sdev: The SCSI device / LUN where the access has been denied
+ * @qual: The FSF status qualifier for the access denied FSF status
+ */
+void zfcp_cfdc_lun_denied(struct scsi_device *sdev,
+ union fsf_status_qual *qual)
+{
+ struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+
+ dev_warn(&zfcp_sdev->port->adapter->ccw_device->dev,
+ "Access denied to LUN 0x%016Lx on port 0x%016Lx\n",
+ zfcp_scsi_dev_lun(sdev),
+ (unsigned long long)zfcp_sdev->port->wwpn);
+ zfcp_act_eval_err(zfcp_sdev->port->adapter, qual->halfword[0]);
+ zfcp_act_eval_err(zfcp_sdev->port->adapter, qual->halfword[1]);
+ zfcp_erp_set_lun_status(sdev,
+ ZFCP_STATUS_COMMON_ERP_FAILED |
+ ZFCP_STATUS_COMMON_ACCESS_DENIED);
+
+ atomic_clear_mask(ZFCP_STATUS_LUN_SHARED, &zfcp_sdev->status);
+ atomic_clear_mask(ZFCP_STATUS_LUN_READONLY, &zfcp_sdev->status);
+}
+
+/**
+ * zfcp_cfdc_lun_shrng_vltn - Evaluate LUN sharing violation status
+ * @sdev: The LUN / SCSI device where sharing violation occurred
+ * @qual: The FSF status qualifier from the LUN sharing violation
+ */
+void zfcp_cfdc_lun_shrng_vltn(struct scsi_device *sdev,
+ union fsf_status_qual *qual)
+{
+ struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+
+ if (qual->word[0])
+ dev_warn(&zfcp_sdev->port->adapter->ccw_device->dev,
+ "LUN 0x%Lx on port 0x%Lx is already in "
+ "use by CSS%d, MIF Image ID %x\n",
+ zfcp_scsi_dev_lun(sdev),
+ (unsigned long long)zfcp_sdev->port->wwpn,
+ qual->fsf_queue_designator.cssid,
+ qual->fsf_queue_designator.hla);
+ else
+ zfcp_act_eval_err(zfcp_sdev->port->adapter, qual->word[2]);
+
+ zfcp_erp_set_lun_status(sdev,
+ ZFCP_STATUS_COMMON_ERP_FAILED |
+ ZFCP_STATUS_COMMON_ACCESS_DENIED);
+ atomic_clear_mask(ZFCP_STATUS_LUN_SHARED, &zfcp_sdev->status);
+ atomic_clear_mask(ZFCP_STATUS_LUN_READONLY, &zfcp_sdev->status);
+}
+
+/**
+ * zfcp_cfdc_open_lun_eval - Eval access ctrl. status for successful "open lun"
+ * @sdev: The SCSI device / LUN where to evaluate the status
+ * @bottom: The qtcb bottom with the status from the "open lun"
+ *
+ * Returns: 0 if LUN is usable, -EACCES if the access control table
+ * reports an unsupported configuration.
+ */
+int zfcp_cfdc_open_lun_eval(struct scsi_device *sdev,
+ struct fsf_qtcb_bottom_support *bottom)
+{
+ int shared, rw;
+ struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+ struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
+
+ if ((adapter->connection_features & FSF_FEATURE_NPIV_MODE) ||
+ !(adapter->adapter_features & FSF_FEATURE_LUN_SHARING) ||
+ zfcp_ccw_priv_sch(adapter))
+ return 0;
+
+ shared = !(bottom->lun_access_info & FSF_UNIT_ACCESS_EXCLUSIVE);
+ rw = (bottom->lun_access_info & FSF_UNIT_ACCESS_OUTBOUND_TRANSFER);
+
+ if (shared)
+ atomic_set_mask(ZFCP_STATUS_LUN_SHARED, &zfcp_sdev->status);
+
+ if (!rw) {
+ atomic_set_mask(ZFCP_STATUS_LUN_READONLY, &zfcp_sdev->status);
+ dev_info(&adapter->ccw_device->dev, "SCSI device at LUN "
+ "0x%016Lx on port 0x%016Lx opened read-only\n",
+ zfcp_scsi_dev_lun(sdev),
+ (unsigned long long)zfcp_sdev->port->wwpn);
+ }
+
+ if (!shared && !rw) {
+ dev_err(&adapter->ccw_device->dev, "Exclusive read-only access "
+ "not supported (LUN 0x%016Lx, port 0x%016Lx)\n",
+ zfcp_scsi_dev_lun(sdev),
+ (unsigned long long)zfcp_sdev->port->wwpn);
+ zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ERP_FAILED);
+ zfcp_erp_lun_shutdown(sdev, 0, "fsouh_6", NULL);
+ return -EACCES;
+ }
+
+ if (shared && rw) {
+ dev_err(&adapter->ccw_device->dev,
+ "Shared read-write access not supported "
+ "(LUN 0x%016Lx, port 0x%016Lx)\n",
+ zfcp_scsi_dev_lun(sdev),
+ (unsigned long long)zfcp_sdev->port->wwpn);
+ zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ERP_FAILED);
+ zfcp_erp_lun_shutdown(sdev, 0, "fsosh_8", NULL);
+ return -EACCES;
+ }
+
+ return 0;
+}
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index a86117b0d6e1..2cdd6b28ff7f 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -154,7 +154,6 @@ void _zfcp_dbf_hba_fsf_response(const char *tag2, int level,
scsi_cmnd = (struct scsi_cmnd *)fsf_req->data;
if (scsi_cmnd) {
response->u.fcp.cmnd = (unsigned long)scsi_cmnd;
- response->u.fcp.serial = scsi_cmnd->serial_number;
response->u.fcp.data_dir =
qtcb->bottom.io.data_direction;
}
@@ -330,7 +329,6 @@ static void zfcp_dbf_hba_view_response(char **p,
break;
zfcp_dbf_out(p, "data_direction", "0x%04x", r->u.fcp.data_dir);
zfcp_dbf_out(p, "scsi_cmnd", "0x%0Lx", r->u.fcp.cmnd);
- zfcp_dbf_out(p, "scsi_serial", "0x%016Lx", r->u.fcp.serial);
*p += sprintf(*p, "\n");
break;
@@ -482,7 +480,7 @@ static int zfcp_dbf_rec_view_format(debug_info_t *id, struct debug_view *view,
zfcp_dbf_out(&p, "fcp_lun", "0x%016Lx", r->u.trigger.fcp_lun);
zfcp_dbf_out(&p, "adapter_status", "0x%08x", r->u.trigger.as);
zfcp_dbf_out(&p, "port_status", "0x%08x", r->u.trigger.ps);
- zfcp_dbf_out(&p, "unit_status", "0x%08x", r->u.trigger.us);
+ zfcp_dbf_out(&p, "lun_status", "0x%08x", r->u.trigger.ls);
break;
case ZFCP_REC_DBF_ID_ACTION:
zfcp_dbf_out(&p, "erp_action", "0x%016Lx", r->u.action.action);
@@ -600,19 +598,20 @@ void zfcp_dbf_rec_port(char *id, void *ref, struct zfcp_port *port)
}
/**
- * zfcp_dbf_rec_unit - trace event for unit state change
+ * zfcp_dbf_rec_lun - trace event for LUN state change
* @id: identifier for trigger of state change
* @ref: additional reference (e.g. request)
- * @unit: unit
+ * @sdev: SCSI device
*/
-void zfcp_dbf_rec_unit(char *id, void *ref, struct zfcp_unit *unit)
+void zfcp_dbf_rec_lun(char *id, void *ref, struct scsi_device *sdev)
{
- struct zfcp_port *port = unit->port;
+ struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+ struct zfcp_port *port = zfcp_sdev->port;
struct zfcp_dbf *dbf = port->adapter->dbf;
- zfcp_dbf_rec_target(id, ref, dbf, &unit->status,
- &unit->erp_counter, port->wwpn, port->d_id,
- unit->fcp_lun);
+ zfcp_dbf_rec_target(id, ref, dbf, &zfcp_sdev->status,
+ &zfcp_sdev->erp_counter, port->wwpn, port->d_id,
+ zfcp_scsi_dev_lun(sdev));
}
/**
@@ -624,11 +623,11 @@ void zfcp_dbf_rec_unit(char *id, void *ref, struct zfcp_unit *unit)
* @action: address of error recovery action struct
* @adapter: adapter
* @port: port
- * @unit: unit
+ * @sdev: SCSI device
*/
void zfcp_dbf_rec_trigger(char *id2, void *ref, u8 want, u8 need, void *action,
struct zfcp_adapter *adapter, struct zfcp_port *port,
- struct zfcp_unit *unit)
+ struct scsi_device *sdev)
{
struct zfcp_dbf *dbf = adapter->dbf;
struct zfcp_dbf_rec_record *r = &dbf->rec_buf;
@@ -647,9 +646,10 @@ void zfcp_dbf_rec_trigger(char *id2, void *ref, u8 want, u8 need, void *action,
r->u.trigger.ps = atomic_read(&port->status);
r->u.trigger.wwpn = port->wwpn;
}
- if (unit)
- r->u.trigger.us = atomic_read(&unit->status);
- r->u.trigger.fcp_lun = unit ? unit->fcp_lun : ZFCP_DBF_INVALID_LUN;
+ if (sdev)
+ r->u.trigger.ls = atomic_read(&sdev_to_zfcp(sdev)->status);
+ r->u.trigger.fcp_lun = sdev ? zfcp_scsi_dev_lun(sdev) :
+ ZFCP_DBF_INVALID_LUN;
debug_event(dbf->rec, action ? 1 : 4, r, sizeof(*r));
spin_unlock_irqrestore(&dbf->rec_lock, flags);
}
@@ -879,7 +879,6 @@ void _zfcp_dbf_scsi(const char *tag, const char *tag2, int level,
}
rec->scsi_result = scsi_cmnd->result;
rec->scsi_cmnd = (unsigned long)scsi_cmnd;
- rec->scsi_serial = scsi_cmnd->serial_number;
memcpy(rec->scsi_opcode, scsi_cmnd->cmnd,
min((int)scsi_cmnd->cmd_len,
ZFCP_DBF_SCSI_OPCODE));
@@ -948,7 +947,6 @@ static int zfcp_dbf_scsi_view_format(debug_info_t *id, struct debug_view *view,
zfcp_dbf_out(&p, "scsi_lun", "0x%08x", r->scsi_lun);
zfcp_dbf_out(&p, "scsi_result", "0x%08x", r->scsi_result);
zfcp_dbf_out(&p, "scsi_cmnd", "0x%0Lx", r->scsi_cmnd);
- zfcp_dbf_out(&p, "scsi_serial", "0x%016Lx", r->scsi_serial);
zfcp_dbf_outd(&p, "scsi_opcode", r->scsi_opcode, ZFCP_DBF_SCSI_OPCODE,
0, ZFCP_DBF_SCSI_OPCODE);
zfcp_dbf_out(&p, "scsi_retries", "0x%02x", r->scsi_retries);
diff --git a/drivers/s390/scsi/zfcp_dbf.h b/drivers/s390/scsi/zfcp_dbf.h
index 2bcc3403126a..04081b1b62b4 100644
--- a/drivers/s390/scsi/zfcp_dbf.h
+++ b/drivers/s390/scsi/zfcp_dbf.h
@@ -60,7 +60,7 @@ struct zfcp_dbf_rec_record_trigger {
u8 need;
u32 as;
u32 ps;
- u32 us;
+ u32 ls;
u64 ref;
u64 action;
u64 wwpn;
@@ -110,7 +110,6 @@ struct zfcp_dbf_hba_record_response {
union {
struct {
u64 cmnd;
- u64 serial;
u32 data_dir;
} fcp;
struct {
@@ -206,7 +205,6 @@ struct zfcp_dbf_scsi_record {
u32 scsi_lun;
u32 scsi_result;
u64 scsi_cmnd;
- u64 scsi_serial;
#define ZFCP_DBF_SCSI_OPCODE 16
u8 scsi_opcode[ZFCP_DBF_SCSI_OPCODE];
u8 scsi_retries;
@@ -350,16 +348,16 @@ void zfcp_dbf_scsi_abort(const char *tag, struct zfcp_dbf *dbf,
/**
* zfcp_dbf_scsi_devreset - trace event for Logical Unit or Target Reset
* @tag: tag indicating success or failure of reset operation
+ * @scmnd: SCSI command which caused this error recovery
* @flag: indicates type of reset (Target Reset, Logical Unit Reset)
- * @unit: unit that needs reset
- * @scsi_cmnd: SCSI command which caused this error recovery
*/
static inline
-void zfcp_dbf_scsi_devreset(const char *tag, u8 flag, struct zfcp_unit *unit,
- struct scsi_cmnd *scsi_cmnd)
+void zfcp_dbf_scsi_devreset(const char *tag, struct scsi_cmnd *scmnd, u8 flag)
{
+ struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scmnd->device);
+
zfcp_dbf_scsi(flag == FCP_TMF_TGT_RESET ? "trst" : "lrst", tag, 1,
- unit->port->adapter->dbf, scsi_cmnd, NULL, 0);
+ zfcp_sdev->port->adapter->dbf, scmnd, NULL, 0);
}
#endif /* ZFCP_DBF_H */
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index e1c6b6e05a75..9ae1d0a6f627 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -85,8 +85,8 @@ struct zfcp_reqlist;
#define ZFCP_STATUS_PORT_LINK_TEST 0x00000002
/* logical unit status */
-#define ZFCP_STATUS_UNIT_SHARED 0x00000004
-#define ZFCP_STATUS_UNIT_READONLY 0x00000008
+#define ZFCP_STATUS_LUN_SHARED 0x00000004
+#define ZFCP_STATUS_LUN_READONLY 0x00000008
/* FSF request status (this does not have a common part) */
#define ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT 0x00000002
@@ -118,7 +118,7 @@ struct zfcp_erp_action {
int action; /* requested action code */
struct zfcp_adapter *adapter; /* device which should be recovered */
struct zfcp_port *port;
- struct zfcp_unit *unit;
+ struct scsi_device *sdev;
u32 status; /* recovery status */
u32 step; /* active step of this erp action */
unsigned long fsf_req_id;
@@ -219,21 +219,66 @@ struct zfcp_port {
unsigned int starget_id;
};
+/**
+ * struct zfcp_unit - LUN configured via zfcp sysfs
+ * @dev: struct device for sysfs representation and reference counting
+ * @list: entry in LUN/unit list per zfcp_port
+ * @port: reference to zfcp_port where this LUN is configured
+ * @fcp_lun: 64 bit LUN value
+ * @scsi_work: for running scsi_scan_target
+ *
+ * This is the representation of a LUN that has been configured for
+ * usage. The main data here is the 64 bit LUN value, data for
+ * running I/O and recovery is in struct zfcp_scsi_dev.
+ */
struct zfcp_unit {
- struct device dev;
- struct list_head list; /* list of logical units */
- struct zfcp_port *port; /* remote port of unit */
- atomic_t status; /* status of this logical unit */
- u64 fcp_lun; /* own FCP_LUN */
- u32 handle; /* handle assigned by FSF */
- struct scsi_device *device; /* scsi device struct pointer */
- struct zfcp_erp_action erp_action; /* pending error recovery */
- atomic_t erp_counter;
- struct zfcp_latencies latencies;
+ struct device dev;
+ struct list_head list;
+ struct zfcp_port *port;
+ u64 fcp_lun;
struct work_struct scsi_work;
};
/**
+ * struct zfcp_scsi_dev - zfcp data per SCSI device
+ * @status: zfcp internal status flags
+ * @lun_handle: handle from "open lun" for issuing FSF requests
+ * @erp_action: zfcp erp data for opening and recovering this LUN
+ * @erp_counter: zfcp erp counter for this LUN
+ * @latencies: FSF channel and fabric latencies
+ * @port: zfcp_port where this LUN belongs to
+ */
+struct zfcp_scsi_dev {
+ atomic_t status;
+ u32 lun_handle;
+ struct zfcp_erp_action erp_action;
+ atomic_t erp_counter;
+ struct zfcp_latencies latencies;
+ struct zfcp_port *port;
+};
+
+/**
+ * sdev_to_zfcp - Access zfcp LUN data for SCSI device
+ * @sdev: scsi_device where to get the zfcp_scsi_dev pointer
+ */
+static inline struct zfcp_scsi_dev *sdev_to_zfcp(struct scsi_device *sdev)
+{
+ return scsi_transport_device_data(sdev);
+}
+
+/**
+ * zfcp_scsi_dev_lun - Return SCSI device LUN as 64 bit FCP LUN
+ * @sdev: SCSI device where to get the LUN from
+ */
+static inline u64 zfcp_scsi_dev_lun(struct scsi_device *sdev)
+{
+ u64 fcp_lun;
+
+ int_to_scsilun(sdev->lun, (struct scsi_lun *)&fcp_lun);
+ return fcp_lun;
+}
+
+/**
* struct zfcp_fsf_req - basic FSF request structure
* @list: list of FSF requests
* @req_id: unique request ID
@@ -249,7 +294,6 @@ struct zfcp_unit {
* @erp_action: reference to erp action if request issued on behalf of ERP
* @pool: reference to memory pool if used for this request
* @issued: time when request was send (STCK)
- * @unit: reference to unit if this request is a SCSI request
* @handler: handler which should be called to process response
*/
struct zfcp_fsf_req {
@@ -267,7 +311,6 @@ struct zfcp_fsf_req {
struct zfcp_erp_action *erp_action;
mempool_t *pool;
unsigned long long issued;
- struct zfcp_unit *unit;
void (*handler)(struct zfcp_fsf_req *);
};
@@ -282,9 +325,4 @@ struct zfcp_data {
struct kmem_cache *adisc_cache;
};
-/********************** ZFCP SPECIFIC DEFINES ********************************/
-
-#define ZFCP_SET 0x00000100
-#define ZFCP_CLEAR 0x00000200
-
#endif /* ZFCP_DEF_H */
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index 160b432c907f..d37c7331f244 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -21,6 +21,7 @@ enum zfcp_erp_act_flags {
ZFCP_STATUS_ERP_DISMISSING = 0x00100000,
ZFCP_STATUS_ERP_DISMISSED = 0x00200000,
ZFCP_STATUS_ERP_LOWMEM = 0x00400000,
+ ZFCP_STATUS_ERP_NO_REF = 0x00800000,
};
enum zfcp_erp_steps {
@@ -29,12 +30,12 @@ enum zfcp_erp_steps {
ZFCP_ERP_STEP_PHYS_PORT_CLOSING = 0x0010,
ZFCP_ERP_STEP_PORT_CLOSING = 0x0100,
ZFCP_ERP_STEP_PORT_OPENING = 0x0800,
- ZFCP_ERP_STEP_UNIT_CLOSING = 0x1000,
- ZFCP_ERP_STEP_UNIT_OPENING = 0x2000,
+ ZFCP_ERP_STEP_LUN_CLOSING = 0x1000,
+ ZFCP_ERP_STEP_LUN_OPENING = 0x2000,
};
enum zfcp_erp_act_type {
- ZFCP_ERP_ACTION_REOPEN_UNIT = 1,
+ ZFCP_ERP_ACTION_REOPEN_LUN = 1,
ZFCP_ERP_ACTION_REOPEN_PORT = 2,
ZFCP_ERP_ACTION_REOPEN_PORT_FORCED = 3,
ZFCP_ERP_ACTION_REOPEN_ADAPTER = 4,
@@ -56,9 +57,8 @@ enum zfcp_erp_act_result {
static void zfcp_erp_adapter_block(struct zfcp_adapter *adapter, int mask)
{
- zfcp_erp_modify_adapter_status(adapter, "erablk1", NULL,
- ZFCP_STATUS_COMMON_UNBLOCKED | mask,
- ZFCP_CLEAR);
+ zfcp_erp_clear_adapter_status(adapter,
+ ZFCP_STATUS_COMMON_UNBLOCKED | mask);
}
static int zfcp_erp_action_exists(struct zfcp_erp_action *act)
@@ -88,24 +88,24 @@ static void zfcp_erp_action_dismiss(struct zfcp_erp_action *act)
zfcp_erp_action_ready(act);
}
-static void zfcp_erp_action_dismiss_unit(struct zfcp_unit *unit)
+static void zfcp_erp_action_dismiss_lun(struct scsi_device *sdev)
{
- if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_ERP_INUSE)
- zfcp_erp_action_dismiss(&unit->erp_action);
+ struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+
+ if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_ERP_INUSE)
+ zfcp_erp_action_dismiss(&zfcp_sdev->erp_action);
}
static void zfcp_erp_action_dismiss_port(struct zfcp_port *port)
{
- struct zfcp_unit *unit;
+ struct scsi_device *sdev;
if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_INUSE)
zfcp_erp_action_dismiss(&port->erp_action);
- else {
- read_lock(&port->unit_list_lock);
- list_for_each_entry(unit, &port->unit_list, list)
- zfcp_erp_action_dismiss_unit(unit);
- read_unlock(&port->unit_list_lock);
- }
+ else
+ shost_for_each_device(sdev, port->adapter->scsi_host)
+ if (sdev_to_zfcp(sdev)->port == port)
+ zfcp_erp_action_dismiss_lun(sdev);
}
static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter)
@@ -124,15 +124,17 @@ static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter)
static int zfcp_erp_required_act(int want, struct zfcp_adapter *adapter,
struct zfcp_port *port,
- struct zfcp_unit *unit)
+ struct scsi_device *sdev)
{
int need = want;
- int u_status, p_status, a_status;
+ int l_status, p_status, a_status;
+ struct zfcp_scsi_dev *zfcp_sdev;
switch (want) {
- case ZFCP_ERP_ACTION_REOPEN_UNIT:
- u_status = atomic_read(&unit->status);
- if (u_status & ZFCP_STATUS_COMMON_ERP_INUSE)
+ case ZFCP_ERP_ACTION_REOPEN_LUN:
+ zfcp_sdev = sdev_to_zfcp(sdev);
+ l_status = atomic_read(&zfcp_sdev->status);
+ if (l_status & ZFCP_STATUS_COMMON_ERP_INUSE)
return 0;
p_status = atomic_read(&port->status);
if (!(p_status & ZFCP_STATUS_COMMON_RUNNING) ||
@@ -169,22 +171,26 @@ static int zfcp_erp_required_act(int want, struct zfcp_adapter *adapter,
return need;
}
-static struct zfcp_erp_action *zfcp_erp_setup_act(int need,
+static struct zfcp_erp_action *zfcp_erp_setup_act(int need, u32 act_status,
struct zfcp_adapter *adapter,
struct zfcp_port *port,
- struct zfcp_unit *unit)
+ struct scsi_device *sdev)
{
struct zfcp_erp_action *erp_action;
- u32 status = 0;
+ struct zfcp_scsi_dev *zfcp_sdev;
switch (need) {
- case ZFCP_ERP_ACTION_REOPEN_UNIT:
- if (!get_device(&unit->dev))
- return NULL;
- atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status);
- erp_action = &unit->erp_action;
- if (!(atomic_read(&unit->status) & ZFCP_STATUS_COMMON_RUNNING))
- status = ZFCP_STATUS_ERP_CLOSE_ONLY;
+ case ZFCP_ERP_ACTION_REOPEN_LUN:
+ zfcp_sdev = sdev_to_zfcp(sdev);
+ if (!(act_status & ZFCP_STATUS_ERP_NO_REF))
+ if (scsi_device_get(sdev))
+ return NULL;
+ atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE,
+ &zfcp_sdev->status);
+ erp_action = &zfcp_sdev->erp_action;
+ if (!(atomic_read(&zfcp_sdev->status) &
+ ZFCP_STATUS_COMMON_RUNNING))
+ act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY;
break;
case ZFCP_ERP_ACTION_REOPEN_PORT:
@@ -195,7 +201,7 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need,
atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status);
erp_action = &port->erp_action;
if (!(atomic_read(&port->status) & ZFCP_STATUS_COMMON_RUNNING))
- status = ZFCP_STATUS_ERP_CLOSE_ONLY;
+ act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY;
break;
case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
@@ -205,7 +211,7 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need,
erp_action = &adapter->erp_action;
if (!(atomic_read(&adapter->status) &
ZFCP_STATUS_COMMON_RUNNING))
- status = ZFCP_STATUS_ERP_CLOSE_ONLY;
+ act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY;
break;
default:
@@ -215,16 +221,17 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need,
memset(erp_action, 0, sizeof(struct zfcp_erp_action));
erp_action->adapter = adapter;
erp_action->port = port;
- erp_action->unit = unit;
+ erp_action->sdev = sdev;
erp_action->action = need;
- erp_action->status = status;
+ erp_action->status = act_status;
return erp_action;
}
static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter,
struct zfcp_port *port,
- struct zfcp_unit *unit, char *id, void *ref)
+ struct scsi_device *sdev,
+ char *id, void *ref, u32 act_status)
{
int retval = 1, need;
struct zfcp_erp_action *act = NULL;
@@ -232,21 +239,21 @@ static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter,
if (!adapter->erp_thread)
return -EIO;
- need = zfcp_erp_required_act(want, adapter, port, unit);
+ need = zfcp_erp_required_act(want, adapter, port, sdev);
if (!need)
goto out;
- atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, &adapter->status);
- act = zfcp_erp_setup_act(need, adapter, port, unit);
+ act = zfcp_erp_setup_act(need, act_status, adapter, port, sdev);
if (!act)
goto out;
+ atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, &adapter->status);
++adapter->erp_total_count;
list_add_tail(&act->list, &adapter->erp_ready_head);
wake_up(&adapter->erp_ready_wq);
zfcp_dbf_rec_thread("eracte1", adapter->dbf);
retval = 0;
out:
- zfcp_dbf_rec_trigger(id, ref, want, need, act, adapter, port, unit);
+ zfcp_dbf_rec_trigger(id, ref, want, need, act, adapter, port, sdev);
return retval;
}
@@ -258,11 +265,12 @@ static int _zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter,
/* ensure propagation of failed status to new devices */
if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED) {
- zfcp_erp_adapter_failed(adapter, "erareo1", NULL);
+ zfcp_erp_set_adapter_status(adapter,
+ ZFCP_STATUS_COMMON_ERP_FAILED);
return -EIO;
}
return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER,
- adapter, NULL, NULL, id, ref);
+ adapter, NULL, NULL, id, ref, 0);
}
/**
@@ -282,10 +290,11 @@ void zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear,
write_lock_irqsave(&adapter->erp_lock, flags);
if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED)
- zfcp_erp_adapter_failed(adapter, "erareo1", NULL);
+ zfcp_erp_set_adapter_status(adapter,
+ ZFCP_STATUS_COMMON_ERP_FAILED);
else
zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, adapter,
- NULL, NULL, id, ref);
+ NULL, NULL, id, ref, 0);
write_unlock_irqrestore(&adapter->erp_lock, flags);
}
@@ -317,25 +326,10 @@ void zfcp_erp_port_shutdown(struct zfcp_port *port, int clear, char *id,
zfcp_erp_port_reopen(port, clear | flags, id, ref);
}
-/**
- * zfcp_erp_unit_shutdown - Shutdown unit
- * @unit: Unit to shut down.
- * @clear: Status flags to clear.
- * @id: Id for debug trace event.
- * @ref: Reference for debug trace event.
- */
-void zfcp_erp_unit_shutdown(struct zfcp_unit *unit, int clear, char *id,
- void *ref)
-{
- int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED;
- zfcp_erp_unit_reopen(unit, clear | flags, id, ref);
-}
-
static void zfcp_erp_port_block(struct zfcp_port *port, int clear)
{
- zfcp_erp_modify_port_status(port, "erpblk1", NULL,
- ZFCP_STATUS_COMMON_UNBLOCKED | clear,
- ZFCP_CLEAR);
+ zfcp_erp_clear_port_status(port,
+ ZFCP_STATUS_COMMON_UNBLOCKED | clear);
}
static void _zfcp_erp_port_forced_reopen(struct zfcp_port *port,
@@ -348,7 +342,7 @@ static void _zfcp_erp_port_forced_reopen(struct zfcp_port *port,
return;
zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT_FORCED,
- port->adapter, port, NULL, id, ref);
+ port->adapter, port, NULL, id, ref, 0);
}
/**
@@ -376,12 +370,12 @@ static int _zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id,
if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED) {
/* ensure propagation of failed status to new devices */
- zfcp_erp_port_failed(port, "erpreo1", NULL);
+ zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_ERP_FAILED);
return -EIO;
}
return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT,
- port->adapter, port, NULL, id, ref);
+ port->adapter, port, NULL, id, ref, 0);
}
/**
@@ -404,53 +398,88 @@ int zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id, void *ref)
return retval;
}
-static void zfcp_erp_unit_block(struct zfcp_unit *unit, int clear_mask)
+static void zfcp_erp_lun_block(struct scsi_device *sdev, int clear_mask)
{
- zfcp_erp_modify_unit_status(unit, "erublk1", NULL,
- ZFCP_STATUS_COMMON_UNBLOCKED | clear_mask,
- ZFCP_CLEAR);
+ zfcp_erp_clear_lun_status(sdev,
+ ZFCP_STATUS_COMMON_UNBLOCKED | clear_mask);
}
-static void _zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear, char *id,
- void *ref)
+static void _zfcp_erp_lun_reopen(struct scsi_device *sdev, int clear, char *id,
+ void *ref, u32 act_status)
{
- struct zfcp_adapter *adapter = unit->port->adapter;
+ struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+ struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
- zfcp_erp_unit_block(unit, clear);
+ zfcp_erp_lun_block(sdev, clear);
- if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_ERP_FAILED)
+ if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_ERP_FAILED)
return;
- zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_UNIT,
- adapter, unit->port, unit, id, ref);
+ zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_LUN, adapter,
+ zfcp_sdev->port, sdev, id, ref, act_status);
}
/**
- * zfcp_erp_unit_reopen - initiate reopen of a unit
- * @unit: unit to be reopened
- * @clear_mask: specifies flags in unit status to be cleared
+ * zfcp_erp_lun_reopen - initiate reopen of a LUN
+ * @sdev: SCSI device / LUN to be reopened
+ * @clear_mask: specifies flags in LUN status to be cleared
* Return: 0 on success, < 0 on error
*/
-void zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear, char *id,
- void *ref)
+void zfcp_erp_lun_reopen(struct scsi_device *sdev, int clear, char *id,
+ void *ref)
{
unsigned long flags;
- struct zfcp_port *port = unit->port;
+ struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+ struct zfcp_port *port = zfcp_sdev->port;
struct zfcp_adapter *adapter = port->adapter;
write_lock_irqsave(&adapter->erp_lock, flags);
- _zfcp_erp_unit_reopen(unit, clear, id, ref);
+ _zfcp_erp_lun_reopen(sdev, clear, id, ref, 0);
write_unlock_irqrestore(&adapter->erp_lock, flags);
}
-static int status_change_set(unsigned long mask, atomic_t *status)
+/**
+ * zfcp_erp_lun_shutdown - Shutdown LUN
+ * @sdev: SCSI device / LUN to shut down.
+ * @clear: Status flags to clear.
+ * @id: Id for debug trace event.
+ * @ref: Reference for debug trace event.
+ */
+void zfcp_erp_lun_shutdown(struct scsi_device *sdev, int clear, char *id,
+ void *ref)
{
- return (atomic_read(status) ^ mask) & mask;
+ int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED;
+ zfcp_erp_lun_reopen(sdev, clear | flags, id, ref);
}
-static int status_change_clear(unsigned long mask, atomic_t *status)
+/**
+ * zfcp_erp_lun_shutdown_wait - Shutdown LUN and wait for erp completion
+ * @sdev: SCSI device / LUN to shut down.
+ * @id: Id for debug trace event.
+ *
+ * Do not acquire a reference for the LUN when creating the ERP
+ * action. It is safe, because this function waits for the ERP to
+ * complete first. This allows to shutdown the LUN, even when the SCSI
+ * device is in the state SDEV_DEL when scsi_device_get will fail.
+ */
+void zfcp_erp_lun_shutdown_wait(struct scsi_device *sdev, char *id)
{
- return atomic_read(status) & mask;
+ unsigned long flags;
+ struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+ struct zfcp_port *port = zfcp_sdev->port;
+ struct zfcp_adapter *adapter = port->adapter;
+ int clear = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED;
+
+ write_lock_irqsave(&adapter->erp_lock, flags);
+ _zfcp_erp_lun_reopen(sdev, clear, id, NULL, ZFCP_STATUS_ERP_NO_REF);
+ write_unlock_irqrestore(&adapter->erp_lock, flags);
+
+ zfcp_erp_wait(adapter);
+}
+
+static int status_change_set(unsigned long mask, atomic_t *status)
+{
+ return (atomic_read(status) ^ mask) & mask;
}
static void zfcp_erp_adapter_unblock(struct zfcp_adapter *adapter)
@@ -467,11 +496,13 @@ static void zfcp_erp_port_unblock(struct zfcp_port *port)
atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status);
}
-static void zfcp_erp_unit_unblock(struct zfcp_unit *unit)
+static void zfcp_erp_lun_unblock(struct scsi_device *sdev)
{
- if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &unit->status))
- zfcp_dbf_rec_unit("eruubl1", NULL, unit);
- atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &unit->status);
+ struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+
+ if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &zfcp_sdev->status))
+ zfcp_dbf_rec_lun("erlubl1", NULL, sdev);
+ atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &zfcp_sdev->status);
}
static void zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action)
@@ -559,15 +590,14 @@ static void _zfcp_erp_port_reopen_all(struct zfcp_adapter *adapter,
read_unlock(&adapter->port_list_lock);
}
-static void _zfcp_erp_unit_reopen_all(struct zfcp_port *port, int clear,
- char *id, void *ref)
+static void _zfcp_erp_lun_reopen_all(struct zfcp_port *port, int clear,
+ char *id, void *ref)
{
- struct zfcp_unit *unit;
+ struct scsi_device *sdev;
- read_lock(&port->unit_list_lock);
- list_for_each_entry(unit, &port->unit_list, list)
- _zfcp_erp_unit_reopen(unit, clear, id, ref);
- read_unlock(&port->unit_list_lock);
+ shost_for_each_device(sdev, port->adapter->scsi_host)
+ if (sdev_to_zfcp(sdev)->port == port)
+ _zfcp_erp_lun_reopen(sdev, clear, id, ref, 0);
}
static void zfcp_erp_strategy_followup_failed(struct zfcp_erp_action *act)
@@ -582,8 +612,8 @@ static void zfcp_erp_strategy_followup_failed(struct zfcp_erp_action *act)
case ZFCP_ERP_ACTION_REOPEN_PORT:
_zfcp_erp_port_reopen(act->port, 0, "ersff_3", NULL);
break;
- case ZFCP_ERP_ACTION_REOPEN_UNIT:
- _zfcp_erp_unit_reopen(act->unit, 0, "ersff_4", NULL);
+ case ZFCP_ERP_ACTION_REOPEN_LUN:
+ _zfcp_erp_lun_reopen(act->sdev, 0, "ersff_4", NULL, 0);
break;
}
}
@@ -598,7 +628,7 @@ static void zfcp_erp_strategy_followup_success(struct zfcp_erp_action *act)
_zfcp_erp_port_reopen(act->port, 0, "ersfs_2", NULL);
break;
case ZFCP_ERP_ACTION_REOPEN_PORT:
- _zfcp_erp_unit_reopen_all(act->port, 0, "ersfs_3", NULL);
+ _zfcp_erp_lun_reopen_all(act->port, 0, "ersfs_3", NULL);
break;
}
}
@@ -742,9 +772,8 @@ static void zfcp_erp_adapter_strategy_close(struct zfcp_erp_action *act)
zfcp_fsf_req_dismiss_all(adapter);
adapter->fsf_req_seq_no = 0;
zfcp_fc_wka_ports_force_offline(adapter->gs);
- /* all ports and units are closed */
- zfcp_erp_modify_adapter_status(adapter, "erascl1", NULL,
- ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR);
+ /* all ports and LUNs are closed */
+ zfcp_erp_clear_adapter_status(adapter, ZFCP_STATUS_COMMON_OPEN);
atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK |
ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status);
@@ -861,7 +890,7 @@ static int zfcp_erp_open_ptp_port(struct zfcp_erp_action *act)
struct zfcp_port *port = act->port;
if (port->wwpn != adapter->peer_wwpn) {
- zfcp_erp_port_failed(port, "eroptp1", NULL);
+ zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_ERP_FAILED);
return ZFCP_ERP_FAILED;
}
port->d_id = adapter->peer_d_id;
@@ -933,82 +962,87 @@ close_init_done:
return zfcp_erp_port_strategy_open_common(erp_action);
}
-static void zfcp_erp_unit_strategy_clearstati(struct zfcp_unit *unit)
+static void zfcp_erp_lun_strategy_clearstati(struct scsi_device *sdev)
{
+ struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+
atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
- ZFCP_STATUS_UNIT_SHARED |
- ZFCP_STATUS_UNIT_READONLY,
- &unit->status);
+ ZFCP_STATUS_LUN_SHARED | ZFCP_STATUS_LUN_READONLY,
+ &zfcp_sdev->status);
}
-static int zfcp_erp_unit_strategy_close(struct zfcp_erp_action *erp_action)
+static int zfcp_erp_lun_strategy_close(struct zfcp_erp_action *erp_action)
{
- int retval = zfcp_fsf_close_unit(erp_action);
+ int retval = zfcp_fsf_close_lun(erp_action);
if (retval == -ENOMEM)
return ZFCP_ERP_NOMEM;
- erp_action->step = ZFCP_ERP_STEP_UNIT_CLOSING;
+ erp_action->step = ZFCP_ERP_STEP_LUN_CLOSING;
if (retval)
return ZFCP_ERP_FAILED;
return ZFCP_ERP_CONTINUES;
}
-static int zfcp_erp_unit_strategy_open(struct zfcp_erp_action *erp_action)
+static int zfcp_erp_lun_strategy_open(struct zfcp_erp_action *erp_action)
{
- int retval = zfcp_fsf_open_unit(erp_action);
+ int retval = zfcp_fsf_open_lun(erp_action);
if (retval == -ENOMEM)
return ZFCP_ERP_NOMEM;
- erp_action->step = ZFCP_ERP_STEP_UNIT_OPENING;
+ erp_action->step = ZFCP_ERP_STEP_LUN_OPENING;
if (retval)
return ZFCP_ERP_FAILED;
return ZFCP_ERP_CONTINUES;
}
-static int zfcp_erp_unit_strategy(struct zfcp_erp_action *erp_action)
+static int zfcp_erp_lun_strategy(struct zfcp_erp_action *erp_action)
{
- struct zfcp_unit *unit = erp_action->unit;
+ struct scsi_device *sdev = erp_action->sdev;
+ struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
switch (erp_action->step) {
case ZFCP_ERP_STEP_UNINITIALIZED:
- zfcp_erp_unit_strategy_clearstati(unit);
- if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_OPEN)
- return zfcp_erp_unit_strategy_close(erp_action);
+ zfcp_erp_lun_strategy_clearstati(sdev);
+ if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_OPEN)
+ return zfcp_erp_lun_strategy_close(erp_action);
/* already closed, fall through */
- case ZFCP_ERP_STEP_UNIT_CLOSING:
- if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_OPEN)
+ case ZFCP_ERP_STEP_LUN_CLOSING:
+ if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_OPEN)
return ZFCP_ERP_FAILED;
if (erp_action->status & ZFCP_STATUS_ERP_CLOSE_ONLY)
return ZFCP_ERP_EXIT;
- return zfcp_erp_unit_strategy_open(erp_action);
+ return zfcp_erp_lun_strategy_open(erp_action);
- case ZFCP_ERP_STEP_UNIT_OPENING:
- if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_OPEN)
+ case ZFCP_ERP_STEP_LUN_OPENING:
+ if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_OPEN)
return ZFCP_ERP_SUCCEEDED;
}
return ZFCP_ERP_FAILED;
}
-static int zfcp_erp_strategy_check_unit(struct zfcp_unit *unit, int result)
+static int zfcp_erp_strategy_check_lun(struct scsi_device *sdev, int result)
{
+ struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+
switch (result) {
case ZFCP_ERP_SUCCEEDED :
- atomic_set(&unit->erp_counter, 0);
- zfcp_erp_unit_unblock(unit);
+ atomic_set(&zfcp_sdev->erp_counter, 0);
+ zfcp_erp_lun_unblock(sdev);
break;
case ZFCP_ERP_FAILED :
- atomic_inc(&unit->erp_counter);
- if (atomic_read(&unit->erp_counter) > ZFCP_MAX_ERPS) {
- dev_err(&unit->port->adapter->ccw_device->dev,
- "ERP failed for unit 0x%016Lx on "
+ atomic_inc(&zfcp_sdev->erp_counter);
+ if (atomic_read(&zfcp_sdev->erp_counter) > ZFCP_MAX_ERPS) {
+ dev_err(&zfcp_sdev->port->adapter->ccw_device->dev,
+ "ERP failed for LUN 0x%016Lx on "
"port 0x%016Lx\n",
- (unsigned long long)unit->fcp_lun,
- (unsigned long long)unit->port->wwpn);
- zfcp_erp_unit_failed(unit, "erusck1", NULL);
+ (unsigned long long)zfcp_scsi_dev_lun(sdev),
+ (unsigned long long)zfcp_sdev->port->wwpn);
+ zfcp_erp_set_lun_status(sdev,
+ ZFCP_STATUS_COMMON_ERP_FAILED);
}
break;
}
- if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_ERP_FAILED) {
- zfcp_erp_unit_block(unit, 0);
+ if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_ERP_FAILED) {
+ zfcp_erp_lun_block(sdev, 0);
result = ZFCP_ERP_EXIT;
}
return result;
@@ -1032,7 +1066,8 @@ static int zfcp_erp_strategy_check_port(struct zfcp_port *port, int result)
dev_err(&port->adapter->ccw_device->dev,
"ERP failed for remote port 0x%016Lx\n",
(unsigned long long)port->wwpn);
- zfcp_erp_port_failed(port, "erpsck1", NULL);
+ zfcp_erp_set_port_status(port,
+ ZFCP_STATUS_COMMON_ERP_FAILED);
}
break;
}
@@ -1059,7 +1094,8 @@ static int zfcp_erp_strategy_check_adapter(struct zfcp_adapter *adapter,
dev_err(&adapter->ccw_device->dev,
"ERP cannot recover an error "
"on the FCP device\n");
- zfcp_erp_adapter_failed(adapter, "erasck1", NULL);
+ zfcp_erp_set_adapter_status(adapter,
+ ZFCP_STATUS_COMMON_ERP_FAILED);
}
break;
}
@@ -1076,12 +1112,12 @@ static int zfcp_erp_strategy_check_target(struct zfcp_erp_action *erp_action,
{
struct zfcp_adapter *adapter = erp_action->adapter;
struct zfcp_port *port = erp_action->port;
- struct zfcp_unit *unit = erp_action->unit;
+ struct scsi_device *sdev = erp_action->sdev;
switch (erp_action->action) {
- case ZFCP_ERP_ACTION_REOPEN_UNIT:
- result = zfcp_erp_strategy_check_unit(unit, result);
+ case ZFCP_ERP_ACTION_REOPEN_LUN:
+ result = zfcp_erp_strategy_check_lun(sdev, result);
break;
case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
@@ -1116,7 +1152,8 @@ static int zfcp_erp_strategy_statechange(struct zfcp_erp_action *act, int ret)
int action = act->action;
struct zfcp_adapter *adapter = act->adapter;
struct zfcp_port *port = act->port;
- struct zfcp_unit *unit = act->unit;
+ struct scsi_device *sdev = act->sdev;
+ struct zfcp_scsi_dev *zfcp_sdev;
u32 erp_status = act->status;
switch (action) {
@@ -1139,11 +1176,12 @@ static int zfcp_erp_strategy_statechange(struct zfcp_erp_action *act, int ret)
}
break;
- case ZFCP_ERP_ACTION_REOPEN_UNIT:
- if (zfcp_erp_strat_change_det(&unit->status, erp_status)) {
- _zfcp_erp_unit_reopen(unit,
- ZFCP_STATUS_COMMON_ERP_FAILED,
- "ersscg3", NULL);
+ case ZFCP_ERP_ACTION_REOPEN_LUN:
+ zfcp_sdev = sdev_to_zfcp(sdev);
+ if (zfcp_erp_strat_change_det(&zfcp_sdev->status, erp_status)) {
+ _zfcp_erp_lun_reopen(sdev,
+ ZFCP_STATUS_COMMON_ERP_FAILED,
+ "ersscg3", NULL, 0);
return ZFCP_ERP_EXIT;
}
break;
@@ -1154,6 +1192,7 @@ static int zfcp_erp_strategy_statechange(struct zfcp_erp_action *act, int ret)
static void zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action)
{
struct zfcp_adapter *adapter = erp_action->adapter;
+ struct zfcp_scsi_dev *zfcp_sdev;
adapter->erp_total_count--;
if (erp_action->status & ZFCP_STATUS_ERP_LOWMEM) {
@@ -1165,9 +1204,10 @@ static void zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action)
zfcp_dbf_rec_action("eractd1", erp_action);
switch (erp_action->action) {
- case ZFCP_ERP_ACTION_REOPEN_UNIT:
+ case ZFCP_ERP_ACTION_REOPEN_LUN:
+ zfcp_sdev = sdev_to_zfcp(erp_action->sdev);
atomic_clear_mask(ZFCP_STATUS_COMMON_ERP_INUSE,
- &erp_action->unit->status);
+ &zfcp_sdev->status);
break;
case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
@@ -1187,11 +1227,12 @@ static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result)
{
struct zfcp_adapter *adapter = act->adapter;
struct zfcp_port *port = act->port;
- struct zfcp_unit *unit = act->unit;
+ struct scsi_device *sdev = act->sdev;
switch (act->action) {
- case ZFCP_ERP_ACTION_REOPEN_UNIT:
- put_device(&unit->dev);
+ case ZFCP_ERP_ACTION_REOPEN_LUN:
+ if (!(act->status & ZFCP_STATUS_ERP_NO_REF))
+ scsi_device_put(sdev);
break;
case ZFCP_ERP_ACTION_REOPEN_PORT:
@@ -1222,8 +1263,8 @@ static int zfcp_erp_strategy_do_action(struct zfcp_erp_action *erp_action)
return zfcp_erp_port_forced_strategy(erp_action);
case ZFCP_ERP_ACTION_REOPEN_PORT:
return zfcp_erp_port_strategy(erp_action);
- case ZFCP_ERP_ACTION_REOPEN_UNIT:
- return zfcp_erp_unit_strategy(erp_action);
+ case ZFCP_ERP_ACTION_REOPEN_LUN:
+ return zfcp_erp_lun_strategy(erp_action);
}
return ZFCP_ERP_FAILED;
}
@@ -1376,42 +1417,6 @@ void zfcp_erp_thread_kill(struct zfcp_adapter *adapter)
}
/**
- * zfcp_erp_adapter_failed - Set adapter status to failed.
- * @adapter: Failed adapter.
- * @id: Event id for debug trace.
- * @ref: Reference for debug trace.
- */
-void zfcp_erp_adapter_failed(struct zfcp_adapter *adapter, char *id, void *ref)
-{
- zfcp_erp_modify_adapter_status(adapter, id, ref,
- ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET);
-}
-
-/**
- * zfcp_erp_port_failed - Set port status to failed.
- * @port: Failed port.
- * @id: Event id for debug trace.
- * @ref: Reference for debug trace.
- */
-void zfcp_erp_port_failed(struct zfcp_port *port, char *id, void *ref)
-{
- zfcp_erp_modify_port_status(port, id, ref,
- ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET);
-}
-
-/**
- * zfcp_erp_unit_failed - Set unit status to failed.
- * @unit: Failed unit.
- * @id: Event id for debug trace.
- * @ref: Reference for debug trace.
- */
-void zfcp_erp_unit_failed(struct zfcp_unit *unit, char *id, void *ref)
-{
- zfcp_erp_modify_unit_status(unit, id, ref,
- ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET);
-}
-
-/**
* zfcp_erp_wait - wait for completion of error recovery on an adapter
* @adapter: adapter for which to wait for completion of its error recovery
*/
@@ -1423,210 +1428,148 @@ void zfcp_erp_wait(struct zfcp_adapter *adapter)
}
/**
- * zfcp_erp_modify_adapter_status - change adapter status bits
+ * zfcp_erp_set_adapter_status - set adapter status bits
* @adapter: adapter to change the status
- * @id: id for the debug trace
- * @ref: reference for the debug trace
* @mask: status bits to change
- * @set_or_clear: ZFCP_SET or ZFCP_CLEAR
*
- * Changes in common status bits are propagated to attached ports and units.
+ * Changes in common status bits are propagated to attached ports and LUNs.
*/
-void zfcp_erp_modify_adapter_status(struct zfcp_adapter *adapter, char *id,
- void *ref, u32 mask, int set_or_clear)
+void zfcp_erp_set_adapter_status(struct zfcp_adapter *adapter, u32 mask)
{
struct zfcp_port *port;
+ struct scsi_device *sdev;
unsigned long flags;
u32 common_mask = mask & ZFCP_COMMON_FLAGS;
- if (set_or_clear == ZFCP_SET) {
- if (status_change_set(mask, &adapter->status))
- zfcp_dbf_rec_adapter(id, ref, adapter->dbf);
- atomic_set_mask(mask, &adapter->status);
- } else {
- if (status_change_clear(mask, &adapter->status))
- zfcp_dbf_rec_adapter(id, ref, adapter->dbf);
- atomic_clear_mask(mask, &adapter->status);
- if (mask & ZFCP_STATUS_COMMON_ERP_FAILED)
- atomic_set(&adapter->erp_counter, 0);
- }
+ atomic_set_mask(mask, &adapter->status);
- if (common_mask) {
- read_lock_irqsave(&adapter->port_list_lock, flags);
- list_for_each_entry(port, &adapter->port_list, list)
- zfcp_erp_modify_port_status(port, id, ref, common_mask,
- set_or_clear);
- read_unlock_irqrestore(&adapter->port_list_lock, flags);
- }
+ if (!common_mask)
+ return;
+
+ read_lock_irqsave(&adapter->port_list_lock, flags);
+ list_for_each_entry(port, &adapter->port_list, list)
+ atomic_set_mask(common_mask, &port->status);
+ read_unlock_irqrestore(&adapter->port_list_lock, flags);
+
+ shost_for_each_device(sdev, adapter->scsi_host)
+ atomic_set_mask(common_mask, &sdev_to_zfcp(sdev)->status);
}
/**
- * zfcp_erp_modify_port_status - change port status bits
- * @port: port to change the status bits
- * @id: id for the debug trace
- * @ref: reference for the debug trace
+ * zfcp_erp_clear_adapter_status - clear adapter status bits
+ * @adapter: adapter to change the status
* @mask: status bits to change
- * @set_or_clear: ZFCP_SET or ZFCP_CLEAR
*
- * Changes in common status bits are propagated to attached units.
+ * Changes in common status bits are propagated to attached ports and LUNs.
*/
-void zfcp_erp_modify_port_status(struct zfcp_port *port, char *id, void *ref,
- u32 mask, int set_or_clear)
+void zfcp_erp_clear_adapter_status(struct zfcp_adapter *adapter, u32 mask)
{
- struct zfcp_unit *unit;
+ struct zfcp_port *port;
+ struct scsi_device *sdev;
unsigned long flags;
u32 common_mask = mask & ZFCP_COMMON_FLAGS;
+ u32 clear_counter = mask & ZFCP_STATUS_COMMON_ERP_FAILED;
+
+ atomic_clear_mask(mask, &adapter->status);
+
+ if (!common_mask)
+ return;
+
+ if (clear_counter)
+ atomic_set(&adapter->erp_counter, 0);
- if (set_or_clear == ZFCP_SET) {
- if (status_change_set(mask, &port->status))
- zfcp_dbf_rec_port(id, ref, port);
- atomic_set_mask(mask, &port->status);
- } else {
- if (status_change_clear(mask, &port->status))
- zfcp_dbf_rec_port(id, ref, port);
- atomic_clear_mask(mask, &port->status);
- if (mask & ZFCP_STATUS_COMMON_ERP_FAILED)
+ read_lock_irqsave(&adapter->port_list_lock, flags);
+ list_for_each_entry(port, &adapter->port_list, list) {
+ atomic_clear_mask(common_mask, &port->status);
+ if (clear_counter)
atomic_set(&port->erp_counter, 0);
}
+ read_unlock_irqrestore(&adapter->port_list_lock, flags);
- if (common_mask) {
- read_lock_irqsave(&port->unit_list_lock, flags);
- list_for_each_entry(unit, &port->unit_list, list)
- zfcp_erp_modify_unit_status(unit, id, ref, common_mask,
- set_or_clear);
- read_unlock_irqrestore(&port->unit_list_lock, flags);
+ shost_for_each_device(sdev, adapter->scsi_host) {
+ atomic_clear_mask(common_mask, &sdev_to_zfcp(sdev)->status);
+ if (clear_counter)
+ atomic_set(&sdev_to_zfcp(sdev)->erp_counter, 0);
}
}
/**
- * zfcp_erp_modify_unit_status - change unit status bits
- * @unit: unit to change the status bits
- * @id: id for the debug trace
- * @ref: reference for the debug trace
+ * zfcp_erp_set_port_status - set port status bits
+ * @port: port to change the status
* @mask: status bits to change
- * @set_or_clear: ZFCP_SET or ZFCP_CLEAR
- */
-void zfcp_erp_modify_unit_status(struct zfcp_unit *unit, char *id, void *ref,
- u32 mask, int set_or_clear)
-{
- if (set_or_clear == ZFCP_SET) {
- if (status_change_set(mask, &unit->status))
- zfcp_dbf_rec_unit(id, ref, unit);
- atomic_set_mask(mask, &unit->status);
- } else {
- if (status_change_clear(mask, &unit->status))
- zfcp_dbf_rec_unit(id, ref, unit);
- atomic_clear_mask(mask, &unit->status);
- if (mask & ZFCP_STATUS_COMMON_ERP_FAILED) {
- atomic_set(&unit->erp_counter, 0);
- }
- }
-}
-
-/**
- * zfcp_erp_port_boxed - Mark port as "boxed" and start ERP
- * @port: The "boxed" port.
- * @id: The debug trace id.
- * @id: Reference for the debug trace.
+ *
+ * Changes in common status bits are propagated to attached LUNs.
*/
-void zfcp_erp_port_boxed(struct zfcp_port *port, char *id, void *ref)
+void zfcp_erp_set_port_status(struct zfcp_port *port, u32 mask)
{
- zfcp_erp_modify_port_status(port, id, ref,
- ZFCP_STATUS_COMMON_ACCESS_BOXED, ZFCP_SET);
- zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref);
-}
+ struct scsi_device *sdev;
+ u32 common_mask = mask & ZFCP_COMMON_FLAGS;
-/**
- * zfcp_erp_unit_boxed - Mark unit as "boxed" and start ERP
- * @port: The "boxed" unit.
- * @id: The debug trace id.
- * @id: Reference for the debug trace.
- */
-void zfcp_erp_unit_boxed(struct zfcp_unit *unit, char *id, void *ref)
-{
- zfcp_erp_modify_unit_status(unit, id, ref,
- ZFCP_STATUS_COMMON_ACCESS_BOXED, ZFCP_SET);
- zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref);
-}
+ atomic_set_mask(mask, &port->status);
-/**
- * zfcp_erp_port_access_denied - Adapter denied access to port.
- * @port: port where access has been denied
- * @id: id for debug trace
- * @ref: reference for debug trace
- *
- * Since the adapter has denied access, stop using the port and the
- * attached units.
- */
-void zfcp_erp_port_access_denied(struct zfcp_port *port, char *id, void *ref)
-{
- zfcp_erp_modify_port_status(port, id, ref,
- ZFCP_STATUS_COMMON_ERP_FAILED |
- ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET);
+ if (!common_mask)
+ return;
+
+ shost_for_each_device(sdev, port->adapter->scsi_host)
+ if (sdev_to_zfcp(sdev)->port == port)
+ atomic_set_mask(common_mask,
+ &sdev_to_zfcp(sdev)->status);
}
/**
- * zfcp_erp_unit_access_denied - Adapter denied access to unit.
- * @unit: unit where access has been denied
- * @id: id for debug trace
- * @ref: reference for debug trace
+ * zfcp_erp_clear_port_status - clear port status bits
+ * @port: adapter to change the status
+ * @mask: status bits to change
*
- * Since the adapter has denied access, stop using the unit.
+ * Changes in common status bits are propagated to attached LUNs.
*/
-void zfcp_erp_unit_access_denied(struct zfcp_unit *unit, char *id, void *ref)
+void zfcp_erp_clear_port_status(struct zfcp_port *port, u32 mask)
{
- zfcp_erp_modify_unit_status(unit, id, ref,
- ZFCP_STATUS_COMMON_ERP_FAILED |
- ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET);
-}
+ struct scsi_device *sdev;
+ u32 common_mask = mask & ZFCP_COMMON_FLAGS;
+ u32 clear_counter = mask & ZFCP_STATUS_COMMON_ERP_FAILED;
-static void zfcp_erp_unit_access_changed(struct zfcp_unit *unit, char *id,
- void *ref)
-{
- int status = atomic_read(&unit->status);
- if (!(status & (ZFCP_STATUS_COMMON_ACCESS_DENIED |
- ZFCP_STATUS_COMMON_ACCESS_BOXED)))
+ atomic_clear_mask(mask, &port->status);
+
+ if (!common_mask)
return;
- zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref);
+ if (clear_counter)
+ atomic_set(&port->erp_counter, 0);
+
+ shost_for_each_device(sdev, port->adapter->scsi_host)
+ if (sdev_to_zfcp(sdev)->port == port) {
+ atomic_clear_mask(common_mask,
+ &sdev_to_zfcp(sdev)->status);
+ if (clear_counter)
+ atomic_set(&sdev_to_zfcp(sdev)->erp_counter, 0);
+ }
}
-static void zfcp_erp_port_access_changed(struct zfcp_port *port, char *id,
- void *ref)
+/**
+ * zfcp_erp_set_lun_status - set lun status bits
+ * @sdev: SCSI device / lun to set the status bits
+ * @mask: status bits to change
+ */
+void zfcp_erp_set_lun_status(struct scsi_device *sdev, u32 mask)
{
- struct zfcp_unit *unit;
- unsigned long flags;
- int status = atomic_read(&port->status);
+ struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
- if (!(status & (ZFCP_STATUS_COMMON_ACCESS_DENIED |
- ZFCP_STATUS_COMMON_ACCESS_BOXED))) {
- read_lock_irqsave(&port->unit_list_lock, flags);
- list_for_each_entry(unit, &port->unit_list, list)
- zfcp_erp_unit_access_changed(unit, id, ref);
- read_unlock_irqrestore(&port->unit_list_lock, flags);
- return;
- }
-
- zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref);
+ atomic_set_mask(mask, &zfcp_sdev->status);
}
/**
- * zfcp_erp_adapter_access_changed - Process change in adapter ACT
- * @adapter: Adapter where the Access Control Table (ACT) changed
- * @id: Id for debug trace
- * @ref: Reference for debug trace
+ * zfcp_erp_clear_lun_status - clear lun status bits
+ * @sdev: SCSi device / lun to clear the status bits
+ * @mask: status bits to change
*/
-void zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter, char *id,
- void *ref)
+void zfcp_erp_clear_lun_status(struct scsi_device *sdev, u32 mask)
{
- unsigned long flags;
- struct zfcp_port *port;
+ struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
- if (adapter->connection_features & FSF_FEATURE_NPIV_MODE)
- return;
+ atomic_clear_mask(mask, &zfcp_sdev->status);
- read_lock_irqsave(&adapter->port_list_lock, flags);
- list_for_each_entry(port, &adapter->port_list, list)
- zfcp_erp_port_access_changed(port, id, ref);
- read_unlock_irqrestore(&adapter->port_list_lock, flags);
+ if (mask & ZFCP_STATUS_COMMON_ERP_FAILED)
+ atomic_set(&zfcp_sdev->erp_counter, 0);
}
+
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index 3b93239c6f69..bf8f3e514839 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -15,12 +15,10 @@
#include "zfcp_fc.h"
/* zfcp_aux.c */
-extern struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *, u64);
extern struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *, u64);
extern struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *);
extern struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *, u64, u32,
u32);
-extern struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *, u64);
extern void zfcp_sg_free_table(struct scatterlist *, int);
extern int zfcp_sg_setup_table(struct scatterlist *, int);
extern void zfcp_device_unregister(struct device *,
@@ -36,6 +34,14 @@ extern void zfcp_ccw_adapter_put(struct zfcp_adapter *);
/* zfcp_cfdc.c */
extern struct miscdevice zfcp_cfdc_misc;
+extern void zfcp_cfdc_port_denied(struct zfcp_port *, union fsf_status_qual *);
+extern void zfcp_cfdc_lun_denied(struct scsi_device *, union fsf_status_qual *);
+extern void zfcp_cfdc_lun_shrng_vltn(struct scsi_device *,
+ union fsf_status_qual *);
+extern int zfcp_cfdc_open_lun_eval(struct scsi_device *,
+ struct fsf_qtcb_bottom_support *);
+extern void zfcp_cfdc_adapter_access_changed(struct zfcp_adapter *);
+
/* zfcp_dbf.c */
extern int zfcp_dbf_adapter_register(struct zfcp_adapter *);
@@ -44,10 +50,10 @@ extern void zfcp_dbf_rec_thread(char *, struct zfcp_dbf *);
extern void zfcp_dbf_rec_thread_lock(char *, struct zfcp_dbf *);
extern void zfcp_dbf_rec_adapter(char *, void *, struct zfcp_dbf *);
extern void zfcp_dbf_rec_port(char *, void *, struct zfcp_port *);
-extern void zfcp_dbf_rec_unit(char *, void *, struct zfcp_unit *);
+extern void zfcp_dbf_rec_lun(char *, void *, struct scsi_device *);
extern void zfcp_dbf_rec_trigger(char *, void *, u8, u8, void *,
struct zfcp_adapter *, struct zfcp_port *,
- struct zfcp_unit *);
+ struct scsi_device *);
extern void zfcp_dbf_rec_action(char *, struct zfcp_erp_action *);
extern void _zfcp_dbf_hba_fsf_response(const char *, int, struct zfcp_fsf_req *,
struct zfcp_dbf *);
@@ -65,34 +71,26 @@ extern void _zfcp_dbf_scsi(const char *, const char *, int, struct zfcp_dbf *,
unsigned long);
/* zfcp_erp.c */
-extern void zfcp_erp_modify_adapter_status(struct zfcp_adapter *, char *,
- void *, u32, int);
+extern void zfcp_erp_set_adapter_status(struct zfcp_adapter *, u32);
+extern void zfcp_erp_clear_adapter_status(struct zfcp_adapter *, u32);
extern void zfcp_erp_adapter_reopen(struct zfcp_adapter *, int, char *, void *);
extern void zfcp_erp_adapter_shutdown(struct zfcp_adapter *, int, char *,
void *);
-extern void zfcp_erp_adapter_failed(struct zfcp_adapter *, char *, void *);
-extern void zfcp_erp_modify_port_status(struct zfcp_port *, char *, void *, u32,
- int);
+extern void zfcp_erp_set_port_status(struct zfcp_port *, u32);
+extern void zfcp_erp_clear_port_status(struct zfcp_port *, u32);
extern int zfcp_erp_port_reopen(struct zfcp_port *, int, char *, void *);
extern void zfcp_erp_port_shutdown(struct zfcp_port *, int, char *, void *);
extern void zfcp_erp_port_forced_reopen(struct zfcp_port *, int, char *,
void *);
-extern void zfcp_erp_port_failed(struct zfcp_port *, char *, void *);
-extern void zfcp_erp_modify_unit_status(struct zfcp_unit *, char *, void *, u32,
- int);
-extern void zfcp_erp_unit_reopen(struct zfcp_unit *, int, char *, void *);
-extern void zfcp_erp_unit_shutdown(struct zfcp_unit *, int, char *, void *);
-extern void zfcp_erp_unit_failed(struct zfcp_unit *, char *, void *);
+extern void zfcp_erp_set_lun_status(struct scsi_device *, u32);
+extern void zfcp_erp_clear_lun_status(struct scsi_device *, u32);
+extern void zfcp_erp_lun_reopen(struct scsi_device *, int, char *, void *);
+extern void zfcp_erp_lun_shutdown(struct scsi_device *, int, char *, void *);
+extern void zfcp_erp_lun_shutdown_wait(struct scsi_device *, char *);
extern int zfcp_erp_thread_setup(struct zfcp_adapter *);
extern void zfcp_erp_thread_kill(struct zfcp_adapter *);
extern void zfcp_erp_wait(struct zfcp_adapter *);
extern void zfcp_erp_notify(struct zfcp_erp_action *, unsigned long);
-extern void zfcp_erp_port_boxed(struct zfcp_port *, char *, void *);
-extern void zfcp_erp_unit_boxed(struct zfcp_unit *, char *, void *);
-extern void zfcp_erp_port_access_denied(struct zfcp_port *, char *, void *);
-extern void zfcp_erp_unit_access_denied(struct zfcp_unit *, char *, void *);
-extern void zfcp_erp_adapter_access_changed(struct zfcp_adapter *, char *,
- void *);
extern void zfcp_erp_timeout_handler(unsigned long);
/* zfcp_fc.c */
@@ -118,8 +116,8 @@ extern int zfcp_fsf_open_wka_port(struct zfcp_fc_wka_port *);
extern int zfcp_fsf_close_wka_port(struct zfcp_fc_wka_port *);
extern int zfcp_fsf_close_port(struct zfcp_erp_action *);
extern int zfcp_fsf_close_physical_port(struct zfcp_erp_action *);
-extern int zfcp_fsf_open_unit(struct zfcp_erp_action *);
-extern int zfcp_fsf_close_unit(struct zfcp_erp_action *);
+extern int zfcp_fsf_open_lun(struct zfcp_erp_action *);
+extern int zfcp_fsf_close_lun(struct zfcp_erp_action *);
extern int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *);
extern int zfcp_fsf_exchange_config_data_sync(struct zfcp_qdio *,
struct fsf_qtcb_bottom_config *);
@@ -135,12 +133,10 @@ extern int zfcp_fsf_send_ct(struct zfcp_fc_wka_port *, struct zfcp_fsf_ct_els *,
mempool_t *, unsigned int);
extern int zfcp_fsf_send_els(struct zfcp_adapter *, u32,
struct zfcp_fsf_ct_els *, unsigned int);
-extern int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *,
- struct scsi_cmnd *);
+extern int zfcp_fsf_fcp_cmnd(struct scsi_cmnd *);
extern void zfcp_fsf_req_free(struct zfcp_fsf_req *);
-extern struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *, u8);
-extern struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long,
- struct zfcp_unit *);
+extern struct zfcp_fsf_req *zfcp_fsf_fcp_task_mgmt(struct scsi_cmnd *, u8);
+extern struct zfcp_fsf_req *zfcp_fsf_abort_fcp_cmnd(struct scsi_cmnd *);
extern void zfcp_fsf_reqid_check(struct zfcp_qdio *, int);
/* zfcp_qdio.c */
@@ -163,8 +159,6 @@ extern void zfcp_scsi_rport_work(struct work_struct *);
extern void zfcp_scsi_schedule_rport_register(struct zfcp_port *);
extern void zfcp_scsi_schedule_rport_block(struct zfcp_port *);
extern void zfcp_scsi_schedule_rports_block(struct zfcp_adapter *);
-extern void zfcp_scsi_scan(struct zfcp_unit *);
-extern void zfcp_scsi_scan_work(struct work_struct *);
extern void zfcp_scsi_set_prot(struct zfcp_adapter *);
extern void zfcp_scsi_dif_sense_error(struct scsi_cmnd *, int);
@@ -175,4 +169,13 @@ extern struct attribute_group zfcp_sysfs_port_attrs;
extern struct device_attribute *zfcp_sysfs_sdev_attrs[];
extern struct device_attribute *zfcp_sysfs_shost_attrs[];
+/* zfcp_unit.c */
+extern int zfcp_unit_add(struct zfcp_port *, u64);
+extern int zfcp_unit_remove(struct zfcp_port *, u64);
+extern struct zfcp_unit *zfcp_unit_find(struct zfcp_port *, u64);
+extern struct scsi_device *zfcp_unit_sdev(struct zfcp_unit *unit);
+extern void zfcp_unit_scsi_scan(struct zfcp_unit *);
+extern void zfcp_unit_queue_scsi_scan(struct zfcp_port *);
+extern unsigned int zfcp_unit_sdev_status(struct zfcp_unit *);
+
#endif /* ZFCP_EXT_H */
diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c
index 6f3ed2b9a349..86fd905df48b 100644
--- a/drivers/s390/scsi/zfcp_fc.c
+++ b/drivers/s390/scsi/zfcp_fc.c
@@ -365,7 +365,7 @@ void zfcp_fc_port_did_lookup(struct work_struct *work)
}
if (!port->d_id) {
- zfcp_erp_port_failed(port, "fcgpn_2", NULL);
+ zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_ERP_FAILED);
goto out;
}
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 9d1d7d1842ce..beaf0916ceab 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -61,45 +61,6 @@ static u32 fsf_qtcb_type[] = {
[FSF_QTCB_UPLOAD_CONTROL_FILE] = FSF_SUPPORT_COMMAND
};
-static void zfcp_act_eval_err(struct zfcp_adapter *adapter, u32 table)
-{
- u16 subtable = table >> 16;
- u16 rule = table & 0xffff;
- const char *act_type[] = { "unknown", "OS", "WWPN", "DID", "LUN" };
-
- if (subtable && subtable < ARRAY_SIZE(act_type))
- dev_warn(&adapter->ccw_device->dev,
- "Access denied according to ACT rule type %s, "
- "rule %d\n", act_type[subtable], rule);
-}
-
-static void zfcp_fsf_access_denied_port(struct zfcp_fsf_req *req,
- struct zfcp_port *port)
-{
- struct fsf_qtcb_header *header = &req->qtcb->header;
- dev_warn(&req->adapter->ccw_device->dev,
- "Access denied to port 0x%016Lx\n",
- (unsigned long long)port->wwpn);
- zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[0]);
- zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[1]);
- zfcp_erp_port_access_denied(port, "fspad_1", req);
- req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-}
-
-static void zfcp_fsf_access_denied_unit(struct zfcp_fsf_req *req,
- struct zfcp_unit *unit)
-{
- struct fsf_qtcb_header *header = &req->qtcb->header;
- dev_warn(&req->adapter->ccw_device->dev,
- "Access denied to unit 0x%016Lx on port 0x%016Lx\n",
- (unsigned long long)unit->fcp_lun,
- (unsigned long long)unit->port->wwpn);
- zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[0]);
- zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[1]);
- zfcp_erp_unit_access_denied(unit, "fsuad_1", req);
- req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-}
-
static void zfcp_fsf_class_not_supp(struct zfcp_fsf_req *req)
{
dev_err(&req->adapter->ccw_device->dev, "FCP device not "
@@ -143,7 +104,7 @@ static void zfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *req)
read_unlock_irqrestore(&adapter->port_list_lock, flags);
}
-static void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *req, char *id,
+static void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *req,
struct fsf_link_down_info *link_down)
{
struct zfcp_adapter *adapter = req->adapter;
@@ -223,7 +184,7 @@ static void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *req, char *id,
"the FC fabric is down\n");
}
out:
- zfcp_erp_adapter_failed(adapter, id, req);
+ zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_ERP_FAILED);
}
static void zfcp_fsf_status_read_link_down(struct zfcp_fsf_req *req)
@@ -234,13 +195,13 @@ static void zfcp_fsf_status_read_link_down(struct zfcp_fsf_req *req)
switch (sr_buf->status_subtype) {
case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK:
- zfcp_fsf_link_down_info_eval(req, "fssrld1", ldi);
+ zfcp_fsf_link_down_info_eval(req, ldi);
break;
case FSF_STATUS_READ_SUB_FDISC_FAILED:
- zfcp_fsf_link_down_info_eval(req, "fssrld2", ldi);
+ zfcp_fsf_link_down_info_eval(req, ldi);
break;
case FSF_STATUS_READ_SUB_FIRMWARE_UPDATE:
- zfcp_fsf_link_down_info_eval(req, "fssrld3", NULL);
+ zfcp_fsf_link_down_info_eval(req, NULL);
};
}
@@ -281,9 +242,8 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req)
dev_info(&adapter->ccw_device->dev,
"The local link has been restored\n");
/* All ports should be marked as ready to run again */
- zfcp_erp_modify_adapter_status(adapter, "fssrh_1", NULL,
- ZFCP_STATUS_COMMON_RUNNING,
- ZFCP_SET);
+ zfcp_erp_set_adapter_status(adapter,
+ ZFCP_STATUS_COMMON_RUNNING);
zfcp_erp_adapter_reopen(adapter,
ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
ZFCP_STATUS_COMMON_ERP_FAILED,
@@ -293,13 +253,12 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req)
break;
case FSF_STATUS_READ_NOTIFICATION_LOST:
if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_ACT_UPDATED)
- zfcp_erp_adapter_access_changed(adapter, "fssrh_3",
- req);
+ zfcp_cfdc_adapter_access_changed(adapter);
if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_INCOMING_ELS)
queue_work(adapter->work_queue, &adapter->scan_work);
break;
case FSF_STATUS_READ_CFDC_UPDATED:
- zfcp_erp_adapter_access_changed(adapter, "fssrh_4", req);
+ zfcp_cfdc_adapter_access_changed(adapter);
break;
case FSF_STATUS_READ_FEATURE_UPDATE_ALERT:
adapter->adapter_features = sr_buf->payload.word[0];
@@ -399,16 +358,14 @@ static void zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *req)
zfcp_erp_adapter_shutdown(adapter, 0, "fspse_4", req);
break;
case FSF_PROT_LINK_DOWN:
- zfcp_fsf_link_down_info_eval(req, "fspse_5",
- &psq->link_down_info);
+ zfcp_fsf_link_down_info_eval(req, &psq->link_down_info);
/* go through reopen to flush pending requests */
zfcp_erp_adapter_reopen(adapter, 0, "fspse_6", req);
break;
case FSF_PROT_REEST_QUEUE:
/* All ports should be marked as ready to run again */
- zfcp_erp_modify_adapter_status(adapter, "fspse_7", NULL,
- ZFCP_STATUS_COMMON_RUNNING,
- ZFCP_SET);
+ zfcp_erp_set_adapter_status(adapter,
+ ZFCP_STATUS_COMMON_RUNNING);
zfcp_erp_adapter_reopen(adapter,
ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
ZFCP_STATUS_COMMON_ERP_FAILED,
@@ -578,7 +535,7 @@ static void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req)
atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK,
&adapter->status);
- zfcp_fsf_link_down_info_eval(req, "fsecdh2",
+ zfcp_fsf_link_down_info_eval(req,
&qtcb->header.fsf_status_qual.link_down_info);
break;
default:
@@ -644,7 +601,7 @@ static void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *req)
break;
case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE:
zfcp_fsf_exchange_port_evaluate(req);
- zfcp_fsf_link_down_info_eval(req, "fsepdh1",
+ zfcp_fsf_link_down_info_eval(req,
&qtcb->header.fsf_status_qual.link_down_info);
break;
}
@@ -771,7 +728,7 @@ int zfcp_fsf_status_read(struct zfcp_qdio *qdio)
struct fsf_status_read_buffer *sr_buf;
int retval = -EIO;
- spin_lock_bh(&qdio->req_q_lock);
+ spin_lock_irq(&qdio->req_q_lock);
if (zfcp_qdio_sbal_get(qdio))
goto out;
@@ -805,13 +762,14 @@ failed_buf:
zfcp_fsf_req_free(req);
zfcp_dbf_hba_fsf_unsol("fail", adapter->dbf, NULL);
out:
- spin_unlock_bh(&qdio->req_q_lock);
+ spin_unlock_irq(&qdio->req_q_lock);
return retval;
}
static void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req)
{
- struct zfcp_unit *unit = req->data;
+ struct scsi_device *sdev = req->data;
+ struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
union fsf_status_qual *fsq = &req->qtcb->header.fsf_status_qual;
if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
@@ -820,14 +778,15 @@ static void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req)
switch (req->qtcb->header.fsf_status) {
case FSF_PORT_HANDLE_NOT_VALID:
if (fsq->word[0] == fsq->word[1]) {
- zfcp_erp_adapter_reopen(unit->port->adapter, 0,
+ zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0,
"fsafch1", req);
req->status |= ZFCP_STATUS_FSFREQ_ERROR;
}
break;
case FSF_LUN_HANDLE_NOT_VALID:
if (fsq->word[0] == fsq->word[1]) {
- zfcp_erp_port_reopen(unit->port, 0, "fsafch2", req);
+ zfcp_erp_port_reopen(zfcp_sdev->port, 0, "fsafch2",
+ req);
req->status |= ZFCP_STATUS_FSFREQ_ERROR;
}
break;
@@ -835,17 +794,23 @@ static void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req)
req->status |= ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED;
break;
case FSF_PORT_BOXED:
- zfcp_erp_port_boxed(unit->port, "fsafch3", req);
+ zfcp_erp_set_port_status(zfcp_sdev->port,
+ ZFCP_STATUS_COMMON_ACCESS_BOXED);
+ zfcp_erp_port_reopen(zfcp_sdev->port,
+ ZFCP_STATUS_COMMON_ERP_FAILED, "fsafch3",
+ req);
req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
case FSF_LUN_BOXED:
- zfcp_erp_unit_boxed(unit, "fsafch4", req);
+ zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ACCESS_BOXED);
+ zfcp_erp_lun_reopen(sdev, ZFCP_STATUS_COMMON_ERP_FAILED,
+ "fsafch4", req);
req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
case FSF_ADAPTER_STATUS_AVAILABLE:
switch (fsq->word[0]) {
case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
- zfcp_fc_test_link(unit->port);
+ zfcp_fc_test_link(zfcp_sdev->port);
/* fall through */
case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
req->status |= ZFCP_STATUS_FSFREQ_ERROR;
@@ -859,19 +824,20 @@ static void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req)
}
/**
- * zfcp_fsf_abort_fcp_command - abort running SCSI command
- * @old_req_id: unsigned long
- * @unit: pointer to struct zfcp_unit
+ * zfcp_fsf_abort_fcp_cmnd - abort running SCSI command
+ * @scmnd: The SCSI command to abort
* Returns: pointer to struct zfcp_fsf_req
*/
-struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long old_req_id,
- struct zfcp_unit *unit)
+struct zfcp_fsf_req *zfcp_fsf_abort_fcp_cmnd(struct scsi_cmnd *scmnd)
{
struct zfcp_fsf_req *req = NULL;
- struct zfcp_qdio *qdio = unit->port->adapter->qdio;
+ struct scsi_device *sdev = scmnd->device;
+ struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+ struct zfcp_qdio *qdio = zfcp_sdev->port->adapter->qdio;
+ unsigned long old_req_id = (unsigned long) scmnd->host_scribble;
- spin_lock_bh(&qdio->req_q_lock);
+ spin_lock_irq(&qdio->req_q_lock);
if (zfcp_qdio_sbal_get(qdio))
goto out;
req = zfcp_fsf_req_create(qdio, FSF_QTCB_ABORT_FCP_CMND,
@@ -882,16 +848,16 @@ struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long old_req_id,
goto out;
}
- if (unlikely(!(atomic_read(&unit->status) &
+ if (unlikely(!(atomic_read(&zfcp_sdev->status) &
ZFCP_STATUS_COMMON_UNBLOCKED)))
goto out_error_free;
zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
- req->data = unit;
+ req->data = zfcp_sdev;
req->handler = zfcp_fsf_abort_fcp_command_handler;
- req->qtcb->header.lun_handle = unit->handle;
- req->qtcb->header.port_handle = unit->port->handle;
+ req->qtcb->header.lun_handle = zfcp_sdev->lun_handle;
+ req->qtcb->header.port_handle = zfcp_sdev->port->handle;
req->qtcb->bottom.support.req_handle = (u64) old_req_id;
zfcp_fsf_start_timer(req, ZFCP_SCSI_ER_TIMEOUT);
@@ -902,7 +868,7 @@ out_error_free:
zfcp_fsf_req_free(req);
req = NULL;
out:
- spin_unlock_bh(&qdio->req_q_lock);
+ spin_unlock_irq(&qdio->req_q_lock);
return req;
}
@@ -1041,7 +1007,7 @@ int zfcp_fsf_send_ct(struct zfcp_fc_wka_port *wka_port,
struct zfcp_fsf_req *req;
int ret = -EIO;
- spin_lock_bh(&qdio->req_q_lock);
+ spin_lock_irq(&qdio->req_q_lock);
if (zfcp_qdio_sbal_get(qdio))
goto out;
@@ -1073,7 +1039,7 @@ int zfcp_fsf_send_ct(struct zfcp_fc_wka_port *wka_port,
failed_send:
zfcp_fsf_req_free(req);
out:
- spin_unlock_bh(&qdio->req_q_lock);
+ spin_unlock_irq(&qdio->req_q_lock);
return ret;
}
@@ -1111,8 +1077,10 @@ static void zfcp_fsf_send_els_handler(struct zfcp_fsf_req *req)
case FSF_RESPONSE_SIZE_TOO_LARGE:
break;
case FSF_ACCESS_DENIED:
- if (port)
- zfcp_fsf_access_denied_port(req, port);
+ if (port) {
+ zfcp_cfdc_port_denied(port, &header->fsf_status_qual);
+ req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ }
break;
case FSF_SBAL_MISMATCH:
/* should never occure, avoided in zfcp_fsf_send_els */
@@ -1137,7 +1105,7 @@ int zfcp_fsf_send_els(struct zfcp_adapter *adapter, u32 d_id,
struct zfcp_qdio *qdio = adapter->qdio;
int ret = -EIO;
- spin_lock_bh(&qdio->req_q_lock);
+ spin_lock_irq(&qdio->req_q_lock);
if (zfcp_qdio_sbal_get(qdio))
goto out;
@@ -1173,7 +1141,7 @@ int zfcp_fsf_send_els(struct zfcp_adapter *adapter, u32 d_id,
failed_send:
zfcp_fsf_req_free(req);
out:
- spin_unlock_bh(&qdio->req_q_lock);
+ spin_unlock_irq(&qdio->req_q_lock);
return ret;
}
@@ -1183,7 +1151,7 @@ int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
struct zfcp_qdio *qdio = erp_action->adapter->qdio;
int retval = -EIO;
- spin_lock_bh(&qdio->req_q_lock);
+ spin_lock_irq(&qdio->req_q_lock);
if (zfcp_qdio_sbal_get(qdio))
goto out;
@@ -1215,7 +1183,7 @@ int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
erp_action->fsf_req_id = 0;
}
out:
- spin_unlock_bh(&qdio->req_q_lock);
+ spin_unlock_irq(&qdio->req_q_lock);
return retval;
}
@@ -1225,7 +1193,7 @@ int zfcp_fsf_exchange_config_data_sync(struct zfcp_qdio *qdio,
struct zfcp_fsf_req *req = NULL;
int retval = -EIO;
- spin_lock_bh(&qdio->req_q_lock);
+ spin_lock_irq(&qdio->req_q_lock);
if (zfcp_qdio_sbal_get(qdio))
goto out_unlock;
@@ -1251,7 +1219,7 @@ int zfcp_fsf_exchange_config_data_sync(struct zfcp_qdio *qdio,
zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
retval = zfcp_fsf_req_send(req);
- spin_unlock_bh(&qdio->req_q_lock);
+ spin_unlock_irq(&qdio->req_q_lock);
if (!retval)
wait_for_completion(&req->completion);
@@ -1259,7 +1227,7 @@ int zfcp_fsf_exchange_config_data_sync(struct zfcp_qdio *qdio,
return retval;
out_unlock:
- spin_unlock_bh(&qdio->req_q_lock);
+ spin_unlock_irq(&qdio->req_q_lock);
return retval;
}
@@ -1277,7 +1245,7 @@ int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action)
if (!(qdio->adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT))
return -EOPNOTSUPP;
- spin_lock_bh(&qdio->req_q_lock);
+ spin_lock_irq(&qdio->req_q_lock);
if (zfcp_qdio_sbal_get(qdio))
goto out;
@@ -1304,7 +1272,7 @@ int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action)
erp_action->fsf_req_id = 0;
}
out:
- spin_unlock_bh(&qdio->req_q_lock);
+ spin_unlock_irq(&qdio->req_q_lock);
return retval;
}
@@ -1323,7 +1291,7 @@ int zfcp_fsf_exchange_port_data_sync(struct zfcp_qdio *qdio,
if (!(qdio->adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT))
return -EOPNOTSUPP;
- spin_lock_bh(&qdio->req_q_lock);
+ spin_lock_irq(&qdio->req_q_lock);
if (zfcp_qdio_sbal_get(qdio))
goto out_unlock;
@@ -1343,7 +1311,7 @@ int zfcp_fsf_exchange_port_data_sync(struct zfcp_qdio *qdio,
req->handler = zfcp_fsf_exchange_port_data_handler;
zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
retval = zfcp_fsf_req_send(req);
- spin_unlock_bh(&qdio->req_q_lock);
+ spin_unlock_irq(&qdio->req_q_lock);
if (!retval)
wait_for_completion(&req->completion);
@@ -1353,7 +1321,7 @@ int zfcp_fsf_exchange_port_data_sync(struct zfcp_qdio *qdio,
return retval;
out_unlock:
- spin_unlock_bh(&qdio->req_q_lock);
+ spin_unlock_irq(&qdio->req_q_lock);
return retval;
}
@@ -1370,14 +1338,16 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req)
case FSF_PORT_ALREADY_OPEN:
break;
case FSF_ACCESS_DENIED:
- zfcp_fsf_access_denied_port(req, port);
+ zfcp_cfdc_port_denied(port, &header->fsf_status_qual);
+ req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
case FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED:
dev_warn(&req->adapter->ccw_device->dev,
"Not enough FCP adapter resources to open "
"remote port 0x%016Lx\n",
(unsigned long long)port->wwpn);
- zfcp_erp_port_failed(port, "fsoph_1", req);
+ zfcp_erp_set_port_status(port,
+ ZFCP_STATUS_COMMON_ERP_FAILED);
req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
case FSF_ADAPTER_STATUS_AVAILABLE:
@@ -1437,7 +1407,7 @@ int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action)
struct zfcp_fsf_req *req;
int retval = -EIO;
- spin_lock_bh(&qdio->req_q_lock);
+ spin_lock_irq(&qdio->req_q_lock);
if (zfcp_qdio_sbal_get(qdio))
goto out;
@@ -1468,7 +1438,7 @@ int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action)
put_device(&port->dev);
}
out:
- spin_unlock_bh(&qdio->req_q_lock);
+ spin_unlock_irq(&qdio->req_q_lock);
return retval;
}
@@ -1487,9 +1457,7 @@ static void zfcp_fsf_close_port_handler(struct zfcp_fsf_req *req)
case FSF_ADAPTER_STATUS_AVAILABLE:
break;
case FSF_GOOD:
- zfcp_erp_modify_port_status(port, "fscph_2", req,
- ZFCP_STATUS_COMMON_OPEN,
- ZFCP_CLEAR);
+ zfcp_erp_clear_port_status(port, ZFCP_STATUS_COMMON_OPEN);
break;
}
}
@@ -1505,7 +1473,7 @@ int zfcp_fsf_close_port(struct zfcp_erp_action *erp_action)
struct zfcp_fsf_req *req;
int retval = -EIO;
- spin_lock_bh(&qdio->req_q_lock);
+ spin_lock_irq(&qdio->req_q_lock);
if (zfcp_qdio_sbal_get(qdio))
goto out;
@@ -1534,7 +1502,7 @@ int zfcp_fsf_close_port(struct zfcp_erp_action *erp_action)
erp_action->fsf_req_id = 0;
}
out:
- spin_unlock_bh(&qdio->req_q_lock);
+ spin_unlock_irq(&qdio->req_q_lock);
return retval;
}
@@ -1580,7 +1548,7 @@ int zfcp_fsf_open_wka_port(struct zfcp_fc_wka_port *wka_port)
struct zfcp_fsf_req *req;
int retval = -EIO;
- spin_lock_bh(&qdio->req_q_lock);
+ spin_lock_irq(&qdio->req_q_lock);
if (zfcp_qdio_sbal_get(qdio))
goto out;
@@ -1605,7 +1573,7 @@ int zfcp_fsf_open_wka_port(struct zfcp_fc_wka_port *wka_port)
if (retval)
zfcp_fsf_req_free(req);
out:
- spin_unlock_bh(&qdio->req_q_lock);
+ spin_unlock_irq(&qdio->req_q_lock);
return retval;
}
@@ -1633,7 +1601,7 @@ int zfcp_fsf_close_wka_port(struct zfcp_fc_wka_port *wka_port)
struct zfcp_fsf_req *req;
int retval = -EIO;
- spin_lock_bh(&qdio->req_q_lock);
+ spin_lock_irq(&qdio->req_q_lock);
if (zfcp_qdio_sbal_get(qdio))
goto out;
@@ -1658,7 +1626,7 @@ int zfcp_fsf_close_wka_port(struct zfcp_fc_wka_port *wka_port)
if (retval)
zfcp_fsf_req_free(req);
out:
- spin_unlock_bh(&qdio->req_q_lock);
+ spin_unlock_irq(&qdio->req_q_lock);
return retval;
}
@@ -1666,7 +1634,7 @@ static void zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *req)
{
struct zfcp_port *port = req->data;
struct fsf_qtcb_header *header = &req->qtcb->header;
- struct zfcp_unit *unit;
+ struct scsi_device *sdev;
if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
return;
@@ -1677,18 +1645,19 @@ static void zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *req)
req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
case FSF_ACCESS_DENIED:
- zfcp_fsf_access_denied_port(req, port);
+ zfcp_cfdc_port_denied(port, &header->fsf_status_qual);
break;
case FSF_PORT_BOXED:
/* can't use generic zfcp_erp_modify_port_status because
* ZFCP_STATUS_COMMON_OPEN must not be reset for the port */
atomic_clear_mask(ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
- read_lock(&port->unit_list_lock);
- list_for_each_entry(unit, &port->unit_list, list)
- atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN,
- &unit->status);
- read_unlock(&port->unit_list_lock);
- zfcp_erp_port_boxed(port, "fscpph2", req);
+ shost_for_each_device(sdev, port->adapter->scsi_host)
+ if (sdev_to_zfcp(sdev)->port == port)
+ atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN,
+ &sdev_to_zfcp(sdev)->status);
+ zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_ACCESS_BOXED);
+ zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED,
+ "fscpph2", req);
req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
case FSF_ADAPTER_STATUS_AVAILABLE:
@@ -1705,11 +1674,10 @@ static void zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *req)
* ZFCP_STATUS_COMMON_OPEN must not be reset for the port
*/
atomic_clear_mask(ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
- read_lock(&port->unit_list_lock);
- list_for_each_entry(unit, &port->unit_list, list)
- atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN,
- &unit->status);
- read_unlock(&port->unit_list_lock);
+ shost_for_each_device(sdev, port->adapter->scsi_host)
+ if (sdev_to_zfcp(sdev)->port == port)
+ atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN,
+ &sdev_to_zfcp(sdev)->status);
break;
}
}
@@ -1725,7 +1693,7 @@ int zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action)
struct zfcp_fsf_req *req;
int retval = -EIO;
- spin_lock_bh(&qdio->req_q_lock);
+ spin_lock_irq(&qdio->req_q_lock);
if (zfcp_qdio_sbal_get(qdio))
goto out;
@@ -1754,69 +1722,57 @@ int zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action)
erp_action->fsf_req_id = 0;
}
out:
- spin_unlock_bh(&qdio->req_q_lock);
+ spin_unlock_irq(&qdio->req_q_lock);
return retval;
}
-static void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req)
+static void zfcp_fsf_open_lun_handler(struct zfcp_fsf_req *req)
{
struct zfcp_adapter *adapter = req->adapter;
- struct zfcp_unit *unit = req->data;
+ struct scsi_device *sdev = req->data;
+ struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
struct fsf_qtcb_header *header = &req->qtcb->header;
struct fsf_qtcb_bottom_support *bottom = &req->qtcb->bottom.support;
- struct fsf_queue_designator *queue_designator =
- &header->fsf_status_qual.fsf_queue_designator;
- int exclusive, readwrite;
if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
return;
atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
ZFCP_STATUS_COMMON_ACCESS_BOXED |
- ZFCP_STATUS_UNIT_SHARED |
- ZFCP_STATUS_UNIT_READONLY,
- &unit->status);
+ ZFCP_STATUS_LUN_SHARED |
+ ZFCP_STATUS_LUN_READONLY,
+ &zfcp_sdev->status);
switch (header->fsf_status) {
case FSF_PORT_HANDLE_NOT_VALID:
- zfcp_erp_adapter_reopen(unit->port->adapter, 0, "fsouh_1", req);
+ zfcp_erp_adapter_reopen(adapter, 0, "fsouh_1", req);
/* fall through */
case FSF_LUN_ALREADY_OPEN:
break;
case FSF_ACCESS_DENIED:
- zfcp_fsf_access_denied_unit(req, unit);
- atomic_clear_mask(ZFCP_STATUS_UNIT_SHARED, &unit->status);
- atomic_clear_mask(ZFCP_STATUS_UNIT_READONLY, &unit->status);
+ zfcp_cfdc_lun_denied(sdev, &header->fsf_status_qual);
+ req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
case FSF_PORT_BOXED:
- zfcp_erp_port_boxed(unit->port, "fsouh_2", req);
+ zfcp_erp_set_port_status(zfcp_sdev->port,
+ ZFCP_STATUS_COMMON_ACCESS_BOXED);
+ zfcp_erp_port_reopen(zfcp_sdev->port,
+ ZFCP_STATUS_COMMON_ERP_FAILED, "fsouh_2",
+ req);
req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
case FSF_LUN_SHARING_VIOLATION:
- if (header->fsf_status_qual.word[0])
- dev_warn(&adapter->ccw_device->dev,
- "LUN 0x%Lx on port 0x%Lx is already in "
- "use by CSS%d, MIF Image ID %x\n",
- (unsigned long long)unit->fcp_lun,
- (unsigned long long)unit->port->wwpn,
- queue_designator->cssid,
- queue_designator->hla);
- else
- zfcp_act_eval_err(adapter,
- header->fsf_status_qual.word[2]);
- zfcp_erp_unit_access_denied(unit, "fsouh_3", req);
- atomic_clear_mask(ZFCP_STATUS_UNIT_SHARED, &unit->status);
- atomic_clear_mask(ZFCP_STATUS_UNIT_READONLY, &unit->status);
+ zfcp_cfdc_lun_shrng_vltn(sdev, &header->fsf_status_qual);
req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
case FSF_MAXIMUM_NUMBER_OF_LUNS_EXCEEDED:
dev_warn(&adapter->ccw_device->dev,
"No handle is available for LUN "
"0x%016Lx on port 0x%016Lx\n",
- (unsigned long long)unit->fcp_lun,
- (unsigned long long)unit->port->wwpn);
- zfcp_erp_unit_failed(unit, "fsouh_4", req);
+ (unsigned long long)zfcp_scsi_dev_lun(sdev),
+ (unsigned long long)zfcp_sdev->port->wwpn);
+ zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ERP_FAILED);
/* fall through */
case FSF_INVALID_COMMAND_OPTION:
req->status |= ZFCP_STATUS_FSFREQ_ERROR;
@@ -1824,7 +1780,7 @@ static void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req)
case FSF_ADAPTER_STATUS_AVAILABLE:
switch (header->fsf_status_qual.word[0]) {
case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
- zfcp_fc_test_link(unit->port);
+ zfcp_fc_test_link(zfcp_sdev->port);
/* fall through */
case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
req->status |= ZFCP_STATUS_FSFREQ_ERROR;
@@ -1833,70 +1789,26 @@ static void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req)
break;
case FSF_GOOD:
- unit->handle = header->lun_handle;
- atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status);
-
- if (!(adapter->connection_features & FSF_FEATURE_NPIV_MODE) &&
- (adapter->adapter_features & FSF_FEATURE_LUN_SHARING) &&
- !zfcp_ccw_priv_sch(adapter)) {
- exclusive = (bottom->lun_access_info &
- FSF_UNIT_ACCESS_EXCLUSIVE);
- readwrite = (bottom->lun_access_info &
- FSF_UNIT_ACCESS_OUTBOUND_TRANSFER);
-
- if (!exclusive)
- atomic_set_mask(ZFCP_STATUS_UNIT_SHARED,
- &unit->status);
-
- if (!readwrite) {
- atomic_set_mask(ZFCP_STATUS_UNIT_READONLY,
- &unit->status);
- dev_info(&adapter->ccw_device->dev,
- "SCSI device at LUN 0x%016Lx on port "
- "0x%016Lx opened read-only\n",
- (unsigned long long)unit->fcp_lun,
- (unsigned long long)unit->port->wwpn);
- }
-
- if (exclusive && !readwrite) {
- dev_err(&adapter->ccw_device->dev,
- "Exclusive read-only access not "
- "supported (unit 0x%016Lx, "
- "port 0x%016Lx)\n",
- (unsigned long long)unit->fcp_lun,
- (unsigned long long)unit->port->wwpn);
- zfcp_erp_unit_failed(unit, "fsouh_5", req);
- req->status |= ZFCP_STATUS_FSFREQ_ERROR;
- zfcp_erp_unit_shutdown(unit, 0, "fsouh_6", req);
- } else if (!exclusive && readwrite) {
- dev_err(&adapter->ccw_device->dev,
- "Shared read-write access not "
- "supported (unit 0x%016Lx, port "
- "0x%016Lx)\n",
- (unsigned long long)unit->fcp_lun,
- (unsigned long long)unit->port->wwpn);
- zfcp_erp_unit_failed(unit, "fsouh_7", req);
- req->status |= ZFCP_STATUS_FSFREQ_ERROR;
- zfcp_erp_unit_shutdown(unit, 0, "fsouh_8", req);
- }
- }
+ zfcp_sdev->lun_handle = header->lun_handle;
+ atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &zfcp_sdev->status);
+ zfcp_cfdc_open_lun_eval(sdev, bottom);
break;
}
}
/**
- * zfcp_fsf_open_unit - open unit
+ * zfcp_fsf_open_lun - open LUN
* @erp_action: pointer to struct zfcp_erp_action
* Returns: 0 on success, error otherwise
*/
-int zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action)
+int zfcp_fsf_open_lun(struct zfcp_erp_action *erp_action)
{
struct zfcp_adapter *adapter = erp_action->adapter;
struct zfcp_qdio *qdio = adapter->qdio;
struct zfcp_fsf_req *req;
int retval = -EIO;
- spin_lock_bh(&qdio->req_q_lock);
+ spin_lock_irq(&qdio->req_q_lock);
if (zfcp_qdio_sbal_get(qdio))
goto out;
@@ -1913,9 +1825,9 @@ int zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action)
zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
req->qtcb->header.port_handle = erp_action->port->handle;
- req->qtcb->bottom.support.fcp_lun = erp_action->unit->fcp_lun;
- req->handler = zfcp_fsf_open_unit_handler;
- req->data = erp_action->unit;
+ req->qtcb->bottom.support.fcp_lun = zfcp_scsi_dev_lun(erp_action->sdev);
+ req->handler = zfcp_fsf_open_lun_handler;
+ req->data = erp_action->sdev;
req->erp_action = erp_action;
erp_action->fsf_req_id = req->req_id;
@@ -1929,34 +1841,40 @@ int zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action)
erp_action->fsf_req_id = 0;
}
out:
- spin_unlock_bh(&qdio->req_q_lock);
+ spin_unlock_irq(&qdio->req_q_lock);
return retval;
}
-static void zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *req)
+static void zfcp_fsf_close_lun_handler(struct zfcp_fsf_req *req)
{
- struct zfcp_unit *unit = req->data;
+ struct scsi_device *sdev = req->data;
+ struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
return;
switch (req->qtcb->header.fsf_status) {
case FSF_PORT_HANDLE_NOT_VALID:
- zfcp_erp_adapter_reopen(unit->port->adapter, 0, "fscuh_1", req);
+ zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0, "fscuh_1",
+ req);
req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
case FSF_LUN_HANDLE_NOT_VALID:
- zfcp_erp_port_reopen(unit->port, 0, "fscuh_2", req);
+ zfcp_erp_port_reopen(zfcp_sdev->port, 0, "fscuh_2", req);
req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
case FSF_PORT_BOXED:
- zfcp_erp_port_boxed(unit->port, "fscuh_3", req);
+ zfcp_erp_set_port_status(zfcp_sdev->port,
+ ZFCP_STATUS_COMMON_ACCESS_BOXED);
+ zfcp_erp_port_reopen(zfcp_sdev->port,
+ ZFCP_STATUS_COMMON_ERP_FAILED, "fscuh_3",
+ req);
req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
case FSF_ADAPTER_STATUS_AVAILABLE:
switch (req->qtcb->header.fsf_status_qual.word[0]) {
case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
- zfcp_fc_test_link(unit->port);
+ zfcp_fc_test_link(zfcp_sdev->port);
/* fall through */
case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
req->status |= ZFCP_STATUS_FSFREQ_ERROR;
@@ -1964,23 +1882,24 @@ static void zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *req)
}
break;
case FSF_GOOD:
- atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status);
+ atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN, &zfcp_sdev->status);
break;
}
}
/**
- * zfcp_fsf_close_unit - close zfcp unit
- * @erp_action: pointer to struct zfcp_unit
+ * zfcp_fsf_close_LUN - close LUN
+ * @erp_action: pointer to erp_action triggering the "close LUN"
* Returns: 0 on success, error otherwise
*/
-int zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action)
+int zfcp_fsf_close_lun(struct zfcp_erp_action *erp_action)
{
struct zfcp_qdio *qdio = erp_action->adapter->qdio;
+ struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(erp_action->sdev);
struct zfcp_fsf_req *req;
int retval = -EIO;
- spin_lock_bh(&qdio->req_q_lock);
+ spin_lock_irq(&qdio->req_q_lock);
if (zfcp_qdio_sbal_get(qdio))
goto out;
@@ -1997,9 +1916,9 @@ int zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action)
zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
req->qtcb->header.port_handle = erp_action->port->handle;
- req->qtcb->header.lun_handle = erp_action->unit->handle;
- req->handler = zfcp_fsf_close_unit_handler;
- req->data = erp_action->unit;
+ req->qtcb->header.lun_handle = zfcp_sdev->lun_handle;
+ req->handler = zfcp_fsf_close_lun_handler;
+ req->data = erp_action->sdev;
req->erp_action = erp_action;
erp_action->fsf_req_id = req->req_id;
@@ -2010,7 +1929,7 @@ int zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action)
erp_action->fsf_req_id = 0;
}
out:
- spin_unlock_bh(&qdio->req_q_lock);
+ spin_unlock_irq(&qdio->req_q_lock);
return retval;
}
@@ -2025,7 +1944,7 @@ static void zfcp_fsf_req_trace(struct zfcp_fsf_req *req, struct scsi_cmnd *scsi)
{
struct fsf_qual_latency_info *lat_in;
struct latency_cont *lat = NULL;
- struct zfcp_unit *unit = req->unit;
+ struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scsi->device);
struct zfcp_blk_drv_data blktrc;
int ticks = req->adapter->timer_ticks;
@@ -2048,24 +1967,24 @@ static void zfcp_fsf_req_trace(struct zfcp_fsf_req *req, struct scsi_cmnd *scsi)
case FSF_DATADIR_DIF_READ_STRIP:
case FSF_DATADIR_DIF_READ_CONVERT:
case FSF_DATADIR_READ:
- lat = &unit->latencies.read;
+ lat = &zfcp_sdev->latencies.read;
break;
case FSF_DATADIR_DIF_WRITE_INSERT:
case FSF_DATADIR_DIF_WRITE_CONVERT:
case FSF_DATADIR_WRITE:
- lat = &unit->latencies.write;
+ lat = &zfcp_sdev->latencies.write;
break;
case FSF_DATADIR_CMND:
- lat = &unit->latencies.cmd;
+ lat = &zfcp_sdev->latencies.cmd;
break;
}
if (lat) {
- spin_lock(&unit->latencies.lock);
+ spin_lock(&zfcp_sdev->latencies.lock);
zfcp_fsf_update_lat(&lat->channel, lat_in->channel_lat);
zfcp_fsf_update_lat(&lat->fabric, lat_in->fabric_lat);
lat->counter++;
- spin_unlock(&unit->latencies.lock);
+ spin_unlock(&zfcp_sdev->latencies.lock);
}
}
@@ -2073,12 +1992,88 @@ static void zfcp_fsf_req_trace(struct zfcp_fsf_req *req, struct scsi_cmnd *scsi)
sizeof(blktrc));
}
-static void zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *req)
+static void zfcp_fsf_fcp_handler_common(struct zfcp_fsf_req *req)
+{
+ struct scsi_cmnd *scmnd = req->data;
+ struct scsi_device *sdev = scmnd->device;
+ struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+ struct fsf_qtcb_header *header = &req->qtcb->header;
+
+ if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR))
+ return;
+
+ switch (header->fsf_status) {
+ case FSF_HANDLE_MISMATCH:
+ case FSF_PORT_HANDLE_NOT_VALID:
+ zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0, "fssfch1",
+ req);
+ req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+ case FSF_FCPLUN_NOT_VALID:
+ case FSF_LUN_HANDLE_NOT_VALID:
+ zfcp_erp_port_reopen(zfcp_sdev->port, 0, "fssfch2", req);
+ req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+ case FSF_SERVICE_CLASS_NOT_SUPPORTED:
+ zfcp_fsf_class_not_supp(req);
+ break;
+ case FSF_ACCESS_DENIED:
+ zfcp_cfdc_lun_denied(sdev, &header->fsf_status_qual);
+ req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+ case FSF_DIRECTION_INDICATOR_NOT_VALID:
+ dev_err(&req->adapter->ccw_device->dev,
+ "Incorrect direction %d, LUN 0x%016Lx on port "
+ "0x%016Lx closed\n",
+ req->qtcb->bottom.io.data_direction,
+ (unsigned long long)zfcp_scsi_dev_lun(sdev),
+ (unsigned long long)zfcp_sdev->port->wwpn);
+ zfcp_erp_adapter_shutdown(zfcp_sdev->port->adapter, 0,
+ "fssfch3", req);
+ req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+ case FSF_CMND_LENGTH_NOT_VALID:
+ dev_err(&req->adapter->ccw_device->dev,
+ "Incorrect CDB length %d, LUN 0x%016Lx on "
+ "port 0x%016Lx closed\n",
+ req->qtcb->bottom.io.fcp_cmnd_length,
+ (unsigned long long)zfcp_scsi_dev_lun(sdev),
+ (unsigned long long)zfcp_sdev->port->wwpn);
+ zfcp_erp_adapter_shutdown(zfcp_sdev->port->adapter, 0,
+ "fssfch4", req);
+ req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+ case FSF_PORT_BOXED:
+ zfcp_erp_set_port_status(zfcp_sdev->port,
+ ZFCP_STATUS_COMMON_ACCESS_BOXED);
+ zfcp_erp_port_reopen(zfcp_sdev->port,
+ ZFCP_STATUS_COMMON_ERP_FAILED, "fssfch5",
+ req);
+ req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+ case FSF_LUN_BOXED:
+ zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ACCESS_BOXED);
+ zfcp_erp_lun_reopen(sdev, ZFCP_STATUS_COMMON_ERP_FAILED,
+ "fssfch6", req);
+ req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+ case FSF_ADAPTER_STATUS_AVAILABLE:
+ if (header->fsf_status_qual.word[0] ==
+ FSF_SQ_INVOKE_LINK_TEST_PROCEDURE)
+ zfcp_fc_test_link(zfcp_sdev->port);
+ req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+ }
+}
+
+static void zfcp_fsf_fcp_cmnd_handler(struct zfcp_fsf_req *req)
{
struct scsi_cmnd *scpnt;
struct fcp_resp_with_ext *fcp_rsp;
unsigned long flags;
+ zfcp_fsf_fcp_handler_common(req);
+
read_lock_irqsave(&req->adapter->abort_lock, flags);
scpnt = req->data;
@@ -2125,97 +2120,6 @@ skip_fsfstatus:
read_unlock_irqrestore(&req->adapter->abort_lock, flags);
}
-static void zfcp_fsf_send_fcp_ctm_handler(struct zfcp_fsf_req *req)
-{
- struct fcp_resp_with_ext *fcp_rsp;
- struct fcp_resp_rsp_info *rsp_info;
-
- fcp_rsp = (struct fcp_resp_with_ext *) &req->qtcb->bottom.io.fcp_rsp;
- rsp_info = (struct fcp_resp_rsp_info *) &fcp_rsp[1];
-
- if ((rsp_info->rsp_code != FCP_TMF_CMPL) ||
- (req->status & ZFCP_STATUS_FSFREQ_ERROR))
- req->status |= ZFCP_STATUS_FSFREQ_TMFUNCFAILED;
-}
-
-
-static void zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *req)
-{
- struct zfcp_unit *unit;
- struct fsf_qtcb_header *header = &req->qtcb->header;
-
- if (unlikely(req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT))
- unit = req->data;
- else
- unit = req->unit;
-
- if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR))
- goto skip_fsfstatus;
-
- switch (header->fsf_status) {
- case FSF_HANDLE_MISMATCH:
- case FSF_PORT_HANDLE_NOT_VALID:
- zfcp_erp_adapter_reopen(unit->port->adapter, 0, "fssfch1", req);
- req->status |= ZFCP_STATUS_FSFREQ_ERROR;
- break;
- case FSF_FCPLUN_NOT_VALID:
- case FSF_LUN_HANDLE_NOT_VALID:
- zfcp_erp_port_reopen(unit->port, 0, "fssfch2", req);
- req->status |= ZFCP_STATUS_FSFREQ_ERROR;
- break;
- case FSF_SERVICE_CLASS_NOT_SUPPORTED:
- zfcp_fsf_class_not_supp(req);
- break;
- case FSF_ACCESS_DENIED:
- zfcp_fsf_access_denied_unit(req, unit);
- break;
- case FSF_DIRECTION_INDICATOR_NOT_VALID:
- dev_err(&req->adapter->ccw_device->dev,
- "Incorrect direction %d, unit 0x%016Lx on port "
- "0x%016Lx closed\n",
- req->qtcb->bottom.io.data_direction,
- (unsigned long long)unit->fcp_lun,
- (unsigned long long)unit->port->wwpn);
- zfcp_erp_adapter_shutdown(unit->port->adapter, 0, "fssfch3",
- req);
- req->status |= ZFCP_STATUS_FSFREQ_ERROR;
- break;
- case FSF_CMND_LENGTH_NOT_VALID:
- dev_err(&req->adapter->ccw_device->dev,
- "Incorrect CDB length %d, unit 0x%016Lx on "
- "port 0x%016Lx closed\n",
- req->qtcb->bottom.io.fcp_cmnd_length,
- (unsigned long long)unit->fcp_lun,
- (unsigned long long)unit->port->wwpn);
- zfcp_erp_adapter_shutdown(unit->port->adapter, 0, "fssfch4",
- req);
- req->status |= ZFCP_STATUS_FSFREQ_ERROR;
- break;
- case FSF_PORT_BOXED:
- zfcp_erp_port_boxed(unit->port, "fssfch5", req);
- req->status |= ZFCP_STATUS_FSFREQ_ERROR;
- break;
- case FSF_LUN_BOXED:
- zfcp_erp_unit_boxed(unit, "fssfch6", req);
- req->status |= ZFCP_STATUS_FSFREQ_ERROR;
- break;
- case FSF_ADAPTER_STATUS_AVAILABLE:
- if (header->fsf_status_qual.word[0] ==
- FSF_SQ_INVOKE_LINK_TEST_PROCEDURE)
- zfcp_fc_test_link(unit->port);
- req->status |= ZFCP_STATUS_FSFREQ_ERROR;
- break;
- }
-skip_fsfstatus:
- if (req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT)
- zfcp_fsf_send_fcp_ctm_handler(req);
- else {
- zfcp_fsf_send_fcp_command_task_handler(req);
- req->unit = NULL;
- put_device(&unit->dev);
- }
-}
-
static int zfcp_fsf_set_data_dir(struct scsi_cmnd *scsi_cmnd, u32 *data_dir)
{
switch (scsi_get_prot_op(scsi_cmnd)) {
@@ -2255,22 +2159,22 @@ static int zfcp_fsf_set_data_dir(struct scsi_cmnd *scsi_cmnd, u32 *data_dir)
}
/**
- * zfcp_fsf_send_fcp_command_task - initiate an FCP command (for a SCSI command)
- * @unit: unit where command is sent to
+ * zfcp_fsf_fcp_cmnd - initiate an FCP command (for a SCSI command)
* @scsi_cmnd: scsi command to be sent
*/
-int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit,
- struct scsi_cmnd *scsi_cmnd)
+int zfcp_fsf_fcp_cmnd(struct scsi_cmnd *scsi_cmnd)
{
struct zfcp_fsf_req *req;
struct fcp_cmnd *fcp_cmnd;
unsigned int sbtype = SBAL_FLAGS0_TYPE_READ;
int real_bytes, retval = -EIO, dix_bytes = 0;
- struct zfcp_adapter *adapter = unit->port->adapter;
+ struct scsi_device *sdev = scsi_cmnd->device;
+ struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+ struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
struct zfcp_qdio *qdio = adapter->qdio;
struct fsf_qtcb_bottom_io *io;
- if (unlikely(!(atomic_read(&unit->status) &
+ if (unlikely(!(atomic_read(&zfcp_sdev->status) &
ZFCP_STATUS_COMMON_UNBLOCKED)))
return -EBUSY;
@@ -2295,11 +2199,10 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit,
io = &req->qtcb->bottom.io;
req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
- req->unit = unit;
req->data = scsi_cmnd;
- req->handler = zfcp_fsf_send_fcp_command_handler;
- req->qtcb->header.lun_handle = unit->handle;
- req->qtcb->header.port_handle = unit->port->handle;
+ req->handler = zfcp_fsf_fcp_cmnd_handler;
+ req->qtcb->header.lun_handle = zfcp_sdev->lun_handle;
+ req->qtcb->header.port_handle = zfcp_sdev->port->handle;
io->service_class = FSF_CLASS_3;
io->fcp_cmnd_length = FCP_CMND_LEN;
@@ -2310,8 +2213,6 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit,
zfcp_fsf_set_data_dir(scsi_cmnd, &io->data_direction);
- get_device(&unit->dev);
-
fcp_cmnd = (struct fcp_cmnd *) &req->qtcb->bottom.io.fcp_cmnd;
zfcp_fc_scsi_to_fcp(fcp_cmnd, scsi_cmnd);
@@ -2338,7 +2239,6 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit,
goto out;
failed_scsi_cmnd:
- put_device(&unit->dev);
zfcp_fsf_req_free(req);
scsi_cmnd->host_scribble = NULL;
out:
@@ -2346,23 +2246,40 @@ out:
return retval;
}
+static void zfcp_fsf_fcp_task_mgmt_handler(struct zfcp_fsf_req *req)
+{
+ struct fcp_resp_with_ext *fcp_rsp;
+ struct fcp_resp_rsp_info *rsp_info;
+
+ zfcp_fsf_fcp_handler_common(req);
+
+ fcp_rsp = (struct fcp_resp_with_ext *) &req->qtcb->bottom.io.fcp_rsp;
+ rsp_info = (struct fcp_resp_rsp_info *) &fcp_rsp[1];
+
+ if ((rsp_info->rsp_code != FCP_TMF_CMPL) ||
+ (req->status & ZFCP_STATUS_FSFREQ_ERROR))
+ req->status |= ZFCP_STATUS_FSFREQ_TMFUNCFAILED;
+}
+
/**
- * zfcp_fsf_send_fcp_ctm - send SCSI task management command
- * @unit: pointer to struct zfcp_unit
+ * zfcp_fsf_fcp_task_mgmt - send SCSI task management command
+ * @scmnd: SCSI command to send the task management command for
* @tm_flags: unsigned byte for task management flags
* Returns: on success pointer to struct fsf_req, NULL otherwise
*/
-struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *unit, u8 tm_flags)
+struct zfcp_fsf_req *zfcp_fsf_fcp_task_mgmt(struct scsi_cmnd *scmnd,
+ u8 tm_flags)
{
struct zfcp_fsf_req *req = NULL;
struct fcp_cmnd *fcp_cmnd;
- struct zfcp_qdio *qdio = unit->port->adapter->qdio;
+ struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scmnd->device);
+ struct zfcp_qdio *qdio = zfcp_sdev->port->adapter->qdio;
- if (unlikely(!(atomic_read(&unit->status) &
+ if (unlikely(!(atomic_read(&zfcp_sdev->status) &
ZFCP_STATUS_COMMON_UNBLOCKED)))
return NULL;
- spin_lock_bh(&qdio->req_q_lock);
+ spin_lock_irq(&qdio->req_q_lock);
if (zfcp_qdio_sbal_get(qdio))
goto out;
@@ -2376,10 +2293,10 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *unit, u8 tm_flags)
}
req->status |= ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT;
- req->data = unit;
- req->handler = zfcp_fsf_send_fcp_command_handler;
- req->qtcb->header.lun_handle = unit->handle;
- req->qtcb->header.port_handle = unit->port->handle;
+ req->data = scmnd;
+ req->handler = zfcp_fsf_fcp_task_mgmt_handler;
+ req->qtcb->header.lun_handle = zfcp_sdev->lun_handle;
+ req->qtcb->header.port_handle = zfcp_sdev->port->handle;
req->qtcb->bottom.io.data_direction = FSF_DATADIR_CMND;
req->qtcb->bottom.io.service_class = FSF_CLASS_3;
req->qtcb->bottom.io.fcp_cmnd_length = FCP_CMND_LEN;
@@ -2387,7 +2304,7 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *unit, u8 tm_flags)
zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
fcp_cmnd = (struct fcp_cmnd *) &req->qtcb->bottom.io.fcp_cmnd;
- zfcp_fc_fcp_tm(fcp_cmnd, unit->device, tm_flags);
+ zfcp_fc_fcp_tm(fcp_cmnd, scmnd->device, tm_flags);
zfcp_fsf_start_timer(req, ZFCP_SCSI_ER_TIMEOUT);
if (!zfcp_fsf_req_send(req))
@@ -2396,7 +2313,7 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *unit, u8 tm_flags)
zfcp_fsf_req_free(req);
req = NULL;
out:
- spin_unlock_bh(&qdio->req_q_lock);
+ spin_unlock_irq(&qdio->req_q_lock);
return req;
}
@@ -2432,7 +2349,7 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
return ERR_PTR(-EINVAL);
}
- spin_lock_bh(&qdio->req_q_lock);
+ spin_lock_irq(&qdio->req_q_lock);
if (zfcp_qdio_sbal_get(qdio))
goto out;
@@ -2459,7 +2376,7 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
retval = zfcp_fsf_req_send(req);
out:
- spin_unlock_bh(&qdio->req_q_lock);
+ spin_unlock_irq(&qdio->req_q_lock);
if (!retval) {
wait_for_completion(&req->completion);
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c
index b2635759721c..a0554beb4179 100644
--- a/drivers/s390/scsi/zfcp_qdio.c
+++ b/drivers/s390/scsi/zfcp_qdio.c
@@ -60,13 +60,11 @@ static inline void zfcp_qdio_account(struct zfcp_qdio *qdio)
unsigned long long now, span;
int used;
- spin_lock(&qdio->stat_lock);
now = get_clock_monotonic();
span = (now - qdio->req_q_time) >> 12;
used = QDIO_MAX_BUFFERS_PER_Q - atomic_read(&qdio->req_q_free);
qdio->req_q_util += used * span;
qdio->req_q_time = now;
- spin_unlock(&qdio->stat_lock);
}
static void zfcp_qdio_int_req(struct ccw_device *cdev, unsigned int qdio_err,
@@ -84,7 +82,9 @@ static void zfcp_qdio_int_req(struct ccw_device *cdev, unsigned int qdio_err,
/* cleanup all SBALs being program-owned now */
zfcp_qdio_zero_sbals(qdio->req_q, idx, count);
+ spin_lock_irq(&qdio->stat_lock);
zfcp_qdio_account(qdio);
+ spin_unlock_irq(&qdio->stat_lock);
atomic_add(count, &qdio->req_q_free);
wake_up(&qdio->req_q_wq);
}
@@ -201,11 +201,11 @@ int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
static int zfcp_qdio_sbal_check(struct zfcp_qdio *qdio)
{
- spin_lock_bh(&qdio->req_q_lock);
+ spin_lock_irq(&qdio->req_q_lock);
if (atomic_read(&qdio->req_q_free) ||
!(atomic_read(&qdio->adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP))
return 1;
- spin_unlock_bh(&qdio->req_q_lock);
+ spin_unlock_irq(&qdio->req_q_lock);
return 0;
}
@@ -223,7 +223,7 @@ int zfcp_qdio_sbal_get(struct zfcp_qdio *qdio)
{
long ret;
- spin_unlock_bh(&qdio->req_q_lock);
+ spin_unlock_irq(&qdio->req_q_lock);
ret = wait_event_interruptible_timeout(qdio->req_q_wq,
zfcp_qdio_sbal_check(qdio), 5 * HZ);
@@ -239,7 +239,7 @@ int zfcp_qdio_sbal_get(struct zfcp_qdio *qdio)
zfcp_erp_adapter_reopen(qdio->adapter, 0, "qdsbg_1", NULL);
}
- spin_lock_bh(&qdio->req_q_lock);
+ spin_lock_irq(&qdio->req_q_lock);
return -EIO;
}
@@ -254,7 +254,9 @@ int zfcp_qdio_send(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req)
int retval;
u8 sbal_number = q_req->sbal_number;
+ spin_lock(&qdio->stat_lock);
zfcp_qdio_account(qdio);
+ spin_unlock(&qdio->stat_lock);
retval = do_QDIO(qdio->adapter->ccw_device, QDIO_FLAG_SYNC_OUTPUT, 0,
q_req->sbal_first, sbal_number);
@@ -277,16 +279,12 @@ int zfcp_qdio_send(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req)
static void zfcp_qdio_setup_init_data(struct qdio_initialize *id,
struct zfcp_qdio *qdio)
{
-
+ memset(id, 0, sizeof(*id));
id->cdev = qdio->adapter->ccw_device;
id->q_format = QDIO_ZFCP_QFMT;
memcpy(id->adapter_name, dev_name(&id->cdev->dev), 8);
ASCEBC(id->adapter_name, 8);
id->qib_rflags = QIB_RFLAGS_ENABLE_DATA_DIV;
- id->qib_param_field_format = 0;
- id->qib_param_field = NULL;
- id->input_slib_elements = NULL;
- id->output_slib_elements = NULL;
id->no_input_qs = 1;
id->no_output_qs = 1;
id->input_handler = zfcp_qdio_int_resp;
@@ -328,9 +326,9 @@ void zfcp_qdio_close(struct zfcp_qdio *qdio)
return;
/* clear QDIOUP flag, thus do_QDIO is not called during qdio_shutdown */
- spin_lock_bh(&qdio->req_q_lock);
+ spin_lock_irq(&qdio->req_q_lock);
atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status);
- spin_unlock_bh(&qdio->req_q_lock);
+ spin_unlock_irq(&qdio->req_q_lock);
wake_up(&qdio->req_q_wq);
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index cb000c9833bb..50286d8707f3 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -49,11 +49,12 @@ static int zfcp_scsi_change_queue_depth(struct scsi_device *sdev, int depth,
return sdev->queue_depth;
}
-static void zfcp_scsi_slave_destroy(struct scsi_device *sdpnt)
+static void zfcp_scsi_slave_destroy(struct scsi_device *sdev)
{
- struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata;
- unit->device = NULL;
- put_device(&unit->dev);
+ struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+
+ zfcp_erp_lun_shutdown_wait(sdev, "scssd_1");
+ put_device(&zfcp_sdev->port->dev);
}
static int zfcp_scsi_slave_configure(struct scsi_device *sdp)
@@ -78,23 +79,16 @@ static void zfcp_scsi_command_fail(struct scsi_cmnd *scpnt, int result)
static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
void (*done) (struct scsi_cmnd *))
{
- struct zfcp_unit *unit;
- struct zfcp_adapter *adapter;
- int status, scsi_result, ret;
+ struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scpnt->device);
+ struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
struct fc_rport *rport = starget_to_rport(scsi_target(scpnt->device));
+ int status, scsi_result, ret;
/* reset the status for this request */
scpnt->result = 0;
scpnt->host_scribble = NULL;
scpnt->scsi_done = done;
- /*
- * figure out adapter and target device
- * (stored there by zfcp_scsi_slave_alloc)
- */
- adapter = (struct zfcp_adapter *) scpnt->device->host->hostdata[0];
- unit = scpnt->device->hostdata;
-
scsi_result = fc_remote_port_chkready(rport);
if (unlikely(scsi_result)) {
scpnt->result = scsi_result;
@@ -103,11 +97,11 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
return 0;
}
- status = atomic_read(&unit->status);
+ status = atomic_read(&zfcp_sdev->status);
if (unlikely(status & ZFCP_STATUS_COMMON_ERP_FAILED) &&
- !(atomic_read(&unit->port->status) &
+ !(atomic_read(&zfcp_sdev->port->status) &
ZFCP_STATUS_COMMON_ERP_FAILED)) {
- /* only unit access denied, but port is good
+ /* only LUN access denied, but port is good
* not covered by FC transport, have to fail here */
zfcp_scsi_command_fail(scpnt, DID_ERROR);
return 0;
@@ -115,8 +109,8 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
if (unlikely(!(status & ZFCP_STATUS_COMMON_UNBLOCKED))) {
/* This could be either
- * open unit pending: this is temporary, will result in
- * open unit or ERP_FAILED, so retry command
+ * open LUN pending: this is temporary, will result in
+ * open LUN or ERP_FAILED, so retry command
* call to rport_delete pending: mimic retry from
* fc_remote_port_chkready until rport is BLOCKED
*/
@@ -124,7 +118,7 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
return 0;
}
- ret = zfcp_fsf_send_fcp_command_task(unit, scpnt);
+ ret = zfcp_fsf_fcp_cmnd(scpnt);
if (unlikely(ret == -EBUSY))
return SCSI_MLQUEUE_DEVICE_BUSY;
else if (unlikely(ret < 0))
@@ -133,45 +127,42 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
return ret;
}
-static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *adapter,
- unsigned int id, u64 lun)
+static int zfcp_scsi_slave_alloc(struct scsi_device *sdev)
{
- unsigned long flags;
+ struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
+ struct zfcp_adapter *adapter =
+ (struct zfcp_adapter *) sdev->host->hostdata[0];
+ struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
struct zfcp_port *port;
- struct zfcp_unit *unit = NULL;
+ struct zfcp_unit *unit;
- read_lock_irqsave(&adapter->port_list_lock, flags);
- list_for_each_entry(port, &adapter->port_list, list) {
- if (!port->rport || (id != port->rport->scsi_target_id))
- continue;
- unit = zfcp_get_unit_by_lun(port, lun);
- if (unit)
- break;
- }
- read_unlock_irqrestore(&adapter->port_list_lock, flags);
+ port = zfcp_get_port_by_wwpn(adapter, rport->port_name);
+ if (!port)
+ return -ENXIO;
- return unit;
-}
+ unit = zfcp_unit_find(port, zfcp_scsi_dev_lun(sdev));
+ if (unit)
+ put_device(&unit->dev);
-static int zfcp_scsi_slave_alloc(struct scsi_device *sdp)
-{
- struct zfcp_adapter *adapter;
- struct zfcp_unit *unit;
- u64 lun;
+ if (!unit && !(adapter->connection_features & FSF_FEATURE_NPIV_MODE)) {
+ put_device(&port->dev);
+ return -ENXIO;
+ }
- adapter = (struct zfcp_adapter *) sdp->host->hostdata[0];
- if (!adapter)
- goto out;
+ zfcp_sdev->port = port;
+ zfcp_sdev->latencies.write.channel.min = 0xFFFFFFFF;
+ zfcp_sdev->latencies.write.fabric.min = 0xFFFFFFFF;
+ zfcp_sdev->latencies.read.channel.min = 0xFFFFFFFF;
+ zfcp_sdev->latencies.read.fabric.min = 0xFFFFFFFF;
+ zfcp_sdev->latencies.cmd.channel.min = 0xFFFFFFFF;
+ zfcp_sdev->latencies.cmd.fabric.min = 0xFFFFFFFF;
+ spin_lock_init(&zfcp_sdev->latencies.lock);
- int_to_scsilun(sdp->lun, (struct scsi_lun *)&lun);
- unit = zfcp_unit_lookup(adapter, sdp->id, lun);
- if (unit) {
- sdp->hostdata = unit;
- unit->device = sdp;
- return 0;
- }
-out:
- return -ENXIO;
+ zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_RUNNING);
+ zfcp_erp_lun_reopen(sdev, 0, "scsla_1", NULL);
+ zfcp_erp_wait(port->adapter);
+
+ return 0;
}
static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
@@ -179,7 +170,6 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
struct Scsi_Host *scsi_host = scpnt->device->host;
struct zfcp_adapter *adapter =
(struct zfcp_adapter *) scsi_host->hostdata[0];
- struct zfcp_unit *unit = scpnt->device->hostdata;
struct zfcp_fsf_req *old_req, *abrt_req;
unsigned long flags;
unsigned long old_reqid = (unsigned long) scpnt->host_scribble;
@@ -203,7 +193,7 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
write_unlock_irqrestore(&adapter->abort_lock, flags);
while (retry--) {
- abrt_req = zfcp_fsf_abort_fcp_command(old_reqid, unit);
+ abrt_req = zfcp_fsf_abort_fcp_cmnd(scpnt);
if (abrt_req)
break;
@@ -238,14 +228,14 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags)
{
- struct zfcp_unit *unit = scpnt->device->hostdata;
- struct zfcp_adapter *adapter = unit->port->adapter;
+ struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scpnt->device);
+ struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
struct zfcp_fsf_req *fsf_req = NULL;
int retval = SUCCESS, ret;
int retry = 3;
while (retry--) {
- fsf_req = zfcp_fsf_send_fcp_ctm(unit, tm_flags);
+ fsf_req = zfcp_fsf_fcp_task_mgmt(scpnt, tm_flags);
if (fsf_req)
break;
@@ -256,7 +246,7 @@ static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags)
if (!(atomic_read(&adapter->status) &
ZFCP_STATUS_COMMON_RUNNING)) {
- zfcp_dbf_scsi_devreset("nres", tm_flags, unit, scpnt);
+ zfcp_dbf_scsi_devreset("nres", scpnt, tm_flags);
return SUCCESS;
}
}
@@ -266,10 +256,10 @@ static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags)
wait_for_completion(&fsf_req->completion);
if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCFAILED) {
- zfcp_dbf_scsi_devreset("fail", tm_flags, unit, scpnt);
+ zfcp_dbf_scsi_devreset("fail", scpnt, tm_flags);
retval = FAILED;
} else
- zfcp_dbf_scsi_devreset("okay", tm_flags, unit, scpnt);
+ zfcp_dbf_scsi_devreset("okay", scpnt, tm_flags);
zfcp_fsf_req_free(fsf_req);
return retval;
@@ -287,8 +277,8 @@ static int zfcp_scsi_eh_target_reset_handler(struct scsi_cmnd *scpnt)
static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
{
- struct zfcp_unit *unit = scpnt->device->hostdata;
- struct zfcp_adapter *adapter = unit->port->adapter;
+ struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scpnt->device);
+ struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
int ret;
zfcp_erp_adapter_reopen(adapter, 0, "schrh_1", scpnt);
@@ -319,8 +309,8 @@ int zfcp_adapter_scsi_register(struct zfcp_adapter *adapter)
}
/* tell the SCSI stack some characteristics of this adapter */
- adapter->scsi_host->max_id = 1;
- adapter->scsi_host->max_lun = 1;
+ adapter->scsi_host->max_id = 511;
+ adapter->scsi_host->max_lun = 0xFFFFFFFF;
adapter->scsi_host->max_channel = 0;
adapter->scsi_host->unique_id = dev_id.devno;
adapter->scsi_host->max_cmd_len = 16; /* in struct fcp_cmnd */
@@ -534,20 +524,6 @@ static void zfcp_scsi_terminate_rport_io(struct fc_rport *rport)
}
}
-static void zfcp_scsi_queue_unit_register(struct zfcp_port *port)
-{
- struct zfcp_unit *unit;
-
- read_lock_irq(&port->unit_list_lock);
- list_for_each_entry(unit, &port->unit_list, list) {
- get_device(&unit->dev);
- if (scsi_queue_work(port->adapter->scsi_host,
- &unit->scsi_work) <= 0)
- put_device(&unit->dev);
- }
- read_unlock_irq(&port->unit_list_lock);
-}
-
static void zfcp_scsi_rport_register(struct zfcp_port *port)
{
struct fc_rport_identifiers ids;
@@ -574,7 +550,7 @@ static void zfcp_scsi_rport_register(struct zfcp_port *port)
port->rport = rport;
port->starget_id = rport->scsi_target_id;
- zfcp_scsi_queue_unit_register(port);
+ zfcp_unit_queue_scsi_scan(port);
}
static void zfcp_scsi_rport_block(struct zfcp_port *port)
@@ -638,29 +614,6 @@ void zfcp_scsi_rport_work(struct work_struct *work)
}
/**
- * zfcp_scsi_scan - Register LUN with SCSI midlayer
- * @unit: The LUN/unit to register
- */
-void zfcp_scsi_scan(struct zfcp_unit *unit)
-{
- struct fc_rport *rport = unit->port->rport;
-
- if (rport && rport->port_state == FC_PORTSTATE_ONLINE)
- scsi_scan_target(&rport->dev, 0, rport->scsi_target_id,
- scsilun_to_int((struct scsi_lun *)
- &unit->fcp_lun), 0);
-}
-
-void zfcp_scsi_scan_work(struct work_struct *work)
-{
- struct zfcp_unit *unit = container_of(work, struct zfcp_unit,
- scsi_work);
-
- zfcp_scsi_scan(unit);
- put_device(&unit->dev);
-}
-
-/**
* zfcp_scsi_set_prot - Configure DIF/DIX support in scsi_host
* @adapter: The adapter where to configure DIF/DIX for the SCSI host
*/
@@ -681,6 +634,7 @@ void zfcp_scsi_set_prot(struct zfcp_adapter *adapter)
adapter->adapter_features & FSF_FEATURE_DIX_PROT_TCPIP) {
mask |= SHOST_DIX_TYPE1_PROTECTION;
scsi_host_set_guard(shost, SHOST_DIX_GUARD_IP);
+ shost->sg_prot_tablesize = ZFCP_QDIO_MAX_SBALES_PER_REQ / 2;
shost->sg_tablesize = ZFCP_QDIO_MAX_SBALES_PER_REQ / 2;
shost->max_sectors = ZFCP_QDIO_MAX_SBALES_PER_REQ * 8 / 2;
}
@@ -734,7 +688,6 @@ struct fc_function_template zfcp_transport_functions = {
.show_host_port_type = 1,
.show_host_speed = 1,
.show_host_port_id = 1,
- .disable_target_scan = 1,
.dd_bsg_size = sizeof(struct zfcp_fsf_ct_els),
};
diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c
index b4561c86e230..2f2c54f4718f 100644
--- a/drivers/s390/scsi/zfcp_sysfs.c
+++ b/drivers/s390/scsi/zfcp_sysfs.c
@@ -68,63 +68,96 @@ ZFCP_DEFINE_ATTR(zfcp_port, port, access_denied, "%d\n",
ZFCP_STATUS_COMMON_ACCESS_DENIED) != 0);
ZFCP_DEFINE_ATTR(zfcp_unit, unit, status, "0x%08x\n",
- atomic_read(&unit->status));
+ zfcp_unit_sdev_status(unit));
ZFCP_DEFINE_ATTR(zfcp_unit, unit, in_recovery, "%d\n",
- (atomic_read(&unit->status) &
+ (zfcp_unit_sdev_status(unit) &
ZFCP_STATUS_COMMON_ERP_INUSE) != 0);
ZFCP_DEFINE_ATTR(zfcp_unit, unit, access_denied, "%d\n",
- (atomic_read(&unit->status) &
+ (zfcp_unit_sdev_status(unit) &
ZFCP_STATUS_COMMON_ACCESS_DENIED) != 0);
ZFCP_DEFINE_ATTR(zfcp_unit, unit, access_shared, "%d\n",
- (atomic_read(&unit->status) &
- ZFCP_STATUS_UNIT_SHARED) != 0);
+ (zfcp_unit_sdev_status(unit) &
+ ZFCP_STATUS_LUN_SHARED) != 0);
ZFCP_DEFINE_ATTR(zfcp_unit, unit, access_readonly, "%d\n",
- (atomic_read(&unit->status) &
- ZFCP_STATUS_UNIT_READONLY) != 0);
+ (zfcp_unit_sdev_status(unit) &
+ ZFCP_STATUS_LUN_READONLY) != 0);
-#define ZFCP_SYSFS_FAILED(_feat_def, _feat, _adapter, _mod_id, _reopen_id) \
-static ssize_t zfcp_sysfs_##_feat##_failed_show(struct device *dev, \
- struct device_attribute *attr, \
- char *buf) \
-{ \
- struct _feat_def *_feat = container_of(dev, struct _feat_def, dev); \
- \
- if (atomic_read(&_feat->status) & ZFCP_STATUS_COMMON_ERP_FAILED) \
- return sprintf(buf, "1\n"); \
- else \
- return sprintf(buf, "0\n"); \
-} \
-static ssize_t zfcp_sysfs_##_feat##_failed_store(struct device *dev, \
- struct device_attribute *attr,\
- const char *buf, size_t count)\
-{ \
- struct _feat_def *_feat = container_of(dev, struct _feat_def, dev); \
- unsigned long val; \
- int retval = 0; \
- \
- if (!(_feat && get_device(&_feat->dev))) \
- return -EBUSY; \
- \
- if (strict_strtoul(buf, 0, &val) || val != 0) { \
- retval = -EINVAL; \
- goto out; \
- } \
- \
- zfcp_erp_modify_##_feat##_status(_feat, _mod_id, NULL, \
- ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);\
- zfcp_erp_##_feat##_reopen(_feat, ZFCP_STATUS_COMMON_ERP_FAILED, \
- _reopen_id, NULL); \
- zfcp_erp_wait(_adapter); \
-out: \
- put_device(&_feat->dev); \
- return retval ? retval : (ssize_t) count; \
-} \
-static ZFCP_DEV_ATTR(_feat, failed, S_IWUSR | S_IRUGO, \
- zfcp_sysfs_##_feat##_failed_show, \
- zfcp_sysfs_##_feat##_failed_store);
+static ssize_t zfcp_sysfs_port_failed_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct zfcp_port *port = container_of(dev, struct zfcp_port, dev);
+
+ if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED)
+ return sprintf(buf, "1\n");
+
+ return sprintf(buf, "0\n");
+}
+
+static ssize_t zfcp_sysfs_port_failed_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct zfcp_port *port = container_of(dev, struct zfcp_port, dev);
+ unsigned long val;
+
+ if (strict_strtoul(buf, 0, &val) || val != 0)
+ return -EINVAL;
+
+ zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_RUNNING);
+ zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, "sypfai2",
+ NULL);
+ zfcp_erp_wait(port->adapter);
-ZFCP_SYSFS_FAILED(zfcp_port, port, port->adapter, "sypfai1", "sypfai2");
-ZFCP_SYSFS_FAILED(zfcp_unit, unit, unit->port->adapter, "syufai1", "syufai2");
+ return count;
+}
+static ZFCP_DEV_ATTR(port, failed, S_IWUSR | S_IRUGO,
+ zfcp_sysfs_port_failed_show,
+ zfcp_sysfs_port_failed_store);
+
+static ssize_t zfcp_sysfs_unit_failed_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct zfcp_unit *unit = container_of(dev, struct zfcp_unit, dev);
+ struct scsi_device *sdev;
+ unsigned int status, failed = 1;
+
+ sdev = zfcp_unit_sdev(unit);
+ if (sdev) {
+ status = atomic_read(&sdev_to_zfcp(sdev)->status);
+ failed = status & ZFCP_STATUS_COMMON_ERP_FAILED ? 1 : 0;
+ scsi_device_put(sdev);
+ }
+
+ return sprintf(buf, "%d\n", failed);
+}
+
+static ssize_t zfcp_sysfs_unit_failed_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct zfcp_unit *unit = container_of(dev, struct zfcp_unit, dev);
+ unsigned long val;
+ struct scsi_device *sdev;
+
+ if (strict_strtoul(buf, 0, &val) || val != 0)
+ return -EINVAL;
+
+ sdev = zfcp_unit_sdev(unit);
+ if (sdev) {
+ zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_RUNNING);
+ zfcp_erp_lun_reopen(sdev, ZFCP_STATUS_COMMON_ERP_FAILED,
+ "syufai2", NULL);
+ zfcp_erp_wait(unit->port->adapter);
+ } else
+ zfcp_unit_scsi_scan(unit);
+
+ return count;
+}
+static ZFCP_DEV_ATTR(unit, failed, S_IWUSR | S_IRUGO,
+ zfcp_sysfs_unit_failed_show,
+ zfcp_sysfs_unit_failed_store);
static ssize_t zfcp_sysfs_adapter_failed_show(struct device *dev,
struct device_attribute *attr,
@@ -163,8 +196,7 @@ static ssize_t zfcp_sysfs_adapter_failed_store(struct device *dev,
goto out;
}
- zfcp_erp_modify_adapter_status(adapter, "syafai1", NULL,
- ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
+ zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING);
zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
"syafai2", NULL);
zfcp_erp_wait(adapter);
@@ -257,28 +289,15 @@ static ssize_t zfcp_sysfs_unit_add_store(struct device *dev,
const char *buf, size_t count)
{
struct zfcp_port *port = container_of(dev, struct zfcp_port, dev);
- struct zfcp_unit *unit;
u64 fcp_lun;
- int retval = -EINVAL;
-
- if (!(port && get_device(&port->dev)))
- return -EBUSY;
if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun))
- goto out;
+ return -EINVAL;
- unit = zfcp_unit_enqueue(port, fcp_lun);
- if (IS_ERR(unit))
- goto out;
- else
- retval = 0;
+ if (zfcp_unit_add(port, fcp_lun))
+ return -EINVAL;
- zfcp_erp_unit_reopen(unit, 0, "syuas_1", NULL);
- zfcp_erp_wait(unit->port->adapter);
- zfcp_scsi_scan(unit);
-out:
- put_device(&port->dev);
- return retval ? retval : (ssize_t) count;
+ return count;
}
static DEVICE_ATTR(unit_add, S_IWUSR, NULL, zfcp_sysfs_unit_add_store);
@@ -287,42 +306,15 @@ static ssize_t zfcp_sysfs_unit_remove_store(struct device *dev,
const char *buf, size_t count)
{
struct zfcp_port *port = container_of(dev, struct zfcp_port, dev);
- struct zfcp_unit *unit;
u64 fcp_lun;
- int retval = -EINVAL;
- struct scsi_device *sdev;
-
- if (!(port && get_device(&port->dev)))
- return -EBUSY;
if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun))
- goto out;
+ return -EINVAL;
- unit = zfcp_get_unit_by_lun(port, fcp_lun);
- if (!unit)
- goto out;
- else
- retval = 0;
-
- sdev = scsi_device_lookup(port->adapter->scsi_host, 0,
- port->starget_id,
- scsilun_to_int((struct scsi_lun *)&fcp_lun));
- if (sdev) {
- scsi_remove_device(sdev);
- scsi_device_put(sdev);
- }
-
- write_lock_irq(&port->unit_list_lock);
- list_del(&unit->list);
- write_unlock_irq(&port->unit_list_lock);
-
- put_device(&unit->dev);
+ if (zfcp_unit_remove(port, fcp_lun))
+ return -EINVAL;
- zfcp_erp_unit_shutdown(unit, 0, "syurs_1", NULL);
- zfcp_device_unregister(&unit->dev, &zfcp_sysfs_unit_attrs);
-out:
- put_device(&port->dev);
- return retval ? retval : (ssize_t) count;
+ return count;
}
static DEVICE_ATTR(unit_remove, S_IWUSR, NULL, zfcp_sysfs_unit_remove_store);
@@ -363,9 +355,9 @@ zfcp_sysfs_unit_##_name##_latency_show(struct device *dev, \
struct device_attribute *attr, \
char *buf) { \
struct scsi_device *sdev = to_scsi_device(dev); \
- struct zfcp_unit *unit = sdev->hostdata; \
- struct zfcp_latencies *lat = &unit->latencies; \
- struct zfcp_adapter *adapter = unit->port->adapter; \
+ struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); \
+ struct zfcp_latencies *lat = &zfcp_sdev->latencies; \
+ struct zfcp_adapter *adapter = zfcp_sdev->port->adapter; \
unsigned long long fsum, fmin, fmax, csum, cmin, cmax, cc; \
\
spin_lock_bh(&lat->lock); \
@@ -394,8 +386,8 @@ zfcp_sysfs_unit_##_name##_latency_store(struct device *dev, \
const char *buf, size_t count) \
{ \
struct scsi_device *sdev = to_scsi_device(dev); \
- struct zfcp_unit *unit = sdev->hostdata; \
- struct zfcp_latencies *lat = &unit->latencies; \
+ struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); \
+ struct zfcp_latencies *lat = &zfcp_sdev->latencies; \
unsigned long flags; \
\
spin_lock_irqsave(&lat->lock, flags); \
@@ -423,19 +415,28 @@ static ssize_t zfcp_sysfs_scsi_##_name##_show(struct device *dev, \
struct device_attribute *attr,\
char *buf) \
{ \
- struct scsi_device *sdev = to_scsi_device(dev); \
- struct zfcp_unit *unit = sdev->hostdata; \
+ struct scsi_device *sdev = to_scsi_device(dev); \
+ struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); \
+ struct zfcp_port *port = zfcp_sdev->port; \
\
return sprintf(buf, _format, _value); \
} \
static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_scsi_##_name##_show, NULL);
ZFCP_DEFINE_SCSI_ATTR(hba_id, "%s\n",
- dev_name(&unit->port->adapter->ccw_device->dev));
+ dev_name(&port->adapter->ccw_device->dev));
ZFCP_DEFINE_SCSI_ATTR(wwpn, "0x%016llx\n",
- (unsigned long long) unit->port->wwpn);
-ZFCP_DEFINE_SCSI_ATTR(fcp_lun, "0x%016llx\n",
- (unsigned long long) unit->fcp_lun);
+ (unsigned long long) port->wwpn);
+
+static ssize_t zfcp_sysfs_scsi_fcp_lun_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct scsi_device *sdev = to_scsi_device(dev);
+
+ return sprintf(buf, "0x%016llx\n", zfcp_scsi_dev_lun(sdev));
+}
+static DEVICE_ATTR(fcp_lun, S_IRUGO, zfcp_sysfs_scsi_fcp_lun_show, NULL);
struct device_attribute *zfcp_sysfs_sdev_attrs[] = {
&dev_attr_fcp_lun,
diff --git a/drivers/s390/scsi/zfcp_unit.c b/drivers/s390/scsi/zfcp_unit.c
new file mode 100644
index 000000000000..1119c535a667
--- /dev/null
+++ b/drivers/s390/scsi/zfcp_unit.c
@@ -0,0 +1,244 @@
+/*
+ * zfcp device driver
+ *
+ * Tracking of manually configured LUNs and helper functions to
+ * register the LUNs with the SCSI midlayer.
+ *
+ * Copyright IBM Corporation 2010
+ */
+
+#include "zfcp_def.h"
+#include "zfcp_ext.h"
+
+/**
+ * zfcp_unit_scsi_scan - Register LUN with SCSI midlayer
+ * @unit: The zfcp LUN/unit to register
+ *
+ * When the SCSI midlayer is not allowed to automatically scan and
+ * attach SCSI devices, zfcp has to register the single devices with
+ * the SCSI midlayer.
+ */
+void zfcp_unit_scsi_scan(struct zfcp_unit *unit)
+{
+ struct fc_rport *rport = unit->port->rport;
+ unsigned int lun;
+
+ lun = scsilun_to_int((struct scsi_lun *) &unit->fcp_lun);
+
+ if (rport && rport->port_state == FC_PORTSTATE_ONLINE)
+ scsi_scan_target(&rport->dev, 0, rport->scsi_target_id, lun, 1);
+}
+
+static void zfcp_unit_scsi_scan_work(struct work_struct *work)
+{
+ struct zfcp_unit *unit = container_of(work, struct zfcp_unit,
+ scsi_work);
+
+ zfcp_unit_scsi_scan(unit);
+ put_device(&unit->dev);
+}
+
+/**
+ * zfcp_unit_queue_scsi_scan - Register configured units on port
+ * @port: The zfcp_port where to register units
+ *
+ * After opening a port, all units configured on this port have to be
+ * registered with the SCSI midlayer. This function should be called
+ * after calling fc_remote_port_add, so that the fc_rport is already
+ * ONLINE and the call to scsi_scan_target runs the same way as the
+ * call in the FC transport class.
+ */
+void zfcp_unit_queue_scsi_scan(struct zfcp_port *port)
+{
+ struct zfcp_unit *unit;
+
+ read_lock_irq(&port->unit_list_lock);
+ list_for_each_entry(unit, &port->unit_list, list) {
+ get_device(&unit->dev);
+ if (scsi_queue_work(port->adapter->scsi_host,
+ &unit->scsi_work) <= 0)
+ put_device(&unit->dev);
+ }
+ read_unlock_irq(&port->unit_list_lock);
+}
+
+static struct zfcp_unit *_zfcp_unit_find(struct zfcp_port *port, u64 fcp_lun)
+{
+ struct zfcp_unit *unit;
+
+ list_for_each_entry(unit, &port->unit_list, list)
+ if (unit->fcp_lun == fcp_lun) {
+ get_device(&unit->dev);
+ return unit;
+ }
+
+ return NULL;
+}
+
+/**
+ * zfcp_unit_find - Find and return zfcp_unit with specified FCP LUN
+ * @port: zfcp_port where to look for the unit
+ * @fcp_lun: 64 Bit FCP LUN used to identify the zfcp_unit
+ *
+ * If zfcp_unit is found, a reference is acquired that has to be
+ * released later.
+ *
+ * Returns: Pointer to the zfcp_unit, or NULL if there is no zfcp_unit
+ * with the specified FCP LUN.
+ */
+struct zfcp_unit *zfcp_unit_find(struct zfcp_port *port, u64 fcp_lun)
+{
+ struct zfcp_unit *unit;
+
+ read_lock_irq(&port->unit_list_lock);
+ unit = _zfcp_unit_find(port, fcp_lun);
+ read_unlock_irq(&port->unit_list_lock);
+ return unit;
+}
+
+/**
+ * zfcp_unit_release - Drop reference to zfcp_port and free memory of zfcp_unit.
+ * @dev: pointer to device in zfcp_unit
+ */
+static void zfcp_unit_release(struct device *dev)
+{
+ struct zfcp_unit *unit = container_of(dev, struct zfcp_unit, dev);
+
+ put_device(&unit->port->dev);
+ kfree(unit);
+}
+
+/**
+ * zfcp_unit_enqueue - enqueue unit to unit list of a port.
+ * @port: pointer to port where unit is added
+ * @fcp_lun: FCP LUN of unit to be enqueued
+ * Returns: 0 success
+ *
+ * Sets up some unit internal structures and creates sysfs entry.
+ */
+int zfcp_unit_add(struct zfcp_port *port, u64 fcp_lun)
+{
+ struct zfcp_unit *unit;
+
+ unit = zfcp_unit_find(port, fcp_lun);
+ if (unit) {
+ put_device(&unit->dev);
+ return -EEXIST;
+ }
+
+ unit = kzalloc(sizeof(struct zfcp_unit), GFP_KERNEL);
+ if (!unit)
+ return -ENOMEM;
+
+ unit->port = port;
+ unit->fcp_lun = fcp_lun;
+ unit->dev.parent = &port->dev;
+ unit->dev.release = zfcp_unit_release;
+ INIT_WORK(&unit->scsi_work, zfcp_unit_scsi_scan_work);
+
+ if (dev_set_name(&unit->dev, "0x%016llx",
+ (unsigned long long) fcp_lun)) {
+ kfree(unit);
+ return -ENOMEM;
+ }
+
+ if (device_register(&unit->dev)) {
+ put_device(&unit->dev);
+ return -ENOMEM;
+ }
+
+ if (sysfs_create_group(&unit->dev.kobj, &zfcp_sysfs_unit_attrs)) {
+ device_unregister(&unit->dev);
+ return -EINVAL;
+ }
+
+ get_device(&port->dev);
+
+ write_lock_irq(&port->unit_list_lock);
+ list_add_tail(&unit->list, &port->unit_list);
+ write_unlock_irq(&port->unit_list_lock);
+
+ zfcp_unit_scsi_scan(unit);
+
+ return 0;
+}
+
+/**
+ * zfcp_unit_sdev - Return SCSI device for zfcp_unit
+ * @unit: The zfcp_unit where to get the SCSI device for
+ *
+ * Returns: scsi_device pointer on success, NULL if there is no SCSI
+ * device for this zfcp_unit
+ *
+ * On success, the caller also holds a reference to the SCSI device
+ * that must be released with scsi_device_put.
+ */
+struct scsi_device *zfcp_unit_sdev(struct zfcp_unit *unit)
+{
+ struct Scsi_Host *shost;
+ struct zfcp_port *port;
+ unsigned int lun;
+
+ lun = scsilun_to_int((struct scsi_lun *) &unit->fcp_lun);
+ port = unit->port;
+ shost = port->adapter->scsi_host;
+ return scsi_device_lookup(shost, 0, port->starget_id, lun);
+}
+
+/**
+ * zfcp_unit_sdev_status - Return zfcp LUN status for SCSI device
+ * @unit: The unit to lookup the SCSI device for
+ *
+ * Returns the zfcp LUN status field of the SCSI device if the SCSI device
+ * for the zfcp_unit exists, 0 otherwise.
+ */
+unsigned int zfcp_unit_sdev_status(struct zfcp_unit *unit)
+{
+ unsigned int status = 0;
+ struct scsi_device *sdev;
+ struct zfcp_scsi_dev *zfcp_sdev;
+
+ sdev = zfcp_unit_sdev(unit);
+ if (sdev) {
+ zfcp_sdev = sdev_to_zfcp(sdev);
+ status = atomic_read(&zfcp_sdev->status);
+ scsi_device_put(sdev);
+ }
+
+ return status;
+}
+
+/**
+ * zfcp_unit_remove - Remove entry from list of configured units
+ * @port: The port where to remove the unit from the configuration
+ * @fcp_lun: The 64 bit LUN of the unit to remove
+ *
+ * Returns: -EINVAL if a unit with the specified LUN does not exist,
+ * 0 on success.
+ */
+int zfcp_unit_remove(struct zfcp_port *port, u64 fcp_lun)
+{
+ struct zfcp_unit *unit;
+ struct scsi_device *sdev;
+
+ write_lock_irq(&port->unit_list_lock);
+ unit = _zfcp_unit_find(port, fcp_lun);
+ if (unit)
+ list_del(&unit->list);
+ write_unlock_irq(&port->unit_list_lock);
+
+ if (!unit)
+ return -EINVAL;
+
+ sdev = zfcp_unit_sdev(unit);
+ if (sdev) {
+ scsi_remove_device(sdev);
+ scsi_device_put(sdev);
+ }
+
+ put_device(&unit->dev);
+
+ zfcp_device_unregister(&unit->dev, &zfcp_sysfs_unit_attrs);
+
+ return 0;
+}
diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c
index 1690e53fb84a..55f71ea9c418 100644
--- a/drivers/sbus/char/display7seg.c
+++ b/drivers/sbus/char/display7seg.c
@@ -162,6 +162,7 @@ static const struct file_operations d7s_fops = {
.compat_ioctl = d7s_ioctl,
.open = d7s_open,
.release = d7s_release,
+ .llseek = noop_llseek,
};
static struct miscdevice d7s_miscdev = {
diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c
index 078e5f4520ef..8ce414e39489 100644
--- a/drivers/sbus/char/envctrl.c
+++ b/drivers/sbus/char/envctrl.c
@@ -720,6 +720,7 @@ static const struct file_operations envctrl_fops = {
#endif
.open = envctrl_open,
.release = envctrl_release,
+ .llseek = noop_llseek,
};
static struct miscdevice envctrl_dev = {
diff --git a/drivers/sbus/char/jsflash.c b/drivers/sbus/char/jsflash.c
index 4942050dc5b6..13f48e28a1e1 100644
--- a/drivers/sbus/char/jsflash.c
+++ b/drivers/sbus/char/jsflash.c
@@ -27,7 +27,7 @@
*/
#include <linux/module.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
@@ -68,6 +68,8 @@
#define JSF_PART_BITS 2 /* 2 bits of minors to cover JSF_NPART */
#define JSF_PART_MASK 0x3 /* 2 bits mask */
+static DEFINE_MUTEX(jsf_mutex);
+
/*
* Access functions.
* We could ioremap(), but it's easier this way.
@@ -225,7 +227,7 @@ static loff_t jsf_lseek(struct file * file, loff_t offset, int orig)
{
loff_t ret;
- lock_kernel();
+ mutex_lock(&jsf_mutex);
switch (orig) {
case 0:
file->f_pos = offset;
@@ -238,7 +240,7 @@ static loff_t jsf_lseek(struct file * file, loff_t offset, int orig)
default:
ret = -EINVAL;
}
- unlock_kernel();
+ mutex_unlock(&jsf_mutex);
return ret;
}
@@ -384,18 +386,18 @@ static int jsf_ioctl_program(void __user *arg)
static long jsf_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
{
- lock_kernel();
+ mutex_lock(&jsf_mutex);
int error = -ENOTTY;
void __user *argp = (void __user *)arg;
if (!capable(CAP_SYS_ADMIN)) {
- unlock_kernel();
+ mutex_unlock(&jsf_mutex);
return -EPERM;
}
switch (cmd) {
case JSFLASH_IDENT:
if (copy_to_user(argp, &jsf0.id, JSFIDSZ)) {
- unlock_kernel();
+ mutex_unlock(&jsf_mutex);
return -EFAULT;
}
break;
@@ -407,7 +409,7 @@ static long jsf_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
break;
}
- unlock_kernel();
+ mutex_unlock(&jsf_mutex);
return error;
}
@@ -418,17 +420,17 @@ static int jsf_mmap(struct file * file, struct vm_area_struct * vma)
static int jsf_open(struct inode * inode, struct file * filp)
{
- lock_kernel();
+ mutex_lock(&jsf_mutex);
if (jsf0.base == 0) {
- unlock_kernel();
+ mutex_unlock(&jsf_mutex);
return -ENXIO;
}
if (test_and_set_bit(0, (void *)&jsf0.busy) != 0) {
- unlock_kernel();
+ mutex_unlock(&jsf_mutex);
return -EBUSY;
}
- unlock_kernel();
+ mutex_unlock(&jsf_mutex);
return 0; /* XXX What security? */
}
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index e20b7bdd4c78..fcf08b3f52c1 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -92,7 +92,6 @@
#include <linux/pci.h>
#include <linux/time.h>
#include <linux/mutex.h>
-#include <linux/smp_lock.h>
#include <linux/slab.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -105,6 +104,7 @@
/* Globals */
#define TW_DRIVER_VERSION "2.26.02.014"
+static DEFINE_MUTEX(twa_chrdev_mutex);
static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT];
static unsigned int twa_device_extension_count;
static int twa_major = -1;
@@ -222,7 +222,8 @@ static const struct file_operations twa_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = twa_chrdev_ioctl,
.open = twa_chrdev_open,
- .release = NULL
+ .release = NULL,
+ .llseek = noop_llseek,
};
/* This function will complete an aen request from the isr */
@@ -658,7 +659,7 @@ static long twa_chrdev_ioctl(struct file *file, unsigned int cmd, unsigned long
int retval = TW_IOCTL_ERROR_OS_EFAULT;
void __user *argp = (void __user *)arg;
- lock_kernel();
+ mutex_lock(&twa_chrdev_mutex);
/* Only let one of these through at a time */
if (mutex_lock_interruptible(&tw_dev->ioctl_lock)) {
@@ -879,7 +880,7 @@ out3:
out2:
mutex_unlock(&tw_dev->ioctl_lock);
out:
- unlock_kernel();
+ mutex_unlock(&twa_chrdev_mutex);
return retval;
} /* End twa_chrdev_ioctl() */
@@ -890,7 +891,6 @@ static int twa_chrdev_open(struct inode *inode, struct file *file)
unsigned int minor_number;
int retval = TW_IOCTL_ERROR_OS_ENODEV;
- cycle_kernel_lock();
minor_number = iminor(inode);
if (minor_number >= twa_device_extension_count)
goto out;
diff --git a/drivers/scsi/3w-sas.c b/drivers/scsi/3w-sas.c
index f481e734aad4..6a95d111d207 100644
--- a/drivers/scsi/3w-sas.c
+++ b/drivers/scsi/3w-sas.c
@@ -64,7 +64,6 @@
#include <linux/pci.h>
#include <linux/time.h>
#include <linux/mutex.h>
-#include <linux/smp_lock.h>
#include <linux/slab.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -77,6 +76,7 @@
/* Globals */
#define TW_DRIVER_VERSION "3.26.02.000"
+static DEFINE_MUTEX(twl_chrdev_mutex);
static TW_Device_Extension *twl_device_extension_list[TW_MAX_SLOT];
static unsigned int twl_device_extension_count;
static int twl_major = -1;
@@ -764,7 +764,7 @@ static long twl_chrdev_ioctl(struct file *file, unsigned int cmd, unsigned long
int retval = -EFAULT;
void __user *argp = (void __user *)arg;
- lock_kernel();
+ mutex_lock(&twl_chrdev_mutex);
/* Only let one of these through at a time */
if (mutex_lock_interruptible(&tw_dev->ioctl_lock)) {
@@ -861,7 +861,7 @@ out3:
out2:
mutex_unlock(&tw_dev->ioctl_lock);
out:
- unlock_kernel();
+ mutex_unlock(&twl_chrdev_mutex);
return retval;
} /* End twl_chrdev_ioctl() */
@@ -876,7 +876,6 @@ static int twl_chrdev_open(struct inode *inode, struct file *file)
goto out;
}
- cycle_kernel_lock();
minor_number = iminor(inode);
if (minor_number >= twl_device_extension_count)
goto out;
@@ -890,7 +889,8 @@ static const struct file_operations twl_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = twl_chrdev_ioctl,
.open = twl_chrdev_open,
- .release = NULL
+ .release = NULL,
+ .llseek = noop_llseek,
};
/* This function passes sense data from firmware to scsi layer */
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
index 30d735ad35b5..b1125341f4c8 100644
--- a/drivers/scsi/3w-xxxx.c
+++ b/drivers/scsi/3w-xxxx.c
@@ -199,7 +199,6 @@
#include <linux/module.h>
#include <linux/reboot.h>
-#include <linux/smp_lock.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/moduleparam.h>
@@ -221,6 +220,7 @@
/* Globals */
#define TW_DRIVER_VERSION "1.26.02.003"
+static DEFINE_MUTEX(tw_mutex);
static TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT];
static int tw_device_extension_count = 0;
static int twe_major = -1;
@@ -900,10 +900,10 @@ static long tw_chrdev_ioctl(struct file *file, unsigned int cmd, unsigned long a
dprintk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl()\n");
- lock_kernel();
+ mutex_lock(&tw_mutex);
/* Only let one of these through at a time */
if (mutex_lock_interruptible(&tw_dev->ioctl_lock)) {
- unlock_kernel();
+ mutex_unlock(&tw_mutex);
return -EINTR;
}
@@ -1034,7 +1034,7 @@ out2:
dma_free_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted+sizeof(TW_New_Ioctl) - 1, cpu_addr, dma_handle);
out:
mutex_unlock(&tw_dev->ioctl_lock);
- unlock_kernel();
+ mutex_unlock(&tw_mutex);
return retval;
} /* End tw_chrdev_ioctl() */
@@ -1044,7 +1044,6 @@ static int tw_chrdev_open(struct inode *inode, struct file *file)
{
unsigned int minor_number;
- cycle_kernel_lock();
dprintk(KERN_WARNING "3w-xxxx: tw_ioctl_open()\n");
minor_number = iminor(inode);
@@ -1059,7 +1058,8 @@ static const struct file_operations tw_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = tw_chrdev_ioctl,
.open = tw_chrdev_open,
- .release = NULL
+ .release = NULL,
+ .llseek = noop_llseek,
};
/* This function will free up device extension resources */
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index bbf91aec64f5..2e9632e2c98b 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -316,7 +316,8 @@ config SCSI_ISCSI_ATTRS
config SCSI_SAS_ATTRS
tristate "SAS Transport Attributes"
- depends on SCSI && BLK_DEV_BSG
+ depends on SCSI
+ select BLK_DEV_BSG
help
If you wish to export transport-specific information about
each attached SAS device to sysfs, say Y.
@@ -378,7 +379,7 @@ config ISCSI_BOOT_SYSFS
via sysfs to userspace. If you wish to export this information,
say Y. Otherwise, say N.
-source "drivers/scsi/cxgb3i/Kconfig"
+source "drivers/scsi/cxgbi/Kconfig"
source "drivers/scsi/bnx2i/Kconfig"
source "drivers/scsi/be2iscsi/Kconfig"
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 2703c6ec5e36..2e9a87e8e7d8 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -133,7 +133,8 @@ obj-$(CONFIG_SCSI_HPTIOP) += hptiop.o
obj-$(CONFIG_SCSI_STEX) += stex.o
obj-$(CONFIG_SCSI_MVSAS) += mvsas/
obj-$(CONFIG_PS3_ROM) += ps3rom.o
-obj-$(CONFIG_SCSI_CXGB3_ISCSI) += libiscsi.o libiscsi_tcp.o cxgb3i/
+obj-$(CONFIG_SCSI_CXGB3_ISCSI) += libiscsi.o libiscsi_tcp.o cxgbi/
+obj-$(CONFIG_SCSI_CXGB4_ISCSI) += libiscsi.o libiscsi_tcp.o cxgbi/
obj-$(CONFIG_SCSI_BNX2_ISCSI) += libiscsi.o bnx2i/
obj-$(CONFIG_BE2ISCSI) += libiscsi.o be2iscsi/
obj-$(CONFIG_SCSI_PMCRAID) += pmcraid.o
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c
index 1a5bf5724750..645ddd9d9b9e 100644
--- a/drivers/scsi/aacraid/commctrl.c
+++ b/drivers/scsi/aacraid/commctrl.c
@@ -190,7 +190,7 @@ static int open_getadapter_fib(struct aac_dev * dev, void __user *arg)
/*
* Initialize the mutex used to wait for the next AIF.
*/
- init_MUTEX_LOCKED(&fibctx->wait_sem);
+ sema_init(&fibctx->wait_sem, 0);
fibctx->wait = 0;
/*
* Initialize the fibs and set the count of fibs on
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
index 70079146e203..afc9aeba5edb 100644
--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -124,7 +124,7 @@ int aac_fib_setup(struct aac_dev * dev)
fibptr->hw_fib_va = hw_fib;
fibptr->data = (void *) fibptr->hw_fib_va->data;
fibptr->next = fibptr+1; /* Forward chain the fibs */
- init_MUTEX_LOCKED(&fibptr->event_wait);
+ sema_init(&fibptr->event_wait, 0);
spin_lock_init(&fibptr->event_lock);
hw_fib->header.XferState = cpu_to_le32(0xffffffff);
hw_fib->header.SenderSize = cpu_to_le16(dev->max_fib_size);
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index cad6f9abaeb9..dae46d779c7b 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -38,7 +38,7 @@
#include <linux/moduleparam.h>
#include <linux/pci.h>
#include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/spinlock.h>
#include <linux/syscalls.h>
#include <linux/delay.h>
@@ -76,6 +76,7 @@ MODULE_DESCRIPTION("Dell PERC2, 2/Si, 3/Si, 3/Di, "
MODULE_LICENSE("GPL");
MODULE_VERSION(AAC_DRIVER_FULL_VERSION);
+static DEFINE_MUTEX(aac_mutex);
static LIST_HEAD(aac_devices);
static int aac_cfg_major = -1;
char aac_driver_version[] = AAC_DRIVER_FULL_VERSION;
@@ -678,7 +679,7 @@ static int aac_cfg_open(struct inode *inode, struct file *file)
unsigned minor_number = iminor(inode);
int err = -ENODEV;
- lock_kernel(); /* BKL pushdown: nothing else protects this list */
+ mutex_lock(&aac_mutex); /* BKL pushdown: nothing else protects this list */
list_for_each_entry(aac, &aac_devices, entry) {
if (aac->id == minor_number) {
file->private_data = aac;
@@ -686,7 +687,7 @@ static int aac_cfg_open(struct inode *inode, struct file *file)
break;
}
}
- unlock_kernel();
+ mutex_unlock(&aac_mutex);
return err;
}
@@ -711,9 +712,9 @@ static long aac_cfg_ioctl(struct file *file,
int ret;
if (!capable(CAP_SYS_RAWIO))
return -EPERM;
- lock_kernel();
+ mutex_lock(&aac_mutex);
ret = aac_do_ioctl(file->private_data, cmd, (void __user *)arg);
- unlock_kernel();
+ mutex_unlock(&aac_mutex);
return ret;
}
@@ -722,7 +723,7 @@ static long aac_cfg_ioctl(struct file *file,
static long aac_compat_do_ioctl(struct aac_dev *dev, unsigned cmd, unsigned long arg)
{
long ret;
- lock_kernel();
+ mutex_lock(&aac_mutex);
switch (cmd) {
case FSACTL_MINIPORT_REV_CHECK:
case FSACTL_SENDFIB:
@@ -756,7 +757,7 @@ static long aac_compat_do_ioctl(struct aac_dev *dev, unsigned cmd, unsigned long
ret = -ENOIOCTLCMD;
break;
}
- unlock_kernel();
+ mutex_unlock(&aac_mutex);
return ret;
}
@@ -1039,6 +1040,7 @@ static const struct file_operations aac_cfg_fops = {
.compat_ioctl = aac_compat_cfg_ioctl,
#endif
.open = aac_cfg_open,
+ .llseek = noop_llseek,
};
static struct scsi_host_template aac_driver_template = {
diff --git a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c
index 93984c9dfe14..aee73fafccc8 100644
--- a/drivers/scsi/aic7xxx_old.c
+++ b/drivers/scsi/aic7xxx_old.c
@@ -2850,12 +2850,6 @@ aic7xxx_done(struct aic7xxx_host *p, struct aic7xxx_scb *scb)
aic_dev->r_total++;
ptr = aic_dev->r_bins;
}
- if(cmd->device->simple_tags && cmd->request->cmd_flags & REQ_HARDBARRIER)
- {
- aic_dev->barrier_total++;
- if(scb->tag_action == MSG_ORDERED_Q_TAG)
- aic_dev->ordered_total++;
- }
x = scb->sg_length;
x >>= 10;
for(i=0; i<6; i++)
@@ -10125,7 +10119,6 @@ static void aic7xxx_buildscb(struct aic7xxx_host *p, struct scsi_cmnd *cmd,
struct aic_dev_data *aic_dev = cmd->device->hostdata;
struct scsi_device *sdptr = cmd->device;
unsigned char tindex = TARGET_INDEX(cmd);
- struct request *req = cmd->request;
int use_sg;
mask = (0x01 << tindex);
@@ -10144,19 +10137,8 @@ static void aic7xxx_buildscb(struct aic7xxx_host *p, struct scsi_cmnd *cmd,
/* We always force TEST_UNIT_READY to untagged */
if (cmd->cmnd[0] != TEST_UNIT_READY && sdptr->simple_tags)
{
- if (req->cmd_flags & REQ_HARDBARRIER)
- {
- if(sdptr->ordered_tags)
- {
- hscb->control |= MSG_ORDERED_Q_TAG;
- scb->tag_action = MSG_ORDERED_Q_TAG;
- }
- }
- else
- {
- hscb->control |= MSG_SIMPLE_Q_TAG;
- scb->tag_action = MSG_SIMPLE_Q_TAG;
- }
+ hscb->control |= MSG_SIMPLE_Q_TAG;
+ scb->tag_action = MSG_SIMPLE_Q_TAG;
}
}
if ( !(aic_dev->dtr_pending) &&
diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c
index c8dc392edd57..05a78e515a24 100644
--- a/drivers/scsi/arcmsr/arcmsr_hba.c
+++ b/drivers/scsi/arcmsr/arcmsr_hba.c
@@ -878,8 +878,8 @@ static void arcmsr_report_ccb_state(struct AdapterControlBlock *acb,
if (!error) {
if (acb->devstate[id][lun] == ARECA_RAID_GONE)
acb->devstate[id][lun] = ARECA_RAID_GOOD;
- ccb->pcmd->result = DID_OK << 16;
- arcmsr_ccb_complete(ccb);
+ ccb->pcmd->result = DID_OK << 16;
+ arcmsr_ccb_complete(ccb);
}else{
switch (ccb->arcmsr_cdb.DeviceStatus) {
case ARCMSR_DEV_SELECT_TIMEOUT: {
diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c
index 7c7537335c88..ad246369d373 100644
--- a/drivers/scsi/be2iscsi/be_cmds.c
+++ b/drivers/scsi/be2iscsi/be_cmds.c
@@ -335,7 +335,7 @@ static int be_mbox_db_ready_wait(struct be_ctrl_info *ctrl)
if (ready)
break;
- if (cnt > 6000000) {
+ if (cnt > 12000000) {
dev_err(&ctrl->pdev->dev, "mbox_db poll timed out\n");
return -EBUSY;
}
diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c
index 7f11f3e48e12..eaaa8813067d 100644
--- a/drivers/scsi/be2iscsi/be_iscsi.c
+++ b/drivers/scsi/be2iscsi/be_iscsi.c
@@ -522,7 +522,6 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep,
if (beiscsi_ep->ep_cid > (phba->fw_config.iscsi_cid_start +
phba->params.cxns_per_ctrl * 2)) {
SE_DEBUG(DBG_LVL_1, "Failed in allocate iscsi cid\n");
- beiscsi_put_cid(phba, beiscsi_ep->ep_cid);
goto free_ep;
}
@@ -559,7 +558,6 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep,
SE_DEBUG(DBG_LVL_1, "mgmt_open_connection Failed"
" status = %d extd_status = %d\n",
status, extd_status);
- beiscsi_put_cid(phba, beiscsi_ep->ep_cid);
free_mcc_tag(&phba->ctrl, tag);
pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
nonemb_cmd.va, nonemb_cmd.dma);
@@ -574,7 +572,6 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep,
beiscsi_ep->cid_vld = 1;
SE_DEBUG(DBG_LVL_8, "mgmt_open_connection Success\n");
}
- beiscsi_put_cid(phba, beiscsi_ep->ep_cid);
pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
nonemb_cmd.va, nonemb_cmd.dma);
return 0;
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
index 8220bde6c04c..75a85aa9e882 100644
--- a/drivers/scsi/be2iscsi/be_main.c
+++ b/drivers/scsi/be2iscsi/be_main.c
@@ -2040,7 +2040,7 @@ hwi_write_sgl(struct iscsi_wrb *pwrb, struct scatterlist *sg,
unsigned int num_sg, struct beiscsi_io_task *io_task)
{
struct iscsi_sge *psgl;
- unsigned short sg_len, index;
+ unsigned int sg_len, index;
unsigned int sge_len = 0;
unsigned long long addr;
struct scatterlist *l_sg;
diff --git a/drivers/scsi/bfa/Makefile b/drivers/scsi/bfa/Makefile
index ac3fdf02d5f6..d2eefd3e3bd5 100644
--- a/drivers/scsi/bfa/Makefile
+++ b/drivers/scsi/bfa/Makefile
@@ -1,15 +1,8 @@
obj-$(CONFIG_SCSI_BFA_FC) := bfa.o
-bfa-y := bfad.o bfad_intr.o bfad_os.o bfad_im.o bfad_attr.o bfad_fwimg.o
-bfa-y += bfad_debugfs.o
-bfa-y += bfa_core.o bfa_ioc.o bfa_ioc_ct.o bfa_ioc_cb.o bfa_iocfc.o bfa_fcxp.o
-bfa-y += bfa_lps.o bfa_hw_cb.o bfa_hw_ct.o bfa_intr.o bfa_timer.o bfa_rport.o
-bfa-y += bfa_fcport.o bfa_port.o bfa_uf.o bfa_sgpg.o bfa_module.o bfa_ioim.o
-bfa-y += bfa_itnim.o bfa_fcpim.o bfa_tskim.o bfa_log.o bfa_log_module.o
-bfa-y += bfa_csdebug.o bfa_sm.o plog.o
+bfa-y := bfad.o bfad_im.o bfad_attr.o bfad_debugfs.o
+bfa-y += bfa_ioc.o bfa_ioc_cb.o bfa_ioc_ct.o bfa_hw_cb.o bfa_hw_ct.o
+bfa-y += bfa_fcs.o bfa_fcs_lport.o bfa_fcs_rport.o bfa_fcs_fcpim.o bfa_fcbuild.o
+bfa-y += bfa_port.o bfa_fcpim.o bfa_core.o bfa_drv.o bfa_svc.o
-bfa-y += fcbuild.o fabric.o fcpim.o vfapi.o fcptm.o bfa_fcs.o bfa_fcs_port.o
-bfa-y += bfa_fcs_uf.o bfa_fcs_lport.o fab.o fdmi.o ms.o ns.o scn.o loop.o
-bfa-y += lport_api.o n2n.o rport.o rport_api.o rport_ftrs.o vport.o
-
-ccflags-y := -I$(obj) -I$(obj)/include -I$(obj)/include/cna -DBFA_PERF_BUILD
+ccflags-y := -DBFA_PERF_BUILD
diff --git a/drivers/scsi/bfa/bfa.h b/drivers/scsi/bfa/bfa.h
new file mode 100644
index 000000000000..ceaac65a91ff
--- /dev/null
+++ b/drivers/scsi/bfa/bfa.h
@@ -0,0 +1,438 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+#ifndef __BFA_H__
+#define __BFA_H__
+
+#include "bfa_os_inc.h"
+#include "bfa_cs.h"
+#include "bfa_plog.h"
+#include "bfa_defs_svc.h"
+#include "bfi.h"
+#include "bfa_ioc.h"
+
+struct bfa_s;
+
+typedef void (*bfa_isr_func_t) (struct bfa_s *bfa, struct bfi_msg_s *m);
+typedef void (*bfa_cb_cbfn_t) (void *cbarg, bfa_boolean_t complete);
+
+/**
+ * Interrupt message handlers
+ */
+void bfa_isr_unhandled(struct bfa_s *bfa, struct bfi_msg_s *m);
+void bfa_isr_bind(enum bfi_mclass mc, bfa_isr_func_t isr_func);
+
+/**
+ * Request and response queue related defines
+ */
+#define BFA_REQQ_NELEMS_MIN (4)
+#define BFA_RSPQ_NELEMS_MIN (4)
+
+#define bfa_reqq_pi(__bfa, __reqq) ((__bfa)->iocfc.req_cq_pi[__reqq])
+#define bfa_reqq_ci(__bfa, __reqq) \
+ (*(u32 *)((__bfa)->iocfc.req_cq_shadow_ci[__reqq].kva))
+
+#define bfa_reqq_full(__bfa, __reqq) \
+ (((bfa_reqq_pi(__bfa, __reqq) + 1) & \
+ ((__bfa)->iocfc.cfg.drvcfg.num_reqq_elems - 1)) == \
+ bfa_reqq_ci(__bfa, __reqq))
+
+#define bfa_reqq_next(__bfa, __reqq) \
+ (bfa_reqq_full(__bfa, __reqq) ? NULL : \
+ ((void *)((struct bfi_msg_s *)((__bfa)->iocfc.req_cq_ba[__reqq].kva) \
+ + bfa_reqq_pi((__bfa), (__reqq)))))
+
+#define bfa_reqq_produce(__bfa, __reqq) do { \
+ (__bfa)->iocfc.req_cq_pi[__reqq]++; \
+ (__bfa)->iocfc.req_cq_pi[__reqq] &= \
+ ((__bfa)->iocfc.cfg.drvcfg.num_reqq_elems - 1); \
+ bfa_reg_write((__bfa)->iocfc.bfa_regs.cpe_q_pi[__reqq], \
+ (__bfa)->iocfc.req_cq_pi[__reqq]); \
+ mmiowb(); \
+ } while (0)
+
+#define bfa_rspq_pi(__bfa, __rspq) \
+ (*(u32 *)((__bfa)->iocfc.rsp_cq_shadow_pi[__rspq].kva))
+
+#define bfa_rspq_ci(__bfa, __rspq) ((__bfa)->iocfc.rsp_cq_ci[__rspq])
+#define bfa_rspq_elem(__bfa, __rspq, __ci) \
+ (&((struct bfi_msg_s *)((__bfa)->iocfc.rsp_cq_ba[__rspq].kva))[__ci])
+
+#define CQ_INCR(__index, __size) do { \
+ (__index)++; \
+ (__index) &= ((__size) - 1); \
+} while (0)
+
+/**
+ * Queue element to wait for room in request queue. FIFO order is
+ * maintained when fullfilling requests.
+ */
+struct bfa_reqq_wait_s {
+ struct list_head qe;
+ void (*qresume) (void *cbarg);
+ void *cbarg;
+};
+
+/**
+ * Circular queue usage assignments
+ */
+enum {
+ BFA_REQQ_IOC = 0, /* all low-priority IOC msgs */
+ BFA_REQQ_FCXP = 0, /* all FCXP messages */
+ BFA_REQQ_LPS = 0, /* all lport service msgs */
+ BFA_REQQ_PORT = 0, /* all port messages */
+ BFA_REQQ_FLASH = 0, /* for flash module */
+ BFA_REQQ_DIAG = 0, /* for diag module */
+ BFA_REQQ_RPORT = 0, /* all port messages */
+ BFA_REQQ_SBOOT = 0, /* all san boot messages */
+ BFA_REQQ_QOS_LO = 1, /* all low priority IO */
+ BFA_REQQ_QOS_MD = 2, /* all medium priority IO */
+ BFA_REQQ_QOS_HI = 3, /* all high priority IO */
+};
+
+static inline void
+bfa_reqq_winit(struct bfa_reqq_wait_s *wqe, void (*qresume) (void *cbarg),
+ void *cbarg)
+{
+ wqe->qresume = qresume;
+ wqe->cbarg = cbarg;
+}
+
+#define bfa_reqq(__bfa, __reqq) (&(__bfa)->reqq_waitq[__reqq])
+
+/**
+ * static inline void
+ * bfa_reqq_wait(struct bfa_s *bfa, int reqq, struct bfa_reqq_wait_s *wqe)
+ */
+#define bfa_reqq_wait(__bfa, __reqq, __wqe) do { \
+ \
+ struct list_head *waitq = bfa_reqq(__bfa, __reqq); \
+ \
+ bfa_assert(((__reqq) < BFI_IOC_MAX_CQS)); \
+ bfa_assert((__wqe)->qresume && (__wqe)->cbarg); \
+ \
+ list_add_tail(&(__wqe)->qe, waitq); \
+ } while (0)
+
+#define bfa_reqq_wcancel(__wqe) list_del(&(__wqe)->qe)
+
+
+/**
+ * Generic BFA callback element.
+ */
+struct bfa_cb_qe_s {
+ struct list_head qe;
+ bfa_cb_cbfn_t cbfn;
+ bfa_boolean_t once;
+ u32 rsvd;
+ void *cbarg;
+};
+
+#define bfa_cb_queue(__bfa, __hcb_qe, __cbfn, __cbarg) do { \
+ (__hcb_qe)->cbfn = (__cbfn); \
+ (__hcb_qe)->cbarg = (__cbarg); \
+ list_add_tail(&(__hcb_qe)->qe, &(__bfa)->comp_q); \
+ } while (0)
+
+#define bfa_cb_dequeue(__hcb_qe) list_del(&(__hcb_qe)->qe)
+
+#define bfa_cb_queue_once(__bfa, __hcb_qe, __cbfn, __cbarg) do { \
+ (__hcb_qe)->cbfn = (__cbfn); \
+ (__hcb_qe)->cbarg = (__cbarg); \
+ if (!(__hcb_qe)->once) { \
+ list_add_tail(&(__hcb_qe)->qe, &(__bfa)->comp_q); \
+ (__hcb_qe)->once = BFA_TRUE; \
+ } \
+ } while (0)
+
+#define bfa_cb_queue_done(__hcb_qe) do { \
+ (__hcb_qe)->once = BFA_FALSE; \
+ } while (0)
+
+
+/**
+ * PCI devices supported by the current BFA
+ */
+struct bfa_pciid_s {
+ u16 device_id;
+ u16 vendor_id;
+};
+
+extern char bfa_version[];
+
+/**
+ * BFA memory resources
+ */
+enum bfa_mem_type {
+ BFA_MEM_TYPE_KVA = 1, /* Kernel Virtual Memory *(non-dma-able) */
+ BFA_MEM_TYPE_DMA = 2, /* DMA-able memory */
+ BFA_MEM_TYPE_MAX = BFA_MEM_TYPE_DMA,
+};
+
+struct bfa_mem_elem_s {
+ enum bfa_mem_type mem_type; /* see enum bfa_mem_type */
+ u32 mem_len; /* Total Length in Bytes */
+ u8 *kva; /* kernel virtual address */
+ u64 dma; /* dma address if DMA memory */
+ u8 *kva_curp; /* kva allocation cursor */
+ u64 dma_curp; /* dma allocation cursor */
+};
+
+struct bfa_meminfo_s {
+ struct bfa_mem_elem_s meminfo[BFA_MEM_TYPE_MAX];
+};
+#define bfa_meminfo_kva(_m) \
+ ((_m)->meminfo[BFA_MEM_TYPE_KVA - 1].kva_curp)
+#define bfa_meminfo_dma_virt(_m) \
+ ((_m)->meminfo[BFA_MEM_TYPE_DMA - 1].kva_curp)
+#define bfa_meminfo_dma_phys(_m) \
+ ((_m)->meminfo[BFA_MEM_TYPE_DMA - 1].dma_curp)
+
+struct bfa_iocfc_regs_s {
+ bfa_os_addr_t intr_status;
+ bfa_os_addr_t intr_mask;
+ bfa_os_addr_t cpe_q_pi[BFI_IOC_MAX_CQS];
+ bfa_os_addr_t cpe_q_ci[BFI_IOC_MAX_CQS];
+ bfa_os_addr_t cpe_q_depth[BFI_IOC_MAX_CQS];
+ bfa_os_addr_t cpe_q_ctrl[BFI_IOC_MAX_CQS];
+ bfa_os_addr_t rme_q_ci[BFI_IOC_MAX_CQS];
+ bfa_os_addr_t rme_q_pi[BFI_IOC_MAX_CQS];
+ bfa_os_addr_t rme_q_depth[BFI_IOC_MAX_CQS];
+ bfa_os_addr_t rme_q_ctrl[BFI_IOC_MAX_CQS];
+};
+
+/**
+ * MSIX vector handlers
+ */
+#define BFA_MSIX_MAX_VECTORS 22
+typedef void (*bfa_msix_handler_t)(struct bfa_s *bfa, int vec);
+struct bfa_msix_s {
+ int nvecs;
+ bfa_msix_handler_t handler[BFA_MSIX_MAX_VECTORS];
+};
+
+/**
+ * Chip specific interfaces
+ */
+struct bfa_hwif_s {
+ void (*hw_reginit)(struct bfa_s *bfa);
+ void (*hw_reqq_ack)(struct bfa_s *bfa, int reqq);
+ void (*hw_rspq_ack)(struct bfa_s *bfa, int rspq);
+ void (*hw_msix_init)(struct bfa_s *bfa, int nvecs);
+ void (*hw_msix_install)(struct bfa_s *bfa);
+ void (*hw_msix_uninstall)(struct bfa_s *bfa);
+ void (*hw_isr_mode_set)(struct bfa_s *bfa, bfa_boolean_t msix);
+ void (*hw_msix_getvecs)(struct bfa_s *bfa, u32 *vecmap,
+ u32 *nvecs, u32 *maxvec);
+ void (*hw_msix_get_rme_range) (struct bfa_s *bfa, u32 *start,
+ u32 *end);
+};
+typedef void (*bfa_cb_iocfc_t) (void *cbarg, enum bfa_status status);
+
+struct bfa_iocfc_s {
+ struct bfa_s *bfa;
+ struct bfa_iocfc_cfg_s cfg;
+ int action;
+ u32 req_cq_pi[BFI_IOC_MAX_CQS];
+ u32 rsp_cq_ci[BFI_IOC_MAX_CQS];
+ struct bfa_cb_qe_s init_hcb_qe;
+ struct bfa_cb_qe_s stop_hcb_qe;
+ struct bfa_cb_qe_s dis_hcb_qe;
+ struct bfa_cb_qe_s stats_hcb_qe;
+ bfa_boolean_t cfgdone;
+
+ struct bfa_dma_s cfg_info;
+ struct bfi_iocfc_cfg_s *cfginfo;
+ struct bfa_dma_s cfgrsp_dma;
+ struct bfi_iocfc_cfgrsp_s *cfgrsp;
+ struct bfi_iocfc_cfg_reply_s *cfg_reply;
+ struct bfa_dma_s req_cq_ba[BFI_IOC_MAX_CQS];
+ struct bfa_dma_s req_cq_shadow_ci[BFI_IOC_MAX_CQS];
+ struct bfa_dma_s rsp_cq_ba[BFI_IOC_MAX_CQS];
+ struct bfa_dma_s rsp_cq_shadow_pi[BFI_IOC_MAX_CQS];
+ struct bfa_iocfc_regs_s bfa_regs; /* BFA device registers */
+ struct bfa_hwif_s hwif;
+ bfa_cb_iocfc_t updateq_cbfn; /* bios callback function */
+ void *updateq_cbarg; /* bios callback arg */
+ u32 intr_mask;
+};
+
+#define bfa_lpuid(__bfa) \
+ bfa_ioc_portid(&(__bfa)->ioc)
+#define bfa_msix_init(__bfa, __nvecs) \
+ ((__bfa)->iocfc.hwif.hw_msix_init(__bfa, __nvecs))
+#define bfa_msix_install(__bfa) \
+ ((__bfa)->iocfc.hwif.hw_msix_install(__bfa))
+#define bfa_msix_uninstall(__bfa) \
+ ((__bfa)->iocfc.hwif.hw_msix_uninstall(__bfa))
+#define bfa_isr_mode_set(__bfa, __msix) \
+ ((__bfa)->iocfc.hwif.hw_isr_mode_set(__bfa, __msix))
+#define bfa_msix_getvecs(__bfa, __vecmap, __nvecs, __maxvec) \
+ ((__bfa)->iocfc.hwif.hw_msix_getvecs(__bfa, __vecmap, \
+ __nvecs, __maxvec))
+#define bfa_msix_get_rme_range(__bfa, __start, __end) \
+ ((__bfa)->iocfc.hwif.hw_msix_get_rme_range(__bfa, __start, __end))
+#define bfa_msix(__bfa, __vec) \
+ ((__bfa)->msix.handler[__vec](__bfa, __vec))
+
+/*
+ * FC specific IOC functions.
+ */
+void bfa_iocfc_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
+ u32 *dm_len);
+void bfa_iocfc_attach(struct bfa_s *bfa, void *bfad,
+ struct bfa_iocfc_cfg_s *cfg,
+ struct bfa_meminfo_s *meminfo,
+ struct bfa_pcidev_s *pcidev);
+void bfa_iocfc_detach(struct bfa_s *bfa);
+void bfa_iocfc_init(struct bfa_s *bfa);
+void bfa_iocfc_start(struct bfa_s *bfa);
+void bfa_iocfc_stop(struct bfa_s *bfa);
+void bfa_iocfc_isr(void *bfa, struct bfi_mbmsg_s *msg);
+void bfa_iocfc_set_snsbase(struct bfa_s *bfa, u64 snsbase_pa);
+bfa_boolean_t bfa_iocfc_is_operational(struct bfa_s *bfa);
+void bfa_iocfc_reset_queues(struct bfa_s *bfa);
+
+void bfa_msix_all(struct bfa_s *bfa, int vec);
+void bfa_msix_reqq(struct bfa_s *bfa, int vec);
+void bfa_msix_rspq(struct bfa_s *bfa, int vec);
+void bfa_msix_lpu_err(struct bfa_s *bfa, int vec);
+
+void bfa_hwcb_reginit(struct bfa_s *bfa);
+void bfa_hwcb_reqq_ack(struct bfa_s *bfa, int rspq);
+void bfa_hwcb_rspq_ack(struct bfa_s *bfa, int rspq);
+void bfa_hwcb_msix_init(struct bfa_s *bfa, int nvecs);
+void bfa_hwcb_msix_install(struct bfa_s *bfa);
+void bfa_hwcb_msix_uninstall(struct bfa_s *bfa);
+void bfa_hwcb_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix);
+void bfa_hwcb_msix_getvecs(struct bfa_s *bfa, u32 *vecmap, u32 *nvecs,
+ u32 *maxvec);
+void bfa_hwcb_msix_get_rme_range(struct bfa_s *bfa, u32 *start,
+ u32 *end);
+void bfa_hwct_reginit(struct bfa_s *bfa);
+void bfa_hwct_reqq_ack(struct bfa_s *bfa, int rspq);
+void bfa_hwct_rspq_ack(struct bfa_s *bfa, int rspq);
+void bfa_hwct_msix_init(struct bfa_s *bfa, int nvecs);
+void bfa_hwct_msix_install(struct bfa_s *bfa);
+void bfa_hwct_msix_uninstall(struct bfa_s *bfa);
+void bfa_hwct_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix);
+void bfa_hwct_msix_getvecs(struct bfa_s *bfa, u32 *vecmap, u32 *nvecs,
+ u32 *maxvec);
+void bfa_hwct_msix_get_rme_range(struct bfa_s *bfa, u32 *start,
+ u32 *end);
+void bfa_com_port_attach(struct bfa_s *bfa, struct bfa_meminfo_s *mi);
+void bfa_iocfc_get_bootwwns(struct bfa_s *bfa, u8 *nwwns, wwn_t *wwns);
+wwn_t bfa_iocfc_get_pwwn(struct bfa_s *bfa);
+wwn_t bfa_iocfc_get_nwwn(struct bfa_s *bfa);
+void bfa_iocfc_get_pbc_boot_cfg(struct bfa_s *bfa,
+ struct bfa_boot_pbc_s *pbcfg);
+int bfa_iocfc_get_pbc_vports(struct bfa_s *bfa,
+ struct bfi_pbc_vport_s *pbc_vport);
+
+
+/**
+ *----------------------------------------------------------------------
+ * BFA public interfaces
+ *----------------------------------------------------------------------
+ */
+#define bfa_stats(_mod, _stats) ((_mod)->stats._stats++)
+#define bfa_ioc_get_stats(__bfa, __ioc_stats) \
+ bfa_ioc_fetch_stats(&(__bfa)->ioc, __ioc_stats)
+#define bfa_ioc_clear_stats(__bfa) \
+ bfa_ioc_clr_stats(&(__bfa)->ioc)
+#define bfa_get_nports(__bfa) \
+ bfa_ioc_get_nports(&(__bfa)->ioc)
+#define bfa_get_adapter_manufacturer(__bfa, __manufacturer) \
+ bfa_ioc_get_adapter_manufacturer(&(__bfa)->ioc, __manufacturer)
+#define bfa_get_adapter_model(__bfa, __model) \
+ bfa_ioc_get_adapter_model(&(__bfa)->ioc, __model)
+#define bfa_get_adapter_serial_num(__bfa, __serial_num) \
+ bfa_ioc_get_adapter_serial_num(&(__bfa)->ioc, __serial_num)
+#define bfa_get_adapter_fw_ver(__bfa, __fw_ver) \
+ bfa_ioc_get_adapter_fw_ver(&(__bfa)->ioc, __fw_ver)
+#define bfa_get_adapter_optrom_ver(__bfa, __optrom_ver) \
+ bfa_ioc_get_adapter_optrom_ver(&(__bfa)->ioc, __optrom_ver)
+#define bfa_get_pci_chip_rev(__bfa, __chip_rev) \
+ bfa_ioc_get_pci_chip_rev(&(__bfa)->ioc, __chip_rev)
+#define bfa_get_ioc_state(__bfa) \
+ bfa_ioc_get_state(&(__bfa)->ioc)
+#define bfa_get_type(__bfa) \
+ bfa_ioc_get_type(&(__bfa)->ioc)
+#define bfa_get_mac(__bfa) \
+ bfa_ioc_get_mac(&(__bfa)->ioc)
+#define bfa_get_mfg_mac(__bfa) \
+ bfa_ioc_get_mfg_mac(&(__bfa)->ioc)
+#define bfa_get_fw_clock_res(__bfa) \
+ ((__bfa)->iocfc.cfgrsp->fwcfg.fw_tick_res)
+
+void bfa_get_pciids(struct bfa_pciid_s **pciids, int *npciids);
+void bfa_cfg_get_default(struct bfa_iocfc_cfg_s *cfg);
+void bfa_cfg_get_min(struct bfa_iocfc_cfg_s *cfg);
+void bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg,
+ struct bfa_meminfo_s *meminfo);
+void bfa_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
+ struct bfa_meminfo_s *meminfo,
+ struct bfa_pcidev_s *pcidev);
+void bfa_init_trc(struct bfa_s *bfa, struct bfa_trc_mod_s *trcmod);
+void bfa_init_plog(struct bfa_s *bfa, struct bfa_plog_s *plog);
+void bfa_detach(struct bfa_s *bfa);
+void bfa_init(struct bfa_s *bfa);
+void bfa_start(struct bfa_s *bfa);
+void bfa_stop(struct bfa_s *bfa);
+void bfa_attach_fcs(struct bfa_s *bfa);
+void bfa_cb_init(void *bfad, bfa_status_t status);
+void bfa_cb_updateq(void *bfad, bfa_status_t status);
+
+bfa_boolean_t bfa_intx(struct bfa_s *bfa);
+void bfa_intx_disable(struct bfa_s *bfa);
+void bfa_intx_enable(struct bfa_s *bfa);
+void bfa_isr_enable(struct bfa_s *bfa);
+void bfa_isr_disable(struct bfa_s *bfa);
+
+void bfa_comp_deq(struct bfa_s *bfa, struct list_head *comp_q);
+void bfa_comp_process(struct bfa_s *bfa, struct list_head *comp_q);
+void bfa_comp_free(struct bfa_s *bfa, struct list_head *comp_q);
+
+typedef void (*bfa_cb_ioc_t) (void *cbarg, enum bfa_status status);
+void bfa_iocfc_get_attr(struct bfa_s *bfa, struct bfa_iocfc_attr_s *attr);
+void bfa_get_attr(struct bfa_s *bfa, struct bfa_ioc_attr_s *ioc_attr);
+
+void bfa_adapter_get_attr(struct bfa_s *bfa,
+ struct bfa_adapter_attr_s *ad_attr);
+u64 bfa_adapter_get_id(struct bfa_s *bfa);
+
+bfa_status_t bfa_iocfc_israttr_set(struct bfa_s *bfa,
+ struct bfa_iocfc_intr_attr_s *attr);
+
+void bfa_iocfc_enable(struct bfa_s *bfa);
+void bfa_iocfc_disable(struct bfa_s *bfa);
+void bfa_chip_reset(struct bfa_s *bfa);
+void bfa_timer_tick(struct bfa_s *bfa);
+#define bfa_timer_start(_bfa, _timer, _timercb, _arg, _timeout) \
+ bfa_timer_begin(&(_bfa)->timer_mod, _timer, _timercb, _arg, _timeout)
+
+/*
+ * BFA debug API functions
+ */
+bfa_status_t bfa_debug_fwtrc(struct bfa_s *bfa, void *trcdata, int *trclen);
+bfa_status_t bfa_debug_fwsave(struct bfa_s *bfa, void *trcdata, int *trclen);
+bfa_status_t bfa_debug_fwcore(struct bfa_s *bfa, void *buf,
+ u32 *offset, int *buflen);
+void bfa_debug_fwsave_clear(struct bfa_s *bfa);
+bfa_status_t bfa_fw_stats_get(struct bfa_s *bfa, void *data);
+bfa_status_t bfa_fw_stats_clear(struct bfa_s *bfa);
+
+#endif /* __BFA_H__ */
diff --git a/drivers/scsi/bfa/bfa_callback_priv.h b/drivers/scsi/bfa/bfa_callback_priv.h
deleted file mode 100644
index 1e3265c9f7d4..000000000000
--- a/drivers/scsi/bfa/bfa_callback_priv.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_CALLBACK_PRIV_H__
-#define __BFA_CALLBACK_PRIV_H__
-
-#include <cs/bfa_q.h>
-
-typedef void (*bfa_cb_cbfn_t) (void *cbarg, bfa_boolean_t complete);
-
-/**
- * Generic BFA callback element.
- */
-struct bfa_cb_qe_s {
- struct list_head qe;
- bfa_cb_cbfn_t cbfn;
- bfa_boolean_t once;
- u32 rsvd;
- void *cbarg;
-};
-
-#define bfa_cb_queue(__bfa, __hcb_qe, __cbfn, __cbarg) do { \
- (__hcb_qe)->cbfn = (__cbfn); \
- (__hcb_qe)->cbarg = (__cbarg); \
- list_add_tail(&(__hcb_qe)->qe, &(__bfa)->comp_q); \
-} while (0)
-
-#define bfa_cb_dequeue(__hcb_qe) list_del(&(__hcb_qe)->qe)
-
-#define bfa_cb_queue_once(__bfa, __hcb_qe, __cbfn, __cbarg) do { \
- (__hcb_qe)->cbfn = (__cbfn); \
- (__hcb_qe)->cbarg = (__cbarg); \
- if (!(__hcb_qe)->once) { \
- list_add_tail((__hcb_qe), &(__bfa)->comp_q); \
- (__hcb_qe)->once = BFA_TRUE; \
- } \
-} while (0)
-
-#define bfa_cb_queue_done(__hcb_qe) do { \
- (__hcb_qe)->once = BFA_FALSE; \
-} while (0)
-
-#endif /* __BFA_CALLBACK_PRIV_H__ */
diff --git a/drivers/scsi/bfa/bfa_cb_ioim_macros.h b/drivers/scsi/bfa/bfa_cb_ioim.h
index 3906ed926966..a989a94c38da 100644
--- a/drivers/scsi/bfa/bfa_cb_ioim_macros.h
+++ b/drivers/scsi/bfa/bfa_cb_ioim.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
* All rights reserved
* www.brocade.com
*
@@ -15,37 +15,25 @@
* General Public License for more details.
*/
-/**
- * bfa_cb_ioim_macros.h BFA IOIM driver interface macros.
- */
-
-#ifndef __BFA_HCB_IOIM_MACROS_H__
-#define __BFA_HCB_IOIM_MACROS_H__
-
-#include <bfa_os_inc.h>
-/*
- * #include <linux/dma-mapping.h>
- *
- * #include <scsi/scsi.h> #include <scsi/scsi_cmnd.h> #include
- * <scsi/scsi_device.h> #include <scsi/scsi_host.h>
- */
-#include "bfad_im_compat.h"
+#ifndef __BFA_HCB_IOIM_H__
+#define __BFA_HCB_IOIM_H__
+#include "bfa_os_inc.h"
/*
* task attribute values in FCP-2 FCP_CMND IU
*/
#define SIMPLE_Q 0
#define HEAD_OF_Q 1
#define ORDERED_Q 2
-#define ACA_Q 4
+#define ACA_Q 4
#define UNTAGGED 5
static inline lun_t
bfad_int_to_lun(u32 luno)
{
union {
- u16 scsi_lun[4];
- lun_t bfa_lun;
+ u16 scsi_lun[4];
+ lun_t bfa_lun;
} lun;
lun.bfa_lun = 0;
@@ -141,7 +129,7 @@ static inline u8
bfa_cb_ioim_get_taskattr(struct bfad_ioim_s *dio)
{
struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
- u8 task_attr = UNTAGGED;
+ u8 task_attr = UNTAGGED;
if (cmnd->device->tagged_supported) {
switch (cmnd->tag) {
@@ -178,4 +166,4 @@ bfa_cb_ioim_get_cdblen(struct bfad_ioim_s *dio)
*/
#define bfa_cb_ioim_get_reqq(__dio) BFA_FALSE
-#endif /* __BFA_HCB_IOIM_MACROS_H__ */
+#endif /* __BFA_HCB_IOIM_H__ */
diff --git a/drivers/scsi/bfa/bfa_cee.c b/drivers/scsi/bfa/bfa_cee.c
deleted file mode 100644
index 2b917792c6bc..000000000000
--- a/drivers/scsi/bfa/bfa_cee.c
+++ /dev/null
@@ -1,492 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#include <defs/bfa_defs_cee.h>
-#include <cs/bfa_trc.h>
-#include <cs/bfa_log.h>
-#include <cs/bfa_debug.h>
-#include <cee/bfa_cee.h>
-#include <bfi/bfi_cee.h>
-#include <bfi/bfi.h>
-#include <bfa_ioc.h>
-#include <cna/bfa_cna_trcmod.h>
-
-BFA_TRC_FILE(CNA, CEE);
-
-#define bfa_ioc_portid(__ioc) ((__ioc)->port_id)
-#define bfa_lpuid(__arg) bfa_ioc_portid(&(__arg)->ioc)
-
-static void bfa_cee_format_lldp_cfg(struct bfa_cee_lldp_cfg_s *lldp_cfg);
-static void bfa_cee_format_dcbcx_stats(struct bfa_cee_dcbx_stats_s
- *dcbcx_stats);
-static void bfa_cee_format_lldp_stats(struct bfa_cee_lldp_stats_s
- *lldp_stats);
-static void bfa_cee_format_cfg_stats(struct bfa_cee_cfg_stats_s *cfg_stats);
-static void bfa_cee_format_cee_cfg(void *buffer);
-static void bfa_cee_format_cee_stats(void *buffer);
-
-static void
-bfa_cee_format_cee_stats(void *buffer)
-{
- struct bfa_cee_stats_s *cee_stats = buffer;
- bfa_cee_format_dcbcx_stats(&cee_stats->dcbx_stats);
- bfa_cee_format_lldp_stats(&cee_stats->lldp_stats);
- bfa_cee_format_cfg_stats(&cee_stats->cfg_stats);
-}
-
-static void
-bfa_cee_format_cee_cfg(void *buffer)
-{
- struct bfa_cee_attr_s *cee_cfg = buffer;
- bfa_cee_format_lldp_cfg(&cee_cfg->lldp_remote);
-}
-
-static void
-bfa_cee_format_dcbcx_stats(struct bfa_cee_dcbx_stats_s *dcbcx_stats)
-{
- dcbcx_stats->subtlvs_unrecognized =
- bfa_os_ntohl(dcbcx_stats->subtlvs_unrecognized);
- dcbcx_stats->negotiation_failed =
- bfa_os_ntohl(dcbcx_stats->negotiation_failed);
- dcbcx_stats->remote_cfg_changed =
- bfa_os_ntohl(dcbcx_stats->remote_cfg_changed);
- dcbcx_stats->tlvs_received = bfa_os_ntohl(dcbcx_stats->tlvs_received);
- dcbcx_stats->tlvs_invalid = bfa_os_ntohl(dcbcx_stats->tlvs_invalid);
- dcbcx_stats->seqno = bfa_os_ntohl(dcbcx_stats->seqno);
- dcbcx_stats->ackno = bfa_os_ntohl(dcbcx_stats->ackno);
- dcbcx_stats->recvd_seqno = bfa_os_ntohl(dcbcx_stats->recvd_seqno);
- dcbcx_stats->recvd_ackno = bfa_os_ntohl(dcbcx_stats->recvd_ackno);
-}
-
-static void
-bfa_cee_format_lldp_stats(struct bfa_cee_lldp_stats_s *lldp_stats)
-{
- lldp_stats->frames_transmitted =
- bfa_os_ntohl(lldp_stats->frames_transmitted);
- lldp_stats->frames_aged_out = bfa_os_ntohl(lldp_stats->frames_aged_out);
- lldp_stats->frames_discarded =
- bfa_os_ntohl(lldp_stats->frames_discarded);
- lldp_stats->frames_in_error = bfa_os_ntohl(lldp_stats->frames_in_error);
- lldp_stats->frames_rcvd = bfa_os_ntohl(lldp_stats->frames_rcvd);
- lldp_stats->tlvs_discarded = bfa_os_ntohl(lldp_stats->tlvs_discarded);
- lldp_stats->tlvs_unrecognized =
- bfa_os_ntohl(lldp_stats->tlvs_unrecognized);
-}
-
-static void
-bfa_cee_format_cfg_stats(struct bfa_cee_cfg_stats_s *cfg_stats)
-{
- cfg_stats->cee_status_down = bfa_os_ntohl(cfg_stats->cee_status_down);
- cfg_stats->cee_status_up = bfa_os_ntohl(cfg_stats->cee_status_up);
- cfg_stats->cee_hw_cfg_changed =
- bfa_os_ntohl(cfg_stats->cee_hw_cfg_changed);
- cfg_stats->recvd_invalid_cfg =
- bfa_os_ntohl(cfg_stats->recvd_invalid_cfg);
-}
-
-static void
-bfa_cee_format_lldp_cfg(struct bfa_cee_lldp_cfg_s *lldp_cfg)
-{
- lldp_cfg->time_to_interval = bfa_os_ntohs(lldp_cfg->time_to_interval);
- lldp_cfg->enabled_system_cap =
- bfa_os_ntohs(lldp_cfg->enabled_system_cap);
-}
-
-/**
- * bfa_cee_attr_meminfo()
- *
- *
- * @param[in] void
- *
- * @return Size of DMA region
- */
-static u32
-bfa_cee_attr_meminfo(void)
-{
- return BFA_ROUNDUP(sizeof(struct bfa_cee_attr_s), BFA_DMA_ALIGN_SZ);
-}
-
-/**
- * bfa_cee_stats_meminfo()
- *
- *
- * @param[in] void
- *
- * @return Size of DMA region
- */
-static u32
-bfa_cee_stats_meminfo(void)
-{
- return BFA_ROUNDUP(sizeof(struct bfa_cee_stats_s), BFA_DMA_ALIGN_SZ);
-}
-
-/**
- * bfa_cee_get_attr_isr()
- *
- *
- * @param[in] cee - Pointer to the CEE module
- * status - Return status from the f/w
- *
- * @return void
- */
-static void
-bfa_cee_get_attr_isr(struct bfa_cee_s *cee, bfa_status_t status)
-{
- cee->get_attr_status = status;
- bfa_trc(cee, 0);
- if (status == BFA_STATUS_OK) {
- bfa_trc(cee, 0);
- /*
- * The requested data has been copied to the DMA area, *process
- * it.
- */
- memcpy(cee->attr, cee->attr_dma.kva,
- sizeof(struct bfa_cee_attr_s));
- bfa_cee_format_cee_cfg(cee->attr);
- }
- cee->get_attr_pending = BFA_FALSE;
- if (cee->cbfn.get_attr_cbfn) {
- bfa_trc(cee, 0);
- cee->cbfn.get_attr_cbfn(cee->cbfn.get_attr_cbarg, status);
- }
- bfa_trc(cee, 0);
-}
-
-/**
- * bfa_cee_get_attr_isr()
- *
- *
- * @param[in] cee - Pointer to the CEE module
- * status - Return status from the f/w
- *
- * @return void
- */
-static void
-bfa_cee_get_stats_isr(struct bfa_cee_s *cee, bfa_status_t status)
-{
- cee->get_stats_status = status;
- bfa_trc(cee, 0);
- if (status == BFA_STATUS_OK) {
- bfa_trc(cee, 0);
- /*
- * The requested data has been copied to the DMA area, process
- * it.
- */
- memcpy(cee->stats, cee->stats_dma.kva,
- sizeof(struct bfa_cee_stats_s));
- bfa_cee_format_cee_stats(cee->stats);
- }
- cee->get_stats_pending = BFA_FALSE;
- bfa_trc(cee, 0);
- if (cee->cbfn.get_stats_cbfn) {
- bfa_trc(cee, 0);
- cee->cbfn.get_stats_cbfn(cee->cbfn.get_stats_cbarg, status);
- }
- bfa_trc(cee, 0);
-}
-
-/**
- * bfa_cee_get_attr_isr()
- *
- *
- * @param[in] cee - Pointer to the CEE module
- * status - Return status from the f/w
- *
- * @return void
- */
-static void
-bfa_cee_reset_stats_isr(struct bfa_cee_s *cee, bfa_status_t status)
-{
- cee->reset_stats_status = status;
- cee->reset_stats_pending = BFA_FALSE;
- if (cee->cbfn.reset_stats_cbfn)
- cee->cbfn.reset_stats_cbfn(cee->cbfn.reset_stats_cbarg, status);
-}
-
-/**
- * bfa_cee_meminfo()
- *
- *
- * @param[in] void
- *
- * @return Size of DMA region
- */
-u32
-bfa_cee_meminfo(void)
-{
- return bfa_cee_attr_meminfo() + bfa_cee_stats_meminfo();
-}
-
-/**
- * bfa_cee_mem_claim()
- *
- *
- * @param[in] cee CEE module pointer
- * dma_kva Kernel Virtual Address of CEE DMA Memory
- * dma_pa Physical Address of CEE DMA Memory
- *
- * @return void
- */
-void
-bfa_cee_mem_claim(struct bfa_cee_s *cee, u8 *dma_kva, u64 dma_pa)
-{
- cee->attr_dma.kva = dma_kva;
- cee->attr_dma.pa = dma_pa;
- cee->stats_dma.kva = dma_kva + bfa_cee_attr_meminfo();
- cee->stats_dma.pa = dma_pa + bfa_cee_attr_meminfo();
- cee->attr = (struct bfa_cee_attr_s *)dma_kva;
- cee->stats =
- (struct bfa_cee_stats_s *)(dma_kva + bfa_cee_attr_meminfo());
-}
-
-/**
- * bfa_cee_get_attr()
- *
- * Send the request to the f/w to fetch CEE attributes.
- *
- * @param[in] Pointer to the CEE module data structure.
- *
- * @return Status
- */
-
-bfa_status_t
-bfa_cee_get_attr(struct bfa_cee_s *cee, struct bfa_cee_attr_s *attr,
- bfa_cee_get_attr_cbfn_t cbfn, void *cbarg)
-{
- struct bfi_cee_get_req_s *cmd;
-
- bfa_assert((cee != NULL) && (cee->ioc != NULL));
- bfa_trc(cee, 0);
- if (!bfa_ioc_is_operational(cee->ioc)) {
- bfa_trc(cee, 0);
- return BFA_STATUS_IOC_FAILURE;
- }
- if (cee->get_attr_pending == BFA_TRUE) {
- bfa_trc(cee, 0);
- return BFA_STATUS_DEVBUSY;
- }
- cee->get_attr_pending = BFA_TRUE;
- cmd = (struct bfi_cee_get_req_s *)cee->get_cfg_mb.msg;
- cee->attr = attr;
- cee->cbfn.get_attr_cbfn = cbfn;
- cee->cbfn.get_attr_cbarg = cbarg;
- bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_GET_CFG_REQ,
- bfa_ioc_portid(cee->ioc));
- bfa_dma_be_addr_set(cmd->dma_addr, cee->attr_dma.pa);
- bfa_ioc_mbox_queue(cee->ioc, &cee->get_cfg_mb);
- bfa_trc(cee, 0);
-
- return BFA_STATUS_OK;
-}
-
-/**
- * bfa_cee_get_stats()
- *
- * Send the request to the f/w to fetch CEE statistics.
- *
- * @param[in] Pointer to the CEE module data structure.
- *
- * @return Status
- */
-
-bfa_status_t
-bfa_cee_get_stats(struct bfa_cee_s *cee, struct bfa_cee_stats_s *stats,
- bfa_cee_get_stats_cbfn_t cbfn, void *cbarg)
-{
- struct bfi_cee_get_req_s *cmd;
-
- bfa_assert((cee != NULL) && (cee->ioc != NULL));
-
- if (!bfa_ioc_is_operational(cee->ioc)) {
- bfa_trc(cee, 0);
- return BFA_STATUS_IOC_FAILURE;
- }
- if (cee->get_stats_pending == BFA_TRUE) {
- bfa_trc(cee, 0);
- return BFA_STATUS_DEVBUSY;
- }
- cee->get_stats_pending = BFA_TRUE;
- cmd = (struct bfi_cee_get_req_s *)cee->get_stats_mb.msg;
- cee->stats = stats;
- cee->cbfn.get_stats_cbfn = cbfn;
- cee->cbfn.get_stats_cbarg = cbarg;
- bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_GET_STATS_REQ,
- bfa_ioc_portid(cee->ioc));
- bfa_dma_be_addr_set(cmd->dma_addr, cee->stats_dma.pa);
- bfa_ioc_mbox_queue(cee->ioc, &cee->get_stats_mb);
- bfa_trc(cee, 0);
-
- return BFA_STATUS_OK;
-}
-
-/**
- * bfa_cee_reset_stats()
- *
- *
- * @param[in] Pointer to the CEE module data structure.
- *
- * @return Status
- */
-
-bfa_status_t
-bfa_cee_reset_stats(struct bfa_cee_s *cee, bfa_cee_reset_stats_cbfn_t cbfn,
- void *cbarg)
-{
- struct bfi_cee_reset_stats_s *cmd;
-
- bfa_assert((cee != NULL) && (cee->ioc != NULL));
- if (!bfa_ioc_is_operational(cee->ioc)) {
- bfa_trc(cee, 0);
- return BFA_STATUS_IOC_FAILURE;
- }
- if (cee->reset_stats_pending == BFA_TRUE) {
- bfa_trc(cee, 0);
- return BFA_STATUS_DEVBUSY;
- }
- cee->reset_stats_pending = BFA_TRUE;
- cmd = (struct bfi_cee_reset_stats_s *)cee->reset_stats_mb.msg;
- cee->cbfn.reset_stats_cbfn = cbfn;
- cee->cbfn.reset_stats_cbarg = cbarg;
- bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_RESET_STATS,
- bfa_ioc_portid(cee->ioc));
- bfa_ioc_mbox_queue(cee->ioc, &cee->reset_stats_mb);
- bfa_trc(cee, 0);
- return BFA_STATUS_OK;
-}
-
-/**
- * bfa_cee_isrs()
- *
- *
- * @param[in] Pointer to the CEE module data structure.
- *
- * @return void
- */
-
-void
-bfa_cee_isr(void *cbarg, struct bfi_mbmsg_s *m)
-{
- union bfi_cee_i2h_msg_u *msg;
- struct bfi_cee_get_rsp_s *get_rsp;
- struct bfa_cee_s *cee = (struct bfa_cee_s *)cbarg;
- msg = (union bfi_cee_i2h_msg_u *)m;
- get_rsp = (struct bfi_cee_get_rsp_s *)m;
- bfa_trc(cee, msg->mh.msg_id);
- switch (msg->mh.msg_id) {
- case BFI_CEE_I2H_GET_CFG_RSP:
- bfa_trc(cee, get_rsp->cmd_status);
- bfa_cee_get_attr_isr(cee, get_rsp->cmd_status);
- break;
- case BFI_CEE_I2H_GET_STATS_RSP:
- bfa_cee_get_stats_isr(cee, get_rsp->cmd_status);
- break;
- case BFI_CEE_I2H_RESET_STATS_RSP:
- bfa_cee_reset_stats_isr(cee, get_rsp->cmd_status);
- break;
- default:
- bfa_assert(0);
- }
-}
-
-/**
- * bfa_cee_hbfail()
- *
- *
- * @param[in] Pointer to the CEE module data structure.
- *
- * @return void
- */
-
-void
-bfa_cee_hbfail(void *arg)
-{
- struct bfa_cee_s *cee;
- cee = (struct bfa_cee_s *)arg;
-
- if (cee->get_attr_pending == BFA_TRUE) {
- cee->get_attr_status = BFA_STATUS_FAILED;
- cee->get_attr_pending = BFA_FALSE;
- if (cee->cbfn.get_attr_cbfn) {
- cee->cbfn.get_attr_cbfn(cee->cbfn.get_attr_cbarg,
- BFA_STATUS_FAILED);
- }
- }
- if (cee->get_stats_pending == BFA_TRUE) {
- cee->get_stats_status = BFA_STATUS_FAILED;
- cee->get_stats_pending = BFA_FALSE;
- if (cee->cbfn.get_stats_cbfn) {
- cee->cbfn.get_stats_cbfn(cee->cbfn.get_stats_cbarg,
- BFA_STATUS_FAILED);
- }
- }
- if (cee->reset_stats_pending == BFA_TRUE) {
- cee->reset_stats_status = BFA_STATUS_FAILED;
- cee->reset_stats_pending = BFA_FALSE;
- if (cee->cbfn.reset_stats_cbfn) {
- cee->cbfn.reset_stats_cbfn(cee->cbfn.reset_stats_cbarg,
- BFA_STATUS_FAILED);
- }
- }
-}
-
-/**
- * bfa_cee_attach()
- *
- *
- * @param[in] cee - Pointer to the CEE module data structure
- * ioc - Pointer to the ioc module data structure
- * dev - Pointer to the device driver module data structure
- * The device driver specific mbox ISR functions have
- * this pointer as one of the parameters.
- * trcmod -
- * logmod -
- *
- * @return void
- */
-void
-bfa_cee_attach(struct bfa_cee_s *cee, struct bfa_ioc_s *ioc, void *dev,
- struct bfa_trc_mod_s *trcmod, struct bfa_log_mod_s *logmod)
-{
- bfa_assert(cee != NULL);
- cee->dev = dev;
- cee->trcmod = trcmod;
- cee->logmod = logmod;
- cee->ioc = ioc;
-
- bfa_ioc_mbox_regisr(cee->ioc, BFI_MC_CEE, bfa_cee_isr, cee);
- bfa_ioc_hbfail_init(&cee->hbfail, bfa_cee_hbfail, cee);
- bfa_ioc_hbfail_register(cee->ioc, &cee->hbfail);
- bfa_trc(cee, 0);
-}
-
-/**
- * bfa_cee_detach()
- *
- *
- * @param[in] cee - Pointer to the CEE module data structure
- *
- * @return void
- */
-void
-bfa_cee_detach(struct bfa_cee_s *cee)
-{
- /*
- * For now, just check if there is some ioctl pending and mark that as
- * failed?
- */
- /* bfa_cee_hbfail(cee); */
-}
diff --git a/drivers/scsi/bfa/bfa_core.c b/drivers/scsi/bfa/bfa_core.c
index 76fa5c5b40dd..c2fa07f2485d 100644
--- a/drivers/scsi/bfa/bfa_core.c
+++ b/drivers/scsi/bfa/bfa_core.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
* All rights reserved
* www.brocade.com
*
@@ -15,27 +15,992 @@
* General Public License for more details.
*/
-#include <bfa.h>
-#include <defs/bfa_defs_pci.h>
-#include <cs/bfa_debug.h>
-#include <bfa_iocfc.h>
+#include "bfa_modules.h"
+#include "bfi_ctreg.h"
+#include "bfad_drv.h"
-#define DEF_CFG_NUM_FABRICS 1
-#define DEF_CFG_NUM_LPORTS 256
-#define DEF_CFG_NUM_CQS 4
-#define DEF_CFG_NUM_IOIM_REQS (BFA_IOIM_MAX)
-#define DEF_CFG_NUM_TSKIM_REQS 128
-#define DEF_CFG_NUM_FCXP_REQS 64
-#define DEF_CFG_NUM_UF_BUFS 64
-#define DEF_CFG_NUM_RPORTS 1024
-#define DEF_CFG_NUM_ITNIMS (DEF_CFG_NUM_RPORTS)
-#define DEF_CFG_NUM_TINS 256
+BFA_TRC_FILE(HAL, CORE);
-#define DEF_CFG_NUM_SGPGS 2048
-#define DEF_CFG_NUM_REQQ_ELEMS 256
-#define DEF_CFG_NUM_RSPQ_ELEMS 64
-#define DEF_CFG_NUM_SBOOT_TGTS 16
-#define DEF_CFG_NUM_SBOOT_LUNS 16
+/**
+ * BFA IOC FC related definitions
+ */
+
+/**
+ * IOC local definitions
+ */
+#define BFA_IOCFC_TOV 5000 /* msecs */
+
+enum {
+ BFA_IOCFC_ACT_NONE = 0,
+ BFA_IOCFC_ACT_INIT = 1,
+ BFA_IOCFC_ACT_STOP = 2,
+ BFA_IOCFC_ACT_DISABLE = 3,
+};
+
+#define DEF_CFG_NUM_FABRICS 1
+#define DEF_CFG_NUM_LPORTS 256
+#define DEF_CFG_NUM_CQS 4
+#define DEF_CFG_NUM_IOIM_REQS (BFA_IOIM_MAX)
+#define DEF_CFG_NUM_TSKIM_REQS 128
+#define DEF_CFG_NUM_FCXP_REQS 64
+#define DEF_CFG_NUM_UF_BUFS 64
+#define DEF_CFG_NUM_RPORTS 1024
+#define DEF_CFG_NUM_ITNIMS (DEF_CFG_NUM_RPORTS)
+#define DEF_CFG_NUM_TINS 256
+
+#define DEF_CFG_NUM_SGPGS 2048
+#define DEF_CFG_NUM_REQQ_ELEMS 256
+#define DEF_CFG_NUM_RSPQ_ELEMS 64
+#define DEF_CFG_NUM_SBOOT_TGTS 16
+#define DEF_CFG_NUM_SBOOT_LUNS 16
+
+/**
+ * forward declaration for IOC FC functions
+ */
+static void bfa_iocfc_enable_cbfn(void *bfa_arg, enum bfa_status status);
+static void bfa_iocfc_disable_cbfn(void *bfa_arg);
+static void bfa_iocfc_hbfail_cbfn(void *bfa_arg);
+static void bfa_iocfc_reset_cbfn(void *bfa_arg);
+static struct bfa_ioc_cbfn_s bfa_iocfc_cbfn;
+
+/**
+ * BFA Interrupt handling functions
+ */
+static void
+bfa_msix_errint(struct bfa_s *bfa, u32 intr)
+{
+ bfa_ioc_error_isr(&bfa->ioc);
+}
+
+static void
+bfa_msix_lpu(struct bfa_s *bfa)
+{
+ bfa_ioc_mbox_isr(&bfa->ioc);
+}
+
+static void
+bfa_reqq_resume(struct bfa_s *bfa, int qid)
+{
+ struct list_head *waitq, *qe, *qen;
+ struct bfa_reqq_wait_s *wqe;
+
+ waitq = bfa_reqq(bfa, qid);
+ list_for_each_safe(qe, qen, waitq) {
+ /**
+ * Callback only as long as there is room in request queue
+ */
+ if (bfa_reqq_full(bfa, qid))
+ break;
+
+ list_del(qe);
+ wqe = (struct bfa_reqq_wait_s *) qe;
+ wqe->qresume(wqe->cbarg);
+ }
+}
+
+void
+bfa_msix_all(struct bfa_s *bfa, int vec)
+{
+ bfa_intx(bfa);
+}
+
+/**
+ * hal_intr_api
+ */
+bfa_boolean_t
+bfa_intx(struct bfa_s *bfa)
+{
+ u32 intr, qintr;
+ int queue;
+
+ intr = bfa_reg_read(bfa->iocfc.bfa_regs.intr_status);
+ if (!intr)
+ return BFA_FALSE;
+
+ /**
+ * RME completion queue interrupt
+ */
+ qintr = intr & __HFN_INT_RME_MASK;
+ bfa_reg_write(bfa->iocfc.bfa_regs.intr_status, qintr);
+
+ for (queue = 0; queue < BFI_IOC_MAX_CQS_ASIC; queue++) {
+ if (intr & (__HFN_INT_RME_Q0 << queue))
+ bfa_msix_rspq(bfa, queue & (BFI_IOC_MAX_CQS - 1));
+ }
+ intr &= ~qintr;
+ if (!intr)
+ return BFA_TRUE;
+
+ /**
+ * CPE completion queue interrupt
+ */
+ qintr = intr & __HFN_INT_CPE_MASK;
+ bfa_reg_write(bfa->iocfc.bfa_regs.intr_status, qintr);
+
+ for (queue = 0; queue < BFI_IOC_MAX_CQS_ASIC; queue++) {
+ if (intr & (__HFN_INT_CPE_Q0 << queue))
+ bfa_msix_reqq(bfa, queue & (BFI_IOC_MAX_CQS - 1));
+ }
+ intr &= ~qintr;
+ if (!intr)
+ return BFA_TRUE;
+
+ bfa_msix_lpu_err(bfa, intr);
+
+ return BFA_TRUE;
+}
+
+void
+bfa_intx_enable(struct bfa_s *bfa)
+{
+ bfa_reg_write(bfa->iocfc.bfa_regs.intr_mask, bfa->iocfc.intr_mask);
+}
+
+void
+bfa_intx_disable(struct bfa_s *bfa)
+{
+ bfa_reg_write(bfa->iocfc.bfa_regs.intr_mask, -1L);
+}
+
+void
+bfa_isr_enable(struct bfa_s *bfa)
+{
+ u32 intr_unmask;
+ int pci_func = bfa_ioc_pcifn(&bfa->ioc);
+
+ bfa_trc(bfa, pci_func);
+
+ bfa_msix_install(bfa);
+ intr_unmask = (__HFN_INT_ERR_EMC | __HFN_INT_ERR_LPU0 |
+ __HFN_INT_ERR_LPU1 | __HFN_INT_ERR_PSS |
+ __HFN_INT_LL_HALT);
+
+ if (pci_func == 0)
+ intr_unmask |= (__HFN_INT_CPE_Q0 | __HFN_INT_CPE_Q1 |
+ __HFN_INT_CPE_Q2 | __HFN_INT_CPE_Q3 |
+ __HFN_INT_RME_Q0 | __HFN_INT_RME_Q1 |
+ __HFN_INT_RME_Q2 | __HFN_INT_RME_Q3 |
+ __HFN_INT_MBOX_LPU0);
+ else
+ intr_unmask |= (__HFN_INT_CPE_Q4 | __HFN_INT_CPE_Q5 |
+ __HFN_INT_CPE_Q6 | __HFN_INT_CPE_Q7 |
+ __HFN_INT_RME_Q4 | __HFN_INT_RME_Q5 |
+ __HFN_INT_RME_Q6 | __HFN_INT_RME_Q7 |
+ __HFN_INT_MBOX_LPU1);
+
+ bfa_reg_write(bfa->iocfc.bfa_regs.intr_status, intr_unmask);
+ bfa_reg_write(bfa->iocfc.bfa_regs.intr_mask, ~intr_unmask);
+ bfa->iocfc.intr_mask = ~intr_unmask;
+ bfa_isr_mode_set(bfa, bfa->msix.nvecs != 0);
+}
+
+void
+bfa_isr_disable(struct bfa_s *bfa)
+{
+ bfa_isr_mode_set(bfa, BFA_FALSE);
+ bfa_reg_write(bfa->iocfc.bfa_regs.intr_mask, -1L);
+ bfa_msix_uninstall(bfa);
+}
+
+void
+bfa_msix_reqq(struct bfa_s *bfa, int qid)
+{
+ struct list_head *waitq;
+
+ qid &= (BFI_IOC_MAX_CQS - 1);
+
+ bfa->iocfc.hwif.hw_reqq_ack(bfa, qid);
+
+ /**
+ * Resume any pending requests in the corresponding reqq.
+ */
+ waitq = bfa_reqq(bfa, qid);
+ if (!list_empty(waitq))
+ bfa_reqq_resume(bfa, qid);
+}
+
+void
+bfa_isr_unhandled(struct bfa_s *bfa, struct bfi_msg_s *m)
+{
+ bfa_trc(bfa, m->mhdr.msg_class);
+ bfa_trc(bfa, m->mhdr.msg_id);
+ bfa_trc(bfa, m->mhdr.mtag.i2htok);
+ bfa_assert(0);
+ bfa_trc_stop(bfa->trcmod);
+}
+
+void
+bfa_msix_rspq(struct bfa_s *bfa, int qid)
+{
+ struct bfi_msg_s *m;
+ u32 pi, ci;
+ struct list_head *waitq;
+
+ bfa_trc_fp(bfa, qid);
+
+ qid &= (BFI_IOC_MAX_CQS - 1);
+
+ bfa->iocfc.hwif.hw_rspq_ack(bfa, qid);
+
+ ci = bfa_rspq_ci(bfa, qid);
+ pi = bfa_rspq_pi(bfa, qid);
+
+ bfa_trc_fp(bfa, ci);
+ bfa_trc_fp(bfa, pi);
+
+ if (bfa->rme_process) {
+ while (ci != pi) {
+ m = bfa_rspq_elem(bfa, qid, ci);
+ bfa_assert_fp(m->mhdr.msg_class < BFI_MC_MAX);
+
+ bfa_isrs[m->mhdr.msg_class] (bfa, m);
+
+ CQ_INCR(ci, bfa->iocfc.cfg.drvcfg.num_rspq_elems);
+ }
+ }
+
+ /**
+ * update CI
+ */
+ bfa_rspq_ci(bfa, qid) = pi;
+ bfa_reg_write(bfa->iocfc.bfa_regs.rme_q_ci[qid], pi);
+ mmiowb();
+
+ /**
+ * Resume any pending requests in the corresponding reqq.
+ */
+ waitq = bfa_reqq(bfa, qid);
+ if (!list_empty(waitq))
+ bfa_reqq_resume(bfa, qid);
+}
+
+void
+bfa_msix_lpu_err(struct bfa_s *bfa, int vec)
+{
+ u32 intr, curr_value;
+
+ intr = bfa_reg_read(bfa->iocfc.bfa_regs.intr_status);
+
+ if (intr & (__HFN_INT_MBOX_LPU0 | __HFN_INT_MBOX_LPU1))
+ bfa_msix_lpu(bfa);
+
+ intr &= (__HFN_INT_ERR_EMC | __HFN_INT_ERR_LPU0 |
+ __HFN_INT_ERR_LPU1 | __HFN_INT_ERR_PSS | __HFN_INT_LL_HALT);
+
+ if (intr) {
+ if (intr & __HFN_INT_LL_HALT) {
+ /**
+ * If LL_HALT bit is set then FW Init Halt LL Port
+ * Register needs to be cleared as well so Interrupt
+ * Status Register will be cleared.
+ */
+ curr_value = bfa_reg_read(bfa->ioc.ioc_regs.ll_halt);
+ curr_value &= ~__FW_INIT_HALT_P;
+ bfa_reg_write(bfa->ioc.ioc_regs.ll_halt, curr_value);
+ }
+
+ if (intr & __HFN_INT_ERR_PSS) {
+ /**
+ * ERR_PSS bit needs to be cleared as well in case
+ * interrups are shared so driver's interrupt handler is
+ * still called eventhough it is already masked out.
+ */
+ curr_value = bfa_reg_read(
+ bfa->ioc.ioc_regs.pss_err_status_reg);
+ curr_value &= __PSS_ERR_STATUS_SET;
+ bfa_reg_write(bfa->ioc.ioc_regs.pss_err_status_reg,
+ curr_value);
+ }
+
+ bfa_reg_write(bfa->iocfc.bfa_regs.intr_status, intr);
+ bfa_msix_errint(bfa, intr);
+ }
+}
+
+void
+bfa_isr_bind(enum bfi_mclass mc, bfa_isr_func_t isr_func)
+{
+ bfa_isrs[mc] = isr_func;
+}
+
+/**
+ * BFA IOC FC related functions
+ */
+
+/**
+ * hal_ioc_pvt BFA IOC private functions
+ */
+
+static void
+bfa_iocfc_cqs_sz(struct bfa_iocfc_cfg_s *cfg, u32 *dm_len)
+{
+ int i, per_reqq_sz, per_rspq_sz;
+
+ per_reqq_sz = BFA_ROUNDUP((cfg->drvcfg.num_reqq_elems * BFI_LMSG_SZ),
+ BFA_DMA_ALIGN_SZ);
+ per_rspq_sz = BFA_ROUNDUP((cfg->drvcfg.num_rspq_elems * BFI_LMSG_SZ),
+ BFA_DMA_ALIGN_SZ);
+
+ /*
+ * Calculate CQ size
+ */
+ for (i = 0; i < cfg->fwcfg.num_cqs; i++) {
+ *dm_len = *dm_len + per_reqq_sz;
+ *dm_len = *dm_len + per_rspq_sz;
+ }
+
+ /*
+ * Calculate Shadow CI/PI size
+ */
+ for (i = 0; i < cfg->fwcfg.num_cqs; i++)
+ *dm_len += (2 * BFA_CACHELINE_SZ);
+}
+
+static void
+bfa_iocfc_fw_cfg_sz(struct bfa_iocfc_cfg_s *cfg, u32 *dm_len)
+{
+ *dm_len +=
+ BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfg_s), BFA_CACHELINE_SZ);
+ *dm_len +=
+ BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s),
+ BFA_CACHELINE_SZ);
+}
+
+/**
+ * Use the Mailbox interface to send BFI_IOCFC_H2I_CFG_REQ
+ */
+static void
+bfa_iocfc_send_cfg(void *bfa_arg)
+{
+ struct bfa_s *bfa = bfa_arg;
+ struct bfa_iocfc_s *iocfc = &bfa->iocfc;
+ struct bfi_iocfc_cfg_req_s cfg_req;
+ struct bfi_iocfc_cfg_s *cfg_info = iocfc->cfginfo;
+ struct bfa_iocfc_cfg_s *cfg = &iocfc->cfg;
+ int i;
+
+ bfa_assert(cfg->fwcfg.num_cqs <= BFI_IOC_MAX_CQS);
+ bfa_trc(bfa, cfg->fwcfg.num_cqs);
+
+ bfa_iocfc_reset_queues(bfa);
+
+ /**
+ * initialize IOC configuration info
+ */
+ cfg_info->endian_sig = BFI_IOC_ENDIAN_SIG;
+ cfg_info->num_cqs = cfg->fwcfg.num_cqs;
+
+ bfa_dma_be_addr_set(cfg_info->cfgrsp_addr, iocfc->cfgrsp_dma.pa);
+ /**
+ * dma map REQ and RSP circular queues and shadow pointers
+ */
+ for (i = 0; i < cfg->fwcfg.num_cqs; i++) {
+ bfa_dma_be_addr_set(cfg_info->req_cq_ba[i],
+ iocfc->req_cq_ba[i].pa);
+ bfa_dma_be_addr_set(cfg_info->req_shadow_ci[i],
+ iocfc->req_cq_shadow_ci[i].pa);
+ cfg_info->req_cq_elems[i] =
+ bfa_os_htons(cfg->drvcfg.num_reqq_elems);
+
+ bfa_dma_be_addr_set(cfg_info->rsp_cq_ba[i],
+ iocfc->rsp_cq_ba[i].pa);
+ bfa_dma_be_addr_set(cfg_info->rsp_shadow_pi[i],
+ iocfc->rsp_cq_shadow_pi[i].pa);
+ cfg_info->rsp_cq_elems[i] =
+ bfa_os_htons(cfg->drvcfg.num_rspq_elems);
+ }
+
+ /**
+ * Enable interrupt coalescing if it is driver init path
+ * and not ioc disable/enable path.
+ */
+ if (!iocfc->cfgdone)
+ cfg_info->intr_attr.coalesce = BFA_TRUE;
+
+ iocfc->cfgdone = BFA_FALSE;
+
+ /**
+ * dma map IOC configuration itself
+ */
+ bfi_h2i_set(cfg_req.mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_CFG_REQ,
+ bfa_lpuid(bfa));
+ bfa_dma_be_addr_set(cfg_req.ioc_cfg_dma_addr, iocfc->cfg_info.pa);
+
+ bfa_ioc_mbox_send(&bfa->ioc, &cfg_req,
+ sizeof(struct bfi_iocfc_cfg_req_s));
+}
+
+static void
+bfa_iocfc_init_mem(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
+ struct bfa_pcidev_s *pcidev)
+{
+ struct bfa_iocfc_s *iocfc = &bfa->iocfc;
+
+ bfa->bfad = bfad;
+ iocfc->bfa = bfa;
+ iocfc->action = BFA_IOCFC_ACT_NONE;
+
+ bfa_os_assign(iocfc->cfg, *cfg);
+
+ /**
+ * Initialize chip specific handlers.
+ */
+ if (bfa_asic_id_ct(bfa_ioc_devid(&bfa->ioc))) {
+ iocfc->hwif.hw_reginit = bfa_hwct_reginit;
+ iocfc->hwif.hw_reqq_ack = bfa_hwct_reqq_ack;
+ iocfc->hwif.hw_rspq_ack = bfa_hwct_rspq_ack;
+ iocfc->hwif.hw_msix_init = bfa_hwct_msix_init;
+ iocfc->hwif.hw_msix_install = bfa_hwct_msix_install;
+ iocfc->hwif.hw_msix_uninstall = bfa_hwct_msix_uninstall;
+ iocfc->hwif.hw_isr_mode_set = bfa_hwct_isr_mode_set;
+ iocfc->hwif.hw_msix_getvecs = bfa_hwct_msix_getvecs;
+ iocfc->hwif.hw_msix_get_rme_range = bfa_hwct_msix_get_rme_range;
+ } else {
+ iocfc->hwif.hw_reginit = bfa_hwcb_reginit;
+ iocfc->hwif.hw_reqq_ack = bfa_hwcb_reqq_ack;
+ iocfc->hwif.hw_rspq_ack = bfa_hwcb_rspq_ack;
+ iocfc->hwif.hw_msix_init = bfa_hwcb_msix_init;
+ iocfc->hwif.hw_msix_install = bfa_hwcb_msix_install;
+ iocfc->hwif.hw_msix_uninstall = bfa_hwcb_msix_uninstall;
+ iocfc->hwif.hw_isr_mode_set = bfa_hwcb_isr_mode_set;
+ iocfc->hwif.hw_msix_getvecs = bfa_hwcb_msix_getvecs;
+ iocfc->hwif.hw_msix_get_rme_range = bfa_hwcb_msix_get_rme_range;
+ }
+
+ iocfc->hwif.hw_reginit(bfa);
+ bfa->msix.nvecs = 0;
+}
+
+static void
+bfa_iocfc_mem_claim(struct bfa_s *bfa, struct bfa_iocfc_cfg_s *cfg,
+ struct bfa_meminfo_s *meminfo)
+{
+ u8 *dm_kva;
+ u64 dm_pa;
+ int i, per_reqq_sz, per_rspq_sz;
+ struct bfa_iocfc_s *iocfc = &bfa->iocfc;
+ int dbgsz;
+
+ dm_kva = bfa_meminfo_dma_virt(meminfo);
+ dm_pa = bfa_meminfo_dma_phys(meminfo);
+
+ /*
+ * First allocate dma memory for IOC.
+ */
+ bfa_ioc_mem_claim(&bfa->ioc, dm_kva, dm_pa);
+ dm_kva += bfa_ioc_meminfo();
+ dm_pa += bfa_ioc_meminfo();
+
+ /*
+ * Claim DMA-able memory for the request/response queues and for shadow
+ * ci/pi registers
+ */
+ per_reqq_sz = BFA_ROUNDUP((cfg->drvcfg.num_reqq_elems * BFI_LMSG_SZ),
+ BFA_DMA_ALIGN_SZ);
+ per_rspq_sz = BFA_ROUNDUP((cfg->drvcfg.num_rspq_elems * BFI_LMSG_SZ),
+ BFA_DMA_ALIGN_SZ);
+
+ for (i = 0; i < cfg->fwcfg.num_cqs; i++) {
+ iocfc->req_cq_ba[i].kva = dm_kva;
+ iocfc->req_cq_ba[i].pa = dm_pa;
+ bfa_os_memset(dm_kva, 0, per_reqq_sz);
+ dm_kva += per_reqq_sz;
+ dm_pa += per_reqq_sz;
+
+ iocfc->rsp_cq_ba[i].kva = dm_kva;
+ iocfc->rsp_cq_ba[i].pa = dm_pa;
+ bfa_os_memset(dm_kva, 0, per_rspq_sz);
+ dm_kva += per_rspq_sz;
+ dm_pa += per_rspq_sz;
+ }
+
+ for (i = 0; i < cfg->fwcfg.num_cqs; i++) {
+ iocfc->req_cq_shadow_ci[i].kva = dm_kva;
+ iocfc->req_cq_shadow_ci[i].pa = dm_pa;
+ dm_kva += BFA_CACHELINE_SZ;
+ dm_pa += BFA_CACHELINE_SZ;
+
+ iocfc->rsp_cq_shadow_pi[i].kva = dm_kva;
+ iocfc->rsp_cq_shadow_pi[i].pa = dm_pa;
+ dm_kva += BFA_CACHELINE_SZ;
+ dm_pa += BFA_CACHELINE_SZ;
+ }
+
+ /*
+ * Claim DMA-able memory for the config info page
+ */
+ bfa->iocfc.cfg_info.kva = dm_kva;
+ bfa->iocfc.cfg_info.pa = dm_pa;
+ bfa->iocfc.cfginfo = (struct bfi_iocfc_cfg_s *) dm_kva;
+ dm_kva += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfg_s), BFA_CACHELINE_SZ);
+ dm_pa += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfg_s), BFA_CACHELINE_SZ);
+
+ /*
+ * Claim DMA-able memory for the config response
+ */
+ bfa->iocfc.cfgrsp_dma.kva = dm_kva;
+ bfa->iocfc.cfgrsp_dma.pa = dm_pa;
+ bfa->iocfc.cfgrsp = (struct bfi_iocfc_cfgrsp_s *) dm_kva;
+
+ dm_kva +=
+ BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s),
+ BFA_CACHELINE_SZ);
+ dm_pa += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s),
+ BFA_CACHELINE_SZ);
+
+
+ bfa_meminfo_dma_virt(meminfo) = dm_kva;
+ bfa_meminfo_dma_phys(meminfo) = dm_pa;
+
+ dbgsz = bfa_ioc_debug_trcsz(bfa_auto_recover);
+ if (dbgsz > 0) {
+ bfa_ioc_debug_memclaim(&bfa->ioc, bfa_meminfo_kva(meminfo));
+ bfa_meminfo_kva(meminfo) += dbgsz;
+ }
+}
+
+/**
+ * Start BFA submodules.
+ */
+static void
+bfa_iocfc_start_submod(struct bfa_s *bfa)
+{
+ int i;
+
+ bfa->rme_process = BFA_TRUE;
+
+ for (i = 0; hal_mods[i]; i++)
+ hal_mods[i]->start(bfa);
+}
+
+/**
+ * Disable BFA submodules.
+ */
+static void
+bfa_iocfc_disable_submod(struct bfa_s *bfa)
+{
+ int i;
+
+ for (i = 0; hal_mods[i]; i++)
+ hal_mods[i]->iocdisable(bfa);
+}
+
+static void
+bfa_iocfc_init_cb(void *bfa_arg, bfa_boolean_t complete)
+{
+ struct bfa_s *bfa = bfa_arg;
+
+ if (complete) {
+ if (bfa->iocfc.cfgdone)
+ bfa_cb_init(bfa->bfad, BFA_STATUS_OK);
+ else
+ bfa_cb_init(bfa->bfad, BFA_STATUS_FAILED);
+ } else {
+ if (bfa->iocfc.cfgdone)
+ bfa->iocfc.action = BFA_IOCFC_ACT_NONE;
+ }
+}
+
+static void
+bfa_iocfc_stop_cb(void *bfa_arg, bfa_boolean_t compl)
+{
+ struct bfa_s *bfa = bfa_arg;
+ struct bfad_s *bfad = bfa->bfad;
+
+ if (compl)
+ complete(&bfad->comp);
+ else
+ bfa->iocfc.action = BFA_IOCFC_ACT_NONE;
+}
+
+static void
+bfa_iocfc_disable_cb(void *bfa_arg, bfa_boolean_t compl)
+{
+ struct bfa_s *bfa = bfa_arg;
+ struct bfad_s *bfad = bfa->bfad;
+
+ if (compl)
+ complete(&bfad->disable_comp);
+}
+
+/**
+ * Update BFA configuration from firmware configuration.
+ */
+static void
+bfa_iocfc_cfgrsp(struct bfa_s *bfa)
+{
+ struct bfa_iocfc_s *iocfc = &bfa->iocfc;
+ struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp;
+ struct bfa_iocfc_fwcfg_s *fwcfg = &cfgrsp->fwcfg;
+
+ fwcfg->num_cqs = fwcfg->num_cqs;
+ fwcfg->num_ioim_reqs = bfa_os_ntohs(fwcfg->num_ioim_reqs);
+ fwcfg->num_tskim_reqs = bfa_os_ntohs(fwcfg->num_tskim_reqs);
+ fwcfg->num_fcxp_reqs = bfa_os_ntohs(fwcfg->num_fcxp_reqs);
+ fwcfg->num_uf_bufs = bfa_os_ntohs(fwcfg->num_uf_bufs);
+ fwcfg->num_rports = bfa_os_ntohs(fwcfg->num_rports);
+
+ iocfc->cfgdone = BFA_TRUE;
+
+ /**
+ * Configuration is complete - initialize/start submodules
+ */
+ bfa_fcport_init(bfa);
+
+ if (iocfc->action == BFA_IOCFC_ACT_INIT)
+ bfa_cb_queue(bfa, &iocfc->init_hcb_qe, bfa_iocfc_init_cb, bfa);
+ else
+ bfa_iocfc_start_submod(bfa);
+}
+void
+bfa_iocfc_reset_queues(struct bfa_s *bfa)
+{
+ int q;
+
+ for (q = 0; q < BFI_IOC_MAX_CQS; q++) {
+ bfa_reqq_ci(bfa, q) = 0;
+ bfa_reqq_pi(bfa, q) = 0;
+ bfa_rspq_ci(bfa, q) = 0;
+ bfa_rspq_pi(bfa, q) = 0;
+ }
+}
+
+/**
+ * IOC enable request is complete
+ */
+static void
+bfa_iocfc_enable_cbfn(void *bfa_arg, enum bfa_status status)
+{
+ struct bfa_s *bfa = bfa_arg;
+
+ if (status != BFA_STATUS_OK) {
+ bfa_isr_disable(bfa);
+ if (bfa->iocfc.action == BFA_IOCFC_ACT_INIT)
+ bfa_cb_queue(bfa, &bfa->iocfc.init_hcb_qe,
+ bfa_iocfc_init_cb, bfa);
+ return;
+ }
+
+ bfa_iocfc_send_cfg(bfa);
+}
+
+/**
+ * IOC disable request is complete
+ */
+static void
+bfa_iocfc_disable_cbfn(void *bfa_arg)
+{
+ struct bfa_s *bfa = bfa_arg;
+
+ bfa_isr_disable(bfa);
+ bfa_iocfc_disable_submod(bfa);
+
+ if (bfa->iocfc.action == BFA_IOCFC_ACT_STOP)
+ bfa_cb_queue(bfa, &bfa->iocfc.stop_hcb_qe, bfa_iocfc_stop_cb,
+ bfa);
+ else {
+ bfa_assert(bfa->iocfc.action == BFA_IOCFC_ACT_DISABLE);
+ bfa_cb_queue(bfa, &bfa->iocfc.dis_hcb_qe, bfa_iocfc_disable_cb,
+ bfa);
+ }
+}
+
+/**
+ * Notify sub-modules of hardware failure.
+ */
+static void
+bfa_iocfc_hbfail_cbfn(void *bfa_arg)
+{
+ struct bfa_s *bfa = bfa_arg;
+
+ bfa->rme_process = BFA_FALSE;
+
+ bfa_isr_disable(bfa);
+ bfa_iocfc_disable_submod(bfa);
+
+ if (bfa->iocfc.action == BFA_IOCFC_ACT_INIT)
+ bfa_cb_queue(bfa, &bfa->iocfc.init_hcb_qe, bfa_iocfc_init_cb,
+ bfa);
+}
+
+/**
+ * Actions on chip-reset completion.
+ */
+static void
+bfa_iocfc_reset_cbfn(void *bfa_arg)
+{
+ struct bfa_s *bfa = bfa_arg;
+
+ bfa_iocfc_reset_queues(bfa);
+ bfa_isr_enable(bfa);
+}
+
+/**
+ * hal_ioc_public
+ */
+
+/**
+ * Query IOC memory requirement information.
+ */
+void
+bfa_iocfc_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
+ u32 *dm_len)
+{
+ /* dma memory for IOC */
+ *dm_len += bfa_ioc_meminfo();
+
+ bfa_iocfc_fw_cfg_sz(cfg, dm_len);
+ bfa_iocfc_cqs_sz(cfg, dm_len);
+ *km_len += bfa_ioc_debug_trcsz(bfa_auto_recover);
+}
+
+/**
+ * Query IOC memory requirement information.
+ */
+void
+bfa_iocfc_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
+ struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
+{
+ int i;
+ struct bfa_ioc_s *ioc = &bfa->ioc;
+
+ bfa_iocfc_cbfn.enable_cbfn = bfa_iocfc_enable_cbfn;
+ bfa_iocfc_cbfn.disable_cbfn = bfa_iocfc_disable_cbfn;
+ bfa_iocfc_cbfn.hbfail_cbfn = bfa_iocfc_hbfail_cbfn;
+ bfa_iocfc_cbfn.reset_cbfn = bfa_iocfc_reset_cbfn;
+
+ ioc->trcmod = bfa->trcmod;
+ bfa_ioc_attach(&bfa->ioc, bfa, &bfa_iocfc_cbfn, &bfa->timer_mod);
+
+ /**
+ * Set FC mode for BFA_PCI_DEVICE_ID_CT_FC.
+ */
+ if (pcidev->device_id == BFA_PCI_DEVICE_ID_CT_FC)
+ bfa_ioc_set_fcmode(&bfa->ioc);
+
+ bfa_ioc_pci_init(&bfa->ioc, pcidev, BFI_MC_IOCFC);
+ bfa_ioc_mbox_register(&bfa->ioc, bfa_mbox_isrs);
+
+ bfa_iocfc_init_mem(bfa, bfad, cfg, pcidev);
+ bfa_iocfc_mem_claim(bfa, cfg, meminfo);
+ bfa_timer_init(&bfa->timer_mod);
+
+ INIT_LIST_HEAD(&bfa->comp_q);
+ for (i = 0; i < BFI_IOC_MAX_CQS; i++)
+ INIT_LIST_HEAD(&bfa->reqq_waitq[i]);
+}
+
+/**
+ * Query IOC memory requirement information.
+ */
+void
+bfa_iocfc_detach(struct bfa_s *bfa)
+{
+ bfa_ioc_detach(&bfa->ioc);
+}
+
+/**
+ * Query IOC memory requirement information.
+ */
+void
+bfa_iocfc_init(struct bfa_s *bfa)
+{
+ bfa->iocfc.action = BFA_IOCFC_ACT_INIT;
+ bfa_ioc_enable(&bfa->ioc);
+}
+
+/**
+ * IOC start called from bfa_start(). Called to start IOC operations
+ * at driver instantiation for this instance.
+ */
+void
+bfa_iocfc_start(struct bfa_s *bfa)
+{
+ if (bfa->iocfc.cfgdone)
+ bfa_iocfc_start_submod(bfa);
+}
+
+/**
+ * IOC stop called from bfa_stop(). Called only when driver is unloaded
+ * for this instance.
+ */
+void
+bfa_iocfc_stop(struct bfa_s *bfa)
+{
+ bfa->iocfc.action = BFA_IOCFC_ACT_STOP;
+
+ bfa->rme_process = BFA_FALSE;
+ bfa_ioc_disable(&bfa->ioc);
+}
+
+void
+bfa_iocfc_isr(void *bfaarg, struct bfi_mbmsg_s *m)
+{
+ struct bfa_s *bfa = bfaarg;
+ struct bfa_iocfc_s *iocfc = &bfa->iocfc;
+ union bfi_iocfc_i2h_msg_u *msg;
+
+ msg = (union bfi_iocfc_i2h_msg_u *) m;
+ bfa_trc(bfa, msg->mh.msg_id);
+
+ switch (msg->mh.msg_id) {
+ case BFI_IOCFC_I2H_CFG_REPLY:
+ iocfc->cfg_reply = &msg->cfg_reply;
+ bfa_iocfc_cfgrsp(bfa);
+ break;
+ case BFI_IOCFC_I2H_UPDATEQ_RSP:
+ iocfc->updateq_cbfn(iocfc->updateq_cbarg, BFA_STATUS_OK);
+ break;
+ default:
+ bfa_assert(0);
+ }
+}
+
+void
+bfa_adapter_get_attr(struct bfa_s *bfa, struct bfa_adapter_attr_s *ad_attr)
+{
+ bfa_ioc_get_adapter_attr(&bfa->ioc, ad_attr);
+}
+
+u64
+bfa_adapter_get_id(struct bfa_s *bfa)
+{
+ return bfa_ioc_get_adid(&bfa->ioc);
+}
+
+void
+bfa_iocfc_get_attr(struct bfa_s *bfa, struct bfa_iocfc_attr_s *attr)
+{
+ struct bfa_iocfc_s *iocfc = &bfa->iocfc;
+
+ attr->intr_attr.coalesce = iocfc->cfginfo->intr_attr.coalesce;
+
+ attr->intr_attr.delay = iocfc->cfginfo->intr_attr.delay ?
+ bfa_os_ntohs(iocfc->cfginfo->intr_attr.delay) :
+ bfa_os_ntohs(iocfc->cfgrsp->intr_attr.delay);
+
+ attr->intr_attr.latency = iocfc->cfginfo->intr_attr.latency ?
+ bfa_os_ntohs(iocfc->cfginfo->intr_attr.latency) :
+ bfa_os_ntohs(iocfc->cfgrsp->intr_attr.latency);
+
+ attr->config = iocfc->cfg;
+}
+
+bfa_status_t
+bfa_iocfc_israttr_set(struct bfa_s *bfa, struct bfa_iocfc_intr_attr_s *attr)
+{
+ struct bfa_iocfc_s *iocfc = &bfa->iocfc;
+ struct bfi_iocfc_set_intr_req_s *m;
+
+ iocfc->cfginfo->intr_attr.coalesce = attr->coalesce;
+ iocfc->cfginfo->intr_attr.delay = bfa_os_htons(attr->delay);
+ iocfc->cfginfo->intr_attr.latency = bfa_os_htons(attr->latency);
+
+ if (!bfa_iocfc_is_operational(bfa))
+ return BFA_STATUS_OK;
+
+ m = bfa_reqq_next(bfa, BFA_REQQ_IOC);
+ if (!m)
+ return BFA_STATUS_DEVBUSY;
+
+ bfi_h2i_set(m->mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_SET_INTR_REQ,
+ bfa_lpuid(bfa));
+ m->coalesce = iocfc->cfginfo->intr_attr.coalesce;
+ m->delay = iocfc->cfginfo->intr_attr.delay;
+ m->latency = iocfc->cfginfo->intr_attr.latency;
+
+ bfa_trc(bfa, attr->delay);
+ bfa_trc(bfa, attr->latency);
+
+ bfa_reqq_produce(bfa, BFA_REQQ_IOC);
+ return BFA_STATUS_OK;
+}
+
+void
+bfa_iocfc_set_snsbase(struct bfa_s *bfa, u64 snsbase_pa)
+{
+ struct bfa_iocfc_s *iocfc = &bfa->iocfc;
+
+ iocfc->cfginfo->sense_buf_len = (BFI_IOIM_SNSLEN - 1);
+ bfa_dma_be_addr_set(iocfc->cfginfo->ioim_snsbase, snsbase_pa);
+}
+/**
+ * Enable IOC after it is disabled.
+ */
+void
+bfa_iocfc_enable(struct bfa_s *bfa)
+{
+ bfa_plog_str(bfa->plog, BFA_PL_MID_HAL, BFA_PL_EID_MISC, 0,
+ "IOC Enable");
+ bfa_ioc_enable(&bfa->ioc);
+}
+
+void
+bfa_iocfc_disable(struct bfa_s *bfa)
+{
+ bfa_plog_str(bfa->plog, BFA_PL_MID_HAL, BFA_PL_EID_MISC, 0,
+ "IOC Disable");
+ bfa->iocfc.action = BFA_IOCFC_ACT_DISABLE;
+
+ bfa->rme_process = BFA_FALSE;
+ bfa_ioc_disable(&bfa->ioc);
+}
+
+
+bfa_boolean_t
+bfa_iocfc_is_operational(struct bfa_s *bfa)
+{
+ return bfa_ioc_is_operational(&bfa->ioc) && bfa->iocfc.cfgdone;
+}
+
+/**
+ * Return boot target port wwns -- read from boot information in flash.
+ */
+void
+bfa_iocfc_get_bootwwns(struct bfa_s *bfa, u8 *nwwns, wwn_t *wwns)
+{
+ struct bfa_iocfc_s *iocfc = &bfa->iocfc;
+ struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp;
+ int i;
+
+ if (cfgrsp->pbc_cfg.boot_enabled && cfgrsp->pbc_cfg.nbluns) {
+ bfa_trc(bfa, cfgrsp->pbc_cfg.nbluns);
+ *nwwns = cfgrsp->pbc_cfg.nbluns;
+ for (i = 0; i < cfgrsp->pbc_cfg.nbluns; i++)
+ wwns[i] = cfgrsp->pbc_cfg.blun[i].tgt_pwwn;
+
+ return;
+ }
+
+ *nwwns = cfgrsp->bootwwns.nwwns;
+ memcpy(wwns, cfgrsp->bootwwns.wwn, sizeof(cfgrsp->bootwwns.wwn));
+}
+
+void
+bfa_iocfc_get_pbc_boot_cfg(struct bfa_s *bfa, struct bfa_boot_pbc_s *pbcfg)
+{
+ struct bfa_iocfc_s *iocfc = &bfa->iocfc;
+ struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp;
+
+ pbcfg->enable = cfgrsp->pbc_cfg.boot_enabled;
+ pbcfg->nbluns = cfgrsp->pbc_cfg.nbluns;
+ pbcfg->speed = cfgrsp->pbc_cfg.port_speed;
+ memcpy(pbcfg->pblun, cfgrsp->pbc_cfg.blun, sizeof(pbcfg->pblun));
+}
+
+int
+bfa_iocfc_get_pbc_vports(struct bfa_s *bfa, struct bfi_pbc_vport_s *pbc_vport)
+{
+ struct bfa_iocfc_s *iocfc = &bfa->iocfc;
+ struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp;
+
+ memcpy(pbc_vport, cfgrsp->pbc_cfg.vport, sizeof(cfgrsp->pbc_cfg.vport));
+ return cfgrsp->pbc_cfg.nvports;
+}
+
+/**
+ * hal_api
+ */
/**
* Use this function query the memory requirement of the BFA library.
@@ -45,16 +1010,16 @@
* This call will fail, if the cap is out of range compared to pre-defined
* values within the BFA library
*
- * @param[in] cfg - pointer to bfa_ioc_cfg_t. Driver layer should indicate
- * its configuration in this structure.
+ * @param[in] cfg - pointer to bfa_ioc_cfg_t. Driver layer should indicate
+ * its configuration in this structure.
* The default values for struct bfa_iocfc_cfg_s can be
* fetched using bfa_cfg_get_default() API.
*
- * If cap's boundary check fails, the library will use
+ * If cap's boundary check fails, the library will use
* the default bfa_cap_t values (and log a warning msg).
*
* @param[out] meminfo - pointer to bfa_meminfo_t. This content
- * indicates the memory type (see bfa_mem_type_t) and
+ * indicates the memory type (see bfa_mem_type_t) and
* amount of memory required.
*
* Driver should allocate the memory, populate the
@@ -68,8 +1033,8 @@
void
bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo)
{
- int i;
- u32 km_len = 0, dm_len = 0;
+ int i;
+ u32 km_len = 0, dm_len = 0;
bfa_assert((cfg != NULL) && (meminfo != NULL));
@@ -90,26 +1055,6 @@ bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo)
meminfo->meminfo[BFA_MEM_TYPE_DMA - 1].mem_len = dm_len;
}
-static void
-bfa_com_port_attach(struct bfa_s *bfa, struct bfa_meminfo_s *mi)
-{
- struct bfa_port_s *port = &bfa->modules.port;
- uint32_t dm_len;
- uint8_t *dm_kva;
- uint64_t dm_pa;
-
- dm_len = bfa_port_meminfo();
- dm_kva = bfa_meminfo_dma_virt(mi);
- dm_pa = bfa_meminfo_dma_phys(mi);
-
- memset(port, 0, sizeof(struct bfa_port_s));
- bfa_port_attach(port, &bfa->ioc, bfa, bfa->trcmod, bfa->logm);
- bfa_port_mem_claim(port, dm_kva, dm_pa);
-
- bfa_meminfo_dma_virt(mi) = dm_kva + dm_len;
- bfa_meminfo_dma_phys(mi) = dm_pa + dm_len;
-}
-
/**
* Use this function to do attach the driver instance with the BFA
* library. This function will not trigger any HW initialization
@@ -119,14 +1064,14 @@ bfa_com_port_attach(struct bfa_s *bfa, struct bfa_meminfo_s *mi)
* pre-defined values within the BFA library
*
* @param[out] bfa Pointer to bfa_t.
- * @param[in] bfad Opaque handle back to the driver's IOC structure
+ * @param[in] bfad Opaque handle back to the driver's IOC structure
* @param[in] cfg Pointer to bfa_ioc_cfg_t. Should be same structure
- * that was used in bfa_cfg_get_meminfo().
- * @param[in] meminfo Pointer to bfa_meminfo_t. The driver should
- * use the bfa_cfg_get_meminfo() call to
- * find the memory blocks required, allocate the
- * required memory and provide the starting addresses.
- * @param[in] pcidev pointer to struct bfa_pcidev_s
+ * that was used in bfa_cfg_get_meminfo().
+ * @param[in] meminfo Pointer to bfa_meminfo_t. The driver should
+ * use the bfa_cfg_get_meminfo() call to
+ * find the memory blocks required, allocate the
+ * required memory and provide the starting addresses.
+ * @param[in] pcidev pointer to struct bfa_pcidev_s
*
* @return
* void
@@ -140,8 +1085,8 @@ void
bfa_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
{
- int i;
- struct bfa_mem_elem_s *melem;
+ int i;
+ struct bfa_mem_elem_s *melem;
bfa->fcs = BFA_FALSE;
@@ -195,20 +1140,6 @@ bfa_init_trc(struct bfa_s *bfa, struct bfa_trc_mod_s *trcmod)
bfa->trcmod = trcmod;
}
-
-void
-bfa_init_log(struct bfa_s *bfa, struct bfa_log_mod_s *logmod)
-{
- bfa->logm = logmod;
-}
-
-
-void
-bfa_init_aen(struct bfa_s *bfa, struct bfa_aen_s *aen)
-{
- bfa->aen = aen;
-}
-
void
bfa_init_plog(struct bfa_s *bfa, struct bfa_plog_s *plog)
{
@@ -254,14 +1185,14 @@ bfa_start(struct bfa_s *bfa)
/**
* Use this function quiese the IOC. This function will return immediately,
- * when the IOC is actually stopped, the bfa_cb_stop() will be called.
+ * when the IOC is actually stopped, the bfad->comp will be set.
*
- * @param[in] bfa - pointer to bfa_t.
+ * @param[in]bfa - pointer to bfa_t.
*
* @return None
*
* Special Considerations:
- * bfa_cb_stop() could be called before or after bfa_stop() returns.
+ * bfad->comp can be set before or after bfa_stop() returns.
*
* @note
* In case of any failure, we could handle it automatically by doing a
@@ -283,9 +1214,9 @@ bfa_comp_deq(struct bfa_s *bfa, struct list_head *comp_q)
void
bfa_comp_process(struct bfa_s *bfa, struct list_head *comp_q)
{
- struct list_head *qe;
- struct list_head *qen;
- struct bfa_cb_qe_s *hcb_qe;
+ struct list_head *qe;
+ struct list_head *qen;
+ struct bfa_cb_qe_s *hcb_qe;
list_for_each_safe(qe, qen, comp_q) {
hcb_qe = (struct bfa_cb_qe_s *) qe;
@@ -296,8 +1227,8 @@ bfa_comp_process(struct bfa_s *bfa, struct list_head *comp_q)
void
bfa_comp_free(struct bfa_s *bfa, struct list_head *comp_q)
{
- struct list_head *qe;
- struct bfa_cb_qe_s *hcb_qe;
+ struct list_head *qe;
+ struct bfa_cb_qe_s *hcb_qe;
while (!list_empty(comp_q)) {
bfa_q_deq(comp_q, &qe);
@@ -321,7 +1252,6 @@ bfa_timer_tick(struct bfa_s *bfa)
bfa_timer_beat(&bfa->timer_mod);
}
-#ifndef BFA_BIOS_BUILD
/**
* Return the list of PCI vendor/device id lists supported by this
* BFA instance.
@@ -336,7 +1266,7 @@ bfa_get_pciids(struct bfa_pciid_s **pciids, int *npciids)
{BFA_PCI_VENDOR_ID_BROCADE, BFA_PCI_DEVICE_ID_CT_FC},
};
- *npciids = ARRAY_SIZE(__pciids);
+ *npciids = sizeof(__pciids) / sizeof(__pciids[0]);
*pciids = __pciids;
}
@@ -351,7 +1281,7 @@ bfa_get_pciids(struct bfa_pciid_s **pciids, int *npciids)
* void
*
* Special Considerations:
- * note
+ * note
*/
void
bfa_cfg_get_default(struct bfa_iocfc_cfg_s *cfg)
@@ -389,7 +1319,7 @@ bfa_cfg_get_min(struct bfa_iocfc_cfg_s *cfg)
cfg->drvcfg.num_sgpgs = BFA_SGPG_MIN;
cfg->drvcfg.num_reqq_elems = BFA_REQQ_NELEMS_MIN;
cfg->drvcfg.num_rspq_elems = BFA_RSPQ_NELEMS_MIN;
- cfg->drvcfg.min_cfg = BFA_TRUE;
+ cfg->drvcfg.min_cfg = BFA_TRUE;
}
void
@@ -417,7 +1347,7 @@ bfa_debug_fwsave_clear(struct bfa_s *bfa)
}
/**
- * Fetch firmware trace data.
+ * Fetch firmware trace data.
*
* @param[in] bfa BFA instance
* @param[out] trcdata Firmware trace buffer
@@ -433,6 +1363,22 @@ bfa_debug_fwtrc(struct bfa_s *bfa, void *trcdata, int *trclen)
}
/**
+ * Dump firmware memory.
+ *
+ * @param[in] bfa BFA instance
+ * @param[out] buf buffer for dump
+ * @param[in,out] offset smem offset to start read
+ * @param[in,out] buflen length of buffer
+ *
+ * @retval BFA_STATUS_OK Firmware memory is dumped.
+ * @retval BFA_STATUS_INPROGRESS Firmware memory dump is in progress.
+ */
+bfa_status_t
+bfa_debug_fwcore(struct bfa_s *bfa, void *buf, u32 *offset, int *buflen)
+{
+ return bfa_ioc_debug_fwcore(&bfa->ioc, buf, offset, buflen);
+}
+/**
* Reset hw semaphore & usage cnt regs and initialize.
*/
void
@@ -441,4 +1387,23 @@ bfa_chip_reset(struct bfa_s *bfa)
bfa_ioc_ownership_reset(&bfa->ioc);
bfa_ioc_pll_init(&bfa->ioc);
}
-#endif
+
+/**
+ * Fetch firmware statistics data.
+ *
+ * @param[in] bfa BFA instance
+ * @param[out] data Firmware stats buffer
+ *
+ * @retval BFA_STATUS_OK Firmware trace is fetched.
+ */
+bfa_status_t
+bfa_fw_stats_get(struct bfa_s *bfa, void *data)
+{
+ return bfa_ioc_fw_stats_get(&bfa->ioc, data);
+}
+
+bfa_status_t
+bfa_fw_stats_clear(struct bfa_s *bfa)
+{
+ return bfa_ioc_fw_stats_clear(&bfa->ioc);
+}
diff --git a/drivers/scsi/bfa/bfa_cs.h b/drivers/scsi/bfa/bfa_cs.h
new file mode 100644
index 000000000000..7260c74620f8
--- /dev/null
+++ b/drivers/scsi/bfa/bfa_cs.h
@@ -0,0 +1,364 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+/**
+ * bfa_cs.h BFA common services
+ */
+
+#ifndef __BFA_CS_H__
+#define __BFA_CS_H__
+
+#include "bfa_os_inc.h"
+
+/**
+ * BFA TRC
+ */
+
+#ifndef BFA_TRC_MAX
+#define BFA_TRC_MAX (4 * 1024)
+#endif
+
+#ifndef BFA_TRC_TS
+#define BFA_TRC_TS(_trcm) ((_trcm)->ticks++)
+#endif
+
+struct bfa_trc_s {
+#ifdef __BIGENDIAN
+ u16 fileno;
+ u16 line;
+#else
+ u16 line;
+ u16 fileno;
+#endif
+ u32 timestamp;
+ union {
+ struct {
+ u32 rsvd;
+ u32 u32;
+ } u32;
+ u64 u64;
+ } data;
+};
+
+struct bfa_trc_mod_s {
+ u32 head;
+ u32 tail;
+ u32 ntrc;
+ u32 stopped;
+ u32 ticks;
+ u32 rsvd[3];
+ struct bfa_trc_s trc[BFA_TRC_MAX];
+};
+
+enum {
+ BFA_TRC_HAL = 1, /* BFA modules */
+ BFA_TRC_FCS = 2, /* BFA FCS modules */
+ BFA_TRC_LDRV = 3, /* Linux driver modules */
+ BFA_TRC_CNA = 4, /* Common modules */
+};
+#define BFA_TRC_MOD_SH 10
+#define BFA_TRC_MOD(__mod) ((BFA_TRC_ ## __mod) << BFA_TRC_MOD_SH)
+
+/**
+ * Define a new tracing file (module). Module should match one defined above.
+ */
+#define BFA_TRC_FILE(__mod, __submod) \
+ static int __trc_fileno = ((BFA_TRC_ ## __mod ## _ ## __submod) | \
+ BFA_TRC_MOD(__mod))
+
+
+#define bfa_trc32(_trcp, _data) \
+ __bfa_trc((_trcp)->trcmod, __trc_fileno, __LINE__, (u32)_data)
+#define bfa_trc(_trcp, _data) \
+ __bfa_trc((_trcp)->trcmod, __trc_fileno, __LINE__, (u64)_data)
+
+static inline void
+bfa_trc_init(struct bfa_trc_mod_s *trcm)
+{
+ trcm->head = trcm->tail = trcm->stopped = 0;
+ trcm->ntrc = BFA_TRC_MAX;
+}
+
+static inline void
+bfa_trc_stop(struct bfa_trc_mod_s *trcm)
+{
+ trcm->stopped = 1;
+}
+
+#ifdef FWTRC
+extern void dc_flush(void *data);
+#else
+#define dc_flush(data)
+#endif
+
+
+static inline void
+__bfa_trc(struct bfa_trc_mod_s *trcm, int fileno, int line, u64 data)
+{
+ int tail = trcm->tail;
+ struct bfa_trc_s *trc = &trcm->trc[tail];
+
+ if (trcm->stopped)
+ return;
+
+ trc->fileno = (u16) fileno;
+ trc->line = (u16) line;
+ trc->data.u64 = data;
+ trc->timestamp = BFA_TRC_TS(trcm);
+ dc_flush(trc);
+
+ trcm->tail = (trcm->tail + 1) & (BFA_TRC_MAX - 1);
+ if (trcm->tail == trcm->head)
+ trcm->head = (trcm->head + 1) & (BFA_TRC_MAX - 1);
+ dc_flush(trcm);
+}
+
+
+static inline void
+__bfa_trc32(struct bfa_trc_mod_s *trcm, int fileno, int line, u32 data)
+{
+ int tail = trcm->tail;
+ struct bfa_trc_s *trc = &trcm->trc[tail];
+
+ if (trcm->stopped)
+ return;
+
+ trc->fileno = (u16) fileno;
+ trc->line = (u16) line;
+ trc->data.u32.u32 = data;
+ trc->timestamp = BFA_TRC_TS(trcm);
+ dc_flush(trc);
+
+ trcm->tail = (trcm->tail + 1) & (BFA_TRC_MAX - 1);
+ if (trcm->tail == trcm->head)
+ trcm->head = (trcm->head + 1) & (BFA_TRC_MAX - 1);
+ dc_flush(trcm);
+}
+
+#ifndef BFA_PERF_BUILD
+#define bfa_trc_fp(_trcp, _data) bfa_trc(_trcp, _data)
+#else
+#define bfa_trc_fp(_trcp, _data)
+#endif
+
+/**
+ * @ BFA LOG interfaces
+ */
+#define bfa_assert(__cond) do { \
+ if (!(__cond)) { \
+ printk(KERN_ERR "assert(%s) failed at %s:%d\\n", \
+ #__cond, __FILE__, __LINE__); \
+ } \
+} while (0)
+
+#define bfa_sm_fault(__mod, __event) do { \
+ bfa_trc(__mod, (((u32)0xDEAD << 16) | __event)); \
+ printk(KERN_ERR "Assertion failure: %s:%d: %d", \
+ __FILE__, __LINE__, (__event)); \
+} while (0)
+
+#ifndef BFA_PERF_BUILD
+#define bfa_assert_fp(__cond) bfa_assert(__cond)
+#else
+#define bfa_assert_fp(__cond)
+#endif
+
+/* BFA queue definitions */
+#define bfa_q_first(_q) ((void *)(((struct list_head *) (_q))->next))
+#define bfa_q_next(_qe) (((struct list_head *) (_qe))->next)
+#define bfa_q_prev(_qe) (((struct list_head *) (_qe))->prev)
+
+/*
+ * bfa_q_qe_init - to initialize a queue element
+ */
+#define bfa_q_qe_init(_qe) { \
+ bfa_q_next(_qe) = (struct list_head *) NULL; \
+ bfa_q_prev(_qe) = (struct list_head *) NULL; \
+}
+
+/*
+ * bfa_q_deq - dequeue an element from head of the queue
+ */
+#define bfa_q_deq(_q, _qe) { \
+ if (!list_empty(_q)) { \
+ (*((struct list_head **) (_qe))) = bfa_q_next(_q); \
+ bfa_q_prev(bfa_q_next(*((struct list_head **) _qe))) = \
+ (struct list_head *) (_q); \
+ bfa_q_next(_q) = bfa_q_next(*((struct list_head **) _qe));\
+ BFA_Q_DBG_INIT(*((struct list_head **) _qe)); \
+ } else { \
+ *((struct list_head **) (_qe)) = (struct list_head *) NULL;\
+ } \
+}
+
+/*
+ * bfa_q_deq_tail - dequeue an element from tail of the queue
+ */
+#define bfa_q_deq_tail(_q, _qe) { \
+ if (!list_empty(_q)) { \
+ *((struct list_head **) (_qe)) = bfa_q_prev(_q); \
+ bfa_q_next(bfa_q_prev(*((struct list_head **) _qe))) = \
+ (struct list_head *) (_q); \
+ bfa_q_prev(_q) = bfa_q_prev(*(struct list_head **) _qe);\
+ BFA_Q_DBG_INIT(*((struct list_head **) _qe)); \
+ } else { \
+ *((struct list_head **) (_qe)) = (struct list_head *) NULL;\
+ } \
+}
+
+static inline int
+bfa_q_is_on_q_func(struct list_head *q, struct list_head *qe)
+{
+ struct list_head *tqe;
+
+ tqe = bfa_q_next(q);
+ while (tqe != q) {
+ if (tqe == qe)
+ return 1;
+ tqe = bfa_q_next(tqe);
+ if (tqe == NULL)
+ break;
+ }
+ return 0;
+}
+
+/*
+ * #ifdef BFA_DEBUG (Using bfa_assert to check for debug_build is not
+ * consistent across modules)
+ */
+#ifndef BFA_PERF_BUILD
+#define BFA_Q_DBG_INIT(_qe) bfa_q_qe_init(_qe)
+#else
+#define BFA_Q_DBG_INIT(_qe)
+#endif
+
+#define bfa_q_is_on_q(_q, _qe) \
+ bfa_q_is_on_q_func(_q, (struct list_head *)(_qe))
+
+/**
+ * @ BFA state machine interfaces
+ */
+
+typedef void (*bfa_sm_t)(void *sm, int event);
+
+/**
+ * oc - object class eg. bfa_ioc
+ * st - state, eg. reset
+ * otype - object type, eg. struct bfa_ioc_s
+ * etype - object type, eg. enum ioc_event
+ */
+#define bfa_sm_state_decl(oc, st, otype, etype) \
+ static void oc ## _sm_ ## st(otype * fsm, etype event)
+
+#define bfa_sm_set_state(_sm, _state) ((_sm)->sm = (bfa_sm_t)(_state))
+#define bfa_sm_send_event(_sm, _event) ((_sm)->sm((_sm), (_event)))
+#define bfa_sm_get_state(_sm) ((_sm)->sm)
+#define bfa_sm_cmp_state(_sm, _state) ((_sm)->sm == (bfa_sm_t)(_state))
+
+/**
+ * For converting from state machine function to state encoding.
+ */
+struct bfa_sm_table_s {
+ bfa_sm_t sm; /* state machine function */
+ int state; /* state machine encoding */
+ char *name; /* state name for display */
+};
+#define BFA_SM(_sm) ((bfa_sm_t)(_sm))
+
+/**
+ * State machine with entry actions.
+ */
+typedef void (*bfa_fsm_t)(void *fsm, int event);
+
+/**
+ * oc - object class eg. bfa_ioc
+ * st - state, eg. reset
+ * otype - object type, eg. struct bfa_ioc_s
+ * etype - object type, eg. enum ioc_event
+ */
+#define bfa_fsm_state_decl(oc, st, otype, etype) \
+ static void oc ## _sm_ ## st(otype * fsm, etype event); \
+ static void oc ## _sm_ ## st ## _entry(otype * fsm)
+
+#define bfa_fsm_set_state(_fsm, _state) do { \
+ (_fsm)->fsm = (bfa_fsm_t)(_state); \
+ _state ## _entry(_fsm); \
+} while (0)
+
+#define bfa_fsm_send_event(_fsm, _event) ((_fsm)->fsm((_fsm), (_event)))
+#define bfa_fsm_get_state(_fsm) ((_fsm)->fsm)
+#define bfa_fsm_cmp_state(_fsm, _state) \
+ ((_fsm)->fsm == (bfa_fsm_t)(_state))
+
+static inline int
+bfa_sm_to_state(struct bfa_sm_table_s *smt, bfa_sm_t sm)
+{
+ int i = 0;
+
+ while (smt[i].sm && smt[i].sm != sm)
+ i++;
+ return smt[i].state;
+}
+
+/**
+ * @ Generic wait counter.
+ */
+
+typedef void (*bfa_wc_resume_t) (void *cbarg);
+
+struct bfa_wc_s {
+ bfa_wc_resume_t wc_resume;
+ void *wc_cbarg;
+ int wc_count;
+};
+
+static inline void
+bfa_wc_up(struct bfa_wc_s *wc)
+{
+ wc->wc_count++;
+}
+
+static inline void
+bfa_wc_down(struct bfa_wc_s *wc)
+{
+ wc->wc_count--;
+ if (wc->wc_count == 0)
+ wc->wc_resume(wc->wc_cbarg);
+}
+
+/**
+ * Initialize a waiting counter.
+ */
+static inline void
+bfa_wc_init(struct bfa_wc_s *wc, bfa_wc_resume_t wc_resume, void *wc_cbarg)
+{
+ wc->wc_resume = wc_resume;
+ wc->wc_cbarg = wc_cbarg;
+ wc->wc_count = 0;
+ bfa_wc_up(wc);
+}
+
+/**
+ * Wait for counter to reach zero
+ */
+static inline void
+bfa_wc_wait(struct bfa_wc_s *wc)
+{
+ bfa_wc_down(wc);
+}
+
+#endif /* __BFA_CS_H__ */
diff --git a/drivers/scsi/bfa/bfa_csdebug.c b/drivers/scsi/bfa/bfa_csdebug.c
deleted file mode 100644
index caeb1143a4e6..000000000000
--- a/drivers/scsi/bfa/bfa_csdebug.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#include <cs/bfa_debug.h>
-#include <bfa_os_inc.h>
-#include <cs/bfa_q.h>
-#include <log/bfa_log_hal.h>
-
-/**
- * cs_debug_api
- */
-
-
-void
-bfa_panic(int line, char *file, char *panicstr)
-{
- bfa_log(NULL, BFA_LOG_HAL_ASSERT, file, line, panicstr);
- bfa_os_panic();
-}
-
-void
-bfa_sm_panic(struct bfa_log_mod_s *logm, int line, char *file, int event)
-{
- bfa_log(logm, BFA_LOG_HAL_SM_ASSERT, file, line, event);
- bfa_os_panic();
-}
-
-int
-bfa_q_is_on_q_func(struct list_head *q, struct list_head *qe)
-{
- struct list_head *tqe;
-
- tqe = bfa_q_next(q);
- while (tqe != q) {
- if (tqe == qe)
- return 1;
- tqe = bfa_q_next(tqe);
- if (tqe == NULL)
- break;
- }
- return 0;
-}
-
-
diff --git a/drivers/scsi/bfa/bfa_defs.h b/drivers/scsi/bfa/bfa_defs.h
new file mode 100644
index 000000000000..d49877ff5140
--- /dev/null
+++ b/drivers/scsi/bfa/bfa_defs.h
@@ -0,0 +1,466 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_DEFS_H__
+#define __BFA_DEFS_H__
+
+#include "bfa_fc.h"
+#include "bfa_os_inc.h"
+
+#define BFA_MFG_SERIALNUM_SIZE 11
+#define STRSZ(_n) (((_n) + 4) & ~3)
+
+/**
+ * Manufacturing card type
+ */
+enum {
+ BFA_MFG_TYPE_CB_MAX = 825, /* Crossbow card type max */
+ BFA_MFG_TYPE_FC8P2 = 825, /* 8G 2port FC card */
+ BFA_MFG_TYPE_FC8P1 = 815, /* 8G 1port FC card */
+ BFA_MFG_TYPE_FC4P2 = 425, /* 4G 2port FC card */
+ BFA_MFG_TYPE_FC4P1 = 415, /* 4G 1port FC card */
+ BFA_MFG_TYPE_CNA10P2 = 1020, /* 10G 2port CNA card */
+ BFA_MFG_TYPE_CNA10P1 = 1010, /* 10G 1port CNA card */
+ BFA_MFG_TYPE_JAYHAWK = 804, /* Jayhawk mezz card */
+ BFA_MFG_TYPE_WANCHESE = 1007, /* Wanchese mezz card */
+ BFA_MFG_TYPE_ASTRA = 807, /* Astra mezz card */
+ BFA_MFG_TYPE_LIGHTNING_P0 = 902, /* Lightning mezz card - old */
+ BFA_MFG_TYPE_LIGHTNING = 1741, /* Lightning mezz card */
+ BFA_MFG_TYPE_INVALID = 0, /* Invalid card type */
+};
+
+#pragma pack(1)
+
+/**
+ * Check if Mezz card
+ */
+#define bfa_mfg_is_mezz(type) (( \
+ (type) == BFA_MFG_TYPE_JAYHAWK || \
+ (type) == BFA_MFG_TYPE_WANCHESE || \
+ (type) == BFA_MFG_TYPE_ASTRA || \
+ (type) == BFA_MFG_TYPE_LIGHTNING_P0 || \
+ (type) == BFA_MFG_TYPE_LIGHTNING))
+
+/**
+ * Check if the card having old wwn/mac handling
+ */
+#define bfa_mfg_is_old_wwn_mac_model(type) (( \
+ (type) == BFA_MFG_TYPE_FC8P2 || \
+ (type) == BFA_MFG_TYPE_FC8P1 || \
+ (type) == BFA_MFG_TYPE_FC4P2 || \
+ (type) == BFA_MFG_TYPE_FC4P1 || \
+ (type) == BFA_MFG_TYPE_CNA10P2 || \
+ (type) == BFA_MFG_TYPE_CNA10P1 || \
+ (type) == BFA_MFG_TYPE_JAYHAWK || \
+ (type) == BFA_MFG_TYPE_WANCHESE))
+
+#define bfa_mfg_increment_wwn_mac(m, i) \
+do { \
+ u32 t = ((u32)(m)[0] << 16) | ((u32)(m)[1] << 8) | \
+ (u32)(m)[2]; \
+ t += (i); \
+ (m)[0] = (t >> 16) & 0xFF; \
+ (m)[1] = (t >> 8) & 0xFF; \
+ (m)[2] = t & 0xFF; \
+} while (0)
+
+/**
+ * VPD data length
+ */
+#define BFA_MFG_VPD_LEN 512
+
+/**
+ * VPD vendor tag
+ */
+enum {
+ BFA_MFG_VPD_UNKNOWN = 0, /* vendor unknown */
+ BFA_MFG_VPD_IBM = 1, /* vendor IBM */
+ BFA_MFG_VPD_HP = 2, /* vendor HP */
+ BFA_MFG_VPD_DELL = 3, /* vendor DELL */
+ BFA_MFG_VPD_PCI_IBM = 0x08, /* PCI VPD IBM */
+ BFA_MFG_VPD_PCI_HP = 0x10, /* PCI VPD HP */
+ BFA_MFG_VPD_PCI_DELL = 0x20, /* PCI VPD DELL */
+ BFA_MFG_VPD_PCI_BRCD = 0xf8, /* PCI VPD Brocade */
+};
+
+/**
+ * All numerical fields are in big-endian format.
+ */
+struct bfa_mfg_vpd_s {
+ u8 version; /* vpd data version */
+ u8 vpd_sig[3]; /* characters 'V', 'P', 'D' */
+ u8 chksum; /* u8 checksum */
+ u8 vendor; /* vendor */
+ u8 len; /* vpd data length excluding header */
+ u8 rsv;
+ u8 data[BFA_MFG_VPD_LEN]; /* vpd data */
+};
+
+#pragma pack()
+
+/**
+ * Status return values
+ */
+enum bfa_status {
+ BFA_STATUS_OK = 0, /* Success */
+ BFA_STATUS_FAILED = 1, /* Operation failed */
+ BFA_STATUS_EINVAL = 2, /* Invalid params Check input
+ * parameters */
+ BFA_STATUS_ENOMEM = 3, /* Out of resources */
+ BFA_STATUS_ETIMER = 5, /* Timer expired - Retry, if persists,
+ * contact support */
+ BFA_STATUS_EPROTOCOL = 6, /* Protocol error */
+ BFA_STATUS_DEVBUSY = 13, /* Device busy - Retry operation */
+ BFA_STATUS_UNKNOWN_LWWN = 18, /* LPORT PWWN not found */
+ BFA_STATUS_UNKNOWN_RWWN = 19, /* RPORT PWWN not found */
+ BFA_STATUS_VPORT_EXISTS = 21, /* VPORT already exists */
+ BFA_STATUS_VPORT_MAX = 22, /* Reached max VPORT supported limit */
+ BFA_STATUS_UNSUPP_SPEED = 23, /* Invalid Speed Check speed setting */
+ BFA_STATUS_INVLD_DFSZ = 24, /* Invalid Max data field size */
+ BFA_STATUS_FABRIC_RJT = 29, /* Reject from attached fabric */
+ BFA_STATUS_VPORT_WWN_BP = 46, /* WWN is same as base port's WWN */
+ BFA_STATUS_NO_FCPIM_NEXUS = 52, /* No FCP Nexus exists with the rport */
+ BFA_STATUS_IOC_FAILURE = 56, /* IOC failure - Retry, if persists
+ * contact support */
+ BFA_STATUS_INVALID_WWN = 57, /* Invalid WWN */
+ BFA_STATUS_DIAG_BUSY = 71, /* diag busy */
+ BFA_STATUS_ENOFSAVE = 78, /* No saved firmware trace */
+ BFA_STATUS_IOC_DISABLED = 82, /* IOC is already disabled */
+ BFA_STATUS_INVALID_MAC = 134, /* Invalid MAC address */
+ BFA_STATUS_PBC = 154, /* Operation not allowed for pre-boot
+ * configuration */
+ BFA_STATUS_TRUNK_ENABLED = 164, /* Trunk is already enabled on
+ * this adapter */
+ BFA_STATUS_TRUNK_DISABLED = 165, /* Trunking is disabled on
+ * the adapter */
+ BFA_STATUS_IOPROFILE_OFF = 175, /* IO profile OFF */
+ BFA_STATUS_MAX_VAL /* Unknown error code */
+};
+#define bfa_status_t enum bfa_status
+
+enum bfa_eproto_status {
+ BFA_EPROTO_BAD_ACCEPT = 0,
+ BFA_EPROTO_UNKNOWN_RSP = 1
+};
+#define bfa_eproto_status_t enum bfa_eproto_status
+
+enum bfa_boolean {
+ BFA_FALSE = 0,
+ BFA_TRUE = 1
+};
+#define bfa_boolean_t enum bfa_boolean
+
+#define BFA_STRING_32 32
+#define BFA_VERSION_LEN 64
+
+/**
+ * ---------------------- adapter definitions ------------
+ */
+
+/**
+ * BFA adapter level attributes.
+ */
+enum {
+ BFA_ADAPTER_SERIAL_NUM_LEN = STRSZ(BFA_MFG_SERIALNUM_SIZE),
+ /*
+ *!< adapter serial num length
+ */
+ BFA_ADAPTER_MODEL_NAME_LEN = 16, /* model name length */
+ BFA_ADAPTER_MODEL_DESCR_LEN = 128, /* model description length */
+ BFA_ADAPTER_MFG_NAME_LEN = 8, /* manufacturer name length */
+ BFA_ADAPTER_SYM_NAME_LEN = 64, /* adapter symbolic name length */
+ BFA_ADAPTER_OS_TYPE_LEN = 64, /* adapter os type length */
+};
+
+struct bfa_adapter_attr_s {
+ char manufacturer[BFA_ADAPTER_MFG_NAME_LEN];
+ char serial_num[BFA_ADAPTER_SERIAL_NUM_LEN];
+ u32 card_type;
+ char model[BFA_ADAPTER_MODEL_NAME_LEN];
+ char model_descr[BFA_ADAPTER_MODEL_DESCR_LEN];
+ wwn_t pwwn;
+ char node_symname[FC_SYMNAME_MAX];
+ char hw_ver[BFA_VERSION_LEN];
+ char fw_ver[BFA_VERSION_LEN];
+ char optrom_ver[BFA_VERSION_LEN];
+ char os_type[BFA_ADAPTER_OS_TYPE_LEN];
+ struct bfa_mfg_vpd_s vpd;
+ struct mac_s mac;
+
+ u8 nports;
+ u8 max_speed;
+ u8 prototype;
+ char asic_rev;
+
+ u8 pcie_gen;
+ u8 pcie_lanes_orig;
+ u8 pcie_lanes;
+ u8 cna_capable;
+
+ u8 is_mezz;
+ u8 trunk_capable;
+};
+
+/**
+ * ---------------------- IOC definitions ------------
+ */
+
+enum {
+ BFA_IOC_DRIVER_LEN = 16,
+ BFA_IOC_CHIP_REV_LEN = 8,
+};
+
+/**
+ * Driver and firmware versions.
+ */
+struct bfa_ioc_driver_attr_s {
+ char driver[BFA_IOC_DRIVER_LEN]; /* driver name */
+ char driver_ver[BFA_VERSION_LEN]; /* driver version */
+ char fw_ver[BFA_VERSION_LEN]; /* firmware version */
+ char bios_ver[BFA_VERSION_LEN]; /* bios version */
+ char efi_ver[BFA_VERSION_LEN]; /* EFI version */
+ char ob_ver[BFA_VERSION_LEN]; /* openboot version */
+};
+
+/**
+ * IOC PCI device attributes
+ */
+struct bfa_ioc_pci_attr_s {
+ u16 vendor_id; /* PCI vendor ID */
+ u16 device_id; /* PCI device ID */
+ u16 ssid; /* subsystem ID */
+ u16 ssvid; /* subsystem vendor ID */
+ u32 pcifn; /* PCI device function */
+ u32 rsvd; /* padding */
+ char chip_rev[BFA_IOC_CHIP_REV_LEN]; /* chip revision */
+};
+
+/**
+ * IOC states
+ */
+enum bfa_ioc_state {
+ BFA_IOC_UNINIT = 1, /* IOC is in uninit state */
+ BFA_IOC_RESET = 2, /* IOC is in reset state */
+ BFA_IOC_SEMWAIT = 3, /* Waiting for IOC h/w semaphore */
+ BFA_IOC_HWINIT = 4, /* IOC h/w is being initialized */
+ BFA_IOC_GETATTR = 5, /* IOC is being configured */
+ BFA_IOC_OPERATIONAL = 6, /* IOC is operational */
+ BFA_IOC_INITFAIL = 7, /* IOC hardware failure */
+ BFA_IOC_FAIL = 8, /* IOC heart-beat failure */
+ BFA_IOC_DISABLING = 9, /* IOC is being disabled */
+ BFA_IOC_DISABLED = 10, /* IOC is disabled */
+ BFA_IOC_FWMISMATCH = 11, /* IOC f/w different from drivers */
+ BFA_IOC_ENABLING = 12, /* IOC is being enabled */
+};
+
+/**
+ * IOC firmware stats
+ */
+struct bfa_fw_ioc_stats_s {
+ u32 enable_reqs;
+ u32 disable_reqs;
+ u32 get_attr_reqs;
+ u32 dbg_sync;
+ u32 dbg_dump;
+ u32 unknown_reqs;
+};
+
+/**
+ * IOC driver stats
+ */
+struct bfa_ioc_drv_stats_s {
+ u32 ioc_isrs;
+ u32 ioc_enables;
+ u32 ioc_disables;
+ u32 ioc_hbfails;
+ u32 ioc_boots;
+ u32 stats_tmos;
+ u32 hb_count;
+ u32 disable_reqs;
+ u32 enable_reqs;
+ u32 disable_replies;
+ u32 enable_replies;
+};
+
+/**
+ * IOC statistics
+ */
+struct bfa_ioc_stats_s {
+ struct bfa_ioc_drv_stats_s drv_stats; /* driver IOC stats */
+ struct bfa_fw_ioc_stats_s fw_stats; /* firmware IOC stats */
+};
+
+enum bfa_ioc_type_e {
+ BFA_IOC_TYPE_FC = 1,
+ BFA_IOC_TYPE_FCoE = 2,
+ BFA_IOC_TYPE_LL = 3,
+};
+
+/**
+ * IOC attributes returned in queries
+ */
+struct bfa_ioc_attr_s {
+ enum bfa_ioc_type_e ioc_type;
+ enum bfa_ioc_state state; /* IOC state */
+ struct bfa_adapter_attr_s adapter_attr; /* HBA attributes */
+ struct bfa_ioc_driver_attr_s driver_attr; /* driver attr */
+ struct bfa_ioc_pci_attr_s pci_attr;
+ u8 port_id; /* port number */
+ u8 rsvd[7]; /* 64bit align */
+};
+
+/**
+ * ---------------------- mfg definitions ------------
+ */
+
+/**
+ * Checksum size
+ */
+#define BFA_MFG_CHKSUM_SIZE 16
+
+#define BFA_MFG_PARTNUM_SIZE 14
+#define BFA_MFG_SUPPLIER_ID_SIZE 10
+#define BFA_MFG_SUPPLIER_PARTNUM_SIZE 20
+#define BFA_MFG_SUPPLIER_SERIALNUM_SIZE 20
+#define BFA_MFG_SUPPLIER_REVISION_SIZE 4
+
+#pragma pack(1)
+
+/**
+ * All numerical fields are in big-endian format.
+ */
+struct bfa_mfg_block_s {
+ u8 version; /* manufacturing block version */
+ u8 mfg_sig[3]; /* characters 'M', 'F', 'G' */
+ u16 mfgsize; /* mfg block size */
+ u16 u16_chksum; /* old u16 checksum */
+ char brcd_serialnum[STRSZ(BFA_MFG_SERIALNUM_SIZE)];
+ char brcd_partnum[STRSZ(BFA_MFG_PARTNUM_SIZE)];
+ u8 mfg_day; /* manufacturing day */
+ u8 mfg_month; /* manufacturing month */
+ u16 mfg_year; /* manufacturing year */
+ wwn_t mfg_wwn; /* wwn base for this adapter */
+ u8 num_wwn; /* number of wwns assigned */
+ u8 mfg_speeds; /* speeds allowed for this adapter */
+ u8 rsv[2];
+ char supplier_id[STRSZ(BFA_MFG_SUPPLIER_ID_SIZE)];
+ char supplier_partnum[STRSZ(BFA_MFG_SUPPLIER_PARTNUM_SIZE)];
+ char
+ supplier_serialnum[STRSZ(BFA_MFG_SUPPLIER_SERIALNUM_SIZE)];
+ char
+ supplier_revision[STRSZ(BFA_MFG_SUPPLIER_REVISION_SIZE)];
+ mac_t mfg_mac; /* mac address */
+ u8 num_mac; /* number of mac addresses */
+ u8 rsv2;
+ u32 mfg_type; /* card type */
+ u8 rsv3[108];
+ u8 md5_chksum[BFA_MFG_CHKSUM_SIZE]; /* md5 checksum */
+};
+
+#pragma pack()
+
+/**
+ * ---------------------- pci definitions ------------
+ */
+
+/**
+ * PCI device and vendor ID information
+ */
+enum {
+ BFA_PCI_VENDOR_ID_BROCADE = 0x1657,
+ BFA_PCI_DEVICE_ID_FC_8G2P = 0x13,
+ BFA_PCI_DEVICE_ID_FC_8G1P = 0x17,
+ BFA_PCI_DEVICE_ID_CT = 0x14,
+ BFA_PCI_DEVICE_ID_CT_FC = 0x21,
+};
+
+#define bfa_asic_id_ct(devid) \
+ ((devid) == BFA_PCI_DEVICE_ID_CT || \
+ (devid) == BFA_PCI_DEVICE_ID_CT_FC)
+
+/**
+ * PCI sub-system device and vendor ID information
+ */
+enum {
+ BFA_PCI_FCOE_SSDEVICE_ID = 0x14,
+};
+
+/**
+ * Maximum number of device address ranges mapped through different BAR(s)
+ */
+#define BFA_PCI_ACCESS_RANGES 1
+
+/*
+ * Port speed settings. Each specific speed is a bit field. Use multiple
+ * bits to specify speeds to be selected for auto-negotiation.
+ */
+enum bfa_port_speed {
+ BFA_PORT_SPEED_UNKNOWN = 0,
+ BFA_PORT_SPEED_1GBPS = 1,
+ BFA_PORT_SPEED_2GBPS = 2,
+ BFA_PORT_SPEED_4GBPS = 4,
+ BFA_PORT_SPEED_8GBPS = 8,
+ BFA_PORT_SPEED_10GBPS = 10,
+ BFA_PORT_SPEED_16GBPS = 16,
+ BFA_PORT_SPEED_AUTO =
+ (BFA_PORT_SPEED_1GBPS | BFA_PORT_SPEED_2GBPS |
+ BFA_PORT_SPEED_4GBPS | BFA_PORT_SPEED_8GBPS),
+};
+#define bfa_port_speed_t enum bfa_port_speed
+
+enum {
+ BFA_BOOT_BOOTLUN_MAX = 4, /* maximum boot lun per IOC */
+ BFA_PREBOOT_BOOTLUN_MAX = 8, /* maximum preboot lun per IOC */
+};
+
+#define BOOT_CFG_REV1 1
+#define BOOT_CFG_VLAN 1
+
+/**
+ * Boot options setting. Boot options setting determines from where
+ * to get the boot lun information
+ */
+enum bfa_boot_bootopt {
+ BFA_BOOT_AUTO_DISCOVER = 0, /* Boot from blun provided by fabric */
+ BFA_BOOT_STORED_BLUN = 1, /* Boot from bluns stored in flash */
+ BFA_BOOT_FIRST_LUN = 2, /* Boot from first discovered blun */
+ BFA_BOOT_PBC = 3, /* Boot from pbc configured blun */
+};
+
+#pragma pack(1)
+/**
+ * Boot lun information.
+ */
+struct bfa_boot_bootlun_s {
+ wwn_t pwwn; /* port wwn of target */
+ lun_t lun; /* 64-bit lun */
+};
+#pragma pack()
+
+/**
+ * BOOT boot configuraton
+ */
+struct bfa_boot_pbc_s {
+ u8 enable; /* enable/disable SAN boot */
+ u8 speed; /* boot speed settings */
+ u8 topology; /* boot topology setting */
+ u8 rsvd1;
+ u32 nbluns; /* number of boot luns */
+ struct bfa_boot_bootlun_s pblun[BFA_PREBOOT_BOOTLUN_MAX];
+};
+
+#endif /* __BFA_DEFS_H__ */
diff --git a/drivers/scsi/bfa/bfa_defs_fcs.h b/drivers/scsi/bfa/bfa_defs_fcs.h
new file mode 100644
index 000000000000..96905d301828
--- /dev/null
+++ b/drivers/scsi/bfa/bfa_defs_fcs.h
@@ -0,0 +1,457 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_DEFS_FCS_H__
+#define __BFA_DEFS_FCS_H__
+
+#include "bfa_fc.h"
+#include "bfa_defs_svc.h"
+
+/**
+ * VF states
+ */
+enum bfa_vf_state {
+ BFA_VF_UNINIT = 0, /* fabric is not yet initialized */
+ BFA_VF_LINK_DOWN = 1, /* link is down */
+ BFA_VF_FLOGI = 2, /* flogi is in progress */
+ BFA_VF_AUTH = 3, /* authentication in progress */
+ BFA_VF_NOFABRIC = 4, /* fabric is not present */
+ BFA_VF_ONLINE = 5, /* login to fabric is complete */
+ BFA_VF_EVFP = 6, /* EVFP is in progress */
+ BFA_VF_ISOLATED = 7, /* port isolated due to vf_id mismatch */
+};
+
+/**
+ * VF statistics
+ */
+struct bfa_vf_stats_s {
+ u32 flogi_sent; /* Num FLOGIs sent */
+ u32 flogi_rsp_err; /* FLOGI response errors */
+ u32 flogi_acc_err; /* FLOGI accept errors */
+ u32 flogi_accepts; /* FLOGI accepts received */
+ u32 flogi_rejects; /* FLOGI rejects received */
+ u32 flogi_unknown_rsp; /* Unknown responses for FLOGI */
+ u32 flogi_alloc_wait; /* Allocation waits prior to sending FLOGI */
+ u32 flogi_rcvd; /* FLOGIs received */
+ u32 flogi_rejected; /* Incoming FLOGIs rejected */
+ u32 fabric_onlines; /* Internal fabric online notification sent
+ * to other modules */
+ u32 fabric_offlines; /* Internal fabric offline notification sent
+ * to other modules */
+ u32 resvd; /* padding for 64 bit alignment */
+};
+
+/**
+ * VF attributes returned in queries
+ */
+struct bfa_vf_attr_s {
+ enum bfa_vf_state state; /* VF state */
+ u32 rsvd;
+ wwn_t fabric_name; /* fabric name */
+};
+
+#define BFA_FCS_MAX_LPORTS 256
+#define BFA_FCS_FABRIC_IPADDR_SZ 16
+
+/**
+ * symbolic names for base port/virtual port
+ */
+#define BFA_SYMNAME_MAXLEN 128 /* 128 bytes */
+struct bfa_lport_symname_s {
+ char symname[BFA_SYMNAME_MAXLEN];
+};
+
+/**
+* Roles of FCS port:
+ * - FCP IM and FCP TM roles cannot be enabled together for a FCS port
+ * - Create multiple ports if both IM and TM functions required.
+ * - Atleast one role must be specified.
+ */
+enum bfa_lport_role {
+ BFA_LPORT_ROLE_FCP_IM = 0x01, /* FCP initiator role */
+ BFA_LPORT_ROLE_FCP_MAX = BFA_LPORT_ROLE_FCP_IM,
+};
+
+/**
+ * FCS port configuration.
+ */
+struct bfa_lport_cfg_s {
+ wwn_t pwwn; /* port wwn */
+ wwn_t nwwn; /* node wwn */
+ struct bfa_lport_symname_s sym_name; /* vm port symbolic name */
+ bfa_boolean_t preboot_vp; /* vport created from PBC */
+ enum bfa_lport_role roles; /* FCS port roles */
+ u8 tag[16]; /* opaque tag from application */
+};
+
+/**
+ * FCS port states
+ */
+enum bfa_lport_state {
+ BFA_LPORT_UNINIT = 0, /* PORT is not yet initialized */
+ BFA_LPORT_FDISC = 1, /* FDISC is in progress */
+ BFA_LPORT_ONLINE = 2, /* login to fabric is complete */
+ BFA_LPORT_OFFLINE = 3, /* No login to fabric */
+};
+
+/**
+ * FCS port type.
+ */
+enum bfa_lport_type {
+ BFA_LPORT_TYPE_PHYSICAL = 0,
+ BFA_LPORT_TYPE_VIRTUAL,
+};
+
+/**
+ * FCS port offline reason.
+ */
+enum bfa_lport_offline_reason {
+ BFA_LPORT_OFFLINE_UNKNOWN = 0,
+ BFA_LPORT_OFFLINE_LINKDOWN,
+ BFA_LPORT_OFFLINE_FAB_UNSUPPORTED, /* NPIV not supported by the
+ * fabric */
+ BFA_LPORT_OFFLINE_FAB_NORESOURCES,
+ BFA_LPORT_OFFLINE_FAB_LOGOUT,
+};
+
+/**
+ * FCS lport info.
+ */
+struct bfa_lport_info_s {
+ u8 port_type; /* bfa_lport_type_t : physical or
+ * virtual */
+ u8 port_state; /* one of bfa_lport_state values */
+ u8 offline_reason; /* one of bfa_lport_offline_reason_t
+ * values */
+ wwn_t port_wwn;
+ wwn_t node_wwn;
+
+ /*
+ * following 4 feilds are valid for Physical Ports only
+ */
+ u32 max_vports_supp; /* Max supported vports */
+ u32 num_vports_inuse; /* Num of in use vports */
+ u32 max_rports_supp; /* Max supported rports */
+ u32 num_rports_inuse; /* Num of doscovered rports */
+
+};
+
+/**
+ * FCS port statistics
+ */
+struct bfa_lport_stats_s {
+ u32 ns_plogi_sent;
+ u32 ns_plogi_rsp_err;
+ u32 ns_plogi_acc_err;
+ u32 ns_plogi_accepts;
+ u32 ns_rejects; /* NS command rejects */
+ u32 ns_plogi_unknown_rsp;
+ u32 ns_plogi_alloc_wait;
+
+ u32 ns_retries; /* NS command retries */
+ u32 ns_timeouts; /* NS command timeouts */
+
+ u32 ns_rspnid_sent;
+ u32 ns_rspnid_accepts;
+ u32 ns_rspnid_rsp_err;
+ u32 ns_rspnid_rejects;
+ u32 ns_rspnid_alloc_wait;
+
+ u32 ns_rftid_sent;
+ u32 ns_rftid_accepts;
+ u32 ns_rftid_rsp_err;
+ u32 ns_rftid_rejects;
+ u32 ns_rftid_alloc_wait;
+
+ u32 ns_rffid_sent;
+ u32 ns_rffid_accepts;
+ u32 ns_rffid_rsp_err;
+ u32 ns_rffid_rejects;
+ u32 ns_rffid_alloc_wait;
+
+ u32 ns_gidft_sent;
+ u32 ns_gidft_accepts;
+ u32 ns_gidft_rsp_err;
+ u32 ns_gidft_rejects;
+ u32 ns_gidft_unknown_rsp;
+ u32 ns_gidft_alloc_wait;
+
+ /*
+ * Mgmt Server stats
+ */
+ u32 ms_retries; /* MS command retries */
+ u32 ms_timeouts; /* MS command timeouts */
+ u32 ms_plogi_sent;
+ u32 ms_plogi_rsp_err;
+ u32 ms_plogi_acc_err;
+ u32 ms_plogi_accepts;
+ u32 ms_rejects; /* MS command rejects */
+ u32 ms_plogi_unknown_rsp;
+ u32 ms_plogi_alloc_wait;
+
+ u32 num_rscn; /* Num of RSCN received */
+ u32 num_portid_rscn;/* Num portid format RSCN
+ * received */
+
+ u32 uf_recvs; /* Unsolicited recv frames */
+ u32 uf_recv_drops; /* Dropped received frames */
+
+ u32 plogi_rcvd; /* Received plogi */
+ u32 prli_rcvd; /* Received prli */
+ u32 adisc_rcvd; /* Received adisc */
+ u32 prlo_rcvd; /* Received prlo */
+ u32 logo_rcvd; /* Received logo */
+ u32 rpsc_rcvd; /* Received rpsc */
+ u32 un_handled_els_rcvd; /* Received unhandled ELS */
+ u32 rport_plogi_timeouts; /* Rport plogi retry timeout count */
+ u32 rport_del_max_plogi_retry; /* Deleted rport
+ * (max retry of plogi) */
+};
+
+/**
+ * BFA port attribute returned in queries
+ */
+struct bfa_lport_attr_s {
+ enum bfa_lport_state state; /* port state */
+ u32 pid; /* port ID */
+ struct bfa_lport_cfg_s port_cfg; /* port configuration */
+ enum bfa_port_type port_type; /* current topology */
+ u32 loopback; /* cable is externally looped back */
+ wwn_t fabric_name; /* attached switch's nwwn */
+ u8 fabric_ip_addr[BFA_FCS_FABRIC_IPADDR_SZ]; /* attached
+ * fabric's ip addr */
+ mac_t fpma_mac; /* Lport's FPMA Mac address */
+ u16 authfail; /* auth failed state */
+};
+
+
+/**
+ * VPORT states
+ */
+enum bfa_vport_state {
+ BFA_FCS_VPORT_UNINIT = 0,
+ BFA_FCS_VPORT_CREATED = 1,
+ BFA_FCS_VPORT_OFFLINE = 1,
+ BFA_FCS_VPORT_FDISC_SEND = 2,
+ BFA_FCS_VPORT_FDISC = 3,
+ BFA_FCS_VPORT_FDISC_RETRY = 4,
+ BFA_FCS_VPORT_ONLINE = 5,
+ BFA_FCS_VPORT_DELETING = 6,
+ BFA_FCS_VPORT_CLEANUP = 6,
+ BFA_FCS_VPORT_LOGO_SEND = 7,
+ BFA_FCS_VPORT_LOGO = 8,
+ BFA_FCS_VPORT_ERROR = 9,
+ BFA_FCS_VPORT_MAX_STATE,
+};
+
+/**
+ * vport statistics
+ */
+struct bfa_vport_stats_s {
+ struct bfa_lport_stats_s port_stats; /* base class (port) stats */
+ /*
+ * TODO - remove
+ */
+
+ u32 fdisc_sent; /* num fdisc sent */
+ u32 fdisc_accepts; /* fdisc accepts */
+ u32 fdisc_retries; /* fdisc retries */
+ u32 fdisc_timeouts; /* fdisc timeouts */
+ u32 fdisc_rsp_err; /* fdisc response error */
+ u32 fdisc_acc_bad; /* bad fdisc accepts */
+ u32 fdisc_rejects; /* fdisc rejects */
+ u32 fdisc_unknown_rsp;
+ /*
+ *!< fdisc rsp unknown error
+ */
+ u32 fdisc_alloc_wait;/* fdisc req (fcxp)alloc wait */
+
+ u32 logo_alloc_wait;/* logo req (fcxp) alloc wait */
+ u32 logo_sent; /* logo sent */
+ u32 logo_accepts; /* logo accepts */
+ u32 logo_rejects; /* logo rejects */
+ u32 logo_rsp_err; /* logo rsp errors */
+ u32 logo_unknown_rsp;
+ /* logo rsp unknown errors */
+
+ u32 fab_no_npiv; /* fabric does not support npiv */
+
+ u32 fab_offline; /* offline events from fab SM */
+ u32 fab_online; /* online events from fab SM */
+ u32 fab_cleanup; /* cleanup request from fab SM */
+ u32 rsvd;
+};
+
+/**
+ * BFA vport attribute returned in queries
+ */
+struct bfa_vport_attr_s {
+ struct bfa_lport_attr_s port_attr; /* base class (port) attributes */
+ enum bfa_vport_state vport_state; /* vport state */
+ u32 rsvd;
+};
+
+/**
+ * FCS remote port states
+ */
+enum bfa_rport_state {
+ BFA_RPORT_UNINIT = 0, /* PORT is not yet initialized */
+ BFA_RPORT_OFFLINE = 1, /* rport is offline */
+ BFA_RPORT_PLOGI = 2, /* PLOGI to rport is in progress */
+ BFA_RPORT_ONLINE = 3, /* login to rport is complete */
+ BFA_RPORT_PLOGI_RETRY = 4, /* retrying login to rport */
+ BFA_RPORT_NSQUERY = 5, /* nameserver query */
+ BFA_RPORT_ADISC = 6, /* ADISC authentication */
+ BFA_RPORT_LOGO = 7, /* logging out with rport */
+ BFA_RPORT_LOGORCV = 8, /* handling LOGO from rport */
+ BFA_RPORT_NSDISC = 9, /* re-discover rport */
+};
+
+/**
+ * Rport Scsi Function : Initiator/Target.
+ */
+enum bfa_rport_function {
+ BFA_RPORT_INITIATOR = 0x01, /* SCSI Initiator */
+ BFA_RPORT_TARGET = 0x02, /* SCSI Target */
+};
+
+/**
+ * port/node symbolic names for rport
+ */
+#define BFA_RPORT_SYMNAME_MAXLEN 255
+struct bfa_rport_symname_s {
+ char symname[BFA_RPORT_SYMNAME_MAXLEN];
+};
+
+/**
+ * FCS remote port statistics
+ */
+struct bfa_rport_stats_s {
+ u32 offlines; /* remote port offline count */
+ u32 onlines; /* remote port online count */
+ u32 rscns; /* RSCN affecting rport */
+ u32 plogis; /* plogis sent */
+ u32 plogi_accs; /* plogi accepts */
+ u32 plogi_timeouts; /* plogi timeouts */
+ u32 plogi_rejects; /* rcvd plogi rejects */
+ u32 plogi_failed; /* local failure */
+ u32 plogi_rcvd; /* plogis rcvd */
+ u32 prli_rcvd; /* inbound PRLIs */
+ u32 adisc_rcvd; /* ADISCs received */
+ u32 adisc_rejects; /* recvd ADISC rejects */
+ u32 adisc_sent; /* ADISC requests sent */
+ u32 adisc_accs; /* ADISC accepted by rport */
+ u32 adisc_failed; /* ADISC failed (no response) */
+ u32 adisc_rejected; /* ADISC rejected by us */
+ u32 logos; /* logos sent */
+ u32 logo_accs; /* LOGO accepts from rport */
+ u32 logo_failed; /* LOGO failures */
+ u32 logo_rejected; /* LOGO rejects from rport */
+ u32 logo_rcvd; /* LOGO from remote port */
+
+ u32 rpsc_rcvd; /* RPSC received */
+ u32 rpsc_rejects; /* recvd RPSC rejects */
+ u32 rpsc_sent; /* RPSC requests sent */
+ u32 rpsc_accs; /* RPSC accepted by rport */
+ u32 rpsc_failed; /* RPSC failed (no response) */
+ u32 rpsc_rejected; /* RPSC rejected by us */
+
+ u32 rjt_insuff_res; /* LS RJT with insuff resources */
+ struct bfa_rport_hal_stats_s hal_stats; /* BFA rport stats */
+};
+
+/**
+ * FCS remote port attributes returned in queries
+ */
+struct bfa_rport_attr_s {
+ wwn_t nwwn; /* node wwn */
+ wwn_t pwwn; /* port wwn */
+ enum fc_cos cos_supported; /* supported class of services */
+ u32 pid; /* port ID */
+ u32 df_sz; /* Max payload size */
+ enum bfa_rport_state state; /* Rport State machine state */
+ enum fc_cos fc_cos; /* FC classes of services */
+ bfa_boolean_t cisc; /* CISC capable device */
+ struct bfa_rport_symname_s symname; /* Symbolic Name */
+ enum bfa_rport_function scsi_function; /* Initiator/Target */
+ struct bfa_rport_qos_attr_s qos_attr; /* qos attributes */
+ enum bfa_port_speed curr_speed; /* operating speed got from
+ * RPSC ELS. UNKNOWN, if RPSC
+ * is not supported */
+ bfa_boolean_t trl_enforced; /* TRL enforced ? TRUE/FALSE */
+ enum bfa_port_speed assigned_speed; /* Speed assigned by the user.
+ * will be used if RPSC is not
+ * supported by the rport */
+};
+
+struct bfa_rport_remote_link_stats_s {
+ u32 lfc; /* Link Failure Count */
+ u32 lsyc; /* Loss of Synchronization Count */
+ u32 lsic; /* Loss of Signal Count */
+ u32 pspec; /* Primitive Sequence Protocol Error Count */
+ u32 itwc; /* Invalid Transmission Word Count */
+ u32 icc; /* Invalid CRC Count */
+};
+
+
+#define BFA_MAX_IO_INDEX 7
+#define BFA_NO_IO_INDEX 9
+
+/**
+ * FCS itnim states
+ */
+enum bfa_itnim_state {
+ BFA_ITNIM_OFFLINE = 0, /* offline */
+ BFA_ITNIM_PRLI_SEND = 1, /* prli send */
+ BFA_ITNIM_PRLI_SENT = 2, /* prli sent */
+ BFA_ITNIM_PRLI_RETRY = 3, /* prli retry */
+ BFA_ITNIM_HCB_ONLINE = 4, /* online callback */
+ BFA_ITNIM_ONLINE = 5, /* online */
+ BFA_ITNIM_HCB_OFFLINE = 6, /* offline callback */
+ BFA_ITNIM_INITIATIOR = 7, /* initiator */
+};
+
+/**
+ * FCS remote port statistics
+ */
+struct bfa_itnim_stats_s {
+ u32 onlines; /* num rport online */
+ u32 offlines; /* num rport offline */
+ u32 prli_sent; /* num prli sent out */
+ u32 fcxp_alloc_wait;/* num fcxp alloc waits */
+ u32 prli_rsp_err; /* num prli rsp errors */
+ u32 prli_rsp_acc; /* num prli rsp accepts */
+ u32 initiator; /* rport is an initiator */
+ u32 prli_rsp_parse_err; /* prli rsp parsing errors */
+ u32 prli_rsp_rjt; /* num prli rsp rejects */
+ u32 timeout; /* num timeouts detected */
+ u32 sler; /* num sler notification from BFA */
+ u32 rsvd; /* padding for 64 bit alignment */
+};
+
+/**
+ * FCS itnim attributes returned in queries
+ */
+struct bfa_itnim_attr_s {
+ enum bfa_itnim_state state; /* FCS itnim state */
+ u8 retry; /* data retransmision support */
+ u8 task_retry_id; /* task retry ident support */
+ u8 rec_support; /* REC supported */
+ u8 conf_comp; /* confirmed completion supp */
+};
+
+#endif /* __BFA_DEFS_FCS_H__ */
diff --git a/drivers/scsi/bfa/bfa_defs_svc.h b/drivers/scsi/bfa/bfa_defs_svc.h
new file mode 100644
index 000000000000..56226fcf9470
--- /dev/null
+++ b/drivers/scsi/bfa/bfa_defs_svc.h
@@ -0,0 +1,1081 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_DEFS_SVC_H__
+#define __BFA_DEFS_SVC_H__
+
+#include "bfa_defs.h"
+#include "bfa_fc.h"
+#include "bfi.h"
+
+#define BFA_IOCFC_INTR_DELAY 1125
+#define BFA_IOCFC_INTR_LATENCY 225
+#define BFA_IOCFCOE_INTR_DELAY 25
+#define BFA_IOCFCOE_INTR_LATENCY 5
+
+/**
+ * Interrupt coalescing configuration.
+ */
+#pragma pack(1)
+struct bfa_iocfc_intr_attr_s {
+ u8 coalesce; /* enable/disable coalescing */
+ u8 rsvd[3];
+ u16 latency; /* latency in microseconds */
+ u16 delay; /* delay in microseconds */
+};
+
+/**
+ * IOC firmware configuraton
+ */
+struct bfa_iocfc_fwcfg_s {
+ u16 num_fabrics; /* number of fabrics */
+ u16 num_lports; /* number of local lports */
+ u16 num_rports; /* number of remote ports */
+ u16 num_ioim_reqs; /* number of IO reqs */
+ u16 num_tskim_reqs; /* task management requests */
+ u16 num_iotm_reqs; /* number of TM IO reqs */
+ u16 num_tsktm_reqs; /* TM task management requests*/
+ u16 num_fcxp_reqs; /* unassisted FC exchanges */
+ u16 num_uf_bufs; /* unsolicited recv buffers */
+ u8 num_cqs;
+ u8 fw_tick_res; /* FW clock resolution in ms */
+ u8 rsvd[4];
+};
+#pragma pack()
+
+struct bfa_iocfc_drvcfg_s {
+ u16 num_reqq_elems; /* number of req queue elements */
+ u16 num_rspq_elems; /* number of rsp queue elements */
+ u16 num_sgpgs; /* number of total SG pages */
+ u16 num_sboot_tgts; /* number of SAN boot targets */
+ u16 num_sboot_luns; /* number of SAN boot luns */
+ u16 ioc_recover; /* IOC recovery mode */
+ u16 min_cfg; /* minimum configuration */
+ u16 path_tov; /* device path timeout */
+ bfa_boolean_t delay_comp; /* delay completion of
+ failed inflight IOs */
+ u32 rsvd;
+};
+
+/**
+ * IOC configuration
+ */
+struct bfa_iocfc_cfg_s {
+ struct bfa_iocfc_fwcfg_s fwcfg; /* firmware side config */
+ struct bfa_iocfc_drvcfg_s drvcfg; /* driver side config */
+};
+
+/**
+ * IOC firmware IO stats
+ */
+struct bfa_fw_io_stats_s {
+ u32 host_abort; /* IO aborted by host driver*/
+ u32 host_cleanup; /* IO clean up by host driver */
+
+ u32 fw_io_timeout; /* IOs timedout */
+ u32 fw_frm_parse; /* frame parsed by f/w */
+ u32 fw_frm_data; /* fcp_data frame parsed by f/w */
+ u32 fw_frm_rsp; /* fcp_rsp frame parsed by f/w */
+ u32 fw_frm_xfer_rdy; /* xfer_rdy frame parsed by f/w */
+ u32 fw_frm_bls_acc; /* BLS ACC frame parsed by f/w */
+ u32 fw_frm_tgt_abort; /* target ABTS parsed by f/w */
+ u32 fw_frm_unknown; /* unknown parsed by f/w */
+ u32 fw_data_dma; /* f/w DMA'ed the data frame */
+ u32 fw_frm_drop; /* f/w drop the frame */
+
+ u32 rec_timeout; /* FW rec timed out */
+ u32 error_rec; /* FW sending rec on
+ * an error condition*/
+ u32 wait_for_si; /* FW wait for SI */
+ u32 rec_rsp_inval; /* REC rsp invalid */
+ u32 seqr_io_abort; /* target does not know cmd so abort */
+ u32 seqr_io_retry; /* SEQR failed so retry IO */
+
+ u32 itn_cisc_upd_rsp; /* ITN cisc updated on fcp_rsp */
+ u32 itn_cisc_upd_data; /* ITN cisc updated on fcp_data */
+ u32 itn_cisc_upd_xfer_rdy; /* ITN cisc updated on fcp_data */
+
+ u32 fcp_data_lost; /* fcp data lost */
+
+ u32 ro_set_in_xfer_rdy; /* Target set RO in Xfer_rdy frame */
+ u32 xfer_rdy_ooo_err; /* Out of order Xfer_rdy received */
+ u32 xfer_rdy_unknown_err; /* unknown error in xfer_rdy frame */
+
+ u32 io_abort_timeout; /* ABTS timedout */
+ u32 sler_initiated; /* SLER initiated */
+
+ u32 unexp_fcp_rsp; /* fcp response in wrong state */
+
+ u32 fcp_rsp_under_run; /* fcp rsp IO underrun */
+ u32 fcp_rsp_under_run_wr; /* fcp rsp IO underrun for write */
+ u32 fcp_rsp_under_run_err; /* fcp rsp IO underrun error */
+ u32 fcp_rsp_resid_inval; /* invalid residue */
+ u32 fcp_rsp_over_run; /* fcp rsp IO overrun */
+ u32 fcp_rsp_over_run_err; /* fcp rsp IO overrun error */
+ u32 fcp_rsp_proto_err; /* protocol error in fcp rsp */
+ u32 fcp_rsp_sense_err; /* error in sense info in fcp rsp */
+ u32 fcp_conf_req; /* FCP conf requested */
+
+ u32 tgt_aborted_io; /* target initiated abort */
+
+ u32 ioh_edtov_timeout_event;/* IOH edtov timer popped */
+ u32 ioh_fcp_rsp_excp_event; /* IOH FCP_RSP exception */
+ u32 ioh_fcp_conf_event; /* IOH FCP_CONF */
+ u32 ioh_mult_frm_rsp_event; /* IOH multi_frame FCP_RSP */
+ u32 ioh_hit_class2_event; /* IOH hit class2 */
+ u32 ioh_miss_other_event; /* IOH miss other */
+ u32 ioh_seq_cnt_err_event; /* IOH seq cnt error */
+ u32 ioh_len_err_event; /* IOH len error - fcp_dl !=
+ * bytes xfered */
+ u32 ioh_seq_len_err_event; /* IOH seq len error */
+ u32 ioh_data_oor_event; /* Data out of range */
+ u32 ioh_ro_ooo_event; /* Relative offset out of range */
+ u32 ioh_cpu_owned_event; /* IOH hit -iost owned by f/w */
+ u32 ioh_unexp_frame_event; /* unexpected frame recieved
+ * count */
+ u32 ioh_err_int; /* IOH error int during data-phase
+ * for scsi write
+ */
+};
+
+/**
+ * IOC port firmware stats
+ */
+
+struct bfa_fw_port_fpg_stats_s {
+ u32 intr_evt;
+ u32 intr;
+ u32 intr_excess;
+ u32 intr_cause0;
+ u32 intr_other;
+ u32 intr_other_ign;
+ u32 sig_lost;
+ u32 sig_regained;
+ u32 sync_lost;
+ u32 sync_to;
+ u32 sync_regained;
+ u32 div2_overflow;
+ u32 div2_underflow;
+ u32 efifo_overflow;
+ u32 efifo_underflow;
+ u32 idle_rx;
+ u32 lrr_rx;
+ u32 lr_rx;
+ u32 ols_rx;
+ u32 nos_rx;
+ u32 lip_rx;
+ u32 arbf0_rx;
+ u32 arb_rx;
+ u32 mrk_rx;
+ u32 const_mrk_rx;
+ u32 prim_unknown;
+};
+
+
+struct bfa_fw_port_lksm_stats_s {
+ u32 hwsm_success; /* hwsm state machine success */
+ u32 hwsm_fails; /* hwsm fails */
+ u32 hwsm_wdtov; /* hwsm timed out */
+ u32 swsm_success; /* swsm success */
+ u32 swsm_fails; /* swsm fails */
+ u32 swsm_wdtov; /* swsm timed out */
+ u32 busybufs; /* link init failed due to busybuf */
+ u32 buf_waits; /* bufwait state entries */
+ u32 link_fails; /* link failures */
+ u32 psp_errors; /* primitive sequence protocol errors */
+ u32 lr_unexp; /* No. of times LR rx-ed unexpectedly */
+ u32 lrr_unexp; /* No. of times LRR rx-ed unexpectedly */
+ u32 lr_tx; /* No. of times LR tx started */
+ u32 lrr_tx; /* No. of times LRR tx started */
+ u32 ols_tx; /* No. of times OLS tx started */
+ u32 nos_tx; /* No. of times NOS tx started */
+ u32 hwsm_lrr_rx; /* No. of times LRR rx-ed by HWSM */
+ u32 hwsm_lr_rx; /* No. of times LR rx-ed by HWSM */
+};
+
+struct bfa_fw_port_snsm_stats_s {
+ u32 hwsm_success; /* Successful hwsm terminations */
+ u32 hwsm_fails; /* hwsm fail count */
+ u32 hwsm_wdtov; /* hwsm timed out */
+ u32 swsm_success; /* swsm success */
+ u32 swsm_wdtov; /* swsm timed out */
+ u32 error_resets; /* error resets initiated by upsm */
+ u32 sync_lost; /* Sync loss count */
+ u32 sig_lost; /* Signal loss count */
+};
+
+struct bfa_fw_port_physm_stats_s {
+ u32 module_inserts; /* Module insert count */
+ u32 module_xtracts; /* Module extracts count */
+ u32 module_invalids; /* Invalid module inserted count */
+ u32 module_read_ign; /* Module validation status ignored */
+ u32 laser_faults; /* Laser fault count */
+ u32 rsvd;
+};
+
+struct bfa_fw_fip_stats_s {
+ u32 vlan_req; /* vlan discovery requests */
+ u32 vlan_notify; /* vlan notifications */
+ u32 vlan_err; /* vlan response error */
+ u32 vlan_timeouts; /* vlan disvoery timeouts */
+ u32 vlan_invalids; /* invalid vlan in discovery advert. */
+ u32 disc_req; /* Discovery solicit requests */
+ u32 disc_rsp; /* Discovery solicit response */
+ u32 disc_err; /* Discovery advt. parse errors */
+ u32 disc_unsol; /* Discovery unsolicited */
+ u32 disc_timeouts; /* Discovery timeouts */
+ u32 disc_fcf_unavail; /* Discovery FCF Not Avail. */
+ u32 linksvc_unsupp; /* Unsupported link service req */
+ u32 linksvc_err; /* Parse error in link service req */
+ u32 logo_req; /* FIP logos received */
+ u32 clrvlink_req; /* Clear virtual link req */
+ u32 op_unsupp; /* Unsupported FIP operation */
+ u32 untagged; /* Untagged frames (ignored) */
+ u32 invalid_version; /* Invalid FIP version */
+};
+
+struct bfa_fw_lps_stats_s {
+ u32 mac_invalids; /* Invalid mac assigned */
+ u32 rsvd;
+};
+
+struct bfa_fw_fcoe_stats_s {
+ u32 cee_linkups; /* CEE link up count */
+ u32 cee_linkdns; /* CEE link down count */
+ u32 fip_linkups; /* FIP link up count */
+ u32 fip_linkdns; /* FIP link up count */
+ u32 fip_fails; /* FIP fail count */
+ u32 mac_invalids; /* Invalid mac assigned */
+};
+
+/**
+ * IOC firmware FCoE port stats
+ */
+struct bfa_fw_fcoe_port_stats_s {
+ struct bfa_fw_fcoe_stats_s fcoe_stats;
+ struct bfa_fw_fip_stats_s fip_stats;
+};
+
+/**
+ * IOC firmware FC uport stats
+ */
+struct bfa_fw_fc_uport_stats_s {
+ struct bfa_fw_port_snsm_stats_s snsm_stats;
+ struct bfa_fw_port_lksm_stats_s lksm_stats;
+};
+
+/**
+ * IOC firmware FC port stats
+ */
+union bfa_fw_fc_port_stats_s {
+ struct bfa_fw_fc_uport_stats_s fc_stats;
+ struct bfa_fw_fcoe_port_stats_s fcoe_stats;
+};
+
+/**
+ * IOC firmware port stats
+ */
+struct bfa_fw_port_stats_s {
+ struct bfa_fw_port_fpg_stats_s fpg_stats;
+ struct bfa_fw_port_physm_stats_s physm_stats;
+ union bfa_fw_fc_port_stats_s fc_port;
+};
+
+/**
+ * fcxchg module statistics
+ */
+struct bfa_fw_fcxchg_stats_s {
+ u32 ua_tag_inv;
+ u32 ua_state_inv;
+};
+
+struct bfa_fw_lpsm_stats_s {
+ u32 cls_rx;
+ u32 cls_tx;
+};
+
+/**
+ * Trunk statistics
+ */
+struct bfa_fw_trunk_stats_s {
+ u32 emt_recvd; /* Trunk EMT received */
+ u32 emt_accepted; /* Trunk EMT Accepted */
+ u32 emt_rejected; /* Trunk EMT rejected */
+ u32 etp_recvd; /* Trunk ETP received */
+ u32 etp_accepted; /* Trunk ETP Accepted */
+ u32 etp_rejected; /* Trunk ETP rejected */
+ u32 lr_recvd; /* Trunk LR received */
+ u32 rsvd; /* padding for 64 bit alignment */
+};
+
+struct bfa_fw_advsm_stats_s {
+ u32 flogi_sent; /* Flogi sent */
+ u32 flogi_acc_recvd; /* Flogi Acc received */
+ u32 flogi_rjt_recvd; /* Flogi rejects received */
+ u32 flogi_retries; /* Flogi retries */
+
+ u32 elp_recvd; /* ELP received */
+ u32 elp_accepted; /* ELP Accepted */
+ u32 elp_rejected; /* ELP rejected */
+ u32 elp_dropped; /* ELP dropped */
+};
+
+/**
+ * IOCFC firmware stats
+ */
+struct bfa_fw_iocfc_stats_s {
+ u32 cfg_reqs; /* cfg request */
+ u32 updq_reqs; /* update queue request */
+ u32 ic_reqs; /* interrupt coalesce reqs */
+ u32 unknown_reqs;
+ u32 set_intr_reqs; /* set interrupt reqs */
+};
+
+/**
+ * IOC attributes returned in queries
+ */
+struct bfa_iocfc_attr_s {
+ struct bfa_iocfc_cfg_s config; /* IOCFC config */
+ struct bfa_iocfc_intr_attr_s intr_attr; /* interrupt attr */
+};
+
+/**
+ * Eth_sndrcv mod stats
+ */
+struct bfa_fw_eth_sndrcv_stats_s {
+ u32 crc_err;
+ u32 rsvd; /* 64bit align */
+};
+
+/**
+ * CT MAC mod stats
+ */
+struct bfa_fw_mac_mod_stats_s {
+ u32 mac_on; /* MAC got turned-on */
+ u32 link_up; /* link-up */
+ u32 signal_off; /* lost signal */
+ u32 dfe_on; /* DFE on */
+ u32 mac_reset; /* # of MAC reset to bring lnk up */
+ u32 pcs_reset; /* # of PCS reset to bring lnk up */
+ u32 loopback; /* MAC got into serdes loopback */
+ u32 lb_mac_reset;
+ /* # of MAC reset to bring link up in loopback */
+ u32 lb_pcs_reset;
+ /* # of PCS reset to bring link up in loopback */
+ u32 rsvd; /* 64bit align */
+};
+
+/**
+ * CT MOD stats
+ */
+struct bfa_fw_ct_mod_stats_s {
+ u32 rxa_rds_undrun; /* RxA RDS underrun */
+ u32 rad_bpc_ovfl; /* RAD BPC overflow */
+ u32 rad_rlb_bpc_ovfl; /* RAD RLB BPC overflow */
+ u32 bpc_fcs_err; /* BPC FCS_ERR */
+ u32 txa_tso_hdr; /* TxA TSO header too long */
+ u32 rsvd; /* 64bit align */
+};
+
+/**
+ * IOC firmware stats
+ */
+struct bfa_fw_stats_s {
+ struct bfa_fw_ioc_stats_s ioc_stats;
+ struct bfa_fw_iocfc_stats_s iocfc_stats;
+ struct bfa_fw_io_stats_s io_stats;
+ struct bfa_fw_port_stats_s port_stats;
+ struct bfa_fw_fcxchg_stats_s fcxchg_stats;
+ struct bfa_fw_lpsm_stats_s lpsm_stats;
+ struct bfa_fw_lps_stats_s lps_stats;
+ struct bfa_fw_trunk_stats_s trunk_stats;
+ struct bfa_fw_advsm_stats_s advsm_stats;
+ struct bfa_fw_mac_mod_stats_s macmod_stats;
+ struct bfa_fw_ct_mod_stats_s ctmod_stats;
+ struct bfa_fw_eth_sndrcv_stats_s ethsndrcv_stats;
+};
+
+#define BFA_IOCFC_PATHTOV_MAX 60
+#define BFA_IOCFC_QDEPTH_MAX 2000
+
+/**
+ * QoS states
+ */
+enum bfa_qos_state {
+ BFA_QOS_ONLINE = 1, /* QoS is online */
+ BFA_QOS_OFFLINE = 2, /* QoS is offline */
+};
+
+/**
+ * QoS Priority levels.
+ */
+enum bfa_qos_priority {
+ BFA_QOS_UNKNOWN = 0,
+ BFA_QOS_HIGH = 1, /* QoS Priority Level High */
+ BFA_QOS_MED = 2, /* QoS Priority Level Medium */
+ BFA_QOS_LOW = 3, /* QoS Priority Level Low */
+};
+
+/**
+ * QoS bandwidth allocation for each priority level
+ */
+enum bfa_qos_bw_alloc {
+ BFA_QOS_BW_HIGH = 60, /* bandwidth allocation for High */
+ BFA_QOS_BW_MED = 30, /* bandwidth allocation for Medium */
+ BFA_QOS_BW_LOW = 10, /* bandwidth allocation for Low */
+};
+#pragma pack(1)
+/**
+ * QoS attribute returned in QoS Query
+ */
+struct bfa_qos_attr_s {
+ u8 state; /* QoS current state */
+ u8 rsvd[3];
+ u32 total_bb_cr; /* Total BB Credits */
+};
+
+/**
+ * These fields should be displayed only from the CLI.
+ * There will be a separate BFAL API (get_qos_vc_attr ?)
+ * to retrieve this.
+ *
+ */
+#define BFA_QOS_MAX_VC 16
+
+struct bfa_qos_vc_info_s {
+ u8 vc_credit;
+ u8 borrow_credit;
+ u8 priority;
+ u8 resvd;
+};
+
+struct bfa_qos_vc_attr_s {
+ u16 total_vc_count; /* Total VC Count */
+ u16 shared_credit;
+ u32 elp_opmode_flags;
+ struct bfa_qos_vc_info_s vc_info[BFA_QOS_MAX_VC]; /* as many as
+ * total_vc_count */
+};
+
+/**
+ * QoS statistics
+ */
+struct bfa_qos_stats_s {
+ u32 flogi_sent; /* QoS Flogi sent */
+ u32 flogi_acc_recvd; /* QoS Flogi Acc received */
+ u32 flogi_rjt_recvd; /* QoS Flogi rejects received */
+ u32 flogi_retries; /* QoS Flogi retries */
+
+ u32 elp_recvd; /* QoS ELP received */
+ u32 elp_accepted; /* QoS ELP Accepted */
+ u32 elp_rejected; /* QoS ELP rejected */
+ u32 elp_dropped; /* QoS ELP dropped */
+
+ u32 qos_rscn_recvd; /* QoS RSCN received */
+ u32 rsvd; /* padding for 64 bit alignment */
+};
+
+/**
+ * FCoE statistics
+ */
+struct bfa_fcoe_stats_s {
+ u64 secs_reset; /* Seconds since stats reset */
+ u64 cee_linkups; /* CEE link up */
+ u64 cee_linkdns; /* CEE link down */
+ u64 fip_linkups; /* FIP link up */
+ u64 fip_linkdns; /* FIP link down */
+ u64 fip_fails; /* FIP failures */
+ u64 mac_invalids; /* Invalid mac assignments */
+ u64 vlan_req; /* Vlan requests */
+ u64 vlan_notify; /* Vlan notifications */
+ u64 vlan_err; /* Vlan notification errors */
+ u64 vlan_timeouts; /* Vlan request timeouts */
+ u64 vlan_invalids; /* Vlan invalids */
+ u64 disc_req; /* Discovery requests */
+ u64 disc_rsp; /* Discovery responses */
+ u64 disc_err; /* Discovery error frames */
+ u64 disc_unsol; /* Discovery unsolicited */
+ u64 disc_timeouts; /* Discovery timeouts */
+ u64 disc_fcf_unavail; /* Discovery FCF not avail */
+ u64 linksvc_unsupp; /* FIP link service req unsupp. */
+ u64 linksvc_err; /* FIP link service req errors */
+ u64 logo_req; /* FIP logos received */
+ u64 clrvlink_req; /* Clear virtual link requests */
+ u64 op_unsupp; /* FIP operation unsupp. */
+ u64 untagged; /* FIP untagged frames */
+ u64 txf_ucast; /* Tx FCoE unicast frames */
+ u64 txf_ucast_vlan; /* Tx FCoE unicast vlan frames */
+ u64 txf_ucast_octets; /* Tx FCoE unicast octets */
+ u64 txf_mcast; /* Tx FCoE multicast frames */
+ u64 txf_mcast_vlan; /* Tx FCoE multicast vlan frames */
+ u64 txf_mcast_octets; /* Tx FCoE multicast octets */
+ u64 txf_bcast; /* Tx FCoE broadcast frames */
+ u64 txf_bcast_vlan; /* Tx FCoE broadcast vlan frames */
+ u64 txf_bcast_octets; /* Tx FCoE broadcast octets */
+ u64 txf_timeout; /* Tx timeouts */
+ u64 txf_parity_errors; /* Transmit parity err */
+ u64 txf_fid_parity_errors; /* Transmit FID parity err */
+ u64 rxf_ucast_octets; /* Rx FCoE unicast octets */
+ u64 rxf_ucast; /* Rx FCoE unicast frames */
+ u64 rxf_ucast_vlan; /* Rx FCoE unicast vlan frames */
+ u64 rxf_mcast_octets; /* Rx FCoE multicast octets */
+ u64 rxf_mcast; /* Rx FCoE multicast frames */
+ u64 rxf_mcast_vlan; /* Rx FCoE multicast vlan frames */
+ u64 rxf_bcast_octets; /* Rx FCoE broadcast octets */
+ u64 rxf_bcast; /* Rx FCoE broadcast frames */
+ u64 rxf_bcast_vlan; /* Rx FCoE broadcast vlan frames */
+};
+
+/**
+ * QoS or FCoE stats (fcport stats excluding physical FC port stats)
+ */
+union bfa_fcport_stats_u {
+ struct bfa_qos_stats_s fcqos;
+ struct bfa_fcoe_stats_s fcoe;
+};
+#pragma pack()
+
+struct bfa_fcpim_del_itn_stats_s {
+ u32 del_itn_iocomp_aborted; /* Aborted IO requests */
+ u32 del_itn_iocomp_timedout; /* IO timeouts */
+ u32 del_itn_iocom_sqer_needed; /* IO retry for SQ error recovery */
+ u32 del_itn_iocom_res_free; /* Delayed freeing of IO resources */
+ u32 del_itn_iocom_hostabrts; /* Host IO abort requests */
+ u32 del_itn_total_ios; /* Total IO count */
+ u32 del_io_iocdowns; /* IO cleaned-up due to IOC down */
+ u32 del_tm_iocdowns; /* TM cleaned-up due to IOC down */
+};
+
+struct bfa_itnim_iostats_s {
+
+ u32 total_ios; /* Total IO Requests */
+ u32 input_reqs; /* Data in-bound requests */
+ u32 output_reqs; /* Data out-bound requests */
+ u32 io_comps; /* Total IO Completions */
+ u32 wr_throughput; /* Write data transfered in bytes */
+ u32 rd_throughput; /* Read data transfered in bytes */
+
+ u32 iocomp_ok; /* Slowpath IO completions */
+ u32 iocomp_underrun; /* IO underrun */
+ u32 iocomp_overrun; /* IO overrun */
+ u32 qwait; /* IO Request-Q wait */
+ u32 qresumes; /* IO Request-Q wait done */
+ u32 no_iotags; /* No free IO tag */
+ u32 iocomp_timedout; /* IO timeouts */
+ u32 iocom_nexus_abort; /* IO failure due to target offline */
+ u32 iocom_proto_err; /* IO protocol errors */
+ u32 iocom_dif_err; /* IO SBC-3 protection errors */
+
+ u32 iocom_sqer_needed; /* fcp-2 error recovery failed */
+ u32 iocom_res_free; /* Delayed freeing of IO tag */
+
+
+ u32 io_aborts; /* Host IO abort requests */
+ u32 iocom_hostabrts; /* Host IO abort completions */
+ u32 io_cleanups; /* IO clean-up requests */
+ u32 path_tov_expired; /* IO path tov expired */
+ u32 iocomp_aborted; /* IO abort completions */
+ u32 io_iocdowns; /* IO cleaned-up due to IOC down */
+ u32 iocom_utags; /* IO comp with unknown tags */
+
+ u32 io_tmaborts; /* Abort request due to TM command */
+ u32 tm_io_comps; /* Abort completion due to TM command */
+
+ u32 creates; /* IT Nexus create requests */
+ u32 fw_create; /* IT Nexus FW create requests */
+ u32 create_comps; /* IT Nexus FW create completions */
+ u32 onlines; /* IT Nexus onlines */
+ u32 offlines; /* IT Nexus offlines */
+ u32 fw_delete; /* IT Nexus FW delete requests */
+ u32 delete_comps; /* IT Nexus FW delete completions */
+ u32 deletes; /* IT Nexus delete requests */
+ u32 sler_events; /* SLER events */
+ u32 ioc_disabled; /* Num IOC disables */
+ u32 cleanup_comps; /* IT Nexus cleanup completions */
+
+ u32 tm_cmnds; /* TM Requests */
+ u32 tm_fw_rsps; /* TM Completions */
+ u32 tm_success; /* TM initiated IO cleanup success */
+ u32 tm_failures; /* TM initiated IO cleanup failure */
+ u32 no_tskims; /* No free TM tag */
+ u32 tm_qwait; /* TM Request-Q wait */
+ u32 tm_qresumes; /* TM Request-Q wait done */
+
+ u32 tm_iocdowns; /* TM cleaned-up due to IOC down */
+ u32 tm_cleanups; /* TM cleanup requests */
+ u32 tm_cleanup_comps; /* TM cleanup completions */
+};
+
+/* Modify char* port_stt[] in bfal_port.c if a new state was added */
+enum bfa_port_states {
+ BFA_PORT_ST_UNINIT = 1,
+ BFA_PORT_ST_ENABLING_QWAIT = 2,
+ BFA_PORT_ST_ENABLING = 3,
+ BFA_PORT_ST_LINKDOWN = 4,
+ BFA_PORT_ST_LINKUP = 5,
+ BFA_PORT_ST_DISABLING_QWAIT = 6,
+ BFA_PORT_ST_DISABLING = 7,
+ BFA_PORT_ST_DISABLED = 8,
+ BFA_PORT_ST_STOPPED = 9,
+ BFA_PORT_ST_IOCDOWN = 10,
+ BFA_PORT_ST_IOCDIS = 11,
+ BFA_PORT_ST_FWMISMATCH = 12,
+ BFA_PORT_ST_PREBOOT_DISABLED = 13,
+ BFA_PORT_ST_TOGGLING_QWAIT = 14,
+ BFA_PORT_ST_MAX_STATE,
+};
+
+/**
+ * Port operational type (in sync with SNIA port type).
+ */
+enum bfa_port_type {
+ BFA_PORT_TYPE_UNKNOWN = 1, /* port type is unknown */
+ BFA_PORT_TYPE_NPORT = 5, /* P2P with switched fabric */
+ BFA_PORT_TYPE_NLPORT = 6, /* public loop */
+ BFA_PORT_TYPE_LPORT = 20, /* private loop */
+ BFA_PORT_TYPE_P2P = 21, /* P2P with no switched fabric */
+ BFA_PORT_TYPE_VPORT = 22, /* NPIV - virtual port */
+};
+
+/**
+ * Port topology setting. A port's topology and fabric login status
+ * determine its operational type.
+ */
+enum bfa_port_topology {
+ BFA_PORT_TOPOLOGY_NONE = 0, /* No valid topology */
+ BFA_PORT_TOPOLOGY_P2P = 1, /* P2P only */
+ BFA_PORT_TOPOLOGY_LOOP = 2, /* LOOP topology */
+ BFA_PORT_TOPOLOGY_AUTO = 3, /* auto topology selection */
+};
+
+/**
+ * Physical port loopback types.
+ */
+enum bfa_port_opmode {
+ BFA_PORT_OPMODE_NORMAL = 0x00, /* normal non-loopback mode */
+ BFA_PORT_OPMODE_LB_INT = 0x01, /* internal loop back */
+ BFA_PORT_OPMODE_LB_SLW = 0x02, /* serial link wrapback (serdes) */
+ BFA_PORT_OPMODE_LB_EXT = 0x04, /* external loop back (serdes) */
+ BFA_PORT_OPMODE_LB_CBL = 0x08, /* cabled loop back */
+ BFA_PORT_OPMODE_LB_NLINT = 0x20, /* NL_Port internal loopback */
+};
+
+#define BFA_PORT_OPMODE_LB_HARD(_mode) \
+ ((_mode == BFA_PORT_OPMODE_LB_INT) || \
+ (_mode == BFA_PORT_OPMODE_LB_SLW) || \
+ (_mode == BFA_PORT_OPMODE_LB_EXT))
+
+/**
+ * Port link state
+ */
+enum bfa_port_linkstate {
+ BFA_PORT_LINKUP = 1, /* Physical port/Trunk link up */
+ BFA_PORT_LINKDOWN = 2, /* Physical port/Trunk link down */
+};
+
+/**
+ * Port link state reason code
+ */
+enum bfa_port_linkstate_rsn {
+ BFA_PORT_LINKSTATE_RSN_NONE = 0,
+ BFA_PORT_LINKSTATE_RSN_DISABLED = 1,
+ BFA_PORT_LINKSTATE_RSN_RX_NOS = 2,
+ BFA_PORT_LINKSTATE_RSN_RX_OLS = 3,
+ BFA_PORT_LINKSTATE_RSN_RX_LIP = 4,
+ BFA_PORT_LINKSTATE_RSN_RX_LIPF7 = 5,
+ BFA_PORT_LINKSTATE_RSN_SFP_REMOVED = 6,
+ BFA_PORT_LINKSTATE_RSN_PORT_FAULT = 7,
+ BFA_PORT_LINKSTATE_RSN_RX_LOS = 8,
+ BFA_PORT_LINKSTATE_RSN_LOCAL_FAULT = 9,
+ BFA_PORT_LINKSTATE_RSN_REMOTE_FAULT = 10,
+ BFA_PORT_LINKSTATE_RSN_TIMEOUT = 11,
+
+
+
+ /* CEE related reason codes/errors */
+ CEE_LLDP_INFO_AGED_OUT = 20,
+ CEE_LLDP_SHUTDOWN_TLV_RCVD = 21,
+ CEE_PEER_NOT_ADVERTISE_DCBX = 22,
+ CEE_PEER_NOT_ADVERTISE_PG = 23,
+ CEE_PEER_NOT_ADVERTISE_PFC = 24,
+ CEE_PEER_NOT_ADVERTISE_FCOE = 25,
+ CEE_PG_NOT_COMPATIBLE = 26,
+ CEE_PFC_NOT_COMPATIBLE = 27,
+ CEE_FCOE_NOT_COMPATIBLE = 28,
+ CEE_BAD_PG_RCVD = 29,
+ CEE_BAD_BW_RCVD = 30,
+ CEE_BAD_PFC_RCVD = 31,
+ CEE_BAD_APP_PRI_RCVD = 32,
+ CEE_FCOE_PRI_PFC_OFF = 33,
+ CEE_DUP_CONTROL_TLV_RCVD = 34,
+ CEE_DUP_FEAT_TLV_RCVD = 35,
+ CEE_APPLY_NEW_CFG = 36, /* reason, not error */
+ CEE_PROTOCOL_INIT = 37, /* reason, not error */
+ CEE_PHY_LINK_DOWN = 38,
+ CEE_LLS_FCOE_ABSENT = 39,
+ CEE_LLS_FCOE_DOWN = 40,
+ CEE_ISCSI_NOT_COMPATIBLE = 41,
+ CEE_ISCSI_PRI_PFC_OFF = 42,
+ CEE_ISCSI_PRI_OVERLAP_FCOE_PRI = 43
+};
+#pragma pack(1)
+/**
+ * Physical port configuration
+ */
+struct bfa_port_cfg_s {
+ u8 topology; /* bfa_port_topology */
+ u8 speed; /* enum bfa_port_speed */
+ u8 trunked; /* trunked or not */
+ u8 qos_enabled; /* qos enabled or not */
+ u8 cfg_hardalpa; /* is hard alpa configured */
+ u8 hardalpa; /* configured hard alpa */
+ u16 maxfrsize; /* maximum frame size */
+ u8 rx_bbcredit; /* receive buffer credits */
+ u8 tx_bbcredit; /* transmit buffer credits */
+ u8 ratelimit; /* ratelimit enabled or not */
+ u8 trl_def_speed; /* ratelimit default speed */
+ u16 path_tov; /* device path timeout */
+ u16 q_depth; /* SCSI Queue depth */
+};
+#pragma pack()
+
+/**
+ * Port attribute values.
+ */
+struct bfa_port_attr_s {
+ /*
+ * Static fields
+ */
+ wwn_t nwwn; /* node wwn */
+ wwn_t pwwn; /* port wwn */
+ wwn_t factorynwwn; /* factory node wwn */
+ wwn_t factorypwwn; /* factory port wwn */
+ enum fc_cos cos_supported; /* supported class of services */
+ u32 rsvd;
+ struct fc_symname_s port_symname; /* port symbolic name */
+ enum bfa_port_speed speed_supported; /* supported speeds */
+ bfa_boolean_t pbind_enabled;
+
+ /*
+ * Configured values
+ */
+ struct bfa_port_cfg_s pport_cfg; /* pport cfg */
+
+ /*
+ * Dynamic field - info from BFA
+ */
+ enum bfa_port_states port_state; /* current port state */
+ enum bfa_port_speed speed; /* current speed */
+ enum bfa_port_topology topology; /* current topology */
+ bfa_boolean_t beacon; /* current beacon status */
+ bfa_boolean_t link_e2e_beacon; /* link beacon is on */
+ bfa_boolean_t plog_enabled; /* portlog is enabled */
+
+ /*
+ * Dynamic field - info from FCS
+ */
+ u32 pid; /* port ID */
+ enum bfa_port_type port_type; /* current topology */
+ u32 loopback; /* external loopback */
+ u32 authfail; /* auth fail state */
+ bfa_boolean_t io_profile; /* get it from fcpim mod */
+ u8 pad[4]; /* for 64-bit alignement */
+
+ /* FCoE specific */
+ u16 fcoe_vlan;
+ u8 rsvd1[6];
+};
+
+/**
+ * Port FCP mappings.
+ */
+struct bfa_port_fcpmap_s {
+ char osdevname[256];
+ u32 bus;
+ u32 target;
+ u32 oslun;
+ u32 fcid;
+ wwn_t nwwn;
+ wwn_t pwwn;
+ u64 fcplun;
+ char luid[256];
+};
+
+/**
+ * Port RNID info.
+ */
+struct bfa_port_rnid_s {
+ wwn_t wwn;
+ u32 unittype;
+ u32 portid;
+ u32 attached_nodes_num;
+ u16 ip_version;
+ u16 udp_port;
+ u8 ipaddr[16];
+ u16 rsvd;
+ u16 topologydiscoveryflags;
+};
+
+#pragma pack(1)
+struct bfa_fcport_fcf_s {
+ wwn_t name; /* FCF name */
+ wwn_t fabric_name; /* Fabric Name */
+ u8 fipenabled; /* FIP enabled or not */
+ u8 fipfailed; /* FIP failed or not */
+ u8 resv[2];
+ u8 pri; /* FCF priority */
+ u8 version; /* FIP version used */
+ u8 available; /* Available for login */
+ u8 fka_disabled; /* FKA is disabled */
+ u8 maxsz_verified; /* FCoE max size verified */
+ u8 fc_map[3]; /* FC map */
+ u16 vlan; /* FCoE vlan tag/priority */
+ u32 fka_adv_per; /* FIP ka advert. period */
+ mac_t mac; /* FCF mac */
+};
+
+/**
+ * Trunk states for BCU/BFAL
+ */
+enum bfa_trunk_state {
+ BFA_TRUNK_DISABLED = 0, /* Trunk is not configured */
+ BFA_TRUNK_ONLINE = 1, /* Trunk is online */
+ BFA_TRUNK_OFFLINE = 2, /* Trunk is offline */
+};
+
+/**
+ * VC attributes for trunked link
+ */
+struct bfa_trunk_vc_attr_s {
+ u32 bb_credit;
+ u32 elp_opmode_flags;
+ u32 req_credit;
+ u16 vc_credits[8];
+};
+
+/**
+ * Link state information
+ */
+struct bfa_port_link_s {
+ u8 linkstate; /* Link state bfa_port_linkstate */
+ u8 linkstate_rsn; /* bfa_port_linkstate_rsn_t */
+ u8 topology; /* P2P/LOOP bfa_port_topology */
+ u8 speed; /* Link speed (1/2/4/8 G) */
+ u32 linkstate_opt; /* Linkstate optional data (debug) */
+ u8 trunked; /* Trunked or not (1 or 0) */
+ u8 resvd[3];
+ struct bfa_qos_attr_s qos_attr; /* QoS Attributes */
+ union {
+ struct bfa_qos_vc_attr_s qos_vc_attr; /* VC info from ELP */
+ struct bfa_trunk_vc_attr_s trunk_vc_attr;
+ struct bfa_fcport_fcf_s fcf; /* FCF information (for FCoE) */
+ } vc_fcf;
+};
+#pragma pack()
+
+enum bfa_trunk_link_fctl {
+ BFA_TRUNK_LINK_FCTL_NORMAL,
+ BFA_TRUNK_LINK_FCTL_VC,
+ BFA_TRUNK_LINK_FCTL_VC_QOS,
+};
+
+enum bfa_trunk_link_state {
+ BFA_TRUNK_LINK_STATE_UP = 1, /* link part of trunk */
+ BFA_TRUNK_LINK_STATE_DN_LINKDN = 2, /* physical link down */
+ BFA_TRUNK_LINK_STATE_DN_GRP_MIS = 3, /* trunk group different */
+ BFA_TRUNK_LINK_STATE_DN_SPD_MIS = 4, /* speed mismatch */
+ BFA_TRUNK_LINK_STATE_DN_MODE_MIS = 5, /* remote port not trunked */
+};
+
+#define BFA_TRUNK_MAX_PORTS 2
+struct bfa_trunk_link_attr_s {
+ wwn_t trunk_wwn;
+ enum bfa_trunk_link_fctl fctl;
+ enum bfa_trunk_link_state link_state;
+ enum bfa_port_speed speed;
+ u32 deskew;
+};
+
+struct bfa_trunk_attr_s {
+ enum bfa_trunk_state state;
+ enum bfa_port_speed speed;
+ u32 port_id;
+ u32 rsvd;
+ struct bfa_trunk_link_attr_s link_attr[BFA_TRUNK_MAX_PORTS];
+};
+
+struct bfa_rport_hal_stats_s {
+ u32 sm_un_cr; /* uninit: create events */
+ u32 sm_un_unexp; /* uninit: exception events */
+ u32 sm_cr_on; /* created: online events */
+ u32 sm_cr_del; /* created: delete events */
+ u32 sm_cr_hwf; /* created: IOC down */
+ u32 sm_cr_unexp; /* created: exception events */
+ u32 sm_fwc_rsp; /* fw create: f/w responses */
+ u32 sm_fwc_del; /* fw create: delete events */
+ u32 sm_fwc_off; /* fw create: offline events */
+ u32 sm_fwc_hwf; /* fw create: IOC down */
+ u32 sm_fwc_unexp; /* fw create: exception events*/
+ u32 sm_on_off; /* online: offline events */
+ u32 sm_on_del; /* online: delete events */
+ u32 sm_on_hwf; /* online: IOC down events */
+ u32 sm_on_unexp; /* online: exception events */
+ u32 sm_fwd_rsp; /* fw delete: fw responses */
+ u32 sm_fwd_del; /* fw delete: delete events */
+ u32 sm_fwd_hwf; /* fw delete: IOC down events */
+ u32 sm_fwd_unexp; /* fw delete: exception events*/
+ u32 sm_off_del; /* offline: delete events */
+ u32 sm_off_on; /* offline: online events */
+ u32 sm_off_hwf; /* offline: IOC down events */
+ u32 sm_off_unexp; /* offline: exception events */
+ u32 sm_del_fwrsp; /* delete: fw responses */
+ u32 sm_del_hwf; /* delete: IOC down events */
+ u32 sm_del_unexp; /* delete: exception events */
+ u32 sm_delp_fwrsp; /* delete pend: fw responses */
+ u32 sm_delp_hwf; /* delete pend: IOC downs */
+ u32 sm_delp_unexp; /* delete pend: exceptions */
+ u32 sm_offp_fwrsp; /* off-pending: fw responses */
+ u32 sm_offp_del; /* off-pending: deletes */
+ u32 sm_offp_hwf; /* off-pending: IOC downs */
+ u32 sm_offp_unexp; /* off-pending: exceptions */
+ u32 sm_iocd_off; /* IOC down: offline events */
+ u32 sm_iocd_del; /* IOC down: delete events */
+ u32 sm_iocd_on; /* IOC down: online events */
+ u32 sm_iocd_unexp; /* IOC down: exceptions */
+ u32 rsvd;
+};
+#pragma pack(1)
+/**
+ * Rport's QoS attributes
+ */
+struct bfa_rport_qos_attr_s {
+ u8 qos_priority; /* rport's QoS priority */
+ u8 rsvd[3];
+ u32 qos_flow_id; /* QoS flow Id */
+};
+#pragma pack()
+
+#define BFA_IOBUCKET_MAX 14
+
+struct bfa_itnim_latency_s {
+ u32 min[BFA_IOBUCKET_MAX];
+ u32 max[BFA_IOBUCKET_MAX];
+ u32 count[BFA_IOBUCKET_MAX];
+ u32 avg[BFA_IOBUCKET_MAX];
+};
+
+struct bfa_itnim_ioprofile_s {
+ u32 clock_res_mul;
+ u32 clock_res_div;
+ u32 index;
+ u32 io_profile_start_time; /* IO profile start time */
+ u32 iocomps[BFA_IOBUCKET_MAX]; /* IO completed */
+ struct bfa_itnim_latency_s io_latency;
+};
+
+/**
+ * FC physical port statistics.
+ */
+struct bfa_port_fc_stats_s {
+ u64 secs_reset; /* Seconds since stats is reset */
+ u64 tx_frames; /* Tx frames */
+ u64 tx_words; /* Tx words */
+ u64 tx_lip; /* Tx LIP */
+ u64 tx_nos; /* Tx NOS */
+ u64 tx_ols; /* Tx OLS */
+ u64 tx_lr; /* Tx LR */
+ u64 tx_lrr; /* Tx LRR */
+ u64 rx_frames; /* Rx frames */
+ u64 rx_words; /* Rx words */
+ u64 lip_count; /* Rx LIP */
+ u64 nos_count; /* Rx NOS */
+ u64 ols_count; /* Rx OLS */
+ u64 lr_count; /* Rx LR */
+ u64 lrr_count; /* Rx LRR */
+ u64 invalid_crcs; /* Rx CRC err frames */
+ u64 invalid_crc_gd_eof; /* Rx CRC err good EOF frames */
+ u64 undersized_frm; /* Rx undersized frames */
+ u64 oversized_frm; /* Rx oversized frames */
+ u64 bad_eof_frm; /* Rx frames with bad EOF */
+ u64 error_frames; /* Errored frames */
+ u64 dropped_frames; /* Dropped frames */
+ u64 link_failures; /* Link Failure (LF) count */
+ u64 loss_of_syncs; /* Loss of sync count */
+ u64 loss_of_signals; /* Loss of signal count */
+ u64 primseq_errs; /* Primitive sequence protocol err. */
+ u64 bad_os_count; /* Invalid ordered sets */
+ u64 err_enc_out; /* Encoding err nonframe_8b10b */
+ u64 err_enc; /* Encoding err frame_8b10b */
+};
+
+/**
+ * Eth Physical Port statistics.
+ */
+struct bfa_port_eth_stats_s {
+ u64 secs_reset; /* Seconds since stats is reset */
+ u64 frame_64; /* Frames 64 bytes */
+ u64 frame_65_127; /* Frames 65-127 bytes */
+ u64 frame_128_255; /* Frames 128-255 bytes */
+ u64 frame_256_511; /* Frames 256-511 bytes */
+ u64 frame_512_1023; /* Frames 512-1023 bytes */
+ u64 frame_1024_1518; /* Frames 1024-1518 bytes */
+ u64 frame_1519_1522; /* Frames 1519-1522 bytes */
+ u64 tx_bytes; /* Tx bytes */
+ u64 tx_packets; /* Tx packets */
+ u64 tx_mcast_packets; /* Tx multicast packets */
+ u64 tx_bcast_packets; /* Tx broadcast packets */
+ u64 tx_control_frame; /* Tx control frame */
+ u64 tx_drop; /* Tx drops */
+ u64 tx_jabber; /* Tx jabber */
+ u64 tx_fcs_error; /* Tx FCS errors */
+ u64 tx_fragments; /* Tx fragments */
+ u64 rx_bytes; /* Rx bytes */
+ u64 rx_packets; /* Rx packets */
+ u64 rx_mcast_packets; /* Rx multicast packets */
+ u64 rx_bcast_packets; /* Rx broadcast packets */
+ u64 rx_control_frames; /* Rx control frames */
+ u64 rx_unknown_opcode; /* Rx unknown opcode */
+ u64 rx_drop; /* Rx drops */
+ u64 rx_jabber; /* Rx jabber */
+ u64 rx_fcs_error; /* Rx FCS errors */
+ u64 rx_alignment_error; /* Rx alignment errors */
+ u64 rx_frame_length_error; /* Rx frame len errors */
+ u64 rx_code_error; /* Rx code errors */
+ u64 rx_fragments; /* Rx fragments */
+ u64 rx_pause; /* Rx pause */
+ u64 rx_zero_pause; /* Rx zero pause */
+ u64 tx_pause; /* Tx pause */
+ u64 tx_zero_pause; /* Tx zero pause */
+ u64 rx_fcoe_pause; /* Rx FCoE pause */
+ u64 rx_fcoe_zero_pause; /* Rx FCoE zero pause */
+ u64 tx_fcoe_pause; /* Tx FCoE pause */
+ u64 tx_fcoe_zero_pause; /* Tx FCoE zero pause */
+ u64 rx_iscsi_pause; /* Rx iSCSI pause */
+ u64 rx_iscsi_zero_pause; /* Rx iSCSI zero pause */
+ u64 tx_iscsi_pause; /* Tx iSCSI pause */
+ u64 tx_iscsi_zero_pause; /* Tx iSCSI zero pause */
+};
+
+/**
+ * Port statistics.
+ */
+union bfa_port_stats_u {
+ struct bfa_port_fc_stats_s fc;
+ struct bfa_port_eth_stats_s eth;
+};
+
+#endif /* __BFA_DEFS_SVC_H__ */
diff --git a/drivers/scsi/bfa/bfa_module.c b/drivers/scsi/bfa/bfa_drv.c
index a7fcc80c177e..14127646dc54 100644
--- a/drivers/scsi/bfa/bfa_module.c
+++ b/drivers/scsi/bfa/bfa_drv.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
* All rights reserved
* www.brocade.com
*
@@ -14,10 +14,8 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
-#include <bfa.h>
-#include <defs/bfa_defs_pci.h>
-#include <cs/bfa_debug.h>
-#include <bfa_iocfc.h>
+
+#include "bfa_modules.h"
/**
* BFA module list terminated by NULL
@@ -30,9 +28,6 @@ struct bfa_module_s *hal_mods[] = {
&hal_mod_uf,
&hal_mod_rport,
&hal_mod_fcpim,
-#ifdef BFA_CFG_PBIND
- &hal_mod_pbind,
-#endif
NULL
};
@@ -74,17 +69,39 @@ bfa_isr_func_t bfa_isrs[BFI_MC_MAX] = {
bfa_isr_unhandled, /* --------- */
};
+
/**
* Message handlers for mailbox command classes
*/
bfa_ioc_mbox_mcfunc_t bfa_mbox_isrs[BFI_MC_MAX] = {
NULL,
- NULL, /* BFI_MC_IOC */
- NULL, /* BFI_MC_DIAG */
+ NULL, /* BFI_MC_IOC */
+ NULL, /* BFI_MC_DIAG */
NULL, /* BFI_MC_FLASH */
- NULL, /* BFI_MC_CEE */
- NULL, /* BFI_MC_PORT */
+ NULL, /* BFI_MC_CEE */
+ NULL, /* BFI_MC_PORT */
bfa_iocfc_isr, /* BFI_MC_IOCFC */
NULL,
};
+
+
+void
+bfa_com_port_attach(struct bfa_s *bfa, struct bfa_meminfo_s *mi)
+{
+ struct bfa_port_s *port = &bfa->modules.port;
+ u32 dm_len;
+ u8 *dm_kva;
+ u64 dm_pa;
+
+ dm_len = bfa_port_meminfo();
+ dm_kva = bfa_meminfo_dma_virt(mi);
+ dm_pa = bfa_meminfo_dma_phys(mi);
+
+ memset(port, 0, sizeof(struct bfa_port_s));
+ bfa_port_attach(port, &bfa->ioc, bfa, bfa->trcmod);
+ bfa_port_mem_claim(port, dm_kva, dm_pa);
+
+ bfa_meminfo_dma_virt(mi) = dm_kva + dm_len;
+ bfa_meminfo_dma_phys(mi) = dm_pa + dm_len;
+}
diff --git a/drivers/scsi/bfa/include/protocol/fc.h b/drivers/scsi/bfa/bfa_fc.h
index 436dd7c5643a..6eff705564eb 100644
--- a/drivers/scsi/bfa/include/protocol/fc.h
+++ b/drivers/scsi/bfa/bfa_fc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
* All rights reserved
* www.brocade.com
*
@@ -15,13 +15,50 @@
* General Public License for more details.
*/
-#ifndef __FC_H__
-#define __FC_H__
+#ifndef __BFA_FC_H__
+#define __BFA_FC_H__
-#include <protocol/types.h>
+#include "bfa_os_inc.h"
+
+typedef u64 wwn_t;
+typedef u64 lun_t;
+
+#define WWN_NULL (0)
+#define FC_SYMNAME_MAX 256 /* max name server symbolic name size */
+#define FC_ALPA_MAX 128
#pragma pack(1)
+#define MAC_ADDRLEN (6)
+struct mac_s { u8 mac[MAC_ADDRLEN]; };
+#define mac_t struct mac_s
+
+/*
+ * generic SCSI cdb definition
+ */
+#define SCSI_MAX_CDBLEN 16
+struct scsi_cdb_s {
+ u8 scsi_cdb[SCSI_MAX_CDBLEN];
+};
+#define scsi_cdb_t struct scsi_cdb_s
+
+/* ------------------------------------------------------------
+ * SCSI status byte values
+ * ------------------------------------------------------------
+ */
+#define SCSI_STATUS_GOOD 0x00
+#define SCSI_STATUS_CHECK_CONDITION 0x02
+#define SCSI_STATUS_CONDITION_MET 0x04
+#define SCSI_STATUS_BUSY 0x08
+#define SCSI_STATUS_INTERMEDIATE 0x10
+#define SCSI_STATUS_ICM 0x14 /* intermediate condition met */
+#define SCSI_STATUS_RESERVATION_CONFLICT 0x18
+#define SCSI_STATUS_COMMAND_TERMINATED 0x22
+#define SCSI_STATUS_QUEUE_FULL 0x28
+#define SCSI_STATUS_ACA_ACTIVE 0x30
+
+#define SCSI_MAX_ALLOC_LEN 0xFF /* maximum allocarion length */
+
/*
* Fibre Channel Header Structure (FCHS) definition
*/
@@ -51,9 +88,9 @@ struct fchs_s {
u32 ro; /* relative offset */
};
-#define FC_SOF_LEN 4
-#define FC_EOF_LEN 4
-#define FC_CRC_LEN 4
+#define FC_SOF_LEN 4
+#define FC_EOF_LEN 4
+#define FC_CRC_LEN 4
/*
* Fibre Channel BB_E Header Structure
@@ -140,10 +177,12 @@ enum {
FC_TYPE_FC_FSS = 0x22, /* Fabric Switch Services */
FC_TYPE_FC_AL = 0x23, /* FC-AL */
FC_TYPE_FC_SNMP = 0x24, /* FC-SNMP */
+ FC_TYPE_FC_SPINFAB = 0xEE, /* SPINFAB */
+ FC_TYPE_FC_DIAG = 0xEF, /* DIAG */
FC_TYPE_MAX = 256, /* 256 FC-4 types */
};
-struct fc_fc4types_s{
+struct fc_fc4types_s {
u8 bits[FC_TYPE_MAX / 8];
};
@@ -168,7 +207,7 @@ enum {
*/
enum {
FC_MIN_WELL_KNOWN_ADDR = 0xFFFFF0,
- FC_DOMAIN_CONTROLLER_MASK = 0xFFFC00,
+ FC_DOMAIN_CONTROLLER_MASK = 0xFFFC00,
FC_ALIAS_SERVER = 0xFFFFF8,
FC_MGMT_SERVER = 0xFFFFFA,
FC_TIME_SERVER = 0xFFFFFB,
@@ -201,7 +240,7 @@ enum {
/*
* generic ELS command
*/
-struct fc_els_cmd_s{
+struct fc_els_cmd_s {
u32 els_code:8; /* ELS Command Code */
u32 reserved:24;
};
@@ -233,6 +272,8 @@ enum {
FC_ELS_PDISC = 0x50, /* Discover N_Port Parameters. */
FC_ELS_FDISC = 0x51, /* Discover F_Port Parameters. */
FC_ELS_ADISC = 0x52, /* Discover Address. */
+ FC_ELS_FARP_REQ = 0x54, /* FARP Request. */
+ FC_ELS_FARP_REP = 0x55, /* FARP Reply. */
FC_ELS_FAN = 0x60, /* Fabric Address Notification */
FC_ELS_RSCN = 0x61, /* Reg State Change Notification */
FC_ELS_SCR = 0x62, /* State Change Registration. */
@@ -272,7 +313,7 @@ enum {
* N_Port PLOGI Common Service Parameters.
* FC-PH-x. Figure-76. pg. 308.
*/
-struct fc_plogi_csp_s{
+struct fc_plogi_csp_s {
u8 verhi; /* FC-PH high version */
u8 verlo; /* FC-PH low version */
u16 bbcred; /* BB_Credit */
@@ -326,7 +367,7 @@ struct fc_plogi_csp_s{
* N_Port PLOGI Class Specific Parameters.
* FC-PH-x. Figure 78. pg. 318.
*/
-struct fc_plogi_clp_s{
+struct fc_plogi_clp_s {
#ifdef __BIGENDIAN
u32 class_valid:1;
u32 intermix:1; /* class intermix supported if set =1.
@@ -361,29 +402,29 @@ struct fc_plogi_clp_s{
u32 reserved8:16;
};
-#define FLOGI_VVL_BRCD 0x42524344 /* ASCII value for each character in
- * string "BRCD" */
+/* ASCII value for each character in string "BRCD" */
+#define FLOGI_VVL_BRCD 0x42524344
/*
* PLOGI els command and reply payload
*/
-struct fc_logi_s{
+struct fc_logi_s {
struct fc_els_cmd_s els_cmd; /* ELS command code */
- struct fc_plogi_csp_s csp; /* common service params */
+ struct fc_plogi_csp_s csp; /* common service params */
wwn_t port_name;
wwn_t node_name;
- struct fc_plogi_clp_s class1; /* class 1 service parameters */
- struct fc_plogi_clp_s class2; /* class 2 service parameters */
- struct fc_plogi_clp_s class3; /* class 3 service parameters */
- struct fc_plogi_clp_s class4; /* class 4 service parameters */
+ struct fc_plogi_clp_s class1; /* class 1 service parameters */
+ struct fc_plogi_clp_s class2; /* class 2 service parameters */
+ struct fc_plogi_clp_s class3; /* class 3 service parameters */
+ struct fc_plogi_clp_s class4; /* class 4 service parameters */
u8 vvl[16]; /* vendor version level */
};
/*
* LOGO els command payload
*/
-struct fc_logo_s{
- struct fc_els_cmd_s els_cmd; /* ELS command code */
+struct fc_logo_s {
+ struct fc_els_cmd_s els_cmd; /* ELS command code */
u32 res1:8;
u32 nport_id:24; /* N_Port identifier of source */
wwn_t orig_port_name; /* Port name of the LOGO originator */
@@ -393,7 +434,7 @@ struct fc_logo_s{
* ADISC els command payload
*/
struct fc_adisc_s {
- struct fc_els_cmd_s els_cmd; /* ELS command code */
+ struct fc_els_cmd_s els_cmd; /* ELS command code */
u32 res1:8;
u32 orig_HA:24; /* originator hard address */
wwn_t orig_port_name; /* originator port name */
@@ -405,7 +446,7 @@ struct fc_adisc_s {
/*
* Exchange status block
*/
-struct fc_exch_status_blk_s{
+struct fc_exch_status_blk_s {
u32 oxid:16;
u32 rxid:16;
u32 res1:8;
@@ -423,7 +464,7 @@ struct fc_exch_status_blk_s{
* RES els command payload
*/
struct fc_res_s {
- struct fc_els_cmd_s els_cmd; /* ELS command code */
+ struct fc_els_cmd_s els_cmd; /* ELS command code */
u32 res1:8;
u32 nport_id:24; /* N_Port identifier of source */
u32 oxid:16;
@@ -434,16 +475,16 @@ struct fc_res_s {
/*
* RES els accept payload
*/
-struct fc_res_acc_s{
- struct fc_els_cmd_s els_cmd; /* ELS command code */
- struct fc_exch_status_blk_s fc_exch_blk; /* Exchange status block */
+struct fc_res_acc_s {
+ struct fc_els_cmd_s els_cmd; /* ELS command code */
+ struct fc_exch_status_blk_s fc_exch_blk; /* Exchange status block */
};
/*
* REC els command payload
*/
struct fc_rec_s {
- struct fc_els_cmd_s els_cmd; /* ELS command code */
+ struct fc_els_cmd_s els_cmd; /* ELS command code */
u32 res1:8;
u32 nport_id:24; /* N_Port identifier of source */
u32 oxid:16;
@@ -451,9 +492,9 @@ struct fc_rec_s {
};
#define FC_REC_ESB_OWN_RSP 0x80000000 /* responder owns */
-#define FC_REC_ESB_SI 0x40000000 /* SI is owned */
+#define FC_REC_ESB_SI 0x40000000 /* SI is owned */
#define FC_REC_ESB_COMP 0x20000000 /* exchange is complete */
-#define FC_REC_ESB_ENDCOND_ABN 0x10000000 /* abnormal ending */
+#define FC_REC_ESB_ENDCOND_ABN 0x10000000 /* abnormal ending */
#define FC_REC_ESB_RQACT 0x04000000 /* recovery qual active */
#define FC_REC_ESB_ERRP_MSK 0x03000000
#define FC_REC_ESB_OXID_INV 0x00800000 /* invalid OXID */
@@ -464,7 +505,7 @@ struct fc_rec_s {
* REC els accept payload
*/
struct fc_rec_acc_s {
- struct fc_els_cmd_s els_cmd; /* ELS command code */
+ struct fc_els_cmd_s els_cmd; /* ELS command code */
u32 oxid:16;
u32 rxid:16;
u32 res1:8;
@@ -479,7 +520,7 @@ struct fc_rec_acc_s {
* RSI els payload
*/
struct fc_rsi_s {
- struct fc_els_cmd_s els_cmd;
+ struct fc_els_cmd_s els_cmd;
u32 res1:8;
u32 orig_sid:24;
u32 oxid:16;
@@ -490,7 +531,7 @@ struct fc_rsi_s {
* structure for PRLI paramater pages, both request & response
* see FC-PH-X table 113 & 115 for explanation also FCP table 8
*/
-struct fc_prli_params_s{
+struct fc_prli_params_s {
u32 reserved:16;
#ifdef __BIGENDIAN
u32 reserved1:5;
@@ -531,7 +572,7 @@ enum {
FC_PRLI_ACC_PREDEF_IMG = 0x5, /* predefined image - no prli needed */
};
-struct fc_prli_params_page_s{
+struct fc_prli_params_page_s {
u32 type:8;
u32 codext:8;
#ifdef __BIGENDIAN
@@ -551,13 +592,13 @@ struct fc_prli_params_page_s{
u32 origprocas;
u32 rspprocas;
- struct fc_prli_params_s servparams;
+ struct fc_prli_params_s servparams;
};
/*
* PRLI request and accept payload, FC-PH-X tables 112 & 114
*/
-struct fc_prli_s{
+struct fc_prli_s {
u32 command:8;
u32 pglen:8;
u32 pagebytes:16;
@@ -567,7 +608,7 @@ struct fc_prli_s{
/*
* PRLO logout params page
*/
-struct fc_prlo_params_page_s{
+struct fc_prlo_params_page_s {
u32 type:8;
u32 type_ext:8;
#ifdef __BIGENDIAN
@@ -592,17 +633,17 @@ struct fc_prlo_params_page_s{
/*
* PRLO els command payload
*/
-struct fc_prlo_s{
- u32 command:8;
- u32 page_len:8;
- u32 payload_len:16;
- struct fc_prlo_params_page_s prlo_params[1];
+struct fc_prlo_s {
+ u32 command:8;
+ u32 page_len:8;
+ u32 payload_len:16;
+ struct fc_prlo_params_page_s prlo_params[1];
};
/*
* PRLO Logout response parameter page
*/
-struct fc_prlo_acc_params_page_s{
+struct fc_prlo_acc_params_page_s {
u32 type:8;
u32 type_ext:8;
@@ -628,7 +669,7 @@ struct fc_prlo_acc_params_page_s{
/*
* PRLO els command ACC payload
*/
-struct fc_prlo_acc_s{
+struct fc_prlo_acc_s {
u32 command:8;
u32 page_len:8;
u32 payload_len:16;
@@ -650,7 +691,7 @@ enum {
FC_VU_SCR_REG_FUNC_FABRIC_NAME_CHANGE = 0x01
};
-struct fc_scr_s{
+struct fc_scr_s {
u32 command:8;
u32 res:24;
u32 vu_reg_func:8; /* Vendor Unique Registrations */
@@ -674,7 +715,7 @@ enum {
* LS_RJT els reply payload
*/
struct fc_ls_rjt_s {
- struct fc_els_cmd_s els_cmd; /* ELS command code */
+ struct fc_els_cmd_s els_cmd; /* ELS command code */
u32 res1:8;
u32 reason_code:8; /* Reason code for reject */
u32 reason_code_expl:8; /* Reason code explanation */
@@ -722,8 +763,8 @@ enum {
/*
* RRQ els command payload
*/
-struct fc_rrq_s{
- struct fc_els_cmd_s els_cmd; /* ELS command code */
+struct fc_rrq_s {
+ struct fc_els_cmd_s els_cmd; /* ELS command code */
u32 res1:8;
u32 s_id:24; /* exchange originator S_ID */
@@ -736,7 +777,7 @@ struct fc_rrq_s{
/*
* ABTS BA_ACC reply payload
*/
-struct fc_ba_acc_s{
+struct fc_ba_acc_s {
u32 seq_id_valid:8; /* set to 0x00 for Abort Exchange */
u32 seq_id:8; /* invalid for Abort Exchange */
u32 res2:16;
@@ -749,7 +790,7 @@ struct fc_ba_acc_s{
/*
* ABTS BA_RJT reject payload
*/
-struct fc_ba_rjt_s{
+struct fc_ba_rjt_s {
u32 res1:8; /* Reserved */
u32 reason_code:8; /* reason code for reject */
u32 reason_expl:8; /* reason code explanation */
@@ -759,9 +800,9 @@ struct fc_ba_rjt_s{
/*
* TPRLO logout parameter page
*/
-struct fc_tprlo_params_page_s{
- u32 type:8;
- u32 type_ext:8;
+struct fc_tprlo_params_page_s {
+u32 type:8;
+u32 type_ext:8;
#ifdef __BIGENDIAN
u32 opa_valid:1;
@@ -787,7 +828,7 @@ struct fc_tprlo_params_page_s{
/*
* TPRLO ELS command payload
*/
-struct fc_tprlo_s{
+struct fc_tprlo_s {
u32 command:8;
u32 page_len:8;
u32 payload_len:16;
@@ -795,7 +836,7 @@ struct fc_tprlo_s{
struct fc_tprlo_params_page_s tprlo_params[1];
};
-enum fc_tprlo_type{
+enum fc_tprlo_type {
FC_GLOBAL_LOGO = 1,
FC_TPR_LOGO
};
@@ -803,7 +844,7 @@ enum fc_tprlo_type{
/*
* TPRLO els command ACC payload
*/
-struct fc_tprlo_acc_s{
+struct fc_tprlo_acc_s {
u32 command:8;
u32 page_len:8;
u32 payload_len:16;
@@ -815,21 +856,21 @@ struct fc_tprlo_acc_s{
*/
#define FC_RSCN_PGLEN 0x4
-enum fc_rscn_format{
+enum fc_rscn_format {
FC_RSCN_FORMAT_PORTID = 0x0,
FC_RSCN_FORMAT_AREA = 0x1,
FC_RSCN_FORMAT_DOMAIN = 0x2,
FC_RSCN_FORMAT_FABRIC = 0x3,
};
-struct fc_rscn_event_s{
+struct fc_rscn_event_s {
u32 format:2;
u32 qualifier:4;
u32 resvd:2;
u32 portid:24;
};
-struct fc_rscn_pl_s{
+struct fc_rscn_pl_s {
u8 command;
u8 pagelen;
u16 payldlen;
@@ -840,18 +881,18 @@ struct fc_rscn_pl_s{
* ECHO els command req payload
*/
struct fc_echo_s {
- struct fc_els_cmd_s els_cmd;
+ struct fc_els_cmd_s els_cmd;
};
/*
* RNID els command
*/
-#define RNID_NODEID_DATA_FORMAT_COMMON 0x00
-#define RNID_NODEID_DATA_FORMAT_FCP3 0x08
-#define RNID_NODEID_DATA_FORMAT_DISCOVERY 0xDF
+#define RNID_NODEID_DATA_FORMAT_COMMON 0x00
+#define RNID_NODEID_DATA_FORMAT_FCP3 0x08
+#define RNID_NODEID_DATA_FORMAT_DISCOVERY 0xDF
-#define RNID_ASSOCIATED_TYPE_UNKNOWN 0x00000001
+#define RNID_ASSOCIATED_TYPE_UNKNOWN 0x00000001
#define RNID_ASSOCIATED_TYPE_OTHER 0x00000002
#define RNID_ASSOCIATED_TYPE_HUB 0x00000003
#define RNID_ASSOCIATED_TYPE_SWITCH 0x00000004
@@ -868,8 +909,8 @@ struct fc_echo_s {
/*
* RNID els command payload
*/
-struct fc_rnid_cmd_s{
- struct fc_els_cmd_s els_cmd;
+struct fc_rnid_cmd_s {
+ struct fc_els_cmd_s els_cmd;
u32 node_id_data_format:8;
u32 reserved:24;
};
@@ -878,12 +919,12 @@ struct fc_rnid_cmd_s{
* RNID els response payload
*/
-struct fc_rnid_common_id_data_s{
+struct fc_rnid_common_id_data_s {
wwn_t port_name;
wwn_t node_name;
};
-struct fc_rnid_general_topology_data_s{
+struct fc_rnid_general_topology_data_s {
u32 vendor_unique[4];
u32 asso_type;
u32 phy_port_num;
@@ -896,8 +937,8 @@ struct fc_rnid_general_topology_data_s{
u32 vendor_specific:16;
};
-struct fc_rnid_acc_s{
- struct fc_els_cmd_s els_cmd;
+struct fc_rnid_acc_s {
+ struct fc_els_cmd_s els_cmd;
u32 node_id_data_format:8;
u32 common_id_data_length:8;
u32 reserved:8;
@@ -920,7 +961,7 @@ struct fc_rnid_acc_s{
#define RNID_ASSOCIATED_TYPE_VIRTUALIZATION_DEVICE 0x00000003
#define RNID_ASSOCIATED_TYPE_MULTI_FUNCTION_DEVICE 0x000000FF
-enum fc_rpsc_speed_cap{
+enum fc_rpsc_speed_cap {
RPSC_SPEED_CAP_1G = 0x8000,
RPSC_SPEED_CAP_2G = 0x4000,
RPSC_SPEED_CAP_4G = 0x2000,
@@ -931,7 +972,7 @@ enum fc_rpsc_speed_cap{
RPSC_SPEED_CAP_UNKNOWN = 0x0001,
};
-enum fc_rpsc_op_speed_s{
+enum fc_rpsc_op_speed {
RPSC_OP_SPEED_1G = 0x8000,
RPSC_OP_SPEED_2G = 0x4000,
RPSC_OP_SPEED_4G = 0x2000,
@@ -942,24 +983,24 @@ enum fc_rpsc_op_speed_s{
RPSC_OP_SPEED_NOT_EST = 0x0001, /*! speed not established */
};
-struct fc_rpsc_speed_info_s{
- u16 port_speed_cap; /*! see fc_rpsc_speed_cap_t */
- u16 port_op_speed; /*! see fc_rpsc_op_speed_t */
+struct fc_rpsc_speed_info_s {
+ u16 port_speed_cap; /*! see enum fc_rpsc_speed_cap */
+ u16 port_op_speed; /*! see enum fc_rpsc_op_speed */
};
-enum link_e2e_beacon_subcmd{
+enum link_e2e_beacon_subcmd {
LINK_E2E_BEACON_ON = 1,
LINK_E2E_BEACON_OFF = 2
};
-enum beacon_type{
+enum beacon_type {
BEACON_TYPE_NORMAL = 1, /*! Normal Beaconing. Green */
BEACON_TYPE_WARN = 2, /*! Warning Beaconing. Yellow/Amber */
BEACON_TYPE_CRITICAL = 3 /*! Critical Beaconing. Red */
};
struct link_e2e_beacon_param_s {
- u8 beacon_type; /* Beacon Type. See beacon_type_t */
+ u8 beacon_type; /* Beacon Type. See enum beacon_type */
u8 beacon_frequency;
/* Beacon frequency. Number of blinks
* per 10 seconds
@@ -978,12 +1019,13 @@ struct link_e2e_beacon_param_s {
};
/*
- * Link E2E beacon request/good response format. For LS_RJTs use fc_ls_rjt_t
+ * Link E2E beacon request/good response format.
+ * For LS_RJTs use struct fc_ls_rjt_s
*/
-struct link_e2e_beacon_req_s{
+struct link_e2e_beacon_req_s {
u32 ls_code; /*! FC_ELS_E2E_LBEACON in requests *
*or FC_ELS_ACC in good replies */
- u32 ls_sub_cmd; /*! See link_e2e_beacon_subcmd_t */
+ u32 ls_sub_cmd; /*! See enum link_e2e_beacon_subcmd */
struct link_e2e_beacon_param_s beacon_parm;
};
@@ -992,14 +1034,14 @@ struct link_e2e_beacon_req_s{
* all the ports within that domain (TODO - I don't think FOS implements
* this...).
*/
-struct fc_rpsc_cmd_s{
- struct fc_els_cmd_s els_cmd;
+struct fc_rpsc_cmd_s {
+ struct fc_els_cmd_s els_cmd;
};
/*
* RPSC Acc
*/
-struct fc_rpsc_acc_s{
+struct fc_rpsc_acc_s {
u32 command:8;
u32 rsvd:8;
u32 num_entries:16;
@@ -1012,51 +1054,50 @@ struct fc_rpsc_acc_s{
*/
#define FC_BRCD_TOKEN 0x42524344
-struct fc_rpsc2_cmd_s{
- struct fc_els_cmd_s els_cmd;
- u32 token;
- u16 resvd;
- u16 num_pids; /* Number of pids in the request */
+struct fc_rpsc2_cmd_s {
+ struct fc_els_cmd_s els_cmd;
+ u32 token;
+ u16 resvd;
+ u16 num_pids; /* Number of pids in the request */
struct {
u32 rsvd1:8;
- u32 pid:24; /* port identifier */
+ u32 pid:24; /* port identifier */
} pid_list[1];
};
-enum fc_rpsc2_port_type{
+enum fc_rpsc2_port_type {
RPSC2_PORT_TYPE_UNKNOWN = 0,
RPSC2_PORT_TYPE_NPORT = 1,
RPSC2_PORT_TYPE_NLPORT = 2,
RPSC2_PORT_TYPE_NPIV_PORT = 0x5f,
RPSC2_PORT_TYPE_NPORT_TRUNK = 0x6f,
};
-
/*
* RPSC2 portInfo entry structure
*/
-struct fc_rpsc2_port_info_s{
+struct fc_rpsc2_port_info_s {
u32 pid; /* PID */
u16 resvd1;
u16 index; /* port number / index */
u8 resvd2;
- u8 type; /* port type N/NL/... */
+ u8 type; /* port type N/NL/... */
u16 speed; /* port Operating Speed */
};
/*
* RPSC2 Accept payload
*/
-struct fc_rpsc2_acc_s{
+struct fc_rpsc2_acc_s {
u8 els_cmd;
u8 resvd;
- u16 num_pids; /* Number of pids in the request */
- struct fc_rpsc2_port_info_s port_info[1]; /* port information */
+ u16 num_pids; /* Number of pids in the request */
+ struct fc_rpsc2_port_info_s port_info[1]; /* port information */
};
/**
* bit fields so that multiple classes can be specified
*/
-enum fc_cos{
+enum fc_cos {
FC_CLASS_2 = 0x04,
FC_CLASS_3 = 0x08,
FC_CLASS_2_3 = 0x0C,
@@ -1065,11 +1106,11 @@ enum fc_cos{
/*
* symbolic name
*/
-struct fc_symname_s{
+struct fc_symname_s {
u8 symname[FC_SYMNAME_MAX];
};
-struct fc_alpabm_s{
+struct fc_alpabm_s {
u8 alpa_bm[FC_ALPA_MAX / 8];
};
@@ -1094,7 +1135,7 @@ struct fc_alpabm_s{
* Virtual Fabric Tagging header format
* @caution This is defined only in BIG ENDIAN format.
*/
-struct fc_vft_s{
+struct fc_vft_s {
u32 r_ctl:8;
u32 ver:2;
u32 type:4;
@@ -1106,6 +1147,770 @@ struct fc_vft_s{
u32 res_c:24;
};
-#pragma pack()
+/*
+ * FCP
+ */
+enum {
+ FCP_RJT = 0x01000000, /* SRR reject */
+ FCP_SRR_ACCEPT = 0x02000000, /* SRR accept */
+ FCP_SRR = 0x14000000, /* Sequence Retransmission Request */
+};
+
+/*
+ * SRR FC-4 LS payload
+ */
+struct fc_srr_s {
+ u32 ls_cmd;
+ u32 ox_id:16; /* ox-id */
+ u32 rx_id:16; /* rx-id */
+ u32 ro; /* relative offset */
+ u32 r_ctl:8; /* R_CTL for I.U. */
+ u32 res:24;
+};
+
+
+/*
+ * FCP_CMND definitions
+ */
+#define FCP_CMND_CDB_LEN 16
+#define FCP_CMND_LUN_LEN 8
+
+struct fcp_cmnd_s {
+ lun_t lun; /* 64-bit LU number */
+ u8 crn; /* command reference number */
+#ifdef __BIGENDIAN
+ u8 resvd:1,
+ priority:4, /* FCP-3: SAM-3 priority */
+ taskattr:3; /* scsi task attribute */
+#else
+ u8 taskattr:3, /* scsi task attribute */
+ priority:4, /* FCP-3: SAM-3 priority */
+ resvd:1;
+#endif
+ u8 tm_flags; /* task management flags */
+#ifdef __BIGENDIAN
+ u8 addl_cdb_len:6, /* additional CDB length words */
+ iodir:2; /* read/write FCP_DATA IUs */
+#else
+ u8 iodir:2, /* read/write FCP_DATA IUs */
+ addl_cdb_len:6; /* additional CDB length */
+#endif
+ scsi_cdb_t cdb;
+
+ /*
+ * !!! additional cdb bytes follows here!!!
+ */
+ u32 fcp_dl; /* bytes to be transferred */
+};
+
+#define fcp_cmnd_cdb_len(_cmnd) ((_cmnd)->addl_cdb_len * 4 + FCP_CMND_CDB_LEN)
+#define fcp_cmnd_fcpdl(_cmnd) ((&(_cmnd)->fcp_dl)[(_cmnd)->addl_cdb_len])
+/*
+ * struct fcp_cmnd_s .iodir field values
+ */
+enum fcp_iodir {
+ FCP_IODIR_NONE = 0,
+ FCP_IODIR_WRITE = 1,
+ FCP_IODIR_READ = 2,
+ FCP_IODIR_RW = 3,
+};
+
+/*
+ * Task attribute field
+ */
+enum {
+ FCP_TASK_ATTR_SIMPLE = 0,
+ FCP_TASK_ATTR_HOQ = 1,
+ FCP_TASK_ATTR_ORDERED = 2,
+ FCP_TASK_ATTR_ACA = 4,
+ FCP_TASK_ATTR_UNTAGGED = 5, /* obsolete in FCP-3 */
+};
+
+/*
+ * Task management flags field - only one bit shall be set
+ */
+enum fcp_tm_cmnd {
+ FCP_TM_ABORT_TASK_SET = BIT(1),
+ FCP_TM_CLEAR_TASK_SET = BIT(2),
+ FCP_TM_LUN_RESET = BIT(4),
+ FCP_TM_TARGET_RESET = BIT(5), /* obsolete in FCP-3 */
+ FCP_TM_CLEAR_ACA = BIT(6),
+};
+
+/*
+ * FCP_XFER_RDY IU defines
+ */
+struct fcp_xfer_rdy_s {
+ u32 data_ro;
+ u32 burst_len;
+ u32 reserved;
+};
+
+/*
+ * FCP_RSP residue flags
+ */
+enum fcp_residue {
+ FCP_NO_RESIDUE = 0, /* no residue */
+ FCP_RESID_OVER = 1, /* more data left that was not sent */
+ FCP_RESID_UNDER = 2, /* less data than requested */
+};
+
+enum {
+ FCP_RSPINFO_GOOD = 0,
+ FCP_RSPINFO_DATALEN_MISMATCH = 1,
+ FCP_RSPINFO_CMND_INVALID = 2,
+ FCP_RSPINFO_ROLEN_MISMATCH = 3,
+ FCP_RSPINFO_TM_NOT_SUPP = 4,
+ FCP_RSPINFO_TM_FAILED = 5,
+};
+
+struct fcp_rspinfo_s {
+ u32 res0:24;
+ u32 rsp_code:8; /* response code (as above) */
+ u32 res1;
+};
+
+struct fcp_resp_s {
+ u32 reserved[2]; /* 2 words reserved */
+ u16 reserved2;
+#ifdef __BIGENDIAN
+ u8 reserved3:3;
+ u8 fcp_conf_req:1; /* FCP_CONF is requested */
+ u8 resid_flags:2; /* underflow/overflow */
+ u8 sns_len_valid:1;/* sense len is valid */
+ u8 rsp_len_valid:1;/* response len is valid */
+#else
+ u8 rsp_len_valid:1;/* response len is valid */
+ u8 sns_len_valid:1;/* sense len is valid */
+ u8 resid_flags:2; /* underflow/overflow */
+ u8 fcp_conf_req:1; /* FCP_CONF is requested */
+ u8 reserved3:3;
#endif
+ u8 scsi_status; /* one byte SCSI status */
+ u32 residue; /* residual data bytes */
+ u32 sns_len; /* length od sense info */
+ u32 rsp_len; /* length of response info */
+};
+
+#define fcp_snslen(__fcprsp) ((__fcprsp)->sns_len_valid ? \
+ (__fcprsp)->sns_len : 0)
+#define fcp_rsplen(__fcprsp) ((__fcprsp)->rsp_len_valid ? \
+ (__fcprsp)->rsp_len : 0)
+#define fcp_rspinfo(__fcprsp) ((struct fcp_rspinfo_s *)((__fcprsp) + 1))
+#define fcp_snsinfo(__fcprsp) (((u8 *)fcp_rspinfo(__fcprsp)) + \
+ fcp_rsplen(__fcprsp))
+
+struct fcp_cmnd_fr_s {
+ struct fchs_s fchs;
+ struct fcp_cmnd_s fcp;
+};
+
+/*
+ * CT
+ */
+struct ct_hdr_s {
+ u32 rev_id:8; /* Revision of the CT */
+ u32 in_id:24; /* Initiator Id */
+ u32 gs_type:8; /* Generic service Type */
+ u32 gs_sub_type:8; /* Generic service sub type */
+ u32 options:8; /* options */
+ u32 rsvrd:8; /* reserved */
+ u32 cmd_rsp_code:16;/* ct command/response code */
+ u32 max_res_size:16;/* maximum/residual size */
+ u32 frag_id:8; /* fragment ID */
+ u32 reason_code:8; /* reason code */
+ u32 exp_code:8; /* explanation code */
+ u32 vendor_unq:8; /* vendor unique */
+};
+
+/*
+ * defines for the Revision
+ */
+enum {
+ CT_GS3_REVISION = 0x01,
+};
+
+/*
+ * defines for gs_type
+ */
+enum {
+ CT_GSTYPE_KEYSERVICE = 0xF7,
+ CT_GSTYPE_ALIASSERVICE = 0xF8,
+ CT_GSTYPE_MGMTSERVICE = 0xFA,
+ CT_GSTYPE_TIMESERVICE = 0xFB,
+ CT_GSTYPE_DIRSERVICE = 0xFC,
+};
+
+/*
+ * defines for gs_sub_type for gs type directory service
+ */
+enum {
+ CT_GSSUBTYPE_NAMESERVER = 0x02,
+};
+
+/*
+ * defines for gs_sub_type for gs type management service
+ */
+enum {
+ CT_GSSUBTYPE_CFGSERVER = 0x01,
+ CT_GSSUBTYPE_UNZONED_NS = 0x02,
+ CT_GSSUBTYPE_ZONESERVER = 0x03,
+ CT_GSSUBTYPE_LOCKSERVER = 0x04,
+ CT_GSSUBTYPE_HBA_MGMTSERVER = 0x10, /* for FDMI */
+};
+
+/*
+ * defines for CT response code field
+ */
+enum {
+ CT_RSP_REJECT = 0x8001,
+ CT_RSP_ACCEPT = 0x8002,
+};
+
+/*
+ * defintions for CT reason code
+ */
+enum {
+ CT_RSN_INV_CMD = 0x01,
+ CT_RSN_INV_VER = 0x02,
+ CT_RSN_LOGIC_ERR = 0x03,
+ CT_RSN_INV_SIZE = 0x04,
+ CT_RSN_LOGICAL_BUSY = 0x05,
+ CT_RSN_PROTO_ERR = 0x07,
+ CT_RSN_UNABLE_TO_PERF = 0x09,
+ CT_RSN_NOT_SUPP = 0x0B,
+ CT_RSN_SERVER_NOT_AVBL = 0x0D,
+ CT_RSN_SESSION_COULD_NOT_BE_ESTBD = 0x0E,
+ CT_RSN_VENDOR_SPECIFIC = 0xFF,
+
+};
+
+/*
+ * definitions for explanations code for Name server
+ */
+enum {
+ CT_NS_EXP_NOADDITIONAL = 0x00,
+ CT_NS_EXP_ID_NOT_REG = 0x01,
+ CT_NS_EXP_PN_NOT_REG = 0x02,
+ CT_NS_EXP_NN_NOT_REG = 0x03,
+ CT_NS_EXP_CS_NOT_REG = 0x04,
+ CT_NS_EXP_IPN_NOT_REG = 0x05,
+ CT_NS_EXP_IPA_NOT_REG = 0x06,
+ CT_NS_EXP_FT_NOT_REG = 0x07,
+ CT_NS_EXP_SPN_NOT_REG = 0x08,
+ CT_NS_EXP_SNN_NOT_REG = 0x09,
+ CT_NS_EXP_PT_NOT_REG = 0x0A,
+ CT_NS_EXP_IPP_NOT_REG = 0x0B,
+ CT_NS_EXP_FPN_NOT_REG = 0x0C,
+ CT_NS_EXP_HA_NOT_REG = 0x0D,
+ CT_NS_EXP_FD_NOT_REG = 0x0E,
+ CT_NS_EXP_FF_NOT_REG = 0x0F,
+ CT_NS_EXP_ACCESSDENIED = 0x10,
+ CT_NS_EXP_UNACCEPTABLE_ID = 0x11,
+ CT_NS_EXP_DATABASEEMPTY = 0x12,
+ CT_NS_EXP_NOT_REG_IN_SCOPE = 0x13,
+ CT_NS_EXP_DOM_ID_NOT_PRESENT = 0x14,
+ CT_NS_EXP_PORT_NUM_NOT_PRESENT = 0x15,
+ CT_NS_EXP_NO_DEVICE_ATTACHED = 0x16
+};
+
+/*
+ * defintions for the explanation code for all servers
+ */
+enum {
+ CT_EXP_AUTH_EXCEPTION = 0xF1,
+ CT_EXP_DB_FULL = 0xF2,
+ CT_EXP_DB_EMPTY = 0xF3,
+ CT_EXP_PROCESSING_REQ = 0xF4,
+ CT_EXP_UNABLE_TO_VERIFY_CONN = 0xF5,
+ CT_EXP_DEVICES_NOT_IN_CMN_ZONE = 0xF6
+};
+
+/*
+ * Command codes for Name server
+ */
+enum {
+ GS_GID_PN = 0x0121, /* Get Id on port name */
+ GS_GPN_ID = 0x0112, /* Get port name on ID */
+ GS_GNN_ID = 0x0113, /* Get node name on ID */
+ GS_GID_FT = 0x0171, /* Get Id on FC4 type */
+ GS_GSPN_ID = 0x0118, /* Get symbolic PN on ID */
+ GS_RFT_ID = 0x0217, /* Register fc4type on ID */
+ GS_RSPN_ID = 0x0218, /* Register symbolic PN on ID */
+ GS_RPN_ID = 0x0212, /* Register port name */
+ GS_RNN_ID = 0x0213, /* Register node name */
+ GS_RCS_ID = 0x0214, /* Register class of service */
+ GS_RPT_ID = 0x021A, /* Register port type */
+ GS_GA_NXT = 0x0100, /* Get all next */
+ GS_RFF_ID = 0x021F, /* Register FC4 Feature */
+};
+
+struct fcgs_id_req_s{
+ u32 rsvd:8;
+ u32 dap:24; /* port identifier */
+};
+#define fcgs_gpnid_req_t struct fcgs_id_req_s
+#define fcgs_gnnid_req_t struct fcgs_id_req_s
+#define fcgs_gspnid_req_t struct fcgs_id_req_s
+
+struct fcgs_gidpn_req_s {
+ wwn_t port_name; /* port wwn */
+};
+
+struct fcgs_gidpn_resp_s {
+ u32 rsvd:8;
+ u32 dap:24; /* port identifier */
+};
+
+/**
+ * RFT_ID
+ */
+struct fcgs_rftid_req_s {
+ u32 rsvd:8;
+ u32 dap:24; /* port identifier */
+ u32 fc4_type[8]; /* fc4 types */
+};
+
+/**
+ * RFF_ID : Register FC4 features.
+ */
+
+#define FC_GS_FCP_FC4_FEATURE_INITIATOR 0x02
+#define FC_GS_FCP_FC4_FEATURE_TARGET 0x01
+
+struct fcgs_rffid_req_s {
+ u32 rsvd:8;
+ u32 dap:24; /* port identifier */
+ u32 rsvd1:16;
+ u32 fc4ftr_bits:8; /* fc4 feature bits */
+ u32 fc4_type:8; /* corresponding FC4 Type */
+};
+
+/**
+ * GID_FT Request
+ */
+struct fcgs_gidft_req_s {
+ u8 reserved;
+ u8 domain_id; /* domain, 0 - all fabric */
+ u8 area_id; /* area, 0 - whole domain */
+ u8 fc4_type; /* FC_TYPE_FCP for SCSI devices */
+}; /* GID_FT Request */
+
+/**
+ * GID_FT Response
+ */
+struct fcgs_gidft_resp_s {
+ u8 last:1; /* last port identifier flag */
+ u8 reserved:7;
+ u32 pid:24; /* port identifier */
+}; /* GID_FT Response */
+
+/**
+ * RSPN_ID
+ */
+struct fcgs_rspnid_req_s {
+ u32 rsvd:8;
+ u32 dap:24; /* port identifier */
+ u8 spn_len; /* symbolic port name length */
+ u8 spn[256]; /* symbolic port name */
+};
+
+/**
+ * RPN_ID
+ */
+struct fcgs_rpnid_req_s {
+ u32 rsvd:8;
+ u32 port_id:24;
+ wwn_t port_name;
+};
+
+/**
+ * RNN_ID
+ */
+struct fcgs_rnnid_req_s {
+ u32 rsvd:8;
+ u32 port_id:24;
+ wwn_t node_name;
+};
+
+/**
+ * RCS_ID
+ */
+struct fcgs_rcsid_req_s {
+ u32 rsvd:8;
+ u32 port_id:24;
+ u32 cos;
+};
+
+/**
+ * RPT_ID
+ */
+struct fcgs_rptid_req_s {
+ u32 rsvd:8;
+ u32 port_id:24;
+ u32 port_type:8;
+ u32 rsvd1:24;
+};
+
+/**
+ * GA_NXT Request
+ */
+struct fcgs_ganxt_req_s {
+ u32 rsvd:8;
+ u32 port_id:24;
+};
+
+/**
+ * GA_NXT Response
+ */
+struct fcgs_ganxt_rsp_s {
+ u32 port_type:8; /* Port Type */
+ u32 port_id:24; /* Port Identifier */
+ wwn_t port_name; /* Port Name */
+ u8 spn_len; /* Length of Symbolic Port Name */
+ char spn[255]; /* Symbolic Port Name */
+ wwn_t node_name; /* Node Name */
+ u8 snn_len; /* Length of Symbolic Node Name */
+ char snn[255]; /* Symbolic Node Name */
+ u8 ipa[8]; /* Initial Process Associator */
+ u8 ip[16]; /* IP Address */
+ u32 cos; /* Class of Service */
+ u32 fc4types[8]; /* FC-4 TYPEs */
+ wwn_t fabric_port_name;
+ /* Fabric Port Name */
+ u32 rsvd:8; /* Reserved */
+ u32 hard_addr:24; /* Hard Address */
+};
+
+/*
+ * Fabric Config Server
+ */
+
+/*
+ * Command codes for Fabric Configuration Server
+ */
+enum {
+ GS_FC_GFN_CMD = 0x0114, /* GS FC Get Fabric Name */
+ GS_FC_GMAL_CMD = 0x0116, /* GS FC GMAL */
+ GS_FC_TRACE_CMD = 0x0400, /* GS FC Trace Route */
+ GS_FC_PING_CMD = 0x0401, /* GS FC Ping */
+};
+
+/*
+ * Source or Destination Port Tags.
+ */
+enum {
+ GS_FTRACE_TAG_NPORT_ID = 1,
+ GS_FTRACE_TAG_NPORT_NAME = 2,
+};
+
+/*
+* Port Value : Could be a Port id or wwn
+ */
+union fcgs_port_val_u {
+ u32 nport_id;
+ wwn_t nport_wwn;
+};
+
+#define GS_FTRACE_MAX_HOP_COUNT 20
+#define GS_FTRACE_REVISION 1
+
+/*
+ * Ftrace Related Structures.
+ */
+
+/*
+ * STR (Switch Trace) Reject Reason Codes. From FC-SW.
+ */
+enum {
+ GS_FTRACE_STR_CMD_COMPLETED_SUCC = 0,
+ GS_FTRACE_STR_CMD_NOT_SUPP_IN_NEXT_SWITCH,
+ GS_FTRACE_STR_NO_RESP_FROM_NEXT_SWITCH,
+ GS_FTRACE_STR_MAX_HOP_CNT_REACHED,
+ GS_FTRACE_STR_SRC_PORT_NOT_FOUND,
+ GS_FTRACE_STR_DST_PORT_NOT_FOUND,
+ GS_FTRACE_STR_DEVICES_NOT_IN_COMMON_ZONE,
+ GS_FTRACE_STR_NO_ROUTE_BW_PORTS,
+ GS_FTRACE_STR_NO_ADDL_EXPLN,
+ GS_FTRACE_STR_FABRIC_BUSY,
+ GS_FTRACE_STR_FABRIC_BUILD_IN_PROGRESS,
+ GS_FTRACE_STR_VENDOR_SPECIFIC_ERR_START = 0xf0,
+ GS_FTRACE_STR_VENDOR_SPECIFIC_ERR_END = 0xff,
+};
+
+/*
+ * Ftrace Request
+ */
+struct fcgs_ftrace_req_s {
+ u32 revision;
+ u16 src_port_tag; /* Source Port tag */
+ u16 src_port_len; /* Source Port len */
+ union fcgs_port_val_u src_port_val; /* Source Port value */
+ u16 dst_port_tag; /* Destination Port tag */
+ u16 dst_port_len; /* Destination Port len */
+ union fcgs_port_val_u dst_port_val; /* Destination Port value */
+ u32 token;
+ u8 vendor_id[8]; /* T10 Vendor Identifier */
+ u8 vendor_info[8]; /* Vendor specific Info */
+ u32 max_hop_cnt; /* Max Hop Count */
+};
+
+/*
+ * Path info structure
+ */
+struct fcgs_ftrace_path_info_s {
+ wwn_t switch_name; /* Switch WWN */
+ u32 domain_id;
+ wwn_t ingress_port_name; /* Ingress ports wwn */
+ u32 ingress_phys_port_num; /* Ingress ports physical port
+ * number
+ */
+ wwn_t egress_port_name; /* Ingress ports wwn */
+ u32 egress_phys_port_num; /* Ingress ports physical port
+ * number
+ */
+};
+
+/*
+ * Ftrace Acc Response
+ */
+struct fcgs_ftrace_resp_s {
+ u32 revision;
+ u32 token;
+ u8 vendor_id[8]; /* T10 Vendor Identifier */
+ u8 vendor_info[8]; /* Vendor specific Info */
+ u32 str_rej_reason_code; /* STR Reject Reason Code */
+ u32 num_path_info_entries; /* No. of path info entries */
+ /*
+ * path info entry/entries.
+ */
+ struct fcgs_ftrace_path_info_s path_info[1];
+
+};
+
+/*
+* Fabric Config Server : FCPing
+ */
+
+/*
+ * FC Ping Request
+ */
+struct fcgs_fcping_req_s {
+ u32 revision;
+ u16 port_tag;
+ u16 port_len; /* Port len */
+ union fcgs_port_val_u port_val; /* Port value */
+ u32 token;
+};
+
+/*
+ * FC Ping Response
+ */
+struct fcgs_fcping_resp_s {
+ u32 token;
+};
+
+/*
+ * Command codes for zone server query.
+ */
+enum {
+ ZS_GZME = 0x0124, /* Get zone member extended */
+};
+
+/*
+ * ZS GZME request
+ */
+#define ZS_GZME_ZNAMELEN 32
+struct zs_gzme_req_s {
+ u8 znamelen;
+ u8 rsvd[3];
+ u8 zname[ZS_GZME_ZNAMELEN];
+};
+
+enum zs_mbr_type {
+ ZS_MBR_TYPE_PWWN = 1,
+ ZS_MBR_TYPE_DOMPORT = 2,
+ ZS_MBR_TYPE_PORTID = 3,
+ ZS_MBR_TYPE_NWWN = 4,
+};
+
+struct zs_mbr_wwn_s {
+ u8 mbr_type;
+ u8 rsvd[3];
+ wwn_t wwn;
+};
+
+struct zs_query_resp_s {
+ u32 nmbrs; /* number of zone members */
+ struct zs_mbr_wwn_s mbr[1];
+};
+
+/*
+ * GMAL Command ( Get ( interconnect Element) Management Address List)
+ * To retrieve the IP Address of a Switch.
+ */
+
+#define CT_GMAL_RESP_PREFIX_TELNET "telnet://"
+#define CT_GMAL_RESP_PREFIX_HTTP "http://"
+
+/* GMAL/GFN request */
+struct fcgs_req_s {
+ wwn_t wwn; /* PWWN/NWWN */
+};
+
+#define fcgs_gmal_req_t struct fcgs_req_s
+#define fcgs_gfn_req_t struct fcgs_req_s
+
+/* Accept Response to GMAL */
+struct fcgs_gmal_resp_s {
+ u32 ms_len; /* Num of entries */
+ u8 ms_ma[256];
+};
+
+struct fcgs_gmal_entry_s {
+ u8 len;
+ u8 prefix[7]; /* like "http://" */
+ u8 ip_addr[248];
+};
+
+/*
+ * FDMI
+ */
+/*
+ * FDMI Command Codes
+ */
+#define FDMI_GRHL 0x0100
+#define FDMI_GHAT 0x0101
+#define FDMI_GRPL 0x0102
+#define FDMI_GPAT 0x0110
+#define FDMI_RHBA 0x0200
+#define FDMI_RHAT 0x0201
+#define FDMI_RPRT 0x0210
+#define FDMI_RPA 0x0211
+#define FDMI_DHBA 0x0300
+#define FDMI_DPRT 0x0310
+
+/*
+ * FDMI reason codes
+ */
+#define FDMI_NO_ADDITIONAL_EXP 0x00
+#define FDMI_HBA_ALREADY_REG 0x10
+#define FDMI_HBA_ATTRIB_NOT_REG 0x11
+#define FDMI_HBA_ATTRIB_MULTIPLE 0x12
+#define FDMI_HBA_ATTRIB_LENGTH_INVALID 0x13
+#define FDMI_HBA_ATTRIB_NOT_PRESENT 0x14
+#define FDMI_PORT_ORIG_NOT_IN_LIST 0x15
+#define FDMI_PORT_HBA_NOT_IN_LIST 0x16
+#define FDMI_PORT_ATTRIB_NOT_REG 0x20
+#define FDMI_PORT_NOT_REG 0x21
+#define FDMI_PORT_ATTRIB_MULTIPLE 0x22
+#define FDMI_PORT_ATTRIB_LENGTH_INVALID 0x23
+#define FDMI_PORT_ALREADY_REGISTEREED 0x24
+
+/*
+ * FDMI Transmission Speed Mask values
+ */
+#define FDMI_TRANS_SPEED_1G 0x00000001
+#define FDMI_TRANS_SPEED_2G 0x00000002
+#define FDMI_TRANS_SPEED_10G 0x00000004
+#define FDMI_TRANS_SPEED_4G 0x00000008
+#define FDMI_TRANS_SPEED_8G 0x00000010
+#define FDMI_TRANS_SPEED_16G 0x00000020
+#define FDMI_TRANS_SPEED_UNKNOWN 0x00008000
+
+/*
+ * FDMI HBA attribute types
+ */
+enum fdmi_hba_attribute_type {
+ FDMI_HBA_ATTRIB_NODENAME = 1, /* 0x0001 */
+ FDMI_HBA_ATTRIB_MANUFACTURER, /* 0x0002 */
+ FDMI_HBA_ATTRIB_SERIALNUM, /* 0x0003 */
+ FDMI_HBA_ATTRIB_MODEL, /* 0x0004 */
+ FDMI_HBA_ATTRIB_MODEL_DESC, /* 0x0005 */
+ FDMI_HBA_ATTRIB_HW_VERSION, /* 0x0006 */
+ FDMI_HBA_ATTRIB_DRIVER_VERSION, /* 0x0007 */
+ FDMI_HBA_ATTRIB_ROM_VERSION, /* 0x0008 */
+ FDMI_HBA_ATTRIB_FW_VERSION, /* 0x0009 */
+ FDMI_HBA_ATTRIB_OS_NAME, /* 0x000A */
+ FDMI_HBA_ATTRIB_MAX_CT, /* 0x000B */
+
+ FDMI_HBA_ATTRIB_MAX_TYPE
+};
+
+/*
+ * FDMI Port attribute types
+ */
+enum fdmi_port_attribute_type {
+ FDMI_PORT_ATTRIB_FC4_TYPES = 1, /* 0x0001 */
+ FDMI_PORT_ATTRIB_SUPP_SPEED, /* 0x0002 */
+ FDMI_PORT_ATTRIB_PORT_SPEED, /* 0x0003 */
+ FDMI_PORT_ATTRIB_FRAME_SIZE, /* 0x0004 */
+ FDMI_PORT_ATTRIB_DEV_NAME, /* 0x0005 */
+ FDMI_PORT_ATTRIB_HOST_NAME, /* 0x0006 */
+
+ FDMI_PORT_ATTR_MAX_TYPE
+};
+
+/*
+ * FDMI attribute
+ */
+struct fdmi_attr_s {
+ u16 type;
+ u16 len;
+ u8 value[1];
+};
+
+/*
+ * HBA Attribute Block
+ */
+struct fdmi_hba_attr_s {
+ u32 attr_count; /* # of attributes */
+ struct fdmi_attr_s hba_attr; /* n attributes */
+};
+
+/*
+ * Registered Port List
+ */
+struct fdmi_port_list_s {
+ u32 num_ports; /* number Of Port Entries */
+ wwn_t port_entry; /* one or more */
+};
+
+/*
+ * Port Attribute Block
+ */
+struct fdmi_port_attr_s {
+ u32 attr_count; /* # of attributes */
+ struct fdmi_attr_s port_attr; /* n attributes */
+};
+
+/*
+ * FDMI Register HBA Attributes
+ */
+struct fdmi_rhba_s {
+ wwn_t hba_id; /* HBA Identifier */
+ struct fdmi_port_list_s port_list; /* Registered Port List */
+ struct fdmi_hba_attr_s hba_attr_blk; /* HBA attribute block */
+};
+
+/*
+ * FDMI Register Port
+ */
+struct fdmi_rprt_s {
+ wwn_t hba_id; /* HBA Identifier */
+ wwn_t port_name; /* Port wwn */
+ struct fdmi_port_attr_s port_attr_blk; /* Port Attr Block */
+};
+
+/*
+ * FDMI Register Port Attributes
+ */
+struct fdmi_rpa_s {
+ wwn_t port_name; /* port wwn */
+ struct fdmi_port_attr_s port_attr_blk; /* Port Attr Block */
+};
+
+#pragma pack()
+
+#endif /* __BFA_FC_H__ */
diff --git a/drivers/scsi/bfa/fcbuild.c b/drivers/scsi/bfa/bfa_fcbuild.c
index fee5456451cb..b7d2657ca82a 100644
--- a/drivers/scsi/bfa/fcbuild.c
+++ b/drivers/scsi/bfa/bfa_fcbuild.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
* All rights reserved
* www.brocade.com
*
@@ -18,25 +18,25 @@
* fcbuild.c - FC link service frame building and parsing routines
*/
-#include <bfa_os_inc.h>
-#include "fcbuild.h"
+#include "bfa_os_inc.h"
+#include "bfa_fcbuild.h"
/*
* static build functions
*/
-static void fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
- u16 ox_id);
-static void fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
- u16 ox_id);
-static struct fchs_s fc_els_req_tmpl;
-static struct fchs_s fc_els_rsp_tmpl;
-static struct fchs_s fc_bls_req_tmpl;
-static struct fchs_s fc_bls_rsp_tmpl;
+static void fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
+ u16 ox_id);
+static void fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
+ u16 ox_id);
+static struct fchs_s fc_els_req_tmpl;
+static struct fchs_s fc_els_rsp_tmpl;
+static struct fchs_s fc_bls_req_tmpl;
+static struct fchs_s fc_bls_rsp_tmpl;
static struct fc_ba_acc_s ba_acc_tmpl;
static struct fc_logi_s plogi_tmpl;
static struct fc_prli_s prli_tmpl;
static struct fc_rrq_s rrq_tmpl;
-static struct fchs_s fcp_fchs_tmpl;
+static struct fchs_s fcp_fchs_tmpl;
void
fcbuild_init(void)
@@ -123,7 +123,7 @@ fcbuild_init(void)
rrq_tmpl.els_cmd.els_code = FC_ELS_RRQ;
/*
- * fcp_fchs_tmpl
+ * fcp_struct fchs_s mpl
*/
fcp_fchs_tmpl.routing = FC_RTG_FC4_DEV_DATA;
fcp_fchs_tmpl.cat_info = FC_CAT_UNSOLICIT_CMD;
@@ -135,8 +135,7 @@ fcbuild_init(void)
}
static void
-fc_gs_fchdr_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
- u32 ox_id)
+fc_gs_fchdr_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u32 ox_id)
{
bfa_os_memset(fchs, 0, sizeof(struct fchs_s));
@@ -158,8 +157,7 @@ fc_gs_fchdr_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
}
void
-fc_els_req_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
- u16 ox_id)
+fc_els_req_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id)
{
bfa_os_memcpy(fchs, &fc_els_req_tmpl, sizeof(struct fchs_s));
fchs->d_id = (d_id);
@@ -168,8 +166,7 @@ fc_els_req_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
}
static void
-fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
- u16 ox_id)
+fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id)
{
bfa_os_memcpy(fchs, &fc_els_rsp_tmpl, sizeof(struct fchs_s));
fchs->d_id = d_id;
@@ -180,8 +177,8 @@ fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
enum fc_parse_status
fc_els_rsp_parse(struct fchs_s *fchs, int len)
{
- struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
- struct fc_ls_rjt_s *ls_rjt = (struct fc_ls_rjt_s *) els_cmd;
+ struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
+ struct fc_ls_rjt_s *ls_rjt = (struct fc_ls_rjt_s *) els_cmd;
len = len;
@@ -199,8 +196,7 @@ fc_els_rsp_parse(struct fchs_s *fchs, int len)
}
static void
-fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
- u16 ox_id)
+fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id)
{
bfa_os_memcpy(fchs, &fc_bls_rsp_tmpl, sizeof(struct fchs_s));
fchs->d_id = d_id;
@@ -213,7 +209,7 @@ fc_plogi_x_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
u16 ox_id, wwn_t port_name, wwn_t node_name,
u16 pdu_size, u8 els_code)
{
- struct fc_logi_s *plogi = (struct fc_logi_s *) (pld);
+ struct fc_logi_s *plogi = (struct fc_logi_s *) (pld);
bfa_os_memcpy(plogi, &plogi_tmpl, sizeof(struct fc_logi_s));
@@ -233,12 +229,11 @@ fc_plogi_x_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
u16
fc_flogi_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
- u16 ox_id, wwn_t port_name, wwn_t node_name,
- u16 pdu_size, u8 set_npiv, u8 set_auth,
- u16 local_bb_credits)
+ u16 ox_id, wwn_t port_name, wwn_t node_name, u16 pdu_size,
+ u8 set_npiv, u8 set_auth, u16 local_bb_credits)
{
u32 d_id = bfa_os_hton3b(FC_FABRIC_PORT);
- u32 *vvl_info;
+ u32 *vvl_info;
bfa_os_memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s));
@@ -292,8 +287,7 @@ fc_flogi_acc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
u16
fc_fdisc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
- u16 ox_id, wwn_t port_name, wwn_t node_name,
- u16 pdu_size)
+ u16 ox_id, wwn_t port_name, wwn_t node_name, u16 pdu_size)
{
u32 d_id = bfa_os_hton3b(FC_FABRIC_PORT);
@@ -330,9 +324,9 @@ fc_plogi_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
enum fc_parse_status
fc_plogi_rsp_parse(struct fchs_s *fchs, int len, wwn_t port_name)
{
- struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
- struct fc_logi_s *plogi;
- struct fc_ls_rjt_s *ls_rjt;
+ struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
+ struct fc_logi_s *plogi;
+ struct fc_ls_rjt_s *ls_rjt;
switch (els_cmd->els_code) {
case FC_ELS_LS_RJT:
@@ -364,7 +358,7 @@ fc_plogi_rsp_parse(struct fchs_s *fchs, int len, wwn_t port_name)
enum fc_parse_status
fc_plogi_parse(struct fchs_s *fchs)
{
- struct fc_logi_s *plogi = (struct fc_logi_s *) (fchs + 1);
+ struct fc_logi_s *plogi = (struct fc_logi_s *) (fchs + 1);
if (plogi->class3.class_valid != 1)
return FC_PARSE_FAILURE;
@@ -381,7 +375,7 @@ u16
fc_prli_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
u16 ox_id)
{
- struct fc_prli_s *prli = (struct fc_prli_s *) (pld);
+ struct fc_prli_s *prli = (struct fc_prli_s *) (pld);
fc_els_req_build(fchs, d_id, s_id, ox_id);
bfa_os_memcpy(prli, &prli_tmpl, sizeof(struct fc_prli_s));
@@ -398,19 +392,16 @@ fc_prli_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
u16
fc_prli_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
- u16 ox_id, enum bfa_port_role role)
+ u16 ox_id, enum bfa_lport_role role)
{
- struct fc_prli_s *prli = (struct fc_prli_s *) (pld);
+ struct fc_prli_s *prli = (struct fc_prli_s *) (pld);
fc_els_rsp_build(fchs, d_id, s_id, ox_id);
bfa_os_memcpy(prli, &prli_tmpl, sizeof(struct fc_prli_s));
prli->command = FC_ELS_ACC;
- if ((role & BFA_PORT_ROLE_FCP_TM) == BFA_PORT_ROLE_FCP_TM)
- prli->parampage.servparams.target = 1;
- else
- prli->parampage.servparams.initiator = 1;
+ prli->parampage.servparams.initiator = 1;
prli->parampage.rspcode = FC_PRLI_ACC_XQTD;
@@ -452,12 +443,12 @@ fc_prli_parse(struct fc_prli_s *prli)
}
u16
-fc_logo_build(struct fchs_s *fchs, struct fc_logo_s *logo, u32 d_id,
- u32 s_id, u16 ox_id, wwn_t port_name)
+fc_logo_build(struct fchs_s *fchs, struct fc_logo_s *logo, u32 d_id, u32 s_id,
+ u16 ox_id, wwn_t port_name)
{
fc_els_req_build(fchs, d_id, s_id, ox_id);
- memset(logo, '\0', sizeof(struct fc_logo_s));
+ bfa_os_memset(logo, '\0', sizeof(struct fc_logo_s));
logo->els_cmd.els_code = FC_ELS_LOGO;
logo->nport_id = (s_id);
logo->orig_port_name = port_name;
@@ -470,7 +461,7 @@ fc_adisc_x_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id,
u32 s_id, u16 ox_id, wwn_t port_name,
wwn_t node_name, u8 els_code)
{
- memset(adisc, '\0', sizeof(struct fc_adisc_s));
+ bfa_os_memset(adisc, '\0', sizeof(struct fc_adisc_s));
adisc->els_cmd.els_code = els_code;
@@ -489,8 +480,7 @@ fc_adisc_x_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id,
u16
fc_adisc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id,
- u32 s_id, u16 ox_id, wwn_t port_name,
- wwn_t node_name)
+ u32 s_id, u16 ox_id, wwn_t port_name, wwn_t node_name)
{
return fc_adisc_x_build(fchs, adisc, d_id, s_id, ox_id, port_name,
node_name, FC_ELS_ADISC);
@@ -523,10 +513,10 @@ fc_adisc_rsp_parse(struct fc_adisc_s *adisc, int len, wwn_t port_name,
}
enum fc_parse_status
-fc_adisc_parse(struct fchs_s *fchs, void *pld, u32 host_dap,
- wwn_t node_name, wwn_t port_name)
+fc_adisc_parse(struct fchs_s *fchs, void *pld, u32 host_dap, wwn_t node_name,
+ wwn_t port_name)
{
- struct fc_adisc_s *adisc = (struct fc_adisc_s *) pld;
+ struct fc_adisc_s *adisc = (struct fc_adisc_s *) pld;
if (adisc->els_cmd.els_code != FC_ELS_ACC)
return FC_PARSE_FAILURE;
@@ -542,13 +532,13 @@ fc_adisc_parse(struct fchs_s *fchs, void *pld, u32 host_dap,
enum fc_parse_status
fc_pdisc_parse(struct fchs_s *fchs, wwn_t node_name, wwn_t port_name)
{
- struct fc_logi_s *pdisc = (struct fc_logi_s *) (fchs + 1);
+ struct fc_logi_s *pdisc = (struct fc_logi_s *) (fchs + 1);
if (pdisc->class3.class_valid != 1)
return FC_PARSE_FAILURE;
if ((bfa_os_ntohs(pdisc->class3.rxsz) <
- (FC_MIN_PDUSZ - sizeof(struct fchs_s)))
+ (FC_MIN_PDUSZ - sizeof(struct fchs_s)))
|| (pdisc->class3.rxsz == 0))
return FC_PARSE_FAILURE;
@@ -584,8 +574,8 @@ fc_abts_rsp_parse(struct fchs_s *fchs, int len)
}
u16
-fc_rrq_build(struct fchs_s *fchs, struct fc_rrq_s *rrq, u32 d_id,
- u32 s_id, u16 ox_id, u16 rrq_oxid)
+fc_rrq_build(struct fchs_s *fchs, struct fc_rrq_s *rrq, u32 d_id, u32 s_id,
+ u16 ox_id, u16 rrq_oxid)
{
fc_els_req_build(fchs, d_id, s_id, ox_id);
@@ -604,11 +594,11 @@ u16
fc_logo_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
u16 ox_id)
{
- struct fc_els_cmd_s *acc = pld;
+ struct fc_els_cmd_s *acc = pld;
fc_els_rsp_build(fchs, d_id, s_id, ox_id);
- memset(acc, 0, sizeof(struct fc_els_cmd_s));
+ bfa_os_memset(acc, 0, sizeof(struct fc_els_cmd_s));
acc->els_code = FC_ELS_ACC;
return sizeof(struct fc_els_cmd_s);
@@ -620,7 +610,7 @@ fc_ls_rjt_build(struct fchs_s *fchs, struct fc_ls_rjt_s *ls_rjt, u32 d_id,
u8 reason_code_expl)
{
fc_els_rsp_build(fchs, d_id, s_id, ox_id);
- memset(ls_rjt, 0, sizeof(struct fc_ls_rjt_s));
+ bfa_os_memset(ls_rjt, 0, sizeof(struct fc_ls_rjt_s));
ls_rjt->els_cmd.els_code = FC_ELS_LS_RJT;
ls_rjt->reason_code = reason_code;
@@ -647,11 +637,11 @@ fc_ba_acc_build(struct fchs_s *fchs, struct fc_ba_acc_s *ba_acc, u32 d_id,
}
u16
-fc_ls_acc_build(struct fchs_s *fchs, struct fc_els_cmd_s *els_cmd,
- u32 d_id, u32 s_id, u16 ox_id)
+fc_ls_acc_build(struct fchs_s *fchs, struct fc_els_cmd_s *els_cmd, u32 d_id,
+ u32 s_id, u16 ox_id)
{
fc_els_rsp_build(fchs, d_id, s_id, ox_id);
- memset(els_cmd, 0, sizeof(struct fc_els_cmd_s));
+ bfa_os_memset(els_cmd, 0, sizeof(struct fc_els_cmd_s));
els_cmd->els_code = FC_ELS_ACC;
return sizeof(struct fc_els_cmd_s);
@@ -661,8 +651,8 @@ int
fc_logout_params_pages(struct fchs_s *fc_frame, u8 els_code)
{
int num_pages = 0;
- struct fc_prlo_s *prlo;
- struct fc_tprlo_s *tprlo;
+ struct fc_prlo_s *prlo;
+ struct fc_tprlo_s *tprlo;
if (els_code == FC_ELS_PRLO) {
prlo = (struct fc_prlo_s *) (fc_frame + 1);
@@ -676,14 +666,13 @@ fc_logout_params_pages(struct fchs_s *fc_frame, u8 els_code)
u16
fc_tprlo_acc_build(struct fchs_s *fchs, struct fc_tprlo_acc_s *tprlo_acc,
- u32 d_id, u32 s_id, u16 ox_id,
- int num_pages)
+ u32 d_id, u32 s_id, u16 ox_id, int num_pages)
{
int page;
fc_els_rsp_build(fchs, d_id, s_id, ox_id);
- memset(tprlo_acc, 0, (num_pages * 16) + 4);
+ bfa_os_memset(tprlo_acc, 0, (num_pages * 16) + 4);
tprlo_acc->command = FC_ELS_ACC;
tprlo_acc->page_len = 0x10;
@@ -700,15 +689,14 @@ fc_tprlo_acc_build(struct fchs_s *fchs, struct fc_tprlo_acc_s *tprlo_acc,
}
u16
-fc_prlo_acc_build(struct fchs_s *fchs, struct fc_prlo_acc_s *prlo_acc,
- u32 d_id, u32 s_id, u16 ox_id,
- int num_pages)
+fc_prlo_acc_build(struct fchs_s *fchs, struct fc_prlo_acc_s *prlo_acc, u32 d_id,
+ u32 s_id, u16 ox_id, int num_pages)
{
int page;
fc_els_rsp_build(fchs, d_id, s_id, ox_id);
- memset(prlo_acc, 0, (num_pages * 16) + 4);
+ bfa_os_memset(prlo_acc, 0, (num_pages * 16) + 4);
prlo_acc->command = FC_ELS_ACC;
prlo_acc->page_len = 0x10;
prlo_acc->payload_len = bfa_os_htons((num_pages * 16) + 4);
@@ -726,11 +714,11 @@ fc_prlo_acc_build(struct fchs_s *fchs, struct fc_prlo_acc_s *prlo_acc,
u16
fc_rnid_build(struct fchs_s *fchs, struct fc_rnid_cmd_s *rnid, u32 d_id,
- u32 s_id, u16 ox_id, u32 data_format)
+ u32 s_id, u16 ox_id, u32 data_format)
{
fc_els_req_build(fchs, d_id, s_id, ox_id);
- memset(rnid, 0, sizeof(struct fc_rnid_cmd_s));
+ bfa_os_memset(rnid, 0, sizeof(struct fc_rnid_cmd_s));
rnid->els_cmd.els_code = FC_ELS_RNID;
rnid->node_id_data_format = data_format;
@@ -739,13 +727,12 @@ fc_rnid_build(struct fchs_s *fchs, struct fc_rnid_cmd_s *rnid, u32 d_id,
}
u16
-fc_rnid_acc_build(struct fchs_s *fchs, struct fc_rnid_acc_s *rnid_acc,
- u32 d_id, u32 s_id, u16 ox_id,
- u32 data_format,
- struct fc_rnid_common_id_data_s *common_id_data,
- struct fc_rnid_general_topology_data_s *gen_topo_data)
+fc_rnid_acc_build(struct fchs_s *fchs, struct fc_rnid_acc_s *rnid_acc, u32 d_id,
+ u32 s_id, u16 ox_id, u32 data_format,
+ struct fc_rnid_common_id_data_s *common_id_data,
+ struct fc_rnid_general_topology_data_s *gen_topo_data)
{
- memset(rnid_acc, 0, sizeof(struct fc_rnid_acc_s));
+ bfa_os_memset(rnid_acc, 0, sizeof(struct fc_rnid_acc_s));
fc_els_rsp_build(fchs, d_id, s_id, ox_id);
@@ -769,27 +756,26 @@ fc_rnid_acc_build(struct fchs_s *fchs, struct fc_rnid_acc_s *rnid_acc,
u16
fc_rpsc_build(struct fchs_s *fchs, struct fc_rpsc_cmd_s *rpsc, u32 d_id,
- u32 s_id, u16 ox_id)
+ u32 s_id, u16 ox_id)
{
fc_els_req_build(fchs, d_id, s_id, ox_id);
- memset(rpsc, 0, sizeof(struct fc_rpsc_cmd_s));
+ bfa_os_memset(rpsc, 0, sizeof(struct fc_rpsc_cmd_s));
rpsc->els_cmd.els_code = FC_ELS_RPSC;
return sizeof(struct fc_rpsc_cmd_s);
}
u16
-fc_rpsc2_build(struct fchs_s *fchs, struct fc_rpsc2_cmd_s *rpsc2,
- u32 d_id, u32 s_id, u32 *pid_list,
- u16 npids)
+fc_rpsc2_build(struct fchs_s *fchs, struct fc_rpsc2_cmd_s *rpsc2, u32 d_id,
+ u32 s_id, u32 *pid_list, u16 npids)
{
u32 dctlr_id = FC_DOMAIN_CTRLR(bfa_os_hton3b(d_id));
int i = 0;
fc_els_req_build(fchs, bfa_os_hton3b(dctlr_id), s_id, 0);
- memset(rpsc2, 0, sizeof(struct fc_rpsc2_cmd_s));
+ bfa_os_memset(rpsc2, 0, sizeof(struct fc_rpsc2_cmd_s));
rpsc2->els_cmd.els_code = FC_ELS_RPSC;
rpsc2->token = bfa_os_htonl(FC_BRCD_TOKEN);
@@ -797,16 +783,15 @@ fc_rpsc2_build(struct fchs_s *fchs, struct fc_rpsc2_cmd_s *rpsc2,
for (i = 0; i < npids; i++)
rpsc2->pid_list[i].pid = pid_list[i];
- return sizeof(struct fc_rpsc2_cmd_s) + ((npids - 1) *
- (sizeof(u32)));
+ return sizeof(struct fc_rpsc2_cmd_s) + ((npids - 1) * (sizeof(u32)));
}
u16
fc_rpsc_acc_build(struct fchs_s *fchs, struct fc_rpsc_acc_s *rpsc_acc,
- u32 d_id, u32 s_id, u16 ox_id,
- struct fc_rpsc_speed_info_s *oper_speed)
+ u32 d_id, u32 s_id, u16 ox_id,
+ struct fc_rpsc_speed_info_s *oper_speed)
{
- memset(rpsc_acc, 0, sizeof(struct fc_rpsc_acc_s));
+ bfa_os_memset(rpsc_acc, 0, sizeof(struct fc_rpsc_acc_s));
fc_els_rsp_build(fchs, d_id, s_id, ox_id);
@@ -820,7 +805,6 @@ fc_rpsc_acc_build(struct fchs_s *fchs, struct fc_rpsc_acc_s *rpsc_acc,
bfa_os_htons(oper_speed->port_op_speed);
return sizeof(struct fc_rpsc_acc_s);
-
}
/*
@@ -831,7 +815,7 @@ fc_rpsc_acc_build(struct fchs_s *fchs, struct fc_rpsc_acc_s *rpsc_acc,
u16
fc_logo_rsp_parse(struct fchs_s *fchs, int len)
{
- struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
+ struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
len = len;
if (els_cmd->els_code != FC_ELS_ACC)
@@ -841,11 +825,10 @@ fc_logo_rsp_parse(struct fchs_s *fchs, int len)
}
u16
-fc_pdisc_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
- u16 ox_id, wwn_t port_name, wwn_t node_name,
- u16 pdu_size)
+fc_pdisc_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id,
+ wwn_t port_name, wwn_t node_name, u16 pdu_size)
{
- struct fc_logi_s *pdisc = (struct fc_logi_s *) (fchs + 1);
+ struct fc_logi_s *pdisc = (struct fc_logi_s *) (fchs + 1);
bfa_os_memcpy(pdisc, &plogi_tmpl, sizeof(struct fc_logi_s));
@@ -862,7 +845,7 @@ fc_pdisc_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
u16
fc_pdisc_rsp_parse(struct fchs_s *fchs, int len, wwn_t port_name)
{
- struct fc_logi_s *pdisc = (struct fc_logi_s *) (fchs + 1);
+ struct fc_logi_s *pdisc = (struct fc_logi_s *) (fchs + 1);
if (len < sizeof(struct fc_logi_s))
return FC_PARSE_LEN_INVAL;
@@ -886,11 +869,11 @@ u16
fc_prlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id,
int num_pages)
{
- struct fc_prlo_s *prlo = (struct fc_prlo_s *) (fchs + 1);
+ struct fc_prlo_s *prlo = (struct fc_prlo_s *) (fchs + 1);
int page;
fc_els_req_build(fchs, d_id, s_id, ox_id);
- memset(prlo, 0, (num_pages * 16) + 4);
+ bfa_os_memset(prlo, 0, (num_pages * 16) + 4);
prlo->command = FC_ELS_PRLO;
prlo->page_len = 0x10;
prlo->payload_len = bfa_os_htons((num_pages * 16) + 4);
@@ -909,7 +892,7 @@ fc_prlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id,
u16
fc_prlo_rsp_parse(struct fchs_s *fchs, int len)
{
- struct fc_prlo_acc_s *prlo = (struct fc_prlo_acc_s *) (fchs + 1);
+ struct fc_prlo_acc_s *prlo = (struct fc_prlo_acc_s *) (fchs + 1);
int num_pages = 0;
int page = 0;
@@ -941,15 +924,14 @@ fc_prlo_rsp_parse(struct fchs_s *fchs, int len)
}
u16
-fc_tprlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
- u16 ox_id, int num_pages,
- enum fc_tprlo_type tprlo_type, u32 tpr_id)
+fc_tprlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id,
+ int num_pages, enum fc_tprlo_type tprlo_type, u32 tpr_id)
{
- struct fc_tprlo_s *tprlo = (struct fc_tprlo_s *) (fchs + 1);
+ struct fc_tprlo_s *tprlo = (struct fc_tprlo_s *) (fchs + 1);
int page;
fc_els_req_build(fchs, d_id, s_id, ox_id);
- memset(tprlo, 0, (num_pages * 16) + 4);
+ bfa_os_memset(tprlo, 0, (num_pages * 16) + 4);
tprlo->command = FC_ELS_TPRLO;
tprlo->page_len = 0x10;
tprlo->payload_len = bfa_os_htons((num_pages * 16) + 4);
@@ -1003,7 +985,7 @@ fc_tprlo_rsp_parse(struct fchs_s *fchs, int len)
enum fc_parse_status
fc_rrq_rsp_parse(struct fchs_s *fchs, int len)
{
- struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
+ struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
len = len;
if (els_cmd->els_code != FC_ELS_ACC)
@@ -1013,11 +995,10 @@ fc_rrq_rsp_parse(struct fchs_s *fchs, int len)
}
u16
-fc_ba_rjt_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
- u16 ox_id, u32 reason_code,
- u32 reason_expl)
+fc_ba_rjt_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id,
+ u32 reason_code, u32 reason_expl)
{
- struct fc_ba_rjt_s *ba_rjt = (struct fc_ba_rjt_s *) (fchs + 1);
+ struct fc_ba_rjt_s *ba_rjt = (struct fc_ba_rjt_s *) (fchs + 1);
fc_bls_rsp_build(fchs, d_id, s_id, ox_id);
@@ -1062,10 +1043,8 @@ u16
fc_gidpn_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
wwn_t port_name)
{
-
- struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
- struct fcgs_gidpn_req_s *gidpn =
- (struct fcgs_gidpn_req_s *) (cthdr + 1);
+ struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
+ struct fcgs_gidpn_req_s *gidpn = (struct fcgs_gidpn_req_s *)(cthdr + 1);
u32 d_id = bfa_os_hton3b(FC_NAME_SERVER);
fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
@@ -1080,8 +1059,7 @@ u16
fc_gpnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
u32 port_id)
{
-
- struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
+ struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
fcgs_gpnid_req_t *gpnid = (fcgs_gpnid_req_t *) (cthdr + 1);
u32 d_id = bfa_os_hton3b(FC_NAME_SERVER);
@@ -1097,8 +1075,7 @@ u16
fc_gnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
u32 port_id)
{
-
- struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
+ struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
fcgs_gnnid_req_t *gnnid = (fcgs_gnnid_req_t *) (cthdr + 1);
u32 d_id = bfa_os_hton3b(FC_NAME_SERVER);
@@ -1124,8 +1101,8 @@ fc_ct_rsp_parse(struct ct_hdr_s *cthdr)
}
u16
-fc_scr_build(struct fchs_s *fchs, struct fc_scr_s *scr, u8 set_br_reg,
- u32 s_id, u16 ox_id)
+fc_scr_build(struct fchs_s *fchs, struct fc_scr_s *scr,
+ u8 set_br_reg, u32 s_id, u16 ox_id)
{
u32 d_id = bfa_os_hton3b(FC_FABRIC_CONTROLLER);
@@ -1141,8 +1118,8 @@ fc_scr_build(struct fchs_s *fchs, struct fc_scr_s *scr, u8 set_br_reg,
}
u16
-fc_rscn_build(struct fchs_s *fchs, struct fc_rscn_pl_s *rscn, u32 s_id,
- u16 ox_id)
+fc_rscn_build(struct fchs_s *fchs, struct fc_rscn_pl_s *rscn,
+ u32 s_id, u16 ox_id)
{
u32 d_id = bfa_os_hton3b(FC_FABRIC_CONTROLLER);
u16 payldlen;
@@ -1162,11 +1139,10 @@ fc_rscn_build(struct fchs_s *fchs, struct fc_rscn_pl_s *rscn, u32 s_id,
u16
fc_rftid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
- enum bfa_port_role roles)
+ enum bfa_lport_role roles)
{
- struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
- struct fcgs_rftid_req_s *rftid =
- (struct fcgs_rftid_req_s *) (cthdr + 1);
+ struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
+ struct fcgs_rftid_req_s *rftid = (struct fcgs_rftid_req_s *)(cthdr + 1);
u32 type_value, d_id = bfa_os_hton3b(FC_NAME_SERVER);
u8 index;
@@ -1182,23 +1158,15 @@ fc_rftid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
type_value = 1 << (FC_TYPE_FCP % 32);
rftid->fc4_type[index] = bfa_os_htonl(type_value);
- if (roles & BFA_PORT_ROLE_FCP_IPFC) {
- index = FC_TYPE_IP >> 5;
- type_value = 1 << (FC_TYPE_IP % 32);
- rftid->fc4_type[index] |= bfa_os_htonl(type_value);
- }
-
return sizeof(struct fcgs_rftid_req_s) + sizeof(struct ct_hdr_s);
}
u16
-fc_rftid_build_sol(struct fchs_s *fchs, void *pyld, u32 s_id,
- u16 ox_id, u8 *fc4_bitmap,
- u32 bitmap_size)
+fc_rftid_build_sol(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
+ u8 *fc4_bitmap, u32 bitmap_size)
{
- struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
- struct fcgs_rftid_req_s *rftid =
- (struct fcgs_rftid_req_s *) (cthdr + 1);
+ struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
+ struct fcgs_rftid_req_s *rftid = (struct fcgs_rftid_req_s *)(cthdr + 1);
u32 d_id = bfa_os_hton3b(FC_NAME_SERVER);
fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
@@ -1208,7 +1176,7 @@ fc_rftid_build_sol(struct fchs_s *fchs, void *pyld, u32 s_id,
rftid->dap = s_id;
bfa_os_memcpy((void *)rftid->fc4_type, (void *)fc4_bitmap,
- (bitmap_size < 32 ? bitmap_size : 32));
+ (bitmap_size < 32 ? bitmap_size : 32));
return sizeof(struct fcgs_rftid_req_s) + sizeof(struct ct_hdr_s);
}
@@ -1217,9 +1185,8 @@ u16
fc_rffid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
u8 fc4_type, u8 fc4_ftrs)
{
- struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
- struct fcgs_rffid_req_s *rffid =
- (struct fcgs_rffid_req_s *) (cthdr + 1);
+ struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
+ struct fcgs_rffid_req_s *rffid = (struct fcgs_rffid_req_s *)(cthdr + 1);
u32 d_id = bfa_os_hton3b(FC_NAME_SERVER);
fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
@@ -1227,9 +1194,9 @@ fc_rffid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
bfa_os_memset(rffid, 0, sizeof(struct fcgs_rffid_req_s));
- rffid->dap = s_id;
+ rffid->dap = s_id;
rffid->fc4ftr_bits = fc4_ftrs;
- rffid->fc4_type = fc4_type;
+ rffid->fc4_type = fc4_type;
return sizeof(struct fcgs_rffid_req_s) + sizeof(struct ct_hdr_s);
}
@@ -1239,9 +1206,9 @@ fc_rspnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
u8 *name)
{
- struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
+ struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
struct fcgs_rspnid_req_s *rspnid =
- (struct fcgs_rspnid_req_s *) (cthdr + 1);
+ (struct fcgs_rspnid_req_s *)(cthdr + 1);
u32 d_id = bfa_os_hton3b(FC_NAME_SERVER);
fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
@@ -1257,13 +1224,11 @@ fc_rspnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
}
u16
-fc_gid_ft_build(struct fchs_s *fchs, void *pyld, u32 s_id,
- u8 fc4_type)
+fc_gid_ft_build(struct fchs_s *fchs, void *pyld, u32 s_id, u8 fc4_type)
{
- struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
- struct fcgs_gidft_req_s *gidft =
- (struct fcgs_gidft_req_s *) (cthdr + 1);
+ struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
+ struct fcgs_gidft_req_s *gidft = (struct fcgs_gidft_req_s *)(cthdr + 1);
u32 d_id = bfa_os_hton3b(FC_NAME_SERVER);
fc_gs_fchdr_build(fchs, d_id, s_id, 0);
@@ -1282,9 +1247,8 @@ u16
fc_rpnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
wwn_t port_name)
{
- struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
- struct fcgs_rpnid_req_s *rpnid =
- (struct fcgs_rpnid_req_s *) (cthdr + 1);
+ struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
+ struct fcgs_rpnid_req_s *rpnid = (struct fcgs_rpnid_req_s *)(cthdr + 1);
u32 d_id = bfa_os_hton3b(FC_NAME_SERVER);
fc_gs_fchdr_build(fchs, d_id, s_id, 0);
@@ -1301,9 +1265,8 @@ u16
fc_rnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
wwn_t node_name)
{
- struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
- struct fcgs_rnnid_req_s *rnnid =
- (struct fcgs_rnnid_req_s *) (cthdr + 1);
+ struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
+ struct fcgs_rnnid_req_s *rnnid = (struct fcgs_rnnid_req_s *)(cthdr + 1);
u32 d_id = bfa_os_hton3b(FC_NAME_SERVER);
fc_gs_fchdr_build(fchs, d_id, s_id, 0);
@@ -1320,7 +1283,7 @@ u16
fc_rcsid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
u32 cos)
{
- struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
+ struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
struct fcgs_rcsid_req_s *rcsid =
(struct fcgs_rcsid_req_s *) (cthdr + 1);
u32 d_id = bfa_os_hton3b(FC_NAME_SERVER);
@@ -1339,9 +1302,8 @@ u16
fc_rptid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
u8 port_type)
{
- struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
- struct fcgs_rptid_req_s *rptid =
- (struct fcgs_rptid_req_s *) (cthdr + 1);
+ struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
+ struct fcgs_rptid_req_s *rptid = (struct fcgs_rptid_req_s *)(cthdr + 1);
u32 d_id = bfa_os_hton3b(FC_NAME_SERVER);
fc_gs_fchdr_build(fchs, d_id, s_id, 0);
@@ -1357,9 +1319,8 @@ fc_rptid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
u16
fc_ganxt_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id)
{
- struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
- struct fcgs_ganxt_req_s *ganxt =
- (struct fcgs_ganxt_req_s *) (cthdr + 1);
+ struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
+ struct fcgs_ganxt_req_s *ganxt = (struct fcgs_ganxt_req_s *)(cthdr + 1);
u32 d_id = bfa_os_hton3b(FC_NAME_SERVER);
fc_gs_fchdr_build(fchs, d_id, s_id, 0);
@@ -1379,7 +1340,7 @@ fc_fdmi_reqhdr_build(struct fchs_s *fchs, void *pyld, u32 s_id,
u16 cmd_code)
{
- struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
+ struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
u32 d_id = bfa_os_hton3b(FC_MGMT_SERVER);
fc_gs_fchdr_build(fchs, d_id, s_id, 0);
@@ -1409,12 +1370,12 @@ fc_get_fc4type_bitmask(u8 fc4_type, u8 *bit_mask)
}
/*
- * GMAL Request
+ * GMAL Request
*/
u16
fc_gmal_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, wwn_t wwn)
{
- struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
+ struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
fcgs_gmal_req_t *gmal = (fcgs_gmal_req_t *) (cthdr + 1);
u32 d_id = bfa_os_hton3b(FC_MGMT_SERVER);
@@ -1434,7 +1395,7 @@ fc_gmal_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, wwn_t wwn)
u16
fc_gfn_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, wwn_t wwn)
{
- struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
+ struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
fcgs_gfn_req_t *gfn = (fcgs_gfn_req_t *) (cthdr + 1);
u32 d_id = bfa_os_hton3b(FC_MGMT_SERVER);
diff --git a/drivers/scsi/bfa/bfa_fcbuild.h b/drivers/scsi/bfa/bfa_fcbuild.h
new file mode 100644
index 000000000000..73abd02e53cc
--- /dev/null
+++ b/drivers/scsi/bfa/bfa_fcbuild.h
@@ -0,0 +1,316 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+/*
+ * fcbuild.h - FC link service frame building and parsing routines
+ */
+
+#ifndef __FCBUILD_H__
+#define __FCBUILD_H__
+
+#include "bfa_os_inc.h"
+#include "bfa_fc.h"
+#include "bfa_defs_fcs.h"
+
+/*
+ * Utility Macros/functions
+ */
+
+#define wwn_is_equal(_wwn1, _wwn2) \
+ (memcmp(&(_wwn1), &(_wwn2), sizeof(wwn_t)) == 0)
+
+#define fc_roundup(_l, _s) (((_l) + ((_s) - 1)) & ~((_s) - 1))
+
+/*
+ * Given the fc response length, this routine will return
+ * the length of the actual payload bytes following the CT header.
+ *
+ * Assumes the input response length does not include the crc, eof, etc.
+ */
+static inline u32
+fc_get_ctresp_pyld_len(u32 resp_len)
+{
+ return resp_len - sizeof(struct ct_hdr_s);
+}
+
+/*
+ * Convert bfa speed to rpsc speed value.
+ */
+static inline enum bfa_port_speed
+fc_rpsc_operspeed_to_bfa_speed(enum fc_rpsc_op_speed speed)
+{
+ switch (speed) {
+
+ case RPSC_OP_SPEED_1G:
+ return BFA_PORT_SPEED_1GBPS;
+
+ case RPSC_OP_SPEED_2G:
+ return BFA_PORT_SPEED_2GBPS;
+
+ case RPSC_OP_SPEED_4G:
+ return BFA_PORT_SPEED_4GBPS;
+
+ case RPSC_OP_SPEED_8G:
+ return BFA_PORT_SPEED_8GBPS;
+
+ case RPSC_OP_SPEED_10G:
+ return BFA_PORT_SPEED_10GBPS;
+
+ default:
+ return BFA_PORT_SPEED_UNKNOWN;
+ }
+}
+
+/*
+ * Convert RPSC speed to bfa speed value.
+ */
+static inline enum fc_rpsc_op_speed
+fc_bfa_speed_to_rpsc_operspeed(enum bfa_port_speed op_speed)
+{
+ switch (op_speed) {
+
+ case BFA_PORT_SPEED_1GBPS:
+ return RPSC_OP_SPEED_1G;
+
+ case BFA_PORT_SPEED_2GBPS:
+ return RPSC_OP_SPEED_2G;
+
+ case BFA_PORT_SPEED_4GBPS:
+ return RPSC_OP_SPEED_4G;
+
+ case BFA_PORT_SPEED_8GBPS:
+ return RPSC_OP_SPEED_8G;
+
+ case BFA_PORT_SPEED_10GBPS:
+ return RPSC_OP_SPEED_10G;
+
+ default:
+ return RPSC_OP_SPEED_NOT_EST;
+ }
+}
+
+enum fc_parse_status {
+ FC_PARSE_OK = 0,
+ FC_PARSE_FAILURE = 1,
+ FC_PARSE_BUSY = 2,
+ FC_PARSE_LEN_INVAL,
+ FC_PARSE_ACC_INVAL,
+ FC_PARSE_PWWN_NOT_EQUAL,
+ FC_PARSE_NWWN_NOT_EQUAL,
+ FC_PARSE_RXSZ_INVAL,
+ FC_PARSE_NOT_FCP,
+ FC_PARSE_OPAFLAG_INVAL,
+ FC_PARSE_RPAFLAG_INVAL,
+ FC_PARSE_OPA_INVAL,
+ FC_PARSE_RPA_INVAL,
+
+};
+
+struct fc_templates_s {
+ struct fchs_s fc_els_req;
+ struct fchs_s fc_bls_req;
+ struct fc_logi_s plogi;
+ struct fc_rrq_s rrq;
+};
+
+void fcbuild_init(void);
+
+u16 fc_flogi_build(struct fchs_s *fchs, struct fc_logi_s *flogi,
+ u32 s_id, u16 ox_id, wwn_t port_name, wwn_t node_name,
+ u16 pdu_size, u8 set_npiv, u8 set_auth,
+ u16 local_bb_credits);
+
+u16 fc_fdisc_build(struct fchs_s *buf, struct fc_logi_s *flogi, u32 s_id,
+ u16 ox_id, wwn_t port_name, wwn_t node_name,
+ u16 pdu_size);
+
+u16 fc_flogi_acc_build(struct fchs_s *fchs, struct fc_logi_s *flogi,
+ u32 s_id, u16 ox_id,
+ wwn_t port_name, wwn_t node_name,
+ u16 pdu_size,
+ u16 local_bb_credits);
+
+u16 fc_plogi_build(struct fchs_s *fchs, void *pld, u32 d_id,
+ u32 s_id, u16 ox_id, wwn_t port_name,
+ wwn_t node_name, u16 pdu_size);
+
+enum fc_parse_status fc_plogi_parse(struct fchs_s *fchs);
+
+u16 fc_abts_build(struct fchs_s *buf, u32 d_id, u32 s_id,
+ u16 ox_id);
+
+enum fc_parse_status fc_abts_rsp_parse(struct fchs_s *buf, int len);
+
+u16 fc_rrq_build(struct fchs_s *buf, struct fc_rrq_s *rrq, u32 d_id,
+ u32 s_id, u16 ox_id, u16 rrq_oxid);
+enum fc_parse_status fc_rrq_rsp_parse(struct fchs_s *buf, int len);
+
+u16 fc_rspnid_build(struct fchs_s *fchs, void *pld, u32 s_id,
+ u16 ox_id, u8 *name);
+
+u16 fc_rftid_build(struct fchs_s *fchs, void *pld, u32 s_id,
+ u16 ox_id, enum bfa_lport_role role);
+
+u16 fc_rftid_build_sol(struct fchs_s *fchs, void *pyld, u32 s_id,
+ u16 ox_id, u8 *fc4_bitmap,
+ u32 bitmap_size);
+
+u16 fc_rffid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
+ u16 ox_id, u8 fc4_type, u8 fc4_ftrs);
+
+u16 fc_gidpn_build(struct fchs_s *fchs, void *pyld, u32 s_id,
+ u16 ox_id, wwn_t port_name);
+
+u16 fc_gpnid_build(struct fchs_s *fchs, void *pld, u32 s_id,
+ u16 ox_id, u32 port_id);
+
+u16 fc_scr_build(struct fchs_s *fchs, struct fc_scr_s *scr,
+ u8 set_br_reg, u32 s_id, u16 ox_id);
+
+u16 fc_plogi_acc_build(struct fchs_s *fchs, void *pld, u32 d_id,
+ u32 s_id, u16 ox_id,
+ wwn_t port_name, wwn_t node_name,
+ u16 pdu_size);
+
+u16 fc_adisc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc,
+ u32 d_id, u32 s_id, u16 ox_id, wwn_t port_name,
+ wwn_t node_name);
+
+enum fc_parse_status fc_adisc_parse(struct fchs_s *fchs, void *pld,
+ u32 host_dap, wwn_t node_name, wwn_t port_name);
+
+enum fc_parse_status fc_adisc_rsp_parse(struct fc_adisc_s *adisc, int len,
+ wwn_t port_name, wwn_t node_name);
+
+u16 fc_adisc_acc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc,
+ u32 d_id, u32 s_id, u16 ox_id,
+ wwn_t port_name, wwn_t node_name);
+u16 fc_ls_rjt_build(struct fchs_s *fchs, struct fc_ls_rjt_s *ls_rjt,
+ u32 d_id, u32 s_id, u16 ox_id,
+ u8 reason_code, u8 reason_code_expl);
+u16 fc_ls_acc_build(struct fchs_s *fchs, struct fc_els_cmd_s *els_cmd,
+ u32 d_id, u32 s_id, u16 ox_id);
+u16 fc_prli_build(struct fchs_s *fchs, void *pld, u32 d_id,
+ u32 s_id, u16 ox_id);
+
+enum fc_parse_status fc_prli_rsp_parse(struct fc_prli_s *prli, int len);
+
+u16 fc_prli_acc_build(struct fchs_s *fchs, void *pld, u32 d_id,
+ u32 s_id, u16 ox_id,
+ enum bfa_lport_role role);
+
+u16 fc_rnid_build(struct fchs_s *fchs, struct fc_rnid_cmd_s *rnid,
+ u32 d_id, u32 s_id, u16 ox_id,
+ u32 data_format);
+
+u16 fc_rnid_acc_build(struct fchs_s *fchs,
+ struct fc_rnid_acc_s *rnid_acc, u32 d_id, u32 s_id,
+ u16 ox_id, u32 data_format,
+ struct fc_rnid_common_id_data_s *common_id_data,
+ struct fc_rnid_general_topology_data_s *gen_topo_data);
+
+u16 fc_rpsc2_build(struct fchs_s *fchs, struct fc_rpsc2_cmd_s *rps2c,
+ u32 d_id, u32 s_id, u32 *pid_list, u16 npids);
+u16 fc_rpsc_build(struct fchs_s *fchs, struct fc_rpsc_cmd_s *rpsc,
+ u32 d_id, u32 s_id, u16 ox_id);
+u16 fc_rpsc_acc_build(struct fchs_s *fchs,
+ struct fc_rpsc_acc_s *rpsc_acc, u32 d_id, u32 s_id,
+ u16 ox_id, struct fc_rpsc_speed_info_s *oper_speed);
+u16 fc_gid_ft_build(struct fchs_s *fchs, void *pld, u32 s_id,
+ u8 fc4_type);
+
+u16 fc_rpnid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
+ u32 port_id, wwn_t port_name);
+
+u16 fc_rnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
+ u32 port_id, wwn_t node_name);
+
+u16 fc_rcsid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
+ u32 port_id, u32 cos);
+
+u16 fc_rptid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
+ u32 port_id, u8 port_type);
+
+u16 fc_ganxt_build(struct fchs_s *fchs, void *pyld, u32 s_id,
+ u32 port_id);
+
+u16 fc_logo_build(struct fchs_s *fchs, struct fc_logo_s *logo, u32 d_id,
+ u32 s_id, u16 ox_id, wwn_t port_name);
+
+u16 fc_logo_acc_build(struct fchs_s *fchs, void *pld, u32 d_id,
+ u32 s_id, u16 ox_id);
+
+u16 fc_fdmi_reqhdr_build(struct fchs_s *fchs, void *pyld, u32 s_id,
+ u16 cmd_code);
+u16 fc_gmal_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, wwn_t wwn);
+u16 fc_gfn_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, wwn_t wwn);
+
+void fc_get_fc4type_bitmask(u8 fc4_type, u8 *bit_mask);
+
+void fc_els_req_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
+ u16 ox_id);
+
+enum fc_parse_status fc_els_rsp_parse(struct fchs_s *fchs, int len);
+
+enum fc_parse_status fc_plogi_rsp_parse(struct fchs_s *fchs, int len,
+ wwn_t port_name);
+
+enum fc_parse_status fc_prli_parse(struct fc_prli_s *prli);
+
+enum fc_parse_status fc_pdisc_parse(struct fchs_s *fchs, wwn_t node_name,
+ wwn_t port_name);
+
+u16 fc_ba_acc_build(struct fchs_s *fchs, struct fc_ba_acc_s *ba_acc, u32 d_id,
+ u32 s_id, u16 ox_id, u16 rx_id);
+
+int fc_logout_params_pages(struct fchs_s *fc_frame, u8 els_code);
+
+u16 fc_tprlo_acc_build(struct fchs_s *fchs, struct fc_tprlo_acc_s *tprlo_acc,
+ u32 d_id, u32 s_id, u16 ox_id, int num_pages);
+
+u16 fc_prlo_acc_build(struct fchs_s *fchs, struct fc_prlo_acc_s *prlo_acc,
+ u32 d_id, u32 s_id, u16 ox_id, int num_pages);
+
+u16 fc_logo_rsp_parse(struct fchs_s *fchs, int len);
+
+u16 fc_pdisc_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
+ u16 ox_id, wwn_t port_name, wwn_t node_name,
+ u16 pdu_size);
+
+u16 fc_pdisc_rsp_parse(struct fchs_s *fchs, int len, wwn_t port_name);
+
+u16 fc_prlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
+ u16 ox_id, int num_pages);
+
+u16 fc_prlo_rsp_parse(struct fchs_s *fchs, int len);
+
+u16 fc_tprlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
+ u16 ox_id, int num_pages, enum fc_tprlo_type tprlo_type,
+ u32 tpr_id);
+
+u16 fc_tprlo_rsp_parse(struct fchs_s *fchs, int len);
+
+u16 fc_ba_rjt_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
+ u16 ox_id, u32 reason_code, u32 reason_expl);
+
+u16 fc_gnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
+ u32 port_id);
+
+u16 fc_ct_rsp_parse(struct ct_hdr_s *cthdr);
+
+u16 fc_rscn_build(struct fchs_s *fchs, struct fc_rscn_pl_s *rscn, u32 s_id,
+ u16 ox_id);
+#endif
diff --git a/drivers/scsi/bfa/bfa_fcpim.c b/drivers/scsi/bfa/bfa_fcpim.c
index 8c703d8dc94b..33c8dd51f474 100644
--- a/drivers/scsi/bfa/bfa_fcpim.c
+++ b/drivers/scsi/bfa/bfa_fcpim.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
* All rights reserved
* www.brocade.com
*
@@ -15,18 +15,291 @@
* General Public License for more details.
*/
-#include <bfa.h>
-#include <log/bfa_log_hal.h>
+#include "bfa_modules.h"
+#include "bfa_cb_ioim.h"
BFA_TRC_FILE(HAL, FCPIM);
BFA_MODULE(fcpim);
+
+#define bfa_fcpim_add_iostats(__l, __r, __stats) \
+ (__l->__stats += __r->__stats)
+
+
+/**
+ * BFA ITNIM Related definitions
+ */
+static void bfa_itnim_update_del_itn_stats(struct bfa_itnim_s *itnim);
+
+#define BFA_ITNIM_FROM_TAG(_fcpim, _tag) \
+ (((_fcpim)->itnim_arr + ((_tag) & ((_fcpim)->num_itnims - 1))))
+
+#define bfa_fcpim_additn(__itnim) \
+ list_add_tail(&(__itnim)->qe, &(__itnim)->fcpim->itnim_q)
+#define bfa_fcpim_delitn(__itnim) do { \
+ bfa_assert(bfa_q_is_on_q(&(__itnim)->fcpim->itnim_q, __itnim)); \
+ bfa_itnim_update_del_itn_stats(__itnim); \
+ list_del(&(__itnim)->qe); \
+ bfa_assert(list_empty(&(__itnim)->io_q)); \
+ bfa_assert(list_empty(&(__itnim)->io_cleanup_q)); \
+ bfa_assert(list_empty(&(__itnim)->pending_q)); \
+} while (0)
+
+#define bfa_itnim_online_cb(__itnim) do { \
+ if ((__itnim)->bfa->fcs) \
+ bfa_cb_itnim_online((__itnim)->ditn); \
+ else { \
+ bfa_cb_queue((__itnim)->bfa, &(__itnim)->hcb_qe, \
+ __bfa_cb_itnim_online, (__itnim)); \
+ } \
+} while (0)
+
+#define bfa_itnim_offline_cb(__itnim) do { \
+ if ((__itnim)->bfa->fcs) \
+ bfa_cb_itnim_offline((__itnim)->ditn); \
+ else { \
+ bfa_cb_queue((__itnim)->bfa, &(__itnim)->hcb_qe, \
+ __bfa_cb_itnim_offline, (__itnim)); \
+ } \
+} while (0)
+
+#define bfa_itnim_sler_cb(__itnim) do { \
+ if ((__itnim)->bfa->fcs) \
+ bfa_cb_itnim_sler((__itnim)->ditn); \
+ else { \
+ bfa_cb_queue((__itnim)->bfa, &(__itnim)->hcb_qe, \
+ __bfa_cb_itnim_sler, (__itnim)); \
+ } \
+} while (0)
+
+/**
+ * bfa_itnim_sm BFA itnim state machine
+ */
+
+
+enum bfa_itnim_event {
+ BFA_ITNIM_SM_CREATE = 1, /* itnim is created */
+ BFA_ITNIM_SM_ONLINE = 2, /* itnim is online */
+ BFA_ITNIM_SM_OFFLINE = 3, /* itnim is offline */
+ BFA_ITNIM_SM_FWRSP = 4, /* firmware response */
+ BFA_ITNIM_SM_DELETE = 5, /* deleting an existing itnim */
+ BFA_ITNIM_SM_CLEANUP = 6, /* IO cleanup completion */
+ BFA_ITNIM_SM_SLER = 7, /* second level error recovery */
+ BFA_ITNIM_SM_HWFAIL = 8, /* IOC h/w failure event */
+ BFA_ITNIM_SM_QRESUME = 9, /* queue space available */
+};
+
+/**
+ * BFA IOIM related definitions
+ */
+#define bfa_ioim_move_to_comp_q(__ioim) do { \
+ list_del(&(__ioim)->qe); \
+ list_add_tail(&(__ioim)->qe, &(__ioim)->fcpim->ioim_comp_q); \
+} while (0)
+
+
+#define bfa_ioim_cb_profile_comp(__fcpim, __ioim) do { \
+ if ((__fcpim)->profile_comp) \
+ (__fcpim)->profile_comp(__ioim); \
+} while (0)
+
+#define bfa_ioim_cb_profile_start(__fcpim, __ioim) do { \
+ if ((__fcpim)->profile_start) \
+ (__fcpim)->profile_start(__ioim); \
+} while (0)
+/**
+ * hal_ioim_sm
+ */
+
+/**
+ * IO state machine events
+ */
+enum bfa_ioim_event {
+ BFA_IOIM_SM_START = 1, /* io start request from host */
+ BFA_IOIM_SM_COMP_GOOD = 2, /* io good comp, resource free */
+ BFA_IOIM_SM_COMP = 3, /* io comp, resource is free */
+ BFA_IOIM_SM_COMP_UTAG = 4, /* io comp, resource is free */
+ BFA_IOIM_SM_DONE = 5, /* io comp, resource not free */
+ BFA_IOIM_SM_FREE = 6, /* io resource is freed */
+ BFA_IOIM_SM_ABORT = 7, /* abort request from scsi stack */
+ BFA_IOIM_SM_ABORT_COMP = 8, /* abort from f/w */
+ BFA_IOIM_SM_ABORT_DONE = 9, /* abort completion from f/w */
+ BFA_IOIM_SM_QRESUME = 10, /* CQ space available to queue IO */
+ BFA_IOIM_SM_SGALLOCED = 11, /* SG page allocation successful */
+ BFA_IOIM_SM_SQRETRY = 12, /* sequence recovery retry */
+ BFA_IOIM_SM_HCB = 13, /* bfa callback complete */
+ BFA_IOIM_SM_CLEANUP = 14, /* IO cleanup from itnim */
+ BFA_IOIM_SM_TMSTART = 15, /* IO cleanup from tskim */
+ BFA_IOIM_SM_TMDONE = 16, /* IO cleanup from tskim */
+ BFA_IOIM_SM_HWFAIL = 17, /* IOC h/w failure event */
+ BFA_IOIM_SM_IOTOV = 18, /* ITN offline TOV */
+};
+
+
+/**
+ * BFA TSKIM related definitions
+ */
+
+/**
+ * task management completion handling
+ */
+#define bfa_tskim_qcomp(__tskim, __cbfn) do { \
+ bfa_cb_queue((__tskim)->bfa, &(__tskim)->hcb_qe, __cbfn, (__tskim));\
+ bfa_tskim_notify_comp(__tskim); \
+} while (0)
+
+#define bfa_tskim_notify_comp(__tskim) do { \
+ if ((__tskim)->notify) \
+ bfa_itnim_tskdone((__tskim)->itnim); \
+} while (0)
+
+
+enum bfa_tskim_event {
+ BFA_TSKIM_SM_START = 1, /* TM command start */
+ BFA_TSKIM_SM_DONE = 2, /* TM completion */
+ BFA_TSKIM_SM_QRESUME = 3, /* resume after qfull */
+ BFA_TSKIM_SM_HWFAIL = 5, /* IOC h/w failure event */
+ BFA_TSKIM_SM_HCB = 6, /* BFA callback completion */
+ BFA_TSKIM_SM_IOS_DONE = 7, /* IO and sub TM completions */
+ BFA_TSKIM_SM_CLEANUP = 8, /* TM cleanup on ITN offline */
+ BFA_TSKIM_SM_CLEANUP_DONE = 9, /* TM abort completion */
+};
+
+/**
+ * forward declaration for BFA ITNIM functions
+ */
+static void bfa_itnim_iocdisable_cleanup(struct bfa_itnim_s *itnim);
+static bfa_boolean_t bfa_itnim_send_fwcreate(struct bfa_itnim_s *itnim);
+static bfa_boolean_t bfa_itnim_send_fwdelete(struct bfa_itnim_s *itnim);
+static void bfa_itnim_cleanp_comp(void *itnim_cbarg);
+static void bfa_itnim_cleanup(struct bfa_itnim_s *itnim);
+static void __bfa_cb_itnim_online(void *cbarg, bfa_boolean_t complete);
+static void __bfa_cb_itnim_offline(void *cbarg, bfa_boolean_t complete);
+static void __bfa_cb_itnim_sler(void *cbarg, bfa_boolean_t complete);
+static void bfa_itnim_iotov_online(struct bfa_itnim_s *itnim);
+static void bfa_itnim_iotov_cleanup(struct bfa_itnim_s *itnim);
+static void bfa_itnim_iotov(void *itnim_arg);
+static void bfa_itnim_iotov_start(struct bfa_itnim_s *itnim);
+static void bfa_itnim_iotov_stop(struct bfa_itnim_s *itnim);
+static void bfa_itnim_iotov_delete(struct bfa_itnim_s *itnim);
+
+/**
+ * forward declaration of ITNIM state machine
+ */
+static void bfa_itnim_sm_uninit(struct bfa_itnim_s *itnim,
+ enum bfa_itnim_event event);
+static void bfa_itnim_sm_created(struct bfa_itnim_s *itnim,
+ enum bfa_itnim_event event);
+static void bfa_itnim_sm_fwcreate(struct bfa_itnim_s *itnim,
+ enum bfa_itnim_event event);
+static void bfa_itnim_sm_delete_pending(struct bfa_itnim_s *itnim,
+ enum bfa_itnim_event event);
+static void bfa_itnim_sm_online(struct bfa_itnim_s *itnim,
+ enum bfa_itnim_event event);
+static void bfa_itnim_sm_sler(struct bfa_itnim_s *itnim,
+ enum bfa_itnim_event event);
+static void bfa_itnim_sm_cleanup_offline(struct bfa_itnim_s *itnim,
+ enum bfa_itnim_event event);
+static void bfa_itnim_sm_cleanup_delete(struct bfa_itnim_s *itnim,
+ enum bfa_itnim_event event);
+static void bfa_itnim_sm_fwdelete(struct bfa_itnim_s *itnim,
+ enum bfa_itnim_event event);
+static void bfa_itnim_sm_offline(struct bfa_itnim_s *itnim,
+ enum bfa_itnim_event event);
+static void bfa_itnim_sm_iocdisable(struct bfa_itnim_s *itnim,
+ enum bfa_itnim_event event);
+static void bfa_itnim_sm_deleting(struct bfa_itnim_s *itnim,
+ enum bfa_itnim_event event);
+static void bfa_itnim_sm_fwcreate_qfull(struct bfa_itnim_s *itnim,
+ enum bfa_itnim_event event);
+static void bfa_itnim_sm_fwdelete_qfull(struct bfa_itnim_s *itnim,
+ enum bfa_itnim_event event);
+static void bfa_itnim_sm_deleting_qfull(struct bfa_itnim_s *itnim,
+ enum bfa_itnim_event event);
+
+/**
+ * forward declaration for BFA IOIM functions
+ */
+static bfa_boolean_t bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim);
+static bfa_boolean_t bfa_ioim_sge_setup(struct bfa_ioim_s *ioim);
+static void bfa_ioim_sgpg_setup(struct bfa_ioim_s *ioim);
+static bfa_boolean_t bfa_ioim_send_abort(struct bfa_ioim_s *ioim);
+static void bfa_ioim_notify_cleanup(struct bfa_ioim_s *ioim);
+static void __bfa_cb_ioim_good_comp(void *cbarg, bfa_boolean_t complete);
+static void __bfa_cb_ioim_comp(void *cbarg, bfa_boolean_t complete);
+static void __bfa_cb_ioim_abort(void *cbarg, bfa_boolean_t complete);
+static void __bfa_cb_ioim_failed(void *cbarg, bfa_boolean_t complete);
+static void __bfa_cb_ioim_pathtov(void *cbarg, bfa_boolean_t complete);
+static bfa_boolean_t bfa_ioim_is_abortable(struct bfa_ioim_s *ioim);
+
+
+/**
+ * forward declaration of BFA IO state machine
+ */
+static void bfa_ioim_sm_uninit(struct bfa_ioim_s *ioim,
+ enum bfa_ioim_event event);
+static void bfa_ioim_sm_sgalloc(struct bfa_ioim_s *ioim,
+ enum bfa_ioim_event event);
+static void bfa_ioim_sm_active(struct bfa_ioim_s *ioim,
+ enum bfa_ioim_event event);
+static void bfa_ioim_sm_abort(struct bfa_ioim_s *ioim,
+ enum bfa_ioim_event event);
+static void bfa_ioim_sm_cleanup(struct bfa_ioim_s *ioim,
+ enum bfa_ioim_event event);
+static void bfa_ioim_sm_qfull(struct bfa_ioim_s *ioim,
+ enum bfa_ioim_event event);
+static void bfa_ioim_sm_abort_qfull(struct bfa_ioim_s *ioim,
+ enum bfa_ioim_event event);
+static void bfa_ioim_sm_cleanup_qfull(struct bfa_ioim_s *ioim,
+ enum bfa_ioim_event event);
+static void bfa_ioim_sm_hcb(struct bfa_ioim_s *ioim,
+ enum bfa_ioim_event event);
+static void bfa_ioim_sm_hcb_free(struct bfa_ioim_s *ioim,
+ enum bfa_ioim_event event);
+static void bfa_ioim_sm_resfree(struct bfa_ioim_s *ioim,
+ enum bfa_ioim_event event);
+static void bfa_ioim_sm_cmnd_retry(struct bfa_ioim_s *ioim,
+ enum bfa_ioim_event event);
+
+/**
+ * forward declaration for BFA TSKIM functions
+ */
+static void __bfa_cb_tskim_done(void *cbarg, bfa_boolean_t complete);
+static void __bfa_cb_tskim_failed(void *cbarg, bfa_boolean_t complete);
+static bfa_boolean_t bfa_tskim_match_scope(struct bfa_tskim_s *tskim,
+ lun_t lun);
+static void bfa_tskim_gather_ios(struct bfa_tskim_s *tskim);
+static void bfa_tskim_cleanp_comp(void *tskim_cbarg);
+static void bfa_tskim_cleanup_ios(struct bfa_tskim_s *tskim);
+static bfa_boolean_t bfa_tskim_send(struct bfa_tskim_s *tskim);
+static bfa_boolean_t bfa_tskim_send_abort(struct bfa_tskim_s *tskim);
+static void bfa_tskim_iocdisable_ios(struct bfa_tskim_s *tskim);
+
+
+/**
+ * forward declaration of BFA TSKIM state machine
+ */
+static void bfa_tskim_sm_uninit(struct bfa_tskim_s *tskim,
+ enum bfa_tskim_event event);
+static void bfa_tskim_sm_active(struct bfa_tskim_s *tskim,
+ enum bfa_tskim_event event);
+static void bfa_tskim_sm_cleanup(struct bfa_tskim_s *tskim,
+ enum bfa_tskim_event event);
+static void bfa_tskim_sm_iocleanup(struct bfa_tskim_s *tskim,
+ enum bfa_tskim_event event);
+static void bfa_tskim_sm_qfull(struct bfa_tskim_s *tskim,
+ enum bfa_tskim_event event);
+static void bfa_tskim_sm_cleanup_qfull(struct bfa_tskim_s *tskim,
+ enum bfa_tskim_event event);
+static void bfa_tskim_sm_hcb(struct bfa_tskim_s *tskim,
+ enum bfa_tskim_event event);
+
/**
* hal_fcpim_mod BFA FCP Initiator Mode module
*/
/**
- * Compute and return memory needed by FCP(im) module.
+ * Compute and return memory needed by FCP(im) module.
*/
static void
bfa_fcpim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
@@ -58,7 +331,7 @@ bfa_fcpim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
static void
bfa_fcpim_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
- struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
+ struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
{
struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
@@ -67,12 +340,14 @@ bfa_fcpim_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
bfa_trc(bfa, cfg->fwcfg.num_ioim_reqs);
bfa_trc(bfa, cfg->fwcfg.num_tskim_reqs);
- fcpim->bfa = bfa;
- fcpim->num_itnims = cfg->fwcfg.num_rports;
+ fcpim->bfa = bfa;
+ fcpim->num_itnims = cfg->fwcfg.num_rports;
fcpim->num_ioim_reqs = cfg->fwcfg.num_ioim_reqs;
fcpim->num_tskim_reqs = cfg->fwcfg.num_tskim_reqs;
- fcpim->path_tov = cfg->drvcfg.path_tov;
- fcpim->delay_comp = cfg->drvcfg.delay_comp;
+ fcpim->path_tov = cfg->drvcfg.path_tov;
+ fcpim->delay_comp = cfg->drvcfg.delay_comp;
+ fcpim->profile_comp = NULL;
+ fcpim->profile_start = NULL;
bfa_itnim_attach(fcpim, meminfo);
bfa_tskim_attach(fcpim, meminfo);
@@ -103,7 +378,7 @@ bfa_fcpim_iocdisable(struct bfa_s *bfa)
{
struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
struct bfa_itnim_s *itnim;
- struct list_head *qe, *qen;
+ struct list_head *qe, *qen;
list_for_each_safe(qe, qen, &fcpim->itnim_q) {
itnim = (struct bfa_itnim_s *) qe;
@@ -112,6 +387,56 @@ bfa_fcpim_iocdisable(struct bfa_s *bfa)
}
void
+bfa_fcpim_add_stats(struct bfa_itnim_iostats_s *lstats,
+ struct bfa_itnim_iostats_s *rstats)
+{
+ bfa_fcpim_add_iostats(lstats, rstats, total_ios);
+ bfa_fcpim_add_iostats(lstats, rstats, qresumes);
+ bfa_fcpim_add_iostats(lstats, rstats, no_iotags);
+ bfa_fcpim_add_iostats(lstats, rstats, io_aborts);
+ bfa_fcpim_add_iostats(lstats, rstats, no_tskims);
+ bfa_fcpim_add_iostats(lstats, rstats, iocomp_ok);
+ bfa_fcpim_add_iostats(lstats, rstats, iocomp_underrun);
+ bfa_fcpim_add_iostats(lstats, rstats, iocomp_overrun);
+ bfa_fcpim_add_iostats(lstats, rstats, iocomp_aborted);
+ bfa_fcpim_add_iostats(lstats, rstats, iocomp_timedout);
+ bfa_fcpim_add_iostats(lstats, rstats, iocom_nexus_abort);
+ bfa_fcpim_add_iostats(lstats, rstats, iocom_proto_err);
+ bfa_fcpim_add_iostats(lstats, rstats, iocom_dif_err);
+ bfa_fcpim_add_iostats(lstats, rstats, iocom_sqer_needed);
+ bfa_fcpim_add_iostats(lstats, rstats, iocom_res_free);
+ bfa_fcpim_add_iostats(lstats, rstats, iocom_hostabrts);
+ bfa_fcpim_add_iostats(lstats, rstats, iocom_utags);
+ bfa_fcpim_add_iostats(lstats, rstats, io_cleanups);
+ bfa_fcpim_add_iostats(lstats, rstats, io_tmaborts);
+ bfa_fcpim_add_iostats(lstats, rstats, onlines);
+ bfa_fcpim_add_iostats(lstats, rstats, offlines);
+ bfa_fcpim_add_iostats(lstats, rstats, creates);
+ bfa_fcpim_add_iostats(lstats, rstats, deletes);
+ bfa_fcpim_add_iostats(lstats, rstats, create_comps);
+ bfa_fcpim_add_iostats(lstats, rstats, delete_comps);
+ bfa_fcpim_add_iostats(lstats, rstats, sler_events);
+ bfa_fcpim_add_iostats(lstats, rstats, fw_create);
+ bfa_fcpim_add_iostats(lstats, rstats, fw_delete);
+ bfa_fcpim_add_iostats(lstats, rstats, ioc_disabled);
+ bfa_fcpim_add_iostats(lstats, rstats, cleanup_comps);
+ bfa_fcpim_add_iostats(lstats, rstats, tm_cmnds);
+ bfa_fcpim_add_iostats(lstats, rstats, tm_fw_rsps);
+ bfa_fcpim_add_iostats(lstats, rstats, tm_success);
+ bfa_fcpim_add_iostats(lstats, rstats, tm_failures);
+ bfa_fcpim_add_iostats(lstats, rstats, tm_io_comps);
+ bfa_fcpim_add_iostats(lstats, rstats, tm_qresumes);
+ bfa_fcpim_add_iostats(lstats, rstats, tm_iocdowns);
+ bfa_fcpim_add_iostats(lstats, rstats, tm_cleanups);
+ bfa_fcpim_add_iostats(lstats, rstats, tm_cleanup_comps);
+ bfa_fcpim_add_iostats(lstats, rstats, io_comps);
+ bfa_fcpim_add_iostats(lstats, rstats, input_reqs);
+ bfa_fcpim_add_iostats(lstats, rstats, output_reqs);
+ bfa_fcpim_add_iostats(lstats, rstats, rd_throughput);
+ bfa_fcpim_add_iostats(lstats, rstats, wr_throughput);
+}
+
+void
bfa_fcpim_path_tov_set(struct bfa_s *bfa, u16 path_tov)
{
struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
@@ -130,21 +455,113 @@ bfa_fcpim_path_tov_get(struct bfa_s *bfa)
}
bfa_status_t
-bfa_fcpim_get_modstats(struct bfa_s *bfa, struct bfa_fcpim_stats_s *modstats)
+bfa_fcpim_port_iostats(struct bfa_s *bfa, struct bfa_itnim_iostats_s *stats,
+ u8 lp_tag)
+{
+ struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+ struct list_head *qe, *qen;
+ struct bfa_itnim_s *itnim;
+
+ /* accumulate IO stats from itnim */
+ bfa_os_memset(stats, 0, sizeof(struct bfa_itnim_iostats_s));
+ list_for_each_safe(qe, qen, &fcpim->itnim_q) {
+ itnim = (struct bfa_itnim_s *) qe;
+ if (itnim->rport->rport_info.lp_tag != lp_tag)
+ continue;
+ bfa_fcpim_add_stats(stats, &(itnim->stats));
+ }
+ return BFA_STATUS_OK;
+}
+bfa_status_t
+bfa_fcpim_get_modstats(struct bfa_s *bfa, struct bfa_itnim_iostats_s *modstats)
+{
+ struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+ struct list_head *qe, *qen;
+ struct bfa_itnim_s *itnim;
+
+ /* accumulate IO stats from itnim */
+ bfa_os_memset(modstats, 0, sizeof(struct bfa_itnim_iostats_s));
+ list_for_each_safe(qe, qen, &fcpim->itnim_q) {
+ itnim = (struct bfa_itnim_s *) qe;
+ bfa_fcpim_add_stats(modstats, &(itnim->stats));
+ }
+ return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_fcpim_get_del_itn_stats(struct bfa_s *bfa,
+ struct bfa_fcpim_del_itn_stats_s *modstats)
{
struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
- *modstats = fcpim->stats;
+ *modstats = fcpim->del_itn_stats;
return BFA_STATUS_OK;
}
+
+bfa_status_t
+bfa_fcpim_profile_on(struct bfa_s *bfa, u32 time)
+{
+ struct bfa_itnim_s *itnim;
+ struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+ struct list_head *qe, *qen;
+
+ /* accumulate IO stats from itnim */
+ list_for_each_safe(qe, qen, &fcpim->itnim_q) {
+ itnim = (struct bfa_itnim_s *) qe;
+ bfa_itnim_clear_stats(itnim);
+ }
+ fcpim->io_profile = BFA_TRUE;
+ fcpim->io_profile_start_time = time;
+ fcpim->profile_comp = bfa_ioim_profile_comp;
+ fcpim->profile_start = bfa_ioim_profile_start;
+
+ return BFA_STATUS_OK;
+}
+bfa_status_t
+bfa_fcpim_profile_off(struct bfa_s *bfa)
+{
+ struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+ fcpim->io_profile = BFA_FALSE;
+ fcpim->io_profile_start_time = 0;
+ fcpim->profile_comp = NULL;
+ fcpim->profile_start = NULL;
+ return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_fcpim_port_clear_iostats(struct bfa_s *bfa, u8 lp_tag)
+{
+ struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+ struct list_head *qe, *qen;
+ struct bfa_itnim_s *itnim;
+
+ /* clear IO stats from all active itnims */
+ list_for_each_safe(qe, qen, &fcpim->itnim_q) {
+ itnim = (struct bfa_itnim_s *) qe;
+ if (itnim->rport->rport_info.lp_tag != lp_tag)
+ continue;
+ bfa_itnim_clear_stats(itnim);
+ }
+ return BFA_STATUS_OK;
+
+}
+
bfa_status_t
bfa_fcpim_clr_modstats(struct bfa_s *bfa)
{
struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+ struct list_head *qe, *qen;
+ struct bfa_itnim_s *itnim;
- memset(&fcpim->stats, 0, sizeof(struct bfa_fcpim_stats_s));
+ /* clear IO stats from all active itnims */
+ list_for_each_safe(qe, qen, &fcpim->itnim_q) {
+ itnim = (struct bfa_itnim_s *) qe;
+ bfa_itnim_clear_stats(itnim);
+ }
+ bfa_os_memset(&fcpim->del_itn_stats, 0,
+ sizeof(struct bfa_fcpim_del_itn_stats_s));
return BFA_STATUS_OK;
}
@@ -176,14 +593,6 @@ bfa_fcpim_update_ioredirect(struct bfa_s *bfa)
* IO redirection is turned off when QoS is enabled and vice versa
*/
ioredirect = bfa_fcport_is_qos_enabled(bfa) ? BFA_FALSE : BFA_TRUE;
-
- /*
- * Notify the bfad module of a possible state change in
- * IO redirection capability, due to a QoS state change. bfad will
- * check on the support for io redirection and update the
- * fcpim's ioredirect state accordingly.
- */
- bfa_cb_ioredirect_state_change((void *)(bfa->bfad), ioredirect);
}
void
@@ -192,3 +601,3012 @@ bfa_fcpim_set_ioredirect(struct bfa_s *bfa, bfa_boolean_t state)
struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
fcpim->ioredirect = state;
}
+
+
+
+/**
+ * BFA ITNIM module state machine functions
+ */
+
+/**
+ * Beginning/unallocated state - no events expected.
+ */
+static void
+bfa_itnim_sm_uninit(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
+{
+ bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+ bfa_trc(itnim->bfa, event);
+
+ switch (event) {
+ case BFA_ITNIM_SM_CREATE:
+ bfa_sm_set_state(itnim, bfa_itnim_sm_created);
+ itnim->is_online = BFA_FALSE;
+ bfa_fcpim_additn(itnim);
+ break;
+
+ default:
+ bfa_sm_fault(itnim->bfa, event);
+ }
+}
+
+/**
+ * Beginning state, only online event expected.
+ */
+static void
+bfa_itnim_sm_created(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
+{
+ bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+ bfa_trc(itnim->bfa, event);
+
+ switch (event) {
+ case BFA_ITNIM_SM_ONLINE:
+ if (bfa_itnim_send_fwcreate(itnim))
+ bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate);
+ else
+ bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate_qfull);
+ break;
+
+ case BFA_ITNIM_SM_DELETE:
+ bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
+ bfa_fcpim_delitn(itnim);
+ break;
+
+ case BFA_ITNIM_SM_HWFAIL:
+ bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
+ break;
+
+ default:
+ bfa_sm_fault(itnim->bfa, event);
+ }
+}
+
+/**
+ * Waiting for itnim create response from firmware.
+ */
+static void
+bfa_itnim_sm_fwcreate(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
+{
+ bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+ bfa_trc(itnim->bfa, event);
+
+ switch (event) {
+ case BFA_ITNIM_SM_FWRSP:
+ bfa_sm_set_state(itnim, bfa_itnim_sm_online);
+ itnim->is_online = BFA_TRUE;
+ bfa_itnim_iotov_online(itnim);
+ bfa_itnim_online_cb(itnim);
+ break;
+
+ case BFA_ITNIM_SM_DELETE:
+ bfa_sm_set_state(itnim, bfa_itnim_sm_delete_pending);
+ break;
+
+ case BFA_ITNIM_SM_OFFLINE:
+ if (bfa_itnim_send_fwdelete(itnim))
+ bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete);
+ else
+ bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete_qfull);
+ break;
+
+ case BFA_ITNIM_SM_HWFAIL:
+ bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
+ break;
+
+ default:
+ bfa_sm_fault(itnim->bfa, event);
+ }
+}
+
+static void
+bfa_itnim_sm_fwcreate_qfull(struct bfa_itnim_s *itnim,
+ enum bfa_itnim_event event)
+{
+ bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+ bfa_trc(itnim->bfa, event);
+
+ switch (event) {
+ case BFA_ITNIM_SM_QRESUME:
+ bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate);
+ bfa_itnim_send_fwcreate(itnim);
+ break;
+
+ case BFA_ITNIM_SM_DELETE:
+ bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
+ bfa_reqq_wcancel(&itnim->reqq_wait);
+ bfa_fcpim_delitn(itnim);
+ break;
+
+ case BFA_ITNIM_SM_OFFLINE:
+ bfa_sm_set_state(itnim, bfa_itnim_sm_offline);
+ bfa_reqq_wcancel(&itnim->reqq_wait);
+ bfa_itnim_offline_cb(itnim);
+ break;
+
+ case BFA_ITNIM_SM_HWFAIL:
+ bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
+ bfa_reqq_wcancel(&itnim->reqq_wait);
+ break;
+
+ default:
+ bfa_sm_fault(itnim->bfa, event);
+ }
+}
+
+/**
+ * Waiting for itnim create response from firmware, a delete is pending.
+ */
+static void
+bfa_itnim_sm_delete_pending(struct bfa_itnim_s *itnim,
+ enum bfa_itnim_event event)
+{
+ bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+ bfa_trc(itnim->bfa, event);
+
+ switch (event) {
+ case BFA_ITNIM_SM_FWRSP:
+ if (bfa_itnim_send_fwdelete(itnim))
+ bfa_sm_set_state(itnim, bfa_itnim_sm_deleting);
+ else
+ bfa_sm_set_state(itnim, bfa_itnim_sm_deleting_qfull);
+ break;
+
+ case BFA_ITNIM_SM_HWFAIL:
+ bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
+ bfa_fcpim_delitn(itnim);
+ break;
+
+ default:
+ bfa_sm_fault(itnim->bfa, event);
+ }
+}
+
+/**
+ * Online state - normal parking state.
+ */
+static void
+bfa_itnim_sm_online(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
+{
+ bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+ bfa_trc(itnim->bfa, event);
+
+ switch (event) {
+ case BFA_ITNIM_SM_OFFLINE:
+ bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_offline);
+ itnim->is_online = BFA_FALSE;
+ bfa_itnim_iotov_start(itnim);
+ bfa_itnim_cleanup(itnim);
+ break;
+
+ case BFA_ITNIM_SM_DELETE:
+ bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_delete);
+ itnim->is_online = BFA_FALSE;
+ bfa_itnim_cleanup(itnim);
+ break;
+
+ case BFA_ITNIM_SM_SLER:
+ bfa_sm_set_state(itnim, bfa_itnim_sm_sler);
+ itnim->is_online = BFA_FALSE;
+ bfa_itnim_iotov_start(itnim);
+ bfa_itnim_sler_cb(itnim);
+ break;
+
+ case BFA_ITNIM_SM_HWFAIL:
+ bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
+ itnim->is_online = BFA_FALSE;
+ bfa_itnim_iotov_start(itnim);
+ bfa_itnim_iocdisable_cleanup(itnim);
+ break;
+
+ default:
+ bfa_sm_fault(itnim->bfa, event);
+ }
+}
+
+/**
+ * Second level error recovery need.
+ */
+static void
+bfa_itnim_sm_sler(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
+{
+ bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+ bfa_trc(itnim->bfa, event);
+
+ switch (event) {
+ case BFA_ITNIM_SM_OFFLINE:
+ bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_offline);
+ bfa_itnim_cleanup(itnim);
+ break;
+
+ case BFA_ITNIM_SM_DELETE:
+ bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_delete);
+ bfa_itnim_cleanup(itnim);
+ bfa_itnim_iotov_delete(itnim);
+ break;
+
+ case BFA_ITNIM_SM_HWFAIL:
+ bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
+ bfa_itnim_iocdisable_cleanup(itnim);
+ break;
+
+ default:
+ bfa_sm_fault(itnim->bfa, event);
+ }
+}
+
+/**
+ * Going offline. Waiting for active IO cleanup.
+ */
+static void
+bfa_itnim_sm_cleanup_offline(struct bfa_itnim_s *itnim,
+ enum bfa_itnim_event event)
+{
+ bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+ bfa_trc(itnim->bfa, event);
+
+ switch (event) {
+ case BFA_ITNIM_SM_CLEANUP:
+ if (bfa_itnim_send_fwdelete(itnim))
+ bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete);
+ else
+ bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete_qfull);
+ break;
+
+ case BFA_ITNIM_SM_DELETE:
+ bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_delete);
+ bfa_itnim_iotov_delete(itnim);
+ break;
+
+ case BFA_ITNIM_SM_HWFAIL:
+ bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
+ bfa_itnim_iocdisable_cleanup(itnim);
+ bfa_itnim_offline_cb(itnim);
+ break;
+
+ case BFA_ITNIM_SM_SLER:
+ break;
+
+ default:
+ bfa_sm_fault(itnim->bfa, event);
+ }
+}
+
+/**
+ * Deleting itnim. Waiting for active IO cleanup.
+ */
+static void
+bfa_itnim_sm_cleanup_delete(struct bfa_itnim_s *itnim,
+ enum bfa_itnim_event event)
+{
+ bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+ bfa_trc(itnim->bfa, event);
+
+ switch (event) {
+ case BFA_ITNIM_SM_CLEANUP:
+ if (bfa_itnim_send_fwdelete(itnim))
+ bfa_sm_set_state(itnim, bfa_itnim_sm_deleting);
+ else
+ bfa_sm_set_state(itnim, bfa_itnim_sm_deleting_qfull);
+ break;
+
+ case BFA_ITNIM_SM_HWFAIL:
+ bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
+ bfa_itnim_iocdisable_cleanup(itnim);
+ break;
+
+ default:
+ bfa_sm_fault(itnim->bfa, event);
+ }
+}
+
+/**
+ * Rport offline. Fimrware itnim is being deleted - awaiting f/w response.
+ */
+static void
+bfa_itnim_sm_fwdelete(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
+{
+ bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+ bfa_trc(itnim->bfa, event);
+
+ switch (event) {
+ case BFA_ITNIM_SM_FWRSP:
+ bfa_sm_set_state(itnim, bfa_itnim_sm_offline);
+ bfa_itnim_offline_cb(itnim);
+ break;
+
+ case BFA_ITNIM_SM_DELETE:
+ bfa_sm_set_state(itnim, bfa_itnim_sm_deleting);
+ break;
+
+ case BFA_ITNIM_SM_HWFAIL:
+ bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
+ bfa_itnim_offline_cb(itnim);
+ break;
+
+ default:
+ bfa_sm_fault(itnim->bfa, event);
+ }
+}
+
+static void
+bfa_itnim_sm_fwdelete_qfull(struct bfa_itnim_s *itnim,
+ enum bfa_itnim_event event)
+{
+ bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+ bfa_trc(itnim->bfa, event);
+
+ switch (event) {
+ case BFA_ITNIM_SM_QRESUME:
+ bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete);
+ bfa_itnim_send_fwdelete(itnim);
+ break;
+
+ case BFA_ITNIM_SM_DELETE:
+ bfa_sm_set_state(itnim, bfa_itnim_sm_deleting_qfull);
+ break;
+
+ case BFA_ITNIM_SM_HWFAIL:
+ bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
+ bfa_reqq_wcancel(&itnim->reqq_wait);
+ bfa_itnim_offline_cb(itnim);
+ break;
+
+ default:
+ bfa_sm_fault(itnim->bfa, event);
+ }
+}
+
+/**
+ * Offline state.
+ */
+static void
+bfa_itnim_sm_offline(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
+{
+ bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+ bfa_trc(itnim->bfa, event);
+
+ switch (event) {
+ case BFA_ITNIM_SM_DELETE:
+ bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
+ bfa_itnim_iotov_delete(itnim);
+ bfa_fcpim_delitn(itnim);
+ break;
+
+ case BFA_ITNIM_SM_ONLINE:
+ if (bfa_itnim_send_fwcreate(itnim))
+ bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate);
+ else
+ bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate_qfull);
+ break;
+
+ case BFA_ITNIM_SM_HWFAIL:
+ bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
+ break;
+
+ default:
+ bfa_sm_fault(itnim->bfa, event);
+ }
+}
+
+/**
+ * IOC h/w failed state.
+ */
+static void
+bfa_itnim_sm_iocdisable(struct bfa_itnim_s *itnim,
+ enum bfa_itnim_event event)
+{
+ bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+ bfa_trc(itnim->bfa, event);
+
+ switch (event) {
+ case BFA_ITNIM_SM_DELETE:
+ bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
+ bfa_itnim_iotov_delete(itnim);
+ bfa_fcpim_delitn(itnim);
+ break;
+
+ case BFA_ITNIM_SM_OFFLINE:
+ bfa_itnim_offline_cb(itnim);
+ break;
+
+ case BFA_ITNIM_SM_ONLINE:
+ if (bfa_itnim_send_fwcreate(itnim))
+ bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate);
+ else
+ bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate_qfull);
+ break;
+
+ case BFA_ITNIM_SM_HWFAIL:
+ break;
+
+ default:
+ bfa_sm_fault(itnim->bfa, event);
+ }
+}
+
+/**
+ * Itnim is deleted, waiting for firmware response to delete.
+ */
+static void
+bfa_itnim_sm_deleting(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
+{
+ bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+ bfa_trc(itnim->bfa, event);
+
+ switch (event) {
+ case BFA_ITNIM_SM_FWRSP:
+ case BFA_ITNIM_SM_HWFAIL:
+ bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
+ bfa_fcpim_delitn(itnim);
+ break;
+
+ default:
+ bfa_sm_fault(itnim->bfa, event);
+ }
+}
+
+static void
+bfa_itnim_sm_deleting_qfull(struct bfa_itnim_s *itnim,
+ enum bfa_itnim_event event)
+{
+ bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+ bfa_trc(itnim->bfa, event);
+
+ switch (event) {
+ case BFA_ITNIM_SM_QRESUME:
+ bfa_sm_set_state(itnim, bfa_itnim_sm_deleting);
+ bfa_itnim_send_fwdelete(itnim);
+ break;
+
+ case BFA_ITNIM_SM_HWFAIL:
+ bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
+ bfa_reqq_wcancel(&itnim->reqq_wait);
+ bfa_fcpim_delitn(itnim);
+ break;
+
+ default:
+ bfa_sm_fault(itnim->bfa, event);
+ }
+}
+
+/**
+ * Initiate cleanup of all IOs on an IOC failure.
+ */
+static void
+bfa_itnim_iocdisable_cleanup(struct bfa_itnim_s *itnim)
+{
+ struct bfa_tskim_s *tskim;
+ struct bfa_ioim_s *ioim;
+ struct list_head *qe, *qen;
+
+ list_for_each_safe(qe, qen, &itnim->tsk_q) {
+ tskim = (struct bfa_tskim_s *) qe;
+ bfa_tskim_iocdisable(tskim);
+ }
+
+ list_for_each_safe(qe, qen, &itnim->io_q) {
+ ioim = (struct bfa_ioim_s *) qe;
+ bfa_ioim_iocdisable(ioim);
+ }
+
+ /**
+ * For IO request in pending queue, we pretend an early timeout.
+ */
+ list_for_each_safe(qe, qen, &itnim->pending_q) {
+ ioim = (struct bfa_ioim_s *) qe;
+ bfa_ioim_tov(ioim);
+ }
+
+ list_for_each_safe(qe, qen, &itnim->io_cleanup_q) {
+ ioim = (struct bfa_ioim_s *) qe;
+ bfa_ioim_iocdisable(ioim);
+ }
+}
+
+/**
+ * IO cleanup completion
+ */
+static void
+bfa_itnim_cleanp_comp(void *itnim_cbarg)
+{
+ struct bfa_itnim_s *itnim = itnim_cbarg;
+
+ bfa_stats(itnim, cleanup_comps);
+ bfa_sm_send_event(itnim, BFA_ITNIM_SM_CLEANUP);
+}
+
+/**
+ * Initiate cleanup of all IOs.
+ */
+static void
+bfa_itnim_cleanup(struct bfa_itnim_s *itnim)
+{
+ struct bfa_ioim_s *ioim;
+ struct bfa_tskim_s *tskim;
+ struct list_head *qe, *qen;
+
+ bfa_wc_init(&itnim->wc, bfa_itnim_cleanp_comp, itnim);
+
+ list_for_each_safe(qe, qen, &itnim->io_q) {
+ ioim = (struct bfa_ioim_s *) qe;
+
+ /**
+ * Move IO to a cleanup queue from active queue so that a later
+ * TM will not pickup this IO.
+ */
+ list_del(&ioim->qe);
+ list_add_tail(&ioim->qe, &itnim->io_cleanup_q);
+
+ bfa_wc_up(&itnim->wc);
+ bfa_ioim_cleanup(ioim);
+ }
+
+ list_for_each_safe(qe, qen, &itnim->tsk_q) {
+ tskim = (struct bfa_tskim_s *) qe;
+ bfa_wc_up(&itnim->wc);
+ bfa_tskim_cleanup(tskim);
+ }
+
+ bfa_wc_wait(&itnim->wc);
+}
+
+static void
+__bfa_cb_itnim_online(void *cbarg, bfa_boolean_t complete)
+{
+ struct bfa_itnim_s *itnim = cbarg;
+
+ if (complete)
+ bfa_cb_itnim_online(itnim->ditn);
+}
+
+static void
+__bfa_cb_itnim_offline(void *cbarg, bfa_boolean_t complete)
+{
+ struct bfa_itnim_s *itnim = cbarg;
+
+ if (complete)
+ bfa_cb_itnim_offline(itnim->ditn);
+}
+
+static void
+__bfa_cb_itnim_sler(void *cbarg, bfa_boolean_t complete)
+{
+ struct bfa_itnim_s *itnim = cbarg;
+
+ if (complete)
+ bfa_cb_itnim_sler(itnim->ditn);
+}
+
+/**
+ * Call to resume any I/O requests waiting for room in request queue.
+ */
+static void
+bfa_itnim_qresume(void *cbarg)
+{
+ struct bfa_itnim_s *itnim = cbarg;
+
+ bfa_sm_send_event(itnim, BFA_ITNIM_SM_QRESUME);
+}
+
+
+
+
+/**
+ * bfa_itnim_public
+ */
+
+void
+bfa_itnim_iodone(struct bfa_itnim_s *itnim)
+{
+ bfa_wc_down(&itnim->wc);
+}
+
+void
+bfa_itnim_tskdone(struct bfa_itnim_s *itnim)
+{
+ bfa_wc_down(&itnim->wc);
+}
+
+void
+bfa_itnim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
+ u32 *dm_len)
+{
+ /**
+ * ITN memory
+ */
+ *km_len += cfg->fwcfg.num_rports * sizeof(struct bfa_itnim_s);
+}
+
+void
+bfa_itnim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
+{
+ struct bfa_s *bfa = fcpim->bfa;
+ struct bfa_itnim_s *itnim;
+ int i, j;
+
+ INIT_LIST_HEAD(&fcpim->itnim_q);
+
+ itnim = (struct bfa_itnim_s *) bfa_meminfo_kva(minfo);
+ fcpim->itnim_arr = itnim;
+
+ for (i = 0; i < fcpim->num_itnims; i++, itnim++) {
+ bfa_os_memset(itnim, 0, sizeof(struct bfa_itnim_s));
+ itnim->bfa = bfa;
+ itnim->fcpim = fcpim;
+ itnim->reqq = BFA_REQQ_QOS_LO;
+ itnim->rport = BFA_RPORT_FROM_TAG(bfa, i);
+ itnim->iotov_active = BFA_FALSE;
+ bfa_reqq_winit(&itnim->reqq_wait, bfa_itnim_qresume, itnim);
+
+ INIT_LIST_HEAD(&itnim->io_q);
+ INIT_LIST_HEAD(&itnim->io_cleanup_q);
+ INIT_LIST_HEAD(&itnim->pending_q);
+ INIT_LIST_HEAD(&itnim->tsk_q);
+ INIT_LIST_HEAD(&itnim->delay_comp_q);
+ for (j = 0; j < BFA_IOBUCKET_MAX; j++)
+ itnim->ioprofile.io_latency.min[j] = ~0;
+ bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
+ }
+
+ bfa_meminfo_kva(minfo) = (u8 *) itnim;
+}
+
+void
+bfa_itnim_iocdisable(struct bfa_itnim_s *itnim)
+{
+ bfa_stats(itnim, ioc_disabled);
+ bfa_sm_send_event(itnim, BFA_ITNIM_SM_HWFAIL);
+}
+
+static bfa_boolean_t
+bfa_itnim_send_fwcreate(struct bfa_itnim_s *itnim)
+{
+ struct bfi_itnim_create_req_s *m;
+
+ itnim->msg_no++;
+
+ /**
+ * check for room in queue to send request now
+ */
+ m = bfa_reqq_next(itnim->bfa, itnim->reqq);
+ if (!m) {
+ bfa_reqq_wait(itnim->bfa, itnim->reqq, &itnim->reqq_wait);
+ return BFA_FALSE;
+ }
+
+ bfi_h2i_set(m->mh, BFI_MC_ITNIM, BFI_ITNIM_H2I_CREATE_REQ,
+ bfa_lpuid(itnim->bfa));
+ m->fw_handle = itnim->rport->fw_handle;
+ m->class = FC_CLASS_3;
+ m->seq_rec = itnim->seq_rec;
+ m->msg_no = itnim->msg_no;
+ bfa_stats(itnim, fw_create);
+
+ /**
+ * queue I/O message to firmware
+ */
+ bfa_reqq_produce(itnim->bfa, itnim->reqq);
+ return BFA_TRUE;
+}
+
+static bfa_boolean_t
+bfa_itnim_send_fwdelete(struct bfa_itnim_s *itnim)
+{
+ struct bfi_itnim_delete_req_s *m;
+
+ /**
+ * check for room in queue to send request now
+ */
+ m = bfa_reqq_next(itnim->bfa, itnim->reqq);
+ if (!m) {
+ bfa_reqq_wait(itnim->bfa, itnim->reqq, &itnim->reqq_wait);
+ return BFA_FALSE;
+ }
+
+ bfi_h2i_set(m->mh, BFI_MC_ITNIM, BFI_ITNIM_H2I_DELETE_REQ,
+ bfa_lpuid(itnim->bfa));
+ m->fw_handle = itnim->rport->fw_handle;
+ bfa_stats(itnim, fw_delete);
+
+ /**
+ * queue I/O message to firmware
+ */
+ bfa_reqq_produce(itnim->bfa, itnim->reqq);
+ return BFA_TRUE;
+}
+
+/**
+ * Cleanup all pending failed inflight requests.
+ */
+static void
+bfa_itnim_delayed_comp(struct bfa_itnim_s *itnim, bfa_boolean_t iotov)
+{
+ struct bfa_ioim_s *ioim;
+ struct list_head *qe, *qen;
+
+ list_for_each_safe(qe, qen, &itnim->delay_comp_q) {
+ ioim = (struct bfa_ioim_s *)qe;
+ bfa_ioim_delayed_comp(ioim, iotov);
+ }
+}
+
+/**
+ * Start all pending IO requests.
+ */
+static void
+bfa_itnim_iotov_online(struct bfa_itnim_s *itnim)
+{
+ struct bfa_ioim_s *ioim;
+
+ bfa_itnim_iotov_stop(itnim);
+
+ /**
+ * Abort all inflight IO requests in the queue
+ */
+ bfa_itnim_delayed_comp(itnim, BFA_FALSE);
+
+ /**
+ * Start all pending IO requests.
+ */
+ while (!list_empty(&itnim->pending_q)) {
+ bfa_q_deq(&itnim->pending_q, &ioim);
+ list_add_tail(&ioim->qe, &itnim->io_q);
+ bfa_ioim_start(ioim);
+ }
+}
+
+/**
+ * Fail all pending IO requests
+ */
+static void
+bfa_itnim_iotov_cleanup(struct bfa_itnim_s *itnim)
+{
+ struct bfa_ioim_s *ioim;
+
+ /**
+ * Fail all inflight IO requests in the queue
+ */
+ bfa_itnim_delayed_comp(itnim, BFA_TRUE);
+
+ /**
+ * Fail any pending IO requests.
+ */
+ while (!list_empty(&itnim->pending_q)) {
+ bfa_q_deq(&itnim->pending_q, &ioim);
+ list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
+ bfa_ioim_tov(ioim);
+ }
+}
+
+/**
+ * IO TOV timer callback. Fail any pending IO requests.
+ */
+static void
+bfa_itnim_iotov(void *itnim_arg)
+{
+ struct bfa_itnim_s *itnim = itnim_arg;
+
+ itnim->iotov_active = BFA_FALSE;
+
+ bfa_cb_itnim_tov_begin(itnim->ditn);
+ bfa_itnim_iotov_cleanup(itnim);
+ bfa_cb_itnim_tov(itnim->ditn);
+}
+
+/**
+ * Start IO TOV timer for failing back pending IO requests in offline state.
+ */
+static void
+bfa_itnim_iotov_start(struct bfa_itnim_s *itnim)
+{
+ if (itnim->fcpim->path_tov > 0) {
+
+ itnim->iotov_active = BFA_TRUE;
+ bfa_assert(bfa_itnim_hold_io(itnim));
+ bfa_timer_start(itnim->bfa, &itnim->timer,
+ bfa_itnim_iotov, itnim, itnim->fcpim->path_tov);
+ }
+}
+
+/**
+ * Stop IO TOV timer.
+ */
+static void
+bfa_itnim_iotov_stop(struct bfa_itnim_s *itnim)
+{
+ if (itnim->iotov_active) {
+ itnim->iotov_active = BFA_FALSE;
+ bfa_timer_stop(&itnim->timer);
+ }
+}
+
+/**
+ * Stop IO TOV timer.
+ */
+static void
+bfa_itnim_iotov_delete(struct bfa_itnim_s *itnim)
+{
+ bfa_boolean_t pathtov_active = BFA_FALSE;
+
+ if (itnim->iotov_active)
+ pathtov_active = BFA_TRUE;
+
+ bfa_itnim_iotov_stop(itnim);
+ if (pathtov_active)
+ bfa_cb_itnim_tov_begin(itnim->ditn);
+ bfa_itnim_iotov_cleanup(itnim);
+ if (pathtov_active)
+ bfa_cb_itnim_tov(itnim->ditn);
+}
+
+static void
+bfa_itnim_update_del_itn_stats(struct bfa_itnim_s *itnim)
+{
+ struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(itnim->bfa);
+ fcpim->del_itn_stats.del_itn_iocomp_aborted +=
+ itnim->stats.iocomp_aborted;
+ fcpim->del_itn_stats.del_itn_iocomp_timedout +=
+ itnim->stats.iocomp_timedout;
+ fcpim->del_itn_stats.del_itn_iocom_sqer_needed +=
+ itnim->stats.iocom_sqer_needed;
+ fcpim->del_itn_stats.del_itn_iocom_res_free +=
+ itnim->stats.iocom_res_free;
+ fcpim->del_itn_stats.del_itn_iocom_hostabrts +=
+ itnim->stats.iocom_hostabrts;
+ fcpim->del_itn_stats.del_itn_total_ios += itnim->stats.total_ios;
+ fcpim->del_itn_stats.del_io_iocdowns += itnim->stats.io_iocdowns;
+ fcpim->del_itn_stats.del_tm_iocdowns += itnim->stats.tm_iocdowns;
+}
+
+
+
+/**
+ * bfa_itnim_public
+ */
+
+/**
+ * Itnim interrupt processing.
+ */
+void
+bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
+{
+ struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+ union bfi_itnim_i2h_msg_u msg;
+ struct bfa_itnim_s *itnim;
+
+ bfa_trc(bfa, m->mhdr.msg_id);
+
+ msg.msg = m;
+
+ switch (m->mhdr.msg_id) {
+ case BFI_ITNIM_I2H_CREATE_RSP:
+ itnim = BFA_ITNIM_FROM_TAG(fcpim,
+ msg.create_rsp->bfa_handle);
+ bfa_assert(msg.create_rsp->status == BFA_STATUS_OK);
+ bfa_stats(itnim, create_comps);
+ bfa_sm_send_event(itnim, BFA_ITNIM_SM_FWRSP);
+ break;
+
+ case BFI_ITNIM_I2H_DELETE_RSP:
+ itnim = BFA_ITNIM_FROM_TAG(fcpim,
+ msg.delete_rsp->bfa_handle);
+ bfa_assert(msg.delete_rsp->status == BFA_STATUS_OK);
+ bfa_stats(itnim, delete_comps);
+ bfa_sm_send_event(itnim, BFA_ITNIM_SM_FWRSP);
+ break;
+
+ case BFI_ITNIM_I2H_SLER_EVENT:
+ itnim = BFA_ITNIM_FROM_TAG(fcpim,
+ msg.sler_event->bfa_handle);
+ bfa_stats(itnim, sler_events);
+ bfa_sm_send_event(itnim, BFA_ITNIM_SM_SLER);
+ break;
+
+ default:
+ bfa_trc(bfa, m->mhdr.msg_id);
+ bfa_assert(0);
+ }
+}
+
+
+
+/**
+ * bfa_itnim_api
+ */
+
+struct bfa_itnim_s *
+bfa_itnim_create(struct bfa_s *bfa, struct bfa_rport_s *rport, void *ditn)
+{
+ struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+ struct bfa_itnim_s *itnim;
+
+ itnim = BFA_ITNIM_FROM_TAG(fcpim, rport->rport_tag);
+ bfa_assert(itnim->rport == rport);
+
+ itnim->ditn = ditn;
+
+ bfa_stats(itnim, creates);
+ bfa_sm_send_event(itnim, BFA_ITNIM_SM_CREATE);
+
+ return itnim;
+}
+
+void
+bfa_itnim_delete(struct bfa_itnim_s *itnim)
+{
+ bfa_stats(itnim, deletes);
+ bfa_sm_send_event(itnim, BFA_ITNIM_SM_DELETE);
+}
+
+void
+bfa_itnim_online(struct bfa_itnim_s *itnim, bfa_boolean_t seq_rec)
+{
+ itnim->seq_rec = seq_rec;
+ bfa_stats(itnim, onlines);
+ bfa_sm_send_event(itnim, BFA_ITNIM_SM_ONLINE);
+}
+
+void
+bfa_itnim_offline(struct bfa_itnim_s *itnim)
+{
+ bfa_stats(itnim, offlines);
+ bfa_sm_send_event(itnim, BFA_ITNIM_SM_OFFLINE);
+}
+
+/**
+ * Return true if itnim is considered offline for holding off IO request.
+ * IO is not held if itnim is being deleted.
+ */
+bfa_boolean_t
+bfa_itnim_hold_io(struct bfa_itnim_s *itnim)
+{
+ return itnim->fcpim->path_tov && itnim->iotov_active &&
+ (bfa_sm_cmp_state(itnim, bfa_itnim_sm_fwcreate) ||
+ bfa_sm_cmp_state(itnim, bfa_itnim_sm_sler) ||
+ bfa_sm_cmp_state(itnim, bfa_itnim_sm_cleanup_offline) ||
+ bfa_sm_cmp_state(itnim, bfa_itnim_sm_fwdelete) ||
+ bfa_sm_cmp_state(itnim, bfa_itnim_sm_offline) ||
+ bfa_sm_cmp_state(itnim, bfa_itnim_sm_iocdisable));
+}
+
+bfa_status_t
+bfa_itnim_get_ioprofile(struct bfa_itnim_s *itnim,
+ struct bfa_itnim_ioprofile_s *ioprofile)
+{
+ struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(itnim->bfa);
+ if (!fcpim->io_profile)
+ return BFA_STATUS_IOPROFILE_OFF;
+
+ itnim->ioprofile.index = BFA_IOBUCKET_MAX;
+ itnim->ioprofile.io_profile_start_time =
+ bfa_io_profile_start_time(itnim->bfa);
+ itnim->ioprofile.clock_res_mul = bfa_io_lat_clock_res_mul;
+ itnim->ioprofile.clock_res_div = bfa_io_lat_clock_res_div;
+ *ioprofile = itnim->ioprofile;
+
+ return BFA_STATUS_OK;
+}
+
+void
+bfa_itnim_get_stats(struct bfa_itnim_s *itnim,
+ struct bfa_itnim_iostats_s *stats)
+{
+ *stats = itnim->stats;
+}
+
+void
+bfa_itnim_clear_stats(struct bfa_itnim_s *itnim)
+{
+ int j;
+ bfa_os_memset(&itnim->stats, 0, sizeof(itnim->stats));
+ bfa_os_memset(&itnim->ioprofile, 0, sizeof(itnim->ioprofile));
+ for (j = 0; j < BFA_IOBUCKET_MAX; j++)
+ itnim->ioprofile.io_latency.min[j] = ~0;
+}
+
+/**
+ * BFA IO module state machine functions
+ */
+
+/**
+ * IO is not started (unallocated).
+ */
+static void
+bfa_ioim_sm_uninit(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+ bfa_trc_fp(ioim->bfa, ioim->iotag);
+ bfa_trc_fp(ioim->bfa, event);
+
+ switch (event) {
+ case BFA_IOIM_SM_START:
+ if (!bfa_itnim_is_online(ioim->itnim)) {
+ if (!bfa_itnim_hold_io(ioim->itnim)) {
+ bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+ list_del(&ioim->qe);
+ list_add_tail(&ioim->qe,
+ &ioim->fcpim->ioim_comp_q);
+ bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
+ __bfa_cb_ioim_pathtov, ioim);
+ } else {
+ list_del(&ioim->qe);
+ list_add_tail(&ioim->qe,
+ &ioim->itnim->pending_q);
+ }
+ break;
+ }
+
+ if (ioim->nsges > BFI_SGE_INLINE) {
+ if (!bfa_ioim_sge_setup(ioim)) {
+ bfa_sm_set_state(ioim, bfa_ioim_sm_sgalloc);
+ return;
+ }
+ }
+
+ if (!bfa_ioim_send_ioreq(ioim)) {
+ bfa_sm_set_state(ioim, bfa_ioim_sm_qfull);
+ break;
+ }
+
+ bfa_sm_set_state(ioim, bfa_ioim_sm_active);
+ break;
+
+ case BFA_IOIM_SM_IOTOV:
+ bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+ bfa_ioim_move_to_comp_q(ioim);
+ bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
+ __bfa_cb_ioim_pathtov, ioim);
+ break;
+
+ case BFA_IOIM_SM_ABORT:
+ /**
+ * IO in pending queue can get abort requests. Complete abort
+ * requests immediately.
+ */
+ bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+ bfa_assert(bfa_q_is_on_q(&ioim->itnim->pending_q, ioim));
+ bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
+ __bfa_cb_ioim_abort, ioim);
+ break;
+
+ default:
+ bfa_sm_fault(ioim->bfa, event);
+ }
+}
+
+/**
+ * IO is waiting for SG pages.
+ */
+static void
+bfa_ioim_sm_sgalloc(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+ bfa_trc(ioim->bfa, ioim->iotag);
+ bfa_trc(ioim->bfa, event);
+
+ switch (event) {
+ case BFA_IOIM_SM_SGALLOCED:
+ if (!bfa_ioim_send_ioreq(ioim)) {
+ bfa_sm_set_state(ioim, bfa_ioim_sm_qfull);
+ break;
+ }
+ bfa_sm_set_state(ioim, bfa_ioim_sm_active);
+ break;
+
+ case BFA_IOIM_SM_CLEANUP:
+ bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+ bfa_sgpg_wcancel(ioim->bfa, &ioim->iosp->sgpg_wqe);
+ bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
+ ioim);
+ bfa_ioim_notify_cleanup(ioim);
+ break;
+
+ case BFA_IOIM_SM_ABORT:
+ bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+ bfa_sgpg_wcancel(ioim->bfa, &ioim->iosp->sgpg_wqe);
+ bfa_ioim_move_to_comp_q(ioim);
+ bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
+ ioim);
+ break;
+
+ case BFA_IOIM_SM_HWFAIL:
+ bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+ bfa_sgpg_wcancel(ioim->bfa, &ioim->iosp->sgpg_wqe);
+ bfa_ioim_move_to_comp_q(ioim);
+ bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
+ ioim);
+ break;
+
+ default:
+ bfa_sm_fault(ioim->bfa, event);
+ }
+}
+
+/**
+ * IO is active.
+ */
+static void
+bfa_ioim_sm_active(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+ bfa_trc_fp(ioim->bfa, ioim->iotag);
+ bfa_trc_fp(ioim->bfa, event);
+
+ switch (event) {
+ case BFA_IOIM_SM_COMP_GOOD:
+ bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+ bfa_ioim_move_to_comp_q(ioim);
+ bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
+ __bfa_cb_ioim_good_comp, ioim);
+ break;
+
+ case BFA_IOIM_SM_COMP:
+ bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+ bfa_ioim_move_to_comp_q(ioim);
+ bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_comp,
+ ioim);
+ break;
+
+ case BFA_IOIM_SM_DONE:
+ bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
+ bfa_ioim_move_to_comp_q(ioim);
+ bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_comp,
+ ioim);
+ break;
+
+ case BFA_IOIM_SM_ABORT:
+ ioim->iosp->abort_explicit = BFA_TRUE;
+ ioim->io_cbfn = __bfa_cb_ioim_abort;
+
+ if (bfa_ioim_send_abort(ioim))
+ bfa_sm_set_state(ioim, bfa_ioim_sm_abort);
+ else {
+ bfa_sm_set_state(ioim, bfa_ioim_sm_abort_qfull);
+ bfa_stats(ioim->itnim, qwait);
+ bfa_reqq_wait(ioim->bfa, ioim->reqq,
+ &ioim->iosp->reqq_wait);
+ }
+ break;
+
+ case BFA_IOIM_SM_CLEANUP:
+ ioim->iosp->abort_explicit = BFA_FALSE;
+ ioim->io_cbfn = __bfa_cb_ioim_failed;
+
+ if (bfa_ioim_send_abort(ioim))
+ bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup);
+ else {
+ bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup_qfull);
+ bfa_stats(ioim->itnim, qwait);
+ bfa_reqq_wait(ioim->bfa, ioim->reqq,
+ &ioim->iosp->reqq_wait);
+ }
+ break;
+
+ case BFA_IOIM_SM_HWFAIL:
+ bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+ bfa_ioim_move_to_comp_q(ioim);
+ bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
+ ioim);
+ break;
+
+ case BFA_IOIM_SM_SQRETRY:
+ if (bfa_ioim_get_iotag(ioim) != BFA_TRUE) {
+ /* max retry completed free IO */
+ bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
+ bfa_ioim_move_to_comp_q(ioim);
+ bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
+ __bfa_cb_ioim_failed, ioim);
+ break;
+ }
+ /* waiting for IO tag resource free */
+ bfa_sm_set_state(ioim, bfa_ioim_sm_cmnd_retry);
+ break;
+
+ default:
+ bfa_sm_fault(ioim->bfa, event);
+ }
+}
+
+/**
+* IO is retried with new tag.
+*/
+static void
+bfa_ioim_sm_cmnd_retry(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+ bfa_trc_fp(ioim->bfa, ioim->iotag);
+ bfa_trc_fp(ioim->bfa, event);
+
+ switch (event) {
+ case BFA_IOIM_SM_FREE:
+ /* abts and rrq done. Now retry the IO with new tag */
+ if (!bfa_ioim_send_ioreq(ioim)) {
+ bfa_sm_set_state(ioim, bfa_ioim_sm_qfull);
+ break;
+ }
+ bfa_sm_set_state(ioim, bfa_ioim_sm_active);
+ break;
+
+ case BFA_IOIM_SM_CLEANUP:
+ ioim->iosp->abort_explicit = BFA_FALSE;
+ ioim->io_cbfn = __bfa_cb_ioim_failed;
+
+ if (bfa_ioim_send_abort(ioim))
+ bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup);
+ else {
+ bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup_qfull);
+ bfa_stats(ioim->itnim, qwait);
+ bfa_reqq_wait(ioim->bfa, ioim->reqq,
+ &ioim->iosp->reqq_wait);
+ }
+ break;
+
+ case BFA_IOIM_SM_HWFAIL:
+ bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+ bfa_ioim_move_to_comp_q(ioim);
+ bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
+ __bfa_cb_ioim_failed, ioim);
+ break;
+
+ case BFA_IOIM_SM_ABORT:
+ /** in this state IO abort is done.
+ * Waiting for IO tag resource free.
+ */
+ bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
+ bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
+ ioim);
+ break;
+
+ default:
+ bfa_sm_fault(ioim->bfa, event);
+ }
+}
+
+/**
+ * IO is being aborted, waiting for completion from firmware.
+ */
+static void
+bfa_ioim_sm_abort(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+ bfa_trc(ioim->bfa, ioim->iotag);
+ bfa_trc(ioim->bfa, event);
+
+ switch (event) {
+ case BFA_IOIM_SM_COMP_GOOD:
+ case BFA_IOIM_SM_COMP:
+ case BFA_IOIM_SM_DONE:
+ case BFA_IOIM_SM_FREE:
+ break;
+
+ case BFA_IOIM_SM_ABORT_DONE:
+ bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
+ bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
+ ioim);
+ break;
+
+ case BFA_IOIM_SM_ABORT_COMP:
+ bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+ bfa_ioim_move_to_comp_q(ioim);
+ bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
+ ioim);
+ break;
+
+ case BFA_IOIM_SM_COMP_UTAG:
+ bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+ bfa_ioim_move_to_comp_q(ioim);
+ bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
+ ioim);
+ break;
+
+ case BFA_IOIM_SM_CLEANUP:
+ bfa_assert(ioim->iosp->abort_explicit == BFA_TRUE);
+ ioim->iosp->abort_explicit = BFA_FALSE;
+
+ if (bfa_ioim_send_abort(ioim))
+ bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup);
+ else {
+ bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup_qfull);
+ bfa_stats(ioim->itnim, qwait);
+ bfa_reqq_wait(ioim->bfa, ioim->reqq,
+ &ioim->iosp->reqq_wait);
+ }
+ break;
+
+ case BFA_IOIM_SM_HWFAIL:
+ bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+ bfa_ioim_move_to_comp_q(ioim);
+ bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
+ ioim);
+ break;
+
+ default:
+ bfa_sm_fault(ioim->bfa, event);
+ }
+}
+
+/**
+ * IO is being cleaned up (implicit abort), waiting for completion from
+ * firmware.
+ */
+static void
+bfa_ioim_sm_cleanup(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+ bfa_trc(ioim->bfa, ioim->iotag);
+ bfa_trc(ioim->bfa, event);
+
+ switch (event) {
+ case BFA_IOIM_SM_COMP_GOOD:
+ case BFA_IOIM_SM_COMP:
+ case BFA_IOIM_SM_DONE:
+ case BFA_IOIM_SM_FREE:
+ break;
+
+ case BFA_IOIM_SM_ABORT:
+ /**
+ * IO is already being aborted implicitly
+ */
+ ioim->io_cbfn = __bfa_cb_ioim_abort;
+ break;
+
+ case BFA_IOIM_SM_ABORT_DONE:
+ bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
+ bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
+ bfa_ioim_notify_cleanup(ioim);
+ break;
+
+ case BFA_IOIM_SM_ABORT_COMP:
+ bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+ bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
+ bfa_ioim_notify_cleanup(ioim);
+ break;
+
+ case BFA_IOIM_SM_COMP_UTAG:
+ bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+ bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
+ bfa_ioim_notify_cleanup(ioim);
+ break;
+
+ case BFA_IOIM_SM_HWFAIL:
+ bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+ bfa_ioim_move_to_comp_q(ioim);
+ bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
+ ioim);
+ break;
+
+ case BFA_IOIM_SM_CLEANUP:
+ /**
+ * IO can be in cleanup state already due to TM command.
+ * 2nd cleanup request comes from ITN offline event.
+ */
+ break;
+
+ default:
+ bfa_sm_fault(ioim->bfa, event);
+ }
+}
+
+/**
+ * IO is waiting for room in request CQ
+ */
+static void
+bfa_ioim_sm_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+ bfa_trc(ioim->bfa, ioim->iotag);
+ bfa_trc(ioim->bfa, event);
+
+ switch (event) {
+ case BFA_IOIM_SM_QRESUME:
+ bfa_sm_set_state(ioim, bfa_ioim_sm_active);
+ bfa_ioim_send_ioreq(ioim);
+ break;
+
+ case BFA_IOIM_SM_ABORT:
+ bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+ bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
+ bfa_ioim_move_to_comp_q(ioim);
+ bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
+ ioim);
+ break;
+
+ case BFA_IOIM_SM_CLEANUP:
+ bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+ bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
+ bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
+ ioim);
+ bfa_ioim_notify_cleanup(ioim);
+ break;
+
+ case BFA_IOIM_SM_HWFAIL:
+ bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+ bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
+ bfa_ioim_move_to_comp_q(ioim);
+ bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
+ ioim);
+ break;
+
+ default:
+ bfa_sm_fault(ioim->bfa, event);
+ }
+}
+
+/**
+ * Active IO is being aborted, waiting for room in request CQ.
+ */
+static void
+bfa_ioim_sm_abort_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+ bfa_trc(ioim->bfa, ioim->iotag);
+ bfa_trc(ioim->bfa, event);
+
+ switch (event) {
+ case BFA_IOIM_SM_QRESUME:
+ bfa_sm_set_state(ioim, bfa_ioim_sm_abort);
+ bfa_ioim_send_abort(ioim);
+ break;
+
+ case BFA_IOIM_SM_CLEANUP:
+ bfa_assert(ioim->iosp->abort_explicit == BFA_TRUE);
+ ioim->iosp->abort_explicit = BFA_FALSE;
+ bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup_qfull);
+ break;
+
+ case BFA_IOIM_SM_COMP_GOOD:
+ case BFA_IOIM_SM_COMP:
+ bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+ bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
+ bfa_ioim_move_to_comp_q(ioim);
+ bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
+ ioim);
+ break;
+
+ case BFA_IOIM_SM_DONE:
+ bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
+ bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
+ bfa_ioim_move_to_comp_q(ioim);
+ bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
+ ioim);
+ break;
+
+ case BFA_IOIM_SM_HWFAIL:
+ bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+ bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
+ bfa_ioim_move_to_comp_q(ioim);
+ bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
+ ioim);
+ break;
+
+ default:
+ bfa_sm_fault(ioim->bfa, event);
+ }
+}
+
+/**
+ * Active IO is being cleaned up, waiting for room in request CQ.
+ */
+static void
+bfa_ioim_sm_cleanup_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+ bfa_trc(ioim->bfa, ioim->iotag);
+ bfa_trc(ioim->bfa, event);
+
+ switch (event) {
+ case BFA_IOIM_SM_QRESUME:
+ bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup);
+ bfa_ioim_send_abort(ioim);
+ break;
+
+ case BFA_IOIM_SM_ABORT:
+ /**
+ * IO is alraedy being cleaned up implicitly
+ */
+ ioim->io_cbfn = __bfa_cb_ioim_abort;
+ break;
+
+ case BFA_IOIM_SM_COMP_GOOD:
+ case BFA_IOIM_SM_COMP:
+ bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+ bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
+ bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
+ bfa_ioim_notify_cleanup(ioim);
+ break;
+
+ case BFA_IOIM_SM_DONE:
+ bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
+ bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
+ bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
+ bfa_ioim_notify_cleanup(ioim);
+ break;
+
+ case BFA_IOIM_SM_HWFAIL:
+ bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+ bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
+ bfa_ioim_move_to_comp_q(ioim);
+ bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
+ ioim);
+ break;
+
+ default:
+ bfa_sm_fault(ioim->bfa, event);
+ }
+}
+
+/**
+ * IO bfa callback is pending.
+ */
+static void
+bfa_ioim_sm_hcb(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+ bfa_trc_fp(ioim->bfa, ioim->iotag);
+ bfa_trc_fp(ioim->bfa, event);
+
+ switch (event) {
+ case BFA_IOIM_SM_HCB:
+ bfa_sm_set_state(ioim, bfa_ioim_sm_uninit);
+ bfa_ioim_free(ioim);
+ break;
+
+ case BFA_IOIM_SM_CLEANUP:
+ bfa_ioim_notify_cleanup(ioim);
+ break;
+
+ case BFA_IOIM_SM_HWFAIL:
+ break;
+
+ default:
+ bfa_sm_fault(ioim->bfa, event);
+ }
+}
+
+/**
+ * IO bfa callback is pending. IO resource cannot be freed.
+ */
+static void
+bfa_ioim_sm_hcb_free(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+ bfa_trc(ioim->bfa, ioim->iotag);
+ bfa_trc(ioim->bfa, event);
+
+ switch (event) {
+ case BFA_IOIM_SM_HCB:
+ bfa_sm_set_state(ioim, bfa_ioim_sm_resfree);
+ list_del(&ioim->qe);
+ list_add_tail(&ioim->qe, &ioim->fcpim->ioim_resfree_q);
+ break;
+
+ case BFA_IOIM_SM_FREE:
+ bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+ break;
+
+ case BFA_IOIM_SM_CLEANUP:
+ bfa_ioim_notify_cleanup(ioim);
+ break;
+
+ case BFA_IOIM_SM_HWFAIL:
+ bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+ break;
+
+ default:
+ bfa_sm_fault(ioim->bfa, event);
+ }
+}
+
+/**
+ * IO is completed, waiting resource free from firmware.
+ */
+static void
+bfa_ioim_sm_resfree(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+ bfa_trc(ioim->bfa, ioim->iotag);
+ bfa_trc(ioim->bfa, event);
+
+ switch (event) {
+ case BFA_IOIM_SM_FREE:
+ bfa_sm_set_state(ioim, bfa_ioim_sm_uninit);
+ bfa_ioim_free(ioim);
+ break;
+
+ case BFA_IOIM_SM_CLEANUP:
+ bfa_ioim_notify_cleanup(ioim);
+ break;
+
+ case BFA_IOIM_SM_HWFAIL:
+ break;
+
+ default:
+ bfa_sm_fault(ioim->bfa, event);
+ }
+}
+
+
+
+/**
+ * hal_ioim_private
+ */
+
+static void
+__bfa_cb_ioim_good_comp(void *cbarg, bfa_boolean_t complete)
+{
+ struct bfa_ioim_s *ioim = cbarg;
+
+ if (!complete) {
+ bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
+ return;
+ }
+
+ bfa_cb_ioim_good_comp(ioim->bfa->bfad, ioim->dio);
+}
+
+static void
+__bfa_cb_ioim_comp(void *cbarg, bfa_boolean_t complete)
+{
+ struct bfa_ioim_s *ioim = cbarg;
+ struct bfi_ioim_rsp_s *m;
+ u8 *snsinfo = NULL;
+ u8 sns_len = 0;
+ s32 residue = 0;
+
+ if (!complete) {
+ bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
+ return;
+ }
+
+ m = (struct bfi_ioim_rsp_s *) &ioim->iosp->comp_rspmsg;
+ if (m->io_status == BFI_IOIM_STS_OK) {
+ /**
+ * setup sense information, if present
+ */
+ if ((m->scsi_status == SCSI_STATUS_CHECK_CONDITION) &&
+ m->sns_len) {
+ sns_len = m->sns_len;
+ snsinfo = ioim->iosp->snsinfo;
+ }
+
+ /**
+ * setup residue value correctly for normal completions
+ */
+ if (m->resid_flags == FCP_RESID_UNDER) {
+ residue = bfa_os_ntohl(m->residue);
+ bfa_stats(ioim->itnim, iocomp_underrun);
+ }
+ if (m->resid_flags == FCP_RESID_OVER) {
+ residue = bfa_os_ntohl(m->residue);
+ residue = -residue;
+ bfa_stats(ioim->itnim, iocomp_overrun);
+ }
+ }
+
+ bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, m->io_status,
+ m->scsi_status, sns_len, snsinfo, residue);
+}
+
+static void
+__bfa_cb_ioim_failed(void *cbarg, bfa_boolean_t complete)
+{
+ struct bfa_ioim_s *ioim = cbarg;
+
+ if (!complete) {
+ bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
+ return;
+ }
+
+ bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_ABORTED,
+ 0, 0, NULL, 0);
+}
+
+static void
+__bfa_cb_ioim_pathtov(void *cbarg, bfa_boolean_t complete)
+{
+ struct bfa_ioim_s *ioim = cbarg;
+
+ bfa_stats(ioim->itnim, path_tov_expired);
+ if (!complete) {
+ bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
+ return;
+ }
+
+ bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_PATHTOV,
+ 0, 0, NULL, 0);
+}
+
+static void
+__bfa_cb_ioim_abort(void *cbarg, bfa_boolean_t complete)
+{
+ struct bfa_ioim_s *ioim = cbarg;
+
+ if (!complete) {
+ bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
+ return;
+ }
+
+ bfa_cb_ioim_abort(ioim->bfa->bfad, ioim->dio);
+}
+
+static void
+bfa_ioim_sgpg_alloced(void *cbarg)
+{
+ struct bfa_ioim_s *ioim = cbarg;
+
+ ioim->nsgpgs = BFA_SGPG_NPAGE(ioim->nsges);
+ list_splice_tail_init(&ioim->iosp->sgpg_wqe.sgpg_q, &ioim->sgpg_q);
+ bfa_ioim_sgpg_setup(ioim);
+ bfa_sm_send_event(ioim, BFA_IOIM_SM_SGALLOCED);
+}
+
+/**
+ * Send I/O request to firmware.
+ */
+static bfa_boolean_t
+bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim)
+{
+ struct bfa_itnim_s *itnim = ioim->itnim;
+ struct bfi_ioim_req_s *m;
+ static struct fcp_cmnd_s cmnd_z0 = { 0 };
+ struct bfi_sge_s *sge;
+ u32 pgdlen = 0;
+ u32 fcp_dl;
+ u64 addr;
+ struct scatterlist *sg;
+ struct scsi_cmnd *cmnd = (struct scsi_cmnd *) ioim->dio;
+
+ /**
+ * check for room in queue to send request now
+ */
+ m = bfa_reqq_next(ioim->bfa, ioim->reqq);
+ if (!m) {
+ bfa_stats(ioim->itnim, qwait);
+ bfa_reqq_wait(ioim->bfa, ioim->reqq,
+ &ioim->iosp->reqq_wait);
+ return BFA_FALSE;
+ }
+
+ /**
+ * build i/o request message next
+ */
+ m->io_tag = bfa_os_htons(ioim->iotag);
+ m->rport_hdl = ioim->itnim->rport->fw_handle;
+ m->io_timeout = bfa_cb_ioim_get_timeout(ioim->dio);
+
+ /**
+ * build inline IO SG element here
+ */
+ sge = &m->sges[0];
+ if (ioim->nsges) {
+ sg = (struct scatterlist *)scsi_sglist(cmnd);
+ addr = bfa_os_sgaddr(sg_dma_address(sg));
+ sge->sga = *(union bfi_addr_u *) &addr;
+ pgdlen = sg_dma_len(sg);
+ sge->sg_len = pgdlen;
+ sge->flags = (ioim->nsges > BFI_SGE_INLINE) ?
+ BFI_SGE_DATA_CPL : BFI_SGE_DATA_LAST;
+ bfa_sge_to_be(sge);
+ sge++;
+ }
+
+ if (ioim->nsges > BFI_SGE_INLINE) {
+ sge->sga = ioim->sgpg->sgpg_pa;
+ } else {
+ sge->sga.a32.addr_lo = 0;
+ sge->sga.a32.addr_hi = 0;
+ }
+ sge->sg_len = pgdlen;
+ sge->flags = BFI_SGE_PGDLEN;
+ bfa_sge_to_be(sge);
+
+ /**
+ * set up I/O command parameters
+ */
+ bfa_os_assign(m->cmnd, cmnd_z0);
+ m->cmnd.lun = bfa_cb_ioim_get_lun(ioim->dio);
+ m->cmnd.iodir = bfa_cb_ioim_get_iodir(ioim->dio);
+ bfa_os_assign(m->cmnd.cdb,
+ *(scsi_cdb_t *)bfa_cb_ioim_get_cdb(ioim->dio));
+ fcp_dl = bfa_cb_ioim_get_size(ioim->dio);
+ m->cmnd.fcp_dl = bfa_os_htonl(fcp_dl);
+
+ /**
+ * set up I/O message header
+ */
+ switch (m->cmnd.iodir) {
+ case FCP_IODIR_READ:
+ bfi_h2i_set(m->mh, BFI_MC_IOIM_READ, 0, bfa_lpuid(ioim->bfa));
+ bfa_stats(itnim, input_reqs);
+ ioim->itnim->stats.rd_throughput += fcp_dl;
+ break;
+ case FCP_IODIR_WRITE:
+ bfi_h2i_set(m->mh, BFI_MC_IOIM_WRITE, 0, bfa_lpuid(ioim->bfa));
+ bfa_stats(itnim, output_reqs);
+ ioim->itnim->stats.wr_throughput += fcp_dl;
+ break;
+ case FCP_IODIR_RW:
+ bfa_stats(itnim, input_reqs);
+ bfa_stats(itnim, output_reqs);
+ default:
+ bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_lpuid(ioim->bfa));
+ }
+ if (itnim->seq_rec ||
+ (bfa_cb_ioim_get_size(ioim->dio) & (sizeof(u32) - 1)))
+ bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_lpuid(ioim->bfa));
+
+#ifdef IOIM_ADVANCED
+ m->cmnd.crn = bfa_cb_ioim_get_crn(ioim->dio);
+ m->cmnd.priority = bfa_cb_ioim_get_priority(ioim->dio);
+ m->cmnd.taskattr = bfa_cb_ioim_get_taskattr(ioim->dio);
+
+ /**
+ * Handle large CDB (>16 bytes).
+ */
+ m->cmnd.addl_cdb_len = (bfa_cb_ioim_get_cdblen(ioim->dio) -
+ FCP_CMND_CDB_LEN) / sizeof(u32);
+ if (m->cmnd.addl_cdb_len) {
+ bfa_os_memcpy(&m->cmnd.cdb + 1, (scsi_cdb_t *)
+ bfa_cb_ioim_get_cdb(ioim->dio) + 1,
+ m->cmnd.addl_cdb_len * sizeof(u32));
+ fcp_cmnd_fcpdl(&m->cmnd) =
+ bfa_os_htonl(bfa_cb_ioim_get_size(ioim->dio));
+ }
+#endif
+
+ /**
+ * queue I/O message to firmware
+ */
+ bfa_reqq_produce(ioim->bfa, ioim->reqq);
+ return BFA_TRUE;
+}
+
+/**
+ * Setup any additional SG pages needed.Inline SG element is setup
+ * at queuing time.
+ */
+static bfa_boolean_t
+bfa_ioim_sge_setup(struct bfa_ioim_s *ioim)
+{
+ u16 nsgpgs;
+
+ bfa_assert(ioim->nsges > BFI_SGE_INLINE);
+
+ /**
+ * allocate SG pages needed
+ */
+ nsgpgs = BFA_SGPG_NPAGE(ioim->nsges);
+ if (!nsgpgs)
+ return BFA_TRUE;
+
+ if (bfa_sgpg_malloc(ioim->bfa, &ioim->sgpg_q, nsgpgs)
+ != BFA_STATUS_OK) {
+ bfa_sgpg_wait(ioim->bfa, &ioim->iosp->sgpg_wqe, nsgpgs);
+ return BFA_FALSE;
+ }
+
+ ioim->nsgpgs = nsgpgs;
+ bfa_ioim_sgpg_setup(ioim);
+
+ return BFA_TRUE;
+}
+
+static void
+bfa_ioim_sgpg_setup(struct bfa_ioim_s *ioim)
+{
+ int sgeid, nsges, i;
+ struct bfi_sge_s *sge;
+ struct bfa_sgpg_s *sgpg;
+ u32 pgcumsz;
+ u64 addr;
+ struct scatterlist *sg;
+ struct scsi_cmnd *cmnd = (struct scsi_cmnd *) ioim->dio;
+
+ sgeid = BFI_SGE_INLINE;
+ ioim->sgpg = sgpg = bfa_q_first(&ioim->sgpg_q);
+
+ sg = scsi_sglist(cmnd);
+ sg = sg_next(sg);
+
+ do {
+ sge = sgpg->sgpg->sges;
+ nsges = ioim->nsges - sgeid;
+ if (nsges > BFI_SGPG_DATA_SGES)
+ nsges = BFI_SGPG_DATA_SGES;
+
+ pgcumsz = 0;
+ for (i = 0; i < nsges; i++, sge++, sgeid++, sg = sg_next(sg)) {
+ addr = bfa_os_sgaddr(sg_dma_address(sg));
+ sge->sga = *(union bfi_addr_u *) &addr;
+ sge->sg_len = sg_dma_len(sg);
+ pgcumsz += sge->sg_len;
+
+ /**
+ * set flags
+ */
+ if (i < (nsges - 1))
+ sge->flags = BFI_SGE_DATA;
+ else if (sgeid < (ioim->nsges - 1))
+ sge->flags = BFI_SGE_DATA_CPL;
+ else
+ sge->flags = BFI_SGE_DATA_LAST;
+
+ bfa_sge_to_le(sge);
+ }
+
+ sgpg = (struct bfa_sgpg_s *) bfa_q_next(sgpg);
+
+ /**
+ * set the link element of each page
+ */
+ if (sgeid == ioim->nsges) {
+ sge->flags = BFI_SGE_PGDLEN;
+ sge->sga.a32.addr_lo = 0;
+ sge->sga.a32.addr_hi = 0;
+ } else {
+ sge->flags = BFI_SGE_LINK;
+ sge->sga = sgpg->sgpg_pa;
+ }
+ sge->sg_len = pgcumsz;
+
+ bfa_sge_to_le(sge);
+ } while (sgeid < ioim->nsges);
+}
+
+/**
+ * Send I/O abort request to firmware.
+ */
+static bfa_boolean_t
+bfa_ioim_send_abort(struct bfa_ioim_s *ioim)
+{
+ struct bfi_ioim_abort_req_s *m;
+ enum bfi_ioim_h2i msgop;
+
+ /**
+ * check for room in queue to send request now
+ */
+ m = bfa_reqq_next(ioim->bfa, ioim->reqq);
+ if (!m)
+ return BFA_FALSE;
+
+ /**
+ * build i/o request message next
+ */
+ if (ioim->iosp->abort_explicit)
+ msgop = BFI_IOIM_H2I_IOABORT_REQ;
+ else
+ msgop = BFI_IOIM_H2I_IOCLEANUP_REQ;
+
+ bfi_h2i_set(m->mh, BFI_MC_IOIM, msgop, bfa_lpuid(ioim->bfa));
+ m->io_tag = bfa_os_htons(ioim->iotag);
+ m->abort_tag = ++ioim->abort_tag;
+
+ /**
+ * queue I/O message to firmware
+ */
+ bfa_reqq_produce(ioim->bfa, ioim->reqq);
+ return BFA_TRUE;
+}
+
+/**
+ * Call to resume any I/O requests waiting for room in request queue.
+ */
+static void
+bfa_ioim_qresume(void *cbarg)
+{
+ struct bfa_ioim_s *ioim = cbarg;
+
+ bfa_stats(ioim->itnim, qresumes);
+ bfa_sm_send_event(ioim, BFA_IOIM_SM_QRESUME);
+}
+
+
+static void
+bfa_ioim_notify_cleanup(struct bfa_ioim_s *ioim)
+{
+ /**
+ * Move IO from itnim queue to fcpim global queue since itnim will be
+ * freed.
+ */
+ list_del(&ioim->qe);
+ list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
+
+ if (!ioim->iosp->tskim) {
+ if (ioim->fcpim->delay_comp && ioim->itnim->iotov_active) {
+ bfa_cb_dequeue(&ioim->hcb_qe);
+ list_del(&ioim->qe);
+ list_add_tail(&ioim->qe, &ioim->itnim->delay_comp_q);
+ }
+ bfa_itnim_iodone(ioim->itnim);
+ } else
+ bfa_tskim_iodone(ioim->iosp->tskim);
+}
+
+static bfa_boolean_t
+bfa_ioim_is_abortable(struct bfa_ioim_s *ioim)
+{
+ if ((bfa_sm_cmp_state(ioim, bfa_ioim_sm_uninit) &&
+ (!bfa_q_is_on_q(&ioim->itnim->pending_q, ioim))) ||
+ (bfa_sm_cmp_state(ioim, bfa_ioim_sm_abort)) ||
+ (bfa_sm_cmp_state(ioim, bfa_ioim_sm_abort_qfull)) ||
+ (bfa_sm_cmp_state(ioim, bfa_ioim_sm_hcb)) ||
+ (bfa_sm_cmp_state(ioim, bfa_ioim_sm_hcb_free)) ||
+ (bfa_sm_cmp_state(ioim, bfa_ioim_sm_resfree)))
+ return BFA_FALSE;
+
+ return BFA_TRUE;
+}
+
+/**
+ * or after the link comes back.
+ */
+void
+bfa_ioim_delayed_comp(struct bfa_ioim_s *ioim, bfa_boolean_t iotov)
+{
+ /**
+ * If path tov timer expired, failback with PATHTOV status - these
+ * IO requests are not normally retried by IO stack.
+ *
+ * Otherwise device cameback online and fail it with normal failed
+ * status so that IO stack retries these failed IO requests.
+ */
+ if (iotov)
+ ioim->io_cbfn = __bfa_cb_ioim_pathtov;
+ else {
+ ioim->io_cbfn = __bfa_cb_ioim_failed;
+ bfa_stats(ioim->itnim, iocom_nexus_abort);
+ }
+ bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
+
+ /**
+ * Move IO to fcpim global queue since itnim will be
+ * freed.
+ */
+ list_del(&ioim->qe);
+ list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
+}
+
+
+
+/**
+ * hal_ioim_friend
+ */
+
+/**
+ * Memory allocation and initialization.
+ */
+void
+bfa_ioim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
+{
+ struct bfa_ioim_s *ioim;
+ struct bfa_ioim_sp_s *iosp;
+ u16 i;
+ u8 *snsinfo;
+ u32 snsbufsz;
+
+ /**
+ * claim memory first
+ */
+ ioim = (struct bfa_ioim_s *) bfa_meminfo_kva(minfo);
+ fcpim->ioim_arr = ioim;
+ bfa_meminfo_kva(minfo) = (u8 *) (ioim + fcpim->num_ioim_reqs);
+
+ iosp = (struct bfa_ioim_sp_s *) bfa_meminfo_kva(minfo);
+ fcpim->ioim_sp_arr = iosp;
+ bfa_meminfo_kva(minfo) = (u8 *) (iosp + fcpim->num_ioim_reqs);
+
+ /**
+ * Claim DMA memory for per IO sense data.
+ */
+ snsbufsz = fcpim->num_ioim_reqs * BFI_IOIM_SNSLEN;
+ fcpim->snsbase.pa = bfa_meminfo_dma_phys(minfo);
+ bfa_meminfo_dma_phys(minfo) += snsbufsz;
+
+ fcpim->snsbase.kva = bfa_meminfo_dma_virt(minfo);
+ bfa_meminfo_dma_virt(minfo) += snsbufsz;
+ snsinfo = fcpim->snsbase.kva;
+ bfa_iocfc_set_snsbase(fcpim->bfa, fcpim->snsbase.pa);
+
+ /**
+ * Initialize ioim free queues
+ */
+ INIT_LIST_HEAD(&fcpim->ioim_free_q);
+ INIT_LIST_HEAD(&fcpim->ioim_resfree_q);
+ INIT_LIST_HEAD(&fcpim->ioim_comp_q);
+
+ for (i = 0; i < fcpim->num_ioim_reqs;
+ i++, ioim++, iosp++, snsinfo += BFI_IOIM_SNSLEN) {
+ /*
+ * initialize IOIM
+ */
+ bfa_os_memset(ioim, 0, sizeof(struct bfa_ioim_s));
+ ioim->iotag = i;
+ ioim->bfa = fcpim->bfa;
+ ioim->fcpim = fcpim;
+ ioim->iosp = iosp;
+ iosp->snsinfo = snsinfo;
+ INIT_LIST_HEAD(&ioim->sgpg_q);
+ bfa_reqq_winit(&ioim->iosp->reqq_wait,
+ bfa_ioim_qresume, ioim);
+ bfa_sgpg_winit(&ioim->iosp->sgpg_wqe,
+ bfa_ioim_sgpg_alloced, ioim);
+ bfa_sm_set_state(ioim, bfa_ioim_sm_uninit);
+
+ list_add_tail(&ioim->qe, &fcpim->ioim_free_q);
+ }
+}
+
+/**
+ * Driver detach time call.
+ */
+void
+bfa_ioim_detach(struct bfa_fcpim_mod_s *fcpim)
+{
+}
+
+void
+bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
+{
+ struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+ struct bfi_ioim_rsp_s *rsp = (struct bfi_ioim_rsp_s *) m;
+ struct bfa_ioim_s *ioim;
+ u16 iotag;
+ enum bfa_ioim_event evt = BFA_IOIM_SM_COMP;
+
+ iotag = bfa_os_ntohs(rsp->io_tag);
+
+ ioim = BFA_IOIM_FROM_TAG(fcpim, iotag);
+ bfa_assert(ioim->iotag == iotag);
+
+ bfa_trc(ioim->bfa, ioim->iotag);
+ bfa_trc(ioim->bfa, rsp->io_status);
+ bfa_trc(ioim->bfa, rsp->reuse_io_tag);
+
+ if (bfa_sm_cmp_state(ioim, bfa_ioim_sm_active))
+ bfa_os_assign(ioim->iosp->comp_rspmsg, *m);
+
+ switch (rsp->io_status) {
+ case BFI_IOIM_STS_OK:
+ bfa_stats(ioim->itnim, iocomp_ok);
+ if (rsp->reuse_io_tag == 0)
+ evt = BFA_IOIM_SM_DONE;
+ else
+ evt = BFA_IOIM_SM_COMP;
+ break;
+
+ case BFI_IOIM_STS_TIMEDOUT:
+ bfa_stats(ioim->itnim, iocomp_timedout);
+ case BFI_IOIM_STS_ABORTED:
+ rsp->io_status = BFI_IOIM_STS_ABORTED;
+ bfa_stats(ioim->itnim, iocomp_aborted);
+ if (rsp->reuse_io_tag == 0)
+ evt = BFA_IOIM_SM_DONE;
+ else
+ evt = BFA_IOIM_SM_COMP;
+ break;
+
+ case BFI_IOIM_STS_PROTO_ERR:
+ bfa_stats(ioim->itnim, iocom_proto_err);
+ bfa_assert(rsp->reuse_io_tag);
+ evt = BFA_IOIM_SM_COMP;
+ break;
+
+ case BFI_IOIM_STS_SQER_NEEDED:
+ bfa_stats(ioim->itnim, iocom_sqer_needed);
+ bfa_assert(rsp->reuse_io_tag == 0);
+ evt = BFA_IOIM_SM_SQRETRY;
+ break;
+
+ case BFI_IOIM_STS_RES_FREE:
+ bfa_stats(ioim->itnim, iocom_res_free);
+ evt = BFA_IOIM_SM_FREE;
+ break;
+
+ case BFI_IOIM_STS_HOST_ABORTED:
+ bfa_stats(ioim->itnim, iocom_hostabrts);
+ if (rsp->abort_tag != ioim->abort_tag) {
+ bfa_trc(ioim->bfa, rsp->abort_tag);
+ bfa_trc(ioim->bfa, ioim->abort_tag);
+ return;
+ }
+
+ if (rsp->reuse_io_tag)
+ evt = BFA_IOIM_SM_ABORT_COMP;
+ else
+ evt = BFA_IOIM_SM_ABORT_DONE;
+ break;
+
+ case BFI_IOIM_STS_UTAG:
+ bfa_stats(ioim->itnim, iocom_utags);
+ evt = BFA_IOIM_SM_COMP_UTAG;
+ break;
+
+ default:
+ bfa_assert(0);
+ }
+
+ bfa_sm_send_event(ioim, evt);
+}
+
+void
+bfa_ioim_good_comp_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
+{
+ struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+ struct bfi_ioim_rsp_s *rsp = (struct bfi_ioim_rsp_s *) m;
+ struct bfa_ioim_s *ioim;
+ u16 iotag;
+
+ iotag = bfa_os_ntohs(rsp->io_tag);
+
+ ioim = BFA_IOIM_FROM_TAG(fcpim, iotag);
+ bfa_assert(ioim->iotag == iotag);
+
+ bfa_trc_fp(ioim->bfa, ioim->iotag);
+ bfa_ioim_cb_profile_comp(fcpim, ioim);
+
+ bfa_sm_send_event(ioim, BFA_IOIM_SM_COMP_GOOD);
+}
+
+void
+bfa_ioim_profile_start(struct bfa_ioim_s *ioim)
+{
+ ioim->start_time = bfa_os_get_clock();
+}
+
+void
+bfa_ioim_profile_comp(struct bfa_ioim_s *ioim)
+{
+ u32 fcp_dl = bfa_cb_ioim_get_size(ioim->dio);
+ u32 index = bfa_ioim_get_index(fcp_dl);
+ u64 end_time = bfa_os_get_clock();
+ struct bfa_itnim_latency_s *io_lat =
+ &(ioim->itnim->ioprofile.io_latency);
+ u32 val = (u32)(end_time - ioim->start_time);
+
+ bfa_itnim_ioprofile_update(ioim->itnim, index);
+
+ io_lat->count[index]++;
+ io_lat->min[index] = (io_lat->min[index] < val) ?
+ io_lat->min[index] : val;
+ io_lat->max[index] = (io_lat->max[index] > val) ?
+ io_lat->max[index] : val;
+ io_lat->avg[index] += val;
+}
+/**
+ * Called by itnim to clean up IO while going offline.
+ */
+void
+bfa_ioim_cleanup(struct bfa_ioim_s *ioim)
+{
+ bfa_trc(ioim->bfa, ioim->iotag);
+ bfa_stats(ioim->itnim, io_cleanups);
+
+ ioim->iosp->tskim = NULL;
+ bfa_sm_send_event(ioim, BFA_IOIM_SM_CLEANUP);
+}
+
+void
+bfa_ioim_cleanup_tm(struct bfa_ioim_s *ioim, struct bfa_tskim_s *tskim)
+{
+ bfa_trc(ioim->bfa, ioim->iotag);
+ bfa_stats(ioim->itnim, io_tmaborts);
+
+ ioim->iosp->tskim = tskim;
+ bfa_sm_send_event(ioim, BFA_IOIM_SM_CLEANUP);
+}
+
+/**
+ * IOC failure handling.
+ */
+void
+bfa_ioim_iocdisable(struct bfa_ioim_s *ioim)
+{
+ bfa_trc(ioim->bfa, ioim->iotag);
+ bfa_stats(ioim->itnim, io_iocdowns);
+ bfa_sm_send_event(ioim, BFA_IOIM_SM_HWFAIL);
+}
+
+/**
+ * IO offline TOV popped. Fail the pending IO.
+ */
+void
+bfa_ioim_tov(struct bfa_ioim_s *ioim)
+{
+ bfa_trc(ioim->bfa, ioim->iotag);
+ bfa_sm_send_event(ioim, BFA_IOIM_SM_IOTOV);
+}
+
+
+
+/**
+ * hal_ioim_api
+ */
+
+/**
+ * Allocate IOIM resource for initiator mode I/O request.
+ */
+struct bfa_ioim_s *
+bfa_ioim_alloc(struct bfa_s *bfa, struct bfad_ioim_s *dio,
+ struct bfa_itnim_s *itnim, u16 nsges)
+{
+ struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+ struct bfa_ioim_s *ioim;
+
+ /**
+ * alocate IOIM resource
+ */
+ bfa_q_deq(&fcpim->ioim_free_q, &ioim);
+ if (!ioim) {
+ bfa_stats(itnim, no_iotags);
+ return NULL;
+ }
+
+ ioim->dio = dio;
+ ioim->itnim = itnim;
+ ioim->nsges = nsges;
+ ioim->nsgpgs = 0;
+
+ bfa_stats(itnim, total_ios);
+ fcpim->ios_active++;
+
+ list_add_tail(&ioim->qe, &itnim->io_q);
+ bfa_trc_fp(ioim->bfa, ioim->iotag);
+
+ return ioim;
+}
+
+void
+bfa_ioim_free(struct bfa_ioim_s *ioim)
+{
+ struct bfa_fcpim_mod_s *fcpim = ioim->fcpim;
+
+ bfa_trc_fp(ioim->bfa, ioim->iotag);
+ bfa_assert_fp(bfa_sm_cmp_state(ioim, bfa_ioim_sm_uninit));
+
+ bfa_assert_fp(list_empty(&ioim->sgpg_q) ||
+ (ioim->nsges > BFI_SGE_INLINE));
+
+ if (ioim->nsgpgs > 0)
+ bfa_sgpg_mfree(ioim->bfa, &ioim->sgpg_q, ioim->nsgpgs);
+
+ bfa_stats(ioim->itnim, io_comps);
+ fcpim->ios_active--;
+
+ list_del(&ioim->qe);
+ list_add_tail(&ioim->qe, &fcpim->ioim_free_q);
+}
+
+void
+bfa_ioim_start(struct bfa_ioim_s *ioim)
+{
+ bfa_trc_fp(ioim->bfa, ioim->iotag);
+
+ bfa_ioim_cb_profile_start(ioim->fcpim, ioim);
+
+ /**
+ * Obtain the queue over which this request has to be issued
+ */
+ ioim->reqq = bfa_fcpim_ioredirect_enabled(ioim->bfa) ?
+ bfa_cb_ioim_get_reqq(ioim->dio) :
+ bfa_itnim_get_reqq(ioim);
+
+ bfa_sm_send_event(ioim, BFA_IOIM_SM_START);
+}
+
+/**
+ * Driver I/O abort request.
+ */
+bfa_status_t
+bfa_ioim_abort(struct bfa_ioim_s *ioim)
+{
+
+ bfa_trc(ioim->bfa, ioim->iotag);
+
+ if (!bfa_ioim_is_abortable(ioim))
+ return BFA_STATUS_FAILED;
+
+ bfa_stats(ioim->itnim, io_aborts);
+ bfa_sm_send_event(ioim, BFA_IOIM_SM_ABORT);
+
+ return BFA_STATUS_OK;
+}
+
+
+/**
+ * BFA TSKIM state machine functions
+ */
+
+/**
+ * Task management command beginning state.
+ */
+static void
+bfa_tskim_sm_uninit(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
+{
+ bfa_trc(tskim->bfa, event);
+
+ switch (event) {
+ case BFA_TSKIM_SM_START:
+ bfa_sm_set_state(tskim, bfa_tskim_sm_active);
+ bfa_tskim_gather_ios(tskim);
+
+ /**
+ * If device is offline, do not send TM on wire. Just cleanup
+ * any pending IO requests and complete TM request.
+ */
+ if (!bfa_itnim_is_online(tskim->itnim)) {
+ bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup);
+ tskim->tsk_status = BFI_TSKIM_STS_OK;
+ bfa_tskim_cleanup_ios(tskim);
+ return;
+ }
+
+ if (!bfa_tskim_send(tskim)) {
+ bfa_sm_set_state(tskim, bfa_tskim_sm_qfull);
+ bfa_stats(tskim->itnim, tm_qwait);
+ bfa_reqq_wait(tskim->bfa, tskim->itnim->reqq,
+ &tskim->reqq_wait);
+ }
+ break;
+
+ default:
+ bfa_sm_fault(tskim->bfa, event);
+ }
+}
+
+/**
+ * brief
+ * TM command is active, awaiting completion from firmware to
+ * cleanup IO requests in TM scope.
+ */
+static void
+bfa_tskim_sm_active(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
+{
+ bfa_trc(tskim->bfa, event);
+
+ switch (event) {
+ case BFA_TSKIM_SM_DONE:
+ bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup);
+ bfa_tskim_cleanup_ios(tskim);
+ break;
+
+ case BFA_TSKIM_SM_CLEANUP:
+ bfa_sm_set_state(tskim, bfa_tskim_sm_cleanup);
+ if (!bfa_tskim_send_abort(tskim)) {
+ bfa_sm_set_state(tskim, bfa_tskim_sm_cleanup_qfull);
+ bfa_stats(tskim->itnim, tm_qwait);
+ bfa_reqq_wait(tskim->bfa, tskim->itnim->reqq,
+ &tskim->reqq_wait);
+ }
+ break;
+
+ case BFA_TSKIM_SM_HWFAIL:
+ bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
+ bfa_tskim_iocdisable_ios(tskim);
+ bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);
+ break;
+
+ default:
+ bfa_sm_fault(tskim->bfa, event);
+ }
+}
+
+/**
+ * An active TM is being cleaned up since ITN is offline. Awaiting cleanup
+ * completion event from firmware.
+ */
+static void
+bfa_tskim_sm_cleanup(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
+{
+ bfa_trc(tskim->bfa, event);
+
+ switch (event) {
+ case BFA_TSKIM_SM_DONE:
+ /**
+ * Ignore and wait for ABORT completion from firmware.
+ */
+ break;
+
+ case BFA_TSKIM_SM_CLEANUP_DONE:
+ bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup);
+ bfa_tskim_cleanup_ios(tskim);
+ break;
+
+ case BFA_TSKIM_SM_HWFAIL:
+ bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
+ bfa_tskim_iocdisable_ios(tskim);
+ bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);
+ break;
+
+ default:
+ bfa_sm_fault(tskim->bfa, event);
+ }
+}
+
+static void
+bfa_tskim_sm_iocleanup(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
+{
+ bfa_trc(tskim->bfa, event);
+
+ switch (event) {
+ case BFA_TSKIM_SM_IOS_DONE:
+ bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
+ bfa_tskim_qcomp(tskim, __bfa_cb_tskim_done);
+ break;
+
+ case BFA_TSKIM_SM_CLEANUP:
+ /**
+ * Ignore, TM command completed on wire.
+ * Notify TM conmpletion on IO cleanup completion.
+ */
+ break;
+
+ case BFA_TSKIM_SM_HWFAIL:
+ bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
+ bfa_tskim_iocdisable_ios(tskim);
+ bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);
+ break;
+
+ default:
+ bfa_sm_fault(tskim->bfa, event);
+ }
+}
+
+/**
+ * Task management command is waiting for room in request CQ
+ */
+static void
+bfa_tskim_sm_qfull(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
+{
+ bfa_trc(tskim->bfa, event);
+
+ switch (event) {
+ case BFA_TSKIM_SM_QRESUME:
+ bfa_sm_set_state(tskim, bfa_tskim_sm_active);
+ bfa_tskim_send(tskim);
+ break;
+
+ case BFA_TSKIM_SM_CLEANUP:
+ /**
+ * No need to send TM on wire since ITN is offline.
+ */
+ bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup);
+ bfa_reqq_wcancel(&tskim->reqq_wait);
+ bfa_tskim_cleanup_ios(tskim);
+ break;
+
+ case BFA_TSKIM_SM_HWFAIL:
+ bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
+ bfa_reqq_wcancel(&tskim->reqq_wait);
+ bfa_tskim_iocdisable_ios(tskim);
+ bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);
+ break;
+
+ default:
+ bfa_sm_fault(tskim->bfa, event);
+ }
+}
+
+/**
+ * Task management command is active, awaiting for room in request CQ
+ * to send clean up request.
+ */
+static void
+bfa_tskim_sm_cleanup_qfull(struct bfa_tskim_s *tskim,
+ enum bfa_tskim_event event)
+{
+ bfa_trc(tskim->bfa, event);
+
+ switch (event) {
+ case BFA_TSKIM_SM_DONE:
+ bfa_reqq_wcancel(&tskim->reqq_wait);
+ /**
+ *
+ * Fall through !!!
+ */
+
+ case BFA_TSKIM_SM_QRESUME:
+ bfa_sm_set_state(tskim, bfa_tskim_sm_cleanup);
+ bfa_tskim_send_abort(tskim);
+ break;
+
+ case BFA_TSKIM_SM_HWFAIL:
+ bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
+ bfa_reqq_wcancel(&tskim->reqq_wait);
+ bfa_tskim_iocdisable_ios(tskim);
+ bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);
+ break;
+
+ default:
+ bfa_sm_fault(tskim->bfa, event);
+ }
+}
+
+/**
+ * BFA callback is pending
+ */
+static void
+bfa_tskim_sm_hcb(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
+{
+ bfa_trc(tskim->bfa, event);
+
+ switch (event) {
+ case BFA_TSKIM_SM_HCB:
+ bfa_sm_set_state(tskim, bfa_tskim_sm_uninit);
+ bfa_tskim_free(tskim);
+ break;
+
+ case BFA_TSKIM_SM_CLEANUP:
+ bfa_tskim_notify_comp(tskim);
+ break;
+
+ case BFA_TSKIM_SM_HWFAIL:
+ break;
+
+ default:
+ bfa_sm_fault(tskim->bfa, event);
+ }
+}
+
+
+
+/**
+ * hal_tskim_private
+ */
+
+static void
+__bfa_cb_tskim_done(void *cbarg, bfa_boolean_t complete)
+{
+ struct bfa_tskim_s *tskim = cbarg;
+
+ if (!complete) {
+ bfa_sm_send_event(tskim, BFA_TSKIM_SM_HCB);
+ return;
+ }
+
+ bfa_stats(tskim->itnim, tm_success);
+ bfa_cb_tskim_done(tskim->bfa->bfad, tskim->dtsk, tskim->tsk_status);
+}
+
+static void
+__bfa_cb_tskim_failed(void *cbarg, bfa_boolean_t complete)
+{
+ struct bfa_tskim_s *tskim = cbarg;
+
+ if (!complete) {
+ bfa_sm_send_event(tskim, BFA_TSKIM_SM_HCB);
+ return;
+ }
+
+ bfa_stats(tskim->itnim, tm_failures);
+ bfa_cb_tskim_done(tskim->bfa->bfad, tskim->dtsk,
+ BFI_TSKIM_STS_FAILED);
+}
+
+static bfa_boolean_t
+bfa_tskim_match_scope(struct bfa_tskim_s *tskim, lun_t lun)
+{
+ switch (tskim->tm_cmnd) {
+ case FCP_TM_TARGET_RESET:
+ return BFA_TRUE;
+
+ case FCP_TM_ABORT_TASK_SET:
+ case FCP_TM_CLEAR_TASK_SET:
+ case FCP_TM_LUN_RESET:
+ case FCP_TM_CLEAR_ACA:
+ return (tskim->lun == lun);
+
+ default:
+ bfa_assert(0);
+ }
+
+ return BFA_FALSE;
+}
+
+/**
+ * Gather affected IO requests and task management commands.
+ */
+static void
+bfa_tskim_gather_ios(struct bfa_tskim_s *tskim)
+{
+ struct bfa_itnim_s *itnim = tskim->itnim;
+ struct bfa_ioim_s *ioim;
+ struct list_head *qe, *qen;
+
+ INIT_LIST_HEAD(&tskim->io_q);
+
+ /**
+ * Gather any active IO requests first.
+ */
+ list_for_each_safe(qe, qen, &itnim->io_q) {
+ ioim = (struct bfa_ioim_s *) qe;
+ if (bfa_tskim_match_scope
+ (tskim, bfa_cb_ioim_get_lun(ioim->dio))) {
+ list_del(&ioim->qe);
+ list_add_tail(&ioim->qe, &tskim->io_q);
+ }
+ }
+
+ /**
+ * Failback any pending IO requests immediately.
+ */
+ list_for_each_safe(qe, qen, &itnim->pending_q) {
+ ioim = (struct bfa_ioim_s *) qe;
+ if (bfa_tskim_match_scope
+ (tskim, bfa_cb_ioim_get_lun(ioim->dio))) {
+ list_del(&ioim->qe);
+ list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
+ bfa_ioim_tov(ioim);
+ }
+ }
+}
+
+/**
+ * IO cleanup completion
+ */
+static void
+bfa_tskim_cleanp_comp(void *tskim_cbarg)
+{
+ struct bfa_tskim_s *tskim = tskim_cbarg;
+
+ bfa_stats(tskim->itnim, tm_io_comps);
+ bfa_sm_send_event(tskim, BFA_TSKIM_SM_IOS_DONE);
+}
+
+/**
+ * Gather affected IO requests and task management commands.
+ */
+static void
+bfa_tskim_cleanup_ios(struct bfa_tskim_s *tskim)
+{
+ struct bfa_ioim_s *ioim;
+ struct list_head *qe, *qen;
+
+ bfa_wc_init(&tskim->wc, bfa_tskim_cleanp_comp, tskim);
+
+ list_for_each_safe(qe, qen, &tskim->io_q) {
+ ioim = (struct bfa_ioim_s *) qe;
+ bfa_wc_up(&tskim->wc);
+ bfa_ioim_cleanup_tm(ioim, tskim);
+ }
+
+ bfa_wc_wait(&tskim->wc);
+}
+
+/**
+ * Send task management request to firmware.
+ */
+static bfa_boolean_t
+bfa_tskim_send(struct bfa_tskim_s *tskim)
+{
+ struct bfa_itnim_s *itnim = tskim->itnim;
+ struct bfi_tskim_req_s *m;
+
+ /**
+ * check for room in queue to send request now
+ */
+ m = bfa_reqq_next(tskim->bfa, itnim->reqq);
+ if (!m)
+ return BFA_FALSE;
+
+ /**
+ * build i/o request message next
+ */
+ bfi_h2i_set(m->mh, BFI_MC_TSKIM, BFI_TSKIM_H2I_TM_REQ,
+ bfa_lpuid(tskim->bfa));
+
+ m->tsk_tag = bfa_os_htons(tskim->tsk_tag);
+ m->itn_fhdl = tskim->itnim->rport->fw_handle;
+ m->t_secs = tskim->tsecs;
+ m->lun = tskim->lun;
+ m->tm_flags = tskim->tm_cmnd;
+
+ /**
+ * queue I/O message to firmware
+ */
+ bfa_reqq_produce(tskim->bfa, itnim->reqq);
+ return BFA_TRUE;
+}
+
+/**
+ * Send abort request to cleanup an active TM to firmware.
+ */
+static bfa_boolean_t
+bfa_tskim_send_abort(struct bfa_tskim_s *tskim)
+{
+ struct bfa_itnim_s *itnim = tskim->itnim;
+ struct bfi_tskim_abortreq_s *m;
+
+ /**
+ * check for room in queue to send request now
+ */
+ m = bfa_reqq_next(tskim->bfa, itnim->reqq);
+ if (!m)
+ return BFA_FALSE;
+
+ /**
+ * build i/o request message next
+ */
+ bfi_h2i_set(m->mh, BFI_MC_TSKIM, BFI_TSKIM_H2I_ABORT_REQ,
+ bfa_lpuid(tskim->bfa));
+
+ m->tsk_tag = bfa_os_htons(tskim->tsk_tag);
+
+ /**
+ * queue I/O message to firmware
+ */
+ bfa_reqq_produce(tskim->bfa, itnim->reqq);
+ return BFA_TRUE;
+}
+
+/**
+ * Call to resume task management cmnd waiting for room in request queue.
+ */
+static void
+bfa_tskim_qresume(void *cbarg)
+{
+ struct bfa_tskim_s *tskim = cbarg;
+
+ bfa_stats(tskim->itnim, tm_qresumes);
+ bfa_sm_send_event(tskim, BFA_TSKIM_SM_QRESUME);
+}
+
+/**
+ * Cleanup IOs associated with a task mangement command on IOC failures.
+ */
+static void
+bfa_tskim_iocdisable_ios(struct bfa_tskim_s *tskim)
+{
+ struct bfa_ioim_s *ioim;
+ struct list_head *qe, *qen;
+
+ list_for_each_safe(qe, qen, &tskim->io_q) {
+ ioim = (struct bfa_ioim_s *) qe;
+ bfa_ioim_iocdisable(ioim);
+ }
+}
+
+
+
+/**
+ * hal_tskim_friend
+ */
+
+/**
+ * Notification on completions from related ioim.
+ */
+void
+bfa_tskim_iodone(struct bfa_tskim_s *tskim)
+{
+ bfa_wc_down(&tskim->wc);
+}
+
+/**
+ * Handle IOC h/w failure notification from itnim.
+ */
+void
+bfa_tskim_iocdisable(struct bfa_tskim_s *tskim)
+{
+ tskim->notify = BFA_FALSE;
+ bfa_stats(tskim->itnim, tm_iocdowns);
+ bfa_sm_send_event(tskim, BFA_TSKIM_SM_HWFAIL);
+}
+
+/**
+ * Cleanup TM command and associated IOs as part of ITNIM offline.
+ */
+void
+bfa_tskim_cleanup(struct bfa_tskim_s *tskim)
+{
+ tskim->notify = BFA_TRUE;
+ bfa_stats(tskim->itnim, tm_cleanups);
+ bfa_sm_send_event(tskim, BFA_TSKIM_SM_CLEANUP);
+}
+
+/**
+ * Memory allocation and initialization.
+ */
+void
+bfa_tskim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
+{
+ struct bfa_tskim_s *tskim;
+ u16 i;
+
+ INIT_LIST_HEAD(&fcpim->tskim_free_q);
+
+ tskim = (struct bfa_tskim_s *) bfa_meminfo_kva(minfo);
+ fcpim->tskim_arr = tskim;
+
+ for (i = 0; i < fcpim->num_tskim_reqs; i++, tskim++) {
+ /*
+ * initialize TSKIM
+ */
+ bfa_os_memset(tskim, 0, sizeof(struct bfa_tskim_s));
+ tskim->tsk_tag = i;
+ tskim->bfa = fcpim->bfa;
+ tskim->fcpim = fcpim;
+ tskim->notify = BFA_FALSE;
+ bfa_reqq_winit(&tskim->reqq_wait, bfa_tskim_qresume,
+ tskim);
+ bfa_sm_set_state(tskim, bfa_tskim_sm_uninit);
+
+ list_add_tail(&tskim->qe, &fcpim->tskim_free_q);
+ }
+
+ bfa_meminfo_kva(minfo) = (u8 *) tskim;
+}
+
+void
+bfa_tskim_detach(struct bfa_fcpim_mod_s *fcpim)
+{
+ /**
+ * @todo
+ */
+}
+
+void
+bfa_tskim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
+{
+ struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+ struct bfi_tskim_rsp_s *rsp = (struct bfi_tskim_rsp_s *) m;
+ struct bfa_tskim_s *tskim;
+ u16 tsk_tag = bfa_os_ntohs(rsp->tsk_tag);
+
+ tskim = BFA_TSKIM_FROM_TAG(fcpim, tsk_tag);
+ bfa_assert(tskim->tsk_tag == tsk_tag);
+
+ tskim->tsk_status = rsp->tsk_status;
+
+ /**
+ * Firmware sends BFI_TSKIM_STS_ABORTED status for abort
+ * requests. All other statuses are for normal completions.
+ */
+ if (rsp->tsk_status == BFI_TSKIM_STS_ABORTED) {
+ bfa_stats(tskim->itnim, tm_cleanup_comps);
+ bfa_sm_send_event(tskim, BFA_TSKIM_SM_CLEANUP_DONE);
+ } else {
+ bfa_stats(tskim->itnim, tm_fw_rsps);
+ bfa_sm_send_event(tskim, BFA_TSKIM_SM_DONE);
+ }
+}
+
+
+
+/**
+ * hal_tskim_api
+ */
+
+
+struct bfa_tskim_s *
+bfa_tskim_alloc(struct bfa_s *bfa, struct bfad_tskim_s *dtsk)
+{
+ struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+ struct bfa_tskim_s *tskim;
+
+ bfa_q_deq(&fcpim->tskim_free_q, &tskim);
+
+ if (tskim)
+ tskim->dtsk = dtsk;
+
+ return tskim;
+}
+
+void
+bfa_tskim_free(struct bfa_tskim_s *tskim)
+{
+ bfa_assert(bfa_q_is_on_q_func(&tskim->itnim->tsk_q, &tskim->qe));
+ list_del(&tskim->qe);
+ list_add_tail(&tskim->qe, &tskim->fcpim->tskim_free_q);
+}
+
+/**
+ * Start a task management command.
+ *
+ * @param[in] tskim BFA task management command instance
+ * @param[in] itnim i-t nexus for the task management command
+ * @param[in] lun lun, if applicable
+ * @param[in] tm_cmnd Task management command code.
+ * @param[in] t_secs Timeout in seconds
+ *
+ * @return None.
+ */
+void
+bfa_tskim_start(struct bfa_tskim_s *tskim, struct bfa_itnim_s *itnim, lun_t lun,
+ enum fcp_tm_cmnd tm_cmnd, u8 tsecs)
+{
+ tskim->itnim = itnim;
+ tskim->lun = lun;
+ tskim->tm_cmnd = tm_cmnd;
+ tskim->tsecs = tsecs;
+ tskim->notify = BFA_FALSE;
+ bfa_stats(itnim, tm_cmnds);
+
+ list_add_tail(&tskim->qe, &itnim->tsk_q);
+ bfa_sm_send_event(tskim, BFA_TSKIM_SM_START);
+}
diff --git a/drivers/scsi/bfa/bfa_fcpim.h b/drivers/scsi/bfa/bfa_fcpim.h
new file mode 100644
index 000000000000..3bf343160aac
--- /dev/null
+++ b/drivers/scsi/bfa/bfa_fcpim.h
@@ -0,0 +1,401 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_FCPIM_H__
+#define __BFA_FCPIM_H__
+
+#include "bfa.h"
+#include "bfa_svc.h"
+#include "bfi_ms.h"
+#include "bfa_defs_svc.h"
+#include "bfa_cs.h"
+
+
+#define BFA_ITNIM_MIN 32
+#define BFA_ITNIM_MAX 1024
+
+#define BFA_IOIM_MIN 8
+#define BFA_IOIM_MAX 2000
+
+#define BFA_TSKIM_MIN 4
+#define BFA_TSKIM_MAX 512
+#define BFA_FCPIM_PATHTOV_DEF (30 * 1000) /* in millisecs */
+#define BFA_FCPIM_PATHTOV_MAX (90 * 1000) /* in millisecs */
+
+
+#define bfa_itnim_ioprofile_update(__itnim, __index) \
+ (__itnim->ioprofile.iocomps[__index]++)
+
+#define BFA_IOIM_RETRY_TAG_OFFSET 11
+#define BFA_IOIM_RETRY_TAG_MASK 0x07ff /* 2K IOs */
+#define BFA_IOIM_RETRY_MAX 7
+
+/* Buckets are are 512 bytes to 2MB */
+static inline u32
+bfa_ioim_get_index(u32 n) {
+ int pos = 0;
+ if (n >= (1UL)<<22)
+ return BFA_IOBUCKET_MAX - 1;
+ n >>= 8;
+ if (n >= (1UL)<<16)
+ n >>= 16; pos += 16;
+ if (n >= 1 << 8)
+ n >>= 8; pos += 8;
+ if (n >= 1 << 4)
+ n >>= 4; pos += 4;
+ if (n >= 1 << 2)
+ n >>= 2; pos += 2;
+ if (n >= 1 << 1)
+ pos += 1;
+
+ return (n == 0) ? (0) : pos;
+}
+
+/*
+ * forward declarations
+ */
+struct bfa_ioim_s;
+struct bfa_tskim_s;
+struct bfad_ioim_s;
+struct bfad_tskim_s;
+
+typedef void (*bfa_fcpim_profile_t) (struct bfa_ioim_s *ioim);
+
+struct bfa_fcpim_mod_s {
+ struct bfa_s *bfa;
+ struct bfa_itnim_s *itnim_arr;
+ struct bfa_ioim_s *ioim_arr;
+ struct bfa_ioim_sp_s *ioim_sp_arr;
+ struct bfa_tskim_s *tskim_arr;
+ struct bfa_dma_s snsbase;
+ int num_itnims;
+ int num_ioim_reqs;
+ int num_tskim_reqs;
+ u32 path_tov;
+ u16 q_depth;
+ u8 reqq; /* Request queue to be used */
+ u8 rsvd;
+ struct list_head itnim_q; /* queue of active itnim */
+ struct list_head ioim_free_q; /* free IO resources */
+ struct list_head ioim_resfree_q; /* IOs waiting for f/w */
+ struct list_head ioim_comp_q; /* IO global comp Q */
+ struct list_head tskim_free_q;
+ u32 ios_active; /* current active IOs */
+ u32 delay_comp;
+ struct bfa_fcpim_del_itn_stats_s del_itn_stats;
+ bfa_boolean_t ioredirect;
+ bfa_boolean_t io_profile;
+ u32 io_profile_start_time;
+ bfa_fcpim_profile_t profile_comp;
+ bfa_fcpim_profile_t profile_start;
+};
+
+/**
+ * BFA IO (initiator mode)
+ */
+struct bfa_ioim_s {
+ struct list_head qe; /* queue elememt */
+ bfa_sm_t sm; /* BFA ioim state machine */
+ struct bfa_s *bfa; /* BFA module */
+ struct bfa_fcpim_mod_s *fcpim; /* parent fcpim module */
+ struct bfa_itnim_s *itnim; /* i-t-n nexus for this IO */
+ struct bfad_ioim_s *dio; /* driver IO handle */
+ u16 iotag; /* FWI IO tag */
+ u16 abort_tag; /* unqiue abort request tag */
+ u16 nsges; /* number of SG elements */
+ u16 nsgpgs; /* number of SG pages */
+ struct bfa_sgpg_s *sgpg; /* first SG page */
+ struct list_head sgpg_q; /* allocated SG pages */
+ struct bfa_cb_qe_s hcb_qe; /* bfa callback qelem */
+ bfa_cb_cbfn_t io_cbfn; /* IO completion handler */
+ struct bfa_ioim_sp_s *iosp; /* slow-path IO handling */
+ u8 reqq; /* Request queue for I/O */
+ u64 start_time; /* IO's Profile start val */
+};
+
+
+struct bfa_ioim_sp_s {
+ struct bfi_msg_s comp_rspmsg; /* IO comp f/w response */
+ u8 *snsinfo; /* sense info for this IO */
+ struct bfa_sgpg_wqe_s sgpg_wqe; /* waitq elem for sgpg */
+ struct bfa_reqq_wait_s reqq_wait; /* to wait for room in reqq */
+ bfa_boolean_t abort_explicit; /* aborted by OS */
+ struct bfa_tskim_s *tskim; /* Relevant TM cmd */
+};
+
+/**
+ * BFA Task management command (initiator mode)
+ */
+struct bfa_tskim_s {
+ struct list_head qe;
+ bfa_sm_t sm;
+ struct bfa_s *bfa; /* BFA module */
+ struct bfa_fcpim_mod_s *fcpim; /* parent fcpim module */
+ struct bfa_itnim_s *itnim; /* i-t-n nexus for this IO */
+ struct bfad_tskim_s *dtsk; /* driver task mgmt cmnd */
+ bfa_boolean_t notify; /* notify itnim on TM comp */
+ lun_t lun; /* lun if applicable */
+ enum fcp_tm_cmnd tm_cmnd; /* task management command */
+ u16 tsk_tag; /* FWI IO tag */
+ u8 tsecs; /* timeout in seconds */
+ struct bfa_reqq_wait_s reqq_wait; /* to wait for room in reqq */
+ struct list_head io_q; /* queue of affected IOs */
+ struct bfa_wc_s wc; /* waiting counter */
+ struct bfa_cb_qe_s hcb_qe; /* bfa callback qelem */
+ enum bfi_tskim_status tsk_status; /* TM status */
+};
+
+
+/**
+ * BFA i-t-n (initiator mode)
+ */
+struct bfa_itnim_s {
+ struct list_head qe; /* queue element */
+ bfa_sm_t sm; /* i-t-n im BFA state machine */
+ struct bfa_s *bfa; /* bfa instance */
+ struct bfa_rport_s *rport; /* bfa rport */
+ void *ditn; /* driver i-t-n structure */
+ struct bfi_mhdr_s mhdr; /* pre-built mhdr */
+ u8 msg_no; /* itnim/rport firmware handle */
+ u8 reqq; /* CQ for requests */
+ struct bfa_cb_qe_s hcb_qe; /* bfa callback qelem */
+ struct list_head pending_q; /* queue of pending IO requests */
+ struct list_head io_q; /* queue of active IO requests */
+ struct list_head io_cleanup_q; /* IO being cleaned up */
+ struct list_head tsk_q; /* queue of active TM commands */
+ struct list_head delay_comp_q; /* queue of failed inflight cmds */
+ bfa_boolean_t seq_rec; /* SQER supported */
+ bfa_boolean_t is_online; /* itnim is ONLINE for IO */
+ bfa_boolean_t iotov_active; /* IO TOV timer is active */
+ struct bfa_wc_s wc; /* waiting counter */
+ struct bfa_timer_s timer; /* pending IO TOV */
+ struct bfa_reqq_wait_s reqq_wait; /* to wait for room in reqq */
+ struct bfa_fcpim_mod_s *fcpim; /* fcpim module */
+ struct bfa_itnim_iostats_s stats;
+ struct bfa_itnim_ioprofile_s ioprofile;
+};
+
+
+#define bfa_itnim_is_online(_itnim) ((_itnim)->is_online)
+#define BFA_FCPIM_MOD(_hal) (&(_hal)->modules.fcpim_mod)
+#define BFA_IOIM_FROM_TAG(_fcpim, _iotag) \
+ (&fcpim->ioim_arr[(_iotag & BFA_IOIM_RETRY_TAG_MASK)])
+#define BFA_TSKIM_FROM_TAG(_fcpim, _tmtag) \
+ (&fcpim->tskim_arr[_tmtag & (fcpim->num_tskim_reqs - 1)])
+
+#define bfa_io_profile_start_time(_bfa) \
+ (_bfa->modules.fcpim_mod.io_profile_start_time)
+#define bfa_fcpim_get_io_profile(_bfa) \
+ (_bfa->modules.fcpim_mod.io_profile)
+
+static inline bfa_boolean_t
+bfa_ioim_get_iotag(struct bfa_ioim_s *ioim)
+{
+ u16 k = ioim->iotag;
+
+ k >>= BFA_IOIM_RETRY_TAG_OFFSET; k++;
+
+ if (k > BFA_IOIM_RETRY_MAX)
+ return BFA_FALSE;
+ ioim->iotag &= BFA_IOIM_RETRY_TAG_MASK;
+ ioim->iotag |= k<<BFA_IOIM_RETRY_TAG_OFFSET;
+ return BFA_TRUE;
+}
+/*
+ * function prototypes
+ */
+void bfa_ioim_attach(struct bfa_fcpim_mod_s *fcpim,
+ struct bfa_meminfo_s *minfo);
+void bfa_ioim_detach(struct bfa_fcpim_mod_s *fcpim);
+void bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
+void bfa_ioim_good_comp_isr(struct bfa_s *bfa,
+ struct bfi_msg_s *msg);
+void bfa_ioim_cleanup(struct bfa_ioim_s *ioim);
+void bfa_ioim_cleanup_tm(struct bfa_ioim_s *ioim,
+ struct bfa_tskim_s *tskim);
+void bfa_ioim_iocdisable(struct bfa_ioim_s *ioim);
+void bfa_ioim_tov(struct bfa_ioim_s *ioim);
+
+void bfa_tskim_attach(struct bfa_fcpim_mod_s *fcpim,
+ struct bfa_meminfo_s *minfo);
+void bfa_tskim_detach(struct bfa_fcpim_mod_s *fcpim);
+void bfa_tskim_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
+void bfa_tskim_iodone(struct bfa_tskim_s *tskim);
+void bfa_tskim_iocdisable(struct bfa_tskim_s *tskim);
+void bfa_tskim_cleanup(struct bfa_tskim_s *tskim);
+
+void bfa_itnim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
+ u32 *dm_len);
+void bfa_itnim_attach(struct bfa_fcpim_mod_s *fcpim,
+ struct bfa_meminfo_s *minfo);
+void bfa_itnim_detach(struct bfa_fcpim_mod_s *fcpim);
+void bfa_itnim_iocdisable(struct bfa_itnim_s *itnim);
+void bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
+void bfa_itnim_iodone(struct bfa_itnim_s *itnim);
+void bfa_itnim_tskdone(struct bfa_itnim_s *itnim);
+bfa_boolean_t bfa_itnim_hold_io(struct bfa_itnim_s *itnim);
+void bfa_ioim_profile_comp(struct bfa_ioim_s *ioim);
+void bfa_ioim_profile_start(struct bfa_ioim_s *ioim);
+
+
+/*
+ * bfa fcpim module API functions
+ */
+void bfa_fcpim_path_tov_set(struct bfa_s *bfa, u16 path_tov);
+u16 bfa_fcpim_path_tov_get(struct bfa_s *bfa);
+void bfa_fcpim_qdepth_set(struct bfa_s *bfa, u16 q_depth);
+u16 bfa_fcpim_qdepth_get(struct bfa_s *bfa);
+bfa_status_t bfa_fcpim_get_modstats(struct bfa_s *bfa,
+ struct bfa_itnim_iostats_s *modstats);
+bfa_status_t bfa_fcpim_port_iostats(struct bfa_s *bfa,
+ struct bfa_itnim_iostats_s *stats, u8 lp_tag);
+bfa_status_t bfa_fcpim_get_del_itn_stats(struct bfa_s *bfa,
+ struct bfa_fcpim_del_itn_stats_s *modstats);
+bfa_status_t bfa_fcpim_port_clear_iostats(struct bfa_s *bfa, u8 lp_tag);
+void bfa_fcpim_add_stats(struct bfa_itnim_iostats_s *fcpim_stats,
+ struct bfa_itnim_iostats_s *itnim_stats);
+bfa_status_t bfa_fcpim_clr_modstats(struct bfa_s *bfa);
+void bfa_fcpim_set_ioredirect(struct bfa_s *bfa,
+ bfa_boolean_t state);
+void bfa_fcpim_update_ioredirect(struct bfa_s *bfa);
+bfa_status_t bfa_fcpim_profile_on(struct bfa_s *bfa, u32 time);
+bfa_status_t bfa_fcpim_profile_off(struct bfa_s *bfa);
+#define bfa_fcpim_ioredirect_enabled(__bfa) \
+ (((struct bfa_fcpim_mod_s *)(BFA_FCPIM_MOD(__bfa)))->ioredirect)
+
+#define bfa_fcpim_get_next_reqq(__bfa, __qid) \
+{ \
+ struct bfa_fcpim_mod_s *__fcpim = BFA_FCPIM_MOD(__bfa); \
+ __fcpim->reqq++; \
+ __fcpim->reqq &= (BFI_IOC_MAX_CQS - 1); \
+ *(__qid) = __fcpim->reqq; \
+}
+
+#define bfa_iocfc_map_msg_to_qid(__msg, __qid) \
+ *(__qid) = (u8)((__msg) & (BFI_IOC_MAX_CQS - 1));
+/*
+ * bfa itnim API functions
+ */
+struct bfa_itnim_s *bfa_itnim_create(struct bfa_s *bfa,
+ struct bfa_rport_s *rport, void *itnim);
+void bfa_itnim_delete(struct bfa_itnim_s *itnim);
+void bfa_itnim_online(struct bfa_itnim_s *itnim,
+ bfa_boolean_t seq_rec);
+void bfa_itnim_offline(struct bfa_itnim_s *itnim);
+void bfa_itnim_get_stats(struct bfa_itnim_s *itnim,
+ struct bfa_itnim_iostats_s *stats);
+void bfa_itnim_clear_stats(struct bfa_itnim_s *itnim);
+bfa_status_t bfa_itnim_get_ioprofile(struct bfa_itnim_s *itnim,
+ struct bfa_itnim_ioprofile_s *ioprofile);
+#define bfa_itnim_get_reqq(__ioim) (((struct bfa_ioim_s *)__ioim)->itnim->reqq)
+
+/**
+ * BFA completion callback for bfa_itnim_online().
+ *
+ * @param[in] itnim FCS or driver itnim instance
+ *
+ * return None
+ */
+void bfa_cb_itnim_online(void *itnim);
+
+/**
+ * BFA completion callback for bfa_itnim_offline().
+ *
+ * @param[in] itnim FCS or driver itnim instance
+ *
+ * return None
+ */
+void bfa_cb_itnim_offline(void *itnim);
+void bfa_cb_itnim_tov_begin(void *itnim);
+void bfa_cb_itnim_tov(void *itnim);
+
+/**
+ * BFA notification to FCS/driver for second level error recovery.
+ *
+ * Atleast one I/O request has timedout and target is unresponsive to
+ * repeated abort requests. Second level error recovery should be initiated
+ * by starting implicit logout and recovery procedures.
+ *
+ * @param[in] itnim FCS or driver itnim instance
+ *
+ * return None
+ */
+void bfa_cb_itnim_sler(void *itnim);
+
+/*
+ * bfa ioim API functions
+ */
+struct bfa_ioim_s *bfa_ioim_alloc(struct bfa_s *bfa,
+ struct bfad_ioim_s *dio,
+ struct bfa_itnim_s *itnim,
+ u16 nsgles);
+
+void bfa_ioim_free(struct bfa_ioim_s *ioim);
+void bfa_ioim_start(struct bfa_ioim_s *ioim);
+bfa_status_t bfa_ioim_abort(struct bfa_ioim_s *ioim);
+void bfa_ioim_delayed_comp(struct bfa_ioim_s *ioim,
+ bfa_boolean_t iotov);
+
+
+/**
+ * I/O completion notification.
+ *
+ * @param[in] dio driver IO structure
+ * @param[in] io_status IO completion status
+ * @param[in] scsi_status SCSI status returned by target
+ * @param[in] sns_len SCSI sense length, 0 if none
+ * @param[in] sns_info SCSI sense data, if any
+ * @param[in] residue Residual length
+ *
+ * @return None
+ */
+void bfa_cb_ioim_done(void *bfad, struct bfad_ioim_s *dio,
+ enum bfi_ioim_status io_status,
+ u8 scsi_status, int sns_len,
+ u8 *sns_info, s32 residue);
+
+/**
+ * I/O good completion notification.
+ *
+ * @param[in] dio driver IO structure
+ *
+ * @return None
+ */
+void bfa_cb_ioim_good_comp(void *bfad, struct bfad_ioim_s *dio);
+
+/**
+ * I/O abort completion notification
+ *
+ * @param[in] dio driver IO that was aborted
+ *
+ * @return None
+ */
+void bfa_cb_ioim_abort(void *bfad, struct bfad_ioim_s *dio);
+
+/*
+ * bfa tskim API functions
+ */
+struct bfa_tskim_s *bfa_tskim_alloc(struct bfa_s *bfa,
+ struct bfad_tskim_s *dtsk);
+void bfa_tskim_free(struct bfa_tskim_s *tskim);
+void bfa_tskim_start(struct bfa_tskim_s *tskim,
+ struct bfa_itnim_s *itnim, lun_t lun,
+ enum fcp_tm_cmnd tm, u8 t_secs);
+void bfa_cb_tskim_done(void *bfad, struct bfad_tskim_s *dtsk,
+ enum bfi_tskim_status tsk_status);
+
+#endif /* __BFA_FCPIM_H__ */
diff --git a/drivers/scsi/bfa/bfa_fcpim_priv.h b/drivers/scsi/bfa/bfa_fcpim_priv.h
deleted file mode 100644
index 762516cb5cb2..000000000000
--- a/drivers/scsi/bfa/bfa_fcpim_priv.h
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_FCPIM_PRIV_H__
-#define __BFA_FCPIM_PRIV_H__
-
-#include <bfa_fcpim.h>
-#include <defs/bfa_defs_fcpim.h>
-#include <cs/bfa_wc.h>
-#include "bfa_sgpg_priv.h"
-
-#define BFA_ITNIM_MIN 32
-#define BFA_ITNIM_MAX 1024
-
-#define BFA_IOIM_MIN 8
-#define BFA_IOIM_MAX 2000
-
-#define BFA_TSKIM_MIN 4
-#define BFA_TSKIM_MAX 512
-#define BFA_FCPIM_PATHTOV_DEF (30 * 1000) /* in millisecs */
-#define BFA_FCPIM_PATHTOV_MAX (90 * 1000) /* in millisecs */
-
-#define bfa_fcpim_stats(__fcpim, __stats) \
- ((__fcpim)->stats.__stats++)
-
-struct bfa_fcpim_mod_s {
- struct bfa_s *bfa;
- struct bfa_itnim_s *itnim_arr;
- struct bfa_ioim_s *ioim_arr;
- struct bfa_ioim_sp_s *ioim_sp_arr;
- struct bfa_tskim_s *tskim_arr;
- struct bfa_dma_s snsbase;
- int num_itnims;
- int num_ioim_reqs;
- int num_tskim_reqs;
- u32 path_tov;
- u16 q_depth;
- u8 reqq; /* Request queue to be used */
- u8 rsvd;
- struct list_head itnim_q; /* queue of active itnim */
- struct list_head ioim_free_q; /* free IO resources */
- struct list_head ioim_resfree_q; /* IOs waiting for f/w */
- struct list_head ioim_comp_q; /* IO global comp Q */
- struct list_head tskim_free_q;
- u32 ios_active; /* current active IOs */
- u32 delay_comp;
- struct bfa_fcpim_stats_s stats;
- bfa_boolean_t ioredirect;
-};
-
-struct bfa_ioim_s;
-struct bfa_tskim_s;
-
-/**
- * BFA IO (initiator mode)
- */
-struct bfa_ioim_s {
- struct list_head qe; /* queue elememt */
- bfa_sm_t sm; /* BFA ioim state machine */
- struct bfa_s *bfa; /* BFA module */
- struct bfa_fcpim_mod_s *fcpim; /* parent fcpim module */
- struct bfa_itnim_s *itnim; /* i-t-n nexus for this IO */
- struct bfad_ioim_s *dio; /* driver IO handle */
- u16 iotag; /* FWI IO tag */
- u16 abort_tag; /* unqiue abort request tag */
- u16 nsges; /* number of SG elements */
- u16 nsgpgs; /* number of SG pages */
- struct bfa_sgpg_s *sgpg; /* first SG page */
- struct list_head sgpg_q; /* allocated SG pages */
- struct bfa_cb_qe_s hcb_qe; /* bfa callback qelem */
- bfa_cb_cbfn_t io_cbfn; /* IO completion handler */
- struct bfa_ioim_sp_s *iosp; /* slow-path IO handling */
- u8 reqq; /* Request queue for I/O */
-};
-
-struct bfa_ioim_sp_s {
- struct bfi_msg_s comp_rspmsg; /* IO comp f/w response */
- u8 *snsinfo; /* sense info for this IO */
- struct bfa_sgpg_wqe_s sgpg_wqe; /* waitq elem for sgpg */
- struct bfa_reqq_wait_s reqq_wait; /* to wait for room in reqq */
- bfa_boolean_t abort_explicit; /* aborted by OS */
- struct bfa_tskim_s *tskim; /* Relevant TM cmd */
-};
-
-/**
- * BFA Task management command (initiator mode)
- */
-struct bfa_tskim_s {
- struct list_head qe;
- bfa_sm_t sm;
- struct bfa_s *bfa; /* BFA module */
- struct bfa_fcpim_mod_s *fcpim; /* parent fcpim module */
- struct bfa_itnim_s *itnim; /* i-t-n nexus for this IO */
- struct bfad_tskim_s *dtsk; /* driver task mgmt cmnd */
- bfa_boolean_t notify; /* notify itnim on TM comp */
- lun_t lun; /* lun if applicable */
- enum fcp_tm_cmnd tm_cmnd; /* task management command */
- u16 tsk_tag; /* FWI IO tag */
- u8 tsecs; /* timeout in seconds */
- struct bfa_reqq_wait_s reqq_wait; /* to wait for room in reqq */
- struct list_head io_q; /* queue of affected IOs */
- struct bfa_wc_s wc; /* waiting counter */
- struct bfa_cb_qe_s hcb_qe; /* bfa callback qelem */
- enum bfi_tskim_status tsk_status; /* TM status */
-};
-
-/**
- * BFA i-t-n (initiator mode)
- */
-struct bfa_itnim_s {
- struct list_head qe; /* queue element */
- bfa_sm_t sm; /* i-t-n im BFA state machine */
- struct bfa_s *bfa; /* bfa instance */
- struct bfa_rport_s *rport; /* bfa rport */
- void *ditn; /* driver i-t-n structure */
- struct bfi_mhdr_s mhdr; /* pre-built mhdr */
- u8 msg_no; /* itnim/rport firmware handle */
- u8 reqq; /* CQ for requests */
- struct bfa_cb_qe_s hcb_qe; /* bfa callback qelem */
- struct list_head pending_q; /* queue of pending IO requests*/
- struct list_head io_q; /* queue of active IO requests */
- struct list_head io_cleanup_q; /* IO being cleaned up */
- struct list_head tsk_q; /* queue of active TM commands */
- struct list_head delay_comp_q;/* queue of failed inflight cmds */
- bfa_boolean_t seq_rec; /* SQER supported */
- bfa_boolean_t is_online; /* itnim is ONLINE for IO */
- bfa_boolean_t iotov_active; /* IO TOV timer is active */
- struct bfa_wc_s wc; /* waiting counter */
- struct bfa_timer_s timer; /* pending IO TOV */
- struct bfa_reqq_wait_s reqq_wait; /* to wait for room in reqq */
- struct bfa_fcpim_mod_s *fcpim; /* fcpim module */
- struct bfa_itnim_hal_stats_s stats;
- struct bfa_itnim_latency_s io_latency;
-};
-
-#define bfa_itnim_is_online(_itnim) ((_itnim)->is_online)
-#define BFA_FCPIM_MOD(_hal) (&(_hal)->modules.fcpim_mod)
-#define BFA_IOIM_FROM_TAG(_fcpim, _iotag) \
- (&fcpim->ioim_arr[_iotag])
-#define BFA_TSKIM_FROM_TAG(_fcpim, _tmtag) \
- (&fcpim->tskim_arr[_tmtag & (fcpim->num_tskim_reqs - 1)])
-
-/*
- * function prototypes
- */
-void bfa_ioim_attach(struct bfa_fcpim_mod_s *fcpim,
- struct bfa_meminfo_s *minfo);
-void bfa_ioim_detach(struct bfa_fcpim_mod_s *fcpim);
-void bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
-void bfa_ioim_good_comp_isr(struct bfa_s *bfa,
- struct bfi_msg_s *msg);
-void bfa_ioim_cleanup(struct bfa_ioim_s *ioim);
-void bfa_ioim_cleanup_tm(struct bfa_ioim_s *ioim,
- struct bfa_tskim_s *tskim);
-void bfa_ioim_iocdisable(struct bfa_ioim_s *ioim);
-void bfa_ioim_tov(struct bfa_ioim_s *ioim);
-
-void bfa_tskim_attach(struct bfa_fcpim_mod_s *fcpim,
- struct bfa_meminfo_s *minfo);
-void bfa_tskim_detach(struct bfa_fcpim_mod_s *fcpim);
-void bfa_tskim_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
-void bfa_tskim_iodone(struct bfa_tskim_s *tskim);
-void bfa_tskim_iocdisable(struct bfa_tskim_s *tskim);
-void bfa_tskim_cleanup(struct bfa_tskim_s *tskim);
-
-void bfa_itnim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
- u32 *dm_len);
-void bfa_itnim_attach(struct bfa_fcpim_mod_s *fcpim,
- struct bfa_meminfo_s *minfo);
-void bfa_itnim_detach(struct bfa_fcpim_mod_s *fcpim);
-void bfa_itnim_iocdisable(struct bfa_itnim_s *itnim);
-void bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
-void bfa_itnim_iodone(struct bfa_itnim_s *itnim);
-void bfa_itnim_tskdone(struct bfa_itnim_s *itnim);
-bfa_boolean_t bfa_itnim_hold_io(struct bfa_itnim_s *itnim);
-
-#endif /* __BFA_FCPIM_PRIV_H__ */
-
diff --git a/drivers/scsi/bfa/bfa_fcport.c b/drivers/scsi/bfa/bfa_fcport.c
deleted file mode 100644
index 76867b5577fa..000000000000
--- a/drivers/scsi/bfa/bfa_fcport.c
+++ /dev/null
@@ -1,1962 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#include <bfa.h>
-#include <bfa_svc.h>
-#include <bfi/bfi_pport.h>
-#include <bfi/bfi_pbc.h>
-#include <cs/bfa_debug.h>
-#include <aen/bfa_aen.h>
-#include <cs/bfa_plog.h>
-#include <aen/bfa_aen_port.h>
-
-BFA_TRC_FILE(HAL, FCPORT);
-BFA_MODULE(fcport);
-
-/*
- * The port is considered disabled if corresponding physical port or IOC are
- * disabled explicitly
- */
-#define BFA_PORT_IS_DISABLED(bfa) \
- ((bfa_fcport_is_disabled(bfa) == BFA_TRUE) || \
- (bfa_ioc_is_disabled(&bfa->ioc) == BFA_TRUE))
-
-/*
- * forward declarations
- */
-static bfa_boolean_t bfa_fcport_send_enable(struct bfa_fcport_s *fcport);
-static bfa_boolean_t bfa_fcport_send_disable(struct bfa_fcport_s *fcport);
-static void bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport);
-static void bfa_fcport_reset_linkinfo(struct bfa_fcport_s *fcport);
-static void bfa_fcport_set_wwns(struct bfa_fcport_s *fcport);
-static void __bfa_cb_fcport_event(void *cbarg, bfa_boolean_t complete);
-static void bfa_fcport_callback(struct bfa_fcport_s *fcport,
- enum bfa_pport_linkstate event);
-static void bfa_fcport_queue_cb(struct bfa_fcport_ln_s *ln,
- enum bfa_pport_linkstate event);
-static void __bfa_cb_fcport_stats_clr(void *cbarg, bfa_boolean_t complete);
-static void bfa_fcport_stats_get_timeout(void *cbarg);
-static void bfa_fcport_stats_clr_timeout(void *cbarg);
-
-/**
- * bfa_pport_private
- */
-
-/**
- * BFA port state machine events
- */
-enum bfa_fcport_sm_event {
- BFA_FCPORT_SM_START = 1, /* start port state machine */
- BFA_FCPORT_SM_STOP = 2, /* stop port state machine */
- BFA_FCPORT_SM_ENABLE = 3, /* enable port */
- BFA_FCPORT_SM_DISABLE = 4, /* disable port state machine */
- BFA_FCPORT_SM_FWRSP = 5, /* firmware enable/disable rsp */
- BFA_FCPORT_SM_LINKUP = 6, /* firmware linkup event */
- BFA_FCPORT_SM_LINKDOWN = 7, /* firmware linkup down */
- BFA_FCPORT_SM_QRESUME = 8, /* CQ space available */
- BFA_FCPORT_SM_HWFAIL = 9, /* IOC h/w failure */
-};
-
-/**
- * BFA port link notification state machine events
- */
-
-enum bfa_fcport_ln_sm_event {
- BFA_FCPORT_LN_SM_LINKUP = 1, /* linkup event */
- BFA_FCPORT_LN_SM_LINKDOWN = 2, /* linkdown event */
- BFA_FCPORT_LN_SM_NOTIFICATION = 3 /* done notification */
-};
-
-static void bfa_fcport_sm_uninit(struct bfa_fcport_s *fcport,
- enum bfa_fcport_sm_event event);
-static void bfa_fcport_sm_enabling_qwait(struct bfa_fcport_s *fcport,
- enum bfa_fcport_sm_event event);
-static void bfa_fcport_sm_enabling(struct bfa_fcport_s *fcport,
- enum bfa_fcport_sm_event event);
-static void bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport,
- enum bfa_fcport_sm_event event);
-static void bfa_fcport_sm_linkup(struct bfa_fcport_s *fcport,
- enum bfa_fcport_sm_event event);
-static void bfa_fcport_sm_disabling(struct bfa_fcport_s *fcport,
- enum bfa_fcport_sm_event event);
-static void bfa_fcport_sm_disabling_qwait(struct bfa_fcport_s *fcport,
- enum bfa_fcport_sm_event event);
-static void bfa_fcport_sm_disabled(struct bfa_fcport_s *fcport,
- enum bfa_fcport_sm_event event);
-static void bfa_fcport_sm_stopped(struct bfa_fcport_s *fcport,
- enum bfa_fcport_sm_event event);
-static void bfa_fcport_sm_iocdown(struct bfa_fcport_s *fcport,
- enum bfa_fcport_sm_event event);
-static void bfa_fcport_sm_iocfail(struct bfa_fcport_s *fcport,
- enum bfa_fcport_sm_event event);
-
-static void bfa_fcport_ln_sm_dn(struct bfa_fcport_ln_s *ln,
- enum bfa_fcport_ln_sm_event event);
-static void bfa_fcport_ln_sm_dn_nf(struct bfa_fcport_ln_s *ln,
- enum bfa_fcport_ln_sm_event event);
-static void bfa_fcport_ln_sm_dn_up_nf(struct bfa_fcport_ln_s *ln,
- enum bfa_fcport_ln_sm_event event);
-static void bfa_fcport_ln_sm_up(struct bfa_fcport_ln_s *ln,
- enum bfa_fcport_ln_sm_event event);
-static void bfa_fcport_ln_sm_up_nf(struct bfa_fcport_ln_s *ln,
- enum bfa_fcport_ln_sm_event event);
-static void bfa_fcport_ln_sm_up_dn_nf(struct bfa_fcport_ln_s *ln,
- enum bfa_fcport_ln_sm_event event);
-static void bfa_fcport_ln_sm_up_dn_up_nf(struct bfa_fcport_ln_s *ln,
- enum bfa_fcport_ln_sm_event event);
-
-static struct bfa_sm_table_s hal_pport_sm_table[] = {
- {BFA_SM(bfa_fcport_sm_uninit), BFA_PPORT_ST_UNINIT},
- {BFA_SM(bfa_fcport_sm_enabling_qwait), BFA_PPORT_ST_ENABLING_QWAIT},
- {BFA_SM(bfa_fcport_sm_enabling), BFA_PPORT_ST_ENABLING},
- {BFA_SM(bfa_fcport_sm_linkdown), BFA_PPORT_ST_LINKDOWN},
- {BFA_SM(bfa_fcport_sm_linkup), BFA_PPORT_ST_LINKUP},
- {BFA_SM(bfa_fcport_sm_disabling_qwait), BFA_PPORT_ST_DISABLING_QWAIT},
- {BFA_SM(bfa_fcport_sm_disabling), BFA_PPORT_ST_DISABLING},
- {BFA_SM(bfa_fcport_sm_disabled), BFA_PPORT_ST_DISABLED},
- {BFA_SM(bfa_fcport_sm_stopped), BFA_PPORT_ST_STOPPED},
- {BFA_SM(bfa_fcport_sm_iocdown), BFA_PPORT_ST_IOCDOWN},
- {BFA_SM(bfa_fcport_sm_iocfail), BFA_PPORT_ST_IOCDOWN},
-};
-
-static void
-bfa_fcport_aen_post(struct bfa_fcport_s *fcport, enum bfa_port_aen_event event)
-{
- union bfa_aen_data_u aen_data;
- struct bfa_log_mod_s *logmod = fcport->bfa->logm;
- wwn_t pwwn = fcport->pwwn;
- char pwwn_ptr[BFA_STRING_32];
-
- memset(&aen_data, 0, sizeof(aen_data));
- wwn2str(pwwn_ptr, pwwn);
- bfa_log(logmod, BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, event), pwwn_ptr);
-
- aen_data.port.ioc_type = bfa_get_type(fcport->bfa);
- aen_data.port.pwwn = pwwn;
-}
-
-static void
-bfa_fcport_sm_uninit(struct bfa_fcport_s *fcport,
- enum bfa_fcport_sm_event event)
-{
- bfa_trc(fcport->bfa, event);
-
- switch (event) {
- case BFA_FCPORT_SM_START:
- /**
- * Start event after IOC is configured and BFA is started.
- */
- if (bfa_fcport_send_enable(fcport))
- bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
- else
- bfa_sm_set_state(fcport, bfa_fcport_sm_enabling_qwait);
- break;
-
- case BFA_FCPORT_SM_ENABLE:
- /**
- * Port is persistently configured to be in enabled state. Do
- * not change state. Port enabling is done when START event is
- * received.
- */
- break;
-
- case BFA_FCPORT_SM_DISABLE:
- /**
- * If a port is persistently configured to be disabled, the
- * first event will a port disable request.
- */
- bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
- break;
-
- case BFA_FCPORT_SM_HWFAIL:
- bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
- break;
-
- default:
- bfa_sm_fault(fcport->bfa, event);
- }
-}
-
-static void
-bfa_fcport_sm_enabling_qwait(struct bfa_fcport_s *fcport,
- enum bfa_fcport_sm_event event)
-{
- bfa_trc(fcport->bfa, event);
-
- switch (event) {
- case BFA_FCPORT_SM_QRESUME:
- bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
- bfa_fcport_send_enable(fcport);
- break;
-
- case BFA_FCPORT_SM_STOP:
- bfa_reqq_wcancel(&fcport->reqq_wait);
- bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
- break;
-
- case BFA_FCPORT_SM_ENABLE:
- /**
- * Already enable is in progress.
- */
- break;
-
- case BFA_FCPORT_SM_DISABLE:
- /**
- * Just send disable request to firmware when room becomes
- * available in request queue.
- */
- bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
- bfa_reqq_wcancel(&fcport->reqq_wait);
- bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
- BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
- bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
- break;
-
- case BFA_FCPORT_SM_LINKUP:
- case BFA_FCPORT_SM_LINKDOWN:
- /**
- * Possible to get link events when doing back-to-back
- * enable/disables.
- */
- break;
-
- case BFA_FCPORT_SM_HWFAIL:
- bfa_reqq_wcancel(&fcport->reqq_wait);
- bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
- break;
-
- default:
- bfa_sm_fault(fcport->bfa, event);
- }
-}
-
-static void
-bfa_fcport_sm_enabling(struct bfa_fcport_s *fcport,
- enum bfa_fcport_sm_event event)
-{
- bfa_trc(fcport->bfa, event);
-
- switch (event) {
- case BFA_FCPORT_SM_FWRSP:
- case BFA_FCPORT_SM_LINKDOWN:
- bfa_sm_set_state(fcport, bfa_fcport_sm_linkdown);
- break;
-
- case BFA_FCPORT_SM_LINKUP:
- bfa_fcport_update_linkinfo(fcport);
- bfa_sm_set_state(fcport, bfa_fcport_sm_linkup);
-
- bfa_assert(fcport->event_cbfn);
- bfa_fcport_callback(fcport, BFA_PPORT_LINKUP);
- break;
-
- case BFA_FCPORT_SM_ENABLE:
- /**
- * Already being enabled.
- */
- break;
-
- case BFA_FCPORT_SM_DISABLE:
- if (bfa_fcport_send_disable(fcport))
- bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
- else
- bfa_sm_set_state(fcport, bfa_fcport_sm_disabling_qwait);
-
- bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
- BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
- bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
- break;
-
- case BFA_FCPORT_SM_STOP:
- bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
- break;
-
- case BFA_FCPORT_SM_HWFAIL:
- bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
- break;
-
- default:
- bfa_sm_fault(fcport->bfa, event);
- }
-}
-
-static void
-bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport,
- enum bfa_fcport_sm_event event)
-{
- struct bfi_fcport_event_s *pevent = fcport->event_arg.i2hmsg.event;
- bfa_trc(fcport->bfa, event);
-
- switch (event) {
- case BFA_FCPORT_SM_LINKUP:
- bfa_fcport_update_linkinfo(fcport);
- bfa_sm_set_state(fcport, bfa_fcport_sm_linkup);
- bfa_assert(fcport->event_cbfn);
- bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
- BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkup");
-
- if (!bfa_ioc_get_fcmode(&fcport->bfa->ioc)) {
-
- bfa_trc(fcport->bfa,
- pevent->link_state.vc_fcf.fcf.fipenabled);
- bfa_trc(fcport->bfa,
- pevent->link_state.vc_fcf.fcf.fipfailed);
-
- if (pevent->link_state.vc_fcf.fcf.fipfailed)
- bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
- BFA_PL_EID_FIP_FCF_DISC, 0,
- "FIP FCF Discovery Failed");
- else
- bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
- BFA_PL_EID_FIP_FCF_DISC, 0,
- "FIP FCF Discovered");
- }
-
- bfa_fcport_callback(fcport, BFA_PPORT_LINKUP);
- bfa_fcport_aen_post(fcport, BFA_PORT_AEN_ONLINE);
- /**
- * If QoS is enabled and it is not online,
- * Send a separate event.
- */
- if ((fcport->cfg.qos_enabled)
- && (bfa_os_ntohl(fcport->qos_attr.state) != BFA_QOS_ONLINE))
- bfa_fcport_aen_post(fcport, BFA_PORT_AEN_QOS_NEG);
-
- break;
-
- case BFA_FCPORT_SM_LINKDOWN:
- /**
- * Possible to get link down event.
- */
- break;
-
- case BFA_FCPORT_SM_ENABLE:
- /**
- * Already enabled.
- */
- break;
-
- case BFA_FCPORT_SM_DISABLE:
- if (bfa_fcport_send_disable(fcport))
- bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
- else
- bfa_sm_set_state(fcport, bfa_fcport_sm_disabling_qwait);
-
- bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
- BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
- bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
- break;
-
- case BFA_FCPORT_SM_STOP:
- bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
- break;
-
- case BFA_FCPORT_SM_HWFAIL:
- bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
- break;
-
- default:
- bfa_sm_fault(fcport->bfa, event);
- }
-}
-
-static void
-bfa_fcport_sm_linkup(struct bfa_fcport_s *fcport,
- enum bfa_fcport_sm_event event)
-{
- bfa_trc(fcport->bfa, event);
-
- switch (event) {
- case BFA_FCPORT_SM_ENABLE:
- /**
- * Already enabled.
- */
- break;
-
- case BFA_FCPORT_SM_DISABLE:
- if (bfa_fcport_send_disable(fcport))
- bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
- else
- bfa_sm_set_state(fcport, bfa_fcport_sm_disabling_qwait);
-
- bfa_fcport_reset_linkinfo(fcport);
- bfa_fcport_callback(fcport, BFA_PPORT_LINKDOWN);
- bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
- BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
- bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE);
- bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
- break;
-
- case BFA_FCPORT_SM_LINKDOWN:
- bfa_sm_set_state(fcport, bfa_fcport_sm_linkdown);
- bfa_fcport_reset_linkinfo(fcport);
- bfa_fcport_callback(fcport, BFA_PPORT_LINKDOWN);
- bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
- BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkdown");
- if (BFA_PORT_IS_DISABLED(fcport->bfa))
- bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE);
- else
- bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
- break;
-
- case BFA_FCPORT_SM_STOP:
- bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
- bfa_fcport_reset_linkinfo(fcport);
- if (BFA_PORT_IS_DISABLED(fcport->bfa))
- bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE);
- else
- bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
- break;
-
- case BFA_FCPORT_SM_HWFAIL:
- bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
- bfa_fcport_reset_linkinfo(fcport);
- bfa_fcport_callback(fcport, BFA_PPORT_LINKDOWN);
- if (BFA_PORT_IS_DISABLED(fcport->bfa))
- bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE);
- else
- bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
- break;
-
- default:
- bfa_sm_fault(fcport->bfa, event);
- }
-}
-
-static void
-bfa_fcport_sm_disabling_qwait(struct bfa_fcport_s *fcport,
- enum bfa_fcport_sm_event event)
-{
- bfa_trc(fcport->bfa, event);
-
- switch (event) {
- case BFA_FCPORT_SM_QRESUME:
- bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
- bfa_fcport_send_disable(fcport);
- break;
-
- case BFA_FCPORT_SM_STOP:
- bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
- bfa_reqq_wcancel(&fcport->reqq_wait);
- break;
-
- case BFA_FCPORT_SM_DISABLE:
- /**
- * Already being disabled.
- */
- break;
-
- case BFA_FCPORT_SM_LINKUP:
- case BFA_FCPORT_SM_LINKDOWN:
- /**
- * Possible to get link events when doing back-to-back
- * enable/disables.
- */
- break;
-
- case BFA_FCPORT_SM_HWFAIL:
- bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
- bfa_reqq_wcancel(&fcport->reqq_wait);
- break;
-
- default:
- bfa_sm_fault(fcport->bfa, event);
- }
-}
-
-static void
-bfa_fcport_sm_disabling(struct bfa_fcport_s *fcport,
- enum bfa_fcport_sm_event event)
-{
- bfa_trc(fcport->bfa, event);
-
- switch (event) {
- case BFA_FCPORT_SM_FWRSP:
- bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
- break;
-
- case BFA_FCPORT_SM_DISABLE:
- /**
- * Already being disabled.
- */
- break;
-
- case BFA_FCPORT_SM_ENABLE:
- if (bfa_fcport_send_enable(fcport))
- bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
- else
- bfa_sm_set_state(fcport, bfa_fcport_sm_enabling_qwait);
-
- bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
- BFA_PL_EID_PORT_ENABLE, 0, "Port Enable");
- bfa_fcport_aen_post(fcport, BFA_PORT_AEN_ENABLE);
- break;
-
- case BFA_FCPORT_SM_STOP:
- bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
- break;
-
- case BFA_FCPORT_SM_LINKUP:
- case BFA_FCPORT_SM_LINKDOWN:
- /**
- * Possible to get link events when doing back-to-back
- * enable/disables.
- */
- break;
-
- case BFA_FCPORT_SM_HWFAIL:
- bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
- break;
-
- default:
- bfa_sm_fault(fcport->bfa, event);
- }
-}
-
-static void
-bfa_fcport_sm_disabled(struct bfa_fcport_s *fcport,
- enum bfa_fcport_sm_event event)
-{
- bfa_trc(fcport->bfa, event);
-
- switch (event) {
- case BFA_FCPORT_SM_START:
- /**
- * Ignore start event for a port that is disabled.
- */
- break;
-
- case BFA_FCPORT_SM_STOP:
- bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
- break;
-
- case BFA_FCPORT_SM_ENABLE:
- if (bfa_fcport_send_enable(fcport))
- bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
- else
- bfa_sm_set_state(fcport, bfa_fcport_sm_enabling_qwait);
-
- bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
- BFA_PL_EID_PORT_ENABLE, 0, "Port Enable");
- bfa_fcport_aen_post(fcport, BFA_PORT_AEN_ENABLE);
- break;
-
- case BFA_FCPORT_SM_DISABLE:
- /**
- * Already disabled.
- */
- break;
-
- case BFA_FCPORT_SM_HWFAIL:
- bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
- break;
-
- default:
- bfa_sm_fault(fcport->bfa, event);
- }
-}
-
-static void
-bfa_fcport_sm_stopped(struct bfa_fcport_s *fcport,
- enum bfa_fcport_sm_event event)
-{
- bfa_trc(fcport->bfa, event);
-
- switch (event) {
- case BFA_FCPORT_SM_START:
- if (bfa_fcport_send_enable(fcport))
- bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
- else
- bfa_sm_set_state(fcport, bfa_fcport_sm_enabling_qwait);
- break;
-
- default:
- /**
- * Ignore all other events.
- */
- ;
- }
-}
-
-/**
- * Port is enabled. IOC is down/failed.
- */
-static void
-bfa_fcport_sm_iocdown(struct bfa_fcport_s *fcport,
- enum bfa_fcport_sm_event event)
-{
- bfa_trc(fcport->bfa, event);
-
- switch (event) {
- case BFA_FCPORT_SM_START:
- if (bfa_fcport_send_enable(fcport))
- bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
- else
- bfa_sm_set_state(fcport, bfa_fcport_sm_enabling_qwait);
- break;
-
- default:
- /**
- * Ignore all events.
- */
- ;
- }
-}
-
-/**
- * Port is disabled. IOC is down/failed.
- */
-static void
-bfa_fcport_sm_iocfail(struct bfa_fcport_s *fcport,
- enum bfa_fcport_sm_event event)
-{
- bfa_trc(fcport->bfa, event);
-
- switch (event) {
- case BFA_FCPORT_SM_START:
- bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
- break;
-
- case BFA_FCPORT_SM_ENABLE:
- bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
- break;
-
- default:
- /**
- * Ignore all events.
- */
- ;
- }
-}
-
-/**
- * Link state is down
- */
-static void
-bfa_fcport_ln_sm_dn(struct bfa_fcport_ln_s *ln,
- enum bfa_fcport_ln_sm_event event)
-{
- bfa_trc(ln->fcport->bfa, event);
-
- switch (event) {
- case BFA_FCPORT_LN_SM_LINKUP:
- bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_nf);
- bfa_fcport_queue_cb(ln, BFA_PPORT_LINKUP);
- break;
-
- default:
- bfa_sm_fault(ln->fcport->bfa, event);
- }
-}
-
-/**
- * Link state is waiting for down notification
- */
-static void
-bfa_fcport_ln_sm_dn_nf(struct bfa_fcport_ln_s *ln,
- enum bfa_fcport_ln_sm_event event)
-{
- bfa_trc(ln->fcport->bfa, event);
-
- switch (event) {
- case BFA_FCPORT_LN_SM_LINKUP:
- bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_up_nf);
- break;
-
- case BFA_FCPORT_LN_SM_NOTIFICATION:
- bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn);
- break;
-
- default:
- bfa_sm_fault(ln->fcport->bfa, event);
- }
-}
-
-/**
- * Link state is waiting for down notification and there is a pending up
- */
-static void
-bfa_fcport_ln_sm_dn_up_nf(struct bfa_fcport_ln_s *ln,
- enum bfa_fcport_ln_sm_event event)
-{
- bfa_trc(ln->fcport->bfa, event);
-
- switch (event) {
- case BFA_FCPORT_LN_SM_LINKDOWN:
- bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_nf);
- break;
-
- case BFA_FCPORT_LN_SM_NOTIFICATION:
- bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_nf);
- bfa_fcport_queue_cb(ln, BFA_PPORT_LINKUP);
- break;
-
- default:
- bfa_sm_fault(ln->fcport->bfa, event);
- }
-}
-
-/**
- * Link state is up
- */
-static void
-bfa_fcport_ln_sm_up(struct bfa_fcport_ln_s *ln,
- enum bfa_fcport_ln_sm_event event)
-{
- bfa_trc(ln->fcport->bfa, event);
-
- switch (event) {
- case BFA_FCPORT_LN_SM_LINKDOWN:
- bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_nf);
- bfa_fcport_queue_cb(ln, BFA_PPORT_LINKDOWN);
- break;
-
- default:
- bfa_sm_fault(ln->fcport->bfa, event);
- }
-}
-
-/**
- * Link state is waiting for up notification
- */
-static void
-bfa_fcport_ln_sm_up_nf(struct bfa_fcport_ln_s *ln,
- enum bfa_fcport_ln_sm_event event)
-{
- bfa_trc(ln->fcport->bfa, event);
-
- switch (event) {
- case BFA_FCPORT_LN_SM_LINKDOWN:
- bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_dn_nf);
- break;
-
- case BFA_FCPORT_LN_SM_NOTIFICATION:
- bfa_sm_set_state(ln, bfa_fcport_ln_sm_up);
- break;
-
- default:
- bfa_sm_fault(ln->fcport->bfa, event);
- }
-}
-
-/**
- * Link state is waiting for up notification and there is a pending down
- */
-static void
-bfa_fcport_ln_sm_up_dn_nf(struct bfa_fcport_ln_s *ln,
- enum bfa_fcport_ln_sm_event event)
-{
- bfa_trc(ln->fcport->bfa, event);
-
- switch (event) {
- case BFA_FCPORT_LN_SM_LINKUP:
- bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_dn_up_nf);
- break;
-
- case BFA_FCPORT_LN_SM_NOTIFICATION:
- bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_nf);
- bfa_fcport_queue_cb(ln, BFA_PPORT_LINKDOWN);
- break;
-
- default:
- bfa_sm_fault(ln->fcport->bfa, event);
- }
-}
-
-/**
- * Link state is waiting for up notification and there are pending down and up
- */
-static void
-bfa_fcport_ln_sm_up_dn_up_nf(struct bfa_fcport_ln_s *ln,
- enum bfa_fcport_ln_sm_event event)
-{
- bfa_trc(ln->fcport->bfa, event);
-
- switch (event) {
- case BFA_FCPORT_LN_SM_LINKDOWN:
- bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_dn_nf);
- break;
-
- case BFA_FCPORT_LN_SM_NOTIFICATION:
- bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_up_nf);
- bfa_fcport_queue_cb(ln, BFA_PPORT_LINKDOWN);
- break;
-
- default:
- bfa_sm_fault(ln->fcport->bfa, event);
- }
-}
-
-/**
- * bfa_pport_private
- */
-
-static void
-__bfa_cb_fcport_event(void *cbarg, bfa_boolean_t complete)
-{
- struct bfa_fcport_ln_s *ln = cbarg;
-
- if (complete)
- ln->fcport->event_cbfn(ln->fcport->event_cbarg, ln->ln_event);
- else
- bfa_sm_send_event(ln, BFA_FCPORT_LN_SM_NOTIFICATION);
-}
-
-static void
-bfa_fcport_callback(struct bfa_fcport_s *fcport, enum bfa_pport_linkstate event)
-{
- if (fcport->bfa->fcs) {
- fcport->event_cbfn(fcport->event_cbarg, event);
- return;
- }
-
- switch (event) {
- case BFA_PPORT_LINKUP:
- bfa_sm_send_event(&fcport->ln, BFA_FCPORT_LN_SM_LINKUP);
- break;
- case BFA_PPORT_LINKDOWN:
- bfa_sm_send_event(&fcport->ln, BFA_FCPORT_LN_SM_LINKDOWN);
- break;
- default:
- bfa_assert(0);
- }
-}
-
-static void
-bfa_fcport_queue_cb(struct bfa_fcport_ln_s *ln, enum bfa_pport_linkstate event)
-{
- ln->ln_event = event;
- bfa_cb_queue(ln->fcport->bfa, &ln->ln_qe, __bfa_cb_fcport_event, ln);
-}
-
-#define FCPORT_STATS_DMA_SZ (BFA_ROUNDUP(sizeof(union bfa_fcport_stats_u), \
- BFA_CACHELINE_SZ))
-
-static void
-bfa_fcport_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
- u32 *dm_len)
-{
- *dm_len += FCPORT_STATS_DMA_SZ;
-}
-
-static void
-bfa_fcport_qresume(void *cbarg)
-{
- struct bfa_fcport_s *fcport = cbarg;
-
- bfa_sm_send_event(fcport, BFA_FCPORT_SM_QRESUME);
-}
-
-static void
-bfa_fcport_mem_claim(struct bfa_fcport_s *fcport, struct bfa_meminfo_s *meminfo)
-{
- u8 *dm_kva;
- u64 dm_pa;
-
- dm_kva = bfa_meminfo_dma_virt(meminfo);
- dm_pa = bfa_meminfo_dma_phys(meminfo);
-
- fcport->stats_kva = dm_kva;
- fcport->stats_pa = dm_pa;
- fcport->stats = (union bfa_fcport_stats_u *)dm_kva;
-
- dm_kva += FCPORT_STATS_DMA_SZ;
- dm_pa += FCPORT_STATS_DMA_SZ;
-
- bfa_meminfo_dma_virt(meminfo) = dm_kva;
- bfa_meminfo_dma_phys(meminfo) = dm_pa;
-}
-
-/**
- * Memory initialization.
- */
-static void
-bfa_fcport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
- struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
- struct bfa_pport_cfg_s *port_cfg = &fcport->cfg;
- struct bfa_fcport_ln_s *ln = &fcport->ln;
- struct bfa_timeval_s tv;
-
- bfa_os_memset(fcport, 0, sizeof(struct bfa_fcport_s));
- fcport->bfa = bfa;
- ln->fcport = fcport;
-
- bfa_fcport_mem_claim(fcport, meminfo);
-
- bfa_sm_set_state(fcport, bfa_fcport_sm_uninit);
- bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn);
-
- /**
- * initialize time stamp for stats reset
- */
- bfa_os_gettimeofday(&tv);
- fcport->stats_reset_time = tv.tv_sec;
-
- /**
- * initialize and set default configuration
- */
- port_cfg->topology = BFA_PPORT_TOPOLOGY_P2P;
- port_cfg->speed = BFA_PPORT_SPEED_AUTO;
- port_cfg->trunked = BFA_FALSE;
- port_cfg->maxfrsize = 0;
-
- port_cfg->trl_def_speed = BFA_PPORT_SPEED_1GBPS;
-
- bfa_reqq_winit(&fcport->reqq_wait, bfa_fcport_qresume, fcport);
-}
-
-static void
-bfa_fcport_detach(struct bfa_s *bfa)
-{
-}
-
-/**
- * Called when IOC is ready.
- */
-static void
-bfa_fcport_start(struct bfa_s *bfa)
-{
- bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_START);
-}
-
-/**
- * Called before IOC is stopped.
- */
-static void
-bfa_fcport_stop(struct bfa_s *bfa)
-{
- bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_STOP);
-}
-
-/**
- * Called when IOC failure is detected.
- */
-static void
-bfa_fcport_iocdisable(struct bfa_s *bfa)
-{
- bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_HWFAIL);
-}
-
-static void
-bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport)
-{
- struct bfi_fcport_event_s *pevent = fcport->event_arg.i2hmsg.event;
-
- fcport->speed = pevent->link_state.speed;
- fcport->topology = pevent->link_state.topology;
-
- if (fcport->topology == BFA_PPORT_TOPOLOGY_LOOP)
- fcport->myalpa = 0;
-
- /*
- * QoS Details
- */
- bfa_os_assign(fcport->qos_attr, pevent->link_state.qos_attr);
- bfa_os_assign(fcport->qos_vc_attr,
- pevent->link_state.vc_fcf.qos_vc_attr);
-
-
- bfa_trc(fcport->bfa, fcport->speed);
- bfa_trc(fcport->bfa, fcport->topology);
-}
-
-static void
-bfa_fcport_reset_linkinfo(struct bfa_fcport_s *fcport)
-{
- fcport->speed = BFA_PPORT_SPEED_UNKNOWN;
- fcport->topology = BFA_PPORT_TOPOLOGY_NONE;
-}
-
-/**
- * Send port enable message to firmware.
- */
-static bfa_boolean_t
-bfa_fcport_send_enable(struct bfa_fcport_s *fcport)
-{
- struct bfi_fcport_enable_req_s *m;
-
- /**
- * Increment message tag before queue check, so that responses to old
- * requests are discarded.
- */
- fcport->msgtag++;
-
- /**
- * check for room in queue to send request now
- */
- m = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
- if (!m) {
- bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
- &fcport->reqq_wait);
- return BFA_FALSE;
- }
-
- bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_ENABLE_REQ,
- bfa_lpuid(fcport->bfa));
- m->nwwn = fcport->nwwn;
- m->pwwn = fcport->pwwn;
- m->port_cfg = fcport->cfg;
- m->msgtag = fcport->msgtag;
- m->port_cfg.maxfrsize = bfa_os_htons(fcport->cfg.maxfrsize);
- bfa_dma_be_addr_set(m->stats_dma_addr, fcport->stats_pa);
- bfa_trc(fcport->bfa, m->stats_dma_addr.a32.addr_lo);
- bfa_trc(fcport->bfa, m->stats_dma_addr.a32.addr_hi);
-
- /**
- * queue I/O message to firmware
- */
- bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT);
- return BFA_TRUE;
-}
-
-/**
- * Send port disable message to firmware.
- */
-static bfa_boolean_t
-bfa_fcport_send_disable(struct bfa_fcport_s *fcport)
-{
- struct bfi_fcport_req_s *m;
-
- /**
- * Increment message tag before queue check, so that responses to old
- * requests are discarded.
- */
- fcport->msgtag++;
-
- /**
- * check for room in queue to send request now
- */
- m = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
- if (!m) {
- bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
- &fcport->reqq_wait);
- return BFA_FALSE;
- }
-
- bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_DISABLE_REQ,
- bfa_lpuid(fcport->bfa));
- m->msgtag = fcport->msgtag;
-
- /**
- * queue I/O message to firmware
- */
- bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT);
-
- return BFA_TRUE;
-}
-
-static void
-bfa_fcport_set_wwns(struct bfa_fcport_s *fcport)
-{
- fcport->pwwn = bfa_ioc_get_pwwn(&fcport->bfa->ioc);
- fcport->nwwn = bfa_ioc_get_nwwn(&fcport->bfa->ioc);
-
- bfa_trc(fcport->bfa, fcport->pwwn);
- bfa_trc(fcport->bfa, fcport->nwwn);
-}
-
-static void
-bfa_fcport_send_txcredit(void *port_cbarg)
-{
-
- struct bfa_fcport_s *fcport = port_cbarg;
- struct bfi_fcport_set_svc_params_req_s *m;
-
- /**
- * check for room in queue to send request now
- */
- m = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
- if (!m) {
- bfa_trc(fcport->bfa, fcport->cfg.tx_bbcredit);
- return;
- }
-
- bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_SET_SVC_PARAMS_REQ,
- bfa_lpuid(fcport->bfa));
- m->tx_bbcredit = bfa_os_htons((u16) fcport->cfg.tx_bbcredit);
-
- /**
- * queue I/O message to firmware
- */
- bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT);
-}
-
-static void
-bfa_fcport_qos_stats_swap(struct bfa_qos_stats_s *d,
- struct bfa_qos_stats_s *s)
-{
- u32 *dip = (u32 *) d;
- u32 *sip = (u32 *) s;
- int i;
-
- /* Now swap the 32 bit fields */
- for (i = 0; i < (sizeof(struct bfa_qos_stats_s)/sizeof(u32)); ++i)
- dip[i] = bfa_os_ntohl(sip[i]);
-}
-
-static void
-bfa_fcport_fcoe_stats_swap(struct bfa_fcoe_stats_s *d,
- struct bfa_fcoe_stats_s *s)
-{
- u32 *dip = (u32 *) d;
- u32 *sip = (u32 *) s;
- int i;
-
- for (i = 0; i < ((sizeof(struct bfa_fcoe_stats_s))/sizeof(u32));
- i = i + 2) {
-#ifdef __BIGENDIAN
- dip[i] = bfa_os_ntohl(sip[i]);
- dip[i + 1] = bfa_os_ntohl(sip[i + 1]);
-#else
- dip[i] = bfa_os_ntohl(sip[i + 1]);
- dip[i + 1] = bfa_os_ntohl(sip[i]);
-#endif
- }
-}
-
-static void
-__bfa_cb_fcport_stats_get(void *cbarg, bfa_boolean_t complete)
-{
- struct bfa_fcport_s *fcport = cbarg;
-
- if (complete) {
- if (fcport->stats_status == BFA_STATUS_OK) {
- struct bfa_timeval_s tv;
-
- /* Swap FC QoS or FCoE stats */
- if (bfa_ioc_get_fcmode(&fcport->bfa->ioc)) {
- bfa_fcport_qos_stats_swap(
- &fcport->stats_ret->fcqos,
- &fcport->stats->fcqos);
- } else {
- bfa_fcport_fcoe_stats_swap(
- &fcport->stats_ret->fcoe,
- &fcport->stats->fcoe);
-
- bfa_os_gettimeofday(&tv);
- fcport->stats_ret->fcoe.secs_reset =
- tv.tv_sec - fcport->stats_reset_time;
- }
- }
- fcport->stats_cbfn(fcport->stats_cbarg, fcport->stats_status);
- } else {
- fcport->stats_busy = BFA_FALSE;
- fcport->stats_status = BFA_STATUS_OK;
- }
-}
-
-static void
-bfa_fcport_stats_get_timeout(void *cbarg)
-{
- struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
-
- bfa_trc(fcport->bfa, fcport->stats_qfull);
-
- if (fcport->stats_qfull) {
- bfa_reqq_wcancel(&fcport->stats_reqq_wait);
- fcport->stats_qfull = BFA_FALSE;
- }
-
- fcport->stats_status = BFA_STATUS_ETIMER;
- bfa_cb_queue(fcport->bfa, &fcport->hcb_qe, __bfa_cb_fcport_stats_get,
- fcport);
-}
-
-static void
-bfa_fcport_send_stats_get(void *cbarg)
-{
- struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
- struct bfi_fcport_req_s *msg;
-
- msg = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
-
- if (!msg) {
- fcport->stats_qfull = BFA_TRUE;
- bfa_reqq_winit(&fcport->stats_reqq_wait,
- bfa_fcport_send_stats_get, fcport);
- bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
- &fcport->stats_reqq_wait);
- return;
- }
- fcport->stats_qfull = BFA_FALSE;
-
- bfa_os_memset(msg, 0, sizeof(struct bfi_fcport_req_s));
- bfi_h2i_set(msg->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_STATS_GET_REQ,
- bfa_lpuid(fcport->bfa));
- bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT);
-}
-
-static void
-__bfa_cb_fcport_stats_clr(void *cbarg, bfa_boolean_t complete)
-{
- struct bfa_fcport_s *fcport = cbarg;
-
- if (complete) {
- struct bfa_timeval_s tv;
-
- /**
- * re-initialize time stamp for stats reset
- */
- bfa_os_gettimeofday(&tv);
- fcport->stats_reset_time = tv.tv_sec;
-
- fcport->stats_cbfn(fcport->stats_cbarg, fcport->stats_status);
- } else {
- fcport->stats_busy = BFA_FALSE;
- fcport->stats_status = BFA_STATUS_OK;
- }
-}
-
-static void
-bfa_fcport_stats_clr_timeout(void *cbarg)
-{
- struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
-
- bfa_trc(fcport->bfa, fcport->stats_qfull);
-
- if (fcport->stats_qfull) {
- bfa_reqq_wcancel(&fcport->stats_reqq_wait);
- fcport->stats_qfull = BFA_FALSE;
- }
-
- fcport->stats_status = BFA_STATUS_ETIMER;
- bfa_cb_queue(fcport->bfa, &fcport->hcb_qe,
- __bfa_cb_fcport_stats_clr, fcport);
-}
-
-static void
-bfa_fcport_send_stats_clear(void *cbarg)
-{
- struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
- struct bfi_fcport_req_s *msg;
-
- msg = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
-
- if (!msg) {
- fcport->stats_qfull = BFA_TRUE;
- bfa_reqq_winit(&fcport->stats_reqq_wait,
- bfa_fcport_send_stats_clear, fcport);
- bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
- &fcport->stats_reqq_wait);
- return;
- }
- fcport->stats_qfull = BFA_FALSE;
-
- bfa_os_memset(msg, 0, sizeof(struct bfi_fcport_req_s));
- bfi_h2i_set(msg->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_STATS_CLEAR_REQ,
- bfa_lpuid(fcport->bfa));
- bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT);
-}
-
-/**
- * bfa_pport_public
- */
-
-/**
- * Called to initialize port attributes
- */
-void
-bfa_fcport_init(struct bfa_s *bfa)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
- /**
- * Initialize port attributes from IOC hardware data.
- */
- bfa_fcport_set_wwns(fcport);
- if (fcport->cfg.maxfrsize == 0)
- fcport->cfg.maxfrsize = bfa_ioc_maxfrsize(&bfa->ioc);
- fcport->cfg.rx_bbcredit = bfa_ioc_rx_bbcredit(&bfa->ioc);
- fcport->speed_sup = bfa_ioc_speed_sup(&bfa->ioc);
-
- bfa_assert(fcport->cfg.maxfrsize);
- bfa_assert(fcport->cfg.rx_bbcredit);
- bfa_assert(fcport->speed_sup);
-}
-
-
-/**
- * Firmware message handler.
- */
-void
-bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
- union bfi_fcport_i2h_msg_u i2hmsg;
-
- i2hmsg.msg = msg;
- fcport->event_arg.i2hmsg = i2hmsg;
-
- switch (msg->mhdr.msg_id) {
- case BFI_FCPORT_I2H_ENABLE_RSP:
- if (fcport->msgtag == i2hmsg.penable_rsp->msgtag)
- bfa_sm_send_event(fcport, BFA_FCPORT_SM_FWRSP);
- break;
-
- case BFI_FCPORT_I2H_DISABLE_RSP:
- if (fcport->msgtag == i2hmsg.pdisable_rsp->msgtag)
- bfa_sm_send_event(fcport, BFA_FCPORT_SM_FWRSP);
- break;
-
- case BFI_FCPORT_I2H_EVENT:
- switch (i2hmsg.event->link_state.linkstate) {
- case BFA_PPORT_LINKUP:
- bfa_sm_send_event(fcport, BFA_FCPORT_SM_LINKUP);
- break;
- case BFA_PPORT_LINKDOWN:
- bfa_sm_send_event(fcport, BFA_FCPORT_SM_LINKDOWN);
- break;
- case BFA_PPORT_TRUNK_LINKDOWN:
- /** todo: event notification */
- break;
- }
- break;
-
- case BFI_FCPORT_I2H_STATS_GET_RSP:
- /*
- * check for timer pop before processing the rsp
- */
- if (fcport->stats_busy == BFA_FALSE ||
- fcport->stats_status == BFA_STATUS_ETIMER)
- break;
-
- bfa_timer_stop(&fcport->timer);
- fcport->stats_status = i2hmsg.pstatsget_rsp->status;
- bfa_cb_queue(fcport->bfa, &fcport->hcb_qe,
- __bfa_cb_fcport_stats_get, fcport);
- break;
-
- case BFI_FCPORT_I2H_STATS_CLEAR_RSP:
- /*
- * check for timer pop before processing the rsp
- */
- if (fcport->stats_busy == BFA_FALSE ||
- fcport->stats_status == BFA_STATUS_ETIMER)
- break;
-
- bfa_timer_stop(&fcport->timer);
- fcport->stats_status = BFA_STATUS_OK;
- bfa_cb_queue(fcport->bfa, &fcport->hcb_qe,
- __bfa_cb_fcport_stats_clr, fcport);
- break;
-
- default:
- bfa_assert(0);
- break;
- }
-}
-
-/**
- * bfa_pport_api
- */
-
-/**
- * Registered callback for port events.
- */
-void
-bfa_fcport_event_register(struct bfa_s *bfa,
- void (*cbfn) (void *cbarg, bfa_pport_event_t event),
- void *cbarg)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
- fcport->event_cbfn = cbfn;
- fcport->event_cbarg = cbarg;
-}
-
-bfa_status_t
-bfa_fcport_enable(struct bfa_s *bfa)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
- struct bfa_iocfc_s *iocfc = &bfa->iocfc;
- struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp;
-
- /* if port is PBC disabled, return error */
- if (cfgrsp->pbc_cfg.port_enabled == BFI_PBC_PORT_DISABLED) {
- bfa_trc(bfa, fcport->pwwn);
- return BFA_STATUS_PBC;
- }
-
- if (bfa_ioc_is_disabled(&bfa->ioc))
- return BFA_STATUS_IOC_DISABLED;
-
- if (fcport->diag_busy)
- return BFA_STATUS_DIAG_BUSY;
- else if (bfa_sm_cmp_state
- (BFA_FCPORT_MOD(bfa), bfa_fcport_sm_disabling_qwait))
- return BFA_STATUS_DEVBUSY;
-
- bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_ENABLE);
- return BFA_STATUS_OK;
-}
-
-bfa_status_t
-bfa_fcport_disable(struct bfa_s *bfa)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
- struct bfa_iocfc_s *iocfc = &bfa->iocfc;
- struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp;
-
- /* if port is PBC disabled, return error */
- if (cfgrsp->pbc_cfg.port_enabled == BFI_PBC_PORT_DISABLED) {
- bfa_trc(bfa, fcport->pwwn);
- return BFA_STATUS_PBC;
- }
-
- bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DISABLE);
- return BFA_STATUS_OK;
-}
-
-/**
- * Configure port speed.
- */
-bfa_status_t
-bfa_fcport_cfg_speed(struct bfa_s *bfa, enum bfa_pport_speed speed)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
- bfa_trc(bfa, speed);
-
- if ((speed != BFA_PPORT_SPEED_AUTO) && (speed > fcport->speed_sup)) {
- bfa_trc(bfa, fcport->speed_sup);
- return BFA_STATUS_UNSUPP_SPEED;
- }
-
- fcport->cfg.speed = speed;
-
- return BFA_STATUS_OK;
-}
-
-/**
- * Get current speed.
- */
-enum bfa_pport_speed
-bfa_fcport_get_speed(struct bfa_s *bfa)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
- return fcport->speed;
-}
-
-/**
- * Configure port topology.
- */
-bfa_status_t
-bfa_fcport_cfg_topology(struct bfa_s *bfa, enum bfa_pport_topology topology)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
- bfa_trc(bfa, topology);
- bfa_trc(bfa, fcport->cfg.topology);
-
- switch (topology) {
- case BFA_PPORT_TOPOLOGY_P2P:
- case BFA_PPORT_TOPOLOGY_LOOP:
- case BFA_PPORT_TOPOLOGY_AUTO:
- break;
-
- default:
- return BFA_STATUS_EINVAL;
- }
-
- fcport->cfg.topology = topology;
- return BFA_STATUS_OK;
-}
-
-/**
- * Get current topology.
- */
-enum bfa_pport_topology
-bfa_fcport_get_topology(struct bfa_s *bfa)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
- return fcport->topology;
-}
-
-bfa_status_t
-bfa_fcport_cfg_hardalpa(struct bfa_s *bfa, u8 alpa)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
- bfa_trc(bfa, alpa);
- bfa_trc(bfa, fcport->cfg.cfg_hardalpa);
- bfa_trc(bfa, fcport->cfg.hardalpa);
-
- fcport->cfg.cfg_hardalpa = BFA_TRUE;
- fcport->cfg.hardalpa = alpa;
-
- return BFA_STATUS_OK;
-}
-
-bfa_status_t
-bfa_fcport_clr_hardalpa(struct bfa_s *bfa)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
- bfa_trc(bfa, fcport->cfg.cfg_hardalpa);
- bfa_trc(bfa, fcport->cfg.hardalpa);
-
- fcport->cfg.cfg_hardalpa = BFA_FALSE;
- return BFA_STATUS_OK;
-}
-
-bfa_boolean_t
-bfa_fcport_get_hardalpa(struct bfa_s *bfa, u8 *alpa)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
- *alpa = fcport->cfg.hardalpa;
- return fcport->cfg.cfg_hardalpa;
-}
-
-u8
-bfa_fcport_get_myalpa(struct bfa_s *bfa)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
- return fcport->myalpa;
-}
-
-bfa_status_t
-bfa_fcport_cfg_maxfrsize(struct bfa_s *bfa, u16 maxfrsize)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
- bfa_trc(bfa, maxfrsize);
- bfa_trc(bfa, fcport->cfg.maxfrsize);
-
- /*
- * with in range
- */
- if ((maxfrsize > FC_MAX_PDUSZ) || (maxfrsize < FC_MIN_PDUSZ))
- return BFA_STATUS_INVLD_DFSZ;
-
- /*
- * power of 2, if not the max frame size of 2112
- */
- if ((maxfrsize != FC_MAX_PDUSZ) && (maxfrsize & (maxfrsize - 1)))
- return BFA_STATUS_INVLD_DFSZ;
-
- fcport->cfg.maxfrsize = maxfrsize;
- return BFA_STATUS_OK;
-}
-
-u16
-bfa_fcport_get_maxfrsize(struct bfa_s *bfa)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
- return fcport->cfg.maxfrsize;
-}
-
-u32
-bfa_fcport_mypid(struct bfa_s *bfa)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
- return fcport->mypid;
-}
-
-u8
-bfa_fcport_get_rx_bbcredit(struct bfa_s *bfa)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
- return fcport->cfg.rx_bbcredit;
-}
-
-void
-bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
- fcport->cfg.tx_bbcredit = (u8) tx_bbcredit;
- bfa_fcport_send_txcredit(fcport);
-}
-
-/**
- * Get port attributes.
- */
-
-wwn_t
-bfa_fcport_get_wwn(struct bfa_s *bfa, bfa_boolean_t node)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
- if (node)
- return fcport->nwwn;
- else
- return fcport->pwwn;
-}
-
-void
-bfa_fcport_get_attr(struct bfa_s *bfa, struct bfa_pport_attr_s *attr)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
- struct bfa_iocfc_s *iocfc = &bfa->iocfc;
- struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp;
-
- bfa_os_memset(attr, 0, sizeof(struct bfa_pport_attr_s));
-
- attr->nwwn = fcport->nwwn;
- attr->pwwn = fcport->pwwn;
-
- attr->factorypwwn = bfa_ioc_get_mfg_pwwn(&bfa->ioc);
- attr->factorynwwn = bfa_ioc_get_mfg_nwwn(&bfa->ioc);
-
- bfa_os_memcpy(&attr->pport_cfg, &fcport->cfg,
- sizeof(struct bfa_pport_cfg_s));
- /*
- * speed attributes
- */
- attr->pport_cfg.speed = fcport->cfg.speed;
- attr->speed_supported = fcport->speed_sup;
- attr->speed = fcport->speed;
- attr->cos_supported = FC_CLASS_3;
-
- /*
- * topology attributes
- */
- attr->pport_cfg.topology = fcport->cfg.topology;
- attr->topology = fcport->topology;
-
- /*
- * beacon attributes
- */
- attr->beacon = fcport->beacon;
- attr->link_e2e_beacon = fcport->link_e2e_beacon;
- attr->plog_enabled = bfa_plog_get_setting(fcport->bfa->plog);
-
- attr->pport_cfg.path_tov = bfa_fcpim_path_tov_get(bfa);
- attr->pport_cfg.q_depth = bfa_fcpim_qdepth_get(bfa);
-
- /* PBC Disabled State */
- if (cfgrsp->pbc_cfg.port_enabled == BFI_PBC_PORT_DISABLED)
- attr->port_state = BFA_PPORT_ST_PREBOOT_DISABLED;
- else {
- attr->port_state = bfa_sm_to_state(
- hal_pport_sm_table, fcport->sm);
- if (bfa_ioc_is_disabled(&fcport->bfa->ioc))
- attr->port_state = BFA_PPORT_ST_IOCDIS;
- else if (bfa_ioc_fw_mismatch(&fcport->bfa->ioc))
- attr->port_state = BFA_PPORT_ST_FWMISMATCH;
- }
-}
-
-#define BFA_FCPORT_STATS_TOV 1000
-
-/**
- * Fetch port attributes (FCQoS or FCoE).
- */
-bfa_status_t
-bfa_fcport_get_stats(struct bfa_s *bfa, union bfa_fcport_stats_u *stats,
- bfa_cb_pport_t cbfn, void *cbarg)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
- if (fcport->stats_busy) {
- bfa_trc(bfa, fcport->stats_busy);
- return BFA_STATUS_DEVBUSY;
- }
-
- fcport->stats_busy = BFA_TRUE;
- fcport->stats_ret = stats;
- fcport->stats_cbfn = cbfn;
- fcport->stats_cbarg = cbarg;
-
- bfa_fcport_send_stats_get(fcport);
-
- bfa_timer_start(bfa, &fcport->timer, bfa_fcport_stats_get_timeout,
- fcport, BFA_FCPORT_STATS_TOV);
- return BFA_STATUS_OK;
-}
-
-/**
- * Reset port statistics (FCQoS or FCoE).
- */
-bfa_status_t
-bfa_fcport_clear_stats(struct bfa_s *bfa, bfa_cb_pport_t cbfn, void *cbarg)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
- if (fcport->stats_busy) {
- bfa_trc(bfa, fcport->stats_busy);
- return BFA_STATUS_DEVBUSY;
- }
-
- fcport->stats_busy = BFA_TRUE;
- fcport->stats_cbfn = cbfn;
- fcport->stats_cbarg = cbarg;
-
- bfa_fcport_send_stats_clear(fcport);
-
- bfa_timer_start(bfa, &fcport->timer, bfa_fcport_stats_clr_timeout,
- fcport, BFA_FCPORT_STATS_TOV);
- return BFA_STATUS_OK;
-}
-
-/**
- * Fetch FCQoS port statistics
- */
-bfa_status_t
-bfa_fcport_get_qos_stats(struct bfa_s *bfa, union bfa_fcport_stats_u *stats,
- bfa_cb_pport_t cbfn, void *cbarg)
-{
- /* Meaningful only for FC mode */
- bfa_assert(bfa_ioc_get_fcmode(&bfa->ioc));
-
- return bfa_fcport_get_stats(bfa, stats, cbfn, cbarg);
-}
-
-/**
- * Reset FCoE port statistics
- */
-bfa_status_t
-bfa_fcport_clear_qos_stats(struct bfa_s *bfa, bfa_cb_pport_t cbfn, void *cbarg)
-{
- /* Meaningful only for FC mode */
- bfa_assert(bfa_ioc_get_fcmode(&bfa->ioc));
-
- return bfa_fcport_clear_stats(bfa, cbfn, cbarg);
-}
-
-/**
- * Fetch FCQoS port statistics
- */
-bfa_status_t
-bfa_fcport_get_fcoe_stats(struct bfa_s *bfa, union bfa_fcport_stats_u *stats,
- bfa_cb_pport_t cbfn, void *cbarg)
-{
- /* Meaningful only for FCoE mode */
- bfa_assert(!bfa_ioc_get_fcmode(&bfa->ioc));
-
- return bfa_fcport_get_stats(bfa, stats, cbfn, cbarg);
-}
-
-/**
- * Reset FCoE port statistics
- */
-bfa_status_t
-bfa_fcport_clear_fcoe_stats(struct bfa_s *bfa, bfa_cb_pport_t cbfn, void *cbarg)
-{
- /* Meaningful only for FCoE mode */
- bfa_assert(!bfa_ioc_get_fcmode(&bfa->ioc));
-
- return bfa_fcport_clear_stats(bfa, cbfn, cbarg);
-}
-
-bfa_status_t
-bfa_fcport_trunk_enable(struct bfa_s *bfa, u8 bitmap)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
- bfa_trc(bfa, bitmap);
- bfa_trc(bfa, fcport->cfg.trunked);
- bfa_trc(bfa, fcport->cfg.trunk_ports);
-
- if (!bitmap || (bitmap & (bitmap - 1)))
- return BFA_STATUS_EINVAL;
-
- fcport->cfg.trunked = BFA_TRUE;
- fcport->cfg.trunk_ports = bitmap;
-
- return BFA_STATUS_OK;
-}
-
-void
-bfa_fcport_qos_get_attr(struct bfa_s *bfa, struct bfa_qos_attr_s *qos_attr)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
- qos_attr->state = bfa_os_ntohl(fcport->qos_attr.state);
- qos_attr->total_bb_cr = bfa_os_ntohl(fcport->qos_attr.total_bb_cr);
-}
-
-void
-bfa_fcport_qos_get_vc_attr(struct bfa_s *bfa,
- struct bfa_qos_vc_attr_s *qos_vc_attr)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
- struct bfa_qos_vc_attr_s *bfa_vc_attr = &fcport->qos_vc_attr;
- u32 i = 0;
-
- qos_vc_attr->total_vc_count = bfa_os_ntohs(bfa_vc_attr->total_vc_count);
- qos_vc_attr->shared_credit = bfa_os_ntohs(bfa_vc_attr->shared_credit);
- qos_vc_attr->elp_opmode_flags =
- bfa_os_ntohl(bfa_vc_attr->elp_opmode_flags);
-
- /*
- * Individual VC info
- */
- while (i < qos_vc_attr->total_vc_count) {
- qos_vc_attr->vc_info[i].vc_credit =
- bfa_vc_attr->vc_info[i].vc_credit;
- qos_vc_attr->vc_info[i].borrow_credit =
- bfa_vc_attr->vc_info[i].borrow_credit;
- qos_vc_attr->vc_info[i].priority =
- bfa_vc_attr->vc_info[i].priority;
- ++i;
- }
-}
-
-/**
- * Fetch port attributes.
- */
-bfa_status_t
-bfa_fcport_trunk_disable(struct bfa_s *bfa)
-{
- return BFA_STATUS_OK;
-}
-
-bfa_boolean_t
-bfa_fcport_trunk_query(struct bfa_s *bfa, u32 *bitmap)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
- *bitmap = fcport->cfg.trunk_ports;
- return fcport->cfg.trunked;
-}
-
-bfa_boolean_t
-bfa_fcport_is_disabled(struct bfa_s *bfa)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
- return bfa_sm_to_state(hal_pport_sm_table, fcport->sm) ==
- BFA_PPORT_ST_DISABLED;
-
-}
-
-bfa_boolean_t
-bfa_fcport_is_ratelim(struct bfa_s *bfa)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
- return fcport->cfg.ratelimit ? BFA_TRUE : BFA_FALSE;
-
-}
-
-void
-bfa_fcport_cfg_qos(struct bfa_s *bfa, bfa_boolean_t on_off)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
- enum bfa_ioc_type_e ioc_type = bfa_get_type(bfa);
-
- bfa_trc(bfa, on_off);
- bfa_trc(bfa, fcport->cfg.qos_enabled);
-
- bfa_trc(bfa, ioc_type);
-
- if (ioc_type == BFA_IOC_TYPE_FC) {
- fcport->cfg.qos_enabled = on_off;
- /**
- * Notify fcpim of the change in QoS state
- */
- bfa_fcpim_update_ioredirect(bfa);
- }
-}
-
-void
-bfa_fcport_cfg_ratelim(struct bfa_s *bfa, bfa_boolean_t on_off)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
- bfa_trc(bfa, on_off);
- bfa_trc(bfa, fcport->cfg.ratelimit);
-
- fcport->cfg.ratelimit = on_off;
- if (fcport->cfg.trl_def_speed == BFA_PPORT_SPEED_UNKNOWN)
- fcport->cfg.trl_def_speed = BFA_PPORT_SPEED_1GBPS;
-}
-
-/**
- * Configure default minimum ratelim speed
- */
-bfa_status_t
-bfa_fcport_cfg_ratelim_speed(struct bfa_s *bfa, enum bfa_pport_speed speed)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
- bfa_trc(bfa, speed);
-
- /*
- * Auto and speeds greater than the supported speed, are invalid
- */
- if ((speed == BFA_PPORT_SPEED_AUTO) || (speed > fcport->speed_sup)) {
- bfa_trc(bfa, fcport->speed_sup);
- return BFA_STATUS_UNSUPP_SPEED;
- }
-
- fcport->cfg.trl_def_speed = speed;
-
- return BFA_STATUS_OK;
-}
-
-/**
- * Get default minimum ratelim speed
- */
-enum bfa_pport_speed
-bfa_fcport_get_ratelim_speed(struct bfa_s *bfa)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
- bfa_trc(bfa, fcport->cfg.trl_def_speed);
- return fcport->cfg.trl_def_speed;
-
-}
-
-void
-bfa_fcport_busy(struct bfa_s *bfa, bfa_boolean_t status)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
- bfa_trc(bfa, status);
- bfa_trc(bfa, fcport->diag_busy);
-
- fcport->diag_busy = status;
-}
-
-void
-bfa_fcport_beacon(struct bfa_s *bfa, bfa_boolean_t beacon,
- bfa_boolean_t link_e2e_beacon)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
- bfa_trc(bfa, beacon);
- bfa_trc(bfa, link_e2e_beacon);
- bfa_trc(bfa, fcport->beacon);
- bfa_trc(bfa, fcport->link_e2e_beacon);
-
- fcport->beacon = beacon;
- fcport->link_e2e_beacon = link_e2e_beacon;
-}
-
-bfa_boolean_t
-bfa_fcport_is_linkup(struct bfa_s *bfa)
-{
- return bfa_sm_cmp_state(BFA_FCPORT_MOD(bfa), bfa_fcport_sm_linkup);
-}
-
-bfa_boolean_t
-bfa_fcport_is_qos_enabled(struct bfa_s *bfa)
-{
- struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
- return fcport->cfg.qos_enabled;
-}
diff --git a/drivers/scsi/bfa/bfa_fcs.c b/drivers/scsi/bfa/bfa_fcs.c
index d1a99209bf5f..9cebbe30a678 100644
--- a/drivers/scsi/bfa/bfa_fcs.c
+++ b/drivers/scsi/bfa/bfa_fcs.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
* All rights reserved
* www.brocade.com
*
@@ -19,35 +19,28 @@
* bfa_fcs.c BFA FCS main
*/
-#include <fcs/bfa_fcs.h>
-#include "fcs_port.h"
-#include "fcs_uf.h"
-#include "fcs_vport.h"
-#include "fcs_rport.h"
-#include "fcs_fabric.h"
-#include "fcs_fcpim.h"
-#include "fcs_fcptm.h"
-#include "fcbuild.h"
-#include "fcs.h"
+#include "bfa_fcs.h"
+#include "bfa_fcbuild.h"
#include "bfad_drv.h"
-#include <fcb/bfa_fcb.h>
+
+BFA_TRC_FILE(FCS, FCS);
/**
* FCS sub-modules
*/
struct bfa_fcs_mod_s {
void (*attach) (struct bfa_fcs_s *fcs);
- void (*modinit) (struct bfa_fcs_s *fcs);
- void (*modexit) (struct bfa_fcs_s *fcs);
+ void (*modinit) (struct bfa_fcs_s *fcs);
+ void (*modexit) (struct bfa_fcs_s *fcs);
};
#define BFA_FCS_MODULE(_mod) { _mod ## _modinit, _mod ## _modexit }
static struct bfa_fcs_mod_s fcs_modules[] = {
- { bfa_fcs_pport_attach, NULL, NULL },
+ { bfa_fcs_port_attach, NULL, NULL },
{ bfa_fcs_uf_attach, NULL, NULL },
{ bfa_fcs_fabric_attach, bfa_fcs_fabric_modinit,
- bfa_fcs_fabric_modexit },
+ bfa_fcs_fabric_modexit },
};
/**
@@ -57,8 +50,8 @@ static struct bfa_fcs_mod_s fcs_modules[] = {
static void
bfa_fcs_exit_comp(void *fcs_cbarg)
{
- struct bfa_fcs_s *fcs = fcs_cbarg;
- struct bfad_s *bfad = fcs->bfad;
+ struct bfa_fcs_s *fcs = fcs_cbarg;
+ struct bfad_s *bfad = fcs->bfad;
complete(&bfad->comp);
}
@@ -74,9 +67,9 @@ bfa_fcs_exit_comp(void *fcs_cbarg)
*/
void
bfa_fcs_attach(struct bfa_fcs_s *fcs, struct bfa_s *bfa, struct bfad_s *bfad,
- bfa_boolean_t min_cfg)
+ bfa_boolean_t min_cfg)
{
- int i;
+ int i;
struct bfa_fcs_mod_s *mod;
fcs->bfa = bfa;
@@ -86,7 +79,7 @@ bfa_fcs_attach(struct bfa_fcs_s *fcs, struct bfa_s *bfa, struct bfad_s *bfad,
bfa_attach_fcs(bfa);
fcbuild_init();
- for (i = 0; i < ARRAY_SIZE(fcs_modules); i++) {
+ for (i = 0; i < sizeof(fcs_modules) / sizeof(fcs_modules[0]); i++) {
mod = &fcs_modules[i];
if (mod->attach)
mod->attach(fcs);
@@ -99,11 +92,11 @@ bfa_fcs_attach(struct bfa_fcs_s *fcs, struct bfa_s *bfa, struct bfad_s *bfad,
void
bfa_fcs_init(struct bfa_fcs_s *fcs)
{
- int i, npbc_vports;
+ int i, npbc_vports;
struct bfa_fcs_mod_s *mod;
struct bfi_pbc_vport_s pbc_vports[BFI_PBC_MAX_VPORTS];
- for (i = 0; i < ARRAY_SIZE(fcs_modules); i++) {
+ for (i = 0; i < sizeof(fcs_modules) / sizeof(fcs_modules[0]); i++) {
mod = &fcs_modules[i];
if (mod->modinit)
mod->modinit(fcs);
@@ -111,7 +104,7 @@ bfa_fcs_init(struct bfa_fcs_s *fcs)
/* Initialize pbc vports */
if (!fcs->min_cfg) {
npbc_vports =
- bfa_iocfc_get_pbc_vports(fcs->bfa, pbc_vports);
+ bfa_iocfc_get_pbc_vports(fcs->bfa, pbc_vports);
for (i = 0; i < npbc_vports; i++)
bfa_fcb_pbc_vport_create(fcs->bfa->bfad, pbc_vports[i]);
}
@@ -127,12 +120,13 @@ bfa_fcs_start(struct bfa_fcs_s *fcs)
}
/**
- * FCS driver details initialization.
+ * brief
+ * FCS driver details initialization.
*
- * param[in] fcs FCS instance
- * param[in] driver_info Driver Details
+ * param[in] fcs FCS instance
+ * param[in] driver_info Driver Details
*
- * return None
+ * return None
*/
void
bfa_fcs_driver_info_init(struct bfa_fcs_s *fcs,
@@ -145,13 +139,13 @@ bfa_fcs_driver_info_init(struct bfa_fcs_s *fcs,
}
/**
- * @brief
- * FCS FDMI Driver Parameter Initialization
+ * brief
+ * FCS FDMI Driver Parameter Initialization
*
- * @param[in] fcs FCS instance
- * @param[in] fdmi_enable TRUE/FALSE
+ * param[in] fcs FCS instance
+ * param[in] fdmi_enable TRUE/FALSE
*
- * @return None
+ * return None
*/
void
bfa_fcs_set_fdmi_param(struct bfa_fcs_s *fcs, bfa_boolean_t fdmi_enable)
@@ -160,22 +154,24 @@ bfa_fcs_set_fdmi_param(struct bfa_fcs_s *fcs, bfa_boolean_t fdmi_enable)
fcs->fdmi_enabled = fdmi_enable;
}
-
/**
- * FCS instance cleanup and exit.
+ * brief
+ * FCS instance cleanup and exit.
*
- * param[in] fcs FCS instance
- * return None
+ * param[in] fcs FCS instance
+ * return None
*/
void
bfa_fcs_exit(struct bfa_fcs_s *fcs)
{
struct bfa_fcs_mod_s *mod;
- int i;
+ int nmods, i;
bfa_wc_init(&fcs->wc, bfa_fcs_exit_comp, fcs);
- for (i = 0; i < ARRAY_SIZE(fcs_modules); i++) {
+ nmods = sizeof(fcs_modules) / sizeof(fcs_modules[0]);
+
+ for (i = 0; i < nmods; i++) {
mod = &fcs_modules[i];
if (mod->modexit) {
@@ -194,24 +190,1547 @@ bfa_fcs_trc_init(struct bfa_fcs_s *fcs, struct bfa_trc_mod_s *trcmod)
fcs->trcmod = trcmod;
}
+void
+bfa_fcs_modexit_comp(struct bfa_fcs_s *fcs)
+{
+ bfa_wc_down(&fcs->wc);
+}
+
+/**
+ * Fabric module implementation.
+ */
+
+#define BFA_FCS_FABRIC_RETRY_DELAY (2000) /* Milliseconds */
+#define BFA_FCS_FABRIC_CLEANUP_DELAY (10000) /* Milliseconds */
+
+#define bfa_fcs_fabric_set_opertype(__fabric) do { \
+ if (bfa_fcport_get_topology((__fabric)->fcs->bfa) \
+ == BFA_PORT_TOPOLOGY_P2P) \
+ (__fabric)->oper_type = BFA_PORT_TYPE_NPORT; \
+ else \
+ (__fabric)->oper_type = BFA_PORT_TYPE_NLPORT; \
+} while (0)
+
+/*
+ * forward declarations
+ */
+static void bfa_fcs_fabric_init(struct bfa_fcs_fabric_s *fabric);
+static void bfa_fcs_fabric_login(struct bfa_fcs_fabric_s *fabric);
+static void bfa_fcs_fabric_notify_online(struct bfa_fcs_fabric_s *fabric);
+static void bfa_fcs_fabric_notify_offline(struct bfa_fcs_fabric_s *fabric);
+static void bfa_fcs_fabric_delay(void *cbarg);
+static void bfa_fcs_fabric_delete(struct bfa_fcs_fabric_s *fabric);
+static void bfa_fcs_fabric_delete_comp(void *cbarg);
+static void bfa_fcs_fabric_process_uf(struct bfa_fcs_fabric_s *fabric,
+ struct fchs_s *fchs, u16 len);
+static void bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s *fabric,
+ struct fchs_s *fchs, u16 len);
+static void bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric);
+static void bfa_fcs_fabric_flogiacc_comp(void *fcsarg,
+ struct bfa_fcxp_s *fcxp, void *cbarg,
+ bfa_status_t status,
+ u32 rsp_len,
+ u32 resid_len,
+ struct fchs_s *rspfchs);
+/**
+ * fcs_fabric_sm fabric state machine functions
+ */
+
+/**
+ * Fabric state machine events
+ */
+enum bfa_fcs_fabric_event {
+ BFA_FCS_FABRIC_SM_CREATE = 1, /* create from driver */
+ BFA_FCS_FABRIC_SM_DELETE = 2, /* delete from driver */
+ BFA_FCS_FABRIC_SM_LINK_DOWN = 3, /* link down from port */
+ BFA_FCS_FABRIC_SM_LINK_UP = 4, /* link up from port */
+ BFA_FCS_FABRIC_SM_CONT_OP = 5, /* flogi/auth continue op */
+ BFA_FCS_FABRIC_SM_RETRY_OP = 6, /* flogi/auth retry op */
+ BFA_FCS_FABRIC_SM_NO_FABRIC = 7, /* from flogi/auth */
+ BFA_FCS_FABRIC_SM_PERF_EVFP = 8, /* from flogi/auth */
+ BFA_FCS_FABRIC_SM_ISOLATE = 9, /* from EVFP processing */
+ BFA_FCS_FABRIC_SM_NO_TAGGING = 10, /* no VFT tagging from EVFP */
+ BFA_FCS_FABRIC_SM_DELAYED = 11, /* timeout delay event */
+ BFA_FCS_FABRIC_SM_AUTH_FAILED = 12, /* auth failed */
+ BFA_FCS_FABRIC_SM_AUTH_SUCCESS = 13, /* auth successful */
+ BFA_FCS_FABRIC_SM_DELCOMP = 14, /* all vports deleted event */
+ BFA_FCS_FABRIC_SM_LOOPBACK = 15, /* Received our own FLOGI */
+ BFA_FCS_FABRIC_SM_START = 16, /* from driver */
+};
+
+static void bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s *fabric,
+ enum bfa_fcs_fabric_event event);
+static void bfa_fcs_fabric_sm_created(struct bfa_fcs_fabric_s *fabric,
+ enum bfa_fcs_fabric_event event);
+static void bfa_fcs_fabric_sm_linkdown(struct bfa_fcs_fabric_s *fabric,
+ enum bfa_fcs_fabric_event event);
+static void bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric,
+ enum bfa_fcs_fabric_event event);
+static void bfa_fcs_fabric_sm_flogi_retry(struct bfa_fcs_fabric_s *fabric,
+ enum bfa_fcs_fabric_event event);
+static void bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s *fabric,
+ enum bfa_fcs_fabric_event event);
+static void bfa_fcs_fabric_sm_auth_failed(struct bfa_fcs_fabric_s *fabric,
+ enum bfa_fcs_fabric_event event);
+static void bfa_fcs_fabric_sm_loopback(struct bfa_fcs_fabric_s *fabric,
+ enum bfa_fcs_fabric_event event);
+static void bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric,
+ enum bfa_fcs_fabric_event event);
+static void bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric,
+ enum bfa_fcs_fabric_event event);
+static void bfa_fcs_fabric_sm_evfp(struct bfa_fcs_fabric_s *fabric,
+ enum bfa_fcs_fabric_event event);
+static void bfa_fcs_fabric_sm_evfp_done(struct bfa_fcs_fabric_s *fabric,
+ enum bfa_fcs_fabric_event event);
+static void bfa_fcs_fabric_sm_isolated(struct bfa_fcs_fabric_s *fabric,
+ enum bfa_fcs_fabric_event event);
+static void bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s *fabric,
+ enum bfa_fcs_fabric_event event);
+/**
+ * Beginning state before fabric creation.
+ */
+static void
+bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s *fabric,
+ enum bfa_fcs_fabric_event event)
+{
+ bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+ bfa_trc(fabric->fcs, event);
+
+ switch (event) {
+ case BFA_FCS_FABRIC_SM_CREATE:
+ bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_created);
+ bfa_fcs_fabric_init(fabric);
+ bfa_fcs_lport_init(&fabric->bport, &fabric->bport.port_cfg);
+ break;
+
+ case BFA_FCS_FABRIC_SM_LINK_UP:
+ case BFA_FCS_FABRIC_SM_LINK_DOWN:
+ break;
+
+ default:
+ bfa_sm_fault(fabric->fcs, event);
+ }
+}
+
+/**
+ * Beginning state before fabric creation.
+ */
+static void
+bfa_fcs_fabric_sm_created(struct bfa_fcs_fabric_s *fabric,
+ enum bfa_fcs_fabric_event event)
+{
+ bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+ bfa_trc(fabric->fcs, event);
+
+ switch (event) {
+ case BFA_FCS_FABRIC_SM_START:
+ if (bfa_fcport_is_linkup(fabric->fcs->bfa)) {
+ bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);
+ bfa_fcs_fabric_login(fabric);
+ } else
+ bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
+ break;
+
+ case BFA_FCS_FABRIC_SM_LINK_UP:
+ case BFA_FCS_FABRIC_SM_LINK_DOWN:
+ break;
+
+ case BFA_FCS_FABRIC_SM_DELETE:
+ bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit);
+ bfa_fcs_modexit_comp(fabric->fcs);
+ break;
+
+ default:
+ bfa_sm_fault(fabric->fcs, event);
+ }
+}
+
+/**
+ * Link is down, awaiting LINK UP event from port. This is also the
+ * first state at fabric creation.
+ */
+static void
+bfa_fcs_fabric_sm_linkdown(struct bfa_fcs_fabric_s *fabric,
+ enum bfa_fcs_fabric_event event)
+{
+ bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+ bfa_trc(fabric->fcs, event);
+
+ switch (event) {
+ case BFA_FCS_FABRIC_SM_LINK_UP:
+ bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);
+ bfa_fcs_fabric_login(fabric);
+ break;
+
+ case BFA_FCS_FABRIC_SM_RETRY_OP:
+ break;
+
+ case BFA_FCS_FABRIC_SM_DELETE:
+ bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
+ bfa_fcs_fabric_delete(fabric);
+ break;
+
+ default:
+ bfa_sm_fault(fabric->fcs, event);
+ }
+}
+
+/**
+ * FLOGI is in progress, awaiting FLOGI reply.
+ */
+static void
+bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric,
+ enum bfa_fcs_fabric_event event)
+{
+ bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+ bfa_trc(fabric->fcs, event);
+
+ switch (event) {
+ case BFA_FCS_FABRIC_SM_CONT_OP:
+
+ bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa,
+ fabric->bb_credit);
+ fabric->fab_type = BFA_FCS_FABRIC_SWITCHED;
+
+ if (fabric->auth_reqd && fabric->is_auth) {
+ bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth);
+ bfa_trc(fabric->fcs, event);
+ } else {
+ bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_online);
+ bfa_fcs_fabric_notify_online(fabric);
+ }
+ break;
+
+ case BFA_FCS_FABRIC_SM_RETRY_OP:
+ bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi_retry);
+ bfa_timer_start(fabric->fcs->bfa, &fabric->delay_timer,
+ bfa_fcs_fabric_delay, fabric,
+ BFA_FCS_FABRIC_RETRY_DELAY);
+ break;
+
+ case BFA_FCS_FABRIC_SM_LOOPBACK:
+ bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_loopback);
+ bfa_lps_discard(fabric->lps);
+ bfa_fcs_fabric_set_opertype(fabric);
+ break;
+
+ case BFA_FCS_FABRIC_SM_NO_FABRIC:
+ fabric->fab_type = BFA_FCS_FABRIC_N2N;
+ bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa,
+ fabric->bb_credit);
+ bfa_fcs_fabric_notify_online(fabric);
+ bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_nofabric);
+ break;
+
+ case BFA_FCS_FABRIC_SM_LINK_DOWN:
+ bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
+ bfa_lps_discard(fabric->lps);
+ break;
+
+ case BFA_FCS_FABRIC_SM_DELETE:
+ bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
+ bfa_lps_discard(fabric->lps);
+ bfa_fcs_fabric_delete(fabric);
+ break;
+
+ default:
+ bfa_sm_fault(fabric->fcs, event);
+ }
+}
+
+
+static void
+bfa_fcs_fabric_sm_flogi_retry(struct bfa_fcs_fabric_s *fabric,
+ enum bfa_fcs_fabric_event event)
+{
+ bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+ bfa_trc(fabric->fcs, event);
+
+ switch (event) {
+ case BFA_FCS_FABRIC_SM_DELAYED:
+ bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);
+ bfa_fcs_fabric_login(fabric);
+ break;
+
+ case BFA_FCS_FABRIC_SM_LINK_DOWN:
+ bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
+ bfa_timer_stop(&fabric->delay_timer);
+ break;
+
+ case BFA_FCS_FABRIC_SM_DELETE:
+ bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
+ bfa_timer_stop(&fabric->delay_timer);
+ bfa_fcs_fabric_delete(fabric);
+ break;
+
+ default:
+ bfa_sm_fault(fabric->fcs, event);
+ }
+}
+
+/**
+ * Authentication is in progress, awaiting authentication results.
+ */
+static void
+bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s *fabric,
+ enum bfa_fcs_fabric_event event)
+{
+ bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+ bfa_trc(fabric->fcs, event);
+
+ switch (event) {
+ case BFA_FCS_FABRIC_SM_AUTH_FAILED:
+ bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth_failed);
+ bfa_lps_discard(fabric->lps);
+ break;
+
+ case BFA_FCS_FABRIC_SM_AUTH_SUCCESS:
+ bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_online);
+ bfa_fcs_fabric_notify_online(fabric);
+ break;
+
+ case BFA_FCS_FABRIC_SM_PERF_EVFP:
+ bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_evfp);
+ break;
+
+ case BFA_FCS_FABRIC_SM_LINK_DOWN:
+ bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
+ bfa_lps_discard(fabric->lps);
+ break;
+
+ case BFA_FCS_FABRIC_SM_DELETE:
+ bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
+ bfa_fcs_fabric_delete(fabric);
+ break;
+
+ default:
+ bfa_sm_fault(fabric->fcs, event);
+ }
+}
+
+/**
+ * Authentication failed
+ */
+static void
+bfa_fcs_fabric_sm_auth_failed(struct bfa_fcs_fabric_s *fabric,
+ enum bfa_fcs_fabric_event event)
+{
+ bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+ bfa_trc(fabric->fcs, event);
+
+ switch (event) {
+ case BFA_FCS_FABRIC_SM_LINK_DOWN:
+ bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
+ bfa_fcs_fabric_notify_offline(fabric);
+ break;
+
+ case BFA_FCS_FABRIC_SM_DELETE:
+ bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
+ bfa_fcs_fabric_delete(fabric);
+ break;
+
+ default:
+ bfa_sm_fault(fabric->fcs, event);
+ }
+}
+
+/**
+ * Port is in loopback mode.
+ */
+static void
+bfa_fcs_fabric_sm_loopback(struct bfa_fcs_fabric_s *fabric,
+ enum bfa_fcs_fabric_event event)
+{
+ bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+ bfa_trc(fabric->fcs, event);
+
+ switch (event) {
+ case BFA_FCS_FABRIC_SM_LINK_DOWN:
+ bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
+ bfa_fcs_fabric_notify_offline(fabric);
+ break;
+
+ case BFA_FCS_FABRIC_SM_DELETE:
+ bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
+ bfa_fcs_fabric_delete(fabric);
+ break;
+
+ default:
+ bfa_sm_fault(fabric->fcs, event);
+ }
+}
+
+/**
+ * There is no attached fabric - private loop or NPort-to-NPort topology.
+ */
+static void
+bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric,
+ enum bfa_fcs_fabric_event event)
+{
+ bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+ bfa_trc(fabric->fcs, event);
+
+ switch (event) {
+ case BFA_FCS_FABRIC_SM_LINK_DOWN:
+ bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
+ bfa_lps_discard(fabric->lps);
+ bfa_fcs_fabric_notify_offline(fabric);
+ break;
+
+ case BFA_FCS_FABRIC_SM_DELETE:
+ bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
+ bfa_fcs_fabric_delete(fabric);
+ break;
+
+ case BFA_FCS_FABRIC_SM_NO_FABRIC:
+ bfa_trc(fabric->fcs, fabric->bb_credit);
+ bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa,
+ fabric->bb_credit);
+ break;
+
+ default:
+ bfa_sm_fault(fabric->fcs, event);
+ }
+}
+
+/**
+ * Fabric is online - normal operating state.
+ */
+static void
+bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric,
+ enum bfa_fcs_fabric_event event)
+{
+ bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+ bfa_trc(fabric->fcs, event);
+
+ switch (event) {
+ case BFA_FCS_FABRIC_SM_LINK_DOWN:
+ bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
+ bfa_lps_discard(fabric->lps);
+ bfa_fcs_fabric_notify_offline(fabric);
+ break;
+
+ case BFA_FCS_FABRIC_SM_DELETE:
+ bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
+ bfa_fcs_fabric_delete(fabric);
+ break;
+
+ case BFA_FCS_FABRIC_SM_AUTH_FAILED:
+ bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth_failed);
+ bfa_lps_discard(fabric->lps);
+ break;
+
+ case BFA_FCS_FABRIC_SM_AUTH_SUCCESS:
+ break;
+
+ default:
+ bfa_sm_fault(fabric->fcs, event);
+ }
+}
+
+/**
+ * Exchanging virtual fabric parameters.
+ */
+static void
+bfa_fcs_fabric_sm_evfp(struct bfa_fcs_fabric_s *fabric,
+ enum bfa_fcs_fabric_event event)
+{
+ bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+ bfa_trc(fabric->fcs, event);
+
+ switch (event) {
+ case BFA_FCS_FABRIC_SM_CONT_OP:
+ bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_evfp_done);
+ break;
+ case BFA_FCS_FABRIC_SM_ISOLATE:
+ bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_isolated);
+ break;
+
+ default:
+ bfa_sm_fault(fabric->fcs, event);
+ }
+}
+
+/**
+ * EVFP exchange complete and VFT tagging is enabled.
+ */
+static void
+bfa_fcs_fabric_sm_evfp_done(struct bfa_fcs_fabric_s *fabric,
+ enum bfa_fcs_fabric_event event)
+{
+ bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+ bfa_trc(fabric->fcs, event);
+}
+
+/**
+ * Port is isolated after EVFP exchange due to VF_ID mismatch (N and F).
+ */
+static void
+bfa_fcs_fabric_sm_isolated(struct bfa_fcs_fabric_s *fabric,
+ enum bfa_fcs_fabric_event event)
+{
+ struct bfad_s *bfad = (struct bfad_s *)fabric->fcs->bfad;
+ char pwwn_ptr[BFA_STRING_32];
+
+ bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+ bfa_trc(fabric->fcs, event);
+ wwn2str(pwwn_ptr, fabric->bport.port_cfg.pwwn);
+
+ BFA_LOG(KERN_INFO, bfad, log_level,
+ "Port is isolated due to VF_ID mismatch. "
+ "PWWN: %s Port VF_ID: %04x switch port VF_ID: %04x.",
+ pwwn_ptr, fabric->fcs->port_vfid,
+ fabric->event_arg.swp_vfid);
+}
+
+/**
+ * Fabric is being deleted, awaiting vport delete completions.
+ */
+static void
+bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s *fabric,
+ enum bfa_fcs_fabric_event event)
+{
+ bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+ bfa_trc(fabric->fcs, event);
+
+ switch (event) {
+ case BFA_FCS_FABRIC_SM_DELCOMP:
+ bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit);
+ bfa_fcs_modexit_comp(fabric->fcs);
+ break;
+
+ case BFA_FCS_FABRIC_SM_LINK_UP:
+ break;
+
+ case BFA_FCS_FABRIC_SM_LINK_DOWN:
+ bfa_fcs_fabric_notify_offline(fabric);
+ break;
+
+ default:
+ bfa_sm_fault(fabric->fcs, event);
+ }
+}
+
+
+
+/**
+ * fcs_fabric_private fabric private functions
+ */
+
+static void
+bfa_fcs_fabric_init(struct bfa_fcs_fabric_s *fabric)
+{
+ struct bfa_lport_cfg_s *port_cfg = &fabric->bport.port_cfg;
+
+ port_cfg->roles = BFA_LPORT_ROLE_FCP_IM;
+ port_cfg->nwwn = bfa_ioc_get_nwwn(&fabric->fcs->bfa->ioc);
+ port_cfg->pwwn = bfa_ioc_get_pwwn(&fabric->fcs->bfa->ioc);
+}
+
+/**
+ * Port Symbolic Name Creation for base port.
+ */
void
-bfa_fcs_log_init(struct bfa_fcs_s *fcs, struct bfa_log_mod_s *logmod)
+bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s *fabric)
+{
+ struct bfa_lport_cfg_s *port_cfg = &fabric->bport.port_cfg;
+ char model[BFA_ADAPTER_MODEL_NAME_LEN] = {0};
+ struct bfa_fcs_driver_info_s *driver_info = &fabric->fcs->driver_info;
+
+ bfa_ioc_get_adapter_model(&fabric->fcs->bfa->ioc, model);
+
+ /* Model name/number */
+ strncpy((char *)&port_cfg->sym_name, model,
+ BFA_FCS_PORT_SYMBNAME_MODEL_SZ);
+ strncat((char *)&port_cfg->sym_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
+ sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
+
+ /* Driver Version */
+ strncat((char *)&port_cfg->sym_name, (char *)driver_info->version,
+ BFA_FCS_PORT_SYMBNAME_VERSION_SZ);
+ strncat((char *)&port_cfg->sym_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
+ sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
+
+ /* Host machine name */
+ strncat((char *)&port_cfg->sym_name,
+ (char *)driver_info->host_machine_name,
+ BFA_FCS_PORT_SYMBNAME_MACHINENAME_SZ);
+ strncat((char *)&port_cfg->sym_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
+ sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
+
+ /*
+ * Host OS Info :
+ * If OS Patch Info is not there, do not truncate any bytes from the
+ * OS name string and instead copy the entire OS info string (64 bytes).
+ */
+ if (driver_info->host_os_patch[0] == '\0') {
+ strncat((char *)&port_cfg->sym_name,
+ (char *)driver_info->host_os_name,
+ BFA_FCS_OS_STR_LEN);
+ strncat((char *)&port_cfg->sym_name,
+ BFA_FCS_PORT_SYMBNAME_SEPARATOR,
+ sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
+ } else {
+ strncat((char *)&port_cfg->sym_name,
+ (char *)driver_info->host_os_name,
+ BFA_FCS_PORT_SYMBNAME_OSINFO_SZ);
+ strncat((char *)&port_cfg->sym_name,
+ BFA_FCS_PORT_SYMBNAME_SEPARATOR,
+ sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
+
+ /* Append host OS Patch Info */
+ strncat((char *)&port_cfg->sym_name,
+ (char *)driver_info->host_os_patch,
+ BFA_FCS_PORT_SYMBNAME_OSPATCH_SZ);
+ }
+
+ /* null terminate */
+ port_cfg->sym_name.symname[BFA_SYMNAME_MAXLEN - 1] = 0;
+}
+
+/**
+ * bfa lps login completion callback
+ */
+void
+bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status)
+{
+ struct bfa_fcs_fabric_s *fabric = uarg;
+
+ bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+ bfa_trc(fabric->fcs, status);
+
+ switch (status) {
+ case BFA_STATUS_OK:
+ fabric->stats.flogi_accepts++;
+ break;
+
+ case BFA_STATUS_INVALID_MAC:
+ /* Only for CNA */
+ fabric->stats.flogi_acc_err++;
+ bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
+
+ return;
+
+ case BFA_STATUS_EPROTOCOL:
+ switch (bfa_lps_get_extstatus(fabric->lps)) {
+ case BFA_EPROTO_BAD_ACCEPT:
+ fabric->stats.flogi_acc_err++;
+ break;
+
+ case BFA_EPROTO_UNKNOWN_RSP:
+ fabric->stats.flogi_unknown_rsp++;
+ break;
+
+ default:
+ break;
+ }
+ bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
+
+ return;
+
+ case BFA_STATUS_FABRIC_RJT:
+ fabric->stats.flogi_rejects++;
+ bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
+ return;
+
+ default:
+ fabric->stats.flogi_rsp_err++;
+ bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
+ return;
+ }
+
+ fabric->bb_credit = bfa_lps_get_peer_bbcredit(fabric->lps);
+ bfa_trc(fabric->fcs, fabric->bb_credit);
+
+ if (!bfa_lps_is_brcd_fabric(fabric->lps))
+ fabric->fabric_name = bfa_lps_get_peer_nwwn(fabric->lps);
+
+ /*
+ * Check port type. It should be 1 = F-port.
+ */
+ if (bfa_lps_is_fport(fabric->lps)) {
+ fabric->bport.pid = bfa_lps_get_pid(fabric->lps);
+ fabric->is_npiv = bfa_lps_is_npiv_en(fabric->lps);
+ fabric->is_auth = bfa_lps_is_authreq(fabric->lps);
+ bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_CONT_OP);
+ } else {
+ /*
+ * Nport-2-Nport direct attached
+ */
+ fabric->bport.port_topo.pn2n.rem_port_wwn =
+ bfa_lps_get_peer_pwwn(fabric->lps);
+ bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_NO_FABRIC);
+ }
+
+ bfa_trc(fabric->fcs, fabric->bport.pid);
+ bfa_trc(fabric->fcs, fabric->is_npiv);
+ bfa_trc(fabric->fcs, fabric->is_auth);
+}
+/**
+ * Allocate and send FLOGI.
+ */
+static void
+bfa_fcs_fabric_login(struct bfa_fcs_fabric_s *fabric)
+{
+ struct bfa_s *bfa = fabric->fcs->bfa;
+ struct bfa_lport_cfg_s *pcfg = &fabric->bport.port_cfg;
+ u8 alpa = 0;
+
+ if (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP)
+ alpa = bfa_fcport_get_myalpa(bfa);
+
+ bfa_lps_flogi(fabric->lps, fabric, alpa, bfa_fcport_get_maxfrsize(bfa),
+ pcfg->pwwn, pcfg->nwwn, fabric->auth_reqd);
+
+ fabric->stats.flogi_sent++;
+}
+
+static void
+bfa_fcs_fabric_notify_online(struct bfa_fcs_fabric_s *fabric)
+{
+ struct bfa_fcs_vport_s *vport;
+ struct list_head *qe, *qen;
+
+ bfa_trc(fabric->fcs, fabric->fabric_name);
+
+ bfa_fcs_fabric_set_opertype(fabric);
+ fabric->stats.fabric_onlines++;
+
+ /**
+ * notify online event to base and then virtual ports
+ */
+ bfa_fcs_lport_online(&fabric->bport);
+
+ list_for_each_safe(qe, qen, &fabric->vport_q) {
+ vport = (struct bfa_fcs_vport_s *) qe;
+ bfa_fcs_vport_online(vport);
+ }
+}
+
+static void
+bfa_fcs_fabric_notify_offline(struct bfa_fcs_fabric_s *fabric)
+{
+ struct bfa_fcs_vport_s *vport;
+ struct list_head *qe, *qen;
+
+ bfa_trc(fabric->fcs, fabric->fabric_name);
+ fabric->stats.fabric_offlines++;
+
+ /**
+ * notify offline event first to vports and then base port.
+ */
+ list_for_each_safe(qe, qen, &fabric->vport_q) {
+ vport = (struct bfa_fcs_vport_s *) qe;
+ bfa_fcs_vport_offline(vport);
+ }
+
+ bfa_fcs_lport_offline(&fabric->bport);
+
+ fabric->fabric_name = 0;
+ fabric->fabric_ip_addr[0] = 0;
+}
+
+static void
+bfa_fcs_fabric_delay(void *cbarg)
{
- fcs->logm = logmod;
+ struct bfa_fcs_fabric_s *fabric = cbarg;
+
+ bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELAYED);
}
+/**
+ * Delete all vports and wait for vport delete completions.
+ */
+static void
+bfa_fcs_fabric_delete(struct bfa_fcs_fabric_s *fabric)
+{
+ struct bfa_fcs_vport_s *vport;
+ struct list_head *qe, *qen;
+ list_for_each_safe(qe, qen, &fabric->vport_q) {
+ vport = (struct bfa_fcs_vport_s *) qe;
+ bfa_fcs_vport_fcs_delete(vport);
+ }
+
+ bfa_fcs_lport_delete(&fabric->bport);
+ bfa_wc_wait(&fabric->wc);
+}
+
+static void
+bfa_fcs_fabric_delete_comp(void *cbarg)
+{
+ struct bfa_fcs_fabric_s *fabric = cbarg;
+
+ bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELCOMP);
+}
+
+/**
+ * fcs_fabric_public fabric public functions
+ */
+
+/**
+ * Attach time initialization.
+ */
void
-bfa_fcs_aen_init(struct bfa_fcs_s *fcs, struct bfa_aen_s *aen)
+bfa_fcs_fabric_attach(struct bfa_fcs_s *fcs)
{
- fcs->aen = aen;
+ struct bfa_fcs_fabric_s *fabric;
+
+ fabric = &fcs->fabric;
+ bfa_os_memset(fabric, 0, sizeof(struct bfa_fcs_fabric_s));
+
+ /**
+ * Initialize base fabric.
+ */
+ fabric->fcs = fcs;
+ INIT_LIST_HEAD(&fabric->vport_q);
+ INIT_LIST_HEAD(&fabric->vf_q);
+ fabric->lps = bfa_lps_alloc(fcs->bfa);
+ bfa_assert(fabric->lps);
+
+ /**
+ * Initialize fabric delete completion handler. Fabric deletion is
+ * complete when the last vport delete is complete.
+ */
+ bfa_wc_init(&fabric->wc, bfa_fcs_fabric_delete_comp, fabric);
+ bfa_wc_up(&fabric->wc); /* For the base port */
+
+ bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit);
+ bfa_fcs_lport_attach(&fabric->bport, fabric->fcs, FC_VF_ID_NULL, NULL);
}
void
-bfa_fcs_modexit_comp(struct bfa_fcs_s *fcs)
+bfa_fcs_fabric_modinit(struct bfa_fcs_s *fcs)
{
- bfa_wc_down(&fcs->wc);
+ bfa_sm_send_event(&fcs->fabric, BFA_FCS_FABRIC_SM_CREATE);
+ bfa_trc(fcs, 0);
}
+/**
+ * Module cleanup
+ */
+void
+bfa_fcs_fabric_modexit(struct bfa_fcs_s *fcs)
+{
+ struct bfa_fcs_fabric_s *fabric;
+
+ bfa_trc(fcs, 0);
+
+ /**
+ * Cleanup base fabric.
+ */
+ fabric = &fcs->fabric;
+ bfa_lps_delete(fabric->lps);
+ bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELETE);
+}
+/**
+ * Fabric module start -- kick starts FCS actions
+ */
+void
+bfa_fcs_fabric_modstart(struct bfa_fcs_s *fcs)
+{
+ struct bfa_fcs_fabric_s *fabric;
+
+ bfa_trc(fcs, 0);
+ fabric = &fcs->fabric;
+ bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_START);
+}
+
+/**
+ * Suspend fabric activity as part of driver suspend.
+ */
+void
+bfa_fcs_fabric_modsusp(struct bfa_fcs_s *fcs)
+{
+}
+
+bfa_boolean_t
+bfa_fcs_fabric_is_loopback(struct bfa_fcs_fabric_s *fabric)
+{
+ return bfa_sm_cmp_state(fabric, bfa_fcs_fabric_sm_loopback);
+}
+
+bfa_boolean_t
+bfa_fcs_fabric_is_auth_failed(struct bfa_fcs_fabric_s *fabric)
+{
+ return bfa_sm_cmp_state(fabric, bfa_fcs_fabric_sm_auth_failed);
+}
+
+enum bfa_port_type
+bfa_fcs_fabric_port_type(struct bfa_fcs_fabric_s *fabric)
+{
+ return fabric->oper_type;
+}
+
+/**
+ * Link up notification from BFA physical port module.
+ */
+void
+bfa_fcs_fabric_link_up(struct bfa_fcs_fabric_s *fabric)
+{
+ bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+ bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LINK_UP);
+}
+
+/**
+ * Link down notification from BFA physical port module.
+ */
+void
+bfa_fcs_fabric_link_down(struct bfa_fcs_fabric_s *fabric)
+{
+ bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+ bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LINK_DOWN);
+}
+
+/**
+ * A child vport is being created in the fabric.
+ *
+ * Call from vport module at vport creation. A list of base port and vports
+ * belonging to a fabric is maintained to propagate link events.
+ *
+ * param[in] fabric - Fabric instance. This can be a base fabric or vf.
+ * param[in] vport - Vport being created.
+ *
+ * @return None (always succeeds)
+ */
+void
+bfa_fcs_fabric_addvport(struct bfa_fcs_fabric_s *fabric,
+ struct bfa_fcs_vport_s *vport)
+{
+ /**
+ * - add vport to fabric's vport_q
+ */
+ bfa_trc(fabric->fcs, fabric->vf_id);
+
+ list_add_tail(&vport->qe, &fabric->vport_q);
+ fabric->num_vports++;
+ bfa_wc_up(&fabric->wc);
+}
+
+/**
+ * A child vport is being deleted from fabric.
+ *
+ * Vport is being deleted.
+ */
+void
+bfa_fcs_fabric_delvport(struct bfa_fcs_fabric_s *fabric,
+ struct bfa_fcs_vport_s *vport)
+{
+ list_del(&vport->qe);
+ fabric->num_vports--;
+ bfa_wc_down(&fabric->wc);
+}
+
+/**
+ * Base port is deleted.
+ */
+void
+bfa_fcs_fabric_port_delete_comp(struct bfa_fcs_fabric_s *fabric)
+{
+ bfa_wc_down(&fabric->wc);
+}
+
+
+/**
+ * Check if fabric is online.
+ *
+ * param[in] fabric - Fabric instance. This can be a base fabric or vf.
+ *
+ * @return TRUE/FALSE
+ */
+int
+bfa_fcs_fabric_is_online(struct bfa_fcs_fabric_s *fabric)
+{
+ return bfa_sm_cmp_state(fabric, bfa_fcs_fabric_sm_online);
+}
+
+/**
+ * brief
+ *
+ */
+bfa_status_t
+bfa_fcs_fabric_addvf(struct bfa_fcs_fabric_s *vf, struct bfa_fcs_s *fcs,
+ struct bfa_lport_cfg_s *port_cfg, struct bfad_vf_s *vf_drv)
+{
+ bfa_sm_set_state(vf, bfa_fcs_fabric_sm_uninit);
+ return BFA_STATUS_OK;
+}
+
+/**
+ * Lookup for a vport withing a fabric given its pwwn
+ */
+struct bfa_fcs_vport_s *
+bfa_fcs_fabric_vport_lookup(struct bfa_fcs_fabric_s *fabric, wwn_t pwwn)
+{
+ struct bfa_fcs_vport_s *vport;
+ struct list_head *qe;
+
+ list_for_each(qe, &fabric->vport_q) {
+ vport = (struct bfa_fcs_vport_s *) qe;
+ if (bfa_fcs_lport_get_pwwn(&vport->lport) == pwwn)
+ return vport;
+ }
+
+ return NULL;
+}
+
+/**
+ * In a given fabric, return the number of lports.
+ *
+ * param[in] fabric - Fabric instance. This can be a base fabric or vf.
+ *
+ * @return : 1 or more.
+ */
+u16
+bfa_fcs_fabric_vport_count(struct bfa_fcs_fabric_s *fabric)
+{
+ return fabric->num_vports;
+}
+
+/*
+ * Get OUI of the attached switch.
+ *
+ * Note : Use of this function should be avoided as much as possible.
+ * This function should be used only if there is any requirement
+* to check for FOS version below 6.3.
+ * To check if the attached fabric is a brocade fabric, use
+ * bfa_lps_is_brcd_fabric() which works for FOS versions 6.3
+ * or above only.
+ */
+
+u16
+bfa_fcs_fabric_get_switch_oui(struct bfa_fcs_fabric_s *fabric)
+{
+ wwn_t fab_nwwn;
+ u8 *tmp;
+ u16 oui;
+
+ fab_nwwn = bfa_lps_get_peer_nwwn(fabric->lps);
+
+ tmp = (u8 *)&fab_nwwn;
+ oui = (tmp[3] << 8) | tmp[4];
+
+ return oui;
+}
+/**
+ * Unsolicited frame receive handling.
+ */
+void
+bfa_fcs_fabric_uf_recv(struct bfa_fcs_fabric_s *fabric, struct fchs_s *fchs,
+ u16 len)
+{
+ u32 pid = fchs->d_id;
+ struct bfa_fcs_vport_s *vport;
+ struct list_head *qe;
+ struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
+ struct fc_logi_s *flogi = (struct fc_logi_s *) els_cmd;
+
+ bfa_trc(fabric->fcs, len);
+ bfa_trc(fabric->fcs, pid);
+
+ /**
+ * Look for our own FLOGI frames being looped back. This means an
+ * external loopback cable is in place. Our own FLOGI frames are
+ * sometimes looped back when switch port gets temporarily bypassed.
+ */
+ if ((pid == bfa_os_ntoh3b(FC_FABRIC_PORT)) &&
+ (els_cmd->els_code == FC_ELS_FLOGI) &&
+ (flogi->port_name == bfa_fcs_lport_get_pwwn(&fabric->bport))) {
+ bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LOOPBACK);
+ return;
+ }
+
+ /**
+ * FLOGI/EVFP exchanges should be consumed by base fabric.
+ */
+ if (fchs->d_id == bfa_os_hton3b(FC_FABRIC_PORT)) {
+ bfa_trc(fabric->fcs, pid);
+ bfa_fcs_fabric_process_uf(fabric, fchs, len);
+ return;
+ }
+
+ if (fabric->bport.pid == pid) {
+ /**
+ * All authentication frames should be routed to auth
+ */
+ bfa_trc(fabric->fcs, els_cmd->els_code);
+ if (els_cmd->els_code == FC_ELS_AUTH) {
+ bfa_trc(fabric->fcs, els_cmd->els_code);
+ return;
+ }
+
+ bfa_trc(fabric->fcs, *(u8 *) ((u8 *) fchs));
+ bfa_fcs_lport_uf_recv(&fabric->bport, fchs, len);
+ return;
+ }
+
+ /**
+ * look for a matching local port ID
+ */
+ list_for_each(qe, &fabric->vport_q) {
+ vport = (struct bfa_fcs_vport_s *) qe;
+ if (vport->lport.pid == pid) {
+ bfa_fcs_lport_uf_recv(&vport->lport, fchs, len);
+ return;
+ }
+ }
+ bfa_trc(fabric->fcs, els_cmd->els_code);
+ bfa_fcs_lport_uf_recv(&fabric->bport, fchs, len);
+}
+
+/**
+ * Unsolicited frames to be processed by fabric.
+ */
+static void
+bfa_fcs_fabric_process_uf(struct bfa_fcs_fabric_s *fabric, struct fchs_s *fchs,
+ u16 len)
+{
+ struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
+
+ bfa_trc(fabric->fcs, els_cmd->els_code);
+
+ switch (els_cmd->els_code) {
+ case FC_ELS_FLOGI:
+ bfa_fcs_fabric_process_flogi(fabric, fchs, len);
+ break;
+
+ default:
+ /*
+ * need to generate a LS_RJT
+ */
+ break;
+ }
+}
+
+/**
+ * Process incoming FLOGI
+ */
+static void
+bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s *fabric,
+ struct fchs_s *fchs, u16 len)
+{
+ struct fc_logi_s *flogi = (struct fc_logi_s *) (fchs + 1);
+ struct bfa_fcs_lport_s *bport = &fabric->bport;
+
+ bfa_trc(fabric->fcs, fchs->s_id);
+
+ fabric->stats.flogi_rcvd++;
+ /*
+ * Check port type. It should be 0 = n-port.
+ */
+ if (flogi->csp.port_type) {
+ /*
+ * @todo: may need to send a LS_RJT
+ */
+ bfa_trc(fabric->fcs, flogi->port_name);
+ fabric->stats.flogi_rejected++;
+ return;
+ }
+
+ fabric->bb_credit = bfa_os_ntohs(flogi->csp.bbcred);
+ bport->port_topo.pn2n.rem_port_wwn = flogi->port_name;
+ bport->port_topo.pn2n.reply_oxid = fchs->ox_id;
+
+ /*
+ * Send a Flogi Acc
+ */
+ bfa_fcs_fabric_send_flogi_acc(fabric);
+ bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_NO_FABRIC);
+}
+
+static void
+bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric)
+{
+ struct bfa_lport_cfg_s *pcfg = &fabric->bport.port_cfg;
+ struct bfa_fcs_lport_n2n_s *n2n_port = &fabric->bport.port_topo.pn2n;
+ struct bfa_s *bfa = fabric->fcs->bfa;
+ struct bfa_fcxp_s *fcxp;
+ u16 reqlen;
+ struct fchs_s fchs;
+
+ fcxp = bfa_fcs_fcxp_alloc(fabric->fcs);
+ /**
+ * Do not expect this failure -- expect remote node to retry
+ */
+ if (!fcxp)
+ return;
+
+ reqlen = fc_flogi_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+ bfa_os_hton3b(FC_FABRIC_PORT),
+ n2n_port->reply_oxid, pcfg->pwwn,
+ pcfg->nwwn,
+ bfa_fcport_get_maxfrsize(bfa),
+ bfa_fcport_get_rx_bbcredit(bfa));
+
+ bfa_fcxp_send(fcxp, NULL, fabric->vf_id, bfa_lps_get_tag(fabric->lps),
+ BFA_FALSE, FC_CLASS_3,
+ reqlen, &fchs, bfa_fcs_fabric_flogiacc_comp, fabric,
+ FC_MAX_PDUSZ, 0);
+}
+
+/**
+ * Flogi Acc completion callback.
+ */
+static void
+bfa_fcs_fabric_flogiacc_comp(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
+ bfa_status_t status, u32 rsp_len,
+ u32 resid_len, struct fchs_s *rspfchs)
+{
+ struct bfa_fcs_fabric_s *fabric = cbarg;
+
+ bfa_trc(fabric->fcs, status);
+}
+
+/*
+ *
+ * @param[in] fabric - fabric
+ * @param[in] wwn_t - new fabric name
+ *
+ * @return - none
+ */
+void
+bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric,
+ wwn_t fabric_name)
+{
+ struct bfad_s *bfad = (struct bfad_s *)fabric->fcs->bfad;
+ char pwwn_ptr[BFA_STRING_32];
+ char fwwn_ptr[BFA_STRING_32];
+
+ bfa_trc(fabric->fcs, fabric_name);
+
+ if (fabric->fabric_name == 0) {
+ /*
+ * With BRCD switches, we don't get Fabric Name in FLOGI.
+ * Don't generate a fabric name change event in this case.
+ */
+ fabric->fabric_name = fabric_name;
+ } else {
+ fabric->fabric_name = fabric_name;
+ wwn2str(pwwn_ptr, bfa_fcs_lport_get_pwwn(&fabric->bport));
+ wwn2str(fwwn_ptr,
+ bfa_fcs_lport_get_fabric_name(&fabric->bport));
+ BFA_LOG(KERN_WARNING, bfad, log_level,
+ "Base port WWN = %s Fabric WWN = %s\n",
+ pwwn_ptr, fwwn_ptr);
+ }
+}
+
+/**
+ * fcs_vf_api virtual fabrics API
+ */
+
+/**
+ * Enable VF mode.
+ *
+ * @param[in] fcs fcs module instance
+ * @param[in] vf_id default vf_id of port, FC_VF_ID_NULL
+ * to use standard default vf_id of 1.
+ *
+ * @retval BFA_STATUS_OK vf mode is enabled
+ * @retval BFA_STATUS_BUSY Port is active. Port must be disabled
+ * before VF mode can be enabled.
+ */
+bfa_status_t
+bfa_fcs_vf_mode_enable(struct bfa_fcs_s *fcs, u16 vf_id)
+{
+ return BFA_STATUS_OK;
+}
+
+/**
+ * Disable VF mode.
+ *
+ * @param[in] fcs fcs module instance
+ *
+ * @retval BFA_STATUS_OK vf mode is disabled
+ * @retval BFA_STATUS_BUSY VFs are present and being used. All
+ * VFs must be deleted before disabling
+ * VF mode.
+ */
+bfa_status_t
+bfa_fcs_vf_mode_disable(struct bfa_fcs_s *fcs)
+{
+ return BFA_STATUS_OK;
+}
+
+/**
+ * Create a new VF instance.
+ *
+ * A new VF is created using the given VF configuration. A VF is identified
+ * by VF id. No duplicate VF creation is allowed with the same VF id. Once
+ * a VF is created, VF is automatically started after link initialization
+ * and EVFP exchange is completed.
+ *
+ * param[in] vf - FCS vf data structure. Memory is
+ * allocated by caller (driver)
+ * param[in] fcs - FCS module
+ * param[in] vf_cfg - VF configuration
+ * param[in] vf_drv - Opaque handle back to the driver's
+ * virtual vf structure
+ *
+ * retval BFA_STATUS_OK VF creation is successful
+ * retval BFA_STATUS_FAILED VF creation failed
+ * retval BFA_STATUS_EEXIST A VF exists with the given vf_id
+ */
+bfa_status_t
+bfa_fcs_vf_create(bfa_fcs_vf_t *vf, struct bfa_fcs_s *fcs, u16 vf_id,
+ struct bfa_lport_cfg_s *port_cfg, struct bfad_vf_s *vf_drv)
+{
+ bfa_trc(fcs, vf_id);
+ return BFA_STATUS_OK;
+}
+
+/**
+ * Use this function to delete a BFA VF object. VF object should
+ * be stopped before this function call.
+ *
+ * param[in] vf - pointer to bfa_vf_t.
+ *
+ * retval BFA_STATUS_OK On vf deletion success
+ * retval BFA_STATUS_BUSY VF is not in a stopped state
+ * retval BFA_STATUS_INPROGRESS VF deletion in in progress
+ */
+bfa_status_t
+bfa_fcs_vf_delete(bfa_fcs_vf_t *vf)
+{
+ bfa_trc(vf->fcs, vf->vf_id);
+ return BFA_STATUS_OK;
+}
+
+
+/**
+ * Returns attributes of the given VF.
+ *
+ * param[in] vf pointer to bfa_vf_t.
+ * param[out] vf_attr vf attributes returned
+ *
+ * return None
+ */
+void
+bfa_fcs_vf_get_attr(bfa_fcs_vf_t *vf, struct bfa_vf_attr_s *vf_attr)
+{
+ bfa_trc(vf->fcs, vf->vf_id);
+}
+
+/**
+ * Return statistics associated with the given vf.
+ *
+ * param[in] vf pointer to bfa_vf_t.
+ * param[out] vf_stats vf statistics returned
+ *
+ * @return None
+ */
+void
+bfa_fcs_vf_get_stats(bfa_fcs_vf_t *vf, struct bfa_vf_stats_s *vf_stats)
+{
+ bfa_os_memcpy(vf_stats, &vf->stats, sizeof(struct bfa_vf_stats_s));
+}
+
+/**
+ * clear statistics associated with the given vf.
+ *
+ * param[in] vf pointer to bfa_vf_t.
+ *
+ * @return None
+ */
+void
+bfa_fcs_vf_clear_stats(bfa_fcs_vf_t *vf)
+{
+ bfa_os_memset(&vf->stats, 0, sizeof(struct bfa_vf_stats_s));
+}
+
+/**
+ * Returns FCS vf structure for a given vf_id.
+ *
+ * param[in] vf_id - VF_ID
+ *
+ * return
+ * If lookup succeeds, retuns fcs vf object, otherwise returns NULL
+ */
+bfa_fcs_vf_t *
+bfa_fcs_vf_lookup(struct bfa_fcs_s *fcs, u16 vf_id)
+{
+ bfa_trc(fcs, vf_id);
+ if (vf_id == FC_VF_ID_NULL)
+ return &fcs->fabric;
+
+ return NULL;
+}
+
+/**
+ * Return the list of VFs configured.
+ *
+ * param[in] fcs fcs module instance
+ * param[out] vf_ids returned list of vf_ids
+ * param[in,out] nvfs in:size of vf_ids array,
+ * out:total elements present,
+ * actual elements returned is limited by the size
+ *
+ * return Driver VF structure
+ */
+void
+bfa_fcs_vf_list(struct bfa_fcs_s *fcs, u16 *vf_ids, int *nvfs)
+{
+ bfa_trc(fcs, *nvfs);
+}
+
+/**
+ * Return the list of all VFs visible from fabric.
+ *
+ * param[in] fcs fcs module instance
+ * param[out] vf_ids returned list of vf_ids
+ * param[in,out] nvfs in:size of vf_ids array,
+ * out:total elements present,
+ * actual elements returned is limited by the size
+ *
+ * return Driver VF structure
+ */
+void
+bfa_fcs_vf_list_all(struct bfa_fcs_s *fcs, u16 *vf_ids, int *nvfs)
+{
+ bfa_trc(fcs, *nvfs);
+}
+
+/**
+ * Return the list of local logical ports present in the given VF.
+ *
+ * param[in] vf vf for which logical ports are returned
+ * param[out] lpwwn returned logical port wwn list
+ * param[in,out] nlports in:size of lpwwn list;
+ * out:total elements present,
+ * actual elements returned is limited by the size
+ */
+void
+bfa_fcs_vf_get_ports(bfa_fcs_vf_t *vf, wwn_t lpwwn[], int *nlports)
+{
+ struct list_head *qe;
+ struct bfa_fcs_vport_s *vport;
+ int i;
+ struct bfa_fcs_s *fcs;
+
+ if (vf == NULL || lpwwn == NULL || *nlports == 0)
+ return;
+
+ fcs = vf->fcs;
+
+ bfa_trc(fcs, vf->vf_id);
+ bfa_trc(fcs, (u32) *nlports);
+
+ i = 0;
+ lpwwn[i++] = vf->bport.port_cfg.pwwn;
+
+ list_for_each(qe, &vf->vport_q) {
+ if (i >= *nlports)
+ break;
+
+ vport = (struct bfa_fcs_vport_s *) qe;
+ lpwwn[i++] = vport->lport.port_cfg.pwwn;
+ }
+
+ bfa_trc(fcs, i);
+ *nlports = i;
+}
+
+/**
+ * BFA FCS PPORT ( physical port)
+ */
+static void
+bfa_fcs_port_event_handler(void *cbarg, enum bfa_port_linkstate event)
+{
+ struct bfa_fcs_s *fcs = cbarg;
+
+ bfa_trc(fcs, event);
+
+ switch (event) {
+ case BFA_PORT_LINKUP:
+ bfa_fcs_fabric_link_up(&fcs->fabric);
+ break;
+
+ case BFA_PORT_LINKDOWN:
+ bfa_fcs_fabric_link_down(&fcs->fabric);
+ break;
+
+ default:
+ bfa_assert(0);
+ }
+}
+
+void
+bfa_fcs_port_attach(struct bfa_fcs_s *fcs)
+{
+ bfa_fcport_event_register(fcs->bfa, bfa_fcs_port_event_handler, fcs);
+}
+
+/**
+ * BFA FCS UF ( Unsolicited Frames)
+ */
+
+/**
+ * BFA callback for unsolicited frame receive handler.
+ *
+ * @param[in] cbarg callback arg for receive handler
+ * @param[in] uf unsolicited frame descriptor
+ *
+ * @return None
+ */
+static void
+bfa_fcs_uf_recv(void *cbarg, struct bfa_uf_s *uf)
+{
+ struct bfa_fcs_s *fcs = (struct bfa_fcs_s *) cbarg;
+ struct fchs_s *fchs = bfa_uf_get_frmbuf(uf);
+ u16 len = bfa_uf_get_frmlen(uf);
+ struct fc_vft_s *vft;
+ struct bfa_fcs_fabric_s *fabric;
+
+ /**
+ * check for VFT header
+ */
+ if (fchs->routing == FC_RTG_EXT_HDR &&
+ fchs->cat_info == FC_CAT_VFT_HDR) {
+ bfa_stats(fcs, uf.tagged);
+ vft = bfa_uf_get_frmbuf(uf);
+ if (fcs->port_vfid == vft->vf_id)
+ fabric = &fcs->fabric;
+ else
+ fabric = bfa_fcs_vf_lookup(fcs, (u16) vft->vf_id);
+
+ /**
+ * drop frame if vfid is unknown
+ */
+ if (!fabric) {
+ bfa_assert(0);
+ bfa_stats(fcs, uf.vfid_unknown);
+ bfa_uf_free(uf);
+ return;
+ }
+
+ /**
+ * skip vft header
+ */
+ fchs = (struct fchs_s *) (vft + 1);
+ len -= sizeof(struct fc_vft_s);
+
+ bfa_trc(fcs, vft->vf_id);
+ } else {
+ bfa_stats(fcs, uf.untagged);
+ fabric = &fcs->fabric;
+ }
+
+ bfa_trc(fcs, ((u32 *) fchs)[0]);
+ bfa_trc(fcs, ((u32 *) fchs)[1]);
+ bfa_trc(fcs, ((u32 *) fchs)[2]);
+ bfa_trc(fcs, ((u32 *) fchs)[3]);
+ bfa_trc(fcs, ((u32 *) fchs)[4]);
+ bfa_trc(fcs, ((u32 *) fchs)[5]);
+ bfa_trc(fcs, len);
+
+ bfa_fcs_fabric_uf_recv(fabric, fchs, len);
+ bfa_uf_free(uf);
+}
+
+void
+bfa_fcs_uf_attach(struct bfa_fcs_s *fcs)
+{
+ bfa_uf_recv_register(fcs->bfa, bfa_fcs_uf_recv, fcs);
+}
diff --git a/drivers/scsi/bfa/bfa_fcs.h b/drivers/scsi/bfa/bfa_fcs.h
new file mode 100644
index 000000000000..d75045df1e7e
--- /dev/null
+++ b/drivers/scsi/bfa/bfa_fcs.h
@@ -0,0 +1,779 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_FCS_H__
+#define __BFA_FCS_H__
+
+#include "bfa_cs.h"
+#include "bfa_defs.h"
+#include "bfa_defs_fcs.h"
+#include "bfa_modules.h"
+#include "bfa_fc.h"
+
+#define BFA_FCS_OS_STR_LEN 64
+
+/*
+ * !!! Only append to the enums defined here to avoid any versioning
+ * !!! needed between trace utility and driver version
+ */
+enum {
+ BFA_TRC_FCS_FCS = 1,
+ BFA_TRC_FCS_PORT = 2,
+ BFA_TRC_FCS_RPORT = 3,
+ BFA_TRC_FCS_FCPIM = 4,
+};
+
+
+struct bfa_fcs_s;
+
+#define __fcs_min_cfg(__fcs) ((__fcs)->min_cfg)
+void bfa_fcs_modexit_comp(struct bfa_fcs_s *fcs);
+
+#define BFA_FCS_BRCD_SWITCH_OUI 0x051e
+#define N2N_LOCAL_PID 0x010000
+#define N2N_REMOTE_PID 0x020000
+#define BFA_FCS_RETRY_TIMEOUT 2000
+#define BFA_FCS_PID_IS_WKA(pid) ((bfa_os_ntoh3b(pid) > 0xFFF000) ? 1 : 0)
+
+
+
+struct bfa_fcs_lport_ns_s {
+ bfa_sm_t sm; /* state machine */
+ struct bfa_timer_s timer;
+ struct bfa_fcs_lport_s *port; /* parent port */
+ struct bfa_fcxp_s *fcxp;
+ struct bfa_fcxp_wqe_s fcxp_wqe;
+};
+
+
+struct bfa_fcs_lport_scn_s {
+ bfa_sm_t sm; /* state machine */
+ struct bfa_timer_s timer;
+ struct bfa_fcs_lport_s *port; /* parent port */
+ struct bfa_fcxp_s *fcxp;
+ struct bfa_fcxp_wqe_s fcxp_wqe;
+};
+
+
+struct bfa_fcs_lport_fdmi_s {
+ bfa_sm_t sm; /* state machine */
+ struct bfa_timer_s timer;
+ struct bfa_fcs_lport_ms_s *ms; /* parent ms */
+ struct bfa_fcxp_s *fcxp;
+ struct bfa_fcxp_wqe_s fcxp_wqe;
+ u8 retry_cnt; /* retry count */
+ u8 rsvd[3];
+};
+
+
+struct bfa_fcs_lport_ms_s {
+ bfa_sm_t sm; /* state machine */
+ struct bfa_timer_s timer;
+ struct bfa_fcs_lport_s *port; /* parent port */
+ struct bfa_fcxp_s *fcxp;
+ struct bfa_fcxp_wqe_s fcxp_wqe;
+ struct bfa_fcs_lport_fdmi_s fdmi; /* FDMI component of MS */
+ u8 retry_cnt; /* retry count */
+ u8 rsvd[3];
+};
+
+
+struct bfa_fcs_lport_fab_s {
+ struct bfa_fcs_lport_ns_s ns; /* NS component of port */
+ struct bfa_fcs_lport_scn_s scn; /* scn component of port */
+ struct bfa_fcs_lport_ms_s ms; /* MS component of port */
+};
+
+#define MAX_ALPA_COUNT 127
+
+struct bfa_fcs_lport_loop_s {
+ u8 num_alpa; /* Num of ALPA entries in the map */
+ u8 alpa_pos_map[MAX_ALPA_COUNT]; /* ALPA Positional
+ *Map */
+ struct bfa_fcs_lport_s *port; /* parent port */
+};
+
+struct bfa_fcs_lport_n2n_s {
+ u32 rsvd;
+ u16 reply_oxid; /* ox_id from the req flogi to be
+ *used in flogi acc */
+ wwn_t rem_port_wwn; /* Attached port's wwn */
+};
+
+
+union bfa_fcs_lport_topo_u {
+ struct bfa_fcs_lport_fab_s pfab;
+ struct bfa_fcs_lport_loop_s ploop;
+ struct bfa_fcs_lport_n2n_s pn2n;
+};
+
+
+struct bfa_fcs_lport_s {
+ struct list_head qe; /* used by port/vport */
+ bfa_sm_t sm; /* state machine */
+ struct bfa_fcs_fabric_s *fabric; /* parent fabric */
+ struct bfa_lport_cfg_s port_cfg; /* port configuration */
+ struct bfa_timer_s link_timer; /* timer for link offline */
+ u32 pid:24; /* FC address */
+ u8 lp_tag; /* lport tag */
+ u16 num_rports; /* Num of r-ports */
+ struct list_head rport_q; /* queue of discovered r-ports */
+ struct bfa_fcs_s *fcs; /* FCS instance */
+ union bfa_fcs_lport_topo_u port_topo; /* fabric/loop/n2n details */
+ struct bfad_port_s *bfad_port; /* driver peer instance */
+ struct bfa_fcs_vport_s *vport; /* NULL for base ports */
+ struct bfa_fcxp_s *fcxp;
+ struct bfa_fcxp_wqe_s fcxp_wqe;
+ struct bfa_lport_stats_s stats;
+ struct bfa_wc_s wc; /* waiting counter for events */
+};
+#define BFA_FCS_GET_HAL_FROM_PORT(port) (port->fcs->bfa)
+#define BFA_FCS_GET_NS_FROM_PORT(port) (&port->port_topo.pfab.ns)
+#define BFA_FCS_GET_SCN_FROM_PORT(port) (&port->port_topo.pfab.scn)
+#define BFA_FCS_GET_MS_FROM_PORT(port) (&port->port_topo.pfab.ms)
+#define BFA_FCS_GET_FDMI_FROM_PORT(port) (&port->port_topo.pfab.ms.fdmi)
+#define BFA_FCS_VPORT_IS_INITIATOR_MODE(port) \
+ (port->port_cfg.roles & BFA_LPORT_ROLE_FCP_IM)
+
+/*
+ * forward declaration
+ */
+struct bfad_vf_s;
+
+enum bfa_fcs_fabric_type {
+ BFA_FCS_FABRIC_UNKNOWN = 0,
+ BFA_FCS_FABRIC_SWITCHED = 1,
+ BFA_FCS_FABRIC_N2N = 2,
+};
+
+
+struct bfa_fcs_fabric_s {
+ struct list_head qe; /* queue element */
+ bfa_sm_t sm; /* state machine */
+ struct bfa_fcs_s *fcs; /* FCS instance */
+ struct bfa_fcs_lport_s bport; /* base logical port */
+ enum bfa_fcs_fabric_type fab_type; /* fabric type */
+ enum bfa_port_type oper_type; /* current link topology */
+ u8 is_vf; /* is virtual fabric? */
+ u8 is_npiv; /* is NPIV supported ? */
+ u8 is_auth; /* is Security/Auth supported ? */
+ u16 bb_credit; /* BB credit from fabric */
+ u16 vf_id; /* virtual fabric ID */
+ u16 num_vports; /* num vports */
+ u16 rsvd;
+ struct list_head vport_q; /* queue of virtual ports */
+ struct list_head vf_q; /* queue of virtual fabrics */
+ struct bfad_vf_s *vf_drv; /* driver vf structure */
+ struct bfa_timer_s link_timer; /* Link Failure timer. Vport */
+ wwn_t fabric_name; /* attached fabric name */
+ bfa_boolean_t auth_reqd; /* authentication required */
+ struct bfa_timer_s delay_timer; /* delay timer */
+ union {
+ u16 swp_vfid;/* switch port VF id */
+ } event_arg;
+ struct bfa_wc_s wc; /* wait counter for delete */
+ struct bfa_vf_stats_s stats; /* fabric/vf stats */
+ struct bfa_lps_s *lps; /* lport login services */
+ u8 fabric_ip_addr[BFA_FCS_FABRIC_IPADDR_SZ];
+ /* attached fabric's ip addr */
+};
+
+#define bfa_fcs_fabric_npiv_capable(__f) ((__f)->is_npiv)
+#define bfa_fcs_fabric_is_switched(__f) \
+ ((__f)->fab_type == BFA_FCS_FABRIC_SWITCHED)
+
+/**
+ * The design calls for a single implementation of base fabric and vf.
+ */
+#define bfa_fcs_vf_t struct bfa_fcs_fabric_s
+
+struct bfa_vf_event_s {
+ u32 undefined;
+};
+
+struct bfa_fcs_s;
+struct bfa_fcs_fabric_s;
+
+/*
+ * @todo : need to move to a global config file.
+ * Maximum Rports supported per port (physical/logical).
+ */
+#define BFA_FCS_MAX_RPORTS_SUPP 256 /* @todo : tentative value */
+
+#define bfa_fcs_lport_t struct bfa_fcs_lport_s
+
+/**
+ * Symbolic Name related defines
+ * Total bytes 255.
+ * Physical Port's symbolic name 128 bytes.
+ * For Vports, Vport's symbolic name is appended to the Physical port's
+ * Symbolic Name.
+ *
+ * Physical Port's symbolic name Format : (Total 128 bytes)
+ * Adapter Model number/name : 12 bytes
+ * Driver Version : 10 bytes
+ * Host Machine Name : 30 bytes
+ * Host OS Info : 48 bytes
+ * Host OS PATCH Info : 16 bytes
+ * ( remaining 12 bytes reserved to be used for separator)
+ */
+#define BFA_FCS_PORT_SYMBNAME_SEPARATOR " | "
+
+#define BFA_FCS_PORT_SYMBNAME_MODEL_SZ 12
+#define BFA_FCS_PORT_SYMBNAME_VERSION_SZ 10
+#define BFA_FCS_PORT_SYMBNAME_MACHINENAME_SZ 30
+#define BFA_FCS_PORT_SYMBNAME_OSINFO_SZ 48
+#define BFA_FCS_PORT_SYMBNAME_OSPATCH_SZ 16
+
+/**
+ * Get FC port ID for a logical port.
+ */
+#define bfa_fcs_lport_get_fcid(_lport) ((_lport)->pid)
+#define bfa_fcs_lport_get_pwwn(_lport) ((_lport)->port_cfg.pwwn)
+#define bfa_fcs_lport_get_nwwn(_lport) ((_lport)->port_cfg.nwwn)
+#define bfa_fcs_lport_get_psym_name(_lport) ((_lport)->port_cfg.sym_name)
+#define bfa_fcs_lport_is_initiator(_lport) \
+ ((_lport)->port_cfg.roles & BFA_LPORT_ROLE_FCP_IM)
+#define bfa_fcs_lport_get_nrports(_lport) \
+ ((_lport) ? (_lport)->num_rports : 0)
+
+static inline struct bfad_port_s *
+bfa_fcs_lport_get_drvport(struct bfa_fcs_lport_s *port)
+{
+ return port->bfad_port;
+}
+
+#define bfa_fcs_lport_get_opertype(_lport) ((_lport)->fabric->oper_type)
+#define bfa_fcs_lport_get_fabric_name(_lport) ((_lport)->fabric->fabric_name)
+#define bfa_fcs_lport_get_fabric_ipaddr(_lport) \
+ ((_lport)->fabric->fabric_ip_addr)
+
+/**
+ * bfa fcs port public functions
+ */
+
+bfa_boolean_t bfa_fcs_lport_is_online(struct bfa_fcs_lport_s *port);
+struct bfa_fcs_lport_s *bfa_fcs_get_base_port(struct bfa_fcs_s *fcs);
+void bfa_fcs_lport_get_rports(struct bfa_fcs_lport_s *port,
+ wwn_t rport_wwns[], int *nrports);
+
+wwn_t bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s *port, wwn_t wwn,
+ int index, int nrports, bfa_boolean_t bwwn);
+
+struct bfa_fcs_lport_s *bfa_fcs_lookup_port(struct bfa_fcs_s *fcs,
+ u16 vf_id, wwn_t lpwwn);
+
+void bfa_fcs_lport_get_info(struct bfa_fcs_lport_s *port,
+ struct bfa_lport_info_s *port_info);
+void bfa_fcs_lport_get_attr(struct bfa_fcs_lport_s *port,
+ struct bfa_lport_attr_s *port_attr);
+void bfa_fcs_lport_get_stats(struct bfa_fcs_lport_s *fcs_port,
+ struct bfa_lport_stats_s *port_stats);
+void bfa_fcs_lport_clear_stats(struct bfa_fcs_lport_s *fcs_port);
+enum bfa_port_speed bfa_fcs_lport_get_rport_max_speed(
+ struct bfa_fcs_lport_s *port);
+
+/* MS FCS routines */
+void bfa_fcs_lport_ms_init(struct bfa_fcs_lport_s *port);
+void bfa_fcs_lport_ms_offline(struct bfa_fcs_lport_s *port);
+void bfa_fcs_lport_ms_online(struct bfa_fcs_lport_s *port);
+void bfa_fcs_lport_ms_fabric_rscn(struct bfa_fcs_lport_s *port);
+
+/* FDMI FCS routines */
+void bfa_fcs_lport_fdmi_init(struct bfa_fcs_lport_ms_s *ms);
+void bfa_fcs_lport_fdmi_offline(struct bfa_fcs_lport_ms_s *ms);
+void bfa_fcs_lport_fdmi_online(struct bfa_fcs_lport_ms_s *ms);
+void bfa_fcs_lport_uf_recv(struct bfa_fcs_lport_s *lport, struct fchs_s *fchs,
+ u16 len);
+void bfa_fcs_lport_attach(struct bfa_fcs_lport_s *lport, struct bfa_fcs_s *fcs,
+ u16 vf_id, struct bfa_fcs_vport_s *vport);
+void bfa_fcs_lport_init(struct bfa_fcs_lport_s *lport,
+ struct bfa_lport_cfg_s *port_cfg);
+void bfa_fcs_lport_online(struct bfa_fcs_lport_s *port);
+void bfa_fcs_lport_offline(struct bfa_fcs_lport_s *port);
+void bfa_fcs_lport_delete(struct bfa_fcs_lport_s *port);
+struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_pid(
+ struct bfa_fcs_lport_s *port, u32 pid);
+struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_pwwn(
+ struct bfa_fcs_lport_s *port, wwn_t pwwn);
+struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_nwwn(
+ struct bfa_fcs_lport_s *port, wwn_t nwwn);
+void bfa_fcs_lport_add_rport(struct bfa_fcs_lport_s *port,
+ struct bfa_fcs_rport_s *rport);
+void bfa_fcs_lport_del_rport(struct bfa_fcs_lport_s *port,
+ struct bfa_fcs_rport_s *rport);
+void bfa_fcs_lport_modinit(struct bfa_fcs_s *fcs);
+void bfa_fcs_lport_modexit(struct bfa_fcs_s *fcs);
+void bfa_fcs_lport_ns_init(struct bfa_fcs_lport_s *vport);
+void bfa_fcs_lport_ns_offline(struct bfa_fcs_lport_s *vport);
+void bfa_fcs_lport_ns_online(struct bfa_fcs_lport_s *vport);
+void bfa_fcs_lport_ns_query(struct bfa_fcs_lport_s *port);
+void bfa_fcs_lport_scn_init(struct bfa_fcs_lport_s *vport);
+void bfa_fcs_lport_scn_offline(struct bfa_fcs_lport_s *vport);
+void bfa_fcs_lport_scn_online(struct bfa_fcs_lport_s *vport);
+void bfa_fcs_lport_scn_process_rscn(struct bfa_fcs_lport_s *port,
+ struct fchs_s *rx_frame, u32 len);
+
+struct bfa_fcs_vport_s {
+ struct list_head qe; /* queue elem */
+ bfa_sm_t sm; /* state machine */
+ bfa_fcs_lport_t lport; /* logical port */
+ struct bfa_timer_s timer;
+ struct bfad_vport_s *vport_drv; /* Driver private */
+ struct bfa_vport_stats_s vport_stats; /* vport statistics */
+ struct bfa_lps_s *lps; /* Lport login service*/
+ int fdisc_retries;
+};
+
+#define bfa_fcs_vport_get_port(vport) \
+ ((struct bfa_fcs_lport_s *)(&vport->port))
+
+/**
+ * bfa fcs vport public functions
+ */
+bfa_status_t bfa_fcs_vport_create(struct bfa_fcs_vport_s *vport,
+ struct bfa_fcs_s *fcs, u16 vf_id,
+ struct bfa_lport_cfg_s *port_cfg,
+ struct bfad_vport_s *vport_drv);
+bfa_status_t bfa_fcs_pbc_vport_create(struct bfa_fcs_vport_s *vport,
+ struct bfa_fcs_s *fcs, u16 vf_id,
+ struct bfa_lport_cfg_s *port_cfg,
+ struct bfad_vport_s *vport_drv);
+bfa_boolean_t bfa_fcs_is_pbc_vport(struct bfa_fcs_vport_s *vport);
+bfa_status_t bfa_fcs_vport_delete(struct bfa_fcs_vport_s *vport);
+bfa_status_t bfa_fcs_vport_start(struct bfa_fcs_vport_s *vport);
+bfa_status_t bfa_fcs_vport_stop(struct bfa_fcs_vport_s *vport);
+void bfa_fcs_vport_get_attr(struct bfa_fcs_vport_s *vport,
+ struct bfa_vport_attr_s *vport_attr);
+void bfa_fcs_vport_get_stats(struct bfa_fcs_vport_s *vport,
+ struct bfa_vport_stats_s *vport_stats);
+void bfa_fcs_vport_clr_stats(struct bfa_fcs_vport_s *vport);
+struct bfa_fcs_vport_s *bfa_fcs_vport_lookup(struct bfa_fcs_s *fcs,
+ u16 vf_id, wwn_t vpwwn);
+void bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s *vport);
+void bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport);
+void bfa_fcs_vport_offline(struct bfa_fcs_vport_s *vport);
+void bfa_fcs_vport_delete_comp(struct bfa_fcs_vport_s *vport);
+void bfa_fcs_vport_fcs_delete(struct bfa_fcs_vport_s *vport);
+
+#define BFA_FCS_RPORT_DEF_DEL_TIMEOUT 90 /* in secs */
+#define BFA_FCS_RPORT_MAX_RETRIES (5)
+
+/*
+ * forward declarations
+ */
+struct bfad_rport_s;
+
+struct bfa_fcs_itnim_s;
+struct bfa_fcs_tin_s;
+struct bfa_fcs_iprp_s;
+
+/* Rport Features (RPF) */
+struct bfa_fcs_rpf_s {
+ bfa_sm_t sm; /* state machine */
+ struct bfa_fcs_rport_s *rport; /* parent rport */
+ struct bfa_timer_s timer; /* general purpose timer */
+ struct bfa_fcxp_s *fcxp; /* FCXP needed for discarding */
+ struct bfa_fcxp_wqe_s fcxp_wqe; /* fcxp wait queue element */
+ int rpsc_retries; /* max RPSC retry attempts */
+ enum bfa_port_speed rpsc_speed;
+ /* Current Speed from RPSC. O if RPSC fails */
+ enum bfa_port_speed assigned_speed;
+ /**
+ * Speed assigned by the user. will be used if RPSC is
+ * not supported by the rport.
+ */
+};
+
+struct bfa_fcs_rport_s {
+ struct list_head qe; /* used by port/vport */
+ struct bfa_fcs_lport_s *port; /* parent FCS port */
+ struct bfa_fcs_s *fcs; /* fcs instance */
+ struct bfad_rport_s *rp_drv; /* driver peer instance */
+ u32 pid; /* port ID of rport */
+ u16 maxfrsize; /* maximum frame size */
+ u16 reply_oxid; /* OX_ID of inbound requests */
+ enum fc_cos fc_cos; /* FC classes of service supp */
+ bfa_boolean_t cisc; /* CISC capable device */
+ bfa_boolean_t prlo; /* processing prlo or LOGO */
+ wwn_t pwwn; /* port wwn of rport */
+ wwn_t nwwn; /* node wwn of rport */
+ struct bfa_rport_symname_s psym_name; /* port symbolic name */
+ bfa_sm_t sm; /* state machine */
+ struct bfa_timer_s timer; /* general purpose timer */
+ struct bfa_fcs_itnim_s *itnim; /* ITN initiator mode role */
+ struct bfa_fcs_tin_s *tin; /* ITN initiator mode role */
+ struct bfa_fcs_iprp_s *iprp; /* IP/FC role */
+ struct bfa_rport_s *bfa_rport; /* BFA Rport */
+ struct bfa_fcxp_s *fcxp; /* FCXP needed for discarding */
+ int plogi_retries; /* max plogi retry attempts */
+ int ns_retries; /* max NS query retry attempts */
+ struct bfa_fcxp_wqe_s fcxp_wqe; /* fcxp wait queue element */
+ struct bfa_rport_stats_s stats; /* rport stats */
+ enum bfa_rport_function scsi_function; /* Initiator/Target */
+ struct bfa_fcs_rpf_s rpf; /* Rport features module */
+};
+
+static inline struct bfa_rport_s *
+bfa_fcs_rport_get_halrport(struct bfa_fcs_rport_s *rport)
+{
+ return rport->bfa_rport;
+}
+
+/**
+ * bfa fcs rport API functions
+ */
+bfa_status_t bfa_fcs_rport_add(struct bfa_fcs_lport_s *port, wwn_t *pwwn,
+ struct bfa_fcs_rport_s *rport,
+ struct bfad_rport_s *rport_drv);
+bfa_status_t bfa_fcs_rport_remove(struct bfa_fcs_rport_s *rport);
+void bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport,
+ struct bfa_rport_attr_s *attr);
+void bfa_fcs_rport_get_stats(struct bfa_fcs_rport_s *rport,
+ struct bfa_rport_stats_s *stats);
+void bfa_fcs_rport_clear_stats(struct bfa_fcs_rport_s *rport);
+struct bfa_fcs_rport_s *bfa_fcs_rport_lookup(struct bfa_fcs_lport_s *port,
+ wwn_t rpwwn);
+struct bfa_fcs_rport_s *bfa_fcs_rport_lookup_by_nwwn(
+ struct bfa_fcs_lport_s *port, wwn_t rnwwn);
+void bfa_fcs_rport_set_del_timeout(u8 rport_tmo);
+
+void bfa_fcs_rport_set_speed(struct bfa_fcs_rport_s *rport,
+ enum bfa_port_speed speed);
+void bfa_fcs_rport_uf_recv(struct bfa_fcs_rport_s *rport,
+ struct fchs_s *fchs, u16 len);
+void bfa_fcs_rport_scn(struct bfa_fcs_rport_s *rport);
+
+struct bfa_fcs_rport_s *bfa_fcs_rport_create(struct bfa_fcs_lport_s *port,
+ u32 pid);
+void bfa_fcs_rport_delete(struct bfa_fcs_rport_s *rport);
+void bfa_fcs_rport_online(struct bfa_fcs_rport_s *rport);
+void bfa_fcs_rport_offline(struct bfa_fcs_rport_s *rport);
+void bfa_fcs_rport_start(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
+ struct fc_logi_s *plogi_rsp);
+void bfa_fcs_rport_plogi_create(struct bfa_fcs_lport_s *port,
+ struct fchs_s *rx_fchs,
+ struct fc_logi_s *plogi);
+void bfa_fcs_rport_plogi(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs,
+ struct fc_logi_s *plogi);
+void bfa_fcs_rport_logo_imp(struct bfa_fcs_rport_s *rport);
+void bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, u16 ox_id);
+
+void bfa_fcs_rport_itnim_ack(struct bfa_fcs_rport_s *rport);
+void bfa_fcs_rport_itntm_ack(struct bfa_fcs_rport_s *rport);
+void bfa_fcs_rport_fcptm_offline_done(struct bfa_fcs_rport_s *rport);
+int bfa_fcs_rport_get_state(struct bfa_fcs_rport_s *rport);
+struct bfa_fcs_rport_s *bfa_fcs_rport_create_by_wwn(
+ struct bfa_fcs_lport_s *port, wwn_t wwn);
+void bfa_fcs_rpf_init(struct bfa_fcs_rport_s *rport);
+void bfa_fcs_rpf_rport_online(struct bfa_fcs_rport_s *rport);
+void bfa_fcs_rpf_rport_offline(struct bfa_fcs_rport_s *rport);
+
+/*
+ * forward declarations
+ */
+struct bfad_itnim_s;
+
+struct bfa_fcs_itnim_s {
+ bfa_sm_t sm; /* state machine */
+ struct bfa_fcs_rport_s *rport; /* parent remote rport */
+ struct bfad_itnim_s *itnim_drv; /* driver peer instance */
+ struct bfa_fcs_s *fcs; /* fcs instance */
+ struct bfa_timer_s timer; /* timer functions */
+ struct bfa_itnim_s *bfa_itnim; /* BFA itnim struct */
+ u32 prli_retries; /* max prli retry attempts */
+ bfa_boolean_t seq_rec; /* seq recovery support */
+ bfa_boolean_t rec_support; /* REC supported */
+ bfa_boolean_t conf_comp; /* FCP_CONF support */
+ bfa_boolean_t task_retry_id; /* task retry id supp */
+ struct bfa_fcxp_wqe_s fcxp_wqe; /* wait qelem for fcxp */
+ struct bfa_fcxp_s *fcxp; /* FCXP in use */
+ struct bfa_itnim_stats_s stats; /* itn statistics */
+};
+#define bfa_fcs_fcxp_alloc(__fcs) \
+ bfa_fcxp_alloc(NULL, (__fcs)->bfa, 0, 0, NULL, NULL, NULL, NULL)
+
+#define bfa_fcs_fcxp_alloc_wait(__bfa, __wqe, __alloc_cbfn, __alloc_cbarg) \
+ bfa_fcxp_alloc_wait(__bfa, __wqe, __alloc_cbfn, __alloc_cbarg, \
+ NULL, 0, 0, NULL, NULL, NULL, NULL)
+
+static inline struct bfad_port_s *
+bfa_fcs_itnim_get_drvport(struct bfa_fcs_itnim_s *itnim)
+{
+ return itnim->rport->port->bfad_port;
+}
+
+
+static inline struct bfa_fcs_lport_s *
+bfa_fcs_itnim_get_port(struct bfa_fcs_itnim_s *itnim)
+{
+ return itnim->rport->port;
+}
+
+
+static inline wwn_t
+bfa_fcs_itnim_get_nwwn(struct bfa_fcs_itnim_s *itnim)
+{
+ return itnim->rport->nwwn;
+}
+
+
+static inline wwn_t
+bfa_fcs_itnim_get_pwwn(struct bfa_fcs_itnim_s *itnim)
+{
+ return itnim->rport->pwwn;
+}
+
+
+static inline u32
+bfa_fcs_itnim_get_fcid(struct bfa_fcs_itnim_s *itnim)
+{
+ return itnim->rport->pid;
+}
+
+
+static inline u32
+bfa_fcs_itnim_get_maxfrsize(struct bfa_fcs_itnim_s *itnim)
+{
+ return itnim->rport->maxfrsize;
+}
+
+
+static inline enum fc_cos
+bfa_fcs_itnim_get_cos(struct bfa_fcs_itnim_s *itnim)
+{
+ return itnim->rport->fc_cos;
+}
+
+
+static inline struct bfad_itnim_s *
+bfa_fcs_itnim_get_drvitn(struct bfa_fcs_itnim_s *itnim)
+{
+ return itnim->itnim_drv;
+}
+
+
+static inline struct bfa_itnim_s *
+bfa_fcs_itnim_get_halitn(struct bfa_fcs_itnim_s *itnim)
+{
+ return itnim->bfa_itnim;
+}
+
+/**
+ * bfa fcs FCP Initiator mode API functions
+ */
+void bfa_fcs_itnim_get_attr(struct bfa_fcs_itnim_s *itnim,
+ struct bfa_itnim_attr_s *attr);
+void bfa_fcs_itnim_get_stats(struct bfa_fcs_itnim_s *itnim,
+ struct bfa_itnim_stats_s *stats);
+struct bfa_fcs_itnim_s *bfa_fcs_itnim_lookup(struct bfa_fcs_lport_s *port,
+ wwn_t rpwwn);
+bfa_status_t bfa_fcs_itnim_attr_get(struct bfa_fcs_lport_s *port, wwn_t rpwwn,
+ struct bfa_itnim_attr_s *attr);
+bfa_status_t bfa_fcs_itnim_stats_get(struct bfa_fcs_lport_s *port, wwn_t rpwwn,
+ struct bfa_itnim_stats_s *stats);
+bfa_status_t bfa_fcs_itnim_stats_clear(struct bfa_fcs_lport_s *port,
+ wwn_t rpwwn);
+struct bfa_fcs_itnim_s *bfa_fcs_itnim_create(struct bfa_fcs_rport_s *rport);
+void bfa_fcs_itnim_delete(struct bfa_fcs_itnim_s *itnim);
+void bfa_fcs_itnim_rport_offline(struct bfa_fcs_itnim_s *itnim);
+void bfa_fcs_itnim_rport_online(struct bfa_fcs_itnim_s *itnim);
+bfa_status_t bfa_fcs_itnim_get_online_state(struct bfa_fcs_itnim_s *itnim);
+void bfa_fcs_itnim_is_initiator(struct bfa_fcs_itnim_s *itnim);
+void bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s *itnim,
+ struct fchs_s *fchs, u16 len);
+
+#define BFA_FCS_FDMI_SUPORTED_SPEEDS (FDMI_TRANS_SPEED_1G | \
+ FDMI_TRANS_SPEED_2G | \
+ FDMI_TRANS_SPEED_4G | \
+ FDMI_TRANS_SPEED_8G)
+
+/*
+ * HBA Attribute Block : BFA internal representation. Note : Some variable
+ * sizes have been trimmed to suit BFA For Ex : Model will be "Brocade". Based
+ * on this the size has been reduced to 16 bytes from the standard's 64 bytes.
+ */
+struct bfa_fcs_fdmi_hba_attr_s {
+ wwn_t node_name;
+ u8 manufacturer[64];
+ u8 serial_num[64];
+ u8 model[16];
+ u8 model_desc[256];
+ u8 hw_version[8];
+ u8 driver_version[8];
+ u8 option_rom_ver[BFA_VERSION_LEN];
+ u8 fw_version[8];
+ u8 os_name[256];
+ u32 max_ct_pyld;
+};
+
+/*
+ * Port Attribute Block
+ */
+struct bfa_fcs_fdmi_port_attr_s {
+ u8 supp_fc4_types[32]; /* supported FC4 types */
+ u32 supp_speed; /* supported speed */
+ u32 curr_speed; /* current Speed */
+ u32 max_frm_size; /* max frame size */
+ u8 os_device_name[256]; /* OS device Name */
+ u8 host_name[256]; /* host name */
+};
+
+struct bfa_fcs_stats_s {
+ struct {
+ u32 untagged; /* untagged receive frames */
+ u32 tagged; /* tagged receive frames */
+ u32 vfid_unknown; /* VF id is unknown */
+ } uf;
+};
+
+struct bfa_fcs_driver_info_s {
+ u8 version[BFA_VERSION_LEN]; /* Driver Version */
+ u8 host_machine_name[BFA_FCS_OS_STR_LEN];
+ u8 host_os_name[BFA_FCS_OS_STR_LEN]; /* OS name and version */
+ u8 host_os_patch[BFA_FCS_OS_STR_LEN]; /* patch or service pack */
+ u8 os_device_name[BFA_FCS_OS_STR_LEN]; /* Driver Device Name */
+};
+
+struct bfa_fcs_s {
+ struct bfa_s *bfa; /* corresponding BFA bfa instance */
+ struct bfad_s *bfad; /* corresponding BDA driver instance */
+ struct bfa_trc_mod_s *trcmod; /* tracing module */
+ bfa_boolean_t vf_enabled; /* VF mode is enabled */
+ bfa_boolean_t fdmi_enabled; /* FDMI is enabled */
+ bfa_boolean_t min_cfg; /* min cfg enabled/disabled */
+ u16 port_vfid; /* port default VF ID */
+ struct bfa_fcs_driver_info_s driver_info;
+ struct bfa_fcs_fabric_s fabric; /* base fabric state machine */
+ struct bfa_fcs_stats_s stats; /* FCS statistics */
+ struct bfa_wc_s wc; /* waiting counter */
+};
+
+/*
+ * bfa fcs API functions
+ */
+void bfa_fcs_attach(struct bfa_fcs_s *fcs, struct bfa_s *bfa,
+ struct bfad_s *bfad,
+ bfa_boolean_t min_cfg);
+void bfa_fcs_init(struct bfa_fcs_s *fcs);
+void bfa_fcs_driver_info_init(struct bfa_fcs_s *fcs,
+ struct bfa_fcs_driver_info_s *driver_info);
+void bfa_fcs_set_fdmi_param(struct bfa_fcs_s *fcs, bfa_boolean_t fdmi_enable);
+void bfa_fcs_exit(struct bfa_fcs_s *fcs);
+void bfa_fcs_trc_init(struct bfa_fcs_s *fcs, struct bfa_trc_mod_s *trcmod);
+void bfa_fcs_start(struct bfa_fcs_s *fcs);
+
+/**
+ * bfa fcs vf public functions
+ */
+bfa_status_t bfa_fcs_vf_mode_enable(struct bfa_fcs_s *fcs, u16 vf_id);
+bfa_status_t bfa_fcs_vf_mode_disable(struct bfa_fcs_s *fcs);
+bfa_status_t bfa_fcs_vf_create(bfa_fcs_vf_t *vf, struct bfa_fcs_s *fcs,
+ u16 vf_id, struct bfa_lport_cfg_s *port_cfg,
+ struct bfad_vf_s *vf_drv);
+bfa_status_t bfa_fcs_vf_delete(bfa_fcs_vf_t *vf);
+void bfa_fcs_vf_list(struct bfa_fcs_s *fcs, u16 *vf_ids, int *nvfs);
+void bfa_fcs_vf_list_all(struct bfa_fcs_s *fcs, u16 *vf_ids, int *nvfs);
+void bfa_fcs_vf_get_attr(bfa_fcs_vf_t *vf, struct bfa_vf_attr_s *vf_attr);
+void bfa_fcs_vf_get_stats(bfa_fcs_vf_t *vf,
+ struct bfa_vf_stats_s *vf_stats);
+void bfa_fcs_vf_clear_stats(bfa_fcs_vf_t *vf);
+void bfa_fcs_vf_get_ports(bfa_fcs_vf_t *vf, wwn_t vpwwn[], int *nports);
+bfa_fcs_vf_t *bfa_fcs_vf_lookup(struct bfa_fcs_s *fcs, u16 vf_id);
+u16 bfa_fcs_fabric_vport_count(struct bfa_fcs_fabric_s *fabric);
+
+/*
+ * fabric protected interface functions
+ */
+void bfa_fcs_fabric_attach(struct bfa_fcs_s *fcs);
+void bfa_fcs_fabric_modinit(struct bfa_fcs_s *fcs);
+void bfa_fcs_fabric_modexit(struct bfa_fcs_s *fcs);
+void bfa_fcs_fabric_modsusp(struct bfa_fcs_s *fcs);
+void bfa_fcs_fabric_link_up(struct bfa_fcs_fabric_s *fabric);
+void bfa_fcs_fabric_link_down(struct bfa_fcs_fabric_s *fabric);
+void bfa_fcs_fabric_addvport(struct bfa_fcs_fabric_s *fabric,
+ struct bfa_fcs_vport_s *vport);
+void bfa_fcs_fabric_delvport(struct bfa_fcs_fabric_s *fabric,
+ struct bfa_fcs_vport_s *vport);
+int bfa_fcs_fabric_is_online(struct bfa_fcs_fabric_s *fabric);
+struct bfa_fcs_vport_s *bfa_fcs_fabric_vport_lookup(
+ struct bfa_fcs_fabric_s *fabric, wwn_t pwwn);
+void bfa_fcs_fabric_modstart(struct bfa_fcs_s *fcs);
+void bfa_fcs_fabric_uf_recv(struct bfa_fcs_fabric_s *fabric,
+ struct fchs_s *fchs, u16 len);
+bfa_boolean_t bfa_fcs_fabric_is_loopback(struct bfa_fcs_fabric_s *fabric);
+bfa_boolean_t bfa_fcs_fabric_is_auth_failed(struct bfa_fcs_fabric_s *fabric);
+enum bfa_port_type bfa_fcs_fabric_port_type(struct bfa_fcs_fabric_s *fabric);
+void bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s *fabric);
+void bfa_fcs_fabric_port_delete_comp(struct bfa_fcs_fabric_s *fabric);
+bfa_status_t bfa_fcs_fabric_addvf(struct bfa_fcs_fabric_s *vf,
+ struct bfa_fcs_s *fcs, struct bfa_lport_cfg_s *port_cfg,
+ struct bfad_vf_s *vf_drv);
+void bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric,
+ wwn_t fabric_name);
+u16 bfa_fcs_fabric_get_switch_oui(struct bfa_fcs_fabric_s *fabric);
+void bfa_fcs_uf_attach(struct bfa_fcs_s *fcs);
+void bfa_fcs_port_attach(struct bfa_fcs_s *fcs);
+
+/**
+ * BFA FCS callback interfaces
+ */
+
+/**
+ * fcb Main fcs callbacks
+ */
+
+struct bfad_port_s;
+struct bfad_vf_s;
+struct bfad_vport_s;
+struct bfad_rport_s;
+
+/**
+ * lport callbacks
+ */
+struct bfad_port_s *bfa_fcb_lport_new(struct bfad_s *bfad,
+ struct bfa_fcs_lport_s *port,
+ enum bfa_lport_role roles,
+ struct bfad_vf_s *vf_drv,
+ struct bfad_vport_s *vp_drv);
+void bfa_fcb_lport_delete(struct bfad_s *bfad, enum bfa_lport_role roles,
+ struct bfad_vf_s *vf_drv,
+ struct bfad_vport_s *vp_drv);
+
+/**
+ * vport callbacks
+ */
+void bfa_fcb_pbc_vport_create(struct bfad_s *bfad, struct bfi_pbc_vport_s);
+
+/**
+ * rport callbacks
+ */
+bfa_status_t bfa_fcb_rport_alloc(struct bfad_s *bfad,
+ struct bfa_fcs_rport_s **rport,
+ struct bfad_rport_s **rport_drv);
+
+/**
+ * itnim callbacks
+ */
+void bfa_fcb_itnim_alloc(struct bfad_s *bfad, struct bfa_fcs_itnim_s **itnim,
+ struct bfad_itnim_s **itnim_drv);
+void bfa_fcb_itnim_free(struct bfad_s *bfad,
+ struct bfad_itnim_s *itnim_drv);
+void bfa_fcb_itnim_online(struct bfad_itnim_s *itnim_drv);
+void bfa_fcb_itnim_offline(struct bfad_itnim_s *itnim_drv);
+
+#endif /* __BFA_FCS_H__ */
diff --git a/drivers/scsi/bfa/fcpim.c b/drivers/scsi/bfa/bfa_fcs_fcpim.c
index 6b8976ad22fa..569dfefab70d 100644
--- a/drivers/scsi/bfa/fcpim.c
+++ b/drivers/scsi/bfa/bfa_fcs_fcpim.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
* All rights reserved
* www.brocade.com
*
@@ -19,36 +19,24 @@
* fcpim.c - FCP initiator mode i-t nexus state machine
*/
-#include <bfa.h>
-#include <bfa_svc.h>
-#include "fcs_fcpim.h"
-#include "fcs_rport.h"
-#include "fcs_lport.h"
-#include "fcs_trcmod.h"
-#include "fcs_fcxp.h"
-#include "fcs.h"
-#include <fcs/bfa_fcs_fcpim.h>
-#include <fcb/bfa_fcb_fcpim.h>
-#include <aen/bfa_aen_itnim.h>
+#include "bfa_fcs.h"
+#include "bfa_fcbuild.h"
+#include "bfad_drv.h"
+#include "bfad_im.h"
BFA_TRC_FILE(FCS, FCPIM);
/*
* forward declarations
*/
-static void bfa_fcs_itnim_timeout(void *arg);
-static void bfa_fcs_itnim_free(struct bfa_fcs_itnim_s *itnim);
-static void bfa_fcs_itnim_send_prli(void *itnim_cbarg,
+static void bfa_fcs_itnim_timeout(void *arg);
+static void bfa_fcs_itnim_free(struct bfa_fcs_itnim_s *itnim);
+static void bfa_fcs_itnim_send_prli(void *itnim_cbarg,
struct bfa_fcxp_s *fcxp_alloced);
-static void bfa_fcs_itnim_prli_response(void *fcsarg,
- struct bfa_fcxp_s *fcxp,
- void *cbarg,
- bfa_status_t req_status,
- u32 rsp_len,
- u32 resid_len,
- struct fchs_s *rsp_fchs);
-static void bfa_fcs_itnim_aen_post(struct bfa_fcs_itnim_s *itnim,
- enum bfa_itnim_aen_event event);
+static void bfa_fcs_itnim_prli_response(void *fcsarg,
+ struct bfa_fcxp_s *fcxp, void *cbarg,
+ bfa_status_t req_status, u32 rsp_len,
+ u32 resid_len, struct fchs_s *rsp_fchs);
/**
* fcs_itnim_sm FCS itnim state machine events
@@ -61,28 +49,28 @@ enum bfa_fcs_itnim_event {
BFA_FCS_ITNIM_SM_RSP_OK = 4, /* good response */
BFA_FCS_ITNIM_SM_RSP_ERROR = 5, /* error response */
BFA_FCS_ITNIM_SM_TIMEOUT = 6, /* delay timeout */
- BFA_FCS_ITNIM_SM_HCB_OFFLINE = 7, /* BFA online callback */
- BFA_FCS_ITNIM_SM_HCB_ONLINE = 8, /* BFA offline callback */
+ BFA_FCS_ITNIM_SM_HCB_OFFLINE = 7, /* BFA online callback */
+ BFA_FCS_ITNIM_SM_HCB_ONLINE = 8, /* BFA offline callback */
BFA_FCS_ITNIM_SM_INITIATOR = 9, /* rport is initiator */
BFA_FCS_ITNIM_SM_DELETE = 10, /* delete event from rport */
BFA_FCS_ITNIM_SM_PRLO = 11, /* delete event from rport */
};
-static void bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s *itnim,
+static void bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s *itnim,
enum bfa_fcs_itnim_event event);
-static void bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s *itnim,
+static void bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s *itnim,
enum bfa_fcs_itnim_event event);
-static void bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim,
+static void bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim,
enum bfa_fcs_itnim_event event);
-static void bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s *itnim,
+static void bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s *itnim,
enum bfa_fcs_itnim_event event);
-static void bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s *itnim,
+static void bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s *itnim,
enum bfa_fcs_itnim_event event);
-static void bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s *itnim,
+static void bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s *itnim,
enum bfa_fcs_itnim_event event);
-static void bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s *itnim,
+static void bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s *itnim,
enum bfa_fcs_itnim_event event);
-static void bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s *itnim,
+static void bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s *itnim,
enum bfa_fcs_itnim_event event);
static struct bfa_sm_table_s itnim_sm_table[] = {
@@ -102,7 +90,7 @@ static struct bfa_sm_table_s itnim_sm_table[] = {
static void
bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s *itnim,
- enum bfa_fcs_itnim_event event)
+ enum bfa_fcs_itnim_event event)
{
bfa_trc(itnim->fcs, itnim->rport->pwwn);
bfa_trc(itnim->fcs, event);
@@ -134,7 +122,7 @@ bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s *itnim,
static void
bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s *itnim,
- enum bfa_fcs_itnim_event event)
+ enum bfa_fcs_itnim_event event)
{
bfa_trc(itnim->fcs, itnim->rport->pwwn);
bfa_trc(itnim->fcs, event);
@@ -168,7 +156,7 @@ bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s *itnim,
static void
bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim,
- enum bfa_fcs_itnim_event event)
+ enum bfa_fcs_itnim_event event)
{
bfa_trc(itnim->fcs, itnim->rport->pwwn);
bfa_trc(itnim->fcs, event);
@@ -233,6 +221,7 @@ bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s *itnim,
}
break;
+
case BFA_FCS_ITNIM_SM_OFFLINE:
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
bfa_timer_stop(&itnim->timer);
@@ -259,6 +248,10 @@ static void
bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s *itnim,
enum bfa_fcs_itnim_event event)
{
+ struct bfad_s *bfad = (struct bfad_s *)itnim->fcs->bfad;
+ char lpwwn_buf[BFA_STRING_32];
+ char rpwwn_buf[BFA_STRING_32];
+
bfa_trc(itnim->fcs, itnim->rport->pwwn);
bfa_trc(itnim->fcs, event);
@@ -266,7 +259,11 @@ bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s *itnim,
case BFA_FCS_ITNIM_SM_HCB_ONLINE:
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_online);
bfa_fcb_itnim_online(itnim->itnim_drv);
- bfa_fcs_itnim_aen_post(itnim, BFA_ITNIM_AEN_ONLINE);
+ wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(itnim->rport->port));
+ wwn2str(rpwwn_buf, itnim->rport->pwwn);
+ BFA_LOG(KERN_INFO, bfad, log_level,
+ "Target (WWN = %s) is online for initiator (WWN = %s)\n",
+ rpwwn_buf, lpwwn_buf);
break;
case BFA_FCS_ITNIM_SM_OFFLINE:
@@ -287,8 +284,12 @@ bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s *itnim,
static void
bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s *itnim,
- enum bfa_fcs_itnim_event event)
+ enum bfa_fcs_itnim_event event)
{
+ struct bfad_s *bfad = (struct bfad_s *)itnim->fcs->bfad;
+ char lpwwn_buf[BFA_STRING_32];
+ char rpwwn_buf[BFA_STRING_32];
+
bfa_trc(itnim->fcs, itnim->rport->pwwn);
bfa_trc(itnim->fcs, event);
@@ -297,10 +298,16 @@ bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s *itnim,
bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_hcb_offline);
bfa_fcb_itnim_offline(itnim->itnim_drv);
bfa_itnim_offline(itnim->bfa_itnim);
- if (bfa_fcs_port_is_online(itnim->rport->port) == BFA_TRUE)
- bfa_fcs_itnim_aen_post(itnim, BFA_ITNIM_AEN_DISCONNECT);
+ wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(itnim->rport->port));
+ wwn2str(rpwwn_buf, itnim->rport->pwwn);
+ if (bfa_fcs_lport_is_online(itnim->rport->port) == BFA_TRUE)
+ BFA_LOG(KERN_ERR, bfad, log_level,
+ "Target (WWN = %s) connectivity lost for "
+ "initiator (WWN = %s)\n", rpwwn_buf, lpwwn_buf);
else
- bfa_fcs_itnim_aen_post(itnim, BFA_ITNIM_AEN_OFFLINE);
+ BFA_LOG(KERN_INFO, bfad, log_level,
+ "Target (WWN = %s) offlined by initiator (WWN = %s)\n",
+ rpwwn_buf, lpwwn_buf);
break;
case BFA_FCS_ITNIM_SM_DELETE:
@@ -343,7 +350,7 @@ bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s *itnim,
*/
static void
bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s *itnim,
- enum bfa_fcs_itnim_event event)
+ enum bfa_fcs_itnim_event event)
{
bfa_trc(itnim->fcs, itnim->rport->pwwn);
bfa_trc(itnim->fcs, event);
@@ -369,71 +376,34 @@ bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s *itnim,
}
}
-
-
-/**
- * itnim_private FCS ITNIM private interfaces
- */
-
-static void
-bfa_fcs_itnim_aen_post(struct bfa_fcs_itnim_s *itnim,
- enum bfa_itnim_aen_event event)
-{
- struct bfa_fcs_rport_s *rport = itnim->rport;
- union bfa_aen_data_u aen_data;
- struct bfa_log_mod_s *logmod = rport->fcs->logm;
- wwn_t lpwwn = bfa_fcs_port_get_pwwn(rport->port);
- wwn_t rpwwn = rport->pwwn;
- char lpwwn_ptr[BFA_STRING_32];
- char rpwwn_ptr[BFA_STRING_32];
-
- /*
- * Don't post events for well known addresses
- */
- if (BFA_FCS_PID_IS_WKA(rport->pid))
- return;
-
- wwn2str(lpwwn_ptr, lpwwn);
- wwn2str(rpwwn_ptr, rpwwn);
-
- bfa_log(logmod, BFA_LOG_CREATE_ID(BFA_AEN_CAT_ITNIM, event),
- rpwwn_ptr, lpwwn_ptr);
-
- aen_data.itnim.vf_id = rport->port->fabric->vf_id;
- aen_data.itnim.ppwwn =
- bfa_fcs_port_get_pwwn(bfa_fcs_get_base_port(itnim->fcs));
- aen_data.itnim.lpwwn = lpwwn;
- aen_data.itnim.rpwwn = rpwwn;
-}
-
static void
bfa_fcs_itnim_send_prli(void *itnim_cbarg, struct bfa_fcxp_s *fcxp_alloced)
{
struct bfa_fcs_itnim_s *itnim = itnim_cbarg;
struct bfa_fcs_rport_s *rport = itnim->rport;
- struct bfa_fcs_port_s *port = rport->port;
- struct fchs_s fchs;
+ struct bfa_fcs_lport_s *port = rport->port;
+ struct fchs_s fchs;
struct bfa_fcxp_s *fcxp;
- int len;
+ int len;
bfa_trc(itnim->fcs, itnim->rport->pwwn);
fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
if (!fcxp) {
itnim->stats.fcxp_alloc_wait++;
- bfa_fcxp_alloc_wait(port->fcs->bfa, &itnim->fcxp_wqe,
+ bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &itnim->fcxp_wqe,
bfa_fcs_itnim_send_prli, itnim);
return;
}
itnim->fcxp = fcxp;
- len = fc_prli_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), itnim->rport->pid,
- bfa_fcs_port_get_fcid(port), 0);
+ len = fc_prli_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+ itnim->rport->pid, bfa_fcs_lport_get_fcid(port), 0);
bfa_fcxp_send(fcxp, rport->bfa_rport, port->fabric->vf_id, port->lp_tag,
BFA_FALSE, FC_CLASS_3, len, &fchs,
- bfa_fcs_itnim_prli_response, (void *)itnim, FC_MAX_PDUSZ,
- FC_ELS_TOV);
+ bfa_fcs_itnim_prli_response, (void *)itnim,
+ FC_MAX_PDUSZ, FC_ELS_TOV);
itnim->stats.prli_sent++;
bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_FRMSENT);
@@ -444,10 +414,10 @@ bfa_fcs_itnim_prli_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
bfa_status_t req_status, u32 rsp_len,
u32 resid_len, struct fchs_s *rsp_fchs)
{
- struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)cbarg;
- struct fc_els_cmd_s *els_cmd;
- struct fc_prli_s *prli_resp;
- struct fc_ls_rjt_s *ls_rjt;
+ struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cbarg;
+ struct fc_els_cmd_s *els_cmd;
+ struct fc_prli_s *prli_resp;
+ struct fc_ls_rjt_s *ls_rjt;
struct fc_prli_params_s *sparams;
bfa_trc(itnim->fcs, req_status);
@@ -475,7 +445,7 @@ bfa_fcs_itnim_prli_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
if (prli_resp->parampage.servparams.initiator) {
bfa_trc(itnim->fcs, prli_resp->parampage.type);
itnim->rport->scsi_function =
- BFA_RPORT_INITIATOR;
+ BFA_RPORT_INITIATOR;
itnim->stats.prli_rsp_acc++;
bfa_sm_send_event(itnim,
BFA_FCS_ITNIM_SM_RSP_OK);
@@ -488,10 +458,10 @@ bfa_fcs_itnim_prli_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
itnim->rport->scsi_function = BFA_RPORT_TARGET;
sparams = &prli_resp->parampage.servparams;
- itnim->seq_rec = sparams->retry;
- itnim->rec_support = sparams->rec_support;
+ itnim->seq_rec = sparams->retry;
+ itnim->rec_support = sparams->rec_support;
itnim->task_retry_id = sparams->task_retry_id;
- itnim->conf_comp = sparams->confirm;
+ itnim->conf_comp = sparams->confirm;
itnim->stats.prli_rsp_acc++;
bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_OK);
@@ -509,7 +479,7 @@ bfa_fcs_itnim_prli_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
static void
bfa_fcs_itnim_timeout(void *arg)
{
- struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)arg;
+ struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) arg;
itnim->stats.timeout++;
bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_TIMEOUT);
@@ -529,16 +499,16 @@ bfa_fcs_itnim_free(struct bfa_fcs_itnim_s *itnim)
*/
/**
- * Called by rport when a new rport is created.
+ * Called by rport when a new rport is created.
*
* @param[in] rport - remote port.
*/
struct bfa_fcs_itnim_s *
bfa_fcs_itnim_create(struct bfa_fcs_rport_s *rport)
{
- struct bfa_fcs_port_s *port = rport->port;
+ struct bfa_fcs_lport_s *port = rport->port;
struct bfa_fcs_itnim_s *itnim;
- struct bfad_itnim_s *itnim_drv;
+ struct bfad_itnim_s *itnim_drv;
struct bfa_itnim_s *bfa_itnim;
/*
@@ -560,7 +530,8 @@ bfa_fcs_itnim_create(struct bfa_fcs_rport_s *rport)
/*
* call BFA to create the itnim
*/
- bfa_itnim = bfa_itnim_create(port->fcs->bfa, rport->bfa_rport, itnim);
+ bfa_itnim =
+ bfa_itnim_create(port->fcs->bfa, rport->bfa_rport, itnim);
if (bfa_itnim == NULL) {
bfa_trc(port->fcs, rport->pwwn);
@@ -569,10 +540,10 @@ bfa_fcs_itnim_create(struct bfa_fcs_rport_s *rport)
return NULL;
}
- itnim->bfa_itnim = bfa_itnim;
- itnim->seq_rec = BFA_FALSE;
- itnim->rec_support = BFA_FALSE;
- itnim->conf_comp = BFA_FALSE;
+ itnim->bfa_itnim = bfa_itnim;
+ itnim->seq_rec = BFA_FALSE;
+ itnim->rec_support = BFA_FALSE;
+ itnim->conf_comp = BFA_FALSE;
itnim->task_retry_id = BFA_FALSE;
/*
@@ -584,7 +555,7 @@ bfa_fcs_itnim_create(struct bfa_fcs_rport_s *rport)
}
/**
- * Called by rport to delete the instance of FCPIM.
+ * Called by rport to delete the instance of FCPIM.
*
* @param[in] rport - remote port.
*/
@@ -607,8 +578,8 @@ bfa_fcs_itnim_rport_online(struct bfa_fcs_itnim_s *itnim)
bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_ONLINE);
} else {
/*
- * For well known addresses, we set the itnim to initiator
- * state
+ * For well known addresses, we set the itnim to initiator
+ * state
*/
itnim->stats.initiator++;
bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_INITIATOR);
@@ -651,7 +622,6 @@ bfa_fcs_itnim_get_online_state(struct bfa_fcs_itnim_s *itnim)
default:
return BFA_STATUS_NO_FCPIM_NEXUS;
-
}
}
@@ -661,7 +631,7 @@ bfa_fcs_itnim_get_online_state(struct bfa_fcs_itnim_s *itnim)
void
bfa_cb_itnim_online(void *cbarg)
{
- struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)cbarg;
+ struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cbarg;
bfa_trc(itnim->fcs, itnim->rport->pwwn);
bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_HCB_ONLINE);
@@ -673,7 +643,7 @@ bfa_cb_itnim_online(void *cbarg)
void
bfa_cb_itnim_offline(void *cb_arg)
{
- struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)cb_arg;
+ struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cb_arg;
bfa_trc(itnim->fcs, itnim->rport->pwwn);
bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_HCB_OFFLINE);
@@ -686,7 +656,7 @@ bfa_cb_itnim_offline(void *cb_arg)
void
bfa_cb_itnim_tov_begin(void *cb_arg)
{
- struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)cb_arg;
+ struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cb_arg;
bfa_trc(itnim->fcs, itnim->rport->pwwn);
}
@@ -697,14 +667,15 @@ bfa_cb_itnim_tov_begin(void *cb_arg)
void
bfa_cb_itnim_tov(void *cb_arg)
{
- struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)cb_arg;
+ struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cb_arg;
+ struct bfad_itnim_s *itnim_drv = itnim->itnim_drv;
bfa_trc(itnim->fcs, itnim->rport->pwwn);
- bfa_fcb_itnim_tov(itnim->itnim_drv);
+ itnim_drv->state = ITNIM_STATE_TIMEOUT;
}
/**
- * BFA notification to FCS/driver for second level error recovery.
+ * BFA notification to FCS/driver for second level error recovery.
*
* Atleast one I/O request has timedout and target is unresponsive to
* repeated abort requests. Second level error recovery should be initiated
@@ -713,7 +684,7 @@ bfa_cb_itnim_tov(void *cb_arg)
void
bfa_cb_itnim_sler(void *cb_arg)
{
- struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)cb_arg;
+ struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cb_arg;
itnim->stats.sler++;
bfa_trc(itnim->fcs, itnim->rport->pwwn);
@@ -721,7 +692,7 @@ bfa_cb_itnim_sler(void *cb_arg)
}
struct bfa_fcs_itnim_s *
-bfa_fcs_itnim_lookup(struct bfa_fcs_port_s *port, wwn_t rpwwn)
+bfa_fcs_itnim_lookup(struct bfa_fcs_lport_s *port, wwn_t rpwwn)
{
struct bfa_fcs_rport_s *rport;
rport = bfa_fcs_rport_lookup(port, rpwwn);
@@ -734,7 +705,7 @@ bfa_fcs_itnim_lookup(struct bfa_fcs_port_s *port, wwn_t rpwwn)
}
bfa_status_t
-bfa_fcs_itnim_attr_get(struct bfa_fcs_port_s *port, wwn_t rpwwn,
+bfa_fcs_itnim_attr_get(struct bfa_fcs_lport_s *port, wwn_t rpwwn,
struct bfa_itnim_attr_s *attr)
{
struct bfa_fcs_itnim_s *itnim = NULL;
@@ -744,18 +715,16 @@ bfa_fcs_itnim_attr_get(struct bfa_fcs_port_s *port, wwn_t rpwwn,
if (itnim == NULL)
return BFA_STATUS_NO_FCPIM_NEXUS;
- attr->state = bfa_sm_to_state(itnim_sm_table, itnim->sm);
- attr->retry = itnim->seq_rec;
- attr->rec_support = itnim->rec_support;
- attr->conf_comp = itnim->conf_comp;
+ attr->state = bfa_sm_to_state(itnim_sm_table, itnim->sm);
+ attr->retry = itnim->seq_rec;
+ attr->rec_support = itnim->rec_support;
+ attr->conf_comp = itnim->conf_comp;
attr->task_retry_id = itnim->task_retry_id;
- bfa_os_memset(&attr->io_latency, 0, sizeof(struct bfa_itnim_latency_s));
-
return BFA_STATUS_OK;
}
bfa_status_t
-bfa_fcs_itnim_stats_get(struct bfa_fcs_port_s *port, wwn_t rpwwn,
+bfa_fcs_itnim_stats_get(struct bfa_fcs_lport_s *port, wwn_t rpwwn,
struct bfa_itnim_stats_s *stats)
{
struct bfa_fcs_itnim_s *itnim = NULL;
@@ -773,7 +742,7 @@ bfa_fcs_itnim_stats_get(struct bfa_fcs_port_s *port, wwn_t rpwwn,
}
bfa_status_t
-bfa_fcs_itnim_stats_clear(struct bfa_fcs_port_s *port, wwn_t rpwwn)
+bfa_fcs_itnim_stats_clear(struct bfa_fcs_lport_s *port, wwn_t rpwwn)
{
struct bfa_fcs_itnim_s *itnim = NULL;
@@ -789,10 +758,10 @@ bfa_fcs_itnim_stats_clear(struct bfa_fcs_port_s *port, wwn_t rpwwn)
}
void
-bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s *itnim, struct fchs_s *fchs,
- u16 len)
+bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s *itnim,
+ struct fchs_s *fchs, u16 len)
{
- struct fc_els_cmd_s *els_cmd;
+ struct fc_els_cmd_s *els_cmd;
bfa_trc(itnim->fcs, fchs->type);
@@ -812,13 +781,3 @@ bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s *itnim, struct fchs_s *fchs,
bfa_assert(0);
}
}
-
-void
-bfa_fcs_itnim_pause(struct bfa_fcs_itnim_s *itnim)
-{
-}
-
-void
-bfa_fcs_itnim_resume(struct bfa_fcs_itnim_s *itnim)
-{
-}
diff --git a/drivers/scsi/bfa/bfa_fcs_lport.c b/drivers/scsi/bfa/bfa_fcs_lport.c
index 35df20e68a52..b522bf30247a 100644
--- a/drivers/scsi/bfa/bfa_fcs_lport.c
+++ b/drivers/scsi/bfa/bfa_fcs_lport.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
* All rights reserved
* www.brocade.com
*
@@ -16,23 +16,13 @@
*/
/**
- * bfa_fcs_port.c BFA FCS port
+ * bfa_fcs_lport.c BFA FCS port
*/
-#include <fcs/bfa_fcs.h>
-#include <fcs/bfa_fcs_lport.h>
-#include <fcs/bfa_fcs_rport.h>
-#include <fcb/bfa_fcb_port.h>
-#include <bfa_svc.h>
-#include <log/bfa_log_fcs.h>
-#include "fcs.h"
-#include "fcs_lport.h"
-#include "fcs_vport.h"
-#include "fcs_rport.h"
-#include "fcs_fcxp.h"
-#include "fcs_trcmod.h"
-#include "lport_priv.h"
-#include <aen/bfa_aen_lport.h>
+#include "bfa_fcs.h"
+#include "bfa_fcbuild.h"
+#include "bfa_fc.h"
+#include "bfad_drv.h"
BFA_TRC_FILE(FCS, PORT);
@@ -40,49 +30,53 @@ BFA_TRC_FILE(FCS, PORT);
* Forward declarations
*/
-static void bfa_fcs_port_aen_post(struct bfa_fcs_port_s *port,
- enum bfa_lport_aen_event event);
-static void bfa_fcs_port_send_ls_rjt(struct bfa_fcs_port_s *port,
- struct fchs_s *rx_fchs, u8 reason_code,
- u8 reason_code_expl);
-static void bfa_fcs_port_plogi(struct bfa_fcs_port_s *port,
- struct fchs_s *rx_fchs,
- struct fc_logi_s *plogi);
-static void bfa_fcs_port_online_actions(struct bfa_fcs_port_s *port);
-static void bfa_fcs_port_offline_actions(struct bfa_fcs_port_s *port);
-static void bfa_fcs_port_unknown_init(struct bfa_fcs_port_s *port);
-static void bfa_fcs_port_unknown_online(struct bfa_fcs_port_s *port);
-static void bfa_fcs_port_unknown_offline(struct bfa_fcs_port_s *port);
-static void bfa_fcs_port_deleted(struct bfa_fcs_port_s *port);
-static void bfa_fcs_port_echo(struct bfa_fcs_port_s *port,
+static void bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port,
+ struct fchs_s *rx_fchs, u8 reason_code,
+ u8 reason_code_expl);
+static void bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port,
+ struct fchs_s *rx_fchs, struct fc_logi_s *plogi);
+static void bfa_fcs_lport_online_actions(struct bfa_fcs_lport_s *port);
+static void bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port);
+static void bfa_fcs_lport_unknown_init(struct bfa_fcs_lport_s *port);
+static void bfa_fcs_lport_unknown_online(struct bfa_fcs_lport_s *port);
+static void bfa_fcs_lport_unknown_offline(struct bfa_fcs_lport_s *port);
+static void bfa_fcs_lport_deleted(struct bfa_fcs_lport_s *port);
+static void bfa_fcs_lport_echo(struct bfa_fcs_lport_s *port,
struct fchs_s *rx_fchs,
struct fc_echo_s *echo, u16 len);
-static void bfa_fcs_port_rnid(struct bfa_fcs_port_s *port,
+static void bfa_fcs_lport_rnid(struct bfa_fcs_lport_s *port,
struct fchs_s *rx_fchs,
struct fc_rnid_cmd_s *rnid, u16 len);
-static void bfa_fs_port_get_gen_topo_data(struct bfa_fcs_port_s *port,
+static void bfa_fs_port_get_gen_topo_data(struct bfa_fcs_lport_s *port,
struct fc_rnid_general_topology_data_s *gen_topo_data);
+static void bfa_fcs_lport_fab_init(struct bfa_fcs_lport_s *port);
+static void bfa_fcs_lport_fab_online(struct bfa_fcs_lport_s *port);
+static void bfa_fcs_lport_fab_offline(struct bfa_fcs_lport_s *port);
+
+static void bfa_fcs_lport_n2n_init(struct bfa_fcs_lport_s *port);
+static void bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port);
+static void bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s *port);
+
static struct {
- void (*init) (struct bfa_fcs_port_s *port);
- void (*online) (struct bfa_fcs_port_s *port);
- void (*offline) (struct bfa_fcs_port_s *port);
+ void (*init) (struct bfa_fcs_lport_s *port);
+ void (*online) (struct bfa_fcs_lport_s *port);
+ void (*offline) (struct bfa_fcs_lport_s *port);
} __port_action[] = {
{
- bfa_fcs_port_unknown_init, bfa_fcs_port_unknown_online,
- bfa_fcs_port_unknown_offline}, {
- bfa_fcs_port_fab_init, bfa_fcs_port_fab_online,
- bfa_fcs_port_fab_offline}, {
- bfa_fcs_port_loop_init, bfa_fcs_port_loop_online,
- bfa_fcs_port_loop_offline}, {
-bfa_fcs_port_n2n_init, bfa_fcs_port_n2n_online,
- bfa_fcs_port_n2n_offline},};
+ bfa_fcs_lport_unknown_init, bfa_fcs_lport_unknown_online,
+ bfa_fcs_lport_unknown_offline}, {
+ bfa_fcs_lport_fab_init, bfa_fcs_lport_fab_online,
+ bfa_fcs_lport_fab_offline}, {
+ bfa_fcs_lport_n2n_init, bfa_fcs_lport_n2n_online,
+ bfa_fcs_lport_n2n_offline},
+ };
/**
* fcs_port_sm FCS logical port state machine
*/
-enum bfa_fcs_port_event {
+enum bfa_fcs_lport_event {
BFA_FCS_PORT_SM_CREATE = 1,
BFA_FCS_PORT_SM_ONLINE = 2,
BFA_FCS_PORT_SM_OFFLINE = 3,
@@ -90,27 +84,28 @@ enum bfa_fcs_port_event {
BFA_FCS_PORT_SM_DELRPORT = 5,
};
-static void bfa_fcs_port_sm_uninit(struct bfa_fcs_port_s *port,
- enum bfa_fcs_port_event event);
-static void bfa_fcs_port_sm_init(struct bfa_fcs_port_s *port,
- enum bfa_fcs_port_event event);
-static void bfa_fcs_port_sm_online(struct bfa_fcs_port_s *port,
- enum bfa_fcs_port_event event);
-static void bfa_fcs_port_sm_offline(struct bfa_fcs_port_s *port,
- enum bfa_fcs_port_event event);
-static void bfa_fcs_port_sm_deleting(struct bfa_fcs_port_s *port,
- enum bfa_fcs_port_event event);
+static void bfa_fcs_lport_sm_uninit(struct bfa_fcs_lport_s *port,
+ enum bfa_fcs_lport_event event);
+static void bfa_fcs_lport_sm_init(struct bfa_fcs_lport_s *port,
+ enum bfa_fcs_lport_event event);
+static void bfa_fcs_lport_sm_online(struct bfa_fcs_lport_s *port,
+ enum bfa_fcs_lport_event event);
+static void bfa_fcs_lport_sm_offline(struct bfa_fcs_lport_s *port,
+ enum bfa_fcs_lport_event event);
+static void bfa_fcs_lport_sm_deleting(struct bfa_fcs_lport_s *port,
+ enum bfa_fcs_lport_event event);
static void
-bfa_fcs_port_sm_uninit(struct bfa_fcs_port_s *port,
- enum bfa_fcs_port_event event)
+bfa_fcs_lport_sm_uninit(
+ struct bfa_fcs_lport_s *port,
+ enum bfa_fcs_lport_event event)
{
bfa_trc(port->fcs, port->port_cfg.pwwn);
bfa_trc(port->fcs, event);
switch (event) {
case BFA_FCS_PORT_SM_CREATE:
- bfa_sm_set_state(port, bfa_fcs_port_sm_init);
+ bfa_sm_set_state(port, bfa_fcs_lport_sm_init);
break;
default:
@@ -119,20 +114,21 @@ bfa_fcs_port_sm_uninit(struct bfa_fcs_port_s *port,
}
static void
-bfa_fcs_port_sm_init(struct bfa_fcs_port_s *port, enum bfa_fcs_port_event event)
+bfa_fcs_lport_sm_init(struct bfa_fcs_lport_s *port,
+ enum bfa_fcs_lport_event event)
{
bfa_trc(port->fcs, port->port_cfg.pwwn);
bfa_trc(port->fcs, event);
switch (event) {
case BFA_FCS_PORT_SM_ONLINE:
- bfa_sm_set_state(port, bfa_fcs_port_sm_online);
- bfa_fcs_port_online_actions(port);
+ bfa_sm_set_state(port, bfa_fcs_lport_sm_online);
+ bfa_fcs_lport_online_actions(port);
break;
case BFA_FCS_PORT_SM_DELETE:
- bfa_sm_set_state(port, bfa_fcs_port_sm_uninit);
- bfa_fcs_port_deleted(port);
+ bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
+ bfa_fcs_lport_deleted(port);
break;
case BFA_FCS_PORT_SM_OFFLINE:
@@ -144,19 +140,20 @@ bfa_fcs_port_sm_init(struct bfa_fcs_port_s *port, enum bfa_fcs_port_event event)
}
static void
-bfa_fcs_port_sm_online(struct bfa_fcs_port_s *port,
- enum bfa_fcs_port_event event)
+bfa_fcs_lport_sm_online(
+ struct bfa_fcs_lport_s *port,
+ enum bfa_fcs_lport_event event)
{
struct bfa_fcs_rport_s *rport;
- struct list_head *qe, *qen;
+ struct list_head *qe, *qen;
bfa_trc(port->fcs, port->port_cfg.pwwn);
bfa_trc(port->fcs, event);
switch (event) {
case BFA_FCS_PORT_SM_OFFLINE:
- bfa_sm_set_state(port, bfa_fcs_port_sm_offline);
- bfa_fcs_port_offline_actions(port);
+ bfa_sm_set_state(port, bfa_fcs_lport_sm_offline);
+ bfa_fcs_lport_offline_actions(port);
break;
case BFA_FCS_PORT_SM_DELETE:
@@ -164,12 +161,12 @@ bfa_fcs_port_sm_online(struct bfa_fcs_port_s *port,
__port_action[port->fabric->fab_type].offline(port);
if (port->num_rports == 0) {
- bfa_sm_set_state(port, bfa_fcs_port_sm_uninit);
- bfa_fcs_port_deleted(port);
+ bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
+ bfa_fcs_lport_deleted(port);
} else {
- bfa_sm_set_state(port, bfa_fcs_port_sm_deleting);
+ bfa_sm_set_state(port, bfa_fcs_lport_sm_deleting);
list_for_each_safe(qe, qen, &port->rport_q) {
- rport = (struct bfa_fcs_rport_s *)qe;
+ rport = (struct bfa_fcs_rport_s *) qe;
bfa_fcs_rport_delete(rport);
}
}
@@ -184,29 +181,30 @@ bfa_fcs_port_sm_online(struct bfa_fcs_port_s *port,
}
static void
-bfa_fcs_port_sm_offline(struct bfa_fcs_port_s *port,
- enum bfa_fcs_port_event event)
+bfa_fcs_lport_sm_offline(
+ struct bfa_fcs_lport_s *port,
+ enum bfa_fcs_lport_event event)
{
struct bfa_fcs_rport_s *rport;
- struct list_head *qe, *qen;
+ struct list_head *qe, *qen;
bfa_trc(port->fcs, port->port_cfg.pwwn);
bfa_trc(port->fcs, event);
switch (event) {
case BFA_FCS_PORT_SM_ONLINE:
- bfa_sm_set_state(port, bfa_fcs_port_sm_online);
- bfa_fcs_port_online_actions(port);
+ bfa_sm_set_state(port, bfa_fcs_lport_sm_online);
+ bfa_fcs_lport_online_actions(port);
break;
case BFA_FCS_PORT_SM_DELETE:
if (port->num_rports == 0) {
- bfa_sm_set_state(port, bfa_fcs_port_sm_uninit);
- bfa_fcs_port_deleted(port);
+ bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
+ bfa_fcs_lport_deleted(port);
} else {
- bfa_sm_set_state(port, bfa_fcs_port_sm_deleting);
+ bfa_sm_set_state(port, bfa_fcs_lport_sm_deleting);
list_for_each_safe(qe, qen, &port->rport_q) {
- rport = (struct bfa_fcs_rport_s *)qe;
+ rport = (struct bfa_fcs_rport_s *) qe;
bfa_fcs_rport_delete(rport);
}
}
@@ -222,8 +220,9 @@ bfa_fcs_port_sm_offline(struct bfa_fcs_port_s *port,
}
static void
-bfa_fcs_port_sm_deleting(struct bfa_fcs_port_s *port,
- enum bfa_fcs_port_event event)
+bfa_fcs_lport_sm_deleting(
+ struct bfa_fcs_lport_s *port,
+ enum bfa_fcs_lport_event event)
{
bfa_trc(port->fcs, port->port_cfg.pwwn);
bfa_trc(port->fcs, event);
@@ -231,8 +230,8 @@ bfa_fcs_port_sm_deleting(struct bfa_fcs_port_s *port,
switch (event) {
case BFA_FCS_PORT_SM_DELRPORT:
if (port->num_rports == 0) {
- bfa_sm_set_state(port, bfa_fcs_port_sm_uninit);
- bfa_fcs_port_deleted(port);
+ bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
+ bfa_fcs_lport_deleted(port);
}
break;
@@ -241,74 +240,44 @@ bfa_fcs_port_sm_deleting(struct bfa_fcs_port_s *port,
}
}
-
-
/**
* fcs_port_pvt
*/
-/**
- * Send AEN notification
- */
-static void
-bfa_fcs_port_aen_post(struct bfa_fcs_port_s *port,
- enum bfa_lport_aen_event event)
-{
- union bfa_aen_data_u aen_data;
- struct bfa_log_mod_s *logmod = port->fcs->logm;
- enum bfa_port_role role = port->port_cfg.roles;
- wwn_t lpwwn = bfa_fcs_port_get_pwwn(port);
- char lpwwn_ptr[BFA_STRING_32];
- char *role_str[BFA_PORT_ROLE_FCP_MAX / 2 + 1] =
- { "Initiator", "Target", "IPFC" };
-
- wwn2str(lpwwn_ptr, lpwwn);
-
- bfa_assert(role <= BFA_PORT_ROLE_FCP_MAX);
-
- bfa_log(logmod, BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, event), lpwwn_ptr,
- role_str[role/2]);
-
- aen_data.lport.vf_id = port->fabric->vf_id;
- aen_data.lport.roles = role;
- aen_data.lport.ppwwn =
- bfa_fcs_port_get_pwwn(bfa_fcs_get_base_port(port->fcs));
- aen_data.lport.lpwwn = lpwwn;
-}
-
/*
* Send a LS reject
*/
static void
-bfa_fcs_port_send_ls_rjt(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs,
+bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
u8 reason_code, u8 reason_code_expl)
{
- struct fchs_s fchs;
+ struct fchs_s fchs;
struct bfa_fcxp_s *fcxp;
struct bfa_rport_s *bfa_rport = NULL;
- int len;
+ int len;
+ bfa_trc(port->fcs, rx_fchs->d_id);
bfa_trc(port->fcs, rx_fchs->s_id);
fcxp = bfa_fcs_fcxp_alloc(port->fcs);
if (!fcxp)
return;
- len = fc_ls_rjt_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
- bfa_fcs_port_get_fcid(port), rx_fchs->ox_id,
- reason_code, reason_code_expl);
+ len = fc_ls_rjt_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+ rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
+ rx_fchs->ox_id, reason_code, reason_code_expl);
bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
- BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
- FC_MAX_PDUSZ, 0);
+ BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
+ FC_MAX_PDUSZ, 0);
}
/**
* Process incoming plogi from a remote port.
*/
static void
-bfa_fcs_port_plogi(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs,
- struct fc_logi_s *plogi)
+bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port,
+ struct fchs_s *rx_fchs, struct fc_logi_s *plogi)
{
struct bfa_fcs_rport_s *rport;
@@ -328,46 +297,40 @@ bfa_fcs_port_plogi(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs,
/*
* send a LS reject
*/
- bfa_fcs_port_send_ls_rjt(port, rx_fchs,
- FC_LS_RJT_RSN_PROTOCOL_ERROR,
- FC_LS_RJT_EXP_SPARMS_ERR_OPTIONS);
+ bfa_fcs_lport_send_ls_rjt(port, rx_fchs,
+ FC_LS_RJT_RSN_PROTOCOL_ERROR,
+ FC_LS_RJT_EXP_SPARMS_ERR_OPTIONS);
return;
}
/**
-* Direct Attach P2P mode : verify address assigned by the r-port.
+ * Direct Attach P2P mode : verify address assigned by the r-port.
*/
- if ((!bfa_fcs_fabric_is_switched(port->fabric))
- &&
- (memcmp
- ((void *)&bfa_fcs_port_get_pwwn(port), (void *)&plogi->port_name,
- sizeof(wwn_t)) < 0)) {
+ if ((!bfa_fcs_fabric_is_switched(port->fabric)) &&
+ (memcmp((void *)&bfa_fcs_lport_get_pwwn(port),
+ (void *)&plogi->port_name, sizeof(wwn_t)) < 0)) {
if (BFA_FCS_PID_IS_WKA(rx_fchs->d_id)) {
- /*
- * Address assigned to us cannot be a WKA
- */
- bfa_fcs_port_send_ls_rjt(port, rx_fchs,
+ /* Address assigned to us cannot be a WKA */
+ bfa_fcs_lport_send_ls_rjt(port, rx_fchs,
FC_LS_RJT_RSN_PROTOCOL_ERROR,
FC_LS_RJT_EXP_INVALID_NPORT_ID);
return;
}
- port->pid = rx_fchs->d_id;
+ port->pid = rx_fchs->d_id;
}
/**
* First, check if we know the device by pwwn.
*/
- rport = bfa_fcs_port_get_rport_by_pwwn(port, plogi->port_name);
+ rport = bfa_fcs_lport_get_rport_by_pwwn(port, plogi->port_name);
if (rport) {
/**
- * Direct Attach P2P mode: handle address assigned by the rport.
- */
- if ((!bfa_fcs_fabric_is_switched(port->fabric))
- &&
- (memcmp
- ((void *)&bfa_fcs_port_get_pwwn(port),
- (void *)&plogi->port_name, sizeof(wwn_t)) < 0)) {
- port->pid = rx_fchs->d_id;
+ * Direct Attach P2P mode : handle address assigned by r-port.
+ */
+ if ((!bfa_fcs_fabric_is_switched(port->fabric)) &&
+ (memcmp((void *)&bfa_fcs_lport_get_pwwn(port),
+ (void *)&plogi->port_name, sizeof(wwn_t)) < 0)) {
+ port->pid = rx_fchs->d_id;
rport->pid = rx_fchs->s_id;
}
bfa_fcs_rport_plogi(rport, rx_fchs, plogi);
@@ -377,7 +340,7 @@ bfa_fcs_port_plogi(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs,
/**
* Next, lookup rport by PID.
*/
- rport = bfa_fcs_port_get_rport_by_pid(port, rx_fchs->s_id);
+ rport = bfa_fcs_lport_get_rport_by_pid(port, rx_fchs->s_id);
if (!rport) {
/**
* Inbound PLOGI from a new device.
@@ -416,39 +379,40 @@ bfa_fcs_port_plogi(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs,
* Since it does not require a login, it is processed here.
*/
static void
-bfa_fcs_port_echo(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs,
- struct fc_echo_s *echo, u16 rx_len)
+bfa_fcs_lport_echo(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
+ struct fc_echo_s *echo, u16 rx_len)
{
- struct fchs_s fchs;
- struct bfa_fcxp_s *fcxp;
- struct bfa_rport_s *bfa_rport = NULL;
- int len, pyld_len;
+ struct fchs_s fchs;
+ struct bfa_fcxp_s *fcxp;
+ struct bfa_rport_s *bfa_rport = NULL;
+ int len, pyld_len;
bfa_trc(port->fcs, rx_fchs->s_id);
bfa_trc(port->fcs, rx_fchs->d_id);
- bfa_trc(port->fcs, rx_len);
fcxp = bfa_fcs_fcxp_alloc(port->fcs);
if (!fcxp)
return;
- len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
- bfa_fcs_port_get_fcid(port), rx_fchs->ox_id);
+ len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+ rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
+ rx_fchs->ox_id);
/*
* Copy the payload (if any) from the echo frame
*/
pyld_len = rx_len - sizeof(struct fchs_s);
+ bfa_trc(port->fcs, rx_len);
bfa_trc(port->fcs, pyld_len);
if (pyld_len > len)
memcpy(((u8 *) bfa_fcxp_get_reqbuf(fcxp)) +
- sizeof(struct fc_echo_s), (echo + 1),
- (pyld_len - sizeof(struct fc_echo_s)));
+ sizeof(struct fc_echo_s), (echo + 1),
+ (pyld_len - sizeof(struct fc_echo_s)));
bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
- BFA_FALSE, FC_CLASS_3, pyld_len, &fchs, NULL, NULL,
- FC_MAX_PDUSZ, 0);
+ BFA_FALSE, FC_CLASS_3, pyld_len, &fchs, NULL, NULL,
+ FC_MAX_PDUSZ, 0);
}
/*
@@ -456,16 +420,16 @@ bfa_fcs_port_echo(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs,
* Since it does not require a login, it is processed here.
*/
static void
-bfa_fcs_port_rnid(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs,
- struct fc_rnid_cmd_s *rnid, u16 rx_len)
+bfa_fcs_lport_rnid(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
+ struct fc_rnid_cmd_s *rnid, u16 rx_len)
{
struct fc_rnid_common_id_data_s common_id_data;
struct fc_rnid_general_topology_data_s gen_topo_data;
- struct fchs_s fchs;
+ struct fchs_s fchs;
struct bfa_fcxp_s *fcxp;
struct bfa_rport_s *bfa_rport = NULL;
- u16 len;
- u32 data_format;
+ u16 len;
+ u32 data_format;
bfa_trc(port->fcs, rx_fchs->s_id);
bfa_trc(port->fcs, rx_fchs->d_id);
@@ -495,28 +459,26 @@ bfa_fcs_port_rnid(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs,
/*
* Copy the Node Id Info
*/
- common_id_data.port_name = bfa_fcs_port_get_pwwn(port);
- common_id_data.node_name = bfa_fcs_port_get_nwwn(port);
+ common_id_data.port_name = bfa_fcs_lport_get_pwwn(port);
+ common_id_data.node_name = bfa_fcs_lport_get_nwwn(port);
- len = fc_rnid_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
- bfa_fcs_port_get_fcid(port), rx_fchs->ox_id,
- data_format, &common_id_data, &gen_topo_data);
+ len = fc_rnid_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+ rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
+ rx_fchs->ox_id, data_format, &common_id_data,
+ &gen_topo_data);
bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
- BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
- FC_MAX_PDUSZ, 0);
-
- return;
+ BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
+ FC_MAX_PDUSZ, 0);
}
/*
* Fill out General Topolpgy Discovery Data for RNID ELS.
*/
static void
-bfa_fs_port_get_gen_topo_data(struct bfa_fcs_port_s *port,
+bfa_fs_port_get_gen_topo_data(struct bfa_fcs_lport_s *port,
struct fc_rnid_general_topology_data_s *gen_topo_data)
{
-
bfa_os_memset(gen_topo_data, 0,
sizeof(struct fc_rnid_general_topology_data_s));
@@ -526,76 +488,111 @@ bfa_fs_port_get_gen_topo_data(struct bfa_fcs_port_s *port,
}
static void
-bfa_fcs_port_online_actions(struct bfa_fcs_port_s *port)
+bfa_fcs_lport_online_actions(struct bfa_fcs_lport_s *port)
{
+ struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
+ char lpwwn_buf[BFA_STRING_32];
+
bfa_trc(port->fcs, port->fabric->oper_type);
__port_action[port->fabric->fab_type].init(port);
__port_action[port->fabric->fab_type].online(port);
- bfa_fcs_port_aen_post(port, BFA_LPORT_AEN_ONLINE);
- bfa_fcb_port_online(port->fcs->bfad, port->port_cfg.roles,
- port->fabric->vf_drv, (port->vport == NULL) ?
- NULL : port->vport->vport_drv);
+ wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
+ BFA_LOG(KERN_INFO, bfad, log_level,
+ "Logical port online: WWN = %s Role = %s\n",
+ lpwwn_buf, "Initiator");
+
+ bfad->bfad_flags |= BFAD_PORT_ONLINE;
}
static void
-bfa_fcs_port_offline_actions(struct bfa_fcs_port_s *port)
+bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port)
{
- struct list_head *qe, *qen;
+ struct list_head *qe, *qen;
struct bfa_fcs_rport_s *rport;
+ struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
+ char lpwwn_buf[BFA_STRING_32];
bfa_trc(port->fcs, port->fabric->oper_type);
__port_action[port->fabric->fab_type].offline(port);
+ wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
if (bfa_fcs_fabric_is_online(port->fabric) == BFA_TRUE)
- bfa_fcs_port_aen_post(port, BFA_LPORT_AEN_DISCONNECT);
+ BFA_LOG(KERN_ERR, bfad, log_level,
+ "Logical port lost fabric connectivity: WWN = %s Role = %s\n",
+ lpwwn_buf, "Initiator");
else
- bfa_fcs_port_aen_post(port, BFA_LPORT_AEN_OFFLINE);
- bfa_fcb_port_offline(port->fcs->bfad, port->port_cfg.roles,
- port->fabric->vf_drv,
- (port->vport == NULL) ? NULL : port->vport->vport_drv);
+ BFA_LOG(KERN_INFO, bfad, log_level,
+ "Logical port taken offline: WWN = %s Role = %s\n",
+ lpwwn_buf, "Initiator");
list_for_each_safe(qe, qen, &port->rport_q) {
- rport = (struct bfa_fcs_rport_s *)qe;
+ rport = (struct bfa_fcs_rport_s *) qe;
bfa_fcs_rport_offline(rport);
}
}
static void
-bfa_fcs_port_unknown_init(struct bfa_fcs_port_s *port)
+bfa_fcs_lport_unknown_init(struct bfa_fcs_lport_s *port)
{
bfa_assert(0);
}
static void
-bfa_fcs_port_unknown_online(struct bfa_fcs_port_s *port)
+bfa_fcs_lport_unknown_online(struct bfa_fcs_lport_s *port)
{
bfa_assert(0);
}
static void
-bfa_fcs_port_unknown_offline(struct bfa_fcs_port_s *port)
+bfa_fcs_lport_unknown_offline(struct bfa_fcs_lport_s *port)
{
bfa_assert(0);
}
static void
-bfa_fcs_port_deleted(struct bfa_fcs_port_s *port)
+bfa_fcs_lport_abts_acc(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs)
{
- bfa_fcs_port_aen_post(port, BFA_LPORT_AEN_DELETE);
+ struct fchs_s fchs;
+ struct bfa_fcxp_s *fcxp;
+ int len;
- /*
- * Base port will be deleted by the OS driver
- */
+ bfa_trc(port->fcs, rx_fchs->d_id);
+ bfa_trc(port->fcs, rx_fchs->s_id);
+
+ fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+ if (!fcxp)
+ return;
+
+ len = fc_ba_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+ rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
+ rx_fchs->ox_id, 0);
+
+ bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag,
+ BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
+ FC_MAX_PDUSZ, 0);
+}
+static void
+bfa_fcs_lport_deleted(struct bfa_fcs_lport_s *port)
+{
+ struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
+ char lpwwn_buf[BFA_STRING_32];
+
+ wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
+ BFA_LOG(KERN_INFO, bfad, log_level,
+ "Logical port deleted: WWN = %s Role = %s\n",
+ lpwwn_buf, "Initiator");
+
+ /* Base port will be deleted by the OS driver */
if (port->vport) {
- bfa_fcb_port_delete(port->fcs->bfad, port->port_cfg.roles,
- port->fabric->vf_drv,
- port->vport ? port->vport->vport_drv : NULL);
+ bfa_fcb_lport_delete(port->fcs->bfad, port->port_cfg.roles,
+ port->fabric->vf_drv,
+ port->vport ? port->vport->vport_drv : NULL);
bfa_fcs_vport_delete_comp(port->vport);
} else {
- bfa_fcs_fabric_port_delete_comp(port->fabric);
+ bfa_fcs_fabric_port_delete_comp(port->fabric);
}
}
@@ -608,7 +605,7 @@ bfa_fcs_port_deleted(struct bfa_fcs_port_s *port)
* Module initialization
*/
void
-bfa_fcs_port_modinit(struct bfa_fcs_s *fcs)
+bfa_fcs_lport_modinit(struct bfa_fcs_s *fcs)
{
}
@@ -617,25 +614,25 @@ bfa_fcs_port_modinit(struct bfa_fcs_s *fcs)
* Module cleanup
*/
void
-bfa_fcs_port_modexit(struct bfa_fcs_s *fcs)
+bfa_fcs_lport_modexit(struct bfa_fcs_s *fcs)
{
bfa_fcs_modexit_comp(fcs);
}
/**
- * Unsolicited frame receive handling.
+ * Unsolicited frame receive handling.
*/
void
-bfa_fcs_port_uf_recv(struct bfa_fcs_port_s *lport, struct fchs_s *fchs,
- u16 len)
+bfa_fcs_lport_uf_recv(struct bfa_fcs_lport_s *lport,
+ struct fchs_s *fchs, u16 len)
{
- u32 pid = fchs->s_id;
+ u32 pid = fchs->s_id;
struct bfa_fcs_rport_s *rport = NULL;
- struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
+ struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
bfa_stats(lport, uf_recvs);
- if (!bfa_fcs_port_is_online(lport)) {
+ if (!bfa_fcs_lport_is_online(lport)) {
bfa_stats(lport, uf_recv_drops);
return;
}
@@ -648,7 +645,7 @@ bfa_fcs_port_uf_recv(struct bfa_fcs_port_s *lport, struct fchs_s *fchs,
*/
if ((fchs->type == FC_TYPE_ELS) &&
(els_cmd->els_code == FC_ELS_PLOGI)) {
- bfa_fcs_port_plogi(lport, fchs, (struct fc_logi_s *) els_cmd);
+ bfa_fcs_lport_plogi(lport, fchs, (struct fc_logi_s *) els_cmd);
return;
}
@@ -656,8 +653,8 @@ bfa_fcs_port_uf_recv(struct bfa_fcs_port_s *lport, struct fchs_s *fchs,
* Handle ECHO separately.
*/
if ((fchs->type == FC_TYPE_ELS) && (els_cmd->els_code == FC_ELS_ECHO)) {
- bfa_fcs_port_echo(lport, fchs,
- (struct fc_echo_s *) els_cmd, len);
+ bfa_fcs_lport_echo(lport, fchs,
+ (struct fc_echo_s *)els_cmd, len);
return;
}
@@ -665,15 +662,21 @@ bfa_fcs_port_uf_recv(struct bfa_fcs_port_s *lport, struct fchs_s *fchs,
* Handle RNID separately.
*/
if ((fchs->type == FC_TYPE_ELS) && (els_cmd->els_code == FC_ELS_RNID)) {
- bfa_fcs_port_rnid(lport, fchs,
+ bfa_fcs_lport_rnid(lport, fchs,
(struct fc_rnid_cmd_s *) els_cmd, len);
return;
}
+ if (fchs->type == FC_TYPE_BLS) {
+ if ((fchs->routing == FC_RTG_BASIC_LINK) &&
+ (fchs->cat_info == FC_CAT_ABTS))
+ bfa_fcs_lport_abts_acc(lport, fchs);
+ return;
+ }
/**
* look for a matching remote port ID
*/
- rport = bfa_fcs_port_get_rport_by_pid(lport, pid);
+ rport = bfa_fcs_lport_get_rport_by_pid(lport, pid);
if (rport) {
bfa_trc(rport->fcs, fchs->s_id);
bfa_trc(rport->fcs, fchs->d_id);
@@ -694,7 +697,7 @@ bfa_fcs_port_uf_recv(struct bfa_fcs_port_s *lport, struct fchs_s *fchs,
bfa_trc(lport->fcs, els_cmd->els_code);
if (els_cmd->els_code == FC_ELS_RSCN) {
- bfa_fcs_port_scn_process_rscn(lport, fchs, len);
+ bfa_fcs_lport_scn_process_rscn(lport, fchs, len);
return;
}
@@ -702,7 +705,6 @@ bfa_fcs_port_uf_recv(struct bfa_fcs_port_s *lport, struct fchs_s *fchs,
/**
* @todo Handle LOGO frames received.
*/
- bfa_trc(lport->fcs, els_cmd->els_code);
return;
}
@@ -710,14 +712,13 @@ bfa_fcs_port_uf_recv(struct bfa_fcs_port_s *lport, struct fchs_s *fchs,
/**
* @todo Handle PRLI frames received.
*/
- bfa_trc(lport->fcs, els_cmd->els_code);
return;
}
/**
* Unhandled ELS frames. Send a LS_RJT.
*/
- bfa_fcs_port_send_ls_rjt(lport, fchs, FC_LS_RJT_RSN_CMD_NOT_SUPP,
+ bfa_fcs_lport_send_ls_rjt(lport, fchs, FC_LS_RJT_RSN_CMD_NOT_SUPP,
FC_LS_RJT_EXP_NO_ADDL_INFO);
}
@@ -726,13 +727,13 @@ bfa_fcs_port_uf_recv(struct bfa_fcs_port_s *lport, struct fchs_s *fchs,
* PID based Lookup for a R-Port in the Port R-Port Queue
*/
struct bfa_fcs_rport_s *
-bfa_fcs_port_get_rport_by_pid(struct bfa_fcs_port_s *port, u32 pid)
+bfa_fcs_lport_get_rport_by_pid(struct bfa_fcs_lport_s *port, u32 pid)
{
struct bfa_fcs_rport_s *rport;
- struct list_head *qe;
+ struct list_head *qe;
list_for_each(qe, &port->rport_q) {
- rport = (struct bfa_fcs_rport_s *)qe;
+ rport = (struct bfa_fcs_rport_s *) qe;
if (rport->pid == pid)
return rport;
}
@@ -745,13 +746,13 @@ bfa_fcs_port_get_rport_by_pid(struct bfa_fcs_port_s *port, u32 pid)
* PWWN based Lookup for a R-Port in the Port R-Port Queue
*/
struct bfa_fcs_rport_s *
-bfa_fcs_port_get_rport_by_pwwn(struct bfa_fcs_port_s *port, wwn_t pwwn)
+bfa_fcs_lport_get_rport_by_pwwn(struct bfa_fcs_lport_s *port, wwn_t pwwn)
{
struct bfa_fcs_rport_s *rport;
- struct list_head *qe;
+ struct list_head *qe;
list_for_each(qe, &port->rport_q) {
- rport = (struct bfa_fcs_rport_s *)qe;
+ rport = (struct bfa_fcs_rport_s *) qe;
if (wwn_is_equal(rport->pwwn, pwwn))
return rport;
}
@@ -764,13 +765,13 @@ bfa_fcs_port_get_rport_by_pwwn(struct bfa_fcs_port_s *port, wwn_t pwwn)
* NWWN based Lookup for a R-Port in the Port R-Port Queue
*/
struct bfa_fcs_rport_s *
-bfa_fcs_port_get_rport_by_nwwn(struct bfa_fcs_port_s *port, wwn_t nwwn)
+bfa_fcs_lport_get_rport_by_nwwn(struct bfa_fcs_lport_s *port, wwn_t nwwn)
{
struct bfa_fcs_rport_s *rport;
- struct list_head *qe;
+ struct list_head *qe;
list_for_each(qe, &port->rport_q) {
- rport = (struct bfa_fcs_rport_s *)qe;
+ rport = (struct bfa_fcs_rport_s *) qe;
if (wwn_is_equal(rport->nwwn, nwwn))
return rport;
}
@@ -783,8 +784,9 @@ bfa_fcs_port_get_rport_by_nwwn(struct bfa_fcs_port_s *port, wwn_t nwwn)
* Called by rport module when new rports are discovered.
*/
void
-bfa_fcs_port_add_rport(struct bfa_fcs_port_s *port,
- struct bfa_fcs_rport_s *rport)
+bfa_fcs_lport_add_rport(
+ struct bfa_fcs_lport_s *port,
+ struct bfa_fcs_rport_s *rport)
{
list_add_tail(&rport->qe, &port->rport_q);
port->num_rports++;
@@ -794,8 +796,9 @@ bfa_fcs_port_add_rport(struct bfa_fcs_port_s *port,
* Called by rport module to when rports are deleted.
*/
void
-bfa_fcs_port_del_rport(struct bfa_fcs_port_s *port,
- struct bfa_fcs_rport_s *rport)
+bfa_fcs_lport_del_rport(
+ struct bfa_fcs_lport_s *port,
+ struct bfa_fcs_rport_s *rport)
{
bfa_assert(bfa_q_is_on_q(&port->rport_q, rport));
list_del(&rport->qe);
@@ -809,7 +812,7 @@ bfa_fcs_port_del_rport(struct bfa_fcs_port_s *port,
* Called by vport for virtual ports when FDISC is complete.
*/
void
-bfa_fcs_port_online(struct bfa_fcs_port_s *port)
+bfa_fcs_lport_online(struct bfa_fcs_lport_s *port)
{
bfa_sm_send_event(port, BFA_FCS_PORT_SM_ONLINE);
}
@@ -819,7 +822,7 @@ bfa_fcs_port_online(struct bfa_fcs_port_s *port)
* Called by vport for virtual ports when virtual port becomes offline.
*/
void
-bfa_fcs_port_offline(struct bfa_fcs_port_s *port)
+bfa_fcs_lport_offline(struct bfa_fcs_lport_s *port)
{
bfa_sm_send_event(port, BFA_FCS_PORT_SM_OFFLINE);
}
@@ -831,40 +834,32 @@ bfa_fcs_port_offline(struct bfa_fcs_port_s *port)
* bfa_fcs_vport_delete_comp() for vports on completion.
*/
void
-bfa_fcs_port_delete(struct bfa_fcs_port_s *port)
+bfa_fcs_lport_delete(struct bfa_fcs_lport_s *port)
{
bfa_sm_send_event(port, BFA_FCS_PORT_SM_DELETE);
}
/**
- * Called by fabric in private loop topology to process LIP event.
- */
-void
-bfa_fcs_port_lip(struct bfa_fcs_port_s *port)
-{
-}
-
-/**
* Return TRUE if port is online, else return FALSE
*/
bfa_boolean_t
-bfa_fcs_port_is_online(struct bfa_fcs_port_s *port)
+bfa_fcs_lport_is_online(struct bfa_fcs_lport_s *port)
{
- return bfa_sm_cmp_state(port, bfa_fcs_port_sm_online);
+ return bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online);
}
/**
- * Attach time initialization of logical ports.
+ * Attach time initialization of logical ports.
*/
void
-bfa_fcs_lport_attach(struct bfa_fcs_port_s *lport, struct bfa_fcs_s *fcs,
- uint16_t vf_id, struct bfa_fcs_vport_s *vport)
+bfa_fcs_lport_attach(struct bfa_fcs_lport_s *lport, struct bfa_fcs_s *fcs,
+ u16 vf_id, struct bfa_fcs_vport_s *vport)
{
lport->fcs = fcs;
lport->fabric = bfa_fcs_vf_lookup(fcs, vf_id);
lport->vport = vport;
lport->lp_tag = (vport) ? bfa_lps_get_tag(vport->lps) :
- bfa_lps_get_tag(lport->fabric->lps);
+ bfa_lps_get_tag(lport->fabric->lps);
INIT_LIST_HEAD(&lport->rport_q);
lport->num_rports = 0;
@@ -876,21 +871,26 @@ bfa_fcs_lport_attach(struct bfa_fcs_port_s *lport, struct bfa_fcs_s *fcs,
*/
void
-bfa_fcs_lport_init(struct bfa_fcs_port_s *lport,
- struct bfa_port_cfg_s *port_cfg)
+bfa_fcs_lport_init(struct bfa_fcs_lport_s *lport,
+ struct bfa_lport_cfg_s *port_cfg)
{
struct bfa_fcs_vport_s *vport = lport->vport;
+ struct bfad_s *bfad = (struct bfad_s *)lport->fcs->bfad;
+ char lpwwn_buf[BFA_STRING_32];
bfa_os_assign(lport->port_cfg, *port_cfg);
- lport->bfad_port = bfa_fcb_port_new(lport->fcs->bfad, lport,
- lport->port_cfg.roles,
- lport->fabric->vf_drv,
- vport ? vport->vport_drv : NULL);
+ lport->bfad_port = bfa_fcb_lport_new(lport->fcs->bfad, lport,
+ lport->port_cfg.roles,
+ lport->fabric->vf_drv,
+ vport ? vport->vport_drv : NULL);
- bfa_fcs_port_aen_post(lport, BFA_LPORT_AEN_NEW);
+ wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(lport));
+ BFA_LOG(KERN_INFO, bfad, log_level,
+ "New logical port created: WWN = %s Role = %s\n",
+ lpwwn_buf, "Initiator");
- bfa_sm_set_state(lport, bfa_fcs_port_sm_uninit);
+ bfa_sm_set_state(lport, bfa_fcs_lport_sm_uninit);
bfa_sm_send_event(lport, BFA_FCS_PORT_SM_CREATE);
}
@@ -899,10 +899,11 @@ bfa_fcs_lport_init(struct bfa_fcs_port_s *lport,
*/
void
-bfa_fcs_port_get_attr(struct bfa_fcs_port_s *port,
- struct bfa_port_attr_s *port_attr)
+bfa_fcs_lport_get_attr(
+ struct bfa_fcs_lport_s *port,
+ struct bfa_lport_attr_s *port_attr)
{
- if (bfa_sm_cmp_state(port, bfa_fcs_port_sm_online))
+ if (bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online))
port_attr->pid = port->pid;
else
port_attr->pid = 0;
@@ -913,25 +914,4895 @@ bfa_fcs_port_get_attr(struct bfa_fcs_port_s *port,
port_attr->port_type = bfa_fcs_fabric_port_type(port->fabric);
port_attr->loopback = bfa_fcs_fabric_is_loopback(port->fabric);
port_attr->authfail =
- bfa_fcs_fabric_is_auth_failed(port->fabric);
- port_attr->fabric_name = bfa_fcs_port_get_fabric_name(port);
+ bfa_fcs_fabric_is_auth_failed(port->fabric);
+ port_attr->fabric_name = bfa_fcs_lport_get_fabric_name(port);
memcpy(port_attr->fabric_ip_addr,
- bfa_fcs_port_get_fabric_ipaddr(port),
- BFA_FCS_FABRIC_IPADDR_SZ);
+ bfa_fcs_lport_get_fabric_ipaddr(port),
+ BFA_FCS_FABRIC_IPADDR_SZ);
if (port->vport != NULL) {
- port_attr->port_type = BFA_PPORT_TYPE_VPORT;
+ port_attr->port_type = BFA_PORT_TYPE_VPORT;
port_attr->fpma_mac =
bfa_lps_get_lp_mac(port->vport->lps);
- } else
+ } else {
port_attr->fpma_mac =
bfa_lps_get_lp_mac(port->fabric->lps);
+ }
+ } else {
+ port_attr->port_type = BFA_PORT_TYPE_UNKNOWN;
+ port_attr->state = BFA_LPORT_UNINIT;
+ }
+}
+
+/**
+ * bfa_fcs_lport_fab port fab functions
+ */
+
+/**
+ * Called by port to initialize fabric services of the base port.
+ */
+static void
+bfa_fcs_lport_fab_init(struct bfa_fcs_lport_s *port)
+{
+ bfa_fcs_lport_ns_init(port);
+ bfa_fcs_lport_scn_init(port);
+ bfa_fcs_lport_ms_init(port);
+}
+
+/**
+ * Called by port to notify transition to online state.
+ */
+static void
+bfa_fcs_lport_fab_online(struct bfa_fcs_lport_s *port)
+{
+ bfa_fcs_lport_ns_online(port);
+ bfa_fcs_lport_scn_online(port);
+}
+
+/**
+ * Called by port to notify transition to offline state.
+ */
+static void
+bfa_fcs_lport_fab_offline(struct bfa_fcs_lport_s *port)
+{
+ bfa_fcs_lport_ns_offline(port);
+ bfa_fcs_lport_scn_offline(port);
+ bfa_fcs_lport_ms_offline(port);
+}
+
+/**
+ * bfa_fcs_lport_n2n functions
+ */
+
+/**
+ * Called by fcs/port to initialize N2N topology.
+ */
+static void
+bfa_fcs_lport_n2n_init(struct bfa_fcs_lport_s *port)
+{
+}
+
+/**
+ * Called by fcs/port to notify transition to online state.
+ */
+static void
+bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port)
+{
+ struct bfa_fcs_lport_n2n_s *n2n_port = &port->port_topo.pn2n;
+ struct bfa_lport_cfg_s *pcfg = &port->port_cfg;
+ struct bfa_fcs_rport_s *rport;
+
+ bfa_trc(port->fcs, pcfg->pwwn);
+
+ /*
+ * If our PWWN is > than that of the r-port, we have to initiate PLOGI
+ * and assign an Address. if not, we need to wait for its PLOGI.
+ *
+ * If our PWWN is < than that of the remote port, it will send a PLOGI
+ * with the PIDs assigned. The rport state machine take care of this
+ * incoming PLOGI.
+ */
+ if (memcmp
+ ((void *)&pcfg->pwwn, (void *)&n2n_port->rem_port_wwn,
+ sizeof(wwn_t)) > 0) {
+ port->pid = N2N_LOCAL_PID;
+ /**
+ * First, check if we know the device by pwwn.
+ */
+ rport = bfa_fcs_lport_get_rport_by_pwwn(port,
+ n2n_port->rem_port_wwn);
+ if (rport) {
+ bfa_trc(port->fcs, rport->pid);
+ bfa_trc(port->fcs, rport->pwwn);
+ rport->pid = N2N_REMOTE_PID;
+ bfa_fcs_rport_online(rport);
+ return;
+ }
+
+ /*
+ * In n2n there can be only one rport. Delete the old one
+ * whose pid should be zero, because it is offline.
+ */
+ if (port->num_rports > 0) {
+ rport = bfa_fcs_lport_get_rport_by_pid(port, 0);
+ bfa_assert(rport != NULL);
+ if (rport) {
+ bfa_trc(port->fcs, rport->pwwn);
+ bfa_fcs_rport_delete(rport);
+ }
+ }
+ bfa_fcs_rport_create(port, N2N_REMOTE_PID);
+ }
+}
+
+/**
+ * Called by fcs/port to notify transition to offline state.
+ */
+static void
+bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s *port)
+{
+ struct bfa_fcs_lport_n2n_s *n2n_port = &port->port_topo.pn2n;
+
+ bfa_trc(port->fcs, port->pid);
+ port->pid = 0;
+ n2n_port->rem_port_wwn = 0;
+ n2n_port->reply_oxid = 0;
+}
+
+#define BFA_FCS_FDMI_CMD_MAX_RETRIES 2
+
+/*
+ * forward declarations
+ */
+static void bfa_fcs_lport_fdmi_send_rhba(void *fdmi_cbarg,
+ struct bfa_fcxp_s *fcxp_alloced);
+static void bfa_fcs_lport_fdmi_send_rprt(void *fdmi_cbarg,
+ struct bfa_fcxp_s *fcxp_alloced);
+static void bfa_fcs_lport_fdmi_send_rpa(void *fdmi_cbarg,
+ struct bfa_fcxp_s *fcxp_alloced);
+static void bfa_fcs_lport_fdmi_rhba_response(void *fcsarg,
+ struct bfa_fcxp_s *fcxp,
+ void *cbarg,
+ bfa_status_t req_status,
+ u32 rsp_len,
+ u32 resid_len,
+ struct fchs_s *rsp_fchs);
+static void bfa_fcs_lport_fdmi_rprt_response(void *fcsarg,
+ struct bfa_fcxp_s *fcxp,
+ void *cbarg,
+ bfa_status_t req_status,
+ u32 rsp_len,
+ u32 resid_len,
+ struct fchs_s *rsp_fchs);
+static void bfa_fcs_lport_fdmi_rpa_response(void *fcsarg,
+ struct bfa_fcxp_s *fcxp,
+ void *cbarg,
+ bfa_status_t req_status,
+ u32 rsp_len,
+ u32 resid_len,
+ struct fchs_s *rsp_fchs);
+static void bfa_fcs_lport_fdmi_timeout(void *arg);
+static u16 bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
+ u8 *pyld);
+static u16 bfa_fcs_lport_fdmi_build_rprt_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
+ u8 *pyld);
+static u16 bfa_fcs_lport_fdmi_build_rpa_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
+ u8 *pyld);
+static u16 bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *
+ fdmi, u8 *pyld);
+static void bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
+ struct bfa_fcs_fdmi_hba_attr_s *hba_attr);
+static void bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
+ struct bfa_fcs_fdmi_port_attr_s *port_attr);
+/**
+ * fcs_fdmi_sm FCS FDMI state machine
+ */
+
+/**
+ * FDMI State Machine events
+ */
+enum port_fdmi_event {
+ FDMISM_EVENT_PORT_ONLINE = 1,
+ FDMISM_EVENT_PORT_OFFLINE = 2,
+ FDMISM_EVENT_RSP_OK = 4,
+ FDMISM_EVENT_RSP_ERROR = 5,
+ FDMISM_EVENT_TIMEOUT = 6,
+ FDMISM_EVENT_RHBA_SENT = 7,
+ FDMISM_EVENT_RPRT_SENT = 8,
+ FDMISM_EVENT_RPA_SENT = 9,
+};
+
+static void bfa_fcs_lport_fdmi_sm_offline(struct bfa_fcs_lport_fdmi_s *fdmi,
+ enum port_fdmi_event event);
+static void bfa_fcs_lport_fdmi_sm_sending_rhba(
+ struct bfa_fcs_lport_fdmi_s *fdmi,
+ enum port_fdmi_event event);
+static void bfa_fcs_lport_fdmi_sm_rhba(struct bfa_fcs_lport_fdmi_s *fdmi,
+ enum port_fdmi_event event);
+static void bfa_fcs_lport_fdmi_sm_rhba_retry(
+ struct bfa_fcs_lport_fdmi_s *fdmi,
+ enum port_fdmi_event event);
+static void bfa_fcs_lport_fdmi_sm_sending_rprt(
+ struct bfa_fcs_lport_fdmi_s *fdmi,
+ enum port_fdmi_event event);
+static void bfa_fcs_lport_fdmi_sm_rprt(struct bfa_fcs_lport_fdmi_s *fdmi,
+ enum port_fdmi_event event);
+static void bfa_fcs_lport_fdmi_sm_rprt_retry(
+ struct bfa_fcs_lport_fdmi_s *fdmi,
+ enum port_fdmi_event event);
+static void bfa_fcs_lport_fdmi_sm_sending_rpa(
+ struct bfa_fcs_lport_fdmi_s *fdmi,
+ enum port_fdmi_event event);
+static void bfa_fcs_lport_fdmi_sm_rpa(struct bfa_fcs_lport_fdmi_s *fdmi,
+ enum port_fdmi_event event);
+static void bfa_fcs_lport_fdmi_sm_rpa_retry(
+ struct bfa_fcs_lport_fdmi_s *fdmi,
+ enum port_fdmi_event event);
+static void bfa_fcs_lport_fdmi_sm_online(struct bfa_fcs_lport_fdmi_s *fdmi,
+ enum port_fdmi_event event);
+static void bfa_fcs_lport_fdmi_sm_disabled(
+ struct bfa_fcs_lport_fdmi_s *fdmi,
+ enum port_fdmi_event event);
+/**
+ * Start in offline state - awaiting MS to send start.
+ */
+static void
+bfa_fcs_lport_fdmi_sm_offline(struct bfa_fcs_lport_fdmi_s *fdmi,
+ enum port_fdmi_event event)
+{
+ struct bfa_fcs_lport_s *port = fdmi->ms->port;
+
+ bfa_trc(port->fcs, port->port_cfg.pwwn);
+ bfa_trc(port->fcs, event);
+
+ fdmi->retry_cnt = 0;
+
+ switch (event) {
+ case FDMISM_EVENT_PORT_ONLINE:
+ if (port->vport) {
+ /*
+ * For Vports, register a new port.
+ */
+ bfa_sm_set_state(fdmi,
+ bfa_fcs_lport_fdmi_sm_sending_rprt);
+ bfa_fcs_lport_fdmi_send_rprt(fdmi, NULL);
+ } else {
+ /*
+ * For a base port, we should first register the HBA
+ * atribute. The HBA attribute also contains the base
+ * port registration.
+ */
+ bfa_sm_set_state(fdmi,
+ bfa_fcs_lport_fdmi_sm_sending_rhba);
+ bfa_fcs_lport_fdmi_send_rhba(fdmi, NULL);
+ }
+ break;
+
+ case FDMISM_EVENT_PORT_OFFLINE:
+ break;
+
+ default:
+ bfa_sm_fault(port->fcs, event);
+ }
+}
+
+static void
+bfa_fcs_lport_fdmi_sm_sending_rhba(struct bfa_fcs_lport_fdmi_s *fdmi,
+ enum port_fdmi_event event)
+{
+ struct bfa_fcs_lport_s *port = fdmi->ms->port;
+
+ bfa_trc(port->fcs, port->port_cfg.pwwn);
+ bfa_trc(port->fcs, event);
+
+ switch (event) {
+ case FDMISM_EVENT_RHBA_SENT:
+ bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rhba);
+ break;
+
+ case FDMISM_EVENT_PORT_OFFLINE:
+ bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
+ bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
+ &fdmi->fcxp_wqe);
+ break;
+
+ default:
+ bfa_sm_fault(port->fcs, event);
+ }
+}
+
+static void
+bfa_fcs_lport_fdmi_sm_rhba(struct bfa_fcs_lport_fdmi_s *fdmi,
+ enum port_fdmi_event event)
+{
+ struct bfa_fcs_lport_s *port = fdmi->ms->port;
+
+ bfa_trc(port->fcs, port->port_cfg.pwwn);
+ bfa_trc(port->fcs, event);
+
+ switch (event) {
+ case FDMISM_EVENT_RSP_ERROR:
+ /*
+ * if max retries have not been reached, start timer for a
+ * delayed retry
+ */
+ if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
+ bfa_sm_set_state(fdmi,
+ bfa_fcs_lport_fdmi_sm_rhba_retry);
+ bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
+ &fdmi->timer,
+ bfa_fcs_lport_fdmi_timeout, fdmi,
+ BFA_FCS_RETRY_TIMEOUT);
+ } else {
+ /*
+ * set state to offline
+ */
+ bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
+ }
+ break;
+
+ case FDMISM_EVENT_RSP_OK:
+ /*
+ * Initiate Register Port Attributes
+ */
+ bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rpa);
+ fdmi->retry_cnt = 0;
+ bfa_fcs_lport_fdmi_send_rpa(fdmi, NULL);
+ break;
+
+ case FDMISM_EVENT_PORT_OFFLINE:
+ bfa_fcxp_discard(fdmi->fcxp);
+ bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
+ break;
+
+ default:
+ bfa_sm_fault(port->fcs, event);
+ }
+}
+
+static void
+bfa_fcs_lport_fdmi_sm_rhba_retry(struct bfa_fcs_lport_fdmi_s *fdmi,
+ enum port_fdmi_event event)
+{
+ struct bfa_fcs_lport_s *port = fdmi->ms->port;
+
+ bfa_trc(port->fcs, port->port_cfg.pwwn);
+ bfa_trc(port->fcs, event);
+
+ switch (event) {
+ case FDMISM_EVENT_TIMEOUT:
+ /*
+ * Retry Timer Expired. Re-send
+ */
+ bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rhba);
+ bfa_fcs_lport_fdmi_send_rhba(fdmi, NULL);
+ break;
+
+ case FDMISM_EVENT_PORT_OFFLINE:
+ bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
+ bfa_timer_stop(&fdmi->timer);
+ break;
+
+ default:
+ bfa_sm_fault(port->fcs, event);
+ }
+}
+
+/*
+* RPRT : Register Port
+ */
+static void
+bfa_fcs_lport_fdmi_sm_sending_rprt(struct bfa_fcs_lport_fdmi_s *fdmi,
+ enum port_fdmi_event event)
+{
+ struct bfa_fcs_lport_s *port = fdmi->ms->port;
+
+ bfa_trc(port->fcs, port->port_cfg.pwwn);
+ bfa_trc(port->fcs, event);
+
+ switch (event) {
+ case FDMISM_EVENT_RPRT_SENT:
+ bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rprt);
+ break;
+
+ case FDMISM_EVENT_PORT_OFFLINE:
+ bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
+ bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
+ &fdmi->fcxp_wqe);
+ break;
+
+ default:
+ bfa_sm_fault(port->fcs, event);
+ }
+}
+
+static void
+bfa_fcs_lport_fdmi_sm_rprt(struct bfa_fcs_lport_fdmi_s *fdmi,
+ enum port_fdmi_event event)
+{
+ struct bfa_fcs_lport_s *port = fdmi->ms->port;
+
+ bfa_trc(port->fcs, port->port_cfg.pwwn);
+ bfa_trc(port->fcs, event);
+
+ switch (event) {
+ case FDMISM_EVENT_RSP_ERROR:
+ /*
+ * if max retries have not been reached, start timer for a
+ * delayed retry
+ */
+ if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
+ bfa_sm_set_state(fdmi,
+ bfa_fcs_lport_fdmi_sm_rprt_retry);
+ bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
+ &fdmi->timer,
+ bfa_fcs_lport_fdmi_timeout, fdmi,
+ BFA_FCS_RETRY_TIMEOUT);
+
+ } else {
+ /*
+ * set state to offline
+ */
+ bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
+ fdmi->retry_cnt = 0;
+ }
+ break;
+
+ case FDMISM_EVENT_RSP_OK:
+ fdmi->retry_cnt = 0;
+ bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_online);
+ break;
+
+ case FDMISM_EVENT_PORT_OFFLINE:
+ bfa_fcxp_discard(fdmi->fcxp);
+ bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
+ break;
+
+ default:
+ bfa_sm_fault(port->fcs, event);
+ }
+}
+
+static void
+bfa_fcs_lport_fdmi_sm_rprt_retry(struct bfa_fcs_lport_fdmi_s *fdmi,
+ enum port_fdmi_event event)
+{
+ struct bfa_fcs_lport_s *port = fdmi->ms->port;
+
+ bfa_trc(port->fcs, port->port_cfg.pwwn);
+ bfa_trc(port->fcs, event);
+
+ switch (event) {
+ case FDMISM_EVENT_TIMEOUT:
+ /*
+ * Retry Timer Expired. Re-send
+ */
+ bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rprt);
+ bfa_fcs_lport_fdmi_send_rprt(fdmi, NULL);
+ break;
+
+ case FDMISM_EVENT_PORT_OFFLINE:
+ bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
+ bfa_timer_stop(&fdmi->timer);
+ break;
+
+ default:
+ bfa_sm_fault(port->fcs, event);
+ }
+}
+
+/*
+ * Register Port Attributes
+ */
+static void
+bfa_fcs_lport_fdmi_sm_sending_rpa(struct bfa_fcs_lport_fdmi_s *fdmi,
+ enum port_fdmi_event event)
+{
+ struct bfa_fcs_lport_s *port = fdmi->ms->port;
+
+ bfa_trc(port->fcs, port->port_cfg.pwwn);
+ bfa_trc(port->fcs, event);
+
+ switch (event) {
+ case FDMISM_EVENT_RPA_SENT:
+ bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rpa);
+ break;
+
+ case FDMISM_EVENT_PORT_OFFLINE:
+ bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
+ bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
+ &fdmi->fcxp_wqe);
+ break;
+
+ default:
+ bfa_sm_fault(port->fcs, event);
+ }
+}
+
+static void
+bfa_fcs_lport_fdmi_sm_rpa(struct bfa_fcs_lport_fdmi_s *fdmi,
+ enum port_fdmi_event event)
+{
+ struct bfa_fcs_lport_s *port = fdmi->ms->port;
+
+ bfa_trc(port->fcs, port->port_cfg.pwwn);
+ bfa_trc(port->fcs, event);
+
+ switch (event) {
+ case FDMISM_EVENT_RSP_ERROR:
+ /*
+ * if max retries have not been reached, start timer for a
+ * delayed retry
+ */
+ if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
+ bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rpa_retry);
+ bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
+ &fdmi->timer,
+ bfa_fcs_lport_fdmi_timeout, fdmi,
+ BFA_FCS_RETRY_TIMEOUT);
+ } else {
+ /*
+ * set state to offline
+ */
+ bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
+ fdmi->retry_cnt = 0;
+ }
+ break;
+
+ case FDMISM_EVENT_RSP_OK:
+ bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_online);
+ fdmi->retry_cnt = 0;
+ break;
+
+ case FDMISM_EVENT_PORT_OFFLINE:
+ bfa_fcxp_discard(fdmi->fcxp);
+ bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
+ break;
+
+ default:
+ bfa_sm_fault(port->fcs, event);
+ }
+}
+
+static void
+bfa_fcs_lport_fdmi_sm_rpa_retry(struct bfa_fcs_lport_fdmi_s *fdmi,
+ enum port_fdmi_event event)
+{
+ struct bfa_fcs_lport_s *port = fdmi->ms->port;
+
+ bfa_trc(port->fcs, port->port_cfg.pwwn);
+ bfa_trc(port->fcs, event);
+
+ switch (event) {
+ case FDMISM_EVENT_TIMEOUT:
+ /*
+ * Retry Timer Expired. Re-send
+ */
+ bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rpa);
+ bfa_fcs_lport_fdmi_send_rpa(fdmi, NULL);
+ break;
+
+ case FDMISM_EVENT_PORT_OFFLINE:
+ bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
+ bfa_timer_stop(&fdmi->timer);
+ break;
+
+ default:
+ bfa_sm_fault(port->fcs, event);
+ }
+}
+
+static void
+bfa_fcs_lport_fdmi_sm_online(struct bfa_fcs_lport_fdmi_s *fdmi,
+ enum port_fdmi_event event)
+{
+ struct bfa_fcs_lport_s *port = fdmi->ms->port;
+
+ bfa_trc(port->fcs, port->port_cfg.pwwn);
+ bfa_trc(port->fcs, event);
+
+ switch (event) {
+ case FDMISM_EVENT_PORT_OFFLINE:
+ bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
+ break;
+
+ default:
+ bfa_sm_fault(port->fcs, event);
+ }
+}
+/**
+ * FDMI is disabled state.
+ */
+static void
+bfa_fcs_lport_fdmi_sm_disabled(struct bfa_fcs_lport_fdmi_s *fdmi,
+ enum port_fdmi_event event)
+{
+ struct bfa_fcs_lport_s *port = fdmi->ms->port;
+
+ bfa_trc(port->fcs, port->port_cfg.pwwn);
+ bfa_trc(port->fcs, event);
+
+ /* No op State. It can only be enabled at Driver Init. */
+}
+
+/**
+* RHBA : Register HBA Attributes.
+ */
+static void
+bfa_fcs_lport_fdmi_send_rhba(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+ struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg;
+ struct bfa_fcs_lport_s *port = fdmi->ms->port;
+ struct fchs_s fchs;
+ int len, attr_len;
+ struct bfa_fcxp_s *fcxp;
+ u8 *pyld;
+
+ bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+ fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+ if (!fcxp) {
+ bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
+ bfa_fcs_lport_fdmi_send_rhba, fdmi);
+ return;
+ }
+ fdmi->fcxp = fcxp;
+
+ pyld = bfa_fcxp_get_reqbuf(fcxp);
+ bfa_os_memset(pyld, 0, FC_MAX_PDUSZ);
+
+ len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
+ FDMI_RHBA);
+
+ attr_len =
+ bfa_fcs_lport_fdmi_build_rhba_pyld(fdmi,
+ (u8 *) ((struct ct_hdr_s *) pyld
+ + 1));
+
+ bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+ FC_CLASS_3, (len + attr_len), &fchs,
+ bfa_fcs_lport_fdmi_rhba_response, (void *)fdmi,
+ FC_MAX_PDUSZ, FC_FCCT_TOV);
+
+ bfa_sm_send_event(fdmi, FDMISM_EVENT_RHBA_SENT);
+}
+
+static u16
+bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
+{
+ struct bfa_fcs_lport_s *port = fdmi->ms->port;
+ struct bfa_fcs_fdmi_hba_attr_s hba_attr;
+ struct bfa_fcs_fdmi_hba_attr_s *fcs_hba_attr = &hba_attr;
+ struct fdmi_rhba_s *rhba = (struct fdmi_rhba_s *) pyld;
+ struct fdmi_attr_s *attr;
+ u8 *curr_ptr;
+ u16 len, count;
+
+ /*
+ * get hba attributes
+ */
+ bfa_fcs_fdmi_get_hbaattr(fdmi, fcs_hba_attr);
+
+ rhba->hba_id = bfa_fcs_lport_get_pwwn(port);
+ rhba->port_list.num_ports = bfa_os_htonl(1);
+ rhba->port_list.port_entry = bfa_fcs_lport_get_pwwn(port);
+
+ len = sizeof(rhba->hba_id) + sizeof(rhba->port_list);
+
+ count = 0;
+ len += sizeof(rhba->hba_attr_blk.attr_count);
+
+ /*
+ * fill out the invididual entries of the HBA attrib Block
+ */
+ curr_ptr = (u8 *) &rhba->hba_attr_blk.hba_attr;
+
+ /*
+ * Node Name
+ */
+ attr = (struct fdmi_attr_s *) curr_ptr;
+ attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_NODENAME);
+ attr->len = sizeof(wwn_t);
+ memcpy(attr->value, &bfa_fcs_lport_get_nwwn(port), attr->len);
+ curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+ len += attr->len;
+ count++;
+ attr->len =
+ bfa_os_htons(attr->len + sizeof(attr->type) +
+ sizeof(attr->len));
+
+ /*
+ * Manufacturer
+ */
+ attr = (struct fdmi_attr_s *) curr_ptr;
+ attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_MANUFACTURER);
+ attr->len = (u16) strlen(fcs_hba_attr->manufacturer);
+ memcpy(attr->value, fcs_hba_attr->manufacturer, attr->len);
+ attr->len = fc_roundup(attr->len, sizeof(u32)); /* variable
+ *fields need
+ *to be 4 byte
+ *aligned */
+ curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+ len += attr->len;
+ count++;
+ attr->len =
+ bfa_os_htons(attr->len + sizeof(attr->type) +
+ sizeof(attr->len));
+
+ /*
+ * Serial Number
+ */
+ attr = (struct fdmi_attr_s *) curr_ptr;
+ attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_SERIALNUM);
+ attr->len = (u16) strlen(fcs_hba_attr->serial_num);
+ memcpy(attr->value, fcs_hba_attr->serial_num, attr->len);
+ attr->len = fc_roundup(attr->len, sizeof(u32)); /* variable
+ *fields need
+ *to be 4 byte
+ *aligned */
+ curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+ len += attr->len;
+ count++;
+ attr->len =
+ bfa_os_htons(attr->len + sizeof(attr->type) +
+ sizeof(attr->len));
+
+ /*
+ * Model
+ */
+ attr = (struct fdmi_attr_s *) curr_ptr;
+ attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_MODEL);
+ attr->len = (u16) strlen(fcs_hba_attr->model);
+ memcpy(attr->value, fcs_hba_attr->model, attr->len);
+ attr->len = fc_roundup(attr->len, sizeof(u32)); /* variable
+ *fields need
+ *to be 4 byte
+ *aligned */
+ curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+ len += attr->len;
+ count++;
+ attr->len =
+ bfa_os_htons(attr->len + sizeof(attr->type) +
+ sizeof(attr->len));
+
+ /*
+ * Model Desc
+ */
+ attr = (struct fdmi_attr_s *) curr_ptr;
+ attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_MODEL_DESC);
+ attr->len = (u16) strlen(fcs_hba_attr->model_desc);
+ memcpy(attr->value, fcs_hba_attr->model_desc, attr->len);
+ attr->len = fc_roundup(attr->len, sizeof(u32)); /* variable
+ *fields need
+ *to be 4 byte
+ *aligned */
+ curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+ len += attr->len;
+ count++;
+ attr->len =
+ bfa_os_htons(attr->len + sizeof(attr->type) +
+ sizeof(attr->len));
+
+ /*
+ * H/W Version
+ */
+ if (fcs_hba_attr->hw_version[0] != '\0') {
+ attr = (struct fdmi_attr_s *) curr_ptr;
+ attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_HW_VERSION);
+ attr->len = (u16) strlen(fcs_hba_attr->hw_version);
+ memcpy(attr->value, fcs_hba_attr->hw_version, attr->len);
+ attr->len = fc_roundup(attr->len, sizeof(u32)); /* variable
+ *fields need
+ *to be 4 byte
+ *aligned */
+ curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+ len += attr->len;
+ count++;
+ attr->len =
+ bfa_os_htons(attr->len + sizeof(attr->type) +
+ sizeof(attr->len));
+ }
+
+ /*
+ * Driver Version
+ */
+ attr = (struct fdmi_attr_s *) curr_ptr;
+ attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_DRIVER_VERSION);
+ attr->len = (u16) strlen(fcs_hba_attr->driver_version);
+ memcpy(attr->value, fcs_hba_attr->driver_version, attr->len);
+ attr->len = fc_roundup(attr->len, sizeof(u32)); /* variable
+ *fields need
+ *to be 4 byte
+ *aligned */
+ curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+ len += attr->len;;
+ count++;
+ attr->len =
+ bfa_os_htons(attr->len + sizeof(attr->type) +
+ sizeof(attr->len));
+
+ /*
+ * Option Rom Version
+ */
+ if (fcs_hba_attr->option_rom_ver[0] != '\0') {
+ attr = (struct fdmi_attr_s *) curr_ptr;
+ attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_ROM_VERSION);
+ attr->len = (u16) strlen(fcs_hba_attr->option_rom_ver);
+ memcpy(attr->value, fcs_hba_attr->option_rom_ver, attr->len);
+ attr->len = fc_roundup(attr->len, sizeof(u32)); /* variable
+ *fields need
+ *to be 4 byte
+ *aligned */
+ curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+ len += attr->len;
+ count++;
+ attr->len =
+ bfa_os_htons(attr->len + sizeof(attr->type) +
+ sizeof(attr->len));
+ }
+
+ /*
+ * f/w Version = driver version
+ */
+ attr = (struct fdmi_attr_s *) curr_ptr;
+ attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_FW_VERSION);
+ attr->len = (u16) strlen(fcs_hba_attr->driver_version);
+ memcpy(attr->value, fcs_hba_attr->driver_version, attr->len);
+ attr->len = fc_roundup(attr->len, sizeof(u32)); /* variable
+ *fields need
+ *to be 4 byte
+ *aligned */
+ curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+ len += attr->len;
+ count++;
+ attr->len =
+ bfa_os_htons(attr->len + sizeof(attr->type) +
+ sizeof(attr->len));
+
+ /*
+ * OS Name
+ */
+ if (fcs_hba_attr->os_name[0] != '\0') {
+ attr = (struct fdmi_attr_s *) curr_ptr;
+ attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_OS_NAME);
+ attr->len = (u16) strlen(fcs_hba_attr->os_name);
+ memcpy(attr->value, fcs_hba_attr->os_name, attr->len);
+ attr->len = fc_roundup(attr->len, sizeof(u32)); /* variable
+ *fields need
+ *to be 4 byte
+ *aligned */
+ curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+ len += attr->len;
+ count++;
+ attr->len =
+ bfa_os_htons(attr->len + sizeof(attr->type) +
+ sizeof(attr->len));
+ }
+
+ /*
+ * MAX_CT_PAYLOAD
+ */
+ attr = (struct fdmi_attr_s *) curr_ptr;
+ attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_MAX_CT);
+ attr->len = sizeof(fcs_hba_attr->max_ct_pyld);
+ memcpy(attr->value, &fcs_hba_attr->max_ct_pyld, attr->len);
+ len += attr->len;
+ count++;
+ attr->len =
+ bfa_os_htons(attr->len + sizeof(attr->type) +
+ sizeof(attr->len));
+
+ /*
+ * Update size of payload
+ */
+ len += ((sizeof(attr->type) +
+ sizeof(attr->len)) * count);
+
+ rhba->hba_attr_blk.attr_count = bfa_os_htonl(count);
+ return len;
+}
+
+static void
+bfa_fcs_lport_fdmi_rhba_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+ void *cbarg, bfa_status_t req_status,
+ u32 rsp_len, u32 resid_len,
+ struct fchs_s *rsp_fchs)
+{
+ struct bfa_fcs_lport_fdmi_s *fdmi =
+ (struct bfa_fcs_lport_fdmi_s *) cbarg;
+ struct bfa_fcs_lport_s *port = fdmi->ms->port;
+ struct ct_hdr_s *cthdr = NULL;
+
+ bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+ /*
+ * Sanity Checks
+ */
+ if (req_status != BFA_STATUS_OK) {
+ bfa_trc(port->fcs, req_status);
+ bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
+ return;
+ }
+
+ cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
+ cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
+
+ if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
+ bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
+ return;
+ }
+
+ bfa_trc(port->fcs, cthdr->reason_code);
+ bfa_trc(port->fcs, cthdr->exp_code);
+ bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
+}
+
+/**
+* RPRT : Register Port
+ */
+static void
+bfa_fcs_lport_fdmi_send_rprt(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+ struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg;
+ struct bfa_fcs_lport_s *port = fdmi->ms->port;
+ struct fchs_s fchs;
+ u16 len, attr_len;
+ struct bfa_fcxp_s *fcxp;
+ u8 *pyld;
+
+ bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+ fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+ if (!fcxp) {
+ bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
+ bfa_fcs_lport_fdmi_send_rprt, fdmi);
+ return;
+ }
+ fdmi->fcxp = fcxp;
+
+ pyld = bfa_fcxp_get_reqbuf(fcxp);
+ bfa_os_memset(pyld, 0, FC_MAX_PDUSZ);
+
+ len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
+ FDMI_RPRT);
+
+ attr_len =
+ bfa_fcs_lport_fdmi_build_rprt_pyld(fdmi,
+ (u8 *) ((struct ct_hdr_s *) pyld
+ + 1));
+
+ bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+ FC_CLASS_3, len + attr_len, &fchs,
+ bfa_fcs_lport_fdmi_rprt_response, (void *)fdmi,
+ FC_MAX_PDUSZ, FC_FCCT_TOV);
+
+ bfa_sm_send_event(fdmi, FDMISM_EVENT_RPRT_SENT);
+}
+
+/**
+ * This routine builds Port Attribute Block that used in RPA, RPRT commands.
+ */
+static u16
+bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *fdmi,
+ u8 *pyld)
+{
+ struct bfa_fcs_fdmi_port_attr_s fcs_port_attr;
+ struct fdmi_port_attr_s *port_attrib = (struct fdmi_port_attr_s *) pyld;
+ struct fdmi_attr_s *attr;
+ u8 *curr_ptr;
+ u16 len;
+ u8 count = 0;
+
+ /*
+ * get port attributes
+ */
+ bfa_fcs_fdmi_get_portattr(fdmi, &fcs_port_attr);
+
+ len = sizeof(port_attrib->attr_count);
+
+ /*
+ * fill out the invididual entries
+ */
+ curr_ptr = (u8 *) &port_attrib->port_attr;
+
+ /*
+ * FC4 Types
+ */
+ attr = (struct fdmi_attr_s *) curr_ptr;
+ attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_FC4_TYPES);
+ attr->len = sizeof(fcs_port_attr.supp_fc4_types);
+ memcpy(attr->value, fcs_port_attr.supp_fc4_types, attr->len);
+ curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+ len += attr->len;
+ ++count;
+ attr->len =
+ bfa_os_htons(attr->len + sizeof(attr->type) +
+ sizeof(attr->len));
+
+ /*
+ * Supported Speed
+ */
+ attr = (struct fdmi_attr_s *) curr_ptr;
+ attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_SUPP_SPEED);
+ attr->len = sizeof(fcs_port_attr.supp_speed);
+ memcpy(attr->value, &fcs_port_attr.supp_speed, attr->len);
+ curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+ len += attr->len;
+ ++count;
+ attr->len =
+ bfa_os_htons(attr->len + sizeof(attr->type) +
+ sizeof(attr->len));
+
+ /*
+ * current Port Speed
+ */
+ attr = (struct fdmi_attr_s *) curr_ptr;
+ attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_PORT_SPEED);
+ attr->len = sizeof(fcs_port_attr.curr_speed);
+ memcpy(attr->value, &fcs_port_attr.curr_speed, attr->len);
+ curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+ len += attr->len;
+ ++count;
+ attr->len =
+ bfa_os_htons(attr->len + sizeof(attr->type) +
+ sizeof(attr->len));
+
+ /*
+ * max frame size
+ */
+ attr = (struct fdmi_attr_s *) curr_ptr;
+ attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_FRAME_SIZE);
+ attr->len = sizeof(fcs_port_attr.max_frm_size);
+ memcpy(attr->value, &fcs_port_attr.max_frm_size, attr->len);
+ curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+ len += attr->len;
+ ++count;
+ attr->len =
+ bfa_os_htons(attr->len + sizeof(attr->type) +
+ sizeof(attr->len));
+
+ /*
+ * OS Device Name
+ */
+ if (fcs_port_attr.os_device_name[0] != '\0') {
+ attr = (struct fdmi_attr_s *) curr_ptr;
+ attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_DEV_NAME);
+ attr->len = (u16) strlen(fcs_port_attr.os_device_name);
+ memcpy(attr->value, fcs_port_attr.os_device_name, attr->len);
+ attr->len = fc_roundup(attr->len, sizeof(u32)); /* variable
+ *fields need
+ *to be 4 byte
+ *aligned */
+ curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+ len += attr->len;
+ ++count;
+ attr->len =
+ bfa_os_htons(attr->len + sizeof(attr->type) +
+ sizeof(attr->len));
+ }
+ /*
+ * Host Name
+ */
+ if (fcs_port_attr.host_name[0] != '\0') {
+ attr = (struct fdmi_attr_s *) curr_ptr;
+ attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_HOST_NAME);
+ attr->len = (u16) strlen(fcs_port_attr.host_name);
+ memcpy(attr->value, fcs_port_attr.host_name, attr->len);
+ attr->len = fc_roundup(attr->len, sizeof(u32)); /* variable
+ *fields need
+ *to be 4 byte
+ *aligned */
+ curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+ len += attr->len;
+ ++count;
+ attr->len =
+ bfa_os_htons(attr->len + sizeof(attr->type) +
+ sizeof(attr->len));
+ }
+
+ /*
+ * Update size of payload
+ */
+ port_attrib->attr_count = bfa_os_htonl(count);
+ len += ((sizeof(attr->type) +
+ sizeof(attr->len)) * count);
+ return len;
+}
+
+static u16
+bfa_fcs_lport_fdmi_build_rprt_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
+{
+ struct bfa_fcs_lport_s *port = fdmi->ms->port;
+ struct fdmi_rprt_s *rprt = (struct fdmi_rprt_s *) pyld;
+ u16 len;
+
+ rprt->hba_id = bfa_fcs_lport_get_pwwn(bfa_fcs_get_base_port(port->fcs));
+ rprt->port_name = bfa_fcs_lport_get_pwwn(port);
+
+ len = bfa_fcs_lport_fdmi_build_portattr_block(fdmi,
+ (u8 *) &rprt->port_attr_blk);
+
+ len += sizeof(rprt->hba_id) + sizeof(rprt->port_name);
+
+ return len;
+}
+
+static void
+bfa_fcs_lport_fdmi_rprt_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+ void *cbarg, bfa_status_t req_status,
+ u32 rsp_len, u32 resid_len,
+ struct fchs_s *rsp_fchs)
+{
+ struct bfa_fcs_lport_fdmi_s *fdmi =
+ (struct bfa_fcs_lport_fdmi_s *) cbarg;
+ struct bfa_fcs_lport_s *port = fdmi->ms->port;
+ struct ct_hdr_s *cthdr = NULL;
+
+ bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+ /*
+ * Sanity Checks
+ */
+ if (req_status != BFA_STATUS_OK) {
+ bfa_trc(port->fcs, req_status);
+ bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
+ return;
+ }
+
+ cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
+ cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
+
+ if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
+ bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
+ return;
+ }
+
+ bfa_trc(port->fcs, cthdr->reason_code);
+ bfa_trc(port->fcs, cthdr->exp_code);
+ bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
+}
+
+/**
+* RPA : Register Port Attributes.
+ */
+static void
+bfa_fcs_lport_fdmi_send_rpa(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+ struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg;
+ struct bfa_fcs_lport_s *port = fdmi->ms->port;
+ struct fchs_s fchs;
+ u16 len, attr_len;
+ struct bfa_fcxp_s *fcxp;
+ u8 *pyld;
+
+ bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+ fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+ if (!fcxp) {
+ bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
+ bfa_fcs_lport_fdmi_send_rpa, fdmi);
+ return;
+ }
+ fdmi->fcxp = fcxp;
+
+ pyld = bfa_fcxp_get_reqbuf(fcxp);
+ bfa_os_memset(pyld, 0, FC_MAX_PDUSZ);
+
+ len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
+ FDMI_RPA);
+
+ attr_len =
+ bfa_fcs_lport_fdmi_build_rpa_pyld(fdmi,
+ (u8 *) ((struct ct_hdr_s *) pyld
+ + 1));
+
+ bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+ FC_CLASS_3, len + attr_len, &fchs,
+ bfa_fcs_lport_fdmi_rpa_response, (void *)fdmi,
+ FC_MAX_PDUSZ, FC_FCCT_TOV);
+
+ bfa_sm_send_event(fdmi, FDMISM_EVENT_RPA_SENT);
+}
+
+static u16
+bfa_fcs_lport_fdmi_build_rpa_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
+{
+ struct bfa_fcs_lport_s *port = fdmi->ms->port;
+ struct fdmi_rpa_s *rpa = (struct fdmi_rpa_s *) pyld;
+ u16 len;
+
+ rpa->port_name = bfa_fcs_lport_get_pwwn(port);
+
+ len = bfa_fcs_lport_fdmi_build_portattr_block(fdmi,
+ (u8 *) &rpa->port_attr_blk);
+
+ len += sizeof(rpa->port_name);
+
+ return len;
+}
+
+static void
+bfa_fcs_lport_fdmi_rpa_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+ void *cbarg, bfa_status_t req_status, u32 rsp_len,
+ u32 resid_len, struct fchs_s *rsp_fchs)
+{
+ struct bfa_fcs_lport_fdmi_s *fdmi =
+ (struct bfa_fcs_lport_fdmi_s *) cbarg;
+ struct bfa_fcs_lport_s *port = fdmi->ms->port;
+ struct ct_hdr_s *cthdr = NULL;
+
+ bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+ /*
+ * Sanity Checks
+ */
+ if (req_status != BFA_STATUS_OK) {
+ bfa_trc(port->fcs, req_status);
+ bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
+ return;
+ }
+
+ cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
+ cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
+
+ if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
+ bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
+ return;
+ }
+
+ bfa_trc(port->fcs, cthdr->reason_code);
+ bfa_trc(port->fcs, cthdr->exp_code);
+ bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
+}
+
+static void
+bfa_fcs_lport_fdmi_timeout(void *arg)
+{
+ struct bfa_fcs_lport_fdmi_s *fdmi = (struct bfa_fcs_lport_fdmi_s *) arg;
+
+ bfa_sm_send_event(fdmi, FDMISM_EVENT_TIMEOUT);
+}
+
+void
+bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
+ struct bfa_fcs_fdmi_hba_attr_s *hba_attr)
+{
+ struct bfa_fcs_lport_s *port = fdmi->ms->port;
+ struct bfa_fcs_driver_info_s *driver_info = &port->fcs->driver_info;
+
+ bfa_os_memset(hba_attr, 0, sizeof(struct bfa_fcs_fdmi_hba_attr_s));
+
+ bfa_ioc_get_adapter_manufacturer(&port->fcs->bfa->ioc,
+ hba_attr->manufacturer);
+ bfa_ioc_get_adapter_serial_num(&port->fcs->bfa->ioc,
+ hba_attr->serial_num);
+ bfa_ioc_get_adapter_model(&port->fcs->bfa->ioc,
+ hba_attr->model);
+ bfa_ioc_get_adapter_model(&port->fcs->bfa->ioc,
+ hba_attr->model_desc);
+ bfa_ioc_get_pci_chip_rev(&port->fcs->bfa->ioc,
+ hba_attr->hw_version);
+ bfa_ioc_get_adapter_optrom_ver(&port->fcs->bfa->ioc,
+ hba_attr->option_rom_ver);
+ bfa_ioc_get_adapter_fw_ver(&port->fcs->bfa->ioc,
+ hba_attr->fw_version);
+
+ strncpy(hba_attr->driver_version, (char *)driver_info->version,
+ sizeof(hba_attr->driver_version));
+
+ strncpy(hba_attr->os_name, driver_info->host_os_name,
+ sizeof(hba_attr->os_name));
+
+ /*
+ * If there is a patch level, append it
+ * to the os name along with a separator
+ */
+ if (driver_info->host_os_patch[0] != '\0') {
+ strncat(hba_attr->os_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
+ sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
+ strncat(hba_attr->os_name, driver_info->host_os_patch,
+ sizeof(driver_info->host_os_patch));
+ }
+
+ hba_attr->max_ct_pyld = bfa_os_htonl(FC_MAX_PDUSZ);
+}
+
+void
+bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
+ struct bfa_fcs_fdmi_port_attr_s *port_attr)
+{
+ struct bfa_fcs_lport_s *port = fdmi->ms->port;
+ struct bfa_fcs_driver_info_s *driver_info = &port->fcs->driver_info;
+ struct bfa_port_attr_s pport_attr;
+
+ bfa_os_memset(port_attr, 0, sizeof(struct bfa_fcs_fdmi_port_attr_s));
+
+ /*
+ * get pport attributes from hal
+ */
+ bfa_fcport_get_attr(port->fcs->bfa, &pport_attr);
+
+ /*
+ * get FC4 type Bitmask
+ */
+ fc_get_fc4type_bitmask(FC_TYPE_FCP, port_attr->supp_fc4_types);
+
+ /*
+ * Supported Speeds
+ */
+ port_attr->supp_speed = bfa_os_htonl(BFA_FCS_FDMI_SUPORTED_SPEEDS);
+
+ /*
+ * Current Speed
+ */
+ port_attr->curr_speed = bfa_os_htonl(pport_attr.speed);
+
+ /*
+ * Max PDU Size.
+ */
+ port_attr->max_frm_size = bfa_os_htonl(FC_MAX_PDUSZ);
+
+ /*
+ * OS device Name
+ */
+ strncpy(port_attr->os_device_name, (char *)driver_info->os_device_name,
+ sizeof(port_attr->os_device_name));
+
+ /*
+ * Host name
+ */
+ strncpy(port_attr->host_name, (char *)driver_info->host_machine_name,
+ sizeof(port_attr->host_name));
+
+}
+
+
+void
+bfa_fcs_lport_fdmi_init(struct bfa_fcs_lport_ms_s *ms)
+{
+ struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
+
+ fdmi->ms = ms;
+ if (ms->port->fcs->fdmi_enabled)
+ bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
+ else
+ bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_disabled);
+}
+
+void
+bfa_fcs_lport_fdmi_offline(struct bfa_fcs_lport_ms_s *ms)
+{
+ struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
+
+ fdmi->ms = ms;
+ bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_OFFLINE);
+}
+
+void
+bfa_fcs_lport_fdmi_online(struct bfa_fcs_lport_ms_s *ms)
+{
+ struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
+
+ fdmi->ms = ms;
+ bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_ONLINE);
+}
+
+#define BFA_FCS_MS_CMD_MAX_RETRIES 2
+
+/*
+ * forward declarations
+ */
+static void bfa_fcs_lport_ms_send_plogi(void *ms_cbarg,
+ struct bfa_fcxp_s *fcxp_alloced);
+static void bfa_fcs_lport_ms_timeout(void *arg);
+static void bfa_fcs_lport_ms_plogi_response(void *fcsarg,
+ struct bfa_fcxp_s *fcxp,
+ void *cbarg,
+ bfa_status_t req_status,
+ u32 rsp_len,
+ u32 resid_len,
+ struct fchs_s *rsp_fchs);
+
+static void bfa_fcs_lport_ms_send_gmal(void *ms_cbarg,
+ struct bfa_fcxp_s *fcxp_alloced);
+static void bfa_fcs_lport_ms_gmal_response(void *fcsarg,
+ struct bfa_fcxp_s *fcxp,
+ void *cbarg,
+ bfa_status_t req_status,
+ u32 rsp_len,
+ u32 resid_len,
+ struct fchs_s *rsp_fchs);
+static void bfa_fcs_lport_ms_send_gfn(void *ms_cbarg,
+ struct bfa_fcxp_s *fcxp_alloced);
+static void bfa_fcs_lport_ms_gfn_response(void *fcsarg,
+ struct bfa_fcxp_s *fcxp,
+ void *cbarg,
+ bfa_status_t req_status,
+ u32 rsp_len,
+ u32 resid_len,
+ struct fchs_s *rsp_fchs);
+/**
+ * fcs_ms_sm FCS MS state machine
+ */
+
+/**
+ * MS State Machine events
+ */
+enum port_ms_event {
+ MSSM_EVENT_PORT_ONLINE = 1,
+ MSSM_EVENT_PORT_OFFLINE = 2,
+ MSSM_EVENT_RSP_OK = 3,
+ MSSM_EVENT_RSP_ERROR = 4,
+ MSSM_EVENT_TIMEOUT = 5,
+ MSSM_EVENT_FCXP_SENT = 6,
+ MSSM_EVENT_PORT_FABRIC_RSCN = 7
+};
+
+static void bfa_fcs_lport_ms_sm_offline(struct bfa_fcs_lport_ms_s *ms,
+ enum port_ms_event event);
+static void bfa_fcs_lport_ms_sm_plogi_sending(struct bfa_fcs_lport_ms_s *ms,
+ enum port_ms_event event);
+static void bfa_fcs_lport_ms_sm_plogi(struct bfa_fcs_lport_ms_s *ms,
+ enum port_ms_event event);
+static void bfa_fcs_lport_ms_sm_plogi_retry(struct bfa_fcs_lport_ms_s *ms,
+ enum port_ms_event event);
+static void bfa_fcs_lport_ms_sm_gmal_sending(struct bfa_fcs_lport_ms_s *ms,
+ enum port_ms_event event);
+static void bfa_fcs_lport_ms_sm_gmal(struct bfa_fcs_lport_ms_s *ms,
+ enum port_ms_event event);
+static void bfa_fcs_lport_ms_sm_gmal_retry(struct bfa_fcs_lport_ms_s *ms,
+ enum port_ms_event event);
+static void bfa_fcs_lport_ms_sm_gfn_sending(struct bfa_fcs_lport_ms_s *ms,
+ enum port_ms_event event);
+static void bfa_fcs_lport_ms_sm_gfn(struct bfa_fcs_lport_ms_s *ms,
+ enum port_ms_event event);
+static void bfa_fcs_lport_ms_sm_gfn_retry(struct bfa_fcs_lport_ms_s *ms,
+ enum port_ms_event event);
+static void bfa_fcs_lport_ms_sm_online(struct bfa_fcs_lport_ms_s *ms,
+ enum port_ms_event event);
+/**
+ * Start in offline state - awaiting NS to send start.
+ */
+static void
+bfa_fcs_lport_ms_sm_offline(struct bfa_fcs_lport_ms_s *ms,
+ enum port_ms_event event)
+{
+ bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
+ bfa_trc(ms->port->fcs, event);
+
+ switch (event) {
+ case MSSM_EVENT_PORT_ONLINE:
+ bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_sending);
+ bfa_fcs_lport_ms_send_plogi(ms, NULL);
+ break;
+
+ case MSSM_EVENT_PORT_OFFLINE:
+ break;
+
+ default:
+ bfa_sm_fault(ms->port->fcs, event);
+ }
+}
+
+static void
+bfa_fcs_lport_ms_sm_plogi_sending(struct bfa_fcs_lport_ms_s *ms,
+ enum port_ms_event event)
+{
+ bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
+ bfa_trc(ms->port->fcs, event);
+
+ switch (event) {
+ case MSSM_EVENT_FCXP_SENT:
+ bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi);
+ break;
+
+ case MSSM_EVENT_PORT_OFFLINE:
+ bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
+ bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
+ &ms->fcxp_wqe);
+ break;
+
+ default:
+ bfa_sm_fault(ms->port->fcs, event);
+ }
+}
+
+static void
+bfa_fcs_lport_ms_sm_plogi(struct bfa_fcs_lport_ms_s *ms,
+ enum port_ms_event event)
+{
+ bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
+ bfa_trc(ms->port->fcs, event);
+
+ switch (event) {
+ case MSSM_EVENT_RSP_ERROR:
+ /*
+ * Start timer for a delayed retry
+ */
+ bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_retry);
+ ms->port->stats.ms_retries++;
+ bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
+ &ms->timer, bfa_fcs_lport_ms_timeout, ms,
+ BFA_FCS_RETRY_TIMEOUT);
+ break;
+
+ case MSSM_EVENT_RSP_OK:
+ /*
+ * since plogi is done, now invoke MS related sub-modules
+ */
+ bfa_fcs_lport_fdmi_online(ms);
+
+ /**
+ * if this is a Vport, go to online state.
+ */
+ if (ms->port->vport) {
+ bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
+ break;
+ }
+
+ /*
+ * For a base port we need to get the
+ * switch's IP address.
+ */
+ bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_sending);
+ bfa_fcs_lport_ms_send_gmal(ms, NULL);
+ break;
+
+ case MSSM_EVENT_PORT_OFFLINE:
+ bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
+ bfa_fcxp_discard(ms->fcxp);
+ break;
+
+ default:
+ bfa_sm_fault(ms->port->fcs, event);
+ }
+}
+
+static void
+bfa_fcs_lport_ms_sm_plogi_retry(struct bfa_fcs_lport_ms_s *ms,
+ enum port_ms_event event)
+{
+ bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
+ bfa_trc(ms->port->fcs, event);
+
+ switch (event) {
+ case MSSM_EVENT_TIMEOUT:
+ /*
+ * Retry Timer Expired. Re-send
+ */
+ bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_sending);
+ bfa_fcs_lport_ms_send_plogi(ms, NULL);
+ break;
+
+ case MSSM_EVENT_PORT_OFFLINE:
+ bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
+ bfa_timer_stop(&ms->timer);
+ break;
+
+ default:
+ bfa_sm_fault(ms->port->fcs, event);
+ }
+}
+
+static void
+bfa_fcs_lport_ms_sm_online(struct bfa_fcs_lport_ms_s *ms,
+ enum port_ms_event event)
+{
+ bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
+ bfa_trc(ms->port->fcs, event);
+
+ switch (event) {
+ case MSSM_EVENT_PORT_OFFLINE:
+ bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
+ break;
+
+ case MSSM_EVENT_PORT_FABRIC_RSCN:
+ bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
+ ms->retry_cnt = 0;
+ bfa_fcs_lport_ms_send_gfn(ms, NULL);
+ break;
+
+ default:
+ bfa_sm_fault(ms->port->fcs, event);
+ }
+}
+
+static void
+bfa_fcs_lport_ms_sm_gmal_sending(struct bfa_fcs_lport_ms_s *ms,
+ enum port_ms_event event)
+{
+ bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
+ bfa_trc(ms->port->fcs, event);
+
+ switch (event) {
+ case MSSM_EVENT_FCXP_SENT:
+ bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal);
+ break;
+
+ case MSSM_EVENT_PORT_OFFLINE:
+ bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
+ bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
+ &ms->fcxp_wqe);
+ break;
+
+ default:
+ bfa_sm_fault(ms->port->fcs, event);
+ }
+}
+
+static void
+bfa_fcs_lport_ms_sm_gmal(struct bfa_fcs_lport_ms_s *ms,
+ enum port_ms_event event)
+{
+ bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
+ bfa_trc(ms->port->fcs, event);
+
+ switch (event) {
+ case MSSM_EVENT_RSP_ERROR:
+ /*
+ * Start timer for a delayed retry
+ */
+ if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
+ bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_retry);
+ ms->port->stats.ms_retries++;
+ bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
+ &ms->timer, bfa_fcs_lport_ms_timeout, ms,
+ BFA_FCS_RETRY_TIMEOUT);
+ } else {
+ bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
+ bfa_fcs_lport_ms_send_gfn(ms, NULL);
+ ms->retry_cnt = 0;
+ }
+ break;
+
+ case MSSM_EVENT_RSP_OK:
+ bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
+ bfa_fcs_lport_ms_send_gfn(ms, NULL);
+ break;
+
+ case MSSM_EVENT_PORT_OFFLINE:
+ bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
+ bfa_fcxp_discard(ms->fcxp);
+ break;
+
+ default:
+ bfa_sm_fault(ms->port->fcs, event);
+ }
+}
+
+static void
+bfa_fcs_lport_ms_sm_gmal_retry(struct bfa_fcs_lport_ms_s *ms,
+ enum port_ms_event event)
+{
+ bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
+ bfa_trc(ms->port->fcs, event);
+
+ switch (event) {
+ case MSSM_EVENT_TIMEOUT:
+ /*
+ * Retry Timer Expired. Re-send
+ */
+ bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_sending);
+ bfa_fcs_lport_ms_send_gmal(ms, NULL);
+ break;
+
+ case MSSM_EVENT_PORT_OFFLINE:
+ bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
+ bfa_timer_stop(&ms->timer);
+ break;
+
+ default:
+ bfa_sm_fault(ms->port->fcs, event);
+ }
+}
+/**
+ * ms_pvt MS local functions
+ */
+
+static void
+bfa_fcs_lport_ms_send_gmal(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+ struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
+ bfa_fcs_lport_t *port = ms->port;
+ struct fchs_s fchs;
+ int len;
+ struct bfa_fcxp_s *fcxp;
+
+ bfa_trc(port->fcs, port->pid);
+
+ fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+ if (!fcxp) {
+ bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
+ bfa_fcs_lport_ms_send_gmal, ms);
+ return;
+ }
+ ms->fcxp = fcxp;
+
+ len = fc_gmal_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+ bfa_fcs_lport_get_fcid(port),
+ bfa_lps_get_peer_nwwn(port->fabric->lps));
+
+ bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+ FC_CLASS_3, len, &fchs,
+ bfa_fcs_lport_ms_gmal_response, (void *)ms,
+ FC_MAX_PDUSZ, FC_FCCT_TOV);
+
+ bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
+}
+
+static void
+bfa_fcs_lport_ms_gmal_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+ void *cbarg, bfa_status_t req_status,
+ u32 rsp_len, u32 resid_len,
+ struct fchs_s *rsp_fchs)
+{
+ struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
+ bfa_fcs_lport_t *port = ms->port;
+ struct ct_hdr_s *cthdr = NULL;
+ struct fcgs_gmal_resp_s *gmal_resp;
+ struct fcgs_gmal_entry_s *gmal_entry;
+ u32 num_entries;
+ u8 *rsp_str;
+
+ bfa_trc(port->fcs, req_status);
+ bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+ /*
+ * Sanity Checks
+ */
+ if (req_status != BFA_STATUS_OK) {
+ bfa_trc(port->fcs, req_status);
+ bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
+ return;
+ }
+
+ cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
+ cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
+
+ if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
+ gmal_resp = (struct fcgs_gmal_resp_s *)(cthdr + 1);
+
+ num_entries = bfa_os_ntohl(gmal_resp->ms_len);
+ if (num_entries == 0) {
+ bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
+ return;
+ }
+ /*
+ * The response could contain multiple Entries.
+ * Entries for SNMP interface, etc.
+ * We look for the entry with a telnet prefix.
+ * First "http://" entry refers to IP addr
+ */
+
+ gmal_entry = (struct fcgs_gmal_entry_s *)gmal_resp->ms_ma;
+ while (num_entries > 0) {
+ if (strncmp(gmal_entry->prefix,
+ CT_GMAL_RESP_PREFIX_HTTP,
+ sizeof(gmal_entry->prefix)) == 0) {
+
+ /*
+ * if the IP address is terminating with a '/',
+ * remove it.
+ * Byte 0 consists of the length of the string.
+ */
+ rsp_str = &(gmal_entry->prefix[0]);
+ if (rsp_str[gmal_entry->len-1] == '/')
+ rsp_str[gmal_entry->len-1] = 0;
+
+ /* copy IP Address to fabric */
+ strncpy(bfa_fcs_lport_get_fabric_ipaddr(port),
+ gmal_entry->ip_addr,
+ BFA_FCS_FABRIC_IPADDR_SZ);
+ break;
+ } else {
+ --num_entries;
+ ++gmal_entry;
+ }
+ }
+
+ bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
+ return;
+ }
+
+ bfa_trc(port->fcs, cthdr->reason_code);
+ bfa_trc(port->fcs, cthdr->exp_code);
+ bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
+}
+
+static void
+bfa_fcs_lport_ms_sm_gfn_sending(struct bfa_fcs_lport_ms_s *ms,
+ enum port_ms_event event)
+{
+ bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
+ bfa_trc(ms->port->fcs, event);
+
+ switch (event) {
+ case MSSM_EVENT_FCXP_SENT:
+ bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn);
+ break;
+
+ case MSSM_EVENT_PORT_OFFLINE:
+ bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
+ bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
+ &ms->fcxp_wqe);
+ break;
+
+ default:
+ bfa_sm_fault(ms->port->fcs, event);
+ }
+}
+
+static void
+bfa_fcs_lport_ms_sm_gfn(struct bfa_fcs_lport_ms_s *ms,
+ enum port_ms_event event)
+{
+ bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
+ bfa_trc(ms->port->fcs, event);
+
+ switch (event) {
+ case MSSM_EVENT_RSP_ERROR:
+ /*
+ * Start timer for a delayed retry
+ */
+ if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
+ bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_retry);
+ ms->port->stats.ms_retries++;
+ bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
+ &ms->timer, bfa_fcs_lport_ms_timeout, ms,
+ BFA_FCS_RETRY_TIMEOUT);
+ } else {
+ bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
+ ms->retry_cnt = 0;
+ }
+ break;
+
+ case MSSM_EVENT_RSP_OK:
+ bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
+ break;
+
+ case MSSM_EVENT_PORT_OFFLINE:
+ bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
+ bfa_fcxp_discard(ms->fcxp);
+ break;
+
+ default:
+ bfa_sm_fault(ms->port->fcs, event);
+ }
+}
+
+static void
+bfa_fcs_lport_ms_sm_gfn_retry(struct bfa_fcs_lport_ms_s *ms,
+ enum port_ms_event event)
+{
+ bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
+ bfa_trc(ms->port->fcs, event);
+
+ switch (event) {
+ case MSSM_EVENT_TIMEOUT:
+ /*
+ * Retry Timer Expired. Re-send
+ */
+ bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
+ bfa_fcs_lport_ms_send_gfn(ms, NULL);
+ break;
+
+ case MSSM_EVENT_PORT_OFFLINE:
+ bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
+ bfa_timer_stop(&ms->timer);
+ break;
+
+ default:
+ bfa_sm_fault(ms->port->fcs, event);
+ }
+}
+/**
+ * ms_pvt MS local functions
+ */
+
+static void
+bfa_fcs_lport_ms_send_gfn(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+ struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
+ bfa_fcs_lport_t *port = ms->port;
+ struct fchs_s fchs;
+ int len;
+ struct bfa_fcxp_s *fcxp;
+
+ bfa_trc(port->fcs, port->pid);
+
+ fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+ if (!fcxp) {
+ bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
+ bfa_fcs_lport_ms_send_gfn, ms);
+ return;
+ }
+ ms->fcxp = fcxp;
+
+ len = fc_gfn_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+ bfa_fcs_lport_get_fcid(port),
+ bfa_lps_get_peer_nwwn(port->fabric->lps));
+
+ bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+ FC_CLASS_3, len, &fchs,
+ bfa_fcs_lport_ms_gfn_response, (void *)ms,
+ FC_MAX_PDUSZ, FC_FCCT_TOV);
+
+ bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
+}
+
+static void
+bfa_fcs_lport_ms_gfn_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+ void *cbarg, bfa_status_t req_status, u32 rsp_len,
+ u32 resid_len, struct fchs_s *rsp_fchs)
+{
+ struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
+ bfa_fcs_lport_t *port = ms->port;
+ struct ct_hdr_s *cthdr = NULL;
+ wwn_t *gfn_resp;
+
+ bfa_trc(port->fcs, req_status);
+ bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+ /*
+ * Sanity Checks
+ */
+ if (req_status != BFA_STATUS_OK) {
+ bfa_trc(port->fcs, req_status);
+ bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
+ return;
+ }
+
+ cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
+ cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
+
+ if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
+ gfn_resp = (wwn_t *)(cthdr + 1);
+ /* check if it has actually changed */
+ if ((memcmp((void *)&bfa_fcs_lport_get_fabric_name(port),
+ gfn_resp, sizeof(wwn_t)) != 0)) {
+ bfa_fcs_fabric_set_fabric_name(port->fabric, *gfn_resp);
+ }
+ bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
+ return;
+ }
+
+ bfa_trc(port->fcs, cthdr->reason_code);
+ bfa_trc(port->fcs, cthdr->exp_code);
+ bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
+}
+
+/**
+ * ms_pvt MS local functions
+ */
+
+static void
+bfa_fcs_lport_ms_send_plogi(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+ struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
+ struct bfa_fcs_lport_s *port = ms->port;
+ struct fchs_s fchs;
+ int len;
+ struct bfa_fcxp_s *fcxp;
+
+ bfa_trc(port->fcs, port->pid);
+
+ fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+ if (!fcxp) {
+ port->stats.ms_plogi_alloc_wait++;
+ bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
+ bfa_fcs_lport_ms_send_plogi, ms);
+ return;
+ }
+ ms->fcxp = fcxp;
+
+ len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+ bfa_os_hton3b(FC_MGMT_SERVER),
+ bfa_fcs_lport_get_fcid(port), 0,
+ port->port_cfg.pwwn, port->port_cfg.nwwn,
+ bfa_fcport_get_maxfrsize(port->fcs->bfa));
+
+ bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+ FC_CLASS_3, len, &fchs,
+ bfa_fcs_lport_ms_plogi_response, (void *)ms,
+ FC_MAX_PDUSZ, FC_ELS_TOV);
+
+ port->stats.ms_plogi_sent++;
+ bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
+}
+
+static void
+bfa_fcs_lport_ms_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+ void *cbarg, bfa_status_t req_status,
+ u32 rsp_len, u32 resid_len, struct fchs_s *rsp_fchs)
+{
+ struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
+ struct bfa_fcs_lport_s *port = ms->port;
+ struct fc_els_cmd_s *els_cmd;
+ struct fc_ls_rjt_s *ls_rjt;
+
+ bfa_trc(port->fcs, req_status);
+ bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+ /*
+ * Sanity Checks
+ */
+ if (req_status != BFA_STATUS_OK) {
+ port->stats.ms_plogi_rsp_err++;
+ bfa_trc(port->fcs, req_status);
+ bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
+ return;
+ }
+
+ els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
+
+ switch (els_cmd->els_code) {
+
+ case FC_ELS_ACC:
+ if (rsp_len < sizeof(struct fc_logi_s)) {
+ bfa_trc(port->fcs, rsp_len);
+ port->stats.ms_plogi_acc_err++;
+ bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
+ break;
+ }
+ port->stats.ms_plogi_accepts++;
+ bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
+ break;
+
+ case FC_ELS_LS_RJT:
+ ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
+
+ bfa_trc(port->fcs, ls_rjt->reason_code);
+ bfa_trc(port->fcs, ls_rjt->reason_code_expl);
+
+ port->stats.ms_rejects++;
+ bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
+ break;
+
+ default:
+ port->stats.ms_plogi_unknown_rsp++;
+ bfa_trc(port->fcs, els_cmd->els_code);
+ bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
+ }
+}
+
+static void
+bfa_fcs_lport_ms_timeout(void *arg)
+{
+ struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) arg;
+
+ ms->port->stats.ms_timeouts++;
+ bfa_sm_send_event(ms, MSSM_EVENT_TIMEOUT);
+}
+
+
+void
+bfa_fcs_lport_ms_init(struct bfa_fcs_lport_s *port)
+{
+ struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
+
+ ms->port = port;
+ bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
+
+ /*
+ * Invoke init routines of sub modules.
+ */
+ bfa_fcs_lport_fdmi_init(ms);
+}
+
+void
+bfa_fcs_lport_ms_offline(struct bfa_fcs_lport_s *port)
+{
+ struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
+
+ ms->port = port;
+ bfa_sm_send_event(ms, MSSM_EVENT_PORT_OFFLINE);
+ bfa_fcs_lport_fdmi_offline(ms);
+}
+
+void
+bfa_fcs_lport_ms_online(struct bfa_fcs_lport_s *port)
+{
+ struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
+
+ ms->port = port;
+ bfa_sm_send_event(ms, MSSM_EVENT_PORT_ONLINE);
+}
+void
+bfa_fcs_lport_ms_fabric_rscn(struct bfa_fcs_lport_s *port)
+{
+ struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
+
+ /* todo. Handle this only when in Online state */
+ if (bfa_sm_cmp_state(ms, bfa_fcs_lport_ms_sm_online))
+ bfa_sm_send_event(ms, MSSM_EVENT_PORT_FABRIC_RSCN);
+}
+
+/**
+ * @page ns_sm_info VPORT NS State Machine
+ *
+ * @section ns_sm_interactions VPORT NS State Machine Interactions
+ *
+ * @section ns_sm VPORT NS State Machine
+ * img ns_sm.jpg
+ */
+
+/*
+ * forward declarations
+ */
+static void bfa_fcs_lport_ns_send_plogi(void *ns_cbarg,
+ struct bfa_fcxp_s *fcxp_alloced);
+static void bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg,
+ struct bfa_fcxp_s *fcxp_alloced);
+static void bfa_fcs_lport_ns_send_rft_id(void *ns_cbarg,
+ struct bfa_fcxp_s *fcxp_alloced);
+static void bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg,
+ struct bfa_fcxp_s *fcxp_alloced);
+static void bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg,
+ struct bfa_fcxp_s *fcxp_alloced);
+static void bfa_fcs_lport_ns_timeout(void *arg);
+static void bfa_fcs_lport_ns_plogi_response(void *fcsarg,
+ struct bfa_fcxp_s *fcxp,
+ void *cbarg,
+ bfa_status_t req_status,
+ u32 rsp_len,
+ u32 resid_len,
+ struct fchs_s *rsp_fchs);
+static void bfa_fcs_lport_ns_rspn_id_response(void *fcsarg,
+ struct bfa_fcxp_s *fcxp,
+ void *cbarg,
+ bfa_status_t req_status,
+ u32 rsp_len,
+ u32 resid_len,
+ struct fchs_s *rsp_fchs);
+static void bfa_fcs_lport_ns_rft_id_response(void *fcsarg,
+ struct bfa_fcxp_s *fcxp,
+ void *cbarg,
+ bfa_status_t req_status,
+ u32 rsp_len,
+ u32 resid_len,
+ struct fchs_s *rsp_fchs);
+static void bfa_fcs_lport_ns_rff_id_response(void *fcsarg,
+ struct bfa_fcxp_s *fcxp,
+ void *cbarg,
+ bfa_status_t req_status,
+ u32 rsp_len,
+ u32 resid_len,
+ struct fchs_s *rsp_fchs);
+static void bfa_fcs_lport_ns_gid_ft_response(void *fcsarg,
+ struct bfa_fcxp_s *fcxp,
+ void *cbarg,
+ bfa_status_t req_status,
+ u32 rsp_len,
+ u32 resid_len,
+ struct fchs_s *rsp_fchs);
+static void bfa_fcs_lport_ns_process_gidft_pids(
+ struct bfa_fcs_lport_s *port,
+ u32 *pid_buf, u32 n_pids);
+
+static void bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port);
+/**
+ * fcs_ns_sm FCS nameserver interface state machine
+ */
+
+/**
+ * VPort NS State Machine events
+ */
+enum vport_ns_event {
+ NSSM_EVENT_PORT_ONLINE = 1,
+ NSSM_EVENT_PORT_OFFLINE = 2,
+ NSSM_EVENT_PLOGI_SENT = 3,
+ NSSM_EVENT_RSP_OK = 4,
+ NSSM_EVENT_RSP_ERROR = 5,
+ NSSM_EVENT_TIMEOUT = 6,
+ NSSM_EVENT_NS_QUERY = 7,
+ NSSM_EVENT_RSPNID_SENT = 8,
+ NSSM_EVENT_RFTID_SENT = 9,
+ NSSM_EVENT_RFFID_SENT = 10,
+ NSSM_EVENT_GIDFT_SENT = 11,
+};
+
+static void bfa_fcs_lport_ns_sm_offline(struct bfa_fcs_lport_ns_s *ns,
+ enum vport_ns_event event);
+static void bfa_fcs_lport_ns_sm_plogi_sending(struct bfa_fcs_lport_ns_s *ns,
+ enum vport_ns_event event);
+static void bfa_fcs_lport_ns_sm_plogi(struct bfa_fcs_lport_ns_s *ns,
+ enum vport_ns_event event);
+static void bfa_fcs_lport_ns_sm_plogi_retry(struct bfa_fcs_lport_ns_s *ns,
+ enum vport_ns_event event);
+static void bfa_fcs_lport_ns_sm_sending_rspn_id(
+ struct bfa_fcs_lport_ns_s *ns,
+ enum vport_ns_event event);
+static void bfa_fcs_lport_ns_sm_rspn_id(struct bfa_fcs_lport_ns_s *ns,
+ enum vport_ns_event event);
+static void bfa_fcs_lport_ns_sm_rspn_id_retry(struct bfa_fcs_lport_ns_s *ns,
+ enum vport_ns_event event);
+static void bfa_fcs_lport_ns_sm_sending_rft_id(
+ struct bfa_fcs_lport_ns_s *ns,
+ enum vport_ns_event event);
+static void bfa_fcs_lport_ns_sm_rft_id_retry(struct bfa_fcs_lport_ns_s *ns,
+ enum vport_ns_event event);
+static void bfa_fcs_lport_ns_sm_rft_id(struct bfa_fcs_lport_ns_s *ns,
+ enum vport_ns_event event);
+static void bfa_fcs_lport_ns_sm_sending_rff_id(
+ struct bfa_fcs_lport_ns_s *ns,
+ enum vport_ns_event event);
+static void bfa_fcs_lport_ns_sm_rff_id_retry(struct bfa_fcs_lport_ns_s *ns,
+ enum vport_ns_event event);
+static void bfa_fcs_lport_ns_sm_rff_id(struct bfa_fcs_lport_ns_s *ns,
+ enum vport_ns_event event);
+static void bfa_fcs_lport_ns_sm_sending_gid_ft(
+ struct bfa_fcs_lport_ns_s *ns,
+ enum vport_ns_event event);
+static void bfa_fcs_lport_ns_sm_gid_ft(struct bfa_fcs_lport_ns_s *ns,
+ enum vport_ns_event event);
+static void bfa_fcs_lport_ns_sm_gid_ft_retry(struct bfa_fcs_lport_ns_s *ns,
+ enum vport_ns_event event);
+static void bfa_fcs_lport_ns_sm_online(struct bfa_fcs_lport_ns_s *ns,
+ enum vport_ns_event event);
+/**
+ * Start in offline state - awaiting linkup
+ */
+static void
+bfa_fcs_lport_ns_sm_offline(struct bfa_fcs_lport_ns_s *ns,
+ enum vport_ns_event event)
+{
+ bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+ bfa_trc(ns->port->fcs, event);
+
+ switch (event) {
+ case NSSM_EVENT_PORT_ONLINE:
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_sending);
+ bfa_fcs_lport_ns_send_plogi(ns, NULL);
+ break;
+
+ case NSSM_EVENT_PORT_OFFLINE:
+ break;
+
+ default:
+ bfa_sm_fault(ns->port->fcs, event);
+ }
+}
+
+static void
+bfa_fcs_lport_ns_sm_plogi_sending(struct bfa_fcs_lport_ns_s *ns,
+ enum vport_ns_event event)
+{
+ bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+ bfa_trc(ns->port->fcs, event);
+
+ switch (event) {
+ case NSSM_EVENT_PLOGI_SENT:
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi);
+ break;
+
+ case NSSM_EVENT_PORT_OFFLINE:
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+ bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
+ &ns->fcxp_wqe);
+ break;
+
+ default:
+ bfa_sm_fault(ns->port->fcs, event);
+ }
+}
+
+static void
+bfa_fcs_lport_ns_sm_plogi(struct bfa_fcs_lport_ns_s *ns,
+ enum vport_ns_event event)
+{
+ bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+ bfa_trc(ns->port->fcs, event);
+
+ switch (event) {
+ case NSSM_EVENT_RSP_ERROR:
+ /*
+ * Start timer for a delayed retry
+ */
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_retry);
+ ns->port->stats.ns_retries++;
+ bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
+ &ns->timer, bfa_fcs_lport_ns_timeout, ns,
+ BFA_FCS_RETRY_TIMEOUT);
+ break;
+
+ case NSSM_EVENT_RSP_OK:
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rspn_id);
+ bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
+ break;
+
+ case NSSM_EVENT_PORT_OFFLINE:
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+ bfa_fcxp_discard(ns->fcxp);
+ break;
+
+ default:
+ bfa_sm_fault(ns->port->fcs, event);
+ }
+}
+
+static void
+bfa_fcs_lport_ns_sm_plogi_retry(struct bfa_fcs_lport_ns_s *ns,
+ enum vport_ns_event event)
+{
+ bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+ bfa_trc(ns->port->fcs, event);
+
+ switch (event) {
+ case NSSM_EVENT_TIMEOUT:
+ /*
+ * Retry Timer Expired. Re-send
+ */
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_sending);
+ bfa_fcs_lport_ns_send_plogi(ns, NULL);
+ break;
+
+ case NSSM_EVENT_PORT_OFFLINE:
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+ bfa_timer_stop(&ns->timer);
+ break;
+
+ default:
+ bfa_sm_fault(ns->port->fcs, event);
+ }
+}
+
+static void
+bfa_fcs_lport_ns_sm_sending_rspn_id(struct bfa_fcs_lport_ns_s *ns,
+ enum vport_ns_event event)
+{
+ bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+ bfa_trc(ns->port->fcs, event);
+
+ switch (event) {
+ case NSSM_EVENT_RSPNID_SENT:
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rspn_id);
+ break;
+
+ case NSSM_EVENT_PORT_OFFLINE:
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+ bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
+ &ns->fcxp_wqe);
+ break;
+
+ default:
+ bfa_sm_fault(ns->port->fcs, event);
+ }
+}
+
+static void
+bfa_fcs_lport_ns_sm_rspn_id(struct bfa_fcs_lport_ns_s *ns,
+ enum vport_ns_event event)
+{
+ bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+ bfa_trc(ns->port->fcs, event);
+
+ switch (event) {
+ case NSSM_EVENT_RSP_ERROR:
+ /*
+ * Start timer for a delayed retry
+ */
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rspn_id_retry);
+ ns->port->stats.ns_retries++;
+ bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
+ &ns->timer, bfa_fcs_lport_ns_timeout, ns,
+ BFA_FCS_RETRY_TIMEOUT);
+ break;
+
+ case NSSM_EVENT_RSP_OK:
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rft_id);
+ bfa_fcs_lport_ns_send_rft_id(ns, NULL);
+ break;
+
+ case NSSM_EVENT_PORT_OFFLINE:
+ bfa_fcxp_discard(ns->fcxp);
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+ break;
+
+ default:
+ bfa_sm_fault(ns->port->fcs, event);
+ }
+}
+
+static void
+bfa_fcs_lport_ns_sm_rspn_id_retry(struct bfa_fcs_lport_ns_s *ns,
+ enum vport_ns_event event)
+{
+ bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+ bfa_trc(ns->port->fcs, event);
+
+ switch (event) {
+ case NSSM_EVENT_TIMEOUT:
+ /*
+ * Retry Timer Expired. Re-send
+ */
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rspn_id);
+ bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
+ break;
+
+ case NSSM_EVENT_PORT_OFFLINE:
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+ bfa_timer_stop(&ns->timer);
+ break;
+
+ default:
+ bfa_sm_fault(ns->port->fcs, event);
+ }
+}
+
+static void
+bfa_fcs_lport_ns_sm_sending_rft_id(struct bfa_fcs_lport_ns_s *ns,
+ enum vport_ns_event event)
+{
+ bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+ bfa_trc(ns->port->fcs, event);
+
+ switch (event) {
+ case NSSM_EVENT_RFTID_SENT:
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rft_id);
+ break;
+
+ case NSSM_EVENT_PORT_OFFLINE:
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+ bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
+ &ns->fcxp_wqe);
+ break;
+
+ default:
+ bfa_sm_fault(ns->port->fcs, event);
+ }
+}
+
+static void
+bfa_fcs_lport_ns_sm_rft_id(struct bfa_fcs_lport_ns_s *ns,
+ enum vport_ns_event event)
+{
+ bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+ bfa_trc(ns->port->fcs, event);
+
+ switch (event) {
+ case NSSM_EVENT_RSP_OK:
+ /* Now move to register FC4 Features */
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rff_id);
+ bfa_fcs_lport_ns_send_rff_id(ns, NULL);
+ break;
+
+ case NSSM_EVENT_RSP_ERROR:
+ /*
+ * Start timer for a delayed retry
+ */
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rft_id_retry);
+ ns->port->stats.ns_retries++;
+ bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
+ &ns->timer, bfa_fcs_lport_ns_timeout, ns,
+ BFA_FCS_RETRY_TIMEOUT);
+ break;
+
+ case NSSM_EVENT_PORT_OFFLINE:
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+ bfa_fcxp_discard(ns->fcxp);
+ break;
+
+ default:
+ bfa_sm_fault(ns->port->fcs, event);
+ }
+}
+
+static void
+bfa_fcs_lport_ns_sm_rft_id_retry(struct bfa_fcs_lport_ns_s *ns,
+ enum vport_ns_event event)
+{
+ bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+ bfa_trc(ns->port->fcs, event);
+
+ switch (event) {
+ case NSSM_EVENT_TIMEOUT:
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rft_id);
+ bfa_fcs_lport_ns_send_rft_id(ns, NULL);
+ break;
+
+ case NSSM_EVENT_PORT_OFFLINE:
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+ bfa_timer_stop(&ns->timer);
+ break;
+
+ default:
+ bfa_sm_fault(ns->port->fcs, event);
+ }
+}
+
+static void
+bfa_fcs_lport_ns_sm_sending_rff_id(struct bfa_fcs_lport_ns_s *ns,
+ enum vport_ns_event event)
+{
+ bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+ bfa_trc(ns->port->fcs, event);
+
+ switch (event) {
+ case NSSM_EVENT_RFFID_SENT:
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rff_id);
+ break;
+
+ case NSSM_EVENT_PORT_OFFLINE:
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+ bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
+ &ns->fcxp_wqe);
+ break;
+
+ default:
+ bfa_sm_fault(ns->port->fcs, event);
+ }
+}
+
+static void
+bfa_fcs_lport_ns_sm_rff_id(struct bfa_fcs_lport_ns_s *ns,
+ enum vport_ns_event event)
+{
+ bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+ bfa_trc(ns->port->fcs, event);
+
+ switch (event) {
+ case NSSM_EVENT_RSP_OK:
+
+ /*
+ * If min cfg mode is enabled, we donot initiate rport
+ * discovery with the fabric. Instead, we will retrieve the
+ * boot targets from HAL/FW.
+ */
+ if (__fcs_min_cfg(ns->port->fcs)) {
+ bfa_fcs_lport_ns_boot_target_disc(ns->port);
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_online);
+ return;
+ }
+
+ /*
+ * If the port role is Initiator Mode issue NS query.
+ * If it is Target Mode, skip this and go to online.
+ */
+ if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) {
+ bfa_sm_set_state(ns,
+ bfa_fcs_lport_ns_sm_sending_gid_ft);
+ bfa_fcs_lport_ns_send_gid_ft(ns, NULL);
+ }
+ /*
+ * kick off mgmt srvr state machine
+ */
+ bfa_fcs_lport_ms_online(ns->port);
+ break;
+
+ case NSSM_EVENT_RSP_ERROR:
+ /*
+ * Start timer for a delayed retry
+ */
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rff_id_retry);
+ ns->port->stats.ns_retries++;
+ bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
+ &ns->timer, bfa_fcs_lport_ns_timeout, ns,
+ BFA_FCS_RETRY_TIMEOUT);
+ break;
+
+ case NSSM_EVENT_PORT_OFFLINE:
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+ bfa_fcxp_discard(ns->fcxp);
+ break;
+
+ default:
+ bfa_sm_fault(ns->port->fcs, event);
+ }
+}
+
+static void
+bfa_fcs_lport_ns_sm_rff_id_retry(struct bfa_fcs_lport_ns_s *ns,
+ enum vport_ns_event event)
+{
+ bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+ bfa_trc(ns->port->fcs, event);
+
+ switch (event) {
+ case NSSM_EVENT_TIMEOUT:
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rff_id);
+ bfa_fcs_lport_ns_send_rff_id(ns, NULL);
+ break;
+
+ case NSSM_EVENT_PORT_OFFLINE:
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+ bfa_timer_stop(&ns->timer);
+ break;
+
+ default:
+ bfa_sm_fault(ns->port->fcs, event);
+ }
+}
+static void
+bfa_fcs_lport_ns_sm_sending_gid_ft(struct bfa_fcs_lport_ns_s *ns,
+ enum vport_ns_event event)
+{
+ bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+ bfa_trc(ns->port->fcs, event);
+
+ switch (event) {
+ case NSSM_EVENT_GIDFT_SENT:
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_gid_ft);
+ break;
+
+ case NSSM_EVENT_PORT_OFFLINE:
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+ bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
+ &ns->fcxp_wqe);
+ break;
+
+ default:
+ bfa_sm_fault(ns->port->fcs, event);
+ }
+}
+
+static void
+bfa_fcs_lport_ns_sm_gid_ft(struct bfa_fcs_lport_ns_s *ns,
+ enum vport_ns_event event)
+{
+ bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+ bfa_trc(ns->port->fcs, event);
+
+ switch (event) {
+ case NSSM_EVENT_RSP_OK:
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_online);
+ break;
+
+ case NSSM_EVENT_RSP_ERROR:
+ /*
+ * TBD: for certain reject codes, we don't need to retry
+ */
+ /*
+ * Start timer for a delayed retry
+ */
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_gid_ft_retry);
+ ns->port->stats.ns_retries++;
+ bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
+ &ns->timer, bfa_fcs_lport_ns_timeout, ns,
+ BFA_FCS_RETRY_TIMEOUT);
+ break;
+
+ case NSSM_EVENT_PORT_OFFLINE:
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+ bfa_fcxp_discard(ns->fcxp);
+ break;
+
+ case NSSM_EVENT_NS_QUERY:
+ break;
+
+ default:
+ bfa_sm_fault(ns->port->fcs, event);
+ }
+}
+
+static void
+bfa_fcs_lport_ns_sm_gid_ft_retry(struct bfa_fcs_lport_ns_s *ns,
+ enum vport_ns_event event)
+{
+ bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+ bfa_trc(ns->port->fcs, event);
+
+ switch (event) {
+ case NSSM_EVENT_TIMEOUT:
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_gid_ft);
+ bfa_fcs_lport_ns_send_gid_ft(ns, NULL);
+ break;
+
+ case NSSM_EVENT_PORT_OFFLINE:
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+ bfa_timer_stop(&ns->timer);
+ break;
+
+ default:
+ bfa_sm_fault(ns->port->fcs, event);
+ }
+}
+
+static void
+bfa_fcs_lport_ns_sm_online(struct bfa_fcs_lport_ns_s *ns,
+ enum vport_ns_event event)
+{
+ bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+ bfa_trc(ns->port->fcs, event);
+
+ switch (event) {
+ case NSSM_EVENT_PORT_OFFLINE:
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+ break;
+
+ case NSSM_EVENT_NS_QUERY:
+ /*
+ * If the port role is Initiator Mode issue NS query.
+ * If it is Target Mode, skip this and go to online.
+ */
+ if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) {
+ bfa_sm_set_state(ns,
+ bfa_fcs_lport_ns_sm_sending_gid_ft);
+ bfa_fcs_lport_ns_send_gid_ft(ns, NULL);
+ };
+ break;
+
+ default:
+ bfa_sm_fault(ns->port->fcs, event);
+ }
+}
+
+
+
+/**
+ * ns_pvt Nameserver local functions
+ */
+
+static void
+bfa_fcs_lport_ns_send_plogi(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+ struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
+ struct bfa_fcs_lport_s *port = ns->port;
+ struct fchs_s fchs;
+ int len;
+ struct bfa_fcxp_s *fcxp;
+
+ bfa_trc(port->fcs, port->pid);
+
+fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+ if (!fcxp) {
+ port->stats.ns_plogi_alloc_wait++;
+ bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
+ bfa_fcs_lport_ns_send_plogi, ns);
+ return;
+ }
+ ns->fcxp = fcxp;
+
+ len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+ bfa_os_hton3b(FC_NAME_SERVER),
+ bfa_fcs_lport_get_fcid(port), 0,
+ port->port_cfg.pwwn, port->port_cfg.nwwn,
+ bfa_fcport_get_maxfrsize(port->fcs->bfa));
+
+ bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+ FC_CLASS_3, len, &fchs,
+ bfa_fcs_lport_ns_plogi_response, (void *)ns,
+ FC_MAX_PDUSZ, FC_ELS_TOV);
+ port->stats.ns_plogi_sent++;
+
+ bfa_sm_send_event(ns, NSSM_EVENT_PLOGI_SENT);
+}
+
+static void
+bfa_fcs_lport_ns_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+ void *cbarg, bfa_status_t req_status, u32 rsp_len,
+ u32 resid_len, struct fchs_s *rsp_fchs)
+{
+ struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
+ struct bfa_fcs_lport_s *port = ns->port;
+ /* struct fc_logi_s *plogi_resp; */
+ struct fc_els_cmd_s *els_cmd;
+ struct fc_ls_rjt_s *ls_rjt;
+
+ bfa_trc(port->fcs, req_status);
+ bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+ /*
+ * Sanity Checks
+ */
+ if (req_status != BFA_STATUS_OK) {
+ bfa_trc(port->fcs, req_status);
+ port->stats.ns_plogi_rsp_err++;
+ bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+ return;
+ }
+
+ els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
+
+ switch (els_cmd->els_code) {
+
+ case FC_ELS_ACC:
+ if (rsp_len < sizeof(struct fc_logi_s)) {
+ bfa_trc(port->fcs, rsp_len);
+ port->stats.ns_plogi_acc_err++;
+ bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+ break;
+ }
+ port->stats.ns_plogi_accepts++;
+ bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
+ break;
+
+ case FC_ELS_LS_RJT:
+ ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
+
+ bfa_trc(port->fcs, ls_rjt->reason_code);
+ bfa_trc(port->fcs, ls_rjt->reason_code_expl);
+
+ port->stats.ns_rejects++;
+
+ bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+ break;
+
+ default:
+ port->stats.ns_plogi_unknown_rsp++;
+ bfa_trc(port->fcs, els_cmd->els_code);
+ bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+ }
+}
+
+/**
+ * Register the symbolic port name.
+ */
+static void
+bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+ struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
+ struct bfa_fcs_lport_s *port = ns->port;
+ struct fchs_s fchs;
+ int len;
+ struct bfa_fcxp_s *fcxp;
+ u8 symbl[256];
+ u8 *psymbl = &symbl[0];
+
+ bfa_os_memset(symbl, 0, sizeof(symbl));
+
+ bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+ fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+ if (!fcxp) {
+ port->stats.ns_rspnid_alloc_wait++;
+ bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
+ bfa_fcs_lport_ns_send_rspn_id, ns);
+ return;
+ }
+ ns->fcxp = fcxp;
+
+ /*
+ * for V-Port, form a Port Symbolic Name
+ */
+ if (port->vport) {
+ /**
+ * For Vports, we append the vport's port symbolic name
+ * to that of the base port.
+ */
+
+ strncpy((char *)psymbl,
+ (char *) &
+ (bfa_fcs_lport_get_psym_name
+ (bfa_fcs_get_base_port(port->fcs))),
+ strlen((char *) &
+ bfa_fcs_lport_get_psym_name(bfa_fcs_get_base_port
+ (port->fcs))));
+
+ /* Ensure we have a null terminating string. */
+ ((char *)psymbl)[strlen((char *) &
+ bfa_fcs_lport_get_psym_name(bfa_fcs_get_base_port
+ (port->fcs)))] = 0;
+ strncat((char *)psymbl,
+ (char *) &(bfa_fcs_lport_get_psym_name(port)),
+ strlen((char *) &bfa_fcs_lport_get_psym_name(port)));
+ } else {
+ psymbl = (u8 *) &(bfa_fcs_lport_get_psym_name(port));
+ }
+
+ len = fc_rspnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+ bfa_fcs_lport_get_fcid(port), 0, psymbl);
+
+ bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+ FC_CLASS_3, len, &fchs,
+ bfa_fcs_lport_ns_rspn_id_response, (void *)ns,
+ FC_MAX_PDUSZ, FC_FCCT_TOV);
+
+ port->stats.ns_rspnid_sent++;
+
+ bfa_sm_send_event(ns, NSSM_EVENT_RSPNID_SENT);
+}
+
+static void
+bfa_fcs_lport_ns_rspn_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+ void *cbarg, bfa_status_t req_status,
+ u32 rsp_len, u32 resid_len,
+ struct fchs_s *rsp_fchs)
+{
+ struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
+ struct bfa_fcs_lport_s *port = ns->port;
+ struct ct_hdr_s *cthdr = NULL;
+
+ bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+ /*
+ * Sanity Checks
+ */
+ if (req_status != BFA_STATUS_OK) {
+ bfa_trc(port->fcs, req_status);
+ port->stats.ns_rspnid_rsp_err++;
+ bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+ return;
+ }
+
+ cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
+ cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
+
+ if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
+ port->stats.ns_rspnid_accepts++;
+ bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
+ return;
+ }
+
+ port->stats.ns_rspnid_rejects++;
+ bfa_trc(port->fcs, cthdr->reason_code);
+ bfa_trc(port->fcs, cthdr->exp_code);
+ bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+}
+
+/**
+ * Register FC4-Types
+ */
+static void
+bfa_fcs_lport_ns_send_rft_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+ struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
+ struct bfa_fcs_lport_s *port = ns->port;
+ struct fchs_s fchs;
+ int len;
+ struct bfa_fcxp_s *fcxp;
+
+ bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+ fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+ if (!fcxp) {
+ port->stats.ns_rftid_alloc_wait++;
+ bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
+ bfa_fcs_lport_ns_send_rft_id, ns);
+ return;
+ }
+ ns->fcxp = fcxp;
+
+ len = fc_rftid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+ bfa_fcs_lport_get_fcid(port), 0, port->port_cfg.roles);
+
+ bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+ FC_CLASS_3, len, &fchs,
+ bfa_fcs_lport_ns_rft_id_response, (void *)ns,
+ FC_MAX_PDUSZ, FC_FCCT_TOV);
+
+ port->stats.ns_rftid_sent++;
+ bfa_sm_send_event(ns, NSSM_EVENT_RFTID_SENT);
+}
+
+static void
+bfa_fcs_lport_ns_rft_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+ void *cbarg, bfa_status_t req_status,
+ u32 rsp_len, u32 resid_len,
+ struct fchs_s *rsp_fchs)
+{
+ struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
+ struct bfa_fcs_lport_s *port = ns->port;
+ struct ct_hdr_s *cthdr = NULL;
+
+ bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+ /*
+ * Sanity Checks
+ */
+ if (req_status != BFA_STATUS_OK) {
+ bfa_trc(port->fcs, req_status);
+ port->stats.ns_rftid_rsp_err++;
+ bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+ return;
+ }
+
+ cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
+ cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
+
+ if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
+ port->stats.ns_rftid_accepts++;
+ bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
+ return;
+ }
+
+ port->stats.ns_rftid_rejects++;
+ bfa_trc(port->fcs, cthdr->reason_code);
+ bfa_trc(port->fcs, cthdr->exp_code);
+ bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+}
+
+/**
+ * Register FC4-Features : Should be done after RFT_ID
+ */
+static void
+bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+ struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
+ struct bfa_fcs_lport_s *port = ns->port;
+ struct fchs_s fchs;
+ int len;
+ struct bfa_fcxp_s *fcxp;
+ u8 fc4_ftrs = 0;
+
+ bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+ fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+ if (!fcxp) {
+ port->stats.ns_rffid_alloc_wait++;
+ bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
+ bfa_fcs_lport_ns_send_rff_id, ns);
+ return;
+ }
+ ns->fcxp = fcxp;
+
+ if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port))
+ fc4_ftrs = FC_GS_FCP_FC4_FEATURE_INITIATOR;
+
+ len = fc_rffid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+ bfa_fcs_lport_get_fcid(port), 0,
+ FC_TYPE_FCP, fc4_ftrs);
+
+ bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+ FC_CLASS_3, len, &fchs,
+ bfa_fcs_lport_ns_rff_id_response, (void *)ns,
+ FC_MAX_PDUSZ, FC_FCCT_TOV);
+
+ port->stats.ns_rffid_sent++;
+ bfa_sm_send_event(ns, NSSM_EVENT_RFFID_SENT);
+}
+
+static void
+bfa_fcs_lport_ns_rff_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+ void *cbarg, bfa_status_t req_status,
+ u32 rsp_len, u32 resid_len,
+ struct fchs_s *rsp_fchs)
+{
+ struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
+ struct bfa_fcs_lport_s *port = ns->port;
+ struct ct_hdr_s *cthdr = NULL;
+
+ bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+ /*
+ * Sanity Checks
+ */
+ if (req_status != BFA_STATUS_OK) {
+ bfa_trc(port->fcs, req_status);
+ port->stats.ns_rffid_rsp_err++;
+ bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+ return;
+ }
+
+ cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
+ cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
+
+ if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
+ port->stats.ns_rffid_accepts++;
+ bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
+ return;
+ }
+
+ port->stats.ns_rffid_rejects++;
+ bfa_trc(port->fcs, cthdr->reason_code);
+ bfa_trc(port->fcs, cthdr->exp_code);
+
+ if (cthdr->reason_code == CT_RSN_NOT_SUPP) {
+ /* if this command is not supported, we don't retry */
+ bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
+ } else
+ bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+}
+/**
+ * Query Fabric for FC4-Types Devices.
+ *
+* TBD : Need to use a local (FCS private) response buffer, since the response
+ * can be larger than 2K.
+ */
+static void
+bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+ struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
+ struct bfa_fcs_lport_s *port = ns->port;
+ struct fchs_s fchs;
+ int len;
+ struct bfa_fcxp_s *fcxp;
+
+ bfa_trc(port->fcs, port->pid);
+
+ fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+ if (!fcxp) {
+ port->stats.ns_gidft_alloc_wait++;
+ bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
+ bfa_fcs_lport_ns_send_gid_ft, ns);
+ return;
+ }
+ ns->fcxp = fcxp;
+
+ /*
+ * This query is only initiated for FCP initiator mode.
+ */
+ len = fc_gid_ft_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+ ns->port->pid, FC_TYPE_FCP);
+
+ bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+ FC_CLASS_3, len, &fchs,
+ bfa_fcs_lport_ns_gid_ft_response, (void *)ns,
+ bfa_fcxp_get_maxrsp(port->fcs->bfa), FC_FCCT_TOV);
+
+ port->stats.ns_gidft_sent++;
+
+ bfa_sm_send_event(ns, NSSM_EVENT_GIDFT_SENT);
+}
+
+static void
+bfa_fcs_lport_ns_gid_ft_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+ void *cbarg, bfa_status_t req_status,
+ u32 rsp_len, u32 resid_len,
+ struct fchs_s *rsp_fchs)
+{
+ struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
+ struct bfa_fcs_lport_s *port = ns->port;
+ struct ct_hdr_s *cthdr = NULL;
+ u32 n_pids;
+
+ bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+ /*
+ * Sanity Checks
+ */
+ if (req_status != BFA_STATUS_OK) {
+ bfa_trc(port->fcs, req_status);
+ port->stats.ns_gidft_rsp_err++;
+ bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+ return;
+ }
+
+ if (resid_len != 0) {
+ /*
+ * TBD : we will need to allocate a larger buffer & retry the
+ * command
+ */
+ bfa_trc(port->fcs, rsp_len);
+ bfa_trc(port->fcs, resid_len);
+ return;
+ }
+
+ cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
+ cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
+
+ switch (cthdr->cmd_rsp_code) {
+
+ case CT_RSP_ACCEPT:
+
+ port->stats.ns_gidft_accepts++;
+ n_pids = (fc_get_ctresp_pyld_len(rsp_len) / sizeof(u32));
+ bfa_trc(port->fcs, n_pids);
+ bfa_fcs_lport_ns_process_gidft_pids(port,
+ (u32 *) (cthdr + 1),
+ n_pids);
+ bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
+ break;
+
+ case CT_RSP_REJECT:
+
+ /*
+ * Check the reason code & explanation.
+ * There may not have been any FC4 devices in the fabric
+ */
+ port->stats.ns_gidft_rejects++;
+ bfa_trc(port->fcs, cthdr->reason_code);
+ bfa_trc(port->fcs, cthdr->exp_code);
+
+ if ((cthdr->reason_code == CT_RSN_UNABLE_TO_PERF)
+ && (cthdr->exp_code == CT_NS_EXP_FT_NOT_REG)) {
+
+ bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
+ } else {
+ /*
+ * for all other errors, retry
+ */
+ bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+ }
+ break;
+
+ default:
+ port->stats.ns_gidft_unknown_rsp++;
+ bfa_trc(port->fcs, cthdr->cmd_rsp_code);
+ bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+ }
+}
+
+/**
+ * This routine will be called by bfa_timer on timer timeouts.
+ *
+ * param[in] port - pointer to bfa_fcs_lport_t.
+ *
+ * return
+ * void
+ *
+ * Special Considerations:
+ *
+ * note
+ */
+static void
+bfa_fcs_lport_ns_timeout(void *arg)
+{
+ struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) arg;
+
+ ns->port->stats.ns_timeouts++;
+ bfa_sm_send_event(ns, NSSM_EVENT_TIMEOUT);
+}
+
+/*
+ * Process the PID list in GID_FT response
+ */
+static void
+bfa_fcs_lport_ns_process_gidft_pids(struct bfa_fcs_lport_s *port, u32 *pid_buf,
+ u32 n_pids)
+{
+ struct fcgs_gidft_resp_s *gidft_entry;
+ struct bfa_fcs_rport_s *rport;
+ u32 ii;
+
+ for (ii = 0; ii < n_pids; ii++) {
+ gidft_entry = (struct fcgs_gidft_resp_s *) &pid_buf[ii];
+
+ if (gidft_entry->pid == port->pid)
+ continue;
+
+ /*
+ * Check if this rport already exists
+ */
+ rport = bfa_fcs_lport_get_rport_by_pid(port, gidft_entry->pid);
+ if (rport == NULL) {
+ /*
+ * this is a new device. create rport
+ */
+ rport = bfa_fcs_rport_create(port, gidft_entry->pid);
+ } else {
+ /*
+ * this rport already exists
+ */
+ bfa_fcs_rport_scn(rport);
+ }
+
+ bfa_trc(port->fcs, gidft_entry->pid);
+
+ /*
+ * if the last entry bit is set, bail out.
+ */
+ if (gidft_entry->last)
+ return;
+ }
+}
+
+/**
+ * fcs_ns_public FCS nameserver public interfaces
+ */
+
+/*
+ * Functions called by port/fab.
+ * These will send relevant Events to the ns state machine.
+ */
+void
+bfa_fcs_lport_ns_init(struct bfa_fcs_lport_s *port)
+{
+ struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
+
+ ns->port = port;
+ bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+}
+
+void
+bfa_fcs_lport_ns_offline(struct bfa_fcs_lport_s *port)
+{
+ struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
+
+ ns->port = port;
+ bfa_sm_send_event(ns, NSSM_EVENT_PORT_OFFLINE);
+}
+
+void
+bfa_fcs_lport_ns_online(struct bfa_fcs_lport_s *port)
+{
+ struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
+
+ ns->port = port;
+ bfa_sm_send_event(ns, NSSM_EVENT_PORT_ONLINE);
+}
+
+void
+bfa_fcs_lport_ns_query(struct bfa_fcs_lport_s *port)
+{
+ struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
+
+ bfa_trc(port->fcs, port->pid);
+ bfa_sm_send_event(ns, NSSM_EVENT_NS_QUERY);
+}
+
+void
+bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port)
+{
+
+ struct bfa_fcs_rport_s *rport;
+ u8 nwwns;
+ wwn_t wwns[BFA_PREBOOT_BOOTLUN_MAX];
+ int ii;
+
+ bfa_iocfc_get_bootwwns(port->fcs->bfa, &nwwns, wwns);
+
+ for (ii = 0 ; ii < nwwns; ++ii) {
+ rport = bfa_fcs_rport_create_by_wwn(port, wwns[ii]);
+ bfa_assert(rport);
+ }
+}
+
+/**
+ * FCS SCN
+ */
+
+#define FC_QOS_RSCN_EVENT 0x0c
+#define FC_FABRIC_NAME_RSCN_EVENT 0x0d
+
+/*
+ * forward declarations
+ */
+static void bfa_fcs_lport_scn_send_scr(void *scn_cbarg,
+ struct bfa_fcxp_s *fcxp_alloced);
+static void bfa_fcs_lport_scn_scr_response(void *fcsarg,
+ struct bfa_fcxp_s *fcxp,
+ void *cbarg,
+ bfa_status_t req_status,
+ u32 rsp_len,
+ u32 resid_len,
+ struct fchs_s *rsp_fchs);
+static void bfa_fcs_lport_scn_send_ls_acc(struct bfa_fcs_lport_s *port,
+ struct fchs_s *rx_fchs);
+static void bfa_fcs_lport_scn_timeout(void *arg);
+
+/**
+ * fcs_scm_sm FCS SCN state machine
+ */
+
+/**
+ * VPort SCN State Machine events
+ */
+enum port_scn_event {
+ SCNSM_EVENT_PORT_ONLINE = 1,
+ SCNSM_EVENT_PORT_OFFLINE = 2,
+ SCNSM_EVENT_RSP_OK = 3,
+ SCNSM_EVENT_RSP_ERROR = 4,
+ SCNSM_EVENT_TIMEOUT = 5,
+ SCNSM_EVENT_SCR_SENT = 6,
+};
+
+static void bfa_fcs_lport_scn_sm_offline(struct bfa_fcs_lport_scn_s *scn,
+ enum port_scn_event event);
+static void bfa_fcs_lport_scn_sm_sending_scr(
+ struct bfa_fcs_lport_scn_s *scn,
+ enum port_scn_event event);
+static void bfa_fcs_lport_scn_sm_scr(struct bfa_fcs_lport_scn_s *scn,
+ enum port_scn_event event);
+static void bfa_fcs_lport_scn_sm_scr_retry(struct bfa_fcs_lport_scn_s *scn,
+ enum port_scn_event event);
+static void bfa_fcs_lport_scn_sm_online(struct bfa_fcs_lport_scn_s *scn,
+ enum port_scn_event event);
+
+/**
+ * Starting state - awaiting link up.
+ */
+static void
+bfa_fcs_lport_scn_sm_offline(struct bfa_fcs_lport_scn_s *scn,
+ enum port_scn_event event)
+{
+ switch (event) {
+ case SCNSM_EVENT_PORT_ONLINE:
+ bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_sending_scr);
+ bfa_fcs_lport_scn_send_scr(scn, NULL);
+ break;
+
+ case SCNSM_EVENT_PORT_OFFLINE:
+ break;
+
+ default:
+ bfa_sm_fault(scn->port->fcs, event);
+ }
+}
+
+static void
+bfa_fcs_lport_scn_sm_sending_scr(struct bfa_fcs_lport_scn_s *scn,
+ enum port_scn_event event)
+{
+ switch (event) {
+ case SCNSM_EVENT_SCR_SENT:
+ bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_scr);
+ break;
+
+ case SCNSM_EVENT_PORT_OFFLINE:
+ bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
+ bfa_fcxp_walloc_cancel(scn->port->fcs->bfa, &scn->fcxp_wqe);
+ break;
+
+ default:
+ bfa_sm_fault(scn->port->fcs, event);
+ }
+}
+
+static void
+bfa_fcs_lport_scn_sm_scr(struct bfa_fcs_lport_scn_s *scn,
+ enum port_scn_event event)
+{
+ struct bfa_fcs_lport_s *port = scn->port;
+
+ switch (event) {
+ case SCNSM_EVENT_RSP_OK:
+ bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_online);
+ break;
+
+ case SCNSM_EVENT_RSP_ERROR:
+ bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_scr_retry);
+ bfa_timer_start(port->fcs->bfa, &scn->timer,
+ bfa_fcs_lport_scn_timeout, scn,
+ BFA_FCS_RETRY_TIMEOUT);
+ break;
+
+ case SCNSM_EVENT_PORT_OFFLINE:
+ bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
+ bfa_fcxp_discard(scn->fcxp);
+ break;
+
+ default:
+ bfa_sm_fault(port->fcs, event);
+ }
+}
+
+static void
+bfa_fcs_lport_scn_sm_scr_retry(struct bfa_fcs_lport_scn_s *scn,
+ enum port_scn_event event)
+{
+ switch (event) {
+ case SCNSM_EVENT_TIMEOUT:
+ bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_sending_scr);
+ bfa_fcs_lport_scn_send_scr(scn, NULL);
+ break;
+
+ case SCNSM_EVENT_PORT_OFFLINE:
+ bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
+ bfa_timer_stop(&scn->timer);
+ break;
+
+ default:
+ bfa_sm_fault(scn->port->fcs, event);
+ }
+}
+
+static void
+bfa_fcs_lport_scn_sm_online(struct bfa_fcs_lport_scn_s *scn,
+ enum port_scn_event event)
+{
+ switch (event) {
+ case SCNSM_EVENT_PORT_OFFLINE:
+ bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
+ break;
+
+ default:
+ bfa_sm_fault(scn->port->fcs, event);
+ }
+}
+
+
+
+/**
+ * fcs_scn_private FCS SCN private functions
+ */
+
+/**
+ * This routine will be called to send a SCR command.
+ */
+static void
+bfa_fcs_lport_scn_send_scr(void *scn_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+ struct bfa_fcs_lport_scn_s *scn = scn_cbarg;
+ struct bfa_fcs_lport_s *port = scn->port;
+ struct fchs_s fchs;
+ int len;
+ struct bfa_fcxp_s *fcxp;
+
+ bfa_trc(port->fcs, port->pid);
+ bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+ fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+ if (!fcxp) {
+ bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &scn->fcxp_wqe,
+ bfa_fcs_lport_scn_send_scr, scn);
+ return;
+ }
+ scn->fcxp = fcxp;
+
+ /* Handle VU registrations for Base port only */
+ if ((!port->vport) && bfa_ioc_get_fcmode(&port->fcs->bfa->ioc)) {
+ len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+ bfa_lps_is_brcd_fabric(port->fabric->lps),
+ port->pid, 0);
+ } else {
+ len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+ BFA_FALSE,
+ port->pid, 0);
+ }
+
+ bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+ FC_CLASS_3, len, &fchs,
+ bfa_fcs_lport_scn_scr_response,
+ (void *)scn, FC_MAX_PDUSZ, FC_ELS_TOV);
+
+ bfa_sm_send_event(scn, SCNSM_EVENT_SCR_SENT);
+}
+
+static void
+bfa_fcs_lport_scn_scr_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+ void *cbarg, bfa_status_t req_status, u32 rsp_len,
+ u32 resid_len, struct fchs_s *rsp_fchs)
+{
+ struct bfa_fcs_lport_scn_s *scn = (struct bfa_fcs_lport_scn_s *) cbarg;
+ struct bfa_fcs_lport_s *port = scn->port;
+ struct fc_els_cmd_s *els_cmd;
+ struct fc_ls_rjt_s *ls_rjt;
+
+ bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+ /*
+ * Sanity Checks
+ */
+ if (req_status != BFA_STATUS_OK) {
+ bfa_trc(port->fcs, req_status);
+ bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
+ return;
+ }
+
+ els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
+
+ switch (els_cmd->els_code) {
+
+ case FC_ELS_ACC:
+ bfa_sm_send_event(scn, SCNSM_EVENT_RSP_OK);
+ break;
+
+ case FC_ELS_LS_RJT:
+
+ ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
+
+ bfa_trc(port->fcs, ls_rjt->reason_code);
+ bfa_trc(port->fcs, ls_rjt->reason_code_expl);
+
+ bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
+ break;
+
+ default:
+ bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
+ }
+}
+
+/*
+ * Send a LS Accept
+ */
+static void
+bfa_fcs_lport_scn_send_ls_acc(struct bfa_fcs_lport_s *port,
+ struct fchs_s *rx_fchs)
+{
+ struct fchs_s fchs;
+ struct bfa_fcxp_s *fcxp;
+ struct bfa_rport_s *bfa_rport = NULL;
+ int len;
+
+ bfa_trc(port->fcs, rx_fchs->s_id);
+
+ fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+ if (!fcxp)
+ return;
+
+ len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+ rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
+ rx_fchs->ox_id);
+
+ bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
+ BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
+ FC_MAX_PDUSZ, 0);
+}
+
+/**
+ * This routine will be called by bfa_timer on timer timeouts.
+ *
+ * param[in] vport - pointer to bfa_fcs_lport_t.
+ * param[out] vport_status - pointer to return vport status in
+ *
+ * return
+ * void
+ *
+ * Special Considerations:
+ *
+ * note
+ */
+static void
+bfa_fcs_lport_scn_timeout(void *arg)
+{
+ struct bfa_fcs_lport_scn_s *scn = (struct bfa_fcs_lport_scn_s *) arg;
+
+ bfa_sm_send_event(scn, SCNSM_EVENT_TIMEOUT);
+}
+
+
+
+/**
+ * fcs_scn_public FCS state change notification public interfaces
+ */
+
+/*
+ * Functions called by port/fab
+ */
+void
+bfa_fcs_lport_scn_init(struct bfa_fcs_lport_s *port)
+{
+ struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
+
+ scn->port = port;
+ bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
+}
+
+void
+bfa_fcs_lport_scn_offline(struct bfa_fcs_lport_s *port)
+{
+ struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
+
+ scn->port = port;
+ bfa_sm_send_event(scn, SCNSM_EVENT_PORT_OFFLINE);
+}
+
+void
+bfa_fcs_lport_scn_online(struct bfa_fcs_lport_s *port)
+{
+ struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
+
+ scn->port = port;
+ bfa_sm_send_event(scn, SCNSM_EVENT_PORT_ONLINE);
+}
+
+static void
+bfa_fcs_lport_scn_portid_rscn(struct bfa_fcs_lport_s *port, u32 rpid)
+{
+ struct bfa_fcs_rport_s *rport;
+
+ bfa_trc(port->fcs, rpid);
+
+ /**
+ * If this is an unknown device, then it just came online.
+ * Otherwise let rport handle the RSCN event.
+ */
+ rport = bfa_fcs_lport_get_rport_by_pid(port, rpid);
+ if (rport == NULL) {
+ /*
+ * If min cfg mode is enabled, we donot need to
+ * discover any new rports.
+ */
+ if (!__fcs_min_cfg(port->fcs))
+ rport = bfa_fcs_rport_create(port, rpid);
+ } else
+ bfa_fcs_rport_scn(rport);
+}
+
+/**
+ * rscn format based PID comparison
+ */
+#define __fc_pid_match(__c0, __c1, __fmt) \
+ (((__fmt) == FC_RSCN_FORMAT_FABRIC) || \
+ (((__fmt) == FC_RSCN_FORMAT_DOMAIN) && \
+ ((__c0)[0] == (__c1)[0])) || \
+ (((__fmt) == FC_RSCN_FORMAT_AREA) && \
+ ((__c0)[0] == (__c1)[0]) && \
+ ((__c0)[1] == (__c1)[1])))
+
+static void
+bfa_fcs_lport_scn_multiport_rscn(struct bfa_fcs_lport_s *port,
+ enum fc_rscn_format format,
+ u32 rscn_pid)
+{
+ struct bfa_fcs_rport_s *rport;
+ struct list_head *qe, *qe_next;
+ u8 *c0, *c1;
+
+ bfa_trc(port->fcs, format);
+ bfa_trc(port->fcs, rscn_pid);
+
+ c0 = (u8 *) &rscn_pid;
+
+ list_for_each_safe(qe, qe_next, &port->rport_q) {
+ rport = (struct bfa_fcs_rport_s *) qe;
+ c1 = (u8 *) &rport->pid;
+ if (__fc_pid_match(c0, c1, format))
+ bfa_fcs_rport_scn(rport);
+ }
+}
+
+
+void
+bfa_fcs_lport_scn_process_rscn(struct bfa_fcs_lport_s *port,
+ struct fchs_s *fchs, u32 len)
+{
+ struct fc_rscn_pl_s *rscn = (struct fc_rscn_pl_s *) (fchs + 1);
+ int num_entries;
+ u32 rscn_pid;
+ bfa_boolean_t nsquery = BFA_FALSE, found;
+ int i = 0, j;
+
+ num_entries =
+ (bfa_os_ntohs(rscn->payldlen) -
+ sizeof(u32)) / sizeof(rscn->event[0]);
+
+ bfa_trc(port->fcs, num_entries);
+
+ port->stats.num_rscn++;
+
+ bfa_fcs_lport_scn_send_ls_acc(port, fchs);
+
+ for (i = 0; i < num_entries; i++) {
+ rscn_pid = rscn->event[i].portid;
+
+ bfa_trc(port->fcs, rscn->event[i].format);
+ bfa_trc(port->fcs, rscn_pid);
+
+ /* check for duplicate entries in the list */
+ found = BFA_FALSE;
+ for (j = 0; j < i; j++) {
+ if (rscn->event[j].portid == rscn_pid) {
+ found = BFA_TRUE;
+ break;
+ }
+ }
+
+ /* if found in down the list, pid has been already processed */
+ if (found) {
+ bfa_trc(port->fcs, rscn_pid);
+ continue;
+ }
+
+ switch (rscn->event[i].format) {
+ case FC_RSCN_FORMAT_PORTID:
+ if (rscn->event[i].qualifier == FC_QOS_RSCN_EVENT) {
+ /*
+ * Ignore this event.
+ * f/w would have processed it
+ */
+ bfa_trc(port->fcs, rscn_pid);
+ } else {
+ port->stats.num_portid_rscn++;
+ bfa_fcs_lport_scn_portid_rscn(port, rscn_pid);
+ }
+ break;
+
+ case FC_RSCN_FORMAT_FABRIC:
+ if (rscn->event[i].qualifier ==
+ FC_FABRIC_NAME_RSCN_EVENT) {
+ bfa_fcs_lport_ms_fabric_rscn(port);
+ break;
+ }
+ /* !!!!!!!!! Fall Through !!!!!!!!!!!!! */
+
+ case FC_RSCN_FORMAT_AREA:
+ case FC_RSCN_FORMAT_DOMAIN:
+ nsquery = BFA_TRUE;
+ bfa_fcs_lport_scn_multiport_rscn(port,
+ rscn->event[i].format,
+ rscn_pid);
+ break;
+
+
+ default:
+ bfa_assert(0);
+ nsquery = BFA_TRUE;
+ }
+ }
+
+ /**
+ * If any of area, domain or fabric RSCN is received, do a fresh discovery
+ * to find new devices.
+ */
+ if (nsquery)
+ bfa_fcs_lport_ns_query(port);
+}
+
+/**
+ * BFA FCS port
+ */
+/**
+ * fcs_port_api BFA FCS port API
+ */
+struct bfa_fcs_lport_s *
+bfa_fcs_get_base_port(struct bfa_fcs_s *fcs)
+{
+ return &fcs->fabric.bport;
+}
+
+wwn_t
+bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s *port, wwn_t wwn, int index,
+ int nrports, bfa_boolean_t bwwn)
+{
+ struct list_head *qh, *qe;
+ struct bfa_fcs_rport_s *rport = NULL;
+ int i;
+ struct bfa_fcs_s *fcs;
+
+ if (port == NULL || nrports == 0)
+ return (wwn_t) 0;
+
+ fcs = port->fcs;
+ bfa_trc(fcs, (u32) nrports);
+
+ i = 0;
+ qh = &port->rport_q;
+ qe = bfa_q_first(qh);
+
+ while ((qe != qh) && (i < nrports)) {
+ rport = (struct bfa_fcs_rport_s *) qe;
+ if (bfa_os_ntoh3b(rport->pid) > 0xFFF000) {
+ qe = bfa_q_next(qe);
+ bfa_trc(fcs, (u32) rport->pwwn);
+ bfa_trc(fcs, rport->pid);
+ bfa_trc(fcs, i);
+ continue;
+ }
+
+ if (bwwn) {
+ if (!memcmp(&wwn, &rport->pwwn, 8))
+ break;
+ } else {
+ if (i == index)
+ break;
+ }
+
+ i++;
+ qe = bfa_q_next(qe);
+ }
+
+ bfa_trc(fcs, i);
+ if (rport)
+ return rport->pwwn;
+ else
+ return (wwn_t) 0;
+}
+
+void
+bfa_fcs_lport_get_rports(struct bfa_fcs_lport_s *port,
+ wwn_t rport_wwns[], int *nrports)
+{
+ struct list_head *qh, *qe;
+ struct bfa_fcs_rport_s *rport = NULL;
+ int i;
+ struct bfa_fcs_s *fcs;
+
+ if (port == NULL || rport_wwns == NULL || *nrports == 0)
+ return;
+
+ fcs = port->fcs;
+ bfa_trc(fcs, (u32) *nrports);
+
+ i = 0;
+ qh = &port->rport_q;
+ qe = bfa_q_first(qh);
+
+ while ((qe != qh) && (i < *nrports)) {
+ rport = (struct bfa_fcs_rport_s *) qe;
+ if (bfa_os_ntoh3b(rport->pid) > 0xFFF000) {
+ qe = bfa_q_next(qe);
+ bfa_trc(fcs, (u32) rport->pwwn);
+ bfa_trc(fcs, rport->pid);
+ bfa_trc(fcs, i);
+ continue;
+ }
+
+ rport_wwns[i] = rport->pwwn;
+
+ i++;
+ qe = bfa_q_next(qe);
+ }
+
+ bfa_trc(fcs, i);
+ *nrports = i;
+}
+
+/*
+ * Iterate's through all the rport's in the given port to
+ * determine the maximum operating speed.
+ *
+ * !!!! To be used in TRL Functionality only !!!!
+ */
+bfa_port_speed_t
+bfa_fcs_lport_get_rport_max_speed(bfa_fcs_lport_t *port)
+{
+ struct list_head *qh, *qe;
+ struct bfa_fcs_rport_s *rport = NULL;
+ struct bfa_fcs_s *fcs;
+ bfa_port_speed_t max_speed = 0;
+ struct bfa_port_attr_s port_attr;
+ bfa_port_speed_t port_speed, rport_speed;
+ bfa_boolean_t trl_enabled = bfa_fcport_is_ratelim(port->fcs->bfa);
+
+
+ if (port == NULL)
+ return 0;
+
+ fcs = port->fcs;
+
+ /* Get Physical port's current speed */
+ bfa_fcport_get_attr(port->fcs->bfa, &port_attr);
+ port_speed = port_attr.speed;
+ bfa_trc(fcs, port_speed);
+
+ qh = &port->rport_q;
+ qe = bfa_q_first(qh);
+
+ while (qe != qh) {
+ rport = (struct bfa_fcs_rport_s *) qe;
+ if ((bfa_os_ntoh3b(rport->pid) > 0xFFF000) ||
+ (bfa_fcs_rport_get_state(rport) ==
+ BFA_RPORT_OFFLINE)) {
+ qe = bfa_q_next(qe);
+ continue;
+ }
+
+ rport_speed = rport->rpf.rpsc_speed;
+ if ((trl_enabled) && (rport_speed ==
+ BFA_PORT_SPEED_UNKNOWN)) {
+ /* Use default ratelim speed setting */
+ rport_speed =
+ bfa_fcport_get_ratelim_speed(port->fcs->bfa);
+ }
+ if ((rport_speed == BFA_PORT_SPEED_8GBPS) ||
+ (rport_speed > port_speed)) {
+ max_speed = rport_speed;
+ break;
+ } else if (rport_speed > max_speed) {
+ max_speed = rport_speed;
+ }
+
+ qe = bfa_q_next(qe);
+ }
+
+ bfa_trc(fcs, max_speed);
+ return max_speed;
+}
+
+struct bfa_fcs_lport_s *
+bfa_fcs_lookup_port(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t lpwwn)
+{
+ struct bfa_fcs_vport_s *vport;
+ bfa_fcs_vf_t *vf;
+
+ bfa_assert(fcs != NULL);
+
+ vf = bfa_fcs_vf_lookup(fcs, vf_id);
+ if (vf == NULL) {
+ bfa_trc(fcs, vf_id);
+ return NULL;
+ }
+
+ if (!lpwwn || (vf->bport.port_cfg.pwwn == lpwwn))
+ return &vf->bport;
+
+ vport = bfa_fcs_fabric_vport_lookup(vf, lpwwn);
+ if (vport)
+ return &vport->lport;
+
+ return NULL;
+}
+
+/*
+ * API corresponding to NPIV_VPORT_GETINFO.
+ */
+void
+bfa_fcs_lport_get_info(struct bfa_fcs_lport_s *port,
+ struct bfa_lport_info_s *port_info)
+{
+
+ bfa_trc(port->fcs, port->fabric->fabric_name);
+
+ if (port->vport == NULL) {
+ /*
+ * This is a Physical port
+ */
+ port_info->port_type = BFA_LPORT_TYPE_PHYSICAL;
+
+ /*
+ * @todo : need to fix the state & reason
+ */
+ port_info->port_state = 0;
+ port_info->offline_reason = 0;
+
+ port_info->port_wwn = bfa_fcs_lport_get_pwwn(port);
+ port_info->node_wwn = bfa_fcs_lport_get_nwwn(port);
+
+ port_info->max_vports_supp =
+ bfa_lps_get_max_vport(port->fcs->bfa);
+ port_info->num_vports_inuse =
+ bfa_fcs_fabric_vport_count(port->fabric);
+ port_info->max_rports_supp = BFA_FCS_MAX_RPORTS_SUPP;
+ port_info->num_rports_inuse = port->num_rports;
} else {
- port_attr->port_type = BFA_PPORT_TYPE_UNKNOWN;
- port_attr->state = BFA_PORT_UNINIT;
+ /*
+ * This is a virtual port
+ */
+ port_info->port_type = BFA_LPORT_TYPE_VIRTUAL;
+
+ /*
+ * @todo : need to fix the state & reason
+ */
+ port_info->port_state = 0;
+ port_info->offline_reason = 0;
+
+ port_info->port_wwn = bfa_fcs_lport_get_pwwn(port);
+ port_info->node_wwn = bfa_fcs_lport_get_nwwn(port);
+ }
+}
+
+void
+bfa_fcs_lport_get_stats(struct bfa_fcs_lport_s *fcs_port,
+ struct bfa_lport_stats_s *port_stats)
+{
+ *port_stats = fcs_port->stats;
+}
+
+void
+bfa_fcs_lport_clear_stats(struct bfa_fcs_lport_s *fcs_port)
+{
+ bfa_os_memset(&fcs_port->stats, 0, sizeof(struct bfa_lport_stats_s));
+}
+
+/**
+ * FCS virtual port state machine
+ */
+
+#define __vport_fcs(__vp) ((__vp)->lport.fcs)
+#define __vport_pwwn(__vp) ((__vp)->lport.port_cfg.pwwn)
+#define __vport_nwwn(__vp) ((__vp)->lport.port_cfg.nwwn)
+#define __vport_bfa(__vp) ((__vp)->lport.fcs->bfa)
+#define __vport_fcid(__vp) ((__vp)->lport.pid)
+#define __vport_fabric(__vp) ((__vp)->lport.fabric)
+#define __vport_vfid(__vp) ((__vp)->lport.fabric->vf_id)
+
+#define BFA_FCS_VPORT_MAX_RETRIES 5
+/*
+ * Forward declarations
+ */
+static void bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport);
+static void bfa_fcs_vport_timeout(void *vport_arg);
+static void bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport);
+static void bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport);
+
+/**
+ * fcs_vport_sm FCS virtual port state machine
+ */
+
+/**
+ * VPort State Machine events
+ */
+enum bfa_fcs_vport_event {
+ BFA_FCS_VPORT_SM_CREATE = 1, /* vport create event */
+ BFA_FCS_VPORT_SM_DELETE = 2, /* vport delete event */
+ BFA_FCS_VPORT_SM_START = 3, /* vport start request */
+ BFA_FCS_VPORT_SM_STOP = 4, /* stop: unsupported */
+ BFA_FCS_VPORT_SM_ONLINE = 5, /* fabric online */
+ BFA_FCS_VPORT_SM_OFFLINE = 6, /* fabric offline event */
+ BFA_FCS_VPORT_SM_FRMSENT = 7, /* fdisc/logo sent events */
+ BFA_FCS_VPORT_SM_RSP_OK = 8, /* good response */
+ BFA_FCS_VPORT_SM_RSP_ERROR = 9, /* error/bad response */
+ BFA_FCS_VPORT_SM_TIMEOUT = 10, /* delay timer event */
+ BFA_FCS_VPORT_SM_DELCOMP = 11, /* lport delete completion */
+ BFA_FCS_VPORT_SM_RSP_DUP_WWN = 12, /* Dup wnn error*/
+ BFA_FCS_VPORT_SM_RSP_FAILED = 13, /* non-retryable failure */
+};
+
+static void bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport,
+ enum bfa_fcs_vport_event event);
+static void bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport,
+ enum bfa_fcs_vport_event event);
+static void bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport,
+ enum bfa_fcs_vport_event event);
+static void bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
+ enum bfa_fcs_vport_event event);
+static void bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
+ enum bfa_fcs_vport_event event);
+static void bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
+ enum bfa_fcs_vport_event event);
+static void bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport,
+ enum bfa_fcs_vport_event event);
+static void bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,
+ enum bfa_fcs_vport_event event);
+static void bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,
+ enum bfa_fcs_vport_event event);
+static void bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport,
+ enum bfa_fcs_vport_event event);
+
+static struct bfa_sm_table_s vport_sm_table[] = {
+ {BFA_SM(bfa_fcs_vport_sm_uninit), BFA_FCS_VPORT_UNINIT},
+ {BFA_SM(bfa_fcs_vport_sm_created), BFA_FCS_VPORT_CREATED},
+ {BFA_SM(bfa_fcs_vport_sm_offline), BFA_FCS_VPORT_OFFLINE},
+ {BFA_SM(bfa_fcs_vport_sm_fdisc), BFA_FCS_VPORT_FDISC},
+ {BFA_SM(bfa_fcs_vport_sm_fdisc_retry), BFA_FCS_VPORT_FDISC_RETRY},
+ {BFA_SM(bfa_fcs_vport_sm_online), BFA_FCS_VPORT_ONLINE},
+ {BFA_SM(bfa_fcs_vport_sm_deleting), BFA_FCS_VPORT_DELETING},
+ {BFA_SM(bfa_fcs_vport_sm_cleanup), BFA_FCS_VPORT_CLEANUP},
+ {BFA_SM(bfa_fcs_vport_sm_logo), BFA_FCS_VPORT_LOGO},
+ {BFA_SM(bfa_fcs_vport_sm_error), BFA_FCS_VPORT_ERROR}
+};
+
+/**
+ * Beginning state.
+ */
+static void
+bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport,
+ enum bfa_fcs_vport_event event)
+{
+ bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+ bfa_trc(__vport_fcs(vport), event);
+
+ switch (event) {
+ case BFA_FCS_VPORT_SM_CREATE:
+ bfa_sm_set_state(vport, bfa_fcs_vport_sm_created);
+ bfa_fcs_fabric_addvport(__vport_fabric(vport), vport);
+ break;
+
+ default:
+ bfa_sm_fault(__vport_fcs(vport), event);
+ }
+}
+
+/**
+ * Created state - a start event is required to start up the state machine.
+ */
+static void
+bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport,
+ enum bfa_fcs_vport_event event)
+{
+ bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+ bfa_trc(__vport_fcs(vport), event);
+
+ switch (event) {
+ case BFA_FCS_VPORT_SM_START:
+ if (bfa_fcs_fabric_is_online(__vport_fabric(vport))
+ && bfa_fcs_fabric_npiv_capable(__vport_fabric(vport))) {
+ bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
+ bfa_fcs_vport_do_fdisc(vport);
+ } else {
+ /**
+ * Fabric is offline or not NPIV capable, stay in
+ * offline state.
+ */
+ vport->vport_stats.fab_no_npiv++;
+ bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
+ }
+ break;
+
+ case BFA_FCS_VPORT_SM_DELETE:
+ bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
+ bfa_fcs_lport_delete(&vport->lport);
+ break;
+
+ case BFA_FCS_VPORT_SM_ONLINE:
+ case BFA_FCS_VPORT_SM_OFFLINE:
+ /**
+ * Ignore ONLINE/OFFLINE events from fabric
+ * till vport is started.
+ */
+ break;
+
+ default:
+ bfa_sm_fault(__vport_fcs(vport), event);
+ }
+}
+
+/**
+ * Offline state - awaiting ONLINE event from fabric SM.
+ */
+static void
+bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport,
+ enum bfa_fcs_vport_event event)
+{
+ bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+ bfa_trc(__vport_fcs(vport), event);
+
+ switch (event) {
+ case BFA_FCS_VPORT_SM_DELETE:
+ bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
+ bfa_fcs_lport_delete(&vport->lport);
+ break;
+
+ case BFA_FCS_VPORT_SM_ONLINE:
+ bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
+ vport->fdisc_retries = 0;
+ bfa_fcs_vport_do_fdisc(vport);
+ break;
+
+ case BFA_FCS_VPORT_SM_OFFLINE:
+ /*
+ * This can happen if the vport couldn't be initialzied
+ * due the fact that the npiv was not enabled on the switch.
+ * In that case we will put the vport in offline state.
+ * However, the link can go down and cause the this event to
+ * be sent when we are already offline. Ignore it.
+ */
+ break;
+
+ default:
+ bfa_sm_fault(__vport_fcs(vport), event);
+ }
+}
+
+
+/**
+ * FDISC is sent and awaiting reply from fabric.
+ */
+static void
+bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
+ enum bfa_fcs_vport_event event)
+{
+ bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+ bfa_trc(__vport_fcs(vport), event);
+
+ switch (event) {
+ case BFA_FCS_VPORT_SM_DELETE:
+ bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
+ bfa_lps_discard(vport->lps);
+ bfa_fcs_lport_delete(&vport->lport);
+ break;
+
+ case BFA_FCS_VPORT_SM_OFFLINE:
+ bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
+ bfa_lps_discard(vport->lps);
+ break;
+
+ case BFA_FCS_VPORT_SM_RSP_OK:
+ bfa_sm_set_state(vport, bfa_fcs_vport_sm_online);
+ bfa_fcs_lport_online(&vport->lport);
+ break;
+
+ case BFA_FCS_VPORT_SM_RSP_ERROR:
+ bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc_retry);
+ bfa_timer_start(__vport_bfa(vport), &vport->timer,
+ bfa_fcs_vport_timeout, vport,
+ BFA_FCS_RETRY_TIMEOUT);
+ break;
+
+ case BFA_FCS_VPORT_SM_RSP_FAILED:
+ bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
+ break;
+
+ case BFA_FCS_VPORT_SM_RSP_DUP_WWN:
+ bfa_sm_set_state(vport, bfa_fcs_vport_sm_error);
+ break;
+
+ default:
+ bfa_sm_fault(__vport_fcs(vport), event);
+ }
+}
+
+/**
+ * FDISC attempt failed - a timer is active to retry FDISC.
+ */
+static void
+bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
+ enum bfa_fcs_vport_event event)
+{
+ bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+ bfa_trc(__vport_fcs(vport), event);
+
+ switch (event) {
+ case BFA_FCS_VPORT_SM_DELETE:
+ bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
+ bfa_timer_stop(&vport->timer);
+ bfa_fcs_lport_delete(&vport->lport);
+ break;
+
+ case BFA_FCS_VPORT_SM_OFFLINE:
+ bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
+ bfa_timer_stop(&vport->timer);
+ break;
+
+ case BFA_FCS_VPORT_SM_TIMEOUT:
+ bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
+ vport->vport_stats.fdisc_retries++;
+ vport->fdisc_retries++;
+ bfa_fcs_vport_do_fdisc(vport);
+ break;
+
+ default:
+ bfa_sm_fault(__vport_fcs(vport), event);
+ }
+}
+
+/**
+ * Vport is online (FDISC is complete).
+ */
+static void
+bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
+ enum bfa_fcs_vport_event event)
+{
+ bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+ bfa_trc(__vport_fcs(vport), event);
+
+ switch (event) {
+ case BFA_FCS_VPORT_SM_DELETE:
+ bfa_sm_set_state(vport, bfa_fcs_vport_sm_deleting);
+ bfa_fcs_lport_delete(&vport->lport);
+ break;
+
+ case BFA_FCS_VPORT_SM_OFFLINE:
+ bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
+ bfa_lps_discard(vport->lps);
+ bfa_fcs_lport_offline(&vport->lport);
+ break;
+
+ default:
+ bfa_sm_fault(__vport_fcs(vport), event);
+ }
+}
+
+/**
+ * Vport is being deleted - awaiting lport delete completion to send
+ * LOGO to fabric.
+ */
+static void
+bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport,
+ enum bfa_fcs_vport_event event)
+{
+ bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+ bfa_trc(__vport_fcs(vport), event);
+
+ switch (event) {
+ case BFA_FCS_VPORT_SM_DELETE:
+ break;
+
+ case BFA_FCS_VPORT_SM_DELCOMP:
+ bfa_sm_set_state(vport, bfa_fcs_vport_sm_logo);
+ bfa_fcs_vport_do_logo(vport);
+ break;
+
+ case BFA_FCS_VPORT_SM_OFFLINE:
+ bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
+ break;
+
+ default:
+ bfa_sm_fault(__vport_fcs(vport), event);
+ }
+}
+
+/**
+ * Error State.
+ * This state will be set when the Vport Creation fails due
+ * to errors like Dup WWN. In this state only operation allowed
+ * is a Vport Delete.
+ */
+static void
+bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport,
+ enum bfa_fcs_vport_event event)
+{
+ bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+ bfa_trc(__vport_fcs(vport), event);
+
+ switch (event) {
+ case BFA_FCS_VPORT_SM_DELETE:
+ bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
+ bfa_fcs_lport_delete(&vport->lport);
+ break;
+
+ default:
+ bfa_trc(__vport_fcs(vport), event);
+ }
+}
+
+/**
+ * Lport cleanup is in progress since vport is being deleted. Fabric is
+ * offline, so no LOGO is needed to complete vport deletion.
+ */
+static void
+bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,
+ enum bfa_fcs_vport_event event)
+{
+ bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+ bfa_trc(__vport_fcs(vport), event);
+
+ switch (event) {
+ case BFA_FCS_VPORT_SM_DELCOMP:
+ bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
+ bfa_fcs_vport_free(vport);
+ break;
+
+ case BFA_FCS_VPORT_SM_DELETE:
+ break;
+
+ default:
+ bfa_sm_fault(__vport_fcs(vport), event);
+ }
+}
+
+/**
+ * LOGO is sent to fabric. Vport delete is in progress. Lport delete cleanup
+ * is done.
+ */
+static void
+bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,
+ enum bfa_fcs_vport_event event)
+{
+ bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+ bfa_trc(__vport_fcs(vport), event);
+
+ switch (event) {
+ case BFA_FCS_VPORT_SM_OFFLINE:
+ bfa_lps_discard(vport->lps);
+ /*
+ * !!! fall through !!!
+ */
+
+ case BFA_FCS_VPORT_SM_RSP_OK:
+ case BFA_FCS_VPORT_SM_RSP_ERROR:
+ bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
+ bfa_fcs_vport_free(vport);
+ break;
+
+ case BFA_FCS_VPORT_SM_DELETE:
+ break;
+
+ default:
+ bfa_sm_fault(__vport_fcs(vport), event);
+ }
+}
+
+
+
+/**
+ * fcs_vport_private FCS virtual port private functions
+ */
+/**
+ * This routine will be called to send a FDISC command.
+ */
+static void
+bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport)
+{
+ bfa_lps_fdisc(vport->lps, vport,
+ bfa_fcport_get_maxfrsize(__vport_bfa(vport)),
+ __vport_pwwn(vport), __vport_nwwn(vport));
+ vport->vport_stats.fdisc_sent++;
+}
+
+static void
+bfa_fcs_vport_fdisc_rejected(struct bfa_fcs_vport_s *vport)
+{
+ u8 lsrjt_rsn = bfa_lps_get_lsrjt_rsn(vport->lps);
+ u8 lsrjt_expl = bfa_lps_get_lsrjt_expl(vport->lps);
+
+ bfa_trc(__vport_fcs(vport), lsrjt_rsn);
+ bfa_trc(__vport_fcs(vport), lsrjt_expl);
+
+ /* For certain reason codes, we don't want to retry. */
+ switch (bfa_lps_get_lsrjt_expl(vport->lps)) {
+ case FC_LS_RJT_EXP_INV_PORT_NAME: /* by brocade */
+ case FC_LS_RJT_EXP_INVALID_NPORT_ID: /* by Cisco */
+ if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
+ bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
+ else
+ bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_DUP_WWN);
+ break;
+
+ case FC_LS_RJT_EXP_INSUFF_RES:
+ /*
+ * This means max logins per port/switch setting on the
+ * switch was exceeded.
+ */
+ if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
+ bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
+ else
+ bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_FAILED);
+ break;
+
+ default:
+ bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
}
+}
+
+/**
+ * Called to send a logout to the fabric. Used when a V-Port is
+ * deleted/stopped.
+ */
+static void
+bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport)
+{
+ bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+
+ vport->vport_stats.logo_sent++;
+ bfa_lps_fdisclogo(vport->lps);
+}
+
+
+/**
+ * This routine will be called by bfa_timer on timer timeouts.
+ *
+ * param[in] vport - pointer to bfa_fcs_vport_t.
+ * param[out] vport_status - pointer to return vport status in
+ *
+ * return
+ * void
+ *
+ * Special Considerations:
+ *
+ * note
+ */
+static void
+bfa_fcs_vport_timeout(void *vport_arg)
+{
+ struct bfa_fcs_vport_s *vport = (struct bfa_fcs_vport_s *) vport_arg;
+
+ vport->vport_stats.fdisc_timeouts++;
+ bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_TIMEOUT);
+}
+
+static void
+bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport)
+{
+ struct bfad_vport_s *vport_drv =
+ (struct bfad_vport_s *)vport->vport_drv;
+
+ bfa_fcs_fabric_delvport(__vport_fabric(vport), vport);
+
+ if (vport_drv->comp_del)
+ complete(vport_drv->comp_del);
+
+ bfa_lps_delete(vport->lps);
+}
+
+
+/**
+ * fcs_vport_public FCS virtual port public interfaces
+ */
+
+/**
+ * Online notification from fabric SM.
+ */
+void
+bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport)
+{
+ vport->vport_stats.fab_online++;
+ bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);
+}
+
+/**
+ * Offline notification from fabric SM.
+ */
+void
+bfa_fcs_vport_offline(struct bfa_fcs_vport_s *vport)
+{
+ vport->vport_stats.fab_offline++;
+ bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE);
+}
+
+/**
+ * Cleanup notification from fabric SM on link timer expiry.
+ */
+void
+bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s *vport)
+{
+ vport->vport_stats.fab_cleanup++;
+}
+/**
+ * delete notification from fabric SM. To be invoked from within FCS.
+ */
+void
+bfa_fcs_vport_fcs_delete(struct bfa_fcs_vport_s *vport)
+{
+ bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE);
}
+/**
+ * Delete completion callback from associated lport
+ */
+void
+bfa_fcs_vport_delete_comp(struct bfa_fcs_vport_s *vport)
+{
+ bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELCOMP);
+}
+
+
+/**
+ * fcs_vport_api Virtual port API
+ */
+
+/**
+ * Use this function to instantiate a new FCS vport object. This
+ * function will not trigger any HW initialization process (which will be
+ * done in vport_start() call)
+ *
+ * param[in] vport - pointer to bfa_fcs_vport_t. This space
+ * needs to be allocated by the driver.
+ * param[in] fcs - FCS instance
+ * param[in] vport_cfg - vport configuration
+ * param[in] vf_id - VF_ID if vport is created within a VF.
+ * FC_VF_ID_NULL to specify base fabric.
+ * param[in] vport_drv - Opaque handle back to the driver's vport
+ * structure
+ *
+ * retval BFA_STATUS_OK - on success.
+ * retval BFA_STATUS_FAILED - on failure.
+ */
+bfa_status_t
+bfa_fcs_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs,
+ u16 vf_id, struct bfa_lport_cfg_s *vport_cfg,
+ struct bfad_vport_s *vport_drv)
+{
+ if (vport_cfg->pwwn == 0)
+ return BFA_STATUS_INVALID_WWN;
+
+ if (bfa_fcs_lport_get_pwwn(&fcs->fabric.bport) == vport_cfg->pwwn)
+ return BFA_STATUS_VPORT_WWN_BP;
+
+ if (bfa_fcs_vport_lookup(fcs, vf_id, vport_cfg->pwwn) != NULL)
+ return BFA_STATUS_VPORT_EXISTS;
+
+ if (bfa_fcs_fabric_vport_count(&fcs->fabric) ==
+ bfa_lps_get_max_vport(fcs->bfa))
+ return BFA_STATUS_VPORT_MAX;
+
+ vport->lps = bfa_lps_alloc(fcs->bfa);
+ if (!vport->lps)
+ return BFA_STATUS_VPORT_MAX;
+
+ vport->vport_drv = vport_drv;
+ vport_cfg->preboot_vp = BFA_FALSE;
+
+ bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
+ bfa_fcs_lport_attach(&vport->lport, fcs, vf_id, vport);
+ bfa_fcs_lport_init(&vport->lport, vport_cfg);
+ bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_CREATE);
+
+ return BFA_STATUS_OK;
+}
+
+/**
+ * Use this function to instantiate a new FCS PBC vport object. This
+ * function will not trigger any HW initialization process (which will be
+ * done in vport_start() call)
+ *
+ * param[in] vport - pointer to bfa_fcs_vport_t. This space
+ * needs to be allocated by the driver.
+ * param[in] fcs - FCS instance
+ * param[in] vport_cfg - vport configuration
+ * param[in] vf_id - VF_ID if vport is created within a VF.
+ * FC_VF_ID_NULL to specify base fabric.
+ * param[in] vport_drv - Opaque handle back to the driver's vport
+ * structure
+ *
+ * retval BFA_STATUS_OK - on success.
+ * retval BFA_STATUS_FAILED - on failure.
+ */
+bfa_status_t
+bfa_fcs_pbc_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs,
+ u16 vf_id, struct bfa_lport_cfg_s *vport_cfg,
+ struct bfad_vport_s *vport_drv)
+{
+ bfa_status_t rc;
+
+ rc = bfa_fcs_vport_create(vport, fcs, vf_id, vport_cfg, vport_drv);
+ vport->lport.port_cfg.preboot_vp = BFA_TRUE;
+
+ return rc;
+}
+
+/**
+ * Use this function to findout if this is a pbc vport or not.
+ *
+ * @param[in] vport - pointer to bfa_fcs_vport_t.
+ *
+ * @returns None
+ */
+bfa_boolean_t
+bfa_fcs_is_pbc_vport(struct bfa_fcs_vport_s *vport)
+{
+
+ if (vport && (vport->lport.port_cfg.preboot_vp == BFA_TRUE))
+ return BFA_TRUE;
+ else
+ return BFA_FALSE;
+
+}
+
+/**
+ * Use this function initialize the vport.
+ *
+ * @param[in] vport - pointer to bfa_fcs_vport_t.
+ *
+ * @returns None
+ */
+bfa_status_t
+bfa_fcs_vport_start(struct bfa_fcs_vport_s *vport)
+{
+ bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_START);
+
+ return BFA_STATUS_OK;
+}
+
+/**
+ * Use this function quiese the vport object. This function will return
+ * immediately, when the vport is actually stopped, the
+ * bfa_drv_vport_stop_cb() will be called.
+ *
+ * param[in] vport - pointer to bfa_fcs_vport_t.
+ *
+ * return None
+ */
+bfa_status_t
+bfa_fcs_vport_stop(struct bfa_fcs_vport_s *vport)
+{
+ bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOP);
+
+ return BFA_STATUS_OK;
+}
+
+/**
+ * Use this function to delete a vport object. Fabric object should
+ * be stopped before this function call.
+ *
+ * !!!!!!! Donot invoke this from within FCS !!!!!!!
+ *
+ * param[in] vport - pointer to bfa_fcs_vport_t.
+ *
+ * return None
+ */
+bfa_status_t
+bfa_fcs_vport_delete(struct bfa_fcs_vport_s *vport)
+{
+
+ if (vport->lport.port_cfg.preboot_vp)
+ return BFA_STATUS_PBC;
+
+ bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE);
+
+ return BFA_STATUS_OK;
+}
+
+/**
+ * Use this function to get vport's current status info.
+ *
+ * param[in] vport pointer to bfa_fcs_vport_t.
+ * param[out] attr pointer to return vport attributes
+ *
+ * return None
+ */
+void
+bfa_fcs_vport_get_attr(struct bfa_fcs_vport_s *vport,
+ struct bfa_vport_attr_s *attr)
+{
+ if (vport == NULL || attr == NULL)
+ return;
+
+ bfa_os_memset(attr, 0, sizeof(struct bfa_vport_attr_s));
+
+ bfa_fcs_lport_get_attr(&vport->lport, &attr->port_attr);
+ attr->vport_state = bfa_sm_to_state(vport_sm_table, vport->sm);
+}
+
+/**
+ * Use this function to get vport's statistics.
+ *
+ * param[in] vport pointer to bfa_fcs_vport_t.
+ * param[out] stats pointer to return vport statistics in
+ *
+ * return None
+ */
+void
+bfa_fcs_vport_get_stats(struct bfa_fcs_vport_s *vport,
+ struct bfa_vport_stats_s *stats)
+{
+ *stats = vport->vport_stats;
+}
+
+/**
+ * Use this function to clear vport's statistics.
+ *
+ * param[in] vport pointer to bfa_fcs_vport_t.
+ *
+ * return None
+ */
+void
+bfa_fcs_vport_clr_stats(struct bfa_fcs_vport_s *vport)
+{
+ bfa_os_memset(&vport->vport_stats, 0, sizeof(struct bfa_vport_stats_s));
+}
+
+/**
+ * Lookup a virtual port. Excludes base port from lookup.
+ */
+struct bfa_fcs_vport_s *
+bfa_fcs_vport_lookup(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t vpwwn)
+{
+ struct bfa_fcs_vport_s *vport;
+ struct bfa_fcs_fabric_s *fabric;
+
+ bfa_trc(fcs, vf_id);
+ bfa_trc(fcs, vpwwn);
+
+ fabric = bfa_fcs_vf_lookup(fcs, vf_id);
+ if (!fabric) {
+ bfa_trc(fcs, vf_id);
+ return NULL;
+ }
+
+ vport = bfa_fcs_fabric_vport_lookup(fabric, vpwwn);
+ return vport;
+}
+
+/**
+ * FDISC Response
+ */
+void
+bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status)
+{
+ struct bfa_fcs_vport_s *vport = uarg;
+
+ bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+ bfa_trc(__vport_fcs(vport), status);
+
+ switch (status) {
+ case BFA_STATUS_OK:
+ /*
+ * Initialiaze the V-Port fields
+ */
+ __vport_fcid(vport) = bfa_lps_get_pid(vport->lps);
+ vport->vport_stats.fdisc_accepts++;
+ bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK);
+ break;
+
+ case BFA_STATUS_INVALID_MAC:
+ /* Only for CNA */
+ vport->vport_stats.fdisc_acc_bad++;
+ bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
+
+ break;
+
+ case BFA_STATUS_EPROTOCOL:
+ switch (bfa_lps_get_extstatus(vport->lps)) {
+ case BFA_EPROTO_BAD_ACCEPT:
+ vport->vport_stats.fdisc_acc_bad++;
+ break;
+
+ case BFA_EPROTO_UNKNOWN_RSP:
+ vport->vport_stats.fdisc_unknown_rsp++;
+ break;
+
+ default:
+ break;
+ }
+
+ bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
+ break;
+
+ case BFA_STATUS_FABRIC_RJT:
+ vport->vport_stats.fdisc_rejects++;
+ bfa_fcs_vport_fdisc_rejected(vport);
+ break;
+
+ default:
+ vport->vport_stats.fdisc_rsp_err++;
+ bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
+ }
+}
+
+/**
+ * LOGO response
+ */
+void
+bfa_cb_lps_fdisclogo_comp(void *bfad, void *uarg)
+{
+ struct bfa_fcs_vport_s *vport = uarg;
+ bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK);
+}
+
+/**
+ * Received clear virtual link
+ */
+void
+bfa_cb_lps_cvl_event(void *bfad, void *uarg)
+{
+ struct bfa_fcs_vport_s *vport = uarg;
+
+ /* Send an Offline followed by an ONLINE */
+ bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE);
+ bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);
+}
diff --git a/drivers/scsi/bfa/bfa_fcs_port.c b/drivers/scsi/bfa/bfa_fcs_port.c
deleted file mode 100644
index 3c27788cd527..000000000000
--- a/drivers/scsi/bfa/bfa_fcs_port.c
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/**
- * bfa_fcs_pport.c BFA FCS PPORT ( physical port)
- */
-
-#include <fcs/bfa_fcs.h>
-#include <bfa_svc.h>
-#include <fcs/bfa_fcs_fabric.h>
-#include "fcs_trcmod.h"
-#include "fcs.h"
-#include "fcs_fabric.h"
-#include "fcs_port.h"
-
-BFA_TRC_FILE(FCS, PPORT);
-
-static void
-bfa_fcs_pport_event_handler(void *cbarg, bfa_pport_event_t event)
-{
- struct bfa_fcs_s *fcs = cbarg;
-
- bfa_trc(fcs, event);
-
- switch (event) {
- case BFA_PPORT_LINKUP:
- bfa_fcs_fabric_link_up(&fcs->fabric);
- break;
-
- case BFA_PPORT_LINKDOWN:
- bfa_fcs_fabric_link_down(&fcs->fabric);
- break;
-
- case BFA_PPORT_TRUNK_LINKDOWN:
- bfa_assert(0);
- break;
-
- default:
- bfa_assert(0);
- }
-}
-
-void
-bfa_fcs_pport_attach(struct bfa_fcs_s *fcs)
-{
- bfa_fcport_event_register(fcs->bfa, bfa_fcs_pport_event_handler, fcs);
-}
diff --git a/drivers/scsi/bfa/rport.c b/drivers/scsi/bfa/bfa_fcs_rport.c
index 9b4c2c9a644b..635f0cd88714 100644
--- a/drivers/scsi/bfa/rport.c
+++ b/drivers/scsi/bfa/bfa_fcs_rport.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
* All rights reserved
* www.brocade.com
*
@@ -19,151 +19,133 @@
* rport.c Remote port implementation.
*/
-#include <linux/slab.h>
-#include <bfa.h>
-#include <bfa_svc.h>
-#include "fcbuild.h"
-#include "fcs_vport.h"
-#include "fcs_lport.h"
-#include "fcs_rport.h"
-#include "fcs_fcpim.h"
-#include "fcs_fcptm.h"
-#include "fcs_trcmod.h"
-#include "fcs_fcxp.h"
-#include "fcs.h"
-#include <fcb/bfa_fcb_rport.h>
-#include <aen/bfa_aen_rport.h>
+#include "bfa_fcs.h"
+#include "bfa_fcbuild.h"
+#include "bfad_drv.h"
BFA_TRC_FILE(FCS, RPORT);
-/* In millisecs */
-static u32 bfa_fcs_rport_del_timeout =
- BFA_FCS_RPORT_DEF_DEL_TIMEOUT * 1000;
-
+static u32
+bfa_fcs_rport_del_timeout = BFA_FCS_RPORT_DEF_DEL_TIMEOUT * 1000;
+ /* In millisecs */
/*
* forward declarations
*/
-static struct bfa_fcs_rport_s *bfa_fcs_rport_alloc(struct bfa_fcs_port_s *port,
- wwn_t pwwn, u32 rpid);
-static void bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport);
-static void bfa_fcs_rport_hal_online(struct bfa_fcs_rport_s *rport);
-static void bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport);
-static void bfa_fcs_rport_offline_action(struct bfa_fcs_rport_s *rport);
-static void bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport,
- struct fc_logi_s *plogi);
-static void bfa_fcs_rport_fc4_pause(struct bfa_fcs_rport_s *rport);
-static void bfa_fcs_rport_fc4_resume(struct bfa_fcs_rport_s *rport);
-static void bfa_fcs_rport_timeout(void *arg);
-static void bfa_fcs_rport_send_plogi(void *rport_cbarg,
+static struct bfa_fcs_rport_s *bfa_fcs_rport_alloc(
+ struct bfa_fcs_lport_s *port, wwn_t pwwn, u32 rpid);
+static void bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport);
+static void bfa_fcs_rport_hal_online(struct bfa_fcs_rport_s *rport);
+static void bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport);
+static void bfa_fcs_rport_offline_action(struct bfa_fcs_rport_s *rport);
+static void bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport,
+ struct fc_logi_s *plogi);
+static void bfa_fcs_rport_timeout(void *arg);
+static void bfa_fcs_rport_send_plogi(void *rport_cbarg,
struct bfa_fcxp_s *fcxp_alloced);
-static void bfa_fcs_rport_send_plogiacc(void *rport_cbarg,
- struct bfa_fcxp_s *fcxp_alloced);
-static void bfa_fcs_rport_plogi_response(void *fcsarg,
- struct bfa_fcxp_s *fcxp,
- void *cbarg,
- bfa_status_t req_status,
- u32 rsp_len,
- u32 resid_len,
- struct fchs_s *rsp_fchs);
-static void bfa_fcs_rport_send_adisc(void *rport_cbarg,
+static void bfa_fcs_rport_send_plogiacc(void *rport_cbarg,
+ struct bfa_fcxp_s *fcxp_alloced);
+static void bfa_fcs_rport_plogi_response(void *fcsarg,
+ struct bfa_fcxp_s *fcxp, void *cbarg,
+ bfa_status_t req_status, u32 rsp_len,
+ u32 resid_len, struct fchs_s *rsp_fchs);
+static void bfa_fcs_rport_send_adisc(void *rport_cbarg,
struct bfa_fcxp_s *fcxp_alloced);
-static void bfa_fcs_rport_adisc_response(void *fcsarg,
- struct bfa_fcxp_s *fcxp,
- void *cbarg,
- bfa_status_t req_status,
- u32 rsp_len,
- u32 resid_len,
- struct fchs_s *rsp_fchs);
-static void bfa_fcs_rport_send_gidpn(void *rport_cbarg,
+static void bfa_fcs_rport_adisc_response(void *fcsarg,
+ struct bfa_fcxp_s *fcxp, void *cbarg,
+ bfa_status_t req_status, u32 rsp_len,
+ u32 resid_len, struct fchs_s *rsp_fchs);
+static void bfa_fcs_rport_send_nsdisc(void *rport_cbarg,
struct bfa_fcxp_s *fcxp_alloced);
-static void bfa_fcs_rport_gidpn_response(void *fcsarg,
- struct bfa_fcxp_s *fcxp,
- void *cbarg,
- bfa_status_t req_status,
- u32 rsp_len,
- u32 resid_len,
- struct fchs_s *rsp_fchs);
-static void bfa_fcs_rport_send_logo(void *rport_cbarg,
+static void bfa_fcs_rport_gidpn_response(void *fcsarg,
+ struct bfa_fcxp_s *fcxp, void *cbarg,
+ bfa_status_t req_status, u32 rsp_len,
+ u32 resid_len, struct fchs_s *rsp_fchs);
+static void bfa_fcs_rport_gpnid_response(void *fcsarg,
+ struct bfa_fcxp_s *fcxp, void *cbarg,
+ bfa_status_t req_status, u32 rsp_len,
+ u32 resid_len, struct fchs_s *rsp_fchs);
+static void bfa_fcs_rport_send_logo(void *rport_cbarg,
struct bfa_fcxp_s *fcxp_alloced);
-static void bfa_fcs_rport_send_logo_acc(void *rport_cbarg);
-static void bfa_fcs_rport_process_prli(struct bfa_fcs_rport_s *rport,
- struct fchs_s *rx_fchs, u16 len);
-static void bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport,
- struct fchs_s *rx_fchs, u8 reason_code,
- u8 reason_code_expl);
-static void bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport,
- struct fchs_s *rx_fchs, u16 len);
-static void bfa_fcs_rport_send_prlo_acc(struct bfa_fcs_rport_s *rport);
+static void bfa_fcs_rport_send_logo_acc(void *rport_cbarg);
+static void bfa_fcs_rport_process_prli(struct bfa_fcs_rport_s *rport,
+ struct fchs_s *rx_fchs, u16 len);
+static void bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport,
+ struct fchs_s *rx_fchs, u8 reason_code,
+ u8 reason_code_expl);
+static void bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport,
+ struct fchs_s *rx_fchs, u16 len);
+static void bfa_fcs_rport_send_prlo_acc(struct bfa_fcs_rport_s *rport);
/**
* fcs_rport_sm FCS rport state machine events
*/
enum rport_event {
- RPSM_EVENT_PLOGI_SEND = 1, /* new rport; start with PLOGI */
- RPSM_EVENT_PLOGI_RCVD = 2, /* Inbound PLOGI from remote port */
- RPSM_EVENT_PLOGI_COMP = 3, /* PLOGI completed to rport */
- RPSM_EVENT_LOGO_RCVD = 4, /* LOGO from remote device */
- RPSM_EVENT_LOGO_IMP = 5, /* implicit logo for SLER */
- RPSM_EVENT_FCXP_SENT = 6, /* Frame from has been sent */
- RPSM_EVENT_DELETE = 7, /* RPORT delete request */
- RPSM_EVENT_SCN = 8, /* state change notification */
- RPSM_EVENT_ACCEPTED = 9,/* Good response from remote device */
- RPSM_EVENT_FAILED = 10, /* Request to rport failed. */
- RPSM_EVENT_TIMEOUT = 11, /* Rport SM timeout event */
- RPSM_EVENT_HCB_ONLINE = 12, /* BFA rport online callback */
- RPSM_EVENT_HCB_OFFLINE = 13, /* BFA rport offline callback */
- RPSM_EVENT_FC4_OFFLINE = 14, /* FC-4 offline complete */
- RPSM_EVENT_ADDRESS_CHANGE = 15, /* Rport's PID has changed */
+ RPSM_EVENT_PLOGI_SEND = 1, /* new rport; start with PLOGI */
+ RPSM_EVENT_PLOGI_RCVD = 2, /* Inbound PLOGI from remote port */
+ RPSM_EVENT_PLOGI_COMP = 3, /* PLOGI completed to rport */
+ RPSM_EVENT_LOGO_RCVD = 4, /* LOGO from remote device */
+ RPSM_EVENT_LOGO_IMP = 5, /* implicit logo for SLER */
+ RPSM_EVENT_FCXP_SENT = 6, /* Frame from has been sent */
+ RPSM_EVENT_DELETE = 7, /* RPORT delete request */
+ RPSM_EVENT_SCN = 8, /* state change notification */
+ RPSM_EVENT_ACCEPTED = 9, /* Good response from remote device */
+ RPSM_EVENT_FAILED = 10, /* Request to rport failed. */
+ RPSM_EVENT_TIMEOUT = 11, /* Rport SM timeout event */
+ RPSM_EVENT_HCB_ONLINE = 12, /* BFA rport online callback */
+ RPSM_EVENT_HCB_OFFLINE = 13, /* BFA rport offline callback */
+ RPSM_EVENT_FC4_OFFLINE = 14, /* FC-4 offline complete */
+ RPSM_EVENT_ADDRESS_CHANGE = 15, /* Rport's PID has changed */
RPSM_EVENT_ADDRESS_DISC = 16, /* Need to Discover rport's PID */
- RPSM_EVENT_PRLO_RCVD = 17, /* PRLO from remote device */
+ RPSM_EVENT_PRLO_RCVD = 17, /* PRLO from remote device */
+ RPSM_EVENT_PLOGI_RETRY = 18, /* Retry PLOGI continously */
};
-static void bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport,
+static void bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport,
enum rport_event event);
-static void bfa_fcs_rport_sm_plogi_sending(struct bfa_fcs_rport_s *rport,
- enum rport_event event);
-static void bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport,
+static void bfa_fcs_rport_sm_plogi_sending(struct bfa_fcs_rport_s *rport,
+ enum rport_event event);
+static void bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport,
enum rport_event event);
-static void bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport,
- enum rport_event event);
-static void bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport,
- enum rport_event event);
-static void bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,
- enum rport_event event);
-static void bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport,
+static void bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport,
+ enum rport_event event);
+static void bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport,
enum rport_event event);
-static void bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,
+static void bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,
+ enum rport_event event);
+static void bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport,
+ enum rport_event event);
+static void bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,
enum rport_event event);
-static void bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport,
+static void bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport,
enum rport_event event);
-static void bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,
- enum rport_event event);
-static void bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport,
- enum rport_event event);
-static void bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,
- enum rport_event event);
-static void bfa_fcs_rport_sm_fc4_logosend(struct bfa_fcs_rport_s *rport,
- enum rport_event event);
-static void bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport,
- enum rport_event event);
-static void bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,
- enum rport_event event);
-static void bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport,
- enum rport_event event);
-static void bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport,
- enum rport_event event);
-static void bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport,
- enum rport_event event);
-static void bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport,
+static void bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,
+ enum rport_event event);
+static void bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport,
+ enum rport_event event);
+static void bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,
+ enum rport_event event);
+static void bfa_fcs_rport_sm_fc4_logosend(struct bfa_fcs_rport_s *rport,
+ enum rport_event event);
+static void bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport,
+ enum rport_event event);
+static void bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,
+ enum rport_event event);
+static void bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport,
+ enum rport_event event);
+static void bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport,
+ enum rport_event event);
+static void bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport,
+ enum rport_event event);
+static void bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport,
enum rport_event event);
-static void bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport,
+static void bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport,
+ enum rport_event event);
+static void bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport,
+ enum rport_event event);
+static void bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
+ enum rport_event event);
+static void bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
enum rport_event event);
-static void bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport,
- enum rport_event event);
-static void bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
- enum rport_event event);
-static void bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
- enum rport_event event);
static struct bfa_sm_table_s rport_sm_table[] = {
{BFA_SM(bfa_fcs_rport_sm_uninit), BFA_RPORT_UNINIT},
@@ -191,7 +173,7 @@ static struct bfa_sm_table_s rport_sm_table[] = {
};
/**
- * Beginning state.
+ * Beginning state.
*/
static void
bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport, enum rport_event event)
@@ -221,20 +203,19 @@ bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport, enum rport_event event)
case RPSM_EVENT_ADDRESS_DISC:
bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
rport->ns_retries = 0;
- bfa_fcs_rport_send_gidpn(rport, NULL);
+ bfa_fcs_rport_send_nsdisc(rport, NULL);
break;
-
default:
bfa_sm_fault(rport->fcs, event);
}
}
/**
- * PLOGI is being sent.
+ * PLOGI is being sent.
*/
static void
bfa_fcs_rport_sm_plogi_sending(struct bfa_fcs_rport_s *rport,
- enum rport_event event)
+ enum rport_event event)
{
bfa_trc(rport->fcs, rport->pwwn);
bfa_trc(rport->fcs, rport->pid);
@@ -258,10 +239,12 @@ bfa_fcs_rport_sm_plogi_sending(struct bfa_fcs_rport_s *rport,
break;
case RPSM_EVENT_ADDRESS_CHANGE:
+ case RPSM_EVENT_SCN:
+ /* query the NS */
bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
rport->ns_retries = 0;
- bfa_fcs_rport_send_gidpn(rport, NULL);
+ bfa_fcs_rport_send_nsdisc(rport, NULL);
break;
case RPSM_EVENT_LOGO_IMP:
@@ -273,8 +256,6 @@ bfa_fcs_rport_sm_plogi_sending(struct bfa_fcs_rport_s *rport,
bfa_fcs_rport_del_timeout);
break;
- case RPSM_EVENT_SCN:
- break;
default:
bfa_sm_fault(rport->fcs, event);
@@ -282,11 +263,11 @@ bfa_fcs_rport_sm_plogi_sending(struct bfa_fcs_rport_s *rport,
}
/**
- * PLOGI is being sent.
+ * PLOGI is being sent.
*/
static void
bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport,
- enum rport_event event)
+ enum rport_event event)
{
bfa_trc(rport->fcs, rport->pwwn);
bfa_trc(rport->fcs, rport->pid);
@@ -304,6 +285,7 @@ bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport,
bfa_fcs_rport_free(rport);
break;
+ case RPSM_EVENT_PLOGI_RCVD:
case RPSM_EVENT_SCN:
/**
* Ignore, SCN is possibly online notification.
@@ -314,7 +296,7 @@ bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport,
bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
rport->ns_retries = 0;
- bfa_fcs_rport_send_gidpn(rport, NULL);
+ bfa_fcs_rport_send_nsdisc(rport, NULL);
break;
case RPSM_EVENT_LOGO_IMP:
@@ -338,7 +320,7 @@ bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport,
}
/**
- * PLOGI is sent.
+ * PLOGI is sent.
*/
static void
bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport,
@@ -349,24 +331,9 @@ bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport,
bfa_trc(rport->fcs, event);
switch (event) {
- case RPSM_EVENT_SCN:
- bfa_timer_stop(&rport->timer);
- /*
- * !! fall through !!
- */
-
case RPSM_EVENT_TIMEOUT:
- if (rport->plogi_retries < BFA_FCS_RPORT_MAX_RETRIES) {
- rport->plogi_retries++;
- bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
- bfa_fcs_rport_send_plogi(rport, NULL);
- } else {
- rport->pid = 0;
- bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
- bfa_timer_start(rport->fcs->bfa, &rport->timer,
- bfa_fcs_rport_timeout, rport,
- bfa_fcs_rport_del_timeout);
- }
+ bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
+ bfa_fcs_rport_send_plogi(rport, NULL);
break;
case RPSM_EVENT_DELETE:
@@ -386,10 +353,11 @@ bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport,
break;
case RPSM_EVENT_ADDRESS_CHANGE:
+ case RPSM_EVENT_SCN:
bfa_timer_stop(&rport->timer);
bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
rport->ns_retries = 0;
- bfa_fcs_rport_send_gidpn(rport, NULL);
+ bfa_fcs_rport_send_nsdisc(rport, NULL);
break;
case RPSM_EVENT_LOGO_IMP:
@@ -413,7 +381,7 @@ bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport,
}
/**
- * PLOGI is sent.
+ * PLOGI is sent.
*/
static void
bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event)
@@ -443,10 +411,28 @@ bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event)
* !! fall through !!
*/
case RPSM_EVENT_FAILED:
+ if (rport->plogi_retries < BFA_FCS_RPORT_MAX_RETRIES) {
+ rport->plogi_retries++;
+ bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_retry);
+ bfa_timer_start(rport->fcs->bfa, &rport->timer,
+ bfa_fcs_rport_timeout, rport,
+ BFA_FCS_RETRY_TIMEOUT);
+ } else {
+ bfa_stats(rport->port, rport_del_max_plogi_retry);
+ rport->pid = 0;
+ bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+ bfa_timer_start(rport->fcs->bfa, &rport->timer,
+ bfa_fcs_rport_timeout, rport,
+ bfa_fcs_rport_del_timeout);
+ }
+ break;
+
+ case RPSM_EVENT_PLOGI_RETRY:
+ rport->plogi_retries = 0;
bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_retry);
bfa_timer_start(rport->fcs->bfa, &rport->timer,
bfa_fcs_rport_timeout, rport,
- BFA_FCS_RETRY_TIMEOUT);
+ (FC_RA_TOV * 1000));
break;
case RPSM_EVENT_LOGO_IMP:
@@ -459,10 +445,11 @@ bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event)
break;
case RPSM_EVENT_ADDRESS_CHANGE:
+ case RPSM_EVENT_SCN:
bfa_fcxp_discard(rport->fcxp);
bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
rport->ns_retries = 0;
- bfa_fcs_rport_send_gidpn(rport, NULL);
+ bfa_fcs_rport_send_nsdisc(rport, NULL);
break;
case RPSM_EVENT_PLOGI_RCVD:
@@ -471,12 +458,6 @@ bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event)
bfa_fcs_rport_send_plogiacc(rport, NULL);
break;
- case RPSM_EVENT_SCN:
- /**
- * Ignore SCN - wait for PLOGI response.
- */
- break;
-
case RPSM_EVENT_DELETE:
bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
bfa_fcxp_discard(rport->fcxp);
@@ -495,8 +476,8 @@ bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event)
}
/**
- * PLOGI is complete. Awaiting BFA rport online callback. FC-4s
- * are offline.
+ * PLOGI is complete. Awaiting BFA rport online callback. FC-4s
+ * are offline.
*/
static void
bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,
@@ -551,7 +532,7 @@ bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,
}
/**
- * Rport is ONLINE. FC-4s active.
+ * Rport is ONLINE. FC-4s active.
*/
static void
bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport, enum rport_event event)
@@ -562,18 +543,11 @@ bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport, enum rport_event event)
switch (event) {
case RPSM_EVENT_SCN:
- /**
- * Pause FC-4 activity till rport is authenticated.
- * In switched fabrics, check presence of device in nameserver
- * first.
- */
- bfa_fcs_rport_fc4_pause(rport);
-
if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {
bfa_sm_set_state(rport,
bfa_fcs_rport_sm_nsquery_sending);
rport->ns_retries = 0;
- bfa_fcs_rport_send_gidpn(rport, NULL);
+ bfa_fcs_rport_send_nsdisc(rport, NULL);
} else {
bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_sending);
bfa_fcs_rport_send_adisc(rport, NULL);
@@ -607,12 +581,12 @@ bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport, enum rport_event event)
}
/**
- * An SCN event is received in ONLINE state. NS query is being sent
- * prior to ADISC authentication with rport. FC-4s are paused.
+ * An SCN event is received in ONLINE state. NS query is being sent
+ * prior to ADISC authentication with rport. FC-4s are paused.
*/
static void
bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,
- enum rport_event event)
+ enum rport_event event)
{
bfa_trc(rport->fcs, rport->pwwn);
bfa_trc(rport->fcs, rport->pid);
@@ -665,8 +639,8 @@ bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,
}
/**
- * An SCN event is received in ONLINE state. NS query is sent to rport.
- * FC-4s are paused.
+ * An SCN event is received in ONLINE state. NS query is sent to rport.
+ * FC-4s are paused.
*/
static void
bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport, enum rport_event event)
@@ -686,7 +660,7 @@ bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport, enum rport_event event)
if (rport->ns_retries < BFA_FCS_RPORT_MAX_RETRIES) {
bfa_sm_set_state(rport,
bfa_fcs_rport_sm_nsquery_sending);
- bfa_fcs_rport_send_gidpn(rport, NULL);
+ bfa_fcs_rport_send_nsdisc(rport, NULL);
} else {
bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
bfa_fcs_rport_offline_action(rport);
@@ -724,12 +698,12 @@ bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport, enum rport_event event)
}
/**
- * An SCN event is received in ONLINE state. ADISC is being sent for
- * authenticating with rport. FC-4s are paused.
+ * An SCN event is received in ONLINE state. ADISC is being sent for
+ * authenticating with rport. FC-4s are paused.
*/
static void
bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,
- enum rport_event event)
+ enum rport_event event)
{
bfa_trc(rport->fcs, rport->pwwn);
bfa_trc(rport->fcs, rport->pid);
@@ -775,8 +749,8 @@ bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,
}
/**
- * An SCN event is received in ONLINE state. ADISC is to rport.
- * FC-4s are paused.
+ * An SCN event is received in ONLINE state. ADISC is to rport.
+ * FC-4s are paused.
*/
static void
bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport, enum rport_event event)
@@ -788,7 +762,6 @@ bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport, enum rport_event event)
switch (event) {
case RPSM_EVENT_ACCEPTED:
bfa_sm_set_state(rport, bfa_fcs_rport_sm_online);
- bfa_fcs_rport_fc4_resume(rport);
break;
case RPSM_EVENT_PLOGI_RCVD:
@@ -838,7 +811,7 @@ bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport, enum rport_event event)
}
/**
- * Rport has sent LOGO. Awaiting FC-4 offline completion callback.
+ * Rport has sent LOGO. Awaiting FC-4 offline completion callback.
*/
static void
bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,
@@ -869,12 +842,12 @@ bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,
}
/**
- * LOGO needs to be sent to rport. Awaiting FC-4 offline completion
- * callback.
+ * LOGO needs to be sent to rport. Awaiting FC-4 offline completion
+ * callback.
*/
static void
bfa_fcs_rport_sm_fc4_logosend(struct bfa_fcs_rport_s *rport,
- enum rport_event event)
+ enum rport_event event)
{
bfa_trc(rport->fcs, rport->pwwn);
bfa_trc(rport->fcs, rport->pid);
@@ -892,7 +865,7 @@ bfa_fcs_rport_sm_fc4_logosend(struct bfa_fcs_rport_s *rport,
}
/**
- * Rport is going offline. Awaiting FC-4 offline completion callback.
+ * Rport is going offline. Awaiting FC-4 offline completion callback.
*/
static void
bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport,
@@ -929,12 +902,12 @@ bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport,
}
/**
- * Rport is offline. FC-4s are offline. Awaiting BFA rport offline
- * callback.
+ * Rport is offline. FC-4s are offline. Awaiting BFA rport offline
+ * callback.
*/
static void
bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,
- enum rport_event event)
+ enum rport_event event)
{
bfa_trc(rport->fcs, rport->pwwn);
bfa_trc(rport->fcs, rport->pid);
@@ -943,12 +916,12 @@ bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,
switch (event) {
case RPSM_EVENT_HCB_OFFLINE:
case RPSM_EVENT_ADDRESS_CHANGE:
- if (bfa_fcs_port_is_online(rport->port)) {
+ if (bfa_fcs_lport_is_online(rport->port)) {
if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {
bfa_sm_set_state(rport,
bfa_fcs_rport_sm_nsdisc_sending);
rport->ns_retries = 0;
- bfa_fcs_rport_send_gidpn(rport, NULL);
+ bfa_fcs_rport_send_nsdisc(rport, NULL);
} else {
bfa_sm_set_state(rport,
bfa_fcs_rport_sm_plogi_sending);
@@ -983,8 +956,8 @@ bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,
}
/**
- * Rport is offline. FC-4s are offline. Awaiting BFA rport offline
- * callback to send LOGO accept.
+ * Rport is offline. FC-4s are offline. Awaiting BFA rport offline
+ * callback to send LOGO accept.
*/
static void
bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport,
@@ -1001,21 +974,21 @@ bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport,
bfa_fcs_rport_send_prlo_acc(rport);
if (rport->pid && (rport->prlo == BFA_FALSE))
bfa_fcs_rport_send_logo_acc(rport);
-
/*
- * If the lport is online and if the rport is not a well known
- * address port, we try to re-discover the r-port.
+ * If the lport is online and if the rport is not a well
+ * known address port,
+ * we try to re-discover the r-port.
*/
- if (bfa_fcs_port_is_online(rport->port)
- && (!BFA_FCS_PID_IS_WKA(rport->pid))) {
+ if (bfa_fcs_lport_is_online(rport->port) &&
+ (!BFA_FCS_PID_IS_WKA(rport->pid))) {
bfa_sm_set_state(rport,
- bfa_fcs_rport_sm_nsdisc_sending);
+ bfa_fcs_rport_sm_nsdisc_sending);
rport->ns_retries = 0;
- bfa_fcs_rport_send_gidpn(rport, NULL);
+ bfa_fcs_rport_send_nsdisc(rport, NULL);
} else {
/*
- * if it is not a well known address, reset the pid to
- *
+ * if it is not a well known address, reset the
+ * pid to 0.
*/
if (!BFA_FCS_PID_IS_WKA(rport->pid))
rport->pid = 0;
@@ -1047,12 +1020,13 @@ bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport,
}
/**
- * Rport is being deleted. FC-4s are offline. Awaiting BFA rport offline
- * callback to send LOGO.
+ * Rport is being deleted. FC-4s are offline.
+ * Awaiting BFA rport offline
+ * callback to send LOGO.
*/
static void
bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport,
- enum rport_event event)
+ enum rport_event event)
{
bfa_trc(rport->fcs, rport->pwwn);
bfa_trc(rport->fcs, rport->pid);
@@ -1075,11 +1049,11 @@ bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport,
}
/**
- * Rport is being deleted. FC-4s are offline. LOGO is being sent.
+ * Rport is being deleted. FC-4s are offline. LOGO is being sent.
*/
static void
bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport,
- enum rport_event event)
+ enum rport_event event)
{
bfa_trc(rport->fcs, rport->pwwn);
bfa_trc(rport->fcs, rport->pid);
@@ -1087,9 +1061,7 @@ bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport,
switch (event) {
case RPSM_EVENT_FCXP_SENT:
- /*
- * Once LOGO is sent, we donot wait for the response
- */
+ /* Once LOGO is sent, we donot wait for the response */
bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
bfa_fcs_rport_free(rport);
break;
@@ -1111,8 +1083,8 @@ bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport,
}
/**
- * Rport is offline. FC-4s are offline. BFA rport is offline.
- * Timer active to delete stale rport.
+ * Rport is offline. FC-4s are offline. BFA rport is offline.
+ * Timer active to delete stale rport.
*/
static void
bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport, enum rport_event event)
@@ -1132,7 +1104,7 @@ bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport, enum rport_event event)
bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
bfa_timer_stop(&rport->timer);
rport->ns_retries = 0;
- bfa_fcs_rport_send_gidpn(rport, NULL);
+ bfa_fcs_rport_send_nsdisc(rport, NULL);
break;
case RPSM_EVENT_DELETE:
@@ -1171,11 +1143,11 @@ bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport, enum rport_event event)
}
/**
- * Rport address has changed. Nameserver discovery request is being sent.
+ * Rport address has changed. Nameserver discovery request is being sent.
*/
static void
bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport,
- enum rport_event event)
+ enum rport_event event)
{
bfa_trc(rport->fcs, rport->pwwn);
bfa_trc(rport->fcs, rport->pid);
@@ -1205,7 +1177,7 @@ bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport,
break;
case RPSM_EVENT_ADDRESS_CHANGE:
- rport->ns_retries = 0; /* reset the retry count */
+ rport->ns_retries = 0; /* reset the retry count */
break;
case RPSM_EVENT_LOGO_IMP:
@@ -1228,11 +1200,11 @@ bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport,
}
/**
- * Nameserver discovery failed. Waiting for timeout to retry.
+ * Nameserver discovery failed. Waiting for timeout to retry.
*/
static void
bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport,
- enum rport_event event)
+ enum rport_event event)
{
bfa_trc(rport->fcs, rport->pwwn);
bfa_trc(rport->fcs, rport->pid);
@@ -1241,7 +1213,7 @@ bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport,
switch (event) {
case RPSM_EVENT_TIMEOUT:
bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
- bfa_fcs_rport_send_gidpn(rport, NULL);
+ bfa_fcs_rport_send_nsdisc(rport, NULL);
break;
case RPSM_EVENT_SCN:
@@ -1249,7 +1221,7 @@ bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport,
bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
bfa_timer_stop(&rport->timer);
rport->ns_retries = 0;
- bfa_fcs_rport_send_gidpn(rport, NULL);
+ bfa_fcs_rport_send_nsdisc(rport, NULL);
break;
case RPSM_EVENT_DELETE:
@@ -1276,7 +1248,6 @@ bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport,
case RPSM_EVENT_LOGO_RCVD:
bfa_fcs_rport_send_logo_acc(rport);
break;
-
case RPSM_EVENT_PRLO_RCVD:
bfa_fcs_rport_send_prlo_acc(rport);
break;
@@ -1293,7 +1264,7 @@ bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport,
}
/**
- * Rport address has changed. Nameserver discovery request is sent.
+ * Rport address has changed. Nameserver discovery request is sent.
*/
static void
bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
@@ -1311,9 +1282,9 @@ bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
bfa_fcs_rport_send_plogi(rport, NULL);
} else {
bfa_sm_set_state(rport,
- bfa_fcs_rport_sm_nsdisc_sending);
+ bfa_fcs_rport_sm_nsdisc_sending);
rport->ns_retries = 0;
- bfa_fcs_rport_send_gidpn(rport, NULL);
+ bfa_fcs_rport_send_nsdisc(rport, NULL);
}
break;
@@ -1321,8 +1292,8 @@ bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
rport->ns_retries++;
if (rport->ns_retries < BFA_FCS_RPORT_MAX_RETRIES) {
bfa_sm_set_state(rport,
- bfa_fcs_rport_sm_nsdisc_sending);
- bfa_fcs_rport_send_gidpn(rport, NULL);
+ bfa_fcs_rport_sm_nsdisc_sending);
+ bfa_fcs_rport_send_nsdisc(rport, NULL);
} else {
rport->pid = 0;
bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
@@ -1353,10 +1324,10 @@ bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
bfa_fcs_rport_del_timeout);
break;
+
case RPSM_EVENT_PRLO_RCVD:
bfa_fcs_rport_send_prlo_acc(rport);
break;
-
case RPSM_EVENT_SCN:
/**
* ignore, wait for NS query response
@@ -1391,29 +1362,29 @@ static void
bfa_fcs_rport_send_plogi(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
{
struct bfa_fcs_rport_s *rport = rport_cbarg;
- struct bfa_fcs_port_s *port = rport->port;
- struct fchs_s fchs;
- int len;
+ struct bfa_fcs_lport_s *port = rport->port;
+ struct fchs_s fchs;
+ int len;
struct bfa_fcxp_s *fcxp;
bfa_trc(rport->fcs, rport->pwwn);
fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
if (!fcxp) {
- bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
- bfa_fcs_rport_send_plogi, rport);
+ bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
+ bfa_fcs_rport_send_plogi, rport);
return;
}
rport->fcxp = fcxp;
len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
- bfa_fcs_port_get_fcid(port), 0,
- port->port_cfg.pwwn, port->port_cfg.nwwn,
- bfa_fcport_get_maxfrsize(port->fcs->bfa));
+ bfa_fcs_lport_get_fcid(port), 0,
+ port->port_cfg.pwwn, port->port_cfg.nwwn,
+ bfa_fcport_get_maxfrsize(port->fcs->bfa));
bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
- FC_CLASS_3, len, &fchs, bfa_fcs_rport_plogi_response,
- (void *)rport, FC_MAX_PDUSZ, FC_ELS_TOV);
+ FC_CLASS_3, len, &fchs, bfa_fcs_rport_plogi_response,
+ (void *)rport, FC_MAX_PDUSZ, FC_ELS_TOV);
rport->stats.plogis++;
bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
@@ -1421,14 +1392,14 @@ bfa_fcs_rport_send_plogi(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
static void
bfa_fcs_rport_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
- bfa_status_t req_status, u32 rsp_len,
- u32 resid_len, struct fchs_s *rsp_fchs)
+ bfa_status_t req_status, u32 rsp_len,
+ u32 resid_len, struct fchs_s *rsp_fchs)
{
- struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
+ struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
struct fc_logi_s *plogi_rsp;
struct fc_ls_rjt_s *ls_rjt;
struct bfa_fcs_rport_s *twin;
- struct list_head *qe;
+ struct list_head *qe;
bfa_trc(rport->fcs, rport->pwwn);
@@ -1453,6 +1424,13 @@ bfa_fcs_rport_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
bfa_trc(rport->fcs, ls_rjt->reason_code);
bfa_trc(rport->fcs, ls_rjt->reason_code_expl);
+ if ((ls_rjt->reason_code == FC_LS_RJT_RSN_UNABLE_TO_PERF_CMD) &&
+ (ls_rjt->reason_code_expl == FC_LS_RJT_EXP_INSUFF_RES)) {
+ rport->stats.rjt_insuff_res++;
+ bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RETRY);
+ return;
+ }
+
rport->stats.plogi_rejects++;
bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
return;
@@ -1463,22 +1441,22 @@ bfa_fcs_rport_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
* device with a new FC port address.
*/
list_for_each(qe, &rport->port->rport_q) {
- twin = (struct bfa_fcs_rport_s *)qe;
+ twin = (struct bfa_fcs_rport_s *) qe;
if (twin == rport)
continue;
if (!rport->pwwn && (plogi_rsp->port_name == twin->pwwn)) {
bfa_trc(rport->fcs, twin->pid);
bfa_trc(rport->fcs, rport->pid);
- /*
- * Update plogi stats in twin
- */
- twin->stats.plogis += rport->stats.plogis;
- twin->stats.plogi_rejects += rport->stats.plogi_rejects;
- twin->stats.plogi_timeouts +=
- rport->stats.plogi_timeouts;
- twin->stats.plogi_failed += rport->stats.plogi_failed;
- twin->stats.plogi_rcvd += rport->stats.plogi_rcvd;
+ /* Update plogi stats in twin */
+ twin->stats.plogis += rport->stats.plogis;
+ twin->stats.plogi_rejects +=
+ rport->stats.plogi_rejects;
+ twin->stats.plogi_timeouts +=
+ rport->stats.plogi_timeouts;
+ twin->stats.plogi_failed +=
+ rport->stats.plogi_failed;
+ twin->stats.plogi_rcvd += rport->stats.plogi_rcvd;
twin->stats.plogi_accs++;
bfa_fcs_rport_delete(rport);
@@ -1502,9 +1480,9 @@ static void
bfa_fcs_rport_send_plogiacc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
{
struct bfa_fcs_rport_s *rport = rport_cbarg;
- struct bfa_fcs_port_s *port = rport->port;
- struct fchs_s fchs;
- int len;
+ struct bfa_fcs_lport_s *port = rport->port;
+ struct fchs_s fchs;
+ int len;
struct bfa_fcxp_s *fcxp;
bfa_trc(rport->fcs, rport->pwwn);
@@ -1512,19 +1490,20 @@ bfa_fcs_rport_send_plogiacc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
if (!fcxp) {
- bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
- bfa_fcs_rport_send_plogiacc, rport);
+ bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
+ bfa_fcs_rport_send_plogiacc, rport);
return;
}
rport->fcxp = fcxp;
- len = fc_plogi_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
- bfa_fcs_port_get_fcid(port), rport->reply_oxid,
- port->port_cfg.pwwn, port->port_cfg.nwwn,
+ len = fc_plogi_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+ rport->pid, bfa_fcs_lport_get_fcid(port),
+ rport->reply_oxid, port->port_cfg.pwwn,
+ port->port_cfg.nwwn,
bfa_fcport_get_maxfrsize(port->fcs->bfa));
bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
- FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
+ FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
}
@@ -1533,28 +1512,28 @@ static void
bfa_fcs_rport_send_adisc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
{
struct bfa_fcs_rport_s *rport = rport_cbarg;
- struct bfa_fcs_port_s *port = rport->port;
- struct fchs_s fchs;
- int len;
+ struct bfa_fcs_lport_s *port = rport->port;
+ struct fchs_s fchs;
+ int len;
struct bfa_fcxp_s *fcxp;
bfa_trc(rport->fcs, rport->pwwn);
fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
if (!fcxp) {
- bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
- bfa_fcs_rport_send_adisc, rport);
+ bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
+ bfa_fcs_rport_send_adisc, rport);
return;
}
rport->fcxp = fcxp;
len = fc_adisc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
- bfa_fcs_port_get_fcid(port), 0,
- port->port_cfg.pwwn, port->port_cfg.nwwn);
+ bfa_fcs_lport_get_fcid(port), 0,
+ port->port_cfg.pwwn, port->port_cfg.nwwn);
bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
- FC_CLASS_3, len, &fchs, bfa_fcs_rport_adisc_response,
- rport, FC_MAX_PDUSZ, FC_ELS_TOV);
+ FC_CLASS_3, len, &fchs, bfa_fcs_rport_adisc_response,
+ rport, FC_MAX_PDUSZ, FC_ELS_TOV);
rport->stats.adisc_sent++;
bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
@@ -1562,12 +1541,12 @@ bfa_fcs_rport_send_adisc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
static void
bfa_fcs_rport_adisc_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
- bfa_status_t req_status, u32 rsp_len,
- u32 resid_len, struct fchs_s *rsp_fchs)
+ bfa_status_t req_status, u32 rsp_len,
+ u32 resid_len, struct fchs_s *rsp_fchs)
{
- struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
- void *pld = bfa_fcxp_get_rspbuf(fcxp);
- struct fc_ls_rjt_s *ls_rjt;
+ struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
+ void *pld = bfa_fcxp_get_rspbuf(fcxp);
+ struct fc_ls_rjt_s *ls_rjt;
if (req_status != BFA_STATUS_OK) {
bfa_trc(rport->fcs, req_status);
@@ -1577,7 +1556,7 @@ bfa_fcs_rport_adisc_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
}
if (fc_adisc_rsp_parse((struct fc_adisc_s *)pld, rsp_len, rport->pwwn,
- rport->nwwn) == FC_PARSE_OK) {
+ rport->nwwn) == FC_PARSE_OK) {
rport->stats.adisc_accs++;
bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
return;
@@ -1592,44 +1571,52 @@ bfa_fcs_rport_adisc_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
}
static void
-bfa_fcs_rport_send_gidpn(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+bfa_fcs_rport_send_nsdisc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
{
struct bfa_fcs_rport_s *rport = rport_cbarg;
- struct bfa_fcs_port_s *port = rport->port;
- struct fchs_s fchs;
+ struct bfa_fcs_lport_s *port = rport->port;
+ struct fchs_s fchs;
struct bfa_fcxp_s *fcxp;
- int len;
+ int len;
+ bfa_cb_fcxp_send_t cbfn;
bfa_trc(rport->fcs, rport->pid);
fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
if (!fcxp) {
- bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
- bfa_fcs_rport_send_gidpn, rport);
+ bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
+ bfa_fcs_rport_send_nsdisc, rport);
return;
}
rport->fcxp = fcxp;
- len = fc_gidpn_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
- bfa_fcs_port_get_fcid(port), 0, rport->pwwn);
+ if (rport->pwwn) {
+ len = fc_gidpn_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+ bfa_fcs_lport_get_fcid(port), 0, rport->pwwn);
+ cbfn = bfa_fcs_rport_gidpn_response;
+ } else {
+ len = fc_gpnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+ bfa_fcs_lport_get_fcid(port), 0, rport->pid);
+ cbfn = bfa_fcs_rport_gpnid_response;
+ }
bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
- FC_CLASS_3, len, &fchs, bfa_fcs_rport_gidpn_response,
- (void *)rport, FC_MAX_PDUSZ, FC_FCCT_TOV);
+ FC_CLASS_3, len, &fchs, cbfn,
+ (void *)rport, FC_MAX_PDUSZ, FC_FCCT_TOV);
bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
}
static void
bfa_fcs_rport_gidpn_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
- bfa_status_t req_status, u32 rsp_len,
- u32 resid_len, struct fchs_s *rsp_fchs)
+ bfa_status_t req_status, u32 rsp_len,
+ u32 resid_len, struct fchs_s *rsp_fchs)
{
- struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
- struct bfa_fcs_rport_s *twin;
- struct list_head *qe;
- struct ct_hdr_s *cthdr;
+ struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
+ struct ct_hdr_s *cthdr;
struct fcgs_gidpn_resp_s *gidpn_rsp;
+ struct bfa_fcs_rport_s *twin;
+ struct list_head *qe;
bfa_trc(rport->fcs, rport->pwwn);
@@ -1637,25 +1624,21 @@ bfa_fcs_rport_gidpn_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
- /*
- * Check if the pid is the same as before.
- */
+ /* Check if the pid is the same as before. */
gidpn_rsp = (struct fcgs_gidpn_resp_s *) (cthdr + 1);
if (gidpn_rsp->dap == rport->pid) {
- /*
- * Device is online
- */
+ /* Device is online */
bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
} else {
/*
- * Device's PID has changed. We need to cleanup and
- * re-login. If there is another device with the the
- * newly discovered pid, send an scn notice so that its
- * new pid can be discovered.
+ * Device's PID has changed. We need to cleanup
+ * and re-login. If there is another device with
+ * the the newly discovered pid, send an scn notice
+ * so that its new pid can be discovered.
*/
list_for_each(qe, &rport->port->rport_q) {
- twin = (struct bfa_fcs_rport_s *)qe;
+ twin = (struct bfa_fcs_rport_s *) qe;
if (twin == rport)
continue;
if (gidpn_rsp->dap == twin->pid) {
@@ -1664,7 +1647,7 @@ bfa_fcs_rport_gidpn_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
twin->pid = 0;
bfa_sm_send_event(twin,
- RPSM_EVENT_ADDRESS_CHANGE);
+ RPSM_EVENT_ADDRESS_CHANGE);
}
}
rport->pid = gidpn_rsp->dap;
@@ -1697,17 +1680,59 @@ bfa_fcs_rport_gidpn_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
}
}
+static void
+bfa_fcs_rport_gpnid_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
+ bfa_status_t req_status, u32 rsp_len,
+ u32 resid_len, struct fchs_s *rsp_fchs)
+{
+ struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
+ struct ct_hdr_s *cthdr;
+
+ bfa_trc(rport->fcs, rport->pwwn);
+
+ cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
+ cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
+
+ if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
+ bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
+ return;
+ }
+
+ /*
+ * Reject Response
+ */
+ switch (cthdr->reason_code) {
+ case CT_RSN_LOGICAL_BUSY:
+ /*
+ * Need to retry
+ */
+ bfa_sm_send_event(rport, RPSM_EVENT_TIMEOUT);
+ break;
+
+ case CT_RSN_UNABLE_TO_PERF:
+ /*
+ * device doesn't exist : Start timer to cleanup this later.
+ */
+ bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
+ break;
+
+ default:
+ bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
+ break;
+ }
+}
+
/**
- * Called to send a logout to the rport.
+ * Called to send a logout to the rport.
*/
static void
bfa_fcs_rport_send_logo(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
{
struct bfa_fcs_rport_s *rport = rport_cbarg;
- struct bfa_fcs_port_s *port;
- struct fchs_s fchs;
+ struct bfa_fcs_lport_s *port;
+ struct fchs_s fchs;
struct bfa_fcxp_s *fcxp;
- u16 len;
+ u16 len;
bfa_trc(rport->fcs, rport->pid);
@@ -1715,19 +1740,19 @@ bfa_fcs_rport_send_logo(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
if (!fcxp) {
- bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
- bfa_fcs_rport_send_logo, rport);
+ bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
+ bfa_fcs_rport_send_logo, rport);
return;
}
rport->fcxp = fcxp;
len = fc_logo_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
- bfa_fcs_port_get_fcid(port), 0,
- bfa_fcs_port_get_pwwn(port));
+ bfa_fcs_lport_get_fcid(port), 0,
+ bfa_fcs_lport_get_pwwn(port));
bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
- FC_CLASS_3, len, &fchs, NULL, rport, FC_MAX_PDUSZ,
- FC_ELS_TOV);
+ FC_CLASS_3, len, &fchs, NULL,
+ rport, FC_MAX_PDUSZ, FC_ELS_TOV);
rport->stats.logos++;
bfa_fcxp_discard(rport->fcxp);
@@ -1735,16 +1760,16 @@ bfa_fcs_rport_send_logo(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
}
/**
- * Send ACC for a LOGO received.
+ * Send ACC for a LOGO received.
*/
static void
bfa_fcs_rport_send_logo_acc(void *rport_cbarg)
{
struct bfa_fcs_rport_s *rport = rport_cbarg;
- struct bfa_fcs_port_s *port;
- struct fchs_s fchs;
+ struct bfa_fcs_lport_s *port;
+ struct fchs_s fchs;
struct bfa_fcxp_s *fcxp;
- u16 len;
+ u16 len;
bfa_trc(rport->fcs, rport->pid);
@@ -1755,32 +1780,35 @@ bfa_fcs_rport_send_logo_acc(void *rport_cbarg)
return;
rport->stats.logo_rcvd++;
- len = fc_logo_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
- bfa_fcs_port_get_fcid(port), rport->reply_oxid);
+ len = fc_logo_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+ rport->pid, bfa_fcs_lport_get_fcid(port),
+ rport->reply_oxid);
bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
- FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
+ FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
}
/**
- * This routine will be called by bfa_timer on timer timeouts.
+ * brief
+ * This routine will be called by bfa_timer on timer timeouts.
*
- * param[in] rport - pointer to bfa_fcs_port_ns_t.
- * param[out] rport_status - pointer to return vport status in
+ * param[in] rport - pointer to bfa_fcs_lport_ns_t.
+ * param[out] rport_status - pointer to return vport status in
*
- * return
- * void
+ * return
+ * void
*
-* Special Considerations:
+ * Special Considerations:
*
- * note
+ * note
*/
static void
bfa_fcs_rport_timeout(void *arg)
{
- struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)arg;
+ struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) arg;
rport->stats.plogi_timeouts++;
+ bfa_stats(rport->port, rport_plogi_timeouts);
bfa_sm_send_event(rport, RPSM_EVENT_TIMEOUT);
}
@@ -1789,50 +1817,45 @@ bfa_fcs_rport_process_prli(struct bfa_fcs_rport_s *rport,
struct fchs_s *rx_fchs, u16 len)
{
struct bfa_fcxp_s *fcxp;
- struct fchs_s fchs;
- struct bfa_fcs_port_s *port = rport->port;
- struct fc_prli_s *prli;
+ struct fchs_s fchs;
+ struct bfa_fcs_lport_s *port = rport->port;
+ struct fc_prli_s *prli;
bfa_trc(port->fcs, rx_fchs->s_id);
bfa_trc(port->fcs, rx_fchs->d_id);
rport->stats.prli_rcvd++;
- if (BFA_FCS_VPORT_IS_TARGET_MODE(port)) {
- /*
- * Target Mode : Let the fcptm handle it
- */
- bfa_fcs_tin_rx_prli(rport->tin, rx_fchs, len);
- return;
- }
-
/*
- * We are either in Initiator or ipfc Mode
+ * We are in Initiator Mode
*/
prli = (struct fc_prli_s *) (rx_fchs + 1);
- if (prli->parampage.servparams.initiator) {
- bfa_trc(rport->fcs, prli->parampage.type);
- rport->scsi_function = BFA_RPORT_INITIATOR;
- bfa_fcs_itnim_is_initiator(rport->itnim);
- } else {
+ if (prli->parampage.servparams.target) {
/*
- * @todo: PRLI from a target ?
+ * PRLI from a target ?
+ * Send the Acc.
+ * PRLI sent by us will be used to transition the IT nexus,
+ * once the response is received from the target.
*/
bfa_trc(port->fcs, rx_fchs->s_id);
rport->scsi_function = BFA_RPORT_TARGET;
+ } else {
+ bfa_trc(rport->fcs, prli->parampage.type);
+ rport->scsi_function = BFA_RPORT_INITIATOR;
+ bfa_fcs_itnim_is_initiator(rport->itnim);
}
fcxp = bfa_fcs_fcxp_alloc(port->fcs);
if (!fcxp)
return;
- len = fc_prli_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
- bfa_fcs_port_get_fcid(port), rx_fchs->ox_id,
- port->port_cfg.roles);
+ len = fc_prli_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+ rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
+ rx_fchs->ox_id, port->port_cfg.roles);
bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
- FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
+ FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
}
static void
@@ -1840,10 +1863,10 @@ bfa_fcs_rport_process_rpsc(struct bfa_fcs_rport_s *rport,
struct fchs_s *rx_fchs, u16 len)
{
struct bfa_fcxp_s *fcxp;
- struct fchs_s fchs;
- struct bfa_fcs_port_s *port = rport->port;
+ struct fchs_s fchs;
+ struct bfa_fcs_lport_s *port = rport->port;
struct fc_rpsc_speed_info_s speeds;
- struct bfa_pport_attr_s pport_attr;
+ struct bfa_port_attr_s pport_attr;
bfa_trc(port->fcs, rx_fchs->s_id);
bfa_trc(port->fcs, rx_fchs->d_id);
@@ -1864,12 +1887,12 @@ bfa_fcs_rport_process_rpsc(struct bfa_fcs_rport_s *rport,
if (!fcxp)
return;
- len = fc_rpsc_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
- bfa_fcs_port_get_fcid(port), rx_fchs->ox_id,
- &speeds);
+ len = fc_rpsc_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+ rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
+ rx_fchs->ox_id, &speeds);
bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
- FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
+ FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
}
static void
@@ -1877,28 +1900,20 @@ bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport,
struct fchs_s *rx_fchs, u16 len)
{
struct bfa_fcxp_s *fcxp;
- struct fchs_s fchs;
- struct bfa_fcs_port_s *port = rport->port;
- struct fc_adisc_s *adisc;
+ struct fchs_s fchs;
+ struct bfa_fcs_lport_s *port = rport->port;
+ struct fc_adisc_s *adisc;
bfa_trc(port->fcs, rx_fchs->s_id);
bfa_trc(port->fcs, rx_fchs->d_id);
rport->stats.adisc_rcvd++;
- if (BFA_FCS_VPORT_IS_TARGET_MODE(port)) {
- /*
- * @todo : Target Mode handling
- */
- bfa_trc(port->fcs, rx_fchs->d_id);
- bfa_assert(0);
- return;
- }
-
adisc = (struct fc_adisc_s *) (rx_fchs + 1);
/*
- * Accept if the itnim for this rport is online. Else reject the ADISC
+ * Accept if the itnim for this rport is online.
+ * Else reject the ADISC.
*/
if (bfa_fcs_itnim_get_online_state(rport->itnim) == BFA_STATUS_OK) {
@@ -1907,27 +1922,25 @@ bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport,
return;
len = fc_adisc_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
- rx_fchs->s_id,
- bfa_fcs_port_get_fcid(port),
- rx_fchs->ox_id, port->port_cfg.pwwn,
- port->port_cfg.nwwn);
+ rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
+ rx_fchs->ox_id, port->port_cfg.pwwn,
+ port->port_cfg.nwwn);
bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag,
- BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
- FC_MAX_PDUSZ, 0);
+ BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
+ FC_MAX_PDUSZ, 0);
} else {
rport->stats.adisc_rejected++;
bfa_fcs_rport_send_ls_rjt(rport, rx_fchs,
FC_LS_RJT_RSN_UNABLE_TO_PERF_CMD,
FC_LS_RJT_EXP_LOGIN_REQUIRED);
}
-
}
static void
bfa_fcs_rport_hal_online(struct bfa_fcs_rport_s *rport)
{
- struct bfa_fcs_port_s *port = rport->port;
+ struct bfa_fcs_lport_s *port = rport->port;
struct bfa_rport_info_s rport_info;
rport_info.pid = rport->pid;
@@ -1941,38 +1954,18 @@ bfa_fcs_rport_hal_online(struct bfa_fcs_rport_s *rport)
bfa_rport_online(rport->bfa_rport, &rport_info);
}
-static void
-bfa_fcs_rport_fc4_pause(struct bfa_fcs_rport_s *rport)
-{
- if (bfa_fcs_port_is_initiator(rport->port))
- bfa_fcs_itnim_pause(rport->itnim);
-
- if (bfa_fcs_port_is_target(rport->port))
- bfa_fcs_tin_pause(rport->tin);
-}
-
-static void
-bfa_fcs_rport_fc4_resume(struct bfa_fcs_rport_s *rport)
-{
- if (bfa_fcs_port_is_initiator(rport->port))
- bfa_fcs_itnim_resume(rport->itnim);
-
- if (bfa_fcs_port_is_target(rport->port))
- bfa_fcs_tin_resume(rport->tin);
-}
-
static struct bfa_fcs_rport_s *
-bfa_fcs_rport_alloc(struct bfa_fcs_port_s *port, wwn_t pwwn, u32 rpid)
+bfa_fcs_rport_alloc(struct bfa_fcs_lport_s *port, wwn_t pwwn, u32 rpid)
{
- struct bfa_fcs_s *fcs = port->fcs;
+ struct bfa_fcs_s *fcs = port->fcs;
struct bfa_fcs_rport_s *rport;
- struct bfad_rport_s *rport_drv;
+ struct bfad_rport_s *rport_drv;
/**
* allocate rport
*/
if (bfa_fcb_rport_alloc(fcs->bfad, &rport, &rport_drv)
- != BFA_STATUS_OK) {
+ != BFA_STATUS_OK) {
bfa_trc(fcs, rpid);
return NULL;
}
@@ -1999,10 +1992,9 @@ bfa_fcs_rport_alloc(struct bfa_fcs_port_s *port, wwn_t pwwn, u32 rpid)
/**
* allocate FC-4s
*/
- bfa_assert(bfa_fcs_port_is_initiator(port) ^
- bfa_fcs_port_is_target(port));
+ bfa_assert(bfa_fcs_lport_is_initiator(port));
- if (bfa_fcs_port_is_initiator(port)) {
+ if (bfa_fcs_lport_is_initiator(port)) {
rport->itnim = bfa_fcs_itnim_create(rport);
if (!rport->itnim) {
bfa_trc(fcs, rpid);
@@ -2012,23 +2004,11 @@ bfa_fcs_rport_alloc(struct bfa_fcs_port_s *port, wwn_t pwwn, u32 rpid)
}
}
- if (bfa_fcs_port_is_target(port)) {
- rport->tin = bfa_fcs_tin_create(rport);
- if (!rport->tin) {
- bfa_trc(fcs, rpid);
- bfa_rport_delete(rport->bfa_rport);
- kfree(rport_drv);
- return NULL;
- }
- }
-
- bfa_fcs_port_add_rport(port, rport);
+ bfa_fcs_lport_add_rport(port, rport);
bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
- /*
- * Initialize the Rport Features(RPF) Sub Module
- */
+ /* Initialize the Rport Features(RPF) Sub Module */
if (!BFA_FCS_PID_IS_WKA(rport->pid))
bfa_fcs_rpf_init(rport);
@@ -2039,121 +2019,78 @@ bfa_fcs_rport_alloc(struct bfa_fcs_port_s *port, wwn_t pwwn, u32 rpid)
static void
bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport)
{
- struct bfa_fcs_port_s *port = rport->port;
+ struct bfa_fcs_lport_s *port = rport->port;
/**
* - delete FC-4s
* - delete BFA rport
* - remove from queue of rports
*/
- if (bfa_fcs_port_is_initiator(port))
+ if (bfa_fcs_lport_is_initiator(port)) {
bfa_fcs_itnim_delete(rport->itnim);
-
- if (bfa_fcs_port_is_target(port))
- bfa_fcs_tin_delete(rport->tin);
+ if (rport->pid != 0 && !BFA_FCS_PID_IS_WKA(rport->pid))
+ bfa_fcs_rpf_rport_offline(rport);
+ }
bfa_rport_delete(rport->bfa_rport);
- bfa_fcs_port_del_rport(port, rport);
+ bfa_fcs_lport_del_rport(port, rport);
kfree(rport->rp_drv);
}
static void
-bfa_fcs_rport_aen_post(struct bfa_fcs_rport_s *rport,
- enum bfa_rport_aen_event event,
- struct bfa_rport_aen_data_s *data)
-{
- union bfa_aen_data_u aen_data;
- struct bfa_log_mod_s *logmod = rport->fcs->logm;
- wwn_t lpwwn = bfa_fcs_port_get_pwwn(rport->port);
- wwn_t rpwwn = rport->pwwn;
- char lpwwn_ptr[BFA_STRING_32];
- char rpwwn_ptr[BFA_STRING_32];
- char *prio_str[] = { "unknown", "high", "medium", "low" };
-
- wwn2str(lpwwn_ptr, lpwwn);
- wwn2str(rpwwn_ptr, rpwwn);
-
- switch (event) {
- case BFA_RPORT_AEN_ONLINE:
- case BFA_RPORT_AEN_OFFLINE:
- case BFA_RPORT_AEN_DISCONNECT:
- bfa_log(logmod, BFA_LOG_CREATE_ID(BFA_AEN_CAT_RPORT, event),
- rpwwn_ptr, lpwwn_ptr);
- break;
- case BFA_RPORT_AEN_QOS_PRIO:
- aen_data.rport.priv.qos = data->priv.qos;
- bfa_log(logmod, BFA_AEN_RPORT_QOS_PRIO,
- prio_str[aen_data.rport.priv.qos.qos_priority],
- rpwwn_ptr, lpwwn_ptr);
- break;
- case BFA_RPORT_AEN_QOS_FLOWID:
- aen_data.rport.priv.qos = data->priv.qos;
- bfa_log(logmod, BFA_AEN_RPORT_QOS_FLOWID,
- aen_data.rport.priv.qos.qos_flow_id, rpwwn_ptr,
- lpwwn_ptr);
- break;
- default:
- break;
- }
-
- aen_data.rport.vf_id = rport->port->fabric->vf_id;
- aen_data.rport.ppwwn =
- bfa_fcs_port_get_pwwn(bfa_fcs_get_base_port(rport->fcs));
- aen_data.rport.lpwwn = lpwwn;
- aen_data.rport.rpwwn = rpwwn;
-}
-
-static void
bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport)
{
- struct bfa_fcs_port_s *port = rport->port;
+ struct bfa_fcs_lport_s *port = rport->port;
+ struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
+ char lpwwn_buf[BFA_STRING_32];
+ char rpwwn_buf[BFA_STRING_32];
rport->stats.onlines++;
- if (bfa_fcs_port_is_initiator(port)) {
+ if (bfa_fcs_lport_is_initiator(port)) {
bfa_fcs_itnim_rport_online(rport->itnim);
if (!BFA_FCS_PID_IS_WKA(rport->pid))
bfa_fcs_rpf_rport_online(rport);
};
- if (bfa_fcs_port_is_target(port))
- bfa_fcs_tin_rport_online(rport->tin);
-
- /*
- * Don't post events for well known addresses
- */
+ wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
+ wwn2str(rpwwn_buf, rport->pwwn);
if (!BFA_FCS_PID_IS_WKA(rport->pid))
- bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_ONLINE, NULL);
+ BFA_LOG(KERN_INFO, bfad, log_level,
+ "Remote port (WWN = %s) online for logical port (WWN = %s)\n",
+ rpwwn_buf, lpwwn_buf);
}
static void
bfa_fcs_rport_offline_action(struct bfa_fcs_rport_s *rport)
{
- struct bfa_fcs_port_s *port = rport->port;
+ struct bfa_fcs_lport_s *port = rport->port;
+ struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
+ char lpwwn_buf[BFA_STRING_32];
+ char rpwwn_buf[BFA_STRING_32];
rport->stats.offlines++;
- /*
- * Don't post events for well known addresses
- */
+ wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
+ wwn2str(rpwwn_buf, rport->pwwn);
if (!BFA_FCS_PID_IS_WKA(rport->pid)) {
- if (bfa_fcs_port_is_online(rport->port) == BFA_TRUE) {
- bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_DISCONNECT,
- NULL);
- } else {
- bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_OFFLINE,
- NULL);
- }
+ if (bfa_fcs_lport_is_online(rport->port) == BFA_TRUE)
+ BFA_LOG(KERN_ERR, bfad, log_level,
+ "Remote port (WWN = %s) connectivity lost for "
+ "logical port (WWN = %s)\n",
+ rpwwn_buf, lpwwn_buf);
+ else
+ BFA_LOG(KERN_INFO, bfad, log_level,
+ "Remote port (WWN = %s) offlined by "
+ "logical port (WWN = %s)\n",
+ rpwwn_buf, lpwwn_buf);
}
- if (bfa_fcs_port_is_initiator(port)) {
+ if (bfa_fcs_lport_is_initiator(port)) {
bfa_fcs_itnim_rport_offline(rport->itnim);
if (!BFA_FCS_PID_IS_WKA(rport->pid))
bfa_fcs_rpf_rport_offline(rport);
}
-
- if (bfa_fcs_port_is_target(port))
- bfa_fcs_tin_rport_offline(rport->tin);
}
/**
@@ -2162,7 +2099,7 @@ bfa_fcs_rport_offline_action(struct bfa_fcs_rport_s *rport)
static void
bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport, struct fc_logi_s *plogi)
{
- struct bfa_fcs_port_s *port = rport->port;
+ bfa_fcs_lport_t *port = rport->port;
/**
* - port name
@@ -2193,12 +2130,13 @@ bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport, struct fc_logi_s *plogi)
/**
* Direct Attach P2P mode :
* This is to handle a bug (233476) in IBM targets in Direct Attach
- * Mode. Basically, in FLOGI Accept the target would have erroneously
- * set the BB Credit to the value used in the FLOGI sent by the HBA.
- * It uses the correct value (its own BB credit) in PLOGI.
+ * Mode. Basically, in FLOGI Accept the target would have
+ * erroneously set the BB Credit to the value used in the FLOGI
+ * sent by the HBA. It uses the correct value (its own BB credit)
+ * in PLOGI.
*/
- if ((!bfa_fcs_fabric_is_switched(port->fabric))
- && (bfa_os_ntohs(plogi->csp.bbcred) < port->fabric->bb_credit)) {
+ if ((!bfa_fcs_fabric_is_switched(port->fabric)) &&
+ (bfa_os_ntohs(plogi->csp.bbcred) < port->fabric->bb_credit)) {
bfa_trc(port->fcs, bfa_os_ntohs(plogi->csp.bbcred));
bfa_trc(port->fcs, port->fabric->bb_credit);
@@ -2211,7 +2149,7 @@ bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport, struct fc_logi_s *plogi)
}
/**
- * Called to handle LOGO received from an existing remote port.
+ * Called to handle LOGO received from an existing remote port.
*/
static void
bfa_fcs_rport_process_logo(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs)
@@ -2231,8 +2169,8 @@ bfa_fcs_rport_process_logo(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs)
*/
/**
- * Called by bport/vport to create a remote port instance for a discovered
- * remote device.
+ * Called by bport/vport to create a remote port instance for a discovered
+ * remote device.
*
* @param[in] port - base port or vport
* @param[in] rpid - remote port ID
@@ -2240,7 +2178,7 @@ bfa_fcs_rport_process_logo(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs)
* @return None
*/
struct bfa_fcs_rport_s *
-bfa_fcs_rport_create(struct bfa_fcs_port_s *port, u32 rpid)
+bfa_fcs_rport_create(struct bfa_fcs_lport_s *port, u32 rpid)
{
struct bfa_fcs_rport_s *rport;
@@ -2262,10 +2200,9 @@ bfa_fcs_rport_create(struct bfa_fcs_port_s *port, u32 rpid)
* @return None
*/
struct bfa_fcs_rport_s *
-bfa_fcs_rport_create_by_wwn(struct bfa_fcs_port_s *port, wwn_t rpwwn)
+bfa_fcs_rport_create_by_wwn(struct bfa_fcs_lport_s *port, wwn_t rpwwn)
{
struct bfa_fcs_rport_s *rport;
-
bfa_trc(port->fcs, rpwwn);
rport = bfa_fcs_rport_alloc(port, rpwwn, 0);
if (!rport)
@@ -2274,7 +2211,6 @@ bfa_fcs_rport_create_by_wwn(struct bfa_fcs_port_s *port, wwn_t rpwwn)
bfa_sm_send_event(rport, RPSM_EVENT_ADDRESS_DISC);
return rport;
}
-
/**
* Called by bport in private loop topology to indicate that a
* rport has been discovered and plogi has been completed.
@@ -2283,8 +2219,8 @@ bfa_fcs_rport_create_by_wwn(struct bfa_fcs_port_s *port, wwn_t rpwwn)
* @param[in] rpid - remote port ID
*/
void
-bfa_fcs_rport_start(struct bfa_fcs_port_s *port, struct fchs_s *fchs,
- struct fc_logi_s *plogi)
+bfa_fcs_rport_start(struct bfa_fcs_lport_s *port, struct fchs_s *fchs,
+ struct fc_logi_s *plogi)
{
struct bfa_fcs_rport_s *rport;
@@ -2298,12 +2234,12 @@ bfa_fcs_rport_start(struct bfa_fcs_port_s *port, struct fchs_s *fchs,
}
/**
- * Called by bport/vport to handle PLOGI received from a new remote port.
- * If an existing rport does a plogi, it will be handled separately.
+ * Called by bport/vport to handle PLOGI received from a new remote port.
+ * If an existing rport does a plogi, it will be handled separately.
*/
void
-bfa_fcs_rport_plogi_create(struct bfa_fcs_port_s *port, struct fchs_s *fchs,
- struct fc_logi_s *plogi)
+bfa_fcs_rport_plogi_create(struct bfa_fcs_lport_s *port, struct fchs_s *fchs,
+ struct fc_logi_s *plogi)
{
struct bfa_fcs_rport_s *rport;
@@ -2323,9 +2259,9 @@ bfa_fcs_rport_plogi_create(struct bfa_fcs_port_s *port, struct fchs_s *fchs,
static int
wwn_compare(wwn_t wwn1, wwn_t wwn2)
{
- u8 *b1 = (u8 *) &wwn1;
- u8 *b2 = (u8 *) &wwn2;
- int i;
+ u8 *b1 = (u8 *) &wwn1;
+ u8 *b2 = (u8 *) &wwn2;
+ int i;
for (i = 0; i < sizeof(wwn_t); i++) {
if (b1[i] < b2[i])
@@ -2337,12 +2273,12 @@ wwn_compare(wwn_t wwn1, wwn_t wwn2)
}
/**
- * Called by bport/vport to handle PLOGI received from an existing
- * remote port.
+ * Called by bport/vport to handle PLOGI received from an existing
+ * remote port.
*/
void
bfa_fcs_rport_plogi(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs,
- struct fc_logi_s *plogi)
+ struct fc_logi_s *plogi)
{
/**
* @todo Handle P2P and initiator-initiator.
@@ -2360,9 +2296,9 @@ bfa_fcs_rport_plogi(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs,
* If the link topology is N2N,
* this Plogi should be accepted.
*/
- if ((wwn_compare(rport->port->port_cfg.pwwn, rport->pwwn) == -1)
- && (bfa_fcs_fabric_is_switched(rport->port->fabric))
- && (!BFA_FCS_PID_IS_WKA(rport->pid))) {
+ if ((wwn_compare(rport->port->port_cfg.pwwn, rport->pwwn) == -1) &&
+ (bfa_fcs_fabric_is_switched(rport->port->fabric)) &&
+ (!BFA_FCS_PID_IS_WKA(rport->pid))) {
bfa_trc(rport->fcs, rport->pid);
return;
}
@@ -2374,10 +2310,10 @@ bfa_fcs_rport_plogi(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs,
/**
* Called by bport/vport to delete a remote port instance.
*
-* Rport delete is called under the following conditions:
- * - vport is deleted
- * - vf is deleted
- * - explicit request from OS to delete rport (vmware)
+ * Rport delete is called under the following conditions:
+ * - vport is deleted
+ * - vf is deleted
+ * - explicit request from OS to delete rport
*/
void
bfa_fcs_rport_delete(struct bfa_fcs_rport_s *rport)
@@ -2404,20 +2340,18 @@ bfa_fcs_rport_online(struct bfa_fcs_rport_s *rport)
{
bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND);
}
-
/**
- * Called by bport/vport to notify SCN for the remote port
+ * Called by bport/vport to notify SCN for the remote port
*/
void
bfa_fcs_rport_scn(struct bfa_fcs_rport_s *rport)
{
-
rport->stats.rscns++;
bfa_sm_send_event(rport, RPSM_EVENT_SCN);
}
/**
- * Called by fcpim to notify that the ITN cleanup is done.
+ * Called by fcpim to notify that the ITN cleanup is done.
*/
void
bfa_fcs_rport_itnim_ack(struct bfa_fcs_rport_s *rport)
@@ -2426,7 +2360,7 @@ bfa_fcs_rport_itnim_ack(struct bfa_fcs_rport_s *rport)
}
/**
- * Called by fcptm to notify that the ITN cleanup is done.
+ * Called by fcptm to notify that the ITN cleanup is done.
*/
void
bfa_fcs_rport_tin_ack(struct bfa_fcs_rport_s *rport)
@@ -2435,99 +2369,100 @@ bfa_fcs_rport_tin_ack(struct bfa_fcs_rport_s *rport)
}
/**
- * This routine BFA callback for bfa_rport_online() call.
+ * brief
+ * This routine BFA callback for bfa_rport_online() call.
*
- * param[in] cb_arg - rport struct.
+ * param[in] cb_arg - rport struct.
*
- * return
- * void
+ * return
+ * void
*
-* Special Considerations:
+ * Special Considerations:
*
- * note
+ * note
*/
void
bfa_cb_rport_online(void *cbarg)
{
- struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
+ struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
bfa_trc(rport->fcs, rport->pwwn);
bfa_sm_send_event(rport, RPSM_EVENT_HCB_ONLINE);
}
/**
- * This routine BFA callback for bfa_rport_offline() call.
+ * brief
+ * This routine BFA callback for bfa_rport_offline() call.
*
- * param[in] rport -
+ * param[in] rport -
*
- * return
- * void
+ * return
+ * void
*
- * Special Considerations:
+ * Special Considerations:
*
- * note
+ * note
*/
void
bfa_cb_rport_offline(void *cbarg)
{
- struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
+ struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
bfa_trc(rport->fcs, rport->pwwn);
bfa_sm_send_event(rport, RPSM_EVENT_HCB_OFFLINE);
}
/**
- * This routine is a static BFA callback when there is a QoS flow_id
- * change notification
+ * brief
+ * This routine is a static BFA callback when there is a QoS flow_id
+ * change notification
*
- * @param[in] rport -
+ * param[in] rport -
*
- * @return void
+ * return
+ * void
*
- * Special Considerations:
+ * Special Considerations:
*
- * @note
+ * note
*/
void
bfa_cb_rport_qos_scn_flowid(void *cbarg,
- struct bfa_rport_qos_attr_s old_qos_attr,
- struct bfa_rport_qos_attr_s new_qos_attr)
+ struct bfa_rport_qos_attr_s old_qos_attr,
+ struct bfa_rport_qos_attr_s new_qos_attr)
{
- struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
- struct bfa_rport_aen_data_s aen_data;
+ struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
bfa_trc(rport->fcs, rport->pwwn);
- aen_data.priv.qos = new_qos_attr;
- bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_QOS_FLOWID, &aen_data);
}
/**
- * This routine is a static BFA callback when there is a QoS priority
- * change notification
+ * brief
+ * This routine is a static BFA callback when there is a QoS priority
+ * change notification
*
- * @param[in] rport -
+ * param[in] rport -
*
- * @return void
+ * return
+ * void
*
- * Special Considerations:
+ * Special Considerations:
*
- * @note
+ * note
*/
void
-bfa_cb_rport_qos_scn_prio(void *cbarg, struct bfa_rport_qos_attr_s old_qos_attr,
- struct bfa_rport_qos_attr_s new_qos_attr)
+bfa_cb_rport_qos_scn_prio(void *cbarg,
+ struct bfa_rport_qos_attr_s old_qos_attr,
+ struct bfa_rport_qos_attr_s new_qos_attr)
{
- struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
- struct bfa_rport_aen_data_s aen_data;
+ struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
bfa_trc(rport->fcs, rport->pwwn);
- aen_data.priv.qos = new_qos_attr;
- bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_QOS_PRIO, &aen_data);
}
/**
- * Called to process any unsolicted frames from this remote port
+ * Called to process any unsolicted frames from this remote port
*/
void
bfa_fcs_rport_logo_imp(struct bfa_fcs_rport_s *rport)
@@ -2536,14 +2471,14 @@ bfa_fcs_rport_logo_imp(struct bfa_fcs_rport_s *rport)
}
/**
- * Called to process any unsolicted frames from this remote port
+ * Called to process any unsolicted frames from this remote port
*/
void
-bfa_fcs_rport_uf_recv(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs,
- u16 len)
+bfa_fcs_rport_uf_recv(struct bfa_fcs_rport_s *rport,
+ struct fchs_s *fchs, u16 len)
{
- struct bfa_fcs_port_s *port = rport->port;
- struct fc_els_cmd_s *els_cmd;
+ struct bfa_fcs_lport_s *port = rport->port;
+ struct fc_els_cmd_s *els_cmd;
bfa_trc(rport->fcs, fchs->s_id);
bfa_trc(rport->fcs, fchs->d_id);
@@ -2558,30 +2493,33 @@ bfa_fcs_rport_uf_recv(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs,
switch (els_cmd->els_code) {
case FC_ELS_LOGO:
+ bfa_stats(port, plogi_rcvd);
bfa_fcs_rport_process_logo(rport, fchs);
break;
case FC_ELS_ADISC:
+ bfa_stats(port, adisc_rcvd);
bfa_fcs_rport_process_adisc(rport, fchs, len);
break;
case FC_ELS_PRLO:
- if (bfa_fcs_port_is_initiator(port))
+ bfa_stats(port, prlo_rcvd);
+ if (bfa_fcs_lport_is_initiator(port))
bfa_fcs_fcpim_uf_recv(rport->itnim, fchs, len);
-
- if (bfa_fcs_port_is_target(port))
- bfa_fcs_fcptm_uf_recv(rport->tin, fchs, len);
break;
case FC_ELS_PRLI:
+ bfa_stats(port, prli_rcvd);
bfa_fcs_rport_process_prli(rport, fchs, len);
break;
case FC_ELS_RPSC:
+ bfa_stats(port, rpsc_rcvd);
bfa_fcs_rport_process_rpsc(rport, fchs, len);
break;
default:
+ bfa_stats(port, un_handled_els_rcvd);
bfa_fcs_rport_send_ls_rjt(rport, fchs,
FC_LS_RJT_RSN_CMD_NOT_SUPP,
FC_LS_RJT_EXP_NO_ADDL_INFO);
@@ -2589,28 +2527,27 @@ bfa_fcs_rport_uf_recv(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs,
}
}
-/* Send best case acc to prlo */
+/* send best case acc to prlo */
static void
bfa_fcs_rport_send_prlo_acc(struct bfa_fcs_rport_s *rport)
{
- struct bfa_fcs_port_s *port = rport->port;
- struct fchs_s fchs;
+ struct bfa_fcs_lport_s *port = rport->port;
+ struct fchs_s fchs;
struct bfa_fcxp_s *fcxp;
- int len;
+ int len;
bfa_trc(rport->fcs, rport->pid);
fcxp = bfa_fcs_fcxp_alloc(port->fcs);
if (!fcxp)
return;
-
len = fc_prlo_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
- rport->pid, bfa_fcs_port_get_fcid(port),
+ rport->pid, bfa_fcs_lport_get_fcid(port),
rport->reply_oxid, 0);
bfa_fcxp_send(fcxp, rport->bfa_rport, port->fabric->vf_id,
- port->lp_tag, BFA_FALSE, FC_CLASS_3, len, &fchs,
- NULL, NULL, FC_MAX_PDUSZ, 0);
+ port->lp_tag, BFA_FALSE, FC_CLASS_3, len, &fchs,
+ NULL, NULL, FC_MAX_PDUSZ, 0);
}
/*
@@ -2620,10 +2557,10 @@ static void
bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs,
u8 reason_code, u8 reason_code_expl)
{
- struct bfa_fcs_port_s *port = rport->port;
- struct fchs_s fchs;
+ struct bfa_fcs_lport_s *port = rport->port;
+ struct fchs_s fchs;
struct bfa_fcxp_s *fcxp;
- int len;
+ int len;
bfa_trc(rport->fcs, rx_fchs->s_id);
@@ -2631,12 +2568,13 @@ bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs,
if (!fcxp)
return;
- len = fc_ls_rjt_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
- bfa_fcs_port_get_fcid(port), rx_fchs->ox_id,
- reason_code, reason_code_expl);
+ len = fc_ls_rjt_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+ rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
+ rx_fchs->ox_id, reason_code, reason_code_expl);
- bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
- FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
+ bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag,
+ BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
+ FC_MAX_PDUSZ, 0);
}
/**
@@ -2649,24 +2587,22 @@ bfa_fcs_rport_get_state(struct bfa_fcs_rport_s *rport)
}
/**
- * Called by the Driver to set rport delete/ageout timeout
+ * brief
+ * Called by the Driver to set rport delete/ageout timeout
*
- * param[in] rport timeout value in seconds.
+ * param[in] rport timeout value in seconds.
*
- * return None
+ * return None
*/
void
bfa_fcs_rport_set_del_timeout(u8 rport_tmo)
{
- /*
- * convert to Millisecs
- */
+ /* convert to Millisecs */
if (rport_tmo > 0)
bfa_fcs_rport_del_timeout = rport_tmo * 1000;
}
-
void
-bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, uint16_t ox_id)
+bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, u16 ox_id)
{
bfa_trc(rport->fcs, rport->pid);
@@ -2674,3 +2610,517 @@ bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, uint16_t ox_id)
rport->reply_oxid = ox_id;
bfa_sm_send_event(rport, RPSM_EVENT_PRLO_RCVD);
}
+
+
+
+/**
+ * Remote port implementation.
+ */
+
+/**
+ * fcs_rport_api FCS rport API.
+ */
+
+/**
+ * Direct API to add a target by port wwn. This interface is used, for
+ * example, by bios when target pwwn is known from boot lun configuration.
+ */
+bfa_status_t
+bfa_fcs_rport_add(struct bfa_fcs_lport_s *port, wwn_t *pwwn,
+ struct bfa_fcs_rport_s *rport, struct bfad_rport_s *rport_drv)
+{
+ bfa_trc(port->fcs, *pwwn);
+
+ return BFA_STATUS_OK;
+}
+
+/**
+ * Direct API to remove a target and its associated resources. This
+ * interface is used, for example, by driver to remove target
+ * ports from the target list for a VM.
+ */
+bfa_status_t
+bfa_fcs_rport_remove(struct bfa_fcs_rport_s *rport_in)
+{
+
+ struct bfa_fcs_rport_s *rport;
+
+ bfa_trc(rport_in->fcs, rport_in->pwwn);
+
+ rport = bfa_fcs_lport_get_rport_by_pwwn(rport_in->port, rport_in->pwwn);
+ if (rport == NULL) {
+ /*
+ * TBD Error handling
+ */
+ bfa_trc(rport_in->fcs, rport_in->pid);
+ return BFA_STATUS_UNKNOWN_RWWN;
+ }
+
+ /*
+ * TBD if this remote port is online, send a logo
+ */
+ return BFA_STATUS_OK;
+
+}
+
+/**
+ * Remote device status for display/debug.
+ */
+void
+bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport,
+ struct bfa_rport_attr_s *rport_attr)
+{
+ struct bfa_rport_qos_attr_s qos_attr;
+ bfa_fcs_lport_t *port = rport->port;
+ bfa_port_speed_t rport_speed = rport->rpf.rpsc_speed;
+
+ bfa_os_memset(rport_attr, 0, sizeof(struct bfa_rport_attr_s));
+
+ rport_attr->pid = rport->pid;
+ rport_attr->pwwn = rport->pwwn;
+ rport_attr->nwwn = rport->nwwn;
+ rport_attr->cos_supported = rport->fc_cos;
+ rport_attr->df_sz = rport->maxfrsize;
+ rport_attr->state = bfa_fcs_rport_get_state(rport);
+ rport_attr->fc_cos = rport->fc_cos;
+ rport_attr->cisc = rport->cisc;
+ rport_attr->scsi_function = rport->scsi_function;
+ rport_attr->curr_speed = rport->rpf.rpsc_speed;
+ rport_attr->assigned_speed = rport->rpf.assigned_speed;
+
+ bfa_rport_get_qos_attr(rport->bfa_rport, &qos_attr);
+ rport_attr->qos_attr = qos_attr;
+
+ rport_attr->trl_enforced = BFA_FALSE;
+ if (bfa_fcport_is_ratelim(port->fcs->bfa)) {
+ if (rport_speed == BFA_PORT_SPEED_UNKNOWN) {
+ /* Use default ratelim speed setting */
+ rport_speed =
+ bfa_fcport_get_ratelim_speed(rport->fcs->bfa);
+ }
+
+ if (rport_speed < bfa_fcs_lport_get_rport_max_speed(port))
+ rport_attr->trl_enforced = BFA_TRUE;
+ }
+}
+
+/**
+ * Per remote device statistics.
+ */
+void
+bfa_fcs_rport_get_stats(struct bfa_fcs_rport_s *rport,
+ struct bfa_rport_stats_s *stats)
+{
+ *stats = rport->stats;
+}
+
+void
+bfa_fcs_rport_clear_stats(struct bfa_fcs_rport_s *rport)
+{
+ bfa_os_memset((char *)&rport->stats, 0,
+ sizeof(struct bfa_rport_stats_s));
+}
+
+struct bfa_fcs_rport_s *
+bfa_fcs_rport_lookup(struct bfa_fcs_lport_s *port, wwn_t rpwwn)
+{
+ struct bfa_fcs_rport_s *rport;
+
+ rport = bfa_fcs_lport_get_rport_by_pwwn(port, rpwwn);
+ if (rport == NULL) {
+ /*
+ * TBD Error handling
+ */
+ }
+
+ return rport;
+}
+
+struct bfa_fcs_rport_s *
+bfa_fcs_rport_lookup_by_nwwn(struct bfa_fcs_lport_s *port, wwn_t rnwwn)
+{
+ struct bfa_fcs_rport_s *rport;
+
+ rport = bfa_fcs_lport_get_rport_by_nwwn(port, rnwwn);
+ if (rport == NULL) {
+ /*
+ * TBD Error handling
+ */
+ }
+
+ return rport;
+}
+
+/*
+ * This API is to set the Rport's speed. Should be used when RPSC is not
+ * supported by the rport.
+ */
+void
+bfa_fcs_rport_set_speed(struct bfa_fcs_rport_s *rport, bfa_port_speed_t speed)
+{
+ rport->rpf.assigned_speed = speed;
+
+ /* Set this speed in f/w only if the RPSC speed is not available */
+ if (rport->rpf.rpsc_speed == BFA_PORT_SPEED_UNKNOWN)
+ bfa_rport_speed(rport->bfa_rport, speed);
+}
+
+
+
+/**
+ * Remote port features (RPF) implementation.
+ */
+
+#define BFA_FCS_RPF_RETRIES (3)
+#define BFA_FCS_RPF_RETRY_TIMEOUT (1000) /* 1 sec (In millisecs) */
+
+static void bfa_fcs_rpf_send_rpsc2(void *rport_cbarg,
+ struct bfa_fcxp_s *fcxp_alloced);
+static void bfa_fcs_rpf_rpsc2_response(void *fcsarg,
+ struct bfa_fcxp_s *fcxp,
+ void *cbarg,
+ bfa_status_t req_status,
+ u32 rsp_len,
+ u32 resid_len,
+ struct fchs_s *rsp_fchs);
+
+static void bfa_fcs_rpf_timeout(void *arg);
+
+/**
+ * fcs_rport_ftrs_sm FCS rport state machine events
+ */
+
+enum rpf_event {
+ RPFSM_EVENT_RPORT_OFFLINE = 1, /* Rport offline */
+ RPFSM_EVENT_RPORT_ONLINE = 2, /* Rport online */
+ RPFSM_EVENT_FCXP_SENT = 3, /* Frame from has been sent */
+ RPFSM_EVENT_TIMEOUT = 4, /* Rport SM timeout event */
+ RPFSM_EVENT_RPSC_COMP = 5,
+ RPFSM_EVENT_RPSC_FAIL = 6,
+ RPFSM_EVENT_RPSC_ERROR = 7,
+};
+
+static void bfa_fcs_rpf_sm_uninit(struct bfa_fcs_rpf_s *rpf,
+ enum rpf_event event);
+static void bfa_fcs_rpf_sm_rpsc_sending(struct bfa_fcs_rpf_s *rpf,
+ enum rpf_event event);
+static void bfa_fcs_rpf_sm_rpsc(struct bfa_fcs_rpf_s *rpf,
+ enum rpf_event event);
+static void bfa_fcs_rpf_sm_rpsc_retry(struct bfa_fcs_rpf_s *rpf,
+ enum rpf_event event);
+static void bfa_fcs_rpf_sm_offline(struct bfa_fcs_rpf_s *rpf,
+ enum rpf_event event);
+static void bfa_fcs_rpf_sm_online(struct bfa_fcs_rpf_s *rpf,
+ enum rpf_event event);
+
+static void
+bfa_fcs_rpf_sm_uninit(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
+{
+ struct bfa_fcs_rport_s *rport = rpf->rport;
+ struct bfa_fcs_fabric_s *fabric = &rport->fcs->fabric;
+
+ bfa_trc(rport->fcs, rport->pwwn);
+ bfa_trc(rport->fcs, rport->pid);
+ bfa_trc(rport->fcs, event);
+
+ switch (event) {
+ case RPFSM_EVENT_RPORT_ONLINE:
+ /* Send RPSC2 to a Brocade fabric only. */
+ if ((!BFA_FCS_PID_IS_WKA(rport->pid)) &&
+ ((bfa_lps_is_brcd_fabric(rport->port->fabric->lps)) ||
+ (bfa_fcs_fabric_get_switch_oui(fabric) ==
+ BFA_FCS_BRCD_SWITCH_OUI))) {
+ bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);
+ rpf->rpsc_retries = 0;
+ bfa_fcs_rpf_send_rpsc2(rpf, NULL);
+ }
+ break;
+
+ case RPFSM_EVENT_RPORT_OFFLINE:
+ break;
+
+ default:
+ bfa_sm_fault(rport->fcs, event);
+ }
+}
+
+static void
+bfa_fcs_rpf_sm_rpsc_sending(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
+{
+ struct bfa_fcs_rport_s *rport = rpf->rport;
+
+ bfa_trc(rport->fcs, event);
+
+ switch (event) {
+ case RPFSM_EVENT_FCXP_SENT:
+ bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc);
+ break;
+
+ case RPFSM_EVENT_RPORT_OFFLINE:
+ bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
+ bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rpf->fcxp_wqe);
+ rpf->rpsc_retries = 0;
+ break;
+
+ default:
+ bfa_sm_fault(rport->fcs, event);
+ }
+}
+
+static void
+bfa_fcs_rpf_sm_rpsc(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
+{
+ struct bfa_fcs_rport_s *rport = rpf->rport;
+
+ bfa_trc(rport->fcs, rport->pid);
+ bfa_trc(rport->fcs, event);
+
+ switch (event) {
+ case RPFSM_EVENT_RPSC_COMP:
+ bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online);
+ /* Update speed info in f/w via BFA */
+ if (rpf->rpsc_speed != BFA_PORT_SPEED_UNKNOWN)
+ bfa_rport_speed(rport->bfa_rport, rpf->rpsc_speed);
+ else if (rpf->assigned_speed != BFA_PORT_SPEED_UNKNOWN)
+ bfa_rport_speed(rport->bfa_rport, rpf->assigned_speed);
+ break;
+
+ case RPFSM_EVENT_RPSC_FAIL:
+ /* RPSC not supported by rport */
+ bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online);
+ break;
+
+ case RPFSM_EVENT_RPSC_ERROR:
+ /* need to retry...delayed a bit. */
+ if (rpf->rpsc_retries++ < BFA_FCS_RPF_RETRIES) {
+ bfa_timer_start(rport->fcs->bfa, &rpf->timer,
+ bfa_fcs_rpf_timeout, rpf,
+ BFA_FCS_RPF_RETRY_TIMEOUT);
+ bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_retry);
+ } else {
+ bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online);
+ }
+ break;
+
+ case RPFSM_EVENT_RPORT_OFFLINE:
+ bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
+ bfa_fcxp_discard(rpf->fcxp);
+ rpf->rpsc_retries = 0;
+ break;
+
+ default:
+ bfa_sm_fault(rport->fcs, event);
+ }
+}
+
+static void
+bfa_fcs_rpf_sm_rpsc_retry(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
+{
+ struct bfa_fcs_rport_s *rport = rpf->rport;
+
+ bfa_trc(rport->fcs, rport->pid);
+ bfa_trc(rport->fcs, event);
+
+ switch (event) {
+ case RPFSM_EVENT_TIMEOUT:
+ /* re-send the RPSC */
+ bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);
+ bfa_fcs_rpf_send_rpsc2(rpf, NULL);
+ break;
+
+ case RPFSM_EVENT_RPORT_OFFLINE:
+ bfa_timer_stop(&rpf->timer);
+ bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
+ rpf->rpsc_retries = 0;
+ break;
+
+ default:
+ bfa_sm_fault(rport->fcs, event);
+ }
+}
+
+static void
+bfa_fcs_rpf_sm_online(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
+{
+ struct bfa_fcs_rport_s *rport = rpf->rport;
+
+ bfa_trc(rport->fcs, rport->pwwn);
+ bfa_trc(rport->fcs, rport->pid);
+ bfa_trc(rport->fcs, event);
+
+ switch (event) {
+ case RPFSM_EVENT_RPORT_OFFLINE:
+ bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
+ rpf->rpsc_retries = 0;
+ break;
+
+ default:
+ bfa_sm_fault(rport->fcs, event);
+ }
+}
+
+static void
+bfa_fcs_rpf_sm_offline(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
+{
+ struct bfa_fcs_rport_s *rport = rpf->rport;
+
+ bfa_trc(rport->fcs, rport->pwwn);
+ bfa_trc(rport->fcs, rport->pid);
+ bfa_trc(rport->fcs, event);
+
+ switch (event) {
+ case RPFSM_EVENT_RPORT_ONLINE:
+ bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);
+ bfa_fcs_rpf_send_rpsc2(rpf, NULL);
+ break;
+
+ case RPFSM_EVENT_RPORT_OFFLINE:
+ break;
+
+ default:
+ bfa_sm_fault(rport->fcs, event);
+ }
+}
+/**
+ * Called when Rport is created.
+ */
+void
+bfa_fcs_rpf_init(struct bfa_fcs_rport_s *rport)
+{
+ struct bfa_fcs_rpf_s *rpf = &rport->rpf;
+
+ bfa_trc(rport->fcs, rport->pid);
+ rpf->rport = rport;
+
+ bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_uninit);
+}
+
+/**
+ * Called when Rport becomes online
+ */
+void
+bfa_fcs_rpf_rport_online(struct bfa_fcs_rport_s *rport)
+{
+ bfa_trc(rport->fcs, rport->pid);
+
+ if (__fcs_min_cfg(rport->port->fcs))
+ return;
+
+ if (bfa_fcs_fabric_is_switched(rport->port->fabric))
+ bfa_sm_send_event(&rport->rpf, RPFSM_EVENT_RPORT_ONLINE);
+}
+
+/**
+ * Called when Rport becomes offline
+ */
+void
+bfa_fcs_rpf_rport_offline(struct bfa_fcs_rport_s *rport)
+{
+ bfa_trc(rport->fcs, rport->pid);
+
+ if (__fcs_min_cfg(rport->port->fcs))
+ return;
+
+ rport->rpf.rpsc_speed = 0;
+ bfa_sm_send_event(&rport->rpf, RPFSM_EVENT_RPORT_OFFLINE);
+}
+
+static void
+bfa_fcs_rpf_timeout(void *arg)
+{
+ struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *) arg;
+ struct bfa_fcs_rport_s *rport = rpf->rport;
+
+ bfa_trc(rport->fcs, rport->pid);
+ bfa_sm_send_event(rpf, RPFSM_EVENT_TIMEOUT);
+}
+
+static void
+bfa_fcs_rpf_send_rpsc2(void *rpf_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+ struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *)rpf_cbarg;
+ struct bfa_fcs_rport_s *rport = rpf->rport;
+ struct bfa_fcs_lport_s *port = rport->port;
+ struct fchs_s fchs;
+ int len;
+ struct bfa_fcxp_s *fcxp;
+
+ bfa_trc(rport->fcs, rport->pwwn);
+
+ fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+ if (!fcxp) {
+ bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rpf->fcxp_wqe,
+ bfa_fcs_rpf_send_rpsc2, rpf);
+ return;
+ }
+ rpf->fcxp = fcxp;
+
+ len = fc_rpsc2_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
+ bfa_fcs_lport_get_fcid(port), &rport->pid, 1);
+
+ bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+ FC_CLASS_3, len, &fchs, bfa_fcs_rpf_rpsc2_response,
+ rpf, FC_MAX_PDUSZ, FC_ELS_TOV);
+ rport->stats.rpsc_sent++;
+ bfa_sm_send_event(rpf, RPFSM_EVENT_FCXP_SENT);
+
+}
+
+static void
+bfa_fcs_rpf_rpsc2_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
+ bfa_status_t req_status, u32 rsp_len,
+ u32 resid_len, struct fchs_s *rsp_fchs)
+{
+ struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *) cbarg;
+ struct bfa_fcs_rport_s *rport = rpf->rport;
+ struct fc_ls_rjt_s *ls_rjt;
+ struct fc_rpsc2_acc_s *rpsc2_acc;
+ u16 num_ents;
+
+ bfa_trc(rport->fcs, req_status);
+
+ if (req_status != BFA_STATUS_OK) {
+ bfa_trc(rport->fcs, req_status);
+ if (req_status == BFA_STATUS_ETIMER)
+ rport->stats.rpsc_failed++;
+ bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);
+ return;
+ }
+
+ rpsc2_acc = (struct fc_rpsc2_acc_s *) BFA_FCXP_RSP_PLD(fcxp);
+ if (rpsc2_acc->els_cmd == FC_ELS_ACC) {
+ rport->stats.rpsc_accs++;
+ num_ents = bfa_os_ntohs(rpsc2_acc->num_pids);
+ bfa_trc(rport->fcs, num_ents);
+ if (num_ents > 0) {
+ bfa_assert(rpsc2_acc->port_info[0].pid != rport->pid);
+ bfa_trc(rport->fcs,
+ bfa_os_ntohs(rpsc2_acc->port_info[0].pid));
+ bfa_trc(rport->fcs,
+ bfa_os_ntohs(rpsc2_acc->port_info[0].speed));
+ bfa_trc(rport->fcs,
+ bfa_os_ntohs(rpsc2_acc->port_info[0].index));
+ bfa_trc(rport->fcs,
+ rpsc2_acc->port_info[0].type);
+
+ if (rpsc2_acc->port_info[0].speed == 0) {
+ bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);
+ return;
+ }
+
+ rpf->rpsc_speed = fc_rpsc_operspeed_to_bfa_speed(
+ bfa_os_ntohs(rpsc2_acc->port_info[0].speed));
+
+ bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_COMP);
+ }
+ } else {
+ ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
+ bfa_trc(rport->fcs, ls_rjt->reason_code);
+ bfa_trc(rport->fcs, ls_rjt->reason_code_expl);
+ rport->stats.rpsc_rejects++;
+ if (ls_rjt->reason_code == FC_LS_RJT_RSN_CMD_NOT_SUPP)
+ bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_FAIL);
+ else
+ bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);
+ }
+}
diff --git a/drivers/scsi/bfa/bfa_fcs_uf.c b/drivers/scsi/bfa/bfa_fcs_uf.c
deleted file mode 100644
index 3d57d48bbae4..000000000000
--- a/drivers/scsi/bfa/bfa_fcs_uf.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/**
- * bfa_fcs_uf.c BFA FCS UF ( Unsolicited Frames)
- */
-
-#include <fcs/bfa_fcs.h>
-#include <bfa_svc.h>
-#include <fcs/bfa_fcs_fabric.h>
-#include "fcs.h"
-#include "fcs_trcmod.h"
-#include "fcs_fabric.h"
-#include "fcs_uf.h"
-
-BFA_TRC_FILE(FCS, UF);
-
-/**
- * BFA callback for unsolicited frame receive handler.
- *
- * @param[in] cbarg callback arg for receive handler
- * @param[in] uf unsolicited frame descriptor
- *
- * @return None
- */
-static void
-bfa_fcs_uf_recv(void *cbarg, struct bfa_uf_s *uf)
-{
- struct bfa_fcs_s *fcs = (struct bfa_fcs_s *) cbarg;
- struct fchs_s *fchs = bfa_uf_get_frmbuf(uf);
- u16 len = bfa_uf_get_frmlen(uf);
- struct fc_vft_s *vft;
- struct bfa_fcs_fabric_s *fabric;
-
- /**
- * check for VFT header
- */
- if (fchs->routing == FC_RTG_EXT_HDR &&
- fchs->cat_info == FC_CAT_VFT_HDR) {
- bfa_stats(fcs, uf.tagged);
- vft = bfa_uf_get_frmbuf(uf);
- if (fcs->port_vfid == vft->vf_id)
- fabric = &fcs->fabric;
- else
- fabric = bfa_fcs_vf_lookup(fcs, (u16) vft->vf_id);
-
- /**
- * drop frame if vfid is unknown
- */
- if (!fabric) {
- bfa_assert(0);
- bfa_stats(fcs, uf.vfid_unknown);
- bfa_uf_free(uf);
- return;
- }
-
- /**
- * skip vft header
- */
- fchs = (struct fchs_s *) (vft + 1);
- len -= sizeof(struct fc_vft_s);
-
- bfa_trc(fcs, vft->vf_id);
- } else {
- bfa_stats(fcs, uf.untagged);
- fabric = &fcs->fabric;
- }
-
- bfa_trc(fcs, ((u32 *) fchs)[0]);
- bfa_trc(fcs, ((u32 *) fchs)[1]);
- bfa_trc(fcs, ((u32 *) fchs)[2]);
- bfa_trc(fcs, ((u32 *) fchs)[3]);
- bfa_trc(fcs, ((u32 *) fchs)[4]);
- bfa_trc(fcs, ((u32 *) fchs)[5]);
- bfa_trc(fcs, len);
-
- bfa_fcs_fabric_uf_recv(fabric, fchs, len);
- bfa_uf_free(uf);
-}
-
-void
-bfa_fcs_uf_attach(struct bfa_fcs_s *fcs)
-{
- bfa_uf_recv_register(fcs->bfa, bfa_fcs_uf_recv, fcs);
-}
diff --git a/drivers/scsi/bfa/bfa_fcxp.c b/drivers/scsi/bfa/bfa_fcxp.c
deleted file mode 100644
index 8258f88bfee6..000000000000
--- a/drivers/scsi/bfa/bfa_fcxp.c
+++ /dev/null
@@ -1,774 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#include <bfa.h>
-#include <bfi/bfi_uf.h>
-#include <cs/bfa_debug.h>
-
-BFA_TRC_FILE(HAL, FCXP);
-BFA_MODULE(fcxp);
-
-/**
- * forward declarations
- */
-static void __bfa_fcxp_send_cbfn(void *cbarg, bfa_boolean_t complete);
-static void hal_fcxp_rx_plog(struct bfa_s *bfa, struct bfa_fcxp_s *fcxp,
- struct bfi_fcxp_send_rsp_s *fcxp_rsp);
-static void hal_fcxp_tx_plog(struct bfa_s *bfa, u32 reqlen,
- struct bfa_fcxp_s *fcxp, struct fchs_s *fchs);
-static void bfa_fcxp_qresume(void *cbarg);
-static void bfa_fcxp_queue(struct bfa_fcxp_s *fcxp,
- struct bfi_fcxp_send_req_s *send_req);
-
-/**
- * fcxp_pvt BFA FCXP private functions
- */
-
-static void
-claim_fcxp_req_rsp_mem(struct bfa_fcxp_mod_s *mod, struct bfa_meminfo_s *mi)
-{
- u8 *dm_kva = NULL;
- u64 dm_pa;
- u32 buf_pool_sz;
-
- dm_kva = bfa_meminfo_dma_virt(mi);
- dm_pa = bfa_meminfo_dma_phys(mi);
-
- buf_pool_sz = mod->req_pld_sz * mod->num_fcxps;
-
- /*
- * Initialize the fcxp req payload list
- */
- mod->req_pld_list_kva = dm_kva;
- mod->req_pld_list_pa = dm_pa;
- dm_kva += buf_pool_sz;
- dm_pa += buf_pool_sz;
- bfa_os_memset(mod->req_pld_list_kva, 0, buf_pool_sz);
-
- /*
- * Initialize the fcxp rsp payload list
- */
- buf_pool_sz = mod->rsp_pld_sz * mod->num_fcxps;
- mod->rsp_pld_list_kva = dm_kva;
- mod->rsp_pld_list_pa = dm_pa;
- dm_kva += buf_pool_sz;
- dm_pa += buf_pool_sz;
- bfa_os_memset(mod->rsp_pld_list_kva, 0, buf_pool_sz);
-
- bfa_meminfo_dma_virt(mi) = dm_kva;
- bfa_meminfo_dma_phys(mi) = dm_pa;
-}
-
-static void
-claim_fcxps_mem(struct bfa_fcxp_mod_s *mod, struct bfa_meminfo_s *mi)
-{
- u16 i;
- struct bfa_fcxp_s *fcxp;
-
- fcxp = (struct bfa_fcxp_s *) bfa_meminfo_kva(mi);
- bfa_os_memset(fcxp, 0, sizeof(struct bfa_fcxp_s) * mod->num_fcxps);
-
- INIT_LIST_HEAD(&mod->fcxp_free_q);
- INIT_LIST_HEAD(&mod->fcxp_active_q);
-
- mod->fcxp_list = fcxp;
-
- for (i = 0; i < mod->num_fcxps; i++) {
- fcxp->fcxp_mod = mod;
- fcxp->fcxp_tag = i;
-
- list_add_tail(&fcxp->qe, &mod->fcxp_free_q);
- bfa_reqq_winit(&fcxp->reqq_wqe, bfa_fcxp_qresume, fcxp);
- fcxp->reqq_waiting = BFA_FALSE;
-
- fcxp = fcxp + 1;
- }
-
- bfa_meminfo_kva(mi) = (void *)fcxp;
-}
-
-static void
-bfa_fcxp_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
- u32 *dm_len)
-{
- u16 num_fcxp_reqs = cfg->fwcfg.num_fcxp_reqs;
-
- if (num_fcxp_reqs == 0)
- return;
-
- /*
- * Account for req/rsp payload
- */
- *dm_len += BFA_FCXP_MAX_IBUF_SZ * num_fcxp_reqs;
- if (cfg->drvcfg.min_cfg)
- *dm_len += BFA_FCXP_MAX_IBUF_SZ * num_fcxp_reqs;
- else
- *dm_len += BFA_FCXP_MAX_LBUF_SZ * num_fcxp_reqs;
-
- /*
- * Account for fcxp structs
- */
- *ndm_len += sizeof(struct bfa_fcxp_s) * num_fcxp_reqs;
-}
-
-static void
-bfa_fcxp_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
- struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
-{
- struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
-
- bfa_os_memset(mod, 0, sizeof(struct bfa_fcxp_mod_s));
- mod->bfa = bfa;
- mod->num_fcxps = cfg->fwcfg.num_fcxp_reqs;
-
- /**
- * Initialize FCXP request and response payload sizes.
- */
- mod->req_pld_sz = mod->rsp_pld_sz = BFA_FCXP_MAX_IBUF_SZ;
- if (!cfg->drvcfg.min_cfg)
- mod->rsp_pld_sz = BFA_FCXP_MAX_LBUF_SZ;
-
- INIT_LIST_HEAD(&mod->wait_q);
-
- claim_fcxp_req_rsp_mem(mod, meminfo);
- claim_fcxps_mem(mod, meminfo);
-}
-
-static void
-bfa_fcxp_detach(struct bfa_s *bfa)
-{
-}
-
-static void
-bfa_fcxp_start(struct bfa_s *bfa)
-{
-}
-
-static void
-bfa_fcxp_stop(struct bfa_s *bfa)
-{
-}
-
-static void
-bfa_fcxp_iocdisable(struct bfa_s *bfa)
-{
- struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
- struct bfa_fcxp_s *fcxp;
- struct list_head *qe, *qen;
-
- list_for_each_safe(qe, qen, &mod->fcxp_active_q) {
- fcxp = (struct bfa_fcxp_s *) qe;
- if (fcxp->caller == NULL) {
- fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
- BFA_STATUS_IOC_FAILURE, 0, 0, NULL);
- bfa_fcxp_free(fcxp);
- } else {
- fcxp->rsp_status = BFA_STATUS_IOC_FAILURE;
- bfa_cb_queue(bfa, &fcxp->hcb_qe,
- __bfa_fcxp_send_cbfn, fcxp);
- }
- }
-}
-
-static struct bfa_fcxp_s *
-bfa_fcxp_get(struct bfa_fcxp_mod_s *fm)
-{
- struct bfa_fcxp_s *fcxp;
-
- bfa_q_deq(&fm->fcxp_free_q, &fcxp);
-
- if (fcxp)
- list_add_tail(&fcxp->qe, &fm->fcxp_active_q);
-
- return fcxp;
-}
-
-static void
-bfa_fcxp_put(struct bfa_fcxp_s *fcxp)
-{
- struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
- struct bfa_fcxp_wqe_s *wqe;
-
- bfa_q_deq(&mod->wait_q, &wqe);
- if (wqe) {
- bfa_trc(mod->bfa, fcxp->fcxp_tag);
- wqe->alloc_cbfn(wqe->alloc_cbarg, fcxp);
- return;
- }
-
- bfa_assert(bfa_q_is_on_q(&mod->fcxp_active_q, fcxp));
- list_del(&fcxp->qe);
- list_add_tail(&fcxp->qe, &mod->fcxp_free_q);
-}
-
-static void
-bfa_fcxp_null_comp(void *bfad_fcxp, struct bfa_fcxp_s *fcxp, void *cbarg,
- bfa_status_t req_status, u32 rsp_len,
- u32 resid_len, struct fchs_s *rsp_fchs)
-{
- /* discarded fcxp completion */
-}
-
-static void
-__bfa_fcxp_send_cbfn(void *cbarg, bfa_boolean_t complete)
-{
- struct bfa_fcxp_s *fcxp = cbarg;
-
- if (complete) {
- fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
- fcxp->rsp_status, fcxp->rsp_len,
- fcxp->residue_len, &fcxp->rsp_fchs);
- } else {
- bfa_fcxp_free(fcxp);
- }
-}
-
-static void
-hal_fcxp_send_comp(struct bfa_s *bfa, struct bfi_fcxp_send_rsp_s *fcxp_rsp)
-{
- struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
- struct bfa_fcxp_s *fcxp;
- u16 fcxp_tag = bfa_os_ntohs(fcxp_rsp->fcxp_tag);
-
- bfa_trc(bfa, fcxp_tag);
-
- fcxp_rsp->rsp_len = bfa_os_ntohl(fcxp_rsp->rsp_len);
-
- /**
- * @todo f/w should not set residue to non-0 when everything
- * is received.
- */
- if (fcxp_rsp->req_status == BFA_STATUS_OK)
- fcxp_rsp->residue_len = 0;
- else
- fcxp_rsp->residue_len = bfa_os_ntohl(fcxp_rsp->residue_len);
-
- fcxp = BFA_FCXP_FROM_TAG(mod, fcxp_tag);
-
- bfa_assert(fcxp->send_cbfn != NULL);
-
- hal_fcxp_rx_plog(mod->bfa, fcxp, fcxp_rsp);
-
- if (fcxp->send_cbfn != NULL) {
- if (fcxp->caller == NULL) {
- bfa_trc(mod->bfa, fcxp->fcxp_tag);
-
- fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
- fcxp_rsp->req_status, fcxp_rsp->rsp_len,
- fcxp_rsp->residue_len, &fcxp_rsp->fchs);
- /*
- * fcxp automatically freed on return from the callback
- */
- bfa_fcxp_free(fcxp);
- } else {
- bfa_trc(mod->bfa, fcxp->fcxp_tag);
- fcxp->rsp_status = fcxp_rsp->req_status;
- fcxp->rsp_len = fcxp_rsp->rsp_len;
- fcxp->residue_len = fcxp_rsp->residue_len;
- fcxp->rsp_fchs = fcxp_rsp->fchs;
-
- bfa_cb_queue(bfa, &fcxp->hcb_qe,
- __bfa_fcxp_send_cbfn, fcxp);
- }
- } else {
- bfa_trc(bfa, fcxp_tag);
- }
-}
-
-static void
-hal_fcxp_set_local_sges(struct bfi_sge_s *sge, u32 reqlen, u64 req_pa)
-{
- union bfi_addr_u sga_zero = { {0} };
-
- sge->sg_len = reqlen;
- sge->flags = BFI_SGE_DATA_LAST;
- bfa_dma_addr_set(sge[0].sga, req_pa);
- bfa_sge_to_be(sge);
- sge++;
-
- sge->sga = sga_zero;
- sge->sg_len = reqlen;
- sge->flags = BFI_SGE_PGDLEN;
- bfa_sge_to_be(sge);
-}
-
-static void
-hal_fcxp_tx_plog(struct bfa_s *bfa, u32 reqlen, struct bfa_fcxp_s *fcxp,
- struct fchs_s *fchs)
-{
- /*
- * TODO: TX ox_id
- */
- if (reqlen > 0) {
- if (fcxp->use_ireqbuf) {
- u32 pld_w0 =
- *((u32 *) BFA_FCXP_REQ_PLD(fcxp));
-
- bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_FCXP,
- BFA_PL_EID_TX,
- reqlen + sizeof(struct fchs_s), fchs, pld_w0);
- } else {
- bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP,
- BFA_PL_EID_TX, reqlen + sizeof(struct fchs_s),
- fchs);
- }
- } else {
- bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP, BFA_PL_EID_TX,
- reqlen + sizeof(struct fchs_s), fchs);
- }
-}
-
-static void
-hal_fcxp_rx_plog(struct bfa_s *bfa, struct bfa_fcxp_s *fcxp,
- struct bfi_fcxp_send_rsp_s *fcxp_rsp)
-{
- if (fcxp_rsp->rsp_len > 0) {
- if (fcxp->use_irspbuf) {
- u32 pld_w0 =
- *((u32 *) BFA_FCXP_RSP_PLD(fcxp));
-
- bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_FCXP,
- BFA_PL_EID_RX,
- (u16) fcxp_rsp->rsp_len,
- &fcxp_rsp->fchs, pld_w0);
- } else {
- bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP,
- BFA_PL_EID_RX,
- (u16) fcxp_rsp->rsp_len,
- &fcxp_rsp->fchs);
- }
- } else {
- bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP, BFA_PL_EID_RX,
- (u16) fcxp_rsp->rsp_len, &fcxp_rsp->fchs);
- }
-}
-
-/**
- * Handler to resume sending fcxp when space in available in cpe queue.
- */
-static void
-bfa_fcxp_qresume(void *cbarg)
-{
- struct bfa_fcxp_s *fcxp = cbarg;
- struct bfa_s *bfa = fcxp->fcxp_mod->bfa;
- struct bfi_fcxp_send_req_s *send_req;
-
- fcxp->reqq_waiting = BFA_FALSE;
- send_req = bfa_reqq_next(bfa, BFA_REQQ_FCXP);
- bfa_fcxp_queue(fcxp, send_req);
-}
-
-/**
- * Queue fcxp send request to foimrware.
- */
-static void
-bfa_fcxp_queue(struct bfa_fcxp_s *fcxp, struct bfi_fcxp_send_req_s *send_req)
-{
- struct bfa_s *bfa = fcxp->fcxp_mod->bfa;
- struct bfa_fcxp_req_info_s *reqi = &fcxp->req_info;
- struct bfa_fcxp_rsp_info_s *rspi = &fcxp->rsp_info;
- struct bfa_rport_s *rport = reqi->bfa_rport;
-
- bfi_h2i_set(send_req->mh, BFI_MC_FCXP, BFI_FCXP_H2I_SEND_REQ,
- bfa_lpuid(bfa));
-
- send_req->fcxp_tag = bfa_os_htons(fcxp->fcxp_tag);
- if (rport) {
- send_req->rport_fw_hndl = rport->fw_handle;
- send_req->max_frmsz = bfa_os_htons(rport->rport_info.max_frmsz);
- if (send_req->max_frmsz == 0)
- send_req->max_frmsz = bfa_os_htons(FC_MAX_PDUSZ);
- } else {
- send_req->rport_fw_hndl = 0;
- send_req->max_frmsz = bfa_os_htons(FC_MAX_PDUSZ);
- }
-
- send_req->vf_id = bfa_os_htons(reqi->vf_id);
- send_req->lp_tag = reqi->lp_tag;
- send_req->class = reqi->class;
- send_req->rsp_timeout = rspi->rsp_timeout;
- send_req->cts = reqi->cts;
- send_req->fchs = reqi->fchs;
-
- send_req->req_len = bfa_os_htonl(reqi->req_tot_len);
- send_req->rsp_maxlen = bfa_os_htonl(rspi->rsp_maxlen);
-
- /*
- * setup req sgles
- */
- if (fcxp->use_ireqbuf == 1) {
- hal_fcxp_set_local_sges(send_req->req_sge, reqi->req_tot_len,
- BFA_FCXP_REQ_PLD_PA(fcxp));
- } else {
- if (fcxp->nreq_sgles > 0) {
- bfa_assert(fcxp->nreq_sgles == 1);
- hal_fcxp_set_local_sges(send_req->req_sge,
- reqi->req_tot_len,
- fcxp->req_sga_cbfn(fcxp->caller,
- 0));
- } else {
- bfa_assert(reqi->req_tot_len == 0);
- hal_fcxp_set_local_sges(send_req->rsp_sge, 0, 0);
- }
- }
-
- /*
- * setup rsp sgles
- */
- if (fcxp->use_irspbuf == 1) {
- bfa_assert(rspi->rsp_maxlen <= BFA_FCXP_MAX_LBUF_SZ);
-
- hal_fcxp_set_local_sges(send_req->rsp_sge, rspi->rsp_maxlen,
- BFA_FCXP_RSP_PLD_PA(fcxp));
-
- } else {
- if (fcxp->nrsp_sgles > 0) {
- bfa_assert(fcxp->nrsp_sgles == 1);
- hal_fcxp_set_local_sges(send_req->rsp_sge,
- rspi->rsp_maxlen,
- fcxp->rsp_sga_cbfn(fcxp->caller,
- 0));
- } else {
- bfa_assert(rspi->rsp_maxlen == 0);
- hal_fcxp_set_local_sges(send_req->rsp_sge, 0, 0);
- }
- }
-
- hal_fcxp_tx_plog(bfa, reqi->req_tot_len, fcxp, &reqi->fchs);
-
- bfa_reqq_produce(bfa, BFA_REQQ_FCXP);
-
- bfa_trc(bfa, bfa_reqq_pi(bfa, BFA_REQQ_FCXP));
- bfa_trc(bfa, bfa_reqq_ci(bfa, BFA_REQQ_FCXP));
-}
-
-
-/**
- * hal_fcxp_api BFA FCXP API
- */
-
-/**
- * Allocate an FCXP instance to send a response or to send a request
- * that has a response. Request/response buffers are allocated by caller.
- *
- * @param[in] bfa BFA bfa instance
- * @param[in] nreq_sgles Number of SG elements required for request
- * buffer. 0, if fcxp internal buffers are used.
- * Use bfa_fcxp_get_reqbuf() to get the
- * internal req buffer.
- * @param[in] req_sgles SG elements describing request buffer. Will be
- * copied in by BFA and hence can be freed on
- * return from this function.
- * @param[in] get_req_sga function ptr to be called to get a request SG
- * Address (given the sge index).
- * @param[in] get_req_sglen function ptr to be called to get a request SG
- * len (given the sge index).
- * @param[in] get_rsp_sga function ptr to be called to get a response SG
- * Address (given the sge index).
- * @param[in] get_rsp_sglen function ptr to be called to get a response SG
- * len (given the sge index).
- *
- * @return FCXP instance. NULL on failure.
- */
-struct bfa_fcxp_s *
-bfa_fcxp_alloc(void *caller, struct bfa_s *bfa, int nreq_sgles,
- int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,
- bfa_fcxp_get_sglen_t req_sglen_cbfn,
- bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,
- bfa_fcxp_get_sglen_t rsp_sglen_cbfn)
-{
- struct bfa_fcxp_s *fcxp = NULL;
- u32 nreq_sgpg, nrsp_sgpg;
-
- bfa_assert(bfa != NULL);
-
- fcxp = bfa_fcxp_get(BFA_FCXP_MOD(bfa));
- if (fcxp == NULL)
- return NULL;
-
- bfa_trc(bfa, fcxp->fcxp_tag);
-
- fcxp->caller = caller;
-
- if (nreq_sgles == 0) {
- fcxp->use_ireqbuf = 1;
- } else {
- bfa_assert(req_sga_cbfn != NULL);
- bfa_assert(req_sglen_cbfn != NULL);
-
- fcxp->use_ireqbuf = 0;
- fcxp->req_sga_cbfn = req_sga_cbfn;
- fcxp->req_sglen_cbfn = req_sglen_cbfn;
-
- fcxp->nreq_sgles = nreq_sgles;
-
- /*
- * alloc required sgpgs
- */
- if (nreq_sgles > BFI_SGE_INLINE) {
- nreq_sgpg = BFA_SGPG_NPAGE(nreq_sgles);
-
- if (bfa_sgpg_malloc(bfa, &fcxp->req_sgpg_q, nreq_sgpg)
- != BFA_STATUS_OK) {
- /*
- * TODO
- */
- }
- }
- }
-
- if (nrsp_sgles == 0) {
- fcxp->use_irspbuf = 1;
- } else {
- bfa_assert(rsp_sga_cbfn != NULL);
- bfa_assert(rsp_sglen_cbfn != NULL);
-
- fcxp->use_irspbuf = 0;
- fcxp->rsp_sga_cbfn = rsp_sga_cbfn;
- fcxp->rsp_sglen_cbfn = rsp_sglen_cbfn;
-
- fcxp->nrsp_sgles = nrsp_sgles;
- /*
- * alloc required sgpgs
- */
- if (nrsp_sgles > BFI_SGE_INLINE) {
- nrsp_sgpg = BFA_SGPG_NPAGE(nreq_sgles);
-
- if (bfa_sgpg_malloc
- (bfa, &fcxp->rsp_sgpg_q, nrsp_sgpg)
- != BFA_STATUS_OK) {
- /* bfa_sgpg_wait(bfa, &fcxp->rsp_sgpg_wqe,
- nrsp_sgpg); */
- /*
- * TODO
- */
- }
- }
- }
-
- return fcxp;
-}
-
-/**
- * Get the internal request buffer pointer
- *
- * @param[in] fcxp BFA fcxp pointer
- *
- * @return pointer to the internal request buffer
- */
-void *
-bfa_fcxp_get_reqbuf(struct bfa_fcxp_s *fcxp)
-{
- struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
- void *reqbuf;
-
- bfa_assert(fcxp->use_ireqbuf == 1);
- reqbuf = ((u8 *)mod->req_pld_list_kva) +
- fcxp->fcxp_tag * mod->req_pld_sz;
- return reqbuf;
-}
-
-u32
-bfa_fcxp_get_reqbufsz(struct bfa_fcxp_s *fcxp)
-{
- struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
-
- return mod->req_pld_sz;
-}
-
-/**
- * Get the internal response buffer pointer
- *
- * @param[in] fcxp BFA fcxp pointer
- *
- * @return pointer to the internal request buffer
- */
-void *
-bfa_fcxp_get_rspbuf(struct bfa_fcxp_s *fcxp)
-{
- struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
- void *rspbuf;
-
- bfa_assert(fcxp->use_irspbuf == 1);
-
- rspbuf = ((u8 *)mod->rsp_pld_list_kva) +
- fcxp->fcxp_tag * mod->rsp_pld_sz;
- return rspbuf;
-}
-
-/**
- * Free the BFA FCXP
- *
- * @param[in] fcxp BFA fcxp pointer
- *
- * @return void
- */
-void
-bfa_fcxp_free(struct bfa_fcxp_s *fcxp)
-{
- struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
-
- bfa_assert(fcxp != NULL);
- bfa_trc(mod->bfa, fcxp->fcxp_tag);
- bfa_fcxp_put(fcxp);
-}
-
-/**
- * Send a FCXP request
- *
- * @param[in] fcxp BFA fcxp pointer
- * @param[in] rport BFA rport pointer. Could be left NULL for WKA rports
- * @param[in] vf_id virtual Fabric ID
- * @param[in] lp_tag lport tag
- * @param[in] cts use Continous sequence
- * @param[in] cos fc Class of Service
- * @param[in] reqlen request length, does not include FCHS length
- * @param[in] fchs fc Header Pointer. The header content will be copied
- * in by BFA.
- *
- * @param[in] cbfn call back function to be called on receiving
- * the response
- * @param[in] cbarg arg for cbfn
- * @param[in] rsp_timeout
- * response timeout
- *
- * @return bfa_status_t
- */
-void
-bfa_fcxp_send(struct bfa_fcxp_s *fcxp, struct bfa_rport_s *rport,
- u16 vf_id, u8 lp_tag, bfa_boolean_t cts, enum fc_cos cos,
- u32 reqlen, struct fchs_s *fchs, bfa_cb_fcxp_send_t cbfn,
- void *cbarg, u32 rsp_maxlen, u8 rsp_timeout)
-{
- struct bfa_s *bfa = fcxp->fcxp_mod->bfa;
- struct bfa_fcxp_req_info_s *reqi = &fcxp->req_info;
- struct bfa_fcxp_rsp_info_s *rspi = &fcxp->rsp_info;
- struct bfi_fcxp_send_req_s *send_req;
-
- bfa_trc(bfa, fcxp->fcxp_tag);
-
- /**
- * setup request/response info
- */
- reqi->bfa_rport = rport;
- reqi->vf_id = vf_id;
- reqi->lp_tag = lp_tag;
- reqi->class = cos;
- rspi->rsp_timeout = rsp_timeout;
- reqi->cts = cts;
- reqi->fchs = *fchs;
- reqi->req_tot_len = reqlen;
- rspi->rsp_maxlen = rsp_maxlen;
- fcxp->send_cbfn = cbfn ? cbfn : bfa_fcxp_null_comp;
- fcxp->send_cbarg = cbarg;
-
- /**
- * If no room in CPE queue, wait for space in request queue
- */
- send_req = bfa_reqq_next(bfa, BFA_REQQ_FCXP);
- if (!send_req) {
- bfa_trc(bfa, fcxp->fcxp_tag);
- fcxp->reqq_waiting = BFA_TRUE;
- bfa_reqq_wait(bfa, BFA_REQQ_FCXP, &fcxp->reqq_wqe);
- return;
- }
-
- bfa_fcxp_queue(fcxp, send_req);
-}
-
-/**
- * Abort a BFA FCXP
- *
- * @param[in] fcxp BFA fcxp pointer
- *
- * @return void
- */
-bfa_status_t
-bfa_fcxp_abort(struct bfa_fcxp_s *fcxp)
-{
- bfa_assert(0);
- return BFA_STATUS_OK;
-}
-
-void
-bfa_fcxp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe,
- bfa_fcxp_alloc_cbfn_t alloc_cbfn, void *alloc_cbarg)
-{
- struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
-
- bfa_assert(list_empty(&mod->fcxp_free_q));
-
- wqe->alloc_cbfn = alloc_cbfn;
- wqe->alloc_cbarg = alloc_cbarg;
- list_add_tail(&wqe->qe, &mod->wait_q);
-}
-
-void
-bfa_fcxp_walloc_cancel(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe)
-{
- struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
-
- bfa_assert(bfa_q_is_on_q(&mod->wait_q, wqe));
- list_del(&wqe->qe);
-}
-
-void
-bfa_fcxp_discard(struct bfa_fcxp_s *fcxp)
-{
- /**
- * If waiting for room in request queue, cancel reqq wait
- * and free fcxp.
- */
- if (fcxp->reqq_waiting) {
- fcxp->reqq_waiting = BFA_FALSE;
- bfa_reqq_wcancel(&fcxp->reqq_wqe);
- bfa_fcxp_free(fcxp);
- return;
- }
-
- fcxp->send_cbfn = bfa_fcxp_null_comp;
-}
-
-
-
-/**
- * hal_fcxp_public BFA FCXP public functions
- */
-
-void
-bfa_fcxp_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
-{
- switch (msg->mhdr.msg_id) {
- case BFI_FCXP_I2H_SEND_RSP:
- hal_fcxp_send_comp(bfa, (struct bfi_fcxp_send_rsp_s *) msg);
- break;
-
- default:
- bfa_trc(bfa, msg->mhdr.msg_id);
- bfa_assert(0);
- }
-}
-
-u32
-bfa_fcxp_get_maxrsp(struct bfa_s *bfa)
-{
- struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
-
- return mod->rsp_pld_sz;
-}
-
-
diff --git a/drivers/scsi/bfa/bfa_fcxp_priv.h b/drivers/scsi/bfa/bfa_fcxp_priv.h
deleted file mode 100644
index 4cda49397da0..000000000000
--- a/drivers/scsi/bfa/bfa_fcxp_priv.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_FCXP_PRIV_H__
-#define __BFA_FCXP_PRIV_H__
-
-#include <cs/bfa_sm.h>
-#include <protocol/fc.h>
-#include <bfa_svc.h>
-#include <bfi/bfi_fcxp.h>
-
-#define BFA_FCXP_MIN (1)
-#define BFA_FCXP_MAX_IBUF_SZ (2 * 1024 + 256)
-#define BFA_FCXP_MAX_LBUF_SZ (4 * 1024 + 256)
-
-struct bfa_fcxp_mod_s {
- struct bfa_s *bfa; /* backpointer to BFA */
- struct bfa_fcxp_s *fcxp_list; /* array of FCXPs */
- u16 num_fcxps; /* max num FCXP requests */
- struct list_head fcxp_free_q; /* free FCXPs */
- struct list_head fcxp_active_q; /* active FCXPs */
- void *req_pld_list_kva; /* list of FCXP req pld */
- u64 req_pld_list_pa; /* list of FCXP req pld */
- void *rsp_pld_list_kva; /* list of FCXP resp pld */
- u64 rsp_pld_list_pa; /* list of FCXP resp pld */
- struct list_head wait_q; /* wait queue for free fcxp */
- u32 req_pld_sz;
- u32 rsp_pld_sz;
-};
-
-#define BFA_FCXP_MOD(__bfa) (&(__bfa)->modules.fcxp_mod)
-#define BFA_FCXP_FROM_TAG(__mod, __tag) (&(__mod)->fcxp_list[__tag])
-
-typedef void (*fcxp_send_cb_t) (struct bfa_s *ioc, struct bfa_fcxp_s *fcxp,
- void *cb_arg, bfa_status_t req_status,
- u32 rsp_len, u32 resid_len,
- struct fchs_s *rsp_fchs);
-
-/**
- * Information needed for a FCXP request
- */
-struct bfa_fcxp_req_info_s {
- struct bfa_rport_s *bfa_rport; /* Pointer to the bfa rport that was
- *returned from bfa_rport_create().
- *This could be left NULL for WKA or for
- *FCXP interactions before the rport
- *nexus is established
- */
- struct fchs_s fchs; /* request FC header structure */
- u8 cts; /* continous sequence */
- u8 class; /* FC class for the request/response */
- u16 max_frmsz; /* max send frame size */
- u16 vf_id; /* vsan tag if applicable */
- u8 lp_tag; /* lport tag */
- u32 req_tot_len; /* request payload total length */
-};
-
-struct bfa_fcxp_rsp_info_s {
- struct fchs_s rsp_fchs; /* Response frame's FC header will
- * be *sent back in this field */
- u8 rsp_timeout; /* timeout in seconds, 0-no response
- */
- u8 rsvd2[3];
- u32 rsp_maxlen; /* max response length expected */
-};
-
-struct bfa_fcxp_s {
- struct list_head qe; /* fcxp queue element */
- bfa_sm_t sm; /* state machine */
- void *caller; /* driver or fcs */
- struct bfa_fcxp_mod_s *fcxp_mod;
- /* back pointer to fcxp mod */
- u16 fcxp_tag; /* internal tag */
- struct bfa_fcxp_req_info_s req_info;
- /* request info */
- struct bfa_fcxp_rsp_info_s rsp_info;
- /* response info */
- u8 use_ireqbuf; /* use internal req buf */
- u8 use_irspbuf; /* use internal rsp buf */
- u32 nreq_sgles; /* num request SGLEs */
- u32 nrsp_sgles; /* num response SGLEs */
- struct list_head req_sgpg_q; /* SG pages for request buf */
- struct list_head req_sgpg_wqe; /* wait queue for req SG page */
- struct list_head rsp_sgpg_q; /* SG pages for response buf */
- struct list_head rsp_sgpg_wqe; /* wait queue for rsp SG page */
-
- bfa_fcxp_get_sgaddr_t req_sga_cbfn;
- /* SG elem addr user function */
- bfa_fcxp_get_sglen_t req_sglen_cbfn;
- /* SG elem len user function */
- bfa_fcxp_get_sgaddr_t rsp_sga_cbfn;
- /* SG elem addr user function */
- bfa_fcxp_get_sglen_t rsp_sglen_cbfn;
- /* SG elem len user function */
- bfa_cb_fcxp_send_t send_cbfn; /* send completion callback */
- void *send_cbarg; /* callback arg */
- struct bfa_sge_s req_sge[BFA_FCXP_MAX_SGES];
- /* req SG elems */
- struct bfa_sge_s rsp_sge[BFA_FCXP_MAX_SGES];
- /* rsp SG elems */
- u8 rsp_status; /* comp: rsp status */
- u32 rsp_len; /* comp: actual response len */
- u32 residue_len; /* comp: residual rsp length */
- struct fchs_s rsp_fchs; /* comp: response fchs */
- struct bfa_cb_qe_s hcb_qe; /* comp: callback qelem */
- struct bfa_reqq_wait_s reqq_wqe;
- bfa_boolean_t reqq_waiting;
-};
-
-#define BFA_FCXP_REQ_PLD(_fcxp) (bfa_fcxp_get_reqbuf(_fcxp))
-
-#define BFA_FCXP_RSP_FCHS(_fcxp) (&((_fcxp)->rsp_info.fchs))
-#define BFA_FCXP_RSP_PLD(_fcxp) (bfa_fcxp_get_rspbuf(_fcxp))
-
-#define BFA_FCXP_REQ_PLD_PA(_fcxp) \
- ((_fcxp)->fcxp_mod->req_pld_list_pa + \
- ((_fcxp)->fcxp_mod->req_pld_sz * (_fcxp)->fcxp_tag))
-
-#define BFA_FCXP_RSP_PLD_PA(_fcxp) \
- ((_fcxp)->fcxp_mod->rsp_pld_list_pa + \
- ((_fcxp)->fcxp_mod->rsp_pld_sz * (_fcxp)->fcxp_tag))
-
-void bfa_fcxp_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
-#endif /* __BFA_FCXP_PRIV_H__ */
diff --git a/drivers/scsi/bfa/bfa_fwimg_priv.h b/drivers/scsi/bfa/bfa_fwimg_priv.h
deleted file mode 100644
index d33e19e54395..000000000000
--- a/drivers/scsi/bfa/bfa_fwimg_priv.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_FWIMG_PRIV_H__
-#define __BFA_FWIMG_PRIV_H__
-
-#define BFI_FLASH_CHUNK_SZ 256 /* Flash chunk size */
-#define BFI_FLASH_CHUNK_SZ_WORDS (BFI_FLASH_CHUNK_SZ/sizeof(u32))
-
-/**
- * BFI FW image type
- */
-enum {
- BFI_IMAGE_CB_FC,
- BFI_IMAGE_CT_FC,
- BFI_IMAGE_CT_CNA,
- BFI_IMAGE_MAX,
-};
-
-extern u32 *bfi_image_get_chunk(int type, uint32_t off);
-extern u32 bfi_image_get_size(int type);
-extern u32 bfi_image_ct_fc_size;
-extern u32 bfi_image_ct_cna_size;
-extern u32 bfi_image_cb_fc_size;
-extern u32 *bfi_image_ct_fc;
-extern u32 *bfi_image_ct_cna;
-extern u32 *bfi_image_cb_fc;
-
-
-#endif /* __BFA_FWIMG_PRIV_H__ */
diff --git a/drivers/scsi/bfa/bfa_hw_cb.c b/drivers/scsi/bfa/bfa_hw_cb.c
index edfd729445cf..c787d3af0886 100644
--- a/drivers/scsi/bfa/bfa_hw_cb.c
+++ b/drivers/scsi/bfa/bfa_hw_cb.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
* All rights reserved
* www.brocade.com
*
@@ -15,15 +15,15 @@
* General Public License for more details.
*/
-#include <bfa_priv.h>
-#include <bfi/bfi_cbreg.h>
+#include "bfa_modules.h"
+#include "bfi_cbreg.h"
void
bfa_hwcb_reginit(struct bfa_s *bfa)
{
struct bfa_iocfc_regs_s *bfa_regs = &bfa->iocfc.bfa_regs;
bfa_os_addr_t kva = bfa_ioc_bar0(&bfa->ioc);
- int i, q, fn = bfa_ioc_pcifn(&bfa->ioc);
+ int i, q, fn = bfa_ioc_pcifn(&bfa->ioc);
if (fn == 0) {
bfa_regs->intr_status = (kva + HOSTFN0_INT_STATUS);
diff --git a/drivers/scsi/bfa/bfa_hw_ct.c b/drivers/scsi/bfa/bfa_hw_ct.c
index a357fb3066fd..c97ebafec5ea 100644
--- a/drivers/scsi/bfa/bfa_hw_ct.c
+++ b/drivers/scsi/bfa/bfa_hw_ct.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
* All rights reserved
* www.brocade.com
*
@@ -15,9 +15,8 @@
* General Public License for more details.
*/
-#include <bfa_priv.h>
-#include <bfi/bfi_ctreg.h>
-#include <bfa_ioc.h>
+#include "bfa_modules.h"
+#include "bfi_ctreg.h"
BFA_TRC_FILE(HAL, IOCFC_CT);
@@ -53,7 +52,7 @@ bfa_hwct_reginit(struct bfa_s *bfa)
{
struct bfa_iocfc_regs_s *bfa_regs = &bfa->iocfc.bfa_regs;
bfa_os_addr_t kva = bfa_ioc_bar0(&bfa->ioc);
- int i, q, fn = bfa_ioc_pcifn(&bfa->ioc);
+ int i, q, fn = bfa_ioc_pcifn(&bfa->ioc);
if (fn == 0) {
bfa_regs->intr_status = (kva + HOSTFN0_INT_STATUS);
@@ -87,7 +86,7 @@ bfa_hwct_reginit(struct bfa_s *bfa)
void
bfa_hwct_reqq_ack(struct bfa_s *bfa, int reqq)
{
- u32 r32;
+ u32 r32;
r32 = bfa_reg_read(bfa->iocfc.bfa_regs.cpe_q_ctrl[reqq]);
bfa_reg_write(bfa->iocfc.bfa_regs.cpe_q_ctrl[reqq], r32);
diff --git a/drivers/scsi/bfa/bfa_intr.c b/drivers/scsi/bfa/bfa_intr.c
deleted file mode 100644
index 493678889b24..000000000000
--- a/drivers/scsi/bfa/bfa_intr.c
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-#include <bfa.h>
-#include <bfi/bfi_ctreg.h>
-#include <bfa_port_priv.h>
-#include <bfa_intr_priv.h>
-#include <cs/bfa_debug.h>
-
-BFA_TRC_FILE(HAL, INTR);
-
-static void
-bfa_msix_errint(struct bfa_s *bfa, u32 intr)
-{
- bfa_ioc_error_isr(&bfa->ioc);
-}
-
-static void
-bfa_msix_lpu(struct bfa_s *bfa)
-{
- bfa_ioc_mbox_isr(&bfa->ioc);
-}
-
-static void
-bfa_reqq_resume(struct bfa_s *bfa, int qid)
-{
- struct list_head *waitq, *qe, *qen;
- struct bfa_reqq_wait_s *wqe;
-
- waitq = bfa_reqq(bfa, qid);
- list_for_each_safe(qe, qen, waitq) {
- /**
- * Callback only as long as there is room in request queue
- */
- if (bfa_reqq_full(bfa, qid))
- break;
-
- list_del(qe);
- wqe = (struct bfa_reqq_wait_s *) qe;
- wqe->qresume(wqe->cbarg);
- }
-}
-
-void
-bfa_msix_all(struct bfa_s *bfa, int vec)
-{
- bfa_intx(bfa);
-}
-
-/**
- * hal_intr_api
- */
-bfa_boolean_t
-bfa_intx(struct bfa_s *bfa)
-{
- u32 intr, qintr;
- int queue;
-
- intr = bfa_reg_read(bfa->iocfc.bfa_regs.intr_status);
- if (!intr)
- return BFA_FALSE;
-
- /**
- * RME completion queue interrupt
- */
- qintr = intr & __HFN_INT_RME_MASK;
- bfa_reg_write(bfa->iocfc.bfa_regs.intr_status, qintr);
-
- for (queue = 0; queue < BFI_IOC_MAX_CQS_ASIC; queue++) {
- if (intr & (__HFN_INT_RME_Q0 << queue))
- bfa_msix_rspq(bfa, queue & (BFI_IOC_MAX_CQS - 1));
- }
- intr &= ~qintr;
- if (!intr)
- return BFA_TRUE;
-
- /**
- * CPE completion queue interrupt
- */
- qintr = intr & __HFN_INT_CPE_MASK;
- bfa_reg_write(bfa->iocfc.bfa_regs.intr_status, qintr);
-
- for (queue = 0; queue < BFI_IOC_MAX_CQS_ASIC; queue++) {
- if (intr & (__HFN_INT_CPE_Q0 << queue))
- bfa_msix_reqq(bfa, queue & (BFI_IOC_MAX_CQS - 1));
- }
- intr &= ~qintr;
- if (!intr)
- return BFA_TRUE;
-
- bfa_msix_lpu_err(bfa, intr);
-
- return BFA_TRUE;
-}
-
-void
-bfa_isr_enable(struct bfa_s *bfa)
-{
- u32 intr_unmask;
- int pci_func = bfa_ioc_pcifn(&bfa->ioc);
-
- bfa_trc(bfa, pci_func);
-
- bfa_msix_install(bfa);
- intr_unmask = (__HFN_INT_ERR_EMC | __HFN_INT_ERR_LPU0 |
- __HFN_INT_ERR_LPU1 | __HFN_INT_ERR_PSS |
- __HFN_INT_LL_HALT);
-
- if (pci_func == 0)
- intr_unmask |= (__HFN_INT_CPE_Q0 | __HFN_INT_CPE_Q1 |
- __HFN_INT_CPE_Q2 | __HFN_INT_CPE_Q3 |
- __HFN_INT_RME_Q0 | __HFN_INT_RME_Q1 |
- __HFN_INT_RME_Q2 | __HFN_INT_RME_Q3 |
- __HFN_INT_MBOX_LPU0);
- else
- intr_unmask |= (__HFN_INT_CPE_Q4 | __HFN_INT_CPE_Q5 |
- __HFN_INT_CPE_Q6 | __HFN_INT_CPE_Q7 |
- __HFN_INT_RME_Q4 | __HFN_INT_RME_Q5 |
- __HFN_INT_RME_Q6 | __HFN_INT_RME_Q7 |
- __HFN_INT_MBOX_LPU1);
-
- bfa_reg_write(bfa->iocfc.bfa_regs.intr_status, intr_unmask);
- bfa_reg_write(bfa->iocfc.bfa_regs.intr_mask, ~intr_unmask);
- bfa->iocfc.intr_mask = ~intr_unmask;
- bfa_isr_mode_set(bfa, bfa->msix.nvecs != 0);
-}
-
-void
-bfa_isr_disable(struct bfa_s *bfa)
-{
- bfa_isr_mode_set(bfa, BFA_FALSE);
- bfa_reg_write(bfa->iocfc.bfa_regs.intr_mask, -1L);
- bfa_msix_uninstall(bfa);
-}
-
-void
-bfa_msix_reqq(struct bfa_s *bfa, int qid)
-{
- struct list_head *waitq;
-
- qid &= (BFI_IOC_MAX_CQS - 1);
-
- bfa->iocfc.hwif.hw_reqq_ack(bfa, qid);
-
- /**
- * Resume any pending requests in the corresponding reqq.
- */
- waitq = bfa_reqq(bfa, qid);
- if (!list_empty(waitq))
- bfa_reqq_resume(bfa, qid);
-}
-
-void
-bfa_isr_unhandled(struct bfa_s *bfa, struct bfi_msg_s *m)
-{
- bfa_trc(bfa, m->mhdr.msg_class);
- bfa_trc(bfa, m->mhdr.msg_id);
- bfa_trc(bfa, m->mhdr.mtag.i2htok);
- bfa_assert(0);
- bfa_trc_stop(bfa->trcmod);
-}
-
-void
-bfa_msix_rspq(struct bfa_s *bfa, int qid)
-{
- struct bfi_msg_s *m;
- u32 pi, ci;
- struct list_head *waitq;
-
- bfa_trc_fp(bfa, qid);
-
- qid &= (BFI_IOC_MAX_CQS - 1);
-
- bfa->iocfc.hwif.hw_rspq_ack(bfa, qid);
-
- ci = bfa_rspq_ci(bfa, qid);
- pi = bfa_rspq_pi(bfa, qid);
-
- bfa_trc_fp(bfa, ci);
- bfa_trc_fp(bfa, pi);
-
- if (bfa->rme_process) {
- while (ci != pi) {
- m = bfa_rspq_elem(bfa, qid, ci);
- bfa_assert_fp(m->mhdr.msg_class < BFI_MC_MAX);
-
- bfa_isrs[m->mhdr.msg_class] (bfa, m);
-
- CQ_INCR(ci, bfa->iocfc.cfg.drvcfg.num_rspq_elems);
- }
- }
-
- /**
- * update CI
- */
- bfa_rspq_ci(bfa, qid) = pi;
- bfa_reg_write(bfa->iocfc.bfa_regs.rme_q_ci[qid], pi);
- bfa_os_mmiowb();
-
- /**
- * Resume any pending requests in the corresponding reqq.
- */
- waitq = bfa_reqq(bfa, qid);
- if (!list_empty(waitq))
- bfa_reqq_resume(bfa, qid);
-}
-
-void
-bfa_msix_lpu_err(struct bfa_s *bfa, int vec)
-{
- u32 intr, curr_value;
-
- intr = bfa_reg_read(bfa->iocfc.bfa_regs.intr_status);
-
- if (intr & (__HFN_INT_MBOX_LPU0 | __HFN_INT_MBOX_LPU1))
- bfa_msix_lpu(bfa);
-
- intr &= (__HFN_INT_ERR_EMC | __HFN_INT_ERR_LPU0 |
- __HFN_INT_ERR_LPU1 | __HFN_INT_ERR_PSS | __HFN_INT_LL_HALT);
-
- if (intr) {
- if (intr & __HFN_INT_LL_HALT) {
- /**
- * If LL_HALT bit is set then FW Init Halt LL Port
- * Register needs to be cleared as well so Interrupt
- * Status Register will be cleared.
- */
- curr_value = bfa_reg_read(bfa->ioc.ioc_regs.ll_halt);
- curr_value &= ~__FW_INIT_HALT_P;
- bfa_reg_write(bfa->ioc.ioc_regs.ll_halt, curr_value);
- }
-
- if (intr & __HFN_INT_ERR_PSS) {
- /**
- * ERR_PSS bit needs to be cleared as well in case
- * interrups are shared so driver's interrupt handler is
- * still called eventhough it is already masked out.
- */
- curr_value = bfa_reg_read(
- bfa->ioc.ioc_regs.pss_err_status_reg);
- curr_value &= __PSS_ERR_STATUS_SET;
- bfa_reg_write(bfa->ioc.ioc_regs.pss_err_status_reg,
- curr_value);
- }
-
- bfa_reg_write(bfa->iocfc.bfa_regs.intr_status, intr);
- bfa_msix_errint(bfa, intr);
- }
-}
-
-void
-bfa_isr_bind(enum bfi_mclass mc, bfa_isr_func_t isr_func)
-{
- bfa_isrs[mc] = isr_func;
-}
-
-
diff --git a/drivers/scsi/bfa/bfa_intr_priv.h b/drivers/scsi/bfa/bfa_intr_priv.h
deleted file mode 100644
index 5fc301cf4d1b..000000000000
--- a/drivers/scsi/bfa/bfa_intr_priv.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_INTR_PRIV_H__
-#define __BFA_INTR_PRIV_H__
-
-/**
- * Message handler
- */
-typedef void (*bfa_isr_func_t) (struct bfa_s *bfa, struct bfi_msg_s *m);
-void bfa_isr_unhandled(struct bfa_s *bfa, struct bfi_msg_s *m);
-void bfa_isr_bind(enum bfi_mclass mc, bfa_isr_func_t isr_func);
-
-
-#define bfa_reqq_pi(__bfa, __reqq) ((__bfa)->iocfc.req_cq_pi[__reqq])
-#define bfa_reqq_ci(__bfa, __reqq) \
- (*(u32 *)((__bfa)->iocfc.req_cq_shadow_ci[__reqq].kva))
-
-#define bfa_reqq_full(__bfa, __reqq) \
- (((bfa_reqq_pi(__bfa, __reqq) + 1) & \
- ((__bfa)->iocfc.cfg.drvcfg.num_reqq_elems - 1)) == \
- bfa_reqq_ci(__bfa, __reqq))
-
-#define bfa_reqq_next(__bfa, __reqq) \
- (bfa_reqq_full(__bfa, __reqq) ? NULL : \
- ((void *)((struct bfi_msg_s *)((__bfa)->iocfc.req_cq_ba[__reqq].kva) \
- + bfa_reqq_pi((__bfa), (__reqq)))))
-
-#define bfa_reqq_produce(__bfa, __reqq) do { \
- (__bfa)->iocfc.req_cq_pi[__reqq]++; \
- (__bfa)->iocfc.req_cq_pi[__reqq] &= \
- ((__bfa)->iocfc.cfg.drvcfg.num_reqq_elems - 1); \
- bfa_reg_write((__bfa)->iocfc.bfa_regs.cpe_q_pi[__reqq], \
- (__bfa)->iocfc.req_cq_pi[__reqq]); \
- bfa_os_mmiowb(); \
-} while (0)
-
-#define bfa_rspq_pi(__bfa, __rspq) \
- (*(u32 *)((__bfa)->iocfc.rsp_cq_shadow_pi[__rspq].kva))
-
-#define bfa_rspq_ci(__bfa, __rspq) ((__bfa)->iocfc.rsp_cq_ci[__rspq])
-#define bfa_rspq_elem(__bfa, __rspq, __ci) \
- (&((struct bfi_msg_s *)((__bfa)->iocfc.rsp_cq_ba[__rspq].kva))[__ci])
-
-#define CQ_INCR(__index, __size) do { \
- (__index)++; \
- (__index) &= ((__size) - 1); \
-} while (0)
-
-/**
- * Queue element to wait for room in request queue. FIFO order is
- * maintained when fullfilling requests.
- */
-struct bfa_reqq_wait_s {
- struct list_head qe;
- void (*qresume) (void *cbarg);
- void *cbarg;
-};
-
-/**
- * Circular queue usage assignments
- */
-enum {
- BFA_REQQ_IOC = 0, /* all low-priority IOC msgs */
- BFA_REQQ_FCXP = 0, /* all FCXP messages */
- BFA_REQQ_LPS = 0, /* all lport service msgs */
- BFA_REQQ_PORT = 0, /* all port messages */
- BFA_REQQ_FLASH = 0, /* for flash module */
- BFA_REQQ_DIAG = 0, /* for diag module */
- BFA_REQQ_RPORT = 0, /* all port messages */
- BFA_REQQ_SBOOT = 0, /* all san boot messages */
- BFA_REQQ_QOS_LO = 1, /* all low priority IO */
- BFA_REQQ_QOS_MD = 2, /* all medium priority IO */
- BFA_REQQ_QOS_HI = 3, /* all high priority IO */
-};
-
-static inline void
-bfa_reqq_winit(struct bfa_reqq_wait_s *wqe, void (*qresume) (void *cbarg),
- void *cbarg)
-{
- wqe->qresume = qresume;
- wqe->cbarg = cbarg;
-}
-
-#define bfa_reqq(__bfa, __reqq) (&(__bfa)->reqq_waitq[__reqq])
-
-/**
- * static inline void
- * bfa_reqq_wait(struct bfa_s *bfa, int reqq, struct bfa_reqq_wait_s *wqe)
- */
-#define bfa_reqq_wait(__bfa, __reqq, __wqe) do { \
- \
- struct list_head *waitq = bfa_reqq(__bfa, __reqq); \
- \
- bfa_assert(((__reqq) < BFI_IOC_MAX_CQS)); \
- bfa_assert((__wqe)->qresume && (__wqe)->cbarg); \
- \
- list_add_tail(&(__wqe)->qe, waitq); \
-} while (0)
-
-#define bfa_reqq_wcancel(__wqe) list_del(&(__wqe)->qe)
-
-#endif /* __BFA_INTR_PRIV_H__ */
diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c
index 8e78f20110a5..6795b247791a 100644
--- a/drivers/scsi/bfa/bfa_ioc.c
+++ b/drivers/scsi/bfa/bfa_ioc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
* All rights reserved
* www.brocade.com
*
@@ -15,35 +15,33 @@
* General Public License for more details.
*/
-#include <bfa.h>
-#include <bfa_ioc.h>
-#include <bfa_fwimg_priv.h>
-#include <cna/bfa_cna_trcmod.h>
-#include <cs/bfa_debug.h>
-#include <bfi/bfi_ioc.h>
-#include <bfi/bfi_ctreg.h>
-#include <aen/bfa_aen_ioc.h>
-#include <aen/bfa_aen.h>
-#include <log/bfa_log_hal.h>
-#include <defs/bfa_defs_pci.h>
+#include "bfa_ioc.h"
+#include "bfi_ctreg.h"
+#include "bfa_defs.h"
+#include "bfa_defs_svc.h"
+#include "bfad_drv.h"
BFA_TRC_FILE(CNA, IOC);
/**
* IOC local definitions
*/
-#define BFA_IOC_TOV 2000 /* msecs */
-#define BFA_IOC_HWSEM_TOV 500 /* msecs */
-#define BFA_IOC_HB_TOV 500 /* msecs */
-#define BFA_IOC_HWINIT_MAX 2
-#define BFA_IOC_FWIMG_MINSZ (16 * 1024)
-#define BFA_IOC_TOV_RECOVER BFA_IOC_HB_TOV
+#define BFA_IOC_TOV 3000 /* msecs */
+#define BFA_IOC_HWSEM_TOV 500 /* msecs */
+#define BFA_IOC_HB_TOV 500 /* msecs */
+#define BFA_IOC_HWINIT_MAX 2
+#define BFA_IOC_TOV_RECOVER BFA_IOC_HB_TOV
#define bfa_ioc_timer_start(__ioc) \
bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->ioc_timer, \
bfa_ioc_timeout, (__ioc), BFA_IOC_TOV)
#define bfa_ioc_timer_stop(__ioc) bfa_timer_stop(&(__ioc)->ioc_timer)
+#define bfa_hb_timer_start(__ioc) \
+ bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->hb_timer, \
+ bfa_ioc_hb_check, (__ioc), BFA_IOC_HB_TOV)
+#define bfa_hb_timer_stop(__ioc) bfa_timer_stop(&(__ioc)->hb_timer)
+
#define BFA_DBG_FWTRC_ENTS (BFI_IOC_TRC_ENTS)
#define BFA_DBG_FWTRC_LEN \
(BFA_DBG_FWTRC_ENTS * sizeof(struct bfa_trc_s) + \
@@ -55,100 +53,226 @@ BFA_TRC_FILE(CNA, IOC);
* Asic specific macros : see bfa_hw_cb.c and bfa_hw_ct.c for details.
*/
-#define bfa_ioc_firmware_lock(__ioc) \
+#define bfa_ioc_firmware_lock(__ioc) \
((__ioc)->ioc_hwif->ioc_firmware_lock(__ioc))
-#define bfa_ioc_firmware_unlock(__ioc) \
+#define bfa_ioc_firmware_unlock(__ioc) \
((__ioc)->ioc_hwif->ioc_firmware_unlock(__ioc))
#define bfa_ioc_reg_init(__ioc) ((__ioc)->ioc_hwif->ioc_reg_init(__ioc))
#define bfa_ioc_map_port(__ioc) ((__ioc)->ioc_hwif->ioc_map_port(__ioc))
-#define bfa_ioc_notify_hbfail(__ioc) \
+#define bfa_ioc_notify_hbfail(__ioc) \
((__ioc)->ioc_hwif->ioc_notify_hbfail(__ioc))
-#define bfa_ioc_is_optrom(__ioc) \
- (bfi_image_get_size(BFA_IOC_FWIMG_TYPE(__ioc)) < BFA_IOC_FWIMG_MINSZ)
-bfa_boolean_t bfa_auto_recover = BFA_TRUE;
+#ifdef BFA_IOC_IS_UEFI
+#define bfa_ioc_is_bios_optrom(__ioc) (0)
+#define bfa_ioc_is_uefi(__ioc) BFA_IOC_IS_UEFI
+#else
+#define bfa_ioc_is_bios_optrom(__ioc) \
+ (bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(__ioc)) < BFA_IOC_FWIMG_MINSZ)
+#define bfa_ioc_is_uefi(__ioc) (0)
+#endif
+
+#define bfa_ioc_mbox_cmd_pending(__ioc) \
+ (!list_empty(&((__ioc)->mbox_mod.cmd_q)) || \
+ bfa_reg_read((__ioc)->ioc_regs.hfn_mbox_cmd))
+
+bfa_boolean_t bfa_auto_recover = BFA_TRUE;
/*
* forward declarations
*/
-static void bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc);
-static void bfa_ioc_hw_sem_get_cancel(struct bfa_ioc_s *ioc);
-static void bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force);
-static void bfa_ioc_timeout(void *ioc);
-static void bfa_ioc_send_enable(struct bfa_ioc_s *ioc);
-static void bfa_ioc_send_disable(struct bfa_ioc_s *ioc);
-static void bfa_ioc_send_getattr(struct bfa_ioc_s *ioc);
-static void bfa_ioc_hb_monitor(struct bfa_ioc_s *ioc);
-static void bfa_ioc_hb_stop(struct bfa_ioc_s *ioc);
-static void bfa_ioc_reset(struct bfa_ioc_s *ioc, bfa_boolean_t force);
-static void bfa_ioc_mbox_poll(struct bfa_ioc_s *ioc);
-static void bfa_ioc_mbox_hbfail(struct bfa_ioc_s *ioc);
-static void bfa_ioc_recover(struct bfa_ioc_s *ioc);
-static void bfa_ioc_check_attr_wwns(struct bfa_ioc_s *ioc);
-static void bfa_ioc_disable_comp(struct bfa_ioc_s *ioc);
-static void bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc);
+static void bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc);
+static void bfa_ioc_hw_sem_get_cancel(struct bfa_ioc_s *ioc);
+static void bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force);
+static void bfa_ioc_timeout(void *ioc);
+static void bfa_ioc_send_enable(struct bfa_ioc_s *ioc);
+static void bfa_ioc_send_disable(struct bfa_ioc_s *ioc);
+static void bfa_ioc_send_getattr(struct bfa_ioc_s *ioc);
+static void bfa_ioc_hb_monitor(struct bfa_ioc_s *ioc);
+static void bfa_ioc_hb_stop(struct bfa_ioc_s *ioc);
+static void bfa_ioc_reset(struct bfa_ioc_s *ioc, bfa_boolean_t force);
+static void bfa_ioc_mbox_poll(struct bfa_ioc_s *ioc);
+static void bfa_ioc_mbox_hbfail(struct bfa_ioc_s *ioc);
+static void bfa_ioc_recover(struct bfa_ioc_s *ioc);
+static void bfa_ioc_check_attr_wwns(struct bfa_ioc_s *ioc);
+static void bfa_ioc_disable_comp(struct bfa_ioc_s *ioc);
+static void bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc);
+static void bfa_ioc_pf_enabled(struct bfa_ioc_s *ioc);
+static void bfa_ioc_pf_disabled(struct bfa_ioc_s *ioc);
+static void bfa_ioc_pf_failed(struct bfa_ioc_s *ioc);
+static void bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc);
/**
- * bfa_ioc_sm
+ * hal_ioc_sm
*/
/**
- * IOC state machine events
+ * IOC state machine definitions/declarations
*/
enum ioc_event {
- IOC_E_ENABLE = 1, /* IOC enable request */
- IOC_E_DISABLE = 2, /* IOC disable request */
- IOC_E_TIMEOUT = 3, /* f/w response timeout */
- IOC_E_FWREADY = 4, /* f/w initialization done */
- IOC_E_FWRSP_GETATTR = 5, /* IOC get attribute response */
- IOC_E_FWRSP_ENABLE = 6, /* enable f/w response */
- IOC_E_FWRSP_DISABLE = 7, /* disable f/w response */
- IOC_E_HBFAIL = 8, /* heartbeat failure */
- IOC_E_HWERROR = 9, /* hardware error interrupt */
- IOC_E_SEMLOCKED = 10, /* h/w semaphore is locked */
- IOC_E_DETACH = 11, /* driver detach cleanup */
+ IOC_E_RESET = 1, /* IOC reset request */
+ IOC_E_ENABLE = 2, /* IOC enable request */
+ IOC_E_DISABLE = 3, /* IOC disable request */
+ IOC_E_DETACH = 4, /* driver detach cleanup */
+ IOC_E_ENABLED = 5, /* f/w enabled */
+ IOC_E_FWRSP_GETATTR = 6, /* IOC get attribute response */
+ IOC_E_DISABLED = 7, /* f/w disabled */
+ IOC_E_FAILED = 8, /* failure notice by iocpf sm */
+ IOC_E_HBFAIL = 9, /* heartbeat failure */
+ IOC_E_HWERROR = 10, /* hardware error interrupt */
+ IOC_E_TIMEOUT = 11, /* timeout */
};
+bfa_fsm_state_decl(bfa_ioc, uninit, struct bfa_ioc_s, enum ioc_event);
bfa_fsm_state_decl(bfa_ioc, reset, struct bfa_ioc_s, enum ioc_event);
-bfa_fsm_state_decl(bfa_ioc, fwcheck, struct bfa_ioc_s, enum ioc_event);
-bfa_fsm_state_decl(bfa_ioc, mismatch, struct bfa_ioc_s, enum ioc_event);
-bfa_fsm_state_decl(bfa_ioc, semwait, struct bfa_ioc_s, enum ioc_event);
-bfa_fsm_state_decl(bfa_ioc, hwinit, struct bfa_ioc_s, enum ioc_event);
bfa_fsm_state_decl(bfa_ioc, enabling, struct bfa_ioc_s, enum ioc_event);
bfa_fsm_state_decl(bfa_ioc, getattr, struct bfa_ioc_s, enum ioc_event);
bfa_fsm_state_decl(bfa_ioc, op, struct bfa_ioc_s, enum ioc_event);
bfa_fsm_state_decl(bfa_ioc, initfail, struct bfa_ioc_s, enum ioc_event);
-bfa_fsm_state_decl(bfa_ioc, hbfail, struct bfa_ioc_s, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, fail, struct bfa_ioc_s, enum ioc_event);
bfa_fsm_state_decl(bfa_ioc, disabling, struct bfa_ioc_s, enum ioc_event);
bfa_fsm_state_decl(bfa_ioc, disabled, struct bfa_ioc_s, enum ioc_event);
static struct bfa_sm_table_s ioc_sm_table[] = {
+ {BFA_SM(bfa_ioc_sm_uninit), BFA_IOC_UNINIT},
{BFA_SM(bfa_ioc_sm_reset), BFA_IOC_RESET},
- {BFA_SM(bfa_ioc_sm_fwcheck), BFA_IOC_FWMISMATCH},
- {BFA_SM(bfa_ioc_sm_mismatch), BFA_IOC_FWMISMATCH},
- {BFA_SM(bfa_ioc_sm_semwait), BFA_IOC_SEMWAIT},
- {BFA_SM(bfa_ioc_sm_hwinit), BFA_IOC_HWINIT},
- {BFA_SM(bfa_ioc_sm_enabling), BFA_IOC_HWINIT},
+ {BFA_SM(bfa_ioc_sm_enabling), BFA_IOC_ENABLING},
{BFA_SM(bfa_ioc_sm_getattr), BFA_IOC_GETATTR},
{BFA_SM(bfa_ioc_sm_op), BFA_IOC_OPERATIONAL},
{BFA_SM(bfa_ioc_sm_initfail), BFA_IOC_INITFAIL},
- {BFA_SM(bfa_ioc_sm_hbfail), BFA_IOC_HBFAIL},
+ {BFA_SM(bfa_ioc_sm_fail), BFA_IOC_FAIL},
{BFA_SM(bfa_ioc_sm_disabling), BFA_IOC_DISABLING},
{BFA_SM(bfa_ioc_sm_disabled), BFA_IOC_DISABLED},
};
/**
+ * IOCPF state machine definitions/declarations
+ */
+
+#define bfa_iocpf_timer_start(__ioc) \
+ bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->ioc_timer, \
+ bfa_iocpf_timeout, (__ioc), BFA_IOC_TOV)
+#define bfa_iocpf_timer_stop(__ioc) bfa_timer_stop(&(__ioc)->ioc_timer)
+
+#define bfa_iocpf_recovery_timer_start(__ioc) \
+ bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->ioc_timer, \
+ bfa_iocpf_timeout, (__ioc), BFA_IOC_TOV_RECOVER)
+
+#define bfa_sem_timer_start(__ioc) \
+ bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->sem_timer, \
+ bfa_iocpf_sem_timeout, (__ioc), BFA_IOC_HWSEM_TOV)
+#define bfa_sem_timer_stop(__ioc) bfa_timer_stop(&(__ioc)->sem_timer)
+
+/*
+ * Forward declareations for iocpf state machine
+ */
+static void bfa_iocpf_enable(struct bfa_ioc_s *ioc);
+static void bfa_iocpf_disable(struct bfa_ioc_s *ioc);
+static void bfa_iocpf_fail(struct bfa_ioc_s *ioc);
+static void bfa_iocpf_initfail(struct bfa_ioc_s *ioc);
+static void bfa_iocpf_getattrfail(struct bfa_ioc_s *ioc);
+static void bfa_iocpf_stop(struct bfa_ioc_s *ioc);
+static void bfa_iocpf_timeout(void *ioc_arg);
+static void bfa_iocpf_sem_timeout(void *ioc_arg);
+
+/**
+ * IOCPF state machine events
+ */
+enum iocpf_event {
+ IOCPF_E_ENABLE = 1, /* IOCPF enable request */
+ IOCPF_E_DISABLE = 2, /* IOCPF disable request */
+ IOCPF_E_STOP = 3, /* stop on driver detach */
+ IOCPF_E_FWREADY = 4, /* f/w initialization done */
+ IOCPF_E_FWRSP_ENABLE = 5, /* enable f/w response */
+ IOCPF_E_FWRSP_DISABLE = 6, /* disable f/w response */
+ IOCPF_E_FAIL = 7, /* failure notice by ioc sm */
+ IOCPF_E_INITFAIL = 8, /* init fail notice by ioc sm */
+ IOCPF_E_GETATTRFAIL = 9, /* init fail notice by ioc sm */
+ IOCPF_E_SEMLOCKED = 10, /* h/w semaphore is locked */
+ IOCPF_E_TIMEOUT = 11, /* f/w response timeout */
+};
+
+/**
+ * IOCPF states
+ */
+enum bfa_iocpf_state {
+ BFA_IOCPF_RESET = 1, /* IOC is in reset state */
+ BFA_IOCPF_SEMWAIT = 2, /* Waiting for IOC h/w semaphore */
+ BFA_IOCPF_HWINIT = 3, /* IOC h/w is being initialized */
+ BFA_IOCPF_READY = 4, /* IOCPF is initialized */
+ BFA_IOCPF_INITFAIL = 5, /* IOCPF failed */
+ BFA_IOCPF_FAIL = 6, /* IOCPF failed */
+ BFA_IOCPF_DISABLING = 7, /* IOCPF is being disabled */
+ BFA_IOCPF_DISABLED = 8, /* IOCPF is disabled */
+ BFA_IOCPF_FWMISMATCH = 9, /* IOC f/w different from drivers */
+};
+
+bfa_fsm_state_decl(bfa_iocpf, reset, struct bfa_iocpf_s, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, fwcheck, struct bfa_iocpf_s, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, mismatch, struct bfa_iocpf_s, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, semwait, struct bfa_iocpf_s, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, hwinit, struct bfa_iocpf_s, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, enabling, struct bfa_iocpf_s, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, ready, struct bfa_iocpf_s, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, initfail, struct bfa_iocpf_s, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, fail, struct bfa_iocpf_s, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, disabling, struct bfa_iocpf_s, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, disabled, struct bfa_iocpf_s, enum iocpf_event);
+
+static struct bfa_sm_table_s iocpf_sm_table[] = {
+ {BFA_SM(bfa_iocpf_sm_reset), BFA_IOCPF_RESET},
+ {BFA_SM(bfa_iocpf_sm_fwcheck), BFA_IOCPF_FWMISMATCH},
+ {BFA_SM(bfa_iocpf_sm_mismatch), BFA_IOCPF_FWMISMATCH},
+ {BFA_SM(bfa_iocpf_sm_semwait), BFA_IOCPF_SEMWAIT},
+ {BFA_SM(bfa_iocpf_sm_hwinit), BFA_IOCPF_HWINIT},
+ {BFA_SM(bfa_iocpf_sm_enabling), BFA_IOCPF_HWINIT},
+ {BFA_SM(bfa_iocpf_sm_ready), BFA_IOCPF_READY},
+ {BFA_SM(bfa_iocpf_sm_initfail), BFA_IOCPF_INITFAIL},
+ {BFA_SM(bfa_iocpf_sm_fail), BFA_IOCPF_FAIL},
+ {BFA_SM(bfa_iocpf_sm_disabling), BFA_IOCPF_DISABLING},
+ {BFA_SM(bfa_iocpf_sm_disabled), BFA_IOCPF_DISABLED},
+};
+
+/**
+ * IOC State Machine
+ */
+
+/**
+ * Beginning state. IOC uninit state.
+ */
+
+static void
+bfa_ioc_sm_uninit_entry(struct bfa_ioc_s *ioc)
+{
+}
+
+/**
+ * IOC is in uninit state.
+ */
+static void
+bfa_ioc_sm_uninit(struct bfa_ioc_s *ioc, enum ioc_event event)
+{
+ bfa_trc(ioc, event);
+
+ switch (event) {
+ case IOC_E_RESET:
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
+ break;
+
+ default:
+ bfa_sm_fault(ioc, event);
+ }
+}
+/**
* Reset entry actions -- initialize state machine
*/
static void
bfa_ioc_sm_reset_entry(struct bfa_ioc_s *ioc)
{
- ioc->retry_count = 0;
- ioc->auto_recover = bfa_auto_recover;
+ bfa_fsm_set_state(&ioc->iocpf, bfa_iocpf_sm_reset);
}
/**
- * Beginning state. IOC is in reset state.
+ * IOC is in reset state.
*/
static void
bfa_ioc_sm_reset(struct bfa_ioc_s *ioc, enum ioc_event event)
@@ -157,7 +281,7 @@ bfa_ioc_sm_reset(struct bfa_ioc_s *ioc, enum ioc_event event)
switch (event) {
case IOC_E_ENABLE:
- bfa_fsm_set_state(ioc, bfa_ioc_sm_fwcheck);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_enabling);
break;
case IOC_E_DISABLE:
@@ -165,6 +289,7 @@ bfa_ioc_sm_reset(struct bfa_ioc_s *ioc, enum ioc_event event)
break;
case IOC_E_DETACH:
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
break;
default:
@@ -172,46 +297,209 @@ bfa_ioc_sm_reset(struct bfa_ioc_s *ioc, enum ioc_event event)
}
}
+
+static void
+bfa_ioc_sm_enabling_entry(struct bfa_ioc_s *ioc)
+{
+ bfa_iocpf_enable(ioc);
+}
+
/**
- * Semaphore should be acquired for version check.
+ * Host IOC function is being enabled, awaiting response from firmware.
+ * Semaphore is acquired.
*/
static void
-bfa_ioc_sm_fwcheck_entry(struct bfa_ioc_s *ioc)
+bfa_ioc_sm_enabling(struct bfa_ioc_s *ioc, enum ioc_event event)
{
- bfa_ioc_hw_sem_get(ioc);
+ bfa_trc(ioc, event);
+
+ switch (event) {
+ case IOC_E_ENABLED:
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
+ break;
+
+ case IOC_E_FAILED:
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
+ break;
+
+ case IOC_E_HWERROR:
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
+ bfa_iocpf_initfail(ioc);
+ break;
+
+ case IOC_E_DISABLE:
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
+ break;
+
+ case IOC_E_DETACH:
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
+ bfa_iocpf_stop(ioc);
+ break;
+
+ case IOC_E_ENABLE:
+ break;
+
+ default:
+ bfa_sm_fault(ioc, event);
+ }
+}
+
+
+static void
+bfa_ioc_sm_getattr_entry(struct bfa_ioc_s *ioc)
+{
+ bfa_ioc_timer_start(ioc);
+ bfa_ioc_send_getattr(ioc);
}
/**
- * Awaiting h/w semaphore to continue with version check.
+ * IOC configuration in progress. Timer is active.
*/
static void
-bfa_ioc_sm_fwcheck(struct bfa_ioc_s *ioc, enum ioc_event event)
+bfa_ioc_sm_getattr(struct bfa_ioc_s *ioc, enum ioc_event event)
{
bfa_trc(ioc, event);
switch (event) {
- case IOC_E_SEMLOCKED:
- if (bfa_ioc_firmware_lock(ioc)) {
- ioc->retry_count = 0;
- bfa_fsm_set_state(ioc, bfa_ioc_sm_hwinit);
- } else {
- bfa_ioc_hw_sem_release(ioc);
- bfa_fsm_set_state(ioc, bfa_ioc_sm_mismatch);
- }
+ case IOC_E_FWRSP_GETATTR:
+ bfa_ioc_timer_stop(ioc);
+ bfa_ioc_check_attr_wwns(ioc);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_op);
+ break;
+
+ case IOC_E_FAILED:
+ bfa_ioc_timer_stop(ioc);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
+ break;
+
+ case IOC_E_HWERROR:
+ bfa_ioc_timer_stop(ioc);
+ /* fall through */
+
+ case IOC_E_TIMEOUT:
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
+ bfa_iocpf_getattrfail(ioc);
break;
case IOC_E_DISABLE:
- bfa_ioc_disable_comp(ioc);
+ bfa_ioc_timer_stop(ioc);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
+ break;
+
+ case IOC_E_ENABLE:
+ break;
+
+ default:
+ bfa_sm_fault(ioc, event);
+ }
+}
+
+
+static void
+bfa_ioc_sm_op_entry(struct bfa_ioc_s *ioc)
+{
+ struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
+
+ ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_OK);
+ bfa_ioc_hb_monitor(ioc);
+ BFA_LOG(KERN_INFO, bfad, log_level, "IOC enabled\n");
+}
+
+static void
+bfa_ioc_sm_op(struct bfa_ioc_s *ioc, enum ioc_event event)
+{
+ bfa_trc(ioc, event);
+
+ switch (event) {
+ case IOC_E_ENABLE:
+ break;
+
+ case IOC_E_DISABLE:
+ bfa_ioc_hb_stop(ioc);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
+ break;
+
+ case IOC_E_FAILED:
+ bfa_ioc_hb_stop(ioc);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
+ break;
+
+ case IOC_E_HWERROR:
+ bfa_ioc_hb_stop(ioc);
+ /* !!! fall through !!! */
+
+ case IOC_E_HBFAIL:
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
+ bfa_iocpf_fail(ioc);
+ break;
+
+ default:
+ bfa_sm_fault(ioc, event);
+ }
+}
+
+
+static void
+bfa_ioc_sm_disabling_entry(struct bfa_ioc_s *ioc)
+{
+ struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
+ bfa_iocpf_disable(ioc);
+ BFA_LOG(KERN_INFO, bfad, log_level, "IOC disabled\n");
+}
+
+/**
+ * IOC is being disabled
+ */
+static void
+bfa_ioc_sm_disabling(struct bfa_ioc_s *ioc, enum ioc_event event)
+{
+ bfa_trc(ioc, event);
+
+ switch (event) {
+ case IOC_E_DISABLED:
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+ break;
+
+ case IOC_E_HWERROR:
/*
- * fall through
+ * No state change. Will move to disabled state
+ * after iocpf sm completes failure processing and
+ * moves to disabled state.
*/
+ bfa_iocpf_fail(ioc);
+ break;
- case IOC_E_DETACH:
- bfa_ioc_hw_sem_get_cancel(ioc);
- bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
+ default:
+ bfa_sm_fault(ioc, event);
+ }
+}
+
+/**
+ * IOC disable completion entry.
+ */
+static void
+bfa_ioc_sm_disabled_entry(struct bfa_ioc_s *ioc)
+{
+ bfa_ioc_disable_comp(ioc);
+}
+
+static void
+bfa_ioc_sm_disabled(struct bfa_ioc_s *ioc, enum ioc_event event)
+{
+ bfa_trc(ioc, event);
+
+ switch (event) {
+ case IOC_E_ENABLE:
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_enabling);
+ break;
+
+ case IOC_E_DISABLE:
+ ioc->cbfn->disable_cbfn(ioc->bfa);
break;
- case IOC_E_FWREADY:
+ case IOC_E_DETACH:
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
+ bfa_iocpf_stop(ioc);
break;
default:
@@ -219,48 +507,138 @@ bfa_ioc_sm_fwcheck(struct bfa_ioc_s *ioc, enum ioc_event event)
}
}
+
+static void
+bfa_ioc_sm_initfail_entry(struct bfa_ioc_s *ioc)
+{
+ ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+}
+
/**
- * Notify enable completion callback and generate mismatch AEN.
+ * Hardware initialization failed.
*/
static void
-bfa_ioc_sm_mismatch_entry(struct bfa_ioc_s *ioc)
+bfa_ioc_sm_initfail(struct bfa_ioc_s *ioc, enum ioc_event event)
+{
+ bfa_trc(ioc, event);
+
+ switch (event) {
+ case IOC_E_ENABLED:
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
+ break;
+
+ case IOC_E_FAILED:
+ /**
+ * Initialization failure during iocpf init retry.
+ */
+ ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+ break;
+
+ case IOC_E_DISABLE:
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
+ break;
+
+ case IOC_E_DETACH:
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
+ bfa_iocpf_stop(ioc);
+ break;
+
+ default:
+ bfa_sm_fault(ioc, event);
+ }
+}
+
+
+static void
+bfa_ioc_sm_fail_entry(struct bfa_ioc_s *ioc)
{
+ struct list_head *qe;
+ struct bfa_ioc_hbfail_notify_s *notify;
+ struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
+
/**
- * Provide enable completion callback and AEN notification only once.
+ * Notify driver and common modules registered for notification.
*/
- if (ioc->retry_count == 0) {
- ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
- bfa_ioc_aen_post(ioc, BFA_IOC_AEN_FWMISMATCH);
+ ioc->cbfn->hbfail_cbfn(ioc->bfa);
+ list_for_each(qe, &ioc->hb_notify_q) {
+ notify = (struct bfa_ioc_hbfail_notify_s *) qe;
+ notify->cbfn(notify->cbarg);
}
- ioc->retry_count++;
- bfa_ioc_timer_start(ioc);
+
+ BFA_LOG(KERN_CRIT, bfad, log_level,
+ "Heart Beat of IOC has failed\n");
}
/**
- * Awaiting firmware version match.
+ * IOC failure.
*/
static void
-bfa_ioc_sm_mismatch(struct bfa_ioc_s *ioc, enum ioc_event event)
+bfa_ioc_sm_fail(struct bfa_ioc_s *ioc, enum ioc_event event)
{
bfa_trc(ioc, event);
switch (event) {
- case IOC_E_TIMEOUT:
- bfa_fsm_set_state(ioc, bfa_ioc_sm_fwcheck);
+
+ case IOC_E_FAILED:
+ /**
+ * Initialization failure during iocpf recovery.
+ * !!! Fall through !!!
+ */
+ case IOC_E_ENABLE:
+ ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+ break;
+
+ case IOC_E_ENABLED:
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
break;
case IOC_E_DISABLE:
- bfa_ioc_disable_comp(ioc);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
+ break;
+
+ case IOC_E_HWERROR:
/*
- * fall through
+ * HB failure notification, ignore.
*/
+ break;
+ default:
+ bfa_sm_fault(ioc, event);
+ }
+}
- case IOC_E_DETACH:
- bfa_ioc_timer_stop(ioc);
- bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
+
+
+/**
+ * IOCPF State Machine
+ */
+
+
+/**
+ * Reset entry actions -- initialize state machine
+ */
+static void
+bfa_iocpf_sm_reset_entry(struct bfa_iocpf_s *iocpf)
+{
+ iocpf->retry_count = 0;
+ iocpf->auto_recover = bfa_auto_recover;
+}
+
+/**
+ * Beginning state. IOC is in reset state.
+ */
+static void
+bfa_iocpf_sm_reset(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
+{
+ struct bfa_ioc_s *ioc = iocpf->ioc;
+
+ bfa_trc(ioc, event);
+
+ switch (event) {
+ case IOCPF_E_ENABLE:
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fwcheck);
break;
- case IOC_E_FWREADY:
+ case IOCPF_E_STOP:
break;
default:
@@ -269,31 +647,44 @@ bfa_ioc_sm_mismatch(struct bfa_ioc_s *ioc, enum ioc_event event)
}
/**
- * Request for semaphore.
+ * Semaphore should be acquired for version check.
*/
static void
-bfa_ioc_sm_semwait_entry(struct bfa_ioc_s *ioc)
+bfa_iocpf_sm_fwcheck_entry(struct bfa_iocpf_s *iocpf)
{
- bfa_ioc_hw_sem_get(ioc);
+ bfa_ioc_hw_sem_get(iocpf->ioc);
}
/**
- * Awaiting semaphore for h/w initialzation.
+ * Awaiting h/w semaphore to continue with version check.
*/
static void
-bfa_ioc_sm_semwait(struct bfa_ioc_s *ioc, enum ioc_event event)
+bfa_iocpf_sm_fwcheck(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
{
+ struct bfa_ioc_s *ioc = iocpf->ioc;
+
bfa_trc(ioc, event);
switch (event) {
- case IOC_E_SEMLOCKED:
- ioc->retry_count = 0;
- bfa_fsm_set_state(ioc, bfa_ioc_sm_hwinit);
+ case IOCPF_E_SEMLOCKED:
+ if (bfa_ioc_firmware_lock(ioc)) {
+ iocpf->retry_count = 0;
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
+ } else {
+ bfa_ioc_hw_sem_release(ioc);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_mismatch);
+ }
break;
- case IOC_E_DISABLE:
+ case IOCPF_E_DISABLE:
bfa_ioc_hw_sem_get_cancel(ioc);
- bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
+ bfa_ioc_pf_disabled(ioc);
+ break;
+
+ case IOCPF_E_STOP:
+ bfa_ioc_hw_sem_get_cancel(ioc);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
break;
default:
@@ -301,51 +692,81 @@ bfa_ioc_sm_semwait(struct bfa_ioc_s *ioc, enum ioc_event event)
}
}
-
+/**
+ * Notify enable completion callback.
+ */
static void
-bfa_ioc_sm_hwinit_entry(struct bfa_ioc_s *ioc)
+bfa_iocpf_sm_mismatch_entry(struct bfa_iocpf_s *iocpf)
{
- bfa_ioc_timer_start(ioc);
- bfa_ioc_reset(ioc, BFA_FALSE);
+ /*
+ * Call only the first time sm enters fwmismatch state.
+ */
+ if (iocpf->retry_count == 0)
+ bfa_ioc_pf_fwmismatch(iocpf->ioc);
+
+ iocpf->retry_count++;
+ bfa_iocpf_timer_start(iocpf->ioc);
}
/**
- * Hardware is being initialized. Interrupts are enabled.
- * Holding hardware semaphore lock.
+ * Awaiting firmware version match.
*/
static void
-bfa_ioc_sm_hwinit(struct bfa_ioc_s *ioc, enum ioc_event event)
+bfa_iocpf_sm_mismatch(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
{
+ struct bfa_ioc_s *ioc = iocpf->ioc;
+
bfa_trc(ioc, event);
switch (event) {
- case IOC_E_FWREADY:
- bfa_ioc_timer_stop(ioc);
- bfa_fsm_set_state(ioc, bfa_ioc_sm_enabling);
+ case IOCPF_E_TIMEOUT:
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fwcheck);
break;
- case IOC_E_HWERROR:
- bfa_ioc_timer_stop(ioc);
- /*
- * fall through
- */
+ case IOCPF_E_DISABLE:
+ bfa_iocpf_timer_stop(ioc);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
+ bfa_ioc_pf_disabled(ioc);
+ break;
- case IOC_E_TIMEOUT:
- ioc->retry_count++;
- if (ioc->retry_count < BFA_IOC_HWINIT_MAX) {
- bfa_ioc_timer_start(ioc);
- bfa_ioc_reset(ioc, BFA_TRUE);
- break;
- }
+ case IOCPF_E_STOP:
+ bfa_iocpf_timer_stop(ioc);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
+ break;
- bfa_ioc_hw_sem_release(ioc);
- bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
+ default:
+ bfa_sm_fault(ioc, event);
+ }
+}
+
+/**
+ * Request for semaphore.
+ */
+static void
+bfa_iocpf_sm_semwait_entry(struct bfa_iocpf_s *iocpf)
+{
+ bfa_ioc_hw_sem_get(iocpf->ioc);
+}
+
+/**
+ * Awaiting semaphore for h/w initialzation.
+ */
+static void
+bfa_iocpf_sm_semwait(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
+{
+ struct bfa_ioc_s *ioc = iocpf->ioc;
+
+ bfa_trc(ioc, event);
+
+ switch (event) {
+ case IOCPF_E_SEMLOCKED:
+ iocpf->retry_count = 0;
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
break;
- case IOC_E_DISABLE:
- bfa_ioc_hw_sem_release(ioc);
- bfa_ioc_timer_stop(ioc);
- bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+ case IOCPF_E_DISABLE:
+ bfa_ioc_hw_sem_get_cancel(ioc);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
break;
default:
@@ -355,55 +776,54 @@ bfa_ioc_sm_hwinit(struct bfa_ioc_s *ioc, enum ioc_event event)
static void
-bfa_ioc_sm_enabling_entry(struct bfa_ioc_s *ioc)
+bfa_iocpf_sm_hwinit_entry(struct bfa_iocpf_s *iocpf)
{
- bfa_ioc_timer_start(ioc);
- bfa_ioc_send_enable(ioc);
+ bfa_iocpf_timer_start(iocpf->ioc);
+ bfa_ioc_reset(iocpf->ioc, BFA_FALSE);
}
/**
- * Host IOC function is being enabled, awaiting response from firmware.
- * Semaphore is acquired.
+ * Hardware is being initialized. Interrupts are enabled.
+ * Holding hardware semaphore lock.
*/
static void
-bfa_ioc_sm_enabling(struct bfa_ioc_s *ioc, enum ioc_event event)
+bfa_iocpf_sm_hwinit(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
{
+ struct bfa_ioc_s *ioc = iocpf->ioc;
+
bfa_trc(ioc, event);
switch (event) {
- case IOC_E_FWRSP_ENABLE:
- bfa_ioc_timer_stop(ioc);
- bfa_ioc_hw_sem_release(ioc);
- bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
+ case IOCPF_E_FWREADY:
+ bfa_iocpf_timer_stop(ioc);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_enabling);
break;
- case IOC_E_HWERROR:
- bfa_ioc_timer_stop(ioc);
+ case IOCPF_E_INITFAIL:
+ bfa_iocpf_timer_stop(ioc);
/*
- * fall through
+ * !!! fall through !!!
*/
- case IOC_E_TIMEOUT:
- ioc->retry_count++;
- if (ioc->retry_count < BFA_IOC_HWINIT_MAX) {
- bfa_reg_write(ioc->ioc_regs.ioc_fwstate,
- BFI_IOC_UNINIT);
- bfa_fsm_set_state(ioc, bfa_ioc_sm_hwinit);
+ case IOCPF_E_TIMEOUT:
+ iocpf->retry_count++;
+ if (iocpf->retry_count < BFA_IOC_HWINIT_MAX) {
+ bfa_iocpf_timer_start(ioc);
+ bfa_ioc_reset(ioc, BFA_TRUE);
break;
}
bfa_ioc_hw_sem_release(ioc);
- bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
- break;
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
- case IOC_E_DISABLE:
- bfa_ioc_timer_stop(ioc);
- bfa_ioc_hw_sem_release(ioc);
- bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+ if (event == IOCPF_E_TIMEOUT)
+ bfa_ioc_pf_failed(ioc);
break;
- case IOC_E_FWREADY:
- bfa_ioc_send_enable(ioc);
+ case IOCPF_E_DISABLE:
+ bfa_ioc_hw_sem_release(ioc);
+ bfa_iocpf_timer_stop(ioc);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
break;
default:
@@ -413,40 +833,60 @@ bfa_ioc_sm_enabling(struct bfa_ioc_s *ioc, enum ioc_event event)
static void
-bfa_ioc_sm_getattr_entry(struct bfa_ioc_s *ioc)
+bfa_iocpf_sm_enabling_entry(struct bfa_iocpf_s *iocpf)
{
- bfa_ioc_timer_start(ioc);
- bfa_ioc_send_getattr(ioc);
+ bfa_iocpf_timer_start(iocpf->ioc);
+ bfa_ioc_send_enable(iocpf->ioc);
}
/**
- * IOC configuration in progress. Timer is active.
+ * Host IOC function is being enabled, awaiting response from firmware.
+ * Semaphore is acquired.
*/
static void
-bfa_ioc_sm_getattr(struct bfa_ioc_s *ioc, enum ioc_event event)
+bfa_iocpf_sm_enabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
{
+ struct bfa_ioc_s *ioc = iocpf->ioc;
+
bfa_trc(ioc, event);
switch (event) {
- case IOC_E_FWRSP_GETATTR:
- bfa_ioc_timer_stop(ioc);
- bfa_ioc_check_attr_wwns(ioc);
- bfa_fsm_set_state(ioc, bfa_ioc_sm_op);
+ case IOCPF_E_FWRSP_ENABLE:
+ bfa_iocpf_timer_stop(ioc);
+ bfa_ioc_hw_sem_release(ioc);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_ready);
break;
- case IOC_E_HWERROR:
- bfa_ioc_timer_stop(ioc);
+ case IOCPF_E_INITFAIL:
+ bfa_iocpf_timer_stop(ioc);
/*
- * fall through
+ * !!! fall through !!!
*/
- case IOC_E_TIMEOUT:
- bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
+ case IOCPF_E_TIMEOUT:
+ iocpf->retry_count++;
+ if (iocpf->retry_count < BFA_IOC_HWINIT_MAX) {
+ bfa_reg_write(ioc->ioc_regs.ioc_fwstate,
+ BFI_IOC_UNINIT);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
+ break;
+ }
+
+ bfa_ioc_hw_sem_release(ioc);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
+
+ if (event == IOCPF_E_TIMEOUT)
+ bfa_ioc_pf_failed(ioc);
break;
- case IOC_E_DISABLE:
- bfa_ioc_timer_stop(ioc);
- bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+ case IOCPF_E_DISABLE:
+ bfa_iocpf_timer_stop(ioc);
+ bfa_ioc_hw_sem_release(ioc);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling);
+ break;
+
+ case IOCPF_E_FWREADY:
+ bfa_ioc_send_enable(ioc);
break;
default:
@@ -455,41 +895,40 @@ bfa_ioc_sm_getattr(struct bfa_ioc_s *ioc, enum ioc_event event)
}
+
static void
-bfa_ioc_sm_op_entry(struct bfa_ioc_s *ioc)
+bfa_iocpf_sm_ready_entry(struct bfa_iocpf_s *iocpf)
{
- ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_OK);
- bfa_ioc_hb_monitor(ioc);
- bfa_ioc_aen_post(ioc, BFA_IOC_AEN_ENABLE);
+ bfa_ioc_pf_enabled(iocpf->ioc);
}
static void
-bfa_ioc_sm_op(struct bfa_ioc_s *ioc, enum ioc_event event)
+bfa_iocpf_sm_ready(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
{
+ struct bfa_ioc_s *ioc = iocpf->ioc;
+
bfa_trc(ioc, event);
switch (event) {
- case IOC_E_ENABLE:
+ case IOCPF_E_DISABLE:
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling);
break;
- case IOC_E_DISABLE:
- bfa_ioc_hb_stop(ioc);
- bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
+ case IOCPF_E_GETATTRFAIL:
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
break;
- case IOC_E_HWERROR:
- case IOC_E_FWREADY:
- /**
- * Hard error or IOC recovery by other function.
- * Treat it same as heartbeat failure.
- */
- bfa_ioc_hb_stop(ioc);
- /*
- * !!! fall through !!!
- */
+ case IOCPF_E_FAIL:
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
+ break;
- case IOC_E_HBFAIL:
- bfa_fsm_set_state(ioc, bfa_ioc_sm_hbfail);
+ case IOCPF_E_FWREADY:
+ if (bfa_ioc_is_operational(ioc))
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
+ else
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
+
+ bfa_ioc_pf_failed(ioc);
break;
default:
@@ -499,36 +938,41 @@ bfa_ioc_sm_op(struct bfa_ioc_s *ioc, enum ioc_event event)
static void
-bfa_ioc_sm_disabling_entry(struct bfa_ioc_s *ioc)
+bfa_iocpf_sm_disabling_entry(struct bfa_iocpf_s *iocpf)
{
- bfa_ioc_aen_post(ioc, BFA_IOC_AEN_DISABLE);
- bfa_ioc_timer_start(ioc);
- bfa_ioc_send_disable(ioc);
+ bfa_iocpf_timer_start(iocpf->ioc);
+ bfa_ioc_send_disable(iocpf->ioc);
}
/**
* IOC is being disabled
*/
static void
-bfa_ioc_sm_disabling(struct bfa_ioc_s *ioc, enum ioc_event event)
+bfa_iocpf_sm_disabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
{
+ struct bfa_ioc_s *ioc = iocpf->ioc;
+
bfa_trc(ioc, event);
switch (event) {
- case IOC_E_FWRSP_DISABLE:
- bfa_ioc_timer_stop(ioc);
- bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+ case IOCPF_E_FWRSP_DISABLE:
+ case IOCPF_E_FWREADY:
+ bfa_iocpf_timer_stop(ioc);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
break;
- case IOC_E_HWERROR:
- bfa_ioc_timer_stop(ioc);
+ case IOCPF_E_FAIL:
+ bfa_iocpf_timer_stop(ioc);
/*
* !!! fall through !!!
*/
- case IOC_E_TIMEOUT:
+ case IOCPF_E_TIMEOUT:
bfa_reg_write(ioc->ioc_regs.ioc_fwstate, BFI_IOC_FAIL);
- bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
+ break;
+
+ case IOCPF_E_FWRSP_ENABLE:
break;
default:
@@ -540,31 +984,26 @@ bfa_ioc_sm_disabling(struct bfa_ioc_s *ioc, enum ioc_event event)
* IOC disable completion entry.
*/
static void
-bfa_ioc_sm_disabled_entry(struct bfa_ioc_s *ioc)
+bfa_iocpf_sm_disabled_entry(struct bfa_iocpf_s *iocpf)
{
- bfa_ioc_disable_comp(ioc);
+ bfa_ioc_pf_disabled(iocpf->ioc);
}
static void
-bfa_ioc_sm_disabled(struct bfa_ioc_s *ioc, enum ioc_event event)
+bfa_iocpf_sm_disabled(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
{
+ struct bfa_ioc_s *ioc = iocpf->ioc;
+
bfa_trc(ioc, event);
switch (event) {
- case IOC_E_ENABLE:
- bfa_fsm_set_state(ioc, bfa_ioc_sm_semwait);
+ case IOCPF_E_ENABLE:
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
break;
- case IOC_E_DISABLE:
- ioc->cbfn->disable_cbfn(ioc->bfa);
- break;
-
- case IOC_E_FWREADY:
- break;
-
- case IOC_E_DETACH:
+ case IOCPF_E_STOP:
bfa_ioc_firmware_unlock(ioc);
- bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
break;
default:
@@ -574,34 +1013,35 @@ bfa_ioc_sm_disabled(struct bfa_ioc_s *ioc, enum ioc_event event)
static void
-bfa_ioc_sm_initfail_entry(struct bfa_ioc_s *ioc)
+bfa_iocpf_sm_initfail_entry(struct bfa_iocpf_s *iocpf)
{
- ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
- bfa_ioc_timer_start(ioc);
+ bfa_iocpf_timer_start(iocpf->ioc);
}
/**
* Hardware initialization failed.
*/
static void
-bfa_ioc_sm_initfail(struct bfa_ioc_s *ioc, enum ioc_event event)
+bfa_iocpf_sm_initfail(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
{
+ struct bfa_ioc_s *ioc = iocpf->ioc;
+
bfa_trc(ioc, event);
switch (event) {
- case IOC_E_DISABLE:
- bfa_ioc_timer_stop(ioc);
- bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+ case IOCPF_E_DISABLE:
+ bfa_iocpf_timer_stop(ioc);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
break;
- case IOC_E_DETACH:
- bfa_ioc_timer_stop(ioc);
+ case IOCPF_E_STOP:
+ bfa_iocpf_timer_stop(ioc);
bfa_ioc_firmware_unlock(ioc);
- bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
break;
- case IOC_E_TIMEOUT:
- bfa_fsm_set_state(ioc, bfa_ioc_sm_semwait);
+ case IOCPF_E_TIMEOUT:
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
break;
default:
@@ -611,80 +1051,47 @@ bfa_ioc_sm_initfail(struct bfa_ioc_s *ioc, enum ioc_event event)
static void
-bfa_ioc_sm_hbfail_entry(struct bfa_ioc_s *ioc)
+bfa_iocpf_sm_fail_entry(struct bfa_iocpf_s *iocpf)
{
- struct list_head *qe;
- struct bfa_ioc_hbfail_notify_s *notify;
-
/**
* Mark IOC as failed in hardware and stop firmware.
*/
- bfa_ioc_lpu_stop(ioc);
- bfa_reg_write(ioc->ioc_regs.ioc_fwstate, BFI_IOC_FAIL);
+ bfa_ioc_lpu_stop(iocpf->ioc);
+ bfa_reg_write(iocpf->ioc->ioc_regs.ioc_fwstate, BFI_IOC_FAIL);
/**
* Notify other functions on HB failure.
*/
- bfa_ioc_notify_hbfail(ioc);
-
- /**
- * Notify driver and common modules registered for notification.
- */
- ioc->cbfn->hbfail_cbfn(ioc->bfa);
- list_for_each(qe, &ioc->hb_notify_q) {
- notify = (struct bfa_ioc_hbfail_notify_s *)qe;
- notify->cbfn(notify->cbarg);
- }
+ bfa_ioc_notify_hbfail(iocpf->ioc);
/**
* Flush any queued up mailbox requests.
*/
- bfa_ioc_mbox_hbfail(ioc);
- bfa_ioc_aen_post(ioc, BFA_IOC_AEN_HBFAIL);
+ bfa_ioc_mbox_hbfail(iocpf->ioc);
- /**
- * Trigger auto-recovery after a delay.
- */
- if (ioc->auto_recover) {
- bfa_timer_begin(ioc->timer_mod, &ioc->ioc_timer,
- bfa_ioc_timeout, ioc, BFA_IOC_TOV_RECOVER);
- }
+ if (iocpf->auto_recover)
+ bfa_iocpf_recovery_timer_start(iocpf->ioc);
}
/**
- * IOC heartbeat failure.
+ * IOC is in failed state.
*/
static void
-bfa_ioc_sm_hbfail(struct bfa_ioc_s *ioc, enum ioc_event event)
+bfa_iocpf_sm_fail(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
{
+ struct bfa_ioc_s *ioc = iocpf->ioc;
+
bfa_trc(ioc, event);
switch (event) {
-
- case IOC_E_ENABLE:
- ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
- break;
-
- case IOC_E_DISABLE:
- if (ioc->auto_recover)
- bfa_ioc_timer_stop(ioc);
- bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+ case IOCPF_E_DISABLE:
+ if (iocpf->auto_recover)
+ bfa_iocpf_timer_stop(ioc);
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
break;
- case IOC_E_TIMEOUT:
- bfa_fsm_set_state(ioc, bfa_ioc_sm_semwait);
- break;
-
- case IOC_E_FWREADY:
- /**
- * Recovery is already initiated by other function.
- */
- break;
-
- case IOC_E_HWERROR:
- /*
- * HB failure notification, ignore.
- */
+ case IOCPF_E_TIMEOUT:
+ bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
break;
default:
@@ -695,14 +1102,14 @@ bfa_ioc_sm_hbfail(struct bfa_ioc_s *ioc, enum ioc_event event)
/**
- * bfa_ioc_pvt BFA IOC private functions
+ * hal_ioc_pvt BFA IOC private functions
*/
static void
bfa_ioc_disable_comp(struct bfa_ioc_s *ioc)
{
- struct list_head *qe;
- struct bfa_ioc_hbfail_notify_s *notify;
+ struct list_head *qe;
+ struct bfa_ioc_hbfail_notify_s *notify;
ioc->cbfn->disable_cbfn(ioc->bfa);
@@ -710,25 +1117,17 @@ bfa_ioc_disable_comp(struct bfa_ioc_s *ioc)
* Notify common modules registered for notification.
*/
list_for_each(qe, &ioc->hb_notify_q) {
- notify = (struct bfa_ioc_hbfail_notify_s *)qe;
+ notify = (struct bfa_ioc_hbfail_notify_s *) qe;
notify->cbfn(notify->cbarg);
}
}
-void
-bfa_ioc_sem_timeout(void *ioc_arg)
-{
- struct bfa_ioc_s *ioc = (struct bfa_ioc_s *)ioc_arg;
-
- bfa_ioc_hw_sem_get(ioc);
-}
-
bfa_boolean_t
bfa_ioc_sem_get(bfa_os_addr_t sem_reg)
{
u32 r32;
int cnt = 0;
-#define BFA_SEM_SPINCNT 3000
+#define BFA_SEM_SPINCNT 3000
r32 = bfa_reg_read(sem_reg);
@@ -754,7 +1153,7 @@ bfa_ioc_sem_release(bfa_os_addr_t sem_reg)
static void
bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc)
{
- u32 r32;
+ u32 r32;
/**
* First read to the semaphore register will return 0, subsequent reads
@@ -762,12 +1161,11 @@ bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc)
*/
r32 = bfa_reg_read(ioc->ioc_regs.ioc_sem_reg);
if (r32 == 0) {
- bfa_fsm_send_event(ioc, IOC_E_SEMLOCKED);
+ bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_SEMLOCKED);
return;
}
- bfa_timer_begin(ioc->timer_mod, &ioc->sem_timer, bfa_ioc_sem_timeout,
- ioc, BFA_IOC_HWSEM_TOV);
+ bfa_sem_timer_start(ioc);
}
void
@@ -779,7 +1177,7 @@ bfa_ioc_hw_sem_release(struct bfa_ioc_s *ioc)
static void
bfa_ioc_hw_sem_get_cancel(struct bfa_ioc_s *ioc)
{
- bfa_timer_stop(&ioc->sem_timer);
+ bfa_sem_timer_stop(ioc);
}
/**
@@ -788,14 +1186,18 @@ bfa_ioc_hw_sem_get_cancel(struct bfa_ioc_s *ioc)
static void
bfa_ioc_lmem_init(struct bfa_ioc_s *ioc)
{
- u32 pss_ctl;
- int i;
+ u32 pss_ctl;
+ int i;
#define PSS_LMEM_INIT_TIME 10000
pss_ctl = bfa_reg_read(ioc->ioc_regs.pss_ctl_reg);
pss_ctl &= ~__PSS_LMEM_RESET;
pss_ctl |= __PSS_LMEM_INIT_EN;
- pss_ctl |= __PSS_I2C_CLK_DIV(3UL); /* i2c workaround 12.5khz clock */
+
+ /*
+ * i2c workaround 12.5khz clock
+ */
+ pss_ctl |= __PSS_I2C_CLK_DIV(3UL);
bfa_reg_write(ioc->ioc_regs.pss_ctl_reg, pss_ctl);
/**
@@ -821,7 +1223,7 @@ bfa_ioc_lmem_init(struct bfa_ioc_s *ioc)
static void
bfa_ioc_lpu_start(struct bfa_ioc_s *ioc)
{
- u32 pss_ctl;
+ u32 pss_ctl;
/**
* Take processor out of reset.
@@ -835,7 +1237,7 @@ bfa_ioc_lpu_start(struct bfa_ioc_s *ioc)
static void
bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc)
{
- u32 pss_ctl;
+ u32 pss_ctl;
/**
* Put processors in reset.
@@ -852,10 +1254,10 @@ bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc)
void
bfa_ioc_fwver_get(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr)
{
- u32 pgnum, pgoff;
- u32 loff = 0;
- int i;
- u32 *fwsig = (u32 *) fwhdr;
+ u32 pgnum, pgoff;
+ u32 loff = 0;
+ int i;
+ u32 *fwsig = (u32 *) fwhdr;
pgnum = bfa_ioc_smem_pgnum(ioc, loff);
pgoff = bfa_ioc_smem_pgoff(ioc, loff);
@@ -863,7 +1265,8 @@ bfa_ioc_fwver_get(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr)
for (i = 0; i < (sizeof(struct bfi_ioc_image_hdr_s) / sizeof(u32));
i++) {
- fwsig[i] = bfa_mem_read(ioc->ioc_regs.smem_page_start, loff);
+ fwsig[i] =
+ bfa_mem_read(ioc->ioc_regs.smem_page_start, loff);
loff += sizeof(u32);
}
}
@@ -875,10 +1278,10 @@ bfa_boolean_t
bfa_ioc_fwver_cmp(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr)
{
struct bfi_ioc_image_hdr_s *drv_fwhdr;
- int i;
+ int i;
drv_fwhdr = (struct bfi_ioc_image_hdr_s *)
- bfi_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0);
+ bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0);
for (i = 0; i < BFI_IOC_MD5SUM_SZ; i++) {
if (fwhdr->md5sum[i] != drv_fwhdr->md5sum[i]) {
@@ -897,21 +1300,20 @@ bfa_ioc_fwver_cmp(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr)
* Return true if current running version is valid. Firmware signature and
* execution context (driver/bios) must match.
*/
-static bfa_boolean_t
-bfa_ioc_fwver_valid(struct bfa_ioc_s *ioc)
+static bfa_boolean_t
+bfa_ioc_fwver_valid(struct bfa_ioc_s *ioc, u32 boot_env)
{
struct bfi_ioc_image_hdr_s fwhdr, *drv_fwhdr;
/**
* If bios/efi boot (flash based) -- return true
*/
- if (bfa_ioc_is_optrom(ioc))
+ if (bfa_ioc_is_bios_optrom(ioc))
return BFA_TRUE;
bfa_ioc_fwver_get(ioc, &fwhdr);
drv_fwhdr = (struct bfi_ioc_image_hdr_s *)
- bfi_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0);
-
+ bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0);
if (fwhdr.signature != drv_fwhdr->signature) {
bfa_trc(ioc, fwhdr.signature);
@@ -919,9 +1321,9 @@ bfa_ioc_fwver_valid(struct bfa_ioc_s *ioc)
return BFA_FALSE;
}
- if (fwhdr.exec != drv_fwhdr->exec) {
- bfa_trc(ioc, fwhdr.exec);
- bfa_trc(ioc, drv_fwhdr->exec);
+ if (bfa_os_swap32(fwhdr.param) != boot_env) {
+ bfa_trc(ioc, fwhdr.param);
+ bfa_trc(ioc, boot_env);
return BFA_FALSE;
}
@@ -934,7 +1336,7 @@ bfa_ioc_fwver_valid(struct bfa_ioc_s *ioc)
static void
bfa_ioc_msgflush(struct bfa_ioc_s *ioc)
{
- u32 r32;
+ u32 r32;
r32 = bfa_reg_read(ioc->ioc_regs.lpu_mbox_cmd);
if (r32)
@@ -946,7 +1348,9 @@ static void
bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)
{
enum bfi_ioc_state ioc_fwstate;
- bfa_boolean_t fwvalid;
+ bfa_boolean_t fwvalid;
+ u32 boot_type;
+ u32 boot_env;
ioc_fwstate = bfa_reg_read(ioc->ioc_regs.ioc_fwstate);
@@ -955,14 +1359,33 @@ bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)
bfa_trc(ioc, ioc_fwstate);
+ boot_type = BFI_BOOT_TYPE_NORMAL;
+ boot_env = BFI_BOOT_LOADER_OS;
+
+ /**
+ * Flash based firmware boot BIOS env.
+ */
+ if (bfa_ioc_is_bios_optrom(ioc)) {
+ boot_type = BFI_BOOT_TYPE_FLASH;
+ boot_env = BFI_BOOT_LOADER_BIOS;
+ }
+
+ /**
+ * Flash based firmware boot UEFI env.
+ */
+ if (bfa_ioc_is_uefi(ioc)) {
+ boot_type = BFI_BOOT_TYPE_FLASH;
+ boot_env = BFI_BOOT_LOADER_UEFI;
+ }
+
/**
* check if firmware is valid
*/
fwvalid = (ioc_fwstate == BFI_IOC_UNINIT) ?
- BFA_FALSE : bfa_ioc_fwver_valid(ioc);
+ BFA_FALSE : bfa_ioc_fwver_valid(ioc, boot_env);
if (!fwvalid) {
- bfa_ioc_boot(ioc, BFI_BOOT_TYPE_NORMAL, ioc->pcidev.device_id);
+ bfa_ioc_boot(ioc, boot_type, boot_env);
return;
}
@@ -971,7 +1394,6 @@ bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)
* just wait for an initialization completion interrupt.
*/
if (ioc_fwstate == BFI_IOC_INITING) {
- bfa_trc(ioc, ioc_fwstate);
ioc->cbfn->reset_cbfn(ioc->bfa);
return;
}
@@ -985,8 +1407,7 @@ bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)
* is loaded.
*/
if (ioc_fwstate == BFI_IOC_DISABLED ||
- (!bfa_ioc_is_optrom(ioc) && ioc_fwstate == BFI_IOC_OP)) {
- bfa_trc(ioc, ioc_fwstate);
+ (!bfa_ioc_is_bios_optrom(ioc) && ioc_fwstate == BFI_IOC_OP)) {
/**
* When using MSI-X any pending firmware ready event should
@@ -994,20 +1415,20 @@ bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)
*/
bfa_ioc_msgflush(ioc);
ioc->cbfn->reset_cbfn(ioc->bfa);
- bfa_fsm_send_event(ioc, IOC_E_FWREADY);
+ bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FWREADY);
return;
}
/**
* Initialize the h/w for any other states.
*/
- bfa_ioc_boot(ioc, BFI_BOOT_TYPE_NORMAL, ioc->pcidev.device_id);
+ bfa_ioc_boot(ioc, boot_type, boot_env);
}
static void
bfa_ioc_timeout(void *ioc_arg)
{
- struct bfa_ioc_s *ioc = (struct bfa_ioc_s *)ioc_arg;
+ struct bfa_ioc_s *ioc = (struct bfa_ioc_s *) ioc_arg;
bfa_trc(ioc, 0);
bfa_fsm_send_event(ioc, IOC_E_TIMEOUT);
@@ -1016,8 +1437,8 @@ bfa_ioc_timeout(void *ioc_arg)
void
bfa_ioc_mbox_send(struct bfa_ioc_s *ioc, void *ioc_msg, int len)
{
- u32 *msgp = (u32 *) ioc_msg;
- u32 i;
+ u32 *msgp = (u32 *) ioc_msg;
+ u32 i;
bfa_trc(ioc, msgp[0]);
bfa_trc(ioc, len);
@@ -1038,17 +1459,20 @@ bfa_ioc_mbox_send(struct bfa_ioc_s *ioc, void *ioc_msg, int len)
* write 1 to mailbox CMD to trigger LPU event
*/
bfa_reg_write(ioc->ioc_regs.hfn_mbox_cmd, 1);
- (void)bfa_reg_read(ioc->ioc_regs.hfn_mbox_cmd);
+ (void) bfa_reg_read(ioc->ioc_regs.hfn_mbox_cmd);
}
static void
bfa_ioc_send_enable(struct bfa_ioc_s *ioc)
{
struct bfi_ioc_ctrl_req_s enable_req;
+ struct bfa_timeval_s tv;
bfi_h2i_set(enable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_ENABLE_REQ,
bfa_ioc_portid(ioc));
enable_req.ioc_class = ioc->ioc_mc;
+ bfa_os_gettimeofday(&tv);
+ enable_req.tv_sec = bfa_os_ntohl(tv.tv_sec);
bfa_ioc_mbox_send(ioc, &enable_req, sizeof(struct bfi_ioc_ctrl_req_s));
}
@@ -1065,7 +1489,7 @@ bfa_ioc_send_disable(struct bfa_ioc_s *ioc)
static void
bfa_ioc_send_getattr(struct bfa_ioc_s *ioc)
{
- struct bfi_ioc_getattr_req_s attr_req;
+ struct bfi_ioc_getattr_req_s attr_req;
bfi_h2i_set(attr_req.mh, BFI_MC_IOC, BFI_IOC_H2I_GETATTR_REQ,
bfa_ioc_portid(ioc));
@@ -1077,12 +1501,11 @@ static void
bfa_ioc_hb_check(void *cbarg)
{
struct bfa_ioc_s *ioc = cbarg;
- u32 hb_count;
+ u32 hb_count;
hb_count = bfa_reg_read(ioc->ioc_regs.heartbeat);
if (ioc->hb_count == hb_count) {
- bfa_log(ioc->logm, BFA_LOG_HAL_HEARTBEAT_FAILURE,
- hb_count);
+ printk(KERN_CRIT "Firmware heartbeat failure at %d", hb_count);
bfa_ioc_recover(ioc);
return;
} else {
@@ -1090,61 +1513,54 @@ bfa_ioc_hb_check(void *cbarg)
}
bfa_ioc_mbox_poll(ioc);
- bfa_timer_begin(ioc->timer_mod, &ioc->ioc_timer, bfa_ioc_hb_check,
- ioc, BFA_IOC_HB_TOV);
+ bfa_hb_timer_start(ioc);
}
static void
bfa_ioc_hb_monitor(struct bfa_ioc_s *ioc)
{
ioc->hb_count = bfa_reg_read(ioc->ioc_regs.heartbeat);
- bfa_timer_begin(ioc->timer_mod, &ioc->ioc_timer, bfa_ioc_hb_check, ioc,
- BFA_IOC_HB_TOV);
+ bfa_hb_timer_start(ioc);
}
static void
bfa_ioc_hb_stop(struct bfa_ioc_s *ioc)
{
- bfa_timer_stop(&ioc->ioc_timer);
+ bfa_hb_timer_stop(ioc);
}
+
/**
- * Initiate a full firmware download.
+ * Initiate a full firmware download.
*/
static void
bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type,
- u32 boot_param)
+ u32 boot_env)
{
- u32 *fwimg;
- u32 pgnum, pgoff;
- u32 loff = 0;
- u32 chunkno = 0;
- u32 i;
+ u32 *fwimg;
+ u32 pgnum, pgoff;
+ u32 loff = 0;
+ u32 chunkno = 0;
+ u32 i;
/**
* Initialize LMEM first before code download
*/
bfa_ioc_lmem_init(ioc);
- /**
- * Flash based firmware boot
- */
- bfa_trc(ioc, bfi_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)));
- if (bfa_ioc_is_optrom(ioc))
- boot_type = BFI_BOOT_TYPE_FLASH;
- fwimg = bfi_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), chunkno);
-
+ bfa_trc(ioc, bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)));
+ fwimg = bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), chunkno);
pgnum = bfa_ioc_smem_pgnum(ioc, loff);
pgoff = bfa_ioc_smem_pgoff(ioc, loff);
bfa_reg_write(ioc->ioc_regs.host_page_num_fn, pgnum);
- for (i = 0; i < bfi_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)); i++) {
+ for (i = 0; i < bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)); i++) {
if (BFA_IOC_FLASH_CHUNK_NO(i) != chunkno) {
chunkno = BFA_IOC_FLASH_CHUNK_NO(i);
- fwimg = bfi_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc),
+ fwimg = bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc),
BFA_IOC_FLASH_CHUNK_ADDR(chunkno));
}
@@ -1162,7 +1578,8 @@ bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type,
loff = PSS_SMEM_PGOFF(loff);
if (loff == 0) {
pgnum++;
- bfa_reg_write(ioc->ioc_regs.host_page_num_fn, pgnum);
+ bfa_reg_write(ioc->ioc_regs.host_page_num_fn,
+ pgnum);
}
}
@@ -1171,11 +1588,11 @@ bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type,
/*
* Set boot type and boot param at the end.
- */
+ */
bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_BOOT_TYPE_OFF,
bfa_os_swap32(boot_type));
- bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_BOOT_PARAM_OFF,
- bfa_os_swap32(boot_param));
+ bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_BOOT_LOADER_OFF,
+ bfa_os_swap32(boot_env));
}
static void
@@ -1190,11 +1607,11 @@ bfa_ioc_reset(struct bfa_ioc_s *ioc, bfa_boolean_t force)
static void
bfa_ioc_getattr_reply(struct bfa_ioc_s *ioc)
{
- struct bfi_ioc_attr_s *attr = ioc->attr;
+ struct bfi_ioc_attr_s *attr = ioc->attr;
- attr->adapter_prop = bfa_os_ntohl(attr->adapter_prop);
+ attr->adapter_prop = bfa_os_ntohl(attr->adapter_prop);
attr->card_type = bfa_os_ntohl(attr->card_type);
- attr->maxfrsize = bfa_os_ntohs(attr->maxfrsize);
+ attr->maxfrsize = bfa_os_ntohs(attr->maxfrsize);
bfa_fsm_send_event(ioc, IOC_E_FWRSP_GETATTR);
}
@@ -1205,8 +1622,8 @@ bfa_ioc_getattr_reply(struct bfa_ioc_s *ioc)
static void
bfa_ioc_mbox_attach(struct bfa_ioc_s *ioc)
{
- struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
- int mc;
+ struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
+ int mc;
INIT_LIST_HEAD(&mod->cmd_q);
for (mc = 0; mc < BFI_MC_MAX; mc++) {
@@ -1221,9 +1638,9 @@ bfa_ioc_mbox_attach(struct bfa_ioc_s *ioc)
static void
bfa_ioc_mbox_poll(struct bfa_ioc_s *ioc)
{
- struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
- struct bfa_mbox_cmd_s *cmd;
- u32 stat;
+ struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
+ struct bfa_mbox_cmd_s *cmd;
+ u32 stat;
/**
* If no command pending, do nothing
@@ -1251,25 +1668,194 @@ bfa_ioc_mbox_poll(struct bfa_ioc_s *ioc)
static void
bfa_ioc_mbox_hbfail(struct bfa_ioc_s *ioc)
{
- struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
- struct bfa_mbox_cmd_s *cmd;
+ struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
+ struct bfa_mbox_cmd_s *cmd;
while (!list_empty(&mod->cmd_q))
bfa_q_deq(&mod->cmd_q, &cmd);
}
/**
- * bfa_ioc_public
+ * Read data from SMEM to host through PCI memmap
+ *
+ * @param[in] ioc memory for IOC
+ * @param[in] tbuf app memory to store data from smem
+ * @param[in] soff smem offset
+ * @param[in] sz size of smem in bytes
+ */
+static bfa_status_t
+bfa_ioc_smem_read(struct bfa_ioc_s *ioc, void *tbuf, u32 soff, u32 sz)
+{
+ u32 pgnum, loff, r32;
+ int i, len;
+ u32 *buf = tbuf;
+
+ pgnum = bfa_ioc_smem_pgnum(ioc, soff);
+ loff = bfa_ioc_smem_pgoff(ioc, soff);
+ bfa_trc(ioc, pgnum);
+ bfa_trc(ioc, loff);
+ bfa_trc(ioc, sz);
+
+ /*
+ * Hold semaphore to serialize pll init and fwtrc.
+ */
+ if (BFA_FALSE == bfa_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg)) {
+ bfa_trc(ioc, 0);
+ return BFA_STATUS_FAILED;
+ }
+
+ bfa_reg_write(ioc->ioc_regs.host_page_num_fn, pgnum);
+
+ len = sz/sizeof(u32);
+ bfa_trc(ioc, len);
+ for (i = 0; i < len; i++) {
+ r32 = bfa_mem_read(ioc->ioc_regs.smem_page_start, loff);
+ buf[i] = bfa_os_ntohl(r32);
+ loff += sizeof(u32);
+
+ /**
+ * handle page offset wrap around
+ */
+ loff = PSS_SMEM_PGOFF(loff);
+ if (loff == 0) {
+ pgnum++;
+ bfa_reg_write(ioc->ioc_regs.host_page_num_fn, pgnum);
+ }
+ }
+ bfa_reg_write(ioc->ioc_regs.host_page_num_fn,
+ bfa_ioc_smem_pgnum(ioc, 0));
+ /*
+ * release semaphore.
+ */
+ bfa_ioc_sem_release(ioc->ioc_regs.ioc_init_sem_reg);
+
+ bfa_trc(ioc, pgnum);
+ return BFA_STATUS_OK;
+}
+
+/**
+ * Clear SMEM data from host through PCI memmap
+ *
+ * @param[in] ioc memory for IOC
+ * @param[in] soff smem offset
+ * @param[in] sz size of smem in bytes
+ */
+static bfa_status_t
+bfa_ioc_smem_clr(struct bfa_ioc_s *ioc, u32 soff, u32 sz)
+{
+ int i, len;
+ u32 pgnum, loff;
+
+ pgnum = bfa_ioc_smem_pgnum(ioc, soff);
+ loff = bfa_ioc_smem_pgoff(ioc, soff);
+ bfa_trc(ioc, pgnum);
+ bfa_trc(ioc, loff);
+ bfa_trc(ioc, sz);
+
+ /*
+ * Hold semaphore to serialize pll init and fwtrc.
+ */
+ if (BFA_FALSE == bfa_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg)) {
+ bfa_trc(ioc, 0);
+ return BFA_STATUS_FAILED;
+ }
+
+ bfa_reg_write(ioc->ioc_regs.host_page_num_fn, pgnum);
+
+ len = sz/sizeof(u32); /* len in words */
+ bfa_trc(ioc, len);
+ for (i = 0; i < len; i++) {
+ bfa_mem_write(ioc->ioc_regs.smem_page_start, loff, 0);
+ loff += sizeof(u32);
+
+ /**
+ * handle page offset wrap around
+ */
+ loff = PSS_SMEM_PGOFF(loff);
+ if (loff == 0) {
+ pgnum++;
+ bfa_reg_write(ioc->ioc_regs.host_page_num_fn, pgnum);
+ }
+ }
+ bfa_reg_write(ioc->ioc_regs.host_page_num_fn,
+ bfa_ioc_smem_pgnum(ioc, 0));
+
+ /*
+ * release semaphore.
+ */
+ bfa_ioc_sem_release(ioc->ioc_regs.ioc_init_sem_reg);
+ bfa_trc(ioc, pgnum);
+ return BFA_STATUS_OK;
+}
+
+/**
+ * hal iocpf to ioc interface
+ */
+static void
+bfa_ioc_pf_enabled(struct bfa_ioc_s *ioc)
+{
+ bfa_fsm_send_event(ioc, IOC_E_ENABLED);
+}
+
+static void
+bfa_ioc_pf_disabled(struct bfa_ioc_s *ioc)
+{
+ bfa_fsm_send_event(ioc, IOC_E_DISABLED);
+}
+
+static void
+bfa_ioc_pf_failed(struct bfa_ioc_s *ioc)
+{
+ bfa_fsm_send_event(ioc, IOC_E_FAILED);
+}
+
+static void
+bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc)
+{
+ struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
+ /**
+ * Provide enable completion callback.
+ */
+ ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+ BFA_LOG(KERN_WARNING, bfad, log_level,
+ "Running firmware version is incompatible "
+ "with the driver version\n");
+}
+
+
+
+/**
+ * hal_ioc_public
*/
+bfa_status_t
+bfa_ioc_pll_init(struct bfa_ioc_s *ioc)
+{
+
+ /*
+ * Hold semaphore so that nobody can access the chip during init.
+ */
+ bfa_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg);
+
+ bfa_ioc_pll_init_asic(ioc);
+
+ ioc->pllinit = BFA_TRUE;
+ /*
+ * release semaphore.
+ */
+ bfa_ioc_sem_release(ioc->ioc_regs.ioc_init_sem_reg);
+
+ return BFA_STATUS_OK;
+}
+
/**
* Interface used by diag module to do firmware boot with memory test
* as the entry vector.
*/
void
-bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, u32 boot_param)
+bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, u32 boot_env)
{
- bfa_os_addr_t rb;
+ bfa_os_addr_t rb;
bfa_ioc_stats(ioc, ioc_boots);
@@ -1280,7 +1866,7 @@ bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, u32 boot_param)
* Initialize IOC state of all functions on a chip reset.
*/
rb = ioc->pcidev.pci_bar_kva;
- if (boot_param == BFI_BOOT_TYPE_MEMTEST) {
+ if (boot_type == BFI_BOOT_TYPE_MEMTEST) {
bfa_reg_write((rb + BFA_IOC0_STATE_REG), BFI_IOC_MEMTEST);
bfa_reg_write((rb + BFA_IOC1_STATE_REG), BFI_IOC_MEMTEST);
} else {
@@ -1289,7 +1875,7 @@ bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, u32 boot_param)
}
bfa_ioc_msgflush(ioc);
- bfa_ioc_download_fw(ioc, boot_type, boot_param);
+ bfa_ioc_download_fw(ioc, boot_type, boot_env);
/**
* Enable interrupts just before starting LPU
@@ -1308,18 +1894,29 @@ bfa_ioc_auto_recover(bfa_boolean_t auto_recover)
}
+
bfa_boolean_t
bfa_ioc_is_operational(struct bfa_ioc_s *ioc)
{
return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_op);
}
+bfa_boolean_t
+bfa_ioc_is_initialized(struct bfa_ioc_s *ioc)
+{
+ u32 r32 = bfa_reg_read(ioc->ioc_regs.ioc_fwstate);
+
+ return ((r32 != BFI_IOC_UNINIT) &&
+ (r32 != BFI_IOC_INITING) &&
+ (r32 != BFI_IOC_MEMTEST));
+}
+
void
bfa_ioc_msgget(struct bfa_ioc_s *ioc, void *mbmsg)
{
- u32 *msgp = mbmsg;
- u32 r32;
- int i;
+ u32 *msgp = mbmsg;
+ u32 r32;
+ int i;
/**
* read the MBOX msg
@@ -1341,9 +1938,10 @@ bfa_ioc_msgget(struct bfa_ioc_s *ioc, void *mbmsg)
void
bfa_ioc_isr(struct bfa_ioc_s *ioc, struct bfi_mbmsg_s *m)
{
- union bfi_ioc_i2h_msg_u *msg;
+ union bfi_ioc_i2h_msg_u *msg;
+ struct bfa_iocpf_s *iocpf = &ioc->iocpf;
- msg = (union bfi_ioc_i2h_msg_u *)m;
+ msg = (union bfi_ioc_i2h_msg_u *) m;
bfa_ioc_stats(ioc, ioc_isrs);
@@ -1352,15 +1950,15 @@ bfa_ioc_isr(struct bfa_ioc_s *ioc, struct bfi_mbmsg_s *m)
break;
case BFI_IOC_I2H_READY_EVENT:
- bfa_fsm_send_event(ioc, IOC_E_FWREADY);
+ bfa_fsm_send_event(iocpf, IOCPF_E_FWREADY);
break;
case BFI_IOC_I2H_ENABLE_REPLY:
- bfa_fsm_send_event(ioc, IOC_E_FWRSP_ENABLE);
+ bfa_fsm_send_event(iocpf, IOCPF_E_FWRSP_ENABLE);
break;
case BFI_IOC_I2H_DISABLE_REPLY:
- bfa_fsm_send_event(ioc, IOC_E_FWRSP_DISABLE);
+ bfa_fsm_send_event(iocpf, IOCPF_E_FWRSP_DISABLE);
break;
case BFI_IOC_I2H_GETATTR_REPLY:
@@ -1378,29 +1976,24 @@ bfa_ioc_isr(struct bfa_ioc_s *ioc, struct bfi_mbmsg_s *m)
*
* @param[in] ioc memory for IOC
* @param[in] bfa driver instance structure
- * @param[in] trcmod kernel trace module
- * @param[in] aen kernel aen event module
- * @param[in] logm kernel logging module
*/
void
bfa_ioc_attach(struct bfa_ioc_s *ioc, void *bfa, struct bfa_ioc_cbfn_s *cbfn,
- struct bfa_timer_mod_s *timer_mod, struct bfa_trc_mod_s *trcmod,
- struct bfa_aen_s *aen, struct bfa_log_mod_s *logm)
-{
- ioc->bfa = bfa;
- ioc->cbfn = cbfn;
- ioc->timer_mod = timer_mod;
- ioc->trcmod = trcmod;
- ioc->aen = aen;
- ioc->logm = logm;
- ioc->fcmode = BFA_FALSE;
- ioc->pllinit = BFA_FALSE;
+ struct bfa_timer_mod_s *timer_mod)
+{
+ ioc->bfa = bfa;
+ ioc->cbfn = cbfn;
+ ioc->timer_mod = timer_mod;
+ ioc->fcmode = BFA_FALSE;
+ ioc->pllinit = BFA_FALSE;
ioc->dbg_fwsave_once = BFA_TRUE;
+ ioc->iocpf.ioc = ioc;
bfa_ioc_mbox_attach(ioc);
INIT_LIST_HEAD(&ioc->hb_notify_q);
- bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
+ bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
+ bfa_fsm_send_event(ioc, IOC_E_RESET);
}
/**
@@ -1421,10 +2014,10 @@ void
bfa_ioc_pci_init(struct bfa_ioc_s *ioc, struct bfa_pcidev_s *pcidev,
enum bfi_mclass mc)
{
- ioc->ioc_mc = mc;
- ioc->pcidev = *pcidev;
- ioc->ctdev = bfa_asic_id_ct(ioc->pcidev.device_id);
- ioc->cna = ioc->ctdev && !ioc->fcmode;
+ ioc->ioc_mc = mc;
+ ioc->pcidev = *pcidev;
+ ioc->ctdev = bfa_asic_id_ct(ioc->pcidev.device_id);
+ ioc->cna = ioc->ctdev && !ioc->fcmode;
/**
* Set asic specific interfaces. See bfa_ioc_cb.c and bfa_ioc_ct.c
@@ -1445,14 +2038,14 @@ bfa_ioc_pci_init(struct bfa_ioc_s *ioc, struct bfa_pcidev_s *pcidev,
* @param[in] dm_pa physical address of IOC dma memory
*/
void
-bfa_ioc_mem_claim(struct bfa_ioc_s *ioc, u8 *dm_kva, u64 dm_pa)
+bfa_ioc_mem_claim(struct bfa_ioc_s *ioc, u8 *dm_kva, u64 dm_pa)
{
/**
* dma memory for firmware attribute
*/
ioc->attr_dma.kva = dm_kva;
ioc->attr_dma.pa = dm_pa;
- ioc->attr = (struct bfi_ioc_attr_s *)dm_kva;
+ ioc->attr = (struct bfi_ioc_attr_s *) dm_kva;
}
/**
@@ -1490,7 +2083,7 @@ bfa_ioc_disable(struct bfa_ioc_s *ioc)
int
bfa_ioc_debug_trcsz(bfa_boolean_t auto_recover)
{
-return (auto_recover) ? BFA_DBG_FWTRC_LEN : 0;
+ return (auto_recover) ? BFA_DBG_FWTRC_LEN : 0;
}
/**
@@ -1500,8 +2093,8 @@ return (auto_recover) ? BFA_DBG_FWTRC_LEN : 0;
void
bfa_ioc_debug_memclaim(struct bfa_ioc_s *ioc, void *dbg_fwsave)
{
- ioc->dbg_fwsave = dbg_fwsave;
- ioc->dbg_fwsave_len = bfa_ioc_debug_trcsz(ioc->auto_recover);
+ ioc->dbg_fwsave = dbg_fwsave;
+ ioc->dbg_fwsave_len = bfa_ioc_debug_trcsz(ioc->iocpf.auto_recover);
}
u32
@@ -1525,8 +2118,8 @@ bfa_ioc_smem_pgoff(struct bfa_ioc_s *ioc, u32 fmaddr)
void
bfa_ioc_mbox_register(struct bfa_ioc_s *ioc, bfa_ioc_mbox_mcfunc_t *mcfuncs)
{
- struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
- int mc;
+ struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
+ int mc;
for (mc = 0; mc < BFI_MC_MAX; mc++)
mod->mbhdlr[mc].cbfn = mcfuncs[mc];
@@ -1539,10 +2132,10 @@ void
bfa_ioc_mbox_regisr(struct bfa_ioc_s *ioc, enum bfi_mclass mc,
bfa_ioc_mbox_mcfunc_t cbfn, void *cbarg)
{
- struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
+ struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
- mod->mbhdlr[mc].cbfn = cbfn;
- mod->mbhdlr[mc].cbarg = cbarg;
+ mod->mbhdlr[mc].cbfn = cbfn;
+ mod->mbhdlr[mc].cbarg = cbarg;
}
/**
@@ -1555,8 +2148,8 @@ bfa_ioc_mbox_regisr(struct bfa_ioc_s *ioc, enum bfi_mclass mc,
void
bfa_ioc_mbox_queue(struct bfa_ioc_s *ioc, struct bfa_mbox_cmd_s *cmd)
{
- struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
- u32 stat;
+ struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
+ u32 stat;
/**
* If a previous command is pending, queue new command
@@ -1587,9 +2180,9 @@ bfa_ioc_mbox_queue(struct bfa_ioc_s *ioc, struct bfa_mbox_cmd_s *cmd)
void
bfa_ioc_mbox_isr(struct bfa_ioc_s *ioc)
{
- struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
- struct bfi_mbmsg_s m;
- int mc;
+ struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
+ struct bfi_mbmsg_s m;
+ int mc;
bfa_ioc_msgget(ioc, &m);
@@ -1621,16 +2214,14 @@ bfa_ioc_set_fcmode(struct bfa_ioc_s *ioc)
ioc->port_id = bfa_ioc_pcifn(ioc);
}
-#ifndef BFA_BIOS_BUILD
-
/**
* return true if IOC is disabled
*/
bfa_boolean_t
bfa_ioc_is_disabled(struct bfa_ioc_s *ioc)
{
- return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabling)
- || bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled);
+ return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabling) ||
+ bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled);
}
/**
@@ -1639,9 +2230,9 @@ bfa_ioc_is_disabled(struct bfa_ioc_s *ioc)
bfa_boolean_t
bfa_ioc_fw_mismatch(struct bfa_ioc_s *ioc)
{
- return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_reset)
- || bfa_fsm_cmp_state(ioc, bfa_ioc_sm_fwcheck)
- || bfa_fsm_cmp_state(ioc, bfa_ioc_sm_mismatch);
+ return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_reset) ||
+ bfa_fsm_cmp_state(&ioc->iocpf, bfa_iocpf_sm_fwcheck) ||
+ bfa_fsm_cmp_state(&ioc->iocpf, bfa_iocpf_sm_mismatch);
}
#define bfa_ioc_state_disabled(__sm) \
@@ -1659,8 +2250,8 @@ bfa_ioc_fw_mismatch(struct bfa_ioc_s *ioc)
bfa_boolean_t
bfa_ioc_adapter_is_disabled(struct bfa_ioc_s *ioc)
{
- u32 ioc_state;
- bfa_os_addr_t rb = ioc->pcidev.pci_bar_kva;
+ u32 ioc_state;
+ bfa_os_addr_t rb = ioc->pcidev.pci_bar_kva;
if (!bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled))
return BFA_FALSE;
@@ -1669,16 +2260,18 @@ bfa_ioc_adapter_is_disabled(struct bfa_ioc_s *ioc)
if (!bfa_ioc_state_disabled(ioc_state))
return BFA_FALSE;
- ioc_state = bfa_reg_read(rb + BFA_IOC1_STATE_REG);
- if (!bfa_ioc_state_disabled(ioc_state))
- return BFA_FALSE;
+ if (ioc->pcidev.device_id != BFA_PCI_DEVICE_ID_FC_8G1P) {
+ ioc_state = bfa_reg_read(rb + BFA_IOC1_STATE_REG);
+ if (!bfa_ioc_state_disabled(ioc_state))
+ return BFA_FALSE;
+ }
return BFA_TRUE;
}
/**
* Add to IOC heartbeat failure notification queue. To be used by common
- * modules such as
+ * modules such as cee, port, diag.
*/
void
bfa_ioc_hbfail_register(struct bfa_ioc_s *ioc,
@@ -1692,7 +2285,7 @@ void
bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc,
struct bfa_adapter_attr_s *ad_attr)
{
- struct bfi_ioc_attr_s *ioc_attr;
+ struct bfi_ioc_attr_s *ioc_attr;
ioc_attr = ioc->attr;
@@ -1719,7 +2312,7 @@ bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc,
ad_attr->prototype = 0;
ad_attr->pwwn = bfa_ioc_get_pwwn(ioc);
- ad_attr->mac = bfa_ioc_get_mac(ioc);
+ ad_attr->mac = bfa_ioc_get_mac(ioc);
ad_attr->pcie_gen = ioc_attr->pcie_gen;
ad_attr->pcie_lanes = ioc_attr->pcie_lanes;
@@ -1729,6 +2322,7 @@ bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc,
bfa_ioc_get_pci_chip_rev(ioc, ad_attr->hw_ver);
ad_attr->cna_capable = ioc->cna;
+ ad_attr->trunk_capable = (ad_attr->nports > 1) && !ioc->cna;
}
enum bfa_ioc_type_e
@@ -1782,7 +2376,7 @@ bfa_ioc_get_adapter_optrom_ver(struct bfa_ioc_s *ioc, char *optrom_ver)
{
bfa_os_memset((void *)optrom_ver, 0, BFA_VERSION_LEN);
bfa_os_memcpy(optrom_ver, ioc->attr->optrom_version,
- BFA_VERSION_LEN);
+ BFA_VERSION_LEN);
}
void
@@ -1795,7 +2389,7 @@ bfa_ioc_get_adapter_manufacturer(struct bfa_ioc_s *ioc, char *manufacturer)
void
bfa_ioc_get_adapter_model(struct bfa_ioc_s *ioc, char *model)
{
- struct bfi_ioc_attr_s *ioc_attr;
+ struct bfi_ioc_attr_s *ioc_attr;
bfa_assert(model);
bfa_os_memset((void *)model, 0, BFA_ADAPTER_MODEL_NAME_LEN);
@@ -1805,14 +2399,48 @@ bfa_ioc_get_adapter_model(struct bfa_ioc_s *ioc, char *model)
/**
* model name
*/
- snprintf(model, BFA_ADAPTER_MODEL_NAME_LEN, "%s-%u",
- BFA_MFG_NAME, ioc_attr->card_type);
+ bfa_os_snprintf(model, BFA_ADAPTER_MODEL_NAME_LEN, "%s-%u",
+ BFA_MFG_NAME, ioc_attr->card_type);
}
enum bfa_ioc_state
bfa_ioc_get_state(struct bfa_ioc_s *ioc)
{
- return bfa_sm_to_state(ioc_sm_table, ioc->fsm);
+ enum bfa_iocpf_state iocpf_st;
+ enum bfa_ioc_state ioc_st = bfa_sm_to_state(ioc_sm_table, ioc->fsm);
+
+ if (ioc_st == BFA_IOC_ENABLING ||
+ ioc_st == BFA_IOC_FAIL || ioc_st == BFA_IOC_INITFAIL) {
+
+ iocpf_st = bfa_sm_to_state(iocpf_sm_table, ioc->iocpf.fsm);
+
+ switch (iocpf_st) {
+ case BFA_IOCPF_SEMWAIT:
+ ioc_st = BFA_IOC_SEMWAIT;
+ break;
+
+ case BFA_IOCPF_HWINIT:
+ ioc_st = BFA_IOC_HWINIT;
+ break;
+
+ case BFA_IOCPF_FWMISMATCH:
+ ioc_st = BFA_IOC_FWMISMATCH;
+ break;
+
+ case BFA_IOCPF_FAIL:
+ ioc_st = BFA_IOC_FAIL;
+ break;
+
+ case BFA_IOCPF_INITFAIL:
+ ioc_st = BFA_IOC_INITFAIL;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return ioc_st;
}
void
@@ -1833,7 +2461,7 @@ bfa_ioc_get_attr(struct bfa_ioc_s *ioc, struct bfa_ioc_attr_s *ioc_attr)
}
/**
- * bfa_wwn_public
+ * hal_wwn_public
*/
wwn_t
bfa_ioc_get_pwwn(struct bfa_ioc_s *ioc)
@@ -1857,10 +2485,10 @@ mac_t
bfa_ioc_get_mac(struct bfa_ioc_s *ioc)
{
/*
- * Currently mfg mac is used as FCoE enode mac (not configured by PBC)
+ * Check the IOC type and return the appropriate MAC
*/
if (bfa_ioc_get_type(ioc) == BFA_IOC_TYPE_FCoE)
- return bfa_ioc_get_mfg_mac(ioc);
+ return ioc->attr->fcoe_mac;
else
return ioc->attr->mac;
}
@@ -1880,12 +2508,16 @@ bfa_ioc_get_mfg_nwwn(struct bfa_ioc_s *ioc)
mac_t
bfa_ioc_get_mfg_mac(struct bfa_ioc_s *ioc)
{
- mac_t mac;
+ mac_t m;
- mac = ioc->attr->mfg_mac;
- mac.mac[MAC_ADDRLEN - 1] += bfa_ioc_pcifn(ioc);
+ m = ioc->attr->mfg_mac;
+ if (bfa_mfg_is_old_wwn_mac_model(ioc->attr->card_type))
+ m.mac[MAC_ADDRLEN - 1] += bfa_ioc_pcifn(ioc);
+ else
+ bfa_mfg_increment_wwn_mac(&(m.mac[MAC_ADDRLEN-3]),
+ bfa_ioc_pcifn(ioc));
- return mac;
+ return m;
}
bfa_boolean_t
@@ -1895,46 +2527,12 @@ bfa_ioc_get_fcmode(struct bfa_ioc_s *ioc)
}
/**
- * Send AEN notification
- */
-void
-bfa_ioc_aen_post(struct bfa_ioc_s *ioc, enum bfa_ioc_aen_event event)
-{
- union bfa_aen_data_u aen_data;
- struct bfa_log_mod_s *logmod = ioc->logm;
- s32 inst_num = 0;
- enum bfa_ioc_type_e ioc_type;
-
- bfa_log(logmod, BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, event), inst_num);
-
- memset(&aen_data.ioc.pwwn, 0, sizeof(aen_data.ioc.pwwn));
- memset(&aen_data.ioc.mac, 0, sizeof(aen_data.ioc.mac));
- ioc_type = bfa_ioc_get_type(ioc);
- switch (ioc_type) {
- case BFA_IOC_TYPE_FC:
- aen_data.ioc.pwwn = bfa_ioc_get_pwwn(ioc);
- break;
- case BFA_IOC_TYPE_FCoE:
- aen_data.ioc.pwwn = bfa_ioc_get_pwwn(ioc);
- aen_data.ioc.mac = bfa_ioc_get_mac(ioc);
- break;
- case BFA_IOC_TYPE_LL:
- aen_data.ioc.mac = bfa_ioc_get_mac(ioc);
- break;
- default:
- bfa_assert(ioc_type == BFA_IOC_TYPE_FC);
- break;
- }
- aen_data.ioc.ioc_type = ioc_type;
-}
-
-/**
* Retrieve saved firmware trace from a prior IOC failure.
*/
bfa_status_t
bfa_ioc_debug_fwsave(struct bfa_ioc_s *ioc, void *trcdata, int *trclen)
{
- int tlen;
+ int tlen;
if (ioc->dbg_fwsave_len == 0)
return BFA_STATUS_ENOFSAVE;
@@ -1963,57 +2561,145 @@ bfa_ioc_debug_fwsave_clear(struct bfa_ioc_s *ioc)
bfa_status_t
bfa_ioc_debug_fwtrc(struct bfa_ioc_s *ioc, void *trcdata, int *trclen)
{
- u32 pgnum;
- u32 loff = BFA_DBG_FWTRC_OFF(bfa_ioc_portid(ioc));
- int i, tlen;
- u32 *tbuf = trcdata, r32;
+ u32 loff = BFA_DBG_FWTRC_OFF(bfa_ioc_portid(ioc));
+ int tlen;
+ bfa_status_t status;
bfa_trc(ioc, *trclen);
- pgnum = bfa_ioc_smem_pgnum(ioc, loff);
- loff = bfa_ioc_smem_pgoff(ioc, loff);
-
- /*
- * Hold semaphore to serialize pll init and fwtrc.
- */
- if (BFA_FALSE == bfa_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg))
- return BFA_STATUS_FAILED;
-
- bfa_reg_write(ioc->ioc_regs.host_page_num_fn, pgnum);
-
tlen = *trclen;
if (tlen > BFA_DBG_FWTRC_LEN)
tlen = BFA_DBG_FWTRC_LEN;
- tlen /= sizeof(u32);
- bfa_trc(ioc, tlen);
+ status = bfa_ioc_smem_read(ioc, trcdata, loff, tlen);
+ *trclen = tlen;
+ return status;
+}
- for (i = 0; i < tlen; i++) {
- r32 = bfa_mem_read(ioc->ioc_regs.smem_page_start, loff);
- tbuf[i] = bfa_os_ntohl(r32);
- loff += sizeof(u32);
+static void
+bfa_ioc_send_fwsync(struct bfa_ioc_s *ioc)
+{
+ struct bfa_mbox_cmd_s cmd;
+ struct bfi_ioc_ctrl_req_s *req = (struct bfi_ioc_ctrl_req_s *) cmd.msg;
- /**
- * handle page offset wrap around
- */
- loff = PSS_SMEM_PGOFF(loff);
- if (loff == 0) {
- pgnum++;
- bfa_reg_write(ioc->ioc_regs.host_page_num_fn, pgnum);
- }
+ bfi_h2i_set(req->mh, BFI_MC_IOC, BFI_IOC_H2I_DBG_SYNC,
+ bfa_ioc_portid(ioc));
+ req->ioc_class = ioc->ioc_mc;
+ bfa_ioc_mbox_queue(ioc, &cmd);
+}
+
+static void
+bfa_ioc_fwsync(struct bfa_ioc_s *ioc)
+{
+ u32 fwsync_iter = 1000;
+
+ bfa_ioc_send_fwsync(ioc);
+
+ /**
+ * After sending a fw sync mbox command wait for it to
+ * take effect. We will not wait for a response because
+ * 1. fw_sync mbox cmd doesn't have a response.
+ * 2. Even if we implement that, interrupts might not
+ * be enabled when we call this function.
+ * So, just keep checking if any mbox cmd is pending, and
+ * after waiting for a reasonable amount of time, go ahead.
+ * It is possible that fw has crashed and the mbox command
+ * is never acknowledged.
+ */
+ while (bfa_ioc_mbox_cmd_pending(ioc) && fwsync_iter > 0)
+ fwsync_iter--;
+}
+
+/**
+ * Dump firmware smem
+ */
+bfa_status_t
+bfa_ioc_debug_fwcore(struct bfa_ioc_s *ioc, void *buf,
+ u32 *offset, int *buflen)
+{
+ u32 loff;
+ int dlen;
+ bfa_status_t status;
+ u32 smem_len = BFA_IOC_FW_SMEM_SIZE(ioc);
+
+ if (*offset >= smem_len) {
+ *offset = *buflen = 0;
+ return BFA_STATUS_EINVAL;
}
- bfa_reg_write(ioc->ioc_regs.host_page_num_fn,
- bfa_ioc_smem_pgnum(ioc, 0));
- /*
- * release semaphore.
+ loff = *offset;
+ dlen = *buflen;
+
+ /**
+ * First smem read, sync smem before proceeding
+ * No need to sync before reading every chunk.
*/
- bfa_ioc_sem_release(ioc->ioc_regs.ioc_init_sem_reg);
+ if (loff == 0)
+ bfa_ioc_fwsync(ioc);
- bfa_trc(ioc, pgnum);
+ if ((loff + dlen) >= smem_len)
+ dlen = smem_len - loff;
- *trclen = tlen * sizeof(u32);
- return BFA_STATUS_OK;
+ status = bfa_ioc_smem_read(ioc, buf, loff, dlen);
+
+ if (status != BFA_STATUS_OK) {
+ *offset = *buflen = 0;
+ return status;
+ }
+
+ *offset += dlen;
+
+ if (*offset >= smem_len)
+ *offset = 0;
+
+ *buflen = dlen;
+
+ return status;
+}
+
+/**
+ * Firmware statistics
+ */
+bfa_status_t
+bfa_ioc_fw_stats_get(struct bfa_ioc_s *ioc, void *stats)
+{
+ u32 loff = BFI_IOC_FWSTATS_OFF + \
+ BFI_IOC_FWSTATS_SZ * (bfa_ioc_portid(ioc));
+ int tlen;
+ bfa_status_t status;
+
+ if (ioc->stats_busy) {
+ bfa_trc(ioc, ioc->stats_busy);
+ return BFA_STATUS_DEVBUSY;
+ }
+ ioc->stats_busy = BFA_TRUE;
+
+ tlen = sizeof(struct bfa_fw_stats_s);
+ status = bfa_ioc_smem_read(ioc, stats, loff, tlen);
+
+ ioc->stats_busy = BFA_FALSE;
+ return status;
+}
+
+bfa_status_t
+bfa_ioc_fw_stats_clear(struct bfa_ioc_s *ioc)
+{
+ u32 loff = BFI_IOC_FWSTATS_OFF + \
+ BFI_IOC_FWSTATS_SZ * (bfa_ioc_portid(ioc));
+ int tlen;
+ bfa_status_t status;
+
+ if (ioc->stats_busy) {
+ bfa_trc(ioc, ioc->stats_busy);
+ return BFA_STATUS_DEVBUSY;
+ }
+ ioc->stats_busy = BFA_TRUE;
+
+ tlen = sizeof(struct bfa_fw_stats_s);
+ status = bfa_ioc_smem_clr(ioc, loff, tlen);
+
+ ioc->stats_busy = BFA_FALSE;
+ return status;
}
/**
@@ -2022,7 +2708,7 @@ bfa_ioc_debug_fwtrc(struct bfa_ioc_s *ioc, void *trcdata, int *trclen)
static void
bfa_ioc_debug_save(struct bfa_ioc_s *ioc)
{
- int tlen;
+ int tlen;
if (ioc->dbg_fwsave_len) {
tlen = ioc->dbg_fwsave_len;
@@ -2050,11 +2736,135 @@ bfa_ioc_check_attr_wwns(struct bfa_ioc_s *ioc)
{
if (bfa_ioc_get_type(ioc) == BFA_IOC_TYPE_LL)
return;
+}
+
+/**
+ * hal_iocpf_pvt BFA IOC PF private functions
+ */
- if (ioc->attr->nwwn == 0)
- bfa_ioc_aen_post(ioc, BFA_IOC_AEN_INVALID_NWWN);
- if (ioc->attr->pwwn == 0)
- bfa_ioc_aen_post(ioc, BFA_IOC_AEN_INVALID_PWWN);
+static void
+bfa_iocpf_enable(struct bfa_ioc_s *ioc)
+{
+ bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_ENABLE);
}
-#endif
+static void
+bfa_iocpf_disable(struct bfa_ioc_s *ioc)
+{
+ bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_DISABLE);
+}
+
+static void
+bfa_iocpf_fail(struct bfa_ioc_s *ioc)
+{
+ bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FAIL);
+}
+
+static void
+bfa_iocpf_initfail(struct bfa_ioc_s *ioc)
+{
+ bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL);
+}
+
+static void
+bfa_iocpf_getattrfail(struct bfa_ioc_s *ioc)
+{
+ bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_GETATTRFAIL);
+}
+
+static void
+bfa_iocpf_stop(struct bfa_ioc_s *ioc)
+{
+ bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP);
+}
+
+static void
+bfa_iocpf_timeout(void *ioc_arg)
+{
+ struct bfa_ioc_s *ioc = (struct bfa_ioc_s *) ioc_arg;
+
+ bfa_trc(ioc, 0);
+ bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_TIMEOUT);
+}
+
+static void
+bfa_iocpf_sem_timeout(void *ioc_arg)
+{
+ struct bfa_ioc_s *ioc = (struct bfa_ioc_s *) ioc_arg;
+
+ bfa_ioc_hw_sem_get(ioc);
+}
+
+/**
+ * bfa timer function
+ */
+void
+bfa_timer_init(struct bfa_timer_mod_s *mod)
+{
+ INIT_LIST_HEAD(&mod->timer_q);
+}
+
+void
+bfa_timer_beat(struct bfa_timer_mod_s *mod)
+{
+ struct list_head *qh = &mod->timer_q;
+ struct list_head *qe, *qe_next;
+ struct bfa_timer_s *elem;
+ struct list_head timedout_q;
+
+ INIT_LIST_HEAD(&timedout_q);
+
+ qe = bfa_q_next(qh);
+
+ while (qe != qh) {
+ qe_next = bfa_q_next(qe);
+
+ elem = (struct bfa_timer_s *) qe;
+ if (elem->timeout <= BFA_TIMER_FREQ) {
+ elem->timeout = 0;
+ list_del(&elem->qe);
+ list_add_tail(&elem->qe, &timedout_q);
+ } else {
+ elem->timeout -= BFA_TIMER_FREQ;
+ }
+
+ qe = qe_next; /* go to next elem */
+ }
+
+ /*
+ * Pop all the timeout entries
+ */
+ while (!list_empty(&timedout_q)) {
+ bfa_q_deq(&timedout_q, &elem);
+ elem->timercb(elem->arg);
+ }
+}
+
+/**
+ * Should be called with lock protection
+ */
+void
+bfa_timer_begin(struct bfa_timer_mod_s *mod, struct bfa_timer_s *timer,
+ void (*timercb) (void *), void *arg, unsigned int timeout)
+{
+
+ bfa_assert(timercb != NULL);
+ bfa_assert(!bfa_q_is_on_q(&mod->timer_q, timer));
+
+ timer->timeout = timeout;
+ timer->timercb = timercb;
+ timer->arg = arg;
+
+ list_add_tail(&timer->qe, &mod->timer_q);
+}
+
+/**
+ * Should be called with lock protection
+ */
+void
+bfa_timer_stop(struct bfa_timer_s *timer)
+{
+ bfa_assert(!list_empty(&timer->qe));
+
+ list_del(&timer->qe);
+}
diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h
index cae05b251c99..288c5801aace 100644
--- a/drivers/scsi/bfa/bfa_ioc.h
+++ b/drivers/scsi/bfa/bfa_ioc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
* All rights reserved
* www.brocade.com
*
@@ -18,18 +18,74 @@
#ifndef __BFA_IOC_H__
#define __BFA_IOC_H__
-#include <cs/bfa_sm.h>
-#include <bfi/bfi.h>
-#include <bfi/bfi_ioc.h>
-#include <bfi/bfi_boot.h>
-#include <bfa_timer.h>
+#include "bfa_os_inc.h"
+#include "bfa_cs.h"
+#include "bfi.h"
+
+/**
+ * BFA timer declarations
+ */
+typedef void (*bfa_timer_cbfn_t)(void *);
+
+/**
+ * BFA timer data structure
+ */
+struct bfa_timer_s {
+ struct list_head qe;
+ bfa_timer_cbfn_t timercb;
+ void *arg;
+ int timeout; /**< in millisecs. */
+};
+
+/**
+ * Timer module structure
+ */
+struct bfa_timer_mod_s {
+ struct list_head timer_q;
+};
+
+#define BFA_TIMER_FREQ 200 /**< specified in millisecs */
+
+void bfa_timer_beat(struct bfa_timer_mod_s *mod);
+void bfa_timer_init(struct bfa_timer_mod_s *mod);
+void bfa_timer_begin(struct bfa_timer_mod_s *mod, struct bfa_timer_s *timer,
+ bfa_timer_cbfn_t timercb, void *arg,
+ unsigned int timeout);
+void bfa_timer_stop(struct bfa_timer_s *timer);
+
+/**
+ * Generic Scatter Gather Element used by driver
+ */
+struct bfa_sge_s {
+ u32 sg_len;
+ void *sg_addr;
+};
+
+#define bfa_sge_word_swap(__sge) do { \
+ ((u32 *)(__sge))[0] = bfa_os_swap32(((u32 *)(__sge))[0]); \
+ ((u32 *)(__sge))[1] = bfa_os_swap32(((u32 *)(__sge))[1]); \
+ ((u32 *)(__sge))[2] = bfa_os_swap32(((u32 *)(__sge))[2]); \
+} while (0)
+
+#define bfa_swap_words(_x) ( \
+ ((_x) << 32) | ((_x) >> 32))
+
+#ifdef __BIGENDIAN
+#define bfa_sge_to_be(_x)
+#define bfa_sge_to_le(_x) bfa_sge_word_swap(_x)
+#define bfa_sgaddr_le(_x) bfa_swap_words(_x)
+#else
+#define bfa_sge_to_be(_x) bfa_sge_word_swap(_x)
+#define bfa_sge_to_le(_x)
+#define bfa_sgaddr_le(_x) (_x)
+#endif
/**
* PCI device information required by IOC
*/
struct bfa_pcidev_s {
- int pci_slot;
- u8 pci_func;
+ int pci_slot;
+ u8 pci_func;
u16 device_id;
bfa_os_addr_t pci_bar_kva;
};
@@ -39,13 +95,18 @@ struct bfa_pcidev_s {
* Address
*/
struct bfa_dma_s {
- void *kva; /*! Kernel virtual address */
- u64 pa; /*! Physical address */
+ void *kva; /* ! Kernel virtual address */
+ u64 pa; /* ! Physical address */
};
#define BFA_DMA_ALIGN_SZ 256
#define BFA_ROUNDUP(_l, _s) (((_l) + ((_s) - 1)) & ~((_s) - 1))
+/**
+ * smem size for Crossbow and Catapult
+ */
+#define BFI_SMEM_CB_SIZE 0x200000U /* ! 2MB for crossbow */
+#define BFI_SMEM_CT_SIZE 0x280000U /* ! 2.5MB for catapult */
#define bfa_dma_addr_set(dma_addr, pa) \
@@ -101,7 +162,7 @@ struct bfa_ioc_regs_s {
* IOC Mailbox structures
*/
struct bfa_mbox_cmd_s {
- struct list_head qe;
+ struct list_head qe;
u32 msg[BFI_IOC_MSGSZ];
};
@@ -110,8 +171,8 @@ struct bfa_mbox_cmd_s {
*/
typedef void (*bfa_ioc_mbox_mcfunc_t)(void *cbarg, struct bfi_mbmsg_s *m);
struct bfa_ioc_mbox_mod_s {
- struct list_head cmd_q; /* pending mbox queue */
- int nmclass; /* number of handlers */
+ struct list_head cmd_q; /* pending mbox queue */
+ int nmclass; /* number of handlers */
struct {
bfa_ioc_mbox_mcfunc_t cbfn; /* message handlers */
void *cbarg;
@@ -149,49 +210,54 @@ struct bfa_ioc_hbfail_notify_s {
(__notify)->cbarg = (__cbarg); \
} while (0)
+struct bfa_iocpf_s {
+ bfa_fsm_t fsm;
+ struct bfa_ioc_s *ioc;
+ u32 retry_count;
+ bfa_boolean_t auto_recover;
+};
+
struct bfa_ioc_s {
bfa_fsm_t fsm;
struct bfa_s *bfa;
struct bfa_pcidev_s pcidev;
- struct bfa_timer_mod_s *timer_mod;
- struct bfa_timer_s ioc_timer;
- struct bfa_timer_s sem_timer;
+ struct bfa_timer_mod_s *timer_mod;
+ struct bfa_timer_s ioc_timer;
+ struct bfa_timer_s sem_timer;
+ struct bfa_timer_s hb_timer;
u32 hb_count;
- u32 retry_count;
struct list_head hb_notify_q;
void *dbg_fwsave;
int dbg_fwsave_len;
bfa_boolean_t dbg_fwsave_once;
enum bfi_mclass ioc_mc;
- struct bfa_ioc_regs_s ioc_regs;
+ struct bfa_ioc_regs_s ioc_regs;
struct bfa_trc_mod_s *trcmod;
- struct bfa_aen_s *aen;
- struct bfa_log_mod_s *logm;
struct bfa_ioc_drv_stats_s stats;
- bfa_boolean_t auto_recover;
bfa_boolean_t fcmode;
bfa_boolean_t ctdev;
bfa_boolean_t cna;
bfa_boolean_t pllinit;
+ bfa_boolean_t stats_busy; /* outstanding stats */
u8 port_id;
-
struct bfa_dma_s attr_dma;
struct bfi_ioc_attr_s *attr;
struct bfa_ioc_cbfn_s *cbfn;
struct bfa_ioc_mbox_mod_s mbox_mod;
- struct bfa_ioc_hwif_s *ioc_hwif;
+ struct bfa_ioc_hwif_s *ioc_hwif;
+ struct bfa_iocpf_s iocpf;
};
struct bfa_ioc_hwif_s {
- bfa_status_t (*ioc_pll_init) (struct bfa_ioc_s *ioc);
- bfa_boolean_t (*ioc_firmware_lock) (struct bfa_ioc_s *ioc);
- void (*ioc_firmware_unlock) (struct bfa_ioc_s *ioc);
- void (*ioc_reg_init) (struct bfa_ioc_s *ioc);
- void (*ioc_map_port) (struct bfa_ioc_s *ioc);
- void (*ioc_isr_mode_set) (struct bfa_ioc_s *ioc,
- bfa_boolean_t msix);
- void (*ioc_notify_hbfail) (struct bfa_ioc_s *ioc);
- void (*ioc_ownership_reset) (struct bfa_ioc_s *ioc);
+ bfa_status_t (*ioc_pll_init) (bfa_os_addr_t rb, bfa_boolean_t fcmode);
+ bfa_boolean_t (*ioc_firmware_lock) (struct bfa_ioc_s *ioc);
+ void (*ioc_firmware_unlock) (struct bfa_ioc_s *ioc);
+ void (*ioc_reg_init) (struct bfa_ioc_s *ioc);
+ void (*ioc_map_port) (struct bfa_ioc_s *ioc);
+ void (*ioc_isr_mode_set) (struct bfa_ioc_s *ioc,
+ bfa_boolean_t msix);
+ void (*ioc_notify_hbfail) (struct bfa_ioc_s *ioc);
+ void (*ioc_ownership_reset) (struct bfa_ioc_s *ioc);
};
#define bfa_ioc_pcifn(__ioc) ((__ioc)->pcidev.pci_func)
@@ -206,18 +272,19 @@ struct bfa_ioc_hwif_s {
#define bfa_ioc_rx_bbcredit(__ioc) ((__ioc)->attr->rx_bbcredit)
#define bfa_ioc_speed_sup(__ioc) \
BFI_ADAPTER_GETP(SPEED, (__ioc)->attr->adapter_prop)
-#define bfa_ioc_get_nports(__ioc) \
+#define bfa_ioc_get_nports(__ioc) \
BFI_ADAPTER_GETP(NPORTS, (__ioc)->attr->adapter_prop)
-#define bfa_ioc_stats(_ioc, _stats) ((_ioc)->stats._stats++)
-#define BFA_IOC_FWIMG_MINSZ (16 * 1024)
-#define BFA_IOC_FWIMG_TYPE(__ioc) \
- (((__ioc)->ctdev) ? \
- (((__ioc)->fcmode) ? BFI_IMAGE_CT_FC : BFI_IMAGE_CT_CNA) : \
+#define bfa_ioc_stats(_ioc, _stats) ((_ioc)->stats._stats++)
+#define BFA_IOC_FWIMG_MINSZ (16 * 1024)
+#define BFA_IOC_FWIMG_TYPE(__ioc) \
+ (((__ioc)->ctdev) ? \
+ (((__ioc)->fcmode) ? BFI_IMAGE_CT_FC : BFI_IMAGE_CT_CNA) : \
BFI_IMAGE_CB_FC)
-
-#define BFA_IOC_FLASH_CHUNK_NO(off) (off / BFI_FLASH_CHUNK_SZ_WORDS)
-#define BFA_IOC_FLASH_OFFSET_IN_CHUNK(off) (off % BFI_FLASH_CHUNK_SZ_WORDS)
+#define BFA_IOC_FW_SMEM_SIZE(__ioc) \
+ (((__ioc)->ctdev) ? BFI_SMEM_CT_SIZE : BFI_SMEM_CB_SIZE)
+#define BFA_IOC_FLASH_CHUNK_NO(off) (off / BFI_FLASH_CHUNK_SZ_WORDS)
+#define BFA_IOC_FLASH_OFFSET_IN_CHUNK(off) (off % BFI_FLASH_CHUNK_SZ_WORDS)
#define BFA_IOC_FLASH_CHUNK_ADDR(chunkno) (chunkno * BFI_FLASH_CHUNK_SZ_WORDS)
/**
@@ -235,18 +302,28 @@ void bfa_ioc_mbox_regisr(struct bfa_ioc_s *ioc, enum bfi_mclass mc,
/**
* IOC interfaces
*/
-#define bfa_ioc_pll_init(__ioc) ((__ioc)->ioc_hwif->ioc_pll_init(__ioc))
-#define bfa_ioc_isr_mode_set(__ioc, __msix) \
+
+#define bfa_ioc_pll_init_asic(__ioc) \
+ ((__ioc)->ioc_hwif->ioc_pll_init((__ioc)->pcidev.pci_bar_kva, \
+ (__ioc)->fcmode))
+
+bfa_status_t bfa_ioc_pll_init(struct bfa_ioc_s *ioc);
+bfa_status_t bfa_ioc_cb_pll_init(bfa_os_addr_t rb, bfa_boolean_t fcmode);
+bfa_boolean_t bfa_ioc_ct_pll_init_complete(bfa_os_addr_t rb);
+bfa_status_t bfa_ioc_ct_pll_init(bfa_os_addr_t rb, bfa_boolean_t fcmode);
+
+#define bfa_ioc_isr_mode_set(__ioc, __msix) \
((__ioc)->ioc_hwif->ioc_isr_mode_set(__ioc, __msix))
-#define bfa_ioc_ownership_reset(__ioc) \
+#define bfa_ioc_ownership_reset(__ioc) \
((__ioc)->ioc_hwif->ioc_ownership_reset(__ioc))
+
void bfa_ioc_set_ct_hwif(struct bfa_ioc_s *ioc);
void bfa_ioc_set_cb_hwif(struct bfa_ioc_s *ioc);
+
void bfa_ioc_attach(struct bfa_ioc_s *ioc, void *bfa,
- struct bfa_ioc_cbfn_s *cbfn, struct bfa_timer_mod_s *timer_mod,
- struct bfa_trc_mod_s *trcmod,
- struct bfa_aen_s *aen, struct bfa_log_mod_s *logm);
+ struct bfa_ioc_cbfn_s *cbfn, struct bfa_timer_mod_s *timer_mod);
+void bfa_ioc_auto_recover(bfa_boolean_t auto_recover);
void bfa_ioc_detach(struct bfa_ioc_s *ioc);
void bfa_ioc_pci_init(struct bfa_ioc_s *ioc, struct bfa_pcidev_s *pcidev,
enum bfi_mclass mc);
@@ -256,21 +333,22 @@ void bfa_ioc_enable(struct bfa_ioc_s *ioc);
void bfa_ioc_disable(struct bfa_ioc_s *ioc);
bfa_boolean_t bfa_ioc_intx_claim(struct bfa_ioc_s *ioc);
-void bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, u32 boot_param);
+void bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type,
+ u32 boot_param);
void bfa_ioc_isr(struct bfa_ioc_s *ioc, struct bfi_mbmsg_s *msg);
void bfa_ioc_error_isr(struct bfa_ioc_s *ioc);
bfa_boolean_t bfa_ioc_is_operational(struct bfa_ioc_s *ioc);
+bfa_boolean_t bfa_ioc_is_initialized(struct bfa_ioc_s *ioc);
bfa_boolean_t bfa_ioc_is_disabled(struct bfa_ioc_s *ioc);
bfa_boolean_t bfa_ioc_fw_mismatch(struct bfa_ioc_s *ioc);
bfa_boolean_t bfa_ioc_adapter_is_disabled(struct bfa_ioc_s *ioc);
-void bfa_ioc_cfg_complete(struct bfa_ioc_s *ioc);
enum bfa_ioc_type_e bfa_ioc_get_type(struct bfa_ioc_s *ioc);
void bfa_ioc_get_adapter_serial_num(struct bfa_ioc_s *ioc, char *serial_num);
void bfa_ioc_get_adapter_fw_ver(struct bfa_ioc_s *ioc, char *fw_ver);
void bfa_ioc_get_adapter_optrom_ver(struct bfa_ioc_s *ioc, char *optrom_ver);
void bfa_ioc_get_adapter_model(struct bfa_ioc_s *ioc, char *model);
void bfa_ioc_get_adapter_manufacturer(struct bfa_ioc_s *ioc,
- char *manufacturer);
+ char *manufacturer);
void bfa_ioc_get_pci_chip_rev(struct bfa_ioc_s *ioc, char *chip_rev);
enum bfa_ioc_state bfa_ioc_get_state(struct bfa_ioc_s *ioc);
@@ -284,6 +362,8 @@ bfa_status_t bfa_ioc_debug_fwsave(struct bfa_ioc_s *ioc, void *trcdata,
void bfa_ioc_debug_fwsave_clear(struct bfa_ioc_s *ioc);
bfa_status_t bfa_ioc_debug_fwtrc(struct bfa_ioc_s *ioc, void *trcdata,
int *trclen);
+bfa_status_t bfa_ioc_debug_fwcore(struct bfa_ioc_s *ioc, void *buf,
+ u32 *offset, int *buflen);
u32 bfa_ioc_smem_pgnum(struct bfa_ioc_s *ioc, u32 fmaddr);
u32 bfa_ioc_smem_pgoff(struct bfa_ioc_s *ioc, u32 fmaddr);
void bfa_ioc_set_fcmode(struct bfa_ioc_s *ioc);
@@ -297,7 +377,8 @@ void bfa_ioc_fwver_get(struct bfa_ioc_s *ioc,
struct bfi_ioc_image_hdr_s *fwhdr);
bfa_boolean_t bfa_ioc_fwver_cmp(struct bfa_ioc_s *ioc,
struct bfi_ioc_image_hdr_s *fwhdr);
-void bfa_ioc_aen_post(struct bfa_ioc_s *ioc, enum bfa_ioc_aen_event event);
+bfa_status_t bfa_ioc_fw_stats_get(struct bfa_ioc_s *ioc, void *stats);
+bfa_status_t bfa_ioc_fw_stats_clear(struct bfa_ioc_s *ioc);
/*
* bfa mfg wwn API functions
@@ -310,5 +391,68 @@ wwn_t bfa_ioc_get_mfg_nwwn(struct bfa_ioc_s *ioc);
mac_t bfa_ioc_get_mfg_mac(struct bfa_ioc_s *ioc);
u64 bfa_ioc_get_adid(struct bfa_ioc_s *ioc);
-#endif /* __BFA_IOC_H__ */
+/*
+ * F/W Image Size & Chunk
+ */
+extern u32 bfi_image_ct_fc_size;
+extern u32 bfi_image_ct_cna_size;
+extern u32 bfi_image_cb_fc_size;
+extern u32 *bfi_image_ct_fc;
+extern u32 *bfi_image_ct_cna;
+extern u32 *bfi_image_cb_fc;
+
+static inline u32 *
+bfi_image_ct_fc_get_chunk(u32 off)
+{ return (u32 *)(bfi_image_ct_fc + off); }
+
+static inline u32 *
+bfi_image_ct_cna_get_chunk(u32 off)
+{ return (u32 *)(bfi_image_ct_cna + off); }
+static inline u32 *
+bfi_image_cb_fc_get_chunk(u32 off)
+{ return (u32 *)(bfi_image_cb_fc + off); }
+
+static inline u32*
+bfa_cb_image_get_chunk(int type, u32 off)
+{
+ switch (type) {
+ case BFI_IMAGE_CT_FC:
+ return bfi_image_ct_fc_get_chunk(off); break;
+ case BFI_IMAGE_CT_CNA:
+ return bfi_image_ct_cna_get_chunk(off); break;
+ case BFI_IMAGE_CB_FC:
+ return bfi_image_cb_fc_get_chunk(off); break;
+ default: return 0;
+ }
+}
+
+static inline u32
+bfa_cb_image_get_size(int type)
+{
+ switch (type) {
+ case BFI_IMAGE_CT_FC:
+ return bfi_image_ct_fc_size; break;
+ case BFI_IMAGE_CT_CNA:
+ return bfi_image_ct_cna_size; break;
+ case BFI_IMAGE_CB_FC:
+ return bfi_image_cb_fc_size; break;
+ default: return 0;
+ }
+}
+
+/**
+ * CNA TRCMOD declaration
+ */
+/*
+ * !!! Only append to the enums defined here to avoid any versioning
+ * !!! needed between trace utility and driver version
+ */
+enum {
+ BFA_TRC_CNA_PORT = 1,
+ BFA_TRC_CNA_IOC = 2,
+ BFA_TRC_CNA_IOC_CB = 3,
+ BFA_TRC_CNA_IOC_CT = 4,
+};
+
+#endif /* __BFA_IOC_H__ */
diff --git a/drivers/scsi/bfa/bfa_ioc_cb.c b/drivers/scsi/bfa/bfa_ioc_cb.c
index 324bdde7ea2e..d7ac864d8539 100644
--- a/drivers/scsi/bfa/bfa_ioc_cb.c
+++ b/drivers/scsi/bfa/bfa_ioc_cb.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
* All rights reserved
* www.brocade.com
*
@@ -15,22 +15,15 @@
* General Public License for more details.
*/
-#include <bfa.h>
-#include <bfa_ioc.h>
-#include <bfa_fwimg_priv.h>
-#include <cna/bfa_cna_trcmod.h>
-#include <cs/bfa_debug.h>
-#include <bfi/bfi_ioc.h>
-#include <bfi/bfi_cbreg.h>
-#include <log/bfa_log_hal.h>
-#include <defs/bfa_defs_pci.h>
+#include "bfa_ioc.h"
+#include "bfi_cbreg.h"
+#include "bfa_defs.h"
BFA_TRC_FILE(CNA, IOC_CB);
/*
* forward declarations
*/
-static bfa_status_t bfa_ioc_cb_pll_init(struct bfa_ioc_s *ioc);
static bfa_boolean_t bfa_ioc_cb_firmware_lock(struct bfa_ioc_s *ioc);
static void bfa_ioc_cb_firmware_unlock(struct bfa_ioc_s *ioc);
static void bfa_ioc_cb_reg_init(struct bfa_ioc_s *ioc);
@@ -95,6 +88,7 @@ static struct { u32 hfn_mbox, lpu_mbox, hfn_pgn; } iocreg_fnreg[] = {
* Host <-> LPU mailbox command/status registers
*/
static struct { u32 hfn, lpu; } iocreg_mbcmd[] = {
+
{ HOSTFN0_LPU0_CMD_STAT, LPU0_HOSTFN0_CMD_STAT },
{ HOSTFN1_LPU1_CMD_STAT, LPU1_HOSTFN1_CMD_STAT }
};
@@ -154,6 +148,7 @@ bfa_ioc_cb_reg_init(struct bfa_ioc_s *ioc)
/**
* Initialize IOC to port mapping.
*/
+
static void
bfa_ioc_cb_map_port(struct bfa_ioc_s *ioc)
{
@@ -161,6 +156,7 @@ bfa_ioc_cb_map_port(struct bfa_ioc_s *ioc)
* For crossbow, port id is same as pci function.
*/
ioc->port_id = bfa_ioc_pcifn(ioc);
+
bfa_trc(ioc, ioc->port_id);
}
@@ -172,87 +168,69 @@ bfa_ioc_cb_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix)
{
}
-static bfa_status_t
-bfa_ioc_cb_pll_init(struct bfa_ioc_s *ioc)
+/**
+ * Cleanup hw semaphore and usecnt registers
+ */
+static void
+bfa_ioc_cb_ownership_reset(struct bfa_ioc_s *ioc)
{
- bfa_os_addr_t rb = ioc->pcidev.pci_bar_kva;
- u32 pll_sclk, pll_fclk;
/*
- * Hold semaphore so that nobody can access the chip during init.
+ * Read the hw sem reg to make sure that it is locked
+ * before we clear it. If it is not locked, writing 1
+ * will lock it instead of clearing it.
*/
- bfa_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg);
+ bfa_reg_read(ioc->ioc_regs.ioc_sem_reg);
+ bfa_ioc_hw_sem_release(ioc);
+}
+
+
+
+bfa_status_t
+bfa_ioc_cb_pll_init(bfa_os_addr_t rb, bfa_boolean_t fcmode)
+{
+ u32 pll_sclk, pll_fclk;
pll_sclk = __APP_PLL_212_ENABLE | __APP_PLL_212_LRESETN |
- __APP_PLL_212_P0_1(3U) |
- __APP_PLL_212_JITLMT0_1(3U) |
- __APP_PLL_212_CNTLMT0_1(3U);
+ __APP_PLL_212_P0_1(3U) |
+ __APP_PLL_212_JITLMT0_1(3U) |
+ __APP_PLL_212_CNTLMT0_1(3U);
pll_fclk = __APP_PLL_400_ENABLE | __APP_PLL_400_LRESETN |
- __APP_PLL_400_RSEL200500 | __APP_PLL_400_P0_1(3U) |
- __APP_PLL_400_JITLMT0_1(3U) |
- __APP_PLL_400_CNTLMT0_1(3U);
-
+ __APP_PLL_400_RSEL200500 | __APP_PLL_400_P0_1(3U) |
+ __APP_PLL_400_JITLMT0_1(3U) |
+ __APP_PLL_400_CNTLMT0_1(3U);
bfa_reg_write((rb + BFA_IOC0_STATE_REG), BFI_IOC_UNINIT);
bfa_reg_write((rb + BFA_IOC1_STATE_REG), BFI_IOC_UNINIT);
-
bfa_reg_write((rb + HOSTFN0_INT_MSK), 0xffffffffU);
bfa_reg_write((rb + HOSTFN1_INT_MSK), 0xffffffffU);
bfa_reg_write((rb + HOSTFN0_INT_STATUS), 0xffffffffU);
bfa_reg_write((rb + HOSTFN1_INT_STATUS), 0xffffffffU);
bfa_reg_write((rb + HOSTFN0_INT_MSK), 0xffffffffU);
bfa_reg_write((rb + HOSTFN1_INT_MSK), 0xffffffffU);
-
- bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg,
- __APP_PLL_212_LOGIC_SOFT_RESET);
- bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg,
- __APP_PLL_212_BYPASS |
- __APP_PLL_212_LOGIC_SOFT_RESET);
- bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg,
- __APP_PLL_400_LOGIC_SOFT_RESET);
- bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg,
- __APP_PLL_400_BYPASS |
- __APP_PLL_400_LOGIC_SOFT_RESET);
+ bfa_reg_write(rb + APP_PLL_212_CTL_REG,
+ __APP_PLL_212_LOGIC_SOFT_RESET);
+ bfa_reg_write(rb + APP_PLL_212_CTL_REG,
+ __APP_PLL_212_BYPASS |
+ __APP_PLL_212_LOGIC_SOFT_RESET);
+ bfa_reg_write(rb + APP_PLL_400_CTL_REG,
+ __APP_PLL_400_LOGIC_SOFT_RESET);
+ bfa_reg_write(rb + APP_PLL_400_CTL_REG,
+ __APP_PLL_400_BYPASS |
+ __APP_PLL_400_LOGIC_SOFT_RESET);
bfa_os_udelay(2);
- bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg,
- __APP_PLL_212_LOGIC_SOFT_RESET);
- bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg,
- __APP_PLL_400_LOGIC_SOFT_RESET);
-
- bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg,
- pll_sclk | __APP_PLL_212_LOGIC_SOFT_RESET);
- bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg,
- pll_fclk | __APP_PLL_400_LOGIC_SOFT_RESET);
-
- /**
- * Wait for PLLs to lock.
- */
+ bfa_reg_write(rb + APP_PLL_212_CTL_REG,
+ __APP_PLL_212_LOGIC_SOFT_RESET);
+ bfa_reg_write(rb + APP_PLL_400_CTL_REG,
+ __APP_PLL_400_LOGIC_SOFT_RESET);
+ bfa_reg_write(rb + APP_PLL_212_CTL_REG,
+ pll_sclk | __APP_PLL_212_LOGIC_SOFT_RESET);
+ bfa_reg_write(rb + APP_PLL_400_CTL_REG,
+ pll_fclk | __APP_PLL_400_LOGIC_SOFT_RESET);
bfa_os_udelay(2000);
bfa_reg_write((rb + HOSTFN0_INT_STATUS), 0xffffffffU);
bfa_reg_write((rb + HOSTFN1_INT_STATUS), 0xffffffffU);
-
- bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg, pll_sclk);
- bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg, pll_fclk);
-
- /*
- * release semaphore.
- */
- bfa_ioc_sem_release(ioc->ioc_regs.ioc_init_sem_reg);
+ bfa_reg_write((rb + APP_PLL_212_CTL_REG), pll_sclk);
+ bfa_reg_write((rb + APP_PLL_400_CTL_REG), pll_fclk);
return BFA_STATUS_OK;
}
-
-/**
- * Cleanup hw semaphore and usecnt registers
- */
-static void
-bfa_ioc_cb_ownership_reset(struct bfa_ioc_s *ioc)
-{
-
- /*
- * Read the hw sem reg to make sure that it is locked
- * before we clear it. If it is not locked, writing 1
- * will lock it instead of clearing it.
- */
- bfa_reg_read(ioc->ioc_regs.ioc_sem_reg);
- bfa_ioc_hw_sem_release(ioc);
-}
diff --git a/drivers/scsi/bfa/bfa_ioc_ct.c b/drivers/scsi/bfa/bfa_ioc_ct.c
index 68f027da001e..f21b82c5f64c 100644
--- a/drivers/scsi/bfa/bfa_ioc_ct.c
+++ b/drivers/scsi/bfa/bfa_ioc_ct.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
* All rights reserved
* www.brocade.com
*
@@ -15,22 +15,15 @@
* General Public License for more details.
*/
-#include <bfa.h>
-#include <bfa_ioc.h>
-#include <bfa_fwimg_priv.h>
-#include <cna/bfa_cna_trcmod.h>
-#include <cs/bfa_debug.h>
-#include <bfi/bfi_ioc.h>
-#include <bfi/bfi_ctreg.h>
-#include <log/bfa_log_hal.h>
-#include <defs/bfa_defs_pci.h>
+#include "bfa_ioc.h"
+#include "bfi_ctreg.h"
+#include "bfa_defs.h"
BFA_TRC_FILE(CNA, IOC_CT);
/*
* forward declarations
*/
-static bfa_status_t bfa_ioc_ct_pll_init(struct bfa_ioc_s *ioc);
static bfa_boolean_t bfa_ioc_ct_firmware_lock(struct bfa_ioc_s *ioc);
static void bfa_ioc_ct_firmware_unlock(struct bfa_ioc_s *ioc);
static void bfa_ioc_ct_reg_init(struct bfa_ioc_s *ioc);
@@ -78,7 +71,8 @@ bfa_ioc_ct_firmware_lock(struct bfa_ioc_s *ioc)
/**
* If bios boot (flash based) -- do not increment usage count
*/
- if (bfi_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)) < BFA_IOC_FWIMG_MINSZ)
+ if (bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)) <
+ BFA_IOC_FWIMG_MINSZ)
return BFA_TRUE;
bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);
@@ -136,7 +130,8 @@ bfa_ioc_ct_firmware_unlock(struct bfa_ioc_s *ioc)
/**
* If bios boot (flash based) -- do not decrement usage count
*/
- if (bfi_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)) < BFA_IOC_FWIMG_MINSZ)
+ if (bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)) <
+ BFA_IOC_FWIMG_MINSZ)
return;
/**
@@ -308,16 +303,47 @@ bfa_ioc_ct_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix)
bfa_reg_write(rb + FNC_PERS_REG, r32);
}
-static bfa_status_t
-bfa_ioc_ct_pll_init(struct bfa_ioc_s *ioc)
+/**
+ * Cleanup hw semaphore and usecnt registers
+ */
+static void
+bfa_ioc_ct_ownership_reset(struct bfa_ioc_s *ioc)
{
- bfa_os_addr_t rb = ioc->pcidev.pci_bar_kva;
- u32 pll_sclk, pll_fclk, r32;
+
+ if (ioc->cna) {
+ bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);
+ bfa_reg_write(ioc->ioc_regs.ioc_usage_reg, 0);
+ bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg);
+ }
/*
- * Hold semaphore so that nobody can access the chip during init.
+ * Read the hw sem reg to make sure that it is locked
+ * before we clear it. If it is not locked, writing 1
+ * will lock it instead of clearing it.
*/
- bfa_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg);
+ bfa_reg_read(ioc->ioc_regs.ioc_sem_reg);
+ bfa_ioc_hw_sem_release(ioc);
+}
+
+
+
+/*
+ * Check the firmware state to know if pll_init has been completed already
+ */
+bfa_boolean_t
+bfa_ioc_ct_pll_init_complete(bfa_os_addr_t rb)
+{
+ if ((bfa_reg_read(rb + BFA_IOC0_STATE_REG) == BFI_IOC_OP) ||
+ (bfa_reg_read(rb + BFA_IOC1_STATE_REG) == BFI_IOC_OP))
+ return BFA_TRUE;
+
+ return BFA_FALSE;
+}
+
+bfa_status_t
+bfa_ioc_ct_pll_init(bfa_os_addr_t rb, bfa_boolean_t fcmode)
+{
+ u32 pll_sclk, pll_fclk, r32;
pll_sclk = __APP_PLL_312_LRESETN | __APP_PLL_312_ENARST |
__APP_PLL_312_RSEL200500 | __APP_PLL_312_P0_1(3U) |
@@ -327,70 +353,50 @@ bfa_ioc_ct_pll_init(struct bfa_ioc_s *ioc)
__APP_PLL_425_RSEL200500 | __APP_PLL_425_P0_1(3U) |
__APP_PLL_425_JITLMT0_1(3U) |
__APP_PLL_425_CNTLMT0_1(1U);
-
- /**
- * For catapult, choose operational mode FC/FCoE
- */
- if (ioc->fcmode) {
+ if (fcmode) {
bfa_reg_write((rb + OP_MODE), 0);
bfa_reg_write((rb + ETH_MAC_SER_REG),
__APP_EMS_CMLCKSEL |
__APP_EMS_REFCKBUFEN2 |
__APP_EMS_CHANNEL_SEL);
} else {
- ioc->pllinit = BFA_TRUE;
bfa_reg_write((rb + OP_MODE), __GLOBAL_FCOE_MODE);
bfa_reg_write((rb + ETH_MAC_SER_REG),
- __APP_EMS_REFCKBUFEN1);
+ __APP_EMS_REFCKBUFEN1);
}
-
bfa_reg_write((rb + BFA_IOC0_STATE_REG), BFI_IOC_UNINIT);
bfa_reg_write((rb + BFA_IOC1_STATE_REG), BFI_IOC_UNINIT);
-
bfa_reg_write((rb + HOSTFN0_INT_MSK), 0xffffffffU);
bfa_reg_write((rb + HOSTFN1_INT_MSK), 0xffffffffU);
bfa_reg_write((rb + HOSTFN0_INT_STATUS), 0xffffffffU);
bfa_reg_write((rb + HOSTFN1_INT_STATUS), 0xffffffffU);
bfa_reg_write((rb + HOSTFN0_INT_MSK), 0xffffffffU);
bfa_reg_write((rb + HOSTFN1_INT_MSK), 0xffffffffU);
-
- bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg, pll_sclk |
+ bfa_reg_write(rb + APP_PLL_312_CTL_REG, pll_sclk |
__APP_PLL_312_LOGIC_SOFT_RESET);
- bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg, pll_fclk |
+ bfa_reg_write(rb + APP_PLL_425_CTL_REG, pll_fclk |
__APP_PLL_425_LOGIC_SOFT_RESET);
- bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg, pll_sclk |
+ bfa_reg_write(rb + APP_PLL_312_CTL_REG, pll_sclk |
__APP_PLL_312_LOGIC_SOFT_RESET | __APP_PLL_312_ENABLE);
- bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg, pll_fclk |
+ bfa_reg_write(rb + APP_PLL_425_CTL_REG, pll_fclk |
__APP_PLL_425_LOGIC_SOFT_RESET | __APP_PLL_425_ENABLE);
-
- /**
- * Wait for PLLs to lock.
- */
bfa_reg_read(rb + HOSTFN0_INT_MSK);
bfa_os_udelay(2000);
bfa_reg_write((rb + HOSTFN0_INT_STATUS), 0xffffffffU);
bfa_reg_write((rb + HOSTFN1_INT_STATUS), 0xffffffffU);
-
- bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg, pll_sclk |
+ bfa_reg_write(rb + APP_PLL_312_CTL_REG, pll_sclk |
__APP_PLL_312_ENABLE);
- bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg, pll_fclk |
+ bfa_reg_write(rb + APP_PLL_425_CTL_REG, pll_fclk |
__APP_PLL_425_ENABLE);
-
- /**
- * PSS memory reset is asserted at power-on-reset. Need to clear
- * this before running EDRAM BISTR
- */
- if (ioc->cna) {
+ if (!fcmode) {
bfa_reg_write((rb + PMM_1T_RESET_REG_P0), __PMM_1T_RESET_P);
bfa_reg_write((rb + PMM_1T_RESET_REG_P1), __PMM_1T_RESET_P);
}
-
r32 = bfa_reg_read((rb + PSS_CTL_REG));
r32 &= ~__PSS_LMEM_RESET;
bfa_reg_write((rb + PSS_CTL_REG), r32);
bfa_os_udelay(1000);
-
- if (ioc->cna) {
+ if (!fcmode) {
bfa_reg_write((rb + PMM_1T_RESET_REG_P0), 0);
bfa_reg_write((rb + PMM_1T_RESET_REG_P1), 0);
}
@@ -398,39 +404,6 @@ bfa_ioc_ct_pll_init(struct bfa_ioc_s *ioc)
bfa_reg_write((rb + MBIST_CTL_REG), __EDRAM_BISTR_START);
bfa_os_udelay(1000);
r32 = bfa_reg_read((rb + MBIST_STAT_REG));
- bfa_trc(ioc, r32);
-
- /**
- * Clear BISTR
- */
bfa_reg_write((rb + MBIST_CTL_REG), 0);
-
- /*
- * release semaphore.
- */
- bfa_ioc_sem_release(ioc->ioc_regs.ioc_init_sem_reg);
-
return BFA_STATUS_OK;
}
-
-/**
- * Cleanup hw semaphore and usecnt registers
- */
-static void
-bfa_ioc_ct_ownership_reset(struct bfa_ioc_s *ioc)
-{
-
- if (ioc->cna) {
- bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);
- bfa_reg_write(ioc->ioc_regs.ioc_usage_reg, 0);
- bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg);
- }
-
- /*
- * Read the hw sem reg to make sure that it is locked
- * before we clear it. If it is not locked, writing 1
- * will lock it instead of clearing it.
- */
- bfa_reg_read(ioc->ioc_regs.ioc_sem_reg);
- bfa_ioc_hw_sem_release(ioc);
-}
diff --git a/drivers/scsi/bfa/bfa_iocfc.c b/drivers/scsi/bfa/bfa_iocfc.c
deleted file mode 100644
index 90820be99864..000000000000
--- a/drivers/scsi/bfa/bfa_iocfc.c
+++ /dev/null
@@ -1,927 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#include <cs/bfa_debug.h>
-#include <bfa_priv.h>
-#include <log/bfa_log_hal.h>
-#include <bfi/bfi_boot.h>
-#include <bfi/bfi_cbreg.h>
-#include <aen/bfa_aen_ioc.h>
-#include <defs/bfa_defs_iocfc.h>
-#include <defs/bfa_defs_pci.h>
-#include "bfa_callback_priv.h"
-#include "bfad_drv.h"
-
-BFA_TRC_FILE(HAL, IOCFC);
-
-/**
- * IOC local definitions
- */
-#define BFA_IOCFC_TOV 5000 /* msecs */
-
-enum {
- BFA_IOCFC_ACT_NONE = 0,
- BFA_IOCFC_ACT_INIT = 1,
- BFA_IOCFC_ACT_STOP = 2,
- BFA_IOCFC_ACT_DISABLE = 3,
-};
-
-/*
- * forward declarations
- */
-static void bfa_iocfc_enable_cbfn(void *bfa_arg, enum bfa_status status);
-static void bfa_iocfc_disable_cbfn(void *bfa_arg);
-static void bfa_iocfc_hbfail_cbfn(void *bfa_arg);
-static void bfa_iocfc_reset_cbfn(void *bfa_arg);
-static void bfa_iocfc_stats_clear(void *bfa_arg);
-static void bfa_iocfc_stats_swap(struct bfa_fw_stats_s *d,
- struct bfa_fw_stats_s *s);
-static void bfa_iocfc_stats_clr_cb(void *bfa_arg, bfa_boolean_t complete);
-static void bfa_iocfc_stats_clr_timeout(void *bfa_arg);
-static void bfa_iocfc_stats_cb(void *bfa_arg, bfa_boolean_t complete);
-static void bfa_iocfc_stats_timeout(void *bfa_arg);
-
-static struct bfa_ioc_cbfn_s bfa_iocfc_cbfn;
-
-/**
- * bfa_ioc_pvt BFA IOC private functions
- */
-
-static void
-bfa_iocfc_cqs_sz(struct bfa_iocfc_cfg_s *cfg, u32 *dm_len)
-{
- int i, per_reqq_sz, per_rspq_sz;
-
- per_reqq_sz = BFA_ROUNDUP((cfg->drvcfg.num_reqq_elems * BFI_LMSG_SZ),
- BFA_DMA_ALIGN_SZ);
- per_rspq_sz = BFA_ROUNDUP((cfg->drvcfg.num_rspq_elems * BFI_LMSG_SZ),
- BFA_DMA_ALIGN_SZ);
-
- /*
- * Calculate CQ size
- */
- for (i = 0; i < cfg->fwcfg.num_cqs; i++) {
- *dm_len = *dm_len + per_reqq_sz;
- *dm_len = *dm_len + per_rspq_sz;
- }
-
- /*
- * Calculate Shadow CI/PI size
- */
- for (i = 0; i < cfg->fwcfg.num_cqs; i++)
- *dm_len += (2 * BFA_CACHELINE_SZ);
-}
-
-static void
-bfa_iocfc_fw_cfg_sz(struct bfa_iocfc_cfg_s *cfg, u32 *dm_len)
-{
- *dm_len +=
- BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfg_s), BFA_CACHELINE_SZ);
- *dm_len +=
- BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s),
- BFA_CACHELINE_SZ);
- *dm_len += BFA_ROUNDUP(sizeof(struct bfa_fw_stats_s), BFA_CACHELINE_SZ);
-}
-
-/**
- * Use the Mailbox interface to send BFI_IOCFC_H2I_CFG_REQ
- */
-static void
-bfa_iocfc_send_cfg(void *bfa_arg)
-{
- struct bfa_s *bfa = bfa_arg;
- struct bfa_iocfc_s *iocfc = &bfa->iocfc;
- struct bfi_iocfc_cfg_req_s cfg_req;
- struct bfi_iocfc_cfg_s *cfg_info = iocfc->cfginfo;
- struct bfa_iocfc_cfg_s *cfg = &iocfc->cfg;
- int i;
-
- bfa_assert(cfg->fwcfg.num_cqs <= BFI_IOC_MAX_CQS);
- bfa_trc(bfa, cfg->fwcfg.num_cqs);
-
- bfa_iocfc_reset_queues(bfa);
-
- /**
- * initialize IOC configuration info
- */
- cfg_info->endian_sig = BFI_IOC_ENDIAN_SIG;
- cfg_info->num_cqs = cfg->fwcfg.num_cqs;
-
- bfa_dma_be_addr_set(cfg_info->cfgrsp_addr, iocfc->cfgrsp_dma.pa);
- bfa_dma_be_addr_set(cfg_info->stats_addr, iocfc->stats_pa);
-
- /**
- * dma map REQ and RSP circular queues and shadow pointers
- */
- for (i = 0; i < cfg->fwcfg.num_cqs; i++) {
- bfa_dma_be_addr_set(cfg_info->req_cq_ba[i],
- iocfc->req_cq_ba[i].pa);
- bfa_dma_be_addr_set(cfg_info->req_shadow_ci[i],
- iocfc->req_cq_shadow_ci[i].pa);
- cfg_info->req_cq_elems[i] =
- bfa_os_htons(cfg->drvcfg.num_reqq_elems);
-
- bfa_dma_be_addr_set(cfg_info->rsp_cq_ba[i],
- iocfc->rsp_cq_ba[i].pa);
- bfa_dma_be_addr_set(cfg_info->rsp_shadow_pi[i],
- iocfc->rsp_cq_shadow_pi[i].pa);
- cfg_info->rsp_cq_elems[i] =
- bfa_os_htons(cfg->drvcfg.num_rspq_elems);
- }
-
- /**
- * Enable interrupt coalescing if it is driver init path
- * and not ioc disable/enable path.
- */
- if (!iocfc->cfgdone)
- cfg_info->intr_attr.coalesce = BFA_TRUE;
-
- iocfc->cfgdone = BFA_FALSE;
-
- /**
- * dma map IOC configuration itself
- */
- bfi_h2i_set(cfg_req.mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_CFG_REQ,
- bfa_lpuid(bfa));
- bfa_dma_be_addr_set(cfg_req.ioc_cfg_dma_addr, iocfc->cfg_info.pa);
-
- bfa_ioc_mbox_send(&bfa->ioc, &cfg_req,
- sizeof(struct bfi_iocfc_cfg_req_s));
-}
-
-static void
-bfa_iocfc_init_mem(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
- struct bfa_pcidev_s *pcidev)
-{
- struct bfa_iocfc_s *iocfc = &bfa->iocfc;
-
- bfa->bfad = bfad;
- iocfc->bfa = bfa;
- iocfc->action = BFA_IOCFC_ACT_NONE;
-
- bfa_os_assign(iocfc->cfg, *cfg);
-
- /**
- * Initialize chip specific handlers.
- */
- if (bfa_asic_id_ct(bfa_ioc_devid(&bfa->ioc))) {
- iocfc->hwif.hw_reginit = bfa_hwct_reginit;
- iocfc->hwif.hw_reqq_ack = bfa_hwct_reqq_ack;
- iocfc->hwif.hw_rspq_ack = bfa_hwct_rspq_ack;
- iocfc->hwif.hw_msix_init = bfa_hwct_msix_init;
- iocfc->hwif.hw_msix_install = bfa_hwct_msix_install;
- iocfc->hwif.hw_msix_uninstall = bfa_hwct_msix_uninstall;
- iocfc->hwif.hw_isr_mode_set = bfa_hwct_isr_mode_set;
- iocfc->hwif.hw_msix_getvecs = bfa_hwct_msix_getvecs;
- iocfc->hwif.hw_msix_get_rme_range = bfa_hwct_msix_get_rme_range;
- } else {
- iocfc->hwif.hw_reginit = bfa_hwcb_reginit;
- iocfc->hwif.hw_reqq_ack = bfa_hwcb_reqq_ack;
- iocfc->hwif.hw_rspq_ack = bfa_hwcb_rspq_ack;
- iocfc->hwif.hw_msix_init = bfa_hwcb_msix_init;
- iocfc->hwif.hw_msix_install = bfa_hwcb_msix_install;
- iocfc->hwif.hw_msix_uninstall = bfa_hwcb_msix_uninstall;
- iocfc->hwif.hw_isr_mode_set = bfa_hwcb_isr_mode_set;
- iocfc->hwif.hw_msix_getvecs = bfa_hwcb_msix_getvecs;
- iocfc->hwif.hw_msix_get_rme_range = bfa_hwcb_msix_get_rme_range;
- }
-
- iocfc->hwif.hw_reginit(bfa);
- bfa->msix.nvecs = 0;
-}
-
-static void
-bfa_iocfc_mem_claim(struct bfa_s *bfa, struct bfa_iocfc_cfg_s *cfg,
- struct bfa_meminfo_s *meminfo)
-{
- u8 *dm_kva;
- u64 dm_pa;
- int i, per_reqq_sz, per_rspq_sz;
- struct bfa_iocfc_s *iocfc = &bfa->iocfc;
- int dbgsz;
-
- dm_kva = bfa_meminfo_dma_virt(meminfo);
- dm_pa = bfa_meminfo_dma_phys(meminfo);
-
- /*
- * First allocate dma memory for IOC.
- */
- bfa_ioc_mem_claim(&bfa->ioc, dm_kva, dm_pa);
- dm_kva += bfa_ioc_meminfo();
- dm_pa += bfa_ioc_meminfo();
-
- /*
- * Claim DMA-able memory for the request/response queues and for shadow
- * ci/pi registers
- */
- per_reqq_sz = BFA_ROUNDUP((cfg->drvcfg.num_reqq_elems * BFI_LMSG_SZ),
- BFA_DMA_ALIGN_SZ);
- per_rspq_sz = BFA_ROUNDUP((cfg->drvcfg.num_rspq_elems * BFI_LMSG_SZ),
- BFA_DMA_ALIGN_SZ);
-
- for (i = 0; i < cfg->fwcfg.num_cqs; i++) {
- iocfc->req_cq_ba[i].kva = dm_kva;
- iocfc->req_cq_ba[i].pa = dm_pa;
- bfa_os_memset(dm_kva, 0, per_reqq_sz);
- dm_kva += per_reqq_sz;
- dm_pa += per_reqq_sz;
-
- iocfc->rsp_cq_ba[i].kva = dm_kva;
- iocfc->rsp_cq_ba[i].pa = dm_pa;
- bfa_os_memset(dm_kva, 0, per_rspq_sz);
- dm_kva += per_rspq_sz;
- dm_pa += per_rspq_sz;
- }
-
- for (i = 0; i < cfg->fwcfg.num_cqs; i++) {
- iocfc->req_cq_shadow_ci[i].kva = dm_kva;
- iocfc->req_cq_shadow_ci[i].pa = dm_pa;
- dm_kva += BFA_CACHELINE_SZ;
- dm_pa += BFA_CACHELINE_SZ;
-
- iocfc->rsp_cq_shadow_pi[i].kva = dm_kva;
- iocfc->rsp_cq_shadow_pi[i].pa = dm_pa;
- dm_kva += BFA_CACHELINE_SZ;
- dm_pa += BFA_CACHELINE_SZ;
- }
-
- /*
- * Claim DMA-able memory for the config info page
- */
- bfa->iocfc.cfg_info.kva = dm_kva;
- bfa->iocfc.cfg_info.pa = dm_pa;
- bfa->iocfc.cfginfo = (struct bfi_iocfc_cfg_s *) dm_kva;
- dm_kva += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfg_s), BFA_CACHELINE_SZ);
- dm_pa += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfg_s), BFA_CACHELINE_SZ);
-
- /*
- * Claim DMA-able memory for the config response
- */
- bfa->iocfc.cfgrsp_dma.kva = dm_kva;
- bfa->iocfc.cfgrsp_dma.pa = dm_pa;
- bfa->iocfc.cfgrsp = (struct bfi_iocfc_cfgrsp_s *) dm_kva;
-
- dm_kva +=
- BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s),
- BFA_CACHELINE_SZ);
- dm_pa += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s),
- BFA_CACHELINE_SZ);
-
- /*
- * Claim DMA-able memory for iocfc stats
- */
- bfa->iocfc.stats_kva = dm_kva;
- bfa->iocfc.stats_pa = dm_pa;
- bfa->iocfc.fw_stats = (struct bfa_fw_stats_s *) dm_kva;
- dm_kva += BFA_ROUNDUP(sizeof(struct bfa_fw_stats_s), BFA_CACHELINE_SZ);
- dm_pa += BFA_ROUNDUP(sizeof(struct bfa_fw_stats_s), BFA_CACHELINE_SZ);
-
- bfa_meminfo_dma_virt(meminfo) = dm_kva;
- bfa_meminfo_dma_phys(meminfo) = dm_pa;
-
- dbgsz = bfa_ioc_debug_trcsz(bfa_auto_recover);
- if (dbgsz > 0) {
- bfa_ioc_debug_memclaim(&bfa->ioc, bfa_meminfo_kva(meminfo));
- bfa_meminfo_kva(meminfo) += dbgsz;
- }
-}
-
-/**
- * Start BFA submodules.
- */
-static void
-bfa_iocfc_start_submod(struct bfa_s *bfa)
-{
- int i;
-
- bfa->rme_process = BFA_TRUE;
-
- for (i = 0; hal_mods[i]; i++)
- hal_mods[i]->start(bfa);
-}
-
-/**
- * Disable BFA submodules.
- */
-static void
-bfa_iocfc_disable_submod(struct bfa_s *bfa)
-{
- int i;
-
- for (i = 0; hal_mods[i]; i++)
- hal_mods[i]->iocdisable(bfa);
-}
-
-static void
-bfa_iocfc_init_cb(void *bfa_arg, bfa_boolean_t complete)
-{
- struct bfa_s *bfa = bfa_arg;
-
- if (complete) {
- if (bfa->iocfc.cfgdone)
- bfa_cb_init(bfa->bfad, BFA_STATUS_OK);
- else
- bfa_cb_init(bfa->bfad, BFA_STATUS_FAILED);
- } else {
- if (bfa->iocfc.cfgdone)
- bfa->iocfc.action = BFA_IOCFC_ACT_NONE;
- }
-}
-
-static void
-bfa_iocfc_stop_cb(void *bfa_arg, bfa_boolean_t compl)
-{
- struct bfa_s *bfa = bfa_arg;
- struct bfad_s *bfad = bfa->bfad;
-
- if (compl)
- complete(&bfad->comp);
-
- else
- bfa->iocfc.action = BFA_IOCFC_ACT_NONE;
-}
-
-static void
-bfa_iocfc_disable_cb(void *bfa_arg, bfa_boolean_t compl)
-{
- struct bfa_s *bfa = bfa_arg;
- struct bfad_s *bfad = bfa->bfad;
-
- if (compl)
- complete(&bfad->disable_comp);
-}
-
-/**
- * Update BFA configuration from firmware configuration.
- */
-static void
-bfa_iocfc_cfgrsp(struct bfa_s *bfa)
-{
- struct bfa_iocfc_s *iocfc = &bfa->iocfc;
- struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp;
- struct bfa_iocfc_fwcfg_s *fwcfg = &cfgrsp->fwcfg;
-
- fwcfg->num_cqs = fwcfg->num_cqs;
- fwcfg->num_ioim_reqs = bfa_os_ntohs(fwcfg->num_ioim_reqs);
- fwcfg->num_tskim_reqs = bfa_os_ntohs(fwcfg->num_tskim_reqs);
- fwcfg->num_fcxp_reqs = bfa_os_ntohs(fwcfg->num_fcxp_reqs);
- fwcfg->num_uf_bufs = bfa_os_ntohs(fwcfg->num_uf_bufs);
- fwcfg->num_rports = bfa_os_ntohs(fwcfg->num_rports);
-
- iocfc->cfgdone = BFA_TRUE;
-
- /**
- * Configuration is complete - initialize/start submodules
- */
- bfa_fcport_init(bfa);
-
- if (iocfc->action == BFA_IOCFC_ACT_INIT)
- bfa_cb_queue(bfa, &iocfc->init_hcb_qe, bfa_iocfc_init_cb, bfa);
- else
- bfa_iocfc_start_submod(bfa);
-}
-
-static void
-bfa_iocfc_stats_clear(void *bfa_arg)
-{
- struct bfa_s *bfa = bfa_arg;
- struct bfa_iocfc_s *iocfc = &bfa->iocfc;
- struct bfi_iocfc_stats_req_s stats_req;
-
- bfa_timer_start(bfa, &iocfc->stats_timer,
- bfa_iocfc_stats_clr_timeout, bfa,
- BFA_IOCFC_TOV);
-
- bfi_h2i_set(stats_req.mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_CLEAR_STATS_REQ,
- bfa_lpuid(bfa));
- bfa_ioc_mbox_send(&bfa->ioc, &stats_req,
- sizeof(struct bfi_iocfc_stats_req_s));
-}
-
-static void
-bfa_iocfc_stats_swap(struct bfa_fw_stats_s *d, struct bfa_fw_stats_s *s)
-{
- u32 *dip = (u32 *) d;
- u32 *sip = (u32 *) s;
- int i;
-
- for (i = 0; i < (sizeof(struct bfa_fw_stats_s) / sizeof(u32)); i++)
- dip[i] = bfa_os_ntohl(sip[i]);
-}
-
-static void
-bfa_iocfc_stats_clr_cb(void *bfa_arg, bfa_boolean_t complete)
-{
- struct bfa_s *bfa = bfa_arg;
- struct bfa_iocfc_s *iocfc = &bfa->iocfc;
-
- if (complete) {
- bfa_ioc_clr_stats(&bfa->ioc);
- iocfc->stats_cbfn(iocfc->stats_cbarg, iocfc->stats_status);
- } else {
- iocfc->stats_busy = BFA_FALSE;
- iocfc->stats_status = BFA_STATUS_OK;
- }
-}
-
-static void
-bfa_iocfc_stats_clr_timeout(void *bfa_arg)
-{
- struct bfa_s *bfa = bfa_arg;
- struct bfa_iocfc_s *iocfc = &bfa->iocfc;
-
- bfa_trc(bfa, 0);
-
- iocfc->stats_status = BFA_STATUS_ETIMER;
- bfa_cb_queue(bfa, &iocfc->stats_hcb_qe, bfa_iocfc_stats_clr_cb, bfa);
-}
-
-static void
-bfa_iocfc_stats_cb(void *bfa_arg, bfa_boolean_t complete)
-{
- struct bfa_s *bfa = bfa_arg;
- struct bfa_iocfc_s *iocfc = &bfa->iocfc;
-
- if (complete) {
- if (iocfc->stats_status == BFA_STATUS_OK) {
- bfa_os_memset(iocfc->stats_ret, 0,
- sizeof(*iocfc->stats_ret));
- bfa_iocfc_stats_swap(&iocfc->stats_ret->fw_stats,
- iocfc->fw_stats);
- }
- iocfc->stats_cbfn(iocfc->stats_cbarg, iocfc->stats_status);
- } else {
- iocfc->stats_busy = BFA_FALSE;
- iocfc->stats_status = BFA_STATUS_OK;
- }
-}
-
-static void
-bfa_iocfc_stats_timeout(void *bfa_arg)
-{
- struct bfa_s *bfa = bfa_arg;
- struct bfa_iocfc_s *iocfc = &bfa->iocfc;
-
- bfa_trc(bfa, 0);
-
- iocfc->stats_status = BFA_STATUS_ETIMER;
- bfa_cb_queue(bfa, &iocfc->stats_hcb_qe, bfa_iocfc_stats_cb, bfa);
-}
-
-static void
-bfa_iocfc_stats_query(struct bfa_s *bfa)
-{
- struct bfa_iocfc_s *iocfc = &bfa->iocfc;
- struct bfi_iocfc_stats_req_s stats_req;
-
- bfa_timer_start(bfa, &iocfc->stats_timer,
- bfa_iocfc_stats_timeout, bfa, BFA_IOCFC_TOV);
-
- bfi_h2i_set(stats_req.mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_GET_STATS_REQ,
- bfa_lpuid(bfa));
- bfa_ioc_mbox_send(&bfa->ioc, &stats_req,
- sizeof(struct bfi_iocfc_stats_req_s));
-}
-
-void
-bfa_iocfc_reset_queues(struct bfa_s *bfa)
-{
- int q;
-
- for (q = 0; q < BFI_IOC_MAX_CQS; q++) {
- bfa_reqq_ci(bfa, q) = 0;
- bfa_reqq_pi(bfa, q) = 0;
- bfa_rspq_ci(bfa, q) = 0;
- bfa_rspq_pi(bfa, q) = 0;
- }
-}
-
-/**
- * IOC enable request is complete
- */
-static void
-bfa_iocfc_enable_cbfn(void *bfa_arg, enum bfa_status status)
-{
- struct bfa_s *bfa = bfa_arg;
-
- if (status != BFA_STATUS_OK) {
- bfa_isr_disable(bfa);
- if (bfa->iocfc.action == BFA_IOCFC_ACT_INIT)
- bfa_cb_queue(bfa, &bfa->iocfc.init_hcb_qe,
- bfa_iocfc_init_cb, bfa);
- return;
- }
-
- bfa_iocfc_send_cfg(bfa);
-}
-
-/**
- * IOC disable request is complete
- */
-static void
-bfa_iocfc_disable_cbfn(void *bfa_arg)
-{
- struct bfa_s *bfa = bfa_arg;
-
- bfa_isr_disable(bfa);
- bfa_iocfc_disable_submod(bfa);
-
- if (bfa->iocfc.action == BFA_IOCFC_ACT_STOP)
- bfa_cb_queue(bfa, &bfa->iocfc.stop_hcb_qe, bfa_iocfc_stop_cb,
- bfa);
- else {
- bfa_assert(bfa->iocfc.action == BFA_IOCFC_ACT_DISABLE);
- bfa_cb_queue(bfa, &bfa->iocfc.dis_hcb_qe, bfa_iocfc_disable_cb,
- bfa);
- }
-}
-
-/**
- * Notify sub-modules of hardware failure.
- */
-static void
-bfa_iocfc_hbfail_cbfn(void *bfa_arg)
-{
- struct bfa_s *bfa = bfa_arg;
-
- bfa->rme_process = BFA_FALSE;
-
- bfa_isr_disable(bfa);
- bfa_iocfc_disable_submod(bfa);
-
- if (bfa->iocfc.action == BFA_IOCFC_ACT_INIT)
- bfa_cb_queue(bfa, &bfa->iocfc.init_hcb_qe, bfa_iocfc_init_cb,
- bfa);
-}
-
-/**
- * Actions on chip-reset completion.
- */
-static void
-bfa_iocfc_reset_cbfn(void *bfa_arg)
-{
- struct bfa_s *bfa = bfa_arg;
-
- bfa_iocfc_reset_queues(bfa);
- bfa_isr_enable(bfa);
-}
-
-
-
-/**
- * bfa_ioc_public
- */
-
-/**
- * Query IOC memory requirement information.
- */
-void
-bfa_iocfc_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
- u32 *dm_len)
-{
- /* dma memory for IOC */
- *dm_len += bfa_ioc_meminfo();
-
- bfa_iocfc_fw_cfg_sz(cfg, dm_len);
- bfa_iocfc_cqs_sz(cfg, dm_len);
- *km_len += bfa_ioc_debug_trcsz(bfa_auto_recover);
-}
-
-/**
- * Query IOC memory requirement information.
- */
-void
-bfa_iocfc_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
- struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
-{
- int i;
-
- bfa_iocfc_cbfn.enable_cbfn = bfa_iocfc_enable_cbfn;
- bfa_iocfc_cbfn.disable_cbfn = bfa_iocfc_disable_cbfn;
- bfa_iocfc_cbfn.hbfail_cbfn = bfa_iocfc_hbfail_cbfn;
- bfa_iocfc_cbfn.reset_cbfn = bfa_iocfc_reset_cbfn;
-
- bfa_ioc_attach(&bfa->ioc, bfa, &bfa_iocfc_cbfn, &bfa->timer_mod,
- bfa->trcmod, bfa->aen, bfa->logm);
-
- /**
- * Set FC mode for BFA_PCI_DEVICE_ID_CT_FC.
- */
- if (pcidev->device_id == BFA_PCI_DEVICE_ID_CT_FC)
- bfa_ioc_set_fcmode(&bfa->ioc);
-
- bfa_ioc_pci_init(&bfa->ioc, pcidev, BFI_MC_IOCFC);
- bfa_ioc_mbox_register(&bfa->ioc, bfa_mbox_isrs);
-
- bfa_iocfc_init_mem(bfa, bfad, cfg, pcidev);
- bfa_iocfc_mem_claim(bfa, cfg, meminfo);
- bfa_timer_init(&bfa->timer_mod);
-
- INIT_LIST_HEAD(&bfa->comp_q);
- for (i = 0; i < BFI_IOC_MAX_CQS; i++)
- INIT_LIST_HEAD(&bfa->reqq_waitq[i]);
-}
-
-/**
- * Query IOC memory requirement information.
- */
-void
-bfa_iocfc_detach(struct bfa_s *bfa)
-{
- bfa_ioc_detach(&bfa->ioc);
-}
-
-/**
- * Query IOC memory requirement information.
- */
-void
-bfa_iocfc_init(struct bfa_s *bfa)
-{
- bfa->iocfc.action = BFA_IOCFC_ACT_INIT;
- bfa_ioc_enable(&bfa->ioc);
-}
-
-/**
- * IOC start called from bfa_start(). Called to start IOC operations
- * at driver instantiation for this instance.
- */
-void
-bfa_iocfc_start(struct bfa_s *bfa)
-{
- if (bfa->iocfc.cfgdone)
- bfa_iocfc_start_submod(bfa);
-}
-
-/**
- * IOC stop called from bfa_stop(). Called only when driver is unloaded
- * for this instance.
- */
-void
-bfa_iocfc_stop(struct bfa_s *bfa)
-{
- bfa->iocfc.action = BFA_IOCFC_ACT_STOP;
-
- bfa->rme_process = BFA_FALSE;
- bfa_ioc_disable(&bfa->ioc);
-}
-
-void
-bfa_iocfc_isr(void *bfaarg, struct bfi_mbmsg_s *m)
-{
- struct bfa_s *bfa = bfaarg;
- struct bfa_iocfc_s *iocfc = &bfa->iocfc;
- union bfi_iocfc_i2h_msg_u *msg;
-
- msg = (union bfi_iocfc_i2h_msg_u *) m;
- bfa_trc(bfa, msg->mh.msg_id);
-
- switch (msg->mh.msg_id) {
- case BFI_IOCFC_I2H_CFG_REPLY:
- iocfc->cfg_reply = &msg->cfg_reply;
- bfa_iocfc_cfgrsp(bfa);
- break;
-
- case BFI_IOCFC_I2H_GET_STATS_RSP:
- if (iocfc->stats_busy == BFA_FALSE
- || iocfc->stats_status == BFA_STATUS_ETIMER)
- break;
-
- bfa_timer_stop(&iocfc->stats_timer);
- iocfc->stats_status = BFA_STATUS_OK;
- bfa_cb_queue(bfa, &iocfc->stats_hcb_qe, bfa_iocfc_stats_cb,
- bfa);
- break;
- case BFI_IOCFC_I2H_CLEAR_STATS_RSP:
- /*
- * check for timer pop before processing the rsp
- */
- if (iocfc->stats_busy == BFA_FALSE
- || iocfc->stats_status == BFA_STATUS_ETIMER)
- break;
-
- bfa_timer_stop(&iocfc->stats_timer);
- iocfc->stats_status = BFA_STATUS_OK;
- bfa_cb_queue(bfa, &iocfc->stats_hcb_qe,
- bfa_iocfc_stats_clr_cb, bfa);
- break;
- case BFI_IOCFC_I2H_UPDATEQ_RSP:
- iocfc->updateq_cbfn(iocfc->updateq_cbarg, BFA_STATUS_OK);
- break;
- default:
- bfa_assert(0);
- }
-}
-
-#ifndef BFA_BIOS_BUILD
-void
-bfa_adapter_get_attr(struct bfa_s *bfa, struct bfa_adapter_attr_s *ad_attr)
-{
- bfa_ioc_get_adapter_attr(&bfa->ioc, ad_attr);
-}
-
-u64
-bfa_adapter_get_id(struct bfa_s *bfa)
-{
- return bfa_ioc_get_adid(&bfa->ioc);
-}
-
-void
-bfa_iocfc_get_attr(struct bfa_s *bfa, struct bfa_iocfc_attr_s *attr)
-{
- struct bfa_iocfc_s *iocfc = &bfa->iocfc;
-
- attr->intr_attr.coalesce = iocfc->cfginfo->intr_attr.coalesce;
-
- attr->intr_attr.delay = iocfc->cfginfo->intr_attr.delay ?
- bfa_os_ntohs(iocfc->cfginfo->intr_attr.delay) :
- bfa_os_ntohs(iocfc->cfgrsp->intr_attr.delay);
-
- attr->intr_attr.latency = iocfc->cfginfo->intr_attr.latency ?
- bfa_os_ntohs(iocfc->cfginfo->intr_attr.latency) :
- bfa_os_ntohs(iocfc->cfgrsp->intr_attr.latency);
-
- attr->config = iocfc->cfg;
-
-}
-
-bfa_status_t
-bfa_iocfc_israttr_set(struct bfa_s *bfa, struct bfa_iocfc_intr_attr_s *attr)
-{
- struct bfa_iocfc_s *iocfc = &bfa->iocfc;
- struct bfi_iocfc_set_intr_req_s *m;
-
- iocfc->cfginfo->intr_attr.coalesce = attr->coalesce;
- iocfc->cfginfo->intr_attr.delay = bfa_os_htons(attr->delay);
- iocfc->cfginfo->intr_attr.latency = bfa_os_htons(attr->latency);
-
- if (!bfa_iocfc_is_operational(bfa))
- return BFA_STATUS_OK;
-
- m = bfa_reqq_next(bfa, BFA_REQQ_IOC);
- if (!m)
- return BFA_STATUS_DEVBUSY;
-
- bfi_h2i_set(m->mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_SET_INTR_REQ,
- bfa_lpuid(bfa));
- m->coalesce = iocfc->cfginfo->intr_attr.coalesce;
- m->delay = iocfc->cfginfo->intr_attr.delay;
- m->latency = iocfc->cfginfo->intr_attr.latency;
-
-
- bfa_trc(bfa, attr->delay);
- bfa_trc(bfa, attr->latency);
-
- bfa_reqq_produce(bfa, BFA_REQQ_IOC);
- return BFA_STATUS_OK;
-}
-
-void
-bfa_iocfc_set_snsbase(struct bfa_s *bfa, u64 snsbase_pa)
-{
- struct bfa_iocfc_s *iocfc = &bfa->iocfc;
-
- iocfc->cfginfo->sense_buf_len = (BFI_IOIM_SNSLEN - 1);
- bfa_dma_be_addr_set(iocfc->cfginfo->ioim_snsbase, snsbase_pa);
-}
-
-bfa_status_t
-bfa_iocfc_get_stats(struct bfa_s *bfa, struct bfa_iocfc_stats_s *stats,
- bfa_cb_ioc_t cbfn, void *cbarg)
-{
- struct bfa_iocfc_s *iocfc = &bfa->iocfc;
-
- if (iocfc->stats_busy) {
- bfa_trc(bfa, iocfc->stats_busy);
- return BFA_STATUS_DEVBUSY;
- }
-
- if (!bfa_iocfc_is_operational(bfa)) {
- bfa_trc(bfa, 0);
- return BFA_STATUS_IOC_NON_OP;
- }
-
- iocfc->stats_busy = BFA_TRUE;
- iocfc->stats_ret = stats;
- iocfc->stats_cbfn = cbfn;
- iocfc->stats_cbarg = cbarg;
-
- bfa_iocfc_stats_query(bfa);
-
- return BFA_STATUS_OK;
-}
-
-bfa_status_t
-bfa_iocfc_clear_stats(struct bfa_s *bfa, bfa_cb_ioc_t cbfn, void *cbarg)
-{
- struct bfa_iocfc_s *iocfc = &bfa->iocfc;
-
- if (iocfc->stats_busy) {
- bfa_trc(bfa, iocfc->stats_busy);
- return BFA_STATUS_DEVBUSY;
- }
-
- if (!bfa_iocfc_is_operational(bfa)) {
- bfa_trc(bfa, 0);
- return BFA_STATUS_IOC_NON_OP;
- }
-
- iocfc->stats_busy = BFA_TRUE;
- iocfc->stats_cbfn = cbfn;
- iocfc->stats_cbarg = cbarg;
-
- bfa_iocfc_stats_clear(bfa);
- return BFA_STATUS_OK;
-}
-
-/**
- * Enable IOC after it is disabled.
- */
-void
-bfa_iocfc_enable(struct bfa_s *bfa)
-{
- bfa_plog_str(bfa->plog, BFA_PL_MID_HAL, BFA_PL_EID_MISC, 0,
- "IOC Enable");
- bfa_ioc_enable(&bfa->ioc);
-}
-
-void
-bfa_iocfc_disable(struct bfa_s *bfa)
-{
- bfa_plog_str(bfa->plog, BFA_PL_MID_HAL, BFA_PL_EID_MISC, 0,
- "IOC Disable");
- bfa->iocfc.action = BFA_IOCFC_ACT_DISABLE;
-
- bfa->rme_process = BFA_FALSE;
- bfa_ioc_disable(&bfa->ioc);
-}
-
-
-bfa_boolean_t
-bfa_iocfc_is_operational(struct bfa_s *bfa)
-{
- return bfa_ioc_is_operational(&bfa->ioc) && bfa->iocfc.cfgdone;
-}
-
-/**
- * Return boot target port wwns -- read from boot information in flash.
- */
-void
-bfa_iocfc_get_bootwwns(struct bfa_s *bfa, u8 *nwwns, wwn_t *wwns)
-{
- struct bfa_iocfc_s *iocfc = &bfa->iocfc;
- struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp;
- int i;
-
- if (cfgrsp->pbc_cfg.boot_enabled && cfgrsp->pbc_cfg.nbluns) {
- bfa_trc(bfa, cfgrsp->pbc_cfg.nbluns);
- *nwwns = cfgrsp->pbc_cfg.nbluns;
- for (i = 0; i < cfgrsp->pbc_cfg.nbluns; i++)
- wwns[i] = cfgrsp->pbc_cfg.blun[i].tgt_pwwn;
-
- return;
- }
-
- *nwwns = cfgrsp->bootwwns.nwwns;
- memcpy(wwns, cfgrsp->bootwwns.wwn, sizeof(cfgrsp->bootwwns.wwn));
-}
-
-void
-bfa_iocfc_get_pbc_boot_cfg(struct bfa_s *bfa, struct bfa_boot_pbc_s *pbcfg)
-{
- struct bfa_iocfc_s *iocfc = &bfa->iocfc;
- struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp;
-
- pbcfg->enable = cfgrsp->pbc_cfg.boot_enabled;
- pbcfg->nbluns = cfgrsp->pbc_cfg.nbluns;
- pbcfg->speed = cfgrsp->pbc_cfg.port_speed;
- memcpy(pbcfg->pblun, cfgrsp->pbc_cfg.blun, sizeof(pbcfg->pblun));
-}
-
-int
-bfa_iocfc_get_pbc_vports(struct bfa_s *bfa, struct bfi_pbc_vport_s *pbc_vport)
-{
- struct bfa_iocfc_s *iocfc = &bfa->iocfc;
- struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp;
-
- memcpy(pbc_vport, cfgrsp->pbc_cfg.vport, sizeof(cfgrsp->pbc_cfg.vport));
- return cfgrsp->pbc_cfg.nvports;
-}
-
-
-#endif
-
-
diff --git a/drivers/scsi/bfa/bfa_iocfc.h b/drivers/scsi/bfa/bfa_iocfc.h
deleted file mode 100644
index 74a6a048d1fd..000000000000
--- a/drivers/scsi/bfa/bfa_iocfc.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_IOCFC_H__
-#define __BFA_IOCFC_H__
-
-#include <bfa_ioc.h>
-#include <bfa.h>
-#include <bfi/bfi_iocfc.h>
-#include <bfi/bfi_pbc.h>
-#include <bfa_callback_priv.h>
-
-#define BFA_REQQ_NELEMS_MIN (4)
-#define BFA_RSPQ_NELEMS_MIN (4)
-
-struct bfa_iocfc_regs_s {
- bfa_os_addr_t intr_status;
- bfa_os_addr_t intr_mask;
- bfa_os_addr_t cpe_q_pi[BFI_IOC_MAX_CQS];
- bfa_os_addr_t cpe_q_ci[BFI_IOC_MAX_CQS];
- bfa_os_addr_t cpe_q_depth[BFI_IOC_MAX_CQS];
- bfa_os_addr_t cpe_q_ctrl[BFI_IOC_MAX_CQS];
- bfa_os_addr_t rme_q_ci[BFI_IOC_MAX_CQS];
- bfa_os_addr_t rme_q_pi[BFI_IOC_MAX_CQS];
- bfa_os_addr_t rme_q_depth[BFI_IOC_MAX_CQS];
- bfa_os_addr_t rme_q_ctrl[BFI_IOC_MAX_CQS];
-};
-
-/**
- * MSIX vector handlers
- */
-#define BFA_MSIX_MAX_VECTORS 22
-typedef void (*bfa_msix_handler_t)(struct bfa_s *bfa, int vec);
-struct bfa_msix_s {
- int nvecs;
- bfa_msix_handler_t handler[BFA_MSIX_MAX_VECTORS];
-};
-
-/**
- * Chip specific interfaces
- */
-struct bfa_hwif_s {
- void (*hw_reginit)(struct bfa_s *bfa);
- void (*hw_reqq_ack)(struct bfa_s *bfa, int reqq);
- void (*hw_rspq_ack)(struct bfa_s *bfa, int rspq);
- void (*hw_msix_init)(struct bfa_s *bfa, int nvecs);
- void (*hw_msix_install)(struct bfa_s *bfa);
- void (*hw_msix_uninstall)(struct bfa_s *bfa);
- void (*hw_isr_mode_set)(struct bfa_s *bfa, bfa_boolean_t msix);
- void (*hw_msix_getvecs)(struct bfa_s *bfa, u32 *vecmap,
- u32 *nvecs, u32 *maxvec);
- void (*hw_msix_get_rme_range) (struct bfa_s *bfa, u32 *start,
- u32 *end);
-};
-typedef void (*bfa_cb_iocfc_t) (void *cbarg, enum bfa_status status);
-
-struct bfa_iocfc_s {
- struct bfa_s *bfa;
- struct bfa_iocfc_cfg_s cfg;
- int action;
-
- u32 req_cq_pi[BFI_IOC_MAX_CQS];
- u32 rsp_cq_ci[BFI_IOC_MAX_CQS];
-
- struct bfa_cb_qe_s init_hcb_qe;
- struct bfa_cb_qe_s stop_hcb_qe;
- struct bfa_cb_qe_s dis_hcb_qe;
- struct bfa_cb_qe_s stats_hcb_qe;
- bfa_boolean_t cfgdone;
-
- struct bfa_dma_s cfg_info;
- struct bfi_iocfc_cfg_s *cfginfo;
- struct bfa_dma_s cfgrsp_dma;
- struct bfi_iocfc_cfgrsp_s *cfgrsp;
- struct bfi_iocfc_cfg_reply_s *cfg_reply;
-
- u8 *stats_kva;
- u64 stats_pa;
- struct bfa_fw_stats_s *fw_stats;
- struct bfa_timer_s stats_timer; /* timer */
- struct bfa_iocfc_stats_s *stats_ret; /* driver stats location */
- bfa_status_t stats_status; /* stats/statsclr status */
- bfa_boolean_t stats_busy; /* outstanding stats */
- bfa_cb_ioc_t stats_cbfn; /* driver callback function */
- void *stats_cbarg; /* user callback arg */
-
- struct bfa_dma_s req_cq_ba[BFI_IOC_MAX_CQS];
- struct bfa_dma_s req_cq_shadow_ci[BFI_IOC_MAX_CQS];
- struct bfa_dma_s rsp_cq_ba[BFI_IOC_MAX_CQS];
- struct bfa_dma_s rsp_cq_shadow_pi[BFI_IOC_MAX_CQS];
- struct bfa_iocfc_regs_s bfa_regs; /* BFA device registers */
- struct bfa_hwif_s hwif;
-
- bfa_cb_iocfc_t updateq_cbfn; /* bios callback function */
- void *updateq_cbarg; /* bios callback arg */
- u32 intr_mask;
-};
-
-#define bfa_lpuid(__bfa) bfa_ioc_portid(&(__bfa)->ioc)
-#define bfa_msix_init(__bfa, __nvecs) \
- ((__bfa)->iocfc.hwif.hw_msix_init(__bfa, __nvecs))
-#define bfa_msix_install(__bfa) \
- ((__bfa)->iocfc.hwif.hw_msix_install(__bfa))
-#define bfa_msix_uninstall(__bfa) \
- ((__bfa)->iocfc.hwif.hw_msix_uninstall(__bfa))
-#define bfa_isr_mode_set(__bfa, __msix) \
- ((__bfa)->iocfc.hwif.hw_isr_mode_set(__bfa, __msix))
-#define bfa_msix_getvecs(__bfa, __vecmap, __nvecs, __maxvec) \
- ((__bfa)->iocfc.hwif.hw_msix_getvecs(__bfa, __vecmap, \
- __nvecs, __maxvec))
-#define bfa_msix_get_rme_range(__bfa, __start, __end) \
- ((__bfa)->iocfc.hwif.hw_msix_get_rme_range(__bfa, __start, __end))
-
-/*
- * FC specific IOC functions.
- */
-void bfa_iocfc_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
- u32 *dm_len);
-void bfa_iocfc_attach(struct bfa_s *bfa, void *bfad,
- struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo,
- struct bfa_pcidev_s *pcidev);
-void bfa_iocfc_detach(struct bfa_s *bfa);
-void bfa_iocfc_init(struct bfa_s *bfa);
-void bfa_iocfc_start(struct bfa_s *bfa);
-void bfa_iocfc_stop(struct bfa_s *bfa);
-void bfa_iocfc_isr(void *bfa, struct bfi_mbmsg_s *msg);
-void bfa_iocfc_set_snsbase(struct bfa_s *bfa, u64 snsbase_pa);
-bfa_boolean_t bfa_iocfc_is_operational(struct bfa_s *bfa);
-void bfa_iocfc_reset_queues(struct bfa_s *bfa);
-void bfa_iocfc_updateq(struct bfa_s *bfa, u32 reqq_ba, u32 rspq_ba,
- u32 reqq_sci, u32 rspq_spi,
- bfa_cb_iocfc_t cbfn, void *cbarg);
-
-void bfa_msix_all(struct bfa_s *bfa, int vec);
-void bfa_msix_reqq(struct bfa_s *bfa, int vec);
-void bfa_msix_rspq(struct bfa_s *bfa, int vec);
-void bfa_msix_lpu_err(struct bfa_s *bfa, int vec);
-
-void bfa_hwcb_reginit(struct bfa_s *bfa);
-void bfa_hwcb_reqq_ack(struct bfa_s *bfa, int rspq);
-void bfa_hwcb_rspq_ack(struct bfa_s *bfa, int rspq);
-void bfa_hwcb_msix_init(struct bfa_s *bfa, int nvecs);
-void bfa_hwcb_msix_install(struct bfa_s *bfa);
-void bfa_hwcb_msix_uninstall(struct bfa_s *bfa);
-void bfa_hwcb_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix);
-void bfa_hwcb_msix_getvecs(struct bfa_s *bfa, u32 *vecmap,
- u32 *nvecs, u32 *maxvec);
-void bfa_hwcb_msix_get_rme_range(struct bfa_s *bfa, u32 *start, u32 *end);
-void bfa_hwct_reginit(struct bfa_s *bfa);
-void bfa_hwct_reqq_ack(struct bfa_s *bfa, int rspq);
-void bfa_hwct_rspq_ack(struct bfa_s *bfa, int rspq);
-void bfa_hwct_msix_init(struct bfa_s *bfa, int nvecs);
-void bfa_hwct_msix_install(struct bfa_s *bfa);
-void bfa_hwct_msix_uninstall(struct bfa_s *bfa);
-void bfa_hwct_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix);
-void bfa_hwct_msix_getvecs(struct bfa_s *bfa, u32 *vecmap,
- u32 *nvecs, u32 *maxvec);
-void bfa_hwct_msix_get_rme_range(struct bfa_s *bfa, u32 *start, u32 *end);
-
-void bfa_com_meminfo(bfa_boolean_t mincfg, u32 *dm_len);
-void bfa_com_attach(struct bfa_s *bfa, struct bfa_meminfo_s *mi,
- bfa_boolean_t mincfg);
-void bfa_iocfc_get_bootwwns(struct bfa_s *bfa, u8 *nwwns, wwn_t *wwns);
-void bfa_iocfc_get_pbc_boot_cfg(struct bfa_s *bfa,
- struct bfa_boot_pbc_s *pbcfg);
-int bfa_iocfc_get_pbc_vports(struct bfa_s *bfa,
- struct bfi_pbc_vport_s *pbc_vport);
-
-#endif /* __BFA_IOCFC_H__ */
-
diff --git a/drivers/scsi/bfa/bfa_iocfc_q.c b/drivers/scsi/bfa/bfa_iocfc_q.c
deleted file mode 100644
index 500a17df40b2..000000000000
--- a/drivers/scsi/bfa/bfa_iocfc_q.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#include <bfa.h>
-#include "bfa_intr_priv.h"
-
-BFA_TRC_FILE(HAL, IOCFC_Q);
-
-void
-bfa_iocfc_updateq(struct bfa_s *bfa, u32 reqq_ba, u32 rspq_ba,
- u32 reqq_sci, u32 rspq_spi, bfa_cb_iocfc_t cbfn,
- void *cbarg)
-{
- struct bfa_iocfc_s *iocfc = &bfa->iocfc;
- struct bfi_iocfc_updateq_req_s updateq_req;
-
- iocfc->updateq_cbfn = cbfn;
- iocfc->updateq_cbarg = cbarg;
-
- bfi_h2i_set(updateq_req.mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_UPDATEQ_REQ,
- bfa_lpuid(bfa));
-
- updateq_req.reqq_ba = bfa_os_htonl(reqq_ba);
- updateq_req.rspq_ba = bfa_os_htonl(rspq_ba);
- updateq_req.reqq_sci = bfa_os_htonl(reqq_sci);
- updateq_req.rspq_spi = bfa_os_htonl(rspq_spi);
-
- bfa_ioc_mbox_send(&bfa->ioc, &updateq_req,
- sizeof(struct bfi_iocfc_updateq_req_s));
-}
diff --git a/drivers/scsi/bfa/bfa_ioim.c b/drivers/scsi/bfa/bfa_ioim.c
deleted file mode 100644
index bdfdc19915f8..000000000000
--- a/drivers/scsi/bfa/bfa_ioim.c
+++ /dev/null
@@ -1,1364 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#include <bfa.h>
-#include <cs/bfa_debug.h>
-#include <bfa_cb_ioim_macros.h>
-
-BFA_TRC_FILE(HAL, IOIM);
-
-/*
- * forward declarations.
- */
-static bfa_boolean_t bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim);
-static bfa_boolean_t bfa_ioim_sge_setup(struct bfa_ioim_s *ioim);
-static void bfa_ioim_sgpg_setup(struct bfa_ioim_s *ioim);
-static bfa_boolean_t bfa_ioim_send_abort(struct bfa_ioim_s *ioim);
-static void bfa_ioim_notify_cleanup(struct bfa_ioim_s *ioim);
-static void __bfa_cb_ioim_good_comp(void *cbarg, bfa_boolean_t complete);
-static void __bfa_cb_ioim_comp(void *cbarg, bfa_boolean_t complete);
-static void __bfa_cb_ioim_abort(void *cbarg, bfa_boolean_t complete);
-static void __bfa_cb_ioim_failed(void *cbarg, bfa_boolean_t complete);
-static void __bfa_cb_ioim_pathtov(void *cbarg, bfa_boolean_t complete);
-
-/**
- * bfa_ioim_sm
- */
-
-/**
- * IO state machine events
- */
-enum bfa_ioim_event {
- BFA_IOIM_SM_START = 1, /* io start request from host */
- BFA_IOIM_SM_COMP_GOOD = 2, /* io good comp, resource free */
- BFA_IOIM_SM_COMP = 3, /* io comp, resource is free */
- BFA_IOIM_SM_COMP_UTAG = 4, /* io comp, resource is free */
- BFA_IOIM_SM_DONE = 5, /* io comp, resource not free */
- BFA_IOIM_SM_FREE = 6, /* io resource is freed */
- BFA_IOIM_SM_ABORT = 7, /* abort request from scsi stack */
- BFA_IOIM_SM_ABORT_COMP = 8, /* abort from f/w */
- BFA_IOIM_SM_ABORT_DONE = 9, /* abort completion from f/w */
- BFA_IOIM_SM_QRESUME = 10, /* CQ space available to queue IO */
- BFA_IOIM_SM_SGALLOCED = 11, /* SG page allocation successful */
- BFA_IOIM_SM_SQRETRY = 12, /* sequence recovery retry */
- BFA_IOIM_SM_HCB = 13, /* bfa callback complete */
- BFA_IOIM_SM_CLEANUP = 14, /* IO cleanup from itnim */
- BFA_IOIM_SM_TMSTART = 15, /* IO cleanup from tskim */
- BFA_IOIM_SM_TMDONE = 16, /* IO cleanup from tskim */
- BFA_IOIM_SM_HWFAIL = 17, /* IOC h/w failure event */
- BFA_IOIM_SM_IOTOV = 18, /* ITN offline TOV */
-};
-
-/*
- * forward declaration of IO state machine
- */
-static void bfa_ioim_sm_uninit(struct bfa_ioim_s *ioim,
- enum bfa_ioim_event event);
-static void bfa_ioim_sm_sgalloc(struct bfa_ioim_s *ioim,
- enum bfa_ioim_event event);
-static void bfa_ioim_sm_active(struct bfa_ioim_s *ioim,
- enum bfa_ioim_event event);
-static void bfa_ioim_sm_abort(struct bfa_ioim_s *ioim,
- enum bfa_ioim_event event);
-static void bfa_ioim_sm_cleanup(struct bfa_ioim_s *ioim,
- enum bfa_ioim_event event);
-static void bfa_ioim_sm_qfull(struct bfa_ioim_s *ioim,
- enum bfa_ioim_event event);
-static void bfa_ioim_sm_abort_qfull(struct bfa_ioim_s *ioim,
- enum bfa_ioim_event event);
-static void bfa_ioim_sm_cleanup_qfull(struct bfa_ioim_s *ioim,
- enum bfa_ioim_event event);
-static void bfa_ioim_sm_hcb(struct bfa_ioim_s *ioim,
- enum bfa_ioim_event event);
-static void bfa_ioim_sm_hcb_free(struct bfa_ioim_s *ioim,
- enum bfa_ioim_event event);
-static void bfa_ioim_sm_resfree(struct bfa_ioim_s *ioim,
- enum bfa_ioim_event event);
-
-/**
- * IO is not started (unallocated).
- */
-static void
-bfa_ioim_sm_uninit(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
-{
- bfa_trc_fp(ioim->bfa, ioim->iotag);
- bfa_trc_fp(ioim->bfa, event);
-
- switch (event) {
- case BFA_IOIM_SM_START:
- if (!bfa_itnim_is_online(ioim->itnim)) {
- if (!bfa_itnim_hold_io(ioim->itnim)) {
- bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
- list_del(&ioim->qe);
- list_add_tail(&ioim->qe,
- &ioim->fcpim->ioim_comp_q);
- bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
- __bfa_cb_ioim_pathtov, ioim);
- } else {
- list_del(&ioim->qe);
- list_add_tail(&ioim->qe,
- &ioim->itnim->pending_q);
- }
- break;
- }
-
- if (ioim->nsges > BFI_SGE_INLINE) {
- if (!bfa_ioim_sge_setup(ioim)) {
- bfa_sm_set_state(ioim, bfa_ioim_sm_sgalloc);
- return;
- }
- }
-
- if (!bfa_ioim_send_ioreq(ioim)) {
- bfa_sm_set_state(ioim, bfa_ioim_sm_qfull);
- break;
- }
-
- bfa_sm_set_state(ioim, bfa_ioim_sm_active);
- break;
-
- case BFA_IOIM_SM_IOTOV:
- bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
- list_del(&ioim->qe);
- list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
- bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
- __bfa_cb_ioim_pathtov, ioim);
- break;
-
- case BFA_IOIM_SM_ABORT:
- /**
- * IO in pending queue can get abort requests. Complete abort
- * requests immediately.
- */
- bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
- bfa_assert(bfa_q_is_on_q(&ioim->itnim->pending_q, ioim));
- bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
- ioim);
- break;
-
- default:
- bfa_sm_fault(ioim->bfa, event);
- }
-}
-
-/**
- * IO is waiting for SG pages.
- */
-static void
-bfa_ioim_sm_sgalloc(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
-{
- bfa_trc(ioim->bfa, ioim->iotag);
- bfa_trc(ioim->bfa, event);
-
- switch (event) {
- case BFA_IOIM_SM_SGALLOCED:
- if (!bfa_ioim_send_ioreq(ioim)) {
- bfa_sm_set_state(ioim, bfa_ioim_sm_qfull);
- break;
- }
- bfa_sm_set_state(ioim, bfa_ioim_sm_active);
- break;
-
- case BFA_IOIM_SM_CLEANUP:
- bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
- bfa_sgpg_wcancel(ioim->bfa, &ioim->iosp->sgpg_wqe);
- bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
- ioim);
- bfa_ioim_notify_cleanup(ioim);
- break;
-
- case BFA_IOIM_SM_ABORT:
- bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
- bfa_sgpg_wcancel(ioim->bfa, &ioim->iosp->sgpg_wqe);
- list_del(&ioim->qe);
- list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
- bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
- ioim);
- break;
-
- case BFA_IOIM_SM_HWFAIL:
- bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
- bfa_sgpg_wcancel(ioim->bfa, &ioim->iosp->sgpg_wqe);
- list_del(&ioim->qe);
- list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
- bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
- ioim);
- break;
-
- default:
- bfa_sm_fault(ioim->bfa, event);
- }
-}
-
-/**
- * IO is active.
- */
-static void
-bfa_ioim_sm_active(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
-{
- bfa_trc_fp(ioim->bfa, ioim->iotag);
- bfa_trc_fp(ioim->bfa, event);
-
- switch (event) {
- case BFA_IOIM_SM_COMP_GOOD:
- bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
- list_del(&ioim->qe);
- list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
- bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
- __bfa_cb_ioim_good_comp, ioim);
- break;
-
- case BFA_IOIM_SM_COMP:
- bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
- list_del(&ioim->qe);
- list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
- bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_comp,
- ioim);
- break;
-
- case BFA_IOIM_SM_DONE:
- bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
- list_del(&ioim->qe);
- list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
- bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_comp,
- ioim);
- break;
-
- case BFA_IOIM_SM_ABORT:
- ioim->iosp->abort_explicit = BFA_TRUE;
- ioim->io_cbfn = __bfa_cb_ioim_abort;
-
- if (bfa_ioim_send_abort(ioim))
- bfa_sm_set_state(ioim, bfa_ioim_sm_abort);
- else {
- bfa_sm_set_state(ioim, bfa_ioim_sm_abort_qfull);
- bfa_reqq_wait(ioim->bfa, ioim->reqq,
- &ioim->iosp->reqq_wait);
- }
- break;
-
- case BFA_IOIM_SM_CLEANUP:
- ioim->iosp->abort_explicit = BFA_FALSE;
- ioim->io_cbfn = __bfa_cb_ioim_failed;
-
- if (bfa_ioim_send_abort(ioim))
- bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup);
- else {
- bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup_qfull);
- bfa_reqq_wait(ioim->bfa, ioim->reqq,
- &ioim->iosp->reqq_wait);
- }
- break;
-
- case BFA_IOIM_SM_HWFAIL:
- bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
- list_del(&ioim->qe);
- list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
- bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
- ioim);
- break;
-
- default:
- bfa_sm_fault(ioim->bfa, event);
- }
-}
-
-/**
- * IO is being aborted, waiting for completion from firmware.
- */
-static void
-bfa_ioim_sm_abort(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
-{
- bfa_trc(ioim->bfa, ioim->iotag);
- bfa_trc(ioim->bfa, event);
-
- switch (event) {
- case BFA_IOIM_SM_COMP_GOOD:
- case BFA_IOIM_SM_COMP:
- case BFA_IOIM_SM_DONE:
- case BFA_IOIM_SM_FREE:
- break;
-
- case BFA_IOIM_SM_ABORT_DONE:
- bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
- bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
- ioim);
- break;
-
- case BFA_IOIM_SM_ABORT_COMP:
- bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
- list_del(&ioim->qe);
- list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
- bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
- ioim);
- break;
-
- case BFA_IOIM_SM_COMP_UTAG:
- bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
- list_del(&ioim->qe);
- list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
- bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
- ioim);
- break;
-
- case BFA_IOIM_SM_CLEANUP:
- bfa_assert(ioim->iosp->abort_explicit == BFA_TRUE);
- ioim->iosp->abort_explicit = BFA_FALSE;
-
- if (bfa_ioim_send_abort(ioim))
- bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup);
- else {
- bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup_qfull);
- bfa_reqq_wait(ioim->bfa, ioim->reqq,
- &ioim->iosp->reqq_wait);
- }
- break;
-
- case BFA_IOIM_SM_HWFAIL:
- bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
- list_del(&ioim->qe);
- list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
- bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
- ioim);
- break;
-
- default:
- bfa_sm_fault(ioim->bfa, event);
- }
-}
-
-/**
- * IO is being cleaned up (implicit abort), waiting for completion from
- * firmware.
- */
-static void
-bfa_ioim_sm_cleanup(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
-{
- bfa_trc(ioim->bfa, ioim->iotag);
- bfa_trc(ioim->bfa, event);
-
- switch (event) {
- case BFA_IOIM_SM_COMP_GOOD:
- case BFA_IOIM_SM_COMP:
- case BFA_IOIM_SM_DONE:
- case BFA_IOIM_SM_FREE:
- break;
-
- case BFA_IOIM_SM_ABORT:
- /**
- * IO is already being aborted implicitly
- */
- ioim->io_cbfn = __bfa_cb_ioim_abort;
- break;
-
- case BFA_IOIM_SM_ABORT_DONE:
- bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
- bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
- bfa_ioim_notify_cleanup(ioim);
- break;
-
- case BFA_IOIM_SM_ABORT_COMP:
- bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
- bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
- bfa_ioim_notify_cleanup(ioim);
- break;
-
- case BFA_IOIM_SM_COMP_UTAG:
- bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
- bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
- bfa_ioim_notify_cleanup(ioim);
- break;
-
- case BFA_IOIM_SM_HWFAIL:
- bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
- list_del(&ioim->qe);
- list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
- bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
- ioim);
- break;
-
- case BFA_IOIM_SM_CLEANUP:
- /**
- * IO can be in cleanup state already due to TM command. 2nd cleanup
- * request comes from ITN offline event.
- */
- break;
-
- default:
- bfa_sm_fault(ioim->bfa, event);
- }
-}
-
-/**
- * IO is waiting for room in request CQ
- */
-static void
-bfa_ioim_sm_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
-{
- bfa_trc(ioim->bfa, ioim->iotag);
- bfa_trc(ioim->bfa, event);
-
- switch (event) {
- case BFA_IOIM_SM_QRESUME:
- bfa_sm_set_state(ioim, bfa_ioim_sm_active);
- bfa_ioim_send_ioreq(ioim);
- break;
-
- case BFA_IOIM_SM_ABORT:
- bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
- bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
- list_del(&ioim->qe);
- list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
- bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
- ioim);
- break;
-
- case BFA_IOIM_SM_CLEANUP:
- bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
- bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
- bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
- ioim);
- bfa_ioim_notify_cleanup(ioim);
- break;
-
- case BFA_IOIM_SM_HWFAIL:
- bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
- bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
- list_del(&ioim->qe);
- list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
- bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
- ioim);
- break;
-
- default:
- bfa_sm_fault(ioim->bfa, event);
- }
-}
-
-/**
- * Active IO is being aborted, waiting for room in request CQ.
- */
-static void
-bfa_ioim_sm_abort_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
-{
- bfa_trc(ioim->bfa, ioim->iotag);
- bfa_trc(ioim->bfa, event);
-
- switch (event) {
- case BFA_IOIM_SM_QRESUME:
- bfa_sm_set_state(ioim, bfa_ioim_sm_abort);
- bfa_ioim_send_abort(ioim);
- break;
-
- case BFA_IOIM_SM_CLEANUP:
- bfa_assert(ioim->iosp->abort_explicit == BFA_TRUE);
- ioim->iosp->abort_explicit = BFA_FALSE;
- bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup_qfull);
- break;
-
- case BFA_IOIM_SM_COMP_GOOD:
- case BFA_IOIM_SM_COMP:
- bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
- bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
- list_del(&ioim->qe);
- list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
- bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
- ioim);
- break;
-
- case BFA_IOIM_SM_DONE:
- bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
- bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
- list_del(&ioim->qe);
- list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
- bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
- ioim);
- break;
-
- case BFA_IOIM_SM_HWFAIL:
- bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
- bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
- list_del(&ioim->qe);
- list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
- bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
- ioim);
- break;
-
- default:
- bfa_sm_fault(ioim->bfa, event);
- }
-}
-
-/**
- * Active IO is being cleaned up, waiting for room in request CQ.
- */
-static void
-bfa_ioim_sm_cleanup_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
-{
- bfa_trc(ioim->bfa, ioim->iotag);
- bfa_trc(ioim->bfa, event);
-
- switch (event) {
- case BFA_IOIM_SM_QRESUME:
- bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup);
- bfa_ioim_send_abort(ioim);
- break;
-
- case BFA_IOIM_SM_ABORT:
- /**
- * IO is already being cleaned up implicitly
- */
- ioim->io_cbfn = __bfa_cb_ioim_abort;
- break;
-
- case BFA_IOIM_SM_COMP_GOOD:
- case BFA_IOIM_SM_COMP:
- bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
- bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
- bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
- bfa_ioim_notify_cleanup(ioim);
- break;
-
- case BFA_IOIM_SM_DONE:
- bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
- bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
- bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
- bfa_ioim_notify_cleanup(ioim);
- break;
-
- case BFA_IOIM_SM_HWFAIL:
- bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
- bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
- list_del(&ioim->qe);
- list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
- bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
- ioim);
- break;
-
- default:
- bfa_sm_fault(ioim->bfa, event);
- }
-}
-
-/**
- * IO bfa callback is pending.
- */
-static void
-bfa_ioim_sm_hcb(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
-{
- bfa_trc_fp(ioim->bfa, ioim->iotag);
- bfa_trc_fp(ioim->bfa, event);
-
- switch (event) {
- case BFA_IOIM_SM_HCB:
- bfa_sm_set_state(ioim, bfa_ioim_sm_uninit);
- bfa_ioim_free(ioim);
- bfa_cb_ioim_resfree(ioim->bfa->bfad);
- break;
-
- case BFA_IOIM_SM_CLEANUP:
- bfa_ioim_notify_cleanup(ioim);
- break;
-
- case BFA_IOIM_SM_HWFAIL:
- break;
-
- default:
- bfa_sm_fault(ioim->bfa, event);
- }
-}
-
-/**
- * IO bfa callback is pending. IO resource cannot be freed.
- */
-static void
-bfa_ioim_sm_hcb_free(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
-{
- bfa_trc(ioim->bfa, ioim->iotag);
- bfa_trc(ioim->bfa, event);
-
- switch (event) {
- case BFA_IOIM_SM_HCB:
- bfa_sm_set_state(ioim, bfa_ioim_sm_resfree);
- list_del(&ioim->qe);
- list_add_tail(&ioim->qe, &ioim->fcpim->ioim_resfree_q);
- break;
-
- case BFA_IOIM_SM_FREE:
- bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
- break;
-
- case BFA_IOIM_SM_CLEANUP:
- bfa_ioim_notify_cleanup(ioim);
- break;
-
- case BFA_IOIM_SM_HWFAIL:
- bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
- break;
-
- default:
- bfa_sm_fault(ioim->bfa, event);
- }
-}
-
-/**
- * IO is completed, waiting resource free from firmware.
- */
-static void
-bfa_ioim_sm_resfree(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
-{
- bfa_trc(ioim->bfa, ioim->iotag);
- bfa_trc(ioim->bfa, event);
-
- switch (event) {
- case BFA_IOIM_SM_FREE:
- bfa_sm_set_state(ioim, bfa_ioim_sm_uninit);
- bfa_ioim_free(ioim);
- bfa_cb_ioim_resfree(ioim->bfa->bfad);
- break;
-
- case BFA_IOIM_SM_CLEANUP:
- bfa_ioim_notify_cleanup(ioim);
- break;
-
- case BFA_IOIM_SM_HWFAIL:
- break;
-
- default:
- bfa_sm_fault(ioim->bfa, event);
- }
-}
-
-
-
-/**
- * bfa_ioim_private
- */
-
-static void
-__bfa_cb_ioim_good_comp(void *cbarg, bfa_boolean_t complete)
-{
- struct bfa_ioim_s *ioim = cbarg;
-
- if (!complete) {
- bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
- return;
- }
-
- bfa_cb_ioim_good_comp(ioim->bfa->bfad, ioim->dio);
-}
-
-static void
-__bfa_cb_ioim_comp(void *cbarg, bfa_boolean_t complete)
-{
- struct bfa_ioim_s *ioim = cbarg;
- struct bfi_ioim_rsp_s *m;
- u8 *snsinfo = NULL;
- u8 sns_len = 0;
- s32 residue = 0;
-
- if (!complete) {
- bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
- return;
- }
-
- m = (struct bfi_ioim_rsp_s *) &ioim->iosp->comp_rspmsg;
- if (m->io_status == BFI_IOIM_STS_OK) {
- /**
- * setup sense information, if present
- */
- if (m->scsi_status == SCSI_STATUS_CHECK_CONDITION
- && m->sns_len) {
- sns_len = m->sns_len;
- snsinfo = ioim->iosp->snsinfo;
- }
-
- /**
- * setup residue value correctly for normal completions
- */
- if (m->resid_flags == FCP_RESID_UNDER)
- residue = bfa_os_ntohl(m->residue);
- if (m->resid_flags == FCP_RESID_OVER) {
- residue = bfa_os_ntohl(m->residue);
- residue = -residue;
- }
- }
-
- bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, m->io_status,
- m->scsi_status, sns_len, snsinfo, residue);
-}
-
-static void
-__bfa_cb_ioim_failed(void *cbarg, bfa_boolean_t complete)
-{
- struct bfa_ioim_s *ioim = cbarg;
-
- if (!complete) {
- bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
- return;
- }
-
- bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_ABORTED,
- 0, 0, NULL, 0);
-}
-
-static void
-__bfa_cb_ioim_pathtov(void *cbarg, bfa_boolean_t complete)
-{
- struct bfa_ioim_s *ioim = cbarg;
-
- if (!complete) {
- bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
- return;
- }
-
- bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_PATHTOV,
- 0, 0, NULL, 0);
-}
-
-static void
-__bfa_cb_ioim_abort(void *cbarg, bfa_boolean_t complete)
-{
- struct bfa_ioim_s *ioim = cbarg;
-
- if (!complete) {
- bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
- return;
- }
-
- bfa_cb_ioim_abort(ioim->bfa->bfad, ioim->dio);
-}
-
-static void
-bfa_ioim_sgpg_alloced(void *cbarg)
-{
- struct bfa_ioim_s *ioim = cbarg;
-
- ioim->nsgpgs = BFA_SGPG_NPAGE(ioim->nsges);
- list_splice_tail_init(&ioim->iosp->sgpg_wqe.sgpg_q, &ioim->sgpg_q);
- bfa_ioim_sgpg_setup(ioim);
- bfa_sm_send_event(ioim, BFA_IOIM_SM_SGALLOCED);
-}
-
-/**
- * Send I/O request to firmware.
- */
-static bfa_boolean_t
-bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim)
-{
- struct bfa_itnim_s *itnim = ioim->itnim;
- struct bfi_ioim_req_s *m;
- static struct fcp_cmnd_s cmnd_z0 = { 0 };
- struct bfi_sge_s *sge;
- u32 pgdlen = 0;
- u64 addr;
- struct scatterlist *sg;
- struct scsi_cmnd *cmnd = (struct scsi_cmnd *) ioim->dio;
-
- /**
- * check for room in queue to send request now
- */
- m = bfa_reqq_next(ioim->bfa, ioim->reqq);
- if (!m) {
- bfa_reqq_wait(ioim->bfa, ioim->reqq,
- &ioim->iosp->reqq_wait);
- return BFA_FALSE;
- }
-
- /**
- * build i/o request message next
- */
- m->io_tag = bfa_os_htons(ioim->iotag);
- m->rport_hdl = ioim->itnim->rport->fw_handle;
- m->io_timeout = bfa_cb_ioim_get_timeout(ioim->dio);
-
- /**
- * build inline IO SG element here
- */
- sge = &m->sges[0];
- if (ioim->nsges) {
- sg = (struct scatterlist *)scsi_sglist(cmnd);
- addr = bfa_os_sgaddr(sg_dma_address(sg));
- sge->sga = *(union bfi_addr_u *) &addr;
- pgdlen = sg_dma_len(sg);
- sge->sg_len = pgdlen;
- sge->flags = (ioim->nsges > BFI_SGE_INLINE) ?
- BFI_SGE_DATA_CPL : BFI_SGE_DATA_LAST;
- bfa_sge_to_be(sge);
- sge++;
- }
-
- if (ioim->nsges > BFI_SGE_INLINE) {
- sge->sga = ioim->sgpg->sgpg_pa;
- } else {
- sge->sga.a32.addr_lo = 0;
- sge->sga.a32.addr_hi = 0;
- }
- sge->sg_len = pgdlen;
- sge->flags = BFI_SGE_PGDLEN;
- bfa_sge_to_be(sge);
-
- /**
- * set up I/O command parameters
- */
- bfa_os_assign(m->cmnd, cmnd_z0);
- m->cmnd.lun = bfa_cb_ioim_get_lun(ioim->dio);
- m->cmnd.iodir = bfa_cb_ioim_get_iodir(ioim->dio);
- bfa_os_assign(m->cmnd.cdb,
- *(struct scsi_cdb_s *)bfa_cb_ioim_get_cdb(ioim->dio));
- m->cmnd.fcp_dl = bfa_os_htonl(bfa_cb_ioim_get_size(ioim->dio));
-
- /**
- * set up I/O message header
- */
- switch (m->cmnd.iodir) {
- case FCP_IODIR_READ:
- bfi_h2i_set(m->mh, BFI_MC_IOIM_READ, 0, bfa_lpuid(ioim->bfa));
- bfa_stats(itnim, input_reqs);
- break;
- case FCP_IODIR_WRITE:
- bfi_h2i_set(m->mh, BFI_MC_IOIM_WRITE, 0, bfa_lpuid(ioim->bfa));
- bfa_stats(itnim, output_reqs);
- break;
- case FCP_IODIR_RW:
- bfa_stats(itnim, input_reqs);
- bfa_stats(itnim, output_reqs);
- default:
- bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_lpuid(ioim->bfa));
- }
- if (itnim->seq_rec ||
- (bfa_cb_ioim_get_size(ioim->dio) & (sizeof(u32) - 1)))
- bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_lpuid(ioim->bfa));
-
-#ifdef IOIM_ADVANCED
- m->cmnd.crn = bfa_cb_ioim_get_crn(ioim->dio);
- m->cmnd.priority = bfa_cb_ioim_get_priority(ioim->dio);
- m->cmnd.taskattr = bfa_cb_ioim_get_taskattr(ioim->dio);
-
- /**
- * Handle large CDB (>16 bytes).
- */
- m->cmnd.addl_cdb_len = (bfa_cb_ioim_get_cdblen(ioim->dio) -
- FCP_CMND_CDB_LEN) / sizeof(u32);
- if (m->cmnd.addl_cdb_len) {
- bfa_os_memcpy(&m->cmnd.cdb + 1, (struct scsi_cdb_s *)
- bfa_cb_ioim_get_cdb(ioim->dio) + 1,
- m->cmnd.addl_cdb_len * sizeof(u32));
- fcp_cmnd_fcpdl(&m->cmnd) =
- bfa_os_htonl(bfa_cb_ioim_get_size(ioim->dio));
- }
-#endif
-
- /**
- * queue I/O message to firmware
- */
- bfa_reqq_produce(ioim->bfa, ioim->reqq);
- return BFA_TRUE;
-}
-
-/**
- * Setup any additional SG pages needed.Inline SG element is setup
- * at queuing time.
- */
-static bfa_boolean_t
-bfa_ioim_sge_setup(struct bfa_ioim_s *ioim)
-{
- u16 nsgpgs;
-
- bfa_assert(ioim->nsges > BFI_SGE_INLINE);
-
- /**
- * allocate SG pages needed
- */
- nsgpgs = BFA_SGPG_NPAGE(ioim->nsges);
- if (!nsgpgs)
- return BFA_TRUE;
-
- if (bfa_sgpg_malloc(ioim->bfa, &ioim->sgpg_q, nsgpgs)
- != BFA_STATUS_OK) {
- bfa_sgpg_wait(ioim->bfa, &ioim->iosp->sgpg_wqe, nsgpgs);
- return BFA_FALSE;
- }
-
- ioim->nsgpgs = nsgpgs;
- bfa_ioim_sgpg_setup(ioim);
-
- return BFA_TRUE;
-}
-
-static void
-bfa_ioim_sgpg_setup(struct bfa_ioim_s *ioim)
-{
- int sgeid, nsges, i;
- struct bfi_sge_s *sge;
- struct bfa_sgpg_s *sgpg;
- u32 pgcumsz;
- u64 addr;
- struct scatterlist *sg;
- struct scsi_cmnd *cmnd = (struct scsi_cmnd *) ioim->dio;
-
- sgeid = BFI_SGE_INLINE;
- ioim->sgpg = sgpg = bfa_q_first(&ioim->sgpg_q);
-
- sg = scsi_sglist(cmnd);
- sg = sg_next(sg);
-
- do {
- sge = sgpg->sgpg->sges;
- nsges = ioim->nsges - sgeid;
- if (nsges > BFI_SGPG_DATA_SGES)
- nsges = BFI_SGPG_DATA_SGES;
-
- pgcumsz = 0;
- for (i = 0; i < nsges; i++, sge++, sgeid++, sg = sg_next(sg)) {
- addr = bfa_os_sgaddr(sg_dma_address(sg));
- sge->sga = *(union bfi_addr_u *) &addr;
- sge->sg_len = sg_dma_len(sg);
- pgcumsz += sge->sg_len;
-
- /**
- * set flags
- */
- if (i < (nsges - 1))
- sge->flags = BFI_SGE_DATA;
- else if (sgeid < (ioim->nsges - 1))
- sge->flags = BFI_SGE_DATA_CPL;
- else
- sge->flags = BFI_SGE_DATA_LAST;
- }
-
- sgpg = (struct bfa_sgpg_s *) bfa_q_next(sgpg);
-
- /**
- * set the link element of each page
- */
- if (sgeid == ioim->nsges) {
- sge->flags = BFI_SGE_PGDLEN;
- sge->sga.a32.addr_lo = 0;
- sge->sga.a32.addr_hi = 0;
- } else {
- sge->flags = BFI_SGE_LINK;
- sge->sga = sgpg->sgpg_pa;
- }
- sge->sg_len = pgcumsz;
- } while (sgeid < ioim->nsges);
-}
-
-/**
- * Send I/O abort request to firmware.
- */
-static bfa_boolean_t
-bfa_ioim_send_abort(struct bfa_ioim_s *ioim)
-{
- struct bfi_ioim_abort_req_s *m;
- enum bfi_ioim_h2i msgop;
-
- /**
- * check for room in queue to send request now
- */
- m = bfa_reqq_next(ioim->bfa, ioim->reqq);
- if (!m)
- return BFA_FALSE;
-
- /**
- * build i/o request message next
- */
- if (ioim->iosp->abort_explicit)
- msgop = BFI_IOIM_H2I_IOABORT_REQ;
- else
- msgop = BFI_IOIM_H2I_IOCLEANUP_REQ;
-
- bfi_h2i_set(m->mh, BFI_MC_IOIM, msgop, bfa_lpuid(ioim->bfa));
- m->io_tag = bfa_os_htons(ioim->iotag);
- m->abort_tag = ++ioim->abort_tag;
-
- /**
- * queue I/O message to firmware
- */
- bfa_reqq_produce(ioim->bfa, ioim->reqq);
- return BFA_TRUE;
-}
-
-/**
- * Call to resume any I/O requests waiting for room in request queue.
- */
-static void
-bfa_ioim_qresume(void *cbarg)
-{
- struct bfa_ioim_s *ioim = cbarg;
-
- bfa_fcpim_stats(ioim->fcpim, qresumes);
- bfa_sm_send_event(ioim, BFA_IOIM_SM_QRESUME);
-}
-
-
-static void
-bfa_ioim_notify_cleanup(struct bfa_ioim_s *ioim)
-{
- /**
- * Move IO from itnim queue to fcpim global queue since itnim will be
- * freed.
- */
- list_del(&ioim->qe);
- list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
-
- if (!ioim->iosp->tskim) {
- if (ioim->fcpim->delay_comp && ioim->itnim->iotov_active) {
- bfa_cb_dequeue(&ioim->hcb_qe);
- list_del(&ioim->qe);
- list_add_tail(&ioim->qe, &ioim->itnim->delay_comp_q);
- }
- bfa_itnim_iodone(ioim->itnim);
- } else
- bfa_tskim_iodone(ioim->iosp->tskim);
-}
-
-/**
- * or after the link comes back.
- */
-void
-bfa_ioim_delayed_comp(struct bfa_ioim_s *ioim, bfa_boolean_t iotov)
-{
- /**
- * If path tov timer expired, failback with PATHTOV status - these
- * IO requests are not normally retried by IO stack.
- *
- * Otherwise device cameback online and fail it with normal failed
- * status so that IO stack retries these failed IO requests.
- */
- if (iotov)
- ioim->io_cbfn = __bfa_cb_ioim_pathtov;
- else
- ioim->io_cbfn = __bfa_cb_ioim_failed;
-
- bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
-
- /**
- * Move IO to fcpim global queue since itnim will be
- * freed.
- */
- list_del(&ioim->qe);
- list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
-}
-
-
-
-/**
- * bfa_ioim_friend
- */
-
-/**
- * Memory allocation and initialization.
- */
-void
-bfa_ioim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
-{
- struct bfa_ioim_s *ioim;
- struct bfa_ioim_sp_s *iosp;
- u16 i;
- u8 *snsinfo;
- u32 snsbufsz;
-
- /**
- * claim memory first
- */
- ioim = (struct bfa_ioim_s *) bfa_meminfo_kva(minfo);
- fcpim->ioim_arr = ioim;
- bfa_meminfo_kva(minfo) = (u8 *) (ioim + fcpim->num_ioim_reqs);
-
- iosp = (struct bfa_ioim_sp_s *) bfa_meminfo_kva(minfo);
- fcpim->ioim_sp_arr = iosp;
- bfa_meminfo_kva(minfo) = (u8 *) (iosp + fcpim->num_ioim_reqs);
-
- /**
- * Claim DMA memory for per IO sense data.
- */
- snsbufsz = fcpim->num_ioim_reqs * BFI_IOIM_SNSLEN;
- fcpim->snsbase.pa = bfa_meminfo_dma_phys(minfo);
- bfa_meminfo_dma_phys(minfo) += snsbufsz;
-
- fcpim->snsbase.kva = bfa_meminfo_dma_virt(minfo);
- bfa_meminfo_dma_virt(minfo) += snsbufsz;
- snsinfo = fcpim->snsbase.kva;
- bfa_iocfc_set_snsbase(fcpim->bfa, fcpim->snsbase.pa);
-
- /**
- * Initialize ioim free queues
- */
- INIT_LIST_HEAD(&fcpim->ioim_free_q);
- INIT_LIST_HEAD(&fcpim->ioim_resfree_q);
- INIT_LIST_HEAD(&fcpim->ioim_comp_q);
-
- for (i = 0; i < fcpim->num_ioim_reqs;
- i++, ioim++, iosp++, snsinfo += BFI_IOIM_SNSLEN) {
- /*
- * initialize IOIM
- */
- bfa_os_memset(ioim, 0, sizeof(struct bfa_ioim_s));
- ioim->iotag = i;
- ioim->bfa = fcpim->bfa;
- ioim->fcpim = fcpim;
- ioim->iosp = iosp;
- iosp->snsinfo = snsinfo;
- INIT_LIST_HEAD(&ioim->sgpg_q);
- bfa_reqq_winit(&ioim->iosp->reqq_wait,
- bfa_ioim_qresume, ioim);
- bfa_sgpg_winit(&ioim->iosp->sgpg_wqe,
- bfa_ioim_sgpg_alloced, ioim);
- bfa_sm_set_state(ioim, bfa_ioim_sm_uninit);
-
- list_add_tail(&ioim->qe, &fcpim->ioim_free_q);
- }
-}
-
-/**
- * Driver detach time call.
- */
-void
-bfa_ioim_detach(struct bfa_fcpim_mod_s *fcpim)
-{
-}
-
-void
-bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
-{
- struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
- struct bfi_ioim_rsp_s *rsp = (struct bfi_ioim_rsp_s *) m;
- struct bfa_ioim_s *ioim;
- u16 iotag;
- enum bfa_ioim_event evt = BFA_IOIM_SM_COMP;
-
- iotag = bfa_os_ntohs(rsp->io_tag);
-
- ioim = BFA_IOIM_FROM_TAG(fcpim, iotag);
- bfa_assert(ioim->iotag == iotag);
-
- bfa_trc(ioim->bfa, ioim->iotag);
- bfa_trc(ioim->bfa, rsp->io_status);
- bfa_trc(ioim->bfa, rsp->reuse_io_tag);
-
- if (bfa_sm_cmp_state(ioim, bfa_ioim_sm_active))
- bfa_os_assign(ioim->iosp->comp_rspmsg, *m);
-
- switch (rsp->io_status) {
- case BFI_IOIM_STS_OK:
- bfa_fcpim_stats(fcpim, iocomp_ok);
- if (rsp->reuse_io_tag == 0)
- evt = BFA_IOIM_SM_DONE;
- else
- evt = BFA_IOIM_SM_COMP;
- break;
-
- case BFI_IOIM_STS_TIMEDOUT:
- case BFI_IOIM_STS_ABORTED:
- rsp->io_status = BFI_IOIM_STS_ABORTED;
- bfa_fcpim_stats(fcpim, iocomp_aborted);
- if (rsp->reuse_io_tag == 0)
- evt = BFA_IOIM_SM_DONE;
- else
- evt = BFA_IOIM_SM_COMP;
- break;
-
- case BFI_IOIM_STS_PROTO_ERR:
- bfa_fcpim_stats(fcpim, iocom_proto_err);
- bfa_assert(rsp->reuse_io_tag);
- evt = BFA_IOIM_SM_COMP;
- break;
-
- case BFI_IOIM_STS_SQER_NEEDED:
- bfa_fcpim_stats(fcpim, iocom_sqer_needed);
- bfa_assert(rsp->reuse_io_tag == 0);
- evt = BFA_IOIM_SM_SQRETRY;
- break;
-
- case BFI_IOIM_STS_RES_FREE:
- bfa_fcpim_stats(fcpim, iocom_res_free);
- evt = BFA_IOIM_SM_FREE;
- break;
-
- case BFI_IOIM_STS_HOST_ABORTED:
- bfa_fcpim_stats(fcpim, iocom_hostabrts);
- if (rsp->abort_tag != ioim->abort_tag) {
- bfa_trc(ioim->bfa, rsp->abort_tag);
- bfa_trc(ioim->bfa, ioim->abort_tag);
- return;
- }
-
- if (rsp->reuse_io_tag)
- evt = BFA_IOIM_SM_ABORT_COMP;
- else
- evt = BFA_IOIM_SM_ABORT_DONE;
- break;
-
- case BFI_IOIM_STS_UTAG:
- bfa_fcpim_stats(fcpim, iocom_utags);
- evt = BFA_IOIM_SM_COMP_UTAG;
- break;
-
- default:
- bfa_assert(0);
- }
-
- bfa_sm_send_event(ioim, evt);
-}
-
-void
-bfa_ioim_good_comp_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
-{
- struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
- struct bfi_ioim_rsp_s *rsp = (struct bfi_ioim_rsp_s *) m;
- struct bfa_ioim_s *ioim;
- u16 iotag;
-
- iotag = bfa_os_ntohs(rsp->io_tag);
-
- ioim = BFA_IOIM_FROM_TAG(fcpim, iotag);
- bfa_assert(ioim->iotag == iotag);
-
- bfa_trc_fp(ioim->bfa, ioim->iotag);
- bfa_sm_send_event(ioim, BFA_IOIM_SM_COMP_GOOD);
-}
-
-/**
- * Called by itnim to clean up IO while going offline.
- */
-void
-bfa_ioim_cleanup(struct bfa_ioim_s *ioim)
-{
- bfa_trc(ioim->bfa, ioim->iotag);
- bfa_fcpim_stats(ioim->fcpim, io_cleanups);
-
- ioim->iosp->tskim = NULL;
- bfa_sm_send_event(ioim, BFA_IOIM_SM_CLEANUP);
-}
-
-void
-bfa_ioim_cleanup_tm(struct bfa_ioim_s *ioim, struct bfa_tskim_s *tskim)
-{
- bfa_trc(ioim->bfa, ioim->iotag);
- bfa_fcpim_stats(ioim->fcpim, io_tmaborts);
-
- ioim->iosp->tskim = tskim;
- bfa_sm_send_event(ioim, BFA_IOIM_SM_CLEANUP);
-}
-
-/**
- * IOC failure handling.
- */
-void
-bfa_ioim_iocdisable(struct bfa_ioim_s *ioim)
-{
- bfa_sm_send_event(ioim, BFA_IOIM_SM_HWFAIL);
-}
-
-/**
- * IO offline TOV popped. Fail the pending IO.
- */
-void
-bfa_ioim_tov(struct bfa_ioim_s *ioim)
-{
- bfa_sm_send_event(ioim, BFA_IOIM_SM_IOTOV);
-}
-
-
-
-/**
- * bfa_ioim_api
- */
-
-/**
- * Allocate IOIM resource for initiator mode I/O request.
- */
-struct bfa_ioim_s *
-bfa_ioim_alloc(struct bfa_s *bfa, struct bfad_ioim_s *dio,
- struct bfa_itnim_s *itnim, u16 nsges)
-{
- struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
- struct bfa_ioim_s *ioim;
-
- /**
- * alocate IOIM resource
- */
- bfa_q_deq(&fcpim->ioim_free_q, &ioim);
- if (!ioim) {
- bfa_fcpim_stats(fcpim, no_iotags);
- return NULL;
- }
-
- ioim->dio = dio;
- ioim->itnim = itnim;
- ioim->nsges = nsges;
- ioim->nsgpgs = 0;
-
- bfa_stats(fcpim, total_ios);
- bfa_stats(itnim, ios);
- fcpim->ios_active++;
-
- list_add_tail(&ioim->qe, &itnim->io_q);
- bfa_trc_fp(ioim->bfa, ioim->iotag);
-
- return ioim;
-}
-
-void
-bfa_ioim_free(struct bfa_ioim_s *ioim)
-{
- struct bfa_fcpim_mod_s *fcpim = ioim->fcpim;
-
- bfa_trc_fp(ioim->bfa, ioim->iotag);
- bfa_assert_fp(bfa_sm_cmp_state(ioim, bfa_ioim_sm_uninit));
-
- bfa_assert_fp(list_empty(&ioim->sgpg_q)
- || (ioim->nsges > BFI_SGE_INLINE));
-
- if (ioim->nsgpgs > 0)
- bfa_sgpg_mfree(ioim->bfa, &ioim->sgpg_q, ioim->nsgpgs);
-
- bfa_stats(ioim->itnim, io_comps);
- fcpim->ios_active--;
-
- list_del(&ioim->qe);
- list_add_tail(&ioim->qe, &fcpim->ioim_free_q);
-}
-
-void
-bfa_ioim_start(struct bfa_ioim_s *ioim)
-{
- bfa_trc_fp(ioim->bfa, ioim->iotag);
-
- /**
- * Obtain the queue over which this request has to be issued
- */
- ioim->reqq = bfa_fcpim_ioredirect_enabled(ioim->bfa) ?
- bfa_cb_ioim_get_reqq(ioim->dio) :
- bfa_itnim_get_reqq(ioim);
-
- bfa_sm_send_event(ioim, BFA_IOIM_SM_START);
-}
-
-/**
- * Driver I/O abort request.
- */
-void
-bfa_ioim_abort(struct bfa_ioim_s *ioim)
-{
- bfa_trc(ioim->bfa, ioim->iotag);
- bfa_fcpim_stats(ioim->fcpim, io_aborts);
- bfa_sm_send_event(ioim, BFA_IOIM_SM_ABORT);
-}
-
-
diff --git a/drivers/scsi/bfa/bfa_itnim.c b/drivers/scsi/bfa/bfa_itnim.c
deleted file mode 100644
index a914ff255135..000000000000
--- a/drivers/scsi/bfa/bfa_itnim.c
+++ /dev/null
@@ -1,1088 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#include <bfa.h>
-#include <bfa_fcpim.h>
-#include "bfa_fcpim_priv.h"
-
-BFA_TRC_FILE(HAL, ITNIM);
-
-#define BFA_ITNIM_FROM_TAG(_fcpim, _tag) \
- ((_fcpim)->itnim_arr + ((_tag) & ((_fcpim)->num_itnims - 1)))
-
-#define bfa_fcpim_additn(__itnim) \
- list_add_tail(&(__itnim)->qe, &(__itnim)->fcpim->itnim_q)
-#define bfa_fcpim_delitn(__itnim) do { \
- bfa_assert(bfa_q_is_on_q(&(__itnim)->fcpim->itnim_q, __itnim)); \
- list_del(&(__itnim)->qe); \
- bfa_assert(list_empty(&(__itnim)->io_q)); \
- bfa_assert(list_empty(&(__itnim)->io_cleanup_q)); \
- bfa_assert(list_empty(&(__itnim)->pending_q)); \
-} while (0)
-
-#define bfa_itnim_online_cb(__itnim) do { \
- if ((__itnim)->bfa->fcs) \
- bfa_cb_itnim_online((__itnim)->ditn); \
- else { \
- bfa_cb_queue((__itnim)->bfa, &(__itnim)->hcb_qe, \
- __bfa_cb_itnim_online, (__itnim)); \
- } \
-} while (0)
-
-#define bfa_itnim_offline_cb(__itnim) do { \
- if ((__itnim)->bfa->fcs) \
- bfa_cb_itnim_offline((__itnim)->ditn); \
- else { \
- bfa_cb_queue((__itnim)->bfa, &(__itnim)->hcb_qe, \
- __bfa_cb_itnim_offline, (__itnim)); \
- } \
-} while (0)
-
-#define bfa_itnim_sler_cb(__itnim) do { \
- if ((__itnim)->bfa->fcs) \
- bfa_cb_itnim_sler((__itnim)->ditn); \
- else { \
- bfa_cb_queue((__itnim)->bfa, &(__itnim)->hcb_qe, \
- __bfa_cb_itnim_sler, (__itnim)); \
- } \
-} while (0)
-
-/*
- * forward declarations
- */
-static void bfa_itnim_iocdisable_cleanup(struct bfa_itnim_s *itnim);
-static bfa_boolean_t bfa_itnim_send_fwcreate(struct bfa_itnim_s *itnim);
-static bfa_boolean_t bfa_itnim_send_fwdelete(struct bfa_itnim_s *itnim);
-static void bfa_itnim_cleanp_comp(void *itnim_cbarg);
-static void bfa_itnim_cleanup(struct bfa_itnim_s *itnim);
-static void __bfa_cb_itnim_online(void *cbarg, bfa_boolean_t complete);
-static void __bfa_cb_itnim_offline(void *cbarg, bfa_boolean_t complete);
-static void __bfa_cb_itnim_sler(void *cbarg, bfa_boolean_t complete);
-static void bfa_itnim_iotov_online(struct bfa_itnim_s *itnim);
-static void bfa_itnim_iotov_cleanup(struct bfa_itnim_s *itnim);
-static void bfa_itnim_iotov(void *itnim_arg);
-static void bfa_itnim_iotov_start(struct bfa_itnim_s *itnim);
-static void bfa_itnim_iotov_stop(struct bfa_itnim_s *itnim);
-static void bfa_itnim_iotov_delete(struct bfa_itnim_s *itnim);
-
-/**
- * bfa_itnim_sm BFA itnim state machine
- */
-
-
-enum bfa_itnim_event {
- BFA_ITNIM_SM_CREATE = 1, /* itnim is created */
- BFA_ITNIM_SM_ONLINE = 2, /* itnim is online */
- BFA_ITNIM_SM_OFFLINE = 3, /* itnim is offline */
- BFA_ITNIM_SM_FWRSP = 4, /* firmware response */
- BFA_ITNIM_SM_DELETE = 5, /* deleting an existing itnim */
- BFA_ITNIM_SM_CLEANUP = 6, /* IO cleanup completion */
- BFA_ITNIM_SM_SLER = 7, /* second level error recovery */
- BFA_ITNIM_SM_HWFAIL = 8, /* IOC h/w failure event */
- BFA_ITNIM_SM_QRESUME = 9, /* queue space available */
-};
-
-static void bfa_itnim_sm_uninit(struct bfa_itnim_s *itnim,
- enum bfa_itnim_event event);
-static void bfa_itnim_sm_created(struct bfa_itnim_s *itnim,
- enum bfa_itnim_event event);
-static void bfa_itnim_sm_fwcreate(struct bfa_itnim_s *itnim,
- enum bfa_itnim_event event);
-static void bfa_itnim_sm_delete_pending(struct bfa_itnim_s *itnim,
- enum bfa_itnim_event event);
-static void bfa_itnim_sm_online(struct bfa_itnim_s *itnim,
- enum bfa_itnim_event event);
-static void bfa_itnim_sm_sler(struct bfa_itnim_s *itnim,
- enum bfa_itnim_event event);
-static void bfa_itnim_sm_cleanup_offline(struct bfa_itnim_s *itnim,
- enum bfa_itnim_event event);
-static void bfa_itnim_sm_cleanup_delete(struct bfa_itnim_s *itnim,
- enum bfa_itnim_event event);
-static void bfa_itnim_sm_fwdelete(struct bfa_itnim_s *itnim,
- enum bfa_itnim_event event);
-static void bfa_itnim_sm_offline(struct bfa_itnim_s *itnim,
- enum bfa_itnim_event event);
-static void bfa_itnim_sm_iocdisable(struct bfa_itnim_s *itnim,
- enum bfa_itnim_event event);
-static void bfa_itnim_sm_deleting(struct bfa_itnim_s *itnim,
- enum bfa_itnim_event event);
-static void bfa_itnim_sm_fwcreate_qfull(struct bfa_itnim_s *itnim,
- enum bfa_itnim_event event);
-static void bfa_itnim_sm_fwdelete_qfull(struct bfa_itnim_s *itnim,
- enum bfa_itnim_event event);
-static void bfa_itnim_sm_deleting_qfull(struct bfa_itnim_s *itnim,
- enum bfa_itnim_event event);
-
-/**
- * Beginning/unallocated state - no events expected.
- */
-static void
-bfa_itnim_sm_uninit(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
-{
- bfa_trc(itnim->bfa, itnim->rport->rport_tag);
- bfa_trc(itnim->bfa, event);
-
- switch (event) {
- case BFA_ITNIM_SM_CREATE:
- bfa_sm_set_state(itnim, bfa_itnim_sm_created);
- itnim->is_online = BFA_FALSE;
- bfa_fcpim_additn(itnim);
- break;
-
- default:
- bfa_sm_fault(itnim->bfa, event);
- }
-}
-
-/**
- * Beginning state, only online event expected.
- */
-static void
-bfa_itnim_sm_created(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
-{
- bfa_trc(itnim->bfa, itnim->rport->rport_tag);
- bfa_trc(itnim->bfa, event);
-
- switch (event) {
- case BFA_ITNIM_SM_ONLINE:
- if (bfa_itnim_send_fwcreate(itnim))
- bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate);
- else
- bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate_qfull);
- break;
-
- case BFA_ITNIM_SM_DELETE:
- bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
- bfa_fcpim_delitn(itnim);
- break;
-
- case BFA_ITNIM_SM_HWFAIL:
- bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
- break;
-
- default:
- bfa_sm_fault(itnim->bfa, event);
- }
-}
-
-/**
- * Waiting for itnim create response from firmware.
- */
-static void
-bfa_itnim_sm_fwcreate(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
-{
- bfa_trc(itnim->bfa, itnim->rport->rport_tag);
- bfa_trc(itnim->bfa, event);
-
- switch (event) {
- case BFA_ITNIM_SM_FWRSP:
- bfa_sm_set_state(itnim, bfa_itnim_sm_online);
- itnim->is_online = BFA_TRUE;
- bfa_itnim_iotov_online(itnim);
- bfa_itnim_online_cb(itnim);
- break;
-
- case BFA_ITNIM_SM_DELETE:
- bfa_sm_set_state(itnim, bfa_itnim_sm_delete_pending);
- break;
-
- case BFA_ITNIM_SM_OFFLINE:
- if (bfa_itnim_send_fwdelete(itnim))
- bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete);
- else
- bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete_qfull);
- break;
-
- case BFA_ITNIM_SM_HWFAIL:
- bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
- break;
-
- default:
- bfa_sm_fault(itnim->bfa, event);
- }
-}
-
-static void
-bfa_itnim_sm_fwcreate_qfull(struct bfa_itnim_s *itnim,
- enum bfa_itnim_event event)
-{
- bfa_trc(itnim->bfa, itnim->rport->rport_tag);
- bfa_trc(itnim->bfa, event);
-
- switch (event) {
- case BFA_ITNIM_SM_QRESUME:
- bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate);
- bfa_itnim_send_fwcreate(itnim);
- break;
-
- case BFA_ITNIM_SM_DELETE:
- bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
- bfa_reqq_wcancel(&itnim->reqq_wait);
- bfa_fcpim_delitn(itnim);
- break;
-
- case BFA_ITNIM_SM_OFFLINE:
- bfa_sm_set_state(itnim, bfa_itnim_sm_offline);
- bfa_reqq_wcancel(&itnim->reqq_wait);
- bfa_itnim_offline_cb(itnim);
- break;
-
- case BFA_ITNIM_SM_HWFAIL:
- bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
- bfa_reqq_wcancel(&itnim->reqq_wait);
- break;
-
- default:
- bfa_sm_fault(itnim->bfa, event);
- }
-}
-
-/**
- * Waiting for itnim create response from firmware, a delete is pending.
- */
-static void
-bfa_itnim_sm_delete_pending(struct bfa_itnim_s *itnim,
- enum bfa_itnim_event event)
-{
- bfa_trc(itnim->bfa, itnim->rport->rport_tag);
- bfa_trc(itnim->bfa, event);
-
- switch (event) {
- case BFA_ITNIM_SM_FWRSP:
- if (bfa_itnim_send_fwdelete(itnim))
- bfa_sm_set_state(itnim, bfa_itnim_sm_deleting);
- else
- bfa_sm_set_state(itnim, bfa_itnim_sm_deleting_qfull);
- break;
-
- case BFA_ITNIM_SM_HWFAIL:
- bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
- bfa_fcpim_delitn(itnim);
- break;
-
- default:
- bfa_sm_fault(itnim->bfa, event);
- }
-}
-
-/**
- * Online state - normal parking state.
- */
-static void
-bfa_itnim_sm_online(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
-{
- bfa_trc(itnim->bfa, itnim->rport->rport_tag);
- bfa_trc(itnim->bfa, event);
-
- switch (event) {
- case BFA_ITNIM_SM_OFFLINE:
- bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_offline);
- itnim->is_online = BFA_FALSE;
- bfa_itnim_iotov_start(itnim);
- bfa_itnim_cleanup(itnim);
- break;
-
- case BFA_ITNIM_SM_DELETE:
- bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_delete);
- itnim->is_online = BFA_FALSE;
- bfa_itnim_cleanup(itnim);
- break;
-
- case BFA_ITNIM_SM_SLER:
- bfa_sm_set_state(itnim, bfa_itnim_sm_sler);
- itnim->is_online = BFA_FALSE;
- bfa_itnim_iotov_start(itnim);
- bfa_itnim_sler_cb(itnim);
- break;
-
- case BFA_ITNIM_SM_HWFAIL:
- bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
- itnim->is_online = BFA_FALSE;
- bfa_itnim_iotov_start(itnim);
- bfa_itnim_iocdisable_cleanup(itnim);
- break;
-
- default:
- bfa_sm_fault(itnim->bfa, event);
- }
-}
-
-/**
- * Second level error recovery need.
- */
-static void
-bfa_itnim_sm_sler(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
-{
- bfa_trc(itnim->bfa, itnim->rport->rport_tag);
- bfa_trc(itnim->bfa, event);
-
- switch (event) {
- case BFA_ITNIM_SM_OFFLINE:
- bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_offline);
- bfa_itnim_cleanup(itnim);
- break;
-
- case BFA_ITNIM_SM_DELETE:
- bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_delete);
- bfa_itnim_cleanup(itnim);
- bfa_itnim_iotov_delete(itnim);
- break;
-
- case BFA_ITNIM_SM_HWFAIL:
- bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
- bfa_itnim_iocdisable_cleanup(itnim);
- break;
-
- default:
- bfa_sm_fault(itnim->bfa, event);
- }
-}
-
-/**
- * Going offline. Waiting for active IO cleanup.
- */
-static void
-bfa_itnim_sm_cleanup_offline(struct bfa_itnim_s *itnim,
- enum bfa_itnim_event event)
-{
- bfa_trc(itnim->bfa, itnim->rport->rport_tag);
- bfa_trc(itnim->bfa, event);
-
- switch (event) {
- case BFA_ITNIM_SM_CLEANUP:
- if (bfa_itnim_send_fwdelete(itnim))
- bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete);
- else
- bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete_qfull);
- break;
-
- case BFA_ITNIM_SM_DELETE:
- bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_delete);
- bfa_itnim_iotov_delete(itnim);
- break;
-
- case BFA_ITNIM_SM_HWFAIL:
- bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
- bfa_itnim_iocdisable_cleanup(itnim);
- bfa_itnim_offline_cb(itnim);
- break;
-
- case BFA_ITNIM_SM_SLER:
- break;
-
- default:
- bfa_sm_fault(itnim->bfa, event);
- }
-}
-
-/**
- * Deleting itnim. Waiting for active IO cleanup.
- */
-static void
-bfa_itnim_sm_cleanup_delete(struct bfa_itnim_s *itnim,
- enum bfa_itnim_event event)
-{
- bfa_trc(itnim->bfa, itnim->rport->rport_tag);
- bfa_trc(itnim->bfa, event);
-
- switch (event) {
- case BFA_ITNIM_SM_CLEANUP:
- if (bfa_itnim_send_fwdelete(itnim))
- bfa_sm_set_state(itnim, bfa_itnim_sm_deleting);
- else
- bfa_sm_set_state(itnim, bfa_itnim_sm_deleting_qfull);
- break;
-
- case BFA_ITNIM_SM_HWFAIL:
- bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
- bfa_itnim_iocdisable_cleanup(itnim);
- break;
-
- default:
- bfa_sm_fault(itnim->bfa, event);
- }
-}
-
-/**
- * Rport offline. Fimrware itnim is being deleted - awaiting f/w response.
- */
-static void
-bfa_itnim_sm_fwdelete(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
-{
- bfa_trc(itnim->bfa, itnim->rport->rport_tag);
- bfa_trc(itnim->bfa, event);
-
- switch (event) {
- case BFA_ITNIM_SM_FWRSP:
- bfa_sm_set_state(itnim, bfa_itnim_sm_offline);
- bfa_itnim_offline_cb(itnim);
- break;
-
- case BFA_ITNIM_SM_DELETE:
- bfa_sm_set_state(itnim, bfa_itnim_sm_deleting);
- break;
-
- case BFA_ITNIM_SM_HWFAIL:
- bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
- bfa_itnim_offline_cb(itnim);
- break;
-
- default:
- bfa_sm_fault(itnim->bfa, event);
- }
-}
-
-static void
-bfa_itnim_sm_fwdelete_qfull(struct bfa_itnim_s *itnim,
- enum bfa_itnim_event event)
-{
- bfa_trc(itnim->bfa, itnim->rport->rport_tag);
- bfa_trc(itnim->bfa, event);
-
- switch (event) {
- case BFA_ITNIM_SM_QRESUME:
- bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete);
- bfa_itnim_send_fwdelete(itnim);
- break;
-
- case BFA_ITNIM_SM_DELETE:
- bfa_sm_set_state(itnim, bfa_itnim_sm_deleting_qfull);
- break;
-
- case BFA_ITNIM_SM_HWFAIL:
- bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
- bfa_reqq_wcancel(&itnim->reqq_wait);
- bfa_itnim_offline_cb(itnim);
- break;
-
- default:
- bfa_sm_fault(itnim->bfa, event);
- }
-}
-
-/**
- * Offline state.
- */
-static void
-bfa_itnim_sm_offline(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
-{
- bfa_trc(itnim->bfa, itnim->rport->rport_tag);
- bfa_trc(itnim->bfa, event);
-
- switch (event) {
- case BFA_ITNIM_SM_DELETE:
- bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
- bfa_itnim_iotov_delete(itnim);
- bfa_fcpim_delitn(itnim);
- break;
-
- case BFA_ITNIM_SM_ONLINE:
- if (bfa_itnim_send_fwcreate(itnim))
- bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate);
- else
- bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate_qfull);
- break;
-
- case BFA_ITNIM_SM_HWFAIL:
- bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
- break;
-
- default:
- bfa_sm_fault(itnim->bfa, event);
- }
-}
-
-/**
- * IOC h/w failed state.
- */
-static void
-bfa_itnim_sm_iocdisable(struct bfa_itnim_s *itnim,
- enum bfa_itnim_event event)
-{
- bfa_trc(itnim->bfa, itnim->rport->rport_tag);
- bfa_trc(itnim->bfa, event);
-
- switch (event) {
- case BFA_ITNIM_SM_DELETE:
- bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
- bfa_itnim_iotov_delete(itnim);
- bfa_fcpim_delitn(itnim);
- break;
-
- case BFA_ITNIM_SM_OFFLINE:
- bfa_itnim_offline_cb(itnim);
- break;
-
- case BFA_ITNIM_SM_ONLINE:
- if (bfa_itnim_send_fwcreate(itnim))
- bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate);
- else
- bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate_qfull);
- break;
-
- case BFA_ITNIM_SM_HWFAIL:
- break;
-
- default:
- bfa_sm_fault(itnim->bfa, event);
- }
-}
-
-/**
- * Itnim is deleted, waiting for firmware response to delete.
- */
-static void
-bfa_itnim_sm_deleting(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
-{
- bfa_trc(itnim->bfa, itnim->rport->rport_tag);
- bfa_trc(itnim->bfa, event);
-
- switch (event) {
- case BFA_ITNIM_SM_FWRSP:
- case BFA_ITNIM_SM_HWFAIL:
- bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
- bfa_fcpim_delitn(itnim);
- break;
-
- default:
- bfa_sm_fault(itnim->bfa, event);
- }
-}
-
-static void
-bfa_itnim_sm_deleting_qfull(struct bfa_itnim_s *itnim,
- enum bfa_itnim_event event)
-{
- bfa_trc(itnim->bfa, itnim->rport->rport_tag);
- bfa_trc(itnim->bfa, event);
-
- switch (event) {
- case BFA_ITNIM_SM_QRESUME:
- bfa_sm_set_state(itnim, bfa_itnim_sm_deleting);
- bfa_itnim_send_fwdelete(itnim);
- break;
-
- case BFA_ITNIM_SM_HWFAIL:
- bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
- bfa_reqq_wcancel(&itnim->reqq_wait);
- bfa_fcpim_delitn(itnim);
- break;
-
- default:
- bfa_sm_fault(itnim->bfa, event);
- }
-}
-
-
-
-/**
- * bfa_itnim_private
- */
-
-/**
- * Initiate cleanup of all IOs on an IOC failure.
- */
-static void
-bfa_itnim_iocdisable_cleanup(struct bfa_itnim_s *itnim)
-{
- struct bfa_tskim_s *tskim;
- struct bfa_ioim_s *ioim;
- struct list_head *qe, *qen;
-
- list_for_each_safe(qe, qen, &itnim->tsk_q) {
- tskim = (struct bfa_tskim_s *) qe;
- bfa_tskim_iocdisable(tskim);
- }
-
- list_for_each_safe(qe, qen, &itnim->io_q) {
- ioim = (struct bfa_ioim_s *) qe;
- bfa_ioim_iocdisable(ioim);
- }
-
- /**
- * For IO request in pending queue, we pretend an early timeout.
- */
- list_for_each_safe(qe, qen, &itnim->pending_q) {
- ioim = (struct bfa_ioim_s *) qe;
- bfa_ioim_tov(ioim);
- }
-
- list_for_each_safe(qe, qen, &itnim->io_cleanup_q) {
- ioim = (struct bfa_ioim_s *) qe;
- bfa_ioim_iocdisable(ioim);
- }
-}
-
-/**
- * IO cleanup completion
- */
-static void
-bfa_itnim_cleanp_comp(void *itnim_cbarg)
-{
- struct bfa_itnim_s *itnim = itnim_cbarg;
-
- bfa_stats(itnim, cleanup_comps);
- bfa_sm_send_event(itnim, BFA_ITNIM_SM_CLEANUP);
-}
-
-/**
- * Initiate cleanup of all IOs.
- */
-static void
-bfa_itnim_cleanup(struct bfa_itnim_s *itnim)
-{
- struct bfa_ioim_s *ioim;
- struct bfa_tskim_s *tskim;
- struct list_head *qe, *qen;
-
- bfa_wc_init(&itnim->wc, bfa_itnim_cleanp_comp, itnim);
-
- list_for_each_safe(qe, qen, &itnim->io_q) {
- ioim = (struct bfa_ioim_s *) qe;
-
- /**
- * Move IO to a cleanup queue from active queue so that a later
- * TM will not pickup this IO.
- */
- list_del(&ioim->qe);
- list_add_tail(&ioim->qe, &itnim->io_cleanup_q);
-
- bfa_wc_up(&itnim->wc);
- bfa_ioim_cleanup(ioim);
- }
-
- list_for_each_safe(qe, qen, &itnim->tsk_q) {
- tskim = (struct bfa_tskim_s *) qe;
- bfa_wc_up(&itnim->wc);
- bfa_tskim_cleanup(tskim);
- }
-
- bfa_wc_wait(&itnim->wc);
-}
-
-static void
-__bfa_cb_itnim_online(void *cbarg, bfa_boolean_t complete)
-{
- struct bfa_itnim_s *itnim = cbarg;
-
- if (complete)
- bfa_cb_itnim_online(itnim->ditn);
-}
-
-static void
-__bfa_cb_itnim_offline(void *cbarg, bfa_boolean_t complete)
-{
- struct bfa_itnim_s *itnim = cbarg;
-
- if (complete)
- bfa_cb_itnim_offline(itnim->ditn);
-}
-
-static void
-__bfa_cb_itnim_sler(void *cbarg, bfa_boolean_t complete)
-{
- struct bfa_itnim_s *itnim = cbarg;
-
- if (complete)
- bfa_cb_itnim_sler(itnim->ditn);
-}
-
-/**
- * Call to resume any I/O requests waiting for room in request queue.
- */
-static void
-bfa_itnim_qresume(void *cbarg)
-{
- struct bfa_itnim_s *itnim = cbarg;
-
- bfa_sm_send_event(itnim, BFA_ITNIM_SM_QRESUME);
-}
-
-
-
-
-/**
- * bfa_itnim_public
- */
-
-void
-bfa_itnim_iodone(struct bfa_itnim_s *itnim)
-{
- bfa_wc_down(&itnim->wc);
-}
-
-void
-bfa_itnim_tskdone(struct bfa_itnim_s *itnim)
-{
- bfa_wc_down(&itnim->wc);
-}
-
-void
-bfa_itnim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
- u32 *dm_len)
-{
- /**
- * ITN memory
- */
- *km_len += cfg->fwcfg.num_rports * sizeof(struct bfa_itnim_s);
-}
-
-void
-bfa_itnim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
-{
- struct bfa_s *bfa = fcpim->bfa;
- struct bfa_itnim_s *itnim;
- int i;
-
- INIT_LIST_HEAD(&fcpim->itnim_q);
-
- itnim = (struct bfa_itnim_s *) bfa_meminfo_kva(minfo);
- fcpim->itnim_arr = itnim;
-
- for (i = 0; i < fcpim->num_itnims; i++, itnim++) {
- bfa_os_memset(itnim, 0, sizeof(struct bfa_itnim_s));
- itnim->bfa = bfa;
- itnim->fcpim = fcpim;
- itnim->reqq = BFA_REQQ_QOS_LO;
- itnim->rport = BFA_RPORT_FROM_TAG(bfa, i);
- itnim->iotov_active = BFA_FALSE;
- bfa_reqq_winit(&itnim->reqq_wait, bfa_itnim_qresume, itnim);
-
- INIT_LIST_HEAD(&itnim->io_q);
- INIT_LIST_HEAD(&itnim->io_cleanup_q);
- INIT_LIST_HEAD(&itnim->pending_q);
- INIT_LIST_HEAD(&itnim->tsk_q);
- INIT_LIST_HEAD(&itnim->delay_comp_q);
- bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
- }
-
- bfa_meminfo_kva(minfo) = (u8 *) itnim;
-}
-
-void
-bfa_itnim_iocdisable(struct bfa_itnim_s *itnim)
-{
- bfa_stats(itnim, ioc_disabled);
- bfa_sm_send_event(itnim, BFA_ITNIM_SM_HWFAIL);
-}
-
-static bfa_boolean_t
-bfa_itnim_send_fwcreate(struct bfa_itnim_s *itnim)
-{
- struct bfi_itnim_create_req_s *m;
-
- itnim->msg_no++;
-
- /**
- * check for room in queue to send request now
- */
- m = bfa_reqq_next(itnim->bfa, itnim->reqq);
- if (!m) {
- bfa_reqq_wait(itnim->bfa, itnim->reqq, &itnim->reqq_wait);
- return BFA_FALSE;
- }
-
- bfi_h2i_set(m->mh, BFI_MC_ITNIM, BFI_ITNIM_H2I_CREATE_REQ,
- bfa_lpuid(itnim->bfa));
- m->fw_handle = itnim->rport->fw_handle;
- m->class = FC_CLASS_3;
- m->seq_rec = itnim->seq_rec;
- m->msg_no = itnim->msg_no;
-
- /**
- * queue I/O message to firmware
- */
- bfa_reqq_produce(itnim->bfa, itnim->reqq);
- return BFA_TRUE;
-}
-
-static bfa_boolean_t
-bfa_itnim_send_fwdelete(struct bfa_itnim_s *itnim)
-{
- struct bfi_itnim_delete_req_s *m;
-
- /**
- * check for room in queue to send request now
- */
- m = bfa_reqq_next(itnim->bfa, itnim->reqq);
- if (!m) {
- bfa_reqq_wait(itnim->bfa, itnim->reqq, &itnim->reqq_wait);
- return BFA_FALSE;
- }
-
- bfi_h2i_set(m->mh, BFI_MC_ITNIM, BFI_ITNIM_H2I_DELETE_REQ,
- bfa_lpuid(itnim->bfa));
- m->fw_handle = itnim->rport->fw_handle;
-
- /**
- * queue I/O message to firmware
- */
- bfa_reqq_produce(itnim->bfa, itnim->reqq);
- return BFA_TRUE;
-}
-
-/**
- * Cleanup all pending failed inflight requests.
- */
-static void
-bfa_itnim_delayed_comp(struct bfa_itnim_s *itnim, bfa_boolean_t iotov)
-{
- struct bfa_ioim_s *ioim;
- struct list_head *qe, *qen;
-
- list_for_each_safe(qe, qen, &itnim->delay_comp_q) {
- ioim = (struct bfa_ioim_s *)qe;
- bfa_ioim_delayed_comp(ioim, iotov);
- }
-}
-
-/**
- * Start all pending IO requests.
- */
-static void
-bfa_itnim_iotov_online(struct bfa_itnim_s *itnim)
-{
- struct bfa_ioim_s *ioim;
-
- bfa_itnim_iotov_stop(itnim);
-
- /**
- * Abort all inflight IO requests in the queue
- */
- bfa_itnim_delayed_comp(itnim, BFA_FALSE);
-
- /**
- * Start all pending IO requests.
- */
- while (!list_empty(&itnim->pending_q)) {
- bfa_q_deq(&itnim->pending_q, &ioim);
- list_add_tail(&ioim->qe, &itnim->io_q);
- bfa_ioim_start(ioim);
- }
-}
-
-/**
- * Fail all pending IO requests
- */
-static void
-bfa_itnim_iotov_cleanup(struct bfa_itnim_s *itnim)
-{
- struct bfa_ioim_s *ioim;
-
- /**
- * Fail all inflight IO requests in the queue
- */
- bfa_itnim_delayed_comp(itnim, BFA_TRUE);
-
- /**
- * Fail any pending IO requests.
- */
- while (!list_empty(&itnim->pending_q)) {
- bfa_q_deq(&itnim->pending_q, &ioim);
- list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
- bfa_ioim_tov(ioim);
- }
-}
-
-/**
- * IO TOV timer callback. Fail any pending IO requests.
- */
-static void
-bfa_itnim_iotov(void *itnim_arg)
-{
- struct bfa_itnim_s *itnim = itnim_arg;
-
- itnim->iotov_active = BFA_FALSE;
-
- bfa_cb_itnim_tov_begin(itnim->ditn);
- bfa_itnim_iotov_cleanup(itnim);
- bfa_cb_itnim_tov(itnim->ditn);
-}
-
-/**
- * Start IO TOV timer for failing back pending IO requests in offline state.
- */
-static void
-bfa_itnim_iotov_start(struct bfa_itnim_s *itnim)
-{
- if (itnim->fcpim->path_tov > 0) {
-
- itnim->iotov_active = BFA_TRUE;
- bfa_assert(bfa_itnim_hold_io(itnim));
- bfa_timer_start(itnim->bfa, &itnim->timer,
- bfa_itnim_iotov, itnim, itnim->fcpim->path_tov);
- }
-}
-
-/**
- * Stop IO TOV timer.
- */
-static void
-bfa_itnim_iotov_stop(struct bfa_itnim_s *itnim)
-{
- if (itnim->iotov_active) {
- itnim->iotov_active = BFA_FALSE;
- bfa_timer_stop(&itnim->timer);
- }
-}
-
-/**
- * Stop IO TOV timer.
- */
-static void
-bfa_itnim_iotov_delete(struct bfa_itnim_s *itnim)
-{
- bfa_boolean_t pathtov_active = BFA_FALSE;
-
- if (itnim->iotov_active)
- pathtov_active = BFA_TRUE;
-
- bfa_itnim_iotov_stop(itnim);
- if (pathtov_active)
- bfa_cb_itnim_tov_begin(itnim->ditn);
- bfa_itnim_iotov_cleanup(itnim);
- if (pathtov_active)
- bfa_cb_itnim_tov(itnim->ditn);
-}
-
-
-
-/**
- * bfa_itnim_public
- */
-
-/**
- * Itnim interrupt processing.
- */
-void
-bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
-{
- struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
- union bfi_itnim_i2h_msg_u msg;
- struct bfa_itnim_s *itnim;
-
- bfa_trc(bfa, m->mhdr.msg_id);
-
- msg.msg = m;
-
- switch (m->mhdr.msg_id) {
- case BFI_ITNIM_I2H_CREATE_RSP:
- itnim = BFA_ITNIM_FROM_TAG(fcpim,
- msg.create_rsp->bfa_handle);
- bfa_assert(msg.create_rsp->status == BFA_STATUS_OK);
- bfa_stats(itnim, create_comps);
- bfa_sm_send_event(itnim, BFA_ITNIM_SM_FWRSP);
- break;
-
- case BFI_ITNIM_I2H_DELETE_RSP:
- itnim = BFA_ITNIM_FROM_TAG(fcpim,
- msg.delete_rsp->bfa_handle);
- bfa_assert(msg.delete_rsp->status == BFA_STATUS_OK);
- bfa_stats(itnim, delete_comps);
- bfa_sm_send_event(itnim, BFA_ITNIM_SM_FWRSP);
- break;
-
- case BFI_ITNIM_I2H_SLER_EVENT:
- itnim = BFA_ITNIM_FROM_TAG(fcpim,
- msg.sler_event->bfa_handle);
- bfa_stats(itnim, sler_events);
- bfa_sm_send_event(itnim, BFA_ITNIM_SM_SLER);
- break;
-
- default:
- bfa_trc(bfa, m->mhdr.msg_id);
- bfa_assert(0);
- }
-}
-
-
-
-/**
- * bfa_itnim_api
- */
-
-struct bfa_itnim_s *
-bfa_itnim_create(struct bfa_s *bfa, struct bfa_rport_s *rport, void *ditn)
-{
- struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
- struct bfa_itnim_s *itnim;
-
- itnim = BFA_ITNIM_FROM_TAG(fcpim, rport->rport_tag);
- bfa_assert(itnim->rport == rport);
-
- itnim->ditn = ditn;
-
- bfa_stats(itnim, creates);
- bfa_sm_send_event(itnim, BFA_ITNIM_SM_CREATE);
-
- return itnim;
-}
-
-void
-bfa_itnim_delete(struct bfa_itnim_s *itnim)
-{
- bfa_stats(itnim, deletes);
- bfa_sm_send_event(itnim, BFA_ITNIM_SM_DELETE);
-}
-
-void
-bfa_itnim_online(struct bfa_itnim_s *itnim, bfa_boolean_t seq_rec)
-{
- itnim->seq_rec = seq_rec;
- bfa_stats(itnim, onlines);
- bfa_sm_send_event(itnim, BFA_ITNIM_SM_ONLINE);
-}
-
-void
-bfa_itnim_offline(struct bfa_itnim_s *itnim)
-{
- bfa_stats(itnim, offlines);
- bfa_sm_send_event(itnim, BFA_ITNIM_SM_OFFLINE);
-}
-
-/**
- * Return true if itnim is considered offline for holding off IO request.
- * IO is not held if itnim is being deleted.
- */
-bfa_boolean_t
-bfa_itnim_hold_io(struct bfa_itnim_s *itnim)
-{
- return
- itnim->fcpim->path_tov && itnim->iotov_active &&
- (bfa_sm_cmp_state(itnim, bfa_itnim_sm_fwcreate) ||
- bfa_sm_cmp_state(itnim, bfa_itnim_sm_sler) ||
- bfa_sm_cmp_state(itnim, bfa_itnim_sm_cleanup_offline) ||
- bfa_sm_cmp_state(itnim, bfa_itnim_sm_fwdelete) ||
- bfa_sm_cmp_state(itnim, bfa_itnim_sm_offline) ||
- bfa_sm_cmp_state(itnim, bfa_itnim_sm_iocdisable))
- ;
-}
-
-void
-bfa_itnim_get_stats(struct bfa_itnim_s *itnim,
- struct bfa_itnim_hal_stats_s *stats)
-{
- *stats = itnim->stats;
-}
-
-void
-bfa_itnim_clear_stats(struct bfa_itnim_s *itnim)
-{
- bfa_os_memset(&itnim->stats, 0, sizeof(itnim->stats));
-}
-
-
diff --git a/drivers/scsi/bfa/bfa_log.c b/drivers/scsi/bfa/bfa_log.c
deleted file mode 100644
index e7514016c9c6..000000000000
--- a/drivers/scsi/bfa/bfa_log.c
+++ /dev/null
@@ -1,346 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/**
- * bfa_log.c BFA log library
- */
-
-#include <bfa_os_inc.h>
-#include <cs/bfa_log.h>
-
-/*
- * global log info structure
- */
-struct bfa_log_info_s {
- u32 start_idx; /* start index for a module */
- u32 total_count; /* total count for a module */
- enum bfa_log_severity level; /* global log level */
- bfa_log_cb_t cbfn; /* callback function */
-};
-
-static struct bfa_log_info_s bfa_log_info[BFA_LOG_MODULE_ID_MAX + 1];
-static u32 bfa_log_msg_total_count;
-static int bfa_log_initialized;
-
-static char *bfa_log_severity[] =
- { "[none]", "[critical]", "[error]", "[warn]", "[info]", "" };
-
-/**
- * BFA log library initialization
- *
- * The log library initialization includes the following,
- * - set log instance name and callback function
- * - read the message array generated from xml files
- * - calculate start index for each module
- * - calculate message count for each module
- * - perform error checking
- *
- * @param[in] log_mod - log module info
- * @param[in] instance_name - instance name
- * @param[in] cbfn - callback function
- *
- * It return 0 on success, or -1 on failure
- */
-int
-bfa_log_init(struct bfa_log_mod_s *log_mod, char *instance_name,
- bfa_log_cb_t cbfn)
-{
- struct bfa_log_msgdef_s *msg;
- u32 pre_mod_id = 0;
- u32 cur_mod_id = 0;
- u32 i, pre_idx, idx, msg_id;
-
- /*
- * set instance name
- */
- if (log_mod) {
- strncpy(log_mod->instance_info, instance_name,
- sizeof(log_mod->instance_info));
- log_mod->cbfn = cbfn;
- for (i = 0; i <= BFA_LOG_MODULE_ID_MAX; i++)
- log_mod->log_level[i] = BFA_LOG_WARNING;
- }
-
- if (bfa_log_initialized)
- return 0;
-
- for (i = 0; i <= BFA_LOG_MODULE_ID_MAX; i++) {
- bfa_log_info[i].start_idx = 0;
- bfa_log_info[i].total_count = 0;
- bfa_log_info[i].level = BFA_LOG_WARNING;
- bfa_log_info[i].cbfn = cbfn;
- }
-
- pre_idx = 0;
- idx = 0;
- msg = bfa_log_msg_array;
- msg_id = BFA_LOG_GET_MSG_ID(msg);
- pre_mod_id = BFA_LOG_GET_MOD_ID(msg_id);
- while (msg_id != 0) {
- cur_mod_id = BFA_LOG_GET_MOD_ID(msg_id);
-
- if (cur_mod_id > BFA_LOG_MODULE_ID_MAX) {
- cbfn(log_mod, msg_id,
- "%s%s log: module id %u out of range\n",
- BFA_LOG_CAT_NAME,
- bfa_log_severity[BFA_LOG_ERROR],
- cur_mod_id);
- return -1;
- }
-
- if (pre_mod_id > BFA_LOG_MODULE_ID_MAX) {
- cbfn(log_mod, msg_id,
- "%s%s log: module id %u out of range\n",
- BFA_LOG_CAT_NAME,
- bfa_log_severity[BFA_LOG_ERROR],
- pre_mod_id);
- return -1;
- }
-
- if (cur_mod_id != pre_mod_id) {
- bfa_log_info[pre_mod_id].start_idx = pre_idx;
- bfa_log_info[pre_mod_id].total_count = idx - pre_idx;
- pre_mod_id = cur_mod_id;
- pre_idx = idx;
- }
-
- idx++;
- msg++;
- msg_id = BFA_LOG_GET_MSG_ID(msg);
- }
-
- bfa_log_info[cur_mod_id].start_idx = pre_idx;
- bfa_log_info[cur_mod_id].total_count = idx - pre_idx;
- bfa_log_msg_total_count = idx;
-
- cbfn(log_mod, msg_id, "%s%s log: init OK, msg total count %u\n",
- BFA_LOG_CAT_NAME,
- bfa_log_severity[BFA_LOG_INFO], bfa_log_msg_total_count);
-
- bfa_log_initialized = 1;
-
- return 0;
-}
-
-/**
- * BFA log set log level for a module
- *
- * @param[in] log_mod - log module info
- * @param[in] mod_id - module id
- * @param[in] log_level - log severity level
- *
- * It return BFA_STATUS_OK on success, or > 0 on failure
- */
-bfa_status_t
-bfa_log_set_level(struct bfa_log_mod_s *log_mod, int mod_id,
- enum bfa_log_severity log_level)
-{
- if (mod_id <= BFA_LOG_UNUSED_ID || mod_id > BFA_LOG_MODULE_ID_MAX)
- return BFA_STATUS_EINVAL;
-
- if (log_level <= BFA_LOG_INVALID || log_level > BFA_LOG_LEVEL_MAX)
- return BFA_STATUS_EINVAL;
-
- if (log_mod)
- log_mod->log_level[mod_id] = log_level;
- else
- bfa_log_info[mod_id].level = log_level;
-
- return BFA_STATUS_OK;
-}
-
-/**
- * BFA log set log level for all modules
- *
- * @param[in] log_mod - log module info
- * @param[in] log_level - log severity level
- *
- * It return BFA_STATUS_OK on success, or > 0 on failure
- */
-bfa_status_t
-bfa_log_set_level_all(struct bfa_log_mod_s *log_mod,
- enum bfa_log_severity log_level)
-{
- int mod_id = BFA_LOG_UNUSED_ID + 1;
-
- if (log_level <= BFA_LOG_INVALID || log_level > BFA_LOG_LEVEL_MAX)
- return BFA_STATUS_EINVAL;
-
- if (log_mod) {
- for (; mod_id <= BFA_LOG_MODULE_ID_MAX; mod_id++)
- log_mod->log_level[mod_id] = log_level;
- } else {
- for (; mod_id <= BFA_LOG_MODULE_ID_MAX; mod_id++)
- bfa_log_info[mod_id].level = log_level;
- }
-
- return BFA_STATUS_OK;
-}
-
-/**
- * BFA log set log level for all aen sub-modules
- *
- * @param[in] log_mod - log module info
- * @param[in] log_level - log severity level
- *
- * It return BFA_STATUS_OK on success, or > 0 on failure
- */
-bfa_status_t
-bfa_log_set_level_aen(struct bfa_log_mod_s *log_mod,
- enum bfa_log_severity log_level)
-{
- int mod_id = BFA_LOG_AEN_MIN + 1;
-
- if (log_mod) {
- for (; mod_id <= BFA_LOG_AEN_MAX; mod_id++)
- log_mod->log_level[mod_id] = log_level;
- } else {
- for (; mod_id <= BFA_LOG_AEN_MAX; mod_id++)
- bfa_log_info[mod_id].level = log_level;
- }
-
- return BFA_STATUS_OK;
-}
-
-/**
- * BFA log get log level for a module
- *
- * @param[in] log_mod - log module info
- * @param[in] mod_id - module id
- *
- * It returns log level or -1 on error
- */
-enum bfa_log_severity
-bfa_log_get_level(struct bfa_log_mod_s *log_mod, int mod_id)
-{
- if (mod_id <= BFA_LOG_UNUSED_ID || mod_id > BFA_LOG_MODULE_ID_MAX)
- return BFA_LOG_INVALID;
-
- if (log_mod)
- return log_mod->log_level[mod_id];
- else
- return bfa_log_info[mod_id].level;
-}
-
-enum bfa_log_severity
-bfa_log_get_msg_level(struct bfa_log_mod_s *log_mod, u32 msg_id)
-{
- struct bfa_log_msgdef_s *msg;
- u32 mod = BFA_LOG_GET_MOD_ID(msg_id);
- u32 idx = BFA_LOG_GET_MSG_IDX(msg_id) - 1;
-
- if (!bfa_log_initialized)
- return BFA_LOG_INVALID;
-
- if (mod > BFA_LOG_MODULE_ID_MAX)
- return BFA_LOG_INVALID;
-
- if (idx >= bfa_log_info[mod].total_count) {
- bfa_log_info[mod].cbfn(log_mod, msg_id,
- "%s%s log: inconsistent idx %u vs. total count %u\n",
- BFA_LOG_CAT_NAME, bfa_log_severity[BFA_LOG_ERROR], idx,
- bfa_log_info[mod].total_count);
- return BFA_LOG_INVALID;
- }
-
- msg = bfa_log_msg_array + bfa_log_info[mod].start_idx + idx;
- if (msg_id != BFA_LOG_GET_MSG_ID(msg)) {
- bfa_log_info[mod].cbfn(log_mod, msg_id,
- "%s%s log: inconsistent msg id %u array msg id %u\n",
- BFA_LOG_CAT_NAME, bfa_log_severity[BFA_LOG_ERROR],
- msg_id, BFA_LOG_GET_MSG_ID(msg));
- return BFA_LOG_INVALID;
- }
-
- return BFA_LOG_GET_SEVERITY(msg);
-}
-
-/**
- * BFA log message handling
- *
- * BFA log message handling finds the message based on message id and prints
- * out the message based on its format and arguments. It also does prefix
- * the severity etc.
- *
- * @param[in] log_mod - log module info
- * @param[in] msg_id - message id
- * @param[in] ... - message arguments
- *
- * It return 0 on success, or -1 on errors
- */
-int
-bfa_log(struct bfa_log_mod_s *log_mod, u32 msg_id, ...)
-{
- va_list ap;
- char buf[256];
- struct bfa_log_msgdef_s *msg;
- int log_level;
- u32 mod = BFA_LOG_GET_MOD_ID(msg_id);
- u32 idx = BFA_LOG_GET_MSG_IDX(msg_id) - 1;
-
- if (!bfa_log_initialized)
- return -1;
-
- if (mod > BFA_LOG_MODULE_ID_MAX)
- return -1;
-
- if (idx >= bfa_log_info[mod].total_count) {
- bfa_log_info[mod].
- cbfn
- (log_mod, msg_id,
- "%s%s log: inconsistent idx %u vs. total count %u\n",
- BFA_LOG_CAT_NAME, bfa_log_severity[BFA_LOG_ERROR], idx,
- bfa_log_info[mod].total_count);
- return -1;
- }
-
- msg = bfa_log_msg_array + bfa_log_info[mod].start_idx + idx;
- if (msg_id != BFA_LOG_GET_MSG_ID(msg)) {
- bfa_log_info[mod].
- cbfn
- (log_mod, msg_id,
- "%s%s log: inconsistent msg id %u array msg id %u\n",
- BFA_LOG_CAT_NAME, bfa_log_severity[BFA_LOG_ERROR],
- msg_id, BFA_LOG_GET_MSG_ID(msg));
- return -1;
- }
-
- log_level = log_mod ? log_mod->log_level[mod] : bfa_log_info[mod].level;
- if ((BFA_LOG_GET_SEVERITY(msg) > log_level) &&
- (msg->attributes != BFA_LOG_ATTR_NONE))
- return 0;
-
- va_start(ap, msg_id);
- bfa_os_vsprintf(buf, BFA_LOG_GET_MSG_FMT_STRING(msg), ap);
- va_end(ap);
-
- if (log_mod)
- log_mod->cbfn(log_mod, msg_id, "%s[%s]%s%s %s: %s\n",
- BFA_LOG_CAT_NAME, log_mod->instance_info,
- bfa_log_severity[BFA_LOG_GET_SEVERITY(msg)],
- (msg->attributes & BFA_LOG_ATTR_AUDIT)
- ? " (audit) " : "", msg->msg_value, buf);
- else
- bfa_log_info[mod].cbfn(log_mod, msg_id, "%s%s%s %s: %s\n",
- BFA_LOG_CAT_NAME,
- bfa_log_severity[BFA_LOG_GET_SEVERITY(msg)],
- (msg->attributes & BFA_LOG_ATTR_AUDIT) ?
- " (audit) " : "", msg->msg_value, buf);
-
- return 0;
-}
-
diff --git a/drivers/scsi/bfa/bfa_log_module.c b/drivers/scsi/bfa/bfa_log_module.c
deleted file mode 100644
index cf577ef7cb97..000000000000
--- a/drivers/scsi/bfa/bfa_log_module.c
+++ /dev/null
@@ -1,537 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#include <cs/bfa_log.h>
-#include <aen/bfa_aen_adapter.h>
-#include <aen/bfa_aen_audit.h>
-#include <aen/bfa_aen_ethport.h>
-#include <aen/bfa_aen_ioc.h>
-#include <aen/bfa_aen_itnim.h>
-#include <aen/bfa_aen_lport.h>
-#include <aen/bfa_aen_port.h>
-#include <aen/bfa_aen_rport.h>
-#include <log/bfa_log_fcs.h>
-#include <log/bfa_log_hal.h>
-#include <log/bfa_log_linux.h>
-#include <log/bfa_log_wdrv.h>
-
-struct bfa_log_msgdef_s bfa_log_msg_array[] = {
-
-
-/* messages define for BFA_AEN_CAT_ADAPTER Module */
-{BFA_AEN_ADAPTER_ADD, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_ADAPTER_ADD",
- "New adapter found: SN = %s, base port WWN = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_ADAPTER_REMOVE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_WARNING, "BFA_AEN_ADAPTER_REMOVE",
- "Adapter removed: SN = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-
-
-
-/* messages define for BFA_AEN_CAT_AUDIT Module */
-{BFA_AEN_AUDIT_AUTH_ENABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "BFA_AEN_AUDIT_AUTH_ENABLE",
- "Authentication enabled for base port: WWN = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_AUDIT_AUTH_DISABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "BFA_AEN_AUDIT_AUTH_DISABLE",
- "Authentication disabled for base port: WWN = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-
-
-
-/* messages define for BFA_AEN_CAT_ETHPORT Module */
-{BFA_AEN_ETHPORT_LINKUP, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_ETHPORT_LINKUP",
- "Base port ethernet linkup: mac = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_ETHPORT_LINKDOWN, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_ETHPORT_LINKDOWN",
- "Base port ethernet linkdown: mac = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_ETHPORT_ENABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_ETHPORT_ENABLE",
- "Base port ethernet interface enabled: mac = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_ETHPORT_DISABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_ETHPORT_DISABLE",
- "Base port ethernet interface disabled: mac = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-
-
-
-/* messages define for BFA_AEN_CAT_IOC Module */
-{BFA_AEN_IOC_HBGOOD, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_IOC_HBGOOD",
- "Heart Beat of IOC %d is good.",
- ((BFA_LOG_D << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_IOC_HBFAIL, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_CRITICAL,
- "BFA_AEN_IOC_HBFAIL",
- "Heart Beat of IOC %d has failed.",
- ((BFA_LOG_D << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_IOC_ENABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_IOC_ENABLE",
- "IOC %d is enabled.",
- ((BFA_LOG_D << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_IOC_DISABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_IOC_DISABLE",
- "IOC %d is disabled.",
- ((BFA_LOG_D << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_IOC_FWMISMATCH, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_CRITICAL, "BFA_AEN_IOC_FWMISMATCH",
- "Running firmware version is incompatible with the driver version.",
- (0), 0},
-
-{BFA_AEN_IOC_FWCFG_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_CRITICAL, "BFA_AEN_IOC_FWCFG_ERROR",
- "Link initialization failed due to firmware configuration read error:"
- " WWN = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_IOC_INVALID_VENDOR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_ERROR, "BFA_AEN_IOC_INVALID_VENDOR",
- "Unsupported switch vendor. Link initialization failed: WWN = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_IOC_INVALID_NWWN, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_ERROR, "BFA_AEN_IOC_INVALID_NWWN",
- "Invalid NWWN. Link initialization failed: NWWN = 00:00:00:00:00:00:00:00.",
- (0), 0},
-
-{BFA_AEN_IOC_INVALID_PWWN, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_ERROR, "BFA_AEN_IOC_INVALID_PWWN",
- "Invalid PWWN. Link initialization failed: PWWN = 00:00:00:00:00:00:00:00.",
- (0), 0},
-
-
-
-
-/* messages define for BFA_AEN_CAT_ITNIM Module */
-{BFA_AEN_ITNIM_ONLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_ITNIM_ONLINE",
- "Target (WWN = %s) is online for initiator (WWN = %s).",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_ITNIM_OFFLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_ITNIM_OFFLINE",
- "Target (WWN = %s) offlined by initiator (WWN = %s).",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_ITNIM_DISCONNECT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_ERROR, "BFA_AEN_ITNIM_DISCONNECT",
- "Target (WWN = %s) connectivity lost for initiator (WWN = %s).",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-
-
-
-/* messages define for BFA_AEN_CAT_LPORT Module */
-{BFA_AEN_LPORT_NEW, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_LPORT_NEW",
- "New logical port created: WWN = %s, Role = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_LPORT_DELETE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_LPORT_DELETE",
- "Logical port deleted: WWN = %s, Role = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_LPORT_ONLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_LPORT_ONLINE",
- "Logical port online: WWN = %s, Role = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_LPORT_OFFLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_LPORT_OFFLINE",
- "Logical port taken offline: WWN = %s, Role = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_LPORT_DISCONNECT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_ERROR, "BFA_AEN_LPORT_DISCONNECT",
- "Logical port lost fabric connectivity: WWN = %s, Role = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_LPORT_NEW_PROP, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_LPORT_NEW_PROP",
- "New virtual port created using proprietary interface: WWN = %s, Role = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_LPORT_DELETE_PROP, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "BFA_AEN_LPORT_DELETE_PROP",
- "Virtual port deleted using proprietary interface: WWN = %s, Role = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_LPORT_NEW_STANDARD, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "BFA_AEN_LPORT_NEW_STANDARD",
- "New virtual port created using standard interface: WWN = %s, Role = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_LPORT_DELETE_STANDARD, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "BFA_AEN_LPORT_DELETE_STANDARD",
- "Virtual port deleted using standard interface: WWN = %s, Role = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_LPORT_NPIV_DUP_WWN, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_WARNING, "BFA_AEN_LPORT_NPIV_DUP_WWN",
- "Virtual port login failed. Duplicate WWN = %s reported by fabric.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_LPORT_NPIV_FABRIC_MAX, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_WARNING, "BFA_AEN_LPORT_NPIV_FABRIC_MAX",
- "Virtual port (WWN = %s) login failed. Max NPIV ports already exist in"
- " fabric/fport.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_LPORT_NPIV_UNKNOWN, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_WARNING, "BFA_AEN_LPORT_NPIV_UNKNOWN",
- "Virtual port (WWN = %s) login failed.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-
-
-
-/* messages define for BFA_AEN_CAT_PORT Module */
-{BFA_AEN_PORT_ONLINE, BFA_LOG_ATTR_NONE, BFA_LOG_INFO, "BFA_AEN_PORT_ONLINE",
- "Base port online: WWN = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_PORT_OFFLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_WARNING,
- "BFA_AEN_PORT_OFFLINE",
- "Base port offline: WWN = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_PORT_RLIR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_PORT_RLIR",
- "RLIR event not supported.",
- (0), 0},
-
-{BFA_AEN_PORT_SFP_INSERT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_PORT_SFP_INSERT",
- "New SFP found: WWN/MAC = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_PORT_SFP_REMOVE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_WARNING, "BFA_AEN_PORT_SFP_REMOVE",
- "SFP removed: WWN/MAC = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_PORT_SFP_POM, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_WARNING,
- "BFA_AEN_PORT_SFP_POM",
- "SFP POM level to %s: WWN/MAC = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_PORT_ENABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_PORT_ENABLE",
- "Base port enabled: WWN = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_PORT_DISABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_PORT_DISABLE",
- "Base port disabled: WWN = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_PORT_AUTH_ON, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_PORT_AUTH_ON",
- "Authentication successful for base port: WWN = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_PORT_AUTH_OFF, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_ERROR,
- "BFA_AEN_PORT_AUTH_OFF",
- "Authentication unsuccessful for base port: WWN = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_PORT_DISCONNECT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_ERROR,
- "BFA_AEN_PORT_DISCONNECT",
- "Base port (WWN = %s) lost fabric connectivity.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_PORT_QOS_NEG, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_WARNING,
- "BFA_AEN_PORT_QOS_NEG",
- "QOS negotiation failed for base port: WWN = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_PORT_FABRIC_NAME_CHANGE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_WARNING, "BFA_AEN_PORT_FABRIC_NAME_CHANGE",
- "Base port WWN = %s, Fabric WWN = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_PORT_SFP_ACCESS_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_WARNING, "BFA_AEN_PORT_SFP_ACCESS_ERROR",
- "SFP access error: WWN/MAC = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_PORT_SFP_UNSUPPORT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_WARNING, "BFA_AEN_PORT_SFP_UNSUPPORT",
- "Unsupported SFP found: WWN/MAC = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-
-
-
-/* messages define for BFA_AEN_CAT_RPORT Module */
-{BFA_AEN_RPORT_ONLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_RPORT_ONLINE",
- "Remote port (WWN = %s) online for logical port (WWN = %s).",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_RPORT_OFFLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_RPORT_OFFLINE",
- "Remote port (WWN = %s) offlined by logical port (WWN = %s).",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_RPORT_DISCONNECT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_ERROR, "BFA_AEN_RPORT_DISCONNECT",
- "Remote port (WWN = %s) connectivity lost for logical port (WWN = %s).",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_RPORT_QOS_PRIO, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_RPORT_QOS_PRIO",
- "QOS priority changed to %s: RPWWN = %s and LPWWN = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) |
- (BFA_LOG_S << BFA_LOG_ARG2) | 0), 3},
-
-{BFA_AEN_RPORT_QOS_FLOWID, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_RPORT_QOS_FLOWID",
- "QOS flow ID changed to %d: RPWWN = %s and LPWWN = %s.",
- ((BFA_LOG_D << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) |
- (BFA_LOG_S << BFA_LOG_ARG2) | 0), 3},
-
-
-
-
-/* messages define for FCS Module */
-{BFA_LOG_FCS_FABRIC_NOSWITCH, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "FCS_FABRIC_NOSWITCH",
- "No switched fabric presence is detected.",
- (0), 0},
-
-{BFA_LOG_FCS_FABRIC_ISOLATED, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "FCS_FABRIC_ISOLATED",
- "Port is isolated due to VF_ID mismatch. PWWN: %s, Port VF_ID: %04x and"
- " switch port VF_ID: %04x.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_X << BFA_LOG_ARG1) |
- (BFA_LOG_X << BFA_LOG_ARG2) | 0), 3},
-
-
-
-
-/* messages define for HAL Module */
-{BFA_LOG_HAL_ASSERT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_ERROR,
- "HAL_ASSERT",
- "Assertion failure: %s:%d: %s",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_D << BFA_LOG_ARG1) |
- (BFA_LOG_S << BFA_LOG_ARG2) | 0), 3},
-
-{BFA_LOG_HAL_HEARTBEAT_FAILURE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_CRITICAL, "HAL_HEARTBEAT_FAILURE",
- "Firmware heartbeat failure at %d",
- ((BFA_LOG_D << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_HAL_FCPIM_PARM_INVALID, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "HAL_FCPIM_PARM_INVALID",
- "Driver configuration %s value %d is invalid. Value should be within"
- " %d and %d.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_D << BFA_LOG_ARG1) |
- (BFA_LOG_D << BFA_LOG_ARG2) | (BFA_LOG_D << BFA_LOG_ARG3) | 0), 4},
-
-{BFA_LOG_HAL_SM_ASSERT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_ERROR,
- "HAL_SM_ASSERT",
- "SM Assertion failure: %s:%d: event = %d",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_D << BFA_LOG_ARG1) |
- (BFA_LOG_D << BFA_LOG_ARG2) | 0), 3},
-
-{BFA_LOG_HAL_DRIVER_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "HAL_DRIVER_ERROR",
- "%s",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_HAL_DRIVER_CONFIG_ERROR,
- BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "HAL_DRIVER_CONFIG_ERROR",
- "%s",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_HAL_MBOX_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "HAL_MBOX_ERROR",
- "%s",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-
-
-
-/* messages define for LINUX Module */
-{BFA_LOG_LINUX_DEVICE_CLAIMED, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "LINUX_DEVICE_CLAIMED",
- "bfa device at %s claimed.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_LINUX_HASH_INIT_FAILED, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "LINUX_HASH_INIT_FAILED",
- "Hash table initialization failure for the port %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_LINUX_SYSFS_FAILED, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "LINUX_SYSFS_FAILED",
- "sysfs file creation failure for the port %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_LINUX_MEM_ALLOC_FAILED, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "LINUX_MEM_ALLOC_FAILED",
- "Memory allocation failed: %s. ",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_LINUX_DRIVER_REGISTRATION_FAILED,
- BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "LINUX_DRIVER_REGISTRATION_FAILED",
- "%s. ",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_LINUX_ITNIM_FREE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "LINUX_ITNIM_FREE",
- "scsi%d: FCID: %s WWPN: %s",
- ((BFA_LOG_D << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) |
- (BFA_LOG_S << BFA_LOG_ARG2) | 0), 3},
-
-{BFA_LOG_LINUX_ITNIM_ONLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "LINUX_ITNIM_ONLINE",
- "Target: %d:0:%d FCID: %s WWPN: %s",
- ((BFA_LOG_D << BFA_LOG_ARG0) | (BFA_LOG_D << BFA_LOG_ARG1) |
- (BFA_LOG_S << BFA_LOG_ARG2) | (BFA_LOG_S << BFA_LOG_ARG3) | 0), 4},
-
-{BFA_LOG_LINUX_ITNIM_OFFLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "LINUX_ITNIM_OFFLINE",
- "Target: %d:0:%d FCID: %s WWPN: %s",
- ((BFA_LOG_D << BFA_LOG_ARG0) | (BFA_LOG_D << BFA_LOG_ARG1) |
- (BFA_LOG_S << BFA_LOG_ARG2) | (BFA_LOG_S << BFA_LOG_ARG3) | 0), 4},
-
-{BFA_LOG_LINUX_SCSI_HOST_FREE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "LINUX_SCSI_HOST_FREE",
- "Free scsi%d",
- ((BFA_LOG_D << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_LINUX_SCSI_ABORT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "LINUX_SCSI_ABORT",
- "scsi%d: abort cmnd %p, iotag %x",
- ((BFA_LOG_D << BFA_LOG_ARG0) | (BFA_LOG_P << BFA_LOG_ARG1) |
- (BFA_LOG_X << BFA_LOG_ARG2) | 0), 3},
-
-{BFA_LOG_LINUX_SCSI_ABORT_COMP, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "LINUX_SCSI_ABORT_COMP",
- "scsi%d: complete abort 0x%p, iotag 0x%x",
- ((BFA_LOG_D << BFA_LOG_ARG0) | (BFA_LOG_P << BFA_LOG_ARG1) |
- (BFA_LOG_X << BFA_LOG_ARG2) | 0), 3},
-
-{BFA_LOG_LINUX_DRIVER_CONFIG_ERROR,
- BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "LINUX_DRIVER_CONFIG_ERROR",
- "%s",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_LINUX_BNA_STATE_MACHINE,
- BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "LINUX_BNA_STATE_MACHINE",
- "%s",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_LINUX_IOC_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "LINUX_IOC_ERROR",
- "%s",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_LINUX_RESOURCE_ALLOC_ERROR,
- BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "LINUX_RESOURCE_ALLOC_ERROR",
- "%s",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_LINUX_RING_BUFFER_ERROR,
- BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "LINUX_RING_BUFFER_ERROR",
- "%s",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_LINUX_DRIVER_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_ERROR, "LINUX_DRIVER_ERROR",
- "%s",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_LINUX_DRIVER_INFO, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "LINUX_DRIVER_INFO",
- "%s",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_LINUX_DRIVER_DIAG, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "LINUX_DRIVER_DIAG",
- "%s",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_LINUX_DRIVER_AEN, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "LINUX_DRIVER_AEN",
- "%s",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-
-
-
-/* messages define for WDRV Module */
-{BFA_LOG_WDRV_IOC_INIT_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "WDRV_IOC_INIT_ERROR",
- "IOC initialization has failed.",
- (0), 0},
-
-{BFA_LOG_WDRV_IOC_INTERNAL_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "WDRV_IOC_INTERNAL_ERROR",
- "IOC internal error. ",
- (0), 0},
-
-{BFA_LOG_WDRV_IOC_START_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "WDRV_IOC_START_ERROR",
- "IOC could not be started. ",
- (0), 0},
-
-{BFA_LOG_WDRV_IOC_STOP_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "WDRV_IOC_STOP_ERROR",
- "IOC could not be stopped. ",
- (0), 0},
-
-{BFA_LOG_WDRV_INSUFFICIENT_RESOURCES, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "WDRV_INSUFFICIENT_RESOURCES",
- "Insufficient memory. ",
- (0), 0},
-
-{BFA_LOG_WDRV_BASE_ADDRESS_MAP_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "WDRV_BASE_ADDRESS_MAP_ERROR",
- "Unable to map the IOC onto the system address space. ",
- (0), 0},
-
-
-{0, 0, 0, "", "", 0, 0},
-};
diff --git a/drivers/scsi/bfa/bfa_lps.c b/drivers/scsi/bfa/bfa_lps.c
deleted file mode 100644
index acabb44f092f..000000000000
--- a/drivers/scsi/bfa/bfa_lps.c
+++ /dev/null
@@ -1,892 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#include <bfa.h>
-#include <bfi/bfi_lps.h>
-#include <cs/bfa_debug.h>
-#include <defs/bfa_defs_pci.h>
-
-BFA_TRC_FILE(HAL, LPS);
-BFA_MODULE(lps);
-
-#define BFA_LPS_MIN_LPORTS (1)
-#define BFA_LPS_MAX_LPORTS (256)
-
-/*
- * Maximum Vports supported per physical port or vf.
- */
-#define BFA_LPS_MAX_VPORTS_SUPP_CB 255
-#define BFA_LPS_MAX_VPORTS_SUPP_CT 190
-
-/**
- * forward declarations
- */
-static void bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
- u32 *dm_len);
-static void bfa_lps_attach(struct bfa_s *bfa, void *bfad,
- struct bfa_iocfc_cfg_s *cfg,
- struct bfa_meminfo_s *meminfo,
- struct bfa_pcidev_s *pcidev);
-static void bfa_lps_detach(struct bfa_s *bfa);
-static void bfa_lps_start(struct bfa_s *bfa);
-static void bfa_lps_stop(struct bfa_s *bfa);
-static void bfa_lps_iocdisable(struct bfa_s *bfa);
-static void bfa_lps_login_rsp(struct bfa_s *bfa,
- struct bfi_lps_login_rsp_s *rsp);
-static void bfa_lps_logout_rsp(struct bfa_s *bfa,
- struct bfi_lps_logout_rsp_s *rsp);
-static void bfa_lps_reqq_resume(void *lps_arg);
-static void bfa_lps_free(struct bfa_lps_s *lps);
-static void bfa_lps_send_login(struct bfa_lps_s *lps);
-static void bfa_lps_send_logout(struct bfa_lps_s *lps);
-static void bfa_lps_login_comp(struct bfa_lps_s *lps);
-static void bfa_lps_logout_comp(struct bfa_lps_s *lps);
-static void bfa_lps_cvl_event(struct bfa_lps_s *lps);
-
-/**
- * lps_pvt BFA LPS private functions
- */
-
-enum bfa_lps_event {
- BFA_LPS_SM_LOGIN = 1, /* login request from user */
- BFA_LPS_SM_LOGOUT = 2, /* logout request from user */
- BFA_LPS_SM_FWRSP = 3, /* f/w response to login/logout */
- BFA_LPS_SM_RESUME = 4, /* space present in reqq queue */
- BFA_LPS_SM_DELETE = 5, /* lps delete from user */
- BFA_LPS_SM_OFFLINE = 6, /* Link is offline */
- BFA_LPS_SM_RX_CVL = 7, /* Rx clear virtual link */
-};
-
-static void bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event);
-static void bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event);
-static void bfa_lps_sm_loginwait(struct bfa_lps_s *lps,
- enum bfa_lps_event event);
-static void bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event);
-static void bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event);
-static void bfa_lps_sm_logowait(struct bfa_lps_s *lps,
- enum bfa_lps_event event);
-
-/**
- * Init state -- no login
- */
-static void
-bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event)
-{
- bfa_trc(lps->bfa, lps->lp_tag);
- bfa_trc(lps->bfa, event);
-
- switch (event) {
- case BFA_LPS_SM_LOGIN:
- if (bfa_reqq_full(lps->bfa, lps->reqq)) {
- bfa_sm_set_state(lps, bfa_lps_sm_loginwait);
- bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);
- } else {
- bfa_sm_set_state(lps, bfa_lps_sm_login);
- bfa_lps_send_login(lps);
- }
- if (lps->fdisc)
- bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
- BFA_PL_EID_LOGIN, 0, "FDISC Request");
- else
- bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
- BFA_PL_EID_LOGIN, 0, "FLOGI Request");
- break;
-
- case BFA_LPS_SM_LOGOUT:
- bfa_lps_logout_comp(lps);
- break;
-
- case BFA_LPS_SM_DELETE:
- bfa_lps_free(lps);
- break;
-
- case BFA_LPS_SM_RX_CVL:
- case BFA_LPS_SM_OFFLINE:
- break;
-
- case BFA_LPS_SM_FWRSP:
- /* Could happen when fabric detects loopback and discards
- * the lps request. Fw will eventually sent out the timeout
- * Just ignore
- */
- break;
-
- default:
- bfa_sm_fault(lps->bfa, event);
- }
-}
-
-/**
- * login is in progress -- awaiting response from firmware
- */
-static void
-bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event)
-{
- bfa_trc(lps->bfa, lps->lp_tag);
- bfa_trc(lps->bfa, event);
-
- switch (event) {
- case BFA_LPS_SM_FWRSP:
- if (lps->status == BFA_STATUS_OK) {
- bfa_sm_set_state(lps, bfa_lps_sm_online);
- if (lps->fdisc)
- bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
- BFA_PL_EID_LOGIN, 0, "FDISC Accept");
- else
- bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
- BFA_PL_EID_LOGIN, 0, "FLOGI Accept");
- } else {
- bfa_sm_set_state(lps, bfa_lps_sm_init);
- if (lps->fdisc)
- bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
- BFA_PL_EID_LOGIN, 0,
- "FDISC Fail (RJT or timeout)");
- else
- bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
- BFA_PL_EID_LOGIN, 0,
- "FLOGI Fail (RJT or timeout)");
- }
- bfa_lps_login_comp(lps);
- break;
-
- case BFA_LPS_SM_OFFLINE:
- bfa_sm_set_state(lps, bfa_lps_sm_init);
- break;
-
- default:
- bfa_sm_fault(lps->bfa, event);
- }
-}
-
-/**
- * login pending - awaiting space in request queue
- */
-static void
-bfa_lps_sm_loginwait(struct bfa_lps_s *lps, enum bfa_lps_event event)
-{
- bfa_trc(lps->bfa, lps->lp_tag);
- bfa_trc(lps->bfa, event);
-
- switch (event) {
- case BFA_LPS_SM_RESUME:
- bfa_sm_set_state(lps, bfa_lps_sm_login);
- break;
-
- case BFA_LPS_SM_OFFLINE:
- bfa_sm_set_state(lps, bfa_lps_sm_init);
- bfa_reqq_wcancel(&lps->wqe);
- break;
-
- case BFA_LPS_SM_RX_CVL:
- /*
- * Login was not even sent out; so when getting out
- * of this state, it will appear like a login retry
- * after Clear virtual link
- */
- break;
-
- default:
- bfa_sm_fault(lps->bfa, event);
- }
-}
-
-/**
- * login complete
- */
-static void
-bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event)
-{
- bfa_trc(lps->bfa, lps->lp_tag);
- bfa_trc(lps->bfa, event);
-
- switch (event) {
- case BFA_LPS_SM_LOGOUT:
- if (bfa_reqq_full(lps->bfa, lps->reqq)) {
- bfa_sm_set_state(lps, bfa_lps_sm_logowait);
- bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);
- } else {
- bfa_sm_set_state(lps, bfa_lps_sm_logout);
- bfa_lps_send_logout(lps);
- }
- bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
- BFA_PL_EID_LOGO, 0, "Logout");
- break;
-
- case BFA_LPS_SM_RX_CVL:
- bfa_sm_set_state(lps, bfa_lps_sm_init);
-
- /* Let the vport module know about this event */
- bfa_lps_cvl_event(lps);
- bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
- BFA_PL_EID_FIP_FCF_CVL, 0, "FCF Clear Virt. Link Rx");
- break;
-
- case BFA_LPS_SM_OFFLINE:
- case BFA_LPS_SM_DELETE:
- bfa_sm_set_state(lps, bfa_lps_sm_init);
- break;
-
- default:
- bfa_sm_fault(lps->bfa, event);
- }
-}
-
-/**
- * logout in progress - awaiting firmware response
- */
-static void
-bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event)
-{
- bfa_trc(lps->bfa, lps->lp_tag);
- bfa_trc(lps->bfa, event);
-
- switch (event) {
- case BFA_LPS_SM_FWRSP:
- bfa_sm_set_state(lps, bfa_lps_sm_init);
- bfa_lps_logout_comp(lps);
- break;
-
- case BFA_LPS_SM_OFFLINE:
- bfa_sm_set_state(lps, bfa_lps_sm_init);
- break;
-
- default:
- bfa_sm_fault(lps->bfa, event);
- }
-}
-
-/**
- * logout pending -- awaiting space in request queue
- */
-static void
-bfa_lps_sm_logowait(struct bfa_lps_s *lps, enum bfa_lps_event event)
-{
- bfa_trc(lps->bfa, lps->lp_tag);
- bfa_trc(lps->bfa, event);
-
- switch (event) {
- case BFA_LPS_SM_RESUME:
- bfa_sm_set_state(lps, bfa_lps_sm_logout);
- bfa_lps_send_logout(lps);
- break;
-
- case BFA_LPS_SM_OFFLINE:
- bfa_sm_set_state(lps, bfa_lps_sm_init);
- bfa_reqq_wcancel(&lps->wqe);
- break;
-
- default:
- bfa_sm_fault(lps->bfa, event);
- }
-}
-
-
-
-/**
- * lps_pvt BFA LPS private functions
- */
-
-/**
- * return memory requirement
- */
-static void
-bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len, u32 *dm_len)
-{
- if (cfg->drvcfg.min_cfg)
- *ndm_len += sizeof(struct bfa_lps_s) * BFA_LPS_MIN_LPORTS;
- else
- *ndm_len += sizeof(struct bfa_lps_s) * BFA_LPS_MAX_LPORTS;
-}
-
-/**
- * bfa module attach at initialization time
- */
-static void
-bfa_lps_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
- struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
-{
- struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa);
- struct bfa_lps_s *lps;
- int i;
-
- bfa_os_memset(mod, 0, sizeof(struct bfa_lps_mod_s));
- mod->num_lps = BFA_LPS_MAX_LPORTS;
- if (cfg->drvcfg.min_cfg)
- mod->num_lps = BFA_LPS_MIN_LPORTS;
- else
- mod->num_lps = BFA_LPS_MAX_LPORTS;
- mod->lps_arr = lps = (struct bfa_lps_s *) bfa_meminfo_kva(meminfo);
-
- bfa_meminfo_kva(meminfo) += mod->num_lps * sizeof(struct bfa_lps_s);
-
- INIT_LIST_HEAD(&mod->lps_free_q);
- INIT_LIST_HEAD(&mod->lps_active_q);
-
- for (i = 0; i < mod->num_lps; i++, lps++) {
- lps->bfa = bfa;
- lps->lp_tag = (u8) i;
- lps->reqq = BFA_REQQ_LPS;
- bfa_reqq_winit(&lps->wqe, bfa_lps_reqq_resume, lps);
- list_add_tail(&lps->qe, &mod->lps_free_q);
- }
-}
-
-static void
-bfa_lps_detach(struct bfa_s *bfa)
-{
-}
-
-static void
-bfa_lps_start(struct bfa_s *bfa)
-{
-}
-
-static void
-bfa_lps_stop(struct bfa_s *bfa)
-{
-}
-
-/**
- * IOC in disabled state -- consider all lps offline
- */
-static void
-bfa_lps_iocdisable(struct bfa_s *bfa)
-{
- struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa);
- struct bfa_lps_s *lps;
- struct list_head *qe, *qen;
-
- list_for_each_safe(qe, qen, &mod->lps_active_q) {
- lps = (struct bfa_lps_s *) qe;
- bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE);
- }
-}
-
-/**
- * Firmware login response
- */
-static void
-bfa_lps_login_rsp(struct bfa_s *bfa, struct bfi_lps_login_rsp_s *rsp)
-{
- struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa);
- struct bfa_lps_s *lps;
-
- bfa_assert(rsp->lp_tag < mod->num_lps);
- lps = BFA_LPS_FROM_TAG(mod, rsp->lp_tag);
-
- lps->status = rsp->status;
- switch (rsp->status) {
- case BFA_STATUS_OK:
- lps->fport = rsp->f_port;
- lps->npiv_en = rsp->npiv_en;
- lps->lp_pid = rsp->lp_pid;
- lps->pr_bbcred = bfa_os_ntohs(rsp->bb_credit);
- lps->pr_pwwn = rsp->port_name;
- lps->pr_nwwn = rsp->node_name;
- lps->auth_req = rsp->auth_req;
- lps->lp_mac = rsp->lp_mac;
- lps->brcd_switch = rsp->brcd_switch;
- lps->fcf_mac = rsp->fcf_mac;
-
- break;
-
- case BFA_STATUS_FABRIC_RJT:
- lps->lsrjt_rsn = rsp->lsrjt_rsn;
- lps->lsrjt_expl = rsp->lsrjt_expl;
-
- break;
-
- case BFA_STATUS_EPROTOCOL:
- lps->ext_status = rsp->ext_status;
-
- break;
-
- default:
- /* Nothing to do with other status */
- break;
- }
-
- bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
-}
-
-/**
- * Firmware logout response
- */
-static void
-bfa_lps_logout_rsp(struct bfa_s *bfa, struct bfi_lps_logout_rsp_s *rsp)
-{
- struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa);
- struct bfa_lps_s *lps;
-
- bfa_assert(rsp->lp_tag < mod->num_lps);
- lps = BFA_LPS_FROM_TAG(mod, rsp->lp_tag);
-
- bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
-}
-
-/**
- * Firmware received a Clear virtual link request (for FCoE)
- */
-static void
-bfa_lps_rx_cvl_event(struct bfa_s *bfa, struct bfi_lps_cvl_event_s *cvl)
-{
- struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa);
- struct bfa_lps_s *lps;
-
- lps = BFA_LPS_FROM_TAG(mod, cvl->lp_tag);
-
- bfa_sm_send_event(lps, BFA_LPS_SM_RX_CVL);
-}
-
-/**
- * Space is available in request queue, resume queueing request to firmware.
- */
-static void
-bfa_lps_reqq_resume(void *lps_arg)
-{
- struct bfa_lps_s *lps = lps_arg;
-
- bfa_sm_send_event(lps, BFA_LPS_SM_RESUME);
-}
-
-/**
- * lps is freed -- triggered by vport delete
- */
-static void
-bfa_lps_free(struct bfa_lps_s *lps)
-{
- struct bfa_lps_mod_s *mod = BFA_LPS_MOD(lps->bfa);
-
- list_del(&lps->qe);
- list_add_tail(&lps->qe, &mod->lps_free_q);
-}
-
-/**
- * send login request to firmware
- */
-static void
-bfa_lps_send_login(struct bfa_lps_s *lps)
-{
- struct bfi_lps_login_req_s *m;
-
- m = bfa_reqq_next(lps->bfa, lps->reqq);
- bfa_assert(m);
-
- bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGIN_REQ,
- bfa_lpuid(lps->bfa));
-
- m->lp_tag = lps->lp_tag;
- m->alpa = lps->alpa;
- m->pdu_size = bfa_os_htons(lps->pdusz);
- m->pwwn = lps->pwwn;
- m->nwwn = lps->nwwn;
- m->fdisc = lps->fdisc;
- m->auth_en = lps->auth_en;
-
- bfa_reqq_produce(lps->bfa, lps->reqq);
-}
-
-/**
- * send logout request to firmware
- */
-static void
-bfa_lps_send_logout(struct bfa_lps_s *lps)
-{
- struct bfi_lps_logout_req_s *m;
-
- m = bfa_reqq_next(lps->bfa, lps->reqq);
- bfa_assert(m);
-
- bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGOUT_REQ,
- bfa_lpuid(lps->bfa));
-
- m->lp_tag = lps->lp_tag;
- m->port_name = lps->pwwn;
- bfa_reqq_produce(lps->bfa, lps->reqq);
-}
-
-/**
- * Indirect login completion handler for non-fcs
- */
-static void
-bfa_lps_login_comp_cb(void *arg, bfa_boolean_t complete)
-{
- struct bfa_lps_s *lps = arg;
-
- if (!complete)
- return;
-
- if (lps->fdisc)
- bfa_cb_lps_fdisc_comp(lps->bfa->bfad, lps->uarg, lps->status);
- else
- bfa_cb_lps_flogi_comp(lps->bfa->bfad, lps->uarg, lps->status);
-}
-
-/**
- * Login completion handler -- direct call for fcs, queue for others
- */
-static void
-bfa_lps_login_comp(struct bfa_lps_s *lps)
-{
- if (!lps->bfa->fcs) {
- bfa_cb_queue(lps->bfa, &lps->hcb_qe,
- bfa_lps_login_comp_cb, lps);
- return;
- }
-
- if (lps->fdisc)
- bfa_cb_lps_fdisc_comp(lps->bfa->bfad, lps->uarg, lps->status);
- else
- bfa_cb_lps_flogi_comp(lps->bfa->bfad, lps->uarg, lps->status);
-}
-
-/**
- * Indirect logout completion handler for non-fcs
- */
-static void
-bfa_lps_logout_comp_cb(void *arg, bfa_boolean_t complete)
-{
- struct bfa_lps_s *lps = arg;
-
- if (!complete)
- return;
-
- if (lps->fdisc)
- bfa_cb_lps_fdisclogo_comp(lps->bfa->bfad, lps->uarg);
- else
- bfa_cb_lps_flogo_comp(lps->bfa->bfad, lps->uarg);
-}
-
-/**
- * Logout completion handler -- direct call for fcs, queue for others
- */
-static void
-bfa_lps_logout_comp(struct bfa_lps_s *lps)
-{
- if (!lps->bfa->fcs) {
- bfa_cb_queue(lps->bfa, &lps->hcb_qe,
- bfa_lps_logout_comp_cb, lps);
- return;
- }
- if (lps->fdisc)
- bfa_cb_lps_fdisclogo_comp(lps->bfa->bfad, lps->uarg);
- else
- bfa_cb_lps_flogo_comp(lps->bfa->bfad, lps->uarg);
-}
-
-/**
- * Clear virtual link completion handler for non-fcs
- */
-static void
-bfa_lps_cvl_event_cb(void *arg, bfa_boolean_t complete)
-{
- struct bfa_lps_s *lps = arg;
-
- if (!complete)
- return;
-
- /* Clear virtual link to base port will result in link down */
- if (lps->fdisc)
- bfa_cb_lps_cvl_event(lps->bfa->bfad, lps->uarg);
-}
-
-/**
- * Received Clear virtual link event --direct call for fcs,
- * queue for others
- */
-static void
-bfa_lps_cvl_event(struct bfa_lps_s *lps)
-{
- if (!lps->bfa->fcs) {
- bfa_cb_queue(lps->bfa, &lps->hcb_qe, bfa_lps_cvl_event_cb,
- lps);
- return;
- }
-
- /* Clear virtual link to base port will result in link down */
- if (lps->fdisc)
- bfa_cb_lps_cvl_event(lps->bfa->bfad, lps->uarg);
-}
-
-u32
-bfa_lps_get_max_vport(struct bfa_s *bfa)
-{
- if (bfa_ioc_devid(&bfa->ioc) == BFA_PCI_DEVICE_ID_CT)
- return BFA_LPS_MAX_VPORTS_SUPP_CT;
- else
- return BFA_LPS_MAX_VPORTS_SUPP_CB;
-}
-
-/**
- * lps_public BFA LPS public functions
- */
-
-/**
- * Allocate a lport srvice tag.
- */
-struct bfa_lps_s *
-bfa_lps_alloc(struct bfa_s *bfa)
-{
- struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa);
- struct bfa_lps_s *lps = NULL;
-
- bfa_q_deq(&mod->lps_free_q, &lps);
-
- if (lps == NULL)
- return NULL;
-
- list_add_tail(&lps->qe, &mod->lps_active_q);
-
- bfa_sm_set_state(lps, bfa_lps_sm_init);
- return lps;
-}
-
-/**
- * Free lport service tag. This can be called anytime after an alloc.
- * No need to wait for any pending login/logout completions.
- */
-void
-bfa_lps_delete(struct bfa_lps_s *lps)
-{
- bfa_sm_send_event(lps, BFA_LPS_SM_DELETE);
-}
-
-/**
- * Initiate a lport login.
- */
-void
-bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa, u16 pdusz,
- wwn_t pwwn, wwn_t nwwn, bfa_boolean_t auth_en)
-{
- lps->uarg = uarg;
- lps->alpa = alpa;
- lps->pdusz = pdusz;
- lps->pwwn = pwwn;
- lps->nwwn = nwwn;
- lps->fdisc = BFA_FALSE;
- lps->auth_en = auth_en;
- bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN);
-}
-
-/**
- * Initiate a lport fdisc login.
- */
-void
-bfa_lps_fdisc(struct bfa_lps_s *lps, void *uarg, u16 pdusz, wwn_t pwwn,
- wwn_t nwwn)
-{
- lps->uarg = uarg;
- lps->alpa = 0;
- lps->pdusz = pdusz;
- lps->pwwn = pwwn;
- lps->nwwn = nwwn;
- lps->fdisc = BFA_TRUE;
- lps->auth_en = BFA_FALSE;
- bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN);
-}
-
-/**
- * Initiate a lport logout (flogi).
- */
-void
-bfa_lps_flogo(struct bfa_lps_s *lps)
-{
- bfa_sm_send_event(lps, BFA_LPS_SM_LOGOUT);
-}
-
-/**
- * Initiate a lport FDSIC logout.
- */
-void
-bfa_lps_fdisclogo(struct bfa_lps_s *lps)
-{
- bfa_sm_send_event(lps, BFA_LPS_SM_LOGOUT);
-}
-
-/**
- * Discard a pending login request -- should be called only for
- * link down handling.
- */
-void
-bfa_lps_discard(struct bfa_lps_s *lps)
-{
- bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE);
-}
-
-/**
- * Return lport services tag
- */
-u8
-bfa_lps_get_tag(struct bfa_lps_s *lps)
-{
- return lps->lp_tag;
-}
-
-/**
- * Return lport services tag given the pid
- */
-u8
-bfa_lps_get_tag_from_pid(struct bfa_s *bfa, u32 pid)
-{
- struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa);
- struct bfa_lps_s *lps;
- int i;
-
- for (i = 0, lps = mod->lps_arr; i < mod->num_lps; i++, lps++) {
- if (lps->lp_pid == pid)
- return lps->lp_tag;
- }
-
- /* Return base port tag anyway */
- return 0;
-}
-
-/**
- * return if fabric login indicates support for NPIV
- */
-bfa_boolean_t
-bfa_lps_is_npiv_en(struct bfa_lps_s *lps)
-{
- return lps->npiv_en;
-}
-
-/**
- * Return TRUE if attached to F-Port, else return FALSE
- */
-bfa_boolean_t
-bfa_lps_is_fport(struct bfa_lps_s *lps)
-{
- return lps->fport;
-}
-
-/**
- * Return TRUE if attached to a Brocade Fabric
- */
-bfa_boolean_t
-bfa_lps_is_brcd_fabric(struct bfa_lps_s *lps)
-{
- return lps->brcd_switch;
-}
-/**
- * return TRUE if authentication is required
- */
-bfa_boolean_t
-bfa_lps_is_authreq(struct bfa_lps_s *lps)
-{
- return lps->auth_req;
-}
-
-bfa_eproto_status_t
-bfa_lps_get_extstatus(struct bfa_lps_s *lps)
-{
- return lps->ext_status;
-}
-
-/**
- * return port id assigned to the lport
- */
-u32
-bfa_lps_get_pid(struct bfa_lps_s *lps)
-{
- return lps->lp_pid;
-}
-
-/**
- * Return bb_credit assigned in FLOGI response
- */
-u16
-bfa_lps_get_peer_bbcredit(struct bfa_lps_s *lps)
-{
- return lps->pr_bbcred;
-}
-
-/**
- * Return peer port name
- */
-wwn_t
-bfa_lps_get_peer_pwwn(struct bfa_lps_s *lps)
-{
- return lps->pr_pwwn;
-}
-
-/**
- * Return peer node name
- */
-wwn_t
-bfa_lps_get_peer_nwwn(struct bfa_lps_s *lps)
-{
- return lps->pr_nwwn;
-}
-
-/**
- * return reason code if login request is rejected
- */
-u8
-bfa_lps_get_lsrjt_rsn(struct bfa_lps_s *lps)
-{
- return lps->lsrjt_rsn;
-}
-
-/**
- * return explanation code if login request is rejected
- */
-u8
-bfa_lps_get_lsrjt_expl(struct bfa_lps_s *lps)
-{
- return lps->lsrjt_expl;
-}
-
-/**
- * Return fpma/spma MAC for lport
- */
-struct mac_s
-bfa_lps_get_lp_mac(struct bfa_lps_s *lps)
-{
- return lps->lp_mac;
-}
-
-/**
- * LPS firmware message class handler.
- */
-void
-bfa_lps_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
-{
- union bfi_lps_i2h_msg_u msg;
-
- bfa_trc(bfa, m->mhdr.msg_id);
- msg.msg = m;
-
- switch (m->mhdr.msg_id) {
- case BFI_LPS_H2I_LOGIN_RSP:
- bfa_lps_login_rsp(bfa, msg.login_rsp);
- break;
-
- case BFI_LPS_H2I_LOGOUT_RSP:
- bfa_lps_logout_rsp(bfa, msg.logout_rsp);
- break;
-
- case BFI_LPS_H2I_CVL_EVENT:
- bfa_lps_rx_cvl_event(bfa, msg.cvl_event);
- break;
-
- default:
- bfa_trc(bfa, m->mhdr.msg_id);
- bfa_assert(0);
- }
-}
-
-
diff --git a/drivers/scsi/bfa/bfa_lps_priv.h b/drivers/scsi/bfa/bfa_lps_priv.h
deleted file mode 100644
index d16c6ce995df..000000000000
--- a/drivers/scsi/bfa/bfa_lps_priv.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_LPS_PRIV_H__
-#define __BFA_LPS_PRIV_H__
-
-#include <bfa_svc.h>
-
-struct bfa_lps_mod_s {
- struct list_head lps_free_q;
- struct list_head lps_active_q;
- struct bfa_lps_s *lps_arr;
- int num_lps;
-};
-
-#define BFA_LPS_MOD(__bfa) (&(__bfa)->modules.lps_mod)
-#define BFA_LPS_FROM_TAG(__mod, __tag) (&(__mod)->lps_arr[__tag])
-
-/*
- * external functions
- */
-void bfa_lps_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
-
-#endif /* __BFA_LPS_PRIV_H__ */
diff --git a/drivers/scsi/bfa/bfa_priv.h b/drivers/scsi/bfa/bfa_modules.h
index bf4939b1676c..2cd527338677 100644
--- a/drivers/scsi/bfa/bfa_priv.h
+++ b/drivers/scsi/bfa/bfa_modules.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
* All rights reserved
* www.brocade.com
*
@@ -15,26 +15,52 @@
* General Public License for more details.
*/
-#ifndef __BFA_PRIV_H__
-#define __BFA_PRIV_H__
+/**
+ * bfa_modules.h BFA modules
+ */
+
+#ifndef __BFA_MODULES_H__
+#define __BFA_MODULES_H__
+
+#include "bfa_cs.h"
+#include "bfa.h"
+#include "bfa_svc.h"
+#include "bfa_fcpim.h"
+#include "bfa_port.h"
+
+struct bfa_modules_s {
+ struct bfa_fcport_s fcport; /* fc port module */
+ struct bfa_fcxp_mod_s fcxp_mod; /* fcxp module */
+ struct bfa_lps_mod_s lps_mod; /* fcxp module */
+ struct bfa_uf_mod_s uf_mod; /* unsolicited frame module */
+ struct bfa_rport_mod_s rport_mod; /* remote port module */
+ struct bfa_fcpim_mod_s fcpim_mod; /* FCP initiator module */
+ struct bfa_sgpg_mod_s sgpg_mod; /* SG page module */
+ struct bfa_port_s port; /* Physical port module */
+};
+
+/*
+ * !!! Only append to the enums defined here to avoid any versioning
+ * !!! needed between trace utility and driver version
+ */
+enum {
+ BFA_TRC_HAL_CORE = 1,
+ BFA_TRC_HAL_FCXP = 2,
+ BFA_TRC_HAL_FCPIM = 3,
+ BFA_TRC_HAL_IOCFC_CT = 4,
+ BFA_TRC_HAL_IOCFC_CB = 5,
+};
-#include "bfa_iocfc.h"
-#include "bfa_intr_priv.h"
-#include "bfa_trcmod_priv.h"
-#include "bfa_modules_priv.h"
-#include "bfa_fwimg_priv.h"
-#include <cs/bfa_log.h>
-#include <bfa_timer.h>
/**
* Macro to define a new BFA module
*/
-#define BFA_MODULE(__mod) \
+#define BFA_MODULE(__mod) \
static void bfa_ ## __mod ## _meminfo( \
struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len, \
u32 *dm_len); \
static void bfa_ ## __mod ## _attach(struct bfa_s *bfa, \
- void *bfad, struct bfa_iocfc_cfg_s *cfg, \
+ void *bfad, struct bfa_iocfc_cfg_s *cfg, \
struct bfa_meminfo_s *meminfo, \
struct bfa_pcidev_s *pcidev); \
static void bfa_ ## __mod ## _detach(struct bfa_s *bfa); \
@@ -77,17 +103,15 @@ extern struct bfa_module_s *hal_mods[];
struct bfa_s {
void *bfad; /* BFA driver instance */
- struct bfa_aen_s *aen; /* AEN module */
struct bfa_plog_s *plog; /* portlog buffer */
- struct bfa_log_mod_s *logm; /* driver logging modulen */
struct bfa_trc_mod_s *trcmod; /* driver tracing */
struct bfa_ioc_s ioc; /* IOC module */
struct bfa_iocfc_s iocfc; /* IOCFC module */
struct bfa_timer_mod_s timer_mod; /* timer module */
struct bfa_modules_s modules; /* BFA modules */
- struct list_head comp_q; /* pending completions */
- bfa_boolean_t rme_process; /* RME processing enabled */
- struct list_head reqq_waitq[BFI_IOC_MAX_CQS];
+ struct list_head comp_q; /* pending completions */
+ bfa_boolean_t rme_process; /* RME processing enabled */
+ struct list_head reqq_waitq[BFI_IOC_MAX_CQS];
bfa_boolean_t fcs; /* FCS is attached to BFA */
struct bfa_msix_s msix;
};
@@ -95,8 +119,6 @@ struct bfa_s {
extern bfa_isr_func_t bfa_isrs[BFI_MC_MAX];
extern bfa_ioc_mbox_mcfunc_t bfa_mbox_isrs[];
extern bfa_boolean_t bfa_auto_recover;
-extern struct bfa_module_s hal_mod_flash;
-extern struct bfa_module_s hal_mod_fcdiag;
extern struct bfa_module_s hal_mod_sgpg;
extern struct bfa_module_s hal_mod_fcport;
extern struct bfa_module_s hal_mod_fcxp;
@@ -104,7 +126,5 @@ extern struct bfa_module_s hal_mod_lps;
extern struct bfa_module_s hal_mod_uf;
extern struct bfa_module_s hal_mod_rport;
extern struct bfa_module_s hal_mod_fcpim;
-extern struct bfa_module_s hal_mod_pbind;
-
-#endif /* __BFA_PRIV_H__ */
+#endif /* __BFA_MODULES_H__ */
diff --git a/drivers/scsi/bfa/bfa_modules_priv.h b/drivers/scsi/bfa/bfa_modules_priv.h
deleted file mode 100644
index f554c2fad6a9..000000000000
--- a/drivers/scsi/bfa/bfa_modules_priv.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_MODULES_PRIV_H__
-#define __BFA_MODULES_PRIV_H__
-
-#include "bfa_uf_priv.h"
-#include "bfa_port_priv.h"
-#include "bfa_rport_priv.h"
-#include "bfa_fcxp_priv.h"
-#include "bfa_lps_priv.h"
-#include "bfa_fcpim_priv.h"
-#include <cee/bfa_cee.h>
-#include <port/bfa_port.h>
-
-
-struct bfa_modules_s {
- struct bfa_fcport_s fcport; /* fc port module */
- struct bfa_fcxp_mod_s fcxp_mod; /* fcxp module */
- struct bfa_lps_mod_s lps_mod; /* fcxp module */
- struct bfa_uf_mod_s uf_mod; /* unsolicited frame module */
- struct bfa_rport_mod_s rport_mod; /* remote port module */
- struct bfa_fcpim_mod_s fcpim_mod; /* FCP initiator module */
- struct bfa_sgpg_mod_s sgpg_mod; /* SG page module */
- struct bfa_cee_s cee; /* CEE Module */
- struct bfa_port_s port; /* Physical port module */
-};
-
-#endif /* __BFA_MODULES_PRIV_H__ */
diff --git a/drivers/scsi/bfa/bfa_os_inc.h b/drivers/scsi/bfa/bfa_os_inc.h
index bd1cd3ee3022..788a250ffb8a 100644
--- a/drivers/scsi/bfa/bfa_os_inc.h
+++ b/drivers/scsi/bfa/bfa_os_inc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
* All rights reserved
* www.brocade.com
*
@@ -22,30 +22,20 @@
#ifndef __BFA_OS_INC_H__
#define __BFA_OS_INC_H__
-#ifndef __KERNEL__
-#include <stdint.h>
-#else
#include <linux/types.h>
-
#include <linux/version.h>
#include <linux/pci.h>
-
#include <linux/dma-mapping.h>
-#define SET_MODULE_VERSION(VER)
-
#include <linux/idr.h>
-
#include <linux/interrupt.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/delay.h>
#include <linux/vmalloc.h>
-
#include <linux/workqueue.h>
-
+#include <linux/bitops.h>
#include <scsi/scsi.h>
#include <scsi/scsi_host.h>
-
#include <scsi/scsi_tcq.h>
#include <scsi/scsi_transport_fc.h>
#include <scsi/scsi_transport.h>
@@ -54,97 +44,75 @@
#define __BIGENDIAN
#endif
-#define BFA_ERR KERN_ERR
-#define BFA_WARNING KERN_WARNING
-#define BFA_NOTICE KERN_NOTICE
-#define BFA_INFO KERN_INFO
-#define BFA_DEBUG KERN_DEBUG
-
-#define LOG_BFAD_INIT 0x00000001
-#define LOG_FCP_IO 0x00000002
-
-#ifdef DEBUG
-#define BFA_LOG_TRACE(bfad, level, mask, fmt, arg...) \
- BFA_LOG(bfad, level, mask, fmt, ## arg)
-#define BFA_DEV_TRACE(bfad, level, fmt, arg...) \
- BFA_DEV_PRINTF(bfad, level, fmt, ## arg)
-#define BFA_TRACE(level, fmt, arg...) \
- BFA_PRINTF(level, fmt, ## arg)
-#else
-#define BFA_LOG_TRACE(bfad, level, mask, fmt, arg...)
-#define BFA_DEV_TRACE(bfad, level, fmt, arg...)
-#define BFA_TRACE(level, fmt, arg...)
-#endif
+static inline u64 bfa_os_get_clock(void)
+{
+ return jiffies;
+}
+
+static inline u64 bfa_os_get_log_time(void)
+{
+ u64 system_time = 0;
+ struct timeval tv;
+ do_gettimeofday(&tv);
+
+ /* We are interested in seconds only. */
+ system_time = tv.tv_sec;
+ return system_time;
+}
+
+#define bfa_io_lat_clock_res_div HZ
+#define bfa_io_lat_clock_res_mul 1000
#define BFA_ASSERT(p) do { \
if (!(p)) { \
printk(KERN_ERR "assert(%s) failed at %s:%d\n", \
#p, __FILE__, __LINE__); \
- BUG(); \
} \
} while (0)
-
-#define BFA_LOG(bfad, level, mask, fmt, arg...) \
-do { \
- if (((mask) & (((struct bfad_s *)(bfad))-> \
- cfg_data[cfg_log_mask])) || (level[1] <= '3')) \
- dev_printk(level, &(((struct bfad_s *) \
- (bfad))->pcidev->dev), fmt, ##arg); \
+#define BFA_LOG(level, bfad, mask, fmt, arg...) \
+do { \
+ if (((mask) == 4) || (level[1] <= '4')) \
+ dev_printk(level, &((bfad)->pcidev)->dev, fmt, ##arg); \
} while (0)
-#ifndef BFA_DEV_PRINTF
-#define BFA_DEV_PRINTF(bfad, level, fmt, arg...) \
- dev_printk(level, &(((struct bfad_s *) \
- (bfad))->pcidev->dev), fmt, ##arg);
-#endif
-
-#define BFA_PRINTF(level, fmt, arg...) \
- printk(level fmt, ##arg);
-
-int bfa_os_MWB(void *);
-
-#define bfa_os_mmiowb() mmiowb()
-
#define bfa_swap_3b(_x) \
((((_x) & 0xff) << 16) | \
((_x) & 0x00ff00) | \
(((_x) & 0xff0000) >> 16))
-#define bfa_swap_8b(_x) \
- ((((_x) & 0xff00000000000000ull) >> 56) \
- | (((_x) & 0x00ff000000000000ull) >> 40) \
- | (((_x) & 0x0000ff0000000000ull) >> 24) \
- | (((_x) & 0x000000ff00000000ull) >> 8) \
- | (((_x) & 0x00000000ff000000ull) << 8) \
- | (((_x) & 0x0000000000ff0000ull) << 24) \
- | (((_x) & 0x000000000000ff00ull) << 40) \
- | (((_x) & 0x00000000000000ffull) << 56))
-
-#define bfa_os_swap32(_x) \
- ((((_x) & 0xff) << 24) | \
+#define bfa_swap_8b(_x) \
+ ((((_x) & 0xff00000000000000ull) >> 56) \
+ | (((_x) & 0x00ff000000000000ull) >> 40) \
+ | (((_x) & 0x0000ff0000000000ull) >> 24) \
+ | (((_x) & 0x000000ff00000000ull) >> 8) \
+ | (((_x) & 0x00000000ff000000ull) << 8) \
+ | (((_x) & 0x0000000000ff0000ull) << 24) \
+ | (((_x) & 0x000000000000ff00ull) << 40) \
+ | (((_x) & 0x00000000000000ffull) << 56))
+
+#define bfa_os_swap32(_x) \
+ ((((_x) & 0xff) << 24) | \
(((_x) & 0x0000ff00) << 8) | \
(((_x) & 0x00ff0000) >> 8) | \
(((_x) & 0xff000000) >> 24))
-#define bfa_os_swap_sgaddr(_x) ((u64)( \
- (((u64)(_x) & (u64)0x00000000000000ffull) << 32) | \
- (((u64)(_x) & (u64)0x000000000000ff00ull) << 32) | \
- (((u64)(_x) & (u64)0x0000000000ff0000ull) << 32) | \
- (((u64)(_x) & (u64)0x00000000ff000000ull) << 32) | \
- (((u64)(_x) & (u64)0x000000ff00000000ull) >> 32) | \
- (((u64)(_x) & (u64)0x0000ff0000000000ull) >> 32) | \
- (((u64)(_x) & (u64)0x00ff000000000000ull) >> 32) | \
+#define bfa_os_swap_sgaddr(_x) ((u64)( \
+ (((u64)(_x) & (u64)0x00000000000000ffull) << 32) | \
+ (((u64)(_x) & (u64)0x000000000000ff00ull) << 32) | \
+ (((u64)(_x) & (u64)0x0000000000ff0000ull) << 32) | \
+ (((u64)(_x) & (u64)0x00000000ff000000ull) << 32) | \
+ (((u64)(_x) & (u64)0x000000ff00000000ull) >> 32) | \
+ (((u64)(_x) & (u64)0x0000ff0000000000ull) >> 32) | \
+ (((u64)(_x) & (u64)0x00ff000000000000ull) >> 32) | \
(((u64)(_x) & (u64)0xff00000000000000ull) >> 32)))
#ifndef __BIGENDIAN
#define bfa_os_htons(_x) ((u16)((((_x) & 0xff00) >> 8) | \
(((_x) & 0x00ff) << 8)))
-
#define bfa_os_htonl(_x) bfa_os_swap32(_x)
#define bfa_os_htonll(_x) bfa_swap_8b(_x)
#define bfa_os_hton3b(_x) bfa_swap_3b(_x)
-
#define bfa_os_wtole(_x) (_x)
#define bfa_os_sgaddr(_x) (_x)
@@ -170,17 +138,16 @@ int bfa_os_MWB(void *);
#define bfa_os_memcpy memcpy
#define bfa_os_udelay udelay
#define bfa_os_vsprintf vsprintf
+#define bfa_os_snprintf snprintf
#define bfa_os_assign(__t, __s) __t = __s
-
-#define bfa_os_addr_t char __iomem *
-#define bfa_os_panic()
+#define bfa_os_addr_t void __iomem *
#define bfa_os_reg_read(_raddr) readl(_raddr)
#define bfa_os_reg_write(_raddr, _val) writel((_val), (_raddr))
-#define bfa_os_mem_read(_raddr, _off) \
+#define bfa_os_mem_read(_raddr, _off) \
bfa_os_swap32(readl(((_raddr) + (_off))))
-#define bfa_os_mem_write(_raddr, _off, _val) \
+#define bfa_os_mem_write(_raddr, _off, _val) \
writel(bfa_os_swap32((_val)), ((_raddr) + (_off)))
#define BFA_TRC_TS(_trcm) \
@@ -191,11 +158,6 @@ int bfa_os_MWB(void *);
(tv.tv_sec*1000000+tv.tv_usec); \
})
-struct bfa_log_mod_s;
-void bfa_os_printf(struct bfa_log_mod_s *log_mod, u32 msg_id,
- const char *fmt, ...);
-#endif
-
#define boolean_t int
/**
@@ -206,7 +168,15 @@ struct bfa_timeval_s {
u32 tv_usec; /* microseconds */
};
-void bfa_os_gettimeofday(struct bfa_timeval_s *tv);
+static inline void
+bfa_os_gettimeofday(struct bfa_timeval_s *tv)
+{
+ struct timeval tmp_tv;
+
+ do_gettimeofday(&tmp_tv);
+ tv->tv_sec = (u32) tmp_tv.tv_sec;
+ tv->tv_usec = (u32) tmp_tv.tv_usec;
+}
static inline void
wwn2str(char *wwn_str, u64 wwn)
diff --git a/drivers/scsi/bfa/include/cs/bfa_plog.h b/drivers/scsi/bfa/bfa_plog.h
index f5bef63b5877..501f0ed35cf0 100644
--- a/drivers/scsi/bfa/include/cs/bfa_plog.h
+++ b/drivers/scsi/bfa/bfa_plog.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
* All rights reserved
* www.brocade.com
*
@@ -17,8 +17,8 @@
#ifndef __BFA_PORTLOG_H__
#define __BFA_PORTLOG_H__
-#include "protocol/fc.h"
-#include <defs/bfa_defs_types.h>
+#include "bfa_fc.h"
+#include "bfa_defs.h"
#define BFA_PL_NLOG_ENTS 256
#define BFA_PL_LOG_REC_INCR(_x) ((_x)++, (_x) %= BFA_PL_NLOG_ENTS)
@@ -27,38 +27,30 @@
#define BFA_PL_INT_LOG_SZ 8 /* number of integers in the integer log */
enum bfa_plog_log_type {
- BFA_PL_LOG_TYPE_INVALID = 0,
- BFA_PL_LOG_TYPE_INT = 1,
- BFA_PL_LOG_TYPE_STRING = 2,
+ BFA_PL_LOG_TYPE_INVALID = 0,
+ BFA_PL_LOG_TYPE_INT = 1,
+ BFA_PL_LOG_TYPE_STRING = 2,
};
/*
* the (fixed size) record format for each entry in the portlog
*/
struct bfa_plog_rec_s {
- u32 tv; /* Filled by the portlog driver when the *
- * entry is added to the circular log. */
- u8 port; /* Source port that logged this entry. CM
- * entities will use 0xFF */
- u8 mid; /* Integer value to be used by all entities *
- * while logging. The module id to string *
- * conversion will be done by BFAL. See
- * enum bfa_plog_mid */
- u8 eid; /* indicates Rx, Tx, IOCTL, etc. See
- * enum bfa_plog_eid */
- u8 log_type; /* indicates string log or integer log.
- * see bfa_plog_log_type_t */
- u8 log_num_ints;
+ u64 tv; /* timestamp */
+ u8 port; /* Source port that logged this entry */
+ u8 mid; /* module id */
+ u8 eid; /* indicates Rx, Tx, IOCTL, etc. bfa_plog_eid */
+ u8 log_type; /* string/integer log, bfa_plog_log_type_t */
+ u8 log_num_ints;
/*
* interpreted only if log_type is INT_LOG. indicates number of
* integers in the int_log[] (0-PL_INT_LOG_SZ).
*/
- u8 rsvd;
- u16 misc; /* can be used to indicate fc frame length,
- *etc.. */
+ u8 rsvd;
+ u16 misc; /* can be used to indicate fc frame length */
union {
- char string_log[BFA_PL_STRING_LOG_SZ];
- u32 int_log[BFA_PL_INT_LOG_SZ];
+ char string_log[BFA_PL_STRING_LOG_SZ];
+ u32 int_log[BFA_PL_INT_LOG_SZ];
} log_entry;
};
@@ -73,20 +65,20 @@ struct bfa_plog_rec_s {
* - Do not remove any entry or rearrange the order.
*/
enum bfa_plog_mid {
- BFA_PL_MID_INVALID = 0,
- BFA_PL_MID_DEBUG = 1,
- BFA_PL_MID_DRVR = 2,
- BFA_PL_MID_HAL = 3,
- BFA_PL_MID_HAL_FCXP = 4,
- BFA_PL_MID_HAL_UF = 5,
- BFA_PL_MID_FCS = 6,
+ BFA_PL_MID_INVALID = 0,
+ BFA_PL_MID_DEBUG = 1,
+ BFA_PL_MID_DRVR = 2,
+ BFA_PL_MID_HAL = 3,
+ BFA_PL_MID_HAL_FCXP = 4,
+ BFA_PL_MID_HAL_UF = 5,
+ BFA_PL_MID_FCS = 6,
BFA_PL_MID_LPS = 7,
- BFA_PL_MID_MAX = 8
+ BFA_PL_MID_MAX = 8
};
#define BFA_PL_MID_STRLEN 8
struct bfa_plog_mid_strings_s {
- char m_str[BFA_PL_MID_STRLEN];
+ char m_str[BFA_PL_MID_STRLEN];
};
/*
@@ -99,36 +91,37 @@ struct bfa_plog_mid_strings_s {
* - Do not remove any entry or rearrange the order.
*/
enum bfa_plog_eid {
- BFA_PL_EID_INVALID = 0,
- BFA_PL_EID_IOC_DISABLE = 1,
- BFA_PL_EID_IOC_ENABLE = 2,
- BFA_PL_EID_PORT_DISABLE = 3,
- BFA_PL_EID_PORT_ENABLE = 4,
- BFA_PL_EID_PORT_ST_CHANGE = 5,
- BFA_PL_EID_TX = 6,
- BFA_PL_EID_TX_ACK1 = 7,
- BFA_PL_EID_TX_RJT = 8,
- BFA_PL_EID_TX_BSY = 9,
- BFA_PL_EID_RX = 10,
- BFA_PL_EID_RX_ACK1 = 11,
- BFA_PL_EID_RX_RJT = 12,
- BFA_PL_EID_RX_BSY = 13,
- BFA_PL_EID_CT_IN = 14,
- BFA_PL_EID_CT_OUT = 15,
- BFA_PL_EID_DRIVER_START = 16,
- BFA_PL_EID_RSCN = 17,
- BFA_PL_EID_DEBUG = 18,
- BFA_PL_EID_MISC = 19,
+ BFA_PL_EID_INVALID = 0,
+ BFA_PL_EID_IOC_DISABLE = 1,
+ BFA_PL_EID_IOC_ENABLE = 2,
+ BFA_PL_EID_PORT_DISABLE = 3,
+ BFA_PL_EID_PORT_ENABLE = 4,
+ BFA_PL_EID_PORT_ST_CHANGE = 5,
+ BFA_PL_EID_TX = 6,
+ BFA_PL_EID_TX_ACK1 = 7,
+ BFA_PL_EID_TX_RJT = 8,
+ BFA_PL_EID_TX_BSY = 9,
+ BFA_PL_EID_RX = 10,
+ BFA_PL_EID_RX_ACK1 = 11,
+ BFA_PL_EID_RX_RJT = 12,
+ BFA_PL_EID_RX_BSY = 13,
+ BFA_PL_EID_CT_IN = 14,
+ BFA_PL_EID_CT_OUT = 15,
+ BFA_PL_EID_DRIVER_START = 16,
+ BFA_PL_EID_RSCN = 17,
+ BFA_PL_EID_DEBUG = 18,
+ BFA_PL_EID_MISC = 19,
BFA_PL_EID_FIP_FCF_DISC = 20,
BFA_PL_EID_FIP_FCF_CVL = 21,
BFA_PL_EID_LOGIN = 22,
BFA_PL_EID_LOGO = 23,
- BFA_PL_EID_MAX = 24
+ BFA_PL_EID_TRUNK_SCN = 24,
+ BFA_PL_EID_MAX
};
-#define BFA_PL_ENAME_STRLEN 8
+#define BFA_PL_ENAME_STRLEN 8
struct bfa_plog_eid_strings_s {
- char e_str[BFA_PL_ENAME_STRLEN];
+ char e_str[BFA_PL_ENAME_STRLEN];
};
#define BFA_PL_SIG_LEN 8
@@ -138,12 +131,12 @@ struct bfa_plog_eid_strings_s {
* per port circular log buffer
*/
struct bfa_plog_s {
- char plog_sig[BFA_PL_SIG_LEN]; /* Start signature */
- u8 plog_enabled;
- u8 rsvd[7];
- u32 ticks;
- u16 head;
- u16 tail;
+ char plog_sig[BFA_PL_SIG_LEN]; /* Start signature */
+ u8 plog_enabled;
+ u8 rsvd[7];
+ u32 ticks;
+ u16 head;
+ u16 tail;
struct bfa_plog_rec_s plog_recs[BFA_PL_NLOG_ENTS];
};
@@ -154,8 +147,7 @@ void bfa_plog_intarr(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
enum bfa_plog_eid event, u16 misc,
u32 *intarr, u32 num_ints);
void bfa_plog_fchdr(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
- enum bfa_plog_eid event, u16 misc,
- struct fchs_s *fchdr);
+ enum bfa_plog_eid event, u16 misc, struct fchs_s *fchdr);
void bfa_plog_fchdr_and_pl(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
enum bfa_plog_eid event, u16 misc,
struct fchs_s *fchdr, u32 pld_w0);
diff --git a/drivers/scsi/bfa/bfa_port.c b/drivers/scsi/bfa/bfa_port.c
index c7e69f1e56e3..b6d170a13bea 100644
--- a/drivers/scsi/bfa/bfa_port.c
+++ b/drivers/scsi/bfa/bfa_port.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
* All rights reserved
* www.brocade.com
*
@@ -15,30 +15,25 @@
* General Public License for more details.
*/
-#include <defs/bfa_defs_port.h>
-#include <cs/bfa_trc.h>
-#include <cs/bfa_log.h>
-#include <cs/bfa_debug.h>
-#include <port/bfa_port.h>
-#include <bfi/bfi.h>
-#include <bfi/bfi_port.h>
-#include <bfa_ioc.h>
-#include <cna/bfa_cna_trcmod.h>
+#include "bfa_defs_svc.h"
+#include "bfa_port.h"
+#include "bfi.h"
+#include "bfa_ioc.h"
+
BFA_TRC_FILE(CNA, PORT);
#define bfa_ioc_portid(__ioc) ((__ioc)->port_id)
-#define bfa_lpuid(__arg) bfa_ioc_portid(&(__arg)->ioc)
static void
-bfa_port_stats_swap(struct bfa_port_s *port, union bfa_pport_stats_u *stats)
+bfa_port_stats_swap(struct bfa_port_s *port, union bfa_port_stats_u *stats)
{
- u32 *dip = (u32 *) stats;
- u32 t0, t1;
- int i;
+ u32 *dip = (u32 *) stats;
+ u32 t0, t1;
+ int i;
- for (i = 0; i < sizeof(union bfa_pport_stats_u) / sizeof(u32);
- i += 2) {
+ for (i = 0; i < sizeof(union bfa_port_stats_u)/sizeof(u32);
+ i += 2) {
t0 = dip[i];
t1 = dip[i + 1];
#ifdef __BIGENDIAN
@@ -49,11 +44,6 @@ bfa_port_stats_swap(struct bfa_port_s *port, union bfa_pport_stats_u *stats)
dip[i + 1] = bfa_os_ntohl(t0);
#endif
}
-
- /** todo
- * QoS stats r also swapped as 64bit; that structure also
- * has to use 64 bit counters
- */
}
/**
@@ -68,7 +58,9 @@ bfa_port_stats_swap(struct bfa_port_s *port, union bfa_pport_stats_u *stats)
static void
bfa_port_enable_isr(struct bfa_port_s *port, bfa_status_t status)
{
- bfa_assert(0);
+ bfa_trc(port, status);
+ port->endis_pending = BFA_FALSE;
+ port->endis_cbfn(port->endis_cbarg, status);
}
/**
@@ -83,7 +75,9 @@ bfa_port_enable_isr(struct bfa_port_s *port, bfa_status_t status)
static void
bfa_port_disable_isr(struct bfa_port_s *port, bfa_status_t status)
{
- bfa_assert(0);
+ bfa_trc(port, status);
+ port->endis_pending = BFA_FALSE;
+ port->endis_cbfn(port->endis_cbarg, status);
}
/**
@@ -105,7 +99,7 @@ bfa_port_get_stats_isr(struct bfa_port_s *port, bfa_status_t status)
struct bfa_timeval_s tv;
memcpy(port->stats, port->stats_dma.kva,
- sizeof(union bfa_pport_stats_u));
+ sizeof(union bfa_port_stats_u));
bfa_port_stats_swap(port, port->stats);
bfa_os_gettimeofday(&tv);
@@ -133,11 +127,11 @@ bfa_port_clear_stats_isr(struct bfa_port_s *port, bfa_status_t status)
struct bfa_timeval_s tv;
port->stats_status = status;
- port->stats_busy = BFA_FALSE;
+ port->stats_busy = BFA_FALSE;
/**
- * re-initialize time stamp for stats reset
- */
+ * re-initialize time stamp for stats reset
+ */
bfa_os_gettimeofday(&tv);
port->stats_reset_time = tv.tv_sec;
@@ -158,10 +152,10 @@ bfa_port_clear_stats_isr(struct bfa_port_s *port, bfa_status_t status)
static void
bfa_port_isr(void *cbarg, struct bfi_mbmsg_s *m)
{
- struct bfa_port_s *port = (struct bfa_port_s *)cbarg;
+ struct bfa_port_s *port = (struct bfa_port_s *) cbarg;
union bfi_port_i2h_msg_u *i2hmsg;
- i2hmsg = (union bfi_port_i2h_msg_u *)m;
+ i2hmsg = (union bfi_port_i2h_msg_u *) m;
bfa_trc(port, m->mh.msg_id);
switch (m->mh.msg_id) {
@@ -178,9 +172,7 @@ bfa_port_isr(void *cbarg, struct bfi_mbmsg_s *m)
break;
case BFI_PORT_I2H_GET_STATS_RSP:
- /*
- * Stats busy flag is still set? (may be cmd timed out)
- */
+ /* Stats busy flag is still set? (may be cmd timed out) */
if (port->stats_busy == BFA_FALSE)
break;
bfa_port_get_stats_isr(port, i2hmsg->getstats_rsp.status);
@@ -208,7 +200,7 @@ bfa_port_isr(void *cbarg, struct bfi_mbmsg_s *m)
u32
bfa_port_meminfo(void)
{
- return BFA_ROUNDUP(sizeof(union bfa_pport_stats_u), BFA_DMA_ALIGN_SZ);
+ return BFA_ROUNDUP(sizeof(union bfa_port_stats_u), BFA_DMA_ALIGN_SZ);
}
/**
@@ -216,8 +208,8 @@ bfa_port_meminfo(void)
*
*
* @param[in] port Port module pointer
- * dma_kva Kernel Virtual Address of Port DMA Memory
- * dma_pa Physical Address of Port DMA Memory
+ * dma_kva Kernel Virtual Address of Port DMA Memory
+ * dma_pa Physical Address of Port DMA Memory
*
* @return void
*/
@@ -225,7 +217,7 @@ void
bfa_port_mem_claim(struct bfa_port_s *port, u8 *dma_kva, u64 dma_pa)
{
port->stats_dma.kva = dma_kva;
- port->stats_dma.pa = dma_pa;
+ port->stats_dma.pa = dma_pa;
}
/**
@@ -239,12 +231,14 @@ bfa_port_mem_claim(struct bfa_port_s *port, u8 *dma_kva, u64 dma_pa)
*/
bfa_status_t
bfa_port_enable(struct bfa_port_s *port, bfa_port_endis_cbfn_t cbfn,
- void *cbarg)
+ void *cbarg)
{
struct bfi_port_generic_req_s *m;
- /** todo Not implemented */
- bfa_assert(0);
+ if (bfa_ioc_is_disabled(port->ioc)) {
+ bfa_trc(port, BFA_STATUS_IOC_DISABLED);
+ return BFA_STATUS_IOC_DISABLED;
+ }
if (!bfa_ioc_is_operational(port->ioc)) {
bfa_trc(port, BFA_STATUS_IOC_FAILURE);
@@ -256,11 +250,11 @@ bfa_port_enable(struct bfa_port_s *port, bfa_port_endis_cbfn_t cbfn,
return BFA_STATUS_DEVBUSY;
}
- m = (struct bfi_port_generic_req_s *)port->endis_mb.msg;
+ m = (struct bfi_port_generic_req_s *) port->endis_mb.msg;
port->msgtag++;
- port->endis_cbfn = cbfn;
- port->endis_cbarg = cbarg;
+ port->endis_cbfn = cbfn;
+ port->endis_cbarg = cbarg;
port->endis_pending = BFA_TRUE;
bfi_h2i_set(m->mh, BFI_MC_PORT, BFI_PORT_H2I_ENABLE_REQ,
@@ -281,12 +275,14 @@ bfa_port_enable(struct bfa_port_s *port, bfa_port_endis_cbfn_t cbfn,
*/
bfa_status_t
bfa_port_disable(struct bfa_port_s *port, bfa_port_endis_cbfn_t cbfn,
- void *cbarg)
+ void *cbarg)
{
struct bfi_port_generic_req_s *m;
- /** todo Not implemented */
- bfa_assert(0);
+ if (bfa_ioc_is_disabled(port->ioc)) {
+ bfa_trc(port, BFA_STATUS_IOC_DISABLED);
+ return BFA_STATUS_IOC_DISABLED;
+ }
if (!bfa_ioc_is_operational(port->ioc)) {
bfa_trc(port, BFA_STATUS_IOC_FAILURE);
@@ -298,11 +294,11 @@ bfa_port_disable(struct bfa_port_s *port, bfa_port_endis_cbfn_t cbfn,
return BFA_STATUS_DEVBUSY;
}
- m = (struct bfi_port_generic_req_s *)port->endis_mb.msg;
+ m = (struct bfi_port_generic_req_s *) port->endis_mb.msg;
port->msgtag++;
- port->endis_cbfn = cbfn;
- port->endis_cbarg = cbarg;
+ port->endis_cbfn = cbfn;
+ port->endis_cbarg = cbarg;
port->endis_pending = BFA_TRUE;
bfi_h2i_set(m->mh, BFI_MC_PORT, BFI_PORT_H2I_DISABLE_REQ,
@@ -322,8 +318,8 @@ bfa_port_disable(struct bfa_port_s *port, bfa_port_endis_cbfn_t cbfn,
* @return Status
*/
bfa_status_t
-bfa_port_get_stats(struct bfa_port_s *port, union bfa_pport_stats_u *stats,
- bfa_port_stats_cbfn_t cbfn, void *cbarg)
+bfa_port_get_stats(struct bfa_port_s *port, union bfa_port_stats_u *stats,
+ bfa_port_stats_cbfn_t cbfn, void *cbarg)
{
struct bfi_port_get_stats_req_s *m;
@@ -337,12 +333,12 @@ bfa_port_get_stats(struct bfa_port_s *port, union bfa_pport_stats_u *stats,
return BFA_STATUS_DEVBUSY;
}
- m = (struct bfi_port_get_stats_req_s *)port->stats_mb.msg;
+ m = (struct bfi_port_get_stats_req_s *) port->stats_mb.msg;
- port->stats = stats;
- port->stats_cbfn = cbfn;
+ port->stats = stats;
+ port->stats_cbfn = cbfn;
port->stats_cbarg = cbarg;
- port->stats_busy = BFA_TRUE;
+ port->stats_busy = BFA_TRUE;
bfa_dma_be_addr_set(m->dma_addr, port->stats_dma.pa);
bfi_h2i_set(m->mh, BFI_MC_PORT, BFI_PORT_H2I_GET_STATS_REQ,
@@ -362,7 +358,7 @@ bfa_port_get_stats(struct bfa_port_s *port, union bfa_pport_stats_u *stats,
*/
bfa_status_t
bfa_port_clear_stats(struct bfa_port_s *port, bfa_port_stats_cbfn_t cbfn,
- void *cbarg)
+ void *cbarg)
{
struct bfi_port_generic_req_s *m;
@@ -376,11 +372,11 @@ bfa_port_clear_stats(struct bfa_port_s *port, bfa_port_stats_cbfn_t cbfn,
return BFA_STATUS_DEVBUSY;
}
- m = (struct bfi_port_generic_req_s *)port->stats_mb.msg;
+ m = (struct bfi_port_generic_req_s *) port->stats_mb.msg;
- port->stats_cbfn = cbfn;
+ port->stats_cbfn = cbfn;
port->stats_cbarg = cbarg;
- port->stats_busy = BFA_TRUE;
+ port->stats_busy = BFA_TRUE;
bfi_h2i_set(m->mh, BFI_MC_PORT, BFI_PORT_H2I_CLEAR_STATS_REQ,
bfa_ioc_portid(port->ioc));
@@ -400,11 +396,9 @@ bfa_port_clear_stats(struct bfa_port_s *port, bfa_port_stats_cbfn_t cbfn,
void
bfa_port_hbfail(void *arg)
{
- struct bfa_port_s *port = (struct bfa_port_s *)arg;
+ struct bfa_port_s *port = (struct bfa_port_s *) arg;
- /*
- * Fail any pending get_stats/clear_stats requests
- */
+ /* Fail any pending get_stats/clear_stats requests */
if (port->stats_busy) {
if (port->stats_cbfn)
port->stats_cbfn(port->stats_cbarg, BFA_STATUS_FAILED);
@@ -412,9 +406,7 @@ bfa_port_hbfail(void *arg)
port->stats_busy = BFA_FALSE;
}
- /*
- * Clear any enable/disable is pending
- */
+ /* Clear any enable/disable is pending */
if (port->endis_pending) {
if (port->endis_cbfn)
port->endis_cbfn(port->endis_cbarg, BFA_STATUS_FAILED);
@@ -433,22 +425,20 @@ bfa_port_hbfail(void *arg)
* The device driver specific mbox ISR functions have
* this pointer as one of the parameters.
* trcmod -
- * logmod -
*
* @return void
*/
void
-bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc, void *dev,
- struct bfa_trc_mod_s *trcmod, struct bfa_log_mod_s *logmod)
+bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc,
+ void *dev, struct bfa_trc_mod_s *trcmod)
{
struct bfa_timeval_s tv;
bfa_assert(port);
- port->dev = dev;
- port->ioc = ioc;
+ port->dev = dev;
+ port->ioc = ioc;
port->trcmod = trcmod;
- port->logmod = logmod;
port->stats_busy = BFA_FALSE;
port->endis_pending = BFA_FALSE;
diff --git a/drivers/scsi/bfa/bfa_port.h b/drivers/scsi/bfa/bfa_port.h
new file mode 100644
index 000000000000..dbce9dfd056b
--- /dev/null
+++ b/drivers/scsi/bfa/bfa_port.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_PORT_H__
+#define __BFA_PORT_H__
+
+#include "bfa_defs_svc.h"
+#include "bfa_ioc.h"
+#include "bfa_cs.h"
+
+typedef void (*bfa_port_stats_cbfn_t) (void *dev, bfa_status_t status);
+typedef void (*bfa_port_endis_cbfn_t) (void *dev, bfa_status_t status);
+
+struct bfa_port_s {
+ void *dev;
+ struct bfa_ioc_s *ioc;
+ struct bfa_trc_mod_s *trcmod;
+ u32 msgtag;
+ bfa_boolean_t stats_busy;
+ struct bfa_mbox_cmd_s stats_mb;
+ bfa_port_stats_cbfn_t stats_cbfn;
+ void *stats_cbarg;
+ bfa_status_t stats_status;
+ u32 stats_reset_time;
+ union bfa_port_stats_u *stats;
+ struct bfa_dma_s stats_dma;
+ bfa_boolean_t endis_pending;
+ struct bfa_mbox_cmd_s endis_mb;
+ bfa_port_endis_cbfn_t endis_cbfn;
+ void *endis_cbarg;
+ bfa_status_t endis_status;
+ struct bfa_ioc_hbfail_notify_s hbfail;
+};
+
+void bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc,
+ void *dev, struct bfa_trc_mod_s *trcmod);
+void bfa_port_detach(struct bfa_port_s *port);
+void bfa_port_hbfail(void *arg);
+
+bfa_status_t bfa_port_get_stats(struct bfa_port_s *port,
+ union bfa_port_stats_u *stats,
+ bfa_port_stats_cbfn_t cbfn, void *cbarg);
+bfa_status_t bfa_port_clear_stats(struct bfa_port_s *port,
+ bfa_port_stats_cbfn_t cbfn, void *cbarg);
+bfa_status_t bfa_port_enable(struct bfa_port_s *port,
+ bfa_port_endis_cbfn_t cbfn, void *cbarg);
+bfa_status_t bfa_port_disable(struct bfa_port_s *port,
+ bfa_port_endis_cbfn_t cbfn, void *cbarg);
+u32 bfa_port_meminfo(void);
+void bfa_port_mem_claim(struct bfa_port_s *port,
+ u8 *dma_kva, u64 dma_pa);
+#endif /* __BFA_PORT_H__ */
diff --git a/drivers/scsi/bfa/bfa_port_priv.h b/drivers/scsi/bfa/bfa_port_priv.h
deleted file mode 100644
index c9ebe0426fa6..000000000000
--- a/drivers/scsi/bfa/bfa_port_priv.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_PORT_PRIV_H__
-#define __BFA_PORT_PRIV_H__
-
-#include <defs/bfa_defs_pport.h>
-#include <bfi/bfi_pport.h>
-#include "bfa_intr_priv.h"
-
-/**
- * Link notification data structure
- */
-struct bfa_fcport_ln_s {
- struct bfa_fcport_s *fcport;
- bfa_sm_t sm;
- struct bfa_cb_qe_s ln_qe; /* BFA callback queue elem for ln */
- enum bfa_pport_linkstate ln_event; /* ln event for callback */
-};
-
-/**
- * BFA FC port data structure
- */
-struct bfa_fcport_s {
- struct bfa_s *bfa; /* parent BFA instance */
- bfa_sm_t sm; /* port state machine */
- wwn_t nwwn; /* node wwn of physical port */
- wwn_t pwwn; /* port wwn of physical oprt */
- enum bfa_pport_speed speed_sup;
- /* supported speeds */
- enum bfa_pport_speed speed; /* current speed */
- enum bfa_pport_topology topology; /* current topology */
- u8 myalpa; /* my ALPA in LOOP topology */
- u8 rsvd[3];
- u32 mypid:24;
- u32 rsvd_b:8;
- struct bfa_pport_cfg_s cfg; /* current port configuration */
- struct bfa_qos_attr_s qos_attr; /* QoS Attributes */
- struct bfa_qos_vc_attr_s qos_vc_attr; /* VC info from ELP */
- struct bfa_reqq_wait_s reqq_wait;
- /* to wait for room in reqq */
- struct bfa_reqq_wait_s svcreq_wait;
- /* to wait for room in reqq */
- struct bfa_reqq_wait_s stats_reqq_wait;
- /* to wait for room in reqq (stats) */
- void *event_cbarg;
- void (*event_cbfn) (void *cbarg,
- bfa_pport_event_t event);
- union {
- union bfi_fcport_i2h_msg_u i2hmsg;
- } event_arg;
- void *bfad; /* BFA driver handle */
- struct bfa_fcport_ln_s ln; /* Link Notification */
- struct bfa_cb_qe_s hcb_qe; /* BFA callback queue elem */
- struct bfa_timer_s timer; /* timer */
- u32 msgtag; /* fimrware msg tag for reply */
- u8 *stats_kva;
- u64 stats_pa;
- union bfa_fcport_stats_u *stats;
- union bfa_fcport_stats_u *stats_ret; /* driver stats location */
- bfa_status_t stats_status; /* stats/statsclr status */
- bfa_boolean_t stats_busy; /* outstanding stats/statsclr */
- bfa_boolean_t stats_qfull;
- u32 stats_reset_time; /* stats reset time stamp */
- bfa_cb_pport_t stats_cbfn; /* driver callback function */
- void *stats_cbarg; /* user callback arg */
- bfa_boolean_t diag_busy; /* diag busy status */
- bfa_boolean_t beacon; /* port beacon status */
- bfa_boolean_t link_e2e_beacon; /* link beacon status */
-};
-
-#define BFA_FCPORT_MOD(__bfa) (&(__bfa)->modules.fcport)
-
-/*
- * public functions
- */
-void bfa_fcport_init(struct bfa_s *bfa);
-void bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
-
-#endif /* __BFA_PORT_PRIV_H__ */
diff --git a/drivers/scsi/bfa/bfa_rport.c b/drivers/scsi/bfa/bfa_rport.c
deleted file mode 100644
index ccd0680f6f16..000000000000
--- a/drivers/scsi/bfa/bfa_rport.c
+++ /dev/null
@@ -1,906 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#include <bfa.h>
-#include <bfa_svc.h>
-#include <cs/bfa_debug.h>
-#include <bfi/bfi_rport.h>
-#include "bfa_intr_priv.h"
-
-BFA_TRC_FILE(HAL, RPORT);
-BFA_MODULE(rport);
-
-#define bfa_rport_offline_cb(__rp) do { \
- if ((__rp)->bfa->fcs) \
- bfa_cb_rport_offline((__rp)->rport_drv); \
- else { \
- bfa_cb_queue((__rp)->bfa, &(__rp)->hcb_qe, \
- __bfa_cb_rport_offline, (__rp)); \
- } \
-} while (0)
-
-#define bfa_rport_online_cb(__rp) do { \
- if ((__rp)->bfa->fcs) \
- bfa_cb_rport_online((__rp)->rport_drv); \
- else { \
- bfa_cb_queue((__rp)->bfa, &(__rp)->hcb_qe, \
- __bfa_cb_rport_online, (__rp)); \
- } \
-} while (0)
-
-/*
- * forward declarations
- */
-static struct bfa_rport_s *bfa_rport_alloc(struct bfa_rport_mod_s *rp_mod);
-static void bfa_rport_free(struct bfa_rport_s *rport);
-static bfa_boolean_t bfa_rport_send_fwcreate(struct bfa_rport_s *rp);
-static bfa_boolean_t bfa_rport_send_fwdelete(struct bfa_rport_s *rp);
-static bfa_boolean_t bfa_rport_send_fwspeed(struct bfa_rport_s *rp);
-static void __bfa_cb_rport_online(void *cbarg, bfa_boolean_t complete);
-static void __bfa_cb_rport_offline(void *cbarg, bfa_boolean_t complete);
-
-/**
- * bfa_rport_sm BFA rport state machine
- */
-
-
-enum bfa_rport_event {
- BFA_RPORT_SM_CREATE = 1, /* rport create event */
- BFA_RPORT_SM_DELETE = 2, /* deleting an existing rport */
- BFA_RPORT_SM_ONLINE = 3, /* rport is online */
- BFA_RPORT_SM_OFFLINE = 4, /* rport is offline */
- BFA_RPORT_SM_FWRSP = 5, /* firmware response */
- BFA_RPORT_SM_HWFAIL = 6, /* IOC h/w failure */
- BFA_RPORT_SM_QOS_SCN = 7, /* QoS SCN from firmware */
- BFA_RPORT_SM_SET_SPEED = 8, /* Set Rport Speed */
- BFA_RPORT_SM_QRESUME = 9, /* space in requeue queue */
-};
-
-static void bfa_rport_sm_uninit(struct bfa_rport_s *rp,
- enum bfa_rport_event event);
-static void bfa_rport_sm_created(struct bfa_rport_s *rp,
- enum bfa_rport_event event);
-static void bfa_rport_sm_fwcreate(struct bfa_rport_s *rp,
- enum bfa_rport_event event);
-static void bfa_rport_sm_online(struct bfa_rport_s *rp,
- enum bfa_rport_event event);
-static void bfa_rport_sm_fwdelete(struct bfa_rport_s *rp,
- enum bfa_rport_event event);
-static void bfa_rport_sm_offline(struct bfa_rport_s *rp,
- enum bfa_rport_event event);
-static void bfa_rport_sm_deleting(struct bfa_rport_s *rp,
- enum bfa_rport_event event);
-static void bfa_rport_sm_offline_pending(struct bfa_rport_s *rp,
- enum bfa_rport_event event);
-static void bfa_rport_sm_delete_pending(struct bfa_rport_s *rp,
- enum bfa_rport_event event);
-static void bfa_rport_sm_iocdisable(struct bfa_rport_s *rp,
- enum bfa_rport_event event);
-static void bfa_rport_sm_fwcreate_qfull(struct bfa_rport_s *rp,
- enum bfa_rport_event event);
-static void bfa_rport_sm_fwdelete_qfull(struct bfa_rport_s *rp,
- enum bfa_rport_event event);
-static void bfa_rport_sm_deleting_qfull(struct bfa_rport_s *rp,
- enum bfa_rport_event event);
-
-/**
- * Beginning state, only online event expected.
- */
-static void
-bfa_rport_sm_uninit(struct bfa_rport_s *rp, enum bfa_rport_event event)
-{
- bfa_trc(rp->bfa, rp->rport_tag);
- bfa_trc(rp->bfa, event);
-
- switch (event) {
- case BFA_RPORT_SM_CREATE:
- bfa_stats(rp, sm_un_cr);
- bfa_sm_set_state(rp, bfa_rport_sm_created);
- break;
-
- default:
- bfa_stats(rp, sm_un_unexp);
- bfa_sm_fault(rp->bfa, event);
- }
-}
-
-static void
-bfa_rport_sm_created(struct bfa_rport_s *rp, enum bfa_rport_event event)
-{
- bfa_trc(rp->bfa, rp->rport_tag);
- bfa_trc(rp->bfa, event);
-
- switch (event) {
- case BFA_RPORT_SM_ONLINE:
- bfa_stats(rp, sm_cr_on);
- if (bfa_rport_send_fwcreate(rp))
- bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
- else
- bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);
- break;
-
- case BFA_RPORT_SM_DELETE:
- bfa_stats(rp, sm_cr_del);
- bfa_sm_set_state(rp, bfa_rport_sm_uninit);
- bfa_rport_free(rp);
- break;
-
- case BFA_RPORT_SM_HWFAIL:
- bfa_stats(rp, sm_cr_hwf);
- bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
- break;
-
- default:
- bfa_stats(rp, sm_cr_unexp);
- bfa_sm_fault(rp->bfa, event);
- }
-}
-
-/**
- * Waiting for rport create response from firmware.
- */
-static void
-bfa_rport_sm_fwcreate(struct bfa_rport_s *rp, enum bfa_rport_event event)
-{
- bfa_trc(rp->bfa, rp->rport_tag);
- bfa_trc(rp->bfa, event);
-
- switch (event) {
- case BFA_RPORT_SM_FWRSP:
- bfa_stats(rp, sm_fwc_rsp);
- bfa_sm_set_state(rp, bfa_rport_sm_online);
- bfa_rport_online_cb(rp);
- break;
-
- case BFA_RPORT_SM_DELETE:
- bfa_stats(rp, sm_fwc_del);
- bfa_sm_set_state(rp, bfa_rport_sm_delete_pending);
- break;
-
- case BFA_RPORT_SM_OFFLINE:
- bfa_stats(rp, sm_fwc_off);
- bfa_sm_set_state(rp, bfa_rport_sm_offline_pending);
- break;
-
- case BFA_RPORT_SM_HWFAIL:
- bfa_stats(rp, sm_fwc_hwf);
- bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
- break;
-
- default:
- bfa_stats(rp, sm_fwc_unexp);
- bfa_sm_fault(rp->bfa, event);
- }
-}
-
-/**
- * Request queue is full, awaiting queue resume to send create request.
- */
-static void
-bfa_rport_sm_fwcreate_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)
-{
- bfa_trc(rp->bfa, rp->rport_tag);
- bfa_trc(rp->bfa, event);
-
- switch (event) {
- case BFA_RPORT_SM_QRESUME:
- bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
- bfa_rport_send_fwcreate(rp);
- break;
-
- case BFA_RPORT_SM_DELETE:
- bfa_stats(rp, sm_fwc_del);
- bfa_sm_set_state(rp, bfa_rport_sm_uninit);
- bfa_reqq_wcancel(&rp->reqq_wait);
- bfa_rport_free(rp);
- break;
-
- case BFA_RPORT_SM_OFFLINE:
- bfa_stats(rp, sm_fwc_off);
- bfa_sm_set_state(rp, bfa_rport_sm_offline);
- bfa_reqq_wcancel(&rp->reqq_wait);
- bfa_rport_offline_cb(rp);
- break;
-
- case BFA_RPORT_SM_HWFAIL:
- bfa_stats(rp, sm_fwc_hwf);
- bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
- bfa_reqq_wcancel(&rp->reqq_wait);
- break;
-
- default:
- bfa_stats(rp, sm_fwc_unexp);
- bfa_sm_fault(rp->bfa, event);
- }
-}
-
-/**
- * Online state - normal parking state.
- */
-static void
-bfa_rport_sm_online(struct bfa_rport_s *rp, enum bfa_rport_event event)
-{
- struct bfi_rport_qos_scn_s *qos_scn;
-
- bfa_trc(rp->bfa, rp->rport_tag);
- bfa_trc(rp->bfa, event);
-
- switch (event) {
- case BFA_RPORT_SM_OFFLINE:
- bfa_stats(rp, sm_on_off);
- if (bfa_rport_send_fwdelete(rp))
- bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);
- else
- bfa_sm_set_state(rp, bfa_rport_sm_fwdelete_qfull);
- break;
-
- case BFA_RPORT_SM_DELETE:
- bfa_stats(rp, sm_on_del);
- if (bfa_rport_send_fwdelete(rp))
- bfa_sm_set_state(rp, bfa_rport_sm_deleting);
- else
- bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);
- break;
-
- case BFA_RPORT_SM_HWFAIL:
- bfa_stats(rp, sm_on_hwf);
- bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
- break;
-
- case BFA_RPORT_SM_SET_SPEED:
- bfa_rport_send_fwspeed(rp);
- break;
-
- case BFA_RPORT_SM_QOS_SCN:
- qos_scn = (struct bfi_rport_qos_scn_s *) rp->event_arg.fw_msg;
- rp->qos_attr = qos_scn->new_qos_attr;
- bfa_trc(rp->bfa, qos_scn->old_qos_attr.qos_flow_id);
- bfa_trc(rp->bfa, qos_scn->new_qos_attr.qos_flow_id);
- bfa_trc(rp->bfa, qos_scn->old_qos_attr.qos_priority);
- bfa_trc(rp->bfa, qos_scn->new_qos_attr.qos_priority);
-
- qos_scn->old_qos_attr.qos_flow_id =
- bfa_os_ntohl(qos_scn->old_qos_attr.qos_flow_id);
- qos_scn->new_qos_attr.qos_flow_id =
- bfa_os_ntohl(qos_scn->new_qos_attr.qos_flow_id);
- qos_scn->old_qos_attr.qos_priority =
- bfa_os_ntohl(qos_scn->old_qos_attr.qos_priority);
- qos_scn->new_qos_attr.qos_priority =
- bfa_os_ntohl(qos_scn->new_qos_attr.qos_priority);
-
- if (qos_scn->old_qos_attr.qos_flow_id !=
- qos_scn->new_qos_attr.qos_flow_id)
- bfa_cb_rport_qos_scn_flowid(rp->rport_drv,
- qos_scn->old_qos_attr,
- qos_scn->new_qos_attr);
- if (qos_scn->old_qos_attr.qos_priority !=
- qos_scn->new_qos_attr.qos_priority)
- bfa_cb_rport_qos_scn_prio(rp->rport_drv,
- qos_scn->old_qos_attr,
- qos_scn->new_qos_attr);
- break;
-
- default:
- bfa_stats(rp, sm_on_unexp);
- bfa_sm_fault(rp->bfa, event);
- }
-}
-
-/**
- * Firmware rport is being deleted - awaiting f/w response.
- */
-static void
-bfa_rport_sm_fwdelete(struct bfa_rport_s *rp, enum bfa_rport_event event)
-{
- bfa_trc(rp->bfa, rp->rport_tag);
- bfa_trc(rp->bfa, event);
-
- switch (event) {
- case BFA_RPORT_SM_FWRSP:
- bfa_stats(rp, sm_fwd_rsp);
- bfa_sm_set_state(rp, bfa_rport_sm_offline);
- bfa_rport_offline_cb(rp);
- break;
-
- case BFA_RPORT_SM_DELETE:
- bfa_stats(rp, sm_fwd_del);
- bfa_sm_set_state(rp, bfa_rport_sm_deleting);
- break;
-
- case BFA_RPORT_SM_HWFAIL:
- bfa_stats(rp, sm_fwd_hwf);
- bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
- bfa_rport_offline_cb(rp);
- break;
-
- default:
- bfa_stats(rp, sm_fwd_unexp);
- bfa_sm_fault(rp->bfa, event);
- }
-}
-
-static void
-bfa_rport_sm_fwdelete_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)
-{
- bfa_trc(rp->bfa, rp->rport_tag);
- bfa_trc(rp->bfa, event);
-
- switch (event) {
- case BFA_RPORT_SM_QRESUME:
- bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);
- bfa_rport_send_fwdelete(rp);
- break;
-
- case BFA_RPORT_SM_DELETE:
- bfa_stats(rp, sm_fwd_del);
- bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);
- break;
-
- case BFA_RPORT_SM_HWFAIL:
- bfa_stats(rp, sm_fwd_hwf);
- bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
- bfa_reqq_wcancel(&rp->reqq_wait);
- bfa_rport_offline_cb(rp);
- break;
-
- default:
- bfa_stats(rp, sm_fwd_unexp);
- bfa_sm_fault(rp->bfa, event);
- }
-}
-
-/**
- * Offline state.
- */
-static void
-bfa_rport_sm_offline(struct bfa_rport_s *rp, enum bfa_rport_event event)
-{
- bfa_trc(rp->bfa, rp->rport_tag);
- bfa_trc(rp->bfa, event);
-
- switch (event) {
- case BFA_RPORT_SM_DELETE:
- bfa_stats(rp, sm_off_del);
- bfa_sm_set_state(rp, bfa_rport_sm_uninit);
- bfa_rport_free(rp);
- break;
-
- case BFA_RPORT_SM_ONLINE:
- bfa_stats(rp, sm_off_on);
- if (bfa_rport_send_fwcreate(rp))
- bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
- else
- bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);
- break;
-
- case BFA_RPORT_SM_HWFAIL:
- bfa_stats(rp, sm_off_hwf);
- bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
- break;
-
- default:
- bfa_stats(rp, sm_off_unexp);
- bfa_sm_fault(rp->bfa, event);
- }
-}
-
-/**
- * Rport is deleted, waiting for firmware response to delete.
- */
-static void
-bfa_rport_sm_deleting(struct bfa_rport_s *rp, enum bfa_rport_event event)
-{
- bfa_trc(rp->bfa, rp->rport_tag);
- bfa_trc(rp->bfa, event);
-
- switch (event) {
- case BFA_RPORT_SM_FWRSP:
- bfa_stats(rp, sm_del_fwrsp);
- bfa_sm_set_state(rp, bfa_rport_sm_uninit);
- bfa_rport_free(rp);
- break;
-
- case BFA_RPORT_SM_HWFAIL:
- bfa_stats(rp, sm_del_hwf);
- bfa_sm_set_state(rp, bfa_rport_sm_uninit);
- bfa_rport_free(rp);
- break;
-
- default:
- bfa_sm_fault(rp->bfa, event);
- }
-}
-
-static void
-bfa_rport_sm_deleting_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)
-{
- bfa_trc(rp->bfa, rp->rport_tag);
- bfa_trc(rp->bfa, event);
-
- switch (event) {
- case BFA_RPORT_SM_QRESUME:
- bfa_stats(rp, sm_del_fwrsp);
- bfa_sm_set_state(rp, bfa_rport_sm_deleting);
- bfa_rport_send_fwdelete(rp);
- break;
-
- case BFA_RPORT_SM_HWFAIL:
- bfa_stats(rp, sm_del_hwf);
- bfa_sm_set_state(rp, bfa_rport_sm_uninit);
- bfa_reqq_wcancel(&rp->reqq_wait);
- bfa_rport_free(rp);
- break;
-
- default:
- bfa_sm_fault(rp->bfa, event);
- }
-}
-
-/**
- * Waiting for rport create response from firmware. A delete is pending.
- */
-static void
-bfa_rport_sm_delete_pending(struct bfa_rport_s *rp,
- enum bfa_rport_event event)
-{
- bfa_trc(rp->bfa, rp->rport_tag);
- bfa_trc(rp->bfa, event);
-
- switch (event) {
- case BFA_RPORT_SM_FWRSP:
- bfa_stats(rp, sm_delp_fwrsp);
- if (bfa_rport_send_fwdelete(rp))
- bfa_sm_set_state(rp, bfa_rport_sm_deleting);
- else
- bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);
- break;
-
- case BFA_RPORT_SM_HWFAIL:
- bfa_stats(rp, sm_delp_hwf);
- bfa_sm_set_state(rp, bfa_rport_sm_uninit);
- bfa_rport_free(rp);
- break;
-
- default:
- bfa_stats(rp, sm_delp_unexp);
- bfa_sm_fault(rp->bfa, event);
- }
-}
-
-/**
- * Waiting for rport create response from firmware. Rport offline is pending.
- */
-static void
-bfa_rport_sm_offline_pending(struct bfa_rport_s *rp,
- enum bfa_rport_event event)
-{
- bfa_trc(rp->bfa, rp->rport_tag);
- bfa_trc(rp->bfa, event);
-
- switch (event) {
- case BFA_RPORT_SM_FWRSP:
- bfa_stats(rp, sm_offp_fwrsp);
- if (bfa_rport_send_fwdelete(rp))
- bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);
- else
- bfa_sm_set_state(rp, bfa_rport_sm_fwdelete_qfull);
- break;
-
- case BFA_RPORT_SM_DELETE:
- bfa_stats(rp, sm_offp_del);
- bfa_sm_set_state(rp, bfa_rport_sm_delete_pending);
- break;
-
- case BFA_RPORT_SM_HWFAIL:
- bfa_stats(rp, sm_offp_hwf);
- bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
- break;
-
- default:
- bfa_stats(rp, sm_offp_unexp);
- bfa_sm_fault(rp->bfa, event);
- }
-}
-
-/**
- * IOC h/w failed.
- */
-static void
-bfa_rport_sm_iocdisable(struct bfa_rport_s *rp, enum bfa_rport_event event)
-{
- bfa_trc(rp->bfa, rp->rport_tag);
- bfa_trc(rp->bfa, event);
-
- switch (event) {
- case BFA_RPORT_SM_OFFLINE:
- bfa_stats(rp, sm_iocd_off);
- bfa_rport_offline_cb(rp);
- break;
-
- case BFA_RPORT_SM_DELETE:
- bfa_stats(rp, sm_iocd_del);
- bfa_sm_set_state(rp, bfa_rport_sm_uninit);
- bfa_rport_free(rp);
- break;
-
- case BFA_RPORT_SM_ONLINE:
- bfa_stats(rp, sm_iocd_on);
- if (bfa_rport_send_fwcreate(rp))
- bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
- else
- bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);
- break;
-
- case BFA_RPORT_SM_HWFAIL:
- break;
-
- default:
- bfa_stats(rp, sm_iocd_unexp);
- bfa_sm_fault(rp->bfa, event);
- }
-}
-
-
-
-/**
- * bfa_rport_private BFA rport private functions
- */
-
-static void
-__bfa_cb_rport_online(void *cbarg, bfa_boolean_t complete)
-{
- struct bfa_rport_s *rp = cbarg;
-
- if (complete)
- bfa_cb_rport_online(rp->rport_drv);
-}
-
-static void
-__bfa_cb_rport_offline(void *cbarg, bfa_boolean_t complete)
-{
- struct bfa_rport_s *rp = cbarg;
-
- if (complete)
- bfa_cb_rport_offline(rp->rport_drv);
-}
-
-static void
-bfa_rport_qresume(void *cbarg)
-{
- struct bfa_rport_s *rp = cbarg;
-
- bfa_sm_send_event(rp, BFA_RPORT_SM_QRESUME);
-}
-
-static void
-bfa_rport_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
- u32 *dm_len)
-{
- if (cfg->fwcfg.num_rports < BFA_RPORT_MIN)
- cfg->fwcfg.num_rports = BFA_RPORT_MIN;
-
- *km_len += cfg->fwcfg.num_rports * sizeof(struct bfa_rport_s);
-}
-
-static void
-bfa_rport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
- struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
-{
- struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(bfa);
- struct bfa_rport_s *rp;
- u16 i;
-
- INIT_LIST_HEAD(&mod->rp_free_q);
- INIT_LIST_HEAD(&mod->rp_active_q);
-
- rp = (struct bfa_rport_s *) bfa_meminfo_kva(meminfo);
- mod->rps_list = rp;
- mod->num_rports = cfg->fwcfg.num_rports;
-
- bfa_assert(mod->num_rports
- && !(mod->num_rports & (mod->num_rports - 1)));
-
- for (i = 0; i < mod->num_rports; i++, rp++) {
- bfa_os_memset(rp, 0, sizeof(struct bfa_rport_s));
- rp->bfa = bfa;
- rp->rport_tag = i;
- bfa_sm_set_state(rp, bfa_rport_sm_uninit);
-
- /**
- * - is unused
- */
- if (i)
- list_add_tail(&rp->qe, &mod->rp_free_q);
-
- bfa_reqq_winit(&rp->reqq_wait, bfa_rport_qresume, rp);
- }
-
- /**
- * consume memory
- */
- bfa_meminfo_kva(meminfo) = (u8 *) rp;
-}
-
-static void
-bfa_rport_detach(struct bfa_s *bfa)
-{
-}
-
-static void
-bfa_rport_start(struct bfa_s *bfa)
-{
-}
-
-static void
-bfa_rport_stop(struct bfa_s *bfa)
-{
-}
-
-static void
-bfa_rport_iocdisable(struct bfa_s *bfa)
-{
- struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(bfa);
- struct bfa_rport_s *rport;
- struct list_head *qe, *qen;
-
- list_for_each_safe(qe, qen, &mod->rp_active_q) {
- rport = (struct bfa_rport_s *) qe;
- bfa_sm_send_event(rport, BFA_RPORT_SM_HWFAIL);
- }
-}
-
-static struct bfa_rport_s *
-bfa_rport_alloc(struct bfa_rport_mod_s *mod)
-{
- struct bfa_rport_s *rport;
-
- bfa_q_deq(&mod->rp_free_q, &rport);
- if (rport)
- list_add_tail(&rport->qe, &mod->rp_active_q);
-
- return rport;
-}
-
-static void
-bfa_rport_free(struct bfa_rport_s *rport)
-{
- struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(rport->bfa);
-
- bfa_assert(bfa_q_is_on_q(&mod->rp_active_q, rport));
- list_del(&rport->qe);
- list_add_tail(&rport->qe, &mod->rp_free_q);
-}
-
-static bfa_boolean_t
-bfa_rport_send_fwcreate(struct bfa_rport_s *rp)
-{
- struct bfi_rport_create_req_s *m;
-
- /**
- * check for room in queue to send request now
- */
- m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);
- if (!m) {
- bfa_reqq_wait(rp->bfa, BFA_REQQ_RPORT, &rp->reqq_wait);
- return BFA_FALSE;
- }
-
- bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_CREATE_REQ,
- bfa_lpuid(rp->bfa));
- m->bfa_handle = rp->rport_tag;
- m->max_frmsz = bfa_os_htons(rp->rport_info.max_frmsz);
- m->pid = rp->rport_info.pid;
- m->lp_tag = rp->rport_info.lp_tag;
- m->local_pid = rp->rport_info.local_pid;
- m->fc_class = rp->rport_info.fc_class;
- m->vf_en = rp->rport_info.vf_en;
- m->vf_id = rp->rport_info.vf_id;
- m->cisc = rp->rport_info.cisc;
-
- /**
- * queue I/O message to firmware
- */
- bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT);
- return BFA_TRUE;
-}
-
-static bfa_boolean_t
-bfa_rport_send_fwdelete(struct bfa_rport_s *rp)
-{
- struct bfi_rport_delete_req_s *m;
-
- /**
- * check for room in queue to send request now
- */
- m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);
- if (!m) {
- bfa_reqq_wait(rp->bfa, BFA_REQQ_RPORT, &rp->reqq_wait);
- return BFA_FALSE;
- }
-
- bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_DELETE_REQ,
- bfa_lpuid(rp->bfa));
- m->fw_handle = rp->fw_handle;
-
- /**
- * queue I/O message to firmware
- */
- bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT);
- return BFA_TRUE;
-}
-
-static bfa_boolean_t
-bfa_rport_send_fwspeed(struct bfa_rport_s *rp)
-{
- struct bfa_rport_speed_req_s *m;
-
- /**
- * check for room in queue to send request now
- */
- m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);
- if (!m) {
- bfa_trc(rp->bfa, rp->rport_info.speed);
- return BFA_FALSE;
- }
-
- bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_SET_SPEED_REQ,
- bfa_lpuid(rp->bfa));
- m->fw_handle = rp->fw_handle;
- m->speed = (u8)rp->rport_info.speed;
-
- /**
- * queue I/O message to firmware
- */
- bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT);
- return BFA_TRUE;
-}
-
-
-
-/**
- * bfa_rport_public
- */
-
-/**
- * Rport interrupt processing.
- */
-void
-bfa_rport_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
-{
- union bfi_rport_i2h_msg_u msg;
- struct bfa_rport_s *rp;
-
- bfa_trc(bfa, m->mhdr.msg_id);
-
- msg.msg = m;
-
- switch (m->mhdr.msg_id) {
- case BFI_RPORT_I2H_CREATE_RSP:
- rp = BFA_RPORT_FROM_TAG(bfa, msg.create_rsp->bfa_handle);
- rp->fw_handle = msg.create_rsp->fw_handle;
- rp->qos_attr = msg.create_rsp->qos_attr;
- bfa_assert(msg.create_rsp->status == BFA_STATUS_OK);
- bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP);
- break;
-
- case BFI_RPORT_I2H_DELETE_RSP:
- rp = BFA_RPORT_FROM_TAG(bfa, msg.delete_rsp->bfa_handle);
- bfa_assert(msg.delete_rsp->status == BFA_STATUS_OK);
- bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP);
- break;
-
- case BFI_RPORT_I2H_QOS_SCN:
- rp = BFA_RPORT_FROM_TAG(bfa, msg.qos_scn_evt->bfa_handle);
- rp->event_arg.fw_msg = msg.qos_scn_evt;
- bfa_sm_send_event(rp, BFA_RPORT_SM_QOS_SCN);
- break;
-
- default:
- bfa_trc(bfa, m->mhdr.msg_id);
- bfa_assert(0);
- }
-}
-
-
-
-/**
- * bfa_rport_api
- */
-
-struct bfa_rport_s *
-bfa_rport_create(struct bfa_s *bfa, void *rport_drv)
-{
- struct bfa_rport_s *rp;
-
- rp = bfa_rport_alloc(BFA_RPORT_MOD(bfa));
-
- if (rp == NULL)
- return NULL;
-
- rp->bfa = bfa;
- rp->rport_drv = rport_drv;
- bfa_rport_clear_stats(rp);
-
- bfa_assert(bfa_sm_cmp_state(rp, bfa_rport_sm_uninit));
- bfa_sm_send_event(rp, BFA_RPORT_SM_CREATE);
-
- return rp;
-}
-
-void
-bfa_rport_delete(struct bfa_rport_s *rport)
-{
- bfa_sm_send_event(rport, BFA_RPORT_SM_DELETE);
-}
-
-void
-bfa_rport_online(struct bfa_rport_s *rport, struct bfa_rport_info_s *rport_info)
-{
- bfa_assert(rport_info->max_frmsz != 0);
-
- /**
- * Some JBODs are seen to be not setting PDU size correctly in PLOGI
- * responses. Default to minimum size.
- */
- if (rport_info->max_frmsz == 0) {
- bfa_trc(rport->bfa, rport->rport_tag);
- rport_info->max_frmsz = FC_MIN_PDUSZ;
- }
-
- bfa_os_assign(rport->rport_info, *rport_info);
- bfa_sm_send_event(rport, BFA_RPORT_SM_ONLINE);
-}
-
-void
-bfa_rport_offline(struct bfa_rport_s *rport)
-{
- bfa_sm_send_event(rport, BFA_RPORT_SM_OFFLINE);
-}
-
-void
-bfa_rport_speed(struct bfa_rport_s *rport, enum bfa_pport_speed speed)
-{
- bfa_assert(speed != 0);
- bfa_assert(speed != BFA_PPORT_SPEED_AUTO);
-
- rport->rport_info.speed = speed;
- bfa_sm_send_event(rport, BFA_RPORT_SM_SET_SPEED);
-}
-
-void
-bfa_rport_get_stats(struct bfa_rport_s *rport,
- struct bfa_rport_hal_stats_s *stats)
-{
- *stats = rport->stats;
-}
-
-void
-bfa_rport_get_qos_attr(struct bfa_rport_s *rport,
- struct bfa_rport_qos_attr_s *qos_attr)
-{
- qos_attr->qos_priority = bfa_os_ntohl(rport->qos_attr.qos_priority);
- qos_attr->qos_flow_id = bfa_os_ntohl(rport->qos_attr.qos_flow_id);
-
-}
-
-void
-bfa_rport_clear_stats(struct bfa_rport_s *rport)
-{
- bfa_os_memset(&rport->stats, 0, sizeof(rport->stats));
-}
-
-
diff --git a/drivers/scsi/bfa/bfa_rport_priv.h b/drivers/scsi/bfa/bfa_rport_priv.h
deleted file mode 100644
index 6490ce2e990d..000000000000
--- a/drivers/scsi/bfa/bfa_rport_priv.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_RPORT_PRIV_H__
-#define __BFA_RPORT_PRIV_H__
-
-#include <bfa_svc.h>
-
-#define BFA_RPORT_MIN 4
-
-struct bfa_rport_mod_s {
- struct bfa_rport_s *rps_list; /* list of rports */
- struct list_head rp_free_q; /* free bfa_rports */
- struct list_head rp_active_q; /* free bfa_rports */
- u16 num_rports; /* number of rports */
-};
-
-#define BFA_RPORT_MOD(__bfa) (&(__bfa)->modules.rport_mod)
-
-/**
- * Convert rport tag to RPORT
- */
-#define BFA_RPORT_FROM_TAG(__bfa, _tag) \
- (BFA_RPORT_MOD(__bfa)->rps_list + \
- ((_tag) & (BFA_RPORT_MOD(__bfa)->num_rports - 1)))
-
-/*
- * external functions
- */
-void bfa_rport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
-#endif /* __BFA_RPORT_PRIV_H__ */
diff --git a/drivers/scsi/bfa/bfa_sgpg.c b/drivers/scsi/bfa/bfa_sgpg.c
deleted file mode 100644
index ae452c42e40e..000000000000
--- a/drivers/scsi/bfa/bfa_sgpg.c
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#include <bfa.h>
-
-BFA_TRC_FILE(HAL, SGPG);
-BFA_MODULE(sgpg);
-
-/**
- * bfa_sgpg_mod BFA SGPG Mode module
- */
-
-/**
- * Compute and return memory needed by FCP(im) module.
- */
-static void
-bfa_sgpg_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
- u32 *dm_len)
-{
- if (cfg->drvcfg.num_sgpgs < BFA_SGPG_MIN)
- cfg->drvcfg.num_sgpgs = BFA_SGPG_MIN;
-
- *km_len += (cfg->drvcfg.num_sgpgs + 1) * sizeof(struct bfa_sgpg_s);
- *dm_len += (cfg->drvcfg.num_sgpgs + 1) * sizeof(struct bfi_sgpg_s);
-}
-
-
-static void
-bfa_sgpg_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
- struct bfa_meminfo_s *minfo, struct bfa_pcidev_s *pcidev)
-{
- struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
- int i;
- struct bfa_sgpg_s *hsgpg;
- struct bfi_sgpg_s *sgpg;
- u64 align_len;
-
- union {
- u64 pa;
- union bfi_addr_u addr;
- } sgpg_pa;
-
- INIT_LIST_HEAD(&mod->sgpg_q);
- INIT_LIST_HEAD(&mod->sgpg_wait_q);
-
- bfa_trc(bfa, cfg->drvcfg.num_sgpgs);
-
- mod->num_sgpgs = cfg->drvcfg.num_sgpgs;
- mod->sgpg_arr_pa = bfa_meminfo_dma_phys(minfo);
- align_len = (BFA_SGPG_ROUNDUP(mod->sgpg_arr_pa) - mod->sgpg_arr_pa);
- mod->sgpg_arr_pa += align_len;
- mod->hsgpg_arr = (struct bfa_sgpg_s *) (bfa_meminfo_kva(minfo) +
- align_len);
- mod->sgpg_arr = (struct bfi_sgpg_s *) (bfa_meminfo_dma_virt(minfo) +
- align_len);
-
- hsgpg = mod->hsgpg_arr;
- sgpg = mod->sgpg_arr;
- sgpg_pa.pa = mod->sgpg_arr_pa;
- mod->free_sgpgs = mod->num_sgpgs;
-
- bfa_assert(!(sgpg_pa.pa & (sizeof(struct bfi_sgpg_s) - 1)));
-
- for (i = 0; i < mod->num_sgpgs; i++) {
- bfa_os_memset(hsgpg, 0, sizeof(*hsgpg));
- bfa_os_memset(sgpg, 0, sizeof(*sgpg));
-
- hsgpg->sgpg = sgpg;
- hsgpg->sgpg_pa = sgpg_pa.addr;
- list_add_tail(&hsgpg->qe, &mod->sgpg_q);
-
- hsgpg++;
- sgpg++;
- sgpg_pa.pa += sizeof(struct bfi_sgpg_s);
- }
-
- bfa_meminfo_kva(minfo) = (u8 *) hsgpg;
- bfa_meminfo_dma_virt(minfo) = (u8 *) sgpg;
- bfa_meminfo_dma_phys(minfo) = sgpg_pa.pa;
-}
-
-static void
-bfa_sgpg_detach(struct bfa_s *bfa)
-{
-}
-
-static void
-bfa_sgpg_start(struct bfa_s *bfa)
-{
-}
-
-static void
-bfa_sgpg_stop(struct bfa_s *bfa)
-{
-}
-
-static void
-bfa_sgpg_iocdisable(struct bfa_s *bfa)
-{
-}
-
-
-
-/**
- * bfa_sgpg_public BFA SGPG public functions
- */
-
-bfa_status_t
-bfa_sgpg_malloc(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpgs)
-{
- struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
- struct bfa_sgpg_s *hsgpg;
- int i;
-
- bfa_trc_fp(bfa, nsgpgs);
-
- if (mod->free_sgpgs < nsgpgs)
- return BFA_STATUS_ENOMEM;
-
- for (i = 0; i < nsgpgs; i++) {
- bfa_q_deq(&mod->sgpg_q, &hsgpg);
- bfa_assert(hsgpg);
- list_add_tail(&hsgpg->qe, sgpg_q);
- }
-
- mod->free_sgpgs -= nsgpgs;
- return BFA_STATUS_OK;
-}
-
-void
-bfa_sgpg_mfree(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpg)
-{
- struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
- struct bfa_sgpg_wqe_s *wqe;
-
- bfa_trc_fp(bfa, nsgpg);
-
- mod->free_sgpgs += nsgpg;
- bfa_assert(mod->free_sgpgs <= mod->num_sgpgs);
-
- list_splice_tail_init(sgpg_q, &mod->sgpg_q);
-
- if (list_empty(&mod->sgpg_wait_q))
- return;
-
- /**
- * satisfy as many waiting requests as possible
- */
- do {
- wqe = bfa_q_first(&mod->sgpg_wait_q);
- if (mod->free_sgpgs < wqe->nsgpg)
- nsgpg = mod->free_sgpgs;
- else
- nsgpg = wqe->nsgpg;
- bfa_sgpg_malloc(bfa, &wqe->sgpg_q, nsgpg);
- wqe->nsgpg -= nsgpg;
- if (wqe->nsgpg == 0) {
- list_del(&wqe->qe);
- wqe->cbfn(wqe->cbarg);
- }
- } while (mod->free_sgpgs && !list_empty(&mod->sgpg_wait_q));
-}
-
-void
-bfa_sgpg_wait(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe, int nsgpg)
-{
- struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
-
- bfa_assert(nsgpg > 0);
- bfa_assert(nsgpg > mod->free_sgpgs);
-
- wqe->nsgpg_total = wqe->nsgpg = nsgpg;
-
- /**
- * allocate any left to this one first
- */
- if (mod->free_sgpgs) {
- /**
- * no one else is waiting for SGPG
- */
- bfa_assert(list_empty(&mod->sgpg_wait_q));
- list_splice_tail_init(&mod->sgpg_q, &wqe->sgpg_q);
- wqe->nsgpg -= mod->free_sgpgs;
- mod->free_sgpgs = 0;
- }
-
- list_add_tail(&wqe->qe, &mod->sgpg_wait_q);
-}
-
-void
-bfa_sgpg_wcancel(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe)
-{
- struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
-
- bfa_assert(bfa_q_is_on_q(&mod->sgpg_wait_q, wqe));
- list_del(&wqe->qe);
-
- if (wqe->nsgpg_total != wqe->nsgpg)
- bfa_sgpg_mfree(bfa, &wqe->sgpg_q,
- wqe->nsgpg_total - wqe->nsgpg);
-}
-
-void
-bfa_sgpg_winit(struct bfa_sgpg_wqe_s *wqe, void (*cbfn) (void *cbarg),
- void *cbarg)
-{
- INIT_LIST_HEAD(&wqe->sgpg_q);
- wqe->cbfn = cbfn;
- wqe->cbarg = cbarg;
-}
-
-
diff --git a/drivers/scsi/bfa/bfa_sgpg_priv.h b/drivers/scsi/bfa/bfa_sgpg_priv.h
deleted file mode 100644
index 9c2a8cbe7522..000000000000
--- a/drivers/scsi/bfa/bfa_sgpg_priv.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/**
- * hal_sgpg.h BFA SG page module
- */
-
-#ifndef __BFA_SGPG_PRIV_H__
-#define __BFA_SGPG_PRIV_H__
-
-#include <cs/bfa_q.h>
-
-#define BFA_SGPG_MIN (16)
-
-/**
- * Alignment macro for SG page allocation
- */
-#define BFA_SGPG_ROUNDUP(_l) (((_l) + (sizeof(struct bfi_sgpg_s) - 1)) \
- & ~(sizeof(struct bfi_sgpg_s) - 1))
-
-struct bfa_sgpg_wqe_s {
- struct list_head qe; /* queue sg page element */
- int nsgpg; /* pages to be allocated */
- int nsgpg_total; /* total pages required */
- void (*cbfn) (void *cbarg);
- /* callback function */
- void *cbarg; /* callback arg */
- struct list_head sgpg_q; /* queue of alloced sgpgs */
-};
-
-struct bfa_sgpg_s {
- struct list_head qe; /* queue sg page element */
- struct bfi_sgpg_s *sgpg; /* va of SG page */
- union bfi_addr_u sgpg_pa;/* pa of SG page */
-};
-
-/**
- * Given number of SG elements, BFA_SGPG_NPAGE() returns the number of
- * SG pages required.
- */
-#define BFA_SGPG_NPAGE(_nsges) (((_nsges) / BFI_SGPG_DATA_SGES) + 1)
-
-struct bfa_sgpg_mod_s {
- struct bfa_s *bfa;
- int num_sgpgs; /* number of SG pages */
- int free_sgpgs; /* number of free SG pages */
- struct bfa_sgpg_s *hsgpg_arr; /* BFA SG page array */
- struct bfi_sgpg_s *sgpg_arr; /* actual SG page array */
- u64 sgpg_arr_pa; /* SG page array DMA addr */
- struct list_head sgpg_q; /* queue of free SG pages */
- struct list_head sgpg_wait_q; /* wait queue for SG pages */
-};
-#define BFA_SGPG_MOD(__bfa) (&(__bfa)->modules.sgpg_mod)
-
-bfa_status_t bfa_sgpg_malloc(struct bfa_s *bfa, struct list_head *sgpg_q,
- int nsgpgs);
-void bfa_sgpg_mfree(struct bfa_s *bfa, struct list_head *sgpg_q,
- int nsgpgs);
-void bfa_sgpg_winit(struct bfa_sgpg_wqe_s *wqe,
- void (*cbfn) (void *cbarg), void *cbarg);
-void bfa_sgpg_wait(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe,
- int nsgpgs);
-void bfa_sgpg_wcancel(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe);
-
-#endif /* __BFA_SGPG_PRIV_H__ */
diff --git a/drivers/scsi/bfa/bfa_sm.c b/drivers/scsi/bfa/bfa_sm.c
deleted file mode 100644
index 5420f4f45e58..000000000000
--- a/drivers/scsi/bfa/bfa_sm.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/**
- * bfasm.c BFA State machine utility functions
- */
-
-#include <cs/bfa_sm.h>
-
-/**
- * cs_sm_api
- */
-
-int
-bfa_sm_to_state(struct bfa_sm_table_s *smt, bfa_sm_t sm)
-{
- int i = 0;
-
- while (smt[i].sm && smt[i].sm != sm)
- i++;
- return smt[i].state;
-}
-
-
diff --git a/drivers/scsi/bfa/bfa_svc.c b/drivers/scsi/bfa/bfa_svc.c
new file mode 100644
index 000000000000..aa1dc749b281
--- /dev/null
+++ b/drivers/scsi/bfa/bfa_svc.c
@@ -0,0 +1,5423 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#include "bfa_os_inc.h"
+#include "bfa_plog.h"
+#include "bfa_cs.h"
+#include "bfa_modules.h"
+#include "bfad_drv.h"
+
+BFA_TRC_FILE(HAL, FCXP);
+BFA_MODULE(fcxp);
+BFA_MODULE(sgpg);
+BFA_MODULE(lps);
+BFA_MODULE(fcport);
+BFA_MODULE(rport);
+BFA_MODULE(uf);
+
+/**
+ * LPS related definitions
+ */
+#define BFA_LPS_MIN_LPORTS (1)
+#define BFA_LPS_MAX_LPORTS (256)
+
+/*
+ * Maximum Vports supported per physical port or vf.
+ */
+#define BFA_LPS_MAX_VPORTS_SUPP_CB 255
+#define BFA_LPS_MAX_VPORTS_SUPP_CT 190
+
+/**
+ * lps_pvt BFA LPS private functions
+ */
+
+enum bfa_lps_event {
+ BFA_LPS_SM_LOGIN = 1, /* login request from user */
+ BFA_LPS_SM_LOGOUT = 2, /* logout request from user */
+ BFA_LPS_SM_FWRSP = 3, /* f/w response to login/logout */
+ BFA_LPS_SM_RESUME = 4, /* space present in reqq queue */
+ BFA_LPS_SM_DELETE = 5, /* lps delete from user */
+ BFA_LPS_SM_OFFLINE = 6, /* Link is offline */
+ BFA_LPS_SM_RX_CVL = 7, /* Rx clear virtual link */
+};
+
+/**
+ * FC PORT related definitions
+ */
+/*
+ * The port is considered disabled if corresponding physical port or IOC are
+ * disabled explicitly
+ */
+#define BFA_PORT_IS_DISABLED(bfa) \
+ ((bfa_fcport_is_disabled(bfa) == BFA_TRUE) || \
+ (bfa_ioc_is_disabled(&bfa->ioc) == BFA_TRUE))
+
+
+/**
+ * BFA port state machine events
+ */
+enum bfa_fcport_sm_event {
+ BFA_FCPORT_SM_START = 1, /* start port state machine */
+ BFA_FCPORT_SM_STOP = 2, /* stop port state machine */
+ BFA_FCPORT_SM_ENABLE = 3, /* enable port */
+ BFA_FCPORT_SM_DISABLE = 4, /* disable port state machine */
+ BFA_FCPORT_SM_FWRSP = 5, /* firmware enable/disable rsp */
+ BFA_FCPORT_SM_LINKUP = 6, /* firmware linkup event */
+ BFA_FCPORT_SM_LINKDOWN = 7, /* firmware linkup down */
+ BFA_FCPORT_SM_QRESUME = 8, /* CQ space available */
+ BFA_FCPORT_SM_HWFAIL = 9, /* IOC h/w failure */
+};
+
+/**
+ * BFA port link notification state machine events
+ */
+
+enum bfa_fcport_ln_sm_event {
+ BFA_FCPORT_LN_SM_LINKUP = 1, /* linkup event */
+ BFA_FCPORT_LN_SM_LINKDOWN = 2, /* linkdown event */
+ BFA_FCPORT_LN_SM_NOTIFICATION = 3 /* done notification */
+};
+
+/**
+ * RPORT related definitions
+ */
+#define bfa_rport_offline_cb(__rp) do { \
+ if ((__rp)->bfa->fcs) \
+ bfa_cb_rport_offline((__rp)->rport_drv); \
+ else { \
+ bfa_cb_queue((__rp)->bfa, &(__rp)->hcb_qe, \
+ __bfa_cb_rport_offline, (__rp)); \
+ } \
+} while (0)
+
+#define bfa_rport_online_cb(__rp) do { \
+ if ((__rp)->bfa->fcs) \
+ bfa_cb_rport_online((__rp)->rport_drv); \
+ else { \
+ bfa_cb_queue((__rp)->bfa, &(__rp)->hcb_qe, \
+ __bfa_cb_rport_online, (__rp)); \
+ } \
+} while (0)
+
+
+enum bfa_rport_event {
+ BFA_RPORT_SM_CREATE = 1, /* rport create event */
+ BFA_RPORT_SM_DELETE = 2, /* deleting an existing rport */
+ BFA_RPORT_SM_ONLINE = 3, /* rport is online */
+ BFA_RPORT_SM_OFFLINE = 4, /* rport is offline */
+ BFA_RPORT_SM_FWRSP = 5, /* firmware response */
+ BFA_RPORT_SM_HWFAIL = 6, /* IOC h/w failure */
+ BFA_RPORT_SM_QOS_SCN = 7, /* QoS SCN from firmware */
+ BFA_RPORT_SM_SET_SPEED = 8, /* Set Rport Speed */
+ BFA_RPORT_SM_QRESUME = 9, /* space in requeue queue */
+};
+
+/**
+ * forward declarations FCXP related functions
+ */
+static void __bfa_fcxp_send_cbfn(void *cbarg, bfa_boolean_t complete);
+static void hal_fcxp_rx_plog(struct bfa_s *bfa, struct bfa_fcxp_s *fcxp,
+ struct bfi_fcxp_send_rsp_s *fcxp_rsp);
+static void hal_fcxp_tx_plog(struct bfa_s *bfa, u32 reqlen,
+ struct bfa_fcxp_s *fcxp, struct fchs_s *fchs);
+static void bfa_fcxp_qresume(void *cbarg);
+static void bfa_fcxp_queue(struct bfa_fcxp_s *fcxp,
+ struct bfi_fcxp_send_req_s *send_req);
+
+/**
+ * forward declarations for LPS functions
+ */
+static void bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
+ u32 *dm_len);
+static void bfa_lps_attach(struct bfa_s *bfa, void *bfad,
+ struct bfa_iocfc_cfg_s *cfg,
+ struct bfa_meminfo_s *meminfo,
+ struct bfa_pcidev_s *pcidev);
+static void bfa_lps_detach(struct bfa_s *bfa);
+static void bfa_lps_start(struct bfa_s *bfa);
+static void bfa_lps_stop(struct bfa_s *bfa);
+static void bfa_lps_iocdisable(struct bfa_s *bfa);
+static void bfa_lps_login_rsp(struct bfa_s *bfa,
+ struct bfi_lps_login_rsp_s *rsp);
+static void bfa_lps_logout_rsp(struct bfa_s *bfa,
+ struct bfi_lps_logout_rsp_s *rsp);
+static void bfa_lps_reqq_resume(void *lps_arg);
+static void bfa_lps_free(struct bfa_lps_s *lps);
+static void bfa_lps_send_login(struct bfa_lps_s *lps);
+static void bfa_lps_send_logout(struct bfa_lps_s *lps);
+static void bfa_lps_login_comp(struct bfa_lps_s *lps);
+static void bfa_lps_logout_comp(struct bfa_lps_s *lps);
+static void bfa_lps_cvl_event(struct bfa_lps_s *lps);
+
+/**
+ * forward declaration for LPS state machine
+ */
+static void bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event);
+static void bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event);
+static void bfa_lps_sm_loginwait(struct bfa_lps_s *lps, enum bfa_lps_event
+ event);
+static void bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event);
+static void bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event);
+static void bfa_lps_sm_logowait(struct bfa_lps_s *lps, enum bfa_lps_event
+ event);
+
+/**
+ * forward declaration for FC Port functions
+ */
+static bfa_boolean_t bfa_fcport_send_enable(struct bfa_fcport_s *fcport);
+static bfa_boolean_t bfa_fcport_send_disable(struct bfa_fcport_s *fcport);
+static void bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport);
+static void bfa_fcport_reset_linkinfo(struct bfa_fcport_s *fcport);
+static void bfa_fcport_set_wwns(struct bfa_fcport_s *fcport);
+static void __bfa_cb_fcport_event(void *cbarg, bfa_boolean_t complete);
+static void bfa_fcport_scn(struct bfa_fcport_s *fcport,
+ enum bfa_port_linkstate event, bfa_boolean_t trunk);
+static void bfa_fcport_queue_cb(struct bfa_fcport_ln_s *ln,
+ enum bfa_port_linkstate event);
+static void __bfa_cb_fcport_stats_clr(void *cbarg, bfa_boolean_t complete);
+static void bfa_fcport_stats_get_timeout(void *cbarg);
+static void bfa_fcport_stats_clr_timeout(void *cbarg);
+static void bfa_trunk_iocdisable(struct bfa_s *bfa);
+
+/**
+ * forward declaration for FC PORT state machine
+ */
+static void bfa_fcport_sm_uninit(struct bfa_fcport_s *fcport,
+ enum bfa_fcport_sm_event event);
+static void bfa_fcport_sm_enabling_qwait(struct bfa_fcport_s *fcport,
+ enum bfa_fcport_sm_event event);
+static void bfa_fcport_sm_enabling(struct bfa_fcport_s *fcport,
+ enum bfa_fcport_sm_event event);
+static void bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport,
+ enum bfa_fcport_sm_event event);
+static void bfa_fcport_sm_linkup(struct bfa_fcport_s *fcport,
+ enum bfa_fcport_sm_event event);
+static void bfa_fcport_sm_disabling(struct bfa_fcport_s *fcport,
+ enum bfa_fcport_sm_event event);
+static void bfa_fcport_sm_disabling_qwait(struct bfa_fcport_s *fcport,
+ enum bfa_fcport_sm_event event);
+static void bfa_fcport_sm_toggling_qwait(struct bfa_fcport_s *fcport,
+ enum bfa_fcport_sm_event event);
+static void bfa_fcport_sm_disabled(struct bfa_fcport_s *fcport,
+ enum bfa_fcport_sm_event event);
+static void bfa_fcport_sm_stopped(struct bfa_fcport_s *fcport,
+ enum bfa_fcport_sm_event event);
+static void bfa_fcport_sm_iocdown(struct bfa_fcport_s *fcport,
+ enum bfa_fcport_sm_event event);
+static void bfa_fcport_sm_iocfail(struct bfa_fcport_s *fcport,
+ enum bfa_fcport_sm_event event);
+
+static void bfa_fcport_ln_sm_dn(struct bfa_fcport_ln_s *ln,
+ enum bfa_fcport_ln_sm_event event);
+static void bfa_fcport_ln_sm_dn_nf(struct bfa_fcport_ln_s *ln,
+ enum bfa_fcport_ln_sm_event event);
+static void bfa_fcport_ln_sm_dn_up_nf(struct bfa_fcport_ln_s *ln,
+ enum bfa_fcport_ln_sm_event event);
+static void bfa_fcport_ln_sm_up(struct bfa_fcport_ln_s *ln,
+ enum bfa_fcport_ln_sm_event event);
+static void bfa_fcport_ln_sm_up_nf(struct bfa_fcport_ln_s *ln,
+ enum bfa_fcport_ln_sm_event event);
+static void bfa_fcport_ln_sm_up_dn_nf(struct bfa_fcport_ln_s *ln,
+ enum bfa_fcport_ln_sm_event event);
+static void bfa_fcport_ln_sm_up_dn_up_nf(struct bfa_fcport_ln_s *ln,
+ enum bfa_fcport_ln_sm_event event);
+
+static struct bfa_sm_table_s hal_port_sm_table[] = {
+ {BFA_SM(bfa_fcport_sm_uninit), BFA_PORT_ST_UNINIT},
+ {BFA_SM(bfa_fcport_sm_enabling_qwait), BFA_PORT_ST_ENABLING_QWAIT},
+ {BFA_SM(bfa_fcport_sm_enabling), BFA_PORT_ST_ENABLING},
+ {BFA_SM(bfa_fcport_sm_linkdown), BFA_PORT_ST_LINKDOWN},
+ {BFA_SM(bfa_fcport_sm_linkup), BFA_PORT_ST_LINKUP},
+ {BFA_SM(bfa_fcport_sm_disabling_qwait), BFA_PORT_ST_DISABLING_QWAIT},
+ {BFA_SM(bfa_fcport_sm_toggling_qwait), BFA_PORT_ST_TOGGLING_QWAIT},
+ {BFA_SM(bfa_fcport_sm_disabling), BFA_PORT_ST_DISABLING},
+ {BFA_SM(bfa_fcport_sm_disabled), BFA_PORT_ST_DISABLED},
+ {BFA_SM(bfa_fcport_sm_stopped), BFA_PORT_ST_STOPPED},
+ {BFA_SM(bfa_fcport_sm_iocdown), BFA_PORT_ST_IOCDOWN},
+ {BFA_SM(bfa_fcport_sm_iocfail), BFA_PORT_ST_IOCDOWN},
+};
+
+
+/**
+ * forward declaration for RPORT related functions
+ */
+static struct bfa_rport_s *bfa_rport_alloc(struct bfa_rport_mod_s *rp_mod);
+static void bfa_rport_free(struct bfa_rport_s *rport);
+static bfa_boolean_t bfa_rport_send_fwcreate(struct bfa_rport_s *rp);
+static bfa_boolean_t bfa_rport_send_fwdelete(struct bfa_rport_s *rp);
+static bfa_boolean_t bfa_rport_send_fwspeed(struct bfa_rport_s *rp);
+static void __bfa_cb_rport_online(void *cbarg,
+ bfa_boolean_t complete);
+static void __bfa_cb_rport_offline(void *cbarg,
+ bfa_boolean_t complete);
+
+/**
+ * forward declaration for RPORT state machine
+ */
+static void bfa_rport_sm_uninit(struct bfa_rport_s *rp,
+ enum bfa_rport_event event);
+static void bfa_rport_sm_created(struct bfa_rport_s *rp,
+ enum bfa_rport_event event);
+static void bfa_rport_sm_fwcreate(struct bfa_rport_s *rp,
+ enum bfa_rport_event event);
+static void bfa_rport_sm_online(struct bfa_rport_s *rp,
+ enum bfa_rport_event event);
+static void bfa_rport_sm_fwdelete(struct bfa_rport_s *rp,
+ enum bfa_rport_event event);
+static void bfa_rport_sm_offline(struct bfa_rport_s *rp,
+ enum bfa_rport_event event);
+static void bfa_rport_sm_deleting(struct bfa_rport_s *rp,
+ enum bfa_rport_event event);
+static void bfa_rport_sm_offline_pending(struct bfa_rport_s *rp,
+ enum bfa_rport_event event);
+static void bfa_rport_sm_delete_pending(struct bfa_rport_s *rp,
+ enum bfa_rport_event event);
+static void bfa_rport_sm_iocdisable(struct bfa_rport_s *rp,
+ enum bfa_rport_event event);
+static void bfa_rport_sm_fwcreate_qfull(struct bfa_rport_s *rp,
+ enum bfa_rport_event event);
+static void bfa_rport_sm_fwdelete_qfull(struct bfa_rport_s *rp,
+ enum bfa_rport_event event);
+static void bfa_rport_sm_deleting_qfull(struct bfa_rport_s *rp,
+ enum bfa_rport_event event);
+
+/**
+ * PLOG related definitions
+ */
+static int
+plkd_validate_logrec(struct bfa_plog_rec_s *pl_rec)
+{
+ if ((pl_rec->log_type != BFA_PL_LOG_TYPE_INT) &&
+ (pl_rec->log_type != BFA_PL_LOG_TYPE_STRING))
+ return 1;
+
+ if ((pl_rec->log_type != BFA_PL_LOG_TYPE_INT) &&
+ (pl_rec->log_num_ints > BFA_PL_INT_LOG_SZ))
+ return 1;
+
+ return 0;
+}
+
+static void
+bfa_plog_add(struct bfa_plog_s *plog, struct bfa_plog_rec_s *pl_rec)
+{
+ u16 tail;
+ struct bfa_plog_rec_s *pl_recp;
+
+ if (plog->plog_enabled == 0)
+ return;
+
+ if (plkd_validate_logrec(pl_rec)) {
+ bfa_assert(0);
+ return;
+ }
+
+ tail = plog->tail;
+
+ pl_recp = &(plog->plog_recs[tail]);
+
+ bfa_os_memcpy(pl_recp, pl_rec, sizeof(struct bfa_plog_rec_s));
+
+ pl_recp->tv = bfa_os_get_log_time();
+ BFA_PL_LOG_REC_INCR(plog->tail);
+
+ if (plog->head == plog->tail)
+ BFA_PL_LOG_REC_INCR(plog->head);
+}
+
+void
+bfa_plog_init(struct bfa_plog_s *plog)
+{
+ bfa_os_memset((char *)plog, 0, sizeof(struct bfa_plog_s));
+
+ bfa_os_memcpy(plog->plog_sig, BFA_PL_SIG_STR, BFA_PL_SIG_LEN);
+ plog->head = plog->tail = 0;
+ plog->plog_enabled = 1;
+}
+
+void
+bfa_plog_str(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
+ enum bfa_plog_eid event,
+ u16 misc, char *log_str)
+{
+ struct bfa_plog_rec_s lp;
+
+ if (plog->plog_enabled) {
+ bfa_os_memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
+ lp.mid = mid;
+ lp.eid = event;
+ lp.log_type = BFA_PL_LOG_TYPE_STRING;
+ lp.misc = misc;
+ strncpy(lp.log_entry.string_log, log_str,
+ BFA_PL_STRING_LOG_SZ - 1);
+ lp.log_entry.string_log[BFA_PL_STRING_LOG_SZ - 1] = '\0';
+ bfa_plog_add(plog, &lp);
+ }
+}
+
+void
+bfa_plog_intarr(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
+ enum bfa_plog_eid event,
+ u16 misc, u32 *intarr, u32 num_ints)
+{
+ struct bfa_plog_rec_s lp;
+ u32 i;
+
+ if (num_ints > BFA_PL_INT_LOG_SZ)
+ num_ints = BFA_PL_INT_LOG_SZ;
+
+ if (plog->plog_enabled) {
+ bfa_os_memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
+ lp.mid = mid;
+ lp.eid = event;
+ lp.log_type = BFA_PL_LOG_TYPE_INT;
+ lp.misc = misc;
+
+ for (i = 0; i < num_ints; i++)
+ bfa_os_assign(lp.log_entry.int_log[i],
+ intarr[i]);
+
+ lp.log_num_ints = (u8) num_ints;
+
+ bfa_plog_add(plog, &lp);
+ }
+}
+
+void
+bfa_plog_fchdr(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
+ enum bfa_plog_eid event,
+ u16 misc, struct fchs_s *fchdr)
+{
+ struct bfa_plog_rec_s lp;
+ u32 *tmp_int = (u32 *) fchdr;
+ u32 ints[BFA_PL_INT_LOG_SZ];
+
+ if (plog->plog_enabled) {
+ bfa_os_memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
+
+ ints[0] = tmp_int[0];
+ ints[1] = tmp_int[1];
+ ints[2] = tmp_int[4];
+
+ bfa_plog_intarr(plog, mid, event, misc, ints, 3);
+ }
+}
+
+void
+bfa_plog_fchdr_and_pl(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
+ enum bfa_plog_eid event, u16 misc, struct fchs_s *fchdr,
+ u32 pld_w0)
+{
+ struct bfa_plog_rec_s lp;
+ u32 *tmp_int = (u32 *) fchdr;
+ u32 ints[BFA_PL_INT_LOG_SZ];
+
+ if (plog->plog_enabled) {
+ bfa_os_memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
+
+ ints[0] = tmp_int[0];
+ ints[1] = tmp_int[1];
+ ints[2] = tmp_int[4];
+ ints[3] = pld_w0;
+
+ bfa_plog_intarr(plog, mid, event, misc, ints, 4);
+ }
+}
+
+void
+bfa_plog_clear(struct bfa_plog_s *plog)
+{
+ plog->head = plog->tail = 0;
+}
+
+void
+bfa_plog_enable(struct bfa_plog_s *plog)
+{
+ plog->plog_enabled = 1;
+}
+
+void
+bfa_plog_disable(struct bfa_plog_s *plog)
+{
+ plog->plog_enabled = 0;
+}
+
+bfa_boolean_t
+bfa_plog_get_setting(struct bfa_plog_s *plog)
+{
+ return (bfa_boolean_t)plog->plog_enabled;
+}
+
+/**
+ * fcxp_pvt BFA FCXP private functions
+ */
+
+static void
+claim_fcxp_req_rsp_mem(struct bfa_fcxp_mod_s *mod, struct bfa_meminfo_s *mi)
+{
+ u8 *dm_kva = NULL;
+ u64 dm_pa;
+ u32 buf_pool_sz;
+
+ dm_kva = bfa_meminfo_dma_virt(mi);
+ dm_pa = bfa_meminfo_dma_phys(mi);
+
+ buf_pool_sz = mod->req_pld_sz * mod->num_fcxps;
+
+ /*
+ * Initialize the fcxp req payload list
+ */
+ mod->req_pld_list_kva = dm_kva;
+ mod->req_pld_list_pa = dm_pa;
+ dm_kva += buf_pool_sz;
+ dm_pa += buf_pool_sz;
+ bfa_os_memset(mod->req_pld_list_kva, 0, buf_pool_sz);
+
+ /*
+ * Initialize the fcxp rsp payload list
+ */
+ buf_pool_sz = mod->rsp_pld_sz * mod->num_fcxps;
+ mod->rsp_pld_list_kva = dm_kva;
+ mod->rsp_pld_list_pa = dm_pa;
+ dm_kva += buf_pool_sz;
+ dm_pa += buf_pool_sz;
+ bfa_os_memset(mod->rsp_pld_list_kva, 0, buf_pool_sz);
+
+ bfa_meminfo_dma_virt(mi) = dm_kva;
+ bfa_meminfo_dma_phys(mi) = dm_pa;
+}
+
+static void
+claim_fcxps_mem(struct bfa_fcxp_mod_s *mod, struct bfa_meminfo_s *mi)
+{
+ u16 i;
+ struct bfa_fcxp_s *fcxp;
+
+ fcxp = (struct bfa_fcxp_s *) bfa_meminfo_kva(mi);
+ bfa_os_memset(fcxp, 0, sizeof(struct bfa_fcxp_s) * mod->num_fcxps);
+
+ INIT_LIST_HEAD(&mod->fcxp_free_q);
+ INIT_LIST_HEAD(&mod->fcxp_active_q);
+
+ mod->fcxp_list = fcxp;
+
+ for (i = 0; i < mod->num_fcxps; i++) {
+ fcxp->fcxp_mod = mod;
+ fcxp->fcxp_tag = i;
+
+ list_add_tail(&fcxp->qe, &mod->fcxp_free_q);
+ bfa_reqq_winit(&fcxp->reqq_wqe, bfa_fcxp_qresume, fcxp);
+ fcxp->reqq_waiting = BFA_FALSE;
+
+ fcxp = fcxp + 1;
+ }
+
+ bfa_meminfo_kva(mi) = (void *)fcxp;
+}
+
+static void
+bfa_fcxp_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
+ u32 *dm_len)
+{
+ u16 num_fcxp_reqs = cfg->fwcfg.num_fcxp_reqs;
+
+ if (num_fcxp_reqs == 0)
+ return;
+
+ /*
+ * Account for req/rsp payload
+ */
+ *dm_len += BFA_FCXP_MAX_IBUF_SZ * num_fcxp_reqs;
+ if (cfg->drvcfg.min_cfg)
+ *dm_len += BFA_FCXP_MAX_IBUF_SZ * num_fcxp_reqs;
+ else
+ *dm_len += BFA_FCXP_MAX_LBUF_SZ * num_fcxp_reqs;
+
+ /*
+ * Account for fcxp structs
+ */
+ *ndm_len += sizeof(struct bfa_fcxp_s) * num_fcxp_reqs;
+}
+
+static void
+bfa_fcxp_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
+ struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
+{
+ struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
+
+ bfa_os_memset(mod, 0, sizeof(struct bfa_fcxp_mod_s));
+ mod->bfa = bfa;
+ mod->num_fcxps = cfg->fwcfg.num_fcxp_reqs;
+
+ /**
+ * Initialize FCXP request and response payload sizes.
+ */
+ mod->req_pld_sz = mod->rsp_pld_sz = BFA_FCXP_MAX_IBUF_SZ;
+ if (!cfg->drvcfg.min_cfg)
+ mod->rsp_pld_sz = BFA_FCXP_MAX_LBUF_SZ;
+
+ INIT_LIST_HEAD(&mod->wait_q);
+
+ claim_fcxp_req_rsp_mem(mod, meminfo);
+ claim_fcxps_mem(mod, meminfo);
+}
+
+static void
+bfa_fcxp_detach(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_fcxp_start(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_fcxp_stop(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_fcxp_iocdisable(struct bfa_s *bfa)
+{
+ struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
+ struct bfa_fcxp_s *fcxp;
+ struct list_head *qe, *qen;
+
+ list_for_each_safe(qe, qen, &mod->fcxp_active_q) {
+ fcxp = (struct bfa_fcxp_s *) qe;
+ if (fcxp->caller == NULL) {
+ fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
+ BFA_STATUS_IOC_FAILURE, 0, 0, NULL);
+ bfa_fcxp_free(fcxp);
+ } else {
+ fcxp->rsp_status = BFA_STATUS_IOC_FAILURE;
+ bfa_cb_queue(bfa, &fcxp->hcb_qe,
+ __bfa_fcxp_send_cbfn, fcxp);
+ }
+ }
+}
+
+static struct bfa_fcxp_s *
+bfa_fcxp_get(struct bfa_fcxp_mod_s *fm)
+{
+ struct bfa_fcxp_s *fcxp;
+
+ bfa_q_deq(&fm->fcxp_free_q, &fcxp);
+
+ if (fcxp)
+ list_add_tail(&fcxp->qe, &fm->fcxp_active_q);
+
+ return fcxp;
+}
+
+static void
+bfa_fcxp_init_reqrsp(struct bfa_fcxp_s *fcxp,
+ struct bfa_s *bfa,
+ u8 *use_ibuf,
+ u32 *nr_sgles,
+ bfa_fcxp_get_sgaddr_t *r_sga_cbfn,
+ bfa_fcxp_get_sglen_t *r_sglen_cbfn,
+ struct list_head *r_sgpg_q,
+ int n_sgles,
+ bfa_fcxp_get_sgaddr_t sga_cbfn,
+ bfa_fcxp_get_sglen_t sglen_cbfn)
+{
+
+ bfa_assert(bfa != NULL);
+
+ bfa_trc(bfa, fcxp->fcxp_tag);
+
+ if (n_sgles == 0) {
+ *use_ibuf = 1;
+ } else {
+ bfa_assert(*sga_cbfn != NULL);
+ bfa_assert(*sglen_cbfn != NULL);
+
+ *use_ibuf = 0;
+ *r_sga_cbfn = sga_cbfn;
+ *r_sglen_cbfn = sglen_cbfn;
+
+ *nr_sgles = n_sgles;
+
+ /*
+ * alloc required sgpgs
+ */
+ if (n_sgles > BFI_SGE_INLINE)
+ bfa_assert(0);
+ }
+
+}
+
+static void
+bfa_fcxp_init(struct bfa_fcxp_s *fcxp,
+ void *caller, struct bfa_s *bfa, int nreq_sgles,
+ int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,
+ bfa_fcxp_get_sglen_t req_sglen_cbfn,
+ bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,
+ bfa_fcxp_get_sglen_t rsp_sglen_cbfn)
+{
+
+ bfa_assert(bfa != NULL);
+
+ bfa_trc(bfa, fcxp->fcxp_tag);
+
+ fcxp->caller = caller;
+
+ bfa_fcxp_init_reqrsp(fcxp, bfa,
+ &fcxp->use_ireqbuf, &fcxp->nreq_sgles, &fcxp->req_sga_cbfn,
+ &fcxp->req_sglen_cbfn, &fcxp->req_sgpg_q,
+ nreq_sgles, req_sga_cbfn, req_sglen_cbfn);
+
+ bfa_fcxp_init_reqrsp(fcxp, bfa,
+ &fcxp->use_irspbuf, &fcxp->nrsp_sgles, &fcxp->rsp_sga_cbfn,
+ &fcxp->rsp_sglen_cbfn, &fcxp->rsp_sgpg_q,
+ nrsp_sgles, rsp_sga_cbfn, rsp_sglen_cbfn);
+
+}
+
+static void
+bfa_fcxp_put(struct bfa_fcxp_s *fcxp)
+{
+ struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
+ struct bfa_fcxp_wqe_s *wqe;
+
+ bfa_q_deq(&mod->wait_q, &wqe);
+ if (wqe) {
+ bfa_trc(mod->bfa, fcxp->fcxp_tag);
+
+ bfa_fcxp_init(fcxp, wqe->caller, wqe->bfa, wqe->nreq_sgles,
+ wqe->nrsp_sgles, wqe->req_sga_cbfn,
+ wqe->req_sglen_cbfn, wqe->rsp_sga_cbfn,
+ wqe->rsp_sglen_cbfn);
+
+ wqe->alloc_cbfn(wqe->alloc_cbarg, fcxp);
+ return;
+ }
+
+ bfa_assert(bfa_q_is_on_q(&mod->fcxp_active_q, fcxp));
+ list_del(&fcxp->qe);
+ list_add_tail(&fcxp->qe, &mod->fcxp_free_q);
+}
+
+static void
+bfa_fcxp_null_comp(void *bfad_fcxp, struct bfa_fcxp_s *fcxp, void *cbarg,
+ bfa_status_t req_status, u32 rsp_len,
+ u32 resid_len, struct fchs_s *rsp_fchs)
+{
+ /* discarded fcxp completion */
+}
+
+static void
+__bfa_fcxp_send_cbfn(void *cbarg, bfa_boolean_t complete)
+{
+ struct bfa_fcxp_s *fcxp = cbarg;
+
+ if (complete) {
+ fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
+ fcxp->rsp_status, fcxp->rsp_len,
+ fcxp->residue_len, &fcxp->rsp_fchs);
+ } else {
+ bfa_fcxp_free(fcxp);
+ }
+}
+
+static void
+hal_fcxp_send_comp(struct bfa_s *bfa, struct bfi_fcxp_send_rsp_s *fcxp_rsp)
+{
+ struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
+ struct bfa_fcxp_s *fcxp;
+ u16 fcxp_tag = bfa_os_ntohs(fcxp_rsp->fcxp_tag);
+
+ bfa_trc(bfa, fcxp_tag);
+
+ fcxp_rsp->rsp_len = bfa_os_ntohl(fcxp_rsp->rsp_len);
+
+ /**
+ * @todo f/w should not set residue to non-0 when everything
+ * is received.
+ */
+ if (fcxp_rsp->req_status == BFA_STATUS_OK)
+ fcxp_rsp->residue_len = 0;
+ else
+ fcxp_rsp->residue_len = bfa_os_ntohl(fcxp_rsp->residue_len);
+
+ fcxp = BFA_FCXP_FROM_TAG(mod, fcxp_tag);
+
+ bfa_assert(fcxp->send_cbfn != NULL);
+
+ hal_fcxp_rx_plog(mod->bfa, fcxp, fcxp_rsp);
+
+ if (fcxp->send_cbfn != NULL) {
+ bfa_trc(mod->bfa, (NULL == fcxp->caller));
+ if (fcxp->caller == NULL) {
+ fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
+ fcxp_rsp->req_status, fcxp_rsp->rsp_len,
+ fcxp_rsp->residue_len, &fcxp_rsp->fchs);
+ /*
+ * fcxp automatically freed on return from the callback
+ */
+ bfa_fcxp_free(fcxp);
+ } else {
+ fcxp->rsp_status = fcxp_rsp->req_status;
+ fcxp->rsp_len = fcxp_rsp->rsp_len;
+ fcxp->residue_len = fcxp_rsp->residue_len;
+ fcxp->rsp_fchs = fcxp_rsp->fchs;
+
+ bfa_cb_queue(bfa, &fcxp->hcb_qe,
+ __bfa_fcxp_send_cbfn, fcxp);
+ }
+ } else {
+ bfa_trc(bfa, (NULL == fcxp->send_cbfn));
+ }
+}
+
+static void
+hal_fcxp_set_local_sges(struct bfi_sge_s *sge, u32 reqlen, u64 req_pa)
+{
+ union bfi_addr_u sga_zero = { {0} };
+
+ sge->sg_len = reqlen;
+ sge->flags = BFI_SGE_DATA_LAST;
+ bfa_dma_addr_set(sge[0].sga, req_pa);
+ bfa_sge_to_be(sge);
+ sge++;
+
+ sge->sga = sga_zero;
+ sge->sg_len = reqlen;
+ sge->flags = BFI_SGE_PGDLEN;
+ bfa_sge_to_be(sge);
+}
+
+static void
+hal_fcxp_tx_plog(struct bfa_s *bfa, u32 reqlen, struct bfa_fcxp_s *fcxp,
+ struct fchs_s *fchs)
+{
+ /*
+ * TODO: TX ox_id
+ */
+ if (reqlen > 0) {
+ if (fcxp->use_ireqbuf) {
+ u32 pld_w0 =
+ *((u32 *) BFA_FCXP_REQ_PLD(fcxp));
+
+ bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_FCXP,
+ BFA_PL_EID_TX,
+ reqlen + sizeof(struct fchs_s), fchs,
+ pld_w0);
+ } else {
+ bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP,
+ BFA_PL_EID_TX,
+ reqlen + sizeof(struct fchs_s),
+ fchs);
+ }
+ } else {
+ bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP, BFA_PL_EID_TX,
+ reqlen + sizeof(struct fchs_s), fchs);
+ }
+}
+
+static void
+hal_fcxp_rx_plog(struct bfa_s *bfa, struct bfa_fcxp_s *fcxp,
+ struct bfi_fcxp_send_rsp_s *fcxp_rsp)
+{
+ if (fcxp_rsp->rsp_len > 0) {
+ if (fcxp->use_irspbuf) {
+ u32 pld_w0 =
+ *((u32 *) BFA_FCXP_RSP_PLD(fcxp));
+
+ bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_FCXP,
+ BFA_PL_EID_RX,
+ (u16) fcxp_rsp->rsp_len,
+ &fcxp_rsp->fchs, pld_w0);
+ } else {
+ bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP,
+ BFA_PL_EID_RX,
+ (u16) fcxp_rsp->rsp_len,
+ &fcxp_rsp->fchs);
+ }
+ } else {
+ bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP, BFA_PL_EID_RX,
+ (u16) fcxp_rsp->rsp_len, &fcxp_rsp->fchs);
+ }
+}
+
+/**
+ * Handler to resume sending fcxp when space in available in cpe queue.
+ */
+static void
+bfa_fcxp_qresume(void *cbarg)
+{
+ struct bfa_fcxp_s *fcxp = cbarg;
+ struct bfa_s *bfa = fcxp->fcxp_mod->bfa;
+ struct bfi_fcxp_send_req_s *send_req;
+
+ fcxp->reqq_waiting = BFA_FALSE;
+ send_req = bfa_reqq_next(bfa, BFA_REQQ_FCXP);
+ bfa_fcxp_queue(fcxp, send_req);
+}
+
+/**
+ * Queue fcxp send request to foimrware.
+ */
+static void
+bfa_fcxp_queue(struct bfa_fcxp_s *fcxp, struct bfi_fcxp_send_req_s *send_req)
+{
+ struct bfa_s *bfa = fcxp->fcxp_mod->bfa;
+ struct bfa_fcxp_req_info_s *reqi = &fcxp->req_info;
+ struct bfa_fcxp_rsp_info_s *rspi = &fcxp->rsp_info;
+ struct bfa_rport_s *rport = reqi->bfa_rport;
+
+ bfi_h2i_set(send_req->mh, BFI_MC_FCXP, BFI_FCXP_H2I_SEND_REQ,
+ bfa_lpuid(bfa));
+
+ send_req->fcxp_tag = bfa_os_htons(fcxp->fcxp_tag);
+ if (rport) {
+ send_req->rport_fw_hndl = rport->fw_handle;
+ send_req->max_frmsz = bfa_os_htons(rport->rport_info.max_frmsz);
+ if (send_req->max_frmsz == 0)
+ send_req->max_frmsz = bfa_os_htons(FC_MAX_PDUSZ);
+ } else {
+ send_req->rport_fw_hndl = 0;
+ send_req->max_frmsz = bfa_os_htons(FC_MAX_PDUSZ);
+ }
+
+ send_req->vf_id = bfa_os_htons(reqi->vf_id);
+ send_req->lp_tag = reqi->lp_tag;
+ send_req->class = reqi->class;
+ send_req->rsp_timeout = rspi->rsp_timeout;
+ send_req->cts = reqi->cts;
+ send_req->fchs = reqi->fchs;
+
+ send_req->req_len = bfa_os_htonl(reqi->req_tot_len);
+ send_req->rsp_maxlen = bfa_os_htonl(rspi->rsp_maxlen);
+
+ /*
+ * setup req sgles
+ */
+ if (fcxp->use_ireqbuf == 1) {
+ hal_fcxp_set_local_sges(send_req->req_sge, reqi->req_tot_len,
+ BFA_FCXP_REQ_PLD_PA(fcxp));
+ } else {
+ if (fcxp->nreq_sgles > 0) {
+ bfa_assert(fcxp->nreq_sgles == 1);
+ hal_fcxp_set_local_sges(send_req->req_sge,
+ reqi->req_tot_len,
+ fcxp->req_sga_cbfn(fcxp->caller,
+ 0));
+ } else {
+ bfa_assert(reqi->req_tot_len == 0);
+ hal_fcxp_set_local_sges(send_req->rsp_sge, 0, 0);
+ }
+ }
+
+ /*
+ * setup rsp sgles
+ */
+ if (fcxp->use_irspbuf == 1) {
+ bfa_assert(rspi->rsp_maxlen <= BFA_FCXP_MAX_LBUF_SZ);
+
+ hal_fcxp_set_local_sges(send_req->rsp_sge, rspi->rsp_maxlen,
+ BFA_FCXP_RSP_PLD_PA(fcxp));
+
+ } else {
+ if (fcxp->nrsp_sgles > 0) {
+ bfa_assert(fcxp->nrsp_sgles == 1);
+ hal_fcxp_set_local_sges(send_req->rsp_sge,
+ rspi->rsp_maxlen,
+ fcxp->rsp_sga_cbfn(fcxp->caller,
+ 0));
+ } else {
+ bfa_assert(rspi->rsp_maxlen == 0);
+ hal_fcxp_set_local_sges(send_req->rsp_sge, 0, 0);
+ }
+ }
+
+ hal_fcxp_tx_plog(bfa, reqi->req_tot_len, fcxp, &reqi->fchs);
+
+ bfa_reqq_produce(bfa, BFA_REQQ_FCXP);
+
+ bfa_trc(bfa, bfa_reqq_pi(bfa, BFA_REQQ_FCXP));
+ bfa_trc(bfa, bfa_reqq_ci(bfa, BFA_REQQ_FCXP));
+}
+
+/**
+ * hal_fcxp_api BFA FCXP API
+ */
+
+/**
+ * Allocate an FCXP instance to send a response or to send a request
+ * that has a response. Request/response buffers are allocated by caller.
+ *
+ * @param[in] bfa BFA bfa instance
+ * @param[in] nreq_sgles Number of SG elements required for request
+ * buffer. 0, if fcxp internal buffers are used.
+ * Use bfa_fcxp_get_reqbuf() to get the
+ * internal req buffer.
+ * @param[in] req_sgles SG elements describing request buffer. Will be
+ * copied in by BFA and hence can be freed on
+ * return from this function.
+ * @param[in] get_req_sga function ptr to be called to get a request SG
+ * Address (given the sge index).
+ * @param[in] get_req_sglen function ptr to be called to get a request SG
+ * len (given the sge index).
+ * @param[in] get_rsp_sga function ptr to be called to get a response SG
+ * Address (given the sge index).
+ * @param[in] get_rsp_sglen function ptr to be called to get a response SG
+ * len (given the sge index).
+ *
+ * @return FCXP instance. NULL on failure.
+ */
+struct bfa_fcxp_s *
+bfa_fcxp_alloc(void *caller, struct bfa_s *bfa, int nreq_sgles,
+ int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,
+ bfa_fcxp_get_sglen_t req_sglen_cbfn,
+ bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,
+ bfa_fcxp_get_sglen_t rsp_sglen_cbfn)
+{
+ struct bfa_fcxp_s *fcxp = NULL;
+
+ bfa_assert(bfa != NULL);
+
+ fcxp = bfa_fcxp_get(BFA_FCXP_MOD(bfa));
+ if (fcxp == NULL)
+ return NULL;
+
+ bfa_trc(bfa, fcxp->fcxp_tag);
+
+ bfa_fcxp_init(fcxp, caller, bfa, nreq_sgles, nrsp_sgles, req_sga_cbfn,
+ req_sglen_cbfn, rsp_sga_cbfn, rsp_sglen_cbfn);
+
+ return fcxp;
+}
+
+/**
+ * Get the internal request buffer pointer
+ *
+ * @param[in] fcxp BFA fcxp pointer
+ *
+ * @return pointer to the internal request buffer
+ */
+void *
+bfa_fcxp_get_reqbuf(struct bfa_fcxp_s *fcxp)
+{
+ struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
+ void *reqbuf;
+
+ bfa_assert(fcxp->use_ireqbuf == 1);
+ reqbuf = ((u8 *)mod->req_pld_list_kva) +
+ fcxp->fcxp_tag * mod->req_pld_sz;
+ return reqbuf;
+}
+
+u32
+bfa_fcxp_get_reqbufsz(struct bfa_fcxp_s *fcxp)
+{
+ struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
+
+ return mod->req_pld_sz;
+}
+
+/**
+ * Get the internal response buffer pointer
+ *
+ * @param[in] fcxp BFA fcxp pointer
+ *
+ * @return pointer to the internal request buffer
+ */
+void *
+bfa_fcxp_get_rspbuf(struct bfa_fcxp_s *fcxp)
+{
+ struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
+ void *rspbuf;
+
+ bfa_assert(fcxp->use_irspbuf == 1);
+
+ rspbuf = ((u8 *)mod->rsp_pld_list_kva) +
+ fcxp->fcxp_tag * mod->rsp_pld_sz;
+ return rspbuf;
+}
+
+/**
+ * Free the BFA FCXP
+ *
+ * @param[in] fcxp BFA fcxp pointer
+ *
+ * @return void
+ */
+void
+bfa_fcxp_free(struct bfa_fcxp_s *fcxp)
+{
+ struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
+
+ bfa_assert(fcxp != NULL);
+ bfa_trc(mod->bfa, fcxp->fcxp_tag);
+ bfa_fcxp_put(fcxp);
+}
+
+/**
+ * Send a FCXP request
+ *
+ * @param[in] fcxp BFA fcxp pointer
+ * @param[in] rport BFA rport pointer. Could be left NULL for WKA rports
+ * @param[in] vf_id virtual Fabric ID
+ * @param[in] lp_tag lport tag
+ * @param[in] cts use Continous sequence
+ * @param[in] cos fc Class of Service
+ * @param[in] reqlen request length, does not include FCHS length
+ * @param[in] fchs fc Header Pointer. The header content will be copied
+ * in by BFA.
+ *
+ * @param[in] cbfn call back function to be called on receiving
+ * the response
+ * @param[in] cbarg arg for cbfn
+ * @param[in] rsp_timeout
+ * response timeout
+ *
+ * @return bfa_status_t
+ */
+void
+bfa_fcxp_send(struct bfa_fcxp_s *fcxp, struct bfa_rport_s *rport,
+ u16 vf_id, u8 lp_tag, bfa_boolean_t cts, enum fc_cos cos,
+ u32 reqlen, struct fchs_s *fchs, bfa_cb_fcxp_send_t cbfn,
+ void *cbarg, u32 rsp_maxlen, u8 rsp_timeout)
+{
+ struct bfa_s *bfa = fcxp->fcxp_mod->bfa;
+ struct bfa_fcxp_req_info_s *reqi = &fcxp->req_info;
+ struct bfa_fcxp_rsp_info_s *rspi = &fcxp->rsp_info;
+ struct bfi_fcxp_send_req_s *send_req;
+
+ bfa_trc(bfa, fcxp->fcxp_tag);
+
+ /**
+ * setup request/response info
+ */
+ reqi->bfa_rport = rport;
+ reqi->vf_id = vf_id;
+ reqi->lp_tag = lp_tag;
+ reqi->class = cos;
+ rspi->rsp_timeout = rsp_timeout;
+ reqi->cts = cts;
+ reqi->fchs = *fchs;
+ reqi->req_tot_len = reqlen;
+ rspi->rsp_maxlen = rsp_maxlen;
+ fcxp->send_cbfn = cbfn ? cbfn : bfa_fcxp_null_comp;
+ fcxp->send_cbarg = cbarg;
+
+ /**
+ * If no room in CPE queue, wait for space in request queue
+ */
+ send_req = bfa_reqq_next(bfa, BFA_REQQ_FCXP);
+ if (!send_req) {
+ bfa_trc(bfa, fcxp->fcxp_tag);
+ fcxp->reqq_waiting = BFA_TRUE;
+ bfa_reqq_wait(bfa, BFA_REQQ_FCXP, &fcxp->reqq_wqe);
+ return;
+ }
+
+ bfa_fcxp_queue(fcxp, send_req);
+}
+
+/**
+ * Abort a BFA FCXP
+ *
+ * @param[in] fcxp BFA fcxp pointer
+ *
+ * @return void
+ */
+bfa_status_t
+bfa_fcxp_abort(struct bfa_fcxp_s *fcxp)
+{
+ bfa_trc(fcxp->fcxp_mod->bfa, fcxp->fcxp_tag);
+ bfa_assert(0);
+ return BFA_STATUS_OK;
+}
+
+void
+bfa_fcxp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe,
+ bfa_fcxp_alloc_cbfn_t alloc_cbfn, void *alloc_cbarg,
+ void *caller, int nreq_sgles,
+ int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,
+ bfa_fcxp_get_sglen_t req_sglen_cbfn,
+ bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,
+ bfa_fcxp_get_sglen_t rsp_sglen_cbfn)
+{
+ struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
+
+ bfa_assert(list_empty(&mod->fcxp_free_q));
+
+ wqe->alloc_cbfn = alloc_cbfn;
+ wqe->alloc_cbarg = alloc_cbarg;
+ wqe->caller = caller;
+ wqe->bfa = bfa;
+ wqe->nreq_sgles = nreq_sgles;
+ wqe->nrsp_sgles = nrsp_sgles;
+ wqe->req_sga_cbfn = req_sga_cbfn;
+ wqe->req_sglen_cbfn = req_sglen_cbfn;
+ wqe->rsp_sga_cbfn = rsp_sga_cbfn;
+ wqe->rsp_sglen_cbfn = rsp_sglen_cbfn;
+
+ list_add_tail(&wqe->qe, &mod->wait_q);
+}
+
+void
+bfa_fcxp_walloc_cancel(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe)
+{
+ struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
+
+ bfa_assert(bfa_q_is_on_q(&mod->wait_q, wqe));
+ list_del(&wqe->qe);
+}
+
+void
+bfa_fcxp_discard(struct bfa_fcxp_s *fcxp)
+{
+ /**
+ * If waiting for room in request queue, cancel reqq wait
+ * and free fcxp.
+ */
+ if (fcxp->reqq_waiting) {
+ fcxp->reqq_waiting = BFA_FALSE;
+ bfa_reqq_wcancel(&fcxp->reqq_wqe);
+ bfa_fcxp_free(fcxp);
+ return;
+ }
+
+ fcxp->send_cbfn = bfa_fcxp_null_comp;
+}
+
+
+
+/**
+ * hal_fcxp_public BFA FCXP public functions
+ */
+
+void
+bfa_fcxp_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
+{
+ switch (msg->mhdr.msg_id) {
+ case BFI_FCXP_I2H_SEND_RSP:
+ hal_fcxp_send_comp(bfa, (struct bfi_fcxp_send_rsp_s *) msg);
+ break;
+
+ default:
+ bfa_trc(bfa, msg->mhdr.msg_id);
+ bfa_assert(0);
+ }
+}
+
+u32
+bfa_fcxp_get_maxrsp(struct bfa_s *bfa)
+{
+ struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
+
+ return mod->rsp_pld_sz;
+}
+
+
+/**
+ * BFA LPS state machine functions
+ */
+
+/**
+ * Init state -- no login
+ */
+static void
+bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event)
+{
+ bfa_trc(lps->bfa, lps->lp_tag);
+ bfa_trc(lps->bfa, event);
+
+ switch (event) {
+ case BFA_LPS_SM_LOGIN:
+ if (bfa_reqq_full(lps->bfa, lps->reqq)) {
+ bfa_sm_set_state(lps, bfa_lps_sm_loginwait);
+ bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);
+ } else {
+ bfa_sm_set_state(lps, bfa_lps_sm_login);
+ bfa_lps_send_login(lps);
+ }
+
+ if (lps->fdisc)
+ bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
+ BFA_PL_EID_LOGIN, 0, "FDISC Request");
+ else
+ bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
+ BFA_PL_EID_LOGIN, 0, "FLOGI Request");
+ break;
+
+ case BFA_LPS_SM_LOGOUT:
+ bfa_lps_logout_comp(lps);
+ break;
+
+ case BFA_LPS_SM_DELETE:
+ bfa_lps_free(lps);
+ break;
+
+ case BFA_LPS_SM_RX_CVL:
+ case BFA_LPS_SM_OFFLINE:
+ break;
+
+ case BFA_LPS_SM_FWRSP:
+ /*
+ * Could happen when fabric detects loopback and discards
+ * the lps request. Fw will eventually sent out the timeout
+ * Just ignore
+ */
+ break;
+
+ default:
+ bfa_sm_fault(lps->bfa, event);
+ }
+}
+
+/**
+ * login is in progress -- awaiting response from firmware
+ */
+static void
+bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event)
+{
+ bfa_trc(lps->bfa, lps->lp_tag);
+ bfa_trc(lps->bfa, event);
+
+ switch (event) {
+ case BFA_LPS_SM_FWRSP:
+ if (lps->status == BFA_STATUS_OK) {
+ bfa_sm_set_state(lps, bfa_lps_sm_online);
+ if (lps->fdisc)
+ bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
+ BFA_PL_EID_LOGIN, 0, "FDISC Accept");
+ else
+ bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
+ BFA_PL_EID_LOGIN, 0, "FLOGI Accept");
+ } else {
+ bfa_sm_set_state(lps, bfa_lps_sm_init);
+ if (lps->fdisc)
+ bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
+ BFA_PL_EID_LOGIN, 0,
+ "FDISC Fail (RJT or timeout)");
+ else
+ bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
+ BFA_PL_EID_LOGIN, 0,
+ "FLOGI Fail (RJT or timeout)");
+ }
+ bfa_lps_login_comp(lps);
+ break;
+
+ case BFA_LPS_SM_OFFLINE:
+ bfa_sm_set_state(lps, bfa_lps_sm_init);
+ break;
+
+ default:
+ bfa_sm_fault(lps->bfa, event);
+ }
+}
+
+/**
+ * login pending - awaiting space in request queue
+ */
+static void
+bfa_lps_sm_loginwait(struct bfa_lps_s *lps, enum bfa_lps_event event)
+{
+ bfa_trc(lps->bfa, lps->lp_tag);
+ bfa_trc(lps->bfa, event);
+
+ switch (event) {
+ case BFA_LPS_SM_RESUME:
+ bfa_sm_set_state(lps, bfa_lps_sm_login);
+ break;
+
+ case BFA_LPS_SM_OFFLINE:
+ bfa_sm_set_state(lps, bfa_lps_sm_init);
+ bfa_reqq_wcancel(&lps->wqe);
+ break;
+
+ case BFA_LPS_SM_RX_CVL:
+ /*
+ * Login was not even sent out; so when getting out
+ * of this state, it will appear like a login retry
+ * after Clear virtual link
+ */
+ break;
+
+ default:
+ bfa_sm_fault(lps->bfa, event);
+ }
+}
+
+/**
+ * login complete
+ */
+static void
+bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event)
+{
+ bfa_trc(lps->bfa, lps->lp_tag);
+ bfa_trc(lps->bfa, event);
+
+ switch (event) {
+ case BFA_LPS_SM_LOGOUT:
+ if (bfa_reqq_full(lps->bfa, lps->reqq)) {
+ bfa_sm_set_state(lps, bfa_lps_sm_logowait);
+ bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);
+ } else {
+ bfa_sm_set_state(lps, bfa_lps_sm_logout);
+ bfa_lps_send_logout(lps);
+ }
+ bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
+ BFA_PL_EID_LOGO, 0, "Logout");
+ break;
+
+ case BFA_LPS_SM_RX_CVL:
+ bfa_sm_set_state(lps, bfa_lps_sm_init);
+
+ /* Let the vport module know about this event */
+ bfa_lps_cvl_event(lps);
+ bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
+ BFA_PL_EID_FIP_FCF_CVL, 0, "FCF Clear Virt. Link Rx");
+ break;
+
+ case BFA_LPS_SM_OFFLINE:
+ case BFA_LPS_SM_DELETE:
+ bfa_sm_set_state(lps, bfa_lps_sm_init);
+ break;
+
+ default:
+ bfa_sm_fault(lps->bfa, event);
+ }
+}
+
+/**
+ * logout in progress - awaiting firmware response
+ */
+static void
+bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event)
+{
+ bfa_trc(lps->bfa, lps->lp_tag);
+ bfa_trc(lps->bfa, event);
+
+ switch (event) {
+ case BFA_LPS_SM_FWRSP:
+ bfa_sm_set_state(lps, bfa_lps_sm_init);
+ bfa_lps_logout_comp(lps);
+ break;
+
+ case BFA_LPS_SM_OFFLINE:
+ bfa_sm_set_state(lps, bfa_lps_sm_init);
+ break;
+
+ default:
+ bfa_sm_fault(lps->bfa, event);
+ }
+}
+
+/**
+ * logout pending -- awaiting space in request queue
+ */
+static void
+bfa_lps_sm_logowait(struct bfa_lps_s *lps, enum bfa_lps_event event)
+{
+ bfa_trc(lps->bfa, lps->lp_tag);
+ bfa_trc(lps->bfa, event);
+
+ switch (event) {
+ case BFA_LPS_SM_RESUME:
+ bfa_sm_set_state(lps, bfa_lps_sm_logout);
+ bfa_lps_send_logout(lps);
+ break;
+
+ case BFA_LPS_SM_OFFLINE:
+ bfa_sm_set_state(lps, bfa_lps_sm_init);
+ bfa_reqq_wcancel(&lps->wqe);
+ break;
+
+ default:
+ bfa_sm_fault(lps->bfa, event);
+ }
+}
+
+
+
+/**
+ * lps_pvt BFA LPS private functions
+ */
+
+/**
+ * return memory requirement
+ */
+static void
+bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
+ u32 *dm_len)
+{
+ if (cfg->drvcfg.min_cfg)
+ *ndm_len += sizeof(struct bfa_lps_s) * BFA_LPS_MIN_LPORTS;
+ else
+ *ndm_len += sizeof(struct bfa_lps_s) * BFA_LPS_MAX_LPORTS;
+}
+
+/**
+ * bfa module attach at initialization time
+ */
+static void
+bfa_lps_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
+ struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
+{
+ struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa);
+ struct bfa_lps_s *lps;
+ int i;
+
+ bfa_os_memset(mod, 0, sizeof(struct bfa_lps_mod_s));
+ mod->num_lps = BFA_LPS_MAX_LPORTS;
+ if (cfg->drvcfg.min_cfg)
+ mod->num_lps = BFA_LPS_MIN_LPORTS;
+ else
+ mod->num_lps = BFA_LPS_MAX_LPORTS;
+ mod->lps_arr = lps = (struct bfa_lps_s *) bfa_meminfo_kva(meminfo);
+
+ bfa_meminfo_kva(meminfo) += mod->num_lps * sizeof(struct bfa_lps_s);
+
+ INIT_LIST_HEAD(&mod->lps_free_q);
+ INIT_LIST_HEAD(&mod->lps_active_q);
+
+ for (i = 0; i < mod->num_lps; i++, lps++) {
+ lps->bfa = bfa;
+ lps->lp_tag = (u8) i;
+ lps->reqq = BFA_REQQ_LPS;
+ bfa_reqq_winit(&lps->wqe, bfa_lps_reqq_resume, lps);
+ list_add_tail(&lps->qe, &mod->lps_free_q);
+ }
+}
+
+static void
+bfa_lps_detach(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_lps_start(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_lps_stop(struct bfa_s *bfa)
+{
+}
+
+/**
+ * IOC in disabled state -- consider all lps offline
+ */
+static void
+bfa_lps_iocdisable(struct bfa_s *bfa)
+{
+ struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa);
+ struct bfa_lps_s *lps;
+ struct list_head *qe, *qen;
+
+ list_for_each_safe(qe, qen, &mod->lps_active_q) {
+ lps = (struct bfa_lps_s *) qe;
+ bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE);
+ }
+}
+
+/**
+ * Firmware login response
+ */
+static void
+bfa_lps_login_rsp(struct bfa_s *bfa, struct bfi_lps_login_rsp_s *rsp)
+{
+ struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa);
+ struct bfa_lps_s *lps;
+
+ bfa_assert(rsp->lp_tag < mod->num_lps);
+ lps = BFA_LPS_FROM_TAG(mod, rsp->lp_tag);
+
+ lps->status = rsp->status;
+ switch (rsp->status) {
+ case BFA_STATUS_OK:
+ lps->fport = rsp->f_port;
+ lps->npiv_en = rsp->npiv_en;
+ lps->lp_pid = rsp->lp_pid;
+ lps->pr_bbcred = bfa_os_ntohs(rsp->bb_credit);
+ lps->pr_pwwn = rsp->port_name;
+ lps->pr_nwwn = rsp->node_name;
+ lps->auth_req = rsp->auth_req;
+ lps->lp_mac = rsp->lp_mac;
+ lps->brcd_switch = rsp->brcd_switch;
+ lps->fcf_mac = rsp->fcf_mac;
+
+ break;
+
+ case BFA_STATUS_FABRIC_RJT:
+ lps->lsrjt_rsn = rsp->lsrjt_rsn;
+ lps->lsrjt_expl = rsp->lsrjt_expl;
+
+ break;
+
+ case BFA_STATUS_EPROTOCOL:
+ lps->ext_status = rsp->ext_status;
+
+ break;
+
+ default:
+ /* Nothing to do with other status */
+ break;
+ }
+
+ bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
+}
+
+/**
+ * Firmware logout response
+ */
+static void
+bfa_lps_logout_rsp(struct bfa_s *bfa, struct bfi_lps_logout_rsp_s *rsp)
+{
+ struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa);
+ struct bfa_lps_s *lps;
+
+ bfa_assert(rsp->lp_tag < mod->num_lps);
+ lps = BFA_LPS_FROM_TAG(mod, rsp->lp_tag);
+
+ bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
+}
+
+/**
+ * Firmware received a Clear virtual link request (for FCoE)
+ */
+static void
+bfa_lps_rx_cvl_event(struct bfa_s *bfa, struct bfi_lps_cvl_event_s *cvl)
+{
+ struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa);
+ struct bfa_lps_s *lps;
+
+ lps = BFA_LPS_FROM_TAG(mod, cvl->lp_tag);
+
+ bfa_sm_send_event(lps, BFA_LPS_SM_RX_CVL);
+}
+
+/**
+ * Space is available in request queue, resume queueing request to firmware.
+ */
+static void
+bfa_lps_reqq_resume(void *lps_arg)
+{
+ struct bfa_lps_s *lps = lps_arg;
+
+ bfa_sm_send_event(lps, BFA_LPS_SM_RESUME);
+}
+
+/**
+ * lps is freed -- triggered by vport delete
+ */
+static void
+bfa_lps_free(struct bfa_lps_s *lps)
+{
+ struct bfa_lps_mod_s *mod = BFA_LPS_MOD(lps->bfa);
+
+ lps->lp_pid = 0;
+ list_del(&lps->qe);
+ list_add_tail(&lps->qe, &mod->lps_free_q);
+}
+
+/**
+ * send login request to firmware
+ */
+static void
+bfa_lps_send_login(struct bfa_lps_s *lps)
+{
+ struct bfi_lps_login_req_s *m;
+
+ m = bfa_reqq_next(lps->bfa, lps->reqq);
+ bfa_assert(m);
+
+ bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGIN_REQ,
+ bfa_lpuid(lps->bfa));
+
+ m->lp_tag = lps->lp_tag;
+ m->alpa = lps->alpa;
+ m->pdu_size = bfa_os_htons(lps->pdusz);
+ m->pwwn = lps->pwwn;
+ m->nwwn = lps->nwwn;
+ m->fdisc = lps->fdisc;
+ m->auth_en = lps->auth_en;
+
+ bfa_reqq_produce(lps->bfa, lps->reqq);
+}
+
+/**
+ * send logout request to firmware
+ */
+static void
+bfa_lps_send_logout(struct bfa_lps_s *lps)
+{
+ struct bfi_lps_logout_req_s *m;
+
+ m = bfa_reqq_next(lps->bfa, lps->reqq);
+ bfa_assert(m);
+
+ bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGOUT_REQ,
+ bfa_lpuid(lps->bfa));
+
+ m->lp_tag = lps->lp_tag;
+ m->port_name = lps->pwwn;
+ bfa_reqq_produce(lps->bfa, lps->reqq);
+}
+
+/**
+ * Indirect login completion handler for non-fcs
+ */
+static void
+bfa_lps_login_comp_cb(void *arg, bfa_boolean_t complete)
+{
+ struct bfa_lps_s *lps = arg;
+
+ if (!complete)
+ return;
+
+ if (lps->fdisc)
+ bfa_cb_lps_fdisc_comp(lps->bfa->bfad, lps->uarg, lps->status);
+ else
+ bfa_cb_lps_flogi_comp(lps->bfa->bfad, lps->uarg, lps->status);
+}
+
+/**
+ * Login completion handler -- direct call for fcs, queue for others
+ */
+static void
+bfa_lps_login_comp(struct bfa_lps_s *lps)
+{
+ if (!lps->bfa->fcs) {
+ bfa_cb_queue(lps->bfa, &lps->hcb_qe, bfa_lps_login_comp_cb,
+ lps);
+ return;
+ }
+
+ if (lps->fdisc)
+ bfa_cb_lps_fdisc_comp(lps->bfa->bfad, lps->uarg, lps->status);
+ else
+ bfa_cb_lps_flogi_comp(lps->bfa->bfad, lps->uarg, lps->status);
+}
+
+/**
+ * Indirect logout completion handler for non-fcs
+ */
+static void
+bfa_lps_logout_comp_cb(void *arg, bfa_boolean_t complete)
+{
+ struct bfa_lps_s *lps = arg;
+
+ if (!complete)
+ return;
+
+ if (lps->fdisc)
+ bfa_cb_lps_fdisclogo_comp(lps->bfa->bfad, lps->uarg);
+}
+
+/**
+ * Logout completion handler -- direct call for fcs, queue for others
+ */
+static void
+bfa_lps_logout_comp(struct bfa_lps_s *lps)
+{
+ if (!lps->bfa->fcs) {
+ bfa_cb_queue(lps->bfa, &lps->hcb_qe, bfa_lps_logout_comp_cb,
+ lps);
+ return;
+ }
+ if (lps->fdisc)
+ bfa_cb_lps_fdisclogo_comp(lps->bfa->bfad, lps->uarg);
+}
+
+/**
+ * Clear virtual link completion handler for non-fcs
+ */
+static void
+bfa_lps_cvl_event_cb(void *arg, bfa_boolean_t complete)
+{
+ struct bfa_lps_s *lps = arg;
+
+ if (!complete)
+ return;
+
+ /* Clear virtual link to base port will result in link down */
+ if (lps->fdisc)
+ bfa_cb_lps_cvl_event(lps->bfa->bfad, lps->uarg);
+}
+
+/**
+ * Received Clear virtual link event --direct call for fcs,
+ * queue for others
+ */
+static void
+bfa_lps_cvl_event(struct bfa_lps_s *lps)
+{
+ if (!lps->bfa->fcs) {
+ bfa_cb_queue(lps->bfa, &lps->hcb_qe, bfa_lps_cvl_event_cb,
+ lps);
+ return;
+ }
+
+ /* Clear virtual link to base port will result in link down */
+ if (lps->fdisc)
+ bfa_cb_lps_cvl_event(lps->bfa->bfad, lps->uarg);
+}
+
+
+
+/**
+ * lps_public BFA LPS public functions
+ */
+
+u32
+bfa_lps_get_max_vport(struct bfa_s *bfa)
+{
+ if (bfa_ioc_devid(&bfa->ioc) == BFA_PCI_DEVICE_ID_CT)
+ return BFA_LPS_MAX_VPORTS_SUPP_CT;
+ else
+ return BFA_LPS_MAX_VPORTS_SUPP_CB;
+}
+
+/**
+ * Allocate a lport srvice tag.
+ */
+struct bfa_lps_s *
+bfa_lps_alloc(struct bfa_s *bfa)
+{
+ struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa);
+ struct bfa_lps_s *lps = NULL;
+
+ bfa_q_deq(&mod->lps_free_q, &lps);
+
+ if (lps == NULL)
+ return NULL;
+
+ list_add_tail(&lps->qe, &mod->lps_active_q);
+
+ bfa_sm_set_state(lps, bfa_lps_sm_init);
+ return lps;
+}
+
+/**
+ * Free lport service tag. This can be called anytime after an alloc.
+ * No need to wait for any pending login/logout completions.
+ */
+void
+bfa_lps_delete(struct bfa_lps_s *lps)
+{
+ bfa_sm_send_event(lps, BFA_LPS_SM_DELETE);
+}
+
+/**
+ * Initiate a lport login.
+ */
+void
+bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa, u16 pdusz,
+ wwn_t pwwn, wwn_t nwwn, bfa_boolean_t auth_en)
+{
+ lps->uarg = uarg;
+ lps->alpa = alpa;
+ lps->pdusz = pdusz;
+ lps->pwwn = pwwn;
+ lps->nwwn = nwwn;
+ lps->fdisc = BFA_FALSE;
+ lps->auth_en = auth_en;
+ bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN);
+}
+
+/**
+ * Initiate a lport fdisc login.
+ */
+void
+bfa_lps_fdisc(struct bfa_lps_s *lps, void *uarg, u16 pdusz, wwn_t pwwn,
+ wwn_t nwwn)
+{
+ lps->uarg = uarg;
+ lps->alpa = 0;
+ lps->pdusz = pdusz;
+ lps->pwwn = pwwn;
+ lps->nwwn = nwwn;
+ lps->fdisc = BFA_TRUE;
+ lps->auth_en = BFA_FALSE;
+ bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN);
+}
+
+/**
+ * Initiate a lport logout (flogi).
+ */
+void
+bfa_lps_flogo(struct bfa_lps_s *lps)
+{
+ bfa_sm_send_event(lps, BFA_LPS_SM_LOGOUT);
+}
+
+/**
+ * Initiate a lport FDSIC logout.
+ */
+void
+bfa_lps_fdisclogo(struct bfa_lps_s *lps)
+{
+ bfa_sm_send_event(lps, BFA_LPS_SM_LOGOUT);
+}
+
+/**
+ * Discard a pending login request -- should be called only for
+ * link down handling.
+ */
+void
+bfa_lps_discard(struct bfa_lps_s *lps)
+{
+ bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE);
+}
+
+/**
+ * Return lport services tag
+ */
+u8
+bfa_lps_get_tag(struct bfa_lps_s *lps)
+{
+ return lps->lp_tag;
+}
+
+/**
+ * Return lport services tag given the pid
+ */
+u8
+bfa_lps_get_tag_from_pid(struct bfa_s *bfa, u32 pid)
+{
+ struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa);
+ struct bfa_lps_s *lps;
+ int i;
+
+ for (i = 0, lps = mod->lps_arr; i < mod->num_lps; i++, lps++) {
+ if (lps->lp_pid == pid)
+ return lps->lp_tag;
+ }
+
+ /* Return base port tag anyway */
+ return 0;
+}
+
+/**
+ * return if fabric login indicates support for NPIV
+ */
+bfa_boolean_t
+bfa_lps_is_npiv_en(struct bfa_lps_s *lps)
+{
+ return lps->npiv_en;
+}
+
+/**
+ * Return TRUE if attached to F-Port, else return FALSE
+ */
+bfa_boolean_t
+bfa_lps_is_fport(struct bfa_lps_s *lps)
+{
+ return lps->fport;
+}
+
+/**
+ * Return TRUE if attached to a Brocade Fabric
+ */
+bfa_boolean_t
+bfa_lps_is_brcd_fabric(struct bfa_lps_s *lps)
+{
+ return lps->brcd_switch;
+}
+/**
+ * return TRUE if authentication is required
+ */
+bfa_boolean_t
+bfa_lps_is_authreq(struct bfa_lps_s *lps)
+{
+ return lps->auth_req;
+}
+
+bfa_eproto_status_t
+bfa_lps_get_extstatus(struct bfa_lps_s *lps)
+{
+ return lps->ext_status;
+}
+
+/**
+ * return port id assigned to the lport
+ */
+u32
+bfa_lps_get_pid(struct bfa_lps_s *lps)
+{
+ return lps->lp_pid;
+}
+
+/**
+ * return port id assigned to the base lport
+ */
+u32
+bfa_lps_get_base_pid(struct bfa_s *bfa)
+{
+ struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa);
+
+ return BFA_LPS_FROM_TAG(mod, 0)->lp_pid;
+}
+
+/**
+ * Return bb_credit assigned in FLOGI response
+ */
+u16
+bfa_lps_get_peer_bbcredit(struct bfa_lps_s *lps)
+{
+ return lps->pr_bbcred;
+}
+
+/**
+ * Return peer port name
+ */
+wwn_t
+bfa_lps_get_peer_pwwn(struct bfa_lps_s *lps)
+{
+ return lps->pr_pwwn;
+}
+
+/**
+ * Return peer node name
+ */
+wwn_t
+bfa_lps_get_peer_nwwn(struct bfa_lps_s *lps)
+{
+ return lps->pr_nwwn;
+}
+
+/**
+ * return reason code if login request is rejected
+ */
+u8
+bfa_lps_get_lsrjt_rsn(struct bfa_lps_s *lps)
+{
+ return lps->lsrjt_rsn;
+}
+
+/**
+ * return explanation code if login request is rejected
+ */
+u8
+bfa_lps_get_lsrjt_expl(struct bfa_lps_s *lps)
+{
+ return lps->lsrjt_expl;
+}
+
+/**
+ * Return fpma/spma MAC for lport
+ */
+mac_t
+bfa_lps_get_lp_mac(struct bfa_lps_s *lps)
+{
+ return lps->lp_mac;
+}
+
+/**
+ * LPS firmware message class handler.
+ */
+void
+bfa_lps_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
+{
+ union bfi_lps_i2h_msg_u msg;
+
+ bfa_trc(bfa, m->mhdr.msg_id);
+ msg.msg = m;
+
+ switch (m->mhdr.msg_id) {
+ case BFI_LPS_H2I_LOGIN_RSP:
+ bfa_lps_login_rsp(bfa, msg.login_rsp);
+ break;
+
+ case BFI_LPS_H2I_LOGOUT_RSP:
+ bfa_lps_logout_rsp(bfa, msg.logout_rsp);
+ break;
+
+ case BFI_LPS_H2I_CVL_EVENT:
+ bfa_lps_rx_cvl_event(bfa, msg.cvl_event);
+ break;
+
+ default:
+ bfa_trc(bfa, m->mhdr.msg_id);
+ bfa_assert(0);
+ }
+}
+
+/**
+ * FC PORT state machine functions
+ */
+static void
+bfa_fcport_sm_uninit(struct bfa_fcport_s *fcport,
+ enum bfa_fcport_sm_event event)
+{
+ bfa_trc(fcport->bfa, event);
+
+ switch (event) {
+ case BFA_FCPORT_SM_START:
+ /**
+ * Start event after IOC is configured and BFA is started.
+ */
+ if (bfa_fcport_send_enable(fcport)) {
+ bfa_trc(fcport->bfa, BFA_TRUE);
+ bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
+ } else {
+ bfa_trc(fcport->bfa, BFA_FALSE);
+ bfa_sm_set_state(fcport,
+ bfa_fcport_sm_enabling_qwait);
+ }
+ break;
+
+ case BFA_FCPORT_SM_ENABLE:
+ /**
+ * Port is persistently configured to be in enabled state. Do
+ * not change state. Port enabling is done when START event is
+ * received.
+ */
+ break;
+
+ case BFA_FCPORT_SM_DISABLE:
+ /**
+ * If a port is persistently configured to be disabled, the
+ * first event will a port disable request.
+ */
+ bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
+ break;
+
+ case BFA_FCPORT_SM_HWFAIL:
+ bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
+ break;
+
+ default:
+ bfa_sm_fault(fcport->bfa, event);
+ }
+}
+
+static void
+bfa_fcport_sm_enabling_qwait(struct bfa_fcport_s *fcport,
+ enum bfa_fcport_sm_event event)
+{
+ char pwwn_buf[BFA_STRING_32];
+ struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
+ bfa_trc(fcport->bfa, event);
+
+ switch (event) {
+ case BFA_FCPORT_SM_QRESUME:
+ bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
+ bfa_fcport_send_enable(fcport);
+ break;
+
+ case BFA_FCPORT_SM_STOP:
+ bfa_reqq_wcancel(&fcport->reqq_wait);
+ bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
+ break;
+
+ case BFA_FCPORT_SM_ENABLE:
+ /**
+ * Already enable is in progress.
+ */
+ break;
+
+ case BFA_FCPORT_SM_DISABLE:
+ /**
+ * Just send disable request to firmware when room becomes
+ * available in request queue.
+ */
+ bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
+ bfa_reqq_wcancel(&fcport->reqq_wait);
+ bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
+ BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
+ wwn2str(pwwn_buf, fcport->pwwn);
+ BFA_LOG(KERN_INFO, bfad, log_level,
+ "Base port disabled: WWN = %s\n", pwwn_buf);
+ break;
+
+ case BFA_FCPORT_SM_LINKUP:
+ case BFA_FCPORT_SM_LINKDOWN:
+ /**
+ * Possible to get link events when doing back-to-back
+ * enable/disables.
+ */
+ break;
+
+ case BFA_FCPORT_SM_HWFAIL:
+ bfa_reqq_wcancel(&fcport->reqq_wait);
+ bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
+ break;
+
+ default:
+ bfa_sm_fault(fcport->bfa, event);
+ }
+}
+
+static void
+bfa_fcport_sm_enabling(struct bfa_fcport_s *fcport,
+ enum bfa_fcport_sm_event event)
+{
+ char pwwn_buf[BFA_STRING_32];
+ struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
+ bfa_trc(fcport->bfa, event);
+
+ switch (event) {
+ case BFA_FCPORT_SM_FWRSP:
+ case BFA_FCPORT_SM_LINKDOWN:
+ bfa_sm_set_state(fcport, bfa_fcport_sm_linkdown);
+ break;
+
+ case BFA_FCPORT_SM_LINKUP:
+ bfa_fcport_update_linkinfo(fcport);
+ bfa_sm_set_state(fcport, bfa_fcport_sm_linkup);
+
+ bfa_assert(fcport->event_cbfn);
+ bfa_fcport_scn(fcport, BFA_PORT_LINKUP, BFA_FALSE);
+ break;
+
+ case BFA_FCPORT_SM_ENABLE:
+ /**
+ * Already being enabled.
+ */
+ break;
+
+ case BFA_FCPORT_SM_DISABLE:
+ if (bfa_fcport_send_disable(fcport))
+ bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
+ else
+ bfa_sm_set_state(fcport,
+ bfa_fcport_sm_disabling_qwait);
+
+ bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
+ BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
+ wwn2str(pwwn_buf, fcport->pwwn);
+ BFA_LOG(KERN_INFO, bfad, log_level,
+ "Base port disabled: WWN = %s\n", pwwn_buf);
+ break;
+
+ case BFA_FCPORT_SM_STOP:
+ bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
+ break;
+
+ case BFA_FCPORT_SM_HWFAIL:
+ bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
+ break;
+
+ default:
+ bfa_sm_fault(fcport->bfa, event);
+ }
+}
+
+static void
+bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport,
+ enum bfa_fcport_sm_event event)
+{
+ struct bfi_fcport_event_s *pevent = fcport->event_arg.i2hmsg.event;
+ char pwwn_buf[BFA_STRING_32];
+ struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
+
+ bfa_trc(fcport->bfa, event);
+
+ switch (event) {
+ case BFA_FCPORT_SM_LINKUP:
+ bfa_fcport_update_linkinfo(fcport);
+ bfa_sm_set_state(fcport, bfa_fcport_sm_linkup);
+ bfa_assert(fcport->event_cbfn);
+ bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
+ BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkup");
+ if (!bfa_ioc_get_fcmode(&fcport->bfa->ioc)) {
+
+ bfa_trc(fcport->bfa,
+ pevent->link_state.vc_fcf.fcf.fipenabled);
+ bfa_trc(fcport->bfa,
+ pevent->link_state.vc_fcf.fcf.fipfailed);
+
+ if (pevent->link_state.vc_fcf.fcf.fipfailed)
+ bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
+ BFA_PL_EID_FIP_FCF_DISC, 0,
+ "FIP FCF Discovery Failed");
+ else
+ bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
+ BFA_PL_EID_FIP_FCF_DISC, 0,
+ "FIP FCF Discovered");
+ }
+
+ bfa_fcport_scn(fcport, BFA_PORT_LINKUP, BFA_FALSE);
+ wwn2str(pwwn_buf, fcport->pwwn);
+ BFA_LOG(KERN_INFO, bfad, log_level,
+ "Base port online: WWN = %s\n", pwwn_buf);
+ break;
+
+ case BFA_FCPORT_SM_LINKDOWN:
+ /**
+ * Possible to get link down event.
+ */
+ break;
+
+ case BFA_FCPORT_SM_ENABLE:
+ /**
+ * Already enabled.
+ */
+ break;
+
+ case BFA_FCPORT_SM_DISABLE:
+ if (bfa_fcport_send_disable(fcport))
+ bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
+ else
+ bfa_sm_set_state(fcport,
+ bfa_fcport_sm_disabling_qwait);
+
+ bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
+ BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
+ wwn2str(pwwn_buf, fcport->pwwn);
+ BFA_LOG(KERN_INFO, bfad, log_level,
+ "Base port disabled: WWN = %s\n", pwwn_buf);
+ break;
+
+ case BFA_FCPORT_SM_STOP:
+ bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
+ break;
+
+ case BFA_FCPORT_SM_HWFAIL:
+ bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
+ break;
+
+ default:
+ bfa_sm_fault(fcport->bfa, event);
+ }
+}
+
+static void
+bfa_fcport_sm_linkup(struct bfa_fcport_s *fcport,
+ enum bfa_fcport_sm_event event)
+{
+ char pwwn_buf[BFA_STRING_32];
+ struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
+
+ bfa_trc(fcport->bfa, event);
+
+ switch (event) {
+ case BFA_FCPORT_SM_ENABLE:
+ /**
+ * Already enabled.
+ */
+ break;
+
+ case BFA_FCPORT_SM_DISABLE:
+ if (bfa_fcport_send_disable(fcport))
+ bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
+ else
+ bfa_sm_set_state(fcport,
+ bfa_fcport_sm_disabling_qwait);
+
+ bfa_fcport_reset_linkinfo(fcport);
+ bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
+ bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
+ BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
+ wwn2str(pwwn_buf, fcport->pwwn);
+ BFA_LOG(KERN_INFO, bfad, log_level,
+ "Base port offline: WWN = %s\n", pwwn_buf);
+ BFA_LOG(KERN_INFO, bfad, log_level,
+ "Base port disabled: WWN = %s\n", pwwn_buf);
+ break;
+
+ case BFA_FCPORT_SM_LINKDOWN:
+ bfa_sm_set_state(fcport, bfa_fcport_sm_linkdown);
+ bfa_fcport_reset_linkinfo(fcport);
+ bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
+ bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
+ BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkdown");
+ wwn2str(pwwn_buf, fcport->pwwn);
+ if (BFA_PORT_IS_DISABLED(fcport->bfa))
+ BFA_LOG(KERN_INFO, bfad, log_level,
+ "Base port offline: WWN = %s\n", pwwn_buf);
+ else
+ BFA_LOG(KERN_ERR, bfad, log_level,
+ "Base port (WWN = %s) "
+ "lost fabric connectivity\n", pwwn_buf);
+ break;
+
+ case BFA_FCPORT_SM_STOP:
+ bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
+ bfa_fcport_reset_linkinfo(fcport);
+ wwn2str(pwwn_buf, fcport->pwwn);
+ if (BFA_PORT_IS_DISABLED(fcport->bfa))
+ BFA_LOG(KERN_INFO, bfad, log_level,
+ "Base port offline: WWN = %s\n", pwwn_buf);
+ else
+ BFA_LOG(KERN_ERR, bfad, log_level,
+ "Base port (WWN = %s) "
+ "lost fabric connectivity\n", pwwn_buf);
+ break;
+
+ case BFA_FCPORT_SM_HWFAIL:
+ bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
+ bfa_fcport_reset_linkinfo(fcport);
+ bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
+ wwn2str(pwwn_buf, fcport->pwwn);
+ if (BFA_PORT_IS_DISABLED(fcport->bfa))
+ BFA_LOG(KERN_INFO, bfad, log_level,
+ "Base port offline: WWN = %s\n", pwwn_buf);
+ else
+ BFA_LOG(KERN_ERR, bfad, log_level,
+ "Base port (WWN = %s) "
+ "lost fabric connectivity\n", pwwn_buf);
+ break;
+
+ default:
+ bfa_sm_fault(fcport->bfa, event);
+ }
+}
+
+static void
+bfa_fcport_sm_disabling_qwait(struct bfa_fcport_s *fcport,
+ enum bfa_fcport_sm_event event)
+{
+ bfa_trc(fcport->bfa, event);
+
+ switch (event) {
+ case BFA_FCPORT_SM_QRESUME:
+ bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
+ bfa_fcport_send_disable(fcport);
+ break;
+
+ case BFA_FCPORT_SM_STOP:
+ bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
+ bfa_reqq_wcancel(&fcport->reqq_wait);
+ break;
+
+ case BFA_FCPORT_SM_ENABLE:
+ bfa_sm_set_state(fcport, bfa_fcport_sm_toggling_qwait);
+ break;
+
+ case BFA_FCPORT_SM_DISABLE:
+ /**
+ * Already being disabled.
+ */
+ break;
+
+ case BFA_FCPORT_SM_LINKUP:
+ case BFA_FCPORT_SM_LINKDOWN:
+ /**
+ * Possible to get link events when doing back-to-back
+ * enable/disables.
+ */
+ break;
+
+ case BFA_FCPORT_SM_HWFAIL:
+ bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
+ bfa_reqq_wcancel(&fcport->reqq_wait);
+ break;
+
+ default:
+ bfa_sm_fault(fcport->bfa, event);
+ }
+}
+
+static void
+bfa_fcport_sm_toggling_qwait(struct bfa_fcport_s *fcport,
+ enum bfa_fcport_sm_event event)
+{
+ bfa_trc(fcport->bfa, event);
+
+ switch (event) {
+ case BFA_FCPORT_SM_QRESUME:
+ bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
+ bfa_fcport_send_disable(fcport);
+ if (bfa_fcport_send_enable(fcport))
+ bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
+ else
+ bfa_sm_set_state(fcport,
+ bfa_fcport_sm_enabling_qwait);
+ break;
+
+ case BFA_FCPORT_SM_STOP:
+ bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
+ bfa_reqq_wcancel(&fcport->reqq_wait);
+ break;
+
+ case BFA_FCPORT_SM_ENABLE:
+ break;
+
+ case BFA_FCPORT_SM_DISABLE:
+ bfa_sm_set_state(fcport, bfa_fcport_sm_disabling_qwait);
+ break;
+
+ case BFA_FCPORT_SM_LINKUP:
+ case BFA_FCPORT_SM_LINKDOWN:
+ /**
+ * Possible to get link events when doing back-to-back
+ * enable/disables.
+ */
+ break;
+
+ case BFA_FCPORT_SM_HWFAIL:
+ bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
+ bfa_reqq_wcancel(&fcport->reqq_wait);
+ break;
+
+ default:
+ bfa_sm_fault(fcport->bfa, event);
+ }
+}
+
+static void
+bfa_fcport_sm_disabling(struct bfa_fcport_s *fcport,
+ enum bfa_fcport_sm_event event)
+{
+ char pwwn_buf[BFA_STRING_32];
+ struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
+ bfa_trc(fcport->bfa, event);
+
+ switch (event) {
+ case BFA_FCPORT_SM_FWRSP:
+ bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
+ break;
+
+ case BFA_FCPORT_SM_DISABLE:
+ /**
+ * Already being disabled.
+ */
+ break;
+
+ case BFA_FCPORT_SM_ENABLE:
+ if (bfa_fcport_send_enable(fcport))
+ bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
+ else
+ bfa_sm_set_state(fcport,
+ bfa_fcport_sm_enabling_qwait);
+
+ bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
+ BFA_PL_EID_PORT_ENABLE, 0, "Port Enable");
+ wwn2str(pwwn_buf, fcport->pwwn);
+ BFA_LOG(KERN_INFO, bfad, log_level,
+ "Base port enabled: WWN = %s\n", pwwn_buf);
+ break;
+
+ case BFA_FCPORT_SM_STOP:
+ bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
+ break;
+
+ case BFA_FCPORT_SM_LINKUP:
+ case BFA_FCPORT_SM_LINKDOWN:
+ /**
+ * Possible to get link events when doing back-to-back
+ * enable/disables.
+ */
+ break;
+
+ case BFA_FCPORT_SM_HWFAIL:
+ bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
+ break;
+
+ default:
+ bfa_sm_fault(fcport->bfa, event);
+ }
+}
+
+static void
+bfa_fcport_sm_disabled(struct bfa_fcport_s *fcport,
+ enum bfa_fcport_sm_event event)
+{
+ char pwwn_buf[BFA_STRING_32];
+ struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
+ bfa_trc(fcport->bfa, event);
+
+ switch (event) {
+ case BFA_FCPORT_SM_START:
+ /**
+ * Ignore start event for a port that is disabled.
+ */
+ break;
+
+ case BFA_FCPORT_SM_STOP:
+ bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
+ break;
+
+ case BFA_FCPORT_SM_ENABLE:
+ if (bfa_fcport_send_enable(fcport))
+ bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
+ else
+ bfa_sm_set_state(fcport,
+ bfa_fcport_sm_enabling_qwait);
+
+ bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
+ BFA_PL_EID_PORT_ENABLE, 0, "Port Enable");
+ wwn2str(pwwn_buf, fcport->pwwn);
+ BFA_LOG(KERN_INFO, bfad, log_level,
+ "Base port enabled: WWN = %s\n", pwwn_buf);
+ break;
+
+ case BFA_FCPORT_SM_DISABLE:
+ /**
+ * Already disabled.
+ */
+ break;
+
+ case BFA_FCPORT_SM_HWFAIL:
+ bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
+ break;
+
+ default:
+ bfa_sm_fault(fcport->bfa, event);
+ }
+}
+
+static void
+bfa_fcport_sm_stopped(struct bfa_fcport_s *fcport,
+ enum bfa_fcport_sm_event event)
+{
+ bfa_trc(fcport->bfa, event);
+
+ switch (event) {
+ case BFA_FCPORT_SM_START:
+ if (bfa_fcport_send_enable(fcport))
+ bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
+ else
+ bfa_sm_set_state(fcport,
+ bfa_fcport_sm_enabling_qwait);
+ break;
+
+ default:
+ /**
+ * Ignore all other events.
+ */
+ ;
+ }
+}
+
+/**
+ * Port is enabled. IOC is down/failed.
+ */
+static void
+bfa_fcport_sm_iocdown(struct bfa_fcport_s *fcport,
+ enum bfa_fcport_sm_event event)
+{
+ bfa_trc(fcport->bfa, event);
+
+ switch (event) {
+ case BFA_FCPORT_SM_START:
+ if (bfa_fcport_send_enable(fcport))
+ bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
+ else
+ bfa_sm_set_state(fcport,
+ bfa_fcport_sm_enabling_qwait);
+ break;
+
+ default:
+ /**
+ * Ignore all events.
+ */
+ ;
+ }
+}
+
+/**
+ * Port is disabled. IOC is down/failed.
+ */
+static void
+bfa_fcport_sm_iocfail(struct bfa_fcport_s *fcport,
+ enum bfa_fcport_sm_event event)
+{
+ bfa_trc(fcport->bfa, event);
+
+ switch (event) {
+ case BFA_FCPORT_SM_START:
+ bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
+ break;
+
+ case BFA_FCPORT_SM_ENABLE:
+ bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
+ break;
+
+ default:
+ /**
+ * Ignore all events.
+ */
+ ;
+ }
+}
+
+/**
+ * Link state is down
+ */
+static void
+bfa_fcport_ln_sm_dn(struct bfa_fcport_ln_s *ln,
+ enum bfa_fcport_ln_sm_event event)
+{
+ bfa_trc(ln->fcport->bfa, event);
+
+ switch (event) {
+ case BFA_FCPORT_LN_SM_LINKUP:
+ bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_nf);
+ bfa_fcport_queue_cb(ln, BFA_PORT_LINKUP);
+ break;
+
+ default:
+ bfa_sm_fault(ln->fcport->bfa, event);
+ }
+}
+
+/**
+ * Link state is waiting for down notification
+ */
+static void
+bfa_fcport_ln_sm_dn_nf(struct bfa_fcport_ln_s *ln,
+ enum bfa_fcport_ln_sm_event event)
+{
+ bfa_trc(ln->fcport->bfa, event);
+
+ switch (event) {
+ case BFA_FCPORT_LN_SM_LINKUP:
+ bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_up_nf);
+ break;
+
+ case BFA_FCPORT_LN_SM_NOTIFICATION:
+ bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn);
+ break;
+
+ default:
+ bfa_sm_fault(ln->fcport->bfa, event);
+ }
+}
+
+/**
+ * Link state is waiting for down notification and there is a pending up
+ */
+static void
+bfa_fcport_ln_sm_dn_up_nf(struct bfa_fcport_ln_s *ln,
+ enum bfa_fcport_ln_sm_event event)
+{
+ bfa_trc(ln->fcport->bfa, event);
+
+ switch (event) {
+ case BFA_FCPORT_LN_SM_LINKDOWN:
+ bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_nf);
+ break;
+
+ case BFA_FCPORT_LN_SM_NOTIFICATION:
+ bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_nf);
+ bfa_fcport_queue_cb(ln, BFA_PORT_LINKUP);
+ break;
+
+ default:
+ bfa_sm_fault(ln->fcport->bfa, event);
+ }
+}
+
+/**
+ * Link state is up
+ */
+static void
+bfa_fcport_ln_sm_up(struct bfa_fcport_ln_s *ln,
+ enum bfa_fcport_ln_sm_event event)
+{
+ bfa_trc(ln->fcport->bfa, event);
+
+ switch (event) {
+ case BFA_FCPORT_LN_SM_LINKDOWN:
+ bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_nf);
+ bfa_fcport_queue_cb(ln, BFA_PORT_LINKDOWN);
+ break;
+
+ default:
+ bfa_sm_fault(ln->fcport->bfa, event);
+ }
+}
+
+/**
+ * Link state is waiting for up notification
+ */
+static void
+bfa_fcport_ln_sm_up_nf(struct bfa_fcport_ln_s *ln,
+ enum bfa_fcport_ln_sm_event event)
+{
+ bfa_trc(ln->fcport->bfa, event);
+
+ switch (event) {
+ case BFA_FCPORT_LN_SM_LINKDOWN:
+ bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_dn_nf);
+ break;
+
+ case BFA_FCPORT_LN_SM_NOTIFICATION:
+ bfa_sm_set_state(ln, bfa_fcport_ln_sm_up);
+ break;
+
+ default:
+ bfa_sm_fault(ln->fcport->bfa, event);
+ }
+}
+
+/**
+ * Link state is waiting for up notification and there is a pending down
+ */
+static void
+bfa_fcport_ln_sm_up_dn_nf(struct bfa_fcport_ln_s *ln,
+ enum bfa_fcport_ln_sm_event event)
+{
+ bfa_trc(ln->fcport->bfa, event);
+
+ switch (event) {
+ case BFA_FCPORT_LN_SM_LINKUP:
+ bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_dn_up_nf);
+ break;
+
+ case BFA_FCPORT_LN_SM_NOTIFICATION:
+ bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_nf);
+ bfa_fcport_queue_cb(ln, BFA_PORT_LINKDOWN);
+ break;
+
+ default:
+ bfa_sm_fault(ln->fcport->bfa, event);
+ }
+}
+
+/**
+ * Link state is waiting for up notification and there are pending down and up
+ */
+static void
+bfa_fcport_ln_sm_up_dn_up_nf(struct bfa_fcport_ln_s *ln,
+ enum bfa_fcport_ln_sm_event event)
+{
+ bfa_trc(ln->fcport->bfa, event);
+
+ switch (event) {
+ case BFA_FCPORT_LN_SM_LINKDOWN:
+ bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_dn_nf);
+ break;
+
+ case BFA_FCPORT_LN_SM_NOTIFICATION:
+ bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_up_nf);
+ bfa_fcport_queue_cb(ln, BFA_PORT_LINKDOWN);
+ break;
+
+ default:
+ bfa_sm_fault(ln->fcport->bfa, event);
+ }
+}
+
+
+
+/**
+ * hal_port_private
+ */
+
+static void
+__bfa_cb_fcport_event(void *cbarg, bfa_boolean_t complete)
+{
+ struct bfa_fcport_ln_s *ln = cbarg;
+
+ if (complete)
+ ln->fcport->event_cbfn(ln->fcport->event_cbarg, ln->ln_event);
+ else
+ bfa_sm_send_event(ln, BFA_FCPORT_LN_SM_NOTIFICATION);
+}
+
+/**
+ * Send SCN notification to upper layers.
+ * trunk - false if caller is fcport to ignore fcport event in trunked mode
+ */
+static void
+bfa_fcport_scn(struct bfa_fcport_s *fcport, enum bfa_port_linkstate event,
+ bfa_boolean_t trunk)
+{
+ if (fcport->cfg.trunked && !trunk)
+ return;
+
+ switch (event) {
+ case BFA_PORT_LINKUP:
+ bfa_sm_send_event(&fcport->ln, BFA_FCPORT_LN_SM_LINKUP);
+ break;
+ case BFA_PORT_LINKDOWN:
+ bfa_sm_send_event(&fcport->ln, BFA_FCPORT_LN_SM_LINKDOWN);
+ break;
+ default:
+ bfa_assert(0);
+ }
+}
+
+static void
+bfa_fcport_queue_cb(struct bfa_fcport_ln_s *ln, enum bfa_port_linkstate event)
+{
+ struct bfa_fcport_s *fcport = ln->fcport;
+
+ if (fcport->bfa->fcs) {
+ fcport->event_cbfn(fcport->event_cbarg, event);
+ bfa_sm_send_event(ln, BFA_FCPORT_LN_SM_NOTIFICATION);
+ } else {
+ ln->ln_event = event;
+ bfa_cb_queue(fcport->bfa, &ln->ln_qe,
+ __bfa_cb_fcport_event, ln);
+ }
+}
+
+#define FCPORT_STATS_DMA_SZ (BFA_ROUNDUP(sizeof(union bfa_fcport_stats_u), \
+ BFA_CACHELINE_SZ))
+
+static void
+bfa_fcport_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
+ u32 *dm_len)
+{
+ *dm_len += FCPORT_STATS_DMA_SZ;
+}
+
+static void
+bfa_fcport_qresume(void *cbarg)
+{
+ struct bfa_fcport_s *fcport = cbarg;
+
+ bfa_sm_send_event(fcport, BFA_FCPORT_SM_QRESUME);
+}
+
+static void
+bfa_fcport_mem_claim(struct bfa_fcport_s *fcport, struct bfa_meminfo_s *meminfo)
+{
+ u8 *dm_kva;
+ u64 dm_pa;
+
+ dm_kva = bfa_meminfo_dma_virt(meminfo);
+ dm_pa = bfa_meminfo_dma_phys(meminfo);
+
+ fcport->stats_kva = dm_kva;
+ fcport->stats_pa = dm_pa;
+ fcport->stats = (union bfa_fcport_stats_u *) dm_kva;
+
+ dm_kva += FCPORT_STATS_DMA_SZ;
+ dm_pa += FCPORT_STATS_DMA_SZ;
+
+ bfa_meminfo_dma_virt(meminfo) = dm_kva;
+ bfa_meminfo_dma_phys(meminfo) = dm_pa;
+}
+
+/**
+ * Memory initialization.
+ */
+static void
+bfa_fcport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
+ struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+ struct bfa_port_cfg_s *port_cfg = &fcport->cfg;
+ struct bfa_fcport_ln_s *ln = &fcport->ln;
+ struct bfa_timeval_s tv;
+
+ bfa_os_memset(fcport, 0, sizeof(struct bfa_fcport_s));
+ fcport->bfa = bfa;
+ ln->fcport = fcport;
+
+ bfa_fcport_mem_claim(fcport, meminfo);
+
+ bfa_sm_set_state(fcport, bfa_fcport_sm_uninit);
+ bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn);
+
+ /**
+ * initialize time stamp for stats reset
+ */
+ bfa_os_gettimeofday(&tv);
+ fcport->stats_reset_time = tv.tv_sec;
+
+ /**
+ * initialize and set default configuration
+ */
+ port_cfg->topology = BFA_PORT_TOPOLOGY_P2P;
+ port_cfg->speed = BFA_PORT_SPEED_AUTO;
+ port_cfg->trunked = BFA_FALSE;
+ port_cfg->maxfrsize = 0;
+
+ port_cfg->trl_def_speed = BFA_PORT_SPEED_1GBPS;
+
+ bfa_reqq_winit(&fcport->reqq_wait, bfa_fcport_qresume, fcport);
+}
+
+static void
+bfa_fcport_detach(struct bfa_s *bfa)
+{
+}
+
+/**
+ * Called when IOC is ready.
+ */
+static void
+bfa_fcport_start(struct bfa_s *bfa)
+{
+ bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_START);
+}
+
+/**
+ * Called before IOC is stopped.
+ */
+static void
+bfa_fcport_stop(struct bfa_s *bfa)
+{
+ bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_STOP);
+ bfa_trunk_iocdisable(bfa);
+}
+
+/**
+ * Called when IOC failure is detected.
+ */
+static void
+bfa_fcport_iocdisable(struct bfa_s *bfa)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+ bfa_sm_send_event(fcport, BFA_FCPORT_SM_HWFAIL);
+ bfa_trunk_iocdisable(bfa);
+}
+
+static void
+bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport)
+{
+ struct bfi_fcport_event_s *pevent = fcport->event_arg.i2hmsg.event;
+ struct bfa_fcport_trunk_s *trunk = &fcport->trunk;
+
+ fcport->speed = pevent->link_state.speed;
+ fcport->topology = pevent->link_state.topology;
+
+ if (fcport->topology == BFA_PORT_TOPOLOGY_LOOP)
+ fcport->myalpa = 0;
+
+ /* QoS Details */
+ bfa_os_assign(fcport->qos_attr, pevent->link_state.qos_attr);
+ bfa_os_assign(fcport->qos_vc_attr,
+ pevent->link_state.vc_fcf.qos_vc_attr);
+
+ /**
+ * update trunk state if applicable
+ */
+ if (!fcport->cfg.trunked)
+ trunk->attr.state = BFA_TRUNK_DISABLED;
+
+ /* update FCoE specific */
+ fcport->fcoe_vlan = bfa_os_ntohs(pevent->link_state.vc_fcf.fcf.vlan);
+
+ bfa_trc(fcport->bfa, fcport->speed);
+ bfa_trc(fcport->bfa, fcport->topology);
+}
+
+static void
+bfa_fcport_reset_linkinfo(struct bfa_fcport_s *fcport)
+{
+ fcport->speed = BFA_PORT_SPEED_UNKNOWN;
+ fcport->topology = BFA_PORT_TOPOLOGY_NONE;
+}
+
+/**
+ * Send port enable message to firmware.
+ */
+static bfa_boolean_t
+bfa_fcport_send_enable(struct bfa_fcport_s *fcport)
+{
+ struct bfi_fcport_enable_req_s *m;
+
+ /**
+ * Increment message tag before queue check, so that responses to old
+ * requests are discarded.
+ */
+ fcport->msgtag++;
+
+ /**
+ * check for room in queue to send request now
+ */
+ m = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
+ if (!m) {
+ bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
+ &fcport->reqq_wait);
+ return BFA_FALSE;
+ }
+
+ bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_ENABLE_REQ,
+ bfa_lpuid(fcport->bfa));
+ m->nwwn = fcport->nwwn;
+ m->pwwn = fcport->pwwn;
+ m->port_cfg = fcport->cfg;
+ m->msgtag = fcport->msgtag;
+ m->port_cfg.maxfrsize = bfa_os_htons(fcport->cfg.maxfrsize);
+ bfa_dma_be_addr_set(m->stats_dma_addr, fcport->stats_pa);
+ bfa_trc(fcport->bfa, m->stats_dma_addr.a32.addr_lo);
+ bfa_trc(fcport->bfa, m->stats_dma_addr.a32.addr_hi);
+
+ /**
+ * queue I/O message to firmware
+ */
+ bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT);
+ return BFA_TRUE;
+}
+
+/**
+ * Send port disable message to firmware.
+ */
+static bfa_boolean_t
+bfa_fcport_send_disable(struct bfa_fcport_s *fcport)
+{
+ struct bfi_fcport_req_s *m;
+
+ /**
+ * Increment message tag before queue check, so that responses to old
+ * requests are discarded.
+ */
+ fcport->msgtag++;
+
+ /**
+ * check for room in queue to send request now
+ */
+ m = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
+ if (!m) {
+ bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
+ &fcport->reqq_wait);
+ return BFA_FALSE;
+ }
+
+ bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_DISABLE_REQ,
+ bfa_lpuid(fcport->bfa));
+ m->msgtag = fcport->msgtag;
+
+ /**
+ * queue I/O message to firmware
+ */
+ bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT);
+
+ return BFA_TRUE;
+}
+
+static void
+bfa_fcport_set_wwns(struct bfa_fcport_s *fcport)
+{
+ fcport->pwwn = bfa_ioc_get_pwwn(&fcport->bfa->ioc);
+ fcport->nwwn = bfa_ioc_get_nwwn(&fcport->bfa->ioc);
+
+ bfa_trc(fcport->bfa, fcport->pwwn);
+ bfa_trc(fcport->bfa, fcport->nwwn);
+}
+
+static void
+bfa_fcport_send_txcredit(void *port_cbarg)
+{
+
+ struct bfa_fcport_s *fcport = port_cbarg;
+ struct bfi_fcport_set_svc_params_req_s *m;
+
+ /**
+ * check for room in queue to send request now
+ */
+ m = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
+ if (!m) {
+ bfa_trc(fcport->bfa, fcport->cfg.tx_bbcredit);
+ return;
+ }
+
+ bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_SET_SVC_PARAMS_REQ,
+ bfa_lpuid(fcport->bfa));
+ m->tx_bbcredit = bfa_os_htons((u16)fcport->cfg.tx_bbcredit);
+
+ /**
+ * queue I/O message to firmware
+ */
+ bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT);
+}
+
+static void
+bfa_fcport_qos_stats_swap(struct bfa_qos_stats_s *d,
+ struct bfa_qos_stats_s *s)
+{
+ u32 *dip = (u32 *) d;
+ u32 *sip = (u32 *) s;
+ int i;
+
+ /* Now swap the 32 bit fields */
+ for (i = 0; i < (sizeof(struct bfa_qos_stats_s)/sizeof(u32)); ++i)
+ dip[i] = bfa_os_ntohl(sip[i]);
+}
+
+static void
+bfa_fcport_fcoe_stats_swap(struct bfa_fcoe_stats_s *d,
+ struct bfa_fcoe_stats_s *s)
+{
+ u32 *dip = (u32 *) d;
+ u32 *sip = (u32 *) s;
+ int i;
+
+ for (i = 0; i < ((sizeof(struct bfa_fcoe_stats_s))/sizeof(u32));
+ i = i + 2) {
+#ifdef __BIGENDIAN
+ dip[i] = bfa_os_ntohl(sip[i]);
+ dip[i + 1] = bfa_os_ntohl(sip[i + 1]);
+#else
+ dip[i] = bfa_os_ntohl(sip[i + 1]);
+ dip[i + 1] = bfa_os_ntohl(sip[i]);
+#endif
+ }
+}
+
+static void
+__bfa_cb_fcport_stats_get(void *cbarg, bfa_boolean_t complete)
+{
+ struct bfa_fcport_s *fcport = cbarg;
+
+ if (complete) {
+ if (fcport->stats_status == BFA_STATUS_OK) {
+ struct bfa_timeval_s tv;
+
+ /* Swap FC QoS or FCoE stats */
+ if (bfa_ioc_get_fcmode(&fcport->bfa->ioc)) {
+ bfa_fcport_qos_stats_swap(
+ &fcport->stats_ret->fcqos,
+ &fcport->stats->fcqos);
+ } else {
+ bfa_fcport_fcoe_stats_swap(
+ &fcport->stats_ret->fcoe,
+ &fcport->stats->fcoe);
+
+ bfa_os_gettimeofday(&tv);
+ fcport->stats_ret->fcoe.secs_reset =
+ tv.tv_sec - fcport->stats_reset_time;
+ }
+ }
+ fcport->stats_cbfn(fcport->stats_cbarg, fcport->stats_status);
+ } else {
+ fcport->stats_busy = BFA_FALSE;
+ fcport->stats_status = BFA_STATUS_OK;
+ }
+}
+
+static void
+bfa_fcport_stats_get_timeout(void *cbarg)
+{
+ struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
+
+ bfa_trc(fcport->bfa, fcport->stats_qfull);
+
+ if (fcport->stats_qfull) {
+ bfa_reqq_wcancel(&fcport->stats_reqq_wait);
+ fcport->stats_qfull = BFA_FALSE;
+ }
+
+ fcport->stats_status = BFA_STATUS_ETIMER;
+ bfa_cb_queue(fcport->bfa, &fcport->hcb_qe, __bfa_cb_fcport_stats_get,
+ fcport);
+}
+
+static void
+bfa_fcport_send_stats_get(void *cbarg)
+{
+ struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
+ struct bfi_fcport_req_s *msg;
+
+ msg = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
+
+ if (!msg) {
+ fcport->stats_qfull = BFA_TRUE;
+ bfa_reqq_winit(&fcport->stats_reqq_wait,
+ bfa_fcport_send_stats_get, fcport);
+ bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
+ &fcport->stats_reqq_wait);
+ return;
+ }
+ fcport->stats_qfull = BFA_FALSE;
+
+ bfa_os_memset(msg, 0, sizeof(struct bfi_fcport_req_s));
+ bfi_h2i_set(msg->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_STATS_GET_REQ,
+ bfa_lpuid(fcport->bfa));
+ bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT);
+}
+
+static void
+__bfa_cb_fcport_stats_clr(void *cbarg, bfa_boolean_t complete)
+{
+ struct bfa_fcport_s *fcport = cbarg;
+
+ if (complete) {
+ struct bfa_timeval_s tv;
+
+ /**
+ * re-initialize time stamp for stats reset
+ */
+ bfa_os_gettimeofday(&tv);
+ fcport->stats_reset_time = tv.tv_sec;
+
+ fcport->stats_cbfn(fcport->stats_cbarg, fcport->stats_status);
+ } else {
+ fcport->stats_busy = BFA_FALSE;
+ fcport->stats_status = BFA_STATUS_OK;
+ }
+}
+
+static void
+bfa_fcport_stats_clr_timeout(void *cbarg)
+{
+ struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
+
+ bfa_trc(fcport->bfa, fcport->stats_qfull);
+
+ if (fcport->stats_qfull) {
+ bfa_reqq_wcancel(&fcport->stats_reqq_wait);
+ fcport->stats_qfull = BFA_FALSE;
+ }
+
+ fcport->stats_status = BFA_STATUS_ETIMER;
+ bfa_cb_queue(fcport->bfa, &fcport->hcb_qe,
+ __bfa_cb_fcport_stats_clr, fcport);
+}
+
+static void
+bfa_fcport_send_stats_clear(void *cbarg)
+{
+ struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
+ struct bfi_fcport_req_s *msg;
+
+ msg = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
+
+ if (!msg) {
+ fcport->stats_qfull = BFA_TRUE;
+ bfa_reqq_winit(&fcport->stats_reqq_wait,
+ bfa_fcport_send_stats_clear, fcport);
+ bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
+ &fcport->stats_reqq_wait);
+ return;
+ }
+ fcport->stats_qfull = BFA_FALSE;
+
+ bfa_os_memset(msg, 0, sizeof(struct bfi_fcport_req_s));
+ bfi_h2i_set(msg->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_STATS_CLEAR_REQ,
+ bfa_lpuid(fcport->bfa));
+ bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT);
+}
+
+/**
+ * Handle trunk SCN event from firmware.
+ */
+static void
+bfa_trunk_scn(struct bfa_fcport_s *fcport, struct bfi_fcport_trunk_scn_s *scn)
+{
+ struct bfa_fcport_trunk_s *trunk = &fcport->trunk;
+ struct bfi_fcport_trunk_link_s *tlink;
+ struct bfa_trunk_link_attr_s *lattr;
+ enum bfa_trunk_state state_prev;
+ int i;
+ int link_bm = 0;
+
+ bfa_trc(fcport->bfa, fcport->cfg.trunked);
+ bfa_assert(scn->trunk_state == BFA_TRUNK_ONLINE ||
+ scn->trunk_state == BFA_TRUNK_OFFLINE);
+
+ bfa_trc(fcport->bfa, trunk->attr.state);
+ bfa_trc(fcport->bfa, scn->trunk_state);
+ bfa_trc(fcport->bfa, scn->trunk_speed);
+
+ /**
+ * Save off new state for trunk attribute query
+ */
+ state_prev = trunk->attr.state;
+ if (fcport->cfg.trunked && (trunk->attr.state != BFA_TRUNK_DISABLED))
+ trunk->attr.state = scn->trunk_state;
+ trunk->attr.speed = scn->trunk_speed;
+ for (i = 0; i < BFA_TRUNK_MAX_PORTS; i++) {
+ lattr = &trunk->attr.link_attr[i];
+ tlink = &scn->tlink[i];
+
+ lattr->link_state = tlink->state;
+ lattr->trunk_wwn = tlink->trunk_wwn;
+ lattr->fctl = tlink->fctl;
+ lattr->speed = tlink->speed;
+ lattr->deskew = bfa_os_ntohl(tlink->deskew);
+
+ if (tlink->state == BFA_TRUNK_LINK_STATE_UP) {
+ fcport->speed = tlink->speed;
+ fcport->topology = BFA_PORT_TOPOLOGY_P2P;
+ link_bm |= 1 << i;
+ }
+
+ bfa_trc(fcport->bfa, lattr->link_state);
+ bfa_trc(fcport->bfa, lattr->trunk_wwn);
+ bfa_trc(fcport->bfa, lattr->fctl);
+ bfa_trc(fcport->bfa, lattr->speed);
+ bfa_trc(fcport->bfa, lattr->deskew);
+ }
+
+ switch (link_bm) {
+ case 3:
+ bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
+ BFA_PL_EID_TRUNK_SCN, 0, "Trunk up(0,1)");
+ break;
+ case 2:
+ bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
+ BFA_PL_EID_TRUNK_SCN, 0, "Trunk up(-,1)");
+ break;
+ case 1:
+ bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
+ BFA_PL_EID_TRUNK_SCN, 0, "Trunk up(0,-)");
+ break;
+ default:
+ bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
+ BFA_PL_EID_TRUNK_SCN, 0, "Trunk down");
+ }
+
+ /**
+ * Notify upper layers if trunk state changed.
+ */
+ if ((state_prev != trunk->attr.state) ||
+ (scn->trunk_state == BFA_TRUNK_OFFLINE)) {
+ bfa_fcport_scn(fcport, (scn->trunk_state == BFA_TRUNK_ONLINE) ?
+ BFA_PORT_LINKUP : BFA_PORT_LINKDOWN, BFA_TRUE);
+ }
+}
+
+static void
+bfa_trunk_iocdisable(struct bfa_s *bfa)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+ int i = 0;
+
+ /**
+ * In trunked mode, notify upper layers that link is down
+ */
+ if (fcport->cfg.trunked) {
+ if (fcport->trunk.attr.state == BFA_TRUNK_ONLINE)
+ bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_TRUE);
+
+ fcport->trunk.attr.state = BFA_TRUNK_OFFLINE;
+ fcport->trunk.attr.speed = BFA_PORT_SPEED_UNKNOWN;
+ for (i = 0; i < BFA_TRUNK_MAX_PORTS; i++) {
+ fcport->trunk.attr.link_attr[i].trunk_wwn = 0;
+ fcport->trunk.attr.link_attr[i].fctl =
+ BFA_TRUNK_LINK_FCTL_NORMAL;
+ fcport->trunk.attr.link_attr[i].link_state =
+ BFA_TRUNK_LINK_STATE_DN_LINKDN;
+ fcport->trunk.attr.link_attr[i].speed =
+ BFA_PORT_SPEED_UNKNOWN;
+ fcport->trunk.attr.link_attr[i].deskew = 0;
+ }
+ }
+}
+
+
+
+/**
+ * hal_port_public
+ */
+
+/**
+ * Called to initialize port attributes
+ */
+void
+bfa_fcport_init(struct bfa_s *bfa)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+ /**
+ * Initialize port attributes from IOC hardware data.
+ */
+ bfa_fcport_set_wwns(fcport);
+ if (fcport->cfg.maxfrsize == 0)
+ fcport->cfg.maxfrsize = bfa_ioc_maxfrsize(&bfa->ioc);
+ fcport->cfg.rx_bbcredit = bfa_ioc_rx_bbcredit(&bfa->ioc);
+ fcport->speed_sup = bfa_ioc_speed_sup(&bfa->ioc);
+
+ bfa_assert(fcport->cfg.maxfrsize);
+ bfa_assert(fcport->cfg.rx_bbcredit);
+ bfa_assert(fcport->speed_sup);
+}
+
+/**
+ * Firmware message handler.
+ */
+void
+bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+ union bfi_fcport_i2h_msg_u i2hmsg;
+
+ i2hmsg.msg = msg;
+ fcport->event_arg.i2hmsg = i2hmsg;
+
+ bfa_trc(bfa, msg->mhdr.msg_id);
+ bfa_trc(bfa, bfa_sm_to_state(hal_port_sm_table, fcport->sm));
+
+ switch (msg->mhdr.msg_id) {
+ case BFI_FCPORT_I2H_ENABLE_RSP:
+ if (fcport->msgtag == i2hmsg.penable_rsp->msgtag)
+ bfa_sm_send_event(fcport, BFA_FCPORT_SM_FWRSP);
+ break;
+
+ case BFI_FCPORT_I2H_DISABLE_RSP:
+ if (fcport->msgtag == i2hmsg.penable_rsp->msgtag)
+ bfa_sm_send_event(fcport, BFA_FCPORT_SM_FWRSP);
+ break;
+
+ case BFI_FCPORT_I2H_EVENT:
+ if (i2hmsg.event->link_state.linkstate == BFA_PORT_LINKUP)
+ bfa_sm_send_event(fcport, BFA_FCPORT_SM_LINKUP);
+ else
+ bfa_sm_send_event(fcport, BFA_FCPORT_SM_LINKDOWN);
+ break;
+
+ case BFI_FCPORT_I2H_TRUNK_SCN:
+ bfa_trunk_scn(fcport, i2hmsg.trunk_scn);
+ break;
+
+ case BFI_FCPORT_I2H_STATS_GET_RSP:
+ /*
+ * check for timer pop before processing the rsp
+ */
+ if (fcport->stats_busy == BFA_FALSE ||
+ fcport->stats_status == BFA_STATUS_ETIMER)
+ break;
+
+ bfa_timer_stop(&fcport->timer);
+ fcport->stats_status = i2hmsg.pstatsget_rsp->status;
+ bfa_cb_queue(fcport->bfa, &fcport->hcb_qe,
+ __bfa_cb_fcport_stats_get, fcport);
+ break;
+
+ case BFI_FCPORT_I2H_STATS_CLEAR_RSP:
+ /*
+ * check for timer pop before processing the rsp
+ */
+ if (fcport->stats_busy == BFA_FALSE ||
+ fcport->stats_status == BFA_STATUS_ETIMER)
+ break;
+
+ bfa_timer_stop(&fcport->timer);
+ fcport->stats_status = BFA_STATUS_OK;
+ bfa_cb_queue(fcport->bfa, &fcport->hcb_qe,
+ __bfa_cb_fcport_stats_clr, fcport);
+ break;
+
+ case BFI_FCPORT_I2H_ENABLE_AEN:
+ bfa_sm_send_event(fcport, BFA_FCPORT_SM_ENABLE);
+ break;
+
+ case BFI_FCPORT_I2H_DISABLE_AEN:
+ bfa_sm_send_event(fcport, BFA_FCPORT_SM_DISABLE);
+ break;
+
+ default:
+ bfa_assert(0);
+ break;
+ }
+}
+
+
+
+/**
+ * hal_port_api
+ */
+
+/**
+ * Registered callback for port events.
+ */
+void
+bfa_fcport_event_register(struct bfa_s *bfa,
+ void (*cbfn) (void *cbarg,
+ enum bfa_port_linkstate event),
+ void *cbarg)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+ fcport->event_cbfn = cbfn;
+ fcport->event_cbarg = cbarg;
+}
+
+bfa_status_t
+bfa_fcport_enable(struct bfa_s *bfa)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+ if (bfa_ioc_is_disabled(&bfa->ioc))
+ return BFA_STATUS_IOC_DISABLED;
+
+ if (fcport->diag_busy)
+ return BFA_STATUS_DIAG_BUSY;
+
+ bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_ENABLE);
+ return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_fcport_disable(struct bfa_s *bfa)
+{
+
+ if (bfa_ioc_is_disabled(&bfa->ioc))
+ return BFA_STATUS_IOC_DISABLED;
+
+ bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DISABLE);
+ return BFA_STATUS_OK;
+}
+
+/**
+ * Configure port speed.
+ */
+bfa_status_t
+bfa_fcport_cfg_speed(struct bfa_s *bfa, enum bfa_port_speed speed)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+ bfa_trc(bfa, speed);
+
+ if (fcport->cfg.trunked == BFA_TRUE)
+ return BFA_STATUS_TRUNK_ENABLED;
+ if ((speed != BFA_PORT_SPEED_AUTO) && (speed > fcport->speed_sup)) {
+ bfa_trc(bfa, fcport->speed_sup);
+ return BFA_STATUS_UNSUPP_SPEED;
+ }
+
+ fcport->cfg.speed = speed;
+
+ return BFA_STATUS_OK;
+}
+
+/**
+ * Get current speed.
+ */
+enum bfa_port_speed
+bfa_fcport_get_speed(struct bfa_s *bfa)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+ return fcport->speed;
+}
+
+/**
+ * Configure port topology.
+ */
+bfa_status_t
+bfa_fcport_cfg_topology(struct bfa_s *bfa, enum bfa_port_topology topology)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+ bfa_trc(bfa, topology);
+ bfa_trc(bfa, fcport->cfg.topology);
+
+ switch (topology) {
+ case BFA_PORT_TOPOLOGY_P2P:
+ case BFA_PORT_TOPOLOGY_LOOP:
+ case BFA_PORT_TOPOLOGY_AUTO:
+ break;
+
+ default:
+ return BFA_STATUS_EINVAL;
+ }
+
+ fcport->cfg.topology = topology;
+ return BFA_STATUS_OK;
+}
+
+/**
+ * Get current topology.
+ */
+enum bfa_port_topology
+bfa_fcport_get_topology(struct bfa_s *bfa)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+ return fcport->topology;
+}
+
+bfa_status_t
+bfa_fcport_cfg_hardalpa(struct bfa_s *bfa, u8 alpa)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+ bfa_trc(bfa, alpa);
+ bfa_trc(bfa, fcport->cfg.cfg_hardalpa);
+ bfa_trc(bfa, fcport->cfg.hardalpa);
+
+ fcport->cfg.cfg_hardalpa = BFA_TRUE;
+ fcport->cfg.hardalpa = alpa;
+
+ return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_fcport_clr_hardalpa(struct bfa_s *bfa)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+ bfa_trc(bfa, fcport->cfg.cfg_hardalpa);
+ bfa_trc(bfa, fcport->cfg.hardalpa);
+
+ fcport->cfg.cfg_hardalpa = BFA_FALSE;
+ return BFA_STATUS_OK;
+}
+
+bfa_boolean_t
+bfa_fcport_get_hardalpa(struct bfa_s *bfa, u8 *alpa)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+ *alpa = fcport->cfg.hardalpa;
+ return fcport->cfg.cfg_hardalpa;
+}
+
+u8
+bfa_fcport_get_myalpa(struct bfa_s *bfa)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+ return fcport->myalpa;
+}
+
+bfa_status_t
+bfa_fcport_cfg_maxfrsize(struct bfa_s *bfa, u16 maxfrsize)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+ bfa_trc(bfa, maxfrsize);
+ bfa_trc(bfa, fcport->cfg.maxfrsize);
+
+ /* with in range */
+ if ((maxfrsize > FC_MAX_PDUSZ) || (maxfrsize < FC_MIN_PDUSZ))
+ return BFA_STATUS_INVLD_DFSZ;
+
+ /* power of 2, if not the max frame size of 2112 */
+ if ((maxfrsize != FC_MAX_PDUSZ) && (maxfrsize & (maxfrsize - 1)))
+ return BFA_STATUS_INVLD_DFSZ;
+
+ fcport->cfg.maxfrsize = maxfrsize;
+ return BFA_STATUS_OK;
+}
+
+u16
+bfa_fcport_get_maxfrsize(struct bfa_s *bfa)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+ return fcport->cfg.maxfrsize;
+}
+
+u8
+bfa_fcport_get_rx_bbcredit(struct bfa_s *bfa)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+ return fcport->cfg.rx_bbcredit;
+}
+
+void
+bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+ fcport->cfg.tx_bbcredit = (u8)tx_bbcredit;
+ bfa_fcport_send_txcredit(fcport);
+}
+
+/**
+ * Get port attributes.
+ */
+
+wwn_t
+bfa_fcport_get_wwn(struct bfa_s *bfa, bfa_boolean_t node)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+ if (node)
+ return fcport->nwwn;
+ else
+ return fcport->pwwn;
+}
+
+void
+bfa_fcport_get_attr(struct bfa_s *bfa, struct bfa_port_attr_s *attr)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+ bfa_os_memset(attr, 0, sizeof(struct bfa_port_attr_s));
+
+ attr->nwwn = fcport->nwwn;
+ attr->pwwn = fcport->pwwn;
+
+ attr->factorypwwn = bfa_ioc_get_mfg_pwwn(&bfa->ioc);
+ attr->factorynwwn = bfa_ioc_get_mfg_nwwn(&bfa->ioc);
+
+ bfa_os_memcpy(&attr->pport_cfg, &fcport->cfg,
+ sizeof(struct bfa_port_cfg_s));
+ /* speed attributes */
+ attr->pport_cfg.speed = fcport->cfg.speed;
+ attr->speed_supported = fcport->speed_sup;
+ attr->speed = fcport->speed;
+ attr->cos_supported = FC_CLASS_3;
+
+ /* topology attributes */
+ attr->pport_cfg.topology = fcport->cfg.topology;
+ attr->topology = fcport->topology;
+ attr->pport_cfg.trunked = fcport->cfg.trunked;
+
+ /* beacon attributes */
+ attr->beacon = fcport->beacon;
+ attr->link_e2e_beacon = fcport->link_e2e_beacon;
+ attr->plog_enabled = bfa_plog_get_setting(fcport->bfa->plog);
+ attr->io_profile = bfa_fcpim_get_io_profile(fcport->bfa);
+
+ attr->pport_cfg.path_tov = bfa_fcpim_path_tov_get(bfa);
+ attr->pport_cfg.q_depth = bfa_fcpim_qdepth_get(bfa);
+ attr->port_state = bfa_sm_to_state(hal_port_sm_table, fcport->sm);
+ if (bfa_ioc_is_disabled(&fcport->bfa->ioc))
+ attr->port_state = BFA_PORT_ST_IOCDIS;
+ else if (bfa_ioc_fw_mismatch(&fcport->bfa->ioc))
+ attr->port_state = BFA_PORT_ST_FWMISMATCH;
+
+ /* FCoE vlan */
+ attr->fcoe_vlan = fcport->fcoe_vlan;
+}
+
+#define BFA_FCPORT_STATS_TOV 1000
+
+/**
+ * Fetch port statistics (FCQoS or FCoE).
+ */
+bfa_status_t
+bfa_fcport_get_stats(struct bfa_s *bfa, union bfa_fcport_stats_u *stats,
+ bfa_cb_port_t cbfn, void *cbarg)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+ if (fcport->stats_busy) {
+ bfa_trc(bfa, fcport->stats_busy);
+ return BFA_STATUS_DEVBUSY;
+ }
+
+ fcport->stats_busy = BFA_TRUE;
+ fcport->stats_ret = stats;
+ fcport->stats_cbfn = cbfn;
+ fcport->stats_cbarg = cbarg;
+
+ bfa_fcport_send_stats_get(fcport);
+
+ bfa_timer_start(bfa, &fcport->timer, bfa_fcport_stats_get_timeout,
+ fcport, BFA_FCPORT_STATS_TOV);
+ return BFA_STATUS_OK;
+}
+
+/**
+ * Reset port statistics (FCQoS or FCoE).
+ */
+bfa_status_t
+bfa_fcport_clear_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn, void *cbarg)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+ if (fcport->stats_busy) {
+ bfa_trc(bfa, fcport->stats_busy);
+ return BFA_STATUS_DEVBUSY;
+ }
+
+ fcport->stats_busy = BFA_TRUE;
+ fcport->stats_cbfn = cbfn;
+ fcport->stats_cbarg = cbarg;
+
+ bfa_fcport_send_stats_clear(fcport);
+
+ bfa_timer_start(bfa, &fcport->timer, bfa_fcport_stats_clr_timeout,
+ fcport, BFA_FCPORT_STATS_TOV);
+ return BFA_STATUS_OK;
+}
+
+/**
+ * Fetch FCQoS port statistics
+ */
+bfa_status_t
+bfa_fcport_get_qos_stats(struct bfa_s *bfa, union bfa_fcport_stats_u *stats,
+ bfa_cb_port_t cbfn, void *cbarg)
+{
+ /* Meaningful only for FC mode */
+ bfa_assert(bfa_ioc_get_fcmode(&bfa->ioc));
+
+ return bfa_fcport_get_stats(bfa, stats, cbfn, cbarg);
+}
+
+/**
+ * Reset FCoE port statistics
+ */
+bfa_status_t
+bfa_fcport_clear_qos_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn, void *cbarg)
+{
+ /* Meaningful only for FC mode */
+ bfa_assert(bfa_ioc_get_fcmode(&bfa->ioc));
+
+ return bfa_fcport_clear_stats(bfa, cbfn, cbarg);
+}
+
+/**
+ * Fetch FCQoS port statistics
+ */
+bfa_status_t
+bfa_fcport_get_fcoe_stats(struct bfa_s *bfa, union bfa_fcport_stats_u *stats,
+ bfa_cb_port_t cbfn, void *cbarg)
+{
+ /* Meaningful only for FCoE mode */
+ bfa_assert(!bfa_ioc_get_fcmode(&bfa->ioc));
+
+ return bfa_fcport_get_stats(bfa, stats, cbfn, cbarg);
+}
+
+/**
+ * Reset FCoE port statistics
+ */
+bfa_status_t
+bfa_fcport_clear_fcoe_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn, void *cbarg)
+{
+ /* Meaningful only for FCoE mode */
+ bfa_assert(!bfa_ioc_get_fcmode(&bfa->ioc));
+
+ return bfa_fcport_clear_stats(bfa, cbfn, cbarg);
+}
+
+void
+bfa_fcport_qos_get_attr(struct bfa_s *bfa, struct bfa_qos_attr_s *qos_attr)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+ qos_attr->state = fcport->qos_attr.state;
+ qos_attr->total_bb_cr = bfa_os_ntohl(fcport->qos_attr.total_bb_cr);
+}
+
+void
+bfa_fcport_qos_get_vc_attr(struct bfa_s *bfa,
+ struct bfa_qos_vc_attr_s *qos_vc_attr)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+ struct bfa_qos_vc_attr_s *bfa_vc_attr = &fcport->qos_vc_attr;
+ u32 i = 0;
+
+ qos_vc_attr->total_vc_count = bfa_os_ntohs(bfa_vc_attr->total_vc_count);
+ qos_vc_attr->shared_credit = bfa_os_ntohs(bfa_vc_attr->shared_credit);
+ qos_vc_attr->elp_opmode_flags =
+ bfa_os_ntohl(bfa_vc_attr->elp_opmode_flags);
+
+ /* Individual VC info */
+ while (i < qos_vc_attr->total_vc_count) {
+ qos_vc_attr->vc_info[i].vc_credit =
+ bfa_vc_attr->vc_info[i].vc_credit;
+ qos_vc_attr->vc_info[i].borrow_credit =
+ bfa_vc_attr->vc_info[i].borrow_credit;
+ qos_vc_attr->vc_info[i].priority =
+ bfa_vc_attr->vc_info[i].priority;
+ ++i;
+ }
+}
+
+/**
+ * Fetch port attributes.
+ */
+bfa_boolean_t
+bfa_fcport_is_disabled(struct bfa_s *bfa)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+ return bfa_sm_to_state(hal_port_sm_table, fcport->sm) ==
+ BFA_PORT_ST_DISABLED;
+
+}
+
+bfa_boolean_t
+bfa_fcport_is_ratelim(struct bfa_s *bfa)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+ return fcport->cfg.ratelimit ? BFA_TRUE : BFA_FALSE;
+
+}
+
+void
+bfa_fcport_cfg_qos(struct bfa_s *bfa, bfa_boolean_t on_off)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+ enum bfa_ioc_type_e ioc_type = bfa_get_type(bfa);
+
+ bfa_trc(bfa, on_off);
+ bfa_trc(bfa, fcport->cfg.qos_enabled);
+
+ bfa_trc(bfa, ioc_type);
+
+ if (ioc_type == BFA_IOC_TYPE_FC) {
+ fcport->cfg.qos_enabled = on_off;
+ /**
+ * Notify fcpim of the change in QoS state
+ */
+ bfa_fcpim_update_ioredirect(bfa);
+ }
+}
+
+void
+bfa_fcport_cfg_ratelim(struct bfa_s *bfa, bfa_boolean_t on_off)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+ bfa_trc(bfa, on_off);
+ bfa_trc(bfa, fcport->cfg.ratelimit);
+
+ fcport->cfg.ratelimit = on_off;
+ if (fcport->cfg.trl_def_speed == BFA_PORT_SPEED_UNKNOWN)
+ fcport->cfg.trl_def_speed = BFA_PORT_SPEED_1GBPS;
+}
+
+/**
+ * Configure default minimum ratelim speed
+ */
+bfa_status_t
+bfa_fcport_cfg_ratelim_speed(struct bfa_s *bfa, enum bfa_port_speed speed)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+ bfa_trc(bfa, speed);
+
+ /* Auto and speeds greater than the supported speed, are invalid */
+ if ((speed == BFA_PORT_SPEED_AUTO) || (speed > fcport->speed_sup)) {
+ bfa_trc(bfa, fcport->speed_sup);
+ return BFA_STATUS_UNSUPP_SPEED;
+ }
+
+ fcport->cfg.trl_def_speed = speed;
+
+ return BFA_STATUS_OK;
+}
+
+/**
+ * Get default minimum ratelim speed
+ */
+enum bfa_port_speed
+bfa_fcport_get_ratelim_speed(struct bfa_s *bfa)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+ bfa_trc(bfa, fcport->cfg.trl_def_speed);
+ return fcport->cfg.trl_def_speed;
+
+}
+void
+bfa_fcport_busy(struct bfa_s *bfa, bfa_boolean_t status)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+ bfa_trc(bfa, status);
+ bfa_trc(bfa, fcport->diag_busy);
+
+ fcport->diag_busy = status;
+}
+
+void
+bfa_fcport_beacon(void *dev, bfa_boolean_t beacon,
+ bfa_boolean_t link_e2e_beacon)
+{
+ struct bfa_s *bfa = dev;
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+ bfa_trc(bfa, beacon);
+ bfa_trc(bfa, link_e2e_beacon);
+ bfa_trc(bfa, fcport->beacon);
+ bfa_trc(bfa, fcport->link_e2e_beacon);
+
+ fcport->beacon = beacon;
+ fcport->link_e2e_beacon = link_e2e_beacon;
+}
+
+bfa_boolean_t
+bfa_fcport_is_linkup(struct bfa_s *bfa)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+ return (!fcport->cfg.trunked &&
+ bfa_sm_cmp_state(fcport, bfa_fcport_sm_linkup)) ||
+ (fcport->cfg.trunked &&
+ fcport->trunk.attr.state == BFA_TRUNK_ONLINE);
+}
+
+bfa_boolean_t
+bfa_fcport_is_qos_enabled(struct bfa_s *bfa)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+ return fcport->cfg.qos_enabled;
+}
+
+bfa_status_t
+bfa_trunk_get_attr(struct bfa_s *bfa, struct bfa_trunk_attr_s *attr)
+
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+ struct bfa_fcport_trunk_s *trunk = &fcport->trunk;
+
+ bfa_trc(bfa, fcport->cfg.trunked);
+ bfa_trc(bfa, trunk->attr.state);
+ *attr = trunk->attr;
+ attr->port_id = bfa_lps_get_base_pid(bfa);
+
+ return BFA_STATUS_OK;
+}
+
+void
+bfa_trunk_enable_cfg(struct bfa_s *bfa)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+ struct bfa_fcport_trunk_s *trunk = &fcport->trunk;
+
+ bfa_trc(bfa, 1);
+ trunk->attr.state = BFA_TRUNK_OFFLINE;
+ fcport->cfg.trunked = BFA_TRUE;
+}
+
+bfa_status_t
+bfa_trunk_enable(struct bfa_s *bfa)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+ struct bfa_fcport_trunk_s *trunk = &fcport->trunk;
+
+ bfa_trc(bfa, 1);
+
+ trunk->attr.state = BFA_TRUNK_OFFLINE;
+ bfa_fcport_disable(bfa);
+ fcport->cfg.trunked = BFA_TRUE;
+ bfa_fcport_enable(bfa);
+
+ return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_trunk_disable(struct bfa_s *bfa)
+{
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+ struct bfa_fcport_trunk_s *trunk = &fcport->trunk;
+
+ bfa_trc(bfa, 0);
+ trunk->attr.state = BFA_TRUNK_DISABLED;
+ bfa_fcport_disable(bfa);
+ fcport->cfg.trunked = BFA_FALSE;
+ bfa_fcport_enable(bfa);
+ return BFA_STATUS_OK;
+}
+
+
+/**
+ * Rport State machine functions
+ */
+/**
+ * Beginning state, only online event expected.
+ */
+static void
+bfa_rport_sm_uninit(struct bfa_rport_s *rp, enum bfa_rport_event event)
+{
+ bfa_trc(rp->bfa, rp->rport_tag);
+ bfa_trc(rp->bfa, event);
+
+ switch (event) {
+ case BFA_RPORT_SM_CREATE:
+ bfa_stats(rp, sm_un_cr);
+ bfa_sm_set_state(rp, bfa_rport_sm_created);
+ break;
+
+ default:
+ bfa_stats(rp, sm_un_unexp);
+ bfa_sm_fault(rp->bfa, event);
+ }
+}
+
+static void
+bfa_rport_sm_created(struct bfa_rport_s *rp, enum bfa_rport_event event)
+{
+ bfa_trc(rp->bfa, rp->rport_tag);
+ bfa_trc(rp->bfa, event);
+
+ switch (event) {
+ case BFA_RPORT_SM_ONLINE:
+ bfa_stats(rp, sm_cr_on);
+ if (bfa_rport_send_fwcreate(rp))
+ bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
+ else
+ bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);
+ break;
+
+ case BFA_RPORT_SM_DELETE:
+ bfa_stats(rp, sm_cr_del);
+ bfa_sm_set_state(rp, bfa_rport_sm_uninit);
+ bfa_rport_free(rp);
+ break;
+
+ case BFA_RPORT_SM_HWFAIL:
+ bfa_stats(rp, sm_cr_hwf);
+ bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
+ break;
+
+ default:
+ bfa_stats(rp, sm_cr_unexp);
+ bfa_sm_fault(rp->bfa, event);
+ }
+}
+
+/**
+ * Waiting for rport create response from firmware.
+ */
+static void
+bfa_rport_sm_fwcreate(struct bfa_rport_s *rp, enum bfa_rport_event event)
+{
+ bfa_trc(rp->bfa, rp->rport_tag);
+ bfa_trc(rp->bfa, event);
+
+ switch (event) {
+ case BFA_RPORT_SM_FWRSP:
+ bfa_stats(rp, sm_fwc_rsp);
+ bfa_sm_set_state(rp, bfa_rport_sm_online);
+ bfa_rport_online_cb(rp);
+ break;
+
+ case BFA_RPORT_SM_DELETE:
+ bfa_stats(rp, sm_fwc_del);
+ bfa_sm_set_state(rp, bfa_rport_sm_delete_pending);
+ break;
+
+ case BFA_RPORT_SM_OFFLINE:
+ bfa_stats(rp, sm_fwc_off);
+ bfa_sm_set_state(rp, bfa_rport_sm_offline_pending);
+ break;
+
+ case BFA_RPORT_SM_HWFAIL:
+ bfa_stats(rp, sm_fwc_hwf);
+ bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
+ break;
+
+ default:
+ bfa_stats(rp, sm_fwc_unexp);
+ bfa_sm_fault(rp->bfa, event);
+ }
+}
+
+/**
+ * Request queue is full, awaiting queue resume to send create request.
+ */
+static void
+bfa_rport_sm_fwcreate_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)
+{
+ bfa_trc(rp->bfa, rp->rport_tag);
+ bfa_trc(rp->bfa, event);
+
+ switch (event) {
+ case BFA_RPORT_SM_QRESUME:
+ bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
+ bfa_rport_send_fwcreate(rp);
+ break;
+
+ case BFA_RPORT_SM_DELETE:
+ bfa_stats(rp, sm_fwc_del);
+ bfa_sm_set_state(rp, bfa_rport_sm_uninit);
+ bfa_reqq_wcancel(&rp->reqq_wait);
+ bfa_rport_free(rp);
+ break;
+
+ case BFA_RPORT_SM_OFFLINE:
+ bfa_stats(rp, sm_fwc_off);
+ bfa_sm_set_state(rp, bfa_rport_sm_offline);
+ bfa_reqq_wcancel(&rp->reqq_wait);
+ bfa_rport_offline_cb(rp);
+ break;
+
+ case BFA_RPORT_SM_HWFAIL:
+ bfa_stats(rp, sm_fwc_hwf);
+ bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
+ bfa_reqq_wcancel(&rp->reqq_wait);
+ break;
+
+ default:
+ bfa_stats(rp, sm_fwc_unexp);
+ bfa_sm_fault(rp->bfa, event);
+ }
+}
+
+/**
+ * Online state - normal parking state.
+ */
+static void
+bfa_rport_sm_online(struct bfa_rport_s *rp, enum bfa_rport_event event)
+{
+ struct bfi_rport_qos_scn_s *qos_scn;
+
+ bfa_trc(rp->bfa, rp->rport_tag);
+ bfa_trc(rp->bfa, event);
+
+ switch (event) {
+ case BFA_RPORT_SM_OFFLINE:
+ bfa_stats(rp, sm_on_off);
+ if (bfa_rport_send_fwdelete(rp))
+ bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);
+ else
+ bfa_sm_set_state(rp, bfa_rport_sm_fwdelete_qfull);
+ break;
+
+ case BFA_RPORT_SM_DELETE:
+ bfa_stats(rp, sm_on_del);
+ if (bfa_rport_send_fwdelete(rp))
+ bfa_sm_set_state(rp, bfa_rport_sm_deleting);
+ else
+ bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);
+ break;
+
+ case BFA_RPORT_SM_HWFAIL:
+ bfa_stats(rp, sm_on_hwf);
+ bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
+ break;
+
+ case BFA_RPORT_SM_SET_SPEED:
+ bfa_rport_send_fwspeed(rp);
+ break;
+
+ case BFA_RPORT_SM_QOS_SCN:
+ qos_scn = (struct bfi_rport_qos_scn_s *) rp->event_arg.fw_msg;
+ rp->qos_attr = qos_scn->new_qos_attr;
+ bfa_trc(rp->bfa, qos_scn->old_qos_attr.qos_flow_id);
+ bfa_trc(rp->bfa, qos_scn->new_qos_attr.qos_flow_id);
+ bfa_trc(rp->bfa, qos_scn->old_qos_attr.qos_priority);
+ bfa_trc(rp->bfa, qos_scn->new_qos_attr.qos_priority);
+
+ qos_scn->old_qos_attr.qos_flow_id =
+ bfa_os_ntohl(qos_scn->old_qos_attr.qos_flow_id);
+ qos_scn->new_qos_attr.qos_flow_id =
+ bfa_os_ntohl(qos_scn->new_qos_attr.qos_flow_id);
+
+ if (qos_scn->old_qos_attr.qos_flow_id !=
+ qos_scn->new_qos_attr.qos_flow_id)
+ bfa_cb_rport_qos_scn_flowid(rp->rport_drv,
+ qos_scn->old_qos_attr,
+ qos_scn->new_qos_attr);
+ if (qos_scn->old_qos_attr.qos_priority !=
+ qos_scn->new_qos_attr.qos_priority)
+ bfa_cb_rport_qos_scn_prio(rp->rport_drv,
+ qos_scn->old_qos_attr,
+ qos_scn->new_qos_attr);
+ break;
+
+ default:
+ bfa_stats(rp, sm_on_unexp);
+ bfa_sm_fault(rp->bfa, event);
+ }
+}
+
+/**
+ * Firmware rport is being deleted - awaiting f/w response.
+ */
+static void
+bfa_rport_sm_fwdelete(struct bfa_rport_s *rp, enum bfa_rport_event event)
+{
+ bfa_trc(rp->bfa, rp->rport_tag);
+ bfa_trc(rp->bfa, event);
+
+ switch (event) {
+ case BFA_RPORT_SM_FWRSP:
+ bfa_stats(rp, sm_fwd_rsp);
+ bfa_sm_set_state(rp, bfa_rport_sm_offline);
+ bfa_rport_offline_cb(rp);
+ break;
+
+ case BFA_RPORT_SM_DELETE:
+ bfa_stats(rp, sm_fwd_del);
+ bfa_sm_set_state(rp, bfa_rport_sm_deleting);
+ break;
+
+ case BFA_RPORT_SM_HWFAIL:
+ bfa_stats(rp, sm_fwd_hwf);
+ bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
+ bfa_rport_offline_cb(rp);
+ break;
+
+ default:
+ bfa_stats(rp, sm_fwd_unexp);
+ bfa_sm_fault(rp->bfa, event);
+ }
+}
+
+static void
+bfa_rport_sm_fwdelete_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)
+{
+ bfa_trc(rp->bfa, rp->rport_tag);
+ bfa_trc(rp->bfa, event);
+
+ switch (event) {
+ case BFA_RPORT_SM_QRESUME:
+ bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);
+ bfa_rport_send_fwdelete(rp);
+ break;
+
+ case BFA_RPORT_SM_DELETE:
+ bfa_stats(rp, sm_fwd_del);
+ bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);
+ break;
+
+ case BFA_RPORT_SM_HWFAIL:
+ bfa_stats(rp, sm_fwd_hwf);
+ bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
+ bfa_reqq_wcancel(&rp->reqq_wait);
+ bfa_rport_offline_cb(rp);
+ break;
+
+ default:
+ bfa_stats(rp, sm_fwd_unexp);
+ bfa_sm_fault(rp->bfa, event);
+ }
+}
+
+/**
+ * Offline state.
+ */
+static void
+bfa_rport_sm_offline(struct bfa_rport_s *rp, enum bfa_rport_event event)
+{
+ bfa_trc(rp->bfa, rp->rport_tag);
+ bfa_trc(rp->bfa, event);
+
+ switch (event) {
+ case BFA_RPORT_SM_DELETE:
+ bfa_stats(rp, sm_off_del);
+ bfa_sm_set_state(rp, bfa_rport_sm_uninit);
+ bfa_rport_free(rp);
+ break;
+
+ case BFA_RPORT_SM_ONLINE:
+ bfa_stats(rp, sm_off_on);
+ if (bfa_rport_send_fwcreate(rp))
+ bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
+ else
+ bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);
+ break;
+
+ case BFA_RPORT_SM_HWFAIL:
+ bfa_stats(rp, sm_off_hwf);
+ bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
+ break;
+
+ default:
+ bfa_stats(rp, sm_off_unexp);
+ bfa_sm_fault(rp->bfa, event);
+ }
+}
+
+/**
+ * Rport is deleted, waiting for firmware response to delete.
+ */
+static void
+bfa_rport_sm_deleting(struct bfa_rport_s *rp, enum bfa_rport_event event)
+{
+ bfa_trc(rp->bfa, rp->rport_tag);
+ bfa_trc(rp->bfa, event);
+
+ switch (event) {
+ case BFA_RPORT_SM_FWRSP:
+ bfa_stats(rp, sm_del_fwrsp);
+ bfa_sm_set_state(rp, bfa_rport_sm_uninit);
+ bfa_rport_free(rp);
+ break;
+
+ case BFA_RPORT_SM_HWFAIL:
+ bfa_stats(rp, sm_del_hwf);
+ bfa_sm_set_state(rp, bfa_rport_sm_uninit);
+ bfa_rport_free(rp);
+ break;
+
+ default:
+ bfa_sm_fault(rp->bfa, event);
+ }
+}
+
+static void
+bfa_rport_sm_deleting_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)
+{
+ bfa_trc(rp->bfa, rp->rport_tag);
+ bfa_trc(rp->bfa, event);
+
+ switch (event) {
+ case BFA_RPORT_SM_QRESUME:
+ bfa_stats(rp, sm_del_fwrsp);
+ bfa_sm_set_state(rp, bfa_rport_sm_deleting);
+ bfa_rport_send_fwdelete(rp);
+ break;
+
+ case BFA_RPORT_SM_HWFAIL:
+ bfa_stats(rp, sm_del_hwf);
+ bfa_sm_set_state(rp, bfa_rport_sm_uninit);
+ bfa_reqq_wcancel(&rp->reqq_wait);
+ bfa_rport_free(rp);
+ break;
+
+ default:
+ bfa_sm_fault(rp->bfa, event);
+ }
+}
+
+/**
+ * Waiting for rport create response from firmware. A delete is pending.
+ */
+static void
+bfa_rport_sm_delete_pending(struct bfa_rport_s *rp,
+ enum bfa_rport_event event)
+{
+ bfa_trc(rp->bfa, rp->rport_tag);
+ bfa_trc(rp->bfa, event);
+
+ switch (event) {
+ case BFA_RPORT_SM_FWRSP:
+ bfa_stats(rp, sm_delp_fwrsp);
+ if (bfa_rport_send_fwdelete(rp))
+ bfa_sm_set_state(rp, bfa_rport_sm_deleting);
+ else
+ bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);
+ break;
+
+ case BFA_RPORT_SM_HWFAIL:
+ bfa_stats(rp, sm_delp_hwf);
+ bfa_sm_set_state(rp, bfa_rport_sm_uninit);
+ bfa_rport_free(rp);
+ break;
+
+ default:
+ bfa_stats(rp, sm_delp_unexp);
+ bfa_sm_fault(rp->bfa, event);
+ }
+}
+
+/**
+ * Waiting for rport create response from firmware. Rport offline is pending.
+ */
+static void
+bfa_rport_sm_offline_pending(struct bfa_rport_s *rp,
+ enum bfa_rport_event event)
+{
+ bfa_trc(rp->bfa, rp->rport_tag);
+ bfa_trc(rp->bfa, event);
+
+ switch (event) {
+ case BFA_RPORT_SM_FWRSP:
+ bfa_stats(rp, sm_offp_fwrsp);
+ if (bfa_rport_send_fwdelete(rp))
+ bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);
+ else
+ bfa_sm_set_state(rp, bfa_rport_sm_fwdelete_qfull);
+ break;
+
+ case BFA_RPORT_SM_DELETE:
+ bfa_stats(rp, sm_offp_del);
+ bfa_sm_set_state(rp, bfa_rport_sm_delete_pending);
+ break;
+
+ case BFA_RPORT_SM_HWFAIL:
+ bfa_stats(rp, sm_offp_hwf);
+ bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
+ break;
+
+ default:
+ bfa_stats(rp, sm_offp_unexp);
+ bfa_sm_fault(rp->bfa, event);
+ }
+}
+
+/**
+ * IOC h/w failed.
+ */
+static void
+bfa_rport_sm_iocdisable(struct bfa_rport_s *rp, enum bfa_rport_event event)
+{
+ bfa_trc(rp->bfa, rp->rport_tag);
+ bfa_trc(rp->bfa, event);
+
+ switch (event) {
+ case BFA_RPORT_SM_OFFLINE:
+ bfa_stats(rp, sm_iocd_off);
+ bfa_rport_offline_cb(rp);
+ break;
+
+ case BFA_RPORT_SM_DELETE:
+ bfa_stats(rp, sm_iocd_del);
+ bfa_sm_set_state(rp, bfa_rport_sm_uninit);
+ bfa_rport_free(rp);
+ break;
+
+ case BFA_RPORT_SM_ONLINE:
+ bfa_stats(rp, sm_iocd_on);
+ if (bfa_rport_send_fwcreate(rp))
+ bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
+ else
+ bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);
+ break;
+
+ case BFA_RPORT_SM_HWFAIL:
+ break;
+
+ default:
+ bfa_stats(rp, sm_iocd_unexp);
+ bfa_sm_fault(rp->bfa, event);
+ }
+}
+
+
+
+/**
+ * bfa_rport_private BFA rport private functions
+ */
+
+static void
+__bfa_cb_rport_online(void *cbarg, bfa_boolean_t complete)
+{
+ struct bfa_rport_s *rp = cbarg;
+
+ if (complete)
+ bfa_cb_rport_online(rp->rport_drv);
+}
+
+static void
+__bfa_cb_rport_offline(void *cbarg, bfa_boolean_t complete)
+{
+ struct bfa_rport_s *rp = cbarg;
+
+ if (complete)
+ bfa_cb_rport_offline(rp->rport_drv);
+}
+
+static void
+bfa_rport_qresume(void *cbarg)
+{
+ struct bfa_rport_s *rp = cbarg;
+
+ bfa_sm_send_event(rp, BFA_RPORT_SM_QRESUME);
+}
+
+static void
+bfa_rport_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
+ u32 *dm_len)
+{
+ if (cfg->fwcfg.num_rports < BFA_RPORT_MIN)
+ cfg->fwcfg.num_rports = BFA_RPORT_MIN;
+
+ *km_len += cfg->fwcfg.num_rports * sizeof(struct bfa_rport_s);
+}
+
+static void
+bfa_rport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
+ struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
+{
+ struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(bfa);
+ struct bfa_rport_s *rp;
+ u16 i;
+
+ INIT_LIST_HEAD(&mod->rp_free_q);
+ INIT_LIST_HEAD(&mod->rp_active_q);
+
+ rp = (struct bfa_rport_s *) bfa_meminfo_kva(meminfo);
+ mod->rps_list = rp;
+ mod->num_rports = cfg->fwcfg.num_rports;
+
+ bfa_assert(mod->num_rports &&
+ !(mod->num_rports & (mod->num_rports - 1)));
+
+ for (i = 0; i < mod->num_rports; i++, rp++) {
+ bfa_os_memset(rp, 0, sizeof(struct bfa_rport_s));
+ rp->bfa = bfa;
+ rp->rport_tag = i;
+ bfa_sm_set_state(rp, bfa_rport_sm_uninit);
+
+ /**
+ * - is unused
+ */
+ if (i)
+ list_add_tail(&rp->qe, &mod->rp_free_q);
+
+ bfa_reqq_winit(&rp->reqq_wait, bfa_rport_qresume, rp);
+ }
+
+ /**
+ * consume memory
+ */
+ bfa_meminfo_kva(meminfo) = (u8 *) rp;
+}
+
+static void
+bfa_rport_detach(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_rport_start(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_rport_stop(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_rport_iocdisable(struct bfa_s *bfa)
+{
+ struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(bfa);
+ struct bfa_rport_s *rport;
+ struct list_head *qe, *qen;
+
+ list_for_each_safe(qe, qen, &mod->rp_active_q) {
+ rport = (struct bfa_rport_s *) qe;
+ bfa_sm_send_event(rport, BFA_RPORT_SM_HWFAIL);
+ }
+}
+
+static struct bfa_rport_s *
+bfa_rport_alloc(struct bfa_rport_mod_s *mod)
+{
+ struct bfa_rport_s *rport;
+
+ bfa_q_deq(&mod->rp_free_q, &rport);
+ if (rport)
+ list_add_tail(&rport->qe, &mod->rp_active_q);
+
+ return rport;
+}
+
+static void
+bfa_rport_free(struct bfa_rport_s *rport)
+{
+ struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(rport->bfa);
+
+ bfa_assert(bfa_q_is_on_q(&mod->rp_active_q, rport));
+ list_del(&rport->qe);
+ list_add_tail(&rport->qe, &mod->rp_free_q);
+}
+
+static bfa_boolean_t
+bfa_rport_send_fwcreate(struct bfa_rport_s *rp)
+{
+ struct bfi_rport_create_req_s *m;
+
+ /**
+ * check for room in queue to send request now
+ */
+ m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);
+ if (!m) {
+ bfa_reqq_wait(rp->bfa, BFA_REQQ_RPORT, &rp->reqq_wait);
+ return BFA_FALSE;
+ }
+
+ bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_CREATE_REQ,
+ bfa_lpuid(rp->bfa));
+ m->bfa_handle = rp->rport_tag;
+ m->max_frmsz = bfa_os_htons(rp->rport_info.max_frmsz);
+ m->pid = rp->rport_info.pid;
+ m->lp_tag = rp->rport_info.lp_tag;
+ m->local_pid = rp->rport_info.local_pid;
+ m->fc_class = rp->rport_info.fc_class;
+ m->vf_en = rp->rport_info.vf_en;
+ m->vf_id = rp->rport_info.vf_id;
+ m->cisc = rp->rport_info.cisc;
+
+ /**
+ * queue I/O message to firmware
+ */
+ bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT);
+ return BFA_TRUE;
+}
+
+static bfa_boolean_t
+bfa_rport_send_fwdelete(struct bfa_rport_s *rp)
+{
+ struct bfi_rport_delete_req_s *m;
+
+ /**
+ * check for room in queue to send request now
+ */
+ m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);
+ if (!m) {
+ bfa_reqq_wait(rp->bfa, BFA_REQQ_RPORT, &rp->reqq_wait);
+ return BFA_FALSE;
+ }
+
+ bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_DELETE_REQ,
+ bfa_lpuid(rp->bfa));
+ m->fw_handle = rp->fw_handle;
+
+ /**
+ * queue I/O message to firmware
+ */
+ bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT);
+ return BFA_TRUE;
+}
+
+static bfa_boolean_t
+bfa_rport_send_fwspeed(struct bfa_rport_s *rp)
+{
+ struct bfa_rport_speed_req_s *m;
+
+ /**
+ * check for room in queue to send request now
+ */
+ m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);
+ if (!m) {
+ bfa_trc(rp->bfa, rp->rport_info.speed);
+ return BFA_FALSE;
+ }
+
+ bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_SET_SPEED_REQ,
+ bfa_lpuid(rp->bfa));
+ m->fw_handle = rp->fw_handle;
+ m->speed = (u8)rp->rport_info.speed;
+
+ /**
+ * queue I/O message to firmware
+ */
+ bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT);
+ return BFA_TRUE;
+}
+
+
+
+/**
+ * bfa_rport_public
+ */
+
+/**
+ * Rport interrupt processing.
+ */
+void
+bfa_rport_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
+{
+ union bfi_rport_i2h_msg_u msg;
+ struct bfa_rport_s *rp;
+
+ bfa_trc(bfa, m->mhdr.msg_id);
+
+ msg.msg = m;
+
+ switch (m->mhdr.msg_id) {
+ case BFI_RPORT_I2H_CREATE_RSP:
+ rp = BFA_RPORT_FROM_TAG(bfa, msg.create_rsp->bfa_handle);
+ rp->fw_handle = msg.create_rsp->fw_handle;
+ rp->qos_attr = msg.create_rsp->qos_attr;
+ bfa_assert(msg.create_rsp->status == BFA_STATUS_OK);
+ bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP);
+ break;
+
+ case BFI_RPORT_I2H_DELETE_RSP:
+ rp = BFA_RPORT_FROM_TAG(bfa, msg.delete_rsp->bfa_handle);
+ bfa_assert(msg.delete_rsp->status == BFA_STATUS_OK);
+ bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP);
+ break;
+
+ case BFI_RPORT_I2H_QOS_SCN:
+ rp = BFA_RPORT_FROM_TAG(bfa, msg.qos_scn_evt->bfa_handle);
+ rp->event_arg.fw_msg = msg.qos_scn_evt;
+ bfa_sm_send_event(rp, BFA_RPORT_SM_QOS_SCN);
+ break;
+
+ default:
+ bfa_trc(bfa, m->mhdr.msg_id);
+ bfa_assert(0);
+ }
+}
+
+
+
+/**
+ * bfa_rport_api
+ */
+
+struct bfa_rport_s *
+bfa_rport_create(struct bfa_s *bfa, void *rport_drv)
+{
+ struct bfa_rport_s *rp;
+
+ rp = bfa_rport_alloc(BFA_RPORT_MOD(bfa));
+
+ if (rp == NULL)
+ return NULL;
+
+ rp->bfa = bfa;
+ rp->rport_drv = rport_drv;
+ bfa_rport_clear_stats(rp);
+
+ bfa_assert(bfa_sm_cmp_state(rp, bfa_rport_sm_uninit));
+ bfa_sm_send_event(rp, BFA_RPORT_SM_CREATE);
+
+ return rp;
+}
+
+void
+bfa_rport_delete(struct bfa_rport_s *rport)
+{
+ bfa_sm_send_event(rport, BFA_RPORT_SM_DELETE);
+}
+
+void
+bfa_rport_online(struct bfa_rport_s *rport, struct bfa_rport_info_s *rport_info)
+{
+ bfa_assert(rport_info->max_frmsz != 0);
+
+ /**
+ * Some JBODs are seen to be not setting PDU size correctly in PLOGI
+ * responses. Default to minimum size.
+ */
+ if (rport_info->max_frmsz == 0) {
+ bfa_trc(rport->bfa, rport->rport_tag);
+ rport_info->max_frmsz = FC_MIN_PDUSZ;
+ }
+
+ bfa_os_assign(rport->rport_info, *rport_info);
+ bfa_sm_send_event(rport, BFA_RPORT_SM_ONLINE);
+}
+
+void
+bfa_rport_offline(struct bfa_rport_s *rport)
+{
+ bfa_sm_send_event(rport, BFA_RPORT_SM_OFFLINE);
+}
+
+void
+bfa_rport_speed(struct bfa_rport_s *rport, enum bfa_port_speed speed)
+{
+ bfa_assert(speed != 0);
+ bfa_assert(speed != BFA_PORT_SPEED_AUTO);
+
+ rport->rport_info.speed = speed;
+ bfa_sm_send_event(rport, BFA_RPORT_SM_SET_SPEED);
+}
+
+void
+bfa_rport_get_stats(struct bfa_rport_s *rport,
+ struct bfa_rport_hal_stats_s *stats)
+{
+ *stats = rport->stats;
+}
+
+void
+bfa_rport_get_qos_attr(struct bfa_rport_s *rport,
+ struct bfa_rport_qos_attr_s *qos_attr)
+{
+ qos_attr->qos_priority = rport->qos_attr.qos_priority;
+ qos_attr->qos_flow_id = bfa_os_ntohl(rport->qos_attr.qos_flow_id);
+
+}
+
+void
+bfa_rport_clear_stats(struct bfa_rport_s *rport)
+{
+ bfa_os_memset(&rport->stats, 0, sizeof(rport->stats));
+}
+
+
+/**
+ * SGPG related functions
+ */
+
+/**
+ * Compute and return memory needed by FCP(im) module.
+ */
+static void
+bfa_sgpg_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
+ u32 *dm_len)
+{
+ if (cfg->drvcfg.num_sgpgs < BFA_SGPG_MIN)
+ cfg->drvcfg.num_sgpgs = BFA_SGPG_MIN;
+
+ *km_len += (cfg->drvcfg.num_sgpgs + 1) * sizeof(struct bfa_sgpg_s);
+ *dm_len += (cfg->drvcfg.num_sgpgs + 1) * sizeof(struct bfi_sgpg_s);
+}
+
+
+static void
+bfa_sgpg_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
+ struct bfa_meminfo_s *minfo, struct bfa_pcidev_s *pcidev)
+{
+ struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
+ int i;
+ struct bfa_sgpg_s *hsgpg;
+ struct bfi_sgpg_s *sgpg;
+ u64 align_len;
+
+ union {
+ u64 pa;
+ union bfi_addr_u addr;
+ } sgpg_pa, sgpg_pa_tmp;
+
+ INIT_LIST_HEAD(&mod->sgpg_q);
+ INIT_LIST_HEAD(&mod->sgpg_wait_q);
+
+ bfa_trc(bfa, cfg->drvcfg.num_sgpgs);
+
+ mod->num_sgpgs = cfg->drvcfg.num_sgpgs;
+ mod->sgpg_arr_pa = bfa_meminfo_dma_phys(minfo);
+ align_len = (BFA_SGPG_ROUNDUP(mod->sgpg_arr_pa) - mod->sgpg_arr_pa);
+ mod->sgpg_arr_pa += align_len;
+ mod->hsgpg_arr = (struct bfa_sgpg_s *) (bfa_meminfo_kva(minfo) +
+ align_len);
+ mod->sgpg_arr = (struct bfi_sgpg_s *) (bfa_meminfo_dma_virt(minfo) +
+ align_len);
+
+ hsgpg = mod->hsgpg_arr;
+ sgpg = mod->sgpg_arr;
+ sgpg_pa.pa = mod->sgpg_arr_pa;
+ mod->free_sgpgs = mod->num_sgpgs;
+
+ bfa_assert(!(sgpg_pa.pa & (sizeof(struct bfi_sgpg_s) - 1)));
+
+ for (i = 0; i < mod->num_sgpgs; i++) {
+ bfa_os_memset(hsgpg, 0, sizeof(*hsgpg));
+ bfa_os_memset(sgpg, 0, sizeof(*sgpg));
+
+ hsgpg->sgpg = sgpg;
+ sgpg_pa_tmp.pa = bfa_sgaddr_le(sgpg_pa.pa);
+ hsgpg->sgpg_pa = sgpg_pa_tmp.addr;
+ list_add_tail(&hsgpg->qe, &mod->sgpg_q);
+
+ hsgpg++;
+ sgpg++;
+ sgpg_pa.pa += sizeof(struct bfi_sgpg_s);
+ }
+
+ bfa_meminfo_kva(minfo) = (u8 *) hsgpg;
+ bfa_meminfo_dma_virt(minfo) = (u8 *) sgpg;
+ bfa_meminfo_dma_phys(minfo) = sgpg_pa.pa;
+}
+
+static void
+bfa_sgpg_detach(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_sgpg_start(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_sgpg_stop(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_sgpg_iocdisable(struct bfa_s *bfa)
+{
+}
+
+
+
+/**
+ * hal_sgpg_public BFA SGPG public functions
+ */
+
+bfa_status_t
+bfa_sgpg_malloc(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpgs)
+{
+ struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
+ struct bfa_sgpg_s *hsgpg;
+ int i;
+
+ bfa_trc_fp(bfa, nsgpgs);
+
+ if (mod->free_sgpgs < nsgpgs)
+ return BFA_STATUS_ENOMEM;
+
+ for (i = 0; i < nsgpgs; i++) {
+ bfa_q_deq(&mod->sgpg_q, &hsgpg);
+ bfa_assert(hsgpg);
+ list_add_tail(&hsgpg->qe, sgpg_q);
+ }
+
+ mod->free_sgpgs -= nsgpgs;
+ return BFA_STATUS_OK;
+}
+
+void
+bfa_sgpg_mfree(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpg)
+{
+ struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
+ struct bfa_sgpg_wqe_s *wqe;
+
+ bfa_trc_fp(bfa, nsgpg);
+
+ mod->free_sgpgs += nsgpg;
+ bfa_assert(mod->free_sgpgs <= mod->num_sgpgs);
+
+ list_splice_tail_init(sgpg_q, &mod->sgpg_q);
+
+ if (list_empty(&mod->sgpg_wait_q))
+ return;
+
+ /**
+ * satisfy as many waiting requests as possible
+ */
+ do {
+ wqe = bfa_q_first(&mod->sgpg_wait_q);
+ if (mod->free_sgpgs < wqe->nsgpg)
+ nsgpg = mod->free_sgpgs;
+ else
+ nsgpg = wqe->nsgpg;
+ bfa_sgpg_malloc(bfa, &wqe->sgpg_q, nsgpg);
+ wqe->nsgpg -= nsgpg;
+ if (wqe->nsgpg == 0) {
+ list_del(&wqe->qe);
+ wqe->cbfn(wqe->cbarg);
+ }
+ } while (mod->free_sgpgs && !list_empty(&mod->sgpg_wait_q));
+}
+
+void
+bfa_sgpg_wait(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe, int nsgpg)
+{
+ struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
+
+ bfa_assert(nsgpg > 0);
+ bfa_assert(nsgpg > mod->free_sgpgs);
+
+ wqe->nsgpg_total = wqe->nsgpg = nsgpg;
+
+ /**
+ * allocate any left to this one first
+ */
+ if (mod->free_sgpgs) {
+ /**
+ * no one else is waiting for SGPG
+ */
+ bfa_assert(list_empty(&mod->sgpg_wait_q));
+ list_splice_tail_init(&mod->sgpg_q, &wqe->sgpg_q);
+ wqe->nsgpg -= mod->free_sgpgs;
+ mod->free_sgpgs = 0;
+ }
+
+ list_add_tail(&wqe->qe, &mod->sgpg_wait_q);
+}
+
+void
+bfa_sgpg_wcancel(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe)
+{
+ struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
+
+ bfa_assert(bfa_q_is_on_q(&mod->sgpg_wait_q, wqe));
+ list_del(&wqe->qe);
+
+ if (wqe->nsgpg_total != wqe->nsgpg)
+ bfa_sgpg_mfree(bfa, &wqe->sgpg_q,
+ wqe->nsgpg_total - wqe->nsgpg);
+}
+
+void
+bfa_sgpg_winit(struct bfa_sgpg_wqe_s *wqe, void (*cbfn) (void *cbarg),
+ void *cbarg)
+{
+ INIT_LIST_HEAD(&wqe->sgpg_q);
+ wqe->cbfn = cbfn;
+ wqe->cbarg = cbarg;
+}
+
+/**
+ * UF related functions
+ */
+/*
+ *****************************************************************************
+ * Internal functions
+ *****************************************************************************
+ */
+static void
+__bfa_cb_uf_recv(void *cbarg, bfa_boolean_t complete)
+{
+ struct bfa_uf_s *uf = cbarg;
+ struct bfa_uf_mod_s *ufm = BFA_UF_MOD(uf->bfa);
+
+ if (complete)
+ ufm->ufrecv(ufm->cbarg, uf);
+}
+
+static void
+claim_uf_pbs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
+{
+ u32 uf_pb_tot_sz;
+
+ ufm->uf_pbs_kva = (struct bfa_uf_buf_s *) bfa_meminfo_dma_virt(mi);
+ ufm->uf_pbs_pa = bfa_meminfo_dma_phys(mi);
+ uf_pb_tot_sz = BFA_ROUNDUP((sizeof(struct bfa_uf_buf_s) * ufm->num_ufs),
+ BFA_DMA_ALIGN_SZ);
+
+ bfa_meminfo_dma_virt(mi) += uf_pb_tot_sz;
+ bfa_meminfo_dma_phys(mi) += uf_pb_tot_sz;
+
+ bfa_os_memset((void *)ufm->uf_pbs_kva, 0, uf_pb_tot_sz);
+}
+
+static void
+claim_uf_post_msgs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
+{
+ struct bfi_uf_buf_post_s *uf_bp_msg;
+ struct bfi_sge_s *sge;
+ union bfi_addr_u sga_zero = { {0} };
+ u16 i;
+ u16 buf_len;
+
+ ufm->uf_buf_posts = (struct bfi_uf_buf_post_s *) bfa_meminfo_kva(mi);
+ uf_bp_msg = ufm->uf_buf_posts;
+
+ for (i = 0, uf_bp_msg = ufm->uf_buf_posts; i < ufm->num_ufs;
+ i++, uf_bp_msg++) {
+ bfa_os_memset(uf_bp_msg, 0, sizeof(struct bfi_uf_buf_post_s));
+
+ uf_bp_msg->buf_tag = i;
+ buf_len = sizeof(struct bfa_uf_buf_s);
+ uf_bp_msg->buf_len = bfa_os_htons(buf_len);
+ bfi_h2i_set(uf_bp_msg->mh, BFI_MC_UF, BFI_UF_H2I_BUF_POST,
+ bfa_lpuid(ufm->bfa));
+
+ sge = uf_bp_msg->sge;
+ sge[0].sg_len = buf_len;
+ sge[0].flags = BFI_SGE_DATA_LAST;
+ bfa_dma_addr_set(sge[0].sga, ufm_pbs_pa(ufm, i));
+ bfa_sge_to_be(sge);
+
+ sge[1].sg_len = buf_len;
+ sge[1].flags = BFI_SGE_PGDLEN;
+ sge[1].sga = sga_zero;
+ bfa_sge_to_be(&sge[1]);
+ }
+
+ /**
+ * advance pointer beyond consumed memory
+ */
+ bfa_meminfo_kva(mi) = (u8 *) uf_bp_msg;
+}
+
+static void
+claim_ufs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
+{
+ u16 i;
+ struct bfa_uf_s *uf;
+
+ /*
+ * Claim block of memory for UF list
+ */
+ ufm->uf_list = (struct bfa_uf_s *) bfa_meminfo_kva(mi);
+
+ /*
+ * Initialize UFs and queue it in UF free queue
+ */
+ for (i = 0, uf = ufm->uf_list; i < ufm->num_ufs; i++, uf++) {
+ bfa_os_memset(uf, 0, sizeof(struct bfa_uf_s));
+ uf->bfa = ufm->bfa;
+ uf->uf_tag = i;
+ uf->pb_len = sizeof(struct bfa_uf_buf_s);
+ uf->buf_kva = (void *)&ufm->uf_pbs_kva[i];
+ uf->buf_pa = ufm_pbs_pa(ufm, i);
+ list_add_tail(&uf->qe, &ufm->uf_free_q);
+ }
+
+ /**
+ * advance memory pointer
+ */
+ bfa_meminfo_kva(mi) = (u8 *) uf;
+}
+
+static void
+uf_mem_claim(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
+{
+ claim_uf_pbs(ufm, mi);
+ claim_ufs(ufm, mi);
+ claim_uf_post_msgs(ufm, mi);
+}
+
+static void
+bfa_uf_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len, u32 *dm_len)
+{
+ u32 num_ufs = cfg->fwcfg.num_uf_bufs;
+
+ /*
+ * dma-able memory for UF posted bufs
+ */
+ *dm_len += BFA_ROUNDUP((sizeof(struct bfa_uf_buf_s) * num_ufs),
+ BFA_DMA_ALIGN_SZ);
+
+ /*
+ * kernel Virtual memory for UFs and UF buf post msg copies
+ */
+ *ndm_len += sizeof(struct bfa_uf_s) * num_ufs;
+ *ndm_len += sizeof(struct bfi_uf_buf_post_s) * num_ufs;
+}
+
+static void
+bfa_uf_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
+ struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
+{
+ struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
+
+ bfa_os_memset(ufm, 0, sizeof(struct bfa_uf_mod_s));
+ ufm->bfa = bfa;
+ ufm->num_ufs = cfg->fwcfg.num_uf_bufs;
+ INIT_LIST_HEAD(&ufm->uf_free_q);
+ INIT_LIST_HEAD(&ufm->uf_posted_q);
+
+ uf_mem_claim(ufm, meminfo);
+}
+
+static void
+bfa_uf_detach(struct bfa_s *bfa)
+{
+}
+
+static struct bfa_uf_s *
+bfa_uf_get(struct bfa_uf_mod_s *uf_mod)
+{
+ struct bfa_uf_s *uf;
+
+ bfa_q_deq(&uf_mod->uf_free_q, &uf);
+ return uf;
+}
+
+static void
+bfa_uf_put(struct bfa_uf_mod_s *uf_mod, struct bfa_uf_s *uf)
+{
+ list_add_tail(&uf->qe, &uf_mod->uf_free_q);
+}
+
+static bfa_status_t
+bfa_uf_post(struct bfa_uf_mod_s *ufm, struct bfa_uf_s *uf)
+{
+ struct bfi_uf_buf_post_s *uf_post_msg;
+
+ uf_post_msg = bfa_reqq_next(ufm->bfa, BFA_REQQ_FCXP);
+ if (!uf_post_msg)
+ return BFA_STATUS_FAILED;
+
+ bfa_os_memcpy(uf_post_msg, &ufm->uf_buf_posts[uf->uf_tag],
+ sizeof(struct bfi_uf_buf_post_s));
+ bfa_reqq_produce(ufm->bfa, BFA_REQQ_FCXP);
+
+ bfa_trc(ufm->bfa, uf->uf_tag);
+
+ list_add_tail(&uf->qe, &ufm->uf_posted_q);
+ return BFA_STATUS_OK;
+}
+
+static void
+bfa_uf_post_all(struct bfa_uf_mod_s *uf_mod)
+{
+ struct bfa_uf_s *uf;
+
+ while ((uf = bfa_uf_get(uf_mod)) != NULL) {
+ if (bfa_uf_post(uf_mod, uf) != BFA_STATUS_OK)
+ break;
+ }
+}
+
+static void
+uf_recv(struct bfa_s *bfa, struct bfi_uf_frm_rcvd_s *m)
+{
+ struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
+ u16 uf_tag = m->buf_tag;
+ struct bfa_uf_buf_s *uf_buf = &ufm->uf_pbs_kva[uf_tag];
+ struct bfa_uf_s *uf = &ufm->uf_list[uf_tag];
+ u8 *buf = &uf_buf->d[0];
+ struct fchs_s *fchs;
+
+ m->frm_len = bfa_os_ntohs(m->frm_len);
+ m->xfr_len = bfa_os_ntohs(m->xfr_len);
+
+ fchs = (struct fchs_s *)uf_buf;
+
+ list_del(&uf->qe); /* dequeue from posted queue */
+
+ uf->data_ptr = buf;
+ uf->data_len = m->xfr_len;
+
+ bfa_assert(uf->data_len >= sizeof(struct fchs_s));
+
+ if (uf->data_len == sizeof(struct fchs_s)) {
+ bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_UF, BFA_PL_EID_RX,
+ uf->data_len, (struct fchs_s *)buf);
+ } else {
+ u32 pld_w0 = *((u32 *) (buf + sizeof(struct fchs_s)));
+ bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_UF,
+ BFA_PL_EID_RX, uf->data_len,
+ (struct fchs_s *)buf, pld_w0);
+ }
+
+ if (bfa->fcs)
+ __bfa_cb_uf_recv(uf, BFA_TRUE);
+ else
+ bfa_cb_queue(bfa, &uf->hcb_qe, __bfa_cb_uf_recv, uf);
+}
+
+static void
+bfa_uf_stop(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_uf_iocdisable(struct bfa_s *bfa)
+{
+ struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
+ struct bfa_uf_s *uf;
+ struct list_head *qe, *qen;
+
+ list_for_each_safe(qe, qen, &ufm->uf_posted_q) {
+ uf = (struct bfa_uf_s *) qe;
+ list_del(&uf->qe);
+ bfa_uf_put(ufm, uf);
+ }
+}
+
+static void
+bfa_uf_start(struct bfa_s *bfa)
+{
+ bfa_uf_post_all(BFA_UF_MOD(bfa));
+}
+
+
+
+/**
+ * hal_uf_api
+ */
+
+/**
+ * Register handler for all unsolicted recieve frames.
+ *
+ * @param[in] bfa BFA instance
+ * @param[in] ufrecv receive handler function
+ * @param[in] cbarg receive handler arg
+ */
+void
+bfa_uf_recv_register(struct bfa_s *bfa, bfa_cb_uf_recv_t ufrecv, void *cbarg)
+{
+ struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
+
+ ufm->ufrecv = ufrecv;
+ ufm->cbarg = cbarg;
+}
+
+/**
+ * Free an unsolicited frame back to BFA.
+ *
+ * @param[in] uf unsolicited frame to be freed
+ *
+ * @return None
+ */
+void
+bfa_uf_free(struct bfa_uf_s *uf)
+{
+ bfa_uf_put(BFA_UF_MOD(uf->bfa), uf);
+ bfa_uf_post_all(BFA_UF_MOD(uf->bfa));
+}
+
+
+
+/**
+ * uf_pub BFA uf module public functions
+ */
+void
+bfa_uf_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
+{
+ bfa_trc(bfa, msg->mhdr.msg_id);
+
+ switch (msg->mhdr.msg_id) {
+ case BFI_UF_I2H_FRM_RCVD:
+ uf_recv(bfa, (struct bfi_uf_frm_rcvd_s *) msg);
+ break;
+
+ default:
+ bfa_trc(bfa, msg->mhdr.msg_id);
+ bfa_assert(0);
+ }
+}
+
+
diff --git a/drivers/scsi/bfa/bfa_svc.h b/drivers/scsi/bfa/bfa_svc.h
new file mode 100644
index 000000000000..9921dad0d039
--- /dev/null
+++ b/drivers/scsi/bfa/bfa_svc.h
@@ -0,0 +1,657 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFA_SVC_H__
+#define __BFA_SVC_H__
+
+#include "bfa_cs.h"
+#include "bfi_ms.h"
+
+
+/**
+ * Scatter-gather DMA related defines
+ */
+#define BFA_SGPG_MIN (16)
+
+/**
+ * Alignment macro for SG page allocation
+ */
+#define BFA_SGPG_ROUNDUP(_l) (((_l) + (sizeof(struct bfi_sgpg_s) - 1)) \
+ & ~(sizeof(struct bfi_sgpg_s) - 1))
+
+struct bfa_sgpg_wqe_s {
+ struct list_head qe; /* queue sg page element */
+ int nsgpg; /* pages to be allocated */
+ int nsgpg_total; /* total pages required */
+ void (*cbfn) (void *cbarg); /* callback function */
+ void *cbarg; /* callback arg */
+ struct list_head sgpg_q; /* queue of alloced sgpgs */
+};
+
+struct bfa_sgpg_s {
+ struct list_head qe; /* queue sg page element */
+ struct bfi_sgpg_s *sgpg; /* va of SG page */
+ union bfi_addr_u sgpg_pa; /* pa of SG page */
+};
+
+/**
+ * Given number of SG elements, BFA_SGPG_NPAGE() returns the number of
+ * SG pages required.
+ */
+#define BFA_SGPG_NPAGE(_nsges) (((_nsges) / BFI_SGPG_DATA_SGES) + 1)
+
+struct bfa_sgpg_mod_s {
+ struct bfa_s *bfa;
+ int num_sgpgs; /* number of SG pages */
+ int free_sgpgs; /* number of free SG pages */
+ struct bfa_sgpg_s *hsgpg_arr; /* BFA SG page array */
+ struct bfi_sgpg_s *sgpg_arr; /* actual SG page array */
+ u64 sgpg_arr_pa; /* SG page array DMA addr */
+ struct list_head sgpg_q; /* queue of free SG pages */
+ struct list_head sgpg_wait_q; /* wait queue for SG pages */
+};
+#define BFA_SGPG_MOD(__bfa) (&(__bfa)->modules.sgpg_mod)
+
+bfa_status_t bfa_sgpg_malloc(struct bfa_s *bfa, struct list_head *sgpg_q,
+ int nsgpgs);
+void bfa_sgpg_mfree(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpgs);
+void bfa_sgpg_winit(struct bfa_sgpg_wqe_s *wqe,
+ void (*cbfn) (void *cbarg), void *cbarg);
+void bfa_sgpg_wait(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe, int nsgpgs);
+void bfa_sgpg_wcancel(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe);
+
+
+/**
+ * FCXP related defines
+ */
+#define BFA_FCXP_MIN (1)
+#define BFA_FCXP_MAX_IBUF_SZ (2 * 1024 + 256)
+#define BFA_FCXP_MAX_LBUF_SZ (4 * 1024 + 256)
+
+struct bfa_fcxp_mod_s {
+ struct bfa_s *bfa; /* backpointer to BFA */
+ struct bfa_fcxp_s *fcxp_list; /* array of FCXPs */
+ u16 num_fcxps; /* max num FCXP requests */
+ struct list_head fcxp_free_q; /* free FCXPs */
+ struct list_head fcxp_active_q; /* active FCXPs */
+ void *req_pld_list_kva; /* list of FCXP req pld */
+ u64 req_pld_list_pa; /* list of FCXP req pld */
+ void *rsp_pld_list_kva; /* list of FCXP resp pld */
+ u64 rsp_pld_list_pa; /* list of FCXP resp pld */
+ struct list_head wait_q; /* wait queue for free fcxp */
+ u32 req_pld_sz;
+ u32 rsp_pld_sz;
+};
+
+#define BFA_FCXP_MOD(__bfa) (&(__bfa)->modules.fcxp_mod)
+#define BFA_FCXP_FROM_TAG(__mod, __tag) (&(__mod)->fcxp_list[__tag])
+
+typedef void (*fcxp_send_cb_t) (struct bfa_s *ioc, struct bfa_fcxp_s *fcxp,
+ void *cb_arg, bfa_status_t req_status,
+ u32 rsp_len, u32 resid_len,
+ struct fchs_s *rsp_fchs);
+
+typedef u64 (*bfa_fcxp_get_sgaddr_t) (void *bfad_fcxp, int sgeid);
+typedef u32 (*bfa_fcxp_get_sglen_t) (void *bfad_fcxp, int sgeid);
+typedef void (*bfa_cb_fcxp_send_t) (void *bfad_fcxp, struct bfa_fcxp_s *fcxp,
+ void *cbarg, enum bfa_status req_status,
+ u32 rsp_len, u32 resid_len,
+ struct fchs_s *rsp_fchs);
+typedef void (*bfa_fcxp_alloc_cbfn_t) (void *cbarg, struct bfa_fcxp_s *fcxp);
+
+
+
+/**
+ * Information needed for a FCXP request
+ */
+struct bfa_fcxp_req_info_s {
+ struct bfa_rport_s *bfa_rport;
+ /** Pointer to the bfa rport that was
+ * returned from bfa_rport_create().
+ * This could be left NULL for WKA or
+ * for FCXP interactions before the
+ * rport nexus is established
+ */
+ struct fchs_s fchs; /* request FC header structure */
+ u8 cts; /* continous sequence */
+ u8 class; /* FC class for the request/response */
+ u16 max_frmsz; /* max send frame size */
+ u16 vf_id; /* vsan tag if applicable */
+ u8 lp_tag; /* lport tag */
+ u32 req_tot_len; /* request payload total length */
+};
+
+struct bfa_fcxp_rsp_info_s {
+ struct fchs_s rsp_fchs;
+ /** !< Response frame's FC header will
+ * be sent back in this field */
+ u8 rsp_timeout;
+ /** !< timeout in seconds, 0-no response
+ */
+ u8 rsvd2[3];
+ u32 rsp_maxlen; /* max response length expected */
+};
+
+struct bfa_fcxp_s {
+ struct list_head qe; /* fcxp queue element */
+ bfa_sm_t sm; /* state machine */
+ void *caller; /* driver or fcs */
+ struct bfa_fcxp_mod_s *fcxp_mod;
+ /* back pointer to fcxp mod */
+ u16 fcxp_tag; /* internal tag */
+ struct bfa_fcxp_req_info_s req_info;
+ /* request info */
+ struct bfa_fcxp_rsp_info_s rsp_info;
+ /* response info */
+ u8 use_ireqbuf; /* use internal req buf */
+ u8 use_irspbuf; /* use internal rsp buf */
+ u32 nreq_sgles; /* num request SGLEs */
+ u32 nrsp_sgles; /* num response SGLEs */
+ struct list_head req_sgpg_q; /* SG pages for request buf */
+ struct list_head req_sgpg_wqe; /* wait queue for req SG page */
+ struct list_head rsp_sgpg_q; /* SG pages for response buf */
+ struct list_head rsp_sgpg_wqe; /* wait queue for rsp SG page */
+
+ bfa_fcxp_get_sgaddr_t req_sga_cbfn;
+ /* SG elem addr user function */
+ bfa_fcxp_get_sglen_t req_sglen_cbfn;
+ /* SG elem len user function */
+ bfa_fcxp_get_sgaddr_t rsp_sga_cbfn;
+ /* SG elem addr user function */
+ bfa_fcxp_get_sglen_t rsp_sglen_cbfn;
+ /* SG elem len user function */
+ bfa_cb_fcxp_send_t send_cbfn; /* send completion callback */
+ void *send_cbarg; /* callback arg */
+ struct bfa_sge_s req_sge[BFA_FCXP_MAX_SGES];
+ /* req SG elems */
+ struct bfa_sge_s rsp_sge[BFA_FCXP_MAX_SGES];
+ /* rsp SG elems */
+ u8 rsp_status; /* comp: rsp status */
+ u32 rsp_len; /* comp: actual response len */
+ u32 residue_len; /* comp: residual rsp length */
+ struct fchs_s rsp_fchs; /* comp: response fchs */
+ struct bfa_cb_qe_s hcb_qe; /* comp: callback qelem */
+ struct bfa_reqq_wait_s reqq_wqe;
+ bfa_boolean_t reqq_waiting;
+};
+
+struct bfa_fcxp_wqe_s {
+ struct list_head qe;
+ bfa_fcxp_alloc_cbfn_t alloc_cbfn;
+ void *alloc_cbarg;
+ void *caller;
+ struct bfa_s *bfa;
+ int nreq_sgles;
+ int nrsp_sgles;
+ bfa_fcxp_get_sgaddr_t req_sga_cbfn;
+ bfa_fcxp_get_sglen_t req_sglen_cbfn;
+ bfa_fcxp_get_sgaddr_t rsp_sga_cbfn;
+ bfa_fcxp_get_sglen_t rsp_sglen_cbfn;
+};
+
+#define BFA_FCXP_REQ_PLD(_fcxp) (bfa_fcxp_get_reqbuf(_fcxp))
+#define BFA_FCXP_RSP_FCHS(_fcxp) (&((_fcxp)->rsp_info.fchs))
+#define BFA_FCXP_RSP_PLD(_fcxp) (bfa_fcxp_get_rspbuf(_fcxp))
+
+#define BFA_FCXP_REQ_PLD_PA(_fcxp) \
+ ((_fcxp)->fcxp_mod->req_pld_list_pa + \
+ ((_fcxp)->fcxp_mod->req_pld_sz * (_fcxp)->fcxp_tag))
+
+#define BFA_FCXP_RSP_PLD_PA(_fcxp) \
+ ((_fcxp)->fcxp_mod->rsp_pld_list_pa + \
+ ((_fcxp)->fcxp_mod->rsp_pld_sz * (_fcxp)->fcxp_tag))
+
+void bfa_fcxp_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
+
+
+/**
+ * RPORT related defines
+ */
+#define BFA_RPORT_MIN 4
+
+struct bfa_rport_mod_s {
+ struct bfa_rport_s *rps_list; /* list of rports */
+ struct list_head rp_free_q; /* free bfa_rports */
+ struct list_head rp_active_q; /* free bfa_rports */
+ u16 num_rports; /* number of rports */
+};
+
+#define BFA_RPORT_MOD(__bfa) (&(__bfa)->modules.rport_mod)
+
+/**
+ * Convert rport tag to RPORT
+ */
+#define BFA_RPORT_FROM_TAG(__bfa, _tag) \
+ (BFA_RPORT_MOD(__bfa)->rps_list + \
+ ((_tag) & (BFA_RPORT_MOD(__bfa)->num_rports - 1)))
+
+/*
+ * protected functions
+ */
+void bfa_rport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
+
+/**
+ * BFA rport information.
+ */
+struct bfa_rport_info_s {
+ u16 max_frmsz; /* max rcv pdu size */
+ u32 pid:24, /* remote port ID */
+ lp_tag:8; /* tag */
+ u32 local_pid:24, /* local port ID */
+ cisc:8; /* CIRO supported */
+ u8 fc_class; /* supported FC classes. enum fc_cos */
+ u8 vf_en; /* virtual fabric enable */
+ u16 vf_id; /* virtual fabric ID */
+ enum bfa_port_speed speed; /* Rport's current speed */
+};
+
+/**
+ * BFA rport data structure
+ */
+struct bfa_rport_s {
+ struct list_head qe; /* queue element */
+ bfa_sm_t sm; /* state machine */
+ struct bfa_s *bfa; /* backpointer to BFA */
+ void *rport_drv; /* fcs/driver rport object */
+ u16 fw_handle; /* firmware rport handle */
+ u16 rport_tag; /* BFA rport tag */
+ struct bfa_rport_info_s rport_info; /* rport info from fcs/driver */
+ struct bfa_reqq_wait_s reqq_wait; /* to wait for room in reqq */
+ struct bfa_cb_qe_s hcb_qe; /* BFA callback qelem */
+ struct bfa_rport_hal_stats_s stats; /* BFA rport statistics */
+ struct bfa_rport_qos_attr_s qos_attr;
+ union a {
+ bfa_status_t status; /* f/w status */
+ void *fw_msg; /* QoS scn event */
+ } event_arg;
+};
+#define BFA_RPORT_FC_COS(_rport) ((_rport)->rport_info.fc_class)
+
+
+/**
+ * UF - unsolicited receive related defines
+ */
+
+#define BFA_UF_MIN (4)
+
+
+struct bfa_uf_s {
+ struct list_head qe; /* queue element */
+ struct bfa_s *bfa; /* bfa instance */
+ u16 uf_tag; /* identifying tag fw msgs */
+ u16 vf_id;
+ u16 src_rport_handle;
+ u16 rsvd;
+ u8 *data_ptr;
+ u16 data_len; /* actual receive length */
+ u16 pb_len; /* posted buffer length */
+ void *buf_kva; /* buffer virtual address */
+ u64 buf_pa; /* buffer physical address */
+ struct bfa_cb_qe_s hcb_qe; /* comp: BFA comp qelem */
+ struct bfa_sge_s sges[BFI_SGE_INLINE_MAX];
+};
+
+/**
+ * Callback prototype for unsolicited frame receive handler.
+ *
+ * @param[in] cbarg callback arg for receive handler
+ * @param[in] uf unsolicited frame descriptor
+ *
+ * @return None
+ */
+typedef void (*bfa_cb_uf_recv_t) (void *cbarg, struct bfa_uf_s *uf);
+
+struct bfa_uf_mod_s {
+ struct bfa_s *bfa; /* back pointer to BFA */
+ struct bfa_uf_s *uf_list; /* array of UFs */
+ u16 num_ufs; /* num unsolicited rx frames */
+ struct list_head uf_free_q; /* free UFs */
+ struct list_head uf_posted_q; /* UFs posted to IOC */
+ struct bfa_uf_buf_s *uf_pbs_kva; /* list UF bufs request pld */
+ u64 uf_pbs_pa; /* phy addr for UF bufs */
+ struct bfi_uf_buf_post_s *uf_buf_posts;
+ /* pre-built UF post msgs */
+ bfa_cb_uf_recv_t ufrecv; /* uf recv handler function */
+ void *cbarg; /* uf receive handler arg */
+};
+
+#define BFA_UF_MOD(__bfa) (&(__bfa)->modules.uf_mod)
+
+#define ufm_pbs_pa(_ufmod, _uftag) \
+ ((_ufmod)->uf_pbs_pa + sizeof(struct bfa_uf_buf_s) * (_uftag))
+
+void bfa_uf_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
+
+#define BFA_UF_BUFSZ (2 * 1024 + 256)
+
+/**
+ * @todo private
+ */
+struct bfa_uf_buf_s {
+ u8 d[BFA_UF_BUFSZ];
+};
+
+
+/**
+ * LPS - bfa lport login/logout service interface
+ */
+struct bfa_lps_s {
+ struct list_head qe; /* queue element */
+ struct bfa_s *bfa; /* parent bfa instance */
+ bfa_sm_t sm; /* finite state machine */
+ u8 lp_tag; /* lport tag */
+ u8 reqq; /* lport request queue */
+ u8 alpa; /* ALPA for loop topologies */
+ u32 lp_pid; /* lport port ID */
+ bfa_boolean_t fdisc; /* snd FDISC instead of FLOGI */
+ bfa_boolean_t auth_en; /* enable authentication */
+ bfa_boolean_t auth_req; /* authentication required */
+ bfa_boolean_t npiv_en; /* NPIV is allowed by peer */
+ bfa_boolean_t fport; /* attached peer is F_PORT */
+ bfa_boolean_t brcd_switch; /* attached peer is brcd sw */
+ bfa_status_t status; /* login status */
+ u16 pdusz; /* max receive PDU size */
+ u16 pr_bbcred; /* BB_CREDIT from peer */
+ u8 lsrjt_rsn; /* LSRJT reason */
+ u8 lsrjt_expl; /* LSRJT explanation */
+ wwn_t pwwn; /* port wwn of lport */
+ wwn_t nwwn; /* node wwn of lport */
+ wwn_t pr_pwwn; /* port wwn of lport peer */
+ wwn_t pr_nwwn; /* node wwn of lport peer */
+ mac_t lp_mac; /* fpma/spma MAC for lport */
+ mac_t fcf_mac; /* FCF MAC of lport */
+ struct bfa_reqq_wait_s wqe; /* request wait queue element */
+ void *uarg; /* user callback arg */
+ struct bfa_cb_qe_s hcb_qe; /* comp: callback qelem */
+ struct bfi_lps_login_rsp_s *loginrsp;
+ bfa_eproto_status_t ext_status;
+};
+
+struct bfa_lps_mod_s {
+ struct list_head lps_free_q;
+ struct list_head lps_active_q;
+ struct bfa_lps_s *lps_arr;
+ int num_lps;
+};
+
+#define BFA_LPS_MOD(__bfa) (&(__bfa)->modules.lps_mod)
+#define BFA_LPS_FROM_TAG(__mod, __tag) (&(__mod)->lps_arr[__tag])
+
+/*
+ * external functions
+ */
+void bfa_lps_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
+
+
+/**
+ * FCPORT related defines
+ */
+
+#define BFA_FCPORT(_bfa) (&((_bfa)->modules.port))
+typedef void (*bfa_cb_port_t) (void *cbarg, enum bfa_status status);
+
+/**
+ * Link notification data structure
+ */
+struct bfa_fcport_ln_s {
+ struct bfa_fcport_s *fcport;
+ bfa_sm_t sm;
+ struct bfa_cb_qe_s ln_qe; /* BFA callback queue elem for ln */
+ enum bfa_port_linkstate ln_event; /* ln event for callback */
+};
+
+struct bfa_fcport_trunk_s {
+ struct bfa_trunk_attr_s attr;
+};
+
+/**
+ * BFA FC port data structure
+ */
+struct bfa_fcport_s {
+ struct bfa_s *bfa; /* parent BFA instance */
+ bfa_sm_t sm; /* port state machine */
+ wwn_t nwwn; /* node wwn of physical port */
+ wwn_t pwwn; /* port wwn of physical oprt */
+ enum bfa_port_speed speed_sup;
+ /* supported speeds */
+ enum bfa_port_speed speed; /* current speed */
+ enum bfa_port_topology topology; /* current topology */
+ u8 myalpa; /* my ALPA in LOOP topology */
+ u8 rsvd[3];
+ struct bfa_port_cfg_s cfg; /* current port configuration */
+ struct bfa_qos_attr_s qos_attr; /* QoS Attributes */
+ struct bfa_qos_vc_attr_s qos_vc_attr; /* VC info from ELP */
+ struct bfa_reqq_wait_s reqq_wait;
+ /* to wait for room in reqq */
+ struct bfa_reqq_wait_s svcreq_wait;
+ /* to wait for room in reqq */
+ struct bfa_reqq_wait_s stats_reqq_wait;
+ /* to wait for room in reqq (stats) */
+ void *event_cbarg;
+ void (*event_cbfn) (void *cbarg,
+ enum bfa_port_linkstate event);
+ union {
+ union bfi_fcport_i2h_msg_u i2hmsg;
+ } event_arg;
+ void *bfad; /* BFA driver handle */
+ struct bfa_fcport_ln_s ln; /* Link Notification */
+ struct bfa_cb_qe_s hcb_qe; /* BFA callback queue elem */
+ struct bfa_timer_s timer; /* timer */
+ u32 msgtag; /* fimrware msg tag for reply */
+ u8 *stats_kva;
+ u64 stats_pa;
+ union bfa_fcport_stats_u *stats;
+ union bfa_fcport_stats_u *stats_ret; /* driver stats location */
+ bfa_status_t stats_status; /* stats/statsclr status */
+ bfa_boolean_t stats_busy; /* outstanding stats/statsclr */
+ bfa_boolean_t stats_qfull;
+ u32 stats_reset_time; /* stats reset time stamp */
+ bfa_cb_port_t stats_cbfn; /* driver callback function */
+ void *stats_cbarg; /* *!< user callback arg */
+ bfa_boolean_t diag_busy; /* diag busy status */
+ bfa_boolean_t beacon; /* port beacon status */
+ bfa_boolean_t link_e2e_beacon; /* link beacon status */
+ struct bfa_fcport_trunk_s trunk;
+ u16 fcoe_vlan;
+};
+
+#define BFA_FCPORT_MOD(__bfa) (&(__bfa)->modules.fcport)
+
+/*
+ * protected functions
+ */
+void bfa_fcport_init(struct bfa_s *bfa);
+void bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
+
+/*
+ * bfa fcport API functions
+ */
+bfa_status_t bfa_fcport_enable(struct bfa_s *bfa);
+bfa_status_t bfa_fcport_disable(struct bfa_s *bfa);
+bfa_status_t bfa_fcport_cfg_speed(struct bfa_s *bfa,
+ enum bfa_port_speed speed);
+enum bfa_port_speed bfa_fcport_get_speed(struct bfa_s *bfa);
+bfa_status_t bfa_fcport_cfg_topology(struct bfa_s *bfa,
+ enum bfa_port_topology topo);
+enum bfa_port_topology bfa_fcport_get_topology(struct bfa_s *bfa);
+bfa_status_t bfa_fcport_cfg_hardalpa(struct bfa_s *bfa, u8 alpa);
+bfa_boolean_t bfa_fcport_get_hardalpa(struct bfa_s *bfa, u8 *alpa);
+u8 bfa_fcport_get_myalpa(struct bfa_s *bfa);
+bfa_status_t bfa_fcport_clr_hardalpa(struct bfa_s *bfa);
+bfa_status_t bfa_fcport_cfg_maxfrsize(struct bfa_s *bfa, u16 maxsize);
+u16 bfa_fcport_get_maxfrsize(struct bfa_s *bfa);
+u8 bfa_fcport_get_rx_bbcredit(struct bfa_s *bfa);
+void bfa_fcport_get_attr(struct bfa_s *bfa, struct bfa_port_attr_s *attr);
+wwn_t bfa_fcport_get_wwn(struct bfa_s *bfa, bfa_boolean_t node);
+void bfa_fcport_event_register(struct bfa_s *bfa,
+ void (*event_cbfn) (void *cbarg,
+ enum bfa_port_linkstate event), void *event_cbarg);
+bfa_boolean_t bfa_fcport_is_disabled(struct bfa_s *bfa);
+void bfa_fcport_cfg_qos(struct bfa_s *bfa, bfa_boolean_t on_off);
+void bfa_fcport_cfg_ratelim(struct bfa_s *bfa, bfa_boolean_t on_off);
+bfa_status_t bfa_fcport_cfg_ratelim_speed(struct bfa_s *bfa,
+ enum bfa_port_speed speed);
+enum bfa_port_speed bfa_fcport_get_ratelim_speed(struct bfa_s *bfa);
+
+void bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit);
+void bfa_fcport_busy(struct bfa_s *bfa, bfa_boolean_t status);
+void bfa_fcport_beacon(void *dev, bfa_boolean_t beacon,
+ bfa_boolean_t link_e2e_beacon);
+void bfa_fcport_qos_get_attr(struct bfa_s *bfa,
+ struct bfa_qos_attr_s *qos_attr);
+void bfa_fcport_qos_get_vc_attr(struct bfa_s *bfa,
+ struct bfa_qos_vc_attr_s *qos_vc_attr);
+bfa_status_t bfa_fcport_get_qos_stats(struct bfa_s *bfa,
+ union bfa_fcport_stats_u *stats,
+ bfa_cb_port_t cbfn, void *cbarg);
+bfa_status_t bfa_fcport_clear_qos_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn,
+ void *cbarg);
+bfa_status_t bfa_fcport_get_fcoe_stats(struct bfa_s *bfa,
+ union bfa_fcport_stats_u *stats,
+ bfa_cb_port_t cbfn, void *cbarg);
+bfa_status_t bfa_fcport_clear_fcoe_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn,
+ void *cbarg);
+bfa_boolean_t bfa_fcport_is_ratelim(struct bfa_s *bfa);
+bfa_boolean_t bfa_fcport_is_linkup(struct bfa_s *bfa);
+bfa_status_t bfa_fcport_get_stats(struct bfa_s *bfa,
+ union bfa_fcport_stats_u *stats,
+ bfa_cb_port_t cbfn, void *cbarg);
+bfa_status_t bfa_fcport_clear_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn,
+ void *cbarg);
+bfa_boolean_t bfa_fcport_is_qos_enabled(struct bfa_s *bfa);
+
+/*
+ * bfa rport API functions
+ */
+struct bfa_rport_s *bfa_rport_create(struct bfa_s *bfa, void *rport_drv);
+void bfa_rport_delete(struct bfa_rport_s *rport);
+void bfa_rport_online(struct bfa_rport_s *rport,
+ struct bfa_rport_info_s *rport_info);
+void bfa_rport_offline(struct bfa_rport_s *rport);
+void bfa_rport_speed(struct bfa_rport_s *rport, enum bfa_port_speed speed);
+void bfa_rport_get_stats(struct bfa_rport_s *rport,
+ struct bfa_rport_hal_stats_s *stats);
+void bfa_rport_clear_stats(struct bfa_rport_s *rport);
+void bfa_cb_rport_online(void *rport);
+void bfa_cb_rport_offline(void *rport);
+void bfa_cb_rport_qos_scn_flowid(void *rport,
+ struct bfa_rport_qos_attr_s old_qos_attr,
+ struct bfa_rport_qos_attr_s new_qos_attr);
+void bfa_cb_rport_qos_scn_prio(void *rport,
+ struct bfa_rport_qos_attr_s old_qos_attr,
+ struct bfa_rport_qos_attr_s new_qos_attr);
+void bfa_rport_get_qos_attr(struct bfa_rport_s *rport,
+ struct bfa_rport_qos_attr_s *qos_attr);
+
+/*
+ * bfa fcxp API functions
+ */
+struct bfa_fcxp_s *bfa_fcxp_alloc(void *bfad_fcxp, struct bfa_s *bfa,
+ int nreq_sgles, int nrsp_sgles,
+ bfa_fcxp_get_sgaddr_t get_req_sga,
+ bfa_fcxp_get_sglen_t get_req_sglen,
+ bfa_fcxp_get_sgaddr_t get_rsp_sga,
+ bfa_fcxp_get_sglen_t get_rsp_sglen);
+void bfa_fcxp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe,
+ bfa_fcxp_alloc_cbfn_t alloc_cbfn,
+ void *cbarg, void *bfad_fcxp,
+ int nreq_sgles, int nrsp_sgles,
+ bfa_fcxp_get_sgaddr_t get_req_sga,
+ bfa_fcxp_get_sglen_t get_req_sglen,
+ bfa_fcxp_get_sgaddr_t get_rsp_sga,
+ bfa_fcxp_get_sglen_t get_rsp_sglen);
+void bfa_fcxp_walloc_cancel(struct bfa_s *bfa,
+ struct bfa_fcxp_wqe_s *wqe);
+void bfa_fcxp_discard(struct bfa_fcxp_s *fcxp);
+
+void *bfa_fcxp_get_reqbuf(struct bfa_fcxp_s *fcxp);
+void *bfa_fcxp_get_rspbuf(struct bfa_fcxp_s *fcxp);
+
+void bfa_fcxp_free(struct bfa_fcxp_s *fcxp);
+
+void bfa_fcxp_send(struct bfa_fcxp_s *fcxp, struct bfa_rport_s *rport,
+ u16 vf_id, u8 lp_tag,
+ bfa_boolean_t cts, enum fc_cos cos,
+ u32 reqlen, struct fchs_s *fchs,
+ bfa_cb_fcxp_send_t cbfn,
+ void *cbarg,
+ u32 rsp_maxlen, u8 rsp_timeout);
+bfa_status_t bfa_fcxp_abort(struct bfa_fcxp_s *fcxp);
+u32 bfa_fcxp_get_reqbufsz(struct bfa_fcxp_s *fcxp);
+u32 bfa_fcxp_get_maxrsp(struct bfa_s *bfa);
+
+static inline void *
+bfa_uf_get_frmbuf(struct bfa_uf_s *uf)
+{
+ return uf->data_ptr;
+}
+
+static inline u16
+bfa_uf_get_frmlen(struct bfa_uf_s *uf)
+{
+ return uf->data_len;
+}
+
+/*
+ * bfa uf API functions
+ */
+void bfa_uf_recv_register(struct bfa_s *bfa, bfa_cb_uf_recv_t ufrecv,
+ void *cbarg);
+void bfa_uf_free(struct bfa_uf_s *uf);
+
+/**
+ * bfa lport service api
+ */
+
+u32 bfa_lps_get_max_vport(struct bfa_s *bfa);
+struct bfa_lps_s *bfa_lps_alloc(struct bfa_s *bfa);
+void bfa_lps_delete(struct bfa_lps_s *lps);
+void bfa_lps_discard(struct bfa_lps_s *lps);
+void bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa,
+ u16 pdusz, wwn_t pwwn, wwn_t nwwn,
+ bfa_boolean_t auth_en);
+void bfa_lps_fdisc(struct bfa_lps_s *lps, void *uarg, u16 pdusz,
+ wwn_t pwwn, wwn_t nwwn);
+void bfa_lps_flogo(struct bfa_lps_s *lps);
+void bfa_lps_fdisclogo(struct bfa_lps_s *lps);
+u8 bfa_lps_get_tag(struct bfa_lps_s *lps);
+bfa_boolean_t bfa_lps_is_npiv_en(struct bfa_lps_s *lps);
+bfa_boolean_t bfa_lps_is_fport(struct bfa_lps_s *lps);
+bfa_boolean_t bfa_lps_is_brcd_fabric(struct bfa_lps_s *lps);
+bfa_boolean_t bfa_lps_is_authreq(struct bfa_lps_s *lps);
+bfa_eproto_status_t bfa_lps_get_extstatus(struct bfa_lps_s *lps);
+u32 bfa_lps_get_pid(struct bfa_lps_s *lps);
+u32 bfa_lps_get_base_pid(struct bfa_s *bfa);
+u8 bfa_lps_get_tag_from_pid(struct bfa_s *bfa, u32 pid);
+u16 bfa_lps_get_peer_bbcredit(struct bfa_lps_s *lps);
+wwn_t bfa_lps_get_peer_pwwn(struct bfa_lps_s *lps);
+wwn_t bfa_lps_get_peer_nwwn(struct bfa_lps_s *lps);
+u8 bfa_lps_get_lsrjt_rsn(struct bfa_lps_s *lps);
+u8 bfa_lps_get_lsrjt_expl(struct bfa_lps_s *lps);
+mac_t bfa_lps_get_lp_mac(struct bfa_lps_s *lps);
+void bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status);
+void bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status);
+void bfa_cb_lps_fdisclogo_comp(void *bfad, void *uarg);
+void bfa_cb_lps_cvl_event(void *bfad, void *uarg);
+
+void bfa_trunk_enable_cfg(struct bfa_s *bfa);
+bfa_status_t bfa_trunk_enable(struct bfa_s *bfa);
+bfa_status_t bfa_trunk_disable(struct bfa_s *bfa);
+bfa_status_t bfa_trunk_get_attr(struct bfa_s *bfa,
+ struct bfa_trunk_attr_s *attr);
+
+#endif /* __BFA_SVC_H__ */
diff --git a/drivers/scsi/bfa/bfa_timer.c b/drivers/scsi/bfa/bfa_timer.c
deleted file mode 100644
index cb76481f5cb1..000000000000
--- a/drivers/scsi/bfa/bfa_timer.c
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#include <bfa_timer.h>
-#include <cs/bfa_debug.h>
-
-void
-bfa_timer_init(struct bfa_timer_mod_s *mod)
-{
- INIT_LIST_HEAD(&mod->timer_q);
-}
-
-void
-bfa_timer_beat(struct bfa_timer_mod_s *mod)
-{
- struct list_head *qh = &mod->timer_q;
- struct list_head *qe, *qe_next;
- struct bfa_timer_s *elem;
- struct list_head timedout_q;
-
- INIT_LIST_HEAD(&timedout_q);
-
- qe = bfa_q_next(qh);
-
- while (qe != qh) {
- qe_next = bfa_q_next(qe);
-
- elem = (struct bfa_timer_s *) qe;
- if (elem->timeout <= BFA_TIMER_FREQ) {
- elem->timeout = 0;
- list_del(&elem->qe);
- list_add_tail(&elem->qe, &timedout_q);
- } else {
- elem->timeout -= BFA_TIMER_FREQ;
- }
-
- qe = qe_next; /* go to next elem */
- }
-
- /*
- * Pop all the timeout entries
- */
- while (!list_empty(&timedout_q)) {
- bfa_q_deq(&timedout_q, &elem);
- elem->timercb(elem->arg);
- }
-}
-
-/**
- * Should be called with lock protection
- */
-void
-bfa_timer_begin(struct bfa_timer_mod_s *mod, struct bfa_timer_s *timer,
- void (*timercb) (void *), void *arg, unsigned int timeout)
-{
-
- bfa_assert(timercb != NULL);
- bfa_assert(!bfa_q_is_on_q(&mod->timer_q, timer));
-
- timer->timeout = timeout;
- timer->timercb = timercb;
- timer->arg = arg;
-
- list_add_tail(&timer->qe, &mod->timer_q);
-}
-
-/**
- * Should be called with lock protection
- */
-void
-bfa_timer_stop(struct bfa_timer_s *timer)
-{
- bfa_assert(!list_empty(&timer->qe));
-
- list_del(&timer->qe);
-}
diff --git a/drivers/scsi/bfa/bfa_trcmod_priv.h b/drivers/scsi/bfa/bfa_trcmod_priv.h
deleted file mode 100644
index a7a82610db85..000000000000
--- a/drivers/scsi/bfa/bfa_trcmod_priv.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/**
- * hal_trcmod.h BFA trace modules
- */
-
-#ifndef __BFA_TRCMOD_PRIV_H__
-#define __BFA_TRCMOD_PRIV_H__
-
-#include <cs/bfa_trc.h>
-
-/*
- * !!! Only append to the enums defined here to avoid any versioning
- * !!! needed between trace utility and driver version
- */
-enum {
- BFA_TRC_HAL_INTR = 1,
- BFA_TRC_HAL_FCXP = 2,
- BFA_TRC_HAL_UF = 3,
- BFA_TRC_HAL_RPORT = 4,
- BFA_TRC_HAL_FCPIM = 5,
- BFA_TRC_HAL_IOIM = 6,
- BFA_TRC_HAL_TSKIM = 7,
- BFA_TRC_HAL_ITNIM = 8,
- BFA_TRC_HAL_FCPORT = 9,
- BFA_TRC_HAL_SGPG = 10,
- BFA_TRC_HAL_FLASH = 11,
- BFA_TRC_HAL_DEBUG = 12,
- BFA_TRC_HAL_WWN = 13,
- BFA_TRC_HAL_FLASH_RAW = 14,
- BFA_TRC_HAL_SBOOT = 15,
- BFA_TRC_HAL_SBOOT_IO = 16,
- BFA_TRC_HAL_SBOOT_INTR = 17,
- BFA_TRC_HAL_SBTEST = 18,
- BFA_TRC_HAL_IPFC = 19,
- BFA_TRC_HAL_IOCFC = 20,
- BFA_TRC_HAL_FCPTM = 21,
- BFA_TRC_HAL_IOTM = 22,
- BFA_TRC_HAL_TSKTM = 23,
- BFA_TRC_HAL_TIN = 24,
- BFA_TRC_HAL_LPS = 25,
- BFA_TRC_HAL_FCDIAG = 26,
- BFA_TRC_HAL_PBIND = 27,
- BFA_TRC_HAL_IOCFC_CT = 28,
- BFA_TRC_HAL_IOCFC_CB = 29,
- BFA_TRC_HAL_IOCFC_Q = 30,
-};
-
-#endif /* __BFA_TRCMOD_PRIV_H__ */
diff --git a/drivers/scsi/bfa/bfa_tskim.c b/drivers/scsi/bfa/bfa_tskim.c
deleted file mode 100644
index ad9aaaedd3f1..000000000000
--- a/drivers/scsi/bfa/bfa_tskim.c
+++ /dev/null
@@ -1,690 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#include <bfa.h>
-#include <bfa_cb_ioim_macros.h>
-
-BFA_TRC_FILE(HAL, TSKIM);
-
-/**
- * task management completion handling
- */
-#define bfa_tskim_qcomp(__tskim, __cbfn) do { \
- bfa_cb_queue((__tskim)->bfa, &(__tskim)->hcb_qe, \
- __cbfn, (__tskim)); \
- bfa_tskim_notify_comp(__tskim); \
-} while (0)
-
-#define bfa_tskim_notify_comp(__tskim) do { \
- if ((__tskim)->notify) \
- bfa_itnim_tskdone((__tskim)->itnim); \
-} while (0)
-
-/*
- * forward declarations
- */
-static void __bfa_cb_tskim_done(void *cbarg, bfa_boolean_t complete);
-static void __bfa_cb_tskim_failed(void *cbarg, bfa_boolean_t complete);
-static bfa_boolean_t bfa_tskim_match_scope(struct bfa_tskim_s *tskim,
- lun_t lun);
-static void bfa_tskim_gather_ios(struct bfa_tskim_s *tskim);
-static void bfa_tskim_cleanp_comp(void *tskim_cbarg);
-static void bfa_tskim_cleanup_ios(struct bfa_tskim_s *tskim);
-static bfa_boolean_t bfa_tskim_send(struct bfa_tskim_s *tskim);
-static bfa_boolean_t bfa_tskim_send_abort(struct bfa_tskim_s *tskim);
-static void bfa_tskim_iocdisable_ios(struct bfa_tskim_s *tskim);
-
-/**
- * bfa_tskim_sm
- */
-
-enum bfa_tskim_event {
- BFA_TSKIM_SM_START = 1, /* TM command start */
- BFA_TSKIM_SM_DONE = 2, /* TM completion */
- BFA_TSKIM_SM_QRESUME = 3, /* resume after qfull */
- BFA_TSKIM_SM_HWFAIL = 5, /* IOC h/w failure event */
- BFA_TSKIM_SM_HCB = 6, /* BFA callback completion */
- BFA_TSKIM_SM_IOS_DONE = 7, /* IO and sub TM completions */
- BFA_TSKIM_SM_CLEANUP = 8, /* TM cleanup on ITN offline */
- BFA_TSKIM_SM_CLEANUP_DONE = 9, /* TM abort completion */
-};
-
-static void bfa_tskim_sm_uninit(struct bfa_tskim_s *tskim,
- enum bfa_tskim_event event);
-static void bfa_tskim_sm_active(struct bfa_tskim_s *tskim,
- enum bfa_tskim_event event);
-static void bfa_tskim_sm_cleanup(struct bfa_tskim_s *tskim,
- enum bfa_tskim_event event);
-static void bfa_tskim_sm_iocleanup(struct bfa_tskim_s *tskim,
- enum bfa_tskim_event event);
-static void bfa_tskim_sm_qfull(struct bfa_tskim_s *tskim,
- enum bfa_tskim_event event);
-static void bfa_tskim_sm_cleanup_qfull(struct bfa_tskim_s *tskim,
- enum bfa_tskim_event event);
-static void bfa_tskim_sm_hcb(struct bfa_tskim_s *tskim,
- enum bfa_tskim_event event);
-
-/**
- * Task management command beginning state.
- */
-static void
-bfa_tskim_sm_uninit(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
-{
- bfa_trc(tskim->bfa, event);
-
- switch (event) {
- case BFA_TSKIM_SM_START:
- bfa_sm_set_state(tskim, bfa_tskim_sm_active);
- bfa_tskim_gather_ios(tskim);
-
- /**
- * If device is offline, do not send TM on wire. Just cleanup
- * any pending IO requests and complete TM request.
- */
- if (!bfa_itnim_is_online(tskim->itnim)) {
- bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup);
- tskim->tsk_status = BFI_TSKIM_STS_OK;
- bfa_tskim_cleanup_ios(tskim);
- return;
- }
-
- if (!bfa_tskim_send(tskim)) {
- bfa_sm_set_state(tskim, bfa_tskim_sm_qfull);
- bfa_reqq_wait(tskim->bfa, tskim->itnim->reqq,
- &tskim->reqq_wait);
- }
- break;
-
- default:
- bfa_sm_fault(tskim->bfa, event);
- }
-}
-
-/**
- * brief
- * TM command is active, awaiting completion from firmware to
- * cleanup IO requests in TM scope.
- */
-static void
-bfa_tskim_sm_active(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
-{
- bfa_trc(tskim->bfa, event);
-
- switch (event) {
- case BFA_TSKIM_SM_DONE:
- bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup);
- bfa_tskim_cleanup_ios(tskim);
- break;
-
- case BFA_TSKIM_SM_CLEANUP:
- bfa_sm_set_state(tskim, bfa_tskim_sm_cleanup);
- if (!bfa_tskim_send_abort(tskim)) {
- bfa_sm_set_state(tskim, bfa_tskim_sm_cleanup_qfull);
- bfa_reqq_wait(tskim->bfa, tskim->itnim->reqq,
- &tskim->reqq_wait);
- }
- break;
-
- case BFA_TSKIM_SM_HWFAIL:
- bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
- bfa_tskim_iocdisable_ios(tskim);
- bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);
- break;
-
- default:
- bfa_sm_fault(tskim->bfa, event);
- }
-}
-
-/**
- * An active TM is being cleaned up since ITN is offline. Awaiting cleanup
- * completion event from firmware.
- */
-static void
-bfa_tskim_sm_cleanup(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
-{
- bfa_trc(tskim->bfa, event);
-
- switch (event) {
- case BFA_TSKIM_SM_DONE:
- /**
- * Ignore and wait for ABORT completion from firmware.
- */
- break;
-
- case BFA_TSKIM_SM_CLEANUP_DONE:
- bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup);
- bfa_tskim_cleanup_ios(tskim);
- break;
-
- case BFA_TSKIM_SM_HWFAIL:
- bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
- bfa_tskim_iocdisable_ios(tskim);
- bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);
- break;
-
- default:
- bfa_sm_fault(tskim->bfa, event);
- }
-}
-
-static void
-bfa_tskim_sm_iocleanup(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
-{
- bfa_trc(tskim->bfa, event);
-
- switch (event) {
- case BFA_TSKIM_SM_IOS_DONE:
- bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
- bfa_tskim_qcomp(tskim, __bfa_cb_tskim_done);
- break;
-
- case BFA_TSKIM_SM_CLEANUP:
- /**
- * Ignore, TM command completed on wire.
- * Notify TM conmpletion on IO cleanup completion.
- */
- break;
-
- case BFA_TSKIM_SM_HWFAIL:
- bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
- bfa_tskim_iocdisable_ios(tskim);
- bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);
- break;
-
- default:
- bfa_sm_fault(tskim->bfa, event);
- }
-}
-
-/**
- * Task management command is waiting for room in request CQ
- */
-static void
-bfa_tskim_sm_qfull(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
-{
- bfa_trc(tskim->bfa, event);
-
- switch (event) {
- case BFA_TSKIM_SM_QRESUME:
- bfa_sm_set_state(tskim, bfa_tskim_sm_active);
- bfa_tskim_send(tskim);
- break;
-
- case BFA_TSKIM_SM_CLEANUP:
- /**
- * No need to send TM on wire since ITN is offline.
- */
- bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup);
- bfa_reqq_wcancel(&tskim->reqq_wait);
- bfa_tskim_cleanup_ios(tskim);
- break;
-
- case BFA_TSKIM_SM_HWFAIL:
- bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
- bfa_reqq_wcancel(&tskim->reqq_wait);
- bfa_tskim_iocdisable_ios(tskim);
- bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);
- break;
-
- default:
- bfa_sm_fault(tskim->bfa, event);
- }
-}
-
-/**
- * Task management command is active, awaiting for room in request CQ
- * to send clean up request.
- */
-static void
-bfa_tskim_sm_cleanup_qfull(struct bfa_tskim_s *tskim,
- enum bfa_tskim_event event)
-{
- bfa_trc(tskim->bfa, event);
-
- switch (event) {
- case BFA_TSKIM_SM_DONE:
- bfa_reqq_wcancel(&tskim->reqq_wait);
- /**
- *
- * Fall through !!!
- */
-
- case BFA_TSKIM_SM_QRESUME:
- bfa_sm_set_state(tskim, bfa_tskim_sm_cleanup);
- bfa_tskim_send_abort(tskim);
- break;
-
- case BFA_TSKIM_SM_HWFAIL:
- bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
- bfa_reqq_wcancel(&tskim->reqq_wait);
- bfa_tskim_iocdisable_ios(tskim);
- bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);
- break;
-
- default:
- bfa_sm_fault(tskim->bfa, event);
- }
-}
-
-/**
- * BFA callback is pending
- */
-static void
-bfa_tskim_sm_hcb(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
-{
- bfa_trc(tskim->bfa, event);
-
- switch (event) {
- case BFA_TSKIM_SM_HCB:
- bfa_sm_set_state(tskim, bfa_tskim_sm_uninit);
- bfa_tskim_free(tskim);
- break;
-
- case BFA_TSKIM_SM_CLEANUP:
- bfa_tskim_notify_comp(tskim);
- break;
-
- case BFA_TSKIM_SM_HWFAIL:
- break;
-
- default:
- bfa_sm_fault(tskim->bfa, event);
- }
-}
-
-
-
-/**
- * bfa_tskim_private
- */
-
-static void
-__bfa_cb_tskim_done(void *cbarg, bfa_boolean_t complete)
-{
- struct bfa_tskim_s *tskim = cbarg;
-
- if (!complete) {
- bfa_sm_send_event(tskim, BFA_TSKIM_SM_HCB);
- return;
- }
-
- bfa_stats(tskim->itnim, tm_success);
- bfa_cb_tskim_done(tskim->bfa->bfad, tskim->dtsk, tskim->tsk_status);
-}
-
-static void
-__bfa_cb_tskim_failed(void *cbarg, bfa_boolean_t complete)
-{
- struct bfa_tskim_s *tskim = cbarg;
-
- if (!complete) {
- bfa_sm_send_event(tskim, BFA_TSKIM_SM_HCB);
- return;
- }
-
- bfa_stats(tskim->itnim, tm_failures);
- bfa_cb_tskim_done(tskim->bfa->bfad, tskim->dtsk,
- BFI_TSKIM_STS_FAILED);
-}
-
-static bfa_boolean_t
-bfa_tskim_match_scope(struct bfa_tskim_s *tskim, lun_t lun)
-{
- switch (tskim->tm_cmnd) {
- case FCP_TM_TARGET_RESET:
- return BFA_TRUE;
-
- case FCP_TM_ABORT_TASK_SET:
- case FCP_TM_CLEAR_TASK_SET:
- case FCP_TM_LUN_RESET:
- case FCP_TM_CLEAR_ACA:
- return (tskim->lun == lun);
-
- default:
- bfa_assert(0);
- }
-
- return BFA_FALSE;
-}
-
-/**
- * Gather affected IO requests and task management commands.
- */
-static void
-bfa_tskim_gather_ios(struct bfa_tskim_s *tskim)
-{
- struct bfa_itnim_s *itnim = tskim->itnim;
- struct bfa_ioim_s *ioim;
- struct list_head *qe, *qen;
-
- INIT_LIST_HEAD(&tskim->io_q);
-
- /**
- * Gather any active IO requests first.
- */
- list_for_each_safe(qe, qen, &itnim->io_q) {
- ioim = (struct bfa_ioim_s *) qe;
- if (bfa_tskim_match_scope
- (tskim, bfa_cb_ioim_get_lun(ioim->dio))) {
- list_del(&ioim->qe);
- list_add_tail(&ioim->qe, &tskim->io_q);
- }
- }
-
- /**
- * Failback any pending IO requests immediately.
- */
- list_for_each_safe(qe, qen, &itnim->pending_q) {
- ioim = (struct bfa_ioim_s *) qe;
- if (bfa_tskim_match_scope
- (tskim, bfa_cb_ioim_get_lun(ioim->dio))) {
- list_del(&ioim->qe);
- list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
- bfa_ioim_tov(ioim);
- }
- }
-}
-
-/**
- * IO cleanup completion
- */
-static void
-bfa_tskim_cleanp_comp(void *tskim_cbarg)
-{
- struct bfa_tskim_s *tskim = tskim_cbarg;
-
- bfa_stats(tskim->itnim, tm_io_comps);
- bfa_sm_send_event(tskim, BFA_TSKIM_SM_IOS_DONE);
-}
-
-/**
- * Gather affected IO requests and task management commands.
- */
-static void
-bfa_tskim_cleanup_ios(struct bfa_tskim_s *tskim)
-{
- struct bfa_ioim_s *ioim;
- struct list_head *qe, *qen;
-
- bfa_wc_init(&tskim->wc, bfa_tskim_cleanp_comp, tskim);
-
- list_for_each_safe(qe, qen, &tskim->io_q) {
- ioim = (struct bfa_ioim_s *) qe;
- bfa_wc_up(&tskim->wc);
- bfa_ioim_cleanup_tm(ioim, tskim);
- }
-
- bfa_wc_wait(&tskim->wc);
-}
-
-/**
- * Send task management request to firmware.
- */
-static bfa_boolean_t
-bfa_tskim_send(struct bfa_tskim_s *tskim)
-{
- struct bfa_itnim_s *itnim = tskim->itnim;
- struct bfi_tskim_req_s *m;
-
- /**
- * check for room in queue to send request now
- */
- m = bfa_reqq_next(tskim->bfa, itnim->reqq);
- if (!m)
- return BFA_FALSE;
-
- /**
- * build i/o request message next
- */
- bfi_h2i_set(m->mh, BFI_MC_TSKIM, BFI_TSKIM_H2I_TM_REQ,
- bfa_lpuid(tskim->bfa));
-
- m->tsk_tag = bfa_os_htons(tskim->tsk_tag);
- m->itn_fhdl = tskim->itnim->rport->fw_handle;
- m->t_secs = tskim->tsecs;
- m->lun = tskim->lun;
- m->tm_flags = tskim->tm_cmnd;
-
- /**
- * queue I/O message to firmware
- */
- bfa_reqq_produce(tskim->bfa, itnim->reqq);
- return BFA_TRUE;
-}
-
-/**
- * Send abort request to cleanup an active TM to firmware.
- */
-static bfa_boolean_t
-bfa_tskim_send_abort(struct bfa_tskim_s *tskim)
-{
- struct bfa_itnim_s *itnim = tskim->itnim;
- struct bfi_tskim_abortreq_s *m;
-
- /**
- * check for room in queue to send request now
- */
- m = bfa_reqq_next(tskim->bfa, itnim->reqq);
- if (!m)
- return BFA_FALSE;
-
- /**
- * build i/o request message next
- */
- bfi_h2i_set(m->mh, BFI_MC_TSKIM, BFI_TSKIM_H2I_ABORT_REQ,
- bfa_lpuid(tskim->bfa));
-
- m->tsk_tag = bfa_os_htons(tskim->tsk_tag);
-
- /**
- * queue I/O message to firmware
- */
- bfa_reqq_produce(tskim->bfa, itnim->reqq);
- return BFA_TRUE;
-}
-
-/**
- * Call to resume task management cmnd waiting for room in request queue.
- */
-static void
-bfa_tskim_qresume(void *cbarg)
-{
- struct bfa_tskim_s *tskim = cbarg;
-
- bfa_fcpim_stats(tskim->fcpim, qresumes);
- bfa_stats(tskim->itnim, tm_qresumes);
- bfa_sm_send_event(tskim, BFA_TSKIM_SM_QRESUME);
-}
-
-/**
- * Cleanup IOs associated with a task mangement command on IOC failures.
- */
-static void
-bfa_tskim_iocdisable_ios(struct bfa_tskim_s *tskim)
-{
- struct bfa_ioim_s *ioim;
- struct list_head *qe, *qen;
-
- list_for_each_safe(qe, qen, &tskim->io_q) {
- ioim = (struct bfa_ioim_s *) qe;
- bfa_ioim_iocdisable(ioim);
- }
-}
-
-
-
-/**
- * bfa_tskim_friend
- */
-
-/**
- * Notification on completions from related ioim.
- */
-void
-bfa_tskim_iodone(struct bfa_tskim_s *tskim)
-{
- bfa_wc_down(&tskim->wc);
-}
-
-/**
- * Handle IOC h/w failure notification from itnim.
- */
-void
-bfa_tskim_iocdisable(struct bfa_tskim_s *tskim)
-{
- tskim->notify = BFA_FALSE;
- bfa_stats(tskim->itnim, tm_iocdowns);
- bfa_sm_send_event(tskim, BFA_TSKIM_SM_HWFAIL);
-}
-
-/**
- * Cleanup TM command and associated IOs as part of ITNIM offline.
- */
-void
-bfa_tskim_cleanup(struct bfa_tskim_s *tskim)
-{
- tskim->notify = BFA_TRUE;
- bfa_stats(tskim->itnim, tm_cleanups);
- bfa_sm_send_event(tskim, BFA_TSKIM_SM_CLEANUP);
-}
-
-/**
- * Memory allocation and initialization.
- */
-void
-bfa_tskim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
-{
- struct bfa_tskim_s *tskim;
- u16 i;
-
- INIT_LIST_HEAD(&fcpim->tskim_free_q);
-
- tskim = (struct bfa_tskim_s *) bfa_meminfo_kva(minfo);
- fcpim->tskim_arr = tskim;
-
- for (i = 0; i < fcpim->num_tskim_reqs; i++, tskim++) {
- /*
- * initialize TSKIM
- */
- bfa_os_memset(tskim, 0, sizeof(struct bfa_tskim_s));
- tskim->tsk_tag = i;
- tskim->bfa = fcpim->bfa;
- tskim->fcpim = fcpim;
- tskim->notify = BFA_FALSE;
- bfa_reqq_winit(&tskim->reqq_wait, bfa_tskim_qresume,
- tskim);
- bfa_sm_set_state(tskim, bfa_tskim_sm_uninit);
-
- list_add_tail(&tskim->qe, &fcpim->tskim_free_q);
- }
-
- bfa_meminfo_kva(minfo) = (u8 *) tskim;
-}
-
-void
-bfa_tskim_detach(struct bfa_fcpim_mod_s *fcpim)
-{
- /**
- * @todo
- */
-}
-
-void
-bfa_tskim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
-{
- struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
- struct bfi_tskim_rsp_s *rsp = (struct bfi_tskim_rsp_s *) m;
- struct bfa_tskim_s *tskim;
- u16 tsk_tag = bfa_os_ntohs(rsp->tsk_tag);
-
- tskim = BFA_TSKIM_FROM_TAG(fcpim, tsk_tag);
- bfa_assert(tskim->tsk_tag == tsk_tag);
-
- tskim->tsk_status = rsp->tsk_status;
-
- /**
- * Firmware sends BFI_TSKIM_STS_ABORTED status for abort
- * requests. All other statuses are for normal completions.
- */
- if (rsp->tsk_status == BFI_TSKIM_STS_ABORTED) {
- bfa_stats(tskim->itnim, tm_cleanup_comps);
- bfa_sm_send_event(tskim, BFA_TSKIM_SM_CLEANUP_DONE);
- } else {
- bfa_stats(tskim->itnim, tm_fw_rsps);
- bfa_sm_send_event(tskim, BFA_TSKIM_SM_DONE);
- }
-}
-
-
-
-/**
- * bfa_tskim_api
- */
-
-
-struct bfa_tskim_s *
-bfa_tskim_alloc(struct bfa_s *bfa, struct bfad_tskim_s *dtsk)
-{
- struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
- struct bfa_tskim_s *tskim;
-
- bfa_q_deq(&fcpim->tskim_free_q, &tskim);
-
- if (!tskim)
- bfa_fcpim_stats(fcpim, no_tskims);
- else
- tskim->dtsk = dtsk;
-
- return tskim;
-}
-
-void
-bfa_tskim_free(struct bfa_tskim_s *tskim)
-{
- bfa_assert(bfa_q_is_on_q_func(&tskim->itnim->tsk_q, &tskim->qe));
- list_del(&tskim->qe);
- list_add_tail(&tskim->qe, &tskim->fcpim->tskim_free_q);
-}
-
-/**
- * Start a task management command.
- *
- * @param[in] tskim BFA task management command instance
- * @param[in] itnim i-t nexus for the task management command
- * @param[in] lun lun, if applicable
- * @param[in] tm_cmnd Task management command code.
- * @param[in] t_secs Timeout in seconds
- *
- * @return None.
- */
-void
-bfa_tskim_start(struct bfa_tskim_s *tskim, struct bfa_itnim_s *itnim, lun_t lun,
- enum fcp_tm_cmnd tm_cmnd, u8 tsecs)
-{
- tskim->itnim = itnim;
- tskim->lun = lun;
- tskim->tm_cmnd = tm_cmnd;
- tskim->tsecs = tsecs;
- tskim->notify = BFA_FALSE;
- bfa_stats(itnim, tm_cmnds);
-
- list_add_tail(&tskim->qe, &itnim->tsk_q);
- bfa_sm_send_event(tskim, BFA_TSKIM_SM_START);
-}
-
-
diff --git a/drivers/scsi/bfa/bfa_uf.c b/drivers/scsi/bfa/bfa_uf.c
deleted file mode 100644
index b9a9a686ef6a..000000000000
--- a/drivers/scsi/bfa/bfa_uf.c
+++ /dev/null
@@ -1,343 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/**
- * bfa_uf.c BFA unsolicited frame receive implementation
- */
-
-#include <bfa.h>
-#include <bfa_svc.h>
-#include <bfi/bfi_uf.h>
-#include <cs/bfa_debug.h>
-
-BFA_TRC_FILE(HAL, UF);
-BFA_MODULE(uf);
-
-/*
- *****************************************************************************
- * Internal functions
- *****************************************************************************
- */
-static void
-__bfa_cb_uf_recv(void *cbarg, bfa_boolean_t complete)
-{
- struct bfa_uf_s *uf = cbarg;
- struct bfa_uf_mod_s *ufm = BFA_UF_MOD(uf->bfa);
-
- if (complete)
- ufm->ufrecv(ufm->cbarg, uf);
-}
-
-static void
-claim_uf_pbs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
-{
- u32 uf_pb_tot_sz;
-
- ufm->uf_pbs_kva = (struct bfa_uf_buf_s *) bfa_meminfo_dma_virt(mi);
- ufm->uf_pbs_pa = bfa_meminfo_dma_phys(mi);
- uf_pb_tot_sz = BFA_ROUNDUP((sizeof(struct bfa_uf_buf_s) * ufm->num_ufs),
- BFA_DMA_ALIGN_SZ);
-
- bfa_meminfo_dma_virt(mi) += uf_pb_tot_sz;
- bfa_meminfo_dma_phys(mi) += uf_pb_tot_sz;
-
- bfa_os_memset((void *)ufm->uf_pbs_kva, 0, uf_pb_tot_sz);
-}
-
-static void
-claim_uf_post_msgs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
-{
- struct bfi_uf_buf_post_s *uf_bp_msg;
- struct bfi_sge_s *sge;
- union bfi_addr_u sga_zero = { {0} };
- u16 i;
- u16 buf_len;
-
- ufm->uf_buf_posts = (struct bfi_uf_buf_post_s *) bfa_meminfo_kva(mi);
- uf_bp_msg = ufm->uf_buf_posts;
-
- for (i = 0, uf_bp_msg = ufm->uf_buf_posts; i < ufm->num_ufs;
- i++, uf_bp_msg++) {
- bfa_os_memset(uf_bp_msg, 0, sizeof(struct bfi_uf_buf_post_s));
-
- uf_bp_msg->buf_tag = i;
- buf_len = sizeof(struct bfa_uf_buf_s);
- uf_bp_msg->buf_len = bfa_os_htons(buf_len);
- bfi_h2i_set(uf_bp_msg->mh, BFI_MC_UF, BFI_UF_H2I_BUF_POST,
- bfa_lpuid(ufm->bfa));
-
- sge = uf_bp_msg->sge;
- sge[0].sg_len = buf_len;
- sge[0].flags = BFI_SGE_DATA_LAST;
- bfa_dma_addr_set(sge[0].sga, ufm_pbs_pa(ufm, i));
- bfa_sge_to_be(sge);
-
- sge[1].sg_len = buf_len;
- sge[1].flags = BFI_SGE_PGDLEN;
- sge[1].sga = sga_zero;
- bfa_sge_to_be(&sge[1]);
- }
-
- /**
- * advance pointer beyond consumed memory
- */
- bfa_meminfo_kva(mi) = (u8 *) uf_bp_msg;
-}
-
-static void
-claim_ufs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
-{
- u16 i;
- struct bfa_uf_s *uf;
-
- /*
- * Claim block of memory for UF list
- */
- ufm->uf_list = (struct bfa_uf_s *) bfa_meminfo_kva(mi);
-
- /*
- * Initialize UFs and queue it in UF free queue
- */
- for (i = 0, uf = ufm->uf_list; i < ufm->num_ufs; i++, uf++) {
- bfa_os_memset(uf, 0, sizeof(struct bfa_uf_s));
- uf->bfa = ufm->bfa;
- uf->uf_tag = i;
- uf->pb_len = sizeof(struct bfa_uf_buf_s);
- uf->buf_kva = (void *)&ufm->uf_pbs_kva[i];
- uf->buf_pa = ufm_pbs_pa(ufm, i);
- list_add_tail(&uf->qe, &ufm->uf_free_q);
- }
-
- /**
- * advance memory pointer
- */
- bfa_meminfo_kva(mi) = (u8 *) uf;
-}
-
-static void
-uf_mem_claim(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
-{
- claim_uf_pbs(ufm, mi);
- claim_ufs(ufm, mi);
- claim_uf_post_msgs(ufm, mi);
-}
-
-static void
-bfa_uf_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len, u32 *dm_len)
-{
- u32 num_ufs = cfg->fwcfg.num_uf_bufs;
-
- /*
- * dma-able memory for UF posted bufs
- */
- *dm_len += BFA_ROUNDUP((sizeof(struct bfa_uf_buf_s) * num_ufs),
- BFA_DMA_ALIGN_SZ);
-
- /*
- * kernel Virtual memory for UFs and UF buf post msg copies
- */
- *ndm_len += sizeof(struct bfa_uf_s) * num_ufs;
- *ndm_len += sizeof(struct bfi_uf_buf_post_s) * num_ufs;
-}
-
-static void
-bfa_uf_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
- struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
-{
- struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
-
- bfa_os_memset(ufm, 0, sizeof(struct bfa_uf_mod_s));
- ufm->bfa = bfa;
- ufm->num_ufs = cfg->fwcfg.num_uf_bufs;
- INIT_LIST_HEAD(&ufm->uf_free_q);
- INIT_LIST_HEAD(&ufm->uf_posted_q);
-
- uf_mem_claim(ufm, meminfo);
-}
-
-static void
-bfa_uf_detach(struct bfa_s *bfa)
-{
-}
-
-static struct bfa_uf_s *
-bfa_uf_get(struct bfa_uf_mod_s *uf_mod)
-{
- struct bfa_uf_s *uf;
-
- bfa_q_deq(&uf_mod->uf_free_q, &uf);
- return uf;
-}
-
-static void
-bfa_uf_put(struct bfa_uf_mod_s *uf_mod, struct bfa_uf_s *uf)
-{
- list_add_tail(&uf->qe, &uf_mod->uf_free_q);
-}
-
-static bfa_status_t
-bfa_uf_post(struct bfa_uf_mod_s *ufm, struct bfa_uf_s *uf)
-{
- struct bfi_uf_buf_post_s *uf_post_msg;
-
- uf_post_msg = bfa_reqq_next(ufm->bfa, BFA_REQQ_FCXP);
- if (!uf_post_msg)
- return BFA_STATUS_FAILED;
-
- bfa_os_memcpy(uf_post_msg, &ufm->uf_buf_posts[uf->uf_tag],
- sizeof(struct bfi_uf_buf_post_s));
- bfa_reqq_produce(ufm->bfa, BFA_REQQ_FCXP);
-
- bfa_trc(ufm->bfa, uf->uf_tag);
-
- list_add_tail(&uf->qe, &ufm->uf_posted_q);
- return BFA_STATUS_OK;
-}
-
-static void
-bfa_uf_post_all(struct bfa_uf_mod_s *uf_mod)
-{
- struct bfa_uf_s *uf;
-
- while ((uf = bfa_uf_get(uf_mod)) != NULL) {
- if (bfa_uf_post(uf_mod, uf) != BFA_STATUS_OK)
- break;
- }
-}
-
-static void
-uf_recv(struct bfa_s *bfa, struct bfi_uf_frm_rcvd_s *m)
-{
- struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
- u16 uf_tag = m->buf_tag;
- struct bfa_uf_buf_s *uf_buf = &ufm->uf_pbs_kva[uf_tag];
- struct bfa_uf_s *uf = &ufm->uf_list[uf_tag];
- u8 *buf = &uf_buf->d[0];
- struct fchs_s *fchs;
-
- m->frm_len = bfa_os_ntohs(m->frm_len);
- m->xfr_len = bfa_os_ntohs(m->xfr_len);
-
- fchs = (struct fchs_s *) uf_buf;
-
- list_del(&uf->qe); /* dequeue from posted queue */
-
- uf->data_ptr = buf;
- uf->data_len = m->xfr_len;
-
- bfa_assert(uf->data_len >= sizeof(struct fchs_s));
-
- if (uf->data_len == sizeof(struct fchs_s)) {
- bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_UF, BFA_PL_EID_RX,
- uf->data_len, (struct fchs_s *) buf);
- } else {
- u32 pld_w0 = *((u32 *) (buf + sizeof(struct fchs_s)));
- bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_UF,
- BFA_PL_EID_RX, uf->data_len,
- (struct fchs_s *) buf, pld_w0);
- }
-
- if (bfa->fcs)
- __bfa_cb_uf_recv(uf, BFA_TRUE);
- else
- bfa_cb_queue(bfa, &uf->hcb_qe, __bfa_cb_uf_recv, uf);
-}
-
-static void
-bfa_uf_stop(struct bfa_s *bfa)
-{
-}
-
-static void
-bfa_uf_iocdisable(struct bfa_s *bfa)
-{
- struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
- struct bfa_uf_s *uf;
- struct list_head *qe, *qen;
-
- list_for_each_safe(qe, qen, &ufm->uf_posted_q) {
- uf = (struct bfa_uf_s *) qe;
- list_del(&uf->qe);
- bfa_uf_put(ufm, uf);
- }
-}
-
-static void
-bfa_uf_start(struct bfa_s *bfa)
-{
- bfa_uf_post_all(BFA_UF_MOD(bfa));
-}
-
-
-
-/**
- * bfa_uf_api
- */
-
-/**
- * Register handler for all unsolicted recieve frames.
- *
- * @param[in] bfa BFA instance
- * @param[in] ufrecv receive handler function
- * @param[in] cbarg receive handler arg
- */
-void
-bfa_uf_recv_register(struct bfa_s *bfa, bfa_cb_uf_recv_t ufrecv, void *cbarg)
-{
- struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
-
- ufm->ufrecv = ufrecv;
- ufm->cbarg = cbarg;
-}
-
-/**
- * Free an unsolicited frame back to BFA.
- *
- * @param[in] uf unsolicited frame to be freed
- *
- * @return None
- */
-void
-bfa_uf_free(struct bfa_uf_s *uf)
-{
- bfa_uf_put(BFA_UF_MOD(uf->bfa), uf);
- bfa_uf_post_all(BFA_UF_MOD(uf->bfa));
-}
-
-
-
-/**
- * uf_pub BFA uf module public functions
- */
-
-void
-bfa_uf_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
-{
- bfa_trc(bfa, msg->mhdr.msg_id);
-
- switch (msg->mhdr.msg_id) {
- case BFI_UF_I2H_FRM_RCVD:
- uf_recv(bfa, (struct bfi_uf_frm_rcvd_s *) msg);
- break;
-
- default:
- bfa_trc(bfa, msg->mhdr.msg_id);
- bfa_assert(0);
- }
-}
-
-
diff --git a/drivers/scsi/bfa/bfa_uf_priv.h b/drivers/scsi/bfa/bfa_uf_priv.h
deleted file mode 100644
index bcb490f834f3..000000000000
--- a/drivers/scsi/bfa/bfa_uf_priv.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-#ifndef __BFA_UF_PRIV_H__
-#define __BFA_UF_PRIV_H__
-
-#include <cs/bfa_sm.h>
-#include <bfa_svc.h>
-#include <bfi/bfi_uf.h>
-
-#define BFA_UF_MIN (4)
-
-struct bfa_uf_mod_s {
- struct bfa_s *bfa; /* back pointer to BFA */
- struct bfa_uf_s *uf_list; /* array of UFs */
- u16 num_ufs; /* num unsolicited rx frames */
- struct list_head uf_free_q; /* free UFs */
- struct list_head uf_posted_q; /* UFs posted to IOC */
- struct bfa_uf_buf_s *uf_pbs_kva; /* list UF bufs request pld */
- u64 uf_pbs_pa; /* phy addr for UF bufs */
- struct bfi_uf_buf_post_s *uf_buf_posts;
- /* pre-built UF post msgs */
- bfa_cb_uf_recv_t ufrecv; /* uf recv handler function */
- void *cbarg; /* uf receive handler arg */
-};
-
-#define BFA_UF_MOD(__bfa) (&(__bfa)->modules.uf_mod)
-
-#define ufm_pbs_pa(_ufmod, _uftag) \
- ((_ufmod)->uf_pbs_pa + sizeof(struct bfa_uf_buf_s) * (_uftag))
-
-void bfa_uf_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
-
-#endif /* __BFA_UF_PRIV_H__ */
diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c
index ca04cc9d332f..4d8784e06e14 100644
--- a/drivers/scsi/bfa/bfad.c
+++ b/drivers/scsi/bfa/bfad.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
* All rights reserved
* www.brocade.com
*
@@ -18,46 +18,62 @@
/**
* bfad.c Linux driver PCI interface module.
*/
-
-#include <linux/slab.h>
#include <linux/module.h>
#include <linux/kthread.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/pci.h>
+#include <linux/firmware.h>
+#include <asm/uaccess.h>
+#include <asm/fcntl.h>
+
#include "bfad_drv.h"
#include "bfad_im.h"
-#include "bfad_tm.h"
-#include "bfad_ipfc.h"
-#include "bfad_trcmod.h"
-#include <fcb/bfa_fcb_vf.h>
-#include <fcb/bfa_fcb_rport.h>
-#include <fcb/bfa_fcb_port.h>
-#include <fcb/bfa_fcb.h>
+#include "bfa_fcs.h"
+#include "bfa_os_inc.h"
+#include "bfa_defs.h"
+#include "bfa.h"
BFA_TRC_FILE(LDRV, BFAD);
DEFINE_MUTEX(bfad_mutex);
LIST_HEAD(bfad_list);
-static int bfad_inst;
-int bfad_supported_fc4s;
-
-static char *host_name;
-static char *os_name;
-static char *os_patch;
-static int num_rports;
-static int num_ios;
-static int num_tms;
-static int num_fcxps;
-static int num_ufbufs;
-static int reqq_size;
-static int rspq_size;
-static int num_sgpgs;
-static int rport_del_timeout = BFA_FCS_RPORT_DEF_DEL_TIMEOUT;
-static int bfa_io_max_sge = BFAD_IO_MAX_SGE;
-static int log_level = BFA_LOG_WARNING;
-static int ioc_auto_recover = BFA_TRUE;
-static int ipfc_enable = BFA_FALSE;
-static int fdmi_enable = BFA_TRUE;
-int bfa_lun_queue_depth = BFAD_LUN_QUEUE_DEPTH;
-int bfa_linkup_delay = -1;
+
+static int bfad_inst;
+static int num_sgpgs_parm;
+int supported_fc4s;
+char *host_name, *os_name, *os_patch;
+int num_rports, num_ios, num_tms;
+int num_fcxps, num_ufbufs;
+int reqq_size, rspq_size, num_sgpgs;
+int rport_del_timeout = BFA_FCS_RPORT_DEF_DEL_TIMEOUT;
+int bfa_lun_queue_depth = BFAD_LUN_QUEUE_DEPTH;
+int bfa_io_max_sge = BFAD_IO_MAX_SGE;
+int log_level = 3; /* WARNING log level */
+int ioc_auto_recover = BFA_TRUE;
+int bfa_linkup_delay = -1;
+int fdmi_enable = BFA_TRUE;
+int pcie_max_read_reqsz;
int bfa_debugfs_enable = 1;
+int msix_disable_cb = 0, msix_disable_ct = 0;
+
+u32 bfi_image_ct_fc_size, bfi_image_ct_cna_size, bfi_image_cb_fc_size;
+u32 *bfi_image_ct_fc, *bfi_image_ct_cna, *bfi_image_cb_fc;
+
+const char *msix_name_ct[] = {
+ "cpe0", "cpe1", "cpe2", "cpe3",
+ "rme0", "rme1", "rme2", "rme3",
+ "ctrl" };
+
+const char *msix_name_cb[] = {
+ "cpe0", "cpe1", "cpe2", "cpe3",
+ "rme0", "rme1", "rme2", "rme3",
+ "eemc", "elpu0", "elpu1", "epss", "mlpu" };
+
+MODULE_FIRMWARE(BFAD_FW_FILE_CT_FC);
+MODULE_FIRMWARE(BFAD_FW_FILE_CT_CNA);
+MODULE_FIRMWARE(BFAD_FW_FILE_CB_FC);
module_param(os_name, charp, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(os_name, "OS name of the hba host machine");
@@ -66,8 +82,8 @@ MODULE_PARM_DESC(os_patch, "OS patch level of the hba host machine");
module_param(host_name, charp, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(host_name, "Hostname of the hba host machine");
module_param(num_rports, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(num_rports, "Max number of rports supported per port"
- " (physical/logical), default=1024");
+MODULE_PARM_DESC(num_rports, "Max number of rports supported per port "
+ "(physical/logical), default=1024");
module_param(num_ios, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(num_ios, "Max number of ioim requests, default=2000");
module_param(num_tms, int, S_IRUGO | S_IWUSR);
@@ -75,120 +91,277 @@ MODULE_PARM_DESC(num_tms, "Max number of task im requests, default=128");
module_param(num_fcxps, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(num_fcxps, "Max number of fcxp requests, default=64");
module_param(num_ufbufs, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(num_ufbufs, "Max number of unsolicited frame buffers,"
- " default=64");
+MODULE_PARM_DESC(num_ufbufs, "Max number of unsolicited frame "
+ "buffers, default=64");
module_param(reqq_size, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(reqq_size, "Max number of request queue elements,"
- " default=256");
+MODULE_PARM_DESC(reqq_size, "Max number of request queue elements, "
+ "default=256");
module_param(rspq_size, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(rspq_size, "Max number of response queue elements,"
- " default=64");
+MODULE_PARM_DESC(rspq_size, "Max number of response queue elements, "
+ "default=64");
module_param(num_sgpgs, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(num_sgpgs, "Number of scatter/gather pages, default=2048");
module_param(rport_del_timeout, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(rport_del_timeout, "Rport delete timeout, default=90 secs,"
- " Range[>0]");
+MODULE_PARM_DESC(rport_del_timeout, "Rport delete timeout, default=90 secs, "
+ "Range[>0]");
module_param(bfa_lun_queue_depth, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(bfa_lun_queue_depth, "Lun queue depth, default=32,"
- " Range[>0]");
+MODULE_PARM_DESC(bfa_lun_queue_depth, "Lun queue depth, default=32, Range[>0]");
module_param(bfa_io_max_sge, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(bfa_io_max_sge, "Max io scatter/gather elements, default=255");
module_param(log_level, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(log_level, "Driver log level, default=3,"
- " Range[Critical:1|Error:2|Warning:3|Info:4]");
+MODULE_PARM_DESC(log_level, "Driver log level, default=3, "
+ "Range[Critical:1|Error:2|Warning:3|Info:4]");
module_param(ioc_auto_recover, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(ioc_auto_recover, "IOC auto recovery, default=1,"
- " Range[off:0|on:1]");
-module_param(ipfc_enable, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(ipfc_enable, "Enable IPoFC, default=0, Range[off:0|on:1]");
+MODULE_PARM_DESC(ioc_auto_recover, "IOC auto recovery, default=1, "
+ "Range[off:0|on:1]");
module_param(bfa_linkup_delay, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(bfa_linkup_delay, "Link up delay, default=30 secs for boot"
- " port. Otherwise Range[>0]");
+MODULE_PARM_DESC(bfa_linkup_delay, "Link up delay, default=30 secs for "
+ "boot port. Otherwise 10 secs in RHEL4 & 0 for "
+ "[RHEL5, SLES10, ESX40] Range[>0]");
+module_param(msix_disable_cb, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(msix_disable_cb, "Disable Message Signaled Interrupts "
+ "for Brocade-415/425/815/825 cards, default=0, "
+ " Range[false:0|true:1]");
+module_param(msix_disable_ct, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(msix_disable_ct, "Disable Message Signaled Interrupts "
+ "if possible for Brocade-1010/1020/804/1007/902/1741 "
+ "cards, default=0, Range[false:0|true:1]");
module_param(fdmi_enable, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(fdmi_enable, "Enables fdmi registration, default=1,"
- " Range[false:0|true:1]");
+MODULE_PARM_DESC(fdmi_enable, "Enables fdmi registration, default=1, "
+ "Range[false:0|true:1]");
+module_param(pcie_max_read_reqsz, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(pcie_max_read_reqsz, "PCIe max read request size, default=0 "
+ "(use system setting), Range[128|256|512|1024|2048|4096]");
module_param(bfa_debugfs_enable, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(bfa_debugfs_enable, "Enables debugfs feature, default=1,"
" Range[false:0|true:1]");
-/*
- * Stores the module parm num_sgpgs value;
- * used to reset for bfad next instance.
+static void
+bfad_sm_uninit(struct bfad_s *bfad, enum bfad_sm_event event);
+static void
+bfad_sm_created(struct bfad_s *bfad, enum bfad_sm_event event);
+static void
+bfad_sm_initializing(struct bfad_s *bfad, enum bfad_sm_event event);
+static void
+bfad_sm_operational(struct bfad_s *bfad, enum bfad_sm_event event);
+static void
+bfad_sm_stopping(struct bfad_s *bfad, enum bfad_sm_event event);
+static void
+bfad_sm_failed(struct bfad_s *bfad, enum bfad_sm_event event);
+static void
+bfad_sm_fcs_exit(struct bfad_s *bfad, enum bfad_sm_event event);
+
+/**
+ * Beginning state for the driver instance, awaiting the pci_probe event
*/
-static int num_sgpgs_parm;
+static void
+bfad_sm_uninit(struct bfad_s *bfad, enum bfad_sm_event event)
+{
+ bfa_trc(bfad, event);
+
+ switch (event) {
+ case BFAD_E_CREATE:
+ bfa_sm_set_state(bfad, bfad_sm_created);
+ bfad->bfad_tsk = kthread_create(bfad_worker, (void *) bfad,
+ "%s", "bfad_worker");
+ if (IS_ERR(bfad->bfad_tsk)) {
+ printk(KERN_INFO "bfad[%d]: Kernel thread "
+ "creation failed!\n", bfad->inst_no);
+ bfa_sm_send_event(bfad, BFAD_E_KTHREAD_CREATE_FAILED);
+ }
+ bfa_sm_send_event(bfad, BFAD_E_INIT);
+ break;
+
+ case BFAD_E_STOP:
+ /* Ignore stop; already in uninit */
+ break;
+
+ default:
+ bfa_sm_fault(bfad, event);
+ }
+}
-static bfa_status_t
-bfad_fc4_probe(struct bfad_s *bfad)
+/**
+ * Driver Instance is created, awaiting event INIT to initialize the bfad
+ */
+static void
+bfad_sm_created(struct bfad_s *bfad, enum bfad_sm_event event)
{
- int rc;
+ unsigned long flags;
- rc = bfad_im_probe(bfad);
- if (rc != BFA_STATUS_OK)
- goto ext;
+ bfa_trc(bfad, event);
- bfad_tm_probe(bfad);
+ switch (event) {
+ case BFAD_E_INIT:
+ bfa_sm_set_state(bfad, bfad_sm_initializing);
- if (ipfc_enable)
- bfad_ipfc_probe(bfad);
+ init_completion(&bfad->comp);
- bfad->bfad_flags |= BFAD_FC4_PROBE_DONE;
-ext:
- return rc;
+ /* Enable Interrupt and wait bfa_init completion */
+ if (bfad_setup_intr(bfad)) {
+ printk(KERN_WARNING "bfad%d: bfad_setup_intr failed\n",
+ bfad->inst_no);
+ bfa_sm_send_event(bfad, BFAD_E_INTR_INIT_FAILED);
+ break;
+ }
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ bfa_init(&bfad->bfa);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+ /* Set up interrupt handler for each vectors */
+ if ((bfad->bfad_flags & BFAD_MSIX_ON) &&
+ bfad_install_msix_handler(bfad)) {
+ printk(KERN_WARNING "%s: install_msix failed, bfad%d\n",
+ __func__, bfad->inst_no);
+ }
+
+ bfad_init_timer(bfad);
+
+ wait_for_completion(&bfad->comp);
+
+ if ((bfad->bfad_flags & BFAD_HAL_INIT_DONE)) {
+ bfa_sm_send_event(bfad, BFAD_E_INIT_SUCCESS);
+ } else {
+ bfad->bfad_flags |= BFAD_HAL_INIT_FAIL;
+ bfa_sm_send_event(bfad, BFAD_E_INIT_FAILED);
+ }
+
+ break;
+
+ case BFAD_E_KTHREAD_CREATE_FAILED:
+ bfa_sm_set_state(bfad, bfad_sm_uninit);
+ break;
+
+ default:
+ bfa_sm_fault(bfad, event);
+ }
}
static void
-bfad_fc4_probe_undo(struct bfad_s *bfad)
+bfad_sm_initializing(struct bfad_s *bfad, enum bfad_sm_event event)
{
- bfad_im_probe_undo(bfad);
- bfad_tm_probe_undo(bfad);
- if (ipfc_enable)
- bfad_ipfc_probe_undo(bfad);
- bfad->bfad_flags &= ~BFAD_FC4_PROBE_DONE;
+ int retval;
+ unsigned long flags;
+
+ bfa_trc(bfad, event);
+
+ switch (event) {
+ case BFAD_E_INIT_SUCCESS:
+ kthread_stop(bfad->bfad_tsk);
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ bfad->bfad_tsk = NULL;
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+ retval = bfad_start_ops(bfad);
+ if (retval != BFA_STATUS_OK)
+ break;
+ bfa_sm_set_state(bfad, bfad_sm_operational);
+ break;
+
+ case BFAD_E_INTR_INIT_FAILED:
+ bfa_sm_set_state(bfad, bfad_sm_uninit);
+ kthread_stop(bfad->bfad_tsk);
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ bfad->bfad_tsk = NULL;
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ break;
+
+ case BFAD_E_INIT_FAILED:
+ bfa_sm_set_state(bfad, bfad_sm_failed);
+ break;
+ default:
+ bfa_sm_fault(bfad, event);
+ }
}
static void
-bfad_fc4_probe_post(struct bfad_s *bfad)
+bfad_sm_failed(struct bfad_s *bfad, enum bfad_sm_event event)
{
- if (bfad->im)
- bfad_im_probe_post(bfad->im);
+ int retval;
- bfad_tm_probe_post(bfad);
- if (ipfc_enable)
- bfad_ipfc_probe_post(bfad);
+ bfa_trc(bfad, event);
+
+ switch (event) {
+ case BFAD_E_INIT_SUCCESS:
+ retval = bfad_start_ops(bfad);
+ if (retval != BFA_STATUS_OK)
+ break;
+ bfa_sm_set_state(bfad, bfad_sm_operational);
+ break;
+
+ case BFAD_E_STOP:
+ if (bfad->bfad_flags & BFAD_CFG_PPORT_DONE)
+ bfad_uncfg_pport(bfad);
+ if (bfad->bfad_flags & BFAD_FC4_PROBE_DONE) {
+ bfad_im_probe_undo(bfad);
+ bfad->bfad_flags &= ~BFAD_FC4_PROBE_DONE;
+ }
+ bfad_stop(bfad);
+ break;
+
+ case BFAD_E_EXIT_COMP:
+ bfa_sm_set_state(bfad, bfad_sm_uninit);
+ bfad_remove_intr(bfad);
+ del_timer_sync(&bfad->hal_tmo);
+ break;
+
+ default:
+ bfa_sm_fault(bfad, event);
+ }
}
-static bfa_status_t
-bfad_fc4_port_new(struct bfad_s *bfad, struct bfad_port_s *port, int roles)
+static void
+bfad_sm_operational(struct bfad_s *bfad, enum bfad_sm_event event)
{
- int rc = BFA_STATUS_FAILED;
+ bfa_trc(bfad, event);
- if (roles & BFA_PORT_ROLE_FCP_IM)
- rc = bfad_im_port_new(bfad, port);
- if (rc != BFA_STATUS_OK)
- goto ext;
+ switch (event) {
+ case BFAD_E_STOP:
+ bfa_sm_set_state(bfad, bfad_sm_fcs_exit);
+ bfad_fcs_stop(bfad);
+ break;
- if (roles & BFA_PORT_ROLE_FCP_TM)
- rc = bfad_tm_port_new(bfad, port);
- if (rc != BFA_STATUS_OK)
- goto ext;
+ default:
+ bfa_sm_fault(bfad, event);
+ }
+}
- if ((roles & BFA_PORT_ROLE_FCP_IPFC) && ipfc_enable)
- rc = bfad_ipfc_port_new(bfad, port, port->pvb_type);
-ext:
- return rc;
+static void
+bfad_sm_fcs_exit(struct bfad_s *bfad, enum bfad_sm_event event)
+{
+ bfa_trc(bfad, event);
+
+ switch (event) {
+ case BFAD_E_FCS_EXIT_COMP:
+ bfa_sm_set_state(bfad, bfad_sm_stopping);
+ bfad_stop(bfad);
+ break;
+
+ default:
+ bfa_sm_fault(bfad, event);
+ }
}
static void
-bfad_fc4_port_delete(struct bfad_s *bfad, struct bfad_port_s *port, int roles)
+bfad_sm_stopping(struct bfad_s *bfad, enum bfad_sm_event event)
{
- if (roles & BFA_PORT_ROLE_FCP_IM)
- bfad_im_port_delete(bfad, port);
+ bfa_trc(bfad, event);
- if (roles & BFA_PORT_ROLE_FCP_TM)
- bfad_tm_port_delete(bfad, port);
+ switch (event) {
+ case BFAD_E_EXIT_COMP:
+ bfa_sm_set_state(bfad, bfad_sm_uninit);
+ bfad_remove_intr(bfad);
+ del_timer_sync(&bfad->hal_tmo);
+ bfad_im_probe_undo(bfad);
+ bfad->bfad_flags &= ~BFAD_FC4_PROBE_DONE;
+ bfad_uncfg_pport(bfad);
+ break;
- if ((roles & BFA_PORT_ROLE_FCP_IPFC) && ipfc_enable)
- bfad_ipfc_port_delete(bfad, port);
+ default:
+ bfa_sm_fault(bfad, event);
+ break;
+ }
}
/**
@@ -209,12 +382,13 @@ bfad_hcb_comp(void *arg, bfa_status_t status)
void
bfa_cb_init(void *drv, bfa_status_t init_status)
{
- struct bfad_s *bfad = drv;
+ struct bfad_s *bfad = drv;
if (init_status == BFA_STATUS_OK) {
bfad->bfad_flags |= BFAD_HAL_INIT_DONE;
- /* If BFAD_HAL_INIT_FAIL flag is set:
+ /*
+ * If BFAD_HAL_INIT_FAIL flag is set:
* Wake up the kernel thread to start
* the bfad operations after HAL init done
*/
@@ -227,26 +401,16 @@ bfa_cb_init(void *drv, bfa_status_t init_status)
complete(&bfad->comp);
}
-
-
/**
* BFA_FCS callbacks
*/
-static struct bfad_port_s *
-bfad_get_drv_port(struct bfad_s *bfad, struct bfad_vf_s *vf_drv,
- struct bfad_vport_s *vp_drv)
-{
- return (vp_drv) ? (&(vp_drv)->drv_port)
- : ((vf_drv) ? (&(vf_drv)->base_port) : (&(bfad)->pport));
-}
-
struct bfad_port_s *
-bfa_fcb_port_new(struct bfad_s *bfad, struct bfa_fcs_port_s *port,
- enum bfa_port_role roles, struct bfad_vf_s *vf_drv,
+bfa_fcb_lport_new(struct bfad_s *bfad, struct bfa_fcs_lport_s *port,
+ enum bfa_lport_role roles, struct bfad_vf_s *vf_drv,
struct bfad_vport_s *vp_drv)
{
- bfa_status_t rc;
- struct bfad_port_s *port_drv;
+ bfa_status_t rc;
+ struct bfad_port_s *port_drv;
if (!vp_drv && !vf_drv) {
port_drv = &bfad->pport;
@@ -264,71 +428,32 @@ bfa_fcb_port_new(struct bfad_s *bfad, struct bfa_fcs_port_s *port,
port_drv->fcs_port = port;
port_drv->roles = roles;
- rc = bfad_fc4_port_new(bfad, port_drv, roles);
- if (rc != BFA_STATUS_OK) {
- bfad_fc4_port_delete(bfad, port_drv, roles);
- port_drv = NULL;
+
+ if (roles & BFA_LPORT_ROLE_FCP_IM) {
+ rc = bfad_im_port_new(bfad, port_drv);
+ if (rc != BFA_STATUS_OK) {
+ bfad_im_port_delete(bfad, port_drv);
+ port_drv = NULL;
+ }
}
return port_drv;
}
void
-bfa_fcb_port_delete(struct bfad_s *bfad, enum bfa_port_role roles,
+bfa_fcb_lport_delete(struct bfad_s *bfad, enum bfa_lport_role roles,
struct bfad_vf_s *vf_drv, struct bfad_vport_s *vp_drv)
{
- struct bfad_port_s *port_drv;
+ struct bfad_port_s *port_drv;
- /*
- * this will be only called from rmmod context
- */
+ /* this will be only called from rmmod context */
if (vp_drv && !vp_drv->comp_del) {
- port_drv = bfad_get_drv_port(bfad, vf_drv, vp_drv);
+ port_drv = (vp_drv) ? (&(vp_drv)->drv_port) :
+ ((vf_drv) ? (&(vf_drv)->base_port) :
+ (&(bfad)->pport));
bfa_trc(bfad, roles);
- bfad_fc4_port_delete(bfad, port_drv, roles);
- }
-}
-
-void
-bfa_fcb_port_online(struct bfad_s *bfad, enum bfa_port_role roles,
- struct bfad_vf_s *vf_drv, struct bfad_vport_s *vp_drv)
-{
- struct bfad_port_s *port_drv = bfad_get_drv_port(bfad, vf_drv, vp_drv);
-
- if (roles & BFA_PORT_ROLE_FCP_IM)
- bfad_im_port_online(bfad, port_drv);
-
- if (roles & BFA_PORT_ROLE_FCP_TM)
- bfad_tm_port_online(bfad, port_drv);
-
- if ((roles & BFA_PORT_ROLE_FCP_IPFC) && ipfc_enable)
- bfad_ipfc_port_online(bfad, port_drv);
-
- bfad->bfad_flags |= BFAD_PORT_ONLINE;
-}
-
-void
-bfa_fcb_port_offline(struct bfad_s *bfad, enum bfa_port_role roles,
- struct bfad_vf_s *vf_drv, struct bfad_vport_s *vp_drv)
-{
- struct bfad_port_s *port_drv = bfad_get_drv_port(bfad, vf_drv, vp_drv);
-
- if (roles & BFA_PORT_ROLE_FCP_IM)
- bfad_im_port_offline(bfad, port_drv);
-
- if (roles & BFA_PORT_ROLE_FCP_TM)
- bfad_tm_port_offline(bfad, port_drv);
-
- if ((roles & BFA_PORT_ROLE_FCP_IPFC) && ipfc_enable)
- bfad_ipfc_port_offline(bfad, port_drv);
-}
-
-void
-bfa_fcb_vport_delete(struct bfad_vport_s *vport_drv)
-{
- if (vport_drv->comp_del) {
- complete(vport_drv->comp_del);
- return;
+ if (roles & BFA_LPORT_ROLE_FCP_IM)
+ bfad_im_port_delete(bfad, port_drv);
}
}
@@ -339,7 +464,7 @@ bfa_status_t
bfa_fcb_rport_alloc(struct bfad_s *bfad, struct bfa_fcs_rport_s **rport,
struct bfad_rport_s **rport_drv)
{
- bfa_status_t rc = BFA_STATUS_OK;
+ bfa_status_t rc = BFA_STATUS_OK;
*rport_drv = kzalloc(sizeof(struct bfad_rport_s), GFP_ATOMIC);
if (*rport_drv == NULL) {
@@ -354,35 +479,43 @@ ext:
}
/**
- * @brief
* FCS PBC VPORT Create
*/
void
bfa_fcb_pbc_vport_create(struct bfad_s *bfad, struct bfi_pbc_vport_s pbc_vport)
{
- struct bfad_pcfg_s *pcfg;
+ struct bfa_lport_cfg_s port_cfg = {0};
+ struct bfad_vport_s *vport;
+ int rc;
- pcfg = kzalloc(sizeof(struct bfad_pcfg_s), GFP_ATOMIC);
- if (!pcfg) {
+ vport = kzalloc(sizeof(struct bfad_vport_s), GFP_KERNEL);
+ if (!vport) {
bfa_trc(bfad, 0);
return;
}
- pcfg->port_cfg.roles = BFA_PORT_ROLE_FCP_IM;
- pcfg->port_cfg.pwwn = pbc_vport.vp_pwwn;
- pcfg->port_cfg.nwwn = pbc_vport.vp_nwwn;
- pcfg->port_cfg.preboot_vp = BFA_TRUE;
+ vport->drv_port.bfad = bfad;
+ port_cfg.roles = BFA_LPORT_ROLE_FCP_IM;
+ port_cfg.pwwn = pbc_vport.vp_pwwn;
+ port_cfg.nwwn = pbc_vport.vp_nwwn;
+ port_cfg.preboot_vp = BFA_TRUE;
+
+ rc = bfa_fcs_pbc_vport_create(&vport->fcs_vport, &bfad->bfa_fcs, 0,
+ &port_cfg, vport);
- list_add_tail(&pcfg->list_entry, &bfad->pbc_pcfg_list);
+ if (rc != BFA_STATUS_OK) {
+ bfa_trc(bfad, 0);
+ return;
+ }
- return;
+ list_add_tail(&vport->list_entry, &bfad->pbc_vport_list);
}
void
bfad_hal_mem_release(struct bfad_s *bfad)
{
- int i;
+ int i;
struct bfa_meminfo_s *hal_meminfo = &bfad->meminfo;
struct bfa_mem_elem_s *meminfo_elem;
@@ -395,9 +528,9 @@ bfad_hal_mem_release(struct bfad_s *bfad)
break;
case BFA_MEM_TYPE_DMA:
dma_free_coherent(&bfad->pcidev->dev,
- meminfo_elem->mem_len,
- meminfo_elem->kva,
- (dma_addr_t) meminfo_elem->dma);
+ meminfo_elem->mem_len,
+ meminfo_elem->kva,
+ (dma_addr_t) meminfo_elem->dma);
break;
default:
bfa_assert(0);
@@ -434,27 +567,27 @@ bfad_update_hal_cfg(struct bfa_iocfc_cfg_s *bfa_cfg)
* otherwise, the default values will be shown as 0 in sysfs
*/
num_rports = bfa_cfg->fwcfg.num_rports;
- num_ios = bfa_cfg->fwcfg.num_ioim_reqs;
- num_tms = bfa_cfg->fwcfg.num_tskim_reqs;
- num_fcxps = bfa_cfg->fwcfg.num_fcxp_reqs;
+ num_ios = bfa_cfg->fwcfg.num_ioim_reqs;
+ num_tms = bfa_cfg->fwcfg.num_tskim_reqs;
+ num_fcxps = bfa_cfg->fwcfg.num_fcxp_reqs;
num_ufbufs = bfa_cfg->fwcfg.num_uf_bufs;
- reqq_size = bfa_cfg->drvcfg.num_reqq_elems;
- rspq_size = bfa_cfg->drvcfg.num_rspq_elems;
- num_sgpgs = bfa_cfg->drvcfg.num_sgpgs;
+ reqq_size = bfa_cfg->drvcfg.num_reqq_elems;
+ rspq_size = bfa_cfg->drvcfg.num_rspq_elems;
+ num_sgpgs = bfa_cfg->drvcfg.num_sgpgs;
}
bfa_status_t
bfad_hal_mem_alloc(struct bfad_s *bfad)
{
+ int i;
struct bfa_meminfo_s *hal_meminfo = &bfad->meminfo;
struct bfa_mem_elem_s *meminfo_elem;
- bfa_status_t rc = BFA_STATUS_OK;
- dma_addr_t phys_addr;
- int retry_count = 0;
- int reset_value = 1;
- int min_num_sgpgs = 512;
- void *kva;
- int i;
+ dma_addr_t phys_addr;
+ void *kva;
+ bfa_status_t rc = BFA_STATUS_OK;
+ int retry_count = 0;
+ int reset_value = 1;
+ int min_num_sgpgs = 512;
bfa_cfg_get_default(&bfad->ioc_cfg);
@@ -478,8 +611,7 @@ retry:
break;
case BFA_MEM_TYPE_DMA:
kva = dma_alloc_coherent(&bfad->pcidev->dev,
- meminfo_elem->mem_len,
- &phys_addr, GFP_KERNEL);
+ meminfo_elem->mem_len, &phys_addr, GFP_KERNEL);
if (kva == NULL) {
bfad_hal_mem_release(bfad);
/*
@@ -487,14 +619,14 @@ retry:
* num_sgpages try with half the value.
*/
if (num_sgpgs > min_num_sgpgs) {
- printk(KERN_INFO "bfad[%d]: memory"
- " allocation failed with"
- " num_sgpgs: %d\n",
+ printk(KERN_INFO
+ "bfad[%d]: memory allocation failed"
+ " with num_sgpgs: %d\n",
bfad->inst_no, num_sgpgs);
nextLowerInt(&num_sgpgs);
- printk(KERN_INFO "bfad[%d]: trying to"
- " allocate memory with"
- " num_sgpgs: %d\n",
+ printk(KERN_INFO
+ "bfad[%d]: trying to allocate memory"
+ " with num_sgpgs: %d\n",
bfad->inst_no, num_sgpgs);
retry_count++;
goto retry;
@@ -536,11 +668,11 @@ ext:
*/
bfa_status_t
bfad_vport_create(struct bfad_s *bfad, u16 vf_id,
- struct bfa_port_cfg_s *port_cfg, struct device *dev)
+ struct bfa_lport_cfg_s *port_cfg, struct device *dev)
{
- struct bfad_vport_s *vport;
- int rc = BFA_STATUS_OK;
- unsigned long flags;
+ struct bfad_vport_s *vport;
+ int rc = BFA_STATUS_OK;
+ unsigned long flags;
struct completion fcomp;
vport = kzalloc(sizeof(struct bfad_vport_s), GFP_KERNEL);
@@ -551,18 +683,14 @@ bfad_vport_create(struct bfad_s *bfad, u16 vf_id,
vport->drv_port.bfad = bfad;
spin_lock_irqsave(&bfad->bfad_lock, flags);
- if (port_cfg->preboot_vp == BFA_TRUE)
- rc = bfa_fcs_pbc_vport_create(&vport->fcs_vport,
- &bfad->bfa_fcs, vf_id, port_cfg, vport);
- else
- rc = bfa_fcs_vport_create(&vport->fcs_vport,
- &bfad->bfa_fcs, vf_id, port_cfg, vport);
+ rc = bfa_fcs_vport_create(&vport->fcs_vport, &bfad->bfa_fcs, vf_id,
+ port_cfg, vport);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
if (rc != BFA_STATUS_OK)
goto ext_free_vport;
- if (port_cfg->roles & BFA_PORT_ROLE_FCP_IM) {
+ if (port_cfg->roles & BFA_LPORT_ROLE_FCP_IM) {
rc = bfad_im_scsi_host_alloc(bfad, vport->drv_port.im_port,
dev);
if (rc != BFA_STATUS_OK)
@@ -593,10 +721,10 @@ ext:
*/
bfa_status_t
bfad_vf_create(struct bfad_s *bfad, u16 vf_id,
- struct bfa_port_cfg_s *port_cfg)
+ struct bfa_lport_cfg_s *port_cfg)
{
- struct bfad_vf_s *vf;
- int rc = BFA_STATUS_OK;
+ struct bfad_vf_s *vf;
+ int rc = BFA_STATUS_OK;
vf = kzalloc(sizeof(struct bfad_vf_s), GFP_KERNEL);
if (!vf) {
@@ -615,9 +743,9 @@ ext:
void
bfad_bfa_tmo(unsigned long data)
{
- struct bfad_s *bfad = (struct bfad_s *)data;
- unsigned long flags;
- struct list_head doneq;
+ struct bfad_s *bfad = (struct bfad_s *) data;
+ unsigned long flags;
+ struct list_head doneq;
spin_lock_irqsave(&bfad->bfad_lock, flags);
@@ -633,7 +761,8 @@ bfad_bfa_tmo(unsigned long data)
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
}
- mod_timer(&bfad->hal_tmo, jiffies + msecs_to_jiffies(BFA_TIMER_FREQ));
+ mod_timer(&bfad->hal_tmo,
+ jiffies + msecs_to_jiffies(BFA_TIMER_FREQ));
}
void
@@ -643,16 +772,17 @@ bfad_init_timer(struct bfad_s *bfad)
bfad->hal_tmo.function = bfad_bfa_tmo;
bfad->hal_tmo.data = (unsigned long)bfad;
- mod_timer(&bfad->hal_tmo, jiffies + msecs_to_jiffies(BFA_TIMER_FREQ));
+ mod_timer(&bfad->hal_tmo,
+ jiffies + msecs_to_jiffies(BFA_TIMER_FREQ));
}
int
bfad_pci_init(struct pci_dev *pdev, struct bfad_s *bfad)
{
- int rc = -ENODEV;
+ int rc = -ENODEV;
if (pci_enable_device(pdev)) {
- BFA_PRINTF(BFA_ERR, "pci_enable_device fail %p\n", pdev);
+ printk(KERN_ERR "pci_enable_device fail %p\n", pdev);
goto out;
}
@@ -664,14 +794,14 @@ bfad_pci_init(struct pci_dev *pdev, struct bfad_s *bfad)
if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0)
if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0) {
- BFA_PRINTF(BFA_ERR, "pci_set_dma_mask fail %p\n", pdev);
+ printk(KERN_ERR "pci_set_dma_mask fail %p\n", pdev);
goto out_release_region;
}
bfad->pci_bar0_kva = pci_iomap(pdev, 0, pci_resource_len(pdev, 0));
if (bfad->pci_bar0_kva == NULL) {
- BFA_PRINTF(BFA_ERR, "Fail to map bar0\n");
+ printk(KERN_ERR "Fail to map bar0\n");
goto out_release_region;
}
@@ -688,6 +818,54 @@ bfad_pci_init(struct pci_dev *pdev, struct bfad_s *bfad)
bfad->pci_attr.pcifn = PCI_FUNC(pdev->devfn);
bfad->pcidev = pdev;
+
+ /* Adjust PCIe Maximum Read Request Size */
+ if (pcie_max_read_reqsz > 0) {
+ int pcie_cap_reg;
+ u16 pcie_dev_ctl;
+ u16 mask = 0xffff;
+
+ switch (pcie_max_read_reqsz) {
+ case 128:
+ mask = 0x0;
+ break;
+ case 256:
+ mask = 0x1000;
+ break;
+ case 512:
+ mask = 0x2000;
+ break;
+ case 1024:
+ mask = 0x3000;
+ break;
+ case 2048:
+ mask = 0x4000;
+ break;
+ case 4096:
+ mask = 0x5000;
+ break;
+ default:
+ break;
+ }
+
+ pcie_cap_reg = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+ if (mask != 0xffff && pcie_cap_reg) {
+ pcie_cap_reg += 0x08;
+ pci_read_config_word(pdev, pcie_cap_reg, &pcie_dev_ctl);
+ if ((pcie_dev_ctl & 0x7000) != mask) {
+ printk(KERN_WARNING "BFA[%s]: "
+ "pcie_max_read_request_size is %d, "
+ "reset to %d\n", bfad->pci_name,
+ (1 << ((pcie_dev_ctl & 0x7000) >> 12)) << 7,
+ pcie_max_read_reqsz);
+
+ pcie_dev_ctl &= ~0x7000;
+ pci_write_config_word(pdev, pcie_cap_reg,
+ pcie_dev_ctl | mask);
+ }
+ }
+ }
+
return 0;
out_release_region:
@@ -710,25 +888,22 @@ bfad_pci_uninit(struct pci_dev *pdev, struct bfad_s *bfad)
void
bfad_fcs_port_cfg(struct bfad_s *bfad)
{
- struct bfa_port_cfg_s port_cfg;
- struct bfa_pport_attr_s attr;
- char symname[BFA_SYMNAME_MAXLEN];
+ struct bfa_lport_cfg_s port_cfg;
+ struct bfa_port_attr_s attr;
+ char symname[BFA_SYMNAME_MAXLEN];
sprintf(symname, "%s-%d", BFAD_DRIVER_NAME, bfad->inst_no);
memcpy(port_cfg.sym_name.symname, symname, strlen(symname));
bfa_fcport_get_attr(&bfad->bfa, &attr);
port_cfg.nwwn = attr.nwwn;
port_cfg.pwwn = attr.pwwn;
-
- bfa_fcs_cfg_base_port(&bfad->bfa_fcs, &port_cfg);
}
bfa_status_t
bfad_drv_init(struct bfad_s *bfad)
{
- bfa_status_t rc;
- unsigned long flags;
- struct bfa_fcs_driver_info_s driver_info;
+ bfa_status_t rc;
+ unsigned long flags;
bfad->cfg_data.rport_del_timeout = rport_del_timeout;
bfad->cfg_data.lun_queue_depth = bfa_lun_queue_depth;
@@ -740,15 +915,12 @@ bfad_drv_init(struct bfad_s *bfad)
printk(KERN_WARNING "bfad%d bfad_hal_mem_alloc failure\n",
bfad->inst_no);
printk(KERN_WARNING
- "Not enough memory to attach all Brocade HBA ports,"
- " System may need more memory.\n");
+ "Not enough memory to attach all Brocade HBA ports, %s",
+ "System may need more memory.\n");
goto out_hal_mem_alloc_failure;
}
- bfa_init_log(&bfad->bfa, bfad->logmod);
bfa_init_trc(&bfad->bfa, bfad->trcmod);
- bfa_init_aen(&bfad->bfa, bfad->aen);
- memset(bfad->file_map, 0, sizeof(bfad->file_map));
bfa_init_plog(&bfad->bfa, &bfad->plog_buf);
bfa_plog_init(&bfad->plog_buf);
bfa_plog_str(&bfad->plog_buf, BFA_PL_MID_DRVR, BFA_PL_EID_DRIVER_START,
@@ -757,77 +929,17 @@ bfad_drv_init(struct bfad_s *bfad)
bfa_attach(&bfad->bfa, bfad, &bfad->ioc_cfg, &bfad->meminfo,
&bfad->hal_pcidev);
- init_completion(&bfad->comp);
-
- /*
- * Enable Interrupt and wait bfa_init completion
- */
- if (bfad_setup_intr(bfad)) {
- printk(KERN_WARNING "bfad%d: bfad_setup_intr failed\n",
- bfad->inst_no);
- goto out_setup_intr_failure;
- }
-
+ /* FCS INIT */
spin_lock_irqsave(&bfad->bfad_lock, flags);
- bfa_init(&bfad->bfa);
- spin_unlock_irqrestore(&bfad->bfad_lock, flags);
-
- /*
- * Set up interrupt handler for each vectors
- */
- if ((bfad->bfad_flags & BFAD_MSIX_ON)
- && bfad_install_msix_handler(bfad)) {
- printk(KERN_WARNING "%s: install_msix failed, bfad%d\n",
- __func__, bfad->inst_no);
- }
-
- bfad_init_timer(bfad);
-
- wait_for_completion(&bfad->comp);
-
- memset(&driver_info, 0, sizeof(driver_info));
- strncpy(driver_info.version, BFAD_DRIVER_VERSION,
- sizeof(driver_info.version) - 1);
- __kernel_param_lock();
- if (host_name)
- strncpy(driver_info.host_machine_name, host_name,
- sizeof(driver_info.host_machine_name) - 1);
- if (os_name)
- strncpy(driver_info.host_os_name, os_name,
- sizeof(driver_info.host_os_name) - 1);
- if (os_patch)
- strncpy(driver_info.host_os_patch, os_patch,
- sizeof(driver_info.host_os_patch) - 1);
- __kernel_param_unlock();
-
- strncpy(driver_info.os_device_name, bfad->pci_name,
- sizeof(driver_info.os_device_name - 1));
-
- /*
- * FCS INIT
- */
- spin_lock_irqsave(&bfad->bfad_lock, flags);
- bfa_fcs_log_init(&bfad->bfa_fcs, bfad->logmod);
bfa_fcs_trc_init(&bfad->bfa_fcs, bfad->trcmod);
- bfa_fcs_aen_init(&bfad->bfa_fcs, bfad->aen);
bfa_fcs_attach(&bfad->bfa_fcs, &bfad->bfa, bfad, BFA_FALSE);
-
- /* Do FCS init only when HAL init is done */
- if ((bfad->bfad_flags & BFAD_HAL_INIT_DONE)) {
- bfa_fcs_init(&bfad->bfa_fcs);
- bfad->bfad_flags |= BFAD_FCS_INIT_DONE;
- }
-
- bfa_fcs_driver_info_init(&bfad->bfa_fcs, &driver_info);
bfa_fcs_set_fdmi_param(&bfad->bfa_fcs, fdmi_enable);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
bfad->bfad_flags |= BFAD_DRV_INIT_DONE;
+
return BFA_STATUS_OK;
-out_setup_intr_failure:
- bfa_detach(&bfad->bfa);
- bfad_hal_mem_release(bfad);
out_hal_mem_alloc_failure:
return BFA_STATUS_FAILED;
}
@@ -855,7 +967,7 @@ bfad_drv_uninit(struct bfad_s *bfad)
void
bfad_drv_start(struct bfad_s *bfad)
{
- unsigned long flags;
+ unsigned long flags;
spin_lock_irqsave(&bfad->bfad_lock, flags);
bfa_start(&bfad->bfa);
@@ -863,13 +975,14 @@ bfad_drv_start(struct bfad_s *bfad)
bfad->bfad_flags |= BFAD_HAL_START_DONE;
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
- bfad_fc4_probe_post(bfad);
+ if (bfad->im)
+ flush_workqueue(bfad->im->drv_workq);
}
void
-bfad_drv_stop(struct bfad_s *bfad)
+bfad_fcs_stop(struct bfad_s *bfad)
{
- unsigned long flags;
+ unsigned long flags;
spin_lock_irqsave(&bfad->bfad_lock, flags);
init_completion(&bfad->comp);
@@ -878,24 +991,32 @@ bfad_drv_stop(struct bfad_s *bfad)
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
wait_for_completion(&bfad->comp);
+ bfa_sm_send_event(bfad, BFAD_E_FCS_EXIT_COMP);
+}
+
+void
+bfad_stop(struct bfad_s *bfad)
+{
+ unsigned long flags;
+
spin_lock_irqsave(&bfad->bfad_lock, flags);
init_completion(&bfad->comp);
bfa_stop(&bfad->bfa);
bfad->bfad_flags &= ~BFAD_HAL_START_DONE;
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
wait_for_completion(&bfad->comp);
+
+ bfa_sm_send_event(bfad, BFAD_E_EXIT_COMP);
}
bfa_status_t
-bfad_cfg_pport(struct bfad_s *bfad, enum bfa_port_role role)
+bfad_cfg_pport(struct bfad_s *bfad, enum bfa_lport_role role)
{
- int rc = BFA_STATUS_OK;
+ int rc = BFA_STATUS_OK;
- /*
- * Allocate scsi_host for the physical port
- */
- if ((bfad_supported_fc4s & BFA_PORT_ROLE_FCP_IM)
- && (role & BFA_PORT_ROLE_FCP_IM)) {
+ /* Allocate scsi_host for the physical port */
+ if ((supported_fc4s & BFA_LPORT_ROLE_FCP_IM) &&
+ (role & BFA_LPORT_ROLE_FCP_IM)) {
if (bfad->pport.im_port == NULL) {
rc = BFA_STATUS_FAILED;
goto out;
@@ -906,7 +1027,7 @@ bfad_cfg_pport(struct bfad_s *bfad, enum bfa_port_role role)
if (rc != BFA_STATUS_OK)
goto out;
- bfad->pport.roles |= BFA_PORT_ROLE_FCP_IM;
+ bfad->pport.roles |= BFA_LPORT_ROLE_FCP_IM;
}
/* Setup the debugfs node for this scsi_host */
@@ -922,74 +1043,102 @@ out:
void
bfad_uncfg_pport(struct bfad_s *bfad)
{
- /* Remove the debugfs node for this scsi_host */
+ /* Remove the debugfs node for this scsi_host */
kfree(bfad->regdata);
bfad_debugfs_exit(&bfad->pport);
- if ((bfad->pport.roles & BFA_PORT_ROLE_FCP_IPFC) && ipfc_enable) {
- bfad_ipfc_port_delete(bfad, &bfad->pport);
- bfad->pport.roles &= ~BFA_PORT_ROLE_FCP_IPFC;
- }
-
- if ((bfad_supported_fc4s & BFA_PORT_ROLE_FCP_IM)
- && (bfad->pport.roles & BFA_PORT_ROLE_FCP_IM)) {
+ if ((supported_fc4s & BFA_LPORT_ROLE_FCP_IM) &&
+ (bfad->pport.roles & BFA_LPORT_ROLE_FCP_IM)) {
bfad_im_scsi_host_free(bfad, bfad->pport.im_port);
bfad_im_port_clean(bfad->pport.im_port);
kfree(bfad->pport.im_port);
- bfad->pport.roles &= ~BFA_PORT_ROLE_FCP_IM;
+ bfad->pport.roles &= ~BFA_LPORT_ROLE_FCP_IM;
}
bfad->bfad_flags &= ~BFAD_CFG_PPORT_DONE;
}
-void
-bfad_drv_log_level_set(struct bfad_s *bfad)
-{
- if (log_level > BFA_LOG_INVALID && log_level <= BFA_LOG_LEVEL_MAX)
- bfa_log_set_level_all(&bfad->log_data, log_level);
-}
-
bfa_status_t
-bfad_start_ops(struct bfad_s *bfad)
-{
- int retval;
- struct bfad_pcfg_s *pcfg, *pcfg_new;
+bfad_start_ops(struct bfad_s *bfad) {
+
+ int retval;
+ unsigned long flags;
+ struct bfad_vport_s *vport, *vport_new;
+ struct bfa_fcs_driver_info_s driver_info;
+
+ /* Fill the driver_info info to fcs*/
+ memset(&driver_info, 0, sizeof(driver_info));
+ strncpy(driver_info.version, BFAD_DRIVER_VERSION,
+ sizeof(driver_info.version) - 1);
+ if (host_name)
+ strncpy(driver_info.host_machine_name, host_name,
+ sizeof(driver_info.host_machine_name) - 1);
+ if (os_name)
+ strncpy(driver_info.host_os_name, os_name,
+ sizeof(driver_info.host_os_name) - 1);
+ if (os_patch)
+ strncpy(driver_info.host_os_patch, os_patch,
+ sizeof(driver_info.host_os_patch) - 1);
+
+ strncpy(driver_info.os_device_name, bfad->pci_name,
+ sizeof(driver_info.os_device_name - 1));
+
+ /* FCS INIT */
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ bfa_fcs_driver_info_init(&bfad->bfa_fcs, &driver_info);
+ bfa_fcs_init(&bfad->bfa_fcs);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
/* PPORT FCS config */
bfad_fcs_port_cfg(bfad);
- retval = bfad_cfg_pport(bfad, BFA_PORT_ROLE_FCP_IM);
- if (retval != BFA_STATUS_OK)
- goto out_cfg_pport_failure;
-
- /* BFAD level FC4 (IM/TM/IPFC) specific resource allocation */
- retval = bfad_fc4_probe(bfad);
+ retval = bfad_cfg_pport(bfad, BFA_LPORT_ROLE_FCP_IM);
if (retval != BFA_STATUS_OK) {
- printk(KERN_WARNING "bfad_fc4_probe failed\n");
- goto out_fc4_probe_failure;
+ if (bfa_sm_cmp_state(bfad, bfad_sm_initializing))
+ bfa_sm_set_state(bfad, bfad_sm_failed);
+ bfad_stop(bfad);
+ return BFA_STATUS_FAILED;
}
+ /* BFAD level FC4 IM specific resource allocation */
+ retval = bfad_im_probe(bfad);
+ if (retval != BFA_STATUS_OK) {
+ printk(KERN_WARNING "bfad_im_probe failed\n");
+ if (bfa_sm_cmp_state(bfad, bfad_sm_initializing))
+ bfa_sm_set_state(bfad, bfad_sm_failed);
+ bfad_im_probe_undo(bfad);
+ bfad->bfad_flags &= ~BFAD_FC4_PROBE_DONE;
+ bfad_uncfg_pport(bfad);
+ bfad_stop(bfad);
+ return BFA_STATUS_FAILED;
+ } else
+ bfad->bfad_flags |= BFAD_FC4_PROBE_DONE;
+
bfad_drv_start(bfad);
- /* pbc vport creation */
- list_for_each_entry_safe(pcfg, pcfg_new, &bfad->pbc_pcfg_list,
- list_entry) {
+ /* Complete pbc vport create */
+ list_for_each_entry_safe(vport, vport_new, &bfad->pbc_vport_list,
+ list_entry) {
struct fc_vport_identifiers vid;
struct fc_vport *fc_vport;
+ char pwwn_buf[BFA_STRING_32];
memset(&vid, 0, sizeof(vid));
vid.roles = FC_PORT_ROLE_FCP_INITIATOR;
vid.vport_type = FC_PORTTYPE_NPIV;
vid.disable = false;
- vid.node_name = wwn_to_u64((u8 *)&pcfg->port_cfg.nwwn);
- vid.port_name = wwn_to_u64((u8 *)&pcfg->port_cfg.pwwn);
+ vid.node_name = wwn_to_u64((u8 *)
+ (&((vport->fcs_vport).lport.port_cfg.nwwn)));
+ vid.port_name = wwn_to_u64((u8 *)
+ (&((vport->fcs_vport).lport.port_cfg.pwwn)));
fc_vport = fc_vport_create(bfad->pport.im_port->shost, 0, &vid);
- if (!fc_vport)
+ if (!fc_vport) {
+ wwn2str(pwwn_buf, vid.port_name);
printk(KERN_WARNING "bfad%d: failed to create pbc vport"
- " %llx\n", bfad->inst_no, vid.port_name);
- list_del(&pcfg->list_entry);
- kfree(pcfg);
-
+ " %s\n", bfad->inst_no, pwwn_buf);
+ }
+ list_del(&vport->list_entry);
+ kfree(vport);
}
/*
@@ -998,24 +1147,15 @@ bfad_start_ops(struct bfad_s *bfad)
* passed in module param value as the bfa_linkup_delay.
*/
if (bfa_linkup_delay < 0) {
-
bfa_linkup_delay = bfad_os_get_linkup_delay(bfad);
bfad_os_rport_online_wait(bfad);
bfa_linkup_delay = -1;
-
- } else {
+ } else
bfad_os_rport_online_wait(bfad);
- }
- bfa_log(bfad->logmod, BFA_LOG_LINUX_DEVICE_CLAIMED, bfad->pci_name);
+ BFA_LOG(KERN_INFO, bfad, log_level, "bfa device claimed\n");
return BFA_STATUS_OK;
-
-out_fc4_probe_failure:
- bfad_fc4_probe_undo(bfad);
- bfad_uncfg_pport(bfad);
-out_cfg_pport_failure:
- return BFA_STATUS_FAILED;
}
int
@@ -1028,18 +1168,8 @@ bfad_worker(void *ptr)
while (!kthread_should_stop()) {
- /* Check if the FCS init is done from bfad_drv_init;
- * if not done do FCS init and set the flag.
- */
- if (!(bfad->bfad_flags & BFAD_FCS_INIT_DONE)) {
- spin_lock_irqsave(&bfad->bfad_lock, flags);
- bfa_fcs_init(&bfad->bfa_fcs);
- bfad->bfad_flags |= BFAD_FCS_INIT_DONE;
- spin_unlock_irqrestore(&bfad->bfad_lock, flags);
- }
-
- /* Start the bfad operations after HAL init done */
- bfad_start_ops(bfad);
+ /* Send event BFAD_E_INIT_SUCCESS */
+ bfa_sm_send_event(bfad, BFAD_E_INIT_SUCCESS);
spin_lock_irqsave(&bfad->bfad_lock, flags);
bfad->bfad_tsk = NULL;
@@ -1051,9 +1181,198 @@ bfad_worker(void *ptr)
return 0;
}
- /*
- * PCI_entry PCI driver entries * {
- */
+/**
+ * BFA driver interrupt functions
+ */
+irqreturn_t
+bfad_intx(int irq, void *dev_id)
+{
+ struct bfad_s *bfad = dev_id;
+ struct list_head doneq;
+ unsigned long flags;
+ bfa_boolean_t rc;
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ rc = bfa_intx(&bfad->bfa);
+ if (!rc) {
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ return IRQ_NONE;
+ }
+
+ bfa_comp_deq(&bfad->bfa, &doneq);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+ if (!list_empty(&doneq)) {
+ bfa_comp_process(&bfad->bfa, &doneq);
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ bfa_comp_free(&bfad->bfa, &doneq);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ bfa_trc_fp(bfad, irq);
+ }
+
+ return IRQ_HANDLED;
+
+}
+
+static irqreturn_t
+bfad_msix(int irq, void *dev_id)
+{
+ struct bfad_msix_s *vec = dev_id;
+ struct bfad_s *bfad = vec->bfad;
+ struct list_head doneq;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+
+ bfa_msix(&bfad->bfa, vec->msix.entry);
+ bfa_comp_deq(&bfad->bfa, &doneq);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+ if (!list_empty(&doneq)) {
+ bfa_comp_process(&bfad->bfa, &doneq);
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ bfa_comp_free(&bfad->bfa, &doneq);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+ }
+
+ return IRQ_HANDLED;
+}
+
+/**
+ * Initialize the MSIX entry table.
+ */
+static void
+bfad_init_msix_entry(struct bfad_s *bfad, struct msix_entry *msix_entries,
+ int mask, int max_bit)
+{
+ int i;
+ int match = 0x00000001;
+
+ for (i = 0, bfad->nvec = 0; i < MAX_MSIX_ENTRY; i++) {
+ if (mask & match) {
+ bfad->msix_tab[bfad->nvec].msix.entry = i;
+ bfad->msix_tab[bfad->nvec].bfad = bfad;
+ msix_entries[bfad->nvec].entry = i;
+ bfad->nvec++;
+ }
+
+ match <<= 1;
+ }
+
+}
+
+int
+bfad_install_msix_handler(struct bfad_s *bfad)
+{
+ int i, error = 0;
+
+ for (i = 0; i < bfad->nvec; i++) {
+ sprintf(bfad->msix_tab[i].name, "bfa-%s-%s",
+ bfad->pci_name,
+ ((bfa_asic_id_ct(bfad->hal_pcidev.device_id)) ?
+ msix_name_ct[i] : msix_name_cb[i]));
+
+ error = request_irq(bfad->msix_tab[i].msix.vector,
+ (irq_handler_t) bfad_msix, 0,
+ bfad->msix_tab[i].name, &bfad->msix_tab[i]);
+ bfa_trc(bfad, i);
+ bfa_trc(bfad, bfad->msix_tab[i].msix.vector);
+ if (error) {
+ int j;
+
+ for (j = 0; j < i; j++)
+ free_irq(bfad->msix_tab[j].msix.vector,
+ &bfad->msix_tab[j]);
+
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Setup MSIX based interrupt.
+ */
+int
+bfad_setup_intr(struct bfad_s *bfad)
+{
+ int error = 0;
+ u32 mask = 0, i, num_bit = 0, max_bit = 0;
+ struct msix_entry msix_entries[MAX_MSIX_ENTRY];
+ struct pci_dev *pdev = bfad->pcidev;
+
+ /* Call BFA to get the msix map for this PCI function. */
+ bfa_msix_getvecs(&bfad->bfa, &mask, &num_bit, &max_bit);
+
+ /* Set up the msix entry table */
+ bfad_init_msix_entry(bfad, msix_entries, mask, max_bit);
+
+ if ((bfa_asic_id_ct(pdev->device) && !msix_disable_ct) ||
+ (!bfa_asic_id_ct(pdev->device) && !msix_disable_cb)) {
+
+ error = pci_enable_msix(bfad->pcidev, msix_entries, bfad->nvec);
+ if (error) {
+ /*
+ * Only error number of vector is available.
+ * We don't have a mechanism to map multiple
+ * interrupts into one vector, so even if we
+ * can try to request less vectors, we don't
+ * know how to associate interrupt events to
+ * vectors. Linux doesn't dupicate vectors
+ * in the MSIX table for this case.
+ */
+
+ printk(KERN_WARNING "bfad%d: "
+ "pci_enable_msix failed (%d),"
+ " use line based.\n", bfad->inst_no, error);
+
+ goto line_based;
+ }
+
+ /* Save the vectors */
+ for (i = 0; i < bfad->nvec; i++) {
+ bfa_trc(bfad, msix_entries[i].vector);
+ bfad->msix_tab[i].msix.vector = msix_entries[i].vector;
+ }
+
+ bfa_msix_init(&bfad->bfa, bfad->nvec);
+
+ bfad->bfad_flags |= BFAD_MSIX_ON;
+
+ return error;
+ }
+
+line_based:
+ error = 0;
+ if (request_irq
+ (bfad->pcidev->irq, (irq_handler_t) bfad_intx, BFAD_IRQ_FLAGS,
+ BFAD_DRIVER_NAME, bfad) != 0) {
+ /* Enable interrupt handler failed */
+ return 1;
+ }
+
+ return error;
+}
+
+void
+bfad_remove_intr(struct bfad_s *bfad)
+{
+ int i;
+
+ if (bfad->bfad_flags & BFAD_MSIX_ON) {
+ for (i = 0; i < bfad->nvec; i++)
+ free_irq(bfad->msix_tab[i].msix.vector,
+ &bfad->msix_tab[i]);
+
+ pci_disable_msix(bfad->pcidev);
+ bfad->bfad_flags &= ~BFAD_MSIX_ON;
+ } else {
+ free_irq(bfad->pcidev->irq, bfad);
+ }
+}
/**
* PCI probe entry.
@@ -1061,18 +1380,14 @@ bfad_worker(void *ptr)
int
bfad_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid)
{
- struct bfad_s *bfad;
- int error = -ENODEV, retval;
+ struct bfad_s *bfad;
+ int error = -ENODEV, retval;
- /*
- * For single port cards - only claim function 0
- */
- if ((pdev->device == BFA_PCI_DEVICE_ID_FC_8G1P)
- && (PCI_FUNC(pdev->devfn) != 0))
+ /* For single port cards - only claim function 0 */
+ if ((pdev->device == BFA_PCI_DEVICE_ID_FC_8G1P) &&
+ (PCI_FUNC(pdev->devfn) != 0))
return -ENODEV;
- BFA_TRACE(BFA_INFO, "bfad_pci_probe entry");
-
bfad = kzalloc(sizeof(struct bfad_s), GFP_KERNEL);
if (!bfad) {
error = -ENOMEM;
@@ -1086,21 +1401,11 @@ bfad_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid)
goto out_alloc_trace_failure;
}
- /*
- * LOG/TRACE INIT
- */
+ /* TRACE INIT */
bfa_trc_init(bfad->trcmod);
bfa_trc(bfad, bfad_inst);
- bfad->logmod = &bfad->log_data;
- bfa_log_init(bfad->logmod, (char *)pci_name(pdev), bfa_os_printf);
-
- bfad_drv_log_level_set(bfad);
-
- bfad->aen = &bfad->aen_buf;
-
if (!(bfad_load_fwimg(pdev))) {
- printk(KERN_WARNING "bfad_load_fwimg failure!\n");
kfree(bfad->trcmod);
goto out_alloc_trace_failure;
}
@@ -1117,46 +1422,31 @@ bfad_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid)
list_add_tail(&bfad->list_entry, &bfad_list);
mutex_unlock(&bfad_mutex);
+ /* Initializing the state machine: State set to uninit */
+ bfa_sm_set_state(bfad, bfad_sm_uninit);
+
spin_lock_init(&bfad->bfad_lock);
pci_set_drvdata(pdev, bfad);
bfad->ref_count = 0;
bfad->pport.bfad = bfad;
- INIT_LIST_HEAD(&bfad->pbc_pcfg_list);
-
- bfad->bfad_tsk = kthread_create(bfad_worker, (void *) bfad, "%s",
- "bfad_worker");
- if (IS_ERR(bfad->bfad_tsk)) {
- printk(KERN_INFO "bfad[%d]: Kernel thread"
- " creation failed!\n",
- bfad->inst_no);
- goto out_kthread_create_failure;
- }
+ INIT_LIST_HEAD(&bfad->pbc_vport_list);
retval = bfad_drv_init(bfad);
if (retval != BFA_STATUS_OK)
goto out_drv_init_failure;
- if (!(bfad->bfad_flags & BFAD_HAL_INIT_DONE)) {
- bfad->bfad_flags |= BFAD_HAL_INIT_FAIL;
- printk(KERN_WARNING "bfad%d: hal init failed\n", bfad->inst_no);
- goto ok;
- }
- retval = bfad_start_ops(bfad);
- if (retval != BFA_STATUS_OK)
- goto out_start_ops_failure;
+ bfa_sm_send_event(bfad, BFAD_E_CREATE);
- kthread_stop(bfad->bfad_tsk);
- bfad->bfad_tsk = NULL;
+ if (bfa_sm_cmp_state(bfad, bfad_sm_uninit))
+ goto out_bfad_sm_failure;
-ok:
return 0;
-out_start_ops_failure:
- bfad_drv_uninit(bfad);
+out_bfad_sm_failure:
+ bfa_detach(&bfad->bfa);
+ bfad_hal_mem_release(bfad);
out_drv_init_failure:
- kthread_stop(bfad->bfad_tsk);
-out_kthread_create_failure:
mutex_lock(&bfad_mutex);
bfad_inst--;
list_del(&bfad->list_entry);
@@ -1176,62 +1466,29 @@ out:
void
bfad_pci_remove(struct pci_dev *pdev)
{
- struct bfad_s *bfad = pci_get_drvdata(pdev);
- unsigned long flags;
+ struct bfad_s *bfad = pci_get_drvdata(pdev);
+ unsigned long flags;
bfa_trc(bfad, bfad->inst_no);
spin_lock_irqsave(&bfad->bfad_lock, flags);
- if (bfad->bfad_tsk != NULL)
- kthread_stop(bfad->bfad_tsk);
- spin_unlock_irqrestore(&bfad->bfad_lock, flags);
-
- if ((bfad->bfad_flags & BFAD_DRV_INIT_DONE)
- && !(bfad->bfad_flags & BFAD_HAL_INIT_DONE)) {
-
- spin_lock_irqsave(&bfad->bfad_lock, flags);
- init_completion(&bfad->comp);
- bfa_stop(&bfad->bfa);
+ if (bfad->bfad_tsk != NULL) {
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
- wait_for_completion(&bfad->comp);
-
- bfad_remove_intr(bfad);
- del_timer_sync(&bfad->hal_tmo);
- goto hal_detach;
- } else if (!(bfad->bfad_flags & BFAD_DRV_INIT_DONE)) {
- goto remove_sysfs;
- }
-
- if (bfad->bfad_flags & BFAD_HAL_START_DONE) {
- bfad_drv_stop(bfad);
- } else if (bfad->bfad_flags & BFAD_DRV_INIT_DONE) {
- /* Invoking bfa_stop() before bfa_detach
- * when HAL and DRV init are success
- * but HAL start did not occur.
- */
- spin_lock_irqsave(&bfad->bfad_lock, flags);
- init_completion(&bfad->comp);
- bfa_stop(&bfad->bfa);
+ kthread_stop(bfad->bfad_tsk);
+ } else {
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
- wait_for_completion(&bfad->comp);
}
- bfad_remove_intr(bfad);
- del_timer_sync(&bfad->hal_tmo);
+ /* Send Event BFAD_E_STOP */
+ bfa_sm_send_event(bfad, BFAD_E_STOP);
- if (bfad->bfad_flags & BFAD_FC4_PROBE_DONE)
- bfad_fc4_probe_undo(bfad);
-
- if (bfad->bfad_flags & BFAD_CFG_PPORT_DONE)
- bfad_uncfg_pport(bfad);
-
-hal_detach:
+ /* Driver detach and dealloc mem */
spin_lock_irqsave(&bfad->bfad_lock, flags);
bfa_detach(&bfad->bfa);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
bfad_hal_mem_release(bfad);
-remove_sysfs:
+ /* Cleaning the BFAD instance */
mutex_lock(&bfad_mutex);
bfad_inst--;
list_del(&bfad->list_entry);
@@ -1242,35 +1499,34 @@ remove_sysfs:
kfree(bfad);
}
-
-static struct pci_device_id bfad_id_table[] = {
+struct pci_device_id bfad_id_table[] = {
{
- .vendor = BFA_PCI_VENDOR_ID_BROCADE,
- .device = BFA_PCI_DEVICE_ID_FC_8G2P,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- },
+ .vendor = BFA_PCI_VENDOR_ID_BROCADE,
+ .device = BFA_PCI_DEVICE_ID_FC_8G2P,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ },
{
- .vendor = BFA_PCI_VENDOR_ID_BROCADE,
- .device = BFA_PCI_DEVICE_ID_FC_8G1P,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- },
+ .vendor = BFA_PCI_VENDOR_ID_BROCADE,
+ .device = BFA_PCI_DEVICE_ID_FC_8G1P,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ },
{
- .vendor = BFA_PCI_VENDOR_ID_BROCADE,
- .device = BFA_PCI_DEVICE_ID_CT,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .class = (PCI_CLASS_SERIAL_FIBER << 8),
- .class_mask = ~0,
- },
+ .vendor = BFA_PCI_VENDOR_ID_BROCADE,
+ .device = BFA_PCI_DEVICE_ID_CT,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .class = (PCI_CLASS_SERIAL_FIBER << 8),
+ .class_mask = ~0,
+ },
{
- .vendor = BFA_PCI_VENDOR_ID_BROCADE,
- .device = BFA_PCI_DEVICE_ID_CT_FC,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .class = (PCI_CLASS_SERIAL_FIBER << 8),
- .class_mask = ~0,
+ .vendor = BFA_PCI_VENDOR_ID_BROCADE,
+ .device = BFA_PCI_DEVICE_ID_CT_FC,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .class = (PCI_CLASS_SERIAL_FIBER << 8),
+ .class_mask = ~0,
},
{0, 0},
@@ -1286,89 +1542,104 @@ static struct pci_driver bfad_pci_driver = {
};
/**
- * Linux driver module functions
- */
-bfa_status_t
-bfad_fc4_module_init(void)
-{
- int rc;
-
- rc = bfad_im_module_init();
- if (rc != BFA_STATUS_OK)
- goto ext;
-
- bfad_tm_module_init();
- if (ipfc_enable)
- bfad_ipfc_module_init();
-ext:
- return rc;
-}
-
-void
-bfad_fc4_module_exit(void)
-{
- if (ipfc_enable)
- bfad_ipfc_module_exit();
- bfad_tm_module_exit();
- bfad_im_module_exit();
-}
-
-/**
* Driver module init.
*/
-static int __init
+static int __init
bfad_init(void)
{
- int error = 0;
+ int error = 0;
printk(KERN_INFO "Brocade BFA FC/FCOE SCSI driver - version: %s\n",
- BFAD_DRIVER_VERSION);
+ BFAD_DRIVER_VERSION);
if (num_sgpgs > 0)
num_sgpgs_parm = num_sgpgs;
- error = bfad_fc4_module_init();
+ error = bfad_im_module_init();
if (error) {
error = -ENOMEM;
- printk(KERN_WARNING "bfad_fc4_module_init failure\n");
+ printk(KERN_WARNING "bfad_im_module_init failure\n");
goto ext;
}
- if (!strcmp(FCPI_NAME, " fcpim"))
- bfad_supported_fc4s |= BFA_PORT_ROLE_FCP_IM;
- if (!strcmp(FCPT_NAME, " fcptm"))
- bfad_supported_fc4s |= BFA_PORT_ROLE_FCP_TM;
- if (!strcmp(IPFC_NAME, " ipfc"))
- bfad_supported_fc4s |= BFA_PORT_ROLE_FCP_IPFC;
+ if (strcmp(FCPI_NAME, " fcpim") == 0)
+ supported_fc4s |= BFA_LPORT_ROLE_FCP_IM;
bfa_ioc_auto_recover(ioc_auto_recover);
bfa_fcs_rport_set_del_timeout(rport_del_timeout);
- error = pci_register_driver(&bfad_pci_driver);
+ error = pci_register_driver(&bfad_pci_driver);
if (error) {
- printk(KERN_WARNING "bfad pci_register_driver failure\n");
+ printk(KERN_WARNING "pci_register_driver failure\n");
goto ext;
}
return 0;
ext:
- bfad_fc4_module_exit();
+ bfad_im_module_exit();
return error;
}
/**
* Driver module exit.
*/
-static void __exit
+static void __exit
bfad_exit(void)
{
pci_unregister_driver(&bfad_pci_driver);
- bfad_fc4_module_exit();
+ bfad_im_module_exit();
bfad_free_fwimg();
}
-#define BFAD_PROTO_NAME FCPI_NAME FCPT_NAME IPFC_NAME
+/* Firmware handling */
+u32 *
+bfad_read_firmware(struct pci_dev *pdev, u32 **bfi_image,
+ u32 *bfi_image_size, char *fw_name)
+{
+ const struct firmware *fw;
+
+ if (request_firmware(&fw, fw_name, &pdev->dev)) {
+ printk(KERN_ALERT "Can't locate firmware %s\n", fw_name);
+ goto error;
+ }
+
+ *bfi_image = vmalloc(fw->size);
+ if (NULL == *bfi_image) {
+ printk(KERN_ALERT "Fail to allocate buffer for fw image "
+ "size=%x!\n", (u32) fw->size);
+ goto error;
+ }
+
+ memcpy(*bfi_image, fw->data, fw->size);
+ *bfi_image_size = fw->size/sizeof(u32);
+
+ return *bfi_image;
+
+error:
+ return NULL;
+}
+
+u32 *
+bfad_get_firmware_buf(struct pci_dev *pdev)
+{
+ if (pdev->device == BFA_PCI_DEVICE_ID_CT_FC) {
+ if (bfi_image_ct_fc_size == 0)
+ bfad_read_firmware(pdev, &bfi_image_ct_fc,
+ &bfi_image_ct_fc_size, BFAD_FW_FILE_CT_FC);
+ return bfi_image_ct_fc;
+ } else if (pdev->device == BFA_PCI_DEVICE_ID_CT) {
+ if (bfi_image_ct_cna_size == 0)
+ bfad_read_firmware(pdev, &bfi_image_ct_cna,
+ &bfi_image_ct_cna_size, BFAD_FW_FILE_CT_CNA);
+ return bfi_image_ct_cna;
+ } else {
+ if (bfi_image_cb_fc_size == 0)
+ bfad_read_firmware(pdev, &bfi_image_cb_fc,
+ &bfi_image_cb_fc_size, BFAD_FW_FILE_CB_FC);
+ return bfi_image_cb_fc;
+ }
+}
module_init(bfad_init);
module_exit(bfad_exit);
@@ -1376,5 +1647,3 @@ MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Brocade Fibre Channel HBA Driver" BFAD_PROTO_NAME);
MODULE_AUTHOR("Brocade Communications Systems, Inc.");
MODULE_VERSION(BFAD_DRIVER_VERSION);
-
-
diff --git a/drivers/scsi/bfa/bfad_attr.c b/drivers/scsi/bfa/bfad_attr.c
index 0818eb07ef88..d8843720eac1 100644
--- a/drivers/scsi/bfa/bfad_attr.c
+++ b/drivers/scsi/bfa/bfad_attr.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
* All rights reserved
* www.brocade.com
*
@@ -19,15 +19,8 @@
* bfa_attr.c Linux driver configuration interface module.
*/
-#include <linux/slab.h>
#include "bfad_drv.h"
#include "bfad_im.h"
-#include "bfad_trcmod.h"
-#include "bfad_attr.h"
-
-/**
- * FC_transport_template FC transport template
- */
/**
* FC transport template entry, get SCSI target port ID.
@@ -42,7 +35,7 @@ bfad_im_get_starget_port_id(struct scsi_target *starget)
u32 fc_id = -1;
unsigned long flags;
- shost = bfad_os_starget_to_shost(starget);
+ shost = dev_to_shost(starget->dev.parent);
im_port = (struct bfad_im_port_s *) shost->hostdata[0];
bfad = im_port->bfad;
spin_lock_irqsave(&bfad->bfad_lock, flags);
@@ -68,7 +61,7 @@ bfad_im_get_starget_node_name(struct scsi_target *starget)
u64 node_name = 0;
unsigned long flags;
- shost = bfad_os_starget_to_shost(starget);
+ shost = dev_to_shost(starget->dev.parent);
im_port = (struct bfad_im_port_s *) shost->hostdata[0];
bfad = im_port->bfad;
spin_lock_irqsave(&bfad->bfad_lock, flags);
@@ -94,7 +87,7 @@ bfad_im_get_starget_port_name(struct scsi_target *starget)
u64 port_name = 0;
unsigned long flags;
- shost = bfad_os_starget_to_shost(starget);
+ shost = dev_to_shost(starget->dev.parent);
im_port = (struct bfad_im_port_s *) shost->hostdata[0];
bfad = im_port->bfad;
spin_lock_irqsave(&bfad->bfad_lock, flags);
@@ -118,17 +111,7 @@ bfad_im_get_host_port_id(struct Scsi_Host *shost)
struct bfad_port_s *port = im_port->port;
fc_host_port_id(shost) =
- bfa_os_hton3b(bfa_fcs_port_get_fcid(port->fcs_port));
-}
-
-
-
-
-
-struct Scsi_Host *
-bfad_os_starget_to_shost(struct scsi_target *starget)
-{
- return dev_to_shost(starget->dev.parent);
+ bfa_os_hton3b(bfa_fcs_lport_get_fcid(port->fcs_port));
}
/**
@@ -140,21 +123,21 @@ bfad_im_get_host_port_type(struct Scsi_Host *shost)
struct bfad_im_port_s *im_port =
(struct bfad_im_port_s *) shost->hostdata[0];
struct bfad_s *bfad = im_port->bfad;
- struct bfa_pport_attr_s attr;
+ struct bfa_lport_attr_s port_attr;
- bfa_fcport_get_attr(&bfad->bfa, &attr);
+ bfa_fcs_lport_get_attr(&bfad->bfa_fcs.fabric.bport, &port_attr);
- switch (attr.port_type) {
- case BFA_PPORT_TYPE_NPORT:
+ switch (port_attr.port_type) {
+ case BFA_PORT_TYPE_NPORT:
fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
break;
- case BFA_PPORT_TYPE_NLPORT:
+ case BFA_PORT_TYPE_NLPORT:
fc_host_port_type(shost) = FC_PORTTYPE_NLPORT;
break;
- case BFA_PPORT_TYPE_P2P:
+ case BFA_PORT_TYPE_P2P:
fc_host_port_type(shost) = FC_PORTTYPE_PTP;
break;
- case BFA_PPORT_TYPE_LPORT:
+ case BFA_PORT_TYPE_LPORT:
fc_host_port_type(shost) = FC_PORTTYPE_LPORT;
break;
default:
@@ -172,25 +155,28 @@ bfad_im_get_host_port_state(struct Scsi_Host *shost)
struct bfad_im_port_s *im_port =
(struct bfad_im_port_s *) shost->hostdata[0];
struct bfad_s *bfad = im_port->bfad;
- struct bfa_pport_attr_s attr;
+ struct bfa_port_attr_s attr;
bfa_fcport_get_attr(&bfad->bfa, &attr);
switch (attr.port_state) {
- case BFA_PPORT_ST_LINKDOWN:
+ case BFA_PORT_ST_LINKDOWN:
fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN;
break;
- case BFA_PPORT_ST_LINKUP:
+ case BFA_PORT_ST_LINKUP:
fc_host_port_state(shost) = FC_PORTSTATE_ONLINE;
break;
- case BFA_PPORT_ST_UNINIT:
- case BFA_PPORT_ST_ENABLING_QWAIT:
- case BFA_PPORT_ST_ENABLING:
- case BFA_PPORT_ST_DISABLING_QWAIT:
- case BFA_PPORT_ST_DISABLING:
- case BFA_PPORT_ST_DISABLED:
- case BFA_PPORT_ST_STOPPED:
- case BFA_PPORT_ST_IOCDOWN:
+ case BFA_PORT_ST_DISABLED:
+ case BFA_PORT_ST_STOPPED:
+ case BFA_PORT_ST_IOCDOWN:
+ case BFA_PORT_ST_IOCDIS:
+ fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE;
+ break;
+ case BFA_PORT_ST_UNINIT:
+ case BFA_PORT_ST_ENABLING_QWAIT:
+ case BFA_PORT_ST_ENABLING:
+ case BFA_PORT_ST_DISABLING_QWAIT:
+ case BFA_PORT_ST_DISABLING:
default:
fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN;
break;
@@ -210,13 +196,9 @@ bfad_im_get_host_active_fc4s(struct Scsi_Host *shost)
memset(fc_host_active_fc4s(shost), 0,
sizeof(fc_host_active_fc4s(shost)));
- if (port->supported_fc4s &
- (BFA_PORT_ROLE_FCP_IM | BFA_PORT_ROLE_FCP_TM))
+ if (port->supported_fc4s & BFA_LPORT_ROLE_FCP_IM)
fc_host_active_fc4s(shost)[2] = 1;
- if (port->supported_fc4s & BFA_PORT_ROLE_FCP_IPFC)
- fc_host_active_fc4s(shost)[3] = 0x20;
-
fc_host_active_fc4s(shost)[7] = 1;
}
@@ -229,29 +211,29 @@ bfad_im_get_host_speed(struct Scsi_Host *shost)
struct bfad_im_port_s *im_port =
(struct bfad_im_port_s *) shost->hostdata[0];
struct bfad_s *bfad = im_port->bfad;
- struct bfa_pport_attr_s attr;
- unsigned long flags;
+ struct bfa_port_attr_s attr;
- spin_lock_irqsave(shost->host_lock, flags);
bfa_fcport_get_attr(&bfad->bfa, &attr);
switch (attr.speed) {
- case BFA_PPORT_SPEED_8GBPS:
+ case BFA_PORT_SPEED_10GBPS:
+ fc_host_speed(shost) = FC_PORTSPEED_10GBIT;
+ break;
+ case BFA_PORT_SPEED_8GBPS:
fc_host_speed(shost) = FC_PORTSPEED_8GBIT;
break;
- case BFA_PPORT_SPEED_4GBPS:
+ case BFA_PORT_SPEED_4GBPS:
fc_host_speed(shost) = FC_PORTSPEED_4GBIT;
break;
- case BFA_PPORT_SPEED_2GBPS:
+ case BFA_PORT_SPEED_2GBPS:
fc_host_speed(shost) = FC_PORTSPEED_2GBIT;
break;
- case BFA_PPORT_SPEED_1GBPS:
+ case BFA_PORT_SPEED_1GBPS:
fc_host_speed(shost) = FC_PORTSPEED_1GBIT;
break;
default:
fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
break;
}
- spin_unlock_irqrestore(shost->host_lock, flags);
}
/**
@@ -265,7 +247,7 @@ bfad_im_get_host_fabric_name(struct Scsi_Host *shost)
struct bfad_port_s *port = im_port->port;
wwn_t fabric_nwwn = 0;
- fabric_nwwn = bfa_fcs_port_get_fabric_name(port->fcs_port);
+ fabric_nwwn = bfa_fcs_lport_get_fabric_name(port->fcs_port);
fc_host_fabric_name(shost) = bfa_os_htonll(fabric_nwwn);
@@ -281,23 +263,44 @@ bfad_im_get_stats(struct Scsi_Host *shost)
(struct bfad_im_port_s *) shost->hostdata[0];
struct bfad_s *bfad = im_port->bfad;
struct bfad_hal_comp fcomp;
+ union bfa_port_stats_u *fcstats;
struct fc_host_statistics *hstats;
bfa_status_t rc;
unsigned long flags;
+ fcstats = kzalloc(sizeof(union bfa_port_stats_u), GFP_KERNEL);
+ if (fcstats == NULL)
+ return NULL;
+
hstats = &bfad->link_stats;
init_completion(&fcomp.comp);
spin_lock_irqsave(&bfad->bfad_lock, flags);
memset(hstats, 0, sizeof(struct fc_host_statistics));
- rc = bfa_port_get_stats(BFA_FCPORT(&bfad->bfa),
- (union bfa_pport_stats_u *) hstats,
- bfad_hcb_comp, &fcomp);
+ rc = bfa_port_get_stats(BFA_FCPORT(&bfad->bfa),
+ fcstats, bfad_hcb_comp, &fcomp);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
if (rc != BFA_STATUS_OK)
return NULL;
wait_for_completion(&fcomp.comp);
+ /* Fill the fc_host_statistics structure */
+ hstats->seconds_since_last_reset = fcstats->fc.secs_reset;
+ hstats->tx_frames = fcstats->fc.tx_frames;
+ hstats->tx_words = fcstats->fc.tx_words;
+ hstats->rx_frames = fcstats->fc.rx_frames;
+ hstats->rx_words = fcstats->fc.rx_words;
+ hstats->lip_count = fcstats->fc.lip_count;
+ hstats->nos_count = fcstats->fc.nos_count;
+ hstats->error_frames = fcstats->fc.error_frames;
+ hstats->dumped_frames = fcstats->fc.dropped_frames;
+ hstats->link_failure_count = fcstats->fc.link_failures;
+ hstats->loss_of_sync_count = fcstats->fc.loss_of_syncs;
+ hstats->loss_of_signal_count = fcstats->fc.loss_of_signals;
+ hstats->prim_seq_protocol_err_count = fcstats->fc.primseq_errs;
+ hstats->invalid_crc_count = fcstats->fc.invalid_crcs;
+
+ kfree(fcstats);
return hstats;
}
@@ -317,7 +320,7 @@ bfad_im_reset_stats(struct Scsi_Host *shost)
init_completion(&fcomp.comp);
spin_lock_irqsave(&bfad->bfad_lock, flags);
rc = bfa_port_clear_stats(BFA_FCPORT(&bfad->bfa), bfad_hcb_comp,
- &fcomp);
+ &fcomp);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
if (rc != BFA_STATUS_OK)
@@ -372,8 +375,8 @@ bfad_im_vport_create(struct fc_vport *fc_vport, bool disable)
struct bfad_im_port_s *im_port =
(struct bfad_im_port_s *) shost->hostdata[0];
struct bfad_s *bfad = im_port->bfad;
- struct bfa_port_cfg_s port_cfg;
- struct bfad_pcfg_s *pcfg;
+ struct bfa_lport_cfg_s port_cfg;
+ struct bfad_vport_s *vp;
int status = 0, rc;
unsigned long flags;
@@ -382,12 +385,14 @@ bfad_im_vport_create(struct fc_vport *fc_vport, bool disable)
u64_to_wwn(fc_vport->port_name, (u8 *)&port_cfg.pwwn);
if (strlen(vname) > 0)
strcpy((char *)&port_cfg.sym_name, vname);
- port_cfg.roles = BFA_PORT_ROLE_FCP_IM;
+ port_cfg.roles = BFA_LPORT_ROLE_FCP_IM;
spin_lock_irqsave(&bfad->bfad_lock, flags);
- list_for_each_entry(pcfg, &bfad->pbc_pcfg_list, list_entry) {
- if (port_cfg.pwwn == pcfg->port_cfg.pwwn) {
- port_cfg.preboot_vp = pcfg->port_cfg.preboot_vp;
+ list_for_each_entry(vp, &bfad->pbc_vport_list, list_entry) {
+ if (port_cfg.pwwn ==
+ vp->fcs_vport.lport.port_cfg.pwwn) {
+ port_cfg.preboot_vp =
+ vp->fcs_vport.lport.port_cfg.preboot_vp;
break;
}
}
@@ -638,7 +643,7 @@ bfad_im_serial_num_show(struct device *dev, struct device_attribute *attr,
struct Scsi_Host *shost = class_to_shost(dev);
struct bfad_im_port_s *im_port =
(struct bfad_im_port_s *) shost->hostdata[0];
- struct bfad_s *bfad = im_port->bfad;
+ struct bfad_s *bfad = im_port->bfad;
char serial_num[BFA_ADAPTER_SERIAL_NUM_LEN];
bfa_get_adapter_serial_num(&bfad->bfa, serial_num);
@@ -652,7 +657,7 @@ bfad_im_model_show(struct device *dev, struct device_attribute *attr,
struct Scsi_Host *shost = class_to_shost(dev);
struct bfad_im_port_s *im_port =
(struct bfad_im_port_s *) shost->hostdata[0];
- struct bfad_s *bfad = im_port->bfad;
+ struct bfad_s *bfad = im_port->bfad;
char model[BFA_ADAPTER_MODEL_NAME_LEN];
bfa_get_adapter_model(&bfad->bfa, model);
@@ -666,10 +671,54 @@ bfad_im_model_desc_show(struct device *dev, struct device_attribute *attr,
struct Scsi_Host *shost = class_to_shost(dev);
struct bfad_im_port_s *im_port =
(struct bfad_im_port_s *) shost->hostdata[0];
- struct bfad_s *bfad = im_port->bfad;
+ struct bfad_s *bfad = im_port->bfad;
+ char model[BFA_ADAPTER_MODEL_NAME_LEN];
char model_descr[BFA_ADAPTER_MODEL_DESCR_LEN];
- bfa_get_adapter_model(&bfad->bfa, model_descr);
+ bfa_get_adapter_model(&bfad->bfa, model);
+ if (!strcmp(model, "Brocade-425"))
+ snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+ "Brocade 4Gbps PCIe dual port FC HBA");
+ else if (!strcmp(model, "Brocade-825"))
+ snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+ "Brocade 8Gbps PCIe dual port FC HBA");
+ else if (!strcmp(model, "Brocade-42B"))
+ snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+ "HP 4Gbps PCIe dual port FC HBA");
+ else if (!strcmp(model, "Brocade-82B"))
+ snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+ "HP 8Gbps PCIe dual port FC HBA");
+ else if (!strcmp(model, "Brocade-1010"))
+ snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+ "Brocade 10Gbps single port CNA");
+ else if (!strcmp(model, "Brocade-1020"))
+ snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+ "Brocade 10Gbps dual port CNA");
+ else if (!strcmp(model, "Brocade-1007"))
+ snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+ "Brocade 10Gbps CNA");
+ else if (!strcmp(model, "Brocade-415"))
+ snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+ "Brocade 4Gbps PCIe single port FC HBA");
+ else if (!strcmp(model, "Brocade-815"))
+ snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+ "Brocade 8Gbps PCIe single port FC HBA");
+ else if (!strcmp(model, "Brocade-41B"))
+ snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+ "HP 4Gbps PCIe single port FC HBA");
+ else if (!strcmp(model, "Brocade-81B"))
+ snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+ "HP 8Gbps PCIe single port FC HBA");
+ else if (!strcmp(model, "Brocade-804"))
+ snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+ "HP Bladesystem C-class 8Gbps FC HBA");
+ else if (!strcmp(model, "Brocade-902"))
+ snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+ "Brocade 10Gbps CNA");
+ else
+ snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+ "Invalid Model");
+
return snprintf(buf, PAGE_SIZE, "%s\n", model_descr);
}
@@ -683,7 +732,7 @@ bfad_im_node_name_show(struct device *dev, struct device_attribute *attr,
struct bfad_port_s *port = im_port->port;
u64 nwwn;
- nwwn = bfa_fcs_port_get_nwwn(port->fcs_port);
+ nwwn = bfa_fcs_lport_get_nwwn(port->fcs_port);
return snprintf(buf, PAGE_SIZE, "0x%llx\n", bfa_os_htonll(nwwn));
}
@@ -694,14 +743,14 @@ bfad_im_symbolic_name_show(struct device *dev, struct device_attribute *attr,
struct Scsi_Host *shost = class_to_shost(dev);
struct bfad_im_port_s *im_port =
(struct bfad_im_port_s *) shost->hostdata[0];
- struct bfad_s *bfad = im_port->bfad;
- char model[BFA_ADAPTER_MODEL_NAME_LEN];
- char fw_ver[BFA_VERSION_LEN];
+ struct bfad_s *bfad = im_port->bfad;
+ struct bfa_lport_attr_s port_attr;
+ char symname[BFA_SYMNAME_MAXLEN];
- bfa_get_adapter_model(&bfad->bfa, model);
- bfa_get_adapter_fw_ver(&bfad->bfa, fw_ver);
- return snprintf(buf, PAGE_SIZE, "Brocade %s FV%s DV%s\n",
- model, fw_ver, BFAD_DRIVER_VERSION);
+ bfa_fcs_lport_get_attr(&bfad->bfa_fcs.fabric.bport, &port_attr);
+ strncpy(symname, port_attr.port_cfg.sym_name.symname,
+ BFA_SYMNAME_MAXLEN);
+ return snprintf(buf, PAGE_SIZE, "%s\n", symname);
}
static ssize_t
@@ -711,7 +760,7 @@ bfad_im_hw_version_show(struct device *dev, struct device_attribute *attr,
struct Scsi_Host *shost = class_to_shost(dev);
struct bfad_im_port_s *im_port =
(struct bfad_im_port_s *) shost->hostdata[0];
- struct bfad_s *bfad = im_port->bfad;
+ struct bfad_s *bfad = im_port->bfad;
char hw_ver[BFA_VERSION_LEN];
bfa_get_pci_chip_rev(&bfad->bfa, hw_ver);
@@ -732,7 +781,7 @@ bfad_im_optionrom_version_show(struct device *dev,
struct Scsi_Host *shost = class_to_shost(dev);
struct bfad_im_port_s *im_port =
(struct bfad_im_port_s *) shost->hostdata[0];
- struct bfad_s *bfad = im_port->bfad;
+ struct bfad_s *bfad = im_port->bfad;
char optrom_ver[BFA_VERSION_LEN];
bfa_get_adapter_optrom_ver(&bfad->bfa, optrom_ver);
@@ -746,7 +795,7 @@ bfad_im_fw_version_show(struct device *dev, struct device_attribute *attr,
struct Scsi_Host *shost = class_to_shost(dev);
struct bfad_im_port_s *im_port =
(struct bfad_im_port_s *) shost->hostdata[0];
- struct bfad_s *bfad = im_port->bfad;
+ struct bfad_s *bfad = im_port->bfad;
char fw_ver[BFA_VERSION_LEN];
bfa_get_adapter_fw_ver(&bfad->bfa, fw_ver);
@@ -760,10 +809,10 @@ bfad_im_num_of_ports_show(struct device *dev, struct device_attribute *attr,
struct Scsi_Host *shost = class_to_shost(dev);
struct bfad_im_port_s *im_port =
(struct bfad_im_port_s *) shost->hostdata[0];
- struct bfad_s *bfad = im_port->bfad;
+ struct bfad_s *bfad = im_port->bfad;
return snprintf(buf, PAGE_SIZE, "%d\n",
- bfa_get_nports(&bfad->bfa));
+ bfa_get_nports(&bfad->bfa));
}
static ssize_t
@@ -788,10 +837,10 @@ bfad_im_num_of_discovered_ports_show(struct device *dev,
rports = kzalloc(sizeof(wwn_t) * nrports , GFP_ATOMIC);
if (rports == NULL)
- return -ENOMEM;
+ return snprintf(buf, PAGE_SIZE, "Failed\n");
spin_lock_irqsave(&bfad->bfad_lock, flags);
- bfa_fcs_port_get_rports(port->fcs_port, rports, &nrports);
+ bfa_fcs_lport_get_rports(port->fcs_port, rports, &nrports);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
kfree(rports);
@@ -837,19 +886,19 @@ struct device_attribute *bfad_im_host_attrs[] = {
};
struct device_attribute *bfad_im_vport_attrs[] = {
- &dev_attr_serial_number,
- &dev_attr_model,
- &dev_attr_model_description,
- &dev_attr_node_name,
- &dev_attr_symbolic_name,
- &dev_attr_hardware_version,
- &dev_attr_driver_version,
- &dev_attr_option_rom_version,
- &dev_attr_firmware_version,
- &dev_attr_number_of_ports,
- &dev_attr_driver_name,
- &dev_attr_number_of_discovered_ports,
- NULL,
+ &dev_attr_serial_number,
+ &dev_attr_model,
+ &dev_attr_model_description,
+ &dev_attr_node_name,
+ &dev_attr_symbolic_name,
+ &dev_attr_hardware_version,
+ &dev_attr_driver_version,
+ &dev_attr_option_rom_version,
+ &dev_attr_firmware_version,
+ &dev_attr_number_of_ports,
+ &dev_attr_driver_name,
+ &dev_attr_number_of_discovered_ports,
+ NULL,
};
diff --git a/drivers/scsi/bfa/bfad_attr.h b/drivers/scsi/bfa/bfad_attr.h
deleted file mode 100644
index bf0102076508..000000000000
--- a/drivers/scsi/bfa/bfad_attr.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFAD_ATTR_H__
-#define __BFAD_ATTR_H__
-
-/**
- * FC_transport_template FC transport template
- */
-
-struct Scsi_Host*
-bfad_os_dev_to_shost(struct scsi_target *starget);
-
-/**
- * FC transport template entry, get SCSI target port ID.
- */
-void
-bfad_im_get_starget_port_id(struct scsi_target *starget);
-
-/**
- * FC transport template entry, get SCSI target nwwn.
- */
-void
-bfad_im_get_starget_node_name(struct scsi_target *starget);
-
-/**
- * FC transport template entry, get SCSI target pwwn.
- */
-void
-bfad_im_get_starget_port_name(struct scsi_target *starget);
-
-/**
- * FC transport template entry, get SCSI host port ID.
- */
-void
-bfad_im_get_host_port_id(struct Scsi_Host *shost);
-
-struct Scsi_Host*
-bfad_os_starget_to_shost(struct scsi_target *starget);
-
-
-#endif /* __BFAD_ATTR_H__ */
diff --git a/drivers/scsi/bfa/bfad_debugfs.c b/drivers/scsi/bfa/bfad_debugfs.c
index 4b82f12aad62..69ed1c4a903e 100644
--- a/drivers/scsi/bfa/bfad_debugfs.c
+++ b/drivers/scsi/bfa/bfad_debugfs.c
@@ -17,8 +17,8 @@
#include <linux/debugfs.h>
-#include <bfad_drv.h>
-#include <bfad_im.h>
+#include "bfad_drv.h"
+#include "bfad_im.h"
/*
* BFA debufs interface
@@ -28,7 +28,7 @@
* mount -t debugfs none /sys/kernel/debug
*
* BFA Hierarchy:
- * - bfa/host#
+ * - bfa/host#
* where the host number corresponds to the one under /sys/class/scsi_host/host#
*
* Debugging service available per host:
@@ -217,7 +217,7 @@ bfad_debugfs_read(struct file *file, char __user *buf,
#define BFA_REG_ADDRSZ(__bfa) \
((bfa_ioc_devid(&(__bfa)->ioc) == BFA_PCI_DEVICE_ID_CT) ? \
BFA_REG_CT_ADDRSZ : BFA_REG_CB_ADDRSZ)
-#define BFA_REG_ADDRMSK(__bfa) ((uint32_t)(BFA_REG_ADDRSZ(__bfa) - 1))
+#define BFA_REG_ADDRMSK(__bfa) ((u32)(BFA_REG_ADDRSZ(__bfa) - 1))
static bfa_status_t
bfad_reg_offset_check(struct bfa_s *bfa, u32 offset, u32 len)
@@ -359,7 +359,7 @@ bfad_debugfs_write_regwr(struct file *file, const char __user *buf,
return -EINVAL;
}
- reg_addr = (uint32_t *) ((uint8_t *) bfa_ioc_bar0(ioc) + addr);
+ reg_addr = (u32 *) ((u8 *) bfa_ioc_bar0(ioc) + addr);
spin_lock_irqsave(&bfad->bfad_lock, flags);
bfa_reg_write(reg_addr, val);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
diff --git a/drivers/scsi/bfa/bfad_drv.h b/drivers/scsi/bfa/bfad_drv.h
index 465b8b86ec9c..98420bbb4f3f 100644
--- a/drivers/scsi/bfa/bfad_drv.h
+++ b/drivers/scsi/bfa/bfad_drv.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
* All rights reserved
* www.brocade.com
*
@@ -28,30 +28,27 @@
#include "bfa_os_inc.h"
-#include <bfa.h>
-#include <bfa_svc.h>
-#include <fcs/bfa_fcs.h>
-#include <defs/bfa_defs_pci.h>
-#include <defs/bfa_defs_port.h>
-#include <defs/bfa_defs_rport.h>
-#include <fcs/bfa_fcs_rport.h>
-#include <defs/bfa_defs_vport.h>
-#include <fcs/bfa_fcs_vport.h>
-
-#include <cs/bfa_plog.h>
-#include "aen/bfa_aen.h"
-#include <log/bfa_log_linux.h>
-
-#define BFAD_DRIVER_NAME "bfa"
+#include "bfa_modules.h"
+#include "bfa_fcs.h"
+#include "bfa_defs_fcs.h"
+
+#include "bfa_plog.h"
+#include "bfa_cs.h"
+
+#define BFAD_DRIVER_NAME "bfa"
#ifdef BFA_DRIVER_VERSION
#define BFAD_DRIVER_VERSION BFA_DRIVER_VERSION
#else
-#define BFAD_DRIVER_VERSION "2.2.2.1"
+#define BFAD_DRIVER_VERSION "2.3.2.0"
#endif
-
+#define BFAD_PROTO_NAME FCPI_NAME
#define BFAD_IRQ_FLAGS IRQF_SHARED
+#ifndef FC_PORTSPEED_8GBIT
+#define FC_PORTSPEED_8GBIT 0x10
+#endif
+
/*
* BFAD flags
*/
@@ -62,9 +59,9 @@
#define BFAD_HAL_START_DONE 0x00000010
#define BFAD_PORT_ONLINE 0x00000020
#define BFAD_RPORT_ONLINE 0x00000040
-#define BFAD_FCS_INIT_DONE 0x00000080
-#define BFAD_HAL_INIT_FAIL 0x00000100
-#define BFAD_FC4_PROBE_DONE 0x00000200
+#define BFAD_FCS_INIT_DONE 0x00000080
+#define BFAD_HAL_INIT_FAIL 0x00000100
+#define BFAD_FC4_PROBE_DONE 0x00000200
#define BFAD_PORT_DELETE 0x00000001
/*
@@ -77,8 +74,8 @@
/*
* BFAD configuration parameter default values
*/
-#define BFAD_LUN_QUEUE_DEPTH 32
-#define BFAD_IO_MAX_SGE SG_ALL
+#define BFAD_LUN_QUEUE_DEPTH 32
+#define BFAD_IO_MAX_SGE SG_ALL
#define bfad_isr_t irq_handler_t
@@ -87,6 +84,16 @@
struct bfad_msix_s {
struct bfad_s *bfad;
struct msix_entry msix;
+ char name[32];
+};
+
+/*
+ * Only append to the enums defined here to avoid any versioning
+ * needed between trace utility and driver version
+ */
+enum {
+ BFA_TRC_LDRV_BFAD = 1,
+ BFA_TRC_LDRV_IM = 2,
};
enum bfad_port_pvb_type {
@@ -101,17 +108,13 @@ enum bfad_port_pvb_type {
*/
struct bfad_port_s {
struct list_head list_entry;
- struct bfad_s *bfad;
- struct bfa_fcs_port_s *fcs_port;
- u32 roles;
- s32 flags;
- u32 supported_fc4s;
- u8 ipfc_flags;
+ struct bfad_s *bfad;
+ struct bfa_fcs_lport_s *fcs_port;
+ u32 roles;
+ s32 flags;
+ u32 supported_fc4s;
enum bfad_port_pvb_type pvb_type;
struct bfad_im_port_s *im_port; /* IM specific data */
- struct bfad_tm_port_s *tm_port; /* TM specific data */
- struct bfad_ipfc_port_s *ipfc_port; /* IPFC specific data */
-
/* port debugfs specific data */
struct dentry *port_debugfs_root;
};
@@ -124,7 +127,6 @@ struct bfad_vport_s {
struct bfa_fcs_vport_s fcs_vport;
struct completion *comp_del;
struct list_head list_entry;
- struct bfa_port_cfg_s port_cfg;
};
/*
@@ -137,20 +139,35 @@ struct bfad_vf_s {
};
struct bfad_cfg_param_s {
- u32 rport_del_timeout;
- u32 ioc_queue_depth;
- u32 lun_queue_depth;
- u32 io_max_sge;
- u32 binding_method;
+ u32 rport_del_timeout;
+ u32 ioc_queue_depth;
+ u32 lun_queue_depth;
+ u32 io_max_sge;
+ u32 binding_method;
+};
+
+union bfad_tmp_buf {
+ /* From struct bfa_adapter_attr_s */
+ char manufacturer[BFA_ADAPTER_MFG_NAME_LEN];
+ char serial_num[BFA_ADAPTER_SERIAL_NUM_LEN];
+ char model[BFA_ADAPTER_MODEL_NAME_LEN];
+ char fw_ver[BFA_VERSION_LEN];
+ char optrom_ver[BFA_VERSION_LEN];
+
+ /* From struct bfa_ioc_pci_attr_s */
+ u8 chip_rev[BFA_IOC_CHIP_REV_LEN]; /* chip revision */
+
+ wwn_t wwn[BFA_FCS_MAX_LPORTS];
};
/*
* BFAD (PCI function) data structure
*/
struct bfad_s {
+ bfa_sm_t sm; /* state machine */
struct list_head list_entry;
- struct bfa_s bfa;
- struct bfa_fcs_s bfa_fcs;
+ struct bfa_s bfa;
+ struct bfa_fcs_s bfa_fcs;
struct pci_dev *pcidev;
const char *pci_name;
struct bfa_pcidev_s hal_pcidev;
@@ -163,41 +180,41 @@ struct bfad_s {
struct bfad_port_s pport; /* physical port of the BFAD */
struct bfa_meminfo_s meminfo;
struct bfa_iocfc_cfg_s ioc_cfg;
- u32 inst_no; /* BFAD instance number */
- u32 bfad_flags;
+ u32 inst_no; /* BFAD instance number */
+ u32 bfad_flags;
spinlock_t bfad_lock;
struct task_struct *bfad_tsk;
struct bfad_cfg_param_s cfg_data;
struct bfad_msix_s msix_tab[MAX_MSIX_ENTRY];
- int nvec;
- char adapter_name[BFA_ADAPTER_SYM_NAME_LEN];
- char port_name[BFA_ADAPTER_SYM_NAME_LEN];
+ int nvec;
+ char adapter_name[BFA_ADAPTER_SYM_NAME_LEN];
+ char port_name[BFA_ADAPTER_SYM_NAME_LEN];
struct timer_list hal_tmo;
unsigned long hs_start;
struct bfad_im_s *im; /* IM specific data */
- struct bfad_tm_s *tm; /* TM specific data */
- struct bfad_ipfc_s *ipfc; /* IPFC specific data */
- struct bfa_log_mod_s log_data;
struct bfa_trc_mod_s *trcmod;
- struct bfa_log_mod_s *logmod;
- struct bfa_aen_s *aen;
- struct bfa_aen_s aen_buf;
- void *file_map[BFA_AEN_MAX_APP];
struct bfa_plog_s plog_buf;
- int ref_count;
- bfa_boolean_t ipfc_enabled;
+ int ref_count;
+ union bfad_tmp_buf tmp_buf;
struct fc_host_statistics link_stats;
- struct list_head pbc_pcfg_list;
- atomic_t wq_reqcnt;
+ struct list_head pbc_vport_list;
/* debugfs specific data */
char *regdata;
u32 reglen;
struct dentry *bfad_dentry_files[5];
};
-struct bfad_pcfg_s {
- struct list_head list_entry;
- struct bfa_port_cfg_s port_cfg;
+/* BFAD state machine events */
+enum bfad_sm_event {
+ BFAD_E_CREATE = 1,
+ BFAD_E_KTHREAD_CREATE_FAILED = 2,
+ BFAD_E_INIT = 3,
+ BFAD_E_INIT_SUCCESS = 4,
+ BFAD_E_INIT_FAILED = 5,
+ BFAD_E_INTR_INIT_FAILED = 6,
+ BFAD_E_FCS_EXIT_COMP = 7,
+ BFAD_E_EXIT_COMP = 8,
+ BFAD_E_STOP = 9
};
/*
@@ -208,30 +225,30 @@ struct bfad_rport_s {
};
struct bfad_buf_info {
- void *virt;
+ void *virt;
dma_addr_t phys;
- u32 size;
+ u32 size;
};
struct bfad_fcxp {
struct bfad_port_s *port;
struct bfa_rport_s *bfa_rport;
bfa_status_t req_status;
- u16 tag;
- u16 rsp_len;
- u16 rsp_maxlen;
- u8 use_ireqbuf;
- u8 use_irspbuf;
- u32 num_req_sgles;
- u32 num_rsp_sgles;
- struct fchs_s fchs;
- void *reqbuf_info;
- void *rspbuf_info;
+ u16 tag;
+ u16 rsp_len;
+ u16 rsp_maxlen;
+ u8 use_ireqbuf;
+ u8 use_irspbuf;
+ u32 num_req_sgles;
+ u32 num_rsp_sgles;
+ struct fchs_s fchs;
+ void *reqbuf_info;
+ void *rspbuf_info;
struct bfa_sge_s *req_sge;
struct bfa_sge_s *rsp_sge;
fcxp_send_cb_t send_cbfn;
- void *send_cbarg;
- void *bfa_fcxp;
+ void *send_cbarg;
+ void *bfa_fcxp;
struct completion comp;
};
@@ -244,34 +261,48 @@ struct bfad_hal_comp {
* Macro to obtain the immediate lower power
* of two for the integer.
*/
-#define nextLowerInt(x) \
-do { \
- int j; \
- (*x)--; \
- for (j = 1; j < (sizeof(int) * 8); j <<= 1) \
- (*x) = (*x) | (*x) >> j; \
- (*x)++; \
- (*x) = (*x) >> 1; \
+#define nextLowerInt(x) \
+do { \
+ int i; \
+ (*x)--; \
+ for (i = 1; i < (sizeof(int)*8); i <<= 1) \
+ (*x) = (*x) | (*x) >> i; \
+ (*x)++; \
+ (*x) = (*x) >> 1; \
} while (0)
-bfa_status_t bfad_vport_create(struct bfad_s *bfad, u16 vf_id,
- struct bfa_port_cfg_s *port_cfg, struct device *dev);
-bfa_status_t bfad_vf_create(struct bfad_s *bfad, u16 vf_id,
- struct bfa_port_cfg_s *port_cfg);
-bfa_status_t bfad_cfg_pport(struct bfad_s *bfad, enum bfa_port_role role);
-bfa_status_t bfad_drv_init(struct bfad_s *bfad);
-bfa_status_t bfad_start_ops(struct bfad_s *bfad);
-void bfad_drv_start(struct bfad_s *bfad);
-void bfad_uncfg_pport(struct bfad_s *bfad);
-void bfad_drv_stop(struct bfad_s *bfad);
-void bfad_remove_intr(struct bfad_s *bfad);
-void bfad_hal_mem_release(struct bfad_s *bfad);
-void bfad_hcb_comp(void *arg, bfa_status_t status);
-
-int bfad_setup_intr(struct bfad_s *bfad);
-void bfad_remove_intr(struct bfad_s *bfad);
+#define list_remove_head(list, entry, type, member) \
+do { \
+ entry = NULL; \
+ if (!list_empty(list)) { \
+ entry = list_entry((list)->next, type, member); \
+ list_del_init(&entry->member); \
+ } \
+} while (0)
+#define list_get_first(list, type, member) \
+((list_empty(list)) ? NULL : \
+ list_entry((list)->next, type, member))
+
+bfa_status_t bfad_vport_create(struct bfad_s *bfad, u16 vf_id,
+ struct bfa_lport_cfg_s *port_cfg,
+ struct device *dev);
+bfa_status_t bfad_vf_create(struct bfad_s *bfad, u16 vf_id,
+ struct bfa_lport_cfg_s *port_cfg);
+bfa_status_t bfad_cfg_pport(struct bfad_s *bfad, enum bfa_lport_role role);
+bfa_status_t bfad_drv_init(struct bfad_s *bfad);
+bfa_status_t bfad_start_ops(struct bfad_s *bfad);
+void bfad_drv_start(struct bfad_s *bfad);
+void bfad_uncfg_pport(struct bfad_s *bfad);
+void bfad_stop(struct bfad_s *bfad);
+void bfad_fcs_stop(struct bfad_s *bfad);
+void bfad_remove_intr(struct bfad_s *bfad);
+void bfad_hal_mem_release(struct bfad_s *bfad);
+void bfad_hcb_comp(void *arg, bfa_status_t status);
+
+int bfad_setup_intr(struct bfad_s *bfad);
+void bfad_remove_intr(struct bfad_s *bfad);
void bfad_update_hal_cfg(struct bfa_iocfc_cfg_s *bfa_cfg);
bfa_status_t bfad_hal_mem_alloc(struct bfad_s *bfad);
void bfad_bfa_tmo(unsigned long data);
@@ -280,9 +311,6 @@ int bfad_pci_init(struct pci_dev *pdev, struct bfad_s *bfad);
void bfad_pci_uninit(struct pci_dev *pdev, struct bfad_s *bfad);
void bfad_fcs_port_cfg(struct bfad_s *bfad);
void bfad_drv_uninit(struct bfad_s *bfad);
-void bfad_drv_log_level_set(struct bfad_s *bfad);
-bfa_status_t bfad_fc4_module_init(void);
-void bfad_fc4_module_exit(void);
int bfad_worker(void *ptr);
void bfad_debugfs_init(struct bfad_port_s *port);
void bfad_debugfs_exit(struct bfad_port_s *port);
@@ -294,10 +322,30 @@ int bfad_os_get_linkup_delay(struct bfad_s *bfad);
int bfad_install_msix_handler(struct bfad_s *bfad);
extern struct idr bfad_im_port_index;
+extern struct pci_device_id bfad_id_table[];
extern struct list_head bfad_list;
-extern int bfa_lun_queue_depth;
-extern int bfad_supported_fc4s;
-extern int bfa_linkup_delay;
+extern char *os_name;
+extern char *os_patch;
+extern char *host_name;
+extern int num_rports;
+extern int num_ios;
+extern int num_tms;
+extern int num_fcxps;
+extern int num_ufbufs;
+extern int reqq_size;
+extern int rspq_size;
+extern int num_sgpgs;
+extern int rport_del_timeout;
+extern int bfa_lun_queue_depth;
+extern int bfa_io_max_sge;
+extern int log_level;
+extern int ioc_auto_recover;
+extern int bfa_linkup_delay;
+extern int msix_disable_cb;
+extern int msix_disable_ct;
+extern int fdmi_enable;
+extern int supported_fc4s;
+extern int pcie_max_read_reqsz;
extern int bfa_debugfs_enable;
extern struct mutex bfad_mutex;
diff --git a/drivers/scsi/bfa/bfad_fwimg.c b/drivers/scsi/bfa/bfad_fwimg.c
deleted file mode 100644
index 1baca1a12085..000000000000
--- a/drivers/scsi/bfa/bfad_fwimg.c
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/**
- * bfad_fwimg.c Linux driver PCI interface module.
- */
-#include <bfa_os_inc.h>
-#include <bfad_drv.h>
-#include <bfad_im_compat.h>
-#include <defs/bfa_defs_version.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <asm/uaccess.h>
-#include <asm/fcntl.h>
-#include <linux/pci.h>
-#include <linux/firmware.h>
-#include <bfa_fwimg_priv.h>
-#include <bfa.h>
-
-u32 bfi_image_ct_fc_size;
-u32 bfi_image_ct_cna_size;
-u32 bfi_image_cb_fc_size;
-u32 *bfi_image_ct_fc;
-u32 *bfi_image_ct_cna;
-u32 *bfi_image_cb_fc;
-
-
-#define BFAD_FW_FILE_CT_FC "ctfw_fc.bin"
-#define BFAD_FW_FILE_CT_CNA "ctfw_cna.bin"
-#define BFAD_FW_FILE_CB_FC "cbfw_fc.bin"
-MODULE_FIRMWARE(BFAD_FW_FILE_CT_FC);
-MODULE_FIRMWARE(BFAD_FW_FILE_CT_CNA);
-MODULE_FIRMWARE(BFAD_FW_FILE_CB_FC);
-
-u32 *
-bfad_read_firmware(struct pci_dev *pdev, u32 **bfi_image,
- u32 *bfi_image_size, char *fw_name)
-{
- const struct firmware *fw;
-
- if (request_firmware(&fw, fw_name, &pdev->dev)) {
- printk(KERN_ALERT "Can't locate firmware %s\n", fw_name);
- goto error;
- }
-
- *bfi_image = vmalloc(fw->size);
- if (NULL == *bfi_image) {
- printk(KERN_ALERT "Fail to allocate buffer for fw image "
- "size=%x!\n", (u32) fw->size);
- goto error;
- }
-
- memcpy(*bfi_image, fw->data, fw->size);
- *bfi_image_size = fw->size/sizeof(u32);
-
- return *bfi_image;
-
-error:
- return NULL;
-}
-
-u32 *
-bfad_get_firmware_buf(struct pci_dev *pdev)
-{
- if (pdev->device == BFA_PCI_DEVICE_ID_CT_FC) {
- if (bfi_image_ct_fc_size == 0)
- bfad_read_firmware(pdev, &bfi_image_ct_fc,
- &bfi_image_ct_fc_size, BFAD_FW_FILE_CT_FC);
- return bfi_image_ct_fc;
- } else if (pdev->device == BFA_PCI_DEVICE_ID_CT) {
- if (bfi_image_ct_cna_size == 0)
- bfad_read_firmware(pdev, &bfi_image_ct_cna,
- &bfi_image_ct_cna_size, BFAD_FW_FILE_CT_CNA);
- return bfi_image_ct_cna;
- } else {
- if (bfi_image_cb_fc_size == 0)
- bfad_read_firmware(pdev, &bfi_image_cb_fc,
- &bfi_image_cb_fc_size, BFAD_FW_FILE_CB_FC);
- return bfi_image_cb_fc;
- }
-}
-
-u32 *
-bfi_image_ct_fc_get_chunk(u32 off)
-{ return (u32 *)(bfi_image_ct_fc + off); }
-
-u32 *
-bfi_image_ct_cna_get_chunk(u32 off)
-{ return (u32 *)(bfi_image_ct_cna + off); }
-
-u32 *
-bfi_image_cb_fc_get_chunk(u32 off)
-{ return (u32 *)(bfi_image_cb_fc + off); }
-
-uint32_t *
-bfi_image_get_chunk(int type, uint32_t off)
-{
- switch (type) {
- case BFI_IMAGE_CT_FC: return bfi_image_ct_fc_get_chunk(off); break;
- case BFI_IMAGE_CT_CNA: return bfi_image_ct_cna_get_chunk(off); break;
- case BFI_IMAGE_CB_FC: return bfi_image_cb_fc_get_chunk(off); break;
- default: return 0; break;
- }
-}
-
-uint32_t
-bfi_image_get_size(int type)
-{
- switch (type) {
- case BFI_IMAGE_CT_FC: return bfi_image_ct_fc_size; break;
- case BFI_IMAGE_CT_CNA: return bfi_image_ct_cna_size; break;
- case BFI_IMAGE_CB_FC: return bfi_image_cb_fc_size; break;
- default: return 0; break;
- }
-}
diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c
index 6ef87f6fcdbb..d950ee44016e 100644
--- a/drivers/scsi/bfa/bfad_im.c
+++ b/drivers/scsi/bfa/bfad_im.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
* All rights reserved
* www.brocade.com
*
@@ -19,12 +19,10 @@
* bfad_im.c Linux driver IM module.
*/
-#include <linux/slab.h>
#include "bfad_drv.h"
#include "bfad_im.h"
-#include "bfad_trcmod.h"
-#include "bfa_cb_ioim_macros.h"
-#include <fcb/bfa_fcb_fcpim.h>
+#include "bfa_cb_ioim.h"
+#include "bfa_fcs.h"
BFA_TRC_FILE(LDRV, IM);
@@ -33,8 +31,10 @@ struct scsi_transport_template *bfad_im_scsi_transport_template;
struct scsi_transport_template *bfad_im_scsi_vport_transport_template;
static void bfad_im_itnim_work_handler(struct work_struct *work);
static int bfad_im_queuecommand(struct scsi_cmnd *cmnd,
- void (*done)(struct scsi_cmnd *));
+ void (*done)(struct scsi_cmnd *));
static int bfad_im_slave_alloc(struct scsi_device *sdev);
+static void bfad_im_fc_rport_add(struct bfad_im_port_s *im_port,
+ struct bfad_itnim_s *itnim);
void
bfa_cb_ioim_done(void *drv, struct bfad_ioim_s *dio,
@@ -58,6 +58,7 @@ bfa_cb_ioim_done(void *drv, struct bfad_ioim_s *dio,
sns_len = SCSI_SENSE_BUFFERSIZE;
memcpy(cmnd->sense_buffer, sns_info, sns_len);
}
+
if (residue > 0) {
bfa_trc(bfad, residue);
scsi_set_resid(cmnd, residue);
@@ -76,7 +77,8 @@ bfa_cb_ioim_done(void *drv, struct bfad_ioim_s *dio,
case BFI_IOIM_STS_TIMEDOUT:
case BFI_IOIM_STS_PATHTOV:
default:
- cmnd->result = ScsiResult(DID_ERROR, 0);
+ host_status = DID_ERROR;
+ cmnd->result = ScsiResult(host_status, 0);
}
/* Unmap DMA, if host is NULL, it means a scsi passthru cmd */
@@ -162,11 +164,6 @@ bfa_cb_tskim_done(void *bfad, struct bfad_tskim_s *dtsk,
wake_up(wq);
}
-void
-bfa_cb_ioim_resfree(void *drv)
-{
-}
-
/**
* Scsi_Host_template SCSI host template
*/
@@ -179,15 +176,23 @@ bfad_im_info(struct Scsi_Host *shost)
static char bfa_buf[256];
struct bfad_im_port_s *im_port =
(struct bfad_im_port_s *) shost->hostdata[0];
- struct bfad_s *bfad = im_port->bfad;
+ struct bfad_s *bfad = im_port->bfad;
+ struct bfa_s *bfa = &bfad->bfa;
+ struct bfa_ioc_s *ioc = &bfa->ioc;
char model[BFA_ADAPTER_MODEL_NAME_LEN];
- bfa_get_adapter_model(&bfad->bfa, model);
+ bfa_get_adapter_model(bfa, model);
memset(bfa_buf, 0, sizeof(bfa_buf));
- snprintf(bfa_buf, sizeof(bfa_buf),
- "Brocade FC/FCOE Adapter, " "model: %s hwpath: %s driver: %s",
+ if (ioc->ctdev)
+ snprintf(bfa_buf, sizeof(bfa_buf),
+ "Brocade FCOE Adapter, " "model: %s hwpath: %s driver: %s",
+ model, bfad->pci_name, BFAD_DRIVER_VERSION);
+ else
+ snprintf(bfa_buf, sizeof(bfa_buf),
+ "Brocade FC Adapter, " "model: %s hwpath: %s driver: %s",
model, bfad->pci_name, BFAD_DRIVER_VERSION);
+
return bfa_buf;
}
@@ -221,9 +226,9 @@ bfad_im_abort_handler(struct scsi_cmnd *cmnd)
}
bfa_trc(bfad, hal_io->iotag);
- bfa_log(bfad->logmod, BFA_LOG_LINUX_SCSI_ABORT,
+ BFA_LOG(KERN_INFO, bfad, log_level, "scsi%d: abort cmnd %p iotag %x\n",
im_port->shost->host_no, cmnd, hal_io->iotag);
- bfa_ioim_abort(hal_io);
+ (void) bfa_ioim_abort(hal_io);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
/* Need to wait until the command get aborted */
@@ -237,7 +242,8 @@ bfad_im_abort_handler(struct scsi_cmnd *cmnd)
cmnd->scsi_done(cmnd);
bfa_trc(bfad, hal_io->iotag);
- bfa_log(bfad->logmod, BFA_LOG_LINUX_SCSI_ABORT_COMP,
+ BFA_LOG(KERN_INFO, bfad, log_level,
+ "scsi%d: complete abort 0x%p iotag 0x%x\n",
im_port->shost->host_no, cmnd, hal_io->iotag);
return SUCCESS;
out:
@@ -255,8 +261,8 @@ bfad_im_target_reset_send(struct bfad_s *bfad, struct scsi_cmnd *cmnd,
tskim = bfa_tskim_alloc(&bfad->bfa, (struct bfad_tskim_s *) cmnd);
if (!tskim) {
- BFA_DEV_PRINTF(bfad, BFA_ERR,
- "target reset, fail to allocate tskim\n");
+ BFA_LOG(KERN_ERR, bfad, log_level,
+ "target reset, fail to allocate tskim\n");
rc = BFA_STATUS_FAILED;
goto out;
}
@@ -306,7 +312,7 @@ bfad_im_reset_lun_handler(struct scsi_cmnd *cmnd)
tskim = bfa_tskim_alloc(&bfad->bfa, (struct bfad_tskim_s *) cmnd);
if (!tskim) {
- BFA_DEV_PRINTF(bfad, BFA_ERR,
+ BFA_LOG(KERN_ERR, bfad, log_level,
"LUN reset, fail to allocate tskim");
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
rc = FAILED;
@@ -331,8 +337,8 @@ bfad_im_reset_lun_handler(struct scsi_cmnd *cmnd)
task_status = cmnd->SCp.Status >> 1;
if (task_status != BFI_TSKIM_STS_OK) {
- BFA_DEV_PRINTF(bfad, BFA_ERR, "LUN reset failure, status: %d\n",
- task_status);
+ BFA_LOG(KERN_ERR, bfad, log_level,
+ "LUN reset failure, status: %d\n", task_status);
rc = FAILED;
}
@@ -375,7 +381,7 @@ bfad_im_reset_bus_handler(struct scsi_cmnd *cmnd)
task_status = cmnd->SCp.Status >> 1;
if (task_status != BFI_TSKIM_STS_OK) {
- BFA_DEV_PRINTF(bfad, BFA_ERR,
+ BFA_LOG(KERN_ERR, bfad, log_level,
"target reset failure,"
" status: %d\n", task_status);
err_cnt++;
@@ -438,6 +444,7 @@ bfa_fcb_itnim_free(struct bfad_s *bfad, struct bfad_itnim_s *itnim_drv)
wwn_t wwpn;
u32 fcid;
char wwpn_str[32], fcid_str[16];
+ struct bfad_im_s *im = itnim_drv->im;
/* online to free state transtion should not happen */
bfa_assert(itnim_drv->state != ITNIM_STATE_ONLINE);
@@ -454,10 +461,14 @@ bfa_fcb_itnim_free(struct bfad_s *bfad, struct bfad_itnim_s *itnim_drv)
fcid = bfa_fcs_itnim_get_fcid(&itnim_drv->fcs_itnim);
wwn2str(wwpn_str, wwpn);
fcid2str(fcid_str, fcid);
- bfa_log(bfad->logmod, BFA_LOG_LINUX_ITNIM_FREE,
+ BFA_LOG(KERN_INFO, bfad, log_level,
+ "ITNIM FREE scsi%d: FCID: %s WWPN: %s\n",
port->im_port->shost->host_no,
fcid_str, wwpn_str);
- bfad_os_itnim_process(itnim_drv);
+
+ /* ITNIM processing */
+ if (itnim_drv->queue_work)
+ queue_work(im->drv_workq, &itnim_drv->itnim_work);
}
/**
@@ -468,13 +479,17 @@ void
bfa_fcb_itnim_online(struct bfad_itnim_s *itnim_drv)
{
struct bfad_port_s *port;
+ struct bfad_im_s *im = itnim_drv->im;
itnim_drv->bfa_itnim = bfa_fcs_itnim_get_halitn(&itnim_drv->fcs_itnim);
port = bfa_fcs_itnim_get_drvport(&itnim_drv->fcs_itnim);
itnim_drv->state = ITNIM_STATE_ONLINE;
itnim_drv->queue_work = 1;
itnim_drv->im_port = port->im_port;
- bfad_os_itnim_process(itnim_drv);
+
+ /* ITNIM processing */
+ if (itnim_drv->queue_work)
+ queue_work(im->drv_workq, &itnim_drv->itnim_work);
}
/**
@@ -486,6 +501,7 @@ bfa_fcb_itnim_offline(struct bfad_itnim_s *itnim_drv)
{
struct bfad_port_s *port;
struct bfad_s *bfad;
+ struct bfad_im_s *im = itnim_drv->im;
port = bfa_fcs_itnim_get_drvport(&itnim_drv->fcs_itnim);
bfad = port->bfad;
@@ -497,16 +513,10 @@ bfa_fcb_itnim_offline(struct bfad_itnim_s *itnim_drv)
itnim_drv->im_port = port->im_port;
itnim_drv->state = ITNIM_STATE_OFFLINE_PENDING;
itnim_drv->queue_work = 1;
- bfad_os_itnim_process(itnim_drv);
-}
-/**
- * BFA FCS itnim timeout callback.
- * Context: Interrupt. bfad_lock is held
- */
-void bfa_fcb_itnim_tov(struct bfad_itnim_s *itnim)
-{
- itnim->state = ITNIM_STATE_TIMEOUT;
+ /* ITNIM processing */
+ if (itnim_drv->queue_work)
+ queue_work(im->drv_workq, &itnim_drv->itnim_work);
}
/**
@@ -514,7 +524,7 @@ void bfa_fcb_itnim_tov(struct bfad_itnim_s *itnim)
*/
int
bfad_im_scsi_host_alloc(struct bfad_s *bfad, struct bfad_im_port_s *im_port,
- struct device *dev)
+ struct device *dev)
{
int error = 1;
@@ -580,7 +590,7 @@ void
bfad_im_scsi_host_free(struct bfad_s *bfad, struct bfad_im_port_s *im_port)
{
bfa_trc(bfad, bfad->inst_no);
- bfa_log(bfad->logmod, BFA_LOG_LINUX_SCSI_HOST_FREE,
+ BFA_LOG(KERN_INFO, bfad, log_level, "Free scsi%d\n",
im_port->shost->host_no);
fc_remove_host(im_port->shost);
@@ -598,14 +608,11 @@ bfad_im_port_delete_handler(struct work_struct *work)
{
struct bfad_im_port_s *im_port =
container_of(work, struct bfad_im_port_s, port_delete_work);
- struct bfad_s *bfad = im_port->bfad;
if (im_port->port->pvb_type != BFAD_PORT_PHYS_BASE) {
im_port->flags |= BFAD_PORT_DELETE;
fc_vport_terminate(im_port->fc_vport);
- atomic_dec(&bfad->wq_reqcnt);
}
-
}
bfa_status_t
@@ -636,11 +643,8 @@ bfad_im_port_delete(struct bfad_s *bfad, struct bfad_port_s *port)
{
struct bfad_im_port_s *im_port = port->im_port;
- if (im_port->port->pvb_type != BFAD_PORT_PHYS_BASE) {
- atomic_inc(&bfad->wq_reqcnt);
- queue_work(bfad->im->drv_workq,
+ queue_work(bfad->im->drv_workq,
&im_port->port_delete_work);
- }
}
void
@@ -663,16 +667,6 @@ bfad_im_port_clean(struct bfad_im_port_s *im_port)
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
}
-void
-bfad_im_port_online(struct bfad_s *bfad, struct bfad_port_s *port)
-{
-}
-
-void
-bfad_im_port_offline(struct bfad_s *bfad, struct bfad_port_s *port)
-{
-}
-
bfa_status_t
bfad_im_probe(struct bfad_s *bfad)
{
@@ -701,27 +695,12 @@ void
bfad_im_probe_undo(struct bfad_s *bfad)
{
if (bfad->im) {
- while (atomic_read(&bfad->wq_reqcnt)) {
- printk(KERN_INFO "bfa %s: waiting workq processing,"
- " wq_reqcnt:%x\n", bfad->pci_name,
- atomic_read(&bfad->wq_reqcnt));
- schedule_timeout_uninterruptible(HZ);
- }
bfad_os_destroy_workq(bfad->im);
kfree(bfad->im);
bfad->im = NULL;
}
}
-/**
- * Call back function to handle IO redirection state change
- */
-void
-bfa_cb_ioredirect_state_change(void *hcb_bfad, bfa_boolean_t ioredirect)
-{
- /* Do nothing */
-}
-
struct Scsi_Host *
bfad_os_scsi_host_alloc(struct bfad_im_port_s *im_port, struct bfad_s *bfad)
{
@@ -751,6 +730,7 @@ void
bfad_os_destroy_workq(struct bfad_im_s *im)
{
if (im && im->drv_workq) {
+ flush_workqueue(im->drv_workq);
destroy_workqueue(im->drv_workq);
im->drv_workq = NULL;
}
@@ -762,7 +742,7 @@ bfad_os_thread_workq(struct bfad_s *bfad)
struct bfad_im_s *im = bfad->im;
bfa_trc(bfad, 0);
- snprintf(im->drv_workq_name, BFAD_KOBJ_NAME_LEN, "bfad_wq_%d",
+ snprintf(im->drv_workq_name, KOBJ_NAME_LEN, "bfad_wq_%d",
bfad->inst_no);
im->drv_workq = create_singlethread_workqueue(im->drv_workq_name);
if (!im->drv_workq)
@@ -832,12 +812,6 @@ struct scsi_host_template bfad_im_vport_template = {
.max_sectors = 0xFFFF,
};
-void
-bfad_im_probe_post(struct bfad_im_s *im)
-{
- flush_workqueue(im->drv_workq);
-}
-
bfa_status_t
bfad_im_module_init(void)
{
@@ -861,20 +835,12 @@ bfad_im_module_exit(void)
{
if (bfad_im_scsi_transport_template)
fc_release_transport(bfad_im_scsi_transport_template);
+
if (bfad_im_scsi_vport_transport_template)
fc_release_transport(bfad_im_scsi_vport_transport_template);
}
void
-bfad_os_itnim_process(struct bfad_itnim_s *itnim_drv)
-{
- struct bfad_im_s *im = itnim_drv->im;
-
- if (itnim_drv->queue_work)
- queue_work(im->drv_workq, &itnim_drv->itnim_work);
-}
-
-void
bfad_os_ramp_up_qdepth(struct bfad_itnim_s *itnim, struct scsi_device *sdev)
{
struct scsi_device *tmp_sdev;
@@ -916,9 +882,6 @@ bfad_os_handle_qfull(struct bfad_itnim_s *itnim, struct scsi_device *sdev)
}
}
-
-
-
struct bfad_itnim_s *
bfad_os_get_itnim(struct bfad_im_port_s *im_port, int id)
{
@@ -949,44 +912,64 @@ bfad_im_slave_alloc(struct scsi_device *sdev)
return 0;
}
+static u32
+bfad_im_supported_speeds(struct bfa_s *bfa)
+{
+ struct bfa_ioc_attr_s ioc_attr;
+ u32 supported_speed = 0;
+
+ bfa_get_attr(bfa, &ioc_attr);
+ if (ioc_attr.adapter_attr.max_speed == BFA_PORT_SPEED_8GBPS) {
+ if (ioc_attr.adapter_attr.is_mezz) {
+ supported_speed |= FC_PORTSPEED_8GBIT |
+ FC_PORTSPEED_4GBIT |
+ FC_PORTSPEED_2GBIT | FC_PORTSPEED_1GBIT;
+ } else {
+ supported_speed |= FC_PORTSPEED_8GBIT |
+ FC_PORTSPEED_4GBIT |
+ FC_PORTSPEED_2GBIT;
+ }
+ } else if (ioc_attr.adapter_attr.max_speed == BFA_PORT_SPEED_4GBPS) {
+ supported_speed |= FC_PORTSPEED_4GBIT | FC_PORTSPEED_2GBIT |
+ FC_PORTSPEED_1GBIT;
+ } else if (ioc_attr.adapter_attr.max_speed == BFA_PORT_SPEED_10GBPS) {
+ supported_speed |= FC_PORTSPEED_10GBIT;
+ }
+ return supported_speed;
+}
+
void
bfad_os_fc_host_init(struct bfad_im_port_s *im_port)
{
struct Scsi_Host *host = im_port->shost;
struct bfad_s *bfad = im_port->bfad;
struct bfad_port_s *port = im_port->port;
- struct bfa_pport_attr_s pattr;
- char model[BFA_ADAPTER_MODEL_NAME_LEN];
- char fw_ver[BFA_VERSION_LEN];
+ struct bfa_port_attr_s pattr;
+ struct bfa_lport_attr_s port_attr;
+ char symname[BFA_SYMNAME_MAXLEN];
fc_host_node_name(host) =
- bfa_os_htonll((bfa_fcs_port_get_nwwn(port->fcs_port)));
+ bfa_os_htonll((bfa_fcs_lport_get_nwwn(port->fcs_port)));
fc_host_port_name(host) =
- bfa_os_htonll((bfa_fcs_port_get_pwwn(port->fcs_port)));
+ bfa_os_htonll((bfa_fcs_lport_get_pwwn(port->fcs_port)));
fc_host_max_npiv_vports(host) = bfa_lps_get_max_vport(&bfad->bfa);
fc_host_supported_classes(host) = FC_COS_CLASS3;
memset(fc_host_supported_fc4s(host), 0,
sizeof(fc_host_supported_fc4s(host)));
- if (bfad_supported_fc4s & (BFA_PORT_ROLE_FCP_IM | BFA_PORT_ROLE_FCP_TM))
+ if (supported_fc4s & BFA_LPORT_ROLE_FCP_IM)
/* For FCP type 0x08 */
fc_host_supported_fc4s(host)[2] = 1;
- if (bfad_supported_fc4s & BFA_PORT_ROLE_FCP_IPFC)
- /* For LLC/SNAP type 0x05 */
- fc_host_supported_fc4s(host)[3] = 0x20;
/* For fibre channel services type 0x20 */
fc_host_supported_fc4s(host)[7] = 1;
- bfa_get_adapter_model(&bfad->bfa, model);
- bfa_get_adapter_fw_ver(&bfad->bfa, fw_ver);
- sprintf(fc_host_symbolic_name(host), "Brocade %s FV%s DV%s",
- model, fw_ver, BFAD_DRIVER_VERSION);
+ bfa_fcs_lport_get_attr(&bfad->bfa_fcs.fabric.bport, &port_attr);
+ strncpy(symname, port_attr.port_cfg.sym_name.symname,
+ BFA_SYMNAME_MAXLEN);
+ sprintf(fc_host_symbolic_name(host), "%s", symname);
- fc_host_supported_speeds(host) = 0;
- fc_host_supported_speeds(host) |=
- FC_PORTSPEED_8GBIT | FC_PORTSPEED_4GBIT | FC_PORTSPEED_2GBIT |
- FC_PORTSPEED_1GBIT;
+ fc_host_supported_speeds(host) = bfad_im_supported_speeds(&bfad->bfa);
bfa_fcport_get_attr(&bfad->bfa, &pattr);
fc_host_maxframe_size(host) = pattr.pport_cfg.maxfrsize;
@@ -1065,7 +1048,9 @@ bfad_im_itnim_work_handler(struct work_struct *work)
fcid2str(fcid_str, fcid);
list_add_tail(&itnim->list_entry,
&im_port->itnim_mapped_list);
- bfa_log(bfad->logmod, BFA_LOG_LINUX_ITNIM_ONLINE,
+ BFA_LOG(KERN_INFO, bfad, log_level,
+ "ITNIM ONLINE Target: %d:0:%d "
+ "FCID: %s WWPN: %s\n",
im_port->shost->host_no,
itnim->scsi_tgt_id,
fcid_str, wwpn_str);
@@ -1096,7 +1081,9 @@ bfad_im_itnim_work_handler(struct work_struct *work)
wwn2str(wwpn_str, wwpn);
fcid2str(fcid_str, fcid);
list_del(&itnim->list_entry);
- bfa_log(bfad->logmod, BFA_LOG_LINUX_ITNIM_OFFLINE,
+ BFA_LOG(KERN_INFO, bfad, log_level,
+ "ITNIM OFFLINE Target: %d:0:%d "
+ "FCID: %s WWPN: %s\n",
im_port->shost->host_no,
itnim->scsi_tgt_id,
fcid_str, wwpn_str);
@@ -1142,7 +1129,7 @@ bfad_im_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
struct bfa_ioim_s *hal_io;
unsigned long flags;
int rc;
- s16 sg_cnt = 0;
+ int sg_cnt = 0;
struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device));
rc = fc_remote_port_chkready(rport);
@@ -1153,7 +1140,6 @@ bfad_im_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
}
sg_cnt = scsi_dma_map(cmnd);
-
if (sg_cnt < 0)
return SCSI_MLQUEUE_HOST_BUSY;
@@ -1168,6 +1154,7 @@ bfad_im_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
goto out_fail_cmd;
}
+
itnim = itnim_data->itnim;
if (!itnim) {
cmnd->result = ScsiResult(DID_IMM_RETRY, 0);
@@ -1206,47 +1193,49 @@ bfad_os_rport_online_wait(struct bfad_s *bfad)
int rport_delay = 10;
for (i = 0; !(bfad->bfad_flags & BFAD_PORT_ONLINE)
- && i < bfa_linkup_delay; i++)
- schedule_timeout_uninterruptible(HZ);
+ && i < bfa_linkup_delay; i++) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(HZ);
+ }
if (bfad->bfad_flags & BFAD_PORT_ONLINE) {
rport_delay = rport_delay < bfa_linkup_delay ?
- rport_delay : bfa_linkup_delay;
+ rport_delay : bfa_linkup_delay;
for (i = 0; !(bfad->bfad_flags & BFAD_RPORT_ONLINE)
- && i < rport_delay; i++)
- schedule_timeout_uninterruptible(HZ);
+ && i < rport_delay; i++) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(HZ);
+ }
- if (rport_delay > 0 && (bfad->bfad_flags & BFAD_RPORT_ONLINE))
- schedule_timeout_uninterruptible(rport_delay * HZ);
+ if (rport_delay > 0 && (bfad->bfad_flags & BFAD_RPORT_ONLINE)) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(rport_delay * HZ);
+ }
}
}
int
bfad_os_get_linkup_delay(struct bfad_s *bfad)
{
-
- u8 nwwns = 0;
- wwn_t wwns[BFA_PREBOOT_BOOTLUN_MAX];
- int ldelay;
+ u8 nwwns = 0;
+ wwn_t wwns[BFA_PREBOOT_BOOTLUN_MAX];
+ int linkup_delay;
/*
* Querying for the boot target port wwns
* -- read from boot information in flash.
- * If nwwns > 0 => boot over SAN and set bfa_linkup_delay = 30
- * else => local boot machine set bfa_linkup_delay = 10
+ * If nwwns > 0 => boot over SAN and set linkup_delay = 30
+ * else => local boot machine set linkup_delay = 0
*/
bfa_iocfc_get_bootwwns(&bfad->bfa, &nwwns, wwns);
- if (nwwns > 0) {
- /* If boot over SAN; linkup_delay = 30sec */
- ldelay = 30;
- } else {
- /* If local boot; linkup_delay = 10sec */
- ldelay = 0;
- }
+ if (nwwns > 0)
+ /* If Boot over SAN set linkup_delay = 30sec */
+ linkup_delay = 30;
+ else
+ /* If local boot; no linkup_delay */
+ linkup_delay = 0;
- return ldelay;
+ return linkup_delay;
}
-
-
diff --git a/drivers/scsi/bfa/bfad_im.h b/drivers/scsi/bfa/bfad_im.h
index 973cab4d09c7..b038c0e08921 100644
--- a/drivers/scsi/bfa/bfad_im.h
+++ b/drivers/scsi/bfa/bfad_im.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
* All rights reserved
* www.brocade.com
*
@@ -18,20 +18,20 @@
#ifndef __BFAD_IM_H__
#define __BFAD_IM_H__
-#include "fcs/bfa_fcs_fcpim.h"
-#include "bfad_im_compat.h"
+#include "bfa_fcs.h"
#define FCPI_NAME " fcpim"
+#ifndef KOBJ_NAME_LEN
+#define KOBJ_NAME_LEN 20
+#endif
+
bfa_status_t bfad_im_module_init(void);
void bfad_im_module_exit(void);
bfa_status_t bfad_im_probe(struct bfad_s *bfad);
void bfad_im_probe_undo(struct bfad_s *bfad);
-void bfad_im_probe_post(struct bfad_im_s *im);
bfa_status_t bfad_im_port_new(struct bfad_s *bfad, struct bfad_port_s *port);
void bfad_im_port_delete(struct bfad_s *bfad, struct bfad_port_s *port);
-void bfad_im_port_online(struct bfad_s *bfad, struct bfad_port_s *port);
-void bfad_im_port_offline(struct bfad_s *bfad, struct bfad_port_s *port);
void bfad_im_port_clean(struct bfad_im_port_s *im_port);
int bfad_im_scsi_host_alloc(struct bfad_s *bfad,
struct bfad_im_port_s *im_port, struct device *dev);
@@ -44,14 +44,10 @@ void bfad_im_scsi_host_free(struct bfad_s *bfad,
#define BFAD_LUN_RESET_TMO 60
#define ScsiResult(host_code, scsi_code) (((host_code) << 16) | scsi_code)
#define BFA_QUEUE_FULL_RAMP_UP_TIME 120
-#define BFAD_KOBJ_NAME_LEN 20
/*
* itnim flags
*/
-#define ITNIM_MAPPED 0x00000001
-
-#define SCSI_TASK_MGMT 0x00000001
#define IO_DONE_BIT 0
struct bfad_itnim_data_s {
@@ -64,7 +60,7 @@ struct bfad_im_port_s {
struct work_struct port_delete_work;
int idr_id;
u16 cur_scsi_id;
- u16 flags;
+ u16 flags;
struct list_head binding_list;
struct Scsi_Host *shost;
struct list_head itnim_mapped_list;
@@ -118,14 +114,13 @@ struct bfad_fcp_binding {
struct bfad_im_s {
struct bfad_s *bfad;
struct workqueue_struct *drv_workq;
- char drv_workq_name[BFAD_KOBJ_NAME_LEN];
+ char drv_workq_name[KOBJ_NAME_LEN];
};
struct Scsi_Host *bfad_os_scsi_host_alloc(struct bfad_im_port_s *im_port,
struct bfad_s *);
bfa_status_t bfad_os_thread_workq(struct bfad_s *bfad);
void bfad_os_destroy_workq(struct bfad_im_s *im);
-void bfad_os_itnim_process(struct bfad_itnim_s *itnim_drv);
void bfad_os_fc_host_init(struct bfad_im_port_s *im_port);
void bfad_os_scsi_host_free(struct bfad_s *bfad,
struct bfad_im_port_s *im_port);
@@ -133,11 +128,6 @@ void bfad_os_ramp_up_qdepth(struct bfad_itnim_s *itnim,
struct scsi_device *sdev);
void bfad_os_handle_qfull(struct bfad_itnim_s *itnim, struct scsi_device *sdev);
struct bfad_itnim_s *bfad_os_get_itnim(struct bfad_im_port_s *im_port, int id);
-int bfad_os_scsi_add_host(struct Scsi_Host *shost,
- struct bfad_im_port_s *im_port, struct bfad_s *bfad);
-
-void bfad_im_itnim_unmap(struct bfad_im_port_s *im_port,
- struct bfad_itnim_s *itnim);
extern struct scsi_host_template bfad_im_scsi_host_template;
extern struct scsi_host_template bfad_im_vport_template;
@@ -146,4 +136,34 @@ extern struct fc_function_template bfad_im_vport_fc_function_template;
extern struct scsi_transport_template *bfad_im_scsi_transport_template;
extern struct scsi_transport_template *bfad_im_scsi_vport_transport_template;
+extern struct device_attribute *bfad_im_host_attrs[];
+extern struct device_attribute *bfad_im_vport_attrs[];
+
+irqreturn_t bfad_intx(int irq, void *dev_id);
+
+/* Firmware releated */
+#define BFAD_FW_FILE_CT_FC "ctfw_fc.bin"
+#define BFAD_FW_FILE_CT_CNA "ctfw_cna.bin"
+#define BFAD_FW_FILE_CB_FC "cbfw_fc.bin"
+
+u32 *bfad_get_firmware_buf(struct pci_dev *pdev);
+u32 *bfad_read_firmware(struct pci_dev *pdev, u32 **bfi_image,
+ u32 *bfi_image_size, char *fw_name);
+
+static inline u32 *
+bfad_load_fwimg(struct pci_dev *pdev)
+{
+ return bfad_get_firmware_buf(pdev);
+}
+
+static inline void
+bfad_free_fwimg(void)
+{
+ if (bfi_image_ct_fc_size && bfi_image_ct_fc)
+ vfree(bfi_image_ct_fc);
+ if (bfi_image_ct_cna_size && bfi_image_ct_cna)
+ vfree(bfi_image_ct_cna);
+ if (bfi_image_cb_fc_size && bfi_image_cb_fc)
+ vfree(bfi_image_cb_fc);
+}
#endif
diff --git a/drivers/scsi/bfa/bfad_im_compat.h b/drivers/scsi/bfa/bfad_im_compat.h
deleted file mode 100644
index 0a122abbbe89..000000000000
--- a/drivers/scsi/bfa/bfad_im_compat.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFAD_IM_COMPAT_H__
-#define __BFAD_IM_COMPAT_H__
-
-extern struct device_attribute *bfad_im_host_attrs[];
-extern struct device_attribute *bfad_im_vport_attrs[];
-
-u32 *bfad_get_firmware_buf(struct pci_dev *pdev);
-u32 *bfad_read_firmware(struct pci_dev *pdev, u32 **bfi_image,
- u32 *bfi_image_size, char *fw_name);
-
-static inline u32 *
-bfad_load_fwimg(struct pci_dev *pdev)
-{
- return bfad_get_firmware_buf(pdev);
-}
-
-static inline void
-bfad_free_fwimg(void)
-{
- if (bfi_image_ct_fc_size && bfi_image_ct_fc)
- vfree(bfi_image_ct_fc);
- if (bfi_image_ct_cna_size && bfi_image_ct_cna)
- vfree(bfi_image_ct_cna);
- if (bfi_image_cb_fc_size && bfi_image_cb_fc)
- vfree(bfi_image_cb_fc);
-}
-
-#endif
diff --git a/drivers/scsi/bfa/bfad_intr.c b/drivers/scsi/bfa/bfad_intr.c
deleted file mode 100644
index 56a351584f0c..000000000000
--- a/drivers/scsi/bfa/bfad_intr.c
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#include "bfad_drv.h"
-#include "bfad_trcmod.h"
-
-BFA_TRC_FILE(LDRV, INTR);
-
-/**
- * bfa_isr BFA driver interrupt functions
- */
-static int msix_disable_cb;
-static int msix_disable_ct;
-module_param(msix_disable_cb, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(msix_disable_cb, "Disable MSIX for Brocade-415/425/815/825"
- " cards, default=0, Range[false:0|true:1]");
-module_param(msix_disable_ct, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(msix_disable_ct, "Disable MSIX for Brocade-1010/1020/804"
- " cards, default=0, Range[false:0|true:1]");
-/**
- * Line based interrupt handler.
- */
-static irqreturn_t
-bfad_intx(int irq, void *dev_id)
-{
- struct bfad_s *bfad = dev_id;
- struct list_head doneq;
- unsigned long flags;
- bfa_boolean_t rc;
-
- spin_lock_irqsave(&bfad->bfad_lock, flags);
- rc = bfa_intx(&bfad->bfa);
- if (!rc) {
- spin_unlock_irqrestore(&bfad->bfad_lock, flags);
- return IRQ_NONE;
- }
-
- bfa_comp_deq(&bfad->bfa, &doneq);
- spin_unlock_irqrestore(&bfad->bfad_lock, flags);
-
- if (!list_empty(&doneq)) {
- bfa_comp_process(&bfad->bfa, &doneq);
-
- spin_lock_irqsave(&bfad->bfad_lock, flags);
- bfa_comp_free(&bfad->bfa, &doneq);
- spin_unlock_irqrestore(&bfad->bfad_lock, flags);
- bfa_trc_fp(bfad, irq);
- }
-
- return IRQ_HANDLED;
-
-}
-
-static irqreturn_t
-bfad_msix(int irq, void *dev_id)
-{
- struct bfad_msix_s *vec = dev_id;
- struct bfad_s *bfad = vec->bfad;
- struct list_head doneq;
- unsigned long flags;
-
- spin_lock_irqsave(&bfad->bfad_lock, flags);
-
- bfa_msix(&bfad->bfa, vec->msix.entry);
- bfa_comp_deq(&bfad->bfa, &doneq);
- spin_unlock_irqrestore(&bfad->bfad_lock, flags);
-
- if (!list_empty(&doneq)) {
- bfa_comp_process(&bfad->bfa, &doneq);
-
- spin_lock_irqsave(&bfad->bfad_lock, flags);
- bfa_comp_free(&bfad->bfa, &doneq);
- spin_unlock_irqrestore(&bfad->bfad_lock, flags);
- }
-
- return IRQ_HANDLED;
-}
-
-/**
- * Initialize the MSIX entry table.
- */
-static void
-bfad_init_msix_entry(struct bfad_s *bfad, struct msix_entry *msix_entries,
- int mask, int max_bit)
-{
- int i;
- int match = 0x00000001;
-
- for (i = 0, bfad->nvec = 0; i < MAX_MSIX_ENTRY; i++) {
- if (mask & match) {
- bfad->msix_tab[bfad->nvec].msix.entry = i;
- bfad->msix_tab[bfad->nvec].bfad = bfad;
- msix_entries[bfad->nvec].entry = i;
- bfad->nvec++;
- }
-
- match <<= 1;
- }
-
-}
-
-int
-bfad_install_msix_handler(struct bfad_s *bfad)
-{
- int i, error = 0;
-
- for (i = 0; i < bfad->nvec; i++) {
- error = request_irq(bfad->msix_tab[i].msix.vector,
- (irq_handler_t) bfad_msix, 0,
- BFAD_DRIVER_NAME, &bfad->msix_tab[i]);
- bfa_trc(bfad, i);
- bfa_trc(bfad, bfad->msix_tab[i].msix.vector);
- if (error) {
- int j;
-
- for (j = 0; j < i; j++)
- free_irq(bfad->msix_tab[j].msix.vector,
- &bfad->msix_tab[j]);
-
- return 1;
- }
- }
-
- return 0;
-}
-
-/**
- * Setup MSIX based interrupt.
- */
-int
-bfad_setup_intr(struct bfad_s *bfad)
-{
- int error = 0;
- u32 mask = 0, i, num_bit = 0, max_bit = 0;
- struct msix_entry msix_entries[MAX_MSIX_ENTRY];
- struct pci_dev *pdev = bfad->pcidev;
-
- /* Call BFA to get the msix map for this PCI function. */
- bfa_msix_getvecs(&bfad->bfa, &mask, &num_bit, &max_bit);
-
- /* Set up the msix entry table */
- bfad_init_msix_entry(bfad, msix_entries, mask, max_bit);
-
- if ((bfa_asic_id_ct(pdev->device) && !msix_disable_ct) ||
- (!bfa_asic_id_ct(pdev->device) && !msix_disable_cb)) {
-
- error = pci_enable_msix(bfad->pcidev, msix_entries, bfad->nvec);
- if (error) {
- /*
- * Only error number of vector is available.
- * We don't have a mechanism to map multiple
- * interrupts into one vector, so even if we
- * can try to request less vectors, we don't
- * know how to associate interrupt events to
- * vectors. Linux doesn't dupicate vectors
- * in the MSIX table for this case.
- */
-
- printk(KERN_WARNING "bfad%d: "
- "pci_enable_msix failed (%d),"
- " use line based.\n", bfad->inst_no, error);
-
- goto line_based;
- }
-
- /* Save the vectors */
- for (i = 0; i < bfad->nvec; i++) {
- bfa_trc(bfad, msix_entries[i].vector);
- bfad->msix_tab[i].msix.vector = msix_entries[i].vector;
- }
-
- bfa_msix_init(&bfad->bfa, bfad->nvec);
-
- bfad->bfad_flags |= BFAD_MSIX_ON;
-
- return error;
- }
-
-line_based:
- error = 0;
- if (request_irq
- (bfad->pcidev->irq, (irq_handler_t) bfad_intx, BFAD_IRQ_FLAGS,
- BFAD_DRIVER_NAME, bfad) != 0) {
- /* Enable interrupt handler failed */
- return 1;
- }
-
- return error;
-}
-
-void
-bfad_remove_intr(struct bfad_s *bfad)
-{
- int i;
-
- if (bfad->bfad_flags & BFAD_MSIX_ON) {
- for (i = 0; i < bfad->nvec; i++)
- free_irq(bfad->msix_tab[i].msix.vector,
- &bfad->msix_tab[i]);
-
- pci_disable_msix(bfad->pcidev);
- bfad->bfad_flags &= ~BFAD_MSIX_ON;
- } else {
- free_irq(bfad->pcidev->irq, bfad);
- }
-}
-
-
diff --git a/drivers/scsi/bfa/bfad_ipfc.h b/drivers/scsi/bfa/bfad_ipfc.h
deleted file mode 100644
index 718bc5227671..000000000000
--- a/drivers/scsi/bfa/bfad_ipfc.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-#ifndef __BFA_DRV_IPFC_H__
-#define __BFA_DRV_IPFC_H__
-
-
-#define IPFC_NAME ""
-
-#define bfad_ipfc_module_init(x) do {} while (0)
-#define bfad_ipfc_module_exit(x) do {} while (0)
-#define bfad_ipfc_probe(x) do {} while (0)
-#define bfad_ipfc_probe_undo(x) do {} while (0)
-#define bfad_ipfc_port_config(x, y) BFA_STATUS_OK
-#define bfad_ipfc_port_unconfig(x, y) do {} while (0)
-
-#define bfad_ipfc_probe_post(x) do {} while (0)
-#define bfad_ipfc_port_new(x, y, z) BFA_STATUS_OK
-#define bfad_ipfc_port_delete(x, y) do {} while (0)
-#define bfad_ipfc_port_online(x, y) do {} while (0)
-#define bfad_ipfc_port_offline(x, y) do {} while (0)
-
-#define bfad_ip_get_attr(x) BFA_STATUS_FAILED
-#define bfad_ip_reset_drv_stats(x) BFA_STATUS_FAILED
-#define bfad_ip_get_drv_stats(x, y) BFA_STATUS_FAILED
-#define bfad_ip_enable_ipfc(x, y, z) BFA_STATUS_FAILED
-
-
-#endif
diff --git a/drivers/scsi/bfa/bfad_os.c b/drivers/scsi/bfa/bfad_os.c
deleted file mode 100644
index faf47b4f1a38..000000000000
--- a/drivers/scsi/bfa/bfad_os.c
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/**
- * bfad_os.c Linux driver OS specific calls.
- */
-
-#include "bfa_os_inc.h"
-#include "bfad_drv.h"
-
-void
-bfa_os_gettimeofday(struct bfa_timeval_s *tv)
-{
- struct timeval tmp_tv;
-
- do_gettimeofday(&tmp_tv);
- tv->tv_sec = (u32) tmp_tv.tv_sec;
- tv->tv_usec = (u32) tmp_tv.tv_usec;
-}
-
-void
-bfa_os_printf(struct bfa_log_mod_s *log_mod, u32 msg_id,
- const char *fmt, ...)
-{
- va_list ap;
- #define BFA_STRING_256 256
- char tmp[BFA_STRING_256];
-
- va_start(ap, fmt);
- vsprintf(tmp, fmt, ap);
- va_end(ap);
-
- printk(tmp);
-}
-
-
diff --git a/drivers/scsi/bfa/bfad_tm.h b/drivers/scsi/bfa/bfad_tm.h
deleted file mode 100644
index 4901b1b7df02..000000000000
--- a/drivers/scsi/bfa/bfad_tm.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/*
- * Brocade Fibre Channel HBA Linux Target Mode Driver
- */
-
-/**
- * tm/dummy/bfad_tm.h BFA callback dummy header file for BFA Linux target mode PCI interface module.
- */
-
-#ifndef __BFAD_TM_H__
-#define __BFAD_TM_H__
-
-#include <defs/bfa_defs_status.h>
-
-#define FCPT_NAME ""
-
-/*
- * Called from base Linux driver on (De)Init events
- */
-
-/* attach tgt template with scst */
-#define bfad_tm_module_init() do {} while (0)
-
-/* detach/release tgt template */
-#define bfad_tm_module_exit() do {} while (0)
-
-#define bfad_tm_probe(x) do {} while (0)
-#define bfad_tm_probe_undo(x) do {} while (0)
-#define bfad_tm_probe_post(x) do {} while (0)
-
-/*
- * Called by base Linux driver but triggered by BFA FCS on config events
- */
-#define bfad_tm_port_new(x, y) BFA_STATUS_OK
-#define bfad_tm_port_delete(x, y) do {} while (0)
-
-/*
- * Called by base Linux driver but triggered by BFA FCS on PLOGI/O events
- */
-#define bfad_tm_port_online(x, y) do {} while (0)
-#define bfad_tm_port_offline(x, y) do {} while (0)
-
-#endif
diff --git a/drivers/scsi/bfa/bfad_trcmod.h b/drivers/scsi/bfa/bfad_trcmod.h
deleted file mode 100644
index 2827b2acd041..000000000000
--- a/drivers/scsi/bfa/bfad_trcmod.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/**
- * bfad_trcmod.h Linux driver trace modules
- */
-
-
-#ifndef __BFAD_TRCMOD_H__
-#define __BFAD_TRCMOD_H__
-
-#include <cs/bfa_trc.h>
-
-/*
- * !!! Only append to the enums defined here to avoid any versioning
- * !!! needed between trace utility and driver version
- */
-enum {
- /* 2.6 Driver */
- BFA_TRC_LDRV_BFAD = 1,
- BFA_TRC_LDRV_BFAD_2_6 = 2,
- BFA_TRC_LDRV_BFAD_2_6_9 = 3,
- BFA_TRC_LDRV_BFAD_2_6_10 = 4,
- BFA_TRC_LDRV_INTR = 5,
- BFA_TRC_LDRV_IOCTL = 6,
- BFA_TRC_LDRV_OS = 7,
- BFA_TRC_LDRV_IM = 8,
- BFA_TRC_LDRV_IM_2_6 = 9,
- BFA_TRC_LDRV_IM_2_6_9 = 10,
- BFA_TRC_LDRV_IM_2_6_10 = 11,
- BFA_TRC_LDRV_TM = 12,
- BFA_TRC_LDRV_IPFC = 13,
- BFA_TRC_LDRV_IM_2_4 = 14,
- BFA_TRC_LDRV_IM_VMW = 15,
- BFA_TRC_LDRV_IM_LT_2_6_10 = 16,
-};
-
-#endif /* __BFAD_TRCMOD_H__ */
diff --git a/drivers/scsi/bfa/bfi.h b/drivers/scsi/bfa/bfi.h
new file mode 100644
index 000000000000..85f2224a5733
--- /dev/null
+++ b/drivers/scsi/bfa/bfi.h
@@ -0,0 +1,579 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFI_H__
+#define __BFI_H__
+
+#include "bfa_defs.h"
+#include "bfa_defs_svc.h"
+
+#pragma pack(1)
+
+/**
+ * BFI FW image type
+ */
+#define BFI_FLASH_CHUNK_SZ 256 /* Flash chunk size */
+#define BFI_FLASH_CHUNK_SZ_WORDS (BFI_FLASH_CHUNK_SZ/sizeof(u32))
+enum {
+ BFI_IMAGE_CB_FC,
+ BFI_IMAGE_CT_FC,
+ BFI_IMAGE_CT_CNA,
+ BFI_IMAGE_MAX,
+};
+
+/**
+ * Msg header common to all msgs
+ */
+struct bfi_mhdr_s {
+ u8 msg_class; /* @ref bfi_mclass_t */
+ u8 msg_id; /* msg opcode with in the class */
+ union {
+ struct {
+ u8 rsvd;
+ u8 lpu_id; /* msg destination */
+ } h2i;
+ u16 i2htok; /* token in msgs to host */
+ } mtag;
+};
+
+#define bfi_h2i_set(_mh, _mc, _op, _lpuid) do { \
+ (_mh).msg_class = (_mc); \
+ (_mh).msg_id = (_op); \
+ (_mh).mtag.h2i.lpu_id = (_lpuid); \
+} while (0)
+
+#define bfi_i2h_set(_mh, _mc, _op, _i2htok) do { \
+ (_mh).msg_class = (_mc); \
+ (_mh).msg_id = (_op); \
+ (_mh).mtag.i2htok = (_i2htok); \
+} while (0)
+
+/*
+ * Message opcodes: 0-127 to firmware, 128-255 to host
+ */
+#define BFI_I2H_OPCODE_BASE 128
+#define BFA_I2HM(_x) ((_x) + BFI_I2H_OPCODE_BASE)
+
+/**
+ ****************************************************************************
+ *
+ * Scatter Gather Element and Page definition
+ *
+ ****************************************************************************
+ */
+
+#define BFI_SGE_INLINE 1
+#define BFI_SGE_INLINE_MAX (BFI_SGE_INLINE + 1)
+
+/**
+ * SG Flags
+ */
+enum {
+ BFI_SGE_DATA = 0, /* data address, not last */
+ BFI_SGE_DATA_CPL = 1, /* data addr, last in current page */
+ BFI_SGE_DATA_LAST = 3, /* data address, last */
+ BFI_SGE_LINK = 2, /* link address */
+ BFI_SGE_PGDLEN = 2, /* cumulative data length for page */
+};
+
+/**
+ * DMA addresses
+ */
+union bfi_addr_u {
+ struct {
+ u32 addr_lo;
+ u32 addr_hi;
+ } a32;
+};
+
+/**
+ * Scatter Gather Element
+ */
+struct bfi_sge_s {
+#ifdef __BIGENDIAN
+ u32 flags:2,
+ rsvd:2,
+ sg_len:28;
+#else
+ u32 sg_len:28,
+ rsvd:2,
+ flags:2;
+#endif
+ union bfi_addr_u sga;
+};
+
+/**
+ * Scatter Gather Page
+ */
+#define BFI_SGPG_DATA_SGES 7
+#define BFI_SGPG_SGES_MAX (BFI_SGPG_DATA_SGES + 1)
+#define BFI_SGPG_RSVD_WD_LEN 8
+struct bfi_sgpg_s {
+ struct bfi_sge_s sges[BFI_SGPG_SGES_MAX];
+ u32 rsvd[BFI_SGPG_RSVD_WD_LEN];
+};
+
+/*
+ * Large Message structure - 128 Bytes size Msgs
+ */
+#define BFI_LMSG_SZ 128
+#define BFI_LMSG_PL_WSZ \
+ ((BFI_LMSG_SZ - sizeof(struct bfi_mhdr_s)) / 4)
+
+struct bfi_msg_s {
+ struct bfi_mhdr_s mhdr;
+ u32 pl[BFI_LMSG_PL_WSZ];
+};
+
+/**
+ * Mailbox message structure
+ */
+#define BFI_MBMSG_SZ 7
+struct bfi_mbmsg_s {
+ struct bfi_mhdr_s mh;
+ u32 pl[BFI_MBMSG_SZ];
+};
+
+/**
+ * Message Classes
+ */
+enum bfi_mclass {
+ BFI_MC_IOC = 1, /* IO Controller (IOC) */
+ BFI_MC_FCPORT = 5, /* FC port */
+ BFI_MC_IOCFC = 6, /* FC - IO Controller (IOC) */
+ BFI_MC_LL = 7, /* Link Layer */
+ BFI_MC_UF = 8, /* Unsolicited frame receive */
+ BFI_MC_FCXP = 9, /* FC Transport */
+ BFI_MC_LPS = 10, /* lport fc login services */
+ BFI_MC_RPORT = 11, /* Remote port */
+ BFI_MC_ITNIM = 12, /* I-T nexus (Initiator mode) */
+ BFI_MC_IOIM_READ = 13, /* read IO (Initiator mode) */
+ BFI_MC_IOIM_WRITE = 14, /* write IO (Initiator mode) */
+ BFI_MC_IOIM_IO = 15, /* IO (Initiator mode) */
+ BFI_MC_IOIM = 16, /* IO (Initiator mode) */
+ BFI_MC_IOIM_IOCOM = 17, /* good IO completion */
+ BFI_MC_TSKIM = 18, /* Initiator Task management */
+ BFI_MC_PORT = 21, /* Physical port */
+ BFI_MC_MAX = 32
+};
+
+#define BFI_IOC_MAX_CQS 4
+#define BFI_IOC_MAX_CQS_ASIC 8
+#define BFI_IOC_MSGLEN_MAX 32 /* 32 bytes */
+
+#define BFI_BOOT_TYPE_OFF 8
+#define BFI_BOOT_LOADER_OFF 12
+
+#define BFI_BOOT_TYPE_NORMAL 0
+#define BFI_BOOT_TYPE_FLASH 1
+#define BFI_BOOT_TYPE_MEMTEST 2
+
+#define BFI_BOOT_LOADER_OS 0
+#define BFI_BOOT_LOADER_BIOS 1
+#define BFI_BOOT_LOADER_UEFI 2
+
+/**
+ *----------------------------------------------------------------------
+ * IOC
+ *----------------------------------------------------------------------
+ */
+
+enum bfi_ioc_h2i_msgs {
+ BFI_IOC_H2I_ENABLE_REQ = 1,
+ BFI_IOC_H2I_DISABLE_REQ = 2,
+ BFI_IOC_H2I_GETATTR_REQ = 3,
+ BFI_IOC_H2I_DBG_SYNC = 4,
+ BFI_IOC_H2I_DBG_DUMP = 5,
+};
+
+enum bfi_ioc_i2h_msgs {
+ BFI_IOC_I2H_ENABLE_REPLY = BFA_I2HM(1),
+ BFI_IOC_I2H_DISABLE_REPLY = BFA_I2HM(2),
+ BFI_IOC_I2H_GETATTR_REPLY = BFA_I2HM(3),
+ BFI_IOC_I2H_READY_EVENT = BFA_I2HM(4),
+ BFI_IOC_I2H_HBEAT = BFA_I2HM(5),
+};
+
+/**
+ * BFI_IOC_H2I_GETATTR_REQ message
+ */
+struct bfi_ioc_getattr_req_s {
+ struct bfi_mhdr_s mh;
+ union bfi_addr_u attr_addr;
+};
+
+struct bfi_ioc_attr_s {
+ wwn_t mfg_pwwn; /* Mfg port wwn */
+ wwn_t mfg_nwwn; /* Mfg node wwn */
+ mac_t mfg_mac; /* Mfg mac */
+ u16 rsvd_a;
+ wwn_t pwwn;
+ wwn_t nwwn;
+ mac_t mac; /* PBC or Mfg mac */
+ u16 rsvd_b;
+ mac_t fcoe_mac;
+ u16 rsvd_c;
+ char brcd_serialnum[STRSZ(BFA_MFG_SERIALNUM_SIZE)];
+ u8 pcie_gen;
+ u8 pcie_lanes_orig;
+ u8 pcie_lanes;
+ u8 rx_bbcredit; /* receive buffer credits */
+ u32 adapter_prop; /* adapter properties */
+ u16 maxfrsize; /* max receive frame size */
+ char asic_rev;
+ u8 rsvd_d;
+ char fw_version[BFA_VERSION_LEN];
+ char optrom_version[BFA_VERSION_LEN];
+ struct bfa_mfg_vpd_s vpd;
+ u32 card_type; /* card type */
+};
+
+/**
+ * BFI_IOC_I2H_GETATTR_REPLY message
+ */
+struct bfi_ioc_getattr_reply_s {
+ struct bfi_mhdr_s mh; /* Common msg header */
+ u8 status; /* cfg reply status */
+ u8 rsvd[3];
+};
+
+/**
+ * Firmware memory page offsets
+ */
+#define BFI_IOC_SMEM_PG0_CB (0x40)
+#define BFI_IOC_SMEM_PG0_CT (0x180)
+
+/**
+ * Firmware statistic offset
+ */
+#define BFI_IOC_FWSTATS_OFF (0x6B40)
+#define BFI_IOC_FWSTATS_SZ (4096)
+
+/**
+ * Firmware trace offset
+ */
+#define BFI_IOC_TRC_OFF (0x4b00)
+#define BFI_IOC_TRC_ENTS 256
+
+#define BFI_IOC_FW_SIGNATURE (0xbfadbfad)
+#define BFI_IOC_MD5SUM_SZ 4
+struct bfi_ioc_image_hdr_s {
+ u32 signature; /* constant signature */
+ u32 rsvd_a;
+ u32 exec; /* exec vector */
+ u32 param; /* parameters */
+ u32 rsvd_b[4];
+ u32 md5sum[BFI_IOC_MD5SUM_SZ];
+};
+
+/**
+ * BFI_IOC_I2H_READY_EVENT message
+ */
+struct bfi_ioc_rdy_event_s {
+ struct bfi_mhdr_s mh; /* common msg header */
+ u8 init_status; /* init event status */
+ u8 rsvd[3];
+};
+
+struct bfi_ioc_hbeat_s {
+ struct bfi_mhdr_s mh; /* common msg header */
+ u32 hb_count; /* current heart beat count */
+};
+
+/**
+ * IOC hardware/firmware state
+ */
+enum bfi_ioc_state {
+ BFI_IOC_UNINIT = 0, /* not initialized */
+ BFI_IOC_INITING = 1, /* h/w is being initialized */
+ BFI_IOC_HWINIT = 2, /* h/w is initialized */
+ BFI_IOC_CFG = 3, /* IOC configuration in progress */
+ BFI_IOC_OP = 4, /* IOC is operational */
+ BFI_IOC_DISABLING = 5, /* IOC is being disabled */
+ BFI_IOC_DISABLED = 6, /* IOC is disabled */
+ BFI_IOC_CFG_DISABLED = 7, /* IOC is being disabled;transient */
+ BFI_IOC_FAIL = 8, /* IOC heart-beat failure */
+ BFI_IOC_MEMTEST = 9, /* IOC is doing memtest */
+};
+
+#define BFI_IOC_ENDIAN_SIG 0x12345678
+
+enum {
+ BFI_ADAPTER_TYPE_FC = 0x01, /* FC adapters */
+ BFI_ADAPTER_TYPE_MK = 0x0f0000, /* adapter type mask */
+ BFI_ADAPTER_TYPE_SH = 16, /* adapter type shift */
+ BFI_ADAPTER_NPORTS_MK = 0xff00, /* number of ports mask */
+ BFI_ADAPTER_NPORTS_SH = 8, /* number of ports shift */
+ BFI_ADAPTER_SPEED_MK = 0xff, /* adapter speed mask */
+ BFI_ADAPTER_SPEED_SH = 0, /* adapter speed shift */
+ BFI_ADAPTER_PROTO = 0x100000, /* prototype adapaters */
+ BFI_ADAPTER_TTV = 0x200000, /* TTV debug capable */
+ BFI_ADAPTER_UNSUPP = 0x400000, /* unknown adapter type */
+};
+
+#define BFI_ADAPTER_GETP(__prop, __adap_prop) \
+ (((__adap_prop) & BFI_ADAPTER_ ## __prop ## _MK) >> \
+ BFI_ADAPTER_ ## __prop ## _SH)
+#define BFI_ADAPTER_SETP(__prop, __val) \
+ ((__val) << BFI_ADAPTER_ ## __prop ## _SH)
+#define BFI_ADAPTER_IS_PROTO(__adap_type) \
+ ((__adap_type) & BFI_ADAPTER_PROTO)
+#define BFI_ADAPTER_IS_TTV(__adap_type) \
+ ((__adap_type) & BFI_ADAPTER_TTV)
+#define BFI_ADAPTER_IS_UNSUPP(__adap_type) \
+ ((__adap_type) & BFI_ADAPTER_UNSUPP)
+#define BFI_ADAPTER_IS_SPECIAL(__adap_type) \
+ ((__adap_type) & (BFI_ADAPTER_TTV | BFI_ADAPTER_PROTO | \
+ BFI_ADAPTER_UNSUPP))
+
+/**
+ * BFI_IOC_H2I_ENABLE_REQ & BFI_IOC_H2I_DISABLE_REQ messages
+ */
+struct bfi_ioc_ctrl_req_s {
+ struct bfi_mhdr_s mh;
+ u8 ioc_class;
+ u8 rsvd[3];
+ u32 tv_sec;
+};
+#define bfi_ioc_enable_req_t struct bfi_ioc_ctrl_req_s;
+#define bfi_ioc_disable_req_t struct bfi_ioc_ctrl_req_s;
+
+/**
+ * BFI_IOC_I2H_ENABLE_REPLY & BFI_IOC_I2H_DISABLE_REPLY messages
+ */
+struct bfi_ioc_ctrl_reply_s {
+ struct bfi_mhdr_s mh; /* Common msg header */
+ u8 status; /* enable/disable status */
+ u8 rsvd[3];
+};
+#define bfi_ioc_enable_reply_t struct bfi_ioc_ctrl_reply_s;
+#define bfi_ioc_disable_reply_t struct bfi_ioc_ctrl_reply_s;
+
+#define BFI_IOC_MSGSZ 8
+/**
+ * H2I Messages
+ */
+union bfi_ioc_h2i_msg_u {
+ struct bfi_mhdr_s mh;
+ struct bfi_ioc_ctrl_req_s enable_req;
+ struct bfi_ioc_ctrl_req_s disable_req;
+ struct bfi_ioc_getattr_req_s getattr_req;
+ u32 mboxmsg[BFI_IOC_MSGSZ];
+};
+
+/**
+ * I2H Messages
+ */
+union bfi_ioc_i2h_msg_u {
+ struct bfi_mhdr_s mh;
+ struct bfi_ioc_rdy_event_s rdy_event;
+ u32 mboxmsg[BFI_IOC_MSGSZ];
+};
+
+
+/**
+ *----------------------------------------------------------------------
+ * PBC
+ *----------------------------------------------------------------------
+ */
+
+#define BFI_PBC_MAX_BLUNS 8
+#define BFI_PBC_MAX_VPORTS 16
+
+/**
+ * PBC boot lun configuration
+ */
+struct bfi_pbc_blun_s {
+ wwn_t tgt_pwwn;
+ lun_t tgt_lun;
+};
+
+/**
+ * PBC virtual port configuration
+ */
+struct bfi_pbc_vport_s {
+ wwn_t vp_pwwn;
+ wwn_t vp_nwwn;
+};
+
+/**
+ * BFI pre-boot configuration information
+ */
+struct bfi_pbc_s {
+ u8 port_enabled;
+ u8 boot_enabled;
+ u8 nbluns;
+ u8 nvports;
+ u8 port_speed;
+ u8 rsvd_a;
+ u16 hss;
+ wwn_t pbc_pwwn;
+ wwn_t pbc_nwwn;
+ struct bfi_pbc_blun_s blun[BFI_PBC_MAX_BLUNS];
+ struct bfi_pbc_vport_s vport[BFI_PBC_MAX_VPORTS];
+};
+
+/**
+ *----------------------------------------------------------------------
+ * MSGQ
+ *----------------------------------------------------------------------
+ */
+#define BFI_MSGQ_FULL(_q) (((_q->pi + 1) % _q->q_depth) == _q->ci)
+#define BFI_MSGQ_EMPTY(_q) (_q->pi == _q->ci)
+#define BFI_MSGQ_UPDATE_CI(_q) (_q->ci = (_q->ci + 1) % _q->q_depth)
+#define BFI_MSGQ_UPDATE_PI(_q) (_q->pi = (_q->pi + 1) % _q->q_depth)
+
+/* q_depth must be power of 2 */
+#define BFI_MSGQ_FREE_CNT(_q) ((_q->ci - _q->pi - 1) & (_q->q_depth - 1))
+
+enum bfi_msgq_h2i_msgs_e {
+ BFI_MSGQ_H2I_INIT_REQ = 1,
+ BFI_MSGQ_H2I_DOORBELL = 2,
+ BFI_MSGQ_H2I_SHUTDOWN = 3,
+};
+
+enum bfi_msgq_i2h_msgs_e {
+ BFI_MSGQ_I2H_INIT_RSP = 1,
+ BFI_MSGQ_I2H_DOORBELL = 2,
+};
+
+
+/* Messages(commands/responsed/AENS will have the following header */
+struct bfi_msgq_mhdr_s {
+ u8 msg_class;
+ u8 msg_id;
+ u16 msg_token;
+ u16 num_entries;
+ u8 enet_id;
+ u8 rsvd[1];
+};
+
+#define bfi_msgq_mhdr_set(_mh, _mc, _mid, _tok, _enet_id) do { \
+ (_mh).msg_class = (_mc); \
+ (_mh).msg_id = (_mid); \
+ (_mh).msg_token = (_tok); \
+ (_mh).enet_id = (_enet_id); \
+} while (0)
+
+/*
+ * Mailbox for messaging interface
+ *
+*/
+#define BFI_MSGQ_CMD_ENTRY_SIZE (64) /* TBD */
+#define BFI_MSGQ_RSP_ENTRY_SIZE (64) /* TBD */
+#define BFI_MSGQ_MSG_SIZE_MAX (2048) /* TBD */
+
+struct bfi_msgq_s {
+ union bfi_addr_u addr;
+ u16 q_depth; /* Total num of entries in the queue */
+ u8 rsvd[2];
+};
+
+/* BFI_ENET_MSGQ_CFG_REQ TBD init or cfg? */
+struct bfi_msgq_cfg_req_s {
+ struct bfi_mhdr_s mh;
+ struct bfi_msgq_s cmdq;
+ struct bfi_msgq_s rspq;
+};
+
+/* BFI_ENET_MSGQ_CFG_RSP */
+struct bfi_msgq_cfg_rsp_s {
+ struct bfi_mhdr_s mh;
+ u8 cmd_status;
+ u8 rsvd[3];
+};
+
+
+/* BFI_MSGQ_H2I_DOORBELL */
+struct bfi_msgq_h2i_db_s {
+ struct bfi_mhdr_s mh;
+ u16 cmdq_pi;
+ u16 rspq_ci;
+};
+
+/* BFI_MSGQ_I2H_DOORBELL */
+struct bfi_msgq_i2h_db_s {
+ struct bfi_mhdr_s mh;
+ u16 rspq_pi;
+ u16 cmdq_ci;
+};
+
+#pragma pack()
+
+/* BFI port specific */
+#pragma pack(1)
+
+enum bfi_port_h2i {
+ BFI_PORT_H2I_ENABLE_REQ = (1),
+ BFI_PORT_H2I_DISABLE_REQ = (2),
+ BFI_PORT_H2I_GET_STATS_REQ = (3),
+ BFI_PORT_H2I_CLEAR_STATS_REQ = (4),
+};
+
+enum bfi_port_i2h {
+ BFI_PORT_I2H_ENABLE_RSP = BFA_I2HM(1),
+ BFI_PORT_I2H_DISABLE_RSP = BFA_I2HM(2),
+ BFI_PORT_I2H_GET_STATS_RSP = BFA_I2HM(3),
+ BFI_PORT_I2H_CLEAR_STATS_RSP = BFA_I2HM(4),
+};
+
+/**
+ * Generic REQ type
+ */
+struct bfi_port_generic_req_s {
+ struct bfi_mhdr_s mh; /* msg header */
+ u32 msgtag; /* msgtag for reply */
+ u32 rsvd;
+};
+
+/**
+ * Generic RSP type
+ */
+struct bfi_port_generic_rsp_s {
+ struct bfi_mhdr_s mh; /* common msg header */
+ u8 status; /* port enable status */
+ u8 rsvd[3];
+ u32 msgtag; /* msgtag for reply */
+};
+
+/**
+ * BFI_PORT_H2I_GET_STATS_REQ
+ */
+struct bfi_port_get_stats_req_s {
+ struct bfi_mhdr_s mh; /* common msg header */
+ union bfi_addr_u dma_addr;
+};
+
+union bfi_port_h2i_msg_u {
+ struct bfi_mhdr_s mh;
+ struct bfi_port_generic_req_s enable_req;
+ struct bfi_port_generic_req_s disable_req;
+ struct bfi_port_get_stats_req_s getstats_req;
+ struct bfi_port_generic_req_s clearstats_req;
+};
+
+union bfi_port_i2h_msg_u {
+ struct bfi_mhdr_s mh;
+ struct bfi_port_generic_rsp_s enable_rsp;
+ struct bfi_port_generic_rsp_s disable_rsp;
+ struct bfi_port_generic_rsp_s getstats_rsp;
+ struct bfi_port_generic_rsp_s clearstats_rsp;
+};
+
+#pragma pack()
+
+#endif /* __BFI_H__ */
diff --git a/drivers/scsi/bfa/include/bfi/bfi_cbreg.h b/drivers/scsi/bfa/bfi_cbreg.h
index a51ee61ddb19..6f03ed382c69 100644
--- a/drivers/scsi/bfa/include/bfi/bfi_cbreg.h
+++ b/drivers/scsi/bfa/bfi_cbreg.h
@@ -1,19 +1,3 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
/*
* bfi_cbreg.h crossbow host block register definitions
@@ -177,8 +161,8 @@
#define __PSS_LMEM_INIT_EN 0x00000100
#define __PSS_LPU1_RESET 0x00000002
#define __PSS_LPU0_RESET 0x00000001
-#define PSS_ERR_STATUS_REG 0x00018810
-#define __PSS_LMEM1_CORR_ERR 0x00000800
+#define PSS_ERR_STATUS_REG 0x00018810
+#define __PSS_LMEM1_CORR_ERR 0x00000800
#define __PSS_LMEM0_CORR_ERR 0x00000400
#define __PSS_LMEM1_UNCORR_ERR 0x00000200
#define __PSS_LMEM0_UNCORR_ERR 0x00000100
@@ -190,8 +174,9 @@
#define __PSS_SGM_IF_ERR 0x00000004
#define __PSS_LPU1_RAM_ERR 0x00000002
#define __PSS_LPU0_RAM_ERR 0x00000001
-#define ERR_SET_REG 0x00018818
-#define __PSS_ERR_STATUS_SET 0x00000fff
+#define ERR_SET_REG 0x00018818
+#define __PSS_ERR_STATUS_SET 0x00000fff
+
/*
* These definitions are either in error/missing in spec. Its auto-generated
diff --git a/drivers/scsi/bfa/bfi_ctreg.h b/drivers/scsi/bfa/bfi_ctreg.h
new file mode 100644
index 000000000000..62b86a4b0e4b
--- /dev/null
+++ b/drivers/scsi/bfa/bfi_ctreg.h
@@ -0,0 +1,627 @@
+
+/*
+ * bfi_ctreg.h catapult host block register definitions
+ *
+ * !!! Do not edit. Auto generated. !!!
+ */
+
+#ifndef __BFI_CTREG_H__
+#define __BFI_CTREG_H__
+
+
+#define HOSTFN0_LPU_MBOX0_0 0x00019200
+#define HOSTFN1_LPU_MBOX0_8 0x00019260
+#define LPU_HOSTFN0_MBOX0_0 0x00019280
+#define LPU_HOSTFN1_MBOX0_8 0x000192e0
+#define HOSTFN2_LPU_MBOX0_0 0x00019400
+#define HOSTFN3_LPU_MBOX0_8 0x00019460
+#define LPU_HOSTFN2_MBOX0_0 0x00019480
+#define LPU_HOSTFN3_MBOX0_8 0x000194e0
+#define HOSTFN0_INT_STATUS 0x00014000
+#define __HOSTFN0_HALT_OCCURRED 0x01000000
+#define __HOSTFN0_INT_STATUS_LVL_MK 0x00f00000
+#define __HOSTFN0_INT_STATUS_LVL_SH 20
+#define __HOSTFN0_INT_STATUS_LVL(_v) ((_v) << __HOSTFN0_INT_STATUS_LVL_SH)
+#define __HOSTFN0_INT_STATUS_P_MK 0x000f0000
+#define __HOSTFN0_INT_STATUS_P_SH 16
+#define __HOSTFN0_INT_STATUS_P(_v) ((_v) << __HOSTFN0_INT_STATUS_P_SH)
+#define __HOSTFN0_INT_STATUS_F 0x0000ffff
+#define HOSTFN0_INT_MSK 0x00014004
+#define HOST_PAGE_NUM_FN0 0x00014008
+#define __HOST_PAGE_NUM_FN 0x000001ff
+#define HOST_MSIX_ERR_INDEX_FN0 0x0001400c
+#define __MSIX_ERR_INDEX_FN 0x000001ff
+#define HOSTFN1_INT_STATUS 0x00014100
+#define __HOSTFN1_HALT_OCCURRED 0x01000000
+#define __HOSTFN1_INT_STATUS_LVL_MK 0x00f00000
+#define __HOSTFN1_INT_STATUS_LVL_SH 20
+#define __HOSTFN1_INT_STATUS_LVL(_v) ((_v) << __HOSTFN1_INT_STATUS_LVL_SH)
+#define __HOSTFN1_INT_STATUS_P_MK 0x000f0000
+#define __HOSTFN1_INT_STATUS_P_SH 16
+#define __HOSTFN1_INT_STATUS_P(_v) ((_v) << __HOSTFN1_INT_STATUS_P_SH)
+#define __HOSTFN1_INT_STATUS_F 0x0000ffff
+#define HOSTFN1_INT_MSK 0x00014104
+#define HOST_PAGE_NUM_FN1 0x00014108
+#define HOST_MSIX_ERR_INDEX_FN1 0x0001410c
+#define APP_PLL_425_CTL_REG 0x00014204
+#define __P_425_PLL_LOCK 0x80000000
+#define __APP_PLL_425_SRAM_USE_100MHZ 0x00100000
+#define __APP_PLL_425_RESET_TIMER_MK 0x000e0000
+#define __APP_PLL_425_RESET_TIMER_SH 17
+#define __APP_PLL_425_RESET_TIMER(_v) ((_v) << __APP_PLL_425_RESET_TIMER_SH)
+#define __APP_PLL_425_LOGIC_SOFT_RESET 0x00010000
+#define __APP_PLL_425_CNTLMT0_1_MK 0x0000c000
+#define __APP_PLL_425_CNTLMT0_1_SH 14
+#define __APP_PLL_425_CNTLMT0_1(_v) ((_v) << __APP_PLL_425_CNTLMT0_1_SH)
+#define __APP_PLL_425_JITLMT0_1_MK 0x00003000
+#define __APP_PLL_425_JITLMT0_1_SH 12
+#define __APP_PLL_425_JITLMT0_1(_v) ((_v) << __APP_PLL_425_JITLMT0_1_SH)
+#define __APP_PLL_425_HREF 0x00000800
+#define __APP_PLL_425_HDIV 0x00000400
+#define __APP_PLL_425_P0_1_MK 0x00000300
+#define __APP_PLL_425_P0_1_SH 8
+#define __APP_PLL_425_P0_1(_v) ((_v) << __APP_PLL_425_P0_1_SH)
+#define __APP_PLL_425_Z0_2_MK 0x000000e0
+#define __APP_PLL_425_Z0_2_SH 5
+#define __APP_PLL_425_Z0_2(_v) ((_v) << __APP_PLL_425_Z0_2_SH)
+#define __APP_PLL_425_RSEL200500 0x00000010
+#define __APP_PLL_425_ENARST 0x00000008
+#define __APP_PLL_425_BYPASS 0x00000004
+#define __APP_PLL_425_LRESETN 0x00000002
+#define __APP_PLL_425_ENABLE 0x00000001
+#define APP_PLL_312_CTL_REG 0x00014208
+#define __P_312_PLL_LOCK 0x80000000
+#define __ENABLE_MAC_AHB_1 0x00800000
+#define __ENABLE_MAC_AHB_0 0x00400000
+#define __ENABLE_MAC_1 0x00200000
+#define __ENABLE_MAC_0 0x00100000
+#define __APP_PLL_312_RESET_TIMER_MK 0x000e0000
+#define __APP_PLL_312_RESET_TIMER_SH 17
+#define __APP_PLL_312_RESET_TIMER(_v) ((_v) << __APP_PLL_312_RESET_TIMER_SH)
+#define __APP_PLL_312_LOGIC_SOFT_RESET 0x00010000
+#define __APP_PLL_312_CNTLMT0_1_MK 0x0000c000
+#define __APP_PLL_312_CNTLMT0_1_SH 14
+#define __APP_PLL_312_CNTLMT0_1(_v) ((_v) << __APP_PLL_312_CNTLMT0_1_SH)
+#define __APP_PLL_312_JITLMT0_1_MK 0x00003000
+#define __APP_PLL_312_JITLMT0_1_SH 12
+#define __APP_PLL_312_JITLMT0_1(_v) ((_v) << __APP_PLL_312_JITLMT0_1_SH)
+#define __APP_PLL_312_HREF 0x00000800
+#define __APP_PLL_312_HDIV 0x00000400
+#define __APP_PLL_312_P0_1_MK 0x00000300
+#define __APP_PLL_312_P0_1_SH 8
+#define __APP_PLL_312_P0_1(_v) ((_v) << __APP_PLL_312_P0_1_SH)
+#define __APP_PLL_312_Z0_2_MK 0x000000e0
+#define __APP_PLL_312_Z0_2_SH 5
+#define __APP_PLL_312_Z0_2(_v) ((_v) << __APP_PLL_312_Z0_2_SH)
+#define __APP_PLL_312_RSEL200500 0x00000010
+#define __APP_PLL_312_ENARST 0x00000008
+#define __APP_PLL_312_BYPASS 0x00000004
+#define __APP_PLL_312_LRESETN 0x00000002
+#define __APP_PLL_312_ENABLE 0x00000001
+#define MBIST_CTL_REG 0x00014220
+#define __EDRAM_BISTR_START 0x00000004
+#define __MBIST_RESET 0x00000002
+#define __MBIST_START 0x00000001
+#define MBIST_STAT_REG 0x00014224
+#define __EDRAM_BISTR_STATUS 0x00000008
+#define __EDRAM_BISTR_DONE 0x00000004
+#define __MEM_BIT_STATUS 0x00000002
+#define __MBIST_DONE 0x00000001
+#define HOST_SEM0_REG 0x00014230
+#define __HOST_SEMAPHORE 0x00000001
+#define HOST_SEM1_REG 0x00014234
+#define HOST_SEM2_REG 0x00014238
+#define HOST_SEM3_REG 0x0001423c
+#define HOST_SEM0_INFO_REG 0x00014240
+#define HOST_SEM1_INFO_REG 0x00014244
+#define HOST_SEM2_INFO_REG 0x00014248
+#define HOST_SEM3_INFO_REG 0x0001424c
+#define ETH_MAC_SER_REG 0x00014288
+#define __APP_EMS_CKBUFAMPIN 0x00000020
+#define __APP_EMS_REFCLKSEL 0x00000010
+#define __APP_EMS_CMLCKSEL 0x00000008
+#define __APP_EMS_REFCKBUFEN2 0x00000004
+#define __APP_EMS_REFCKBUFEN1 0x00000002
+#define __APP_EMS_CHANNEL_SEL 0x00000001
+#define HOSTFN2_INT_STATUS 0x00014300
+#define __HOSTFN2_HALT_OCCURRED 0x01000000
+#define __HOSTFN2_INT_STATUS_LVL_MK 0x00f00000
+#define __HOSTFN2_INT_STATUS_LVL_SH 20
+#define __HOSTFN2_INT_STATUS_LVL(_v) ((_v) << __HOSTFN2_INT_STATUS_LVL_SH)
+#define __HOSTFN2_INT_STATUS_P_MK 0x000f0000
+#define __HOSTFN2_INT_STATUS_P_SH 16
+#define __HOSTFN2_INT_STATUS_P(_v) ((_v) << __HOSTFN2_INT_STATUS_P_SH)
+#define __HOSTFN2_INT_STATUS_F 0x0000ffff
+#define HOSTFN2_INT_MSK 0x00014304
+#define HOST_PAGE_NUM_FN2 0x00014308
+#define HOST_MSIX_ERR_INDEX_FN2 0x0001430c
+#define HOSTFN3_INT_STATUS 0x00014400
+#define __HALT_OCCURRED 0x01000000
+#define __HOSTFN3_INT_STATUS_LVL_MK 0x00f00000
+#define __HOSTFN3_INT_STATUS_LVL_SH 20
+#define __HOSTFN3_INT_STATUS_LVL(_v) ((_v) << __HOSTFN3_INT_STATUS_LVL_SH)
+#define __HOSTFN3_INT_STATUS_P_MK 0x000f0000
+#define __HOSTFN3_INT_STATUS_P_SH 16
+#define __HOSTFN3_INT_STATUS_P(_v) ((_v) << __HOSTFN3_INT_STATUS_P_SH)
+#define __HOSTFN3_INT_STATUS_F 0x0000ffff
+#define HOSTFN3_INT_MSK 0x00014404
+#define HOST_PAGE_NUM_FN3 0x00014408
+#define HOST_MSIX_ERR_INDEX_FN3 0x0001440c
+#define FNC_ID_REG 0x00014600
+#define __FUNCTION_NUMBER 0x00000007
+#define FNC_PERS_REG 0x00014604
+#define __F3_FUNCTION_ACTIVE 0x80000000
+#define __F3_FUNCTION_MODE 0x40000000
+#define __F3_PORT_MAP_MK 0x30000000
+#define __F3_PORT_MAP_SH 28
+#define __F3_PORT_MAP(_v) ((_v) << __F3_PORT_MAP_SH)
+#define __F3_VM_MODE 0x08000000
+#define __F3_INTX_STATUS_MK 0x07000000
+#define __F3_INTX_STATUS_SH 24
+#define __F3_INTX_STATUS(_v) ((_v) << __F3_INTX_STATUS_SH)
+#define __F2_FUNCTION_ACTIVE 0x00800000
+#define __F2_FUNCTION_MODE 0x00400000
+#define __F2_PORT_MAP_MK 0x00300000
+#define __F2_PORT_MAP_SH 20
+#define __F2_PORT_MAP(_v) ((_v) << __F2_PORT_MAP_SH)
+#define __F2_VM_MODE 0x00080000
+#define __F2_INTX_STATUS_MK 0x00070000
+#define __F2_INTX_STATUS_SH 16
+#define __F2_INTX_STATUS(_v) ((_v) << __F2_INTX_STATUS_SH)
+#define __F1_FUNCTION_ACTIVE 0x00008000
+#define __F1_FUNCTION_MODE 0x00004000
+#define __F1_PORT_MAP_MK 0x00003000
+#define __F1_PORT_MAP_SH 12
+#define __F1_PORT_MAP(_v) ((_v) << __F1_PORT_MAP_SH)
+#define __F1_VM_MODE 0x00000800
+#define __F1_INTX_STATUS_MK 0x00000700
+#define __F1_INTX_STATUS_SH 8
+#define __F1_INTX_STATUS(_v) ((_v) << __F1_INTX_STATUS_SH)
+#define __F0_FUNCTION_ACTIVE 0x00000080
+#define __F0_FUNCTION_MODE 0x00000040
+#define __F0_PORT_MAP_MK 0x00000030
+#define __F0_PORT_MAP_SH 4
+#define __F0_PORT_MAP(_v) ((_v) << __F0_PORT_MAP_SH)
+#define __F0_VM_MODE 0x00000008
+#define __F0_INTX_STATUS 0x00000007
+enum {
+ __F0_INTX_STATUS_MSIX = 0x0,
+ __F0_INTX_STATUS_INTA = 0x1,
+ __F0_INTX_STATUS_INTB = 0x2,
+ __F0_INTX_STATUS_INTC = 0x3,
+ __F0_INTX_STATUS_INTD = 0x4,
+};
+#define OP_MODE 0x0001460c
+#define __APP_ETH_CLK_LOWSPEED 0x00000004
+#define __GLOBAL_CORECLK_HALFSPEED 0x00000002
+#define __GLOBAL_FCOE_MODE 0x00000001
+#define HOST_SEM4_REG 0x00014610
+#define HOST_SEM5_REG 0x00014614
+#define HOST_SEM6_REG 0x00014618
+#define HOST_SEM7_REG 0x0001461c
+#define HOST_SEM4_INFO_REG 0x00014620
+#define HOST_SEM5_INFO_REG 0x00014624
+#define HOST_SEM6_INFO_REG 0x00014628
+#define HOST_SEM7_INFO_REG 0x0001462c
+#define HOSTFN0_LPU0_MBOX0_CMD_STAT 0x00019000
+#define __HOSTFN0_LPU0_MBOX0_INFO_MK 0xfffffffe
+#define __HOSTFN0_LPU0_MBOX0_INFO_SH 1
+#define __HOSTFN0_LPU0_MBOX0_INFO(_v) ((_v) << __HOSTFN0_LPU0_MBOX0_INFO_SH)
+#define __HOSTFN0_LPU0_MBOX0_CMD_STATUS 0x00000001
+#define HOSTFN0_LPU1_MBOX0_CMD_STAT 0x00019004
+#define __HOSTFN0_LPU1_MBOX0_INFO_MK 0xfffffffe
+#define __HOSTFN0_LPU1_MBOX0_INFO_SH 1
+#define __HOSTFN0_LPU1_MBOX0_INFO(_v) ((_v) << __HOSTFN0_LPU1_MBOX0_INFO_SH)
+#define __HOSTFN0_LPU1_MBOX0_CMD_STATUS 0x00000001
+#define LPU0_HOSTFN0_MBOX0_CMD_STAT 0x00019008
+#define __LPU0_HOSTFN0_MBOX0_INFO_MK 0xfffffffe
+#define __LPU0_HOSTFN0_MBOX0_INFO_SH 1
+#define __LPU0_HOSTFN0_MBOX0_INFO(_v) ((_v) << __LPU0_HOSTFN0_MBOX0_INFO_SH)
+#define __LPU0_HOSTFN0_MBOX0_CMD_STATUS 0x00000001
+#define LPU1_HOSTFN0_MBOX0_CMD_STAT 0x0001900c
+#define __LPU1_HOSTFN0_MBOX0_INFO_MK 0xfffffffe
+#define __LPU1_HOSTFN0_MBOX0_INFO_SH 1
+#define __LPU1_HOSTFN0_MBOX0_INFO(_v) ((_v) << __LPU1_HOSTFN0_MBOX0_INFO_SH)
+#define __LPU1_HOSTFN0_MBOX0_CMD_STATUS 0x00000001
+#define HOSTFN1_LPU0_MBOX0_CMD_STAT 0x00019010
+#define __HOSTFN1_LPU0_MBOX0_INFO_MK 0xfffffffe
+#define __HOSTFN1_LPU0_MBOX0_INFO_SH 1
+#define __HOSTFN1_LPU0_MBOX0_INFO(_v) ((_v) << __HOSTFN1_LPU0_MBOX0_INFO_SH)
+#define __HOSTFN1_LPU0_MBOX0_CMD_STATUS 0x00000001
+#define HOSTFN1_LPU1_MBOX0_CMD_STAT 0x00019014
+#define __HOSTFN1_LPU1_MBOX0_INFO_MK 0xfffffffe
+#define __HOSTFN1_LPU1_MBOX0_INFO_SH 1
+#define __HOSTFN1_LPU1_MBOX0_INFO(_v) ((_v) << __HOSTFN1_LPU1_MBOX0_INFO_SH)
+#define __HOSTFN1_LPU1_MBOX0_CMD_STATUS 0x00000001
+#define LPU0_HOSTFN1_MBOX0_CMD_STAT 0x00019018
+#define __LPU0_HOSTFN1_MBOX0_INFO_MK 0xfffffffe
+#define __LPU0_HOSTFN1_MBOX0_INFO_SH 1
+#define __LPU0_HOSTFN1_MBOX0_INFO(_v) ((_v) << __LPU0_HOSTFN1_MBOX0_INFO_SH)
+#define __LPU0_HOSTFN1_MBOX0_CMD_STATUS 0x00000001
+#define LPU1_HOSTFN1_MBOX0_CMD_STAT 0x0001901c
+#define __LPU1_HOSTFN1_MBOX0_INFO_MK 0xfffffffe
+#define __LPU1_HOSTFN1_MBOX0_INFO_SH 1
+#define __LPU1_HOSTFN1_MBOX0_INFO(_v) ((_v) << __LPU1_HOSTFN1_MBOX0_INFO_SH)
+#define __LPU1_HOSTFN1_MBOX0_CMD_STATUS 0x00000001
+#define HOSTFN2_LPU0_MBOX0_CMD_STAT 0x00019150
+#define __HOSTFN2_LPU0_MBOX0_INFO_MK 0xfffffffe
+#define __HOSTFN2_LPU0_MBOX0_INFO_SH 1
+#define __HOSTFN2_LPU0_MBOX0_INFO(_v) ((_v) << __HOSTFN2_LPU0_MBOX0_INFO_SH)
+#define __HOSTFN2_LPU0_MBOX0_CMD_STATUS 0x00000001
+#define HOSTFN2_LPU1_MBOX0_CMD_STAT 0x00019154
+#define __HOSTFN2_LPU1_MBOX0_INFO_MK 0xfffffffe
+#define __HOSTFN2_LPU1_MBOX0_INFO_SH 1
+#define __HOSTFN2_LPU1_MBOX0_INFO(_v) ((_v) << __HOSTFN2_LPU1_MBOX0_INFO_SH)
+#define __HOSTFN2_LPU1_MBOX0BOX0_CMD_STATUS 0x00000001
+#define LPU0_HOSTFN2_MBOX0_CMD_STAT 0x00019158
+#define __LPU0_HOSTFN2_MBOX0_INFO_MK 0xfffffffe
+#define __LPU0_HOSTFN2_MBOX0_INFO_SH 1
+#define __LPU0_HOSTFN2_MBOX0_INFO(_v) ((_v) << __LPU0_HOSTFN2_MBOX0_INFO_SH)
+#define __LPU0_HOSTFN2_MBOX0_CMD_STATUS 0x00000001
+#define LPU1_HOSTFN2_MBOX0_CMD_STAT 0x0001915c
+#define __LPU1_HOSTFN2_MBOX0_INFO_MK 0xfffffffe
+#define __LPU1_HOSTFN2_MBOX0_INFO_SH 1
+#define __LPU1_HOSTFN2_MBOX0_INFO(_v) ((_v) << __LPU1_HOSTFN2_MBOX0_INFO_SH)
+#define __LPU1_HOSTFN2_MBOX0_CMD_STATUS 0x00000001
+#define HOSTFN3_LPU0_MBOX0_CMD_STAT 0x00019160
+#define __HOSTFN3_LPU0_MBOX0_INFO_MK 0xfffffffe
+#define __HOSTFN3_LPU0_MBOX0_INFO_SH 1
+#define __HOSTFN3_LPU0_MBOX0_INFO(_v) ((_v) << __HOSTFN3_LPU0_MBOX0_INFO_SH)
+#define __HOSTFN3_LPU0_MBOX0_CMD_STATUS 0x00000001
+#define HOSTFN3_LPU1_MBOX0_CMD_STAT 0x00019164
+#define __HOSTFN3_LPU1_MBOX0_INFO_MK 0xfffffffe
+#define __HOSTFN3_LPU1_MBOX0_INFO_SH 1
+#define __HOSTFN3_LPU1_MBOX0_INFO(_v) ((_v) << __HOSTFN3_LPU1_MBOX0_INFO_SH)
+#define __HOSTFN3_LPU1_MBOX0_CMD_STATUS 0x00000001
+#define LPU0_HOSTFN3_MBOX0_CMD_STAT 0x00019168
+#define __LPU0_HOSTFN3_MBOX0_INFO_MK 0xfffffffe
+#define __LPU0_HOSTFN3_MBOX0_INFO_SH 1
+#define __LPU0_HOSTFN3_MBOX0_INFO(_v) ((_v) << __LPU0_HOSTFN3_MBOX0_INFO_SH)
+#define __LPU0_HOSTFN3_MBOX0_CMD_STATUS 0x00000001
+#define LPU1_HOSTFN3_MBOX0_CMD_STAT 0x0001916c
+#define __LPU1_HOSTFN3_MBOX0_INFO_MK 0xfffffffe
+#define __LPU1_HOSTFN3_MBOX0_INFO_SH 1
+#define __LPU1_HOSTFN3_MBOX0_INFO(_v) ((_v) << __LPU1_HOSTFN3_MBOX0_INFO_SH)
+#define __LPU1_HOSTFN3_MBOX0_CMD_STATUS 0x00000001
+#define FW_INIT_HALT_P0 0x000191ac
+#define __FW_INIT_HALT_P 0x00000001
+#define FW_INIT_HALT_P1 0x000191bc
+#define CPE_PI_PTR_Q0 0x00038000
+#define __CPE_PI_UNUSED_MK 0xffff0000
+#define __CPE_PI_UNUSED_SH 16
+#define __CPE_PI_UNUSED(_v) ((_v) << __CPE_PI_UNUSED_SH)
+#define __CPE_PI_PTR 0x0000ffff
+#define CPE_PI_PTR_Q1 0x00038040
+#define CPE_CI_PTR_Q0 0x00038004
+#define __CPE_CI_UNUSED_MK 0xffff0000
+#define __CPE_CI_UNUSED_SH 16
+#define __CPE_CI_UNUSED(_v) ((_v) << __CPE_CI_UNUSED_SH)
+#define __CPE_CI_PTR 0x0000ffff
+#define CPE_CI_PTR_Q1 0x00038044
+#define CPE_DEPTH_Q0 0x00038008
+#define __CPE_DEPTH_UNUSED_MK 0xf8000000
+#define __CPE_DEPTH_UNUSED_SH 27
+#define __CPE_DEPTH_UNUSED(_v) ((_v) << __CPE_DEPTH_UNUSED_SH)
+#define __CPE_MSIX_VEC_INDEX_MK 0x07ff0000
+#define __CPE_MSIX_VEC_INDEX_SH 16
+#define __CPE_MSIX_VEC_INDEX(_v) ((_v) << __CPE_MSIX_VEC_INDEX_SH)
+#define __CPE_DEPTH 0x0000ffff
+#define CPE_DEPTH_Q1 0x00038048
+#define CPE_QCTRL_Q0 0x0003800c
+#define __CPE_CTRL_UNUSED30_MK 0xfc000000
+#define __CPE_CTRL_UNUSED30_SH 26
+#define __CPE_CTRL_UNUSED30(_v) ((_v) << __CPE_CTRL_UNUSED30_SH)
+#define __CPE_FUNC_INT_CTRL_MK 0x03000000
+#define __CPE_FUNC_INT_CTRL_SH 24
+#define __CPE_FUNC_INT_CTRL(_v) ((_v) << __CPE_FUNC_INT_CTRL_SH)
+enum {
+ __CPE_FUNC_INT_CTRL_DISABLE = 0x0,
+ __CPE_FUNC_INT_CTRL_F2NF = 0x1,
+ __CPE_FUNC_INT_CTRL_3QUART = 0x2,
+ __CPE_FUNC_INT_CTRL_HALF = 0x3,
+};
+#define __CPE_CTRL_UNUSED20_MK 0x00f00000
+#define __CPE_CTRL_UNUSED20_SH 20
+#define __CPE_CTRL_UNUSED20(_v) ((_v) << __CPE_CTRL_UNUSED20_SH)
+#define __CPE_SCI_TH_MK 0x000f0000
+#define __CPE_SCI_TH_SH 16
+#define __CPE_SCI_TH(_v) ((_v) << __CPE_SCI_TH_SH)
+#define __CPE_CTRL_UNUSED10_MK 0x0000c000
+#define __CPE_CTRL_UNUSED10_SH 14
+#define __CPE_CTRL_UNUSED10(_v) ((_v) << __CPE_CTRL_UNUSED10_SH)
+#define __CPE_ACK_PENDING 0x00002000
+#define __CPE_CTRL_UNUSED40_MK 0x00001c00
+#define __CPE_CTRL_UNUSED40_SH 10
+#define __CPE_CTRL_UNUSED40(_v) ((_v) << __CPE_CTRL_UNUSED40_SH)
+#define __CPE_PCIEID_MK 0x00000300
+#define __CPE_PCIEID_SH 8
+#define __CPE_PCIEID(_v) ((_v) << __CPE_PCIEID_SH)
+#define __CPE_CTRL_UNUSED00_MK 0x000000fe
+#define __CPE_CTRL_UNUSED00_SH 1
+#define __CPE_CTRL_UNUSED00(_v) ((_v) << __CPE_CTRL_UNUSED00_SH)
+#define __CPE_ESIZE 0x00000001
+#define CPE_QCTRL_Q1 0x0003804c
+#define __CPE_CTRL_UNUSED31_MK 0xfc000000
+#define __CPE_CTRL_UNUSED31_SH 26
+#define __CPE_CTRL_UNUSED31(_v) ((_v) << __CPE_CTRL_UNUSED31_SH)
+#define __CPE_CTRL_UNUSED21_MK 0x00f00000
+#define __CPE_CTRL_UNUSED21_SH 20
+#define __CPE_CTRL_UNUSED21(_v) ((_v) << __CPE_CTRL_UNUSED21_SH)
+#define __CPE_CTRL_UNUSED11_MK 0x0000c000
+#define __CPE_CTRL_UNUSED11_SH 14
+#define __CPE_CTRL_UNUSED11(_v) ((_v) << __CPE_CTRL_UNUSED11_SH)
+#define __CPE_CTRL_UNUSED41_MK 0x00001c00
+#define __CPE_CTRL_UNUSED41_SH 10
+#define __CPE_CTRL_UNUSED41(_v) ((_v) << __CPE_CTRL_UNUSED41_SH)
+#define __CPE_CTRL_UNUSED01_MK 0x000000fe
+#define __CPE_CTRL_UNUSED01_SH 1
+#define __CPE_CTRL_UNUSED01(_v) ((_v) << __CPE_CTRL_UNUSED01_SH)
+#define RME_PI_PTR_Q0 0x00038020
+#define __LATENCY_TIME_STAMP_MK 0xffff0000
+#define __LATENCY_TIME_STAMP_SH 16
+#define __LATENCY_TIME_STAMP(_v) ((_v) << __LATENCY_TIME_STAMP_SH)
+#define __RME_PI_PTR 0x0000ffff
+#define RME_PI_PTR_Q1 0x00038060
+#define RME_CI_PTR_Q0 0x00038024
+#define __DELAY_TIME_STAMP_MK 0xffff0000
+#define __DELAY_TIME_STAMP_SH 16
+#define __DELAY_TIME_STAMP(_v) ((_v) << __DELAY_TIME_STAMP_SH)
+#define __RME_CI_PTR 0x0000ffff
+#define RME_CI_PTR_Q1 0x00038064
+#define RME_DEPTH_Q0 0x00038028
+#define __RME_DEPTH_UNUSED_MK 0xf8000000
+#define __RME_DEPTH_UNUSED_SH 27
+#define __RME_DEPTH_UNUSED(_v) ((_v) << __RME_DEPTH_UNUSED_SH)
+#define __RME_MSIX_VEC_INDEX_MK 0x07ff0000
+#define __RME_MSIX_VEC_INDEX_SH 16
+#define __RME_MSIX_VEC_INDEX(_v) ((_v) << __RME_MSIX_VEC_INDEX_SH)
+#define __RME_DEPTH 0x0000ffff
+#define RME_DEPTH_Q1 0x00038068
+#define RME_QCTRL_Q0 0x0003802c
+#define __RME_INT_LATENCY_TIMER_MK 0xff000000
+#define __RME_INT_LATENCY_TIMER_SH 24
+#define __RME_INT_LATENCY_TIMER(_v) ((_v) << __RME_INT_LATENCY_TIMER_SH)
+#define __RME_INT_DELAY_TIMER_MK 0x00ff0000
+#define __RME_INT_DELAY_TIMER_SH 16
+#define __RME_INT_DELAY_TIMER(_v) ((_v) << __RME_INT_DELAY_TIMER_SH)
+#define __RME_INT_DELAY_DISABLE 0x00008000
+#define __RME_DLY_DELAY_DISABLE 0x00004000
+#define __RME_ACK_PENDING 0x00002000
+#define __RME_FULL_INTERRUPT_DISABLE 0x00001000
+#define __RME_CTRL_UNUSED10_MK 0x00000c00
+#define __RME_CTRL_UNUSED10_SH 10
+#define __RME_CTRL_UNUSED10(_v) ((_v) << __RME_CTRL_UNUSED10_SH)
+#define __RME_PCIEID_MK 0x00000300
+#define __RME_PCIEID_SH 8
+#define __RME_PCIEID(_v) ((_v) << __RME_PCIEID_SH)
+#define __RME_CTRL_UNUSED00_MK 0x000000fe
+#define __RME_CTRL_UNUSED00_SH 1
+#define __RME_CTRL_UNUSED00(_v) ((_v) << __RME_CTRL_UNUSED00_SH)
+#define __RME_ESIZE 0x00000001
+#define RME_QCTRL_Q1 0x0003806c
+#define __RME_CTRL_UNUSED11_MK 0x00000c00
+#define __RME_CTRL_UNUSED11_SH 10
+#define __RME_CTRL_UNUSED11(_v) ((_v) << __RME_CTRL_UNUSED11_SH)
+#define __RME_CTRL_UNUSED01_MK 0x000000fe
+#define __RME_CTRL_UNUSED01_SH 1
+#define __RME_CTRL_UNUSED01(_v) ((_v) << __RME_CTRL_UNUSED01_SH)
+#define PSS_CTL_REG 0x00018800
+#define __PSS_I2C_CLK_DIV_MK 0x007f0000
+#define __PSS_I2C_CLK_DIV_SH 16
+#define __PSS_I2C_CLK_DIV(_v) ((_v) << __PSS_I2C_CLK_DIV_SH)
+#define __PSS_LMEM_INIT_DONE 0x00001000
+#define __PSS_LMEM_RESET 0x00000200
+#define __PSS_LMEM_INIT_EN 0x00000100
+#define __PSS_LPU1_RESET 0x00000002
+#define __PSS_LPU0_RESET 0x00000001
+#define PSS_ERR_STATUS_REG 0x00018810
+#define __PSS_LPU1_TCM_READ_ERR 0x00200000
+#define __PSS_LPU0_TCM_READ_ERR 0x00100000
+#define __PSS_LMEM5_CORR_ERR 0x00080000
+#define __PSS_LMEM4_CORR_ERR 0x00040000
+#define __PSS_LMEM3_CORR_ERR 0x00020000
+#define __PSS_LMEM2_CORR_ERR 0x00010000
+#define __PSS_LMEM1_CORR_ERR 0x00008000
+#define __PSS_LMEM0_CORR_ERR 0x00004000
+#define __PSS_LMEM5_UNCORR_ERR 0x00002000
+#define __PSS_LMEM4_UNCORR_ERR 0x00001000
+#define __PSS_LMEM3_UNCORR_ERR 0x00000800
+#define __PSS_LMEM2_UNCORR_ERR 0x00000400
+#define __PSS_LMEM1_UNCORR_ERR 0x00000200
+#define __PSS_LMEM0_UNCORR_ERR 0x00000100
+#define __PSS_BAL_PERR 0x00000080
+#define __PSS_DIP_IF_ERR 0x00000040
+#define __PSS_IOH_IF_ERR 0x00000020
+#define __PSS_TDS_IF_ERR 0x00000010
+#define __PSS_RDS_IF_ERR 0x00000008
+#define __PSS_SGM_IF_ERR 0x00000004
+#define __PSS_LPU1_RAM_ERR 0x00000002
+#define __PSS_LPU0_RAM_ERR 0x00000001
+#define ERR_SET_REG 0x00018818
+#define __PSS_ERR_STATUS_SET 0x003fffff
+#define PMM_1T_RESET_REG_P0 0x0002381c
+#define __PMM_1T_RESET_P 0x00000001
+#define PMM_1T_RESET_REG_P1 0x00023c1c
+#define HQM_QSET0_RXQ_DRBL_P0 0x00038000
+#define __RXQ0_ADD_VECTORS_P 0x80000000
+#define __RXQ0_STOP_P 0x40000000
+#define __RXQ0_PRD_PTR_P 0x0000ffff
+#define HQM_QSET1_RXQ_DRBL_P0 0x00038080
+#define __RXQ1_ADD_VECTORS_P 0x80000000
+#define __RXQ1_STOP_P 0x40000000
+#define __RXQ1_PRD_PTR_P 0x0000ffff
+#define HQM_QSET0_RXQ_DRBL_P1 0x0003c000
+#define HQM_QSET1_RXQ_DRBL_P1 0x0003c080
+#define HQM_QSET0_TXQ_DRBL_P0 0x00038020
+#define __TXQ0_ADD_VECTORS_P 0x80000000
+#define __TXQ0_STOP_P 0x40000000
+#define __TXQ0_PRD_PTR_P 0x0000ffff
+#define HQM_QSET1_TXQ_DRBL_P0 0x000380a0
+#define __TXQ1_ADD_VECTORS_P 0x80000000
+#define __TXQ1_STOP_P 0x40000000
+#define __TXQ1_PRD_PTR_P 0x0000ffff
+#define HQM_QSET0_TXQ_DRBL_P1 0x0003c020
+#define HQM_QSET1_TXQ_DRBL_P1 0x0003c0a0
+#define HQM_QSET0_IB_DRBL_1_P0 0x00038040
+#define __IB1_0_ACK_P 0x80000000
+#define __IB1_0_DISABLE_P 0x40000000
+#define __IB1_0_COALESCING_CFG_P_MK 0x00ff0000
+#define __IB1_0_COALESCING_CFG_P_SH 16
+#define __IB1_0_COALESCING_CFG_P(_v) ((_v) << __IB1_0_COALESCING_CFG_P_SH)
+#define __IB1_0_NUM_OF_ACKED_EVENTS_P 0x0000ffff
+#define HQM_QSET1_IB_DRBL_1_P0 0x000380c0
+#define __IB1_1_ACK_P 0x80000000
+#define __IB1_1_DISABLE_P 0x40000000
+#define __IB1_1_COALESCING_CFG_P_MK 0x00ff0000
+#define __IB1_1_COALESCING_CFG_P_SH 16
+#define __IB1_1_COALESCING_CFG_P(_v) ((_v) << __IB1_1_COALESCING_CFG_P_SH)
+#define __IB1_1_NUM_OF_ACKED_EVENTS_P 0x0000ffff
+#define HQM_QSET0_IB_DRBL_1_P1 0x0003c040
+#define HQM_QSET1_IB_DRBL_1_P1 0x0003c0c0
+#define HQM_QSET0_IB_DRBL_2_P0 0x00038060
+#define __IB2_0_ACK_P 0x80000000
+#define __IB2_0_DISABLE_P 0x40000000
+#define __IB2_0_COALESCING_CFG_P_MK 0x00ff0000
+#define __IB2_0_COALESCING_CFG_P_SH 16
+#define __IB2_0_COALESCING_CFG_P(_v) ((_v) << __IB2_0_COALESCING_CFG_P_SH)
+#define __IB2_0_NUM_OF_ACKED_EVENTS_P 0x0000ffff
+#define HQM_QSET1_IB_DRBL_2_P0 0x000380e0
+#define __IB2_1_ACK_P 0x80000000
+#define __IB2_1_DISABLE_P 0x40000000
+#define __IB2_1_COALESCING_CFG_P_MK 0x00ff0000
+#define __IB2_1_COALESCING_CFG_P_SH 16
+#define __IB2_1_COALESCING_CFG_P(_v) ((_v) << __IB2_1_COALESCING_CFG_P_SH)
+#define __IB2_1_NUM_OF_ACKED_EVENTS_P 0x0000ffff
+#define HQM_QSET0_IB_DRBL_2_P1 0x0003c060
+#define HQM_QSET1_IB_DRBL_2_P1 0x0003c0e0
+
+
+/*
+ * These definitions are either in error/missing in spec. Its auto-generated
+ * from hard coded values in regparse.pl.
+ */
+#define __EMPHPOST_AT_4G_MK_FIX 0x0000001c
+#define __EMPHPOST_AT_4G_SH_FIX 0x00000002
+#define __EMPHPRE_AT_4G_FIX 0x00000003
+#define __SFP_TXRATE_EN_FIX 0x00000100
+#define __SFP_RXRATE_EN_FIX 0x00000080
+
+
+/*
+ * These register definitions are auto-generated from hard coded values
+ * in regparse.pl.
+ */
+
+
+/*
+ * These register mapping definitions are auto-generated from mapping tables
+ * in regparse.pl.
+ */
+#define BFA_IOC0_HBEAT_REG HOST_SEM0_INFO_REG
+#define BFA_IOC0_STATE_REG HOST_SEM1_INFO_REG
+#define BFA_IOC1_HBEAT_REG HOST_SEM2_INFO_REG
+#define BFA_IOC1_STATE_REG HOST_SEM3_INFO_REG
+#define BFA_FW_USE_COUNT HOST_SEM4_INFO_REG
+
+#define CPE_DEPTH_Q(__n) \
+ (CPE_DEPTH_Q0 + (__n) * (CPE_DEPTH_Q1 - CPE_DEPTH_Q0))
+#define CPE_QCTRL_Q(__n) \
+ (CPE_QCTRL_Q0 + (__n) * (CPE_QCTRL_Q1 - CPE_QCTRL_Q0))
+#define CPE_PI_PTR_Q(__n) \
+ (CPE_PI_PTR_Q0 + (__n) * (CPE_PI_PTR_Q1 - CPE_PI_PTR_Q0))
+#define CPE_CI_PTR_Q(__n) \
+ (CPE_CI_PTR_Q0 + (__n) * (CPE_CI_PTR_Q1 - CPE_CI_PTR_Q0))
+#define RME_DEPTH_Q(__n) \
+ (RME_DEPTH_Q0 + (__n) * (RME_DEPTH_Q1 - RME_DEPTH_Q0))
+#define RME_QCTRL_Q(__n) \
+ (RME_QCTRL_Q0 + (__n) * (RME_QCTRL_Q1 - RME_QCTRL_Q0))
+#define RME_PI_PTR_Q(__n) \
+ (RME_PI_PTR_Q0 + (__n) * (RME_PI_PTR_Q1 - RME_PI_PTR_Q0))
+#define RME_CI_PTR_Q(__n) \
+ (RME_CI_PTR_Q0 + (__n) * (RME_CI_PTR_Q1 - RME_CI_PTR_Q0))
+#define HQM_QSET_RXQ_DRBL_P0(__n) (HQM_QSET0_RXQ_DRBL_P0 + (__n) \
+ * (HQM_QSET1_RXQ_DRBL_P0 - HQM_QSET0_RXQ_DRBL_P0))
+#define HQM_QSET_TXQ_DRBL_P0(__n) (HQM_QSET0_TXQ_DRBL_P0 + (__n) \
+ * (HQM_QSET1_TXQ_DRBL_P0 - HQM_QSET0_TXQ_DRBL_P0))
+#define HQM_QSET_IB_DRBL_1_P0(__n) (HQM_QSET0_IB_DRBL_1_P0 + (__n) \
+ * (HQM_QSET1_IB_DRBL_1_P0 - HQM_QSET0_IB_DRBL_1_P0))
+#define HQM_QSET_IB_DRBL_2_P0(__n) (HQM_QSET0_IB_DRBL_2_P0 + (__n) \
+ * (HQM_QSET1_IB_DRBL_2_P0 - HQM_QSET0_IB_DRBL_2_P0))
+#define HQM_QSET_RXQ_DRBL_P1(__n) (HQM_QSET0_RXQ_DRBL_P1 + (__n) \
+ * (HQM_QSET1_RXQ_DRBL_P1 - HQM_QSET0_RXQ_DRBL_P1))
+#define HQM_QSET_TXQ_DRBL_P1(__n) (HQM_QSET0_TXQ_DRBL_P1 + (__n) \
+ * (HQM_QSET1_TXQ_DRBL_P1 - HQM_QSET0_TXQ_DRBL_P1))
+#define HQM_QSET_IB_DRBL_1_P1(__n) (HQM_QSET0_IB_DRBL_1_P1 + (__n) \
+ * (HQM_QSET1_IB_DRBL_1_P1 - HQM_QSET0_IB_DRBL_1_P1))
+#define HQM_QSET_IB_DRBL_2_P1(__n) (HQM_QSET0_IB_DRBL_2_P1 + (__n) \
+ * (HQM_QSET1_IB_DRBL_2_P1 - HQM_QSET0_IB_DRBL_2_P1))
+
+#define CPE_Q_NUM(__fn, __q) (((__fn) << 2) + (__q))
+#define RME_Q_NUM(__fn, __q) (((__fn) << 2) + (__q))
+#define CPE_Q_MASK(__q) ((__q) & 0x3)
+#define RME_Q_MASK(__q) ((__q) & 0x3)
+
+
+/*
+ * PCI MSI-X vector defines
+ */
+enum {
+ BFA_MSIX_CPE_Q0 = 0,
+ BFA_MSIX_CPE_Q1 = 1,
+ BFA_MSIX_CPE_Q2 = 2,
+ BFA_MSIX_CPE_Q3 = 3,
+ BFA_MSIX_RME_Q0 = 4,
+ BFA_MSIX_RME_Q1 = 5,
+ BFA_MSIX_RME_Q2 = 6,
+ BFA_MSIX_RME_Q3 = 7,
+ BFA_MSIX_LPU_ERR = 8,
+ BFA_MSIX_CT_MAX = 9,
+};
+
+/*
+ * And corresponding host interrupt status bit field defines
+ */
+#define __HFN_INT_CPE_Q0 0x00000001U
+#define __HFN_INT_CPE_Q1 0x00000002U
+#define __HFN_INT_CPE_Q2 0x00000004U
+#define __HFN_INT_CPE_Q3 0x00000008U
+#define __HFN_INT_CPE_Q4 0x00000010U
+#define __HFN_INT_CPE_Q5 0x00000020U
+#define __HFN_INT_CPE_Q6 0x00000040U
+#define __HFN_INT_CPE_Q7 0x00000080U
+#define __HFN_INT_RME_Q0 0x00000100U
+#define __HFN_INT_RME_Q1 0x00000200U
+#define __HFN_INT_RME_Q2 0x00000400U
+#define __HFN_INT_RME_Q3 0x00000800U
+#define __HFN_INT_RME_Q4 0x00001000U
+#define __HFN_INT_RME_Q5 0x00002000U
+#define __HFN_INT_RME_Q6 0x00004000U
+#define __HFN_INT_RME_Q7 0x00008000U
+#define __HFN_INT_ERR_EMC 0x00010000U
+#define __HFN_INT_ERR_LPU0 0x00020000U
+#define __HFN_INT_ERR_LPU1 0x00040000U
+#define __HFN_INT_ERR_PSS 0x00080000U
+#define __HFN_INT_MBOX_LPU0 0x00100000U
+#define __HFN_INT_MBOX_LPU1 0x00200000U
+#define __HFN_INT_MBOX1_LPU0 0x00400000U
+#define __HFN_INT_MBOX1_LPU1 0x00800000U
+#define __HFN_INT_LL_HALT 0x01000000U
+#define __HFN_INT_CPE_MASK 0x000000ffU
+#define __HFN_INT_RME_MASK 0x0000ff00U
+
+
+/*
+ * catapult memory map.
+ */
+#define LL_PGN_HQM0 0x0096
+#define LL_PGN_HQM1 0x0097
+#define PSS_SMEM_PAGE_START 0x8000
+#define PSS_SMEM_PGNUM(_pg0, _ma) ((_pg0) + ((_ma) >> 15))
+#define PSS_SMEM_PGOFF(_ma) ((_ma) & 0x7fff)
+
+/*
+ * End of catapult memory map
+ */
+
+
+#endif /* __BFI_CTREG_H__ */
diff --git a/drivers/scsi/bfa/bfi_ms.h b/drivers/scsi/bfa/bfi_ms.h
new file mode 100644
index 000000000000..69ac85f9e938
--- /dev/null
+++ b/drivers/scsi/bfa/bfi_ms.h
@@ -0,0 +1,765 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) Version 2 as
+ * published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __BFI_MS_H__
+#define __BFI_MS_H__
+
+#include "bfi.h"
+#include "bfa_fc.h"
+#include "bfa_defs_svc.h"
+
+#pragma pack(1)
+
+enum bfi_iocfc_h2i_msgs {
+ BFI_IOCFC_H2I_CFG_REQ = 1,
+ BFI_IOCFC_H2I_SET_INTR_REQ = 2,
+ BFI_IOCFC_H2I_UPDATEQ_REQ = 3,
+};
+
+enum bfi_iocfc_i2h_msgs {
+ BFI_IOCFC_I2H_CFG_REPLY = BFA_I2HM(1),
+ BFI_IOCFC_I2H_UPDATEQ_RSP = BFA_I2HM(3),
+};
+
+struct bfi_iocfc_cfg_s {
+ u8 num_cqs; /* Number of CQs to be used */
+ u8 sense_buf_len; /* SCSI sense length */
+ u16 rsvd_1;
+ u32 endian_sig; /* endian signature of host */
+
+ /**
+ * Request and response circular queue base addresses, size and
+ * shadow index pointers.
+ */
+ union bfi_addr_u req_cq_ba[BFI_IOC_MAX_CQS];
+ union bfi_addr_u req_shadow_ci[BFI_IOC_MAX_CQS];
+ u16 req_cq_elems[BFI_IOC_MAX_CQS];
+ union bfi_addr_u rsp_cq_ba[BFI_IOC_MAX_CQS];
+ union bfi_addr_u rsp_shadow_pi[BFI_IOC_MAX_CQS];
+ u16 rsp_cq_elems[BFI_IOC_MAX_CQS];
+
+ union bfi_addr_u stats_addr; /* DMA-able address for stats */
+ union bfi_addr_u cfgrsp_addr; /* config response dma address */
+ union bfi_addr_u ioim_snsbase; /* IO sense buffer base address */
+ struct bfa_iocfc_intr_attr_s intr_attr; /* IOC interrupt attributes */
+};
+
+/**
+ * Boot target wwn information for this port. This contains either the stored
+ * or discovered boot target port wwns for the port.
+ */
+struct bfi_iocfc_bootwwns {
+ wwn_t wwn[BFA_BOOT_BOOTLUN_MAX];
+ u8 nwwns;
+ u8 rsvd[7];
+};
+
+struct bfi_iocfc_cfgrsp_s {
+ struct bfa_iocfc_fwcfg_s fwcfg;
+ struct bfa_iocfc_intr_attr_s intr_attr;
+ struct bfi_iocfc_bootwwns bootwwns;
+ struct bfi_pbc_s pbc_cfg;
+};
+
+/**
+ * BFI_IOCFC_H2I_CFG_REQ message
+ */
+struct bfi_iocfc_cfg_req_s {
+ struct bfi_mhdr_s mh;
+ union bfi_addr_u ioc_cfg_dma_addr;
+};
+
+
+/**
+ * BFI_IOCFC_I2H_CFG_REPLY message
+ */
+struct bfi_iocfc_cfg_reply_s {
+ struct bfi_mhdr_s mh; /* Common msg header */
+ u8 cfg_success; /* cfg reply status */
+ u8 lpu_bm; /* LPUs assigned for this IOC */
+ u8 rsvd[2];
+};
+
+
+/**
+ * BFI_IOCFC_H2I_SET_INTR_REQ message
+ */
+struct bfi_iocfc_set_intr_req_s {
+ struct bfi_mhdr_s mh; /* common msg header */
+ u8 coalesce; /* enable intr coalescing */
+ u8 rsvd[3];
+ u16 delay; /* delay timer 0..1125us */
+ u16 latency; /* latency timer 0..225us */
+};
+
+
+/**
+ * BFI_IOCFC_H2I_UPDATEQ_REQ message
+ */
+struct bfi_iocfc_updateq_req_s {
+ struct bfi_mhdr_s mh; /* common msg header */
+ u32 reqq_ba; /* reqq base addr */
+ u32 rspq_ba; /* rspq base addr */
+ u32 reqq_sci; /* reqq shadow ci */
+ u32 rspq_spi; /* rspq shadow pi */
+};
+
+
+/**
+ * BFI_IOCFC_I2H_UPDATEQ_RSP message
+ */
+struct bfi_iocfc_updateq_rsp_s {
+ struct bfi_mhdr_s mh; /* common msg header */
+ u8 status; /* updateq status */
+ u8 rsvd[3];
+};
+
+
+/**
+ * H2I Messages
+ */
+union bfi_iocfc_h2i_msg_u {
+ struct bfi_mhdr_s mh;
+ struct bfi_iocfc_cfg_req_s cfg_req;
+ struct bfi_iocfc_updateq_req_s updateq_req;
+ u32 mboxmsg[BFI_IOC_MSGSZ];
+};
+
+
+/**
+ * I2H Messages
+ */
+union bfi_iocfc_i2h_msg_u {
+ struct bfi_mhdr_s mh;
+ struct bfi_iocfc_cfg_reply_s cfg_reply;
+ struct bfi_iocfc_updateq_rsp_s updateq_rsp;
+ u32 mboxmsg[BFI_IOC_MSGSZ];
+};
+
+
+enum bfi_fcport_h2i {
+ BFI_FCPORT_H2I_ENABLE_REQ = (1),
+ BFI_FCPORT_H2I_DISABLE_REQ = (2),
+ BFI_FCPORT_H2I_SET_SVC_PARAMS_REQ = (3),
+ BFI_FCPORT_H2I_STATS_GET_REQ = (4),
+ BFI_FCPORT_H2I_STATS_CLEAR_REQ = (5),
+};
+
+
+enum bfi_fcport_i2h {
+ BFI_FCPORT_I2H_ENABLE_RSP = BFA_I2HM(1),
+ BFI_FCPORT_I2H_DISABLE_RSP = BFA_I2HM(2),
+ BFI_FCPORT_I2H_SET_SVC_PARAMS_RSP = BFA_I2HM(3),
+ BFI_FCPORT_I2H_STATS_GET_RSP = BFA_I2HM(4),
+ BFI_FCPORT_I2H_STATS_CLEAR_RSP = BFA_I2HM(5),
+ BFI_FCPORT_I2H_EVENT = BFA_I2HM(6),
+ BFI_FCPORT_I2H_TRUNK_SCN = BFA_I2HM(7),
+ BFI_FCPORT_I2H_ENABLE_AEN = BFA_I2HM(8),
+ BFI_FCPORT_I2H_DISABLE_AEN = BFA_I2HM(9),
+};
+
+
+/**
+ * Generic REQ type
+ */
+struct bfi_fcport_req_s {
+ struct bfi_mhdr_s mh; /* msg header */
+ u32 msgtag; /* msgtag for reply */
+};
+
+/**
+ * Generic RSP type
+ */
+struct bfi_fcport_rsp_s {
+ struct bfi_mhdr_s mh; /* common msg header */
+ u8 status; /* port enable status */
+ u8 rsvd[3];
+ u32 msgtag; /* msgtag for reply */
+};
+
+/**
+ * BFI_FCPORT_H2I_ENABLE_REQ
+ */
+struct bfi_fcport_enable_req_s {
+ struct bfi_mhdr_s mh; /* msg header */
+ u32 rsvd1;
+ wwn_t nwwn; /* node wwn of physical port */
+ wwn_t pwwn; /* port wwn of physical port */
+ struct bfa_port_cfg_s port_cfg; /* port configuration */
+ union bfi_addr_u stats_dma_addr; /* DMA address for stats */
+ u32 msgtag; /* msgtag for reply */
+ u32 rsvd2;
+};
+
+/**
+ * BFI_FCPORT_H2I_SET_SVC_PARAMS_REQ
+ */
+struct bfi_fcport_set_svc_params_req_s {
+ struct bfi_mhdr_s mh; /* msg header */
+ u16 tx_bbcredit; /* Tx credits */
+ u16 rsvd;
+};
+
+/**
+ * BFI_FCPORT_I2H_EVENT
+ */
+struct bfi_fcport_event_s {
+ struct bfi_mhdr_s mh; /* common msg header */
+ struct bfa_port_link_s link_state;
+};
+
+/**
+ * BFI_FCPORT_I2H_TRUNK_SCN
+ */
+struct bfi_fcport_trunk_link_s {
+ wwn_t trunk_wwn;
+ u8 fctl; /* bfa_trunk_link_fctl_t */
+ u8 state; /* bfa_trunk_link_state_t */
+ u8 speed; /* bfa_port_speed_t */
+ u8 rsvd;
+ u32 deskew;
+};
+
+#define BFI_FCPORT_MAX_LINKS 2
+struct bfi_fcport_trunk_scn_s {
+ struct bfi_mhdr_s mh;
+ u8 trunk_state; /* bfa_trunk_state_t */
+ u8 trunk_speed; /* bfa_port_speed_t */
+ u8 rsvd_a[2];
+ struct bfi_fcport_trunk_link_s tlink[BFI_FCPORT_MAX_LINKS];
+};
+
+/**
+ * fcport H2I message
+ */
+union bfi_fcport_h2i_msg_u {
+ struct bfi_mhdr_s *mhdr;
+ struct bfi_fcport_enable_req_s *penable;
+ struct bfi_fcport_req_s *pdisable;
+ struct bfi_fcport_set_svc_params_req_s *psetsvcparams;
+ struct bfi_fcport_req_s *pstatsget;
+ struct bfi_fcport_req_s *pstatsclear;
+};
+
+/**
+ * fcport I2H message
+ */
+union bfi_fcport_i2h_msg_u {
+ struct bfi_msg_s *msg;
+ struct bfi_fcport_rsp_s *penable_rsp;
+ struct bfi_fcport_rsp_s *pdisable_rsp;
+ struct bfi_fcport_rsp_s *psetsvcparams_rsp;
+ struct bfi_fcport_rsp_s *pstatsget_rsp;
+ struct bfi_fcport_rsp_s *pstatsclear_rsp;
+ struct bfi_fcport_event_s *event;
+ struct bfi_fcport_trunk_scn_s *trunk_scn;
+};
+
+enum bfi_fcxp_h2i {
+ BFI_FCXP_H2I_SEND_REQ = 1,
+};
+
+enum bfi_fcxp_i2h {
+ BFI_FCXP_I2H_SEND_RSP = BFA_I2HM(1),
+};
+
+#define BFA_FCXP_MAX_SGES 2
+
+/**
+ * FCXP send request structure
+ */
+struct bfi_fcxp_send_req_s {
+ struct bfi_mhdr_s mh; /* Common msg header */
+ u16 fcxp_tag; /* driver request tag */
+ u16 max_frmsz; /* max send frame size */
+ u16 vf_id; /* vsan tag if applicable */
+ u16 rport_fw_hndl; /* FW Handle for the remote port */
+ u8 class; /* FC class used for req/rsp */
+ u8 rsp_timeout; /* timeout in secs, 0-no response */
+ u8 cts; /* continue sequence */
+ u8 lp_tag; /* lport tag */
+ struct fchs_s fchs; /* request FC header structure */
+ u32 req_len; /* request payload length */
+ u32 rsp_maxlen; /* max response length expected */
+ struct bfi_sge_s req_sge[BFA_FCXP_MAX_SGES]; /* request buf */
+ struct bfi_sge_s rsp_sge[BFA_FCXP_MAX_SGES]; /* response buf */
+};
+
+/**
+ * FCXP send response structure
+ */
+struct bfi_fcxp_send_rsp_s {
+ struct bfi_mhdr_s mh; /* Common msg header */
+ u16 fcxp_tag; /* send request tag */
+ u8 req_status; /* request status */
+ u8 rsvd;
+ u32 rsp_len; /* actual response length */
+ u32 residue_len; /* residual response length */
+ struct fchs_s fchs; /* response FC header structure */
+};
+
+enum bfi_uf_h2i {
+ BFI_UF_H2I_BUF_POST = 1,
+};
+
+enum bfi_uf_i2h {
+ BFI_UF_I2H_FRM_RCVD = BFA_I2HM(1),
+};
+
+#define BFA_UF_MAX_SGES 2
+
+struct bfi_uf_buf_post_s {
+ struct bfi_mhdr_s mh; /* Common msg header */
+ u16 buf_tag; /* buffer tag */
+ u16 buf_len; /* total buffer length */
+ struct bfi_sge_s sge[BFA_UF_MAX_SGES]; /* buffer DMA SGEs */
+};
+
+struct bfi_uf_frm_rcvd_s {
+ struct bfi_mhdr_s mh; /* Common msg header */
+ u16 buf_tag; /* buffer tag */
+ u16 rsvd;
+ u16 frm_len; /* received frame length */
+ u16 xfr_len; /* tranferred length */
+};
+
+enum bfi_lps_h2i_msgs {
+ BFI_LPS_H2I_LOGIN_REQ = 1,
+ BFI_LPS_H2I_LOGOUT_REQ = 2,
+};
+
+enum bfi_lps_i2h_msgs {
+ BFI_LPS_H2I_LOGIN_RSP = BFA_I2HM(1),
+ BFI_LPS_H2I_LOGOUT_RSP = BFA_I2HM(2),
+ BFI_LPS_H2I_CVL_EVENT = BFA_I2HM(3),
+};
+
+struct bfi_lps_login_req_s {
+ struct bfi_mhdr_s mh; /* common msg header */
+ u8 lp_tag;
+ u8 alpa;
+ u16 pdu_size;
+ wwn_t pwwn;
+ wwn_t nwwn;
+ u8 fdisc;
+ u8 auth_en;
+ u8 rsvd[2];
+};
+
+struct bfi_lps_login_rsp_s {
+ struct bfi_mhdr_s mh; /* common msg header */
+ u8 lp_tag;
+ u8 status;
+ u8 lsrjt_rsn;
+ u8 lsrjt_expl;
+ wwn_t port_name;
+ wwn_t node_name;
+ u16 bb_credit;
+ u8 f_port;
+ u8 npiv_en;
+ u32 lp_pid:24;
+ u32 auth_req:8;
+ mac_t lp_mac;
+ mac_t fcf_mac;
+ u8 ext_status;
+ u8 brcd_switch; /* attached peer is brcd switch */
+};
+
+struct bfi_lps_logout_req_s {
+ struct bfi_mhdr_s mh; /* common msg header */
+ u8 lp_tag;
+ u8 rsvd[3];
+ wwn_t port_name;
+};
+
+struct bfi_lps_logout_rsp_s {
+ struct bfi_mhdr_s mh; /* common msg header */
+ u8 lp_tag;
+ u8 status;
+ u8 rsvd[2];
+};
+
+struct bfi_lps_cvl_event_s {
+ struct bfi_mhdr_s mh; /* common msg header */
+ u8 lp_tag;
+ u8 rsvd[3];
+};
+
+union bfi_lps_h2i_msg_u {
+ struct bfi_mhdr_s *msg;
+ struct bfi_lps_login_req_s *login_req;
+ struct bfi_lps_logout_req_s *logout_req;
+};
+
+union bfi_lps_i2h_msg_u {
+ struct bfi_msg_s *msg;
+ struct bfi_lps_login_rsp_s *login_rsp;
+ struct bfi_lps_logout_rsp_s *logout_rsp;
+ struct bfi_lps_cvl_event_s *cvl_event;
+};
+
+enum bfi_rport_h2i_msgs {
+ BFI_RPORT_H2I_CREATE_REQ = 1,
+ BFI_RPORT_H2I_DELETE_REQ = 2,
+ BFI_RPORT_H2I_SET_SPEED_REQ = 3,
+};
+
+enum bfi_rport_i2h_msgs {
+ BFI_RPORT_I2H_CREATE_RSP = BFA_I2HM(1),
+ BFI_RPORT_I2H_DELETE_RSP = BFA_I2HM(2),
+ BFI_RPORT_I2H_QOS_SCN = BFA_I2HM(3),
+};
+
+struct bfi_rport_create_req_s {
+ struct bfi_mhdr_s mh; /* common msg header */
+ u16 bfa_handle; /* host rport handle */
+ u16 max_frmsz; /* max rcv pdu size */
+ u32 pid:24, /* remote port ID */
+ lp_tag:8; /* local port tag */
+ u32 local_pid:24, /* local port ID */
+ cisc:8;
+ u8 fc_class; /* supported FC classes */
+ u8 vf_en; /* virtual fabric enable */
+ u16 vf_id; /* virtual fabric ID */
+};
+
+struct bfi_rport_create_rsp_s {
+ struct bfi_mhdr_s mh; /* common msg header */
+ u8 status; /* rport creation status */
+ u8 rsvd[3];
+ u16 bfa_handle; /* host rport handle */
+ u16 fw_handle; /* firmware rport handle */
+ struct bfa_rport_qos_attr_s qos_attr; /* QoS Attributes */
+};
+
+struct bfa_rport_speed_req_s {
+ struct bfi_mhdr_s mh; /* common msg header */
+ u16 fw_handle; /* firmware rport handle */
+ u8 speed; /* rport's speed via RPSC */
+ u8 rsvd;
+};
+
+struct bfi_rport_delete_req_s {
+ struct bfi_mhdr_s mh; /* common msg header */
+ u16 fw_handle; /* firmware rport handle */
+ u16 rsvd;
+};
+
+struct bfi_rport_delete_rsp_s {
+ struct bfi_mhdr_s mh; /* common msg header */
+ u16 bfa_handle; /* host rport handle */
+ u8 status; /* rport deletion status */
+ u8 rsvd;
+};
+
+struct bfi_rport_qos_scn_s {
+ struct bfi_mhdr_s mh; /* common msg header */
+ u16 bfa_handle; /* host rport handle */
+ u16 rsvd;
+ struct bfa_rport_qos_attr_s old_qos_attr; /* Old QoS Attributes */
+ struct bfa_rport_qos_attr_s new_qos_attr; /* New QoS Attributes */
+};
+
+union bfi_rport_h2i_msg_u {
+ struct bfi_msg_s *msg;
+ struct bfi_rport_create_req_s *create_req;
+ struct bfi_rport_delete_req_s *delete_req;
+ struct bfi_rport_speed_req_s *speed_req;
+};
+
+union bfi_rport_i2h_msg_u {
+ struct bfi_msg_s *msg;
+ struct bfi_rport_create_rsp_s *create_rsp;
+ struct bfi_rport_delete_rsp_s *delete_rsp;
+ struct bfi_rport_qos_scn_s *qos_scn_evt;
+};
+
+/*
+ * Initiator mode I-T nexus interface defines.
+ */
+
+enum bfi_itnim_h2i {
+ BFI_ITNIM_H2I_CREATE_REQ = 1, /* i-t nexus creation */
+ BFI_ITNIM_H2I_DELETE_REQ = 2, /* i-t nexus deletion */
+};
+
+enum bfi_itnim_i2h {
+ BFI_ITNIM_I2H_CREATE_RSP = BFA_I2HM(1),
+ BFI_ITNIM_I2H_DELETE_RSP = BFA_I2HM(2),
+ BFI_ITNIM_I2H_SLER_EVENT = BFA_I2HM(3),
+};
+
+struct bfi_itnim_create_req_s {
+ struct bfi_mhdr_s mh; /* common msg header */
+ u16 fw_handle; /* f/w handle for itnim */
+ u8 class; /* FC class for IO */
+ u8 seq_rec; /* sequence recovery support */
+ u8 msg_no; /* seq id of the msg */
+};
+
+struct bfi_itnim_create_rsp_s {
+ struct bfi_mhdr_s mh; /* common msg header */
+ u16 bfa_handle; /* bfa handle for itnim */
+ u8 status; /* fcp request status */
+ u8 seq_id; /* seq id of the msg */
+};
+
+struct bfi_itnim_delete_req_s {
+ struct bfi_mhdr_s mh; /* common msg header */
+ u16 fw_handle; /* f/w itnim handle */
+ u8 seq_id; /* seq id of the msg */
+ u8 rsvd;
+};
+
+struct bfi_itnim_delete_rsp_s {
+ struct bfi_mhdr_s mh; /* common msg header */
+ u16 bfa_handle; /* bfa handle for itnim */
+ u8 status; /* fcp request status */
+ u8 seq_id; /* seq id of the msg */
+};
+
+struct bfi_itnim_sler_event_s {
+ struct bfi_mhdr_s mh; /* common msg header */
+ u16 bfa_handle; /* bfa handle for itnim */
+ u16 rsvd;
+};
+
+union bfi_itnim_h2i_msg_u {
+ struct bfi_itnim_create_req_s *create_req;
+ struct bfi_itnim_delete_req_s *delete_req;
+ struct bfi_msg_s *msg;
+};
+
+union bfi_itnim_i2h_msg_u {
+ struct bfi_itnim_create_rsp_s *create_rsp;
+ struct bfi_itnim_delete_rsp_s *delete_rsp;
+ struct bfi_itnim_sler_event_s *sler_event;
+ struct bfi_msg_s *msg;
+};
+
+/*
+ * Initiator mode IO interface defines.
+ */
+
+enum bfi_ioim_h2i {
+ BFI_IOIM_H2I_IOABORT_REQ = 1, /* IO abort request */
+ BFI_IOIM_H2I_IOCLEANUP_REQ = 2, /* IO cleanup request */
+};
+
+enum bfi_ioim_i2h {
+ BFI_IOIM_I2H_IO_RSP = BFA_I2HM(1), /* non-fp IO response */
+ BFI_IOIM_I2H_IOABORT_RSP = BFA_I2HM(2), /* ABORT rsp */
+};
+
+/**
+ * IO command DIF info
+ */
+struct bfi_ioim_dif_s {
+ u32 dif_info[4];
+};
+
+/**
+ * FCP IO messages overview
+ *
+ * @note
+ * - Max CDB length supported is 64 bytes.
+ * - SCSI Linked commands and SCSI bi-directional Commands not
+ * supported.
+ *
+ */
+struct bfi_ioim_req_s {
+ struct bfi_mhdr_s mh; /* Common msg header */
+ u16 io_tag; /* I/O tag */
+ u16 rport_hdl; /* itnim/rport firmware handle */
+ struct fcp_cmnd_s cmnd; /* IO request info */
+
+ /**
+ * SG elements array within the IO request must be double word
+ * aligned. This aligment is required to optimize SGM setup for the IO.
+ */
+ struct bfi_sge_s sges[BFI_SGE_INLINE_MAX];
+ u8 io_timeout;
+ u8 dif_en;
+ u8 rsvd_a[2];
+ struct bfi_ioim_dif_s dif;
+};
+
+/**
+ * This table shows various IO status codes from firmware and their
+ * meaning. Host driver can use these status codes to further process
+ * IO completions.
+ *
+ * BFI_IOIM_STS_OK : IO completed with error free SCSI &
+ * transport status.
+ * io-tag can be reused.
+ *
+ * BFA_IOIM_STS_SCSI_ERR : IO completed with scsi error.
+ * - io-tag can be reused.
+ *
+ * BFI_IOIM_STS_HOST_ABORTED : IO was aborted successfully due to
+ * host request.
+ * - io-tag cannot be reused yet.
+ *
+ * BFI_IOIM_STS_ABORTED : IO was aborted successfully
+ * internally by f/w.
+ * - io-tag cannot be reused yet.
+ *
+ * BFI_IOIM_STS_TIMEDOUT : IO timedout and ABTS/RRQ is happening
+ * in the firmware and
+ * - io-tag cannot be reused yet.
+ *
+ * BFI_IOIM_STS_SQER_NEEDED : Firmware could not recover the IO
+ * with sequence level error
+ * logic and hence host needs to retry
+ * this IO with a different IO tag
+ * - io-tag cannot be used yet.
+ *
+ * BFI_IOIM_STS_NEXUS_ABORT : Second Level Error Recovery from host
+ * is required because 2 consecutive ABTS
+ * timedout and host needs logout and
+ * re-login with the target
+ * - io-tag cannot be used yet.
+ *
+ * BFI_IOIM_STS_UNDERRUN : IO completed with SCSI status good,
+ * but the data tranferred is less than
+ * the fcp data length in the command.
+ * ex. SCSI INQUIRY where transferred
+ * data length and residue count in FCP
+ * response accounts for total fcp-dl
+ * - io-tag can be reused.
+ *
+ * BFI_IOIM_STS_OVERRUN : IO completed with SCSI status good,
+ * but the data transerred is more than
+ * fcp data length in the command. ex.
+ * TAPE IOs where blocks can of unequal
+ * lengths.
+ * - io-tag can be reused.
+ *
+ * BFI_IOIM_STS_RES_FREE : Firmware has completed using io-tag
+ * during abort process
+ * - io-tag can be reused.
+ *
+ * BFI_IOIM_STS_PROTO_ERR : Firmware detected a protocol error.
+ * ex target sent more data than
+ * requested, or there was data frame
+ * loss and other reasons
+ * - io-tag cannot be used yet.
+ *
+ * BFI_IOIM_STS_DIF_ERR : Firwmare detected DIF error. ex: DIF
+ * CRC err or Ref Tag err or App tag err.
+ * - io-tag can be reused.
+ *
+ * BFA_IOIM_STS_TSK_MGT_ABORT : IO was aborted because of Task
+ * Management command from the host
+ * - io-tag can be reused.
+ *
+ * BFI_IOIM_STS_UTAG : Firmware does not know about this
+ * io_tag.
+ * - io-tag can be reused.
+ */
+enum bfi_ioim_status {
+ BFI_IOIM_STS_OK = 0,
+ BFI_IOIM_STS_HOST_ABORTED = 1,
+ BFI_IOIM_STS_ABORTED = 2,
+ BFI_IOIM_STS_TIMEDOUT = 3,
+ BFI_IOIM_STS_RES_FREE = 4,
+ BFI_IOIM_STS_SQER_NEEDED = 5,
+ BFI_IOIM_STS_PROTO_ERR = 6,
+ BFI_IOIM_STS_UTAG = 7,
+ BFI_IOIM_STS_PATHTOV = 8,
+};
+
+#define BFI_IOIM_SNSLEN (256)
+/**
+ * I/O response message
+ */
+struct bfi_ioim_rsp_s {
+ struct bfi_mhdr_s mh; /* common msg header */
+ u16 io_tag; /* completed IO tag */
+ u16 bfa_rport_hndl; /* releated rport handle */
+ u8 io_status; /* IO completion status */
+ u8 reuse_io_tag; /* IO tag can be reused */
+ u16 abort_tag; /* host abort request tag */
+ u8 scsi_status; /* scsi status from target */
+ u8 sns_len; /* scsi sense length */
+ u8 resid_flags; /* IO residue flags */
+ u8 rsvd_a;
+ u32 residue; /* IO residual length in bytes */
+ u32 rsvd_b[3];
+};
+
+struct bfi_ioim_abort_req_s {
+ struct bfi_mhdr_s mh; /* Common msg header */
+ u16 io_tag; /* I/O tag */
+ u16 abort_tag; /* unique request tag */
+};
+
+/*
+ * Initiator mode task management command interface defines.
+ */
+
+enum bfi_tskim_h2i {
+ BFI_TSKIM_H2I_TM_REQ = 1, /* task-mgmt command */
+ BFI_TSKIM_H2I_ABORT_REQ = 2, /* task-mgmt command */
+};
+
+enum bfi_tskim_i2h {
+ BFI_TSKIM_I2H_TM_RSP = BFA_I2HM(1),
+};
+
+struct bfi_tskim_req_s {
+ struct bfi_mhdr_s mh; /* Common msg header */
+ u16 tsk_tag; /* task management tag */
+ u16 itn_fhdl; /* itn firmware handle */
+ lun_t lun; /* LU number */
+ u8 tm_flags; /* see enum fcp_tm_cmnd */
+ u8 t_secs; /* Timeout value in seconds */
+ u8 rsvd[2];
+};
+
+struct bfi_tskim_abortreq_s {
+ struct bfi_mhdr_s mh; /* Common msg header */
+ u16 tsk_tag; /* task management tag */
+ u16 rsvd;
+};
+
+enum bfi_tskim_status {
+ /*
+ * Following are FCP-4 spec defined status codes,
+ * **DO NOT CHANGE THEM **
+ */
+ BFI_TSKIM_STS_OK = 0,
+ BFI_TSKIM_STS_NOT_SUPP = 4,
+ BFI_TSKIM_STS_FAILED = 5,
+
+ /**
+ * Defined by BFA
+ */
+ BFI_TSKIM_STS_TIMEOUT = 10, /* TM request timedout */
+ BFI_TSKIM_STS_ABORTED = 11, /* Aborted on host request */
+};
+
+struct bfi_tskim_rsp_s {
+ struct bfi_mhdr_s mh; /* Common msg header */
+ u16 tsk_tag; /* task mgmt cmnd tag */
+ u8 tsk_status; /* @ref bfi_tskim_status */
+ u8 rsvd;
+};
+
+#pragma pack()
+
+#endif /* __BFI_MS_H__ */
diff --git a/drivers/scsi/bfa/fab.c b/drivers/scsi/bfa/fab.c
deleted file mode 100644
index 7e3a4d5d7bb4..000000000000
--- a/drivers/scsi/bfa/fab.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#include <bfa.h>
-#include <bfa_svc.h>
-#include "fcs_lport.h"
-#include "fcs_rport.h"
-#include "lport_priv.h"
-
-/**
- * fab.c port fab implementation.
- */
-
-/**
- * bfa_fcs_port_fab_public port fab public functions
- */
-
-/**
- * Called by port to initialize fabric services of the base port.
- */
-void
-bfa_fcs_port_fab_init(struct bfa_fcs_port_s *port)
-{
- bfa_fcs_port_ns_init(port);
- bfa_fcs_port_scn_init(port);
- bfa_fcs_port_ms_init(port);
-}
-
-/**
- * Called by port to notify transition to online state.
- */
-void
-bfa_fcs_port_fab_online(struct bfa_fcs_port_s *port)
-{
- bfa_fcs_port_ns_online(port);
- bfa_fcs_port_scn_online(port);
-}
-
-/**
- * Called by port to notify transition to offline state.
- */
-void
-bfa_fcs_port_fab_offline(struct bfa_fcs_port_s *port)
-{
- bfa_fcs_port_ns_offline(port);
- bfa_fcs_port_scn_offline(port);
- bfa_fcs_port_ms_offline(port);
-}
diff --git a/drivers/scsi/bfa/fabric.c b/drivers/scsi/bfa/fabric.c
deleted file mode 100644
index ddd4ba9317e6..000000000000
--- a/drivers/scsi/bfa/fabric.c
+++ /dev/null
@@ -1,1323 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/**
- * fabric.c Fabric module implementation.
- */
-
-#include "fcs_fabric.h"
-#include "fcs_lport.h"
-#include "fcs_vport.h"
-#include "fcs_trcmod.h"
-#include "fcs_fcxp.h"
-#include "fcs_auth.h"
-#include "fcs.h"
-#include "fcbuild.h"
-#include <log/bfa_log_fcs.h>
-#include <aen/bfa_aen_port.h>
-#include <bfa_svc.h>
-
-BFA_TRC_FILE(FCS, FABRIC);
-
-#define BFA_FCS_FABRIC_RETRY_DELAY (2000) /* Milliseconds */
-#define BFA_FCS_FABRIC_CLEANUP_DELAY (10000) /* Milliseconds */
-
-#define bfa_fcs_fabric_set_opertype(__fabric) do { \
- if (bfa_fcport_get_topology((__fabric)->fcs->bfa) \
- == BFA_PPORT_TOPOLOGY_P2P) \
- (__fabric)->oper_type = BFA_PPORT_TYPE_NPORT; \
- else \
- (__fabric)->oper_type = BFA_PPORT_TYPE_NLPORT; \
-} while (0)
-
-/*
- * forward declarations
- */
-static void bfa_fcs_fabric_init(struct bfa_fcs_fabric_s *fabric);
-static void bfa_fcs_fabric_login(struct bfa_fcs_fabric_s *fabric);
-static void bfa_fcs_fabric_notify_online(struct bfa_fcs_fabric_s *fabric);
-static void bfa_fcs_fabric_notify_offline(struct bfa_fcs_fabric_s *fabric);
-static void bfa_fcs_fabric_delay(void *cbarg);
-static void bfa_fcs_fabric_delete(struct bfa_fcs_fabric_s *fabric);
-static void bfa_fcs_fabric_delete_comp(void *cbarg);
-static void bfa_fcs_fabric_process_uf(struct bfa_fcs_fabric_s *fabric,
- struct fchs_s *fchs, u16 len);
-static void bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s *fabric,
- struct fchs_s *fchs, u16 len);
-static void bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric);
-static void bfa_fcs_fabric_flogiacc_comp(void *fcsarg,
- struct bfa_fcxp_s *fcxp,
- void *cbarg, bfa_status_t status,
- u32 rsp_len,
- u32 resid_len,
- struct fchs_s *rspfchs);
-/**
- * fcs_fabric_sm fabric state machine functions
- */
-
-/**
- * Fabric state machine events
- */
-enum bfa_fcs_fabric_event {
- BFA_FCS_FABRIC_SM_CREATE = 1, /* fabric create from driver */
- BFA_FCS_FABRIC_SM_DELETE = 2, /* fabric delete from driver */
- BFA_FCS_FABRIC_SM_LINK_DOWN = 3, /* link down from port */
- BFA_FCS_FABRIC_SM_LINK_UP = 4, /* link up from port */
- BFA_FCS_FABRIC_SM_CONT_OP = 5, /* continue op from flogi/auth */
- BFA_FCS_FABRIC_SM_RETRY_OP = 6, /* continue op from flogi/auth */
- BFA_FCS_FABRIC_SM_NO_FABRIC = 7, /* no fabric from flogi/auth
- */
- BFA_FCS_FABRIC_SM_PERF_EVFP = 8, /* perform EVFP from
- *flogi/auth */
- BFA_FCS_FABRIC_SM_ISOLATE = 9, /* isolate from EVFP processing */
- BFA_FCS_FABRIC_SM_NO_TAGGING = 10,/* no VFT tagging from EVFP */
- BFA_FCS_FABRIC_SM_DELAYED = 11, /* timeout delay event */
- BFA_FCS_FABRIC_SM_AUTH_FAILED = 12, /* authentication failed */
- BFA_FCS_FABRIC_SM_AUTH_SUCCESS = 13, /* authentication successful
- */
- BFA_FCS_FABRIC_SM_DELCOMP = 14, /* all vports deleted event */
- BFA_FCS_FABRIC_SM_LOOPBACK = 15, /* Received our own FLOGI */
- BFA_FCS_FABRIC_SM_START = 16, /* fabric delete from driver */
-};
-
-static void bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s *fabric,
- enum bfa_fcs_fabric_event event);
-static void bfa_fcs_fabric_sm_created(struct bfa_fcs_fabric_s *fabric,
- enum bfa_fcs_fabric_event event);
-static void bfa_fcs_fabric_sm_linkdown(struct bfa_fcs_fabric_s *fabric,
- enum bfa_fcs_fabric_event event);
-static void bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric,
- enum bfa_fcs_fabric_event event);
-static void bfa_fcs_fabric_sm_flogi_retry(struct bfa_fcs_fabric_s *fabric,
- enum bfa_fcs_fabric_event event);
-static void bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s *fabric,
- enum bfa_fcs_fabric_event event);
-static void bfa_fcs_fabric_sm_auth_failed(struct bfa_fcs_fabric_s *fabric,
- enum bfa_fcs_fabric_event event);
-static void bfa_fcs_fabric_sm_loopback(struct bfa_fcs_fabric_s *fabric,
- enum bfa_fcs_fabric_event event);
-static void bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric,
- enum bfa_fcs_fabric_event event);
-static void bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric,
- enum bfa_fcs_fabric_event event);
-static void bfa_fcs_fabric_sm_evfp(struct bfa_fcs_fabric_s *fabric,
- enum bfa_fcs_fabric_event event);
-static void bfa_fcs_fabric_sm_evfp_done(struct bfa_fcs_fabric_s *fabric,
- enum bfa_fcs_fabric_event event);
-static void bfa_fcs_fabric_sm_isolated(struct bfa_fcs_fabric_s *fabric,
- enum bfa_fcs_fabric_event event);
-static void bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s *fabric,
- enum bfa_fcs_fabric_event event);
-/**
- * Beginning state before fabric creation.
- */
-static void
-bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s *fabric,
- enum bfa_fcs_fabric_event event)
-{
- bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
- bfa_trc(fabric->fcs, event);
-
- switch (event) {
- case BFA_FCS_FABRIC_SM_CREATE:
- bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_created);
- bfa_fcs_fabric_init(fabric);
- bfa_fcs_lport_init(&fabric->bport, &fabric->bport.port_cfg);
- break;
-
- case BFA_FCS_FABRIC_SM_LINK_UP:
- case BFA_FCS_FABRIC_SM_LINK_DOWN:
- break;
-
- default:
- bfa_sm_fault(fabric->fcs, event);
- }
-}
-
-/**
- * Beginning state before fabric creation.
- */
-static void
-bfa_fcs_fabric_sm_created(struct bfa_fcs_fabric_s *fabric,
- enum bfa_fcs_fabric_event event)
-{
- bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
- bfa_trc(fabric->fcs, event);
-
- switch (event) {
- case BFA_FCS_FABRIC_SM_START:
- if (bfa_fcport_is_linkup(fabric->fcs->bfa)) {
- bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);
- bfa_fcs_fabric_login(fabric);
- } else
- bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
- break;
-
- case BFA_FCS_FABRIC_SM_LINK_UP:
- case BFA_FCS_FABRIC_SM_LINK_DOWN:
- break;
-
- case BFA_FCS_FABRIC_SM_DELETE:
- bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit);
- bfa_fcs_modexit_comp(fabric->fcs);
- break;
-
- default:
- bfa_sm_fault(fabric->fcs, event);
- }
-}
-
-/**
- * Link is down, awaiting LINK UP event from port. This is also the
- * first state at fabric creation.
- */
-static void
-bfa_fcs_fabric_sm_linkdown(struct bfa_fcs_fabric_s *fabric,
- enum bfa_fcs_fabric_event event)
-{
- bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
- bfa_trc(fabric->fcs, event);
-
- switch (event) {
- case BFA_FCS_FABRIC_SM_LINK_UP:
- bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);
- bfa_fcs_fabric_login(fabric);
- break;
-
- case BFA_FCS_FABRIC_SM_RETRY_OP:
- break;
-
- case BFA_FCS_FABRIC_SM_DELETE:
- bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
- bfa_fcs_fabric_delete(fabric);
- break;
-
- default:
- bfa_sm_fault(fabric->fcs, event);
- }
-}
-
-/**
- * FLOGI is in progress, awaiting FLOGI reply.
- */
-static void
-bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric,
- enum bfa_fcs_fabric_event event)
-{
- bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
- bfa_trc(fabric->fcs, event);
-
- switch (event) {
- case BFA_FCS_FABRIC_SM_CONT_OP:
-
- bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa, fabric->bb_credit);
- fabric->fab_type = BFA_FCS_FABRIC_SWITCHED;
-
- if (fabric->auth_reqd && fabric->is_auth) {
- bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth);
- bfa_trc(fabric->fcs, event);
- } else {
- bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_online);
- bfa_fcs_fabric_notify_online(fabric);
- }
- break;
-
- case BFA_FCS_FABRIC_SM_RETRY_OP:
- bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi_retry);
- bfa_timer_start(fabric->fcs->bfa, &fabric->delay_timer,
- bfa_fcs_fabric_delay, fabric,
- BFA_FCS_FABRIC_RETRY_DELAY);
- break;
-
- case BFA_FCS_FABRIC_SM_LOOPBACK:
- bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_loopback);
- bfa_lps_discard(fabric->lps);
- bfa_fcs_fabric_set_opertype(fabric);
- break;
-
- case BFA_FCS_FABRIC_SM_NO_FABRIC:
- fabric->fab_type = BFA_FCS_FABRIC_N2N;
- bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa, fabric->bb_credit);
- bfa_fcs_fabric_notify_online(fabric);
- bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_nofabric);
- break;
-
- case BFA_FCS_FABRIC_SM_LINK_DOWN:
- bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
- bfa_lps_discard(fabric->lps);
- break;
-
- case BFA_FCS_FABRIC_SM_DELETE:
- bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
- bfa_lps_discard(fabric->lps);
- bfa_fcs_fabric_delete(fabric);
- break;
-
- default:
- bfa_sm_fault(fabric->fcs, event);
- }
-}
-
-
-static void
-bfa_fcs_fabric_sm_flogi_retry(struct bfa_fcs_fabric_s *fabric,
- enum bfa_fcs_fabric_event event)
-{
- bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
- bfa_trc(fabric->fcs, event);
-
- switch (event) {
- case BFA_FCS_FABRIC_SM_DELAYED:
- bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);
- bfa_fcs_fabric_login(fabric);
- break;
-
- case BFA_FCS_FABRIC_SM_LINK_DOWN:
- bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
- bfa_timer_stop(&fabric->delay_timer);
- break;
-
- case BFA_FCS_FABRIC_SM_DELETE:
- bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
- bfa_timer_stop(&fabric->delay_timer);
- bfa_fcs_fabric_delete(fabric);
- break;
-
- default:
- bfa_sm_fault(fabric->fcs, event);
- }
-}
-
-/**
- * Authentication is in progress, awaiting authentication results.
- */
-static void
-bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s *fabric,
- enum bfa_fcs_fabric_event event)
-{
- bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
- bfa_trc(fabric->fcs, event);
-
- switch (event) {
- case BFA_FCS_FABRIC_SM_AUTH_FAILED:
- bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth_failed);
- bfa_lps_discard(fabric->lps);
- break;
-
- case BFA_FCS_FABRIC_SM_AUTH_SUCCESS:
- bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_online);
- bfa_fcs_fabric_notify_online(fabric);
- break;
-
- case BFA_FCS_FABRIC_SM_PERF_EVFP:
- bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_evfp);
- break;
-
- case BFA_FCS_FABRIC_SM_LINK_DOWN:
- bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
- bfa_lps_discard(fabric->lps);
- break;
-
- case BFA_FCS_FABRIC_SM_DELETE:
- bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
- bfa_fcs_fabric_delete(fabric);
- break;
-
- default:
- bfa_sm_fault(fabric->fcs, event);
- }
-}
-
-/**
- * Authentication failed
- */
-static void
-bfa_fcs_fabric_sm_auth_failed(struct bfa_fcs_fabric_s *fabric,
- enum bfa_fcs_fabric_event event)
-{
- bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
- bfa_trc(fabric->fcs, event);
-
- switch (event) {
- case BFA_FCS_FABRIC_SM_LINK_DOWN:
- bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
- bfa_fcs_fabric_notify_offline(fabric);
- break;
-
- case BFA_FCS_FABRIC_SM_DELETE:
- bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
- bfa_fcs_fabric_delete(fabric);
- break;
-
- default:
- bfa_sm_fault(fabric->fcs, event);
- }
-}
-
-/**
- * Port is in loopback mode.
- */
-static void
-bfa_fcs_fabric_sm_loopback(struct bfa_fcs_fabric_s *fabric,
- enum bfa_fcs_fabric_event event)
-{
- bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
- bfa_trc(fabric->fcs, event);
-
- switch (event) {
- case BFA_FCS_FABRIC_SM_LINK_DOWN:
- bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
- bfa_fcs_fabric_notify_offline(fabric);
- break;
-
- case BFA_FCS_FABRIC_SM_DELETE:
- bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
- bfa_fcs_fabric_delete(fabric);
- break;
-
- default:
- bfa_sm_fault(fabric->fcs, event);
- }
-}
-
-/**
- * There is no attached fabric - private loop or NPort-to-NPort topology.
- */
-static void
-bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric,
- enum bfa_fcs_fabric_event event)
-{
- bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
- bfa_trc(fabric->fcs, event);
-
- switch (event) {
- case BFA_FCS_FABRIC_SM_LINK_DOWN:
- bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
- bfa_lps_discard(fabric->lps);
- bfa_fcs_fabric_notify_offline(fabric);
- break;
-
- case BFA_FCS_FABRIC_SM_DELETE:
- bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
- bfa_fcs_fabric_delete(fabric);
- break;
-
- case BFA_FCS_FABRIC_SM_NO_FABRIC:
- bfa_trc(fabric->fcs, fabric->bb_credit);
- bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa, fabric->bb_credit);
- break;
-
- default:
- bfa_sm_fault(fabric->fcs, event);
- }
-}
-
-/**
- * Fabric is online - normal operating state.
- */
-static void
-bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric,
- enum bfa_fcs_fabric_event event)
-{
- bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
- bfa_trc(fabric->fcs, event);
-
- switch (event) {
- case BFA_FCS_FABRIC_SM_LINK_DOWN:
- bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
- bfa_lps_discard(fabric->lps);
- bfa_fcs_fabric_notify_offline(fabric);
- break;
-
- case BFA_FCS_FABRIC_SM_DELETE:
- bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
- bfa_fcs_fabric_delete(fabric);
- break;
-
- case BFA_FCS_FABRIC_SM_AUTH_FAILED:
- bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth_failed);
- bfa_lps_discard(fabric->lps);
- break;
-
- case BFA_FCS_FABRIC_SM_AUTH_SUCCESS:
- break;
-
- default:
- bfa_sm_fault(fabric->fcs, event);
- }
-}
-
-/**
- * Exchanging virtual fabric parameters.
- */
-static void
-bfa_fcs_fabric_sm_evfp(struct bfa_fcs_fabric_s *fabric,
- enum bfa_fcs_fabric_event event)
-{
- bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
- bfa_trc(fabric->fcs, event);
-
- switch (event) {
- case BFA_FCS_FABRIC_SM_CONT_OP:
- bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_evfp_done);
- break;
-
- case BFA_FCS_FABRIC_SM_ISOLATE:
- bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_isolated);
- break;
-
- default:
- bfa_sm_fault(fabric->fcs, event);
- }
-}
-
-/**
- * EVFP exchange complete and VFT tagging is enabled.
- */
-static void
-bfa_fcs_fabric_sm_evfp_done(struct bfa_fcs_fabric_s *fabric,
- enum bfa_fcs_fabric_event event)
-{
- bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
- bfa_trc(fabric->fcs, event);
-}
-
-/**
- * Port is isolated after EVFP exchange due to VF_ID mismatch (N and F).
- */
-static void
-bfa_fcs_fabric_sm_isolated(struct bfa_fcs_fabric_s *fabric,
- enum bfa_fcs_fabric_event event)
-{
- bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
- bfa_trc(fabric->fcs, event);
-
- bfa_log(fabric->fcs->logm, BFA_LOG_FCS_FABRIC_ISOLATED,
- fabric->bport.port_cfg.pwwn, fabric->fcs->port_vfid,
- fabric->event_arg.swp_vfid);
-}
-
-/**
- * Fabric is being deleted, awaiting vport delete completions.
- */
-static void
-bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s *fabric,
- enum bfa_fcs_fabric_event event)
-{
- bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
- bfa_trc(fabric->fcs, event);
-
- switch (event) {
- case BFA_FCS_FABRIC_SM_DELCOMP:
- bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit);
- bfa_fcs_modexit_comp(fabric->fcs);
- break;
-
- case BFA_FCS_FABRIC_SM_LINK_UP:
- break;
-
- case BFA_FCS_FABRIC_SM_LINK_DOWN:
- bfa_fcs_fabric_notify_offline(fabric);
- break;
-
- default:
- bfa_sm_fault(fabric->fcs, event);
- }
-}
-
-
-
-/**
- * fcs_fabric_private fabric private functions
- */
-
-static void
-bfa_fcs_fabric_init(struct bfa_fcs_fabric_s *fabric)
-{
- struct bfa_port_cfg_s *port_cfg = &fabric->bport.port_cfg;
-
- port_cfg->roles = BFA_PORT_ROLE_FCP_IM;
- port_cfg->nwwn = bfa_ioc_get_nwwn(&fabric->fcs->bfa->ioc);
- port_cfg->pwwn = bfa_ioc_get_pwwn(&fabric->fcs->bfa->ioc);
-}
-
-/**
- * Port Symbolic Name Creation for base port.
- */
-void
-bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s *fabric)
-{
- struct bfa_port_cfg_s *port_cfg = &fabric->bport.port_cfg;
- char model[BFA_ADAPTER_MODEL_NAME_LEN] = {0};
- struct bfa_fcs_driver_info_s *driver_info = &fabric->fcs->driver_info;
-
- bfa_ioc_get_adapter_model(&fabric->fcs->bfa->ioc, model);
-
- /*
- * Model name/number
- */
- strncpy((char *)&port_cfg->sym_name, model,
- BFA_FCS_PORT_SYMBNAME_MODEL_SZ);
- strncat((char *)&port_cfg->sym_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
- sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
-
- /*
- * Driver Version
- */
- strncat((char *)&port_cfg->sym_name, (char *)driver_info->version,
- BFA_FCS_PORT_SYMBNAME_VERSION_SZ);
- strncat((char *)&port_cfg->sym_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
- sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
-
- /*
- * Host machine name
- */
- strncat((char *)&port_cfg->sym_name,
- (char *)driver_info->host_machine_name,
- BFA_FCS_PORT_SYMBNAME_MACHINENAME_SZ);
- strncat((char *)&port_cfg->sym_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
- sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
-
- /*
- * Host OS Info :
- * If OS Patch Info is not there, do not truncate any bytes from the
- * OS name string and instead copy the entire OS info string (64 bytes).
- */
- if (driver_info->host_os_patch[0] == '\0') {
- strncat((char *)&port_cfg->sym_name,
- (char *)driver_info->host_os_name, BFA_FCS_OS_STR_LEN);
- strncat((char *)&port_cfg->sym_name,
- BFA_FCS_PORT_SYMBNAME_SEPARATOR,
- sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
- } else {
- strncat((char *)&port_cfg->sym_name,
- (char *)driver_info->host_os_name,
- BFA_FCS_PORT_SYMBNAME_OSINFO_SZ);
- strncat((char *)&port_cfg->sym_name,
- BFA_FCS_PORT_SYMBNAME_SEPARATOR,
- sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
-
- /*
- * Append host OS Patch Info
- */
- strncat((char *)&port_cfg->sym_name,
- (char *)driver_info->host_os_patch,
- BFA_FCS_PORT_SYMBNAME_OSPATCH_SZ);
- }
-
- /*
- * null terminate
- */
- port_cfg->sym_name.symname[BFA_SYMNAME_MAXLEN - 1] = 0;
-}
-
-/**
- * bfa lps login completion callback
- */
-void
-bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status)
-{
- struct bfa_fcs_fabric_s *fabric = uarg;
-
- bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
- bfa_trc(fabric->fcs, status);
-
- switch (status) {
- case BFA_STATUS_OK:
- fabric->stats.flogi_accepts++;
- break;
-
- case BFA_STATUS_INVALID_MAC:
- /*
- * Only for CNA
- */
- fabric->stats.flogi_acc_err++;
- bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
-
- return;
-
- case BFA_STATUS_EPROTOCOL:
- switch (bfa_lps_get_extstatus(fabric->lps)) {
- case BFA_EPROTO_BAD_ACCEPT:
- fabric->stats.flogi_acc_err++;
- break;
-
- case BFA_EPROTO_UNKNOWN_RSP:
- fabric->stats.flogi_unknown_rsp++;
- break;
-
- default:
- break;
- }
- bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
-
- return;
-
- case BFA_STATUS_FABRIC_RJT:
- fabric->stats.flogi_rejects++;
- bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
- return;
-
- default:
- fabric->stats.flogi_rsp_err++;
- bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
- return;
- }
-
- fabric->bb_credit = bfa_lps_get_peer_bbcredit(fabric->lps);
- bfa_trc(fabric->fcs, fabric->bb_credit);
-
- if (!bfa_lps_is_brcd_fabric(fabric->lps))
- fabric->fabric_name = bfa_lps_get_peer_nwwn(fabric->lps);
-
- /*
- * Check port type. It should be 1 = F-port.
- */
- if (bfa_lps_is_fport(fabric->lps)) {
- fabric->bport.pid = bfa_lps_get_pid(fabric->lps);
- fabric->is_npiv = bfa_lps_is_npiv_en(fabric->lps);
- fabric->is_auth = bfa_lps_is_authreq(fabric->lps);
- bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_CONT_OP);
- } else {
- /*
- * Nport-2-Nport direct attached
- */
- fabric->bport.port_topo.pn2n.rem_port_wwn =
- bfa_lps_get_peer_pwwn(fabric->lps);
- bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_NO_FABRIC);
- }
-
- bfa_trc(fabric->fcs, fabric->bport.pid);
- bfa_trc(fabric->fcs, fabric->is_npiv);
- bfa_trc(fabric->fcs, fabric->is_auth);
-}
-
-/**
- * Allocate and send FLOGI.
- */
-static void
-bfa_fcs_fabric_login(struct bfa_fcs_fabric_s *fabric)
-{
- struct bfa_s *bfa = fabric->fcs->bfa;
- struct bfa_port_cfg_s *pcfg = &fabric->bport.port_cfg;
- u8 alpa = 0;
-
- if (bfa_fcport_get_topology(bfa) == BFA_PPORT_TOPOLOGY_LOOP)
- alpa = bfa_fcport_get_myalpa(bfa);
-
- bfa_lps_flogi(fabric->lps, fabric, alpa, bfa_fcport_get_maxfrsize(bfa),
- pcfg->pwwn, pcfg->nwwn, fabric->auth_reqd);
-
- fabric->stats.flogi_sent++;
-}
-
-static void
-bfa_fcs_fabric_notify_online(struct bfa_fcs_fabric_s *fabric)
-{
- struct bfa_fcs_vport_s *vport;
- struct list_head *qe, *qen;
-
- bfa_trc(fabric->fcs, fabric->fabric_name);
-
- bfa_fcs_fabric_set_opertype(fabric);
- fabric->stats.fabric_onlines++;
-
- /**
- * notify online event to base and then virtual ports
- */
- bfa_fcs_port_online(&fabric->bport);
-
- list_for_each_safe(qe, qen, &fabric->vport_q) {
- vport = (struct bfa_fcs_vport_s *)qe;
- bfa_fcs_vport_online(vport);
- }
-}
-
-static void
-bfa_fcs_fabric_notify_offline(struct bfa_fcs_fabric_s *fabric)
-{
- struct bfa_fcs_vport_s *vport;
- struct list_head *qe, *qen;
-
- bfa_trc(fabric->fcs, fabric->fabric_name);
- fabric->stats.fabric_offlines++;
-
- /**
- * notify offline event first to vports and then base port.
- */
- list_for_each_safe(qe, qen, &fabric->vport_q) {
- vport = (struct bfa_fcs_vport_s *)qe;
- bfa_fcs_vport_offline(vport);
- }
-
- bfa_fcs_port_offline(&fabric->bport);
-
- fabric->fabric_name = 0;
- fabric->fabric_ip_addr[0] = 0;
-}
-
-static void
-bfa_fcs_fabric_delay(void *cbarg)
-{
- struct bfa_fcs_fabric_s *fabric = cbarg;
-
- bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELAYED);
-}
-
-/**
- * Delete all vports and wait for vport delete completions.
- */
-static void
-bfa_fcs_fabric_delete(struct bfa_fcs_fabric_s *fabric)
-{
- struct bfa_fcs_vport_s *vport;
- struct list_head *qe, *qen;
-
- list_for_each_safe(qe, qen, &fabric->vport_q) {
- vport = (struct bfa_fcs_vport_s *)qe;
- bfa_fcs_vport_fcs_delete(vport);
- }
-
- bfa_fcs_port_delete(&fabric->bport);
- bfa_wc_wait(&fabric->wc);
-}
-
-static void
-bfa_fcs_fabric_delete_comp(void *cbarg)
-{
- struct bfa_fcs_fabric_s *fabric = cbarg;
-
- bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELCOMP);
-}
-
-
-
-/**
- * fcs_fabric_public fabric public functions
- */
-
-/**
- * Attach time initialization
- */
-void
-bfa_fcs_fabric_attach(struct bfa_fcs_s *fcs)
-{
- struct bfa_fcs_fabric_s *fabric;
-
- fabric = &fcs->fabric;
- bfa_os_memset(fabric, 0, sizeof(struct bfa_fcs_fabric_s));
-
- /**
- * Initialize base fabric.
- */
- fabric->fcs = fcs;
- INIT_LIST_HEAD(&fabric->vport_q);
- INIT_LIST_HEAD(&fabric->vf_q);
- fabric->lps = bfa_lps_alloc(fcs->bfa);
- bfa_assert(fabric->lps);
-
- /**
- * Initialize fabric delete completion handler. Fabric deletion is complete
- * when the last vport delete is complete.
- */
- bfa_wc_init(&fabric->wc, bfa_fcs_fabric_delete_comp, fabric);
- bfa_wc_up(&fabric->wc); /* For the base port */
-
- bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit);
- bfa_fcs_lport_attach(&fabric->bport, fabric->fcs, FC_VF_ID_NULL, NULL);
-}
-
-void
-bfa_fcs_fabric_modinit(struct bfa_fcs_s *fcs)
-{
- bfa_sm_send_event(&fcs->fabric, BFA_FCS_FABRIC_SM_CREATE);
- bfa_trc(fcs, 0);
-}
-
-/**
- * Module cleanup
- */
-void
-bfa_fcs_fabric_modexit(struct bfa_fcs_s *fcs)
-{
- struct bfa_fcs_fabric_s *fabric;
-
- bfa_trc(fcs, 0);
-
- /**
- * Cleanup base fabric.
- */
- fabric = &fcs->fabric;
- bfa_lps_delete(fabric->lps);
- bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELETE);
-}
-
-/**
- * Fabric module start -- kick starts FCS actions
- */
-void
-bfa_fcs_fabric_modstart(struct bfa_fcs_s *fcs)
-{
- struct bfa_fcs_fabric_s *fabric;
-
- bfa_trc(fcs, 0);
- fabric = &fcs->fabric;
- bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_START);
-}
-
-/**
- * Suspend fabric activity as part of driver suspend.
- */
-void
-bfa_fcs_fabric_modsusp(struct bfa_fcs_s *fcs)
-{
-}
-
-bfa_boolean_t
-bfa_fcs_fabric_is_loopback(struct bfa_fcs_fabric_s *fabric)
-{
- return bfa_sm_cmp_state(fabric, bfa_fcs_fabric_sm_loopback);
-}
-
-bfa_boolean_t
-bfa_fcs_fabric_is_auth_failed(struct bfa_fcs_fabric_s *fabric)
-{
- return bfa_sm_cmp_state(fabric, bfa_fcs_fabric_sm_auth_failed);
-}
-
-enum bfa_pport_type
-bfa_fcs_fabric_port_type(struct bfa_fcs_fabric_s *fabric)
-{
- return fabric->oper_type;
-}
-
-/**
- * Link up notification from BFA physical port module.
- */
-void
-bfa_fcs_fabric_link_up(struct bfa_fcs_fabric_s *fabric)
-{
- bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
- bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LINK_UP);
-}
-
-/**
- * Link down notification from BFA physical port module.
- */
-void
-bfa_fcs_fabric_link_down(struct bfa_fcs_fabric_s *fabric)
-{
- bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
- bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LINK_DOWN);
-}
-
-/**
- * A child vport is being created in the fabric.
- *
- * Call from vport module at vport creation. A list of base port and vports
- * belonging to a fabric is maintained to propagate link events.
- *
- * param[in] fabric - Fabric instance. This can be a base fabric or vf.
- * param[in] vport - Vport being created.
- *
- * @return None (always succeeds)
- */
-void
-bfa_fcs_fabric_addvport(struct bfa_fcs_fabric_s *fabric,
- struct bfa_fcs_vport_s *vport)
-{
- /**
- * - add vport to fabric's vport_q
- */
- bfa_trc(fabric->fcs, fabric->vf_id);
-
- list_add_tail(&vport->qe, &fabric->vport_q);
- fabric->num_vports++;
- bfa_wc_up(&fabric->wc);
-}
-
-/**
- * A child vport is being deleted from fabric.
- *
- * Vport is being deleted.
- */
-void
-bfa_fcs_fabric_delvport(struct bfa_fcs_fabric_s *fabric,
- struct bfa_fcs_vport_s *vport)
-{
- list_del(&vport->qe);
- fabric->num_vports--;
- bfa_wc_down(&fabric->wc);
-}
-
-/**
- * Base port is deleted.
- */
-void
-bfa_fcs_fabric_port_delete_comp(struct bfa_fcs_fabric_s *fabric)
-{
- bfa_wc_down(&fabric->wc);
-}
-
-/**
- * Check if fabric is online.
- *
- * param[in] fabric - Fabric instance. This can be a base fabric or vf.
- *
- * @return TRUE/FALSE
- */
-int
-bfa_fcs_fabric_is_online(struct bfa_fcs_fabric_s *fabric)
-{
- return bfa_sm_cmp_state(fabric, bfa_fcs_fabric_sm_online);
-}
-
-
-bfa_status_t
-bfa_fcs_fabric_addvf(struct bfa_fcs_fabric_s *vf, struct bfa_fcs_s *fcs,
- struct bfa_port_cfg_s *port_cfg,
- struct bfad_vf_s *vf_drv)
-{
- bfa_sm_set_state(vf, bfa_fcs_fabric_sm_uninit);
- return BFA_STATUS_OK;
-}
-
-/**
- * Lookup for a vport withing a fabric given its pwwn
- */
-struct bfa_fcs_vport_s *
-bfa_fcs_fabric_vport_lookup(struct bfa_fcs_fabric_s *fabric, wwn_t pwwn)
-{
- struct bfa_fcs_vport_s *vport;
- struct list_head *qe;
-
- list_for_each(qe, &fabric->vport_q) {
- vport = (struct bfa_fcs_vport_s *)qe;
- if (bfa_fcs_port_get_pwwn(&vport->lport) == pwwn)
- return vport;
- }
-
- return NULL;
-}
-
-/**
- * In a given fabric, return the number of lports.
- *
- * param[in] fabric - Fabric instance. This can be a base fabric or vf.
- *
-* @return : 1 or more.
- */
-u16
-bfa_fcs_fabric_vport_count(struct bfa_fcs_fabric_s *fabric)
-{
- return fabric->num_vports;
-}
-
-/*
- * Get OUI of the attached switch.
- *
- * Note : Use of this function should be avoided as much as possible.
- * This function should be used only if there is any requirement
- * to check for FOS version below 6.3.
- * To check if the attached fabric is a brocade fabric, use
- * bfa_lps_is_brcd_fabric() which works for FOS versions 6.3
- * or above only.
- */
-
-u16
-bfa_fcs_fabric_get_switch_oui(struct bfa_fcs_fabric_s *fabric)
-{
- wwn_t fab_nwwn;
- u8 *tmp;
- u16 oui;
-
- fab_nwwn = bfa_lps_get_peer_nwwn(fabric->lps);
-
- tmp = (uint8_t *)&fab_nwwn;
- oui = (tmp[3] << 8) | tmp[4];
-
- return oui;
-}
-
-/**
- * Unsolicited frame receive handling.
- */
-void
-bfa_fcs_fabric_uf_recv(struct bfa_fcs_fabric_s *fabric, struct fchs_s *fchs,
- u16 len)
-{
- u32 pid = fchs->d_id;
- struct bfa_fcs_vport_s *vport;
- struct list_head *qe;
- struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
- struct fc_logi_s *flogi = (struct fc_logi_s *) els_cmd;
-
- bfa_trc(fabric->fcs, len);
- bfa_trc(fabric->fcs, pid);
-
- /**
- * Look for our own FLOGI frames being looped back. This means an
- * external loopback cable is in place. Our own FLOGI frames are
- * sometimes looped back when switch port gets temporarily bypassed.
- */
- if ((pid == bfa_os_ntoh3b(FC_FABRIC_PORT))
- && (els_cmd->els_code == FC_ELS_FLOGI)
- && (flogi->port_name == bfa_fcs_port_get_pwwn(&fabric->bport))) {
- bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LOOPBACK);
- return;
- }
-
- /**
- * FLOGI/EVFP exchanges should be consumed by base fabric.
- */
- if (fchs->d_id == bfa_os_hton3b(FC_FABRIC_PORT)) {
- bfa_trc(fabric->fcs, pid);
- bfa_fcs_fabric_process_uf(fabric, fchs, len);
- return;
- }
-
- if (fabric->bport.pid == pid) {
- /**
- * All authentication frames should be routed to auth
- */
- bfa_trc(fabric->fcs, els_cmd->els_code);
- if (els_cmd->els_code == FC_ELS_AUTH) {
- bfa_trc(fabric->fcs, els_cmd->els_code);
- fabric->auth.response = (u8 *) els_cmd;
- return;
- }
-
- bfa_trc(fabric->fcs, *(u8 *) ((u8 *) fchs));
- bfa_fcs_port_uf_recv(&fabric->bport, fchs, len);
- return;
- }
-
- /**
- * look for a matching local port ID
- */
- list_for_each(qe, &fabric->vport_q) {
- vport = (struct bfa_fcs_vport_s *)qe;
- if (vport->lport.pid == pid) {
- bfa_fcs_port_uf_recv(&vport->lport, fchs, len);
- return;
- }
- }
- bfa_trc(fabric->fcs, els_cmd->els_code);
- bfa_fcs_port_uf_recv(&fabric->bport, fchs, len);
-}
-
-/**
- * Unsolicited frames to be processed by fabric.
- */
-static void
-bfa_fcs_fabric_process_uf(struct bfa_fcs_fabric_s *fabric, struct fchs_s *fchs,
- u16 len)
-{
- struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
-
- bfa_trc(fabric->fcs, els_cmd->els_code);
-
- switch (els_cmd->els_code) {
- case FC_ELS_FLOGI:
- bfa_fcs_fabric_process_flogi(fabric, fchs, len);
- break;
-
- default:
- /*
- * need to generate a LS_RJT
- */
- break;
- }
-}
-
-/**
- * Process incoming FLOGI
- */
-static void
-bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s *fabric,
- struct fchs_s *fchs, u16 len)
-{
- struct fc_logi_s *flogi = (struct fc_logi_s *) (fchs + 1);
- struct bfa_fcs_port_s *bport = &fabric->bport;
-
- bfa_trc(fabric->fcs, fchs->s_id);
-
- fabric->stats.flogi_rcvd++;
- /*
- * Check port type. It should be 0 = n-port.
- */
- if (flogi->csp.port_type) {
- /*
- * @todo: may need to send a LS_RJT
- */
- bfa_trc(fabric->fcs, flogi->port_name);
- fabric->stats.flogi_rejected++;
- return;
- }
-
- fabric->bb_credit = bfa_os_ntohs(flogi->csp.bbcred);
- bport->port_topo.pn2n.rem_port_wwn = flogi->port_name;
- bport->port_topo.pn2n.reply_oxid = fchs->ox_id;
-
- /*
- * Send a Flogi Acc
- */
- bfa_fcs_fabric_send_flogi_acc(fabric);
- bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_NO_FABRIC);
-}
-
-static void
-bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric)
-{
- struct bfa_port_cfg_s *pcfg = &fabric->bport.port_cfg;
- struct bfa_fcs_port_n2n_s *n2n_port = &fabric->bport.port_topo.pn2n;
- struct bfa_s *bfa = fabric->fcs->bfa;
- struct bfa_fcxp_s *fcxp;
- u16 reqlen;
- struct fchs_s fchs;
-
- fcxp = bfa_fcs_fcxp_alloc(fabric->fcs);
- /**
- * Do not expect this failure -- expect remote node to retry
- */
- if (!fcxp)
- return;
-
- reqlen = fc_flogi_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
- bfa_os_hton3b(FC_FABRIC_PORT),
- n2n_port->reply_oxid, pcfg->pwwn,
- pcfg->nwwn, bfa_fcport_get_maxfrsize(bfa),
- bfa_fcport_get_rx_bbcredit(bfa));
-
- bfa_fcxp_send(fcxp, NULL, fabric->vf_id, bfa_lps_get_tag(fabric->lps),
- BFA_FALSE, FC_CLASS_3, reqlen, &fchs,
- bfa_fcs_fabric_flogiacc_comp, fabric,
- FC_MAX_PDUSZ, 0); /* Timeout 0 indicates no
- * response expected
- */
-}
-
-/**
- * Flogi Acc completion callback.
- */
-static void
-bfa_fcs_fabric_flogiacc_comp(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
- bfa_status_t status, u32 rsp_len,
- u32 resid_len, struct fchs_s *rspfchs)
-{
- struct bfa_fcs_fabric_s *fabric = cbarg;
-
- bfa_trc(fabric->fcs, status);
-}
-
-/*
- *
- * @param[in] fabric - fabric
- * @param[in] result - 1
- *
- * @return - none
- */
-void
-bfa_fcs_auth_finished(struct bfa_fcs_fabric_s *fabric, enum auth_status status)
-{
- bfa_trc(fabric->fcs, status);
-
- if (status == FC_AUTH_STATE_SUCCESS)
- bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_AUTH_SUCCESS);
- else
- bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_AUTH_FAILED);
-}
-
-/**
- * Send AEN notification
- */
-static void
-bfa_fcs_fabric_aen_post(struct bfa_fcs_port_s *port,
- enum bfa_port_aen_event event)
-{
- union bfa_aen_data_u aen_data;
- struct bfa_log_mod_s *logmod = port->fcs->logm;
- wwn_t pwwn = bfa_fcs_port_get_pwwn(port);
- wwn_t fwwn = bfa_fcs_port_get_fabric_name(port);
- char pwwn_ptr[BFA_STRING_32];
- char fwwn_ptr[BFA_STRING_32];
-
- wwn2str(pwwn_ptr, pwwn);
- wwn2str(fwwn_ptr, fwwn);
-
- bfa_log(logmod, BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, event),
- pwwn_ptr, fwwn_ptr);
-
- aen_data.port.pwwn = pwwn;
- aen_data.port.fwwn = fwwn;
-}
-
-/*
- *
- * @param[in] fabric - fabric
- * @param[in] wwn_t - new fabric name
- *
- * @return - none
- */
-void
-bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric,
- wwn_t fabric_name)
-{
- bfa_trc(fabric->fcs, fabric_name);
-
- if (fabric->fabric_name == 0) {
- /*
- * With BRCD switches, we don't get Fabric Name in FLOGI.
- * Don't generate a fabric name change event in this case.
- */
- fabric->fabric_name = fabric_name;
- } else {
- fabric->fabric_name = fabric_name;
- /*
- * Generate a Event
- */
- bfa_fcs_fabric_aen_post(&fabric->bport,
- BFA_PORT_AEN_FABRIC_NAME_CHANGE);
- }
-
-}
-
-/**
- *
- * @param[in] fabric - fabric
- * @param[in] node_symname -
- * Caller allocated buffer to receive the symbolic name
- *
- * @return - none
- */
-void
-bfa_fcs_get_sym_name(const struct bfa_fcs_s *fcs, char *node_symname)
-{
- bfa_os_memcpy(node_symname,
- fcs->fabric.bport.port_cfg.sym_name.symname,
- BFA_SYMNAME_MAXLEN);
-}
-
-/**
- * Not used by FCS.
- */
-void
-bfa_cb_lps_flogo_comp(void *bfad, void *uarg)
-{
-}
-
-
diff --git a/drivers/scsi/bfa/fcbuild.h b/drivers/scsi/bfa/fcbuild.h
deleted file mode 100644
index 981d98d542b9..000000000000
--- a/drivers/scsi/bfa/fcbuild.h
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-/*
- * fcbuild.h - FC link service frame building and parsing routines
- */
-
-#ifndef __FCBUILD_H__
-#define __FCBUILD_H__
-
-#include <bfa_os_inc.h>
-#include <protocol/fc.h>
-#include <protocol/fcp.h>
-#include <protocol/ct.h>
-#include <defs/bfa_defs_port.h>
-#include <defs/bfa_defs_pport.h>
-
-/*
- * Utility Macros/functions
- */
-
-#define fcif_sof_set(_ifhdr, _sof) ((_ifhdr)->sof = FC_ ## _sof)
-#define fcif_eof_set(_ifhdr, _eof) ((_ifhdr)->eof = FC_ ## _eof)
-
-#define wwn_is_equal(_wwn1, _wwn2) \
- (memcmp(&(_wwn1), &(_wwn2), sizeof(wwn_t)) == 0)
-
-#define fc_roundup(_l, _s) (((_l) + ((_s) - 1)) & ~((_s) - 1))
-
-/*
- * Given the fc response length, this routine will return
- * the length of the actual payload bytes following the CT header.
- *
- * Assumes the input response length does not include the crc, eof, etc.
- */
-static inline u32
-fc_get_ctresp_pyld_len(u32 resp_len)
-{
- return resp_len - sizeof(struct ct_hdr_s);
-}
-
-/*
- * Convert bfa speed to rpsc speed value.
- */
-static inline enum bfa_pport_speed
-fc_rpsc_operspeed_to_bfa_speed(enum fc_rpsc_op_speed_s speed)
-{
- switch (speed) {
-
- case RPSC_OP_SPEED_1G:
- return BFA_PPORT_SPEED_1GBPS;
-
- case RPSC_OP_SPEED_2G:
- return BFA_PPORT_SPEED_2GBPS;
-
- case RPSC_OP_SPEED_4G:
- return BFA_PPORT_SPEED_4GBPS;
-
- case RPSC_OP_SPEED_8G:
- return BFA_PPORT_SPEED_8GBPS;
-
- case RPSC_OP_SPEED_10G:
- return BFA_PPORT_SPEED_10GBPS;
-
- default:
- return BFA_PPORT_SPEED_UNKNOWN;
- }
-}
-
-/*
- * Convert RPSC speed to bfa speed value.
- */
-static inline enum fc_rpsc_op_speed_s
-fc_bfa_speed_to_rpsc_operspeed(enum bfa_pport_speed op_speed)
-{
- switch (op_speed) {
-
- case BFA_PPORT_SPEED_1GBPS:
- return RPSC_OP_SPEED_1G;
-
- case BFA_PPORT_SPEED_2GBPS:
- return RPSC_OP_SPEED_2G;
-
- case BFA_PPORT_SPEED_4GBPS:
- return RPSC_OP_SPEED_4G;
-
- case BFA_PPORT_SPEED_8GBPS:
- return RPSC_OP_SPEED_8G;
-
- case BFA_PPORT_SPEED_10GBPS:
- return RPSC_OP_SPEED_10G;
-
- default:
- return RPSC_OP_SPEED_NOT_EST;
- }
-}
-enum fc_parse_status {
- FC_PARSE_OK = 0,
- FC_PARSE_FAILURE = 1,
- FC_PARSE_BUSY = 2,
- FC_PARSE_LEN_INVAL,
- FC_PARSE_ACC_INVAL,
- FC_PARSE_PWWN_NOT_EQUAL,
- FC_PARSE_NWWN_NOT_EQUAL,
- FC_PARSE_RXSZ_INVAL,
- FC_PARSE_NOT_FCP,
- FC_PARSE_OPAFLAG_INVAL,
- FC_PARSE_RPAFLAG_INVAL,
- FC_PARSE_OPA_INVAL,
- FC_PARSE_RPA_INVAL,
-
-};
-
-struct fc_templates_s {
- struct fchs_s fc_els_req;
- struct fchs_s fc_bls_req;
- struct fc_logi_s plogi;
- struct fc_rrq_s rrq;
-};
-
-void fcbuild_init(void);
-
-u16 fc_flogi_build(struct fchs_s *fchs, struct fc_logi_s *flogi,
- u32 s_id, u16 ox_id, wwn_t port_name,
- wwn_t node_name, u16 pdu_size, u8 set_npiv,
- u8 set_auth, u16 local_bb_credits);
-u16 fc_fdisc_build(struct fchs_s *buf, struct fc_logi_s *flogi,
- u32 s_id, u16 ox_id, wwn_t port_name,
- wwn_t node_name, u16 pdu_size);
-u16 fc_flogi_acc_build(struct fchs_s *fchs, struct fc_logi_s *flogi,
- u32 s_id, u16 ox_id, wwn_t port_name,
- wwn_t node_name, u16 pdu_size,
- u16 local_bb_credits);
-u16 fc_plogi_build(struct fchs_s *fchs, void *pld, u32 d_id,
- u32 s_id, u16 ox_id, wwn_t port_name,
- wwn_t node_name, u16 pdu_size);
-enum fc_parse_status fc_plogi_parse(struct fchs_s *fchs);
-u16 fc_abts_build(struct fchs_s *buf, u32 d_id, u32 s_id,
- u16 ox_id);
-enum fc_parse_status fc_abts_rsp_parse(struct fchs_s *buf, int len);
-u16 fc_rrq_build(struct fchs_s *buf, struct fc_rrq_s *rrq, u32 d_id,
- u32 s_id, u16 ox_id, u16 rrq_oxid);
-enum fc_parse_status fc_rrq_rsp_parse(struct fchs_s *buf, int len);
-u16 fc_rspnid_build(struct fchs_s *fchs, void *pld, u32 s_id,
- u16 ox_id, u8 *name);
-u16 fc_rftid_build(struct fchs_s *fchs, void *pld, u32 s_id,
- u16 ox_id, enum bfa_port_role role);
-u16 fc_rftid_build_sol(struct fchs_s *fchs, void *pyld, u32 s_id,
- u16 ox_id, u8 *fc4_bitmap,
- u32 bitmap_size);
-u16 fc_rffid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
- u16 ox_id, u8 fc4_type, u8 fc4_ftrs);
-u16 fc_gidpn_build(struct fchs_s *fchs, void *pyld, u32 s_id,
- u16 ox_id, wwn_t port_name);
-u16 fc_gpnid_build(struct fchs_s *fchs, void *pld, u32 s_id,
- u16 ox_id, u32 port_id);
-u16 fc_scr_build(struct fchs_s *fchs, struct fc_scr_s *scr,
- u8 set_br_reg, u32 s_id, u16 ox_id);
-u16 fc_plogi_acc_build(struct fchs_s *fchs, void *pld, u32 d_id,
- u32 s_id, u16 ox_id,
- wwn_t port_name, wwn_t node_name, u16 pdu_size);
-
-u16 fc_adisc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc,
- u32 d_id, u32 s_id, u16 ox_id,
- wwn_t port_name, wwn_t node_name);
-enum fc_parse_status fc_adisc_parse(struct fchs_s *fchs, void *pld,
- u32 host_dap,
- wwn_t node_name, wwn_t port_name);
-enum fc_parse_status fc_adisc_rsp_parse(struct fc_adisc_s *adisc, int len,
- wwn_t port_name, wwn_t node_name);
-u16 fc_adisc_acc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc,
- u32 d_id, u32 s_id, u16 ox_id,
- wwn_t port_name, wwn_t node_name);
-u16 fc_ls_rjt_build(struct fchs_s *fchs, struct fc_ls_rjt_s *ls_rjt,
- u32 d_id, u32 s_id, u16 ox_id,
- u8 reason_code, u8 reason_code_expl);
-u16 fc_ls_acc_build(struct fchs_s *fchs, struct fc_els_cmd_s *els_cmd,
- u32 d_id, u32 s_id, u16 ox_id);
-u16 fc_prli_build(struct fchs_s *fchs, void *pld, u32 d_id,
- u32 s_id, u16 ox_id);
-enum fc_parse_status fc_prli_rsp_parse(struct fc_prli_s *prli, int len);
-
-u16 fc_prli_acc_build(struct fchs_s *fchs, void *pld, u32 d_id,
- u32 s_id, u16 ox_id,
- enum bfa_port_role role);
-u16 fc_rnid_build(struct fchs_s *fchs, struct fc_rnid_cmd_s *rnid,
- u32 d_id, u32 s_id, u16 ox_id,
- u32 data_format);
-u16 fc_rnid_acc_build(struct fchs_s *fchs, struct fc_rnid_acc_s *rnid_acc,
- u32 d_id, u32 s_id, u16 ox_id,
- u32 data_format,
- struct fc_rnid_common_id_data_s *common_id_data,
- struct fc_rnid_general_topology_data_s *
- gen_topo_data);
-u16 fc_rpsc2_build(struct fchs_s *fchs, struct fc_rpsc2_cmd_s *rps2c,
- u32 d_id, u32 s_id,
- u32 *pid_list, u16 npids);
-u16 fc_rpsc_build(struct fchs_s *fchs, struct fc_rpsc_cmd_s *rpsc,
- u32 d_id, u32 s_id, u16 ox_id);
-u16 fc_rpsc_acc_build(struct fchs_s *fchs, struct fc_rpsc_acc_s *rpsc_acc,
- u32 d_id, u32 s_id, u16 ox_id,
- struct fc_rpsc_speed_info_s *oper_speed);
-u16 fc_gid_ft_build(struct fchs_s *fchs, void *pld, u32 s_id,
- u8 fc4_type);
-u16 fc_rpnid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
- u32 port_id, wwn_t port_name);
-u16 fc_rnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
- u32 port_id, wwn_t node_name);
-u16 fc_rcsid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
- u32 port_id, u32 cos);
-u16 fc_rptid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
- u32 port_id, u8 port_type);
-u16 fc_ganxt_build(struct fchs_s *fchs, void *pyld, u32 s_id,
- u32 port_id);
-u16 fc_logo_build(struct fchs_s *fchs, struct fc_logo_s *logo,
- u32 d_id, u32 s_id, u16 ox_id,
- wwn_t port_name);
-u16 fc_logo_acc_build(struct fchs_s *fchs, void *pld, u32 d_id,
- u32 s_id, u16 ox_id);
-u16 fc_fdmi_reqhdr_build(struct fchs_s *fchs, void *pyld, u32 s_id,
- u16 cmd_code);
-u16 fc_gmal_req_build(struct fchs_s *fchs, void *pyld, u32 s_id,
- wwn_t wwn);
-u16 fc_gfn_req_build(struct fchs_s *fchs, void *pyld, u32 s_id,
- wwn_t wwn);
-void fc_get_fc4type_bitmask(u8 fc4_type, u8 *bit_mask);
-void fc_els_req_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
- u16 ox_id);
-enum fc_parse_status fc_els_rsp_parse(struct fchs_s *fchs, int len);
-enum fc_parse_status fc_plogi_rsp_parse(struct fchs_s *fchs, int len,
- wwn_t port_name);
-enum fc_parse_status fc_prli_parse(struct fc_prli_s *prli);
-enum fc_parse_status fc_pdisc_parse(struct fchs_s *fchs, wwn_t node_name,
- wwn_t port_name);
-u16 fc_ba_acc_build(struct fchs_s *fchs, struct fc_ba_acc_s *ba_acc,
- u32 d_id, u32 s_id, u16 ox_id,
- u16 rx_id);
-int fc_logout_params_pages(struct fchs_s *fc_frame, u8 els_code);
-u16 fc_tprlo_acc_build(struct fchs_s *fchs,
- struct fc_tprlo_acc_s *tprlo_acc,
- u32 d_id, u32 s_id, u16 ox_id,
- int num_pages);
-u16 fc_prlo_acc_build(struct fchs_s *fchs, struct fc_prlo_acc_s *prlo_acc,
- u32 d_id, u32 s_id, u16 ox_id,
- int num_pages);
-u16 fc_logo_rsp_parse(struct fchs_s *fchs, int len);
-u16 fc_pdisc_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
- u16 ox_id, wwn_t port_name, wwn_t node_name,
- u16 pdu_size);
-u16 fc_pdisc_rsp_parse(struct fchs_s *fchs, int len, wwn_t port_name);
-u16 fc_prlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
- u16 ox_id, int num_pages);
-u16 fc_prlo_rsp_parse(struct fchs_s *fchs, int len);
-u16 fc_tprlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
- u16 ox_id, int num_pages,
- enum fc_tprlo_type tprlo_type, u32 tpr_id);
-u16 fc_tprlo_rsp_parse(struct fchs_s *fchs, int len);
-u16 fc_ba_rjt_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
- u16 ox_id, u32 reason_code,
- u32 reason_expl);
-u16 fc_gnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
- u16 ox_id, u32 port_id);
-u16 fc_ct_rsp_parse(struct ct_hdr_s *cthdr);
-u16 fc_rscn_build(struct fchs_s *fchs, struct fc_rscn_pl_s *rscn,
- u32 s_id, u16 ox_id);
-#endif
diff --git a/drivers/scsi/bfa/fcptm.c b/drivers/scsi/bfa/fcptm.c
deleted file mode 100644
index 8c8b08c72e7a..000000000000
--- a/drivers/scsi/bfa/fcptm.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/**
- * This file contains dummy FCPTM routines to aid in Initiator Mode only
- * compilation of OS driver.
- *
- */
-
-#include "bfa_os_inc.h"
-#include "fcs_rport.h"
-#include "fcs_fcptm.h"
-#include "fcs/bfa_fcs_rport.h"
-
-struct bfa_fcs_tin_s *
-bfa_fcs_tin_create(struct bfa_fcs_rport_s *rport)
-{
- return NULL;
-}
-
-void
-bfa_fcs_tin_delete(struct bfa_fcs_tin_s *tin)
-{
-}
-
-void
-bfa_fcs_tin_rport_offline(struct bfa_fcs_tin_s *tin)
-{
-}
-
-void
-bfa_fcs_tin_rport_online(struct bfa_fcs_tin_s *tin)
-{
-}
-
-void
-bfa_fcs_tin_rx_prli(struct bfa_fcs_tin_s *tin, struct fchs_s *fchs, u16 len)
-{
-}
-
-void
-bfa_fcs_fcptm_uf_recv(struct bfa_fcs_tin_s *tin, struct fchs_s *fchs, u16 len)
-{
-}
-
-void
-bfa_fcs_tin_pause(struct bfa_fcs_tin_s *tin)
-{
-}
-
-void
-bfa_fcs_tin_resume(struct bfa_fcs_tin_s *tin)
-{
-}
diff --git a/drivers/scsi/bfa/fcs.h b/drivers/scsi/bfa/fcs.h
deleted file mode 100644
index 8d08230e6295..000000000000
--- a/drivers/scsi/bfa/fcs.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/**
- * fcs.h FCS module functions
- */
-
-
-#ifndef __FCS_H__
-#define __FCS_H__
-
-#define __fcs_min_cfg(__fcs) ((__fcs)->min_cfg)
-
-void bfa_fcs_modexit_comp(struct bfa_fcs_s *fcs);
-
-#endif /* __FCS_H__ */
diff --git a/drivers/scsi/bfa/fcs_auth.h b/drivers/scsi/bfa/fcs_auth.h
deleted file mode 100644
index 65d155fea3d7..000000000000
--- a/drivers/scsi/bfa/fcs_auth.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/**
- * fcs_uf.h FCS unsolicited frame receive
- */
-
-
-#ifndef __FCS_AUTH_H__
-#define __FCS_AUTH_H__
-
-#include <fcs/bfa_fcs.h>
-#include <fcs/bfa_fcs_vport.h>
-#include <fcs/bfa_fcs_lport.h>
-
-/*
- * fcs friend functions: only between fcs modules
- */
-void bfa_fcs_auth_uf_recv(struct bfa_fcs_fabric_s *fabric, int len);
-void bfa_fcs_auth_start(struct bfa_fcs_fabric_s *fabric);
-void bfa_fcs_auth_stop(struct bfa_fcs_fabric_s *fabric);
-
-#endif /* __FCS_UF_H__ */
diff --git a/drivers/scsi/bfa/fcs_fabric.h b/drivers/scsi/bfa/fcs_fabric.h
deleted file mode 100644
index 432ab8ab8c3c..000000000000
--- a/drivers/scsi/bfa/fcs_fabric.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/**
- * fcs_lport.h FCS logical port interfaces
- */
-
-#ifndef __FCS_FABRIC_H__
-#define __FCS_FABRIC_H__
-
-#include <fcs/bfa_fcs.h>
-#include <fcs/bfa_fcs_vport.h>
-#include <fcs/bfa_fcs_lport.h>
-
-#define BFA_FCS_BRCD_SWITCH_OUI 0x051e
-
-/*
-* fcs friend functions: only between fcs modules
- */
-void bfa_fcs_fabric_attach(struct bfa_fcs_s *fcs);
-void bfa_fcs_fabric_modinit(struct bfa_fcs_s *fcs);
-void bfa_fcs_fabric_modexit(struct bfa_fcs_s *fcs);
-void bfa_fcs_fabric_modsusp(struct bfa_fcs_s *fcs);
-void bfa_fcs_fabric_link_up(struct bfa_fcs_fabric_s *fabric);
-void bfa_fcs_fabric_link_down(struct bfa_fcs_fabric_s *fabric);
-void bfa_fcs_fabric_addvport(struct bfa_fcs_fabric_s *fabric,
- struct bfa_fcs_vport_s *vport);
-void bfa_fcs_fabric_delvport(struct bfa_fcs_fabric_s *fabric,
- struct bfa_fcs_vport_s *vport);
-int bfa_fcs_fabric_is_online(struct bfa_fcs_fabric_s *fabric);
-struct bfa_fcs_vport_s *bfa_fcs_fabric_vport_lookup(
- struct bfa_fcs_fabric_s *fabric, wwn_t pwwn);
-void bfa_fcs_fabric_modstart(struct bfa_fcs_s *fcs);
-void bfa_fcs_fabric_uf_recv(struct bfa_fcs_fabric_s *fabric,
- struct fchs_s *fchs, u16 len);
-u16 bfa_fcs_fabric_vport_count(struct bfa_fcs_fabric_s *fabric);
-bfa_boolean_t bfa_fcs_fabric_is_loopback(struct bfa_fcs_fabric_s *fabric);
-bfa_boolean_t bfa_fcs_fabric_is_auth_failed(struct bfa_fcs_fabric_s *fabric);
-enum bfa_pport_type bfa_fcs_fabric_port_type(struct bfa_fcs_fabric_s *fabric);
-void bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s *fabric);
-void bfa_fcs_fabric_port_delete_comp(struct bfa_fcs_fabric_s *fabric);
-
-bfa_status_t bfa_fcs_fabric_addvf(struct bfa_fcs_fabric_s *vf,
- struct bfa_fcs_s *fcs, struct bfa_port_cfg_s *port_cfg,
- struct bfad_vf_s *vf_drv);
-void bfa_fcs_auth_finished(struct bfa_fcs_fabric_s *fabric,
- enum auth_status status);
-
-void bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric,
- wwn_t fabric_name);
-u16 bfa_fcs_fabric_get_switch_oui(struct bfa_fcs_fabric_s *fabric);
-void bfa_fcs_get_sym_name(const struct bfa_fcs_s *fcs, char *node_symname);
-
-#endif /* __FCS_FABRIC_H__ */
diff --git a/drivers/scsi/bfa/fcs_fcpim.h b/drivers/scsi/bfa/fcs_fcpim.h
deleted file mode 100644
index 11e6e7bce9f6..000000000000
--- a/drivers/scsi/bfa/fcs_fcpim.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-#ifndef __FCS_FCPIM_H__
-#define __FCS_FCPIM_H__
-
-#include <defs/bfa_defs_port.h>
-#include <fcs/bfa_fcs_lport.h>
-#include <fcs/bfa_fcs_rport.h>
-
-/*
- * Following routines are from FCPIM and will be called by rport.
- */
-struct bfa_fcs_itnim_s *bfa_fcs_itnim_create(struct bfa_fcs_rport_s *rport);
-void bfa_fcs_itnim_delete(struct bfa_fcs_itnim_s *itnim);
-void bfa_fcs_itnim_rport_offline(struct bfa_fcs_itnim_s *itnim);
-void bfa_fcs_itnim_rport_online(struct bfa_fcs_itnim_s *itnim);
-bfa_status_t bfa_fcs_itnim_get_online_state(struct bfa_fcs_itnim_s *itnim);
-
-void bfa_fcs_itnim_is_initiator(struct bfa_fcs_itnim_s *itnim);
-void bfa_fcs_itnim_pause(struct bfa_fcs_itnim_s *itnim);
-void bfa_fcs_itnim_resume(struct bfa_fcs_itnim_s *itnim);
-
-void bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s *itnim, struct fchs_s *fchs,
- u16 len);
-#endif /* __FCS_FCPIM_H__ */
diff --git a/drivers/scsi/bfa/fcs_fcptm.h b/drivers/scsi/bfa/fcs_fcptm.h
deleted file mode 100644
index ffff0829fd31..000000000000
--- a/drivers/scsi/bfa/fcs_fcptm.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __FCS_FCPTM_H__
-#define __FCS_FCPTM_H__
-
-#include <defs/bfa_defs_port.h>
-#include <fcs/bfa_fcs_lport.h>
-#include <fcs/bfa_fcs_rport.h>
-
-/*
- * Following routines are from FCPTM and will be called by rport.
- */
-struct bfa_fcs_tin_s *bfa_fcs_tin_create(struct bfa_fcs_rport_s *rport);
-void bfa_fcs_tin_rport_offline(struct bfa_fcs_tin_s *tin);
-void bfa_fcs_tin_rport_online(struct bfa_fcs_tin_s *tin);
-void bfa_fcs_tin_delete(struct bfa_fcs_tin_s *tin);
-void bfa_fcs_tin_rx_prli(struct bfa_fcs_tin_s *tin, struct fchs_s *fchs,
- u16 len);
-void bfa_fcs_tin_pause(struct bfa_fcs_tin_s *tin);
-void bfa_fcs_tin_resume(struct bfa_fcs_tin_s *tin);
-
-/*
- * Modudle init/cleanup routines.
- */
-void bfa_fcs_fcptm_modinit(struct bfa_fcs_s *fcs);
-void bfa_fcs_fcptm_modexit(struct bfa_fcs_s *fcs);
-void bfa_fcs_fcptm_uf_recv(struct bfa_fcs_tin_s *tin, struct fchs_s *fchs,
- u16 len);
-
-#endif /* __FCS_FCPTM_H__ */
diff --git a/drivers/scsi/bfa/fcs_fcxp.h b/drivers/scsi/bfa/fcs_fcxp.h
deleted file mode 100644
index 8277fe9c2b70..000000000000
--- a/drivers/scsi/bfa/fcs_fcxp.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/**
- * fcs_fcxp.h FCXP helper macros for FCS
- */
-
-
-#ifndef __FCS_FCXP_H__
-#define __FCS_FCXP_H__
-
-#define bfa_fcs_fcxp_alloc(__fcs) \
- bfa_fcxp_alloc(NULL, (__fcs)->bfa, 0, 0, NULL, NULL, NULL, NULL)
-
-#endif /* __FCS_FCXP_H__ */
diff --git a/drivers/scsi/bfa/fcs_lport.h b/drivers/scsi/bfa/fcs_lport.h
deleted file mode 100644
index a6508c8ab184..000000000000
--- a/drivers/scsi/bfa/fcs_lport.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/**
- * fcs_lport.h FCS logical port interfaces
- */
-
-#ifndef __FCS_LPORT_H__
-#define __FCS_LPORT_H__
-
-#define __VPORT_H__
-#include <defs/bfa_defs_port.h>
-#include <bfa_svc.h>
-#include <fcs/bfa_fcs_lport.h>
-#include <fcs/bfa_fcs_rport.h>
-#include <fcs/bfa_fcs_vport.h>
-#include <fcs_fabric.h>
-#include <fcs_ms.h>
-#include <cs/bfa_q.h>
-#include <fcbuild.h>
-
-/*
- * PID used in P2P/N2N ( In Big Endian)
- */
-#define N2N_LOCAL_PID 0x010000
-#define N2N_REMOTE_PID 0x020000
-
-/*
- * Misc Timeouts
- */
-/*
- * To be used when spawning a timer before retrying a failed command. Milli
- * Secs.
- */
-#define BFA_FCS_RETRY_TIMEOUT 2000
-
-/*
- * Check for Port/Vport Mode/Role
- */
-#define BFA_FCS_VPORT_IS_INITIATOR_MODE(port) \
- (port->port_cfg.roles & BFA_PORT_ROLE_FCP_IM)
-
-#define BFA_FCS_VPORT_IS_TARGET_MODE(port) \
- (port->port_cfg.roles & BFA_PORT_ROLE_FCP_TM)
-
-#define BFA_FCS_VPORT_IS_IPFC_MODE(port) \
- (port->port_cfg.roles & BFA_PORT_ROLE_FCP_IPFC)
-
-/*
- * Is this a Well Known Address
- */
-#define BFA_FCS_PID_IS_WKA(pid) ((bfa_os_ntoh3b(pid) > 0xFFF000) ? 1 : 0)
-
-/*
- * Pointer to elements within Port
- */
-#define BFA_FCS_GET_HAL_FROM_PORT(port) (port->fcs->bfa)
-#define BFA_FCS_GET_NS_FROM_PORT(port) (&port->port_topo.pfab.ns)
-#define BFA_FCS_GET_SCN_FROM_PORT(port) (&port->port_topo.pfab.scn)
-#define BFA_FCS_GET_MS_FROM_PORT(port) (&port->port_topo.pfab.ms)
-#define BFA_FCS_GET_FDMI_FROM_PORT(port) (&port->port_topo.pfab.ms.fdmi)
-
-/*
- * handler for unsolicied frames
- */
-void bfa_fcs_port_uf_recv(struct bfa_fcs_port_s *lport, struct fchs_s *fchs,
- u16 len);
-
-/*
- * Following routines will be called by Fabric to indicate port
- * online/offline to vport.
- */
-void bfa_fcs_lport_attach(struct bfa_fcs_port_s *lport, struct bfa_fcs_s *fcs,
- uint16_t vf_id, struct bfa_fcs_vport_s *vport);
-void bfa_fcs_lport_init(struct bfa_fcs_port_s *lport,
- struct bfa_port_cfg_s *port_cfg);
-void bfa_fcs_port_online(struct bfa_fcs_port_s *port);
-void bfa_fcs_port_offline(struct bfa_fcs_port_s *port);
-void bfa_fcs_port_delete(struct bfa_fcs_port_s *port);
-bfa_boolean_t bfa_fcs_port_is_online(struct bfa_fcs_port_s *port);
-
-/*
- * Lookup rport based on PID
- */
-struct bfa_fcs_rport_s *bfa_fcs_port_get_rport_by_pid(
- struct bfa_fcs_port_s *port, u32 pid);
-
-/*
- * Lookup rport based on PWWN
- */
-struct bfa_fcs_rport_s *bfa_fcs_port_get_rport_by_pwwn(
- struct bfa_fcs_port_s *port, wwn_t pwwn);
-struct bfa_fcs_rport_s *bfa_fcs_port_get_rport_by_nwwn(
- struct bfa_fcs_port_s *port, wwn_t nwwn);
-void bfa_fcs_port_add_rport(struct bfa_fcs_port_s *port,
- struct bfa_fcs_rport_s *rport);
-void bfa_fcs_port_del_rport(struct bfa_fcs_port_s *port,
- struct bfa_fcs_rport_s *rport);
-
-void bfa_fcs_port_modinit(struct bfa_fcs_s *fcs);
-void bfa_fcs_port_modexit(struct bfa_fcs_s *fcs);
-void bfa_fcs_port_lip(struct bfa_fcs_port_s *port);
-
-#endif /* __FCS_LPORT_H__ */
diff --git a/drivers/scsi/bfa/fcs_ms.h b/drivers/scsi/bfa/fcs_ms.h
deleted file mode 100644
index b6a8c12876f4..000000000000
--- a/drivers/scsi/bfa/fcs_ms.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/**
- * fcs_ms.h FCS ms interfaces
- */
-#ifndef __FCS_MS_H__
-#define __FCS_MS_H__
-
-/* MS FCS routines */
-void bfa_fcs_port_ms_init(struct bfa_fcs_port_s *port);
-void bfa_fcs_port_ms_offline(struct bfa_fcs_port_s *port);
-void bfa_fcs_port_ms_online(struct bfa_fcs_port_s *port);
-void bfa_fcs_port_ms_fabric_rscn(struct bfa_fcs_port_s *port);
-
-/* FDMI FCS routines */
-void bfa_fcs_port_fdmi_init(struct bfa_fcs_port_ms_s *ms);
-void bfa_fcs_port_fdmi_offline(struct bfa_fcs_port_ms_s *ms);
-void bfa_fcs_port_fdmi_online(struct bfa_fcs_port_ms_s *ms);
-
-#endif
diff --git a/drivers/scsi/bfa/fcs_port.h b/drivers/scsi/bfa/fcs_port.h
deleted file mode 100644
index 408c06a7d164..000000000000
--- a/drivers/scsi/bfa/fcs_port.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/**
- * fcs_pport.h FCS physical port interfaces
- */
-
-
-#ifndef __FCS_PPORT_H__
-#define __FCS_PPORT_H__
-
-/*
- * fcs friend functions: only between fcs modules
- */
-void bfa_fcs_pport_attach(struct bfa_fcs_s *fcs);
-
-#endif /* __FCS_PPORT_H__ */
diff --git a/drivers/scsi/bfa/fcs_rport.h b/drivers/scsi/bfa/fcs_rport.h
deleted file mode 100644
index e634fb7a69b8..000000000000
--- a/drivers/scsi/bfa/fcs_rport.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/**
- * fcs_rport.h FCS rport interfaces and defines
- */
-
-#ifndef __FCS_RPORT_H__
-#define __FCS_RPORT_H__
-
-#include <fcs/bfa_fcs_rport.h>
-
-#define BFA_FCS_RPORT_MAX_RETRIES (5)
-
-void bfa_fcs_rport_uf_recv(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs,
- u16 len);
-void bfa_fcs_rport_scn(struct bfa_fcs_rport_s *rport);
-
-struct bfa_fcs_rport_s *bfa_fcs_rport_create(struct bfa_fcs_port_s *port,
- u32 pid);
-void bfa_fcs_rport_delete(struct bfa_fcs_rport_s *rport);
-void bfa_fcs_rport_online(struct bfa_fcs_rport_s *rport);
-void bfa_fcs_rport_offline(struct bfa_fcs_rport_s *rport);
-void bfa_fcs_rport_start(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs,
- struct fc_logi_s *plogi_rsp);
-void bfa_fcs_rport_plogi_create(struct bfa_fcs_port_s *port,
- struct fchs_s *rx_fchs,
- struct fc_logi_s *plogi);
-void bfa_fcs_rport_plogi(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs,
- struct fc_logi_s *plogi);
-void bfa_fcs_rport_logo_imp(struct bfa_fcs_rport_s *rport);
-void bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, uint16_t ox_id);
-void bfa_fcs_rport_itnim_ack(struct bfa_fcs_rport_s *rport);
-void bfa_fcs_rport_itntm_ack(struct bfa_fcs_rport_s *rport);
-void bfa_fcs_rport_tin_ack(struct bfa_fcs_rport_s *rport);
-void bfa_fcs_rport_fcptm_offline_done(struct bfa_fcs_rport_s *rport);
-int bfa_fcs_rport_get_state(struct bfa_fcs_rport_s *rport);
-struct bfa_fcs_rport_s *bfa_fcs_rport_create_by_wwn(struct bfa_fcs_port_s *port,
- wwn_t wwn);
-
-
-/* Rport Features */
-void bfa_fcs_rpf_init(struct bfa_fcs_rport_s *rport);
-void bfa_fcs_rpf_rport_online(struct bfa_fcs_rport_s *rport);
-void bfa_fcs_rpf_rport_offline(struct bfa_fcs_rport_s *rport);
-
-#endif /* __FCS_RPORT_H__ */
diff --git a/drivers/scsi/bfa/fcs_trcmod.h b/drivers/scsi/bfa/fcs_trcmod.h
deleted file mode 100644
index 41b5ae8d7644..000000000000
--- a/drivers/scsi/bfa/fcs_trcmod.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/**
- * fcs_trcmod.h BFA FCS trace modules
- */
-
-#ifndef __FCS_TRCMOD_H__
-#define __FCS_TRCMOD_H__
-
-#include <cs/bfa_trc.h>
-
-/*
- * !!! Only append to the enums defined here to avoid any versioning
- * !!! needed between trace utility and driver version
- */
-enum {
- BFA_TRC_FCS_FABRIC = 1,
- BFA_TRC_FCS_VFAPI = 2,
- BFA_TRC_FCS_PORT = 3,
- BFA_TRC_FCS_VPORT = 4,
- BFA_TRC_FCS_VP_API = 5,
- BFA_TRC_FCS_VPS = 6,
- BFA_TRC_FCS_RPORT = 7,
- BFA_TRC_FCS_FCPIM = 8,
- BFA_TRC_FCS_FCPTM = 9,
- BFA_TRC_FCS_NS = 10,
- BFA_TRC_FCS_SCN = 11,
- BFA_TRC_FCS_LOOP = 12,
- BFA_TRC_FCS_UF = 13,
- BFA_TRC_FCS_PPORT = 14,
- BFA_TRC_FCS_FCPIP = 15,
- BFA_TRC_FCS_PORT_API = 16,
- BFA_TRC_FCS_RPORT_API = 17,
- BFA_TRC_FCS_AUTH = 18,
- BFA_TRC_FCS_N2N = 19,
- BFA_TRC_FCS_MS = 20,
- BFA_TRC_FCS_FDMI = 21,
- BFA_TRC_FCS_RPORT_FTRS = 22,
-};
-
-#endif /* __FCS_TRCMOD_H__ */
diff --git a/drivers/scsi/bfa/fcs_uf.h b/drivers/scsi/bfa/fcs_uf.h
deleted file mode 100644
index f591072214fe..000000000000
--- a/drivers/scsi/bfa/fcs_uf.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/**
- * fcs_uf.h FCS unsolicited frame receive
- */
-
-
-#ifndef __FCS_UF_H__
-#define __FCS_UF_H__
-
-/*
- * fcs friend functions: only between fcs modules
- */
-void bfa_fcs_uf_attach(struct bfa_fcs_s *fcs);
-
-#endif /* __FCS_UF_H__ */
diff --git a/drivers/scsi/bfa/fcs_vport.h b/drivers/scsi/bfa/fcs_vport.h
deleted file mode 100644
index bb647a4a5dde..000000000000
--- a/drivers/scsi/bfa/fcs_vport.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __FCS_VPORT_H__
-#define __FCS_VPORT_H__
-
-#include <fcs/bfa_fcs_lport.h>
-#include <fcs/bfa_fcs_vport.h>
-#include <defs/bfa_defs_pci.h>
-
-void bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s *vport);
-void bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport);
-void bfa_fcs_vport_offline(struct bfa_fcs_vport_s *vport);
-void bfa_fcs_vport_delete_comp(struct bfa_fcs_vport_s *vport);
-void bfa_fcs_vport_fcs_delete(struct bfa_fcs_vport_s *vport);
-
-#endif /* __FCS_VPORT_H__ */
-
diff --git a/drivers/scsi/bfa/fdmi.c b/drivers/scsi/bfa/fdmi.c
deleted file mode 100644
index 2b50eabf4b1e..000000000000
--- a/drivers/scsi/bfa/fdmi.c
+++ /dev/null
@@ -1,1230 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/**
- * port_api.c BFA FCS port
- */
-
-
-#include <bfa.h>
-#include <bfa_svc.h>
-#include "fcs_lport.h"
-#include "fcs_rport.h"
-#include "lport_priv.h"
-#include "fcs_trcmod.h"
-#include "fcs_fcxp.h"
-#include <fcs/bfa_fcs_fdmi.h>
-
-BFA_TRC_FILE(FCS, FDMI);
-
-#define BFA_FCS_FDMI_CMD_MAX_RETRIES 2
-
-/*
- * forward declarations
- */
-static void bfa_fcs_port_fdmi_send_rhba(void *fdmi_cbarg,
- struct bfa_fcxp_s *fcxp_alloced);
-static void bfa_fcs_port_fdmi_send_rprt(void *fdmi_cbarg,
- struct bfa_fcxp_s *fcxp_alloced);
-static void bfa_fcs_port_fdmi_send_rpa(void *fdmi_cbarg,
- struct bfa_fcxp_s *fcxp_alloced);
-static void bfa_fcs_port_fdmi_rhba_response(void *fcsarg,
- struct bfa_fcxp_s *fcxp,
- void *cbarg,
- bfa_status_t req_status,
- u32 rsp_len,
- u32 resid_len,
- struct fchs_s *rsp_fchs);
-static void bfa_fcs_port_fdmi_rprt_response(void *fcsarg,
- struct bfa_fcxp_s *fcxp,
- void *cbarg,
- bfa_status_t req_status,
- u32 rsp_len,
- u32 resid_len,
- struct fchs_s *rsp_fchs);
-static void bfa_fcs_port_fdmi_rpa_response(void *fcsarg,
- struct bfa_fcxp_s *fcxp,
- void *cbarg,
- bfa_status_t req_status,
- u32 rsp_len,
- u32 resid_len,
- struct fchs_s *rsp_fchs);
-static void bfa_fcs_port_fdmi_timeout(void *arg);
-static u16 bfa_fcs_port_fdmi_build_rhba_pyld(
- struct bfa_fcs_port_fdmi_s *fdmi, u8 *pyld);
-static u16 bfa_fcs_port_fdmi_build_rprt_pyld(
- struct bfa_fcs_port_fdmi_s *fdmi, u8 *pyld);
-static u16 bfa_fcs_port_fdmi_build_rpa_pyld(
- struct bfa_fcs_port_fdmi_s *fdmi, u8 *pyld);
-static u16 bfa_fcs_port_fdmi_build_portattr_block(
- struct bfa_fcs_port_fdmi_s *fdmi, u8 *pyld);
-static void bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_port_fdmi_s *fdmi,
- struct bfa_fcs_fdmi_hba_attr_s *hba_attr);
-static void bfa_fcs_fdmi_get_portattr(struct bfa_fcs_port_fdmi_s *fdmi,
- struct bfa_fcs_fdmi_port_attr_s *port_attr);
-/**
- * fcs_fdmi_sm FCS FDMI state machine
- */
-
-/**
- * FDMI State Machine events
- */
-enum port_fdmi_event {
- FDMISM_EVENT_PORT_ONLINE = 1,
- FDMISM_EVENT_PORT_OFFLINE = 2,
- FDMISM_EVENT_RSP_OK = 4,
- FDMISM_EVENT_RSP_ERROR = 5,
- FDMISM_EVENT_TIMEOUT = 6,
- FDMISM_EVENT_RHBA_SENT = 7,
- FDMISM_EVENT_RPRT_SENT = 8,
- FDMISM_EVENT_RPA_SENT = 9,
-};
-
-static void bfa_fcs_port_fdmi_sm_offline(struct bfa_fcs_port_fdmi_s *fdmi,
- enum port_fdmi_event event);
-static void bfa_fcs_port_fdmi_sm_sending_rhba(struct bfa_fcs_port_fdmi_s *fdmi,
- enum port_fdmi_event event);
-static void bfa_fcs_port_fdmi_sm_rhba(struct bfa_fcs_port_fdmi_s *fdmi,
- enum port_fdmi_event event);
-static void bfa_fcs_port_fdmi_sm_rhba_retry(struct bfa_fcs_port_fdmi_s *fdmi,
- enum port_fdmi_event event);
-static void bfa_fcs_port_fdmi_sm_sending_rprt(struct bfa_fcs_port_fdmi_s *fdmi,
- enum port_fdmi_event event);
-static void bfa_fcs_port_fdmi_sm_rprt(struct bfa_fcs_port_fdmi_s *fdmi,
- enum port_fdmi_event event);
-static void bfa_fcs_port_fdmi_sm_rprt_retry(struct bfa_fcs_port_fdmi_s *fdmi,
- enum port_fdmi_event event);
-static void bfa_fcs_port_fdmi_sm_sending_rpa(struct bfa_fcs_port_fdmi_s *fdmi,
- enum port_fdmi_event event);
-static void bfa_fcs_port_fdmi_sm_rpa(struct bfa_fcs_port_fdmi_s *fdmi,
- enum port_fdmi_event event);
-static void bfa_fcs_port_fdmi_sm_rpa_retry(struct bfa_fcs_port_fdmi_s *fdmi,
- enum port_fdmi_event event);
-static void bfa_fcs_port_fdmi_sm_online(struct bfa_fcs_port_fdmi_s *fdmi,
- enum port_fdmi_event event);
-static void bfa_fcs_port_fdmi_sm_disabled(struct bfa_fcs_port_fdmi_s *fdmi,
- enum port_fdmi_event event);
-
-/**
- * Start in offline state - awaiting MS to send start.
- */
-static void
-bfa_fcs_port_fdmi_sm_offline(struct bfa_fcs_port_fdmi_s *fdmi,
- enum port_fdmi_event event)
-{
- struct bfa_fcs_port_s *port = fdmi->ms->port;
-
- bfa_trc(port->fcs, port->port_cfg.pwwn);
- bfa_trc(port->fcs, event);
-
- fdmi->retry_cnt = 0;
-
- switch (event) {
- case FDMISM_EVENT_PORT_ONLINE:
- if (port->vport) {
- /*
- * For Vports, register a new port.
- */
- bfa_sm_set_state(fdmi,
- bfa_fcs_port_fdmi_sm_sending_rprt);
- bfa_fcs_port_fdmi_send_rprt(fdmi, NULL);
- } else {
- /*
- * For a base port, we should first register the HBA
- * atribute. The HBA attribute also contains the base
- * port registration.
- */
- bfa_sm_set_state(fdmi,
- bfa_fcs_port_fdmi_sm_sending_rhba);
- bfa_fcs_port_fdmi_send_rhba(fdmi, NULL);
- }
- break;
-
- case FDMISM_EVENT_PORT_OFFLINE:
- break;
-
- default:
- bfa_sm_fault(port->fcs, event);
- }
-}
-
-static void
-bfa_fcs_port_fdmi_sm_sending_rhba(struct bfa_fcs_port_fdmi_s *fdmi,
- enum port_fdmi_event event)
-{
- struct bfa_fcs_port_s *port = fdmi->ms->port;
-
- bfa_trc(port->fcs, port->port_cfg.pwwn);
- bfa_trc(port->fcs, event);
-
- switch (event) {
- case FDMISM_EVENT_RHBA_SENT:
- bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_rhba);
- break;
-
- case FDMISM_EVENT_PORT_OFFLINE:
- bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
- bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
- &fdmi->fcxp_wqe);
- break;
-
- default:
- bfa_sm_fault(port->fcs, event);
- }
-}
-
-static void
-bfa_fcs_port_fdmi_sm_rhba(struct bfa_fcs_port_fdmi_s *fdmi,
- enum port_fdmi_event event)
-{
- struct bfa_fcs_port_s *port = fdmi->ms->port;
-
- bfa_trc(port->fcs, port->port_cfg.pwwn);
- bfa_trc(port->fcs, event);
-
- switch (event) {
- case FDMISM_EVENT_RSP_ERROR:
- /*
- * if max retries have not been reached, start timer for a
- * delayed retry
- */
- if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
- bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_rhba_retry);
- bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
- &fdmi->timer, bfa_fcs_port_fdmi_timeout,
- fdmi, BFA_FCS_RETRY_TIMEOUT);
- } else {
- /*
- * set state to offline
- */
- bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
- }
- break;
-
- case FDMISM_EVENT_RSP_OK:
- /*
- * Initiate Register Port Attributes
- */
- bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_sending_rpa);
- fdmi->retry_cnt = 0;
- bfa_fcs_port_fdmi_send_rpa(fdmi, NULL);
- break;
-
- case FDMISM_EVENT_PORT_OFFLINE:
- bfa_fcxp_discard(fdmi->fcxp);
- bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
- break;
-
- default:
- bfa_sm_fault(port->fcs, event);
- }
-}
-
-static void
-bfa_fcs_port_fdmi_sm_rhba_retry(struct bfa_fcs_port_fdmi_s *fdmi,
- enum port_fdmi_event event)
-{
- struct bfa_fcs_port_s *port = fdmi->ms->port;
-
- bfa_trc(port->fcs, port->port_cfg.pwwn);
- bfa_trc(port->fcs, event);
-
- switch (event) {
- case FDMISM_EVENT_TIMEOUT:
- /*
- * Retry Timer Expired. Re-send
- */
- bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_sending_rhba);
- bfa_fcs_port_fdmi_send_rhba(fdmi, NULL);
- break;
-
- case FDMISM_EVENT_PORT_OFFLINE:
- bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
- bfa_timer_stop(&fdmi->timer);
- break;
-
- default:
- bfa_sm_fault(port->fcs, event);
- }
-}
-
-/*
-* RPRT : Register Port
- */
-static void
-bfa_fcs_port_fdmi_sm_sending_rprt(struct bfa_fcs_port_fdmi_s *fdmi,
- enum port_fdmi_event event)
-{
- struct bfa_fcs_port_s *port = fdmi->ms->port;
-
- bfa_trc(port->fcs, port->port_cfg.pwwn);
- bfa_trc(port->fcs, event);
-
- switch (event) {
- case FDMISM_EVENT_RPRT_SENT:
- bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_rprt);
- break;
-
- case FDMISM_EVENT_PORT_OFFLINE:
- bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
- bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
- &fdmi->fcxp_wqe);
- break;
-
- default:
- bfa_sm_fault(port->fcs, event);
- }
-}
-
-static void
-bfa_fcs_port_fdmi_sm_rprt(struct bfa_fcs_port_fdmi_s *fdmi,
- enum port_fdmi_event event)
-{
- struct bfa_fcs_port_s *port = fdmi->ms->port;
-
- bfa_trc(port->fcs, port->port_cfg.pwwn);
- bfa_trc(port->fcs, event);
-
- switch (event) {
- case FDMISM_EVENT_RSP_ERROR:
- /*
- * if max retries have not been reached, start timer for a
- * delayed retry
- */
- if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
- bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_rprt_retry);
- bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
- &fdmi->timer, bfa_fcs_port_fdmi_timeout,
- fdmi, BFA_FCS_RETRY_TIMEOUT);
-
- } else {
- /*
- * set state to offline
- */
- bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
- fdmi->retry_cnt = 0;
- }
- break;
-
- case FDMISM_EVENT_RSP_OK:
- fdmi->retry_cnt = 0;
- bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_online);
- break;
-
- case FDMISM_EVENT_PORT_OFFLINE:
- bfa_fcxp_discard(fdmi->fcxp);
- bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
- break;
-
- default:
- bfa_sm_fault(port->fcs, event);
- }
-}
-
-static void
-bfa_fcs_port_fdmi_sm_rprt_retry(struct bfa_fcs_port_fdmi_s *fdmi,
- enum port_fdmi_event event)
-{
- struct bfa_fcs_port_s *port = fdmi->ms->port;
-
- bfa_trc(port->fcs, port->port_cfg.pwwn);
- bfa_trc(port->fcs, event);
-
- switch (event) {
- case FDMISM_EVENT_TIMEOUT:
- /*
- * Retry Timer Expired. Re-send
- */
- bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_sending_rprt);
- bfa_fcs_port_fdmi_send_rprt(fdmi, NULL);
- break;
-
- case FDMISM_EVENT_PORT_OFFLINE:
- bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
- bfa_timer_stop(&fdmi->timer);
- break;
-
- default:
- bfa_sm_fault(port->fcs, event);
- }
-}
-
-/*
- * Register Port Attributes
- */
-static void
-bfa_fcs_port_fdmi_sm_sending_rpa(struct bfa_fcs_port_fdmi_s *fdmi,
- enum port_fdmi_event event)
-{
- struct bfa_fcs_port_s *port = fdmi->ms->port;
-
- bfa_trc(port->fcs, port->port_cfg.pwwn);
- bfa_trc(port->fcs, event);
-
- switch (event) {
- case FDMISM_EVENT_RPA_SENT:
- bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_rpa);
- break;
-
- case FDMISM_EVENT_PORT_OFFLINE:
- bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
- bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
- &fdmi->fcxp_wqe);
- break;
-
- default:
- bfa_sm_fault(port->fcs, event);
- }
-}
-
-static void
-bfa_fcs_port_fdmi_sm_rpa(struct bfa_fcs_port_fdmi_s *fdmi,
- enum port_fdmi_event event)
-{
- struct bfa_fcs_port_s *port = fdmi->ms->port;
-
- bfa_trc(port->fcs, port->port_cfg.pwwn);
- bfa_trc(port->fcs, event);
-
- switch (event) {
- case FDMISM_EVENT_RSP_ERROR:
- /*
- * if max retries have not been reached, start timer for a
- * delayed retry
- */
- if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
- bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_rpa_retry);
- bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
- &fdmi->timer, bfa_fcs_port_fdmi_timeout,
- fdmi, BFA_FCS_RETRY_TIMEOUT);
- } else {
- /*
- * set state to offline
- */
- bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
- fdmi->retry_cnt = 0;
- }
- break;
-
- case FDMISM_EVENT_RSP_OK:
- bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_online);
- fdmi->retry_cnt = 0;
- break;
-
- case FDMISM_EVENT_PORT_OFFLINE:
- bfa_fcxp_discard(fdmi->fcxp);
- bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
- break;
-
- default:
- bfa_sm_fault(port->fcs, event);
- }
-}
-
-static void
-bfa_fcs_port_fdmi_sm_rpa_retry(struct bfa_fcs_port_fdmi_s *fdmi,
- enum port_fdmi_event event)
-{
- struct bfa_fcs_port_s *port = fdmi->ms->port;
-
- bfa_trc(port->fcs, port->port_cfg.pwwn);
- bfa_trc(port->fcs, event);
-
- switch (event) {
- case FDMISM_EVENT_TIMEOUT:
- /*
- * Retry Timer Expired. Re-send
- */
- bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_sending_rpa);
- bfa_fcs_port_fdmi_send_rpa(fdmi, NULL);
- break;
-
- case FDMISM_EVENT_PORT_OFFLINE:
- bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
- bfa_timer_stop(&fdmi->timer);
- break;
-
- default:
- bfa_sm_fault(port->fcs, event);
- }
-}
-
-static void
-bfa_fcs_port_fdmi_sm_online(struct bfa_fcs_port_fdmi_s *fdmi,
- enum port_fdmi_event event)
-{
- struct bfa_fcs_port_s *port = fdmi->ms->port;
-
- bfa_trc(port->fcs, port->port_cfg.pwwn);
- bfa_trc(port->fcs, event);
-
- switch (event) {
- case FDMISM_EVENT_PORT_OFFLINE:
- bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
- break;
-
- default:
- bfa_sm_fault(port->fcs, event);
- }
-}
-
-/**
- * FDMI is disabled state.
- */
-static void
-bfa_fcs_port_fdmi_sm_disabled(struct bfa_fcs_port_fdmi_s *fdmi,
- enum port_fdmi_event event)
-{
- struct bfa_fcs_port_s *port = fdmi->ms->port;
-
- bfa_trc(port->fcs, port->port_cfg.pwwn);
- bfa_trc(port->fcs, event);
-
- /* No op State. It can only be enabled at Driver Init. */
-}
-
-/**
-* RHBA : Register HBA Attributes.
- */
-static void
-bfa_fcs_port_fdmi_send_rhba(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
- struct bfa_fcs_port_fdmi_s *fdmi = fdmi_cbarg;
- struct bfa_fcs_port_s *port = fdmi->ms->port;
- struct fchs_s fchs;
- int len, attr_len;
- struct bfa_fcxp_s *fcxp;
- u8 *pyld;
-
- bfa_trc(port->fcs, port->port_cfg.pwwn);
-
- fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
- if (!fcxp) {
- bfa_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
- bfa_fcs_port_fdmi_send_rhba, fdmi);
- return;
- }
- fdmi->fcxp = fcxp;
-
- pyld = bfa_fcxp_get_reqbuf(fcxp);
- bfa_os_memset(pyld, 0, FC_MAX_PDUSZ);
-
- len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_port_get_fcid(port),
- FDMI_RHBA);
-
- attr_len = bfa_fcs_port_fdmi_build_rhba_pyld(fdmi,
- (u8 *) ((struct ct_hdr_s *) pyld + 1));
-
- bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
- FC_CLASS_3, (len + attr_len), &fchs,
- bfa_fcs_port_fdmi_rhba_response, (void *)fdmi,
- FC_MAX_PDUSZ, FC_FCCT_TOV);
-
- bfa_sm_send_event(fdmi, FDMISM_EVENT_RHBA_SENT);
-}
-
-static u16
-bfa_fcs_port_fdmi_build_rhba_pyld(struct bfa_fcs_port_fdmi_s *fdmi,
- u8 *pyld)
-{
- struct bfa_fcs_port_s *port = fdmi->ms->port;
- struct bfa_fcs_fdmi_hba_attr_s hba_attr; /* @todo */
- struct bfa_fcs_fdmi_hba_attr_s *fcs_hba_attr = &hba_attr; /* @todo */
- struct fdmi_rhba_s *rhba = (struct fdmi_rhba_s *) pyld;
- struct fdmi_attr_s *attr;
- u8 *curr_ptr;
- u16 len, count;
-
- /*
- * get hba attributes
- */
- bfa_fcs_fdmi_get_hbaattr(fdmi, fcs_hba_attr);
-
- rhba->hba_id = bfa_fcs_port_get_pwwn(port);
- rhba->port_list.num_ports = bfa_os_htonl(1);
- rhba->port_list.port_entry = bfa_fcs_port_get_pwwn(port);
-
- len = sizeof(rhba->hba_id) + sizeof(rhba->port_list);
-
- count = 0;
- len += sizeof(rhba->hba_attr_blk.attr_count);
-
- /*
- * fill out the invididual entries of the HBA attrib Block
- */
- curr_ptr = (u8 *) &rhba->hba_attr_blk.hba_attr;
-
- /*
- * Node Name
- */
- attr = (struct fdmi_attr_s *) curr_ptr;
- attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_NODENAME);
- attr->len = sizeof(wwn_t);
- memcpy(attr->value, &bfa_fcs_port_get_nwwn(port), attr->len);
- curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
- len += attr->len;
- count++;
- attr->len =
- bfa_os_htons(attr->len + sizeof(attr->type) +
- sizeof(attr->len));
-
- /*
- * Manufacturer
- */
- attr = (struct fdmi_attr_s *) curr_ptr;
- attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_MANUFACTURER);
- attr->len = (u16) strlen(fcs_hba_attr->manufacturer);
- memcpy(attr->value, fcs_hba_attr->manufacturer, attr->len);
- /* variable fields need to be 4 byte aligned */
- attr->len = fc_roundup(attr->len, sizeof(u32));
- curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
- len += attr->len;
- count++;
- attr->len =
- bfa_os_htons(attr->len + sizeof(attr->type) +
- sizeof(attr->len));
-
- /*
- * Serial Number
- */
- attr = (struct fdmi_attr_s *) curr_ptr;
- attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_SERIALNUM);
- attr->len = (u16) strlen(fcs_hba_attr->serial_num);
- memcpy(attr->value, fcs_hba_attr->serial_num, attr->len);
- /* variable fields need to be 4 byte aligned */
- attr->len = fc_roundup(attr->len, sizeof(u32));
- curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
- len += attr->len;
- count++;
- attr->len =
- bfa_os_htons(attr->len + sizeof(attr->type) +
- sizeof(attr->len));
-
- /*
- * Model
- */
- attr = (struct fdmi_attr_s *) curr_ptr;
- attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_MODEL);
- attr->len = (u16) strlen(fcs_hba_attr->model);
- memcpy(attr->value, fcs_hba_attr->model, attr->len);
- /* variable fields need to be 4 byte aligned */
- attr->len = fc_roundup(attr->len, sizeof(u32));
- curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
- len += attr->len;
- count++;
- attr->len =
- bfa_os_htons(attr->len + sizeof(attr->type) +
- sizeof(attr->len));
-
- /*
- * Model Desc
- */
- attr = (struct fdmi_attr_s *) curr_ptr;
- attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_MODEL_DESC);
- attr->len = (u16) strlen(fcs_hba_attr->model_desc);
- memcpy(attr->value, fcs_hba_attr->model_desc, attr->len);
- /* variable fields need to be 4 byte aligned */
- attr->len = fc_roundup(attr->len, sizeof(u32));
- curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
- len += attr->len;
- count++;
- attr->len =
- bfa_os_htons(attr->len + sizeof(attr->type) +
- sizeof(attr->len));
-
- /*
- * H/W Version
- */
- if (fcs_hba_attr->hw_version[0] != '\0') {
- attr = (struct fdmi_attr_s *) curr_ptr;
- attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_HW_VERSION);
- attr->len = (u16) strlen(fcs_hba_attr->hw_version);
- memcpy(attr->value, fcs_hba_attr->hw_version, attr->len);
- /* variable fields need to be 4 byte aligned */
- attr->len = fc_roundup(attr->len, sizeof(u32));
- curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
- len += attr->len;
- count++;
- attr->len =
- bfa_os_htons(attr->len + sizeof(attr->type) +
- sizeof(attr->len));
- }
-
- /*
- * Driver Version
- */
- attr = (struct fdmi_attr_s *) curr_ptr;
- attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_DRIVER_VERSION);
- attr->len = (u16) strlen(fcs_hba_attr->driver_version);
- memcpy(attr->value, fcs_hba_attr->driver_version, attr->len);
- /* variable fields need to be 4 byte aligned */
- attr->len = fc_roundup(attr->len, sizeof(u32));
- curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
- len += attr->len;;
- count++;
- attr->len =
- bfa_os_htons(attr->len + sizeof(attr->type) +
- sizeof(attr->len));
-
- /*
- * Option Rom Version
- */
- if (fcs_hba_attr->option_rom_ver[0] != '\0') {
- attr = (struct fdmi_attr_s *) curr_ptr;
- attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_ROM_VERSION);
- attr->len = (u16) strlen(fcs_hba_attr->option_rom_ver);
- memcpy(attr->value, fcs_hba_attr->option_rom_ver, attr->len);
- /* variable fields need to be 4 byte aligned */
- attr->len = fc_roundup(attr->len, sizeof(u32));
- curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
- len += attr->len;
- count++;
- attr->len =
- bfa_os_htons(attr->len + sizeof(attr->type) +
- sizeof(attr->len));
- }
-
- /*
- * f/w Version = driver version
- */
- attr = (struct fdmi_attr_s *) curr_ptr;
- attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_FW_VERSION);
- attr->len = (u16) strlen(fcs_hba_attr->driver_version);
- memcpy(attr->value, fcs_hba_attr->driver_version, attr->len);
- /* variable fields need to be 4 byte aligned */
- attr->len = fc_roundup(attr->len, sizeof(u32));
- curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
- len += attr->len;
- count++;
- attr->len =
- bfa_os_htons(attr->len + sizeof(attr->type) +
- sizeof(attr->len));
-
- /*
- * OS Name
- */
- if (fcs_hba_attr->os_name[0] != '\0') {
- attr = (struct fdmi_attr_s *) curr_ptr;
- attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_OS_NAME);
- attr->len = (u16) strlen(fcs_hba_attr->os_name);
- memcpy(attr->value, fcs_hba_attr->os_name, attr->len);
- /* variable fields need to be 4 byte aligned */
- attr->len = fc_roundup(attr->len, sizeof(u32));
- curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
- len += attr->len;
- count++;
- attr->len =
- bfa_os_htons(attr->len + sizeof(attr->type) +
- sizeof(attr->len));
- }
-
- /*
- * MAX_CT_PAYLOAD
- */
- attr = (struct fdmi_attr_s *) curr_ptr;
- attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_MAX_CT);
- attr->len = sizeof(fcs_hba_attr->max_ct_pyld);
- memcpy(attr->value, &fcs_hba_attr->max_ct_pyld, attr->len);
- len += attr->len;
- count++;
- attr->len =
- bfa_os_htons(attr->len + sizeof(attr->type) +
- sizeof(attr->len));
-
- /*
- * Update size of payload
- */
- len += ((sizeof(attr->type) + sizeof(attr->len)) * count);
-
- rhba->hba_attr_blk.attr_count = bfa_os_htonl(count);
- return len;
-}
-
-static void
-bfa_fcs_port_fdmi_rhba_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
- void *cbarg, bfa_status_t req_status,
- u32 rsp_len, u32 resid_len,
- struct fchs_s *rsp_fchs)
-{
- struct bfa_fcs_port_fdmi_s *fdmi = (struct bfa_fcs_port_fdmi_s *)cbarg;
- struct bfa_fcs_port_s *port = fdmi->ms->port;
- struct ct_hdr_s *cthdr = NULL;
-
- bfa_trc(port->fcs, port->port_cfg.pwwn);
-
- /*
- * Sanity Checks
- */
- if (req_status != BFA_STATUS_OK) {
- bfa_trc(port->fcs, req_status);
- bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
- return;
- }
-
- cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
- cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
-
- if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
- bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
- return;
- }
-
- bfa_trc(port->fcs, cthdr->reason_code);
- bfa_trc(port->fcs, cthdr->exp_code);
- bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
-}
-
-/**
-* RPRT : Register Port
- */
-static void
-bfa_fcs_port_fdmi_send_rprt(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
- struct bfa_fcs_port_fdmi_s *fdmi = fdmi_cbarg;
- struct bfa_fcs_port_s *port = fdmi->ms->port;
- struct fchs_s fchs;
- u16 len, attr_len;
- struct bfa_fcxp_s *fcxp;
- u8 *pyld;
-
- bfa_trc(port->fcs, port->port_cfg.pwwn);
-
- fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
- if (!fcxp) {
- bfa_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
- bfa_fcs_port_fdmi_send_rprt, fdmi);
- return;
- }
- fdmi->fcxp = fcxp;
-
- pyld = bfa_fcxp_get_reqbuf(fcxp);
- bfa_os_memset(pyld, 0, FC_MAX_PDUSZ);
-
- len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_port_get_fcid(port),
- FDMI_RPRT);
-
- attr_len = bfa_fcs_port_fdmi_build_rprt_pyld(fdmi,
- (u8 *) ((struct ct_hdr_s *) pyld + 1));
-
- bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
- FC_CLASS_3, len + attr_len, &fchs,
- bfa_fcs_port_fdmi_rprt_response, (void *)fdmi,
- FC_MAX_PDUSZ, FC_FCCT_TOV);
-
- bfa_sm_send_event(fdmi, FDMISM_EVENT_RPRT_SENT);
-}
-
-/**
- * This routine builds Port Attribute Block that used in RPA, RPRT commands.
- */
-static u16
-bfa_fcs_port_fdmi_build_portattr_block(struct bfa_fcs_port_fdmi_s *fdmi,
- u8 *pyld)
-{
- struct bfa_fcs_fdmi_port_attr_s fcs_port_attr;
- struct fdmi_port_attr_s *port_attrib = (struct fdmi_port_attr_s *) pyld;
- struct fdmi_attr_s *attr;
- u8 *curr_ptr;
- u16 len;
- u8 count = 0;
-
- /*
- * get port attributes
- */
- bfa_fcs_fdmi_get_portattr(fdmi, &fcs_port_attr);
-
- len = sizeof(port_attrib->attr_count);
-
- /*
- * fill out the invididual entries
- */
- curr_ptr = (u8 *) &port_attrib->port_attr;
-
- /*
- * FC4 Types
- */
- attr = (struct fdmi_attr_s *) curr_ptr;
- attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_FC4_TYPES);
- attr->len = sizeof(fcs_port_attr.supp_fc4_types);
- memcpy(attr->value, fcs_port_attr.supp_fc4_types, attr->len);
- curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
- len += attr->len;
- ++count;
- attr->len =
- bfa_os_htons(attr->len + sizeof(attr->type) +
- sizeof(attr->len));
-
- /*
- * Supported Speed
- */
- attr = (struct fdmi_attr_s *) curr_ptr;
- attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_SUPP_SPEED);
- attr->len = sizeof(fcs_port_attr.supp_speed);
- memcpy(attr->value, &fcs_port_attr.supp_speed, attr->len);
- curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
- len += attr->len;
- ++count;
- attr->len =
- bfa_os_htons(attr->len + sizeof(attr->type) +
- sizeof(attr->len));
-
- /*
- * current Port Speed
- */
- attr = (struct fdmi_attr_s *) curr_ptr;
- attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_PORT_SPEED);
- attr->len = sizeof(fcs_port_attr.curr_speed);
- memcpy(attr->value, &fcs_port_attr.curr_speed, attr->len);
- curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
- len += attr->len;
- ++count;
- attr->len =
- bfa_os_htons(attr->len + sizeof(attr->type) +
- sizeof(attr->len));
-
- /*
- * max frame size
- */
- attr = (struct fdmi_attr_s *) curr_ptr;
- attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_FRAME_SIZE);
- attr->len = sizeof(fcs_port_attr.max_frm_size);
- memcpy(attr->value, &fcs_port_attr.max_frm_size, attr->len);
- curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
- len += attr->len;
- ++count;
- attr->len =
- bfa_os_htons(attr->len + sizeof(attr->type) +
- sizeof(attr->len));
-
- /*
- * OS Device Name
- */
- if (fcs_port_attr.os_device_name[0] != '\0') {
- attr = (struct fdmi_attr_s *) curr_ptr;
- attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_DEV_NAME);
- attr->len = (u16) strlen(fcs_port_attr.os_device_name);
- memcpy(attr->value, fcs_port_attr.os_device_name, attr->len);
- /* variable fields need to be 4 byte aligned */
- attr->len = fc_roundup(attr->len, sizeof(u32));
- curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
- len += attr->len;
- ++count;
- attr->len =
- bfa_os_htons(attr->len + sizeof(attr->type) +
- sizeof(attr->len));
-
- }
- /*
- * Host Name
- */
- if (fcs_port_attr.host_name[0] != '\0') {
- attr = (struct fdmi_attr_s *) curr_ptr;
- attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_HOST_NAME);
- attr->len = (u16) strlen(fcs_port_attr.host_name);
- memcpy(attr->value, fcs_port_attr.host_name, attr->len);
- /* variable fields need to be 4 byte aligned */
- attr->len = fc_roundup(attr->len, sizeof(u32));
- curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
- len += attr->len;
- ++count;
- attr->len =
- bfa_os_htons(attr->len + sizeof(attr->type) +
- sizeof(attr->len));
-
- }
-
- /*
- * Update size of payload
- */
- port_attrib->attr_count = bfa_os_htonl(count);
- len += ((sizeof(attr->type) + sizeof(attr->len)) * count);
- return len;
-}
-
-static u16
-bfa_fcs_port_fdmi_build_rprt_pyld(struct bfa_fcs_port_fdmi_s *fdmi,
- u8 *pyld)
-{
- struct bfa_fcs_port_s *port = fdmi->ms->port;
- struct fdmi_rprt_s *rprt = (struct fdmi_rprt_s *) pyld;
- u16 len;
-
- rprt->hba_id = bfa_fcs_port_get_pwwn(bfa_fcs_get_base_port(port->fcs));
- rprt->port_name = bfa_fcs_port_get_pwwn(port);
-
- len = bfa_fcs_port_fdmi_build_portattr_block(fdmi,
- (u8 *) &rprt->port_attr_blk);
-
- len += sizeof(rprt->hba_id) + sizeof(rprt->port_name);
-
- return len;
-}
-
-static void
-bfa_fcs_port_fdmi_rprt_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
- void *cbarg, bfa_status_t req_status,
- u32 rsp_len, u32 resid_len,
- struct fchs_s *rsp_fchs)
-{
- struct bfa_fcs_port_fdmi_s *fdmi = (struct bfa_fcs_port_fdmi_s *)cbarg;
- struct bfa_fcs_port_s *port = fdmi->ms->port;
- struct ct_hdr_s *cthdr = NULL;
-
- bfa_trc(port->fcs, port->port_cfg.pwwn);
-
- /*
- * Sanity Checks
- */
- if (req_status != BFA_STATUS_OK) {
- bfa_trc(port->fcs, req_status);
- bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
- return;
- }
-
- cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
- cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
-
- if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
- bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
- return;
- }
-
- bfa_trc(port->fcs, cthdr->reason_code);
- bfa_trc(port->fcs, cthdr->exp_code);
- bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
-}
-
-/**
-* RPA : Register Port Attributes.
- */
-static void
-bfa_fcs_port_fdmi_send_rpa(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
- struct bfa_fcs_port_fdmi_s *fdmi = fdmi_cbarg;
- struct bfa_fcs_port_s *port = fdmi->ms->port;
- struct fchs_s fchs;
- u16 len, attr_len;
- struct bfa_fcxp_s *fcxp;
- u8 *pyld;
-
- bfa_trc(port->fcs, port->port_cfg.pwwn);
-
- fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
- if (!fcxp) {
- bfa_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
- bfa_fcs_port_fdmi_send_rpa, fdmi);
- return;
- }
- fdmi->fcxp = fcxp;
-
- pyld = bfa_fcxp_get_reqbuf(fcxp);
- bfa_os_memset(pyld, 0, FC_MAX_PDUSZ);
-
- len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_port_get_fcid(port),
- FDMI_RPA);
-
- attr_len = bfa_fcs_port_fdmi_build_rpa_pyld(fdmi,
- (u8 *) ((struct ct_hdr_s *) pyld + 1));
-
- bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
- FC_CLASS_3, len + attr_len, &fchs,
- bfa_fcs_port_fdmi_rpa_response, (void *)fdmi,
- FC_MAX_PDUSZ, FC_FCCT_TOV);
-
- bfa_sm_send_event(fdmi, FDMISM_EVENT_RPA_SENT);
-}
-
-static u16
-bfa_fcs_port_fdmi_build_rpa_pyld(struct bfa_fcs_port_fdmi_s *fdmi,
- u8 *pyld)
-{
- struct bfa_fcs_port_s *port = fdmi->ms->port;
- struct fdmi_rpa_s *rpa = (struct fdmi_rpa_s *) pyld;
- u16 len;
-
- rpa->port_name = bfa_fcs_port_get_pwwn(port);
-
- len = bfa_fcs_port_fdmi_build_portattr_block(fdmi,
- (u8 *) &rpa->port_attr_blk);
-
- len += sizeof(rpa->port_name);
-
- return len;
-}
-
-static void
-bfa_fcs_port_fdmi_rpa_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
- void *cbarg, bfa_status_t req_status,
- u32 rsp_len, u32 resid_len,
- struct fchs_s *rsp_fchs)
-{
- struct bfa_fcs_port_fdmi_s *fdmi = (struct bfa_fcs_port_fdmi_s *)cbarg;
- struct bfa_fcs_port_s *port = fdmi->ms->port;
- struct ct_hdr_s *cthdr = NULL;
-
- bfa_trc(port->fcs, port->port_cfg.pwwn);
-
- /*
- * Sanity Checks
- */
- if (req_status != BFA_STATUS_OK) {
- bfa_trc(port->fcs, req_status);
- bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
- return;
- }
-
- cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
- cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
-
- if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
- bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
- return;
- }
-
- bfa_trc(port->fcs, cthdr->reason_code);
- bfa_trc(port->fcs, cthdr->exp_code);
- bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
-}
-
-static void
-bfa_fcs_port_fdmi_timeout(void *arg)
-{
- struct bfa_fcs_port_fdmi_s *fdmi = (struct bfa_fcs_port_fdmi_s *)arg;
-
- bfa_sm_send_event(fdmi, FDMISM_EVENT_TIMEOUT);
-}
-
-static void
-bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_port_fdmi_s *fdmi,
- struct bfa_fcs_fdmi_hba_attr_s *hba_attr)
-{
- struct bfa_fcs_port_s *port = fdmi->ms->port;
- struct bfa_fcs_driver_info_s *driver_info = &port->fcs->driver_info;
-
- bfa_os_memset(hba_attr, 0, sizeof(struct bfa_fcs_fdmi_hba_attr_s));
-
- bfa_ioc_get_adapter_manufacturer(&port->fcs->bfa->ioc,
- hba_attr->manufacturer);
- bfa_ioc_get_adapter_serial_num(&port->fcs->bfa->ioc,
- hba_attr->serial_num);
- bfa_ioc_get_adapter_model(&port->fcs->bfa->ioc, hba_attr->model);
- bfa_ioc_get_adapter_model(&port->fcs->bfa->ioc, hba_attr->model_desc);
- bfa_ioc_get_pci_chip_rev(&port->fcs->bfa->ioc, hba_attr->hw_version);
- bfa_ioc_get_adapter_optrom_ver(&port->fcs->bfa->ioc,
- hba_attr->option_rom_ver);
- bfa_ioc_get_adapter_fw_ver(&port->fcs->bfa->ioc, hba_attr->fw_version);
-
- strncpy(hba_attr->driver_version, (char *)driver_info->version,
- sizeof(hba_attr->driver_version));
-
- strncpy(hba_attr->os_name, driver_info->host_os_name,
- sizeof(hba_attr->os_name));
-
- /*
- * If there is a patch level, append it to the os name along with a
- * separator
- */
- if (driver_info->host_os_patch[0] != '\0') {
- strncat(hba_attr->os_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
- sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
- strncat(hba_attr->os_name, driver_info->host_os_patch,
- sizeof(driver_info->host_os_patch));
- }
-
- hba_attr->max_ct_pyld = bfa_os_htonl(FC_MAX_PDUSZ);
-
-}
-
-static void
-bfa_fcs_fdmi_get_portattr(struct bfa_fcs_port_fdmi_s *fdmi,
- struct bfa_fcs_fdmi_port_attr_s *port_attr)
-{
- struct bfa_fcs_port_s *port = fdmi->ms->port;
- struct bfa_fcs_driver_info_s *driver_info = &port->fcs->driver_info;
- struct bfa_pport_attr_s pport_attr;
-
- bfa_os_memset(port_attr, 0, sizeof(struct bfa_fcs_fdmi_port_attr_s));
-
- /*
- * get pport attributes from hal
- */
- bfa_fcport_get_attr(port->fcs->bfa, &pport_attr);
-
- /*
- * get FC4 type Bitmask
- */
- fc_get_fc4type_bitmask(FC_TYPE_FCP, port_attr->supp_fc4_types);
-
- /*
- * Supported Speeds
- */
- port_attr->supp_speed = bfa_os_htonl(BFA_FCS_FDMI_SUPORTED_SPEEDS);
-
- /*
- * Current Speed
- */
- port_attr->curr_speed = bfa_os_htonl(pport_attr.speed);
-
- /*
- * Max PDU Size.
- */
- port_attr->max_frm_size = bfa_os_htonl(FC_MAX_PDUSZ);
-
- /*
- * OS device Name
- */
- strncpy(port_attr->os_device_name, (char *)driver_info->os_device_name,
- sizeof(port_attr->os_device_name));
-
- /*
- * Host name
- */
- strncpy(port_attr->host_name, (char *)driver_info->host_machine_name,
- sizeof(port_attr->host_name));
-
-}
-
-
-void
-bfa_fcs_port_fdmi_init(struct bfa_fcs_port_ms_s *ms)
-{
- struct bfa_fcs_port_fdmi_s *fdmi = &ms->fdmi;
-
- fdmi->ms = ms;
- if (ms->port->fcs->fdmi_enabled)
- bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
- else
- bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_disabled);
-}
-
-void
-bfa_fcs_port_fdmi_offline(struct bfa_fcs_port_ms_s *ms)
-{
- struct bfa_fcs_port_fdmi_s *fdmi = &ms->fdmi;
-
- fdmi->ms = ms;
- bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_OFFLINE);
-}
-
-void
-bfa_fcs_port_fdmi_online(struct bfa_fcs_port_ms_s *ms)
-{
- struct bfa_fcs_port_fdmi_s *fdmi = &ms->fdmi;
-
- fdmi->ms = ms;
- bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_ONLINE);
-}
diff --git a/drivers/scsi/bfa/include/aen/bfa_aen.h b/drivers/scsi/bfa/include/aen/bfa_aen.h
deleted file mode 100644
index 6abbab005db6..000000000000
--- a/drivers/scsi/bfa/include/aen/bfa_aen.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-#ifndef __BFA_AEN_H__
-#define __BFA_AEN_H__
-
-#include "defs/bfa_defs_aen.h"
-#include "defs/bfa_defs_status.h"
-#include "cs/bfa_debug.h"
-
-#define BFA_AEN_MAX_ENTRY 512
-
-extern int bfa_aen_max_cfg_entry;
-struct bfa_aen_s {
- void *bfad;
- int max_entry;
- int write_index;
- int read_index;
- int bfad_num;
- int seq_num;
- void (*aen_cb_notify)(void *bfad);
- void (*gettimeofday)(struct bfa_timeval_s *tv);
- struct bfa_trc_mod_s *trcmod;
- int app_ri[BFA_AEN_MAX_APP]; /* For multiclient support */
- struct bfa_aen_entry_s list[BFA_AEN_MAX_ENTRY]; /* Must be the last */
-};
-
-
-/**
- * Public APIs
- */
-static inline void
-bfa_aen_set_max_cfg_entry(int max_entry)
-{
- bfa_aen_max_cfg_entry = max_entry;
-}
-
-static inline int
-bfa_aen_get_max_cfg_entry(void)
-{
- return bfa_aen_max_cfg_entry;
-}
-
-static inline int
-bfa_aen_get_meminfo(void)
-{
- return sizeof(struct bfa_aen_entry_s) * bfa_aen_get_max_cfg_entry();
-}
-
-static inline int
-bfa_aen_get_wi(struct bfa_aen_s *aen)
-{
- return aen->write_index;
-}
-
-static inline int
-bfa_aen_get_ri(struct bfa_aen_s *aen)
-{
- return aen->read_index;
-}
-
-static inline int
-bfa_aen_fetch_count(struct bfa_aen_s *aen, enum bfa_aen_app app_id)
-{
- bfa_assert((app_id < BFA_AEN_MAX_APP) && (app_id >= bfa_aen_app_bcu));
- return ((aen->write_index + aen->max_entry) - aen->app_ri[app_id])
- % aen->max_entry;
-}
-
-int bfa_aen_init(struct bfa_aen_s *aen, struct bfa_trc_mod_s *trcmod,
- void *bfad, int bfad_num, void (*aen_cb_notify)(void *),
- void (*gettimeofday)(struct bfa_timeval_s *));
-
-void bfa_aen_post(struct bfa_aen_s *aen, enum bfa_aen_category aen_category,
- int aen_type, union bfa_aen_data_u *aen_data);
-
-bfa_status_t bfa_aen_fetch(struct bfa_aen_s *aen,
- struct bfa_aen_entry_s *aen_entry,
- int entry_req, enum bfa_aen_app app_id, int *entry_ret);
-
-int bfa_aen_get_inst(struct bfa_aen_s *aen);
-
-#endif /* __BFA_AEN_H__ */
diff --git a/drivers/scsi/bfa/include/aen/bfa_aen_adapter.h b/drivers/scsi/bfa/include/aen/bfa_aen_adapter.h
deleted file mode 100644
index 260d3ea1cab3..000000000000
--- a/drivers/scsi/bfa/include/aen/bfa_aen_adapter.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/* messages define for BFA_AEN_CAT_ADAPTER Module */
-#ifndef __bfa_aen_adapter_h__
-#define __bfa_aen_adapter_h__
-
-#include <cs/bfa_log.h>
-#include <defs/bfa_defs_aen.h>
-
-#define BFA_AEN_ADAPTER_ADD \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_ADAPTER, BFA_ADAPTER_AEN_ADD)
-#define BFA_AEN_ADAPTER_REMOVE \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_ADAPTER, BFA_ADAPTER_AEN_REMOVE)
-
-#endif
-
diff --git a/drivers/scsi/bfa/include/aen/bfa_aen_audit.h b/drivers/scsi/bfa/include/aen/bfa_aen_audit.h
deleted file mode 100644
index 12cd7aab5d53..000000000000
--- a/drivers/scsi/bfa/include/aen/bfa_aen_audit.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/* messages define for BFA_AEN_CAT_AUDIT Module */
-#ifndef __bfa_aen_audit_h__
-#define __bfa_aen_audit_h__
-
-#include <cs/bfa_log.h>
-#include <defs/bfa_defs_aen.h>
-
-#define BFA_AEN_AUDIT_AUTH_ENABLE \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_AUDIT, BFA_AUDIT_AEN_AUTH_ENABLE)
-#define BFA_AEN_AUDIT_AUTH_DISABLE \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_AUDIT, BFA_AUDIT_AEN_AUTH_DISABLE)
-
-#endif
-
diff --git a/drivers/scsi/bfa/include/aen/bfa_aen_ethport.h b/drivers/scsi/bfa/include/aen/bfa_aen_ethport.h
deleted file mode 100644
index 507d0b58d149..000000000000
--- a/drivers/scsi/bfa/include/aen/bfa_aen_ethport.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/* messages define for BFA_AEN_CAT_ETHPORT Module */
-#ifndef __bfa_aen_ethport_h__
-#define __bfa_aen_ethport_h__
-
-#include <cs/bfa_log.h>
-#include <defs/bfa_defs_aen.h>
-
-#define BFA_AEN_ETHPORT_LINKUP \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_ETHPORT, BFA_ETHPORT_AEN_LINKUP)
-#define BFA_AEN_ETHPORT_LINKDOWN \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_ETHPORT, BFA_ETHPORT_AEN_LINKDOWN)
-#define BFA_AEN_ETHPORT_ENABLE \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_ETHPORT, BFA_ETHPORT_AEN_ENABLE)
-#define BFA_AEN_ETHPORT_DISABLE \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_ETHPORT, BFA_ETHPORT_AEN_DISABLE)
-
-#endif
-
diff --git a/drivers/scsi/bfa/include/aen/bfa_aen_ioc.h b/drivers/scsi/bfa/include/aen/bfa_aen_ioc.h
deleted file mode 100644
index 4daf96faa266..000000000000
--- a/drivers/scsi/bfa/include/aen/bfa_aen_ioc.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/* messages define for BFA_AEN_CAT_IOC Module */
-#ifndef __bfa_aen_ioc_h__
-#define __bfa_aen_ioc_h__
-
-#include <cs/bfa_log.h>
-#include <defs/bfa_defs_aen.h>
-
-#define BFA_AEN_IOC_HBGOOD \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, BFA_IOC_AEN_HBGOOD)
-#define BFA_AEN_IOC_HBFAIL \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, BFA_IOC_AEN_HBFAIL)
-#define BFA_AEN_IOC_ENABLE \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, BFA_IOC_AEN_ENABLE)
-#define BFA_AEN_IOC_DISABLE \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, BFA_IOC_AEN_DISABLE)
-#define BFA_AEN_IOC_FWMISMATCH \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, BFA_IOC_AEN_FWMISMATCH)
-#define BFA_AEN_IOC_FWCFG_ERROR \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, BFA_IOC_AEN_FWCFG_ERROR)
-#define BFA_AEN_IOC_INVALID_VENDOR \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, BFA_IOC_AEN_INVALID_VENDOR)
-#define BFA_AEN_IOC_INVALID_NWWN \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, BFA_IOC_AEN_INVALID_NWWN)
-#define BFA_AEN_IOC_INVALID_PWWN \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, BFA_IOC_AEN_INVALID_PWWN)
-
-#endif
-
diff --git a/drivers/scsi/bfa/include/aen/bfa_aen_itnim.h b/drivers/scsi/bfa/include/aen/bfa_aen_itnim.h
deleted file mode 100644
index a7d8ddcfef99..000000000000
--- a/drivers/scsi/bfa/include/aen/bfa_aen_itnim.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/* messages define for BFA_AEN_CAT_ITNIM Module */
-#ifndef __bfa_aen_itnim_h__
-#define __bfa_aen_itnim_h__
-
-#include <cs/bfa_log.h>
-#include <defs/bfa_defs_aen.h>
-
-#define BFA_AEN_ITNIM_ONLINE \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_ITNIM, BFA_ITNIM_AEN_ONLINE)
-#define BFA_AEN_ITNIM_OFFLINE \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_ITNIM, BFA_ITNIM_AEN_OFFLINE)
-#define BFA_AEN_ITNIM_DISCONNECT \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_ITNIM, BFA_ITNIM_AEN_DISCONNECT)
-
-#endif
-
diff --git a/drivers/scsi/bfa/include/aen/bfa_aen_lport.h b/drivers/scsi/bfa/include/aen/bfa_aen_lport.h
deleted file mode 100644
index 5a8ebb65193f..000000000000
--- a/drivers/scsi/bfa/include/aen/bfa_aen_lport.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/* messages define for BFA_AEN_CAT_LPORT Module */
-#ifndef __bfa_aen_lport_h__
-#define __bfa_aen_lport_h__
-
-#include <cs/bfa_log.h>
-#include <defs/bfa_defs_aen.h>
-
-#define BFA_AEN_LPORT_NEW \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_NEW)
-#define BFA_AEN_LPORT_DELETE \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_DELETE)
-#define BFA_AEN_LPORT_ONLINE \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_ONLINE)
-#define BFA_AEN_LPORT_OFFLINE \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_OFFLINE)
-#define BFA_AEN_LPORT_DISCONNECT \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_DISCONNECT)
-#define BFA_AEN_LPORT_NEW_PROP \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_NEW_PROP)
-#define BFA_AEN_LPORT_DELETE_PROP \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_DELETE_PROP)
-#define BFA_AEN_LPORT_NEW_STANDARD \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_NEW_STANDARD)
-#define BFA_AEN_LPORT_DELETE_STANDARD \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_DELETE_STANDARD)
-#define BFA_AEN_LPORT_NPIV_DUP_WWN \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_NPIV_DUP_WWN)
-#define BFA_AEN_LPORT_NPIV_FABRIC_MAX \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_NPIV_FABRIC_MAX)
-#define BFA_AEN_LPORT_NPIV_UNKNOWN \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_NPIV_UNKNOWN)
-
-#endif
-
diff --git a/drivers/scsi/bfa/include/aen/bfa_aen_port.h b/drivers/scsi/bfa/include/aen/bfa_aen_port.h
deleted file mode 100644
index 9add905a622d..000000000000
--- a/drivers/scsi/bfa/include/aen/bfa_aen_port.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/* messages define for BFA_AEN_CAT_PORT Module */
-#ifndef __bfa_aen_port_h__
-#define __bfa_aen_port_h__
-
-#include <cs/bfa_log.h>
-#include <defs/bfa_defs_aen.h>
-
-#define BFA_AEN_PORT_ONLINE \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_ONLINE)
-#define BFA_AEN_PORT_OFFLINE \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_OFFLINE)
-#define BFA_AEN_PORT_RLIR \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_RLIR)
-#define BFA_AEN_PORT_SFP_INSERT \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_SFP_INSERT)
-#define BFA_AEN_PORT_SFP_REMOVE \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_SFP_REMOVE)
-#define BFA_AEN_PORT_SFP_POM \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_SFP_POM)
-#define BFA_AEN_PORT_ENABLE \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_ENABLE)
-#define BFA_AEN_PORT_DISABLE \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_DISABLE)
-#define BFA_AEN_PORT_AUTH_ON \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_AUTH_ON)
-#define BFA_AEN_PORT_AUTH_OFF \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_AUTH_OFF)
-#define BFA_AEN_PORT_DISCONNECT \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_DISCONNECT)
-#define BFA_AEN_PORT_QOS_NEG \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_QOS_NEG)
-#define BFA_AEN_PORT_FABRIC_NAME_CHANGE \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_FABRIC_NAME_CHANGE)
-#define BFA_AEN_PORT_SFP_ACCESS_ERROR \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_SFP_ACCESS_ERROR)
-#define BFA_AEN_PORT_SFP_UNSUPPORT \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_SFP_UNSUPPORT)
-
-#endif
-
diff --git a/drivers/scsi/bfa/include/aen/bfa_aen_rport.h b/drivers/scsi/bfa/include/aen/bfa_aen_rport.h
deleted file mode 100644
index 7e4be1fd5e15..000000000000
--- a/drivers/scsi/bfa/include/aen/bfa_aen_rport.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/* messages define for BFA_AEN_CAT_RPORT Module */
-#ifndef __bfa_aen_rport_h__
-#define __bfa_aen_rport_h__
-
-#include <cs/bfa_log.h>
-#include <defs/bfa_defs_aen.h>
-
-#define BFA_AEN_RPORT_ONLINE \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_RPORT, BFA_RPORT_AEN_ONLINE)
-#define BFA_AEN_RPORT_OFFLINE \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_RPORT, BFA_RPORT_AEN_OFFLINE)
-#define BFA_AEN_RPORT_DISCONNECT \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_RPORT, BFA_RPORT_AEN_DISCONNECT)
-#define BFA_AEN_RPORT_QOS_PRIO \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_RPORT, BFA_RPORT_AEN_QOS_PRIO)
-#define BFA_AEN_RPORT_QOS_FLOWID \
- BFA_LOG_CREATE_ID(BFA_AEN_CAT_RPORT, BFA_RPORT_AEN_QOS_FLOWID)
-
-#endif
-
diff --git a/drivers/scsi/bfa/include/bfa.h b/drivers/scsi/bfa/include/bfa.h
deleted file mode 100644
index d52b32f5695c..000000000000
--- a/drivers/scsi/bfa/include/bfa.h
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-#ifndef __BFA_H__
-#define __BFA_H__
-
-#include <bfa_os_inc.h>
-#include <cs/bfa_debug.h>
-#include <cs/bfa_q.h>
-#include <cs/bfa_trc.h>
-#include <cs/bfa_log.h>
-#include <cs/bfa_plog.h>
-#include <defs/bfa_defs_status.h>
-#include <defs/bfa_defs_ioc.h>
-#include <defs/bfa_defs_iocfc.h>
-#include <aen/bfa_aen.h>
-#include <bfi/bfi.h>
-
-struct bfa_s;
-#include <bfa_intr_priv.h>
-
-struct bfa_pcidev_s;
-
-/**
- * PCI devices supported by the current BFA
- */
-struct bfa_pciid_s {
- u16 device_id;
- u16 vendor_id;
-};
-
-extern char bfa_version[];
-
-/**
- * BFA Power Mgmt Commands
- */
-enum bfa_pm_cmd {
- BFA_PM_CTL_D0 = 0,
- BFA_PM_CTL_D1 = 1,
- BFA_PM_CTL_D2 = 2,
- BFA_PM_CTL_D3 = 3,
-};
-
-/**
- * BFA memory resources
- */
-enum bfa_mem_type {
- BFA_MEM_TYPE_KVA = 1, /*! Kernel Virtual Memory *(non-dma-able) */
- BFA_MEM_TYPE_DMA = 2, /*! DMA-able memory */
- BFA_MEM_TYPE_MAX = BFA_MEM_TYPE_DMA,
-};
-
-struct bfa_mem_elem_s {
- enum bfa_mem_type mem_type; /* see enum bfa_mem_type */
- u32 mem_len; /* Total Length in Bytes */
- u8 *kva; /* kernel virtual address */
- u64 dma; /* dma address if DMA memory */
- u8 *kva_curp; /* kva allocation cursor */
- u64 dma_curp; /* dma allocation cursor */
-};
-
-struct bfa_meminfo_s {
- struct bfa_mem_elem_s meminfo[BFA_MEM_TYPE_MAX];
-};
-#define bfa_meminfo_kva(_m) \
- ((_m)->meminfo[BFA_MEM_TYPE_KVA - 1].kva_curp)
-#define bfa_meminfo_dma_virt(_m) \
- ((_m)->meminfo[BFA_MEM_TYPE_DMA - 1].kva_curp)
-#define bfa_meminfo_dma_phys(_m) \
- ((_m)->meminfo[BFA_MEM_TYPE_DMA - 1].dma_curp)
-
-/**
- * Generic Scatter Gather Element used by driver
- */
-struct bfa_sge_s {
- u32 sg_len;
- void *sg_addr;
-};
-
-#define bfa_sge_to_be(__sge) do { \
- ((u32 *)(__sge))[0] = bfa_os_htonl(((u32 *)(__sge))[0]); \
- ((u32 *)(__sge))[1] = bfa_os_htonl(((u32 *)(__sge))[1]); \
- ((u32 *)(__sge))[2] = bfa_os_htonl(((u32 *)(__sge))[2]); \
-} while (0)
-
-
-/*
- * bfa stats interfaces
- */
-#define bfa_stats(_mod, _stats) ((_mod)->stats._stats++)
-
-#define bfa_ioc_get_stats(__bfa, __ioc_stats) \
- bfa_ioc_fetch_stats(&(__bfa)->ioc, __ioc_stats)
-#define bfa_ioc_clear_stats(__bfa) \
- bfa_ioc_clr_stats(&(__bfa)->ioc)
-#define bfa_get_nports(__bfa) \
- bfa_ioc_get_nports(&(__bfa)->ioc)
-#define bfa_get_adapter_manufacturer(__bfa, __manufacturer) \
- bfa_ioc_get_adapter_manufacturer(&(__bfa)->ioc, __manufacturer)
-#define bfa_get_adapter_model(__bfa, __model) \
- bfa_ioc_get_adapter_model(&(__bfa)->ioc, __model)
-#define bfa_get_adapter_serial_num(__bfa, __serial_num) \
- bfa_ioc_get_adapter_serial_num(&(__bfa)->ioc, __serial_num)
-#define bfa_get_adapter_fw_ver(__bfa, __fw_ver) \
- bfa_ioc_get_adapter_fw_ver(&(__bfa)->ioc, __fw_ver)
-#define bfa_get_adapter_optrom_ver(__bfa, __optrom_ver) \
- bfa_ioc_get_adapter_optrom_ver(&(__bfa)->ioc, __optrom_ver)
-#define bfa_get_pci_chip_rev(__bfa, __chip_rev) \
- bfa_ioc_get_pci_chip_rev(&(__bfa)->ioc, __chip_rev)
-#define bfa_get_ioc_state(__bfa) \
- bfa_ioc_get_state(&(__bfa)->ioc)
-#define bfa_get_type(__bfa) \
- bfa_ioc_get_type(&(__bfa)->ioc)
-#define bfa_get_mac(__bfa) \
- bfa_ioc_get_mac(&(__bfa)->ioc)
-#define bfa_get_mfg_mac(__bfa) \
- bfa_ioc_get_mfg_mac(&(__bfa)->ioc)
-#define bfa_get_fw_clock_res(__bfa) \
- ((__bfa)->iocfc.cfgrsp->fwcfg.fw_tick_res)
-
-/*
- * bfa API functions
- */
-void bfa_get_pciids(struct bfa_pciid_s **pciids, int *npciids);
-void bfa_cfg_get_default(struct bfa_iocfc_cfg_s *cfg);
-void bfa_cfg_get_min(struct bfa_iocfc_cfg_s *cfg);
-void bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg,
- struct bfa_meminfo_s *meminfo);
-void bfa_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
- struct bfa_meminfo_s *meminfo,
- struct bfa_pcidev_s *pcidev);
-void bfa_init_trc(struct bfa_s *bfa, struct bfa_trc_mod_s *trcmod);
-void bfa_init_log(struct bfa_s *bfa, struct bfa_log_mod_s *logmod);
-void bfa_init_aen(struct bfa_s *bfa, struct bfa_aen_s *aen);
-void bfa_init_plog(struct bfa_s *bfa, struct bfa_plog_s *plog);
-void bfa_detach(struct bfa_s *bfa);
-void bfa_init(struct bfa_s *bfa);
-void bfa_start(struct bfa_s *bfa);
-void bfa_stop(struct bfa_s *bfa);
-void bfa_attach_fcs(struct bfa_s *bfa);
-void bfa_cb_init(void *bfad, bfa_status_t status);
-void bfa_cb_stop(void *bfad, bfa_status_t status);
-void bfa_cb_updateq(void *bfad, bfa_status_t status);
-
-bfa_boolean_t bfa_intx(struct bfa_s *bfa);
-void bfa_isr_enable(struct bfa_s *bfa);
-void bfa_isr_disable(struct bfa_s *bfa);
-void bfa_msix_getvecs(struct bfa_s *bfa, u32 *msix_vecs_bmap,
- u32 *num_vecs, u32 *max_vec_bit);
-#define bfa_msix(__bfa, __vec) ((__bfa)->msix.handler[__vec](__bfa, __vec))
-
-void bfa_comp_deq(struct bfa_s *bfa, struct list_head *comp_q);
-void bfa_comp_process(struct bfa_s *bfa, struct list_head *comp_q);
-void bfa_comp_free(struct bfa_s *bfa, struct list_head *comp_q);
-
-typedef void (*bfa_cb_ioc_t) (void *cbarg, enum bfa_status status);
-void bfa_iocfc_get_attr(struct bfa_s *bfa, struct bfa_iocfc_attr_s *attr);
-bfa_status_t bfa_iocfc_get_stats(struct bfa_s *bfa,
- struct bfa_iocfc_stats_s *stats,
- bfa_cb_ioc_t cbfn, void *cbarg);
-bfa_status_t bfa_iocfc_clear_stats(struct bfa_s *bfa,
- bfa_cb_ioc_t cbfn, void *cbarg);
-void bfa_get_attr(struct bfa_s *bfa, struct bfa_ioc_attr_s *ioc_attr);
-
-void bfa_adapter_get_attr(struct bfa_s *bfa,
- struct bfa_adapter_attr_s *ad_attr);
-u64 bfa_adapter_get_id(struct bfa_s *bfa);
-
-bfa_status_t bfa_iocfc_israttr_set(struct bfa_s *bfa,
- struct bfa_iocfc_intr_attr_s *attr);
-
-void bfa_iocfc_enable(struct bfa_s *bfa);
-void bfa_iocfc_disable(struct bfa_s *bfa);
-void bfa_ioc_auto_recover(bfa_boolean_t auto_recover);
-void bfa_chip_reset(struct bfa_s *bfa);
-void bfa_cb_ioc_disable(void *bfad);
-void bfa_timer_tick(struct bfa_s *bfa);
-#define bfa_timer_start(_bfa, _timer, _timercb, _arg, _timeout) \
- bfa_timer_begin(&(_bfa)->timer_mod, _timer, _timercb, _arg, _timeout)
-
-/*
- * BFA debug API functions
- */
-bfa_status_t bfa_debug_fwtrc(struct bfa_s *bfa, void *trcdata, int *trclen);
-bfa_status_t bfa_debug_fwsave(struct bfa_s *bfa, void *trcdata, int *trclen);
-void bfa_debug_fwsave_clear(struct bfa_s *bfa);
-
-#include "bfa_priv.h"
-
-#endif /* __BFA_H__ */
diff --git a/drivers/scsi/bfa/include/bfa_fcpim.h b/drivers/scsi/bfa/include/bfa_fcpim.h
deleted file mode 100644
index 4bc9453081df..000000000000
--- a/drivers/scsi/bfa/include/bfa_fcpim.h
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_FCPIM_H__
-#define __BFA_FCPIM_H__
-
-#include <bfa.h>
-#include <bfa_svc.h>
-#include <bfi/bfi_fcpim.h>
-#include <defs/bfa_defs_fcpim.h>
-
-/*
- * forward declarations
- */
-struct bfa_itnim_s;
-struct bfa_ioim_s;
-struct bfa_tskim_s;
-struct bfad_ioim_s;
-struct bfad_tskim_s;
-
-/*
- * bfa fcpim module API functions
- */
-void bfa_fcpim_path_tov_set(struct bfa_s *bfa, u16 path_tov);
-u16 bfa_fcpim_path_tov_get(struct bfa_s *bfa);
-void bfa_fcpim_qdepth_set(struct bfa_s *bfa, u16 q_depth);
-u16 bfa_fcpim_qdepth_get(struct bfa_s *bfa);
-bfa_status_t bfa_fcpim_get_modstats(struct bfa_s *bfa,
- struct bfa_fcpim_stats_s *modstats);
-bfa_status_t bfa_fcpim_clr_modstats(struct bfa_s *bfa);
-void bfa_fcpim_set_ioredirect(struct bfa_s *bfa, bfa_boolean_t state);
-void bfa_fcpim_update_ioredirect(struct bfa_s *bfa);
-void bfa_cb_ioredirect_state_change(void *hcb_bfad, bfa_boolean_t ioredirect);
-
-#define bfa_fcpim_ioredirect_enabled(__bfa) \
- (((struct bfa_fcpim_mod_s *)(BFA_FCPIM_MOD(__bfa)))->ioredirect)
-
-#define bfa_fcpim_get_next_reqq(__bfa, __qid) \
-{ \
- struct bfa_fcpim_mod_s *__fcpim = BFA_FCPIM_MOD(__bfa); \
- __fcpim->reqq++; \
- __fcpim->reqq &= (BFI_IOC_MAX_CQS - 1); \
- *(__qid) = __fcpim->reqq; \
-}
-
-#define bfa_iocfc_map_msg_to_qid(__msg, __qid) \
- *(__qid) = (u8)((__msg) & (BFI_IOC_MAX_CQS - 1));
-
-
-/*
- * bfa itnim API functions
- */
-struct bfa_itnim_s *bfa_itnim_create(struct bfa_s *bfa,
- struct bfa_rport_s *rport, void *itnim);
-void bfa_itnim_delete(struct bfa_itnim_s *itnim);
-void bfa_itnim_online(struct bfa_itnim_s *itnim,
- bfa_boolean_t seq_rec);
-void bfa_itnim_offline(struct bfa_itnim_s *itnim);
-void bfa_itnim_get_stats(struct bfa_itnim_s *itnim,
- struct bfa_itnim_hal_stats_s *stats);
-void bfa_itnim_clear_stats(struct bfa_itnim_s *itnim);
-
-#define bfa_itnim_get_reqq(__ioim) (((struct bfa_ioim_s *)__ioim)->itnim->reqq)
-
-/**
- * BFA completion callback for bfa_itnim_online().
- *
- * @param[in] itnim FCS or driver itnim instance
- *
- * return None
- */
-void bfa_cb_itnim_online(void *itnim);
-
-/**
- * BFA completion callback for bfa_itnim_offline().
- *
- * @param[in] itnim FCS or driver itnim instance
- *
- * return None
- */
-void bfa_cb_itnim_offline(void *itnim);
-void bfa_cb_itnim_tov_begin(void *itnim);
-void bfa_cb_itnim_tov(void *itnim);
-
-/**
- * BFA notification to FCS/driver for second level error recovery.
- *
- * Atleast one I/O request has timedout and target is unresponsive to
- * repeated abort requests. Second level error recovery should be initiated
- * by starting implicit logout and recovery procedures.
- *
- * @param[in] itnim FCS or driver itnim instance
- *
- * return None
- */
-void bfa_cb_itnim_sler(void *itnim);
-
-/*
- * bfa ioim API functions
- */
-struct bfa_ioim_s *bfa_ioim_alloc(struct bfa_s *bfa,
- struct bfad_ioim_s *dio,
- struct bfa_itnim_s *itnim,
- u16 nsgles);
-
-void bfa_ioim_free(struct bfa_ioim_s *ioim);
-void bfa_ioim_start(struct bfa_ioim_s *ioim);
-void bfa_ioim_abort(struct bfa_ioim_s *ioim);
-void bfa_ioim_delayed_comp(struct bfa_ioim_s *ioim,
- bfa_boolean_t iotov);
-
-
-/**
- * I/O completion notification.
- *
- * @param[in] dio driver IO structure
- * @param[in] io_status IO completion status
- * @param[in] scsi_status SCSI status returned by target
- * @param[in] sns_len SCSI sense length, 0 if none
- * @param[in] sns_info SCSI sense data, if any
- * @param[in] residue Residual length
- *
- * @return None
- */
-void bfa_cb_ioim_done(void *bfad, struct bfad_ioim_s *dio,
- enum bfi_ioim_status io_status,
- u8 scsi_status, int sns_len,
- u8 *sns_info, s32 residue);
-
-/**
- * I/O good completion notification.
- *
- * @param[in] dio driver IO structure
- *
- * @return None
- */
-void bfa_cb_ioim_good_comp(void *bfad, struct bfad_ioim_s *dio);
-
-/**
- * I/O abort completion notification
- *
- * @param[in] dio driver IO that was aborted
- *
- * @return None
- */
-void bfa_cb_ioim_abort(void *bfad, struct bfad_ioim_s *dio);
-void bfa_cb_ioim_resfree(void *hcb_bfad);
-
-void bfa_cb_ioim_resfree(void *hcb_bfad);
-
-/*
- * bfa tskim API functions
- */
-struct bfa_tskim_s *bfa_tskim_alloc(struct bfa_s *bfa,
- struct bfad_tskim_s *dtsk);
-void bfa_tskim_free(struct bfa_tskim_s *tskim);
-void bfa_tskim_start(struct bfa_tskim_s *tskim,
- struct bfa_itnim_s *itnim, lun_t lun,
- enum fcp_tm_cmnd tm, u8 t_secs);
-void bfa_cb_tskim_done(void *bfad, struct bfad_tskim_s *dtsk,
- enum bfi_tskim_status tsk_status);
-
-#endif /* __BFA_FCPIM_H__ */
diff --git a/drivers/scsi/bfa/include/bfa_fcptm.h b/drivers/scsi/bfa/include/bfa_fcptm.h
deleted file mode 100644
index 5f5ffe0bb1bb..000000000000
--- a/drivers/scsi/bfa/include/bfa_fcptm.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_FCPTM_H__
-#define __BFA_FCPTM_H__
-
-#include <bfa.h>
-#include <bfa_svc.h>
-#include <bfi/bfi_fcptm.h>
-
-/*
- * forward declarations
- */
-struct bfa_tin_s;
-struct bfa_iotm_s;
-struct bfa_tsktm_s;
-
-/*
- * bfa fcptm module API functions
- */
-void bfa_fcptm_path_tov_set(struct bfa_s *bfa, u16 path_tov);
-u16 bfa_fcptm_path_tov_get(struct bfa_s *bfa);
-void bfa_fcptm_qdepth_set(struct bfa_s *bfa, u16 q_depth);
-u16 bfa_fcptm_qdepth_get(struct bfa_s *bfa);
-
-/*
- * bfa tin API functions
- */
-void bfa_tin_get_stats(struct bfa_tin_s *tin, struct bfa_tin_stats_s *stats);
-void bfa_tin_clear_stats(struct bfa_tin_s *tin);
-
-#endif /* __BFA_FCPTM_H__ */
-
diff --git a/drivers/scsi/bfa/include/bfa_svc.h b/drivers/scsi/bfa/include/bfa_svc.h
deleted file mode 100644
index 7840943d73b0..000000000000
--- a/drivers/scsi/bfa/include/bfa_svc.h
+++ /dev/null
@@ -1,338 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-#ifndef __BFA_SVC_H__
-#define __BFA_SVC_H__
-
-/*
- * forward declarations
- */
-struct bfa_fcxp_s;
-
-#include <defs/bfa_defs_status.h>
-#include <defs/bfa_defs_pport.h>
-#include <defs/bfa_defs_rport.h>
-#include <defs/bfa_defs_qos.h>
-#include <defs/bfa_defs_fcport.h>
-#include <cs/bfa_sm.h>
-#include <bfa.h>
-
-/**
- * BFA rport information.
- */
-struct bfa_rport_info_s {
- u16 max_frmsz; /* max rcv pdu size */
- u32 pid:24, /* remote port ID */
- lp_tag:8; /* tag */
- u32 local_pid:24, /* local port ID */
- cisc:8; /* CIRO supported */
- u8 fc_class; /* supported FC classes. enum fc_cos */
- u8 vf_en; /* virtual fabric enable */
- u16 vf_id; /* virtual fabric ID */
- enum bfa_pport_speed speed; /* Rport's current speed */
-};
-
-/**
- * BFA rport data structure
- */
-struct bfa_rport_s {
- struct list_head qe; /* queue element */
- bfa_sm_t sm; /* state machine */
- struct bfa_s *bfa; /* backpointer to BFA */
- void *rport_drv; /* fcs/driver rport object */
- u16 fw_handle; /* firmware rport handle */
- u16 rport_tag; /* BFA rport tag */
- struct bfa_rport_info_s rport_info; /* rport info from fcs/driver */
- struct bfa_reqq_wait_s reqq_wait; /* to wait for room in reqq */
- struct bfa_cb_qe_s hcb_qe; /* BFA callback qelem */
- struct bfa_rport_hal_stats_s stats; /* BFA rport statistics */
- struct bfa_rport_qos_attr_s qos_attr;
- union a {
- bfa_status_t status; /* f/w status */
- void *fw_msg; /* QoS scn event */
- } event_arg;
-};
-#define BFA_RPORT_FC_COS(_rport) ((_rport)->rport_info.fc_class)
-
-/**
- * Send completion callback.
- */
-typedef void (*bfa_cb_fcxp_send_t) (void *bfad_fcxp, struct bfa_fcxp_s *fcxp,
- void *cbarg, enum bfa_status req_status,
- u32 rsp_len, u32 resid_len,
- struct fchs_s *rsp_fchs);
-
-/**
- * BFA fcxp allocation (asynchronous)
- */
-typedef void (*bfa_fcxp_alloc_cbfn_t) (void *cbarg, struct bfa_fcxp_s *fcxp);
-
-struct bfa_fcxp_wqe_s {
- struct list_head qe;
- bfa_fcxp_alloc_cbfn_t alloc_cbfn;
- void *alloc_cbarg;
-};
-
-typedef u64 (*bfa_fcxp_get_sgaddr_t) (void *bfad_fcxp, int sgeid);
-typedef u32 (*bfa_fcxp_get_sglen_t) (void *bfad_fcxp, int sgeid);
-
-#define BFA_UF_BUFSZ (2 * 1024 + 256)
-
-/**
- * @todo private
- */
-struct bfa_uf_buf_s {
- u8 d[BFA_UF_BUFSZ];
-};
-
-
-struct bfa_uf_s {
- struct list_head qe; /* queue element */
- struct bfa_s *bfa; /* bfa instance */
- u16 uf_tag; /* identifying tag fw msgs */
- u16 vf_id;
- u16 src_rport_handle;
- u16 rsvd;
- u8 *data_ptr;
- u16 data_len; /* actual receive length */
- u16 pb_len; /* posted buffer length */
- void *buf_kva; /* buffer virtual address */
- u64 buf_pa; /* buffer physical address */
- struct bfa_cb_qe_s hcb_qe; /* comp: BFA comp qelem */
- struct bfa_sge_s sges[BFI_SGE_INLINE_MAX];
-};
-
-typedef void (*bfa_cb_pport_t) (void *cbarg, enum bfa_status status);
-
-/**
- * bfa lport login/logout service interface
- */
-struct bfa_lps_s {
- struct list_head qe; /* queue element */
- struct bfa_s *bfa; /* parent bfa instance */
- bfa_sm_t sm; /* finite state machine */
- u8 lp_tag; /* lport tag */
- u8 reqq; /* lport request queue */
- u8 alpa; /* ALPA for loop topologies */
- u32 lp_pid; /* lport port ID */
- bfa_boolean_t fdisc; /* send FDISC instead of FLOGI */
- bfa_boolean_t auth_en; /* enable authentication */
- bfa_boolean_t auth_req; /* authentication required */
- bfa_boolean_t npiv_en; /* NPIV is allowed by peer */
- bfa_boolean_t fport; /* attached peer is F_PORT */
- bfa_boolean_t brcd_switch;/* attached peer is brcd switch */
- bfa_status_t status; /* login status */
- u16 pdusz; /* max receive PDU size */
- u16 pr_bbcred; /* BB_CREDIT from peer */
- u8 lsrjt_rsn; /* LSRJT reason */
- u8 lsrjt_expl; /* LSRJT explanation */
- wwn_t pwwn; /* port wwn of lport */
- wwn_t nwwn; /* node wwn of lport */
- wwn_t pr_pwwn; /* port wwn of lport peer */
- wwn_t pr_nwwn; /* node wwn of lport peer */
- mac_t lp_mac; /* fpma/spma MAC for lport */
- mac_t fcf_mac; /* FCF MAC of lport */
- struct bfa_reqq_wait_s wqe; /* request wait queue element */
- void *uarg; /* user callback arg */
- struct bfa_cb_qe_s hcb_qe; /* comp: callback qelem */
- struct bfi_lps_login_rsp_s *loginrsp;
- bfa_eproto_status_t ext_status;
-};
-
-#define BFA_FCPORT(_bfa) (&((_bfa)->modules.port))
-
-/*
- * bfa pport API functions
- */
-bfa_status_t bfa_fcport_enable(struct bfa_s *bfa);
-bfa_status_t bfa_fcport_disable(struct bfa_s *bfa);
-bfa_status_t bfa_fcport_cfg_speed(struct bfa_s *bfa,
- enum bfa_pport_speed speed);
-enum bfa_pport_speed bfa_fcport_get_speed(struct bfa_s *bfa);
-bfa_status_t bfa_fcport_cfg_topology(struct bfa_s *bfa,
- enum bfa_pport_topology topo);
-enum bfa_pport_topology bfa_fcport_get_topology(struct bfa_s *bfa);
-bfa_status_t bfa_fcport_cfg_hardalpa(struct bfa_s *bfa, u8 alpa);
-bfa_boolean_t bfa_fcport_get_hardalpa(struct bfa_s *bfa, u8 *alpa);
-u8 bfa_fcport_get_myalpa(struct bfa_s *bfa);
-bfa_status_t bfa_fcport_clr_hardalpa(struct bfa_s *bfa);
-bfa_status_t bfa_fcport_cfg_maxfrsize(struct bfa_s *bfa, u16 maxsize);
-u16 bfa_fcport_get_maxfrsize(struct bfa_s *bfa);
-u32 bfa_fcport_mypid(struct bfa_s *bfa);
-u8 bfa_fcport_get_rx_bbcredit(struct bfa_s *bfa);
-bfa_status_t bfa_fcport_trunk_enable(struct bfa_s *bfa, u8 bitmap);
-bfa_status_t bfa_fcport_trunk_disable(struct bfa_s *bfa);
-bfa_boolean_t bfa_fcport_trunk_query(struct bfa_s *bfa, u32 *bitmap);
-void bfa_fcport_get_attr(struct bfa_s *bfa, struct bfa_pport_attr_s *attr);
-wwn_t bfa_fcport_get_wwn(struct bfa_s *bfa, bfa_boolean_t node);
-void bfa_fcport_event_register(struct bfa_s *bfa,
- void (*event_cbfn) (void *cbarg,
- bfa_pport_event_t event), void *event_cbarg);
-bfa_boolean_t bfa_fcport_is_disabled(struct bfa_s *bfa);
-void bfa_fcport_cfg_qos(struct bfa_s *bfa, bfa_boolean_t on_off);
-void bfa_fcport_cfg_ratelim(struct bfa_s *bfa, bfa_boolean_t on_off);
-bfa_status_t bfa_fcport_cfg_ratelim_speed(struct bfa_s *bfa,
- enum bfa_pport_speed speed);
-enum bfa_pport_speed bfa_fcport_get_ratelim_speed(struct bfa_s *bfa);
-
-void bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit);
-void bfa_fcport_busy(struct bfa_s *bfa, bfa_boolean_t status);
-void bfa_fcport_beacon(struct bfa_s *bfa, bfa_boolean_t beacon,
- bfa_boolean_t link_e2e_beacon);
-void bfa_cb_pport_event(void *cbarg, bfa_pport_event_t event);
-void bfa_fcport_qos_get_attr(struct bfa_s *bfa,
- struct bfa_qos_attr_s *qos_attr);
-void bfa_fcport_qos_get_vc_attr(struct bfa_s *bfa,
- struct bfa_qos_vc_attr_s *qos_vc_attr);
-bfa_status_t bfa_fcport_get_qos_stats(struct bfa_s *bfa,
- union bfa_fcport_stats_u *stats,
- bfa_cb_pport_t cbfn, void *cbarg);
-bfa_status_t bfa_fcport_clear_qos_stats(struct bfa_s *bfa, bfa_cb_pport_t cbfn,
- void *cbarg);
-bfa_status_t bfa_fcport_get_fcoe_stats(struct bfa_s *bfa,
- union bfa_fcport_stats_u *stats,
- bfa_cb_pport_t cbfn, void *cbarg);
-bfa_status_t bfa_fcport_clear_fcoe_stats(struct bfa_s *bfa, bfa_cb_pport_t cbfn,
- void *cbarg);
-
-bfa_boolean_t bfa_fcport_is_ratelim(struct bfa_s *bfa);
-bfa_boolean_t bfa_fcport_is_linkup(struct bfa_s *bfa);
-bfa_status_t bfa_fcport_get_stats(struct bfa_s *bfa,
- union bfa_fcport_stats_u *stats,
- bfa_cb_pport_t cbfn, void *cbarg);
-bfa_status_t bfa_fcport_clear_stats(struct bfa_s *bfa, bfa_cb_pport_t cbfn,
- void *cbarg);
-bfa_boolean_t bfa_fcport_is_qos_enabled(struct bfa_s *bfa);
-
-/*
- * bfa rport API functions
- */
-struct bfa_rport_s *bfa_rport_create(struct bfa_s *bfa, void *rport_drv);
-void bfa_rport_delete(struct bfa_rport_s *rport);
-void bfa_rport_online(struct bfa_rport_s *rport,
- struct bfa_rport_info_s *rport_info);
-void bfa_rport_offline(struct bfa_rport_s *rport);
-void bfa_rport_speed(struct bfa_rport_s *rport, enum bfa_pport_speed speed);
-void bfa_rport_get_stats(struct bfa_rport_s *rport,
- struct bfa_rport_hal_stats_s *stats);
-void bfa_rport_clear_stats(struct bfa_rport_s *rport);
-void bfa_cb_rport_online(void *rport);
-void bfa_cb_rport_offline(void *rport);
-void bfa_cb_rport_qos_scn_flowid(void *rport,
- struct bfa_rport_qos_attr_s old_qos_attr,
- struct bfa_rport_qos_attr_s new_qos_attr);
-void bfa_cb_rport_qos_scn_prio(void *rport,
- struct bfa_rport_qos_attr_s old_qos_attr,
- struct bfa_rport_qos_attr_s new_qos_attr);
-void bfa_rport_get_qos_attr(struct bfa_rport_s *rport,
- struct bfa_rport_qos_attr_s *qos_attr);
-
-/*
- * bfa fcxp API functions
- */
-struct bfa_fcxp_s *bfa_fcxp_alloc(void *bfad_fcxp, struct bfa_s *bfa,
- int nreq_sgles, int nrsp_sgles,
- bfa_fcxp_get_sgaddr_t get_req_sga,
- bfa_fcxp_get_sglen_t get_req_sglen,
- bfa_fcxp_get_sgaddr_t get_rsp_sga,
- bfa_fcxp_get_sglen_t get_rsp_sglen);
-void bfa_fcxp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe,
- bfa_fcxp_alloc_cbfn_t alloc_cbfn, void *cbarg);
-void bfa_fcxp_walloc_cancel(struct bfa_s *bfa,
- struct bfa_fcxp_wqe_s *wqe);
-void bfa_fcxp_discard(struct bfa_fcxp_s *fcxp);
-
-void *bfa_fcxp_get_reqbuf(struct bfa_fcxp_s *fcxp);
-void *bfa_fcxp_get_rspbuf(struct bfa_fcxp_s *fcxp);
-
-void bfa_fcxp_free(struct bfa_fcxp_s *fcxp);
-
-void bfa_fcxp_send(struct bfa_fcxp_s *fcxp,
- struct bfa_rport_s *rport, u16 vf_id, u8 lp_tag,
- bfa_boolean_t cts, enum fc_cos cos,
- u32 reqlen, struct fchs_s *fchs,
- bfa_cb_fcxp_send_t cbfn,
- void *cbarg,
- u32 rsp_maxlen, u8 rsp_timeout);
-bfa_status_t bfa_fcxp_abort(struct bfa_fcxp_s *fcxp);
-u32 bfa_fcxp_get_reqbufsz(struct bfa_fcxp_s *fcxp);
-u32 bfa_fcxp_get_maxrsp(struct bfa_s *bfa);
-
-static inline void *
-bfa_uf_get_frmbuf(struct bfa_uf_s *uf)
-{
- return uf->data_ptr;
-}
-
-static inline u16
-bfa_uf_get_frmlen(struct bfa_uf_s *uf)
-{
- return uf->data_len;
-}
-
-/**
- * Callback prototype for unsolicited frame receive handler.
- *
- * @param[in] cbarg callback arg for receive handler
- * @param[in] uf unsolicited frame descriptor
- *
- * @return None
- */
-typedef void (*bfa_cb_uf_recv_t) (void *cbarg, struct bfa_uf_s *uf);
-
-/*
- * bfa uf API functions
- */
-void bfa_uf_recv_register(struct bfa_s *bfa, bfa_cb_uf_recv_t ufrecv,
- void *cbarg);
-void bfa_uf_free(struct bfa_uf_s *uf);
-
-/**
- * bfa lport service api
- */
-
-u32 bfa_lps_get_max_vport(struct bfa_s *bfa);
-struct bfa_lps_s *bfa_lps_alloc(struct bfa_s *bfa);
-void bfa_lps_delete(struct bfa_lps_s *lps);
-void bfa_lps_discard(struct bfa_lps_s *lps);
-void bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa, u16 pdusz,
- wwn_t pwwn, wwn_t nwwn, bfa_boolean_t auth_en);
-void bfa_lps_fdisc(struct bfa_lps_s *lps, void *uarg, u16 pdusz, wwn_t pwwn,
- wwn_t nwwn);
-void bfa_lps_flogo(struct bfa_lps_s *lps);
-void bfa_lps_fdisclogo(struct bfa_lps_s *lps);
-u8 bfa_lps_get_tag(struct bfa_lps_s *lps);
-bfa_boolean_t bfa_lps_is_npiv_en(struct bfa_lps_s *lps);
-bfa_boolean_t bfa_lps_is_fport(struct bfa_lps_s *lps);
-bfa_boolean_t bfa_lps_is_brcd_fabric(struct bfa_lps_s *lps);
-bfa_boolean_t bfa_lps_is_authreq(struct bfa_lps_s *lps);
-bfa_eproto_status_t bfa_lps_get_extstatus(struct bfa_lps_s *lps);
-u32 bfa_lps_get_pid(struct bfa_lps_s *lps);
-u8 bfa_lps_get_tag_from_pid(struct bfa_s *bfa, u32 pid);
-u16 bfa_lps_get_peer_bbcredit(struct bfa_lps_s *lps);
-wwn_t bfa_lps_get_peer_pwwn(struct bfa_lps_s *lps);
-wwn_t bfa_lps_get_peer_nwwn(struct bfa_lps_s *lps);
-u8 bfa_lps_get_lsrjt_rsn(struct bfa_lps_s *lps);
-u8 bfa_lps_get_lsrjt_expl(struct bfa_lps_s *lps);
-mac_t bfa_lps_get_lp_mac(struct bfa_lps_s *lps);
-void bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status);
-void bfa_cb_lps_flogo_comp(void *bfad, void *uarg);
-void bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status);
-void bfa_cb_lps_fdisclogo_comp(void *bfad, void *uarg);
-void bfa_cb_lps_cvl_event(void *bfad, void *uarg);
-
-#endif /* __BFA_SVC_H__ */
-
diff --git a/drivers/scsi/bfa/include/bfa_timer.h b/drivers/scsi/bfa/include/bfa_timer.h
deleted file mode 100644
index f71087448222..000000000000
--- a/drivers/scsi/bfa/include/bfa_timer.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-#ifndef __BFA_TIMER_H__
-#define __BFA_TIMER_H__
-
-#include <bfa_os_inc.h>
-#include <cs/bfa_q.h>
-
-struct bfa_s;
-
-typedef void (*bfa_timer_cbfn_t)(void *);
-
-/**
- * BFA timer data structure
- */
-struct bfa_timer_s {
- struct list_head qe;
- bfa_timer_cbfn_t timercb;
- void *arg;
- int timeout; /**< in millisecs. */
-};
-
-/**
- * Timer module structure
- */
-struct bfa_timer_mod_s {
- struct list_head timer_q;
-};
-
-#define BFA_TIMER_FREQ 200 /**< specified in millisecs */
-
-void bfa_timer_beat(struct bfa_timer_mod_s *mod);
-void bfa_timer_init(struct bfa_timer_mod_s *mod);
-void bfa_timer_begin(struct bfa_timer_mod_s *mod, struct bfa_timer_s *timer,
- bfa_timer_cbfn_t timercb, void *arg,
- unsigned int timeout);
-void bfa_timer_stop(struct bfa_timer_s *timer);
-
-#endif /* __BFA_TIMER_H__ */
diff --git a/drivers/scsi/bfa/include/bfi/bfi.h b/drivers/scsi/bfa/include/bfi/bfi.h
deleted file mode 100644
index a550e80cabd2..000000000000
--- a/drivers/scsi/bfa/include/bfi/bfi.h
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFI_H__
-#define __BFI_H__
-
-#include <bfa_os_inc.h>
-#include <defs/bfa_defs_status.h>
-
-#pragma pack(1)
-
-/**
- * Msg header common to all msgs
- */
-struct bfi_mhdr_s {
- u8 msg_class; /* @ref bfi_mclass_t */
- u8 msg_id; /* msg opcode with in the class */
- union {
- struct {
- u8 rsvd;
- u8 lpu_id; /* msg destination */
- } h2i;
- u16 i2htok; /* token in msgs to host */
- } mtag;
-};
-
-#define bfi_h2i_set(_mh, _mc, _op, _lpuid) do { \
- (_mh).msg_class = (_mc); \
- (_mh).msg_id = (_op); \
- (_mh).mtag.h2i.lpu_id = (_lpuid); \
-} while (0)
-
-#define bfi_i2h_set(_mh, _mc, _op, _i2htok) do { \
- (_mh).msg_class = (_mc); \
- (_mh).msg_id = (_op); \
- (_mh).mtag.i2htok = (_i2htok); \
-} while (0)
-
-/*
- * Message opcodes: 0-127 to firmware, 128-255 to host
- */
-#define BFI_I2H_OPCODE_BASE 128
-#define BFA_I2HM(_x) ((_x) + BFI_I2H_OPCODE_BASE)
-
-/**
- ****************************************************************************
- *
- * Scatter Gather Element and Page definition
- *
- ****************************************************************************
- */
-
-#define BFI_SGE_INLINE 1
-#define BFI_SGE_INLINE_MAX (BFI_SGE_INLINE + 1)
-
-/**
- * SG Flags
- */
-enum {
- BFI_SGE_DATA = 0, /* data address, not last */
- BFI_SGE_DATA_CPL = 1, /* data addr, last in current page */
- BFI_SGE_DATA_LAST = 3, /* data address, last */
- BFI_SGE_LINK = 2, /* link address */
- BFI_SGE_PGDLEN = 2, /* cumulative data length for page */
-};
-
-/**
- * DMA addresses
- */
-union bfi_addr_u {
- struct {
- u32 addr_lo;
- u32 addr_hi;
- } a32;
-};
-
-/**
- * Scatter Gather Element
- */
-struct bfi_sge_s {
-#ifdef __BIGENDIAN
- u32 flags:2,
- rsvd:2,
- sg_len:28;
-#else
- u32 sg_len:28,
- rsvd:2,
- flags:2;
-#endif
- union bfi_addr_u sga;
-};
-
-/**
- * Scatter Gather Page
- */
-#define BFI_SGPG_DATA_SGES 7
-#define BFI_SGPG_SGES_MAX (BFI_SGPG_DATA_SGES + 1)
-#define BFI_SGPG_RSVD_WD_LEN 8
-struct bfi_sgpg_s {
- struct bfi_sge_s sges[BFI_SGPG_SGES_MAX];
- u32 rsvd[BFI_SGPG_RSVD_WD_LEN];
-};
-
-/*
- * Large Message structure - 128 Bytes size Msgs
- */
-#define BFI_LMSG_SZ 128
-#define BFI_LMSG_PL_WSZ \
- ((BFI_LMSG_SZ - sizeof(struct bfi_mhdr_s)) / 4)
-
-struct bfi_msg_s {
- struct bfi_mhdr_s mhdr;
- u32 pl[BFI_LMSG_PL_WSZ];
-};
-
-/**
- * Mailbox message structure
- */
-#define BFI_MBMSG_SZ 7
-struct bfi_mbmsg_s {
- struct bfi_mhdr_s mh;
- u32 pl[BFI_MBMSG_SZ];
-};
-
-/**
- * Message Classes
- */
-enum bfi_mclass {
- BFI_MC_IOC = 1, /* IO Controller (IOC) */
- BFI_MC_DIAG = 2, /* Diagnostic Msgs */
- BFI_MC_FLASH = 3, /* Flash message class */
- BFI_MC_CEE = 4, /* CEE */
- BFI_MC_FCPORT = 5, /* FC port */
- BFI_MC_IOCFC = 6, /* FC - IO Controller (IOC) */
- BFI_MC_LL = 7, /* Link Layer */
- BFI_MC_UF = 8, /* Unsolicited frame receive */
- BFI_MC_FCXP = 9, /* FC Transport */
- BFI_MC_LPS = 10, /* lport fc login services */
- BFI_MC_RPORT = 11, /* Remote port */
- BFI_MC_ITNIM = 12, /* I-T nexus (Initiator mode) */
- BFI_MC_IOIM_READ = 13, /* read IO (Initiator mode) */
- BFI_MC_IOIM_WRITE = 14, /* write IO (Initiator mode) */
- BFI_MC_IOIM_IO = 15, /* IO (Initiator mode) */
- BFI_MC_IOIM = 16, /* IO (Initiator mode) */
- BFI_MC_IOIM_IOCOM = 17, /* good IO completion */
- BFI_MC_TSKIM = 18, /* Initiator Task management */
- BFI_MC_SBOOT = 19, /* SAN boot services */
- BFI_MC_IPFC = 20, /* IP over FC Msgs */
- BFI_MC_PORT = 21, /* Physical port */
- BFI_MC_MAX = 32
-};
-
-#define BFI_IOC_MAX_CQS 4
-#define BFI_IOC_MAX_CQS_ASIC 8
-#define BFI_IOC_MSGLEN_MAX 32 /* 32 bytes */
-
-#pragma pack()
-
-#endif /* __BFI_H__ */
-
diff --git a/drivers/scsi/bfa/include/bfi/bfi_boot.h b/drivers/scsi/bfa/include/bfi/bfi_boot.h
deleted file mode 100644
index 5955afe7d108..000000000000
--- a/drivers/scsi/bfa/include/bfi/bfi_boot.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-/*
- * bfi_boot.h
- */
-
-#ifndef __BFI_BOOT_H__
-#define __BFI_BOOT_H__
-
-#define BFI_BOOT_TYPE_OFF 8
-#define BFI_BOOT_PARAM_OFF 12
-
-#define BFI_BOOT_TYPE_NORMAL 0 /* param is device id */
-#define BFI_BOOT_TYPE_FLASH 1
-#define BFI_BOOT_TYPE_MEMTEST 2
-
-#define BFI_BOOT_MEMTEST_RES_ADDR 0x900
-#define BFI_BOOT_MEMTEST_RES_SIG 0xA0A1A2A3
-
-#endif
diff --git a/drivers/scsi/bfa/include/bfi/bfi_cee.h b/drivers/scsi/bfa/include/bfi/bfi_cee.h
deleted file mode 100644
index 0970596583ea..000000000000
--- a/drivers/scsi/bfa/include/bfi/bfi_cee.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-/**
- * Copyright (c) 2006-2009 Brocade Communications Systems, Inc.
- * All rights reserved.
- *
- * bfi_dcbx.h BFI Interface (Mailbox commands and related structures)
- * between host driver and DCBX/LLDP firmware module.
- *
-**/
-
-#ifndef __BFI_CEE_H__
-#define __BFI_CEE_H__
-
-#include <bfi/bfi.h>
-
-#pragma pack(1)
-
-
-enum bfi_cee_h2i_msgs_e {
- BFI_CEE_H2I_GET_CFG_REQ = 1,
- BFI_CEE_H2I_RESET_STATS = 2,
- BFI_CEE_H2I_GET_STATS_REQ = 3,
-};
-
-
-enum bfi_cee_i2h_msgs_e {
- BFI_CEE_I2H_GET_CFG_RSP = BFA_I2HM(1),
- BFI_CEE_I2H_RESET_STATS_RSP = BFA_I2HM(2),
- BFI_CEE_I2H_GET_STATS_RSP = BFA_I2HM(3),
-};
-
-
-/* Data structures */
-
-/*
- * BFI_CEE_H2I_RESET_STATS
- */
-struct bfi_lldp_reset_stats_s {
- struct bfi_mhdr_s mh;
-};
-
-/*
- * BFI_CEE_H2I_RESET_STATS
- */
-struct bfi_cee_reset_stats_s {
- struct bfi_mhdr_s mh;
-};
-
-/*
- * BFI_CEE_H2I_GET_CFG_REQ
- */
-struct bfi_cee_get_req_s {
- struct bfi_mhdr_s mh;
- union bfi_addr_u dma_addr;
-};
-
-
-/*
- * BFI_CEE_I2H_GET_CFG_RSP
- */
-struct bfi_cee_get_rsp_s {
- struct bfi_mhdr_s mh;
- u8 cmd_status;
- u8 rsvd[3];
-};
-
-/*
- * BFI_CEE_H2I_GET_STATS_REQ
- */
-struct bfi_cee_stats_req_s {
- struct bfi_mhdr_s mh;
- union bfi_addr_u dma_addr;
-};
-
-
-/*
- * BFI_CEE_I2H_GET_STATS_RSP
- */
-struct bfi_cee_stats_rsp_s {
- struct bfi_mhdr_s mh;
- u8 cmd_status;
- u8 rsvd[3];
-};
-
-
-
-union bfi_cee_h2i_msg_u {
- struct bfi_mhdr_s mh;
- struct bfi_cee_get_req_s get_req;
- struct bfi_cee_stats_req_s stats_req;
-};
-
-
-union bfi_cee_i2h_msg_u {
- struct bfi_mhdr_s mh;
- struct bfi_cee_get_rsp_s get_rsp;
- struct bfi_cee_stats_rsp_s stats_rsp;
-};
-
-#pragma pack()
-
-
-#endif /* __BFI_CEE_H__ */
-
diff --git a/drivers/scsi/bfa/include/bfi/bfi_ctreg.h b/drivers/scsi/bfa/include/bfi/bfi_ctreg.h
deleted file mode 100644
index c0ef5a93b797..000000000000
--- a/drivers/scsi/bfa/include/bfi/bfi_ctreg.h
+++ /dev/null
@@ -1,640 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/*
- * bfi_ctreg.h catapult host block register definitions
- *
- * !!! Do not edit. Auto generated. !!!
- */
-
-#ifndef __BFI_CTREG_H__
-#define __BFI_CTREG_H__
-
-
-#define HOSTFN0_LPU_MBOX0_0 0x00019200
-#define HOSTFN1_LPU_MBOX0_8 0x00019260
-#define LPU_HOSTFN0_MBOX0_0 0x00019280
-#define LPU_HOSTFN1_MBOX0_8 0x000192e0
-#define HOSTFN2_LPU_MBOX0_0 0x00019400
-#define HOSTFN3_LPU_MBOX0_8 0x00019460
-#define LPU_HOSTFN2_MBOX0_0 0x00019480
-#define LPU_HOSTFN3_MBOX0_8 0x000194e0
-#define HOSTFN0_INT_STATUS 0x00014000
-#define __HOSTFN0_HALT_OCCURRED 0x01000000
-#define __HOSTFN0_INT_STATUS_LVL_MK 0x00f00000
-#define __HOSTFN0_INT_STATUS_LVL_SH 20
-#define __HOSTFN0_INT_STATUS_LVL(_v) ((_v) << __HOSTFN0_INT_STATUS_LVL_SH)
-#define __HOSTFN0_INT_STATUS_P_MK 0x000f0000
-#define __HOSTFN0_INT_STATUS_P_SH 16
-#define __HOSTFN0_INT_STATUS_P(_v) ((_v) << __HOSTFN0_INT_STATUS_P_SH)
-#define __HOSTFN0_INT_STATUS_F 0x0000ffff
-#define HOSTFN0_INT_MSK 0x00014004
-#define HOST_PAGE_NUM_FN0 0x00014008
-#define __HOST_PAGE_NUM_FN 0x000001ff
-#define HOST_MSIX_ERR_INDEX_FN0 0x0001400c
-#define __MSIX_ERR_INDEX_FN 0x000001ff
-#define HOSTFN1_INT_STATUS 0x00014100
-#define __HOSTFN1_HALT_OCCURRED 0x01000000
-#define __HOSTFN1_INT_STATUS_LVL_MK 0x00f00000
-#define __HOSTFN1_INT_STATUS_LVL_SH 20
-#define __HOSTFN1_INT_STATUS_LVL(_v) ((_v) << __HOSTFN1_INT_STATUS_LVL_SH)
-#define __HOSTFN1_INT_STATUS_P_MK 0x000f0000
-#define __HOSTFN1_INT_STATUS_P_SH 16
-#define __HOSTFN1_INT_STATUS_P(_v) ((_v) << __HOSTFN1_INT_STATUS_P_SH)
-#define __HOSTFN1_INT_STATUS_F 0x0000ffff
-#define HOSTFN1_INT_MSK 0x00014104
-#define HOST_PAGE_NUM_FN1 0x00014108
-#define HOST_MSIX_ERR_INDEX_FN1 0x0001410c
-#define APP_PLL_425_CTL_REG 0x00014204
-#define __P_425_PLL_LOCK 0x80000000
-#define __APP_PLL_425_SRAM_USE_100MHZ 0x00100000
-#define __APP_PLL_425_RESET_TIMER_MK 0x000e0000
-#define __APP_PLL_425_RESET_TIMER_SH 17
-#define __APP_PLL_425_RESET_TIMER(_v) ((_v) << __APP_PLL_425_RESET_TIMER_SH)
-#define __APP_PLL_425_LOGIC_SOFT_RESET 0x00010000
-#define __APP_PLL_425_CNTLMT0_1_MK 0x0000c000
-#define __APP_PLL_425_CNTLMT0_1_SH 14
-#define __APP_PLL_425_CNTLMT0_1(_v) ((_v) << __APP_PLL_425_CNTLMT0_1_SH)
-#define __APP_PLL_425_JITLMT0_1_MK 0x00003000
-#define __APP_PLL_425_JITLMT0_1_SH 12
-#define __APP_PLL_425_JITLMT0_1(_v) ((_v) << __APP_PLL_425_JITLMT0_1_SH)
-#define __APP_PLL_425_HREF 0x00000800
-#define __APP_PLL_425_HDIV 0x00000400
-#define __APP_PLL_425_P0_1_MK 0x00000300
-#define __APP_PLL_425_P0_1_SH 8
-#define __APP_PLL_425_P0_1(_v) ((_v) << __APP_PLL_425_P0_1_SH)
-#define __APP_PLL_425_Z0_2_MK 0x000000e0
-#define __APP_PLL_425_Z0_2_SH 5
-#define __APP_PLL_425_Z0_2(_v) ((_v) << __APP_PLL_425_Z0_2_SH)
-#define __APP_PLL_425_RSEL200500 0x00000010
-#define __APP_PLL_425_ENARST 0x00000008
-#define __APP_PLL_425_BYPASS 0x00000004
-#define __APP_PLL_425_LRESETN 0x00000002
-#define __APP_PLL_425_ENABLE 0x00000001
-#define APP_PLL_312_CTL_REG 0x00014208
-#define __P_312_PLL_LOCK 0x80000000
-#define __ENABLE_MAC_AHB_1 0x00800000
-#define __ENABLE_MAC_AHB_0 0x00400000
-#define __ENABLE_MAC_1 0x00200000
-#define __ENABLE_MAC_0 0x00100000
-#define __APP_PLL_312_RESET_TIMER_MK 0x000e0000
-#define __APP_PLL_312_RESET_TIMER_SH 17
-#define __APP_PLL_312_RESET_TIMER(_v) ((_v) << __APP_PLL_312_RESET_TIMER_SH)
-#define __APP_PLL_312_LOGIC_SOFT_RESET 0x00010000
-#define __APP_PLL_312_CNTLMT0_1_MK 0x0000c000
-#define __APP_PLL_312_CNTLMT0_1_SH 14
-#define __APP_PLL_312_CNTLMT0_1(_v) ((_v) << __APP_PLL_312_CNTLMT0_1_SH)
-#define __APP_PLL_312_JITLMT0_1_MK 0x00003000
-#define __APP_PLL_312_JITLMT0_1_SH 12
-#define __APP_PLL_312_JITLMT0_1(_v) ((_v) << __APP_PLL_312_JITLMT0_1_SH)
-#define __APP_PLL_312_HREF 0x00000800
-#define __APP_PLL_312_HDIV 0x00000400
-#define __APP_PLL_312_P0_1_MK 0x00000300
-#define __APP_PLL_312_P0_1_SH 8
-#define __APP_PLL_312_P0_1(_v) ((_v) << __APP_PLL_312_P0_1_SH)
-#define __APP_PLL_312_Z0_2_MK 0x000000e0
-#define __APP_PLL_312_Z0_2_SH 5
-#define __APP_PLL_312_Z0_2(_v) ((_v) << __APP_PLL_312_Z0_2_SH)
-#define __APP_PLL_312_RSEL200500 0x00000010
-#define __APP_PLL_312_ENARST 0x00000008
-#define __APP_PLL_312_BYPASS 0x00000004
-#define __APP_PLL_312_LRESETN 0x00000002
-#define __APP_PLL_312_ENABLE 0x00000001
-#define MBIST_CTL_REG 0x00014220
-#define __EDRAM_BISTR_START 0x00000004
-#define __MBIST_RESET 0x00000002
-#define __MBIST_START 0x00000001
-#define MBIST_STAT_REG 0x00014224
-#define __EDRAM_BISTR_STATUS 0x00000008
-#define __EDRAM_BISTR_DONE 0x00000004
-#define __MEM_BIT_STATUS 0x00000002
-#define __MBIST_DONE 0x00000001
-#define HOST_SEM0_REG 0x00014230
-#define __HOST_SEMAPHORE 0x00000001
-#define HOST_SEM1_REG 0x00014234
-#define HOST_SEM2_REG 0x00014238
-#define HOST_SEM3_REG 0x0001423c
-#define HOST_SEM0_INFO_REG 0x00014240
-#define HOST_SEM1_INFO_REG 0x00014244
-#define HOST_SEM2_INFO_REG 0x00014248
-#define HOST_SEM3_INFO_REG 0x0001424c
-#define ETH_MAC_SER_REG 0x00014288
-#define __APP_EMS_CKBUFAMPIN 0x00000020
-#define __APP_EMS_REFCLKSEL 0x00000010
-#define __APP_EMS_CMLCKSEL 0x00000008
-#define __APP_EMS_REFCKBUFEN2 0x00000004
-#define __APP_EMS_REFCKBUFEN1 0x00000002
-#define __APP_EMS_CHANNEL_SEL 0x00000001
-#define HOSTFN2_INT_STATUS 0x00014300
-#define __HOSTFN2_HALT_OCCURRED 0x01000000
-#define __HOSTFN2_INT_STATUS_LVL_MK 0x00f00000
-#define __HOSTFN2_INT_STATUS_LVL_SH 20
-#define __HOSTFN2_INT_STATUS_LVL(_v) ((_v) << __HOSTFN2_INT_STATUS_LVL_SH)
-#define __HOSTFN2_INT_STATUS_P_MK 0x000f0000
-#define __HOSTFN2_INT_STATUS_P_SH 16
-#define __HOSTFN2_INT_STATUS_P(_v) ((_v) << __HOSTFN2_INT_STATUS_P_SH)
-#define __HOSTFN2_INT_STATUS_F 0x0000ffff
-#define HOSTFN2_INT_MSK 0x00014304
-#define HOST_PAGE_NUM_FN2 0x00014308
-#define HOST_MSIX_ERR_INDEX_FN2 0x0001430c
-#define HOSTFN3_INT_STATUS 0x00014400
-#define __HALT_OCCURRED 0x01000000
-#define __HOSTFN3_INT_STATUS_LVL_MK 0x00f00000
-#define __HOSTFN3_INT_STATUS_LVL_SH 20
-#define __HOSTFN3_INT_STATUS_LVL(_v) ((_v) << __HOSTFN3_INT_STATUS_LVL_SH)
-#define __HOSTFN3_INT_STATUS_P_MK 0x000f0000
-#define __HOSTFN3_INT_STATUS_P_SH 16
-#define __HOSTFN3_INT_STATUS_P(_v) ((_v) << __HOSTFN3_INT_STATUS_P_SH)
-#define __HOSTFN3_INT_STATUS_F 0x0000ffff
-#define HOSTFN3_INT_MSK 0x00014404
-#define HOST_PAGE_NUM_FN3 0x00014408
-#define HOST_MSIX_ERR_INDEX_FN3 0x0001440c
-#define FNC_ID_REG 0x00014600
-#define __FUNCTION_NUMBER 0x00000007
-#define FNC_PERS_REG 0x00014604
-#define __F3_FUNCTION_ACTIVE 0x80000000
-#define __F3_FUNCTION_MODE 0x40000000
-#define __F3_PORT_MAP_MK 0x30000000
-#define __F3_PORT_MAP_SH 28
-#define __F3_PORT_MAP(_v) ((_v) << __F3_PORT_MAP_SH)
-#define __F3_VM_MODE 0x08000000
-#define __F3_INTX_STATUS_MK 0x07000000
-#define __F3_INTX_STATUS_SH 24
-#define __F3_INTX_STATUS(_v) ((_v) << __F3_INTX_STATUS_SH)
-#define __F2_FUNCTION_ACTIVE 0x00800000
-#define __F2_FUNCTION_MODE 0x00400000
-#define __F2_PORT_MAP_MK 0x00300000
-#define __F2_PORT_MAP_SH 20
-#define __F2_PORT_MAP(_v) ((_v) << __F2_PORT_MAP_SH)
-#define __F2_VM_MODE 0x00080000
-#define __F2_INTX_STATUS_MK 0x00070000
-#define __F2_INTX_STATUS_SH 16
-#define __F2_INTX_STATUS(_v) ((_v) << __F2_INTX_STATUS_SH)
-#define __F1_FUNCTION_ACTIVE 0x00008000
-#define __F1_FUNCTION_MODE 0x00004000
-#define __F1_PORT_MAP_MK 0x00003000
-#define __F1_PORT_MAP_SH 12
-#define __F1_PORT_MAP(_v) ((_v) << __F1_PORT_MAP_SH)
-#define __F1_VM_MODE 0x00000800
-#define __F1_INTX_STATUS_MK 0x00000700
-#define __F1_INTX_STATUS_SH 8
-#define __F1_INTX_STATUS(_v) ((_v) << __F1_INTX_STATUS_SH)
-#define __F0_FUNCTION_ACTIVE 0x00000080
-#define __F0_FUNCTION_MODE 0x00000040
-#define __F0_PORT_MAP_MK 0x00000030
-#define __F0_PORT_MAP_SH 4
-#define __F0_PORT_MAP(_v) ((_v) << __F0_PORT_MAP_SH)
-#define __F0_VM_MODE 0x00000008
-#define __F0_INTX_STATUS 0x00000007
-enum {
- __F0_INTX_STATUS_MSIX = 0x0,
- __F0_INTX_STATUS_INTA = 0x1,
- __F0_INTX_STATUS_INTB = 0x2,
- __F0_INTX_STATUS_INTC = 0x3,
- __F0_INTX_STATUS_INTD = 0x4,
-};
-#define OP_MODE 0x0001460c
-#define __APP_ETH_CLK_LOWSPEED 0x00000004
-#define __GLOBAL_CORECLK_HALFSPEED 0x00000002
-#define __GLOBAL_FCOE_MODE 0x00000001
-#define HOST_SEM4_REG 0x00014610
-#define HOST_SEM5_REG 0x00014614
-#define HOST_SEM6_REG 0x00014618
-#define HOST_SEM7_REG 0x0001461c
-#define HOST_SEM4_INFO_REG 0x00014620
-#define HOST_SEM5_INFO_REG 0x00014624
-#define HOST_SEM6_INFO_REG 0x00014628
-#define HOST_SEM7_INFO_REG 0x0001462c
-#define HOSTFN0_LPU0_MBOX0_CMD_STAT 0x00019000
-#define __HOSTFN0_LPU0_MBOX0_INFO_MK 0xfffffffe
-#define __HOSTFN0_LPU0_MBOX0_INFO_SH 1
-#define __HOSTFN0_LPU0_MBOX0_INFO(_v) ((_v) << __HOSTFN0_LPU0_MBOX0_INFO_SH)
-#define __HOSTFN0_LPU0_MBOX0_CMD_STATUS 0x00000001
-#define HOSTFN0_LPU1_MBOX0_CMD_STAT 0x00019004
-#define __HOSTFN0_LPU1_MBOX0_INFO_MK 0xfffffffe
-#define __HOSTFN0_LPU1_MBOX0_INFO_SH 1
-#define __HOSTFN0_LPU1_MBOX0_INFO(_v) ((_v) << __HOSTFN0_LPU1_MBOX0_INFO_SH)
-#define __HOSTFN0_LPU1_MBOX0_CMD_STATUS 0x00000001
-#define LPU0_HOSTFN0_MBOX0_CMD_STAT 0x00019008
-#define __LPU0_HOSTFN0_MBOX0_INFO_MK 0xfffffffe
-#define __LPU0_HOSTFN0_MBOX0_INFO_SH 1
-#define __LPU0_HOSTFN0_MBOX0_INFO(_v) ((_v) << __LPU0_HOSTFN0_MBOX0_INFO_SH)
-#define __LPU0_HOSTFN0_MBOX0_CMD_STATUS 0x00000001
-#define LPU1_HOSTFN0_MBOX0_CMD_STAT 0x0001900c
-#define __LPU1_HOSTFN0_MBOX0_INFO_MK 0xfffffffe
-#define __LPU1_HOSTFN0_MBOX0_INFO_SH 1
-#define __LPU1_HOSTFN0_MBOX0_INFO(_v) ((_v) << __LPU1_HOSTFN0_MBOX0_INFO_SH)
-#define __LPU1_HOSTFN0_MBOX0_CMD_STATUS 0x00000001
-#define HOSTFN1_LPU0_MBOX0_CMD_STAT 0x00019010
-#define __HOSTFN1_LPU0_MBOX0_INFO_MK 0xfffffffe
-#define __HOSTFN1_LPU0_MBOX0_INFO_SH 1
-#define __HOSTFN1_LPU0_MBOX0_INFO(_v) ((_v) << __HOSTFN1_LPU0_MBOX0_INFO_SH)
-#define __HOSTFN1_LPU0_MBOX0_CMD_STATUS 0x00000001
-#define HOSTFN1_LPU1_MBOX0_CMD_STAT 0x00019014
-#define __HOSTFN1_LPU1_MBOX0_INFO_MK 0xfffffffe
-#define __HOSTFN1_LPU1_MBOX0_INFO_SH 1
-#define __HOSTFN1_LPU1_MBOX0_INFO(_v) ((_v) << __HOSTFN1_LPU1_MBOX0_INFO_SH)
-#define __HOSTFN1_LPU1_MBOX0_CMD_STATUS 0x00000001
-#define LPU0_HOSTFN1_MBOX0_CMD_STAT 0x00019018
-#define __LPU0_HOSTFN1_MBOX0_INFO_MK 0xfffffffe
-#define __LPU0_HOSTFN1_MBOX0_INFO_SH 1
-#define __LPU0_HOSTFN1_MBOX0_INFO(_v) ((_v) << __LPU0_HOSTFN1_MBOX0_INFO_SH)
-#define __LPU0_HOSTFN1_MBOX0_CMD_STATUS 0x00000001
-#define LPU1_HOSTFN1_MBOX0_CMD_STAT 0x0001901c
-#define __LPU1_HOSTFN1_MBOX0_INFO_MK 0xfffffffe
-#define __LPU1_HOSTFN1_MBOX0_INFO_SH 1
-#define __LPU1_HOSTFN1_MBOX0_INFO(_v) ((_v) << __LPU1_HOSTFN1_MBOX0_INFO_SH)
-#define __LPU1_HOSTFN1_MBOX0_CMD_STATUS 0x00000001
-#define HOSTFN2_LPU0_MBOX0_CMD_STAT 0x00019150
-#define __HOSTFN2_LPU0_MBOX0_INFO_MK 0xfffffffe
-#define __HOSTFN2_LPU0_MBOX0_INFO_SH 1
-#define __HOSTFN2_LPU0_MBOX0_INFO(_v) ((_v) << __HOSTFN2_LPU0_MBOX0_INFO_SH)
-#define __HOSTFN2_LPU0_MBOX0_CMD_STATUS 0x00000001
-#define HOSTFN2_LPU1_MBOX0_CMD_STAT 0x00019154
-#define __HOSTFN2_LPU1_MBOX0_INFO_MK 0xfffffffe
-#define __HOSTFN2_LPU1_MBOX0_INFO_SH 1
-#define __HOSTFN2_LPU1_MBOX0_INFO(_v) ((_v) << __HOSTFN2_LPU1_MBOX0_INFO_SH)
-#define __HOSTFN2_LPU1_MBOX0BOX0_CMD_STATUS 0x00000001
-#define LPU0_HOSTFN2_MBOX0_CMD_STAT 0x00019158
-#define __LPU0_HOSTFN2_MBOX0_INFO_MK 0xfffffffe
-#define __LPU0_HOSTFN2_MBOX0_INFO_SH 1
-#define __LPU0_HOSTFN2_MBOX0_INFO(_v) ((_v) << __LPU0_HOSTFN2_MBOX0_INFO_SH)
-#define __LPU0_HOSTFN2_MBOX0_CMD_STATUS 0x00000001
-#define LPU1_HOSTFN2_MBOX0_CMD_STAT 0x0001915c
-#define __LPU1_HOSTFN2_MBOX0_INFO_MK 0xfffffffe
-#define __LPU1_HOSTFN2_MBOX0_INFO_SH 1
-#define __LPU1_HOSTFN2_MBOX0_INFO(_v) ((_v) << __LPU1_HOSTFN2_MBOX0_INFO_SH)
-#define __LPU1_HOSTFN2_MBOX0_CMD_STATUS 0x00000001
-#define HOSTFN3_LPU0_MBOX0_CMD_STAT 0x00019160
-#define __HOSTFN3_LPU0_MBOX0_INFO_MK 0xfffffffe
-#define __HOSTFN3_LPU0_MBOX0_INFO_SH 1
-#define __HOSTFN3_LPU0_MBOX0_INFO(_v) ((_v) << __HOSTFN3_LPU0_MBOX0_INFO_SH)
-#define __HOSTFN3_LPU0_MBOX0_CMD_STATUS 0x00000001
-#define HOSTFN3_LPU1_MBOX0_CMD_STAT 0x00019164
-#define __HOSTFN3_LPU1_MBOX0_INFO_MK 0xfffffffe
-#define __HOSTFN3_LPU1_MBOX0_INFO_SH 1
-#define __HOSTFN3_LPU1_MBOX0_INFO(_v) ((_v) << __HOSTFN3_LPU1_MBOX0_INFO_SH)
-#define __HOSTFN3_LPU1_MBOX0_CMD_STATUS 0x00000001
-#define LPU0_HOSTFN3_MBOX0_CMD_STAT 0x00019168
-#define __LPU0_HOSTFN3_MBOX0_INFO_MK 0xfffffffe
-#define __LPU0_HOSTFN3_MBOX0_INFO_SH 1
-#define __LPU0_HOSTFN3_MBOX0_INFO(_v) ((_v) << __LPU0_HOSTFN3_MBOX0_INFO_SH)
-#define __LPU0_HOSTFN3_MBOX0_CMD_STATUS 0x00000001
-#define LPU1_HOSTFN3_MBOX0_CMD_STAT 0x0001916c
-#define __LPU1_HOSTFN3_MBOX0_INFO_MK 0xfffffffe
-#define __LPU1_HOSTFN3_MBOX0_INFO_SH 1
-#define __LPU1_HOSTFN3_MBOX0_INFO(_v) ((_v) << __LPU1_HOSTFN3_MBOX0_INFO_SH)
-#define __LPU1_HOSTFN3_MBOX0_CMD_STATUS 0x00000001
-#define FW_INIT_HALT_P0 0x000191ac
-#define __FW_INIT_HALT_P 0x00000001
-#define FW_INIT_HALT_P1 0x000191bc
-#define CPE_PI_PTR_Q0 0x00038000
-#define __CPE_PI_UNUSED_MK 0xffff0000
-#define __CPE_PI_UNUSED_SH 16
-#define __CPE_PI_UNUSED(_v) ((_v) << __CPE_PI_UNUSED_SH)
-#define __CPE_PI_PTR 0x0000ffff
-#define CPE_PI_PTR_Q1 0x00038040
-#define CPE_CI_PTR_Q0 0x00038004
-#define __CPE_CI_UNUSED_MK 0xffff0000
-#define __CPE_CI_UNUSED_SH 16
-#define __CPE_CI_UNUSED(_v) ((_v) << __CPE_CI_UNUSED_SH)
-#define __CPE_CI_PTR 0x0000ffff
-#define CPE_CI_PTR_Q1 0x00038044
-#define CPE_DEPTH_Q0 0x00038008
-#define __CPE_DEPTH_UNUSED_MK 0xf8000000
-#define __CPE_DEPTH_UNUSED_SH 27
-#define __CPE_DEPTH_UNUSED(_v) ((_v) << __CPE_DEPTH_UNUSED_SH)
-#define __CPE_MSIX_VEC_INDEX_MK 0x07ff0000
-#define __CPE_MSIX_VEC_INDEX_SH 16
-#define __CPE_MSIX_VEC_INDEX(_v) ((_v) << __CPE_MSIX_VEC_INDEX_SH)
-#define __CPE_DEPTH 0x0000ffff
-#define CPE_DEPTH_Q1 0x00038048
-#define CPE_QCTRL_Q0 0x0003800c
-#define __CPE_CTRL_UNUSED30_MK 0xfc000000
-#define __CPE_CTRL_UNUSED30_SH 26
-#define __CPE_CTRL_UNUSED30(_v) ((_v) << __CPE_CTRL_UNUSED30_SH)
-#define __CPE_FUNC_INT_CTRL_MK 0x03000000
-#define __CPE_FUNC_INT_CTRL_SH 24
-#define __CPE_FUNC_INT_CTRL(_v) ((_v) << __CPE_FUNC_INT_CTRL_SH)
-enum {
- __CPE_FUNC_INT_CTRL_DISABLE = 0x0,
- __CPE_FUNC_INT_CTRL_F2NF = 0x1,
- __CPE_FUNC_INT_CTRL_3QUART = 0x2,
- __CPE_FUNC_INT_CTRL_HALF = 0x3,
-};
-#define __CPE_CTRL_UNUSED20_MK 0x00f00000
-#define __CPE_CTRL_UNUSED20_SH 20
-#define __CPE_CTRL_UNUSED20(_v) ((_v) << __CPE_CTRL_UNUSED20_SH)
-#define __CPE_SCI_TH_MK 0x000f0000
-#define __CPE_SCI_TH_SH 16
-#define __CPE_SCI_TH(_v) ((_v) << __CPE_SCI_TH_SH)
-#define __CPE_CTRL_UNUSED10_MK 0x0000c000
-#define __CPE_CTRL_UNUSED10_SH 14
-#define __CPE_CTRL_UNUSED10(_v) ((_v) << __CPE_CTRL_UNUSED10_SH)
-#define __CPE_ACK_PENDING 0x00002000
-#define __CPE_CTRL_UNUSED40_MK 0x00001c00
-#define __CPE_CTRL_UNUSED40_SH 10
-#define __CPE_CTRL_UNUSED40(_v) ((_v) << __CPE_CTRL_UNUSED40_SH)
-#define __CPE_PCIEID_MK 0x00000300
-#define __CPE_PCIEID_SH 8
-#define __CPE_PCIEID(_v) ((_v) << __CPE_PCIEID_SH)
-#define __CPE_CTRL_UNUSED00_MK 0x000000fe
-#define __CPE_CTRL_UNUSED00_SH 1
-#define __CPE_CTRL_UNUSED00(_v) ((_v) << __CPE_CTRL_UNUSED00_SH)
-#define __CPE_ESIZE 0x00000001
-#define CPE_QCTRL_Q1 0x0003804c
-#define __CPE_CTRL_UNUSED31_MK 0xfc000000
-#define __CPE_CTRL_UNUSED31_SH 26
-#define __CPE_CTRL_UNUSED31(_v) ((_v) << __CPE_CTRL_UNUSED31_SH)
-#define __CPE_CTRL_UNUSED21_MK 0x00f00000
-#define __CPE_CTRL_UNUSED21_SH 20
-#define __CPE_CTRL_UNUSED21(_v) ((_v) << __CPE_CTRL_UNUSED21_SH)
-#define __CPE_CTRL_UNUSED11_MK 0x0000c000
-#define __CPE_CTRL_UNUSED11_SH 14
-#define __CPE_CTRL_UNUSED11(_v) ((_v) << __CPE_CTRL_UNUSED11_SH)
-#define __CPE_CTRL_UNUSED41_MK 0x00001c00
-#define __CPE_CTRL_UNUSED41_SH 10
-#define __CPE_CTRL_UNUSED41(_v) ((_v) << __CPE_CTRL_UNUSED41_SH)
-#define __CPE_CTRL_UNUSED01_MK 0x000000fe
-#define __CPE_CTRL_UNUSED01_SH 1
-#define __CPE_CTRL_UNUSED01(_v) ((_v) << __CPE_CTRL_UNUSED01_SH)
-#define RME_PI_PTR_Q0 0x00038020
-#define __LATENCY_TIME_STAMP_MK 0xffff0000
-#define __LATENCY_TIME_STAMP_SH 16
-#define __LATENCY_TIME_STAMP(_v) ((_v) << __LATENCY_TIME_STAMP_SH)
-#define __RME_PI_PTR 0x0000ffff
-#define RME_PI_PTR_Q1 0x00038060
-#define RME_CI_PTR_Q0 0x00038024
-#define __DELAY_TIME_STAMP_MK 0xffff0000
-#define __DELAY_TIME_STAMP_SH 16
-#define __DELAY_TIME_STAMP(_v) ((_v) << __DELAY_TIME_STAMP_SH)
-#define __RME_CI_PTR 0x0000ffff
-#define RME_CI_PTR_Q1 0x00038064
-#define RME_DEPTH_Q0 0x00038028
-#define __RME_DEPTH_UNUSED_MK 0xf8000000
-#define __RME_DEPTH_UNUSED_SH 27
-#define __RME_DEPTH_UNUSED(_v) ((_v) << __RME_DEPTH_UNUSED_SH)
-#define __RME_MSIX_VEC_INDEX_MK 0x07ff0000
-#define __RME_MSIX_VEC_INDEX_SH 16
-#define __RME_MSIX_VEC_INDEX(_v) ((_v) << __RME_MSIX_VEC_INDEX_SH)
-#define __RME_DEPTH 0x0000ffff
-#define RME_DEPTH_Q1 0x00038068
-#define RME_QCTRL_Q0 0x0003802c
-#define __RME_INT_LATENCY_TIMER_MK 0xff000000
-#define __RME_INT_LATENCY_TIMER_SH 24
-#define __RME_INT_LATENCY_TIMER(_v) ((_v) << __RME_INT_LATENCY_TIMER_SH)
-#define __RME_INT_DELAY_TIMER_MK 0x00ff0000
-#define __RME_INT_DELAY_TIMER_SH 16
-#define __RME_INT_DELAY_TIMER(_v) ((_v) << __RME_INT_DELAY_TIMER_SH)
-#define __RME_INT_DELAY_DISABLE 0x00008000
-#define __RME_DLY_DELAY_DISABLE 0x00004000
-#define __RME_ACK_PENDING 0x00002000
-#define __RME_FULL_INTERRUPT_DISABLE 0x00001000
-#define __RME_CTRL_UNUSED10_MK 0x00000c00
-#define __RME_CTRL_UNUSED10_SH 10
-#define __RME_CTRL_UNUSED10(_v) ((_v) << __RME_CTRL_UNUSED10_SH)
-#define __RME_PCIEID_MK 0x00000300
-#define __RME_PCIEID_SH 8
-#define __RME_PCIEID(_v) ((_v) << __RME_PCIEID_SH)
-#define __RME_CTRL_UNUSED00_MK 0x000000fe
-#define __RME_CTRL_UNUSED00_SH 1
-#define __RME_CTRL_UNUSED00(_v) ((_v) << __RME_CTRL_UNUSED00_SH)
-#define __RME_ESIZE 0x00000001
-#define RME_QCTRL_Q1 0x0003806c
-#define __RME_CTRL_UNUSED11_MK 0x00000c00
-#define __RME_CTRL_UNUSED11_SH 10
-#define __RME_CTRL_UNUSED11(_v) ((_v) << __RME_CTRL_UNUSED11_SH)
-#define __RME_CTRL_UNUSED01_MK 0x000000fe
-#define __RME_CTRL_UNUSED01_SH 1
-#define __RME_CTRL_UNUSED01(_v) ((_v) << __RME_CTRL_UNUSED01_SH)
-#define PSS_CTL_REG 0x00018800
-#define __PSS_I2C_CLK_DIV_MK 0x007f0000
-#define __PSS_I2C_CLK_DIV_SH 16
-#define __PSS_I2C_CLK_DIV(_v) ((_v) << __PSS_I2C_CLK_DIV_SH)
-#define __PSS_LMEM_INIT_DONE 0x00001000
-#define __PSS_LMEM_RESET 0x00000200
-#define __PSS_LMEM_INIT_EN 0x00000100
-#define __PSS_LPU1_RESET 0x00000002
-#define __PSS_LPU0_RESET 0x00000001
-#define PSS_ERR_STATUS_REG 0x00018810
-#define __PSS_LPU1_TCM_READ_ERR 0x00200000
-#define __PSS_LPU0_TCM_READ_ERR 0x00100000
-#define __PSS_LMEM5_CORR_ERR 0x00080000
-#define __PSS_LMEM4_CORR_ERR 0x00040000
-#define __PSS_LMEM3_CORR_ERR 0x00020000
-#define __PSS_LMEM2_CORR_ERR 0x00010000
-#define __PSS_LMEM1_CORR_ERR 0x00008000
-#define __PSS_LMEM0_CORR_ERR 0x00004000
-#define __PSS_LMEM5_UNCORR_ERR 0x00002000
-#define __PSS_LMEM4_UNCORR_ERR 0x00001000
-#define __PSS_LMEM3_UNCORR_ERR 0x00000800
-#define __PSS_LMEM2_UNCORR_ERR 0x00000400
-#define __PSS_LMEM1_UNCORR_ERR 0x00000200
-#define __PSS_LMEM0_UNCORR_ERR 0x00000100
-#define __PSS_BAL_PERR 0x00000080
-#define __PSS_DIP_IF_ERR 0x00000040
-#define __PSS_IOH_IF_ERR 0x00000020
-#define __PSS_TDS_IF_ERR 0x00000010
-#define __PSS_RDS_IF_ERR 0x00000008
-#define __PSS_SGM_IF_ERR 0x00000004
-#define __PSS_LPU1_RAM_ERR 0x00000002
-#define __PSS_LPU0_RAM_ERR 0x00000001
-#define ERR_SET_REG 0x00018818
-#define __PSS_ERR_STATUS_SET 0x003fffff
-#define PMM_1T_RESET_REG_P0 0x0002381c
-#define __PMM_1T_RESET_P 0x00000001
-#define PMM_1T_RESET_REG_P1 0x00023c1c
-#define HQM_QSET0_RXQ_DRBL_P0 0x00038000
-#define __RXQ0_ADD_VECTORS_P 0x80000000
-#define __RXQ0_STOP_P 0x40000000
-#define __RXQ0_PRD_PTR_P 0x0000ffff
-#define HQM_QSET1_RXQ_DRBL_P0 0x00038080
-#define __RXQ1_ADD_VECTORS_P 0x80000000
-#define __RXQ1_STOP_P 0x40000000
-#define __RXQ1_PRD_PTR_P 0x0000ffff
-#define HQM_QSET0_RXQ_DRBL_P1 0x0003c000
-#define HQM_QSET1_RXQ_DRBL_P1 0x0003c080
-#define HQM_QSET0_TXQ_DRBL_P0 0x00038020
-#define __TXQ0_ADD_VECTORS_P 0x80000000
-#define __TXQ0_STOP_P 0x40000000
-#define __TXQ0_PRD_PTR_P 0x0000ffff
-#define HQM_QSET1_TXQ_DRBL_P0 0x000380a0
-#define __TXQ1_ADD_VECTORS_P 0x80000000
-#define __TXQ1_STOP_P 0x40000000
-#define __TXQ1_PRD_PTR_P 0x0000ffff
-#define HQM_QSET0_TXQ_DRBL_P1 0x0003c020
-#define HQM_QSET1_TXQ_DRBL_P1 0x0003c0a0
-#define HQM_QSET0_IB_DRBL_1_P0 0x00038040
-#define __IB1_0_ACK_P 0x80000000
-#define __IB1_0_DISABLE_P 0x40000000
-#define __IB1_0_NUM_OF_ACKED_EVENTS_P 0x0000ffff
-#define HQM_QSET1_IB_DRBL_1_P0 0x000380c0
-#define __IB1_1_ACK_P 0x80000000
-#define __IB1_1_DISABLE_P 0x40000000
-#define __IB1_1_NUM_OF_ACKED_EVENTS_P 0x0000ffff
-#define HQM_QSET0_IB_DRBL_1_P1 0x0003c040
-#define HQM_QSET1_IB_DRBL_1_P1 0x0003c0c0
-#define HQM_QSET0_IB_DRBL_2_P0 0x00038060
-#define __IB2_0_ACK_P 0x80000000
-#define __IB2_0_DISABLE_P 0x40000000
-#define __IB2_0_NUM_OF_ACKED_EVENTS_P 0x0000ffff
-#define HQM_QSET1_IB_DRBL_2_P0 0x000380e0
-#define __IB2_1_ACK_P 0x80000000
-#define __IB2_1_DISABLE_P 0x40000000
-#define __IB2_1_NUM_OF_ACKED_EVENTS_P 0x0000ffff
-#define HQM_QSET0_IB_DRBL_2_P1 0x0003c060
-#define HQM_QSET1_IB_DRBL_2_P1 0x0003c0e0
-
-
-/*
- * These definitions are either in error/missing in spec. Its auto-generated
- * from hard coded values in regparse.pl.
- */
-#define __EMPHPOST_AT_4G_MK_FIX 0x0000001c
-#define __EMPHPOST_AT_4G_SH_FIX 0x00000002
-#define __EMPHPRE_AT_4G_FIX 0x00000003
-#define __SFP_TXRATE_EN_FIX 0x00000100
-#define __SFP_RXRATE_EN_FIX 0x00000080
-
-
-/*
- * These register definitions are auto-generated from hard coded values
- * in regparse.pl.
- */
-
-
-/*
- * These register mapping definitions are auto-generated from mapping tables
- * in regparse.pl.
- */
-#define BFA_IOC0_HBEAT_REG HOST_SEM0_INFO_REG
-#define BFA_IOC0_STATE_REG HOST_SEM1_INFO_REG
-#define BFA_IOC1_HBEAT_REG HOST_SEM2_INFO_REG
-#define BFA_IOC1_STATE_REG HOST_SEM3_INFO_REG
-#define BFA_FW_USE_COUNT HOST_SEM4_INFO_REG
-
-#define CPE_DEPTH_Q(__n) \
- (CPE_DEPTH_Q0 + (__n) * (CPE_DEPTH_Q1 - CPE_DEPTH_Q0))
-#define CPE_QCTRL_Q(__n) \
- (CPE_QCTRL_Q0 + (__n) * (CPE_QCTRL_Q1 - CPE_QCTRL_Q0))
-#define CPE_PI_PTR_Q(__n) \
- (CPE_PI_PTR_Q0 + (__n) * (CPE_PI_PTR_Q1 - CPE_PI_PTR_Q0))
-#define CPE_CI_PTR_Q(__n) \
- (CPE_CI_PTR_Q0 + (__n) * (CPE_CI_PTR_Q1 - CPE_CI_PTR_Q0))
-#define RME_DEPTH_Q(__n) \
- (RME_DEPTH_Q0 + (__n) * (RME_DEPTH_Q1 - RME_DEPTH_Q0))
-#define RME_QCTRL_Q(__n) \
- (RME_QCTRL_Q0 + (__n) * (RME_QCTRL_Q1 - RME_QCTRL_Q0))
-#define RME_PI_PTR_Q(__n) \
- (RME_PI_PTR_Q0 + (__n) * (RME_PI_PTR_Q1 - RME_PI_PTR_Q0))
-#define RME_CI_PTR_Q(__n) \
- (RME_CI_PTR_Q0 + (__n) * (RME_CI_PTR_Q1 - RME_CI_PTR_Q0))
-#define HQM_QSET_RXQ_DRBL_P0(__n) \
- (HQM_QSET0_RXQ_DRBL_P0 + (__n) * (HQM_QSET1_RXQ_DRBL_P0 - \
- HQM_QSET0_RXQ_DRBL_P0))
-#define HQM_QSET_TXQ_DRBL_P0(__n) \
- (HQM_QSET0_TXQ_DRBL_P0 + (__n) * (HQM_QSET1_TXQ_DRBL_P0 - \
- HQM_QSET0_TXQ_DRBL_P0))
-#define HQM_QSET_IB_DRBL_1_P0(__n) \
- (HQM_QSET0_IB_DRBL_1_P0 + (__n) * (HQM_QSET1_IB_DRBL_1_P0 - \
- HQM_QSET0_IB_DRBL_1_P0))
-#define HQM_QSET_IB_DRBL_2_P0(__n) \
- (HQM_QSET0_IB_DRBL_2_P0 + (__n) * (HQM_QSET1_IB_DRBL_2_P0 - \
- HQM_QSET0_IB_DRBL_2_P0))
-#define HQM_QSET_RXQ_DRBL_P1(__n) \
- (HQM_QSET0_RXQ_DRBL_P1 + (__n) * (HQM_QSET1_RXQ_DRBL_P1 - \
- HQM_QSET0_RXQ_DRBL_P1))
-#define HQM_QSET_TXQ_DRBL_P1(__n) \
- (HQM_QSET0_TXQ_DRBL_P1 + (__n) * (HQM_QSET1_TXQ_DRBL_P1 - \
- HQM_QSET0_TXQ_DRBL_P1))
-#define HQM_QSET_IB_DRBL_1_P1(__n) \
- (HQM_QSET0_IB_DRBL_1_P1 + (__n) * (HQM_QSET1_IB_DRBL_1_P1 - \
- HQM_QSET0_IB_DRBL_1_P1))
-#define HQM_QSET_IB_DRBL_2_P1(__n) \
- (HQM_QSET0_IB_DRBL_2_P1 + (__n) * (HQM_QSET1_IB_DRBL_2_P1 - \
- HQM_QSET0_IB_DRBL_2_P1))
-
-#define CPE_Q_NUM(__fn, __q) (((__fn) << 2) + (__q))
-#define RME_Q_NUM(__fn, __q) (((__fn) << 2) + (__q))
-#define CPE_Q_MASK(__q) ((__q) & 0x3)
-#define RME_Q_MASK(__q) ((__q) & 0x3)
-
-
-/*
- * PCI MSI-X vector defines
- */
-enum {
- BFA_MSIX_CPE_Q0 = 0,
- BFA_MSIX_CPE_Q1 = 1,
- BFA_MSIX_CPE_Q2 = 2,
- BFA_MSIX_CPE_Q3 = 3,
- BFA_MSIX_RME_Q0 = 4,
- BFA_MSIX_RME_Q1 = 5,
- BFA_MSIX_RME_Q2 = 6,
- BFA_MSIX_RME_Q3 = 7,
- BFA_MSIX_LPU_ERR = 8,
- BFA_MSIX_CT_MAX = 9,
-};
-
-/*
- * And corresponding host interrupt status bit field defines
- */
-#define __HFN_INT_CPE_Q0 0x00000001U
-#define __HFN_INT_CPE_Q1 0x00000002U
-#define __HFN_INT_CPE_Q2 0x00000004U
-#define __HFN_INT_CPE_Q3 0x00000008U
-#define __HFN_INT_CPE_Q4 0x00000010U
-#define __HFN_INT_CPE_Q5 0x00000020U
-#define __HFN_INT_CPE_Q6 0x00000040U
-#define __HFN_INT_CPE_Q7 0x00000080U
-#define __HFN_INT_RME_Q0 0x00000100U
-#define __HFN_INT_RME_Q1 0x00000200U
-#define __HFN_INT_RME_Q2 0x00000400U
-#define __HFN_INT_RME_Q3 0x00000800U
-#define __HFN_INT_RME_Q4 0x00001000U
-#define __HFN_INT_RME_Q5 0x00002000U
-#define __HFN_INT_RME_Q6 0x00004000U
-#define __HFN_INT_RME_Q7 0x00008000U
-#define __HFN_INT_ERR_EMC 0x00010000U
-#define __HFN_INT_ERR_LPU0 0x00020000U
-#define __HFN_INT_ERR_LPU1 0x00040000U
-#define __HFN_INT_ERR_PSS 0x00080000U
-#define __HFN_INT_MBOX_LPU0 0x00100000U
-#define __HFN_INT_MBOX_LPU1 0x00200000U
-#define __HFN_INT_MBOX1_LPU0 0x00400000U
-#define __HFN_INT_MBOX1_LPU1 0x00800000U
-#define __HFN_INT_LL_HALT 0x01000000U
-#define __HFN_INT_CPE_MASK 0x000000ffU
-#define __HFN_INT_RME_MASK 0x0000ff00U
-
-
-/*
- * catapult memory map.
- */
-#define LL_PGN_HQM0 0x0096
-#define LL_PGN_HQM1 0x0097
-#define PSS_SMEM_PAGE_START 0x8000
-#define PSS_SMEM_PGNUM(_pg0, _ma) ((_pg0) + ((_ma) >> 15))
-#define PSS_SMEM_PGOFF(_ma) ((_ma) & 0x7fff)
-
-/*
- * End of catapult memory map
- */
-
-
-#endif /* __BFI_CTREG_H__ */
-
diff --git a/drivers/scsi/bfa/include/bfi/bfi_fabric.h b/drivers/scsi/bfa/include/bfi/bfi_fabric.h
deleted file mode 100644
index c0669ed41078..000000000000
--- a/drivers/scsi/bfa/include/bfi/bfi_fabric.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFI_FABRIC_H__
-#define __BFI_FABRIC_H__
-
-#include <bfi/bfi.h>
-
-#pragma pack(1)
-
-enum bfi_fabric_h2i_msgs {
- BFI_FABRIC_H2I_CREATE_REQ = 1,
- BFI_FABRIC_H2I_DELETE_REQ = 2,
- BFI_FABRIC_H2I_SETAUTH = 3,
-};
-
-enum bfi_fabric_i2h_msgs {
- BFI_FABRIC_I2H_CREATE_RSP = BFA_I2HM(1),
- BFI_FABRIC_I2H_DELETE_RSP = BFA_I2HM(2),
- BFI_FABRIC_I2H_SETAUTH_RSP = BFA_I2HM(3),
- BFI_FABRIC_I2H_ONLINE = BFA_I2HM(4),
- BFI_FABRIC_I2H_OFFLINE = BFA_I2HM(5),
-};
-
-struct bfi_fabric_create_req_s {
- bfi_mhdr_t mh; /* common msg header */
- u8 vf_en; /* virtual fabric enable */
- u8 rsvd;
- u16 vf_id; /* virtual fabric ID */
- wwn_t pwwn; /* port name */
- wwn_t nwwn; /* node name */
-};
-
-struct bfi_fabric_create_rsp_s {
- bfi_mhdr_t mh; /* common msg header */
- u16 bfa_handle; /* host fabric handle */
- u8 status; /* fabric create status */
- u8 rsvd;
-};
-
-struct bfi_fabric_delete_req_s {
- bfi_mhdr_t mh; /* common msg header */
- u16 fw_handle; /* firmware fabric handle */
- u16 rsvd;
-};
-
-struct bfi_fabric_delete_rsp_s {
- bfi_mhdr_t mh; /* common msg header */
- u16 bfa_handle; /* host fabric handle */
- u8 status; /* fabric deletion status */
- u8 rsvd;
-};
-
-#define BFI_FABRIC_AUTHSECRET_LEN 64
-struct bfi_fabric_setauth_req_s {
- bfi_mhdr_t mh; /* common msg header */
- u16 fw_handle; /* f/w handle of fabric */
- u8 algorithm;
- u8 group;
- u8 secret[BFI_FABRIC_AUTHSECRET_LEN];
-};
-
-union bfi_fabric_h2i_msg_u {
- bfi_msg_t *msg;
- struct bfi_fabric_create_req_s *create_req;
- struct bfi_fabric_delete_req_s *delete_req;
-};
-
-union bfi_fabric_i2h_msg_u {
- bfi_msg_t *msg;
- struct bfi_fabric_create_rsp_s *create_rsp;
- struct bfi_fabric_delete_rsp_s *delete_rsp;
-};
-
-#pragma pack()
-
-#endif /* __BFI_FABRIC_H__ */
-
diff --git a/drivers/scsi/bfa/include/bfi/bfi_fcpim.h b/drivers/scsi/bfa/include/bfi/bfi_fcpim.h
deleted file mode 100644
index 52c059fb4c3a..000000000000
--- a/drivers/scsi/bfa/include/bfi/bfi_fcpim.h
+++ /dev/null
@@ -1,301 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFI_FCPIM_H__
-#define __BFI_FCPIM_H__
-
-#include "bfi.h"
-#include <protocol/fcp.h>
-
-#pragma pack(1)
-
-/*
- * Initiator mode I-T nexus interface defines.
- */
-
-enum bfi_itnim_h2i {
- BFI_ITNIM_H2I_CREATE_REQ = 1, /* i-t nexus creation */
- BFI_ITNIM_H2I_DELETE_REQ = 2, /* i-t nexus deletion */
-};
-
-enum bfi_itnim_i2h {
- BFI_ITNIM_I2H_CREATE_RSP = BFA_I2HM(1),
- BFI_ITNIM_I2H_DELETE_RSP = BFA_I2HM(2),
- BFI_ITNIM_I2H_SLER_EVENT = BFA_I2HM(3),
-};
-
-struct bfi_itnim_create_req_s {
- struct bfi_mhdr_s mh; /* common msg header */
- u16 fw_handle; /* f/w handle for itnim */
- u8 class; /* FC class for IO */
- u8 seq_rec; /* sequence recovery support */
- u8 msg_no; /* seq id of the msg */
-};
-
-struct bfi_itnim_create_rsp_s {
- struct bfi_mhdr_s mh; /* common msg header */
- u16 bfa_handle; /* bfa handle for itnim */
- u8 status; /* fcp request status */
- u8 seq_id; /* seq id of the msg */
-};
-
-struct bfi_itnim_delete_req_s {
- struct bfi_mhdr_s mh; /* common msg header */
- u16 fw_handle; /* f/w itnim handle */
- u8 seq_id; /* seq id of the msg */
- u8 rsvd;
-};
-
-struct bfi_itnim_delete_rsp_s {
- struct bfi_mhdr_s mh; /* common msg header */
- u16 bfa_handle; /* bfa handle for itnim */
- u8 status; /* fcp request status */
- u8 seq_id; /* seq id of the msg */
-};
-
-struct bfi_itnim_sler_event_s {
- struct bfi_mhdr_s mh; /* common msg header */
- u16 bfa_handle; /* bfa handle for itnim */
- u16 rsvd;
-};
-
-union bfi_itnim_h2i_msg_u {
- struct bfi_itnim_create_req_s *create_req;
- struct bfi_itnim_delete_req_s *delete_req;
- struct bfi_msg_s *msg;
-};
-
-union bfi_itnim_i2h_msg_u {
- struct bfi_itnim_create_rsp_s *create_rsp;
- struct bfi_itnim_delete_rsp_s *delete_rsp;
- struct bfi_itnim_sler_event_s *sler_event;
- struct bfi_msg_s *msg;
-};
-
-/*
- * Initiator mode IO interface defines.
- */
-
-enum bfi_ioim_h2i {
- BFI_IOIM_H2I_IOABORT_REQ = 1, /* IO abort request */
- BFI_IOIM_H2I_IOCLEANUP_REQ = 2, /* IO cleanup request */
-};
-
-enum bfi_ioim_i2h {
- BFI_IOIM_I2H_IO_RSP = BFA_I2HM(1), /* non-fp IO response */
- BFI_IOIM_I2H_IOABORT_RSP = BFA_I2HM(2),/* ABORT rsp */
-};
-
-/**
- * IO command DIF info
- */
-struct bfi_ioim_dif_s {
- u32 dif_info[4];
-};
-
-/**
- * FCP IO messages overview
- *
- * @note
- * - Max CDB length supported is 64 bytes.
- * - SCSI Linked commands and SCSI bi-directional Commands not
- * supported.
- *
- */
-struct bfi_ioim_req_s {
- struct bfi_mhdr_s mh; /* Common msg header */
- u16 io_tag; /* I/O tag */
- u16 rport_hdl; /* itnim/rport firmware handle */
- struct fcp_cmnd_s cmnd; /* IO request info */
-
- /**
- * SG elements array within the IO request must be double word
- * aligned. This aligment is required to optimize SGM setup for the IO.
- */
- struct bfi_sge_s sges[BFI_SGE_INLINE_MAX];
- u8 io_timeout;
- u8 dif_en;
- u8 rsvd_a[2];
- struct bfi_ioim_dif_s dif;
-};
-
-/**
- * This table shows various IO status codes from firmware and their
- * meaning. Host driver can use these status codes to further process
- * IO completions.
- *
- * BFI_IOIM_STS_OK : IO completed with error free SCSI &
- * transport status.
- * - io-tag can be reused.
- *
- * BFA_IOIM_STS_SCSI_ERR : IO completed with scsi error.
- * - io-tag can be reused.
- *
- * BFI_IOIM_STS_HOST_ABORTED : IO was aborted successfully due to
- * host request.
- * - io-tag cannot be reused yet.
- *
- * BFI_IOIM_STS_ABORTED : IO was aborted successfully
- * internally by f/w.
- * - io-tag cannot be reused yet.
- *
- * BFI_IOIM_STS_TIMEDOUT : IO timedout and ABTS/RRQ is happening
- * in the firmware and
- * - io-tag cannot be reused yet.
- *
- * BFI_IOIM_STS_SQER_NEEDED : Firmware could not recover the IO
- * with sequence level error
- * logic and hence host needs to retry
- * this IO with a different IO tag
- * - io-tag cannot be used yet.
- *
- * BFI_IOIM_STS_NEXUS_ABORT : Second Level Error Recovery from host
- * is required because 2 consecutive ABTS
- * timedout and host needs logout and
- * re-login with the target
- * - io-tag cannot be used yet.
- *
- * BFI_IOIM_STS_UNDERRUN : IO completed with SCSI status good,
- * but the data tranferred is less than
- * the fcp data length in the command.
- * ex. SCSI INQUIRY where transferred
- * data length and residue count in FCP
- * response accounts for total fcp-dl
- * - io-tag can be reused.
- *
- * BFI_IOIM_STS_OVERRUN : IO completed with SCSI status good,
- * but the data transerred is more than
- * fcp data length in the command. ex.
- * TAPE IOs where blocks can of unequal
- * lengths.
- * - io-tag can be reused.
- *
- * BFI_IOIM_STS_RES_FREE : Firmware has completed using io-tag
- * during abort process
- * - io-tag can be reused.
- *
- * BFI_IOIM_STS_PROTO_ERR : Firmware detected a protocol error.
- * ex target sent more data than
- * requested, or there was data frame
- * loss and other reasons
- * - io-tag cannot be used yet.
- *
- * BFI_IOIM_STS_DIF_ERR : Firwmare detected DIF error. ex: DIF
- * CRC err or Ref Tag err or App tag err.
- * - io-tag can be reused.
- *
- * BFA_IOIM_STS_TSK_MGT_ABORT : IO was aborted because of Task
- * Management command from the host
- * - io-tag can be reused.
- *
- * BFI_IOIM_STS_UTAG : Firmware does not know about this
- * io_tag.
- * - io-tag can be reused.
- */
-enum bfi_ioim_status {
- BFI_IOIM_STS_OK = 0,
- BFI_IOIM_STS_HOST_ABORTED = 1,
- BFI_IOIM_STS_ABORTED = 2,
- BFI_IOIM_STS_TIMEDOUT = 3,
- BFI_IOIM_STS_RES_FREE = 4,
- BFI_IOIM_STS_SQER_NEEDED = 5,
- BFI_IOIM_STS_PROTO_ERR = 6,
- BFI_IOIM_STS_UTAG = 7,
- BFI_IOIM_STS_PATHTOV = 8,
-};
-
-#define BFI_IOIM_SNSLEN (256)
-/**
- * I/O response message
- */
-struct bfi_ioim_rsp_s {
- struct bfi_mhdr_s mh; /* common msg header */
- u16 io_tag; /* completed IO tag */
- u16 bfa_rport_hndl; /* releated rport handle */
- u8 io_status; /* IO completion status */
- u8 reuse_io_tag; /* IO tag can be reused */
- u16 abort_tag; /* host abort request tag */
- u8 scsi_status; /* scsi status from target */
- u8 sns_len; /* scsi sense length */
- u8 resid_flags; /* IO residue flags */
- u8 rsvd_a;
- u32 residue; /* IO residual length in bytes */
- u32 rsvd_b[3];
-};
-
-struct bfi_ioim_abort_req_s {
- struct bfi_mhdr_s mh; /* Common msg header */
- u16 io_tag; /* I/O tag */
- u16 abort_tag; /* unique request tag */
-};
-
-/*
- * Initiator mode task management command interface defines.
- */
-
-enum bfi_tskim_h2i {
- BFI_TSKIM_H2I_TM_REQ = 1, /* task-mgmt command */
- BFI_TSKIM_H2I_ABORT_REQ = 2, /* task-mgmt command */
-};
-
-enum bfi_tskim_i2h {
- BFI_TSKIM_I2H_TM_RSP = BFA_I2HM(1),
-};
-
-struct bfi_tskim_req_s {
- struct bfi_mhdr_s mh; /* Common msg header */
- u16 tsk_tag; /* task management tag */
- u16 itn_fhdl; /* itn firmware handle */
- lun_t lun; /* LU number */
- u8 tm_flags; /* see fcp_tm_cmnd_t */
- u8 t_secs; /* Timeout value in seconds */
- u8 rsvd[2];
-};
-
-struct bfi_tskim_abortreq_s {
- struct bfi_mhdr_s mh; /* Common msg header */
- u16 tsk_tag; /* task management tag */
- u16 rsvd;
-};
-
-enum bfi_tskim_status {
- /*
- * Following are FCP-4 spec defined status codes,
- * **DO NOT CHANGE THEM **
- */
- BFI_TSKIM_STS_OK = 0,
- BFI_TSKIM_STS_NOT_SUPP = 4,
- BFI_TSKIM_STS_FAILED = 5,
-
- /**
- * Defined by BFA
- */
- BFI_TSKIM_STS_TIMEOUT = 10, /* TM request timedout */
- BFI_TSKIM_STS_ABORTED = 11, /* Aborted on host request */
-};
-
-struct bfi_tskim_rsp_s {
- struct bfi_mhdr_s mh; /* Common msg header */
- u16 tsk_tag; /* task mgmt cmnd tag */
- u8 tsk_status; /* @ref bfi_tskim_status */
- u8 rsvd;
-};
-
-#pragma pack()
-
-#endif /* __BFI_FCPIM_H__ */
-
diff --git a/drivers/scsi/bfa/include/bfi/bfi_fcxp.h b/drivers/scsi/bfa/include/bfi/bfi_fcxp.h
deleted file mode 100644
index e0e995a32828..000000000000
--- a/drivers/scsi/bfa/include/bfi/bfi_fcxp.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFI_FCXP_H__
-#define __BFI_FCXP_H__
-
-#include "bfi.h"
-
-#pragma pack(1)
-
-enum bfi_fcxp_h2i {
- BFI_FCXP_H2I_SEND_REQ = 1,
-};
-
-enum bfi_fcxp_i2h {
- BFI_FCXP_I2H_SEND_RSP = BFA_I2HM(1),
-};
-
-#define BFA_FCXP_MAX_SGES 2
-
-/**
- * FCXP send request structure
- */
-struct bfi_fcxp_send_req_s {
- struct bfi_mhdr_s mh; /* Common msg header */
- u16 fcxp_tag; /* driver request tag */
- u16 max_frmsz; /* max send frame size */
- u16 vf_id; /* vsan tag if applicable */
- u16 rport_fw_hndl; /* FW Handle for the remote port */
- u8 class; /* FC class used for req/rsp */
- u8 rsp_timeout; /* timeout in secs, 0-no response */
- u8 cts; /* continue sequence */
- u8 lp_tag; /* lport tag */
- struct fchs_s fchs; /* request FC header structure */
- u32 req_len; /* request payload length */
- u32 rsp_maxlen; /* max response length expected */
- struct bfi_sge_s req_sge[BFA_FCXP_MAX_SGES]; /* request buf */
- struct bfi_sge_s rsp_sge[BFA_FCXP_MAX_SGES]; /* response buf */
-};
-
-/**
- * FCXP send response structure
- */
-struct bfi_fcxp_send_rsp_s {
- struct bfi_mhdr_s mh; /* Common msg header */
- u16 fcxp_tag; /* send request tag */
- u8 req_status; /* request status */
- u8 rsvd;
- u32 rsp_len; /* actual response length */
- u32 residue_len; /* residual response length */
- struct fchs_s fchs; /* response FC header structure */
-};
-
-#pragma pack()
-
-#endif /* __BFI_FCXP_H__ */
-
diff --git a/drivers/scsi/bfa/include/bfi/bfi_ioc.h b/drivers/scsi/bfa/include/bfi/bfi_ioc.h
deleted file mode 100644
index 450ded6e9bc2..000000000000
--- a/drivers/scsi/bfa/include/bfi/bfi_ioc.h
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFI_IOC_H__
-#define __BFI_IOC_H__
-
-#include "bfi.h"
-#include <defs/bfa_defs_ioc.h>
-
-#pragma pack(1)
-
-enum bfi_ioc_h2i_msgs {
- BFI_IOC_H2I_ENABLE_REQ = 1,
- BFI_IOC_H2I_DISABLE_REQ = 2,
- BFI_IOC_H2I_GETATTR_REQ = 3,
- BFI_IOC_H2I_DBG_SYNC = 4,
- BFI_IOC_H2I_DBG_DUMP = 5,
-};
-
-enum bfi_ioc_i2h_msgs {
- BFI_IOC_I2H_ENABLE_REPLY = BFA_I2HM(1),
- BFI_IOC_I2H_DISABLE_REPLY = BFA_I2HM(2),
- BFI_IOC_I2H_GETATTR_REPLY = BFA_I2HM(3),
- BFI_IOC_I2H_READY_EVENT = BFA_I2HM(4),
- BFI_IOC_I2H_HBEAT = BFA_I2HM(5),
-};
-
-/**
- * BFI_IOC_H2I_GETATTR_REQ message
- */
-struct bfi_ioc_getattr_req_s {
- struct bfi_mhdr_s mh;
- union bfi_addr_u attr_addr;
-};
-
-struct bfi_ioc_attr_s {
- wwn_t mfg_pwwn; /* Mfg port wwn */
- wwn_t mfg_nwwn; /* Mfg node wwn */
- mac_t mfg_mac; /* Mfg mac */
- u16 rsvd_a;
- wwn_t pwwn;
- wwn_t nwwn;
- mac_t mac; /* PBC or Mfg mac */
- u16 rsvd_b;
- char brcd_serialnum[STRSZ(BFA_MFG_SERIALNUM_SIZE)];
- u8 pcie_gen;
- u8 pcie_lanes_orig;
- u8 pcie_lanes;
- u8 rx_bbcredit; /* receive buffer credits */
- u32 adapter_prop; /* adapter properties */
- u16 maxfrsize; /* max receive frame size */
- char asic_rev;
- u8 rsvd_c;
- char fw_version[BFA_VERSION_LEN];
- char optrom_version[BFA_VERSION_LEN];
- struct bfa_mfg_vpd_s vpd;
- u32 card_type; /* card type */
-};
-
-/**
- * BFI_IOC_I2H_GETATTR_REPLY message
- */
-struct bfi_ioc_getattr_reply_s {
- struct bfi_mhdr_s mh; /* Common msg header */
- u8 status; /* cfg reply status */
- u8 rsvd[3];
-};
-
-/**
- * Firmware memory page offsets
- */
-#define BFI_IOC_SMEM_PG0_CB (0x40)
-#define BFI_IOC_SMEM_PG0_CT (0x180)
-
-/**
- * Firmware trace offset
- */
-#define BFI_IOC_TRC_OFF (0x4b00)
-#define BFI_IOC_TRC_ENTS 256
-
-#define BFI_IOC_FW_SIGNATURE (0xbfadbfad)
-#define BFI_IOC_MD5SUM_SZ 4
-struct bfi_ioc_image_hdr_s {
- u32 signature; /* constant signature */
- u32 rsvd_a;
- u32 exec; /* exec vector */
- u32 param; /* parameters */
- u32 rsvd_b[4];
- u32 md5sum[BFI_IOC_MD5SUM_SZ];
-};
-
-/**
- * BFI_IOC_I2H_READY_EVENT message
- */
-struct bfi_ioc_rdy_event_s {
- struct bfi_mhdr_s mh; /* common msg header */
- u8 init_status; /* init event status */
- u8 rsvd[3];
-};
-
-struct bfi_ioc_hbeat_s {
- struct bfi_mhdr_s mh; /* common msg header */
- u32 hb_count; /* current heart beat count */
-};
-
-/**
- * IOC hardware/firmware state
- */
-enum bfi_ioc_state {
- BFI_IOC_UNINIT = 0, /* not initialized */
- BFI_IOC_INITING = 1, /* h/w is being initialized */
- BFI_IOC_HWINIT = 2, /* h/w is initialized */
- BFI_IOC_CFG = 3, /* IOC configuration in progress */
- BFI_IOC_OP = 4, /* IOC is operational */
- BFI_IOC_DISABLING = 5, /* IOC is being disabled */
- BFI_IOC_DISABLED = 6, /* IOC is disabled */
- BFI_IOC_CFG_DISABLED = 7, /* IOC is being disabled;transient */
- BFI_IOC_FAIL = 8, /* IOC heart-beat failure */
- BFI_IOC_MEMTEST = 9, /* IOC is doing memtest */
-};
-
-#define BFI_IOC_ENDIAN_SIG 0x12345678
-
-enum {
- BFI_ADAPTER_TYPE_FC = 0x01, /* FC adapters */
- BFI_ADAPTER_TYPE_MK = 0x0f0000, /* adapter type mask */
- BFI_ADAPTER_TYPE_SH = 16, /* adapter type shift */
- BFI_ADAPTER_NPORTS_MK = 0xff00, /* number of ports mask */
- BFI_ADAPTER_NPORTS_SH = 8, /* number of ports shift */
- BFI_ADAPTER_SPEED_MK = 0xff, /* adapter speed mask */
- BFI_ADAPTER_SPEED_SH = 0, /* adapter speed shift */
- BFI_ADAPTER_PROTO = 0x100000, /* prototype adapaters */
- BFI_ADAPTER_TTV = 0x200000, /* TTV debug capable */
- BFI_ADAPTER_UNSUPP = 0x400000, /* unknown adapter type */
-};
-
-#define BFI_ADAPTER_GETP(__prop, __adap_prop) \
- (((__adap_prop) & BFI_ADAPTER_ ## __prop ## _MK) >> \
- BFI_ADAPTER_ ## __prop ## _SH)
-#define BFI_ADAPTER_SETP(__prop, __val) \
- ((__val) << BFI_ADAPTER_ ## __prop ## _SH)
-#define BFI_ADAPTER_IS_PROTO(__adap_type) \
- ((__adap_type) & BFI_ADAPTER_PROTO)
-#define BFI_ADAPTER_IS_TTV(__adap_type) \
- ((__adap_type) & BFI_ADAPTER_TTV)
-#define BFI_ADAPTER_IS_UNSUPP(__adap_type) \
- ((__adap_type) & BFI_ADAPTER_UNSUPP)
-#define BFI_ADAPTER_IS_SPECIAL(__adap_type) \
- ((__adap_type) & (BFI_ADAPTER_TTV | BFI_ADAPTER_PROTO | \
- BFI_ADAPTER_UNSUPP))
-
-/**
- * BFI_IOC_H2I_ENABLE_REQ & BFI_IOC_H2I_DISABLE_REQ messages
- */
-struct bfi_ioc_ctrl_req_s {
- struct bfi_mhdr_s mh;
- u8 ioc_class;
- u8 rsvd[3];
-};
-
-/**
- * BFI_IOC_I2H_ENABLE_REPLY & BFI_IOC_I2H_DISABLE_REPLY messages
- */
-struct bfi_ioc_ctrl_reply_s {
- struct bfi_mhdr_s mh; /* Common msg header */
- u8 status; /* enable/disable status */
- u8 rsvd[3];
-};
-
-#define BFI_IOC_MSGSZ 8
-/**
- * H2I Messages
- */
-union bfi_ioc_h2i_msg_u {
- struct bfi_mhdr_s mh;
- struct bfi_ioc_ctrl_req_s enable_req;
- struct bfi_ioc_ctrl_req_s disable_req;
- struct bfi_ioc_getattr_req_s getattr_req;
- u32 mboxmsg[BFI_IOC_MSGSZ];
-};
-
-/**
- * I2H Messages
- */
-union bfi_ioc_i2h_msg_u {
- struct bfi_mhdr_s mh;
- struct bfi_ioc_rdy_event_s rdy_event;
- u32 mboxmsg[BFI_IOC_MSGSZ];
-};
-
-#pragma pack()
-
-#endif /* __BFI_IOC_H__ */
-
diff --git a/drivers/scsi/bfa/include/bfi/bfi_iocfc.h b/drivers/scsi/bfa/include/bfi/bfi_iocfc.h
deleted file mode 100644
index ccdfcc5d7e0b..000000000000
--- a/drivers/scsi/bfa/include/bfi/bfi_iocfc.h
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFI_IOCFC_H__
-#define __BFI_IOCFC_H__
-
-#include "bfi.h"
-#include <bfi/bfi_pbc.h>
-#include <defs/bfa_defs_ioc.h>
-#include <defs/bfa_defs_iocfc.h>
-#include <defs/bfa_defs_boot.h>
-
-#pragma pack(1)
-
-enum bfi_iocfc_h2i_msgs {
- BFI_IOCFC_H2I_CFG_REQ = 1,
- BFI_IOCFC_H2I_GET_STATS_REQ = 2,
- BFI_IOCFC_H2I_CLEAR_STATS_REQ = 3,
- BFI_IOCFC_H2I_SET_INTR_REQ = 4,
- BFI_IOCFC_H2I_UPDATEQ_REQ = 5,
-};
-
-enum bfi_iocfc_i2h_msgs {
- BFI_IOCFC_I2H_CFG_REPLY = BFA_I2HM(1),
- BFI_IOCFC_I2H_GET_STATS_RSP = BFA_I2HM(2),
- BFI_IOCFC_I2H_CLEAR_STATS_RSP = BFA_I2HM(3),
- BFI_IOCFC_I2H_UPDATEQ_RSP = BFA_I2HM(5),
-};
-
-struct bfi_iocfc_cfg_s {
- u8 num_cqs; /* Number of CQs to be used */
- u8 sense_buf_len; /* SCSI sense length */
- u8 trunk_enabled; /* port trunking enabled */
- u8 trunk_ports; /* trunk ports bit map */
- u32 endian_sig; /* endian signature of host */
-
- /**
- * Request and response circular queue base addresses, size and
- * shadow index pointers.
- */
- union bfi_addr_u req_cq_ba[BFI_IOC_MAX_CQS];
- union bfi_addr_u req_shadow_ci[BFI_IOC_MAX_CQS];
- u16 req_cq_elems[BFI_IOC_MAX_CQS];
- union bfi_addr_u rsp_cq_ba[BFI_IOC_MAX_CQS];
- union bfi_addr_u rsp_shadow_pi[BFI_IOC_MAX_CQS];
- u16 rsp_cq_elems[BFI_IOC_MAX_CQS];
-
- union bfi_addr_u stats_addr; /* DMA-able address for stats */
- union bfi_addr_u cfgrsp_addr; /* config response dma address */
- union bfi_addr_u ioim_snsbase; /* IO sense buffer base address */
- struct bfa_iocfc_intr_attr_s intr_attr; /* IOC interrupt attributes */
-};
-
-/**
- * Boot target wwn information for this port. This contains either the stored
- * or discovered boot target port wwns for the port.
- */
-struct bfi_iocfc_bootwwns {
- wwn_t wwn[BFA_BOOT_BOOTLUN_MAX];
- u8 nwwns;
- u8 rsvd[7];
-};
-
-struct bfi_iocfc_cfgrsp_s {
- struct bfa_iocfc_fwcfg_s fwcfg;
- struct bfa_iocfc_intr_attr_s intr_attr;
- struct bfi_iocfc_bootwwns bootwwns;
- struct bfi_pbc_s pbc_cfg;
-};
-
-/**
- * BFI_IOCFC_H2I_CFG_REQ message
- */
-struct bfi_iocfc_cfg_req_s {
- struct bfi_mhdr_s mh;
- union bfi_addr_u ioc_cfg_dma_addr;
-};
-
-/**
- * BFI_IOCFC_I2H_CFG_REPLY message
- */
-struct bfi_iocfc_cfg_reply_s {
- struct bfi_mhdr_s mh; /* Common msg header */
- u8 cfg_success; /* cfg reply status */
- u8 lpu_bm; /* LPUs assigned for this IOC */
- u8 rsvd[2];
-};
-
-/**
- * BFI_IOCFC_H2I_GET_STATS_REQ & BFI_IOCFC_H2I_CLEAR_STATS_REQ messages
- */
-struct bfi_iocfc_stats_req_s {
- struct bfi_mhdr_s mh; /* msg header */
- u32 msgtag; /* msgtag for reply */
-};
-
-/**
- * BFI_IOCFC_I2H_GET_STATS_RSP & BFI_IOCFC_I2H_CLEAR_STATS_RSP messages
- */
-struct bfi_iocfc_stats_rsp_s {
- struct bfi_mhdr_s mh; /* common msg header */
- u8 status; /* reply status */
- u8 rsvd[3];
- u32 msgtag; /* msgtag for reply */
-};
-
-/**
- * BFI_IOCFC_H2I_SET_INTR_REQ message
- */
-struct bfi_iocfc_set_intr_req_s {
- struct bfi_mhdr_s mh; /* common msg header */
- u8 coalesce; /* enable intr coalescing*/
- u8 rsvd[3];
- u16 delay; /* delay timer 0..1125us */
- u16 latency; /* latency timer 0..225us */
-};
-
-/**
- * BFI_IOCFC_H2I_UPDATEQ_REQ message
- */
-struct bfi_iocfc_updateq_req_s {
- struct bfi_mhdr_s mh; /* common msg header */
- u32 reqq_ba; /* reqq base addr */
- u32 rspq_ba; /* rspq base addr */
- u32 reqq_sci; /* reqq shadow ci */
- u32 rspq_spi; /* rspq shadow pi */
-};
-
-/**
- * BFI_IOCFC_I2H_UPDATEQ_RSP message
- */
-struct bfi_iocfc_updateq_rsp_s {
- struct bfi_mhdr_s mh; /* common msg header */
- u8 status; /* updateq status */
- u8 rsvd[3];
-};
-
-/**
- * H2I Messages
- */
-union bfi_iocfc_h2i_msg_u {
- struct bfi_mhdr_s mh;
- struct bfi_iocfc_cfg_req_s cfg_req;
- struct bfi_iocfc_stats_req_s stats_get;
- struct bfi_iocfc_stats_req_s stats_clr;
- struct bfi_iocfc_updateq_req_s updateq_req;
- u32 mboxmsg[BFI_IOC_MSGSZ];
-};
-
-/**
- * I2H Messages
- */
-union bfi_iocfc_i2h_msg_u {
- struct bfi_mhdr_s mh;
- struct bfi_iocfc_cfg_reply_s cfg_reply;
- struct bfi_iocfc_stats_rsp_s stats_get_rsp;
- struct bfi_iocfc_stats_rsp_s stats_clr_rsp;
- struct bfi_iocfc_updateq_rsp_s updateq_rsp;
- u32 mboxmsg[BFI_IOC_MSGSZ];
-};
-
-#pragma pack()
-
-#endif /* __BFI_IOCFC_H__ */
-
diff --git a/drivers/scsi/bfa/include/bfi/bfi_lport.h b/drivers/scsi/bfa/include/bfi/bfi_lport.h
deleted file mode 100644
index 29010614bac9..000000000000
--- a/drivers/scsi/bfa/include/bfi/bfi_lport.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFI_LPORT_H__
-#define __BFI_LPORT_H__
-
-#include <bfi/bfi.h>
-
-#pragma pack(1)
-
-enum bfi_lport_h2i_msgs {
- BFI_LPORT_H2I_CREATE_REQ = 1,
- BFI_LPORT_H2I_DELETE_REQ = 2,
-};
-
-enum bfi_lport_i2h_msgs {
- BFI_LPORT_I2H_CREATE_RSP = BFA_I2HM(1),
- BFI_LPORT_I2H_DELETE_RSP = BFA_I2HM(2),
- BFI_LPORT_I2H_ONLINE = BFA_I2HM(3),
- BFI_LPORT_I2H_OFFLINE = BFA_I2HM(4),
-};
-
-#define BFI_LPORT_MAX_SYNNAME 64
-
-enum bfi_lport_role_e {
- BFI_LPORT_ROLE_FCPIM = 1,
- BFI_LPORT_ROLE_FCPTM = 2,
- BFI_LPORT_ROLE_IPFC = 4,
-};
-
-struct bfi_lport_create_req_s {
- bfi_mhdr_t mh; /* common msg header */
- u16 fabric_fwhdl; /* parent fabric instance */
- u8 roles; /* lport FC-4 roles */
- u8 rsvd;
- wwn_t pwwn; /* port name */
- wwn_t nwwn; /* node name */
- u8 symname[BFI_LPORT_MAX_SYNNAME];
-};
-
-struct bfi_lport_create_rsp_s {
- bfi_mhdr_t mh; /* common msg header */
- u8 status; /* lport creation status */
- u8 rsvd[3];
-};
-
-struct bfi_lport_delete_req_s {
- bfi_mhdr_t mh; /* common msg header */
- u16 fw_handle; /* firmware lport handle */
- u16 rsvd;
-};
-
-struct bfi_lport_delete_rsp_s {
- bfi_mhdr_t mh; /* common msg header */
- u16 bfa_handle; /* host lport handle */
- u8 status; /* lport deletion status */
- u8 rsvd;
-};
-
-union bfi_lport_h2i_msg_u {
- bfi_msg_t *msg;
- struct bfi_lport_create_req_s *create_req;
- struct bfi_lport_delete_req_s *delete_req;
-};
-
-union bfi_lport_i2h_msg_u {
- bfi_msg_t *msg;
- struct bfi_lport_create_rsp_s *create_rsp;
- struct bfi_lport_delete_rsp_s *delete_rsp;
-};
-
-#pragma pack()
-
-#endif /* __BFI_LPORT_H__ */
-
diff --git a/drivers/scsi/bfa/include/bfi/bfi_lps.h b/drivers/scsi/bfa/include/bfi/bfi_lps.h
deleted file mode 100644
index 7ed31bbb8696..000000000000
--- a/drivers/scsi/bfa/include/bfi/bfi_lps.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFI_LPS_H__
-#define __BFI_LPS_H__
-
-#include <bfi/bfi.h>
-
-#pragma pack(1)
-
-enum bfi_lps_h2i_msgs {
- BFI_LPS_H2I_LOGIN_REQ = 1,
- BFI_LPS_H2I_LOGOUT_REQ = 2,
-};
-
-enum bfi_lps_i2h_msgs {
- BFI_LPS_H2I_LOGIN_RSP = BFA_I2HM(1),
- BFI_LPS_H2I_LOGOUT_RSP = BFA_I2HM(2),
- BFI_LPS_H2I_CVL_EVENT = BFA_I2HM(3),
-};
-
-struct bfi_lps_login_req_s {
- struct bfi_mhdr_s mh; /* common msg header */
- u8 lp_tag;
- u8 alpa;
- u16 pdu_size;
- wwn_t pwwn;
- wwn_t nwwn;
- u8 fdisc;
- u8 auth_en;
- u8 rsvd[2];
-};
-
-struct bfi_lps_login_rsp_s {
- struct bfi_mhdr_s mh; /* common msg header */
- u8 lp_tag;
- u8 status;
- u8 lsrjt_rsn;
- u8 lsrjt_expl;
- wwn_t port_name;
- wwn_t node_name;
- u16 bb_credit;
- u8 f_port;
- u8 npiv_en;
- u32 lp_pid:24;
- u32 auth_req:8;
- mac_t lp_mac;
- mac_t fcf_mac;
- u8 ext_status;
- u8 brcd_switch;/* attached peer is brcd switch */
-};
-
-struct bfi_lps_logout_req_s {
- struct bfi_mhdr_s mh; /* common msg header */
- u8 lp_tag;
- u8 rsvd[3];
- wwn_t port_name;
-};
-
-struct bfi_lps_logout_rsp_s {
- struct bfi_mhdr_s mh; /* common msg header */
- u8 lp_tag;
- u8 status;
- u8 rsvd[2];
-};
-
-struct bfi_lps_cvl_event_s {
- struct bfi_mhdr_s mh; /* common msg header */
- u8 lp_tag;
- u8 rsvd[3];
-};
-
-union bfi_lps_h2i_msg_u {
- struct bfi_mhdr_s *msg;
- struct bfi_lps_login_req_s *login_req;
- struct bfi_lps_logout_req_s *logout_req;
-};
-
-union bfi_lps_i2h_msg_u {
- struct bfi_msg_s *msg;
- struct bfi_lps_login_rsp_s *login_rsp;
- struct bfi_lps_logout_rsp_s *logout_rsp;
- struct bfi_lps_cvl_event_s *cvl_event;
-};
-
-#pragma pack()
-
-#endif /* __BFI_LPS_H__ */
-
-
diff --git a/drivers/scsi/bfa/include/bfi/bfi_pbc.h b/drivers/scsi/bfa/include/bfi/bfi_pbc.h
deleted file mode 100644
index 88a4154c30c0..000000000000
--- a/drivers/scsi/bfa/include/bfi/bfi_pbc.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFI_PBC_H__
-#define __BFI_PBC_H__
-
-#pragma pack(1)
-
-#define BFI_PBC_MAX_BLUNS 8
-#define BFI_PBC_MAX_VPORTS 16
-
-#define BFI_PBC_PORT_DISABLED 2
-/**
- * PBC boot lun configuration
- */
-struct bfi_pbc_blun_s {
- wwn_t tgt_pwwn;
- lun_t tgt_lun;
-};
-
-/**
- * PBC virtual port configuration
- */
-struct bfi_pbc_vport_s {
- wwn_t vp_pwwn;
- wwn_t vp_nwwn;
-};
-
-/**
- * BFI pre-boot configuration information
- */
-struct bfi_pbc_s {
- u8 port_enabled;
- u8 boot_enabled;
- u8 nbluns;
- u8 nvports;
- u8 port_speed;
- u8 rsvd_a;
- u16 hss;
- wwn_t pbc_pwwn;
- wwn_t pbc_nwwn;
- struct bfi_pbc_blun_s blun[BFI_PBC_MAX_BLUNS];
- struct bfi_pbc_vport_s vport[BFI_PBC_MAX_VPORTS];
-};
-
-#pragma pack()
-
-#endif /* __BFI_PBC_H__ */
diff --git a/drivers/scsi/bfa/include/bfi/bfi_port.h b/drivers/scsi/bfa/include/bfi/bfi_port.h
deleted file mode 100644
index 3ec3bea110ba..000000000000
--- a/drivers/scsi/bfa/include/bfi/bfi_port.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-#ifndef __BFI_PORT_H__
-#define __BFI_PORT_H__
-
-#include <bfi/bfi.h>
-#include <defs/bfa_defs_pport.h>
-
-#pragma pack(1)
-
-enum bfi_port_h2i {
- BFI_PORT_H2I_ENABLE_REQ = (1),
- BFI_PORT_H2I_DISABLE_REQ = (2),
- BFI_PORT_H2I_GET_STATS_REQ = (3),
- BFI_PORT_H2I_CLEAR_STATS_REQ = (4),
-};
-
-enum bfi_port_i2h {
- BFI_PORT_I2H_ENABLE_RSP = BFA_I2HM(1),
- BFI_PORT_I2H_DISABLE_RSP = BFA_I2HM(2),
- BFI_PORT_I2H_GET_STATS_RSP = BFA_I2HM(3),
- BFI_PORT_I2H_CLEAR_STATS_RSP = BFA_I2HM(4),
-};
-
-/**
- * Generic REQ type
- */
-struct bfi_port_generic_req_s {
- struct bfi_mhdr_s mh; /* msg header */
- u32 msgtag; /* msgtag for reply */
- u32 rsvd;
-};
-
-/**
- * Generic RSP type
- */
-struct bfi_port_generic_rsp_s {
- struct bfi_mhdr_s mh; /* common msg header */
- u8 status; /* port enable status */
- u8 rsvd[3];
- u32 msgtag; /* msgtag for reply */
-};
-
-/**
- * @todo
- * BFI_PORT_H2I_ENABLE_REQ
- */
-
-/**
- * @todo
- * BFI_PORT_I2H_ENABLE_RSP
- */
-
-/**
- * BFI_PORT_H2I_DISABLE_REQ
- */
-
-/**
- * BFI_PORT_I2H_DISABLE_RSP
- */
-
-/**
- * BFI_PORT_H2I_GET_STATS_REQ
- */
-struct bfi_port_get_stats_req_s {
- struct bfi_mhdr_s mh; /* common msg header */
- union bfi_addr_u dma_addr;
-};
-
-/**
- * BFI_PORT_I2H_GET_STATS_RSP
- */
-
-/**
- * BFI_PORT_H2I_CLEAR_STATS_REQ
- */
-
-/**
- * BFI_PORT_I2H_CLEAR_STATS_RSP
- */
-
-union bfi_port_h2i_msg_u {
- struct bfi_mhdr_s mh;
- struct bfi_port_generic_req_s enable_req;
- struct bfi_port_generic_req_s disable_req;
- struct bfi_port_get_stats_req_s getstats_req;
- struct bfi_port_generic_req_s clearstats_req;
-};
-
-union bfi_port_i2h_msg_u {
- struct bfi_mhdr_s mh;
- struct bfi_port_generic_rsp_s enable_rsp;
- struct bfi_port_generic_rsp_s disable_rsp;
- struct bfi_port_generic_rsp_s getstats_rsp;
- struct bfi_port_generic_rsp_s clearstats_rsp;
-};
-
-#pragma pack()
-
-#endif /* __BFI_PORT_H__ */
-
diff --git a/drivers/scsi/bfa/include/bfi/bfi_pport.h b/drivers/scsi/bfa/include/bfi/bfi_pport.h
deleted file mode 100644
index 50dcf45c7470..000000000000
--- a/drivers/scsi/bfa/include/bfi/bfi_pport.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-#ifndef __BFI_PPORT_H__
-#define __BFI_PPORT_H__
-
-#include <bfi/bfi.h>
-#include <defs/bfa_defs_pport.h>
-
-#pragma pack(1)
-
-enum bfi_fcport_h2i {
- BFI_FCPORT_H2I_ENABLE_REQ = (1),
- BFI_FCPORT_H2I_DISABLE_REQ = (2),
- BFI_FCPORT_H2I_SET_SVC_PARAMS_REQ = (3),
- BFI_FCPORT_H2I_STATS_GET_REQ = (4),
- BFI_FCPORT_H2I_STATS_CLEAR_REQ = (5),
-};
-
-enum bfi_fcport_i2h {
- BFI_FCPORT_I2H_ENABLE_RSP = BFA_I2HM(1),
- BFI_FCPORT_I2H_DISABLE_RSP = BFA_I2HM(2),
- BFI_FCPORT_I2H_SET_SVC_PARAMS_RSP = BFA_I2HM(3),
- BFI_FCPORT_I2H_STATS_GET_RSP = BFA_I2HM(4),
- BFI_FCPORT_I2H_STATS_CLEAR_RSP = BFA_I2HM(5),
- BFI_FCPORT_I2H_EVENT = BFA_I2HM(6),
-};
-
-/**
- * Generic REQ type
- */
-struct bfi_fcport_req_s {
- struct bfi_mhdr_s mh; /* msg header */
- u32 msgtag; /* msgtag for reply */
-};
-
-/**
- * Generic RSP type
- */
-struct bfi_fcport_rsp_s {
- struct bfi_mhdr_s mh; /* common msg header */
- u8 status; /* port enable status */
- u8 rsvd[3];
- u32 msgtag; /* msgtag for reply */
-};
-
-/**
- * BFI_FCPORT_H2I_ENABLE_REQ
- */
-struct bfi_fcport_enable_req_s {
- struct bfi_mhdr_s mh; /* msg header */
- u32 rsvd1;
- wwn_t nwwn; /* node wwn of physical port */
- wwn_t pwwn; /* port wwn of physical port */
- struct bfa_pport_cfg_s port_cfg; /* port configuration */
- union bfi_addr_u stats_dma_addr; /* DMA address for stats */
- u32 msgtag; /* msgtag for reply */
- u32 rsvd2;
-};
-
-/**
- * BFI_FCPORT_H2I_SET_SVC_PARAMS_REQ
- */
-struct bfi_fcport_set_svc_params_req_s {
- struct bfi_mhdr_s mh; /* msg header */
- u16 tx_bbcredit; /* Tx credits */
- u16 rsvd;
-};
-
-/**
- * BFI_FCPORT_I2H_EVENT
- */
-struct bfi_fcport_event_s {
- struct bfi_mhdr_s mh; /* common msg header */
- struct bfa_pport_link_s link_state;
-};
-
-/**
- * fcport H2I message
- */
-union bfi_fcport_h2i_msg_u {
- struct bfi_mhdr_s *mhdr;
- struct bfi_fcport_enable_req_s *penable;
- struct bfi_fcport_req_s *pdisable;
- struct bfi_fcport_set_svc_params_req_s *psetsvcparams;
- struct bfi_fcport_req_s *pstatsget;
- struct bfi_fcport_req_s *pstatsclear;
-};
-
-/**
- * fcport I2H message
- */
-union bfi_fcport_i2h_msg_u {
- struct bfi_msg_s *msg;
- struct bfi_fcport_rsp_s *penable_rsp;
- struct bfi_fcport_rsp_s *pdisable_rsp;
- struct bfi_fcport_rsp_s *psetsvcparams_rsp;
- struct bfi_fcport_rsp_s *pstatsget_rsp;
- struct bfi_fcport_rsp_s *pstatsclear_rsp;
- struct bfi_fcport_event_s *event;
-};
-
-#pragma pack()
-
-#endif /* __BFI_PPORT_H__ */
diff --git a/drivers/scsi/bfa/include/bfi/bfi_rport.h b/drivers/scsi/bfa/include/bfi/bfi_rport.h
deleted file mode 100644
index e1cd83b56ec6..000000000000
--- a/drivers/scsi/bfa/include/bfi/bfi_rport.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFI_RPORT_H__
-#define __BFI_RPORT_H__
-
-#include <bfi/bfi.h>
-
-#pragma pack(1)
-
-enum bfi_rport_h2i_msgs {
- BFI_RPORT_H2I_CREATE_REQ = 1,
- BFI_RPORT_H2I_DELETE_REQ = 2,
- BFI_RPORT_H2I_SET_SPEED_REQ = 3,
-};
-
-enum bfi_rport_i2h_msgs {
- BFI_RPORT_I2H_CREATE_RSP = BFA_I2HM(1),
- BFI_RPORT_I2H_DELETE_RSP = BFA_I2HM(2),
- BFI_RPORT_I2H_QOS_SCN = BFA_I2HM(3),
-};
-
-struct bfi_rport_create_req_s {
- struct bfi_mhdr_s mh; /* common msg header */
- u16 bfa_handle; /* host rport handle */
- u16 max_frmsz; /* max rcv pdu size */
- u32 pid:24, /* remote port ID */
- lp_tag:8; /* local port tag */
- u32 local_pid:24, /* local port ID */
- cisc:8;
- u8 fc_class; /* supported FC classes */
- u8 vf_en; /* virtual fabric enable */
- u16 vf_id; /* virtual fabric ID */
-};
-
-struct bfi_rport_create_rsp_s {
- struct bfi_mhdr_s mh; /* common msg header */
- u8 status; /* rport creation status */
- u8 rsvd[3];
- u16 bfa_handle; /* host rport handle */
- u16 fw_handle; /* firmware rport handle */
- struct bfa_rport_qos_attr_s qos_attr; /* QoS Attributes */
-};
-
-struct bfa_rport_speed_req_s {
- struct bfi_mhdr_s mh; /* common msg header */
- u16 fw_handle; /* firmware rport handle */
- u8 speed; /*! rport's speed via RPSC */
- u8 rsvd;
-};
-
-struct bfi_rport_delete_req_s {
- struct bfi_mhdr_s mh; /* common msg header */
- u16 fw_handle; /* firmware rport handle */
- u16 rsvd;
-};
-
-struct bfi_rport_delete_rsp_s {
- struct bfi_mhdr_s mh; /* common msg header */
- u16 bfa_handle; /* host rport handle */
- u8 status; /* rport deletion status */
- u8 rsvd;
-};
-
-struct bfi_rport_qos_scn_s {
- struct bfi_mhdr_s mh; /* common msg header */
- u16 bfa_handle; /* host rport handle */
- u16 rsvd;
- struct bfa_rport_qos_attr_s old_qos_attr; /* Old QoS Attributes */
- struct bfa_rport_qos_attr_s new_qos_attr; /* New QoS Attributes */
-};
-
-union bfi_rport_h2i_msg_u {
- struct bfi_msg_s *msg;
- struct bfi_rport_create_req_s *create_req;
- struct bfi_rport_delete_req_s *delete_req;
- struct bfi_rport_speed_req_s *speed_req;
-};
-
-union bfi_rport_i2h_msg_u {
- struct bfi_msg_s *msg;
- struct bfi_rport_create_rsp_s *create_rsp;
- struct bfi_rport_delete_rsp_s *delete_rsp;
- struct bfi_rport_qos_scn_s *qos_scn_evt;
-};
-
-#pragma pack()
-
-#endif /* __BFI_RPORT_H__ */
-
diff --git a/drivers/scsi/bfa/include/bfi/bfi_uf.h b/drivers/scsi/bfa/include/bfi/bfi_uf.h
deleted file mode 100644
index f328a9e7e622..000000000000
--- a/drivers/scsi/bfa/include/bfi/bfi_uf.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFI_UF_H__
-#define __BFI_UF_H__
-
-#include "bfi.h"
-
-#pragma pack(1)
-
-enum bfi_uf_h2i {
- BFI_UF_H2I_BUF_POST = 1,
-};
-
-enum bfi_uf_i2h {
- BFI_UF_I2H_FRM_RCVD = BFA_I2HM(1),
-};
-
-#define BFA_UF_MAX_SGES 2
-
-struct bfi_uf_buf_post_s {
- struct bfi_mhdr_s mh; /* Common msg header */
- u16 buf_tag; /* buffer tag */
- u16 buf_len; /* total buffer length */
- struct bfi_sge_s sge[BFA_UF_MAX_SGES]; /* buffer DMA SGEs */
-};
-
-struct bfi_uf_frm_rcvd_s {
- struct bfi_mhdr_s mh; /* Common msg header */
- u16 buf_tag; /* buffer tag */
- u16 rsvd;
- u16 frm_len; /* received frame length */
- u16 xfr_len; /* tranferred length */
-};
-
-#pragma pack()
-
-#endif /* __BFI_UF_H__ */
diff --git a/drivers/scsi/bfa/include/cna/bfa_cna_trcmod.h b/drivers/scsi/bfa/include/cna/bfa_cna_trcmod.h
deleted file mode 100644
index a75a1f3be315..000000000000
--- a/drivers/scsi/bfa/include/cna/bfa_cna_trcmod.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/**
- * bfa_cna_trcmod.h CNA trace modules
- */
-
-#ifndef __BFA_CNA_TRCMOD_H__
-#define __BFA_CNA_TRCMOD_H__
-
-#include <cs/bfa_trc.h>
-
-/*
- * !!! Only append to the enums defined here to avoid any versioning
- * !!! needed between trace utility and driver version
- */
-enum {
- BFA_TRC_CNA_CEE = 1,
- BFA_TRC_CNA_PORT = 2,
- BFA_TRC_CNA_IOC = 3,
- BFA_TRC_CNA_DIAG = 4,
- BFA_TRC_CNA_IOC_CB = 5,
- BFA_TRC_CNA_IOC_CT = 6,
-};
-
-#endif /* __BFA_CNA_TRCMOD_H__ */
diff --git a/drivers/scsi/bfa/include/cna/cee/bfa_cee.h b/drivers/scsi/bfa/include/cna/cee/bfa_cee.h
deleted file mode 100644
index 77f297f68046..000000000000
--- a/drivers/scsi/bfa/include/cna/cee/bfa_cee.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_CEE_H__
-#define __BFA_CEE_H__
-
-#include <defs/bfa_defs_cee.h>
-#include <bfa_ioc.h>
-#include <cs/bfa_trc.h>
-#include <cs/bfa_log.h>
-
-typedef void (*bfa_cee_get_attr_cbfn_t) (void *dev, bfa_status_t status);
-typedef void (*bfa_cee_get_stats_cbfn_t) (void *dev, bfa_status_t status);
-typedef void (*bfa_cee_reset_stats_cbfn_t) (void *dev, bfa_status_t status);
-typedef void (*bfa_cee_hbfail_cbfn_t) (void *dev, bfa_status_t status);
-
-struct bfa_cee_cbfn_s {
- bfa_cee_get_attr_cbfn_t get_attr_cbfn;
- void *get_attr_cbarg;
- bfa_cee_get_stats_cbfn_t get_stats_cbfn;
- void *get_stats_cbarg;
- bfa_cee_reset_stats_cbfn_t reset_stats_cbfn;
- void *reset_stats_cbarg;
-};
-
-struct bfa_cee_s {
- void *dev;
- bfa_boolean_t get_attr_pending;
- bfa_boolean_t get_stats_pending;
- bfa_boolean_t reset_stats_pending;
- bfa_status_t get_attr_status;
- bfa_status_t get_stats_status;
- bfa_status_t reset_stats_status;
- struct bfa_cee_cbfn_s cbfn;
- struct bfa_ioc_hbfail_notify_s hbfail;
- struct bfa_trc_mod_s *trcmod;
- struct bfa_log_mod_s *logmod;
- struct bfa_cee_attr_s *attr;
- struct bfa_cee_stats_s *stats;
- struct bfa_dma_s attr_dma;
- struct bfa_dma_s stats_dma;
- struct bfa_ioc_s *ioc;
- struct bfa_mbox_cmd_s get_cfg_mb;
- struct bfa_mbox_cmd_s get_stats_mb;
- struct bfa_mbox_cmd_s reset_stats_mb;
-};
-
-u32 bfa_cee_meminfo(void);
-void bfa_cee_mem_claim(struct bfa_cee_s *cee, u8 *dma_kva,
- u64 dma_pa);
-void bfa_cee_attach(struct bfa_cee_s *cee, struct bfa_ioc_s *ioc, void *dev,
- struct bfa_trc_mod_s *trcmod,
- struct bfa_log_mod_s *logmod);
-void bfa_cee_detach(struct bfa_cee_s *cee);
-bfa_status_t bfa_cee_get_attr(struct bfa_cee_s *cee,
- struct bfa_cee_attr_s *attr,
- bfa_cee_get_attr_cbfn_t cbfn, void *cbarg);
-bfa_status_t bfa_cee_get_stats(struct bfa_cee_s *cee,
- struct bfa_cee_stats_s *stats,
- bfa_cee_get_stats_cbfn_t cbfn, void *cbarg);
-bfa_status_t bfa_cee_reset_stats(struct bfa_cee_s *cee,
- bfa_cee_reset_stats_cbfn_t cbfn, void *cbarg);
-#endif /* __BFA_CEE_H__ */
diff --git a/drivers/scsi/bfa/include/cna/port/bfa_port.h b/drivers/scsi/bfa/include/cna/port/bfa_port.h
deleted file mode 100644
index d7babaf97848..000000000000
--- a/drivers/scsi/bfa/include/cna/port/bfa_port.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_PORT_H__
-#define __BFA_PORT_H__
-
-#include <defs/bfa_defs_port.h>
-#include <bfa_ioc.h>
-#include <cs/bfa_trc.h>
-#include <cs/bfa_log.h>
-
-typedef void (*bfa_port_stats_cbfn_t) (void *dev, bfa_status_t status);
-typedef void (*bfa_port_endis_cbfn_t) (void *dev, bfa_status_t status);
-
-struct bfa_port_s {
- void *dev;
- struct bfa_ioc_s *ioc;
- struct bfa_trc_mod_s *trcmod;
- struct bfa_log_mod_s *logmod;
- u32 msgtag;
- bfa_boolean_t stats_busy;
- struct bfa_mbox_cmd_s stats_mb;
- bfa_port_stats_cbfn_t stats_cbfn;
- void *stats_cbarg;
- bfa_status_t stats_status;
- u32 stats_reset_time;
- union bfa_pport_stats_u *stats;
- struct bfa_dma_s stats_dma;
- bfa_boolean_t endis_pending;
- struct bfa_mbox_cmd_s endis_mb;
- bfa_port_endis_cbfn_t endis_cbfn;
- void *endis_cbarg;
- bfa_status_t endis_status;
- struct bfa_ioc_hbfail_notify_s hbfail;
-};
-
-void bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc,
- void *dev, struct bfa_trc_mod_s *trcmod,
- struct bfa_log_mod_s *logmod);
-void bfa_port_detach(struct bfa_port_s *port);
-void bfa_port_hbfail(void *arg);
-
-bfa_status_t bfa_port_get_stats(struct bfa_port_s *port,
- union bfa_pport_stats_u *stats,
- bfa_port_stats_cbfn_t cbfn, void *cbarg);
-bfa_status_t bfa_port_clear_stats(struct bfa_port_s *port,
- bfa_port_stats_cbfn_t cbfn, void *cbarg);
-bfa_status_t bfa_port_enable(struct bfa_port_s *port,
- bfa_port_endis_cbfn_t cbfn, void *cbarg);
-bfa_status_t bfa_port_disable(struct bfa_port_s *port,
- bfa_port_endis_cbfn_t cbfn, void *cbarg);
-u32 bfa_port_meminfo(void);
-void bfa_port_mem_claim(struct bfa_port_s *port, u8 *dma_kva,
- u64 dma_pa);
-
-#endif /* __BFA_PORT_H__ */
diff --git a/drivers/scsi/bfa/include/cna/pstats/ethport_defs.h b/drivers/scsi/bfa/include/cna/pstats/ethport_defs.h
deleted file mode 100644
index 1563ee512218..000000000000
--- a/drivers/scsi/bfa/include/cna/pstats/ethport_defs.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved.
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __ETHPORT_DEFS_H__
-#define __ETHPORT_DEFS_H__
-
-struct bnad_drv_stats {
- u64 netif_queue_stop;
- u64 netif_queue_wakeup;
- u64 tso4;
- u64 tso6;
- u64 tso_err;
- u64 tcpcsum_offload;
- u64 udpcsum_offload;
- u64 csum_help;
- u64 csum_help_err;
-
- u64 hw_stats_updates;
- u64 netif_rx_schedule;
- u64 netif_rx_complete;
- u64 netif_rx_dropped;
-};
-#endif
diff --git a/drivers/scsi/bfa/include/cna/pstats/phyport_defs.h b/drivers/scsi/bfa/include/cna/pstats/phyport_defs.h
deleted file mode 100644
index eb7548030d0f..000000000000
--- a/drivers/scsi/bfa/include/cna/pstats/phyport_defs.h
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved.
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __PHYPORT_DEFS_H__
-#define __PHYPORT_DEFS_H__
-
-#define BNA_TXF_ID_MAX 64
-#define BNA_RXF_ID_MAX 64
-
-/*
- * Statistics
- */
-
-/*
- * TxF Frame Statistics
- */
-struct bna_stats_txf {
- u64 ucast_octets;
- u64 ucast;
- u64 ucast_vlan;
-
- u64 mcast_octets;
- u64 mcast;
- u64 mcast_vlan;
-
- u64 bcast_octets;
- u64 bcast;
- u64 bcast_vlan;
-
- u64 errors;
- u64 filter_vlan; /* frames filtered due to VLAN */
- u64 filter_mac_sa; /* frames filtered due to SA check */
-};
-
-/*
- * RxF Frame Statistics
- */
-struct bna_stats_rxf {
- u64 ucast_octets;
- u64 ucast;
- u64 ucast_vlan;
-
- u64 mcast_octets;
- u64 mcast;
- u64 mcast_vlan;
-
- u64 bcast_octets;
- u64 bcast;
- u64 bcast_vlan;
- u64 frame_drops;
-};
-
-/*
- * FC Tx Frame Statistics
- */
-struct bna_stats_fc_tx {
- u64 txf_ucast_octets;
- u64 txf_ucast;
- u64 txf_ucast_vlan;
-
- u64 txf_mcast_octets;
- u64 txf_mcast;
- u64 txf_mcast_vlan;
-
- u64 txf_bcast_octets;
- u64 txf_bcast;
- u64 txf_bcast_vlan;
-
- u64 txf_parity_errors;
- u64 txf_timeout;
- u64 txf_fid_parity_errors;
-};
-
-/*
- * FC Rx Frame Statistics
- */
-struct bna_stats_fc_rx {
- u64 rxf_ucast_octets;
- u64 rxf_ucast;
- u64 rxf_ucast_vlan;
-
- u64 rxf_mcast_octets;
- u64 rxf_mcast;
- u64 rxf_mcast_vlan;
-
- u64 rxf_bcast_octets;
- u64 rxf_bcast;
- u64 rxf_bcast_vlan;
-};
-
-/*
- * RAD Frame Statistics
- */
-struct cna_stats_rad {
- u64 rx_frames;
- u64 rx_octets;
- u64 rx_vlan_frames;
-
- u64 rx_ucast;
- u64 rx_ucast_octets;
- u64 rx_ucast_vlan;
-
- u64 rx_mcast;
- u64 rx_mcast_octets;
- u64 rx_mcast_vlan;
-
- u64 rx_bcast;
- u64 rx_bcast_octets;
- u64 rx_bcast_vlan;
-
- u64 rx_drops;
-};
-
-/*
- * BPC Tx Registers
- */
-struct cna_stats_bpc_tx {
- u64 tx_pause[8];
- u64 tx_zero_pause[8]; /* Pause cancellation */
- u64 tx_first_pause[8]; /* Pause initiation rather
- *than retention */
-};
-
-/*
- * BPC Rx Registers
- */
-struct cna_stats_bpc_rx {
- u64 rx_pause[8];
- u64 rx_zero_pause[8]; /* Pause cancellation */
- u64 rx_first_pause[8]; /* Pause initiation rather
- *than retention */
-};
-
-/*
- * MAC Rx Statistics
- */
-struct cna_stats_mac_rx {
- u64 frame_64; /* both rx and tx counter */
- u64 frame_65_127; /* both rx and tx counter */
- u64 frame_128_255; /* both rx and tx counter */
- u64 frame_256_511; /* both rx and tx counter */
- u64 frame_512_1023; /* both rx and tx counter */
- u64 frame_1024_1518; /* both rx and tx counter */
- u64 frame_1518_1522; /* both rx and tx counter */
- u64 rx_bytes;
- u64 rx_packets;
- u64 rx_fcs_error;
- u64 rx_multicast;
- u64 rx_broadcast;
- u64 rx_control_frames;
- u64 rx_pause;
- u64 rx_unknown_opcode;
- u64 rx_alignment_error;
- u64 rx_frame_length_error;
- u64 rx_code_error;
- u64 rx_carrier_sense_error;
- u64 rx_undersize;
- u64 rx_oversize;
- u64 rx_fragments;
- u64 rx_jabber;
- u64 rx_drop;
-};
-
-/*
- * MAC Tx Statistics
- */
-struct cna_stats_mac_tx {
- u64 tx_bytes;
- u64 tx_packets;
- u64 tx_multicast;
- u64 tx_broadcast;
- u64 tx_pause;
- u64 tx_deferral;
- u64 tx_excessive_deferral;
- u64 tx_single_collision;
- u64 tx_muliple_collision;
- u64 tx_late_collision;
- u64 tx_excessive_collision;
- u64 tx_total_collision;
- u64 tx_pause_honored;
- u64 tx_drop;
- u64 tx_jabber;
- u64 tx_fcs_error;
- u64 tx_control_frame;
- u64 tx_oversize;
- u64 tx_undersize;
- u64 tx_fragments;
-};
-
-/*
- * Complete statistics
- */
-struct bna_stats {
- struct cna_stats_mac_rx mac_rx_stats;
- struct cna_stats_bpc_rx bpc_rx_stats;
- struct cna_stats_rad rad_stats;
- struct bna_stats_fc_rx fc_rx_stats;
- struct cna_stats_mac_tx mac_tx_stats;
- struct cna_stats_bpc_tx bpc_tx_stats;
- struct bna_stats_fc_tx fc_tx_stats;
- struct bna_stats_rxf rxf_stats[BNA_TXF_ID_MAX];
- struct bna_stats_txf txf_stats[BNA_RXF_ID_MAX];
-};
-
-#endif
diff --git a/drivers/scsi/bfa/include/cs/bfa_checksum.h b/drivers/scsi/bfa/include/cs/bfa_checksum.h
deleted file mode 100644
index 650f8d0aaff9..000000000000
--- a/drivers/scsi/bfa/include/cs/bfa_checksum.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/**
- * bfa_checksum.h BFA checksum utilities
- */
-
-#ifndef __BFA_CHECKSUM_H__
-#define __BFA_CHECKSUM_H__
-
-static inline u32
-bfa_checksum_u32(u32 *buf, int sz)
-{
- int i, m = sz >> 2;
- u32 sum = 0;
-
- for (i = 0; i < m; i++)
- sum ^= buf[i];
-
- return sum;
-}
-
-static inline u16
-bfa_checksum_u16(u16 *buf, int sz)
-{
- int i, m = sz >> 1;
- u16 sum = 0;
-
- for (i = 0; i < m; i++)
- sum ^= buf[i];
-
- return sum;
-}
-
-static inline u8
-bfa_checksum_u8(u8 *buf, int sz)
-{
- int i;
- u8 sum = 0;
-
- for (i = 0; i < sz; i++)
- sum ^= buf[i];
-
- return sum;
-}
-#endif
diff --git a/drivers/scsi/bfa/include/cs/bfa_debug.h b/drivers/scsi/bfa/include/cs/bfa_debug.h
deleted file mode 100644
index 75a911ea7936..000000000000
--- a/drivers/scsi/bfa/include/cs/bfa_debug.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/**
- * bfa_debug.h BFA debug interfaces
- */
-
-#ifndef __BFA_DEBUG_H__
-#define __BFA_DEBUG_H__
-
-#define bfa_assert(__cond) do { \
- if (!(__cond)) \
- bfa_panic(__LINE__, __FILE__, #__cond); \
-} while (0)
-
-#define bfa_sm_fault(__mod, __event) do { \
- bfa_trc(__mod, (((uint32_t)0xDEAD << 16) | __event)); \
- bfa_sm_panic((__mod)->logm, __LINE__, __FILE__, __event); \
-} while (0)
-
-#ifndef BFA_PERF_BUILD
-#define bfa_assert_fp(__cond) bfa_assert(__cond)
-#else
-#define bfa_assert_fp(__cond)
-#endif
-
-struct bfa_log_mod_s;
-void bfa_panic(int line, char *file, char *panicstr);
-void bfa_sm_panic(struct bfa_log_mod_s *logm, int line, char *file, int event);
-
-#endif /* __BFA_DEBUG_H__ */
diff --git a/drivers/scsi/bfa/include/cs/bfa_log.h b/drivers/scsi/bfa/include/cs/bfa_log.h
deleted file mode 100644
index bc334e0a93fa..000000000000
--- a/drivers/scsi/bfa/include/cs/bfa_log.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/**
- * bfa_log.h BFA log library data structure and function definition
- */
-
-#ifndef __BFA_LOG_H__
-#define __BFA_LOG_H__
-
-#include <bfa_os_inc.h>
-#include <defs/bfa_defs_status.h>
-#include <defs/bfa_defs_aen.h>
-
-/*
- * BFA log module definition
- *
- * To create a new module id:
- * Add a #define at the end of the list below. Select a value for your
- * definition so that it is one (1) greater than the previous
- * definition. Modify the definition of BFA_LOG_MODULE_ID_MAX to become
- * your new definition.
- * Should have no gaps in between the values because this is used in arrays.
- * IMPORTANT: AEN_IDs must be at the begining, otherwise update bfa_defs_aen.h
- */
-
-enum bfa_log_module_id {
- BFA_LOG_UNUSED_ID = 0,
-
- /* AEN defs begin */
- BFA_LOG_AEN_MIN = BFA_LOG_UNUSED_ID,
-
- BFA_LOG_AEN_ID_ADAPTER = BFA_LOG_AEN_MIN + BFA_AEN_CAT_ADAPTER,/* 1 */
- BFA_LOG_AEN_ID_PORT = BFA_LOG_AEN_MIN + BFA_AEN_CAT_PORT, /* 2 */
- BFA_LOG_AEN_ID_LPORT = BFA_LOG_AEN_MIN + BFA_AEN_CAT_LPORT, /* 3 */
- BFA_LOG_AEN_ID_RPORT = BFA_LOG_AEN_MIN + BFA_AEN_CAT_RPORT, /* 4 */
- BFA_LOG_AEN_ID_ITNIM = BFA_LOG_AEN_MIN + BFA_AEN_CAT_ITNIM, /* 5 */
- BFA_LOG_AEN_ID_TIN = BFA_LOG_AEN_MIN + BFA_AEN_CAT_TIN, /* 6 */
- BFA_LOG_AEN_ID_IPFC = BFA_LOG_AEN_MIN + BFA_AEN_CAT_IPFC, /* 7 */
- BFA_LOG_AEN_ID_AUDIT = BFA_LOG_AEN_MIN + BFA_AEN_CAT_AUDIT, /* 8 */
- BFA_LOG_AEN_ID_IOC = BFA_LOG_AEN_MIN + BFA_AEN_CAT_IOC, /* 9 */
- BFA_LOG_AEN_ID_ETHPORT = BFA_LOG_AEN_MIN + BFA_AEN_CAT_ETHPORT,/* 10 */
-
- BFA_LOG_AEN_MAX = BFA_LOG_AEN_ID_ETHPORT,
- /* AEN defs end */
-
- BFA_LOG_MODULE_ID_MIN = BFA_LOG_AEN_MAX,
-
- BFA_LOG_FW_ID = BFA_LOG_MODULE_ID_MIN + 1,
- BFA_LOG_HAL_ID = BFA_LOG_MODULE_ID_MIN + 2,
- BFA_LOG_FCS_ID = BFA_LOG_MODULE_ID_MIN + 3,
- BFA_LOG_WDRV_ID = BFA_LOG_MODULE_ID_MIN + 4,
- BFA_LOG_LINUX_ID = BFA_LOG_MODULE_ID_MIN + 5,
- BFA_LOG_SOLARIS_ID = BFA_LOG_MODULE_ID_MIN + 6,
-
- BFA_LOG_MODULE_ID_MAX = BFA_LOG_SOLARIS_ID,
-
- /* Not part of any arrays */
- BFA_LOG_MODULE_ID_ALL = BFA_LOG_MODULE_ID_MAX + 1,
- BFA_LOG_AEN_ALL = BFA_LOG_MODULE_ID_MAX + 2,
- BFA_LOG_DRV_ALL = BFA_LOG_MODULE_ID_MAX + 3,
-};
-
-/*
- * BFA log catalog name
- */
-#define BFA_LOG_CAT_NAME "BFA"
-
-/*
- * bfa log severity values
- */
-enum bfa_log_severity {
- BFA_LOG_INVALID = 0,
- BFA_LOG_CRITICAL = 1,
- BFA_LOG_ERROR = 2,
- BFA_LOG_WARNING = 3,
- BFA_LOG_INFO = 4,
- BFA_LOG_NONE = 5,
- BFA_LOG_LEVEL_MAX = BFA_LOG_NONE
-};
-
-#define BFA_LOG_MODID_OFFSET 16
-
-
-struct bfa_log_msgdef_s {
- u32 msg_id; /* message id */
- int attributes; /* attributes */
- int severity; /* severity level */
- char *msg_value;
- /* msg string */
- char *message;
- /* msg format string */
- int arg_type; /* argument type */
- int arg_num; /* number of argument */
-};
-
-/*
- * supported argument type
- */
-enum bfa_log_arg_type {
- BFA_LOG_S = 0, /* string */
- BFA_LOG_D, /* decimal */
- BFA_LOG_I, /* integer */
- BFA_LOG_O, /* oct number */
- BFA_LOG_U, /* unsigned integer */
- BFA_LOG_X, /* hex number */
- BFA_LOG_F, /* floating */
- BFA_LOG_C, /* character */
- BFA_LOG_L, /* double */
- BFA_LOG_P /* pointer */
-};
-
-#define BFA_LOG_ARG_TYPE 2
-#define BFA_LOG_ARG0 (0 * BFA_LOG_ARG_TYPE)
-#define BFA_LOG_ARG1 (1 * BFA_LOG_ARG_TYPE)
-#define BFA_LOG_ARG2 (2 * BFA_LOG_ARG_TYPE)
-#define BFA_LOG_ARG3 (3 * BFA_LOG_ARG_TYPE)
-
-#define BFA_LOG_GET_MOD_ID(msgid) ((msgid >> BFA_LOG_MODID_OFFSET) & 0xff)
-#define BFA_LOG_GET_MSG_IDX(msgid) (msgid & 0xffff)
-#define BFA_LOG_GET_MSG_ID(msgdef) ((msgdef)->msg_id)
-#define BFA_LOG_GET_MSG_FMT_STRING(msgdef) ((msgdef)->message)
-#define BFA_LOG_GET_SEVERITY(msgdef) ((msgdef)->severity)
-
-/*
- * Event attributes
- */
-#define BFA_LOG_ATTR_NONE 0
-#define BFA_LOG_ATTR_AUDIT 1
-#define BFA_LOG_ATTR_LOG 2
-#define BFA_LOG_ATTR_FFDC 4
-
-#define BFA_LOG_CREATE_ID(msw, lsw) \
- (((u32)msw << BFA_LOG_MODID_OFFSET) | lsw)
-
-struct bfa_log_mod_s;
-
-/**
- * callback function
- */
-typedef void (*bfa_log_cb_t)(struct bfa_log_mod_s *log_mod, u32 msg_id,
- const char *format, ...);
-
-
-struct bfa_log_mod_s {
- char instance_info[BFA_STRING_32]; /* instance info */
- int log_level[BFA_LOG_MODULE_ID_MAX + 1];
- /* log level for modules */
- bfa_log_cb_t cbfn; /* callback function */
-};
-
-extern int bfa_log_init(struct bfa_log_mod_s *log_mod,
- char *instance_name, bfa_log_cb_t cbfn);
-extern int bfa_log(struct bfa_log_mod_s *log_mod, u32 msg_id, ...);
-extern bfa_status_t bfa_log_set_level(struct bfa_log_mod_s *log_mod,
- int mod_id, enum bfa_log_severity log_level);
-extern bfa_status_t bfa_log_set_level_all(struct bfa_log_mod_s *log_mod,
- enum bfa_log_severity log_level);
-extern bfa_status_t bfa_log_set_level_aen(struct bfa_log_mod_s *log_mod,
- enum bfa_log_severity log_level);
-extern enum bfa_log_severity bfa_log_get_level(struct bfa_log_mod_s *log_mod,
- int mod_id);
-extern enum bfa_log_severity bfa_log_get_msg_level(
- struct bfa_log_mod_s *log_mod, u32 msg_id);
-/*
- * array of messages generated from xml files
- */
-extern struct bfa_log_msgdef_s bfa_log_msg_array[];
-
-#endif
diff --git a/drivers/scsi/bfa/include/cs/bfa_perf.h b/drivers/scsi/bfa/include/cs/bfa_perf.h
deleted file mode 100644
index 45aa5f978ff5..000000000000
--- a/drivers/scsi/bfa/include/cs/bfa_perf.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-#ifndef __BFAD_PERF_H__
-#define __BFAD_PERF_H__
-
-#ifdef BFAD_PERF_BUILD
-
-#undef bfa_trc
-#undef bfa_trc32
-#undef bfa_assert
-#undef BFA_TRC_FILE
-
-#define bfa_trc(_trcp, _data)
-#define bfa_trc32(_trcp, _data)
-#define bfa_assert(__cond)
-#define BFA_TRC_FILE(__mod, __submod)
-
-#endif
-
-#endif /* __BFAD_PERF_H__ */
diff --git a/drivers/scsi/bfa/include/cs/bfa_trc.h b/drivers/scsi/bfa/include/cs/bfa_trc.h
deleted file mode 100644
index 310771c888e7..000000000000
--- a/drivers/scsi/bfa/include/cs/bfa_trc.h
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-#ifndef __BFA_TRC_H__
-#define __BFA_TRC_H__
-
-#include <bfa_os_inc.h>
-
-#ifndef BFA_TRC_MAX
-#define BFA_TRC_MAX (4 * 1024)
-#endif
-
-#ifndef BFA_TRC_TS
-#define BFA_TRC_TS(_trcm) ((_trcm)->ticks++)
-#endif
-
-struct bfa_trc_s {
-#ifdef __BIGENDIAN
- u16 fileno;
- u16 line;
-#else
- u16 line;
- u16 fileno;
-#endif
- u32 timestamp;
- union {
- struct {
- u32 rsvd;
- u32 u32;
- } u32;
- u64 u64;
- } data;
-};
-
-
-struct bfa_trc_mod_s {
- u32 head;
- u32 tail;
- u32 ntrc;
- u32 stopped;
- u32 ticks;
- u32 rsvd[3];
- struct bfa_trc_s trc[BFA_TRC_MAX];
-};
-
-
-enum {
- BFA_TRC_FW = 1, /* firmware modules */
- BFA_TRC_HAL = 2, /* BFA modules */
- BFA_TRC_FCS = 3, /* BFA FCS modules */
- BFA_TRC_LDRV = 4, /* Linux driver modules */
- BFA_TRC_SDRV = 5, /* Solaris driver modules */
- BFA_TRC_VDRV = 6, /* vmware driver modules */
- BFA_TRC_WDRV = 7, /* windows driver modules */
- BFA_TRC_AEN = 8, /* AEN module */
- BFA_TRC_BIOS = 9, /* bios driver modules */
- BFA_TRC_EFI = 10, /* EFI driver modules */
- BNA_TRC_WDRV = 11, /* BNA windows driver modules */
- BNA_TRC_VDRV = 12, /* BNA vmware driver modules */
- BNA_TRC_SDRV = 13, /* BNA Solaris driver modules */
- BNA_TRC_LDRV = 14, /* BNA Linux driver modules */
- BNA_TRC_HAL = 15, /* BNA modules */
- BFA_TRC_CNA = 16, /* Common modules */
- BNA_TRC_IMDRV = 17 /* BNA windows intermediate driver modules */
-};
-#define BFA_TRC_MOD_SH 10
-#define BFA_TRC_MOD(__mod) ((BFA_TRC_ ## __mod) << BFA_TRC_MOD_SH)
-
-/**
- * Define a new tracing file (module). Module should match one defined above.
- */
-#define BFA_TRC_FILE(__mod, __submod) \
- static int __trc_fileno = ((BFA_TRC_ ## __mod ## _ ## __submod) | \
- BFA_TRC_MOD(__mod))
-
-
-#define bfa_trc32(_trcp, _data) \
- __bfa_trc((_trcp)->trcmod, __trc_fileno, __LINE__, (u32)_data)
-
-
-#ifndef BFA_BOOT_BUILD
-#define bfa_trc(_trcp, _data) \
- __bfa_trc((_trcp)->trcmod, __trc_fileno, __LINE__, (u64)_data)
-#else
-void bfa_boot_trc(struct bfa_trc_mod_s *trcmod, u16 fileno,
- u16 line, u32 data);
-#define bfa_trc(_trcp, _data) \
- bfa_boot_trc((_trcp)->trcmod, __trc_fileno, __LINE__, (u32)_data)
-#endif
-
-
-static inline void
-bfa_trc_init(struct bfa_trc_mod_s *trcm)
-{
- trcm->head = trcm->tail = trcm->stopped = 0;
- trcm->ntrc = BFA_TRC_MAX;
-}
-
-
-static inline void
-bfa_trc_stop(struct bfa_trc_mod_s *trcm)
-{
- trcm->stopped = 1;
-}
-
-#ifdef FWTRC
-extern void dc_flush(void *data);
-#else
-#define dc_flush(data)
-#endif
-
-
-static inline void
-__bfa_trc(struct bfa_trc_mod_s *trcm, int fileno, int line, u64 data)
-{
- int tail = trcm->tail;
- struct bfa_trc_s *trc = &trcm->trc[tail];
-
- if (trcm->stopped)
- return;
-
- trc->fileno = (u16) fileno;
- trc->line = (u16) line;
- trc->data.u64 = data;
- trc->timestamp = BFA_TRC_TS(trcm);
- dc_flush(trc);
-
- trcm->tail = (trcm->tail + 1) & (BFA_TRC_MAX - 1);
- if (trcm->tail == trcm->head)
- trcm->head = (trcm->head + 1) & (BFA_TRC_MAX - 1);
- dc_flush(trcm);
-}
-
-
-static inline void
-__bfa_trc32(struct bfa_trc_mod_s *trcm, int fileno, int line, u32 data)
-{
- int tail = trcm->tail;
- struct bfa_trc_s *trc = &trcm->trc[tail];
-
- if (trcm->stopped)
- return;
-
- trc->fileno = (u16) fileno;
- trc->line = (u16) line;
- trc->data.u32.u32 = data;
- trc->timestamp = BFA_TRC_TS(trcm);
- dc_flush(trc);
-
- trcm->tail = (trcm->tail + 1) & (BFA_TRC_MAX - 1);
- if (trcm->tail == trcm->head)
- trcm->head = (trcm->head + 1) & (BFA_TRC_MAX - 1);
- dc_flush(trcm);
-}
-
-#ifndef BFA_PERF_BUILD
-#define bfa_trc_fp(_trcp, _data) bfa_trc(_trcp, _data)
-#else
-#define bfa_trc_fp(_trcp, _data)
-#endif
-
-#endif /* __BFA_TRC_H__ */
-
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_adapter.h b/drivers/scsi/bfa/include/defs/bfa_defs_adapter.h
deleted file mode 100644
index aea0360d67d5..000000000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_adapter.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-#ifndef __BFA_DEFS_ADAPTER_H__
-#define __BFA_DEFS_ADAPTER_H__
-
-#include <protocol/types.h>
-#include <defs/bfa_defs_version.h>
-#include <defs/bfa_defs_mfg.h>
-
-/**
- * BFA adapter level attributes.
- */
-enum {
- BFA_ADAPTER_SERIAL_NUM_LEN = STRSZ(BFA_MFG_SERIALNUM_SIZE),
- /*
- *!< adapter serial num length
- */
- BFA_ADAPTER_MODEL_NAME_LEN = 16, /* model name length */
- BFA_ADAPTER_MODEL_DESCR_LEN = 128, /* model description length */
- BFA_ADAPTER_MFG_NAME_LEN = 8, /* manufacturer name length */
- BFA_ADAPTER_SYM_NAME_LEN = 64, /* adapter symbolic name length */
- BFA_ADAPTER_OS_TYPE_LEN = 64, /* adapter os type length */
-};
-
-struct bfa_adapter_attr_s {
- char manufacturer[BFA_ADAPTER_MFG_NAME_LEN];
- char serial_num[BFA_ADAPTER_SERIAL_NUM_LEN];
- u32 card_type;
- char model[BFA_ADAPTER_MODEL_NAME_LEN];
- char model_descr[BFA_ADAPTER_MODEL_DESCR_LEN];
- wwn_t pwwn;
- char node_symname[FC_SYMNAME_MAX];
- char hw_ver[BFA_VERSION_LEN];
- char fw_ver[BFA_VERSION_LEN];
- char optrom_ver[BFA_VERSION_LEN];
- char os_type[BFA_ADAPTER_OS_TYPE_LEN];
- struct bfa_mfg_vpd_s vpd;
- struct mac_s mac;
-
- u8 nports;
- u8 max_speed;
- u8 prototype;
- char asic_rev;
-
- u8 pcie_gen;
- u8 pcie_lanes_orig;
- u8 pcie_lanes;
- u8 cna_capable;
- u8 is_mezz;
-};
-
-/**
- * BFA adapter level events
- * Arguments below are in BFAL context from Mgmt
- * BFA_PORT_AEN_ADD: [in]: None [out]: serial_num, pwwn, nports
- * BFA_PORT_AEN_REMOVE: [in]: pwwn [out]: serial_num, pwwn, nports
- */
-enum bfa_adapter_aen_event {
- BFA_ADAPTER_AEN_ADD = 1, /* New Adapter found event */
- BFA_ADAPTER_AEN_REMOVE = 2, /* Adapter removed event */
-};
-
-struct bfa_adapter_aen_data_s {
- char serial_num[BFA_ADAPTER_SERIAL_NUM_LEN];
- u32 nports; /* Number of NPorts */
- wwn_t pwwn; /* WWN of one of its physical port */
-};
-
-#endif /* __BFA_DEFS_ADAPTER_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_aen.h b/drivers/scsi/bfa/include/defs/bfa_defs_aen.h
deleted file mode 100644
index 35244698fcdc..000000000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_aen.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_DEFS_AEN_H__
-#define __BFA_DEFS_AEN_H__
-
-#include <defs/bfa_defs_types.h>
-#include <defs/bfa_defs_ioc.h>
-#include <defs/bfa_defs_adapter.h>
-#include <defs/bfa_defs_port.h>
-#include <defs/bfa_defs_lport.h>
-#include <defs/bfa_defs_rport.h>
-#include <defs/bfa_defs_itnim.h>
-#include <defs/bfa_defs_tin.h>
-#include <defs/bfa_defs_ipfc.h>
-#include <defs/bfa_defs_audit.h>
-#include <defs/bfa_defs_ethport.h>
-
-#define BFA_AEN_MAX_APP 5
-
-enum bfa_aen_app {
- bfa_aen_app_bcu = 0, /* No thread for bcu */
- bfa_aen_app_hcm = 1,
- bfa_aen_app_cim = 2,
- bfa_aen_app_snia = 3,
- bfa_aen_app_test = 4, /* To be removed after unit test */
-};
-
-enum bfa_aen_category {
- BFA_AEN_CAT_ADAPTER = 1,
- BFA_AEN_CAT_PORT = 2,
- BFA_AEN_CAT_LPORT = 3,
- BFA_AEN_CAT_RPORT = 4,
- BFA_AEN_CAT_ITNIM = 5,
- BFA_AEN_CAT_TIN = 6,
- BFA_AEN_CAT_IPFC = 7,
- BFA_AEN_CAT_AUDIT = 8,
- BFA_AEN_CAT_IOC = 9,
- BFA_AEN_CAT_ETHPORT = 10,
- BFA_AEN_MAX_CAT = 10
-};
-
-#pragma pack(1)
-union bfa_aen_data_u {
- struct bfa_adapter_aen_data_s adapter;
- struct bfa_port_aen_data_s port;
- struct bfa_lport_aen_data_s lport;
- struct bfa_rport_aen_data_s rport;
- struct bfa_itnim_aen_data_s itnim;
- struct bfa_audit_aen_data_s audit;
- struct bfa_ioc_aen_data_s ioc;
- struct bfa_ethport_aen_data_s ethport;
-};
-
-struct bfa_aen_entry_s {
- enum bfa_aen_category aen_category;
- int aen_type;
- union bfa_aen_data_u aen_data;
- struct bfa_timeval_s aen_tv;
- s32 seq_num;
- s32 bfad_num;
- s32 rsvd[1];
-};
-
-#pragma pack()
-
-#define bfa_aen_event_t int
-
-#endif /* __BFA_DEFS_AEN_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_audit.h b/drivers/scsi/bfa/include/defs/bfa_defs_audit.h
deleted file mode 100644
index 8e3a962bf20c..000000000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_audit.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_DEFS_AUDIT_H__
-#define __BFA_DEFS_AUDIT_H__
-
-#include <bfa_os_inc.h>
-
-/**
- * BFA audit events
- */
-enum bfa_audit_aen_event {
- BFA_AUDIT_AEN_AUTH_ENABLE = 1,
- BFA_AUDIT_AEN_AUTH_DISABLE = 2,
-};
-
-/**
- * audit event data
- */
-struct bfa_audit_aen_data_s {
- wwn_t pwwn;
-};
-
-#endif /* __BFA_DEFS_AUDIT_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_auth.h b/drivers/scsi/bfa/include/defs/bfa_defs_auth.h
deleted file mode 100644
index f56ed871bb99..000000000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_auth.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-#ifndef __BFA_DEFS_AUTH_H__
-#define __BFA_DEFS_AUTH_H__
-
-#include <defs/bfa_defs_types.h>
-
-#define PUBLIC_KEY 15409
-#define PRIVATE_KEY 19009
-#define KEY_LEN 32399
-#define BFA_AUTH_SECRET_STRING_LEN 256
-#define BFA_AUTH_FAIL_NO_PASSWORD 0xFE
-#define BFA_AUTH_FAIL_TIMEOUT 0xFF
-
-/**
- * Authentication status
- */
-enum bfa_auth_status {
- BFA_AUTH_STATUS_NONE = 0, /* no authentication */
- BFA_AUTH_UNINIT = 1, /* state - uninit */
- BFA_AUTH_NEG_SEND = 2, /* state - negotiate send */
- BFA_AUTH_CHAL_WAIT = 3, /* state - challenge wait */
- BFA_AUTH_NEG_RETRY = 4, /* state - negotiate retry */
- BFA_AUTH_REPLY_SEND = 5, /* state - reply send */
- BFA_AUTH_STATUS_WAIT = 6, /* state - status wait */
- BFA_AUTH_SUCCESS = 7, /* state - success */
- BFA_AUTH_FAILED = 8, /* state - failed */
- BFA_AUTH_STATUS_UNKNOWN = 9, /* authentication status unknown */
-};
-
-enum bfa_auth_rej_code {
- BFA_AUTH_RJT_CODE_AUTH_FAILURE = 1, /* auth failure */
- BFA_AUTH_RJT_CODE_LOGICAL_ERR = 2, /* logical error */
-};
-
-/**
- * Authentication reject codes
- */
-enum bfa_auth_rej_code_exp {
- BFA_AUTH_MECH_NOT_USABLE = 1, /* auth. mechanism not usable */
- BFA_AUTH_DH_GROUP_NOT_USABLE = 2, /* DH Group not usable */
- BFA_AUTH_HASH_FUNC_NOT_USABLE = 3, /* hash Function not usable */
- BFA_AUTH_AUTH_XACT_STARTED = 4, /* auth xact started */
- BFA_AUTH_AUTH_FAILED = 5, /* auth failed */
- BFA_AUTH_INCORRECT_PLD = 6, /* incorrect payload */
- BFA_AUTH_INCORRECT_PROTO_MSG = 7, /* incorrect proto msg */
- BFA_AUTH_RESTART_AUTH_PROTO = 8, /* restart auth protocol */
- BFA_AUTH_AUTH_CONCAT_NOT_SUPP = 9, /* auth concat not supported */
- BFA_AUTH_PROTO_VER_NOT_SUPP = 10,/* proto version not supported */
-};
-
-struct auth_proto_stats_s {
- u32 auth_rjts;
- u32 auth_negs;
- u32 auth_dones;
-
- u32 dhchap_challenges;
- u32 dhchap_replies;
- u32 dhchap_successes;
-};
-
-/**
- * Authentication related statistics
- */
-struct bfa_auth_stats_s {
- u32 auth_failures; /* authentication failures */
- u32 auth_successes; /* authentication successes*/
- struct auth_proto_stats_s auth_rx_stats; /* Rx protocol stats */
- struct auth_proto_stats_s auth_tx_stats; /* Tx protocol stats */
-};
-
-/**
- * Authentication hash function algorithms
- */
-enum bfa_auth_algo {
- BFA_AUTH_ALGO_MD5 = 1, /* Message-Digest algorithm 5 */
- BFA_AUTH_ALGO_SHA1 = 2, /* Secure Hash Algorithm 1 */
- BFA_AUTH_ALGO_MS = 3, /* MD5, then SHA-1 */
- BFA_AUTH_ALGO_SM = 4, /* SHA-1, then MD5 */
-};
-
-/**
- * DH Groups
- *
- * Current value could be combination of one or more of the following values
- */
-enum bfa_auth_group {
- BFA_AUTH_GROUP_DHNULL = 0, /* DH NULL (value == 0) */
- BFA_AUTH_GROUP_DH768 = 1, /* DH group 768 (value == 1) */
- BFA_AUTH_GROUP_DH1024 = 2, /* DH group 1024 (value == 2) */
- BFA_AUTH_GROUP_DH1280 = 4, /* DH group 1280 (value == 3) */
- BFA_AUTH_GROUP_DH1536 = 8, /* DH group 1536 (value == 4) */
-
- BFA_AUTH_GROUP_ALL = 256 /* Use default DH group order
- * 0, 1, 2, 3, 4 */
-};
-
-/**
- * Authentication secret sources
- */
-enum bfa_auth_secretsource {
- BFA_AUTH_SECSRC_LOCAL = 1, /* locally configured */
- BFA_AUTH_SECSRC_RADIUS = 2, /* use radius server */
- BFA_AUTH_SECSRC_TACACS = 3, /* TACACS server */
-};
-
-/**
- * Authentication attributes
- */
-struct bfa_auth_attr_s {
- enum bfa_auth_status status;
- enum bfa_auth_algo algo;
- enum bfa_auth_group dh_grp;
- enum bfa_auth_rej_code rjt_code;
- enum bfa_auth_rej_code_exp rjt_code_exp;
- u8 secret_set;
- u8 resv[3];
-};
-
-#endif /* __BFA_DEFS_AUTH_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_boot.h b/drivers/scsi/bfa/include/defs/bfa_defs_boot.h
deleted file mode 100644
index 0fca10b6ad10..000000000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_boot.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_DEFS_BOOT_H__
-#define __BFA_DEFS_BOOT_H__
-
-#include <protocol/types.h>
-#include <defs/bfa_defs_types.h>
-#include <defs/bfa_defs_pport.h>
-
-enum {
- BFA_BOOT_BOOTLUN_MAX = 4, /* maximum boot lun per IOC */
- BFA_PREBOOT_BOOTLUN_MAX = 8, /* maximum preboot lun per IOC */
-
-};
-
-#define BOOT_CFG_REV1 1
-
-/**
- * Boot options setting. Boot options setting determines from where
- * to get the boot lun information
- */
-enum bfa_boot_bootopt {
- BFA_BOOT_AUTO_DISCOVER = 0, /* Boot from blun provided by fabric */
- BFA_BOOT_STORED_BLUN = 1, /* Boot from bluns stored in flash */
- BFA_BOOT_FIRST_LUN = 2, /* Boot from first discovered blun */
-};
-
-/**
- * Boot lun information.
- */
-struct bfa_boot_bootlun_s {
- wwn_t pwwn; /* port wwn of target */
- lun_t lun; /* 64-bit lun */
-};
-
-/**
- * BOOT boot configuraton
- */
-struct bfa_boot_cfg_s {
- u8 version;
- u8 rsvd1;
- u16 chksum;
-
- u8 enable; /* enable/disable SAN boot */
- u8 speed; /* boot speed settings */
- u8 topology; /* boot topology setting */
- u8 bootopt; /* bfa_boot_bootopt_t */
-
- u32 nbluns; /* number of boot luns */
-
- u32 rsvd2;
-
- struct bfa_boot_bootlun_s blun[BFA_BOOT_BOOTLUN_MAX];
- struct bfa_boot_bootlun_s blun_disc[BFA_BOOT_BOOTLUN_MAX];
-};
-
-struct bfa_boot_pbc_s {
- u8 enable; /* enable/disable SAN boot */
- u8 speed; /* boot speed settings */
- u8 topology; /* boot topology setting */
- u8 rsvd1;
- u32 nbluns; /* number of boot luns */
- struct bfa_boot_bootlun_s pblun[BFA_PREBOOT_BOOTLUN_MAX];
-};
-
-#endif /* __BFA_DEFS_BOOT_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_cee.h b/drivers/scsi/bfa/include/defs/bfa_defs_cee.h
deleted file mode 100644
index 6eaf519eccdc..000000000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_cee.h
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * bfa_defs_cee.h Interface declarations between host based
- * BFAL and DCBX/LLDP module in Firmware
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-#ifndef __BFA_DEFS_CEE_H__
-#define __BFA_DEFS_CEE_H__
-
-#include <defs/bfa_defs_types.h>
-#include <defs/bfa_defs_pport.h>
-#include <protocol/types.h>
-
-#pragma pack(1)
-
-#define BFA_CEE_LLDP_MAX_STRING_LEN (128)
-
-#define BFA_CEE_LLDP_SYS_CAP_OTHER 0x0001
-#define BFA_CEE_LLDP_SYS_CAP_REPEATER 0x0002
-#define BFA_CEE_LLDP_SYS_CAP_MAC_BRIDGE 0x0004
-#define BFA_CEE_LLDP_SYS_CAP_WLAN_AP 0x0008
-#define BFA_CEE_LLDP_SYS_CAP_ROUTER 0x0010
-#define BFA_CEE_LLDP_SYS_CAP_TELEPHONE 0x0020
-#define BFA_CEE_LLDP_SYS_CAP_DOCSIS_CD 0x0040
-#define BFA_CEE_LLDP_SYS_CAP_STATION 0x0080
-#define BFA_CEE_LLDP_SYS_CAP_CVLAN 0x0100
-#define BFA_CEE_LLDP_SYS_CAP_SVLAN 0x0200
-#define BFA_CEE_LLDP_SYS_CAP_TPMR 0x0400
-
-
-/* LLDP string type */
-struct bfa_cee_lldp_str_s {
- u8 sub_type;
- u8 len;
- u8 rsvd[2];
- u8 value[BFA_CEE_LLDP_MAX_STRING_LEN];
-};
-
-
-/* LLDP parameters */
-struct bfa_cee_lldp_cfg_s {
- struct bfa_cee_lldp_str_s chassis_id;
- struct bfa_cee_lldp_str_s port_id;
- struct bfa_cee_lldp_str_s port_desc;
- struct bfa_cee_lldp_str_s sys_name;
- struct bfa_cee_lldp_str_s sys_desc;
- struct bfa_cee_lldp_str_s mgmt_addr;
- u16 time_to_interval;
- u16 enabled_system_cap;
-};
-
-enum bfa_cee_dcbx_version_e {
- DCBX_PROTOCOL_PRECEE = 1,
- DCBX_PROTOCOL_CEE = 2,
-};
-
-enum bfa_cee_lls_e {
- CEE_LLS_DOWN_NO_TLV = 0, /* LLS is down because the TLV not sent by
- * the peer */
- CEE_LLS_DOWN = 1, /* LLS is down as advertised by the peer */
- CEE_LLS_UP = 2,
-};
-
-/* CEE/DCBX parameters */
-struct bfa_cee_dcbx_cfg_s {
- u8 pgid[8];
- u8 pg_percentage[8];
- u8 pfc_enabled; /* bitmap of priorties with PFC enabled */
- u8 fcoe_user_priority; /* bitmap of priorities used for FcoE
- * traffic */
- u8 dcbx_version; /* operating version:CEE or preCEE */
- u8 lls_fcoe; /* FCoE Logical Link Status */
- u8 lls_lan; /* LAN Logical Link Status */
- u8 rsvd[3];
-};
-
-/* CEE status */
-/* Making this to tri-state for the benefit of port list command */
-enum bfa_cee_status_e {
- CEE_UP = 0,
- CEE_PHY_UP = 1,
- CEE_LOOPBACK = 2,
- CEE_PHY_DOWN = 3,
-};
-
-/* CEE Query */
-struct bfa_cee_attr_s {
- u8 cee_status;
- u8 error_reason;
- struct bfa_cee_lldp_cfg_s lldp_remote;
- struct bfa_cee_dcbx_cfg_s dcbx_remote;
- mac_t src_mac;
- u8 link_speed;
- u8 nw_priority;
- u8 filler[2];
-};
-
-
-
-
-/* LLDP/DCBX/CEE Statistics */
-
-struct bfa_cee_lldp_stats_s {
- u32 frames_transmitted;
- u32 frames_aged_out;
- u32 frames_discarded;
- u32 frames_in_error;
- u32 frames_rcvd;
- u32 tlvs_discarded;
- u32 tlvs_unrecognized;
-};
-
-struct bfa_cee_dcbx_stats_s {
- u32 subtlvs_unrecognized;
- u32 negotiation_failed;
- u32 remote_cfg_changed;
- u32 tlvs_received;
- u32 tlvs_invalid;
- u32 seqno;
- u32 ackno;
- u32 recvd_seqno;
- u32 recvd_ackno;
-};
-
-struct bfa_cee_cfg_stats_s {
- u32 cee_status_down;
- u32 cee_status_up;
- u32 cee_hw_cfg_changed;
- u32 recvd_invalid_cfg;
-};
-
-
-struct bfa_cee_stats_s {
- struct bfa_cee_lldp_stats_s lldp_stats;
- struct bfa_cee_dcbx_stats_s dcbx_stats;
- struct bfa_cee_cfg_stats_s cfg_stats;
-};
-
-#pragma pack()
-
-
-#endif /* __BFA_DEFS_CEE_H__ */
-
-
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_driver.h b/drivers/scsi/bfa/include/defs/bfa_defs_driver.h
deleted file mode 100644
index 7d00d00d3969..000000000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_driver.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_DEFS_DRIVER_H__
-#define __BFA_DEFS_DRIVER_H__
-
-/**
- * Driver statistics
- */
-struct bfa_driver_stats_s {
- u16 tm_io_abort;
- u16 tm_io_abort_comp;
- u16 tm_lun_reset;
- u16 tm_lun_reset_comp;
- u16 tm_target_reset;
- u16 tm_bus_reset;
- u16 ioc_restart; /* IOC restart count */
- u16 rsvd;
- u64 control_req;
- u64 input_req;
- u64 output_req;
- u64 input_words;
- u64 output_words;
-};
-
-
-#endif /* __BFA_DEFS_DRIVER_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_ethport.h b/drivers/scsi/bfa/include/defs/bfa_defs_ethport.h
deleted file mode 100644
index b4fa0923aa89..000000000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_ethport.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_DEFS_ETHPORT_H__
-#define __BFA_DEFS_ETHPORT_H__
-
-#include <defs/bfa_defs_status.h>
-#include <defs/bfa_defs_port.h>
-#include <protocol/types.h>
-#include <cna/pstats/phyport_defs.h>
-#include <cna/pstats/ethport_defs.h>
-
-struct bna_tx_info_s {
- u32 miniport_state;
- u32 adapter_state;
- u64 tx_count;
- u64 tx_wi;
- u64 tx_sg;
- u64 tx_tcp_chksum;
- u64 tx_udp_chksum;
- u64 tx_ip_chksum;
- u64 tx_lsov1;
- u64 tx_lsov2;
- u64 tx_max_sg_len ;
-};
-
-struct bna_rx_queue_info_s {
- u16 q_id ;
- u16 buf_size ;
- u16 buf_count ;
- u16 rsvd ;
- u64 rx_count ;
- u64 rx_dropped ;
- u64 rx_unsupported ;
- u64 rx_internal_err ;
- u64 rss_count ;
- u64 vlan_count ;
- u64 rx_tcp_chksum ;
- u64 rx_udp_chksum ;
- u64 rx_ip_chksum ;
- u64 rx_hds ;
-};
-
-struct bna_rx_q_set_s {
- u16 q_set_type;
- u32 miniport_state;
- u32 adapter_state;
- struct bna_rx_queue_info_s rx_queue[2];
-};
-
-struct bna_port_stats_s {
- struct bna_tx_info_s tx_stats;
- u16 qset_count ;
- struct bna_rx_q_set_s rx_qset[8];
-};
-
-struct bfa_ethport_stats_s {
- struct bna_stats_txf txf_stats[1];
- struct bna_stats_rxf rxf_stats[1];
- struct bnad_drv_stats drv_stats;
-};
-
-/**
- * Ethernet port events
- * Arguments below are in BFAL context from Mgmt
- * BFA_PORT_AEN_ETH_LINKUP: [in]: mac [out]: mac
- * BFA_PORT_AEN_ETH_LINKDOWN: [in]: mac [out]: mac
- * BFA_PORT_AEN_ETH_ENABLE: [in]: mac [out]: mac
- * BFA_PORT_AEN_ETH_DISABLE: [in]: mac [out]: mac
- *
- */
-enum bfa_ethport_aen_event {
- BFA_ETHPORT_AEN_LINKUP = 1, /* Base Port Ethernet link up event */
- BFA_ETHPORT_AEN_LINKDOWN = 2, /* Base Port Ethernet link down event */
- BFA_ETHPORT_AEN_ENABLE = 3, /* Base Port Ethernet link enable event */
- BFA_ETHPORT_AEN_DISABLE = 4, /* Base Port Ethernet link disable
- * event */
-};
-
-struct bfa_ethport_aen_data_s {
- mac_t mac; /* MAC address of the physical port */
-};
-
-
-#endif /* __BFA_DEFS_ETHPORT_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_fcpim.h b/drivers/scsi/bfa/include/defs/bfa_defs_fcpim.h
deleted file mode 100644
index c08f4f5026ac..000000000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_fcpim.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-#ifndef __BFA_DEFS_FCPIM_H__
-#define __BFA_DEFS_FCPIM_H__
-
-struct bfa_fcpim_stats_s {
- u32 total_ios; /* Total IO count */
- u32 qresumes; /* IO waiting for CQ space */
- u32 no_iotags; /* NO IO contexts */
- u32 io_aborts; /* IO abort requests */
- u32 no_tskims; /* NO task management contexts */
- u32 iocomp_ok; /* IO completions with OK status */
- u32 iocomp_underrun; /* IO underrun (good) */
- u32 iocomp_overrun; /* IO overrun (good) */
- u32 iocomp_aborted; /* Aborted IO requests */
- u32 iocomp_timedout; /* IO timeouts */
- u32 iocom_nexus_abort; /* IO selection timeouts */
- u32 iocom_proto_err; /* IO protocol errors */
- u32 iocom_dif_err; /* IO SBC-3 protection errors */
- u32 iocom_tm_abort; /* IO aborted by TM requests */
- u32 iocom_sqer_needed; /* IO retry for SQ error
- *recovery */
- u32 iocom_res_free; /* Delayed freeing of IO resources */
- u32 iocomp_scsierr; /* IO with non-good SCSI status */
- u32 iocom_hostabrts; /* Host IO abort requests */
- u32 iocom_utags; /* IO comp with unknown tags */
- u32 io_cleanups; /* IO implicitly aborted */
- u32 io_tmaborts; /* IO aborted due to TM commands */
- u32 rsvd;
-};
-#endif /*__BFA_DEFS_FCPIM_H__*/
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_fcport.h b/drivers/scsi/bfa/include/defs/bfa_defs_fcport.h
deleted file mode 100644
index af86a6396439..000000000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_fcport.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * bfa_defs_fcport.h
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-#ifndef __BFA_DEFS_FCPORT_H__
-#define __BFA_DEFS_FCPORT_H__
-
-#include <defs/bfa_defs_types.h>
-#include <protocol/types.h>
-
-#pragma pack(1)
-
-/**
- * FCoE statistics
- */
-struct bfa_fcoe_stats_s {
- u64 secs_reset; /* Seconds since stats reset */
- u64 cee_linkups; /* CEE link up */
- u64 cee_linkdns; /* CEE link down */
- u64 fip_linkups; /* FIP link up */
- u64 fip_linkdns; /* FIP link down */
- u64 fip_fails; /* FIP failures */
- u64 mac_invalids; /* Invalid mac assignments */
- u64 vlan_req; /* Vlan requests */
- u64 vlan_notify; /* Vlan notifications */
- u64 vlan_err; /* Vlan notification errors */
- u64 vlan_timeouts; /* Vlan request timeouts */
- u64 vlan_invalids; /* Vlan invalids */
- u64 disc_req; /* Discovery requests */
- u64 disc_rsp; /* Discovery responses */
- u64 disc_err; /* Discovery error frames */
- u64 disc_unsol; /* Discovery unsolicited */
- u64 disc_timeouts; /* Discovery timeouts */
- u64 disc_fcf_unavail; /* Discovery FCF not avail */
- u64 linksvc_unsupp; /* FIP link service req unsupp. */
- u64 linksvc_err; /* FIP link service req errors */
- u64 logo_req; /* FIP logos received */
- u64 clrvlink_req; /* Clear virtual link requests */
- u64 op_unsupp; /* FIP operation unsupp. */
- u64 untagged; /* FIP untagged frames */
- u64 txf_ucast; /* Tx FCoE unicast frames */
- u64 txf_ucast_vlan; /* Tx FCoE unicast vlan frames */
- u64 txf_ucast_octets; /* Tx FCoE unicast octets */
- u64 txf_mcast; /* Tx FCoE mutlicast frames */
- u64 txf_mcast_vlan; /* Tx FCoE mutlicast vlan frames */
- u64 txf_mcast_octets; /* Tx FCoE multicast octets */
- u64 txf_bcast; /* Tx FCoE broadcast frames */
- u64 txf_bcast_vlan; /* Tx FCoE broadcast vlan frames */
- u64 txf_bcast_octets; /* Tx FCoE broadcast octets */
- u64 txf_timeout; /* Tx timeouts */
- u64 txf_parity_errors; /* Transmit parity err */
- u64 txf_fid_parity_errors; /* Transmit FID parity err */
- u64 rxf_ucast_octets; /* Rx FCoE unicast octets */
- u64 rxf_ucast; /* Rx FCoE unicast frames */
- u64 rxf_ucast_vlan; /* Rx FCoE unicast vlan frames */
- u64 rxf_mcast_octets; /* Rx FCoE multicast octets */
- u64 rxf_mcast; /* Rx FCoE multicast frames */
- u64 rxf_mcast_vlan; /* Rx FCoE multicast vlan frames */
- u64 rxf_bcast_octets; /* Rx FCoE broadcast octets */
- u64 rxf_bcast; /* Rx FCoE broadcast frames */
- u64 rxf_bcast_vlan; /* Rx FCoE broadcast vlan frames */
-};
-
-/**
- * QoS or FCoE stats (fcport stats excluding physical FC port stats)
- */
-union bfa_fcport_stats_u {
- struct bfa_qos_stats_s fcqos;
- struct bfa_fcoe_stats_s fcoe;
-};
-
-#pragma pack()
-
-#endif /* __BFA_DEFS_FCPORT_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_ioc.h b/drivers/scsi/bfa/include/defs/bfa_defs_ioc.h
deleted file mode 100644
index add0a05d941d..000000000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_ioc.h
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_DEFS_IOC_H__
-#define __BFA_DEFS_IOC_H__
-
-#include <protocol/types.h>
-#include <defs/bfa_defs_types.h>
-#include <defs/bfa_defs_version.h>
-#include <defs/bfa_defs_adapter.h>
-#include <defs/bfa_defs_pm.h>
-
-enum {
- BFA_IOC_DRIVER_LEN = 16,
- BFA_IOC_CHIP_REV_LEN = 8,
-};
-
-/**
- * Driver and firmware versions.
- */
-struct bfa_ioc_driver_attr_s {
- char driver[BFA_IOC_DRIVER_LEN]; /* driver name */
- char driver_ver[BFA_VERSION_LEN]; /* driver version */
- char fw_ver[BFA_VERSION_LEN]; /* firmware version*/
- char bios_ver[BFA_VERSION_LEN]; /* bios version */
- char efi_ver[BFA_VERSION_LEN]; /* EFI version */
- char ob_ver[BFA_VERSION_LEN]; /* openboot version*/
-};
-
-/**
- * IOC PCI device attributes
- */
-struct bfa_ioc_pci_attr_s {
- u16 vendor_id; /* PCI vendor ID */
- u16 device_id; /* PCI device ID */
- u16 ssid; /* subsystem ID */
- u16 ssvid; /* subsystem vendor ID */
- u32 pcifn; /* PCI device function */
- u32 rsvd; /* padding */
- u8 chip_rev[BFA_IOC_CHIP_REV_LEN]; /* chip revision */
-};
-
-/**
- * IOC states
- */
-enum bfa_ioc_state {
- BFA_IOC_RESET = 1, /* IOC is in reset state */
- BFA_IOC_SEMWAIT = 2, /* Waiting for IOC hardware semaphore */
- BFA_IOC_HWINIT = 3, /* IOC hardware is being initialized */
- BFA_IOC_GETATTR = 4, /* IOC is being configured */
- BFA_IOC_OPERATIONAL = 5, /* IOC is operational */
- BFA_IOC_INITFAIL = 6, /* IOC hardware failure */
- BFA_IOC_HBFAIL = 7, /* IOC heart-beat failure */
- BFA_IOC_DISABLING = 8, /* IOC is being disabled */
- BFA_IOC_DISABLED = 9, /* IOC is disabled */
- BFA_IOC_FWMISMATCH = 10, /* IOC firmware different from drivers */
-};
-
-/**
- * IOC firmware stats
- */
-struct bfa_fw_ioc_stats_s {
- u32 hb_count;
- u32 cfg_reqs;
- u32 enable_reqs;
- u32 disable_reqs;
- u32 stats_reqs;
- u32 clrstats_reqs;
- u32 unknown_reqs;
- u32 ic_reqs; /* interrupt coalesce reqs */
-};
-
-/**
- * IOC driver stats
- */
-struct bfa_ioc_drv_stats_s {
- u32 ioc_isrs;
- u32 ioc_enables;
- u32 ioc_disables;
- u32 ioc_hbfails;
- u32 ioc_boots;
- u32 stats_tmos;
- u32 hb_count;
- u32 disable_reqs;
- u32 enable_reqs;
- u32 disable_replies;
- u32 enable_replies;
-};
-
-/**
- * IOC statistics
- */
-struct bfa_ioc_stats_s {
- struct bfa_ioc_drv_stats_s drv_stats; /* driver IOC stats */
- struct bfa_fw_ioc_stats_s fw_stats; /* firmware IOC stats */
-};
-
-
-enum bfa_ioc_type_e {
- BFA_IOC_TYPE_FC = 1,
- BFA_IOC_TYPE_FCoE = 2,
- BFA_IOC_TYPE_LL = 3,
-};
-
-/**
- * IOC attributes returned in queries
- */
-struct bfa_ioc_attr_s {
- enum bfa_ioc_type_e ioc_type;
- enum bfa_ioc_state state; /* IOC state */
- struct bfa_adapter_attr_s adapter_attr; /* HBA attributes */
- struct bfa_ioc_driver_attr_s driver_attr; /* driver attr */
- struct bfa_ioc_pci_attr_s pci_attr;
- u8 port_id; /* port number */
- u8 rsvd[7]; /* 64bit align */
-};
-
-/**
- * BFA IOC level events
- */
-enum bfa_ioc_aen_event {
- BFA_IOC_AEN_HBGOOD = 1, /* Heart Beat restore event */
- BFA_IOC_AEN_HBFAIL = 2, /* Heart Beat failure event */
- BFA_IOC_AEN_ENABLE = 3, /* IOC enabled event */
- BFA_IOC_AEN_DISABLE = 4, /* IOC disabled event */
- BFA_IOC_AEN_FWMISMATCH = 5, /* IOC firmware mismatch */
- BFA_IOC_AEN_FWCFG_ERROR = 6, /* IOC firmware config error */
- BFA_IOC_AEN_INVALID_VENDOR = 7,
- BFA_IOC_AEN_INVALID_NWWN = 8, /* Zero NWWN */
- BFA_IOC_AEN_INVALID_PWWN = 9 /* Zero PWWN */
-
-};
-
-/**
- * BFA IOC level event data, now just a place holder
- */
-struct bfa_ioc_aen_data_s {
- wwn_t pwwn;
- s16 ioc_type;
- mac_t mac;
-};
-
-#endif /* __BFA_DEFS_IOC_H__ */
-
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_iocfc.h b/drivers/scsi/bfa/include/defs/bfa_defs_iocfc.h
deleted file mode 100644
index 31e728a631ed..000000000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_iocfc.h
+++ /dev/null
@@ -1,322 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_DEFS_IOCFC_H__
-#define __BFA_DEFS_IOCFC_H__
-
-#include <protocol/types.h>
-#include <defs/bfa_defs_types.h>
-#include <defs/bfa_defs_version.h>
-#include <defs/bfa_defs_adapter.h>
-#include <defs/bfa_defs_pm.h>
-
-#define BFA_IOCFC_INTR_DELAY 1125
-#define BFA_IOCFC_INTR_LATENCY 225
-#define BFA_IOCFCOE_INTR_DELAY 25
-#define BFA_IOCFCOE_INTR_LATENCY 5
-
-/**
- * Interrupt coalescing configuration.
- */
-struct bfa_iocfc_intr_attr_s {
- bfa_boolean_t coalesce; /* enable/disable coalescing */
- u16 latency; /* latency in microseconds */
- u16 delay; /* delay in microseconds */
-};
-
-/**
- * IOC firmware configuraton
- */
-struct bfa_iocfc_fwcfg_s {
- u16 num_fabrics; /* number of fabrics */
- u16 num_lports; /* number of local lports */
- u16 num_rports; /* number of remote ports */
- u16 num_ioim_reqs; /* number of IO reqs */
- u16 num_tskim_reqs; /* task management requests */
- u16 num_iotm_reqs; /* number of TM IO reqs */
- u16 num_tsktm_reqs; /* TM task management requests*/
- u16 num_fcxp_reqs; /* unassisted FC exchanges */
- u16 num_uf_bufs; /* unsolicited recv buffers */
- u8 num_cqs;
- u8 fw_tick_res; /*!< FW clock resolution in ms */
- u8 rsvd[4];
-
-};
-
-struct bfa_iocfc_drvcfg_s {
- u16 num_reqq_elems; /* number of req queue elements */
- u16 num_rspq_elems; /* number of rsp queue elements */
- u16 num_sgpgs; /* number of total SG pages */
- u16 num_sboot_tgts; /* number of SAN boot targets */
- u16 num_sboot_luns; /* number of SAN boot luns */
- u16 ioc_recover; /* IOC recovery mode */
- u16 min_cfg; /* minimum configuration */
- u16 path_tov; /* device path timeout */
- bfa_boolean_t delay_comp; /* delay completion of
- failed inflight IOs */
- u32 rsvd;
-};
-/**
- * IOC configuration
- */
-struct bfa_iocfc_cfg_s {
- struct bfa_iocfc_fwcfg_s fwcfg; /* firmware side config */
- struct bfa_iocfc_drvcfg_s drvcfg; /* driver side config */
-};
-
-/**
- * IOC firmware IO stats
- */
-struct bfa_fw_io_stats_s {
- u32 host_abort; /* IO aborted by host driver*/
- u32 host_cleanup; /* IO clean up by host driver */
-
- u32 fw_io_timeout; /* IOs timedout */
- u32 fw_frm_parse; /* frame parsed by f/w */
- u32 fw_frm_data; /* fcp_data frame parsed by f/w */
- u32 fw_frm_rsp; /* fcp_rsp frame parsed by f/w */
- u32 fw_frm_xfer_rdy; /* xfer_rdy frame parsed by f/w */
- u32 fw_frm_bls_acc; /* BLS ACC frame parsed by f/w */
- u32 fw_frm_tgt_abort; /* target ABTS parsed by f/w */
- u32 fw_frm_unknown; /* unknown parsed by f/w */
- u32 fw_data_dma; /* f/w DMA'ed the data frame */
- u32 fw_frm_drop; /* f/w drop the frame */
-
- u32 rec_timeout; /* FW rec timed out */
- u32 error_rec; /* FW sending rec on
- * an error condition*/
- u32 wait_for_si; /* FW wait for SI */
- u32 rec_rsp_inval; /* REC rsp invalid */
- u32 seqr_io_abort; /* target does not know cmd so abort */
- u32 seqr_io_retry; /* SEQR failed so retry IO */
-
- u32 itn_cisc_upd_rsp; /* ITN cisc updated on fcp_rsp */
- u32 itn_cisc_upd_data; /* ITN cisc updated on fcp_data */
- u32 itn_cisc_upd_xfer_rdy; /* ITN cisc updated on fcp_data */
-
- u32 fcp_data_lost; /* fcp data lost */
-
- u32 ro_set_in_xfer_rdy; /* Target set RO in Xfer_rdy frame */
- u32 xfer_rdy_ooo_err; /* Out of order Xfer_rdy received */
- u32 xfer_rdy_unknown_err; /* unknown error in xfer_rdy frame */
-
- u32 io_abort_timeout; /* ABTS timedout */
- u32 sler_initiated; /* SLER initiated */
-
- u32 unexp_fcp_rsp; /* fcp response in wrong state */
-
- u32 fcp_rsp_under_run; /* fcp rsp IO underrun */
- u32 fcp_rsp_under_run_wr; /* fcp rsp IO underrun for write */
- u32 fcp_rsp_under_run_err; /* fcp rsp IO underrun error */
- u32 fcp_rsp_resid_inval; /* invalid residue */
- u32 fcp_rsp_over_run; /* fcp rsp IO overrun */
- u32 fcp_rsp_over_run_err; /* fcp rsp IO overrun error */
- u32 fcp_rsp_proto_err; /* protocol error in fcp rsp */
- u32 fcp_rsp_sense_err; /* error in sense info in fcp rsp */
- u32 fcp_conf_req; /* FCP conf requested */
-
- u32 tgt_aborted_io; /* target initiated abort */
-
- u32 ioh_edtov_timeout_event;/* IOH edtov timer popped */
- u32 ioh_fcp_rsp_excp_event; /* IOH FCP_RSP exception */
- u32 ioh_fcp_conf_event; /* IOH FCP_CONF */
- u32 ioh_mult_frm_rsp_event; /* IOH multi_frame FCP_RSP */
- u32 ioh_hit_class2_event; /* IOH hit class2 */
- u32 ioh_miss_other_event; /* IOH miss other */
- u32 ioh_seq_cnt_err_event; /* IOH seq cnt error */
- u32 ioh_len_err_event; /* IOH len error - fcp_dl !=
- * bytes xfered */
- u32 ioh_seq_len_err_event; /* IOH seq len error */
- u32 ioh_data_oor_event; /* Data out of range */
- u32 ioh_ro_ooo_event; /* Relative offset out of range */
- u32 ioh_cpu_owned_event; /* IOH hit -iost owned by f/w */
- u32 ioh_unexp_frame_event; /* unexpected frame recieved
- * count */
- u32 ioh_err_int; /* IOH error int during data-phase
- * for scsi write
- */
-};
-
-/**
- * IOC port firmware stats
- */
-
-struct bfa_fw_port_fpg_stats_s {
- u32 intr_evt;
- u32 intr;
- u32 intr_excess;
- u32 intr_cause0;
- u32 intr_other;
- u32 intr_other_ign;
- u32 sig_lost;
- u32 sig_regained;
- u32 sync_lost;
- u32 sync_to;
- u32 sync_regained;
- u32 div2_overflow;
- u32 div2_underflow;
- u32 efifo_overflow;
- u32 efifo_underflow;
- u32 idle_rx;
- u32 lrr_rx;
- u32 lr_rx;
- u32 ols_rx;
- u32 nos_rx;
- u32 lip_rx;
- u32 arbf0_rx;
- u32 arb_rx;
- u32 mrk_rx;
- u32 const_mrk_rx;
- u32 prim_unknown;
-};
-
-
-struct bfa_fw_port_lksm_stats_s {
- u32 hwsm_success; /* hwsm state machine success */
- u32 hwsm_fails; /* hwsm fails */
- u32 hwsm_wdtov; /* hwsm timed out */
- u32 swsm_success; /* swsm success */
- u32 swsm_fails; /* swsm fails */
- u32 swsm_wdtov; /* swsm timed out */
- u32 busybufs; /* link init failed due to busybuf */
- u32 buf_waits; /* bufwait state entries */
- u32 link_fails; /* link failures */
- u32 psp_errors; /* primitive sequence protocol errors */
- u32 lr_unexp; /* No. of times LR rx-ed unexpectedly */
- u32 lrr_unexp; /* No. of times LRR rx-ed unexpectedly */
- u32 lr_tx; /* No. of times LR tx started */
- u32 lrr_tx; /* No. of times LRR tx started */
- u32 ols_tx; /* No. of times OLS tx started */
- u32 nos_tx; /* No. of times NOS tx started */
- u32 hwsm_lrr_rx; /* No. of times LRR rx-ed by HWSM */
- u32 hwsm_lr_rx; /* No. of times LR rx-ed by HWSM */
-};
-
-
-struct bfa_fw_port_snsm_stats_s {
- u32 hwsm_success; /* Successful hwsm terminations */
- u32 hwsm_fails; /* hwsm fail count */
- u32 hwsm_wdtov; /* hwsm timed out */
- u32 swsm_success; /* swsm success */
- u32 swsm_wdtov; /* swsm timed out */
- u32 error_resets; /* error resets initiated by upsm */
- u32 sync_lost; /* Sync loss count */
- u32 sig_lost; /* Signal loss count */
-};
-
-
-struct bfa_fw_port_physm_stats_s {
- u32 module_inserts; /* Module insert count */
- u32 module_xtracts; /* Module extracts count */
- u32 module_invalids; /* Invalid module inserted count */
- u32 module_read_ign; /* Module validation status ignored */
- u32 laser_faults; /* Laser fault count */
- u32 rsvd;
-};
-
-
-struct bfa_fw_fip_stats_s {
- u32 vlan_req; /* vlan discovery requests */
- u32 vlan_notify; /* vlan notifications */
- u32 vlan_err; /* vlan response error */
- u32 vlan_timeouts; /* vlan disvoery timeouts */
- u32 vlan_invalids; /* invalid vlan in discovery advert. */
- u32 disc_req; /* Discovery solicit requests */
- u32 disc_rsp; /* Discovery solicit response */
- u32 disc_err; /* Discovery advt. parse errors */
- u32 disc_unsol; /* Discovery unsolicited */
- u32 disc_timeouts; /* Discovery timeouts */
- u32 disc_fcf_unavail; /* Discovery FCF Not Avail. */
- u32 linksvc_unsupp; /* Unsupported link service req */
- u32 linksvc_err; /* Parse error in link service req */
- u32 logo_req; /* FIP logos received */
- u32 clrvlink_req; /* Clear virtual link req */
- u32 op_unsupp; /* Unsupported FIP operation */
- u32 untagged; /* Untagged frames (ignored) */
- u32 invalid_version; /*!< Invalid FIP version */
-};
-
-
-struct bfa_fw_lps_stats_s {
- u32 mac_invalids; /* Invalid mac assigned */
- u32 rsvd;
-};
-
-
-struct bfa_fw_fcoe_stats_s {
- u32 cee_linkups; /* CEE link up count */
- u32 cee_linkdns; /* CEE link down count */
- u32 fip_linkups; /* FIP link up count */
- u32 fip_linkdns; /* FIP link up count */
- u32 fip_fails; /* FIP fail count */
- u32 mac_invalids; /* Invalid mac assigned */
-};
-
-/**
- * IOC firmware FCoE port stats
- */
-struct bfa_fw_fcoe_port_stats_s {
- struct bfa_fw_fcoe_stats_s fcoe_stats;
- struct bfa_fw_fip_stats_s fip_stats;
-};
-
-/**
- * IOC firmware FC port stats
- */
-struct bfa_fw_fc_port_stats_s {
- struct bfa_fw_port_fpg_stats_s fpg_stats;
- struct bfa_fw_port_physm_stats_s physm_stats;
- struct bfa_fw_port_snsm_stats_s snsm_stats;
- struct bfa_fw_port_lksm_stats_s lksm_stats;
-};
-
-/**
- * IOC firmware FC port stats
- */
-union bfa_fw_port_stats_s {
- struct bfa_fw_fc_port_stats_s fc_stats;
- struct bfa_fw_fcoe_port_stats_s fcoe_stats;
-};
-
-/**
- * IOC firmware stats
- */
-struct bfa_fw_stats_s {
- struct bfa_fw_ioc_stats_s ioc_stats;
- struct bfa_fw_io_stats_s io_stats;
- union bfa_fw_port_stats_s port_stats;
-};
-
-/**
- * IOC statistics
- */
-struct bfa_iocfc_stats_s {
- struct bfa_fw_stats_s fw_stats; /* firmware IOC stats */
-};
-
-/**
- * IOC attributes returned in queries
- */
-struct bfa_iocfc_attr_s {
- struct bfa_iocfc_cfg_s config; /* IOCFC config */
- struct bfa_iocfc_intr_attr_s intr_attr; /* interrupt attr */
-};
-
-#define BFA_IOCFC_PATHTOV_MAX 60
-#define BFA_IOCFC_QDEPTH_MAX 2000
-
-#endif /* __BFA_DEFS_IOC_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_ipfc.h b/drivers/scsi/bfa/include/defs/bfa_defs_ipfc.h
deleted file mode 100644
index 7cb63ea98f38..000000000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_ipfc.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-#ifndef __BFA_DEFS_IPFC_H__
-#define __BFA_DEFS_IPFC_H__
-
-#include <bfa_os_inc.h>
-#include <protocol/types.h>
-#include <defs/bfa_defs_types.h>
-
-/**
- * FCS ip remote port states
- */
-enum bfa_iprp_state {
- BFA_IPRP_UNINIT = 0, /* PORT is not yet initialized */
- BFA_IPRP_ONLINE = 1, /* process login is complete */
- BFA_IPRP_OFFLINE = 2, /* iprp is offline */
-};
-
-/**
- * FCS remote port statistics
- */
-struct bfa_iprp_stats_s {
- u32 offlines;
- u32 onlines;
- u32 rscns;
- u32 plogis;
- u32 logos;
- u32 plogi_timeouts;
- u32 plogi_rejects;
-};
-
-/**
- * FCS iprp attribute returned in queries
- */
-struct bfa_iprp_attr_s {
- enum bfa_iprp_state state;
-};
-
-struct bfa_ipfc_stats_s {
- u32 arp_sent;
- u32 arp_recv;
- u32 arp_reply_sent;
- u32 arp_reply_recv;
- u32 farp_sent;
- u32 farp_recv;
- u32 farp_reply_sent;
- u32 farp_reply_recv;
- u32 farp_reject_sent;
- u32 farp_reject_recv;
-};
-
-struct bfa_ipfc_attr_s {
- bfa_boolean_t enabled;
-};
-
-#endif /* __BFA_DEFS_IPFC_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_itnim.h b/drivers/scsi/bfa/include/defs/bfa_defs_itnim.h
deleted file mode 100644
index d77788b3999a..000000000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_itnim.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-#ifndef __BFA_DEFS_ITNIM_H__
-#define __BFA_DEFS_ITNIM_H__
-
-#include <bfa_os_inc.h>
-#include <protocol/types.h>
-
-/**
- * FCS itnim states
- */
-enum bfa_itnim_state {
- BFA_ITNIM_OFFLINE = 0, /* offline */
- BFA_ITNIM_PRLI_SEND = 1, /* prli send */
- BFA_ITNIM_PRLI_SENT = 2, /* prli sent */
- BFA_ITNIM_PRLI_RETRY = 3, /* prli retry */
- BFA_ITNIM_HCB_ONLINE = 4, /* online callback */
- BFA_ITNIM_ONLINE = 5, /* online */
- BFA_ITNIM_HCB_OFFLINE = 6, /* offline callback */
- BFA_ITNIM_INITIATIOR = 7, /* initiator */
-};
-
-struct bfa_itnim_latency_s {
- u32 min;
- u32 max;
- u32 count;
- u32 clock_res;
- u32 avg;
- u32 rsvd;
-};
-
-struct bfa_itnim_hal_stats_s {
- u32 onlines; /* ITN nexus onlines (PRLI done) */
- u32 offlines; /* ITN Nexus offlines */
- u32 creates; /* ITN create requests */
- u32 deletes; /* ITN delete requests */
- u32 create_comps; /* ITN create completions */
- u32 delete_comps; /* ITN delete completions */
- u32 sler_events; /* SLER (sequence level error
- * recovery) events */
- u32 ioc_disabled; /* Num IOC disables */
- u32 cleanup_comps; /* ITN cleanup completions */
- u32 tm_cmnds; /* task management(TM) cmnds sent */
- u32 tm_fw_rsps; /* TM cmds firmware responses */
- u32 tm_success; /* TM successes */
- u32 tm_failures; /* TM failures */
- u32 tm_io_comps; /* TM IO completions */
- u32 tm_qresumes; /* TM queue resumes (after waiting
- * for resources)
- */
- u32 tm_iocdowns; /* TM cmnds affected by IOC down */
- u32 tm_cleanups; /* TM cleanups */
- u32 tm_cleanup_comps;
- /* TM cleanup completions */
- u32 ios; /* IO requests */
- u32 io_comps; /* IO completions */
- u64 input_reqs; /* INPUT requests */
- u64 output_reqs; /* OUTPUT requests */
-};
-
-/**
- * FCS remote port statistics
- */
-struct bfa_itnim_stats_s {
- u32 onlines; /* num rport online */
- u32 offlines; /* num rport offline */
- u32 prli_sent; /* num prli sent out */
- u32 fcxp_alloc_wait;/* num fcxp alloc waits */
- u32 prli_rsp_err; /* num prli rsp errors */
- u32 prli_rsp_acc; /* num prli rsp accepts */
- u32 initiator; /* rport is an initiator */
- u32 prli_rsp_parse_err; /* prli rsp parsing errors */
- u32 prli_rsp_rjt; /* num prli rsp rejects */
- u32 timeout; /* num timeouts detected */
- u32 sler; /* num sler notification from BFA */
- u32 rsvd;
- struct bfa_itnim_hal_stats_s hal_stats;
-};
-
-/**
- * FCS itnim attributes returned in queries
- */
-struct bfa_itnim_attr_s {
- enum bfa_itnim_state state; /* FCS itnim state */
- u8 retry; /* data retransmision support */
- u8 task_retry_id; /* task retry ident support */
- u8 rec_support; /* REC supported */
- u8 conf_comp; /* confirmed completion supp */
- struct bfa_itnim_latency_s io_latency; /* IO latency */
-};
-
-/**
- * BFA ITNIM events.
- * Arguments below are in BFAL context from Mgmt
- * BFA_ITNIM_AEN_NEW: [in]: None [out]: vf_id, lpwwn
- * BFA_ITNIM_AEN_DELETE: [in]: vf_id, lpwwn, rpwwn (0 = all fcp4 targets),
- * [out]: vf_id, ppwwn, lpwwn, rpwwn
- * BFA_ITNIM_AEN_ONLINE: [in]: vf_id, lpwwn, rpwwn (0 = all fcp4 targets),
- * [out]: vf_id, ppwwn, lpwwn, rpwwn
- * BFA_ITNIM_AEN_OFFLINE: [in]: vf_id, lpwwn, rpwwn (0 = all fcp4 targets),
- * [out]: vf_id, ppwwn, lpwwn, rpwwn
- * BFA_ITNIM_AEN_DISCONNECT:[in]: vf_id, lpwwn, rpwwn (0 = all fcp4 targets),
- * [out]: vf_id, ppwwn, lpwwn, rpwwn
- */
-enum bfa_itnim_aen_event {
- BFA_ITNIM_AEN_ONLINE = 1, /* Target online */
- BFA_ITNIM_AEN_OFFLINE = 2, /* Target offline */
- BFA_ITNIM_AEN_DISCONNECT = 3, /* Target disconnected */
-};
-
-/**
- * BFA ITNIM event data structure.
- */
-struct bfa_itnim_aen_data_s {
- u16 vf_id; /* vf_id of the IT nexus */
- u16 rsvd[3];
- wwn_t ppwwn; /* WWN of its physical port */
- wwn_t lpwwn; /* WWN of logical port */
- wwn_t rpwwn; /* WWN of remote(target) port */
-};
-
-#endif /* __BFA_DEFS_ITNIM_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_led.h b/drivers/scsi/bfa/include/defs/bfa_defs_led.h
deleted file mode 100644
index 62039273264e..000000000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_led.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_DEFS_LED_H__
-#define __BFA_DEFS_LED_H__
-
-#define BFA_LED_MAX_NUM 3
-
-enum bfa_led_op {
- BFA_LED_OFF = 0,
- BFA_LED_ON = 1,
- BFA_LED_FLICK = 2,
- BFA_LED_BLINK = 3,
-};
-
-enum bfa_led_color {
- BFA_LED_GREEN = 0,
- BFA_LED_AMBER = 1,
-};
-
-#endif /* __BFA_DEFS_LED_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_lport.h b/drivers/scsi/bfa/include/defs/bfa_defs_lport.h
deleted file mode 100644
index 0952a139c47c..000000000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_lport.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_DEFS_LPORT_H__
-#define __BFA_DEFS_LPORT_H__
-
-#include <defs/bfa_defs_types.h>
-#include <defs/bfa_defs_port.h>
-
-/**
- * BFA AEN logical port events.
- * Arguments below are in BFAL context from Mgmt
- * BFA_LPORT_AEN_NEW: [in]: None [out]: vf_id, ppwwn, lpwwn, roles
- * BFA_LPORT_AEN_DELETE: [in]: lpwwn [out]: vf_id, ppwwn. lpwwn, roles
- * BFA_LPORT_AEN_ONLINE: [in]: lpwwn [out]: vf_id, ppwwn. lpwwn, roles
- * BFA_LPORT_AEN_OFFLINE: [in]: lpwwn [out]: vf_id, ppwwn. lpwwn, roles
- * BFA_LPORT_AEN_DISCONNECT:[in]: lpwwn [out]: vf_id, ppwwn. lpwwn, roles
- * BFA_LPORT_AEN_NEW_PROP: [in]: None [out]: vf_id, ppwwn. lpwwn, roles
- * BFA_LPORT_AEN_DELETE_PROP: [in]: lpwwn [out]: vf_id, ppwwn. lpwwn, roles
- * BFA_LPORT_AEN_NEW_STANDARD: [in]: None [out]: vf_id, ppwwn. lpwwn, roles
- * BFA_LPORT_AEN_DELETE_STANDARD: [in]: lpwwn [out]: vf_id, ppwwn. lpwwn, roles
- * BFA_LPORT_AEN_NPIV_DUP_WWN: [in]: lpwwn [out]: vf_id, ppwwn. lpwwn, roles
- * BFA_LPORT_AEN_NPIV_FABRIC_MAX: [in]: lpwwn [out]: vf_id, ppwwn. lpwwn, roles
- * BFA_LPORT_AEN_NPIV_UNKNOWN: [in]: lpwwn [out]: vf_id, ppwwn. lpwwn, roles
- */
-enum bfa_lport_aen_event {
- BFA_LPORT_AEN_NEW = 1, /* LPort created event */
- BFA_LPORT_AEN_DELETE = 2, /* LPort deleted event */
- BFA_LPORT_AEN_ONLINE = 3, /* LPort online event */
- BFA_LPORT_AEN_OFFLINE = 4, /* LPort offline event */
- BFA_LPORT_AEN_DISCONNECT = 5, /* LPort disconnect event */
- BFA_LPORT_AEN_NEW_PROP = 6, /* VPort created event */
- BFA_LPORT_AEN_DELETE_PROP = 7, /* VPort deleted event */
- BFA_LPORT_AEN_NEW_STANDARD = 8, /* VPort created event */
- BFA_LPORT_AEN_DELETE_STANDARD = 9, /* VPort deleted event */
- BFA_LPORT_AEN_NPIV_DUP_WWN = 10, /* VPort configured with
- * duplicate WWN event
- */
- BFA_LPORT_AEN_NPIV_FABRIC_MAX = 11, /* Max NPIV in fabric/fport */
- BFA_LPORT_AEN_NPIV_UNKNOWN = 12, /* Unknown NPIV Error code event */
-};
-
-/**
- * BFA AEN event data structure
- */
-struct bfa_lport_aen_data_s {
- u16 vf_id; /* vf_id of this logical port */
- s16 roles; /* Logical port mode,IM/TM/IP etc */
- u32 rsvd;
- wwn_t ppwwn; /* WWN of its physical port */
- wwn_t lpwwn; /* WWN of this logical port */
-};
-
-#endif /* __BFA_DEFS_LPORT_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_mfg.h b/drivers/scsi/bfa/include/defs/bfa_defs_mfg.h
deleted file mode 100644
index d22fb7909643..000000000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_mfg.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-#ifndef __BFA_DEFS_MFG_H__
-#define __BFA_DEFS_MFG_H__
-
-#include <bfa_os_inc.h>
-
-/**
- * Manufacturing block version
- */
-#define BFA_MFG_VERSION 2
-
-/**
- * Manufacturing block encrypted version
- */
-#define BFA_MFG_ENC_VER 2
-
-/**
- * Manufacturing block version 1 length
- */
-#define BFA_MFG_VER1_LEN 128
-
-/**
- * Manufacturing block header length
- */
-#define BFA_MFG_HDR_LEN 4
-
-/**
- * Checksum size
- */
-#define BFA_MFG_CHKSUM_SIZE 16
-
-/**
- * Manufacturing block format
- */
-#define BFA_MFG_SERIALNUM_SIZE 11
-#define BFA_MFG_PARTNUM_SIZE 14
-#define BFA_MFG_SUPPLIER_ID_SIZE 10
-#define BFA_MFG_SUPPLIER_PARTNUM_SIZE 20
-#define BFA_MFG_SUPPLIER_SERIALNUM_SIZE 20
-#define BFA_MFG_SUPPLIER_REVISION_SIZE 4
-#define STRSZ(_n) (((_n) + 4) & ~3)
-
-/**
- * Manufacturing card type
- */
-enum {
- BFA_MFG_TYPE_CB_MAX = 825, /* Crossbow card type max */
- BFA_MFG_TYPE_FC8P2 = 825, /* 8G 2port FC card */
- BFA_MFG_TYPE_FC8P1 = 815, /* 8G 1port FC card */
- BFA_MFG_TYPE_FC4P2 = 425, /* 4G 2port FC card */
- BFA_MFG_TYPE_FC4P1 = 415, /* 4G 1port FC card */
- BFA_MFG_TYPE_CNA10P2 = 1020, /* 10G 2port CNA card */
- BFA_MFG_TYPE_CNA10P1 = 1010, /* 10G 1port CNA card */
- BFA_MFG_TYPE_JAYHAWK = 804, /* Jayhawk mezz card */
- BFA_MFG_TYPE_WANCHESE = 1007, /* Wanchese mezz card */
- BFA_MFG_TYPE_INVALID = 0, /* Invalid card type */
-};
-
-#pragma pack(1)
-
-/**
- * Card type to port number conversion
- */
-#define bfa_mfg_type2port_num(card_type) (((card_type) / 10) % 10)
-
-/**
- * Check if Mezz card
- */
-#define bfa_mfg_is_mezz(type) (( \
- (type) == BFA_MFG_TYPE_JAYHAWK || \
- (type) == BFA_MFG_TYPE_WANCHESE))
-
-/**
- * Check if card type valid
- */
-#define bfa_mfg_is_card_type_valid(type) (( \
- (type) == BFA_MFG_TYPE_FC8P2 || \
- (type) == BFA_MFG_TYPE_FC8P1 || \
- (type) == BFA_MFG_TYPE_FC4P2 || \
- (type) == BFA_MFG_TYPE_FC4P1 || \
- (type) == BFA_MFG_TYPE_CNA10P2 || \
- (type) == BFA_MFG_TYPE_CNA10P1 || \
- bfa_mfg_is_mezz(type)))
-
-/**
- * All numerical fields are in big-endian format.
- */
-struct bfa_mfg_block_s {
-};
-
-/**
- * VPD data length
- */
-#define BFA_MFG_VPD_LEN 512
-
-#define BFA_MFG_VPD_PCI_HDR_OFF 137
-#define BFA_MFG_VPD_PCI_VER_MASK 0x07 /* version mask 3 bits */
-#define BFA_MFG_VPD_PCI_VDR_MASK 0xf8 /* vendor mask 5 bits */
-
-/**
- * VPD vendor tag
- */
-enum {
- BFA_MFG_VPD_UNKNOWN = 0, /* vendor unknown */
- BFA_MFG_VPD_IBM = 1, /* vendor IBM */
- BFA_MFG_VPD_HP = 2, /* vendor HP */
- BFA_MFG_VPD_DELL = 3, /* vendor DELL */
- BFA_MFG_VPD_PCI_IBM = 0x08, /* PCI VPD IBM */
- BFA_MFG_VPD_PCI_HP = 0x10, /* PCI VPD HP */
- BFA_MFG_VPD_PCI_DELL = 0x20, /* PCI VPD DELL */
- BFA_MFG_VPD_PCI_BRCD = 0xf8, /* PCI VPD Brocade */
-};
-
-/**
- * All numerical fields are in big-endian format.
- */
-struct bfa_mfg_vpd_s {
- u8 version; /* vpd data version */
- u8 vpd_sig[3]; /* characters 'V', 'P', 'D' */
- u8 chksum; /* u8 checksum */
- u8 vendor; /* vendor */
- u8 len; /* vpd data length excluding header */
- u8 rsv;
- u8 data[BFA_MFG_VPD_LEN]; /* vpd data */
-};
-
-#pragma pack()
-
-#endif /* __BFA_DEFS_MFG_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_pci.h b/drivers/scsi/bfa/include/defs/bfa_defs_pci.h
deleted file mode 100644
index ea7d89bbc0bb..000000000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_pci.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_DEFS_PCI_H__
-#define __BFA_DEFS_PCI_H__
-
-/**
- * PCI device and vendor ID information
- */
-enum {
- BFA_PCI_VENDOR_ID_BROCADE = 0x1657,
- BFA_PCI_DEVICE_ID_FC_8G2P = 0x13,
- BFA_PCI_DEVICE_ID_FC_8G1P = 0x17,
- BFA_PCI_DEVICE_ID_CT = 0x14,
- BFA_PCI_DEVICE_ID_CT_FC = 0x21,
-};
-
-#define bfa_asic_id_ct(devid) \
- ((devid) == BFA_PCI_DEVICE_ID_CT || \
- (devid) == BFA_PCI_DEVICE_ID_CT_FC)
-
-/**
- * PCI sub-system device and vendor ID information
- */
-enum {
- BFA_PCI_FCOE_SSDEVICE_ID = 0x14,
-};
-
-/**
- * Maximum number of device address ranges mapped through different BAR(s)
- */
-#define BFA_PCI_ACCESS_RANGES 1
-
-#endif /* __BFA_DEFS_PCI_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_pm.h b/drivers/scsi/bfa/include/defs/bfa_defs_pm.h
deleted file mode 100644
index e8d6d959006e..000000000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_pm.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_DEFS_PM_H__
-#define __BFA_DEFS_PM_H__
-
-#include <bfa_os_inc.h>
-
-/**
- * BFA power management device states
- */
-enum bfa_pm_ds {
- BFA_PM_DS_D0 = 0, /* full power mode */
- BFA_PM_DS_D1 = 1, /* power save state 1 */
- BFA_PM_DS_D2 = 2, /* power save state 2 */
- BFA_PM_DS_D3 = 3, /* power off state */
-};
-
-#endif /* __BFA_DEFS_PM_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_pom.h b/drivers/scsi/bfa/include/defs/bfa_defs_pom.h
deleted file mode 100644
index d9fa278472b7..000000000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_pom.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-#ifndef __BFA_DEFS_POM_H__
-#define __BFA_DEFS_POM_H__
-
-#include <bfa_os_inc.h>
-#include <defs/bfa_defs_types.h>
-
-/**
- * POM health status levels for each attributes.
- */
-enum bfa_pom_entry_health {
- BFA_POM_HEALTH_NOINFO = 1, /* no information */
- BFA_POM_HEALTH_NORMAL = 2, /* health is normal */
- BFA_POM_HEALTH_WARNING = 3, /* warning level */
- BFA_POM_HEALTH_ALARM = 4, /* alarming level */
-};
-
-/**
- * Reading of temperature/voltage/current/power
- */
-struct bfa_pom_entry_s {
- enum bfa_pom_entry_health health; /* POM entry health */
- u32 curr_value; /* current value */
- u32 thr_warn_high; /* threshold warning high */
- u32 thr_warn_low; /* threshold warning low */
- u32 thr_alarm_low; /* threshold alaram low */
- u32 thr_alarm_high; /* threshold alarm high */
-};
-
-/**
- * POM attributes
- */
-struct bfa_pom_attr_s {
- struct bfa_pom_entry_s temperature; /* centigrade */
- struct bfa_pom_entry_s voltage; /* volts */
- struct bfa_pom_entry_s curr; /* milli amps */
- struct bfa_pom_entry_s txpower; /* micro watts */
- struct bfa_pom_entry_s rxpower; /* micro watts */
-};
-
-#endif /* __BFA_DEFS_POM_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_port.h b/drivers/scsi/bfa/include/defs/bfa_defs_port.h
deleted file mode 100644
index ebdf0d1731a4..000000000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_port.h
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_DEFS_PORT_H__
-#define __BFA_DEFS_PORT_H__
-
-#include <bfa_os_inc.h>
-#include <protocol/types.h>
-#include <defs/bfa_defs_pport.h>
-#include <defs/bfa_defs_ioc.h>
-
-#define BFA_FCS_FABRIC_IPADDR_SZ 16
-
-/**
- * symbolic names for base port/virtual port
- */
-#define BFA_SYMNAME_MAXLEN 128 /* vmware/windows uses 128 bytes */
-struct bfa_port_symname_s {
- char symname[BFA_SYMNAME_MAXLEN];
-};
-
-/**
-* Roles of FCS port:
- * - FCP IM and FCP TM roles cannot be enabled together for a FCS port
- * - Create multiple ports if both IM and TM functions required.
- * - Atleast one role must be specified.
- */
-enum bfa_port_role {
- BFA_PORT_ROLE_FCP_IM = 0x01, /* FCP initiator role */
- BFA_PORT_ROLE_FCP_TM = 0x02, /* FCP target role */
- BFA_PORT_ROLE_FCP_IPFC = 0x04, /* IP over FC role */
- BFA_PORT_ROLE_FCP_MAX = BFA_PORT_ROLE_FCP_IPFC | BFA_PORT_ROLE_FCP_IM
-};
-
-/**
- * FCS port configuration.
- */
-struct bfa_port_cfg_s {
- wwn_t pwwn; /* port wwn */
- wwn_t nwwn; /* node wwn */
- struct bfa_port_symname_s sym_name; /* vm port symbolic name */
- bfa_boolean_t preboot_vp; /* vport created from PBC */
- enum bfa_port_role roles; /* FCS port roles */
- u8 tag[16]; /* opaque tag from application */
-};
-
-/**
- * FCS port states
- */
-enum bfa_port_state {
- BFA_PORT_UNINIT = 0, /* PORT is not yet initialized */
- BFA_PORT_FDISC = 1, /* FDISC is in progress */
- BFA_PORT_ONLINE = 2, /* login to fabric is complete */
- BFA_PORT_OFFLINE = 3, /* No login to fabric */
-};
-
-/**
- * FCS port type. Required for VmWare.
- */
-enum bfa_port_type {
- BFA_PORT_TYPE_PHYSICAL = 0,
- BFA_PORT_TYPE_VIRTUAL,
-};
-
-/**
- * FCS port offline reason. Required for VmWare.
- */
-enum bfa_port_offline_reason {
- BFA_PORT_OFFLINE_UNKNOWN = 0,
- BFA_PORT_OFFLINE_LINKDOWN,
- BFA_PORT_OFFLINE_FAB_UNSUPPORTED, /* NPIV not supported by the
- * fabric */
- BFA_PORT_OFFLINE_FAB_NORESOURCES,
- BFA_PORT_OFFLINE_FAB_LOGOUT,
-};
-
-/**
- * FCS lport info. Required for VmWare.
- */
-struct bfa_port_info_s {
- u8 port_type; /* bfa_port_type_t : physical or
- * virtual */
- u8 port_state; /* one of bfa_port_state values */
- u8 offline_reason; /* one of bfa_port_offline_reason_t
- * values */
- wwn_t port_wwn;
- wwn_t node_wwn;
-
- /*
- * following 4 feilds are valid for Physical Ports only
- */
- u32 max_vports_supp; /* Max supported vports */
- u32 num_vports_inuse; /* Num of in use vports */
- u32 max_rports_supp; /* Max supported rports */
- u32 num_rports_inuse; /* Num of doscovered rports */
-
-};
-
-/**
- * FCS port statistics
- */
-struct bfa_port_stats_s {
- u32 ns_plogi_sent;
- u32 ns_plogi_rsp_err;
- u32 ns_plogi_acc_err;
- u32 ns_plogi_accepts;
- u32 ns_rejects; /* NS command rejects */
- u32 ns_plogi_unknown_rsp;
- u32 ns_plogi_alloc_wait;
-
- u32 ns_retries; /* NS command retries */
- u32 ns_timeouts; /* NS command timeouts */
-
- u32 ns_rspnid_sent;
- u32 ns_rspnid_accepts;
- u32 ns_rspnid_rsp_err;
- u32 ns_rspnid_rejects;
- u32 ns_rspnid_alloc_wait;
-
- u32 ns_rftid_sent;
- u32 ns_rftid_accepts;
- u32 ns_rftid_rsp_err;
- u32 ns_rftid_rejects;
- u32 ns_rftid_alloc_wait;
-
- u32 ns_rffid_sent;
- u32 ns_rffid_accepts;
- u32 ns_rffid_rsp_err;
- u32 ns_rffid_rejects;
- u32 ns_rffid_alloc_wait;
-
- u32 ns_gidft_sent;
- u32 ns_gidft_accepts;
- u32 ns_gidft_rsp_err;
- u32 ns_gidft_rejects;
- u32 ns_gidft_unknown_rsp;
- u32 ns_gidft_alloc_wait;
-
- /*
- * Mgmt Server stats
- */
- u32 ms_retries; /* MS command retries */
- u32 ms_timeouts; /* MS command timeouts */
- u32 ms_plogi_sent;
- u32 ms_plogi_rsp_err;
- u32 ms_plogi_acc_err;
- u32 ms_plogi_accepts;
- u32 ms_rejects; /* MS command rejects */
- u32 ms_plogi_unknown_rsp;
- u32 ms_plogi_alloc_wait;
-
- u32 num_rscn; /* Num of RSCN received */
- u32 num_portid_rscn;/* Num portid format RSCN
- * received */
-
- u32 uf_recvs; /* unsolicited recv frames */
- u32 uf_recv_drops; /* dropped received frames */
-
- u32 rsvd; /* padding for 64 bit alignment */
-};
-
-/**
- * BFA port attribute returned in queries
- */
-struct bfa_port_attr_s {
- enum bfa_port_state state; /* port state */
- u32 pid; /* port ID */
- struct bfa_port_cfg_s port_cfg; /* port configuration */
- enum bfa_pport_type port_type; /* current topology */
- u32 loopback; /* cable is externally looped back */
- wwn_t fabric_name; /* attached switch's nwwn */
- u8 fabric_ip_addr[BFA_FCS_FABRIC_IPADDR_SZ]; /* attached
- * fabric's ip addr */
- struct mac_s fpma_mac; /* Lport's FPMA Mac address */
- u16 authfail; /* auth failed state */
-};
-
-/**
- * BFA physical port Level events
- * Arguments below are in BFAL context from Mgmt
- * BFA_PORT_AEN_ONLINE: [in]: pwwn [out]: pwwn
- * BFA_PORT_AEN_OFFLINE: [in]: pwwn [out]: pwwn
- * BFA_PORT_AEN_RLIR: [in]: None [out]: pwwn, rlir_data, rlir_len
- * BFA_PORT_AEN_SFP_INSERT: [in]: pwwn [out]: port_id, pwwn
- * BFA_PORT_AEN_SFP_REMOVE: [in]: pwwn [out]: port_id, pwwn
- * BFA_PORT_AEN_SFP_POM: [in]: pwwn [out]: level, port_id, pwwn
- * BFA_PORT_AEN_ENABLE: [in]: pwwn [out]: pwwn
- * BFA_PORT_AEN_DISABLE: [in]: pwwn [out]: pwwn
- * BFA_PORT_AEN_AUTH_ON: [in]: pwwn [out]: pwwn
- * BFA_PORT_AEN_AUTH_OFF: [in]: pwwn [out]: pwwn
- * BFA_PORT_AEN_DISCONNECT: [in]: pwwn [out]: pwwn
- * BFA_PORT_AEN_QOS_NEG: [in]: pwwn [out]: pwwn
- * BFA_PORT_AEN_FABRIC_NAME_CHANGE: [in]: pwwn, [out]: pwwn, fwwn
- *
- */
-enum bfa_port_aen_event {
- BFA_PORT_AEN_ONLINE = 1, /* Physical Port online event */
- BFA_PORT_AEN_OFFLINE = 2, /* Physical Port offline event */
- BFA_PORT_AEN_RLIR = 3, /* RLIR event, not supported */
- BFA_PORT_AEN_SFP_INSERT = 4, /* SFP inserted event */
- BFA_PORT_AEN_SFP_REMOVE = 5, /* SFP removed event */
- BFA_PORT_AEN_SFP_POM = 6, /* SFP POM event */
- BFA_PORT_AEN_ENABLE = 7, /* Physical Port enable event */
- BFA_PORT_AEN_DISABLE = 8, /* Physical Port disable event */
- BFA_PORT_AEN_AUTH_ON = 9, /* Physical Port auth success event */
- BFA_PORT_AEN_AUTH_OFF = 10, /* Physical Port auth fail event */
- BFA_PORT_AEN_DISCONNECT = 11, /* Physical Port disconnect event */
- BFA_PORT_AEN_QOS_NEG = 12, /* Base Port QOS negotiation event */
- BFA_PORT_AEN_FABRIC_NAME_CHANGE = 13, /* Fabric Name/WWN change
- * event */
- BFA_PORT_AEN_SFP_ACCESS_ERROR = 14, /* SFP read error event */
- BFA_PORT_AEN_SFP_UNSUPPORT = 15, /* Unsupported SFP event */
-};
-
-enum bfa_port_aen_sfp_pom {
- BFA_PORT_AEN_SFP_POM_GREEN = 1, /* Normal */
- BFA_PORT_AEN_SFP_POM_AMBER = 2, /* Warning */
- BFA_PORT_AEN_SFP_POM_RED = 3, /* Critical */
- BFA_PORT_AEN_SFP_POM_MAX = BFA_PORT_AEN_SFP_POM_RED
-};
-
-struct bfa_port_aen_data_s {
- wwn_t pwwn; /* WWN of the physical port */
- wwn_t fwwn; /* WWN of the fabric port */
- s32 phy_port_num; /*! For SFP related events */
- s16 ioc_type;
- s16 level; /* Only transitions will
- * be informed */
- struct mac_s mac; /* MAC address of the ethernet port,
- * applicable to CNA port only */
- s16 rsvd;
-};
-
-#endif /* __BFA_DEFS_PORT_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_pport.h b/drivers/scsi/bfa/include/defs/bfa_defs_pport.h
deleted file mode 100644
index 2de675839c2f..000000000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_pport.h
+++ /dev/null
@@ -1,393 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_DEFS_PPORT_H__
-#define __BFA_DEFS_PPORT_H__
-
-#include <bfa_os_inc.h>
-#include <protocol/fc.h>
-#include <defs/bfa_defs_types.h>
-#include <defs/bfa_defs_qos.h>
-#include <cna/pstats/phyport_defs.h>
-
-/* Modify char* port_stt[] in bfal_port.c if a new state was added */
-enum bfa_pport_states {
- BFA_PPORT_ST_UNINIT = 1,
- BFA_PPORT_ST_ENABLING_QWAIT = 2,
- BFA_PPORT_ST_ENABLING = 3,
- BFA_PPORT_ST_LINKDOWN = 4,
- BFA_PPORT_ST_LINKUP = 5,
- BFA_PPORT_ST_DISABLING_QWAIT = 6,
- BFA_PPORT_ST_DISABLING = 7,
- BFA_PPORT_ST_DISABLED = 8,
- BFA_PPORT_ST_STOPPED = 9,
- BFA_PPORT_ST_IOCDOWN = 10,
- BFA_PPORT_ST_IOCDIS = 11,
- BFA_PPORT_ST_FWMISMATCH = 12,
- BFA_PPORT_ST_PREBOOT_DISABLED = 13,
- BFA_PPORT_ST_MAX_STATE,
-};
-
-/**
- * Port speed settings. Each specific speed is a bit field. Use multiple
- * bits to specify speeds to be selected for auto-negotiation.
- */
-enum bfa_pport_speed {
- BFA_PPORT_SPEED_UNKNOWN = 0,
- BFA_PPORT_SPEED_1GBPS = 1,
- BFA_PPORT_SPEED_2GBPS = 2,
- BFA_PPORT_SPEED_4GBPS = 4,
- BFA_PPORT_SPEED_8GBPS = 8,
- BFA_PPORT_SPEED_10GBPS = 10,
- BFA_PPORT_SPEED_AUTO =
- (BFA_PPORT_SPEED_1GBPS | BFA_PPORT_SPEED_2GBPS |
- BFA_PPORT_SPEED_4GBPS | BFA_PPORT_SPEED_8GBPS),
-};
-
-/**
- * Port operational type (in sync with SNIA port type).
- */
-enum bfa_pport_type {
- BFA_PPORT_TYPE_UNKNOWN = 1, /* port type is unknown */
- BFA_PPORT_TYPE_TRUNKED = 2, /* Trunked mode */
- BFA_PPORT_TYPE_NPORT = 5, /* P2P with switched fabric */
- BFA_PPORT_TYPE_NLPORT = 6, /* public loop */
- BFA_PPORT_TYPE_LPORT = 20, /* private loop */
- BFA_PPORT_TYPE_P2P = 21, /* P2P with no switched fabric */
- BFA_PPORT_TYPE_VPORT = 22, /* NPIV - virtual port */
-};
-
-/**
- * Port topology setting. A port's topology and fabric login status
- * determine its operational type.
- */
-enum bfa_pport_topology {
- BFA_PPORT_TOPOLOGY_NONE = 0, /* No valid topology */
- BFA_PPORT_TOPOLOGY_P2P = 1, /* P2P only */
- BFA_PPORT_TOPOLOGY_LOOP = 2, /* LOOP topology */
- BFA_PPORT_TOPOLOGY_AUTO = 3, /* auto topology selection */
-};
-
-/**
- * Physical port loopback types.
- */
-enum bfa_pport_opmode {
- BFA_PPORT_OPMODE_NORMAL = 0x00, /* normal non-loopback mode */
- BFA_PPORT_OPMODE_LB_INT = 0x01, /* internal loop back */
- BFA_PPORT_OPMODE_LB_SLW = 0x02, /* serial link wrapback (serdes) */
- BFA_PPORT_OPMODE_LB_EXT = 0x04, /* external loop back (serdes) */
- BFA_PPORT_OPMODE_LB_CBL = 0x08, /* cabled loop back */
- BFA_PPORT_OPMODE_LB_NLINT = 0x20, /* NL_Port internal loopback */
-};
-
-#define BFA_PPORT_OPMODE_LB_HARD(_mode) \
- ((_mode == BFA_PPORT_OPMODE_LB_INT) || \
- (_mode == BFA_PPORT_OPMODE_LB_SLW) || \
- (_mode == BFA_PPORT_OPMODE_LB_EXT))
-
-/**
- Port State (in sync with SNIA port state).
- */
-enum bfa_pport_snia_state {
- BFA_PPORT_STATE_UNKNOWN = 1, /* port is not initialized */
- BFA_PPORT_STATE_ONLINE = 2, /* port is ONLINE */
- BFA_PPORT_STATE_DISABLED = 3, /* port is disabled by user */
- BFA_PPORT_STATE_BYPASSED = 4, /* port is bypassed (in LOOP) */
- BFA_PPORT_STATE_DIAG = 5, /* port diagnostics is active */
- BFA_PPORT_STATE_LINKDOWN = 6, /* link is down */
- BFA_PPORT_STATE_LOOPBACK = 8, /* port is looped back */
-};
-
-/**
- * Port link state
- */
-enum bfa_pport_linkstate {
- BFA_PPORT_LINKUP = 1, /* Physical port/Trunk link up */
- BFA_PPORT_LINKDOWN = 2, /* Physical port/Trunk link down */
- BFA_PPORT_TRUNK_LINKDOWN = 3, /* Trunk link down (new tmaster) */
-};
-
-/**
- * Port link state event
- */
-#define bfa_pport_event_t enum bfa_pport_linkstate
-
-/**
- * Port link state reason code
- */
-enum bfa_pport_linkstate_rsn {
- BFA_PPORT_LINKSTATE_RSN_NONE = 0,
- BFA_PPORT_LINKSTATE_RSN_DISABLED = 1,
- BFA_PPORT_LINKSTATE_RSN_RX_NOS = 2,
- BFA_PPORT_LINKSTATE_RSN_RX_OLS = 3,
- BFA_PPORT_LINKSTATE_RSN_RX_LIP = 4,
- BFA_PPORT_LINKSTATE_RSN_RX_LIPF7 = 5,
- BFA_PPORT_LINKSTATE_RSN_SFP_REMOVED = 6,
- BFA_PPORT_LINKSTATE_RSN_PORT_FAULT = 7,
- BFA_PPORT_LINKSTATE_RSN_RX_LOS = 8,
- BFA_PPORT_LINKSTATE_RSN_LOCAL_FAULT = 9,
- BFA_PPORT_LINKSTATE_RSN_REMOTE_FAULT = 10,
- BFA_PPORT_LINKSTATE_RSN_TIMEOUT = 11,
-
-
-
- /* CEE related reason codes/errors */
- CEE_LLDP_INFO_AGED_OUT = 20,
- CEE_LLDP_SHUTDOWN_TLV_RCVD = 21,
- CEE_PEER_NOT_ADVERTISE_DCBX = 22,
- CEE_PEER_NOT_ADVERTISE_PG = 23,
- CEE_PEER_NOT_ADVERTISE_PFC = 24,
- CEE_PEER_NOT_ADVERTISE_FCOE = 25,
- CEE_PG_NOT_COMPATIBLE = 26,
- CEE_PFC_NOT_COMPATIBLE = 27,
- CEE_FCOE_NOT_COMPATIBLE = 28,
- CEE_BAD_PG_RCVD = 29,
- CEE_BAD_BW_RCVD = 30,
- CEE_BAD_PFC_RCVD = 31,
- CEE_BAD_FCOE_PRI_RCVD = 32,
- CEE_FCOE_PRI_PFC_OFF = 33,
- CEE_DUP_CONTROL_TLV_RCVD = 34,
- CEE_DUP_FEAT_TLV_RCVD = 35,
- CEE_APPLY_NEW_CFG = 36, /* reason, not an error */
- CEE_PROTOCOL_INIT = 37, /* reason, not an error */
- CEE_PHY_LINK_DOWN = 38,
- CEE_LLS_FCOE_ABSENT = 39,
- CEE_LLS_FCOE_DOWN = 40
-};
-
-/**
- * Default Target Rate Limiting Speed.
- */
-#define BFA_PPORT_DEF_TRL_SPEED BFA_PPORT_SPEED_1GBPS
-
-/**
- * Physical port configuration
- */
-struct bfa_pport_cfg_s {
- u8 topology; /* bfa_pport_topology */
- u8 speed; /* enum bfa_pport_speed */
- u8 trunked; /* trunked or not */
- u8 qos_enabled; /* qos enabled or not */
- u8 trunk_ports; /* bitmap of trunked ports */
- u8 cfg_hardalpa; /* is hard alpa configured */
- u16 maxfrsize; /* maximum frame size */
- u8 hardalpa; /* configured hard alpa */
- u8 rx_bbcredit; /* receive buffer credits */
- u8 tx_bbcredit; /* transmit buffer credits */
- u8 ratelimit; /* ratelimit enabled or not */
- u8 trl_def_speed; /* ratelimit default speed */
- u8 rsvd[3];
- u16 path_tov; /* device path timeout */
- u16 q_depth; /* SCSI Queue depth */
-};
-
-/**
- * Port attribute values.
- */
-struct bfa_pport_attr_s {
- /*
- * Static fields
- */
- wwn_t nwwn; /* node wwn */
- wwn_t pwwn; /* port wwn */
- wwn_t factorynwwn; /* factory node wwn */
- wwn_t factorypwwn; /* factory port wwn */
- enum fc_cos cos_supported; /* supported class of services */
- u32 rsvd;
- struct fc_symname_s port_symname; /* port symbolic name */
- enum bfa_pport_speed speed_supported; /* supported speeds */
- bfa_boolean_t pbind_enabled; /* Will be set if Persistent binding
- * enabled. Relevant only in Windows
- */
-
- /*
- * Configured values
- */
- struct bfa_pport_cfg_s pport_cfg; /* pport cfg */
-
- /*
- * Dynamic field - info from BFA
- */
- enum bfa_pport_states port_state; /* current port state */
- enum bfa_pport_speed speed; /* current speed */
- enum bfa_pport_topology topology; /* current topology */
- bfa_boolean_t beacon; /* current beacon status */
- bfa_boolean_t link_e2e_beacon;/* set if link beacon on */
- bfa_boolean_t plog_enabled; /* set if portlog is enabled*/
-
- /*
- * Dynamic field - info from FCS
- */
- u32 pid; /* port ID */
- enum bfa_pport_type port_type; /* current topology */
- u32 loopback; /* external loopback */
- u32 authfail; /* auth fail state */
- u32 rsvd2; /* padding for 64 bit */
-};
-
-/**
- * FC Port statistics.
- */
-struct bfa_pport_fc_stats_s {
- u64 secs_reset; /* Seconds since stats is reset */
- u64 tx_frames; /* Tx frames */
- u64 tx_words; /* Tx words */
- u64 tx_lip; /* Tx LIP */
- u64 tx_nos; /* Tx NOS */
- u64 tx_ols; /* Tx OLS */
- u64 tx_lr; /* Tx LR */
- u64 tx_lrr; /* Tx LRR */
- u64 rx_frames; /* Rx frames */
- u64 rx_words; /* Rx words */
- u64 lip_count; /* Rx LIP */
- u64 nos_count; /* Rx NOS */
- u64 ols_count; /* Rx OLS */
- u64 lr_count; /* Rx LR */
- u64 lrr_count; /* Rx LRR */
- u64 invalid_crcs; /* Rx CRC err frames */
- u64 invalid_crc_gd_eof; /* Rx CRC err good EOF frames */
- u64 undersized_frm; /* Rx undersized frames */
- u64 oversized_frm; /* Rx oversized frames */
- u64 bad_eof_frm; /* Rx frames with bad EOF */
- u64 error_frames; /* Errored frames */
- u64 dropped_frames; /* Dropped frames */
- u64 link_failures; /* Link Failure (LF) count */
- u64 loss_of_syncs; /* Loss of sync count */
- u64 loss_of_signals;/* Loss of signal count */
- u64 primseq_errs; /* Primitive sequence protocol err. */
- u64 bad_os_count; /* Invalid ordered sets */
- u64 err_enc_out; /* Encoding err nonframe_8b10b */
- u64 err_enc; /* Encoding err frame_8b10b */
-};
-
-/**
- * Eth Port statistics.
- */
-struct bfa_pport_eth_stats_s {
- u64 secs_reset; /* Seconds since stats is reset */
- u64 frame_64; /* Frames 64 bytes */
- u64 frame_65_127; /* Frames 65-127 bytes */
- u64 frame_128_255; /* Frames 128-255 bytes */
- u64 frame_256_511; /* Frames 256-511 bytes */
- u64 frame_512_1023; /* Frames 512-1023 bytes */
- u64 frame_1024_1518; /* Frames 1024-1518 bytes */
- u64 frame_1519_1522; /* Frames 1519-1522 bytes */
- u64 tx_bytes; /* Tx bytes */
- u64 tx_packets; /* Tx packets */
- u64 tx_mcast_packets; /* Tx multicast packets */
- u64 tx_bcast_packets; /* Tx broadcast packets */
- u64 tx_control_frame; /* Tx control frame */
- u64 tx_drop; /* Tx drops */
- u64 tx_jabber; /* Tx jabber */
- u64 tx_fcs_error; /* Tx FCS error */
- u64 tx_fragments; /* Tx fragments */
- u64 rx_bytes; /* Rx bytes */
- u64 rx_packets; /* Rx packets */
- u64 rx_mcast_packets; /* Rx multicast packets */
- u64 rx_bcast_packets; /* Rx broadcast packets */
- u64 rx_control_frames; /* Rx control frames */
- u64 rx_unknown_opcode; /* Rx unknown opcode */
- u64 rx_drop; /* Rx drops */
- u64 rx_jabber; /* Rx jabber */
- u64 rx_fcs_error; /* Rx FCS errors */
- u64 rx_alignment_error; /* Rx alignment errors */
- u64 rx_frame_length_error; /* Rx frame len errors */
- u64 rx_code_error; /* Rx code errors */
- u64 rx_fragments; /* Rx fragments */
- u64 rx_pause; /* Rx pause */
- u64 rx_zero_pause; /* Rx zero pause */
- u64 tx_pause; /* Tx pause */
- u64 tx_zero_pause; /* Tx zero pause */
- u64 rx_fcoe_pause; /* Rx FCoE pause */
- u64 rx_fcoe_zero_pause; /* Rx FCoE zero pause */
- u64 tx_fcoe_pause; /* Tx FCoE pause */
- u64 tx_fcoe_zero_pause; /* Tx FCoE zero pause */
-};
-
-/**
- * Port statistics.
- */
-union bfa_pport_stats_u {
- struct bfa_pport_fc_stats_s fc;
- struct bfa_pport_eth_stats_s eth;
-};
-
-/**
- * Port FCP mappings.
- */
-struct bfa_pport_fcpmap_s {
- char osdevname[256];
- u32 bus;
- u32 target;
- u32 oslun;
- u32 fcid;
- wwn_t nwwn;
- wwn_t pwwn;
- u64 fcplun;
- char luid[256];
-};
-
-/**
- * Port RNI */
-struct bfa_pport_rnid_s {
- wwn_t wwn;
- u32 unittype;
- u32 portid;
- u32 attached_nodes_num;
- u16 ip_version;
- u16 udp_port;
- u8 ipaddr[16];
- u16 rsvd;
- u16 topologydiscoveryflags;
-};
-
-struct bfa_fcport_fcf_s {
- wwn_t name; /* FCF name */
- wwn_t fabric_name; /* Fabric Name */
- u8 fipenabled; /* FIP enabled or not */
- u8 fipfailed; /* FIP failed or not */
- u8 resv[2];
- u8 pri; /* FCF priority */
- u8 version; /* FIP version used */
- u8 available; /* Available for login */
- u8 fka_disabled; /* FKA is disabled */
- u8 maxsz_verified; /* FCoE max size verified */
- u8 fc_map[3]; /* FC map */
- u16 vlan; /* FCoE vlan tag/priority */
- u32 fka_adv_per; /* FIP ka advert. period */
- struct mac_s mac; /* FCF mac */
-};
-
-/**
- * Link state information
- */
-struct bfa_pport_link_s {
- u8 linkstate; /* Link state bfa_pport_linkstate */
- u8 linkstate_rsn; /* bfa_pport_linkstate_rsn_t */
- u8 topology; /* P2P/LOOP bfa_pport_topology */
- u8 speed; /* Link speed (1/2/4/8 G) */
- u32 linkstate_opt; /* Linkstate optional data (debug) */
- u8 trunked; /* Trunked or not (1 or 0) */
- u8 resvd[3];
- struct bfa_qos_attr_s qos_attr; /* QoS Attributes */
- union {
- struct bfa_qos_vc_attr_s qos_vc_attr; /* VC info from ELP */
- struct bfa_fcport_fcf_s fcf; /* FCF information (for FCoE) */
- } vc_fcf;
-};
-
-#endif /* __BFA_DEFS_PPORT_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_qos.h b/drivers/scsi/bfa/include/defs/bfa_defs_qos.h
deleted file mode 100644
index aadbacd1d2d7..000000000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_qos.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_DEFS_QOS_H__
-#define __BFA_DEFS_QOS_H__
-
-/**
- * QoS states
- */
-enum bfa_qos_state {
- BFA_QOS_ONLINE = 1, /* QoS is online */
- BFA_QOS_OFFLINE = 2, /* QoS is offline */
-};
-
-
-/**
- * QoS Priority levels.
- */
-enum bfa_qos_priority {
- BFA_QOS_UNKNOWN = 0,
- BFA_QOS_HIGH = 1, /* QoS Priority Level High */
- BFA_QOS_MED = 2, /* QoS Priority Level Medium */
- BFA_QOS_LOW = 3, /* QoS Priority Level Low */
-};
-
-
-/**
- * QoS bandwidth allocation for each priority level
- */
-enum bfa_qos_bw_alloc {
- BFA_QOS_BW_HIGH = 60, /* bandwidth allocation for High */
- BFA_QOS_BW_MED = 30, /* bandwidth allocation for Medium */
- BFA_QOS_BW_LOW = 10, /* bandwidth allocation for Low */
-};
-
-/**
- * QoS attribute returned in QoS Query
- */
-struct bfa_qos_attr_s {
- enum bfa_qos_state state; /* QoS current state */
- u32 total_bb_cr; /* Total BB Credits */
-};
-
-/**
- * These fields should be displayed only from the CLI.
- * There will be a separate BFAL API (get_qos_vc_attr ?)
- * to retrieve this.
- *
- */
-#define BFA_QOS_MAX_VC 16
-
-struct bfa_qos_vc_info_s {
- u8 vc_credit;
- u8 borrow_credit;
- u8 priority;
- u8 resvd;
-};
-
-struct bfa_qos_vc_attr_s {
- u16 total_vc_count; /* Total VC Count */
- u16 shared_credit;
- u32 elp_opmode_flags;
- struct bfa_qos_vc_info_s vc_info[BFA_QOS_MAX_VC]; /* as many as
- * total_vc_count */
-};
-
-/**
- * QoS statistics
- */
-struct bfa_qos_stats_s {
- u32 flogi_sent; /* QoS Flogi sent */
- u32 flogi_acc_recvd; /* QoS Flogi Acc received */
- u32 flogi_rjt_recvd; /* QoS Flogi rejects received */
- u32 flogi_retries; /* QoS Flogi retries */
-
- u32 elp_recvd; /* QoS ELP received */
- u32 elp_accepted; /* QoS ELP Accepted */
- u32 elp_rejected; /* QoS ELP rejected */
- u32 elp_dropped; /* QoS ELP dropped */
-
- u32 qos_rscn_recvd; /* QoS RSCN received */
- u32 rsvd; /* padding for 64 bit alignment */
-};
-
-#endif /* __BFA_DEFS_QOS_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_rport.h b/drivers/scsi/bfa/include/defs/bfa_defs_rport.h
deleted file mode 100644
index e0af59d6d2f6..000000000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_rport.h
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_DEFS_RPORT_H__
-#define __BFA_DEFS_RPORT_H__
-
-#include <bfa_os_inc.h>
-#include <protocol/types.h>
-#include <defs/bfa_defs_pport.h>
-#include <defs/bfa_defs_port.h>
-#include <defs/bfa_defs_qos.h>
-
-/**
- * FCS remote port states
- */
-enum bfa_rport_state {
- BFA_RPORT_UNINIT = 0, /* PORT is not yet initialized */
- BFA_RPORT_OFFLINE = 1, /* rport is offline */
- BFA_RPORT_PLOGI = 2, /* PLOGI to rport is in progress */
- BFA_RPORT_ONLINE = 3, /* login to rport is complete */
- BFA_RPORT_PLOGI_RETRY = 4, /* retrying login to rport */
- BFA_RPORT_NSQUERY = 5, /* nameserver query */
- BFA_RPORT_ADISC = 6, /* ADISC authentication */
- BFA_RPORT_LOGO = 7, /* logging out with rport */
- BFA_RPORT_LOGORCV = 8, /* handling LOGO from rport */
- BFA_RPORT_NSDISC = 9, /* re-discover rport */
-};
-
-/**
- * Rport Scsi Function : Initiator/Target.
- */
-enum bfa_rport_function {
- BFA_RPORT_INITIATOR = 0x01, /* SCSI Initiator */
- BFA_RPORT_TARGET = 0x02, /* SCSI Target */
-};
-
-/**
- * port/node symbolic names for rport
- */
-#define BFA_RPORT_SYMNAME_MAXLEN 255
-struct bfa_rport_symname_s {
- char symname[BFA_RPORT_SYMNAME_MAXLEN];
-};
-
-struct bfa_rport_hal_stats_s {
- u32 sm_un_cr; /* uninit: create events */
- u32 sm_un_unexp; /* uninit: exception events */
- u32 sm_cr_on; /* created: online events */
- u32 sm_cr_del; /* created: delete events */
- u32 sm_cr_hwf; /* created: IOC down */
- u32 sm_cr_unexp; /* created: exception events */
- u32 sm_fwc_rsp; /* fw create: f/w responses */
- u32 sm_fwc_del; /* fw create: delete events */
- u32 sm_fwc_off; /* fw create: offline events */
- u32 sm_fwc_hwf; /* fw create: IOC down */
- u32 sm_fwc_unexp; /* fw create: exception events*/
- u32 sm_on_off; /* online: offline events */
- u32 sm_on_del; /* online: delete events */
- u32 sm_on_hwf; /* online: IOC down events */
- u32 sm_on_unexp; /* online: exception events */
- u32 sm_fwd_rsp; /* fw delete: fw responses */
- u32 sm_fwd_del; /* fw delete: delete events */
- u32 sm_fwd_hwf; /* fw delete: IOC down events */
- u32 sm_fwd_unexp; /* fw delete: exception events*/
- u32 sm_off_del; /* offline: delete events */
- u32 sm_off_on; /* offline: online events */
- u32 sm_off_hwf; /* offline: IOC down events */
- u32 sm_off_unexp; /* offline: exception events */
- u32 sm_del_fwrsp; /* delete: fw responses */
- u32 sm_del_hwf; /* delete: IOC down events */
- u32 sm_del_unexp; /* delete: exception events */
- u32 sm_delp_fwrsp; /* delete pend: fw responses */
- u32 sm_delp_hwf; /* delete pend: IOC downs */
- u32 sm_delp_unexp; /* delete pend: exceptions */
- u32 sm_offp_fwrsp; /* off-pending: fw responses */
- u32 sm_offp_del; /* off-pending: deletes */
- u32 sm_offp_hwf; /* off-pending: IOC downs */
- u32 sm_offp_unexp; /* off-pending: exceptions */
- u32 sm_iocd_off; /* IOC down: offline events */
- u32 sm_iocd_del; /* IOC down: delete events */
- u32 sm_iocd_on; /* IOC down: online events */
- u32 sm_iocd_unexp; /* IOC down: exceptions */
- u32 rsvd;
-};
-
-/**
- * FCS remote port statistics
- */
-struct bfa_rport_stats_s {
- u32 offlines; /* remote port offline count */
- u32 onlines; /* remote port online count */
- u32 rscns; /* RSCN affecting rport */
- u32 plogis; /* plogis sent */
- u32 plogi_accs; /* plogi accepts */
- u32 plogi_timeouts; /* plogi timeouts */
- u32 plogi_rejects; /* rcvd plogi rejects */
- u32 plogi_failed; /* local failure */
- u32 plogi_rcvd; /* plogis rcvd */
- u32 prli_rcvd; /* inbound PRLIs */
- u32 adisc_rcvd; /* ADISCs received */
- u32 adisc_rejects; /* recvd ADISC rejects */
- u32 adisc_sent; /* ADISC requests sent */
- u32 adisc_accs; /* ADISC accepted by rport */
- u32 adisc_failed; /* ADISC failed (no response) */
- u32 adisc_rejected; /* ADISC rejected by us */
- u32 logos; /* logos sent */
- u32 logo_accs; /* LOGO accepts from rport */
- u32 logo_failed; /* LOGO failures */
- u32 logo_rejected; /* LOGO rejects from rport */
- u32 logo_rcvd; /* LOGO from remote port */
-
- u32 rpsc_rcvd; /* RPSC received */
- u32 rpsc_rejects; /* recvd RPSC rejects */
- u32 rpsc_sent; /* RPSC requests sent */
- u32 rpsc_accs; /* RPSC accepted by rport */
- u32 rpsc_failed; /* RPSC failed (no response) */
- u32 rpsc_rejected; /* RPSC rejected by us */
-
- u32 rsvd;
- struct bfa_rport_hal_stats_s hal_stats; /* BFA rport stats */
-};
-
-/**
- * Rport's QoS attributes
- */
-struct bfa_rport_qos_attr_s {
- enum bfa_qos_priority qos_priority; /* rport's QoS priority */
- u32 qos_flow_id; /* QoS flow Id */
-};
-
-/**
- * FCS remote port attributes returned in queries
- */
-struct bfa_rport_attr_s {
- wwn_t nwwn; /* node wwn */
- wwn_t pwwn; /* port wwn */
- enum fc_cos cos_supported; /* supported class of services */
- u32 pid; /* port ID */
- u32 df_sz; /* Max payload size */
- enum bfa_rport_state state; /* Rport State machine state */
- enum fc_cos fc_cos; /* FC classes of services */
- bfa_boolean_t cisc; /* CISC capable device */
- struct bfa_rport_symname_s symname; /* Symbolic Name */
- enum bfa_rport_function scsi_function; /* Initiator/Target */
- struct bfa_rport_qos_attr_s qos_attr; /* qos attributes */
- enum bfa_pport_speed curr_speed; /* operating speed got from
- * RPSC ELS. UNKNOWN, if RPSC
- * is not supported */
- bfa_boolean_t trl_enforced; /* TRL enforced ? TRUE/FALSE */
- enum bfa_pport_speed assigned_speed; /* Speed assigned by the user.
- * will be used if RPSC is not
- * supported by the rport */
-};
-
-#define bfa_rport_aen_qos_data_t struct bfa_rport_qos_attr_s
-
-/**
- * BFA remote port events
- * Arguments below are in BFAL context from Mgmt
- * BFA_RPORT_AEN_ONLINE: [in]: lpwwn [out]: vf_id, lpwwn, rpwwn
- * BFA_RPORT_AEN_OFFLINE: [in]: lpwwn [out]: vf_id, lpwwn, rpwwn
- * BFA_RPORT_AEN_DISCONNECT:[in]: lpwwn [out]: vf_id, lpwwn, rpwwn
- * BFA_RPORT_AEN_QOS_PRIO: [in]: lpwwn [out]: vf_id, lpwwn, rpwwn, prio
- * BFA_RPORT_AEN_QOS_FLOWID:[in]: lpwwn [out]: vf_id, lpwwn, rpwwn, flow_id
- */
-enum bfa_rport_aen_event {
- BFA_RPORT_AEN_ONLINE = 1, /* RPort online event */
- BFA_RPORT_AEN_OFFLINE = 2, /* RPort offline event */
- BFA_RPORT_AEN_DISCONNECT = 3, /* RPort disconnect event */
- BFA_RPORT_AEN_QOS_PRIO = 4, /* QOS priority change event */
- BFA_RPORT_AEN_QOS_FLOWID = 5, /* QOS flow Id change event */
-};
-
-struct bfa_rport_aen_data_s {
- u16 vf_id; /* vf_id of this logical port */
- u16 rsvd[3];
- wwn_t ppwwn; /* WWN of its physical port */
- wwn_t lpwwn; /* WWN of this logical port */
- wwn_t rpwwn; /* WWN of this remote port */
- union {
- bfa_rport_aen_qos_data_t qos;
- } priv;
-};
-
-#endif /* __BFA_DEFS_RPORT_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_status.h b/drivers/scsi/bfa/include/defs/bfa_defs_status.h
deleted file mode 100644
index 6eb4e62096fc..000000000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_status.h
+++ /dev/null
@@ -1,282 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-#ifndef __BFA_DEFS_STATUS_H__
-#define __BFA_DEFS_STATUS_H__
-
-/**
- * API status return values
- *
- * NOTE: The error msgs are auto generated from the comments. Only singe line
- * comments are supported
- */
-enum bfa_status {
- BFA_STATUS_OK = 0, /* Success */
- BFA_STATUS_FAILED = 1, /* Operation failed */
- BFA_STATUS_EINVAL = 2, /* Invalid params Check input
- * parameters */
- BFA_STATUS_ENOMEM = 3, /* Out of resources */
- BFA_STATUS_ENOSYS = 4, /* Function not implemented */
- BFA_STATUS_ETIMER = 5, /* Timer expired - Retry, if
- * persists, contact support */
- BFA_STATUS_EPROTOCOL = 6, /* Protocol error */
- BFA_STATUS_ENOFCPORTS = 7, /* No FC ports resources */
- BFA_STATUS_NOFLASH = 8, /* Flash not present */
- BFA_STATUS_BADFLASH = 9, /* Flash is corrupted or bad */
- BFA_STATUS_SFP_UNSUPP = 10, /* Unsupported SFP - Replace SFP */
- BFA_STATUS_UNKNOWN_VFID = 11, /* VF_ID not found */
- BFA_STATUS_DATACORRUPTED = 12, /* Diag returned data corrupted
- * contact support */
- BFA_STATUS_DEVBUSY = 13, /* Device busy - Retry operation */
- BFA_STATUS_ABORTED = 14, /* Operation aborted */
- BFA_STATUS_NODEV = 15, /* Dev is not present */
- BFA_STATUS_HDMA_FAILED = 16, /* Host dma failed contact support */
- BFA_STATUS_FLASH_BAD_LEN = 17, /* Flash bad length */
- BFA_STATUS_UNKNOWN_LWWN = 18, /* LPORT PWWN not found */
- BFA_STATUS_UNKNOWN_RWWN = 19, /* RPORT PWWN not found */
- BFA_STATUS_FCPT_LS_RJT = 20, /* Got LS_RJT for FC Pass
- * through Req */
- BFA_STATUS_VPORT_EXISTS = 21, /* VPORT already exists */
- BFA_STATUS_VPORT_MAX = 22, /* Reached max VPORT supported
- * limit */
- BFA_STATUS_UNSUPP_SPEED = 23, /* Invalid Speed Check speed
- * setting */
- BFA_STATUS_INVLD_DFSZ = 24, /* Invalid Max data field size */
- BFA_STATUS_CNFG_FAILED = 25, /* Setting can not be persisted */
- BFA_STATUS_CMD_NOTSUPP = 26, /* Command/API not supported */
- BFA_STATUS_NO_ADAPTER = 27, /* No Brocade Adapter Found */
- BFA_STATUS_LINKDOWN = 28, /* Link is down - Check or replace
- * SFP/cable */
- BFA_STATUS_FABRIC_RJT = 29, /* Reject from attached fabric */
- BFA_STATUS_UNKNOWN_VWWN = 30, /* VPORT PWWN not found */
- BFA_STATUS_NSLOGIN_FAILED = 31, /* Nameserver login failed */
- BFA_STATUS_NO_RPORTS = 32, /* No remote ports found */
- BFA_STATUS_NSQUERY_FAILED = 33, /* Nameserver query failed */
- BFA_STATUS_PORT_OFFLINE = 34, /* Port is not online */
- BFA_STATUS_RPORT_OFFLINE = 35, /* RPORT is not online */
- BFA_STATUS_TGTOPEN_FAILED = 36, /* Remote SCSI target open failed */
- BFA_STATUS_BAD_LUNS = 37, /* No valid LUNs found */
- BFA_STATUS_IO_FAILURE = 38, /* SCSI target IO failure */
- BFA_STATUS_NO_FABRIC = 39, /* No switched fabric present */
- BFA_STATUS_EBADF = 40, /* Bad file descriptor */
- BFA_STATUS_EINTR = 41, /* A signal was caught during ioctl */
- BFA_STATUS_EIO = 42, /* I/O error */
- BFA_STATUS_ENOTTY = 43, /* Inappropriate I/O control
- * operation */
- BFA_STATUS_ENXIO = 44, /* No such device or address */
- BFA_STATUS_EFOPEN = 45, /* Failed to open file */
- BFA_STATUS_VPORT_WWN_BP = 46, /* WWN is same as base port's WWN */
- BFA_STATUS_PORT_NOT_DISABLED = 47, /* Port not disabled disable port
- * first */
- BFA_STATUS_BADFRMHDR = 48, /* Bad frame header */
- BFA_STATUS_BADFRMSZ = 49, /* Bad frame size check and replace
- * SFP/cable */
- BFA_STATUS_MISSINGFRM = 50, /* Missing frame check and replace
- * SFP/cable or for Mezz card check and
- * replace pass through module */
- BFA_STATUS_LINKTIMEOUT = 51, /* Link timeout check and replace
- * SFP/cable */
- BFA_STATUS_NO_FCPIM_NEXUS = 52, /* No FCP Nexus exists with the
- * rport */
- BFA_STATUS_CHECKSUM_FAIL = 53, /* checksum failure */
- BFA_STATUS_GZME_FAILED = 54, /* Get zone member query failed */
- BFA_STATUS_SCSISTART_REQD = 55, /* SCSI disk require START command */
- BFA_STATUS_IOC_FAILURE = 56, /* IOC failure - Retry, if persists
- * contact support */
- BFA_STATUS_INVALID_WWN = 57, /* Invalid WWN */
- BFA_STATUS_MISMATCH = 58, /* Version mismatch */
- BFA_STATUS_IOC_ENABLED = 59, /* IOC is already enabled */
- BFA_STATUS_ADAPTER_ENABLED = 60, /* Adapter is not disabled disable
- * adapter first */
- BFA_STATUS_IOC_NON_OP = 61, /* IOC is not operational. Enable IOC
- * and if it still fails,
- * contact support */
- BFA_STATUS_ADDR_MAP_FAILURE = 62, /* PCI base address not mapped
- * in OS */
- BFA_STATUS_SAME_NAME = 63, /* Name exists! use a different
- * name */
- BFA_STATUS_PENDING = 64, /* API completes asynchronously */
- BFA_STATUS_8G_SPD = 65, /* Speed setting not valid for
- * 8G HBA */
- BFA_STATUS_4G_SPD = 66, /* Speed setting not valid for
- * 4G HBA */
- BFA_STATUS_AD_IS_ENABLE = 67, /* Adapter is already enabled */
- BFA_STATUS_EINVAL_TOV = 68, /* Invalid path failover TOV */
- BFA_STATUS_EINVAL_QDEPTH = 69, /* Invalid queue depth value */
- BFA_STATUS_VERSION_FAIL = 70, /* Application/Driver version
- * mismatch */
- BFA_STATUS_DIAG_BUSY = 71, /* diag busy */
- BFA_STATUS_BEACON_ON = 72, /* Port Beacon already on */
- BFA_STATUS_BEACON_OFF = 73, /* Port Beacon already off */
- BFA_STATUS_LBEACON_ON = 74, /* Link End-to-End Beacon already
- * on */
- BFA_STATUS_LBEACON_OFF = 75, /* Link End-to-End Beacon already
- * off */
- BFA_STATUS_PORT_NOT_INITED = 76, /* Port not initialized */
- BFA_STATUS_RPSC_ENABLED = 77, /* Target has a valid speed */
- BFA_STATUS_ENOFSAVE = 78, /* No saved firmware trace */
- BFA_STATUS_BAD_FILE = 79, /* Not a valid Brocade Boot Code
- * file */
- BFA_STATUS_RLIM_EN = 80, /* Target rate limiting is already
- * enabled */
- BFA_STATUS_RLIM_DIS = 81, /* Target rate limiting is already
- * disabled */
- BFA_STATUS_IOC_DISABLED = 82, /* IOC is already disabled */
- BFA_STATUS_ADAPTER_DISABLED = 83, /* Adapter is already disabled */
- BFA_STATUS_BIOS_DISABLED = 84, /* Bios is already disabled */
- BFA_STATUS_AUTH_ENABLED = 85, /* Authentication is already
- * enabled */
- BFA_STATUS_AUTH_DISABLED = 86, /* Authentication is already
- * disabled */
- BFA_STATUS_ERROR_TRL_ENABLED = 87, /* Target rate limiting is
- * enabled */
- BFA_STATUS_ERROR_QOS_ENABLED = 88, /* QoS is enabled */
- BFA_STATUS_NO_SFP_DEV = 89, /* No SFP device check or replace SFP */
- BFA_STATUS_MEMTEST_FAILED = 90, /* Memory test failed contact
- * support */
- BFA_STATUS_INVALID_DEVID = 91, /* Invalid device id provided */
- BFA_STATUS_QOS_ENABLED = 92, /* QOS is already enabled */
- BFA_STATUS_QOS_DISABLED = 93, /* QOS is already disabled */
- BFA_STATUS_INCORRECT_DRV_CONFIG = 94, /* Check configuration
- * key/value pair */
- BFA_STATUS_REG_FAIL = 95, /* Can't read windows registry */
- BFA_STATUS_IM_INV_CODE = 96, /* Invalid IOCTL code */
- BFA_STATUS_IM_INV_VLAN = 97, /* Invalid VLAN ID */
- BFA_STATUS_IM_INV_ADAPT_NAME = 98, /* Invalid adapter name */
- BFA_STATUS_IM_LOW_RESOURCES = 99, /* Memory allocation failure in
- * driver */
- BFA_STATUS_IM_VLANID_IS_PVID = 100, /* Given VLAN id same as PVID */
- BFA_STATUS_IM_VLANID_EXISTS = 101, /* Given VLAN id already exists */
- BFA_STATUS_IM_FW_UPDATE_FAIL = 102, /* Updating firmware with new
- * VLAN ID failed */
- BFA_STATUS_PORTLOG_ENABLED = 103, /* Port Log is already enabled */
- BFA_STATUS_PORTLOG_DISABLED = 104, /* Port Log is already disabled */
- BFA_STATUS_FILE_NOT_FOUND = 105, /* Specified file could not be
- * found */
- BFA_STATUS_QOS_FC_ONLY = 106, /* QOS can be enabled for FC mode
- * only */
- BFA_STATUS_RLIM_FC_ONLY = 107, /* RATELIM can be enabled for FC mode
- * only */
- BFA_STATUS_CT_SPD = 108, /* Invalid speed selection for Catapult. */
- BFA_STATUS_LEDTEST_OP = 109, /* LED test is operating */
- BFA_STATUS_CEE_NOT_DN = 110, /* eth port is not at down state, please
- * bring down first */
- BFA_STATUS_10G_SPD = 111, /* Speed setting not valid for 10G CNA */
- BFA_STATUS_IM_INV_TEAM_NAME = 112, /* Invalid team name */
- BFA_STATUS_IM_DUP_TEAM_NAME = 113, /* Given team name already
- * exists */
- BFA_STATUS_IM_ADAPT_ALREADY_IN_TEAM = 114, /* Given adapter is part
- * of another team */
- BFA_STATUS_IM_ADAPT_HAS_VLANS = 115, /* Adapter has VLANs configured.
- * Delete all VLANs to become
- * part of the team */
- BFA_STATUS_IM_PVID_MISMATCH = 116, /* Mismatching PVIDs configured
- * for adapters */
- BFA_STATUS_IM_LINK_SPEED_MISMATCH = 117, /* Mismatching link speeds
- * configured for adapters */
- BFA_STATUS_IM_MTU_MISMATCH = 118, /* Mismatching MTUs configured for
- * adapters */
- BFA_STATUS_IM_RSS_MISMATCH = 119, /* Mismatching RSS parameters
- * configured for adapters */
- BFA_STATUS_IM_HDS_MISMATCH = 120, /* Mismatching HDS parameters
- * configured for adapters */
- BFA_STATUS_IM_OFFLOAD_MISMATCH = 121, /* Mismatching offload
- * parameters configured for
- * adapters */
- BFA_STATUS_IM_PORT_PARAMS = 122, /* Error setting port parameters */
- BFA_STATUS_IM_PORT_NOT_IN_TEAM = 123, /* Port is not part of team */
- BFA_STATUS_IM_CANNOT_REM_PRI = 124, /* Primary adapter cannot be
- * removed. Change primary before
- * removing */
- BFA_STATUS_IM_MAX_PORTS_REACHED = 125, /* Exceeding maximum ports
- * per team */
- BFA_STATUS_IM_LAST_PORT_DELETE = 126, /* Last port in team being
- * deleted */
- BFA_STATUS_IM_NO_DRIVER = 127, /* IM driver is not installed */
- BFA_STATUS_IM_MAX_VLANS_REACHED = 128, /* Exceeding maximum VLANs
- * per port */
- BFA_STATUS_TOMCAT_SPD_NOT_ALLOWED = 129, /* Bios speed config not
- * allowed for CNA */
- BFA_STATUS_NO_MINPORT_DRIVER = 130, /* Miniport driver is not
- * loaded */
- BFA_STATUS_CARD_TYPE_MISMATCH = 131, /* Card type mismatch */
- BFA_STATUS_BAD_ASICBLK = 132, /* Bad ASIC block */
- BFA_STATUS_NO_DRIVER = 133, /* Brocade adapter/driver not installed
- * or loaded */
- BFA_STATUS_INVALID_MAC = 134, /* Invalid MAC address */
- BFA_STATUS_IM_NO_VLAN = 135, /* No VLANs configured on the adapter */
- BFA_STATUS_IM_ETH_LB_FAILED = 136, /* Ethernet loopback test failed */
- BFA_STATUS_IM_PVID_REMOVE = 137, /* Cannot remove port VLAN (PVID) */
- BFA_STATUS_IM_PVID_EDIT = 138, /* Cannot edit port VLAN (PVID) */
- BFA_STATUS_CNA_NO_BOOT = 139, /* Boot upload not allowed for CNA */
- BFA_STATUS_IM_PVID_NON_ZERO = 140, /* Port VLAN ID (PVID) is Set to
- * Non-Zero Value */
- BFA_STATUS_IM_INETCFG_LOCK_FAILED = 141, /* Acquiring Network
- * Subsystem Lock Failed.Please
- * try after some time */
- BFA_STATUS_IM_GET_INETCFG_FAILED = 142, /* Acquiring Network Subsystem
- * handle Failed. Please try
- * after some time */
- BFA_STATUS_IM_NOT_BOUND = 143, /* IM driver is not active */
- BFA_STATUS_INSUFFICIENT_PERMS = 144, /* User doesn't have sufficient
- * permissions to execute the BCU
- * application */
- BFA_STATUS_IM_INV_VLAN_NAME = 145, /* Invalid/Reserved VLAN name
- * string. The name is not allowed
- * for the normal VLAN */
- BFA_STATUS_CMD_NOTSUPP_CNA = 146, /* Command not supported for CNA */
- BFA_STATUS_IM_PASSTHRU_EDIT = 147, /* Can not edit passthrough VLAN
- * id */
- BFA_STATUS_IM_BIND_FAILED = 148, /* IM Driver bind operation
- * failed */
- BFA_STATUS_IM_UNBIND_FAILED = 149, /* IM Driver unbind operation
- * failed */
- BFA_STATUS_IM_PORT_IN_TEAM = 150, /* Port is already part of the
- * team */
- BFA_STATUS_IM_VLAN_NOT_FOUND = 151, /* VLAN ID doesn't exists */
- BFA_STATUS_IM_TEAM_NOT_FOUND = 152, /* Teaming configuration doesn't
- * exists */
- BFA_STATUS_IM_TEAM_CFG_NOT_ALLOWED = 153, /* Given settings are not
- * allowed for the current
- * Teaming mode */
- BFA_STATUS_PBC = 154, /* Operation not allowed for pre-boot
- * configuration */
- BFA_STATUS_DEVID_MISSING = 155, /* Boot image is not for the adapter(s)
- * installed */
- BFA_STATUS_BAD_FWCFG = 156, /* Bad firmware configuration */
- BFA_STATUS_CREATE_FILE = 157, /* Failed to create temporary file */
- BFA_STATUS_INVALID_VENDOR = 158, /* Invalid switch vendor */
- BFA_STATUS_SFP_NOT_READY = 159, /* SFP info is not ready. Retry */
- BFA_STATUS_NO_TOPOLOGY_FOR_CNA = 160, /* Topology command not
- * applicable to CNA */
- BFA_STATUS_BOOT_CODE_UPDATED = 161, /* reboot -- -r is needed after
- * boot code updated */
- BFA_STATUS_BOOT_VERSION = 162, /* Boot code version not compatible with
- * the driver installed */
- BFA_STATUS_CARDTYPE_MISSING = 163, /* Boot image is not for the
- * adapter(s) installed */
- BFA_STATUS_INVALID_CARDTYPE = 164, /* Invalid card type provided */
- BFA_STATUS_MAX_VAL /* Unknown error code */
-};
-#define bfa_status_t enum bfa_status
-
-enum bfa_eproto_status {
- BFA_EPROTO_BAD_ACCEPT = 0,
- BFA_EPROTO_UNKNOWN_RSP = 1
-};
-#define bfa_eproto_status_t enum bfa_eproto_status
-
-#endif /* __BFA_DEFS_STATUS_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_tin.h b/drivers/scsi/bfa/include/defs/bfa_defs_tin.h
deleted file mode 100644
index e05a2db7abed..000000000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_tin.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_DEFS_TIN_H__
-#define __BFA_DEFS_TIN_H__
-
-#include <protocol/types.h>
-#include <protocol/fc.h>
-
-/**
- * FCS tin states
- */
-enum bfa_tin_state_e {
- BFA_TIN_SM_OFFLINE = 0, /* tin is offline */
- BFA_TIN_SM_WOS_LOGIN = 1, /* Waiting PRLI ACC/RJT from ULP */
- BFA_TIN_SM_WFW_ONLINE = 2, /* Waiting ACK to PRLI ACC from FW */
- BFA_TIN_SM_ONLINE = 3, /* tin login is complete */
- BFA_TIN_SM_WIO_RELOGIN = 4, /* tin relogin is in progress */
- BFA_TIN_SM_WIO_LOGOUT = 5, /* Processing of PRLO req from
- * Initiator is in progress
- */
- BFA_TIN_SM_WOS_LOGOUT = 6, /* Processing of PRLO req from
- * Initiator is in progress
- */
- BFA_TIN_SM_WIO_CLEAN = 7, /* Waiting for IO cleanup before tin
- * is offline. This can be triggered
- * by RPORT LOGO (rcvd/sent) or by
- * PRLO (rcvd/sent)
- */
-};
-
-struct bfa_prli_req_s {
- struct fchs_s fchs;
- struct fc_prli_s prli_payload;
-};
-
-struct bfa_prlo_req_s {
- struct fchs_s fchs;
- struct fc_prlo_s prlo_payload;
-};
-
-void bfa_tin_send_login_rsp(void *bfa_tin, u32 login_rsp,
- struct fc_ls_rjt_s rjt_payload);
-void bfa_tin_send_logout_rsp(void *bfa_tin, u32 logout_rsp,
- struct fc_ls_rjt_s rjt_payload);
-/**
- * FCS target port statistics
- */
-struct bfa_tin_stats_s {
- u32 onlines; /* ITN nexus onlines (PRLI done) */
- u32 offlines; /* ITN Nexus offlines */
- u32 prli_req_parse_err; /* prli req parsing errors */
- u32 prli_rsp_rjt; /* num prli rsp rejects sent */
- u32 prli_rsp_acc; /* num prli rsp accepts sent */
- u32 cleanup_comps; /* ITN cleanup completions */
-};
-
-/**
- * FCS tin attributes returned in queries
- */
-struct bfa_tin_attr_s {
- enum bfa_tin_state_e state;
- u8 seq_retry; /* Sequence retry supported */
- u8 rsvd[3];
-};
-
-/**
- * BFA TIN async event data structure for BFAL
- */
-enum bfa_tin_aen_event {
- BFA_TIN_AEN_ONLINE = 1, /* Target online */
- BFA_TIN_AEN_OFFLINE = 2, /* Target offline */
- BFA_TIN_AEN_DISCONNECT = 3, /* Target disconnected */
-};
-
-/**
- * BFA TIN event data structure.
- */
-struct bfa_tin_aen_data_s {
- u16 vf_id; /* vf_id of the IT nexus */
- u16 rsvd[3];
- wwn_t lpwwn; /* WWN of logical port */
- wwn_t rpwwn; /* WWN of remote(target) port */
-};
-
-/**
- * Below APIs are needed from BFA driver
- * Move these to BFA driver public header file?
- */
-/* TIN rcvd new PRLI & gets bfad_tin_t ptr from driver this callback */
-void *bfad_tin_rcvd_login_req(void *bfad_tm_port, void *bfa_tin,
- wwn_t rp_wwn, u32 rp_fcid,
- struct bfa_prli_req_s prli_req);
-/* TIN rcvd new PRLO */
-void bfad_tin_rcvd_logout_req(void *bfad_tin, wwn_t rp_wwn, u32 rp_fcid,
- struct bfa_prlo_req_s prlo_req);
-/* TIN is online and ready for IO */
-void bfad_tin_online(void *bfad_tin);
-/* TIN is offline and BFA driver can shutdown its upper stack */
-void bfad_tin_offline(void *bfad_tin);
-/* TIN does not need this BFA driver tin tag anymore, so can be freed */
-void bfad_tin_res_free(void *bfad_tin);
-
-#endif /* __BFA_DEFS_TIN_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_tsensor.h b/drivers/scsi/bfa/include/defs/bfa_defs_tsensor.h
deleted file mode 100644
index ade763dbc8ce..000000000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_tsensor.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_DEFS_TSENSOR_H__
-#define __BFA_DEFS_TSENSOR_H__
-
-#include <bfa_os_inc.h>
-#include <defs/bfa_defs_types.h>
-
-/**
- * Temperature sensor status values
- */
-enum bfa_tsensor_status {
- BFA_TSENSOR_STATUS_UNKNOWN = 1, /* unknown status */
- BFA_TSENSOR_STATUS_FAULTY = 2, /* sensor is faulty */
- BFA_TSENSOR_STATUS_BELOW_MIN = 3, /* temperature below mininum */
- BFA_TSENSOR_STATUS_NOMINAL = 4, /* normal temperature */
- BFA_TSENSOR_STATUS_ABOVE_MAX = 5, /* temperature above maximum */
-};
-
-/**
- * Temperature sensor attribute
- */
-struct bfa_tsensor_attr_s {
- enum bfa_tsensor_status status; /* temperature sensor status */
- u32 value; /* current temperature in celsius */
-};
-
-#endif /* __BFA_DEFS_TSENSOR_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_types.h b/drivers/scsi/bfa/include/defs/bfa_defs_types.h
deleted file mode 100644
index 4348332b107a..000000000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_types.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-#ifndef __BFA_DEFS_TYPES_H__
-#define __BFA_DEFS_TYPES_H__
-
-#include <bfa_os_inc.h>
-
-enum bfa_boolean {
- BFA_FALSE = 0,
- BFA_TRUE = 1
-};
-#define bfa_boolean_t enum bfa_boolean
-
-#define BFA_STRING_32 32
-
-#endif /* __BFA_DEFS_TYPES_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_version.h b/drivers/scsi/bfa/include/defs/bfa_defs_version.h
deleted file mode 100644
index f8902a2c9aad..000000000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_version.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-#ifndef __BFA_DEFS_VERSION_H__
-#define __BFA_DEFS_VERSION_H__
-
-#define BFA_VERSION_LEN 64
-
-#endif
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_vf.h b/drivers/scsi/bfa/include/defs/bfa_defs_vf.h
deleted file mode 100644
index 3235be5e9423..000000000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_vf.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_DEFS_VF_H__
-#define __BFA_DEFS_VF_H__
-
-#include <bfa_os_inc.h>
-#include <defs/bfa_defs_port.h>
-#include <protocol/types.h>
-
-/**
- * VF states
- */
-enum bfa_vf_state {
- BFA_VF_UNINIT = 0, /* fabric is not yet initialized */
- BFA_VF_LINK_DOWN = 1, /* link is down */
- BFA_VF_FLOGI = 2, /* flogi is in progress */
- BFA_VF_AUTH = 3, /* authentication in progress */
- BFA_VF_NOFABRIC = 4, /* fabric is not present */
- BFA_VF_ONLINE = 5, /* login to fabric is complete */
- BFA_VF_EVFP = 6, /* EVFP is in progress */
- BFA_VF_ISOLATED = 7, /* port isolated due to vf_id mismatch */
-};
-
-/**
- * VF statistics
- */
-struct bfa_vf_stats_s {
- u32 flogi_sent; /* Num FLOGIs sent */
- u32 flogi_rsp_err; /* FLOGI response errors */
- u32 flogi_acc_err; /* FLOGI accept errors */
- u32 flogi_accepts; /* FLOGI accepts received */
- u32 flogi_rejects; /* FLOGI rejects received */
- u32 flogi_unknown_rsp; /* Unknown responses for FLOGI */
- u32 flogi_alloc_wait; /* Allocation waits prior to
- * sending FLOGI
- */
- u32 flogi_rcvd; /* FLOGIs received */
- u32 flogi_rejected; /* Incoming FLOGIs rejected */
- u32 fabric_onlines; /* Internal fabric online
- * notification sent to other
- * modules
- */
- u32 fabric_offlines; /* Internal fabric offline
- * notification sent to other
- * modules
- */
- u32 resvd;
-};
-
-/**
- * VF attributes returned in queries
- */
-struct bfa_vf_attr_s {
- enum bfa_vf_state state; /* VF state */
- u32 rsvd;
- wwn_t fabric_name; /* fabric name */
-};
-
-#endif /* __BFA_DEFS_VF_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_vport.h b/drivers/scsi/bfa/include/defs/bfa_defs_vport.h
deleted file mode 100644
index 9f021f43b3b4..000000000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_vport.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_DEFS_VPORT_H__
-#define __BFA_DEFS_VPORT_H__
-
-#include <bfa_os_inc.h>
-#include <defs/bfa_defs_port.h>
-#include <protocol/types.h>
-
-/**
- * VPORT states
- */
-enum bfa_vport_state {
- BFA_FCS_VPORT_UNINIT = 0,
- BFA_FCS_VPORT_CREATED = 1,
- BFA_FCS_VPORT_OFFLINE = 1,
- BFA_FCS_VPORT_FDISC_SEND = 2,
- BFA_FCS_VPORT_FDISC = 3,
- BFA_FCS_VPORT_FDISC_RETRY = 4,
- BFA_FCS_VPORT_ONLINE = 5,
- BFA_FCS_VPORT_DELETING = 6,
- BFA_FCS_VPORT_CLEANUP = 6,
- BFA_FCS_VPORT_LOGO_SEND = 7,
- BFA_FCS_VPORT_LOGO = 8,
- BFA_FCS_VPORT_ERROR = 9,
- BFA_FCS_VPORT_MAX_STATE,
-};
-
-/**
- * vport statistics
- */
-struct bfa_vport_stats_s {
- struct bfa_port_stats_s port_stats; /* base class (port) stats */
- /*
- * TODO - remove
- */
-
- u32 fdisc_sent; /* num fdisc sent */
- u32 fdisc_accepts; /* fdisc accepts */
- u32 fdisc_retries; /* fdisc retries */
- u32 fdisc_timeouts; /* fdisc timeouts */
- u32 fdisc_rsp_err; /* fdisc response error */
- u32 fdisc_acc_bad; /* bad fdisc accepts */
- u32 fdisc_rejects; /* fdisc rejects */
- u32 fdisc_unknown_rsp;
- /*
- *!< fdisc rsp unknown error
- */
- u32 fdisc_alloc_wait;/* fdisc req (fcxp)alloc wait */
-
- u32 logo_alloc_wait;/* logo req (fcxp) alloc wait */
- u32 logo_sent; /* logo sent */
- u32 logo_accepts; /* logo accepts */
- u32 logo_rejects; /* logo rejects */
- u32 logo_rsp_err; /* logo rsp errors */
- u32 logo_unknown_rsp;
- /* logo rsp unknown errors */
-
- u32 fab_no_npiv; /* fabric does not support npiv */
-
- u32 fab_offline; /* offline events from fab SM */
- u32 fab_online; /* online events from fab SM */
- u32 fab_cleanup; /* cleanup request from fab SM */
- u32 rsvd;
-};
-
-/**
- * BFA vport attribute returned in queries
- */
-struct bfa_vport_attr_s {
- struct bfa_port_attr_s port_attr; /* base class (port) attributes */
- enum bfa_vport_state vport_state; /* vport state */
- u32 rsvd;
-};
-
-#endif /* __BFA_DEFS_VPORT_H__ */
diff --git a/drivers/scsi/bfa/include/fcb/bfa_fcb.h b/drivers/scsi/bfa/include/fcb/bfa_fcb.h
deleted file mode 100644
index 2963b0bc30e7..000000000000
--- a/drivers/scsi/bfa/include/fcb/bfa_fcb.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/**
- * bfa_fcb.h BFA FCS callback interfaces
- */
-
-#ifndef __BFA_FCB_H__
-#define __BFA_FCB_H__
-
-/**
- * fcb Main fcs callbacks
- */
-
-void bfa_fcb_exit(struct bfad_s *bfad);
-
-
-
-#endif /* __BFA_FCB_H__ */
diff --git a/drivers/scsi/bfa/include/fcb/bfa_fcb_fcpim.h b/drivers/scsi/bfa/include/fcb/bfa_fcb_fcpim.h
deleted file mode 100644
index 52585d3dd891..000000000000
--- a/drivers/scsi/bfa/include/fcb/bfa_fcb_fcpim.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/**
-* : bfad_fcpim.h - BFA FCS initiator mode remote port callbacks
- */
-
-#ifndef __BFAD_FCB_FCPIM_H__
-#define __BFAD_FCB_FCPIM_H__
-
-struct bfad_itnim_s;
-
-/*
- * RPIM callbacks
- */
-
-/**
- * Memory allocation for remote port instance. Called before PRLI is
- * initiated to the remote target port.
- *
- * @param[in] bfad - driver instance
- * @param[out] itnim - FCS remote port (IM) instance
- * @param[out] itnim_drv - driver remote port (IM) instance
- *
- * @return None
- */
-void bfa_fcb_itnim_alloc(struct bfad_s *bfad, struct bfa_fcs_itnim_s **itnim,
- struct bfad_itnim_s **itnim_drv);
-
-/**
- * Free remote port (IM) instance.
- *
- * @param[in] bfad - driver instance
- * @param[in] itnim_drv - driver remote port instance
- *
- * @return None
- */
-void bfa_fcb_itnim_free(struct bfad_s *bfad,
- struct bfad_itnim_s *itnim_drv);
-
-/**
- * Notification of when login with a remote target device is complete.
- *
- * @param[in] itnim_drv - driver remote port instance
- *
- * @return None
- */
-void bfa_fcb_itnim_online(struct bfad_itnim_s *itnim_drv);
-
-/**
- * Notification when login with the remote device is severed.
- *
- * @param[in] itnim_drv - driver remote port instance
- *
- * @return None
- */
-void bfa_fcb_itnim_offline(struct bfad_itnim_s *itnim_drv);
-
-void bfa_fcb_itnim_tov(struct bfad_itnim_s *itnim_drv);
-
-#endif /* __BFAD_FCB_FCPIM_H__ */
diff --git a/drivers/scsi/bfa/include/fcb/bfa_fcb_port.h b/drivers/scsi/bfa/include/fcb/bfa_fcb_port.h
deleted file mode 100644
index 5fd7f986fa32..000000000000
--- a/drivers/scsi/bfa/include/fcb/bfa_fcb_port.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/**
- * bfa_fcb_port.h BFA FCS virtual port driver interfaces
- */
-
-#ifndef __BFA_FCB_PORT_H__
-#define __BFA_FCB_PORT_H__
-
-#include <fcb/bfa_fcb_vport.h>
-/**
- * fcs_port_fcb FCS port driver interfaces
- */
-
-/*
- * Forward declarations
- */
-struct bfad_port_s;
-
-/*
- * Callback functions from BFA FCS to driver
- */
-
-/**
- * Call from FCS to driver module when a port is instantiated. The port
- * can be a base port or a virtual port with in the base fabric or
- * a virtual fabric.
- *
- * On this callback, driver is supposed to create scsi_host, scsi_tgt or
- * network interfaces bases on ports personality/roles.
- *
- * base port of base fabric: vf_drv == NULL && vp_drv == NULL
- * vport of base fabric: vf_drv == NULL && vp_drv != NULL
- * base port of VF: vf_drv != NULL && vp_drv == NULL
- * vport of VF: vf_drv != NULL && vp_drv != NULL
- *
- * @param[in] bfad - driver instance
- * @param[in] port - FCS port instance
- * @param[in] roles - port roles: IM, TM, IP
- * @param[in] vf_drv - VF driver instance, NULL if base fabric (no VF)
- * @param[in] vp_drv - vport driver instance, NULL if base port
- *
- * @return None
- */
-struct bfad_port_s *bfa_fcb_port_new(struct bfad_s *bfad,
- struct bfa_fcs_port_s *port,
- enum bfa_port_role roles, struct bfad_vf_s *vf_drv,
- struct bfad_vport_s *vp_drv);
-
-/**
- * Call from FCS to driver module when a port is deleted. The port
- * can be a base port or a virtual port with in the base fabric or
- * a virtual fabric.
- *
- * @param[in] bfad - driver instance
- * @param[in] roles - port roles: IM, TM, IP
- * @param[in] vf_drv - VF driver instance, NULL if base fabric (no VF)
- * @param[in] vp_drv - vport driver instance, NULL if base port
- *
- * @return None
- */
-void bfa_fcb_port_delete(struct bfad_s *bfad, enum bfa_port_role roles,
- struct bfad_vf_s *vf_drv, struct bfad_vport_s *vp_drv);
-
-/**
- * Notification when port transitions to ONLINE state.
- *
- * Online notification is a logical link up for the local port. This
- * notification is sent after a successfull FLOGI, or a successful
- * link initialization in proviate-loop or N2N topologies.
- *
- * @param[in] bfad - driver instance
- * @param[in] roles - port roles: IM, TM, IP
- * @param[in] vf_drv - VF driver instance, NULL if base fabric (no VF)
- * @param[in] vp_drv - vport driver instance, NULL if base port
- *
- * @return None
- */
-void bfa_fcb_port_online(struct bfad_s *bfad, enum bfa_port_role roles,
- struct bfad_vf_s *vf_drv, struct bfad_vport_s *vp_drv);
-
-/**
- * Notification when port transitions to OFFLINE state.
- *
- * Offline notification is a logical link down for the local port.
- *
- * @param[in] bfad - driver instance
- * @param[in] roles - port roles: IM, TM, IP
- * @param[in] vf_drv - VF driver instance, NULL if base fabric (no VF)
- * @param[in] vp_drv - vport driver instance, NULL if base port
- *
- * @return None
- */
-void bfa_fcb_port_offline(struct bfad_s *bfad, enum bfa_port_role roles,
- struct bfad_vf_s *vf_drv, struct bfad_vport_s *vp_drv);
-
-
-#endif /* __BFA_FCB_PORT_H__ */
diff --git a/drivers/scsi/bfa/include/fcb/bfa_fcb_rport.h b/drivers/scsi/bfa/include/fcb/bfa_fcb_rport.h
deleted file mode 100644
index e0261bb6d1c1..000000000000
--- a/drivers/scsi/bfa/include/fcb/bfa_fcb_rport.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/**
- * bfa_fcb_rport.h BFA FCS rport driver interfaces
- */
-
-#ifndef __BFA_FCB_RPORT_H__
-#define __BFA_FCB_RPORT_H__
-
-/**
- * fcs_rport_fcb Remote port driver interfaces
- */
-
-
-struct bfad_rport_s;
-
-/*
- * Callback functions from BFA FCS to driver
- */
-
-/**
- * Completion callback for bfa_fcs_rport_add().
- *
- * @param[in] rport_drv - driver instance of rport
- *
- * @return None
- */
-void bfa_fcb_rport_add(struct bfad_rport_s *rport_drv);
-
-/**
- * Completion callback for bfa_fcs_rport_remove().
- *
- * @param[in] rport_drv - driver instance of rport
- *
- * @return None
- */
-void bfa_fcb_rport_remove(struct bfad_rport_s *rport_drv);
-
-/**
- * Call to allocate a rport instance.
- *
- * @param[in] bfad - driver instance
- * @param[out] rport - BFA FCS instance of rport
- * @param[out] rport_drv - driver instance of rport
- *
- * @retval BFA_STATUS_OK - successfully allocated
- * @retval BFA_STATUS_ENOMEM - cannot allocate
- */
-bfa_status_t bfa_fcb_rport_alloc(struct bfad_s *bfad,
- struct bfa_fcs_rport_s **rport,
- struct bfad_rport_s **rport_drv);
-
-/**
- * Call to free rport memory resources.
- *
- * @param[in] bfad - driver instance
- * @param[in] rport_drv - driver instance of rport
- *
- * @return None
- */
-void bfa_fcb_rport_free(struct bfad_s *bfad, struct bfad_rport_s **rport_drv);
-
-
-
-#endif /* __BFA_FCB_RPORT_H__ */
diff --git a/drivers/scsi/bfa/include/fcb/bfa_fcb_vf.h b/drivers/scsi/bfa/include/fcb/bfa_fcb_vf.h
deleted file mode 100644
index cfd3fac0a4e2..000000000000
--- a/drivers/scsi/bfa/include/fcb/bfa_fcb_vf.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/**
- * bfa_fcb_vf.h BFA FCS virtual fabric driver interfaces
- */
-
-#ifndef __BFA_FCB_VF_H__
-#define __BFA_FCB_VF_H__
-
-/**
- * fcs_vf_fcb Virtual fabric driver intrefaces
- */
-
-
-struct bfad_vf_s;
-
-/*
- * Callback functions from BFA FCS to driver
- */
-
-/**
- * Completion callback for bfa_fcs_vf_stop().
- *
- * @param[in] vf_drv - driver instance of vf
- *
- * @return None
- */
-void bfa_fcb_vf_stop(struct bfad_vf_s *vf_drv);
-
-
-
-#endif /* __BFA_FCB_VF_H__ */
diff --git a/drivers/scsi/bfa/include/fcb/bfa_fcb_vport.h b/drivers/scsi/bfa/include/fcb/bfa_fcb_vport.h
deleted file mode 100644
index cfd6ba7c47ec..000000000000
--- a/drivers/scsi/bfa/include/fcb/bfa_fcb_vport.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/**
- * bfa_fcb_vport.h BFA FCS virtual port driver interfaces
- */
-
-#ifndef __BFA_FCB_VPORT_H__
-#define __BFA_FCB_VPORT_H__
-
-/**
- * fcs_vport_fcb Virtual port driver interfaces
- */
-
-
-struct bfad_vport_s;
-
-/*
- * Callback functions from BFA FCS to driver
- */
-
-/**
- * Completion callback for bfa_fcs_vport_delete().
- *
- * @param[in] vport_drv - driver instance of vport
- *
- * @return None
- */
-void bfa_fcb_vport_delete(struct bfad_vport_s *vport_drv);
-void bfa_fcb_pbc_vport_create(struct bfad_s *bfad, struct bfi_pbc_vport_s);
-
-
-
-#endif /* __BFA_FCB_VPORT_H__ */
diff --git a/drivers/scsi/bfa/include/fcs/bfa_fcs.h b/drivers/scsi/bfa/include/fcs/bfa_fcs.h
deleted file mode 100644
index 54e5b81ab2a3..000000000000
--- a/drivers/scsi/bfa/include/fcs/bfa_fcs.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_FCS_H__
-#define __BFA_FCS_H__
-
-#include <cs/bfa_debug.h>
-#include <defs/bfa_defs_status.h>
-#include <defs/bfa_defs_version.h>
-#include <bfa.h>
-#include <fcs/bfa_fcs_fabric.h>
-
-#define BFA_FCS_OS_STR_LEN 64
-
-struct bfa_fcs_stats_s {
- struct {
- u32 untagged; /* untagged receive frames */
- u32 tagged; /* tagged receive frames */
- u32 vfid_unknown; /* VF id is unknown */
- } uf;
-};
-
-struct bfa_fcs_driver_info_s {
- u8 version[BFA_VERSION_LEN]; /* Driver Version */
- u8 host_machine_name[BFA_FCS_OS_STR_LEN];
- u8 host_os_name[BFA_FCS_OS_STR_LEN]; /* OS name and version */
- u8 host_os_patch[BFA_FCS_OS_STR_LEN];/* patch or service pack */
- u8 os_device_name[BFA_FCS_OS_STR_LEN]; /* Driver Device Name */
-};
-
-struct bfa_fcs_s {
- struct bfa_s *bfa; /* corresponding BFA bfa instance */
- struct bfad_s *bfad; /* corresponding BDA driver instance */
- struct bfa_log_mod_s *logm; /* driver logging module instance */
- struct bfa_trc_mod_s *trcmod; /* tracing module */
- struct bfa_aen_s *aen; /* aen component */
- bfa_boolean_t vf_enabled; /* VF mode is enabled */
- bfa_boolean_t fdmi_enabled; /*!< FDMI is enabled */
- bfa_boolean_t min_cfg; /* min cfg enabled/disabled */
- u16 port_vfid; /* port default VF ID */
- struct bfa_fcs_driver_info_s driver_info;
- struct bfa_fcs_fabric_s fabric; /* base fabric state machine */
- struct bfa_fcs_stats_s stats; /* FCS statistics */
- struct bfa_wc_s wc; /* waiting counter */
-};
-
-/*
- * bfa fcs API functions
- */
-void bfa_fcs_attach(struct bfa_fcs_s *fcs, struct bfa_s *bfa,
- struct bfad_s *bfad, bfa_boolean_t min_cfg);
-void bfa_fcs_init(struct bfa_fcs_s *fcs);
-void bfa_fcs_driver_info_init(struct bfa_fcs_s *fcs,
- struct bfa_fcs_driver_info_s *driver_info);
-void bfa_fcs_set_fdmi_param(struct bfa_fcs_s *fcs, bfa_boolean_t fdmi_enable);
-void bfa_fcs_exit(struct bfa_fcs_s *fcs);
-void bfa_fcs_trc_init(struct bfa_fcs_s *fcs, struct bfa_trc_mod_s *trcmod);
-void bfa_fcs_log_init(struct bfa_fcs_s *fcs, struct bfa_log_mod_s *logmod);
-void bfa_fcs_aen_init(struct bfa_fcs_s *fcs, struct bfa_aen_s *aen);
-void bfa_fcs_start(struct bfa_fcs_s *fcs);
-
-#endif /* __BFA_FCS_H__ */
diff --git a/drivers/scsi/bfa/include/fcs/bfa_fcs_auth.h b/drivers/scsi/bfa/include/fcs/bfa_fcs_auth.h
deleted file mode 100644
index 28c4c9ff08b3..000000000000
--- a/drivers/scsi/bfa/include/fcs/bfa_fcs_auth.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_FCS_AUTH_H__
-#define __BFA_FCS_AUTH_H__
-
-struct bfa_fcs_s;
-
-#include <defs/bfa_defs_status.h>
-#include <defs/bfa_defs_auth.h>
-#include <defs/bfa_defs_vf.h>
-#include <cs/bfa_q.h>
-#include <cs/bfa_sm.h>
-#include <defs/bfa_defs_pport.h>
-#include <fcs/bfa_fcs_lport.h>
-#include <protocol/fc_sp.h>
-
-struct bfa_fcs_fabric_s;
-
-
-
-struct bfa_fcs_auth_s {
- bfa_sm_t sm; /* state machine */
- bfa_boolean_t policy; /* authentication enabled/disabled */
- enum bfa_auth_status status; /* authentication status */
- enum auth_rjt_codes rjt_code; /* auth reject status */
- enum auth_rjt_code_exps rjt_code_exp; /* auth reject reason */
- enum bfa_auth_algo algo; /* Authentication algorithm */
- struct bfa_auth_stats_s stats; /* Statistics */
- enum auth_dh_gid group; /* DH(diffie-hellman) Group */
- enum bfa_auth_secretsource source; /* Secret source */
- char secret[BFA_AUTH_SECRET_STRING_LEN];
- /* secret string */
- u8 secret_len;
- /* secret string length */
- u8 nretries;
- /* number of retries */
- struct bfa_fcs_fabric_s *fabric;/* pointer to fabric */
- u8 sentcode; /* pointer to response data */
- u8 *response; /* pointer to response data */
- struct bfa_timer_s delay_timer; /* delay timer */
- struct bfa_fcxp_s *fcxp; /* pointer to fcxp */
- struct bfa_fcxp_wqe_s fcxp_wqe;
-};
-
-/**
- * bfa fcs authentication public functions
- */
-bfa_status_t bfa_fcs_auth_get_attr(struct bfa_fcs_s *port,
- struct bfa_auth_attr_s *attr);
-bfa_status_t bfa_fcs_auth_set_policy(struct bfa_fcs_s *port,
- bfa_boolean_t policy);
-enum bfa_auth_status bfa_fcs_auth_get_status(struct bfa_fcs_s *port);
-bfa_status_t bfa_fcs_auth_set_algo(struct bfa_fcs_s *port,
- enum bfa_auth_algo algo);
-bfa_status_t bfa_fcs_auth_get_stats(struct bfa_fcs_s *port,
- struct bfa_auth_stats_s *stats);
-bfa_status_t bfa_fcs_auth_set_dh_group(struct bfa_fcs_s *port, int group);
-bfa_status_t bfa_fcs_auth_set_secretstring(struct bfa_fcs_s *port,
- char *secret);
-bfa_status_t bfa_fcs_auth_set_secretstring_encrypt(struct bfa_fcs_s *port,
- u32 secret[], u32 len);
-bfa_status_t bfa_fcs_auth_set_secretsource(struct bfa_fcs_s *port,
- enum bfa_auth_secretsource src);
-bfa_status_t bfa_fcs_auth_reset_stats(struct bfa_fcs_s *port);
-bfa_status_t bfa_fcs_auth_reinit(struct bfa_fcs_s *port);
-
-#endif /* __BFA_FCS_AUTH_H__ */
diff --git a/drivers/scsi/bfa/include/fcs/bfa_fcs_fabric.h b/drivers/scsi/bfa/include/fcs/bfa_fcs_fabric.h
deleted file mode 100644
index 08b79d5e46f3..000000000000
--- a/drivers/scsi/bfa/include/fcs/bfa_fcs_fabric.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_FCS_FABRIC_H__
-#define __BFA_FCS_FABRIC_H__
-
-struct bfa_fcs_s;
-
-#include <defs/bfa_defs_status.h>
-#include <defs/bfa_defs_vf.h>
-#include <cs/bfa_q.h>
-#include <cs/bfa_sm.h>
-#include <defs/bfa_defs_pport.h>
-#include <fcs/bfa_fcs_lport.h>
-#include <protocol/fc_sp.h>
-#include <fcs/bfa_fcs_auth.h>
-
-/*
- * forward declaration
- */
-struct bfad_vf_s;
-
-enum bfa_fcs_fabric_type {
- BFA_FCS_FABRIC_UNKNOWN = 0,
- BFA_FCS_FABRIC_SWITCHED = 1,
- BFA_FCS_FABRIC_PLOOP = 2,
- BFA_FCS_FABRIC_N2N = 3,
-};
-
-
-struct bfa_fcs_fabric_s {
- struct list_head qe; /* queue element */
- bfa_sm_t sm; /* state machine */
- struct bfa_fcs_s *fcs; /* FCS instance */
- struct bfa_fcs_port_s bport; /* base logical port */
- enum bfa_fcs_fabric_type fab_type; /* fabric type */
- enum bfa_pport_type oper_type; /* current link topology */
- u8 is_vf; /* is virtual fabric? */
- u8 is_npiv; /* is NPIV supported ? */
- u8 is_auth; /* is Security/Auth supported ? */
- u16 bb_credit; /* BB credit from fabric */
- u16 vf_id; /* virtual fabric ID */
- u16 num_vports; /* num vports */
- u16 rsvd;
- struct list_head vport_q; /* queue of virtual ports */
- struct list_head vf_q; /* queue of virtual fabrics */
- struct bfad_vf_s *vf_drv; /* driver vf structure */
- struct bfa_timer_s link_timer; /* Link Failure timer. Vport */
- wwn_t fabric_name; /* attached fabric name */
- bfa_boolean_t auth_reqd; /* authentication required */
- struct bfa_timer_s delay_timer; /* delay timer */
- union {
- u16 swp_vfid;/* switch port VF id */
- } event_arg;
- struct bfa_fcs_auth_s auth; /* authentication config */
- struct bfa_wc_s wc; /* wait counter for delete */
- struct bfa_vf_stats_s stats; /* fabric/vf stats */
- struct bfa_lps_s *lps; /* lport login services */
- u8 fabric_ip_addr[BFA_FCS_FABRIC_IPADDR_SZ]; /* attached
- * fabric's ip addr
- */
-};
-
-#define bfa_fcs_fabric_npiv_capable(__f) ((__f)->is_npiv)
-#define bfa_fcs_fabric_is_switched(__f) \
- ((__f)->fab_type == BFA_FCS_FABRIC_SWITCHED)
-
-/**
- * The design calls for a single implementation of base fabric and vf.
- */
-#define bfa_fcs_vf_t struct bfa_fcs_fabric_s
-
-struct bfa_vf_event_s {
- u32 undefined;
-};
-
-/**
- * bfa fcs vf public functions
- */
-bfa_status_t bfa_fcs_vf_mode_enable(struct bfa_fcs_s *fcs, u16 vf_id);
-bfa_status_t bfa_fcs_vf_mode_disable(struct bfa_fcs_s *fcs);
-bfa_status_t bfa_fcs_vf_create(bfa_fcs_vf_t *vf, struct bfa_fcs_s *fcs,
- u16 vf_id, struct bfa_port_cfg_s *port_cfg,
- struct bfad_vf_s *vf_drv);
-bfa_status_t bfa_fcs_vf_delete(bfa_fcs_vf_t *vf);
-void bfa_fcs_vf_start(bfa_fcs_vf_t *vf);
-bfa_status_t bfa_fcs_vf_stop(bfa_fcs_vf_t *vf);
-void bfa_fcs_vf_list(struct bfa_fcs_s *fcs, u16 *vf_ids, int *nvfs);
-void bfa_fcs_vf_list_all(struct bfa_fcs_s *fcs, u16 *vf_ids, int *nvfs);
-void bfa_fcs_vf_get_attr(bfa_fcs_vf_t *vf, struct bfa_vf_attr_s *vf_attr);
-void bfa_fcs_vf_get_stats(bfa_fcs_vf_t *vf,
- struct bfa_vf_stats_s *vf_stats);
-void bfa_fcs_vf_clear_stats(bfa_fcs_vf_t *vf);
-void bfa_fcs_vf_get_ports(bfa_fcs_vf_t *vf, wwn_t vpwwn[], int *nports);
-bfa_fcs_vf_t *bfa_fcs_vf_lookup(struct bfa_fcs_s *fcs, u16 vf_id);
-struct bfad_vf_s *bfa_fcs_vf_get_drv_vf(bfa_fcs_vf_t *vf);
-
-#endif /* __BFA_FCS_FABRIC_H__ */
diff --git a/drivers/scsi/bfa/include/fcs/bfa_fcs_fcpim.h b/drivers/scsi/bfa/include/fcs/bfa_fcs_fcpim.h
deleted file mode 100644
index 9a35ecf5cdf0..000000000000
--- a/drivers/scsi/bfa/include/fcs/bfa_fcs_fcpim.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/**
- * bfa_fcs_fcpim.h BFA FCS FCP Initiator Mode interfaces/defines.
- */
-
-#ifndef __BFA_FCS_FCPIM_H__
-#define __BFA_FCS_FCPIM_H__
-
-#include <defs/bfa_defs_status.h>
-#include <defs/bfa_defs_itnim.h>
-#include <fcs/bfa_fcs.h>
-#include <fcs/bfa_fcs_rport.h>
-#include <fcs/bfa_fcs_lport.h>
-#include <bfa_fcpim.h>
-
-/*
- * forward declarations
- */
-struct bfad_itnim_s;
-
-struct bfa_fcs_itnim_s {
- bfa_sm_t sm; /* state machine */
- struct bfa_fcs_rport_s *rport; /* parent remote rport */
- struct bfad_itnim_s *itnim_drv; /* driver peer instance */
- struct bfa_fcs_s *fcs; /* fcs instance */
- struct bfa_timer_s timer; /* timer functions */
- struct bfa_itnim_s *bfa_itnim; /* BFA itnim struct */
- u32 prli_retries; /* max prli retry attempts */
- bfa_boolean_t seq_rec; /* seq recovery support */
- bfa_boolean_t rec_support; /* REC supported */
- bfa_boolean_t conf_comp; /* FCP_CONF support */
- bfa_boolean_t task_retry_id; /* task retry id supp */
- struct bfa_fcxp_wqe_s fcxp_wqe; /* wait qelem for fcxp */
- struct bfa_fcxp_s *fcxp; /* FCXP in use */
- struct bfa_itnim_stats_s stats; /* itn statistics */
-};
-
-
-static inline struct bfad_port_s *
-bfa_fcs_itnim_get_drvport(struct bfa_fcs_itnim_s *itnim)
-{
- return itnim->rport->port->bfad_port;
-}
-
-
-static inline struct bfa_fcs_port_s *
-bfa_fcs_itnim_get_port(struct bfa_fcs_itnim_s *itnim)
-{
- return itnim->rport->port;
-}
-
-
-static inline wwn_t
-bfa_fcs_itnim_get_nwwn(struct bfa_fcs_itnim_s *itnim)
-{
- return itnim->rport->nwwn;
-}
-
-
-static inline wwn_t
-bfa_fcs_itnim_get_pwwn(struct bfa_fcs_itnim_s *itnim)
-{
- return itnim->rport->pwwn;
-}
-
-
-static inline u32
-bfa_fcs_itnim_get_fcid(struct bfa_fcs_itnim_s *itnim)
-{
- return itnim->rport->pid;
-}
-
-
-static inline u32
-bfa_fcs_itnim_get_maxfrsize(struct bfa_fcs_itnim_s *itnim)
-{
- return itnim->rport->maxfrsize;
-}
-
-
-static inline enum fc_cos
-bfa_fcs_itnim_get_cos(struct bfa_fcs_itnim_s *itnim)
-{
- return itnim->rport->fc_cos;
-}
-
-
-static inline struct bfad_itnim_s *
-bfa_fcs_itnim_get_drvitn(struct bfa_fcs_itnim_s *itnim)
-{
- return itnim->itnim_drv;
-}
-
-
-static inline struct bfa_itnim_s *
-bfa_fcs_itnim_get_halitn(struct bfa_fcs_itnim_s *itnim)
-{
- return itnim->bfa_itnim;
-}
-
-/**
- * bfa fcs FCP Initiator mode API functions
- */
-void bfa_fcs_itnim_get_attr(struct bfa_fcs_itnim_s *itnim,
- struct bfa_itnim_attr_s *attr);
-void bfa_fcs_itnim_get_stats(struct bfa_fcs_itnim_s *itnim,
- struct bfa_itnim_stats_s *stats);
-struct bfa_fcs_itnim_s *bfa_fcs_itnim_lookup(struct bfa_fcs_port_s *port,
- wwn_t rpwwn);
-bfa_status_t bfa_fcs_itnim_attr_get(struct bfa_fcs_port_s *port, wwn_t rpwwn,
- struct bfa_itnim_attr_s *attr);
-bfa_status_t bfa_fcs_itnim_stats_get(struct bfa_fcs_port_s *port, wwn_t rpwwn,
- struct bfa_itnim_stats_s *stats);
-bfa_status_t bfa_fcs_itnim_stats_clear(struct bfa_fcs_port_s *port,
- wwn_t rpwwn);
-#endif /* __BFA_FCS_FCPIM_H__ */
diff --git a/drivers/scsi/bfa/include/fcs/bfa_fcs_fdmi.h b/drivers/scsi/bfa/include/fcs/bfa_fcs_fdmi.h
deleted file mode 100644
index 4441fffc9c82..000000000000
--- a/drivers/scsi/bfa/include/fcs/bfa_fcs_fdmi.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/**
- * bfa_fcs_fdmi.h BFA fcs fdmi module public interface
- */
-
-#ifndef __BFA_FCS_FDMI_H__
-#define __BFA_FCS_FDMI_H__
-#include <bfa_os_inc.h>
-#include <protocol/fdmi.h>
-
-#define BFA_FCS_FDMI_SUPORTED_SPEEDS (FDMI_TRANS_SPEED_1G | \
- FDMI_TRANS_SPEED_2G | \
- FDMI_TRANS_SPEED_4G | \
- FDMI_TRANS_SPEED_8G)
-
-/*
-* HBA Attribute Block : BFA internal representation. Note : Some variable
-* sizes have been trimmed to suit BFA For Ex : Model will be "Brocade". Based
- * on this the size has been reduced to 16 bytes from the standard's 64 bytes.
- */
-struct bfa_fcs_fdmi_hba_attr_s {
- wwn_t node_name;
- u8 manufacturer[64];
- u8 serial_num[64];
- u8 model[16];
- u8 model_desc[256];
- u8 hw_version[8];
- u8 driver_version[8];
- u8 option_rom_ver[BFA_VERSION_LEN];
- u8 fw_version[8];
- u8 os_name[256];
- u32 max_ct_pyld;
-};
-
-/*
- * Port Attribute Block
- */
-struct bfa_fcs_fdmi_port_attr_s {
- u8 supp_fc4_types[32]; /* supported FC4 types */
- u32 supp_speed; /* supported speed */
- u32 curr_speed; /* current Speed */
- u32 max_frm_size; /* max frame size */
- u8 os_device_name[256]; /* OS device Name */
- u8 host_name[256]; /* host name */
-};
-
-#endif /* __BFA_FCS_FDMI_H__ */
diff --git a/drivers/scsi/bfa/include/fcs/bfa_fcs_lport.h b/drivers/scsi/bfa/include/fcs/bfa_fcs_lport.h
deleted file mode 100644
index ceaefd3060f4..000000000000
--- a/drivers/scsi/bfa/include/fcs/bfa_fcs_lport.h
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/**
- * bfa_fcs_port.h BFA fcs port module public interface
- */
-
-#ifndef __BFA_FCS_PORT_H__
-#define __BFA_FCS_PORT_H__
-
-#include <defs/bfa_defs_status.h>
-#include <defs/bfa_defs_port.h>
-#include <defs/bfa_defs_pport.h>
-#include <defs/bfa_defs_rport.h>
-#include <cs/bfa_q.h>
-#include <bfa_svc.h>
-#include <cs/bfa_wc.h>
-
-struct bfa_fcs_s;
-struct bfa_fcs_fabric_s;
-
-/*
- * Maximum Rports supported per port (physical/logical).
- */
-#define BFA_FCS_MAX_RPORTS_SUPP 256 /* @todo : tentative value */
-
-
-struct bfa_fcs_port_ns_s {
- bfa_sm_t sm; /* state machine */
- struct bfa_timer_s timer;
- struct bfa_fcs_port_s *port; /* parent port */
- struct bfa_fcxp_s *fcxp;
- struct bfa_fcxp_wqe_s fcxp_wqe;
-};
-
-
-struct bfa_fcs_port_scn_s {
- bfa_sm_t sm; /* state machine */
- struct bfa_timer_s timer;
- struct bfa_fcs_port_s *port; /* parent port */
- struct bfa_fcxp_s *fcxp;
- struct bfa_fcxp_wqe_s fcxp_wqe;
-};
-
-
-struct bfa_fcs_port_fdmi_s {
- bfa_sm_t sm; /* state machine */
- struct bfa_timer_s timer;
- struct bfa_fcs_port_ms_s *ms; /* parent ms */
- struct bfa_fcxp_s *fcxp;
- struct bfa_fcxp_wqe_s fcxp_wqe;
- u8 retry_cnt; /* retry count */
- u8 rsvd[3];
-};
-
-
-struct bfa_fcs_port_ms_s {
- bfa_sm_t sm; /* state machine */
- struct bfa_timer_s timer;
- struct bfa_fcs_port_s *port; /* parent port */
- struct bfa_fcxp_s *fcxp;
- struct bfa_fcxp_wqe_s fcxp_wqe;
- struct bfa_fcs_port_fdmi_s fdmi; /* FDMI component of MS */
- u8 retry_cnt; /* retry count */
- u8 rsvd[3];
-};
-
-
-struct bfa_fcs_port_fab_s {
- struct bfa_fcs_port_ns_s ns; /* NS component of port */
- struct bfa_fcs_port_scn_s scn; /* scn component of port */
- struct bfa_fcs_port_ms_s ms; /* MS component of port */
-};
-
-
-
-#define MAX_ALPA_COUNT 127
-
-struct bfa_fcs_port_loop_s {
- u8 num_alpa; /* Num of ALPA entries in the map */
- u8 alpa_pos_map[MAX_ALPA_COUNT]; /* ALPA Positional
- *Map */
- struct bfa_fcs_port_s *port; /* parent port */
-};
-
-
-
-struct bfa_fcs_port_n2n_s {
- u32 rsvd;
- u16 reply_oxid; /* ox_id from the req flogi to be
- *used in flogi acc */
- wwn_t rem_port_wwn; /* Attached port's wwn */
-};
-
-
-union bfa_fcs_port_topo_u {
- struct bfa_fcs_port_fab_s pfab;
- struct bfa_fcs_port_loop_s ploop;
- struct bfa_fcs_port_n2n_s pn2n;
-};
-
-
-struct bfa_fcs_port_s {
- struct list_head qe; /* used by port/vport */
- bfa_sm_t sm; /* state machine */
- struct bfa_fcs_fabric_s *fabric;/* parent fabric */
- struct bfa_port_cfg_s port_cfg;/* port configuration */
- struct bfa_timer_s link_timer; /* timer for link offline */
- u32 pid:24; /* FC address */
- u8 lp_tag; /* lport tag */
- u16 num_rports; /* Num of r-ports */
- struct list_head rport_q; /* queue of discovered r-ports */
- struct bfa_fcs_s *fcs; /* FCS instance */
- union bfa_fcs_port_topo_u port_topo; /* fabric/loop/n2n details */
- struct bfad_port_s *bfad_port; /* driver peer instance */
- struct bfa_fcs_vport_s *vport; /* NULL for base ports */
- struct bfa_fcxp_s *fcxp;
- struct bfa_fcxp_wqe_s fcxp_wqe;
- struct bfa_port_stats_s stats;
- struct bfa_wc_s wc; /* waiting counter for events */
-};
-
-#define bfa_fcs_lport_t struct bfa_fcs_port_s
-
-/**
- * Symbolic Name related defines
- * Total bytes 255.
- * Physical Port's symbolic name 128 bytes.
- * For Vports, Vport's symbolic name is appended to the Physical port's
- * Symbolic Name.
- *
- * Physical Port's symbolic name Format : (Total 128 bytes)
- * Adapter Model number/name : 12 bytes
- * Driver Version : 10 bytes
- * Host Machine Name : 30 bytes
- * Host OS Info : 48 bytes
- * Host OS PATCH Info : 16 bytes
- * ( remaining 12 bytes reserved to be used for separator)
- */
-#define BFA_FCS_PORT_SYMBNAME_SEPARATOR " | "
-
-#define BFA_FCS_PORT_SYMBNAME_MODEL_SZ 12
-#define BFA_FCS_PORT_SYMBNAME_VERSION_SZ 10
-#define BFA_FCS_PORT_SYMBNAME_MACHINENAME_SZ 30
-#define BFA_FCS_PORT_SYMBNAME_OSINFO_SZ 48
-#define BFA_FCS_PORT_SYMBNAME_OSPATCH_SZ 16
-
-/**
- * Get FC port ID for a logical port.
- */
-#define bfa_fcs_port_get_fcid(_lport) ((_lport)->pid)
-#define bfa_fcs_port_get_pwwn(_lport) ((_lport)->port_cfg.pwwn)
-#define bfa_fcs_port_get_nwwn(_lport) ((_lport)->port_cfg.nwwn)
-#define bfa_fcs_port_get_psym_name(_lport) ((_lport)->port_cfg.sym_name)
-#define bfa_fcs_port_is_initiator(_lport) \
- ((_lport)->port_cfg.roles & BFA_PORT_ROLE_FCP_IM)
-#define bfa_fcs_port_is_target(_lport) \
- ((_lport)->port_cfg.roles & BFA_PORT_ROLE_FCP_TM)
-#define bfa_fcs_port_get_nrports(_lport) \
- ((_lport) ? (_lport)->num_rports : 0)
-
-static inline struct bfad_port_s *
-bfa_fcs_port_get_drvport(struct bfa_fcs_port_s *port)
-{
- return port->bfad_port;
-}
-
-
-#define bfa_fcs_port_get_opertype(_lport) ((_lport)->fabric->oper_type)
-
-
-#define bfa_fcs_port_get_fabric_name(_lport) ((_lport)->fabric->fabric_name)
-
-
-#define bfa_fcs_port_get_fabric_ipaddr(_lport) \
- ((_lport)->fabric->fabric_ip_addr)
-
-/**
- * bfa fcs port public functions
- */
-void bfa_fcs_cfg_base_port(struct bfa_fcs_s *fcs,
- struct bfa_port_cfg_s *port_cfg);
-struct bfa_fcs_port_s *bfa_fcs_get_base_port(struct bfa_fcs_s *fcs);
-void bfa_fcs_port_get_rports(struct bfa_fcs_port_s *port,
- wwn_t rport_wwns[], int *nrports);
-
-wwn_t bfa_fcs_port_get_rport(struct bfa_fcs_port_s *port, wwn_t wwn,
- int index, int nrports, bfa_boolean_t bwwn);
-
-struct bfa_fcs_port_s *bfa_fcs_lookup_port(struct bfa_fcs_s *fcs,
- u16 vf_id, wwn_t lpwwn);
-
-void bfa_fcs_port_get_info(struct bfa_fcs_port_s *port,
- struct bfa_port_info_s *port_info);
-void bfa_fcs_port_get_attr(struct bfa_fcs_port_s *port,
- struct bfa_port_attr_s *port_attr);
-void bfa_fcs_port_get_stats(struct bfa_fcs_port_s *fcs_port,
- struct bfa_port_stats_s *port_stats);
-void bfa_fcs_port_clear_stats(struct bfa_fcs_port_s *fcs_port);
-enum bfa_pport_speed bfa_fcs_port_get_rport_max_speed(
- struct bfa_fcs_port_s *port);
-void bfa_fcs_port_enable_ipfc_roles(struct bfa_fcs_port_s *fcs_port);
-void bfa_fcs_port_disable_ipfc_roles(struct bfa_fcs_port_s *fcs_port);
-
-#endif /* __BFA_FCS_PORT_H__ */
diff --git a/drivers/scsi/bfa/include/fcs/bfa_fcs_rport.h b/drivers/scsi/bfa/include/fcs/bfa_fcs_rport.h
deleted file mode 100644
index 3027fc6c7722..000000000000
--- a/drivers/scsi/bfa/include/fcs/bfa_fcs_rport.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __BFA_FCS_RPORT_H__
-#define __BFA_FCS_RPORT_H__
-
-#include <defs/bfa_defs_status.h>
-#include <cs/bfa_q.h>
-#include <fcs/bfa_fcs.h>
-#include <defs/bfa_defs_rport.h>
-
-#define BFA_FCS_RPORT_DEF_DEL_TIMEOUT 90 /* in secs */
-/*
- * forward declarations
- */
-struct bfad_rport_s;
-
-struct bfa_fcs_itnim_s;
-struct bfa_fcs_tin_s;
-struct bfa_fcs_iprp_s;
-
-/* Rport Features (RPF) */
-struct bfa_fcs_rpf_s {
- bfa_sm_t sm; /* state machine */
- struct bfa_fcs_rport_s *rport; /* parent rport */
- struct bfa_timer_s timer; /* general purpose timer */
- struct bfa_fcxp_s *fcxp; /* FCXP needed for discarding */
- struct bfa_fcxp_wqe_s fcxp_wqe; /* fcxp wait queue element */
- int rpsc_retries; /* max RPSC retry attempts */
- enum bfa_pport_speed rpsc_speed; /* Current Speed from RPSC.
- * O if RPSC fails */
- enum bfa_pport_speed assigned_speed; /* Speed assigned by the user.
- * will be used if RPSC is not
- * supported by the rport */
-};
-
-struct bfa_fcs_rport_s {
- struct list_head qe; /* used by port/vport */
- struct bfa_fcs_port_s *port; /* parent FCS port */
- struct bfa_fcs_s *fcs; /* fcs instance */
- struct bfad_rport_s *rp_drv; /* driver peer instance */
- u32 pid; /* port ID of rport */
- u16 maxfrsize; /* maximum frame size */
- u16 reply_oxid; /* OX_ID of inbound requests */
- enum fc_cos fc_cos; /* FC classes of service supp */
- bfa_boolean_t cisc; /* CISC capable device */
- bfa_boolean_t prlo; /* processing prlo or LOGO */
- wwn_t pwwn; /* port wwn of rport */
- wwn_t nwwn; /* node wwn of rport */
- struct bfa_rport_symname_s psym_name; /* port symbolic name */
- bfa_sm_t sm; /* state machine */
- struct bfa_timer_s timer; /* general purpose timer */
- struct bfa_fcs_itnim_s *itnim; /* ITN initiator mode role */
- struct bfa_fcs_tin_s *tin; /* ITN initiator mode role */
- struct bfa_fcs_iprp_s *iprp; /* IP/FC role */
- struct bfa_rport_s *bfa_rport; /* BFA Rport */
- struct bfa_fcxp_s *fcxp; /* FCXP needed for discarding */
- int plogi_retries; /* max plogi retry attempts */
- int ns_retries; /* max NS query retry attempts */
- struct bfa_fcxp_wqe_s fcxp_wqe; /* fcxp wait queue element */
- struct bfa_rport_stats_s stats; /* rport stats */
- enum bfa_rport_function scsi_function; /* Initiator/Target */
- struct bfa_fcs_rpf_s rpf; /* Rport features module */
-};
-
-static inline struct bfa_rport_s *
-bfa_fcs_rport_get_halrport(struct bfa_fcs_rport_s *rport)
-{
- return rport->bfa_rport;
-}
-
-/**
- * bfa fcs rport API functions
- */
-bfa_status_t bfa_fcs_rport_add(struct bfa_fcs_port_s *port, wwn_t *pwwn,
- struct bfa_fcs_rport_s *rport,
- struct bfad_rport_s *rport_drv);
-bfa_status_t bfa_fcs_rport_remove(struct bfa_fcs_rport_s *rport);
-void bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport,
- struct bfa_rport_attr_s *attr);
-void bfa_fcs_rport_get_stats(struct bfa_fcs_rport_s *rport,
- struct bfa_rport_stats_s *stats);
-void bfa_fcs_rport_clear_stats(struct bfa_fcs_rport_s *rport);
-struct bfa_fcs_rport_s *bfa_fcs_rport_lookup(struct bfa_fcs_port_s *port,
- wwn_t rpwwn);
-struct bfa_fcs_rport_s *bfa_fcs_rport_lookup_by_nwwn(
- struct bfa_fcs_port_s *port, wwn_t rnwwn);
-void bfa_fcs_rport_set_del_timeout(u8 rport_tmo);
-void bfa_fcs_rport_set_speed(struct bfa_fcs_rport_s *rport,
- enum bfa_pport_speed speed);
-#endif /* __BFA_FCS_RPORT_H__ */
diff --git a/drivers/scsi/bfa/include/fcs/bfa_fcs_vport.h b/drivers/scsi/bfa/include/fcs/bfa_fcs_vport.h
deleted file mode 100644
index 0af262430860..000000000000
--- a/drivers/scsi/bfa/include/fcs/bfa_fcs_vport.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/**
- * bfa_fcs_vport.h BFA fcs vport module public interface
- */
-
-#ifndef __BFA_FCS_VPORT_H__
-#define __BFA_FCS_VPORT_H__
-
-#include <defs/bfa_defs_status.h>
-#include <defs/bfa_defs_port.h>
-#include <defs/bfa_defs_vport.h>
-#include <fcs/bfa_fcs.h>
-#include <fcb/bfa_fcb_vport.h>
-
-struct bfa_fcs_vport_s {
- struct list_head qe; /* queue elem */
- bfa_sm_t sm; /* state machine */
- bfa_fcs_lport_t lport; /* logical port */
- struct bfa_timer_s timer; /* general purpose timer */
- struct bfad_vport_s *vport_drv; /* Driver private */
- struct bfa_vport_stats_s vport_stats; /* vport statistics */
- struct bfa_lps_s *lps; /* Lport login service */
- int fdisc_retries;
-};
-
-#define bfa_fcs_vport_get_port(vport) \
- ((struct bfa_fcs_port_s *)(&vport->port))
-
-/**
- * bfa fcs vport public functions
- */
-bfa_status_t bfa_fcs_vport_create(struct bfa_fcs_vport_s *vport,
- struct bfa_fcs_s *fcs, u16 vf_id,
- struct bfa_port_cfg_s *port_cfg,
- struct bfad_vport_s *vport_drv);
-bfa_status_t bfa_fcs_pbc_vport_create(struct bfa_fcs_vport_s *vport,
- struct bfa_fcs_s *fcs, uint16_t vf_id,
- struct bfa_port_cfg_s *port_cfg,
- struct bfad_vport_s *vport_drv);
-bfa_status_t bfa_fcs_vport_delete(struct bfa_fcs_vport_s *vport);
-bfa_status_t bfa_fcs_vport_start(struct bfa_fcs_vport_s *vport);
-bfa_status_t bfa_fcs_vport_stop(struct bfa_fcs_vport_s *vport);
-void bfa_fcs_vport_get_attr(struct bfa_fcs_vport_s *vport,
- struct bfa_vport_attr_s *vport_attr);
-void bfa_fcs_vport_get_stats(struct bfa_fcs_vport_s *vport,
- struct bfa_vport_stats_s *vport_stats);
-void bfa_fcs_vport_clr_stats(struct bfa_fcs_vport_s *vport);
-struct bfa_fcs_vport_s *bfa_fcs_vport_lookup(struct bfa_fcs_s *fcs,
- u16 vf_id, wwn_t vpwwn);
-
-#endif /* __BFA_FCS_VPORT_H__ */
diff --git a/drivers/scsi/bfa/include/log/bfa_log_fcs.h b/drivers/scsi/bfa/include/log/bfa_log_fcs.h
deleted file mode 100644
index b6f5df8827f8..000000000000
--- a/drivers/scsi/bfa/include/log/bfa_log_fcs.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/*
- * messages define for FCS Module
- */
-#ifndef __BFA_LOG_FCS_H__
-#define __BFA_LOG_FCS_H__
-#include <cs/bfa_log.h>
-#define BFA_LOG_FCS_FABRIC_NOSWITCH \
- (((u32) BFA_LOG_FCS_ID << BFA_LOG_MODID_OFFSET) | 1)
-#define BFA_LOG_FCS_FABRIC_ISOLATED \
- (((u32) BFA_LOG_FCS_ID << BFA_LOG_MODID_OFFSET) | 2)
-#endif
diff --git a/drivers/scsi/bfa/include/log/bfa_log_hal.h b/drivers/scsi/bfa/include/log/bfa_log_hal.h
deleted file mode 100644
index 5f8f5e30b9e8..000000000000
--- a/drivers/scsi/bfa/include/log/bfa_log_hal.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/* messages define for HAL Module */
-#ifndef __BFA_LOG_HAL_H__
-#define __BFA_LOG_HAL_H__
-#include <cs/bfa_log.h>
-#define BFA_LOG_HAL_ASSERT \
- (((u32) BFA_LOG_HAL_ID << BFA_LOG_MODID_OFFSET) | 1)
-#define BFA_LOG_HAL_HEARTBEAT_FAILURE \
- (((u32) BFA_LOG_HAL_ID << BFA_LOG_MODID_OFFSET) | 2)
-#define BFA_LOG_HAL_FCPIM_PARM_INVALID \
- (((u32) BFA_LOG_HAL_ID << BFA_LOG_MODID_OFFSET) | 3)
-#define BFA_LOG_HAL_SM_ASSERT \
- (((u32) BFA_LOG_HAL_ID << BFA_LOG_MODID_OFFSET) | 4)
-#define BFA_LOG_HAL_DRIVER_ERROR \
- (((u32) BFA_LOG_HAL_ID << BFA_LOG_MODID_OFFSET) | 5)
-#define BFA_LOG_HAL_DRIVER_CONFIG_ERROR \
- (((u32) BFA_LOG_HAL_ID << BFA_LOG_MODID_OFFSET) | 6)
-#define BFA_LOG_HAL_MBOX_ERROR \
- (((u32) BFA_LOG_HAL_ID << BFA_LOG_MODID_OFFSET) | 7)
-#endif
diff --git a/drivers/scsi/bfa/include/log/bfa_log_linux.h b/drivers/scsi/bfa/include/log/bfa_log_linux.h
deleted file mode 100644
index 44bc89768bda..000000000000
--- a/drivers/scsi/bfa/include/log/bfa_log_linux.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/* messages define for LINUX Module */
-#ifndef __BFA_LOG_LINUX_H__
-#define __BFA_LOG_LINUX_H__
-#include <cs/bfa_log.h>
-#define BFA_LOG_LINUX_DEVICE_CLAIMED \
- (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 1)
-#define BFA_LOG_LINUX_HASH_INIT_FAILED \
- (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 2)
-#define BFA_LOG_LINUX_SYSFS_FAILED \
- (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 3)
-#define BFA_LOG_LINUX_MEM_ALLOC_FAILED \
- (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 4)
-#define BFA_LOG_LINUX_DRIVER_REGISTRATION_FAILED \
- (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 5)
-#define BFA_LOG_LINUX_ITNIM_FREE \
- (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 6)
-#define BFA_LOG_LINUX_ITNIM_ONLINE \
- (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 7)
-#define BFA_LOG_LINUX_ITNIM_OFFLINE \
- (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 8)
-#define BFA_LOG_LINUX_SCSI_HOST_FREE \
- (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 9)
-#define BFA_LOG_LINUX_SCSI_ABORT \
- (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 10)
-#define BFA_LOG_LINUX_SCSI_ABORT_COMP \
- (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 11)
-#define BFA_LOG_LINUX_DRIVER_CONFIG_ERROR \
- (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 12)
-#define BFA_LOG_LINUX_BNA_STATE_MACHINE \
- (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 13)
-#define BFA_LOG_LINUX_IOC_ERROR \
- (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 14)
-#define BFA_LOG_LINUX_RESOURCE_ALLOC_ERROR \
- (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 15)
-#define BFA_LOG_LINUX_RING_BUFFER_ERROR \
- (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 16)
-#define BFA_LOG_LINUX_DRIVER_ERROR \
- (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 17)
-#define BFA_LOG_LINUX_DRIVER_INFO \
- (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 18)
-#define BFA_LOG_LINUX_DRIVER_DIAG \
- (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 19)
-#define BFA_LOG_LINUX_DRIVER_AEN \
- (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 20)
-#endif
diff --git a/drivers/scsi/bfa/include/log/bfa_log_wdrv.h b/drivers/scsi/bfa/include/log/bfa_log_wdrv.h
deleted file mode 100644
index 809a95f7afe2..000000000000
--- a/drivers/scsi/bfa/include/log/bfa_log_wdrv.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/*
- * messages define for WDRV Module
- */
-#ifndef __BFA_LOG_WDRV_H__
-#define __BFA_LOG_WDRV_H__
-#include <cs/bfa_log.h>
-#define BFA_LOG_WDRV_IOC_INIT_ERROR \
- (((u32) BFA_LOG_WDRV_ID << BFA_LOG_MODID_OFFSET) | 1)
-#define BFA_LOG_WDRV_IOC_INTERNAL_ERROR \
- (((u32) BFA_LOG_WDRV_ID << BFA_LOG_MODID_OFFSET) | 2)
-#define BFA_LOG_WDRV_IOC_START_ERROR \
- (((u32) BFA_LOG_WDRV_ID << BFA_LOG_MODID_OFFSET) | 3)
-#define BFA_LOG_WDRV_IOC_STOP_ERROR \
- (((u32) BFA_LOG_WDRV_ID << BFA_LOG_MODID_OFFSET) | 4)
-#define BFA_LOG_WDRV_INSUFFICIENT_RESOURCES \
- (((u32) BFA_LOG_WDRV_ID << BFA_LOG_MODID_OFFSET) | 5)
-#define BFA_LOG_WDRV_BASE_ADDRESS_MAP_ERROR \
- (((u32) BFA_LOG_WDRV_ID << BFA_LOG_MODID_OFFSET) | 6)
-#endif
diff --git a/drivers/scsi/bfa/include/protocol/ct.h b/drivers/scsi/bfa/include/protocol/ct.h
deleted file mode 100644
index b82540a230c4..000000000000
--- a/drivers/scsi/bfa/include/protocol/ct.h
+++ /dev/null
@@ -1,492 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __CT_H__
-#define __CT_H__
-
-#include <protocol/types.h>
-
-#pragma pack(1)
-
-struct ct_hdr_s{
- u32 rev_id:8; /* Revision of the CT */
- u32 in_id:24; /* Initiator Id */
- u32 gs_type:8; /* Generic service Type */
- u32 gs_sub_type:8; /* Generic service sub type */
- u32 options:8; /* options */
- u32 rsvrd:8; /* reserved */
- u32 cmd_rsp_code:16;/* ct command/response code */
- u32 max_res_size:16;/* maximum/residual size */
- u32 frag_id:8; /* fragment ID */
- u32 reason_code:8; /* reason code */
- u32 exp_code:8; /* explanation code */
- u32 vendor_unq:8; /* vendor unique */
-};
-
-/*
- * defines for the Revision
- */
-enum {
- CT_GS3_REVISION = 0x01,
-};
-
-/*
- * defines for gs_type
- */
-enum {
- CT_GSTYPE_KEYSERVICE = 0xF7,
- CT_GSTYPE_ALIASSERVICE = 0xF8,
- CT_GSTYPE_MGMTSERVICE = 0xFA,
- CT_GSTYPE_TIMESERVICE = 0xFB,
- CT_GSTYPE_DIRSERVICE = 0xFC,
-};
-
-/*
- * defines for gs_sub_type for gs type directory service
- */
-enum {
- CT_GSSUBTYPE_NAMESERVER = 0x02,
-};
-
-/*
- * defines for gs_sub_type for gs type management service
- */
-enum {
- CT_GSSUBTYPE_CFGSERVER = 0x01,
- CT_GSSUBTYPE_UNZONED_NS = 0x02,
- CT_GSSUBTYPE_ZONESERVER = 0x03,
- CT_GSSUBTYPE_LOCKSERVER = 0x04,
- CT_GSSUBTYPE_HBA_MGMTSERVER = 0x10, /* for FDMI */
-};
-
-/*
- * defines for CT response code field
- */
-enum {
- CT_RSP_REJECT = 0x8001,
- CT_RSP_ACCEPT = 0x8002,
-};
-
-/*
- * definitions for CT reason code
- */
-enum {
- CT_RSN_INV_CMD = 0x01,
- CT_RSN_INV_VER = 0x02,
- CT_RSN_LOGIC_ERR = 0x03,
- CT_RSN_INV_SIZE = 0x04,
- CT_RSN_LOGICAL_BUSY = 0x05,
- CT_RSN_PROTO_ERR = 0x07,
- CT_RSN_UNABLE_TO_PERF = 0x09,
- CT_RSN_NOT_SUPP = 0x0B,
- CT_RSN_SERVER_NOT_AVBL = 0x0D,
- CT_RSN_SESSION_COULD_NOT_BE_ESTBD = 0x0E,
- CT_RSN_VENDOR_SPECIFIC = 0xFF,
-
-};
-
-/*
- * definitions for explanations code for Name server
- */
-enum {
- CT_NS_EXP_NOADDITIONAL = 0x00,
- CT_NS_EXP_ID_NOT_REG = 0x01,
- CT_NS_EXP_PN_NOT_REG = 0x02,
- CT_NS_EXP_NN_NOT_REG = 0x03,
- CT_NS_EXP_CS_NOT_REG = 0x04,
- CT_NS_EXP_IPN_NOT_REG = 0x05,
- CT_NS_EXP_IPA_NOT_REG = 0x06,
- CT_NS_EXP_FT_NOT_REG = 0x07,
- CT_NS_EXP_SPN_NOT_REG = 0x08,
- CT_NS_EXP_SNN_NOT_REG = 0x09,
- CT_NS_EXP_PT_NOT_REG = 0x0A,
- CT_NS_EXP_IPP_NOT_REG = 0x0B,
- CT_NS_EXP_FPN_NOT_REG = 0x0C,
- CT_NS_EXP_HA_NOT_REG = 0x0D,
- CT_NS_EXP_FD_NOT_REG = 0x0E,
- CT_NS_EXP_FF_NOT_REG = 0x0F,
- CT_NS_EXP_ACCESSDENIED = 0x10,
- CT_NS_EXP_UNACCEPTABLE_ID = 0x11,
- CT_NS_EXP_DATABASEEMPTY = 0x12,
- CT_NS_EXP_NOT_REG_IN_SCOPE = 0x13,
- CT_NS_EXP_DOM_ID_NOT_PRESENT = 0x14,
- CT_NS_EXP_PORT_NUM_NOT_PRESENT = 0x15,
- CT_NS_EXP_NO_DEVICE_ATTACHED = 0x16
-};
-
-/*
- * definitions for the explanation code for all servers
- */
-enum {
- CT_EXP_AUTH_EXCEPTION = 0xF1,
- CT_EXP_DB_FULL = 0xF2,
- CT_EXP_DB_EMPTY = 0xF3,
- CT_EXP_PROCESSING_REQ = 0xF4,
- CT_EXP_UNABLE_TO_VERIFY_CONN = 0xF5,
- CT_EXP_DEVICES_NOT_IN_CMN_ZONE = 0xF6
-};
-
-/*
- * Command codes for Name server
- */
-enum {
- GS_GID_PN = 0x0121, /* Get Id on port name */
- GS_GPN_ID = 0x0112, /* Get port name on ID */
- GS_GNN_ID = 0x0113, /* Get node name on ID */
- GS_GID_FT = 0x0171, /* Get Id on FC4 type */
- GS_GSPN_ID = 0x0118, /* Get symbolic PN on ID */
- GS_RFT_ID = 0x0217, /* Register fc4type on ID */
- GS_RSPN_ID = 0x0218, /* Register symbolic PN on ID */
- GS_RPN_ID = 0x0212, /* Register port name */
- GS_RNN_ID = 0x0213, /* Register node name */
- GS_RCS_ID = 0x0214, /* Register class of service */
- GS_RPT_ID = 0x021A, /* Register port type */
- GS_GA_NXT = 0x0100, /* Get all next */
- GS_RFF_ID = 0x021F, /* Register FC4 Feature */
-};
-
-struct fcgs_id_req_s{
- u32 rsvd:8;
- u32 dap:24; /* port identifier */
-};
-#define fcgs_gpnid_req_t struct fcgs_id_req_s
-#define fcgs_gnnid_req_t struct fcgs_id_req_s
-#define fcgs_gspnid_req_t struct fcgs_id_req_s
-
-struct fcgs_gidpn_req_s{
- wwn_t port_name; /* port wwn */
-};
-
-struct fcgs_gidpn_resp_s{
- u32 rsvd:8;
- u32 dap:24; /* port identifier */
-};
-
-/**
- * RFT_ID
- */
-struct fcgs_rftid_req_s {
- u32 rsvd:8;
- u32 dap:24; /* port identifier */
- u32 fc4_type[8]; /* fc4 types */
-};
-
-/**
- * RFF_ID : Register FC4 features.
- */
-
-#define FC_GS_FCP_FC4_FEATURE_INITIATOR 0x02
-#define FC_GS_FCP_FC4_FEATURE_TARGET 0x01
-
-struct fcgs_rffid_req_s{
- u32 rsvd:8;
- u32 dap:24; /* port identifier */
- u32 rsvd1:16;
- u32 fc4ftr_bits:8; /* fc4 feature bits */
- u32 fc4_type:8; /* corresponding FC4 Type */
-};
-
-/**
- * GID_FT Request
- */
-struct fcgs_gidft_req_s{
- u8 reserved;
- u8 domain_id; /* domain, 0 - all fabric */
- u8 area_id; /* area, 0 - whole domain */
- u8 fc4_type; /* FC_TYPE_FCP for SCSI devices */
-}; /* GID_FT Request */
-
-/**
- * GID_FT Response
- */
-struct fcgs_gidft_resp_s {
- u8 last:1; /* last port identifier flag */
- u8 reserved:7;
- u32 pid:24; /* port identifier */
-}; /* GID_FT Response */
-
-/**
- * RSPN_ID
- */
-struct fcgs_rspnid_req_s{
- u32 rsvd:8;
- u32 dap:24; /* port identifier */
- u8 spn_len; /* symbolic port name length */
- u8 spn[256]; /* symbolic port name */
-};
-
-/**
- * RPN_ID
- */
-struct fcgs_rpnid_req_s{
- u32 rsvd:8;
- u32 port_id:24;
- wwn_t port_name;
-};
-
-/**
- * RNN_ID
- */
-struct fcgs_rnnid_req_s{
- u32 rsvd:8;
- u32 port_id:24;
- wwn_t node_name;
-};
-
-/**
- * RCS_ID
- */
-struct fcgs_rcsid_req_s{
- u32 rsvd:8;
- u32 port_id:24;
- u32 cos;
-};
-
-/**
- * RPT_ID
- */
-struct fcgs_rptid_req_s{
- u32 rsvd:8;
- u32 port_id:24;
- u32 port_type:8;
- u32 rsvd1:24;
-};
-
-/**
- * GA_NXT Request
- */
-struct fcgs_ganxt_req_s{
- u32 rsvd:8;
- u32 port_id:24;
-};
-
-/**
- * GA_NXT Response
- */
-struct fcgs_ganxt_rsp_s{
- u32 port_type:8; /* Port Type */
- u32 port_id:24; /* Port Identifier */
- wwn_t port_name; /* Port Name */
- u8 spn_len; /* Length of Symbolic Port Name */
- char spn[255]; /* Symbolic Port Name */
- wwn_t node_name; /* Node Name */
- u8 snn_len; /* Length of Symbolic Node Name */
- char snn[255]; /* Symbolic Node Name */
- u8 ipa[8]; /* Initial Process Associator */
- u8 ip[16]; /* IP Address */
- u32 cos; /* Class of Service */
- u32 fc4types[8]; /* FC-4 TYPEs */
- wwn_t fabric_port_name;
- /* Fabric Port Name */
- u32 rsvd:8; /* Reserved */
- u32 hard_addr:24; /* Hard Address */
-};
-
-/*
- * Fabric Config Server
- */
-
-/*
- * Command codes for Fabric Configuration Server
- */
-enum {
- GS_FC_GFN_CMD = 0x0114, /* GS FC Get Fabric Name */
- GS_FC_GMAL_CMD = 0x0116, /* GS FC GMAL */
- GS_FC_TRACE_CMD = 0x0400, /* GS FC Trace Route */
- GS_FC_PING_CMD = 0x0401, /* GS FC Ping */
-};
-
-/*
- * Source or Destination Port Tags.
- */
-enum {
- GS_FTRACE_TAG_NPORT_ID = 1,
- GS_FTRACE_TAG_NPORT_NAME = 2,
-};
-
-/*
-* Port Value : Could be a Port id or wwn
- */
-union fcgs_port_val_u{
- u32 nport_id;
- wwn_t nport_wwn;
-};
-
-#define GS_FTRACE_MAX_HOP_COUNT 20
-#define GS_FTRACE_REVISION 1
-
-/*
- * Ftrace Related Structures.
- */
-
-/*
- * STR (Switch Trace) Reject Reason Codes. From FC-SW.
- */
-enum {
- GS_FTRACE_STR_CMD_COMPLETED_SUCC = 0,
- GS_FTRACE_STR_CMD_NOT_SUPP_IN_NEXT_SWITCH,
- GS_FTRACE_STR_NO_RESP_FROM_NEXT_SWITCH,
- GS_FTRACE_STR_MAX_HOP_CNT_REACHED,
- GS_FTRACE_STR_SRC_PORT_NOT_FOUND,
- GS_FTRACE_STR_DST_PORT_NOT_FOUND,
- GS_FTRACE_STR_DEVICES_NOT_IN_COMMON_ZONE,
- GS_FTRACE_STR_NO_ROUTE_BW_PORTS,
- GS_FTRACE_STR_NO_ADDL_EXPLN,
- GS_FTRACE_STR_FABRIC_BUSY,
- GS_FTRACE_STR_FABRIC_BUILD_IN_PROGRESS,
- GS_FTRACE_STR_VENDOR_SPECIFIC_ERR_START = 0xf0,
- GS_FTRACE_STR_VENDOR_SPECIFIC_ERR_END = 0xff,
-};
-
-/*
- * Ftrace Request
- */
-struct fcgs_ftrace_req_s{
- u32 revision;
- u16 src_port_tag; /* Source Port tag */
- u16 src_port_len; /* Source Port len */
- union fcgs_port_val_u src_port_val; /* Source Port value */
- u16 dst_port_tag; /* Destination Port tag */
- u16 dst_port_len; /* Destination Port len */
- union fcgs_port_val_u dst_port_val; /* Destination Port value */
- u32 token;
- u8 vendor_id[8]; /* T10 Vendor Identifier */
- u8 vendor_info[8]; /* Vendor specific Info */
- u32 max_hop_cnt; /* Max Hop Count */
-};
-
-/*
- * Path info structure
- */
-struct fcgs_ftrace_path_info_s{
- wwn_t switch_name; /* Switch WWN */
- u32 domain_id;
- wwn_t ingress_port_name; /* Ingress ports wwn */
- u32 ingress_phys_port_num; /* Ingress ports physical port
- * number
- */
- wwn_t egress_port_name; /* Ingress ports wwn */
- u32 egress_phys_port_num; /* Ingress ports physical port
- * number
- */
-};
-
-/*
- * Ftrace Acc Response
- */
-struct fcgs_ftrace_resp_s{
- u32 revision;
- u32 token;
- u8 vendor_id[8]; /* T10 Vendor Identifier */
- u8 vendor_info[8]; /* Vendor specific Info */
- u32 str_rej_reason_code; /* STR Reject Reason Code */
- u32 num_path_info_entries; /* No. of path info entries */
- /*
- * path info entry/entries.
- */
- struct fcgs_ftrace_path_info_s path_info[1];
-
-};
-
-/*
-* Fabric Config Server : FCPing
- */
-
-/*
- * FC Ping Request
- */
-struct fcgs_fcping_req_s{
- u32 revision;
- u16 port_tag;
- u16 port_len; /* Port len */
- union fcgs_port_val_u port_val; /* Port value */
- u32 token;
-};
-
-/*
- * FC Ping Response
- */
-struct fcgs_fcping_resp_s{
- u32 token;
-};
-
-/*
- * Command codes for zone server query.
- */
-enum {
- ZS_GZME = 0x0124, /* Get zone member extended */
-};
-
-/*
- * ZS GZME request
- */
-#define ZS_GZME_ZNAMELEN 32
-struct zs_gzme_req_s{
- u8 znamelen;
- u8 rsvd[3];
- u8 zname[ZS_GZME_ZNAMELEN];
-};
-
-enum zs_mbr_type{
- ZS_MBR_TYPE_PWWN = 1,
- ZS_MBR_TYPE_DOMPORT = 2,
- ZS_MBR_TYPE_PORTID = 3,
- ZS_MBR_TYPE_NWWN = 4,
-};
-
-struct zs_mbr_wwn_s{
- u8 mbr_type;
- u8 rsvd[3];
- wwn_t wwn;
-};
-
-struct zs_query_resp_s{
- u32 nmbrs; /* number of zone members */
- struct zs_mbr_wwn_s mbr[1];
-};
-
-/*
- * GMAL Command ( Get ( interconnect Element) Management Address List)
- * To retrieve the IP Address of a Switch.
- */
-
-#define CT_GMAL_RESP_PREFIX_TELNET "telnet://"
-#define CT_GMAL_RESP_PREFIX_HTTP "http://"
-
-/* GMAL/GFN request */
-struct fcgs_req_s {
- wwn_t wwn; /* PWWN/NWWN */
-};
-
-#define fcgs_gmal_req_t struct fcgs_req_s
-#define fcgs_gfn_req_t struct fcgs_req_s
-
-/* Accept Response to GMAL */
-struct fcgs_gmal_resp_s {
- u32 ms_len; /* Num of entries */
- u8 ms_ma[256];
-};
-
-struct fc_gmal_entry_s {
- u8 len;
- u8 prefix[7]; /* like "http://" */
- u8 ip_addr[248];
-};
-
-#pragma pack()
-
-#endif
diff --git a/drivers/scsi/bfa/include/protocol/fc_sp.h b/drivers/scsi/bfa/include/protocol/fc_sp.h
deleted file mode 100644
index 55bb0b31d04b..000000000000
--- a/drivers/scsi/bfa/include/protocol/fc_sp.h
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __FC_SP_H__
-#define __FC_SP_H__
-
-#include <protocol/types.h>
-
-#pragma pack(1)
-
-enum auth_els_flags{
- FC_AUTH_ELS_MORE_FRAGS_FLAG = 0x80, /*! bit-7. More Fragments
- * Follow
- */
- FC_AUTH_ELS_CONCAT_FLAG = 0x40, /*! bit-6. Concatenation Flag */
- FC_AUTH_ELS_SEQ_NUM_FLAG = 0x01 /*! bit-0. Sequence Number */
-};
-
-enum auth_msg_codes{
- FC_AUTH_MC_AUTH_RJT = 0x0A, /*! Auth Reject */
- FC_AUTH_MC_AUTH_NEG = 0x0B, /*! Auth Negotiate */
- FC_AUTH_MC_AUTH_DONE = 0x0C, /*! Auth Done */
-
- FC_AUTH_MC_DHCHAP_CHAL = 0x10, /*! DHCHAP Challenge */
- FC_AUTH_MC_DHCHAP_REPLY = 0x11, /*! DHCHAP Reply */
- FC_AUTH_MC_DHCHAP_SUCC = 0x12, /*! DHCHAP Success */
-
- FC_AUTH_MC_FCAP_REQ = 0x13, /*! FCAP Request */
- FC_AUTH_MC_FCAP_ACK = 0x14, /*! FCAP Acknowledge */
- FC_AUTH_MC_FCAP_CONF = 0x15, /*! FCAP Confirm */
-
- FC_AUTH_MC_FCPAP_INIT = 0x16, /*! FCPAP Init */
- FC_AUTH_MC_FCPAP_ACC = 0x17, /*! FCPAP Accept */
- FC_AUTH_MC_FCPAP_COMP = 0x18, /*! FCPAP Complete */
-
- FC_AUTH_MC_IKE_SA_INIT = 0x22, /*! IKE SA INIT */
- FC_AUTH_MC_IKE_SA_AUTH = 0x23, /*! IKE SA Auth */
- FC_AUTH_MC_IKE_CREATE_CHILD_SA = 0x24, /*! IKE Create Child SA */
- FC_AUTH_MC_IKE_INFO = 0x25, /*! IKE informational */
-};
-
-enum auth_proto_version{
- FC_AUTH_PROTO_VER_1 = 1, /*! Protocol Version 1 */
-};
-
-enum {
- FC_AUTH_ELS_COMMAND_CODE = 0x90,/*! Authentication ELS Command code */
- FC_AUTH_PROTO_PARAM_LEN_SZ = 4, /*! Size of Proto Parameter Len Field */
- FC_AUTH_PROTO_PARAM_VAL_SZ = 4, /*! Size of Proto Parameter Val Field */
- FC_MAX_AUTH_SECRET_LEN = 256,
- /*! Maximum secret string length */
- FC_AUTH_NUM_USABLE_PROTO_LEN_SZ = 4,
- /*! Size of usable protocols field */
- FC_AUTH_RESP_VALUE_LEN_SZ = 4,
- /*! Size of response value length */
- FC_MAX_CHAP_KEY_LEN = 256, /*! Maximum md5 digest length */
- FC_MAX_AUTH_RETRIES = 3, /*! Maximum number of retries */
- FC_MD5_DIGEST_LEN = 16, /*! MD5 digest length */
- FC_SHA1_DIGEST_LEN = 20, /*! SHA1 digest length */
- FC_MAX_DHG_SUPPORTED = 1, /*! Maximum DH Groups supported */
- FC_MAX_ALG_SUPPORTED = 1, /*! Maximum algorithms supported */
- FC_MAX_PROTO_SUPPORTED = 1, /*! Maximum protocols supported */
- FC_START_TXN_ID = 2, /*! Starting transaction ID */
-};
-
-enum auth_proto_id{
- FC_AUTH_PROTO_DHCHAP = 0x00000001,
- FC_AUTH_PROTO_FCAP = 0x00000002,
- FC_AUTH_PROTO_FCPAP = 0x00000003,
- FC_AUTH_PROTO_IKEv2 = 0x00000004,
- FC_AUTH_PROTO_IKEv2_AUTH = 0x00000005,
-};
-
-struct auth_name_s{
- u16 name_tag; /*! Name Tag = 1 for Authentication */
- u16 name_len; /*! Name Length = 8 for Authentication
- */
- wwn_t name; /*! Name. TODO - is this PWWN */
-};
-
-
-enum auth_hash_func{
- FC_AUTH_HASH_FUNC_MD5 = 0x00000005,
- FC_AUTH_HASH_FUNC_SHA_1 = 0x00000006,
-};
-
-enum auth_dh_gid{
- FC_AUTH_DH_GID_0_DHG_NULL = 0x00000000,
- FC_AUTH_DH_GID_1_DHG_1024 = 0x00000001,
- FC_AUTH_DH_GID_2_DHG_1280 = 0x00000002,
- FC_AUTH_DH_GID_3_DHG_1536 = 0x00000003,
- FC_AUTH_DH_GID_4_DHG_2048 = 0x00000004,
- FC_AUTH_DH_GID_6_DHG_3072 = 0x00000006,
- FC_AUTH_DH_GID_7_DHG_4096 = 0x00000007,
- FC_AUTH_DH_GID_8_DHG_6144 = 0x00000008,
- FC_AUTH_DH_GID_9_DHG_8192 = 0x00000009,
-};
-
-struct auth_els_msg_s {
- u8 auth_els_code; /* Authentication ELS Code (0x90) */
- u8 auth_els_flag; /* Authentication ELS Flags */
- u8 auth_msg_code; /* Authentication Message Code */
- u8 proto_version; /* Protocol Version */
- u32 msg_len; /* Message Length */
- u32 trans_id; /* Transaction Identifier (T_ID) */
-
- /* Msg payload follows... */
-};
-
-
-enum auth_neg_param_tags {
- FC_AUTH_NEG_DHCHAP_HASHLIST = 0x0001,
- FC_AUTH_NEG_DHCHAP_DHG_ID_LIST = 0x0002,
-};
-
-
-struct dhchap_param_format_s {
- u16 tag; /*! Parameter Tag. See
- * auth_neg_param_tags_t
- */
- u16 word_cnt;
-
- /* followed by variable length parameter value... */
-};
-
-struct auth_proto_params_s {
- u32 proto_param_len;
- u32 proto_id;
-
- /*
- * Followed by variable length Protocol specific parameters. DH-CHAP
- * uses dhchap_param_format_t
- */
-};
-
-struct auth_neg_msg_s {
- struct auth_name_s auth_ini_name;
- u32 usable_auth_protos;
- struct auth_proto_params_s proto_params[1]; /*! (1..usable_auth_proto)
- * protocol params
- */
-};
-
-struct auth_dh_val_s {
- u32 dh_val_len;
- u32 dh_val[1];
-};
-
-struct auth_dhchap_chal_msg_s {
- struct auth_els_msg_s hdr;
- struct auth_name_s auth_responder_name; /* TODO VRK - is auth_name_t
- * type OK?
- */
- u32 hash_id;
- u32 dh_grp_id;
- u32 chal_val_len;
- char chal_val[1];
-
- /* ...followed by variable Challenge length/value and DH length/value */
-};
-
-
-enum auth_rjt_codes {
- FC_AUTH_RJT_CODE_AUTH_FAILURE = 0x01,
- FC_AUTH_RJT_CODE_LOGICAL_ERR = 0x02,
-};
-
-enum auth_rjt_code_exps {
- FC_AUTH_CEXP_AUTH_MECH_NOT_USABLE = 0x01,
- FC_AUTH_CEXP_DH_GROUP_NOT_USABLE = 0x02,
- FC_AUTH_CEXP_HASH_FUNC_NOT_USABLE = 0x03,
- FC_AUTH_CEXP_AUTH_XACT_STARTED = 0x04,
- FC_AUTH_CEXP_AUTH_FAILED = 0x05,
- FC_AUTH_CEXP_INCORRECT_PLD = 0x06,
- FC_AUTH_CEXP_INCORRECT_PROTO_MSG = 0x07,
- FC_AUTH_CEXP_RESTART_AUTH_PROTO = 0x08,
- FC_AUTH_CEXP_AUTH_CONCAT_NOT_SUPP = 0x09,
- FC_AUTH_CEXP_PROTO_VER_NOT_SUPP = 0x0A,
-};
-
-enum auth_status {
- FC_AUTH_STATE_INPROGRESS = 0, /*! authentication in progress */
- FC_AUTH_STATE_FAILED = 1, /*! authentication failed */
- FC_AUTH_STATE_SUCCESS = 2 /*! authentication successful */
-};
-
-struct auth_rjt_msg_s {
- struct auth_els_msg_s hdr;
- u8 reason_code;
- u8 reason_code_exp;
- u8 rsvd[2];
-};
-
-
-struct auth_dhchap_neg_msg_s {
- struct auth_els_msg_s hdr;
- struct auth_neg_msg_s nego;
-};
-
-struct auth_dhchap_reply_msg_s {
- struct auth_els_msg_s hdr;
-
- /*
- * followed by response value length & Value + DH Value Length & Value
- */
-};
-
-#pragma pack()
-
-#endif /* __FC_SP_H__ */
diff --git a/drivers/scsi/bfa/include/protocol/fcp.h b/drivers/scsi/bfa/include/protocol/fcp.h
deleted file mode 100644
index 74ea63ce84b7..000000000000
--- a/drivers/scsi/bfa/include/protocol/fcp.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __FCPPROTO_H__
-#define __FCPPROTO_H__
-
-#include <linux/bitops.h>
-#include <protocol/scsi.h>
-
-#pragma pack(1)
-
-enum {
- FCP_RJT = 0x01000000, /* SRR reject */
- FCP_SRR_ACCEPT = 0x02000000, /* SRR accept */
- FCP_SRR = 0x14000000, /* Sequence Retransmission Request */
-};
-
-/*
- * SRR FC-4 LS payload
- */
-struct fc_srr_s{
- u32 ls_cmd;
- u32 ox_id:16; /* ox-id */
- u32 rx_id:16; /* rx-id */
- u32 ro; /* relative offset */
- u32 r_ctl:8; /* R_CTL for I.U. */
- u32 res:24;
-};
-
-
-/*
- * FCP_CMND definitions
- */
-#define FCP_CMND_CDB_LEN 16
-#define FCP_CMND_LUN_LEN 8
-
-struct fcp_cmnd_s{
- lun_t lun; /* 64-bit LU number */
- u8 crn; /* command reference number */
-#ifdef __BIGENDIAN
- u8 resvd:1,
- priority:4, /* FCP-3: SAM-3 priority */
- taskattr:3; /* scsi task attribute */
-#else
- u8 taskattr:3, /* scsi task attribute */
- priority:4, /* FCP-3: SAM-3 priority */
- resvd:1;
-#endif
- u8 tm_flags; /* task management flags */
-#ifdef __BIGENDIAN
- u8 addl_cdb_len:6, /* additional CDB length words */
- iodir:2; /* read/write FCP_DATA IUs */
-#else
- u8 iodir:2, /* read/write FCP_DATA IUs */
- addl_cdb_len:6; /* additional CDB length */
-#endif
- struct scsi_cdb_s cdb;
-
- /*
- * !!! additional cdb bytes follows here!!!
- */
- u32 fcp_dl; /* bytes to be transferred */
-};
-
-#define fcp_cmnd_cdb_len(_cmnd) ((_cmnd)->addl_cdb_len * 4 + FCP_CMND_CDB_LEN)
-#define fcp_cmnd_fcpdl(_cmnd) ((&(_cmnd)->fcp_dl)[(_cmnd)->addl_cdb_len])
-
-/*
- * fcp_cmnd_t.iodir field values
- */
-enum fcp_iodir{
- FCP_IODIR_NONE = 0,
- FCP_IODIR_WRITE = 1,
- FCP_IODIR_READ = 2,
- FCP_IODIR_RW = 3,
-};
-
-/*
- * Task attribute field
- */
-enum {
- FCP_TASK_ATTR_SIMPLE = 0,
- FCP_TASK_ATTR_HOQ = 1,
- FCP_TASK_ATTR_ORDERED = 2,
- FCP_TASK_ATTR_ACA = 4,
- FCP_TASK_ATTR_UNTAGGED = 5, /* obsolete in FCP-3 */
-};
-
-/*
- * Task management flags field - only one bit shall be set
- */
-enum fcp_tm_cmnd{
- FCP_TM_ABORT_TASK_SET = BIT(1),
- FCP_TM_CLEAR_TASK_SET = BIT(2),
- FCP_TM_LUN_RESET = BIT(4),
- FCP_TM_TARGET_RESET = BIT(5), /* obsolete in FCP-3 */
- FCP_TM_CLEAR_ACA = BIT(6),
-};
-
-/*
- * FCP_XFER_RDY IU defines
- */
-struct fcp_xfer_rdy_s{
- u32 data_ro;
- u32 burst_len;
- u32 reserved;
-};
-
-/*
- * FCP_RSP residue flags
- */
-enum fcp_residue{
- FCP_NO_RESIDUE = 0, /* no residue */
- FCP_RESID_OVER = 1, /* more data left that was not sent */
- FCP_RESID_UNDER = 2, /* less data than requested */
-};
-
-enum {
- FCP_RSPINFO_GOOD = 0,
- FCP_RSPINFO_DATALEN_MISMATCH = 1,
- FCP_RSPINFO_CMND_INVALID = 2,
- FCP_RSPINFO_ROLEN_MISMATCH = 3,
- FCP_RSPINFO_TM_NOT_SUPP = 4,
- FCP_RSPINFO_TM_FAILED = 5,
-};
-
-struct fcp_rspinfo_s{
- u32 res0:24;
- u32 rsp_code:8; /* response code (as above) */
- u32 res1;
-};
-
-struct fcp_resp_s{
- u32 reserved[2]; /* 2 words reserved */
- u16 reserved2;
-#ifdef __BIGENDIAN
- u8 reserved3:3;
- u8 fcp_conf_req:1; /* FCP_CONF is requested */
- u8 resid_flags:2; /* underflow/overflow */
- u8 sns_len_valid:1;/* sense len is valid */
- u8 rsp_len_valid:1;/* response len is valid */
-#else
- u8 rsp_len_valid:1;/* response len is valid */
- u8 sns_len_valid:1;/* sense len is valid */
- u8 resid_flags:2; /* underflow/overflow */
- u8 fcp_conf_req:1; /* FCP_CONF is requested */
- u8 reserved3:3;
-#endif
- u8 scsi_status; /* one byte SCSI status */
- u32 residue; /* residual data bytes */
- u32 sns_len; /* length od sense info */
- u32 rsp_len; /* length of response info */
-};
-
-#define fcp_snslen(__fcprsp) ((__fcprsp)->sns_len_valid ? \
- (__fcprsp)->sns_len : 0)
-#define fcp_rsplen(__fcprsp) ((__fcprsp)->rsp_len_valid ? \
- (__fcprsp)->rsp_len : 0)
-#define fcp_rspinfo(__fcprsp) ((struct fcp_rspinfo_s *)((__fcprsp) + 1))
-#define fcp_snsinfo(__fcprsp) (((u8 *)fcp_rspinfo(__fcprsp)) + \
- fcp_rsplen(__fcprsp))
-
-struct fcp_cmnd_fr_s{
- struct fchs_s fchs;
- struct fcp_cmnd_s fcp;
-};
-
-#pragma pack()
-
-#endif
diff --git a/drivers/scsi/bfa/include/protocol/fdmi.h b/drivers/scsi/bfa/include/protocol/fdmi.h
deleted file mode 100644
index 6c05c268c71b..000000000000
--- a/drivers/scsi/bfa/include/protocol/fdmi.h
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __FDMI_H__
-#define __FDMI_H__
-
-#include <protocol/types.h>
-#include <protocol/fc.h>
-#include <protocol/ct.h>
-
-#pragma pack(1)
-
-/*
- * FDMI Command Codes
- */
-#define FDMI_GRHL 0x0100
-#define FDMI_GHAT 0x0101
-#define FDMI_GRPL 0x0102
-#define FDMI_GPAT 0x0110
-#define FDMI_RHBA 0x0200
-#define FDMI_RHAT 0x0201
-#define FDMI_RPRT 0x0210
-#define FDMI_RPA 0x0211
-#define FDMI_DHBA 0x0300
-#define FDMI_DPRT 0x0310
-
-/*
- * FDMI reason codes
- */
-#define FDMI_NO_ADDITIONAL_EXP 0x00
-#define FDMI_HBA_ALREADY_REG 0x10
-#define FDMI_HBA_ATTRIB_NOT_REG 0x11
-#define FDMI_HBA_ATTRIB_MULTIPLE 0x12
-#define FDMI_HBA_ATTRIB_LENGTH_INVALID 0x13
-#define FDMI_HBA_ATTRIB_NOT_PRESENT 0x14
-#define FDMI_PORT_ORIG_NOT_IN_LIST 0x15
-#define FDMI_PORT_HBA_NOT_IN_LIST 0x16
-#define FDMI_PORT_ATTRIB_NOT_REG 0x20
-#define FDMI_PORT_NOT_REG 0x21
-#define FDMI_PORT_ATTRIB_MULTIPLE 0x22
-#define FDMI_PORT_ATTRIB_LENGTH_INVALID 0x23
-#define FDMI_PORT_ALREADY_REGISTEREED 0x24
-
-/*
- * FDMI Transmission Speed Mask values
- */
-#define FDMI_TRANS_SPEED_1G 0x00000001
-#define FDMI_TRANS_SPEED_2G 0x00000002
-#define FDMI_TRANS_SPEED_10G 0x00000004
-#define FDMI_TRANS_SPEED_4G 0x00000008
-#define FDMI_TRANS_SPEED_8G 0x00000010
-#define FDMI_TRANS_SPEED_16G 0x00000020
-#define FDMI_TRANS_SPEED_UNKNOWN 0x00008000
-
-/*
- * FDMI HBA attribute types
- */
-enum fdmi_hba_attribute_type {
- FDMI_HBA_ATTRIB_NODENAME = 1, /* 0x0001 */
- FDMI_HBA_ATTRIB_MANUFACTURER, /* 0x0002 */
- FDMI_HBA_ATTRIB_SERIALNUM, /* 0x0003 */
- FDMI_HBA_ATTRIB_MODEL, /* 0x0004 */
- FDMI_HBA_ATTRIB_MODEL_DESC, /* 0x0005 */
- FDMI_HBA_ATTRIB_HW_VERSION, /* 0x0006 */
- FDMI_HBA_ATTRIB_DRIVER_VERSION, /* 0x0007 */
- FDMI_HBA_ATTRIB_ROM_VERSION, /* 0x0008 */
- FDMI_HBA_ATTRIB_FW_VERSION, /* 0x0009 */
- FDMI_HBA_ATTRIB_OS_NAME, /* 0x000A */
- FDMI_HBA_ATTRIB_MAX_CT, /* 0x000B */
-
- FDMI_HBA_ATTRIB_MAX_TYPE
-};
-
-/*
- * FDMI Port attribute types
- */
-enum fdmi_port_attribute_type {
- FDMI_PORT_ATTRIB_FC4_TYPES = 1, /* 0x0001 */
- FDMI_PORT_ATTRIB_SUPP_SPEED, /* 0x0002 */
- FDMI_PORT_ATTRIB_PORT_SPEED, /* 0x0003 */
- FDMI_PORT_ATTRIB_FRAME_SIZE, /* 0x0004 */
- FDMI_PORT_ATTRIB_DEV_NAME, /* 0x0005 */
- FDMI_PORT_ATTRIB_HOST_NAME, /* 0x0006 */
-
- FDMI_PORT_ATTR_MAX_TYPE
-};
-
-/*
- * FDMI attribute
- */
-struct fdmi_attr_s {
- u16 type;
- u16 len;
- u8 value[1];
-};
-
-/*
- * HBA Attribute Block
- */
-struct fdmi_hba_attr_s {
- u32 attr_count; /* # of attributes */
- struct fdmi_attr_s hba_attr; /* n attributes */
-};
-
-/*
- * Registered Port List
- */
-struct fdmi_port_list_s {
- u32 num_ports; /* number Of Port Entries */
- wwn_t port_entry; /* one or more */
-};
-
-/*
- * Port Attribute Block
- */
-struct fdmi_port_attr_s {
- u32 attr_count; /* # of attributes */
- struct fdmi_attr_s port_attr; /* n attributes */
-};
-
-/*
- * FDMI Register HBA Attributes
- */
-struct fdmi_rhba_s {
- wwn_t hba_id; /* HBA Identifier */
- struct fdmi_port_list_s port_list; /* Registered Port List */
- struct fdmi_hba_attr_s hba_attr_blk; /* HBA attribute block */
-};
-
-/*
- * FDMI Register Port
- */
-struct fdmi_rprt_s {
- wwn_t hba_id; /* HBA Identifier */
- wwn_t port_name; /* Port wwn */
- struct fdmi_port_attr_s port_attr_blk; /* Port Attr Block */
-};
-
-/*
- * FDMI Register Port Attributes
- */
-struct fdmi_rpa_s {
- wwn_t port_name; /* port wwn */
- struct fdmi_port_attr_s port_attr_blk; /* Port Attr Block */
-};
-
-#pragma pack()
-
-#endif
diff --git a/drivers/scsi/bfa/include/protocol/scsi.h b/drivers/scsi/bfa/include/protocol/scsi.h
deleted file mode 100644
index b220e6b4f6e1..000000000000
--- a/drivers/scsi/bfa/include/protocol/scsi.h
+++ /dev/null
@@ -1,1648 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __SCSI_H__
-#define __SCSI_H__
-
-#include <protocol/types.h>
-
-#pragma pack(1)
-
-/*
- * generic SCSI cdb definition
- */
-#define SCSI_MAX_CDBLEN 16
-struct scsi_cdb_s{
- u8 scsi_cdb[SCSI_MAX_CDBLEN];
-};
-
-/*
- * scsi lun serial number definition
- */
-#define SCSI_LUN_SN_LEN 32
-struct scsi_lun_sn_s{
- u8 lun_sn[SCSI_LUN_SN_LEN];
-};
-
-/*
- * SCSI Direct Access Commands
- */
-enum {
- SCSI_OP_TEST_UNIT_READY = 0x00,
- SCSI_OP_REQUEST_SENSE = 0x03,
- SCSI_OP_FORMAT_UNIT = 0x04,
- SCSI_OP_READ6 = 0x08,
- SCSI_OP_WRITE6 = 0x0A,
- SCSI_OP_WRITE_FILEMARKS = 0x10,
- SCSI_OP_INQUIRY = 0x12,
- SCSI_OP_MODE_SELECT6 = 0x15,
- SCSI_OP_RESERVE6 = 0x16,
- SCSI_OP_RELEASE6 = 0x17,
- SCSI_OP_MODE_SENSE6 = 0x1A,
- SCSI_OP_START_STOP_UNIT = 0x1B,
- SCSI_OP_SEND_DIAGNOSTIC = 0x1D,
- SCSI_OP_READ_CAPACITY = 0x25,
- SCSI_OP_READ10 = 0x28,
- SCSI_OP_WRITE10 = 0x2A,
- SCSI_OP_VERIFY10 = 0x2F,
- SCSI_OP_READ_DEFECT_DATA = 0x37,
- SCSI_OP_LOG_SELECT = 0x4C,
- SCSI_OP_LOG_SENSE = 0x4D,
- SCSI_OP_MODE_SELECT10 = 0x55,
- SCSI_OP_RESERVE10 = 0x56,
- SCSI_OP_RELEASE10 = 0x57,
- SCSI_OP_MODE_SENSE10 = 0x5A,
- SCSI_OP_PER_RESERVE_IN = 0x5E,
- SCSI_OP_PER_RESERVE_OUR = 0x5E,
- SCSI_OP_READ16 = 0x88,
- SCSI_OP_WRITE16 = 0x8A,
- SCSI_OP_VERIFY16 = 0x8F,
- SCSI_OP_READ_CAPACITY16 = 0x9E,
- SCSI_OP_REPORT_LUNS = 0xA0,
- SCSI_OP_READ12 = 0xA8,
- SCSI_OP_WRITE12 = 0xAA,
- SCSI_OP_UNDEF = 0xFF,
-};
-
-/*
- * SCSI START_STOP_UNIT command
- */
-struct scsi_start_stop_unit_s{
- u8 opcode;
-#ifdef __BIGENDIAN
- u8 lun:3;
- u8 reserved1:4;
- u8 immed:1;
-#else
- u8 immed:1;
- u8 reserved1:4;
- u8 lun:3;
-#endif
- u8 reserved2;
- u8 reserved3;
-#ifdef __BIGENDIAN
- u8 power_conditions:4;
- u8 reserved4:2;
- u8 loEj:1;
- u8 start:1;
-#else
- u8 start:1;
- u8 loEj:1;
- u8 reserved4:2;
- u8 power_conditions:4;
-#endif
- u8 control;
-};
-
-/*
- * SCSI SEND_DIAGNOSTIC command
- */
-struct scsi_send_diagnostic_s{
- u8 opcode;
-#ifdef __BIGENDIAN
- u8 self_test_code:3;
- u8 pf:1;
- u8 reserved1:1;
- u8 self_test:1;
- u8 dev_offl:1;
- u8 unit_offl:1;
-#else
- u8 unit_offl:1;
- u8 dev_offl:1;
- u8 self_test:1;
- u8 reserved1:1;
- u8 pf:1;
- u8 self_test_code:3;
-#endif
- u8 reserved2;
-
- u8 param_list_length[2]; /* MSB first */
- u8 control;
-
-};
-
-/*
- * SCSI READ10/WRITE10 commands
- */
-struct scsi_rw10_s{
- u8 opcode;
-#ifdef __BIGENDIAN
- u8 lun:3;
- u8 dpo:1; /* Disable Page Out */
- u8 fua:1; /* Force Unit Access */
- u8 reserved1:2;
- u8 rel_adr:1; /* relative address */
-#else
- u8 rel_adr:1;
- u8 reserved1:2;
- u8 fua:1;
- u8 dpo:1;
- u8 lun:3;
-#endif
- u8 lba0; /* logical block address - MSB */
- u8 lba1;
- u8 lba2;
- u8 lba3; /* LSB */
- u8 reserved3;
- u8 xfer_length0; /* transfer length in blocks - MSB */
- u8 xfer_length1; /* LSB */
- u8 control;
-};
-
-#define SCSI_CDB10_GET_LBA(cdb) \
- (((cdb)->lba0 << 24) | ((cdb)->lba1 << 16) | \
- ((cdb)->lba2 << 8) | (cdb)->lba3)
-
-#define SCSI_CDB10_SET_LBA(cdb, lba) { \
- (cdb)->lba0 = lba >> 24; \
- (cdb)->lba1 = (lba >> 16) & 0xFF; \
- (cdb)->lba2 = (lba >> 8) & 0xFF; \
- (cdb)->lba3 = lba & 0xFF; \
-}
-
-#define SCSI_CDB10_GET_TL(cdb) \
- ((cdb)->xfer_length0 << 8 | (cdb)->xfer_length1)
-#define SCSI_CDB10_SET_TL(cdb, tl) { \
- (cdb)->xfer_length0 = tl >> 8; \
- (cdb)->xfer_length1 = tl & 0xFF; \
-}
-
-/*
- * SCSI READ6/WRITE6 commands
- */
-struct scsi_rw6_s{
- u8 opcode;
-#ifdef __BIGENDIAN
- u8 lun:3;
- u8 lba0:5; /* MSb */
-#else
- u8 lba0:5; /* MSb */
- u8 lun:3;
-#endif
- u8 lba1;
- u8 lba2; /* LSB */
- u8 xfer_length;
- u8 control;
-};
-
-#define SCSI_TAPE_CDB6_GET_TL(cdb) \
- (((cdb)->tl0 << 16) | ((cdb)->tl1 << 8) | (cdb)->tl2)
-
-#define SCSI_TAPE_CDB6_SET_TL(cdb, tl) { \
- (cdb)->tl0 = tl >> 16; \
- (cdb)->tl1 = (tl >> 8) & 0xFF; \
- (cdb)->tl2 = tl & 0xFF; \
-}
-
-/*
- * SCSI sequential (TAPE) wrtie command
- */
-struct scsi_tape_wr_s{
- u8 opcode;
-#ifdef __BIGENDIAN
- u8 rsvd:7;
- u8 fixed:1; /* MSb */
-#else
- u8 fixed:1; /* MSb */
- u8 rsvd:7;
-#endif
- u8 tl0; /* Msb */
- u8 tl1;
- u8 tl2; /* Lsb */
-
- u8 control;
-};
-
-#define SCSI_CDB6_GET_LBA(cdb) \
- (((cdb)->lba0 << 16) | ((cdb)->lba1 << 8) | (cdb)->lba2)
-
-#define SCSI_CDB6_SET_LBA(cdb, lba) { \
- (cdb)->lba0 = lba >> 16; \
- (cdb)->lba1 = (lba >> 8) & 0xFF; \
- (cdb)->lba2 = lba & 0xFF; \
-}
-
-#define SCSI_CDB6_GET_TL(cdb) ((cdb)->xfer_length)
-#define SCSI_CDB6_SET_TL(cdb, tl) { \
- (cdb)->xfer_length = tl; \
-}
-
-/*
- * SCSI sense data format
- */
-struct scsi_sense_s{
-#ifdef __BIGENDIAN
- u8 valid:1;
- u8 rsp_code:7;
-#else
- u8 rsp_code:7;
- u8 valid:1;
-#endif
- u8 seg_num;
-#ifdef __BIGENDIAN
- u8 file_mark:1;
- u8 eom:1; /* end of media */
- u8 ili:1; /* incorrect length indicator */
- u8 reserved:1;
- u8 sense_key:4;
-#else
- u8 sense_key:4;
- u8 reserved:1;
- u8 ili:1; /* incorrect length indicator */
- u8 eom:1; /* end of media */
- u8 file_mark:1;
-#endif
- u8 information[4]; /* device-type or command specific info
- */
- u8 add_sense_length;
- /* additional sense length */
- u8 command_info[4];/* command specific information
- */
- u8 asc; /* additional sense code */
- u8 ascq; /* additional sense code qualifier */
- u8 fru_code; /* field replaceable unit code */
-#ifdef __BIGENDIAN
- u8 sksv:1; /* sense key specific valid */
- u8 c_d:1; /* command/data bit */
- u8 res1:2;
- u8 bpv:1; /* bit pointer valid */
- u8 bpointer:3; /* bit pointer */
-#else
- u8 bpointer:3; /* bit pointer */
- u8 bpv:1; /* bit pointer valid */
- u8 res1:2;
- u8 c_d:1; /* command/data bit */
- u8 sksv:1; /* sense key specific valid */
-#endif
- u8 fpointer[2]; /* field pointer */
-};
-
-#define SCSI_SENSE_CUR_ERR 0x70
-#define SCSI_SENSE_DEF_ERR 0x71
-
-/*
- * SCSI sense key values
- */
-#define SCSI_SK_NO_SENSE 0x0
-#define SCSI_SK_REC_ERR 0x1 /* recovered error */
-#define SCSI_SK_NOT_READY 0x2
-#define SCSI_SK_MED_ERR 0x3 /* medium error */
-#define SCSI_SK_HW_ERR 0x4 /* hardware error */
-#define SCSI_SK_ILLEGAL_REQ 0x5
-#define SCSI_SK_UNIT_ATT 0x6 /* unit attention */
-#define SCSI_SK_DATA_PROTECT 0x7
-#define SCSI_SK_BLANK_CHECK 0x8
-#define SCSI_SK_VENDOR_SPEC 0x9
-#define SCSI_SK_COPY_ABORTED 0xA
-#define SCSI_SK_ABORTED_CMND 0xB
-#define SCSI_SK_VOL_OVERFLOW 0xD
-#define SCSI_SK_MISCOMPARE 0xE
-
-/*
- * SCSI additional sense codes
- */
-#define SCSI_ASC_NO_ADD_SENSE 0x00
-#define SCSI_ASC_LUN_NOT_READY 0x04
-#define SCSI_ASC_LUN_COMMUNICATION 0x08
-#define SCSI_ASC_WRITE_ERROR 0x0C
-#define SCSI_ASC_INVALID_CMND_CODE 0x20
-#define SCSI_ASC_BAD_LBA 0x21
-#define SCSI_ASC_INVALID_FIELD_IN_CDB 0x24
-#define SCSI_ASC_LUN_NOT_SUPPORTED 0x25
-#define SCSI_ASC_LUN_WRITE_PROTECT 0x27
-#define SCSI_ASC_POWERON_BDR 0x29 /* power on reset, bus reset,
- * bus device reset
- */
-#define SCSI_ASC_PARAMS_CHANGED 0x2A
-#define SCSI_ASC_CMND_CLEARED_BY_A_I 0x2F
-#define SCSI_ASC_SAVING_PARAM_NOTSUPP 0x39
-#define SCSI_ASC_TOCC 0x3F /* target operating condtions
- * changed
- */
-#define SCSI_ASC_PARITY_ERROR 0x47
-#define SCSI_ASC_CMND_PHASE_ERROR 0x4A
-#define SCSI_ASC_DATA_PHASE_ERROR 0x4B
-#define SCSI_ASC_VENDOR_SPEC 0x7F
-
-/*
- * SCSI additional sense code qualifiers
- */
-#define SCSI_ASCQ_CAUSE_NOT_REPORT 0x00
-#define SCSI_ASCQ_BECOMING_READY 0x01
-#define SCSI_ASCQ_INIT_CMD_REQ 0x02
-#define SCSI_ASCQ_FORMAT_IN_PROGRESS 0x04
-#define SCSI_ASCQ_OPERATION_IN_PROGRESS 0x07
-#define SCSI_ASCQ_SELF_TEST_IN_PROGRESS 0x09
-#define SCSI_ASCQ_WR_UNEXP_UNSOL_DATA 0x0C
-#define SCSI_ASCQ_WR_NOTENG_UNSOL_DATA 0x0D
-
-#define SCSI_ASCQ_LBA_OUT_OF_RANGE 0x00
-#define SCSI_ASCQ_INVALID_ELEMENT_ADDR 0x01
-
-#define SCSI_ASCQ_LUN_WRITE_PROTECTED 0x00
-#define SCSI_ASCQ_LUN_HW_WRITE_PROTECTED 0x01
-#define SCSI_ASCQ_LUN_SW_WRITE_PROTECTED 0x02
-
-#define SCSI_ASCQ_POR 0x01 /* power on reset */
-#define SCSI_ASCQ_SBR 0x02 /* scsi bus reset */
-#define SCSI_ASCQ_BDR 0x03 /* bus device reset */
-#define SCSI_ASCQ_DIR 0x04 /* device internal reset */
-
-#define SCSI_ASCQ_MODE_PARAMS_CHANGED 0x01
-#define SCSI_ASCQ_LOG_PARAMS_CHANGED 0x02
-#define SCSI_ASCQ_RESERVATIONS_PREEMPTED 0x03
-#define SCSI_ASCQ_RESERVATIONS_RELEASED 0x04
-#define SCSI_ASCQ_REGISTRATIONS_PREEMPTED 0x05
-
-#define SCSI_ASCQ_MICROCODE_CHANGED 0x01
-#define SCSI_ASCQ_CHANGED_OPER_COND 0x02
-#define SCSI_ASCQ_INQ_CHANGED 0x03 /* inquiry data changed */
-#define SCSI_ASCQ_DI_CHANGED 0x05 /* device id changed */
-#define SCSI_ASCQ_RL_DATA_CHANGED 0x0E /* report luns data changed */
-
-#define SCSI_ASCQ_DP_CRC_ERR 0x01 /* data phase crc error */
-#define SCSI_ASCQ_DP_SCSI_PARITY_ERR 0x02 /* data phase scsi parity error
- */
-#define SCSI_ASCQ_IU_CRC_ERR 0x03 /* information unit crc error */
-#define SCSI_ASCQ_PROTO_SERV_CRC_ERR 0x05
-
-#define SCSI_ASCQ_LUN_TIME_OUT 0x01
-
-/* ------------------------------------------------------------
- * SCSI INQUIRY
- * ------------------------------------------------------------*/
-
-struct scsi_inquiry_s{
- u8 opcode;
-#ifdef __BIGENDIAN
- u8 lun:3;
- u8 reserved1:3;
- u8 cmd_dt:1;
- u8 evpd:1;
-#else
- u8 evpd:1;
- u8 cmd_dt:1;
- u8 reserved1:3;
- u8 lun:3;
-#endif
- u8 page_code;
- u8 reserved2;
- u8 alloc_length;
- u8 control;
-};
-
-struct scsi_inquiry_vendor_s{
- u8 vendor_id[8];
-};
-
-struct scsi_inquiry_prodid_s{
- u8 product_id[16];
-};
-
-struct scsi_inquiry_prodrev_s{
- u8 product_rev[4];
-};
-
-struct scsi_inquiry_data_s{
-#ifdef __BIGENDIAN
- u8 peripheral_qual:3; /* peripheral qualifier */
- u8 device_type:5; /* peripheral device type */
-
- u8 rmb:1; /* removable medium bit */
- u8 device_type_mod:7; /* device type modifier */
-
- u8 version;
-
- u8 aenc:1; /* async event notification capability
- */
- u8 trm_iop:1; /* terminate I/O process */
- u8 norm_aca:1; /* normal ACA supported */
- u8 hi_support:1; /* SCSI-3: supports REPORT LUNS */
- u8 rsp_data_format:4;
-
- u8 additional_len;
- u8 sccs:1;
- u8 reserved1:7;
-
- u8 reserved2:1;
- u8 enc_serv:1; /* enclosure service component */
- u8 reserved3:1;
- u8 multi_port:1; /* multi-port device */
- u8 m_chngr:1; /* device in medium transport element */
- u8 ack_req_q:1; /* SIP specific bit */
- u8 addr32:1; /* SIP specific bit */
- u8 addr16:1; /* SIP specific bit */
-
- u8 rel_adr:1; /* relative address */
- u8 w_bus32:1;
- u8 w_bus16:1;
- u8 synchronous:1;
- u8 linked_commands:1;
- u8 trans_dis:1;
- u8 cmd_queue:1; /* command queueing supported */
- u8 soft_reset:1; /* soft reset alternative (VS) */
-#else
- u8 device_type:5; /* peripheral device type */
- u8 peripheral_qual:3;
- /* peripheral qualifier */
-
- u8 device_type_mod:7;
- /* device type modifier */
- u8 rmb:1; /* removable medium bit */
-
- u8 version;
-
- u8 rsp_data_format:4;
- u8 hi_support:1; /* SCSI-3: supports REPORT LUNS */
- u8 norm_aca:1; /* normal ACA supported */
- u8 terminate_iop:1;/* terminate I/O process */
- u8 aenc:1; /* async event notification capability
- */
-
- u8 additional_len;
- u8 reserved1:7;
- u8 sccs:1;
-
- u8 addr16:1; /* SIP specific bit */
- u8 addr32:1; /* SIP specific bit */
- u8 ack_req_q:1; /* SIP specific bit */
- u8 m_chngr:1; /* device in medium transport element */
- u8 multi_port:1; /* multi-port device */
- u8 reserved3:1; /* TBD - Vendor Specific */
- u8 enc_serv:1; /* enclosure service component */
- u8 reserved2:1;
-
- u8 soft_seset:1; /* soft reset alternative (VS) */
- u8 cmd_queue:1; /* command queueing supported */
- u8 trans_dis:1;
- u8 linked_commands:1;
- u8 synchronous:1;
- u8 w_bus16:1;
- u8 w_bus32:1;
- u8 rel_adr:1; /* relative address */
-#endif
- struct scsi_inquiry_vendor_s vendor_id;
- struct scsi_inquiry_prodid_s product_id;
- struct scsi_inquiry_prodrev_s product_rev;
- u8 vendor_specific[20];
- u8 reserved4[40];
-};
-
-/*
- * inquiry.peripheral_qual field values
- */
-#define SCSI_DEVQUAL_DEFAULT 0
-#define SCSI_DEVQUAL_NOT_CONNECTED 1
-#define SCSI_DEVQUAL_NOT_SUPPORTED 3
-
-/*
- * inquiry.device_type field values
- */
-#define SCSI_DEVICE_DIRECT_ACCESS 0x00
-#define SCSI_DEVICE_SEQ_ACCESS 0x01
-#define SCSI_DEVICE_ARRAY_CONTROLLER 0x0C
-#define SCSI_DEVICE_UNKNOWN 0x1F
-
-/*
- * inquiry.version
- */
-#define SCSI_VERSION_ANSI_X3131 2 /* ANSI X3.131 SCSI-2 */
-#define SCSI_VERSION_SPC 3 /* SPC (SCSI-3), ANSI X3.301:1997 */
-#define SCSI_VERSION_SPC_2 4 /* SPC-2 */
-
-/*
- * response data format
- */
-#define SCSI_RSP_DATA_FORMAT 2 /* SCSI-2 & SPC */
-
-/*
- * SCSI inquiry page codes
- */
-#define SCSI_INQ_PAGE_VPD_PAGES 0x00 /* supported vpd pages */
-#define SCSI_INQ_PAGE_USN_PAGE 0x80 /* unit serial number page */
-#define SCSI_INQ_PAGE_DEV_IDENT 0x83 /* device indentification page
- */
-#define SCSI_INQ_PAGES_MAX 3
-
-/*
- * supported vital product data pages
- */
-struct scsi_inq_page_vpd_pages_s{
-#ifdef __BIGENDIAN
- u8 peripheral_qual:3;
- u8 device_type:5;
-#else
- u8 device_type:5;
- u8 peripheral_qual:3;
-#endif
- u8 page_code;
- u8 reserved;
- u8 page_length;
- u8 pages[SCSI_INQ_PAGES_MAX];
-};
-
-/*
- * Unit serial number page
- */
-#define SCSI_INQ_USN_LEN 32
-
-struct scsi_inq_usn_s{
- char usn[SCSI_INQ_USN_LEN];
-};
-
-struct scsi_inq_page_usn_s{
-#ifdef __BIGENDIAN
- u8 peripheral_qual:3;
- u8 device_type:5;
-#else
- u8 device_type:5;
- u8 peripheral_qual:3;
-#endif
- u8 page_code;
- u8 reserved1;
- u8 page_length;
- struct scsi_inq_usn_s usn;
-};
-
-enum {
- SCSI_INQ_DIP_CODE_BINARY = 1, /* identifier has binary value */
- SCSI_INQ_DIP_CODE_ASCII = 2, /* identifier has ascii value */
-};
-
-enum {
- SCSI_INQ_DIP_ASSOC_LUN = 0, /* id is associated with device */
- SCSI_INQ_DIP_ASSOC_PORT = 1, /* id is associated with port that
- * received the request
- */
-};
-
-enum {
- SCSI_INQ_ID_TYPE_VENDOR = 1,
- SCSI_INQ_ID_TYPE_IEEE = 2,
- SCSI_INQ_ID_TYPE_FC_FS = 3,
- SCSI_INQ_ID_TYPE_OTHER = 4,
-};
-
-struct scsi_inq_dip_desc_s{
-#ifdef __BIGENDIAN
- u8 res0:4;
- u8 code_set:4;
- u8 res1:2;
- u8 association:2;
- u8 id_type:4;
-#else
- u8 code_set:4;
- u8 res0:4;
- u8 id_type:4;
- u8 association:2;
- u8 res1:2;
-#endif
- u8 res2;
- u8 id_len;
- struct scsi_lun_sn_s id;
-};
-
-/*
- * Device indentification page
- */
-struct scsi_inq_page_dev_ident_s{
-#ifdef __BIGENDIAN
- u8 peripheral_qual:3;
- u8 device_type:5;
-#else
- u8 device_type:5;
- u8 peripheral_qual:3;
-#endif
- u8 page_code;
- u8 reserved1;
- u8 page_length;
- struct scsi_inq_dip_desc_s desc;
-};
-
-/* ------------------------------------------------------------
- * READ CAPACITY
- * ------------------------------------------------------------
- */
-
-struct scsi_read_capacity_s{
- u8 opcode;
-#ifdef __BIGENDIAN
- u8 lun:3;
- u8 reserved1:4;
- u8 rel_adr:1;
-#else
- u8 rel_adr:1;
- u8 reserved1:4;
- u8 lun:3;
-#endif
- u8 lba0; /* MSB */
- u8 lba1;
- u8 lba2;
- u8 lba3; /* LSB */
- u8 reserved2;
- u8 reserved3;
-#ifdef __BIGENDIAN
- u8 reserved4:7;
- u8 pmi:1; /* partial medium indicator */
-#else
- u8 pmi:1; /* partial medium indicator */
- u8 reserved4:7;
-#endif
- u8 control;
-};
-
-struct scsi_read_capacity_data_s{
- u32 max_lba; /* maximum LBA available */
- u32 block_length; /* in bytes */
-};
-
-struct scsi_read_capacity16_data_s{
- u64 lba; /* maximum LBA available */
- u32 block_length; /* in bytes */
-#ifdef __BIGENDIAN
- u8 reserved1:4,
- p_type:3,
- prot_en:1;
- u8 reserved2:4,
- lb_pbe:4; /* logical blocks per physical block
- * exponent */
- u16 reserved3:2,
- lba_align:14; /* lowest aligned logical block
- * address */
-#else
- u16 lba_align:14, /* lowest aligned logical block
- * address */
- reserved3:2;
- u8 lb_pbe:4, /* logical blocks per physical block
- * exponent */
- reserved2:4;
- u8 prot_en:1,
- p_type:3,
- reserved1:4;
-#endif
- u64 reserved4;
- u64 reserved5;
-};
-
-/* ------------------------------------------------------------
- * REPORT LUNS command
- * ------------------------------------------------------------
- */
-
-struct scsi_report_luns_s{
- u8 opcode; /* A0h - REPORT LUNS opCode */
- u8 reserved1[5];
- u8 alloc_length[4];/* allocation length MSB first */
- u8 reserved2;
- u8 control;
-};
-
-#define SCSI_REPORT_LUN_ALLOC_LENGTH(rl) \
- ((rl->alloc_length[0] << 24) | (rl->alloc_length[1] << 16) | \
- (rl->alloc_length[2] << 8) | (rl->alloc_length[3]))
-
-#define SCSI_REPORT_LUNS_SET_ALLOCLEN(rl, alloc_len) { \
- (rl)->alloc_length[0] = (alloc_len) >> 24; \
- (rl)->alloc_length[1] = ((alloc_len) >> 16) & 0xFF; \
- (rl)->alloc_length[2] = ((alloc_len) >> 8) & 0xFF; \
- (rl)->alloc_length[3] = (alloc_len) & 0xFF; \
-}
-
-struct scsi_report_luns_data_s{
- u32 lun_list_length; /* length of LUN list length */
- u32 reserved;
- lun_t lun[1]; /* first LUN in lun list */
-};
-
-/* -------------------------------------------------------------
- * SCSI mode parameters
- * -----------------------------------------------------------
- */
-enum {
- SCSI_DA_MEDIUM_DEF = 0, /* direct access default medium type */
- SCSI_DA_MEDIUM_SS = 1, /* direct access single sided */
- SCSI_DA_MEDIUM_DS = 2, /* direct access double sided */
-};
-
-/*
- * SCSI Mode Select(6) cdb
- */
-struct scsi_mode_select6_s{
- u8 opcode;
-#ifdef __BIGENDIAN
- u8 reserved1:3;
- u8 pf:1; /* page format */
- u8 reserved2:3;
- u8 sp:1; /* save pages if set to 1 */
-#else
- u8 sp:1; /* save pages if set to 1 */
- u8 reserved2:3;
- u8 pf:1; /* page format */
- u8 reserved1:3;
-#endif
- u8 reserved3[2];
- u8 alloc_len;
- u8 control;
-};
-
-/*
- * SCSI Mode Select(10) cdb
- */
-struct scsi_mode_select10_s{
- u8 opcode;
-#ifdef __BIGENDIAN
- u8 reserved1:3;
- u8 pf:1; /* page format */
- u8 reserved2:3;
- u8 sp:1; /* save pages if set to 1 */
-#else
- u8 sp:1; /* save pages if set to 1 */
- u8 reserved2:3;
- u8 pf:1; /* page format */
- u8 reserved1:3;
-#endif
- u8 reserved3[5];
- u8 alloc_len_msb;
- u8 alloc_len_lsb;
- u8 control;
-};
-
-/*
- * SCSI Mode Sense(6) cdb
- */
-struct scsi_mode_sense6_s{
- u8 opcode;
-#ifdef __BIGENDIAN
- u8 reserved1:4;
- u8 dbd:1; /* disable block discriptors if set to 1 */
- u8 reserved2:3;
-
- u8 pc:2; /* page control */
- u8 page_code:6;
-#else
- u8 reserved2:3;
- u8 dbd:1; /* disable block descriptors if set to 1 */
- u8 reserved1:4;
-
- u8 page_code:6;
- u8 pc:2; /* page control */
-#endif
- u8 reserved3;
- u8 alloc_len;
- u8 control;
-};
-
-/*
- * SCSI Mode Sense(10) cdb
- */
-struct scsi_mode_sense10_s{
- u8 opcode;
-#ifdef __BIGENDIAN
- u8 reserved1:3;
- u8 LLBAA:1; /* long LBA accepted if set to 1 */
- u8 dbd:1; /* disable block descriptors if set
- * to 1
- */
- u8 reserved2:3;
-
- u8 pc:2; /* page control */
- u8 page_code:6;
-#else
- u8 reserved2:3;
- u8 dbd:1; /* disable block descriptors if set to
- * 1
- */
- u8 LLBAA:1; /* long LBA accepted if set to 1 */
- u8 reserved1:3;
-
- u8 page_code:6;
- u8 pc:2; /* page control */
-#endif
- u8 reserved3[4];
- u8 alloc_len_msb;
- u8 alloc_len_lsb;
- u8 control;
-};
-
-#define SCSI_CDB10_GET_AL(cdb) \
- ((cdb)->alloc_len_msb << 8 | (cdb)->alloc_len_lsb)
-
-#define SCSI_CDB10_SET_AL(cdb, al) { \
- (cdb)->alloc_len_msb = al >> 8; \
- (cdb)->alloc_len_lsb = al & 0xFF; \
-}
-
-#define SCSI_CDB6_GET_AL(cdb) ((cdb)->alloc_len)
-
-#define SCSI_CDB6_SET_AL(cdb, al) { \
- (cdb)->alloc_len = al; \
-}
-
-/*
- * page control field values
- */
-#define SCSI_PC_CURRENT_VALUES 0x0
-#define SCSI_PC_CHANGEABLE_VALUES 0x1
-#define SCSI_PC_DEFAULT_VALUES 0x2
-#define SCSI_PC_SAVED_VALUES 0x3
-
-/*
- * SCSI mode page codes
- */
-#define SCSI_MP_VENDOR_SPEC 0x00
-#define SCSI_MP_DISC_RECN 0x02 /* disconnect-reconnect page */
-#define SCSI_MP_FORMAT_DEVICE 0x03
-#define SCSI_MP_RDG 0x04 /* rigid disk geometry page */
-#define SCSI_MP_FDP 0x05 /* flexible disk page */
-#define SCSI_MP_CACHING 0x08 /* caching page */
-#define SCSI_MP_CONTROL 0x0A /* control mode page */
-#define SCSI_MP_MED_TYPES_SUP 0x0B /* medium types supported page */
-#define SCSI_MP_INFO_EXCP_CNTL 0x1C /* informational exception control */
-#define SCSI_MP_ALL 0x3F /* return all pages - mode sense only */
-
-/*
- * mode parameter header
- */
-struct scsi_mode_param_header6_s{
- u8 mode_datalen;
- u8 medium_type;
-
- /*
- * device specific parameters expanded for direct access devices
- */
-#ifdef __BIGENDIAN
- u32 wp:1; /* write protected */
- u32 reserved1:2;
- u32 dpofua:1; /* disable page out + force unit access
- */
- u32 reserved2:4;
-#else
- u32 reserved2:4;
- u32 dpofua:1; /* disable page out + force unit access
- */
- u32 reserved1:2;
- u32 wp:1; /* write protected */
-#endif
-
- u8 block_desclen;
-};
-
-struct scsi_mode_param_header10_s{
- u32 mode_datalen:16;
- u32 medium_type:8;
-
- /*
- * device specific parameters expanded for direct access devices
- */
-#ifdef __BIGENDIAN
- u32 wp:1; /* write protected */
- u32 reserved1:2;
- u32 dpofua:1; /* disable page out + force unit access
- */
- u32 reserved2:4;
-#else
- u32 reserved2:4;
- u32 dpofua:1; /* disable page out + force unit access
- */
- u32 reserved1:2;
- u32 wp:1; /* write protected */
-#endif
-
-#ifdef __BIGENDIAN
- u32 reserved3:7;
- u32 longlba:1;
-#else
- u32 longlba:1;
- u32 reserved3:7;
-#endif
- u32 reserved4:8;
- u32 block_desclen:16;
-};
-
-/*
- * mode parameter block descriptor
- */
-struct scsi_mode_param_desc_s{
- u32 nblks;
- u32 density_code:8;
- u32 block_length:24;
-};
-
-/*
- * Disconnect-reconnect mode page format
- */
-struct scsi_mp_disc_recn_s{
-#ifdef __BIGENDIAN
- u8 ps:1;
- u8 reserved1:1;
- u8 page_code:6;
-#else
- u8 page_code:6;
- u8 reserved1:1;
- u8 ps:1;
-#endif
- u8 page_len;
- u8 buf_full_ratio;
- u8 buf_empty_ratio;
-
- u8 bil_msb; /* bus inactivity limit -MSB */
- u8 bil_lsb; /* bus inactivity limit -LSB */
-
- u8 dtl_msb; /* disconnect time limit - MSB */
- u8 dtl_lsb; /* disconnect time limit - LSB */
-
- u8 ctl_msb; /* connect time limit - MSB */
- u8 ctl_lsb; /* connect time limit - LSB */
-
- u8 max_burst_len_msb;
- u8 max_burst_len_lsb;
-#ifdef __BIGENDIAN
- u8 emdp:1; /* enable modify data pointers */
- u8 fa:3; /* fair arbitration */
- u8 dimm:1; /* disconnect immediate */
- u8 dtdc:3; /* data transfer disconnect control */
-#else
- u8 dtdc:3; /* data transfer disconnect control */
- u8 dimm:1; /* disconnect immediate */
- u8 fa:3; /* fair arbitration */
- u8 emdp:1; /* enable modify data pointers */
-#endif
-
- u8 reserved3;
-
- u8 first_burst_len_msb;
- u8 first_burst_len_lsb;
-};
-
-/*
- * SCSI format device mode page
- */
-struct scsi_mp_format_device_s{
-#ifdef __BIGENDIAN
- u32 ps:1;
- u32 reserved1:1;
- u32 page_code:6;
-#else
- u32 page_code:6;
- u32 reserved1:1;
- u32 ps:1;
-#endif
- u32 page_len:8;
- u32 tracks_per_zone:16;
-
- u32 a_sec_per_zone:16;
- u32 a_tracks_per_zone:16;
-
- u32 a_tracks_per_lun:16; /* alternate tracks/lun-MSB */
- u32 sec_per_track:16; /* sectors/track-MSB */
-
- u32 bytes_per_sector:16;
- u32 interleave:16;
-
- u32 tsf:16; /* track skew factor-MSB */
- u32 csf:16; /* cylinder skew factor-MSB */
-
-#ifdef __BIGENDIAN
- u32 ssec:1; /* soft sector formatting */
- u32 hsec:1; /* hard sector formatting */
- u32 rmb:1; /* removable media */
- u32 surf:1; /* surface */
- u32 reserved2:4;
-#else
- u32 reserved2:4;
- u32 surf:1; /* surface */
- u32 rmb:1; /* removable media */
- u32 hsec:1; /* hard sector formatting */
- u32 ssec:1; /* soft sector formatting */
-#endif
- u32 reserved3:24;
-};
-
-/*
- * SCSI rigid disk device geometry page
- */
-struct scsi_mp_rigid_device_geometry_s{
-#ifdef __BIGENDIAN
- u32 ps:1;
- u32 reserved1:1;
- u32 page_code:6;
-#else
- u32 page_code:6;
- u32 reserved1:1;
- u32 ps:1;
-#endif
- u32 page_len:8;
- u32 num_cylinders0:8;
- u32 num_cylinders1:8;
-
- u32 num_cylinders2:8;
- u32 num_heads:8;
- u32 scwp0:8;
- u32 scwp1:8;
-
- u32 scwp2:8;
- u32 scrwc0:8;
- u32 scrwc1:8;
- u32 scrwc2:8;
-
- u32 dsr:16;
- u32 lscyl0:8;
- u32 lscyl1:8;
-
- u32 lscyl2:8;
-#ifdef __BIGENDIAN
- u32 reserved2:6;
- u32 rpl:2; /* rotational position locking */
-#else
- u32 rpl:2; /* rotational position locking */
- u32 reserved2:6;
-#endif
- u32 rot_off:8;
- u32 reserved3:8;
-
- u32 med_rot_rate:16;
- u32 reserved4:16;
-};
-
-/*
- * SCSI caching mode page
- */
-struct scsi_mp_caching_s{
-#ifdef __BIGENDIAN
- u8 ps:1;
- u8 res1:1;
- u8 page_code:6;
-#else
- u8 page_code:6;
- u8 res1:1;
- u8 ps:1;
-#endif
- u8 page_len;
-#ifdef __BIGENDIAN
- u8 ic:1; /* initiator control */
- u8 abpf:1; /* abort pre-fetch */
- u8 cap:1; /* caching analysis permitted */
- u8 disc:1; /* discontinuity */
- u8 size:1; /* size enable */
- u8 wce:1; /* write cache enable */
- u8 mf:1; /* multiplication factor */
- u8 rcd:1; /* read cache disable */
-
- u8 drrp:4; /* demand read retention priority */
- u8 wrp:4; /* write retention priority */
-#else
- u8 rcd:1; /* read cache disable */
- u8 mf:1; /* multiplication factor */
- u8 wce:1; /* write cache enable */
- u8 size:1; /* size enable */
- u8 disc:1; /* discontinuity */
- u8 cap:1; /* caching analysis permitted */
- u8 abpf:1; /* abort pre-fetch */
- u8 ic:1; /* initiator control */
-
- u8 wrp:4; /* write retention priority */
- u8 drrp:4; /* demand read retention priority */
-#endif
- u8 dptl[2];/* disable pre-fetch transfer length */
- u8 min_prefetch[2];
- u8 max_prefetch[2];
- u8 max_prefetch_limit[2];
-#ifdef __BIGENDIAN
- u8 fsw:1; /* force sequential write */
- u8 lbcss:1;/* logical block cache segment size */
- u8 dra:1; /* disable read ahead */
- u8 vs:2; /* vendor specific */
- u8 res2:3;
-#else
- u8 res2:3;
- u8 vs:2; /* vendor specific */
- u8 dra:1; /* disable read ahead */
- u8 lbcss:1;/* logical block cache segment size */
- u8 fsw:1; /* force sequential write */
-#endif
- u8 num_cache_segs;
-
- u8 cache_seg_size[2];
- u8 res3;
- u8 non_cache_seg_size[3];
-};
-
-/*
- * SCSI control mode page
- */
-struct scsi_mp_control_page_s{
-#ifdef __BIGENDIAN
-u8 ps:1;
-u8 reserved1:1;
-u8 page_code:6;
-#else
-u8 page_code:6;
-u8 reserved1:1;
-u8 ps:1;
-#endif
- u8 page_len;
-#ifdef __BIGENDIAN
- u8 tst:3; /* task set type */
- u8 reserved3:3;
- u8 gltsd:1; /* global logging target save disable */
- u8 rlec:1; /* report log exception condition */
-
- u8 qalgo_mod:4; /* queue alogorithm modifier */
- u8 reserved4:1;
- u8 qerr:2; /* queue error management */
- u8 dque:1; /* disable queuing */
-
- u8 reserved5:1;
- u8 rac:1; /* report a check */
- u8 reserved6:2;
- u8 swp:1; /* software write protect */
- u8 raerp:1; /* ready AER permission */
- u8 uaaerp:1; /* unit attenstion AER permission */
- u8 eaerp:1; /* error AER permission */
-
- u8 reserved7:5;
- u8 autoload_mod:3;
-#else
- u8 rlec:1; /* report log exception condition */
- u8 gltsd:1; /* global logging target save disable */
- u8 reserved3:3;
- u8 tst:3; /* task set type */
-
- u8 dque:1; /* disable queuing */
- u8 qerr:2; /* queue error management */
- u8 reserved4:1;
- u8 qalgo_mod:4; /* queue alogorithm modifier */
-
- u8 eaerp:1; /* error AER permission */
- u8 uaaerp:1; /* unit attenstion AER permission */
- u8 raerp:1; /* ready AER permission */
- u8 swp:1; /* software write protect */
- u8 reserved6:2;
- u8 rac:1; /* report a check */
- u8 reserved5:1;
-
- u8 autoload_mod:3;
- u8 reserved7:5;
-#endif
- u8 rahp_msb; /* ready AER holdoff period - MSB */
- u8 rahp_lsb; /* ready AER holdoff period - LSB */
-
- u8 busy_timeout_period_msb;
- u8 busy_timeout_period_lsb;
-
- u8 ext_selftest_compl_time_msb;
- u8 ext_selftest_compl_time_lsb;
-};
-
-/*
- * SCSI medium types supported mode page
- */
-struct scsi_mp_medium_types_sup_s{
-#ifdef __BIGENDIAN
- u8 ps:1;
- u8 reserved1:1;
- u8 page_code:6;
-#else
- u8 page_code:6;
- u8 reserved1:1;
- u8 ps:1;
-#endif
- u8 page_len;
-
- u8 reserved3[2];
- u8 med_type1_sup; /* medium type one supported */
- u8 med_type2_sup; /* medium type two supported */
- u8 med_type3_sup; /* medium type three supported */
- u8 med_type4_sup; /* medium type four supported */
-};
-
-/*
- * SCSI informational exception control mode page
- */
-struct scsi_mp_info_excpt_cntl_s{
-#ifdef __BIGENDIAN
- u8 ps:1;
- u8 reserved1:1;
- u8 page_code:6;
-#else
- u8 page_code:6;
- u8 reserved1:1;
- u8 ps:1;
-#endif
- u8 page_len;
-#ifdef __BIGENDIAN
- u8 perf:1; /* performance */
- u8 reserved3:1;
- u8 ebf:1; /* enable background fucntion */
- u8 ewasc:1; /* enable warning */
- u8 dexcpt:1; /* disable exception control */
- u8 test:1; /* enable test device failure
- * notification
- */
- u8 reserved4:1;
- u8 log_error:1;
-
- u8 reserved5:4;
- u8 mrie:4; /* method of reporting info
- * exceptions
- */
-#else
- u8 log_error:1;
- u8 reserved4:1;
- u8 test:1; /* enable test device failure
- * notification
- */
- u8 dexcpt:1; /* disable exception control */
- u8 ewasc:1; /* enable warning */
- u8 ebf:1; /* enable background fucntion */
- u8 reserved3:1;
- u8 perf:1; /* performance */
-
- u8 mrie:4; /* method of reporting info
- * exceptions
- */
- u8 reserved5:4;
-#endif
- u8 interval_timer_msb;
- u8 interval_timer_lsb;
-
- u8 report_count_msb;
- u8 report_count_lsb;
-};
-
-/*
- * Methods of reporting informational exceptions
- */
-#define SCSI_MP_IEC_NO_REPORT 0x0 /* no reporting of exceptions */
-#define SCSI_MP_IEC_AER 0x1 /* async event reporting */
-#define SCSI_MP_IEC_UNIT_ATTN 0x2 /* generate unit attenstion */
-#define SCSI_MO_IEC_COND_REC_ERR 0x3 /* conditionally generate recovered
- * error
- */
-#define SCSI_MP_IEC_UNCOND_REC_ERR 0x4 /* unconditionally generate recovered
- * error
- */
-#define SCSI_MP_IEC_NO_SENSE 0x5 /* generate no sense */
-#define SCSI_MP_IEC_ON_REQUEST 0x6 /* only report exceptions on request */
-
-/*
- * SCSI flexible disk page
- */
-struct scsi_mp_flexible_disk_s{
-#ifdef __BIGENDIAN
- u8 ps:1;
- u8 reserved1:1;
- u8 page_code:6;
-#else
- u8 page_code:6;
- u8 reserved1:1;
- u8 ps:1;
-#endif
- u8 page_len;
-
- u8 transfer_rate_msb;
- u8 transfer_rate_lsb;
-
- u8 num_heads;
- u8 num_sectors;
-
- u8 bytes_per_sector_msb;
- u8 bytes_per_sector_lsb;
-
- u8 num_cylinders_msb;
- u8 num_cylinders_lsb;
-
- u8 sc_wpc_msb; /* starting cylinder-write
- * precompensation msb
- */
- u8 sc_wpc_lsb; /* starting cylinder-write
- * precompensation lsb
- */
- u8 sc_rwc_msb; /* starting cylinder-reduced write
- * current msb
- */
- u8 sc_rwc_lsb; /* starting cylinder-reduced write
- * current lsb
- */
-
- u8 dev_step_rate_msb;
- u8 dev_step_rate_lsb;
-
- u8 dev_step_pulse_width;
-
- u8 head_sd_msb; /* head settle delay msb */
- u8 head_sd_lsb; /* head settle delay lsb */
-
- u8 motor_on_delay;
- u8 motor_off_delay;
-#ifdef __BIGENDIAN
- u8 trdy:1; /* true ready bit */
- u8 ssn:1; /* start sector number bit */
- u8 mo:1; /* motor on bit */
- u8 reserved3:5;
-
- u8 reserved4:4;
- u8 spc:4; /* step pulse per cylinder */
-#else
- u8 reserved3:5;
- u8 mo:1; /* motor on bit */
- u8 ssn:1; /* start sector number bit */
- u8 trdy:1; /* true ready bit */
-
- u8 spc:4; /* step pulse per cylinder */
- u8 reserved4:4;
-#endif
- u8 write_comp;
- u8 head_load_delay;
- u8 head_unload_delay;
-#ifdef __BIGENDIAN
- u8 pin34:4; /* pin34 usage */
- u8 pin2:4; /* pin2 usage */
-
- u8 pin4:4; /* pin4 usage */
- u8 pin1:4; /* pin1 usage */
-#else
- u8 pin2:4; /* pin2 usage */
- u8 pin34:4; /* pin34 usage */
-
- u8 pin1:4; /* pin1 usage */
- u8 pin4:4; /* pin4 usage */
-#endif
- u8 med_rot_rate_msb;
- u8 med_rot_rate_lsb;
-
- u8 reserved5[2];
-};
-
-struct scsi_mode_page_format_data6_s{
- struct scsi_mode_param_header6_s mph; /* mode page header */
- struct scsi_mode_param_desc_s desc; /* block descriptor */
- struct scsi_mp_format_device_s format; /* format device data */
-};
-
-struct scsi_mode_page_format_data10_s{
- struct scsi_mode_param_header10_s mph; /* mode page header */
- struct scsi_mode_param_desc_s desc; /* block descriptor */
- struct scsi_mp_format_device_s format; /* format device data */
-};
-
-struct scsi_mode_page_rdg_data6_s{
- struct scsi_mode_param_header6_s mph; /* mode page header */
- struct scsi_mode_param_desc_s desc; /* block descriptor */
- struct scsi_mp_rigid_device_geometry_s rdg;
- /* rigid geometry data */
-};
-
-struct scsi_mode_page_rdg_data10_s{
- struct scsi_mode_param_header10_s mph; /* mode page header */
- struct scsi_mode_param_desc_s desc; /* block descriptor */
- struct scsi_mp_rigid_device_geometry_s rdg;
- /* rigid geometry data */
-};
-
-struct scsi_mode_page_cache6_s{
- struct scsi_mode_param_header6_s mph; /* mode page header */
- struct scsi_mode_param_desc_s desc; /* block descriptor */
- struct scsi_mp_caching_s cache; /* cache page data */
-};
-
-struct scsi_mode_page_cache10_s{
- struct scsi_mode_param_header10_s mph; /* mode page header */
- struct scsi_mode_param_desc_s desc; /* block descriptor */
- struct scsi_mp_caching_s cache; /* cache page data */
-};
-
-/* --------------------------------------------------------------
- * Format Unit command
- * ------------------------------------------------------------
- */
-
-/*
- * Format Unit CDB
- */
-struct scsi_format_unit_s{
- u8 opcode;
-#ifdef __BIGENDIAN
- u8 res1:3;
- u8 fmtdata:1; /* if set, data out phase has format
- * data
- */
- u8 cmplst:1; /* if set, defect list is complete */
- u8 def_list:3; /* format of defect descriptor is
- * fmtdata =1
- */
-#else
- u8 def_list:3; /* format of defect descriptor is
- * fmtdata = 1
- */
- u8 cmplst:1; /* if set, defect list is complete */
- u8 fmtdata:1; /* if set, data out phase has format
- * data
- */
- u8 res1:3;
-#endif
- u8 interleave_msb;
- u8 interleave_lsb;
- u8 vendor_spec;
- u8 control;
-};
-
-/*
- * h
- */
-struct scsi_reserve6_s{
- u8 opcode;
-#ifdef __BIGENDIAN
- u8 reserved:3;
- u8 obsolete:4;
- u8 extent:1;
-#else
- u8 extent:1;
- u8 obsolete:4;
- u8 reserved:3;
-#endif
- u8 reservation_id;
- u16 param_list_len;
- u8 control;
-};
-
-/*
- * h
- */
-struct scsi_release6_s{
- u8 opcode;
-#ifdef __BIGENDIAN
- u8 reserved1:3;
- u8 obsolete:4;
- u8 extent:1;
-#else
- u8 extent:1;
- u8 obsolete:4;
- u8 reserved1:3;
-#endif
- u8 reservation_id;
- u16 reserved2;
- u8 control;
-};
-
-/*
- * h
- */
-struct scsi_reserve10_s{
- u8 opcode;
-#ifdef __BIGENDIAN
- u8 reserved1:3;
- u8 third_party:1;
- u8 reserved2:2;
- u8 long_id:1;
- u8 extent:1;
-#else
- u8 extent:1;
- u8 long_id:1;
- u8 reserved2:2;
- u8 third_party:1;
- u8 reserved1:3;
-#endif
- u8 reservation_id;
- u8 third_pty_dev_id;
- u8 reserved3;
- u8 reserved4;
- u8 reserved5;
- u16 param_list_len;
- u8 control;
-};
-
-struct scsi_release10_s{
- u8 opcode;
-#ifdef __BIGENDIAN
- u8 reserved1:3;
- u8 third_party:1;
- u8 reserved2:2;
- u8 long_id:1;
- u8 extent:1;
-#else
- u8 extent:1;
- u8 long_id:1;
- u8 reserved2:2;
- u8 third_party:1;
- u8 reserved1:3;
-#endif
- u8 reservation_id;
- u8 third_pty_dev_id;
- u8 reserved3;
- u8 reserved4;
- u8 reserved5;
- u16 param_list_len;
- u8 control;
-};
-
-struct scsi_verify10_s{
- u8 opcode;
-#ifdef __BIGENDIAN
- u8 lun:3;
- u8 dpo:1;
- u8 reserved:2;
- u8 bytchk:1;
- u8 reladdr:1;
-#else
- u8 reladdr:1;
- u8 bytchk:1;
- u8 reserved:2;
- u8 dpo:1;
- u8 lun:3;
-#endif
- u8 lba0;
- u8 lba1;
- u8 lba2;
- u8 lba3;
- u8 reserved1;
- u8 verification_len0;
- u8 verification_len1;
- u8 control_byte;
-};
-
-struct scsi_request_sense_s{
- u8 opcode;
-#ifdef __BIGENDIAN
- u8 lun:3;
- u8 reserved:5;
-#else
- u8 reserved:5;
- u8 lun:3;
-#endif
- u8 reserved0;
- u8 reserved1;
- u8 alloc_len;
- u8 control_byte;
-};
-
-/* ------------------------------------------------------------
- * SCSI status byte values
- * ------------------------------------------------------------
- */
-#define SCSI_STATUS_GOOD 0x00
-#define SCSI_STATUS_CHECK_CONDITION 0x02
-#define SCSI_STATUS_CONDITION_MET 0x04
-#define SCSI_STATUS_BUSY 0x08
-#define SCSI_STATUS_INTERMEDIATE 0x10
-#define SCSI_STATUS_ICM 0x14 /* intermediate condition met */
-#define SCSI_STATUS_RESERVATION_CONFLICT 0x18
-#define SCSI_STATUS_COMMAND_TERMINATED 0x22
-#define SCSI_STATUS_QUEUE_FULL 0x28
-#define SCSI_STATUS_ACA_ACTIVE 0x30
-
-#define SCSI_MAX_ALLOC_LEN 0xFF /* maximum allocarion length
- * in CDBs
- */
-
-#define SCSI_OP_WRITE_VERIFY10 0x2E
-#define SCSI_OP_WRITE_VERIFY12 0xAE
-#define SCSI_OP_UNDEF 0xFF
-
-/*
- * SCSI WRITE-VERIFY(10) command
- */
-struct scsi_write_verify10_s{
- u8 opcode;
-#ifdef __BIGENDIAN
- u8 reserved1:3;
- u8 dpo:1; /* Disable Page Out */
- u8 reserved2:1;
- u8 ebp:1; /* erse by-pass */
- u8 bytchk:1; /* byte check */
- u8 rel_adr:1; /* relative address */
-#else
- u8 rel_adr:1; /* relative address */
- u8 bytchk:1; /* byte check */
- u8 ebp:1; /* erse by-pass */
- u8 reserved2:1;
- u8 dpo:1; /* Disable Page Out */
- u8 reserved1:3;
-#endif
- u8 lba0; /* logical block address - MSB */
- u8 lba1;
- u8 lba2;
- u8 lba3; /* LSB */
- u8 reserved3;
- u8 xfer_length0; /* transfer length in blocks - MSB */
- u8 xfer_length1; /* LSB */
- u8 control;
-};
-
-#pragma pack()
-
-#endif /* __SCSI_H__ */
diff --git a/drivers/scsi/bfa/include/protocol/types.h b/drivers/scsi/bfa/include/protocol/types.h
deleted file mode 100644
index 2875a6cced3b..000000000000
--- a/drivers/scsi/bfa/include/protocol/types.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/**
- * types.h Protocol defined base types
- */
-
-#ifndef __TYPES_H__
-#define __TYPES_H__
-
-#include <bfa_os_inc.h>
-
-#define wwn_t u64
-#define lun_t u64
-
-#define WWN_NULL (0)
-#define FC_SYMNAME_MAX 256 /* max name server symbolic name size */
-#define FC_ALPA_MAX 128
-
-#pragma pack(1)
-
-#define MAC_ADDRLEN (6)
-struct mac_s { u8 mac[MAC_ADDRLEN]; };
-#define mac_t struct mac_s
-
-#pragma pack()
-
-#endif
diff --git a/drivers/scsi/bfa/loop.c b/drivers/scsi/bfa/loop.c
deleted file mode 100644
index f6342efb6a90..000000000000
--- a/drivers/scsi/bfa/loop.c
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/**
- * port_loop.c vport private loop implementation.
- */
-#include <bfa.h>
-#include <bfa_svc.h>
-#include "fcs_lport.h"
-#include "fcs_rport.h"
-#include "fcs_trcmod.h"
-#include "lport_priv.h"
-
-BFA_TRC_FILE(FCS, LOOP);
-
-/**
- * ALPA to LIXA bitmap mapping
- *
- * ALPA 0x00 (Word 0, Bit 30) is invalid for N_Ports. Also Word 0 Bit 31
- * is for L_bit (login required) and is filled as ALPA 0x00 here.
- */
-static const u8 port_loop_alpa_map[] = {
- 0xEF, 0xE8, 0xE4, 0xE2, 0xE1, 0xE0, 0xDC, 0xDA, /* Word 3 Bits 0..7 */
- 0xD9, 0xD6, 0xD5, 0xD4, 0xD3, 0xD2, 0xD1, 0xCE, /* Word 3 Bits 8..15 */
- 0xCD, 0xCC, 0xCB, 0xCA, 0xC9, 0xC7, 0xC6, 0xC5, /* Word 3 Bits 16..23 */
- 0xC3, 0xBC, 0xBA, 0xB9, 0xB6, 0xB5, 0xB4, 0xB3, /* Word 3 Bits 24..31 */
-
- 0xB2, 0xB1, 0xAE, 0xAD, 0xAC, 0xAB, 0xAA, 0xA9, /* Word 2 Bits 0..7 */
- 0xA7, 0xA6, 0xA5, 0xA3, 0x9F, 0x9E, 0x9D, 0x9B, /* Word 2 Bits 8..15 */
- 0x98, 0x97, 0x90, 0x8F, 0x88, 0x84, 0x82, 0x81, /* Word 2 Bits 16..23 */
- 0x80, 0x7C, 0x7A, 0x79, 0x76, 0x75, 0x74, 0x73, /* Word 2 Bits 24..31 */
-
- 0x72, 0x71, 0x6E, 0x6D, 0x6C, 0x6B, 0x6A, 0x69, /* Word 1 Bits 0..7 */
- 0x67, 0x66, 0x65, 0x63, 0x5C, 0x5A, 0x59, 0x56, /* Word 1 Bits 8..15 */
- 0x55, 0x54, 0x53, 0x52, 0x51, 0x4E, 0x4D, 0x4C, /* Word 1 Bits 16..23 */
- 0x4B, 0x4A, 0x49, 0x47, 0x46, 0x45, 0x43, 0x3C, /* Word 1 Bits 24..31 */
-
- 0x3A, 0x39, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, /* Word 0 Bits 0..7 */
- 0x2E, 0x2D, 0x2C, 0x2B, 0x2A, 0x29, 0x27, 0x26, /* Word 0 Bits 8..15 */
- 0x25, 0x23, 0x1F, 0x1E, 0x1D, 0x1B, 0x18, 0x17, /* Word 0 Bits 16..23 */
- 0x10, 0x0F, 0x08, 0x04, 0x02, 0x01, 0x00, 0x00, /* Word 0 Bits 24..31 */
-};
-
-/*
- * Local Functions
- */
-static bfa_status_t bfa_fcs_port_loop_send_plogi(struct bfa_fcs_port_s *port,
- u8 alpa);
-
-static void bfa_fcs_port_loop_plogi_response(void *fcsarg,
- struct bfa_fcxp_s *fcxp,
- void *cbarg,
- bfa_status_t req_status,
- u32 rsp_len,
- u32 resid_len,
- struct fchs_s *rsp_fchs);
-/**
- * Called by port to initializar in provate LOOP topology.
- */
-void
-bfa_fcs_port_loop_init(struct bfa_fcs_port_s *port)
-{
-}
-
-/**
- * Called by port to notify transition to online state.
- */
-void
-bfa_fcs_port_loop_online(struct bfa_fcs_port_s *port)
-{
-
- u8 num_alpa = port->port_topo.ploop.num_alpa;
- u8 *alpa_pos_map = port->port_topo.ploop.alpa_pos_map;
- struct bfa_fcs_rport_s *r_port;
- int ii = 0;
-
- /*
- * If the port role is Initiator Mode, create Rports.
- */
- if (port->port_cfg.roles == BFA_PORT_ROLE_FCP_IM) {
- /*
- * Check if the ALPA positional bitmap is available.
- * if not, we send PLOGI to all possible ALPAs.
- */
- if (num_alpa > 0) {
- for (ii = 0; ii < num_alpa; ii++) {
- /*
- * ignore ALPA of bfa port
- */
- if (alpa_pos_map[ii] != port->pid) {
- r_port = bfa_fcs_rport_create(port,
- alpa_pos_map[ii]);
- }
- }
- } else {
- for (ii = 0; ii < MAX_ALPA_COUNT; ii++) {
- /*
- * ignore ALPA of bfa port
- */
- if ((port_loop_alpa_map[ii] > 0)
- && (port_loop_alpa_map[ii] != port->pid))
- bfa_fcs_port_loop_send_plogi(port,
- port_loop_alpa_map[ii]);
- /**TBD */
- }
- }
- } else {
- /*
- * TBD Target Mode ??
- */
- }
-
-}
-
-/**
- * Called by port to notify transition to offline state.
- */
-void
-bfa_fcs_port_loop_offline(struct bfa_fcs_port_s *port)
-{
-
-}
-
-/**
- * Called by port to notify a LIP on the loop.
- */
-void
-bfa_fcs_port_loop_lip(struct bfa_fcs_port_s *port)
-{
-}
-
-/**
- * Local Functions.
- */
-static bfa_status_t
-bfa_fcs_port_loop_send_plogi(struct bfa_fcs_port_s *port, u8 alpa)
-{
- struct fchs_s fchs;
- struct bfa_fcxp_s *fcxp = NULL;
- int len;
-
- bfa_trc(port->fcs, alpa);
-
- fcxp = bfa_fcxp_alloc(NULL, port->fcs->bfa, 0, 0, NULL, NULL, NULL,
- NULL);
- bfa_assert(fcxp);
-
- len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), alpa,
- bfa_fcs_port_get_fcid(port), 0,
- port->port_cfg.pwwn, port->port_cfg.nwwn,
- bfa_fcport_get_maxfrsize(port->fcs->bfa));
-
- bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
- FC_CLASS_3, len, &fchs,
- bfa_fcs_port_loop_plogi_response, (void *)port,
- FC_MAX_PDUSZ, FC_RA_TOV);
-
- return BFA_STATUS_OK;
-}
-
-/**
- * Called by fcxp to notify the Plogi response
- */
-static void
-bfa_fcs_port_loop_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
- void *cbarg, bfa_status_t req_status,
- u32 rsp_len, u32 resid_len,
- struct fchs_s *rsp_fchs)
-{
- struct bfa_fcs_port_s *port = (struct bfa_fcs_port_s *) cbarg;
- struct fc_logi_s *plogi_resp;
- struct fc_els_cmd_s *els_cmd;
-
- bfa_trc(port->fcs, req_status);
-
- /*
- * Sanity Checks
- */
- if (req_status != BFA_STATUS_OK) {
- bfa_trc(port->fcs, req_status);
- /*
- * @todo
- * This could mean that the device with this APLA does not
- * exist on the loop.
- */
-
- return;
- }
-
- els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
- plogi_resp = (struct fc_logi_s *) els_cmd;
-
- if (els_cmd->els_code == FC_ELS_ACC) {
- bfa_fcs_rport_start(port, rsp_fchs, plogi_resp);
- } else {
- bfa_trc(port->fcs, plogi_resp->els_cmd.els_code);
- bfa_assert(0);
- }
-}
diff --git a/drivers/scsi/bfa/lport_api.c b/drivers/scsi/bfa/lport_api.c
deleted file mode 100644
index 72b3f508d0e9..000000000000
--- a/drivers/scsi/bfa/lport_api.c
+++ /dev/null
@@ -1,303 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/**
- * port_api.c BFA FCS port
- */
-
-#include <fcs/bfa_fcs.h>
-#include <fcs/bfa_fcs_lport.h>
-#include <fcs/bfa_fcs_rport.h>
-#include "fcs_rport.h"
-#include "fcs_fabric.h"
-#include "fcs_trcmod.h"
-#include "fcs_vport.h"
-
-BFA_TRC_FILE(FCS, PORT_API);
-
-
-
-/**
- * fcs_port_api BFA FCS port API
- */
-
-void
-bfa_fcs_cfg_base_port(struct bfa_fcs_s *fcs, struct bfa_port_cfg_s *port_cfg)
-{
-}
-
-struct bfa_fcs_port_s *
-bfa_fcs_get_base_port(struct bfa_fcs_s *fcs)
-{
- return &fcs->fabric.bport;
-}
-
-wwn_t
-bfa_fcs_port_get_rport(struct bfa_fcs_port_s *port, wwn_t wwn, int index,
- int nrports, bfa_boolean_t bwwn)
-{
- struct list_head *qh, *qe;
- struct bfa_fcs_rport_s *rport = NULL;
- int i;
- struct bfa_fcs_s *fcs;
-
- if (port == NULL || nrports == 0)
- return (wwn_t) 0;
-
- fcs = port->fcs;
- bfa_trc(fcs, (u32) nrports);
-
- i = 0;
- qh = &port->rport_q;
- qe = bfa_q_first(qh);
-
- while ((qe != qh) && (i < nrports)) {
- rport = (struct bfa_fcs_rport_s *)qe;
- if (bfa_os_ntoh3b(rport->pid) > 0xFFF000) {
- qe = bfa_q_next(qe);
- bfa_trc(fcs, (u32) rport->pwwn);
- bfa_trc(fcs, rport->pid);
- bfa_trc(fcs, i);
- continue;
- }
-
- if (bwwn) {
- if (!memcmp(&wwn, &rport->pwwn, 8))
- break;
- } else {
- if (i == index)
- break;
- }
-
- i++;
- qe = bfa_q_next(qe);
- }
-
- bfa_trc(fcs, i);
- if (rport)
- return rport->pwwn;
- else
- return (wwn_t) 0;
-}
-
-void
-bfa_fcs_port_get_rports(struct bfa_fcs_port_s *port, wwn_t rport_wwns[],
- int *nrports)
-{
- struct list_head *qh, *qe;
- struct bfa_fcs_rport_s *rport = NULL;
- int i;
- struct bfa_fcs_s *fcs;
-
- if (port == NULL || rport_wwns == NULL || *nrports == 0)
- return;
-
- fcs = port->fcs;
- bfa_trc(fcs, (u32) *nrports);
-
- i = 0;
- qh = &port->rport_q;
- qe = bfa_q_first(qh);
-
- while ((qe != qh) && (i < *nrports)) {
- rport = (struct bfa_fcs_rport_s *)qe;
- if (bfa_os_ntoh3b(rport->pid) > 0xFFF000) {
- qe = bfa_q_next(qe);
- bfa_trc(fcs, (u32) rport->pwwn);
- bfa_trc(fcs, rport->pid);
- bfa_trc(fcs, i);
- continue;
- }
-
- rport_wwns[i] = rport->pwwn;
-
- i++;
- qe = bfa_q_next(qe);
- }
-
- bfa_trc(fcs, i);
- *nrports = i;
- return;
-}
-
-/*
- * Iterate's through all the rport's in the given port to
- * determine the maximum operating speed.
- *
- * To be used in TRL Functionality only
- */
-enum bfa_pport_speed
-bfa_fcs_port_get_rport_max_speed(struct bfa_fcs_port_s *port)
-{
- struct list_head *qh, *qe;
- struct bfa_fcs_rport_s *rport = NULL;
- struct bfa_fcs_s *fcs;
- enum bfa_pport_speed max_speed = 0;
- struct bfa_pport_attr_s pport_attr;
- enum bfa_pport_speed pport_speed, rport_speed;
- bfa_boolean_t trl_enabled = bfa_fcport_is_ratelim(port->fcs->bfa);
-
- if (port == NULL)
- return 0;
-
- fcs = port->fcs;
-
- /*
- * Get Physical port's current speed
- */
- bfa_fcport_get_attr(port->fcs->bfa, &pport_attr);
- pport_speed = pport_attr.speed;
- bfa_trc(fcs, pport_speed);
-
- qh = &port->rport_q;
- qe = bfa_q_first(qh);
-
- while (qe != qh) {
- rport = (struct bfa_fcs_rport_s *) qe;
- if ((bfa_os_ntoh3b(rport->pid) > 0xFFF000) ||
- (bfa_fcs_rport_get_state(rport) ==
- BFA_RPORT_OFFLINE)) {
- qe = bfa_q_next(qe);
- continue;
- }
-
- rport_speed = rport->rpf.rpsc_speed;
- if ((trl_enabled) && (rport_speed ==
- BFA_PPORT_SPEED_UNKNOWN)) {
- /* Use default ratelim speed setting */
- rport_speed =
- bfa_fcport_get_ratelim_speed(port->fcs->bfa);
- }
-
- if ((rport_speed == BFA_PPORT_SPEED_8GBPS) ||
- (rport_speed > pport_speed)) {
- max_speed = rport_speed;
- break;
- } else if (rport_speed > max_speed) {
- max_speed = rport_speed;
- }
-
- qe = bfa_q_next(qe);
- }
-
- bfa_trc(fcs, max_speed);
- return max_speed;
-}
-
-struct bfa_fcs_port_s *
-bfa_fcs_lookup_port(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t lpwwn)
-{
- struct bfa_fcs_vport_s *vport;
- bfa_fcs_vf_t *vf;
-
- bfa_assert(fcs != NULL);
-
- vf = bfa_fcs_vf_lookup(fcs, vf_id);
- if (vf == NULL) {
- bfa_trc(fcs, vf_id);
- return NULL;
- }
-
- if (!lpwwn || (vf->bport.port_cfg.pwwn == lpwwn))
- return &vf->bport;
-
- vport = bfa_fcs_fabric_vport_lookup(vf, lpwwn);
- if (vport)
- return &vport->lport;
-
- return NULL;
-}
-
-/*
- * API corresponding to VmWare's NPIV_VPORT_GETINFO.
- */
-void
-bfa_fcs_port_get_info(struct bfa_fcs_port_s *port,
- struct bfa_port_info_s *port_info)
-{
-
- bfa_trc(port->fcs, port->fabric->fabric_name);
-
- if (port->vport == NULL) {
- /*
- * This is a Physical port
- */
- port_info->port_type = BFA_PORT_TYPE_PHYSICAL;
-
- /*
- * @todo : need to fix the state & reason
- */
- port_info->port_state = 0;
- port_info->offline_reason = 0;
-
- port_info->port_wwn = bfa_fcs_port_get_pwwn(port);
- port_info->node_wwn = bfa_fcs_port_get_nwwn(port);
-
- port_info->max_vports_supp =
- bfa_lps_get_max_vport(port->fcs->bfa);
- port_info->num_vports_inuse =
- bfa_fcs_fabric_vport_count(port->fabric);
- port_info->max_rports_supp = BFA_FCS_MAX_RPORTS_SUPP;
- port_info->num_rports_inuse = port->num_rports;
- } else {
- /*
- * This is a virtual port
- */
- port_info->port_type = BFA_PORT_TYPE_VIRTUAL;
-
- /*
- * @todo : need to fix the state & reason
- */
- port_info->port_state = 0;
- port_info->offline_reason = 0;
-
- port_info->port_wwn = bfa_fcs_port_get_pwwn(port);
- port_info->node_wwn = bfa_fcs_port_get_nwwn(port);
- }
-}
-
-void
-bfa_fcs_port_get_stats(struct bfa_fcs_port_s *fcs_port,
- struct bfa_port_stats_s *port_stats)
-{
- bfa_os_memcpy(port_stats, &fcs_port->stats,
- sizeof(struct bfa_port_stats_s));
- return;
-}
-
-void
-bfa_fcs_port_clear_stats(struct bfa_fcs_port_s *fcs_port)
-{
- bfa_os_memset(&fcs_port->stats, 0, sizeof(struct bfa_port_stats_s));
- return;
-}
-
-void
-bfa_fcs_port_enable_ipfc_roles(struct bfa_fcs_port_s *fcs_port)
-{
- fcs_port->port_cfg.roles |= BFA_PORT_ROLE_FCP_IPFC;
- return;
-}
-
-void
-bfa_fcs_port_disable_ipfc_roles(struct bfa_fcs_port_s *fcs_port)
-{
- fcs_port->port_cfg.roles &= ~BFA_PORT_ROLE_FCP_IPFC;
- return;
-}
-
-
diff --git a/drivers/scsi/bfa/lport_priv.h b/drivers/scsi/bfa/lport_priv.h
deleted file mode 100644
index dbae370a599a..000000000000
--- a/drivers/scsi/bfa/lport_priv.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef __VP_PRIV_H__
-#define __VP_PRIV_H__
-
-#include <fcs/bfa_fcs_lport.h>
-#include <fcs/bfa_fcs_vport.h>
-
-/*
- * Functions exported by vps
- */
-void bfa_fcs_vport_init(struct bfa_fcs_vport_s *vport);
-
-/*
- * Functions exported by vps
- */
-void bfa_fcs_vps_online(struct bfa_fcs_port_s *port);
-void bfa_fcs_vps_offline(struct bfa_fcs_port_s *port);
-void bfa_fcs_vps_lip(struct bfa_fcs_port_s *port);
-
-/*
- * Functions exported by port_fab
- */
-void bfa_fcs_port_fab_init(struct bfa_fcs_port_s *vport);
-void bfa_fcs_port_fab_online(struct bfa_fcs_port_s *vport);
-void bfa_fcs_port_fab_offline(struct bfa_fcs_port_s *vport);
-void bfa_fcs_port_fab_rx_frame(struct bfa_fcs_port_s *port,
- u8 *rx_frame, u32 len);
-
-/*
- * Functions exported by VP-NS.
- */
-void bfa_fcs_port_ns_init(struct bfa_fcs_port_s *vport);
-void bfa_fcs_port_ns_offline(struct bfa_fcs_port_s *vport);
-void bfa_fcs_port_ns_online(struct bfa_fcs_port_s *vport);
-void bfa_fcs_port_ns_query(struct bfa_fcs_port_s *port);
-
-/*
- * Functions exported by VP-SCN
- */
-void bfa_fcs_port_scn_init(struct bfa_fcs_port_s *vport);
-void bfa_fcs_port_scn_offline(struct bfa_fcs_port_s *vport);
-void bfa_fcs_port_scn_online(struct bfa_fcs_port_s *vport);
-void bfa_fcs_port_scn_process_rscn(struct bfa_fcs_port_s *port,
- struct fchs_s *rx_frame, u32 len);
-
-/*
- * Functions exported by VP-N2N
- */
-
-void bfa_fcs_port_n2n_init(struct bfa_fcs_port_s *port);
-void bfa_fcs_port_n2n_online(struct bfa_fcs_port_s *port);
-void bfa_fcs_port_n2n_offline(struct bfa_fcs_port_s *port);
-void bfa_fcs_port_n2n_rx_frame(struct bfa_fcs_port_s *port,
- u8 *rx_frame, u32 len);
-
-/*
- * Functions exported by VP-LOOP
- */
-void bfa_fcs_port_loop_init(struct bfa_fcs_port_s *port);
-void bfa_fcs_port_loop_online(struct bfa_fcs_port_s *port);
-void bfa_fcs_port_loop_offline(struct bfa_fcs_port_s *port);
-void bfa_fcs_port_loop_lip(struct bfa_fcs_port_s *port);
-void bfa_fcs_port_loop_rx_frame(struct bfa_fcs_port_s *port,
- u8 *rx_frame, u32 len);
-
-#endif /* __VP_PRIV_H__ */
diff --git a/drivers/scsi/bfa/ms.c b/drivers/scsi/bfa/ms.c
deleted file mode 100644
index 1d579ef26122..000000000000
--- a/drivers/scsi/bfa/ms.c
+++ /dev/null
@@ -1,759 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-
-#include <bfa.h>
-#include <bfa_svc.h>
-#include "fcs_lport.h"
-#include "fcs_rport.h"
-#include "fcs_trcmod.h"
-#include "fcs_fcxp.h"
-#include "lport_priv.h"
-
-BFA_TRC_FILE(FCS, MS);
-
-#define BFA_FCS_MS_CMD_MAX_RETRIES 2
-/*
- * forward declarations
- */
-static void bfa_fcs_port_ms_send_plogi(void *ms_cbarg,
- struct bfa_fcxp_s *fcxp_alloced);
-static void bfa_fcs_port_ms_timeout(void *arg);
-static void bfa_fcs_port_ms_plogi_response(void *fcsarg,
- struct bfa_fcxp_s *fcxp,
- void *cbarg,
- bfa_status_t req_status,
- u32 rsp_len,
- u32 resid_len,
- struct fchs_s *rsp_fchs);
-
-static void bfa_fcs_port_ms_send_gmal(void *ms_cbarg,
- struct bfa_fcxp_s *fcxp_alloced);
-static void bfa_fcs_port_ms_gmal_response(void *fcsarg,
- struct bfa_fcxp_s *fcxp,
- void *cbarg,
- bfa_status_t req_status,
- u32 rsp_len,
- u32 resid_len,
- struct fchs_s *rsp_fchs);
-static void bfa_fcs_port_ms_send_gfn(void *ms_cbarg,
- struct bfa_fcxp_s *fcxp_alloced);
-static void bfa_fcs_port_ms_gfn_response(void *fcsarg,
- struct bfa_fcxp_s *fcxp,
- void *cbarg,
- bfa_status_t req_status,
- u32 rsp_len,
- u32 resid_len,
- struct fchs_s *rsp_fchs);
-/**
- * fcs_ms_sm FCS MS state machine
- */
-
-/**
- * MS State Machine events
- */
-enum port_ms_event {
- MSSM_EVENT_PORT_ONLINE = 1,
- MSSM_EVENT_PORT_OFFLINE = 2,
- MSSM_EVENT_RSP_OK = 3,
- MSSM_EVENT_RSP_ERROR = 4,
- MSSM_EVENT_TIMEOUT = 5,
- MSSM_EVENT_FCXP_SENT = 6,
- MSSM_EVENT_PORT_FABRIC_RSCN = 7
-};
-
-static void bfa_fcs_port_ms_sm_offline(struct bfa_fcs_port_ms_s *ms,
- enum port_ms_event event);
-static void bfa_fcs_port_ms_sm_plogi_sending(struct bfa_fcs_port_ms_s *ms,
- enum port_ms_event event);
-static void bfa_fcs_port_ms_sm_plogi(struct bfa_fcs_port_ms_s *ms,
- enum port_ms_event event);
-static void bfa_fcs_port_ms_sm_plogi_retry(struct bfa_fcs_port_ms_s *ms,
- enum port_ms_event event);
-static void bfa_fcs_port_ms_sm_gmal_sending(struct bfa_fcs_port_ms_s *ms,
- enum port_ms_event event);
-static void bfa_fcs_port_ms_sm_gmal(struct bfa_fcs_port_ms_s *ms,
- enum port_ms_event event);
-static void bfa_fcs_port_ms_sm_gmal_retry(struct bfa_fcs_port_ms_s *ms,
- enum port_ms_event event);
-static void bfa_fcs_port_ms_sm_gfn_sending(struct bfa_fcs_port_ms_s *ms,
- enum port_ms_event event);
-static void bfa_fcs_port_ms_sm_gfn(struct bfa_fcs_port_ms_s *ms,
- enum port_ms_event event);
-static void bfa_fcs_port_ms_sm_gfn_retry(struct bfa_fcs_port_ms_s *ms,
- enum port_ms_event event);
-static void bfa_fcs_port_ms_sm_online(struct bfa_fcs_port_ms_s *ms,
- enum port_ms_event event);
-/**
- * Start in offline state - awaiting NS to send start.
- */
-static void
-bfa_fcs_port_ms_sm_offline(struct bfa_fcs_port_ms_s *ms,
- enum port_ms_event event)
-{
- bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
- bfa_trc(ms->port->fcs, event);
-
- switch (event) {
- case MSSM_EVENT_PORT_ONLINE:
- bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_plogi_sending);
- bfa_fcs_port_ms_send_plogi(ms, NULL);
- break;
-
- case MSSM_EVENT_PORT_OFFLINE:
- break;
-
- default:
- bfa_sm_fault(ms->port->fcs, event);
- }
-}
-
-static void
-bfa_fcs_port_ms_sm_plogi_sending(struct bfa_fcs_port_ms_s *ms,
- enum port_ms_event event)
-{
- bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
- bfa_trc(ms->port->fcs, event);
-
- switch (event) {
- case MSSM_EVENT_FCXP_SENT:
- bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_plogi);
- break;
-
- case MSSM_EVENT_PORT_OFFLINE:
- bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
- bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
- &ms->fcxp_wqe);
- break;
-
- default:
- bfa_sm_fault(ms->port->fcs, event);
- }
-}
-
-static void
-bfa_fcs_port_ms_sm_plogi(struct bfa_fcs_port_ms_s *ms, enum port_ms_event event)
-{
- bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
- bfa_trc(ms->port->fcs, event);
-
- switch (event) {
- case MSSM_EVENT_RSP_ERROR:
- /*
- * Start timer for a delayed retry
- */
- bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_plogi_retry);
- ms->port->stats.ms_retries++;
- bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port), &ms->timer,
- bfa_fcs_port_ms_timeout, ms,
- BFA_FCS_RETRY_TIMEOUT);
- break;
-
- case MSSM_EVENT_RSP_OK:
- /*
- * since plogi is done, now invoke MS related sub-modules
- */
- bfa_fcs_port_fdmi_online(ms);
-
- /**
- * if this is a Vport, go to online state.
- */
- if (ms->port->vport) {
- bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_online);
- break;
- }
-
- /*
- * For a base port we need to get the
- * switch's IP address.
- */
- bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gmal_sending);
- bfa_fcs_port_ms_send_gmal(ms, NULL);
- break;
-
- case MSSM_EVENT_PORT_OFFLINE:
- bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
- bfa_fcxp_discard(ms->fcxp);
- break;
-
- default:
- bfa_sm_fault(ms->port->fcs, event);
- }
-}
-
-static void
-bfa_fcs_port_ms_sm_plogi_retry(struct bfa_fcs_port_ms_s *ms,
- enum port_ms_event event)
-{
- bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
- bfa_trc(ms->port->fcs, event);
-
- switch (event) {
- case MSSM_EVENT_TIMEOUT:
- /*
- * Retry Timer Expired. Re-send
- */
- bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_plogi_sending);
- bfa_fcs_port_ms_send_plogi(ms, NULL);
- break;
-
- case MSSM_EVENT_PORT_OFFLINE:
- bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
- bfa_timer_stop(&ms->timer);
- break;
-
- default:
- bfa_sm_fault(ms->port->fcs, event);
- }
-}
-
-static void
-bfa_fcs_port_ms_sm_online(struct bfa_fcs_port_ms_s *ms,
- enum port_ms_event event)
-{
- bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
- bfa_trc(ms->port->fcs, event);
-
- switch (event) {
- case MSSM_EVENT_PORT_OFFLINE:
- bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
- break;
-
- case MSSM_EVENT_PORT_FABRIC_RSCN:
- bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_sending);
- ms->retry_cnt = 0;
- bfa_fcs_port_ms_send_gfn(ms, NULL);
- break;
-
- default:
- bfa_sm_fault(ms->port->fcs, event);
- }
-}
-
-static void
-bfa_fcs_port_ms_sm_gmal_sending(struct bfa_fcs_port_ms_s *ms,
- enum port_ms_event event)
-{
- bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
- bfa_trc(ms->port->fcs, event);
-
- switch (event) {
- case MSSM_EVENT_FCXP_SENT:
- bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gmal);
- break;
-
- case MSSM_EVENT_PORT_OFFLINE:
- bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
- bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
- &ms->fcxp_wqe);
- break;
-
- default:
- bfa_sm_fault(ms->port->fcs, event);
- }
-}
-
-static void
-bfa_fcs_port_ms_sm_gmal(struct bfa_fcs_port_ms_s *ms, enum port_ms_event event)
-{
- bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
- bfa_trc(ms->port->fcs, event);
-
- switch (event) {
- case MSSM_EVENT_RSP_ERROR:
- /*
- * Start timer for a delayed retry
- */
- if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
- bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gmal_retry);
- ms->port->stats.ms_retries++;
- bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
- &ms->timer, bfa_fcs_port_ms_timeout, ms,
- BFA_FCS_RETRY_TIMEOUT);
- } else {
- bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_sending);
- bfa_fcs_port_ms_send_gfn(ms, NULL);
- ms->retry_cnt = 0;
- }
- break;
-
- case MSSM_EVENT_RSP_OK:
- bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_sending);
- bfa_fcs_port_ms_send_gfn(ms, NULL);
- break;
-
- case MSSM_EVENT_PORT_OFFLINE:
- bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
- bfa_fcxp_discard(ms->fcxp);
- break;
-
- default:
- bfa_sm_fault(ms->port->fcs, event);
- }
-}
-
-static void
-bfa_fcs_port_ms_sm_gmal_retry(struct bfa_fcs_port_ms_s *ms,
- enum port_ms_event event)
-{
- bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
- bfa_trc(ms->port->fcs, event);
-
- switch (event) {
- case MSSM_EVENT_TIMEOUT:
- /*
- * Retry Timer Expired. Re-send
- */
- bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gmal_sending);
- bfa_fcs_port_ms_send_gmal(ms, NULL);
- break;
-
- case MSSM_EVENT_PORT_OFFLINE:
- bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
- bfa_timer_stop(&ms->timer);
- break;
-
- default:
- bfa_sm_fault(ms->port->fcs, event);
- }
-}
-
-/**
- * ms_pvt MS local functions
- */
-
-static void
-bfa_fcs_port_ms_send_gmal(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
- struct bfa_fcs_port_ms_s *ms = ms_cbarg;
- struct bfa_fcs_port_s *port = ms->port;
- struct fchs_s fchs;
- int len;
- struct bfa_fcxp_s *fcxp;
-
- bfa_trc(port->fcs, port->pid);
-
- fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
- if (!fcxp) {
- bfa_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
- bfa_fcs_port_ms_send_gmal, ms);
- return;
- }
- ms->fcxp = fcxp;
-
- len = fc_gmal_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
- bfa_fcs_port_get_fcid(port),
- bfa_lps_get_peer_nwwn(port->fabric->lps));
-
- bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
- FC_CLASS_3, len, &fchs, bfa_fcs_port_ms_gmal_response,
- (void *)ms, FC_MAX_PDUSZ, FC_FCCT_TOV);
-
- bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
-}
-
-static void
-bfa_fcs_port_ms_gmal_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
- void *cbarg, bfa_status_t req_status,
- u32 rsp_len, u32 resid_len,
- struct fchs_s *rsp_fchs)
-{
- struct bfa_fcs_port_ms_s *ms = (struct bfa_fcs_port_ms_s *)cbarg;
- struct bfa_fcs_port_s *port = ms->port;
- struct ct_hdr_s *cthdr = NULL;
- struct fcgs_gmal_resp_s *gmal_resp;
- struct fc_gmal_entry_s *gmal_entry;
- u32 num_entries;
- u8 *rsp_str;
-
- bfa_trc(port->fcs, req_status);
- bfa_trc(port->fcs, port->port_cfg.pwwn);
-
- /*
- * Sanity Checks
- */
- if (req_status != BFA_STATUS_OK) {
- bfa_trc(port->fcs, req_status);
- bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
- return;
- }
-
- cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
- cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
-
- if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
- gmal_resp = (struct fcgs_gmal_resp_s *)(cthdr + 1);
- num_entries = bfa_os_ntohl(gmal_resp->ms_len);
- if (num_entries == 0) {
- bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
- return;
- }
- /*
- * The response could contain multiple Entries.
- * Entries for SNMP interface, etc.
- * We look for the entry with a telnet prefix.
- * First "http://" entry refers to IP addr
- */
-
- gmal_entry = (struct fc_gmal_entry_s *)gmal_resp->ms_ma;
- while (num_entries > 0) {
- if (strncmp
- (gmal_entry->prefix, CT_GMAL_RESP_PREFIX_HTTP,
- sizeof(gmal_entry->prefix)) == 0) {
-
- /*
- * if the IP address is terminating with a '/',
- * remove it. *Byte 0 consists of the length
- * of the string.
- */
- rsp_str = &(gmal_entry->prefix[0]);
- if (rsp_str[gmal_entry->len - 1] == '/')
- rsp_str[gmal_entry->len - 1] = 0;
- /*
- * copy IP Address to fabric
- */
- strncpy(bfa_fcs_port_get_fabric_ipaddr(port),
- gmal_entry->ip_addr,
- BFA_FCS_FABRIC_IPADDR_SZ);
- break;
- } else {
- --num_entries;
- ++gmal_entry;
- }
- }
-
- bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
- return;
- }
-
- bfa_trc(port->fcs, cthdr->reason_code);
- bfa_trc(port->fcs, cthdr->exp_code);
- bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
-}
-
-static void
-bfa_fcs_port_ms_sm_gfn_sending(struct bfa_fcs_port_ms_s *ms,
- enum port_ms_event event)
-{
- bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
- bfa_trc(ms->port->fcs, event);
-
- switch (event) {
- case MSSM_EVENT_FCXP_SENT:
- bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn);
- break;
-
- case MSSM_EVENT_PORT_OFFLINE:
- bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
- bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
- &ms->fcxp_wqe);
- break;
-
- default:
- bfa_sm_fault(ms->port->fcs, event);
- }
-}
-
-static void
-bfa_fcs_port_ms_sm_gfn(struct bfa_fcs_port_ms_s *ms, enum port_ms_event event)
-{
- bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
- bfa_trc(ms->port->fcs, event);
-
- switch (event) {
- case MSSM_EVENT_RSP_ERROR:
- /*
- * Start timer for a delayed retry
- */
- if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
- bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_retry);
- ms->port->stats.ms_retries++;
- bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
- &ms->timer, bfa_fcs_port_ms_timeout, ms,
- BFA_FCS_RETRY_TIMEOUT);
- } else {
- bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_online);
- ms->retry_cnt = 0;
- }
- break;
-
- case MSSM_EVENT_RSP_OK:
- bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_online);
- break;
-
- case MSSM_EVENT_PORT_OFFLINE:
- bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
- bfa_fcxp_discard(ms->fcxp);
- break;
-
- default:
- bfa_sm_fault(ms->port->fcs, event);
- }
-}
-
-static void
-bfa_fcs_port_ms_sm_gfn_retry(struct bfa_fcs_port_ms_s *ms,
- enum port_ms_event event)
-{
- bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
- bfa_trc(ms->port->fcs, event);
-
- switch (event) {
- case MSSM_EVENT_TIMEOUT:
- /*
- * Retry Timer Expired. Re-send
- */
- bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_sending);
- bfa_fcs_port_ms_send_gfn(ms, NULL);
- break;
-
- case MSSM_EVENT_PORT_OFFLINE:
- bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
- bfa_timer_stop(&ms->timer);
- break;
-
- default:
- bfa_sm_fault(ms->port->fcs, event);
- }
-}
-
-/**
- * ms_pvt MS local functions
- */
-
-static void
-bfa_fcs_port_ms_send_gfn(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
- struct bfa_fcs_port_ms_s *ms = ms_cbarg;
- struct bfa_fcs_port_s *port = ms->port;
- struct fchs_s fchs;
- int len;
- struct bfa_fcxp_s *fcxp;
-
- bfa_trc(port->fcs, port->pid);
-
- fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
- if (!fcxp) {
- bfa_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
- bfa_fcs_port_ms_send_gfn, ms);
- return;
- }
- ms->fcxp = fcxp;
-
- len = fc_gfn_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
- bfa_fcs_port_get_fcid(port),
- bfa_lps_get_peer_nwwn(port->fabric->lps));
-
- bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
- FC_CLASS_3, len, &fchs, bfa_fcs_port_ms_gfn_response,
- (void *)ms, FC_MAX_PDUSZ, FC_FCCT_TOV);
-
- bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
-}
-
-static void
-bfa_fcs_port_ms_gfn_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
- bfa_status_t req_status, u32 rsp_len,
- u32 resid_len, struct fchs_s *rsp_fchs)
-{
- struct bfa_fcs_port_ms_s *ms = (struct bfa_fcs_port_ms_s *)cbarg;
- struct bfa_fcs_port_s *port = ms->port;
- struct ct_hdr_s *cthdr = NULL;
- wwn_t *gfn_resp;
-
- bfa_trc(port->fcs, req_status);
- bfa_trc(port->fcs, port->port_cfg.pwwn);
-
- /*
- * Sanity Checks
- */
- if (req_status != BFA_STATUS_OK) {
- bfa_trc(port->fcs, req_status);
- bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
- return;
- }
-
- cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
- cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
-
- if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
- gfn_resp = (wwn_t *) (cthdr + 1);
- /*
- * check if it has actually changed
- */
- if ((memcmp
- ((void *)&bfa_fcs_port_get_fabric_name(port), gfn_resp,
- sizeof(wwn_t)) != 0))
- bfa_fcs_fabric_set_fabric_name(port->fabric, *gfn_resp);
- bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
- return;
- }
-
- bfa_trc(port->fcs, cthdr->reason_code);
- bfa_trc(port->fcs, cthdr->exp_code);
- bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
-}
-
-/**
- * ms_pvt MS local functions
- */
-
-static void
-bfa_fcs_port_ms_send_plogi(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
- struct bfa_fcs_port_ms_s *ms = ms_cbarg;
- struct bfa_fcs_port_s *port = ms->port;
- struct fchs_s fchs;
- int len;
- struct bfa_fcxp_s *fcxp;
-
- bfa_trc(port->fcs, port->pid);
-
- fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
- if (!fcxp) {
- port->stats.ms_plogi_alloc_wait++;
- bfa_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
- bfa_fcs_port_ms_send_plogi, ms);
- return;
- }
- ms->fcxp = fcxp;
-
- len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
- bfa_os_hton3b(FC_MGMT_SERVER),
- bfa_fcs_port_get_fcid(port), 0,
- port->port_cfg.pwwn, port->port_cfg.nwwn,
- bfa_fcport_get_maxfrsize(port->fcs->bfa));
-
- bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
- FC_CLASS_3, len, &fchs, bfa_fcs_port_ms_plogi_response,
- (void *)ms, FC_MAX_PDUSZ, FC_ELS_TOV);
-
- port->stats.ms_plogi_sent++;
- bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
-}
-
-static void
-bfa_fcs_port_ms_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
- void *cbarg, bfa_status_t req_status,
- u32 rsp_len, u32 resid_len,
- struct fchs_s *rsp_fchs)
-{
- struct bfa_fcs_port_ms_s *ms = (struct bfa_fcs_port_ms_s *)cbarg;
-
- struct bfa_fcs_port_s *port = ms->port;
- struct fc_els_cmd_s *els_cmd;
- struct fc_ls_rjt_s *ls_rjt;
-
- bfa_trc(port->fcs, req_status);
- bfa_trc(port->fcs, port->port_cfg.pwwn);
-
- /*
- * Sanity Checks
- */
- if (req_status != BFA_STATUS_OK) {
- port->stats.ms_plogi_rsp_err++;
- bfa_trc(port->fcs, req_status);
- bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
- return;
- }
-
- els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
-
- switch (els_cmd->els_code) {
-
- case FC_ELS_ACC:
- if (rsp_len < sizeof(struct fc_logi_s)) {
- bfa_trc(port->fcs, rsp_len);
- port->stats.ms_plogi_acc_err++;
- bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
- break;
- }
- port->stats.ms_plogi_accepts++;
- bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
- break;
-
- case FC_ELS_LS_RJT:
- ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
-
- bfa_trc(port->fcs, ls_rjt->reason_code);
- bfa_trc(port->fcs, ls_rjt->reason_code_expl);
-
- port->stats.ms_rejects++;
- bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
- break;
-
- default:
- port->stats.ms_plogi_unknown_rsp++;
- bfa_trc(port->fcs, els_cmd->els_code);
- bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
- }
-}
-
-static void
-bfa_fcs_port_ms_timeout(void *arg)
-{
- struct bfa_fcs_port_ms_s *ms = (struct bfa_fcs_port_ms_s *)arg;
-
- ms->port->stats.ms_timeouts++;
- bfa_sm_send_event(ms, MSSM_EVENT_TIMEOUT);
-}
-
-
-void
-bfa_fcs_port_ms_init(struct bfa_fcs_port_s *port)
-{
- struct bfa_fcs_port_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
-
- ms->port = port;
- bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
-
- /*
- * Invoke init routines of sub modules.
- */
- bfa_fcs_port_fdmi_init(ms);
-}
-
-void
-bfa_fcs_port_ms_offline(struct bfa_fcs_port_s *port)
-{
- struct bfa_fcs_port_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
-
- ms->port = port;
- bfa_sm_send_event(ms, MSSM_EVENT_PORT_OFFLINE);
- bfa_fcs_port_fdmi_offline(ms);
-}
-
-void
-bfa_fcs_port_ms_online(struct bfa_fcs_port_s *port)
-{
- struct bfa_fcs_port_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
-
- ms->port = port;
- bfa_sm_send_event(ms, MSSM_EVENT_PORT_ONLINE);
-}
-
-void
-bfa_fcs_port_ms_fabric_rscn(struct bfa_fcs_port_s *port)
-{
- struct bfa_fcs_port_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
-
- /*
- * @todo. Handle this only when in Online state
- */
- if (bfa_sm_cmp_state(ms, bfa_fcs_port_ms_sm_online))
- bfa_sm_send_event(ms, MSSM_EVENT_PORT_FABRIC_RSCN);
-}
diff --git a/drivers/scsi/bfa/n2n.c b/drivers/scsi/bfa/n2n.c
deleted file mode 100644
index 735456824346..000000000000
--- a/drivers/scsi/bfa/n2n.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/**
- * n2n.c n2n implementation.
- */
-#include <bfa.h>
-#include <bfa_svc.h>
-#include "fcs_lport.h"
-#include "fcs_rport.h"
-#include "fcs_trcmod.h"
-#include "lport_priv.h"
-
-BFA_TRC_FILE(FCS, N2N);
-
-/**
- * Called by fcs/port to initialize N2N topology.
- */
-void
-bfa_fcs_port_n2n_init(struct bfa_fcs_port_s *port)
-{
-}
-
-/**
- * Called by fcs/port to notify transition to online state.
- */
-void
-bfa_fcs_port_n2n_online(struct bfa_fcs_port_s *port)
-{
- struct bfa_fcs_port_n2n_s *n2n_port = &port->port_topo.pn2n;
- struct bfa_port_cfg_s *pcfg = &port->port_cfg;
- struct bfa_fcs_rport_s *rport;
-
- bfa_trc(port->fcs, pcfg->pwwn);
-
- /*
- * If our PWWN is > than that of the r-port, we have to initiate PLOGI
- * and assign an Address. if not, we need to wait for its PLOGI.
- *
- * If our PWWN is < than that of the remote port, it will send a PLOGI
- * with the PIDs assigned. The rport state machine take care of this
- * incoming PLOGI.
- */
- if (memcmp
- ((void *)&pcfg->pwwn, (void *)&n2n_port->rem_port_wwn,
- sizeof(wwn_t)) > 0) {
- port->pid = N2N_LOCAL_PID;
- /**
- * First, check if we know the device by pwwn.
- */
- rport = bfa_fcs_port_get_rport_by_pwwn(port,
- n2n_port->rem_port_wwn);
- if (rport) {
- bfa_trc(port->fcs, rport->pid);
- bfa_trc(port->fcs, rport->pwwn);
- rport->pid = N2N_REMOTE_PID;
- bfa_fcs_rport_online(rport);
- return;
- }
-
- /*
- * In n2n there can be only one rport. Delete the old one whose
- * pid should be zero, because it is offline.
- */
- if (port->num_rports > 0) {
- rport = bfa_fcs_port_get_rport_by_pid(port, 0);
- bfa_assert(rport != NULL);
- if (rport) {
- bfa_trc(port->fcs, rport->pwwn);
- bfa_fcs_rport_delete(rport);
- }
- }
- bfa_fcs_rport_create(port, N2N_REMOTE_PID);
- }
-}
-
-/**
- * Called by fcs/port to notify transition to offline state.
- */
-void
-bfa_fcs_port_n2n_offline(struct bfa_fcs_port_s *port)
-{
- struct bfa_fcs_port_n2n_s *n2n_port = &port->port_topo.pn2n;
-
- bfa_trc(port->fcs, port->pid);
- port->pid = 0;
- n2n_port->rem_port_wwn = 0;
- n2n_port->reply_oxid = 0;
-}
-
-
diff --git a/drivers/scsi/bfa/ns.c b/drivers/scsi/bfa/ns.c
deleted file mode 100644
index ae0edcc86ed5..000000000000
--- a/drivers/scsi/bfa/ns.c
+++ /dev/null
@@ -1,1242 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/**
- * @page ns_sm_info VPORT NS State Machine
- *
- * @section ns_sm_interactions VPORT NS State Machine Interactions
- *
- * @section ns_sm VPORT NS State Machine
- * img ns_sm.jpg
- */
-#include <bfa.h>
-#include <bfa_svc.h>
-#include <bfa_iocfc.h>
-#include "fcs_lport.h"
-#include "fcs_rport.h"
-#include "fcs_trcmod.h"
-#include "fcs_fcxp.h"
-#include "fcs.h"
-#include "lport_priv.h"
-
-BFA_TRC_FILE(FCS, NS);
-
-/*
- * forward declarations
- */
-static void bfa_fcs_port_ns_send_plogi(void *ns_cbarg,
- struct bfa_fcxp_s *fcxp_alloced);
-static void bfa_fcs_port_ns_send_rspn_id(void *ns_cbarg,
- struct bfa_fcxp_s *fcxp_alloced);
-static void bfa_fcs_port_ns_send_rft_id(void *ns_cbarg,
- struct bfa_fcxp_s *fcxp_alloced);
-static void bfa_fcs_port_ns_send_rff_id(void *ns_cbarg,
- struct bfa_fcxp_s *fcxp_alloced);
-static void bfa_fcs_port_ns_send_gid_ft(void *ns_cbarg,
- struct bfa_fcxp_s *fcxp_alloced);
-static void bfa_fcs_port_ns_timeout(void *arg);
-static void bfa_fcs_port_ns_plogi_response(void *fcsarg,
- struct bfa_fcxp_s *fcxp,
- void *cbarg,
- bfa_status_t req_status,
- u32 rsp_len,
- u32 resid_len,
- struct fchs_s *rsp_fchs);
-static void bfa_fcs_port_ns_rspn_id_response(void *fcsarg,
- struct bfa_fcxp_s *fcxp,
- void *cbarg,
- bfa_status_t req_status,
- u32 rsp_len,
- u32 resid_len,
- struct fchs_s *rsp_fchs);
-static void bfa_fcs_port_ns_rft_id_response(void *fcsarg,
- struct bfa_fcxp_s *fcxp,
- void *cbarg,
- bfa_status_t req_status,
- u32 rsp_len,
- u32 resid_len,
- struct fchs_s *rsp_fchs);
-static void bfa_fcs_port_ns_rff_id_response(void *fcsarg,
- struct bfa_fcxp_s *fcxp,
- void *cbarg,
- bfa_status_t req_status,
- u32 rsp_len,
- u32 resid_len,
- struct fchs_s *rsp_fchs);
-static void bfa_fcs_port_ns_gid_ft_response(void *fcsarg,
- struct bfa_fcxp_s *fcxp,
- void *cbarg,
- bfa_status_t req_status,
- u32 rsp_len,
- u32 resid_len,
- struct fchs_s *rsp_fchs);
-static void bfa_fcs_port_ns_process_gidft_pids(struct bfa_fcs_port_s *port,
- u32 *pid_buf,
- u32 n_pids);
-
-static void bfa_fcs_port_ns_boot_target_disc(struct bfa_fcs_port_s *port);
-/**
- * fcs_ns_sm FCS nameserver interface state machine
- */
-
-/**
- * VPort NS State Machine events
- */
-enum vport_ns_event {
- NSSM_EVENT_PORT_ONLINE = 1,
- NSSM_EVENT_PORT_OFFLINE = 2,
- NSSM_EVENT_PLOGI_SENT = 3,
- NSSM_EVENT_RSP_OK = 4,
- NSSM_EVENT_RSP_ERROR = 5,
- NSSM_EVENT_TIMEOUT = 6,
- NSSM_EVENT_NS_QUERY = 7,
- NSSM_EVENT_RSPNID_SENT = 8,
- NSSM_EVENT_RFTID_SENT = 9,
- NSSM_EVENT_RFFID_SENT = 10,
- NSSM_EVENT_GIDFT_SENT = 11,
-};
-
-static void bfa_fcs_port_ns_sm_offline(struct bfa_fcs_port_ns_s *ns,
- enum vport_ns_event event);
-static void bfa_fcs_port_ns_sm_plogi_sending(struct bfa_fcs_port_ns_s *ns,
- enum vport_ns_event event);
-static void bfa_fcs_port_ns_sm_plogi(struct bfa_fcs_port_ns_s *ns,
- enum vport_ns_event event);
-static void bfa_fcs_port_ns_sm_plogi_retry(struct bfa_fcs_port_ns_s *ns,
- enum vport_ns_event event);
-static void bfa_fcs_port_ns_sm_sending_rspn_id(struct bfa_fcs_port_ns_s *ns,
- enum vport_ns_event event);
-static void bfa_fcs_port_ns_sm_rspn_id(struct bfa_fcs_port_ns_s *ns,
- enum vport_ns_event event);
-static void bfa_fcs_port_ns_sm_rspn_id_retry(struct bfa_fcs_port_ns_s *ns,
- enum vport_ns_event event);
-static void bfa_fcs_port_ns_sm_sending_rft_id(struct bfa_fcs_port_ns_s *ns,
- enum vport_ns_event event);
-static void bfa_fcs_port_ns_sm_rft_id_retry(struct bfa_fcs_port_ns_s *ns,
- enum vport_ns_event event);
-static void bfa_fcs_port_ns_sm_rft_id(struct bfa_fcs_port_ns_s *ns,
- enum vport_ns_event event);
-static void bfa_fcs_port_ns_sm_sending_rff_id(struct bfa_fcs_port_ns_s *ns,
- enum vport_ns_event event);
-static void bfa_fcs_port_ns_sm_rff_id_retry(struct bfa_fcs_port_ns_s *ns,
- enum vport_ns_event event);
-static void bfa_fcs_port_ns_sm_rff_id(struct bfa_fcs_port_ns_s *ns,
- enum vport_ns_event event);
-static void bfa_fcs_port_ns_sm_sending_gid_ft(struct bfa_fcs_port_ns_s *ns,
- enum vport_ns_event event);
-static void bfa_fcs_port_ns_sm_gid_ft(struct bfa_fcs_port_ns_s *ns,
- enum vport_ns_event event);
-static void bfa_fcs_port_ns_sm_gid_ft_retry(struct bfa_fcs_port_ns_s *ns,
- enum vport_ns_event event);
-static void bfa_fcs_port_ns_sm_online(struct bfa_fcs_port_ns_s *ns,
- enum vport_ns_event event);
-/**
- * Start in offline state - awaiting linkup
- */
-static void
-bfa_fcs_port_ns_sm_offline(struct bfa_fcs_port_ns_s *ns,
- enum vport_ns_event event)
-{
- bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
- bfa_trc(ns->port->fcs, event);
-
- switch (event) {
- case NSSM_EVENT_PORT_ONLINE:
- bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_plogi_sending);
- bfa_fcs_port_ns_send_plogi(ns, NULL);
- break;
-
- case NSSM_EVENT_PORT_OFFLINE:
- break;
-
- default:
- bfa_sm_fault(ns->port->fcs, event);
- }
-}
-
-static void
-bfa_fcs_port_ns_sm_plogi_sending(struct bfa_fcs_port_ns_s *ns,
- enum vport_ns_event event)
-{
- bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
- bfa_trc(ns->port->fcs, event);
-
- switch (event) {
- case NSSM_EVENT_PLOGI_SENT:
- bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_plogi);
- break;
-
- case NSSM_EVENT_PORT_OFFLINE:
- bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
- bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
- &ns->fcxp_wqe);
- break;
-
- default:
- bfa_sm_fault(ns->port->fcs, event);
- }
-}
-
-static void
-bfa_fcs_port_ns_sm_plogi(struct bfa_fcs_port_ns_s *ns,
- enum vport_ns_event event)
-{
- bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
- bfa_trc(ns->port->fcs, event);
-
- switch (event) {
- case NSSM_EVENT_RSP_ERROR:
- /*
- * Start timer for a delayed retry
- */
- bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_plogi_retry);
- ns->port->stats.ns_retries++;
- bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port), &ns->timer,
- bfa_fcs_port_ns_timeout, ns,
- BFA_FCS_RETRY_TIMEOUT);
- break;
-
- case NSSM_EVENT_RSP_OK:
- bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_rspn_id);
- bfa_fcs_port_ns_send_rspn_id(ns, NULL);
- break;
-
- case NSSM_EVENT_PORT_OFFLINE:
- bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
- bfa_fcxp_discard(ns->fcxp);
- break;
-
- default:
- bfa_sm_fault(ns->port->fcs, event);
- }
-}
-
-static void
-bfa_fcs_port_ns_sm_plogi_retry(struct bfa_fcs_port_ns_s *ns,
- enum vport_ns_event event)
-{
- bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
- bfa_trc(ns->port->fcs, event);
-
- switch (event) {
- case NSSM_EVENT_TIMEOUT:
- /*
- * Retry Timer Expired. Re-send
- */
- bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_plogi_sending);
- bfa_fcs_port_ns_send_plogi(ns, NULL);
- break;
-
- case NSSM_EVENT_PORT_OFFLINE:
- bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
- bfa_timer_stop(&ns->timer);
- break;
-
- default:
- bfa_sm_fault(ns->port->fcs, event);
- }
-}
-
-static void
-bfa_fcs_port_ns_sm_sending_rspn_id(struct bfa_fcs_port_ns_s *ns,
- enum vport_ns_event event)
-{
- bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
- bfa_trc(ns->port->fcs, event);
-
- switch (event) {
- case NSSM_EVENT_RSPNID_SENT:
- bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_rspn_id);
- break;
-
- case NSSM_EVENT_PORT_OFFLINE:
- bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
- bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
- &ns->fcxp_wqe);
- break;
-
- default:
- bfa_sm_fault(ns->port->fcs, event);
- }
-}
-
-static void
-bfa_fcs_port_ns_sm_rspn_id(struct bfa_fcs_port_ns_s *ns,
- enum vport_ns_event event)
-{
- bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
- bfa_trc(ns->port->fcs, event);
-
- switch (event) {
- case NSSM_EVENT_RSP_ERROR:
- /*
- * Start timer for a delayed retry
- */
- bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_rspn_id_retry);
- ns->port->stats.ns_retries++;
- bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port), &ns->timer,
- bfa_fcs_port_ns_timeout, ns,
- BFA_FCS_RETRY_TIMEOUT);
- break;
-
- case NSSM_EVENT_RSP_OK:
- bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_rft_id);
- bfa_fcs_port_ns_send_rft_id(ns, NULL);
- break;
-
- case NSSM_EVENT_PORT_OFFLINE:
- bfa_fcxp_discard(ns->fcxp);
- bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
- break;
-
- default:
- bfa_sm_fault(ns->port->fcs, event);
- }
-}
-
-static void
-bfa_fcs_port_ns_sm_rspn_id_retry(struct bfa_fcs_port_ns_s *ns,
- enum vport_ns_event event)
-{
- bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
- bfa_trc(ns->port->fcs, event);
-
- switch (event) {
- case NSSM_EVENT_TIMEOUT:
- /*
- * Retry Timer Expired. Re-send
- */
- bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_rspn_id);
- bfa_fcs_port_ns_send_rspn_id(ns, NULL);
- break;
-
- case NSSM_EVENT_PORT_OFFLINE:
- bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
- bfa_timer_stop(&ns->timer);
- break;
-
- default:
- bfa_sm_fault(ns->port->fcs, event);
- }
-}
-
-static void
-bfa_fcs_port_ns_sm_sending_rft_id(struct bfa_fcs_port_ns_s *ns,
- enum vport_ns_event event)
-{
- bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
- bfa_trc(ns->port->fcs, event);
-
- switch (event) {
- case NSSM_EVENT_RFTID_SENT:
- bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_rft_id);
- break;
-
- case NSSM_EVENT_PORT_OFFLINE:
- bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
- bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
- &ns->fcxp_wqe);
- break;
-
- default:
- bfa_sm_fault(ns->port->fcs, event);
- }
-}
-
-static void
-bfa_fcs_port_ns_sm_rft_id(struct bfa_fcs_port_ns_s *ns,
- enum vport_ns_event event)
-{
- bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
- bfa_trc(ns->port->fcs, event);
-
- switch (event) {
- case NSSM_EVENT_RSP_OK:
- /*
- * Now move to register FC4 Features
- */
- bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_rff_id);
- bfa_fcs_port_ns_send_rff_id(ns, NULL);
- break;
-
- case NSSM_EVENT_RSP_ERROR:
- /*
- * Start timer for a delayed retry
- */
- bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_rft_id_retry);
- ns->port->stats.ns_retries++;
- bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port), &ns->timer,
- bfa_fcs_port_ns_timeout, ns,
- BFA_FCS_RETRY_TIMEOUT);
- break;
-
- case NSSM_EVENT_PORT_OFFLINE:
- bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
- bfa_fcxp_discard(ns->fcxp);
- break;
-
- default:
- bfa_sm_fault(ns->port->fcs, event);
- }
-}
-
-static void
-bfa_fcs_port_ns_sm_rft_id_retry(struct bfa_fcs_port_ns_s *ns,
- enum vport_ns_event event)
-{
- bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
- bfa_trc(ns->port->fcs, event);
-
- switch (event) {
- case NSSM_EVENT_TIMEOUT:
- bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_rft_id);
- bfa_fcs_port_ns_send_rft_id(ns, NULL);
- break;
-
- case NSSM_EVENT_PORT_OFFLINE:
- bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
- bfa_timer_stop(&ns->timer);
- break;
-
- default:
- bfa_sm_fault(ns->port->fcs, event);
- }
-}
-
-static void
-bfa_fcs_port_ns_sm_sending_rff_id(struct bfa_fcs_port_ns_s *ns,
- enum vport_ns_event event)
-{
- bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
- bfa_trc(ns->port->fcs, event);
-
- switch (event) {
- case NSSM_EVENT_RFFID_SENT:
- bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_rff_id);
- break;
-
- case NSSM_EVENT_PORT_OFFLINE:
- bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
- bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
- &ns->fcxp_wqe);
- break;
-
- default:
- bfa_sm_fault(ns->port->fcs, event);
- }
-}
-
-static void
-bfa_fcs_port_ns_sm_rff_id(struct bfa_fcs_port_ns_s *ns,
- enum vport_ns_event event)
-{
- bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
- bfa_trc(ns->port->fcs, event);
-
- switch (event) {
- case NSSM_EVENT_RSP_OK:
-
- /*
- * If min cfg mode is enabled, we donot initiate rport
- * discovery with the fabric. Instead, we will retrieve the
- * boot targets from HAL/FW.
- */
- if (__fcs_min_cfg(ns->port->fcs)) {
- bfa_fcs_port_ns_boot_target_disc(ns->port);
- bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_online);
- return;
- }
-
- /*
- * If the port role is Initiator Mode issue NS query.
- * If it is Target Mode, skip this and go to online.
- */
- if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) {
- bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_gid_ft);
- bfa_fcs_port_ns_send_gid_ft(ns, NULL);
- } else if (BFA_FCS_VPORT_IS_TARGET_MODE(ns->port)) {
- bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_online);
- }
- /*
- * kick off mgmt srvr state machine
- */
- bfa_fcs_port_ms_online(ns->port);
- break;
-
- case NSSM_EVENT_RSP_ERROR:
- /*
- * Start timer for a delayed retry
- */
- bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_rff_id_retry);
- ns->port->stats.ns_retries++;
- bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port), &ns->timer,
- bfa_fcs_port_ns_timeout, ns,
- BFA_FCS_RETRY_TIMEOUT);
- break;
-
- case NSSM_EVENT_PORT_OFFLINE:
- bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
- bfa_fcxp_discard(ns->fcxp);
- break;
-
- default:
- bfa_sm_fault(ns->port->fcs, event);
- }
-}
-
-static void
-bfa_fcs_port_ns_sm_rff_id_retry(struct bfa_fcs_port_ns_s *ns,
- enum vport_ns_event event)
-{
- bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
- bfa_trc(ns->port->fcs, event);
-
- switch (event) {
- case NSSM_EVENT_TIMEOUT:
- bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_rff_id);
- bfa_fcs_port_ns_send_rff_id(ns, NULL);
- break;
-
- case NSSM_EVENT_PORT_OFFLINE:
- bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
- bfa_timer_stop(&ns->timer);
- break;
-
- default:
- bfa_sm_fault(ns->port->fcs, event);
- }
-}
-static void
-bfa_fcs_port_ns_sm_sending_gid_ft(struct bfa_fcs_port_ns_s *ns,
- enum vport_ns_event event)
-{
- bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
- bfa_trc(ns->port->fcs, event);
-
- switch (event) {
- case NSSM_EVENT_GIDFT_SENT:
- bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_gid_ft);
- break;
-
- case NSSM_EVENT_PORT_OFFLINE:
- bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
- bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
- &ns->fcxp_wqe);
- break;
-
- default:
- bfa_sm_fault(ns->port->fcs, event);
- }
-}
-
-static void
-bfa_fcs_port_ns_sm_gid_ft(struct bfa_fcs_port_ns_s *ns,
- enum vport_ns_event event)
-{
- bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
- bfa_trc(ns->port->fcs, event);
-
- switch (event) {
- case NSSM_EVENT_RSP_OK:
- bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_online);
- break;
-
- case NSSM_EVENT_RSP_ERROR:
- /*
- * TBD: for certain reject codes, we don't need to retry
- */
- /*
- * Start timer for a delayed retry
- */
- bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_gid_ft_retry);
- ns->port->stats.ns_retries++;
- bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port), &ns->timer,
- bfa_fcs_port_ns_timeout, ns,
- BFA_FCS_RETRY_TIMEOUT);
- break;
-
- case NSSM_EVENT_PORT_OFFLINE:
- bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
- bfa_fcxp_discard(ns->fcxp);
- break;
-
- default:
- bfa_sm_fault(ns->port->fcs, event);
- }
-}
-
-static void
-bfa_fcs_port_ns_sm_gid_ft_retry(struct bfa_fcs_port_ns_s *ns,
- enum vport_ns_event event)
-{
- bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
- bfa_trc(ns->port->fcs, event);
-
- switch (event) {
- case NSSM_EVENT_TIMEOUT:
- bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_gid_ft);
- bfa_fcs_port_ns_send_gid_ft(ns, NULL);
- break;
-
- case NSSM_EVENT_PORT_OFFLINE:
- bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
- bfa_timer_stop(&ns->timer);
- break;
-
- default:
- bfa_sm_fault(ns->port->fcs, event);
- }
-}
-
-static void
-bfa_fcs_port_ns_sm_online(struct bfa_fcs_port_ns_s *ns,
- enum vport_ns_event event)
-{
- bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
- bfa_trc(ns->port->fcs, event);
-
- switch (event) {
- case NSSM_EVENT_PORT_OFFLINE:
- bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
- break;
-
- case NSSM_EVENT_NS_QUERY:
- /*
- * If the port role is Initiator Mode issue NS query.
- * If it is Target Mode, skip this and go to online.
- */
- if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) {
- bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_gid_ft);
- bfa_fcs_port_ns_send_gid_ft(ns, NULL);
- };
- break;
-
- default:
- bfa_sm_fault(ns->port->fcs, event);
- }
-}
-
-
-
-/**
- * ns_pvt Nameserver local functions
- */
-
-static void
-bfa_fcs_port_ns_send_plogi(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
- struct bfa_fcs_port_ns_s *ns = ns_cbarg;
- struct bfa_fcs_port_s *port = ns->port;
- struct fchs_s fchs;
- int len;
- struct bfa_fcxp_s *fcxp;
-
- bfa_trc(port->fcs, port->pid);
-
- fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
- if (!fcxp) {
- port->stats.ns_plogi_alloc_wait++;
- bfa_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
- bfa_fcs_port_ns_send_plogi, ns);
- return;
- }
- ns->fcxp = fcxp;
-
- len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
- bfa_os_hton3b(FC_NAME_SERVER),
- bfa_fcs_port_get_fcid(port), 0,
- port->port_cfg.pwwn, port->port_cfg.nwwn,
- bfa_fcport_get_maxfrsize(port->fcs->bfa));
-
- bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
- FC_CLASS_3, len, &fchs, bfa_fcs_port_ns_plogi_response,
- (void *)ns, FC_MAX_PDUSZ, FC_ELS_TOV);
- port->stats.ns_plogi_sent++;
-
- bfa_sm_send_event(ns, NSSM_EVENT_PLOGI_SENT);
-}
-
-static void
-bfa_fcs_port_ns_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
- void *cbarg, bfa_status_t req_status,
- u32 rsp_len, u32 resid_len,
- struct fchs_s *rsp_fchs)
-{
- struct bfa_fcs_port_ns_s *ns = (struct bfa_fcs_port_ns_s *)cbarg;
- struct bfa_fcs_port_s *port = ns->port;
- /* struct fc_logi_s *plogi_resp; */
- struct fc_els_cmd_s *els_cmd;
- struct fc_ls_rjt_s *ls_rjt;
-
- bfa_trc(port->fcs, req_status);
- bfa_trc(port->fcs, port->port_cfg.pwwn);
-
- /*
- * Sanity Checks
- */
- if (req_status != BFA_STATUS_OK) {
- bfa_trc(port->fcs, req_status);
- port->stats.ns_plogi_rsp_err++;
- bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
- return;
- }
-
- els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
-
- switch (els_cmd->els_code) {
-
- case FC_ELS_ACC:
- if (rsp_len < sizeof(struct fc_logi_s)) {
- bfa_trc(port->fcs, rsp_len);
- port->stats.ns_plogi_acc_err++;
- bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
- break;
- }
- port->stats.ns_plogi_accepts++;
- bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
- break;
-
- case FC_ELS_LS_RJT:
- ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
-
- bfa_trc(port->fcs, ls_rjt->reason_code);
- bfa_trc(port->fcs, ls_rjt->reason_code_expl);
-
- port->stats.ns_rejects++;
-
- bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
- break;
-
- default:
- port->stats.ns_plogi_unknown_rsp++;
- bfa_trc(port->fcs, els_cmd->els_code);
- bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
- }
-}
-
-/**
- * Register the symbolic port name.
- */
-static void
-bfa_fcs_port_ns_send_rspn_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
- struct bfa_fcs_port_ns_s *ns = ns_cbarg;
- struct bfa_fcs_port_s *port = ns->port;
- struct fchs_s fchs;
- int len;
- struct bfa_fcxp_s *fcxp;
- u8 symbl[256];
- u8 *psymbl = &symbl[0];
-
- bfa_os_memset(symbl, 0, sizeof(symbl));
-
- bfa_trc(port->fcs, port->port_cfg.pwwn);
-
- fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
- if (!fcxp) {
- port->stats.ns_rspnid_alloc_wait++;
- bfa_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
- bfa_fcs_port_ns_send_rspn_id, ns);
- return;
- }
- ns->fcxp = fcxp;
-
- /*
- * for V-Port, form a Port Symbolic Name
- */
- if (port->vport) {
- /**For Vports,
- * we append the vport's port symbolic name to that of the base port.
- */
-
- strncpy((char *)psymbl,
- (char *)
- &(bfa_fcs_port_get_psym_name
- (bfa_fcs_get_base_port(port->fcs))),
- strlen((char *)
- &bfa_fcs_port_get_psym_name(bfa_fcs_get_base_port
- (port->fcs))));
-
- /*
- * Ensure we have a null terminating string.
- */
- ((char *)
- psymbl)[strlen((char *)
- &bfa_fcs_port_get_psym_name
- (bfa_fcs_get_base_port(port->fcs)))] = 0;
-
- strncat((char *)psymbl,
- (char *)&(bfa_fcs_port_get_psym_name(port)),
- strlen((char *)&bfa_fcs_port_get_psym_name(port)));
- } else {
- psymbl = (u8 *) &(bfa_fcs_port_get_psym_name(port));
- }
-
- len = fc_rspnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
- bfa_fcs_port_get_fcid(port), 0, psymbl);
-
- bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
- FC_CLASS_3, len, &fchs, bfa_fcs_port_ns_rspn_id_response,
- (void *)ns, FC_MAX_PDUSZ, FC_FCCT_TOV);
-
- port->stats.ns_rspnid_sent++;
-
- bfa_sm_send_event(ns, NSSM_EVENT_RSPNID_SENT);
-}
-
-static void
-bfa_fcs_port_ns_rspn_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
- void *cbarg, bfa_status_t req_status,
- u32 rsp_len, u32 resid_len,
- struct fchs_s *rsp_fchs)
-{
- struct bfa_fcs_port_ns_s *ns = (struct bfa_fcs_port_ns_s *)cbarg;
- struct bfa_fcs_port_s *port = ns->port;
- struct ct_hdr_s *cthdr = NULL;
-
- bfa_trc(port->fcs, port->port_cfg.pwwn);
-
- /*
- * Sanity Checks
- */
- if (req_status != BFA_STATUS_OK) {
- bfa_trc(port->fcs, req_status);
- port->stats.ns_rspnid_rsp_err++;
- bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
- return;
- }
-
- cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
- cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
-
- if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
- port->stats.ns_rspnid_accepts++;
- bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
- return;
- }
-
- port->stats.ns_rspnid_rejects++;
- bfa_trc(port->fcs, cthdr->reason_code);
- bfa_trc(port->fcs, cthdr->exp_code);
- bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
-}
-
-/**
- * Register FC4-Types
- * TBD, Need to retrieve this from the OS driver, in case IPFC is enabled ?
- */
-static void
-bfa_fcs_port_ns_send_rft_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
- struct bfa_fcs_port_ns_s *ns = ns_cbarg;
- struct bfa_fcs_port_s *port = ns->port;
- struct fchs_s fchs;
- int len;
- struct bfa_fcxp_s *fcxp;
-
- bfa_trc(port->fcs, port->port_cfg.pwwn);
-
- fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
- if (!fcxp) {
- port->stats.ns_rftid_alloc_wait++;
- bfa_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
- bfa_fcs_port_ns_send_rft_id, ns);
- return;
- }
- ns->fcxp = fcxp;
-
- len = fc_rftid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
- bfa_fcs_port_get_fcid(port), 0,
- port->port_cfg.roles);
-
- bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
- FC_CLASS_3, len, &fchs, bfa_fcs_port_ns_rft_id_response,
- (void *)ns, FC_MAX_PDUSZ, FC_FCCT_TOV);
-
- port->stats.ns_rftid_sent++;
- bfa_sm_send_event(ns, NSSM_EVENT_RFTID_SENT);
-}
-
-static void
-bfa_fcs_port_ns_rft_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
- void *cbarg, bfa_status_t req_status,
- u32 rsp_len, u32 resid_len,
- struct fchs_s *rsp_fchs)
-{
- struct bfa_fcs_port_ns_s *ns = (struct bfa_fcs_port_ns_s *)cbarg;
- struct bfa_fcs_port_s *port = ns->port;
- struct ct_hdr_s *cthdr = NULL;
-
- bfa_trc(port->fcs, port->port_cfg.pwwn);
-
- /*
- * Sanity Checks
- */
- if (req_status != BFA_STATUS_OK) {
- bfa_trc(port->fcs, req_status);
- port->stats.ns_rftid_rsp_err++;
- bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
- return;
- }
-
- cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
- cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
-
- if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
- port->stats.ns_rftid_accepts++;
- bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
- return;
- }
-
- port->stats.ns_rftid_rejects++;
- bfa_trc(port->fcs, cthdr->reason_code);
- bfa_trc(port->fcs, cthdr->exp_code);
- bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
-}
-
-/**
-* Register FC4-Features : Should be done after RFT_ID
- */
-static void
-bfa_fcs_port_ns_send_rff_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
- struct bfa_fcs_port_ns_s *ns = ns_cbarg;
- struct bfa_fcs_port_s *port = ns->port;
- struct fchs_s fchs;
- int len;
- struct bfa_fcxp_s *fcxp;
- u8 fc4_ftrs = 0;
-
- bfa_trc(port->fcs, port->port_cfg.pwwn);
-
- fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
- if (!fcxp) {
- port->stats.ns_rffid_alloc_wait++;
- bfa_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
- bfa_fcs_port_ns_send_rff_id, ns);
- return;
- }
- ns->fcxp = fcxp;
-
- if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port))
- fc4_ftrs = FC_GS_FCP_FC4_FEATURE_INITIATOR;
- else if (BFA_FCS_VPORT_IS_TARGET_MODE(ns->port))
- fc4_ftrs = FC_GS_FCP_FC4_FEATURE_TARGET;
-
- len = fc_rffid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
- bfa_fcs_port_get_fcid(port), 0, FC_TYPE_FCP,
- fc4_ftrs);
-
- bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
- FC_CLASS_3, len, &fchs, bfa_fcs_port_ns_rff_id_response,
- (void *)ns, FC_MAX_PDUSZ, FC_FCCT_TOV);
-
- port->stats.ns_rffid_sent++;
- bfa_sm_send_event(ns, NSSM_EVENT_RFFID_SENT);
-}
-
-static void
-bfa_fcs_port_ns_rff_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
- void *cbarg, bfa_status_t req_status,
- u32 rsp_len, u32 resid_len,
- struct fchs_s *rsp_fchs)
-{
- struct bfa_fcs_port_ns_s *ns = (struct bfa_fcs_port_ns_s *)cbarg;
- struct bfa_fcs_port_s *port = ns->port;
- struct ct_hdr_s *cthdr = NULL;
-
- bfa_trc(port->fcs, port->port_cfg.pwwn);
-
- /*
- * Sanity Checks
- */
- if (req_status != BFA_STATUS_OK) {
- bfa_trc(port->fcs, req_status);
- port->stats.ns_rffid_rsp_err++;
- bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
- return;
- }
-
- cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
- cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
-
- if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
- port->stats.ns_rffid_accepts++;
- bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
- return;
- }
-
- port->stats.ns_rffid_rejects++;
- bfa_trc(port->fcs, cthdr->reason_code);
- bfa_trc(port->fcs, cthdr->exp_code);
-
- if (cthdr->reason_code == CT_RSN_NOT_SUPP) {
- /*
- * if this command is not supported, we don't retry
- */
- bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
- } else {
- bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
- }
-}
-
-/**
- * Query Fabric for FC4-Types Devices.
- *
-* TBD : Need to use a local (FCS private) response buffer, since the response
- * can be larger than 2K.
- */
-static void
-bfa_fcs_port_ns_send_gid_ft(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
- struct bfa_fcs_port_ns_s *ns = ns_cbarg;
- struct bfa_fcs_port_s *port = ns->port;
- struct fchs_s fchs;
- int len;
- struct bfa_fcxp_s *fcxp;
-
- bfa_trc(port->fcs, port->pid);
-
- fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
- if (!fcxp) {
- port->stats.ns_gidft_alloc_wait++;
- bfa_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
- bfa_fcs_port_ns_send_gid_ft, ns);
- return;
- }
- ns->fcxp = fcxp;
-
- /*
- * This query is only initiated for FCP initiator mode.
- */
- len = fc_gid_ft_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), ns->port->pid,
- FC_TYPE_FCP);
-
- bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
- FC_CLASS_3, len, &fchs, bfa_fcs_port_ns_gid_ft_response,
- (void *)ns, bfa_fcxp_get_maxrsp(port->fcs->bfa),
- FC_FCCT_TOV);
-
- port->stats.ns_gidft_sent++;
-
- bfa_sm_send_event(ns, NSSM_EVENT_GIDFT_SENT);
-}
-
-static void
-bfa_fcs_port_ns_gid_ft_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
- void *cbarg, bfa_status_t req_status,
- u32 rsp_len, u32 resid_len,
- struct fchs_s *rsp_fchs)
-{
- struct bfa_fcs_port_ns_s *ns = (struct bfa_fcs_port_ns_s *)cbarg;
- struct bfa_fcs_port_s *port = ns->port;
- struct ct_hdr_s *cthdr = NULL;
- u32 n_pids;
-
- bfa_trc(port->fcs, port->port_cfg.pwwn);
-
- /*
- * Sanity Checks
- */
- if (req_status != BFA_STATUS_OK) {
- bfa_trc(port->fcs, req_status);
- port->stats.ns_gidft_rsp_err++;
- bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
- return;
- }
-
- if (resid_len != 0) {
- /*
- * TBD : we will need to allocate a larger buffer & retry the
- * command
- */
- bfa_trc(port->fcs, rsp_len);
- bfa_trc(port->fcs, resid_len);
- return;
- }
-
- cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
- cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
-
- switch (cthdr->cmd_rsp_code) {
-
- case CT_RSP_ACCEPT:
-
- port->stats.ns_gidft_accepts++;
- n_pids = (fc_get_ctresp_pyld_len(rsp_len) / sizeof(u32));
- bfa_trc(port->fcs, n_pids);
- bfa_fcs_port_ns_process_gidft_pids(port,
- (u32 *) (cthdr + 1),
- n_pids);
- bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
- break;
-
- case CT_RSP_REJECT:
-
- /*
- * Check the reason code & explanation.
- * There may not have been any FC4 devices in the fabric
- */
- port->stats.ns_gidft_rejects++;
- bfa_trc(port->fcs, cthdr->reason_code);
- bfa_trc(port->fcs, cthdr->exp_code);
-
- if ((cthdr->reason_code == CT_RSN_UNABLE_TO_PERF)
- && (cthdr->exp_code == CT_NS_EXP_FT_NOT_REG)) {
-
- bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
- } else {
- /*
- * for all other errors, retry
- */
- bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
- }
- break;
-
- default:
- port->stats.ns_gidft_unknown_rsp++;
- bfa_trc(port->fcs, cthdr->cmd_rsp_code);
- bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
- }
-}
-
-/**
- * This routine will be called by bfa_timer on timer timeouts.
- *
- * param[in] port - pointer to bfa_fcs_port_t.
- *
- * return
- * void
- *
-* Special Considerations:
- *
- * note
- */
-static void
-bfa_fcs_port_ns_timeout(void *arg)
-{
- struct bfa_fcs_port_ns_s *ns = (struct bfa_fcs_port_ns_s *)arg;
-
- ns->port->stats.ns_timeouts++;
- bfa_sm_send_event(ns, NSSM_EVENT_TIMEOUT);
-}
-
-/*
- * Process the PID list in GID_FT response
- */
-static void
-bfa_fcs_port_ns_process_gidft_pids(struct bfa_fcs_port_s *port,
- u32 *pid_buf, u32 n_pids)
-{
- struct fcgs_gidft_resp_s *gidft_entry;
- struct bfa_fcs_rport_s *rport;
- u32 ii;
-
- for (ii = 0; ii < n_pids; ii++) {
- gidft_entry = (struct fcgs_gidft_resp_s *) &pid_buf[ii];
-
- if (gidft_entry->pid == port->pid)
- continue;
-
- /*
- * Check if this rport already exists
- */
- rport = bfa_fcs_port_get_rport_by_pid(port, gidft_entry->pid);
- if (rport == NULL) {
- /*
- * this is a new device. create rport
- */
- rport = bfa_fcs_rport_create(port, gidft_entry->pid);
- } else {
- /*
- * this rport already exists
- */
- bfa_fcs_rport_scn(rport);
- }
-
- bfa_trc(port->fcs, gidft_entry->pid);
-
- /*
- * if the last entry bit is set, bail out.
- */
- if (gidft_entry->last)
- return;
- }
-}
-
-/**
- * fcs_ns_public FCS nameserver public interfaces
- */
-
-/*
- * Functions called by port/fab.
- * These will send relevant Events to the ns state machine.
- */
-void
-bfa_fcs_port_ns_init(struct bfa_fcs_port_s *port)
-{
- struct bfa_fcs_port_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
-
- ns->port = port;
- bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
-}
-
-void
-bfa_fcs_port_ns_offline(struct bfa_fcs_port_s *port)
-{
- struct bfa_fcs_port_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
-
- ns->port = port;
- bfa_sm_send_event(ns, NSSM_EVENT_PORT_OFFLINE);
-}
-
-void
-bfa_fcs_port_ns_online(struct bfa_fcs_port_s *port)
-{
- struct bfa_fcs_port_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
-
- ns->port = port;
- bfa_sm_send_event(ns, NSSM_EVENT_PORT_ONLINE);
-}
-
-void
-bfa_fcs_port_ns_query(struct bfa_fcs_port_s *port)
-{
- struct bfa_fcs_port_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
-
- bfa_trc(port->fcs, port->pid);
- bfa_sm_send_event(ns, NSSM_EVENT_NS_QUERY);
-}
-
-static void
-bfa_fcs_port_ns_boot_target_disc(struct bfa_fcs_port_s *port)
-{
-
- struct bfa_fcs_rport_s *rport;
- u8 nwwns;
- wwn_t wwns[BFA_PREBOOT_BOOTLUN_MAX];
- int ii;
-
- bfa_iocfc_get_bootwwns(port->fcs->bfa, &nwwns, wwns);
-
- for (ii = 0; ii < nwwns; ++ii) {
- rport = bfa_fcs_rport_create_by_wwn(port, wwns[ii]);
- bfa_assert(rport);
- }
-}
-
-
diff --git a/drivers/scsi/bfa/plog.c b/drivers/scsi/bfa/plog.c
deleted file mode 100644
index fcb8864d3276..000000000000
--- a/drivers/scsi/bfa/plog.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#include <bfa_os_inc.h>
-#include <cs/bfa_plog.h>
-#include <cs/bfa_debug.h>
-
-static int
-plkd_validate_logrec(struct bfa_plog_rec_s *pl_rec)
-{
- if ((pl_rec->log_type != BFA_PL_LOG_TYPE_INT)
- && (pl_rec->log_type != BFA_PL_LOG_TYPE_STRING))
- return 1;
-
- if ((pl_rec->log_type != BFA_PL_LOG_TYPE_INT)
- && (pl_rec->log_num_ints > BFA_PL_INT_LOG_SZ))
- return 1;
-
- return 0;
-}
-
-static void
-bfa_plog_add(struct bfa_plog_s *plog, struct bfa_plog_rec_s *pl_rec)
-{
- u16 tail;
- struct bfa_plog_rec_s *pl_recp;
-
- if (plog->plog_enabled == 0)
- return;
-
- if (plkd_validate_logrec(pl_rec)) {
- bfa_assert(0);
- return;
- }
-
- tail = plog->tail;
-
- pl_recp = &(plog->plog_recs[tail]);
-
- bfa_os_memcpy(pl_recp, pl_rec, sizeof(struct bfa_plog_rec_s));
-
- pl_recp->tv = BFA_TRC_TS(plog);
- BFA_PL_LOG_REC_INCR(plog->tail);
-
- if (plog->head == plog->tail)
- BFA_PL_LOG_REC_INCR(plog->head);
-}
-
-void
-bfa_plog_init(struct bfa_plog_s *plog)
-{
- bfa_os_memset((char *)plog, 0, sizeof(struct bfa_plog_s));
-
- bfa_os_memcpy(plog->plog_sig, BFA_PL_SIG_STR, BFA_PL_SIG_LEN);
- plog->head = plog->tail = 0;
- plog->plog_enabled = 1;
-}
-
-void
-bfa_plog_str(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
- enum bfa_plog_eid event,
- u16 misc, char *log_str)
-{
- struct bfa_plog_rec_s lp;
-
- if (plog->plog_enabled) {
- bfa_os_memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
- lp.mid = mid;
- lp.eid = event;
- lp.log_type = BFA_PL_LOG_TYPE_STRING;
- lp.misc = misc;
- strncpy(lp.log_entry.string_log, log_str,
- BFA_PL_STRING_LOG_SZ - 1);
- lp.log_entry.string_log[BFA_PL_STRING_LOG_SZ - 1] = '\0';
- bfa_plog_add(plog, &lp);
- }
-}
-
-void
-bfa_plog_intarr(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
- enum bfa_plog_eid event,
- u16 misc, u32 *intarr, u32 num_ints)
-{
- struct bfa_plog_rec_s lp;
- u32 i;
-
- if (num_ints > BFA_PL_INT_LOG_SZ)
- num_ints = BFA_PL_INT_LOG_SZ;
-
- if (plog->plog_enabled) {
- bfa_os_memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
- lp.mid = mid;
- lp.eid = event;
- lp.log_type = BFA_PL_LOG_TYPE_INT;
- lp.misc = misc;
-
- for (i = 0; i < num_ints; i++)
- bfa_os_assign(lp.log_entry.int_log[i],
- intarr[i]);
-
- lp.log_num_ints = (u8) num_ints;
-
- bfa_plog_add(plog, &lp);
- }
-}
-
-void
-bfa_plog_fchdr(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
- enum bfa_plog_eid event,
- u16 misc, struct fchs_s *fchdr)
-{
- struct bfa_plog_rec_s lp;
- u32 *tmp_int = (u32 *) fchdr;
- u32 ints[BFA_PL_INT_LOG_SZ];
-
- if (plog->plog_enabled) {
- bfa_os_memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
-
- ints[0] = tmp_int[0];
- ints[1] = tmp_int[1];
- ints[2] = tmp_int[4];
-
- bfa_plog_intarr(plog, mid, event, misc, ints, 3);
- }
-}
-
-void
-bfa_plog_fchdr_and_pl(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
- enum bfa_plog_eid event, u16 misc, struct fchs_s *fchdr,
- u32 pld_w0)
-{
- struct bfa_plog_rec_s lp;
- u32 *tmp_int = (u32 *) fchdr;
- u32 ints[BFA_PL_INT_LOG_SZ];
-
- if (plog->plog_enabled) {
- bfa_os_memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
-
- ints[0] = tmp_int[0];
- ints[1] = tmp_int[1];
- ints[2] = tmp_int[4];
- ints[3] = pld_w0;
-
- bfa_plog_intarr(plog, mid, event, misc, ints, 4);
- }
-}
-
-void
-bfa_plog_clear(struct bfa_plog_s *plog)
-{
- plog->head = plog->tail = 0;
-}
-
-void
-bfa_plog_enable(struct bfa_plog_s *plog)
-{
- plog->plog_enabled = 1;
-}
-
-void
-bfa_plog_disable(struct bfa_plog_s *plog)
-{
- plog->plog_enabled = 0;
-}
-
-bfa_boolean_t
-bfa_plog_get_setting(struct bfa_plog_s *plog)
-{
- return (bfa_boolean_t)plog->plog_enabled;
-}
diff --git a/drivers/scsi/bfa/rport_api.c b/drivers/scsi/bfa/rport_api.c
deleted file mode 100644
index 15e0c470afd9..000000000000
--- a/drivers/scsi/bfa/rport_api.c
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-#include <bfa.h>
-#include <bfa_svc.h>
-#include "fcs_vport.h"
-#include "fcs_lport.h"
-#include "fcs_rport.h"
-#include "fcs_trcmod.h"
-
-BFA_TRC_FILE(FCS, RPORT_API);
-
-/**
- * rport_api.c Remote port implementation.
- */
-
-/**
- * fcs_rport_api FCS rport API.
- */
-
-/**
- * Direct API to add a target by port wwn. This interface is used, for
- * example, by bios when target pwwn is known from boot lun configuration.
- */
-bfa_status_t
-bfa_fcs_rport_add(struct bfa_fcs_port_s *port, wwn_t *pwwn,
- struct bfa_fcs_rport_s *rport,
- struct bfad_rport_s *rport_drv)
-{
- bfa_trc(port->fcs, *pwwn);
-
- return BFA_STATUS_OK;
-}
-
-/**
- * Direct API to remove a target and its associated resources. This
- * interface is used, for example, by vmware driver to remove target
- * ports from the target list for a VM.
- */
-bfa_status_t
-bfa_fcs_rport_remove(struct bfa_fcs_rport_s *rport_in)
-{
-
- struct bfa_fcs_rport_s *rport;
-
- bfa_trc(rport_in->fcs, rport_in->pwwn);
-
- rport = bfa_fcs_port_get_rport_by_pwwn(rport_in->port, rport_in->pwwn);
- if (rport == NULL) {
- /*
- * TBD Error handling
- */
- bfa_trc(rport_in->fcs, rport_in->pid);
- return BFA_STATUS_UNKNOWN_RWWN;
- }
-
- /*
- * TBD if this remote port is online, send a logo
- */
- return BFA_STATUS_OK;
-
-}
-
-/**
- * Remote device status for display/debug.
- */
-void
-bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport,
- struct bfa_rport_attr_s *rport_attr)
-{
- struct bfa_rport_qos_attr_s qos_attr;
- struct bfa_fcs_port_s *port = rport->port;
- enum bfa_pport_speed rport_speed = rport->rpf.rpsc_speed;
-
- bfa_os_memset(rport_attr, 0, sizeof(struct bfa_rport_attr_s));
-
- rport_attr->pid = rport->pid;
- rport_attr->pwwn = rport->pwwn;
- rport_attr->nwwn = rport->nwwn;
- rport_attr->cos_supported = rport->fc_cos;
- rport_attr->df_sz = rport->maxfrsize;
- rport_attr->state = bfa_fcs_rport_get_state(rport);
- rport_attr->fc_cos = rport->fc_cos;
- rport_attr->cisc = rport->cisc;
- rport_attr->scsi_function = rport->scsi_function;
- rport_attr->curr_speed = rport->rpf.rpsc_speed;
- rport_attr->assigned_speed = rport->rpf.assigned_speed;
-
- bfa_rport_get_qos_attr(rport->bfa_rport, &qos_attr);
- rport_attr->qos_attr = qos_attr;
-
- rport_attr->trl_enforced = BFA_FALSE;
-
- if (bfa_fcport_is_ratelim(port->fcs->bfa)) {
- if (rport_speed == BFA_PPORT_SPEED_UNKNOWN) {
- /* Use default ratelim speed setting */
- rport_speed =
- bfa_fcport_get_ratelim_speed(rport->fcs->bfa);
- }
- if (rport_speed < bfa_fcs_port_get_rport_max_speed(port))
- rport_attr->trl_enforced = BFA_TRUE;
- }
-
- /*
- * TODO
- * rport->symname
- */
-}
-
-/**
- * Per remote device statistics.
- */
-void
-bfa_fcs_rport_get_stats(struct bfa_fcs_rport_s *rport,
- struct bfa_rport_stats_s *stats)
-{
- *stats = rport->stats;
-}
-
-void
-bfa_fcs_rport_clear_stats(struct bfa_fcs_rport_s *rport)
-{
- bfa_os_memset((char *)&rport->stats, 0,
- sizeof(struct bfa_rport_stats_s));
-}
-
-struct bfa_fcs_rport_s *
-bfa_fcs_rport_lookup(struct bfa_fcs_port_s *port, wwn_t rpwwn)
-{
- struct bfa_fcs_rport_s *rport;
-
- rport = bfa_fcs_port_get_rport_by_pwwn(port, rpwwn);
- if (rport == NULL) {
- /*
- * TBD Error handling
- */
- }
-
- return rport;
-}
-
-struct bfa_fcs_rport_s *
-bfa_fcs_rport_lookup_by_nwwn(struct bfa_fcs_port_s *port, wwn_t rnwwn)
-{
- struct bfa_fcs_rport_s *rport;
-
- rport = bfa_fcs_port_get_rport_by_nwwn(port, rnwwn);
- if (rport == NULL) {
- /*
- * TBD Error handling
- */
- }
-
- return rport;
-}
-
-/*
- * This API is to set the Rport's speed. Should be used when RPSC is not
- * supported by the rport.
- */
-void
-bfa_fcs_rport_set_speed(struct bfa_fcs_rport_s *rport,
- enum bfa_pport_speed speed)
-{
- rport->rpf.assigned_speed = speed;
-
- /* Set this speed in f/w only if the RPSC speed is not available */
- if (rport->rpf.rpsc_speed == BFA_PPORT_SPEED_UNKNOWN)
- bfa_rport_speed(rport->bfa_rport, speed);
-}
-
-
diff --git a/drivers/scsi/bfa/rport_ftrs.c b/drivers/scsi/bfa/rport_ftrs.c
deleted file mode 100644
index f2a9361ce9a4..000000000000
--- a/drivers/scsi/bfa/rport_ftrs.c
+++ /dev/null
@@ -1,379 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/**
- * rport_ftrs.c Remote port features (RPF) implementation.
- */
-
-#include <bfa.h>
-#include <bfa_svc.h>
-#include "fcbuild.h"
-#include "fcs_rport.h"
-#include "fcs_lport.h"
-#include "fcs_trcmod.h"
-#include "fcs_fcxp.h"
-#include "fcs.h"
-
-BFA_TRC_FILE(FCS, RPORT_FTRS);
-
-#define BFA_FCS_RPF_RETRIES (3)
-#define BFA_FCS_RPF_RETRY_TIMEOUT (1000) /* 1 sec (In millisecs) */
-
-static void bfa_fcs_rpf_send_rpsc2(void *rport_cbarg,
- struct bfa_fcxp_s *fcxp_alloced);
-static void bfa_fcs_rpf_rpsc2_response(void *fcsarg,
- struct bfa_fcxp_s *fcxp, void *cbarg,
- bfa_status_t req_status, u32 rsp_len,
- u32 resid_len,
- struct fchs_s *rsp_fchs);
-static void bfa_fcs_rpf_timeout(void *arg);
-
-/**
- * fcs_rport_ftrs_sm FCS rport state machine events
- */
-
-enum rpf_event {
- RPFSM_EVENT_RPORT_OFFLINE = 1, /* Rport offline */
- RPFSM_EVENT_RPORT_ONLINE = 2, /* Rport online */
- RPFSM_EVENT_FCXP_SENT = 3, /* Frame from has been sent */
- RPFSM_EVENT_TIMEOUT = 4, /* Rport SM timeout event */
- RPFSM_EVENT_RPSC_COMP = 5,
- RPFSM_EVENT_RPSC_FAIL = 6,
- RPFSM_EVENT_RPSC_ERROR = 7,
-};
-
-static void bfa_fcs_rpf_sm_uninit(struct bfa_fcs_rpf_s *rpf,
- enum rpf_event event);
-static void bfa_fcs_rpf_sm_rpsc_sending(struct bfa_fcs_rpf_s *rpf,
- enum rpf_event event);
-static void bfa_fcs_rpf_sm_rpsc(struct bfa_fcs_rpf_s *rpf,
- enum rpf_event event);
-static void bfa_fcs_rpf_sm_rpsc_retry(struct bfa_fcs_rpf_s *rpf,
- enum rpf_event event);
-static void bfa_fcs_rpf_sm_offline(struct bfa_fcs_rpf_s *rpf,
- enum rpf_event event);
-static void bfa_fcs_rpf_sm_online(struct bfa_fcs_rpf_s *rpf,
- enum rpf_event event);
-
-static void
-bfa_fcs_rpf_sm_uninit(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
-{
- struct bfa_fcs_rport_s *rport = rpf->rport;
- struct bfa_fcs_fabric_s *fabric = &rport->fcs->fabric;
-
- bfa_trc(rport->fcs, rport->pwwn);
- bfa_trc(rport->fcs, rport->pid);
- bfa_trc(rport->fcs, event);
-
- switch (event) {
- case RPFSM_EVENT_RPORT_ONLINE:
- /* Send RPSC2 to a Brocade fabric only. */
- if ((!BFA_FCS_PID_IS_WKA(rport->pid)) &&
- ((bfa_lps_is_brcd_fabric(rport->port->fabric->lps)) ||
- (bfa_fcs_fabric_get_switch_oui(fabric) ==
- BFA_FCS_BRCD_SWITCH_OUI))) {
- bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);
- rpf->rpsc_retries = 0;
- bfa_fcs_rpf_send_rpsc2(rpf, NULL);
- }
- break;
-
- case RPFSM_EVENT_RPORT_OFFLINE:
- break;
-
- default:
- bfa_sm_fault(rport->fcs, event);
- }
-}
-
-static void
-bfa_fcs_rpf_sm_rpsc_sending(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
-{
- struct bfa_fcs_rport_s *rport = rpf->rport;
-
- bfa_trc(rport->fcs, event);
-
- switch (event) {
- case RPFSM_EVENT_FCXP_SENT:
- bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc);
- break;
-
- case RPFSM_EVENT_RPORT_OFFLINE:
- bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
- bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rpf->fcxp_wqe);
- rpf->rpsc_retries = 0;
- break;
-
- default:
- bfa_sm_fault(rport->fcs, event);
- }
-}
-
-static void
-bfa_fcs_rpf_sm_rpsc(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
-{
- struct bfa_fcs_rport_s *rport = rpf->rport;
-
- bfa_trc(rport->fcs, rport->pid);
- bfa_trc(rport->fcs, event);
-
- switch (event) {
- case RPFSM_EVENT_RPSC_COMP:
- bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online);
- /* Update speed info in f/w via BFA */
- if (rpf->rpsc_speed != BFA_PPORT_SPEED_UNKNOWN)
- bfa_rport_speed(rport->bfa_rport, rpf->rpsc_speed);
- else if (rpf->assigned_speed != BFA_PPORT_SPEED_UNKNOWN)
- bfa_rport_speed(rport->bfa_rport, rpf->assigned_speed);
- break;
-
- case RPFSM_EVENT_RPSC_FAIL:
- /* RPSC not supported by rport */
- bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online);
- break;
-
- case RPFSM_EVENT_RPSC_ERROR:
- /* need to retry...delayed a bit. */
- if (rpf->rpsc_retries++ < BFA_FCS_RPF_RETRIES) {
- bfa_timer_start(rport->fcs->bfa, &rpf->timer,
- bfa_fcs_rpf_timeout, rpf,
- BFA_FCS_RPF_RETRY_TIMEOUT);
- bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_retry);
- } else {
- bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online);
- }
- break;
-
- case RPFSM_EVENT_RPORT_OFFLINE:
- bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
- bfa_fcxp_discard(rpf->fcxp);
- rpf->rpsc_retries = 0;
- break;
-
- default:
- bfa_sm_fault(rport->fcs, event);
- }
-}
-
-static void
-bfa_fcs_rpf_sm_rpsc_retry(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
-{
- struct bfa_fcs_rport_s *rport = rpf->rport;
-
- bfa_trc(rport->fcs, rport->pid);
- bfa_trc(rport->fcs, event);
-
- switch (event) {
- case RPFSM_EVENT_TIMEOUT:
- /* re-send the RPSC */
- bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);
- bfa_fcs_rpf_send_rpsc2(rpf, NULL);
- break;
-
- case RPFSM_EVENT_RPORT_OFFLINE:
- bfa_timer_stop(&rpf->timer);
- bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
- rpf->rpsc_retries = 0;
- break;
-
- default:
- bfa_sm_fault(rport->fcs, event);
- }
-}
-
-static void
-bfa_fcs_rpf_sm_online(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
-{
- struct bfa_fcs_rport_s *rport = rpf->rport;
-
- bfa_trc(rport->fcs, rport->pwwn);
- bfa_trc(rport->fcs, rport->pid);
- bfa_trc(rport->fcs, event);
-
- switch (event) {
- case RPFSM_EVENT_RPORT_OFFLINE:
- bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
- rpf->rpsc_retries = 0;
- break;
-
- default:
- bfa_sm_fault(rport->fcs, event);
- }
-}
-
-static void
-bfa_fcs_rpf_sm_offline(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
-{
- struct bfa_fcs_rport_s *rport = rpf->rport;
-
- bfa_trc(rport->fcs, rport->pwwn);
- bfa_trc(rport->fcs, rport->pid);
- bfa_trc(rport->fcs, event);
-
- switch (event) {
- case RPFSM_EVENT_RPORT_ONLINE:
- bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);
- bfa_fcs_rpf_send_rpsc2(rpf, NULL);
- break;
-
- case RPFSM_EVENT_RPORT_OFFLINE:
- break;
-
- default:
- bfa_sm_fault(rport->fcs, event);
- }
-}
-/**
- * Called when Rport is created.
- */
-void bfa_fcs_rpf_init(struct bfa_fcs_rport_s *rport)
-{
- struct bfa_fcs_rpf_s *rpf = &rport->rpf;
-
- bfa_trc(rport->fcs, rport->pid);
- rpf->rport = rport;
-
- bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_uninit);
-}
-
-/**
- * Called when Rport becomes online
- */
-void bfa_fcs_rpf_rport_online(struct bfa_fcs_rport_s *rport)
-{
- bfa_trc(rport->fcs, rport->pid);
-
- if (__fcs_min_cfg(rport->port->fcs))
- return;
-
- if (bfa_fcs_fabric_is_switched(rport->port->fabric))
- bfa_sm_send_event(&rport->rpf, RPFSM_EVENT_RPORT_ONLINE);
-}
-
-/**
- * Called when Rport becomes offline
- */
-void bfa_fcs_rpf_rport_offline(struct bfa_fcs_rport_s *rport)
-{
- bfa_trc(rport->fcs, rport->pid);
-
- if (__fcs_min_cfg(rport->port->fcs))
- return;
-
- rport->rpf.rpsc_speed = 0;
- bfa_sm_send_event(&rport->rpf, RPFSM_EVENT_RPORT_OFFLINE);
-}
-
-static void
-bfa_fcs_rpf_timeout(void *arg)
-{
- struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *) arg;
- struct bfa_fcs_rport_s *rport = rpf->rport;
-
- bfa_trc(rport->fcs, rport->pid);
- bfa_sm_send_event(rpf, RPFSM_EVENT_TIMEOUT);
-}
-
-static void
-bfa_fcs_rpf_send_rpsc2(void *rpf_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
- struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *)rpf_cbarg;
- struct bfa_fcs_rport_s *rport = rpf->rport;
- struct bfa_fcs_port_s *port = rport->port;
- struct fchs_s fchs;
- int len;
- struct bfa_fcxp_s *fcxp;
-
- bfa_trc(rport->fcs, rport->pwwn);
-
- fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
- if (!fcxp) {
- bfa_fcxp_alloc_wait(port->fcs->bfa, &rpf->fcxp_wqe,
- bfa_fcs_rpf_send_rpsc2, rpf);
- return;
- }
- rpf->fcxp = fcxp;
-
- len = fc_rpsc2_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
- bfa_fcs_port_get_fcid(port), &rport->pid, 1);
-
- bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
- FC_CLASS_3, len, &fchs, bfa_fcs_rpf_rpsc2_response,
- rpf, FC_MAX_PDUSZ, FC_ELS_TOV);
- rport->stats.rpsc_sent++;
- bfa_sm_send_event(rpf, RPFSM_EVENT_FCXP_SENT);
-
-}
-
-static void
-bfa_fcs_rpf_rpsc2_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
- bfa_status_t req_status, u32 rsp_len,
- u32 resid_len, struct fchs_s *rsp_fchs)
-{
- struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *) cbarg;
- struct bfa_fcs_rport_s *rport = rpf->rport;
- struct fc_ls_rjt_s *ls_rjt;
- struct fc_rpsc2_acc_s *rpsc2_acc;
- u16 num_ents;
-
- bfa_trc(rport->fcs, req_status);
-
- if (req_status != BFA_STATUS_OK) {
- bfa_trc(rport->fcs, req_status);
- if (req_status == BFA_STATUS_ETIMER)
- rport->stats.rpsc_failed++;
- bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);
- return;
- }
-
- rpsc2_acc = (struct fc_rpsc2_acc_s *) BFA_FCXP_RSP_PLD(fcxp);
- if (rpsc2_acc->els_cmd == FC_ELS_ACC) {
- rport->stats.rpsc_accs++;
- num_ents = bfa_os_ntohs(rpsc2_acc->num_pids);
- bfa_trc(rport->fcs, num_ents);
- if (num_ents > 0) {
- bfa_assert(rpsc2_acc->port_info[0].pid != rport->pid);
- bfa_trc(rport->fcs,
- bfa_os_ntohs(rpsc2_acc->port_info[0].pid));
- bfa_trc(rport->fcs,
- bfa_os_ntohs(rpsc2_acc->port_info[0].speed));
- bfa_trc(rport->fcs,
- bfa_os_ntohs(rpsc2_acc->port_info[0].index));
- bfa_trc(rport->fcs,
- rpsc2_acc->port_info[0].type);
-
- if (rpsc2_acc->port_info[0].speed == 0) {
- bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);
- return;
- }
-
- rpf->rpsc_speed = fc_rpsc_operspeed_to_bfa_speed(
- bfa_os_ntohs(rpsc2_acc->port_info[0].speed));
-
- bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_COMP);
- }
- } else {
- ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
- bfa_trc(rport->fcs, ls_rjt->reason_code);
- bfa_trc(rport->fcs, ls_rjt->reason_code_expl);
- rport->stats.rpsc_rejects++;
- if (ls_rjt->reason_code == FC_LS_RJT_RSN_CMD_NOT_SUPP)
- bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_FAIL);
- else
- bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);
- }
-}
diff --git a/drivers/scsi/bfa/scn.c b/drivers/scsi/bfa/scn.c
deleted file mode 100644
index 8a60129e6307..000000000000
--- a/drivers/scsi/bfa/scn.c
+++ /dev/null
@@ -1,482 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#include <bfa.h>
-#include <bfa_svc.h>
-#include "fcs_lport.h"
-#include "fcs_rport.h"
-#include "fcs_ms.h"
-#include "fcs_trcmod.h"
-#include "fcs_fcxp.h"
-#include "fcs.h"
-#include "lport_priv.h"
-
-BFA_TRC_FILE(FCS, SCN);
-
-#define FC_QOS_RSCN_EVENT 0x0c
-#define FC_FABRIC_NAME_RSCN_EVENT 0x0d
-
-/*
- * forward declarations
- */
-static void bfa_fcs_port_scn_send_scr(void *scn_cbarg,
- struct bfa_fcxp_s *fcxp_alloced);
-static void bfa_fcs_port_scn_scr_response(void *fcsarg,
- struct bfa_fcxp_s *fcxp,
- void *cbarg,
- bfa_status_t req_status,
- u32 rsp_len,
- u32 resid_len,
- struct fchs_s *rsp_fchs);
-static void bfa_fcs_port_scn_send_ls_acc(struct bfa_fcs_port_s *port,
- struct fchs_s *rx_fchs);
-static void bfa_fcs_port_scn_timeout(void *arg);
-
-/**
- * fcs_scm_sm FCS SCN state machine
- */
-
-/**
- * VPort SCN State Machine events
- */
-enum port_scn_event {
- SCNSM_EVENT_PORT_ONLINE = 1,
- SCNSM_EVENT_PORT_OFFLINE = 2,
- SCNSM_EVENT_RSP_OK = 3,
- SCNSM_EVENT_RSP_ERROR = 4,
- SCNSM_EVENT_TIMEOUT = 5,
- SCNSM_EVENT_SCR_SENT = 6,
-};
-
-static void bfa_fcs_port_scn_sm_offline(struct bfa_fcs_port_scn_s *scn,
- enum port_scn_event event);
-static void bfa_fcs_port_scn_sm_sending_scr(struct bfa_fcs_port_scn_s *scn,
- enum port_scn_event event);
-static void bfa_fcs_port_scn_sm_scr(struct bfa_fcs_port_scn_s *scn,
- enum port_scn_event event);
-static void bfa_fcs_port_scn_sm_scr_retry(struct bfa_fcs_port_scn_s *scn,
- enum port_scn_event event);
-static void bfa_fcs_port_scn_sm_online(struct bfa_fcs_port_scn_s *scn,
- enum port_scn_event event);
-
-/**
- * Starting state - awaiting link up.
- */
-static void
-bfa_fcs_port_scn_sm_offline(struct bfa_fcs_port_scn_s *scn,
- enum port_scn_event event)
-{
- switch (event) {
- case SCNSM_EVENT_PORT_ONLINE:
- bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_sending_scr);
- bfa_fcs_port_scn_send_scr(scn, NULL);
- break;
-
- case SCNSM_EVENT_PORT_OFFLINE:
- break;
-
- default:
- bfa_sm_fault(scn->port->fcs, event);
- }
-}
-
-static void
-bfa_fcs_port_scn_sm_sending_scr(struct bfa_fcs_port_scn_s *scn,
- enum port_scn_event event)
-{
- switch (event) {
- case SCNSM_EVENT_SCR_SENT:
- bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_scr);
- break;
-
- case SCNSM_EVENT_PORT_OFFLINE:
- bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_offline);
- bfa_fcxp_walloc_cancel(scn->port->fcs->bfa, &scn->fcxp_wqe);
- break;
-
- default:
- bfa_sm_fault(scn->port->fcs, event);
- }
-}
-
-static void
-bfa_fcs_port_scn_sm_scr(struct bfa_fcs_port_scn_s *scn,
- enum port_scn_event event)
-{
- struct bfa_fcs_port_s *port = scn->port;
-
- switch (event) {
- case SCNSM_EVENT_RSP_OK:
- bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_online);
- break;
-
- case SCNSM_EVENT_RSP_ERROR:
- bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_scr_retry);
- bfa_timer_start(port->fcs->bfa, &scn->timer,
- bfa_fcs_port_scn_timeout, scn,
- BFA_FCS_RETRY_TIMEOUT);
- break;
-
- case SCNSM_EVENT_PORT_OFFLINE:
- bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_offline);
- bfa_fcxp_discard(scn->fcxp);
- break;
-
- default:
- bfa_sm_fault(scn->port->fcs, event);
- }
-}
-
-static void
-bfa_fcs_port_scn_sm_scr_retry(struct bfa_fcs_port_scn_s *scn,
- enum port_scn_event event)
-{
- switch (event) {
- case SCNSM_EVENT_TIMEOUT:
- bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_sending_scr);
- bfa_fcs_port_scn_send_scr(scn, NULL);
- break;
-
- case SCNSM_EVENT_PORT_OFFLINE:
- bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_offline);
- bfa_timer_stop(&scn->timer);
- break;
-
- default:
- bfa_sm_fault(scn->port->fcs, event);
- }
-}
-
-static void
-bfa_fcs_port_scn_sm_online(struct bfa_fcs_port_scn_s *scn,
- enum port_scn_event event)
-{
- switch (event) {
- case SCNSM_EVENT_PORT_OFFLINE:
- bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_offline);
- break;
-
- default:
- bfa_sm_fault(scn->port->fcs, event);
- }
-}
-
-
-
-/**
- * fcs_scn_private FCS SCN private functions
- */
-
-/**
- * This routine will be called to send a SCR command.
- */
-static void
-bfa_fcs_port_scn_send_scr(void *scn_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
- struct bfa_fcs_port_scn_s *scn = scn_cbarg;
- struct bfa_fcs_port_s *port = scn->port;
- struct fchs_s fchs;
- int len;
- struct bfa_fcxp_s *fcxp;
-
- bfa_trc(port->fcs, port->pid);
- bfa_trc(port->fcs, port->port_cfg.pwwn);
-
- fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
- if (!fcxp) {
- bfa_fcxp_alloc_wait(port->fcs->bfa, &scn->fcxp_wqe,
- bfa_fcs_port_scn_send_scr, scn);
- return;
- }
- scn->fcxp = fcxp;
-
- /*
- * Handle VU registrations for Base port only
- */
- if ((!port->vport) && bfa_ioc_get_fcmode(&port->fcs->bfa->ioc)) {
- len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
- bfa_lps_is_brcd_fabric(port->fabric->lps),
- port->pid, 0);
- } else {
- len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), BFA_FALSE,
- port->pid, 0);
- }
-
- bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
- FC_CLASS_3, len, &fchs, bfa_fcs_port_scn_scr_response,
- (void *)scn, FC_MAX_PDUSZ, FC_ELS_TOV);
-
- bfa_sm_send_event(scn, SCNSM_EVENT_SCR_SENT);
-}
-
-static void
-bfa_fcs_port_scn_scr_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
- void *cbarg, bfa_status_t req_status,
- u32 rsp_len, u32 resid_len,
- struct fchs_s *rsp_fchs)
-{
- struct bfa_fcs_port_scn_s *scn = (struct bfa_fcs_port_scn_s *)cbarg;
- struct bfa_fcs_port_s *port = scn->port;
- struct fc_els_cmd_s *els_cmd;
- struct fc_ls_rjt_s *ls_rjt;
-
- bfa_trc(port->fcs, port->port_cfg.pwwn);
-
- /*
- * Sanity Checks
- */
- if (req_status != BFA_STATUS_OK) {
- bfa_trc(port->fcs, req_status);
- bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
- return;
- }
-
- els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
-
- switch (els_cmd->els_code) {
-
- case FC_ELS_ACC:
- bfa_sm_send_event(scn, SCNSM_EVENT_RSP_OK);
- break;
-
- case FC_ELS_LS_RJT:
-
- ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
-
- bfa_trc(port->fcs, ls_rjt->reason_code);
- bfa_trc(port->fcs, ls_rjt->reason_code_expl);
-
- bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
- break;
-
- default:
- bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
- }
-}
-
-/*
- * Send a LS Accept
- */
-static void
-bfa_fcs_port_scn_send_ls_acc(struct bfa_fcs_port_s *port,
- struct fchs_s *rx_fchs)
-{
- struct fchs_s fchs;
- struct bfa_fcxp_s *fcxp;
- struct bfa_rport_s *bfa_rport = NULL;
- int len;
-
- bfa_trc(port->fcs, rx_fchs->s_id);
-
- fcxp = bfa_fcs_fcxp_alloc(port->fcs);
- if (!fcxp)
- return;
-
- len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
- bfa_fcs_port_get_fcid(port), rx_fchs->ox_id);
-
- bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
- BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
- FC_MAX_PDUSZ, 0);
-}
-
-/**
- * This routine will be called by bfa_timer on timer timeouts.
- *
- * param[in] vport - pointer to bfa_fcs_port_t.
- * param[out] vport_status - pointer to return vport status in
- *
- * return
- * void
- *
-* Special Considerations:
- *
- * note
- */
-static void
-bfa_fcs_port_scn_timeout(void *arg)
-{
- struct bfa_fcs_port_scn_s *scn = (struct bfa_fcs_port_scn_s *)arg;
-
- bfa_sm_send_event(scn, SCNSM_EVENT_TIMEOUT);
-}
-
-
-
-/**
- * fcs_scn_public FCS state change notification public interfaces
- */
-
-/*
- * Functions called by port/fab
- */
-void
-bfa_fcs_port_scn_init(struct bfa_fcs_port_s *port)
-{
- struct bfa_fcs_port_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
-
- scn->port = port;
- bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_offline);
-}
-
-void
-bfa_fcs_port_scn_offline(struct bfa_fcs_port_s *port)
-{
- struct bfa_fcs_port_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
-
- scn->port = port;
- bfa_sm_send_event(scn, SCNSM_EVENT_PORT_OFFLINE);
-}
-
-void
-bfa_fcs_port_scn_online(struct bfa_fcs_port_s *port)
-{
- struct bfa_fcs_port_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
-
- scn->port = port;
- bfa_sm_send_event(scn, SCNSM_EVENT_PORT_ONLINE);
-}
-
-static void
-bfa_fcs_port_scn_portid_rscn(struct bfa_fcs_port_s *port, u32 rpid)
-{
- struct bfa_fcs_rport_s *rport;
-
- bfa_trc(port->fcs, rpid);
-
- /**
- * If this is an unknown device, then it just came online.
- * Otherwise let rport handle the RSCN event.
- */
- rport = bfa_fcs_port_get_rport_by_pid(port, rpid);
- if (rport == NULL) {
- /*
- * If min cfg mode is enabled, we donot need to
- * discover any new rports.
- */
- if (!__fcs_min_cfg(port->fcs))
- rport = bfa_fcs_rport_create(port, rpid);
- } else {
- bfa_fcs_rport_scn(rport);
- }
-}
-
-/**
- * rscn format based PID comparison
- */
-#define __fc_pid_match(__c0, __c1, __fmt) \
- (((__fmt) == FC_RSCN_FORMAT_FABRIC) || \
- (((__fmt) == FC_RSCN_FORMAT_DOMAIN) && \
- ((__c0)[0] == (__c1)[0])) || \
- (((__fmt) == FC_RSCN_FORMAT_AREA) && \
- ((__c0)[0] == (__c1)[0]) && \
- ((__c0)[1] == (__c1)[1])))
-
-static void
-bfa_fcs_port_scn_multiport_rscn(struct bfa_fcs_port_s *port,
- enum fc_rscn_format format, u32 rscn_pid)
-{
- struct bfa_fcs_rport_s *rport;
- struct list_head *qe, *qe_next;
- u8 *c0, *c1;
-
- bfa_trc(port->fcs, format);
- bfa_trc(port->fcs, rscn_pid);
-
- c0 = (u8 *) &rscn_pid;
-
- list_for_each_safe(qe, qe_next, &port->rport_q) {
- rport = (struct bfa_fcs_rport_s *)qe;
- c1 = (u8 *) &rport->pid;
- if (__fc_pid_match(c0, c1, format))
- bfa_fcs_rport_scn(rport);
- }
-}
-
-void
-bfa_fcs_port_scn_process_rscn(struct bfa_fcs_port_s *port, struct fchs_s *fchs,
- u32 len)
-{
- struct fc_rscn_pl_s *rscn = (struct fc_rscn_pl_s *) (fchs + 1);
- int num_entries;
- u32 rscn_pid;
- bfa_boolean_t nsquery = BFA_FALSE;
- int i = 0;
-
- num_entries =
- (bfa_os_ntohs(rscn->payldlen) -
- sizeof(u32)) / sizeof(rscn->event[0]);
-
- bfa_trc(port->fcs, num_entries);
-
- port->stats.num_rscn++;
-
- bfa_fcs_port_scn_send_ls_acc(port, fchs);
-
- for (i = 0; i < num_entries; i++) {
- rscn_pid = rscn->event[i].portid;
-
- bfa_trc(port->fcs, rscn->event[i].format);
- bfa_trc(port->fcs, rscn_pid);
-
- switch (rscn->event[i].format) {
- case FC_RSCN_FORMAT_PORTID:
- if (rscn->event[i].qualifier == FC_QOS_RSCN_EVENT) {
- /*
- * Ignore this event. f/w would have processed
- * it
- */
- bfa_trc(port->fcs, rscn_pid);
- } else {
- port->stats.num_portid_rscn++;
- bfa_fcs_port_scn_portid_rscn(port, rscn_pid);
- }
- break;
-
- case FC_RSCN_FORMAT_FABRIC:
- if (rscn->event[i].qualifier ==
- FC_FABRIC_NAME_RSCN_EVENT) {
- bfa_fcs_port_ms_fabric_rscn(port);
- break;
- }
- /*
- * !!!!!!!!! Fall Through !!!!!!!!!!!!!
- */
-
- case FC_RSCN_FORMAT_AREA:
- case FC_RSCN_FORMAT_DOMAIN:
- nsquery = BFA_TRUE;
- bfa_fcs_port_scn_multiport_rscn(port,
- rscn->event[i].format,
- rscn_pid);
- break;
-
- default:
- bfa_assert(0);
- nsquery = BFA_TRUE;
- }
- }
-
- /**
- * If any of area, domain or fabric RSCN is received, do a fresh discovery
- * to find new devices.
- */
- if (nsquery)
- bfa_fcs_port_ns_query(port);
-}
-
-
diff --git a/drivers/scsi/bfa/vfapi.c b/drivers/scsi/bfa/vfapi.c
deleted file mode 100644
index 391a4790bebd..000000000000
--- a/drivers/scsi/bfa/vfapi.c
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/**
- * vfapi.c Fabric module implementation.
- */
-
-#include "fcs_fabric.h"
-#include "fcs_trcmod.h"
-
-BFA_TRC_FILE(FCS, VFAPI);
-
-/**
- * fcs_vf_api virtual fabrics API
- */
-
-/**
- * Enable VF mode.
- *
- * @param[in] fcs fcs module instance
- * @param[in] vf_id default vf_id of port, FC_VF_ID_NULL
- * to use standard default vf_id of 1.
- *
- * @retval BFA_STATUS_OK vf mode is enabled
- * @retval BFA_STATUS_BUSY Port is active. Port must be disabled
- * before VF mode can be enabled.
- */
-bfa_status_t
-bfa_fcs_vf_mode_enable(struct bfa_fcs_s *fcs, u16 vf_id)
-{
- return BFA_STATUS_OK;
-}
-
-/**
- * Disable VF mode.
- *
- * @param[in] fcs fcs module instance
- *
- * @retval BFA_STATUS_OK vf mode is disabled
- * @retval BFA_STATUS_BUSY VFs are present and being used. All
- * VFs must be deleted before disabling
- * VF mode.
- */
-bfa_status_t
-bfa_fcs_vf_mode_disable(struct bfa_fcs_s *fcs)
-{
- return BFA_STATUS_OK;
-}
-
-/**
- * Create a new VF instance.
- *
- * A new VF is created using the given VF configuration. A VF is identified
- * by VF id. No duplicate VF creation is allowed with the same VF id. Once
- * a VF is created, VF is automatically started after link initialization
- * and EVFP exchange is completed.
- *
- * param[in] vf - FCS vf data structure. Memory is
- * allocated by caller (driver)
- * param[in] fcs - FCS module
- * param[in] vf_cfg - VF configuration
- * param[in] vf_drv - Opaque handle back to the driver's
- * virtual vf structure
- *
- * retval BFA_STATUS_OK VF creation is successful
- * retval BFA_STATUS_FAILED VF creation failed
- * retval BFA_STATUS_EEXIST A VF exists with the given vf_id
- */
-bfa_status_t
-bfa_fcs_vf_create(bfa_fcs_vf_t *vf, struct bfa_fcs_s *fcs, u16 vf_id,
- struct bfa_port_cfg_s *port_cfg, struct bfad_vf_s *vf_drv)
-{
- bfa_trc(fcs, vf_id);
- return BFA_STATUS_OK;
-}
-
-/**
- * Use this function to delete a BFA VF object. VF object should
- * be stopped before this function call.
- *
- * param[in] vf - pointer to bfa_vf_t.
- *
- * retval BFA_STATUS_OK On vf deletion success
- * retval BFA_STATUS_BUSY VF is not in a stopped state
- * retval BFA_STATUS_INPROGRESS VF deletion in in progress
- */
-bfa_status_t
-bfa_fcs_vf_delete(bfa_fcs_vf_t *vf)
-{
- bfa_trc(vf->fcs, vf->vf_id);
- return BFA_STATUS_OK;
-}
-
-/**
- * Start participation in VF. This triggers login to the virtual fabric.
- *
- * param[in] vf - pointer to bfa_vf_t.
- *
- * return None
- */
-void
-bfa_fcs_vf_start(bfa_fcs_vf_t *vf)
-{
- bfa_trc(vf->fcs, vf->vf_id);
-}
-
-/**
- * Logout with the virtual fabric.
- *
- * param[in] vf - pointer to bfa_vf_t.
- *
- * retval BFA_STATUS_OK On success.
- * retval BFA_STATUS_INPROGRESS VF is being stopped.
- */
-bfa_status_t
-bfa_fcs_vf_stop(bfa_fcs_vf_t *vf)
-{
- bfa_trc(vf->fcs, vf->vf_id);
- return BFA_STATUS_OK;
-}
-
-/**
- * Returns attributes of the given VF.
- *
- * param[in] vf pointer to bfa_vf_t.
- * param[out] vf_attr vf attributes returned
- *
- * return None
- */
-void
-bfa_fcs_vf_get_attr(bfa_fcs_vf_t *vf, struct bfa_vf_attr_s *vf_attr)
-{
- bfa_trc(vf->fcs, vf->vf_id);
-}
-
-/**
- * Return statistics associated with the given vf.
- *
- * param[in] vf pointer to bfa_vf_t.
- * param[out] vf_stats vf statistics returned
- *
- * @return None
- */
-void
-bfa_fcs_vf_get_stats(bfa_fcs_vf_t *vf, struct bfa_vf_stats_s *vf_stats)
-{
- bfa_os_memcpy(vf_stats, &vf->stats, sizeof(struct bfa_vf_stats_s));
- return;
-}
-
-void
-/**
- * clear statistics associated with the given vf.
- *
- * param[in] vf pointer to bfa_vf_t.
- *
- * @return None
- */
-bfa_fcs_vf_clear_stats(bfa_fcs_vf_t *vf)
-{
- bfa_os_memset(&vf->stats, 0, sizeof(struct bfa_vf_stats_s));
- return;
-}
-
-/**
- * Returns FCS vf structure for a given vf_id.
- *
- * param[in] vf_id - VF_ID
- *
- * return
- * If lookup succeeds, retuns fcs vf object, otherwise returns NULL
- */
-bfa_fcs_vf_t *
-bfa_fcs_vf_lookup(struct bfa_fcs_s *fcs, u16 vf_id)
-{
- bfa_trc(fcs, vf_id);
- if (vf_id == FC_VF_ID_NULL)
- return &fcs->fabric;
-
- /**
- * @todo vf support
- */
-
- return NULL;
-}
-
-/**
- * Returns driver VF structure for a given FCS vf.
- *
- * param[in] vf - pointer to bfa_vf_t
- *
- * return Driver VF structure
- */
-struct bfad_vf_s *
-bfa_fcs_vf_get_drv_vf(bfa_fcs_vf_t *vf)
-{
- bfa_assert(vf);
- bfa_trc(vf->fcs, vf->vf_id);
- return vf->vf_drv;
-}
-
-/**
- * Return the list of VFs configured.
- *
- * param[in] fcs fcs module instance
- * param[out] vf_ids returned list of vf_ids
- * param[in,out] nvfs in:size of vf_ids array,
- * out:total elements present,
- * actual elements returned is limited by the size
- *
- * return Driver VF structure
- */
-void
-bfa_fcs_vf_list(struct bfa_fcs_s *fcs, u16 *vf_ids, int *nvfs)
-{
- bfa_trc(fcs, *nvfs);
-}
-
-/**
- * Return the list of all VFs visible from fabric.
- *
- * param[in] fcs fcs module instance
- * param[out] vf_ids returned list of vf_ids
- * param[in,out] nvfs in:size of vf_ids array,
- * out:total elements present,
- * actual elements returned is limited by the size
- *
- * return Driver VF structure
- */
-void
-bfa_fcs_vf_list_all(struct bfa_fcs_s *fcs, u16 *vf_ids, int *nvfs)
-{
- bfa_trc(fcs, *nvfs);
-}
-
-/**
- * Return the list of local logical ports present in the given VF.
- *
- * param[in] vf vf for which logical ports are returned
- * param[out] lpwwn returned logical port wwn list
- * param[in,out] nlports in:size of lpwwn list;
- * out:total elements present,
- * actual elements returned is limited by the size
- *
- */
-void
-bfa_fcs_vf_get_ports(bfa_fcs_vf_t *vf, wwn_t lpwwn[], int *nlports)
-{
- struct list_head *qe;
- struct bfa_fcs_vport_s *vport;
- int i;
- struct bfa_fcs_s *fcs;
-
- if (vf == NULL || lpwwn == NULL || *nlports == 0)
- return;
-
- fcs = vf->fcs;
-
- bfa_trc(fcs, vf->vf_id);
- bfa_trc(fcs, (u32) *nlports);
-
- i = 0;
- lpwwn[i++] = vf->bport.port_cfg.pwwn;
-
- list_for_each(qe, &vf->vport_q) {
- if (i >= *nlports)
- break;
-
- vport = (struct bfa_fcs_vport_s *) qe;
- lpwwn[i++] = vport->lport.port_cfg.pwwn;
- }
-
- bfa_trc(fcs, i);
- *nlports = i;
- return;
-}
-
-
diff --git a/drivers/scsi/bfa/vport.c b/drivers/scsi/bfa/vport.c
deleted file mode 100644
index b378ec79d386..000000000000
--- a/drivers/scsi/bfa/vport.c
+++ /dev/null
@@ -1,903 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) Version 2 as
- * published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/**
- * bfa_fcs_vport.c FCS virtual port state machine
- */
-
-#include <bfa.h>
-#include <bfa_svc.h>
-#include <fcbuild.h>
-#include "fcs_fabric.h"
-#include "fcs_lport.h"
-#include "fcs_vport.h"
-#include "fcs_trcmod.h"
-#include "fcs.h"
-#include <aen/bfa_aen_lport.h>
-
-BFA_TRC_FILE(FCS, VPORT);
-
-#define __vport_fcs(__vp) ((__vp)->lport.fcs)
-#define __vport_pwwn(__vp) ((__vp)->lport.port_cfg.pwwn)
-#define __vport_nwwn(__vp) ((__vp)->lport.port_cfg.nwwn)
-#define __vport_bfa(__vp) ((__vp)->lport.fcs->bfa)
-#define __vport_fcid(__vp) ((__vp)->lport.pid)
-#define __vport_fabric(__vp) ((__vp)->lport.fabric)
-#define __vport_vfid(__vp) ((__vp)->lport.fabric->vf_id)
-
-#define BFA_FCS_VPORT_MAX_RETRIES 5
-/*
- * Forward declarations
- */
-static void bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport);
-static void bfa_fcs_vport_timeout(void *vport_arg);
-static void bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport);
-static void bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport);
-
-/**
- * fcs_vport_sm FCS virtual port state machine
- */
-
-/**
- * VPort State Machine events
- */
-enum bfa_fcs_vport_event {
- BFA_FCS_VPORT_SM_CREATE = 1, /* vport create event */
- BFA_FCS_VPORT_SM_DELETE = 2, /* vport delete event */
- BFA_FCS_VPORT_SM_START = 3, /* vport start request */
- BFA_FCS_VPORT_SM_STOP = 4, /* stop: unsupported */
- BFA_FCS_VPORT_SM_ONLINE = 5, /* fabric online */
- BFA_FCS_VPORT_SM_OFFLINE = 6, /* fabric offline event */
- BFA_FCS_VPORT_SM_FRMSENT = 7, /* fdisc/logo sent events */
- BFA_FCS_VPORT_SM_RSP_OK = 8, /* good response */
- BFA_FCS_VPORT_SM_RSP_ERROR = 9, /* error/bad response */
- BFA_FCS_VPORT_SM_TIMEOUT = 10, /* delay timer event */
- BFA_FCS_VPORT_SM_DELCOMP = 11, /* lport delete completion */
- BFA_FCS_VPORT_SM_RSP_DUP_WWN = 12, /* Dup wnn error */
- BFA_FCS_VPORT_SM_RSP_FAILED = 13, /* non-retryable failure */
-};
-
-static void bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport,
- enum bfa_fcs_vport_event event);
-static void bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport,
- enum bfa_fcs_vport_event event);
-static void bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport,
- enum bfa_fcs_vport_event event);
-static void bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
- enum bfa_fcs_vport_event event);
-static void bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
- enum bfa_fcs_vport_event event);
-static void bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
- enum bfa_fcs_vport_event event);
-static void bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport,
- enum bfa_fcs_vport_event event);
-static void bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,
- enum bfa_fcs_vport_event event);
-static void bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,
- enum bfa_fcs_vport_event event);
-static void bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport,
- enum bfa_fcs_vport_event event);
-
-static struct bfa_sm_table_s vport_sm_table[] = {
- {BFA_SM(bfa_fcs_vport_sm_uninit), BFA_FCS_VPORT_UNINIT},
- {BFA_SM(bfa_fcs_vport_sm_created), BFA_FCS_VPORT_CREATED},
- {BFA_SM(bfa_fcs_vport_sm_offline), BFA_FCS_VPORT_OFFLINE},
- {BFA_SM(bfa_fcs_vport_sm_fdisc), BFA_FCS_VPORT_FDISC},
- {BFA_SM(bfa_fcs_vport_sm_fdisc_retry), BFA_FCS_VPORT_FDISC_RETRY},
- {BFA_SM(bfa_fcs_vport_sm_online), BFA_FCS_VPORT_ONLINE},
- {BFA_SM(bfa_fcs_vport_sm_deleting), BFA_FCS_VPORT_DELETING},
- {BFA_SM(bfa_fcs_vport_sm_cleanup), BFA_FCS_VPORT_CLEANUP},
- {BFA_SM(bfa_fcs_vport_sm_logo), BFA_FCS_VPORT_LOGO},
- {BFA_SM(bfa_fcs_vport_sm_error), BFA_FCS_VPORT_ERROR}
-};
-
-/**
- * Beginning state.
- */
-static void
-bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport,
- enum bfa_fcs_vport_event event)
-{
- bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
- bfa_trc(__vport_fcs(vport), event);
-
- switch (event) {
- case BFA_FCS_VPORT_SM_CREATE:
- bfa_sm_set_state(vport, bfa_fcs_vport_sm_created);
- bfa_fcs_fabric_addvport(__vport_fabric(vport), vport);
- break;
-
- default:
- bfa_sm_fault(__vport_fcs(vport), event);
- }
-}
-
-/**
- * Created state - a start event is required to start up the state machine.
- */
-static void
-bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport,
- enum bfa_fcs_vport_event event)
-{
- bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
- bfa_trc(__vport_fcs(vport), event);
-
- switch (event) {
- case BFA_FCS_VPORT_SM_START:
- if (bfa_fcs_fabric_is_online(__vport_fabric(vport))
- && bfa_fcs_fabric_npiv_capable(__vport_fabric(vport))) {
- bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
- bfa_fcs_vport_do_fdisc(vport);
- } else {
- /**
- * Fabric is offline or not NPIV capable, stay in
- * offline state.
- */
- vport->vport_stats.fab_no_npiv++;
- bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
- }
- break;
-
- case BFA_FCS_VPORT_SM_DELETE:
- bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
- bfa_fcs_port_delete(&vport->lport);
- break;
-
- case BFA_FCS_VPORT_SM_ONLINE:
- case BFA_FCS_VPORT_SM_OFFLINE:
- /**
- * Ignore ONLINE/OFFLINE events from fabric till vport is started.
- */
- break;
-
- default:
- bfa_sm_fault(__vport_fcs(vport), event);
- }
-}
-
-/**
- * Offline state - awaiting ONLINE event from fabric SM.
- */
-static void
-bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport,
- enum bfa_fcs_vport_event event)
-{
- bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
- bfa_trc(__vport_fcs(vport), event);
-
- switch (event) {
- case BFA_FCS_VPORT_SM_DELETE:
- bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
- bfa_fcs_port_delete(&vport->lport);
- break;
-
- case BFA_FCS_VPORT_SM_ONLINE:
- bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
- vport->fdisc_retries = 0;
- bfa_fcs_vport_do_fdisc(vport);
- break;
-
- case BFA_FCS_VPORT_SM_OFFLINE:
- /*
- * This can happen if the vport couldn't be initialzied due
- * the fact that the npiv was not enabled on the switch. In
- * that case we will put the vport in offline state. However,
- * the link can go down and cause the this event to be sent when
- * we are already offline. Ignore it.
- */
- break;
-
- default:
- bfa_sm_fault(__vport_fcs(vport), event);
- }
-}
-
-/**
- * FDISC is sent and awaiting reply from fabric.
- */
-static void
-bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
- enum bfa_fcs_vport_event event)
-{
- bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
- bfa_trc(__vport_fcs(vport), event);
-
- switch (event) {
- case BFA_FCS_VPORT_SM_DELETE:
- bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
- bfa_lps_discard(vport->lps);
- bfa_fcs_port_delete(&vport->lport);
- break;
-
- case BFA_FCS_VPORT_SM_OFFLINE:
- bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
- bfa_lps_discard(vport->lps);
- break;
-
- case BFA_FCS_VPORT_SM_RSP_OK:
- bfa_sm_set_state(vport, bfa_fcs_vport_sm_online);
- bfa_fcs_port_online(&vport->lport);
- break;
-
- case BFA_FCS_VPORT_SM_RSP_ERROR:
- bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc_retry);
- bfa_timer_start(__vport_bfa(vport), &vport->timer,
- bfa_fcs_vport_timeout, vport,
- BFA_FCS_RETRY_TIMEOUT);
- break;
-
- case BFA_FCS_VPORT_SM_RSP_FAILED:
- bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
- break;
-
- case BFA_FCS_VPORT_SM_RSP_DUP_WWN:
- bfa_sm_set_state(vport, bfa_fcs_vport_sm_error);
- break;
-
- default:
- bfa_sm_fault(__vport_fcs(vport), event);
- }
-}
-
-/**
- * FDISC attempt failed - a timer is active to retry FDISC.
- */
-static void
-bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
- enum bfa_fcs_vport_event event)
-{
- bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
- bfa_trc(__vport_fcs(vport), event);
-
- switch (event) {
- case BFA_FCS_VPORT_SM_DELETE:
- bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
- bfa_timer_stop(&vport->timer);
- bfa_fcs_port_delete(&vport->lport);
- break;
-
- case BFA_FCS_VPORT_SM_OFFLINE:
- bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
- bfa_timer_stop(&vport->timer);
- break;
-
- case BFA_FCS_VPORT_SM_TIMEOUT:
- bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
- vport->vport_stats.fdisc_retries++;
- vport->fdisc_retries++;
- bfa_fcs_vport_do_fdisc(vport);
- break;
-
- default:
- bfa_sm_fault(__vport_fcs(vport), event);
- }
-}
-
-/**
- * Vport is online (FDISC is complete).
- */
-static void
-bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
- enum bfa_fcs_vport_event event)
-{
- bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
- bfa_trc(__vport_fcs(vport), event);
-
- switch (event) {
- case BFA_FCS_VPORT_SM_DELETE:
- bfa_sm_set_state(vport, bfa_fcs_vport_sm_deleting);
- bfa_fcs_port_delete(&vport->lport);
- break;
-
- case BFA_FCS_VPORT_SM_OFFLINE:
- bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
- bfa_lps_discard(vport->lps);
- bfa_fcs_port_offline(&vport->lport);
- break;
-
- default:
- bfa_sm_fault(__vport_fcs(vport), event);
- }
-}
-
-/**
- * Vport is being deleted - awaiting lport delete completion to send
- * LOGO to fabric.
- */
-static void
-bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport,
- enum bfa_fcs_vport_event event)
-{
- bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
- bfa_trc(__vport_fcs(vport), event);
-
- switch (event) {
- case BFA_FCS_VPORT_SM_DELETE:
- break;
-
- case BFA_FCS_VPORT_SM_DELCOMP:
- bfa_sm_set_state(vport, bfa_fcs_vport_sm_logo);
- bfa_fcs_vport_do_logo(vport);
- break;
-
- case BFA_FCS_VPORT_SM_OFFLINE:
- bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
- break;
-
- default:
- bfa_sm_fault(__vport_fcs(vport), event);
- }
-}
-
-/**
- * Error State.
- * This state will be set when the Vport Creation fails due to errors like
- * Dup WWN. In this state only operation allowed is a Vport Delete.
- */
-static void
-bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport,
- enum bfa_fcs_vport_event event)
-{
- bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
- bfa_trc(__vport_fcs(vport), event);
-
- switch (event) {
- case BFA_FCS_VPORT_SM_DELETE:
- bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
- bfa_fcs_port_delete(&vport->lport);
-
- break;
-
- default:
- bfa_trc(__vport_fcs(vport), event);
- }
-}
-
-/**
- * Lport cleanup is in progress since vport is being deleted. Fabric is
- * offline, so no LOGO is needed to complete vport deletion.
- */
-static void
-bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,
- enum bfa_fcs_vport_event event)
-{
- bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
- bfa_trc(__vport_fcs(vport), event);
-
- switch (event) {
- case BFA_FCS_VPORT_SM_DELCOMP:
- bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
- bfa_fcs_vport_free(vport);
- break;
-
- case BFA_FCS_VPORT_SM_DELETE:
- break;
-
- default:
- bfa_sm_fault(__vport_fcs(vport), event);
- }
-}
-
-/**
- * LOGO is sent to fabric. Vport delete is in progress. Lport delete cleanup
- * is done.
- */
-static void
-bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,
- enum bfa_fcs_vport_event event)
-{
- bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
- bfa_trc(__vport_fcs(vport), event);
-
- switch (event) {
- case BFA_FCS_VPORT_SM_OFFLINE:
- bfa_lps_discard(vport->lps);
- /*
- * !!! fall through !!!
- */
-
- case BFA_FCS_VPORT_SM_RSP_OK:
- case BFA_FCS_VPORT_SM_RSP_ERROR:
- bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
- bfa_fcs_vport_free(vport);
- break;
-
- case BFA_FCS_VPORT_SM_DELETE:
- break;
-
- default:
- bfa_sm_fault(__vport_fcs(vport), event);
- }
-}
-
-
-
-/**
- * fcs_vport_private FCS virtual port private functions
- */
-
-/**
- * Send AEN notification
- */
-static void
-bfa_fcs_vport_aen_post(bfa_fcs_lport_t *port, enum bfa_lport_aen_event event)
-{
- union bfa_aen_data_u aen_data;
- struct bfa_log_mod_s *logmod = port->fcs->logm;
- enum bfa_port_role role = port->port_cfg.roles;
- wwn_t lpwwn = bfa_fcs_port_get_pwwn(port);
- char lpwwn_ptr[BFA_STRING_32];
- char *role_str[BFA_PORT_ROLE_FCP_MAX / 2 + 1] =
- { "Initiator", "Target", "IPFC" };
-
- wwn2str(lpwwn_ptr, lpwwn);
-
- bfa_assert(role <= BFA_PORT_ROLE_FCP_MAX);
-
- bfa_log(logmod, BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, event), lpwwn_ptr,
- role_str[role/2]);
-
- aen_data.lport.vf_id = port->fabric->vf_id;
- aen_data.lport.roles = role;
- aen_data.lport.ppwwn =
- bfa_fcs_port_get_pwwn(bfa_fcs_get_base_port(port->fcs));
- aen_data.lport.lpwwn = lpwwn;
-}
-
-/**
- * This routine will be called to send a FDISC command.
- */
-static void
-bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport)
-{
- bfa_lps_fdisc(vport->lps, vport,
- bfa_fcport_get_maxfrsize(__vport_bfa(vport)),
- __vport_pwwn(vport), __vport_nwwn(vport));
- vport->vport_stats.fdisc_sent++;
-}
-
-static void
-bfa_fcs_vport_fdisc_rejected(struct bfa_fcs_vport_s *vport)
-{
- u8 lsrjt_rsn = bfa_lps_get_lsrjt_rsn(vport->lps);
- u8 lsrjt_expl = bfa_lps_get_lsrjt_expl(vport->lps);
-
- bfa_trc(__vport_fcs(vport), lsrjt_rsn);
- bfa_trc(__vport_fcs(vport), lsrjt_expl);
-
- /*
- * For certain reason codes, we don't want to retry.
- */
- switch (bfa_lps_get_lsrjt_expl(vport->lps)) {
- case FC_LS_RJT_EXP_INV_PORT_NAME: /* by brocade */
- case FC_LS_RJT_EXP_INVALID_NPORT_ID: /* by Cisco */
- if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
- bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
- else {
- bfa_fcs_vport_aen_post(&vport->lport,
- BFA_LPORT_AEN_NPIV_DUP_WWN);
- bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_DUP_WWN);
- }
- break;
-
- case FC_LS_RJT_EXP_INSUFF_RES:
- /*
- * This means max logins per port/switch setting on the
- * switch was exceeded.
- */
- if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
- bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
- else {
- bfa_fcs_vport_aen_post(&vport->lport,
- BFA_LPORT_AEN_NPIV_FABRIC_MAX);
- bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_FAILED);
- }
- break;
-
- default:
- if (vport->fdisc_retries == 0) /* Print only once */
- bfa_fcs_vport_aen_post(&vport->lport,
- BFA_LPORT_AEN_NPIV_UNKNOWN);
- bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
- }
-}
-
-/**
- * Called to send a logout to the fabric. Used when a V-Port is
- * deleted/stopped.
- */
-static void
-bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport)
-{
- bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
-
- vport->vport_stats.logo_sent++;
- bfa_lps_fdisclogo(vport->lps);
-}
-
-/**
- * This routine will be called by bfa_timer on timer timeouts.
- *
- * param[in] vport - pointer to bfa_fcs_vport_t.
- * param[out] vport_status - pointer to return vport status in
- *
- * return
- * void
- *
-* Special Considerations:
- *
- * note
- */
-static void
-bfa_fcs_vport_timeout(void *vport_arg)
-{
- struct bfa_fcs_vport_s *vport = (struct bfa_fcs_vport_s *)vport_arg;
-
- vport->vport_stats.fdisc_timeouts++;
- bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_TIMEOUT);
-}
-
-static void
-bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport)
-{
- bfa_fcs_fabric_delvport(__vport_fabric(vport), vport);
- bfa_fcb_vport_delete(vport->vport_drv);
- bfa_lps_delete(vport->lps);
-}
-
-
-
-/**
- * fcs_vport_public FCS virtual port public interfaces
- */
-
-/**
- * Online notification from fabric SM.
- */
-void
-bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport)
-{
- vport->vport_stats.fab_online++;
- bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);
-}
-
-/**
- * Offline notification from fabric SM.
- */
-void
-bfa_fcs_vport_offline(struct bfa_fcs_vport_s *vport)
-{
- vport->vport_stats.fab_offline++;
- bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE);
-}
-
-/**
- * Cleanup notification from fabric SM on link timer expiry.
- */
-void
-bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s *vport)
-{
- vport->vport_stats.fab_cleanup++;
-}
-
-/**
- * delete notification from fabric SM. To be invoked from within FCS.
- */
-void
-bfa_fcs_vport_fcs_delete(struct bfa_fcs_vport_s *vport)
-{
- bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE);
-}
-
-/**
- * Delete completion callback from associated lport
- */
-void
-bfa_fcs_vport_delete_comp(struct bfa_fcs_vport_s *vport)
-{
- bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELCOMP);
-}
-
-/**
- * fcs_vport_api Virtual port API
- */
-
-/**
- * Use this function to instantiate a new FCS vport object. This
- * function will not trigger any HW initialization process (which will be
- * done in vport_start() call)
- *
- * param[in] vport - pointer to bfa_fcs_vport_t. This space
- * needs to be allocated by the driver.
- * param[in] fcs - FCS instance
- * param[in] vport_cfg - vport configuration
- * param[in] vf_id - VF_ID if vport is created within a VF.
- * FC_VF_ID_NULL to specify base fabric.
- * param[in] vport_drv - Opaque handle back to the driver's vport
- * structure
- *
- * retval BFA_STATUS_OK - on success.
- * retval BFA_STATUS_FAILED - on failure.
- */
-bfa_status_t
-bfa_fcs_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs,
- u16 vf_id, struct bfa_port_cfg_s *vport_cfg,
- struct bfad_vport_s *vport_drv)
-{
- if (vport_cfg->pwwn == 0)
- return BFA_STATUS_INVALID_WWN;
-
- if (bfa_fcs_port_get_pwwn(&fcs->fabric.bport) == vport_cfg->pwwn)
- return BFA_STATUS_VPORT_WWN_BP;
-
- if (bfa_fcs_vport_lookup(fcs, vf_id, vport_cfg->pwwn) != NULL)
- return BFA_STATUS_VPORT_EXISTS;
-
- if (bfa_fcs_fabric_vport_count(&fcs->fabric) ==
- bfa_lps_get_max_vport(fcs->bfa))
- return BFA_STATUS_VPORT_MAX;
-
- vport->lps = bfa_lps_alloc(fcs->bfa);
- if (!vport->lps)
- return BFA_STATUS_VPORT_MAX;
-
- vport->vport_drv = vport_drv;
- vport_cfg->preboot_vp = BFA_FALSE;
- bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
-
- bfa_fcs_lport_attach(&vport->lport, fcs, vf_id, vport);
- bfa_fcs_lport_init(&vport->lport, vport_cfg);
-
- bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_CREATE);
-
- return BFA_STATUS_OK;
-}
-
-/**
- * Use this function to instantiate a new FCS PBC vport object. This
- * function will not trigger any HW initialization process (which will be
- * done in vport_start() call)
- *
- * param[in] vport - pointer to bfa_fcs_vport_t. This space
- * needs to be allocated by the driver.
- * param[in] fcs - FCS instance
- * param[in] vport_cfg - vport configuration
- * param[in] vf_id - VF_ID if vport is created within a VF.
- * FC_VF_ID_NULL to specify base fabric.
- * param[in] vport_drv - Opaque handle back to the driver's vport
- * structure
- *
- * retval BFA_STATUS_OK - on success.
- * retval BFA_STATUS_FAILED - on failure.
- */
-bfa_status_t
-bfa_fcs_pbc_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs,
- uint16_t vf_id, struct bfa_port_cfg_s *vport_cfg,
- struct bfad_vport_s *vport_drv)
-{
- bfa_status_t rc;
-
- rc = bfa_fcs_vport_create(vport, fcs, vf_id, vport_cfg, vport_drv);
- vport->lport.port_cfg.preboot_vp = BFA_TRUE;
-
- return rc;
-}
-
-/**
- * Use this function initialize the vport.
- *
- * @param[in] vport - pointer to bfa_fcs_vport_t.
- *
- * @returns None
- */
-bfa_status_t
-bfa_fcs_vport_start(struct bfa_fcs_vport_s *vport)
-{
- bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_START);
-
- return BFA_STATUS_OK;
-}
-
-/**
- * Use this function quiese the vport object. This function will return
- * immediately, when the vport is actually stopped, the
- * bfa_drv_vport_stop_cb() will be called.
- *
- * param[in] vport - pointer to bfa_fcs_vport_t.
- *
- * return None
- */
-bfa_status_t
-bfa_fcs_vport_stop(struct bfa_fcs_vport_s *vport)
-{
- bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOP);
-
- return BFA_STATUS_OK;
-}
-
-/**
- * Use this function to delete a vport object. Fabric object should
- * be stopped before this function call.
- *
- * Donot invoke this from within FCS
- *
- * param[in] vport - pointer to bfa_fcs_vport_t.
- *
- * return None
- */
-bfa_status_t
-bfa_fcs_vport_delete(struct bfa_fcs_vport_s *vport)
-{
- if (vport->lport.port_cfg.preboot_vp)
- return BFA_STATUS_PBC;
-
- bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE);
-
- return BFA_STATUS_OK;
-}
-
-/**
- * Use this function to get vport's current status info.
- *
- * param[in] vport pointer to bfa_fcs_vport_t.
- * param[out] attr pointer to return vport attributes
- *
- * return None
- */
-void
-bfa_fcs_vport_get_attr(struct bfa_fcs_vport_s *vport,
- struct bfa_vport_attr_s *attr)
-{
- if (vport == NULL || attr == NULL)
- return;
-
- bfa_os_memset(attr, 0, sizeof(struct bfa_vport_attr_s));
-
- bfa_fcs_port_get_attr(&vport->lport, &attr->port_attr);
- attr->vport_state = bfa_sm_to_state(vport_sm_table, vport->sm);
-}
-
-/**
- * Use this function to get vport's statistics.
- *
- * param[in] vport pointer to bfa_fcs_vport_t.
- * param[out] stats pointer to return vport statistics in
- *
- * return None
- */
-void
-bfa_fcs_vport_get_stats(struct bfa_fcs_vport_s *vport,
- struct bfa_vport_stats_s *stats)
-{
- *stats = vport->vport_stats;
-}
-
-/**
- * Use this function to clear vport's statistics.
- *
- * param[in] vport pointer to bfa_fcs_vport_t.
- *
- * return None
- */
-void
-bfa_fcs_vport_clr_stats(struct bfa_fcs_vport_s *vport)
-{
- bfa_os_memset(&vport->vport_stats, 0, sizeof(struct bfa_vport_stats_s));
-}
-
-/**
- * Lookup a virtual port. Excludes base port from lookup.
- */
-struct bfa_fcs_vport_s *
-bfa_fcs_vport_lookup(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t vpwwn)
-{
- struct bfa_fcs_vport_s *vport;
- struct bfa_fcs_fabric_s *fabric;
-
- bfa_trc(fcs, vf_id);
- bfa_trc(fcs, vpwwn);
-
- fabric = bfa_fcs_vf_lookup(fcs, vf_id);
- if (!fabric) {
- bfa_trc(fcs, vf_id);
- return NULL;
- }
-
- vport = bfa_fcs_fabric_vport_lookup(fabric, vpwwn);
- return vport;
-}
-
-/**
- * FDISC Response
- */
-void
-bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status)
-{
- struct bfa_fcs_vport_s *vport = uarg;
-
- bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
- bfa_trc(__vport_fcs(vport), status);
-
- switch (status) {
- case BFA_STATUS_OK:
- /*
- * Initialize the V-Port fields
- */
- __vport_fcid(vport) = bfa_lps_get_pid(vport->lps);
- vport->vport_stats.fdisc_accepts++;
- bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK);
- break;
-
- case BFA_STATUS_INVALID_MAC:
- /*
- * Only for CNA
- */
- vport->vport_stats.fdisc_acc_bad++;
- bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
-
- break;
-
- case BFA_STATUS_EPROTOCOL:
- switch (bfa_lps_get_extstatus(vport->lps)) {
- case BFA_EPROTO_BAD_ACCEPT:
- vport->vport_stats.fdisc_acc_bad++;
- break;
-
- case BFA_EPROTO_UNKNOWN_RSP:
- vport->vport_stats.fdisc_unknown_rsp++;
- break;
-
- default:
- break;
- }
-
- bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
- break;
-
- case BFA_STATUS_FABRIC_RJT:
- vport->vport_stats.fdisc_rejects++;
- bfa_fcs_vport_fdisc_rejected(vport);
- break;
-
- default:
- vport->vport_stats.fdisc_rsp_err++;
- bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
- }
-}
-
-/**
- * LOGO response
- */
-void
-bfa_cb_lps_fdisclogo_comp(void *bfad, void *uarg)
-{
- struct bfa_fcs_vport_s *vport = uarg;
- bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK);
-}
-
-/**
- * Received clear virtual link
- */
-void
-bfa_cb_lps_cvl_event(void *bfad, void *uarg)
-{
- struct bfa_fcs_vport_s *vport = uarg;
-
- /* Send an Offline followed by an ONLINE */
- bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE);
- bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);
-}
diff --git a/drivers/scsi/bnx2i/57xx_iscsi_constants.h b/drivers/scsi/bnx2i/57xx_iscsi_constants.h
index 2fceb19eb27b..1b6f86b2482d 100644
--- a/drivers/scsi/bnx2i/57xx_iscsi_constants.h
+++ b/drivers/scsi/bnx2i/57xx_iscsi_constants.h
@@ -120,6 +120,8 @@
/* additional LOM specific iSCSI license not installed */
#define ISCSI_KCQE_COMPLETION_STATUS_LOM_ISCSI_NOT_ENABLED (0x51)
+#define ISCSI_KCQE_COMPLETION_STATUS_CID_BUSY (0x80)
+
/* SQ/RQ/CQ DB structure sizes */
#define ISCSI_SQ_DB_SIZE (16)
#define ISCSI_RQ_DB_SIZE (16)
diff --git a/drivers/scsi/bnx2i/bnx2i.h b/drivers/scsi/bnx2i/bnx2i.h
index 00c033511cbf..a44b1b33fa18 100644
--- a/drivers/scsi/bnx2i/bnx2i.h
+++ b/drivers/scsi/bnx2i/bnx2i.h
@@ -58,6 +58,8 @@
#define MAX_PAGES_PER_CTRL_STRUCT_POOL 8
#define BNX2I_RESERVED_SLOW_PATH_CMD_SLOTS 4
+#define BNX2I_5771X_DBELL_PAGE_SIZE 128
+
/* 5706/08 hardware has limit on maximum buffer size per BD it can handle */
#define MAX_BD_LENGTH 65535
#define BD_SPLIT_SIZE 32768
@@ -753,7 +755,7 @@ extern int bnx2i_send_iscsi_tmf(struct bnx2i_conn *conn,
extern int bnx2i_send_iscsi_scsicmd(struct bnx2i_conn *conn,
struct bnx2i_cmd *cmnd);
extern int bnx2i_send_iscsi_nopout(struct bnx2i_conn *conn,
- struct iscsi_task *mtask, u32 ttt,
+ struct iscsi_task *mtask,
char *datap, int data_len, int unsol);
extern int bnx2i_send_iscsi_logout(struct bnx2i_conn *conn,
struct iscsi_task *mtask);
diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c
index d23fc256d585..8d9dbb33972f 100644
--- a/drivers/scsi/bnx2i/bnx2i_hwi.c
+++ b/drivers/scsi/bnx2i/bnx2i_hwi.c
@@ -385,7 +385,6 @@ int bnx2i_send_iscsi_tmf(struct bnx2i_conn *bnx2i_conn,
struct bnx2i_cmd *bnx2i_cmd;
struct bnx2i_tmf_request *tmfabort_wqe;
u32 dword;
- u32 scsi_lun[2];
bnx2i_cmd = (struct bnx2i_cmd *)mtask->dd_data;
tmfabort_hdr = (struct iscsi_tm *)mtask->hdr;
@@ -393,38 +392,41 @@ int bnx2i_send_iscsi_tmf(struct bnx2i_conn *bnx2i_conn,
bnx2i_conn->ep->qp.sq_prod_qe;
tmfabort_wqe->op_code = tmfabort_hdr->opcode;
- tmfabort_wqe->op_attr = 0;
- tmfabort_wqe->op_attr =
- ISCSI_TMF_REQUEST_ALWAYS_ONE | ISCSI_TM_FUNC_ABORT_TASK;
+ tmfabort_wqe->op_attr = tmfabort_hdr->flags;
tmfabort_wqe->itt = (mtask->itt | (ISCSI_TASK_TYPE_MPATH << 14));
tmfabort_wqe->reserved2 = 0;
tmfabort_wqe->cmd_sn = be32_to_cpu(tmfabort_hdr->cmdsn);
- ctask = iscsi_itt_to_task(conn, tmfabort_hdr->rtt);
- if (!ctask || !ctask->sc)
- /*
- * the iscsi layer must have completed the cmd while this
- * was starting up.
- *
- * Note: In the case of a SCSI cmd timeout, the task's sc
- * is still active; hence ctask->sc != 0
- * In this case, the task must be aborted
- */
- return 0;
-
- ref_sc = ctask->sc;
-
- /* Retrieve LUN directly from the ref_sc */
- int_to_scsilun(ref_sc->device->lun, (struct scsi_lun *) scsi_lun);
- tmfabort_wqe->lun[0] = be32_to_cpu(scsi_lun[0]);
- tmfabort_wqe->lun[1] = be32_to_cpu(scsi_lun[1]);
-
- if (ref_sc->sc_data_direction == DMA_TO_DEVICE)
- dword = (ISCSI_TASK_TYPE_WRITE << ISCSI_CMD_REQUEST_TYPE_SHIFT);
- else
- dword = (ISCSI_TASK_TYPE_READ << ISCSI_CMD_REQUEST_TYPE_SHIFT);
- tmfabort_wqe->ref_itt = (dword | (tmfabort_hdr->rtt & ISCSI_ITT_MASK));
+ switch (tmfabort_hdr->flags & ISCSI_FLAG_TM_FUNC_MASK) {
+ case ISCSI_TM_FUNC_ABORT_TASK:
+ case ISCSI_TM_FUNC_TASK_REASSIGN:
+ ctask = iscsi_itt_to_task(conn, tmfabort_hdr->rtt);
+ if (!ctask || !ctask->sc)
+ /*
+ * the iscsi layer must have completed the cmd while
+ * was starting up.
+ *
+ * Note: In the case of a SCSI cmd timeout, the task's
+ * sc is still active; hence ctask->sc != 0
+ * In this case, the task must be aborted
+ */
+ return 0;
+
+ ref_sc = ctask->sc;
+ if (ref_sc->sc_data_direction == DMA_TO_DEVICE)
+ dword = (ISCSI_TASK_TYPE_WRITE <<
+ ISCSI_CMD_REQUEST_TYPE_SHIFT);
+ else
+ dword = (ISCSI_TASK_TYPE_READ <<
+ ISCSI_CMD_REQUEST_TYPE_SHIFT);
+ tmfabort_wqe->ref_itt = (dword |
+ (tmfabort_hdr->rtt & ISCSI_ITT_MASK));
+ break;
+ default:
+ tmfabort_wqe->ref_itt = RESERVED_ITT;
+ }
+ memcpy(tmfabort_wqe->lun, tmfabort_hdr->lun, sizeof(struct scsi_lun));
tmfabort_wqe->ref_cmd_sn = be32_to_cpu(tmfabort_hdr->refcmdsn);
tmfabort_wqe->bd_list_addr_lo = (u32) bnx2i_conn->hba->mp_bd_dma;
@@ -464,7 +466,6 @@ int bnx2i_send_iscsi_scsicmd(struct bnx2i_conn *bnx2i_conn,
* @conn: iscsi connection
* @cmd: driver command structure which is requesting
* a WQE to sent to chip for further processing
- * @ttt: TTT to be used when building pdu header
* @datap: payload buffer pointer
* @data_len: payload data length
* @unsol: indicated whether nopout pdu is unsolicited pdu or
@@ -473,7 +474,7 @@ int bnx2i_send_iscsi_scsicmd(struct bnx2i_conn *bnx2i_conn,
* prepare and post a nopout request WQE to CNIC firmware
*/
int bnx2i_send_iscsi_nopout(struct bnx2i_conn *bnx2i_conn,
- struct iscsi_task *task, u32 ttt,
+ struct iscsi_task *task,
char *datap, int data_len, int unsol)
{
struct bnx2i_endpoint *ep = bnx2i_conn->ep;
@@ -498,7 +499,7 @@ int bnx2i_send_iscsi_nopout(struct bnx2i_conn *bnx2i_conn,
nopout_wqe->itt = ((u16)task->itt |
(ISCSI_TASK_TYPE_MPATH <<
ISCSI_TMF_REQUEST_TYPE_SHIFT));
- nopout_wqe->ttt = ttt;
+ nopout_wqe->ttt = nopout_hdr->ttt;
nopout_wqe->flags = 0;
if (!unsol)
nopout_wqe->flags = ISCSI_NOP_OUT_REQUEST_LOCAL_COMPLETION;
@@ -2405,7 +2406,8 @@ int bnx2i_map_ep_dbell_regs(struct bnx2i_endpoint *ep)
if (test_bit(BNX2I_NX2_DEV_57710, &ep->hba->cnic_dev_type)) {
reg_base = pci_resource_start(ep->hba->pcidev,
BNX2X_DOORBELL_PCI_BAR);
- reg_off = PAGE_SIZE * (cid_num & 0x1FFFF) + DPM_TRIGER_TYPE;
+ reg_off = BNX2I_5771X_DBELL_PAGE_SIZE * (cid_num & 0x1FFFF) +
+ DPM_TRIGER_TYPE;
ep->qp.ctx_base = ioremap_nocache(reg_base + reg_off, 4);
goto arm_cq;
}
diff --git a/drivers/scsi/bnx2i/bnx2i_init.c b/drivers/scsi/bnx2i/bnx2i_init.c
index a796f565f383..50c2aa3b8eb1 100644
--- a/drivers/scsi/bnx2i/bnx2i_init.c
+++ b/drivers/scsi/bnx2i/bnx2i_init.c
@@ -17,15 +17,17 @@ static struct list_head adapter_list = LIST_HEAD_INIT(adapter_list);
static u32 adapter_count;
#define DRV_MODULE_NAME "bnx2i"
-#define DRV_MODULE_VERSION "2.1.2"
-#define DRV_MODULE_RELDATE "Jun 28, 2010"
+#define DRV_MODULE_VERSION "2.1.3"
+#define DRV_MODULE_RELDATE "Aug 10, 2010"
static char version[] __devinitdata =
"Broadcom NetXtreme II iSCSI Driver " DRV_MODULE_NAME \
" v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
-MODULE_AUTHOR("Anil Veerabhadrappa <anilgv@broadcom.com>");
+MODULE_AUTHOR("Anil Veerabhadrappa <anilgv@broadcom.com> and "
+ "Eddie Wai <eddie.wai@broadcom.com>");
+
MODULE_DESCRIPTION("Broadcom NetXtreme II BCM5706/5708/5709/57710/57711"
" iSCSI Driver");
MODULE_LICENSE("GPL");
@@ -167,6 +169,38 @@ void bnx2i_start(void *handle)
/**
+ * bnx2i_chip_cleanup - local routine to handle chip cleanup
+ * @hba: Adapter instance to register
+ *
+ * Driver checks if adapter still has any active connections before
+ * executing the cleanup process
+ */
+static void bnx2i_chip_cleanup(struct bnx2i_hba *hba)
+{
+ struct bnx2i_endpoint *bnx2i_ep;
+ struct list_head *pos, *tmp;
+
+ if (hba->ofld_conns_active) {
+ /* Stage to force the disconnection
+ * This is the case where the daemon is either slow or
+ * not present
+ */
+ printk(KERN_ALERT "bnx2i: (%s) chip cleanup for %d active "
+ "connections\n", hba->netdev->name,
+ hba->ofld_conns_active);
+ mutex_lock(&hba->net_dev_lock);
+ list_for_each_safe(pos, tmp, &hba->ep_active_list) {
+ bnx2i_ep = list_entry(pos, struct bnx2i_endpoint, link);
+ /* Clean up the chip only */
+ bnx2i_hw_ep_disconnect(bnx2i_ep);
+ bnx2i_ep->cm_sk = NULL;
+ }
+ mutex_unlock(&hba->net_dev_lock);
+ }
+}
+
+
+/**
* bnx2i_stop - cnic callback to shutdown adapter instance
* @handle: transparent handle pointing to adapter structure
*
@@ -176,8 +210,6 @@ void bnx2i_start(void *handle)
void bnx2i_stop(void *handle)
{
struct bnx2i_hba *hba = handle;
- struct list_head *pos, *tmp;
- struct bnx2i_endpoint *bnx2i_ep;
int conns_active;
/* check if cleanup happened in GOING_DOWN context */
@@ -198,24 +230,7 @@ void bnx2i_stop(void *handle)
if (hba->ofld_conns_active == conns_active)
break;
}
- if (hba->ofld_conns_active) {
- /* Stage to force the disconnection
- * This is the case where the daemon is either slow or
- * not present
- */
- printk(KERN_ALERT "bnx2i: Wait timeout, force all eps "
- "to disconnect (%d)\n", hba->ofld_conns_active);
- mutex_lock(&hba->net_dev_lock);
- list_for_each_safe(pos, tmp, &hba->ep_active_list) {
- bnx2i_ep = list_entry(pos, struct bnx2i_endpoint, link);
- /* Clean up the chip only */
- bnx2i_hw_ep_disconnect(bnx2i_ep);
- }
- mutex_unlock(&hba->net_dev_lock);
- if (hba->ofld_conns_active)
- printk(KERN_ERR "bnx2i: EP disconnect timeout (%d)!\n",
- hba->ofld_conns_active);
- }
+ bnx2i_chip_cleanup(hba);
/* This flag should be cleared last so that ep_disconnect() gracefully
* cleans up connection context
@@ -457,6 +472,7 @@ static void __exit bnx2i_mod_exit(void)
adapter_count--;
if (test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic)) {
+ bnx2i_chip_cleanup(hba);
hba->cnic->unregister_device(hba->cnic, CNIC_ULP_ISCSI);
clear_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic);
}
diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c
index a46ccc380ab1..fb50efbce087 100644
--- a/drivers/scsi/bnx2i/bnx2i_iscsi.c
+++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c
@@ -1078,11 +1078,9 @@ static int bnx2i_iscsi_send_generic_request(struct iscsi_task *task)
buf = bnx2i_conn->gen_pdu.req_buf;
if (data_len)
rc = bnx2i_send_iscsi_nopout(bnx2i_conn, task,
- RESERVED_ITT,
buf, data_len, 1);
else
rc = bnx2i_send_iscsi_nopout(bnx2i_conn, task,
- RESERVED_ITT,
NULL, 0, 1);
break;
case ISCSI_OP_LOGOUT:
@@ -1955,6 +1953,9 @@ int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep)
if (!cnic)
return 0;
+ if (bnx2i_ep->state == EP_STATE_IDLE)
+ return 0;
+
if (!bnx2i_ep_tcp_conn_active(bnx2i_ep))
goto destroy_conn;
@@ -1998,11 +1999,13 @@ int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep)
else
close_ret = cnic->cm_abort(bnx2i_ep->cm_sk);
+ /* No longer allow CFC delete if cm_close/abort fails the request */
if (close_ret)
- bnx2i_ep->state = EP_STATE_DISCONN_COMPL;
-
- /* wait for option-2 conn teardown */
- wait_event_interruptible(bnx2i_ep->ofld_wait,
+ printk(KERN_ALERT "bnx2i: %s close/abort(%d) returned %d\n",
+ bnx2i_ep->hba->netdev->name, close, close_ret);
+ else
+ /* wait for option-2 conn teardown */
+ wait_event_interruptible(bnx2i_ep->ofld_wait,
bnx2i_ep->state != EP_STATE_DISCONN_START);
if (signal_pending(current))
diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c
index d6532187f616..a15474eef5f7 100644
--- a/drivers/scsi/ch.c
+++ b/drivers/scsi/ch.c
@@ -22,7 +22,6 @@
#include <linux/chio.h> /* here are all the ioctls */
#include <linux/mutex.h>
#include <linux/idr.h>
-#include <linux/smp_lock.h>
#include <linux/slab.h>
#include <scsi/scsi.h>
@@ -44,6 +43,7 @@ MODULE_LICENSE("GPL");
MODULE_ALIAS_CHARDEV_MAJOR(SCSI_CHANGER_MAJOR);
MODULE_ALIAS_SCSI_DEVICE(TYPE_MEDIUM_CHANGER);
+static DEFINE_MUTEX(ch_mutex);
static int init = 1;
module_param(init, int, 0444);
MODULE_PARM_DESC(init, \
@@ -581,19 +581,19 @@ ch_open(struct inode *inode, struct file *file)
scsi_changer *ch;
int minor = iminor(inode);
- lock_kernel();
+ mutex_lock(&ch_mutex);
spin_lock(&ch_index_lock);
ch = idr_find(&ch_index_idr, minor);
if (NULL == ch || scsi_device_get(ch->device)) {
spin_unlock(&ch_index_lock);
- unlock_kernel();
+ mutex_unlock(&ch_mutex);
return -ENXIO;
}
spin_unlock(&ch_index_lock);
file->private_data = ch;
- unlock_kernel();
+ mutex_unlock(&ch_mutex);
return 0;
}
@@ -981,6 +981,7 @@ static const struct file_operations changer_fops = {
#ifdef CONFIG_COMPAT
.compat_ioctl = ch_ioctl_compat,
#endif
+ .llseek = noop_llseek,
};
static int __init init_ch_module(void)
diff --git a/drivers/scsi/cxgb3i/cxgb3i.h b/drivers/scsi/cxgb3i/cxgb3i.h
deleted file mode 100644
index e3133b58e594..000000000000
--- a/drivers/scsi/cxgb3i/cxgb3i.h
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * cxgb3i.h: Chelsio S3xx iSCSI driver.
- *
- * Copyright (c) 2008 Chelsio Communications, 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.
- *
- * Written by: Karen Xie (kxie@chelsio.com)
- */
-
-#ifndef __CXGB3I_H__
-#define __CXGB3I_H__
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/list.h>
-#include <linux/netdevice.h>
-#include <linux/scatterlist.h>
-#include <linux/skbuff.h>
-#include <scsi/libiscsi_tcp.h>
-
-/* from cxgb3 LLD */
-#include "common.h"
-#include "t3_cpl.h"
-#include "t3cdev.h"
-#include "cxgb3_ctl_defs.h"
-#include "cxgb3_offload.h"
-#include "firmware_exports.h"
-
-#include "cxgb3i_offload.h"
-#include "cxgb3i_ddp.h"
-
-#define CXGB3I_SCSI_HOST_QDEPTH 1024
-#define CXGB3I_MAX_TARGET CXGB3I_MAX_CONN
-#define CXGB3I_MAX_LUN 512
-#define ISCSI_PDU_NONPAYLOAD_MAX \
- (sizeof(struct iscsi_hdr) + ISCSI_MAX_AHS_SIZE + 2*ISCSI_DIGEST_SIZE)
-
-struct cxgb3i_adapter;
-struct cxgb3i_hba;
-struct cxgb3i_endpoint;
-
-/**
- * struct cxgb3i_hba - cxgb3i iscsi structure (per port)
- *
- * @snic: cxgb3i adapter containing this port
- * @ndev: pointer to netdev structure
- * @shost: pointer to scsi host structure
- */
-struct cxgb3i_hba {
- struct cxgb3i_adapter *snic;
- struct net_device *ndev;
- struct Scsi_Host *shost;
-};
-
-/**
- * struct cxgb3i_adapter - cxgb3i adapter structure (per pci)
- *
- * @listhead: list head to link elements
- * @lock: lock for this structure
- * @tdev: pointer to t3cdev used by cxgb3 driver
- * @pdev: pointer to pci dev
- * @hba_cnt: # of hbas (the same as # of ports)
- * @hba: all the hbas on this adapter
- * @flags: bit flag for adapter event/status
- * @tx_max_size: max. tx packet size supported
- * @rx_max_size: max. rx packet size supported
- * @tag_format: ddp tag format settings
- */
-#define CXGB3I_ADAPTER_FLAG_RESET 0x1
-struct cxgb3i_adapter {
- struct list_head list_head;
- spinlock_t lock;
- struct t3cdev *tdev;
- struct pci_dev *pdev;
- unsigned char hba_cnt;
- struct cxgb3i_hba *hba[MAX_NPORTS];
-
- unsigned int flags;
- unsigned int tx_max_size;
- unsigned int rx_max_size;
-
- struct cxgb3i_tag_format tag_format;
-};
-
-/**
- * struct cxgb3i_conn - cxgb3i iscsi connection
- *
- * @listhead: list head to link elements
- * @cep: pointer to iscsi_endpoint structure
- * @conn: pointer to iscsi_conn structure
- * @hba: pointer to the hba this conn. is going through
- * @task_idx_bits: # of bits needed for session->cmds_max
- */
-struct cxgb3i_conn {
- struct list_head list_head;
- struct cxgb3i_endpoint *cep;
- struct iscsi_conn *conn;
- struct cxgb3i_hba *hba;
- unsigned int task_idx_bits;
-};
-
-/**
- * struct cxgb3i_endpoint - iscsi tcp endpoint
- *
- * @c3cn: the h/w tcp connection representation
- * @hba: pointer to the hba this conn. is going through
- * @cconn: pointer to the associated cxgb3i iscsi connection
- */
-struct cxgb3i_endpoint {
- struct s3_conn *c3cn;
- struct cxgb3i_hba *hba;
- struct cxgb3i_conn *cconn;
-};
-
-/**
- * struct cxgb3i_task_data - private iscsi task data
- *
- * @nr_frags: # of coalesced page frags (from scsi sgl)
- * @frags: coalesced page frags (from scsi sgl)
- * @skb: tx pdu skb
- * @offset: data offset for the next pdu
- * @count: max. possible pdu payload
- * @sgoffset: offset to the first sg entry for a given offset
- */
-#define MAX_PDU_FRAGS ((ULP2_MAX_PDU_PAYLOAD + 512 - 1) / 512)
-struct cxgb3i_task_data {
- unsigned short nr_frags;
- skb_frag_t frags[MAX_PDU_FRAGS];
- struct sk_buff *skb;
- unsigned int offset;
- unsigned int count;
- unsigned int sgoffset;
-};
-
-int cxgb3i_iscsi_init(void);
-void cxgb3i_iscsi_cleanup(void);
-
-struct cxgb3i_adapter *cxgb3i_adapter_find_by_tdev(struct t3cdev *);
-void cxgb3i_adapter_open(struct t3cdev *);
-void cxgb3i_adapter_close(struct t3cdev *);
-
-struct cxgb3i_hba *cxgb3i_hba_host_add(struct cxgb3i_adapter *,
- struct net_device *);
-void cxgb3i_hba_host_remove(struct cxgb3i_hba *);
-
-int cxgb3i_pdu_init(void);
-void cxgb3i_pdu_cleanup(void);
-void cxgb3i_conn_cleanup_task(struct iscsi_task *);
-int cxgb3i_conn_alloc_pdu(struct iscsi_task *, u8);
-int cxgb3i_conn_init_pdu(struct iscsi_task *, unsigned int, unsigned int);
-int cxgb3i_conn_xmit_pdu(struct iscsi_task *);
-
-void cxgb3i_release_itt(struct iscsi_task *task, itt_t hdr_itt);
-int cxgb3i_reserve_itt(struct iscsi_task *task, itt_t *hdr_itt);
-
-#endif
diff --git a/drivers/scsi/cxgb3i/cxgb3i_ddp.c b/drivers/scsi/cxgb3i/cxgb3i_ddp.c
deleted file mode 100644
index be0e23042c76..000000000000
--- a/drivers/scsi/cxgb3i/cxgb3i_ddp.c
+++ /dev/null
@@ -1,773 +0,0 @@
-/*
- * cxgb3i_ddp.c: Chelsio S3xx iSCSI DDP Manager.
- *
- * Copyright (c) 2008 Chelsio Communications, 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.
- *
- * Written by: Karen Xie (kxie@chelsio.com)
- */
-
-#include <linux/slab.h>
-#include <linux/skbuff.h>
-#include <linux/scatterlist.h>
-
-/* from cxgb3 LLD */
-#include "common.h"
-#include "t3_cpl.h"
-#include "t3cdev.h"
-#include "cxgb3_ctl_defs.h"
-#include "cxgb3_offload.h"
-#include "firmware_exports.h"
-
-#include "cxgb3i_ddp.h"
-
-#define ddp_log_error(fmt...) printk(KERN_ERR "cxgb3i_ddp: ERR! " fmt)
-#define ddp_log_warn(fmt...) printk(KERN_WARNING "cxgb3i_ddp: WARN! " fmt)
-#define ddp_log_info(fmt...) printk(KERN_INFO "cxgb3i_ddp: " fmt)
-
-#ifdef __DEBUG_CXGB3I_DDP__
-#define ddp_log_debug(fmt, args...) \
- printk(KERN_INFO "cxgb3i_ddp: %s - " fmt, __func__ , ## args)
-#else
-#define ddp_log_debug(fmt...)
-#endif
-
-/*
- * iSCSI Direct Data Placement
- *
- * T3 h/w can directly place the iSCSI Data-In or Data-Out PDU's payload into
- * pre-posted final destination host-memory buffers based on the Initiator
- * Task Tag (ITT) in Data-In or Target Task Tag (TTT) in Data-Out PDUs.
- *
- * The host memory address is programmed into h/w in the format of pagepod
- * entries.
- * The location of the pagepod entry is encoded into ddp tag which is used or
- * is the base for ITT/TTT.
- */
-
-#define DDP_PGIDX_MAX 4
-#define DDP_THRESHOLD 2048
-static unsigned char ddp_page_order[DDP_PGIDX_MAX] = {0, 1, 2, 4};
-static unsigned char ddp_page_shift[DDP_PGIDX_MAX] = {12, 13, 14, 16};
-static unsigned char page_idx = DDP_PGIDX_MAX;
-
-/*
- * functions to program the pagepod in h/w
- */
-static inline void ulp_mem_io_set_hdr(struct sk_buff *skb, unsigned int addr)
-{
- struct ulp_mem_io *req = (struct ulp_mem_io *)skb->head;
-
- req->wr.wr_lo = 0;
- req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_BYPASS));
- req->cmd_lock_addr = htonl(V_ULP_MEMIO_ADDR(addr >> 5) |
- V_ULPTX_CMD(ULP_MEM_WRITE));
- req->len = htonl(V_ULP_MEMIO_DATA_LEN(PPOD_SIZE >> 5) |
- V_ULPTX_NFLITS((PPOD_SIZE >> 3) + 1));
-}
-
-static int set_ddp_map(struct cxgb3i_ddp_info *ddp, struct pagepod_hdr *hdr,
- unsigned int idx, unsigned int npods,
- struct cxgb3i_gather_list *gl)
-{
- unsigned int pm_addr = (idx << PPOD_SIZE_SHIFT) + ddp->llimit;
- int i;
-
- for (i = 0; i < npods; i++, idx++, pm_addr += PPOD_SIZE) {
- struct sk_buff *skb = ddp->gl_skb[idx];
- struct pagepod *ppod;
- int j, pidx;
-
- /* hold on to the skb until we clear the ddp mapping */
- skb_get(skb);
-
- ulp_mem_io_set_hdr(skb, pm_addr);
- ppod = (struct pagepod *)
- (skb->head + sizeof(struct ulp_mem_io));
- memcpy(&(ppod->hdr), hdr, sizeof(struct pagepod));
- for (pidx = 4 * i, j = 0; j < 5; ++j, ++pidx)
- ppod->addr[j] = pidx < gl->nelem ?
- cpu_to_be64(gl->phys_addr[pidx]) : 0UL;
-
- skb->priority = CPL_PRIORITY_CONTROL;
- cxgb3_ofld_send(ddp->tdev, skb);
- }
- return 0;
-}
-
-static void clear_ddp_map(struct cxgb3i_ddp_info *ddp, unsigned int tag,
- unsigned int idx, unsigned int npods)
-{
- unsigned int pm_addr = (idx << PPOD_SIZE_SHIFT) + ddp->llimit;
- int i;
-
- for (i = 0; i < npods; i++, idx++, pm_addr += PPOD_SIZE) {
- struct sk_buff *skb = ddp->gl_skb[idx];
-
- if (!skb) {
- ddp_log_error("ddp tag 0x%x, 0x%x, %d/%u, skb NULL.\n",
- tag, idx, i, npods);
- continue;
- }
- ddp->gl_skb[idx] = NULL;
- memset((skb->head + sizeof(struct ulp_mem_io)), 0, PPOD_SIZE);
- ulp_mem_io_set_hdr(skb, pm_addr);
- skb->priority = CPL_PRIORITY_CONTROL;
- cxgb3_ofld_send(ddp->tdev, skb);
- }
-}
-
-static inline int ddp_find_unused_entries(struct cxgb3i_ddp_info *ddp,
- unsigned int start, unsigned int max,
- unsigned int count,
- struct cxgb3i_gather_list *gl)
-{
- unsigned int i, j, k;
-
- /* not enough entries */
- if ((max - start) < count)
- return -EBUSY;
-
- max -= count;
- spin_lock(&ddp->map_lock);
- for (i = start; i < max;) {
- for (j = 0, k = i; j < count; j++, k++) {
- if (ddp->gl_map[k])
- break;
- }
- if (j == count) {
- for (j = 0, k = i; j < count; j++, k++)
- ddp->gl_map[k] = gl;
- spin_unlock(&ddp->map_lock);
- return i;
- }
- i += j + 1;
- }
- spin_unlock(&ddp->map_lock);
- return -EBUSY;
-}
-
-static inline void ddp_unmark_entries(struct cxgb3i_ddp_info *ddp,
- int start, int count)
-{
- spin_lock(&ddp->map_lock);
- memset(&ddp->gl_map[start], 0,
- count * sizeof(struct cxgb3i_gather_list *));
- spin_unlock(&ddp->map_lock);
-}
-
-static inline void ddp_free_gl_skb(struct cxgb3i_ddp_info *ddp,
- int idx, int count)
-{
- int i;
-
- for (i = 0; i < count; i++, idx++)
- if (ddp->gl_skb[idx]) {
- kfree_skb(ddp->gl_skb[idx]);
- ddp->gl_skb[idx] = NULL;
- }
-}
-
-static inline int ddp_alloc_gl_skb(struct cxgb3i_ddp_info *ddp, int idx,
- int count, gfp_t gfp)
-{
- int i;
-
- for (i = 0; i < count; i++) {
- struct sk_buff *skb = alloc_skb(sizeof(struct ulp_mem_io) +
- PPOD_SIZE, gfp);
- if (skb) {
- ddp->gl_skb[idx + i] = skb;
- skb_put(skb, sizeof(struct ulp_mem_io) + PPOD_SIZE);
- } else {
- ddp_free_gl_skb(ddp, idx, i);
- return -ENOMEM;
- }
- }
- return 0;
-}
-
-/**
- * cxgb3i_ddp_find_page_index - return ddp page index for a given page size
- * @pgsz: page size
- * return the ddp page index, if no match is found return DDP_PGIDX_MAX.
- */
-int cxgb3i_ddp_find_page_index(unsigned long pgsz)
-{
- int i;
-
- for (i = 0; i < DDP_PGIDX_MAX; i++) {
- if (pgsz == (1UL << ddp_page_shift[i]))
- return i;
- }
- ddp_log_debug("ddp page size 0x%lx not supported.\n", pgsz);
- return DDP_PGIDX_MAX;
-}
-
-/**
- * cxgb3i_ddp_adjust_page_table - adjust page table with PAGE_SIZE
- * return the ddp page index, if no match is found return DDP_PGIDX_MAX.
- */
-int cxgb3i_ddp_adjust_page_table(void)
-{
- int i;
- unsigned int base_order, order;
-
- if (PAGE_SIZE < (1UL << ddp_page_shift[0])) {
- ddp_log_info("PAGE_SIZE 0x%lx too small, min. 0x%lx.\n",
- PAGE_SIZE, 1UL << ddp_page_shift[0]);
- return -EINVAL;
- }
-
- base_order = get_order(1UL << ddp_page_shift[0]);
- order = get_order(1 << PAGE_SHIFT);
- for (i = 0; i < DDP_PGIDX_MAX; i++) {
- /* first is the kernel page size, then just doubling the size */
- ddp_page_order[i] = order - base_order + i;
- ddp_page_shift[i] = PAGE_SHIFT + i;
- }
- return 0;
-}
-
-static inline void ddp_gl_unmap(struct pci_dev *pdev,
- struct cxgb3i_gather_list *gl)
-{
- int i;
-
- for (i = 0; i < gl->nelem; i++)
- pci_unmap_page(pdev, gl->phys_addr[i], PAGE_SIZE,
- PCI_DMA_FROMDEVICE);
-}
-
-static inline int ddp_gl_map(struct pci_dev *pdev,
- struct cxgb3i_gather_list *gl)
-{
- int i;
-
- for (i = 0; i < gl->nelem; i++) {
- gl->phys_addr[i] = pci_map_page(pdev, gl->pages[i], 0,
- PAGE_SIZE,
- PCI_DMA_FROMDEVICE);
- if (unlikely(pci_dma_mapping_error(pdev, gl->phys_addr[i])))
- goto unmap;
- }
-
- return i;
-
-unmap:
- if (i) {
- unsigned int nelem = gl->nelem;
-
- gl->nelem = i;
- ddp_gl_unmap(pdev, gl);
- gl->nelem = nelem;
- }
- return -ENOMEM;
-}
-
-/**
- * cxgb3i_ddp_make_gl - build ddp page buffer list
- * @xferlen: total buffer length
- * @sgl: page buffer scatter-gather list
- * @sgcnt: # of page buffers
- * @pdev: pci_dev, used for pci map
- * @gfp: allocation mode
- *
- * construct a ddp page buffer list from the scsi scattergather list.
- * coalesce buffers as much as possible, and obtain dma addresses for
- * each page.
- *
- * Return the cxgb3i_gather_list constructed from the page buffers if the
- * memory can be used for ddp. Return NULL otherwise.
- */
-struct cxgb3i_gather_list *cxgb3i_ddp_make_gl(unsigned int xferlen,
- struct scatterlist *sgl,
- unsigned int sgcnt,
- struct pci_dev *pdev,
- gfp_t gfp)
-{
- struct cxgb3i_gather_list *gl;
- struct scatterlist *sg = sgl;
- struct page *sgpage = sg_page(sg);
- unsigned int sglen = sg->length;
- unsigned int sgoffset = sg->offset;
- unsigned int npages = (xferlen + sgoffset + PAGE_SIZE - 1) >>
- PAGE_SHIFT;
- int i = 1, j = 0;
-
- if (xferlen < DDP_THRESHOLD) {
- ddp_log_debug("xfer %u < threshold %u, no ddp.\n",
- xferlen, DDP_THRESHOLD);
- return NULL;
- }
-
- gl = kzalloc(sizeof(struct cxgb3i_gather_list) +
- npages * (sizeof(dma_addr_t) + sizeof(struct page *)),
- gfp);
- if (!gl)
- return NULL;
-
- gl->pages = (struct page **)&gl->phys_addr[npages];
- gl->length = xferlen;
- gl->offset = sgoffset;
- gl->pages[0] = sgpage;
-
- sg = sg_next(sg);
- while (sg) {
- struct page *page = sg_page(sg);
-
- if (sgpage == page && sg->offset == sgoffset + sglen)
- sglen += sg->length;
- else {
- /* make sure the sgl is fit for ddp:
- * each has the same page size, and
- * all of the middle pages are used completely
- */
- if ((j && sgoffset) ||
- ((i != sgcnt - 1) &&
- ((sglen + sgoffset) & ~PAGE_MASK)))
- goto error_out;
-
- j++;
- if (j == gl->nelem || sg->offset)
- goto error_out;
- gl->pages[j] = page;
- sglen = sg->length;
- sgoffset = sg->offset;
- sgpage = page;
- }
- i++;
- sg = sg_next(sg);
- }
- gl->nelem = ++j;
-
- if (ddp_gl_map(pdev, gl) < 0)
- goto error_out;
-
- return gl;
-
-error_out:
- kfree(gl);
- return NULL;
-}
-
-/**
- * cxgb3i_ddp_release_gl - release a page buffer list
- * @gl: a ddp page buffer list
- * @pdev: pci_dev used for pci_unmap
- * free a ddp page buffer list resulted from cxgb3i_ddp_make_gl().
- */
-void cxgb3i_ddp_release_gl(struct cxgb3i_gather_list *gl,
- struct pci_dev *pdev)
-{
- ddp_gl_unmap(pdev, gl);
- kfree(gl);
-}
-
-/**
- * cxgb3i_ddp_tag_reserve - set up ddp for a data transfer
- * @tdev: t3cdev adapter
- * @tid: connection id
- * @tformat: tag format
- * @tagp: contains s/w tag initially, will be updated with ddp/hw tag
- * @gl: the page momory list
- * @gfp: allocation mode
- *
- * ddp setup for a given page buffer list and construct the ddp tag.
- * return 0 if success, < 0 otherwise.
- */
-int cxgb3i_ddp_tag_reserve(struct t3cdev *tdev, unsigned int tid,
- struct cxgb3i_tag_format *tformat, u32 *tagp,
- struct cxgb3i_gather_list *gl, gfp_t gfp)
-{
- struct cxgb3i_ddp_info *ddp = tdev->ulp_iscsi;
- struct pagepod_hdr hdr;
- unsigned int npods;
- int idx = -1;
- int err = -ENOMEM;
- u32 sw_tag = *tagp;
- u32 tag;
-
- if (page_idx >= DDP_PGIDX_MAX || !ddp || !gl || !gl->nelem ||
- gl->length < DDP_THRESHOLD) {
- ddp_log_debug("pgidx %u, xfer %u/%u, NO ddp.\n",
- page_idx, gl->length, DDP_THRESHOLD);
- return -EINVAL;
- }
-
- npods = (gl->nelem + PPOD_PAGES_MAX - 1) >> PPOD_PAGES_SHIFT;
-
- if (ddp->idx_last == ddp->nppods)
- idx = ddp_find_unused_entries(ddp, 0, ddp->nppods, npods, gl);
- else {
- idx = ddp_find_unused_entries(ddp, ddp->idx_last + 1,
- ddp->nppods, npods, gl);
- if (idx < 0 && ddp->idx_last >= npods) {
- idx = ddp_find_unused_entries(ddp, 0,
- min(ddp->idx_last + npods, ddp->nppods),
- npods, gl);
- }
- }
- if (idx < 0) {
- ddp_log_debug("xferlen %u, gl %u, npods %u NO DDP.\n",
- gl->length, gl->nelem, npods);
- return idx;
- }
-
- err = ddp_alloc_gl_skb(ddp, idx, npods, gfp);
- if (err < 0)
- goto unmark_entries;
-
- tag = cxgb3i_ddp_tag_base(tformat, sw_tag);
- tag |= idx << PPOD_IDX_SHIFT;
-
- hdr.rsvd = 0;
- hdr.vld_tid = htonl(F_PPOD_VALID | V_PPOD_TID(tid));
- hdr.pgsz_tag_clr = htonl(tag & ddp->rsvd_tag_mask);
- hdr.maxoffset = htonl(gl->length);
- hdr.pgoffset = htonl(gl->offset);
-
- err = set_ddp_map(ddp, &hdr, idx, npods, gl);
- if (err < 0)
- goto free_gl_skb;
-
- ddp->idx_last = idx;
- ddp_log_debug("xfer %u, gl %u,%u, tid 0x%x, 0x%x -> 0x%x(%u,%u).\n",
- gl->length, gl->nelem, gl->offset, tid, sw_tag, tag,
- idx, npods);
- *tagp = tag;
- return 0;
-
-free_gl_skb:
- ddp_free_gl_skb(ddp, idx, npods);
-unmark_entries:
- ddp_unmark_entries(ddp, idx, npods);
- return err;
-}
-
-/**
- * cxgb3i_ddp_tag_release - release a ddp tag
- * @tdev: t3cdev adapter
- * @tag: ddp tag
- * ddp cleanup for a given ddp tag and release all the resources held
- */
-void cxgb3i_ddp_tag_release(struct t3cdev *tdev, u32 tag)
-{
- struct cxgb3i_ddp_info *ddp = tdev->ulp_iscsi;
- u32 idx;
-
- if (!ddp) {
- ddp_log_error("release ddp tag 0x%x, ddp NULL.\n", tag);
- return;
- }
-
- idx = (tag >> PPOD_IDX_SHIFT) & ddp->idx_mask;
- if (idx < ddp->nppods) {
- struct cxgb3i_gather_list *gl = ddp->gl_map[idx];
- unsigned int npods;
-
- if (!gl || !gl->nelem) {
- ddp_log_error("release 0x%x, idx 0x%x, gl 0x%p, %u.\n",
- tag, idx, gl, gl ? gl->nelem : 0);
- return;
- }
- npods = (gl->nelem + PPOD_PAGES_MAX - 1) >> PPOD_PAGES_SHIFT;
- ddp_log_debug("ddp tag 0x%x, release idx 0x%x, npods %u.\n",
- tag, idx, npods);
- clear_ddp_map(ddp, tag, idx, npods);
- ddp_unmark_entries(ddp, idx, npods);
- cxgb3i_ddp_release_gl(gl, ddp->pdev);
- } else
- ddp_log_error("ddp tag 0x%x, idx 0x%x > max 0x%x.\n",
- tag, idx, ddp->nppods);
-}
-
-static int setup_conn_pgidx(struct t3cdev *tdev, unsigned int tid, int pg_idx,
- int reply)
-{
- struct sk_buff *skb = alloc_skb(sizeof(struct cpl_set_tcb_field),
- GFP_KERNEL);
- struct cpl_set_tcb_field *req;
- u64 val = pg_idx < DDP_PGIDX_MAX ? pg_idx : 0;
-
- if (!skb)
- return -ENOMEM;
-
- /* set up ulp submode and page size */
- req = (struct cpl_set_tcb_field *)skb_put(skb, sizeof(*req));
- req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
- req->wr.wr_lo = 0;
- OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid));
- req->reply = V_NO_REPLY(reply ? 0 : 1);
- req->cpu_idx = 0;
- req->word = htons(31);
- req->mask = cpu_to_be64(0xF0000000);
- req->val = cpu_to_be64(val << 28);
- skb->priority = CPL_PRIORITY_CONTROL;
-
- cxgb3_ofld_send(tdev, skb);
- return 0;
-}
-
-/**
- * cxgb3i_setup_conn_host_pagesize - setup the conn.'s ddp page size
- * @tdev: t3cdev adapter
- * @tid: connection id
- * @reply: request reply from h/w
- * set up the ddp page size based on the host PAGE_SIZE for a connection
- * identified by tid
- */
-int cxgb3i_setup_conn_host_pagesize(struct t3cdev *tdev, unsigned int tid,
- int reply)
-{
- return setup_conn_pgidx(tdev, tid, page_idx, reply);
-}
-
-/**
- * cxgb3i_setup_conn_pagesize - setup the conn.'s ddp page size
- * @tdev: t3cdev adapter
- * @tid: connection id
- * @reply: request reply from h/w
- * @pgsz: ddp page size
- * set up the ddp page size for a connection identified by tid
- */
-int cxgb3i_setup_conn_pagesize(struct t3cdev *tdev, unsigned int tid,
- int reply, unsigned long pgsz)
-{
- int pgidx = cxgb3i_ddp_find_page_index(pgsz);
-
- return setup_conn_pgidx(tdev, tid, pgidx, reply);
-}
-
-/**
- * cxgb3i_setup_conn_digest - setup conn. digest setting
- * @tdev: t3cdev adapter
- * @tid: connection id
- * @hcrc: header digest enabled
- * @dcrc: data digest enabled
- * @reply: request reply from h/w
- * set up the iscsi digest settings for a connection identified by tid
- */
-int cxgb3i_setup_conn_digest(struct t3cdev *tdev, unsigned int tid,
- int hcrc, int dcrc, int reply)
-{
- struct sk_buff *skb = alloc_skb(sizeof(struct cpl_set_tcb_field),
- GFP_KERNEL);
- struct cpl_set_tcb_field *req;
- u64 val = (hcrc ? 1 : 0) | (dcrc ? 2 : 0);
-
- if (!skb)
- return -ENOMEM;
-
- /* set up ulp submode and page size */
- req = (struct cpl_set_tcb_field *)skb_put(skb, sizeof(*req));
- req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
- req->wr.wr_lo = 0;
- OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid));
- req->reply = V_NO_REPLY(reply ? 0 : 1);
- req->cpu_idx = 0;
- req->word = htons(31);
- req->mask = cpu_to_be64(0x0F000000);
- req->val = cpu_to_be64(val << 24);
- skb->priority = CPL_PRIORITY_CONTROL;
-
- cxgb3_ofld_send(tdev, skb);
- return 0;
-}
-
-
-/**
- * cxgb3i_adapter_ddp_info - read the adapter's ddp information
- * @tdev: t3cdev adapter
- * @tformat: tag format
- * @txsz: max tx pdu payload size, filled in by this func.
- * @rxsz: max rx pdu payload size, filled in by this func.
- * setup the tag format for a given iscsi entity
- */
-int cxgb3i_adapter_ddp_info(struct t3cdev *tdev,
- struct cxgb3i_tag_format *tformat,
- unsigned int *txsz, unsigned int *rxsz)
-{
- struct cxgb3i_ddp_info *ddp;
- unsigned char idx_bits;
-
- if (!tformat)
- return -EINVAL;
-
- if (!tdev->ulp_iscsi)
- return -EINVAL;
-
- ddp = (struct cxgb3i_ddp_info *)tdev->ulp_iscsi;
-
- idx_bits = 32 - tformat->sw_bits;
- tformat->rsvd_bits = ddp->idx_bits;
- tformat->rsvd_shift = PPOD_IDX_SHIFT;
- tformat->rsvd_mask = (1 << tformat->rsvd_bits) - 1;
-
- ddp_log_info("tag format: sw %u, rsvd %u,%u, mask 0x%x.\n",
- tformat->sw_bits, tformat->rsvd_bits,
- tformat->rsvd_shift, tformat->rsvd_mask);
-
- *txsz = min_t(unsigned int, ULP2_MAX_PDU_PAYLOAD,
- ddp->max_txsz - ISCSI_PDU_NONPAYLOAD_LEN);
- *rxsz = min_t(unsigned int, ULP2_MAX_PDU_PAYLOAD,
- ddp->max_rxsz - ISCSI_PDU_NONPAYLOAD_LEN);
- ddp_log_info("max payload size: %u/%u, %u/%u.\n",
- *txsz, ddp->max_txsz, *rxsz, ddp->max_rxsz);
- return 0;
-}
-
-/**
- * cxgb3i_ddp_cleanup - release the cxgb3 adapter's ddp resource
- * @tdev: t3cdev adapter
- * release all the resource held by the ddp pagepod manager for a given
- * adapter if needed
- */
-
-static void ddp_cleanup(struct kref *kref)
-{
- struct cxgb3i_ddp_info *ddp = container_of(kref,
- struct cxgb3i_ddp_info,
- refcnt);
- int i = 0;
-
- ddp_log_info("kref release ddp 0x%p, t3dev 0x%p.\n", ddp, ddp->tdev);
-
- ddp->tdev->ulp_iscsi = NULL;
- while (i < ddp->nppods) {
- struct cxgb3i_gather_list *gl = ddp->gl_map[i];
- if (gl) {
- int npods = (gl->nelem + PPOD_PAGES_MAX - 1)
- >> PPOD_PAGES_SHIFT;
- ddp_log_info("t3dev 0x%p, ddp %d + %d.\n",
- ddp->tdev, i, npods);
- kfree(gl);
- ddp_free_gl_skb(ddp, i, npods);
- i += npods;
- } else
- i++;
- }
- cxgb3i_free_big_mem(ddp);
-}
-
-void cxgb3i_ddp_cleanup(struct t3cdev *tdev)
-{
- struct cxgb3i_ddp_info *ddp = (struct cxgb3i_ddp_info *)tdev->ulp_iscsi;
-
- ddp_log_info("t3dev 0x%p, release ddp 0x%p.\n", tdev, ddp);
- if (ddp)
- kref_put(&ddp->refcnt, ddp_cleanup);
-}
-
-/**
- * ddp_init - initialize the cxgb3 adapter's ddp resource
- * @tdev: t3cdev adapter
- * initialize the ddp pagepod manager for a given adapter
- */
-static void ddp_init(struct t3cdev *tdev)
-{
- struct cxgb3i_ddp_info *ddp = tdev->ulp_iscsi;
- struct ulp_iscsi_info uinfo;
- unsigned int ppmax, bits;
- int i, err;
-
- if (ddp) {
- kref_get(&ddp->refcnt);
- ddp_log_warn("t3dev 0x%p, ddp 0x%p already set up.\n",
- tdev, tdev->ulp_iscsi);
- return;
- }
-
- err = tdev->ctl(tdev, ULP_ISCSI_GET_PARAMS, &uinfo);
- if (err < 0) {
- ddp_log_error("%s, failed to get iscsi param err=%d.\n",
- tdev->name, err);
- return;
- }
-
- ppmax = (uinfo.ulimit - uinfo.llimit + 1) >> PPOD_SIZE_SHIFT;
- bits = __ilog2_u32(ppmax) + 1;
- if (bits > PPOD_IDX_MAX_SIZE)
- bits = PPOD_IDX_MAX_SIZE;
- ppmax = (1 << (bits - 1)) - 1;
-
- ddp = cxgb3i_alloc_big_mem(sizeof(struct cxgb3i_ddp_info) +
- ppmax *
- (sizeof(struct cxgb3i_gather_list *) +
- sizeof(struct sk_buff *)),
- GFP_KERNEL);
- if (!ddp) {
- ddp_log_warn("%s unable to alloc ddp 0x%d, ddp disabled.\n",
- tdev->name, ppmax);
- return;
- }
- ddp->gl_map = (struct cxgb3i_gather_list **)(ddp + 1);
- ddp->gl_skb = (struct sk_buff **)(((char *)ddp->gl_map) +
- ppmax *
- sizeof(struct cxgb3i_gather_list *));
- spin_lock_init(&ddp->map_lock);
- kref_init(&ddp->refcnt);
-
- ddp->tdev = tdev;
- ddp->pdev = uinfo.pdev;
- ddp->max_txsz = min_t(unsigned int, uinfo.max_txsz, ULP2_MAX_PKT_SIZE);
- ddp->max_rxsz = min_t(unsigned int, uinfo.max_rxsz, ULP2_MAX_PKT_SIZE);
- ddp->llimit = uinfo.llimit;
- ddp->ulimit = uinfo.ulimit;
- ddp->nppods = ppmax;
- ddp->idx_last = ppmax;
- ddp->idx_bits = bits;
- ddp->idx_mask = (1 << bits) - 1;
- ddp->rsvd_tag_mask = (1 << (bits + PPOD_IDX_SHIFT)) - 1;
-
- uinfo.tagmask = ddp->idx_mask << PPOD_IDX_SHIFT;
- for (i = 0; i < DDP_PGIDX_MAX; i++)
- uinfo.pgsz_factor[i] = ddp_page_order[i];
- uinfo.ulimit = uinfo.llimit + (ppmax << PPOD_SIZE_SHIFT);
-
- err = tdev->ctl(tdev, ULP_ISCSI_SET_PARAMS, &uinfo);
- if (err < 0) {
- ddp_log_warn("%s unable to set iscsi param err=%d, "
- "ddp disabled.\n", tdev->name, err);
- goto free_ddp_map;
- }
-
- tdev->ulp_iscsi = ddp;
-
- ddp_log_info("tdev 0x%p, nppods %u, bits %u, mask 0x%x,0x%x pkt %u/%u,"
- " %u/%u.\n",
- tdev, ppmax, ddp->idx_bits, ddp->idx_mask,
- ddp->rsvd_tag_mask, ddp->max_txsz, uinfo.max_txsz,
- ddp->max_rxsz, uinfo.max_rxsz);
- return;
-
-free_ddp_map:
- cxgb3i_free_big_mem(ddp);
-}
-
-/**
- * cxgb3i_ddp_init - initialize ddp functions
- */
-void cxgb3i_ddp_init(struct t3cdev *tdev)
-{
- if (page_idx == DDP_PGIDX_MAX) {
- page_idx = cxgb3i_ddp_find_page_index(PAGE_SIZE);
-
- if (page_idx == DDP_PGIDX_MAX) {
- ddp_log_info("system PAGE_SIZE %lu, update hw.\n",
- PAGE_SIZE);
- if (cxgb3i_ddp_adjust_page_table() < 0) {
- ddp_log_info("PAGE_SIZE %lu, ddp disabled.\n",
- PAGE_SIZE);
- return;
- }
- page_idx = cxgb3i_ddp_find_page_index(PAGE_SIZE);
- }
- ddp_log_info("system PAGE_SIZE %lu, ddp idx %u.\n",
- PAGE_SIZE, page_idx);
- }
- ddp_init(tdev);
-}
diff --git a/drivers/scsi/cxgb3i/cxgb3i_ddp.h b/drivers/scsi/cxgb3i/cxgb3i_ddp.h
deleted file mode 100644
index 6761b329124d..000000000000
--- a/drivers/scsi/cxgb3i/cxgb3i_ddp.h
+++ /dev/null
@@ -1,312 +0,0 @@
-/*
- * cxgb3i_ddp.h: Chelsio S3xx iSCSI DDP Manager.
- *
- * Copyright (c) 2008 Chelsio Communications, 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.
- *
- * Written by: Karen Xie (kxie@chelsio.com)
- */
-
-#ifndef __CXGB3I_ULP2_DDP_H__
-#define __CXGB3I_ULP2_DDP_H__
-
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-
-/**
- * struct cxgb3i_tag_format - cxgb3i ulp tag format for an iscsi entity
- *
- * @sw_bits: # of bits used by iscsi software layer
- * @rsvd_bits: # of bits used by h/w
- * @rsvd_shift: h/w bits shift left
- * @rsvd_mask: reserved bit mask
- */
-struct cxgb3i_tag_format {
- unsigned char sw_bits;
- unsigned char rsvd_bits;
- unsigned char rsvd_shift;
- unsigned char filler[1];
- u32 rsvd_mask;
-};
-
-/**
- * struct cxgb3i_gather_list - cxgb3i direct data placement memory
- *
- * @tag: ddp tag
- * @length: total data buffer length
- * @offset: initial offset to the 1st page
- * @nelem: # of pages
- * @pages: page pointers
- * @phys_addr: physical address
- */
-struct cxgb3i_gather_list {
- u32 tag;
- unsigned int length;
- unsigned int offset;
- unsigned int nelem;
- struct page **pages;
- dma_addr_t phys_addr[0];
-};
-
-/**
- * struct cxgb3i_ddp_info - cxgb3i direct data placement for pdu payload
- *
- * @list: list head to link elements
- * @refcnt: ref. count
- * @tdev: pointer to t3cdev used by cxgb3 driver
- * @max_txsz: max tx packet size for ddp
- * @max_rxsz: max rx packet size for ddp
- * @llimit: lower bound of the page pod memory
- * @ulimit: upper bound of the page pod memory
- * @nppods: # of page pod entries
- * @idx_last: page pod entry last used
- * @idx_bits: # of bits the pagepod index would take
- * @idx_mask: pagepod index mask
- * @rsvd_tag_mask: tag mask
- * @map_lock: lock to synchonize access to the page pod map
- * @gl_map: ddp memory gather list
- * @gl_skb: skb used to program the pagepod
- */
-struct cxgb3i_ddp_info {
- struct list_head list;
- struct kref refcnt;
- struct t3cdev *tdev;
- struct pci_dev *pdev;
- unsigned int max_txsz;
- unsigned int max_rxsz;
- unsigned int llimit;
- unsigned int ulimit;
- unsigned int nppods;
- unsigned int idx_last;
- unsigned char idx_bits;
- unsigned char filler[3];
- u32 idx_mask;
- u32 rsvd_tag_mask;
- spinlock_t map_lock;
- struct cxgb3i_gather_list **gl_map;
- struct sk_buff **gl_skb;
-};
-
-#define ISCSI_PDU_NONPAYLOAD_LEN 312 /* bhs(48) + ahs(256) + digest(8) */
-#define ULP2_MAX_PKT_SIZE 16224
-#define ULP2_MAX_PDU_PAYLOAD (ULP2_MAX_PKT_SIZE - ISCSI_PDU_NONPAYLOAD_LEN)
-#define PPOD_PAGES_MAX 4
-#define PPOD_PAGES_SHIFT 2 /* 4 pages per pod */
-
-/*
- * struct pagepod_hdr, pagepod - pagepod format
- */
-struct pagepod_hdr {
- u32 vld_tid;
- u32 pgsz_tag_clr;
- u32 maxoffset;
- u32 pgoffset;
- u64 rsvd;
-};
-
-struct pagepod {
- struct pagepod_hdr hdr;
- u64 addr[PPOD_PAGES_MAX + 1];
-};
-
-#define PPOD_SIZE sizeof(struct pagepod) /* 64 */
-#define PPOD_SIZE_SHIFT 6
-
-#define PPOD_COLOR_SHIFT 0
-#define PPOD_COLOR_SIZE 6
-#define PPOD_COLOR_MASK ((1 << PPOD_COLOR_SIZE) - 1)
-
-#define PPOD_IDX_SHIFT PPOD_COLOR_SIZE
-#define PPOD_IDX_MAX_SIZE 24
-
-#define S_PPOD_TID 0
-#define M_PPOD_TID 0xFFFFFF
-#define V_PPOD_TID(x) ((x) << S_PPOD_TID)
-
-#define S_PPOD_VALID 24
-#define V_PPOD_VALID(x) ((x) << S_PPOD_VALID)
-#define F_PPOD_VALID V_PPOD_VALID(1U)
-
-#define S_PPOD_COLOR 0
-#define M_PPOD_COLOR 0x3F
-#define V_PPOD_COLOR(x) ((x) << S_PPOD_COLOR)
-
-#define S_PPOD_TAG 6
-#define M_PPOD_TAG 0xFFFFFF
-#define V_PPOD_TAG(x) ((x) << S_PPOD_TAG)
-
-#define S_PPOD_PGSZ 30
-#define M_PPOD_PGSZ 0x3
-#define V_PPOD_PGSZ(x) ((x) << S_PPOD_PGSZ)
-
-/*
- * large memory chunk allocation/release
- * use vmalloc() if kmalloc() fails
- */
-static inline void *cxgb3i_alloc_big_mem(unsigned int size,
- gfp_t gfp)
-{
- void *p = kmalloc(size, gfp);
- if (!p)
- p = vmalloc(size);
- if (p)
- memset(p, 0, size);
- return p;
-}
-
-static inline void cxgb3i_free_big_mem(void *addr)
-{
- if (is_vmalloc_addr(addr))
- vfree(addr);
- else
- kfree(addr);
-}
-
-/*
- * cxgb3i ddp tag are 32 bits, it consists of reserved bits used by h/w and
- * non-reserved bits that can be used by the iscsi s/w.
- * The reserved bits are identified by the rsvd_bits and rsvd_shift fields
- * in struct cxgb3i_tag_format.
- *
- * The upper most reserved bit can be used to check if a tag is ddp tag or not:
- * if the bit is 0, the tag is a valid ddp tag
- */
-
-/**
- * cxgb3i_is_ddp_tag - check if a given tag is a hw/ddp tag
- * @tformat: tag format information
- * @tag: tag to be checked
- *
- * return true if the tag is a ddp tag, false otherwise.
- */
-static inline int cxgb3i_is_ddp_tag(struct cxgb3i_tag_format *tformat, u32 tag)
-{
- return !(tag & (1 << (tformat->rsvd_bits + tformat->rsvd_shift - 1)));
-}
-
-/**
- * cxgb3i_sw_tag_usable - check if s/w tag has enough bits left for hw bits
- * @tformat: tag format information
- * @sw_tag: s/w tag to be checked
- *
- * return true if the tag can be used for hw ddp tag, false otherwise.
- */
-static inline int cxgb3i_sw_tag_usable(struct cxgb3i_tag_format *tformat,
- u32 sw_tag)
-{
- sw_tag >>= (32 - tformat->rsvd_bits);
- return !sw_tag;
-}
-
-/**
- * cxgb3i_set_non_ddp_tag - mark a given s/w tag as an invalid ddp tag
- * @tformat: tag format information
- * @sw_tag: s/w tag to be checked
- *
- * insert 1 at the upper most reserved bit to mark it as an invalid ddp tag.
- */
-static inline u32 cxgb3i_set_non_ddp_tag(struct cxgb3i_tag_format *tformat,
- u32 sw_tag)
-{
- unsigned char shift = tformat->rsvd_bits + tformat->rsvd_shift - 1;
- u32 mask = (1 << shift) - 1;
-
- if (sw_tag && (sw_tag & ~mask)) {
- u32 v1 = sw_tag & ((1 << shift) - 1);
- u32 v2 = (sw_tag >> (shift - 1)) << shift;
-
- return v2 | v1 | 1 << shift;
- }
- return sw_tag | 1 << shift;
-}
-
-/**
- * cxgb3i_ddp_tag_base - shift s/w tag bits so that reserved bits are not used
- * @tformat: tag format information
- * @sw_tag: s/w tag to be checked
- */
-static inline u32 cxgb3i_ddp_tag_base(struct cxgb3i_tag_format *tformat,
- u32 sw_tag)
-{
- u32 mask = (1 << tformat->rsvd_shift) - 1;
-
- if (sw_tag && (sw_tag & ~mask)) {
- u32 v1 = sw_tag & mask;
- u32 v2 = sw_tag >> tformat->rsvd_shift;
-
- v2 <<= tformat->rsvd_shift + tformat->rsvd_bits;
- return v2 | v1;
- }
- return sw_tag;
-}
-
-/**
- * cxgb3i_tag_rsvd_bits - get the reserved bits used by the h/w
- * @tformat: tag format information
- * @tag: tag to be checked
- *
- * return the reserved bits in the tag
- */
-static inline u32 cxgb3i_tag_rsvd_bits(struct cxgb3i_tag_format *tformat,
- u32 tag)
-{
- if (cxgb3i_is_ddp_tag(tformat, tag))
- return (tag >> tformat->rsvd_shift) & tformat->rsvd_mask;
- return 0;
-}
-
-/**
- * cxgb3i_tag_nonrsvd_bits - get the non-reserved bits used by the s/w
- * @tformat: tag format information
- * @tag: tag to be checked
- *
- * return the non-reserved bits in the tag.
- */
-static inline u32 cxgb3i_tag_nonrsvd_bits(struct cxgb3i_tag_format *tformat,
- u32 tag)
-{
- unsigned char shift = tformat->rsvd_bits + tformat->rsvd_shift - 1;
- u32 v1, v2;
-
- if (cxgb3i_is_ddp_tag(tformat, tag)) {
- v1 = tag & ((1 << tformat->rsvd_shift) - 1);
- v2 = (tag >> (shift + 1)) << tformat->rsvd_shift;
- } else {
- u32 mask = (1 << shift) - 1;
-
- tag &= ~(1 << shift);
- v1 = tag & mask;
- v2 = (tag >> 1) & ~mask;
- }
- return v1 | v2;
-}
-
-int cxgb3i_ddp_tag_reserve(struct t3cdev *, unsigned int tid,
- struct cxgb3i_tag_format *, u32 *tag,
- struct cxgb3i_gather_list *, gfp_t gfp);
-void cxgb3i_ddp_tag_release(struct t3cdev *, u32 tag);
-
-struct cxgb3i_gather_list *cxgb3i_ddp_make_gl(unsigned int xferlen,
- struct scatterlist *sgl,
- unsigned int sgcnt,
- struct pci_dev *pdev,
- gfp_t gfp);
-void cxgb3i_ddp_release_gl(struct cxgb3i_gather_list *gl,
- struct pci_dev *pdev);
-
-int cxgb3i_setup_conn_host_pagesize(struct t3cdev *, unsigned int tid,
- int reply);
-int cxgb3i_setup_conn_pagesize(struct t3cdev *, unsigned int tid, int reply,
- unsigned long pgsz);
-int cxgb3i_setup_conn_digest(struct t3cdev *, unsigned int tid,
- int hcrc, int dcrc, int reply);
-int cxgb3i_ddp_find_page_index(unsigned long pgsz);
-int cxgb3i_adapter_ddp_info(struct t3cdev *, struct cxgb3i_tag_format *,
- unsigned int *txsz, unsigned int *rxsz);
-
-void cxgb3i_ddp_init(struct t3cdev *);
-void cxgb3i_ddp_cleanup(struct t3cdev *);
-#endif
diff --git a/drivers/scsi/cxgb3i/cxgb3i_init.c b/drivers/scsi/cxgb3i/cxgb3i_init.c
deleted file mode 100644
index 685af3698518..000000000000
--- a/drivers/scsi/cxgb3i/cxgb3i_init.c
+++ /dev/null
@@ -1,132 +0,0 @@
-/* cxgb3i_init.c: Chelsio S3xx iSCSI driver.
- *
- * Copyright (c) 2008 Chelsio Communications, 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.
- *
- * Written by: Karen Xie (kxie@chelsio.com)
- */
-
-#include "cxgb3i.h"
-
-#define DRV_MODULE_NAME "cxgb3i"
-#define DRV_MODULE_VERSION "1.0.2"
-#define DRV_MODULE_RELDATE "Mar. 2009"
-
-static char version[] =
- "Chelsio S3xx iSCSI Driver " DRV_MODULE_NAME
- " v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
-
-MODULE_AUTHOR("Karen Xie <kxie@chelsio.com>");
-MODULE_DESCRIPTION("Chelsio S3xx iSCSI Driver");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(DRV_MODULE_VERSION);
-
-static void open_s3_dev(struct t3cdev *);
-static void close_s3_dev(struct t3cdev *);
-static void s3_event_handler(struct t3cdev *tdev, u32 event, u32 port);
-
-static cxgb3_cpl_handler_func cxgb3i_cpl_handlers[NUM_CPL_CMDS];
-static struct cxgb3_client t3c_client = {
- .name = "iscsi_cxgb3",
- .handlers = cxgb3i_cpl_handlers,
- .add = open_s3_dev,
- .remove = close_s3_dev,
- .event_handler = s3_event_handler,
-};
-
-/**
- * open_s3_dev - register with cxgb3 LLD
- * @t3dev: cxgb3 adapter instance
- */
-static void open_s3_dev(struct t3cdev *t3dev)
-{
- static int vers_printed;
-
- if (!vers_printed) {
- printk(KERN_INFO "%s", version);
- vers_printed = 1;
- }
-
- cxgb3i_ddp_init(t3dev);
- cxgb3i_sdev_add(t3dev, &t3c_client);
- cxgb3i_adapter_open(t3dev);
-}
-
-/**
- * close_s3_dev - de-register with cxgb3 LLD
- * @t3dev: cxgb3 adapter instance
- */
-static void close_s3_dev(struct t3cdev *t3dev)
-{
- cxgb3i_adapter_close(t3dev);
- cxgb3i_sdev_remove(t3dev);
- cxgb3i_ddp_cleanup(t3dev);
-}
-
-static void s3_event_handler(struct t3cdev *tdev, u32 event, u32 port)
-{
- struct cxgb3i_adapter *snic = cxgb3i_adapter_find_by_tdev(tdev);
-
- cxgb3i_log_info("snic 0x%p, tdev 0x%p, event 0x%x, port 0x%x.\n",
- snic, tdev, event, port);
- if (!snic)
- return;
-
- switch (event) {
- case OFFLOAD_STATUS_DOWN:
- snic->flags |= CXGB3I_ADAPTER_FLAG_RESET;
- break;
- case OFFLOAD_STATUS_UP:
- snic->flags &= ~CXGB3I_ADAPTER_FLAG_RESET;
- break;
- }
-}
-
-/**
- * cxgb3i_init_module - module init entry point
- *
- * initialize any driver wide global data structures and register itself
- * with the cxgb3 module
- */
-static int __init cxgb3i_init_module(void)
-{
- int err;
-
- err = cxgb3i_sdev_init(cxgb3i_cpl_handlers);
- if (err < 0)
- return err;
-
- err = cxgb3i_iscsi_init();
- if (err < 0)
- return err;
-
- err = cxgb3i_pdu_init();
- if (err < 0) {
- cxgb3i_iscsi_cleanup();
- return err;
- }
-
- cxgb3_register_client(&t3c_client);
-
- return 0;
-}
-
-/**
- * cxgb3i_exit_module - module cleanup/exit entry point
- *
- * go through the driver hba list and for each hba, release any resource held.
- * and unregisters iscsi transport and the cxgb3 module
- */
-static void __exit cxgb3i_exit_module(void)
-{
- cxgb3_unregister_client(&t3c_client);
- cxgb3i_pdu_cleanup();
- cxgb3i_iscsi_cleanup();
- cxgb3i_sdev_cleanup();
-}
-
-module_init(cxgb3i_init_module);
-module_exit(cxgb3i_exit_module);
diff --git a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
deleted file mode 100644
index 7b686abaae64..000000000000
--- a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
+++ /dev/null
@@ -1,1018 +0,0 @@
-/* cxgb3i_iscsi.c: Chelsio S3xx iSCSI driver.
- *
- * Copyright (c) 2008 Chelsio Communications, Inc.
- * Copyright (c) 2008 Mike Christie
- * Copyright (c) 2008 Red Hat, Inc. All rights reserved.
- *
- * 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.
- *
- * Written by: Karen Xie (kxie@chelsio.com)
- */
-
-#include <linux/inet.h>
-#include <linux/slab.h>
-#include <linux/crypto.h>
-#include <linux/if_vlan.h>
-#include <net/dst.h>
-#include <net/tcp.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_device.h>
-#include <scsi/scsi_eh.h>
-#include <scsi/scsi_host.h>
-#include <scsi/scsi.h>
-#include <scsi/iscsi_proto.h>
-#include <scsi/libiscsi.h>
-#include <scsi/scsi_transport_iscsi.h>
-
-#include "cxgb3i.h"
-#include "cxgb3i_pdu.h"
-
-#ifdef __DEBUG_CXGB3I_TAG__
-#define cxgb3i_tag_debug cxgb3i_log_debug
-#else
-#define cxgb3i_tag_debug(fmt...)
-#endif
-
-#ifdef __DEBUG_CXGB3I_API__
-#define cxgb3i_api_debug cxgb3i_log_debug
-#else
-#define cxgb3i_api_debug(fmt...)
-#endif
-
-/*
- * align pdu size to multiple of 512 for better performance
- */
-#define align_pdu_size(n) do { n = (n) & (~511); } while (0)
-
-static struct scsi_transport_template *cxgb3i_scsi_transport;
-static struct scsi_host_template cxgb3i_host_template;
-static struct iscsi_transport cxgb3i_iscsi_transport;
-static unsigned char sw_tag_idx_bits;
-static unsigned char sw_tag_age_bits;
-
-static LIST_HEAD(cxgb3i_snic_list);
-static DEFINE_RWLOCK(cxgb3i_snic_rwlock);
-
-/**
- * cxgb3i_adpater_find_by_tdev - find the cxgb3i_adapter structure via t3cdev
- * @tdev: t3cdev pointer
- */
-struct cxgb3i_adapter *cxgb3i_adapter_find_by_tdev(struct t3cdev *tdev)
-{
- struct cxgb3i_adapter *snic;
-
- read_lock(&cxgb3i_snic_rwlock);
- list_for_each_entry(snic, &cxgb3i_snic_list, list_head) {
- if (snic->tdev == tdev) {
- read_unlock(&cxgb3i_snic_rwlock);
- return snic;
- }
- }
- read_unlock(&cxgb3i_snic_rwlock);
- return NULL;
-}
-
-static inline int adapter_update(struct cxgb3i_adapter *snic)
-{
- cxgb3i_log_info("snic 0x%p, t3dev 0x%p, updating.\n",
- snic, snic->tdev);
- return cxgb3i_adapter_ddp_info(snic->tdev, &snic->tag_format,
- &snic->tx_max_size,
- &snic->rx_max_size);
-}
-
-static int adapter_add(struct cxgb3i_adapter *snic)
-{
- struct t3cdev *t3dev = snic->tdev;
- struct adapter *adapter = tdev2adap(t3dev);
- int i, err;
-
- snic->pdev = adapter->pdev;
- snic->tag_format.sw_bits = sw_tag_idx_bits + sw_tag_age_bits;
-
- err = cxgb3i_adapter_ddp_info(t3dev, &snic->tag_format,
- &snic->tx_max_size,
- &snic->rx_max_size);
- if (err < 0)
- return err;
-
- for_each_port(adapter, i) {
- snic->hba[i] = cxgb3i_hba_host_add(snic, adapter->port[i]);
- if (!snic->hba[i])
- return -EINVAL;
- }
- snic->hba_cnt = adapter->params.nports;
-
- /* add to the list */
- write_lock(&cxgb3i_snic_rwlock);
- list_add_tail(&snic->list_head, &cxgb3i_snic_list);
- write_unlock(&cxgb3i_snic_rwlock);
-
- cxgb3i_log_info("t3dev 0x%p open, snic 0x%p, %u scsi hosts added.\n",
- t3dev, snic, snic->hba_cnt);
- return 0;
-}
-
-/**
- * cxgb3i_adapter_open - init a s3 adapter structure and any h/w settings
- * @t3dev: t3cdev adapter
- */
-void cxgb3i_adapter_open(struct t3cdev *t3dev)
-{
- struct cxgb3i_adapter *snic = cxgb3i_adapter_find_by_tdev(t3dev);
- int err;
-
- if (snic)
- err = adapter_update(snic);
- else {
- snic = kzalloc(sizeof(*snic), GFP_KERNEL);
- if (snic) {
- spin_lock_init(&snic->lock);
- snic->tdev = t3dev;
- err = adapter_add(snic);
- } else
- err = -ENOMEM;
- }
-
- if (err < 0) {
- cxgb3i_log_info("snic 0x%p, f 0x%x, t3dev 0x%p open, err %d.\n",
- snic, snic ? snic->flags : 0, t3dev, err);
- if (snic) {
- snic->flags &= ~CXGB3I_ADAPTER_FLAG_RESET;
- cxgb3i_adapter_close(t3dev);
- }
- }
-}
-
-/**
- * cxgb3i_adapter_close - release the resources held and cleanup h/w settings
- * @t3dev: t3cdev adapter
- */
-void cxgb3i_adapter_close(struct t3cdev *t3dev)
-{
- struct cxgb3i_adapter *snic = cxgb3i_adapter_find_by_tdev(t3dev);
- int i;
-
- if (!snic || snic->flags & CXGB3I_ADAPTER_FLAG_RESET) {
- cxgb3i_log_info("t3dev 0x%p close, snic 0x%p, f 0x%x.\n",
- t3dev, snic, snic ? snic->flags : 0);
- return;
- }
-
- /* remove from the list */
- write_lock(&cxgb3i_snic_rwlock);
- list_del(&snic->list_head);
- write_unlock(&cxgb3i_snic_rwlock);
-
- for (i = 0; i < snic->hba_cnt; i++) {
- if (snic->hba[i]) {
- cxgb3i_hba_host_remove(snic->hba[i]);
- snic->hba[i] = NULL;
- }
- }
- cxgb3i_log_info("t3dev 0x%p close, snic 0x%p, %u scsi hosts removed.\n",
- t3dev, snic, snic->hba_cnt);
- kfree(snic);
-}
-
-/**
- * cxgb3i_hba_find_by_netdev - find the cxgb3i_hba structure via net_device
- * @t3dev: t3cdev adapter
- */
-static struct cxgb3i_hba *cxgb3i_hba_find_by_netdev(struct net_device *ndev)
-{
- struct cxgb3i_adapter *snic;
- int i;
-
- if (ndev->priv_flags & IFF_802_1Q_VLAN)
- ndev = vlan_dev_real_dev(ndev);
-
- read_lock(&cxgb3i_snic_rwlock);
- list_for_each_entry(snic, &cxgb3i_snic_list, list_head) {
- for (i = 0; i < snic->hba_cnt; i++) {
- if (snic->hba[i]->ndev == ndev) {
- read_unlock(&cxgb3i_snic_rwlock);
- return snic->hba[i];
- }
- }
- }
- read_unlock(&cxgb3i_snic_rwlock);
- return NULL;
-}
-
-/**
- * cxgb3i_hba_host_add - register a new host with scsi/iscsi
- * @snic: the cxgb3i adapter
- * @ndev: associated net_device
- */
-struct cxgb3i_hba *cxgb3i_hba_host_add(struct cxgb3i_adapter *snic,
- struct net_device *ndev)
-{
- struct cxgb3i_hba *hba;
- struct Scsi_Host *shost;
- int err;
-
- shost = iscsi_host_alloc(&cxgb3i_host_template,
- sizeof(struct cxgb3i_hba), 1);
- if (!shost) {
- cxgb3i_log_info("snic 0x%p, ndev 0x%p, host_alloc failed.\n",
- snic, ndev);
- return NULL;
- }
-
- shost->transportt = cxgb3i_scsi_transport;
- shost->max_lun = CXGB3I_MAX_LUN;
- shost->max_id = CXGB3I_MAX_TARGET;
- shost->max_channel = 0;
- shost->max_cmd_len = 16;
-
- hba = iscsi_host_priv(shost);
- hba->snic = snic;
- hba->ndev = ndev;
- hba->shost = shost;
-
- pci_dev_get(snic->pdev);
- err = iscsi_host_add(shost, &snic->pdev->dev);
- if (err) {
- cxgb3i_log_info("snic 0x%p, ndev 0x%p, host_add failed.\n",
- snic, ndev);
- goto pci_dev_put;
- }
-
- cxgb3i_api_debug("shost 0x%p, hba 0x%p, no %u.\n",
- shost, hba, shost->host_no);
-
- return hba;
-
-pci_dev_put:
- pci_dev_put(snic->pdev);
- scsi_host_put(shost);
- return NULL;
-}
-
-/**
- * cxgb3i_hba_host_remove - de-register the host with scsi/iscsi
- * @hba: the cxgb3i hba
- */
-void cxgb3i_hba_host_remove(struct cxgb3i_hba *hba)
-{
- cxgb3i_api_debug("shost 0x%p, hba 0x%p, no %u.\n",
- hba->shost, hba, hba->shost->host_no);
- iscsi_host_remove(hba->shost);
- pci_dev_put(hba->snic->pdev);
- iscsi_host_free(hba->shost);
-}
-
-/**
- * cxgb3i_ep_connect - establish TCP connection to target portal
- * @shost: scsi host to use
- * @dst_addr: target IP address
- * @non_blocking: blocking or non-blocking call
- *
- * Initiates a TCP/IP connection to the dst_addr
- */
-static struct iscsi_endpoint *cxgb3i_ep_connect(struct Scsi_Host *shost,
- struct sockaddr *dst_addr,
- int non_blocking)
-{
- struct iscsi_endpoint *ep;
- struct cxgb3i_endpoint *cep;
- struct cxgb3i_hba *hba = NULL;
- struct s3_conn *c3cn = NULL;
- int err = 0;
-
- if (shost)
- hba = iscsi_host_priv(shost);
-
- cxgb3i_api_debug("shost 0x%p, hba 0x%p.\n", shost, hba);
-
- c3cn = cxgb3i_c3cn_create();
- if (!c3cn) {
- cxgb3i_log_info("ep connect OOM.\n");
- err = -ENOMEM;
- goto release_conn;
- }
-
- err = cxgb3i_c3cn_connect(hba ? hba->ndev : NULL, c3cn,
- (struct sockaddr_in *)dst_addr);
- if (err < 0) {
- cxgb3i_log_info("ep connect failed.\n");
- goto release_conn;
- }
-
- hba = cxgb3i_hba_find_by_netdev(c3cn->dst_cache->dev);
- if (!hba) {
- err = -ENOSPC;
- cxgb3i_log_info("NOT going through cxgbi device.\n");
- goto release_conn;
- }
-
- if (shost && hba != iscsi_host_priv(shost)) {
- err = -ENOSPC;
- cxgb3i_log_info("Could not connect through request host%u\n",
- shost->host_no);
- goto release_conn;
- }
-
- if (c3cn_is_closing(c3cn)) {
- err = -ENOSPC;
- cxgb3i_log_info("ep connect unable to connect.\n");
- goto release_conn;
- }
-
- ep = iscsi_create_endpoint(sizeof(*cep));
- if (!ep) {
- err = -ENOMEM;
- cxgb3i_log_info("iscsi alloc ep, OOM.\n");
- goto release_conn;
- }
- cep = ep->dd_data;
- cep->c3cn = c3cn;
- cep->hba = hba;
-
- cxgb3i_api_debug("ep 0x%p, 0x%p, c3cn 0x%p, hba 0x%p.\n",
- ep, cep, c3cn, hba);
- return ep;
-
-release_conn:
- cxgb3i_api_debug("conn 0x%p failed, release.\n", c3cn);
- if (c3cn)
- cxgb3i_c3cn_release(c3cn);
- return ERR_PTR(err);
-}
-
-/**
- * cxgb3i_ep_poll - polls for TCP connection establishement
- * @ep: TCP connection (endpoint) handle
- * @timeout_ms: timeout value in milli secs
- *
- * polls for TCP connect request to complete
- */
-static int cxgb3i_ep_poll(struct iscsi_endpoint *ep, int timeout_ms)
-{
- struct cxgb3i_endpoint *cep = ep->dd_data;
- struct s3_conn *c3cn = cep->c3cn;
-
- if (!c3cn_is_established(c3cn))
- return 0;
- cxgb3i_api_debug("ep 0x%p, c3cn 0x%p established.\n", ep, c3cn);
- return 1;
-}
-
-/**
- * cxgb3i_ep_disconnect - teardown TCP connection
- * @ep: TCP connection (endpoint) handle
- *
- * teardown TCP connection
- */
-static void cxgb3i_ep_disconnect(struct iscsi_endpoint *ep)
-{
- struct cxgb3i_endpoint *cep = ep->dd_data;
- struct cxgb3i_conn *cconn = cep->cconn;
-
- cxgb3i_api_debug("ep 0x%p, cep 0x%p.\n", ep, cep);
-
- if (cconn && cconn->conn) {
- /*
- * stop the xmit path so the xmit_pdu function is
- * not being called
- */
- iscsi_suspend_tx(cconn->conn);
-
- write_lock_bh(&cep->c3cn->callback_lock);
- cep->c3cn->user_data = NULL;
- cconn->cep = NULL;
- write_unlock_bh(&cep->c3cn->callback_lock);
- }
-
- cxgb3i_api_debug("ep 0x%p, cep 0x%p, release c3cn 0x%p.\n",
- ep, cep, cep->c3cn);
- cxgb3i_c3cn_release(cep->c3cn);
- iscsi_destroy_endpoint(ep);
-}
-
-/**
- * cxgb3i_session_create - create a new iscsi session
- * @cmds_max: max # of commands
- * @qdepth: scsi queue depth
- * @initial_cmdsn: initial iscsi CMDSN for this session
- *
- * Creates a new iSCSI session
- */
-static struct iscsi_cls_session *
-cxgb3i_session_create(struct iscsi_endpoint *ep, u16 cmds_max, u16 qdepth,
- u32 initial_cmdsn)
-{
- struct cxgb3i_endpoint *cep;
- struct cxgb3i_hba *hba;
- struct Scsi_Host *shost;
- struct iscsi_cls_session *cls_session;
- struct iscsi_session *session;
-
- if (!ep) {
- cxgb3i_log_error("%s, missing endpoint.\n", __func__);
- return NULL;
- }
-
- cep = ep->dd_data;
- hba = cep->hba;
- shost = hba->shost;
- cxgb3i_api_debug("ep 0x%p, cep 0x%p, hba 0x%p.\n", ep, cep, hba);
- BUG_ON(hba != iscsi_host_priv(shost));
-
- cls_session = iscsi_session_setup(&cxgb3i_iscsi_transport, shost,
- cmds_max, 0,
- sizeof(struct iscsi_tcp_task) +
- sizeof(struct cxgb3i_task_data),
- initial_cmdsn, ISCSI_MAX_TARGET);
- if (!cls_session)
- return NULL;
- session = cls_session->dd_data;
- if (iscsi_tcp_r2tpool_alloc(session))
- goto remove_session;
-
- return cls_session;
-
-remove_session:
- iscsi_session_teardown(cls_session);
- return NULL;
-}
-
-/**
- * cxgb3i_session_destroy - destroys iscsi session
- * @cls_session: pointer to iscsi cls session
- *
- * Destroys an iSCSI session instance and releases its all resources held
- */
-static void cxgb3i_session_destroy(struct iscsi_cls_session *cls_session)
-{
- cxgb3i_api_debug("sess 0x%p.\n", cls_session);
- iscsi_tcp_r2tpool_free(cls_session->dd_data);
- iscsi_session_teardown(cls_session);
-}
-
-/**
- * cxgb3i_conn_max_xmit_dlength -- calc the max. xmit pdu segment size
- * @conn: iscsi connection
- * check the max. xmit pdu payload, reduce it if needed
- */
-static inline int cxgb3i_conn_max_xmit_dlength(struct iscsi_conn *conn)
-
-{
- struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
- struct cxgb3i_conn *cconn = tcp_conn->dd_data;
- unsigned int max = max(512 * MAX_SKB_FRAGS, SKB_TX_HEADROOM);
-
- max = min(cconn->hba->snic->tx_max_size, max);
- if (conn->max_xmit_dlength)
- conn->max_xmit_dlength = min(conn->max_xmit_dlength, max);
- else
- conn->max_xmit_dlength = max;
- align_pdu_size(conn->max_xmit_dlength);
- cxgb3i_api_debug("conn 0x%p, max xmit %u.\n",
- conn, conn->max_xmit_dlength);
- return 0;
-}
-
-/**
- * cxgb3i_conn_max_recv_dlength -- check the max. recv pdu segment size
- * @conn: iscsi connection
- * return 0 if the value is valid, < 0 otherwise.
- */
-static inline int cxgb3i_conn_max_recv_dlength(struct iscsi_conn *conn)
-{
- struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
- struct cxgb3i_conn *cconn = tcp_conn->dd_data;
- unsigned int max = cconn->hba->snic->rx_max_size;
-
- align_pdu_size(max);
- if (conn->max_recv_dlength) {
- if (conn->max_recv_dlength > max) {
- cxgb3i_log_error("MaxRecvDataSegmentLength %u too big."
- " Need to be <= %u.\n",
- conn->max_recv_dlength, max);
- return -EINVAL;
- }
- conn->max_recv_dlength = min(conn->max_recv_dlength, max);
- align_pdu_size(conn->max_recv_dlength);
- } else
- conn->max_recv_dlength = max;
- cxgb3i_api_debug("conn 0x%p, max recv %u.\n",
- conn, conn->max_recv_dlength);
- return 0;
-}
-
-/**
- * cxgb3i_conn_create - create iscsi connection instance
- * @cls_session: pointer to iscsi cls session
- * @cid: iscsi cid
- *
- * Creates a new iSCSI connection instance for a given session
- */
-static struct iscsi_cls_conn *cxgb3i_conn_create(struct iscsi_cls_session
- *cls_session, u32 cid)
-{
- struct iscsi_cls_conn *cls_conn;
- struct iscsi_conn *conn;
- struct iscsi_tcp_conn *tcp_conn;
- struct cxgb3i_conn *cconn;
-
- cxgb3i_api_debug("sess 0x%p, cid %u.\n", cls_session, cid);
-
- cls_conn = iscsi_tcp_conn_setup(cls_session, sizeof(*cconn), cid);
- if (!cls_conn)
- return NULL;
- conn = cls_conn->dd_data;
- tcp_conn = conn->dd_data;
- cconn = tcp_conn->dd_data;
-
- cconn->conn = conn;
- return cls_conn;
-}
-
-/**
- * cxgb3i_conn_bind - binds iscsi sess, conn and endpoint together
- * @cls_session: pointer to iscsi cls session
- * @cls_conn: pointer to iscsi cls conn
- * @transport_eph: 64-bit EP handle
- * @is_leading: leading connection on this session?
- *
- * Binds together an iSCSI session, an iSCSI connection and a
- * TCP connection. This routine returns error code if the TCP
- * connection does not belong on the device iSCSI sess/conn is bound
- */
-
-static int cxgb3i_conn_bind(struct iscsi_cls_session *cls_session,
- struct iscsi_cls_conn *cls_conn,
- u64 transport_eph, int is_leading)
-{
- struct iscsi_conn *conn = cls_conn->dd_data;
- struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
- struct cxgb3i_conn *cconn = tcp_conn->dd_data;
- struct cxgb3i_adapter *snic;
- struct iscsi_endpoint *ep;
- struct cxgb3i_endpoint *cep;
- struct s3_conn *c3cn;
- int err;
-
- ep = iscsi_lookup_endpoint(transport_eph);
- if (!ep)
- return -EINVAL;
-
- /* setup ddp pagesize */
- cep = ep->dd_data;
- c3cn = cep->c3cn;
- snic = cep->hba->snic;
- err = cxgb3i_setup_conn_host_pagesize(snic->tdev, c3cn->tid, 0);
- if (err < 0)
- return err;
-
- cxgb3i_api_debug("ep 0x%p, cls sess 0x%p, cls conn 0x%p.\n",
- ep, cls_session, cls_conn);
-
- err = iscsi_conn_bind(cls_session, cls_conn, is_leading);
- if (err)
- return -EINVAL;
-
- /* calculate the tag idx bits needed for this conn based on cmds_max */
- cconn->task_idx_bits = (__ilog2_u32(conn->session->cmds_max - 1)) + 1;
- cxgb3i_api_debug("session cmds_max 0x%x, bits %u.\n",
- conn->session->cmds_max, cconn->task_idx_bits);
-
- read_lock(&c3cn->callback_lock);
- c3cn->user_data = conn;
- cconn->hba = cep->hba;
- cconn->cep = cep;
- cep->cconn = cconn;
- read_unlock(&c3cn->callback_lock);
-
- cxgb3i_conn_max_xmit_dlength(conn);
- cxgb3i_conn_max_recv_dlength(conn);
-
- spin_lock_bh(&conn->session->lock);
- sprintf(conn->portal_address, "%pI4", &c3cn->daddr.sin_addr.s_addr);
- conn->portal_port = ntohs(c3cn->daddr.sin_port);
- spin_unlock_bh(&conn->session->lock);
-
- /* init recv engine */
- iscsi_tcp_hdr_recv_prep(tcp_conn);
-
- return 0;
-}
-
-/**
- * cxgb3i_conn_get_param - return iscsi connection parameter to caller
- * @cls_conn: pointer to iscsi cls conn
- * @param: parameter type identifier
- * @buf: buffer pointer
- *
- * returns iSCSI connection parameters
- */
-static int cxgb3i_conn_get_param(struct iscsi_cls_conn *cls_conn,
- enum iscsi_param param, char *buf)
-{
- struct iscsi_conn *conn = cls_conn->dd_data;
- int len;
-
- cxgb3i_api_debug("cls_conn 0x%p, param %d.\n", cls_conn, param);
-
- switch (param) {
- case ISCSI_PARAM_CONN_PORT:
- spin_lock_bh(&conn->session->lock);
- len = sprintf(buf, "%hu\n", conn->portal_port);
- spin_unlock_bh(&conn->session->lock);
- break;
- case ISCSI_PARAM_CONN_ADDRESS:
- spin_lock_bh(&conn->session->lock);
- len = sprintf(buf, "%s\n", conn->portal_address);
- spin_unlock_bh(&conn->session->lock);
- break;
- default:
- return iscsi_conn_get_param(cls_conn, param, buf);
- }
-
- return len;
-}
-
-/**
- * cxgb3i_conn_set_param - set iscsi connection parameter
- * @cls_conn: pointer to iscsi cls conn
- * @param: parameter type identifier
- * @buf: buffer pointer
- * @buflen: buffer length
- *
- * set iSCSI connection parameters
- */
-static int cxgb3i_conn_set_param(struct iscsi_cls_conn *cls_conn,
- enum iscsi_param param, char *buf, int buflen)
-{
- struct iscsi_conn *conn = cls_conn->dd_data;
- struct iscsi_session *session = conn->session;
- struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
- struct cxgb3i_conn *cconn = tcp_conn->dd_data;
- struct cxgb3i_adapter *snic = cconn->hba->snic;
- struct s3_conn *c3cn = cconn->cep->c3cn;
- int value, err = 0;
-
- switch (param) {
- case ISCSI_PARAM_HDRDGST_EN:
- err = iscsi_set_param(cls_conn, param, buf, buflen);
- if (!err && conn->hdrdgst_en)
- err = cxgb3i_setup_conn_digest(snic->tdev, c3cn->tid,
- conn->hdrdgst_en,
- conn->datadgst_en, 0);
- break;
- case ISCSI_PARAM_DATADGST_EN:
- err = iscsi_set_param(cls_conn, param, buf, buflen);
- if (!err && conn->datadgst_en)
- err = cxgb3i_setup_conn_digest(snic->tdev, c3cn->tid,
- conn->hdrdgst_en,
- conn->datadgst_en, 0);
- break;
- case ISCSI_PARAM_MAX_R2T:
- sscanf(buf, "%d", &value);
- if (value <= 0 || !is_power_of_2(value))
- return -EINVAL;
- if (session->max_r2t == value)
- break;
- iscsi_tcp_r2tpool_free(session);
- err = iscsi_set_param(cls_conn, param, buf, buflen);
- if (!err && iscsi_tcp_r2tpool_alloc(session))
- return -ENOMEM;
- case ISCSI_PARAM_MAX_RECV_DLENGTH:
- err = iscsi_set_param(cls_conn, param, buf, buflen);
- if (!err)
- err = cxgb3i_conn_max_recv_dlength(conn);
- break;
- case ISCSI_PARAM_MAX_XMIT_DLENGTH:
- err = iscsi_set_param(cls_conn, param, buf, buflen);
- if (!err)
- err = cxgb3i_conn_max_xmit_dlength(conn);
- break;
- default:
- return iscsi_set_param(cls_conn, param, buf, buflen);
- }
- return err;
-}
-
-/**
- * cxgb3i_host_set_param - configure host (adapter) related parameters
- * @shost: scsi host pointer
- * @param: parameter type identifier
- * @buf: buffer pointer
- */
-static int cxgb3i_host_set_param(struct Scsi_Host *shost,
- enum iscsi_host_param param,
- char *buf, int buflen)
-{
- struct cxgb3i_hba *hba = iscsi_host_priv(shost);
-
- if (!hba->ndev) {
- shost_printk(KERN_ERR, shost, "Could not set host param. "
- "Netdev for host not set.\n");
- return -ENODEV;
- }
-
- cxgb3i_api_debug("param %d, buf %s.\n", param, buf);
-
- switch (param) {
- case ISCSI_HOST_PARAM_IPADDRESS:
- {
- __be32 addr = in_aton(buf);
- cxgb3i_set_private_ipv4addr(hba->ndev, addr);
- return 0;
- }
- case ISCSI_HOST_PARAM_HWADDRESS:
- case ISCSI_HOST_PARAM_NETDEV_NAME:
- /* ignore */
- return 0;
- default:
- return iscsi_host_set_param(shost, param, buf, buflen);
- }
-}
-
-/**
- * cxgb3i_host_get_param - returns host (adapter) related parameters
- * @shost: scsi host pointer
- * @param: parameter type identifier
- * @buf: buffer pointer
- */
-static int cxgb3i_host_get_param(struct Scsi_Host *shost,
- enum iscsi_host_param param, char *buf)
-{
- struct cxgb3i_hba *hba = iscsi_host_priv(shost);
- int len = 0;
-
- if (!hba->ndev) {
- shost_printk(KERN_ERR, shost, "Could not set host param. "
- "Netdev for host not set.\n");
- return -ENODEV;
- }
-
- cxgb3i_api_debug("hba %s, param %d.\n", hba->ndev->name, param);
-
- switch (param) {
- case ISCSI_HOST_PARAM_HWADDRESS:
- len = sysfs_format_mac(buf, hba->ndev->dev_addr, 6);
- break;
- case ISCSI_HOST_PARAM_NETDEV_NAME:
- len = sprintf(buf, "%s\n", hba->ndev->name);
- break;
- case ISCSI_HOST_PARAM_IPADDRESS:
- {
- __be32 addr;
-
- addr = cxgb3i_get_private_ipv4addr(hba->ndev);
- len = sprintf(buf, "%pI4", &addr);
- break;
- }
- default:
- return iscsi_host_get_param(shost, param, buf);
- }
- return len;
-}
-
-/**
- * cxgb3i_conn_get_stats - returns iSCSI stats
- * @cls_conn: pointer to iscsi cls conn
- * @stats: pointer to iscsi statistic struct
- */
-static void cxgb3i_conn_get_stats(struct iscsi_cls_conn *cls_conn,
- struct iscsi_stats *stats)
-{
- struct iscsi_conn *conn = cls_conn->dd_data;
-
- stats->txdata_octets = conn->txdata_octets;
- stats->rxdata_octets = conn->rxdata_octets;
- stats->scsicmd_pdus = conn->scsicmd_pdus_cnt;
- stats->dataout_pdus = conn->dataout_pdus_cnt;
- stats->scsirsp_pdus = conn->scsirsp_pdus_cnt;
- stats->datain_pdus = conn->datain_pdus_cnt;
- stats->r2t_pdus = conn->r2t_pdus_cnt;
- stats->tmfcmd_pdus = conn->tmfcmd_pdus_cnt;
- stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt;
- stats->digest_err = 0;
- stats->timeout_err = 0;
- stats->custom_length = 1;
- strcpy(stats->custom[0].desc, "eh_abort_cnt");
- stats->custom[0].value = conn->eh_abort_cnt;
-}
-
-/**
- * cxgb3i_parse_itt - get the idx and age bits from a given tag
- * @conn: iscsi connection
- * @itt: itt tag
- * @idx: task index, filled in by this function
- * @age: session age, filled in by this function
- */
-static void cxgb3i_parse_itt(struct iscsi_conn *conn, itt_t itt,
- int *idx, int *age)
-{
- struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
- struct cxgb3i_conn *cconn = tcp_conn->dd_data;
- struct cxgb3i_adapter *snic = cconn->hba->snic;
- u32 tag = ntohl((__force u32) itt);
- u32 sw_bits;
-
- sw_bits = cxgb3i_tag_nonrsvd_bits(&snic->tag_format, tag);
- if (idx)
- *idx = sw_bits & ((1 << cconn->task_idx_bits) - 1);
- if (age)
- *age = (sw_bits >> cconn->task_idx_bits) & ISCSI_AGE_MASK;
-
- cxgb3i_tag_debug("parse tag 0x%x/0x%x, sw 0x%x, itt 0x%x, age 0x%x.\n",
- tag, itt, sw_bits, idx ? *idx : 0xFFFFF,
- age ? *age : 0xFF);
-}
-
-/**
- * cxgb3i_reserve_itt - generate tag for a give task
- * @task: iscsi task
- * @hdr_itt: tag, filled in by this function
- * Set up ddp for scsi read tasks if possible.
- */
-int cxgb3i_reserve_itt(struct iscsi_task *task, itt_t *hdr_itt)
-{
- struct scsi_cmnd *sc = task->sc;
- struct iscsi_conn *conn = task->conn;
- struct iscsi_session *sess = conn->session;
- struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
- struct cxgb3i_conn *cconn = tcp_conn->dd_data;
- struct cxgb3i_adapter *snic = cconn->hba->snic;
- struct cxgb3i_tag_format *tformat = &snic->tag_format;
- u32 sw_tag = (sess->age << cconn->task_idx_bits) | task->itt;
- u32 tag;
- int err = -EINVAL;
-
- if (sc &&
- (scsi_bidi_cmnd(sc) || sc->sc_data_direction == DMA_FROM_DEVICE) &&
- cxgb3i_sw_tag_usable(tformat, sw_tag)) {
- struct s3_conn *c3cn = cconn->cep->c3cn;
- struct cxgb3i_gather_list *gl;
-
- gl = cxgb3i_ddp_make_gl(scsi_in(sc)->length,
- scsi_in(sc)->table.sgl,
- scsi_in(sc)->table.nents,
- snic->pdev,
- GFP_ATOMIC);
- if (gl) {
- tag = sw_tag;
- err = cxgb3i_ddp_tag_reserve(snic->tdev, c3cn->tid,
- tformat, &tag,
- gl, GFP_ATOMIC);
- if (err < 0)
- cxgb3i_ddp_release_gl(gl, snic->pdev);
- }
- }
-
- if (err < 0)
- tag = cxgb3i_set_non_ddp_tag(tformat, sw_tag);
- /* the itt need to sent in big-endian order */
- *hdr_itt = (__force itt_t)htonl(tag);
-
- cxgb3i_tag_debug("new tag 0x%x/0x%x (itt 0x%x, age 0x%x).\n",
- tag, *hdr_itt, task->itt, sess->age);
- return 0;
-}
-
-/**
- * cxgb3i_release_itt - release the tag for a given task
- * @task: iscsi task
- * @hdr_itt: tag
- * If the tag is a ddp tag, release the ddp setup
- */
-void cxgb3i_release_itt(struct iscsi_task *task, itt_t hdr_itt)
-{
- struct scsi_cmnd *sc = task->sc;
- struct iscsi_tcp_conn *tcp_conn = task->conn->dd_data;
- struct cxgb3i_conn *cconn = tcp_conn->dd_data;
- struct cxgb3i_adapter *snic = cconn->hba->snic;
- struct cxgb3i_tag_format *tformat = &snic->tag_format;
- u32 tag = ntohl((__force u32)hdr_itt);
-
- cxgb3i_tag_debug("release tag 0x%x.\n", tag);
-
- if (sc &&
- (scsi_bidi_cmnd(sc) || sc->sc_data_direction == DMA_FROM_DEVICE) &&
- cxgb3i_is_ddp_tag(tformat, tag))
- cxgb3i_ddp_tag_release(snic->tdev, tag);
-}
-
-/**
- * cxgb3i_host_template -- Scsi_Host_Template structure
- * used when registering with the scsi mid layer
- */
-static struct scsi_host_template cxgb3i_host_template = {
- .module = THIS_MODULE,
- .name = "Chelsio S3xx iSCSI Initiator",
- .proc_name = "cxgb3i",
- .queuecommand = iscsi_queuecommand,
- .change_queue_depth = iscsi_change_queue_depth,
- .can_queue = CXGB3I_SCSI_HOST_QDEPTH,
- .sg_tablesize = SG_ALL,
- .max_sectors = 0xFFFF,
- .cmd_per_lun = ISCSI_DEF_CMD_PER_LUN,
- .eh_abort_handler = iscsi_eh_abort,
- .eh_device_reset_handler = iscsi_eh_device_reset,
- .eh_target_reset_handler = iscsi_eh_recover_target,
- .target_alloc = iscsi_target_alloc,
- .use_clustering = DISABLE_CLUSTERING,
- .this_id = -1,
-};
-
-static struct iscsi_transport cxgb3i_iscsi_transport = {
- .owner = THIS_MODULE,
- .name = "cxgb3i",
- .caps = CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST
- | CAP_DATADGST | CAP_DIGEST_OFFLOAD |
- CAP_PADDING_OFFLOAD,
- .param_mask = ISCSI_MAX_RECV_DLENGTH |
- ISCSI_MAX_XMIT_DLENGTH |
- ISCSI_HDRDGST_EN |
- ISCSI_DATADGST_EN |
- ISCSI_INITIAL_R2T_EN |
- ISCSI_MAX_R2T |
- ISCSI_IMM_DATA_EN |
- ISCSI_FIRST_BURST |
- ISCSI_MAX_BURST |
- ISCSI_PDU_INORDER_EN |
- ISCSI_DATASEQ_INORDER_EN |
- ISCSI_ERL |
- ISCSI_CONN_PORT |
- ISCSI_CONN_ADDRESS |
- ISCSI_EXP_STATSN |
- ISCSI_PERSISTENT_PORT |
- ISCSI_PERSISTENT_ADDRESS |
- ISCSI_TARGET_NAME | ISCSI_TPGT |
- ISCSI_USERNAME | ISCSI_PASSWORD |
- ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
- ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
- ISCSI_LU_RESET_TMO | ISCSI_TGT_RESET_TMO |
- ISCSI_PING_TMO | ISCSI_RECV_TMO |
- ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
- .host_param_mask = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
- ISCSI_HOST_INITIATOR_NAME | ISCSI_HOST_NETDEV_NAME,
- .get_host_param = cxgb3i_host_get_param,
- .set_host_param = cxgb3i_host_set_param,
- /* session management */
- .create_session = cxgb3i_session_create,
- .destroy_session = cxgb3i_session_destroy,
- .get_session_param = iscsi_session_get_param,
- /* connection management */
- .create_conn = cxgb3i_conn_create,
- .bind_conn = cxgb3i_conn_bind,
- .destroy_conn = iscsi_tcp_conn_teardown,
- .start_conn = iscsi_conn_start,
- .stop_conn = iscsi_conn_stop,
- .get_conn_param = cxgb3i_conn_get_param,
- .set_param = cxgb3i_conn_set_param,
- .get_stats = cxgb3i_conn_get_stats,
- /* pdu xmit req. from user space */
- .send_pdu = iscsi_conn_send_pdu,
- /* task */
- .init_task = iscsi_tcp_task_init,
- .xmit_task = iscsi_tcp_task_xmit,
- .cleanup_task = cxgb3i_conn_cleanup_task,
-
- /* pdu */
- .alloc_pdu = cxgb3i_conn_alloc_pdu,
- .init_pdu = cxgb3i_conn_init_pdu,
- .xmit_pdu = cxgb3i_conn_xmit_pdu,
- .parse_pdu_itt = cxgb3i_parse_itt,
-
- /* TCP connect/disconnect */
- .ep_connect = cxgb3i_ep_connect,
- .ep_poll = cxgb3i_ep_poll,
- .ep_disconnect = cxgb3i_ep_disconnect,
- /* Error recovery timeout call */
- .session_recovery_timedout = iscsi_session_recovery_timedout,
-};
-
-int cxgb3i_iscsi_init(void)
-{
- sw_tag_idx_bits = (__ilog2_u32(ISCSI_ITT_MASK)) + 1;
- sw_tag_age_bits = (__ilog2_u32(ISCSI_AGE_MASK)) + 1;
- cxgb3i_log_info("tag itt 0x%x, %u bits, age 0x%x, %u bits.\n",
- ISCSI_ITT_MASK, sw_tag_idx_bits,
- ISCSI_AGE_MASK, sw_tag_age_bits);
-
- cxgb3i_scsi_transport =
- iscsi_register_transport(&cxgb3i_iscsi_transport);
- if (!cxgb3i_scsi_transport) {
- cxgb3i_log_error("Could not register cxgb3i transport.\n");
- return -ENODEV;
- }
- cxgb3i_api_debug("cxgb3i transport 0x%p.\n", cxgb3i_scsi_transport);
- return 0;
-}
-
-void cxgb3i_iscsi_cleanup(void)
-{
- if (cxgb3i_scsi_transport) {
- cxgb3i_api_debug("cxgb3i transport 0x%p.\n",
- cxgb3i_scsi_transport);
- iscsi_unregister_transport(&cxgb3i_iscsi_transport);
- }
-}
diff --git a/drivers/scsi/cxgb3i/cxgb3i_offload.c b/drivers/scsi/cxgb3i/cxgb3i_offload.c
deleted file mode 100644
index 3ee13cf9556b..000000000000
--- a/drivers/scsi/cxgb3i/cxgb3i_offload.c
+++ /dev/null
@@ -1,1944 +0,0 @@
-/*
- * cxgb3i_offload.c: Chelsio S3xx iscsi offloaded tcp connection management
- *
- * Copyright (C) 2003-2008 Chelsio Communications. All rights reserved.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the LICENSE file included in this
- * release for licensing terms and conditions.
- *
- * Written by: Dimitris Michailidis (dm@chelsio.com)
- * Karen Xie (kxie@chelsio.com)
- */
-
-#include <linux/if_vlan.h>
-#include <linux/slab.h>
-#include <linux/version.h>
-
-#include "cxgb3_defs.h"
-#include "cxgb3_ctl_defs.h"
-#include "firmware_exports.h"
-#include "cxgb3i_offload.h"
-#include "cxgb3i_pdu.h"
-#include "cxgb3i_ddp.h"
-
-#ifdef __DEBUG_C3CN_CONN__
-#define c3cn_conn_debug cxgb3i_log_debug
-#else
-#define c3cn_conn_debug(fmt...)
-#endif
-
-#ifdef __DEBUG_C3CN_TX__
-#define c3cn_tx_debug cxgb3i_log_debug
-#else
-#define c3cn_tx_debug(fmt...)
-#endif
-
-#ifdef __DEBUG_C3CN_RX__
-#define c3cn_rx_debug cxgb3i_log_debug
-#else
-#define c3cn_rx_debug(fmt...)
-#endif
-
-/*
- * module parameters releated to offloaded iscsi connection
- */
-static int cxgb3_rcv_win = 256 * 1024;
-module_param(cxgb3_rcv_win, int, 0644);
-MODULE_PARM_DESC(cxgb3_rcv_win, "TCP receive window in bytes (default=256KB)");
-
-static int cxgb3_snd_win = 128 * 1024;
-module_param(cxgb3_snd_win, int, 0644);
-MODULE_PARM_DESC(cxgb3_snd_win, "TCP send window in bytes (default=128KB)");
-
-static int cxgb3_rx_credit_thres = 10 * 1024;
-module_param(cxgb3_rx_credit_thres, int, 0644);
-MODULE_PARM_DESC(rx_credit_thres,
- "RX credits return threshold in bytes (default=10KB)");
-
-static unsigned int cxgb3_max_connect = 8 * 1024;
-module_param(cxgb3_max_connect, uint, 0644);
-MODULE_PARM_DESC(cxgb3_max_connect, "Max. # of connections (default=8092)");
-
-static unsigned int cxgb3_sport_base = 20000;
-module_param(cxgb3_sport_base, uint, 0644);
-MODULE_PARM_DESC(cxgb3_sport_base, "starting port number (default=20000)");
-
-/*
- * cxgb3i tcp connection data(per adapter) list
- */
-static LIST_HEAD(cdata_list);
-static DEFINE_RWLOCK(cdata_rwlock);
-
-static int c3cn_push_tx_frames(struct s3_conn *c3cn, int req_completion);
-static void c3cn_release_offload_resources(struct s3_conn *c3cn);
-
-/*
- * iscsi source port management
- *
- * Find a free source port in the port allocation map. We use a very simple
- * rotor scheme to look for the next free port.
- *
- * If a source port has been specified make sure that it doesn't collide with
- * our normal source port allocation map. If it's outside the range of our
- * allocation/deallocation scheme just let them use it.
- *
- * If the source port is outside our allocation range, the caller is
- * responsible for keeping track of their port usage.
- */
-static int c3cn_get_port(struct s3_conn *c3cn, struct cxgb3i_sdev_data *cdata)
-{
- unsigned int start;
- int idx;
-
- if (!cdata)
- goto error_out;
-
- if (c3cn->saddr.sin_port) {
- cxgb3i_log_error("connect, sin_port NON-ZERO %u.\n",
- c3cn->saddr.sin_port);
- return -EADDRINUSE;
- }
-
- spin_lock_bh(&cdata->lock);
- start = idx = cdata->sport_next;
- do {
- if (++idx >= cxgb3_max_connect)
- idx = 0;
- if (!cdata->sport_conn[idx]) {
- c3cn->saddr.sin_port = htons(cxgb3_sport_base + idx);
- cdata->sport_next = idx;
- cdata->sport_conn[idx] = c3cn;
- spin_unlock_bh(&cdata->lock);
-
- c3cn_conn_debug("%s reserve port %u.\n",
- cdata->cdev->name,
- cxgb3_sport_base + idx);
- return 0;
- }
- } while (idx != start);
- spin_unlock_bh(&cdata->lock);
-
-error_out:
- return -EADDRNOTAVAIL;
-}
-
-static void c3cn_put_port(struct s3_conn *c3cn)
-{
- if (!c3cn->cdev)
- return;
-
- if (c3cn->saddr.sin_port) {
- struct cxgb3i_sdev_data *cdata = CXGB3_SDEV_DATA(c3cn->cdev);
- int idx = ntohs(c3cn->saddr.sin_port) - cxgb3_sport_base;
-
- c3cn->saddr.sin_port = 0;
- if (idx < 0 || idx >= cxgb3_max_connect)
- return;
- spin_lock_bh(&cdata->lock);
- cdata->sport_conn[idx] = NULL;
- spin_unlock_bh(&cdata->lock);
- c3cn_conn_debug("%s, release port %u.\n",
- cdata->cdev->name, cxgb3_sport_base + idx);
- }
-}
-
-static inline void c3cn_set_flag(struct s3_conn *c3cn, enum c3cn_flags flag)
-{
- __set_bit(flag, &c3cn->flags);
- c3cn_conn_debug("c3cn 0x%p, set %d, s %u, f 0x%lx.\n",
- c3cn, flag, c3cn->state, c3cn->flags);
-}
-
-static inline void c3cn_clear_flag(struct s3_conn *c3cn, enum c3cn_flags flag)
-{
- __clear_bit(flag, &c3cn->flags);
- c3cn_conn_debug("c3cn 0x%p, clear %d, s %u, f 0x%lx.\n",
- c3cn, flag, c3cn->state, c3cn->flags);
-}
-
-static inline int c3cn_flag(struct s3_conn *c3cn, enum c3cn_flags flag)
-{
- if (c3cn == NULL)
- return 0;
- return test_bit(flag, &c3cn->flags);
-}
-
-static void c3cn_set_state(struct s3_conn *c3cn, int state)
-{
- c3cn_conn_debug("c3cn 0x%p state -> %u.\n", c3cn, state);
- c3cn->state = state;
-}
-
-static inline void c3cn_hold(struct s3_conn *c3cn)
-{
- atomic_inc(&c3cn->refcnt);
-}
-
-static inline void c3cn_put(struct s3_conn *c3cn)
-{
- if (atomic_dec_and_test(&c3cn->refcnt)) {
- c3cn_conn_debug("free c3cn 0x%p, s %u, f 0x%lx.\n",
- c3cn, c3cn->state, c3cn->flags);
- kfree(c3cn);
- }
-}
-
-static void c3cn_closed(struct s3_conn *c3cn)
-{
- c3cn_conn_debug("c3cn 0x%p, state %u, flag 0x%lx.\n",
- c3cn, c3cn->state, c3cn->flags);
-
- c3cn_put_port(c3cn);
- c3cn_release_offload_resources(c3cn);
- c3cn_set_state(c3cn, C3CN_STATE_CLOSED);
- cxgb3i_conn_closing(c3cn);
-}
-
-/*
- * CPL (Chelsio Protocol Language) defines a message passing interface between
- * the host driver and T3 asic.
- * The section below implments CPLs that related to iscsi tcp connection
- * open/close/abort and data send/receive.
- */
-
-/*
- * CPL connection active open request: host ->
- */
-static unsigned int find_best_mtu(const struct t3c_data *d, unsigned short mtu)
-{
- int i = 0;
-
- while (i < d->nmtus - 1 && d->mtus[i + 1] <= mtu)
- ++i;
- return i;
-}
-
-static unsigned int select_mss(struct s3_conn *c3cn, unsigned int pmtu)
-{
- unsigned int idx;
- struct dst_entry *dst = c3cn->dst_cache;
- struct t3cdev *cdev = c3cn->cdev;
- const struct t3c_data *td = T3C_DATA(cdev);
- u16 advmss = dst_metric(dst, RTAX_ADVMSS);
-
- if (advmss > pmtu - 40)
- advmss = pmtu - 40;
- if (advmss < td->mtus[0] - 40)
- advmss = td->mtus[0] - 40;
- idx = find_best_mtu(td, advmss + 40);
- return idx;
-}
-
-static inline int compute_wscale(int win)
-{
- int wscale = 0;
- while (wscale < 14 && (65535<<wscale) < win)
- wscale++;
- return wscale;
-}
-
-static inline unsigned int calc_opt0h(struct s3_conn *c3cn)
-{
- int wscale = compute_wscale(cxgb3_rcv_win);
- return V_KEEP_ALIVE(1) |
- F_TCAM_BYPASS |
- V_WND_SCALE(wscale) |
- V_MSS_IDX(c3cn->mss_idx);
-}
-
-static inline unsigned int calc_opt0l(struct s3_conn *c3cn)
-{
- return V_ULP_MODE(ULP_MODE_ISCSI) |
- V_RCV_BUFSIZ(cxgb3_rcv_win>>10);
-}
-
-static void make_act_open_req(struct s3_conn *c3cn, struct sk_buff *skb,
- unsigned int atid, const struct l2t_entry *e)
-{
- struct cpl_act_open_req *req;
-
- c3cn_conn_debug("c3cn 0x%p, atid 0x%x.\n", c3cn, atid);
-
- skb->priority = CPL_PRIORITY_SETUP;
- req = (struct cpl_act_open_req *)__skb_put(skb, sizeof(*req));
- req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
- req->wr.wr_lo = 0;
- OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_ACT_OPEN_REQ, atid));
- req->local_port = c3cn->saddr.sin_port;
- req->peer_port = c3cn->daddr.sin_port;
- req->local_ip = c3cn->saddr.sin_addr.s_addr;
- req->peer_ip = c3cn->daddr.sin_addr.s_addr;
- req->opt0h = htonl(calc_opt0h(c3cn) | V_L2T_IDX(e->idx) |
- V_TX_CHANNEL(e->smt_idx));
- req->opt0l = htonl(calc_opt0l(c3cn));
- req->params = 0;
- req->opt2 = 0;
-}
-
-static void fail_act_open(struct s3_conn *c3cn, int errno)
-{
- c3cn_conn_debug("c3cn 0x%p, state %u, flag 0x%lx.\n",
- c3cn, c3cn->state, c3cn->flags);
- c3cn->err = errno;
- c3cn_closed(c3cn);
-}
-
-static void act_open_req_arp_failure(struct t3cdev *dev, struct sk_buff *skb)
-{
- struct s3_conn *c3cn = (struct s3_conn *)skb->sk;
-
- c3cn_conn_debug("c3cn 0x%p, state %u.\n", c3cn, c3cn->state);
-
- c3cn_hold(c3cn);
- spin_lock_bh(&c3cn->lock);
- if (c3cn->state == C3CN_STATE_CONNECTING)
- fail_act_open(c3cn, -EHOSTUNREACH);
- spin_unlock_bh(&c3cn->lock);
- c3cn_put(c3cn);
- __kfree_skb(skb);
-}
-
-/*
- * CPL connection close request: host ->
- *
- * Close a connection by sending a CPL_CLOSE_CON_REQ message and queue it to
- * the write queue (i.e., after any unsent txt data).
- */
-static void skb_entail(struct s3_conn *c3cn, struct sk_buff *skb,
- int flags)
-{
- skb_tcp_seq(skb) = c3cn->write_seq;
- skb_flags(skb) = flags;
- __skb_queue_tail(&c3cn->write_queue, skb);
-}
-
-static void send_close_req(struct s3_conn *c3cn)
-{
- struct sk_buff *skb = c3cn->cpl_close;
- struct cpl_close_con_req *req = (struct cpl_close_con_req *)skb->head;
- unsigned int tid = c3cn->tid;
-
- c3cn_conn_debug("c3cn 0x%p, state 0x%x, flag 0x%lx.\n",
- c3cn, c3cn->state, c3cn->flags);
-
- c3cn->cpl_close = NULL;
-
- req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_CLOSE_CON));
- req->wr.wr_lo = htonl(V_WR_TID(tid));
- OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_CLOSE_CON_REQ, tid));
- req->rsvd = htonl(c3cn->write_seq);
-
- skb_entail(c3cn, skb, C3CB_FLAG_NO_APPEND);
- if (c3cn->state != C3CN_STATE_CONNECTING)
- c3cn_push_tx_frames(c3cn, 1);
-}
-
-/*
- * CPL connection abort request: host ->
- *
- * Send an ABORT_REQ message. Makes sure we do not send multiple ABORT_REQs
- * for the same connection and also that we do not try to send a message
- * after the connection has closed.
- */
-static void abort_arp_failure(struct t3cdev *cdev, struct sk_buff *skb)
-{
- struct cpl_abort_req *req = cplhdr(skb);
-
- c3cn_conn_debug("tdev 0x%p.\n", cdev);
-
- req->cmd = CPL_ABORT_NO_RST;
- cxgb3_ofld_send(cdev, skb);
-}
-
-static inline void c3cn_purge_write_queue(struct s3_conn *c3cn)
-{
- struct sk_buff *skb;
-
- while ((skb = __skb_dequeue(&c3cn->write_queue)))
- __kfree_skb(skb);
-}
-
-static void send_abort_req(struct s3_conn *c3cn)
-{
- struct sk_buff *skb = c3cn->cpl_abort_req;
- struct cpl_abort_req *req;
- unsigned int tid = c3cn->tid;
-
- if (unlikely(c3cn->state == C3CN_STATE_ABORTING) || !skb ||
- !c3cn->cdev)
- return;
-
- c3cn_set_state(c3cn, C3CN_STATE_ABORTING);
-
- c3cn_conn_debug("c3cn 0x%p, flag ABORT_RPL + ABORT_SHUT.\n", c3cn);
-
- c3cn_set_flag(c3cn, C3CN_ABORT_RPL_PENDING);
-
- /* Purge the send queue so we don't send anything after an abort. */
- c3cn_purge_write_queue(c3cn);
-
- c3cn->cpl_abort_req = NULL;
- req = (struct cpl_abort_req *)skb->head;
- memset(req, 0, sizeof(*req));
-
- skb->priority = CPL_PRIORITY_DATA;
- set_arp_failure_handler(skb, abort_arp_failure);
-
- req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_HOST_ABORT_CON_REQ));
- req->wr.wr_lo = htonl(V_WR_TID(tid));
- OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_ABORT_REQ, tid));
- req->rsvd0 = htonl(c3cn->snd_nxt);
- req->rsvd1 = !c3cn_flag(c3cn, C3CN_TX_DATA_SENT);
- req->cmd = CPL_ABORT_SEND_RST;
-
- l2t_send(c3cn->cdev, skb, c3cn->l2t);
-}
-
-/*
- * CPL connection abort reply: host ->
- *
- * Send an ABORT_RPL message in response of the ABORT_REQ received.
- */
-static void send_abort_rpl(struct s3_conn *c3cn, int rst_status)
-{
- struct sk_buff *skb = c3cn->cpl_abort_rpl;
- struct cpl_abort_rpl *rpl = (struct cpl_abort_rpl *)skb->head;
-
- c3cn->cpl_abort_rpl = NULL;
-
- skb->priority = CPL_PRIORITY_DATA;
- memset(rpl, 0, sizeof(*rpl));
- rpl->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_HOST_ABORT_CON_RPL));
- rpl->wr.wr_lo = htonl(V_WR_TID(c3cn->tid));
- OPCODE_TID(rpl) = htonl(MK_OPCODE_TID(CPL_ABORT_RPL, c3cn->tid));
- rpl->cmd = rst_status;
-
- cxgb3_ofld_send(c3cn->cdev, skb);
-}
-
-/*
- * CPL connection rx data ack: host ->
- * Send RX credits through an RX_DATA_ACK CPL message. Returns the number of
- * credits sent.
- */
-static u32 send_rx_credits(struct s3_conn *c3cn, u32 credits, u32 dack)
-{
- struct sk_buff *skb;
- struct cpl_rx_data_ack *req;
-
- skb = alloc_skb(sizeof(*req), GFP_ATOMIC);
- if (!skb)
- return 0;
-
- req = (struct cpl_rx_data_ack *)__skb_put(skb, sizeof(*req));
- req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
- req->wr.wr_lo = 0;
- OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_RX_DATA_ACK, c3cn->tid));
- req->credit_dack = htonl(dack | V_RX_CREDITS(credits));
- skb->priority = CPL_PRIORITY_ACK;
- cxgb3_ofld_send(c3cn->cdev, skb);
- return credits;
-}
-
-/*
- * CPL connection tx data: host ->
- *
- * Send iscsi PDU via TX_DATA CPL message. Returns the number of
- * credits sent.
- * Each TX_DATA consumes work request credit (wrs), so we need to keep track of
- * how many we've used so far and how many are pending (i.e., yet ack'ed by T3).
- */
-
-/*
- * For ULP connections HW may inserts digest bytes into the pdu. Those digest
- * bytes are not sent by the host but are part of the TCP payload and therefore
- * consume TCP sequence space.
- */
-static const unsigned int cxgb3_ulp_extra_len[] = { 0, 4, 4, 8 };
-static inline unsigned int ulp_extra_len(const struct sk_buff *skb)
-{
- return cxgb3_ulp_extra_len[skb_ulp_mode(skb) & 3];
-}
-
-static unsigned int wrlen __read_mostly;
-
-/*
- * The number of WRs needed for an skb depends on the number of fragments
- * in the skb and whether it has any payload in its main body. This maps the
- * length of the gather list represented by an skb into the # of necessary WRs.
- * The extra two fragments are for iscsi bhs and payload padding.
- */
-#define SKB_WR_LIST_SIZE (MAX_SKB_FRAGS + 2)
-static unsigned int skb_wrs[SKB_WR_LIST_SIZE] __read_mostly;
-
-static void s3_init_wr_tab(unsigned int wr_len)
-{
- int i;
-
- if (skb_wrs[1]) /* already initialized */
- return;
-
- for (i = 1; i < SKB_WR_LIST_SIZE; i++) {
- int sgl_len = (3 * i) / 2 + (i & 1);
-
- sgl_len += 3;
- skb_wrs[i] = (sgl_len <= wr_len
- ? 1 : 1 + (sgl_len - 2) / (wr_len - 1));
- }
-
- wrlen = wr_len * 8;
-}
-
-static inline void reset_wr_list(struct s3_conn *c3cn)
-{
- c3cn->wr_pending_head = c3cn->wr_pending_tail = NULL;
-}
-
-/*
- * Add a WR to a connections's list of pending WRs. This is a singly-linked
- * list of sk_buffs operating as a FIFO. The head is kept in wr_pending_head
- * and the tail in wr_pending_tail.
- */
-static inline void enqueue_wr(struct s3_conn *c3cn,
- struct sk_buff *skb)
-{
- skb_tx_wr_next(skb) = NULL;
-
- /*
- * We want to take an extra reference since both us and the driver
- * need to free the packet before it's really freed. We know there's
- * just one user currently so we use atomic_set rather than skb_get
- * to avoid the atomic op.
- */
- atomic_set(&skb->users, 2);
-
- if (!c3cn->wr_pending_head)
- c3cn->wr_pending_head = skb;
- else
- skb_tx_wr_next(c3cn->wr_pending_tail) = skb;
- c3cn->wr_pending_tail = skb;
-}
-
-static int count_pending_wrs(struct s3_conn *c3cn)
-{
- int n = 0;
- const struct sk_buff *skb = c3cn->wr_pending_head;
-
- while (skb) {
- n += skb->csum;
- skb = skb_tx_wr_next(skb);
- }
- return n;
-}
-
-static inline struct sk_buff *peek_wr(const struct s3_conn *c3cn)
-{
- return c3cn->wr_pending_head;
-}
-
-static inline void free_wr_skb(struct sk_buff *skb)
-{
- kfree_skb(skb);
-}
-
-static inline struct sk_buff *dequeue_wr(struct s3_conn *c3cn)
-{
- struct sk_buff *skb = c3cn->wr_pending_head;
-
- if (likely(skb)) {
- /* Don't bother clearing the tail */
- c3cn->wr_pending_head = skb_tx_wr_next(skb);
- skb_tx_wr_next(skb) = NULL;
- }
- return skb;
-}
-
-static void purge_wr_queue(struct s3_conn *c3cn)
-{
- struct sk_buff *skb;
- while ((skb = dequeue_wr(c3cn)) != NULL)
- free_wr_skb(skb);
-}
-
-static inline void make_tx_data_wr(struct s3_conn *c3cn, struct sk_buff *skb,
- int len, int req_completion)
-{
- struct tx_data_wr *req;
-
- skb_reset_transport_header(skb);
- req = (struct tx_data_wr *)__skb_push(skb, sizeof(*req));
- req->wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_TX_DATA) |
- (req_completion ? F_WR_COMPL : 0));
- req->wr_lo = htonl(V_WR_TID(c3cn->tid));
- req->sndseq = htonl(c3cn->snd_nxt);
- /* len includes the length of any HW ULP additions */
- req->len = htonl(len);
- req->param = htonl(V_TX_PORT(c3cn->l2t->smt_idx));
- /* V_TX_ULP_SUBMODE sets both the mode and submode */
- req->flags = htonl(V_TX_ULP_SUBMODE(skb_ulp_mode(skb)) |
- V_TX_SHOVE((skb_peek(&c3cn->write_queue) ? 0 : 1)));
-
- if (!c3cn_flag(c3cn, C3CN_TX_DATA_SENT)) {
- req->flags |= htonl(V_TX_ACK_PAGES(2) | F_TX_INIT |
- V_TX_CPU_IDX(c3cn->qset));
- /* Sendbuffer is in units of 32KB. */
- req->param |= htonl(V_TX_SNDBUF(cxgb3_snd_win >> 15));
- c3cn_set_flag(c3cn, C3CN_TX_DATA_SENT);
- }
-}
-
-/**
- * c3cn_push_tx_frames -- start transmit
- * @c3cn: the offloaded connection
- * @req_completion: request wr_ack or not
- *
- * Prepends TX_DATA_WR or CPL_CLOSE_CON_REQ headers to buffers waiting in a
- * connection's send queue and sends them on to T3. Must be called with the
- * connection's lock held. Returns the amount of send buffer space that was
- * freed as a result of sending queued data to T3.
- */
-static void arp_failure_discard(struct t3cdev *cdev, struct sk_buff *skb)
-{
- kfree_skb(skb);
-}
-
-static int c3cn_push_tx_frames(struct s3_conn *c3cn, int req_completion)
-{
- int total_size = 0;
- struct sk_buff *skb;
- struct t3cdev *cdev;
- struct cxgb3i_sdev_data *cdata;
-
- if (unlikely(c3cn->state == C3CN_STATE_CONNECTING ||
- c3cn->state == C3CN_STATE_CLOSE_WAIT_1 ||
- c3cn->state >= C3CN_STATE_ABORTING)) {
- c3cn_tx_debug("c3cn 0x%p, in closing state %u.\n",
- c3cn, c3cn->state);
- return 0;
- }
-
- cdev = c3cn->cdev;
- cdata = CXGB3_SDEV_DATA(cdev);
-
- while (c3cn->wr_avail
- && (skb = skb_peek(&c3cn->write_queue)) != NULL) {
- int len = skb->len; /* length before skb_push */
- int frags = skb_shinfo(skb)->nr_frags + (len != skb->data_len);
- int wrs_needed = skb_wrs[frags];
-
- if (wrs_needed > 1 && len + sizeof(struct tx_data_wr) <= wrlen)
- wrs_needed = 1;
-
- WARN_ON(frags >= SKB_WR_LIST_SIZE || wrs_needed < 1);
-
- if (c3cn->wr_avail < wrs_needed) {
- c3cn_tx_debug("c3cn 0x%p, skb len %u/%u, frag %u, "
- "wr %d < %u.\n",
- c3cn, skb->len, skb->data_len, frags,
- wrs_needed, c3cn->wr_avail);
- break;
- }
-
- __skb_unlink(skb, &c3cn->write_queue);
- skb->priority = CPL_PRIORITY_DATA;
- skb->csum = wrs_needed; /* remember this until the WR_ACK */
- c3cn->wr_avail -= wrs_needed;
- c3cn->wr_unacked += wrs_needed;
- enqueue_wr(c3cn, skb);
-
- c3cn_tx_debug("c3cn 0x%p, enqueue, skb len %u/%u, frag %u, "
- "wr %d, left %u, unack %u.\n",
- c3cn, skb->len, skb->data_len, frags,
- wrs_needed, c3cn->wr_avail, c3cn->wr_unacked);
-
-
- if (likely(skb_flags(skb) & C3CB_FLAG_NEED_HDR)) {
- if ((req_completion &&
- c3cn->wr_unacked == wrs_needed) ||
- (skb_flags(skb) & C3CB_FLAG_COMPL) ||
- c3cn->wr_unacked >= c3cn->wr_max / 2) {
- req_completion = 1;
- c3cn->wr_unacked = 0;
- }
- len += ulp_extra_len(skb);
- make_tx_data_wr(c3cn, skb, len, req_completion);
- c3cn->snd_nxt += len;
- skb_flags(skb) &= ~C3CB_FLAG_NEED_HDR;
- }
-
- total_size += skb->truesize;
- set_arp_failure_handler(skb, arp_failure_discard);
- l2t_send(cdev, skb, c3cn->l2t);
- }
- return total_size;
-}
-
-/*
- * process_cpl_msg: -> host
- * Top-level CPL message processing used by most CPL messages that
- * pertain to connections.
- */
-static inline void process_cpl_msg(void (*fn)(struct s3_conn *,
- struct sk_buff *),
- struct s3_conn *c3cn,
- struct sk_buff *skb)
-{
- spin_lock_bh(&c3cn->lock);
- fn(c3cn, skb);
- spin_unlock_bh(&c3cn->lock);
-}
-
-/*
- * process_cpl_msg_ref: -> host
- * Similar to process_cpl_msg() but takes an extra connection reference around
- * the call to the handler. Should be used if the handler may drop a
- * connection reference.
- */
-static inline void process_cpl_msg_ref(void (*fn) (struct s3_conn *,
- struct sk_buff *),
- struct s3_conn *c3cn,
- struct sk_buff *skb)
-{
- c3cn_hold(c3cn);
- process_cpl_msg(fn, c3cn, skb);
- c3cn_put(c3cn);
-}
-
-/*
- * Process a CPL_ACT_ESTABLISH message: -> host
- * Updates connection state from an active establish CPL message. Runs with
- * the connection lock held.
- */
-
-static inline void s3_free_atid(struct t3cdev *cdev, unsigned int tid)
-{
- struct s3_conn *c3cn = cxgb3_free_atid(cdev, tid);
- if (c3cn)
- c3cn_put(c3cn);
-}
-
-static void c3cn_established(struct s3_conn *c3cn, u32 snd_isn,
- unsigned int opt)
-{
- c3cn_conn_debug("c3cn 0x%p, state %u.\n", c3cn, c3cn->state);
-
- c3cn->write_seq = c3cn->snd_nxt = c3cn->snd_una = snd_isn;
-
- /*
- * Causes the first RX_DATA_ACK to supply any Rx credits we couldn't
- * pass through opt0.
- */
- if (cxgb3_rcv_win > (M_RCV_BUFSIZ << 10))
- c3cn->rcv_wup -= cxgb3_rcv_win - (M_RCV_BUFSIZ << 10);
-
- dst_confirm(c3cn->dst_cache);
-
- smp_mb();
-
- c3cn_set_state(c3cn, C3CN_STATE_ESTABLISHED);
-}
-
-static void process_act_establish(struct s3_conn *c3cn, struct sk_buff *skb)
-{
- struct cpl_act_establish *req = cplhdr(skb);
- u32 rcv_isn = ntohl(req->rcv_isn); /* real RCV_ISN + 1 */
-
- c3cn_conn_debug("c3cn 0x%p, state %u, flag 0x%lx.\n",
- c3cn, c3cn->state, c3cn->flags);
-
- if (unlikely(c3cn->state != C3CN_STATE_CONNECTING))
- cxgb3i_log_error("TID %u expected SYN_SENT, got EST., s %u\n",
- c3cn->tid, c3cn->state);
-
- c3cn->copied_seq = c3cn->rcv_wup = c3cn->rcv_nxt = rcv_isn;
- c3cn_established(c3cn, ntohl(req->snd_isn), ntohs(req->tcp_opt));
-
- __kfree_skb(skb);
-
- if (unlikely(c3cn_flag(c3cn, C3CN_ACTIVE_CLOSE_NEEDED)))
- /* upper layer has requested closing */
- send_abort_req(c3cn);
- else {
- if (skb_queue_len(&c3cn->write_queue))
- c3cn_push_tx_frames(c3cn, 1);
- cxgb3i_conn_tx_open(c3cn);
- }
-}
-
-static int do_act_establish(struct t3cdev *cdev, struct sk_buff *skb,
- void *ctx)
-{
- struct cpl_act_establish *req = cplhdr(skb);
- unsigned int tid = GET_TID(req);
- unsigned int atid = G_PASS_OPEN_TID(ntohl(req->tos_tid));
- struct s3_conn *c3cn = ctx;
- struct cxgb3i_sdev_data *cdata = CXGB3_SDEV_DATA(cdev);
-
- c3cn_conn_debug("rcv, tid 0x%x, c3cn 0x%p, s %u, f 0x%lx.\n",
- tid, c3cn, c3cn->state, c3cn->flags);
-
- c3cn->tid = tid;
- c3cn_hold(c3cn);
- cxgb3_insert_tid(cdata->cdev, cdata->client, c3cn, tid);
- s3_free_atid(cdev, atid);
-
- c3cn->qset = G_QNUM(ntohl(skb->csum));
-
- process_cpl_msg(process_act_establish, c3cn, skb);
- return 0;
-}
-
-/*
- * Process a CPL_ACT_OPEN_RPL message: -> host
- * Handle active open failures.
- */
-static int act_open_rpl_status_to_errno(int status)
-{
- switch (status) {
- case CPL_ERR_CONN_RESET:
- return -ECONNREFUSED;
- case CPL_ERR_ARP_MISS:
- return -EHOSTUNREACH;
- case CPL_ERR_CONN_TIMEDOUT:
- return -ETIMEDOUT;
- case CPL_ERR_TCAM_FULL:
- return -ENOMEM;
- case CPL_ERR_CONN_EXIST:
- cxgb3i_log_error("ACTIVE_OPEN_RPL: 4-tuple in use\n");
- return -EADDRINUSE;
- default:
- return -EIO;
- }
-}
-
-static void act_open_retry_timer(unsigned long data)
-{
- struct sk_buff *skb;
- struct s3_conn *c3cn = (struct s3_conn *)data;
-
- c3cn_conn_debug("c3cn 0x%p, state %u.\n", c3cn, c3cn->state);
-
- spin_lock_bh(&c3cn->lock);
- skb = alloc_skb(sizeof(struct cpl_act_open_req), GFP_ATOMIC);
- if (!skb)
- fail_act_open(c3cn, -ENOMEM);
- else {
- skb->sk = (struct sock *)c3cn;
- set_arp_failure_handler(skb, act_open_req_arp_failure);
- make_act_open_req(c3cn, skb, c3cn->tid, c3cn->l2t);
- l2t_send(c3cn->cdev, skb, c3cn->l2t);
- }
- spin_unlock_bh(&c3cn->lock);
- c3cn_put(c3cn);
-}
-
-static void process_act_open_rpl(struct s3_conn *c3cn, struct sk_buff *skb)
-{
- struct cpl_act_open_rpl *rpl = cplhdr(skb);
-
- c3cn_conn_debug("c3cn 0x%p, state %u, flag 0x%lx.\n",
- c3cn, c3cn->state, c3cn->flags);
-
- if (rpl->status == CPL_ERR_CONN_EXIST &&
- c3cn->retry_timer.function != act_open_retry_timer) {
- c3cn->retry_timer.function = act_open_retry_timer;
- if (!mod_timer(&c3cn->retry_timer, jiffies + HZ / 2))
- c3cn_hold(c3cn);
- } else
- fail_act_open(c3cn, act_open_rpl_status_to_errno(rpl->status));
- __kfree_skb(skb);
-}
-
-static int do_act_open_rpl(struct t3cdev *cdev, struct sk_buff *skb, void *ctx)
-{
- struct s3_conn *c3cn = ctx;
- struct cpl_act_open_rpl *rpl = cplhdr(skb);
-
- c3cn_conn_debug("rcv, status 0x%x, c3cn 0x%p, s %u, f 0x%lx.\n",
- rpl->status, c3cn, c3cn->state, c3cn->flags);
-
- if (rpl->status != CPL_ERR_TCAM_FULL &&
- rpl->status != CPL_ERR_CONN_EXIST &&
- rpl->status != CPL_ERR_ARP_MISS)
- cxgb3_queue_tid_release(cdev, GET_TID(rpl));
-
- process_cpl_msg_ref(process_act_open_rpl, c3cn, skb);
- return 0;
-}
-
-/*
- * Process PEER_CLOSE CPL messages: -> host
- * Handle peer FIN.
- */
-static void process_peer_close(struct s3_conn *c3cn, struct sk_buff *skb)
-{
- c3cn_conn_debug("c3cn 0x%p, state %u, flag 0x%lx.\n",
- c3cn, c3cn->state, c3cn->flags);
-
- if (c3cn_flag(c3cn, C3CN_ABORT_RPL_PENDING))
- goto out;
-
- switch (c3cn->state) {
- case C3CN_STATE_ESTABLISHED:
- c3cn_set_state(c3cn, C3CN_STATE_PASSIVE_CLOSE);
- break;
- case C3CN_STATE_ACTIVE_CLOSE:
- c3cn_set_state(c3cn, C3CN_STATE_CLOSE_WAIT_2);
- break;
- case C3CN_STATE_CLOSE_WAIT_1:
- c3cn_closed(c3cn);
- break;
- case C3CN_STATE_ABORTING:
- break;
- default:
- cxgb3i_log_error("%s: peer close, TID %u in bad state %u\n",
- c3cn->cdev->name, c3cn->tid, c3cn->state);
- }
-
- cxgb3i_conn_closing(c3cn);
-out:
- __kfree_skb(skb);
-}
-
-static int do_peer_close(struct t3cdev *cdev, struct sk_buff *skb, void *ctx)
-{
- struct s3_conn *c3cn = ctx;
-
- c3cn_conn_debug("rcv, c3cn 0x%p, s %u, f 0x%lx.\n",
- c3cn, c3cn->state, c3cn->flags);
- process_cpl_msg_ref(process_peer_close, c3cn, skb);
- return 0;
-}
-
-/*
- * Process CLOSE_CONN_RPL CPL message: -> host
- * Process a peer ACK to our FIN.
- */
-static void process_close_con_rpl(struct s3_conn *c3cn, struct sk_buff *skb)
-{
- struct cpl_close_con_rpl *rpl = cplhdr(skb);
-
- c3cn_conn_debug("c3cn 0x%p, state %u, flag 0x%lx.\n",
- c3cn, c3cn->state, c3cn->flags);
-
- c3cn->snd_una = ntohl(rpl->snd_nxt) - 1; /* exclude FIN */
-
- if (c3cn_flag(c3cn, C3CN_ABORT_RPL_PENDING))
- goto out;
-
- switch (c3cn->state) {
- case C3CN_STATE_ACTIVE_CLOSE:
- c3cn_set_state(c3cn, C3CN_STATE_CLOSE_WAIT_1);
- break;
- case C3CN_STATE_CLOSE_WAIT_1:
- case C3CN_STATE_CLOSE_WAIT_2:
- c3cn_closed(c3cn);
- break;
- case C3CN_STATE_ABORTING:
- break;
- default:
- cxgb3i_log_error("%s: close_rpl, TID %u in bad state %u\n",
- c3cn->cdev->name, c3cn->tid, c3cn->state);
- }
-
-out:
- kfree_skb(skb);
-}
-
-static int do_close_con_rpl(struct t3cdev *cdev, struct sk_buff *skb,
- void *ctx)
-{
- struct s3_conn *c3cn = ctx;
-
- c3cn_conn_debug("rcv, c3cn 0x%p, s %u, f 0x%lx.\n",
- c3cn, c3cn->state, c3cn->flags);
-
- process_cpl_msg_ref(process_close_con_rpl, c3cn, skb);
- return 0;
-}
-
-/*
- * Process ABORT_REQ_RSS CPL message: -> host
- * Process abort requests. If we are waiting for an ABORT_RPL we ignore this
- * request except that we need to reply to it.
- */
-
-static int abort_status_to_errno(struct s3_conn *c3cn, int abort_reason,
- int *need_rst)
-{
- switch (abort_reason) {
- case CPL_ERR_BAD_SYN: /* fall through */
- case CPL_ERR_CONN_RESET:
- return c3cn->state > C3CN_STATE_ESTABLISHED ?
- -EPIPE : -ECONNRESET;
- case CPL_ERR_XMIT_TIMEDOUT:
- case CPL_ERR_PERSIST_TIMEDOUT:
- case CPL_ERR_FINWAIT2_TIMEDOUT:
- case CPL_ERR_KEEPALIVE_TIMEDOUT:
- return -ETIMEDOUT;
- default:
- return -EIO;
- }
-}
-
-static void process_abort_req(struct s3_conn *c3cn, struct sk_buff *skb)
-{
- int rst_status = CPL_ABORT_NO_RST;
- const struct cpl_abort_req_rss *req = cplhdr(skb);
-
- c3cn_conn_debug("c3cn 0x%p, state %u, flag 0x%lx.\n",
- c3cn, c3cn->state, c3cn->flags);
-
- if (!c3cn_flag(c3cn, C3CN_ABORT_REQ_RCVD)) {
- c3cn_set_flag(c3cn, C3CN_ABORT_REQ_RCVD);
- c3cn_set_state(c3cn, C3CN_STATE_ABORTING);
- __kfree_skb(skb);
- return;
- }
-
- c3cn_clear_flag(c3cn, C3CN_ABORT_REQ_RCVD);
- send_abort_rpl(c3cn, rst_status);
-
- if (!c3cn_flag(c3cn, C3CN_ABORT_RPL_PENDING)) {
- c3cn->err =
- abort_status_to_errno(c3cn, req->status, &rst_status);
- c3cn_closed(c3cn);
- }
-}
-
-static int do_abort_req(struct t3cdev *cdev, struct sk_buff *skb, void *ctx)
-{
- const struct cpl_abort_req_rss *req = cplhdr(skb);
- struct s3_conn *c3cn = ctx;
-
- c3cn_conn_debug("rcv, c3cn 0x%p, s 0x%x, f 0x%lx.\n",
- c3cn, c3cn->state, c3cn->flags);
-
- if (req->status == CPL_ERR_RTX_NEG_ADVICE ||
- req->status == CPL_ERR_PERSIST_NEG_ADVICE) {
- __kfree_skb(skb);
- return 0;
- }
-
- process_cpl_msg_ref(process_abort_req, c3cn, skb);
- return 0;
-}
-
-/*
- * Process ABORT_RPL_RSS CPL message: -> host
- * Process abort replies. We only process these messages if we anticipate
- * them as the coordination between SW and HW in this area is somewhat lacking
- * and sometimes we get ABORT_RPLs after we are done with the connection that
- * originated the ABORT_REQ.
- */
-static void process_abort_rpl(struct s3_conn *c3cn, struct sk_buff *skb)
-{
- c3cn_conn_debug("c3cn 0x%p, state %u, flag 0x%lx.\n",
- c3cn, c3cn->state, c3cn->flags);
-
- if (c3cn_flag(c3cn, C3CN_ABORT_RPL_PENDING)) {
- if (!c3cn_flag(c3cn, C3CN_ABORT_RPL_RCVD))
- c3cn_set_flag(c3cn, C3CN_ABORT_RPL_RCVD);
- else {
- c3cn_clear_flag(c3cn, C3CN_ABORT_RPL_RCVD);
- c3cn_clear_flag(c3cn, C3CN_ABORT_RPL_PENDING);
- if (c3cn_flag(c3cn, C3CN_ABORT_REQ_RCVD))
- cxgb3i_log_error("%s tid %u, ABORT_RPL_RSS\n",
- c3cn->cdev->name, c3cn->tid);
- c3cn_closed(c3cn);
- }
- }
- __kfree_skb(skb);
-}
-
-static int do_abort_rpl(struct t3cdev *cdev, struct sk_buff *skb, void *ctx)
-{
- struct cpl_abort_rpl_rss *rpl = cplhdr(skb);
- struct s3_conn *c3cn = ctx;
-
- c3cn_conn_debug("rcv, status 0x%x, c3cn 0x%p, s %u, 0x%lx.\n",
- rpl->status, c3cn, c3cn ? c3cn->state : 0,
- c3cn ? c3cn->flags : 0UL);
-
- /*
- * Ignore replies to post-close aborts indicating that the abort was
- * requested too late. These connections are terminated when we get
- * PEER_CLOSE or CLOSE_CON_RPL and by the time the abort_rpl_rss
- * arrives the TID is either no longer used or it has been recycled.
- */
- if (rpl->status == CPL_ERR_ABORT_FAILED)
- goto discard;
-
- /*
- * Sometimes we've already closed the connection, e.g., a post-close
- * abort races with ABORT_REQ_RSS, the latter frees the connection
- * expecting the ABORT_REQ will fail with CPL_ERR_ABORT_FAILED,
- * but FW turns the ABORT_REQ into a regular one and so we get
- * ABORT_RPL_RSS with status 0 and no connection.
- */
- if (!c3cn)
- goto discard;
-
- process_cpl_msg_ref(process_abort_rpl, c3cn, skb);
- return 0;
-
-discard:
- __kfree_skb(skb);
- return 0;
-}
-
-/*
- * Process RX_ISCSI_HDR CPL message: -> host
- * Handle received PDUs, the payload could be DDP'ed. If not, the payload
- * follow after the bhs.
- */
-static void process_rx_iscsi_hdr(struct s3_conn *c3cn, struct sk_buff *skb)
-{
- struct cpl_iscsi_hdr *hdr_cpl = cplhdr(skb);
- struct cpl_iscsi_hdr_norss data_cpl;
- struct cpl_rx_data_ddp_norss ddp_cpl;
- unsigned int hdr_len, data_len, status;
- unsigned int len;
- int err;
-
- if (unlikely(c3cn->state >= C3CN_STATE_PASSIVE_CLOSE)) {
- if (c3cn->state != C3CN_STATE_ABORTING)
- send_abort_req(c3cn);
- __kfree_skb(skb);
- return;
- }
-
- skb_tcp_seq(skb) = ntohl(hdr_cpl->seq);
- skb_flags(skb) = 0;
-
- skb_reset_transport_header(skb);
- __skb_pull(skb, sizeof(struct cpl_iscsi_hdr));
-
- len = hdr_len = ntohs(hdr_cpl->len);
- /* msg coalesce is off or not enough data received */
- if (skb->len <= hdr_len) {
- cxgb3i_log_error("%s: TID %u, ISCSI_HDR, skb len %u < %u.\n",
- c3cn->cdev->name, c3cn->tid,
- skb->len, hdr_len);
- goto abort_conn;
- }
-
- err = skb_copy_bits(skb, skb->len - sizeof(ddp_cpl), &ddp_cpl,
- sizeof(ddp_cpl));
- if (err < 0)
- goto abort_conn;
-
- skb_ulp_mode(skb) = ULP2_FLAG_DATA_READY;
- skb_rx_pdulen(skb) = ntohs(ddp_cpl.len);
- skb_rx_ddigest(skb) = ntohl(ddp_cpl.ulp_crc);
- status = ntohl(ddp_cpl.ddp_status);
-
- c3cn_rx_debug("rx skb 0x%p, len %u, pdulen %u, ddp status 0x%x.\n",
- skb, skb->len, skb_rx_pdulen(skb), status);
-
- if (status & (1 << RX_DDP_STATUS_HCRC_SHIFT))
- skb_ulp_mode(skb) |= ULP2_FLAG_HCRC_ERROR;
- if (status & (1 << RX_DDP_STATUS_DCRC_SHIFT))
- skb_ulp_mode(skb) |= ULP2_FLAG_DCRC_ERROR;
- if (status & (1 << RX_DDP_STATUS_PAD_SHIFT))
- skb_ulp_mode(skb) |= ULP2_FLAG_PAD_ERROR;
-
- if (skb->len > (hdr_len + sizeof(ddp_cpl))) {
- err = skb_copy_bits(skb, hdr_len, &data_cpl, sizeof(data_cpl));
- if (err < 0)
- goto abort_conn;
- data_len = ntohs(data_cpl.len);
- len += sizeof(data_cpl) + data_len;
- } else if (status & (1 << RX_DDP_STATUS_DDP_SHIFT))
- skb_ulp_mode(skb) |= ULP2_FLAG_DATA_DDPED;
-
- c3cn->rcv_nxt = ntohl(ddp_cpl.seq) + skb_rx_pdulen(skb);
- __pskb_trim(skb, len);
- __skb_queue_tail(&c3cn->receive_queue, skb);
- cxgb3i_conn_pdu_ready(c3cn);
-
- return;
-
-abort_conn:
- send_abort_req(c3cn);
- __kfree_skb(skb);
-}
-
-static int do_iscsi_hdr(struct t3cdev *t3dev, struct sk_buff *skb, void *ctx)
-{
- struct s3_conn *c3cn = ctx;
-
- process_cpl_msg(process_rx_iscsi_hdr, c3cn, skb);
- return 0;
-}
-
-/*
- * Process TX_DATA_ACK CPL messages: -> host
- * Process an acknowledgment of WR completion. Advance snd_una and send the
- * next batch of work requests from the write queue.
- */
-static void check_wr_invariants(struct s3_conn *c3cn)
-{
- int pending = count_pending_wrs(c3cn);
-
- if (unlikely(c3cn->wr_avail + pending != c3cn->wr_max))
- cxgb3i_log_error("TID %u: credit imbalance: avail %u, "
- "pending %u, total should be %u\n",
- c3cn->tid, c3cn->wr_avail, pending,
- c3cn->wr_max);
-}
-
-static void process_wr_ack(struct s3_conn *c3cn, struct sk_buff *skb)
-{
- struct cpl_wr_ack *hdr = cplhdr(skb);
- unsigned int credits = ntohs(hdr->credits);
- u32 snd_una = ntohl(hdr->snd_una);
-
- c3cn_tx_debug("%u WR credits, avail %u, unack %u, TID %u, state %u.\n",
- credits, c3cn->wr_avail, c3cn->wr_unacked,
- c3cn->tid, c3cn->state);
-
- c3cn->wr_avail += credits;
- if (c3cn->wr_unacked > c3cn->wr_max - c3cn->wr_avail)
- c3cn->wr_unacked = c3cn->wr_max - c3cn->wr_avail;
-
- while (credits) {
- struct sk_buff *p = peek_wr(c3cn);
-
- if (unlikely(!p)) {
- cxgb3i_log_error("%u WR_ACK credits for TID %u with "
- "nothing pending, state %u\n",
- credits, c3cn->tid, c3cn->state);
- break;
- }
- if (unlikely(credits < p->csum)) {
- struct tx_data_wr *w = cplhdr(p);
- cxgb3i_log_error("TID %u got %u WR credits need %u, "
- "len %u, main body %u, frags %u, "
- "seq # %u, ACK una %u, ACK nxt %u, "
- "WR_AVAIL %u, WRs pending %u\n",
- c3cn->tid, credits, p->csum, p->len,
- p->len - p->data_len,
- skb_shinfo(p)->nr_frags,
- ntohl(w->sndseq), snd_una,
- ntohl(hdr->snd_nxt), c3cn->wr_avail,
- count_pending_wrs(c3cn) - credits);
- p->csum -= credits;
- break;
- } else {
- dequeue_wr(c3cn);
- credits -= p->csum;
- free_wr_skb(p);
- }
- }
-
- check_wr_invariants(c3cn);
-
- if (unlikely(before(snd_una, c3cn->snd_una))) {
- cxgb3i_log_error("TID %u, unexpected sequence # %u in WR_ACK "
- "snd_una %u\n",
- c3cn->tid, snd_una, c3cn->snd_una);
- goto out_free;
- }
-
- if (c3cn->snd_una != snd_una) {
- c3cn->snd_una = snd_una;
- dst_confirm(c3cn->dst_cache);
- }
-
- if (skb_queue_len(&c3cn->write_queue)) {
- if (c3cn_push_tx_frames(c3cn, 0))
- cxgb3i_conn_tx_open(c3cn);
- } else
- cxgb3i_conn_tx_open(c3cn);
-out_free:
- __kfree_skb(skb);
-}
-
-static int do_wr_ack(struct t3cdev *cdev, struct sk_buff *skb, void *ctx)
-{
- struct s3_conn *c3cn = ctx;
-
- process_cpl_msg(process_wr_ack, c3cn, skb);
- return 0;
-}
-
-/*
- * for each connection, pre-allocate skbs needed for close/abort requests. So
- * that we can service the request right away.
- */
-static void c3cn_free_cpl_skbs(struct s3_conn *c3cn)
-{
- if (c3cn->cpl_close)
- kfree_skb(c3cn->cpl_close);
- if (c3cn->cpl_abort_req)
- kfree_skb(c3cn->cpl_abort_req);
- if (c3cn->cpl_abort_rpl)
- kfree_skb(c3cn->cpl_abort_rpl);
-}
-
-static int c3cn_alloc_cpl_skbs(struct s3_conn *c3cn)
-{
- c3cn->cpl_close = alloc_skb(sizeof(struct cpl_close_con_req),
- GFP_KERNEL);
- if (!c3cn->cpl_close)
- return -ENOMEM;
- skb_put(c3cn->cpl_close, sizeof(struct cpl_close_con_req));
-
- c3cn->cpl_abort_req = alloc_skb(sizeof(struct cpl_abort_req),
- GFP_KERNEL);
- if (!c3cn->cpl_abort_req)
- goto free_cpl_skbs;
- skb_put(c3cn->cpl_abort_req, sizeof(struct cpl_abort_req));
-
- c3cn->cpl_abort_rpl = alloc_skb(sizeof(struct cpl_abort_rpl),
- GFP_KERNEL);
- if (!c3cn->cpl_abort_rpl)
- goto free_cpl_skbs;
- skb_put(c3cn->cpl_abort_rpl, sizeof(struct cpl_abort_rpl));
-
- return 0;
-
-free_cpl_skbs:
- c3cn_free_cpl_skbs(c3cn);
- return -ENOMEM;
-}
-
-/**
- * c3cn_release_offload_resources - release offload resource
- * @c3cn: the offloaded iscsi tcp connection.
- * Release resources held by an offload connection (TID, L2T entry, etc.)
- */
-static void c3cn_release_offload_resources(struct s3_conn *c3cn)
-{
- struct t3cdev *cdev = c3cn->cdev;
- unsigned int tid = c3cn->tid;
-
- c3cn->qset = 0;
- c3cn_free_cpl_skbs(c3cn);
-
- if (c3cn->wr_avail != c3cn->wr_max) {
- purge_wr_queue(c3cn);
- reset_wr_list(c3cn);
- }
-
- if (cdev) {
- if (c3cn->l2t) {
- l2t_release(L2DATA(cdev), c3cn->l2t);
- c3cn->l2t = NULL;
- }
- if (c3cn->state == C3CN_STATE_CONNECTING)
- /* we have ATID */
- s3_free_atid(cdev, tid);
- else {
- /* we have TID */
- cxgb3_remove_tid(cdev, (void *)c3cn, tid);
- c3cn_put(c3cn);
- }
- }
-
- c3cn->dst_cache = NULL;
- c3cn->cdev = NULL;
-}
-
-/**
- * cxgb3i_c3cn_create - allocate and initialize an s3_conn structure
- * returns the s3_conn structure allocated.
- */
-struct s3_conn *cxgb3i_c3cn_create(void)
-{
- struct s3_conn *c3cn;
-
- c3cn = kzalloc(sizeof(*c3cn), GFP_KERNEL);
- if (!c3cn)
- return NULL;
-
- /* pre-allocate close/abort cpl, so we don't need to wait for memory
- when close/abort is requested. */
- if (c3cn_alloc_cpl_skbs(c3cn) < 0)
- goto free_c3cn;
-
- c3cn_conn_debug("alloc c3cn 0x%p.\n", c3cn);
-
- c3cn->flags = 0;
- spin_lock_init(&c3cn->lock);
- atomic_set(&c3cn->refcnt, 1);
- skb_queue_head_init(&c3cn->receive_queue);
- skb_queue_head_init(&c3cn->write_queue);
- setup_timer(&c3cn->retry_timer, NULL, (unsigned long)c3cn);
- rwlock_init(&c3cn->callback_lock);
-
- return c3cn;
-
-free_c3cn:
- kfree(c3cn);
- return NULL;
-}
-
-static void c3cn_active_close(struct s3_conn *c3cn)
-{
- int data_lost;
- int close_req = 0;
-
- c3cn_conn_debug("c3cn 0x%p, state %u, flag 0x%lx.\n",
- c3cn, c3cn->state, c3cn->flags);
-
- dst_confirm(c3cn->dst_cache);
-
- c3cn_hold(c3cn);
- spin_lock_bh(&c3cn->lock);
-
- data_lost = skb_queue_len(&c3cn->receive_queue);
- __skb_queue_purge(&c3cn->receive_queue);
-
- switch (c3cn->state) {
- case C3CN_STATE_CLOSED:
- case C3CN_STATE_ACTIVE_CLOSE:
- case C3CN_STATE_CLOSE_WAIT_1:
- case C3CN_STATE_CLOSE_WAIT_2:
- case C3CN_STATE_ABORTING:
- /* nothing need to be done */
- break;
- case C3CN_STATE_CONNECTING:
- /* defer until cpl_act_open_rpl or cpl_act_establish */
- c3cn_set_flag(c3cn, C3CN_ACTIVE_CLOSE_NEEDED);
- break;
- case C3CN_STATE_ESTABLISHED:
- close_req = 1;
- c3cn_set_state(c3cn, C3CN_STATE_ACTIVE_CLOSE);
- break;
- case C3CN_STATE_PASSIVE_CLOSE:
- close_req = 1;
- c3cn_set_state(c3cn, C3CN_STATE_CLOSE_WAIT_2);
- break;
- }
-
- if (close_req) {
- if (data_lost)
- /* Unread data was tossed, zap the connection. */
- send_abort_req(c3cn);
- else
- send_close_req(c3cn);
- }
-
- spin_unlock_bh(&c3cn->lock);
- c3cn_put(c3cn);
-}
-
-/**
- * cxgb3i_c3cn_release - close and release an iscsi tcp connection and any
- * resource held
- * @c3cn: the iscsi tcp connection
- */
-void cxgb3i_c3cn_release(struct s3_conn *c3cn)
-{
- c3cn_conn_debug("c3cn 0x%p, s %u, f 0x%lx.\n",
- c3cn, c3cn->state, c3cn->flags);
- if (unlikely(c3cn->state == C3CN_STATE_CONNECTING))
- c3cn_set_flag(c3cn, C3CN_ACTIVE_CLOSE_NEEDED);
- else if (likely(c3cn->state != C3CN_STATE_CLOSED))
- c3cn_active_close(c3cn);
- c3cn_put(c3cn);
-}
-
-static int is_cxgb3_dev(struct net_device *dev)
-{
- struct cxgb3i_sdev_data *cdata;
- struct net_device *ndev = dev;
-
- if (dev->priv_flags & IFF_802_1Q_VLAN)
- ndev = vlan_dev_real_dev(dev);
-
- write_lock(&cdata_rwlock);
- list_for_each_entry(cdata, &cdata_list, list) {
- struct adap_ports *ports = &cdata->ports;
- int i;
-
- for (i = 0; i < ports->nports; i++)
- if (ndev == ports->lldevs[i]) {
- write_unlock(&cdata_rwlock);
- return 1;
- }
- }
- write_unlock(&cdata_rwlock);
- return 0;
-}
-
-/**
- * cxgb3_egress_dev - return the cxgb3 egress device
- * @root_dev: the root device anchoring the search
- * @c3cn: the connection used to determine egress port in bonding mode
- * @context: in bonding mode, indicates a connection set up or failover
- *
- * Return egress device or NULL if the egress device isn't one of our ports.
- */
-static struct net_device *cxgb3_egress_dev(struct net_device *root_dev,
- struct s3_conn *c3cn,
- int context)
-{
- while (root_dev) {
- if (root_dev->priv_flags & IFF_802_1Q_VLAN)
- root_dev = vlan_dev_real_dev(root_dev);
- else if (is_cxgb3_dev(root_dev))
- return root_dev;
- else
- return NULL;
- }
- return NULL;
-}
-
-static struct rtable *find_route(struct net_device *dev,
- __be32 saddr, __be32 daddr,
- __be16 sport, __be16 dport)
-{
- struct rtable *rt;
- struct flowi fl = {
- .oif = dev ? dev->ifindex : 0,
- .nl_u = {
- .ip4_u = {
- .daddr = daddr,
- .saddr = saddr,
- .tos = 0 } },
- .proto = IPPROTO_TCP,
- .uli_u = {
- .ports = {
- .sport = sport,
- .dport = dport } } };
-
- if (ip_route_output_flow(&init_net, &rt, &fl, NULL, 0))
- return NULL;
- return rt;
-}
-
-/*
- * Assign offload parameters to some connection fields.
- */
-static void init_offload_conn(struct s3_conn *c3cn,
- struct t3cdev *cdev,
- struct dst_entry *dst)
-{
- BUG_ON(c3cn->cdev != cdev);
- c3cn->wr_max = c3cn->wr_avail = T3C_DATA(cdev)->max_wrs - 1;
- c3cn->wr_unacked = 0;
- c3cn->mss_idx = select_mss(c3cn, dst_mtu(dst));
-
- reset_wr_list(c3cn);
-}
-
-static int initiate_act_open(struct s3_conn *c3cn, struct net_device *dev)
-{
- struct cxgb3i_sdev_data *cdata = NDEV2CDATA(dev);
- struct t3cdev *cdev = cdata->cdev;
- struct dst_entry *dst = c3cn->dst_cache;
- struct sk_buff *skb;
-
- c3cn_conn_debug("c3cn 0x%p, state %u, flag 0x%lx.\n",
- c3cn, c3cn->state, c3cn->flags);
- /*
- * Initialize connection data. Note that the flags and ULP mode are
- * initialized higher up ...
- */
- c3cn->dev = dev;
- c3cn->cdev = cdev;
- c3cn->tid = cxgb3_alloc_atid(cdev, cdata->client, c3cn);
- if (c3cn->tid < 0)
- goto out_err;
-
- c3cn->qset = 0;
- c3cn->l2t = t3_l2t_get(cdev, dst->neighbour, dev);
- if (!c3cn->l2t)
- goto free_tid;
-
- skb = alloc_skb(sizeof(struct cpl_act_open_req), GFP_KERNEL);
- if (!skb)
- goto free_l2t;
-
- skb->sk = (struct sock *)c3cn;
- set_arp_failure_handler(skb, act_open_req_arp_failure);
-
- c3cn_hold(c3cn);
-
- init_offload_conn(c3cn, cdev, dst);
- c3cn->err = 0;
-
- make_act_open_req(c3cn, skb, c3cn->tid, c3cn->l2t);
- l2t_send(cdev, skb, c3cn->l2t);
- return 0;
-
-free_l2t:
- l2t_release(L2DATA(cdev), c3cn->l2t);
-free_tid:
- s3_free_atid(cdev, c3cn->tid);
- c3cn->tid = 0;
-out_err:
- return -EINVAL;
-}
-
-/**
- * cxgb3i_find_dev - find the interface associated with the given address
- * @ipaddr: ip address
- */
-static struct net_device *
-cxgb3i_find_dev(struct net_device *dev, __be32 ipaddr)
-{
- struct flowi fl;
- int err;
- struct rtable *rt;
-
- memset(&fl, 0, sizeof(fl));
- fl.nl_u.ip4_u.daddr = ipaddr;
-
- err = ip_route_output_key(dev ? dev_net(dev) : &init_net, &rt, &fl);
- if (!err)
- return (&rt->dst)->dev;
-
- return NULL;
-}
-
-/**
- * cxgb3i_c3cn_connect - initiates an iscsi tcp connection to a given address
- * @c3cn: the iscsi tcp connection
- * @usin: destination address
- *
- * return 0 if active open request is sent, < 0 otherwise.
- */
-int cxgb3i_c3cn_connect(struct net_device *dev, struct s3_conn *c3cn,
- struct sockaddr_in *usin)
-{
- struct rtable *rt;
- struct cxgb3i_sdev_data *cdata;
- struct t3cdev *cdev;
- __be32 sipv4;
- struct net_device *dstdev;
- int err;
-
- c3cn_conn_debug("c3cn 0x%p, dev 0x%p.\n", c3cn, dev);
-
- if (usin->sin_family != AF_INET)
- return -EAFNOSUPPORT;
-
- c3cn->daddr.sin_port = usin->sin_port;
- c3cn->daddr.sin_addr.s_addr = usin->sin_addr.s_addr;
-
- dstdev = cxgb3i_find_dev(dev, usin->sin_addr.s_addr);
- if (!dstdev || !is_cxgb3_dev(dstdev))
- return -ENETUNREACH;
-
- if (dstdev->priv_flags & IFF_802_1Q_VLAN)
- dev = dstdev;
-
- rt = find_route(dev, c3cn->saddr.sin_addr.s_addr,
- c3cn->daddr.sin_addr.s_addr,
- c3cn->saddr.sin_port,
- c3cn->daddr.sin_port);
- if (rt == NULL) {
- c3cn_conn_debug("NO route to 0x%x, port %u, dev %s.\n",
- c3cn->daddr.sin_addr.s_addr,
- ntohs(c3cn->daddr.sin_port),
- dev ? dev->name : "any");
- return -ENETUNREACH;
- }
-
- if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) {
- c3cn_conn_debug("multi-cast route to 0x%x, port %u, dev %s.\n",
- c3cn->daddr.sin_addr.s_addr,
- ntohs(c3cn->daddr.sin_port),
- dev ? dev->name : "any");
- ip_rt_put(rt);
- return -ENETUNREACH;
- }
-
- if (!c3cn->saddr.sin_addr.s_addr)
- c3cn->saddr.sin_addr.s_addr = rt->rt_src;
-
- /* now commit destination to connection */
- c3cn->dst_cache = &rt->dst;
-
- /* try to establish an offloaded connection */
- dev = cxgb3_egress_dev(c3cn->dst_cache->dev, c3cn, 0);
- if (dev == NULL) {
- c3cn_conn_debug("c3cn 0x%p, egress dev NULL.\n", c3cn);
- return -ENETUNREACH;
- }
- cdata = NDEV2CDATA(dev);
- cdev = cdata->cdev;
-
- /* get a source port if one hasn't been provided */
- err = c3cn_get_port(c3cn, cdata);
- if (err)
- return err;
-
- c3cn_conn_debug("c3cn 0x%p get port %u.\n",
- c3cn, ntohs(c3cn->saddr.sin_port));
-
- sipv4 = cxgb3i_get_private_ipv4addr(dev);
- if (!sipv4) {
- c3cn_conn_debug("c3cn 0x%p, iscsi ip not configured.\n", c3cn);
- sipv4 = c3cn->saddr.sin_addr.s_addr;
- cxgb3i_set_private_ipv4addr(dev, sipv4);
- } else
- c3cn->saddr.sin_addr.s_addr = sipv4;
-
- c3cn_conn_debug("c3cn 0x%p, %pI4,%u-%pI4,%u SYN_SENT.\n",
- c3cn,
- &c3cn->saddr.sin_addr.s_addr,
- ntohs(c3cn->saddr.sin_port),
- &c3cn->daddr.sin_addr.s_addr,
- ntohs(c3cn->daddr.sin_port));
-
- c3cn_set_state(c3cn, C3CN_STATE_CONNECTING);
- if (!initiate_act_open(c3cn, dev))
- return 0;
-
- /*
- * If we get here, we don't have an offload connection so simply
- * return a failure.
- */
- err = -ENOTSUPP;
-
- /*
- * This trashes the connection and releases the local port,
- * if necessary.
- */
- c3cn_conn_debug("c3cn 0x%p -> CLOSED.\n", c3cn);
- c3cn_set_state(c3cn, C3CN_STATE_CLOSED);
- ip_rt_put(rt);
- c3cn_put_port(c3cn);
- return err;
-}
-
-/**
- * cxgb3i_c3cn_rx_credits - ack received tcp data.
- * @c3cn: iscsi tcp connection
- * @copied: # of bytes processed
- *
- * Called after some received data has been read. It returns RX credits
- * to the HW for the amount of data processed.
- */
-void cxgb3i_c3cn_rx_credits(struct s3_conn *c3cn, int copied)
-{
- struct t3cdev *cdev;
- int must_send;
- u32 credits, dack = 0;
-
- if (c3cn->state != C3CN_STATE_ESTABLISHED)
- return;
-
- credits = c3cn->copied_seq - c3cn->rcv_wup;
- if (unlikely(!credits))
- return;
-
- cdev = c3cn->cdev;
-
- if (unlikely(cxgb3_rx_credit_thres == 0))
- return;
-
- dack = F_RX_DACK_CHANGE | V_RX_DACK_MODE(1);
-
- /*
- * For coalescing to work effectively ensure the receive window has
- * at least 16KB left.
- */
- must_send = credits + 16384 >= cxgb3_rcv_win;
-
- if (must_send || credits >= cxgb3_rx_credit_thres)
- c3cn->rcv_wup += send_rx_credits(c3cn, credits, dack);
-}
-
-/**
- * cxgb3i_c3cn_send_pdus - send the skbs containing iscsi pdus
- * @c3cn: iscsi tcp connection
- * @skb: skb contains the iscsi pdu
- *
- * Add a list of skbs to a connection send queue. The skbs must comply with
- * the max size limit of the device and have a headroom of at least
- * TX_HEADER_LEN bytes.
- * Return # of bytes queued.
- */
-int cxgb3i_c3cn_send_pdus(struct s3_conn *c3cn, struct sk_buff *skb)
-{
- struct sk_buff *next;
- int err, copied = 0;
-
- spin_lock_bh(&c3cn->lock);
-
- if (c3cn->state != C3CN_STATE_ESTABLISHED) {
- c3cn_tx_debug("c3cn 0x%p, not in est. state %u.\n",
- c3cn, c3cn->state);
- err = -EAGAIN;
- goto out_err;
- }
-
- if (c3cn->err) {
- c3cn_tx_debug("c3cn 0x%p, err %d.\n", c3cn, c3cn->err);
- err = -EPIPE;
- goto out_err;
- }
-
- if (c3cn->write_seq - c3cn->snd_una >= cxgb3_snd_win) {
- c3cn_tx_debug("c3cn 0x%p, snd %u - %u > %u.\n",
- c3cn, c3cn->write_seq, c3cn->snd_una,
- cxgb3_snd_win);
- err = -ENOBUFS;
- goto out_err;
- }
-
- while (skb) {
- int frags = skb_shinfo(skb)->nr_frags +
- (skb->len != skb->data_len);
-
- if (unlikely(skb_headroom(skb) < TX_HEADER_LEN)) {
- c3cn_tx_debug("c3cn 0x%p, skb head.\n", c3cn);
- err = -EINVAL;
- goto out_err;
- }
-
- if (frags >= SKB_WR_LIST_SIZE) {
- cxgb3i_log_error("c3cn 0x%p, tx frags %d, len %u,%u.\n",
- c3cn, skb_shinfo(skb)->nr_frags,
- skb->len, skb->data_len);
- err = -EINVAL;
- goto out_err;
- }
-
- next = skb->next;
- skb->next = NULL;
- skb_entail(c3cn, skb, C3CB_FLAG_NO_APPEND | C3CB_FLAG_NEED_HDR);
- copied += skb->len;
- c3cn->write_seq += skb->len + ulp_extra_len(skb);
- skb = next;
- }
-done:
- if (likely(skb_queue_len(&c3cn->write_queue)))
- c3cn_push_tx_frames(c3cn, 1);
- spin_unlock_bh(&c3cn->lock);
- return copied;
-
-out_err:
- if (copied == 0 && err == -EPIPE)
- copied = c3cn->err ? c3cn->err : -EPIPE;
- else
- copied = err;
- goto done;
-}
-
-static void sdev_data_cleanup(struct cxgb3i_sdev_data *cdata)
-{
- struct adap_ports *ports = &cdata->ports;
- struct s3_conn *c3cn;
- int i;
-
- for (i = 0; i < cxgb3_max_connect; i++) {
- if (cdata->sport_conn[i]) {
- c3cn = cdata->sport_conn[i];
- cdata->sport_conn[i] = NULL;
-
- spin_lock_bh(&c3cn->lock);
- c3cn->cdev = NULL;
- c3cn_set_flag(c3cn, C3CN_OFFLOAD_DOWN);
- c3cn_closed(c3cn);
- spin_unlock_bh(&c3cn->lock);
- }
- }
-
- for (i = 0; i < ports->nports; i++)
- NDEV2CDATA(ports->lldevs[i]) = NULL;
-
- cxgb3i_free_big_mem(cdata);
-}
-
-void cxgb3i_sdev_cleanup(void)
-{
- struct cxgb3i_sdev_data *cdata;
-
- write_lock(&cdata_rwlock);
- list_for_each_entry(cdata, &cdata_list, list) {
- list_del(&cdata->list);
- sdev_data_cleanup(cdata);
- }
- write_unlock(&cdata_rwlock);
-}
-
-int cxgb3i_sdev_init(cxgb3_cpl_handler_func *cpl_handlers)
-{
- cpl_handlers[CPL_ACT_ESTABLISH] = do_act_establish;
- cpl_handlers[CPL_ACT_OPEN_RPL] = do_act_open_rpl;
- cpl_handlers[CPL_PEER_CLOSE] = do_peer_close;
- cpl_handlers[CPL_ABORT_REQ_RSS] = do_abort_req;
- cpl_handlers[CPL_ABORT_RPL_RSS] = do_abort_rpl;
- cpl_handlers[CPL_CLOSE_CON_RPL] = do_close_con_rpl;
- cpl_handlers[CPL_TX_DMA_ACK] = do_wr_ack;
- cpl_handlers[CPL_ISCSI_HDR] = do_iscsi_hdr;
-
- if (cxgb3_max_connect > CXGB3I_MAX_CONN)
- cxgb3_max_connect = CXGB3I_MAX_CONN;
- return 0;
-}
-
-/**
- * cxgb3i_sdev_add - allocate and initialize resources for each adapter found
- * @cdev: t3cdev adapter
- * @client: cxgb3 driver client
- */
-void cxgb3i_sdev_add(struct t3cdev *cdev, struct cxgb3_client *client)
-{
- struct cxgb3i_sdev_data *cdata;
- struct ofld_page_info rx_page_info;
- unsigned int wr_len;
- int mapsize = cxgb3_max_connect * sizeof(struct s3_conn *);
- int i;
-
- cdata = cxgb3i_alloc_big_mem(sizeof(*cdata) + mapsize, GFP_KERNEL);
- if (!cdata) {
- cxgb3i_log_warn("t3dev 0x%p, offload up, OOM %d.\n",
- cdev, mapsize);
- return;
- }
-
- if (cdev->ctl(cdev, GET_WR_LEN, &wr_len) < 0 ||
- cdev->ctl(cdev, GET_PORTS, &cdata->ports) < 0 ||
- cdev->ctl(cdev, GET_RX_PAGE_INFO, &rx_page_info) < 0) {
- cxgb3i_log_warn("t3dev 0x%p, offload up, ioctl failed.\n",
- cdev);
- goto free_cdata;
- }
-
- s3_init_wr_tab(wr_len);
-
- spin_lock_init(&cdata->lock);
- INIT_LIST_HEAD(&cdata->list);
- cdata->cdev = cdev;
- cdata->client = client;
-
- for (i = 0; i < cdata->ports.nports; i++)
- NDEV2CDATA(cdata->ports.lldevs[i]) = cdata;
-
- write_lock(&cdata_rwlock);
- list_add_tail(&cdata->list, &cdata_list);
- write_unlock(&cdata_rwlock);
-
- cxgb3i_log_info("t3dev 0x%p, offload up, added.\n", cdev);
- return;
-
-free_cdata:
- cxgb3i_free_big_mem(cdata);
-}
-
-/**
- * cxgb3i_sdev_remove - free the allocated resources for the adapter
- * @cdev: t3cdev adapter
- */
-void cxgb3i_sdev_remove(struct t3cdev *cdev)
-{
- struct cxgb3i_sdev_data *cdata = CXGB3_SDEV_DATA(cdev);
-
- cxgb3i_log_info("t3dev 0x%p, offload down, remove.\n", cdev);
-
- write_lock(&cdata_rwlock);
- list_del(&cdata->list);
- write_unlock(&cdata_rwlock);
-
- sdev_data_cleanup(cdata);
-}
diff --git a/drivers/scsi/cxgb3i/cxgb3i_offload.h b/drivers/scsi/cxgb3i/cxgb3i_offload.h
deleted file mode 100644
index 6a1d86b1fafe..000000000000
--- a/drivers/scsi/cxgb3i/cxgb3i_offload.h
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * cxgb3i_offload.h: Chelsio S3xx iscsi offloaded tcp connection management
- *
- * Copyright (C) 2003-2008 Chelsio Communications. All rights reserved.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the LICENSE file included in this
- * release for licensing terms and conditions.
- *
- * Written by: Dimitris Michailidis (dm@chelsio.com)
- * Karen Xie (kxie@chelsio.com)
- */
-
-#ifndef _CXGB3I_OFFLOAD_H
-#define _CXGB3I_OFFLOAD_H
-
-#include <linux/skbuff.h>
-#include <linux/in.h>
-
-#include "common.h"
-#include "adapter.h"
-#include "t3cdev.h"
-#include "cxgb3_offload.h"
-
-#define cxgb3i_log_error(fmt...) printk(KERN_ERR "cxgb3i: ERR! " fmt)
-#define cxgb3i_log_warn(fmt...) printk(KERN_WARNING "cxgb3i: WARN! " fmt)
-#define cxgb3i_log_info(fmt...) printk(KERN_INFO "cxgb3i: " fmt)
-#define cxgb3i_log_debug(fmt, args...) \
- printk(KERN_INFO "cxgb3i: %s - " fmt, __func__ , ## args)
-
-/**
- * struct s3_conn - an iscsi tcp connection structure
- *
- * @dev: net device of with connection
- * @cdev: adapter t3cdev for net device
- * @flags: see c3cn_flags below
- * @tid: connection id assigned by the h/w
- * @qset: queue set used by connection
- * @mss_idx: Maximum Segment Size table index
- * @l2t: ARP resolution entry for offload packets
- * @wr_max: maximum in-flight writes
- * @wr_avail: number of writes available
- * @wr_unacked: writes since last request for completion notification
- * @wr_pending_head: head of pending write queue
- * @wr_pending_tail: tail of pending write queue
- * @cpl_close: skb for cpl_close_req
- * @cpl_abort_req: skb for cpl_abort_req
- * @cpl_abort_rpl: skb for cpl_abort_rpl
- * @lock: connection status lock
- * @refcnt: reference count on connection
- * @state: connection state
- * @saddr: source ip/port address
- * @daddr: destination ip/port address
- * @dst_cache: reference to destination route
- * @receive_queue: received PDUs
- * @write_queue: un-pushed pending writes
- * @retry_timer: retry timer for various operations
- * @err: connection error status
- * @callback_lock: lock for opaque user context
- * @user_data: opaque user context
- * @rcv_nxt: next receive seq. #
- * @copied_seq: head of yet unread data
- * @rcv_wup: rcv_nxt on last window update sent
- * @snd_nxt: next sequence we send
- * @snd_una: first byte we want an ack for
- * @write_seq: tail+1 of data held in send buffer
- */
-struct s3_conn {
- struct net_device *dev;
- struct t3cdev *cdev;
- unsigned long flags;
- int tid;
- int qset;
- int mss_idx;
- struct l2t_entry *l2t;
- int wr_max;
- int wr_avail;
- int wr_unacked;
- struct sk_buff *wr_pending_head;
- struct sk_buff *wr_pending_tail;
- struct sk_buff *cpl_close;
- struct sk_buff *cpl_abort_req;
- struct sk_buff *cpl_abort_rpl;
- spinlock_t lock;
- atomic_t refcnt;
- volatile unsigned int state;
- struct sockaddr_in saddr;
- struct sockaddr_in daddr;
- struct dst_entry *dst_cache;
- struct sk_buff_head receive_queue;
- struct sk_buff_head write_queue;
- struct timer_list retry_timer;
- int err;
- rwlock_t callback_lock;
- void *user_data;
-
- u32 rcv_nxt;
- u32 copied_seq;
- u32 rcv_wup;
- u32 snd_nxt;
- u32 snd_una;
- u32 write_seq;
-};
-
-/*
- * connection state
- */
-enum conn_states {
- C3CN_STATE_CONNECTING = 1,
- C3CN_STATE_ESTABLISHED,
- C3CN_STATE_ACTIVE_CLOSE,
- C3CN_STATE_PASSIVE_CLOSE,
- C3CN_STATE_CLOSE_WAIT_1,
- C3CN_STATE_CLOSE_WAIT_2,
- C3CN_STATE_ABORTING,
- C3CN_STATE_CLOSED,
-};
-
-static inline unsigned int c3cn_is_closing(const struct s3_conn *c3cn)
-{
- return c3cn->state >= C3CN_STATE_ACTIVE_CLOSE;
-}
-static inline unsigned int c3cn_is_established(const struct s3_conn *c3cn)
-{
- return c3cn->state == C3CN_STATE_ESTABLISHED;
-}
-
-/*
- * Connection flags -- many to track some close related events.
- */
-enum c3cn_flags {
- C3CN_ABORT_RPL_RCVD, /* received one ABORT_RPL_RSS message */
- C3CN_ABORT_REQ_RCVD, /* received one ABORT_REQ_RSS message */
- C3CN_ABORT_RPL_PENDING, /* expecting an abort reply */
- C3CN_TX_DATA_SENT, /* already sent a TX_DATA WR */
- C3CN_ACTIVE_CLOSE_NEEDED, /* need to be closed */
- C3CN_OFFLOAD_DOWN /* offload function off */
-};
-
-/**
- * cxgb3i_sdev_data - Per adapter data.
- * Linked off of each Ethernet device port on the adapter.
- * Also available via the t3cdev structure since we have pointers to our port
- * net_device's there ...
- *
- * @list: list head to link elements
- * @cdev: t3cdev adapter
- * @client: CPL client pointer
- * @ports: array of adapter ports
- * @sport_next: next port
- * @sport_conn: source port connection
- */
-struct cxgb3i_sdev_data {
- struct list_head list;
- struct t3cdev *cdev;
- struct cxgb3_client *client;
- struct adap_ports ports;
- spinlock_t lock;
- unsigned int sport_next;
- struct s3_conn *sport_conn[0];
-};
-#define NDEV2CDATA(ndev) (*(struct cxgb3i_sdev_data **)&(ndev)->ec_ptr)
-#define CXGB3_SDEV_DATA(cdev) NDEV2CDATA((cdev)->lldev)
-
-void cxgb3i_sdev_cleanup(void);
-int cxgb3i_sdev_init(cxgb3_cpl_handler_func *);
-void cxgb3i_sdev_add(struct t3cdev *, struct cxgb3_client *);
-void cxgb3i_sdev_remove(struct t3cdev *);
-
-struct s3_conn *cxgb3i_c3cn_create(void);
-int cxgb3i_c3cn_connect(struct net_device *, struct s3_conn *,
- struct sockaddr_in *);
-void cxgb3i_c3cn_rx_credits(struct s3_conn *, int);
-int cxgb3i_c3cn_send_pdus(struct s3_conn *, struct sk_buff *);
-void cxgb3i_c3cn_release(struct s3_conn *);
-
-/**
- * cxgb3_skb_cb - control block for received pdu state and ULP mode management.
- *
- * @flag: see C3CB_FLAG_* below
- * @ulp_mode: ULP mode/submode of sk_buff
- * @seq: tcp sequence number
- */
-struct cxgb3_skb_rx_cb {
- __u32 ddigest; /* data digest */
- __u32 pdulen; /* recovered pdu length */
-};
-
-struct cxgb3_skb_tx_cb {
- struct sk_buff *wr_next; /* next wr */
-};
-
-struct cxgb3_skb_cb {
- __u8 flags;
- __u8 ulp_mode;
- __u32 seq;
- union {
- struct cxgb3_skb_rx_cb rx;
- struct cxgb3_skb_tx_cb tx;
- };
-};
-
-#define CXGB3_SKB_CB(skb) ((struct cxgb3_skb_cb *)&((skb)->cb[0]))
-#define skb_flags(skb) (CXGB3_SKB_CB(skb)->flags)
-#define skb_ulp_mode(skb) (CXGB3_SKB_CB(skb)->ulp_mode)
-#define skb_tcp_seq(skb) (CXGB3_SKB_CB(skb)->seq)
-#define skb_rx_ddigest(skb) (CXGB3_SKB_CB(skb)->rx.ddigest)
-#define skb_rx_pdulen(skb) (CXGB3_SKB_CB(skb)->rx.pdulen)
-#define skb_tx_wr_next(skb) (CXGB3_SKB_CB(skb)->tx.wr_next)
-
-enum c3cb_flags {
- C3CB_FLAG_NEED_HDR = 1 << 0, /* packet needs a TX_DATA_WR header */
- C3CB_FLAG_NO_APPEND = 1 << 1, /* don't grow this skb */
- C3CB_FLAG_COMPL = 1 << 2, /* request WR completion */
-};
-
-/**
- * sge_opaque_hdr -
- * Opaque version of structure the SGE stores at skb->head of TX_DATA packets
- * and for which we must reserve space.
- */
-struct sge_opaque_hdr {
- void *dev;
- dma_addr_t addr[MAX_SKB_FRAGS + 1];
-};
-
-/* for TX: a skb must have a headroom of at least TX_HEADER_LEN bytes */
-#define TX_HEADER_LEN \
- (sizeof(struct tx_data_wr) + sizeof(struct sge_opaque_hdr))
-#define SKB_TX_HEADROOM SKB_MAX_HEAD(TX_HEADER_LEN)
-
-/*
- * get and set private ip for iscsi traffic
- */
-#define cxgb3i_get_private_ipv4addr(ndev) \
- (((struct port_info *)(netdev_priv(ndev)))->iscsi_ipv4addr)
-#define cxgb3i_set_private_ipv4addr(ndev, addr) \
- (((struct port_info *)(netdev_priv(ndev)))->iscsi_ipv4addr) = addr
-
-/* max. connections per adapter */
-#define CXGB3I_MAX_CONN 16384
-#endif /* _CXGB3_OFFLOAD_H */
diff --git a/drivers/scsi/cxgb3i/cxgb3i_pdu.c b/drivers/scsi/cxgb3i/cxgb3i_pdu.c
deleted file mode 100644
index dc5e3e77a351..000000000000
--- a/drivers/scsi/cxgb3i/cxgb3i_pdu.c
+++ /dev/null
@@ -1,495 +0,0 @@
-/*
- * cxgb3i_pdu.c: Chelsio S3xx iSCSI driver.
- *
- * Copyright (c) 2008 Chelsio Communications, Inc.
- * Copyright (c) 2008 Mike Christie
- * Copyright (c) 2008 Red Hat, Inc. All rights reserved.
- *
- * 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.
- *
- * Written by: Karen Xie (kxie@chelsio.com)
- */
-
-#include <linux/slab.h>
-#include <linux/skbuff.h>
-#include <linux/crypto.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_host.h>
-
-#include "cxgb3i.h"
-#include "cxgb3i_pdu.h"
-
-#ifdef __DEBUG_CXGB3I_RX__
-#define cxgb3i_rx_debug cxgb3i_log_debug
-#else
-#define cxgb3i_rx_debug(fmt...)
-#endif
-
-#ifdef __DEBUG_CXGB3I_TX__
-#define cxgb3i_tx_debug cxgb3i_log_debug
-#else
-#define cxgb3i_tx_debug(fmt...)
-#endif
-
-/* always allocate rooms for AHS */
-#define SKB_TX_PDU_HEADER_LEN \
- (sizeof(struct iscsi_hdr) + ISCSI_MAX_AHS_SIZE)
-static unsigned int skb_extra_headroom;
-static struct page *pad_page;
-
-/*
- * pdu receive, interact with libiscsi_tcp
- */
-static inline int read_pdu_skb(struct iscsi_conn *conn, struct sk_buff *skb,
- unsigned int offset, int offloaded)
-{
- int status = 0;
- int bytes_read;
-
- bytes_read = iscsi_tcp_recv_skb(conn, skb, offset, offloaded, &status);
- switch (status) {
- case ISCSI_TCP_CONN_ERR:
- return -EIO;
- case ISCSI_TCP_SUSPENDED:
- /* no transfer - just have caller flush queue */
- return bytes_read;
- case ISCSI_TCP_SKB_DONE:
- /*
- * pdus should always fit in the skb and we should get
- * segment done notifcation.
- */
- iscsi_conn_printk(KERN_ERR, conn, "Invalid pdu or skb.");
- return -EFAULT;
- case ISCSI_TCP_SEGMENT_DONE:
- return bytes_read;
- default:
- iscsi_conn_printk(KERN_ERR, conn, "Invalid iscsi_tcp_recv_skb "
- "status %d\n", status);
- return -EINVAL;
- }
-}
-
-static int cxgb3i_conn_read_pdu_skb(struct iscsi_conn *conn,
- struct sk_buff *skb)
-{
- struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
- bool offloaded = 0;
- unsigned int offset;
- int rc;
-
- cxgb3i_rx_debug("conn 0x%p, skb 0x%p, len %u, flag 0x%x.\n",
- conn, skb, skb->len, skb_ulp_mode(skb));
-
- if (!iscsi_tcp_recv_segment_is_hdr(tcp_conn)) {
- iscsi_conn_failure(conn, ISCSI_ERR_PROTO);
- return -EIO;
- }
-
- if (conn->hdrdgst_en && (skb_ulp_mode(skb) & ULP2_FLAG_HCRC_ERROR)) {
- iscsi_conn_failure(conn, ISCSI_ERR_HDR_DGST);
- return -EIO;
- }
-
- if (conn->datadgst_en && (skb_ulp_mode(skb) & ULP2_FLAG_DCRC_ERROR)) {
- iscsi_conn_failure(conn, ISCSI_ERR_DATA_DGST);
- return -EIO;
- }
-
- /* iscsi hdr */
- rc = read_pdu_skb(conn, skb, 0, 0);
- if (rc <= 0)
- return rc;
-
- if (iscsi_tcp_recv_segment_is_hdr(tcp_conn))
- return 0;
-
- offset = rc;
- if (conn->hdrdgst_en)
- offset += ISCSI_DIGEST_SIZE;
-
- /* iscsi data */
- if (skb_ulp_mode(skb) & ULP2_FLAG_DATA_DDPED) {
- cxgb3i_rx_debug("skb 0x%p, opcode 0x%x, data %u, ddp'ed, "
- "itt 0x%x.\n",
- skb,
- tcp_conn->in.hdr->opcode & ISCSI_OPCODE_MASK,
- tcp_conn->in.datalen,
- ntohl(tcp_conn->in.hdr->itt));
- offloaded = 1;
- } else {
- cxgb3i_rx_debug("skb 0x%p, opcode 0x%x, data %u, NOT ddp'ed, "
- "itt 0x%x.\n",
- skb,
- tcp_conn->in.hdr->opcode & ISCSI_OPCODE_MASK,
- tcp_conn->in.datalen,
- ntohl(tcp_conn->in.hdr->itt));
- offset += sizeof(struct cpl_iscsi_hdr_norss);
- }
-
- rc = read_pdu_skb(conn, skb, offset, offloaded);
- if (rc < 0)
- return rc;
- else
- return 0;
-}
-
-/*
- * pdu transmit, interact with libiscsi_tcp
- */
-static inline void tx_skb_setmode(struct sk_buff *skb, int hcrc, int dcrc)
-{
- u8 submode = 0;
-
- if (hcrc)
- submode |= 1;
- if (dcrc)
- submode |= 2;
- skb_ulp_mode(skb) = (ULP_MODE_ISCSI << 4) | submode;
-}
-
-void cxgb3i_conn_cleanup_task(struct iscsi_task *task)
-{
- struct cxgb3i_task_data *tdata = task->dd_data +
- sizeof(struct iscsi_tcp_task);
-
- /* never reached the xmit task callout */
- if (tdata->skb)
- __kfree_skb(tdata->skb);
- memset(tdata, 0, sizeof(struct cxgb3i_task_data));
-
- /* MNC - Do we need a check in case this is called but
- * cxgb3i_conn_alloc_pdu has never been called on the task */
- cxgb3i_release_itt(task, task->hdr_itt);
- iscsi_tcp_cleanup_task(task);
-}
-
-static int sgl_seek_offset(struct scatterlist *sgl, unsigned int sgcnt,
- unsigned int offset, unsigned int *off,
- struct scatterlist **sgp)
-{
- int i;
- struct scatterlist *sg;
-
- for_each_sg(sgl, sg, sgcnt, i) {
- if (offset < sg->length) {
- *off = offset;
- *sgp = sg;
- return 0;
- }
- offset -= sg->length;
- }
- return -EFAULT;
-}
-
-static int sgl_read_to_frags(struct scatterlist *sg, unsigned int sgoffset,
- unsigned int dlen, skb_frag_t *frags,
- int frag_max)
-{
- unsigned int datalen = dlen;
- unsigned int sglen = sg->length - sgoffset;
- struct page *page = sg_page(sg);
- int i;
-
- i = 0;
- do {
- unsigned int copy;
-
- if (!sglen) {
- sg = sg_next(sg);
- if (!sg) {
- cxgb3i_log_error("%s, sg NULL, len %u/%u.\n",
- __func__, datalen, dlen);
- return -EINVAL;
- }
- sgoffset = 0;
- sglen = sg->length;
- page = sg_page(sg);
-
- }
- copy = min(datalen, sglen);
- if (i && page == frags[i - 1].page &&
- sgoffset + sg->offset ==
- frags[i - 1].page_offset + frags[i - 1].size) {
- frags[i - 1].size += copy;
- } else {
- if (i >= frag_max) {
- cxgb3i_log_error("%s, too many pages %u, "
- "dlen %u.\n", __func__,
- frag_max, dlen);
- return -EINVAL;
- }
-
- frags[i].page = page;
- frags[i].page_offset = sg->offset + sgoffset;
- frags[i].size = copy;
- i++;
- }
- datalen -= copy;
- sgoffset += copy;
- sglen -= copy;
- } while (datalen);
-
- return i;
-}
-
-int cxgb3i_conn_alloc_pdu(struct iscsi_task *task, u8 opcode)
-{
- struct iscsi_conn *conn = task->conn;
- struct iscsi_tcp_task *tcp_task = task->dd_data;
- struct cxgb3i_task_data *tdata = task->dd_data + sizeof(*tcp_task);
- struct scsi_cmnd *sc = task->sc;
- int headroom = SKB_TX_PDU_HEADER_LEN;
-
- tcp_task->dd_data = tdata;
- task->hdr = NULL;
-
- /* write command, need to send data pdus */
- if (skb_extra_headroom && (opcode == ISCSI_OP_SCSI_DATA_OUT ||
- (opcode == ISCSI_OP_SCSI_CMD &&
- (scsi_bidi_cmnd(sc) || sc->sc_data_direction == DMA_TO_DEVICE))))
- headroom += min(skb_extra_headroom, conn->max_xmit_dlength);
-
- tdata->skb = alloc_skb(TX_HEADER_LEN + headroom, GFP_ATOMIC);
- if (!tdata->skb)
- return -ENOMEM;
- skb_reserve(tdata->skb, TX_HEADER_LEN);
-
- cxgb3i_tx_debug("task 0x%p, opcode 0x%x, skb 0x%p.\n",
- task, opcode, tdata->skb);
-
- task->hdr = (struct iscsi_hdr *)tdata->skb->data;
- task->hdr_max = SKB_TX_PDU_HEADER_LEN;
-
- /* data_out uses scsi_cmd's itt */
- if (opcode != ISCSI_OP_SCSI_DATA_OUT)
- cxgb3i_reserve_itt(task, &task->hdr->itt);
-
- return 0;
-}
-
-int cxgb3i_conn_init_pdu(struct iscsi_task *task, unsigned int offset,
- unsigned int count)
-{
- struct iscsi_conn *conn = task->conn;
- struct iscsi_tcp_task *tcp_task = task->dd_data;
- struct cxgb3i_task_data *tdata = tcp_task->dd_data;
- struct sk_buff *skb = tdata->skb;
- unsigned int datalen = count;
- int i, padlen = iscsi_padding(count);
- struct page *pg;
-
- cxgb3i_tx_debug("task 0x%p,0x%p, offset %u, count %u, skb 0x%p.\n",
- task, task->sc, offset, count, skb);
-
- skb_put(skb, task->hdr_len);
- tx_skb_setmode(skb, conn->hdrdgst_en, datalen ? conn->datadgst_en : 0);
- if (!count)
- return 0;
-
- if (task->sc) {
- struct scsi_data_buffer *sdb = scsi_out(task->sc);
- struct scatterlist *sg = NULL;
- int err;
-
- tdata->offset = offset;
- tdata->count = count;
- err = sgl_seek_offset(sdb->table.sgl, sdb->table.nents,
- tdata->offset, &tdata->sgoffset, &sg);
- if (err < 0) {
- cxgb3i_log_warn("tpdu, sgl %u, bad offset %u/%u.\n",
- sdb->table.nents, tdata->offset,
- sdb->length);
- return err;
- }
- err = sgl_read_to_frags(sg, tdata->sgoffset, tdata->count,
- tdata->frags, MAX_PDU_FRAGS);
- if (err < 0) {
- cxgb3i_log_warn("tpdu, sgl %u, bad offset %u + %u.\n",
- sdb->table.nents, tdata->offset,
- tdata->count);
- return err;
- }
- tdata->nr_frags = err;
-
- if (tdata->nr_frags > MAX_SKB_FRAGS ||
- (padlen && tdata->nr_frags == MAX_SKB_FRAGS)) {
- char *dst = skb->data + task->hdr_len;
- skb_frag_t *frag = tdata->frags;
-
- /* data fits in the skb's headroom */
- for (i = 0; i < tdata->nr_frags; i++, frag++) {
- char *src = kmap_atomic(frag->page,
- KM_SOFTIRQ0);
-
- memcpy(dst, src+frag->page_offset, frag->size);
- dst += frag->size;
- kunmap_atomic(src, KM_SOFTIRQ0);
- }
- if (padlen) {
- memset(dst, 0, padlen);
- padlen = 0;
- }
- skb_put(skb, count + padlen);
- } else {
- /* data fit into frag_list */
- for (i = 0; i < tdata->nr_frags; i++)
- get_page(tdata->frags[i].page);
-
- memcpy(skb_shinfo(skb)->frags, tdata->frags,
- sizeof(skb_frag_t) * tdata->nr_frags);
- skb_shinfo(skb)->nr_frags = tdata->nr_frags;
- skb->len += count;
- skb->data_len += count;
- skb->truesize += count;
- }
-
- } else {
- pg = virt_to_page(task->data);
-
- get_page(pg);
- skb_fill_page_desc(skb, 0, pg, offset_in_page(task->data),
- count);
- skb->len += count;
- skb->data_len += count;
- skb->truesize += count;
- }
-
- if (padlen) {
- i = skb_shinfo(skb)->nr_frags;
- get_page(pad_page);
- skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, pad_page, 0,
- padlen);
-
- skb->data_len += padlen;
- skb->truesize += padlen;
- skb->len += padlen;
- }
-
- return 0;
-}
-
-int cxgb3i_conn_xmit_pdu(struct iscsi_task *task)
-{
- struct iscsi_tcp_conn *tcp_conn = task->conn->dd_data;
- struct cxgb3i_conn *cconn = tcp_conn->dd_data;
- struct iscsi_tcp_task *tcp_task = task->dd_data;
- struct cxgb3i_task_data *tdata = tcp_task->dd_data;
- struct sk_buff *skb = tdata->skb;
- unsigned int datalen;
- int err;
-
- if (!skb)
- return 0;
-
- datalen = skb->data_len;
- tdata->skb = NULL;
- err = cxgb3i_c3cn_send_pdus(cconn->cep->c3cn, skb);
- if (err > 0) {
- int pdulen = err;
-
- cxgb3i_tx_debug("task 0x%p, skb 0x%p, len %u/%u, rv %d.\n",
- task, skb, skb->len, skb->data_len, err);
-
- if (task->conn->hdrdgst_en)
- pdulen += ISCSI_DIGEST_SIZE;
- if (datalen && task->conn->datadgst_en)
- pdulen += ISCSI_DIGEST_SIZE;
-
- task->conn->txdata_octets += pdulen;
- return 0;
- }
-
- if (err == -EAGAIN || err == -ENOBUFS) {
- /* reset skb to send when we are called again */
- tdata->skb = skb;
- return err;
- }
-
- kfree_skb(skb);
- cxgb3i_tx_debug("itt 0x%x, skb 0x%p, len %u/%u, xmit err %d.\n",
- task->itt, skb, skb->len, skb->data_len, err);
- iscsi_conn_printk(KERN_ERR, task->conn, "xmit err %d.\n", err);
- iscsi_conn_failure(task->conn, ISCSI_ERR_XMIT_FAILED);
- return err;
-}
-
-int cxgb3i_pdu_init(void)
-{
- if (SKB_TX_HEADROOM > (512 * MAX_SKB_FRAGS))
- skb_extra_headroom = SKB_TX_HEADROOM;
- pad_page = alloc_page(GFP_KERNEL);
- if (!pad_page)
- return -ENOMEM;
- memset(page_address(pad_page), 0, PAGE_SIZE);
- return 0;
-}
-
-void cxgb3i_pdu_cleanup(void)
-{
- if (pad_page) {
- __free_page(pad_page);
- pad_page = NULL;
- }
-}
-
-void cxgb3i_conn_pdu_ready(struct s3_conn *c3cn)
-{
- struct sk_buff *skb;
- unsigned int read = 0;
- struct iscsi_conn *conn = c3cn->user_data;
- int err = 0;
-
- cxgb3i_rx_debug("cn 0x%p.\n", c3cn);
-
- read_lock(&c3cn->callback_lock);
- if (unlikely(!conn || conn->suspend_rx)) {
- cxgb3i_rx_debug("conn 0x%p, id %d, suspend_rx %lu!\n",
- conn, conn ? conn->id : 0xFF,
- conn ? conn->suspend_rx : 0xFF);
- read_unlock(&c3cn->callback_lock);
- return;
- }
- skb = skb_peek(&c3cn->receive_queue);
- while (!err && skb) {
- __skb_unlink(skb, &c3cn->receive_queue);
- read += skb_rx_pdulen(skb);
- cxgb3i_rx_debug("conn 0x%p, cn 0x%p, rx skb 0x%p, pdulen %u.\n",
- conn, c3cn, skb, skb_rx_pdulen(skb));
- err = cxgb3i_conn_read_pdu_skb(conn, skb);
- __kfree_skb(skb);
- skb = skb_peek(&c3cn->receive_queue);
- }
- read_unlock(&c3cn->callback_lock);
- c3cn->copied_seq += read;
- cxgb3i_c3cn_rx_credits(c3cn, read);
- conn->rxdata_octets += read;
-
- if (err) {
- cxgb3i_log_info("conn 0x%p rx failed err %d.\n", conn, err);
- iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
- }
-}
-
-void cxgb3i_conn_tx_open(struct s3_conn *c3cn)
-{
- struct iscsi_conn *conn = c3cn->user_data;
-
- cxgb3i_tx_debug("cn 0x%p.\n", c3cn);
- if (conn) {
- cxgb3i_tx_debug("cn 0x%p, cid %d.\n", c3cn, conn->id);
- iscsi_conn_queue_work(conn);
- }
-}
-
-void cxgb3i_conn_closing(struct s3_conn *c3cn)
-{
- struct iscsi_conn *conn;
-
- read_lock(&c3cn->callback_lock);
- conn = c3cn->user_data;
- if (conn && c3cn->state != C3CN_STATE_ESTABLISHED)
- iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
- read_unlock(&c3cn->callback_lock);
-}
diff --git a/drivers/scsi/cxgb3i/cxgb3i_pdu.h b/drivers/scsi/cxgb3i/cxgb3i_pdu.h
deleted file mode 100644
index 0770b23d90da..000000000000
--- a/drivers/scsi/cxgb3i/cxgb3i_pdu.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * cxgb3i_ulp2.h: Chelsio S3xx iSCSI driver.
- *
- * Copyright (c) 2008 Chelsio Communications, 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.
- *
- * Written by: Karen Xie (kxie@chelsio.com)
- */
-
-#ifndef __CXGB3I_ULP2_PDU_H__
-#define __CXGB3I_ULP2_PDU_H__
-
-struct cpl_iscsi_hdr_norss {
- union opcode_tid ot;
- u16 pdu_len_ddp;
- u16 len;
- u32 seq;
- u16 urg;
- u8 rsvd;
- u8 status;
-};
-
-struct cpl_rx_data_ddp_norss {
- union opcode_tid ot;
- u16 urg;
- u16 len;
- u32 seq;
- u32 nxt_seq;
- u32 ulp_crc;
- u32 ddp_status;
-};
-
-#define RX_DDP_STATUS_IPP_SHIFT 27 /* invalid pagepod */
-#define RX_DDP_STATUS_TID_SHIFT 26 /* tid mismatch */
-#define RX_DDP_STATUS_COLOR_SHIFT 25 /* color mismatch */
-#define RX_DDP_STATUS_OFFSET_SHIFT 24 /* offset mismatch */
-#define RX_DDP_STATUS_ULIMIT_SHIFT 23 /* ulimit error */
-#define RX_DDP_STATUS_TAG_SHIFT 22 /* tag mismatch */
-#define RX_DDP_STATUS_DCRC_SHIFT 21 /* dcrc error */
-#define RX_DDP_STATUS_HCRC_SHIFT 20 /* hcrc error */
-#define RX_DDP_STATUS_PAD_SHIFT 19 /* pad error */
-#define RX_DDP_STATUS_PPP_SHIFT 18 /* pagepod parity error */
-#define RX_DDP_STATUS_LLIMIT_SHIFT 17 /* llimit error */
-#define RX_DDP_STATUS_DDP_SHIFT 16 /* ddp'able */
-#define RX_DDP_STATUS_PMM_SHIFT 15 /* pagepod mismatch */
-
-#define ULP2_FLAG_DATA_READY 0x1
-#define ULP2_FLAG_DATA_DDPED 0x2
-#define ULP2_FLAG_HCRC_ERROR 0x10
-#define ULP2_FLAG_DCRC_ERROR 0x20
-#define ULP2_FLAG_PAD_ERROR 0x40
-
-void cxgb3i_conn_closing(struct s3_conn *c3cn);
-void cxgb3i_conn_pdu_ready(struct s3_conn *c3cn);
-void cxgb3i_conn_tx_open(struct s3_conn *c3cn);
-#endif
diff --git a/drivers/scsi/cxgbi/Kconfig b/drivers/scsi/cxgbi/Kconfig
new file mode 100644
index 000000000000..17eb5d522f42
--- /dev/null
+++ b/drivers/scsi/cxgbi/Kconfig
@@ -0,0 +1,2 @@
+source "drivers/scsi/cxgbi/cxgb3i/Kconfig"
+source "drivers/scsi/cxgbi/cxgb4i/Kconfig"
diff --git a/drivers/scsi/cxgbi/Makefile b/drivers/scsi/cxgbi/Makefile
new file mode 100644
index 000000000000..86007e344955
--- /dev/null
+++ b/drivers/scsi/cxgbi/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_SCSI_CXGB3_ISCSI) += libcxgbi.o cxgb3i/
+obj-$(CONFIG_SCSI_CXGB4_ISCSI) += libcxgbi.o cxgb4i/
diff --git a/drivers/scsi/cxgb3i/Kbuild b/drivers/scsi/cxgbi/cxgb3i/Kbuild
index 70d060b7ff4f..09dbf9efc8ea 100644
--- a/drivers/scsi/cxgb3i/Kbuild
+++ b/drivers/scsi/cxgbi/cxgb3i/Kbuild
@@ -1,4 +1,3 @@
EXTRA_CFLAGS += -I$(srctree)/drivers/net/cxgb3
-cxgb3i-y := cxgb3i_init.o cxgb3i_iscsi.o cxgb3i_pdu.o cxgb3i_offload.o cxgb3i_ddp.o
obj-$(CONFIG_SCSI_CXGB3_ISCSI) += cxgb3i.o
diff --git a/drivers/scsi/cxgb3i/Kconfig b/drivers/scsi/cxgbi/cxgb3i/Kconfig
index bfdcaf5c9c57..5cf4e9831f1b 100644
--- a/drivers/scsi/cxgb3i/Kconfig
+++ b/drivers/scsi/cxgbi/cxgb3i/Kconfig
@@ -1,7 +1,7 @@
config SCSI_CXGB3_ISCSI
- tristate "Chelsio S3xx iSCSI support"
+ tristate "Chelsio T3 iSCSI support"
depends on CHELSIO_T3_DEPENDS
select CHELSIO_T3
select SCSI_ISCSI_ATTRS
---help---
- This driver supports iSCSI offload for the Chelsio S3 series devices.
+ This driver supports iSCSI offload for the Chelsio T3 devices.
diff --git a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
new file mode 100644
index 000000000000..a129a170b47b
--- /dev/null
+++ b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
@@ -0,0 +1,1465 @@
+/*
+ * cxgb3i_offload.c: Chelsio S3xx iscsi offloaded tcp connection management
+ *
+ * Copyright (C) 2003-2008 Chelsio Communications. All rights reserved.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the LICENSE file included in this
+ * release for licensing terms and conditions.
+ *
+ * Written by: Dimitris Michailidis (dm@chelsio.com)
+ * Karen Xie (kxie@chelsio.com)
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <scsi/scsi_host.h>
+
+#include "common.h"
+#include "t3_cpl.h"
+#include "t3cdev.h"
+#include "cxgb3_defs.h"
+#include "cxgb3_ctl_defs.h"
+#include "cxgb3_offload.h"
+#include "firmware_exports.h"
+#include "cxgb3i.h"
+
+static unsigned int dbg_level;
+#include "../libcxgbi.h"
+
+#define DRV_MODULE_NAME "cxgb3i"
+#define DRV_MODULE_DESC "Chelsio T3 iSCSI Driver"
+#define DRV_MODULE_VERSION "2.0.0"
+#define DRV_MODULE_RELDATE "Jun. 2010"
+
+static char version[] =
+ DRV_MODULE_DESC " " DRV_MODULE_NAME
+ " v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+
+MODULE_AUTHOR("Chelsio Communications, Inc.");
+MODULE_DESCRIPTION(DRV_MODULE_DESC);
+MODULE_VERSION(DRV_MODULE_VERSION);
+MODULE_LICENSE("GPL");
+
+module_param(dbg_level, uint, 0644);
+MODULE_PARM_DESC(dbg_level, "debug flag (default=0)");
+
+static int cxgb3i_rcv_win = 256 * 1024;
+module_param(cxgb3i_rcv_win, int, 0644);
+MODULE_PARM_DESC(cxgb3i_rcv_win, "TCP receive window in bytes (default=256KB)");
+
+static int cxgb3i_snd_win = 128 * 1024;
+module_param(cxgb3i_snd_win, int, 0644);
+MODULE_PARM_DESC(cxgb3i_snd_win, "TCP send window in bytes (default=128KB)");
+
+static int cxgb3i_rx_credit_thres = 10 * 1024;
+module_param(cxgb3i_rx_credit_thres, int, 0644);
+MODULE_PARM_DESC(rx_credit_thres,
+ "RX credits return threshold in bytes (default=10KB)");
+
+static unsigned int cxgb3i_max_connect = 8 * 1024;
+module_param(cxgb3i_max_connect, uint, 0644);
+MODULE_PARM_DESC(cxgb3i_max_connect, "Max. # of connections (default=8092)");
+
+static unsigned int cxgb3i_sport_base = 20000;
+module_param(cxgb3i_sport_base, uint, 0644);
+MODULE_PARM_DESC(cxgb3i_sport_base, "starting port number (default=20000)");
+
+static void cxgb3i_dev_open(struct t3cdev *);
+static void cxgb3i_dev_close(struct t3cdev *);
+static void cxgb3i_dev_event_handler(struct t3cdev *, u32, u32);
+
+static struct cxgb3_client t3_client = {
+ .name = DRV_MODULE_NAME,
+ .handlers = cxgb3i_cpl_handlers,
+ .add = cxgb3i_dev_open,
+ .remove = cxgb3i_dev_close,
+ .event_handler = cxgb3i_dev_event_handler,
+};
+
+static struct scsi_host_template cxgb3i_host_template = {
+ .module = THIS_MODULE,
+ .name = DRV_MODULE_NAME,
+ .proc_name = DRV_MODULE_NAME,
+ .can_queue = CXGB3I_SCSI_HOST_QDEPTH,
+ .queuecommand = iscsi_queuecommand,
+ .change_queue_depth = iscsi_change_queue_depth,
+ .sg_tablesize = SG_ALL,
+ .max_sectors = 0xFFFF,
+ .cmd_per_lun = ISCSI_DEF_CMD_PER_LUN,
+ .eh_abort_handler = iscsi_eh_abort,
+ .eh_device_reset_handler = iscsi_eh_device_reset,
+ .eh_target_reset_handler = iscsi_eh_recover_target,
+ .target_alloc = iscsi_target_alloc,
+ .use_clustering = DISABLE_CLUSTERING,
+ .this_id = -1,
+};
+
+static struct iscsi_transport cxgb3i_iscsi_transport = {
+ .owner = THIS_MODULE,
+ .name = DRV_MODULE_NAME,
+ /* owner and name should be set already */
+ .caps = CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST
+ | CAP_DATADGST | CAP_DIGEST_OFFLOAD |
+ CAP_PADDING_OFFLOAD,
+ .param_mask = ISCSI_MAX_RECV_DLENGTH | ISCSI_MAX_XMIT_DLENGTH |
+ ISCSI_HDRDGST_EN | ISCSI_DATADGST_EN |
+ ISCSI_INITIAL_R2T_EN | ISCSI_MAX_R2T |
+ ISCSI_IMM_DATA_EN | ISCSI_FIRST_BURST |
+ ISCSI_MAX_BURST | ISCSI_PDU_INORDER_EN |
+ ISCSI_DATASEQ_INORDER_EN | ISCSI_ERL |
+ ISCSI_CONN_PORT | ISCSI_CONN_ADDRESS |
+ ISCSI_EXP_STATSN | ISCSI_PERSISTENT_PORT |
+ ISCSI_PERSISTENT_ADDRESS |
+ ISCSI_TARGET_NAME | ISCSI_TPGT |
+ ISCSI_USERNAME | ISCSI_PASSWORD |
+ ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
+ ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
+ ISCSI_LU_RESET_TMO | ISCSI_TGT_RESET_TMO |
+ ISCSI_PING_TMO | ISCSI_RECV_TMO |
+ ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
+ .host_param_mask = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
+ ISCSI_HOST_INITIATOR_NAME |
+ ISCSI_HOST_NETDEV_NAME,
+ .get_host_param = cxgbi_get_host_param,
+ .set_host_param = cxgbi_set_host_param,
+ /* session management */
+ .create_session = cxgbi_create_session,
+ .destroy_session = cxgbi_destroy_session,
+ .get_session_param = iscsi_session_get_param,
+ /* connection management */
+ .create_conn = cxgbi_create_conn,
+ .bind_conn = cxgbi_bind_conn,
+ .destroy_conn = iscsi_tcp_conn_teardown,
+ .start_conn = iscsi_conn_start,
+ .stop_conn = iscsi_conn_stop,
+ .get_conn_param = cxgbi_get_conn_param,
+ .set_param = cxgbi_set_conn_param,
+ .get_stats = cxgbi_get_conn_stats,
+ /* pdu xmit req from user space */
+ .send_pdu = iscsi_conn_send_pdu,
+ /* task */
+ .init_task = iscsi_tcp_task_init,
+ .xmit_task = iscsi_tcp_task_xmit,
+ .cleanup_task = cxgbi_cleanup_task,
+ /* pdu */
+ .alloc_pdu = cxgbi_conn_alloc_pdu,
+ .init_pdu = cxgbi_conn_init_pdu,
+ .xmit_pdu = cxgbi_conn_xmit_pdu,
+ .parse_pdu_itt = cxgbi_parse_pdu_itt,
+ /* TCP connect/disconnect */
+ .ep_connect = cxgbi_ep_connect,
+ .ep_poll = cxgbi_ep_poll,
+ .ep_disconnect = cxgbi_ep_disconnect,
+ /* Error recovery timeout call */
+ .session_recovery_timedout = iscsi_session_recovery_timedout,
+};
+
+static struct scsi_transport_template *cxgb3i_stt;
+
+/*
+ * CPL (Chelsio Protocol Language) defines a message passing interface between
+ * the host driver and Chelsio asic.
+ * The section below implments CPLs that related to iscsi tcp connection
+ * open/close/abort and data send/receive.
+ */
+
+static int push_tx_frames(struct cxgbi_sock *csk, int req_completion);
+
+static void send_act_open_req(struct cxgbi_sock *csk, struct sk_buff *skb,
+ const struct l2t_entry *e)
+{
+ unsigned int wscale = cxgbi_sock_compute_wscale(cxgb3i_rcv_win);
+ struct cpl_act_open_req *req = (struct cpl_act_open_req *)skb->head;
+
+ skb->priority = CPL_PRIORITY_SETUP;
+
+ req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
+ OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_ACT_OPEN_REQ, csk->atid));
+ req->local_port = csk->saddr.sin_port;
+ req->peer_port = csk->daddr.sin_port;
+ req->local_ip = csk->saddr.sin_addr.s_addr;
+ req->peer_ip = csk->daddr.sin_addr.s_addr;
+
+ req->opt0h = htonl(V_KEEP_ALIVE(1) | F_TCAM_BYPASS |
+ V_WND_SCALE(wscale) | V_MSS_IDX(csk->mss_idx) |
+ V_L2T_IDX(e->idx) | V_TX_CHANNEL(e->smt_idx));
+ req->opt0l = htonl(V_ULP_MODE(ULP2_MODE_ISCSI) |
+ V_RCV_BUFSIZ(cxgb3i_rcv_win>>10));
+
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+ "csk 0x%p,%u,0x%lx,%u, %pI4:%u-%pI4:%u, %u,%u,%u.\n",
+ csk, csk->state, csk->flags, csk->atid,
+ &req->local_ip, ntohs(req->local_port),
+ &req->peer_ip, ntohs(req->peer_port),
+ csk->mss_idx, e->idx, e->smt_idx);
+
+ l2t_send(csk->cdev->lldev, skb, csk->l2t);
+}
+
+static inline void act_open_arp_failure(struct t3cdev *dev, struct sk_buff *skb)
+{
+ cxgbi_sock_act_open_req_arp_failure(NULL, skb);
+}
+
+/*
+ * CPL connection close request: host ->
+ *
+ * Close a connection by sending a CPL_CLOSE_CON_REQ message and queue it to
+ * the write queue (i.e., after any unsent txt data).
+ */
+static void send_close_req(struct cxgbi_sock *csk)
+{
+ struct sk_buff *skb = csk->cpl_close;
+ struct cpl_close_con_req *req = (struct cpl_close_con_req *)skb->head;
+ unsigned int tid = csk->tid;
+
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+ "csk 0x%p,%u,0x%lx,%u.\n",
+ csk, csk->state, csk->flags, csk->tid);
+
+ csk->cpl_close = NULL;
+ req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_CLOSE_CON));
+ req->wr.wr_lo = htonl(V_WR_TID(tid));
+ OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_CLOSE_CON_REQ, tid));
+ req->rsvd = htonl(csk->write_seq);
+
+ cxgbi_sock_skb_entail(csk, skb);
+ if (csk->state >= CTP_ESTABLISHED)
+ push_tx_frames(csk, 1);
+}
+
+/*
+ * CPL connection abort request: host ->
+ *
+ * Send an ABORT_REQ message. Makes sure we do not send multiple ABORT_REQs
+ * for the same connection and also that we do not try to send a message
+ * after the connection has closed.
+ */
+static void abort_arp_failure(struct t3cdev *tdev, struct sk_buff *skb)
+{
+ struct cpl_abort_req *req = cplhdr(skb);
+
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+ "t3dev 0x%p, tid %u, skb 0x%p.\n",
+ tdev, GET_TID(req), skb);
+ req->cmd = CPL_ABORT_NO_RST;
+ cxgb3_ofld_send(tdev, skb);
+}
+
+static void send_abort_req(struct cxgbi_sock *csk)
+{
+ struct sk_buff *skb = csk->cpl_abort_req;
+ struct cpl_abort_req *req;
+
+ if (unlikely(csk->state == CTP_ABORTING || !skb))
+ return;
+ cxgbi_sock_set_state(csk, CTP_ABORTING);
+ cxgbi_sock_set_flag(csk, CTPF_ABORT_RPL_PENDING);
+ /* Purge the send queue so we don't send anything after an abort. */
+ cxgbi_sock_purge_write_queue(csk);
+
+ csk->cpl_abort_req = NULL;
+ req = (struct cpl_abort_req *)skb->head;
+ skb->priority = CPL_PRIORITY_DATA;
+ set_arp_failure_handler(skb, abort_arp_failure);
+ req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_HOST_ABORT_CON_REQ));
+ req->wr.wr_lo = htonl(V_WR_TID(csk->tid));
+ OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_ABORT_REQ, csk->tid));
+ req->rsvd0 = htonl(csk->snd_nxt);
+ req->rsvd1 = !cxgbi_sock_flag(csk, CTPF_TX_DATA_SENT);
+ req->cmd = CPL_ABORT_SEND_RST;
+
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+ "csk 0x%p,%u,0x%lx,%u, snd_nxt %u, 0x%x.\n",
+ csk, csk->state, csk->flags, csk->tid, csk->snd_nxt,
+ req->rsvd1);
+
+ l2t_send(csk->cdev->lldev, skb, csk->l2t);
+}
+
+/*
+ * CPL connection abort reply: host ->
+ *
+ * Send an ABORT_RPL message in response of the ABORT_REQ received.
+ */
+static void send_abort_rpl(struct cxgbi_sock *csk, int rst_status)
+{
+ struct sk_buff *skb = csk->cpl_abort_rpl;
+ struct cpl_abort_rpl *rpl = (struct cpl_abort_rpl *)skb->head;
+
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+ "csk 0x%p,%u,0x%lx,%u, status %d.\n",
+ csk, csk->state, csk->flags, csk->tid, rst_status);
+
+ csk->cpl_abort_rpl = NULL;
+ skb->priority = CPL_PRIORITY_DATA;
+ rpl->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_HOST_ABORT_CON_RPL));
+ rpl->wr.wr_lo = htonl(V_WR_TID(csk->tid));
+ OPCODE_TID(rpl) = htonl(MK_OPCODE_TID(CPL_ABORT_RPL, csk->tid));
+ rpl->cmd = rst_status;
+ cxgb3_ofld_send(csk->cdev->lldev, skb);
+}
+
+/*
+ * CPL connection rx data ack: host ->
+ * Send RX credits through an RX_DATA_ACK CPL message. Returns the number of
+ * credits sent.
+ */
+static u32 send_rx_credits(struct cxgbi_sock *csk, u32 credits)
+{
+ struct sk_buff *skb;
+ struct cpl_rx_data_ack *req;
+ u32 dack = F_RX_DACK_CHANGE | V_RX_DACK_MODE(1);
+
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_PDU_RX,
+ "csk 0x%p,%u,0x%lx,%u, credit %u, dack %u.\n",
+ csk, csk->state, csk->flags, csk->tid, credits, dack);
+
+ skb = alloc_wr(sizeof(*req), 0, GFP_ATOMIC);
+ if (!skb) {
+ pr_info("csk 0x%p, credit %u, OOM.\n", csk, credits);
+ return 0;
+ }
+ req = (struct cpl_rx_data_ack *)skb->head;
+ req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
+ OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_RX_DATA_ACK, csk->tid));
+ req->credit_dack = htonl(F_RX_DACK_CHANGE | V_RX_DACK_MODE(1) |
+ V_RX_CREDITS(credits));
+ skb->priority = CPL_PRIORITY_ACK;
+ cxgb3_ofld_send(csk->cdev->lldev, skb);
+ return credits;
+}
+
+/*
+ * CPL connection tx data: host ->
+ *
+ * Send iscsi PDU via TX_DATA CPL message. Returns the number of
+ * credits sent.
+ * Each TX_DATA consumes work request credit (wrs), so we need to keep track of
+ * how many we've used so far and how many are pending (i.e., yet ack'ed by T3).
+ */
+
+static unsigned int wrlen __read_mostly;
+static unsigned int skb_wrs[SKB_WR_LIST_SIZE] __read_mostly;
+
+static void init_wr_tab(unsigned int wr_len)
+{
+ int i;
+
+ if (skb_wrs[1]) /* already initialized */
+ return;
+ for (i = 1; i < SKB_WR_LIST_SIZE; i++) {
+ int sgl_len = (3 * i) / 2 + (i & 1);
+
+ sgl_len += 3;
+ skb_wrs[i] = (sgl_len <= wr_len
+ ? 1 : 1 + (sgl_len - 2) / (wr_len - 1));
+ }
+ wrlen = wr_len * 8;
+}
+
+static inline void make_tx_data_wr(struct cxgbi_sock *csk, struct sk_buff *skb,
+ int len, int req_completion)
+{
+ struct tx_data_wr *req;
+ struct l2t_entry *l2t = csk->l2t;
+
+ skb_reset_transport_header(skb);
+ req = (struct tx_data_wr *)__skb_push(skb, sizeof(*req));
+ req->wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_TX_DATA) |
+ (req_completion ? F_WR_COMPL : 0));
+ req->wr_lo = htonl(V_WR_TID(csk->tid));
+ /* len includes the length of any HW ULP additions */
+ req->len = htonl(len);
+ /* V_TX_ULP_SUBMODE sets both the mode and submode */
+ req->flags = htonl(V_TX_ULP_SUBMODE(cxgbi_skcb_ulp_mode(skb)) |
+ V_TX_SHOVE((skb_peek(&csk->write_queue) ? 0 : 1)));
+ req->sndseq = htonl(csk->snd_nxt);
+ req->param = htonl(V_TX_PORT(l2t->smt_idx));
+
+ if (!cxgbi_sock_flag(csk, CTPF_TX_DATA_SENT)) {
+ req->flags |= htonl(V_TX_ACK_PAGES(2) | F_TX_INIT |
+ V_TX_CPU_IDX(csk->rss_qid));
+ /* sendbuffer is in units of 32KB. */
+ req->param |= htonl(V_TX_SNDBUF(cxgb3i_snd_win >> 15));
+ cxgbi_sock_set_flag(csk, CTPF_TX_DATA_SENT);
+ }
+}
+
+/**
+ * push_tx_frames -- start transmit
+ * @c3cn: the offloaded connection
+ * @req_completion: request wr_ack or not
+ *
+ * Prepends TX_DATA_WR or CPL_CLOSE_CON_REQ headers to buffers waiting in a
+ * connection's send queue and sends them on to T3. Must be called with the
+ * connection's lock held. Returns the amount of send buffer space that was
+ * freed as a result of sending queued data to T3.
+ */
+
+static void arp_failure_skb_discard(struct t3cdev *dev, struct sk_buff *skb)
+{
+ kfree_skb(skb);
+}
+
+static int push_tx_frames(struct cxgbi_sock *csk, int req_completion)
+{
+ int total_size = 0;
+ struct sk_buff *skb;
+
+ if (unlikely(csk->state < CTP_ESTABLISHED ||
+ csk->state == CTP_CLOSE_WAIT_1 || csk->state >= CTP_ABORTING)) {
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_PDU_TX,
+ "csk 0x%p,%u,0x%lx,%u, in closing state.\n",
+ csk, csk->state, csk->flags, csk->tid);
+ return 0;
+ }
+
+ while (csk->wr_cred && (skb = skb_peek(&csk->write_queue)) != NULL) {
+ int len = skb->len; /* length before skb_push */
+ int frags = skb_shinfo(skb)->nr_frags + (len != skb->data_len);
+ int wrs_needed = skb_wrs[frags];
+
+ if (wrs_needed > 1 && len + sizeof(struct tx_data_wr) <= wrlen)
+ wrs_needed = 1;
+
+ WARN_ON(frags >= SKB_WR_LIST_SIZE || wrs_needed < 1);
+
+ if (csk->wr_cred < wrs_needed) {
+ log_debug(1 << CXGBI_DBG_PDU_TX,
+ "csk 0x%p, skb len %u/%u, frag %u, wr %d<%u.\n",
+ csk, skb->len, skb->data_len, frags,
+ wrs_needed, csk->wr_cred);
+ break;
+ }
+
+ __skb_unlink(skb, &csk->write_queue);
+ skb->priority = CPL_PRIORITY_DATA;
+ skb->csum = wrs_needed; /* remember this until the WR_ACK */
+ csk->wr_cred -= wrs_needed;
+ csk->wr_una_cred += wrs_needed;
+ cxgbi_sock_enqueue_wr(csk, skb);
+
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_PDU_TX,
+ "csk 0x%p, enqueue, skb len %u/%u, frag %u, wr %d, "
+ "left %u, unack %u.\n",
+ csk, skb->len, skb->data_len, frags, skb->csum,
+ csk->wr_cred, csk->wr_una_cred);
+
+ if (likely(cxgbi_skcb_test_flag(skb, SKCBF_TX_NEED_HDR))) {
+ if ((req_completion &&
+ csk->wr_una_cred == wrs_needed) ||
+ csk->wr_una_cred >= csk->wr_max_cred / 2) {
+ req_completion = 1;
+ csk->wr_una_cred = 0;
+ }
+ len += cxgbi_ulp_extra_len(cxgbi_skcb_ulp_mode(skb));
+ make_tx_data_wr(csk, skb, len, req_completion);
+ csk->snd_nxt += len;
+ cxgbi_skcb_clear_flag(skb, SKCBF_TX_NEED_HDR);
+ }
+ total_size += skb->truesize;
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_PDU_TX,
+ "csk 0x%p, tid 0x%x, send skb 0x%p.\n",
+ csk, csk->tid, skb);
+ set_arp_failure_handler(skb, arp_failure_skb_discard);
+ l2t_send(csk->cdev->lldev, skb, csk->l2t);
+ }
+ return total_size;
+}
+
+/*
+ * Process a CPL_ACT_ESTABLISH message: -> host
+ * Updates connection state from an active establish CPL message. Runs with
+ * the connection lock held.
+ */
+
+static inline void free_atid(struct cxgbi_sock *csk)
+{
+ if (cxgbi_sock_flag(csk, CTPF_HAS_ATID)) {
+ cxgb3_free_atid(csk->cdev->lldev, csk->atid);
+ cxgbi_sock_clear_flag(csk, CTPF_HAS_ATID);
+ cxgbi_sock_put(csk);
+ }
+}
+
+static int do_act_establish(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+{
+ struct cxgbi_sock *csk = ctx;
+ struct cpl_act_establish *req = cplhdr(skb);
+ unsigned int tid = GET_TID(req);
+ unsigned int atid = G_PASS_OPEN_TID(ntohl(req->tos_tid));
+ u32 rcv_isn = ntohl(req->rcv_isn); /* real RCV_ISN + 1 */
+
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+ "atid 0x%x,tid 0x%x, csk 0x%p,%u,0x%lx, isn %u.\n",
+ atid, atid, csk, csk->state, csk->flags, rcv_isn);
+
+ cxgbi_sock_get(csk);
+ cxgbi_sock_set_flag(csk, CTPF_HAS_TID);
+ csk->tid = tid;
+ cxgb3_insert_tid(csk->cdev->lldev, &t3_client, csk, tid);
+
+ free_atid(csk);
+
+ csk->rss_qid = G_QNUM(ntohs(skb->csum));
+
+ spin_lock_bh(&csk->lock);
+ if (csk->retry_timer.function) {
+ del_timer(&csk->retry_timer);
+ csk->retry_timer.function = NULL;
+ }
+
+ if (unlikely(csk->state != CTP_ACTIVE_OPEN))
+ pr_info("csk 0x%p,%u,0x%lx,%u, got EST.\n",
+ csk, csk->state, csk->flags, csk->tid);
+
+ csk->copied_seq = csk->rcv_wup = csk->rcv_nxt = rcv_isn;
+ if (cxgb3i_rcv_win > (M_RCV_BUFSIZ << 10))
+ csk->rcv_wup -= cxgb3i_rcv_win - (M_RCV_BUFSIZ << 10);
+
+ cxgbi_sock_established(csk, ntohl(req->snd_isn), ntohs(req->tcp_opt));
+
+ if (unlikely(cxgbi_sock_flag(csk, CTPF_ACTIVE_CLOSE_NEEDED)))
+ /* upper layer has requested closing */
+ send_abort_req(csk);
+ else {
+ if (skb_queue_len(&csk->write_queue))
+ push_tx_frames(csk, 1);
+ cxgbi_conn_tx_open(csk);
+ }
+
+ spin_unlock_bh(&csk->lock);
+ __kfree_skb(skb);
+ return 0;
+}
+
+/*
+ * Process a CPL_ACT_OPEN_RPL message: -> host
+ * Handle active open failures.
+ */
+static int act_open_rpl_status_to_errno(int status)
+{
+ switch (status) {
+ case CPL_ERR_CONN_RESET:
+ return -ECONNREFUSED;
+ case CPL_ERR_ARP_MISS:
+ return -EHOSTUNREACH;
+ case CPL_ERR_CONN_TIMEDOUT:
+ return -ETIMEDOUT;
+ case CPL_ERR_TCAM_FULL:
+ return -ENOMEM;
+ case CPL_ERR_CONN_EXIST:
+ return -EADDRINUSE;
+ default:
+ return -EIO;
+ }
+}
+
+static void act_open_retry_timer(unsigned long data)
+{
+ struct sk_buff *skb;
+ struct cxgbi_sock *csk = (struct cxgbi_sock *)data;
+
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+ "csk 0x%p,%u,0x%lx,%u.\n",
+ csk, csk->state, csk->flags, csk->tid);
+
+ cxgbi_sock_get(csk);
+ spin_lock_bh(&csk->lock);
+ skb = alloc_wr(sizeof(struct cpl_act_open_req), 0, GFP_ATOMIC);
+ if (!skb)
+ cxgbi_sock_fail_act_open(csk, -ENOMEM);
+ else {
+ skb->sk = (struct sock *)csk;
+ set_arp_failure_handler(skb, act_open_arp_failure);
+ send_act_open_req(csk, skb, csk->l2t);
+ }
+ spin_unlock_bh(&csk->lock);
+ cxgbi_sock_put(csk);
+}
+
+static int do_act_open_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+{
+ struct cxgbi_sock *csk = ctx;
+ struct cpl_act_open_rpl *rpl = cplhdr(skb);
+
+ pr_info("csk 0x%p,%u,0x%lx,%u, status %u, %pI4:%u-%pI4:%u.\n",
+ csk, csk->state, csk->flags, csk->atid, rpl->status,
+ &csk->saddr.sin_addr.s_addr, ntohs(csk->saddr.sin_port),
+ &csk->daddr.sin_addr.s_addr, ntohs(csk->daddr.sin_port));
+
+ if (rpl->status != CPL_ERR_TCAM_FULL &&
+ rpl->status != CPL_ERR_CONN_EXIST &&
+ rpl->status != CPL_ERR_ARP_MISS)
+ cxgb3_queue_tid_release(tdev, GET_TID(rpl));
+
+ cxgbi_sock_get(csk);
+ spin_lock_bh(&csk->lock);
+ if (rpl->status == CPL_ERR_CONN_EXIST &&
+ csk->retry_timer.function != act_open_retry_timer) {
+ csk->retry_timer.function = act_open_retry_timer;
+ mod_timer(&csk->retry_timer, jiffies + HZ / 2);
+ } else
+ cxgbi_sock_fail_act_open(csk,
+ act_open_rpl_status_to_errno(rpl->status));
+
+ spin_unlock_bh(&csk->lock);
+ cxgbi_sock_put(csk);
+ __kfree_skb(skb);
+ return 0;
+}
+
+/*
+ * Process PEER_CLOSE CPL messages: -> host
+ * Handle peer FIN.
+ */
+static int do_peer_close(struct t3cdev *cdev, struct sk_buff *skb, void *ctx)
+{
+ struct cxgbi_sock *csk = ctx;
+
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+ "csk 0x%p,%u,0x%lx,%u.\n",
+ csk, csk->state, csk->flags, csk->tid);
+
+ cxgbi_sock_rcv_peer_close(csk);
+ __kfree_skb(skb);
+ return 0;
+}
+
+/*
+ * Process CLOSE_CONN_RPL CPL message: -> host
+ * Process a peer ACK to our FIN.
+ */
+static int do_close_con_rpl(struct t3cdev *cdev, struct sk_buff *skb,
+ void *ctx)
+{
+ struct cxgbi_sock *csk = ctx;
+ struct cpl_close_con_rpl *rpl = cplhdr(skb);
+
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+ "csk 0x%p,%u,0x%lx,%u, snxt %u.\n",
+ csk, csk->state, csk->flags, csk->tid, ntohl(rpl->snd_nxt));
+
+ cxgbi_sock_rcv_close_conn_rpl(csk, ntohl(rpl->snd_nxt));
+ __kfree_skb(skb);
+ return 0;
+}
+
+/*
+ * Process ABORT_REQ_RSS CPL message: -> host
+ * Process abort requests. If we are waiting for an ABORT_RPL we ignore this
+ * request except that we need to reply to it.
+ */
+
+static int abort_status_to_errno(struct cxgbi_sock *csk, int abort_reason,
+ int *need_rst)
+{
+ switch (abort_reason) {
+ case CPL_ERR_BAD_SYN: /* fall through */
+ case CPL_ERR_CONN_RESET:
+ return csk->state > CTP_ESTABLISHED ? -EPIPE : -ECONNRESET;
+ case CPL_ERR_XMIT_TIMEDOUT:
+ case CPL_ERR_PERSIST_TIMEDOUT:
+ case CPL_ERR_FINWAIT2_TIMEDOUT:
+ case CPL_ERR_KEEPALIVE_TIMEDOUT:
+ return -ETIMEDOUT;
+ default:
+ return -EIO;
+ }
+}
+
+static int do_abort_req(struct t3cdev *cdev, struct sk_buff *skb, void *ctx)
+{
+ const struct cpl_abort_req_rss *req = cplhdr(skb);
+ struct cxgbi_sock *csk = ctx;
+ int rst_status = CPL_ABORT_NO_RST;
+
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+ "csk 0x%p,%u,0x%lx,%u.\n",
+ csk, csk->state, csk->flags, csk->tid);
+
+ if (req->status == CPL_ERR_RTX_NEG_ADVICE ||
+ req->status == CPL_ERR_PERSIST_NEG_ADVICE) {
+ goto done;
+ }
+
+ cxgbi_sock_get(csk);
+ spin_lock_bh(&csk->lock);
+
+ if (!cxgbi_sock_flag(csk, CTPF_ABORT_REQ_RCVD)) {
+ cxgbi_sock_set_flag(csk, CTPF_ABORT_REQ_RCVD);
+ cxgbi_sock_set_state(csk, CTP_ABORTING);
+ goto out;
+ }
+
+ cxgbi_sock_clear_flag(csk, CTPF_ABORT_REQ_RCVD);
+ send_abort_rpl(csk, rst_status);
+
+ if (!cxgbi_sock_flag(csk, CTPF_ABORT_RPL_PENDING)) {
+ csk->err = abort_status_to_errno(csk, req->status, &rst_status);
+ cxgbi_sock_closed(csk);
+ }
+
+out:
+ spin_unlock_bh(&csk->lock);
+ cxgbi_sock_put(csk);
+done:
+ __kfree_skb(skb);
+ return 0;
+}
+
+/*
+ * Process ABORT_RPL_RSS CPL message: -> host
+ * Process abort replies. We only process these messages if we anticipate
+ * them as the coordination between SW and HW in this area is somewhat lacking
+ * and sometimes we get ABORT_RPLs after we are done with the connection that
+ * originated the ABORT_REQ.
+ */
+static int do_abort_rpl(struct t3cdev *cdev, struct sk_buff *skb, void *ctx)
+{
+ struct cpl_abort_rpl_rss *rpl = cplhdr(skb);
+ struct cxgbi_sock *csk = ctx;
+
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+ "status 0x%x, csk 0x%p, s %u, 0x%lx.\n",
+ rpl->status, csk, csk ? csk->state : 0,
+ csk ? csk->flags : 0UL);
+ /*
+ * Ignore replies to post-close aborts indicating that the abort was
+ * requested too late. These connections are terminated when we get
+ * PEER_CLOSE or CLOSE_CON_RPL and by the time the abort_rpl_rss
+ * arrives the TID is either no longer used or it has been recycled.
+ */
+ if (rpl->status == CPL_ERR_ABORT_FAILED)
+ goto rel_skb;
+ /*
+ * Sometimes we've already closed the connection, e.g., a post-close
+ * abort races with ABORT_REQ_RSS, the latter frees the connection
+ * expecting the ABORT_REQ will fail with CPL_ERR_ABORT_FAILED,
+ * but FW turns the ABORT_REQ into a regular one and so we get
+ * ABORT_RPL_RSS with status 0 and no connection.
+ */
+ if (csk)
+ cxgbi_sock_rcv_abort_rpl(csk);
+rel_skb:
+ __kfree_skb(skb);
+ return 0;
+}
+
+/*
+ * Process RX_ISCSI_HDR CPL message: -> host
+ * Handle received PDUs, the payload could be DDP'ed. If not, the payload
+ * follow after the bhs.
+ */
+static int do_iscsi_hdr(struct t3cdev *t3dev, struct sk_buff *skb, void *ctx)
+{
+ struct cxgbi_sock *csk = ctx;
+ struct cpl_iscsi_hdr *hdr_cpl = cplhdr(skb);
+ struct cpl_iscsi_hdr_norss data_cpl;
+ struct cpl_rx_data_ddp_norss ddp_cpl;
+ unsigned int hdr_len, data_len, status;
+ unsigned int len;
+ int err;
+
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_PDU_RX,
+ "csk 0x%p,%u,0x%lx,%u, skb 0x%p,%u.\n",
+ csk, csk->state, csk->flags, csk->tid, skb, skb->len);
+
+ spin_lock_bh(&csk->lock);
+
+ if (unlikely(csk->state >= CTP_PASSIVE_CLOSE)) {
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+ "csk 0x%p,%u,0x%lx,%u, bad state.\n",
+ csk, csk->state, csk->flags, csk->tid);
+ if (csk->state != CTP_ABORTING)
+ goto abort_conn;
+ else
+ goto discard;
+ }
+
+ cxgbi_skcb_tcp_seq(skb) = ntohl(hdr_cpl->seq);
+ cxgbi_skcb_flags(skb) = 0;
+
+ skb_reset_transport_header(skb);
+ __skb_pull(skb, sizeof(struct cpl_iscsi_hdr));
+
+ len = hdr_len = ntohs(hdr_cpl->len);
+ /* msg coalesce is off or not enough data received */
+ if (skb->len <= hdr_len) {
+ pr_err("%s: tid %u, CPL_ISCSI_HDR, skb len %u < %u.\n",
+ csk->cdev->ports[csk->port_id]->name, csk->tid,
+ skb->len, hdr_len);
+ goto abort_conn;
+ }
+ cxgbi_skcb_set_flag(skb, SKCBF_RX_COALESCED);
+
+ err = skb_copy_bits(skb, skb->len - sizeof(ddp_cpl), &ddp_cpl,
+ sizeof(ddp_cpl));
+ if (err < 0) {
+ pr_err("%s: tid %u, copy cpl_ddp %u-%zu failed %d.\n",
+ csk->cdev->ports[csk->port_id]->name, csk->tid,
+ skb->len, sizeof(ddp_cpl), err);
+ goto abort_conn;
+ }
+
+ cxgbi_skcb_set_flag(skb, SKCBF_RX_STATUS);
+ cxgbi_skcb_rx_pdulen(skb) = ntohs(ddp_cpl.len);
+ cxgbi_skcb_rx_ddigest(skb) = ntohl(ddp_cpl.ulp_crc);
+ status = ntohl(ddp_cpl.ddp_status);
+
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_PDU_RX,
+ "csk 0x%p, skb 0x%p,%u, pdulen %u, status 0x%x.\n",
+ csk, skb, skb->len, cxgbi_skcb_rx_pdulen(skb), status);
+
+ if (status & (1 << CPL_RX_DDP_STATUS_HCRC_SHIFT))
+ cxgbi_skcb_set_flag(skb, SKCBF_RX_HCRC_ERR);
+ if (status & (1 << CPL_RX_DDP_STATUS_DCRC_SHIFT))
+ cxgbi_skcb_set_flag(skb, SKCBF_RX_DCRC_ERR);
+ if (status & (1 << CPL_RX_DDP_STATUS_PAD_SHIFT))
+ cxgbi_skcb_set_flag(skb, SKCBF_RX_PAD_ERR);
+
+ if (skb->len > (hdr_len + sizeof(ddp_cpl))) {
+ err = skb_copy_bits(skb, hdr_len, &data_cpl, sizeof(data_cpl));
+ if (err < 0) {
+ pr_err("%s: tid %u, cp %zu/%u failed %d.\n",
+ csk->cdev->ports[csk->port_id]->name,
+ csk->tid, sizeof(data_cpl), skb->len, err);
+ goto abort_conn;
+ }
+ data_len = ntohs(data_cpl.len);
+ log_debug(1 << CXGBI_DBG_DDP | 1 << CXGBI_DBG_PDU_RX,
+ "skb 0x%p, pdu not ddp'ed %u/%u, status 0x%x.\n",
+ skb, data_len, cxgbi_skcb_rx_pdulen(skb), status);
+ len += sizeof(data_cpl) + data_len;
+ } else if (status & (1 << CPL_RX_DDP_STATUS_DDP_SHIFT))
+ cxgbi_skcb_set_flag(skb, SKCBF_RX_DATA_DDPD);
+
+ csk->rcv_nxt = ntohl(ddp_cpl.seq) + cxgbi_skcb_rx_pdulen(skb);
+ __pskb_trim(skb, len);
+ __skb_queue_tail(&csk->receive_queue, skb);
+ cxgbi_conn_pdu_ready(csk);
+
+ spin_unlock_bh(&csk->lock);
+ return 0;
+
+abort_conn:
+ send_abort_req(csk);
+discard:
+ spin_unlock_bh(&csk->lock);
+ __kfree_skb(skb);
+ return 0;
+}
+
+/*
+ * Process TX_DATA_ACK CPL messages: -> host
+ * Process an acknowledgment of WR completion. Advance snd_una and send the
+ * next batch of work requests from the write queue.
+ */
+static int do_wr_ack(struct t3cdev *cdev, struct sk_buff *skb, void *ctx)
+{
+ struct cxgbi_sock *csk = ctx;
+ struct cpl_wr_ack *hdr = cplhdr(skb);
+
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_PDU_RX,
+ "csk 0x%p,%u,0x%lx,%u, cr %u.\n",
+ csk, csk->state, csk->flags, csk->tid, ntohs(hdr->credits));
+
+ cxgbi_sock_rcv_wr_ack(csk, ntohs(hdr->credits), ntohl(hdr->snd_una), 1);
+ __kfree_skb(skb);
+ return 0;
+}
+
+/*
+ * for each connection, pre-allocate skbs needed for close/abort requests. So
+ * that we can service the request right away.
+ */
+static int alloc_cpls(struct cxgbi_sock *csk)
+{
+ csk->cpl_close = alloc_wr(sizeof(struct cpl_close_con_req), 0,
+ GFP_KERNEL);
+ if (!csk->cpl_close)
+ return -ENOMEM;
+ csk->cpl_abort_req = alloc_wr(sizeof(struct cpl_abort_req), 0,
+ GFP_KERNEL);
+ if (!csk->cpl_abort_req)
+ goto free_cpl_skbs;
+
+ csk->cpl_abort_rpl = alloc_wr(sizeof(struct cpl_abort_rpl), 0,
+ GFP_KERNEL);
+ if (!csk->cpl_abort_rpl)
+ goto free_cpl_skbs;
+
+ return 0;
+
+free_cpl_skbs:
+ cxgbi_sock_free_cpl_skbs(csk);
+ return -ENOMEM;
+}
+
+/**
+ * release_offload_resources - release offload resource
+ * @c3cn: the offloaded iscsi tcp connection.
+ * Release resources held by an offload connection (TID, L2T entry, etc.)
+ */
+static void l2t_put(struct cxgbi_sock *csk)
+{
+ struct t3cdev *t3dev = (struct t3cdev *)csk->cdev->lldev;
+
+ if (csk->l2t) {
+ l2t_release(L2DATA(t3dev), csk->l2t);
+ csk->l2t = NULL;
+ cxgbi_sock_put(csk);
+ }
+}
+
+static void release_offload_resources(struct cxgbi_sock *csk)
+{
+ struct t3cdev *t3dev = (struct t3cdev *)csk->cdev->lldev;
+
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+ "csk 0x%p,%u,0x%lx,%u.\n",
+ csk, csk->state, csk->flags, csk->tid);
+
+ csk->rss_qid = 0;
+ cxgbi_sock_free_cpl_skbs(csk);
+
+ if (csk->wr_cred != csk->wr_max_cred) {
+ cxgbi_sock_purge_wr_queue(csk);
+ cxgbi_sock_reset_wr_list(csk);
+ }
+ l2t_put(csk);
+ if (cxgbi_sock_flag(csk, CTPF_HAS_ATID))
+ free_atid(csk);
+ else if (cxgbi_sock_flag(csk, CTPF_HAS_TID)) {
+ cxgb3_remove_tid(t3dev, (void *)csk, csk->tid);
+ cxgbi_sock_clear_flag(csk, CTPF_HAS_TID);
+ cxgbi_sock_put(csk);
+ }
+ csk->dst = NULL;
+ csk->cdev = NULL;
+}
+
+static void update_address(struct cxgbi_hba *chba)
+{
+ if (chba->ipv4addr) {
+ if (chba->vdev &&
+ chba->ipv4addr != cxgb3i_get_private_ipv4addr(chba->vdev)) {
+ cxgb3i_set_private_ipv4addr(chba->vdev, chba->ipv4addr);
+ cxgb3i_set_private_ipv4addr(chba->ndev, 0);
+ pr_info("%s set %pI4.\n",
+ chba->vdev->name, &chba->ipv4addr);
+ } else if (chba->ipv4addr !=
+ cxgb3i_get_private_ipv4addr(chba->ndev)) {
+ cxgb3i_set_private_ipv4addr(chba->ndev, chba->ipv4addr);
+ pr_info("%s set %pI4.\n",
+ chba->ndev->name, &chba->ipv4addr);
+ }
+ } else if (cxgb3i_get_private_ipv4addr(chba->ndev)) {
+ if (chba->vdev)
+ cxgb3i_set_private_ipv4addr(chba->vdev, 0);
+ cxgb3i_set_private_ipv4addr(chba->ndev, 0);
+ }
+}
+
+static int init_act_open(struct cxgbi_sock *csk)
+{
+ struct dst_entry *dst = csk->dst;
+ struct cxgbi_device *cdev = csk->cdev;
+ struct t3cdev *t3dev = (struct t3cdev *)cdev->lldev;
+ struct net_device *ndev = cdev->ports[csk->port_id];
+ struct cxgbi_hba *chba = cdev->hbas[csk->port_id];
+ struct sk_buff *skb = NULL;
+
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+ "csk 0x%p,%u,0x%lx.\n", csk, csk->state, csk->flags);
+
+ update_address(chba);
+ if (chba->ipv4addr)
+ csk->saddr.sin_addr.s_addr = chba->ipv4addr;
+
+ csk->rss_qid = 0;
+ csk->l2t = t3_l2t_get(t3dev, dst->neighbour, ndev);
+ if (!csk->l2t) {
+ pr_err("NO l2t available.\n");
+ return -EINVAL;
+ }
+ cxgbi_sock_get(csk);
+
+ csk->atid = cxgb3_alloc_atid(t3dev, &t3_client, csk);
+ if (csk->atid < 0) {
+ pr_err("NO atid available.\n");
+ goto rel_resource;
+ }
+ cxgbi_sock_set_flag(csk, CTPF_HAS_ATID);
+ cxgbi_sock_get(csk);
+
+ skb = alloc_wr(sizeof(struct cpl_act_open_req), 0, GFP_KERNEL);
+ if (!skb)
+ goto rel_resource;
+ skb->sk = (struct sock *)csk;
+ set_arp_failure_handler(skb, act_open_arp_failure);
+
+ csk->wr_max_cred = csk->wr_cred = T3C_DATA(t3dev)->max_wrs - 1;
+ csk->wr_una_cred = 0;
+ csk->mss_idx = cxgbi_sock_select_mss(csk, dst_mtu(dst));
+ cxgbi_sock_reset_wr_list(csk);
+ csk->err = 0;
+
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+ "csk 0x%p,%u,0x%lx, %pI4:%u-%pI4:%u.\n",
+ csk, csk->state, csk->flags,
+ &csk->saddr.sin_addr.s_addr, ntohs(csk->saddr.sin_port),
+ &csk->daddr.sin_addr.s_addr, ntohs(csk->daddr.sin_port));
+
+ cxgbi_sock_set_state(csk, CTP_ACTIVE_OPEN);
+ send_act_open_req(csk, skb, csk->l2t);
+ return 0;
+
+rel_resource:
+ if (skb)
+ __kfree_skb(skb);
+ return -EINVAL;
+}
+
+cxgb3_cpl_handler_func cxgb3i_cpl_handlers[NUM_CPL_CMDS] = {
+ [CPL_ACT_ESTABLISH] = do_act_establish,
+ [CPL_ACT_OPEN_RPL] = do_act_open_rpl,
+ [CPL_PEER_CLOSE] = do_peer_close,
+ [CPL_ABORT_REQ_RSS] = do_abort_req,
+ [CPL_ABORT_RPL_RSS] = do_abort_rpl,
+ [CPL_CLOSE_CON_RPL] = do_close_con_rpl,
+ [CPL_TX_DMA_ACK] = do_wr_ack,
+ [CPL_ISCSI_HDR] = do_iscsi_hdr,
+};
+
+/**
+ * cxgb3i_ofld_init - allocate and initialize resources for each adapter found
+ * @cdev: cxgbi adapter
+ */
+int cxgb3i_ofld_init(struct cxgbi_device *cdev)
+{
+ struct t3cdev *t3dev = (struct t3cdev *)cdev->lldev;
+ struct adap_ports port;
+ struct ofld_page_info rx_page_info;
+ unsigned int wr_len;
+ int rc;
+
+ if (t3dev->ctl(t3dev, GET_WR_LEN, &wr_len) < 0 ||
+ t3dev->ctl(t3dev, GET_PORTS, &port) < 0 ||
+ t3dev->ctl(t3dev, GET_RX_PAGE_INFO, &rx_page_info) < 0) {
+ pr_warn("t3 0x%p, offload up, ioctl failed.\n", t3dev);
+ return -EINVAL;
+ }
+
+ if (cxgb3i_max_connect > CXGBI_MAX_CONN)
+ cxgb3i_max_connect = CXGBI_MAX_CONN;
+
+ rc = cxgbi_device_portmap_create(cdev, cxgb3i_sport_base,
+ cxgb3i_max_connect);
+ if (rc < 0)
+ return rc;
+
+ init_wr_tab(wr_len);
+ cdev->csk_release_offload_resources = release_offload_resources;
+ cdev->csk_push_tx_frames = push_tx_frames;
+ cdev->csk_send_abort_req = send_abort_req;
+ cdev->csk_send_close_req = send_close_req;
+ cdev->csk_send_rx_credits = send_rx_credits;
+ cdev->csk_alloc_cpls = alloc_cpls;
+ cdev->csk_init_act_open = init_act_open;
+
+ pr_info("cdev 0x%p, offload up, added.\n", cdev);
+ return 0;
+}
+
+/*
+ * functions to program the pagepod in h/w
+ */
+static inline void ulp_mem_io_set_hdr(struct sk_buff *skb, unsigned int addr)
+{
+ struct ulp_mem_io *req = (struct ulp_mem_io *)skb->head;
+
+ memset(req, 0, sizeof(*req));
+
+ req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_BYPASS));
+ req->cmd_lock_addr = htonl(V_ULP_MEMIO_ADDR(addr >> 5) |
+ V_ULPTX_CMD(ULP_MEM_WRITE));
+ req->len = htonl(V_ULP_MEMIO_DATA_LEN(PPOD_SIZE >> 5) |
+ V_ULPTX_NFLITS((PPOD_SIZE >> 3) + 1));
+}
+
+static int ddp_set_map(struct cxgbi_sock *csk, struct cxgbi_pagepod_hdr *hdr,
+ unsigned int idx, unsigned int npods,
+ struct cxgbi_gather_list *gl)
+{
+ struct cxgbi_device *cdev = csk->cdev;
+ struct cxgbi_ddp_info *ddp = cdev->ddp;
+ unsigned int pm_addr = (idx << PPOD_SIZE_SHIFT) + ddp->llimit;
+ int i;
+
+ log_debug(1 << CXGBI_DBG_DDP,
+ "csk 0x%p, idx %u, npods %u, gl 0x%p.\n",
+ csk, idx, npods, gl);
+
+ for (i = 0; i < npods; i++, idx++, pm_addr += PPOD_SIZE) {
+ struct sk_buff *skb = ddp->gl_skb[idx];
+
+ /* hold on to the skb until we clear the ddp mapping */
+ skb_get(skb);
+
+ ulp_mem_io_set_hdr(skb, pm_addr);
+ cxgbi_ddp_ppod_set((struct cxgbi_pagepod *)(skb->head +
+ sizeof(struct ulp_mem_io)),
+ hdr, gl, i * PPOD_PAGES_MAX);
+ skb->priority = CPL_PRIORITY_CONTROL;
+ cxgb3_ofld_send(cdev->lldev, skb);
+ }
+ return 0;
+}
+
+static void ddp_clear_map(struct cxgbi_hba *chba, unsigned int tag,
+ unsigned int idx, unsigned int npods)
+{
+ struct cxgbi_device *cdev = chba->cdev;
+ struct cxgbi_ddp_info *ddp = cdev->ddp;
+ unsigned int pm_addr = (idx << PPOD_SIZE_SHIFT) + ddp->llimit;
+ int i;
+
+ log_debug(1 << CXGBI_DBG_DDP,
+ "cdev 0x%p, idx %u, npods %u, tag 0x%x.\n",
+ cdev, idx, npods, tag);
+
+ for (i = 0; i < npods; i++, idx++, pm_addr += PPOD_SIZE) {
+ struct sk_buff *skb = ddp->gl_skb[idx];
+
+ if (!skb) {
+ pr_err("tag 0x%x, 0x%x, %d/%u, skb NULL.\n",
+ tag, idx, i, npods);
+ continue;
+ }
+ ddp->gl_skb[idx] = NULL;
+ memset(skb->head + sizeof(struct ulp_mem_io), 0, PPOD_SIZE);
+ ulp_mem_io_set_hdr(skb, pm_addr);
+ skb->priority = CPL_PRIORITY_CONTROL;
+ cxgb3_ofld_send(cdev->lldev, skb);
+ }
+}
+
+static void ddp_free_gl_skb(struct cxgbi_ddp_info *ddp, int idx, int cnt)
+{
+ int i;
+
+ log_debug(1 << CXGBI_DBG_DDP,
+ "ddp 0x%p, idx %d, cnt %d.\n", ddp, idx, cnt);
+
+ for (i = 0; i < cnt; i++, idx++)
+ if (ddp->gl_skb[idx]) {
+ kfree_skb(ddp->gl_skb[idx]);
+ ddp->gl_skb[idx] = NULL;
+ }
+}
+
+static int ddp_alloc_gl_skb(struct cxgbi_ddp_info *ddp, int idx,
+ int cnt, gfp_t gfp)
+{
+ int i;
+
+ log_debug(1 << CXGBI_DBG_DDP,
+ "ddp 0x%p, idx %d, cnt %d.\n", ddp, idx, cnt);
+
+ for (i = 0; i < cnt; i++) {
+ struct sk_buff *skb = alloc_wr(sizeof(struct ulp_mem_io) +
+ PPOD_SIZE, 0, gfp);
+ if (skb)
+ ddp->gl_skb[idx + i] = skb;
+ else {
+ ddp_free_gl_skb(ddp, idx, i);
+ return -ENOMEM;
+ }
+ }
+ return 0;
+}
+
+static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk,
+ unsigned int tid, int pg_idx, bool reply)
+{
+ struct sk_buff *skb = alloc_wr(sizeof(struct cpl_set_tcb_field), 0,
+ GFP_KERNEL);
+ struct cpl_set_tcb_field *req;
+ u64 val = pg_idx < DDP_PGIDX_MAX ? pg_idx : 0;
+
+ log_debug(1 << CXGBI_DBG_DDP,
+ "csk 0x%p, tid %u, pg_idx %d.\n", csk, tid, pg_idx);
+ if (!skb)
+ return -ENOMEM;
+
+ /* set up ulp submode and page size */
+ req = (struct cpl_set_tcb_field *)skb->head;
+ req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
+ OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid));
+ req->reply = V_NO_REPLY(reply ? 0 : 1);
+ req->cpu_idx = 0;
+ req->word = htons(31);
+ req->mask = cpu_to_be64(0xF0000000);
+ req->val = cpu_to_be64(val << 28);
+ skb->priority = CPL_PRIORITY_CONTROL;
+
+ cxgb3_ofld_send(csk->cdev->lldev, skb);
+ return 0;
+}
+
+/**
+ * cxgb3i_setup_conn_digest - setup conn. digest setting
+ * @csk: cxgb tcp socket
+ * @tid: connection id
+ * @hcrc: header digest enabled
+ * @dcrc: data digest enabled
+ * @reply: request reply from h/w
+ * set up the iscsi digest settings for a connection identified by tid
+ */
+static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid,
+ int hcrc, int dcrc, int reply)
+{
+ struct sk_buff *skb = alloc_wr(sizeof(struct cpl_set_tcb_field), 0,
+ GFP_KERNEL);
+ struct cpl_set_tcb_field *req;
+ u64 val = (hcrc ? 1 : 0) | (dcrc ? 2 : 0);
+
+ log_debug(1 << CXGBI_DBG_DDP,
+ "csk 0x%p, tid %u, crc %d,%d.\n", csk, tid, hcrc, dcrc);
+ if (!skb)
+ return -ENOMEM;
+
+ /* set up ulp submode and page size */
+ req = (struct cpl_set_tcb_field *)skb->head;
+ req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
+ OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid));
+ req->reply = V_NO_REPLY(reply ? 0 : 1);
+ req->cpu_idx = 0;
+ req->word = htons(31);
+ req->mask = cpu_to_be64(0x0F000000);
+ req->val = cpu_to_be64(val << 24);
+ skb->priority = CPL_PRIORITY_CONTROL;
+
+ cxgb3_ofld_send(csk->cdev->lldev, skb);
+ return 0;
+}
+
+/**
+ * t3_ddp_cleanup - release the cxgb3 adapter's ddp resource
+ * @cdev: cxgb3i adapter
+ * release all the resource held by the ddp pagepod manager for a given
+ * adapter if needed
+ */
+
+static void t3_ddp_cleanup(struct cxgbi_device *cdev)
+{
+ struct t3cdev *tdev = (struct t3cdev *)cdev->lldev;
+
+ if (cxgbi_ddp_cleanup(cdev)) {
+ pr_info("t3dev 0x%p, ulp_iscsi no more user.\n", tdev);
+ tdev->ulp_iscsi = NULL;
+ }
+}
+
+/**
+ * ddp_init - initialize the cxgb3 adapter's ddp resource
+ * @cdev: cxgb3i adapter
+ * initialize the ddp pagepod manager for a given adapter
+ */
+static int cxgb3i_ddp_init(struct cxgbi_device *cdev)
+{
+ struct t3cdev *tdev = (struct t3cdev *)cdev->lldev;
+ struct cxgbi_ddp_info *ddp = tdev->ulp_iscsi;
+ struct ulp_iscsi_info uinfo;
+ unsigned int pgsz_factor[4];
+ int err;
+
+ if (ddp) {
+ kref_get(&ddp->refcnt);
+ pr_warn("t3dev 0x%p, ddp 0x%p already set up.\n",
+ tdev, tdev->ulp_iscsi);
+ cdev->ddp = ddp;
+ return -EALREADY;
+ }
+
+ err = tdev->ctl(tdev, ULP_ISCSI_GET_PARAMS, &uinfo);
+ if (err < 0) {
+ pr_err("%s, failed to get iscsi param err=%d.\n",
+ tdev->name, err);
+ return err;
+ }
+
+ err = cxgbi_ddp_init(cdev, uinfo.llimit, uinfo.ulimit,
+ uinfo.max_txsz, uinfo.max_rxsz);
+ if (err < 0)
+ return err;
+
+ ddp = cdev->ddp;
+
+ uinfo.tagmask = ddp->idx_mask << PPOD_IDX_SHIFT;
+ cxgbi_ddp_page_size_factor(pgsz_factor);
+ uinfo.ulimit = uinfo.llimit + (ddp->nppods << PPOD_SIZE_SHIFT);
+
+ err = tdev->ctl(tdev, ULP_ISCSI_SET_PARAMS, &uinfo);
+ if (err < 0) {
+ pr_warn("%s unable to set iscsi param err=%d, ddp disabled.\n",
+ tdev->name, err);
+ cxgbi_ddp_cleanup(cdev);
+ return err;
+ }
+ tdev->ulp_iscsi = ddp;
+
+ cdev->csk_ddp_free_gl_skb = ddp_free_gl_skb;
+ cdev->csk_ddp_alloc_gl_skb = ddp_alloc_gl_skb;
+ cdev->csk_ddp_setup_digest = ddp_setup_conn_digest;
+ cdev->csk_ddp_setup_pgidx = ddp_setup_conn_pgidx;
+ cdev->csk_ddp_set = ddp_set_map;
+ cdev->csk_ddp_clear = ddp_clear_map;
+
+ pr_info("tdev 0x%p, nppods %u, bits %u, mask 0x%x,0x%x pkt %u/%u, "
+ "%u/%u.\n",
+ tdev, ddp->nppods, ddp->idx_bits, ddp->idx_mask,
+ ddp->rsvd_tag_mask, ddp->max_txsz, uinfo.max_txsz,
+ ddp->max_rxsz, uinfo.max_rxsz);
+ return 0;
+}
+
+static void cxgb3i_dev_close(struct t3cdev *t3dev)
+{
+ struct cxgbi_device *cdev = cxgbi_device_find_by_lldev(t3dev);
+
+ if (!cdev || cdev->flags & CXGBI_FLAG_ADAPTER_RESET) {
+ pr_info("0x%p close, f 0x%x.\n", cdev, cdev ? cdev->flags : 0);
+ return;
+ }
+
+ cxgbi_device_unregister(cdev);
+}
+
+/**
+ * cxgb3i_dev_open - init a t3 adapter structure and any h/w settings
+ * @t3dev: t3cdev adapter
+ */
+static void cxgb3i_dev_open(struct t3cdev *t3dev)
+{
+ struct cxgbi_device *cdev = cxgbi_device_find_by_lldev(t3dev);
+ struct adapter *adapter = tdev2adap(t3dev);
+ int i, err;
+
+ if (cdev) {
+ pr_info("0x%p, updating.\n", cdev);
+ return;
+ }
+
+ cdev = cxgbi_device_register(0, adapter->params.nports);
+ if (!cdev) {
+ pr_warn("device 0x%p register failed.\n", t3dev);
+ return;
+ }
+
+ cdev->flags = CXGBI_FLAG_DEV_T3 | CXGBI_FLAG_IPV4_SET;
+ cdev->lldev = t3dev;
+ cdev->pdev = adapter->pdev;
+ cdev->ports = adapter->port;
+ cdev->nports = adapter->params.nports;
+ cdev->mtus = adapter->params.mtus;
+ cdev->nmtus = NMTUS;
+ cdev->snd_win = cxgb3i_snd_win;
+ cdev->rcv_win = cxgb3i_rcv_win;
+ cdev->rx_credit_thres = cxgb3i_rx_credit_thres;
+ cdev->skb_tx_rsvd = CXGB3I_TX_HEADER_LEN;
+ cdev->skb_rx_extra = sizeof(struct cpl_iscsi_hdr_norss);
+ cdev->dev_ddp_cleanup = t3_ddp_cleanup;
+ cdev->itp = &cxgb3i_iscsi_transport;
+
+ err = cxgb3i_ddp_init(cdev);
+ if (err) {
+ pr_info("0x%p ddp init failed\n", cdev);
+ goto err_out;
+ }
+
+ err = cxgb3i_ofld_init(cdev);
+ if (err) {
+ pr_info("0x%p offload init failed\n", cdev);
+ goto err_out;
+ }
+
+ err = cxgbi_hbas_add(cdev, CXGB3I_MAX_LUN, CXGBI_MAX_CONN,
+ &cxgb3i_host_template, cxgb3i_stt);
+ if (err)
+ goto err_out;
+
+ for (i = 0; i < cdev->nports; i++)
+ cdev->hbas[i]->ipv4addr =
+ cxgb3i_get_private_ipv4addr(cdev->ports[i]);
+
+ pr_info("cdev 0x%p, f 0x%x, t3dev 0x%p open, err %d.\n",
+ cdev, cdev ? cdev->flags : 0, t3dev, err);
+ return;
+
+err_out:
+ cxgbi_device_unregister(cdev);
+}
+
+static void cxgb3i_dev_event_handler(struct t3cdev *t3dev, u32 event, u32 port)
+{
+ struct cxgbi_device *cdev = cxgbi_device_find_by_lldev(t3dev);
+
+ log_debug(1 << CXGBI_DBG_TOE,
+ "0x%p, cdev 0x%p, event 0x%x, port 0x%x.\n",
+ t3dev, cdev, event, port);
+ if (!cdev)
+ return;
+
+ switch (event) {
+ case OFFLOAD_STATUS_DOWN:
+ cdev->flags |= CXGBI_FLAG_ADAPTER_RESET;
+ break;
+ case OFFLOAD_STATUS_UP:
+ cdev->flags &= ~CXGBI_FLAG_ADAPTER_RESET;
+ break;
+ }
+}
+
+/**
+ * cxgb3i_init_module - module init entry point
+ *
+ * initialize any driver wide global data structures and register itself
+ * with the cxgb3 module
+ */
+static int __init cxgb3i_init_module(void)
+{
+ int rc;
+
+ printk(KERN_INFO "%s", version);
+
+ rc = cxgbi_iscsi_init(&cxgb3i_iscsi_transport, &cxgb3i_stt);
+ if (rc < 0)
+ return rc;
+
+ cxgb3_register_client(&t3_client);
+ return 0;
+}
+
+/**
+ * cxgb3i_exit_module - module cleanup/exit entry point
+ *
+ * go through the driver hba list and for each hba, release any resource held.
+ * and unregisters iscsi transport and the cxgb3 module
+ */
+static void __exit cxgb3i_exit_module(void)
+{
+ cxgb3_unregister_client(&t3_client);
+ cxgbi_device_unregister_all(CXGBI_FLAG_DEV_T3);
+ cxgbi_iscsi_cleanup(&cxgb3i_iscsi_transport, &cxgb3i_stt);
+}
+
+module_init(cxgb3i_init_module);
+module_exit(cxgb3i_exit_module);
diff --git a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.h b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.h
new file mode 100644
index 000000000000..5f5e3394b594
--- /dev/null
+++ b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.h
@@ -0,0 +1,51 @@
+/*
+ * cxgb3i.h: Chelsio S3xx iSCSI driver.
+ *
+ * Copyright (c) 2008 Chelsio Communications, 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.
+ *
+ * Written by: Karen Xie (kxie@chelsio.com)
+ */
+
+#ifndef __CXGB3I_H__
+#define __CXGB3I_H__
+
+#define CXGB3I_SCSI_HOST_QDEPTH 1024
+#define CXGB3I_MAX_LUN 512
+#define ISCSI_PDU_NONPAYLOAD_MAX \
+ (sizeof(struct iscsi_hdr) + ISCSI_MAX_AHS_SIZE + 2*ISCSI_DIGEST_SIZE)
+
+/*for TX: a skb must have a headroom of at least TX_HEADER_LEN bytes */
+#define CXGB3I_TX_HEADER_LEN \
+ (sizeof(struct tx_data_wr) + sizeof(struct sge_opaque_hdr))
+
+extern cxgb3_cpl_handler_func cxgb3i_cpl_handlers[NUM_CPL_CMDS];
+
+#define cxgb3i_get_private_ipv4addr(ndev) \
+ (((struct port_info *)(netdev_priv(ndev)))->iscsi_ipv4addr)
+#define cxgb3i_set_private_ipv4addr(ndev, addr) \
+ (((struct port_info *)(netdev_priv(ndev)))->iscsi_ipv4addr) = addr
+
+struct cpl_iscsi_hdr_norss {
+ union opcode_tid ot;
+ u16 pdu_len_ddp;
+ u16 len;
+ u32 seq;
+ u16 urg;
+ u8 rsvd;
+ u8 status;
+};
+
+struct cpl_rx_data_ddp_norss {
+ union opcode_tid ot;
+ u16 urg;
+ u16 len;
+ u32 seq;
+ u32 nxt_seq;
+ u32 ulp_crc;
+ u32 ddp_status;
+};
+#endif
diff --git a/drivers/scsi/cxgbi/cxgb4i/Kbuild b/drivers/scsi/cxgbi/cxgb4i/Kbuild
new file mode 100644
index 000000000000..b9f4af7454b7
--- /dev/null
+++ b/drivers/scsi/cxgbi/cxgb4i/Kbuild
@@ -0,0 +1,3 @@
+EXTRA_CFLAGS += -I$(srctree)/drivers/net/cxgb4
+
+obj-$(CONFIG_SCSI_CXGB4_ISCSI) += cxgb4i.o
diff --git a/drivers/scsi/cxgbi/cxgb4i/Kconfig b/drivers/scsi/cxgbi/cxgb4i/Kconfig
new file mode 100644
index 000000000000..bb94b39b17b3
--- /dev/null
+++ b/drivers/scsi/cxgbi/cxgb4i/Kconfig
@@ -0,0 +1,7 @@
+config SCSI_CXGB4_ISCSI
+ tristate "Chelsio T4 iSCSI support"
+ depends on CHELSIO_T4_DEPENDS
+ select CHELSIO_T4
+ select SCSI_ISCSI_ATTRS
+ ---help---
+ This driver supports iSCSI offload for the Chelsio T4 devices.
diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
new file mode 100644
index 000000000000..99f2b8c5dd63
--- /dev/null
+++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
@@ -0,0 +1,1604 @@
+/*
+ * cxgb4i.c: Chelsio T4 iSCSI driver.
+ *
+ * Copyright (c) 2010 Chelsio Communications, 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.
+ *
+ * Written by: Karen Xie (kxie@chelsio.com)
+ * Rakesh Ranjan (rranjan@chelsio.com)
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <scsi/scsi_host.h>
+#include <net/tcp.h>
+#include <net/dst.h>
+#include <linux/netdevice.h>
+
+#include "t4_msg.h"
+#include "cxgb4.h"
+#include "cxgb4_uld.h"
+#include "t4fw_api.h"
+#include "l2t.h"
+#include "cxgb4i.h"
+
+static unsigned int dbg_level;
+
+#include "../libcxgbi.h"
+
+#define DRV_MODULE_NAME "cxgb4i"
+#define DRV_MODULE_DESC "Chelsio T4 iSCSI Driver"
+#define DRV_MODULE_VERSION "0.9.1"
+#define DRV_MODULE_RELDATE "Aug. 2010"
+
+static char version[] =
+ DRV_MODULE_DESC " " DRV_MODULE_NAME
+ " v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+
+MODULE_AUTHOR("Chelsio Communications, Inc.");
+MODULE_DESCRIPTION(DRV_MODULE_DESC);
+MODULE_VERSION(DRV_MODULE_VERSION);
+MODULE_LICENSE("GPL");
+
+module_param(dbg_level, uint, 0644);
+MODULE_PARM_DESC(dbg_level, "Debug flag (default=0)");
+
+static int cxgb4i_rcv_win = 256 * 1024;
+module_param(cxgb4i_rcv_win, int, 0644);
+MODULE_PARM_DESC(cxgb4i_rcv_win, "TCP reveive window in bytes");
+
+static int cxgb4i_snd_win = 128 * 1024;
+module_param(cxgb4i_snd_win, int, 0644);
+MODULE_PARM_DESC(cxgb4i_snd_win, "TCP send window in bytes");
+
+static int cxgb4i_rx_credit_thres = 10 * 1024;
+module_param(cxgb4i_rx_credit_thres, int, 0644);
+MODULE_PARM_DESC(cxgb4i_rx_credit_thres,
+ "RX credits return threshold in bytes (default=10KB)");
+
+static unsigned int cxgb4i_max_connect = (8 * 1024);
+module_param(cxgb4i_max_connect, uint, 0644);
+MODULE_PARM_DESC(cxgb4i_max_connect, "Maximum number of connections");
+
+static unsigned short cxgb4i_sport_base = 20000;
+module_param(cxgb4i_sport_base, ushort, 0644);
+MODULE_PARM_DESC(cxgb4i_sport_base, "Starting port number (default 20000)");
+
+typedef void (*cxgb4i_cplhandler_func)(struct cxgbi_device *, struct sk_buff *);
+
+static void *t4_uld_add(const struct cxgb4_lld_info *);
+static int t4_uld_rx_handler(void *, const __be64 *, const struct pkt_gl *);
+static int t4_uld_state_change(void *, enum cxgb4_state state);
+
+static const struct cxgb4_uld_info cxgb4i_uld_info = {
+ .name = DRV_MODULE_NAME,
+ .add = t4_uld_add,
+ .rx_handler = t4_uld_rx_handler,
+ .state_change = t4_uld_state_change,
+};
+
+static struct scsi_host_template cxgb4i_host_template = {
+ .module = THIS_MODULE,
+ .name = DRV_MODULE_NAME,
+ .proc_name = DRV_MODULE_NAME,
+ .can_queue = CXGB4I_SCSI_HOST_QDEPTH,
+ .queuecommand = iscsi_queuecommand,
+ .change_queue_depth = iscsi_change_queue_depth,
+ .sg_tablesize = SG_ALL,
+ .max_sectors = 0xFFFF,
+ .cmd_per_lun = ISCSI_DEF_CMD_PER_LUN,
+ .eh_abort_handler = iscsi_eh_abort,
+ .eh_device_reset_handler = iscsi_eh_device_reset,
+ .eh_target_reset_handler = iscsi_eh_recover_target,
+ .target_alloc = iscsi_target_alloc,
+ .use_clustering = DISABLE_CLUSTERING,
+ .this_id = -1,
+};
+
+static struct iscsi_transport cxgb4i_iscsi_transport = {
+ .owner = THIS_MODULE,
+ .name = DRV_MODULE_NAME,
+ .caps = CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST |
+ CAP_DATADGST | CAP_DIGEST_OFFLOAD |
+ CAP_PADDING_OFFLOAD,
+ .param_mask = ISCSI_MAX_RECV_DLENGTH | ISCSI_MAX_XMIT_DLENGTH |
+ ISCSI_HDRDGST_EN | ISCSI_DATADGST_EN |
+ ISCSI_INITIAL_R2T_EN | ISCSI_MAX_R2T |
+ ISCSI_IMM_DATA_EN | ISCSI_FIRST_BURST |
+ ISCSI_MAX_BURST | ISCSI_PDU_INORDER_EN |
+ ISCSI_DATASEQ_INORDER_EN | ISCSI_ERL |
+ ISCSI_CONN_PORT | ISCSI_CONN_ADDRESS |
+ ISCSI_EXP_STATSN | ISCSI_PERSISTENT_PORT |
+ ISCSI_PERSISTENT_ADDRESS |
+ ISCSI_TARGET_NAME | ISCSI_TPGT |
+ ISCSI_USERNAME | ISCSI_PASSWORD |
+ ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
+ ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
+ ISCSI_LU_RESET_TMO | ISCSI_TGT_RESET_TMO |
+ ISCSI_PING_TMO | ISCSI_RECV_TMO |
+ ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
+ .host_param_mask = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
+ ISCSI_HOST_INITIATOR_NAME |
+ ISCSI_HOST_NETDEV_NAME,
+ .get_host_param = cxgbi_get_host_param,
+ .set_host_param = cxgbi_set_host_param,
+ /* session management */
+ .create_session = cxgbi_create_session,
+ .destroy_session = cxgbi_destroy_session,
+ .get_session_param = iscsi_session_get_param,
+ /* connection management */
+ .create_conn = cxgbi_create_conn,
+ .bind_conn = cxgbi_bind_conn,
+ .destroy_conn = iscsi_tcp_conn_teardown,
+ .start_conn = iscsi_conn_start,
+ .stop_conn = iscsi_conn_stop,
+ .get_conn_param = cxgbi_get_conn_param,
+ .set_param = cxgbi_set_conn_param,
+ .get_stats = cxgbi_get_conn_stats,
+ /* pdu xmit req from user space */
+ .send_pdu = iscsi_conn_send_pdu,
+ /* task */
+ .init_task = iscsi_tcp_task_init,
+ .xmit_task = iscsi_tcp_task_xmit,
+ .cleanup_task = cxgbi_cleanup_task,
+ /* pdu */
+ .alloc_pdu = cxgbi_conn_alloc_pdu,
+ .init_pdu = cxgbi_conn_init_pdu,
+ .xmit_pdu = cxgbi_conn_xmit_pdu,
+ .parse_pdu_itt = cxgbi_parse_pdu_itt,
+ /* TCP connect/disconnect */
+ .ep_connect = cxgbi_ep_connect,
+ .ep_poll = cxgbi_ep_poll,
+ .ep_disconnect = cxgbi_ep_disconnect,
+ /* Error recovery timeout call */
+ .session_recovery_timedout = iscsi_session_recovery_timedout,
+};
+
+static struct scsi_transport_template *cxgb4i_stt;
+
+/*
+ * CPL (Chelsio Protocol Language) defines a message passing interface between
+ * the host driver and Chelsio asic.
+ * The section below implments CPLs that related to iscsi tcp connection
+ * open/close/abort and data send/receive.
+ */
+#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
+#define RCV_BUFSIZ_MASK 0x3FFU
+#define MAX_IMM_TX_PKT_LEN 128
+
+static inline void set_queue(struct sk_buff *skb, unsigned int queue,
+ const struct cxgbi_sock *csk)
+{
+ skb->queue_mapping = queue;
+}
+
+static int push_tx_frames(struct cxgbi_sock *, int);
+
+/*
+ * is_ofld_imm - check whether a packet can be sent as immediate data
+ * @skb: the packet
+ *
+ * Returns true if a packet can be sent as an offload WR with immediate
+ * data. We currently use the same limit as for Ethernet packets.
+ */
+static inline int is_ofld_imm(const struct sk_buff *skb)
+{
+ return skb->len <= (MAX_IMM_TX_PKT_LEN -
+ sizeof(struct fw_ofld_tx_data_wr));
+}
+
+static void send_act_open_req(struct cxgbi_sock *csk, struct sk_buff *skb,
+ struct l2t_entry *e)
+{
+ struct cpl_act_open_req *req;
+ int wscale = cxgbi_sock_compute_wscale(csk->mss_idx);
+ unsigned long long opt0;
+ unsigned int opt2;
+ unsigned int qid_atid = ((unsigned int)csk->atid) |
+ (((unsigned int)csk->rss_qid) << 14);
+
+ opt0 = KEEP_ALIVE(1) |
+ WND_SCALE(wscale) |
+ MSS_IDX(csk->mss_idx) |
+ L2T_IDX(((struct l2t_entry *)csk->l2t)->idx) |
+ TX_CHAN(csk->tx_chan) |
+ SMAC_SEL(csk->smac_idx) |
+ ULP_MODE(ULP_MODE_ISCSI) |
+ RCV_BUFSIZ(cxgb4i_rcv_win >> 10);
+ opt2 = RX_CHANNEL(0) |
+ RSS_QUEUE_VALID |
+ (1 << 20) | (1 << 22) |
+ RSS_QUEUE(csk->rss_qid);
+
+ set_wr_txq(skb, CPL_PRIORITY_SETUP, csk->port_id);
+ req = (struct cpl_act_open_req *)skb->head;
+
+ INIT_TP_WR(req, 0);
+ OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ,
+ qid_atid));
+ req->local_port = csk->saddr.sin_port;
+ req->peer_port = csk->daddr.sin_port;
+ req->local_ip = csk->saddr.sin_addr.s_addr;
+ req->peer_ip = csk->daddr.sin_addr.s_addr;
+ req->opt0 = cpu_to_be64(opt0);
+ req->params = 0;
+ req->opt2 = cpu_to_be32(opt2);
+
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+ "csk 0x%p, %pI4:%u-%pI4:%u, atid %d, qid %u.\n",
+ csk, &req->local_ip, ntohs(req->local_port),
+ &req->peer_ip, ntohs(req->peer_port),
+ csk->atid, csk->rss_qid);
+
+ cxgb4_l2t_send(csk->cdev->ports[csk->port_id], skb, csk->l2t);
+}
+
+static void send_close_req(struct cxgbi_sock *csk)
+{
+ struct sk_buff *skb = csk->cpl_close;
+ struct cpl_close_con_req *req = (struct cpl_close_con_req *)skb->head;
+ unsigned int tid = csk->tid;
+
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+ "csk 0x%p,%u,0x%lx, tid %u.\n",
+ csk, csk->state, csk->flags, csk->tid);
+ csk->cpl_close = NULL;
+ set_wr_txq(skb, CPL_PRIORITY_DATA, csk->port_id);
+ INIT_TP_WR(req, tid);
+ OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_CLOSE_CON_REQ, tid));
+ req->rsvd = 0;
+
+ cxgbi_sock_skb_entail(csk, skb);
+ if (csk->state >= CTP_ESTABLISHED)
+ push_tx_frames(csk, 1);
+}
+
+static void abort_arp_failure(void *handle, struct sk_buff *skb)
+{
+ struct cxgbi_sock *csk = (struct cxgbi_sock *)handle;
+ struct cpl_abort_req *req;
+
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+ "csk 0x%p,%u,0x%lx, tid %u, abort.\n",
+ csk, csk->state, csk->flags, csk->tid);
+ req = (struct cpl_abort_req *)skb->data;
+ req->cmd = CPL_ABORT_NO_RST;
+ cxgb4_ofld_send(csk->cdev->ports[csk->port_id], skb);
+}
+
+static void send_abort_req(struct cxgbi_sock *csk)
+{
+ struct cpl_abort_req *req;
+ struct sk_buff *skb = csk->cpl_abort_req;
+
+ if (unlikely(csk->state == CTP_ABORTING) || !skb || !csk->cdev)
+ return;
+ cxgbi_sock_set_state(csk, CTP_ABORTING);
+ cxgbi_sock_set_flag(csk, CTPF_ABORT_RPL_PENDING);
+ cxgbi_sock_purge_write_queue(csk);
+
+ csk->cpl_abort_req = NULL;
+ req = (struct cpl_abort_req *)skb->head;
+ set_queue(skb, CPL_PRIORITY_DATA, csk);
+ req->cmd = CPL_ABORT_SEND_RST;
+ t4_set_arp_err_handler(skb, csk, abort_arp_failure);
+ INIT_TP_WR(req, csk->tid);
+ OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_ABORT_REQ, csk->tid));
+ req->rsvd0 = htonl(csk->snd_nxt);
+ req->rsvd1 = !cxgbi_sock_flag(csk, CTPF_TX_DATA_SENT);
+
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+ "csk 0x%p,%u,0x%lx,%u, snd_nxt %u, 0x%x.\n",
+ csk, csk->state, csk->flags, csk->tid, csk->snd_nxt,
+ req->rsvd1);
+
+ cxgb4_l2t_send(csk->cdev->ports[csk->port_id], skb, csk->l2t);
+}
+
+static void send_abort_rpl(struct cxgbi_sock *csk, int rst_status)
+{
+ struct sk_buff *skb = csk->cpl_abort_rpl;
+ struct cpl_abort_rpl *rpl = (struct cpl_abort_rpl *)skb->head;
+
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+ "csk 0x%p,%u,0x%lx,%u, status %d.\n",
+ csk, csk->state, csk->flags, csk->tid, rst_status);
+
+ csk->cpl_abort_rpl = NULL;
+ set_queue(skb, CPL_PRIORITY_DATA, csk);
+ INIT_TP_WR(rpl, csk->tid);
+ OPCODE_TID(rpl) = cpu_to_be32(MK_OPCODE_TID(CPL_ABORT_RPL, csk->tid));
+ rpl->cmd = rst_status;
+ cxgb4_ofld_send(csk->cdev->ports[csk->port_id], skb);
+}
+
+/*
+ * CPL connection rx data ack: host ->
+ * Send RX credits through an RX_DATA_ACK CPL message. Returns the number of
+ * credits sent.
+ */
+static u32 send_rx_credits(struct cxgbi_sock *csk, u32 credits)
+{
+ struct sk_buff *skb;
+ struct cpl_rx_data_ack *req;
+
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_PDU_RX,
+ "csk 0x%p,%u,0x%lx,%u, credit %u.\n",
+ csk, csk->state, csk->flags, csk->tid, credits);
+
+ skb = alloc_wr(sizeof(*req), 0, GFP_ATOMIC);
+ if (!skb) {
+ pr_info("csk 0x%p, credit %u, OOM.\n", csk, credits);
+ return 0;
+ }
+ req = (struct cpl_rx_data_ack *)skb->head;
+
+ set_wr_txq(skb, CPL_PRIORITY_ACK, csk->port_id);
+ INIT_TP_WR(req, csk->tid);
+ OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_RX_DATA_ACK,
+ csk->tid));
+ req->credit_dack = cpu_to_be32(RX_CREDITS(credits) | RX_FORCE_ACK(1));
+ cxgb4_ofld_send(csk->cdev->ports[csk->port_id], skb);
+ return credits;
+}
+
+/*
+ * sgl_len - calculates the size of an SGL of the given capacity
+ * @n: the number of SGL entries
+ * Calculates the number of flits needed for a scatter/gather list that
+ * can hold the given number of entries.
+ */
+static inline unsigned int sgl_len(unsigned int n)
+{
+ n--;
+ return (3 * n) / 2 + (n & 1) + 2;
+}
+
+/*
+ * calc_tx_flits_ofld - calculate # of flits for an offload packet
+ * @skb: the packet
+ *
+ * Returns the number of flits needed for the given offload packet.
+ * These packets are already fully constructed and no additional headers
+ * will be added.
+ */
+static inline unsigned int calc_tx_flits_ofld(const struct sk_buff *skb)
+{
+ unsigned int flits, cnt;
+
+ if (is_ofld_imm(skb))
+ return DIV_ROUND_UP(skb->len, 8);
+ flits = skb_transport_offset(skb) / 8;
+ cnt = skb_shinfo(skb)->nr_frags;
+ if (skb->tail != skb->transport_header)
+ cnt++;
+ return flits + sgl_len(cnt);
+}
+
+static inline void send_tx_flowc_wr(struct cxgbi_sock *csk)
+{
+ struct sk_buff *skb;
+ struct fw_flowc_wr *flowc;
+ int flowclen, i;
+
+ flowclen = 80;
+ skb = alloc_wr(flowclen, 0, GFP_ATOMIC);
+ flowc = (struct fw_flowc_wr *)skb->head;
+ flowc->op_to_nparams =
+ htonl(FW_WR_OP(FW_FLOWC_WR) | FW_FLOWC_WR_NPARAMS(8));
+ flowc->flowid_len16 =
+ htonl(FW_WR_LEN16(DIV_ROUND_UP(72, 16)) |
+ FW_WR_FLOWID(csk->tid));
+ flowc->mnemval[0].mnemonic = FW_FLOWC_MNEM_PFNVFN;
+ flowc->mnemval[0].val = htonl(csk->cdev->pfvf);
+ flowc->mnemval[1].mnemonic = FW_FLOWC_MNEM_CH;
+ flowc->mnemval[1].val = htonl(csk->tx_chan);
+ flowc->mnemval[2].mnemonic = FW_FLOWC_MNEM_PORT;
+ flowc->mnemval[2].val = htonl(csk->tx_chan);
+ flowc->mnemval[3].mnemonic = FW_FLOWC_MNEM_IQID;
+ flowc->mnemval[3].val = htonl(csk->rss_qid);
+ flowc->mnemval[4].mnemonic = FW_FLOWC_MNEM_SNDNXT;
+ flowc->mnemval[4].val = htonl(csk->snd_nxt);
+ flowc->mnemval[5].mnemonic = FW_FLOWC_MNEM_RCVNXT;
+ flowc->mnemval[5].val = htonl(csk->rcv_nxt);
+ flowc->mnemval[6].mnemonic = FW_FLOWC_MNEM_SNDBUF;
+ flowc->mnemval[6].val = htonl(cxgb4i_snd_win);
+ flowc->mnemval[7].mnemonic = FW_FLOWC_MNEM_MSS;
+ flowc->mnemval[7].val = htonl(csk->advmss);
+ flowc->mnemval[8].mnemonic = 0;
+ flowc->mnemval[8].val = 0;
+ for (i = 0; i < 9; i++) {
+ flowc->mnemval[i].r4[0] = 0;
+ flowc->mnemval[i].r4[1] = 0;
+ flowc->mnemval[i].r4[2] = 0;
+ }
+ set_queue(skb, CPL_PRIORITY_DATA, csk);
+
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+ "csk 0x%p, tid 0x%x, %u,%u,%u,%u,%u,%u,%u.\n",
+ csk, csk->tid, 0, csk->tx_chan, csk->rss_qid,
+ csk->snd_nxt, csk->rcv_nxt, cxgb4i_snd_win,
+ csk->advmss);
+
+ cxgb4_ofld_send(csk->cdev->ports[csk->port_id], skb);
+}
+
+static inline void make_tx_data_wr(struct cxgbi_sock *csk, struct sk_buff *skb,
+ int dlen, int len, u32 credits, int compl)
+{
+ struct fw_ofld_tx_data_wr *req;
+ unsigned int submode = cxgbi_skcb_ulp_mode(skb) & 3;
+ unsigned int wr_ulp_mode = 0;
+
+ req = (struct fw_ofld_tx_data_wr *)__skb_push(skb, sizeof(*req));
+
+ if (is_ofld_imm(skb)) {
+ req->op_to_immdlen = htonl(FW_WR_OP(FW_OFLD_TX_DATA_WR) |
+ FW_WR_COMPL(1) |
+ FW_WR_IMMDLEN(dlen));
+ req->flowid_len16 = htonl(FW_WR_FLOWID(csk->tid) |
+ FW_WR_LEN16(credits));
+ } else {
+ req->op_to_immdlen =
+ cpu_to_be32(FW_WR_OP(FW_OFLD_TX_DATA_WR) |
+ FW_WR_COMPL(1) |
+ FW_WR_IMMDLEN(0));
+ req->flowid_len16 =
+ cpu_to_be32(FW_WR_FLOWID(csk->tid) |
+ FW_WR_LEN16(credits));
+ }
+ if (submode)
+ wr_ulp_mode = FW_OFLD_TX_DATA_WR_ULPMODE(ULP2_MODE_ISCSI) |
+ FW_OFLD_TX_DATA_WR_ULPSUBMODE(submode);
+ req->tunnel_to_proxy = htonl(wr_ulp_mode) |
+ FW_OFLD_TX_DATA_WR_SHOVE(skb_peek(&csk->write_queue) ? 0 : 1);
+ req->plen = htonl(len);
+ if (!cxgbi_sock_flag(csk, CTPF_TX_DATA_SENT))
+ cxgbi_sock_set_flag(csk, CTPF_TX_DATA_SENT);
+}
+
+static void arp_failure_skb_discard(void *handle, struct sk_buff *skb)
+{
+ kfree_skb(skb);
+}
+
+static int push_tx_frames(struct cxgbi_sock *csk, int req_completion)
+{
+ int total_size = 0;
+ struct sk_buff *skb;
+
+ if (unlikely(csk->state < CTP_ESTABLISHED ||
+ csk->state == CTP_CLOSE_WAIT_1 || csk->state >= CTP_ABORTING)) {
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK |
+ 1 << CXGBI_DBG_PDU_TX,
+ "csk 0x%p,%u,0x%lx,%u, in closing state.\n",
+ csk, csk->state, csk->flags, csk->tid);
+ return 0;
+ }
+
+ while (csk->wr_cred && (skb = skb_peek(&csk->write_queue)) != NULL) {
+ int dlen = skb->len;
+ int len = skb->len;
+ unsigned int credits_needed;
+
+ skb_reset_transport_header(skb);
+ if (is_ofld_imm(skb))
+ credits_needed = DIV_ROUND_UP(dlen +
+ sizeof(struct fw_ofld_tx_data_wr), 16);
+ else
+ credits_needed = DIV_ROUND_UP(8*calc_tx_flits_ofld(skb)
+ + sizeof(struct fw_ofld_tx_data_wr),
+ 16);
+
+ if (csk->wr_cred < credits_needed) {
+ log_debug(1 << CXGBI_DBG_PDU_TX,
+ "csk 0x%p, skb %u/%u, wr %d < %u.\n",
+ csk, skb->len, skb->data_len,
+ credits_needed, csk->wr_cred);
+ break;
+ }
+ __skb_unlink(skb, &csk->write_queue);
+ set_queue(skb, CPL_PRIORITY_DATA, csk);
+ skb->csum = credits_needed;
+ csk->wr_cred -= credits_needed;
+ csk->wr_una_cred += credits_needed;
+ cxgbi_sock_enqueue_wr(csk, skb);
+
+ log_debug(1 << CXGBI_DBG_PDU_TX,
+ "csk 0x%p, skb %u/%u, wr %d, left %u, unack %u.\n",
+ csk, skb->len, skb->data_len, credits_needed,
+ csk->wr_cred, csk->wr_una_cred);
+
+ if (likely(cxgbi_skcb_test_flag(skb, SKCBF_TX_NEED_HDR))) {
+ if (!cxgbi_sock_flag(csk, CTPF_TX_DATA_SENT)) {
+ send_tx_flowc_wr(csk);
+ skb->csum += 5;
+ csk->wr_cred -= 5;
+ csk->wr_una_cred += 5;
+ }
+ len += cxgbi_ulp_extra_len(cxgbi_skcb_ulp_mode(skb));
+ make_tx_data_wr(csk, skb, dlen, len, credits_needed,
+ req_completion);
+ csk->snd_nxt += len;
+ cxgbi_skcb_clear_flag(skb, SKCBF_TX_NEED_HDR);
+ }
+ total_size += skb->truesize;
+ t4_set_arp_err_handler(skb, csk, arp_failure_skb_discard);
+
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_PDU_TX,
+ "csk 0x%p,%u,0x%lx,%u, skb 0x%p, %u.\n",
+ csk, csk->state, csk->flags, csk->tid, skb, len);
+
+ cxgb4_l2t_send(csk->cdev->ports[csk->port_id], skb, csk->l2t);
+ }
+ return total_size;
+}
+
+static inline void free_atid(struct cxgbi_sock *csk)
+{
+ struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(csk->cdev);
+
+ if (cxgbi_sock_flag(csk, CTPF_HAS_ATID)) {
+ cxgb4_free_atid(lldi->tids, csk->atid);
+ cxgbi_sock_clear_flag(csk, CTPF_HAS_ATID);
+ cxgbi_sock_put(csk);
+ }
+}
+
+static void do_act_establish(struct cxgbi_device *cdev, struct sk_buff *skb)
+{
+ struct cxgbi_sock *csk;
+ struct cpl_act_establish *req = (struct cpl_act_establish *)skb->data;
+ unsigned short tcp_opt = ntohs(req->tcp_opt);
+ unsigned int tid = GET_TID(req);
+ unsigned int atid = GET_TID_TID(ntohl(req->tos_atid));
+ struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev);
+ struct tid_info *t = lldi->tids;
+ u32 rcv_isn = be32_to_cpu(req->rcv_isn);
+
+ csk = lookup_atid(t, atid);
+ if (unlikely(!csk)) {
+ pr_err("NO conn. for atid %u, cdev 0x%p.\n", atid, cdev);
+ goto rel_skb;
+ }
+
+ if (csk->atid != atid) {
+ pr_err("bad conn atid %u, csk 0x%p,%u,0x%lx,tid %u, atid %u.\n",
+ atid, csk, csk->state, csk->flags, csk->tid, csk->atid);
+ goto rel_skb;
+ }
+
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+ "csk 0x%p,%u,0x%lx, tid %u, atid %u, rseq %u.\n",
+ csk, csk->state, csk->flags, tid, atid, rcv_isn);
+
+ cxgbi_sock_get(csk);
+ csk->tid = tid;
+ cxgb4_insert_tid(lldi->tids, csk, tid);
+ cxgbi_sock_set_flag(csk, CTPF_HAS_TID);
+
+ free_atid(csk);
+
+ spin_lock_bh(&csk->lock);
+ if (unlikely(csk->state != CTP_ACTIVE_OPEN))
+ pr_info("csk 0x%p,%u,0x%lx,%u, got EST.\n",
+ csk, csk->state, csk->flags, csk->tid);
+
+ if (csk->retry_timer.function) {
+ del_timer(&csk->retry_timer);
+ csk->retry_timer.function = NULL;
+ }
+
+ csk->copied_seq = csk->rcv_wup = csk->rcv_nxt = rcv_isn;
+ /*
+ * Causes the first RX_DATA_ACK to supply any Rx credits we couldn't
+ * pass through opt0.
+ */
+ if (cxgb4i_rcv_win > (RCV_BUFSIZ_MASK << 10))
+ csk->rcv_wup -= cxgb4i_rcv_win - (RCV_BUFSIZ_MASK << 10);
+
+ csk->advmss = lldi->mtus[GET_TCPOPT_MSS(tcp_opt)] - 40;
+ if (GET_TCPOPT_TSTAMP(tcp_opt))
+ csk->advmss -= 12;
+ if (csk->advmss < 128)
+ csk->advmss = 128;
+
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+ "csk 0x%p, mss_idx %u, advmss %u.\n",
+ csk, GET_TCPOPT_MSS(tcp_opt), csk->advmss);
+
+ cxgbi_sock_established(csk, ntohl(req->snd_isn), ntohs(req->tcp_opt));
+
+ if (unlikely(cxgbi_sock_flag(csk, CTPF_ACTIVE_CLOSE_NEEDED)))
+ send_abort_req(csk);
+ else {
+ if (skb_queue_len(&csk->write_queue))
+ push_tx_frames(csk, 0);
+ cxgbi_conn_tx_open(csk);
+ }
+ spin_unlock_bh(&csk->lock);
+
+rel_skb:
+ __kfree_skb(skb);
+}
+
+static int act_open_rpl_status_to_errno(int status)
+{
+ switch (status) {
+ case CPL_ERR_CONN_RESET:
+ return -ECONNREFUSED;
+ case CPL_ERR_ARP_MISS:
+ return -EHOSTUNREACH;
+ case CPL_ERR_CONN_TIMEDOUT:
+ return -ETIMEDOUT;
+ case CPL_ERR_TCAM_FULL:
+ return -ENOMEM;
+ case CPL_ERR_CONN_EXIST:
+ return -EADDRINUSE;
+ default:
+ return -EIO;
+ }
+}
+
+static void csk_act_open_retry_timer(unsigned long data)
+{
+ struct sk_buff *skb;
+ struct cxgbi_sock *csk = (struct cxgbi_sock *)data;
+
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+ "csk 0x%p,%u,0x%lx,%u.\n",
+ csk, csk->state, csk->flags, csk->tid);
+
+ cxgbi_sock_get(csk);
+ spin_lock_bh(&csk->lock);
+ skb = alloc_wr(sizeof(struct cpl_act_open_req), 0, GFP_ATOMIC);
+ if (!skb)
+ cxgbi_sock_fail_act_open(csk, -ENOMEM);
+ else {
+ skb->sk = (struct sock *)csk;
+ t4_set_arp_err_handler(skb, csk,
+ cxgbi_sock_act_open_req_arp_failure);
+ send_act_open_req(csk, skb, csk->l2t);
+ }
+ spin_unlock_bh(&csk->lock);
+ cxgbi_sock_put(csk);
+}
+
+static void do_act_open_rpl(struct cxgbi_device *cdev, struct sk_buff *skb)
+{
+ struct cxgbi_sock *csk;
+ struct cpl_act_open_rpl *rpl = (struct cpl_act_open_rpl *)skb->data;
+ unsigned int tid = GET_TID(rpl);
+ unsigned int atid =
+ GET_TID_TID(GET_AOPEN_ATID(be32_to_cpu(rpl->atid_status)));
+ unsigned int status = GET_AOPEN_STATUS(be32_to_cpu(rpl->atid_status));
+ struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev);
+ struct tid_info *t = lldi->tids;
+
+ csk = lookup_atid(t, atid);
+ if (unlikely(!csk)) {
+ pr_err("NO matching conn. atid %u, tid %u.\n", atid, tid);
+ goto rel_skb;
+ }
+
+ pr_info("%pI4:%u-%pI4:%u, atid %u,%u, status %u, csk 0x%p,%u,0x%lx.\n",
+ &csk->saddr.sin_addr.s_addr, ntohs(csk->saddr.sin_port),
+ &csk->daddr.sin_addr.s_addr, ntohs(csk->daddr.sin_port),
+ atid, tid, status, csk, csk->state, csk->flags);
+
+ if (status && status != CPL_ERR_TCAM_FULL &&
+ status != CPL_ERR_CONN_EXIST &&
+ status != CPL_ERR_ARP_MISS)
+ cxgb4_remove_tid(lldi->tids, csk->port_id, GET_TID(rpl));
+
+ cxgbi_sock_get(csk);
+ spin_lock_bh(&csk->lock);
+
+ if (status == CPL_ERR_CONN_EXIST &&
+ csk->retry_timer.function != csk_act_open_retry_timer) {
+ csk->retry_timer.function = csk_act_open_retry_timer;
+ mod_timer(&csk->retry_timer, jiffies + HZ / 2);
+ } else
+ cxgbi_sock_fail_act_open(csk,
+ act_open_rpl_status_to_errno(status));
+
+ spin_unlock_bh(&csk->lock);
+ cxgbi_sock_put(csk);
+rel_skb:
+ __kfree_skb(skb);
+}
+
+static void do_peer_close(struct cxgbi_device *cdev, struct sk_buff *skb)
+{
+ struct cxgbi_sock *csk;
+ struct cpl_peer_close *req = (struct cpl_peer_close *)skb->data;
+ unsigned int tid = GET_TID(req);
+ struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev);
+ struct tid_info *t = lldi->tids;
+
+ csk = lookup_tid(t, tid);
+ if (unlikely(!csk)) {
+ pr_err("can't find connection for tid %u.\n", tid);
+ goto rel_skb;
+ }
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+ "csk 0x%p,%u,0x%lx,%u.\n",
+ csk, csk->state, csk->flags, csk->tid);
+ cxgbi_sock_rcv_peer_close(csk);
+rel_skb:
+ __kfree_skb(skb);
+}
+
+static void do_close_con_rpl(struct cxgbi_device *cdev, struct sk_buff *skb)
+{
+ struct cxgbi_sock *csk;
+ struct cpl_close_con_rpl *rpl = (struct cpl_close_con_rpl *)skb->data;
+ unsigned int tid = GET_TID(rpl);
+ struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev);
+ struct tid_info *t = lldi->tids;
+
+ csk = lookup_tid(t, tid);
+ if (unlikely(!csk)) {
+ pr_err("can't find connection for tid %u.\n", tid);
+ goto rel_skb;
+ }
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+ "csk 0x%p,%u,0x%lx,%u.\n",
+ csk, csk->state, csk->flags, csk->tid);
+ cxgbi_sock_rcv_close_conn_rpl(csk, ntohl(rpl->snd_nxt));
+rel_skb:
+ __kfree_skb(skb);
+}
+
+static int abort_status_to_errno(struct cxgbi_sock *csk, int abort_reason,
+ int *need_rst)
+{
+ switch (abort_reason) {
+ case CPL_ERR_BAD_SYN: /* fall through */
+ case CPL_ERR_CONN_RESET:
+ return csk->state > CTP_ESTABLISHED ?
+ -EPIPE : -ECONNRESET;
+ case CPL_ERR_XMIT_TIMEDOUT:
+ case CPL_ERR_PERSIST_TIMEDOUT:
+ case CPL_ERR_FINWAIT2_TIMEDOUT:
+ case CPL_ERR_KEEPALIVE_TIMEDOUT:
+ return -ETIMEDOUT;
+ default:
+ return -EIO;
+ }
+}
+
+static void do_abort_req_rss(struct cxgbi_device *cdev, struct sk_buff *skb)
+{
+ struct cxgbi_sock *csk;
+ struct cpl_abort_req_rss *req = (struct cpl_abort_req_rss *)skb->data;
+ unsigned int tid = GET_TID(req);
+ struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev);
+ struct tid_info *t = lldi->tids;
+ int rst_status = CPL_ABORT_NO_RST;
+
+ csk = lookup_tid(t, tid);
+ if (unlikely(!csk)) {
+ pr_err("can't find connection for tid %u.\n", tid);
+ goto rel_skb;
+ }
+
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+ "csk 0x%p,%u,0x%lx, tid %u, status 0x%x.\n",
+ csk, csk->state, csk->flags, csk->tid, req->status);
+
+ if (req->status == CPL_ERR_RTX_NEG_ADVICE ||
+ req->status == CPL_ERR_PERSIST_NEG_ADVICE)
+ goto rel_skb;
+
+ cxgbi_sock_get(csk);
+ spin_lock_bh(&csk->lock);
+
+ if (!cxgbi_sock_flag(csk, CTPF_ABORT_REQ_RCVD)) {
+ cxgbi_sock_set_flag(csk, CTPF_ABORT_REQ_RCVD);
+ cxgbi_sock_set_state(csk, CTP_ABORTING);
+ goto done;
+ }
+
+ cxgbi_sock_clear_flag(csk, CTPF_ABORT_REQ_RCVD);
+ send_abort_rpl(csk, rst_status);
+
+ if (!cxgbi_sock_flag(csk, CTPF_ABORT_RPL_PENDING)) {
+ csk->err = abort_status_to_errno(csk, req->status, &rst_status);
+ cxgbi_sock_closed(csk);
+ }
+done:
+ spin_unlock_bh(&csk->lock);
+ cxgbi_sock_put(csk);
+rel_skb:
+ __kfree_skb(skb);
+}
+
+static void do_abort_rpl_rss(struct cxgbi_device *cdev, struct sk_buff *skb)
+{
+ struct cxgbi_sock *csk;
+ struct cpl_abort_rpl_rss *rpl = (struct cpl_abort_rpl_rss *)skb->data;
+ unsigned int tid = GET_TID(rpl);
+ struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev);
+ struct tid_info *t = lldi->tids;
+
+ csk = lookup_tid(t, tid);
+ if (!csk)
+ goto rel_skb;
+
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+ "status 0x%x, csk 0x%p, s %u, 0x%lx.\n",
+ rpl->status, csk, csk ? csk->state : 0,
+ csk ? csk->flags : 0UL);
+
+ if (rpl->status == CPL_ERR_ABORT_FAILED)
+ goto rel_skb;
+
+ cxgbi_sock_rcv_abort_rpl(csk);
+rel_skb:
+ __kfree_skb(skb);
+}
+
+static void do_rx_iscsi_hdr(struct cxgbi_device *cdev, struct sk_buff *skb)
+{
+ struct cxgbi_sock *csk;
+ struct cpl_iscsi_hdr *cpl = (struct cpl_iscsi_hdr *)skb->data;
+ unsigned short pdu_len_ddp = be16_to_cpu(cpl->pdu_len_ddp);
+ unsigned int tid = GET_TID(cpl);
+ struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev);
+ struct tid_info *t = lldi->tids;
+
+ csk = lookup_tid(t, tid);
+ if (unlikely(!csk)) {
+ pr_err("can't find conn. for tid %u.\n", tid);
+ goto rel_skb;
+ }
+
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_PDU_RX,
+ "csk 0x%p,%u,0x%lx, tid %u, skb 0x%p,%u, 0x%x.\n",
+ csk, csk->state, csk->flags, csk->tid, skb, skb->len,
+ pdu_len_ddp);
+
+ spin_lock_bh(&csk->lock);
+
+ if (unlikely(csk->state >= CTP_PASSIVE_CLOSE)) {
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+ "csk 0x%p,%u,0x%lx,%u, bad state.\n",
+ csk, csk->state, csk->flags, csk->tid);
+ if (csk->state != CTP_ABORTING)
+ goto abort_conn;
+ else
+ goto discard;
+ }
+
+ cxgbi_skcb_tcp_seq(skb) = ntohl(cpl->seq);
+ cxgbi_skcb_flags(skb) = 0;
+
+ skb_reset_transport_header(skb);
+ __skb_pull(skb, sizeof(*cpl));
+ __pskb_trim(skb, ntohs(cpl->len));
+
+ if (!csk->skb_ulp_lhdr) {
+ unsigned char *bhs;
+ unsigned int hlen, dlen;
+
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_PDU_RX,
+ "csk 0x%p,%u,0x%lx, tid %u, skb 0x%p header.\n",
+ csk, csk->state, csk->flags, csk->tid, skb);
+ csk->skb_ulp_lhdr = skb;
+ cxgbi_skcb_set_flag(skb, SKCBF_RX_HDR);
+
+ if (cxgbi_skcb_tcp_seq(skb) != csk->rcv_nxt) {
+ pr_info("tid %u, CPL_ISCSI_HDR, bad seq, 0x%x/0x%x.\n",
+ csk->tid, cxgbi_skcb_tcp_seq(skb),
+ csk->rcv_nxt);
+ goto abort_conn;
+ }
+
+ bhs = skb->data;
+ hlen = ntohs(cpl->len);
+ dlen = ntohl(*(unsigned int *)(bhs + 4)) & 0xFFFFFF;
+
+ if ((hlen + dlen) != ISCSI_PDU_LEN(pdu_len_ddp) - 40) {
+ pr_info("tid 0x%x, CPL_ISCSI_HDR, pdu len "
+ "mismatch %u != %u + %u, seq 0x%x.\n",
+ csk->tid, ISCSI_PDU_LEN(pdu_len_ddp) - 40,
+ hlen, dlen, cxgbi_skcb_tcp_seq(skb));
+ goto abort_conn;
+ }
+
+ cxgbi_skcb_rx_pdulen(skb) = (hlen + dlen + 3) & (~0x3);
+ if (dlen)
+ cxgbi_skcb_rx_pdulen(skb) += csk->dcrc_len;
+ csk->rcv_nxt += cxgbi_skcb_rx_pdulen(skb);
+
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_PDU_RX,
+ "csk 0x%p, skb 0x%p, 0x%x,%u+%u,0x%x,0x%x.\n",
+ csk, skb, *bhs, hlen, dlen,
+ ntohl(*((unsigned int *)(bhs + 16))),
+ ntohl(*((unsigned int *)(bhs + 24))));
+
+ } else {
+ struct sk_buff *lskb = csk->skb_ulp_lhdr;
+
+ cxgbi_skcb_set_flag(lskb, SKCBF_RX_DATA);
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_PDU_RX,
+ "csk 0x%p,%u,0x%lx, skb 0x%p data, 0x%p.\n",
+ csk, csk->state, csk->flags, skb, lskb);
+ }
+
+ __skb_queue_tail(&csk->receive_queue, skb);
+ spin_unlock_bh(&csk->lock);
+ return;
+
+abort_conn:
+ send_abort_req(csk);
+discard:
+ spin_unlock_bh(&csk->lock);
+rel_skb:
+ __kfree_skb(skb);
+}
+
+static void do_rx_data_ddp(struct cxgbi_device *cdev,
+ struct sk_buff *skb)
+{
+ struct cxgbi_sock *csk;
+ struct sk_buff *lskb;
+ struct cpl_rx_data_ddp *rpl = (struct cpl_rx_data_ddp *)skb->data;
+ unsigned int tid = GET_TID(rpl);
+ struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev);
+ struct tid_info *t = lldi->tids;
+ unsigned int status = ntohl(rpl->ddpvld);
+
+ csk = lookup_tid(t, tid);
+ if (unlikely(!csk)) {
+ pr_err("can't find connection for tid %u.\n", tid);
+ goto rel_skb;
+ }
+
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_PDU_RX,
+ "csk 0x%p,%u,0x%lx, skb 0x%p,0x%x, lhdr 0x%p.\n",
+ csk, csk->state, csk->flags, skb, status, csk->skb_ulp_lhdr);
+
+ spin_lock_bh(&csk->lock);
+
+ if (unlikely(csk->state >= CTP_PASSIVE_CLOSE)) {
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+ "csk 0x%p,%u,0x%lx,%u, bad state.\n",
+ csk, csk->state, csk->flags, csk->tid);
+ if (csk->state != CTP_ABORTING)
+ goto abort_conn;
+ else
+ goto discard;
+ }
+
+ if (!csk->skb_ulp_lhdr) {
+ pr_err("tid 0x%x, rcv RX_DATA_DDP w/o pdu bhs.\n", csk->tid);
+ goto abort_conn;
+ }
+
+ lskb = csk->skb_ulp_lhdr;
+ csk->skb_ulp_lhdr = NULL;
+
+ cxgbi_skcb_rx_ddigest(lskb) = ntohl(rpl->ulp_crc);
+
+ if (ntohs(rpl->len) != cxgbi_skcb_rx_pdulen(lskb))
+ pr_info("tid 0x%x, RX_DATA_DDP pdulen %u != %u.\n",
+ csk->tid, ntohs(rpl->len), cxgbi_skcb_rx_pdulen(lskb));
+
+ if (status & (1 << CPL_RX_DDP_STATUS_HCRC_SHIFT)) {
+ pr_info("csk 0x%p, lhdr 0x%p, status 0x%x, hcrc bad 0x%lx.\n",
+ csk, lskb, status, cxgbi_skcb_flags(lskb));
+ cxgbi_skcb_set_flag(lskb, SKCBF_RX_HCRC_ERR);
+ }
+ if (status & (1 << CPL_RX_DDP_STATUS_DCRC_SHIFT)) {
+ pr_info("csk 0x%p, lhdr 0x%p, status 0x%x, dcrc bad 0x%lx.\n",
+ csk, lskb, status, cxgbi_skcb_flags(lskb));
+ cxgbi_skcb_set_flag(lskb, SKCBF_RX_DCRC_ERR);
+ }
+ if (status & (1 << CPL_RX_DDP_STATUS_PAD_SHIFT)) {
+ log_debug(1 << CXGBI_DBG_PDU_RX,
+ "csk 0x%p, lhdr 0x%p, status 0x%x, pad bad.\n",
+ csk, lskb, status);
+ cxgbi_skcb_set_flag(lskb, SKCBF_RX_PAD_ERR);
+ }
+ if ((status & (1 << CPL_RX_DDP_STATUS_DDP_SHIFT)) &&
+ !cxgbi_skcb_test_flag(lskb, SKCBF_RX_DATA)) {
+ log_debug(1 << CXGBI_DBG_PDU_RX,
+ "csk 0x%p, lhdr 0x%p, 0x%x, data ddp'ed.\n",
+ csk, lskb, status);
+ cxgbi_skcb_set_flag(lskb, SKCBF_RX_DATA_DDPD);
+ }
+ log_debug(1 << CXGBI_DBG_PDU_RX,
+ "csk 0x%p, lskb 0x%p, f 0x%lx.\n",
+ csk, lskb, cxgbi_skcb_flags(lskb));
+
+ cxgbi_skcb_set_flag(lskb, SKCBF_RX_STATUS);
+ cxgbi_conn_pdu_ready(csk);
+ spin_unlock_bh(&csk->lock);
+ goto rel_skb;
+
+abort_conn:
+ send_abort_req(csk);
+discard:
+ spin_unlock_bh(&csk->lock);
+rel_skb:
+ __kfree_skb(skb);
+}
+
+static void do_fw4_ack(struct cxgbi_device *cdev, struct sk_buff *skb)
+{
+ struct cxgbi_sock *csk;
+ struct cpl_fw4_ack *rpl = (struct cpl_fw4_ack *)skb->data;
+ unsigned int tid = GET_TID(rpl);
+ struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev);
+ struct tid_info *t = lldi->tids;
+
+ csk = lookup_tid(t, tid);
+ if (unlikely(!csk))
+ pr_err("can't find connection for tid %u.\n", tid);
+ else {
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+ "csk 0x%p,%u,0x%lx,%u.\n",
+ csk, csk->state, csk->flags, csk->tid);
+ cxgbi_sock_rcv_wr_ack(csk, rpl->credits, ntohl(rpl->snd_una),
+ rpl->seq_vld);
+ }
+ __kfree_skb(skb);
+}
+
+static void do_set_tcb_rpl(struct cxgbi_device *cdev, struct sk_buff *skb)
+{
+ struct cpl_set_tcb_rpl *rpl = (struct cpl_set_tcb_rpl *)skb->data;
+ unsigned int tid = GET_TID(rpl);
+ struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev);
+ struct tid_info *t = lldi->tids;
+ struct cxgbi_sock *csk;
+
+ csk = lookup_tid(t, tid);
+ if (!csk)
+ pr_err("can't find conn. for tid %u.\n", tid);
+
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+ "csk 0x%p,%u,%lx,%u, status 0x%x.\n",
+ csk, csk->state, csk->flags, csk->tid, rpl->status);
+
+ if (rpl->status != CPL_ERR_NONE)
+ pr_err("csk 0x%p,%u, SET_TCB_RPL status %u.\n",
+ csk, tid, rpl->status);
+
+ __kfree_skb(skb);
+}
+
+static int alloc_cpls(struct cxgbi_sock *csk)
+{
+ csk->cpl_close = alloc_wr(sizeof(struct cpl_close_con_req),
+ 0, GFP_KERNEL);
+ if (!csk->cpl_close)
+ return -ENOMEM;
+
+ csk->cpl_abort_req = alloc_wr(sizeof(struct cpl_abort_req),
+ 0, GFP_KERNEL);
+ if (!csk->cpl_abort_req)
+ goto free_cpls;
+
+ csk->cpl_abort_rpl = alloc_wr(sizeof(struct cpl_abort_rpl),
+ 0, GFP_KERNEL);
+ if (!csk->cpl_abort_rpl)
+ goto free_cpls;
+ return 0;
+
+free_cpls:
+ cxgbi_sock_free_cpl_skbs(csk);
+ return -ENOMEM;
+}
+
+static inline void l2t_put(struct cxgbi_sock *csk)
+{
+ if (csk->l2t) {
+ cxgb4_l2t_release(csk->l2t);
+ csk->l2t = NULL;
+ cxgbi_sock_put(csk);
+ }
+}
+
+static void release_offload_resources(struct cxgbi_sock *csk)
+{
+ struct cxgb4_lld_info *lldi;
+
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+ "csk 0x%p,%u,0x%lx,%u.\n",
+ csk, csk->state, csk->flags, csk->tid);
+
+ cxgbi_sock_free_cpl_skbs(csk);
+ if (csk->wr_cred != csk->wr_max_cred) {
+ cxgbi_sock_purge_wr_queue(csk);
+ cxgbi_sock_reset_wr_list(csk);
+ }
+
+ l2t_put(csk);
+ if (cxgbi_sock_flag(csk, CTPF_HAS_ATID))
+ free_atid(csk);
+ else if (cxgbi_sock_flag(csk, CTPF_HAS_TID)) {
+ lldi = cxgbi_cdev_priv(csk->cdev);
+ cxgb4_remove_tid(lldi->tids, 0, csk->tid);
+ cxgbi_sock_clear_flag(csk, CTPF_HAS_TID);
+ cxgbi_sock_put(csk);
+ }
+ csk->dst = NULL;
+ csk->cdev = NULL;
+}
+
+static int init_act_open(struct cxgbi_sock *csk)
+{
+ struct cxgbi_device *cdev = csk->cdev;
+ struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev);
+ struct net_device *ndev = cdev->ports[csk->port_id];
+ struct port_info *pi = netdev_priv(ndev);
+ struct sk_buff *skb = NULL;
+ unsigned int step;
+
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+ "csk 0x%p,%u,0x%lx,%u.\n",
+ csk, csk->state, csk->flags, csk->tid);
+
+ csk->atid = cxgb4_alloc_atid(lldi->tids, csk);
+ if (csk->atid < 0) {
+ pr_err("%s, NO atid available.\n", ndev->name);
+ return -EINVAL;
+ }
+ cxgbi_sock_set_flag(csk, CTPF_HAS_ATID);
+ cxgbi_sock_get(csk);
+
+ csk->l2t = cxgb4_l2t_get(lldi->l2t, csk->dst->neighbour, ndev, 0);
+ if (!csk->l2t) {
+ pr_err("%s, cannot alloc l2t.\n", ndev->name);
+ goto rel_resource;
+ }
+ cxgbi_sock_get(csk);
+
+ skb = alloc_wr(sizeof(struct cpl_act_open_req), 0, GFP_KERNEL);
+ if (!skb)
+ goto rel_resource;
+ skb->sk = (struct sock *)csk;
+ t4_set_arp_err_handler(skb, csk, cxgbi_sock_act_open_req_arp_failure);
+
+ if (!csk->mtu)
+ csk->mtu = dst_mtu(csk->dst);
+ cxgb4_best_mtu(lldi->mtus, csk->mtu, &csk->mss_idx);
+ csk->tx_chan = cxgb4_port_chan(ndev);
+ /* SMT two entries per row */
+ csk->smac_idx = ((cxgb4_port_viid(ndev) & 0x7F)) << 1;
+ step = lldi->ntxq / lldi->nchan;
+ csk->txq_idx = cxgb4_port_idx(ndev) * step;
+ step = lldi->nrxq / lldi->nchan;
+ csk->rss_qid = lldi->rxq_ids[cxgb4_port_idx(ndev) * step];
+ csk->wr_max_cred = csk->wr_cred = lldi->wr_cred;
+ csk->wr_una_cred = 0;
+ cxgbi_sock_reset_wr_list(csk);
+ csk->err = 0;
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+ "csk 0x%p,p%d,%s, %u,%u,%u, mss %u,%u, smac %u.\n",
+ csk, pi->port_id, ndev->name, csk->tx_chan,
+ csk->txq_idx, csk->rss_qid, csk->mtu, csk->mss_idx,
+ csk->smac_idx);
+
+ cxgbi_sock_set_state(csk, CTP_ACTIVE_OPEN);
+ send_act_open_req(csk, skb, csk->l2t);
+ return 0;
+
+rel_resource:
+ if (skb)
+ __kfree_skb(skb);
+ return -EINVAL;
+}
+
+cxgb4i_cplhandler_func cxgb4i_cplhandlers[NUM_CPL_CMDS] = {
+ [CPL_ACT_ESTABLISH] = do_act_establish,
+ [CPL_ACT_OPEN_RPL] = do_act_open_rpl,
+ [CPL_PEER_CLOSE] = do_peer_close,
+ [CPL_ABORT_REQ_RSS] = do_abort_req_rss,
+ [CPL_ABORT_RPL_RSS] = do_abort_rpl_rss,
+ [CPL_CLOSE_CON_RPL] = do_close_con_rpl,
+ [CPL_FW4_ACK] = do_fw4_ack,
+ [CPL_ISCSI_HDR] = do_rx_iscsi_hdr,
+ [CPL_SET_TCB_RPL] = do_set_tcb_rpl,
+ [CPL_RX_DATA_DDP] = do_rx_data_ddp,
+};
+
+int cxgb4i_ofld_init(struct cxgbi_device *cdev)
+{
+ int rc;
+
+ if (cxgb4i_max_connect > CXGB4I_MAX_CONN)
+ cxgb4i_max_connect = CXGB4I_MAX_CONN;
+
+ rc = cxgbi_device_portmap_create(cdev, cxgb4i_sport_base,
+ cxgb4i_max_connect);
+ if (rc < 0)
+ return rc;
+
+ cdev->csk_release_offload_resources = release_offload_resources;
+ cdev->csk_push_tx_frames = push_tx_frames;
+ cdev->csk_send_abort_req = send_abort_req;
+ cdev->csk_send_close_req = send_close_req;
+ cdev->csk_send_rx_credits = send_rx_credits;
+ cdev->csk_alloc_cpls = alloc_cpls;
+ cdev->csk_init_act_open = init_act_open;
+
+ pr_info("cdev 0x%p, offload up, added.\n", cdev);
+ return 0;
+}
+
+/*
+ * functions to program the pagepod in h/w
+ */
+#define ULPMEM_IDATA_MAX_NPPODS 4 /* 256/PPOD_SIZE */
+static inline void ulp_mem_io_set_hdr(struct ulp_mem_io *req,
+ unsigned int wr_len, unsigned int dlen,
+ unsigned int pm_addr)
+{
+ struct ulptx_idata *idata = (struct ulptx_idata *)(req + 1);
+
+ INIT_ULPTX_WR(req, wr_len, 0, 0);
+ req->cmd = htonl(ULPTX_CMD(ULP_TX_MEM_WRITE) | (1 << 23));
+ req->dlen = htonl(ULP_MEMIO_DATA_LEN(dlen >> 5));
+ req->lock_addr = htonl(ULP_MEMIO_ADDR(pm_addr >> 5));
+ req->len16 = htonl(DIV_ROUND_UP(wr_len - sizeof(req->wr), 16));
+
+ idata->cmd_more = htonl(ULPTX_CMD(ULP_TX_SC_IMM));
+ idata->len = htonl(dlen);
+}
+
+static int ddp_ppod_write_idata(struct cxgbi_device *cdev, unsigned int port_id,
+ struct cxgbi_pagepod_hdr *hdr, unsigned int idx,
+ unsigned int npods,
+ struct cxgbi_gather_list *gl,
+ unsigned int gl_pidx)
+{
+ struct cxgbi_ddp_info *ddp = cdev->ddp;
+ struct sk_buff *skb;
+ struct ulp_mem_io *req;
+ struct ulptx_idata *idata;
+ struct cxgbi_pagepod *ppod;
+ unsigned int pm_addr = idx * PPOD_SIZE + ddp->llimit;
+ unsigned int dlen = PPOD_SIZE * npods;
+ unsigned int wr_len = roundup(sizeof(struct ulp_mem_io) +
+ sizeof(struct ulptx_idata) + dlen, 16);
+ unsigned int i;
+
+ skb = alloc_wr(wr_len, 0, GFP_ATOMIC);
+ if (!skb) {
+ pr_err("cdev 0x%p, idx %u, npods %u, OOM.\n",
+ cdev, idx, npods);
+ return -ENOMEM;
+ }
+ req = (struct ulp_mem_io *)skb->head;
+ set_queue(skb, CPL_PRIORITY_CONTROL, NULL);
+
+ ulp_mem_io_set_hdr(req, wr_len, dlen, pm_addr);
+ idata = (struct ulptx_idata *)(req + 1);
+ ppod = (struct cxgbi_pagepod *)(idata + 1);
+
+ for (i = 0; i < npods; i++, ppod++, gl_pidx += PPOD_PAGES_MAX) {
+ if (!hdr && !gl)
+ cxgbi_ddp_ppod_clear(ppod);
+ else
+ cxgbi_ddp_ppod_set(ppod, hdr, gl, gl_pidx);
+ }
+
+ cxgb4_ofld_send(cdev->ports[port_id], skb);
+ return 0;
+}
+
+static int ddp_set_map(struct cxgbi_sock *csk, struct cxgbi_pagepod_hdr *hdr,
+ unsigned int idx, unsigned int npods,
+ struct cxgbi_gather_list *gl)
+{
+ unsigned int i, cnt;
+ int err = 0;
+
+ for (i = 0; i < npods; i += cnt, idx += cnt) {
+ cnt = npods - i;
+ if (cnt > ULPMEM_IDATA_MAX_NPPODS)
+ cnt = ULPMEM_IDATA_MAX_NPPODS;
+ err = ddp_ppod_write_idata(csk->cdev, csk->port_id, hdr,
+ idx, cnt, gl, 4 * i);
+ if (err < 0)
+ break;
+ }
+ return err;
+}
+
+static void ddp_clear_map(struct cxgbi_hba *chba, unsigned int tag,
+ unsigned int idx, unsigned int npods)
+{
+ unsigned int i, cnt;
+ int err;
+
+ for (i = 0; i < npods; i += cnt, idx += cnt) {
+ cnt = npods - i;
+ if (cnt > ULPMEM_IDATA_MAX_NPPODS)
+ cnt = ULPMEM_IDATA_MAX_NPPODS;
+ err = ddp_ppod_write_idata(chba->cdev, chba->port_id, NULL,
+ idx, cnt, NULL, 0);
+ if (err < 0)
+ break;
+ }
+}
+
+static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk, unsigned int tid,
+ int pg_idx, bool reply)
+{
+ struct sk_buff *skb;
+ struct cpl_set_tcb_field *req;
+
+ if (!pg_idx || pg_idx >= DDP_PGIDX_MAX)
+ return 0;
+
+ skb = alloc_wr(sizeof(*req), 0, GFP_KERNEL);
+ if (!skb)
+ return -ENOMEM;
+
+ /* set up ulp page size */
+ req = (struct cpl_set_tcb_field *)skb->head;
+ INIT_TP_WR(req, csk->tid);
+ OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, csk->tid));
+ req->reply_ctrl = htons(NO_REPLY(reply) | QUEUENO(csk->rss_qid));
+ req->word_cookie = htons(0);
+ req->mask = cpu_to_be64(0x3 << 8);
+ req->val = cpu_to_be64(pg_idx << 8);
+ set_wr_txq(skb, CPL_PRIORITY_CONTROL, csk->port_id);
+
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+ "csk 0x%p, tid 0x%x, pg_idx %u.\n", csk, csk->tid, pg_idx);
+
+ cxgb4_ofld_send(csk->cdev->ports[csk->port_id], skb);
+ return 0;
+}
+
+static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid,
+ int hcrc, int dcrc, int reply)
+{
+ struct sk_buff *skb;
+ struct cpl_set_tcb_field *req;
+
+ if (!hcrc && !dcrc)
+ return 0;
+
+ skb = alloc_wr(sizeof(*req), 0, GFP_KERNEL);
+ if (!skb)
+ return -ENOMEM;
+
+ csk->hcrc_len = (hcrc ? 4 : 0);
+ csk->dcrc_len = (dcrc ? 4 : 0);
+ /* set up ulp submode */
+ req = (struct cpl_set_tcb_field *)skb->head;
+ INIT_TP_WR(req, tid);
+ OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid));
+ req->reply_ctrl = htons(NO_REPLY(reply) | QUEUENO(csk->rss_qid));
+ req->word_cookie = htons(0);
+ req->mask = cpu_to_be64(0x3 << 4);
+ req->val = cpu_to_be64(((hcrc ? ULP_CRC_HEADER : 0) |
+ (dcrc ? ULP_CRC_DATA : 0)) << 4);
+ set_wr_txq(skb, CPL_PRIORITY_CONTROL, csk->port_id);
+
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+ "csk 0x%p, tid 0x%x, crc %d,%d.\n", csk, csk->tid, hcrc, dcrc);
+
+ cxgb4_ofld_send(csk->cdev->ports[csk->port_id], skb);
+ return 0;
+}
+
+static int cxgb4i_ddp_init(struct cxgbi_device *cdev)
+{
+ struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev);
+ struct cxgbi_ddp_info *ddp = cdev->ddp;
+ unsigned int tagmask, pgsz_factor[4];
+ int err;
+
+ if (ddp) {
+ kref_get(&ddp->refcnt);
+ pr_warn("cdev 0x%p, ddp 0x%p already set up.\n",
+ cdev, cdev->ddp);
+ return -EALREADY;
+ }
+
+ err = cxgbi_ddp_init(cdev, lldi->vr->iscsi.start,
+ lldi->vr->iscsi.start + lldi->vr->iscsi.size - 1,
+ lldi->iscsi_iolen, lldi->iscsi_iolen);
+ if (err < 0)
+ return err;
+
+ ddp = cdev->ddp;
+
+ tagmask = ddp->idx_mask << PPOD_IDX_SHIFT;
+ cxgbi_ddp_page_size_factor(pgsz_factor);
+ cxgb4_iscsi_init(lldi->ports[0], tagmask, pgsz_factor);
+
+ cdev->csk_ddp_free_gl_skb = NULL;
+ cdev->csk_ddp_alloc_gl_skb = NULL;
+ cdev->csk_ddp_setup_digest = ddp_setup_conn_digest;
+ cdev->csk_ddp_setup_pgidx = ddp_setup_conn_pgidx;
+ cdev->csk_ddp_set = ddp_set_map;
+ cdev->csk_ddp_clear = ddp_clear_map;
+
+ pr_info("cxgb4i 0x%p tag: sw %u, rsvd %u,%u, mask 0x%x.\n",
+ cdev, cdev->tag_format.sw_bits, cdev->tag_format.rsvd_bits,
+ cdev->tag_format.rsvd_shift, cdev->tag_format.rsvd_mask);
+ pr_info("cxgb4i 0x%p, nppods %u, bits %u, mask 0x%x,0x%x pkt %u/%u, "
+ " %u/%u.\n",
+ cdev, ddp->nppods, ddp->idx_bits, ddp->idx_mask,
+ ddp->rsvd_tag_mask, ddp->max_txsz, lldi->iscsi_iolen,
+ ddp->max_rxsz, lldi->iscsi_iolen);
+ pr_info("cxgb4i 0x%p max payload size: %u/%u, %u/%u.\n",
+ cdev, cdev->tx_max_size, ddp->max_txsz, cdev->rx_max_size,
+ ddp->max_rxsz);
+ return 0;
+}
+
+static void *t4_uld_add(const struct cxgb4_lld_info *lldi)
+{
+ struct cxgbi_device *cdev;
+ struct port_info *pi;
+ int i, rc;
+
+ cdev = cxgbi_device_register(sizeof(*lldi), lldi->nports);
+ if (!cdev) {
+ pr_info("t4 device 0x%p, register failed.\n", lldi);
+ return NULL;
+ }
+ pr_info("0x%p,0x%x, ports %u,%s, chan %u, q %u,%u, wr %u.\n",
+ cdev, lldi->adapter_type, lldi->nports,
+ lldi->ports[0]->name, lldi->nchan, lldi->ntxq,
+ lldi->nrxq, lldi->wr_cred);
+ for (i = 0; i < lldi->nrxq; i++)
+ log_debug(1 << CXGBI_DBG_DEV,
+ "t4 0x%p, rxq id #%d: %u.\n",
+ cdev, i, lldi->rxq_ids[i]);
+
+ memcpy(cxgbi_cdev_priv(cdev), lldi, sizeof(*lldi));
+ cdev->flags = CXGBI_FLAG_DEV_T4;
+ cdev->pdev = lldi->pdev;
+ cdev->ports = lldi->ports;
+ cdev->nports = lldi->nports;
+ cdev->mtus = lldi->mtus;
+ cdev->nmtus = NMTUS;
+ cdev->snd_win = cxgb4i_snd_win;
+ cdev->rcv_win = cxgb4i_rcv_win;
+ cdev->rx_credit_thres = cxgb4i_rx_credit_thres;
+ cdev->skb_tx_rsvd = CXGB4I_TX_HEADER_LEN;
+ cdev->skb_rx_extra = sizeof(struct cpl_iscsi_hdr);
+ cdev->itp = &cxgb4i_iscsi_transport;
+
+ cdev->pfvf = FW_VIID_PFN_GET(cxgb4_port_viid(lldi->ports[0])) << 8;
+ pr_info("cdev 0x%p,%s, pfvf %u.\n",
+ cdev, lldi->ports[0]->name, cdev->pfvf);
+
+ rc = cxgb4i_ddp_init(cdev);
+ if (rc) {
+ pr_info("t4 0x%p ddp init failed.\n", cdev);
+ goto err_out;
+ }
+ rc = cxgb4i_ofld_init(cdev);
+ if (rc) {
+ pr_info("t4 0x%p ofld init failed.\n", cdev);
+ goto err_out;
+ }
+
+ rc = cxgbi_hbas_add(cdev, CXGB4I_MAX_LUN, CXGBI_MAX_CONN,
+ &cxgb4i_host_template, cxgb4i_stt);
+ if (rc)
+ goto err_out;
+
+ for (i = 0; i < cdev->nports; i++) {
+ pi = netdev_priv(lldi->ports[i]);
+ cdev->hbas[i]->port_id = pi->port_id;
+ }
+ return cdev;
+
+err_out:
+ cxgbi_device_unregister(cdev);
+ return ERR_PTR(-ENOMEM);
+}
+
+#define RX_PULL_LEN 128
+static int t4_uld_rx_handler(void *handle, const __be64 *rsp,
+ const struct pkt_gl *pgl)
+{
+ const struct cpl_act_establish *rpl;
+ struct sk_buff *skb;
+ unsigned int opc;
+ struct cxgbi_device *cdev = handle;
+
+ if (pgl == NULL) {
+ unsigned int len = 64 - sizeof(struct rsp_ctrl) - 8;
+
+ skb = alloc_wr(len, 0, GFP_ATOMIC);
+ if (!skb)
+ goto nomem;
+ skb_copy_to_linear_data(skb, &rsp[1], len);
+ } else {
+ if (unlikely(*(u8 *)rsp != *(u8 *)pgl->va)) {
+ pr_info("? FL 0x%p,RSS%#llx,FL %#llx,len %u.\n",
+ pgl->va, be64_to_cpu(*rsp),
+ be64_to_cpu(*(u64 *)pgl->va),
+ pgl->tot_len);
+ return 0;
+ }
+ skb = cxgb4_pktgl_to_skb(pgl, RX_PULL_LEN, RX_PULL_LEN);
+ if (unlikely(!skb))
+ goto nomem;
+ }
+
+ rpl = (struct cpl_act_establish *)skb->data;
+ opc = rpl->ot.opcode;
+ log_debug(1 << CXGBI_DBG_TOE,
+ "cdev %p, opcode 0x%x(0x%x,0x%x), skb %p.\n",
+ cdev, opc, rpl->ot.opcode_tid, ntohl(rpl->ot.opcode_tid), skb);
+ if (cxgb4i_cplhandlers[opc])
+ cxgb4i_cplhandlers[opc](cdev, skb);
+ else {
+ pr_err("No handler for opcode 0x%x.\n", opc);
+ __kfree_skb(skb);
+ }
+ return 0;
+nomem:
+ log_debug(1 << CXGBI_DBG_TOE, "OOM bailing out.\n");
+ return 1;
+}
+
+static int t4_uld_state_change(void *handle, enum cxgb4_state state)
+{
+ struct cxgbi_device *cdev = handle;
+
+ switch (state) {
+ case CXGB4_STATE_UP:
+ pr_info("cdev 0x%p, UP.\n", cdev);
+ /* re-initialize */
+ break;
+ case CXGB4_STATE_START_RECOVERY:
+ pr_info("cdev 0x%p, RECOVERY.\n", cdev);
+ /* close all connections */
+ break;
+ case CXGB4_STATE_DOWN:
+ pr_info("cdev 0x%p, DOWN.\n", cdev);
+ break;
+ case CXGB4_STATE_DETACH:
+ pr_info("cdev 0x%p, DETACH.\n", cdev);
+ break;
+ default:
+ pr_info("cdev 0x%p, unknown state %d.\n", cdev, state);
+ break;
+ }
+ return 0;
+}
+
+static int __init cxgb4i_init_module(void)
+{
+ int rc;
+
+ printk(KERN_INFO "%s", version);
+
+ rc = cxgbi_iscsi_init(&cxgb4i_iscsi_transport, &cxgb4i_stt);
+ if (rc < 0)
+ return rc;
+ cxgb4_register_uld(CXGB4_ULD_ISCSI, &cxgb4i_uld_info);
+ return 0;
+}
+
+static void __exit cxgb4i_exit_module(void)
+{
+ cxgb4_unregister_uld(CXGB4_ULD_ISCSI);
+ cxgbi_device_unregister_all(CXGBI_FLAG_DEV_T4);
+ cxgbi_iscsi_cleanup(&cxgb4i_iscsi_transport, &cxgb4i_stt);
+}
+
+module_init(cxgb4i_init_module);
+module_exit(cxgb4i_exit_module);
diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.h b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.h
new file mode 100644
index 000000000000..1096026ba241
--- /dev/null
+++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.h
@@ -0,0 +1,43 @@
+/*
+ * cxgb4i.h: Chelsio T4 iSCSI driver.
+ *
+ * Copyright (c) 2010 Chelsio Communications, 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.
+ *
+ * Written by: Karen Xie (kxie@chelsio.com)
+ * Written by: Rakesh Ranjan (rranjan@chelsio.com)
+ */
+
+#ifndef __CXGB4I_H__
+#define __CXGB4I_H__
+
+#define CXGB4I_SCSI_HOST_QDEPTH 1024
+#define CXGB4I_MAX_CONN 16384
+#define CXGB4I_MAX_TARGET CXGB4I_MAX_CONN
+#define CXGB4I_MAX_LUN 0x1000
+
+/* for TX: a skb must have a headroom of at least TX_HEADER_LEN bytes */
+#define CXGB4I_TX_HEADER_LEN \
+ (sizeof(struct fw_ofld_tx_data_wr) + sizeof(struct sge_opaque_hdr))
+
+struct ulptx_idata {
+ __be32 cmd_more;
+ __be32 len;
+};
+
+struct cpl_rx_data_ddp {
+ union opcode_tid ot;
+ __be16 urg;
+ __be16 len;
+ __be32 seq;
+ union {
+ __be32 nxt_seq;
+ __be32 ddp_report;
+ };
+ __be32 ulp_crc;
+ __be32 ddpvld;
+};
+#endif /* __CXGB4I_H__ */
diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c
new file mode 100644
index 000000000000..be5661707dfa
--- /dev/null
+++ b/drivers/scsi/cxgbi/libcxgbi.c
@@ -0,0 +1,2612 @@
+/*
+ * libcxgbi.c: Chelsio common library for T3/T4 iSCSI driver.
+ *
+ * Copyright (c) 2010 Chelsio Communications, 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.
+ *
+ * Written by: Karen Xie (kxie@chelsio.com)
+ * Written by: Rakesh Ranjan (rranjan@chelsio.com)
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
+
+#include <linux/skbuff.h>
+#include <linux/crypto.h>
+#include <linux/scatterlist.h>
+#include <linux/pci.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_host.h>
+#include <linux/if_vlan.h>
+#include <linux/inet.h>
+#include <net/dst.h>
+#include <net/route.h>
+#include <linux/inetdevice.h> /* ip_dev_find */
+#include <net/tcp.h>
+
+static unsigned int dbg_level;
+
+#include "libcxgbi.h"
+
+#define DRV_MODULE_NAME "libcxgbi"
+#define DRV_MODULE_DESC "Chelsio iSCSI driver library"
+#define DRV_MODULE_VERSION "0.9.0"
+#define DRV_MODULE_RELDATE "Jun. 2010"
+
+MODULE_AUTHOR("Chelsio Communications, Inc.");
+MODULE_DESCRIPTION(DRV_MODULE_DESC);
+MODULE_VERSION(DRV_MODULE_VERSION);
+MODULE_LICENSE("GPL");
+
+module_param(dbg_level, uint, 0644);
+MODULE_PARM_DESC(dbg_level, "libiscsi debug level (default=0)");
+
+
+/*
+ * cxgbi device management
+ * maintains a list of the cxgbi devices
+ */
+static LIST_HEAD(cdev_list);
+static DEFINE_MUTEX(cdev_mutex);
+
+int cxgbi_device_portmap_create(struct cxgbi_device *cdev, unsigned int base,
+ unsigned int max_conn)
+{
+ struct cxgbi_ports_map *pmap = &cdev->pmap;
+
+ pmap->port_csk = cxgbi_alloc_big_mem(max_conn *
+ sizeof(struct cxgbi_sock *),
+ GFP_KERNEL);
+ if (!pmap->port_csk) {
+ pr_warn("cdev 0x%p, portmap OOM %u.\n", cdev, max_conn);
+ return -ENOMEM;
+ }
+
+ pmap->max_connect = max_conn;
+ pmap->sport_base = base;
+ spin_lock_init(&pmap->lock);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cxgbi_device_portmap_create);
+
+void cxgbi_device_portmap_cleanup(struct cxgbi_device *cdev)
+{
+ struct cxgbi_ports_map *pmap = &cdev->pmap;
+ struct cxgbi_sock *csk;
+ int i;
+
+ for (i = 0; i < pmap->max_connect; i++) {
+ if (pmap->port_csk[i]) {
+ csk = pmap->port_csk[i];
+ pmap->port_csk[i] = NULL;
+ log_debug(1 << CXGBI_DBG_SOCK,
+ "csk 0x%p, cdev 0x%p, offload down.\n",
+ csk, cdev);
+ spin_lock_bh(&csk->lock);
+ cxgbi_sock_set_flag(csk, CTPF_OFFLOAD_DOWN);
+ cxgbi_sock_closed(csk);
+ spin_unlock_bh(&csk->lock);
+ cxgbi_sock_put(csk);
+ }
+ }
+}
+EXPORT_SYMBOL_GPL(cxgbi_device_portmap_cleanup);
+
+static inline void cxgbi_device_destroy(struct cxgbi_device *cdev)
+{
+ log_debug(1 << CXGBI_DBG_DEV,
+ "cdev 0x%p, p# %u.\n", cdev, cdev->nports);
+ cxgbi_hbas_remove(cdev);
+ cxgbi_device_portmap_cleanup(cdev);
+ if (cdev->dev_ddp_cleanup)
+ cdev->dev_ddp_cleanup(cdev);
+ else
+ cxgbi_ddp_cleanup(cdev);
+ if (cdev->ddp)
+ cxgbi_ddp_cleanup(cdev);
+ if (cdev->pmap.max_connect)
+ cxgbi_free_big_mem(cdev->pmap.port_csk);
+ kfree(cdev);
+}
+
+struct cxgbi_device *cxgbi_device_register(unsigned int extra,
+ unsigned int nports)
+{
+ struct cxgbi_device *cdev;
+
+ cdev = kzalloc(sizeof(*cdev) + extra + nports *
+ (sizeof(struct cxgbi_hba *) +
+ sizeof(struct net_device *)),
+ GFP_KERNEL);
+ if (!cdev) {
+ pr_warn("nport %d, OOM.\n", nports);
+ return NULL;
+ }
+ cdev->ports = (struct net_device **)(cdev + 1);
+ cdev->hbas = (struct cxgbi_hba **)(((char*)cdev->ports) + nports *
+ sizeof(struct net_device *));
+ if (extra)
+ cdev->dd_data = ((char *)cdev->hbas) +
+ nports * sizeof(struct cxgbi_hba *);
+ spin_lock_init(&cdev->pmap.lock);
+
+ mutex_lock(&cdev_mutex);
+ list_add_tail(&cdev->list_head, &cdev_list);
+ mutex_unlock(&cdev_mutex);
+
+ log_debug(1 << CXGBI_DBG_DEV,
+ "cdev 0x%p, p# %u.\n", cdev, nports);
+ return cdev;
+}
+EXPORT_SYMBOL_GPL(cxgbi_device_register);
+
+void cxgbi_device_unregister(struct cxgbi_device *cdev)
+{
+ log_debug(1 << CXGBI_DBG_DEV,
+ "cdev 0x%p, p# %u,%s.\n",
+ cdev, cdev->nports, cdev->nports ? cdev->ports[0]->name : "");
+ mutex_lock(&cdev_mutex);
+ list_del(&cdev->list_head);
+ mutex_unlock(&cdev_mutex);
+ cxgbi_device_destroy(cdev);
+}
+EXPORT_SYMBOL_GPL(cxgbi_device_unregister);
+
+void cxgbi_device_unregister_all(unsigned int flag)
+{
+ struct cxgbi_device *cdev, *tmp;
+
+ mutex_lock(&cdev_mutex);
+ list_for_each_entry_safe(cdev, tmp, &cdev_list, list_head) {
+ if ((cdev->flags & flag) == flag) {
+ log_debug(1 << CXGBI_DBG_DEV,
+ "cdev 0x%p, p# %u,%s.\n",
+ cdev, cdev->nports, cdev->nports ?
+ cdev->ports[0]->name : "");
+ list_del(&cdev->list_head);
+ cxgbi_device_destroy(cdev);
+ }
+ }
+ mutex_unlock(&cdev_mutex);
+}
+EXPORT_SYMBOL_GPL(cxgbi_device_unregister_all);
+
+struct cxgbi_device *cxgbi_device_find_by_lldev(void *lldev)
+{
+ struct cxgbi_device *cdev, *tmp;
+
+ mutex_lock(&cdev_mutex);
+ list_for_each_entry_safe(cdev, tmp, &cdev_list, list_head) {
+ if (cdev->lldev == lldev) {
+ mutex_unlock(&cdev_mutex);
+ return cdev;
+ }
+ }
+ mutex_unlock(&cdev_mutex);
+ log_debug(1 << CXGBI_DBG_DEV,
+ "lldev 0x%p, NO match found.\n", lldev);
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(cxgbi_device_find_by_lldev);
+
+static struct cxgbi_device *cxgbi_device_find_by_netdev(struct net_device *ndev,
+ int *port)
+{
+ struct net_device *vdev = NULL;
+ struct cxgbi_device *cdev, *tmp;
+ int i;
+
+ if (ndev->priv_flags & IFF_802_1Q_VLAN) {
+ vdev = ndev;
+ ndev = vlan_dev_real_dev(ndev);
+ log_debug(1 << CXGBI_DBG_DEV,
+ "vlan dev %s -> %s.\n", vdev->name, ndev->name);
+ }
+
+ mutex_lock(&cdev_mutex);
+ list_for_each_entry_safe(cdev, tmp, &cdev_list, list_head) {
+ for (i = 0; i < cdev->nports; i++) {
+ if (ndev == cdev->ports[i]) {
+ cdev->hbas[i]->vdev = vdev;
+ mutex_unlock(&cdev_mutex);
+ if (port)
+ *port = i;
+ return cdev;
+ }
+ }
+ }
+ mutex_unlock(&cdev_mutex);
+ log_debug(1 << CXGBI_DBG_DEV,
+ "ndev 0x%p, %s, NO match found.\n", ndev, ndev->name);
+ return NULL;
+}
+
+void cxgbi_hbas_remove(struct cxgbi_device *cdev)
+{
+ int i;
+ struct cxgbi_hba *chba;
+
+ log_debug(1 << CXGBI_DBG_DEV,
+ "cdev 0x%p, p#%u.\n", cdev, cdev->nports);
+
+ for (i = 0; i < cdev->nports; i++) {
+ chba = cdev->hbas[i];
+ if (chba) {
+ cdev->hbas[i] = NULL;
+ iscsi_host_remove(chba->shost);
+ pci_dev_put(cdev->pdev);
+ iscsi_host_free(chba->shost);
+ }
+ }
+}
+EXPORT_SYMBOL_GPL(cxgbi_hbas_remove);
+
+int cxgbi_hbas_add(struct cxgbi_device *cdev, unsigned int max_lun,
+ unsigned int max_id, struct scsi_host_template *sht,
+ struct scsi_transport_template *stt)
+{
+ struct cxgbi_hba *chba;
+ struct Scsi_Host *shost;
+ int i, err;
+
+ log_debug(1 << CXGBI_DBG_DEV, "cdev 0x%p, p#%u.\n", cdev, cdev->nports);
+
+ for (i = 0; i < cdev->nports; i++) {
+ shost = iscsi_host_alloc(sht, sizeof(*chba), 1);
+ if (!shost) {
+ pr_info("0x%p, p%d, %s, host alloc failed.\n",
+ cdev, i, cdev->ports[i]->name);
+ err = -ENOMEM;
+ goto err_out;
+ }
+
+ shost->transportt = stt;
+ shost->max_lun = max_lun;
+ shost->max_id = max_id;
+ shost->max_channel = 0;
+ shost->max_cmd_len = 16;
+
+ chba = iscsi_host_priv(shost);
+ chba->cdev = cdev;
+ chba->ndev = cdev->ports[i];
+ chba->shost = shost;
+
+ log_debug(1 << CXGBI_DBG_DEV,
+ "cdev 0x%p, p#%d %s: chba 0x%p.\n",
+ cdev, i, cdev->ports[i]->name, chba);
+
+ pci_dev_get(cdev->pdev);
+ err = iscsi_host_add(shost, &cdev->pdev->dev);
+ if (err) {
+ pr_info("cdev 0x%p, p#%d %s, host add failed.\n",
+ cdev, i, cdev->ports[i]->name);
+ pci_dev_put(cdev->pdev);
+ scsi_host_put(shost);
+ goto err_out;
+ }
+
+ cdev->hbas[i] = chba;
+ }
+
+ return 0;
+
+err_out:
+ cxgbi_hbas_remove(cdev);
+ return err;
+}
+EXPORT_SYMBOL_GPL(cxgbi_hbas_add);
+
+/*
+ * iSCSI offload
+ *
+ * - source port management
+ * To find a free source port in the port allocation map we use a very simple
+ * rotor scheme to look for the next free port.
+ *
+ * If a source port has been specified make sure that it doesn't collide with
+ * our normal source port allocation map. If it's outside the range of our
+ * allocation/deallocation scheme just let them use it.
+ *
+ * If the source port is outside our allocation range, the caller is
+ * responsible for keeping track of their port usage.
+ */
+static int sock_get_port(struct cxgbi_sock *csk)
+{
+ struct cxgbi_device *cdev = csk->cdev;
+ struct cxgbi_ports_map *pmap = &cdev->pmap;
+ unsigned int start;
+ int idx;
+
+ if (!pmap->max_connect) {
+ pr_err("cdev 0x%p, p#%u %s, NO port map.\n",
+ cdev, csk->port_id, cdev->ports[csk->port_id]->name);
+ return -EADDRNOTAVAIL;
+ }
+
+ if (csk->saddr.sin_port) {
+ pr_err("source port NON-ZERO %u.\n",
+ ntohs(csk->saddr.sin_port));
+ return -EADDRINUSE;
+ }
+
+ spin_lock_bh(&pmap->lock);
+ if (pmap->used >= pmap->max_connect) {
+ spin_unlock_bh(&pmap->lock);
+ pr_info("cdev 0x%p, p#%u %s, ALL ports used.\n",
+ cdev, csk->port_id, cdev->ports[csk->port_id]->name);
+ return -EADDRNOTAVAIL;
+ }
+
+ start = idx = pmap->next;
+ do {
+ if (++idx >= pmap->max_connect)
+ idx = 0;
+ if (!pmap->port_csk[idx]) {
+ pmap->used++;
+ csk->saddr.sin_port =
+ htons(pmap->sport_base + idx);
+ pmap->next = idx;
+ pmap->port_csk[idx] = csk;
+ spin_unlock_bh(&pmap->lock);
+ cxgbi_sock_get(csk);
+ log_debug(1 << CXGBI_DBG_SOCK,
+ "cdev 0x%p, p#%u %s, p %u, %u.\n",
+ cdev, csk->port_id,
+ cdev->ports[csk->port_id]->name,
+ pmap->sport_base + idx, pmap->next);
+ return 0;
+ }
+ } while (idx != start);
+ spin_unlock_bh(&pmap->lock);
+
+ /* should not happen */
+ pr_warn("cdev 0x%p, p#%u %s, next %u?\n",
+ cdev, csk->port_id, cdev->ports[csk->port_id]->name,
+ pmap->next);
+ return -EADDRNOTAVAIL;
+}
+
+static void sock_put_port(struct cxgbi_sock *csk)
+{
+ struct cxgbi_device *cdev = csk->cdev;
+ struct cxgbi_ports_map *pmap = &cdev->pmap;
+
+ if (csk->saddr.sin_port) {
+ int idx = ntohs(csk->saddr.sin_port) - pmap->sport_base;
+
+ csk->saddr.sin_port = 0;
+ if (idx < 0 || idx >= pmap->max_connect) {
+ pr_err("cdev 0x%p, p#%u %s, port %u OOR.\n",
+ cdev, csk->port_id,
+ cdev->ports[csk->port_id]->name,
+ ntohs(csk->saddr.sin_port));
+ return;
+ }
+
+ spin_lock_bh(&pmap->lock);
+ pmap->port_csk[idx] = NULL;
+ pmap->used--;
+ spin_unlock_bh(&pmap->lock);
+
+ log_debug(1 << CXGBI_DBG_SOCK,
+ "cdev 0x%p, p#%u %s, release %u.\n",
+ cdev, csk->port_id, cdev->ports[csk->port_id]->name,
+ pmap->sport_base + idx);
+
+ cxgbi_sock_put(csk);
+ }
+}
+
+/*
+ * iscsi tcp connection
+ */
+void cxgbi_sock_free_cpl_skbs(struct cxgbi_sock *csk)
+{
+ if (csk->cpl_close) {
+ kfree_skb(csk->cpl_close);
+ csk->cpl_close = NULL;
+ }
+ if (csk->cpl_abort_req) {
+ kfree_skb(csk->cpl_abort_req);
+ csk->cpl_abort_req = NULL;
+ }
+ if (csk->cpl_abort_rpl) {
+ kfree_skb(csk->cpl_abort_rpl);
+ csk->cpl_abort_rpl = NULL;
+ }
+}
+EXPORT_SYMBOL_GPL(cxgbi_sock_free_cpl_skbs);
+
+static struct cxgbi_sock *cxgbi_sock_create(struct cxgbi_device *cdev)
+{
+ struct cxgbi_sock *csk = kzalloc(sizeof(*csk), GFP_NOIO);
+
+ if (!csk) {
+ pr_info("alloc csk %zu failed.\n", sizeof(*csk));
+ return NULL;
+ }
+
+ if (cdev->csk_alloc_cpls(csk) < 0) {
+ pr_info("csk 0x%p, alloc cpls failed.\n", csk);
+ kfree(csk);
+ return NULL;
+ }
+
+ spin_lock_init(&csk->lock);
+ kref_init(&csk->refcnt);
+ skb_queue_head_init(&csk->receive_queue);
+ skb_queue_head_init(&csk->write_queue);
+ setup_timer(&csk->retry_timer, NULL, (unsigned long)csk);
+ rwlock_init(&csk->callback_lock);
+ csk->cdev = cdev;
+ csk->flags = 0;
+ cxgbi_sock_set_state(csk, CTP_CLOSED);
+
+ log_debug(1 << CXGBI_DBG_SOCK, "cdev 0x%p, new csk 0x%p.\n", cdev, csk);
+
+ return csk;
+}
+
+static struct rtable *find_route_ipv4(__be32 saddr, __be32 daddr,
+ __be16 sport, __be16 dport, u8 tos)
+{
+ struct rtable *rt;
+ struct flowi fl = {
+ .oif = 0,
+ .nl_u = {
+ .ip4_u = {
+ .daddr = daddr,
+ .saddr = saddr,
+ .tos = tos }
+ },
+ .proto = IPPROTO_TCP,
+ .uli_u = {
+ .ports = {
+ .sport = sport,
+ .dport = dport }
+ }
+ };
+
+ if (ip_route_output_flow(&init_net, &rt, &fl, NULL, 0))
+ return NULL;
+
+ return rt;
+}
+
+static struct cxgbi_sock *cxgbi_check_route(struct sockaddr *dst_addr)
+{
+ struct sockaddr_in *daddr = (struct sockaddr_in *)dst_addr;
+ struct dst_entry *dst;
+ struct net_device *ndev;
+ struct cxgbi_device *cdev;
+ struct rtable *rt = NULL;
+ struct cxgbi_sock *csk = NULL;
+ unsigned int mtu = 0;
+ int port = 0xFFFF;
+ int err = 0;
+
+ if (daddr->sin_family != AF_INET) {
+ pr_info("address family 0x%x NOT supported.\n",
+ daddr->sin_family);
+ err = -EAFNOSUPPORT;
+ goto err_out;
+ }
+
+ rt = find_route_ipv4(0, daddr->sin_addr.s_addr, 0, daddr->sin_port, 0);
+ if (!rt) {
+ pr_info("no route to ipv4 0x%x, port %u.\n",
+ daddr->sin_addr.s_addr, daddr->sin_port);
+ err = -ENETUNREACH;
+ goto err_out;
+ }
+ dst = &rt->dst;
+ ndev = dst->neighbour->dev;
+
+ if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) {
+ pr_info("multi-cast route %pI4, port %u, dev %s.\n",
+ &daddr->sin_addr.s_addr, ntohs(daddr->sin_port),
+ ndev->name);
+ err = -ENETUNREACH;
+ goto rel_rt;
+ }
+
+ if (ndev->flags & IFF_LOOPBACK) {
+ ndev = ip_dev_find(&init_net, daddr->sin_addr.s_addr);
+ mtu = ndev->mtu;
+ pr_info("rt dev %s, loopback -> %s, mtu %u.\n",
+ dst->neighbour->dev->name, ndev->name, mtu);
+ }
+
+ cdev = cxgbi_device_find_by_netdev(ndev, &port);
+ if (!cdev) {
+ pr_info("dst %pI4, %s, NOT cxgbi device.\n",
+ &daddr->sin_addr.s_addr, ndev->name);
+ err = -ENETUNREACH;
+ goto rel_rt;
+ }
+ log_debug(1 << CXGBI_DBG_SOCK,
+ "route to %pI4 :%u, ndev p#%d,%s, cdev 0x%p.\n",
+ &daddr->sin_addr.s_addr, ntohs(daddr->sin_port),
+ port, ndev->name, cdev);
+
+ csk = cxgbi_sock_create(cdev);
+ if (!csk) {
+ err = -ENOMEM;
+ goto rel_rt;
+ }
+ csk->cdev = cdev;
+ csk->port_id = port;
+ csk->mtu = mtu;
+ csk->dst = dst;
+ csk->daddr.sin_addr.s_addr = daddr->sin_addr.s_addr;
+ csk->daddr.sin_port = daddr->sin_port;
+ csk->saddr.sin_addr.s_addr = rt->rt_src;
+
+ return csk;
+
+rel_rt:
+ ip_rt_put(rt);
+ if (csk)
+ cxgbi_sock_closed(csk);
+err_out:
+ return ERR_PTR(err);
+}
+
+void cxgbi_sock_established(struct cxgbi_sock *csk, unsigned int snd_isn,
+ unsigned int opt)
+{
+ csk->write_seq = csk->snd_nxt = csk->snd_una = snd_isn;
+ dst_confirm(csk->dst);
+ smp_mb();
+ cxgbi_sock_set_state(csk, CTP_ESTABLISHED);
+}
+EXPORT_SYMBOL_GPL(cxgbi_sock_established);
+
+static void cxgbi_inform_iscsi_conn_closing(struct cxgbi_sock *csk)
+{
+ log_debug(1 << CXGBI_DBG_SOCK,
+ "csk 0x%p, state %u, flags 0x%lx, conn 0x%p.\n",
+ csk, csk->state, csk->flags, csk->user_data);
+
+ if (csk->state != CTP_ESTABLISHED) {
+ read_lock_bh(&csk->callback_lock);
+ if (csk->user_data)
+ iscsi_conn_failure(csk->user_data,
+ ISCSI_ERR_CONN_FAILED);
+ read_unlock_bh(&csk->callback_lock);
+ }
+}
+
+void cxgbi_sock_closed(struct cxgbi_sock *csk)
+{
+ log_debug(1 << CXGBI_DBG_SOCK, "csk 0x%p,%u,0x%lx,%u.\n",
+ csk, (csk)->state, (csk)->flags, (csk)->tid);
+ cxgbi_sock_set_flag(csk, CTPF_ACTIVE_CLOSE_NEEDED);
+ if (csk->state == CTP_ACTIVE_OPEN || csk->state == CTP_CLOSED)
+ return;
+ if (csk->saddr.sin_port)
+ sock_put_port(csk);
+ if (csk->dst)
+ dst_release(csk->dst);
+ csk->cdev->csk_release_offload_resources(csk);
+ cxgbi_sock_set_state(csk, CTP_CLOSED);
+ cxgbi_inform_iscsi_conn_closing(csk);
+ cxgbi_sock_put(csk);
+}
+EXPORT_SYMBOL_GPL(cxgbi_sock_closed);
+
+static void need_active_close(struct cxgbi_sock *csk)
+{
+ int data_lost;
+ int close_req = 0;
+
+ log_debug(1 << CXGBI_DBG_SOCK, "csk 0x%p,%u,0x%lx,%u.\n",
+ csk, (csk)->state, (csk)->flags, (csk)->tid);
+ spin_lock_bh(&csk->lock);
+ dst_confirm(csk->dst);
+ data_lost = skb_queue_len(&csk->receive_queue);
+ __skb_queue_purge(&csk->receive_queue);
+
+ if (csk->state == CTP_ACTIVE_OPEN)
+ cxgbi_sock_set_flag(csk, CTPF_ACTIVE_CLOSE_NEEDED);
+ else if (csk->state == CTP_ESTABLISHED) {
+ close_req = 1;
+ cxgbi_sock_set_state(csk, CTP_ACTIVE_CLOSE);
+ } else if (csk->state == CTP_PASSIVE_CLOSE) {
+ close_req = 1;
+ cxgbi_sock_set_state(csk, CTP_CLOSE_WAIT_2);
+ }
+
+ if (close_req) {
+ if (data_lost)
+ csk->cdev->csk_send_abort_req(csk);
+ else
+ csk->cdev->csk_send_close_req(csk);
+ }
+
+ spin_unlock_bh(&csk->lock);
+}
+
+void cxgbi_sock_fail_act_open(struct cxgbi_sock *csk, int errno)
+{
+ pr_info("csk 0x%p,%u,%lx, %pI4:%u-%pI4:%u, err %d.\n",
+ csk, csk->state, csk->flags,
+ &csk->saddr.sin_addr.s_addr, csk->saddr.sin_port,
+ &csk->daddr.sin_addr.s_addr, csk->daddr.sin_port,
+ errno);
+
+ cxgbi_sock_set_state(csk, CTP_CONNECTING);
+ csk->err = errno;
+ cxgbi_sock_closed(csk);
+}
+EXPORT_SYMBOL_GPL(cxgbi_sock_fail_act_open);
+
+void cxgbi_sock_act_open_req_arp_failure(void *handle, struct sk_buff *skb)
+{
+ struct cxgbi_sock *csk = (struct cxgbi_sock *)skb->sk;
+
+ log_debug(1 << CXGBI_DBG_SOCK, "csk 0x%p,%u,0x%lx,%u.\n",
+ csk, (csk)->state, (csk)->flags, (csk)->tid);
+ cxgbi_sock_get(csk);
+ spin_lock_bh(&csk->lock);
+ if (csk->state == CTP_ACTIVE_OPEN)
+ cxgbi_sock_fail_act_open(csk, -EHOSTUNREACH);
+ spin_unlock_bh(&csk->lock);
+ cxgbi_sock_put(csk);
+ __kfree_skb(skb);
+}
+EXPORT_SYMBOL_GPL(cxgbi_sock_act_open_req_arp_failure);
+
+void cxgbi_sock_rcv_abort_rpl(struct cxgbi_sock *csk)
+{
+ cxgbi_sock_get(csk);
+ spin_lock_bh(&csk->lock);
+ if (cxgbi_sock_flag(csk, CTPF_ABORT_RPL_PENDING)) {
+ if (!cxgbi_sock_flag(csk, CTPF_ABORT_RPL_RCVD))
+ cxgbi_sock_set_flag(csk, CTPF_ABORT_RPL_RCVD);
+ else {
+ cxgbi_sock_clear_flag(csk, CTPF_ABORT_RPL_RCVD);
+ cxgbi_sock_clear_flag(csk, CTPF_ABORT_RPL_PENDING);
+ if (cxgbi_sock_flag(csk, CTPF_ABORT_REQ_RCVD))
+ pr_err("csk 0x%p,%u,0x%lx,%u,ABT_RPL_RSS.\n",
+ csk, csk->state, csk->flags, csk->tid);
+ cxgbi_sock_closed(csk);
+ }
+ }
+ spin_unlock_bh(&csk->lock);
+ cxgbi_sock_put(csk);
+}
+EXPORT_SYMBOL_GPL(cxgbi_sock_rcv_abort_rpl);
+
+void cxgbi_sock_rcv_peer_close(struct cxgbi_sock *csk)
+{
+ log_debug(1 << CXGBI_DBG_SOCK, "csk 0x%p,%u,0x%lx,%u.\n",
+ csk, (csk)->state, (csk)->flags, (csk)->tid);
+ cxgbi_sock_get(csk);
+ spin_lock_bh(&csk->lock);
+
+ if (cxgbi_sock_flag(csk, CTPF_ABORT_RPL_PENDING))
+ goto done;
+
+ switch (csk->state) {
+ case CTP_ESTABLISHED:
+ cxgbi_sock_set_state(csk, CTP_PASSIVE_CLOSE);
+ break;
+ case CTP_ACTIVE_CLOSE:
+ cxgbi_sock_set_state(csk, CTP_CLOSE_WAIT_2);
+ break;
+ case CTP_CLOSE_WAIT_1:
+ cxgbi_sock_closed(csk);
+ break;
+ case CTP_ABORTING:
+ break;
+ default:
+ pr_err("csk 0x%p,%u,0x%lx,%u, bad state.\n",
+ csk, csk->state, csk->flags, csk->tid);
+ }
+ cxgbi_inform_iscsi_conn_closing(csk);
+done:
+ spin_unlock_bh(&csk->lock);
+ cxgbi_sock_put(csk);
+}
+EXPORT_SYMBOL_GPL(cxgbi_sock_rcv_peer_close);
+
+void cxgbi_sock_rcv_close_conn_rpl(struct cxgbi_sock *csk, u32 snd_nxt)
+{
+ log_debug(1 << CXGBI_DBG_SOCK, "csk 0x%p,%u,0x%lx,%u.\n",
+ csk, (csk)->state, (csk)->flags, (csk)->tid);
+ cxgbi_sock_get(csk);
+ spin_lock_bh(&csk->lock);
+
+ csk->snd_una = snd_nxt - 1;
+ if (cxgbi_sock_flag(csk, CTPF_ABORT_RPL_PENDING))
+ goto done;
+
+ switch (csk->state) {
+ case CTP_ACTIVE_CLOSE:
+ cxgbi_sock_set_state(csk, CTP_CLOSE_WAIT_1);
+ break;
+ case CTP_CLOSE_WAIT_1:
+ case CTP_CLOSE_WAIT_2:
+ cxgbi_sock_closed(csk);
+ break;
+ case CTP_ABORTING:
+ break;
+ default:
+ pr_err("csk 0x%p,%u,0x%lx,%u, bad state.\n",
+ csk, csk->state, csk->flags, csk->tid);
+ }
+done:
+ spin_unlock_bh(&csk->lock);
+ cxgbi_sock_put(csk);
+}
+EXPORT_SYMBOL_GPL(cxgbi_sock_rcv_close_conn_rpl);
+
+void cxgbi_sock_rcv_wr_ack(struct cxgbi_sock *csk, unsigned int credits,
+ unsigned int snd_una, int seq_chk)
+{
+ log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+ "csk 0x%p,%u,0x%lx,%u, cr %u,%u+%u, snd_una %u,%d.\n",
+ csk, csk->state, csk->flags, csk->tid, credits,
+ csk->wr_cred, csk->wr_una_cred, snd_una, seq_chk);
+
+ spin_lock_bh(&csk->lock);
+
+ csk->wr_cred += credits;
+ if (csk->wr_una_cred > csk->wr_max_cred - csk->wr_cred)
+ csk->wr_una_cred = csk->wr_max_cred - csk->wr_cred;
+
+ while (credits) {
+ struct sk_buff *p = cxgbi_sock_peek_wr(csk);
+
+ if (unlikely(!p)) {
+ pr_err("csk 0x%p,%u,0x%lx,%u, cr %u,%u+%u, empty.\n",
+ csk, csk->state, csk->flags, csk->tid, credits,
+ csk->wr_cred, csk->wr_una_cred);
+ break;
+ }
+
+ if (unlikely(credits < p->csum)) {
+ pr_warn("csk 0x%p,%u,0x%lx,%u, cr %u,%u+%u, < %u.\n",
+ csk, csk->state, csk->flags, csk->tid,
+ credits, csk->wr_cred, csk->wr_una_cred,
+ p->csum);
+ p->csum -= credits;
+ break;
+ } else {
+ cxgbi_sock_dequeue_wr(csk);
+ credits -= p->csum;
+ kfree_skb(p);
+ }
+ }
+
+ cxgbi_sock_check_wr_invariants(csk);
+
+ if (seq_chk) {
+ if (unlikely(before(snd_una, csk->snd_una))) {
+ pr_warn("csk 0x%p,%u,0x%lx,%u, snd_una %u/%u.",
+ csk, csk->state, csk->flags, csk->tid, snd_una,
+ csk->snd_una);
+ goto done;
+ }
+
+ if (csk->snd_una != snd_una) {
+ csk->snd_una = snd_una;
+ dst_confirm(csk->dst);
+ }
+ }
+
+ if (skb_queue_len(&csk->write_queue)) {
+ if (csk->cdev->csk_push_tx_frames(csk, 0))
+ cxgbi_conn_tx_open(csk);
+ } else
+ cxgbi_conn_tx_open(csk);
+done:
+ spin_unlock_bh(&csk->lock);
+}
+EXPORT_SYMBOL_GPL(cxgbi_sock_rcv_wr_ack);
+
+static unsigned int cxgbi_sock_find_best_mtu(struct cxgbi_sock *csk,
+ unsigned short mtu)
+{
+ int i = 0;
+
+ while (i < csk->cdev->nmtus - 1 && csk->cdev->mtus[i + 1] <= mtu)
+ ++i;
+
+ return i;
+}
+
+unsigned int cxgbi_sock_select_mss(struct cxgbi_sock *csk, unsigned int pmtu)
+{
+ unsigned int idx;
+ struct dst_entry *dst = csk->dst;
+
+ csk->advmss = dst_metric(dst, RTAX_ADVMSS);
+
+ if (csk->advmss > pmtu - 40)
+ csk->advmss = pmtu - 40;
+ if (csk->advmss < csk->cdev->mtus[0] - 40)
+ csk->advmss = csk->cdev->mtus[0] - 40;
+ idx = cxgbi_sock_find_best_mtu(csk, csk->advmss + 40);
+
+ return idx;
+}
+EXPORT_SYMBOL_GPL(cxgbi_sock_select_mss);
+
+void cxgbi_sock_skb_entail(struct cxgbi_sock *csk, struct sk_buff *skb)
+{
+ cxgbi_skcb_tcp_seq(skb) = csk->write_seq;
+ __skb_queue_tail(&csk->write_queue, skb);
+}
+EXPORT_SYMBOL_GPL(cxgbi_sock_skb_entail);
+
+void cxgbi_sock_purge_wr_queue(struct cxgbi_sock *csk)
+{
+ struct sk_buff *skb;
+
+ while ((skb = cxgbi_sock_dequeue_wr(csk)) != NULL)
+ kfree_skb(skb);
+}
+EXPORT_SYMBOL_GPL(cxgbi_sock_purge_wr_queue);
+
+void cxgbi_sock_check_wr_invariants(const struct cxgbi_sock *csk)
+{
+ int pending = cxgbi_sock_count_pending_wrs(csk);
+
+ if (unlikely(csk->wr_cred + pending != csk->wr_max_cred))
+ pr_err("csk 0x%p, tid %u, credit %u + %u != %u.\n",
+ csk, csk->tid, csk->wr_cred, pending, csk->wr_max_cred);
+}
+EXPORT_SYMBOL_GPL(cxgbi_sock_check_wr_invariants);
+
+static int cxgbi_sock_send_pdus(struct cxgbi_sock *csk, struct sk_buff *skb)
+{
+ struct cxgbi_device *cdev = csk->cdev;
+ struct sk_buff *next;
+ int err, copied = 0;
+
+ spin_lock_bh(&csk->lock);
+
+ if (csk->state != CTP_ESTABLISHED) {
+ log_debug(1 << CXGBI_DBG_PDU_TX,
+ "csk 0x%p,%u,0x%lx,%u, EAGAIN.\n",
+ csk, csk->state, csk->flags, csk->tid);
+ err = -EAGAIN;
+ goto out_err;
+ }
+
+ if (csk->err) {
+ log_debug(1 << CXGBI_DBG_PDU_TX,
+ "csk 0x%p,%u,0x%lx,%u, EPIPE %d.\n",
+ csk, csk->state, csk->flags, csk->tid, csk->err);
+ err = -EPIPE;
+ goto out_err;
+ }
+
+ if (csk->write_seq - csk->snd_una >= cdev->snd_win) {
+ log_debug(1 << CXGBI_DBG_PDU_TX,
+ "csk 0x%p,%u,0x%lx,%u, FULL %u-%u >= %u.\n",
+ csk, csk->state, csk->flags, csk->tid, csk->write_seq,
+ csk->snd_una, cdev->snd_win);
+ err = -ENOBUFS;
+ goto out_err;
+ }
+
+ while (skb) {
+ int frags = skb_shinfo(skb)->nr_frags +
+ (skb->len != skb->data_len);
+
+ if (unlikely(skb_headroom(skb) < cdev->skb_tx_rsvd)) {
+ pr_err("csk 0x%p, skb head %u < %u.\n",
+ csk, skb_headroom(skb), cdev->skb_tx_rsvd);
+ err = -EINVAL;
+ goto out_err;
+ }
+
+ if (frags >= SKB_WR_LIST_SIZE) {
+ pr_err("csk 0x%p, frags %d, %u,%u >%u.\n",
+ csk, skb_shinfo(skb)->nr_frags, skb->len,
+ skb->data_len, (uint)(SKB_WR_LIST_SIZE));
+ err = -EINVAL;
+ goto out_err;
+ }
+
+ next = skb->next;
+ skb->next = NULL;
+ cxgbi_skcb_set_flag(skb, SKCBF_TX_NEED_HDR);
+ cxgbi_sock_skb_entail(csk, skb);
+ copied += skb->len;
+ csk->write_seq += skb->len +
+ cxgbi_ulp_extra_len(cxgbi_skcb_ulp_mode(skb));
+ skb = next;
+ }
+done:
+ if (likely(skb_queue_len(&csk->write_queue)))
+ cdev->csk_push_tx_frames(csk, 1);
+ spin_unlock_bh(&csk->lock);
+ return copied;
+
+out_err:
+ if (copied == 0 && err == -EPIPE)
+ copied = csk->err ? csk->err : -EPIPE;
+ else
+ copied = err;
+ goto done;
+}
+
+/*
+ * Direct Data Placement -
+ * Directly place the iSCSI Data-In or Data-Out PDU's payload into pre-posted
+ * final destination host-memory buffers based on the Initiator Task Tag (ITT)
+ * in Data-In or Target Task Tag (TTT) in Data-Out PDUs.
+ * The host memory address is programmed into h/w in the format of pagepod
+ * entries.
+ * The location of the pagepod entry is encoded into ddp tag which is used as
+ * the base for ITT/TTT.
+ */
+
+static unsigned char ddp_page_order[DDP_PGIDX_MAX] = {0, 1, 2, 4};
+static unsigned char ddp_page_shift[DDP_PGIDX_MAX] = {12, 13, 14, 16};
+static unsigned char page_idx = DDP_PGIDX_MAX;
+
+static unsigned char sw_tag_idx_bits;
+static unsigned char sw_tag_age_bits;
+
+/*
+ * Direct-Data Placement page size adjustment
+ */
+static int ddp_adjust_page_table(void)
+{
+ int i;
+ unsigned int base_order, order;
+
+ if (PAGE_SIZE < (1UL << ddp_page_shift[0])) {
+ pr_info("PAGE_SIZE 0x%lx too small, min 0x%lx\n",
+ PAGE_SIZE, 1UL << ddp_page_shift[0]);
+ return -EINVAL;
+ }
+
+ base_order = get_order(1UL << ddp_page_shift[0]);
+ order = get_order(1UL << PAGE_SHIFT);
+
+ for (i = 0; i < DDP_PGIDX_MAX; i++) {
+ /* first is the kernel page size, then just doubling */
+ ddp_page_order[i] = order - base_order + i;
+ ddp_page_shift[i] = PAGE_SHIFT + i;
+ }
+ return 0;
+}
+
+static int ddp_find_page_index(unsigned long pgsz)
+{
+ int i;
+
+ for (i = 0; i < DDP_PGIDX_MAX; i++) {
+ if (pgsz == (1UL << ddp_page_shift[i]))
+ return i;
+ }
+ pr_info("ddp page size %lu not supported.\n", pgsz);
+ return DDP_PGIDX_MAX;
+}
+
+static void ddp_setup_host_page_size(void)
+{
+ if (page_idx == DDP_PGIDX_MAX) {
+ page_idx = ddp_find_page_index(PAGE_SIZE);
+
+ if (page_idx == DDP_PGIDX_MAX) {
+ pr_info("system PAGE %lu, update hw.\n", PAGE_SIZE);
+ if (ddp_adjust_page_table() < 0) {
+ pr_info("PAGE %lu, disable ddp.\n", PAGE_SIZE);
+ return;
+ }
+ page_idx = ddp_find_page_index(PAGE_SIZE);
+ }
+ pr_info("system PAGE %lu, ddp idx %u.\n", PAGE_SIZE, page_idx);
+ }
+}
+
+void cxgbi_ddp_page_size_factor(int *pgsz_factor)
+{
+ int i;
+
+ for (i = 0; i < DDP_PGIDX_MAX; i++)
+ pgsz_factor[i] = ddp_page_order[i];
+}
+EXPORT_SYMBOL_GPL(cxgbi_ddp_page_size_factor);
+
+/*
+ * DDP setup & teardown
+ */
+
+void cxgbi_ddp_ppod_set(struct cxgbi_pagepod *ppod,
+ struct cxgbi_pagepod_hdr *hdr,
+ struct cxgbi_gather_list *gl, unsigned int gidx)
+{
+ int i;
+
+ memcpy(ppod, hdr, sizeof(*hdr));
+ for (i = 0; i < (PPOD_PAGES_MAX + 1); i++, gidx++) {
+ ppod->addr[i] = gidx < gl->nelem ?
+ cpu_to_be64(gl->phys_addr[gidx]) : 0ULL;
+ }
+}
+EXPORT_SYMBOL_GPL(cxgbi_ddp_ppod_set);
+
+void cxgbi_ddp_ppod_clear(struct cxgbi_pagepod *ppod)
+{
+ memset(ppod, 0, sizeof(*ppod));
+}
+EXPORT_SYMBOL_GPL(cxgbi_ddp_ppod_clear);
+
+static inline int ddp_find_unused_entries(struct cxgbi_ddp_info *ddp,
+ unsigned int start, unsigned int max,
+ unsigned int count,
+ struct cxgbi_gather_list *gl)
+{
+ unsigned int i, j, k;
+
+ /* not enough entries */
+ if ((max - start) < count) {
+ log_debug(1 << CXGBI_DBG_DDP,
+ "NOT enough entries %u+%u < %u.\n", start, count, max);
+ return -EBUSY;
+ }
+
+ max -= count;
+ spin_lock(&ddp->map_lock);
+ for (i = start; i < max;) {
+ for (j = 0, k = i; j < count; j++, k++) {
+ if (ddp->gl_map[k])
+ break;
+ }
+ if (j == count) {
+ for (j = 0, k = i; j < count; j++, k++)
+ ddp->gl_map[k] = gl;
+ spin_unlock(&ddp->map_lock);
+ return i;
+ }
+ i += j + 1;
+ }
+ spin_unlock(&ddp->map_lock);
+ log_debug(1 << CXGBI_DBG_DDP,
+ "NO suitable entries %u available.\n", count);
+ return -EBUSY;
+}
+
+static inline void ddp_unmark_entries(struct cxgbi_ddp_info *ddp,
+ int start, int count)
+{
+ spin_lock(&ddp->map_lock);
+ memset(&ddp->gl_map[start], 0,
+ count * sizeof(struct cxgbi_gather_list *));
+ spin_unlock(&ddp->map_lock);
+}
+
+static inline void ddp_gl_unmap(struct pci_dev *pdev,
+ struct cxgbi_gather_list *gl)
+{
+ int i;
+
+ for (i = 0; i < gl->nelem; i++)
+ dma_unmap_page(&pdev->dev, gl->phys_addr[i], PAGE_SIZE,
+ PCI_DMA_FROMDEVICE);
+}
+
+static inline int ddp_gl_map(struct pci_dev *pdev,
+ struct cxgbi_gather_list *gl)
+{
+ int i;
+
+ for (i = 0; i < gl->nelem; i++) {
+ gl->phys_addr[i] = dma_map_page(&pdev->dev, gl->pages[i], 0,
+ PAGE_SIZE,
+ PCI_DMA_FROMDEVICE);
+ if (unlikely(dma_mapping_error(&pdev->dev, gl->phys_addr[i]))) {
+ log_debug(1 << CXGBI_DBG_DDP,
+ "page %d 0x%p, 0x%p dma mapping err.\n",
+ i, gl->pages[i], pdev);
+ goto unmap;
+ }
+ }
+ return i;
+unmap:
+ if (i) {
+ unsigned int nelem = gl->nelem;
+
+ gl->nelem = i;
+ ddp_gl_unmap(pdev, gl);
+ gl->nelem = nelem;
+ }
+ return -EINVAL;
+}
+
+static void ddp_release_gl(struct cxgbi_gather_list *gl,
+ struct pci_dev *pdev)
+{
+ ddp_gl_unmap(pdev, gl);
+ kfree(gl);
+}
+
+static struct cxgbi_gather_list *ddp_make_gl(unsigned int xferlen,
+ struct scatterlist *sgl,
+ unsigned int sgcnt,
+ struct pci_dev *pdev,
+ gfp_t gfp)
+{
+ struct cxgbi_gather_list *gl;
+ struct scatterlist *sg = sgl;
+ struct page *sgpage = sg_page(sg);
+ unsigned int sglen = sg->length;
+ unsigned int sgoffset = sg->offset;
+ unsigned int npages = (xferlen + sgoffset + PAGE_SIZE - 1) >>
+ PAGE_SHIFT;
+ int i = 1, j = 0;
+
+ if (xferlen < DDP_THRESHOLD) {
+ log_debug(1 << CXGBI_DBG_DDP,
+ "xfer %u < threshold %u, no ddp.\n",
+ xferlen, DDP_THRESHOLD);
+ return NULL;
+ }
+
+ gl = kzalloc(sizeof(struct cxgbi_gather_list) +
+ npages * (sizeof(dma_addr_t) +
+ sizeof(struct page *)), gfp);
+ if (!gl) {
+ log_debug(1 << CXGBI_DBG_DDP,
+ "xfer %u, %u pages, OOM.\n", xferlen, npages);
+ return NULL;
+ }
+
+ log_debug(1 << CXGBI_DBG_DDP,
+ "xfer %u, sgl %u, gl max %u.\n", xferlen, sgcnt, npages);
+
+ gl->pages = (struct page **)&gl->phys_addr[npages];
+ gl->nelem = npages;
+ gl->length = xferlen;
+ gl->offset = sgoffset;
+ gl->pages[0] = sgpage;
+
+ for (i = 1, sg = sg_next(sgl), j = 0; i < sgcnt;
+ i++, sg = sg_next(sg)) {
+ struct page *page = sg_page(sg);
+
+ if (sgpage == page && sg->offset == sgoffset + sglen)
+ sglen += sg->length;
+ else {
+ /* make sure the sgl is fit for ddp:
+ * each has the same page size, and
+ * all of the middle pages are used completely
+ */
+ if ((j && sgoffset) || ((i != sgcnt - 1) &&
+ ((sglen + sgoffset) & ~PAGE_MASK))) {
+ log_debug(1 << CXGBI_DBG_DDP,
+ "page %d/%u, %u + %u.\n",
+ i, sgcnt, sgoffset, sglen);
+ goto error_out;
+ }
+
+ j++;
+ if (j == gl->nelem || sg->offset) {
+ log_debug(1 << CXGBI_DBG_DDP,
+ "page %d/%u, offset %u.\n",
+ j, gl->nelem, sg->offset);
+ goto error_out;
+ }
+ gl->pages[j] = page;
+ sglen = sg->length;
+ sgoffset = sg->offset;
+ sgpage = page;
+ }
+ }
+ gl->nelem = ++j;
+
+ if (ddp_gl_map(pdev, gl) < 0)
+ goto error_out;
+
+ return gl;
+
+error_out:
+ kfree(gl);
+ return NULL;
+}
+
+static void ddp_tag_release(struct cxgbi_hba *chba, u32 tag)
+{
+ struct cxgbi_device *cdev = chba->cdev;
+ struct cxgbi_ddp_info *ddp = cdev->ddp;
+ u32 idx;
+
+ idx = (tag >> PPOD_IDX_SHIFT) & ddp->idx_mask;
+ if (idx < ddp->nppods) {
+ struct cxgbi_gather_list *gl = ddp->gl_map[idx];
+ unsigned int npods;
+
+ if (!gl || !gl->nelem) {
+ pr_warn("tag 0x%x, idx %u, gl 0x%p, %u.\n",
+ tag, idx, gl, gl ? gl->nelem : 0);
+ return;
+ }
+ npods = (gl->nelem + PPOD_PAGES_MAX - 1) >> PPOD_PAGES_SHIFT;
+ log_debug(1 << CXGBI_DBG_DDP,
+ "tag 0x%x, release idx %u, npods %u.\n",
+ tag, idx, npods);
+ cdev->csk_ddp_clear(chba, tag, idx, npods);
+ ddp_unmark_entries(ddp, idx, npods);
+ ddp_release_gl(gl, ddp->pdev);
+ } else
+ pr_warn("tag 0x%x, idx %u > max %u.\n", tag, idx, ddp->nppods);
+}
+
+static int ddp_tag_reserve(struct cxgbi_sock *csk, unsigned int tid,
+ u32 sw_tag, u32 *tagp, struct cxgbi_gather_list *gl,
+ gfp_t gfp)
+{
+ struct cxgbi_device *cdev = csk->cdev;
+ struct cxgbi_ddp_info *ddp = cdev->ddp;
+ struct cxgbi_tag_format *tformat = &cdev->tag_format;
+ struct cxgbi_pagepod_hdr hdr;
+ unsigned int npods;
+ int idx = -1;
+ int err = -ENOMEM;
+ u32 tag;
+
+ npods = (gl->nelem + PPOD_PAGES_MAX - 1) >> PPOD_PAGES_SHIFT;
+ if (ddp->idx_last == ddp->nppods)
+ idx = ddp_find_unused_entries(ddp, 0, ddp->nppods,
+ npods, gl);
+ else {
+ idx = ddp_find_unused_entries(ddp, ddp->idx_last + 1,
+ ddp->nppods, npods,
+ gl);
+ if (idx < 0 && ddp->idx_last >= npods) {
+ idx = ddp_find_unused_entries(ddp, 0,
+ min(ddp->idx_last + npods, ddp->nppods),
+ npods, gl);
+ }
+ }
+ if (idx < 0) {
+ log_debug(1 << CXGBI_DBG_DDP,
+ "xferlen %u, gl %u, npods %u NO DDP.\n",
+ gl->length, gl->nelem, npods);
+ return idx;
+ }
+
+ if (cdev->csk_ddp_alloc_gl_skb) {
+ err = cdev->csk_ddp_alloc_gl_skb(ddp, idx, npods, gfp);
+ if (err < 0)
+ goto unmark_entries;
+ }
+
+ tag = cxgbi_ddp_tag_base(tformat, sw_tag);
+ tag |= idx << PPOD_IDX_SHIFT;
+
+ hdr.rsvd = 0;
+ hdr.vld_tid = htonl(PPOD_VALID_FLAG | PPOD_TID(tid));
+ hdr.pgsz_tag_clr = htonl(tag & ddp->rsvd_tag_mask);
+ hdr.max_offset = htonl(gl->length);
+ hdr.page_offset = htonl(gl->offset);
+
+ err = cdev->csk_ddp_set(csk, &hdr, idx, npods, gl);
+ if (err < 0) {
+ if (cdev->csk_ddp_free_gl_skb)
+ cdev->csk_ddp_free_gl_skb(ddp, idx, npods);
+ goto unmark_entries;
+ }
+
+ ddp->idx_last = idx;
+ log_debug(1 << CXGBI_DBG_DDP,
+ "xfer %u, gl %u,%u, tid 0x%x, tag 0x%x->0x%x(%u,%u).\n",
+ gl->length, gl->nelem, gl->offset, tid, sw_tag, tag, idx,
+ npods);
+ *tagp = tag;
+ return 0;
+
+unmark_entries:
+ ddp_unmark_entries(ddp, idx, npods);
+ return err;
+}
+
+int cxgbi_ddp_reserve(struct cxgbi_sock *csk, unsigned int *tagp,
+ unsigned int sw_tag, unsigned int xferlen,
+ struct scatterlist *sgl, unsigned int sgcnt, gfp_t gfp)
+{
+ struct cxgbi_device *cdev = csk->cdev;
+ struct cxgbi_tag_format *tformat = &cdev->tag_format;
+ struct cxgbi_gather_list *gl;
+ int err;
+
+ if (page_idx >= DDP_PGIDX_MAX || !cdev->ddp ||
+ xferlen < DDP_THRESHOLD) {
+ log_debug(1 << CXGBI_DBG_DDP,
+ "pgidx %u, xfer %u, NO ddp.\n", page_idx, xferlen);
+ return -EINVAL;
+ }
+
+ if (!cxgbi_sw_tag_usable(tformat, sw_tag)) {
+ log_debug(1 << CXGBI_DBG_DDP,
+ "sw_tag 0x%x NOT usable.\n", sw_tag);
+ return -EINVAL;
+ }
+
+ gl = ddp_make_gl(xferlen, sgl, sgcnt, cdev->pdev, gfp);
+ if (!gl)
+ return -ENOMEM;
+
+ err = ddp_tag_reserve(csk, csk->tid, sw_tag, tagp, gl, gfp);
+ if (err < 0)
+ ddp_release_gl(gl, cdev->pdev);
+
+ return err;
+}
+
+static void ddp_destroy(struct kref *kref)
+{
+ struct cxgbi_ddp_info *ddp = container_of(kref,
+ struct cxgbi_ddp_info,
+ refcnt);
+ struct cxgbi_device *cdev = ddp->cdev;
+ int i = 0;
+
+ pr_info("kref 0, destroy ddp 0x%p, cdev 0x%p.\n", ddp, cdev);
+
+ while (i < ddp->nppods) {
+ struct cxgbi_gather_list *gl = ddp->gl_map[i];
+
+ if (gl) {
+ int npods = (gl->nelem + PPOD_PAGES_MAX - 1)
+ >> PPOD_PAGES_SHIFT;
+ pr_info("cdev 0x%p, ddp %d + %d.\n", cdev, i, npods);
+ kfree(gl);
+ if (cdev->csk_ddp_free_gl_skb)
+ cdev->csk_ddp_free_gl_skb(ddp, i, npods);
+ i += npods;
+ } else
+ i++;
+ }
+ cxgbi_free_big_mem(ddp);
+}
+
+int cxgbi_ddp_cleanup(struct cxgbi_device *cdev)
+{
+ struct cxgbi_ddp_info *ddp = cdev->ddp;
+
+ log_debug(1 << CXGBI_DBG_DDP,
+ "cdev 0x%p, release ddp 0x%p.\n", cdev, ddp);
+ cdev->ddp = NULL;
+ if (ddp)
+ return kref_put(&ddp->refcnt, ddp_destroy);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cxgbi_ddp_cleanup);
+
+int cxgbi_ddp_init(struct cxgbi_device *cdev,
+ unsigned int llimit, unsigned int ulimit,
+ unsigned int max_txsz, unsigned int max_rxsz)
+{
+ struct cxgbi_ddp_info *ddp;
+ unsigned int ppmax, bits;
+
+ ppmax = (ulimit - llimit + 1) >> PPOD_SIZE_SHIFT;
+ bits = __ilog2_u32(ppmax) + 1;
+ if (bits > PPOD_IDX_MAX_SIZE)
+ bits = PPOD_IDX_MAX_SIZE;
+ ppmax = (1 << (bits - 1)) - 1;
+
+ ddp = cxgbi_alloc_big_mem(sizeof(struct cxgbi_ddp_info) +
+ ppmax * (sizeof(struct cxgbi_gather_list *) +
+ sizeof(struct sk_buff *)),
+ GFP_KERNEL);
+ if (!ddp) {
+ pr_warn("cdev 0x%p, ddp ppmax %u OOM.\n", cdev, ppmax);
+ return -ENOMEM;
+ }
+ ddp->gl_map = (struct cxgbi_gather_list **)(ddp + 1);
+ ddp->gl_skb = (struct sk_buff **)(((char *)ddp->gl_map) +
+ ppmax * sizeof(struct cxgbi_gather_list *));
+ cdev->ddp = ddp;
+
+ spin_lock_init(&ddp->map_lock);
+ kref_init(&ddp->refcnt);
+
+ ddp->cdev = cdev;
+ ddp->pdev = cdev->pdev;
+ ddp->llimit = llimit;
+ ddp->ulimit = ulimit;
+ ddp->max_txsz = min_t(unsigned int, max_txsz, ULP2_MAX_PKT_SIZE);
+ ddp->max_rxsz = min_t(unsigned int, max_rxsz, ULP2_MAX_PKT_SIZE);
+ ddp->nppods = ppmax;
+ ddp->idx_last = ppmax;
+ ddp->idx_bits = bits;
+ ddp->idx_mask = (1 << bits) - 1;
+ ddp->rsvd_tag_mask = (1 << (bits + PPOD_IDX_SHIFT)) - 1;
+
+ cdev->tag_format.sw_bits = sw_tag_idx_bits + sw_tag_age_bits;
+ cdev->tag_format.rsvd_bits = ddp->idx_bits;
+ cdev->tag_format.rsvd_shift = PPOD_IDX_SHIFT;
+ cdev->tag_format.rsvd_mask = (1 << cdev->tag_format.rsvd_bits) - 1;
+
+ pr_info("%s tag format, sw %u, rsvd %u,%u, mask 0x%x.\n",
+ cdev->ports[0]->name, cdev->tag_format.sw_bits,
+ cdev->tag_format.rsvd_bits, cdev->tag_format.rsvd_shift,
+ cdev->tag_format.rsvd_mask);
+
+ cdev->tx_max_size = min_t(unsigned int, ULP2_MAX_PDU_PAYLOAD,
+ ddp->max_txsz - ISCSI_PDU_NONPAYLOAD_LEN);
+ cdev->rx_max_size = min_t(unsigned int, ULP2_MAX_PDU_PAYLOAD,
+ ddp->max_rxsz - ISCSI_PDU_NONPAYLOAD_LEN);
+
+ log_debug(1 << CXGBI_DBG_DDP,
+ "%s max payload size: %u/%u, %u/%u.\n",
+ cdev->ports[0]->name, cdev->tx_max_size, ddp->max_txsz,
+ cdev->rx_max_size, ddp->max_rxsz);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cxgbi_ddp_init);
+
+/*
+ * APIs interacting with open-iscsi libraries
+ */
+
+static unsigned char padding[4];
+
+static void task_release_itt(struct iscsi_task *task, itt_t hdr_itt)
+{
+ struct scsi_cmnd *sc = task->sc;
+ struct iscsi_tcp_conn *tcp_conn = task->conn->dd_data;
+ struct cxgbi_conn *cconn = tcp_conn->dd_data;
+ struct cxgbi_hba *chba = cconn->chba;
+ struct cxgbi_tag_format *tformat = &chba->cdev->tag_format;
+ u32 tag = ntohl((__force u32)hdr_itt);
+
+ log_debug(1 << CXGBI_DBG_DDP,
+ "cdev 0x%p, release tag 0x%x.\n", chba->cdev, tag);
+ if (sc &&
+ (scsi_bidi_cmnd(sc) || sc->sc_data_direction == DMA_FROM_DEVICE) &&
+ cxgbi_is_ddp_tag(tformat, tag))
+ ddp_tag_release(chba, tag);
+}
+
+static int task_reserve_itt(struct iscsi_task *task, itt_t *hdr_itt)
+{
+ struct scsi_cmnd *sc = task->sc;
+ struct iscsi_conn *conn = task->conn;
+ struct iscsi_session *sess = conn->session;
+ struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ struct cxgbi_conn *cconn = tcp_conn->dd_data;
+ struct cxgbi_hba *chba = cconn->chba;
+ struct cxgbi_tag_format *tformat = &chba->cdev->tag_format;
+ u32 sw_tag = (sess->age << cconn->task_idx_bits) | task->itt;
+ u32 tag = 0;
+ int err = -EINVAL;
+
+ if (sc &&
+ (scsi_bidi_cmnd(sc) || sc->sc_data_direction == DMA_FROM_DEVICE)) {
+ err = cxgbi_ddp_reserve(cconn->cep->csk, &tag, sw_tag,
+ scsi_in(sc)->length,
+ scsi_in(sc)->table.sgl,
+ scsi_in(sc)->table.nents,
+ GFP_ATOMIC);
+ if (err < 0)
+ log_debug(1 << CXGBI_DBG_DDP,
+ "csk 0x%p, R task 0x%p, %u,%u, no ddp.\n",
+ cconn->cep->csk, task, scsi_in(sc)->length,
+ scsi_in(sc)->table.nents);
+ }
+
+ if (err < 0)
+ tag = cxgbi_set_non_ddp_tag(tformat, sw_tag);
+ /* the itt need to sent in big-endian order */
+ *hdr_itt = (__force itt_t)htonl(tag);
+
+ log_debug(1 << CXGBI_DBG_DDP,
+ "cdev 0x%p, task 0x%p, 0x%x(0x%x,0x%x)->0x%x/0x%x.\n",
+ chba->cdev, task, sw_tag, task->itt, sess->age, tag, *hdr_itt);
+ return 0;
+}
+
+void cxgbi_parse_pdu_itt(struct iscsi_conn *conn, itt_t itt, int *idx, int *age)
+{
+ struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ struct cxgbi_conn *cconn = tcp_conn->dd_data;
+ struct cxgbi_device *cdev = cconn->chba->cdev;
+ u32 tag = ntohl((__force u32) itt);
+ u32 sw_bits;
+
+ sw_bits = cxgbi_tag_nonrsvd_bits(&cdev->tag_format, tag);
+ if (idx)
+ *idx = sw_bits & ((1 << cconn->task_idx_bits) - 1);
+ if (age)
+ *age = (sw_bits >> cconn->task_idx_bits) & ISCSI_AGE_MASK;
+
+ log_debug(1 << CXGBI_DBG_DDP,
+ "cdev 0x%p, tag 0x%x/0x%x, -> 0x%x(0x%x,0x%x).\n",
+ cdev, tag, itt, sw_bits, idx ? *idx : 0xFFFFF,
+ age ? *age : 0xFF);
+}
+EXPORT_SYMBOL_GPL(cxgbi_parse_pdu_itt);
+
+void cxgbi_conn_tx_open(struct cxgbi_sock *csk)
+{
+ struct iscsi_conn *conn = csk->user_data;
+
+ if (conn) {
+ log_debug(1 << CXGBI_DBG_SOCK,
+ "csk 0x%p, cid %d.\n", csk, conn->id);
+ iscsi_conn_queue_work(conn);
+ }
+}
+EXPORT_SYMBOL_GPL(cxgbi_conn_tx_open);
+
+/*
+ * pdu receive, interact with libiscsi_tcp
+ */
+static inline int read_pdu_skb(struct iscsi_conn *conn,
+ struct sk_buff *skb,
+ unsigned int offset,
+ int offloaded)
+{
+ int status = 0;
+ int bytes_read;
+
+ bytes_read = iscsi_tcp_recv_skb(conn, skb, offset, offloaded, &status);
+ switch (status) {
+ case ISCSI_TCP_CONN_ERR:
+ pr_info("skb 0x%p, off %u, %d, TCP_ERR.\n",
+ skb, offset, offloaded);
+ return -EIO;
+ case ISCSI_TCP_SUSPENDED:
+ log_debug(1 << CXGBI_DBG_PDU_RX,
+ "skb 0x%p, off %u, %d, TCP_SUSPEND, rc %d.\n",
+ skb, offset, offloaded, bytes_read);
+ /* no transfer - just have caller flush queue */
+ return bytes_read;
+ case ISCSI_TCP_SKB_DONE:
+ pr_info("skb 0x%p, off %u, %d, TCP_SKB_DONE.\n",
+ skb, offset, offloaded);
+ /*
+ * pdus should always fit in the skb and we should get
+ * segment done notifcation.
+ */
+ iscsi_conn_printk(KERN_ERR, conn, "Invalid pdu or skb.");
+ return -EFAULT;
+ case ISCSI_TCP_SEGMENT_DONE:
+ log_debug(1 << CXGBI_DBG_PDU_RX,
+ "skb 0x%p, off %u, %d, TCP_SEG_DONE, rc %d.\n",
+ skb, offset, offloaded, bytes_read);
+ return bytes_read;
+ default:
+ pr_info("skb 0x%p, off %u, %d, invalid status %d.\n",
+ skb, offset, offloaded, status);
+ return -EINVAL;
+ }
+}
+
+static int skb_read_pdu_bhs(struct iscsi_conn *conn, struct sk_buff *skb)
+{
+ struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+
+ log_debug(1 << CXGBI_DBG_PDU_RX,
+ "conn 0x%p, skb 0x%p, len %u, flag 0x%lx.\n",
+ conn, skb, skb->len, cxgbi_skcb_flags(skb));
+
+ if (!iscsi_tcp_recv_segment_is_hdr(tcp_conn)) {
+ pr_info("conn 0x%p, skb 0x%p, not hdr.\n", conn, skb);
+ iscsi_conn_failure(conn, ISCSI_ERR_PROTO);
+ return -EIO;
+ }
+
+ if (conn->hdrdgst_en &&
+ cxgbi_skcb_test_flag(skb, SKCBF_RX_HCRC_ERR)) {
+ pr_info("conn 0x%p, skb 0x%p, hcrc.\n", conn, skb);
+ iscsi_conn_failure(conn, ISCSI_ERR_HDR_DGST);
+ return -EIO;
+ }
+
+ return read_pdu_skb(conn, skb, 0, 0);
+}
+
+static int skb_read_pdu_data(struct iscsi_conn *conn, struct sk_buff *lskb,
+ struct sk_buff *skb, unsigned int offset)
+{
+ struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ bool offloaded = 0;
+ int opcode = tcp_conn->in.hdr->opcode & ISCSI_OPCODE_MASK;
+
+ log_debug(1 << CXGBI_DBG_PDU_RX,
+ "conn 0x%p, skb 0x%p, len %u, flag 0x%lx.\n",
+ conn, skb, skb->len, cxgbi_skcb_flags(skb));
+
+ if (conn->datadgst_en &&
+ cxgbi_skcb_test_flag(lskb, SKCBF_RX_DCRC_ERR)) {
+ pr_info("conn 0x%p, skb 0x%p, dcrc 0x%lx.\n",
+ conn, lskb, cxgbi_skcb_flags(lskb));
+ iscsi_conn_failure(conn, ISCSI_ERR_DATA_DGST);
+ return -EIO;
+ }
+
+ if (iscsi_tcp_recv_segment_is_hdr(tcp_conn))
+ return 0;
+
+ /* coalesced, add header digest length */
+ if (lskb == skb && conn->hdrdgst_en)
+ offset += ISCSI_DIGEST_SIZE;
+
+ if (cxgbi_skcb_test_flag(lskb, SKCBF_RX_DATA_DDPD))
+ offloaded = 1;
+
+ if (opcode == ISCSI_OP_SCSI_DATA_IN)
+ log_debug(1 << CXGBI_DBG_PDU_RX,
+ "skb 0x%p, op 0x%x, itt 0x%x, %u %s ddp'ed.\n",
+ skb, opcode, ntohl(tcp_conn->in.hdr->itt),
+ tcp_conn->in.datalen, offloaded ? "is" : "not");
+
+ return read_pdu_skb(conn, skb, offset, offloaded);
+}
+
+static void csk_return_rx_credits(struct cxgbi_sock *csk, int copied)
+{
+ struct cxgbi_device *cdev = csk->cdev;
+ int must_send;
+ u32 credits;
+
+ log_debug(1 << CXGBI_DBG_PDU_RX,
+ "csk 0x%p,%u,0x%lu,%u, seq %u, wup %u, thre %u, %u.\n",
+ csk, csk->state, csk->flags, csk->tid, csk->copied_seq,
+ csk->rcv_wup, cdev->rx_credit_thres,
+ cdev->rcv_win);
+
+ if (csk->state != CTP_ESTABLISHED)
+ return;
+
+ credits = csk->copied_seq - csk->rcv_wup;
+ if (unlikely(!credits))
+ return;
+ if (unlikely(cdev->rx_credit_thres == 0))
+ return;
+
+ must_send = credits + 16384 >= cdev->rcv_win;
+ if (must_send || credits >= cdev->rx_credit_thres)
+ csk->rcv_wup += cdev->csk_send_rx_credits(csk, credits);
+}
+
+void cxgbi_conn_pdu_ready(struct cxgbi_sock *csk)
+{
+ struct cxgbi_device *cdev = csk->cdev;
+ struct iscsi_conn *conn = csk->user_data;
+ struct sk_buff *skb;
+ unsigned int read = 0;
+ int err = 0;
+
+ log_debug(1 << CXGBI_DBG_PDU_RX,
+ "csk 0x%p, conn 0x%p.\n", csk, conn);
+
+ if (unlikely(!conn || conn->suspend_rx)) {
+ log_debug(1 << CXGBI_DBG_PDU_RX,
+ "csk 0x%p, conn 0x%p, id %d, suspend_rx %lu!\n",
+ csk, conn, conn ? conn->id : 0xFF,
+ conn ? conn->suspend_rx : 0xFF);
+ return;
+ }
+
+ while (!err) {
+ skb = skb_peek(&csk->receive_queue);
+ if (!skb ||
+ !(cxgbi_skcb_test_flag(skb, SKCBF_RX_STATUS))) {
+ if (skb)
+ log_debug(1 << CXGBI_DBG_PDU_RX,
+ "skb 0x%p, NOT ready 0x%lx.\n",
+ skb, cxgbi_skcb_flags(skb));
+ break;
+ }
+ __skb_unlink(skb, &csk->receive_queue);
+
+ read += cxgbi_skcb_rx_pdulen(skb);
+ log_debug(1 << CXGBI_DBG_PDU_RX,
+ "csk 0x%p, skb 0x%p,%u,f 0x%lx, pdu len %u.\n",
+ csk, skb, skb->len, cxgbi_skcb_flags(skb),
+ cxgbi_skcb_rx_pdulen(skb));
+
+ if (cxgbi_skcb_test_flag(skb, SKCBF_RX_COALESCED)) {
+ err = skb_read_pdu_bhs(conn, skb);
+ if (err < 0) {
+ pr_err("coalesced bhs, csk 0x%p, skb 0x%p,%u, "
+ "f 0x%lx, plen %u.\n",
+ csk, skb, skb->len,
+ cxgbi_skcb_flags(skb),
+ cxgbi_skcb_rx_pdulen(skb));
+ goto skb_done;
+ }
+ err = skb_read_pdu_data(conn, skb, skb,
+ err + cdev->skb_rx_extra);
+ if (err < 0)
+ pr_err("coalesced data, csk 0x%p, skb 0x%p,%u, "
+ "f 0x%lx, plen %u.\n",
+ csk, skb, skb->len,
+ cxgbi_skcb_flags(skb),
+ cxgbi_skcb_rx_pdulen(skb));
+ } else {
+ err = skb_read_pdu_bhs(conn, skb);
+ if (err < 0) {
+ pr_err("bhs, csk 0x%p, skb 0x%p,%u, "
+ "f 0x%lx, plen %u.\n",
+ csk, skb, skb->len,
+ cxgbi_skcb_flags(skb),
+ cxgbi_skcb_rx_pdulen(skb));
+ goto skb_done;
+ }
+
+ if (cxgbi_skcb_test_flag(skb, SKCBF_RX_DATA)) {
+ struct sk_buff *dskb;
+
+ dskb = skb_peek(&csk->receive_queue);
+ if (!dskb) {
+ pr_err("csk 0x%p, skb 0x%p,%u, f 0x%lx,"
+ " plen %u, NO data.\n",
+ csk, skb, skb->len,
+ cxgbi_skcb_flags(skb),
+ cxgbi_skcb_rx_pdulen(skb));
+ err = -EIO;
+ goto skb_done;
+ }
+ __skb_unlink(dskb, &csk->receive_queue);
+
+ err = skb_read_pdu_data(conn, skb, dskb, 0);
+ if (err < 0)
+ pr_err("data, csk 0x%p, skb 0x%p,%u, "
+ "f 0x%lx, plen %u, dskb 0x%p,"
+ "%u.\n",
+ csk, skb, skb->len,
+ cxgbi_skcb_flags(skb),
+ cxgbi_skcb_rx_pdulen(skb),
+ dskb, dskb->len);
+ __kfree_skb(dskb);
+ } else
+ err = skb_read_pdu_data(conn, skb, skb, 0);
+ }
+skb_done:
+ __kfree_skb(skb);
+
+ if (err < 0)
+ break;
+ }
+
+ log_debug(1 << CXGBI_DBG_PDU_RX, "csk 0x%p, read %u.\n", csk, read);
+ if (read) {
+ csk->copied_seq += read;
+ csk_return_rx_credits(csk, read);
+ conn->rxdata_octets += read;
+ }
+
+ if (err < 0) {
+ pr_info("csk 0x%p, 0x%p, rx failed %d, read %u.\n",
+ csk, conn, err, read);
+ iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+ }
+}
+EXPORT_SYMBOL_GPL(cxgbi_conn_pdu_ready);
+
+static int sgl_seek_offset(struct scatterlist *sgl, unsigned int sgcnt,
+ unsigned int offset, unsigned int *off,
+ struct scatterlist **sgp)
+{
+ int i;
+ struct scatterlist *sg;
+
+ for_each_sg(sgl, sg, sgcnt, i) {
+ if (offset < sg->length) {
+ *off = offset;
+ *sgp = sg;
+ return 0;
+ }
+ offset -= sg->length;
+ }
+ return -EFAULT;
+}
+
+static int sgl_read_to_frags(struct scatterlist *sg, unsigned int sgoffset,
+ unsigned int dlen, skb_frag_t *frags,
+ int frag_max)
+{
+ unsigned int datalen = dlen;
+ unsigned int sglen = sg->length - sgoffset;
+ struct page *page = sg_page(sg);
+ int i;
+
+ i = 0;
+ do {
+ unsigned int copy;
+
+ if (!sglen) {
+ sg = sg_next(sg);
+ if (!sg) {
+ pr_warn("sg %d NULL, len %u/%u.\n",
+ i, datalen, dlen);
+ return -EINVAL;
+ }
+ sgoffset = 0;
+ sglen = sg->length;
+ page = sg_page(sg);
+
+ }
+ copy = min(datalen, sglen);
+ if (i && page == frags[i - 1].page &&
+ sgoffset + sg->offset ==
+ frags[i - 1].page_offset + frags[i - 1].size) {
+ frags[i - 1].size += copy;
+ } else {
+ if (i >= frag_max) {
+ pr_warn("too many pages %u, dlen %u.\n",
+ frag_max, dlen);
+ return -EINVAL;
+ }
+
+ frags[i].page = page;
+ frags[i].page_offset = sg->offset + sgoffset;
+ frags[i].size = copy;
+ i++;
+ }
+ datalen -= copy;
+ sgoffset += copy;
+ sglen -= copy;
+ } while (datalen);
+
+ return i;
+}
+
+int cxgbi_conn_alloc_pdu(struct iscsi_task *task, u8 opcode)
+{
+ struct iscsi_tcp_conn *tcp_conn = task->conn->dd_data;
+ struct cxgbi_conn *cconn = tcp_conn->dd_data;
+ struct cxgbi_device *cdev = cconn->chba->cdev;
+ struct iscsi_conn *conn = task->conn;
+ struct iscsi_tcp_task *tcp_task = task->dd_data;
+ struct cxgbi_task_data *tdata = iscsi_task_cxgbi_data(task);
+ struct scsi_cmnd *sc = task->sc;
+ int headroom = SKB_TX_ISCSI_PDU_HEADER_MAX;
+
+ tcp_task->dd_data = tdata;
+ task->hdr = NULL;
+
+ if (SKB_MAX_HEAD(cdev->skb_tx_rsvd) > (512 * MAX_SKB_FRAGS) &&
+ (opcode == ISCSI_OP_SCSI_DATA_OUT ||
+ (opcode == ISCSI_OP_SCSI_CMD &&
+ (scsi_bidi_cmnd(sc) || sc->sc_data_direction == DMA_TO_DEVICE))))
+ /* data could goes into skb head */
+ headroom += min_t(unsigned int,
+ SKB_MAX_HEAD(cdev->skb_tx_rsvd),
+ conn->max_xmit_dlength);
+
+ tdata->skb = alloc_skb(cdev->skb_tx_rsvd + headroom, GFP_ATOMIC);
+ if (!tdata->skb) {
+ pr_warn("alloc skb %u+%u, opcode 0x%x failed.\n",
+ cdev->skb_tx_rsvd, headroom, opcode);
+ return -ENOMEM;
+ }
+
+ skb_reserve(tdata->skb, cdev->skb_tx_rsvd);
+ task->hdr = (struct iscsi_hdr *)tdata->skb->data;
+ task->hdr_max = SKB_TX_ISCSI_PDU_HEADER_MAX; /* BHS + AHS */
+
+ /* data_out uses scsi_cmd's itt */
+ if (opcode != ISCSI_OP_SCSI_DATA_OUT)
+ task_reserve_itt(task, &task->hdr->itt);
+
+ log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_PDU_TX,
+ "task 0x%p, op 0x%x, skb 0x%p,%u+%u/%u, itt 0x%x.\n",
+ task, opcode, tdata->skb, cdev->skb_tx_rsvd, headroom,
+ conn->max_xmit_dlength, ntohl(task->hdr->itt));
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cxgbi_conn_alloc_pdu);
+
+static inline void tx_skb_setmode(struct sk_buff *skb, int hcrc, int dcrc)
+{
+ u8 submode = 0;
+
+ if (hcrc)
+ submode |= 1;
+ if (dcrc)
+ submode |= 2;
+ cxgbi_skcb_ulp_mode(skb) = (ULP2_MODE_ISCSI << 4) | submode;
+}
+
+int cxgbi_conn_init_pdu(struct iscsi_task *task, unsigned int offset,
+ unsigned int count)
+{
+ struct iscsi_conn *conn = task->conn;
+ struct cxgbi_task_data *tdata = iscsi_task_cxgbi_data(task);
+ struct sk_buff *skb = tdata->skb;
+ unsigned int datalen = count;
+ int i, padlen = iscsi_padding(count);
+ struct page *pg;
+
+ log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_PDU_TX,
+ "task 0x%p,0x%p, skb 0x%p, 0x%x,0x%x,0x%x, %u+%u.\n",
+ task, task->sc, skb, (*skb->data) & ISCSI_OPCODE_MASK,
+ ntohl(task->cmdsn), ntohl(task->hdr->itt), offset, count);
+
+ skb_put(skb, task->hdr_len);
+ tx_skb_setmode(skb, conn->hdrdgst_en, datalen ? conn->datadgst_en : 0);
+ if (!count)
+ return 0;
+
+ if (task->sc) {
+ struct scsi_data_buffer *sdb = scsi_out(task->sc);
+ struct scatterlist *sg = NULL;
+ int err;
+
+ tdata->offset = offset;
+ tdata->count = count;
+ err = sgl_seek_offset(
+ sdb->table.sgl, sdb->table.nents,
+ tdata->offset, &tdata->sgoffset, &sg);
+ if (err < 0) {
+ pr_warn("tpdu, sgl %u, bad offset %u/%u.\n",
+ sdb->table.nents, tdata->offset, sdb->length);
+ return err;
+ }
+ err = sgl_read_to_frags(sg, tdata->sgoffset, tdata->count,
+ tdata->frags, MAX_PDU_FRAGS);
+ if (err < 0) {
+ pr_warn("tpdu, sgl %u, bad offset %u + %u.\n",
+ sdb->table.nents, tdata->offset, tdata->count);
+ return err;
+ }
+ tdata->nr_frags = err;
+
+ if (tdata->nr_frags > MAX_SKB_FRAGS ||
+ (padlen && tdata->nr_frags == MAX_SKB_FRAGS)) {
+ char *dst = skb->data + task->hdr_len;
+ skb_frag_t *frag = tdata->frags;
+
+ /* data fits in the skb's headroom */
+ for (i = 0; i < tdata->nr_frags; i++, frag++) {
+ char *src = kmap_atomic(frag->page,
+ KM_SOFTIRQ0);
+
+ memcpy(dst, src+frag->page_offset, frag->size);
+ dst += frag->size;
+ kunmap_atomic(src, KM_SOFTIRQ0);
+ }
+ if (padlen) {
+ memset(dst, 0, padlen);
+ padlen = 0;
+ }
+ skb_put(skb, count + padlen);
+ } else {
+ /* data fit into frag_list */
+ for (i = 0; i < tdata->nr_frags; i++)
+ get_page(tdata->frags[i].page);
+
+ memcpy(skb_shinfo(skb)->frags, tdata->frags,
+ sizeof(skb_frag_t) * tdata->nr_frags);
+ skb_shinfo(skb)->nr_frags = tdata->nr_frags;
+ skb->len += count;
+ skb->data_len += count;
+ skb->truesize += count;
+ }
+
+ } else {
+ pg = virt_to_page(task->data);
+
+ get_page(pg);
+ skb_fill_page_desc(skb, 0, pg, offset_in_page(task->data),
+ count);
+ skb->len += count;
+ skb->data_len += count;
+ skb->truesize += count;
+ }
+
+ if (padlen) {
+ i = skb_shinfo(skb)->nr_frags;
+ skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags,
+ virt_to_page(padding), offset_in_page(padding),
+ padlen);
+
+ skb->data_len += padlen;
+ skb->truesize += padlen;
+ skb->len += padlen;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cxgbi_conn_init_pdu);
+
+int cxgbi_conn_xmit_pdu(struct iscsi_task *task)
+{
+ struct iscsi_tcp_conn *tcp_conn = task->conn->dd_data;
+ struct cxgbi_conn *cconn = tcp_conn->dd_data;
+ struct cxgbi_task_data *tdata = iscsi_task_cxgbi_data(task);
+ struct sk_buff *skb = tdata->skb;
+ unsigned int datalen;
+ int err;
+
+ if (!skb) {
+ log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_PDU_TX,
+ "task 0x%p, skb NULL.\n", task);
+ return 0;
+ }
+
+ datalen = skb->data_len;
+ tdata->skb = NULL;
+ err = cxgbi_sock_send_pdus(cconn->cep->csk, skb);
+ if (err > 0) {
+ int pdulen = err;
+
+ log_debug(1 << CXGBI_DBG_PDU_TX,
+ "task 0x%p,0x%p, skb 0x%p, len %u/%u, rv %d.\n",
+ task, task->sc, skb, skb->len, skb->data_len, err);
+
+ if (task->conn->hdrdgst_en)
+ pdulen += ISCSI_DIGEST_SIZE;
+
+ if (datalen && task->conn->datadgst_en)
+ pdulen += ISCSI_DIGEST_SIZE;
+
+ task->conn->txdata_octets += pdulen;
+ return 0;
+ }
+
+ if (err == -EAGAIN || err == -ENOBUFS) {
+ log_debug(1 << CXGBI_DBG_PDU_TX,
+ "task 0x%p, skb 0x%p, len %u/%u, %d EAGAIN.\n",
+ task, skb, skb->len, skb->data_len, err);
+ /* reset skb to send when we are called again */
+ tdata->skb = skb;
+ return err;
+ }
+
+ kfree_skb(skb);
+ log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_PDU_TX,
+ "itt 0x%x, skb 0x%p, len %u/%u, xmit err %d.\n",
+ task->itt, skb, skb->len, skb->data_len, err);
+ iscsi_conn_printk(KERN_ERR, task->conn, "xmit err %d.\n", err);
+ iscsi_conn_failure(task->conn, ISCSI_ERR_XMIT_FAILED);
+ return err;
+}
+EXPORT_SYMBOL_GPL(cxgbi_conn_xmit_pdu);
+
+void cxgbi_cleanup_task(struct iscsi_task *task)
+{
+ struct cxgbi_task_data *tdata = iscsi_task_cxgbi_data(task);
+
+ log_debug(1 << CXGBI_DBG_ISCSI,
+ "task 0x%p, skb 0x%p, itt 0x%x.\n",
+ task, tdata->skb, task->hdr_itt);
+
+ /* never reached the xmit task callout */
+ if (tdata->skb)
+ __kfree_skb(tdata->skb);
+ memset(tdata, 0, sizeof(*tdata));
+
+ task_release_itt(task, task->hdr_itt);
+ iscsi_tcp_cleanup_task(task);
+}
+EXPORT_SYMBOL_GPL(cxgbi_cleanup_task);
+
+void cxgbi_get_conn_stats(struct iscsi_cls_conn *cls_conn,
+ struct iscsi_stats *stats)
+{
+ struct iscsi_conn *conn = cls_conn->dd_data;
+
+ stats->txdata_octets = conn->txdata_octets;
+ stats->rxdata_octets = conn->rxdata_octets;
+ stats->scsicmd_pdus = conn->scsicmd_pdus_cnt;
+ stats->dataout_pdus = conn->dataout_pdus_cnt;
+ stats->scsirsp_pdus = conn->scsirsp_pdus_cnt;
+ stats->datain_pdus = conn->datain_pdus_cnt;
+ stats->r2t_pdus = conn->r2t_pdus_cnt;
+ stats->tmfcmd_pdus = conn->tmfcmd_pdus_cnt;
+ stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt;
+ stats->digest_err = 0;
+ stats->timeout_err = 0;
+ stats->custom_length = 1;
+ strcpy(stats->custom[0].desc, "eh_abort_cnt");
+ stats->custom[0].value = conn->eh_abort_cnt;
+}
+EXPORT_SYMBOL_GPL(cxgbi_get_conn_stats);
+
+static int cxgbi_conn_max_xmit_dlength(struct iscsi_conn *conn)
+{
+ struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ struct cxgbi_conn *cconn = tcp_conn->dd_data;
+ struct cxgbi_device *cdev = cconn->chba->cdev;
+ unsigned int headroom = SKB_MAX_HEAD(cdev->skb_tx_rsvd);
+ unsigned int max_def = 512 * MAX_SKB_FRAGS;
+ unsigned int max = max(max_def, headroom);
+
+ max = min(cconn->chba->cdev->tx_max_size, max);
+ if (conn->max_xmit_dlength)
+ conn->max_xmit_dlength = min(conn->max_xmit_dlength, max);
+ else
+ conn->max_xmit_dlength = max;
+ cxgbi_align_pdu_size(conn->max_xmit_dlength);
+
+ return 0;
+}
+
+static int cxgbi_conn_max_recv_dlength(struct iscsi_conn *conn)
+{
+ struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ struct cxgbi_conn *cconn = tcp_conn->dd_data;
+ unsigned int max = cconn->chba->cdev->rx_max_size;
+
+ cxgbi_align_pdu_size(max);
+
+ if (conn->max_recv_dlength) {
+ if (conn->max_recv_dlength > max) {
+ pr_err("MaxRecvDataSegmentLength %u > %u.\n",
+ conn->max_recv_dlength, max);
+ return -EINVAL;
+ }
+ conn->max_recv_dlength = min(conn->max_recv_dlength, max);
+ cxgbi_align_pdu_size(conn->max_recv_dlength);
+ } else
+ conn->max_recv_dlength = max;
+
+ return 0;
+}
+
+int cxgbi_set_conn_param(struct iscsi_cls_conn *cls_conn,
+ enum iscsi_param param, char *buf, int buflen)
+{
+ struct iscsi_conn *conn = cls_conn->dd_data;
+ struct iscsi_session *session = conn->session;
+ struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ struct cxgbi_conn *cconn = tcp_conn->dd_data;
+ struct cxgbi_sock *csk = cconn->cep->csk;
+ int value, err = 0;
+
+ log_debug(1 << CXGBI_DBG_ISCSI,
+ "cls_conn 0x%p, param %d, buf(%d) %s.\n",
+ cls_conn, param, buflen, buf);
+
+ switch (param) {
+ case ISCSI_PARAM_HDRDGST_EN:
+ err = iscsi_set_param(cls_conn, param, buf, buflen);
+ if (!err && conn->hdrdgst_en)
+ err = csk->cdev->csk_ddp_setup_digest(csk, csk->tid,
+ conn->hdrdgst_en,
+ conn->datadgst_en, 0);
+ break;
+ case ISCSI_PARAM_DATADGST_EN:
+ err = iscsi_set_param(cls_conn, param, buf, buflen);
+ if (!err && conn->datadgst_en)
+ err = csk->cdev->csk_ddp_setup_digest(csk, csk->tid,
+ conn->hdrdgst_en,
+ conn->datadgst_en, 0);
+ break;
+ case ISCSI_PARAM_MAX_R2T:
+ sscanf(buf, "%d", &value);
+ if (value <= 0 || !is_power_of_2(value))
+ return -EINVAL;
+ if (session->max_r2t == value)
+ break;
+ iscsi_tcp_r2tpool_free(session);
+ err = iscsi_set_param(cls_conn, param, buf, buflen);
+ if (!err && iscsi_tcp_r2tpool_alloc(session))
+ return -ENOMEM;
+ case ISCSI_PARAM_MAX_RECV_DLENGTH:
+ err = iscsi_set_param(cls_conn, param, buf, buflen);
+ if (!err)
+ err = cxgbi_conn_max_recv_dlength(conn);
+ break;
+ case ISCSI_PARAM_MAX_XMIT_DLENGTH:
+ err = iscsi_set_param(cls_conn, param, buf, buflen);
+ if (!err)
+ err = cxgbi_conn_max_xmit_dlength(conn);
+ break;
+ default:
+ return iscsi_set_param(cls_conn, param, buf, buflen);
+ }
+ return err;
+}
+EXPORT_SYMBOL_GPL(cxgbi_set_conn_param);
+
+int cxgbi_get_conn_param(struct iscsi_cls_conn *cls_conn,
+ enum iscsi_param param, char *buf)
+{
+ struct iscsi_conn *iconn = cls_conn->dd_data;
+ int len;
+
+ log_debug(1 << CXGBI_DBG_ISCSI,
+ "cls_conn 0x%p, param %d.\n", cls_conn, param);
+
+ switch (param) {
+ case ISCSI_PARAM_CONN_PORT:
+ spin_lock_bh(&iconn->session->lock);
+ len = sprintf(buf, "%hu\n", iconn->portal_port);
+ spin_unlock_bh(&iconn->session->lock);
+ break;
+ case ISCSI_PARAM_CONN_ADDRESS:
+ spin_lock_bh(&iconn->session->lock);
+ len = sprintf(buf, "%s\n", iconn->portal_address);
+ spin_unlock_bh(&iconn->session->lock);
+ break;
+ default:
+ return iscsi_conn_get_param(cls_conn, param, buf);
+ }
+ return len;
+}
+EXPORT_SYMBOL_GPL(cxgbi_get_conn_param);
+
+struct iscsi_cls_conn *
+cxgbi_create_conn(struct iscsi_cls_session *cls_session, u32 cid)
+{
+ struct iscsi_cls_conn *cls_conn;
+ struct iscsi_conn *conn;
+ struct iscsi_tcp_conn *tcp_conn;
+ struct cxgbi_conn *cconn;
+
+ cls_conn = iscsi_tcp_conn_setup(cls_session, sizeof(*cconn), cid);
+ if (!cls_conn)
+ return NULL;
+
+ conn = cls_conn->dd_data;
+ tcp_conn = conn->dd_data;
+ cconn = tcp_conn->dd_data;
+ cconn->iconn = conn;
+
+ log_debug(1 << CXGBI_DBG_ISCSI,
+ "cid %u(0x%x), cls 0x%p,0x%p, conn 0x%p,0x%p,0x%p.\n",
+ cid, cid, cls_session, cls_conn, conn, tcp_conn, cconn);
+
+ return cls_conn;
+}
+EXPORT_SYMBOL_GPL(cxgbi_create_conn);
+
+int cxgbi_bind_conn(struct iscsi_cls_session *cls_session,
+ struct iscsi_cls_conn *cls_conn,
+ u64 transport_eph, int is_leading)
+{
+ struct iscsi_conn *conn = cls_conn->dd_data;
+ struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ struct cxgbi_conn *cconn = tcp_conn->dd_data;
+ struct iscsi_endpoint *ep;
+ struct cxgbi_endpoint *cep;
+ struct cxgbi_sock *csk;
+ int err;
+
+ ep = iscsi_lookup_endpoint(transport_eph);
+ if (!ep)
+ return -EINVAL;
+
+ /* setup ddp pagesize */
+ cep = ep->dd_data;
+ csk = cep->csk;
+ err = csk->cdev->csk_ddp_setup_pgidx(csk, csk->tid, page_idx, 0);
+ if (err < 0)
+ return err;
+
+ err = iscsi_conn_bind(cls_session, cls_conn, is_leading);
+ if (err)
+ return -EINVAL;
+
+ /* calculate the tag idx bits needed for this conn based on cmds_max */
+ cconn->task_idx_bits = (__ilog2_u32(conn->session->cmds_max - 1)) + 1;
+
+ write_lock_bh(&csk->callback_lock);
+ csk->user_data = conn;
+ cconn->chba = cep->chba;
+ cconn->cep = cep;
+ cep->cconn = cconn;
+ write_unlock_bh(&csk->callback_lock);
+
+ cxgbi_conn_max_xmit_dlength(conn);
+ cxgbi_conn_max_recv_dlength(conn);
+
+ spin_lock_bh(&conn->session->lock);
+ sprintf(conn->portal_address, "%pI4", &csk->daddr.sin_addr.s_addr);
+ conn->portal_port = ntohs(csk->daddr.sin_port);
+ spin_unlock_bh(&conn->session->lock);
+
+ log_debug(1 << CXGBI_DBG_ISCSI,
+ "cls 0x%p,0x%p, ep 0x%p, cconn 0x%p, csk 0x%p.\n",
+ cls_session, cls_conn, ep, cconn, csk);
+ /* init recv engine */
+ iscsi_tcp_hdr_recv_prep(tcp_conn);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cxgbi_bind_conn);
+
+struct iscsi_cls_session *cxgbi_create_session(struct iscsi_endpoint *ep,
+ u16 cmds_max, u16 qdepth,
+ u32 initial_cmdsn)
+{
+ struct cxgbi_endpoint *cep;
+ struct cxgbi_hba *chba;
+ struct Scsi_Host *shost;
+ struct iscsi_cls_session *cls_session;
+ struct iscsi_session *session;
+
+ if (!ep) {
+ pr_err("missing endpoint.\n");
+ return NULL;
+ }
+
+ cep = ep->dd_data;
+ chba = cep->chba;
+ shost = chba->shost;
+
+ BUG_ON(chba != iscsi_host_priv(shost));
+
+ cls_session = iscsi_session_setup(chba->cdev->itp, shost,
+ cmds_max, 0,
+ sizeof(struct iscsi_tcp_task) +
+ sizeof(struct cxgbi_task_data),
+ initial_cmdsn, ISCSI_MAX_TARGET);
+ if (!cls_session)
+ return NULL;
+
+ session = cls_session->dd_data;
+ if (iscsi_tcp_r2tpool_alloc(session))
+ goto remove_session;
+
+ log_debug(1 << CXGBI_DBG_ISCSI,
+ "ep 0x%p, cls sess 0x%p.\n", ep, cls_session);
+ return cls_session;
+
+remove_session:
+ iscsi_session_teardown(cls_session);
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(cxgbi_create_session);
+
+void cxgbi_destroy_session(struct iscsi_cls_session *cls_session)
+{
+ log_debug(1 << CXGBI_DBG_ISCSI,
+ "cls sess 0x%p.\n", cls_session);
+
+ iscsi_tcp_r2tpool_free(cls_session->dd_data);
+ iscsi_session_teardown(cls_session);
+}
+EXPORT_SYMBOL_GPL(cxgbi_destroy_session);
+
+int cxgbi_set_host_param(struct Scsi_Host *shost, enum iscsi_host_param param,
+ char *buf, int buflen)
+{
+ struct cxgbi_hba *chba = iscsi_host_priv(shost);
+
+ if (!chba->ndev) {
+ shost_printk(KERN_ERR, shost, "Could not get host param. "
+ "netdev for host not set.\n");
+ return -ENODEV;
+ }
+
+ log_debug(1 << CXGBI_DBG_ISCSI,
+ "shost 0x%p, hba 0x%p,%s, param %d, buf(%d) %s.\n",
+ shost, chba, chba->ndev->name, param, buflen, buf);
+
+ switch (param) {
+ case ISCSI_HOST_PARAM_IPADDRESS:
+ {
+ __be32 addr = in_aton(buf);
+ log_debug(1 << CXGBI_DBG_ISCSI,
+ "hba %s, req. ipv4 %pI4.\n", chba->ndev->name, &addr);
+ cxgbi_set_iscsi_ipv4(chba, addr);
+ return 0;
+ }
+ case ISCSI_HOST_PARAM_HWADDRESS:
+ case ISCSI_HOST_PARAM_NETDEV_NAME:
+ return 0;
+ default:
+ return iscsi_host_set_param(shost, param, buf, buflen);
+ }
+}
+EXPORT_SYMBOL_GPL(cxgbi_set_host_param);
+
+int cxgbi_get_host_param(struct Scsi_Host *shost, enum iscsi_host_param param,
+ char *buf)
+{
+ struct cxgbi_hba *chba = iscsi_host_priv(shost);
+ int len = 0;
+
+ if (!chba->ndev) {
+ shost_printk(KERN_ERR, shost, "Could not get host param. "
+ "netdev for host not set.\n");
+ return -ENODEV;
+ }
+
+ log_debug(1 << CXGBI_DBG_ISCSI,
+ "shost 0x%p, hba 0x%p,%s, param %d.\n",
+ shost, chba, chba->ndev->name, param);
+
+ switch (param) {
+ case ISCSI_HOST_PARAM_HWADDRESS:
+ len = sysfs_format_mac(buf, chba->ndev->dev_addr, 6);
+ break;
+ case ISCSI_HOST_PARAM_NETDEV_NAME:
+ len = sprintf(buf, "%s\n", chba->ndev->name);
+ break;
+ case ISCSI_HOST_PARAM_IPADDRESS:
+ {
+ __be32 addr;
+
+ addr = cxgbi_get_iscsi_ipv4(chba);
+ len = sprintf(buf, "%pI4", &addr);
+ log_debug(1 << CXGBI_DBG_ISCSI,
+ "hba %s, ipv4 %pI4.\n", chba->ndev->name, &addr);
+ break;
+ }
+ default:
+ return iscsi_host_get_param(shost, param, buf);
+ }
+
+ return len;
+}
+EXPORT_SYMBOL_GPL(cxgbi_get_host_param);
+
+struct iscsi_endpoint *cxgbi_ep_connect(struct Scsi_Host *shost,
+ struct sockaddr *dst_addr,
+ int non_blocking)
+{
+ struct iscsi_endpoint *ep;
+ struct cxgbi_endpoint *cep;
+ struct cxgbi_hba *hba = NULL;
+ struct cxgbi_sock *csk;
+ int err = -EINVAL;
+
+ log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_SOCK,
+ "shost 0x%p, non_blocking %d, dst_addr 0x%p.\n",
+ shost, non_blocking, dst_addr);
+
+ if (shost) {
+ hba = iscsi_host_priv(shost);
+ if (!hba) {
+ pr_info("shost 0x%p, priv NULL.\n", shost);
+ goto err_out;
+ }
+ }
+
+ csk = cxgbi_check_route(dst_addr);
+ if (IS_ERR(csk))
+ return (struct iscsi_endpoint *)csk;
+ cxgbi_sock_get(csk);
+
+ if (!hba)
+ hba = csk->cdev->hbas[csk->port_id];
+ else if (hba != csk->cdev->hbas[csk->port_id]) {
+ pr_info("Could not connect through requested host %u"
+ "hba 0x%p != 0x%p (%u).\n",
+ shost->host_no, hba,
+ csk->cdev->hbas[csk->port_id], csk->port_id);
+ err = -ENOSPC;
+ goto release_conn;
+ }
+
+ err = sock_get_port(csk);
+ if (err)
+ goto release_conn;
+
+ cxgbi_sock_set_state(csk, CTP_CONNECTING);
+ err = csk->cdev->csk_init_act_open(csk);
+ if (err)
+ goto release_conn;
+
+ if (cxgbi_sock_is_closing(csk)) {
+ err = -ENOSPC;
+ pr_info("csk 0x%p is closing.\n", csk);
+ goto release_conn;
+ }
+
+ ep = iscsi_create_endpoint(sizeof(*cep));
+ if (!ep) {
+ err = -ENOMEM;
+ pr_info("iscsi alloc ep, OOM.\n");
+ goto release_conn;
+ }
+
+ cep = ep->dd_data;
+ cep->csk = csk;
+ cep->chba = hba;
+
+ log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_SOCK,
+ "ep 0x%p, cep 0x%p, csk 0x%p, hba 0x%p,%s.\n",
+ ep, cep, csk, hba, hba->ndev->name);
+ return ep;
+
+release_conn:
+ cxgbi_sock_put(csk);
+ cxgbi_sock_closed(csk);
+err_out:
+ return ERR_PTR(err);
+}
+EXPORT_SYMBOL_GPL(cxgbi_ep_connect);
+
+int cxgbi_ep_poll(struct iscsi_endpoint *ep, int timeout_ms)
+{
+ struct cxgbi_endpoint *cep = ep->dd_data;
+ struct cxgbi_sock *csk = cep->csk;
+
+ if (!cxgbi_sock_is_established(csk))
+ return 0;
+ return 1;
+}
+EXPORT_SYMBOL_GPL(cxgbi_ep_poll);
+
+void cxgbi_ep_disconnect(struct iscsi_endpoint *ep)
+{
+ struct cxgbi_endpoint *cep = ep->dd_data;
+ struct cxgbi_conn *cconn = cep->cconn;
+ struct cxgbi_sock *csk = cep->csk;
+
+ log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_SOCK,
+ "ep 0x%p, cep 0x%p, cconn 0x%p, csk 0x%p,%u,0x%lx.\n",
+ ep, cep, cconn, csk, csk->state, csk->flags);
+
+ if (cconn && cconn->iconn) {
+ iscsi_suspend_tx(cconn->iconn);
+ write_lock_bh(&csk->callback_lock);
+ cep->csk->user_data = NULL;
+ cconn->cep = NULL;
+ write_unlock_bh(&csk->callback_lock);
+ }
+ iscsi_destroy_endpoint(ep);
+
+ if (likely(csk->state >= CTP_ESTABLISHED))
+ need_active_close(csk);
+ else
+ cxgbi_sock_closed(csk);
+
+ cxgbi_sock_put(csk);
+}
+EXPORT_SYMBOL_GPL(cxgbi_ep_disconnect);
+
+int cxgbi_iscsi_init(struct iscsi_transport *itp,
+ struct scsi_transport_template **stt)
+{
+ *stt = iscsi_register_transport(itp);
+ if (*stt == NULL) {
+ pr_err("unable to register %s transport 0x%p.\n",
+ itp->name, itp);
+ return -ENODEV;
+ }
+ log_debug(1 << CXGBI_DBG_ISCSI,
+ "%s, registered iscsi transport 0x%p.\n",
+ itp->name, stt);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cxgbi_iscsi_init);
+
+void cxgbi_iscsi_cleanup(struct iscsi_transport *itp,
+ struct scsi_transport_template **stt)
+{
+ if (*stt) {
+ log_debug(1 << CXGBI_DBG_ISCSI,
+ "de-register transport 0x%p, %s, stt 0x%p.\n",
+ itp, itp->name, *stt);
+ *stt = NULL;
+ iscsi_unregister_transport(itp);
+ }
+}
+EXPORT_SYMBOL_GPL(cxgbi_iscsi_cleanup);
+
+static int __init libcxgbi_init_module(void)
+{
+ sw_tag_idx_bits = (__ilog2_u32(ISCSI_ITT_MASK)) + 1;
+ sw_tag_age_bits = (__ilog2_u32(ISCSI_AGE_MASK)) + 1;
+
+ pr_info("tag itt 0x%x, %u bits, age 0x%x, %u bits.\n",
+ ISCSI_ITT_MASK, sw_tag_idx_bits,
+ ISCSI_AGE_MASK, sw_tag_age_bits);
+
+ ddp_setup_host_page_size();
+ return 0;
+}
+
+static void __exit libcxgbi_exit_module(void)
+{
+ cxgbi_device_unregister_all(0xFF);
+ return;
+}
+
+module_init(libcxgbi_init_module);
+module_exit(libcxgbi_exit_module);
diff --git a/drivers/scsi/cxgbi/libcxgbi.h b/drivers/scsi/cxgbi/libcxgbi.h
new file mode 100644
index 000000000000..c57d59db000c
--- /dev/null
+++ b/drivers/scsi/cxgbi/libcxgbi.h
@@ -0,0 +1,745 @@
+/*
+ * libcxgbi.h: Chelsio common library for T3/T4 iSCSI driver.
+ *
+ * Copyright (c) 2010 Chelsio Communications, 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.
+ *
+ * Written by: Karen Xie (kxie@chelsio.com)
+ * Written by: Rakesh Ranjan (rranjan@chelsio.com)
+ */
+
+#ifndef __LIBCXGBI_H__
+#define __LIBCXGBI_H__
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/debugfs.h>
+#include <linux/list.h>
+#include <linux/netdevice.h>
+#include <linux/if_vlan.h>
+#include <linux/scatterlist.h>
+#include <linux/skbuff.h>
+#include <linux/vmalloc.h>
+#include <scsi/scsi_device.h>
+#include <scsi/libiscsi_tcp.h>
+
+enum cxgbi_dbg_flag {
+ CXGBI_DBG_ISCSI,
+ CXGBI_DBG_DDP,
+ CXGBI_DBG_TOE,
+ CXGBI_DBG_SOCK,
+
+ CXGBI_DBG_PDU_TX,
+ CXGBI_DBG_PDU_RX,
+ CXGBI_DBG_DEV,
+};
+
+#define log_debug(level, fmt, ...) \
+ do { \
+ if (dbg_level & (level)) \
+ pr_info(fmt, ##__VA_ARGS__); \
+ } while (0)
+
+/* max. connections per adapter */
+#define CXGBI_MAX_CONN 16384
+
+/* always allocate rooms for AHS */
+#define SKB_TX_ISCSI_PDU_HEADER_MAX \
+ (sizeof(struct iscsi_hdr) + ISCSI_MAX_AHS_SIZE)
+
+#define ISCSI_PDU_NONPAYLOAD_LEN 312 /* bhs(48) + ahs(256) + digest(8)*/
+
+/*
+ * align pdu size to multiple of 512 for better performance
+ */
+#define cxgbi_align_pdu_size(n) do { n = (n) & (~511); } while (0)
+
+#define ULP2_MODE_ISCSI 2
+
+#define ULP2_MAX_PKT_SIZE 16224
+#define ULP2_MAX_PDU_PAYLOAD \
+ (ULP2_MAX_PKT_SIZE - ISCSI_PDU_NONPAYLOAD_LEN)
+
+/*
+ * For iscsi connections HW may inserts digest bytes into the pdu. Those digest
+ * bytes are not sent by the host but are part of the TCP payload and therefore
+ * consume TCP sequence space.
+ */
+static const unsigned int ulp2_extra_len[] = { 0, 4, 4, 8 };
+static inline unsigned int cxgbi_ulp_extra_len(int submode)
+{
+ return ulp2_extra_len[submode & 3];
+}
+
+/*
+ * struct pagepod_hdr, pagepod - pagepod format
+ */
+
+#define CPL_RX_DDP_STATUS_DDP_SHIFT 16 /* ddp'able */
+#define CPL_RX_DDP_STATUS_PAD_SHIFT 19 /* pad error */
+#define CPL_RX_DDP_STATUS_HCRC_SHIFT 20 /* hcrc error */
+#define CPL_RX_DDP_STATUS_DCRC_SHIFT 21 /* dcrc error */
+
+struct cxgbi_pagepod_hdr {
+ u32 vld_tid;
+ u32 pgsz_tag_clr;
+ u32 max_offset;
+ u32 page_offset;
+ u64 rsvd;
+};
+
+#define PPOD_PAGES_MAX 4
+struct cxgbi_pagepod {
+ struct cxgbi_pagepod_hdr hdr;
+ u64 addr[PPOD_PAGES_MAX + 1];
+};
+
+struct cxgbi_tag_format {
+ unsigned char sw_bits;
+ unsigned char rsvd_bits;
+ unsigned char rsvd_shift;
+ unsigned char filler[1];
+ u32 rsvd_mask;
+};
+
+struct cxgbi_gather_list {
+ unsigned int tag;
+ unsigned int length;
+ unsigned int offset;
+ unsigned int nelem;
+ struct page **pages;
+ dma_addr_t phys_addr[0];
+};
+
+struct cxgbi_ddp_info {
+ struct kref refcnt;
+ struct cxgbi_device *cdev;
+ struct pci_dev *pdev;
+ unsigned int max_txsz;
+ unsigned int max_rxsz;
+ unsigned int llimit;
+ unsigned int ulimit;
+ unsigned int nppods;
+ unsigned int idx_last;
+ unsigned char idx_bits;
+ unsigned char filler[3];
+ unsigned int idx_mask;
+ unsigned int rsvd_tag_mask;
+ spinlock_t map_lock;
+ struct cxgbi_gather_list **gl_map;
+ struct sk_buff **gl_skb;
+};
+
+#define DDP_PGIDX_MAX 4
+#define DDP_THRESHOLD 2048
+
+#define PPOD_PAGES_SHIFT 2 /* 4 pages per pod */
+
+#define PPOD_SIZE sizeof(struct cxgbi_pagepod) /* 64 */
+#define PPOD_SIZE_SHIFT 6
+
+#define ULPMEM_DSGL_MAX_NPPODS 16 /* 1024/PPOD_SIZE */
+#define ULPMEM_IDATA_MAX_NPPODS 4 /* 256/PPOD_SIZE */
+#define PCIE_MEMWIN_MAX_NPPODS 16 /* 1024/PPOD_SIZE */
+
+#define PPOD_COLOR_SHIFT 0
+#define PPOD_COLOR(x) ((x) << PPOD_COLOR_SHIFT)
+
+#define PPOD_IDX_SHIFT 6
+#define PPOD_IDX_MAX_SIZE 24
+
+#define PPOD_TID_SHIFT 0
+#define PPOD_TID(x) ((x) << PPOD_TID_SHIFT)
+
+#define PPOD_TAG_SHIFT 6
+#define PPOD_TAG(x) ((x) << PPOD_TAG_SHIFT)
+
+#define PPOD_VALID_SHIFT 24
+#define PPOD_VALID(x) ((x) << PPOD_VALID_SHIFT)
+#define PPOD_VALID_FLAG PPOD_VALID(1U)
+
+/*
+ * sge_opaque_hdr -
+ * Opaque version of structure the SGE stores at skb->head of TX_DATA packets
+ * and for which we must reserve space.
+ */
+struct sge_opaque_hdr {
+ void *dev;
+ dma_addr_t addr[MAX_SKB_FRAGS + 1];
+};
+
+struct cxgbi_sock {
+ struct cxgbi_device *cdev;
+
+ int tid;
+ int atid;
+ unsigned long flags;
+ unsigned int mtu;
+ unsigned short rss_qid;
+ unsigned short txq_idx;
+ unsigned short advmss;
+ unsigned int tx_chan;
+ unsigned int rx_chan;
+ unsigned int mss_idx;
+ unsigned int smac_idx;
+ unsigned char port_id;
+ int wr_max_cred;
+ int wr_cred;
+ int wr_una_cred;
+ unsigned char hcrc_len;
+ unsigned char dcrc_len;
+
+ void *l2t;
+ struct sk_buff *wr_pending_head;
+ struct sk_buff *wr_pending_tail;
+ struct sk_buff *cpl_close;
+ struct sk_buff *cpl_abort_req;
+ struct sk_buff *cpl_abort_rpl;
+ struct sk_buff *skb_ulp_lhdr;
+ spinlock_t lock;
+ struct kref refcnt;
+ unsigned int state;
+ struct sockaddr_in saddr;
+ struct sockaddr_in daddr;
+ struct dst_entry *dst;
+ struct sk_buff_head receive_queue;
+ struct sk_buff_head write_queue;
+ struct timer_list retry_timer;
+ int err;
+ rwlock_t callback_lock;
+ void *user_data;
+
+ u32 rcv_nxt;
+ u32 copied_seq;
+ u32 rcv_wup;
+ u32 snd_nxt;
+ u32 snd_una;
+ u32 write_seq;
+};
+
+/*
+ * connection states
+ */
+enum cxgbi_sock_states{
+ CTP_CLOSED,
+ CTP_CONNECTING,
+ CTP_ACTIVE_OPEN,
+ CTP_ESTABLISHED,
+ CTP_ACTIVE_CLOSE,
+ CTP_PASSIVE_CLOSE,
+ CTP_CLOSE_WAIT_1,
+ CTP_CLOSE_WAIT_2,
+ CTP_ABORTING,
+};
+
+/*
+ * Connection flags -- many to track some close related events.
+ */
+enum cxgbi_sock_flags {
+ CTPF_ABORT_RPL_RCVD, /*received one ABORT_RPL_RSS message */
+ CTPF_ABORT_REQ_RCVD, /*received one ABORT_REQ_RSS message */
+ CTPF_ABORT_RPL_PENDING, /* expecting an abort reply */
+ CTPF_TX_DATA_SENT, /* already sent a TX_DATA WR */
+ CTPF_ACTIVE_CLOSE_NEEDED,/* need to be closed */
+ CTPF_HAS_ATID, /* reserved atid */
+ CTPF_HAS_TID, /* reserved hw tid */
+ CTPF_OFFLOAD_DOWN, /* offload function off */
+};
+
+struct cxgbi_skb_rx_cb {
+ __u32 ddigest;
+ __u32 pdulen;
+};
+
+struct cxgbi_skb_tx_cb {
+ void *l2t;
+ struct sk_buff *wr_next;
+};
+
+enum cxgbi_skcb_flags {
+ SKCBF_TX_NEED_HDR, /* packet needs a header */
+ SKCBF_RX_COALESCED, /* received whole pdu */
+ SKCBF_RX_HDR, /* recieved pdu header */
+ SKCBF_RX_DATA, /* recieved pdu payload */
+ SKCBF_RX_STATUS, /* recieved ddp status */
+ SKCBF_RX_DATA_DDPD, /* pdu payload ddp'd */
+ SKCBF_RX_HCRC_ERR, /* header digest error */
+ SKCBF_RX_DCRC_ERR, /* data digest error */
+ SKCBF_RX_PAD_ERR, /* padding byte error */
+};
+
+struct cxgbi_skb_cb {
+ unsigned char ulp_mode;
+ unsigned long flags;
+ unsigned int seq;
+ union {
+ struct cxgbi_skb_rx_cb rx;
+ struct cxgbi_skb_tx_cb tx;
+ };
+};
+
+#define CXGBI_SKB_CB(skb) ((struct cxgbi_skb_cb *)&((skb)->cb[0]))
+#define cxgbi_skcb_flags(skb) (CXGBI_SKB_CB(skb)->flags)
+#define cxgbi_skcb_ulp_mode(skb) (CXGBI_SKB_CB(skb)->ulp_mode)
+#define cxgbi_skcb_tcp_seq(skb) (CXGBI_SKB_CB(skb)->seq)
+#define cxgbi_skcb_rx_ddigest(skb) (CXGBI_SKB_CB(skb)->rx.ddigest)
+#define cxgbi_skcb_rx_pdulen(skb) (CXGBI_SKB_CB(skb)->rx.pdulen)
+#define cxgbi_skcb_tx_wr_next(skb) (CXGBI_SKB_CB(skb)->tx.wr_next)
+
+static inline void cxgbi_skcb_set_flag(struct sk_buff *skb,
+ enum cxgbi_skcb_flags flag)
+{
+ __set_bit(flag, &(cxgbi_skcb_flags(skb)));
+}
+
+static inline void cxgbi_skcb_clear_flag(struct sk_buff *skb,
+ enum cxgbi_skcb_flags flag)
+{
+ __clear_bit(flag, &(cxgbi_skcb_flags(skb)));
+}
+
+static inline int cxgbi_skcb_test_flag(struct sk_buff *skb,
+ enum cxgbi_skcb_flags flag)
+{
+ return test_bit(flag, &(cxgbi_skcb_flags(skb)));
+}
+
+static inline void cxgbi_sock_set_flag(struct cxgbi_sock *csk,
+ enum cxgbi_sock_flags flag)
+{
+ __set_bit(flag, &csk->flags);
+ log_debug(1 << CXGBI_DBG_SOCK,
+ "csk 0x%p,%u,0x%lx, bit %d.\n",
+ csk, csk->state, csk->flags, flag);
+}
+
+static inline void cxgbi_sock_clear_flag(struct cxgbi_sock *csk,
+ enum cxgbi_sock_flags flag)
+{
+ __clear_bit(flag, &csk->flags);
+ log_debug(1 << CXGBI_DBG_SOCK,
+ "csk 0x%p,%u,0x%lx, bit %d.\n",
+ csk, csk->state, csk->flags, flag);
+}
+
+static inline int cxgbi_sock_flag(struct cxgbi_sock *csk,
+ enum cxgbi_sock_flags flag)
+{
+ if (csk == NULL)
+ return 0;
+ return test_bit(flag, &csk->flags);
+}
+
+static inline void cxgbi_sock_set_state(struct cxgbi_sock *csk, int state)
+{
+ log_debug(1 << CXGBI_DBG_SOCK,
+ "csk 0x%p,%u,0x%lx, state -> %u.\n",
+ csk, csk->state, csk->flags, state);
+ csk->state = state;
+}
+
+static inline void cxgbi_sock_free(struct kref *kref)
+{
+ struct cxgbi_sock *csk = container_of(kref,
+ struct cxgbi_sock,
+ refcnt);
+ if (csk) {
+ log_debug(1 << CXGBI_DBG_SOCK,
+ "free csk 0x%p, state %u, flags 0x%lx\n",
+ csk, csk->state, csk->flags);
+ kfree(csk);
+ }
+}
+
+static inline void __cxgbi_sock_put(const char *fn, struct cxgbi_sock *csk)
+{
+ log_debug(1 << CXGBI_DBG_SOCK,
+ "%s, put csk 0x%p, ref %u-1.\n",
+ fn, csk, atomic_read(&csk->refcnt.refcount));
+ kref_put(&csk->refcnt, cxgbi_sock_free);
+}
+#define cxgbi_sock_put(csk) __cxgbi_sock_put(__func__, csk)
+
+static inline void __cxgbi_sock_get(const char *fn, struct cxgbi_sock *csk)
+{
+ log_debug(1 << CXGBI_DBG_SOCK,
+ "%s, get csk 0x%p, ref %u+1.\n",
+ fn, csk, atomic_read(&csk->refcnt.refcount));
+ kref_get(&csk->refcnt);
+}
+#define cxgbi_sock_get(csk) __cxgbi_sock_get(__func__, csk)
+
+static inline int cxgbi_sock_is_closing(struct cxgbi_sock *csk)
+{
+ return csk->state >= CTP_ACTIVE_CLOSE;
+}
+
+static inline int cxgbi_sock_is_established(struct cxgbi_sock *csk)
+{
+ return csk->state == CTP_ESTABLISHED;
+}
+
+static inline void cxgbi_sock_purge_write_queue(struct cxgbi_sock *csk)
+{
+ struct sk_buff *skb;
+
+ while ((skb = __skb_dequeue(&csk->write_queue)))
+ __kfree_skb(skb);
+}
+
+static inline unsigned int cxgbi_sock_compute_wscale(unsigned int win)
+{
+ unsigned int wscale = 0;
+
+ while (wscale < 14 && (65535 << wscale) < win)
+ wscale++;
+ return wscale;
+}
+
+static inline struct sk_buff *alloc_wr(int wrlen, int dlen, gfp_t gfp)
+{
+ struct sk_buff *skb = alloc_skb(wrlen + dlen, gfp);
+
+ if (skb) {
+ __skb_put(skb, wrlen);
+ memset(skb->head, 0, wrlen + dlen);
+ } else
+ pr_info("alloc cpl wr skb %u+%u, OOM.\n", wrlen, dlen);
+ return skb;
+}
+
+
+/*
+ * The number of WRs needed for an skb depends on the number of fragments
+ * in the skb and whether it has any payload in its main body. This maps the
+ * length of the gather list represented by an skb into the # of necessary WRs.
+ * The extra two fragments are for iscsi bhs and payload padding.
+ */
+#define SKB_WR_LIST_SIZE (MAX_SKB_FRAGS + 2)
+
+static inline void cxgbi_sock_reset_wr_list(struct cxgbi_sock *csk)
+{
+ csk->wr_pending_head = csk->wr_pending_tail = NULL;
+}
+
+static inline void cxgbi_sock_enqueue_wr(struct cxgbi_sock *csk,
+ struct sk_buff *skb)
+{
+ cxgbi_skcb_tx_wr_next(skb) = NULL;
+ /*
+ * We want to take an extra reference since both us and the driver
+ * need to free the packet before it's really freed. We know there's
+ * just one user currently so we use atomic_set rather than skb_get
+ * to avoid the atomic op.
+ */
+ atomic_set(&skb->users, 2);
+
+ if (!csk->wr_pending_head)
+ csk->wr_pending_head = skb;
+ else
+ cxgbi_skcb_tx_wr_next(csk->wr_pending_tail) = skb;
+ csk->wr_pending_tail = skb;
+}
+
+static inline int cxgbi_sock_count_pending_wrs(const struct cxgbi_sock *csk)
+{
+ int n = 0;
+ const struct sk_buff *skb = csk->wr_pending_head;
+
+ while (skb) {
+ n += skb->csum;
+ skb = cxgbi_skcb_tx_wr_next(skb);
+ }
+ return n;
+}
+
+static inline struct sk_buff *cxgbi_sock_peek_wr(const struct cxgbi_sock *csk)
+{
+ return csk->wr_pending_head;
+}
+
+static inline struct sk_buff *cxgbi_sock_dequeue_wr(struct cxgbi_sock *csk)
+{
+ struct sk_buff *skb = csk->wr_pending_head;
+
+ if (likely(skb)) {
+ csk->wr_pending_head = cxgbi_skcb_tx_wr_next(skb);
+ cxgbi_skcb_tx_wr_next(skb) = NULL;
+ }
+ return skb;
+}
+
+void cxgbi_sock_check_wr_invariants(const struct cxgbi_sock *);
+void cxgbi_sock_purge_wr_queue(struct cxgbi_sock *);
+void cxgbi_sock_skb_entail(struct cxgbi_sock *, struct sk_buff *);
+void cxgbi_sock_fail_act_open(struct cxgbi_sock *, int);
+void cxgbi_sock_act_open_req_arp_failure(void *, struct sk_buff *);
+void cxgbi_sock_closed(struct cxgbi_sock *);
+void cxgbi_sock_established(struct cxgbi_sock *, unsigned int, unsigned int);
+void cxgbi_sock_rcv_abort_rpl(struct cxgbi_sock *);
+void cxgbi_sock_rcv_peer_close(struct cxgbi_sock *);
+void cxgbi_sock_rcv_close_conn_rpl(struct cxgbi_sock *, u32);
+void cxgbi_sock_rcv_wr_ack(struct cxgbi_sock *, unsigned int, unsigned int,
+ int);
+unsigned int cxgbi_sock_select_mss(struct cxgbi_sock *, unsigned int);
+void cxgbi_sock_free_cpl_skbs(struct cxgbi_sock *);
+
+struct cxgbi_hba {
+ struct net_device *ndev;
+ struct net_device *vdev; /* vlan dev */
+ struct Scsi_Host *shost;
+ struct cxgbi_device *cdev;
+ __be32 ipv4addr;
+ unsigned char port_id;
+};
+
+struct cxgbi_ports_map {
+ unsigned int max_connect;
+ unsigned int used;
+ unsigned short sport_base;
+ spinlock_t lock;
+ unsigned int next;
+ struct cxgbi_sock **port_csk;
+};
+
+#define CXGBI_FLAG_DEV_T3 0x1
+#define CXGBI_FLAG_DEV_T4 0x2
+#define CXGBI_FLAG_ADAPTER_RESET 0x4
+#define CXGBI_FLAG_IPV4_SET 0x10
+struct cxgbi_device {
+ struct list_head list_head;
+ unsigned int flags;
+ struct net_device **ports;
+ void *lldev;
+ struct cxgbi_hba **hbas;
+ const unsigned short *mtus;
+ unsigned char nmtus;
+ unsigned char nports;
+ struct pci_dev *pdev;
+ struct dentry *debugfs_root;
+ struct iscsi_transport *itp;
+
+ unsigned int pfvf;
+ unsigned int snd_win;
+ unsigned int rcv_win;
+ unsigned int rx_credit_thres;
+ unsigned int skb_tx_rsvd;
+ unsigned int skb_rx_extra; /* for msg coalesced mode */
+ unsigned int tx_max_size;
+ unsigned int rx_max_size;
+ struct cxgbi_ports_map pmap;
+ struct cxgbi_tag_format tag_format;
+ struct cxgbi_ddp_info *ddp;
+
+ void (*dev_ddp_cleanup)(struct cxgbi_device *);
+ void (*csk_ddp_free_gl_skb)(struct cxgbi_ddp_info *, int, int);
+ int (*csk_ddp_alloc_gl_skb)(struct cxgbi_ddp_info *, int, int, gfp_t);
+ int (*csk_ddp_set)(struct cxgbi_sock *, struct cxgbi_pagepod_hdr *,
+ unsigned int, unsigned int,
+ struct cxgbi_gather_list *);
+ void (*csk_ddp_clear)(struct cxgbi_hba *,
+ unsigned int, unsigned int, unsigned int);
+ int (*csk_ddp_setup_digest)(struct cxgbi_sock *,
+ unsigned int, int, int, int);
+ int (*csk_ddp_setup_pgidx)(struct cxgbi_sock *,
+ unsigned int, int, bool);
+
+ void (*csk_release_offload_resources)(struct cxgbi_sock *);
+ int (*csk_rx_pdu_ready)(struct cxgbi_sock *, struct sk_buff *);
+ u32 (*csk_send_rx_credits)(struct cxgbi_sock *, u32);
+ int (*csk_push_tx_frames)(struct cxgbi_sock *, int);
+ void (*csk_send_abort_req)(struct cxgbi_sock *);
+ void (*csk_send_close_req)(struct cxgbi_sock *);
+ int (*csk_alloc_cpls)(struct cxgbi_sock *);
+ int (*csk_init_act_open)(struct cxgbi_sock *);
+
+ void *dd_data;
+};
+#define cxgbi_cdev_priv(cdev) ((cdev)->dd_data)
+
+struct cxgbi_conn {
+ struct cxgbi_endpoint *cep;
+ struct iscsi_conn *iconn;
+ struct cxgbi_hba *chba;
+ u32 task_idx_bits;
+};
+
+struct cxgbi_endpoint {
+ struct cxgbi_conn *cconn;
+ struct cxgbi_hba *chba;
+ struct cxgbi_sock *csk;
+};
+
+#define MAX_PDU_FRAGS ((ULP2_MAX_PDU_PAYLOAD + 512 - 1) / 512)
+struct cxgbi_task_data {
+ unsigned short nr_frags;
+ skb_frag_t frags[MAX_PDU_FRAGS];
+ struct sk_buff *skb;
+ unsigned int offset;
+ unsigned int count;
+ unsigned int sgoffset;
+};
+#define iscsi_task_cxgbi_data(task) \
+ ((task)->dd_data + sizeof(struct iscsi_tcp_task))
+
+static inline int cxgbi_is_ddp_tag(struct cxgbi_tag_format *tformat, u32 tag)
+{
+ return !(tag & (1 << (tformat->rsvd_bits + tformat->rsvd_shift - 1)));
+}
+
+static inline int cxgbi_sw_tag_usable(struct cxgbi_tag_format *tformat,
+ u32 sw_tag)
+{
+ sw_tag >>= (32 - tformat->rsvd_bits);
+ return !sw_tag;
+}
+
+static inline u32 cxgbi_set_non_ddp_tag(struct cxgbi_tag_format *tformat,
+ u32 sw_tag)
+{
+ unsigned char shift = tformat->rsvd_bits + tformat->rsvd_shift - 1;
+ u32 mask = (1 << shift) - 1;
+
+ if (sw_tag && (sw_tag & ~mask)) {
+ u32 v1 = sw_tag & ((1 << shift) - 1);
+ u32 v2 = (sw_tag >> (shift - 1)) << shift;
+
+ return v2 | v1 | 1 << shift;
+ }
+
+ return sw_tag | 1 << shift;
+}
+
+static inline u32 cxgbi_ddp_tag_base(struct cxgbi_tag_format *tformat,
+ u32 sw_tag)
+{
+ u32 mask = (1 << tformat->rsvd_shift) - 1;
+
+ if (sw_tag && (sw_tag & ~mask)) {
+ u32 v1 = sw_tag & mask;
+ u32 v2 = sw_tag >> tformat->rsvd_shift;
+
+ v2 <<= tformat->rsvd_bits + tformat->rsvd_shift;
+
+ return v2 | v1;
+ }
+
+ return sw_tag;
+}
+
+static inline u32 cxgbi_tag_rsvd_bits(struct cxgbi_tag_format *tformat,
+ u32 tag)
+{
+ if (cxgbi_is_ddp_tag(tformat, tag))
+ return (tag >> tformat->rsvd_shift) & tformat->rsvd_mask;
+
+ return 0;
+}
+
+static inline u32 cxgbi_tag_nonrsvd_bits(struct cxgbi_tag_format *tformat,
+ u32 tag)
+{
+ unsigned char shift = tformat->rsvd_bits + tformat->rsvd_shift - 1;
+ u32 v1, v2;
+
+ if (cxgbi_is_ddp_tag(tformat, tag)) {
+ v1 = tag & ((1 << tformat->rsvd_shift) - 1);
+ v2 = (tag >> (shift + 1)) << tformat->rsvd_shift;
+ } else {
+ u32 mask = (1 << shift) - 1;
+ tag &= ~(1 << shift);
+ v1 = tag & mask;
+ v2 = (tag >> 1) & ~mask;
+ }
+ return v1 | v2;
+}
+
+static inline void *cxgbi_alloc_big_mem(unsigned int size,
+ gfp_t gfp)
+{
+ void *p = kmalloc(size, gfp);
+ if (!p)
+ p = vmalloc(size);
+ if (p)
+ memset(p, 0, size);
+ return p;
+}
+
+static inline void cxgbi_free_big_mem(void *addr)
+{
+ if (is_vmalloc_addr(addr))
+ vfree(addr);
+ else
+ kfree(addr);
+}
+
+static inline void cxgbi_set_iscsi_ipv4(struct cxgbi_hba *chba, __be32 ipaddr)
+{
+ if (chba->cdev->flags & CXGBI_FLAG_IPV4_SET)
+ chba->ipv4addr = ipaddr;
+ else
+ pr_info("set iscsi ipv4 NOT supported, using %s ipv4.\n",
+ chba->ndev->name);
+}
+
+static inline __be32 cxgbi_get_iscsi_ipv4(struct cxgbi_hba *chba)
+{
+ return chba->ipv4addr;
+}
+
+struct cxgbi_device *cxgbi_device_register(unsigned int, unsigned int);
+void cxgbi_device_unregister(struct cxgbi_device *);
+void cxgbi_device_unregister_all(unsigned int flag);
+struct cxgbi_device *cxgbi_device_find_by_lldev(void *);
+int cxgbi_hbas_add(struct cxgbi_device *, unsigned int, unsigned int,
+ struct scsi_host_template *,
+ struct scsi_transport_template *);
+void cxgbi_hbas_remove(struct cxgbi_device *);
+
+int cxgbi_device_portmap_create(struct cxgbi_device *cdev, unsigned int base,
+ unsigned int max_conn);
+void cxgbi_device_portmap_cleanup(struct cxgbi_device *cdev);
+
+void cxgbi_conn_tx_open(struct cxgbi_sock *);
+void cxgbi_conn_pdu_ready(struct cxgbi_sock *);
+int cxgbi_conn_alloc_pdu(struct iscsi_task *, u8);
+int cxgbi_conn_init_pdu(struct iscsi_task *, unsigned int , unsigned int);
+int cxgbi_conn_xmit_pdu(struct iscsi_task *);
+
+void cxgbi_cleanup_task(struct iscsi_task *task);
+
+void cxgbi_get_conn_stats(struct iscsi_cls_conn *, struct iscsi_stats *);
+int cxgbi_set_conn_param(struct iscsi_cls_conn *,
+ enum iscsi_param, char *, int);
+int cxgbi_get_conn_param(struct iscsi_cls_conn *, enum iscsi_param, char *);
+struct iscsi_cls_conn *cxgbi_create_conn(struct iscsi_cls_session *, u32);
+int cxgbi_bind_conn(struct iscsi_cls_session *,
+ struct iscsi_cls_conn *, u64, int);
+void cxgbi_destroy_session(struct iscsi_cls_session *);
+struct iscsi_cls_session *cxgbi_create_session(struct iscsi_endpoint *,
+ u16, u16, u32);
+int cxgbi_set_host_param(struct Scsi_Host *,
+ enum iscsi_host_param, char *, int);
+int cxgbi_get_host_param(struct Scsi_Host *, enum iscsi_host_param, char *);
+struct iscsi_endpoint *cxgbi_ep_connect(struct Scsi_Host *,
+ struct sockaddr *, int);
+int cxgbi_ep_poll(struct iscsi_endpoint *, int);
+void cxgbi_ep_disconnect(struct iscsi_endpoint *);
+
+int cxgbi_iscsi_init(struct iscsi_transport *,
+ struct scsi_transport_template **);
+void cxgbi_iscsi_cleanup(struct iscsi_transport *,
+ struct scsi_transport_template **);
+void cxgbi_parse_pdu_itt(struct iscsi_conn *, itt_t, int *, int *);
+int cxgbi_ddp_init(struct cxgbi_device *, unsigned int, unsigned int,
+ unsigned int, unsigned int);
+int cxgbi_ddp_cleanup(struct cxgbi_device *);
+void cxgbi_ddp_page_size_factor(int *);
+void cxgbi_ddp_ppod_clear(struct cxgbi_pagepod *);
+void cxgbi_ddp_ppod_set(struct cxgbi_pagepod *, struct cxgbi_pagepod_hdr *,
+ struct cxgbi_gather_list *, unsigned int);
+#endif /*__LIBCXGBI_H__*/
diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c
index 1a970a76b1b9..6b729324b8d3 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -1,7 +1,7 @@
/*
* Generic SCSI-3 ALUA SCSI Device Handler
*
- * Copyright (C) 2007, 2008 Hannes Reinecke, SUSE Linux Products GmbH.
+ * Copyright (C) 2007-2010 Hannes Reinecke, SUSE Linux Products GmbH.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -20,17 +20,19 @@
*
*/
#include <linux/slab.h>
+#include <linux/delay.h>
#include <scsi/scsi.h>
#include <scsi/scsi_eh.h>
#include <scsi/scsi_dh.h>
#define ALUA_DH_NAME "alua"
-#define ALUA_DH_VER "1.2"
+#define ALUA_DH_VER "1.3"
#define TPGS_STATE_OPTIMIZED 0x0
#define TPGS_STATE_NONOPTIMIZED 0x1
#define TPGS_STATE_STANDBY 0x2
#define TPGS_STATE_UNAVAILABLE 0x3
+#define TPGS_STATE_LBA_DEPENDENT 0x4
#define TPGS_STATE_OFFLINE 0xe
#define TPGS_STATE_TRANSITIONING 0xf
@@ -39,6 +41,7 @@
#define TPGS_SUPPORT_NONOPTIMIZED 0x02
#define TPGS_SUPPORT_STANDBY 0x04
#define TPGS_SUPPORT_UNAVAILABLE 0x08
+#define TPGS_SUPPORT_LBA_DEPENDENT 0x10
#define TPGS_SUPPORT_OFFLINE 0x40
#define TPGS_SUPPORT_TRANSITION 0x80
@@ -460,6 +463,8 @@ static char print_alua_state(int state)
return 'S';
case TPGS_STATE_UNAVAILABLE:
return 'U';
+ case TPGS_STATE_LBA_DEPENDENT:
+ return 'L';
case TPGS_STATE_OFFLINE:
return 'O';
case TPGS_STATE_TRANSITIONING:
@@ -542,7 +547,9 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h)
int len, k, off, valid_states = 0;
char *ucp;
unsigned err;
+ unsigned long expiry, interval = 10;
+ expiry = round_jiffies_up(jiffies + ALUA_FAILOVER_TIMEOUT);
retry:
err = submit_rtpg(sdev, h);
@@ -553,7 +560,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h)
return SCSI_DH_IO;
err = alua_check_sense(sdev, &sense_hdr);
- if (err == ADD_TO_MLQUEUE)
+ if (err == ADD_TO_MLQUEUE && time_before(jiffies, expiry))
goto retry;
sdev_printk(KERN_INFO, sdev,
"%s: rtpg sense code %02x/%02x/%02x\n",
@@ -587,38 +594,37 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h)
}
sdev_printk(KERN_INFO, sdev,
- "%s: port group %02x state %c supports %c%c%c%c%c%c\n",
+ "%s: port group %02x state %c supports %c%c%c%c%c%c%c\n",
ALUA_DH_NAME, h->group_id, print_alua_state(h->state),
valid_states&TPGS_SUPPORT_TRANSITION?'T':'t',
valid_states&TPGS_SUPPORT_OFFLINE?'O':'o',
+ valid_states&TPGS_SUPPORT_LBA_DEPENDENT?'L':'l',
valid_states&TPGS_SUPPORT_UNAVAILABLE?'U':'u',
valid_states&TPGS_SUPPORT_STANDBY?'S':'s',
valid_states&TPGS_SUPPORT_NONOPTIMIZED?'N':'n',
valid_states&TPGS_SUPPORT_OPTIMIZED?'A':'a');
- if (h->tpgs & TPGS_MODE_EXPLICIT) {
- switch (h->state) {
- case TPGS_STATE_TRANSITIONING:
+ switch (h->state) {
+ case TPGS_STATE_TRANSITIONING:
+ if (time_before(jiffies, expiry)) {
/* State transition, retry */
+ interval *= 10;
+ msleep(interval);
goto retry;
- break;
- case TPGS_STATE_OFFLINE:
- /* Path is offline, fail */
- err = SCSI_DH_DEV_OFFLINED;
- break;
- default:
- break;
}
- } else {
- /* Only Implicit ALUA support */
- if (h->state == TPGS_STATE_OPTIMIZED ||
- h->state == TPGS_STATE_NONOPTIMIZED ||
- h->state == TPGS_STATE_STANDBY)
- /* Useable path if active */
- err = SCSI_DH_OK;
- else
- /* Path unuseable for unavailable/offline */
- err = SCSI_DH_DEV_OFFLINED;
+ /* Transitioning time exceeded, set port to standby */
+ err = SCSI_DH_RETRY;
+ h->state = TPGS_STATE_STANDBY;
+ break;
+ case TPGS_STATE_OFFLINE:
+ case TPGS_STATE_UNAVAILABLE:
+ /* Path unuseable for unavailable/offline */
+ err = SCSI_DH_DEV_OFFLINED;
+ break;
+ default:
+ /* Useable path if active */
+ err = SCSI_DH_OK;
+ break;
}
return err;
}
@@ -672,7 +678,9 @@ static int alua_activate(struct scsi_device *sdev,
goto out;
}
- if (h->tpgs & TPGS_MODE_EXPLICIT && h->state != TPGS_STATE_OPTIMIZED) {
+ if (h->tpgs & TPGS_MODE_EXPLICIT &&
+ h->state != TPGS_STATE_OPTIMIZED &&
+ h->state != TPGS_STATE_LBA_DEPENDENT) {
h->callback_fn = fn;
h->callback_data = data;
err = submit_stpg(h);
@@ -698,8 +706,11 @@ static int alua_prep_fn(struct scsi_device *sdev, struct request *req)
struct alua_dh_data *h = get_alua_data(sdev);
int ret = BLKPREP_OK;
- if (h->state != TPGS_STATE_OPTIMIZED &&
- h->state != TPGS_STATE_NONOPTIMIZED) {
+ if (h->state == TPGS_STATE_TRANSITIONING)
+ ret = BLKPREP_DEFER;
+ else if (h->state != TPGS_STATE_OPTIMIZED &&
+ h->state != TPGS_STATE_NONOPTIMIZED &&
+ h->state != TPGS_STATE_LBA_DEPENDENT) {
ret = BLKPREP_KILL;
req->cmd_flags |= REQ_QUIET;
}
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index ffc1edf5e80d..23dec0063385 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -49,7 +49,6 @@ MODULE_DESCRIPTION("Adaptec I2O RAID Driver");
#include <linux/kernel.h> /* for printk */
#include <linux/sched.h>
#include <linux/reboot.h>
-#include <linux/smp_lock.h>
#include <linux/spinlock.h>
#include <linux/dma-mapping.h>
@@ -76,6 +75,7 @@ MODULE_DESCRIPTION("Adaptec I2O RAID Driver");
* Needed for our management apps
*============================================================================
*/
+static DEFINE_MUTEX(adpt_mutex);
static dpt_sig_S DPTI_sig = {
{'d', 'P', 't', 'S', 'i', 'G'}, SIG_VERSION,
#ifdef __i386__
@@ -126,6 +126,7 @@ static const struct file_operations adpt_fops = {
#ifdef CONFIG_COMPAT
.compat_ioctl = compat_adpt_ioctl,
#endif
+ .llseek = noop_llseek,
};
/* Structures and definitions for synchronous message posting.
@@ -1732,12 +1733,12 @@ static int adpt_open(struct inode *inode, struct file *file)
int minor;
adpt_hba* pHba;
- lock_kernel();
+ mutex_lock(&adpt_mutex);
//TODO check for root access
//
minor = iminor(inode);
if (minor >= hba_count) {
- unlock_kernel();
+ mutex_unlock(&adpt_mutex);
return -ENXIO;
}
mutex_lock(&adpt_configuration_lock);
@@ -1748,7 +1749,7 @@ static int adpt_open(struct inode *inode, struct file *file)
}
if (pHba == NULL) {
mutex_unlock(&adpt_configuration_lock);
- unlock_kernel();
+ mutex_unlock(&adpt_mutex);
return -ENXIO;
}
@@ -1759,7 +1760,7 @@ static int adpt_open(struct inode *inode, struct file *file)
pHba->in_use = 1;
mutex_unlock(&adpt_configuration_lock);
- unlock_kernel();
+ mutex_unlock(&adpt_mutex);
return 0;
}
@@ -2160,9 +2161,9 @@ static long adpt_unlocked_ioctl(struct file *file, uint cmd, ulong arg)
inode = file->f_dentry->d_inode;
- lock_kernel();
+ mutex_lock(&adpt_mutex);
ret = adpt_ioctl(inode, file, cmd, arg);
- unlock_kernel();
+ mutex_unlock(&adpt_mutex);
return ret;
}
@@ -2176,7 +2177,7 @@ static long compat_adpt_ioctl(struct file *file,
inode = file->f_dentry->d_inode;
- lock_kernel();
+ mutex_lock(&adpt_mutex);
switch(cmd) {
case DPT_SIGNATURE:
@@ -2194,7 +2195,7 @@ static long compat_adpt_ioctl(struct file *file,
ret = -ENOIOCTLCMD;
}
- unlock_kernel();
+ mutex_unlock(&adpt_mutex);
return ret;
}
diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c
index 9eb7a9ebccae..bb63f1a1f808 100644
--- a/drivers/scsi/fnic/fnic_main.c
+++ b/drivers/scsi/fnic/fnic_main.c
@@ -80,8 +80,6 @@ static struct libfc_function_template fnic_transport_template = {
static int fnic_slave_alloc(struct scsi_device *sdev)
{
struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
- struct fc_lport *lp = shost_priv(sdev->host);
- struct fnic *fnic = lport_priv(lp);
sdev->tagged_supported = 1;
@@ -89,8 +87,6 @@ static int fnic_slave_alloc(struct scsi_device *sdev)
return -ENXIO;
scsi_activate_tcq(sdev, FNIC_DFLT_QUEUE_DEPTH);
- rport->dev_loss_tmo = fnic->config.port_down_timeout / 1000;
-
return 0;
}
@@ -113,6 +109,15 @@ static struct scsi_host_template fnic_host_template = {
.shost_attrs = fnic_attrs,
};
+static void
+fnic_set_rport_dev_loss_tmo(struct fc_rport *rport, u32 timeout)
+{
+ if (timeout)
+ rport->dev_loss_tmo = timeout;
+ else
+ rport->dev_loss_tmo = 1;
+}
+
static void fnic_get_host_speed(struct Scsi_Host *shost);
static struct scsi_transport_template *fnic_fc_transport;
static struct fc_host_statistics *fnic_get_stats(struct Scsi_Host *);
@@ -140,6 +145,7 @@ static struct fc_function_template fnic_fc_functions = {
.show_starget_port_name = 1,
.show_starget_port_id = 1,
.show_rport_dev_loss_tmo = 1,
+ .set_rport_dev_loss_tmo = fnic_set_rport_dev_loss_tmo,
.issue_fc_host_lip = fnic_reset,
.get_fc_host_stats = fnic_get_stats,
.dd_fcrport_size = sizeof(struct fc_rport_libfc_priv),
@@ -706,6 +712,7 @@ static int __devinit fnic_probe(struct pci_dev *pdev,
goto err_out_free_exch_mgr;
}
fc_host_maxframe_size(lp->host) = lp->mfs;
+ fc_host_dev_loss_tmo(lp->host) = fnic->config.port_down_timeout / 1000;
sprintf(fc_host_symbolic_name(lp->host),
DRV_NAME " v" DRV_VERSION " over %s", fnic->name);
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index b860d650a563..5a3f93101017 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -120,7 +120,7 @@
#include <linux/timer.h>
#include <linux/dma-mapping.h>
#include <linux/list.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/slab.h>
#ifdef GDTH_RTC
@@ -140,6 +140,7 @@
#include <scsi/scsi_host.h>
#include "gdth.h"
+static DEFINE_MUTEX(gdth_mutex);
static void gdth_delay(int milliseconds);
static void gdth_eval_mapping(u32 size, u32 *cyls, int *heads, int *secs);
static irqreturn_t gdth_interrupt(int irq, void *dev_id);
@@ -372,6 +373,7 @@ static const struct file_operations gdth_fops = {
.unlocked_ioctl = gdth_unlocked_ioctl,
.open = gdth_open,
.release = gdth_close,
+ .llseek = noop_llseek,
};
#include "gdth_proc.h"
@@ -4042,12 +4044,12 @@ static int gdth_open(struct inode *inode, struct file *filep)
{
gdth_ha_str *ha;
- lock_kernel();
+ mutex_lock(&gdth_mutex);
list_for_each_entry(ha, &gdth_instances, list) {
if (!ha->sdev)
ha->sdev = scsi_get_host_dev(ha->shost);
}
- unlock_kernel();
+ mutex_unlock(&gdth_mutex);
TRACE(("gdth_open()\n"));
return 0;
@@ -4615,9 +4617,9 @@ static long gdth_unlocked_ioctl(struct file *file, unsigned int cmd,
{
int ret;
- lock_kernel();
+ mutex_lock(&gdth_mutex);
ret = gdth_ioctl(file, cmd, arg);
- unlock_kernel();
+ mutex_unlock(&gdth_mutex);
return ret;
}
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index 8a8f803439e1..4f7a5829ea4c 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -376,6 +376,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
shost->this_id = sht->this_id;
shost->can_queue = sht->can_queue;
shost->sg_tablesize = sht->sg_tablesize;
+ shost->sg_prot_tablesize = sht->sg_prot_tablesize;
shost->cmd_per_lun = sht->cmd_per_lun;
shost->unchecked_isa_dma = sht->unchecked_isa_dma;
shost->use_clustering = sht->use_clustering;
@@ -411,9 +412,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
device_initialize(&shost->shost_gendev);
dev_set_name(&shost->shost_gendev, "host%d", shost->host_no);
-#ifndef CONFIG_SYSFS_DEPRECATED
shost->shost_gendev.bus = &scsi_bus_type;
-#endif
shost->shost_gendev.type = &scsi_host_type;
device_initialize(&shost->shost_dev);
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index 9f75a6d519a2..00d08b25425f 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -50,7 +50,6 @@ static unsigned int max_lun = IBMVFC_MAX_LUN;
static unsigned int max_targets = IBMVFC_MAX_TARGETS;
static unsigned int max_requests = IBMVFC_MAX_REQUESTS_DEFAULT;
static unsigned int disc_threads = IBMVFC_MAX_DISC_THREADS;
-static unsigned int dev_loss_tmo = IBMVFC_DEV_LOSS_TMO;
static unsigned int ibmvfc_debug = IBMVFC_DEBUG;
static unsigned int log_level = IBMVFC_DEFAULT_LOG_LEVEL;
static LIST_HEAD(ibmvfc_head);
@@ -84,11 +83,6 @@ MODULE_PARM_DESC(disc_threads, "Number of device discovery threads to use. "
module_param_named(debug, ibmvfc_debug, uint, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Enable driver debug information. "
"[Default=" __stringify(IBMVFC_DEBUG) "]");
-module_param_named(dev_loss_tmo, dev_loss_tmo, uint, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(dev_loss_tmo, "Maximum number of seconds that the FC "
- "transport should insulate the loss of a remote port. Once this "
- "value is exceeded, the scsi target is removed. "
- "[Default=" __stringify(IBMVFC_DEV_LOSS_TMO) "]");
module_param_named(log_level, log_level, uint, 0);
MODULE_PARM_DESC(log_level, "Set to 0 - 4 for increasing verbosity of device driver. "
"[Default=" __stringify(IBMVFC_DEFAULT_LOG_LEVEL) "]");
@@ -2496,41 +2490,66 @@ static void ibmvfc_terminate_rport_io(struct fc_rport *rport)
LEAVE;
}
-static const struct {
- enum ibmvfc_async_event ae;
- const char *desc;
-} ae_desc [] = {
- { IBMVFC_AE_ELS_PLOGI, "PLOGI" },
- { IBMVFC_AE_ELS_LOGO, "LOGO" },
- { IBMVFC_AE_ELS_PRLO, "PRLO" },
- { IBMVFC_AE_SCN_NPORT, "N-Port SCN" },
- { IBMVFC_AE_SCN_GROUP, "Group SCN" },
- { IBMVFC_AE_SCN_DOMAIN, "Domain SCN" },
- { IBMVFC_AE_SCN_FABRIC, "Fabric SCN" },
- { IBMVFC_AE_LINK_UP, "Link Up" },
- { IBMVFC_AE_LINK_DOWN, "Link Down" },
- { IBMVFC_AE_LINK_DEAD, "Link Dead" },
- { IBMVFC_AE_HALT, "Halt" },
- { IBMVFC_AE_RESUME, "Resume" },
- { IBMVFC_AE_ADAPTER_FAILED, "Adapter Failed" },
+static const struct ibmvfc_async_desc ae_desc [] = {
+ { IBMVFC_AE_ELS_PLOGI, "PLOGI", IBMVFC_DEFAULT_LOG_LEVEL + 1 },
+ { IBMVFC_AE_ELS_LOGO, "LOGO", IBMVFC_DEFAULT_LOG_LEVEL + 1 },
+ { IBMVFC_AE_ELS_PRLO, "PRLO", IBMVFC_DEFAULT_LOG_LEVEL + 1 },
+ { IBMVFC_AE_SCN_NPORT, "N-Port SCN", IBMVFC_DEFAULT_LOG_LEVEL + 1 },
+ { IBMVFC_AE_SCN_GROUP, "Group SCN", IBMVFC_DEFAULT_LOG_LEVEL + 1 },
+ { IBMVFC_AE_SCN_DOMAIN, "Domain SCN", IBMVFC_DEFAULT_LOG_LEVEL },
+ { IBMVFC_AE_SCN_FABRIC, "Fabric SCN", IBMVFC_DEFAULT_LOG_LEVEL },
+ { IBMVFC_AE_LINK_UP, "Link Up", IBMVFC_DEFAULT_LOG_LEVEL },
+ { IBMVFC_AE_LINK_DOWN, "Link Down", IBMVFC_DEFAULT_LOG_LEVEL },
+ { IBMVFC_AE_LINK_DEAD, "Link Dead", IBMVFC_DEFAULT_LOG_LEVEL },
+ { IBMVFC_AE_HALT, "Halt", IBMVFC_DEFAULT_LOG_LEVEL },
+ { IBMVFC_AE_RESUME, "Resume", IBMVFC_DEFAULT_LOG_LEVEL },
+ { IBMVFC_AE_ADAPTER_FAILED, "Adapter Failed", IBMVFC_DEFAULT_LOG_LEVEL },
};
-static const char *unknown_ae = "Unknown async";
+static const struct ibmvfc_async_desc unknown_ae = {
+ 0, "Unknown async", IBMVFC_DEFAULT_LOG_LEVEL
+};
/**
* ibmvfc_get_ae_desc - Get text description for async event
* @ae: async event
*
**/
-static const char *ibmvfc_get_ae_desc(u64 ae)
+static const struct ibmvfc_async_desc *ibmvfc_get_ae_desc(u64 ae)
{
int i;
for (i = 0; i < ARRAY_SIZE(ae_desc); i++)
if (ae_desc[i].ae == ae)
- return ae_desc[i].desc;
+ return &ae_desc[i];
+
+ return &unknown_ae;
+}
+
+static const struct {
+ enum ibmvfc_ae_link_state state;
+ const char *desc;
+} link_desc [] = {
+ { IBMVFC_AE_LS_LINK_UP, " link up" },
+ { IBMVFC_AE_LS_LINK_BOUNCED, " link bounced" },
+ { IBMVFC_AE_LS_LINK_DOWN, " link down" },
+ { IBMVFC_AE_LS_LINK_DEAD, " link dead" },
+};
- return unknown_ae;
+/**
+ * ibmvfc_get_link_state - Get text description for link state
+ * @state: link state
+ *
+ **/
+static const char *ibmvfc_get_link_state(enum ibmvfc_ae_link_state state)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(link_desc); i++)
+ if (link_desc[i].state == state)
+ return link_desc[i].desc;
+
+ return "";
}
/**
@@ -2542,11 +2561,12 @@ static const char *ibmvfc_get_ae_desc(u64 ae)
static void ibmvfc_handle_async(struct ibmvfc_async_crq *crq,
struct ibmvfc_host *vhost)
{
- const char *desc = ibmvfc_get_ae_desc(crq->event);
+ const struct ibmvfc_async_desc *desc = ibmvfc_get_ae_desc(crq->event);
struct ibmvfc_target *tgt;
- ibmvfc_log(vhost, 3, "%s event received. scsi_id: %llx, wwpn: %llx,"
- " node_name: %llx\n", desc, crq->scsi_id, crq->wwpn, crq->node_name);
+ ibmvfc_log(vhost, desc->log_level, "%s event received. scsi_id: %llx, wwpn: %llx,"
+ " node_name: %llx%s\n", desc->desc, crq->scsi_id, crq->wwpn, crq->node_name,
+ ibmvfc_get_link_state(crq->link_state));
switch (crq->event) {
case IBMVFC_AE_RESUME:
@@ -2788,7 +2808,6 @@ static int ibmvfc_target_alloc(struct scsi_target *starget)
static int ibmvfc_slave_configure(struct scsi_device *sdev)
{
struct Scsi_Host *shost = sdev->host;
- struct fc_rport *rport = starget_to_rport(sdev->sdev_target);
unsigned long flags = 0;
spin_lock_irqsave(shost->host_lock, flags);
@@ -2800,8 +2819,6 @@ static int ibmvfc_slave_configure(struct scsi_device *sdev)
scsi_activate_tcq(sdev, sdev->queue_depth);
} else
scsi_deactivate_tcq(sdev, sdev->queue_depth);
-
- rport->dev_loss_tmo = dev_loss_tmo;
spin_unlock_irqrestore(shost->host_lock, flags);
return 0;
}
@@ -4285,8 +4302,10 @@ static void ibmvfc_do_work(struct ibmvfc_host *vhost)
spin_unlock_irqrestore(vhost->host->host_lock, flags);
rc = ibmvfc_reset_crq(vhost);
spin_lock_irqsave(vhost->host->host_lock, flags);
- if (rc || (rc = ibmvfc_send_crq_init(vhost)) ||
- (rc = vio_enable_interrupts(to_vio_dev(vhost->dev)))) {
+ if (rc == H_CLOSED)
+ vio_enable_interrupts(to_vio_dev(vhost->dev));
+ else if (rc || (rc = ibmvfc_send_crq_init(vhost)) ||
+ (rc = vio_enable_interrupts(to_vio_dev(vhost->dev)))) {
ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD);
dev_err(vhost->dev, "Error after reset (rc=%d)\n", rc);
}
@@ -4744,6 +4763,8 @@ static int ibmvfc_probe(struct vio_dev *vdev, const struct vio_device_id *id)
if ((rc = scsi_add_host(shost, dev)))
goto release_event_pool;
+ fc_host_dev_loss_tmo(shost) = IBMVFC_DEV_LOSS_TMO;
+
if ((rc = ibmvfc_create_trace_file(&shost->shost_dev.kobj,
&ibmvfc_trace_attr))) {
dev_err(dev, "Failed to create trace file. rc=%d\n", rc);
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h
index 608af394c8cf..ef663e7c9bbc 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.h
+++ b/drivers/scsi/ibmvscsi/ibmvfc.h
@@ -541,6 +541,12 @@ enum ibmvfc_async_event {
IBMVFC_AE_ADAPTER_FAILED = 0x1000,
};
+struct ibmvfc_async_desc {
+ enum ibmvfc_async_event ae;
+ const char *desc;
+ int log_level;
+};
+
struct ibmvfc_crq {
volatile u8 valid;
volatile u8 format;
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index 52568588039f..df9a12c8b373 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -1096,6 +1096,7 @@ static void ipr_init_res_entry(struct ipr_resource_entry *res,
res->bus = cfgtew->u.cfgte->res_addr.bus;
res->target = cfgtew->u.cfgte->res_addr.target;
res->lun = cfgtew->u.cfgte->res_addr.lun;
+ res->lun_wwn = get_unaligned_be64(cfgtew->u.cfgte->lun_wwn);
}
ipr_update_ata_class(res, proto);
@@ -1142,7 +1143,7 @@ static char *ipr_format_res_path(u8 *res_path, char *buffer, int len)
int i;
char *p = buffer;
- res_path[0] = '\0';
+ *p = '\0';
p += snprintf(p, buffer + len - p, "%02X", res_path[0]);
for (i = 1; res_path[i] != 0xff && ((i * 3) < len); i++)
p += snprintf(p, buffer + len - p, "-%02X", res_path[i]);
@@ -1670,7 +1671,7 @@ static void ipr_log_enhanced_array_error(struct ipr_ioa_cfg *ioa_cfg,
array_entry = error->array_member;
num_entries = min_t(u32, be32_to_cpu(error->num_entries),
- sizeof(error->array_member));
+ ARRAY_SIZE(error->array_member));
for (i = 0; i < num_entries; i++, array_entry++) {
if (!memcmp(array_entry->vpd.vpd.sn, zero_sn, IPR_SERIAL_NUM_LEN))
@@ -2151,8 +2152,8 @@ static void ipr_log_sis64_array_error(struct ipr_ioa_cfg *ioa_cfg,
ipr_err_separator;
array_entry = error->array_member;
- num_entries = min_t(u32, be32_to_cpu(error->num_entries),
- sizeof(error->array_member));
+ num_entries = min_t(u32, error->num_entries,
+ ARRAY_SIZE(error->array_member));
for (i = 0; i < num_entries; i++, array_entry++) {
@@ -2166,10 +2167,10 @@ static void ipr_log_sis64_array_error(struct ipr_ioa_cfg *ioa_cfg,
ipr_err("Array Member %d:\n", i);
ipr_log_ext_vpd(&array_entry->vpd);
- ipr_err("Current Location: %s",
+ ipr_err("Current Location: %s\n",
ipr_format_res_path(array_entry->res_path, buffer,
sizeof(buffer)));
- ipr_err("Expected Location: %s",
+ ipr_err("Expected Location: %s\n",
ipr_format_res_path(array_entry->expected_res_path,
buffer, sizeof(buffer)));
@@ -4089,6 +4090,7 @@ static int ipr_change_queue_type(struct scsi_device *sdev, int tag_type)
/**
* ipr_show_adapter_handle - Show the adapter's resource handle for this device
* @dev: device struct
+ * @attr: device attribute structure
* @buf: buffer
*
* Return value:
@@ -4122,6 +4124,7 @@ static struct device_attribute ipr_adapter_handle_attr = {
* ipr_show_resource_path - Show the resource path or the resource address for
* this device.
* @dev: device struct
+ * @attr: device attribute structure
* @buf: buffer
*
* Return value:
@@ -4159,8 +4162,45 @@ static struct device_attribute ipr_resource_path_attr = {
};
/**
+ * ipr_show_device_id - Show the device_id for this device.
+ * @dev: device struct
+ * @attr: device attribute structure
+ * @buf: buffer
+ *
+ * Return value:
+ * number of bytes printed to buffer
+ **/
+static ssize_t ipr_show_device_id(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct scsi_device *sdev = to_scsi_device(dev);
+ struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)sdev->host->hostdata;
+ struct ipr_resource_entry *res;
+ unsigned long lock_flags = 0;
+ ssize_t len = -ENXIO;
+
+ spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
+ res = (struct ipr_resource_entry *)sdev->hostdata;
+ if (res && ioa_cfg->sis64)
+ len = snprintf(buf, PAGE_SIZE, "0x%llx\n", res->dev_id);
+ else if (res)
+ len = snprintf(buf, PAGE_SIZE, "0x%llx\n", res->lun_wwn);
+
+ spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+ return len;
+}
+
+static struct device_attribute ipr_device_id_attr = {
+ .attr = {
+ .name = "device_id",
+ .mode = S_IRUGO,
+ },
+ .show = ipr_show_device_id
+};
+
+/**
* ipr_show_resource_type - Show the resource type for this device.
* @dev: device struct
+ * @attr: device attribute structure
* @buf: buffer
*
* Return value:
@@ -4195,6 +4235,7 @@ static struct device_attribute ipr_resource_type_attr = {
static struct device_attribute *ipr_dev_attrs[] = {
&ipr_adapter_handle_attr,
&ipr_resource_path_attr,
+ &ipr_device_id_attr,
&ipr_resource_type_attr,
NULL,
};
@@ -4898,39 +4939,15 @@ static int ipr_eh_abort(struct scsi_cmnd * scsi_cmd)
/**
* ipr_handle_other_interrupt - Handle "other" interrupts
* @ioa_cfg: ioa config struct
+ * @int_reg: interrupt register
*
* Return value:
* IRQ_NONE / IRQ_HANDLED
**/
-static irqreturn_t ipr_handle_other_interrupt(struct ipr_ioa_cfg *ioa_cfg)
+static irqreturn_t ipr_handle_other_interrupt(struct ipr_ioa_cfg *ioa_cfg,
+ volatile u32 int_reg)
{
irqreturn_t rc = IRQ_HANDLED;
- volatile u32 int_reg, int_mask_reg;
-
- int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg32);
- int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32) & ~int_mask_reg;
-
- /* If an interrupt on the adapter did not occur, ignore it.
- * Or in the case of SIS 64, check for a stage change interrupt.
- */
- if ((int_reg & IPR_PCII_OPER_INTERRUPTS) == 0) {
- if (ioa_cfg->sis64) {
- int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg);
- int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg;
- if (int_reg & IPR_PCII_IPL_STAGE_CHANGE) {
-
- /* clear stage change */
- writel(IPR_PCII_IPL_STAGE_CHANGE, ioa_cfg->regs.clr_interrupt_reg);
- int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg;
- list_del(&ioa_cfg->reset_cmd->queue);
- del_timer(&ioa_cfg->reset_cmd->timer);
- ipr_reset_ioa_job(ioa_cfg->reset_cmd);
- return IRQ_HANDLED;
- }
- }
-
- return IRQ_NONE;
- }
if (int_reg & IPR_PCII_IOA_TRANS_TO_OPER) {
/* Mask the interrupt */
@@ -4991,7 +5008,7 @@ static irqreturn_t ipr_isr(int irq, void *devp)
{
struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)devp;
unsigned long lock_flags = 0;
- volatile u32 int_reg;
+ volatile u32 int_reg, int_mask_reg;
u32 ioasc;
u16 cmd_index;
int num_hrrq = 0;
@@ -5006,6 +5023,33 @@ static irqreturn_t ipr_isr(int irq, void *devp)
return IRQ_NONE;
}
+ int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg32);
+ int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32) & ~int_mask_reg;
+
+ /* If an interrupt on the adapter did not occur, ignore it.
+ * Or in the case of SIS 64, check for a stage change interrupt.
+ */
+ if (unlikely((int_reg & IPR_PCII_OPER_INTERRUPTS) == 0)) {
+ if (ioa_cfg->sis64) {
+ int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg);
+ int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg;
+ if (int_reg & IPR_PCII_IPL_STAGE_CHANGE) {
+
+ /* clear stage change */
+ writel(IPR_PCII_IPL_STAGE_CHANGE, ioa_cfg->regs.clr_interrupt_reg);
+ int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg;
+ list_del(&ioa_cfg->reset_cmd->queue);
+ del_timer(&ioa_cfg->reset_cmd->timer);
+ ipr_reset_ioa_job(ioa_cfg->reset_cmd);
+ spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+ return IRQ_HANDLED;
+ }
+ }
+
+ spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+ return IRQ_NONE;
+ }
+
while (1) {
ipr_cmd = NULL;
@@ -5045,7 +5089,7 @@ static irqreturn_t ipr_isr(int irq, void *devp)
/* Clear the PCI interrupt */
do {
writel(IPR_PCII_HRRQ_UPDATED, ioa_cfg->regs.clr_interrupt_reg32);
- int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32);
+ int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32) & ~int_mask_reg;
} while (int_reg & IPR_PCII_HRRQ_UPDATED &&
num_hrrq++ < IPR_MAX_HRRQ_RETRIES);
@@ -5060,7 +5104,7 @@ static irqreturn_t ipr_isr(int irq, void *devp)
}
if (unlikely(rc == IRQ_NONE))
- rc = ipr_handle_other_interrupt(ioa_cfg);
+ rc = ipr_handle_other_interrupt(ioa_cfg, int_reg);
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
return rc;
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h
index 4d31625ab9cf..aa8bb2f2c6ee 100644
--- a/drivers/scsi/ipr.h
+++ b/drivers/scsi/ipr.h
@@ -26,6 +26,7 @@
#ifndef _IPR_H
#define _IPR_H
+#include <asm/unaligned.h>
#include <linux/types.h>
#include <linux/completion.h>
#include <linux/libata.h>
@@ -37,8 +38,8 @@
/*
* Literals
*/
-#define IPR_DRIVER_VERSION "2.5.0"
-#define IPR_DRIVER_DATE "(February 11, 2010)"
+#define IPR_DRIVER_VERSION "2.5.1"
+#define IPR_DRIVER_DATE "(August 10, 2010)"
/*
* IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding
@@ -318,6 +319,11 @@ struct ipr_ext_vpd {
__be32 wwid[2];
}__attribute__((packed));
+struct ipr_ext_vpd64 {
+ struct ipr_vpd vpd;
+ __be32 wwid[4];
+}__attribute__((packed));
+
struct ipr_std_inq_data {
u8 peri_qual_dev_type;
#define IPR_STD_INQ_PERI_QUAL(peri) ((peri) >> 5)
@@ -372,7 +378,7 @@ struct ipr_config_table_entry {
struct ipr_res_addr res_addr;
__be32 res_handle;
- __be32 reserved4[2];
+ __be32 lun_wwn[2];
struct ipr_std_inq_data std_inq_data;
}__attribute__ ((packed, aligned (4)));
@@ -394,7 +400,7 @@ struct ipr_config_table_entry64 {
__be64 res_path;
struct ipr_std_inq_data std_inq_data;
u8 reserved2[4];
- __be64 reserved3[2]; // description text
+ __be64 reserved3[2];
u8 reserved4[8];
}__attribute__ ((packed, aligned (8)));
@@ -913,7 +919,7 @@ struct ipr_hostrcb_type_24_error {
u8 array_id;
u8 last_res_path[8];
u8 protection_level[8];
- struct ipr_ext_vpd array_vpd;
+ struct ipr_ext_vpd64 array_vpd;
u8 description[16];
u8 reserved2[3];
u8 num_entries;
@@ -1210,6 +1216,7 @@ struct ipr_resource_entry {
__be32 res_handle;
__be64 dev_id;
+ __be64 lun_wwn;
struct scsi_lun dev_lun;
u8 res_path[8];
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
index 042153cbbde1..e1a395b438ee 100644
--- a/drivers/scsi/libsas/sas_ata.c
+++ b/drivers/scsi/libsas/sas_ata.c
@@ -162,6 +162,10 @@ static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc)
unsigned int xfer = 0;
unsigned int si;
+ /* If the device fell off, no sense in issuing commands */
+ if (dev->gone)
+ return AC_ERR_SYSTEM;
+
task = sas_alloc_task(GFP_ATOMIC);
if (!task)
return AC_ERR_SYSTEM;
@@ -347,6 +351,7 @@ static int sas_ata_scr_read(struct ata_link *link, unsigned int sc_reg_in,
static struct ata_port_operations sas_sata_ops = {
.phy_reset = sas_ata_phy_reset,
.post_internal_cmd = sas_ata_post_internal,
+ .qc_defer = ata_std_qc_defer,
.qc_prep = ata_noop_qc_prep,
.qc_issue = sas_ata_qc_issue,
.qc_fill_rtf = sas_ata_qc_fill_rtf,
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index 83dd5070a15c..505ffe358293 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -175,10 +175,10 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id,
switch (resp->result) {
case SMP_RESP_PHY_VACANT:
phy->phy_state = PHY_VACANT;
- return;
+ break;
default:
phy->phy_state = PHY_NOT_PRESENT;
- return;
+ break;
case SMP_RESP_FUNC_ACC:
phy->phy_state = PHY_EMPTY; /* do not know yet */
break;
@@ -209,7 +209,10 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id,
phy->phy->negotiated_linkrate = phy->linkrate;
if (!rediscover)
- sas_phy_add(phy->phy);
+ if (sas_phy_add(phy->phy)) {
+ sas_phy_free(phy->phy);
+ return;
+ }
SAS_DPRINTK("ex %016llx phy%02d:%c attached: %016llx\n",
SAS_ADDR(dev->sas_addr), phy->phy_id,
@@ -1724,6 +1727,7 @@ static void sas_unregister_ex_tree(struct domain_device *dev)
struct domain_device *child, *n;
list_for_each_entry_safe(child, n, &ex->children, siblings) {
+ child->gone = 1;
if (child->dev_type == EDGE_DEV ||
child->dev_type == FANOUT_DEV)
sas_unregister_ex_tree(child);
@@ -1744,6 +1748,7 @@ static void sas_unregister_devs_sas_addr(struct domain_device *parent,
&ex_dev->children, siblings) {
if (SAS_ADDR(child->sas_addr) ==
SAS_ADDR(phy->attached_sas_addr)) {
+ child->gone = 1;
if (child->dev_type == EDGE_DEV ||
child->dev_type == FANOUT_DEV)
sas_unregister_ex_tree(child);
@@ -1752,6 +1757,7 @@ static void sas_unregister_devs_sas_addr(struct domain_device *parent,
break;
}
}
+ parent->gone = 1;
sas_disable_routing(parent, phy->attached_sas_addr);
}
memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE);
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index f0cfba9a1fc8..55f09e92ab59 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -130,17 +130,6 @@ static void sas_scsi_task_done(struct sas_task *task)
sc->scsi_done(sc);
}
-static enum task_attribute sas_scsi_get_task_attr(struct scsi_cmnd *cmd)
-{
- enum task_attribute ta = TASK_ATTR_SIMPLE;
- if (cmd->request && blk_rq_tagged(cmd->request)) {
- if (cmd->device->ordered_tags &&
- (cmd->request->cmd_flags & REQ_HARDBARRIER))
- ta = TASK_ATTR_ORDERED;
- }
- return ta;
-}
-
static struct sas_task *sas_create_task(struct scsi_cmnd *cmd,
struct domain_device *dev,
gfp_t gfp_flags)
@@ -160,7 +149,7 @@ static struct sas_task *sas_create_task(struct scsi_cmnd *cmd,
task->ssp_task.retry_count = 1;
int_to_scsilun(cmd->device->lun, &lun);
memcpy(task->ssp_task.LUN, &lun.scsi_lun, 8);
- task->ssp_task.task_attr = sas_scsi_get_task_attr(cmd);
+ task->ssp_task.task_attr = TASK_ATTR_SIMPLE;
memcpy(task->ssp_task.cdb, cmd->cmnd, 16);
task->scatter = scsi_sglist(cmd);
@@ -228,6 +217,13 @@ int sas_queuecommand(struct scsi_cmnd *cmd,
goto out;
}
+ /* If the device fell off, no sense in issuing commands */
+ if (dev->gone) {
+ cmd->result = DID_BAD_TARGET << 16;
+ scsi_done(cmd);
+ goto out;
+ }
+
res = -ENOMEM;
task = sas_create_task(cmd, dev, GFP_ATOMIC);
if (!task)
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 23ce45708335..f681eea57730 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -586,6 +586,11 @@ lpfc_issue_lip(struct Scsi_Host *shost)
phba->cfg_link_speed);
mbxstatus = lpfc_sli_issue_mbox_wait(phba, pmboxq,
phba->fc_ratov * 2);
+ if ((mbxstatus == MBX_SUCCESS) &&
+ (pmboxq->u.mb.mbxStatus == MBXERR_SEC_NO_PERMISSION))
+ lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
+ "2859 SLI authentication is required "
+ "for INIT_LINK but has not done yet\n");
}
lpfc_set_loopback_flag(phba);
@@ -2159,6 +2164,11 @@ lpfc_nodev_tmo_set(struct lpfc_vport *vport, int val)
if (val >= LPFC_MIN_DEVLOSS_TMO && val <= LPFC_MAX_DEVLOSS_TMO) {
vport->cfg_nodev_tmo = val;
vport->cfg_devloss_tmo = val;
+ /*
+ * For compat: set the fc_host dev loss so new rports
+ * will get the value.
+ */
+ fc_host_dev_loss_tmo(lpfc_shost_from_vport(vport)) = val;
lpfc_update_rport_devloss_tmo(vport);
return 0;
}
@@ -2208,6 +2218,7 @@ lpfc_devloss_tmo_set(struct lpfc_vport *vport, int val)
vport->cfg_nodev_tmo = val;
vport->cfg_devloss_tmo = val;
vport->dev_loss_tmo_changed = 1;
+ fc_host_dev_loss_tmo(lpfc_shost_from_vport(vport)) = val;
lpfc_update_rport_devloss_tmo(vport);
return 0;
}
@@ -3776,6 +3787,11 @@ sysfs_mbox_read(struct file *filp, struct kobject *kobj,
case MBX_PORT_CAPABILITIES:
case MBX_PORT_IOV_CONTROL:
break;
+ case MBX_SECURITY_MGMT:
+ case MBX_AUTH_PORT:
+ if (phba->pci_dev_grp == LPFC_PCI_DEV_OC)
+ return -EPERM;
+ break;
case MBX_READ_SPARM64:
case MBX_READ_LA:
case MBX_READ_LA64:
diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c
index 49d0cf99c24c..f5d60b55f53a 100644
--- a/drivers/scsi/lpfc/lpfc_bsg.c
+++ b/drivers/scsi/lpfc/lpfc_bsg.c
@@ -259,6 +259,7 @@ lpfc_bsg_send_mgmt_cmd(struct fc_bsg_job *job)
struct bsg_job_data *dd_data;
uint32_t creg_val;
int rc = 0;
+ int iocb_stat;
/* in case no data is transferred */
job->reply->reply_payload_rcv_len = 0;
@@ -373,14 +374,13 @@ lpfc_bsg_send_mgmt_cmd(struct fc_bsg_job *job)
readl(phba->HCregaddr); /* flush */
}
- rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, cmdiocbq, 0);
-
- if (rc == IOCB_SUCCESS)
+ iocb_stat = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, cmdiocbq, 0);
+ if (iocb_stat == IOCB_SUCCESS)
return 0; /* done for now */
- else if (rc == IOCB_BUSY)
- rc = EAGAIN;
+ else if (iocb_stat == IOCB_BUSY)
+ rc = -EAGAIN;
else
- rc = EIO;
+ rc = -EIO;
/* iocb failed so cleanup */
@@ -631,9 +631,9 @@ lpfc_bsg_rport_els(struct fc_bsg_job *job)
if (rc == IOCB_SUCCESS)
return 0; /* done for now */
else if (rc == IOCB_BUSY)
- rc = EAGAIN;
+ rc = -EAGAIN;
else
- rc = EIO;
+ rc = -EIO;
pci_unmap_sg(phba->pcidev, job->request_payload.sg_list,
job->request_payload.sg_cnt, DMA_TO_DEVICE);
@@ -1299,7 +1299,7 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct fc_bsg_job *job, uint32_t tag,
/* Allocate buffer for command iocb */
ctiocb = lpfc_sli_get_iocbq(phba);
if (!ctiocb) {
- rc = ENOMEM;
+ rc = -ENOMEM;
goto no_ctiocb;
}
@@ -1518,7 +1518,7 @@ lpfc_bsg_diag_mode(struct fc_bsg_job *job)
loopback_mode = (struct diag_mode_set *)
job->request->rqst_data.h_vendor.vendor_cmd;
link_flags = loopback_mode->type;
- timeout = loopback_mode->timeout;
+ timeout = loopback_mode->timeout * 100;
if ((phba->link_state == LPFC_HBA_ERROR) ||
(psli->sli_flag & LPFC_BLOCK_MGMT_IO) ||
@@ -1649,17 +1649,18 @@ static int lpfcdiag_loop_self_reg(struct lpfc_hba *phba, uint16_t * rpi)
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!mbox)
- return ENOMEM;
+ return -ENOMEM;
status = lpfc_reg_rpi(phba, 0, phba->pport->fc_myDID,
(uint8_t *)&phba->pport->fc_sparam, mbox, 0);
if (status) {
mempool_free(mbox, phba->mbox_mem_pool);
- return ENOMEM;
+ return -ENOMEM;
}
dmabuff = (struct lpfc_dmabuf *) mbox->context1;
mbox->context1 = NULL;
+ mbox->context2 = NULL;
status = lpfc_sli_issue_mbox_wait(phba, mbox, LPFC_MBOX_TMO);
if ((status != MBX_SUCCESS) || (mbox->u.mb.mbxStatus)) {
@@ -1667,7 +1668,7 @@ static int lpfcdiag_loop_self_reg(struct lpfc_hba *phba, uint16_t * rpi)
kfree(dmabuff);
if (status != MBX_TIMEOUT)
mempool_free(mbox, phba->mbox_mem_pool);
- return ENODEV;
+ return -ENODEV;
}
*rpi = mbox->u.mb.un.varWords[0];
@@ -1693,7 +1694,7 @@ static int lpfcdiag_loop_self_unreg(struct lpfc_hba *phba, uint16_t rpi)
/* Allocate mboxq structure */
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (mbox == NULL)
- return ENOMEM;
+ return -ENOMEM;
lpfc_unreg_login(phba, 0, rpi, mbox);
status = lpfc_sli_issue_mbox_wait(phba, mbox, LPFC_MBOX_TMO);
@@ -1701,7 +1702,7 @@ static int lpfcdiag_loop_self_unreg(struct lpfc_hba *phba, uint16_t rpi)
if ((status != MBX_SUCCESS) || (mbox->u.mb.mbxStatus)) {
if (status != MBX_TIMEOUT)
mempool_free(mbox, phba->mbox_mem_pool);
- return EIO;
+ return -EIO;
}
mempool_free(mbox, phba->mbox_mem_pool);
@@ -1730,6 +1731,8 @@ static int lpfcdiag_loop_get_xri(struct lpfc_hba *phba, uint16_t rpi,
struct ulp_bde64 *bpl = NULL;
struct lpfc_sli_ct_request *ctreq = NULL;
int ret_val = 0;
+ int time_left;
+ int iocb_stat = 0;
unsigned long flags;
*txxri = 0;
@@ -1737,7 +1740,7 @@ static int lpfcdiag_loop_get_xri(struct lpfc_hba *phba, uint16_t rpi,
evt = lpfc_bsg_event_new(FC_REG_CT_EVENT, current->pid,
SLI_CT_ELX_LOOPBACK);
if (!evt)
- return ENOMEM;
+ return -ENOMEM;
spin_lock_irqsave(&phba->ct_ev_lock, flags);
list_add(&evt->node, &phba->ct_ev_waiters);
@@ -1770,7 +1773,7 @@ static int lpfcdiag_loop_get_xri(struct lpfc_hba *phba, uint16_t rpi,
if (cmdiocbq == NULL || rspiocbq == NULL ||
dmabuf == NULL || bpl == NULL || ctreq == NULL ||
dmabuf->virt == NULL) {
- ret_val = ENOMEM;
+ ret_val = -ENOMEM;
goto err_get_xri_exit;
}
@@ -1806,24 +1809,24 @@ static int lpfcdiag_loop_get_xri(struct lpfc_hba *phba, uint16_t rpi,
cmdiocbq->iocb_flag |= LPFC_IO_LIBDFC;
cmdiocbq->vport = phba->pport;
- ret_val = lpfc_sli_issue_iocb_wait(phba, LPFC_ELS_RING, cmdiocbq,
+ iocb_stat = lpfc_sli_issue_iocb_wait(phba, LPFC_ELS_RING, cmdiocbq,
rspiocbq,
(phba->fc_ratov * 2)
+ LPFC_DRVR_TIMEOUT);
- if (ret_val)
+ if (iocb_stat) {
+ ret_val = -EIO;
goto err_get_xri_exit;
-
+ }
*txxri = rsp->ulpContext;
evt->waiting = 1;
evt->wait_time_stamp = jiffies;
- ret_val = wait_event_interruptible_timeout(
+ time_left = wait_event_interruptible_timeout(
evt->wq, !list_empty(&evt->events_to_see),
((phba->fc_ratov * 2) + LPFC_DRVR_TIMEOUT) * HZ);
if (list_empty(&evt->events_to_see))
- ret_val = (ret_val) ? EINTR : ETIMEDOUT;
+ ret_val = (time_left) ? -EINTR : -ETIMEDOUT;
else {
- ret_val = IOCB_SUCCESS;
spin_lock_irqsave(&phba->ct_ev_lock, flags);
list_move(evt->events_to_see.prev, &evt->events_to_get);
spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
@@ -1845,7 +1848,7 @@ err_get_xri_exit:
kfree(dmabuf);
}
- if (cmdiocbq && (ret_val != IOCB_TIMEDOUT))
+ if (cmdiocbq && (iocb_stat != IOCB_TIMEDOUT))
lpfc_sli_release_iocbq(phba, cmdiocbq);
if (rspiocbq)
lpfc_sli_release_iocbq(phba, rspiocbq);
@@ -1959,6 +1962,7 @@ static int lpfcdiag_loop_post_rxbufs(struct lpfc_hba *phba, uint16_t rxxri,
uint32_t num_bde;
struct lpfc_dmabufext *rxbuffer = NULL;
int ret_val = 0;
+ int iocb_stat;
int i = 0;
cmdiocbq = lpfc_sli_get_iocbq(phba);
@@ -1973,7 +1977,7 @@ static int lpfcdiag_loop_post_rxbufs(struct lpfc_hba *phba, uint16_t rxxri,
}
if (!cmdiocbq || !rxbmp || !rxbpl || !rxbuffer) {
- ret_val = ENOMEM;
+ ret_val = -ENOMEM;
goto err_post_rxbufs_exit;
}
@@ -2022,16 +2026,16 @@ static int lpfcdiag_loop_post_rxbufs(struct lpfc_hba *phba, uint16_t rxxri,
cmd->ulpClass = CLASS3;
cmd->ulpContext = rxxri;
- ret_val = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, cmdiocbq, 0);
-
- if (ret_val == IOCB_ERROR) {
+ iocb_stat = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, cmdiocbq,
+ 0);
+ if (iocb_stat == IOCB_ERROR) {
diag_cmd_data_free(phba,
(struct lpfc_dmabufext *)mp[0]);
if (mp[1])
diag_cmd_data_free(phba,
(struct lpfc_dmabufext *)mp[1]);
dmp = list_entry(next, struct lpfc_dmabuf, list);
- ret_val = EIO;
+ ret_val = -EIO;
goto err_post_rxbufs_exit;
}
@@ -2045,7 +2049,7 @@ static int lpfcdiag_loop_post_rxbufs(struct lpfc_hba *phba, uint16_t rxxri,
cmdiocbq = lpfc_sli_get_iocbq(phba);
if (!cmdiocbq) {
dmp = list_entry(next, struct lpfc_dmabuf, list);
- ret_val = EIO;
+ ret_val = -EIO;
goto err_post_rxbufs_exit;
}
@@ -2111,6 +2115,8 @@ lpfc_bsg_diag_test(struct fc_bsg_job *job)
uint32_t num_bde;
uint8_t *ptr = NULL, *rx_databuf = NULL;
int rc = 0;
+ int time_left;
+ int iocb_stat;
unsigned long flags;
void *dataout = NULL;
uint32_t total_mem;
@@ -2185,22 +2191,18 @@ lpfc_bsg_diag_test(struct fc_bsg_job *job)
ptr, size);
rc = lpfcdiag_loop_self_reg(phba, &rpi);
- if (rc) {
- rc = -ENOMEM;
+ if (rc)
goto loopback_test_exit;
- }
rc = lpfcdiag_loop_get_xri(phba, rpi, &txxri, &rxxri);
if (rc) {
lpfcdiag_loop_self_unreg(phba, rpi);
- rc = -ENOMEM;
goto loopback_test_exit;
}
rc = lpfcdiag_loop_post_rxbufs(phba, rxxri, full_size);
if (rc) {
lpfcdiag_loop_self_unreg(phba, rpi);
- rc = -ENOMEM;
goto loopback_test_exit;
}
@@ -2290,21 +2292,22 @@ lpfc_bsg_diag_test(struct fc_bsg_job *job)
cmdiocbq->iocb_flag |= LPFC_IO_LIBDFC;
cmdiocbq->vport = phba->pport;
- rc = lpfc_sli_issue_iocb_wait(phba, LPFC_ELS_RING, cmdiocbq, rspiocbq,
- (phba->fc_ratov * 2) + LPFC_DRVR_TIMEOUT);
+ iocb_stat = lpfc_sli_issue_iocb_wait(phba, LPFC_ELS_RING, cmdiocbq,
+ rspiocbq, (phba->fc_ratov * 2) +
+ LPFC_DRVR_TIMEOUT);
- if ((rc != IOCB_SUCCESS) || (rsp->ulpStatus != IOCB_SUCCESS)) {
+ if ((iocb_stat != IOCB_SUCCESS) || (rsp->ulpStatus != IOCB_SUCCESS)) {
rc = -EIO;
goto err_loopback_test_exit;
}
evt->waiting = 1;
- rc = wait_event_interruptible_timeout(
+ time_left = wait_event_interruptible_timeout(
evt->wq, !list_empty(&evt->events_to_see),
((phba->fc_ratov * 2) + LPFC_DRVR_TIMEOUT) * HZ);
evt->waiting = 0;
if (list_empty(&evt->events_to_see))
- rc = (rc) ? -EINTR : -ETIMEDOUT;
+ rc = (time_left) ? -EINTR : -ETIMEDOUT;
else {
spin_lock_irqsave(&phba->ct_ev_lock, flags);
list_move(evt->events_to_see.prev, &evt->events_to_get);
@@ -2470,6 +2473,17 @@ lpfc_bsg_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
to += sizeof(MAILBOX_t);
size = pmboxq->u.mb.un.varWords[5];
memcpy(to, from, size);
+ } else if ((phba->sli_rev == LPFC_SLI_REV4) &&
+ (pmboxq->u.mb.mbxCommand == MBX_SLI4_CONFIG)) {
+ struct lpfc_mbx_nembed_cmd *nembed_sge =
+ (struct lpfc_mbx_nembed_cmd *)
+ &pmboxq->u.mb.un.varWords[0];
+
+ from = (uint8_t *)dd_data->context_un.mbox.dmp->dma.
+ virt;
+ to += sizeof(MAILBOX_t);
+ size = nembed_sge->sge[0].length;
+ memcpy(to, from, size);
} else if (pmboxq->u.mb.mbxCommand == MBX_READ_EVENT_LOG) {
from = (uint8_t *)dd_data->context_un.
mbox.dmp->dma.virt;
@@ -2911,6 +2925,59 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
from += sizeof(MAILBOX_t);
memcpy((uint8_t *)dmp->dma.virt, from,
bde->tus.f.bdeSize);
+ } else if (pmb->mbxCommand == MBX_SLI4_CONFIG) {
+ struct lpfc_mbx_nembed_cmd *nembed_sge;
+ struct mbox_header *header;
+ uint32_t receive_length;
+
+ /* rebuild the command for sli4 using our own buffers
+ * like we do for biu diags
+ */
+ header = (struct mbox_header *)&pmb->un.varWords[0];
+ nembed_sge = (struct lpfc_mbx_nembed_cmd *)
+ &pmb->un.varWords[0];
+ receive_length = nembed_sge->sge[0].length;
+
+ /* receive length cannot be greater than mailbox
+ * extension size
+ */
+ if ((receive_length == 0) ||
+ (receive_length > MAILBOX_EXT_SIZE)) {
+ rc = -ERANGE;
+ goto job_done;
+ }
+
+ rxbmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
+ if (!rxbmp) {
+ rc = -ENOMEM;
+ goto job_done;
+ }
+
+ rxbmp->virt = lpfc_mbuf_alloc(phba, 0, &rxbmp->phys);
+ if (!rxbmp->virt) {
+ rc = -ENOMEM;
+ goto job_done;
+ }
+
+ INIT_LIST_HEAD(&rxbmp->list);
+ rxbpl = (struct ulp_bde64 *) rxbmp->virt;
+ dmp = diag_cmd_data_alloc(phba, rxbpl, receive_length,
+ 0);
+ if (!dmp) {
+ rc = -ENOMEM;
+ goto job_done;
+ }
+
+ INIT_LIST_HEAD(&dmp->dma.list);
+ nembed_sge->sge[0].pa_hi = putPaddrHigh(dmp->dma.phys);
+ nembed_sge->sge[0].pa_lo = putPaddrLow(dmp->dma.phys);
+ /* copy the transmit data found in the mailbox
+ * extension area
+ */
+ from = (uint8_t *)mb;
+ from += sizeof(MAILBOX_t);
+ memcpy((uint8_t *)dmp->dma.virt, from,
+ header->cfg_mhdr.payload_length);
}
}
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 8d09191c327e..e6ca12f6c6cb 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -3250,6 +3250,8 @@ lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
lpfc_sli4_free_rpi(phba, pmb->u.mb.un.varUnregLogin.rpi);
pmb->context1 = NULL;
+ pmb->context2 = NULL;
+
lpfc_mbuf_free(phba, mp->virt, mp->phys);
kfree(mp);
mempool_free(pmb, phba->mbox_mem_pool);
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index 1f62ea8c165d..c3d7174e3469 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -1015,7 +1015,6 @@ static void
lpfc_mbx_cmpl_reg_fcfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
{
struct lpfc_vport *vport = mboxq->vport;
- unsigned long flags;
if (mboxq->u.mb.mbxStatus) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX,
@@ -1029,18 +1028,18 @@ lpfc_mbx_cmpl_reg_fcfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
/* Start FCoE discovery by sending a FLOGI. */
phba->fcf.fcfi = bf_get(lpfc_reg_fcfi_fcfi, &mboxq->u.mqe.un.reg_fcfi);
/* Set the FCFI registered flag */
- spin_lock_irqsave(&phba->hbalock, flags);
+ spin_lock_irq(&phba->hbalock);
phba->fcf.fcf_flag |= FCF_REGISTERED;
- spin_unlock_irqrestore(&phba->hbalock, flags);
+ spin_unlock_irq(&phba->hbalock);
/* If there is a pending FCoE event, restart FCF table scan. */
if (lpfc_check_pending_fcoe_event(phba, 1)) {
mempool_free(mboxq, phba->mbox_mem_pool);
return;
}
- spin_lock_irqsave(&phba->hbalock, flags);
+ spin_lock_irq(&phba->hbalock);
phba->fcf.fcf_flag |= (FCF_SCAN_DONE | FCF_IN_USE);
phba->hba_flag &= ~FCF_DISC_INPROGRESS;
- spin_unlock_irqrestore(&phba->hbalock, flags);
+ spin_unlock_irq(&phba->hbalock);
if (vport->port_state != LPFC_FLOGI)
lpfc_initial_flogi(vport);
@@ -1240,14 +1239,13 @@ lpfc_register_fcf(struct lpfc_hba *phba)
{
LPFC_MBOXQ_t *fcf_mbxq;
int rc;
- unsigned long flags;
- spin_lock_irqsave(&phba->hbalock, flags);
+ spin_lock_irq(&phba->hbalock);
/* If the FCF is not availabe do nothing. */
if (!(phba->fcf.fcf_flag & FCF_AVAILABLE)) {
phba->hba_flag &= ~FCF_DISC_INPROGRESS;
- spin_unlock_irqrestore(&phba->hbalock, flags);
+ spin_unlock_irq(&phba->hbalock);
return;
}
@@ -1255,19 +1253,19 @@ lpfc_register_fcf(struct lpfc_hba *phba)
if (phba->fcf.fcf_flag & FCF_REGISTERED) {
phba->fcf.fcf_flag |= (FCF_SCAN_DONE | FCF_IN_USE);
phba->hba_flag &= ~FCF_DISC_INPROGRESS;
- spin_unlock_irqrestore(&phba->hbalock, flags);
+ spin_unlock_irq(&phba->hbalock);
if (phba->pport->port_state != LPFC_FLOGI)
lpfc_initial_flogi(phba->pport);
return;
}
- spin_unlock_irqrestore(&phba->hbalock, flags);
+ spin_unlock_irq(&phba->hbalock);
fcf_mbxq = mempool_alloc(phba->mbox_mem_pool,
GFP_KERNEL);
if (!fcf_mbxq) {
- spin_lock_irqsave(&phba->hbalock, flags);
+ spin_lock_irq(&phba->hbalock);
phba->hba_flag &= ~FCF_DISC_INPROGRESS;
- spin_unlock_irqrestore(&phba->hbalock, flags);
+ spin_unlock_irq(&phba->hbalock);
return;
}
@@ -1276,9 +1274,9 @@ lpfc_register_fcf(struct lpfc_hba *phba)
fcf_mbxq->mbox_cmpl = lpfc_mbx_cmpl_reg_fcfi;
rc = lpfc_sli_issue_mbox(phba, fcf_mbxq, MBX_NOWAIT);
if (rc == MBX_NOT_FINISHED) {
- spin_lock_irqsave(&phba->hbalock, flags);
+ spin_lock_irq(&phba->hbalock);
phba->hba_flag &= ~FCF_DISC_INPROGRESS;
- spin_unlock_irqrestore(&phba->hbalock, flags);
+ spin_unlock_irq(&phba->hbalock);
mempool_free(fcf_mbxq, phba->mbox_mem_pool);
}
@@ -2851,6 +2849,7 @@ lpfc_mbx_cmpl_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
pmb->context1 = NULL;
+ pmb->context2 = NULL;
if (ndlp->nlp_flag & NLP_REG_LOGIN_SEND)
ndlp->nlp_flag &= ~NLP_REG_LOGIN_SEND;
@@ -3149,6 +3148,7 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
ndlp = (struct lpfc_nodelist *) pmb->context2;
pmb->context1 = NULL;
pmb->context2 = NULL;
+
if (mb->mbxStatus) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX,
"0258 Register Fabric login error: 0x%x\n",
@@ -3218,6 +3218,9 @@ lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2;
struct lpfc_vport *vport = pmb->vport;
+ pmb->context1 = NULL;
+ pmb->context2 = NULL;
+
if (mb->mbxStatus) {
out:
lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
@@ -3249,8 +3252,6 @@ out:
return;
}
- pmb->context1 = NULL;
-
ndlp->nlp_rpi = mb->un.varWords[0];
ndlp->nlp_flag |= NLP_RPI_VALID;
ndlp->nlp_type |= NLP_FABRIC;
@@ -4784,6 +4785,7 @@ lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
struct lpfc_vport *vport = pmb->vport;
pmb->context1 = NULL;
+ pmb->context2 = NULL;
ndlp->nlp_rpi = mb->un.varWords[0];
ndlp->nlp_flag |= NLP_RPI_VALID;
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h
index 1676f61291e7..a631647051d9 100644
--- a/drivers/scsi/lpfc/lpfc_hw.h
+++ b/drivers/scsi/lpfc/lpfc_hw.h
@@ -1380,6 +1380,9 @@ typedef struct { /* FireFly BIU registers */
#define MBX_INIT_VFI 0xA3
#define MBX_INIT_VPI 0xA4
+#define MBX_AUTH_PORT 0xF8
+#define MBX_SECURITY_MGMT 0xF9
+
/* IOCB Commands */
#define CMD_RCV_SEQUENCE_CX 0x01
@@ -1502,7 +1505,8 @@ typedef struct { /* FireFly BIU registers */
#define MBXERR_DMA_ERROR 15
#define MBXERR_ERROR 16
#define MBXERR_LINK_DOWN 0x33
-#define MBX_NOT_FINISHED 255
+#define MBXERR_SEC_NO_PERMISSION 0xF02
+#define MBX_NOT_FINISHED 255
#define MBX_BUSY 0xffffff /* Attempted cmd to busy Mailbox */
#define MBX_TIMEOUT 0xfffffe /* time-out expired waiting for */
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index da9ba06ad583..295c7ddb36c1 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -1076,21 +1076,16 @@ lpfc_hb_timeout_handler(struct lpfc_hba *phba)
} else {
/*
* If heart beat timeout called with hb_outstanding set
- * we need to take the HBA offline.
+ * we need to give the hb mailbox cmd a chance to
+ * complete or TMO.
*/
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "0459 Adapter heartbeat failure, "
- "taking this port offline.\n");
-
- spin_lock_irq(&phba->hbalock);
- psli->sli_flag &= ~LPFC_SLI_ACTIVE;
- spin_unlock_irq(&phba->hbalock);
-
- lpfc_offline_prep(phba);
- lpfc_offline(phba);
- lpfc_unblock_mgmt_io(phba);
- phba->link_state = LPFC_HBA_ERROR;
- lpfc_hba_down_post(phba);
+ lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
+ "0459 Adapter heartbeat still out"
+ "standing:last compl time was %d ms.\n",
+ jiffies_to_msecs(jiffies
+ - phba->last_completion_time));
+ mod_timer(&phba->hb_tmofunc,
+ jiffies + HZ * LPFC_HB_MBOX_TIMEOUT);
}
}
}
@@ -1277,13 +1272,21 @@ lpfc_handle_eratt_s3(struct lpfc_hba *phba)
if (phba->hba_flag & DEFER_ERATT)
lpfc_handle_deferred_eratt(phba);
- if (phba->work_hs & HS_FFER6) {
- /* Re-establishing Link */
- lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT,
- "1301 Re-establishing Link "
- "Data: x%x x%x x%x\n",
- phba->work_hs,
- phba->work_status[0], phba->work_status[1]);
+ if ((phba->work_hs & HS_FFER6) || (phba->work_hs & HS_FFER8)) {
+ if (phba->work_hs & HS_FFER6)
+ /* Re-establishing Link */
+ lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT,
+ "1301 Re-establishing Link "
+ "Data: x%x x%x x%x\n",
+ phba->work_hs, phba->work_status[0],
+ phba->work_status[1]);
+ if (phba->work_hs & HS_FFER8)
+ /* Device Zeroization */
+ lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT,
+ "2861 Host Authentication device "
+ "zeroization Data:x%x x%x x%x\n",
+ phba->work_hs, phba->work_status[0],
+ phba->work_status[1]);
spin_lock_irq(&phba->hbalock);
psli->sli_flag &= ~LPFC_SLI_ACTIVE;
@@ -2817,6 +2820,8 @@ void lpfc_host_attrib_init(struct Scsi_Host *shost)
(((uint32_t) vport->fc_sparam.cmn.bbRcvSizeMsb & 0x0F) << 8) |
(uint32_t) vport->fc_sparam.cmn.bbRcvSizeLsb;
+ fc_host_dev_loss_tmo(shost) = vport->cfg_devloss_tmo;
+
/* This value is also unchanging */
memset(fc_host_active_fc4s(shost), 0,
sizeof(fc_host_active_fc4s(shost)));
@@ -2883,65 +2888,6 @@ lpfc_stop_port(struct lpfc_hba *phba)
}
/**
- * lpfc_sli4_remove_dflt_fcf - Remove the driver default fcf record from the port.
- * @phba: pointer to lpfc hba data structure.
- *
- * This routine is invoked to remove the driver default fcf record from
- * the port. This routine currently acts on FCF Index 0.
- *
- **/
-void
-lpfc_sli_remove_dflt_fcf(struct lpfc_hba *phba)
-{
- int rc = 0;
- LPFC_MBOXQ_t *mboxq;
- struct lpfc_mbx_del_fcf_tbl_entry *del_fcf_record;
- uint32_t mbox_tmo, req_len;
- uint32_t shdr_status, shdr_add_status;
-
- mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
- if (!mboxq) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "2020 Failed to allocate mbox for ADD_FCF cmd\n");
- return;
- }
-
- req_len = sizeof(struct lpfc_mbx_del_fcf_tbl_entry) -
- sizeof(struct lpfc_sli4_cfg_mhdr);
- rc = lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_FCOE,
- LPFC_MBOX_OPCODE_FCOE_DELETE_FCF,
- req_len, LPFC_SLI4_MBX_EMBED);
- /*
- * In phase 1, there is a single FCF index, 0. In phase2, the driver
- * supports multiple FCF indices.
- */
- del_fcf_record = &mboxq->u.mqe.un.del_fcf_entry;
- bf_set(lpfc_mbx_del_fcf_tbl_count, del_fcf_record, 1);
- bf_set(lpfc_mbx_del_fcf_tbl_index, del_fcf_record,
- phba->fcf.current_rec.fcf_indx);
-
- if (!phba->sli4_hba.intr_enable)
- rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
- else {
- mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG);
- rc = lpfc_sli_issue_mbox_wait(phba, mboxq, mbox_tmo);
- }
- /* The IOCTL status is embedded in the mailbox subheader. */
- shdr_status = bf_get(lpfc_mbox_hdr_status,
- &del_fcf_record->header.cfg_shdr.response);
- shdr_add_status = bf_get(lpfc_mbox_hdr_add_status,
- &del_fcf_record->header.cfg_shdr.response);
- if (shdr_status || shdr_add_status || rc != MBX_SUCCESS) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
- "2516 DEL FCF of default FCF Index failed "
- "mbx status x%x, status x%x add_status x%x\n",
- rc, shdr_status, shdr_add_status);
- }
- if (rc != MBX_TIMEOUT)
- mempool_free(mboxq, phba->mbox_mem_pool);
-}
-
-/**
* lpfc_fcf_redisc_wait_start_timer - Start fcf rediscover wait timer
* @phba: Pointer to hba for which this call is being executed.
*
@@ -4283,12 +4229,6 @@ lpfc_sli4_driver_resource_unset(struct lpfc_hba *phba)
{
struct lpfc_fcf_conn_entry *conn_entry, *next_conn_entry;
- /* unregister default FCFI from the HBA */
- lpfc_sli4_fcfi_unreg(phba, phba->fcf.fcfi);
-
- /* Free the default FCR table */
- lpfc_sli_remove_dflt_fcf(phba);
-
/* Free memory allocated for msi-x interrupt vector entries */
kfree(phba->sli4_hba.msix_entries);
@@ -4316,9 +4256,6 @@ lpfc_sli4_driver_resource_unset(struct lpfc_hba *phba)
lpfc_sli4_cq_event_release_all(phba);
lpfc_sli4_cq_event_pool_destroy(phba);
- /* Reset SLI4 HBA FCoE function */
- lpfc_pci_function_reset(phba);
-
/* Free the bsmbx region. */
lpfc_destroy_bootstrap_mbox(phba);
@@ -4545,7 +4482,6 @@ lpfc_free_sgl_list(struct lpfc_hba *phba)
{
struct lpfc_sglq *sglq_entry = NULL, *sglq_next = NULL;
LIST_HEAD(sglq_list);
- int rc = 0;
spin_lock_irq(&phba->hbalock);
list_splice_init(&phba->sli4_hba.lpfc_sgl_list, &sglq_list);
@@ -4558,11 +4494,6 @@ lpfc_free_sgl_list(struct lpfc_hba *phba)
kfree(sglq_entry);
phba->sli4_hba.total_sglq_bufs--;
}
- rc = lpfc_sli4_remove_all_sgl_pages(phba);
- if (rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
- "2005 Unable to deregister pages from HBA: %x\n", rc);
- }
kfree(phba->sli4_hba.lpfc_els_sgl_array);
}
@@ -4725,8 +4656,8 @@ out_free_mem:
*
* Return codes
* 0 - successful
- * ENOMEM - No availble memory
- * EIO - The mailbox failed to complete successfully.
+ * -ENOMEM - No availble memory
+ * -EIO - The mailbox failed to complete successfully.
**/
int
lpfc_sli4_init_rpi_hdrs(struct lpfc_hba *phba)
@@ -5419,7 +5350,7 @@ lpfc_sli4_bar2_register_memmap(struct lpfc_hba *phba, uint32_t vf)
*
* Return codes
* 0 - successful
- * ENOMEM - could not allocated memory.
+ * -ENOMEM - could not allocated memory.
**/
static int
lpfc_create_bootstrap_mbox(struct lpfc_hba *phba)
@@ -5518,8 +5449,8 @@ lpfc_destroy_bootstrap_mbox(struct lpfc_hba *phba)
*
* Return codes
* 0 - successful
- * ENOMEM - No availble memory
- * EIO - The mailbox failed to complete successfully.
+ * -ENOMEM - No availble memory
+ * -EIO - The mailbox failed to complete successfully.
**/
static int
lpfc_sli4_read_config(struct lpfc_hba *phba)
@@ -5622,8 +5553,8 @@ lpfc_sli4_read_config(struct lpfc_hba *phba)
*
* Return codes
* 0 - successful
- * ENOMEM - No availble memory
- * EIO - The mailbox failed to complete successfully.
+ * -ENOMEM - No availble memory
+ * -EIO - The mailbox failed to complete successfully.
**/
static int
lpfc_setup_endian_order(struct lpfc_hba *phba)
@@ -5671,8 +5602,8 @@ lpfc_setup_endian_order(struct lpfc_hba *phba)
*
* Return codes
* 0 - successful
- * ENOMEM - No availble memory
- * EIO - The mailbox failed to complete successfully.
+ * -ENOMEM - No availble memory
+ * -EIO - The mailbox failed to complete successfully.
**/
static int
lpfc_sli4_queue_create(struct lpfc_hba *phba)
@@ -5966,8 +5897,8 @@ out_error:
*
* Return codes
* 0 - successful
- * ENOMEM - No availble memory
- * EIO - The mailbox failed to complete successfully.
+ * -ENOMEM - No availble memory
+ * -EIO - The mailbox failed to complete successfully.
**/
static void
lpfc_sli4_queue_destroy(struct lpfc_hba *phba)
@@ -6030,8 +5961,8 @@ lpfc_sli4_queue_destroy(struct lpfc_hba *phba)
*
* Return codes
* 0 - successful
- * ENOMEM - No availble memory
- * EIO - The mailbox failed to complete successfully.
+ * -ENOMEM - No availble memory
+ * -EIO - The mailbox failed to complete successfully.
**/
int
lpfc_sli4_queue_setup(struct lpfc_hba *phba)
@@ -6275,8 +6206,8 @@ out_error:
*
* Return codes
* 0 - successful
- * ENOMEM - No availble memory
- * EIO - The mailbox failed to complete successfully.
+ * -ENOMEM - No availble memory
+ * -EIO - The mailbox failed to complete successfully.
**/
void
lpfc_sli4_queue_unset(struct lpfc_hba *phba)
@@ -6481,8 +6412,8 @@ lpfc_sli4_cq_event_release_all(struct lpfc_hba *phba)
*
* Return codes
* 0 - successful
- * ENOMEM - No availble memory
- * EIO - The mailbox failed to complete successfully.
+ * -ENOMEM - No availble memory
+ * -EIO - The mailbox failed to complete successfully.
**/
int
lpfc_pci_function_reset(struct lpfc_hba *phba)
@@ -6592,50 +6523,6 @@ lpfc_sli4_send_nop_mbox_cmds(struct lpfc_hba *phba, uint32_t cnt)
}
/**
- * lpfc_sli4_fcfi_unreg - Unregister fcfi to device
- * @phba: pointer to lpfc hba data structure.
- * @fcfi: fcf index.
- *
- * This routine is invoked to unregister a FCFI from device.
- **/
-void
-lpfc_sli4_fcfi_unreg(struct lpfc_hba *phba, uint16_t fcfi)
-{
- LPFC_MBOXQ_t *mbox;
- uint32_t mbox_tmo;
- int rc;
- unsigned long flags;
-
- mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-
- if (!mbox)
- return;
-
- lpfc_unreg_fcfi(mbox, fcfi);
-
- if (!phba->sli4_hba.intr_enable)
- rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
- else {
- mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG);
- rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo);
- }
- if (rc != MBX_TIMEOUT)
- mempool_free(mbox, phba->mbox_mem_pool);
- if (rc != MBX_SUCCESS)
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
- "2517 Unregister FCFI command failed "
- "status %d, mbxStatus x%x\n", rc,
- bf_get(lpfc_mqe_status, &mbox->u.mqe));
- else {
- spin_lock_irqsave(&phba->hbalock, flags);
- /* Mark the FCFI is no longer registered */
- phba->fcf.fcf_flag &=
- ~(FCF_AVAILABLE | FCF_REGISTERED | FCF_SCAN_DONE);
- spin_unlock_irqrestore(&phba->hbalock, flags);
- }
-}
-
-/**
* lpfc_sli4_pci_mem_setup - Setup SLI4 HBA PCI memory space.
* @phba: pointer to lpfc hba data structure.
*
@@ -7372,10 +7259,14 @@ lpfc_sli4_unset_hba(struct lpfc_hba *phba)
phba->pport->work_port_events = 0;
- lpfc_sli4_hba_down(phba);
+ /* Stop the SLI4 device port */
+ lpfc_stop_port(phba);
lpfc_sli4_disable_intr(phba);
+ /* Reset SLI4 HBA FCoE function */
+ lpfc_pci_function_reset(phba);
+
return;
}
@@ -7424,15 +7315,15 @@ lpfc_sli4_hba_unset(struct lpfc_hba *phba)
spin_unlock_irq(&phba->hbalock);
}
- /* Tear down the queues in the HBA */
- lpfc_sli4_queue_unset(phba);
-
/* Disable PCI subsystem interrupt */
lpfc_sli4_disable_intr(phba);
/* Stop kthread signal shall trigger work_done one more time */
kthread_stop(phba->worker_thread);
+ /* Reset SLI4 HBA FCoE function */
+ lpfc_pci_function_reset(phba);
+
/* Stop the SLI4 device port */
phba->pport->work_port_events = 0;
}
@@ -8368,7 +8259,7 @@ lpfc_pci_remove_one_s4(struct pci_dev *pdev)
list_del_init(&vport->listentry);
spin_unlock_irq(&phba->hbalock);
- /* Call scsi_free before lpfc_sli4_driver_resource_unset since scsi
+ /* Perform scsi free before driver resource_unset since scsi
* buffers are released to their corresponding pools here.
*/
lpfc_scsi_free(phba);
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 2e51aa6b45b3..3a658953486c 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -599,6 +599,7 @@ lpfc_new_scsi_buf_s3(struct lpfc_vport *vport, int num_to_alloc)
iocb->ulpClass = CLASS3;
psb->status = IOSTAT_SUCCESS;
/* Put it back into the SCSI buffer list */
+ psb->cur_iocbq.context1 = psb;
lpfc_release_scsi_buf_s3(phba, psb);
}
@@ -849,6 +850,7 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc)
iocb->ulpBdeCount = 1;
iocb->ulpLe = 1;
iocb->ulpClass = CLASS3;
+ psb->cur_iocbq.context1 = psb;
if (phba->cfg_sg_dma_buf_size > SGL_PAGE_SIZE)
pdma_phys_bpl1 = pdma_phys_bpl + SGL_PAGE_SIZE;
else
@@ -2276,15 +2278,24 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,
* Check SLI validation that all the transfer was actually done
* (fcpi_parm should be zero). Apply check only to reads.
*/
- } else if ((scsi_status == SAM_STAT_GOOD) && fcpi_parm &&
- (cmnd->sc_data_direction == DMA_FROM_DEVICE)) {
+ } else if (fcpi_parm && (cmnd->sc_data_direction == DMA_FROM_DEVICE)) {
lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP | LOG_FCP_ERROR,
"9029 FCP Read Check Error Data: "
- "x%x x%x x%x x%x\n",
+ "x%x x%x x%x x%x x%x\n",
be32_to_cpu(fcpcmd->fcpDl),
be32_to_cpu(fcprsp->rspResId),
- fcpi_parm, cmnd->cmnd[0]);
- host_status = DID_ERROR;
+ fcpi_parm, cmnd->cmnd[0], scsi_status);
+ switch (scsi_status) {
+ case SAM_STAT_GOOD:
+ case SAM_STAT_CHECK_CONDITION:
+ /* Fabric dropped a data frame. Fail any successful
+ * command in which we detected dropped frames.
+ * A status of good or some check conditions could
+ * be considered a successful command.
+ */
+ host_status = DID_ERROR;
+ break;
+ }
scsi_set_resid(cmnd, scsi_bufflen(cmnd));
}
@@ -3072,7 +3083,14 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
if (ret)
return ret;
lpfc_cmd = (struct lpfc_scsi_buf *)cmnd->host_scribble;
- BUG_ON(!lpfc_cmd);
+ if (!lpfc_cmd) {
+ lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
+ "2873 SCSI Layer I/O Abort Request IO CMPL Status "
+ "x%x ID %d "
+ "LUN %d snum %#lx\n", ret, cmnd->device->id,
+ cmnd->device->lun, cmnd->serial_number);
+ return SUCCESS;
+ }
/*
* If pCmd field of the corresponding lpfc_scsi_buf structure
@@ -3656,7 +3674,6 @@ lpfc_slave_alloc(struct scsi_device *sdev)
*
* This routine configures following items
* - Tag command queuing support for @sdev if supported.
- * - Dev loss time out value of fc_rport.
* - Enable SLI polling for fcp ring if ENABLE_FCP_RING_POLLING flag is set.
*
* Return codes:
@@ -3667,21 +3684,12 @@ lpfc_slave_configure(struct scsi_device *sdev)
{
struct lpfc_vport *vport = (struct lpfc_vport *) sdev->host->hostdata;
struct lpfc_hba *phba = vport->phba;
- struct fc_rport *rport = starget_to_rport(sdev->sdev_target);
if (sdev->tagged_supported)
scsi_activate_tcq(sdev, vport->cfg_lun_queue_depth);
else
scsi_deactivate_tcq(sdev, vport->cfg_lun_queue_depth);
- /*
- * Initialize the fc transport attributes for the target
- * containing this scsi device. Also note that the driver's
- * target pointer is stored in the starget_data for the
- * driver's sysfs entry point functions.
- */
- rport->dev_loss_tmo = vport->cfg_devloss_tmo;
-
if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
lpfc_sli_handle_fast_ring_event(phba,
&phba->sli.ring[LPFC_FCP_RING], HA_R0RE_REQ);
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index fb8905f893f5..0d1e187b005d 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -1677,6 +1677,8 @@ lpfc_sli_chk_mbx_command(uint8_t mbxCommand)
case MBX_RESUME_RPI:
case MBX_READ_EVENT_LOG_STATUS:
case MBX_READ_EVENT_LOG:
+ case MBX_SECURITY_MGMT:
+ case MBX_AUTH_PORT:
ret = mbxCommand;
break;
default:
@@ -1730,10 +1732,11 @@ lpfc_sli_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
void
lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
{
+ struct lpfc_vport *vport = pmb->vport;
struct lpfc_dmabuf *mp;
+ struct lpfc_nodelist *ndlp;
uint16_t rpi, vpi;
int rc;
- struct lpfc_vport *vport = pmb->vport;
mp = (struct lpfc_dmabuf *) (pmb->context1);
@@ -1774,6 +1777,19 @@ lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
return;
}
+ if (pmb->u.mb.mbxCommand == MBX_REG_LOGIN64) {
+ ndlp = (struct lpfc_nodelist *)pmb->context2;
+ lpfc_nlp_put(ndlp);
+ pmb->context2 = NULL;
+ }
+
+ /* Check security permission status on INIT_LINK mailbox command */
+ if ((pmb->u.mb.mbxCommand == MBX_INIT_LINK) &&
+ (pmb->u.mb.mbxStatus == MBXERR_SEC_NO_PERMISSION))
+ lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
+ "2860 SLI authentication is required "
+ "for INIT_LINK but has not done yet\n");
+
if (bf_get(lpfc_mqe_command, &pmb->u.mqe) == MBX_SLI4_CONFIG)
lpfc_sli4_mbox_cmd_free(phba, pmb);
else
@@ -3651,11 +3667,15 @@ lpfc_sli_chipset_init(struct lpfc_hba *phba)
i = 0;
while ((status & (HS_FFRDY | HS_MBRDY)) != (HS_FFRDY | HS_MBRDY)) {
- /* Check every 100ms for 5 retries, then every 500ms for 5, then
- * every 2.5 sec for 5, then reset board and every 2.5 sec for
- * 4.
+ /* Check every 10ms for 10 retries, then every 100ms for 90
+ * retries, then every 1 sec for 50 retires for a total of
+ * ~60 seconds before reset the board again and check every
+ * 1 sec for 50 retries. The up to 60 seconds before the
+ * board ready is required by the Falcon FIPS zeroization
+ * complete, and any reset the board in between shall cause
+ * restart of zeroization, further delay the board ready.
*/
- if (i++ >= 20) {
+ if (i++ >= 200) {
/* Adapter failed to init, timeout, status reg
<status> */
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
@@ -3683,16 +3703,15 @@ lpfc_sli_chipset_init(struct lpfc_hba *phba)
return -EIO;
}
- if (i <= 5) {
+ if (i <= 10)
msleep(10);
- } else if (i <= 10) {
- msleep(500);
- } else {
- msleep(2500);
- }
+ else if (i <= 100)
+ msleep(100);
+ else
+ msleep(1000);
- if (i == 15) {
- /* Do post */
+ if (i == 150) {
+ /* Do post */
phba->pport->port_state = LPFC_VPORT_UNKNOWN;
lpfc_sli_brdrestart(phba);
}
@@ -4186,7 +4205,7 @@ lpfc_sli4_read_fcoe_params(struct lpfc_hba *phba,
*
* Return codes
* 0 - successful
- * ENOMEM - could not allocated memory.
+ * -ENOMEM - could not allocated memory.
**/
static int
lpfc_sli4_read_rev(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq,
@@ -5943,6 +5962,8 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
uint8_t command_type = ELS_COMMAND_NON_FIP;
uint8_t cmnd;
uint16_t xritag;
+ uint16_t abrt_iotag;
+ struct lpfc_iocbq *abrtiocbq;
struct ulp_bde64 *bpl = NULL;
uint32_t els_id = ELS_ID_DEFAULT;
int numBdes, i;
@@ -6155,9 +6176,17 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
case CMD_ABORT_XRI_CX:
/* words 0-2 memcpy should be 0 rserved */
/* port will send abts */
- if (iocbq->iocb.ulpCommand == CMD_CLOSE_XRI_CN)
+ abrt_iotag = iocbq->iocb.un.acxri.abortContextTag;
+ if (abrt_iotag != 0 && abrt_iotag <= phba->sli.last_iotag) {
+ abrtiocbq = phba->sli.iocbq_lookup[abrt_iotag];
+ fip = abrtiocbq->iocb_flag & LPFC_FIP_ELS_ID_MASK;
+ } else
+ fip = 0;
+
+ if ((iocbq->iocb.ulpCommand == CMD_CLOSE_XRI_CN) || fip)
/*
- * The link is down so the fw does not need to send abts
+ * The link is down, or the command was ELS_FIP
+ * so the fw does not need to send abts
* on the wire.
*/
bf_set(abort_cmd_ia, &wqe->abort_cmd, 1);
@@ -6901,37 +6930,6 @@ lpfc_sli_hba_down(struct lpfc_hba *phba)
}
/**
- * lpfc_sli4_hba_down - PCI function resource cleanup for the SLI4 HBA
- * @phba: Pointer to HBA context object.
- *
- * This function cleans up all queues, iocb, buffers, mailbox commands while
- * shutting down the SLI4 HBA FCoE function. This function is called with no
- * lock held and always returns 1.
- *
- * This function does the following to cleanup driver FCoE function resources:
- * - Free discovery resources for each virtual port
- * - Cleanup any pending fabric iocbs
- * - Iterate through the iocb txq and free each entry in the list.
- * - Free up any buffer posted to the HBA.
- * - Clean up all the queue entries: WQ, RQ, MQ, EQ, CQ, etc.
- * - Free mailbox commands in the mailbox queue.
- **/
-int
-lpfc_sli4_hba_down(struct lpfc_hba *phba)
-{
- /* Stop the SLI4 device port */
- lpfc_stop_port(phba);
-
- /* Tear down the queues in the HBA */
- lpfc_sli4_queue_unset(phba);
-
- /* unregister default FCFI from the HBA */
- lpfc_sli4_fcfi_unreg(phba, phba->fcf.fcfi);
-
- return 1;
-}
-
-/**
* lpfc_sli_pcimem_bcopy - SLI memory copy function
* @srcp: Source memory pointer.
* @destp: Destination memory pointer.
@@ -7888,7 +7886,7 @@ lpfc_sli_eratt_read(struct lpfc_hba *phba)
/* Check if there is a deferred error condition is active */
if ((HS_FFER1 & phba->work_hs) &&
((HS_FFER2 | HS_FFER3 | HS_FFER4 | HS_FFER5 |
- HS_FFER6 | HS_FFER7) & phba->work_hs)) {
+ HS_FFER6 | HS_FFER7 | HS_FFER8) & phba->work_hs)) {
phba->hba_flag |= DEFER_ERATT;
/* Clear all interrupt enable conditions */
writel(0, phba->HCregaddr);
@@ -8204,7 +8202,8 @@ lpfc_sli_sp_intr_handler(int irq, void *dev_id)
*/
if ((HS_FFER1 & phba->work_hs) &&
((HS_FFER2 | HS_FFER3 | HS_FFER4 | HS_FFER5 |
- HS_FFER6 | HS_FFER7) & phba->work_hs)) {
+ HS_FFER6 | HS_FFER7 | HS_FFER8) &
+ phba->work_hs)) {
phba->hba_flag |= DEFER_ERATT;
/* Clear all interrupt enable conditions */
writel(0, phba->HCregaddr);
@@ -8476,7 +8475,7 @@ lpfc_sli_intr_handler(int irq, void *dev_id)
* If there is deferred error attention, do not check for any interrupt.
*/
if (unlikely(phba->hba_flag & DEFER_ERATT)) {
- spin_unlock_irq(&phba->hbalock);
+ spin_unlock(&phba->hbalock);
return IRQ_NONE;
}
@@ -9724,8 +9723,8 @@ out_fail:
* command to finish before continuing.
*
* On success this function will return a zero. If unable to allocate enough
- * memory this function will return ENOMEM. If the queue create mailbox command
- * fails this function will return ENXIO.
+ * memory this function will return -ENOMEM. If the queue create mailbox command
+ * fails this function will return -ENXIO.
**/
uint32_t
lpfc_eq_create(struct lpfc_hba *phba, struct lpfc_queue *eq, uint16_t imax)
@@ -9840,8 +9839,8 @@ lpfc_eq_create(struct lpfc_hba *phba, struct lpfc_queue *eq, uint16_t imax)
* command to finish before continuing.
*
* On success this function will return a zero. If unable to allocate enough
- * memory this function will return ENOMEM. If the queue create mailbox command
- * fails this function will return ENXIO.
+ * memory this function will return -ENOMEM. If the queue create mailbox command
+ * fails this function will return -ENXIO.
**/
uint32_t
lpfc_cq_create(struct lpfc_hba *phba, struct lpfc_queue *cq,
@@ -10011,8 +10010,8 @@ lpfc_mq_create_fb_init(struct lpfc_hba *phba, struct lpfc_queue *mq,
* command to finish before continuing.
*
* On success this function will return a zero. If unable to allocate enough
- * memory this function will return ENOMEM. If the queue create mailbox command
- * fails this function will return ENXIO.
+ * memory this function will return -ENOMEM. If the queue create mailbox command
+ * fails this function will return -ENXIO.
**/
int32_t
lpfc_mq_create(struct lpfc_hba *phba, struct lpfc_queue *mq,
@@ -10146,8 +10145,8 @@ out:
* command to finish before continuing.
*
* On success this function will return a zero. If unable to allocate enough
- * memory this function will return ENOMEM. If the queue create mailbox command
- * fails this function will return ENXIO.
+ * memory this function will return -ENOMEM. If the queue create mailbox command
+ * fails this function will return -ENXIO.
**/
uint32_t
lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq,
@@ -10234,8 +10233,8 @@ out:
* mailbox command to finish before continuing.
*
* On success this function will return a zero. If unable to allocate enough
- * memory this function will return ENOMEM. If the queue create mailbox command
- * fails this function will return ENXIO.
+ * memory this function will return -ENOMEM. If the queue create mailbox command
+ * fails this function will return -ENXIO.
**/
uint32_t
lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq,
@@ -10403,7 +10402,7 @@ out:
* The @eq struct is used to get the queue ID of the queue to destroy.
*
* On success this function will return a zero. If the queue destroy mailbox
- * command fails this function will return ENXIO.
+ * command fails this function will return -ENXIO.
**/
uint32_t
lpfc_eq_destroy(struct lpfc_hba *phba, struct lpfc_queue *eq)
@@ -10458,7 +10457,7 @@ lpfc_eq_destroy(struct lpfc_hba *phba, struct lpfc_queue *eq)
* The @cq struct is used to get the queue ID of the queue to destroy.
*
* On success this function will return a zero. If the queue destroy mailbox
- * command fails this function will return ENXIO.
+ * command fails this function will return -ENXIO.
**/
uint32_t
lpfc_cq_destroy(struct lpfc_hba *phba, struct lpfc_queue *cq)
@@ -10511,7 +10510,7 @@ lpfc_cq_destroy(struct lpfc_hba *phba, struct lpfc_queue *cq)
* The @mq struct is used to get the queue ID of the queue to destroy.
*
* On success this function will return a zero. If the queue destroy mailbox
- * command fails this function will return ENXIO.
+ * command fails this function will return -ENXIO.
**/
uint32_t
lpfc_mq_destroy(struct lpfc_hba *phba, struct lpfc_queue *mq)
@@ -10564,7 +10563,7 @@ lpfc_mq_destroy(struct lpfc_hba *phba, struct lpfc_queue *mq)
* The @wq struct is used to get the queue ID of the queue to destroy.
*
* On success this function will return a zero. If the queue destroy mailbox
- * command fails this function will return ENXIO.
+ * command fails this function will return -ENXIO.
**/
uint32_t
lpfc_wq_destroy(struct lpfc_hba *phba, struct lpfc_queue *wq)
@@ -10616,7 +10615,7 @@ lpfc_wq_destroy(struct lpfc_hba *phba, struct lpfc_queue *wq)
* The @rq struct is used to get the queue ID of the queue to destroy.
*
* On success this function will return a zero. If the queue destroy mailbox
- * command fails this function will return ENXIO.
+ * command fails this function will return -ENXIO.
**/
uint32_t
lpfc_rq_destroy(struct lpfc_hba *phba, struct lpfc_queue *hrq,
@@ -10758,51 +10757,6 @@ lpfc_sli4_post_sgl(struct lpfc_hba *phba,
}
return 0;
}
-/**
- * lpfc_sli4_remove_all_sgl_pages - Post scatter gather list for an XRI to HBA
- * @phba: The virtual port for which this call being executed.
- *
- * This routine will remove all of the sgl pages registered with the hba.
- *
- * Return codes:
- * 0 - Success
- * -ENXIO, -ENOMEM - Failure
- **/
-int
-lpfc_sli4_remove_all_sgl_pages(struct lpfc_hba *phba)
-{
- LPFC_MBOXQ_t *mbox;
- int rc;
- uint32_t shdr_status, shdr_add_status;
- union lpfc_sli4_cfg_shdr *shdr;
-
- mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
- if (!mbox)
- return -ENOMEM;
-
- lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_FCOE,
- LPFC_MBOX_OPCODE_FCOE_REMOVE_SGL_PAGES, 0,
- LPFC_SLI4_MBX_EMBED);
- if (!phba->sli4_hba.intr_enable)
- rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
- else
- rc = lpfc_sli_issue_mbox_wait(phba, mbox, LPFC_MBOX_TMO);
- /* The IOCTL status is embedded in the mailbox subheader. */
- shdr = (union lpfc_sli4_cfg_shdr *)
- &mbox->u.mqe.un.sli4_config.header.cfg_shdr;
- shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
- shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
- if (rc != MBX_TIMEOUT)
- mempool_free(mbox, phba->mbox_mem_pool);
- if (shdr_status || shdr_add_status || rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "2512 REMOVE_ALL_SGL_PAGES mailbox failed with "
- "status x%x add_status x%x, mbx status x%x\n",
- shdr_status, shdr_add_status, rc);
- rc = -ENXIO;
- }
- return rc;
-}
/**
* lpfc_sli4_next_xritag - Get an xritag for the io
@@ -11819,7 +11773,7 @@ lpfc_sli4_handle_received_buffer(struct lpfc_hba *phba,
*
* Return codes
* 0 - successful
- * EIO - The mailbox failed to complete successfully.
+ * -EIO - The mailbox failed to complete successfully.
* When this error occurs, the driver is not guaranteed
* to have any rpi regions posted to the device and
* must either attempt to repost the regions or take a
@@ -11857,8 +11811,8 @@ lpfc_sli4_post_all_rpi_hdrs(struct lpfc_hba *phba)
*
* Return codes
* 0 - successful
- * ENOMEM - No available memory
- * EIO - The mailbox failed to complete successfully.
+ * -ENOMEM - No available memory
+ * -EIO - The mailbox failed to complete successfully.
**/
int
lpfc_sli4_post_rpi_hdr(struct lpfc_hba *phba, struct lpfc_rpi_hdr *rpi_page)
@@ -12805,8 +12759,11 @@ lpfc_cleanup_pending_mbox(struct lpfc_vport *vport)
LPFC_MBOXQ_t *mb, *nextmb;
struct lpfc_dmabuf *mp;
struct lpfc_nodelist *ndlp;
+ struct lpfc_nodelist *act_mbx_ndlp = NULL;
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+ LIST_HEAD(mbox_cmd_list);
+ /* Clean up internally queued mailbox commands with the vport */
spin_lock_irq(&phba->hbalock);
list_for_each_entry_safe(mb, nextmb, &phba->sli.mboxq, list) {
if (mb->vport != vport)
@@ -12816,6 +12773,28 @@ lpfc_cleanup_pending_mbox(struct lpfc_vport *vport)
(mb->u.mb.mbxCommand != MBX_REG_VPI))
continue;
+ list_del(&mb->list);
+ list_add_tail(&mb->list, &mbox_cmd_list);
+ }
+ /* Clean up active mailbox command with the vport */
+ mb = phba->sli.mbox_active;
+ if (mb && (mb->vport == vport)) {
+ if ((mb->u.mb.mbxCommand == MBX_REG_LOGIN64) ||
+ (mb->u.mb.mbxCommand == MBX_REG_VPI))
+ mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+ if (mb->u.mb.mbxCommand == MBX_REG_LOGIN64) {
+ act_mbx_ndlp = (struct lpfc_nodelist *)mb->context2;
+ /* Put reference count for delayed processing */
+ act_mbx_ndlp = lpfc_nlp_get(act_mbx_ndlp);
+ /* Unregister the RPI when mailbox complete */
+ mb->mbox_flag |= LPFC_MBX_IMED_UNREG;
+ }
+ }
+ spin_unlock_irq(&phba->hbalock);
+
+ /* Release the cleaned-up mailbox commands */
+ while (!list_empty(&mbox_cmd_list)) {
+ list_remove_head(&mbox_cmd_list, mb, LPFC_MBOXQ_t, list);
if (mb->u.mb.mbxCommand == MBX_REG_LOGIN64) {
if (phba->sli_rev == LPFC_SLI_REV4)
__lpfc_sli4_free_rpi(phba,
@@ -12826,36 +12805,24 @@ lpfc_cleanup_pending_mbox(struct lpfc_vport *vport)
kfree(mp);
}
ndlp = (struct lpfc_nodelist *) mb->context2;
+ mb->context2 = NULL;
if (ndlp) {
- spin_lock_irq(shost->host_lock);
+ spin_lock(shost->host_lock);
ndlp->nlp_flag &= ~NLP_IGNR_REG_CMPL;
- spin_unlock_irq(shost->host_lock);
+ spin_unlock(shost->host_lock);
lpfc_nlp_put(ndlp);
- mb->context2 = NULL;
}
}
- list_del(&mb->list);
mempool_free(mb, phba->mbox_mem_pool);
}
- mb = phba->sli.mbox_active;
- if (mb && (mb->vport == vport)) {
- if ((mb->u.mb.mbxCommand == MBX_REG_LOGIN64) ||
- (mb->u.mb.mbxCommand == MBX_REG_VPI))
- mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
- if (mb->u.mb.mbxCommand == MBX_REG_LOGIN64) {
- ndlp = (struct lpfc_nodelist *) mb->context2;
- if (ndlp) {
- spin_lock_irq(shost->host_lock);
- ndlp->nlp_flag &= ~NLP_IGNR_REG_CMPL;
- spin_unlock_irq(shost->host_lock);
- lpfc_nlp_put(ndlp);
- mb->context2 = NULL;
- }
- /* Unregister the RPI when mailbox complete */
- mb->mbox_flag |= LPFC_MBX_IMED_UNREG;
- }
+
+ /* Release the ndlp with the cleaned-up active mailbox command */
+ if (act_mbx_ndlp) {
+ spin_lock(shost->host_lock);
+ act_mbx_ndlp->nlp_flag &= ~NLP_IGNR_REG_CMPL;
+ spin_unlock(shost->host_lock);
+ lpfc_nlp_put(act_mbx_ndlp);
}
- spin_unlock_irq(&phba->hbalock);
}
/**
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h
index a3b24d99a2a7..a0ca572ec28b 100644
--- a/drivers/scsi/lpfc/lpfc_sli4.h
+++ b/drivers/scsi/lpfc/lpfc_sli4.h
@@ -481,7 +481,6 @@ struct lpfc_rpi_hdr {
*/
int lpfc_pci_function_reset(struct lpfc_hba *);
int lpfc_sli4_hba_setup(struct lpfc_hba *);
-int lpfc_sli4_hba_down(struct lpfc_hba *);
int lpfc_sli4_config(struct lpfc_hba *, struct lpfcMboxq *, uint8_t,
uint8_t, uint32_t, bool);
void lpfc_sli4_mbox_cmd_free(struct lpfc_hba *, struct lpfcMboxq *);
@@ -514,7 +513,6 @@ int lpfc_sli4_queue_setup(struct lpfc_hba *);
void lpfc_sli4_queue_unset(struct lpfc_hba *);
int lpfc_sli4_post_sgl(struct lpfc_hba *, dma_addr_t, dma_addr_t, uint16_t);
int lpfc_sli4_repost_scsi_sgl_list(struct lpfc_hba *);
-int lpfc_sli4_remove_all_sgl_pages(struct lpfc_hba *);
uint16_t lpfc_sli4_next_xritag(struct lpfc_hba *);
int lpfc_sli4_post_async_mbox(struct lpfc_hba *);
int lpfc_sli4_post_sgl_list(struct lpfc_hba *phba);
diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
index 61afb3420a96..f93120e4c796 100644
--- a/drivers/scsi/lpfc/lpfc_version.h
+++ b/drivers/scsi/lpfc/lpfc_version.h
@@ -18,7 +18,7 @@
* included with this package. *
*******************************************************************/
-#define LPFC_DRIVER_VERSION "8.3.16"
+#define LPFC_DRIVER_VERSION "8.3.17"
#define LPFC_DRIVER_NAME "lpfc"
#define LPFC_SP_DRIVER_HANDLER_NAME "lpfc:sp"
#define LPFC_FP_DRIVER_HANDLER_NAME "lpfc:fp"
diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c
index 1655507a682c..a5281ce893d0 100644
--- a/drivers/scsi/lpfc/lpfc_vport.c
+++ b/drivers/scsi/lpfc/lpfc_vport.c
@@ -580,7 +580,9 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
"static vport.\n");
return VPORT_ERROR;
}
-
+ spin_lock_irq(&phba->hbalock);
+ vport->load_flag |= FC_UNLOADING;
+ spin_unlock_irq(&phba->hbalock);
/*
* If we are not unloading the driver then prevent the vport_delete
* from happening until after this vport's discovery is finished.
@@ -618,10 +620,6 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
scsi_host_put(shost);
return VPORT_INVAL;
}
- spin_lock_irq(&phba->hbalock);
- vport->load_flag |= FC_UNLOADING;
- spin_unlock_irq(&phba->hbalock);
-
lpfc_free_sysfs_attr(vport);
lpfc_debugfs_terminate(vport);
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index 0b6e3228610a..7ceb5cf12c6b 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -46,7 +46,7 @@
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/dma-mapping.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/slab.h>
#include <scsi/scsicam.h>
@@ -62,6 +62,7 @@ MODULE_DESCRIPTION ("LSI Logic MegaRAID legacy driver");
MODULE_LICENSE ("GPL");
MODULE_VERSION(MEGARAID_MODULE_VERSION);
+static DEFINE_MUTEX(megadev_mutex);
static unsigned int max_cmd_per_lun = DEF_CMD_PER_LUN;
module_param(max_cmd_per_lun, uint, 0);
MODULE_PARM_DESC(max_cmd_per_lun, "Maximum number of commands which can be issued to a single LUN (default=DEF_CMD_PER_LUN=63)");
@@ -101,6 +102,7 @@ static const struct file_operations megadev_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = megadev_unlocked_ioctl,
.open = megadev_open,
+ .llseek = noop_llseek,
};
/*
@@ -3282,7 +3284,6 @@ mega_init_scb(adapter_t *adapter)
static int
megadev_open (struct inode *inode, struct file *filep)
{
- cycle_kernel_lock();
/*
* Only allow superuser to access private ioctl interface
*/
@@ -3701,9 +3702,9 @@ megadev_unlocked_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
{
int ret;
- lock_kernel();
+ mutex_lock(&megadev_mutex);
ret = megadev_ioctl(filep, cmd, arg);
- unlock_kernel();
+ mutex_unlock(&megadev_mutex);
return ret;
}
diff --git a/drivers/scsi/megaraid/megaraid_mm.c b/drivers/scsi/megaraid/megaraid_mm.c
index 41f82f76d884..a7008c0c24f9 100644
--- a/drivers/scsi/megaraid/megaraid_mm.c
+++ b/drivers/scsi/megaraid/megaraid_mm.c
@@ -16,11 +16,12 @@
*/
#include <linux/sched.h>
#include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include "megaraid_mm.h"
// Entry points for char node driver
+static DEFINE_MUTEX(mraid_mm_mutex);
static int mraid_mm_open(struct inode *, struct file *);
static long mraid_mm_unlocked_ioctl(struct file *, uint, unsigned long);
@@ -75,6 +76,7 @@ static const struct file_operations lsi_fops = {
.compat_ioctl = mraid_mm_compat_ioctl,
#endif
.owner = THIS_MODULE,
+ .llseek = noop_llseek,
};
static struct miscdevice megaraid_mm_dev = {
@@ -98,7 +100,6 @@ mraid_mm_open(struct inode *inode, struct file *filep)
*/
if (!capable(CAP_SYS_ADMIN)) return (-EACCES);
- cycle_kernel_lock();
return 0;
}
@@ -224,9 +225,9 @@ mraid_mm_unlocked_ioctl(struct file *filep, unsigned int cmd,
int err;
/* inconsistant: mraid_mm_compat_ioctl doesn't take the BKL */
- lock_kernel();
+ mutex_lock(&mraid_mm_mutex);
err = mraid_mm_ioctl(filep, cmd, arg);
- unlock_kernel();
+ mutex_unlock(&mraid_mm_mutex);
return err;
}
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
index 99e4478c3f3e..d3c9cdee292b 100644
--- a/drivers/scsi/megaraid/megaraid_sas.c
+++ b/drivers/scsi/megaraid/megaraid_sas.c
@@ -33,7 +33,6 @@
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
-#include <linux/smp_lock.h>
#include <linux/uio.h>
#include <linux/slab.h>
#include <asm/uaccess.h>
@@ -62,6 +61,11 @@ MODULE_VERSION(MEGASAS_VERSION);
MODULE_AUTHOR("megaraidlinux@lsi.com");
MODULE_DESCRIPTION("LSI MegaRAID SAS Driver");
+static int megasas_transition_to_ready(struct megasas_instance *instance);
+static int megasas_get_pd_list(struct megasas_instance *instance);
+static int megasas_issue_init_mfi(struct megasas_instance *instance);
+static int megasas_register_aen(struct megasas_instance *instance,
+ u32 seq_num, u32 class_locale_word);
/*
* PCI ID table for all supported controllers
*/
@@ -164,7 +168,7 @@ megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd)
static inline void
megasas_enable_intr_xscale(struct megasas_register_set __iomem * regs)
{
- writel(1, &(regs)->outbound_intr_mask);
+ writel(0, &(regs)->outbound_intr_mask);
/* Dummy readl to force pci flush */
readl(&regs->outbound_intr_mask);
@@ -200,24 +204,27 @@ static int
megasas_clear_intr_xscale(struct megasas_register_set __iomem * regs)
{
u32 status;
+ u32 mfiStatus = 0;
/*
* Check if it is our interrupt
*/
status = readl(&regs->outbound_intr_status);
- if (!(status & MFI_OB_INTR_STATUS_MASK)) {
- return 1;
- }
+ if (status & MFI_OB_INTR_STATUS_MASK)
+ mfiStatus = MFI_INTR_FLAG_REPLY_MESSAGE;
+ if (status & MFI_XSCALE_OMR0_CHANGE_INTERRUPT)
+ mfiStatus |= MFI_INTR_FLAG_FIRMWARE_STATE_CHANGE;
/*
* Clear the interrupt by writing back the same value
*/
- writel(status, &regs->outbound_intr_status);
+ if (mfiStatus)
+ writel(status, &regs->outbound_intr_status);
/* Dummy readl to force pci flush */
readl(&regs->outbound_intr_status);
- return 0;
+ return mfiStatus;
}
/**
@@ -232,8 +239,69 @@ megasas_fire_cmd_xscale(struct megasas_instance *instance,
u32 frame_count,
struct megasas_register_set __iomem *regs)
{
+ unsigned long flags;
+ spin_lock_irqsave(&instance->hba_lock, flags);
writel((frame_phys_addr >> 3)|(frame_count),
&(regs)->inbound_queue_port);
+ spin_unlock_irqrestore(&instance->hba_lock, flags);
+}
+
+/**
+ * megasas_adp_reset_xscale - For controller reset
+ * @regs: MFI register set
+ */
+static int
+megasas_adp_reset_xscale(struct megasas_instance *instance,
+ struct megasas_register_set __iomem *regs)
+{
+ u32 i;
+ u32 pcidata;
+ writel(MFI_ADP_RESET, &regs->inbound_doorbell);
+
+ for (i = 0; i < 3; i++)
+ msleep(1000); /* sleep for 3 secs */
+ pcidata = 0;
+ pci_read_config_dword(instance->pdev, MFI_1068_PCSR_OFFSET, &pcidata);
+ printk(KERN_NOTICE "pcidata = %x\n", pcidata);
+ if (pcidata & 0x2) {
+ printk(KERN_NOTICE "mfi 1068 offset read=%x\n", pcidata);
+ pcidata &= ~0x2;
+ pci_write_config_dword(instance->pdev,
+ MFI_1068_PCSR_OFFSET, pcidata);
+
+ for (i = 0; i < 2; i++)
+ msleep(1000); /* need to wait 2 secs again */
+
+ pcidata = 0;
+ pci_read_config_dword(instance->pdev,
+ MFI_1068_FW_HANDSHAKE_OFFSET, &pcidata);
+ printk(KERN_NOTICE "1068 offset handshake read=%x\n", pcidata);
+ if ((pcidata & 0xffff0000) == MFI_1068_FW_READY) {
+ printk(KERN_NOTICE "1068 offset pcidt=%x\n", pcidata);
+ pcidata = 0;
+ pci_write_config_dword(instance->pdev,
+ MFI_1068_FW_HANDSHAKE_OFFSET, pcidata);
+ }
+ }
+ return 0;
+}
+
+/**
+ * megasas_check_reset_xscale - For controller reset check
+ * @regs: MFI register set
+ */
+static int
+megasas_check_reset_xscale(struct megasas_instance *instance,
+ struct megasas_register_set __iomem *regs)
+{
+ u32 consumer;
+ consumer = *instance->consumer;
+
+ if ((instance->adprecovery != MEGASAS_HBA_OPERATIONAL) &&
+ (*instance->consumer == MEGASAS_ADPRESET_INPROG_SIGN)) {
+ return 1;
+ }
+ return 0;
}
static struct megasas_instance_template megasas_instance_template_xscale = {
@@ -243,6 +311,8 @@ static struct megasas_instance_template megasas_instance_template_xscale = {
.disable_intr = megasas_disable_intr_xscale,
.clear_intr = megasas_clear_intr_xscale,
.read_fw_status_reg = megasas_read_fw_status_reg_xscale,
+ .adp_reset = megasas_adp_reset_xscale,
+ .check_reset = megasas_check_reset_xscale,
};
/**
@@ -264,7 +334,7 @@ megasas_enable_intr_ppc(struct megasas_register_set __iomem * regs)
{
writel(0xFFFFFFFF, &(regs)->outbound_doorbell_clear);
- writel(~0x80000004, &(regs)->outbound_intr_mask);
+ writel(~0x80000000, &(regs)->outbound_intr_mask);
/* Dummy readl to force pci flush */
readl(&regs->outbound_intr_mask);
@@ -307,7 +377,7 @@ megasas_clear_intr_ppc(struct megasas_register_set __iomem * regs)
status = readl(&regs->outbound_intr_status);
if (!(status & MFI_REPLY_1078_MESSAGE_INTERRUPT)) {
- return 1;
+ return 0;
}
/*
@@ -318,7 +388,7 @@ megasas_clear_intr_ppc(struct megasas_register_set __iomem * regs)
/* Dummy readl to force pci flush */
readl(&regs->outbound_doorbell_clear);
- return 0;
+ return 1;
}
/**
* megasas_fire_cmd_ppc - Sends command to the FW
@@ -332,10 +402,34 @@ megasas_fire_cmd_ppc(struct megasas_instance *instance,
u32 frame_count,
struct megasas_register_set __iomem *regs)
{
+ unsigned long flags;
+ spin_lock_irqsave(&instance->hba_lock, flags);
writel((frame_phys_addr | (frame_count<<1))|1,
&(regs)->inbound_queue_port);
+ spin_unlock_irqrestore(&instance->hba_lock, flags);
+}
+
+/**
+ * megasas_adp_reset_ppc - For controller reset
+ * @regs: MFI register set
+ */
+static int
+megasas_adp_reset_ppc(struct megasas_instance *instance,
+ struct megasas_register_set __iomem *regs)
+{
+ return 0;
}
+/**
+ * megasas_check_reset_ppc - For controller reset check
+ * @regs: MFI register set
+ */
+static int
+megasas_check_reset_ppc(struct megasas_instance *instance,
+ struct megasas_register_set __iomem *regs)
+{
+ return 0;
+}
static struct megasas_instance_template megasas_instance_template_ppc = {
.fire_cmd = megasas_fire_cmd_ppc,
@@ -343,6 +437,8 @@ static struct megasas_instance_template megasas_instance_template_ppc = {
.disable_intr = megasas_disable_intr_ppc,
.clear_intr = megasas_clear_intr_ppc,
.read_fw_status_reg = megasas_read_fw_status_reg_ppc,
+ .adp_reset = megasas_adp_reset_ppc,
+ .check_reset = megasas_check_reset_ppc,
};
/**
@@ -397,7 +493,7 @@ megasas_clear_intr_skinny(struct megasas_register_set __iomem *regs)
status = readl(&regs->outbound_intr_status);
if (!(status & MFI_SKINNY_ENABLE_INTERRUPT_MASK)) {
- return 1;
+ return 0;
}
/*
@@ -410,7 +506,7 @@ megasas_clear_intr_skinny(struct megasas_register_set __iomem *regs)
*/
readl(&regs->outbound_intr_status);
- return 0;
+ return 1;
}
/**
@@ -426,11 +522,33 @@ megasas_fire_cmd_skinny(struct megasas_instance *instance,
struct megasas_register_set __iomem *regs)
{
unsigned long flags;
- spin_lock_irqsave(&instance->fire_lock, flags);
+ spin_lock_irqsave(&instance->hba_lock, flags);
writel(0, &(regs)->inbound_high_queue_port);
writel((frame_phys_addr | (frame_count<<1))|1,
&(regs)->inbound_low_queue_port);
- spin_unlock_irqrestore(&instance->fire_lock, flags);
+ spin_unlock_irqrestore(&instance->hba_lock, flags);
+}
+
+/**
+ * megasas_adp_reset_skinny - For controller reset
+ * @regs: MFI register set
+ */
+static int
+megasas_adp_reset_skinny(struct megasas_instance *instance,
+ struct megasas_register_set __iomem *regs)
+{
+ return 0;
+}
+
+/**
+ * megasas_check_reset_skinny - For controller reset check
+ * @regs: MFI register set
+ */
+static int
+megasas_check_reset_skinny(struct megasas_instance *instance,
+ struct megasas_register_set __iomem *regs)
+{
+ return 0;
}
static struct megasas_instance_template megasas_instance_template_skinny = {
@@ -440,6 +558,8 @@ static struct megasas_instance_template megasas_instance_template_skinny = {
.disable_intr = megasas_disable_intr_skinny,
.clear_intr = megasas_clear_intr_skinny,
.read_fw_status_reg = megasas_read_fw_status_reg_skinny,
+ .adp_reset = megasas_adp_reset_skinny,
+ .check_reset = megasas_check_reset_skinny,
};
@@ -495,23 +615,29 @@ static int
megasas_clear_intr_gen2(struct megasas_register_set __iomem *regs)
{
u32 status;
+ u32 mfiStatus = 0;
/*
* Check if it is our interrupt
*/
status = readl(&regs->outbound_intr_status);
- if (!(status & MFI_GEN2_ENABLE_INTERRUPT_MASK))
- return 1;
+ if (status & MFI_GEN2_ENABLE_INTERRUPT_MASK) {
+ mfiStatus = MFI_INTR_FLAG_REPLY_MESSAGE;
+ }
+ if (status & MFI_G2_OUTBOUND_DOORBELL_CHANGE_INTERRUPT) {
+ mfiStatus |= MFI_INTR_FLAG_FIRMWARE_STATE_CHANGE;
+ }
/*
* Clear the interrupt by writing back the same value
*/
- writel(status, &regs->outbound_doorbell_clear);
+ if (mfiStatus)
+ writel(status, &regs->outbound_doorbell_clear);
/* Dummy readl to force pci flush */
readl(&regs->outbound_intr_status);
- return 0;
+ return mfiStatus;
}
/**
* megasas_fire_cmd_gen2 - Sends command to the FW
@@ -525,8 +651,74 @@ megasas_fire_cmd_gen2(struct megasas_instance *instance,
u32 frame_count,
struct megasas_register_set __iomem *regs)
{
+ unsigned long flags;
+ spin_lock_irqsave(&instance->hba_lock, flags);
writel((frame_phys_addr | (frame_count<<1))|1,
&(regs)->inbound_queue_port);
+ spin_unlock_irqrestore(&instance->hba_lock, flags);
+}
+
+/**
+ * megasas_adp_reset_gen2 - For controller reset
+ * @regs: MFI register set
+ */
+static int
+megasas_adp_reset_gen2(struct megasas_instance *instance,
+ struct megasas_register_set __iomem *reg_set)
+{
+ u32 retry = 0 ;
+ u32 HostDiag;
+
+ writel(0, &reg_set->seq_offset);
+ writel(4, &reg_set->seq_offset);
+ writel(0xb, &reg_set->seq_offset);
+ writel(2, &reg_set->seq_offset);
+ writel(7, &reg_set->seq_offset);
+ writel(0xd, &reg_set->seq_offset);
+ msleep(1000);
+
+ HostDiag = (u32)readl(&reg_set->host_diag);
+
+ while ( !( HostDiag & DIAG_WRITE_ENABLE) ) {
+ msleep(100);
+ HostDiag = (u32)readl(&reg_set->host_diag);
+ printk(KERN_NOTICE "RESETGEN2: retry=%x, hostdiag=%x\n",
+ retry, HostDiag);
+
+ if (retry++ >= 100)
+ return 1;
+
+ }
+
+ printk(KERN_NOTICE "ADP_RESET_GEN2: HostDiag=%x\n", HostDiag);
+
+ writel((HostDiag | DIAG_RESET_ADAPTER), &reg_set->host_diag);
+
+ ssleep(10);
+
+ HostDiag = (u32)readl(&reg_set->host_diag);
+ while ( ( HostDiag & DIAG_RESET_ADAPTER) ) {
+ msleep(100);
+ HostDiag = (u32)readl(&reg_set->host_diag);
+ printk(KERN_NOTICE "RESET_GEN2: retry=%x, hostdiag=%x\n",
+ retry, HostDiag);
+
+ if (retry++ >= 1000)
+ return 1;
+
+ }
+ return 0;
+}
+
+/**
+ * megasas_check_reset_gen2 - For controller reset check
+ * @regs: MFI register set
+ */
+static int
+megasas_check_reset_gen2(struct megasas_instance *instance,
+ struct megasas_register_set __iomem *regs)
+{
+ return 0;
}
static struct megasas_instance_template megasas_instance_template_gen2 = {
@@ -536,11 +728,13 @@ static struct megasas_instance_template megasas_instance_template_gen2 = {
.disable_intr = megasas_disable_intr_gen2,
.clear_intr = megasas_clear_intr_gen2,
.read_fw_status_reg = megasas_read_fw_status_reg_gen2,
+ .adp_reset = megasas_adp_reset_gen2,
+ .check_reset = megasas_check_reset_gen2,
};
/**
* This is the end of set of functions & definitions
-* specific to ppc (deviceid : 0x60) controllers
+* specific to gen2 (deviceid : 0x78, 0x79) controllers
*/
/**
@@ -599,8 +793,7 @@ megasas_issue_blocked_cmd(struct megasas_instance *instance,
instance->instancet->fire_cmd(instance,
cmd->frame_phys_addr, 0, instance->reg_set);
- wait_event_timeout(instance->int_cmd_wait_q, (cmd->cmd_status != ENODATA),
- MEGASAS_INTERNAL_CMD_WAIT_TIME*HZ);
+ wait_event(instance->int_cmd_wait_q, cmd->cmd_status != ENODATA);
return 0;
}
@@ -648,8 +841,8 @@ megasas_issue_blocked_abort_cmd(struct megasas_instance *instance,
/*
* Wait for this cmd to complete
*/
- wait_event_timeout(instance->abort_cmd_wait_q, (cmd->cmd_status != 0xFF),
- MEGASAS_INTERNAL_CMD_WAIT_TIME*HZ);
+ wait_event(instance->abort_cmd_wait_q, cmd->cmd_status != 0xFF);
+ cmd->sync_cmd = 0;
megasas_return_cmd(instance, cmd);
return 0;
@@ -1131,14 +1324,22 @@ megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *))
u32 frame_count;
struct megasas_cmd *cmd;
struct megasas_instance *instance;
+ unsigned long flags;
instance = (struct megasas_instance *)
scmd->device->host->hostdata;
- /* Don't process if we have already declared adapter dead */
- if (instance->hw_crit_error)
+ if (instance->issuepend_done == 0)
return SCSI_MLQUEUE_HOST_BUSY;
+ spin_lock_irqsave(&instance->hba_lock, flags);
+ if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) {
+ spin_unlock_irqrestore(&instance->hba_lock, flags);
+ return SCSI_MLQUEUE_HOST_BUSY;
+ }
+
+ spin_unlock_irqrestore(&instance->hba_lock, flags);
+
scmd->scsi_done = done;
scmd->result = 0;
@@ -1274,6 +1475,18 @@ static int megasas_slave_alloc(struct scsi_device *sdev)
return 0;
}
+static void megaraid_sas_kill_hba(struct megasas_instance *instance)
+{
+ if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
+ (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
+ writel(MFI_STOP_ADP,
+ &instance->reg_set->reserved_0[0]);
+ } else {
+ writel(MFI_STOP_ADP,
+ &instance->reg_set->inbound_doorbell);
+ }
+}
+
/**
* megasas_complete_cmd_dpc - Returns FW's controller structure
* @instance_addr: Address of adapter soft state
@@ -1291,7 +1504,7 @@ static void megasas_complete_cmd_dpc(unsigned long instance_addr)
unsigned long flags;
/* If we have already declared adapter dead, donot complete cmds */
- if (instance->hw_crit_error)
+ if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR )
return;
spin_lock_irqsave(&instance->completion_lock, flags);
@@ -1301,6 +1514,11 @@ static void megasas_complete_cmd_dpc(unsigned long instance_addr)
while (consumer != producer) {
context = instance->reply_queue[consumer];
+ if (context >= instance->max_fw_cmds) {
+ printk(KERN_ERR "Unexpected context value %x\n",
+ context);
+ BUG();
+ }
cmd = instance->cmd_list[context];
@@ -1350,7 +1568,76 @@ static void megasas_complete_cmd_dpc(unsigned long instance_addr)
static int megasas_wait_for_outstanding(struct megasas_instance *instance)
{
int i;
+ u32 reset_index;
u32 wait_time = MEGASAS_RESET_WAIT_TIME;
+ u8 adprecovery;
+ unsigned long flags;
+ struct list_head clist_local;
+ struct megasas_cmd *reset_cmd;
+
+ spin_lock_irqsave(&instance->hba_lock, flags);
+ adprecovery = instance->adprecovery;
+ spin_unlock_irqrestore(&instance->hba_lock, flags);
+
+ if (adprecovery != MEGASAS_HBA_OPERATIONAL) {
+
+ INIT_LIST_HEAD(&clist_local);
+ spin_lock_irqsave(&instance->hba_lock, flags);
+ list_splice_init(&instance->internal_reset_pending_q,
+ &clist_local);
+ spin_unlock_irqrestore(&instance->hba_lock, flags);
+
+ printk(KERN_NOTICE "megasas: HBA reset wait ...\n");
+ for (i = 0; i < wait_time; i++) {
+ msleep(1000);
+ spin_lock_irqsave(&instance->hba_lock, flags);
+ adprecovery = instance->adprecovery;
+ spin_unlock_irqrestore(&instance->hba_lock, flags);
+ if (adprecovery == MEGASAS_HBA_OPERATIONAL)
+ break;
+ }
+
+ if (adprecovery != MEGASAS_HBA_OPERATIONAL) {
+ printk(KERN_NOTICE "megasas: reset: Stopping HBA.\n");
+ spin_lock_irqsave(&instance->hba_lock, flags);
+ instance->adprecovery = MEGASAS_HW_CRITICAL_ERROR;
+ spin_unlock_irqrestore(&instance->hba_lock, flags);
+ return FAILED;
+ }
+
+ reset_index = 0;
+ while (!list_empty(&clist_local)) {
+ reset_cmd = list_entry((&clist_local)->next,
+ struct megasas_cmd, list);
+ list_del_init(&reset_cmd->list);
+ if (reset_cmd->scmd) {
+ reset_cmd->scmd->result = DID_RESET << 16;
+ printk(KERN_NOTICE "%d:%p reset [%02x], %#lx\n",
+ reset_index, reset_cmd,
+ reset_cmd->scmd->cmnd[0],
+ reset_cmd->scmd->serial_number);
+
+ reset_cmd->scmd->scsi_done(reset_cmd->scmd);
+ megasas_return_cmd(instance, reset_cmd);
+ } else if (reset_cmd->sync_cmd) {
+ printk(KERN_NOTICE "megasas:%p synch cmds"
+ "reset queue\n",
+ reset_cmd);
+
+ reset_cmd->cmd_status = ENODATA;
+ instance->instancet->fire_cmd(instance,
+ reset_cmd->frame_phys_addr,
+ 0, instance->reg_set);
+ } else {
+ printk(KERN_NOTICE "megasas: %p unexpected"
+ "cmds lst\n",
+ reset_cmd);
+ }
+ reset_index++;
+ }
+
+ return SUCCESS;
+ }
for (i = 0; i < wait_time; i++) {
@@ -1373,6 +1660,7 @@ static int megasas_wait_for_outstanding(struct megasas_instance *instance)
}
if (atomic_read(&instance->fw_outstanding)) {
+ printk(KERN_NOTICE "megaraid_sas: pending cmds after reset\n");
/*
* Send signal to FW to stop processing any pending cmds.
* The controller will be taken offline by the OS now.
@@ -1388,10 +1676,14 @@ static int megasas_wait_for_outstanding(struct megasas_instance *instance)
&instance->reg_set->inbound_doorbell);
}
megasas_dump_pending_frames(instance);
- instance->hw_crit_error = 1;
+ spin_lock_irqsave(&instance->hba_lock, flags);
+ instance->adprecovery = MEGASAS_HW_CRITICAL_ERROR;
+ spin_unlock_irqrestore(&instance->hba_lock, flags);
return FAILED;
}
+ printk(KERN_NOTICE "megaraid_sas: no pending cmds after reset\n");
+
return SUCCESS;
}
@@ -1413,7 +1705,7 @@ static int megasas_generic_reset(struct scsi_cmnd *scmd)
scmd_printk(KERN_NOTICE, scmd, "megasas: RESET -%ld cmd=%x retries=%x\n",
scmd->serial_number, scmd->cmnd[0], scmd->retries);
- if (instance->hw_crit_error) {
+ if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
printk(KERN_ERR "megasas: cannot recover from previous reset "
"failures\n");
return FAILED;
@@ -1568,7 +1860,8 @@ megasas_service_aen(struct megasas_instance *instance, struct megasas_cmd *cmd)
instance->aen_cmd = NULL;
megasas_return_cmd(instance, cmd);
- if (instance->unload == 0) {
+ if ((instance->unload == 0) &&
+ ((instance->issuepend_done == 1))) {
struct megasas_aen_event *ev;
ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
if (!ev) {
@@ -1663,6 +1956,9 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
struct megasas_header *hdr = &cmd->frame->hdr;
unsigned long flags;
+ /* flag for the retry reset */
+ cmd->retry_for_fw_reset = 0;
+
if (cmd->scmd)
cmd->scmd->SCp.ptr = NULL;
@@ -1783,39 +2079,301 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
}
/**
+ * megasas_issue_pending_cmds_again - issue all pending cmds
+ * in FW again because of the fw reset
+ * @instance: Adapter soft state
+ */
+static inline void
+megasas_issue_pending_cmds_again(struct megasas_instance *instance)
+{
+ struct megasas_cmd *cmd;
+ struct list_head clist_local;
+ union megasas_evt_class_locale class_locale;
+ unsigned long flags;
+ u32 seq_num;
+
+ INIT_LIST_HEAD(&clist_local);
+ spin_lock_irqsave(&instance->hba_lock, flags);
+ list_splice_init(&instance->internal_reset_pending_q, &clist_local);
+ spin_unlock_irqrestore(&instance->hba_lock, flags);
+
+ while (!list_empty(&clist_local)) {
+ cmd = list_entry((&clist_local)->next,
+ struct megasas_cmd, list);
+ list_del_init(&cmd->list);
+
+ if (cmd->sync_cmd || cmd->scmd) {
+ printk(KERN_NOTICE "megaraid_sas: command %p, %p:%d"
+ "detected to be pending while HBA reset.\n",
+ cmd, cmd->scmd, cmd->sync_cmd);
+
+ cmd->retry_for_fw_reset++;
+
+ if (cmd->retry_for_fw_reset == 3) {
+ printk(KERN_NOTICE "megaraid_sas: cmd %p, %p:%d"
+ "was tried multiple times during reset."
+ "Shutting down the HBA\n",
+ cmd, cmd->scmd, cmd->sync_cmd);
+ megaraid_sas_kill_hba(instance);
+
+ instance->adprecovery =
+ MEGASAS_HW_CRITICAL_ERROR;
+ return;
+ }
+ }
+
+ if (cmd->sync_cmd == 1) {
+ if (cmd->scmd) {
+ printk(KERN_NOTICE "megaraid_sas: unexpected"
+ "cmd attached to internal command!\n");
+ }
+ printk(KERN_NOTICE "megasas: %p synchronous cmd"
+ "on the internal reset queue,"
+ "issue it again.\n", cmd);
+ cmd->cmd_status = ENODATA;
+ instance->instancet->fire_cmd(instance,
+ cmd->frame_phys_addr ,
+ 0, instance->reg_set);
+ } else if (cmd->scmd) {
+ printk(KERN_NOTICE "megasas: %p scsi cmd [%02x],%#lx"
+ "detected on the internal queue, issue again.\n",
+ cmd, cmd->scmd->cmnd[0], cmd->scmd->serial_number);
+
+ atomic_inc(&instance->fw_outstanding);
+ instance->instancet->fire_cmd(instance,
+ cmd->frame_phys_addr,
+ cmd->frame_count-1, instance->reg_set);
+ } else {
+ printk(KERN_NOTICE "megasas: %p unexpected cmd on the"
+ "internal reset defer list while re-issue!!\n",
+ cmd);
+ }
+ }
+
+ if (instance->aen_cmd) {
+ printk(KERN_NOTICE "megaraid_sas: aen_cmd in def process\n");
+ megasas_return_cmd(instance, instance->aen_cmd);
+
+ instance->aen_cmd = NULL;
+ }
+
+ /*
+ * Initiate AEN (Asynchronous Event Notification)
+ */
+ seq_num = instance->last_seq_num;
+ class_locale.members.reserved = 0;
+ class_locale.members.locale = MR_EVT_LOCALE_ALL;
+ class_locale.members.class = MR_EVT_CLASS_DEBUG;
+
+ megasas_register_aen(instance, seq_num, class_locale.word);
+}
+
+/**
+ * Move the internal reset pending commands to a deferred queue.
+ *
+ * We move the commands pending at internal reset time to a
+ * pending queue. This queue would be flushed after successful
+ * completion of the internal reset sequence. if the internal reset
+ * did not complete in time, the kernel reset handler would flush
+ * these commands.
+ **/
+static void
+megasas_internal_reset_defer_cmds(struct megasas_instance *instance)
+{
+ struct megasas_cmd *cmd;
+ int i;
+ u32 max_cmd = instance->max_fw_cmds;
+ u32 defer_index;
+ unsigned long flags;
+
+ defer_index = 0;
+ spin_lock_irqsave(&instance->cmd_pool_lock, flags);
+ for (i = 0; i < max_cmd; i++) {
+ cmd = instance->cmd_list[i];
+ if (cmd->sync_cmd == 1 || cmd->scmd) {
+ printk(KERN_NOTICE "megasas: moving cmd[%d]:%p:%d:%p"
+ "on the defer queue as internal\n",
+ defer_index, cmd, cmd->sync_cmd, cmd->scmd);
+
+ if (!list_empty(&cmd->list)) {
+ printk(KERN_NOTICE "megaraid_sas: ERROR while"
+ " moving this cmd:%p, %d %p, it was"
+ "discovered on some list?\n",
+ cmd, cmd->sync_cmd, cmd->scmd);
+
+ list_del_init(&cmd->list);
+ }
+ defer_index++;
+ list_add_tail(&cmd->list,
+ &instance->internal_reset_pending_q);
+ }
+ }
+ spin_unlock_irqrestore(&instance->cmd_pool_lock, flags);
+}
+
+
+static void
+process_fw_state_change_wq(struct work_struct *work)
+{
+ struct megasas_instance *instance =
+ container_of(work, struct megasas_instance, work_init);
+ u32 wait;
+ unsigned long flags;
+
+ if (instance->adprecovery != MEGASAS_ADPRESET_SM_INFAULT) {
+ printk(KERN_NOTICE "megaraid_sas: error, recovery st %x \n",
+ instance->adprecovery);
+ return ;
+ }
+
+ if (instance->adprecovery == MEGASAS_ADPRESET_SM_INFAULT) {
+ printk(KERN_NOTICE "megaraid_sas: FW detected to be in fault"
+ "state, restarting it...\n");
+
+ instance->instancet->disable_intr(instance->reg_set);
+ atomic_set(&instance->fw_outstanding, 0);
+
+ atomic_set(&instance->fw_reset_no_pci_access, 1);
+ instance->instancet->adp_reset(instance, instance->reg_set);
+ atomic_set(&instance->fw_reset_no_pci_access, 0 );
+
+ printk(KERN_NOTICE "megaraid_sas: FW restarted successfully,"
+ "initiating next stage...\n");
+
+ printk(KERN_NOTICE "megaraid_sas: HBA recovery state machine,"
+ "state 2 starting...\n");
+
+ /*waitting for about 20 second before start the second init*/
+ for (wait = 0; wait < 30; wait++) {
+ msleep(1000);
+ }
+
+ if (megasas_transition_to_ready(instance)) {
+ printk(KERN_NOTICE "megaraid_sas:adapter not ready\n");
+
+ megaraid_sas_kill_hba(instance);
+ instance->adprecovery = MEGASAS_HW_CRITICAL_ERROR;
+ return ;
+ }
+
+ if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS1064R) ||
+ (instance->pdev->device == PCI_DEVICE_ID_DELL_PERC5) ||
+ (instance->pdev->device == PCI_DEVICE_ID_LSI_VERDE_ZCR)
+ ) {
+ *instance->consumer = *instance->producer;
+ } else {
+ *instance->consumer = 0;
+ *instance->producer = 0;
+ }
+
+ megasas_issue_init_mfi(instance);
+
+ spin_lock_irqsave(&instance->hba_lock, flags);
+ instance->adprecovery = MEGASAS_HBA_OPERATIONAL;
+ spin_unlock_irqrestore(&instance->hba_lock, flags);
+ instance->instancet->enable_intr(instance->reg_set);
+
+ megasas_issue_pending_cmds_again(instance);
+ instance->issuepend_done = 1;
+ }
+ return ;
+}
+
+/**
* megasas_deplete_reply_queue - Processes all completed commands
* @instance: Adapter soft state
* @alt_status: Alternate status to be returned to
* SCSI mid-layer instead of the status
* returned by the FW
+ * Note: this must be called with hba lock held
*/
static int
-megasas_deplete_reply_queue(struct megasas_instance *instance, u8 alt_status)
+megasas_deplete_reply_queue(struct megasas_instance *instance,
+ u8 alt_status)
{
- /*
- * Check if it is our interrupt
- * Clear the interrupt
- */
- if(instance->instancet->clear_intr(instance->reg_set))
+ u32 mfiStatus;
+ u32 fw_state;
+
+ if ((mfiStatus = instance->instancet->check_reset(instance,
+ instance->reg_set)) == 1) {
+ return IRQ_HANDLED;
+ }
+
+ if ((mfiStatus = instance->instancet->clear_intr(
+ instance->reg_set)
+ ) == 0) {
return IRQ_NONE;
+ }
+
+ instance->mfiStatus = mfiStatus;
+
+ if ((mfiStatus & MFI_INTR_FLAG_FIRMWARE_STATE_CHANGE)) {
+ fw_state = instance->instancet->read_fw_status_reg(
+ instance->reg_set) & MFI_STATE_MASK;
+
+ if (fw_state != MFI_STATE_FAULT) {
+ printk(KERN_NOTICE "megaraid_sas: fw state:%x\n",
+ fw_state);
+ }
+
+ if ((fw_state == MFI_STATE_FAULT) &&
+ (instance->disableOnlineCtrlReset == 0)) {
+ printk(KERN_NOTICE "megaraid_sas: wait adp restart\n");
+
+ if ((instance->pdev->device ==
+ PCI_DEVICE_ID_LSI_SAS1064R) ||
+ (instance->pdev->device ==
+ PCI_DEVICE_ID_DELL_PERC5) ||
+ (instance->pdev->device ==
+ PCI_DEVICE_ID_LSI_VERDE_ZCR)) {
+
+ *instance->consumer =
+ MEGASAS_ADPRESET_INPROG_SIGN;
+ }
+
+
+ instance->instancet->disable_intr(instance->reg_set);
+ instance->adprecovery = MEGASAS_ADPRESET_SM_INFAULT;
+ instance->issuepend_done = 0;
+
+ atomic_set(&instance->fw_outstanding, 0);
+ megasas_internal_reset_defer_cmds(instance);
+
+ printk(KERN_NOTICE "megasas: fwState=%x, stage:%d\n",
+ fw_state, instance->adprecovery);
+
+ schedule_work(&instance->work_init);
+ return IRQ_HANDLED;
+
+ } else {
+ printk(KERN_NOTICE "megasas: fwstate:%x, dis_OCR=%x\n",
+ fw_state, instance->disableOnlineCtrlReset);
+ }
+ }
- if (instance->hw_crit_error)
- goto out_done;
- /*
- * Schedule the tasklet for cmd completion
- */
tasklet_schedule(&instance->isr_tasklet);
-out_done:
return IRQ_HANDLED;
}
-
/**
* megasas_isr - isr entry point
*/
static irqreturn_t megasas_isr(int irq, void *devp)
{
- return megasas_deplete_reply_queue((struct megasas_instance *)devp,
- DID_OK);
+ struct megasas_instance *instance;
+ unsigned long flags;
+ irqreturn_t rc;
+
+ if (atomic_read(
+ &(((struct megasas_instance *)devp)->fw_reset_no_pci_access)))
+ return IRQ_HANDLED;
+
+ instance = (struct megasas_instance *)devp;
+
+ spin_lock_irqsave(&instance->hba_lock, flags);
+ rc = megasas_deplete_reply_queue(instance, DID_OK);
+ spin_unlock_irqrestore(&instance->hba_lock, flags);
+
+ return rc;
}
/**
@@ -1972,7 +2530,7 @@ megasas_transition_to_ready(struct megasas_instance* instance)
"in %d secs\n", fw_state, max_wait);
return -ENODEV;
}
- };
+ }
printk(KERN_INFO "megasas: FW now in Ready state\n");
return 0;
@@ -2054,6 +2612,7 @@ static int megasas_create_frame_pool(struct megasas_instance *instance)
*/
sgl_sz = sge_sz * instance->max_num_sge;
frame_count = (sgl_sz + MEGAMFI_FRAME_SIZE - 1) / MEGAMFI_FRAME_SIZE;
+ frame_count = 15;
/*
* We need one extra frame for the MFI command
@@ -2201,6 +2760,7 @@ static int megasas_alloc_cmds(struct megasas_instance *instance)
cmd = instance->cmd_list[i];
memset(cmd, 0, sizeof(struct megasas_cmd));
cmd->index = i;
+ cmd->scmd = NULL;
cmd->instance = instance;
list_add_tail(&cmd->list, &instance->cmd_pool);
@@ -2368,7 +2928,7 @@ megasas_get_ld_list(struct megasas_instance *instance)
/* the following function will get the instance PD LIST */
- if ((ret == 0) && (ci->ldCount < MAX_LOGICAL_DRIVES)) {
+ if ((ret == 0) && (ci->ldCount <= MAX_LOGICAL_DRIVES)) {
memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS);
for (ld_index = 0; ld_index < ci->ldCount; ld_index++) {
@@ -2682,6 +3242,21 @@ static int megasas_init_mfi(struct megasas_instance *instance)
if (megasas_issue_init_mfi(instance))
goto fail_fw_init;
+ instance->fw_support_ieee = 0;
+ instance->fw_support_ieee =
+ (instance->instancet->read_fw_status_reg(reg_set) &
+ 0x04000000);
+
+ printk(KERN_NOTICE "megasas_init_mfi: fw_support_ieee=%d",
+ instance->fw_support_ieee);
+
+ if (instance->fw_support_ieee)
+ instance->flag_ieee = 1;
+
+ /** for passthrough
+ * the following function will get the PD LIST.
+ */
+
memset(instance->pd_list, 0 ,
(MEGASAS_MAX_PD * sizeof(struct megasas_pd_list)));
megasas_get_pd_list(instance);
@@ -2708,6 +3283,8 @@ static int megasas_init_mfi(struct megasas_instance *instance)
max_sectors_2 = ctrl_info->max_request_size;
tmp_sectors = min_t(u32, max_sectors_1 , max_sectors_2);
+ instance->disableOnlineCtrlReset =
+ ctrl_info->properties.OnOffProperties.disableOnlineCtrlReset;
}
instance->max_sectors_per_req = instance->max_num_sge *
@@ -2929,6 +3506,7 @@ megasas_register_aen(struct megasas_instance *instance, u32 seq_num,
dcmd->flags = MFI_FRAME_DIR_READ;
dcmd->timeout = 0;
dcmd->pad_0 = 0;
+ instance->last_seq_num = seq_num;
dcmd->data_xfer_len = sizeof(struct megasas_evt_detail);
dcmd->opcode = MR_DCMD_CTRL_EVENT_WAIT;
dcmd->mbox.w[0] = seq_num;
@@ -3097,6 +3675,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
instance = (struct megasas_instance *)host->hostdata;
memset(instance, 0, sizeof(*instance));
+ atomic_set( &instance->fw_reset_no_pci_access, 0 );
instance->producer = pci_alloc_consistent(pdev, sizeof(u32),
&instance->producer_h);
@@ -3114,6 +3693,9 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
megasas_poll_wait_aen = 0;
instance->flag_ieee = 0;
instance->ev = NULL;
+ instance->issuepend_done = 1;
+ instance->adprecovery = MEGASAS_HBA_OPERATIONAL;
+ megasas_poll_wait_aen = 0;
instance->evt_detail = pci_alloc_consistent(pdev,
sizeof(struct
@@ -3130,6 +3712,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
* Initialize locks and queues
*/
INIT_LIST_HEAD(&instance->cmd_pool);
+ INIT_LIST_HEAD(&instance->internal_reset_pending_q);
atomic_set(&instance->fw_outstanding,0);
@@ -3137,7 +3720,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
init_waitqueue_head(&instance->abort_cmd_wait_q);
spin_lock_init(&instance->cmd_pool_lock);
- spin_lock_init(&instance->fire_lock);
+ spin_lock_init(&instance->hba_lock);
spin_lock_init(&instance->completion_lock);
spin_lock_init(&poll_aen_lock);
@@ -3162,6 +3745,9 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
instance->flag = 0;
instance->unload = 1;
instance->last_time = 0;
+ instance->disableOnlineCtrlReset = 1;
+
+ INIT_WORK(&instance->work_init, process_fw_state_change_wq);
/*
* Initialize MFI Firmware
@@ -3253,6 +3839,9 @@ static void megasas_flush_cache(struct megasas_instance *instance)
struct megasas_cmd *cmd;
struct megasas_dcmd_frame *dcmd;
+ if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR)
+ return;
+
cmd = megasas_get_cmd(instance);
if (!cmd)
@@ -3290,6 +3879,9 @@ static void megasas_shutdown_controller(struct megasas_instance *instance,
struct megasas_cmd *cmd;
struct megasas_dcmd_frame *dcmd;
+ if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR)
+ return;
+
cmd = megasas_get_cmd(instance);
if (!cmd)
@@ -3557,7 +4149,6 @@ static void megasas_shutdown(struct pci_dev *pdev)
*/
static int megasas_mgmt_open(struct inode *inode, struct file *filep)
{
- cycle_kernel_lock();
/*
* Allow only those users with admin rights
*/
@@ -3781,6 +4372,9 @@ static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg)
struct megasas_iocpacket *ioc;
struct megasas_instance *instance;
int error;
+ int i;
+ unsigned long flags;
+ u32 wait_time = MEGASAS_RESET_WAIT_TIME;
ioc = kmalloc(sizeof(*ioc), GFP_KERNEL);
if (!ioc)
@@ -3797,8 +4391,8 @@ static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg)
goto out_kfree_ioc;
}
- if (instance->hw_crit_error == 1) {
- printk(KERN_DEBUG "Controller in Crit ERROR\n");
+ if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
+ printk(KERN_ERR "Controller in crit error\n");
error = -ENODEV;
goto out_kfree_ioc;
}
@@ -3815,6 +4409,35 @@ static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg)
error = -ERESTARTSYS;
goto out_kfree_ioc;
}
+
+ for (i = 0; i < wait_time; i++) {
+
+ spin_lock_irqsave(&instance->hba_lock, flags);
+ if (instance->adprecovery == MEGASAS_HBA_OPERATIONAL) {
+ spin_unlock_irqrestore(&instance->hba_lock, flags);
+ break;
+ }
+ spin_unlock_irqrestore(&instance->hba_lock, flags);
+
+ if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) {
+ printk(KERN_NOTICE "megasas: waiting"
+ "for controller reset to finish\n");
+ }
+
+ msleep(1000);
+ }
+
+ spin_lock_irqsave(&instance->hba_lock, flags);
+ if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) {
+ spin_unlock_irqrestore(&instance->hba_lock, flags);
+
+ printk(KERN_ERR "megaraid_sas: timed out while"
+ "waiting for HBA to recover\n");
+ error = -ENODEV;
+ goto out_kfree_ioc;
+ }
+ spin_unlock_irqrestore(&instance->hba_lock, flags);
+
error = megasas_mgmt_fw_ioctl(instance, user_ioc, ioc);
up(&instance->ioctl_sem);
@@ -3828,6 +4451,9 @@ static int megasas_mgmt_ioctl_aen(struct file *file, unsigned long arg)
struct megasas_instance *instance;
struct megasas_aen aen;
int error;
+ int i;
+ unsigned long flags;
+ u32 wait_time = MEGASAS_RESET_WAIT_TIME;
if (file->private_data != file) {
printk(KERN_DEBUG "megasas: fasync_helper was not "
@@ -3843,14 +4469,42 @@ static int megasas_mgmt_ioctl_aen(struct file *file, unsigned long arg)
if (!instance)
return -ENODEV;
- if (instance->hw_crit_error == 1) {
- error = -ENODEV;
+ if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
+ return -ENODEV;
}
if (instance->unload == 1) {
return -ENODEV;
}
+ for (i = 0; i < wait_time; i++) {
+
+ spin_lock_irqsave(&instance->hba_lock, flags);
+ if (instance->adprecovery == MEGASAS_HBA_OPERATIONAL) {
+ spin_unlock_irqrestore(&instance->hba_lock,
+ flags);
+ break;
+ }
+
+ spin_unlock_irqrestore(&instance->hba_lock, flags);
+
+ if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) {
+ printk(KERN_NOTICE "megasas: waiting for"
+ "controller reset to finish\n");
+ }
+
+ msleep(1000);
+ }
+
+ spin_lock_irqsave(&instance->hba_lock, flags);
+ if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) {
+ spin_unlock_irqrestore(&instance->hba_lock, flags);
+ printk(KERN_ERR "megaraid_sas: timed out while waiting"
+ "for HBA to recover.\n");
+ return -ENODEV;
+ }
+ spin_unlock_irqrestore(&instance->hba_lock, flags);
+
mutex_lock(&instance->aen_mutex);
error = megasas_register_aen(instance, aen.seq_num,
aen.class_locale_word);
@@ -3957,6 +4611,7 @@ static const struct file_operations megasas_mgmt_fops = {
#ifdef CONFIG_COMPAT
.compat_ioctl = megasas_mgmt_compat_ioctl,
#endif
+ .llseek = noop_llseek,
};
/*
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
index 9d8b6bf605aa..16a4f68a34b0 100644
--- a/drivers/scsi/megaraid/megaraid_sas.h
+++ b/drivers/scsi/megaraid/megaraid_sas.h
@@ -60,6 +60,7 @@
#define MFI_STATE_READY 0xB0000000
#define MFI_STATE_OPERATIONAL 0xC0000000
#define MFI_STATE_FAULT 0xF0000000
+#define MFI_RESET_REQUIRED 0x00000001
#define MEGAMFI_FRAME_SIZE 64
@@ -73,6 +74,12 @@
* HOTPLUG : Resume from Hotplug
* MFI_STOP_ADP : Send signal to FW to stop processing
*/
+#define WRITE_SEQUENCE_OFFSET (0x0000000FC) /* I20 */
+#define HOST_DIAGNOSTIC_OFFSET (0x000000F8) /* I20 */
+#define DIAG_WRITE_ENABLE (0x00000080)
+#define DIAG_RESET_ADAPTER (0x00000004)
+
+#define MFI_ADP_RESET 0x00000040
#define MFI_INIT_ABORT 0x00000001
#define MFI_INIT_READY 0x00000002
#define MFI_INIT_MFIMODE 0x00000004
@@ -402,8 +409,40 @@ struct megasas_ctrl_prop {
u16 ecc_bucket_leak_rate;
u8 restore_hotspare_on_insertion;
u8 expose_encl_devices;
- u8 reserved[38];
+ u8 maintainPdFailHistory;
+ u8 disallowHostRequestReordering;
+ u8 abortCCOnError;
+ u8 loadBalanceMode;
+ u8 disableAutoDetectBackplane;
+
+ u8 snapVDSpace;
+
+ /*
+ * Add properties that can be controlled by
+ * a bit in the following structure.
+ */
+ struct {
+ u32 copyBackDisabled : 1;
+ u32 SMARTerEnabled : 1;
+ u32 prCorrectUnconfiguredAreas : 1;
+ u32 useFdeOnly : 1;
+ u32 disableNCQ : 1;
+ u32 SSDSMARTerEnabled : 1;
+ u32 SSDPatrolReadEnabled : 1;
+ u32 enableSpinDownUnconfigured : 1;
+ u32 autoEnhancedImport : 1;
+ u32 enableSecretKeyControl : 1;
+ u32 disableOnlineCtrlReset : 1;
+ u32 allowBootWithPinnedCache : 1;
+ u32 disableSpinDownHS : 1;
+ u32 enableJBOD : 1;
+ u32 reserved :18;
+ } OnOffProperties;
+ u8 autoSnapVDSpace;
+ u8 viewSpace;
+ u16 spinDownTime;
+ u8 reserved[24];
} __packed;
/*
@@ -704,6 +743,12 @@ struct megasas_ctrl_info {
*/
#define IS_DMA64 (sizeof(dma_addr_t) == 8)
+#define MFI_XSCALE_OMR0_CHANGE_INTERRUPT 0x00000001
+
+#define MFI_INTR_FLAG_REPLY_MESSAGE 0x00000001
+#define MFI_INTR_FLAG_FIRMWARE_STATE_CHANGE 0x00000002
+#define MFI_G2_OUTBOUND_DOORBELL_CHANGE_INTERRUPT 0x00000004
+
#define MFI_OB_INTR_STATUS_MASK 0x00000002
#define MFI_POLL_TIMEOUT_SECS 60
#define MEGASAS_COMPLETION_TIMER_INTERVAL (HZ/10)
@@ -714,6 +759,9 @@ struct megasas_ctrl_info {
#define MFI_REPLY_SKINNY_MESSAGE_INTERRUPT 0x40000000
#define MFI_SKINNY_ENABLE_INTERRUPT_MASK (0x00000001)
+#define MFI_1068_PCSR_OFFSET 0x84
+#define MFI_1068_FW_HANDSHAKE_OFFSET 0x64
+#define MFI_1068_FW_READY 0xDDDD0000
/*
* register set for both 1068 and 1078 controllers
* structure extended for 1078 registers
@@ -755,8 +803,10 @@ struct megasas_register_set {
u32 inbound_high_queue_port ; /*00C4h*/
u32 reserved_5; /*00C8h*/
- u32 index_registers[820]; /*00CCh*/
-
+ u32 res_6[11]; /*CCh*/
+ u32 host_diag;
+ u32 seq_offset;
+ u32 index_registers[807]; /*00CCh*/
} __attribute__ ((packed));
struct megasas_sge32 {
@@ -1226,11 +1276,12 @@ struct megasas_instance {
struct megasas_cmd **cmd_list;
struct list_head cmd_pool;
+ /* used to sync fire the cmd to fw */
spinlock_t cmd_pool_lock;
+ /* used to sync fire the cmd to fw */
+ spinlock_t hba_lock;
/* used to synch producer, consumer ptrs in dpc */
spinlock_t completion_lock;
- /* used to sync fire the cmd to fw */
- spinlock_t fire_lock;
struct dma_pool *frame_dma_pool;
struct dma_pool *sense_dma_pool;
@@ -1247,19 +1298,36 @@ struct megasas_instance {
struct pci_dev *pdev;
u32 unique_id;
+ u32 fw_support_ieee;
atomic_t fw_outstanding;
- u32 hw_crit_error;
+ atomic_t fw_reset_no_pci_access;
struct megasas_instance_template *instancet;
struct tasklet_struct isr_tasklet;
+ struct work_struct work_init;
u8 flag;
u8 unload;
u8 flag_ieee;
+ u8 issuepend_done;
+ u8 disableOnlineCtrlReset;
+ u8 adprecovery;
unsigned long last_time;
+ u32 mfiStatus;
+ u32 last_seq_num;
struct timer_list io_completion_timer;
+ struct list_head internal_reset_pending_q;
+};
+
+enum {
+ MEGASAS_HBA_OPERATIONAL = 0,
+ MEGASAS_ADPRESET_SM_INFAULT = 1,
+ MEGASAS_ADPRESET_SM_FW_RESET_SUCCESS = 2,
+ MEGASAS_ADPRESET_SM_OPERATIONAL = 3,
+ MEGASAS_HW_CRITICAL_ERROR = 4,
+ MEGASAS_ADPRESET_INPROG_SIGN = 0xDEADDEAD,
};
struct megasas_instance_template {
@@ -1272,6 +1340,10 @@ struct megasas_instance_template {
int (*clear_intr)(struct megasas_register_set __iomem *);
u32 (*read_fw_status_reg)(struct megasas_register_set __iomem *);
+ int (*adp_reset)(struct megasas_instance *, \
+ struct megasas_register_set __iomem *);
+ int (*check_reset)(struct megasas_instance *, \
+ struct megasas_register_set __iomem *);
};
#define MEGASAS_IS_LOGICAL(scp) \
@@ -1291,7 +1363,9 @@ struct megasas_cmd {
u32 index;
u8 sync_cmd;
u8 cmd_status;
- u16 abort_aen;
+ u8 abort_aen;
+ u8 retry_for_fw_reset;
+
struct list_head list;
struct scsi_cmnd *scmd;
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c
index 57bcd5c9dcff..12faf64f91b0 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.c
@@ -534,7 +534,7 @@ _base_display_event_data(struct MPT2SAS_ADAPTER *ioc,
if (event_data->DiscoveryStatus)
printk("discovery_status(0x%08x)",
le32_to_cpu(event_data->DiscoveryStatus));
- printk("\n");
+ printk("\n");
return;
}
case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
index b774973f0765..40cb8aeb21b1 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
@@ -51,7 +51,7 @@
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/delay.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/compat.h>
#include <linux/poll.h>
@@ -61,6 +61,7 @@
#include "mpt2sas_base.h"
#include "mpt2sas_ctl.h"
+static DEFINE_MUTEX(_ctl_mutex);
static struct fasync_struct *async_queue;
static DECLARE_WAIT_QUEUE_HEAD(ctl_poll_wait);
@@ -2238,9 +2239,9 @@ _ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
long ret;
- lock_kernel();
+ mutex_lock(&_ctl_mutex);
ret = _ctl_ioctl_main(file, cmd, (void __user *)arg);
- unlock_kernel();
+ mutex_unlock(&_ctl_mutex);
return ret;
}
@@ -2309,12 +2310,12 @@ _ctl_ioctl_compat(struct file *file, unsigned cmd, unsigned long arg)
{
long ret;
- lock_kernel();
+ mutex_lock(&_ctl_mutex);
if (cmd == MPT2COMMAND32)
ret = _ctl_compat_mpt_command(file, cmd, arg);
else
ret = _ctl_ioctl_main(file, cmd, (void __user *)arg);
- unlock_kernel();
+ mutex_unlock(&_ctl_mutex);
return ret;
}
#endif
@@ -2952,6 +2953,7 @@ static const struct file_operations ctl_fops = {
#ifdef CONFIG_COMPAT
.compat_ioctl = _ctl_ioctl_compat,
#endif
+ .llseek = noop_llseek,
};
static struct miscdevice ctl_dev = {
diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c
index ffdd9fdb9995..b31a8e3841d7 100644
--- a/drivers/scsi/osd/osd_uld.c
+++ b/drivers/scsi/osd/osd_uld.c
@@ -182,6 +182,7 @@ static const struct file_operations osd_fops = {
.open = osd_uld_open,
.release = osd_uld_release,
.unlocked_ioctl = osd_uld_ioctl,
+ .llseek = noop_llseek,
};
struct osd_dev *osduld_path_lookup(const char *name)
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c
index 278b352ae78d..54de1d1af1a7 100644
--- a/drivers/scsi/osst.c
+++ b/drivers/scsi/osst.c
@@ -51,7 +51,7 @@ static const char * osst_version = "0.99.4";
#include <linux/moduleparam.h>
#include <linux/delay.h>
#include <linux/jiffies.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <asm/uaccess.h>
#include <asm/dma.h>
#include <asm/system.h>
@@ -80,6 +80,7 @@ static const char * osst_version = "0.99.4";
#include "osst_options.h"
#include "osst_detect.h"
+static DEFINE_MUTEX(osst_int_mutex);
static int max_dev = 0;
static int write_threshold_kbs = 0;
static int max_sg_segs = 0;
@@ -4807,9 +4808,9 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp)
{
int ret;
- lock_kernel();
+ mutex_lock(&osst_int_mutex);
ret = __os_scsi_tape_open(inode, filp);
- unlock_kernel();
+ mutex_unlock(&osst_int_mutex);
return ret;
}
@@ -4943,9 +4944,9 @@ static long osst_ioctl(struct file * file,
char * name = tape_name(STp);
void __user * p = (void __user *)arg;
- lock_kernel();
+ mutex_lock(&osst_int_mutex);
if (mutex_lock_interruptible(&STp->lock)) {
- unlock_kernel();
+ mutex_unlock(&osst_int_mutex);
return -ERESTARTSYS;
}
@@ -5260,14 +5261,14 @@ static long osst_ioctl(struct file * file,
mutex_unlock(&STp->lock);
retval = scsi_ioctl(STp->device, cmd_in, p);
- unlock_kernel();
+ mutex_unlock(&osst_int_mutex);
return retval;
out:
if (SRpnt) osst_release_request(SRpnt);
mutex_unlock(&STp->lock);
- unlock_kernel();
+ mutex_unlock(&osst_int_mutex);
return retval;
}
diff --git a/drivers/scsi/pcmcia/Kconfig b/drivers/scsi/pcmcia/Kconfig
index 53857c6b6d4d..ecc855c550aa 100644
--- a/drivers/scsi/pcmcia/Kconfig
+++ b/drivers/scsi/pcmcia/Kconfig
@@ -11,7 +11,6 @@ if SCSI_LOWLEVEL_PCMCIA && SCSI && PCMCIA && m
config PCMCIA_AHA152X
tristate "Adaptec AHA152X PCMCIA support"
- depends on !64BIT
select SCSI_SPI_ATTRS
help
Say Y here if you intend to attach this type of PCMCIA SCSI host
diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c
index 61f49bdcc0c2..e77dd02eccdd 100644
--- a/drivers/scsi/pcmcia/aha152x_stub.c
+++ b/drivers/scsi/pcmcia/aha152x_stub.c
@@ -49,7 +49,6 @@
#include <scsi/scsi_host.h>
#include "aha152x.h"
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
@@ -86,8 +85,6 @@ static void aha152x_release_cs(struct pcmcia_device *link);
static void aha152x_detach(struct pcmcia_device *p_dev);
static int aha152x_config_cs(struct pcmcia_device *link);
-static struct pcmcia_device *dev_list;
-
static int aha152x_probe(struct pcmcia_device *link)
{
scsi_info_t *info;
@@ -100,11 +97,8 @@ static int aha152x_probe(struct pcmcia_device *link)
info->p_dev = link;
link->priv = info;
- link->resource[0]->end = 0x20;
- link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
- link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.IntType = INT_MEMORY_AND_IO;
- link->conf.Present = PRESENT_OPTION;
+ link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+ link->config_regs = PRESENT_OPTION;
return aha152x_config_cs(link);
} /* aha152x_attach */
@@ -123,25 +117,24 @@ static void aha152x_detach(struct pcmcia_device *link)
/*====================================================================*/
-static int aha152x_config_check(struct pcmcia_device *p_dev,
- cistpl_cftable_entry_t *cfg,
- cistpl_cftable_entry_t *dflt,
- unsigned int vcc,
- void *priv_data)
+static int aha152x_config_check(struct pcmcia_device *p_dev, void *priv_data)
{
p_dev->io_lines = 10;
+
/* For New Media T&J, look for a SCSI window */
- if (cfg->io.win[0].len >= 0x20)
- p_dev->resource[0]->start = cfg->io.win[0].base;
- else if ((cfg->io.nwin > 1) &&
- (cfg->io.win[1].len >= 0x20))
- p_dev->resource[0]->start = cfg->io.win[1].base;
- if ((cfg->io.nwin > 0) &&
- (p_dev->resource[0]->start < 0xffff)) {
- if (!pcmcia_request_io(p_dev))
- return 0;
- }
- return -EINVAL;
+ if ((p_dev->resource[0]->end < 0x20) &&
+ (p_dev->resource[1]->end >= 0x20))
+ p_dev->resource[0]->start = p_dev->resource[1]->start;
+
+ if (p_dev->resource[0]->start >= 0xffff)
+ return -EINVAL;
+
+ p_dev->resource[1]->start = p_dev->resource[1]->end = 0;
+ p_dev->resource[0]->end = 0x20;
+ p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+ p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
+
+ return pcmcia_request_io(p_dev);
}
static int aha152x_config_cs(struct pcmcia_device *link)
@@ -160,7 +153,7 @@ static int aha152x_config_cs(struct pcmcia_device *link)
if (!link->irq)
goto failed;
- ret = pcmcia_request_configuration(link, &link->conf);
+ ret = pcmcia_enable_device(link);
if (ret)
goto failed;
@@ -221,9 +214,7 @@ MODULE_DEVICE_TABLE(pcmcia, aha152x_ids);
static struct pcmcia_driver aha152x_cs_driver = {
.owner = THIS_MODULE,
- .drv = {
- .name = "aha152x_cs",
- },
+ .name = "aha152x_cs",
.probe = aha152x_probe,
.remove = aha152x_detach,
.id_table = aha152x_ids,
@@ -238,7 +229,6 @@ static int __init init_aha152x_cs(void)
static void __exit exit_aha152x_cs(void)
{
pcmcia_unregister_driver(&aha152x_cs_driver);
- BUG_ON(dev_list != NULL);
}
module_init(init_aha152x_cs);
diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c
index 13dbe5c48492..cd69c2670f81 100644
--- a/drivers/scsi/pcmcia/fdomain_stub.c
+++ b/drivers/scsi/pcmcia/fdomain_stub.c
@@ -46,7 +46,6 @@
#include <scsi/scsi_host.h>
#include "fdomain.h"
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
@@ -83,11 +82,8 @@ static int fdomain_probe(struct pcmcia_device *link)
info->p_dev = link;
link->priv = info;
- link->resource[0]->end = 0x10;
- link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
- link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.IntType = INT_MEMORY_AND_IO;
- link->conf.Present = PRESENT_OPTION;
+ link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+ link->config_regs = PRESENT_OPTION;
return fdomain_config(link);
} /* fdomain_attach */
@@ -105,14 +101,12 @@ static void fdomain_detach(struct pcmcia_device *link)
/*====================================================================*/
-static int fdomain_config_check(struct pcmcia_device *p_dev,
- cistpl_cftable_entry_t *cfg,
- cistpl_cftable_entry_t *dflt,
- unsigned int vcc,
- void *priv_data)
+static int fdomain_config_check(struct pcmcia_device *p_dev, void *priv_data)
{
p_dev->io_lines = 10;
- p_dev->resource[0]->start = cfg->io.win[0].base;
+ p_dev->resource[0]->end = 0x10;
+ p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+ p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
return pcmcia_request_io(p_dev);
}
@@ -132,7 +126,7 @@ static int fdomain_config(struct pcmcia_device *link)
if (!link->irq)
goto failed;
- ret = pcmcia_request_configuration(link, &link->conf);
+ ret = pcmcia_enable_device(link);
if (ret)
goto failed;
@@ -194,9 +188,7 @@ MODULE_DEVICE_TABLE(pcmcia, fdomain_ids);
static struct pcmcia_driver fdomain_cs_driver = {
.owner = THIS_MODULE,
- .drv = {
- .name = "fdomain_cs",
- },
+ .name = "fdomain_cs",
.probe = fdomain_probe,
.remove = fdomain_detach,
.id_table = fdomain_ids,
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
index dd9b40306f3d..9326c2c14880 100644
--- a/drivers/scsi/pcmcia/nsp_cs.c
+++ b/drivers/scsi/pcmcia/nsp_cs.c
@@ -47,7 +47,6 @@
#include <scsi/scsi.h>
#include <scsi/scsi_ioctl.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/ds.h>
@@ -1531,15 +1530,6 @@ static int nsp_eh_host_reset(struct scsi_cmnd *SCpnt)
PCMCIA functions
**********************************************************************/
-/*======================================================================
- nsp_cs_attach() creates an "instance" of the driver, allocating
- local data structures for one device. The device is registered
- with Card Services.
-
- The dev_link structure is initialized, but we don't actually
- configure the card at this point -- we wait until we receive a
- card insertion event.
-======================================================================*/
static int nsp_cs_probe(struct pcmcia_device *link)
{
scsi_info_t *info;
@@ -1557,14 +1547,6 @@ static int nsp_cs_probe(struct pcmcia_device *link)
nsp_dbg(NSP_DEBUG_INIT, "info=0x%p", info);
- /* The io structure describes IO port mapping */
- link->resource[0]->end = 0x10;
- link->resource[0]->flags = IO_DATA_PATH_WIDTH_AUTO;
-
- /* General socket configuration */
- link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.IntType = INT_MEMORY_AND_IO;
-
ret = nsp_cs_config(link);
nsp_dbg(NSP_DEBUG_INIT, "link=0x%p", link);
@@ -1572,12 +1554,6 @@ static int nsp_cs_probe(struct pcmcia_device *link)
} /* nsp_cs_attach */
-/*======================================================================
- This deletes a driver "instance". The device is de-registered
- with Card Services. If it has been released, all local data
- structures are freed. Otherwise, the structures will be freed
- when the device is released.
-======================================================================*/
static void nsp_cs_detach(struct pcmcia_device *link)
{
nsp_dbg(NSP_DEBUG_INIT, "in, link=0x%p", link);
@@ -1590,98 +1566,36 @@ static void nsp_cs_detach(struct pcmcia_device *link)
} /* nsp_cs_detach */
-/*======================================================================
- nsp_cs_config() is scheduled to run after a CARD_INSERTION event
- is received, to configure the PCMCIA socket, and to make the
- ethernet device available to the system.
-======================================================================*/
-
-struct nsp_cs_configdata {
- nsp_hw_data *data;
- win_req_t req;
-};
-
-static int nsp_cs_config_check(struct pcmcia_device *p_dev,
- cistpl_cftable_entry_t *cfg,
- cistpl_cftable_entry_t *dflt,
- unsigned int vcc,
- void *priv_data)
+static int nsp_cs_config_check(struct pcmcia_device *p_dev, void *priv_data)
{
- struct nsp_cs_configdata *cfg_mem = priv_data;
+ nsp_hw_data *data = priv_data;
- if (cfg->index == 0)
+ if (p_dev->config_index == 0)
return -ENODEV;
- /* Does this card need audio output? */
- if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
- p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
- p_dev->conf.Status = CCSR_AUDIO_ENA;
- }
-
- /* Use power settings for Vcc and Vpp if present */
- /* Note that the CIS values need to be rescaled */
- if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {
- if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM]/10000)
- return -ENODEV;
- else if (dflt->vcc.present & (1<<CISTPL_POWER_VNOM)) {
- if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM]/10000)
- return -ENODEV;
- }
-
- if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) {
- p_dev->conf.Vpp =
- cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
- } else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM)) {
- p_dev->conf.Vpp =
- dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
- }
-
- /* Do we need to allocate an interrupt? */
- p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
-
- /* IO window settings */
- p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
- if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
- cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
- p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
- p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
- p_dev->resource[0]->flags |=
- pcmcia_io_cfg_data_width(io->flags);
- p_dev->resource[0]->start = io->win[0].base;
- p_dev->resource[0]->end = io->win[0].len;
- if (io->nwin > 1) {
- p_dev->resource[1]->flags =
- p_dev->resource[0]->flags;
- p_dev->resource[1]->start = io->win[1].base;
- p_dev->resource[1]->end = io->win[1].len;
- }
- /* This reserves IO space but doesn't actually enable it */
- if (pcmcia_request_io(p_dev) != 0)
- goto next_entry;
- }
-
- if ((cfg->mem.nwin > 0) || (dflt->mem.nwin > 0)) {
- cistpl_mem_t *mem =
- (cfg->mem.nwin) ? &cfg->mem : &dflt->mem;
- cfg_mem->req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM;
- cfg_mem->req.Attributes |= WIN_ENABLE;
- cfg_mem->req.Base = mem->win[0].host_addr;
- cfg_mem->req.Size = mem->win[0].len;
- if (cfg_mem->req.Size < 0x1000)
- cfg_mem->req.Size = 0x1000;
- cfg_mem->req.AccessSpeed = 0;
- if (pcmcia_request_window(p_dev, &cfg_mem->req, &p_dev->win) != 0)
- goto next_entry;
- if (pcmcia_map_mem_page(p_dev, p_dev->win,
- mem->win[0].card_addr) != 0)
- goto next_entry;
-
- cfg_mem->data->MmioAddress = (unsigned long) ioremap_nocache(cfg_mem->req.Base, cfg_mem->req.Size);
- cfg_mem->data->MmioLength = cfg_mem->req.Size;
- }
- /* If we got this far, we're cool! */
- return 0;
+ /* This reserves IO space but doesn't actually enable it */
+ if (pcmcia_request_io(p_dev) != 0)
+ goto next_entry;
+
+ if (resource_size(p_dev->resource[2])) {
+ p_dev->resource[2]->flags |= (WIN_DATA_WIDTH_16 |
+ WIN_MEMORY_TYPE_CM |
+ WIN_ENABLE);
+ if (p_dev->resource[2]->end < 0x1000)
+ p_dev->resource[2]->end = 0x1000;
+ if (pcmcia_request_window(p_dev, p_dev->resource[2], 0) != 0)
+ goto next_entry;
+ if (pcmcia_map_mem_page(p_dev, p_dev->resource[2],
+ p_dev->card_addr) != 0)
+ goto next_entry;
+
+ data->MmioAddress = (unsigned long)
+ ioremap_nocache(p_dev->resource[2]->start,
+ resource_size(p_dev->resource[2]));
+ data->MmioLength = resource_size(p_dev->resource[2]);
}
+ /* If we got this far, we're cool! */
+ return 0;
next_entry:
nsp_dbg(NSP_DEBUG_INIT, "next");
@@ -1693,25 +1607,23 @@ static int nsp_cs_config(struct pcmcia_device *link)
{
int ret;
scsi_info_t *info = link->priv;
- struct nsp_cs_configdata *cfg_mem;
struct Scsi_Host *host;
nsp_hw_data *data = &nsp_data_base;
nsp_dbg(NSP_DEBUG_INIT, "in");
- cfg_mem = kzalloc(sizeof(*cfg_mem), GFP_KERNEL);
- if (!cfg_mem)
- return -ENOMEM;
- cfg_mem->data = data;
+ link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_CHECK_VCC |
+ CONF_AUTO_SET_VPP | CONF_AUTO_AUDIO | CONF_AUTO_SET_IOMEM |
+ CONF_AUTO_SET_IO;
- ret = pcmcia_loop_config(link, nsp_cs_config_check, cfg_mem);
+ ret = pcmcia_loop_config(link, nsp_cs_config_check, data);
if (ret)
goto cs_failed;
if (pcmcia_request_irq(link, nspintr))
goto cs_failed;
- ret = pcmcia_request_configuration(link, &link->conf);
+ ret = pcmcia_enable_device(link);
if (ret)
goto cs_failed;
@@ -1754,41 +1666,16 @@ static int nsp_cs_config(struct pcmcia_device *link)
info->host = host;
- /* Finally, report what we've done */
- printk(KERN_INFO "nsp_cs: index 0x%02x: ",
- link->conf.ConfigIndex);
- if (link->conf.Vpp) {
- printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10);
- }
- if (link->conf.Attributes & CONF_ENABLE_IRQ) {
- printk(", irq %d", link->irq);
- }
- if (link->resource[0])
- printk(", io %pR", link->resource[0]);
- if (link->resource[1])
- printk(" & %pR", link->resource[1]);
- if (link->win)
- printk(", mem 0x%06lx-0x%06lx", cfg_mem->req.Base,
- cfg_mem->req.Base+cfg_mem->req.Size-1);
- printk("\n");
-
- kfree(cfg_mem);
return 0;
cs_failed:
nsp_dbg(NSP_DEBUG_INIT, "config fail");
nsp_cs_release(link);
- kfree(cfg_mem);
return -ENODEV;
} /* nsp_cs_config */
-/*======================================================================
- After a card is removed, nsp_cs_release() will unregister the net
- device, and release the PCMCIA configuration. If the device is
- still open, this will be postponed until it is closed.
-======================================================================*/
static void nsp_cs_release(struct pcmcia_device *link)
{
scsi_info_t *info = link->priv;
@@ -1807,7 +1694,7 @@ static void nsp_cs_release(struct pcmcia_device *link)
scsi_remove_host(info->host);
}
- if (link->win) {
+ if (resource_size(link->resource[2])) {
if (data != NULL) {
iounmap((void *)(data->MmioAddress));
}
@@ -1877,9 +1764,7 @@ MODULE_DEVICE_TABLE(pcmcia, nsp_cs_ids);
static struct pcmcia_driver nsp_driver = {
.owner = THIS_MODULE,
- .drv = {
- .name = "nsp_cs",
- },
+ .name = "nsp_cs",
.probe = nsp_cs_probe,
.remove = nsp_cs_detach,
.id_table = nsp_cs_ids,
@@ -1889,14 +1774,11 @@ static struct pcmcia_driver nsp_driver = {
static int __init nsp_cs_init(void)
{
- nsp_msg(KERN_INFO, "loading...");
-
return pcmcia_register_driver(&nsp_driver);
}
static void __exit nsp_cs_exit(void)
{
- nsp_msg(KERN_INFO, "unloading...");
pcmcia_unregister_driver(&nsp_driver);
}
diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c
index eb775f1a523c..9c96ca889ec9 100644
--- a/drivers/scsi/pcmcia/qlogic_stub.c
+++ b/drivers/scsi/pcmcia/qlogic_stub.c
@@ -48,7 +48,6 @@
#include <scsi/scsi_host.h>
#include "../qlogicfas408.h"
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
#include <pcmcia/ciscode.h>
@@ -156,11 +155,8 @@ static int qlogic_probe(struct pcmcia_device *link)
return -ENOMEM;
info->p_dev = link;
link->priv = info;
- link->resource[0]->end = 16;
- link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
- link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.IntType = INT_MEMORY_AND_IO;
- link->conf.Present = PRESENT_OPTION;
+ link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+ link->config_regs = PRESENT_OPTION;
return qlogic_config(link);
} /* qlogic_attach */
@@ -178,15 +174,11 @@ static void qlogic_detach(struct pcmcia_device *link)
/*====================================================================*/
-static int qlogic_config_check(struct pcmcia_device *p_dev,
- cistpl_cftable_entry_t *cfg,
- cistpl_cftable_entry_t *dflt,
- unsigned int vcc,
- void *priv_data)
+static int qlogic_config_check(struct pcmcia_device *p_dev, void *priv_data)
{
p_dev->io_lines = 10;
- p_dev->resource[0]->start = cfg->io.win[0].base;
- p_dev->resource[0]->end = cfg->io.win[0].len;
+ p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+ p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
if (p_dev->resource[0]->start == 0)
return -ENODEV;
@@ -209,7 +201,7 @@ static int qlogic_config(struct pcmcia_device * link)
if (!link->irq)
goto failed;
- ret = pcmcia_request_configuration(link, &link->conf);
+ ret = pcmcia_enable_device(link);
if (ret)
goto failed;
@@ -264,7 +256,7 @@ static int qlogic_resume(struct pcmcia_device *link)
{
scsi_info_t *info = link->priv;
- pcmcia_request_configuration(link, &link->conf);
+ pcmcia_enable_device(link);
if ((info->manf_id == MANFID_MACNICA) ||
(info->manf_id == MANFID_PIONEER) ||
(info->manf_id == 0x0098)) {
@@ -302,9 +294,7 @@ MODULE_DEVICE_TABLE(pcmcia, qlogic_ids);
static struct pcmcia_driver qlogic_cs_driver = {
.owner = THIS_MODULE,
- .drv = {
.name = "qlogic_cs",
- },
.probe = qlogic_probe,
.remove = qlogic_detach,
.id_table = qlogic_ids,
diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c
index 321e390c9120..0ae27cb5cd6f 100644
--- a/drivers/scsi/pcmcia/sym53c500_cs.c
+++ b/drivers/scsi/pcmcia/sym53c500_cs.c
@@ -71,7 +71,6 @@
#include <scsi/scsi.h>
#include <scsi/scsi_host.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
#include <pcmcia/ciscode.h>
@@ -684,15 +683,11 @@ static struct scsi_host_template sym53c500_driver_template = {
.shost_attrs = SYM53C500_shost_attrs
};
-static int SYM53C500_config_check(struct pcmcia_device *p_dev,
- cistpl_cftable_entry_t *cfg,
- cistpl_cftable_entry_t *dflt,
- unsigned int vcc,
- void *priv_data)
+static int SYM53C500_config_check(struct pcmcia_device *p_dev, void *priv_data)
{
p_dev->io_lines = 10;
- p_dev->resource[0]->start = cfg->io.win[0].base;
- p_dev->resource[0]->end = cfg->io.win[0].len;
+ p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+ p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
if (p_dev->resource[0]->start == 0)
return -ENODEV;
@@ -721,7 +716,7 @@ SYM53C500_config(struct pcmcia_device *link)
if (!link->irq)
goto failed;
- ret = pcmcia_request_configuration(link, &link->conf);
+ ret = pcmcia_enable_device(link);
if (ret)
goto failed;
@@ -859,10 +854,7 @@ SYM53C500_probe(struct pcmcia_device *link)
return -ENOMEM;
info->p_dev = link;
link->priv = info;
- link->resource[0]->end = 16;
- link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
- link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.IntType = INT_MEMORY_AND_IO;
+ link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
return SYM53C500_config(link);
} /* SYM53C500_attach */
@@ -881,9 +873,7 @@ MODULE_DEVICE_TABLE(pcmcia, sym53c500_ids);
static struct pcmcia_driver sym53c500_cs_driver = {
.owner = THIS_MODULE,
- .drv = {
- .name = "sym53c500_cs",
- },
+ .name = "sym53c500_cs",
.probe = SYM53C500_probe,
.remove = SYM53C500_detach,
.id_table = sym53c500_ids,
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 9793aa6afb10..d8db0137c0c7 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -4194,6 +4194,8 @@ static int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha,
nvmd_type = ioctl_payload->minor_function;
fw_control_context = kzalloc(sizeof(struct fw_control_ex), GFP_KERNEL);
+ if (!fw_control_context)
+ return -ENOMEM;
fw_control_context->usrAddr = (u8 *)&ioctl_payload->func_specific[0];
fw_control_context->len = ioctl_payload->length;
circularQ = &pm8001_ha->inbnd_q_tbl[0];
@@ -4272,6 +4274,8 @@ static int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha,
nvmd_type = ioctl_payload->minor_function;
fw_control_context = kzalloc(sizeof(struct fw_control_ex), GFP_KERNEL);
+ if (!fw_control_context)
+ return -ENOMEM;
circularQ = &pm8001_ha->inbnd_q_tbl[0];
memcpy(pm8001_ha->memoryMap.region[NVMD].virt_ptr,
ioctl_payload->func_specific,
@@ -4381,6 +4385,8 @@ pm8001_chip_fw_flash_update_req(struct pm8001_hba_info *pm8001_ha,
struct pm8001_ioctl_payload *ioctl_payload = payload;
fw_control_context = kzalloc(sizeof(struct fw_control_ex), GFP_KERNEL);
+ if (!fw_control_context)
+ return -ENOMEM;
fw_control = (struct fw_control_info *)&ioctl_payload->func_specific[0];
if (fw_control->len != 0) {
if (pm8001_mem_alloc(pm8001_ha->pdev,
diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c
index ecc45c8b4e6b..4b8765785aeb 100644
--- a/drivers/scsi/pmcraid.c
+++ b/drivers/scsi/pmcraid.c
@@ -4165,6 +4165,7 @@ static const struct file_operations pmcraid_fops = {
#ifdef CONFIG_COMPAT
.compat_ioctl = pmcraid_chr_ioctl,
#endif
+ .llseek = noop_llseek,
};
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 114bc5a81171..2ff4342ae362 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -1538,22 +1538,22 @@ qla2x00_dev_loss_tmo_callbk(struct fc_rport *rport)
if (!fcport)
return;
- if (test_bit(ABORT_ISP_ACTIVE, &fcport->vha->dpc_flags))
- return;
-
- if (unlikely(pci_channel_offline(fcport->vha->hw->pdev))) {
- qla2x00_abort_all_cmds(fcport->vha, DID_NO_CONNECT << 16);
- return;
- }
-
/*
* Transport has effectively 'deleted' the rport, clear
* all local references.
*/
spin_lock_irq(host->host_lock);
- fcport->rport = NULL;
+ fcport->rport = fcport->drport = NULL;
*((fc_port_t **)rport->dd_data) = NULL;
spin_unlock_irq(host->host_lock);
+
+ if (test_bit(ABORT_ISP_ACTIVE, &fcport->vha->dpc_flags))
+ return;
+
+ if (unlikely(pci_channel_offline(fcport->vha->hw->pdev))) {
+ qla2x00_abort_all_cmds(fcport->vha, DID_NO_CONNECT << 16);
+ return;
+ }
}
static void
@@ -1676,14 +1676,14 @@ static void
qla2x00_get_host_fabric_name(struct Scsi_Host *shost)
{
scsi_qla_host_t *vha = shost_priv(shost);
- u64 node_name;
+ uint8_t node_name[WWN_SIZE] = { 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF};
+ u64 fabric_name = wwn_to_u64(node_name);
if (vha->device_flags & SWITCH_FOUND)
- node_name = wwn_to_u64(vha->fabric_node_name);
- else
- node_name = wwn_to_u64(vha->node_name);
+ fabric_name = wwn_to_u64(vha->fabric_node_name);
- fc_host_fabric_name(shost) = node_name;
+ fc_host_fabric_name(shost) = fabric_name;
}
static void
@@ -1776,6 +1776,7 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
}
/* initialize attributes */
+ fc_host_dev_loss_tmo(vha->host) = ha->port_down_retry_count;
fc_host_node_name(vha->host) = wwn_to_u64(vha->node_name);
fc_host_port_name(vha->host) = wwn_to_u64(vha->port_name);
fc_host_supported_classes(vha->host) =
@@ -1984,6 +1985,7 @@ qla2x00_init_host_attr(scsi_qla_host_t *vha)
struct qla_hw_data *ha = vha->hw;
u32 speed = FC_PORTSPEED_UNKNOWN;
+ fc_host_dev_loss_tmo(vha->host) = ha->port_down_retry_count;
fc_host_node_name(vha->host) = wwn_to_u64(vha->node_name);
fc_host_port_name(vha->host) = wwn_to_u64(vha->port_name);
fc_host_supported_classes(vha->host) = FC_COS_CLASS3;
diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
index 9067629817ea..fdfbf83a6330 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.c
+++ b/drivers/scsi/qla2xxx/qla_bsg.c
@@ -1254,10 +1254,9 @@ qla24xx_iidma(struct fc_bsg_job *bsg_job)
return -EINVAL;
}
- if (fcport->loop_id == FC_NO_LOOP_ID) {
- DEBUG2(printk(KERN_ERR "%s(%ld): Invalid port loop id, "
- "loop_id = 0x%x\n",
- __func__, vha->host_no, fcport->loop_id));
+ if (atomic_read(&fcport->state) != FCS_ONLINE) {
+ DEBUG2(printk(KERN_ERR "%s(%ld): Port not online\n",
+ __func__, vha->host_no));
return -EINVAL;
}
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index d2a4e1530708..e1d3ad40a946 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -706,6 +706,11 @@ typedef struct {
#define MBC_SET_PORT_CONFIG 0x122 /* Set port configuration */
#define MBC_GET_PORT_CONFIG 0x123 /* Get port configuration */
+/*
+ * ISP81xx mailbox commands
+ */
+#define MBC_WRITE_MPI_REGISTER 0x01 /* Write MPI Register. */
+
/* Firmware return data sizes */
#define FCAL_MAP_SIZE 128
@@ -2860,6 +2865,7 @@ typedef struct scsi_qla_host {
#define NPIV_CONFIG_NEEDED 16
#define ISP_UNRECOVERABLE 17
#define FCOE_CTX_RESET_NEEDED 18 /* Initiate FCoE context reset */
+#define MPI_RESET_NEEDED 19 /* Initiate MPI FW reset */
uint32_t device_flags;
#define SWITCH_FOUND BIT_0
@@ -3003,6 +3009,8 @@ typedef struct scsi_qla_host {
#define CMD_SP(Cmnd) ((Cmnd)->SCp.ptr)
+#define QLA_SG_ALL 1024
+
enum nexus_wait_type {
WAIT_HOST = 0,
WAIT_TARGET,
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 1a1b281cea33..c33dec827e1e 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -352,6 +352,8 @@ qla2x00_read_ram_word(scsi_qla_host_t *, uint32_t, uint32_t *);
extern int
qla2x00_write_ram_word(scsi_qla_host_t *, uint32_t, uint32_t);
+extern int
+qla81xx_write_mpi_register(scsi_qla_host_t *, uint16_t *);
extern int qla2x00_get_data_rate(scsi_qla_host_t *);
extern int qla24xx_set_fcp_prio(scsi_qla_host_t *, uint16_t, uint16_t,
uint16_t *);
@@ -501,7 +503,6 @@ extern void qla24xx_wrt_rsp_reg(struct qla_hw_data *, uint16_t, uint16_t);
/* PCI related functions */
extern int qla82xx_pci_config(struct scsi_qla_host *);
extern int qla82xx_pci_mem_read_2M(struct qla_hw_data *, u64, void *, int);
-extern int qla82xx_pci_mem_write_2M(struct qla_hw_data *, u64, void *, int);
extern char *qla82xx_pci_info_str(struct scsi_qla_host *, char *);
extern int qla82xx_pci_region_offset(struct pci_dev *, int);
extern int qla82xx_iospace_config(struct qla_hw_data *);
@@ -509,8 +510,8 @@ extern int qla82xx_iospace_config(struct qla_hw_data *);
/* Initialization related functions */
extern void qla82xx_reset_chip(struct scsi_qla_host *);
extern void qla82xx_config_rings(struct scsi_qla_host *);
-extern int qla82xx_pinit_from_rom(scsi_qla_host_t *);
extern void qla82xx_watchdog(scsi_qla_host_t *);
+extern int qla82xx_start_firmware(scsi_qla_host_t *);
/* Firmware and flash related functions */
extern int qla82xx_load_risc(scsi_qla_host_t *, uint32_t *);
@@ -533,25 +534,17 @@ extern irqreturn_t qla82xx_msix_default(int, void *);
extern irqreturn_t qla82xx_msix_rsp_q(int, void *);
extern void qla82xx_enable_intrs(struct qla_hw_data *);
extern void qla82xx_disable_intrs(struct qla_hw_data *);
-extern void qla82xx_mbx_completion(scsi_qla_host_t *, uint16_t);
extern void qla82xx_poll(int, void *);
extern void qla82xx_init_flags(struct qla_hw_data *);
/* ISP 8021 hardware related */
-extern int qla82xx_crb_win_lock(struct qla_hw_data *);
+extern void qla82xx_set_drv_active(scsi_qla_host_t *);
extern void qla82xx_crb_win_unlock(struct qla_hw_data *);
-extern int qla82xx_pci_get_crb_addr_2M(struct qla_hw_data *, ulong *);
extern int qla82xx_wr_32(struct qla_hw_data *, ulong, u32);
extern int qla82xx_rd_32(struct qla_hw_data *, ulong);
extern int qla82xx_rdmem(struct qla_hw_data *, u64, void *, int);
extern int qla82xx_wrmem(struct qla_hw_data *, u64, void *, int);
-extern int qla82xx_check_for_bad_spd(struct qla_hw_data *);
-extern int qla82xx_load_fw(scsi_qla_host_t *);
-extern int qla82xx_rom_lock(struct qla_hw_data *);
extern void qla82xx_rom_unlock(struct qla_hw_data *);
-extern int qla82xx_rom_fast_read(struct qla_hw_data *, int , int *);
-extern int qla82xx_do_rom_fast_read(struct qla_hw_data *, int, int *);
-extern unsigned long qla82xx_decode_crb_addr(unsigned long);
/* ISP 8021 IDC */
extern void qla82xx_clear_drv_active(struct qla_hw_data *);
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 9c383baebe27..3cafbef40737 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c